diff --git a/.azure-pipelines/ci.yml b/.azure-pipelines/ci.yml index 63252a76abb69f..b5b2765e43844f 100644 --- a/.azure-pipelines/ci.yml +++ b/.azure-pipelines/ci.yml @@ -1,7 +1,4 @@ -variables: - coverage: false - -trigger: ['main', '3.11', '3.10', '3.9', '3.8', '3.7'] +trigger: ['main', '3.12', '3.11', '3.10', '3.9', '3.8', '3.7'] jobs: - job: Prebuild @@ -14,70 +11,6 @@ jobs: - template: ./prebuild-checks.yml -- job: macOS_CI_Tests - displayName: macOS CI Tests - dependsOn: Prebuild - #condition: and(succeeded(), eq(dependencies.Prebuild.outputs['tests.run'], 'true')) - # bpo-39837: macOS tests on Azure Pipelines are disabled - condition: false - - variables: - testRunTitle: '$(build.sourceBranchName)-macos' - testRunPlatform: macos - - pool: - vmImage: macos-10.15 - - steps: - - template: ./macos-steps.yml - - -- job: Ubuntu_CI_Tests - displayName: Ubuntu CI Tests - dependsOn: Prebuild - condition: and(succeeded(), eq(dependencies.Prebuild.outputs['tests.run'], 'true')) - - pool: - vmImage: ubuntu-22.04 - - variables: - testRunTitle: '$(build.sourceBranchName)-linux' - testRunPlatform: linux - openssl_version: 1.1.1u - - steps: - - template: ./posix-steps.yml - parameters: - dependencies: apt - - -- job: Ubuntu_Coverage_CI_Tests - displayName: Ubuntu CI Tests (coverage) - dependsOn: Prebuild - condition: | - and( - and( - succeeded(), - eq(variables['coverage'], 'true') - ), - eq(dependencies.Prebuild.outputs['tests.run'], 'true') - ) - - pool: - vmImage: ubuntu-22.04 - - variables: - testRunTitle: '$(Build.SourceBranchName)-linux-coverage' - testRunPlatform: linux-coverage - openssl_version: 1.1.1u - - steps: - - template: ./posix-steps.yml - parameters: - dependencies: apt - coverage: true - - - job: Windows_CI_Tests displayName: Windows CI Tests dependsOn: Prebuild diff --git a/.azure-pipelines/macos-steps.yml b/.azure-pipelines/macos-steps.yml deleted file mode 100644 index fa38a0df8c87b8..00000000000000 --- a/.azure-pipelines/macos-steps.yml +++ /dev/null @@ -1,27 +0,0 @@ -steps: -- checkout: self - clean: true - fetchDepth: 5 - -- script: ./configure --with-pydebug --with-openssl=/usr/local/opt/openssl --prefix=/opt/python-azdev - displayName: 'Configure CPython (debug)' - -- script: make -j4 - displayName: 'Build CPython' - -- script: make pythoninfo - displayName: 'Display build info' - -- script: make buildbottest TESTOPTS="-j4 -uall,-cpu --junit-xml=$(build.binariesDirectory)/test-results.xml" - displayName: 'Tests' - continueOnError: true - timeoutInMinutes: 30 - -- task: PublishTestResults@2 - displayName: 'Publish Test Results' - inputs: - testResultsFiles: '$(build.binariesDirectory)/test-results.xml' - mergeTestResults: true - testRunTitle: $(testRunTitle) - platform: $(testRunPlatform) - condition: succeededOrFailed() diff --git a/.azure-pipelines/posix-steps.yml b/.azure-pipelines/posix-steps.yml index 9d7c5e1279f46d..e23c7b1dcb55c1 100644 --- a/.azure-pipelines/posix-steps.yml +++ b/.azure-pipelines/posix-steps.yml @@ -1,10 +1,3 @@ -parameters: - coverage: false - sudo_dependencies: sudo - dependencies: apt - patchcheck: true - xvfb: true - steps: - checkout: self clean: true @@ -14,7 +7,7 @@ steps: - script: sudo setfacl -Rb /home/vsts displayName: 'Workaround ACL issue' -- script: ${{ parameters.sudo_dependencies }} ./.azure-pipelines/posix-deps-${{ parameters.dependencies }}.sh $(openssl_version) +- script: sudo ./.azure-pipelines/posix-deps-apt.sh $(openssl_version) displayName: 'Install dependencies' - script: ./configure --with-pydebug @@ -23,61 +16,11 @@ steps: - script: make -j4 displayName: 'Build CPython' -- ${{ if eq(parameters.coverage, 'true') }}: - - script: ./python -m venv venv && ./venv/bin/python -m pip install -U coverage - displayName: 'Set up virtual environment' - - - script: ./venv/bin/python -m test.pythoninfo - displayName: 'Display build info' - - - script: | - $COMMAND -m coverage run --pylib -m test \ - --fail-env-changed \ - -uall,-cpu \ - --junit-xml=$(build.binariesDirectory)/test-results.xml \ - -x test_multiprocessing_fork \ - -x test_multiprocessing_forkserver \ - -x test_multiprocessing_spawn \ - -x test_concurrent_futures - displayName: 'Tests with coverage' - env: - ${{ if eq(parameters.xvfb, 'true') }}: - COMMAND: xvfb-run ./venv/bin/python - ${{ if ne(parameters.xvfb, 'true') }}: - COMMAND: ./venv/bin/python - - - script: ./venv/bin/python -m coverage xml - displayName: 'Generate coverage.xml' - - - script: source ./venv/bin/activate && bash <(curl -s https://codecov.io/bash) -y .github/codecov.yml - displayName: 'Publish code coverage results' - - -- ${{ if ne(parameters.coverage, 'true') }}: - - script: make pythoninfo - displayName: 'Display build info' - - - script: $COMMAND buildbottest TESTOPTS="-j4 -uall,-cpu --junit-xml=$(build.binariesDirectory)/test-results.xml" - displayName: 'Tests' - env: - ${{ if eq(parameters.xvfb, 'true') }}: - COMMAND: xvfb-run make - ${{ if ne(parameters.xvfb, 'true') }}: - COMMAND: make - -- ${{ if eq(parameters.patchcheck, 'true') }}: - - script: | - git fetch origin - ./python Tools/patchcheck/patchcheck.py --ci true - displayName: 'Run patchcheck.py' - condition: and(succeeded(), eq(variables['Build.Reason'], 'PullRequest')) - +- script: make pythoninfo + displayName: 'Display build info' -- task: PublishTestResults@2 - displayName: 'Publish Test Results' - inputs: - testResultsFiles: '$(build.binariesDirectory)/test-results.xml' - mergeTestResults: true - testRunTitle: $(testRunTitle) - platform: $(testRunPlatform) - condition: succeededOrFailed() +- script: | + git fetch origin + ./python Tools/patchcheck/patchcheck.py --ci true + displayName: 'Run patchcheck.py' + condition: and(succeeded(), eq(variables['Build.Reason'], 'PullRequest')) diff --git a/.azure-pipelines/pr.yml b/.azure-pipelines/pr.yml index 939c9b4249a3c2..335a4b407cb83c 100644 --- a/.azure-pipelines/pr.yml +++ b/.azure-pipelines/pr.yml @@ -1,7 +1,4 @@ -variables: - coverage: false - -pr: ['main', '3.11', '3.10', '3.9', '3.8', '3.7'] +pr: ['main', '3.12', '3.11', '3.10', '3.9', '3.8', '3.7'] jobs: - job: Prebuild @@ -14,28 +11,8 @@ jobs: - template: ./prebuild-checks.yml -- job: macOS_PR_Tests - displayName: macOS PR Tests - dependsOn: Prebuild - #condition: and(succeeded(), eq(dependencies.Prebuild.outputs['tests.run'], 'true')) - # bpo-39837: macOS tests on Azure Pipelines are disabled - condition: false - - variables: - testRunTitle: '$(system.pullRequest.TargetBranch)-macos' - testRunPlatform: macos - - pool: - vmImage: macos-10.15 - - steps: - - template: ./macos-steps.yml - parameters: - targetBranch: $(System.PullRequest.TargetBranch) - - -- job: Ubuntu_PR_Tests - displayName: Ubuntu PR Tests +- job: Ubuntu_Patchcheck + displayName: Ubuntu patchcheck dependsOn: Prebuild condition: and(succeeded(), eq(dependencies.Prebuild.outputs['tests.run'], 'true')) @@ -49,63 +26,3 @@ jobs: steps: - template: ./posix-steps.yml - parameters: - dependencies: apt - - -- job: Ubuntu_Coverage_PR_Tests - displayName: Ubuntu PR Tests (coverage) - dependsOn: Prebuild - condition: | - and( - and( - succeeded(), - eq(variables['coverage'], 'true') - ), - eq(dependencies.Prebuild.outputs['tests.run'], 'true') - ) - - pool: - vmImage: ubuntu-22.04 - - variables: - testRunTitle: '$(Build.SourceBranchName)-linux-coverage' - testRunPlatform: linux-coverage - openssl_version: 1.1.1u - - steps: - - template: ./posix-steps.yml - parameters: - dependencies: apt - coverage: true - - -- job: Windows_PR_Tests - displayName: Windows PR Tests - dependsOn: Prebuild - condition: and(succeeded(), eq(dependencies.Prebuild.outputs['tests.run'], 'true')) - - pool: - vmImage: windows-2022 - - strategy: - matrix: - win32: - arch: win32 - buildOpt: '-p Win32' - testRunTitle: '$(System.PullRequest.TargetBranch)-win32' - testRunPlatform: win32 - win64: - arch: amd64 - buildOpt: '-p x64' - testRunTitle: '$(System.PullRequest.TargetBranch)-win64' - testRunPlatform: win64 - winarm64: - arch: arm64 - buildOpt: '-p arm64' - maxParallel: 4 - - steps: - - template: ./windows-steps.yml - parameters: - targetBranch: $(System.PullRequest.TargetBranch) diff --git a/.coveragerc b/.coveragerc index 18bf2f40fe523f..b5d94317e8aa8b 100644 --- a/.coveragerc +++ b/.coveragerc @@ -7,6 +7,11 @@ exclude_lines = # Don't complain if non-runnable code isn't run: if 0: if __name__ == .__main__.: + raise AssertionError\( + + # Empty bodies in protocols or abstract methods + ^\s*def [a-zA-Z0-9_]+\(.*\)(\s*->.*)?:\s*\.\.\.(\s*#.*)?$ + ^\s*\.\.\.(\s*#.*)?$ .*# pragma: no cover .*# pragma: no branch diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 590d7834b2b8be..9f808af38e69df 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -6,7 +6,7 @@ ENV WASI_SDK_VERSION=20 ENV WASI_SDK_PATH=/opt/wasi-sdk ENV WASMTIME_HOME=/opt/wasmtime -ENV WASMTIME_VERSION=9.0.1 +ENV WASMTIME_VERSION=14.0.4 ENV WASMTIME_CPU_ARCH=x86_64 RUN dnf -y --nodocs --setopt=install_weak_deps=False install /usr/bin/{blurb,clang,curl,git,ln,tar,xz} 'dnf-command(builddep)' && \ diff --git a/.editorconfig b/.editorconfig index 81445d2d79c739..0169eed951cd3f 100644 --- a/.editorconfig +++ b/.editorconfig @@ -8,5 +8,8 @@ indent_style = space [*.{py,c,cpp,h}] indent_size = 4 +[*.rst] +indent_size = 3 + [*.yml] indent_size = 2 diff --git a/.gitattributes b/.gitattributes index 1f2f8a4cd8735a..2a48df079e1aeb 100644 --- a/.gitattributes +++ b/.gitattributes @@ -24,7 +24,7 @@ PC/classicAppCompat.* binary [attr]noeol -text Lib/test/cjkencodings/* noeol -Lib/test/coding20731.py noeol +Lib/test/tokenizedata/coding20731.py noeol Lib/test/decimaltestdata/*.decTest noeol Lib/test/test_email/data/*.txt noeol Lib/test/test_importlib/resources/data01/* noeol @@ -66,6 +66,8 @@ PCbuild/readme.txt dos [attr]generated linguist-generated=true diff=generated **/clinic/*.c.h generated +**/clinic/*.cpp.h generated +**/clinic/*.h.h generated *_db.h generated Doc/data/stable_abi.dat generated Doc/library/token-list.inc generated @@ -74,13 +76,16 @@ Include/internal/pycore_ast_state.h generated Include/internal/pycore_opcode.h generated Include/internal/pycore_opcode_metadata.h generated Include/internal/pycore_*_generated.h generated +Include/internal/pycore_uop_ids.h generated Include/opcode.h generated +Include/opcode_ids.h generated Include/token.h generated Lib/_opcode_metadata.py generated Lib/keyword.py generated Lib/test/levenshtein_examples.json generated Lib/test/test_stable_abi_ctypes.py generated Lib/token.py generated +Misc/sbom.spdx.json generated Objects/typeslots.inc generated PC/python3dll.c generated Parser/parser.c generated diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 578cd71a7bd211..8038206441ab9b 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -9,6 +9,7 @@ # pre-commit .pre-commit-config.yaml @hugovk @AlexWaygood +.ruff.toml @hugovk @AlexWaygood # Build system configure* @erlend-aasland @corona10 @@ -27,14 +28,19 @@ Objects/type* @markshannon Objects/codeobject.c @markshannon Objects/frameobject.c @markshannon Objects/call.c @markshannon -Python/ceval.c @markshannon +Python/ceval*.c @markshannon @gvanrossum +Python/ceval*.h @markshannon @gvanrossum Python/compile.c @markshannon @iritkatriel Python/assemble.c @markshannon @iritkatriel Python/flowgraph.c @markshannon @iritkatriel Python/ast_opt.c @isidentical +Python/bytecodes.c @markshannon @gvanrossum +Python/optimizer*.c @markshannon @gvanrossum Lib/test/test_patma.py @brandtbucher Lib/test/test_peepholer.py @brandtbucher Lib/test/test_type_*.py @JelleZijlstra +Lib/test/test_capi/test_misc.py @markshannon @gvanrossum +Tools/c-analyzer/ @ericsnowcurrently # Exceptions Lib/traceback.py @iritkatriel @@ -101,6 +107,9 @@ Include/internal/pycore_time.h @pganssle @abalkin /Lib/tokenize.py @pablogsal @lysnikolaou /Lib/test/test_tokenize.py @pablogsal @lysnikolaou +# Code generator +/Tools/cases_generator/ @gvanrossum + # AST Python/ast.c @isidentical Parser/asdl.py @isidentical @@ -148,9 +157,11 @@ Doc/c-api/stable.rst @encukou **/*dataclasses* @ericvsmith +**/*ensurepip* @pfmoore @pradyunsg + **/*idlelib* @terryjreedy -**/*typing* @gvanrossum @Fidget-Spinner @JelleZijlstra @AlexWaygood +**/*typing* @JelleZijlstra @AlexWaygood **/*ftplib @giampaolo **/*shutil @giampaolo @@ -179,3 +190,15 @@ Doc/c-api/stable.rst @encukou /Tools/clinic/** @erlend-aasland @AlexWaygood /Lib/test/test_clinic.py @erlend-aasland @AlexWaygood Doc/howto/clinic.rst @erlend-aasland + +# Subinterpreters +Lib/test/support/interpreters/ @ericsnowcurrently +Modules/_xx*interp*module.c @ericsnowcurrently +Lib/test/test_interpreters/ @ericsnowcurrently + +# WebAssembly +/Tools/wasm/ @brettcannon + +# SBOM +/Misc/sbom.spdx.json @sethmlarson +/Tools/build/generate_sbom.py @sethmlarson diff --git a/.github/ISSUE_TEMPLATE/bug.md b/.github/ISSUE_TEMPLATE/bug.md deleted file mode 100644 index 47037cd319e7e2..00000000000000 --- a/.github/ISSUE_TEMPLATE/bug.md +++ /dev/null @@ -1,50 +0,0 @@ ---- -name: Bug report -about: Submit a bug report -labels: "type-bug" ---- - - - -# Bug report - -## Checklist - - - -- [ ] I am confident this is a bug in CPython, not a bug in a third-party project -- [ ] I have searched the CPython issue tracker, and am confident this bug has not been reported before - -## A clear and concise description of the bug - - - - - -# Your environment - - - -- CPython versions tested on: -- Operating system and architecture: - - diff --git a/.github/ISSUE_TEMPLATE/bug.yml b/.github/ISSUE_TEMPLATE/bug.yml new file mode 100644 index 00000000000000..395516f29b037c --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug.yml @@ -0,0 +1,56 @@ +name: Bug report +description: Submit a bug report +labels: ["type-bug"] +body: + - type: markdown + attributes: + value: | + **New to Python?** + + For help or advice on using Python, try one of the following options instead of opening a GitHub issue: + + - Asking on [Discourse](https://discuss.python.org/c/users/7) or [Stack Overflow](https://stackoverflow.com) + - Reading the [Python tutorial](https://docs.python.org/3/tutorial/) + - Emailing [python-list](https://mail.python.org/mailman/listinfo/python-list) + + Make sure to also search the [CPython issue tracker](https://github.com/python/cpython/issues?q=is%3Aissue+sort%3Acreated-desc) to check that the bug has not already been reported. + - type: textarea + attributes: + label: "Bug description:" + description: > + Give a clear and concise description of what happened. + Include a [minimal, reproducible example](https://stackoverflow.com/help/minimal-reproducible-example) if possible. + [Copy and paste code where possible rather than using screenshots](https://meta.stackoverflow.com/a/285557/13990016), + and put any code blocks inside triple backticks. + + value: | + ```python + # Add a code block here, if required + ``` + validations: + required: true + - type: dropdown + attributes: + label: "CPython versions tested on:" + multiple: true + options: + - "3.8" + - "3.9" + - "3.10" + - "3.11" + - "3.12" + - "3.13" + - "CPython main branch" + validations: + required: true + - type: dropdown + attributes: + label: "Operating systems tested on:" + multiple: true + options: + - Linux + - macOS + - Windows + - Other + validations: + required: false diff --git a/.github/ISSUE_TEMPLATE/crash.md b/.github/ISSUE_TEMPLATE/crash.md deleted file mode 100644 index a268249d1c1e65..00000000000000 --- a/.github/ISSUE_TEMPLATE/crash.md +++ /dev/null @@ -1,48 +0,0 @@ ---- -name: Crash report -about: A hard crash of the interpreter, possibly with a core dump -labels: "type-crash" ---- - - - -# Crash report - - - - - -# Error messages - - - - - -# Your environment - - - -- CPython versions tested on: -- Operating system and architecture: - - diff --git a/.github/ISSUE_TEMPLATE/crash.yml b/.github/ISSUE_TEMPLATE/crash.yml new file mode 100644 index 00000000000000..c14d7cf2599d4c --- /dev/null +++ b/.github/ISSUE_TEMPLATE/crash.yml @@ -0,0 +1,54 @@ +name: Crash report +description: A hard crash of the interpreter, possibly with a core dump +labels: ["type-crash"] +body: + - type: markdown + attributes: + value: | + This form is for hard crashes of the Python interpreter, segmentation faults, failed C-level assertions, and similar. Unexpected exceptions raised from Python functions in the standard library count as bugs rather than crashes. + + The CPython interpreter is written in a different programming language, C. A "CPython crash" is when Python itself fails, leading to a traceback in the C stack. + - type: textarea + attributes: + label: What happened? + description: > + Include a [minimal, reproducible example](https://stackoverflow.com/help/minimal-reproducible-example) if possible. + [Copy and paste code where possible rather than using screenshots](https://meta.stackoverflow.com/a/285557/13990016), + and put any code blocks inside triple backticks. + + value: | + ```python + # Add a code block here, if required + ``` + validations: + required: true + - type: dropdown + attributes: + label: "CPython versions tested on:" + multiple: true + options: + - "3.8" + - "3.9" + - "3.10" + - "3.11" + - "3.12" + - "CPython main branch" + validations: + required: true + - type: dropdown + attributes: + label: "Operating systems tested on:" + multiple: true + options: + - Linux + - macOS + - Windows + - Other + validations: + required: false + - type: input + attributes: + label: "Output from running 'python -VV' on the command line:" + description: If you tested with multiple operating systems or architectures, feel free to provide details in the main bug description. + validations: + required: false diff --git a/.github/ISSUE_TEMPLATE/feature.md b/.github/ISSUE_TEMPLATE/feature.md deleted file mode 100644 index 7e96bc9df665c2..00000000000000 --- a/.github/ISSUE_TEMPLATE/feature.md +++ /dev/null @@ -1,50 +0,0 @@ ---- -name: Feature or enhancement -about: Submit a proposal for a new CPython feature or enhancement -labels: "type-feature" ---- - - - -# Feature or enhancement - - - - - -# Pitch - - - - - -# Previous discussion - - - - - - diff --git a/.github/ISSUE_TEMPLATE/feature.yml b/.github/ISSUE_TEMPLATE/feature.yml new file mode 100644 index 00000000000000..4361ab2bf827fb --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature.yml @@ -0,0 +1,40 @@ +name: Feature or enhancement +description: Submit a proposal for a new CPython feature or enhancement +labels: ["type-feature"] +body: + - type: markdown + attributes: + value: | + # Proposing a feature to CPython? + + You'll need to demonstrate widespread support for your idea among the community. + + Major feature proposals should generally be discussed on [Discourse](https://discuss.python.org/c/ideas/6) before opening a GitHub issue. Wait until it's clear that most people support your idea before filling in this form. + - type: textarea + attributes: + label: "Proposal:" + description: > + Explain your proposal, why it should be implemented, and how it would be used. + Add examples, if applicable. + Put any code blocks inside triple backticks. + value: | + ```python + # Add a code block here, if required + ``` + validations: + required: true + - type: dropdown + attributes: + label: Has this already been discussed elsewhere? + options: + - No response given + - I have already discussed this feature proposal on Discourse + - This is a minor feature, which does not need previous discussion elsewhere + multiple: false + validations: + required: true + - type: textarea + attributes: + label: "Links to previous discussion of this feature:" + validations: + required: false diff --git a/.github/dependabot.yml b/.github/dependabot.yml index f026b0f5f9454a..c8a3165d690364 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -13,7 +13,7 @@ updates: - "version-update:semver-minor" - "version-update:semver-patch" - package-ecosystem: "pip" - directory: "/Tools/clinic/" + directory: "/Tools/" schedule: interval: "monthly" labels: diff --git a/.github/problem-matchers/sphinx.json b/.github/problem-matchers/sphinx.json deleted file mode 100644 index 09848608a7b034..00000000000000 --- a/.github/problem-matchers/sphinx.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "problemMatcher": [ - { - "owner": "sphinx-problem-matcher", - "pattern": [ - { - "regexp": "^(.*):(\\d+):\\s+(\\w*):\\s+(.*)$", - "file": 1, - "line": 2, - "severity": 3, - "message": 4 - } - ] - }, - { - "owner": "sphinx-problem-matcher-loose", - "pattern": [ - { - "_comment": "A bit of a looser pattern, doesn't look for line numbers, just looks for file names relying on them to start with / and end with .rst", - "regexp": "(\/.*\\.rst):\\s+(\\w*):\\s+(.*)$", - "file": 1, - "severity": 2, - "message": 3 - } - ] - }, - { - "owner": "sphinx-problem-matcher-loose-no-severity", - "pattern": [ - { - "_comment": "Looks for file names ending with .rst and line numbers but without severity", - "regexp": "^(.*\\.rst):(\\d+):(.*)$", - "file": 1, - "line": 2, - "message": 3 - } - ] - } - ] -} \ No newline at end of file diff --git a/.github/workflows/add-issue-header.yml b/.github/workflows/add-issue-header.yml new file mode 100644 index 00000000000000..570b8779994a0f --- /dev/null +++ b/.github/workflows/add-issue-header.yml @@ -0,0 +1,53 @@ +name: Add issue header +# Automatically edits an issue's descriptions with a header, +# one of: +# +# - Bug report +# - Crash report +# - Feature or enhancement + +on: + issues: + types: + # Only ever run once + - opened + + +jobs: + add-header: + runs-on: ubuntu-latest + permissions: + issues: write + steps: + - uses: actions/github-script@v7 + with: + # language=JavaScript + script: | + // https://devguide.python.org/triage/labels/#type-labels + const HEADERS = new Map([ + ['type-bug', 'Bug report'], + ['type-crash', 'Crash report'], + ['type-feature', 'Feature or enhancement'], + ]); + let issue_data = await github.rest.issues.get({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo + }).then(issue => issue.data); + let header = ''; + for (const label_data of issue_data.labels) { + const label_name = (typeof label_data === 'string') ? label_data : label_data.name; + if (HEADERS.has(label_name)) { + header = HEADERS.get(label_name); + break; + } + } + if (header !== '') { + console.log(`Setting new header: ${header}`); + await github.rest.issues.update({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: `# ${header}\n\n${issue_data.body.replaceAll('\r', '')}` + }); + } diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 06551b13219c2a..a3b1d7786ee914 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -13,7 +13,6 @@ on: - '3.10' - '3.9' - '3.8' - - '3.7' pull_request: branches: - 'main' @@ -22,7 +21,6 @@ on: - '3.10' - '3.9' - '3.8' - - '3.7' permissions: contents: read @@ -40,9 +38,10 @@ jobs: run-docs: ${{ steps.docs-changes.outputs.run-docs || false }} run_tests: ${{ steps.check.outputs.run_tests }} run_hypothesis: ${{ steps.check.outputs.run_hypothesis }} + run_cifuzz: ${{ steps.check.outputs.run_cifuzz }} config_hash: ${{ steps.config_hash.outputs.hash }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Check for source changes id: check run: | @@ -63,7 +62,7 @@ jobs: # into the PR branch anyway. # # https://github.com/python/core-workflow/issues/373 - git diff --name-only origin/$GITHUB_BASE_REF.. | grep -qvE '(\.rst$|^Doc|^Misc)' && echo "run_tests=true" >> $GITHUB_OUTPUT || true + git diff --name-only origin/$GITHUB_BASE_REF.. | grep -qvE '(\.rst$|^Doc|^Misc|^\.pre-commit-config\.yaml$|\.ruff\.toml$)' && echo "run_tests=true" >> $GITHUB_OUTPUT || true fi # Check if we should run hypothesis tests @@ -76,6 +75,21 @@ jobs: echo "Run hypothesis tests" echo "run_hypothesis=true" >> $GITHUB_OUTPUT fi + + # oss-fuzz maintains a configuration for fuzzing the main branch of + # CPython, so CIFuzz should be run only for code that is likely to be + # merged into the main branch; compatibility with older branches may + # be broken. + FUZZ_RELEVANT_FILES='(\.c$|\.h$|\.cpp$|^configure$|^\.github/workflows/build\.yml$|^Modules/_xxtestfuzz)' + if [ "$GITHUB_BASE_REF" = "main" ] && [ "$(git diff --name-only origin/$GITHUB_BASE_REF.. | grep -qE $FUZZ_RELEVANT_FILES; echo $?)" -eq 0 ]; then + # The tests are pretty slow so they are executed only for PRs + # changing relevant files. + echo "Run CIFuzz tests" + echo "run_cifuzz=true" >> $GITHUB_OUTPUT + else + echo "Branch too old for CIFuzz tests; or no C files were changed" + echo "run_cifuzz=false" >> $GITHUB_OUTPUT + fi - name: Compute hash for config cache key id: config_hash run: | @@ -106,41 +120,45 @@ jobs: check_generated_files: name: 'Check if generated files are up to date' - runs-on: ubuntu-latest + # Don't use ubuntu-latest but a specific version to make the job + # reproducible: to get the same tools versions (autoconf, aclocal, ...) + runs-on: ubuntu-22.04 timeout-minutes: 60 needs: check_source if: needs.check_source.outputs.run_tests == 'true' steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: '3.x' - name: Restore config.cache uses: actions/cache@v3 with: path: config.cache - key: ${{ github.job }}-${{ runner.os }}-${{ needs.check_source.outputs.config_hash }} - - uses: actions/setup-python@v3 + key: ${{ github.job }}-${{ runner.os }}-${{ needs.check_source.outputs.config_hash }}-${{ env.pythonLocation }} - name: Install Dependencies run: sudo ./.github/workflows/posix-deps-apt.sh - name: Add ccache to PATH run: echo "PATH=/usr/lib/ccache:$PATH" >> $GITHUB_ENV - name: Configure ccache action uses: hendrikmuhs/ccache-action@v1.2 + with: + save: ${{ github.event_name == 'push' }} - name: Check Autoconf and aclocal versions run: | grep "Generated by GNU Autoconf 2.71" configure - grep "aclocal 1.16.4" aclocal.m4 + grep "aclocal 1.16.5" aclocal.m4 grep -q "runstatedir" configure grep -q "PKG_PROG_PKG_CONFIG" aclocal.m4 - name: Configure CPython run: | # Build Python with the libpython dynamic library ./configure --config-cache --with-pydebug --enable-shared - - name: Regenerate autoconf files with container image - run: make regen-configure + - name: Regenerate autoconf files + # Same command used by Tools/build/regen-configure.sh ($AUTORECONF) + run: autoreconf -ivf -Werror - name: Build CPython run: | - # Deepfreeze will usually cause global objects to be added or removed, - # so we run it before regen-global-objects gets rum (in regen-all). - make regen-deepfreeze make -j4 regen-all make regen-stdlib-module-names - name: Check for changes @@ -165,144 +183,63 @@ jobs: if: github.event_name == 'pull_request' # $GITHUB_EVENT_NAME run: make check-c-globals - build_win32: - name: 'Windows (x86)' - runs-on: windows-latest - timeout-minutes: 60 + build_windows: + name: 'Windows' needs: check_source if: needs.check_source.outputs.run_tests == 'true' - env: - IncludeUwp: 'true' - steps: - - uses: actions/checkout@v3 - - name: Build CPython - run: .\PCbuild\build.bat -e -d -p Win32 - - name: Display build info - run: .\python.bat -m test.pythoninfo - - name: Tests - run: .\PCbuild\rt.bat -p Win32 -d -q -uall -u-cpu -rwW --slowest --timeout=1200 -j0 + uses: ./.github/workflows/reusable-windows.yml - build_win_amd64: - name: 'Windows (x64)' - runs-on: windows-latest - timeout-minutes: 60 + build_windows_free_threading: + name: 'Windows (free-threading)' needs: check_source if: needs.check_source.outputs.run_tests == 'true' - env: - IncludeUwp: 'true' - steps: - - uses: actions/checkout@v3 - - name: Register MSVC problem matcher - run: echo "::add-matcher::.github/problem-matchers/msvc.json" - - name: Build CPython - run: .\PCbuild\build.bat -e -d -p x64 - - name: Display build info - run: .\python.bat -m test.pythoninfo - - name: Tests - run: .\PCbuild\rt.bat -p x64 -d -q -uall -u-cpu -rwW --slowest --timeout=1200 -j0 + uses: ./.github/workflows/reusable-windows.yml + with: + free-threading: true build_macos: name: 'macOS' - runs-on: macos-latest - timeout-minutes: 60 needs: check_source if: needs.check_source.outputs.run_tests == 'true' - env: - HOMEBREW_NO_ANALYTICS: 1 - HOMEBREW_NO_AUTO_UPDATE: 1 - HOMEBREW_NO_INSTALL_CLEANUP: 1 - PYTHONSTRICTEXTENSIONBUILD: 1 - steps: - - uses: actions/checkout@v3 - - name: Restore config.cache - uses: actions/cache@v3 - with: - path: config.cache - key: ${{ github.job }}-${{ runner.os }}-${{ needs.check_source.outputs.config_hash }} - - name: Install Homebrew dependencies - run: brew install pkg-config openssl@3.0 xz gdbm tcl-tk - - name: Configure CPython - run: | - GDBM_CFLAGS="-I$(brew --prefix gdbm)/include" \ - GDBM_LIBS="-L$(brew --prefix gdbm)/lib -lgdbm" \ - ./configure \ - --config-cache \ - --with-pydebug \ - --prefix=/opt/python-dev \ - --with-openssl="$(brew --prefix openssl@3.0)" - - name: Build CPython - run: make -j4 - - name: Display build info - run: make pythoninfo - - name: Tests - run: make buildbottest TESTOPTS="-j4 -uall,-cpu" + uses: ./.github/workflows/reusable-macos.yml + with: + config_hash: ${{ needs.check_source.outputs.config_hash }} + + build_macos_free_threading: + name: 'macOS (free-threading)' + needs: check_source + if: needs.check_source.outputs.run_tests == 'true' + uses: ./.github/workflows/reusable-macos.yml + with: + config_hash: ${{ needs.check_source.outputs.config_hash }} + free-threading: true build_ubuntu: name: 'Ubuntu' - runs-on: ubuntu-20.04 - timeout-minutes: 60 needs: check_source if: needs.check_source.outputs.run_tests == 'true' - env: - OPENSSL_VER: 1.1.1u - PYTHONSTRICTEXTENSIONBUILD: 1 - steps: - - uses: actions/checkout@v3 - - name: Register gcc problem matcher - run: echo "::add-matcher::.github/problem-matchers/gcc.json" - - name: Install Dependencies - run: sudo ./.github/workflows/posix-deps-apt.sh - - name: Configure OpenSSL env vars - run: | - echo "MULTISSL_DIR=${GITHUB_WORKSPACE}/multissl" >> $GITHUB_ENV - echo "OPENSSL_DIR=${GITHUB_WORKSPACE}/multissl/openssl/${OPENSSL_VER}" >> $GITHUB_ENV - echo "LD_LIBRARY_PATH=${GITHUB_WORKSPACE}/multissl/openssl/${OPENSSL_VER}/lib" >> $GITHUB_ENV - - name: 'Restore OpenSSL build' - id: cache-openssl - uses: actions/cache@v3 - with: - path: ./multissl/openssl/${{ env.OPENSSL_VER }} - key: ${{ runner.os }}-multissl-openssl-${{ env.OPENSSL_VER }} - - name: Install OpenSSL - if: steps.cache-openssl.outputs.cache-hit != 'true' - run: python3 Tools/ssl/multissltests.py --steps=library --base-directory $MULTISSL_DIR --openssl $OPENSSL_VER --system Linux - - name: Add ccache to PATH - run: | - echo "PATH=/usr/lib/ccache:$PATH" >> $GITHUB_ENV - - name: Configure ccache action - uses: hendrikmuhs/ccache-action@v1.2 - - name: Setup directory envs for out-of-tree builds - run: | - echo "CPYTHON_RO_SRCDIR=$(realpath -m ${GITHUB_WORKSPACE}/../cpython-ro-srcdir)" >> $GITHUB_ENV - echo "CPYTHON_BUILDDIR=$(realpath -m ${GITHUB_WORKSPACE}/../cpython-builddir)" >> $GITHUB_ENV - - name: Create directories for read-only out-of-tree builds - run: mkdir -p $CPYTHON_RO_SRCDIR $CPYTHON_BUILDDIR - - name: Bind mount sources read-only - run: sudo mount --bind -o ro $GITHUB_WORKSPACE $CPYTHON_RO_SRCDIR - - name: Restore config.cache - uses: actions/cache@v3 - with: - path: ${{ env.CPYTHON_BUILDDIR }}/config.cache - key: ${{ github.job }}-${{ runner.os }}-${{ needs.check_source.outputs.config_hash }} - - name: Configure CPython out-of-tree - working-directory: ${{ env.CPYTHON_BUILDDIR }} - run: | + uses: ./.github/workflows/reusable-ubuntu.yml + with: + config_hash: ${{ needs.check_source.outputs.config_hash }} + options: | ../cpython-ro-srcdir/configure \ --config-cache \ --with-pydebug \ --with-openssl=$OPENSSL_DIR - - name: Build CPython out-of-tree - working-directory: ${{ env.CPYTHON_BUILDDIR }} - run: make -j4 - - name: Display build info - working-directory: ${{ env.CPYTHON_BUILDDIR }} - run: make pythoninfo - - name: Remount sources writable for tests - # some tests write to srcdir, lack of pyc files slows down testing - run: sudo mount $CPYTHON_RO_SRCDIR -oremount,rw - - name: Tests - working-directory: ${{ env.CPYTHON_BUILDDIR }} - run: xvfb-run make buildbottest TESTOPTS="-j4 -uall,-cpu" + + build_ubuntu_free_threading: + name: 'Ubuntu (free-threading)' + needs: check_source + if: needs.check_source.outputs.run_tests == 'true' + uses: ./.github/workflows/reusable-ubuntu.yml + with: + config_hash: ${{ needs.check_source.outputs.config_hash }} + options: | + ../cpython-ro-srcdir/configure \ + --config-cache \ + --with-pydebug \ + --with-openssl=$OPENSSL_DIR \ + --disable-gil build_ubuntu_ssltests: name: 'Ubuntu SSL tests with OpenSSL' @@ -313,14 +250,14 @@ jobs: strategy: fail-fast: false matrix: - openssl_ver: [1.1.1u, 3.0.9, 3.1.1] + openssl_ver: [1.1.1w, 3.0.11, 3.1.3] env: OPENSSL_VER: ${{ matrix.openssl_ver }} MULTISSL_DIR: ${{ github.workspace }}/multissl OPENSSL_DIR: ${{ github.workspace }}/multissl/openssl/${{ matrix.openssl_ver }} LD_LIBRARY_PATH: ${{ github.workspace }}/multissl/openssl/${{ matrix.openssl_ver }}/lib steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Restore config.cache uses: actions/cache@v3 with: @@ -349,6 +286,8 @@ jobs: echo "PATH=/usr/lib/ccache:$PATH" >> $GITHUB_ENV - name: Configure ccache action uses: hendrikmuhs/ccache-action@v1.2 + with: + save: ${{ github.event_name == 'push' }} - name: Configure CPython run: ./configure --config-cache --with-pydebug --with-openssl=$OPENSSL_DIR - name: Build CPython @@ -365,10 +304,10 @@ jobs: needs: check_source if: needs.check_source.outputs.run_tests == 'true' && needs.check_source.outputs.run_hypothesis == 'true' env: - OPENSSL_VER: 1.1.1u + OPENSSL_VER: 3.0.11 PYTHONSTRICTEXTENSIONBUILD: 1 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Register gcc problem matcher run: echo "::add-matcher::.github/problem-matchers/gcc.json" - name: Install Dependencies @@ -392,6 +331,8 @@ jobs: echo "PATH=/usr/lib/ccache:$PATH" >> $GITHUB_ENV - name: Configure ccache action uses: hendrikmuhs/ccache-action@v1.2 + with: + save: ${{ github.event_name == 'push' }} - name: Setup directory envs for out-of-tree builds run: | echo "CPYTHON_RO_SRCDIR=$(realpath -m ${GITHUB_WORKSPACE}/../cpython-ro-srcdir)" >> $GITHUB_ENV @@ -431,7 +372,7 @@ jobs: VENV_PYTHON=$VENV_LOC/bin/python echo "HYPOVENV=${VENV_LOC}" >> $GITHUB_ENV echo "VENV_PYTHON=${VENV_PYTHON}" >> $GITHUB_ENV - ./python -m venv $VENV_LOC && $VENV_PYTHON -m pip install -U hypothesis + ./python -m venv $VENV_LOC && $VENV_PYTHON -m pip install -r ${GITHUB_WORKSPACE}/Tools/requirements-hypothesis.txt - name: 'Restore Hypothesis database' id: cache-hypothesis-database uses: actions/cache@v3 @@ -460,7 +401,7 @@ jobs: -x test_subprocess \ -x test_signal \ -x test_sysconfig - - uses: actions/upload-artifact@v3 + - uses: actions/upload-artifact@v4 if: always() with: name: hypothesis-example-db @@ -474,11 +415,11 @@ jobs: needs: check_source if: needs.check_source.outputs.run_tests == 'true' env: - OPENSSL_VER: 1.1.1u + OPENSSL_VER: 3.0.11 PYTHONSTRICTEXTENSIONBUILD: 1 ASAN_OPTIONS: detect_leaks=0:allocator_may_return_null=1:handle_segv=0 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Restore config.cache uses: actions/cache@v3 with: @@ -511,6 +452,8 @@ jobs: echo "PATH=/usr/lib/ccache:$PATH" >> $GITHUB_ENV - name: Configure ccache action uses: hendrikmuhs/ccache-action@v1.2 + with: + save: ${{ github.event_name == 'push' }} - name: Configure CPython run: ./configure --config-cache --with-address-sanitizer --without-pymalloc - name: Build CPython @@ -518,7 +461,47 @@ jobs: - name: Display build info run: make pythoninfo - name: Tests - run: xvfb-run make buildbottest TESTOPTS="-j4 -uall,-cpu" + run: xvfb-run make test + + # CIFuzz job based on https://google.github.io/oss-fuzz/getting-started/continuous-integration/ + cifuzz: + name: CIFuzz + runs-on: ubuntu-latest + timeout-minutes: 60 + needs: check_source + if: needs.check_source.outputs.run_cifuzz == 'true' + permissions: + security-events: write + strategy: + fail-fast: false + matrix: + sanitizer: [address, undefined, memory] + steps: + - name: Build fuzzers (${{ matrix.sanitizer }}) + id: build + uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master + with: + oss-fuzz-project-name: cpython3 + sanitizer: ${{ matrix.sanitizer }} + - name: Run fuzzers (${{ matrix.sanitizer }}) + uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master + with: + fuzz-seconds: 600 + oss-fuzz-project-name: cpython3 + output-sarif: true + sanitizer: ${{ matrix.sanitizer }} + - name: Upload crash + uses: actions/upload-artifact@v4 + if: failure() && steps.build.outcome == 'success' + with: + name: ${{ matrix.sanitizer }}-artifacts + path: ./out/artifacts + - name: Upload SARIF + if: always() && steps.build.outcome == 'success' + uses: github/codeql-action/upload-sarif@v3 + with: + sarif_file: cifuzz-sarif/results.sarif + checkout_path: cifuzz-sarif all-required-green: # This job does nothing and is only used for the branch protection name: All required checks pass @@ -528,13 +511,16 @@ jobs: - check_source # Transitive dependency, needed to access `run_tests` value - check-docs - check_generated_files - - build_win32 - - build_win_amd64 - build_macos + - build_macos_free_threading - build_ubuntu + - build_ubuntu_free_threading - build_ubuntu_ssltests + - build_windows + - build_windows_free_threading - test_hypothesis - build_asan + - cifuzz runs-on: ubuntu-latest @@ -543,9 +529,8 @@ jobs: uses: re-actors/alls-green@05ac9388f0aebcb5727afa17fcccfecd6f8ec5fe with: allowed-failures: >- - build_macos, build_ubuntu_ssltests, - build_win32, + cifuzz, test_hypothesis, allowed-skips: >- ${{ @@ -559,15 +544,24 @@ jobs: needs.check_source.outputs.run_tests != 'true' && ' check_generated_files, - build_win32, - build_win_amd64, build_macos, + build_macos_free_threading, build_ubuntu, + build_ubuntu_free_threading, build_ubuntu_ssltests, + build_windows, + build_windows_free_threading, build_asan, ' || '' }} + ${{ + !fromJSON(needs.check_source.outputs.run_cifuzz) + && ' + cifuzz, + ' + || '' + }} ${{ !fromJSON(needs.check_source.outputs.run_hypothesis) && ' diff --git a/.github/workflows/build_msi.yml b/.github/workflows/build_msi.yml index 22f613a88aa11e..29282dffa37ec0 100644 --- a/.github/workflows/build_msi.yml +++ b/.github/workflows/build_msi.yml @@ -33,6 +33,6 @@ jobs: matrix: type: [x86, x64, arm64] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Build CPython installer run: .\Tools\msi\build.bat --doc -${{ matrix.type }} diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 4481ea80bfd936..4a70ec6205a05b 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -5,6 +5,10 @@ on: [push, pull_request, workflow_dispatch] permissions: contents: read +env: + FORCE_COLOR: 1 + RUFF_OUTPUT_FORMAT: github + concurrency: group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} cancel-in-progress: true @@ -15,8 +19,8 @@ jobs: timeout-minutes: 10 steps: - - uses: actions/checkout@v3 - - uses: actions/setup-python@v4 + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 with: python-version: "3.x" - uses: pre-commit/action@v3.0.0 diff --git a/.github/workflows/mypy.yml b/.github/workflows/mypy.yml index 1315bb5a966f01..11928e72b9b43a 100644 --- a/.github/workflows/mypy.yml +++ b/.github/workflows/mypy.yml @@ -7,8 +7,14 @@ on: - main pull_request: paths: - - "Tools/clinic/**" - ".github/workflows/mypy.yml" + - "Lib/test/libregrtest/**" + - "Tools/build/generate_sbom.py" + - "Tools/cases_generator/**" + - "Tools/clinic/**" + - "Tools/peg_generator/**" + - "Tools/requirements-dev.txt" + - "Tools/wasm/**" workflow_dispatch: permissions: @@ -25,15 +31,25 @@ concurrency: jobs: mypy: - name: Run mypy on Tools/clinic/ + strategy: + matrix: + target: [ + "Lib/test/libregrtest", + "Tools/build/", + "Tools/cases_generator", + "Tools/clinic", + "Tools/peg_generator", + "Tools/wasm", + ] + name: Run mypy on ${{ matrix.target }} runs-on: ubuntu-latest timeout-minutes: 10 steps: - - uses: actions/checkout@v3 - - uses: actions/setup-python@v4 + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 with: - python-version: "3.x" + python-version: "3.11" cache: pip - cache-dependency-path: Tools/clinic/requirements-dev.txt - - run: pip install -r Tools/clinic/requirements-dev.txt - - run: mypy --config-file Tools/clinic/mypy.ini + cache-dependency-path: Tools/requirements-dev.txt + - run: pip install -r Tools/requirements-dev.txt + - run: mypy --config-file ${{ matrix.target }}/mypy.ini diff --git a/.github/workflows/new-bugs-announce-notifier.yml b/.github/workflows/new-bugs-announce-notifier.yml index 80514b4d2ca572..9f1a8a824e5f19 100644 --- a/.github/workflows/new-bugs-announce-notifier.yml +++ b/.github/workflows/new-bugs-announce-notifier.yml @@ -13,12 +13,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 10 steps: - - uses: actions/setup-node@v3 + - uses: actions/setup-node@v4 with: - node-version: 14 + node-version: 20 - run: npm install mailgun.js form-data - name: Send notification - uses: actions/github-script@v6 + uses: actions/github-script@v7 env: MAILGUN_API_KEY: ${{ secrets.MAILGUN_PYTHON_ORG_MAILGUN_KEY }} with: diff --git a/.github/workflows/posix-deps-apt.sh b/.github/workflows/posix-deps-apt.sh index a220896f2cd7be..0800401f4cd113 100755 --- a/.github/workflows/posix-deps-apt.sh +++ b/.github/workflows/posix-deps-apt.sh @@ -1,9 +1,11 @@ #!/bin/sh apt-get update +# autoconf-archive is needed by autoreconf (check_generated_files job) apt-get -yq install \ build-essential \ pkg-config \ + autoconf-archive \ ccache \ gdb \ lcov \ @@ -19,6 +21,7 @@ apt-get -yq install \ libssl-dev \ lzma \ lzma-dev \ + strace \ tk-dev \ uuid-dev \ xvfb \ diff --git a/.github/workflows/require-pr-label.yml b/.github/workflows/require-pr-label.yml index 9327b43ae02710..080204bcfd3b94 100644 --- a/.github/workflows/require-pr-label.yml +++ b/.github/workflows/require-pr-label.yml @@ -5,8 +5,8 @@ on: types: [opened, reopened, labeled, unlabeled, synchronize] permissions: - issues: read - pull-requests: read + issues: write + pull-requests: write jobs: label: diff --git a/.github/workflows/reusable-docs.yml b/.github/workflows/reusable-docs.yml index 56932c4860573c..e534751ee1011d 100644 --- a/.github/workflows/reusable-docs.yml +++ b/.github/workflows/reusable-docs.yml @@ -16,12 +16,32 @@ jobs: name: 'Docs' runs-on: ubuntu-latest timeout-minutes: 60 + env: + branch_base: 'origin/${{ github.event.pull_request.base.ref }}' + branch_pr: 'origin/${{ github.event.pull_request.head.ref }}' + refspec_base: '+${{ github.event.pull_request.base.sha }}:remotes/origin/${{ github.event.pull_request.base.ref }}' + refspec_pr: '+${{ github.event.pull_request.head.sha }}:remotes/origin/${{ github.event.pull_request.head.ref }}' steps: - - uses: actions/checkout@v3 - - name: Register Sphinx problem matcher - run: echo "::add-matcher::.github/problem-matchers/sphinx.json" + - name: 'Check out latest PR branch commit' + uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.sha }} + # Adapted from https://github.com/actions/checkout/issues/520#issuecomment-1167205721 + - name: 'Fetch commits to get branch diff' + run: | + # Fetch enough history to find a common ancestor commit (aka merge-base): + git fetch origin ${{ env.refspec_pr }} --depth=$(( ${{ github.event.pull_request.commits }} + 1 )) \ + --no-tags --prune --no-recurse-submodules + + # This should get the oldest commit in the local fetched history (which may not be the commit the PR branched from): + COMMON_ANCESTOR=$( git rev-list --first-parent --max-parents=0 --max-count=1 ${{ env.branch_pr }} ) + DATE=$( git log --date=iso8601 --format=%cd "${COMMON_ANCESTOR}" ) + + # Get all commits since that commit date from the base branch (eg: master or main): + git fetch origin ${{ env.refspec_base }} --shallow-since="${DATE}" \ + --no-tags --prune --no-recurse-submodules - name: 'Set up Python' - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3' cache: 'pip' @@ -30,13 +50,6 @@ jobs: run: make -C Doc/ venv # To annotate PRs with Sphinx nitpicks (missing references) - - name: 'Get list of changed files' - if: github.event_name == 'pull_request' - id: changed_files - uses: Ana06/get-changed-files@v2.2.0 - with: - filter: "Doc/**" - format: csv # works for paths with spaces - name: 'Build HTML documentation' continue-on-error: true run: | @@ -47,7 +60,7 @@ jobs: if: github.event_name == 'pull_request' run: | python Doc/tools/check-warnings.py \ - --check-and-annotate '${{ steps.changed_files.outputs.added_modified }}' \ + --annotate-diff '${{ env.branch_base }}' '${{ env.branch_pr }}' \ --fail-if-regression \ --fail-if-improved @@ -57,11 +70,11 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: 'Set up Python' - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: - python-version: '3.11' # known to work with Sphinx 3.2 + python-version: '3.11' # known to work with Sphinx 4.2 cache: 'pip' cache-dependency-path: 'Doc/requirements-oldest-sphinx.txt' - name: 'Install build dependencies' @@ -75,9 +88,7 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 steps: - - uses: actions/checkout@v3 - - name: Register Sphinx problem matcher - run: echo "::add-matcher::.github/problem-matchers/sphinx.json" + - uses: actions/checkout@v4 - uses: actions/cache@v3 with: path: ~/.cache/pip diff --git a/.github/workflows/reusable-macos.yml b/.github/workflows/reusable-macos.yml new file mode 100644 index 00000000000000..c24b6e963ddfd6 --- /dev/null +++ b/.github/workflows/reusable-macos.yml @@ -0,0 +1,46 @@ +on: + workflow_call: + inputs: + config_hash: + required: true + type: string + free-threading: + required: false + type: boolean + default: false + +jobs: + build_macos: + name: 'build and test' + runs-on: macos-latest + timeout-minutes: 60 + env: + HOMEBREW_NO_ANALYTICS: 1 + HOMEBREW_NO_AUTO_UPDATE: 1 + HOMEBREW_NO_INSTALL_CLEANUP: 1 + PYTHONSTRICTEXTENSIONBUILD: 1 + steps: + - uses: actions/checkout@v4 + - name: Restore config.cache + uses: actions/cache@v3 + with: + path: config.cache + key: ${{ github.job }}-${{ runner.os }}-${{ inputs.config_hash }} + - name: Install Homebrew dependencies + run: brew install pkg-config openssl@3.0 xz gdbm tcl-tk + - name: Configure CPython + run: | + GDBM_CFLAGS="-I$(brew --prefix gdbm)/include" \ + GDBM_LIBS="-L$(brew --prefix gdbm)/lib -lgdbm" \ + ./configure \ + --config-cache \ + --with-pydebug \ + ${{ inputs.free-threading && '--disable-gil' || '' }} \ + --prefix=/opt/python-dev \ + --with-openssl="$(brew --prefix openssl@3.0)" + - name: Build CPython + run: make -j4 + - name: Display build info + run: make pythoninfo + - name: Tests + run: make test diff --git a/.github/workflows/reusable-ubuntu.yml b/.github/workflows/reusable-ubuntu.yml new file mode 100644 index 00000000000000..f208064767d42f --- /dev/null +++ b/.github/workflows/reusable-ubuntu.yml @@ -0,0 +1,73 @@ +on: + workflow_call: + inputs: + config_hash: + required: true + type: string + options: + required: true + type: string + +jobs: + build_ubuntu_reusable: + name: 'build and test' + timeout-minutes: 60 + runs-on: ubuntu-20.04 + env: + OPENSSL_VER: 3.0.11 + PYTHONSTRICTEXTENSIONBUILD: 1 + steps: + - uses: actions/checkout@v4 + - name: Register gcc problem matcher + run: echo "::add-matcher::.github/problem-matchers/gcc.json" + - name: Install dependencies + run: sudo ./.github/workflows/posix-deps-apt.sh + - name: Configure OpenSSL env vars + run: | + echo "MULTISSL_DIR=${GITHUB_WORKSPACE}/multissl" >> $GITHUB_ENV + echo "OPENSSL_DIR=${GITHUB_WORKSPACE}/multissl/openssl/${OPENSSL_VER}" >> $GITHUB_ENV + echo "LD_LIBRARY_PATH=${GITHUB_WORKSPACE}/multissl/openssl/${OPENSSL_VER}/lib" >> $GITHUB_ENV + - name: 'Restore OpenSSL build' + id: cache-openssl + uses: actions/cache@v3 + with: + path: ./multissl/openssl/${{ env.OPENSSL_VER }} + key: ${{ runner.os }}-multissl-openssl-${{ env.OPENSSL_VER }} + - name: Install OpenSSL + if: steps.cache-openssl.outputs.cache-hit != 'true' + run: python3 Tools/ssl/multissltests.py --steps=library --base-directory $MULTISSL_DIR --openssl $OPENSSL_VER --system Linux + - name: Add ccache to PATH + run: | + echo "PATH=/usr/lib/ccache:$PATH" >> $GITHUB_ENV + - name: Configure ccache action + uses: hendrikmuhs/ccache-action@v1.2 + with: + save: ${{ github.event_name == 'push' }} + - name: Setup directory envs for out-of-tree builds + run: | + echo "CPYTHON_RO_SRCDIR=$(realpath -m ${GITHUB_WORKSPACE}/../cpython-ro-srcdir)" >> $GITHUB_ENV + echo "CPYTHON_BUILDDIR=$(realpath -m ${GITHUB_WORKSPACE}/../cpython-builddir)" >> $GITHUB_ENV + - name: Create directories for read-only out-of-tree builds + run: mkdir -p $CPYTHON_RO_SRCDIR $CPYTHON_BUILDDIR + - name: Bind mount sources read-only + run: sudo mount --bind -o ro $GITHUB_WORKSPACE $CPYTHON_RO_SRCDIR + - name: Restore config.cache + uses: actions/cache@v3 + with: + path: ${{ env.CPYTHON_BUILDDIR }}/config.cache + key: ${{ github.job }}-${{ runner.os }}-${{ inputs.config_hash }} + - name: Configure CPython out-of-tree + working-directory: ${{ env.CPYTHON_BUILDDIR }} + run: ${{ inputs.options }} + - name: Build CPython out-of-tree + working-directory: ${{ env.CPYTHON_BUILDDIR }} + run: make -j4 + - name: Display build info + working-directory: ${{ env.CPYTHON_BUILDDIR }} + run: make pythoninfo + - name: Remount sources writable for tests + # some tests write to srcdir, lack of pyc files slows down testing + run: sudo mount $CPYTHON_RO_SRCDIR -oremount,rw + - name: Tests + working-directory: ${{ env.CPYTHON_BUILDDIR }} + run: xvfb-run make test diff --git a/.github/workflows/reusable-windows.yml b/.github/workflows/reusable-windows.yml new file mode 100644 index 00000000000000..ae27c108d8368c --- /dev/null +++ b/.github/workflows/reusable-windows.yml @@ -0,0 +1,53 @@ +on: + workflow_call: + inputs: + free-threading: + required: false + type: boolean + default: false + +jobs: + build_win32: + name: 'build and test (x86)' + runs-on: windows-latest + timeout-minutes: 60 + env: + IncludeUwp: 'true' + steps: + - uses: actions/checkout@v4 + - name: Build CPython + run: .\PCbuild\build.bat -e -d -v -p Win32 ${{ inputs.free-threading && '--disable-gil' || '' }} + - name: Display build info + run: .\python.bat -m test.pythoninfo + - name: Tests + run: .\PCbuild\rt.bat -p Win32 -d -q --fast-ci + + build_win_amd64: + name: 'build and test (x64)' + runs-on: windows-latest + timeout-minutes: 60 + env: + IncludeUwp: 'true' + steps: + - uses: actions/checkout@v4 + - name: Register MSVC problem matcher + run: echo "::add-matcher::.github/problem-matchers/msvc.json" + - name: Build CPython + run: .\PCbuild\build.bat -e -d -v -p x64 ${{ inputs.free-threading && '--disable-gil' || '' }} + - name: Display build info + run: .\python.bat -m test.pythoninfo + - name: Tests + run: .\PCbuild\rt.bat -p x64 -d -q --fast-ci + + build_win_arm64: + name: 'build (arm64)' + runs-on: windows-latest + timeout-minutes: 60 + env: + IncludeUwp: 'true' + steps: + - uses: actions/checkout@v4 + - name: Register MSVC problem matcher + run: echo "::add-matcher::.github/problem-matchers/msvc.json" + - name: Build CPython + run: .\PCbuild\build.bat -e -d -v -p arm64 ${{ inputs.free-threading && '--disable-gil' || '' }} diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 94676f5ee5fffc..07608fe91b4dbe 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -16,7 +16,7 @@ jobs: steps: - name: "Check PRs" - uses: actions/stale@v8 + uses: actions/stale@v9 with: repo-token: ${{ secrets.GITHUB_TOKEN }} stale-pr-message: 'This PR is stale because it has been open for 30 days with no activity.' diff --git a/.github/workflows/verify-ensurepip-wheels.yml b/.github/workflows/verify-ensurepip-wheels.yml index 17d841f1f1c54a..83b007f1c9c2ef 100644 --- a/.github/workflows/verify-ensurepip-wheels.yml +++ b/.github/workflows/verify-ensurepip-wheels.yml @@ -25,8 +25,8 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 10 steps: - - uses: actions/checkout@v3 - - uses: actions/setup-python@v4 + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 with: python-version: '3' - name: Compare checksum of bundled wheels to the ones published on PyPI diff --git a/.gitignore b/.gitignore index dddf28da016192..c424a894c2a6e0 100644 --- a/.gitignore +++ b/.gitignore @@ -42,6 +42,7 @@ gmon.out .coverage .mypy_cache/ .pytest_cache/ +.ruff_cache/ .DS_Store *.exe @@ -124,6 +125,7 @@ Tools/unicode/data/ /config.status.lineno # hendrikmuhs/ccache-action@v1 /.ccache +/cross-build/ /platform /profile-clean-stamp /profile-run-stamp diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 85a6de4abe0146..9bd9c59a1ddc74 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,18 +1,36 @@ repos: + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.1.7 + hooks: + - id: ruff + name: Run Ruff on Lib/test/ + args: [--exit-non-zero-on-fix] + files: ^Lib/test/ + - id: ruff + name: Run Ruff on Argument Clinic + args: [--exit-non-zero-on-fix, --config=Tools/clinic/.ruff.toml] + files: ^Tools/clinic/|Lib/test/test_clinic.py + - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.4.0 + rev: v4.5.0 hooks: + - id: check-toml + exclude: ^Lib/test/test_tomllib/ - id: check-yaml - id: end-of-file-fixer types: [python] - exclude: Lib/test/coding20731.py + exclude: Lib/test/tokenizedata/coding20731.py - id: trailing-whitespace - types_or: [c, python, rst] + types_or: [c, inc, python, rst] - repo: https://github.com/sphinx-contrib/sphinx-lint - rev: v0.6.8 + rev: v0.9.1 hooks: - id: sphinx-lint args: [--enable=default-role] - files: ^Doc/ - types: [rst] + files: ^Doc/|^Misc/NEWS.d/next/ + + - repo: meta + hooks: + - id: check-hooks-apply + - id: check-useless-excludes diff --git a/Doc/Makefile b/Doc/Makefile index 22691895068fea..38fd60f2ae01d1 100644 --- a/Doc/Makefile +++ b/Doc/Makefile @@ -7,7 +7,6 @@ PYTHON = python3 VENVDIR = ./venv SPHINXBUILD = PATH=$(VENVDIR)/bin:$$PATH sphinx-build -SPHINXLINT = PATH=$(VENVDIR)/bin:$$PATH sphinx-lint BLURB = PATH=$(VENVDIR)/bin:$$PATH blurb JOBS = auto PAPER = @@ -20,8 +19,12 @@ SPHINXERRORHANDLING = -W PAPEROPT_a4 = -D latex_elements.papersize=a4paper PAPEROPT_letter = -D latex_elements.papersize=letterpaper -ALLSPHINXOPTS = -b $(BUILDER) -d build/doctrees $(PAPEROPT_$(PAPER)) -j $(JOBS) \ - $(SPHINXOPTS) $(SPHINXERRORHANDLING) . build/$(BUILDER) $(SOURCES) +ALLSPHINXOPTS = -b $(BUILDER) \ + -d build/doctrees \ + -j $(JOBS) \ + $(PAPEROPT_$(PAPER)) \ + $(SPHINXOPTS) $(SPHINXERRORHANDLING) \ + . build/$(BUILDER) $(SOURCES) .PHONY: help help: @@ -30,6 +33,7 @@ help: @echo " venv to create a venv with necessary tools" @echo " html to make standalone HTML files" @echo " htmlview to open the index page built by the html target in your browser" + @echo " htmllive to rebuild and reload HTML files in your browser" @echo " htmlhelp to make HTML files and a HTML help project" @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" @echo " text to make plain text files" @@ -140,6 +144,11 @@ pydoc-topics: build htmlview: html $(PYTHON) -c "import os, webbrowser; webbrowser.open('file://' + os.path.realpath('build/html/index.html'))" +.PHONY: htmllive +htmllive: SPHINXBUILD = $(VENVDIR)/bin/sphinx-autobuild +htmllive: SPHINXOPTS = --re-ignore="/venv/" --open-browser --delay 0 +htmllive: html + .PHONY: clean clean: clean-venv -rm -rf build/* diff --git a/Doc/bugs.rst b/Doc/bugs.rst index d98192b369603e..908987cf41ff6e 100644 --- a/Doc/bugs.rst +++ b/Doc/bugs.rst @@ -38,7 +38,7 @@ though it may take a while to be processed. `Helping with Documentation `_ Comprehensive guide for individuals that are interested in contributing to Python documentation. - `Documentation Translations `_ + `Documentation Translations `_ A list of GitHub pages for documentation translation and their primary contacts. diff --git a/Doc/c-api/allocation.rst b/Doc/c-api/allocation.rst index 44747e29643661..b3609c233156b6 100644 --- a/Doc/c-api/allocation.rst +++ b/Doc/c-api/allocation.rst @@ -29,12 +29,13 @@ Allocating Objects on the Heap .. c:macro:: PyObject_New(TYPE, typeobj) - Allocate a new Python object using the C structure type *TYPE* and the - Python type object *typeobj* (``PyTypeObject*``). - Fields not defined by the Python object header - are not initialized; the object's reference count will be one. The size of - the memory allocation is determined from the :c:member:`~PyTypeObject.tp_basicsize` field of - the type object. + Allocate a new Python object using the C structure type *TYPE* + and the Python type object *typeobj* (``PyTypeObject*``). + Fields not defined by the Python object header are not initialized. + The caller will own the only reference to the object + (i.e. its reference count will be one). + The size of the memory allocation is determined from the + :c:member:`~PyTypeObject.tp_basicsize` field of the type object. .. c:macro:: PyObject_NewVar(TYPE, typeobj, size) diff --git a/Doc/c-api/arg.rst b/Doc/c-api/arg.rst index ae321ff918d13c..834aae9372fe3b 100644 --- a/Doc/c-api/arg.rst +++ b/Doc/c-api/arg.rst @@ -293,8 +293,10 @@ Other objects ``O`` (object) [PyObject \*] Store a Python object (without any conversion) in a C object pointer. The C - program thus receives the actual object that was passed. The object's reference - count is not increased. The pointer stored is not ``NULL``. + program thus receives the actual object that was passed. A new + :term:`strong reference` to the object is not created + (i.e. its reference count is not increased). + The pointer stored is not ``NULL``. ``O!`` (object) [*typeobject*, PyObject \*] Store a Python object in a C object pointer. This is similar to ``O``, but @@ -378,7 +380,8 @@ inside nested parentheses. They are: mutually exclude each other. Note that any Python object references which are provided to the caller are -*borrowed* references; do not decrement their reference count! +*borrowed* references; do not release them +(i.e. do not decrement their reference count)! Additional arguments passed to these functions must be addresses of variables whose type is determined by the format string; these are used to store values @@ -410,21 +413,35 @@ API Functions than a variable number of arguments. -.. c:function:: int PyArg_ParseTupleAndKeywords(PyObject *args, PyObject *kw, const char *format, char *keywords[], ...) +.. c:function:: int PyArg_ParseTupleAndKeywords(PyObject *args, PyObject *kw, const char *format, char * const *keywords, ...) Parse the parameters of a function that takes both positional and keyword - parameters into local variables. The *keywords* argument is a - ``NULL``-terminated array of keyword parameter names. Empty names denote + parameters into local variables. + The *keywords* argument is a ``NULL``-terminated array of keyword parameter + names specified as null-terminated ASCII or UTF-8 encoded C strings. + Empty names denote :ref:`positional-only parameters `. Returns true on success; on failure, it returns false and raises the appropriate exception. + .. note:: + + The *keywords* parameter declaration is :c:expr:`char * const *` in C and + :c:expr:`const char * const *` in C++. + This can be overridden with the :c:macro:`PY_CXX_CONST` macro. + .. versionchanged:: 3.6 Added support for :ref:`positional-only parameters `. + .. versionchanged:: 3.13 + The *keywords* parameter has now type :c:expr:`char * const *` in C and + :c:expr:`const char * const *` in C++, instead of :c:expr:`char **`. + Added support for non-ASCII keyword parameter names. + -.. c:function:: int PyArg_VaParseTupleAndKeywords(PyObject *args, PyObject *kw, const char *format, char *keywords[], va_list vargs) + +.. c:function:: int PyArg_VaParseTupleAndKeywords(PyObject *args, PyObject *kw, const char *format, char * const *keywords, va_list vargs) Identical to :c:func:`PyArg_ParseTupleAndKeywords`, except that it accepts a va_list rather than a variable number of arguments. @@ -497,6 +514,19 @@ API Functions PyArg_ParseTuple(args, "O|O:ref", &object, &callback) +.. c:macro:: PY_CXX_CONST + + The value to be inserted, if any, before :c:expr:`char * const *` + in the *keywords* parameter declaration of + :c:func:`PyArg_ParseTupleAndKeywords` and + :c:func:`PyArg_VaParseTupleAndKeywords`. + Default empty for C and ``const`` for C++ + (:c:expr:`const char * const *`). + To override, define it to the desired value before including + :file:`Python.h`. + + .. versionadded:: 3.13 + --------------- Building values @@ -621,8 +651,10 @@ Building values Convert a C :c:type:`Py_complex` structure to a Python complex number. ``O`` (object) [PyObject \*] - Pass a Python object untouched (except for its reference count, which is - incremented by one). If the object passed in is a ``NULL`` pointer, it is assumed + Pass a Python object untouched but create a new + :term:`strong reference` to it + (i.e. its reference count is incremented by one). + If the object passed in is a ``NULL`` pointer, it is assumed that this was caused because the call producing the argument found an error and set an exception. Therefore, :c:func:`Py_BuildValue` will return ``NULL`` but won't raise an exception. If no exception has been raised yet, :exc:`SystemError` is @@ -632,7 +664,7 @@ Building values Same as ``O``. ``N`` (object) [PyObject \*] - Same as ``O``, except it doesn't increment the reference count on the object. + Same as ``O``, except it doesn't create a new :term:`strong reference`. Useful when the object is created by a call to an object constructor in the argument list. diff --git a/Doc/c-api/bool.rst b/Doc/c-api/bool.rst index b14fa6a0a982e2..b4dc4849d044e1 100644 --- a/Doc/c-api/bool.rst +++ b/Doc/c-api/bool.rst @@ -26,19 +26,19 @@ are available, however. .. c:var:: PyObject* Py_False The Python ``False`` object. This object has no methods and is - `immortal `_. + :term:`immortal`. -.. versionchanged:: 3.12 - :c:data:`Py_False` is immortal. + .. versionchanged:: 3.12 + :c:data:`Py_False` is :term:`immortal`. .. c:var:: PyObject* Py_True The Python ``True`` object. This object has no methods and is - `immortal `_. + :term:`immortal`. -.. versionchanged:: 3.12 - :c:data:`Py_True` is immortal. + .. versionchanged:: 3.12 + :c:data:`Py_True` is :term:`immortal`. .. c:macro:: Py_RETURN_FALSE diff --git a/Doc/c-api/buffer.rst b/Doc/c-api/buffer.rst index 02b53ec149c733..e572815ffd6259 100644 --- a/Doc/c-api/buffer.rst +++ b/Doc/c-api/buffer.rst @@ -102,7 +102,9 @@ a buffer, see :c:func:`PyObject_GetBuffer`. .. c:member:: PyObject *obj A new reference to the exporting object. The reference is owned by - the consumer and automatically decremented and set to ``NULL`` by + the consumer and automatically released + (i.e. reference count decremented) + and set to ``NULL`` by :c:func:`PyBuffer_Release`. The field is the equivalent of the return value of any standard C-API function. @@ -159,10 +161,7 @@ a buffer, see :c:func:`PyObject_GetBuffer`. If it is ``0``, :c:member:`~Py_buffer.buf` points to a single item representing a scalar. In this case, :c:member:`~Py_buffer.shape`, :c:member:`~Py_buffer.strides` and :c:member:`~Py_buffer.suboffsets` MUST be ``NULL``. - - The macro :c:macro:`PyBUF_MAX_NDIM` limits the maximum number of dimensions - to 64. Exporters MUST respect this limit, consumers of multi-dimensional - buffers SHOULD be able to handle up to :c:macro:`PyBUF_MAX_NDIM` dimensions. + The maximum number of dimensions is given by :c:macro:`PyBUF_MAX_NDIM`. .. c:member:: Py_ssize_t *shape @@ -215,6 +214,17 @@ a buffer, see :c:func:`PyObject_GetBuffer`. freed when the buffer is released. The consumer MUST NOT alter this value. + +Constants: + +.. c:macro:: PyBUF_MAX_NDIM + + The maximum number of dimensions the memory represents. + Exporters MUST respect this limit, consumers of multi-dimensional + buffers SHOULD be able to handle up to :c:macro:`!PyBUF_MAX_NDIM` dimensions. + Currently set to 64. + + .. _buffer-request-types: Buffer request types @@ -438,7 +448,7 @@ Buffer-related functions Send a request to *exporter* to fill in *view* as specified by *flags*. If the exporter cannot provide a buffer of the exact type, it MUST raise - :c:data:`PyExc_BufferError`, set ``view->obj`` to ``NULL`` and + :exc:`BufferError`, set ``view->obj`` to ``NULL`` and return ``-1``. On success, fill in *view*, set ``view->obj`` to a new reference @@ -454,7 +464,8 @@ Buffer-related functions .. c:function:: void PyBuffer_Release(Py_buffer *view) - Release the buffer *view* and decrement the reference count for + Release the buffer *view* and release the :term:`strong reference` + (i.e. decrement the reference count) to the view's supporting object, ``view->obj``. This function MUST be called when the buffer is no longer being used, otherwise reference leaks may occur. @@ -524,7 +535,7 @@ Buffer-related functions and :c:macro:`PyBUF_WRITABLE` is set in *flags*. On success, set ``view->obj`` to a new reference to *exporter* and - return 0. Otherwise, raise :c:data:`PyExc_BufferError`, set + return 0. Otherwise, raise :exc:`BufferError`, set ``view->obj`` to ``NULL`` and return ``-1``; If this function is used as part of a :ref:`getbufferproc `, diff --git a/Doc/c-api/bytes.rst b/Doc/c-api/bytes.rst index 4e3ffc7e23e3f8..4790d3b2da4375 100644 --- a/Doc/c-api/bytes.rst +++ b/Doc/c-api/bytes.rst @@ -155,6 +155,7 @@ called with a non-bytes parameter. Return the null-terminated contents of the object *obj* through the output variables *buffer* and *length*. + Returns ``0`` on success. If *length* is ``NULL``, the bytes object may not contain embedded null bytes; @@ -184,8 +185,8 @@ called with a non-bytes parameter. .. c:function:: void PyBytes_ConcatAndDel(PyObject **bytes, PyObject *newpart) Create a new bytes object in *\*bytes* containing the contents of *newpart* - appended to *bytes*. This version decrements the reference count of - *newpart*. + appended to *bytes*. This version releases the :term:`strong reference` + to *newpart* (i.e. decrements its reference count). .. c:function:: int _PyBytes_Resize(PyObject **bytes, Py_ssize_t newsize) diff --git a/Doc/c-api/call.rst b/Doc/c-api/call.rst index aed4ae44c76eea..7198d6bc056eb4 100644 --- a/Doc/c-api/call.rst +++ b/Doc/c-api/call.rst @@ -108,6 +108,8 @@ This is a pointer to a function with the following signature: Doing so will allow callables such as bound methods to make their onward calls (which include a prepended *self* argument) very efficiently. + .. versionadded:: 3.8 + To call an object that implements vectorcall, use a :ref:`call API ` function as with any other callable. :c:func:`PyObject_Vectorcall` will usually be most efficient. diff --git a/Doc/c-api/datetime.rst b/Doc/c-api/datetime.rst index 72fc07afbf1f4d..97522da773477e 100644 --- a/Doc/c-api/datetime.rst +++ b/Doc/c-api/datetime.rst @@ -8,11 +8,54 @@ DateTime Objects Various date and time objects are supplied by the :mod:`datetime` module. Before using any of these functions, the header file :file:`datetime.h` must be included in your source (note that this is not included by :file:`Python.h`), -and the macro :c:macro:`PyDateTime_IMPORT` must be invoked, usually as part of +and the macro :c:macro:`!PyDateTime_IMPORT` must be invoked, usually as part of the module initialisation function. The macro puts a pointer to a C structure -into a static variable, :c:data:`PyDateTimeAPI`, that is used by the following +into a static variable, :c:data:`!PyDateTimeAPI`, that is used by the following macros. +.. c:type:: PyDateTime_Date + + This subtype of :c:type:`PyObject` represents a Python date object. + +.. c:type:: PyDateTime_DateTime + + This subtype of :c:type:`PyObject` represents a Python datetime object. + +.. c:type:: PyDateTime_Time + + This subtype of :c:type:`PyObject` represents a Python time object. + +.. c:type:: PyDateTime_Delta + + This subtype of :c:type:`PyObject` represents the difference between two datetime values. + +.. c:var:: PyTypeObject PyDateTime_DateType + + This instance of :c:type:`PyTypeObject` represents the Python date type; + it is the same object as :class:`datetime.date` in the Python layer. + +.. c:var:: PyTypeObject PyDateTime_DateTimeType + + This instance of :c:type:`PyTypeObject` represents the Python datetime type; + it is the same object as :class:`datetime.datetime` in the Python layer. + +.. c:var:: PyTypeObject PyDateTime_TimeType + + This instance of :c:type:`PyTypeObject` represents the Python time type; + it is the same object as :class:`datetime.time` in the Python layer. + +.. c:var:: PyTypeObject PyDateTime_DeltaType + + This instance of :c:type:`PyTypeObject` represents Python type for + the difference between two datetime values; + it is the same object as :class:`datetime.timedelta` in the Python layer. + +.. c:var:: PyTypeObject PyDateTime_TZInfoType + + This instance of :c:type:`PyTypeObject` represents the Python time zone info type; + it is the same object as :class:`datetime.tzinfo` in the Python layer. + + Macro for access to the UTC singleton: .. c:var:: PyObject* PyDateTime_TimeZone_UTC @@ -28,7 +71,7 @@ Type-check macros: .. c:function:: int PyDate_Check(PyObject *ob) Return true if *ob* is of type :c:data:`PyDateTime_DateType` or a subtype of - :c:data:`PyDateTime_DateType`. *ob* must not be ``NULL``. This function always + :c:data:`!PyDateTime_DateType`. *ob* must not be ``NULL``. This function always succeeds. @@ -41,7 +84,7 @@ Type-check macros: .. c:function:: int PyDateTime_Check(PyObject *ob) Return true if *ob* is of type :c:data:`PyDateTime_DateTimeType` or a subtype of - :c:data:`PyDateTime_DateTimeType`. *ob* must not be ``NULL``. This function always + :c:data:`!PyDateTime_DateTimeType`. *ob* must not be ``NULL``. This function always succeeds. @@ -54,7 +97,7 @@ Type-check macros: .. c:function:: int PyTime_Check(PyObject *ob) Return true if *ob* is of type :c:data:`PyDateTime_TimeType` or a subtype of - :c:data:`PyDateTime_TimeType`. *ob* must not be ``NULL``. This function always + :c:data:`!PyDateTime_TimeType`. *ob* must not be ``NULL``. This function always succeeds. @@ -67,7 +110,7 @@ Type-check macros: .. c:function:: int PyDelta_Check(PyObject *ob) Return true if *ob* is of type :c:data:`PyDateTime_DeltaType` or a subtype of - :c:data:`PyDateTime_DeltaType`. *ob* must not be ``NULL``. This function always + :c:data:`!PyDateTime_DeltaType`. *ob* must not be ``NULL``. This function always succeeds. @@ -80,7 +123,7 @@ Type-check macros: .. c:function:: int PyTZInfo_Check(PyObject *ob) Return true if *ob* is of type :c:data:`PyDateTime_TZInfoType` or a subtype of - :c:data:`PyDateTime_TZInfoType`. *ob* must not be ``NULL``. This function always + :c:data:`!PyDateTime_TZInfoType`. *ob* must not be ``NULL``. This function always succeeds. @@ -133,7 +176,7 @@ Macros to create objects: :class:`datetime.timedelta` objects. -.. c:function:: PyObject* PyTimeZone_FromOffset(PyDateTime_DeltaType* offset) +.. c:function:: PyObject* PyTimeZone_FromOffset(PyObject *offset) Return a :class:`datetime.timezone` object with an unnamed fixed offset represented by the *offset* argument. @@ -141,7 +184,7 @@ Macros to create objects: .. versionadded:: 3.7 -.. c:function:: PyObject* PyTimeZone_FromOffsetAndName(PyDateTime_DeltaType* offset, PyUnicode* name) +.. c:function:: PyObject* PyTimeZone_FromOffsetAndName(PyObject *offset, PyObject *name) Return a :class:`datetime.timezone` object with a fixed offset represented by the *offset* argument and with tzname *name*. @@ -150,8 +193,8 @@ Macros to create objects: Macros to extract fields from date objects. The argument must be an instance of -:c:data:`PyDateTime_Date`, including subclasses (such as -:c:data:`PyDateTime_DateTime`). The argument must not be ``NULL``, and the type is +:c:type:`PyDateTime_Date`, including subclasses (such as +:c:type:`PyDateTime_DateTime`). The argument must not be ``NULL``, and the type is not checked: .. c:function:: int PyDateTime_GET_YEAR(PyDateTime_Date *o) @@ -170,7 +213,7 @@ not checked: Macros to extract fields from datetime objects. The argument must be an -instance of :c:data:`PyDateTime_DateTime`, including subclasses. The argument +instance of :c:type:`PyDateTime_DateTime`, including subclasses. The argument must not be ``NULL``, and the type is not checked: .. c:function:: int PyDateTime_DATE_GET_HOUR(PyDateTime_DateTime *o) @@ -208,7 +251,7 @@ must not be ``NULL``, and the type is not checked: Macros to extract fields from time objects. The argument must be an instance of -:c:data:`PyDateTime_Time`, including subclasses. The argument must not be ``NULL``, +:c:type:`PyDateTime_Time`, including subclasses. The argument must not be ``NULL``, and the type is not checked: .. c:function:: int PyDateTime_TIME_GET_HOUR(PyDateTime_Time *o) @@ -246,7 +289,7 @@ and the type is not checked: Macros to extract fields from time delta objects. The argument must be an -instance of :c:data:`PyDateTime_Delta`, including subclasses. The argument must +instance of :c:type:`PyDateTime_Delta`, including subclasses. The argument must not be ``NULL``, and the type is not checked: .. c:function:: int PyDateTime_DELTA_GET_DAYS(PyDateTime_Delta *o) diff --git a/Doc/c-api/dict.rst b/Doc/c-api/dict.rst index e4c1d71a413a68..8471c98d044872 100644 --- a/Doc/c-api/dict.rst +++ b/Doc/c-api/dict.rst @@ -55,6 +55,15 @@ Dictionary Objects This is equivalent to the Python expression ``key in p``. +.. c:function:: int PyDict_ContainsString(PyObject *p, const char *key) + + This is the same as :c:func:`PyDict_Contains`, but *key* is specified as a + :c:expr:`const char*` UTF-8 encoded bytes string, rather than a + :c:expr:`PyObject*`. + + .. versionadded:: 3.13 + + .. c:function:: PyObject* PyDict_Copy(PyObject *p) Return a new dictionary that contains the same key-value pairs as *p*. @@ -70,12 +79,9 @@ Dictionary Objects .. c:function:: int PyDict_SetItemString(PyObject *p, const char *key, PyObject *val) - .. index:: single: PyUnicode_FromString() - - Insert *val* into the dictionary *p* using *key* as a key. *key* should - be a :c:expr:`const char*`. The key object is created using - ``PyUnicode_FromString(key)``. Return ``0`` on success or ``-1`` on - failure. This function *does not* steal a reference to *val*. + This is the same as :c:func:`PyDict_SetItem`, but *key* is + specified as a :c:expr:`const char*` UTF-8 encoded bytes string, + rather than a :c:expr:`PyObject*`. .. c:function:: int PyDict_DelItem(PyObject *p, PyObject *key) @@ -88,9 +94,9 @@ Dictionary Objects .. c:function:: int PyDict_DelItemString(PyObject *p, const char *key) - Remove the entry in dictionary *p* which has a key specified by the string *key*. - If *key* is not in the dictionary, :exc:`KeyError` is raised. - Return ``0`` on success or ``-1`` on failure. + This is the same as :c:func:`PyDict_DelItem`, but *key* is + specified as a :c:expr:`const char*` UTF-8 encoded bytes string, + rather than a :c:expr:`PyObject*`. .. c:function:: int PyDict_GetItemRef(PyObject *p, PyObject *key, PyObject **result) @@ -136,7 +142,8 @@ Dictionary Objects .. c:function:: PyObject* PyDict_GetItemString(PyObject *p, const char *key) This is the same as :c:func:`PyDict_GetItem`, but *key* is specified as a - :c:expr:`const char*`, rather than a :c:expr:`PyObject*`. + :c:expr:`const char*` UTF-8 encoded bytes string, rather than a + :c:expr:`PyObject*`. .. note:: @@ -150,7 +157,8 @@ Dictionary Objects .. c:function:: int PyDict_GetItemStringRef(PyObject *p, const char *key, PyObject **result) Similar than :c:func:`PyDict_GetItemRef`, but *key* is specified as a - :c:expr:`const char*`, rather than a :c:expr:`PyObject*`. + :c:expr:`const char*` UTF-8 encoded bytes string, rather than a + :c:expr:`PyObject*`. .. versionadded:: 3.13 @@ -165,6 +173,33 @@ Dictionary Objects .. versionadded:: 3.4 + +.. c:function:: int PyDict_Pop(PyObject *p, PyObject *key, PyObject **result) + + Remove *key* from dictionary *p* and optionally return the removed value. + Do not raise :exc:`KeyError` if the key missing. + + - If the key is present, set *\*result* to a new reference to the removed + value if *result* is not ``NULL``, and return ``1``. + - If the key is missing, set *\*result* to ``NULL`` if *result* is not + ``NULL``, and return ``0``. + - On error, raise an exception and return ``-1``. + + This is similar to :meth:`dict.pop`, but without the default value and + not raising :exc:`KeyError` if the key missing. + + .. versionadded:: 3.13 + + +.. c:function:: int PyDict_PopString(PyObject *p, const char *key, PyObject **result) + + Similar to :c:func:`PyDict_Pop`, but *key* is specified as a + :c:expr:`const char*` UTF-8 encoded bytes string, rather than a + :c:expr:`PyObject*`. + + .. versionadded:: 3.13 + + .. c:function:: PyObject* PyDict_Items(PyObject *p) Return a :c:type:`PyListObject` containing all the items from the dictionary. diff --git a/Doc/c-api/exceptions.rst b/Doc/c-api/exceptions.rst index a2126ffc559aba..c7e3cd9463e5d7 100644 --- a/Doc/c-api/exceptions.rst +++ b/Doc/c-api/exceptions.rst @@ -88,9 +88,29 @@ Printing and clearing The function is called with a single argument *obj* that identifies the context in which the unraisable exception occurred. If possible, the repr of *obj* will be printed in the warning message. + If *obj* is ``NULL``, only the traceback is printed. An exception must be set when calling this function. + .. versionchanged:: 3.4 + Print a traceback. Print only traceback if *obj* is ``NULL``. + + .. versionchanged:: 3.8 + Use :func:`sys.unraisablehook`. + + +.. c:function:: void PyErr_FormatUnraisable(const char *format, ...) + + Similar to :c:func:`PyErr_WriteUnraisable`, but the *format* and subsequent + parameters help format the warning message; they have the same meaning and + values as in :c:func:`PyUnicode_FromFormat`. + ``PyErr_WriteUnraisable(obj)`` is roughtly equivalent to + ``PyErr_FormatUnraisable("Exception ignored in: %R, obj)``. + If *format* is ``NULL``, only the traceback is printed. + + .. versionadded:: 3.13 + + .. c:function:: void PyErr_DisplayException(PyObject *exc) Print the standard traceback display of ``exc`` to ``sys.stderr``, including @@ -98,6 +118,7 @@ Printing and clearing .. versionadded:: 3.12 + Raising exceptions ================== @@ -110,7 +131,8 @@ For convenience, some of these functions will always return a This is the most common way to set the error indicator. The first argument specifies the exception type; it is normally one of the standard exceptions, - e.g. :c:data:`PyExc_RuntimeError`. You need not increment its reference count. + e.g. :c:data:`PyExc_RuntimeError`. You need not create a new + :term:`strong reference` to it (e.g. with :c:func:`Py_INCREF`). The second argument is an error message; it is decoded from ``'utf-8'``. @@ -221,17 +243,21 @@ For convenience, some of these functions will always return a .. c:function:: PyObject* PyErr_SetFromWindowsErrWithFilename(int ierr, const char *filename) - Similar to :c:func:`PyErr_SetFromWindowsErrWithFilenameObject`, but the - filename is given as a C string. *filename* is decoded from the filesystem - encoding (:func:`os.fsdecode`). + Similar to :c:func:`PyErr_SetFromWindowsErr`, with the additional behavior + that if *filename* is not ``NULL``, it is decoded from the filesystem + encoding (:func:`os.fsdecode`) and passed to the constructor of + :exc:`OSError` as a third parameter to be used to define the + :attr:`!filename` attribute of the exception instance. .. availability:: Windows. .. c:function:: PyObject* PyErr_SetExcFromWindowsErrWithFilenameObject(PyObject *type, int ierr, PyObject *filename) - Similar to :c:func:`PyErr_SetFromWindowsErrWithFilenameObject`, with an - additional parameter specifying the exception type to be raised. + Similar to :c:func:`PyErr_SetExcFromWindowsErr`, with the additional behavior + that if *filename* is not ``NULL``, it is passed to the constructor of + :exc:`OSError` as a third parameter to be used to define the + :attr:`!filename` attribute of the exception instance. .. availability:: Windows. @@ -414,7 +440,7 @@ Querying the error indicator .. c:function:: PyObject *PyErr_GetRaisedException(void) Return the exception currently being raised, clearing the error indicator at - the same time. + the same time. Return ``NULL`` if the error indicator is not set. This function is used by code that needs to catch exceptions, or code that needs to save and restore the error indicator temporarily. @@ -515,7 +541,8 @@ Querying the error indicator .. note:: - This function *does not* implicitly set the ``__traceback__`` + This function *does not* implicitly set the + :attr:`~BaseException.__traceback__` attribute on the exception value. If setting the traceback appropriately is desired, the following additional snippet is needed:: @@ -727,7 +754,8 @@ Exception Objects .. c:function:: PyObject* PyException_GetTraceback(PyObject *ex) Return the traceback associated with the exception as a new reference, as - accessible from Python through :attr:`__traceback__`. If there is no + accessible from Python through the :attr:`~BaseException.__traceback__` + attribute. If there is no traceback associated, this returns ``NULL``. @@ -741,8 +769,8 @@ Exception Objects Return the context (another exception instance during whose handling *ex* was raised) associated with the exception as a new reference, as accessible from - Python through :attr:`__context__`. If there is no context associated, this - returns ``NULL``. + Python through the :attr:`~BaseException.__context__` attribute. + If there is no context associated, this returns ``NULL``. .. c:function:: void PyException_SetContext(PyObject *ex, PyObject *ctx) @@ -756,7 +784,8 @@ Exception Objects Return the cause (either an exception instance, or ``None``, set by ``raise ... from ...``) associated with the exception as a new - reference, as accessible from Python through :attr:`__cause__`. + reference, as accessible from Python through the + :attr:`~BaseException.__cause__` attribute. .. c:function:: void PyException_SetCause(PyObject *ex, PyObject *cause) @@ -765,7 +794,8 @@ Exception Objects it. There is no type check to make sure that *cause* is either an exception instance or ``None``. This steals a reference to *cause*. - :attr:`__suppress_context__` is implicitly set to ``True`` by this function. + The :attr:`~BaseException.__suppress_context__` attribute is implicitly set + to ``True`` by this function. .. c:function:: PyObject* PyException_GetArgs(PyObject *ex) @@ -781,7 +811,7 @@ Exception Objects Implement part of the interpreter's implementation of :keyword:`!except*`. *orig* is the original exception that was caught, and *excs* is the list of - the exceptions that need to be raised. This list contains the the unhandled + the exceptions that need to be raised. This list contains the unhandled part of *orig*, if any, as well as the exceptions that were raised from the :keyword:`!except*` clauses (so they have a different traceback from *orig*) and those that were reraised (and have the same traceback as *orig*). diff --git a/Doc/c-api/frame.rst b/Doc/c-api/frame.rst index 1accee2767a485..6bb1e9b5803b58 100644 --- a/Doc/c-api/frame.rst +++ b/Doc/c-api/frame.rst @@ -50,7 +50,7 @@ See also :ref:`Reflection `. .. c:function:: PyObject* PyFrame_GetBuiltins(PyFrameObject *frame) - Get the *frame*'s ``f_builtins`` attribute. + Get the *frame*'s :attr:`~frame.f_builtins` attribute. Return a :term:`strong reference`. The result cannot be ``NULL``. @@ -81,7 +81,7 @@ See also :ref:`Reflection `. .. c:function:: PyObject* PyFrame_GetGlobals(PyFrameObject *frame) - Get the *frame*'s ``f_globals`` attribute. + Get the *frame*'s :attr:`~frame.f_globals` attribute. Return a :term:`strong reference`. The result cannot be ``NULL``. @@ -90,7 +90,7 @@ See also :ref:`Reflection `. .. c:function:: int PyFrame_GetLasti(PyFrameObject *frame) - Get the *frame*'s ``f_lasti`` attribute. + Get the *frame*'s :attr:`~frame.f_lasti` attribute. Returns -1 if ``frame.f_lasti`` is ``None``. @@ -120,7 +120,7 @@ See also :ref:`Reflection `. .. c:function:: PyObject* PyFrame_GetLocals(PyFrameObject *frame) - Get the *frame*'s ``f_locals`` attribute (:class:`dict`). + Get the *frame*'s :attr:`~frame.f_locals` attribute (:class:`dict`). Return a :term:`strong reference`. diff --git a/Doc/c-api/function.rst b/Doc/c-api/function.rst index 5857dba82c11c6..e7fb5090c09933 100644 --- a/Doc/c-api/function.rst +++ b/Doc/c-api/function.rst @@ -34,18 +34,20 @@ There are a few functions specific to Python functions. Return a new function object associated with the code object *code*. *globals* must be a dictionary with the global variables accessible to the function. - The function's docstring and name are retrieved from the code object. *__module__* + The function's docstring and name are retrieved from the code object. + :attr:`~function.__module__` is retrieved from *globals*. The argument defaults, annotations and closure are - set to ``NULL``. *__qualname__* is set to the same value as the code object's - ``co_qualname`` field. + set to ``NULL``. :attr:`~function.__qualname__` is set to the same value as + the code object's :attr:`~codeobject.co_qualname` field. .. c:function:: PyObject* PyFunction_NewWithQualName(PyObject *code, PyObject *globals, PyObject *qualname) As :c:func:`PyFunction_New`, but also allows setting the function object's - ``__qualname__`` attribute. *qualname* should be a unicode object or ``NULL``; - if ``NULL``, the ``__qualname__`` attribute is set to the same value as the - code object's ``co_qualname`` field. + :attr:`~function.__qualname__` attribute. + *qualname* should be a unicode object or ``NULL``; + if ``NULL``, the :attr:`!__qualname__` attribute is set to the same value as + the code object's :attr:`~codeobject.co_qualname` field. .. versionadded:: 3.3 @@ -62,11 +64,12 @@ There are a few functions specific to Python functions. .. c:function:: PyObject* PyFunction_GetModule(PyObject *op) - Return a :term:`borrowed reference` to the *__module__* attribute of the - function object *op*. It can be *NULL*. + Return a :term:`borrowed reference` to the :attr:`~function.__module__` + attribute of the :ref:`function object ` *op*. + It can be *NULL*. - This is normally a string containing the module name, but can be set to any - other object by Python code. + This is normally a :class:`string ` containing the module name, + but can be set to any other object by Python code. .. c:function:: PyObject* PyFunction_GetDefaults(PyObject *op) diff --git a/Doc/c-api/hash.rst b/Doc/c-api/hash.rst new file mode 100644 index 00000000000000..91d88ae27bc9f4 --- /dev/null +++ b/Doc/c-api/hash.rst @@ -0,0 +1,61 @@ +.. highlight:: c + +PyHash API +---------- + +See also the :c:member:`PyTypeObject.tp_hash` member. + +.. c:type:: Py_hash_t + + Hash value type: signed integer. + + .. versionadded:: 3.2 + +.. c:type:: Py_uhash_t + + Hash value type: unsigned integer. + + .. versionadded:: 3.2 + + +.. c:type:: PyHash_FuncDef + + Hash function definition used by :c:func:`PyHash_GetFuncDef`. + + .. c::member:: Py_hash_t (*const hash)(const void *, Py_ssize_t) + + Hash function. + + .. c:member:: const char *name + + Hash function name (UTF-8 encoded string). + + .. c:member:: const int hash_bits + + Internal size of the hash value in bits. + + .. c:member:: const int seed_bits + + Size of seed input in bits. + + .. versionadded:: 3.4 + + +.. c:function:: PyHash_FuncDef* PyHash_GetFuncDef(void) + + Get the hash function definition. + + .. seealso:: + :pep:`456` "Secure and interchangeable hash algorithm". + + .. versionadded:: 3.4 + + +.. c:function:: Py_hash_t Py_HashPointer(const void *ptr) + + Hash a pointer value: process the pointer value as an integer (cast it to + ``uintptr_t`` internally). The pointer is not dereferenced. + + The function cannot fail: it cannot return ``-1``. + + .. versionadded:: 3.13 diff --git a/Doc/c-api/import.rst b/Doc/c-api/import.rst index 137780cc359cf9..51c20b202f091c 100644 --- a/Doc/c-api/import.rst +++ b/Doc/c-api/import.rst @@ -154,7 +154,7 @@ Importing Modules :class:`~importlib.machinery.SourceFileLoader` otherwise. The module's :attr:`__file__` attribute will be set to the code object's - :attr:`!co_filename`. If applicable, :attr:`__cached__` will also + :attr:`~codeobject.co_filename`. If applicable, :attr:`__cached__` will also be set. This function will reload the module if it was already imported. See diff --git a/Doc/c-api/init.rst b/Doc/c-api/init.rst index dd53fe2bc95696..f8fd48e781d6da 100644 --- a/Doc/c-api/init.rst +++ b/Doc/c-api/init.rst @@ -373,6 +373,14 @@ Initializing and finalizing the interpreter :c:func:`Py_Initialize` is called again. +.. c:function:: int Py_IsFinalizing() + + Return true (non-zero) if the main Python interpreter is + :term:`shutting down `. Return false (zero) otherwise. + + .. versionadded:: 3.13 + + .. c:function:: int Py_FinalizeEx() Undo all initializations made by :c:func:`Py_Initialize` and subsequent use of @@ -852,7 +860,7 @@ code, or when embedding the Python interpreter: .. note:: Calling this function from a thread when the runtime is finalizing will terminate the thread, even if the thread was not created by Python. - You can use :c:func:`!_Py_IsFinalizing` or :func:`sys.is_finalizing` to + You can use :c:func:`Py_IsFinalizing` or :func:`sys.is_finalizing` to check if the interpreter is in process of being finalized before calling this function to avoid unwanted termination. @@ -862,6 +870,19 @@ code, or when embedding the Python interpreter: When the current thread state is ``NULL``, this issues a fatal error (so that the caller needn't check for ``NULL``). + See also :c:func:`PyThreadState_GetUnchecked`. + + +.. c:function:: PyThreadState* PyThreadState_GetUnchecked() + + Similar to :c:func:`PyThreadState_Get`, but don't kill the process with a + fatal error if it is NULL. The caller is responsible to check if the result + is NULL. + + .. versionadded:: 3.13 + In Python 3.5 to 3.12, the function was private and known as + ``_PyThreadState_UncheckedGet()``. + .. c:function:: PyThreadState* PyThreadState_Swap(PyThreadState *tstate) @@ -898,7 +919,7 @@ with sub-interpreters: .. note:: Calling this function from a thread when the runtime is finalizing will terminate the thread, even if the thread was not created by Python. - You can use :c:func:`!_Py_IsFinalizing` or :func:`sys.is_finalizing` to + You can use :c:func:`Py_IsFinalizing` or :func:`sys.is_finalizing` to check if the interpreter is in process of being finalized before calling this function to avoid unwanted termination. @@ -1180,7 +1201,7 @@ All of the following functions must be called after :c:func:`Py_Initialize`. .. note:: Calling this function from a thread when the runtime is finalizing will terminate the thread, even if the thread was not created by Python. - You can use :c:func:`!_Py_IsFinalizing` or :func:`sys.is_finalizing` to + You can use :c:func:`Py_IsFinalizing` or :func:`sys.is_finalizing` to check if the interpreter is in process of being finalized before calling this function to avoid unwanted termination. @@ -1464,7 +1485,7 @@ otherwise immutable (e.g. ``None``, ``(1, 5)``) can't normally be shared because of the refcount. One simple but less-efficient approach around this is to use a global lock around all use of some state (or object). Alternately, effectively immutable objects (like integers or strings) -can be made safe in spite of their refcounts by making them "immortal". +can be made safe in spite of their refcounts by making them :term:`immortal`. In fact, this has been done for the builtin singletons, small integers, and a number of other builtin objects. @@ -1641,7 +1662,8 @@ Python-level trace functions in previous versions. The value passed as the *what* parameter to a :c:type:`Py_tracefunc` function (but not a profiling function) when a line-number event is being reported. - It may be disabled for a frame by setting :attr:`f_trace_lines` to *0* on that frame. + It may be disabled for a frame by setting :attr:`~frame.f_trace_lines` to + *0* on that frame. .. c:var:: int PyTrace_RETURN @@ -1673,7 +1695,7 @@ Python-level trace functions in previous versions. The value for the *what* parameter to :c:type:`Py_tracefunc` functions (but not profiling functions) when a new opcode is about to be executed. This event is not emitted by default: it must be explicitly requested by setting - :attr:`f_trace_opcodes` to *1* on the frame. + :attr:`~frame.f_trace_opcodes` to *1* on the frame. .. c:function:: void PyEval_SetProfile(Py_tracefunc func, PyObject *obj) diff --git a/Doc/c-api/init_config.rst b/Doc/c-api/init_config.rst index ac7b357e08eeba..47a8fbb2cd9c97 100644 --- a/Doc/c-api/init_config.rst +++ b/Doc/c-api/init_config.rst @@ -82,6 +82,8 @@ PyWideStringList If *length* is non-zero, *items* must be non-``NULL`` and all strings must be non-``NULL``. + .. c:namespace:: NULL + Methods: .. c:function:: PyStatus PyWideStringList_Append(PyWideStringList *list, const wchar_t *item) @@ -101,6 +103,8 @@ PyWideStringList Python must be preinitialized to call this function. + .. c:namespace:: PyWideStringList + Structure fields: .. c:member:: Py_ssize_t length @@ -249,11 +253,21 @@ PyPreConfig * ``PYMEM_ALLOCATOR_PYMALLOC_DEBUG`` (``6``): :ref:`Python pymalloc memory allocator ` with :ref:`debug hooks `. + * ``PYMEM_ALLOCATOR_MIMALLOC`` (``6``): use ``mimalloc``, a fast + malloc replacement. + * ``PYMEM_ALLOCATOR_MIMALLOC_DEBUG`` (``7``): use ``mimalloc``, a fast + malloc replacement with :ref:`debug hooks `. + ``PYMEM_ALLOCATOR_PYMALLOC`` and ``PYMEM_ALLOCATOR_PYMALLOC_DEBUG`` are not supported if Python is :option:`configured using --without-pymalloc <--without-pymalloc>`. + ``PYMEM_ALLOCATOR_MIMALLOC`` and ``PYMEM_ALLOCATOR_MIMALLOC_DEBUG`` are + not supported if Python is :option:`configured using --without-mimalloc + <--without-mimalloc>` or if the underlying atomic support isn't + available. + See :ref:`Memory Management `. Default: ``PYMEM_ALLOCATOR_NOT_SET``. @@ -712,7 +726,7 @@ PyConfig Set to ``1`` by the :envvar:`PYTHONDUMPREFS` environment variable. - Need a special build of Python with the ``Py_TRACE_REFS`` macro defined: + Needs a special build of Python with the ``Py_TRACE_REFS`` macro defined: see the :option:`configure --with-trace-refs option <--with-trace-refs>`. Default: ``0``. @@ -874,6 +888,19 @@ PyConfig .. versionadded:: 3.12 + .. c:member:: int cpu_count + + If the value of :c:member:`~PyConfig.cpu_count` is not ``-1`` then it will + override the return values of :func:`os.cpu_count`, + :func:`os.process_cpu_count`, and :func:`multiprocessing.cpu_count`. + + Configured by the :samp:`-X cpu_count={n|default}` command line + flag or the :envvar:`PYTHON_CPU_COUNT` environment variable. + + Default: ``-1``. + + .. versionadded:: 3.13 + .. c:member:: int isolated If greater than ``0``, enable isolated mode: @@ -1031,7 +1058,7 @@ PyConfig Incremented by the :option:`-d` command line option. Set to the :envvar:`PYTHONDEBUG` environment variable value. - Need a :ref:`debug build of Python ` (the ``Py_DEBUG`` macro + Needs a :ref:`debug build of Python ` (the ``Py_DEBUG`` macro must be defined). Default: ``0``. @@ -1083,6 +1110,7 @@ PyConfig Set by the :option:`-X pycache_prefix=PATH <-X>` command line option and the :envvar:`PYTHONPYCACHEPREFIX` environment variable. + The command-line option takes precedence. If ``NULL``, :data:`sys.pycache_prefix` is set to ``None``. @@ -1126,13 +1154,27 @@ PyConfig Default: ``NULL``. + .. c:member:: wchar_t* run_presite + + ``package.module`` path to module that should be imported before + ``site.py`` is run. + + Set by the :option:`-X presite=package.module <-X>` command-line + option and the :envvar:`PYTHON_PRESITE` environment variable. + The command-line option takes precedence. + + Needs a :ref:`debug build of Python ` (the ``Py_DEBUG`` macro + must be defined). + + Default: ``NULL``. + .. c:member:: int show_ref_count - Show total reference count at exit? + Show total reference count at exit (excluding :term:`immortal` objects)? Set to ``1`` by :option:`-X showrefcount <-X>` command line option. - Need a :ref:`debug build of Python ` (the ``Py_REF_DEBUG`` + Needs a :ref:`debug build of Python ` (the ``Py_REF_DEBUG`` macro must be defined). Default: ``0``. diff --git a/Doc/c-api/intro.rst b/Doc/c-api/intro.rst index 1739eabd2a3039..4dbca92b18b5cd 100644 --- a/Doc/c-api/intro.rst +++ b/Doc/c-api/intro.rst @@ -105,6 +105,30 @@ defined closer to where they are useful (e.g. :c:macro:`Py_RETURN_NONE`). Others of a more general utility are defined here. This is not necessarily a complete listing. +.. c:macro:: PyMODINIT_FUNC + + Declare an extension module ``PyInit`` initialization function. The function + return type is :c:expr:`PyObject*`. The macro declares any special linkage + declarations required by the platform, and for C++ declares the function as + ``extern "C"``. + + The initialization function must be named :samp:`PyInit_{name}`, where + *name* is the name of the module, and should be the only non-\ ``static`` + item defined in the module file. Example:: + + static struct PyModuleDef spam_module = { + PyModuleDef_HEAD_INIT, + .m_name = "spam", + ... + }; + + PyMODINIT_FUNC + PyInit_spam(void) + { + return PyModule_Create(&spam_module); + } + + .. c:macro:: Py_ABS(x) Return the absolute value of ``x``. @@ -287,52 +311,58 @@ true if (and only if) the object pointed to by *a* is a Python list. Reference Counts ---------------- -The reference count is important because today's computers have a finite (and -often severely limited) memory size; it counts how many different places there -are that have a reference to an object. Such a place could be another object, -or a global (or static) C variable, or a local variable in some C function. -When an object's reference count becomes zero, the object is deallocated. If -it contains references to other objects, their reference count is decremented. -Those other objects may be deallocated in turn, if this decrement makes their -reference count become zero, and so on. (There's an obvious problem with -objects that reference each other here; for now, the solution is "don't do -that.") +The reference count is important because today's computers have a finite +(and often severely limited) memory size; it counts how many different +places there are that have a :term:`strong reference` to an object. +Such a place could be another object, or a global (or static) C variable, +or a local variable in some C function. +When the last :term:`strong reference` to an object is released +(i.e. its reference count becomes zero), the object is deallocated. +If it contains references to other objects, those references are released. +Those other objects may be deallocated in turn, if there are no more +references to them, and so on. (There's an obvious problem with +objects that reference each other here; for now, the solution +is "don't do that.") .. index:: single: Py_INCREF() single: Py_DECREF() -Reference counts are always manipulated explicitly. The normal way is to use -the macro :c:func:`Py_INCREF` to increment an object's reference count by one, -and :c:func:`Py_DECREF` to decrement it by one. The :c:func:`Py_DECREF` macro +Reference counts are always manipulated explicitly. The normal way is +to use the macro :c:func:`Py_INCREF` to take a new reference to an +object (i.e. increment its reference count by one), +and :c:func:`Py_DECREF` to release that reference (i.e. decrement the +reference count by one). The :c:func:`Py_DECREF` macro is considerably more complex than the incref one, since it must check whether the reference count becomes zero and then cause the object's deallocator to be -called. The deallocator is a function pointer contained in the object's type -structure. The type-specific deallocator takes care of decrementing the -reference counts for other objects contained in the object if this is a compound +called. The deallocator is a function pointer contained in the object's type +structure. The type-specific deallocator takes care of releasing references +for other objects contained in the object if this is a compound object type, such as a list, as well as performing any additional finalization that's needed. There's no chance that the reference count can overflow; at least as many bits are used to hold the reference count as there are distinct memory locations in virtual memory (assuming ``sizeof(Py_ssize_t) >= sizeof(void*)``). Thus, the reference count increment is a simple operation. -It is not necessary to increment an object's reference count for every local -variable that contains a pointer to an object. In theory, the object's +It is not necessary to hold a :term:`strong reference` (i.e. increment +the reference count) for every local variable that contains a pointer +to an object. In theory, the object's reference count goes up by one when the variable is made to point to it and it goes down by one when the variable goes out of scope. However, these two cancel each other out, so at the end the reference count hasn't changed. The only real reason to use the reference count is to prevent the object from being deallocated as long as our variable is pointing to it. If we know that there is at least one other reference to the object that lives at least as long as -our variable, there is no need to increment the reference count temporarily. +our variable, there is no need to take a new :term:`strong reference` +(i.e. increment the reference count) temporarily. An important situation where this arises is in objects that are passed as arguments to C functions in an extension module that are called from Python; the call mechanism guarantees to hold a reference to every argument for the duration of the call. However, a common pitfall is to extract an object from a list and hold on to it -for a while without incrementing its reference count. Some other operation might -conceivably remove the object from the list, decrementing its reference count +for a while without taking a new reference. Some other operation might +conceivably remove the object from the list, releasing that reference, and possibly deallocating it. The real danger is that innocent-looking operations may invoke arbitrary Python code which could do this; there is a code path which allows control to flow back to the user from a :c:func:`Py_DECREF`, so @@ -340,7 +370,8 @@ almost any operation is potentially dangerous. A safe approach is to always use the generic operations (functions whose name begins with ``PyObject_``, ``PyNumber_``, ``PySequence_`` or ``PyMapping_``). -These operations always increment the reference count of the object they return. +These operations always create a new :term:`strong reference` +(i.e. increment the reference count) of the object they return. This leaves the caller with the responsibility to call :c:func:`Py_DECREF` when they are done with the result; this soon becomes second nature. @@ -356,7 +387,7 @@ to objects (objects are not owned: they are always shared). "Owning a reference" means being responsible for calling Py_DECREF on it when the reference is no longer needed. Ownership can also be transferred, meaning that the code that receives ownership of the reference then becomes responsible for -eventually decref'ing it by calling :c:func:`Py_DECREF` or :c:func:`Py_XDECREF` +eventually releasing it by calling :c:func:`Py_DECREF` or :c:func:`Py_XDECREF` when it's no longer needed---or passing on this responsibility (usually to its caller). When a function passes ownership of a reference on to its caller, the caller is said to receive a *new* reference. When no ownership is transferred, @@ -414,9 +445,9 @@ For example, the above two blocks of code could be replaced by the following It is much more common to use :c:func:`PyObject_SetItem` and friends with items whose references you are only borrowing, like arguments that were passed in to -the function you are writing. In that case, their behaviour regarding reference -counts is much saner, since you don't have to increment a reference count so you -can give a reference away ("have it be stolen"). For example, this function +the function you are writing. In that case, their behaviour regarding references +is much saner, since you don't have to take a new reference just so you +can give that reference away ("have it be stolen"). For example, this function sets all items of a list (actually, any mutable sequence) to a given item:: int diff --git a/Doc/c-api/list.rst b/Doc/c-api/list.rst index c15cecd41b89d1..c8b64bad702f50 100644 --- a/Doc/c-api/list.rst +++ b/Doc/c-api/list.rst @@ -128,6 +128,30 @@ List Objects list is not supported. +.. c:function:: int PyList_Extend(PyObject *list, PyObject *iterable) + + Extend *list* with the contents of *iterable*. This is the same as + ``PyList_SetSlice(list, PY_SSIZE_T_MAX, PY_SSIZE_T_MAX, iterable)`` + and analogous to ``list.extend(iterable)`` or ``list += iterable``. + + Raise an exception and return ``-1`` if *list* is not a :class:`list` + object. Return 0 on success. + + .. versionadded:: 3.13 + + +.. c:function:: int PyList_Clear(PyObject *list) + + Remove all items from *list*. This is the same as + ``PyList_SetSlice(list, 0, PY_SSIZE_T_MAX, NULL)`` and analogous to + ``list.clear()`` or ``del list[:]``. + + Raise an exception and return ``-1`` if *list* is not a :class:`list` + object. Return 0 on success. + + .. versionadded:: 3.13 + + .. c:function:: int PyList_Sort(PyObject *list) Sort the items of *list* in place. Return ``0`` on success, ``-1`` on diff --git a/Doc/c-api/long.rst b/Doc/c-api/long.rst index f1354a34f2b2d5..045604870d3c84 100644 --- a/Doc/c-api/long.rst +++ b/Doc/c-api/long.rst @@ -136,6 +136,14 @@ distinguished from a number. Use :c:func:`PyErr_Occurred` to disambiguate. This function will no longer use :meth:`~object.__int__`. +.. c:function:: int PyLong_AsInt(PyObject *obj) + + Similar to :c:func:`PyLong_AsLong`, but store the result in a C + :c:expr:`int` instead of a C :c:expr:`long`. + + .. versionadded:: 3.13 + + .. c:function:: long PyLong_AsLongAndOverflow(PyObject *obj, int *overflow) Return a C :c:expr:`long` representation of *obj*. If *obj* is not an diff --git a/Doc/c-api/mapping.rst b/Doc/c-api/mapping.rst index 82011d9d36a524..1f55c0aa955c75 100644 --- a/Doc/c-api/mapping.rst +++ b/Doc/c-api/mapping.rst @@ -28,9 +28,9 @@ See also :c:func:`PyObject_GetItem`, :c:func:`PyObject_SetItem` and .. c:function:: PyObject* PyMapping_GetItemString(PyObject *o, const char *key) - Return element of *o* corresponding to the string *key* or ``NULL`` on failure. - This is the equivalent of the Python expression ``o[key]``. - See also :c:func:`PyObject_GetItem`. + This is the same as :c:func:`PyObject_GetItem`, but *key* is + specified as a :c:expr:`const char*` UTF-8 encoded bytes string, + rather than a :c:expr:`PyObject*`. .. c:function:: int PyMapping_GetOptionalItem(PyObject *obj, PyObject *key, PyObject **result) @@ -50,60 +50,78 @@ See also :c:func:`PyObject_GetItem`, :c:func:`PyObject_SetItem` and .. c:function:: int PyMapping_GetOptionalItemString(PyObject *obj, const char *key, PyObject **result) - Variant of :c:func:`PyMapping_GetItemString` which doesn't raise - :exc:`KeyError` if the key is not found. - - If the key is found, return ``1`` and set *\*result* to a new - :term:`strong reference` to the corresponding value. - If the key is not found, return ``0`` and set *\*result* to ``NULL``; - the :exc:`KeyError` is silenced. - If an error other than :exc:`KeyError` is raised, return ``-1`` and - set *\*result* to ``NULL``. + This is the same as :c:func:`PyMapping_GetOptionalItem`, but *key* is + specified as a :c:expr:`const char*` UTF-8 encoded bytes string, + rather than a :c:expr:`PyObject*`. .. versionadded:: 3.13 .. c:function:: int PyMapping_SetItemString(PyObject *o, const char *key, PyObject *v) - Map the string *key* to the value *v* in object *o*. Returns ``-1`` on - failure. This is the equivalent of the Python statement ``o[key] = v``. - See also :c:func:`PyObject_SetItem`. This function *does not* steal a - reference to *v*. + This is the same as :c:func:`PyObject_SetItem`, but *key* is + specified as a :c:expr:`const char*` UTF-8 encoded bytes string, + rather than a :c:expr:`PyObject*`. .. c:function:: int PyMapping_DelItem(PyObject *o, PyObject *key) - Remove the mapping for the object *key* from the object *o*. Return ``-1`` - on failure. This is equivalent to the Python statement ``del o[key]``. This is an alias of :c:func:`PyObject_DelItem`. .. c:function:: int PyMapping_DelItemString(PyObject *o, const char *key) - Remove the mapping for the string *key* from the object *o*. Return ``-1`` - on failure. This is equivalent to the Python statement ``del o[key]``. + This is the same as :c:func:`PyObject_DelItem`, but *key* is + specified as a :c:expr:`const char*` UTF-8 encoded bytes string, + rather than a :c:expr:`PyObject*`. -.. c:function:: int PyMapping_HasKey(PyObject *o, PyObject *key) +.. c:function:: int PyMapping_HasKeyWithError(PyObject *o, PyObject *key) Return ``1`` if the mapping object has the key *key* and ``0`` otherwise. This is equivalent to the Python expression ``key in o``. - This function always succeeds. + On failure, return ``-1``. - Note that exceptions which occur while calling the :meth:`~object.__getitem__` - method will get suppressed. - To get error reporting use :c:func:`PyObject_GetItem()` instead. + .. versionadded:: 3.13 -.. c:function:: int PyMapping_HasKeyString(PyObject *o, const char *key) +.. c:function:: int PyMapping_HasKeyStringWithError(PyObject *o, const char *key) + + This is the same as :c:func:`PyMapping_HasKeyWithError`, but *key* is + specified as a :c:expr:`const char*` UTF-8 encoded bytes string, + rather than a :c:expr:`PyObject*`. + + .. versionadded:: 3.13 + + +.. c:function:: int PyMapping_HasKey(PyObject *o, PyObject *key) Return ``1`` if the mapping object has the key *key* and ``0`` otherwise. This is equivalent to the Python expression ``key in o``. This function always succeeds. - Note that exceptions which occur while calling the :meth:`~object.__getitem__` - method and creating a temporary string object will get suppressed. - To get error reporting use :c:func:`PyMapping_GetItemString()` instead. + .. note:: + + Exceptions which occur when this calls :meth:`~object.__getitem__` + method are silently ignored. + For proper error handling, use :c:func:`PyMapping_HasKeyWithError`, + :c:func:`PyMapping_GetOptionalItem` or :c:func:`PyObject_GetItem()` instead. + + +.. c:function:: int PyMapping_HasKeyString(PyObject *o, const char *key) + + This is the same as :c:func:`PyMapping_HasKey`, but *key* is + specified as a :c:expr:`const char*` UTF-8 encoded bytes string, + rather than a :c:expr:`PyObject*`. + + .. note:: + + Exceptions that occur when this calls :meth:`~object.__getitem__` + method or while creating the temporary :class:`str` + object are silently ignored. + For proper error handling, use :c:func:`PyMapping_HasKeyStringWithError`, + :c:func:`PyMapping_GetOptionalItemString` or + :c:func:`PyMapping_GetItemString` instead. .. c:function:: PyObject* PyMapping_Keys(PyObject *o) diff --git a/Doc/c-api/memory.rst b/Doc/c-api/memory.rst index 1df8c2b911ca8f..1f392e55078e77 100644 --- a/Doc/c-api/memory.rst +++ b/Doc/c-api/memory.rst @@ -391,6 +391,8 @@ Legend: * ``malloc``: system allocators from the standard C library, C functions: :c:func:`malloc`, :c:func:`calloc`, :c:func:`realloc` and :c:func:`free`. * ``pymalloc``: :ref:`pymalloc memory allocator `. +* ``mimalloc``: :ref:`mimalloc memory allocator `. The pymalloc + allocator will be used if mimalloc support isn't available. * "+ debug": with :ref:`debug hooks on the Python memory allocators `. * "Debug build": :ref:`Python build in debug mode `. @@ -491,18 +493,18 @@ Customize Memory Allocators :c:func:`PyMem_SetAllocator` does have the following contract: - * It can be called after :c:func:`Py_PreInitialize` and before - :c:func:`Py_InitializeFromConfig` to install a custom memory - allocator. There are no restrictions over the installed allocator - other than the ones imposed by the domain (for instance, the Raw - Domain allows the allocator to be called without the GIL held). See - :ref:`the section on allocator domains ` for more - information. + * It can be called after :c:func:`Py_PreInitialize` and before + :c:func:`Py_InitializeFromConfig` to install a custom memory + allocator. There are no restrictions over the installed allocator + other than the ones imposed by the domain (for instance, the Raw + Domain allows the allocator to be called without the GIL held). See + :ref:`the section on allocator domains ` for more + information. - * If called after Python has finish initializing (after - :c:func:`Py_InitializeFromConfig` has been called) the allocator - **must** wrap the existing allocator. Substituting the current - allocator for some other arbitrary one is **not supported**. + * If called after Python has finish initializing (after + :c:func:`Py_InitializeFromConfig` has been called) the allocator + **must** wrap the existing allocator. Substituting the current + allocator for some other arbitrary one is **not supported**. .. versionchanged:: 3.12 All allocators must be thread-safe. @@ -626,7 +628,8 @@ The pymalloc allocator Python has a *pymalloc* allocator optimized for small objects (smaller or equal to 512 bytes) with a short lifetime. It uses memory mappings called "arenas" -with a fixed size of 256 KiB. It falls back to :c:func:`PyMem_RawMalloc` and +with a fixed size of either 256 KiB on 32-bit platforms or 1 MiB on 64-bit +platforms. It falls back to :c:func:`PyMem_RawMalloc` and :c:func:`PyMem_RawRealloc` for allocations larger than 512 bytes. *pymalloc* is the :ref:`default allocator ` of the @@ -671,6 +674,16 @@ Customize pymalloc Arena Allocator Set the arena allocator. +.. _mimalloc: + +The mimalloc allocator +====================== + +.. versionadded:: 3.13 + +Python supports the mimalloc allocator when the underlying platform support is available. +mimalloc "is a general purpose allocator with excellent performance characteristics. +Initially developed by Daan Leijen for the runtime systems of the Koka and Lean languages." tracemalloc C API ================= diff --git a/Doc/c-api/module.rst b/Doc/c-api/module.rst index e37505f6450a30..979b22261efa3b 100644 --- a/Doc/c-api/module.rst +++ b/Doc/c-api/module.rst @@ -338,6 +338,7 @@ The available slot types are: The *value* pointer of this slot must point to a function of the signature: .. c:function:: PyObject* create_module(PyObject *spec, PyModuleDef *def) + :noindex: The function receives a :py:class:`~importlib.machinery.ModuleSpec` instance, as defined in :PEP:`451`, and the module definition. @@ -372,6 +373,7 @@ The available slot types are: The signature of the function is: .. c:function:: int exec_module(PyObject* module) + :noindex: If multiple ``Py_mod_exec`` slots are specified, they are processed in the order they appear in the *m_slots* array. @@ -380,6 +382,8 @@ The available slot types are: Specifies one of the following values: + .. c:namespace:: NULL + .. c:macro:: Py_MOD_MULTIPLE_INTERPRETERS_NOT_SUPPORTED The module does not support being imported in subinterpreters. @@ -546,7 +550,7 @@ state: .. note:: Unlike other functions that steal references, ``PyModule_AddObject()`` - only decrements the reference count of *value* **on success**. + only releases the reference to *value* **on success**. This means that its return value must be checked, and calling code must :c:func:`Py_XDECREF` *value* manually on error. diff --git a/Doc/c-api/none.rst b/Doc/c-api/none.rst index dd8bfb56104251..f1941fc4bc4e85 100644 --- a/Doc/c-api/none.rst +++ b/Doc/c-api/none.rst @@ -16,10 +16,10 @@ same reason. .. c:var:: PyObject* Py_None The Python ``None`` object, denoting lack of value. This object has no methods - and is `immortal `_. + and is :term:`immortal`. -.. versionchanged:: 3.12 - :c:data:`Py_None` is immortal. + .. versionchanged:: 3.12 + :c:data:`Py_None` is :term:`immortal`. .. c:macro:: Py_RETURN_NONE diff --git a/Doc/c-api/object.rst b/Doc/c-api/object.rst index 1b7e05e7c53eda..8a179690d048e3 100644 --- a/Doc/c-api/object.rst +++ b/Doc/c-api/object.rst @@ -15,8 +15,8 @@ Object Protocol .. c:macro:: Py_RETURN_NOTIMPLEMENTED Properly handle returning :c:data:`Py_NotImplemented` from within a C - function (that is, increment the reference count of NotImplemented and - return it). + function (that is, create a new :term:`strong reference` + to NotImplemented and return it). .. c:function:: int PyObject_Print(PyObject *o, FILE *fp, int flags) @@ -27,32 +27,50 @@ Object Protocol instead of the :func:`repr`. +.. c:function:: int PyObject_HasAttrWithError(PyObject *o, const char *attr_name) + + Returns ``1`` if *o* has the attribute *attr_name*, and ``0`` otherwise. + This is equivalent to the Python expression ``hasattr(o, attr_name)``. + On failure, return ``-1``. + + .. versionadded:: 3.13 + + +.. c:function:: int PyObject_HasAttrStringWithError(PyObject *o, const char *attr_name) + + This is the same as :c:func:`PyObject_HasAttrWithError`, but *attr_name* is + specified as a :c:expr:`const char*` UTF-8 encoded bytes string, + rather than a :c:expr:`PyObject*`. + + .. versionadded:: 3.13 + + .. c:function:: int PyObject_HasAttr(PyObject *o, PyObject *attr_name) - Returns ``1`` if *o* has the attribute *attr_name*, and ``0`` otherwise. This - is equivalent to the Python expression ``hasattr(o, attr_name)``. This function - always succeeds. + Returns ``1`` if *o* has the attribute *attr_name*, and ``0`` otherwise. + This function always succeeds. .. note:: Exceptions that occur when this calls :meth:`~object.__getattr__` and :meth:`~object.__getattribute__` methods are silently ignored. - For proper error handling, use :c:func:`PyObject_GetOptionalAttr` or - :c:func:`PyObject_GetAttr` instead. + For proper error handling, use :c:func:`PyObject_HasAttrWithError`, + :c:func:`PyObject_GetOptionalAttr` or :c:func:`PyObject_GetAttr` instead. .. c:function:: int PyObject_HasAttrString(PyObject *o, const char *attr_name) - Returns ``1`` if *o* has the attribute *attr_name*, and ``0`` otherwise. This - is equivalent to the Python expression ``hasattr(o, attr_name)``. This function - always succeeds. + This is the same as :c:func:`PyObject_HasAttr`, but *attr_name* is + specified as a :c:expr:`const char*` UTF-8 encoded bytes string, + rather than a :c:expr:`PyObject*`. .. note:: Exceptions that occur when this calls :meth:`~object.__getattr__` and - :meth:`~object.__getattribute__` methods or while creating the temporary :class:`str` - object are silently ignored. - For proper error handling, use :c:func:`PyObject_GetOptionalAttrString` + :meth:`~object.__getattribute__` methods or while creating the temporary + :class:`str` object are silently ignored. + For proper error handling, use :c:func:`PyObject_HasAttrStringWithError`, + :c:func:`PyObject_GetOptionalAttrString` or :c:func:`PyObject_GetAttrString` instead. @@ -68,9 +86,9 @@ Object Protocol .. c:function:: PyObject* PyObject_GetAttrString(PyObject *o, const char *attr_name) - Retrieve an attribute named *attr_name* from object *o*. Returns the attribute - value on success, or ``NULL`` on failure. This is the equivalent of the Python - expression ``o.attr_name``. + This is the same as :c:func:`PyObject_GetAttr`, but *attr_name* is + specified as a :c:expr:`const char*` UTF-8 encoded bytes string, + rather than a :c:expr:`PyObject*`. If the missing attribute should not be treated as a failure, you can use :c:func:`PyObject_GetOptionalAttrString` instead. @@ -93,15 +111,9 @@ Object Protocol .. c:function:: int PyObject_GetOptionalAttrString(PyObject *obj, const char *attr_name, PyObject **result); - Variant of :c:func:`PyObject_GetAttrString` which doesn't raise - :exc:`AttributeError` if the attribute is not found. - - If the attribute is found, return ``1`` and set *\*result* to a new - :term:`strong reference` to the attribute. - If the attribute is not found, return ``0`` and set *\*result* to ``NULL``; - the :exc:`AttributeError` is silenced. - If an error other than :exc:`AttributeError` is raised, return ``-1`` and - set *\*result* to ``NULL``. + This is the same as :c:func:`PyObject_GetOptionalAttr`, but *attr_name* is + specified as a :c:expr:`const char*` UTF-8 encoded bytes string, + rather than a :c:expr:`PyObject*`. .. versionadded:: 3.13 @@ -129,10 +141,9 @@ Object Protocol .. c:function:: int PyObject_SetAttrString(PyObject *o, const char *attr_name, PyObject *v) - Set the value of the attribute named *attr_name*, for object *o*, to the value - *v*. Raise an exception and return ``-1`` on failure; - return ``0`` on success. This is the equivalent of the Python statement - ``o.attr_name = v``. + This is the same as :c:func:`PyObject_SetAttr`, but *attr_name* is + specified as a :c:expr:`const char*` UTF-8 encoded bytes string, + rather than a :c:expr:`PyObject*`. If *v* is ``NULL``, the attribute is deleted, but this feature is deprecated in favour of using :c:func:`PyObject_DelAttrString`. @@ -158,8 +169,9 @@ Object Protocol .. c:function:: int PyObject_DelAttrString(PyObject *o, const char *attr_name) - Delete attribute named *attr_name*, for object *o*. Returns ``-1`` on failure. - This is the equivalent of the Python statement ``del o.attr_name``. + This is the same as :c:func:`PyObject_DelAttr`, but *attr_name* is + specified as a :c:expr:`const char*` UTF-8 encoded bytes string, + rather than a :c:expr:`PyObject*`. .. c:function:: PyObject* PyObject_GenericGetDict(PyObject *o, void *context) @@ -357,11 +369,12 @@ Object Protocol When *o* is non-``NULL``, returns a type object corresponding to the object type of object *o*. On failure, raises :exc:`SystemError` and returns ``NULL``. This - is equivalent to the Python expression ``type(o)``. This function increments the - reference count of the return value. There's really no reason to use this + is equivalent to the Python expression ``type(o)``. + This function creates a new :term:`strong reference` to the return value. + There's really no reason to use this function instead of the :c:func:`Py_TYPE()` function, which returns a - pointer of type :c:expr:`PyTypeObject*`, except when the incremented reference - count is needed. + pointer of type :c:expr:`PyTypeObject*`, except when a new + :term:`strong reference` is needed. .. c:function:: int PyObject_TypeCheck(PyObject *o, PyTypeObject *type) @@ -475,3 +488,21 @@ Object Protocol :c:macro:`Py_TPFLAGS_ITEMS_AT_END` set. .. versionadded:: 3.12 + +.. c:function:: int PyObject_VisitManagedDict(PyObject *obj, visitproc visit, void *arg) + + Visit the managed dictionary of *obj*. + + This function must only be called in a traverse function of the type which + has the :c:macro:`Py_TPFLAGS_MANAGED_DICT` flag set. + + .. versionadded:: 3.13 + +.. c:function:: void PyObject_ClearManagedDict(PyObject *obj) + + Clear the managed dictionary of *obj*. + + This function must only be called in a traverse function of the type which + has the :c:macro:`Py_TPFLAGS_MANAGED_DICT` flag set. + + .. versionadded:: 3.13 diff --git a/Doc/c-api/refcounting.rst b/Doc/c-api/refcounting.rst index 640c5c610899f8..75e1d46474f1e7 100644 --- a/Doc/c-api/refcounting.rst +++ b/Doc/c-api/refcounting.rst @@ -15,6 +15,12 @@ of Python objects. Get the reference count of the Python object *o*. + Note that the returned value may not actually reflect how many + references to the object are actually held. For example, some + objects are :term:`immortal` and have a very high refcount that does not + reflect the actual number of references. Consequently, do not rely + on the returned value to be accurate, other than a value of 0 or 1. + Use the :c:func:`Py_SET_REFCNT()` function to set an object reference count. .. versionchanged:: 3.11 @@ -28,36 +34,56 @@ of Python objects. Set the object *o* reference counter to *refcnt*. + On :ref:`Python build with Free Threading `, if + *refcnt* is larger than ``UINT32_MAX``, the object is made :term:`immortal`. + + This function has no effect on :term:`immortal` objects. + .. versionadded:: 3.9 + .. versionchanged:: 3.12 + Immortal objects are not modified. + .. c:function:: void Py_INCREF(PyObject *o) - Increment the reference count for object *o*. + Indicate taking a new :term:`strong reference` to object *o*, + indicating it is in use and should not be destroyed. + + This function has no effect on :term:`immortal` objects. This function is usually used to convert a :term:`borrowed reference` to a :term:`strong reference` in-place. The :c:func:`Py_NewRef` function can be used to create a new :term:`strong reference`. + When done using the object, release is by calling :c:func:`Py_DECREF`. + The object must not be ``NULL``; if you aren't sure that it isn't ``NULL``, use :c:func:`Py_XINCREF`. + Do not expect this function to actually modify *o* in any way. + For at least `some objects `_, + this function has no effect. + + .. versionchanged:: 3.12 + Immortal objects are not modified. + .. c:function:: void Py_XINCREF(PyObject *o) - Increment the reference count for object *o*. The object may be ``NULL``, in - which case the macro has no effect. + Similar to :c:func:`Py_INCREF`, but the object *o* can be ``NULL``, + in which case this has no effect. See also :c:func:`Py_XNewRef`. .. c:function:: PyObject* Py_NewRef(PyObject *o) - Create a new :term:`strong reference` to an object: increment the reference - count of the object *o* and return the object *o*. + Create a new :term:`strong reference` to an object: + call :c:func:`Py_INCREF` on *o* and return the object *o*. When the :term:`strong reference` is no longer needed, :c:func:`Py_DECREF` - should be called on it to decrement the object reference count. + should be called on it to release the reference. The object *o* must not be ``NULL``; use :c:func:`Py_XNewRef` if *o* can be ``NULL``. @@ -87,9 +113,14 @@ of Python objects. .. c:function:: void Py_DECREF(PyObject *o) - Decrement the reference count for object *o*. + Release a :term:`strong reference` to object *o*, indicating the + reference is no longer used. - If the reference count reaches zero, the object's type's deallocation + This function has no effect on :term:`immortal` objects. + + Once the last :term:`strong reference` is released + (i.e. the object's reference count reaches 0), + the object's type's deallocation function (which must not be ``NULL``) is invoked. This function is usually used to delete a :term:`strong reference` before @@ -98,6 +129,10 @@ of Python objects. The object must not be ``NULL``; if you aren't sure that it isn't ``NULL``, use :c:func:`Py_XDECREF`. + Do not expect this function to actually modify *o* in any way. + For at least `some objects `_, + this function has no effect. + .. warning:: The deallocation function can cause arbitrary Python code to be invoked (e.g. @@ -109,25 +144,29 @@ of Python objects. reference to the deleted object in a temporary variable, update the list data structure, and then call :c:func:`Py_DECREF` for the temporary variable. + .. versionchanged:: 3.12 + Immortal objects are not modified. + .. c:function:: void Py_XDECREF(PyObject *o) - Decrement the reference count for object *o*. The object may be ``NULL``, in - which case the macro has no effect; otherwise the effect is the same as for - :c:func:`Py_DECREF`, and the same warning applies. + Similar to :c:func:`Py_DECREF`, but the object *o* can be ``NULL``, + in which case this has no effect. + The same warning from :c:func:`Py_DECREF` applies here as well. .. c:function:: void Py_CLEAR(PyObject *o) - Decrement the reference count for object *o*. The object may be ``NULL``, in + Release a :term:`strong reference` for object *o*. + The object may be ``NULL``, in which case the macro has no effect; otherwise the effect is the same as for :c:func:`Py_DECREF`, except that the argument is also set to ``NULL``. The warning for :c:func:`Py_DECREF` does not apply with respect to the object passed because the macro carefully uses a temporary variable and sets the argument to ``NULL`` - before decrementing its reference count. + before releasing the reference. - It is a good idea to use this macro whenever decrementing the reference - count of an object that might be traversed during garbage collection. + It is a good idea to use this macro whenever releasing a reference + to an object that might be traversed during garbage collection. .. versionchanged:: 3.12 The macro argument is now only evaluated once. If the argument has side @@ -136,20 +175,22 @@ of Python objects. .. c:function:: void Py_IncRef(PyObject *o) - Increment the reference count for object *o*. A function version of :c:func:`Py_XINCREF`. + Indicate taking a new :term:`strong reference` to object *o*. + A function version of :c:func:`Py_XINCREF`. It can be used for runtime dynamic embedding of Python. .. c:function:: void Py_DecRef(PyObject *o) - Decrement the reference count for object *o*. A function version of :c:func:`Py_XDECREF`. + Release a :term:`strong reference` to object *o*. + A function version of :c:func:`Py_XDECREF`. It can be used for runtime dynamic embedding of Python. .. c:macro:: Py_SETREF(dst, src) - Macro safely decrementing the `dst` reference count and setting `dst` to - `src`. + Macro safely releasing a :term:`strong reference` to object *dst* + and setting *dst* to *src*. As in case of :c:func:`Py_CLEAR`, "the obvious" code can be deadly:: @@ -160,9 +201,10 @@ of Python objects. Py_SETREF(dst, src); - That arranges to set `dst` to `src` _before_ decrementing reference count of - *dst* old value, so that any code triggered as a side-effect of `dst` - getting torn down no longer believes `dst` points to a valid object. + That arranges to set *dst* to *src* _before_ releasing the reference + to the old value of *dst*, so that any code triggered as a side-effect + of *dst* getting torn down no longer believes *dst* points + to a valid object. .. versionadded:: 3.6 diff --git a/Doc/c-api/set.rst b/Doc/c-api/set.rst index 1e8a09509032f5..cba823aa027bd6 100644 --- a/Doc/c-api/set.rst +++ b/Doc/c-api/set.rst @@ -147,7 +147,7 @@ subtypes but not for instances of :class:`frozenset` or its subtypes. Return ``1`` if found and removed, ``0`` if not found (no action taken), and ``-1`` if an error is encountered. Does not raise :exc:`KeyError` for missing keys. Raise a - :exc:`TypeError` if the *key* is unhashable. Unlike the Python :meth:`~set.discard` + :exc:`TypeError` if the *key* is unhashable. Unlike the Python :meth:`~frozenset.discard` method, this function does not automatically convert unhashable sets into temporary frozensets. Raise :exc:`SystemError` if *set* is not an instance of :class:`set` or its subtype. @@ -163,4 +163,6 @@ subtypes but not for instances of :class:`frozenset` or its subtypes. .. c:function:: int PySet_Clear(PyObject *set) - Empty an existing set of all elements. + Empty an existing set of all elements. Return ``0`` on + success. Return ``-1`` and raise :exc:`SystemError` if *set* is not an instance of + :class:`set` or its subtype. diff --git a/Doc/c-api/slice.rst b/Doc/c-api/slice.rst index 9e880c6b7f25ad..27a1757c745d8b 100644 --- a/Doc/c-api/slice.rst +++ b/Doc/c-api/slice.rst @@ -119,8 +119,7 @@ Ellipsis Object .. c:var:: PyObject *Py_Ellipsis The Python ``Ellipsis`` object. This object has no methods. Like - :c:data:`Py_None`, it is an `immortal `_. - singleton object. + :c:data:`Py_None`, it is an :term:`immortal` singleton object. .. versionchanged:: 3.12 :c:data:`Py_Ellipsis` is immortal. diff --git a/Doc/c-api/stable.rst b/Doc/c-api/stable.rst index c66b296d304adc..63a100a6f26f24 100644 --- a/Doc/c-api/stable.rst +++ b/Doc/c-api/stable.rst @@ -18,7 +18,7 @@ way; see :ref:`stable-abi-platform` below). So, code compiled for Python 3.10.0 will work on 3.10.8 and vice versa, but will need to be compiled separately for 3.9.x and 3.10.x. -There are two tiers of C API with different stability exepectations: +There are two tiers of C API with different stability expectations: - :ref:`Unstable API `, may change in minor versions without a deprecation period. It is marked by the ``PyUnstable`` prefix in names. diff --git a/Doc/c-api/structures.rst b/Doc/c-api/structures.rst index 747cfa62294c21..7d82f7839dfcd7 100644 --- a/Doc/c-api/structures.rst +++ b/Doc/c-api/structures.rst @@ -406,7 +406,11 @@ Accessing attributes of extension types .. c:type:: PyMemberDef Structure which describes an attribute of a type which corresponds to a C - struct member. Its fields are, in order: + struct member. + When defining a class, put a NULL-terminated array of these + structures in the :c:member:`~PyTypeObject.tp_members` slot. + + Its fields are, in order: .. c:member:: const char* name @@ -415,15 +419,15 @@ Accessing attributes of extension types The string should be static, no copy is made of it. - .. c:member:: Py_ssize_t offset - - The offset in bytes that the member is located on the type’s object struct. - .. c:member:: int type The type of the member in the C struct. See :ref:`PyMemberDef-types` for the possible values. + .. c:member:: Py_ssize_t offset + + The offset in bytes that the member is located on the type’s object struct. + .. c:member:: int flags Zero or more of the :ref:`PyMemberDef-flags`, combined using bitwise OR. @@ -588,7 +592,7 @@ Macro name C type Python type (*): Zero-terminated, UTF8-encoded C string. With :c:macro:`!Py_T_STRING` the C representation is a pointer; - with :c:macro:`!Py_T_STRING_INLINE` the string is stored directly + with :c:macro:`!Py_T_STRING_INPLACE` the string is stored directly in the structure. (**): String of length 1. Only ASCII is accepted. diff --git a/Doc/c-api/sys.rst b/Doc/c-api/sys.rst index 5457d17159f8d3..e3c54b075114ff 100644 --- a/Doc/c-api/sys.rst +++ b/Doc/c-api/sys.rst @@ -8,8 +8,9 @@ Operating System Utilities .. c:function:: PyObject* PyOS_FSPath(PyObject *path) Return the file system representation for *path*. If the object is a - :class:`str` or :class:`bytes` object, then its reference count is - incremented. If the object implements the :class:`os.PathLike` interface, + :class:`str` or :class:`bytes` object, then a new + :term:`strong reference` is returned. + If the object implements the :class:`os.PathLike` interface, then :meth:`~os.PathLike.__fspath__` is returned as long as it is a :class:`str` or :class:`bytes` object. Otherwise :exc:`TypeError` is raised and ``NULL`` is returned. @@ -290,19 +291,24 @@ accessible to C code. They all work with the current interpreter thread's Raise an auditing event with any active hooks. Return zero for success and non-zero with an exception set on failure. + The *event* string argument must not be *NULL*. + If any hooks have been added, *format* and other arguments will be used to construct a tuple to pass. Apart from ``N``, the same format characters as used in :c:func:`Py_BuildValue` are available. If the built value is not - a tuple, it will be added into a single-element tuple. (The ``N`` format - option consumes a reference, but since there is no way to know whether - arguments to this function will be consumed, using it may cause reference - leaks.) + a tuple, it will be added into a single-element tuple. + + The ``N`` format option must not be used. It consumes a reference, but since + there is no way to know whether arguments to this function will be consumed, + using it may cause reference leaks. Note that ``#`` format characters should always be treated as :c:type:`Py_ssize_t`, regardless of whether ``PY_SSIZE_T_CLEAN`` was defined. :func:`sys.audit` performs the same function from Python code. + See also :c:func:`PySys_AuditTuple`. + .. versionadded:: 3.8 .. versionchanged:: 3.8.2 @@ -311,6 +317,14 @@ accessible to C code. They all work with the current interpreter thread's unavoidable deprecation warning was raised. +.. c:function:: int PySys_AuditTuple(const char *event, PyObject *args) + + Similar to :c:func:`PySys_Audit`, but pass arguments as a Python object. + *args* must be a :class:`tuple`. To pass no arguments, *args* can be *NULL*. + + .. versionadded:: 3.13 + + .. c:function:: int PySys_AddAuditHook(Py_AuditHookFunction hook, void *userData) Append the callable *hook* to the list of active auditing hooks. diff --git a/Doc/c-api/type.rst b/Doc/c-api/type.rst index 0f58326f6c06b7..5aaa8147dd3176 100644 --- a/Doc/c-api/type.rst +++ b/Doc/c-api/type.rst @@ -461,21 +461,34 @@ The following functions and structs are used to create * ``Py_nb_add`` to set :c:member:`PyNumberMethods.nb_add` * ``Py_sq_length`` to set :c:member:`PySequenceMethods.sq_length` - The following fields cannot be set at all using :c:type:`PyType_Spec` and - :c:type:`PyType_Slot`: - - * :c:member:`~PyTypeObject.tp_dict` - * :c:member:`~PyTypeObject.tp_mro` - * :c:member:`~PyTypeObject.tp_cache` - * :c:member:`~PyTypeObject.tp_subclasses` - * :c:member:`~PyTypeObject.tp_weaklist` + The following “offset†fields cannot be set using :c:type:`PyType_Slot`: + + * :c:member:`~PyTypeObject.tp_weaklistoffset` + (use :c:macro:`Py_TPFLAGS_MANAGED_WEAKREF` instead if possible) + * :c:member:`~PyTypeObject.tp_dictoffset` + (use :c:macro:`Py_TPFLAGS_MANAGED_DICT` instead if possible) + * :c:member:`~PyTypeObject.tp_vectorcall_offset` + (use ``"__vectorcalloffset__"`` in + :ref:`PyMemberDef `) + + If it is not possible to switch to a ``MANAGED`` flag (for example, + for vectorcall or to support Python older than 3.12), specify the + offset in :c:member:`Py_tp_members `. + See :ref:`PyMemberDef documentation ` + for details. + + The following fields cannot be set at all when creating a heap type: + * :c:member:`~PyTypeObject.tp_vectorcall` - * :c:member:`~PyTypeObject.tp_weaklistoffset` - (use :c:macro:`Py_TPFLAGS_MANAGED_WEAKREF` instead) - * :c:member:`~PyTypeObject.tp_dictoffset` - (use :c:macro:`Py_TPFLAGS_MANAGED_DICT` instead) - * :c:member:`~PyTypeObject.tp_vectorcall_offset` - (see :ref:`PyMemberDef `) + (use :c:member:`~PyTypeObject.tp_new` and/or + :c:member:`~PyTypeObject.tp_init`) + + * Internal fields: + :c:member:`~PyTypeObject.tp_dict`, + :c:member:`~PyTypeObject.tp_mro`, + :c:member:`~PyTypeObject.tp_cache`, + :c:member:`~PyTypeObject.tp_subclasses`, and + :c:member:`~PyTypeObject.tp_weaklist`. Setting :c:data:`Py_tp_bases` or :c:data:`Py_tp_base` may be problematic on some platforms. diff --git a/Doc/c-api/typeobj.rst b/Doc/c-api/typeobj.rst index 26e6133aebaa8f..8a26f237652d12 100644 --- a/Doc/c-api/typeobj.rst +++ b/Doc/c-api/typeobj.rst @@ -147,7 +147,7 @@ Quick Reference +------------------------------------------------+-----------------------------------+-------------------+---+---+---+---+ | :c:member:`~PyTypeObject.tp_vectorcall` | :c:type:`vectorcallfunc` | | | | | | +------------------------------------------------+-----------------------------------+-------------------+---+---+---+---+ - | [:c:member:`~PyTypeObject.tp_watched`] | char | | | | | | + | [:c:member:`~PyTypeObject.tp_watched`] | unsigned char | | | | | | +------------------------------------------------+-----------------------------------+-------------------+---+---+---+---+ .. [#slots] @@ -343,13 +343,13 @@ slot typedefs | | :c:type:`PyTypeObject` * | | | | :c:type:`Py_ssize_t` | | +-----------------------------+-----------------------------+----------------------+ -| :c:type:`destructor` | void * | void | +| :c:type:`destructor` | :c:type:`PyObject` * | void | +-----------------------------+-----------------------------+----------------------+ | :c:type:`freefunc` | void * | void | +-----------------------------+-----------------------------+----------------------+ | :c:type:`traverseproc` | .. line-block:: | int | | | | | -| | void * | | +| | :c:type:`PyObject` * | | | | :c:type:`visitproc` | | | | void * | | +-----------------------------+-----------------------------+----------------------+ @@ -426,7 +426,7 @@ slot typedefs | | :c:type:`PyObject` * | | | | :c:type:`Py_buffer` * | | +-----------------------------+-----------------------------+----------------------+ -| :c:type:`inquiry` | void * | int | +| :c:type:`inquiry` | :c:type:`PyObject` * | int | +-----------------------------+-----------------------------+----------------------+ | :c:type:`unaryfunc` | .. line-block:: | :c:type:`PyObject` * | | | | | @@ -528,28 +528,6 @@ type objects) *must* have the :c:member:`~PyVarObject.ob_size` field. This field is inherited by subtypes. -.. c:member:: PyObject* PyObject._ob_next - PyObject* PyObject._ob_prev - - These fields are only present when the macro ``Py_TRACE_REFS`` is defined - (see the :option:`configure --with-trace-refs option <--with-trace-refs>`). - - Their initialization to ``NULL`` is taken care of by the - ``PyObject_HEAD_INIT`` macro. For :ref:`statically allocated objects - `, these fields always remain ``NULL``. For :ref:`dynamically - allocated objects `, these two fields are used to link the - object into a doubly linked list of *all* live objects on the heap. - - This could be used for various debugging purposes; currently the only uses - are the :func:`sys.getobjects` function and to print the objects that are - still alive at the end of a run when the environment variable - :envvar:`PYTHONDUMPREFS` is set. - - **Inheritance:** - - These fields are not inherited by subtypes. - - PyVarObject Slots ----------------- @@ -690,7 +668,8 @@ and :c:data:`PyType_Type` effectively act as defaults.) } Finally, if the type is heap allocated (:c:macro:`Py_TPFLAGS_HEAPTYPE`), the - deallocator should decrement the reference count for its type object after + deallocator should release the owned reference to its type object + (via :c:func:`Py_DECREF`) after calling the type deallocator. In order to avoid dangling pointers, the recommended way to achieve this is: @@ -1152,6 +1131,9 @@ and :c:data:`PyType_Type` effectively act as defaults.) If this flag is set, :c:macro:`Py_TPFLAGS_HAVE_GC` should also be set. + The type traverse function must call :c:func:`PyObject_VisitManagedDict` + and its clear function must call :c:func:`PyObject_ClearManagedDict`. + .. versionadded:: 3.12 **Inheritance:** @@ -1389,6 +1371,23 @@ and :c:data:`PyType_Type` effectively act as defaults.) debugging aid you may want to visit it anyway just so the :mod:`gc` module's :func:`~gc.get_referents` function will include it. + Heap types (:c:macro:`Py_TPFLAGS_HEAPTYPE`) must visit their type with:: + + Py_VISIT(Py_TYPE(self)); + + It is only needed since Python 3.9. To support Python 3.8 and older, this + line must be conditionnal:: + + #if PY_VERSION_HEX >= 0x03090000 + Py_VISIT(Py_TYPE(self)); + #endif + + If the :c:macro:`Py_TPFLAGS_MANAGED_DICT` bit is set in the + :c:member:`~PyTypeObject.tp_flags` field, the traverse function must call + :c:func:`PyObject_VisitManagedDict` like this:: + + PyObject_VisitManagedDict((PyObject*)self, visit, arg); + .. warning:: When implementing :c:member:`~PyTypeObject.tp_traverse`, only the members that the instance *owns* (by having :term:`strong references @@ -1402,7 +1401,7 @@ and :c:data:`PyType_Type` effectively act as defaults.) are allowed to be removed even if the instance is still alive). Note that :c:func:`Py_VISIT` requires the *visit* and *arg* parameters to - :c:func:`local_traverse` to have these specific names; don't name them just + :c:func:`!local_traverse` to have these specific names; don't name them just anything. Instances of :ref:`heap-allocated types ` hold a reference to @@ -1461,9 +1460,10 @@ and :c:data:`PyType_Type` effectively act as defaults.) } The :c:func:`Py_CLEAR` macro should be used, because clearing references is - delicate: the reference to the contained object must not be decremented until + delicate: the reference to the contained object must not be released + (via :c:func:`Py_DECREF`) until after the pointer to the contained object is set to ``NULL``. This is because - decrementing the reference count may cause the contained object to become trash, + releasing the reference may cause the contained object to become trash, triggering a chain of reclamation activity that may include invoking arbitrary Python code (due to finalizers, or weakref callbacks, associated with the contained object). If it's possible for such code to reference *self* again, @@ -1471,6 +1471,12 @@ and :c:data:`PyType_Type` effectively act as defaults.) so that *self* knows the contained object can no longer be used. The :c:func:`Py_CLEAR` macro performs the operations in a safe order. + If the :c:macro:`Py_TPFLAGS_MANAGED_DICT` bit is set in the + :c:member:`~PyTypeObject.tp_flags` field, the traverse function must call + :c:func:`PyObject_ClearManagedDict` like this:: + + PyObject_ClearManagedDict((PyObject*)self); + Note that :c:member:`~PyTypeObject.tp_clear` is not *always* called before an instance is deallocated. For example, when reference counting is enough to determine that an object is no longer used, the cyclic garbage @@ -1541,7 +1547,7 @@ and :c:data:`PyType_Type` effectively act as defaults.) they may be C ints or floats). The third argument specifies the requested operation, as for :c:func:`PyObject_RichCompare`. - The return value's reference count is properly incremented. + The returned value is a new :term:`strong reference`. On error, sets an exception and returns ``NULL`` from the function. @@ -1695,7 +1701,7 @@ and :c:data:`PyType_Type` effectively act as defaults.) to a pointer, are valid C99 address constants. However, the unary '&' operator applied to a non-static variable - like :c:func:`PyBaseObject_Type` is not required to produce an address + like :c:data:`PyBaseObject_Type` is not required to produce an address constant. Compilers may support this (gcc does), MSVC does not. Both compilers are strictly standard conforming in this particular behavior. @@ -1726,7 +1732,7 @@ and :c:data:`PyType_Type` effectively act as defaults.) treated as read-only. Some types may not store their dictionary in this slot. - Use :c:func:`PyType_GetDict` to retreive the dictionary for an arbitrary + Use :c:func:`PyType_GetDict` to retrieve the dictionary for an arbitrary type. .. versionchanged:: 3.12 @@ -1821,7 +1827,7 @@ and :c:data:`PyType_Type` effectively act as defaults.) field is ``NULL`` then no :attr:`~object.__dict__` gets created for instances. If the :c:macro:`Py_TPFLAGS_MANAGED_DICT` bit is set in the - :c:member:`~PyTypeObject.tp_dict` field, then + :c:member:`~PyTypeObject.tp_flags` field, then :c:member:`~PyTypeObject.tp_dictoffset` will be set to ``-1``, to indicate that it is unsafe to use this field. @@ -2139,7 +2145,7 @@ and :c:data:`PyType_Type` effectively act as defaults.) .. versionadded:: 3.9 (the field exists since 3.8 but it's only used since 3.9) -.. c:member:: char PyTypeObject.tp_watched +.. c:member:: unsigned char PyTypeObject.tp_watched Internal. Do not use. @@ -2441,7 +2447,7 @@ Buffer Object Structures Except for point (3), an implementation of this function MUST take these steps: - (1) Check if the request can be met. If not, raise :c:data:`PyExc_BufferError`, + (1) Check if the request can be met. If not, raise :exc:`BufferError`, set :c:expr:`view->obj` to ``NULL`` and return ``-1``. (2) Fill in the requested fields. diff --git a/Doc/c-api/unicode.rst b/Doc/c-api/unicode.rst index e875cf6ded655e..5541eaa521803b 100644 --- a/Doc/c-api/unicode.rst +++ b/Doc/c-api/unicode.rst @@ -75,19 +75,19 @@ Python: The following APIs are C macros and static inlined functions for fast checks and access to internal read-only data of Unicode objects: -.. c:function:: int PyUnicode_Check(PyObject *o) +.. c:function:: int PyUnicode_Check(PyObject *obj) - Return true if the object *o* is a Unicode object or an instance of a Unicode + Return true if the object *obj* is a Unicode object or an instance of a Unicode subtype. This function always succeeds. -.. c:function:: int PyUnicode_CheckExact(PyObject *o) +.. c:function:: int PyUnicode_CheckExact(PyObject *obj) - Return true if the object *o* is a Unicode object, but not an instance of a + Return true if the object *obj* is a Unicode object, but not an instance of a subtype. This function always succeeds. -.. c:function:: int PyUnicode_READY(PyObject *o) +.. c:function:: int PyUnicode_READY(PyObject *unicode) Returns ``0``. This API is kept only for backward compatibility. @@ -97,17 +97,17 @@ access to internal read-only data of Unicode objects: This API does nothing since Python 3.12. -.. c:function:: Py_ssize_t PyUnicode_GET_LENGTH(PyObject *o) +.. c:function:: Py_ssize_t PyUnicode_GET_LENGTH(PyObject *unicode) - Return the length of the Unicode string, in code points. *o* has to be a + Return the length of the Unicode string, in code points. *unicode* has to be a Unicode object in the "canonical" representation (not checked). .. versionadded:: 3.3 -.. c:function:: Py_UCS1* PyUnicode_1BYTE_DATA(PyObject *o) - Py_UCS2* PyUnicode_2BYTE_DATA(PyObject *o) - Py_UCS4* PyUnicode_4BYTE_DATA(PyObject *o) +.. c:function:: Py_UCS1* PyUnicode_1BYTE_DATA(PyObject *unicode) + Py_UCS2* PyUnicode_2BYTE_DATA(PyObject *unicode) + Py_UCS4* PyUnicode_4BYTE_DATA(PyObject *unicode) Return a pointer to the canonical representation cast to UCS1, UCS2 or UCS4 integer types for direct character access. No checks are performed if the @@ -129,18 +129,18 @@ access to internal read-only data of Unicode objects: ``PyUnicode_WCHAR_KIND`` has been removed. -.. c:function:: int PyUnicode_KIND(PyObject *o) +.. c:function:: int PyUnicode_KIND(PyObject *unicode) Return one of the PyUnicode kind constants (see above) that indicate how many - bytes per character this Unicode object uses to store its data. *o* has to + bytes per character this Unicode object uses to store its data. *unicode* has to be a Unicode object in the "canonical" representation (not checked). .. versionadded:: 3.3 -.. c:function:: void* PyUnicode_DATA(PyObject *o) +.. c:function:: void* PyUnicode_DATA(PyObject *unicode) - Return a void pointer to the raw Unicode buffer. *o* has to be a Unicode + Return a void pointer to the raw Unicode buffer. *unicode* has to be a Unicode object in the "canonical" representation (not checked). .. versionadded:: 3.3 @@ -168,25 +168,25 @@ access to internal read-only data of Unicode objects: .. versionadded:: 3.3 -.. c:function:: Py_UCS4 PyUnicode_READ_CHAR(PyObject *o, Py_ssize_t index) +.. c:function:: Py_UCS4 PyUnicode_READ_CHAR(PyObject *unicode, Py_ssize_t index) - Read a character from a Unicode object *o*, which must be in the "canonical" + Read a character from a Unicode object *unicode*, which must be in the "canonical" representation. This is less efficient than :c:func:`PyUnicode_READ` if you do multiple consecutive reads. .. versionadded:: 3.3 -.. c:function:: Py_UCS4 PyUnicode_MAX_CHAR_VALUE(PyObject *o) +.. c:function:: Py_UCS4 PyUnicode_MAX_CHAR_VALUE(PyObject *unicode) Return the maximum code point that is suitable for creating another string - based on *o*, which must be in the "canonical" representation. This is + based on *unicode*, which must be in the "canonical" representation. This is always an approximation but more efficient than iterating over the string. .. versionadded:: 3.3 -.. c:function:: int PyUnicode_IsIdentifier(PyObject *o) +.. c:function:: int PyUnicode_IsIdentifier(PyObject *unicode) Return ``1`` if the string is a valid identifier according to the language definition, section :ref:`identifiers`. Return ``0`` otherwise. @@ -358,9 +358,9 @@ APIs: .. versionadded:: 3.3 -.. c:function:: PyObject* PyUnicode_FromStringAndSize(const char *u, Py_ssize_t size) +.. c:function:: PyObject* PyUnicode_FromStringAndSize(const char *str, Py_ssize_t size) - Create a Unicode object from the char buffer *u*. The bytes will be + Create a Unicode object from the char buffer *str*. The bytes will be interpreted as being UTF-8 encoded. The buffer is copied into the new object. The return value might be a shared object, i.e. modification of the data is @@ -369,16 +369,16 @@ APIs: This function raises :exc:`SystemError` when: * *size* < 0, - * *u* is ``NULL`` and *size* > 0 + * *str* is ``NULL`` and *size* > 0 .. versionchanged:: 3.12 - *u* == ``NULL`` with *size* > 0 is not allowed anymore. + *str* == ``NULL`` with *size* > 0 is not allowed anymore. -.. c:function:: PyObject *PyUnicode_FromString(const char *u) +.. c:function:: PyObject *PyUnicode_FromString(const char *str) Create a Unicode object from a UTF-8 encoded null-terminated char buffer - *u*. + *str*. .. c:function:: PyObject* PyUnicode_FromFormat(const char *format, ...) @@ -564,7 +564,7 @@ APIs: Copy an instance of a Unicode subtype to a new true Unicode object if necessary. If *obj* is already a true Unicode object (not a subtype), - return the reference with incremented refcount. + return a new :term:`strong reference` to the object. Objects other than Unicode or its subtypes will cause a :exc:`TypeError`. @@ -646,29 +646,29 @@ APIs: .. versionadded:: 3.3 -.. c:function:: PyObject* PyUnicode_Substring(PyObject *str, Py_ssize_t start, \ +.. c:function:: PyObject* PyUnicode_Substring(PyObject *unicode, Py_ssize_t start, \ Py_ssize_t end) - Return a substring of *str*, from character index *start* (included) to + Return a substring of *unicode*, from character index *start* (included) to character index *end* (excluded). Negative indices are not supported. .. versionadded:: 3.3 -.. c:function:: Py_UCS4* PyUnicode_AsUCS4(PyObject *u, Py_UCS4 *buffer, \ +.. c:function:: Py_UCS4* PyUnicode_AsUCS4(PyObject *unicode, Py_UCS4 *buffer, \ Py_ssize_t buflen, int copy_null) - Copy the string *u* into a UCS4 buffer, including a null character, if + Copy the string *unicode* into a UCS4 buffer, including a null character, if *copy_null* is set. Returns ``NULL`` and sets an exception on error (in particular, a :exc:`SystemError` if *buflen* is smaller than the length of - *u*). *buffer* is returned on success. + *unicode*). *buffer* is returned on success. .. versionadded:: 3.3 -.. c:function:: Py_UCS4* PyUnicode_AsUCS4Copy(PyObject *u) +.. c:function:: Py_UCS4* PyUnicode_AsUCS4Copy(PyObject *unicode) - Copy the string *u* into a new UCS4 buffer that is allocated using + Copy the string *unicode* into a new UCS4 buffer that is allocated using :c:func:`PyMem_Malloc`. If this fails, ``NULL`` is returned with a :exc:`MemoryError` set. The returned buffer always has an extra null code point appended. @@ -683,7 +683,7 @@ The current locale encoding can be used to decode text from the operating system. .. c:function:: PyObject* PyUnicode_DecodeLocaleAndSize(const char *str, \ - Py_ssize_t len, \ + Py_ssize_t length, \ const char *errors) Decode a string from UTF-8 on Android and VxWorks, or from the current @@ -788,7 +788,7 @@ conversion function: Accepts a :term:`path-like object`. -.. c:function:: PyObject* PyUnicode_DecodeFSDefaultAndSize(const char *s, Py_ssize_t size) +.. c:function:: PyObject* PyUnicode_DecodeFSDefaultAndSize(const char *str, Py_ssize_t size) Decode a string from the :term:`filesystem encoding and error handler`. @@ -804,7 +804,7 @@ conversion function: handler>` is now used. -.. c:function:: PyObject* PyUnicode_DecodeFSDefault(const char *s) +.. c:function:: PyObject* PyUnicode_DecodeFSDefault(const char *str) Decode a null-terminated string from the :term:`filesystem encoding and error handler`. @@ -841,17 +841,17 @@ wchar_t Support :c:type:`wchar_t` support for platforms which support it: -.. c:function:: PyObject* PyUnicode_FromWideChar(const wchar_t *w, Py_ssize_t size) +.. c:function:: PyObject* PyUnicode_FromWideChar(const wchar_t *wstr, Py_ssize_t size) - Create a Unicode object from the :c:type:`wchar_t` buffer *w* of the given *size*. + Create a Unicode object from the :c:type:`wchar_t` buffer *wstr* of the given *size*. Passing ``-1`` as the *size* indicates that the function must itself compute the length, - using wcslen. + using :c:func:`!wcslen`. Return ``NULL`` on failure. -.. c:function:: Py_ssize_t PyUnicode_AsWideChar(PyObject *unicode, wchar_t *w, Py_ssize_t size) +.. c:function:: Py_ssize_t PyUnicode_AsWideChar(PyObject *unicode, wchar_t *wstr, Py_ssize_t size) - Copy the Unicode object contents into the :c:type:`wchar_t` buffer *w*. At most + Copy the Unicode object contents into the :c:type:`wchar_t` buffer *wstr*. At most *size* :c:type:`wchar_t` characters are copied (excluding a possibly trailing null termination character). Return the number of :c:type:`wchar_t` characters copied or ``-1`` in case of an error. Note that the resulting :c:expr:`wchar_t*` @@ -915,10 +915,10 @@ Generic Codecs These are the generic codec APIs: -.. c:function:: PyObject* PyUnicode_Decode(const char *s, Py_ssize_t size, \ +.. c:function:: PyObject* PyUnicode_Decode(const char *str, Py_ssize_t size, \ const char *encoding, const char *errors) - Create a Unicode object by decoding *size* bytes of the encoded string *s*. + Create a Unicode object by decoding *size* bytes of the encoded string *str*. *encoding* and *errors* have the same meaning as the parameters of the same name in the :func:`str` built-in function. The codec to be used is looked up using the Python codec registry. Return ``NULL`` if an exception was raised by @@ -941,13 +941,13 @@ UTF-8 Codecs These are the UTF-8 codec APIs: -.. c:function:: PyObject* PyUnicode_DecodeUTF8(const char *s, Py_ssize_t size, const char *errors) +.. c:function:: PyObject* PyUnicode_DecodeUTF8(const char *str, Py_ssize_t size, const char *errors) Create a Unicode object by decoding *size* bytes of the UTF-8 encoded string - *s*. Return ``NULL`` if an exception was raised by the codec. + *str*. Return ``NULL`` if an exception was raised by the codec. -.. c:function:: PyObject* PyUnicode_DecodeUTF8Stateful(const char *s, Py_ssize_t size, \ +.. c:function:: PyObject* PyUnicode_DecodeUTF8Stateful(const char *str, Py_ssize_t size, \ const char *errors, Py_ssize_t *consumed) If *consumed* is ``NULL``, behave like :c:func:`PyUnicode_DecodeUTF8`. If @@ -971,8 +971,8 @@ These are the UTF-8 codec APIs: returned buffer always has an extra null byte appended (not included in *size*), regardless of whether there are any other null code points. - In the case of an error, ``NULL`` is returned with an exception set and no - *size* is stored. + On error, set an exception, set *size* to ``-1`` (if it's not NULL) and + return ``NULL``. This caches the UTF-8 representation of the string in the Unicode object, and subsequent calls will return a pointer to the same buffer. The caller is not @@ -1004,7 +1004,7 @@ UTF-32 Codecs These are the UTF-32 codec APIs: -.. c:function:: PyObject* PyUnicode_DecodeUTF32(const char *s, Py_ssize_t size, \ +.. c:function:: PyObject* PyUnicode_DecodeUTF32(const char *str, Py_ssize_t size, \ const char *errors, int *byteorder) Decode *size* bytes from a UTF-32 encoded buffer string and return the @@ -1031,7 +1031,7 @@ These are the UTF-32 codec APIs: Return ``NULL`` if an exception was raised by the codec. -.. c:function:: PyObject* PyUnicode_DecodeUTF32Stateful(const char *s, Py_ssize_t size, \ +.. c:function:: PyObject* PyUnicode_DecodeUTF32Stateful(const char *str, Py_ssize_t size, \ const char *errors, int *byteorder, Py_ssize_t *consumed) If *consumed* is ``NULL``, behave like :c:func:`PyUnicode_DecodeUTF32`. If @@ -1054,7 +1054,7 @@ UTF-16 Codecs These are the UTF-16 codec APIs: -.. c:function:: PyObject* PyUnicode_DecodeUTF16(const char *s, Py_ssize_t size, \ +.. c:function:: PyObject* PyUnicode_DecodeUTF16(const char *str, Py_ssize_t size, \ const char *errors, int *byteorder) Decode *size* bytes from a UTF-16 encoded buffer string and return the @@ -1082,7 +1082,7 @@ These are the UTF-16 codec APIs: Return ``NULL`` if an exception was raised by the codec. -.. c:function:: PyObject* PyUnicode_DecodeUTF16Stateful(const char *s, Py_ssize_t size, \ +.. c:function:: PyObject* PyUnicode_DecodeUTF16Stateful(const char *str, Py_ssize_t size, \ const char *errors, int *byteorder, Py_ssize_t *consumed) If *consumed* is ``NULL``, behave like :c:func:`PyUnicode_DecodeUTF16`. If @@ -1105,13 +1105,13 @@ UTF-7 Codecs These are the UTF-7 codec APIs: -.. c:function:: PyObject* PyUnicode_DecodeUTF7(const char *s, Py_ssize_t size, const char *errors) +.. c:function:: PyObject* PyUnicode_DecodeUTF7(const char *str, Py_ssize_t size, const char *errors) Create a Unicode object by decoding *size* bytes of the UTF-7 encoded string - *s*. Return ``NULL`` if an exception was raised by the codec. + *str*. Return ``NULL`` if an exception was raised by the codec. -.. c:function:: PyObject* PyUnicode_DecodeUTF7Stateful(const char *s, Py_ssize_t size, \ +.. c:function:: PyObject* PyUnicode_DecodeUTF7Stateful(const char *str, Py_ssize_t size, \ const char *errors, Py_ssize_t *consumed) If *consumed* is ``NULL``, behave like :c:func:`PyUnicode_DecodeUTF7`. If @@ -1126,11 +1126,11 @@ Unicode-Escape Codecs These are the "Unicode Escape" codec APIs: -.. c:function:: PyObject* PyUnicode_DecodeUnicodeEscape(const char *s, \ +.. c:function:: PyObject* PyUnicode_DecodeUnicodeEscape(const char *str, \ Py_ssize_t size, const char *errors) Create a Unicode object by decoding *size* bytes of the Unicode-Escape encoded - string *s*. Return ``NULL`` if an exception was raised by the codec. + string *str*. Return ``NULL`` if an exception was raised by the codec. .. c:function:: PyObject* PyUnicode_AsUnicodeEscapeString(PyObject *unicode) @@ -1146,11 +1146,11 @@ Raw-Unicode-Escape Codecs These are the "Raw Unicode Escape" codec APIs: -.. c:function:: PyObject* PyUnicode_DecodeRawUnicodeEscape(const char *s, \ +.. c:function:: PyObject* PyUnicode_DecodeRawUnicodeEscape(const char *str, \ Py_ssize_t size, const char *errors) Create a Unicode object by decoding *size* bytes of the Raw-Unicode-Escape - encoded string *s*. Return ``NULL`` if an exception was raised by the codec. + encoded string *str*. Return ``NULL`` if an exception was raised by the codec. .. c:function:: PyObject* PyUnicode_AsRawUnicodeEscapeString(PyObject *unicode) @@ -1167,10 +1167,10 @@ These are the Latin-1 codec APIs: Latin-1 corresponds to the first 256 Unicode ordinals and only these are accepted by the codecs during encoding. -.. c:function:: PyObject* PyUnicode_DecodeLatin1(const char *s, Py_ssize_t size, const char *errors) +.. c:function:: PyObject* PyUnicode_DecodeLatin1(const char *str, Py_ssize_t size, const char *errors) Create a Unicode object by decoding *size* bytes of the Latin-1 encoded string - *s*. Return ``NULL`` if an exception was raised by the codec. + *str*. Return ``NULL`` if an exception was raised by the codec. .. c:function:: PyObject* PyUnicode_AsLatin1String(PyObject *unicode) @@ -1187,10 +1187,10 @@ These are the ASCII codec APIs. Only 7-bit ASCII data is accepted. All other codes generate errors. -.. c:function:: PyObject* PyUnicode_DecodeASCII(const char *s, Py_ssize_t size, const char *errors) +.. c:function:: PyObject* PyUnicode_DecodeASCII(const char *str, Py_ssize_t size, const char *errors) Create a Unicode object by decoding *size* bytes of the ASCII encoded string - *s*. Return ``NULL`` if an exception was raised by the codec. + *str*. Return ``NULL`` if an exception was raised by the codec. .. c:function:: PyObject* PyUnicode_AsASCIIString(PyObject *unicode) @@ -1211,10 +1211,10 @@ decode characters. The mapping objects provided must support the These are the mapping codec APIs: -.. c:function:: PyObject* PyUnicode_DecodeCharmap(const char *data, Py_ssize_t size, \ +.. c:function:: PyObject* PyUnicode_DecodeCharmap(const char *str, Py_ssize_t length, \ PyObject *mapping, const char *errors) - Create a Unicode object by decoding *size* bytes of the encoded string *s* + Create a Unicode object by decoding *size* bytes of the encoded string *str* using the given *mapping* object. Return ``NULL`` if an exception was raised by the codec. @@ -1241,7 +1241,7 @@ These are the mapping codec APIs: The following codec API is special in that maps Unicode to Unicode. -.. c:function:: PyObject* PyUnicode_Translate(PyObject *str, PyObject *table, const char *errors) +.. c:function:: PyObject* PyUnicode_Translate(PyObject *unicode, PyObject *table, const char *errors) Translate a string by applying a character mapping table to it and return the resulting Unicode object. Return ``NULL`` if an exception was raised by the @@ -1266,13 +1266,13 @@ use the Win32 MBCS converters to implement the conversions. Note that MBCS (or DBCS) is a class of encodings, not just one. The target encoding is defined by the user settings on the machine running the codec. -.. c:function:: PyObject* PyUnicode_DecodeMBCS(const char *s, Py_ssize_t size, const char *errors) +.. c:function:: PyObject* PyUnicode_DecodeMBCS(const char *str, Py_ssize_t size, const char *errors) - Create a Unicode object by decoding *size* bytes of the MBCS encoded string *s*. + Create a Unicode object by decoding *size* bytes of the MBCS encoded string *str*. Return ``NULL`` if an exception was raised by the codec. -.. c:function:: PyObject* PyUnicode_DecodeMBCSStateful(const char *s, Py_ssize_t size, \ +.. c:function:: PyObject* PyUnicode_DecodeMBCSStateful(const char *str, Py_ssize_t size, \ const char *errors, Py_ssize_t *consumed) If *consumed* is ``NULL``, behave like :c:func:`PyUnicode_DecodeMBCS`. If @@ -1292,7 +1292,7 @@ the user settings on the machine running the codec. Encode the Unicode object using the specified code page and return a Python bytes object. Return ``NULL`` if an exception was raised by the codec. Use - :c:macro:`CP_ACP` code page to get the MBCS encoder. + :c:macro:`!CP_ACP` code page to get the MBCS encoder. .. versionadded:: 3.3 @@ -1318,7 +1318,7 @@ They all return ``NULL`` or ``-1`` if an exception occurs. Concat two strings giving a new Unicode string. -.. c:function:: PyObject* PyUnicode_Split(PyObject *s, PyObject *sep, Py_ssize_t maxsplit) +.. c:function:: PyObject* PyUnicode_Split(PyObject *unicode, PyObject *sep, Py_ssize_t maxsplit) Split a string giving a list of Unicode strings. If *sep* is ``NULL``, splitting will be done at all whitespace substrings. Otherwise, splits occur at the given @@ -1326,10 +1326,10 @@ They all return ``NULL`` or ``-1`` if an exception occurs. set. Separators are not included in the resulting list. -.. c:function:: PyObject* PyUnicode_Splitlines(PyObject *s, int keepend) +.. c:function:: PyObject* PyUnicode_Splitlines(PyObject *unicode, int keepends) Split a Unicode string at line breaks, returning a list of Unicode strings. - CRLF is considered to be one line break. If *keepend* is ``0``, the line break + CRLF is considered to be one line break. If *keepends* is ``0``, the Line break characters are not included in the resulting strings. @@ -1339,28 +1339,28 @@ They all return ``NULL`` or ``-1`` if an exception occurs. Unicode string. -.. c:function:: Py_ssize_t PyUnicode_Tailmatch(PyObject *str, PyObject *substr, \ +.. c:function:: Py_ssize_t PyUnicode_Tailmatch(PyObject *unicode, PyObject *substr, \ Py_ssize_t start, Py_ssize_t end, int direction) - Return ``1`` if *substr* matches ``str[start:end]`` at the given tail end + Return ``1`` if *substr* matches ``unicode[start:end]`` at the given tail end (*direction* == ``-1`` means to do a prefix match, *direction* == ``1`` a suffix match), ``0`` otherwise. Return ``-1`` if an error occurred. -.. c:function:: Py_ssize_t PyUnicode_Find(PyObject *str, PyObject *substr, \ +.. c:function:: Py_ssize_t PyUnicode_Find(PyObject *unicode, PyObject *substr, \ Py_ssize_t start, Py_ssize_t end, int direction) - Return the first position of *substr* in ``str[start:end]`` using the given + Return the first position of *substr* in ``unicode[start:end]`` using the given *direction* (*direction* == ``1`` means to do a forward search, *direction* == ``-1`` a backward search). The return value is the index of the first match; a value of ``-1`` indicates that no match was found, and ``-2`` indicates that an error occurred and an exception has been set. -.. c:function:: Py_ssize_t PyUnicode_FindChar(PyObject *str, Py_UCS4 ch, \ +.. c:function:: Py_ssize_t PyUnicode_FindChar(PyObject *unicode, Py_UCS4 ch, \ Py_ssize_t start, Py_ssize_t end, int direction) - Return the first position of the character *ch* in ``str[start:end]`` using + Return the first position of the character *ch* in ``unicode[start:end]`` using the given *direction* (*direction* == ``1`` means to do a forward search, *direction* == ``-1`` a backward search). The return value is the index of the first match; a value of ``-1`` indicates that no match was found, and ``-2`` @@ -1369,20 +1369,20 @@ They all return ``NULL`` or ``-1`` if an exception occurs. .. versionadded:: 3.3 .. versionchanged:: 3.7 - *start* and *end* are now adjusted to behave like ``str[start:end]``. + *start* and *end* are now adjusted to behave like ``unicode[start:end]``. -.. c:function:: Py_ssize_t PyUnicode_Count(PyObject *str, PyObject *substr, \ +.. c:function:: Py_ssize_t PyUnicode_Count(PyObject *unicode, PyObject *substr, \ Py_ssize_t start, Py_ssize_t end) Return the number of non-overlapping occurrences of *substr* in - ``str[start:end]``. Return ``-1`` if an error occurred. + ``unicode[start:end]``. Return ``-1`` if an error occurred. -.. c:function:: PyObject* PyUnicode_Replace(PyObject *str, PyObject *substr, \ +.. c:function:: PyObject* PyUnicode_Replace(PyObject *unicode, PyObject *substr, \ PyObject *replstr, Py_ssize_t maxcount) - Replace at most *maxcount* occurrences of *substr* in *str* with *replstr* and + Replace at most *maxcount* occurrences of *substr* in *unicode* with *replstr* and return the resulting Unicode object. *maxcount* == ``-1`` means replace all occurrences. @@ -1396,9 +1396,31 @@ They all return ``NULL`` or ``-1`` if an exception occurs. :c:func:`PyErr_Occurred` to check for errors. -.. c:function:: int PyUnicode_CompareWithASCIIString(PyObject *uni, const char *string) +.. c:function:: int PyUnicode_EqualToUTF8AndSize(PyObject *unicode, const char *string, Py_ssize_t size) - Compare a Unicode object, *uni*, with *string* and return ``-1``, ``0``, ``1`` for less + Compare a Unicode object with a char buffer which is interpreted as + being UTF-8 or ASCII encoded and return true (``1``) if they are equal, + or false (``0``) otherwise. + If the Unicode object contains surrogate characters or + the C string is not valid UTF-8, false (``0``) is returned. + + This function does not raise exceptions. + + .. versionadded:: 3.13 + + +.. c:function:: int PyUnicode_EqualToUTF8(PyObject *unicode, const char *string) + + Similar to :c:func:`PyUnicode_EqualToUTF8AndSize`, but compute *string* + length using :c:func:`!strlen`. + If the Unicode object contains null characters, false (``0``) is returned. + + .. versionadded:: 3.13 + + +.. c:function:: int PyUnicode_CompareWithASCIIString(PyObject *unicode, const char *string) + + Compare a Unicode object, *unicode*, with *string* and return ``-1``, ``0``, ``1`` for less than, equal, and greater than, respectively. It is best to pass only ASCII-encoded strings, but the function interprets the input string as ISO-8859-1 if it contains non-ASCII characters. @@ -1406,7 +1428,7 @@ They all return ``NULL`` or ``-1`` if an exception occurs. This function does not raise exceptions. -.. c:function:: PyObject* PyUnicode_RichCompare(PyObject *left, PyObject *right, int op) +.. c:function:: PyObject* PyUnicode_RichCompare(PyObject *left, PyObject *right, int op) Rich compare two Unicode strings and return one of the following: @@ -1424,29 +1446,29 @@ They all return ``NULL`` or ``-1`` if an exception occurs. ``format % args``. -.. c:function:: int PyUnicode_Contains(PyObject *container, PyObject *element) +.. c:function:: int PyUnicode_Contains(PyObject *unicode, PyObject *substr) - Check whether *element* is contained in *container* and return true or false + Check whether *substr* is contained in *unicode* and return true or false accordingly. - *element* has to coerce to a one element Unicode string. ``-1`` is returned + *substr* has to coerce to a one element Unicode string. ``-1`` is returned if there was an error. -.. c:function:: void PyUnicode_InternInPlace(PyObject **string) +.. c:function:: void PyUnicode_InternInPlace(PyObject **p_unicode) - Intern the argument *\*string* in place. The argument must be the address of a + Intern the argument :c:expr:`*p_unicode` in place. The argument must be the address of a pointer variable pointing to a Python Unicode string object. If there is an - existing interned string that is the same as *\*string*, it sets *\*string* to - it (decrementing the reference count of the old string object and incrementing - the reference count of the interned string object), otherwise it leaves - *\*string* alone and interns it (incrementing its reference count). - (Clarification: even though there is a lot of talk about reference counts, think - of this function as reference-count-neutral; you own the object after the call + existing interned string that is the same as :c:expr:`*p_unicode`, it sets :c:expr:`*p_unicode` to + it (releasing the reference to the old string object and creating a new + :term:`strong reference` to the interned string object), otherwise it leaves + :c:expr:`*p_unicode` alone and interns it (creating a new :term:`strong reference`). + (Clarification: even though there is a lot of talk about references, think + of this function as reference-neutral; you own the object after the call if and only if you owned it before the call.) -.. c:function:: PyObject* PyUnicode_InternFromString(const char *v) +.. c:function:: PyObject* PyUnicode_InternFromString(const char *str) A combination of :c:func:`PyUnicode_FromString` and :c:func:`PyUnicode_InternInPlace`, returning either a new Unicode string diff --git a/Doc/c-api/utilities.rst b/Doc/c-api/utilities.rst index ccbf14e1850f68..48ae54acebe887 100644 --- a/Doc/c-api/utilities.rst +++ b/Doc/c-api/utilities.rst @@ -17,6 +17,7 @@ and parsing function arguments and constructing Python values from C values. marshal.rst arg.rst conversion.rst + hash.rst reflection.rst codec.rst perfmaps.rst diff --git a/Doc/conf.py b/Doc/conf.py index 1b30b862f9a86c..dc09b0b51ca84c 100644 --- a/Doc/conf.py +++ b/Doc/conf.py @@ -24,7 +24,13 @@ 'sphinx.ext.doctest', ] -# Skip if downstream redistributors haven't installed it +# Skip if downstream redistributors haven't installed them +try: + import notfound.extension +except ImportError: + pass +else: + extensions.append('notfound.extension') try: import sphinxext.opengraph except ImportError: @@ -66,7 +72,7 @@ highlight_language = 'python3' # Minimum version of sphinx required -needs_sphinx = '3.2' +needs_sphinx = '4.2' # Ignore any .rst files in the includes/ directory; # they're embedded in pages but not rendered individually. @@ -94,6 +100,7 @@ ('c:func', 'sprintf'), ('c:func', 'stat'), ('c:func', 'system'), + ('c:func', 'time'), ('c:func', 'vsnprintf'), # Standard C types ('c:type', 'FILE'), @@ -110,6 +117,8 @@ ('c:type', 'uintptr_t'), ('c:type', 'va_list'), ('c:type', 'wchar_t'), + ('c:type', '__int64'), + ('c:type', 'unsigned __int64'), # Standard C structures ('c:struct', 'in6_addr'), ('c:struct', 'in_addr'), @@ -154,10 +163,94 @@ ('envvar', 'USER'), ('envvar', 'USERNAME'), ('envvar', 'USERPROFILE'), + # Deprecated function that was never documented: + ('py:func', 'getargspec'), + ('py:func', 'inspect.getargspec'), + # Undocumented modules that users shouldn't have to worry about + # (implementation details of `os.path`): + ('py:mod', 'ntpath'), + ('py:mod', 'posixpath'), +] + +# Temporary undocumented names. +# In future this list must be empty. +nitpick_ignore += [ + # C API: Standard Python exception classes + ('c:data', 'PyExc_ArithmeticError'), + ('c:data', 'PyExc_AssertionError'), + ('c:data', 'PyExc_AttributeError'), + ('c:data', 'PyExc_BaseException'), + ('c:data', 'PyExc_BlockingIOError'), + ('c:data', 'PyExc_BrokenPipeError'), + ('c:data', 'PyExc_BufferError'), + ('c:data', 'PyExc_ChildProcessError'), + ('c:data', 'PyExc_ConnectionAbortedError'), + ('c:data', 'PyExc_ConnectionError'), + ('c:data', 'PyExc_ConnectionRefusedError'), + ('c:data', 'PyExc_ConnectionResetError'), + ('c:data', 'PyExc_EOFError'), + ('c:data', 'PyExc_Exception'), + ('c:data', 'PyExc_FileExistsError'), + ('c:data', 'PyExc_FileNotFoundError'), + ('c:data', 'PyExc_FloatingPointError'), + ('c:data', 'PyExc_GeneratorExit'), + ('c:data', 'PyExc_ImportError'), + ('c:data', 'PyExc_IndentationError'), + ('c:data', 'PyExc_IndexError'), + ('c:data', 'PyExc_InterruptedError'), + ('c:data', 'PyExc_IsADirectoryError'), + ('c:data', 'PyExc_KeyboardInterrupt'), + ('c:data', 'PyExc_KeyError'), + ('c:data', 'PyExc_LookupError'), + ('c:data', 'PyExc_MemoryError'), + ('c:data', 'PyExc_ModuleNotFoundError'), + ('c:data', 'PyExc_NameError'), + ('c:data', 'PyExc_NotADirectoryError'), + ('c:data', 'PyExc_NotImplementedError'), + ('c:data', 'PyExc_OSError'), + ('c:data', 'PyExc_OverflowError'), + ('c:data', 'PyExc_PermissionError'), + ('c:data', 'PyExc_ProcessLookupError'), + ('c:data', 'PyExc_RecursionError'), + ('c:data', 'PyExc_ReferenceError'), + ('c:data', 'PyExc_RuntimeError'), + ('c:data', 'PyExc_StopAsyncIteration'), + ('c:data', 'PyExc_StopIteration'), + ('c:data', 'PyExc_SyntaxError'), + ('c:data', 'PyExc_SystemError'), + ('c:data', 'PyExc_SystemExit'), + ('c:data', 'PyExc_TabError'), + ('c:data', 'PyExc_TimeoutError'), + ('c:data', 'PyExc_TypeError'), + ('c:data', 'PyExc_UnboundLocalError'), + ('c:data', 'PyExc_UnicodeDecodeError'), + ('c:data', 'PyExc_UnicodeEncodeError'), + ('c:data', 'PyExc_UnicodeError'), + ('c:data', 'PyExc_UnicodeTranslateError'), + ('c:data', 'PyExc_ValueError'), + ('c:data', 'PyExc_ZeroDivisionError'), + # C API: Standard Python warning classes + ('c:data', 'PyExc_BytesWarning'), + ('c:data', 'PyExc_DeprecationWarning'), + ('c:data', 'PyExc_FutureWarning'), + ('c:data', 'PyExc_ImportWarning'), + ('c:data', 'PyExc_PendingDeprecationWarning'), + ('c:data', 'PyExc_ResourceWarning'), + ('c:data', 'PyExc_RuntimeWarning'), + ('c:data', 'PyExc_SyntaxWarning'), + ('c:data', 'PyExc_UnicodeWarning'), + ('c:data', 'PyExc_UserWarning'), + ('c:data', 'PyExc_Warning'), # Do not error nit-picky mode builds when _SubParsersAction.add_parser cannot # be resolved, as the method is currently undocumented. For context, see # https://github.com/python/cpython/pull/103289. ('py:meth', '_SubParsersAction.add_parser'), + # Attributes/methods/etc. that definitely should be documented better, + # but are deferred for now: + ('py:attr', '__annotations__'), + ('py:meth', '__missing__'), + ('py:attr', '__wrapped__'), + ('py:meth', 'index'), # list.index, tuple.index, etc. ] # gh-106948: Copy standard C types declared in the "c:type" domain to the @@ -214,9 +307,8 @@ "pr_id": os.getenv("READTHEDOCS_VERSION") } -# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, -# using the given strftime format. -html_last_updated_fmt = '%b %d, %Y' +# This 'Last updated on:' timestamp is inserted at the bottom of every page. +html_last_updated_fmt = time.strftime('%b %d, %Y (%H:%M UTC)', time.gmtime()) # Path to find HTML templates. templates_path = ['tools/templates'] @@ -280,8 +372,6 @@ latex_documents = [ ('c-api/index', 'c-api.tex', 'The Python/C API', _stdauthor, 'manual'), - ('distributing/index', 'distributing.tex', - 'Distributing Python Modules', _stdauthor, 'manual'), ('extending/index', 'extending.tex', 'Extending and Embedding Python', _stdauthor, 'manual'), ('installing/index', 'installing.tex', diff --git a/Doc/constraints.txt b/Doc/constraints.txt index 54888eaab242ee..147de1271eb2b7 100644 --- a/Doc/constraints.txt +++ b/Doc/constraints.txt @@ -10,8 +10,7 @@ colorama<0.5 imagesize<1.5 Jinja2<3.2 packaging<24 -# Pygments==2.15.0 breaks CI -Pygments<2.16,!=2.15.0 +Pygments>=2.16.1,<3 requests<3 snowballstemmer<3 sphinxcontrib-applehelp<1.1 diff --git a/Doc/contents.rst b/Doc/contents.rst index 464f93bdf85f95..24ceacb0076b5e 100644 --- a/Doc/contents.rst +++ b/Doc/contents.rst @@ -11,7 +11,6 @@ library/index.rst extending/index.rst c-api/index.rst - distributing/index.rst installing/index.rst howto/index.rst faq/index.rst @@ -21,10 +20,3 @@ bugs.rst copyright.rst license.rst - -.. to include legacy packaging docs in build - -.. toctree:: - :hidden: - - install/index.rst diff --git a/Doc/data/refcounts.dat b/Doc/data/refcounts.dat index ef9ac1617a284b..0b48512083ced4 100644 --- a/Doc/data/refcounts.dat +++ b/Doc/data/refcounts.dat @@ -1589,6 +1589,13 @@ PyObject_Call:PyObject*:callable_object:0: PyObject_Call:PyObject*:args:0: PyObject_Call:PyObject*:kw:0: +PyObject_CallNoArgs:PyObject*::+1: +PyObject_CallNoArgs:PyObject*:callable_object:0: + +PyObject_CallOneArg:PyObject*::+1: +PyObject_CallOneArg:PyObject*:callable_object:0: +PyObject_CallOneArg:PyObject*:arg:0: + PyObject_CallFunction:PyObject*::+1: PyObject_CallFunction:PyObject*:callable_object:0: PyObject_CallFunction:const char*:format:: diff --git a/Doc/data/stable_abi.dat b/Doc/data/stable_abi.dat index ed415a4dc644a4..811b1bd84d2417 100644 --- a/Doc/data/stable_abi.dat +++ b/Doc/data/stable_abi.dat @@ -347,6 +347,7 @@ var,PyList_Type,3.2,, type,PyLongObject,3.2,,opaque var,PyLongRangeIter_Type,3.2,, function,PyLong_AsDouble,3.2,, +function,PyLong_AsInt,3.13,, function,PyLong_AsLong,3.2,, function,PyLong_AsLongAndOverflow,3.2,, function,PyLong_AsLongLong,3.2,, @@ -376,6 +377,8 @@ function,PyMapping_GetOptionalItem,3.13,, function,PyMapping_GetOptionalItemString,3.13,, function,PyMapping_HasKey,3.2,, function,PyMapping_HasKeyString,3.2,, +function,PyMapping_HasKeyStringWithError,3.13,, +function,PyMapping_HasKeyWithError,3.13,, function,PyMapping_Items,3.2,, function,PyMapping_Keys,3.2,, function,PyMapping_Length,3.2,, @@ -385,6 +388,10 @@ function,PyMapping_Values,3.2,, function,PyMem_Calloc,3.7,, function,PyMem_Free,3.2,, function,PyMem_Malloc,3.2,, +function,PyMem_RawCalloc,3.13,, +function,PyMem_RawFree,3.13,, +function,PyMem_RawMalloc,3.13,, +function,PyMem_RawRealloc,3.13,, function,PyMem_Realloc,3.2,, type,PyMemberDef,3.2,,full-abi var,PyMemberDescr_Type,3.2,, @@ -522,6 +529,8 @@ function,PyObject_GetOptionalAttrString,3.13,, function,PyObject_GetTypeData,3.12,, function,PyObject_HasAttr,3.2,, function,PyObject_HasAttrString,3.2,, +function,PyObject_HasAttrStringWithError,3.13,, +function,PyObject_HasAttrWithError,3.13,, function,PyObject_Hash,3.2,, function,PyObject_HashNotImplemented,3.2,, function,PyObject_Init,3.2,, @@ -597,6 +606,8 @@ function,PyStructSequence_NewType,3.2,, function,PyStructSequence_SetItem,3.2,, var,PyStructSequence_UnnamedField,3.11,, var,PySuper_Type,3.2,, +function,PySys_Audit,3.13,, +function,PySys_AuditTuple,3.13,, function,PySys_FormatStderr,3.2,, function,PySys_FormatStdout,3.2,, function,PySys_GetObject,3.2,, @@ -750,6 +761,8 @@ function,PyUnicode_DecodeUnicodeEscape,3.2,, function,PyUnicode_EncodeCodePage,3.7,on Windows, function,PyUnicode_EncodeFSDefault,3.2,, function,PyUnicode_EncodeLocale,3.7,, +function,PyUnicode_EqualToUTF8,3.13,, +function,PyUnicode_EqualToUTF8AndSize,3.13,, function,PyUnicode_FSConverter,3.2,, function,PyUnicode_FSDecoder,3.2,, function,PyUnicode_Find,3.2,, @@ -835,6 +848,7 @@ function,Py_Initialize,3.2,, function,Py_InitializeEx,3.2,, function,Py_Is,3.10,, function,Py_IsFalse,3.10,, +function,Py_IsFinalizing,3.13,, function,Py_IsInitialized,3.2,, function,Py_IsNone,3.10,, function,Py_IsTrue,3.10,, diff --git a/Doc/distributing/index.rst b/Doc/distributing/index.rst index d237f8f082d87b..2430564b45d6d2 100644 --- a/Doc/distributing/index.rst +++ b/Doc/distributing/index.rst @@ -1,174 +1,19 @@ +:orphan: + +.. This page is retained solely for existing links to /distributing/index.html. + Direct readers to the PPUG instead. + .. _distributing-index: ############################### Distributing Python Modules ############################### -:Email: distutils-sig@python.org - - -As a popular open source development project, Python has an active -supporting community of contributors and users that also make their software -available for other Python developers to use under open source license terms. - -This allows Python users to share and collaborate effectively, benefiting -from the solutions others have already created to common (and sometimes -even rare!) problems, as well as potentially contributing their own -solutions to the common pool. - -This guide covers the distribution part of the process. For a guide to -installing other Python projects, refer to the -:ref:`installation guide `. - .. note:: - For corporate and other institutional users, be aware that many - organisations have their own policies around using and contributing to - open source software. Please take such policies into account when making - use of the distribution and installation tools provided with Python. - - -Key terms -========= - -* the `Python Package Index `__ is a public - repository of open source licensed packages made available for use by - other Python users -* the `Python Packaging Authority - `__ are the group of - developers and documentation authors responsible for the maintenance and - evolution of the standard packaging tools and the associated metadata and - file format standards. They maintain a variety of tools, documentation - and issue trackers on `GitHub `__. -* ``distutils`` is the original build and distribution system first added - to the Python standard library in 1998. While direct use of ``distutils`` - is being phased out, it still laid the foundation for the current packaging - and distribution infrastructure, and it not only remains part of the - standard library, but its name lives on in other ways (such as the name - of the mailing list used to coordinate Python packaging standards - development). -* `setuptools`_ is a (largely) drop-in replacement for ``distutils`` first - published in 2004. Its most notable addition over the unmodified - ``distutils`` tools was the ability to declare dependencies on other - packages. It is currently recommended as a more regularly updated - alternative to ``distutils`` that offers consistent support for more - recent packaging standards across a wide range of Python versions. -* `wheel`_ (in this context) is a project that adds the ``bdist_wheel`` - command to ``distutils``/`setuptools`_. This produces a cross platform - binary packaging format (called "wheels" or "wheel files" and defined in - :pep:`427`) that allows Python libraries, even those including binary - extensions, to be installed on a system without needing to be built - locally. - -.. _setuptools: https://setuptools.readthedocs.io/en/latest/ -.. _wheel: https://wheel.readthedocs.io/ - -Open source licensing and collaboration -======================================= - -In most parts of the world, software is automatically covered by copyright. -This means that other developers require explicit permission to copy, use, -modify and redistribute the software. - -Open source licensing is a way of explicitly granting such permission in a -relatively consistent way, allowing developers to share and collaborate -efficiently by making common solutions to various problems freely available. -This leaves many developers free to spend more time focusing on the problems -that are relatively unique to their specific situation. - -The distribution tools provided with Python are designed to make it -reasonably straightforward for developers to make their own contributions -back to that common pool of software if they choose to do so. - -The same distribution tools can also be used to distribute software within -an organisation, regardless of whether that software is published as open -source software or not. - - -Installing the tools -==================== - -The standard library does not include build tools that support modern -Python packaging standards, as the core development team has found that it -is important to have standard tools that work consistently, even on older -versions of Python. - -The currently recommended build and distribution tools can be installed -by invoking the ``pip`` module at the command line:: - - python -m pip install setuptools wheel twine - -.. note:: - - For POSIX users (including macOS and Linux users), these instructions - assume the use of a :term:`virtual environment`. - - For Windows users, these instructions assume that the option to - adjust the system PATH environment variable was selected when installing - Python. - -The Python Packaging User Guide includes more details on the `currently -recommended tools`_. - -.. _currently recommended tools: https://packaging.python.org/guides/tool-recommendations/#packaging-tool-recommendations - -.. index:: - single: Python Package Index (PyPI) - single: PyPI; (see Python Package Index (PyPI)) - -.. _publishing-python-packages: - -Reading the Python Packaging User Guide -======================================= - -The Python Packaging User Guide covers the various key steps and elements -involved in creating and publishing a project: - -* `Project structure`_ -* `Building and packaging the project`_ -* `Uploading the project to the Python Package Index`_ -* `The .pypirc file`_ - -.. _Project structure: https://packaging.python.org/tutorials/packaging-projects/#packaging-python-projects -.. _Building and packaging the project: https://packaging.python.org/tutorials/packaging-projects/#creating-the-package-files -.. _Uploading the project to the Python Package Index: https://packaging.python.org/tutorials/packaging-projects/#uploading-the-distribution-archives -.. _The .pypirc file: https://packaging.python.org/specifications/pypirc/ - - -How do I...? -============ - -These are quick answers or links for some common tasks. - -... choose a name for my project? ---------------------------------- - -This isn't an easy topic, but here are a few tips: - -* check the Python Package Index to see if the name is already in use -* check popular hosting sites like GitHub, Bitbucket, etc to see if there - is already a project with that name -* check what comes up in a web search for the name you're considering -* avoid particularly common words, especially ones with multiple meanings, - as they can make it difficult for users to find your software when - searching for it - - -... create and distribute binary extensions? --------------------------------------------- - -This is actually quite a complex topic, with a variety of alternatives -available depending on exactly what you're aiming to achieve. See the -Python Packaging User Guide for more information and recommendations. - -.. seealso:: - - `Python Packaging User Guide: Binary Extensions - `__ - -.. other topics: + Information and guidance on distributing Python modules and packages + has been moved to the `Python Packaging User Guide`_, + and the tutorial on `packaging Python projects`_. - Once the Development & Deployment part of PPUG is fleshed out, some of - those sections should be linked from new questions here (most notably, - we should have a question about avoiding depending on PyPI that links to - https://packaging.python.org/en/latest/mirrors/) + .. _Python Packaging User Guide: https://packaging.python.org/ + .. _packaging Python projects: https://packaging.python.org/en/latest/tutorials/packaging-projects/ diff --git a/Doc/extending/building.rst b/Doc/extending/building.rst index 880bb33ee56718..ddde567f6f3efa 100644 --- a/Doc/extending/building.rst +++ b/Doc/extending/building.rst @@ -45,6 +45,7 @@ See the *"Multiple modules in one library"* section in :pep:`489` for details. .. highlight:: c +.. _install-index: .. _setuptools-index: Building C and C++ Extensions with setuptools diff --git a/Doc/extending/extending.rst b/Doc/extending/extending.rst index f58b4f28113e8c..745fc10a22d161 100644 --- a/Doc/extending/extending.rst +++ b/Doc/extending/extending.rst @@ -242,7 +242,7 @@ needed to ensure that it will not be discarded, causing :c:data:`!SpamError` to become a dangling pointer. Should it become a dangling pointer, C code which raises the exception could cause a core dump or other unintended side effects. -We discuss the use of ``PyMODINIT_FUNC`` as a function return type later in this +We discuss the use of :c:macro:`PyMODINIT_FUNC` as a function return type later in this sample. The :exc:`!spam.error` exception can be raised in your extension module using a @@ -363,7 +363,7 @@ only non-\ ``static`` item defined in the module file:: return PyModule_Create(&spammodule); } -Note that PyMODINIT_FUNC declares the function as ``PyObject *`` return type, +Note that :c:macro:`PyMODINIT_FUNC` declares the function as ``PyObject *`` return type, declares any special linkage declarations required by the platform, and for C++ declares the function as ``extern "C"``. @@ -735,7 +735,7 @@ Keyword Parameters for Extension Functions The :c:func:`PyArg_ParseTupleAndKeywords` function is declared as follows:: int PyArg_ParseTupleAndKeywords(PyObject *arg, PyObject *kwdict, - const char *format, char *kwlist[], ...); + const char *format, char * const *kwlist, ...); The *arg* and *format* parameters are identical to those of the :c:func:`PyArg_ParseTuple` function. The *kwdict* parameter is the dictionary of diff --git a/Doc/extending/newtypes.rst b/Doc/extending/newtypes.rst index 386b3c8f4452c3..7a92b3257c6cd3 100644 --- a/Doc/extending/newtypes.rst +++ b/Doc/extending/newtypes.rst @@ -296,9 +296,9 @@ An interesting advantage of using the :c:member:`~PyTypeObject.tp_members` table descriptors that are used at runtime is that any attribute defined this way can have an associated doc string simply by providing the text in the table. An application can use the introspection API to retrieve the descriptor from the -class object, and get the doc string using its :attr:`__doc__` attribute. +class object, and get the doc string using its :attr:`!__doc__` attribute. -As with the :c:member:`~PyTypeObject.tp_methods` table, a sentinel entry with a :c:member:`~PyMethodDef.name` value +As with the :c:member:`~PyTypeObject.tp_methods` table, a sentinel entry with a :c:member:`~PyMethodDef.ml_name` value of ``NULL`` is required. .. XXX Descriptors need to be explained in more detail somewhere, but not here. diff --git a/Doc/extending/newtypes_tutorial.rst b/Doc/extending/newtypes_tutorial.rst index 209a4ab76d226d..7eba9759119b3b 100644 --- a/Doc/extending/newtypes_tutorial.rst +++ b/Doc/extending/newtypes_tutorial.rst @@ -45,7 +45,7 @@ extension module :mod:`!custom`: allows defining heap-allocated extension types using the :c:func:`PyType_FromSpec` function, which isn't covered in this tutorial. -.. literalinclude:: ../includes/custom.c +.. literalinclude:: ../includes/newtypes/custom.c Now that's quite a bit to take in at once, but hopefully bits will seem familiar from the previous chapter. This file defines three things: @@ -194,36 +194,32 @@ This adds the type to the module dictionary. This allows us to create >>> mycustom = custom.Custom() That's it! All that remains is to build it; put the above code in a file called -:file:`custom.c` and: +:file:`custom.c`, + +.. literalinclude:: ../includes/newtypes/pyproject.toml + +in a file called :file:`pyproject.toml`, and .. code-block:: python - from distutils.core import setup, Extension - setup(name="custom", version="1.0", - ext_modules=[Extension("custom", ["custom.c"])]) + from setuptools import Extension, setup + setup(ext_modules=[Extension("custom", ["custom.c"])]) in a file called :file:`setup.py`; then typing .. code-block:: shell-session - $ python setup.py build + $ python -m pip install . -at a shell should produce a file :file:`custom.so` in a subdirectory; move to -that directory and fire up Python --- you should be able to ``import custom`` and -play around with Custom objects. +in a shell should produce a file :file:`custom.so` in a subdirectory +and install it; now fire up Python --- you should be able to ``import custom`` +and play around with ``Custom`` objects. That wasn't so hard, was it? Of course, the current Custom type is pretty uninteresting. It has no data and doesn't do anything. It can't even be subclassed. -.. note:: - While this documentation showcases the standard :mod:`!distutils` module - for building C extensions, it is recommended in real-world use cases to - use the newer and better-maintained ``setuptools`` library. Documentation - on how to do this is out of scope for this document and can be found in - the `Python Packaging User's Guide `_. - Adding data and methods to the Basic example ============================================ @@ -232,7 +228,7 @@ Let's extend the basic example to add some data and methods. Let's also make the type usable as a base class. We'll create a new module, :mod:`!custom2` that adds these capabilities: -.. literalinclude:: ../includes/custom2.c +.. literalinclude:: ../includes/newtypes/custom2.c This version of the module has a number of changes. @@ -514,17 +510,21 @@ We rename :c:func:`!PyInit_custom` to :c:func:`!PyInit_custom2`, update the module name in the :c:type:`PyModuleDef` struct, and update the full class name in the :c:type:`PyTypeObject` struct. -Finally, we update our :file:`setup.py` file to build the new module: +Finally, we update our :file:`setup.py` file to include the new module, .. code-block:: python - from distutils.core import setup, Extension - setup(name="custom", version="1.0", - ext_modules=[ - Extension("custom", ["custom.c"]), - Extension("custom2", ["custom2.c"]), - ]) + from setuptools import Extension, setup + setup(ext_modules=[ + Extension("custom", ["custom.c"]), + Extension("custom2", ["custom2.c"]), + ]) + +and then we re-install so that we can ``import custom2``: + +.. code-block:: shell-session + $ python -m pip install . Providing finer control over data attributes ============================================ @@ -535,7 +535,7 @@ version of our module, the instance variables :attr:`!first` and :attr:`!last` could be set to non-string values or even deleted. We want to make sure that these attributes always contain strings. -.. literalinclude:: ../includes/custom3.c +.. literalinclude:: ../includes/newtypes/custom3.c To provide greater control, over the :attr:`!first` and :attr:`!last` attributes, @@ -682,7 +682,7 @@ To allow a :class:`!Custom` instance participating in a reference cycle to be properly detected and collected by the cyclic GC, our :class:`!Custom` type needs to fill two additional slots and to enable a flag that enables these slots: -.. literalinclude:: ../includes/custom4.c +.. literalinclude:: ../includes/newtypes/custom4.c First, the traversal method lets the cyclic GC know about subobjects that could @@ -806,7 +806,7 @@ increases an internal counter: >>> print(s.increment()) 2 -.. literalinclude:: ../includes/sublist.c +.. literalinclude:: ../includes/newtypes/sublist.c As you can see, the source code closely resembles the :class:`!Custom` examples in diff --git a/Doc/extending/windows.rst b/Doc/extending/windows.rst index 1129b0968bc4e6..e366d6cb9f79e3 100644 --- a/Doc/extending/windows.rst +++ b/Doc/extending/windows.rst @@ -132,4 +132,4 @@ modules (including Python) to be able to see your identifiers, you have to say Developer Studio will throw in a lot of import libraries that you do not really need, adding about 100K to your executable. To get rid of them, use the Project Settings dialog, Link tab, to specify *ignore default libraries*. Add the -correct :file:`msvcrtxx.lib` to the list of libraries. +correct :file:`msvcrt{xx}.lib` to the list of libraries. diff --git a/Doc/faq/design.rst b/Doc/faq/design.rst index 11d01374dc1e79..300e1b6cc40a58 100644 --- a/Doc/faq/design.rst +++ b/Doc/faq/design.rst @@ -451,7 +451,7 @@ on the key and a per-process seed; for example, ``'Python'`` could hash to to ``1142331976``. The hash code is then used to calculate a location in an internal array where the value will be stored. Assuming that you're storing keys that all have different hash values, this means that dictionaries take -constant time -- O(1), in Big-O notation -- to retrieve a key. +constant time -- *O*\ (1), in Big-O notation -- to retrieve a key. Why must dictionary keys be immutable? @@ -584,9 +584,9 @@ exhaustive test suites that exercise every line of code in a module. An appropriate testing discipline can help build large complex applications in Python as well as having interface specifications would. In fact, it can be better because an interface specification cannot test certain properties of a -program. For example, the :meth:`list.append` method is expected to add new elements +program. For example, the :meth:`!list.append` method is expected to add new elements to the end of some internal list; an interface specification cannot test that -your :meth:`list.append` implementation will actually do this correctly, but it's +your :meth:`!list.append` implementation will actually do this correctly, but it's trivial to check this property in a test suite. Writing test suites is very helpful, and you might want to design your code to diff --git a/Doc/faq/gui.rst b/Doc/faq/gui.rst index 0a372342862d2f..cfa60feceb31b7 100644 --- a/Doc/faq/gui.rst +++ b/Doc/faq/gui.rst @@ -43,7 +43,7 @@ applications, the applications will not be truly stand-alone, as the application will still need the Tcl and Tk libraries. One solution is to ship the application with the Tcl and Tk libraries, and point -to them at run-time using the :envvar:`TCL_LIBRARY` and :envvar:`TK_LIBRARY` +to them at run-time using the :envvar:`!TCL_LIBRARY` and :envvar:`!TK_LIBRARY` environment variables. Various third-party freeze libraries such as py2exe and cx_Freeze have @@ -55,7 +55,7 @@ Can I have Tk events handled while waiting for I/O? On platforms other than Windows, yes, and you don't even need threads! But you'll have to restructure your I/O -code a bit. Tk has the equivalent of Xt's :c:func:`XtAddInput()` call, which allows you +code a bit. Tk has the equivalent of Xt's :c:func:`!XtAddInput` call, which allows you to register a callback function which will be called from the Tk mainloop when I/O is possible on a file descriptor. See :ref:`tkinter-file-handlers`. @@ -63,8 +63,9 @@ I/O is possible on a file descriptor. See :ref:`tkinter-file-handlers`. I can't get key bindings to work in Tkinter: why? ------------------------------------------------- -An often-heard complaint is that event handlers bound to events with the -:meth:`bind` method don't get handled even when the appropriate key is pressed. +An often-heard complaint is that event handlers :ref:`bound ` +to events with the :meth:`!bind` method +don't get handled even when the appropriate key is pressed. The most common cause is that the widget to which the binding applies doesn't have "keyboard focus". Check out the Tk documentation for the focus command. diff --git a/Doc/faq/library.rst b/Doc/faq/library.rst index 9e3727456bb96e..476a43d9c288f1 100644 --- a/Doc/faq/library.rst +++ b/Doc/faq/library.rst @@ -111,7 +111,7 @@ Is there an equivalent to C's onexit() in Python? ------------------------------------------------- The :mod:`atexit` module provides a register function that is similar to C's -:c:func:`onexit`. +:c:func:`!onexit`. Why don't my signal handlers work? @@ -397,7 +397,7 @@ These aren't:: D[x] = D[x] + 1 Operations that replace other objects may invoke those other objects' -:meth:`__del__` method when their reference count reaches zero, and that can +:meth:`~object.__del__` method when their reference count reaches zero, and that can affect things. This is especially true for the mass updates to dictionaries and lists. When in doubt, use a mutex! @@ -730,14 +730,17 @@ The :mod:`select` module is commonly used to help with asynchronous I/O on sockets. To prevent the TCP connect from blocking, you can set the socket to non-blocking -mode. Then when you do the :meth:`socket.connect`, you will either connect immediately +mode. Then when you do the :meth:`~socket.socket.connect`, +you will either connect immediately (unlikely) or get an exception that contains the error number as ``.errno``. ``errno.EINPROGRESS`` indicates that the connection is in progress, but hasn't finished yet. Different OSes will return different values, so you're going to have to check what's returned on your system. -You can use the :meth:`socket.connect_ex` method to avoid creating an exception. It will -just return the errno value. To poll, you can call :meth:`socket.connect_ex` again later +You can use the :meth:`~socket.socket.connect_ex` method +to avoid creating an exception. +It will just return the errno value. +To poll, you can call :meth:`~socket.socket.connect_ex` again later -- ``0`` or ``errno.EISCONN`` indicate that you're connected -- or you can pass this socket to :meth:`select.select` to check if it's writable. diff --git a/Doc/faq/programming.rst b/Doc/faq/programming.rst index 6e1812504a184f..0a88c5f6384f2b 100644 --- a/Doc/faq/programming.rst +++ b/Doc/faq/programming.rst @@ -454,7 +454,7 @@ There are two factors that produce this result: (the list), and both ``x`` and ``y`` refer to it. 2) Lists are :term:`mutable`, which means that you can change their content. -After the call to :meth:`~list.append`, the content of the mutable object has +After the call to :meth:`!append`, the content of the mutable object has changed from ``[]`` to ``[10]``. Since both the variables refer to the same object, using either name accesses the modified value ``[10]``. @@ -1397,7 +1397,7 @@ To see why this happens, you need to know that (a) if an object implements an :meth:`~object.__iadd__` magic method, it gets called when the ``+=`` augmented assignment is executed, and its return value is what gets used in the assignment statement; -and (b) for lists, :meth:`!__iadd__` is equivalent to calling :meth:`~list.extend` on the list +and (b) for lists, :meth:`!__iadd__` is equivalent to calling :meth:`!extend` on the list and returning the list. That's why we say that for lists, ``+=`` is a "shorthand" for :meth:`!list.extend`:: @@ -1903,7 +1903,7 @@ identity tests. This prevents the code from being confused by objects such as ``float('NaN')`` that are not equal to themselves. For example, here is the implementation of -:meth:`collections.abc.Sequence.__contains__`:: +:meth:`!collections.abc.Sequence.__contains__`:: def __contains__(self, value): for v in self: diff --git a/Doc/glossary.rst b/Doc/glossary.rst index a4650a6c3efa22..098bfffb104ef6 100644 --- a/Doc/glossary.rst +++ b/Doc/glossary.rst @@ -151,16 +151,17 @@ Glossary A :term:`file object` able to read and write :term:`bytes-like objects `. Examples of binary files are files opened in binary mode (``'rb'``, - ``'wb'`` or ``'rb+'``), :data:`sys.stdin.buffer`, - :data:`sys.stdout.buffer`, and instances of :class:`io.BytesIO` and - :class:`gzip.GzipFile`. + ``'wb'`` or ``'rb+'``), :data:`sys.stdin.buffer `, + :data:`sys.stdout.buffer `, and instances of + :class:`io.BytesIO` and :class:`gzip.GzipFile`. See also :term:`text file` for a file object able to read and write :class:`str` objects. borrowed reference - In Python's C API, a borrowed reference is a reference to an object. - It does not modify the object reference count. It becomes a dangling + In Python's C API, a borrowed reference is a reference to an object, + where the code using the object does not own the reference. + It becomes a dangling pointer if the object is destroyed. For example, a garbage collection can remove the last :term:`strong reference` to the object and so destroy it. @@ -238,7 +239,7 @@ Glossary context manager An object which controls the environment seen in a :keyword:`with` - statement by defining :meth:`__enter__` and :meth:`__exit__` methods. + statement by defining :meth:`~object.__enter__` and :meth:`~object.__exit__` methods. See :pep:`343`. context variable @@ -303,8 +304,9 @@ Glossary :ref:`class definitions ` for more about decorators. descriptor - Any object which defines the methods :meth:`__get__`, :meth:`__set__`, or - :meth:`__delete__`. When a class attribute is a descriptor, its special + Any object which defines the methods :meth:`~object.__get__`, + :meth:`~object.__set__`, or :meth:`~object.__delete__`. + When a class attribute is a descriptor, its special binding behavior is triggered upon attribute lookup. Normally, using *a.b* to get, set or delete an attribute looks up the object named *b* in the class dictionary for *a*, but if *b* is a descriptor, the respective @@ -318,7 +320,8 @@ Glossary dictionary An associative array, where arbitrary keys are mapped to values. The - keys can be any object with :meth:`__hash__` and :meth:`__eq__` methods. + keys can be any object with :meth:`~object.__hash__` and + :meth:`~object.__eq__` methods. Called a hash in Perl. dictionary comprehension @@ -382,7 +385,7 @@ Glossary file object An object exposing a file-oriented API (with methods such as - :meth:`read()` or :meth:`write()`) to an underlying resource. Depending + :meth:`!read` or :meth:`!write`) to an underlying resource. Depending on the way it was created, a file object can mediate access to a real on-disk file or to another type of storage or communication device (for example standard input/output, in-memory buffers, sockets, pipes, @@ -501,7 +504,7 @@ Glossary .. index:: single: generator expression generator expression - An expression that returns an iterator. It looks like a normal expression + An :term:`expression` that returns an :term:`iterator`. It looks like a normal expression followed by a :keyword:`!for` clause defining a loop variable, range, and an optional :keyword:`!if` clause. The combined expression generates values for an enclosing function:: @@ -558,8 +561,9 @@ Glossary hashable An object is *hashable* if it has a hash value which never changes during - its lifetime (it needs a :meth:`__hash__` method), and can be compared to - other objects (it needs an :meth:`__eq__` method). Hashable objects which + its lifetime (it needs a :meth:`~object.__hash__` method), and can be + compared to other objects (it needs an :meth:`~object.__eq__` method). + Hashable objects which compare equal must have the same hash value. Hashability makes an object usable as a dictionary key and a set member, @@ -578,6 +582,16 @@ Glossary :ref:`idle` is a basic editor and interpreter environment which ships with the standard distribution of Python. + immortal + If an object is immortal, its reference count is never modified, and + therefore it is never deallocated. + + Built-in strings and singletons are immortal objects. For example, + :const:`True` and :const:`None` singletons are immmortal. + + See `PEP 683 – Immortal Objects, Using a Fixed Refcount + `_ for more information. + immutable An object with a fixed value. Immutable objects include numbers, strings and tuples. Such an object cannot be altered. A new object has to @@ -635,7 +649,8 @@ Glossary iterables include all sequence types (such as :class:`list`, :class:`str`, and :class:`tuple`) and some non-sequence types like :class:`dict`, :term:`file objects `, and objects of any classes you define - with an :meth:`__iter__` method or with a :meth:`__getitem__` method + with an :meth:`~iterator.__iter__` method or with a + :meth:`~object.__getitem__` method that implements :term:`sequence` semantics. Iterables can be @@ -644,7 +659,7 @@ Glossary as an argument to the built-in function :func:`iter`, it returns an iterator for the object. This iterator is good for one pass over the set of values. When using iterables, it is usually not necessary to call - :func:`iter` or deal with iterator objects yourself. The ``for`` + :func:`iter` or deal with iterator objects yourself. The :keyword:`for` statement does that automatically for you, creating a temporary unnamed variable to hold the iterator for the duration of the loop. See also :term:`iterator`, :term:`sequence`, and :term:`generator`. @@ -655,8 +670,8 @@ Glossary :func:`next`) return successive items in the stream. When no more data are available a :exc:`StopIteration` exception is raised instead. At this point, the iterator object is exhausted and any further calls to its - :meth:`__next__` method just raise :exc:`StopIteration` again. Iterators - are required to have an :meth:`__iter__` method that returns the iterator + :meth:`!__next__` method just raise :exc:`StopIteration` again. Iterators + are required to have an :meth:`~iterator.__iter__` method that returns the iterator object itself so every iterator is also iterable and may be used in most places where other iterables are accepted. One notable exception is code which attempts multiple iteration passes. A container object (such as a @@ -670,7 +685,7 @@ Glossary .. impl-detail:: CPython does not consistently apply the requirement that an iterator - define :meth:`__iter__`. + define :meth:`~iterator.__iter__`. key function A key function or collation function is a callable that returns a value @@ -727,7 +742,7 @@ Glossary list A built-in Python :term:`sequence`. Despite its name it is more akin to an array in other languages than to a linked list since access to - elements is O(1). + elements is *O*\ (1). list comprehension A compact way to process all or part of the elements in a sequence and @@ -864,7 +879,8 @@ Glossary Old name for the flavor of classes now used for all class objects. In earlier Python versions, only new-style classes could use Python's newer, versatile features like :attr:`~object.__slots__`, descriptors, - properties, :meth:`__getattribute__`, class methods, and static methods. + properties, :meth:`~object.__getattribute__`, class methods, and static + methods. object Any data with state (attributes or value) and defined behavior @@ -944,7 +960,7 @@ Glossary finders implement. path entry hook - A callable on the :data:`sys.path_hook` list which returns a :term:`path + A callable on the :data:`sys.path_hooks` list which returns a :term:`path entry finder` if it knows how to find modules on a specific :term:`path entry`. @@ -1054,7 +1070,9 @@ Glossary reference count The number of references to an object. When the reference count of an - object drops to zero, it is deallocated. Reference counting is + object drops to zero, it is deallocated. Some objects are + :term:`immortal` and have reference counts that are never modified, and + therefore the objects are never deallocated. Reference counting is generally not visible to Python code, but it is a key element of the :term:`CPython` implementation. Programmers can call the :func:`sys.getrefcount` function to return the @@ -1075,19 +1093,19 @@ Glossary sequence An :term:`iterable` which supports efficient element access using integer - indices via the :meth:`__getitem__` special method and defines a - :meth:`__len__` method that returns the length of the sequence. + indices via the :meth:`~object.__getitem__` special method and defines a + :meth:`~object.__len__` method that returns the length of the sequence. Some built-in sequence types are :class:`list`, :class:`str`, :class:`tuple`, and :class:`bytes`. Note that :class:`dict` also - supports :meth:`__getitem__` and :meth:`__len__`, but is considered a + supports :meth:`~object.__getitem__` and :meth:`!__len__`, but is considered a mapping rather than a sequence because the lookups use arbitrary :term:`immutable` keys rather than integers. The :class:`collections.abc.Sequence` abstract base class defines a much richer interface that goes beyond just - :meth:`__getitem__` and :meth:`__len__`, adding :meth:`count`, - :meth:`index`, :meth:`__contains__`, and - :meth:`__reversed__`. Types that implement this expanded + :meth:`~object.__getitem__` and :meth:`~object.__len__`, adding + :meth:`count`, :meth:`index`, :meth:`~object.__contains__`, and + :meth:`~object.__reversed__`. Types that implement this expanded interface can be registered explicitly using :func:`~abc.ABCMeta.register`. @@ -1135,10 +1153,17 @@ Glossary an :term:`expression` or one of several constructs with a keyword, such as :keyword:`if`, :keyword:`while` or :keyword:`for`. + static type checker + An external tool that reads Python code and analyzes it, looking for + issues such as incorrect types. See also :term:`type hints ` + and the :mod:`typing` module. + strong reference In Python's C API, a strong reference is a reference to an object - which increments the object's reference count when it is created and - decrements the object's reference count when it is deleted. + which is owned by the code holding the reference. The strong + reference is taken by calling :c:func:`Py_INCREF` when the + reference is created and released with :c:func:`Py_DECREF` + when the reference is deleted. The :c:func:`Py_NewRef` function can be used to create a strong reference to an object. Usually, the :c:func:`Py_DECREF` function must be called on @@ -1209,8 +1234,8 @@ Glossary attribute, or a function parameter or return value. Type hints are optional and are not enforced by Python but - they are useful to static type analysis tools, and aid IDEs with code - completion and refactoring. + they are useful to :term:`static type checkers `. + They can also aid IDEs with code completion and refactoring. Type hints of global variables, class attributes, and functions, but not local variables, can be accessed using diff --git a/Doc/howto/annotations.rst b/Doc/howto/annotations.rst index 1134686c947d66..be8c7e6c827f57 100644 --- a/Doc/howto/annotations.rst +++ b/Doc/howto/annotations.rst @@ -153,7 +153,8 @@ on an arbitrary object ``o``: unwrap it by accessing either ``o.__wrapped__`` or ``o.func`` as appropriate, until you have found the root unwrapped function. * If ``o`` is a callable (but not a class), use - ``o.__globals__`` as the globals when calling :func:`eval`. + :attr:`o.__globals__ ` as the globals when calling + :func:`eval`. However, not all string values used as annotations can be successfully turned into Python values by :func:`eval`. diff --git a/Doc/howto/clinic.rst b/Doc/howto/clinic.rst index dcede13a03b4a5..060977246149cf 100644 --- a/Doc/howto/clinic.rst +++ b/Doc/howto/clinic.rst @@ -1,1895 +1,14 @@ -.. highlight:: c +:orphan: -.. _howto-clinic: +.. This page is retained solely for existing links to /howto/clinic.html. + Direct readers to the devguide. ********************** Argument Clinic How-To ********************** -:author: Larry Hastings - -**Source code:** :source:`Tools/clinic/clinic.py`. - -.. topic:: Abstract - - Argument Clinic is a preprocessor for CPython C files. - It was introduced in Python 3.4 with :pep:`436`, - in order to provide introspection signatures, - and to generate performant and tailor-made boilerplate code - for argument parsing in CPython builtins, - module level functions, and class methods. - This document is divided in four major sections: - - * :ref:`clinic-background` talks about the basic concepts and goals of - Argument Clinic. - * :ref:`clinic-reference` describes the command-line interface and Argument - Clinic terminology. - * :ref:`clinic-tutorial` guides you through all the steps required to - adapt an existing C function to Argument Clinic. - * :ref:`clinic-howtos` details how to handle specific tasks. - - -.. note:: - - Argument Clinic is considered internal-only - for CPython. Its use is not supported for files outside - CPython, and no guarantees are made regarding backwards - compatibility for future versions. In other words: if you - maintain an external C extension for CPython, you're welcome - to experiment with Argument Clinic in your own code. But the - version of Argument Clinic that ships with the next version - of CPython *could* be totally incompatible and break all your code. - - -.. _clinic-background: - -Background -========== - -Basic concepts --------------- - -When Argument Clinic is run on a file, either via the :ref:`clinic-cli` -or via ``make clinic``, it will scan over the input files looking for -:term:`start lines `: - -.. code-block:: none - - /*[clinic input] - -When it finds one, it reads everything up to the :term:`end line`: - -.. code-block:: none - - [clinic start generated code]*/ - -Everything in between these two lines is Argument Clinic :term:`input`. -When Argument Clinic parses input, it generates :term:`output`. -The output is rewritten into the C file immediately after the input, -followed by a :term:`checksum line`. -All of these lines, including the :term:`start line` and :term:`checksum line`, -are collectively called an Argument Clinic :term:`block`: - -.. code-block:: none - - /*[clinic input] - ... clinic input goes here ... - [clinic start generated code]*/ - ... clinic output goes here ... - /*[clinic end generated code: ...]*/ - -If you run Argument Clinic on the same file a second time, Argument Clinic -will discard the old :term:`output` and write out the new output with a fresh -:term:`checksum line`. -If the :term:`input` hasn't changed, the output won't change either. .. note:: - You should never modify the output of an Argument Clinic block, - as any change will be lost in future Argument Clinic runs; - Argument Clinic will detect an output checksum mismatch and regenerate the - correct output. - If you are not happy with the generated output, - you should instead change the input until it produces the output you want. - - -.. _clinic-reference: - -Reference -========= - - -.. _clinic-terminology: - -Terminology ------------ - -.. glossary:: - - start line - The line ``/*[clinic input]``. - This line marks the beginning of Argument Clinic input. - Note that the *start line* opens a C block comment. - - end line - The line ``[clinic start generated code]*/``. - The *end line* marks the _end_ of Argument Clinic :term:`input`, - but at the same time marks the _start_ of Argument Clinic :term:`output`, - thus the text *"clinic start start generated code"* - Note that the *end line* closes the C block comment opened - by the *start line*. - - checksum - A hash to distinguish unique :term:`inputs ` - and :term:`outputs `. - - checksum line - A line that looks like ``/*[clinic end generated code: ...]*/``. - The three dots will be replaced by a :term:`checksum` generated from the - :term:`input`, and a :term:`checksum` generated from the :term:`output`. - The checksum line marks the end of Argument Clinic generated code, - and is used by Argument Clinic to determine if it needs to regenerate - output. - - input - The text between the :term:`start line` and the :term:`end line`. - Note that the start and end lines open and close a C block comment; - the *input* is thus a part of that same C block comment. - - output - The text between the :term:`end line` and the :term:`checksum line`. - - block - All text from the :term:`start line` to the :term:`checksum line` inclusively. - - -.. _clinic-cli: - -Command-line interface ----------------------- - -The Argument Clinic :abbr:`CLI (Command-Line Interface)` is typically used to -process a single source file, like this: - -.. code-block:: shell-session - - $ python3 ./Tools/clinic/clinic.py foo.c - -The CLI supports the following options: - -.. program:: ./Tools/clinic/clinic.py [-h] [-f] [-o OUTPUT] [-v] \ - [--converters] [--make] [--srcdir SRCDIR] [FILE ...] - -.. option:: -h, --help - - Print CLI usage. - -.. option:: -f, --force - - Force output regeneration. - -.. option:: -o, --output OUTPUT - - Redirect file output to OUTPUT - -.. option:: -v, --verbose - - Enable verbose mode. - -.. option:: --converters - - Print a list of all supported converters and return converters. - -.. option:: --make - - Walk :option:`--srcdir` to run over all relevant files. - -.. option:: --srcdir SRCDIR - - The directory tree to walk in :option:`--make` mode. - -.. option:: FILE ... - - The list of files to process. - - -.. _clinic-tutorial: - -Tutorial -======== - -The best way to get a sense of how Argument Clinic works is to -convert a function to work with it. Here, then, are the bare -minimum steps you'd need to follow to convert a function to -work with Argument Clinic. Note that for code you plan to -check in to CPython, you really should take the conversion farther, -using some of the :ref:`advanced concepts ` -you'll see later on in the document, -like :ref:`clinic-howto-return-converters` -and :ref:`clinic-howto-self-converter`. -But we'll keep it simple for this walkthrough so you can learn. - -First, make sure you're working with a freshly updated checkout -of the CPython trunk. - -Next, find a Python builtin that calls either :c:func:`PyArg_ParseTuple` -or :c:func:`PyArg_ParseTupleAndKeywords`, and hasn't been converted -to work with Argument Clinic yet. -For this tutorial, we'll be using -:py:meth:`_pickle.Pickler.dump `. - -If the call to the :c:func:`!PyArg_Parse*` function uses any of the -following format units...: - - .. code-block:: none - - O& - O! - es - es# - et - et# - -... or if it has multiple calls to :c:func:`PyArg_ParseTuple`, -you should choose a different function. -(See :ref:`clinic-howto-advanced-converters` for those scenarios.) - -Also, if the function has multiple calls to :c:func:`!PyArg_ParseTuple` -or :c:func:`PyArg_ParseTupleAndKeywords` where it supports different -types for the same argument, or if the function uses something besides -:c:func:`!PyArg_Parse*` functions to parse its arguments, it probably -isn't suitable for conversion to Argument Clinic. Argument Clinic -doesn't support generic functions or polymorphic parameters. - -Next, add the following boilerplate above the function, -creating our input block:: - - /*[clinic input] - [clinic start generated code]*/ - -Cut the docstring and paste it in between the ``[clinic]`` lines, -removing all the junk that makes it a properly quoted C string. -When you're done you should have just the text, based at the left -margin, with no line wider than 80 characters. -Argument Clinic will preserve indents inside the docstring. - -If the old docstring had a first line that looked like a function -signature, throw that line away; The docstring doesn't need it anymore --- -when you use :py:func:`help` on your builtin in the future, -the first line will be built automatically based on the function's signature. - -Example docstring summary line:: - - /*[clinic input] - Write a pickled representation of obj to the open file. - [clinic start generated code]*/ - -If your docstring doesn't have a "summary" line, Argument Clinic will -complain, so let's make sure it has one. The "summary" line should -be a paragraph consisting of a single 80-column line -at the beginning of the docstring. -(See :pep:`257` regarding docstring conventions.) - -Our example docstring consists solely of a summary line, so the sample -code doesn't have to change for this step. - -Now, above the docstring, enter the name of the function, followed -by a blank line. This should be the Python name of the function, -and should be the full dotted path to the function --- -it should start with the name of the module, -include any sub-modules, and if the function is a method on -a class it should include the class name too. - -In our example, :mod:`!_pickle` is the module, :py:class:`!Pickler` is the class, -and :py:meth:`!dump` is the method, so the name becomes -:py:meth:`!_pickle.Pickler.dump`:: - - /*[clinic input] - _pickle.Pickler.dump - - Write a pickled representation of obj to the open file. - [clinic start generated code]*/ - -If this is the first time that module or class has been used with Argument -Clinic in this C file, -you must declare the module and/or class. Proper Argument Clinic hygiene -prefers declaring these in a separate block somewhere near the -top of the C file, in the same way that include files and statics go at -the top. -In our sample code we'll just show the two blocks next to each other. - -The name of the class and module should be the same as the one -seen by Python. Check the name defined in the :c:type:`PyModuleDef` -or :c:type:`PyTypeObject` as appropriate. - -When you declare a class, you must also specify two aspects of its type -in C: the type declaration you'd use for a pointer to an instance of -this class, and a pointer to the :c:type:`!PyTypeObject` for this class:: - - /*[clinic input] - module _pickle - class _pickle.Pickler "PicklerObject *" "&Pickler_Type" - [clinic start generated code]*/ - - /*[clinic input] - _pickle.Pickler.dump - - Write a pickled representation of obj to the open file. - [clinic start generated code]*/ - -Declare each of the parameters to the function. Each parameter -should get its own line. All the parameter lines should be -indented from the function name and the docstring. -The general form of these parameter lines is as follows: - -.. code-block:: none - - name_of_parameter: converter - -If the parameter has a default value, add that after the -converter: - -.. code-block:: none - - name_of_parameter: converter = default_value - -Argument Clinic's support for "default values" is quite sophisticated; -see :ref:`clinic-howto-default-values` for more information. - -Next, add a blank line below the parameters. - -What's a "converter"? -It establishes both the type of the variable used in C, -and the method to convert the Python value into a C value at runtime. -For now you're going to use what's called a "legacy converter" --- -a convenience syntax intended to make porting old code into Argument -Clinic easier. - -For each parameter, copy the "format unit" for that -parameter from the :c:func:`PyArg_Parse` format argument and -specify *that* as its converter, as a quoted string. -The "format unit" is the formal name for the one-to-three -character substring of the *format* parameter that tells -the argument parsing function what the type of the variable -is and how to convert it. -For more on format units please see :ref:`arg-parsing`. - -For multicharacter format units like ``z#``, -use the entire two-or-three character string. - -Sample:: - - /*[clinic input] - module _pickle - class _pickle.Pickler "PicklerObject *" "&Pickler_Type" - [clinic start generated code]*/ - - /*[clinic input] - _pickle.Pickler.dump - - obj: 'O' - - Write a pickled representation of obj to the open file. - [clinic start generated code]*/ - -If your function has ``|`` in the format string, -meaning some parameters have default values, you can ignore it. -Argument Clinic infers which parameters are optional -based on whether or not they have default values. - -If your function has ``$`` in the format string, -meaning it takes keyword-only arguments, -specify ``*`` on a line by itself before the first keyword-only argument, -indented the same as the parameter lines. - -:py:meth:`!_pickle.Pickler.dump` has neither, so our sample is unchanged. - -Next, if the existing C function calls :c:func:`PyArg_ParseTuple` -(as opposed to :c:func:`PyArg_ParseTupleAndKeywords`), then all its -arguments are positional-only. - -To mark parameters as positional-only in Argument Clinic, -add a ``/`` on a line by itself after the last positional-only parameter, -indented the same as the parameter lines. - -Sample:: - - /*[clinic input] - module _pickle - class _pickle.Pickler "PicklerObject *" "&Pickler_Type" - [clinic start generated code]*/ - - /*[clinic input] - _pickle.Pickler.dump - - obj: 'O' - / - - Write a pickled representation of obj to the open file. - [clinic start generated code]*/ - -It can be helpful to write a per-parameter docstring for each parameter. -Since per-parameter docstrings are optional, -you can skip this step if you prefer. - -Nevertheless, here's how to add a per-parameter docstring. -The first line of the per-parameter docstring -must be indented further than the parameter definition. -The left margin of this first line establishes -the left margin for the whole per-parameter docstring; -all the text you write will be outdented by this amount. -You can write as much text as you like, across multiple lines if you wish. - -Sample:: - - /*[clinic input] - module _pickle - class _pickle.Pickler "PicklerObject *" "&Pickler_Type" - [clinic start generated code]*/ - - /*[clinic input] - _pickle.Pickler.dump - - obj: 'O' - The object to be pickled. - / - - Write a pickled representation of obj to the open file. - [clinic start generated code]*/ - -Save and close the file, then run ``Tools/clinic/clinic.py`` on it. -With luck everything worked---your block now has output, -and a :file:`.c.h` file has been generated! -Reload the file in your text editor to see the generated code:: - - /*[clinic input] - _pickle.Pickler.dump - - obj: 'O' - The object to be pickled. - / - - Write a pickled representation of obj to the open file. - [clinic start generated code]*/ - - static PyObject * - _pickle_Pickler_dump(PicklerObject *self, PyObject *obj) - /*[clinic end generated code: output=87ecad1261e02ac7 input=552eb1c0f52260d9]*/ - -Obviously, if Argument Clinic didn't produce any output, -it's because it found an error in your input. -Keep fixing your errors and retrying until Argument Clinic processes your file -without complaint. - -For readability, most of the glue code has been generated to a :file:`.c.h` -file. You'll need to include that in your original :file:`.c` file, -typically right after the clinic module block:: - - #include "clinic/_pickle.c.h" - -Double-check that the argument-parsing code Argument Clinic generated -looks basically the same as the existing code. - -First, ensure both places use the same argument-parsing function. -The existing code must call either -:c:func:`PyArg_ParseTuple` or :c:func:`PyArg_ParseTupleAndKeywords`; -ensure that the code generated by Argument Clinic calls the -*exact* same function. - -Second, the format string passed in to :c:func:`!PyArg_ParseTuple` or -:c:func:`!PyArg_ParseTupleAndKeywords` should be *exactly* the same -as the hand-written one in the existing function, -up to the colon or semi-colon. - -Argument Clinic always generates its format strings -with a ``:`` followed by the name of the function. -If the existing code's format string ends with ``;``, -to provide usage help, this change is harmless --- don't worry about it. - -Third, for parameters whose format units require two arguments, -like a length variable, an encoding string, or a pointer -to a conversion function, ensure that the second argument is -*exactly* the same between the two invocations. - -Fourth, inside the output portion of the block, -you'll find a preprocessor macro defining the appropriate static -:c:type:`PyMethodDef` structure for this builtin:: - - #define __PICKLE_PICKLER_DUMP_METHODDEF \ - {"dump", (PyCFunction)__pickle_Pickler_dump, METH_O, __pickle_Pickler_dump__doc__}, - -This static structure should be *exactly* the same as the existing static -:c:type:`!PyMethodDef` structure for this builtin. - -If any of these items differ in *any way*, -adjust your Argument Clinic function specification and rerun -``Tools/clinic/clinic.py`` until they *are* the same. - -Notice that the last line of its output is the declaration -of your "impl" function. This is where the builtin's implementation goes. -Delete the existing prototype of the function you're modifying, but leave -the opening curly brace. Now delete its argument parsing code and the -declarations of all the variables it dumps the arguments into. -Notice how the Python arguments are now arguments to this impl function; -if the implementation used different names for these variables, fix it. - -Let's reiterate, just because it's kind of weird. -Your code should now look like this:: - - static return_type - your_function_impl(...) - /*[clinic end generated code: input=..., output=...]*/ - { - ... - -Argument Clinic generated the checksum line and the function prototype just -above it. You should write the opening and closing curly braces for the -function, and the implementation inside. - -Sample:: - - /*[clinic input] - module _pickle - class _pickle.Pickler "PicklerObject *" "&Pickler_Type" - [clinic start generated code]*/ - /*[clinic end generated code: checksum=da39a3ee5e6b4b0d3255bfef95601890afd80709]*/ - - /*[clinic input] - _pickle.Pickler.dump - - obj: 'O' - The object to be pickled. - / - - Write a pickled representation of obj to the open file. - [clinic start generated code]*/ - - PyDoc_STRVAR(__pickle_Pickler_dump__doc__, - "Write a pickled representation of obj to the open file.\n" - "\n" - ... - static PyObject * - _pickle_Pickler_dump_impl(PicklerObject *self, PyObject *obj) - /*[clinic end generated code: checksum=3bd30745bf206a48f8b576a1da3d90f55a0a4187]*/ - { - /* Check whether the Pickler was initialized correctly (issue3664). - Developers often forget to call __init__() in their subclasses, which - would trigger a segfault without this check. */ - if (self->write == NULL) { - PyErr_Format(PicklingError, - "Pickler.__init__() was not called by %s.__init__()", - Py_TYPE(self)->tp_name); - return NULL; - } - - if (_Pickler_ClearBuffer(self) < 0) { - return NULL; - } - - ... - -Remember the macro with the :c:type:`PyMethodDef` structure for this function? -Find the existing :c:type:`!PyMethodDef` structure for this -function and replace it with a reference to the macro. If the builtin -is at module scope, this will probably be very near the end of the file; -if the builtin is a class method, this will probably be below but relatively -near to the implementation. - -Note that the body of the macro contains a trailing comma; when you -replace the existing static :c:type:`!PyMethodDef` structure with the macro, -*don't* add a comma to the end. - -Sample:: - - static struct PyMethodDef Pickler_methods[] = { - __PICKLE_PICKLER_DUMP_METHODDEF - __PICKLE_PICKLER_CLEAR_MEMO_METHODDEF - {NULL, NULL} /* sentinel */ - }; - -Argument Clinic may generate new instances of ``_Py_ID``. For example:: - - &_Py_ID(new_unique_py_id) - -If it does, you'll have to run ``make regen-global-objects`` -to regenerate the list of precompiled identifiers at this point. - -Finally, compile, then run the relevant portions of the regression-test suite. -This change should not introduce any new compile-time warnings or errors, -and there should be no externally visible change to Python's behavior, -except for one difference: :py:func:`inspect.signature` run on your function -should now provide a valid signature! - -Congratulations, you've ported your first function to work with Argument Clinic! - - -.. _clinic-howtos: - -How-to guides -============= - - -How to rename C functions and variables generated by Argument Clinic --------------------------------------------------------------------- - -Argument Clinic automatically names the functions it generates for you. -Occasionally this may cause a problem, if the generated name collides with -the name of an existing C function. There's an easy solution: override the names -used for the C functions. Just add the keyword ``"as"`` -to your function declaration line, followed by the function name you wish to use. -Argument Clinic will use that function name for the base (generated) function, -then add ``"_impl"`` to the end and use that for the name of the impl function. - -For example, if we wanted to rename the C function names generated for -:py:meth:`pickle.Pickler.dump`, it'd look like this:: - - /*[clinic input] - pickle.Pickler.dump as pickler_dumper - - ... - -The base function would now be named :c:func:`!pickler_dumper`, -and the impl function would now be named :c:func:`!pickler_dumper_impl`. - - -Similarly, you may have a problem where you want to give a parameter -a specific Python name, but that name may be inconvenient in C. Argument -Clinic allows you to give a parameter different names in Python and in C, -using the same ``"as"`` syntax:: - - /*[clinic input] - pickle.Pickler.dump - - obj: object - file as file_obj: object - protocol: object = NULL - * - fix_imports: bool = True - -Here, the name used in Python (in the signature and the ``keywords`` -array) would be *file*, but the C variable would be named ``file_obj``. - -You can use this to rename the *self* parameter too! - - -How to convert functions using ``PyArg_UnpackTuple`` ----------------------------------------------------- - -To convert a function parsing its arguments with :c:func:`PyArg_UnpackTuple`, -simply write out all the arguments, specifying each as an ``object``. You -may specify the *type* argument to cast the type as appropriate. All -arguments should be marked positional-only (add a ``/`` on a line by itself -after the last argument). - -Currently the generated code will use :c:func:`PyArg_ParseTuple`, but this -will change soon. - - -How to use optional groups --------------------------- - -Some legacy functions have a tricky approach to parsing their arguments: -they count the number of positional arguments, then use a ``switch`` statement -to call one of several different :c:func:`PyArg_ParseTuple` calls depending on -how many positional arguments there are. (These functions cannot accept -keyword-only arguments.) This approach was used to simulate optional -arguments back before :c:func:`PyArg_ParseTupleAndKeywords` was created. - -While functions using this approach can often be converted to -use :c:func:`!PyArg_ParseTupleAndKeywords`, optional arguments, and default values, -it's not always possible. Some of these legacy functions have -behaviors :c:func:`!PyArg_ParseTupleAndKeywords` doesn't directly support. -The most obvious example is the builtin function :py:func:`range`, which has -an optional argument on the *left* side of its required argument! -Another example is :py:meth:`curses.window.addch`, which has a group of two -arguments that must always be specified together. (The arguments are -called *x* and *y*; if you call the function passing in *x*, -you must also pass in *y* — and if you don't pass in *x* you may not -pass in *y* either.) - -In any case, the goal of Argument Clinic is to support argument parsing -for all existing CPython builtins without changing their semantics. -Therefore Argument Clinic supports -this alternate approach to parsing, using what are called *optional groups*. -Optional groups are groups of arguments that must all be passed in together. -They can be to the left or the right of the required arguments. They -can *only* be used with positional-only parameters. - -.. note:: Optional groups are *only* intended for use when converting - functions that make multiple calls to :c:func:`PyArg_ParseTuple`! - Functions that use *any* other approach for parsing arguments - should *almost never* be converted to Argument Clinic using - optional groups. Functions using optional groups currently - cannot have accurate signatures in Python, because Python just - doesn't understand the concept. Please avoid using optional - groups wherever possible. - -To specify an optional group, add a ``[`` on a line by itself before -the parameters you wish to group together, and a ``]`` on a line by itself -after these parameters. As an example, here's how :py:meth:`curses.window.addch` -uses optional groups to make the first two parameters and the last -parameter optional:: - - /*[clinic input] - - curses.window.addch - - [ - x: int - X-coordinate. - y: int - Y-coordinate. - ] - - ch: object - Character to add. - - [ - attr: long - Attributes for the character. - ] - / - - ... - - -Notes: - -* For every optional group, one additional parameter will be passed into the - impl function representing the group. The parameter will be an int named - ``group_{direction}_{number}``, - where ``{direction}`` is either ``right`` or ``left`` depending on whether the group - is before or after the required parameters, and ``{number}`` is a monotonically - increasing number (starting at 1) indicating how far away the group is from - the required parameters. When the impl is called, this parameter will be set - to zero if this group was unused, and set to non-zero if this group was used. - (By used or unused, I mean whether or not the parameters received arguments - in this invocation.) - -* If there are no required arguments, the optional groups will behave - as if they're to the right of the required arguments. - -* In the case of ambiguity, the argument parsing code - favors parameters on the left (before the required parameters). - -* Optional groups can only contain positional-only parameters. - -* Optional groups are *only* intended for legacy code. Please do not - use optional groups for new code. - - -How to use real Argument Clinic converters, instead of "legacy converters" --------------------------------------------------------------------------- - -To save time, and to minimize how much you need to learn -to achieve your first port to Argument Clinic, the walkthrough above tells -you to use "legacy converters". "Legacy converters" are a convenience, -designed explicitly to make porting existing code to Argument Clinic -easier. And to be clear, their use is acceptable when porting code for -Python 3.4. - -However, in the long term we probably want all our blocks to -use Argument Clinic's real syntax for converters. Why? A couple -reasons: - -* The proper converters are far easier to read and clearer in their intent. -* There are some format units that are unsupported as "legacy converters", - because they require arguments, and the legacy converter syntax doesn't - support specifying arguments. -* In the future we may have a new argument parsing library that isn't - restricted to what :c:func:`PyArg_ParseTuple` supports; this flexibility - won't be available to parameters using legacy converters. - -Therefore, if you don't mind a little extra effort, please use the normal -converters instead of legacy converters. - -In a nutshell, the syntax for Argument Clinic (non-legacy) converters -looks like a Python function call. However, if there are no explicit -arguments to the function (all functions take their default values), -you may omit the parentheses. Thus ``bool`` and ``bool()`` are exactly -the same converters. - -All arguments to Argument Clinic converters are keyword-only. -All Argument Clinic converters accept the following arguments: - - *c_default* - The default value for this parameter when defined in C. - Specifically, this will be the initializer for the variable declared - in the "parse function". See :ref:`the section on default values ` - for how to use this. - Specified as a string. - - *annotation* - The annotation value for this parameter. Not currently supported, - because :pep:`8` mandates that the Python library may not use - annotations. - - *unused* - Wrap the argument with :c:macro:`Py_UNUSED` in the impl function signature. - -In addition, some converters accept additional arguments. Here is a list -of these arguments, along with their meanings: - - *accept* - A set of Python types (and possibly pseudo-types); - this restricts the allowable Python argument to values of these types. - (This is not a general-purpose facility; as a rule it only supports - specific lists of types as shown in the legacy converter table.) - - To accept ``None``, add ``NoneType`` to this set. - - *bitwise* - Only supported for unsigned integers. The native integer value of this - Python argument will be written to the parameter without any range checking, - even for negative values. - - *converter* - Only supported by the ``object`` converter. Specifies the name of a - :ref:`C "converter function" ` - to use to convert this object to a native type. - - *encoding* - Only supported for strings. Specifies the encoding to use when converting - this string from a Python str (Unicode) value into a C ``char *`` value. - - - *subclass_of* - Only supported for the ``object`` converter. Requires that the Python - value be a subclass of a Python type, as expressed in C. - - *type* - Only supported for the ``object`` and ``self`` converters. Specifies - the C type that will be used to declare the variable. Default value is - ``"PyObject *"``. - - *zeroes* - Only supported for strings. If true, embedded NUL bytes (``'\\0'``) are - permitted inside the value. The length of the string will be passed in - to the impl function, just after the string parameter, as a parameter named - ``_length``. - -Please note, not every possible combination of arguments will work. -Usually these arguments are implemented by specific :c:func:`PyArg_ParseTuple` -*format units*, with specific behavior. For example, currently you cannot -call ``unsigned_short`` without also specifying ``bitwise=True``. -Although it's perfectly reasonable to think this would work, these semantics don't -map to any existing format unit. So Argument Clinic doesn't support it. (Or, at -least, not yet.) - -Below is a table showing the mapping of legacy converters into real -Argument Clinic converters. On the left is the legacy converter, -on the right is the text you'd replace it with. - -========= ================================================================================= -``'B'`` ``unsigned_char(bitwise=True)`` -``'b'`` ``unsigned_char`` -``'c'`` ``char`` -``'C'`` ``int(accept={str})`` -``'d'`` ``double`` -``'D'`` ``Py_complex`` -``'es'`` ``str(encoding='name_of_encoding')`` -``'es#'`` ``str(encoding='name_of_encoding', zeroes=True)`` -``'et'`` ``str(encoding='name_of_encoding', accept={bytes, bytearray, str})`` -``'et#'`` ``str(encoding='name_of_encoding', accept={bytes, bytearray, str}, zeroes=True)`` -``'f'`` ``float`` -``'h'`` ``short`` -``'H'`` ``unsigned_short(bitwise=True)`` -``'i'`` ``int`` -``'I'`` ``unsigned_int(bitwise=True)`` -``'k'`` ``unsigned_long(bitwise=True)`` -``'K'`` ``unsigned_long_long(bitwise=True)`` -``'l'`` ``long`` -``'L'`` ``long long`` -``'n'`` ``Py_ssize_t`` -``'O'`` ``object`` -``'O!'`` ``object(subclass_of='&PySomething_Type')`` -``'O&'`` ``object(converter='name_of_c_function')`` -``'p'`` ``bool`` -``'S'`` ``PyBytesObject`` -``'s'`` ``str`` -``'s#'`` ``str(zeroes=True)`` -``'s*'`` ``Py_buffer(accept={buffer, str})`` -``'U'`` ``unicode`` -``'u'`` ``wchar_t`` -``'u#'`` ``wchar_t(zeroes=True)`` -``'w*'`` ``Py_buffer(accept={rwbuffer})`` -``'Y'`` ``PyByteArrayObject`` -``'y'`` ``str(accept={bytes})`` -``'y#'`` ``str(accept={robuffer}, zeroes=True)`` -``'y*'`` ``Py_buffer`` -``'Z'`` ``wchar_t(accept={str, NoneType})`` -``'Z#'`` ``wchar_t(accept={str, NoneType}, zeroes=True)`` -``'z'`` ``str(accept={str, NoneType})`` -``'z#'`` ``str(accept={str, NoneType}, zeroes=True)`` -``'z*'`` ``Py_buffer(accept={buffer, str, NoneType})`` -========= ================================================================================= - -As an example, here's our sample ``pickle.Pickler.dump`` using the proper -converter:: - - /*[clinic input] - pickle.Pickler.dump - - obj: object - The object to be pickled. - / - - Write a pickled representation of obj to the open file. - [clinic start generated code]*/ - -One advantage of real converters is that they're more flexible than legacy -converters. For example, the ``unsigned_int`` converter (and all the -``unsigned_`` converters) can be specified without ``bitwise=True``. Their -default behavior performs range checking on the value, and they won't accept -negative numbers. You just can't do that with a legacy converter! - -Argument Clinic will show you all the converters it has -available. For each converter it'll show you all the parameters -it accepts, along with the default value for each parameter. -Just run ``Tools/clinic/clinic.py --converters`` to see the full list. - - -How to use the ``Py_buffer`` converter --------------------------------------- - -When using the ``Py_buffer`` converter -(or the ``'s*'``, ``'w*'``, ``'*y'``, or ``'z*'`` legacy converters), -you *must* not call :c:func:`PyBuffer_Release` on the provided buffer. -Argument Clinic generates code that does it for you (in the parsing function). - - -.. _clinic-howto-advanced-converters: - -How to use advanced converters ------------------------------- - -Remember those format units you skipped for your first -time because they were advanced? Here's how to handle those too. - -The trick is, all those format units take arguments—either -conversion functions, or types, or strings specifying an encoding. -(But "legacy converters" don't support arguments. That's why we -skipped them for your first function.) The argument you specified -to the format unit is now an argument to the converter; this -argument is either *converter* (for ``O&``), *subclass_of* (for ``O!``), -or *encoding* (for all the format units that start with ``e``). - -When using *subclass_of*, you may also want to use the other -custom argument for ``object()``: *type*, which lets you set the type -actually used for the parameter. For example, if you want to ensure -that the object is a subclass of :c:var:`PyUnicode_Type`, you probably want -to use the converter ``object(type='PyUnicodeObject *', subclass_of='&PyUnicode_Type')``. - -One possible problem with using Argument Clinic: it takes away some possible -flexibility for the format units starting with ``e``. When writing a -:c:func:`!PyArg_Parse*` call by hand, you could theoretically decide at runtime what -encoding string to pass to that call. But now this string must -be hard-coded at Argument-Clinic-preprocessing-time. This limitation is deliberate; -it made supporting this format unit much easier, and may allow for future optimizations. -This restriction doesn't seem unreasonable; CPython itself always passes in static -hard-coded encoding strings for parameters whose format units start with ``e``. - - -.. _clinic-howto-default-values: -.. _default_values: - -How to assign default values to parameter ------------------------------------------ - -Default values for parameters can be any of a number of values. -At their simplest, they can be string, int, or float literals: - -.. code-block:: none - - foo: str = "abc" - bar: int = 123 - bat: float = 45.6 - -They can also use any of Python's built-in constants: - -.. code-block:: none - - yep: bool = True - nope: bool = False - nada: object = None - -There's also special support for a default value of ``NULL``, and -for simple expressions, documented in the following sections. - - -The ``NULL`` default value -^^^^^^^^^^^^^^^^^^^^^^^^^^ - -For string and object parameters, you can set them to ``None`` to indicate -that there's no default. However, that means the C variable will be -initialized to ``Py_None``. For convenience's sakes, there's a special -value called ``NULL`` for just this reason: from Python's perspective it -behaves like a default value of ``None``, but the C variable is initialized -with ``NULL``. - - -Symbolic default values -^^^^^^^^^^^^^^^^^^^^^^^ - -The default value you provide for a parameter can't be any arbitrary -expression. Currently the following are explicitly supported: - -* Numeric constants (integer and float) -* String constants -* ``True``, ``False``, and ``None`` -* Simple symbolic constants like :py:data:`sys.maxsize`, which must - start with the name of the module - -(In the future, this may need to get even more elaborate, -to allow full expressions like ``CONSTANT - 1``.) - - -Expressions as default values -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -The default value for a parameter can be more than just a literal value. -It can be an entire expression, using math operators and looking up attributes -on objects. However, this support isn't exactly simple, because of some -non-obvious semantics. - -Consider the following example: - -.. code-block:: none - - foo: Py_ssize_t = sys.maxsize - 1 - -:py:data:`sys.maxsize` can have different values on different platforms. Therefore -Argument Clinic can't simply evaluate that expression locally and hard-code it -in C. So it stores the default in such a way that it will get evaluated at -runtime, when the user asks for the function's signature. - -What namespace is available when the expression is evaluated? It's evaluated -in the context of the module the builtin came from. So, if your module has an -attribute called :py:attr:`!max_widgets`, you may simply use it: - -.. code-block:: none - - foo: Py_ssize_t = max_widgets - -If the symbol isn't found in the current module, it fails over to looking in -:py:data:`sys.modules`. That's how it can find :py:data:`sys.maxsize` for example. -(Since you don't know in advance what modules the user will load into their interpreter, -it's best to restrict yourself to modules that are preloaded by Python itself.) - -Evaluating default values only at runtime means Argument Clinic can't compute -the correct equivalent C default value. So you need to tell it explicitly. -When you use an expression, you must also specify the equivalent expression -in C, using the *c_default* parameter to the converter: - -.. code-block:: none - - foo: Py_ssize_t(c_default="PY_SSIZE_T_MAX - 1") = sys.maxsize - 1 - -Another complication: Argument Clinic can't know in advance whether or not the -expression you supply is valid. It parses it to make sure it looks legal, but -it can't *actually* know. You must be very careful when using expressions to -specify values that are guaranteed to be valid at runtime! - -Finally, because expressions must be representable as static C values, there -are many restrictions on legal expressions. Here's a list of Python features -you're not permitted to use: - -* Function calls. -* Inline if statements (``3 if foo else 5``). -* Automatic sequence unpacking (``*[1, 2, 3]``). -* List/set/dict comprehensions and generator expressions. -* Tuple/list/set/dict literals. - - -.. _clinic-howto-return-converters: - -How to use return converters ----------------------------- - -By default, the impl function Argument Clinic generates for you returns -:c:type:`PyObject * `. -But your C function often computes some C type, -then converts it into the :c:type:`!PyObject *` -at the last moment. Argument Clinic handles converting your inputs from Python types -into native C types—why not have it convert your return value from a native C type -into a Python type too? - -That's what a "return converter" does. It changes your impl function to return -some C type, then adds code to the generated (non-impl) function to handle converting -that value into the appropriate :c:type:`!PyObject *`. - -The syntax for return converters is similar to that of parameter converters. -You specify the return converter like it was a return annotation on the -function itself, using ``->`` notation. - -For example: - -.. code-block:: c - - /*[clinic input] - add -> int - - a: int - b: int - / - - [clinic start generated code]*/ - -Return converters behave much the same as parameter converters; -they take arguments, the arguments are all keyword-only, and if you're not changing -any of the default arguments you can omit the parentheses. - -(If you use both ``"as"`` *and* a return converter for your function, -the ``"as"`` should come before the return converter.) - -There's one additional complication when using return converters: how do you -indicate an error has occurred? Normally, a function returns a valid (non-``NULL``) -pointer for success, and ``NULL`` for failure. But if you use an integer return converter, -all integers are valid. How can Argument Clinic detect an error? Its solution: each return -converter implicitly looks for a special value that indicates an error. If you return -that value, and an error has been set (c:func:`PyErr_Occurred` returns a true -value), then the generated code will propagate the error. Otherwise it will -encode the value you return like normal. - -Currently Argument Clinic supports only a few return converters: - -.. code-block:: none - - bool - double - float - int - long - Py_ssize_t - size_t - unsigned int - unsigned long - -None of these take parameters. -For all of these, return ``-1`` to indicate error. - -To see all the return converters Argument Clinic supports, along with -their parameters (if any), -just run ``Tools/clinic/clinic.py --converters`` for the full list. - - -How to clone existing functions -------------------------------- - -If you have a number of functions that look similar, you may be able to -use Clinic's "clone" feature. When you clone an existing function, -you reuse: - -* its parameters, including - - * their names, - - * their converters, with all parameters, - - * their default values, - - * their per-parameter docstrings, - - * their *kind* (whether they're positional only, - positional or keyword, or keyword only), and - -* its return converter. - -The only thing not copied from the original function is its docstring; -the syntax allows you to specify a new docstring. - -Here's the syntax for cloning a function:: - - /*[clinic input] - module.class.new_function [as c_basename] = module.class.existing_function - - Docstring for new_function goes here. - [clinic start generated code]*/ - -(The functions can be in different modules or classes. I wrote -``module.class`` in the sample just to illustrate that you must -use the full path to *both* functions.) - -Sorry, there's no syntax for partially cloning a function, or cloning a function -then modifying it. Cloning is an all-or nothing proposition. - -Also, the function you are cloning from must have been previously defined -in the current file. - - -How to call Python code ------------------------ - -The rest of the advanced topics require you to write Python code -which lives inside your C file and modifies Argument Clinic's -runtime state. This is simple: you simply define a Python block. - -A Python block uses different delimiter lines than an Argument -Clinic function block. It looks like this:: - - /*[python input] - # python code goes here - [python start generated code]*/ - -All the code inside the Python block is executed at the -time it's parsed. All text written to stdout inside the block -is redirected into the "output" after the block. - -As an example, here's a Python block that adds a static integer -variable to the C code:: - - /*[python input] - print('static int __ignored_unused_variable__ = 0;') - [python start generated code]*/ - static int __ignored_unused_variable__ = 0; - /*[python checksum:...]*/ - - -.. _clinic-howto-self-converter: - -How to use the "self converter" -------------------------------- - -Argument Clinic automatically adds a "self" parameter for you -using a default converter. It automatically sets the ``type`` -of this parameter to the "pointer to an instance" you specified -when you declared the type. However, you can override -Argument Clinic's converter and specify one yourself. -Just add your own *self* parameter as the first parameter in a -block, and ensure that its converter is an instance of -:class:`!self_converter` or a subclass thereof. - -What's the point? This lets you override the type of ``self``, -or give it a different default name. - -How do you specify the custom type you want to cast ``self`` to? -If you only have one or two functions with the same type for ``self``, -you can directly use Argument Clinic's existing ``self`` converter, -passing in the type you want to use as the *type* parameter:: - - /*[clinic input] - - _pickle.Pickler.dump - - self: self(type="PicklerObject *") - obj: object - / - - Write a pickled representation of the given object to the open file. - [clinic start generated code]*/ - -On the other hand, if you have a lot of functions that will use the same -type for ``self``, it's best to create your own converter, subclassing -:class:`!self_converter` but overwriting the :py:attr:`!type` member:: - - /*[python input] - class PicklerObject_converter(self_converter): - type = "PicklerObject *" - [python start generated code]*/ - - /*[clinic input] - - _pickle.Pickler.dump - - self: PicklerObject - obj: object - / - - Write a pickled representation of the given object to the open file. - [clinic start generated code]*/ - - -How to use the "defining class" converter ------------------------------------------ - -Argument Clinic facilitates gaining access to the defining class of a method. -This is useful for :ref:`heap type ` methods that need to fetch -module level state. Use :c:func:`PyType_FromModuleAndSpec` to associate a new -heap type with a module. You can now use :c:func:`PyType_GetModuleState` on -the defining class to fetch the module state, for example from a module method. - -Example from :source:`Modules/zlibmodule.c`. -First, ``defining_class`` is added to the clinic input:: - - /*[clinic input] - zlib.Compress.compress - - cls: defining_class - data: Py_buffer - Binary data to be compressed. - / - - -After running the Argument Clinic tool, the following function signature is -generated:: - - /*[clinic start generated code]*/ - static PyObject * - zlib_Compress_compress_impl(compobject *self, PyTypeObject *cls, - Py_buffer *data) - /*[clinic end generated code: output=6731b3f0ff357ca6 input=04d00f65ab01d260]*/ - - -The following code can now use ``PyType_GetModuleState(cls)`` to fetch the -module state:: - - zlibstate *state = PyType_GetModuleState(cls); - - -Each method may only have one argument using this converter, and it must appear -after ``self``, or, if ``self`` is not used, as the first argument. The argument -will be of type ``PyTypeObject *``. The argument will not appear in the -:py:attr:`!__text_signature__`. - -The ``defining_class`` converter is not compatible with :py:meth:`!__init__` -and :py:meth:`!__new__` methods, which cannot use the :c:macro:`METH_METHOD` -convention. - -It is not possible to use ``defining_class`` with slot methods. In order to -fetch the module state from such methods, use :c:func:`PyType_GetModuleByDef` -to look up the module and then :c:func:`PyModule_GetState` to fetch the module -state. Example from the ``setattro`` slot method in -:source:`Modules/_threadmodule.c`:: - - static int - local_setattro(localobject *self, PyObject *name, PyObject *v) - { - PyObject *module = PyType_GetModuleByDef(Py_TYPE(self), &thread_module); - thread_module_state *state = get_thread_state(module); - ... - } - - -See also :pep:`573`. - - -.. _clinic-howto-custom-converter: - -How to write a custom converter -------------------------------- - -A converter is a Python class that inherits from :py:class:`!CConverter`. -The main purpose of a custom converter, is for parameters parsed with -the ``O&`` format unit --- parsing such a parameter means calling -a :c:func:`PyArg_ParseTuple` "converter function". - -Your converter class should be named :samp:`{ConverterName}_converter`. -By following this convention, your converter class will be automatically -registered with Argument Clinic, with its *converter name* being the name of -your converter class with the ``_converter`` suffix stripped off. - -Instead of subclassing :py:meth:`!CConverter.__init__`, -write a :py:meth:`!converter_init` method. -Apart for the *self* parameter, all additional :py:meth:`!converter_init` -parameters **must** be keyword-only. -Any arguments passed to the converter in Argument Clinic -will be passed along to your :py:meth:`!converter_init` method. -See :py:class:`!CConverter` for a list of members you may wish to specify in -your subclass. - -.. module:: clinic - -.. class:: CConverter - - The base class for all converters. - See :ref:`clinic-howto-custom-converter` for how to subclass this class. - - .. attribute:: type - - The C type to use for this variable. - :attr:`!type` should be a Python string specifying the type, - e.g. ``'int'``. - If this is a pointer type, the type string should end with ``' *'``. - - .. attribute:: default - - The Python default value for this parameter, as a Python value. - Or the magic value ``unspecified`` if there is no default. - - .. attribute:: py_default - - :attr:`!default` as it should appear in Python code, - as a string. - Or ``None`` if there is no default. - - .. attribute:: c_default - - :attr:`!default` as it should appear in C code, - as a string. - Or ``None`` if there is no default. - - .. attribute:: c_ignored_default - - The default value used to initialize the C variable when - there is no default, but not specifying a default may - result in an "uninitialized variable" warning. This can - easily happen when using option groups—although - properly written code will never actually use this value, - the variable does get passed in to the impl, and the - C compiler will complain about the "use" of the - uninitialized value. This value should always be a - non-empty string. - - .. attribute:: converter - - The name of the C converter function, as a string. - - .. attribute:: impl_by_reference - - A boolean value. If true, - Argument Clinic will add a ``&`` in front of the name of - the variable when passing it into the impl function. - - .. attribute:: parse_by_reference - - A boolean value. If true, - Argument Clinic will add a ``&`` in front of the name of - the variable when passing it into :c:func:`PyArg_ParseTuple`. - - -Here's the simplest example of a custom converter, from :source:`Modules/zlibmodule.c`:: - - /*[python input] - - class ssize_t_converter(CConverter): - type = 'Py_ssize_t' - converter = 'ssize_t_converter' - - [python start generated code]*/ - /*[python end generated code: output=da39a3ee5e6b4b0d input=35521e4e733823c7]*/ - -This block adds a converter named ``ssize_t`` to Argument Clinic. -Parameters declared as ``ssize_t`` will be declared with type :c:type:`Py_ssize_t`, -and will be parsed by the ``'O&'`` format unit, -which will call the :c:func:`!ssize_t_converter` converter C function. -``ssize_t`` variables automatically support default values. - -More sophisticated custom converters can insert custom C code to -handle initialization and cleanup. -You can see more examples of custom converters in the CPython -source tree; grep the C files for the string ``CConverter``. - - -How to write a custom return converter --------------------------------------- - -Writing a custom return converter is much like writing -a custom converter. Except it's somewhat simpler, because return -converters are themselves much simpler. - -Return converters must subclass :py:class:`!CReturnConverter`. -There are no examples yet of custom return converters, -because they are not widely used yet. If you wish to -write your own return converter, please read :source:`Tools/clinic/clinic.py`, -specifically the implementation of :py:class:`!CReturnConverter` and -all its subclasses. - - -How to convert ``METH_O`` and ``METH_NOARGS`` functions -------------------------------------------------------- - -To convert a function using :c:macro:`METH_O`, make sure the function's -single argument is using the ``object`` converter, and mark the -arguments as positional-only:: - - /*[clinic input] - meth_o_sample - - argument: object - / - [clinic start generated code]*/ - - -To convert a function using :c:macro:`METH_NOARGS`, just don't specify -any arguments. - -You can still use a self converter, a return converter, and specify -a *type* argument to the object converter for :c:macro:`METH_O`. - - -How to convert ``tp_new`` and ``tp_init`` functions ---------------------------------------------------- - -You can convert :c:member:`~PyTypeObject.tp_new` and -:c:member:`~PyTypeObject.tp_init` functions. -Just name them ``__new__`` or ``__init__`` as appropriate. Notes: - -* The function name generated for ``__new__`` doesn't end in ``__new__`` - like it would by default. It's just the name of the class, converted - into a valid C identifier. - -* No :c:type:`PyMethodDef` ``#define`` is generated for these functions. - -* ``__init__`` functions return ``int``, not ``PyObject *``. - -* Use the docstring as the class docstring. - -* Although ``__new__`` and ``__init__`` functions must always - accept both the ``args`` and ``kwargs`` objects, when converting - you may specify any signature for these functions that you like. - (If your function doesn't support keywords, the parsing function - generated will throw an exception if it receives any.) - - -How to change and redirect Clinic's output ------------------------------------------- - -It can be inconvenient to have Clinic's output interspersed with -your conventional hand-edited C code. Luckily, Clinic is configurable: -you can buffer up its output for printing later (or earlier!), or write -its output to a separate file. You can also add a prefix or suffix to -every line of Clinic's generated output. - -While changing Clinic's output in this manner can be a boon to readability, -it may result in Clinic code using types before they are defined, or -your code attempting to use Clinic-generated code before it is defined. -These problems can be easily solved by rearranging the declarations in your file, -or moving where Clinic's generated code goes. (This is why the default behavior -of Clinic is to output everything into the current block; while many people -consider this hampers readability, it will never require rearranging your -code to fix definition-before-use problems.) - -Let's start with defining some terminology: - -*field* - A field, in this context, is a subsection of Clinic's output. - For example, the ``#define`` for the :c:type:`PyMethodDef` structure - is a field, called ``methoddef_define``. Clinic has seven - different fields it can output per function definition: - - .. code-block:: none - - docstring_prototype - docstring_definition - methoddef_define - impl_prototype - parser_prototype - parser_definition - impl_definition - - All the names are of the form ``"_"``, - where ``""`` is the semantic object represented (the parsing function, - the impl function, the docstring, or the methoddef structure) and ``""`` - represents what kind of statement the field is. Field names that end in - ``"_prototype"`` - represent forward declarations of that thing, without the actual body/data - of the thing; field names that end in ``"_definition"`` represent the actual - definition of the thing, with the body/data of the thing. (``"methoddef"`` - is special, it's the only one that ends with ``"_define"``, representing that - it's a preprocessor #define.) - -*destination* - A destination is a place Clinic can write output to. There are - five built-in destinations: - - ``block`` - The default destination: printed in the output section of - the current Clinic block. - - ``buffer`` - A text buffer where you can save text for later. Text sent - here is appended to the end of any existing text. It's an - error to have any text left in the buffer when Clinic finishes - processing a file. - - ``file`` - A separate "clinic file" that will be created automatically by Clinic. - The filename chosen for the file is ``{basename}.clinic{extension}``, - where ``basename`` and ``extension`` were assigned the output - from ``os.path.splitext()`` run on the current file. (Example: - the ``file`` destination for :file:`_pickle.c` would be written to - :file:`_pickle.clinic.c`.) - - **Important: When using a** ``file`` **destination, you** - *must check in* **the generated file!** - - ``two-pass`` - A buffer like ``buffer``. However, a two-pass buffer can only - be dumped once, and it prints out all text sent to it during - all processing, even from Clinic blocks *after* the dumping point. - - ``suppress`` - The text is suppressed—thrown away. - - -Clinic defines five new directives that let you reconfigure its output. - -The first new directive is ``dump``: - -.. code-block:: none - - dump - -This dumps the current contents of the named destination into the output of -the current block, and empties it. This only works with ``buffer`` and -``two-pass`` destinations. - -The second new directive is ``output``. The most basic form of ``output`` -is like this: - -.. code-block:: none - - output - -This tells Clinic to output *field* to *destination*. ``output`` also -supports a special meta-destination, called ``everything``, which tells -Clinic to output *all* fields to that *destination*. - -``output`` has a number of other functions: - -.. code-block:: none - - output push - output pop - output preset - - -``output push`` and ``output pop`` allow you to push and pop -configurations on an internal configuration stack, so that you -can temporarily modify the output configuration, then easily restore -the previous configuration. Simply push before your change to save -the current configuration, then pop when you wish to restore the -previous configuration. - -``output preset`` sets Clinic's output to one of several built-in -preset configurations, as follows: - - ``block`` - Clinic's original starting configuration. Writes everything - immediately after the input block. - - Suppress the ``parser_prototype`` - and ``docstring_prototype``, write everything else to ``block``. - - ``file`` - Designed to write everything to the "clinic file" that it can. - You then ``#include`` this file near the top of your file. - You may need to rearrange your file to make this work, though - usually this just means creating forward declarations for various - ``typedef`` and ``PyTypeObject`` definitions. - - Suppress the ``parser_prototype`` - and ``docstring_prototype``, write the ``impl_definition`` to - ``block``, and write everything else to ``file``. - - The default filename is ``"{dirname}/clinic/{basename}.h"``. - - ``buffer`` - Save up most of the output from Clinic, to be written into - your file near the end. For Python files implementing modules - or builtin types, it's recommended that you dump the buffer - just above the static structures for your module or - builtin type; these are normally very near the end. Using - ``buffer`` may require even more editing than ``file``, if - your file has static ``PyMethodDef`` arrays defined in the - middle of the file. - - Suppress the ``parser_prototype``, ``impl_prototype``, - and ``docstring_prototype``, write the ``impl_definition`` to - ``block``, and write everything else to ``file``. - - ``two-pass`` - Similar to the ``buffer`` preset, but writes forward declarations to - the ``two-pass`` buffer, and definitions to the ``buffer``. - This is similar to the ``buffer`` preset, but may require - less editing than ``buffer``. Dump the ``two-pass`` buffer - near the top of your file, and dump the ``buffer`` near - the end just like you would when using the ``buffer`` preset. - - Suppresses the ``impl_prototype``, write the ``impl_definition`` - to ``block``, write ``docstring_prototype``, ``methoddef_define``, - and ``parser_prototype`` to ``two-pass``, write everything else - to ``buffer``. - - ``partial-buffer`` - Similar to the ``buffer`` preset, but writes more things to ``block``, - only writing the really big chunks of generated code to ``buffer``. - This avoids the definition-before-use problem of ``buffer`` completely, - at the small cost of having slightly more stuff in the block's output. - Dump the ``buffer`` near the end, just like you would when using - the ``buffer`` preset. - - Suppresses the ``impl_prototype``, write the ``docstring_definition`` - and ``parser_definition`` to ``buffer``, write everything else to ``block``. - -The third new directive is ``destination``: - -.. code-block:: none - - destination [...] - -This performs an operation on the destination named ``name``. - -There are two defined subcommands: ``new`` and ``clear``. - -The ``new`` subcommand works like this: - -.. code-block:: none - - destination new - -This creates a new destination with name ```` and type ````. - -There are five destination types: - - ``suppress`` - Throws the text away. - - ``block`` - Writes the text to the current block. This is what Clinic - originally did. - - ``buffer`` - A simple text buffer, like the "buffer" builtin destination above. - - ``file`` - A text file. The file destination takes an extra argument, - a template to use for building the filename, like so: - - destination new - - The template can use three strings internally that will be replaced - by bits of the filename: - - {path} - The full path to the file, including directory and full filename. - {dirname} - The name of the directory the file is in. - {basename} - Just the name of the file, not including the directory. - {basename_root} - Basename with the extension clipped off - (everything up to but not including the last '.'). - {basename_extension} - The last '.' and everything after it. If the basename - does not contain a period, this will be the empty string. - - If there are no periods in the filename, {basename} and {filename} - are the same, and {extension} is empty. "{basename}{extension}" - is always exactly the same as "{filename}"." - - ``two-pass`` - A two-pass buffer, like the "two-pass" builtin destination above. - - -The ``clear`` subcommand works like this: - -.. code-block:: none - - destination clear - -It removes all the accumulated text up to this point in the destination. -(I don't know what you'd need this for, but I thought maybe it'd be -useful while someone's experimenting.) - -The fourth new directive is ``set``: - -.. code-block:: none - - set line_prefix "string" - set line_suffix "string" - -``set`` lets you set two internal variables in Clinic. -``line_prefix`` is a string that will be prepended to every line of Clinic's output; -``line_suffix`` is a string that will be appended to every line of Clinic's output. - -Both of these support two format strings: - - ``{block comment start}`` - Turns into the string ``/*``, the start-comment text sequence for C files. - - ``{block comment end}`` - Turns into the string ``*/``, the end-comment text sequence for C files. - -The final new directive is one you shouldn't need to use directly, -called ``preserve``: - -.. code-block:: none - - preserve - -This tells Clinic that the current contents of the output should be kept, unmodified. -This is used internally by Clinic when dumping output into ``file`` files; wrapping -it in a Clinic block lets Clinic use its existing checksum functionality to ensure -the file was not modified by hand before it gets overwritten. - - -How to use the ``#ifdef`` trick -------------------------------- - -If you're converting a function that isn't available on all platforms, -there's a trick you can use to make life a little easier. The existing -code probably looks like this:: - - #ifdef HAVE_FUNCTIONNAME - static module_functionname(...) - { - ... - } - #endif /* HAVE_FUNCTIONNAME */ - -And then in the ``PyMethodDef`` structure at the bottom the existing code -will have: - -.. code-block:: none - - #ifdef HAVE_FUNCTIONNAME - {'functionname', ... }, - #endif /* HAVE_FUNCTIONNAME */ - -In this scenario, you should enclose the body of your impl function inside the ``#ifdef``, -like so:: - - #ifdef HAVE_FUNCTIONNAME - /*[clinic input] - module.functionname - ... - [clinic start generated code]*/ - static module_functionname(...) - { - ... - } - #endif /* HAVE_FUNCTIONNAME */ - -Then, remove those three lines from the :c:type:`PyMethodDef` structure, -replacing them with the macro Argument Clinic generated: - -.. code-block:: none - - MODULE_FUNCTIONNAME_METHODDEF - -(You can find the real name for this macro inside the generated code. -Or you can calculate it yourself: it's the name of your function as defined -on the first line of your block, but with periods changed to underscores, -uppercased, and ``"_METHODDEF"`` added to the end.) - -Perhaps you're wondering: what if ``HAVE_FUNCTIONNAME`` isn't defined? -The ``MODULE_FUNCTIONNAME_METHODDEF`` macro won't be defined either! - -Here's where Argument Clinic gets very clever. It actually detects that the -Argument Clinic block might be deactivated by the ``#ifdef``. When that -happens, it generates a little extra code that looks like this:: - - #ifndef MODULE_FUNCTIONNAME_METHODDEF - #define MODULE_FUNCTIONNAME_METHODDEF - #endif /* !defined(MODULE_FUNCTIONNAME_METHODDEF) */ - -That means the macro always works. If the function is defined, this turns -into the correct structure, including the trailing comma. If the function is -undefined, this turns into nothing. - -However, this causes one ticklish problem: where should Argument Clinic put this -extra code when using the "block" output preset? It can't go in the output block, -because that could be deactivated by the ``#ifdef``. (That's the whole point!) - -In this situation, Argument Clinic writes the extra code to the "buffer" destination. -This may mean that you get a complaint from Argument Clinic: - -.. code-block:: none - - Warning in file "Modules/posixmodule.c" on line 12357: - Destination buffer 'buffer' not empty at end of file, emptying. - -When this happens, just open your file, find the ``dump buffer`` block that -Argument Clinic added to your file (it'll be at the very bottom), then -move it above the :c:type:`PyMethodDef` structure where that macro is used. - - -How to use Argument Clinic in Python files ------------------------------------------- - -It's actually possible to use Argument Clinic to preprocess Python files. -There's no point to using Argument Clinic blocks, of course, as the output -wouldn't make any sense to the Python interpreter. But using Argument Clinic -to run Python blocks lets you use Python as a Python preprocessor! - -Since Python comments are different from C comments, Argument Clinic -blocks embedded in Python files look slightly different. They look like this: - -.. code-block:: python3 - - #/*[python input] - #print("def foo(): pass") - #[python start generated code]*/ - def foo(): pass - #/*[python checksum:...]*/ + The Argument Clinic How-TO has been moved to the `Python Developer's Guide + `__. diff --git a/Doc/howto/descriptor.rst b/Doc/howto/descriptor.rst index 1d9424cb735a46..75346f2c7618c2 100644 --- a/Doc/howto/descriptor.rst +++ b/Doc/howto/descriptor.rst @@ -521,11 +521,11 @@ everyday Python programs. Descriptor protocol ------------------- -``descr.__get__(self, obj, type=None) -> value`` +``descr.__get__(self, obj, type=None)`` -``descr.__set__(self, obj, value) -> None`` +``descr.__set__(self, obj, value)`` -``descr.__delete__(self, obj) -> None`` +``descr.__delete__(self, obj)`` That is all there is to it. Define any of these methods and an object is considered a descriptor and can override default behavior upon being looked up @@ -943,6 +943,10 @@ it can be updated: >>> Movie('Star Wars').director 'J.J. Abrams' +.. testcleanup:: + + conn.close() + Pure Python Equivalents ^^^^^^^^^^^^^^^^^^^^^^^ @@ -1009,17 +1013,23 @@ here is a pure Python equivalent: if obj is None: return self if self.fget is None: - raise AttributeError(f"property '{self._name}' has no getter") + raise AttributeError( + f'property {self._name!r} of {type(obj).__name__!r} object has no getter' + ) return self.fget(obj) def __set__(self, obj, value): if self.fset is None: - raise AttributeError(f"property '{self._name}' has no setter") + raise AttributeError( + f'property {self._name!r} of {type(obj).__name__!r} object has no setter' + ) self.fset(obj, value) def __delete__(self, obj): if self.fdel is None: - raise AttributeError(f"property '{self._name}' has no deleter") + raise AttributeError( + f'property {self._name!r} of {type(obj).__name__!r} object has no deleter' + ) self.fdel(obj) def getter(self, fget): @@ -1050,6 +1060,11 @@ here is a pure Python equivalent: def delx(self): del self.__x x = Property(getx, setx, delx, "I'm the 'x' property.") + no_getter = Property(None, setx, delx, "I'm the 'x' property.") + no_setter = Property(getx, None, delx, "I'm the 'x' property.") + no_deleter = Property(getx, setx, None, "I'm the 'x' property.") + no_doc = Property(getx, setx, delx, None) + # Now do it again but use the decorator style @@ -1088,6 +1103,32 @@ here is a pure Python equivalent: >>> hasattr(ccc, 'x') False + >>> cc = CC() + >>> cc.x = 33 + >>> try: + ... cc.no_getter + ... except AttributeError as e: + ... e.args[0] + ... + "property 'no_getter' of 'CC' object has no getter" + + >>> try: + ... cc.no_setter = 33 + ... except AttributeError as e: + ... e.args[0] + ... + "property 'no_setter' of 'CC' object has no setter" + + >>> try: + ... del cc.no_deleter + ... except AttributeError as e: + ... e.args[0] + ... + "property 'no_deleter' of 'CC' object has no deleter" + + >>> CC.no_doc.__doc__ is None + True + The :func:`property` builtin helps whenever a user interface has granted attribute access and then subsequent changes require the intervention of a method. @@ -1141,6 +1182,16 @@ roughly equivalent to: obj = self.__self__ return func(obj, *args, **kwargs) + def __getattribute__(self, name): + "Emulate method_getset() in Objects/classobject.c" + if name == '__doc__': + return self.__func__.__doc__ + return object.__getattribute__(self, name) + + def __getattr__(self, name): + "Emulate method_getattro() in Objects/classobject.c" + return getattr(self.__func__, name) + To support automatic creation of methods, functions include the :meth:`__get__` method for binding methods during attribute access. This means that functions are non-data descriptors that return bound methods @@ -1199,7 +1250,7 @@ instance:: >>> d.f.__self__ - <__main__.D object at 0x1012e1f98> + <__main__.D object at 0x00B18C90> If you have ever wondered where *self* comes from in regular methods or where *cls* comes from in class methods, this is it! @@ -1291,7 +1342,8 @@ Using the non-data descriptor protocol, a pure Python version of The :func:`functools.update_wrapper` call adds a ``__wrapped__`` attribute that refers to the underlying function. Also it carries forward the attributes necessary to make the wrapper look like the wrapped -function: ``__name__``, ``__qualname__``, ``__doc__``, and ``__annotations__``. +function: :attr:`~function.__name__`, :attr:`~function.__qualname__`, +:attr:`~function.__doc__`, and :attr:`~function.__annotations__`. .. testcode:: :hide: @@ -1420,10 +1472,6 @@ Using the non-data descriptor protocol, a pure Python version of def __get__(self, obj, cls=None): if cls is None: cls = type(obj) - if hasattr(type(self.f), '__get__'): - # This code path was added in Python 3.9 - # and was deprecated in Python 3.11. - return self.f.__get__(cls, cls) return MethodType(self.f, cls) .. testcode:: @@ -1436,11 +1484,6 @@ Using the non-data descriptor protocol, a pure Python version of "Class method that returns a tuple" return (cls.__name__, x, y) - @ClassMethod - @property - def __doc__(cls): - return f'A doc for {cls.__name__!r}' - .. doctest:: :hide: @@ -1453,10 +1496,6 @@ Using the non-data descriptor protocol, a pure Python version of >>> t.cm(11, 22) ('T', 11, 22) - # Check the alternate path for chained descriptors - >>> T.__doc__ - "A doc for 'T'" - # Verify that T uses our emulation >>> type(vars(T)['cm']).__name__ 'ClassMethod' @@ -1481,29 +1520,12 @@ Using the non-data descriptor protocol, a pure Python version of ('T', 11, 22) -The code path for ``hasattr(type(self.f), '__get__')`` was added in -Python 3.9 and makes it possible for :func:`classmethod` to support -chained decorators. For example, a classmethod and property could be -chained together. In Python 3.11, this functionality was deprecated. - -.. testcode:: - - class G: - @classmethod - @property - def __doc__(cls): - return f'A doc for {cls.__name__!r}' - -.. doctest:: - - >>> G.__doc__ - "A doc for 'G'" - The :func:`functools.update_wrapper` call in ``ClassMethod`` adds a ``__wrapped__`` attribute that refers to the underlying function. Also it carries forward the attributes necessary to make the wrapper look -like the wrapped function: ``__name__``, ``__qualname__``, ``__doc__``, -and ``__annotations__``. +like the wrapped function: :attr:`~function.__name__`, +:attr:`~function.__qualname__`, :attr:`~function.__doc__`, +and :attr:`~function.__annotations__`. Member objects and __slots__ diff --git a/Doc/howto/enum.rst b/Doc/howto/enum.rst index 4312b4c8140f5c..1e9ac9b6761b64 100644 --- a/Doc/howto/enum.rst +++ b/Doc/howto/enum.rst @@ -426,10 +426,17 @@ enumeration, with the exception of special methods (:meth:`__str__`, :meth:`__add__`, etc.), descriptors (methods are also descriptors), and variable names listed in :attr:`_ignore_`. -Note: if your enumeration defines :meth:`__new__` and/or :meth:`__init__` then +Note: if your enumeration defines :meth:`__new__` and/or :meth:`__init__`, any value(s) given to the enum member will be passed into those methods. See `Planet`_ for an example. +.. note:: + + The :meth:`__new__` method, if defined, is used during creation of the Enum + members; it is then replaced by Enum's :meth:`__new__` which is used after + class creation for lookup of existing members. See :ref:`new-vs-init` for + more details. + Restricted Enum subclassing --------------------------- @@ -476,6 +483,7 @@ Dataclass support When inheriting from a :class:`~dataclasses.dataclass`, the :meth:`~Enum.__repr__` omits the inherited class' name. For example:: + >>> from dataclasses import dataclass, field >>> @dataclass ... class CreatureDataMixin: ... size: str @@ -520,7 +528,8 @@ It is possible to modify how enum members are pickled/unpickled by defining :meth:`__reduce_ex__` in the enumeration class. The default method is by-value, but enums with complicated values may want to use by-name:: - >>> class MyEnum(Enum): + >>> import enum + >>> class MyEnum(enum.Enum): ... __reduce_ex__ = enum.pickle_by_enum_name .. note:: @@ -598,9 +607,9 @@ The complete signature is:: start=1, ) -:value: What the new enum class will record as its name. +* *value*: What the new enum class will record as its name. -:names: The enum members. This can be a whitespace- or comma-separated string +* *names*: The enum members. This can be a whitespace- or comma-separated string (values will start at 1 unless otherwise specified):: 'RED GREEN BLUE' | 'RED,GREEN,BLUE' | 'RED, GREEN, BLUE' @@ -617,13 +626,13 @@ The complete signature is:: {'CHARTREUSE': 7, 'SEA_GREEN': 11, 'ROSEMARY': 42} -:module: name of module where new enum class can be found. +* *module*: name of module where new enum class can be found. -:qualname: where in module new enum class can be found. +* *qualname*: where in module new enum class can be found. -:type: type to mix in to new enum class. +* *type*: type to mix in to new enum class. -:start: number to start counting at if only names are passed in. +* *start*: number to start counting at if only names are passed in. .. versionchanged:: 3.5 The *start* parameter was added. @@ -763,7 +772,7 @@ be combined with them (but may lose :class:`IntFlag` membership:: >>> Perm.X | 4 - >>> Perm.X | 8 + >>> Perm.X + 8 9 .. note:: @@ -859,7 +868,7 @@ Others While :class:`IntEnum` is part of the :mod:`enum` module, it would be very simple to implement independently:: - class IntEnum(int, Enum): + class IntEnum(int, ReprEnum): # or Enum instead of ReprEnum pass This demonstrates how similar derived enumerations can be defined; for example @@ -867,8 +876,8 @@ a :class:`FloatEnum` that mixes in :class:`float` instead of :class:`int`. Some rules: -1. When subclassing :class:`Enum`, mix-in types must appear before - :class:`Enum` itself in the sequence of bases, as in the :class:`IntEnum` +1. When subclassing :class:`Enum`, mix-in types must appear before the + :class:`Enum` class itself in the sequence of bases, as in the :class:`IntEnum` example above. 2. Mix-in types must be subclassable. For example, :class:`bool` and :class:`range` are not subclassable and will throw an error during Enum @@ -895,6 +904,8 @@ Some rules: :meth:`__str__` method has been reset to their data types' :meth:`__str__` method. +.. _new-vs-init: + When to use :meth:`__new__` vs. :meth:`__init__` ------------------------------------------------ @@ -927,6 +938,11 @@ want one of them to be the value:: >>> print(Coordinate(3)) Coordinate.VY +.. warning:: + + *Do not* call ``super().__new__()``, as the lookup-only ``__new__`` is the one + that is found; instead, use the data type directly. + Finer Points ^^^^^^^^^^^^ @@ -945,30 +961,34 @@ all the members are created it is no longer used. Supported ``_sunder_`` names """""""""""""""""""""""""""" -- ``_name_`` -- name of the member -- ``_value_`` -- value of the member; can be set / modified in ``__new__`` +- :attr:`~Enum._name_` -- name of the member +- :attr:`~Enum._value_` -- value of the member; can be set in ``__new__`` +- :meth:`~Enum._missing_` -- a lookup function used when a value is not found; + may be overridden +- :attr:`~Enum._ignore_` -- a list of names, either as a :class:`list` or a + :class:`str`, that will not be transformed into members, and will be removed + from the final class +- :meth:`~Enum._generate_next_value_` -- used to get an appropriate value for + an enum member; may be overridden +- :meth:`~Enum._add_alias_` -- adds a new name as an alias to an existing + member. +- :meth:`~Enum._add_value_alias_` -- adds a new value as an alias to an + existing member. See `MultiValueEnum`_ for an example. -- ``_missing_`` -- a lookup function used when a value is not found; may be - overridden -- ``_ignore_`` -- a list of names, either as a :class:`list` or a :class:`str`, - that will not be transformed into members, and will be removed from the final - class -- ``_order_`` -- used in Python 2/3 code to ensure member order is consistent - (class attribute, removed during class creation) -- ``_generate_next_value_`` -- used by the `Functional API`_ and by - :class:`auto` to get an appropriate value for an enum member; may be - overridden + .. note:: -.. note:: + For standard :class:`Enum` classes the next value chosen is the highest + value seen incremented by one. - For standard :class:`Enum` classes the next value chosen is the last value seen - incremented by one. + For :class:`Flag` classes the next value chosen will be the next highest + power-of-two. - For :class:`Flag` classes the next value chosen will be the next highest - power-of-two, regardless of the last value seen. + .. versionchanged:: 3.13 + Prior versions would use the last seen value instead of the highest value. .. versionadded:: 3.6 ``_missing_``, ``_order_``, ``_generate_next_value_`` .. versionadded:: 3.7 ``_ignore_`` +.. versionadded:: 3.13 ``_add_alias_``, ``_add_value_alias_`` To help keep Python 2 / Python 3 code in sync an :attr:`_order_` attribute can be provided. It will be checked against the actual order of the enumeration @@ -1142,13 +1162,14 @@ the following are true: There is a new boundary mechanism that controls how out-of-range / invalid bits are handled: ``STRICT``, ``CONFORM``, ``EJECT``, and ``KEEP``: - * STRICT --> raises an exception when presented with invalid values - * CONFORM --> discards any invalid bits - * EJECT --> lose Flag status and become a normal int with the given value - * KEEP --> keep the extra bits - - keeps Flag status and extra bits - - extra bits do not show up in iteration - - extra bits do show up in repr() and str() +* STRICT --> raises an exception when presented with invalid values +* CONFORM --> discards any invalid bits +* EJECT --> lose Flag status and become a normal int with the given value +* KEEP --> keep the extra bits + + - keeps Flag status and extra bits + - extra bits do not show up in iteration + - extra bits do show up in repr() and str() The default for Flag is ``STRICT``, the default for ``IntFlag`` is ``EJECT``, and the default for ``_convert_`` is ``KEEP`` (see ``ssl.Options`` for an @@ -1353,6 +1374,13 @@ to handle any extra arguments:: members; it is then replaced by Enum's :meth:`__new__` which is used after class creation for lookup of existing members. +.. warning:: + + *Do not* call ``super().__new__()``, as the lookup-only ``__new__`` is the one + that is found; instead, use the data type directly -- e.g.:: + + obj = int.__new__(cls, value) + OrderedEnum ^^^^^^^^^^^ @@ -1413,7 +1441,7 @@ alias:: ... GRENE = 2 ... Traceback (most recent call last): - ... + ... ValueError: aliases not allowed in DuplicateFreeEnum: 'GRENE' --> 'GREEN' .. note:: @@ -1423,6 +1451,29 @@ alias:: disallowing aliases, the :func:`unique` decorator can be used instead. +MultiValueEnum +^^^^^^^^^^^^^^^^^ + +Supports having more than one value per member:: + + >>> class MultiValueEnum(Enum): + ... def __new__(cls, value, *values): + ... self = object.__new__(cls) + ... self._value_ = value + ... for v in values: + ... self._add_value_alias_(v) + ... return self + ... + >>> class DType(MultiValueEnum): + ... float32 = 'f', 8 + ... double64 = 'd', 9 + ... + >>> DType('f') + + >>> DType(9) + + + Planet ^^^^^^ diff --git a/Doc/howto/index.rst b/Doc/howto/index.rst index f521276a5a83c5..a835bb5f13bd1c 100644 --- a/Doc/howto/index.rst +++ b/Doc/howto/index.rst @@ -28,9 +28,9 @@ Currently, the HOWTOs are: urllib2.rst argparse.rst ipaddress.rst - clinic.rst instrumentation.rst perf_profiling.rst annotations.rst isolating-extensions.rst + timerfd.rst diff --git a/Doc/howto/instrumentation.rst b/Doc/howto/instrumentation.rst index 875f846aad0051..9c99fcecce1fcb 100644 --- a/Doc/howto/instrumentation.rst +++ b/Doc/howto/instrumentation.rst @@ -13,9 +13,9 @@ DTrace and SystemTap are monitoring tools, each providing a way to inspect what the processes on a computer system are doing. They both use domain-specific languages allowing a user to write scripts which: - - filter which processes are to be observed - - gather data from the processes of interest - - generate reports on the data +- filter which processes are to be observed +- gather data from the processes of interest +- generate reports on the data As of Python 3.6, CPython can be built with embedded "markers", also known as "probes", that can be observed by a DTrace or SystemTap script, @@ -246,11 +246,9 @@ The output looks like this: where the columns are: - - time in microseconds since start of script - - - name of executable - - - PID of process +- time in microseconds since start of script +- name of executable +- PID of process and the remainder indicates the call/return hierarchy as the script executes. diff --git a/Doc/howto/isolating-extensions.rst b/Doc/howto/isolating-extensions.rst index 2551fbe87b5c2a..e35855deedbe5f 100644 --- a/Doc/howto/isolating-extensions.rst +++ b/Doc/howto/isolating-extensions.rst @@ -64,7 +64,7 @@ Enter Per-Module State Instead of focusing on per-interpreter state, Python's C API is evolving to better support the more granular *per-module* state. -This means that C-level data is be attached to a *module object*. +This means that C-level data should be attached to a *module object*. Each interpreter creates its own module object, keeping the data separate. For testing the isolation, multiple module objects corresponding to a single extension can even be loaded in a single interpreter. @@ -337,14 +337,46 @@ That is, heap types should: - Have the :c:macro:`Py_TPFLAGS_HAVE_GC` flag. - Define a traverse function using ``Py_tp_traverse``, which - visits the type (e.g. using :c:expr:`Py_VISIT(Py_TYPE(self))`). + visits the type (e.g. using ``Py_VISIT(Py_TYPE(self))``). -Please refer to the :ref:`the documentation ` of +Please refer to the the documentation of :c:macro:`Py_TPFLAGS_HAVE_GC` and :c:member:`~PyTypeObject.tp_traverse` for additional considerations. -If your traverse function delegates to the ``tp_traverse`` of its base class -(or another type), ensure that ``Py_TYPE(self)`` is visited only once. +The API for defining heap types grew organically, leaving it +somewhat awkward to use in its current state. +The following sections will guide you through common issues. + + +``tp_traverse`` in Python 3.8 and lower +....................................... + +The requirement to visit the type from ``tp_traverse`` was added in Python 3.9. +If you support Python 3.8 and lower, the traverse function must *not* +visit the type, so it must be more complicated:: + + static int my_traverse(PyObject *self, visitproc visit, void *arg) + { + if (Py_Version >= 0x03090000) { + Py_VISIT(Py_TYPE(self)); + } + return 0; + } + +Unfortunately, :c:data:`Py_Version` was only added in Python 3.11. +As a replacement, use: + +* :c:macro:`PY_VERSION_HEX`, if not using the stable ABI, or +* :py:data:`sys.version_info` (via :c:func:`PySys_GetObject` and + :c:func:`PyArg_ParseTuple`). + + +Delegating ``tp_traverse`` +.......................... + +If your traverse function delegates to the :c:member:`~PyTypeObject.tp_traverse` +of its base class (or another type), ensure that ``Py_TYPE(self)`` is visited +only once. Note that only heap type are expected to visit the type in ``tp_traverse``. For example, if your traverse function includes:: @@ -356,11 +388,70 @@ For example, if your traverse function includes:: if (base->tp_flags & Py_TPFLAGS_HEAPTYPE) { // a heap type's tp_traverse already visited Py_TYPE(self) } else { - Py_VISIT(Py_TYPE(self)); + if (Py_Version >= 0x03090000) { + Py_VISIT(Py_TYPE(self)); + } } -It is not necessary to handle the type's reference count in ``tp_new`` -and ``tp_clear``. +It is not necessary to handle the type's reference count in +:c:member:`~PyTypeObject.tp_new` and :c:member:`~PyTypeObject.tp_clear`. + + +Defining ``tp_dealloc`` +....................... + +If your type has a custom :c:member:`~PyTypeObject.tp_dealloc` function, +it needs to: + +- call :c:func:`PyObject_GC_UnTrack` before any fields are invalidated, and +- decrement the reference count of the type. + +To keep the type valid while ``tp_free`` is called, the type's refcount needs +to be decremented *after* the instance is deallocated. For example:: + + static void my_dealloc(PyObject *self) + { + PyObject_GC_UnTrack(self); + ... + PyTypeObject *type = Py_TYPE(self); + type->tp_free(self); + Py_DECREF(type); + } + +The default ``tp_dealloc`` function does this, so +if your type does *not* override +``tp_dealloc`` you don't need to add it. + + +Not overriding ``tp_free`` +.......................... + +The :c:member:`~PyTypeObject.tp_free` slot of a heap type must be set to +:c:func:`PyObject_GC_Del`. +This is the default; do not override it. + + +Avoiding ``PyObject_New`` +......................... + +GC-tracked objects need to be allocated using GC-aware functions. + +If you use use :c:func:`PyObject_New` or :c:func:`PyObject_NewVar`: + +- Get and call type's :c:member:`~PyTypeObject.tp_alloc` slot, if possible. + That is, replace ``TYPE *o = PyObject_New(TYPE, typeobj)`` with:: + + TYPE *o = typeobj->tp_alloc(typeobj, 0); + + Replace ``o = PyObject_NewVar(TYPE, typeobj, size)`` with the same, + but use size instead of the 0. + +- If the above is not possible (e.g. inside a custom ``tp_alloc``), + call :c:func:`PyObject_GC_New` or :c:func:`PyObject_GC_NewVar`:: + + TYPE *o = PyObject_GC_New(TYPE, typeobj); + + TYPE *o = PyObject_GC_NewVar(TYPE, typeobj, size); Module State Access from Classes @@ -391,7 +482,7 @@ The largest roadblock is getting *the class a method was defined in*, or that method's "defining class" for short. The defining class can have a reference to the module it is part of. -Do not confuse the defining class with :c:expr:`Py_TYPE(self)`. If the method +Do not confuse the defining class with ``Py_TYPE(self)``. If the method is called on a *subclass* of your type, ``Py_TYPE(self)`` will refer to that subclass, which may be defined in different module than yours. diff --git a/Doc/howto/logging-cookbook.rst b/Doc/howto/logging-cookbook.rst index 6ef252d709e735..ea494f2fdbbce4 100644 --- a/Doc/howto/logging-cookbook.rst +++ b/Doc/howto/logging-cookbook.rst @@ -332,10 +332,10 @@ Suppose you configure logging with the following JSON: } } -This configuration does *almost* what we want, except that ``sys.stdout`` would -show messages of severity ``ERROR`` and above as well as ``INFO`` and -``WARNING`` messages. To prevent this, we can set up a filter which excludes -those messages and add it to the relevant handler. This can be configured by +This configuration does *almost* what we want, except that ``sys.stdout`` would show messages +of severity ``ERROR`` and only events of this severity and higher will be tracked +as well as ``INFO`` and ``WARNING`` messages. To prevent this, we can set up a filter which +excludes those messages and add it to the relevant handler. This can be configured by adding a ``filters`` section parallel to ``formatters`` and ``handlers``: .. code-block:: json @@ -761,7 +761,7 @@ printed on the console; on the server side, you should see something like: Note that there are some security issues with pickle in some scenarios. If these affect you, you can use an alternative serialization scheme by overriding -the :meth:`~handlers.SocketHandler.makePickle` method and implementing your +the :meth:`~SocketHandler.makePickle` method and implementing your alternative there, as well as adapting the above script to use your alternative serialization. @@ -835,6 +835,8 @@ To test these files, do the following in a POSIX environment: You may need to tweak the configuration files in the unlikely event that the configured ports clash with something else in your test environment. +.. currentmodule:: logging + .. _context-info: Adding contextual information to your logging output @@ -1546,7 +1548,7 @@ Sometimes you want to let a log file grow to a certain size, then open a new file and log to that. You may want to keep a certain number of these files, and when that many files have been created, rotate the files so that the number of files and the size of the files both remain bounded. For this usage pattern, the -logging package provides a :class:`~handlers.RotatingFileHandler`:: +logging package provides a :class:`RotatingFileHandler`:: import glob import logging @@ -1594,6 +1596,8 @@ and each time it reaches the size limit it is renamed with the suffix Obviously this example sets the log length much too small as an extreme example. You would want to set *maxBytes* to an appropriate value. +.. currentmodule:: logging + .. _format-styles: Use of alternative formatting styles @@ -1724,7 +1728,7 @@ when (and if) the logged message is actually about to be output to a log by a handler. So the only slightly unusual thing which might trip you up is that the parentheses go around the format string and the arguments, not just the format string. That's because the __ notation is just syntax sugar for a constructor -call to one of the XXXMessage classes. +call to one of the :samp:`{XXX}Message` classes. If you prefer, you can use a :class:`LoggerAdapter` to achieve a similar effect to the above, as in the following example:: @@ -1840,6 +1844,7 @@ However, it should be borne in mind that each link in the chain adds run-time overhead to all logging operations, and the technique should only be used when the use of a :class:`Filter` does not provide the desired result. +.. currentmodule:: logging.handlers .. _zeromq-handlers: @@ -1917,6 +1922,8 @@ of queues, for example a ZeroMQ 'subscribe' socket. Here's an example:: :ref:`A more advanced logging tutorial ` +.. currentmodule:: logging + An example dictionary-based configuration ----------------------------------------- @@ -2637,7 +2644,7 @@ when (and if) the logged message is actually about to be output to a log by a handler. So the only slightly unusual thing which might trip you up is that the parentheses go around the format string and the arguments, not just the format string. That’s because the __ notation is just syntax sugar for a constructor -call to one of the ``XXXMessage`` classes shown above. +call to one of the :samp:`{XXX}Message` classes shown above. .. _filters-dictconfig: @@ -3918,8 +3925,8 @@ that in other languages such as Java and C#, loggers are often static class attributes. However, this pattern doesn't make sense in Python, where the module (and not the class) is the unit of software decomposition. -Adding handlers other than :class:`NullHandler` to a logger in a library -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Adding handlers other than :class:`~logging.NullHandler` to a logger in a library +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Configuring logging by adding handlers, formatters and filters is the responsibility of the application developer, not the library developer. If you diff --git a/Doc/howto/logging.rst b/Doc/howto/logging.rst index a72e9a820ef347..f164b461c93b9c 100644 --- a/Doc/howto/logging.rst +++ b/Doc/howto/logging.rst @@ -89,9 +89,8 @@ described below (in increasing order of severity): | | itself may be unable to continue running. | +--------------+---------------------------------------------+ -The default level is ``WARNING``, which means that only events of this level -and above will be tracked, unless the logging package is configured to do -otherwise. +The default level is ``WARNING``, which means that only events of this severity and higher +will be tracked, unless the logging package is configured to do otherwise. Events that are tracked can be handled in different ways. The simplest way of handling tracked events is to print them to the console. Another common way @@ -979,7 +978,7 @@ provided: #. :class:`NullHandler` instances do nothing with error messages. They are used by library developers who want to use logging, but want to avoid the 'No - handlers could be found for logger XXX' message which can be displayed if + handlers could be found for logger *XXX*' message which can be displayed if the library user has not configured logging. See :ref:`library-config` for more information. diff --git a/Doc/howto/perf_profiling.rst b/Doc/howto/perf_profiling.rst index 61812c19ae6ca9..bb1c00e0aa51d5 100644 --- a/Doc/howto/perf_profiling.rst +++ b/Doc/howto/perf_profiling.rst @@ -97,7 +97,7 @@ Then we can use ``perf report`` to analyze the data: | | | | | |--2.97%--_PyObject_Malloc ... -As you can see, the Python functions are not shown in the output, only ``_Py_Eval_EvalFrameDefault`` +As you can see, the Python functions are not shown in the output, only ``_PyEval_EvalFrameDefault`` (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. @@ -162,8 +162,7 @@ the :option:`!-X` option takes precedence over the environment variable. Example, using the environment variable:: - $ PYTHONPERFSUPPORT=1 - $ python script.py + $ PYTHONPERFSUPPORT=1 python script.py $ perf report -g -i perf.data Example, using the :option:`!-X` option:: diff --git a/Doc/howto/pyporting.rst b/Doc/howto/pyporting.rst index baea3e85c3b84b..501b16d82d4d6f 100644 --- a/Doc/howto/pyporting.rst +++ b/Doc/howto/pyporting.rst @@ -1,49 +1,48 @@ .. _pyporting-howto: -********************************* -Porting Python 2 Code to Python 3 -********************************* +************************************* +How to port Python 2 Code to Python 3 +************************************* :author: Brett Cannon .. topic:: Abstract - With Python 3 being the future of Python while Python 2 is still in active - use, it is good to have your project available for both major releases of - Python. This guide is meant to help you figure out how best to support both - Python 2 & 3 simultaneously. + Python 2 reached its official end-of-life at the start of 2020. This means + that no new bug reports, fixes, or changes will be made to Python 2 - it's + no longer supported. + + This guide is intended to provide you with a path to Python 3 for your + code, that includes compatibility with Python 2 as a first step. If you are looking to port an extension module instead of pure Python code, please see :ref:`cporting-howto`. - If you would like to read one core Python developer's take on why Python 3 - came into existence, you can read Nick Coghlan's `Python 3 Q & A`_ or - Brett Cannon's `Why Python 3 exists`_. - + The archived python-porting_ mailing list may contain some useful guidance. - For help with porting, you can view the archived python-porting_ mailing list. The Short Explanation ===================== -To make your project be single-source Python 2/3 compatible, the basic steps +To achieve Python 2/3 compatibility in a single code base, the basic steps are: #. Only worry about supporting Python 2.7 #. Make sure you have good test coverage (coverage.py_ can help; ``python -m pip install coverage``) -#. Learn the differences between Python 2 & 3 +#. Learn the differences between Python 2 and 3 #. Use Futurize_ (or Modernize_) to update your code (e.g. ``python -m pip install future``) #. Use Pylint_ to help make sure you don't regress on your Python 3 support (``python -m pip install pylint``) #. Use caniusepython3_ to find out which of your dependencies are blocking your use of Python 3 (``python -m pip install caniusepython3``) #. Once your dependencies are no longer blocking you, use continuous integration - to make sure you stay compatible with Python 2 & 3 (tox_ can help test + to make sure you stay compatible with Python 2 and 3 (tox_ can help test against multiple versions of Python; ``python -m pip install tox``) -#. Consider using optional static type checking to make sure your type usage - works in both Python 2 & 3 (e.g. use mypy_ to check your typing under both - Python 2 & Python 3; ``python -m pip install mypy``). +#. Consider using optional :term:`static type checking ` + to make sure your type usage + works in both Python 2 and 3 (e.g. use mypy_ to check your typing under both + Python 2 and Python 3; ``python -m pip install mypy``). .. note:: @@ -55,43 +54,30 @@ are: Details ======= -A key point about supporting Python 2 & 3 simultaneously is that you can start -**today**! Even if your dependencies are not supporting Python 3 yet that does -not mean you can't modernize your code **now** to support Python 3. Most changes -required to support Python 3 lead to cleaner code using newer practices even in -Python 2 code. +Even if other factors - say, dependencies over which you have no control - +still require you to support Python 2, that does not prevent you taking the +step of including Python 3 support. -Another key point is that modernizing your Python 2 code to also support -Python 3 is largely automated for you. While you might have to make some API -decisions thanks to Python 3 clarifying text data versus binary data, the -lower-level work is now mostly done for you and thus can at least benefit from -the automated changes immediately. +Most changes required to support Python 3 lead to cleaner code using newer +practices even in Python 2 code. -Keep those key points in mind while you read on about the details of porting -your code to support Python 2 & 3 simultaneously. +Different versions of Python 2 +------------------------------ -Drop support for Python 2.6 and older -------------------------------------- +Ideally, your code should be compatible with Python 2.7, which was the +last supported version of Python 2. -While you can make Python 2.5 work with Python 3, it is **much** easier if you -only have to work with Python 2.7. If dropping Python 2.5 is not an -option then the six_ project can help you support Python 2.5 & 3 simultaneously -(``python -m pip install six``). Do realize, though, that nearly all the projects listed -in this HOWTO will not be available to you. +Some of the tools mentioned in this guide will not work with Python 2.6. -If you are able to skip Python 2.5 and older, then the required changes -to your code should continue to look and feel like idiomatic Python code. At -worst you will have to use a function instead of a method in some instances or -have to import a function instead of using a built-in one, but otherwise the -overall transformation should not feel foreign to you. +If absolutely necessary, the six_ project can help you support Python 2.5 and +3 simultaneously. Do realize, though, that nearly all the projects listed in +this guide will not be available to you. -But you should aim for only supporting Python 2.7. Python 2.6 is no longer -freely supported and thus is not receiving bugfixes. This means **you** will have -to work around any issues you come across with Python 2.6. There are also some -tools mentioned in this HOWTO which do not support Python 2.6 (e.g., Pylint_), -and this will become more commonplace as time goes on. It will simply be easier -for you if you only support the versions of Python that you have to support. +If you are able to skip Python 2.5 and older, the required changes to your +code will be minimal. At worst you will have to use a function instead of a +method in some instances or have to import a function instead of using a +built-in one. Make sure you specify the proper version support in your ``setup.py`` file @@ -118,62 +104,57 @@ coverage). If you don't already have a tool to measure test coverage then coverage.py_ is recommended. -Learn the differences between Python 2 & 3 -------------------------------------------- +Be aware of the differences between Python 2 and 3 +-------------------------------------------------- Once you have your code well-tested you are ready to begin porting your code to Python 3! But to fully understand how your code is going to change and what you want to look out for while you code, you will want to learn what changes -Python 3 makes in terms of Python 2. Typically the two best ways of doing that -is reading the :ref:`"What's New" ` doc for each release of Python 3 and the -`Porting to Python 3`_ book (which is free online). There is also a handy -`cheat sheet`_ from the Python-Future project. +Python 3 makes in terms of Python 2. + +Some resources for understanding the differences and their implications for you +code: + +* the :ref:`"What's New" ` doc for each release of Python 3 +* the `Porting to Python 3`_ book (which is free online) +* the handy `cheat sheet`_ from the Python-Future project. Update your code ---------------- -Once you feel like you know what is different in Python 3 compared to Python 2, -it's time to update your code! You have a choice between two tools in porting -your code automatically: Futurize_ and Modernize_. Which tool you choose will -depend on how much like Python 3 you want your code to be. Futurize_ does its -best to make Python 3 idioms and practices exist in Python 2, e.g. backporting -the ``bytes`` type from Python 3 so that you have semantic parity between the -major versions of Python. Modernize_, -on the other hand, is more conservative and targets a Python 2/3 subset of -Python, directly relying on six_ to help provide compatibility. As Python 3 is -the future, it might be best to consider Futurize to begin adjusting to any new -practices that Python 3 introduces which you are not accustomed to yet. - -Regardless of which tool you choose, they will update your code to run under -Python 3 while staying compatible with the version of Python 2 you started with. -Depending on how conservative you want to be, you may want to run the tool over -your test suite first and visually inspect the diff to make sure the -transformation is accurate. After you have transformed your test suite and -verified that all the tests still pass as expected, then you can transform your -application code knowing that any tests which fail is a translation failure. +There are tools available that can port your code automatically. + +Futurize_ does its best to make Python 3 idioms and practices exist in Python +2, e.g. backporting the ``bytes`` type from Python 3 so that you have +semantic parity between the major versions of Python. This is the better +approach for most cases. + +Modernize_, on the other hand, is more conservative and targets a Python 2/3 +subset of Python, directly relying on six_ to help provide compatibility. + +A good approach is to run the tool over your test suite first and visually +inspect the diff to make sure the transformation is accurate. After you have +transformed your test suite and verified that all the tests still pass as +expected, then you can transform your application code knowing that any tests +which fail is a translation failure. Unfortunately the tools can't automate everything to make your code work under -Python 3 and so there are a handful of things you will need to update manually -to get full Python 3 support (which of these steps are necessary vary between -the tools). Read the documentation for the tool you choose to use to see what it -fixes by default and what it can do optionally to know what will (not) be fixed -for you and what you may have to fix on your own (e.g. using ``io.open()`` over -the built-in ``open()`` function is off by default in Modernize). Luckily, -though, there are only a couple of things to watch out for which can be -considered large issues that may be hard to debug if not watched for. +Python 3, and you will also need to read the tools' documentation in case some +options you need are turned off by default. +Key issues to be aware of and check for: Division ++++++++ -In Python 3, ``5 / 2 == 2.5`` and not ``2``; all division between ``int`` values -result in a ``float``. This change has actually been planned since Python 2.2 -which was released in 2002. Since then users have been encouraged to add -``from __future__ import division`` to any and all files which use the ``/`` and -``//`` operators or to be running the interpreter with the ``-Q`` flag. If you -have not been doing this then you will need to go through your code and do two -things: +In Python 3, ``5 / 2 == 2.5`` and not ``2`` as it was in Python 2; all +division between ``int`` values result in a ``float``. This change has +actually been planned since Python 2.2 which was released in 2002. Since then +users have been encouraged to add ``from __future__ import division`` to any +and all files which use the ``/`` and ``//`` operators or to be running the +interpreter with the ``-Q`` flag. If you have not been doing this then you +will need to go through your code and do two things: #. Add ``from __future__ import division`` to your files #. Update any division operator as necessary to either use ``//`` to use floor @@ -197,30 +178,29 @@ specific type. This complicated the situation especially for anyone supporting multiple languages as APIs wouldn't bother explicitly supporting ``unicode`` when they claimed text data support. -To make the distinction between text and binary data clearer and more -pronounced, Python 3 did what most languages created in the age of the internet -have done and made text and binary data distinct types that cannot blindly be -mixed together (Python predates widespread access to the internet). For any code -that deals only with text or only binary data, this separation doesn't pose an -issue. But for code that has to deal with both, it does mean you might have to -now care about when you are using text compared to binary data, which is why -this cannot be entirely automated. - -To start, you will need to decide which APIs take text and which take binary -(it is **highly** recommended you don't design APIs that can take both due to -the difficulty of keeping the code working; as stated earlier it is difficult to -do well). In Python 2 this means making sure the APIs that take text can work -with ``unicode`` and those that work with binary data work with the -``bytes`` type from Python 3 (which is a subset of ``str`` in Python 2 and acts -as an alias for ``bytes`` type in Python 2). Usually the biggest issue is -realizing which methods exist on which types in Python 2 & 3 simultaneously -(for text that's ``unicode`` in Python 2 and ``str`` in Python 3, for binary -that's ``str``/``bytes`` in Python 2 and ``bytes`` in Python 3). The following -table lists the **unique** methods of each data type across Python 2 & 3 -(e.g., the ``decode()`` method is usable on the equivalent binary data type in -either Python 2 or 3, but it can't be used by the textual data type consistently -between Python 2 and 3 because ``str`` in Python 3 doesn't have the method). Do -note that as of Python 3.5 the ``__mod__`` method was added to the bytes type. +Python 3 made text and binary data distinct types that cannot simply be mixed +together. For any code that deals only with text or only binary data, this +separation doesn't pose an issue. But for code that has to deal with both, it +does mean you might have to now care about when you are using text compared +to binary data, which is why this cannot be entirely automated. + +Decide which APIs take text and which take binary (it is **highly** recommended +you don't design APIs that can take both due to the difficulty of keeping the +code working; as stated earlier it is difficult to do well). In Python 2 this +means making sure the APIs that take text can work with ``unicode`` and those +that work with binary data work with the ``bytes`` type from Python 3 +(which is a subset of ``str`` in Python 2 and acts as an alias for ``bytes`` +type in Python 2). Usually the biggest issue is realizing which methods exist +on which types in Python 2 and 3 simultaneously (for text that's ``unicode`` +in Python 2 and ``str`` in Python 3, for binary that's ``str``/``bytes`` in +Python 2 and ``bytes`` in Python 3). + +The following table lists the **unique** methods of each data type across +Python 2 and 3 (e.g., the ``decode()`` method is usable on the equivalent binary +data type in either Python 2 or 3, but it can't be used by the textual data +type consistently between Python 2 and 3 because ``str`` in Python 3 doesn't +have the method). Do note that as of Python 3.5 the ``__mod__`` method was +added to the bytes type. ======================== ===================== **Text data** **Binary data** @@ -246,12 +226,11 @@ having to keep track of what type of data you are working with. The next issue is making sure you know whether the string literals in your code represent text or binary data. You should add a ``b`` prefix to any literal that presents binary data. For text you should add a ``u`` prefix to -the text literal. (there is a :mod:`__future__` import to force all unspecified +the text literal. (There is a :mod:`__future__` import to force all unspecified literals to be Unicode, but usage has shown it isn't as effective as adding a ``b`` or ``u`` prefix to all literals explicitly) -As part of this dichotomy you also need to be careful about opening files. -Unless you have been working on Windows, there is a chance you have not always +You also need to be careful about opening files. Possibly you have not always bothered to add the ``b`` mode when opening a binary file (e.g., ``rb`` for binary reading). Under Python 3, binary files and text files are clearly distinct and mutually incompatible; see the :mod:`io` module for details. @@ -265,7 +244,7 @@ outdated practice of using :func:`codecs.open` as that's only necessary for keeping compatibility with Python 2.5. The constructors of both ``str`` and ``bytes`` have different semantics for the -same arguments between Python 2 & 3. Passing an integer to ``bytes`` in Python 2 +same arguments between Python 2 and 3. Passing an integer to ``bytes`` in Python 2 will give you the string representation of the integer: ``bytes(3) == '3'``. But in Python 3, an integer argument to ``bytes`` will give you a bytes object as long as the integer specified, filled with null bytes: @@ -400,7 +379,7 @@ Use continuous integration to stay compatible --------------------------------------------- Once you are able to fully run under Python 3 you will want to make sure your -code always works under both Python 2 & 3. Probably the best tool for running +code always works under both Python 2 and 3. Probably the best tool for running your tests under multiple Python interpreters is tox_. You can then integrate tox with your continuous integration system so that you never accidentally break Python 2 or 3 support. @@ -413,16 +392,11 @@ separation of text/binary data handling or indexing on bytes you wouldn't easily find the mistake. This flag will raise an exception when these kinds of comparisons occur, making the mistake much easier to track down. -And that's mostly it! At this point your code base is compatible with both -Python 2 and 3 simultaneously. Your testing will also be set up so that you -don't accidentally break Python 2 or 3 compatibility regardless of which version -you typically run your tests under while developing. - Consider using optional static type checking -------------------------------------------- -Another way to help port your code is to use a static type checker like +Another way to help port your code is to use a :term:`static type checker` like mypy_ or pytype_ on your code. These tools can be used to analyze your code as if it's being run under Python 2, then you can run the tool a second time as if your code is running under Python 3. By running a static type checker twice like diff --git a/Doc/howto/regex.rst b/Doc/howto/regex.rst index c19c48301f5848..5e2f9a9d1837fe 100644 --- a/Doc/howto/regex.rst +++ b/Doc/howto/regex.rst @@ -245,6 +245,9 @@ You can omit either *m* or *n*; in that case, a reasonable value is assumed for the missing value. Omitting *m* is interpreted as a lower limit of 0, while omitting *n* results in an upper bound of infinity. +The simplest case ``{m}`` matches the preceding item exactly *m* times. +For example, ``a/{2}b`` will only match ``'a//b'``. + Readers of a reductionist bent may notice that the three other quantifiers can all be expressed using this notation. ``{0,}`` is the same as ``*``, ``{1,}`` is equivalent to ``+``, and ``{0,1}`` is the same as ``?``. It's better to use diff --git a/Doc/howto/timerfd.rst b/Doc/howto/timerfd.rst new file mode 100644 index 00000000000000..98f0294f9d082d --- /dev/null +++ b/Doc/howto/timerfd.rst @@ -0,0 +1,230 @@ +.. _timerfd-howto: + +***************************** + timer file descriptor HOWTO +***************************** + +:Release: 1.13 + +This HOWTO discusses Python's support for the linux timer file descriptor. + + +Examples +======== + +The following example shows how to use a timer file descriptor +to execute a function twice a second: + +.. code-block:: python + + # Practical scripts should use really use a non-blocking timer, + # we use a blocking timer here for simplicity. + import os, time + + # Create the timer file descriptor + fd = os.timerfd_create(time.CLOCK_REALTIME) + + # Start the timer in 1 second, with an interval of half a second + os.timerfd_settime(fd, initial=1, interval=0.5) + + try: + # Process timer events four times. + for _ in range(4): + # read() will block until the timer expires + _ = os.read(fd, 8) + print("Timer expired") + finally: + # Remember to close the timer file descriptor! + os.close(fd) + +To avoid the precision loss caused by the :class:`float` type, +timer file descriptors allow specifying initial expiration and interval +in integer nanoseconds with ``_ns`` variants of the functions. + +This example shows how :func:`~select.epoll` can be used with timer file +descriptors to wait until the file descriptor is ready for reading: + +.. code-block:: python + + import os, time, select, socket, sys + + # Create an epoll object + ep = select.epoll() + + # In this example, use loopback address to send "stop" command to the server. + # + # $ telnet 127.0.0.1 1234 + # Trying 127.0.0.1... + # Connected to 127.0.0.1. + # Escape character is '^]'. + # stop + # Connection closed by foreign host. + # + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + sock.bind(("127.0.0.1", 1234)) + sock.setblocking(False) + sock.listen(1) + ep.register(sock, select.EPOLLIN) + + # Create timer file descriptors in non-blocking mode. + num = 3 + fds = [] + for _ in range(num): + fd = os.timerfd_create(time.CLOCK_REALTIME, flags=os.TFD_NONBLOCK) + fds.append(fd) + # Register the timer file descriptor for read events + ep.register(fd, select.EPOLLIN) + + # Start the timer with os.timerfd_settime_ns() in nanoseconds. + # Timer 1 fires every 0.25 seconds; timer 2 every 0.5 seconds; etc + for i, fd in enumerate(fds, start=1): + one_sec_in_nsec = 10**9 + i = i * one_sec_in_nsec + os.timerfd_settime_ns(fd, initial=i//4, interval=i//4) + + timeout = 3 + try: + conn = None + is_active = True + while is_active: + # Wait for the timer to expire for 3 seconds. + # epoll.poll() returns a list of (fd, event) pairs. + # fd is a file descriptor. + # sock and conn[=returned value of socket.accept()] are socket objects, not file descriptors. + # So use sock.fileno() and conn.fileno() to get the file descriptors. + events = ep.poll(timeout) + + # If more than one timer file descriptors are ready for reading at once, + # epoll.poll() returns a list of (fd, event) pairs. + # + # In this example settings, + # 1st timer fires every 0.25 seconds in 0.25 seconds. (0.25, 0.5, 0.75, 1.0, ...) + # 2nd timer every 0.5 seconds in 0.5 seconds. (0.5, 1.0, 1.5, 2.0, ...) + # 3rd timer every 0.75 seconds in 0.75 seconds. (0.75, 1.5, 2.25, 3.0, ...) + # + # In 0.25 seconds, only 1st timer fires. + # In 0.5 seconds, 1st timer and 2nd timer fires at once. + # In 0.75 seconds, 1st timer and 3rd timer fires at once. + # In 1.5 seconds, 1st timer, 2nd timer and 3rd timer fires at once. + # + # If a timer file descriptor is signaled more than once since + # the last os.read() call, os.read() returns the nubmer of signaled + # as host order of class bytes. + print(f"Signaled events={events}") + for fd, event in events: + if event & select.EPOLLIN: + if fd == sock.fileno(): + # Check if there is a connection request. + print(f"Accepting connection {fd}") + conn, addr = sock.accept() + conn.setblocking(False) + print(f"Accepted connection {conn} from {addr}") + ep.register(conn, select.EPOLLIN) + elif conn and fd == conn.fileno(): + # Check if there is data to read. + print(f"Reading data {fd}") + data = conn.recv(1024) + if data: + # You should catch UnicodeDecodeError exception for safety. + cmd = data.decode() + if cmd.startswith("stop"): + print(f"Stopping server") + is_active = False + else: + print(f"Unknown command: {cmd}") + else: + # No more data, close connection + print(f"Closing connection {fd}") + ep.unregister(conn) + conn.close() + conn = None + elif fd in fds: + print(f"Reading timer {fd}") + count = int.from_bytes(os.read(fd, 8), byteorder=sys.byteorder) + print(f"Timer {fds.index(fd) + 1} expired {count} times") + else: + print(f"Unknown file descriptor {fd}") + finally: + for fd in fds: + ep.unregister(fd) + os.close(fd) + ep.close() + +This example shows how :func:`~select.select` can be used with timer file +descriptors to wait until the file descriptor is ready for reading: + +.. code-block:: python + + import os, time, select, socket, sys + + # In this example, use loopback address to send "stop" command to the server. + # + # $ telnet 127.0.0.1 1234 + # Trying 127.0.0.1... + # Connected to 127.0.0.1. + # Escape character is '^]'. + # stop + # Connection closed by foreign host. + # + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + sock.bind(("127.0.0.1", 1234)) + sock.setblocking(False) + sock.listen(1) + + # Create timer file descriptors in non-blocking mode. + num = 3 + fds = [os.timerfd_create(time.CLOCK_REALTIME, flags=os.TFD_NONBLOCK) + for _ in range(num)] + select_fds = fds + [sock] + + # Start the timers with os.timerfd_settime() in seconds. + # Timer 1 fires every 0.25 seconds; timer 2 every 0.5 seconds; etc + for i, fd in enumerate(fds, start=1): + os.timerfd_settime(fd, initial=i/4, interval=i/4) + + timeout = 3 + try: + conn = None + is_active = True + while is_active: + # Wait for the timer to expire for 3 seconds. + # select.select() returns a list of file descriptors or objects. + rfd, wfd, xfd = select.select(select_fds, select_fds, select_fds, timeout) + for fd in rfd: + if fd == sock: + # Check if there is a connection request. + print(f"Accepting connection {fd}") + conn, addr = sock.accept() + conn.setblocking(False) + print(f"Accepted connection {conn} from {addr}") + select_fds.append(conn) + elif conn and fd == conn: + # Check if there is data to read. + print(f"Reading data {fd}") + data = conn.recv(1024) + if data: + # You should catch UnicodeDecodeError exception for safety. + cmd = data.decode() + if cmd.startswith("stop"): + print(f"Stopping server") + is_active = False + else: + print(f"Unknown command: {cmd}") + else: + # No more data, close connection + print(f"Closing connection {fd}") + select_fds.remove(conn) + conn.close() + conn = None + elif fd in fds: + print(f"Reading timer {fd}") + count = int.from_bytes(os.read(fd, 8), byteorder=sys.byteorder) + print(f"Timer {fds.index(fd) + 1} expired {count} times") + else: + print(f"Unknown file descriptor {fd}") + finally: + for fd in fds: + os.close(fd) + sock.close() + sock = None + diff --git a/Doc/howto/urllib2.rst b/Doc/howto/urllib2.rst index 86137fb38c9b93..570435d48866d3 100644 --- a/Doc/howto/urllib2.rst +++ b/Doc/howto/urllib2.rst @@ -194,11 +194,11 @@ which comes after we have a look at what happens when things go wrong. Handling Exceptions =================== -*urlopen* raises :exc:`URLError` when it cannot handle a response (though as +*urlopen* raises :exc:`~urllib.error.URLError` when it cannot handle a response (though as usual with Python APIs, built-in exceptions such as :exc:`ValueError`, :exc:`TypeError` etc. may also be raised). -:exc:`HTTPError` is the subclass of :exc:`URLError` raised in the specific case of +:exc:`~urllib.error.HTTPError` is the subclass of :exc:`~urllib.error.URLError` raised in the specific case of HTTP URLs. The exception classes are exported from the :mod:`urllib.error` module. @@ -229,12 +229,12 @@ the status code indicates that the server is unable to fulfil the request. The default handlers will handle some of these responses for you (for example, if the response is a "redirection" that requests the client fetch the document from a different URL, urllib will handle that for you). For those it can't handle, -urlopen will raise an :exc:`HTTPError`. Typical errors include '404' (page not +urlopen will raise an :exc:`~urllib.error.HTTPError`. Typical errors include '404' (page not found), '403' (request forbidden), and '401' (authentication required). See section 10 of :rfc:`2616` for a reference on all the HTTP error codes. -The :exc:`HTTPError` instance raised will have an integer 'code' attribute, which +The :exc:`~urllib.error.HTTPError` instance raised will have an integer 'code' attribute, which corresponds to the error sent by the server. Error Codes @@ -317,7 +317,7 @@ dictionary is reproduced here for convenience :: } When an error is raised the server responds by returning an HTTP error code -*and* an error page. You can use the :exc:`HTTPError` instance as a response on the +*and* an error page. You can use the :exc:`~urllib.error.HTTPError` instance as a response on the page returned. This means that as well as the code attribute, it also has read, geturl, and info, methods as returned by the ``urllib.response`` module:: @@ -338,7 +338,7 @@ geturl, and info, methods as returned by the ``urllib.response`` module:: Wrapping it Up -------------- -So if you want to be prepared for :exc:`HTTPError` *or* :exc:`URLError` there are two +So if you want to be prepared for :exc:`~urllib.error.HTTPError` *or* :exc:`~urllib.error.URLError` there are two basic approaches. I prefer the second approach. Number 1 @@ -365,7 +365,7 @@ Number 1 .. note:: The ``except HTTPError`` *must* come first, otherwise ``except URLError`` - will *also* catch an :exc:`HTTPError`. + will *also* catch an :exc:`~urllib.error.HTTPError`. Number 2 ~~~~~~~~ @@ -391,7 +391,7 @@ Number 2 info and geturl =============== -The response returned by urlopen (or the :exc:`HTTPError` instance) has two +The response returned by urlopen (or the :exc:`~urllib.error.HTTPError` instance) has two useful methods :meth:`info` and :meth:`geturl` and is defined in the module :mod:`urllib.response`.. diff --git a/Doc/includes/custom.c b/Doc/includes/newtypes/custom.c similarity index 100% rename from Doc/includes/custom.c rename to Doc/includes/newtypes/custom.c diff --git a/Doc/includes/custom2.c b/Doc/includes/newtypes/custom2.c similarity index 100% rename from Doc/includes/custom2.c rename to Doc/includes/newtypes/custom2.c diff --git a/Doc/includes/custom3.c b/Doc/includes/newtypes/custom3.c similarity index 100% rename from Doc/includes/custom3.c rename to Doc/includes/newtypes/custom3.c diff --git a/Doc/includes/custom4.c b/Doc/includes/newtypes/custom4.c similarity index 100% rename from Doc/includes/custom4.c rename to Doc/includes/newtypes/custom4.c diff --git a/Doc/includes/newtypes/pyproject.toml b/Doc/includes/newtypes/pyproject.toml new file mode 100644 index 00000000000000..ea7937a3171473 --- /dev/null +++ b/Doc/includes/newtypes/pyproject.toml @@ -0,0 +1,7 @@ +[build-system] +requires = ["setuptools"] +build-backend = "setuptools.build_meta" + +[project] +name = "custom" +version = "1" diff --git a/Doc/includes/newtypes/setup.py b/Doc/includes/newtypes/setup.py new file mode 100644 index 00000000000000..67f83673bcc657 --- /dev/null +++ b/Doc/includes/newtypes/setup.py @@ -0,0 +1,8 @@ +from setuptools import Extension, setup +setup(ext_modules=[ + Extension("custom", ["custom.c"]), + Extension("custom2", ["custom2.c"]), + Extension("custom3", ["custom3.c"]), + Extension("custom4", ["custom4.c"]), + Extension("sublist", ["sublist.c"]), +]) diff --git a/Doc/includes/sublist.c b/Doc/includes/newtypes/sublist.c similarity index 100% rename from Doc/includes/sublist.c rename to Doc/includes/newtypes/sublist.c diff --git a/Doc/includes/test.py b/Doc/includes/newtypes/test.py similarity index 94% rename from Doc/includes/test.py rename to Doc/includes/newtypes/test.py index 09ebe3fec0bdbe..55a5cf9f68b94a 100644 --- a/Doc/includes/test.py +++ b/Doc/includes/newtypes/test.py @@ -187,13 +187,6 @@ >>> gc.enable() """ -import os -import sys -from distutils.util import get_platform -PLAT_SPEC = "%s-%d.%d" % (get_platform(), *sys.version_info[:2]) -src = os.path.join("build", "lib.%s" % PLAT_SPEC) -sys.path.append(src) - if __name__ == "__main__": import doctest, __main__ doctest.testmod(__main__) diff --git a/Doc/includes/setup.py b/Doc/includes/setup.py deleted file mode 100644 index a38a39de3e7c86..00000000000000 --- a/Doc/includes/setup.py +++ /dev/null @@ -1,9 +0,0 @@ -from distutils.core import setup, Extension -setup(name="noddy", version="1.0", - ext_modules=[ - Extension("noddy", ["noddy.c"]), - Extension("noddy2", ["noddy2.c"]), - Extension("noddy3", ["noddy3.c"]), - Extension("noddy4", ["noddy4.c"]), - Extension("shoddy", ["shoddy.c"]), - ]) diff --git a/Doc/includes/typestruct.h b/Doc/includes/typestruct.h index f0ad1e47cb0d86..ec939c28831c33 100644 --- a/Doc/includes/typestruct.h +++ b/Doc/includes/typestruct.h @@ -82,5 +82,5 @@ typedef struct _typeobject { vectorcallfunc tp_vectorcall; /* bitset of which type-watchers care about this type */ - char tp_watched; + unsigned char tp_watched; } PyTypeObject; diff --git a/Doc/install/index.rst b/Doc/install/index.rst deleted file mode 100644 index ffb4a202fe89f2..00000000000000 --- a/Doc/install/index.rst +++ /dev/null @@ -1,1081 +0,0 @@ -.. highlight:: none - -.. _install-index: - -******************************************** - Installing Python Modules (Legacy version) -******************************************** - -:Author: Greg Ward - -.. TODO: Fill in XXX comments - -.. note:: - - The entire ``distutils`` package has been deprecated and will be - removed in Python 3.12. This documentation is retained as a - reference only, and will be removed with the package. See the - :ref:`What's New ` entry for more information. - -.. seealso:: - - :ref:`installing-index` - The up to date module installation documentation. For regular Python - usage, you almost certainly want that document rather than this one. - -.. note:: - - This document is being retained solely until the ``setuptools`` documentation - at https://setuptools.readthedocs.io/en/latest/setuptools.html - independently covers all of the relevant information currently included here. - -.. note:: - - This guide only covers the basic tools for building and distributing - extensions that are provided as part of this version of Python. Third party - tools offer easier to use and more secure alternatives. Refer to the `quick - recommendations section `__ - in the Python Packaging User Guide for more information. - - -.. _inst-intro: - - -Introduction -============ - -In Python 2.0, the ``distutils`` API was first added to the standard library. -This provided Linux distro maintainers with a standard way of converting -Python projects into Linux distro packages, and system administrators with a -standard way of installing them directly onto target systems. - -In the many years since Python 2.0 was released, tightly coupling the build -system and package installer to the language runtime release cycle has turned -out to be problematic, and it is now recommended that projects use the -``pip`` package installer and the ``setuptools`` build system, rather than -using ``distutils`` directly. - -See :ref:`installing-index` and :ref:`distributing-index` for more details. - -This legacy documentation is being retained only until we're confident that the -``setuptools`` documentation covers everything needed. - -.. _inst-new-standard: - -Distutils based source distributions ------------------------------------- - -If you download a module source distribution, you can tell pretty quickly if it -was packaged and distributed in the standard way, i.e. using the Distutils. -First, the distribution's name and version number will be featured prominently -in the name of the downloaded archive, e.g. :file:`foo-1.0.tar.gz` or -:file:`widget-0.9.7.zip`. Next, the archive will unpack into a similarly named -directory: :file:`foo-1.0` or :file:`widget-0.9.7`. Additionally, the -distribution will contain a setup script :file:`setup.py`, and a file named -:file:`README.txt` or possibly just :file:`README`, which should explain that -building and installing the module distribution is a simple matter of running -one command from a terminal:: - - python setup.py install - -For Windows, this command should be run from a command prompt window -(:menuselection:`Start --> Accessories`):: - - setup.py install - -If all these things are true, then you already know how to build and install the -modules you've just downloaded: Run the command above. Unless you need to -install things in a non-standard way or customize the build process, you don't -really need this manual. Or rather, the above command is everything you need to -get out of this manual. - - -.. _inst-standard-install: - -Standard Build and Install -========================== - -As described in section :ref:`inst-new-standard`, building and installing a module -distribution using the Distutils is usually one simple command to run from a -terminal:: - - python setup.py install - - -.. _inst-platform-variations: - -Platform variations -------------------- - -You should always run the setup command from the distribution root directory, -i.e. the top-level subdirectory that the module source distribution unpacks -into. For example, if you've just downloaded a module source distribution -:file:`foo-1.0.tar.gz` onto a Unix system, the normal thing to do is:: - - gunzip -c foo-1.0.tar.gz | tar xf - # unpacks into directory foo-1.0 - cd foo-1.0 - python setup.py install - -On Windows, you'd probably download :file:`foo-1.0.zip`. If you downloaded the -archive file to :file:`C:\\Temp`, then it would unpack into -:file:`C:\\Temp\\foo-1.0`; you can use either an archive manipulator with a -graphical user interface (such as WinZip) or a command-line tool (such as -:program:`unzip` or :program:`pkunzip`) to unpack the archive. Then, open a -command prompt window and run:: - - cd c:\Temp\foo-1.0 - python setup.py install - - -.. _inst-splitting-up: - -Splitting the job up --------------------- - -Running ``setup.py install`` builds and installs all modules in one run. If you -prefer to work incrementally---especially useful if you want to customize the -build process, or if things are going wrong---you can use the setup script to do -one thing at a time. This is particularly helpful when the build and install -will be done by different users---for example, you might want to build a module -distribution and hand it off to a system administrator for installation (or do -it yourself, with super-user privileges). - -For example, you can build everything in one step, and then install everything -in a second step, by invoking the setup script twice:: - - python setup.py build - python setup.py install - -If you do this, you will notice that running the :command:`install` command -first runs the :command:`build` command, which---in this case---quickly notices -that it has nothing to do, since everything in the :file:`build` directory is -up-to-date. - -You may not need this ability to break things down often if all you do is -install modules downloaded off the 'net, but it's very handy for more advanced -tasks. If you get into distributing your own Python modules and extensions, -you'll run lots of individual Distutils commands on their own. - - -.. _inst-how-build-works: - -How building works ------------------- - -As implied above, the :command:`build` command is responsible for putting the -files to install into a *build directory*. By default, this is :file:`build` -under the distribution root; if you're excessively concerned with speed, or want -to keep the source tree pristine, you can change the build directory with the -:option:`!--build-base` option. For example:: - - python setup.py build --build-base=/path/to/pybuild/foo-1.0 - -(Or you could do this permanently with a directive in your system or personal -Distutils configuration file; see section :ref:`inst-config-files`.) Normally, this -isn't necessary. - -The default layout for the build tree is as follows:: - - --- build/ --- lib/ - or - --- build/ --- lib./ - temp./ - -where ```` expands to a brief description of the current OS/hardware -platform and Python version. The first form, with just a :file:`lib` directory, -is used for "pure module distributions"---that is, module distributions that -include only pure Python modules. If a module distribution contains any -extensions (modules written in C/C++), then the second form, with two ```` -directories, is used. In that case, the :file:`temp.{plat}` directory holds -temporary files generated by the compile/link process that don't actually get -installed. In either case, the :file:`lib` (or :file:`lib.{plat}`) directory -contains all Python modules (pure Python and extensions) that will be installed. - -In the future, more directories will be added to handle Python scripts, -documentation, binary executables, and whatever else is needed to handle the job -of installing Python modules and applications. - - -.. _inst-how-install-works: - -How installation works ----------------------- - -After the :command:`build` command runs (whether you run it explicitly, or the -:command:`install` command does it for you), the work of the :command:`install` -command is relatively simple: all it has to do is copy everything under -:file:`build/lib` (or :file:`build/lib.{plat}`) to your chosen installation -directory. - -If you don't choose an installation directory---i.e., if you just run ``setup.py -install``\ ---then the :command:`install` command installs to the standard -location for third-party Python modules. This location varies by platform and -by how you built/installed Python itself. On Unix (and macOS, which is also -Unix-based), it also depends on whether the module distribution being installed -is pure Python or contains extensions ("non-pure"): - -.. tabularcolumns:: |l|l|l|l| - -+-----------------+-----------------------------------------------------+--------------------------------------------------+-------+ -| Platform | Standard installation location | Default value | Notes | -+=================+=====================================================+==================================================+=======+ -| Unix (pure) | :file:`{prefix}/lib/python{X.Y}/site-packages` | :file:`/usr/local/lib/python{X.Y}/site-packages` | \(1) | -+-----------------+-----------------------------------------------------+--------------------------------------------------+-------+ -| Unix (non-pure) | :file:`{exec-prefix}/lib/python{X.Y}/site-packages` | :file:`/usr/local/lib/python{X.Y}/site-packages` | \(1) | -+-----------------+-----------------------------------------------------+--------------------------------------------------+-------+ -| Windows | :file:`{prefix}\\Lib\\site-packages` | :file:`C:\\Python{XY}\\Lib\\site-packages` | \(2) | -+-----------------+-----------------------------------------------------+--------------------------------------------------+-------+ - -Notes: - -(1) - Most Linux distributions include Python as a standard part of the system, so - :file:`{prefix}` and :file:`{exec-prefix}` are usually both :file:`/usr` on - Linux. If you build Python yourself on Linux (or any Unix-like system), the - default :file:`{prefix}` and :file:`{exec-prefix}` are :file:`/usr/local`. - -(2) - The default installation directory on Windows was :file:`C:\\Program - Files\\Python` under Python 1.6a1, 1.5.2, and earlier. - -:file:`{prefix}` and :file:`{exec-prefix}` stand for the directories that Python -is installed to, and where it finds its libraries at run-time. They are always -the same under Windows, and very often the same under Unix and macOS. You -can find out what your Python installation uses for :file:`{prefix}` and -:file:`{exec-prefix}` by running Python in interactive mode and typing a few -simple commands. Under Unix, just type ``python`` at the shell prompt. Under -Windows, choose :menuselection:`Start --> Programs --> Python X.Y --> -Python (command line)`. Once the interpreter is started, you type Python code -at the prompt. For example, on my Linux system, I type the three Python -statements shown below, and get the output as shown, to find out my -:file:`{prefix}` and :file:`{exec-prefix}`: - -.. code-block:: pycon - - Python 2.4 (#26, Aug 7 2004, 17:19:02) - Type "help", "copyright", "credits" or "license" for more information. - >>> import sys - >>> sys.prefix - '/usr' - >>> sys.exec_prefix - '/usr' - -A few other placeholders are used in this document: :file:`{X.Y}` stands for the -version of Python, for example ``3.2``; :file:`{abiflags}` will be replaced by -the value of :data:`sys.abiflags` or the empty string for platforms which don't -define ABI flags; :file:`{distname}` will be replaced by the name of the module -distribution being installed. Dots and capitalization are important in the -paths; for example, a value that uses ``python3.2`` on UNIX will typically use -``Python32`` on Windows. - -If you don't want to install modules to the standard location, or if you don't -have permission to write there, then you need to read about alternate -installations in section :ref:`inst-alt-install`. If you want to customize your -installation directories more heavily, see section :ref:`inst-custom-install` on -custom installations. - - -.. _inst-alt-install: - -Alternate Installation -====================== - -Often, it is necessary or desirable to install modules to a location other than -the standard location for third-party Python modules. For example, on a Unix -system you might not have permission to write to the standard third-party module -directory. Or you might wish to try out a module before making it a standard -part of your local Python installation. This is especially true when upgrading -a distribution already present: you want to make sure your existing base of -scripts still works with the new version before actually upgrading. - -The Distutils :command:`install` command is designed to make installing module -distributions to an alternate location simple and painless. The basic idea is -that you supply a base directory for the installation, and the -:command:`install` command picks a set of directories (called an *installation -scheme*) under this base directory in which to install files. The details -differ across platforms, so read whichever of the following sections applies to -you. - -Note that the various alternate installation schemes are mutually exclusive: you -can pass ``--user``, or ``--home``, or ``--prefix`` and ``--exec-prefix``, or -``--install-base`` and ``--install-platbase``, but you can't mix from these -groups. - - -.. _inst-alt-install-user: - -Alternate installation: the user scheme ---------------------------------------- - -This scheme is designed to be the most convenient solution for users that don't -have write permission to the global site-packages directory or don't want to -install into it. It is enabled with a simple option:: - - python setup.py install --user - -Files will be installed into subdirectories of :const:`site.USER_BASE` (written -as :file:`{userbase}` hereafter). This scheme installs pure Python modules and -extension modules in the same location (also known as :const:`site.USER_SITE`). -Here are the values for UNIX, including macOS: - -=============== =========================================================== -Type of file Installation directory -=============== =========================================================== -modules :file:`{userbase}/lib/python{X.Y}/site-packages` -scripts :file:`{userbase}/bin` -data :file:`{userbase}` -C headers :file:`{userbase}/include/python{X.Y}{abiflags}/{distname}` -=============== =========================================================== - -And here are the values used on Windows: - -=============== =========================================================== -Type of file Installation directory -=============== =========================================================== -modules :file:`{userbase}\\Python{XY}\\site-packages` -scripts :file:`{userbase}\\Python{XY}\\Scripts` -data :file:`{userbase}` -C headers :file:`{userbase}\\Python{XY}\\Include\\{distname}` -=============== =========================================================== - -The advantage of using this scheme compared to the other ones described below is -that the user site-packages directory is under normal conditions always included -in :data:`sys.path` (see :mod:`site` for more information), which means that -there is no additional step to perform after running the :file:`setup.py` script -to finalize the installation. - -The :command:`build_ext` command also has a ``--user`` option to add -:file:`{userbase}/include` to the compiler search path for header files and -:file:`{userbase}/lib` to the compiler search path for libraries as well as to -the runtime search path for shared C libraries (rpath). - - -.. _inst-alt-install-home: - -Alternate installation: the home scheme ---------------------------------------- - -The idea behind the "home scheme" is that you build and maintain a personal -stash of Python modules. This scheme's name is derived from the idea of a -"home" directory on Unix, since it's not unusual for a Unix user to make their -home directory have a layout similar to :file:`/usr/` or :file:`/usr/local/`. -This scheme can be used by anyone, regardless of the operating system they -are installing for. - -Installing a new module distribution is as simple as :: - - python setup.py install --home= - -where you can supply any directory you like for the :option:`!--home` option. On -Unix, lazy typists can just type a tilde (``~``); the :command:`install` command -will expand this to your home directory:: - - python setup.py install --home=~ - -To make Python find the distributions installed with this scheme, you may have -to :ref:`modify Python's search path ` or edit -:mod:`!sitecustomize` (see :mod:`site`) to call :func:`site.addsitedir` or edit -:data:`sys.path`. - -The :option:`!--home` option defines the installation base directory. Files are -installed to the following directories under the installation base as follows: - -=============== =========================================================== -Type of file Installation directory -=============== =========================================================== -modules :file:`{home}/lib/python` -scripts :file:`{home}/bin` -data :file:`{home}` -C headers :file:`{home}/include/python/{distname}` -=============== =========================================================== - -(Mentally replace slashes with backslashes if you're on Windows.) - - -.. _inst-alt-install-prefix-unix: - -Alternate installation: Unix (the prefix scheme) ------------------------------------------------- - -The "prefix scheme" is useful when you wish to use one Python installation to -perform the build/install (i.e., to run the setup script), but install modules -into the third-party module directory of a different Python installation (or -something that looks like a different Python installation). If this sounds a -trifle unusual, it is---that's why the user and home schemes come before. However, -there are at least two known cases where the prefix scheme will be useful. - -First, consider that many Linux distributions put Python in :file:`/usr`, rather -than the more traditional :file:`/usr/local`. This is entirely appropriate, -since in those cases Python is part of "the system" rather than a local add-on. -However, if you are installing Python modules from source, you probably want -them to go in :file:`/usr/local/lib/python2.{X}` rather than -:file:`/usr/lib/python2.{X}`. This can be done with :: - - /usr/bin/python setup.py install --prefix=/usr/local - -Another possibility is a network filesystem where the name used to write to a -remote directory is different from the name used to read it: for example, the -Python interpreter accessed as :file:`/usr/local/bin/python` might search for -modules in :file:`/usr/local/lib/python2.{X}`, but those modules would have to -be installed to, say, :file:`/mnt/{@server}/export/lib/python2.{X}`. This could -be done with :: - - /usr/local/bin/python setup.py install --prefix=/mnt/@server/export - -In either case, the :option:`!--prefix` option defines the installation base, and -the :option:`!--exec-prefix` option defines the platform-specific installation -base, which is used for platform-specific files. (Currently, this just means -non-pure module distributions, but could be expanded to C libraries, binary -executables, etc.) If :option:`!--exec-prefix` is not supplied, it defaults to -:option:`!--prefix`. Files are installed as follows: - -================= ========================================================== -Type of file Installation directory -================= ========================================================== -Python modules :file:`{prefix}/lib/python{X.Y}/site-packages` -extension modules :file:`{exec-prefix}/lib/python{X.Y}/site-packages` -scripts :file:`{prefix}/bin` -data :file:`{prefix}` -C headers :file:`{prefix}/include/python{X.Y}{abiflags}/{distname}` -================= ========================================================== - -There is no requirement that :option:`!--prefix` or :option:`!--exec-prefix` -actually point to an alternate Python installation; if the directories listed -above do not already exist, they are created at installation time. - -Incidentally, the real reason the prefix scheme is important is simply that a -standard Unix installation uses the prefix scheme, but with :option:`!--prefix` -and :option:`!--exec-prefix` supplied by Python itself as ``sys.prefix`` and -``sys.exec_prefix``. Thus, you might think you'll never use the prefix scheme, -but every time you run ``python setup.py install`` without any other options, -you're using it. - -Note that installing extensions to an alternate Python installation has no -effect on how those extensions are built: in particular, the Python header files -(:file:`Python.h` and friends) installed with the Python interpreter used to run -the setup script will be used in compiling extensions. It is your -responsibility to ensure that the interpreter used to run extensions installed -in this way is compatible with the interpreter used to build them. The best way -to do this is to ensure that the two interpreters are the same version of Python -(possibly different builds, or possibly copies of the same build). (Of course, -if your :option:`!--prefix` and :option:`!--exec-prefix` don't even point to an -alternate Python installation, this is immaterial.) - - -.. _inst-alt-install-prefix-windows: - -Alternate installation: Windows (the prefix scheme) ---------------------------------------------------- - -Windows has no concept of a user's home directory, and since the standard Python -installation under Windows is simpler than under Unix, the :option:`!--prefix` -option has traditionally been used to install additional packages in separate -locations on Windows. :: - - python setup.py install --prefix="\Temp\Python" - -to install modules to the :file:`\\Temp\\Python` directory on the current drive. - -The installation base is defined by the :option:`!--prefix` option; the -:option:`!--exec-prefix` option is not supported under Windows, which means that -pure Python modules and extension modules are installed into the same location. -Files are installed as follows: - -=============== ========================================================== -Type of file Installation directory -=============== ========================================================== -modules :file:`{prefix}\\Lib\\site-packages` -scripts :file:`{prefix}\\Scripts` -data :file:`{prefix}` -C headers :file:`{prefix}\\Include\\{distname}` -=============== ========================================================== - - -.. _inst-custom-install: - -Custom Installation -=================== - -Sometimes, the alternate installation schemes described in section -:ref:`inst-alt-install` just don't do what you want. You might want to tweak just -one or two directories while keeping everything under the same base directory, -or you might want to completely redefine the installation scheme. In either -case, you're creating a *custom installation scheme*. - -To create a custom installation scheme, you start with one of the alternate -schemes and override some of the installation directories used for the various -types of files, using these options: - -====================== ======================= -Type of file Override option -====================== ======================= -Python modules ``--install-purelib`` -extension modules ``--install-platlib`` -all modules ``--install-lib`` -scripts ``--install-scripts`` -data ``--install-data`` -C headers ``--install-headers`` -====================== ======================= - -These override options can be relative, absolute, -or explicitly defined in terms of one of the installation base directories. -(There are two installation base directories, and they are normally the -same---they only differ when you use the Unix "prefix scheme" and supply -different ``--prefix`` and ``--exec-prefix`` options; using ``--install-lib`` -will override values computed or given for ``--install-purelib`` and -``--install-platlib``, and is recommended for schemes that don't make a -difference between Python and extension modules.) - -For example, say you're installing a module distribution to your home directory -under Unix---but you want scripts to go in :file:`~/scripts` rather than -:file:`~/bin`. As you might expect, you can override this directory with the -:option:`!--install-scripts` option; in this case, it makes most sense to supply -a relative path, which will be interpreted relative to the installation base -directory (your home directory, in this case):: - - python setup.py install --home=~ --install-scripts=scripts - -Another Unix example: suppose your Python installation was built and installed -with a prefix of :file:`/usr/local/python`, so under a standard installation -scripts will wind up in :file:`/usr/local/python/bin`. If you want them in -:file:`/usr/local/bin` instead, you would supply this absolute directory for the -:option:`!--install-scripts` option:: - - python setup.py install --install-scripts=/usr/local/bin - -(This performs an installation using the "prefix scheme", where the prefix is -whatever your Python interpreter was installed with--- :file:`/usr/local/python` -in this case.) - -If you maintain Python on Windows, you might want third-party modules to live in -a subdirectory of :file:`{prefix}`, rather than right in :file:`{prefix}` -itself. This is almost as easy as customizing the script installation -directory---you just have to remember that there are two types of modules -to worry about, Python and extension modules, which can conveniently be both -controlled by one option:: - - python setup.py install --install-lib=Site - -The specified installation directory is relative to :file:`{prefix}`. Of -course, you also have to ensure that this directory is in Python's module -search path, such as by putting a :file:`.pth` file in a site directory (see -:mod:`site`). See section :ref:`inst-search-path` to find out how to modify -Python's search path. - -If you want to define an entire installation scheme, you just have to supply all -of the installation directory options. The recommended way to do this is to -supply relative paths; for example, if you want to maintain all Python -module-related files under :file:`python` in your home directory, and you want a -separate directory for each platform that you use your home directory from, you -might define the following installation scheme:: - - python setup.py install --home=~ \ - --install-purelib=python/lib \ - --install-platlib=python/lib.$PLAT \ - --install-scripts=python/scripts - --install-data=python/data - -or, equivalently, :: - - python setup.py install --home=~/python \ - --install-purelib=lib \ - --install-platlib='lib.$PLAT' \ - --install-scripts=scripts - --install-data=data - -``$PLAT`` is not (necessarily) an environment variable---it will be expanded by -the Distutils as it parses your command line options, just as it does when -parsing your configuration file(s). - -Obviously, specifying the entire installation scheme every time you install a -new module distribution would be very tedious. Thus, you can put these options -into your Distutils config file (see section :ref:`inst-config-files`): - -.. code-block:: ini - - [install] - install-base=$HOME - install-purelib=python/lib - install-platlib=python/lib.$PLAT - install-scripts=python/scripts - install-data=python/data - -or, equivalently, - -.. code-block:: ini - - [install] - install-base=$HOME/python - install-purelib=lib - install-platlib=lib.$PLAT - install-scripts=scripts - install-data=data - -Note that these two are *not* equivalent if you supply a different installation -base directory when you run the setup script. For example, :: - - python setup.py install --install-base=/tmp - -would install pure modules to :file:`/tmp/python/lib` in the first case, and -to :file:`/tmp/lib` in the second case. (For the second case, you probably -want to supply an installation base of :file:`/tmp/python`.) - -You probably noticed the use of ``$HOME`` and ``$PLAT`` in the sample -configuration file input. These are Distutils configuration variables, which -bear a strong resemblance to environment variables. In fact, you can use -environment variables in config files on platforms that have such a notion but -the Distutils additionally define a few extra variables that may not be in your -environment, such as ``$PLAT``. (And of course, on systems that don't have -environment variables, such as Mac OS 9, the configuration variables supplied by -the Distutils are the only ones you can use.) See section :ref:`inst-config-files` -for details. - -.. note:: When a :ref:`virtual environment ` is activated, any options - that change the installation path will be ignored from all distutils configuration - files to prevent inadvertently installing projects outside of the virtual - environment. - -.. XXX need some Windows examples---when would custom installation schemes be - needed on those platforms? - - -.. XXX Move this to Doc/using - -.. _inst-search-path: - -Modifying Python's Search Path ------------------------------- - -When the Python interpreter executes an :keyword:`import` statement, it searches -for both Python code and extension modules along a search path. A default value -for the path is configured into the Python binary when the interpreter is built. -You can determine the path by importing the :mod:`sys` module and printing the -value of ``sys.path``. :: - - $ python - Python 2.2 (#11, Oct 3 2002, 13:31:27) - [GCC 2.96 20000731 (Red Hat Linux 7.3 2.96-112)] on linux2 - Type "help", "copyright", "credits" or "license" for more information. - >>> import sys - >>> sys.path - ['', '/usr/local/lib/python2.3', '/usr/local/lib/python2.3/plat-linux2', - '/usr/local/lib/python2.3/lib-tk', '/usr/local/lib/python2.3/lib-dynload', - '/usr/local/lib/python2.3/site-packages'] - >>> - -The null string in ``sys.path`` represents the current working directory. - -The expected convention for locally installed packages is to put them in the -:file:`{...}/site-packages/` directory, but you may want to install Python -modules into some arbitrary directory. For example, your site may have a -convention of keeping all software related to the web server under :file:`/www`. -Add-on Python modules might then belong in :file:`/www/python`, and in order to -import them, this directory must be added to ``sys.path``. There are several -different ways to add the directory. - -The most convenient way is to add a path configuration file to a directory -that's already on Python's path, usually to the :file:`.../site-packages/` -directory. Path configuration files have an extension of :file:`.pth`, and each -line must contain a single path that will be appended to ``sys.path``. (Because -the new paths are appended to ``sys.path``, modules in the added directories -will not override standard modules. This means you can't use this mechanism for -installing fixed versions of standard modules.) - -Paths can be absolute or relative, in which case they're relative to the -directory containing the :file:`.pth` file. See the documentation of -the :mod:`site` module for more information. - -A slightly less convenient way is to edit the :file:`site.py` file in Python's -standard library, and modify ``sys.path``. :file:`site.py` is automatically -imported when the Python interpreter is executed, unless the :option:`-S` switch -is supplied to suppress this behaviour. So you could simply edit -:file:`site.py` and add two lines to it: - -.. code-block:: python - - import sys - sys.path.append('/www/python/') - -However, if you reinstall the same minor version of Python (perhaps when -upgrading from 2.2 to 2.2.2, for example) :file:`site.py` will be overwritten by -the stock version. You'd have to remember that it was modified and save a copy -before doing the installation. - -There are two environment variables that can modify ``sys.path``. -:envvar:`PYTHONHOME` sets an alternate value for the prefix of the Python -installation. For example, if :envvar:`PYTHONHOME` is set to ``/www/python``, -the search path will be set to ``['', '/www/python/lib/pythonX.Y/', -'/www/python/lib/pythonX.Y/plat-linux2', ...]``. - -The :envvar:`PYTHONPATH` variable can be set to a list of paths that will be -added to the beginning of ``sys.path``. For example, if :envvar:`PYTHONPATH` is -set to ``/www/python:/opt/py``, the search path will begin with -``['/www/python', '/opt/py']``. (Note that directories must exist in order to -be added to ``sys.path``; the :mod:`site` module removes paths that don't -exist.) - -Finally, ``sys.path`` is just a regular Python list, so any Python application -can modify it by adding or removing entries. - - -.. _inst-config-files: - -Distutils Configuration Files -============================= - -As mentioned above, you can use Distutils configuration files to record personal -or site preferences for any Distutils options. That is, any option to any -command can be stored in one of two or three (depending on your platform) -configuration files, which will be consulted before the command-line is parsed. -This means that configuration files will override default values, and the -command-line will in turn override configuration files. Furthermore, if -multiple configuration files apply, values from "earlier" files are overridden -by "later" files. - - -.. _inst-config-filenames: - -Location and names of config files ----------------------------------- - -The names and locations of the configuration files vary slightly across -platforms. On Unix and macOS, the three configuration files (in the order -they are processed) are: - -+--------------+----------------------------------------------------------+-------+ -| Type of file | Location and filename | Notes | -+==============+==========================================================+=======+ -| system | :file:`{prefix}/lib/python{ver}/distutils/distutils.cfg` | \(1) | -+--------------+----------------------------------------------------------+-------+ -| personal | :file:`$HOME/.pydistutils.cfg` | \(2) | -+--------------+----------------------------------------------------------+-------+ -| local | :file:`setup.cfg` | \(3) | -+--------------+----------------------------------------------------------+-------+ - -And on Windows, the configuration files are: - -+--------------+-------------------------------------------------+-------+ -| Type of file | Location and filename | Notes | -+==============+=================================================+=======+ -| system | :file:`{prefix}\\Lib\\distutils\\distutils.cfg` | \(4) | -+--------------+-------------------------------------------------+-------+ -| personal | :file:`%HOME%\\pydistutils.cfg` | \(5) | -+--------------+-------------------------------------------------+-------+ -| local | :file:`setup.cfg` | \(3) | -+--------------+-------------------------------------------------+-------+ - -On all platforms, the "personal" file can be temporarily disabled by -passing the ``--no-user-cfg`` option. - -Notes: - -(1) - Strictly speaking, the system-wide configuration file lives in the directory - where the Distutils are installed; under Python 1.6 and later on Unix, this is - as shown. For Python 1.5.2, the Distutils will normally be installed to - :file:`{prefix}/lib/python1.5/site-packages/distutils`, so the system - configuration file should be put there under Python 1.5.2. - -(2) - On Unix, if the :envvar:`HOME` environment variable is not defined, the user's - home directory will be determined with the :func:`~pwd.getpwuid` function from the - standard :mod:`pwd` module. This is done by the :func:`os.path.expanduser` - function used by Distutils. - -(3) - I.e., in the current directory (usually the location of the setup script). - -(4) - (See also note (1).) Under Python 1.6 and later, Python's default "installation - prefix" is :file:`C:\\Python`, so the system configuration file is normally - :file:`C:\\Python\\Lib\\distutils\\distutils.cfg`. Under Python 1.5.2, the - default prefix was :file:`C:\\Program Files\\Python`, and the Distutils were not - part of the standard library---so the system configuration file would be - :file:`C:\\Program Files\\Python\\distutils\\distutils.cfg` in a standard Python - 1.5.2 installation under Windows. - -(5) - On Windows, if the :envvar:`HOME` environment variable is not defined, - :envvar:`USERPROFILE` then :envvar:`HOMEDRIVE` and :envvar:`HOMEPATH` will - be tried. This is done by the :func:`os.path.expanduser` function used - by Distutils. - - -.. _inst-config-syntax: - -Syntax of config files ----------------------- - -The Distutils configuration files all have the same syntax. The config files -are grouped into sections. There is one section for each Distutils command, -plus a ``global`` section for global options that affect every command. Each -section consists of one option per line, specified as ``option=value``. - -For example, the following is a complete config file that just forces all -commands to run quietly by default: - -.. code-block:: ini - - [global] - verbose=0 - -If this is installed as the system config file, it will affect all processing of -any Python module distribution by any user on the current system. If it is -installed as your personal config file (on systems that support them), it will -affect only module distributions processed by you. And if it is used as the -:file:`setup.cfg` for a particular module distribution, it affects only that -distribution. - -You could override the default "build base" directory and make the -:command:`build\*` commands always forcibly rebuild all files with the -following: - -.. code-block:: ini - - [build] - build-base=blib - force=1 - -which corresponds to the command-line arguments :: - - python setup.py build --build-base=blib --force - -except that including the :command:`build` command on the command-line means -that command will be run. Including a particular command in config files has no -such implication; it only means that if the command is run, the options in the -config file will apply. (Or if other commands that derive values from it are -run, they will use the values in the config file.) - -You can find out the complete list of options for any command using the -:option:`!--help` option, e.g.:: - - python setup.py build --help - -and you can find out the complete list of global options by using -:option:`!--help` without a command:: - - python setup.py --help - -See also the "Reference" section of the "Distributing Python Modules" manual. - - -.. _inst-building-ext: - -Building Extensions: Tips and Tricks -==================================== - -Whenever possible, the Distutils try to use the configuration information made -available by the Python interpreter used to run the :file:`setup.py` script. -For example, the same compiler and linker flags used to compile Python will also -be used for compiling extensions. Usually this will work well, but in -complicated situations this might be inappropriate. This section discusses how -to override the usual Distutils behaviour. - - -.. _inst-tweak-flags: - -Tweaking compiler/linker flags ------------------------------- - -Compiling a Python extension written in C or C++ will sometimes require -specifying custom flags for the compiler and linker in order to use a particular -library or produce a special kind of object code. This is especially true if the -extension hasn't been tested on your platform, or if you're trying to -cross-compile Python. - -In the most general case, the extension author might have foreseen that -compiling the extensions would be complicated, and provided a :file:`Setup` file -for you to edit. This will likely only be done if the module distribution -contains many separate extension modules, or if they often require elaborate -sets of compiler flags in order to work. - -A :file:`Setup` file, if present, is parsed in order to get a list of extensions -to build. Each line in a :file:`Setup` describes a single module. Lines have -the following structure:: - - module ... [sourcefile ...] [cpparg ...] [library ...] - - -Let's examine each of the fields in turn. - -* *module* is the name of the extension module to be built, and should be a - valid Python identifier. You can't just change this in order to rename a module - (edits to the source code would also be needed), so this should be left alone. - -* *sourcefile* is anything that's likely to be a source code file, at least - judging by the filename. Filenames ending in :file:`.c` are assumed to be - written in C, filenames ending in :file:`.C`, :file:`.cc`, and :file:`.c++` are - assumed to be C++, and filenames ending in :file:`.m` or :file:`.mm` are assumed - to be in Objective C. - -* *cpparg* is an argument for the C preprocessor, and is anything starting with - :option:`!-I`, :option:`!-D`, :option:`!-U` or :option:`!-C`. - -* *library* is anything ending in :file:`.a` or beginning with :option:`!-l` or - :option:`!-L`. - -If a particular platform requires a special library on your platform, you can -add it by editing the :file:`Setup` file and running ``python setup.py build``. -For example, if the module defined by the line :: - - foo foomodule.c - -must be linked with the math library :file:`libm.a` on your platform, simply add -:option:`!-lm` to the line:: - - foo foomodule.c -lm - -Arbitrary switches intended for the compiler or the linker can be supplied with -the :option:`!-Xcompiler` *arg* and :option:`!-Xlinker` *arg* options:: - - foo foomodule.c -Xcompiler -o32 -Xlinker -shared -lm - -The next option after :option:`!-Xcompiler` and :option:`!-Xlinker` will be -appended to the proper command line, so in the above example the compiler will -be passed the :option:`!-o32` option, and the linker will be passed -:option:`!-shared`. If a compiler option requires an argument, you'll have to -supply multiple :option:`!-Xcompiler` options; for example, to pass ``-x c++`` -the :file:`Setup` file would have to contain ``-Xcompiler -x -Xcompiler c++``. - -Compiler flags can also be supplied through setting the :envvar:`CFLAGS` -environment variable. If set, the contents of :envvar:`CFLAGS` will be added to -the compiler flags specified in the :file:`Setup` file. - - -.. _inst-non-ms-compilers: - -Using non-Microsoft compilers on Windows ----------------------------------------- - -.. sectionauthor:: Rene Liebscher - - - -Borland/CodeGear C++ -^^^^^^^^^^^^^^^^^^^^ - -This subsection describes the necessary steps to use Distutils with the Borland -C++ compiler version 5.5. First you have to know that Borland's object file -format (OMF) is different from the format used by the Python version you can -download from the Python or ActiveState web site. (Python is built with -Microsoft Visual C++, which uses COFF as the object file format.) For this -reason you have to convert Python's library :file:`python25.lib` into the -Borland format. You can do this as follows: - -.. Should we mention that users have to create cfg-files for the compiler? -.. see also http://community.borland.com/article/0,1410,21205,00.html - -:: - - coff2omf python25.lib python25_bcpp.lib - -The :file:`coff2omf` program comes with the Borland compiler. The file -:file:`python25.lib` is in the :file:`Libs` directory of your Python -installation. If your extension uses other libraries (zlib, ...) you have to -convert them too. - -The converted files have to reside in the same directories as the normal -libraries. - -How does Distutils manage to use these libraries with their changed names? If -the extension needs a library (eg. :file:`foo`) Distutils checks first if it -finds a library with suffix :file:`_bcpp` (eg. :file:`foo_bcpp.lib`) and then -uses this library. In the case it doesn't find such a special library it uses -the default name (:file:`foo.lib`.) [#]_ - -To let Distutils compile your extension with Borland C++ you now have to type:: - - python setup.py build --compiler=bcpp - -If you want to use the Borland C++ compiler as the default, you could specify -this in your personal or system-wide configuration file for Distutils (see -section :ref:`inst-config-files`.) - - -.. seealso:: - - `C++Builder Compiler `_ - Information about the free C++ compiler from Borland, including links to the - download pages. - - `Creating Python Extensions Using Borland's Free Compiler `_ - Document describing how to use Borland's free command-line C++ compiler to build - Python. - - -GNU C / Cygwin / MinGW -^^^^^^^^^^^^^^^^^^^^^^ - -This section describes the necessary steps to use Distutils with the GNU C/C++ -compilers in their Cygwin and MinGW distributions. [#]_ For a Python interpreter -that was built with Cygwin, everything should work without any of these -following steps. - -Not all extensions can be built with MinGW or Cygwin, but many can. Extensions -most likely to not work are those that use C++ or depend on Microsoft Visual C -extensions. - -To let Distutils compile your extension with Cygwin you have to type:: - - python setup.py build --compiler=cygwin - -and for Cygwin in no-cygwin mode [#]_ or for MinGW type:: - - python setup.py build --compiler=mingw32 - -If you want to use any of these options/compilers as default, you should -consider writing it in your personal or system-wide configuration file for -Distutils (see section :ref:`inst-config-files`.) - -Older Versions of Python and MinGW -"""""""""""""""""""""""""""""""""" -The following instructions only apply if you're using a version of Python -inferior to 2.4.1 with a MinGW inferior to 3.0.0 (with -binutils-2.13.90-20030111-1). - -These compilers require some special libraries. This task is more complex than -for Borland's C++, because there is no program to convert the library. First -you have to create a list of symbols which the Python DLL exports. (You can find -a good program for this task at -https://sourceforge.net/projects/mingw/files/MinGW/Extension/pexports/). - -.. I don't understand what the next line means. --amk -.. (inclusive the references on data structures.) - -:: - - pexports python25.dll >python25.def - -The location of an installed :file:`python25.dll` will depend on the -installation options and the version and language of Windows. In a "just for -me" installation, it will appear in the root of the installation directory. In -a shared installation, it will be located in the system directory. - -Then you can create from these information an import library for gcc. :: - - /cygwin/bin/dlltool --dllname python25.dll --def python25.def --output-lib libpython25.a - -The resulting library has to be placed in the same directory as -:file:`python25.lib`. (Should be the :file:`libs` directory under your Python -installation directory.) - -If your extension uses other libraries (zlib,...) you might have to convert -them too. The converted files have to reside in the same directories as the -normal libraries do. - - -.. seealso:: - - `Building Python modules on MS Windows platform with MinGW `_ - Information about building the required libraries for the MinGW environment. - - -.. rubric:: Footnotes - -.. [#] This also means you could replace all existing COFF-libraries with OMF-libraries - of the same name. - -.. [#] Check https://www.sourceware.org/cygwin/ for more information - -.. [#] Then you have no POSIX emulation available, but you also don't need - :file:`cygwin1.dll`. diff --git a/Doc/installing/index.rst b/Doc/installing/index.rst index 5aec5178d48f3d..a46c1caefe4d8a 100644 --- a/Doc/installing/index.rst +++ b/Doc/installing/index.rst @@ -19,7 +19,9 @@ solutions to the common pool. This guide covers the installation part of the process. For a guide to creating and sharing your own Python projects, refer to the -:ref:`distribution guide `. +`Python packaging user guide`_. + +.. _Python Packaging User Guide: https://packaging.python.org/en/latest/tutorials/packaging-projects/ .. note:: diff --git a/Doc/library/__future__.rst b/Doc/library/__future__.rst index 8bd23daee73977..d261e4a4f338a5 100644 --- a/Doc/library/__future__.rst +++ b/Doc/library/__future__.rst @@ -22,42 +22,48 @@ can be inspected programmatically via importing :mod:`__future__` and examining its contents. -Each statement in :file:`__future__.py` is of the form:: +.. _future-classes: - FeatureName = _Feature(OptionalRelease, MandatoryRelease, - CompilerFlag) +.. class:: _Feature + Each statement in :file:`__future__.py` is of the form:: -where, normally, *OptionalRelease* is less than *MandatoryRelease*, and both are -5-tuples of the same form as :data:`sys.version_info`:: + FeatureName = _Feature(OptionalRelease, MandatoryRelease, + CompilerFlag) - (PY_MAJOR_VERSION, # the 2 in 2.1.0a3; an int - PY_MINOR_VERSION, # the 1; an int - PY_MICRO_VERSION, # the 0; an int - PY_RELEASE_LEVEL, # "alpha", "beta", "candidate" or "final"; string - PY_RELEASE_SERIAL # the 3; an int - ) + where, normally, *OptionalRelease* is less than *MandatoryRelease*, and both are + 5-tuples of the same form as :data:`sys.version_info`:: -*OptionalRelease* records the first release in which the feature was accepted. + (PY_MAJOR_VERSION, # the 2 in 2.1.0a3; an int + PY_MINOR_VERSION, # the 1; an int + PY_MICRO_VERSION, # the 0; an int + PY_RELEASE_LEVEL, # "alpha", "beta", "candidate" or "final"; string + PY_RELEASE_SERIAL # the 3; an int + ) -In the case of a *MandatoryRelease* that has not yet occurred, -*MandatoryRelease* predicts the release in which the feature will become part of -the language. +.. method:: _Feature.getOptionalRelease() -Else *MandatoryRelease* records when the feature became part of the language; in -releases at or after that, modules no longer need a future statement to use the -feature in question, but may continue to use such imports. + *OptionalRelease* records the first release in which the feature was accepted. -*MandatoryRelease* may also be ``None``, meaning that a planned feature got -dropped. +.. method:: _Feature.getMandatoryRelease() -Instances of class :class:`_Feature` have two corresponding methods, -:meth:`getOptionalRelease` and :meth:`getMandatoryRelease`. + In the case of a *MandatoryRelease* that has not yet occurred, + *MandatoryRelease* predicts the release in which the feature will become part of + the language. -*CompilerFlag* is the (bitfield) flag that should be passed in the fourth -argument to the built-in function :func:`compile` to enable the feature in -dynamically compiled code. This flag is stored in the :attr:`compiler_flag` -attribute on :class:`_Feature` instances. + Else *MandatoryRelease* records when the feature became part of the language; in + releases at or after that, modules no longer need a future statement to use the + feature in question, but may continue to use such imports. + + *MandatoryRelease* may also be ``None``, meaning that a planned feature got + dropped or that it is not yet decided. + +.. attribute:: _Feature.compiler_flag + + *CompilerFlag* is the (bitfield) flag that should be passed in the fourth + argument to the built-in function :func:`compile` to enable the feature in + dynamically compiled code. This flag is stored in the :attr:`_Feature.compiler_flag` + attribute on :class:`_Feature` instances. No feature description will ever be deleted from :mod:`__future__`. Since its introduction in Python 2.1 the following features have found their way into the diff --git a/Doc/library/__main__.rst b/Doc/library/__main__.rst index fd60d92d4eb0f9..c999253f781b10 100644 --- a/Doc/library/__main__.rst +++ b/Doc/library/__main__.rst @@ -54,45 +54,45 @@ The top-level code environment can be: * the scope of an interactive prompt:: - >>> __name__ - '__main__' + >>> __name__ + '__main__' * the Python module passed to the Python interpreter as a file argument: - .. code-block:: shell-session + .. code-block:: shell-session - $ python helloworld.py - Hello, world! + $ python helloworld.py + Hello, world! * the Python module or package passed to the Python interpreter with the :option:`-m` argument: - .. code-block:: shell-session + .. code-block:: shell-session - $ python -m tarfile - usage: tarfile.py [-h] [-v] (...) + $ python -m tarfile + usage: tarfile.py [-h] [-v] (...) * Python code read by the Python interpreter from standard input: - .. code-block:: shell-session + .. code-block:: shell-session - $ echo "import this" | python - The Zen of Python, by Tim Peters + $ echo "import this" | python + The Zen of Python, by Tim Peters - Beautiful is better than ugly. - Explicit is better than implicit. - ... + Beautiful is better than ugly. + Explicit is better than implicit. + ... * Python code passed to the Python interpreter with the :option:`-c` argument: - .. code-block:: shell-session + .. code-block:: shell-session - $ python -c "import this" - The Zen of Python, by Tim Peters + $ python -c "import this" + The Zen of Python, by Tim Peters - Beautiful is better than ugly. - Explicit is better than implicit. - ... + Beautiful is better than ugly. + Explicit is better than implicit. + ... In each of these situations, the top-level module's ``__name__`` is set to ``'__main__'``. @@ -102,9 +102,9 @@ top-level environment by checking its own ``__name__``, which allows a common idiom for conditionally executing code when the module is not initialized from an import statement:: - if __name__ == '__main__': - # Execute when the module is not initialized from an import statement. - ... + if __name__ == '__main__': + # Execute when the module is not initialized from an import statement. + ... .. seealso:: @@ -227,7 +227,7 @@ students:: import sys from .student import search_students - student_name = sys.argv[2] if len(sys.argv) >= 2 else '' + student_name = sys.argv[1] if len(sys.argv) >= 2 else '' print(f'Found student: {search_students(student_name)}') Note that ``from .student import search_students`` is an example of a relative @@ -238,9 +238,9 @@ package. For more details, see :ref:`intra-package-references` in the Idiomatic Usage ^^^^^^^^^^^^^^^ -The contents of ``__main__.py`` typically isn't fenced with -``if __name__ == '__main__'`` blocks. Instead, those files are kept short, -functions to execute from other modules. Those other modules can then be +The content of ``__main__.py`` typically isn't fenced with an +``if __name__ == '__main__'`` block. Instead, those files are kept +short and import functions to execute from other modules. Those other modules can then be easily unit-tested and are properly reusable. If used, an ``if __name__ == '__main__'`` block will still work as expected diff --git a/Doc/library/_thread.rst b/Doc/library/_thread.rst index 0442c298c137ba..297f50a46e0692 100644 --- a/Doc/library/_thread.rst +++ b/Doc/library/_thread.rst @@ -120,10 +120,13 @@ This module defines the following constants and functions: Its value may be used to uniquely identify this particular thread system-wide (until the thread terminates, after which the value may be recycled by the OS). - .. availability:: Windows, FreeBSD, Linux, macOS, OpenBSD, NetBSD, AIX, DragonFlyBSD. + .. availability:: Windows, FreeBSD, Linux, macOS, OpenBSD, NetBSD, AIX, DragonFlyBSD, GNU/kFreeBSD. .. versionadded:: 3.8 + .. versionchanged:: 3.13 + Added support for GNU/kFreeBSD. + .. function:: stack_size([size]) @@ -208,7 +211,7 @@ In addition to these methods, lock objects can also be used via the **Caveats:** - .. index:: pair: module; signal +.. index:: pair: module; signal * Threads interact strangely with interrupts: the :exc:`KeyboardInterrupt` exception will be received by an arbitrary thread. (When the :mod:`signal` diff --git a/Doc/library/abc.rst b/Doc/library/abc.rst index 274b2d69f0ab5c..c073ea955abaa4 100644 --- a/Doc/library/abc.rst +++ b/Doc/library/abc.rst @@ -21,7 +21,7 @@ The :mod:`collections` module has some concrete classes that derive from ABCs; these can, of course, be further derived. In addition, the :mod:`collections.abc` submodule has some ABCs that can be used to test whether a class or instance provides a particular interface, for example, if it is -:term:`hashable` or if it is a mapping. +:term:`hashable` or if it is a :term:`mapping`. This module provides the metaclass :class:`ABCMeta` for defining ABCs and @@ -30,7 +30,7 @@ a helper class :class:`ABC` to alternatively define ABCs through inheritance: .. class:: ABC A helper class that has :class:`ABCMeta` as its metaclass. With this class, - an abstract base class can be created by simply deriving from :class:`ABC` + an abstract base class can be created by simply deriving from :class:`!ABC` avoiding sometimes confusing metaclass usage, for example:: from abc import ABC @@ -38,11 +38,11 @@ a helper class :class:`ABC` to alternatively define ABCs through inheritance: class MyABC(ABC): pass - Note that the type of :class:`ABC` is still :class:`ABCMeta`, therefore - inheriting from :class:`ABC` requires the usual precautions regarding + Note that the type of :class:`!ABC` is still :class:`ABCMeta`, therefore + inheriting from :class:`!ABC` requires the usual precautions regarding metaclass usage, as multiple inheritance may lead to metaclass conflicts. One may also define an abstract base class by passing the metaclass - keyword and using :class:`ABCMeta` directly, for example:: + keyword and using :class:`!ABCMeta` directly, for example:: from abc import ABCMeta @@ -65,7 +65,7 @@ a helper class :class:`ABC` to alternatively define ABCs through inheritance: implementations defined by the registering ABC be callable (not even via :func:`super`). [#]_ - Classes created with a metaclass of :class:`ABCMeta` have the following method: + Classes created with a metaclass of :class:`!ABCMeta` have the following method: .. method:: register(subclass) @@ -86,7 +86,7 @@ a helper class :class:`ABC` to alternatively define ABCs through inheritance: Returns the registered subclass, to allow usage as a class decorator. .. versionchanged:: 3.4 - To detect calls to :meth:`register`, you can use the + To detect calls to :meth:`!register`, you can use the :func:`get_cache_token` function. You can also override this method in an abstract base class: @@ -96,10 +96,10 @@ a helper class :class:`ABC` to alternatively define ABCs through inheritance: (Must be defined as a class method.) Check whether *subclass* is considered a subclass of this ABC. This means - that you can customize the behavior of ``issubclass`` further without the + that you can customize the behavior of :func:`issubclass` further without the need to call :meth:`register` on every class you want to consider a subclass of the ABC. (This class method is called from the - :meth:`__subclasscheck__` method of the ABC.) + :meth:`~class.__subclasscheck__` method of the ABC.) This method should return ``True``, ``False`` or ``NotImplemented``. If it returns ``True``, the *subclass* is considered a subclass of this ABC. @@ -142,7 +142,7 @@ a helper class :class:`ABC` to alternatively define ABCs through inheritance: The ABC ``MyIterable`` defines the standard iterable method, :meth:`~iterator.__iter__`, as an abstract method. The implementation given - here can still be called from subclasses. The :meth:`get_iterator` method + here can still be called from subclasses. The :meth:`!get_iterator` method is also part of the ``MyIterable`` abstract base class, but it does not have to be overridden in non-abstract derived classes. @@ -153,14 +153,14 @@ a helper class :class:`ABC` to alternatively define ABCs through inheritance: Finally, the last line makes ``Foo`` a virtual subclass of ``MyIterable``, even though it does not define an :meth:`~iterator.__iter__` method (it uses - the old-style iterable protocol, defined in terms of :meth:`__len__` and - :meth:`__getitem__`). Note that this will not make ``get_iterator`` + the old-style iterable protocol, defined in terms of :meth:`~object.__len__` and + :meth:`~object.__getitem__`). Note that this will not make ``get_iterator`` available as a method of ``Foo``, so it is provided separately. -The :mod:`abc` module also provides the following decorator: +The :mod:`!abc` module also provides the following decorator: .. decorator:: abstractmethod @@ -168,19 +168,19 @@ The :mod:`abc` module also provides the following decorator: Using this decorator requires that the class's metaclass is :class:`ABCMeta` or is derived from it. A class that has a metaclass derived from - :class:`ABCMeta` cannot be instantiated unless all of its abstract methods + :class:`!ABCMeta` cannot be instantiated unless all of its abstract methods and properties are overridden. The abstract methods can be called using any - of the normal 'super' call mechanisms. :func:`abstractmethod` may be used + of the normal 'super' call mechanisms. :func:`!abstractmethod` may be used to declare abstract methods for properties and descriptors. Dynamically adding abstract methods to a class, or attempting to modify the abstraction status of a method or class once it is created, are only supported using the :func:`update_abstractmethods` function. The - :func:`abstractmethod` only affects subclasses derived using regular - inheritance; "virtual subclasses" registered with the ABC's :meth:`register` - method are not affected. + :func:`!abstractmethod` only affects subclasses derived using regular + inheritance; "virtual subclasses" registered with the ABC's + :meth:`~ABCMeta.register` method are not affected. - When :func:`abstractmethod` is applied in combination with other method + When :func:`!abstractmethod` is applied in combination with other method descriptors, it should be applied as the innermost decorator, as shown in the following usage examples:: @@ -216,7 +216,7 @@ The :mod:`abc` module also provides the following decorator: In order to correctly interoperate with the abstract base class machinery, the descriptor must identify itself as abstract using - :attr:`__isabstractmethod__`. In general, this attribute should be ``True`` + :attr:`!__isabstractmethod__`. In general, this attribute should be ``True`` if any of the methods used to compose the descriptor are abstract. For example, Python's built-in :class:`property` does the equivalent of:: @@ -236,7 +236,7 @@ The :mod:`abc` module also provides the following decorator: super-call in a framework that uses cooperative multiple-inheritance. -The :mod:`abc` module also supports the following legacy decorators: +The :mod:`!abc` module also supports the following legacy decorators: .. decorator:: abstractclassmethod @@ -323,7 +323,7 @@ The :mod:`abc` module also supports the following legacy decorators: ... -The :mod:`abc` module also provides the following functions: +The :mod:`!abc` module also provides the following functions: .. function:: get_cache_token() diff --git a/Doc/library/ast.rst b/Doc/library/ast.rst index cd657aedf6d23d..c943c2f498173e 100644 --- a/Doc/library/ast.rst +++ b/Doc/library/ast.rst @@ -45,7 +45,7 @@ Node classes This is the base of all AST node classes. The actual node classes are derived from the :file:`Parser/Python.asdl` file, which is reproduced - :ref:`above `. They are defined in the :mod:`_ast` C + :ref:`above `. They are defined in the :mod:`!_ast` C module and re-exported in :mod:`ast`. There is one class defined for each left-hand side symbol in the abstract @@ -128,14 +128,14 @@ Node classes .. deprecated:: 3.8 - Old classes :class:`ast.Num`, :class:`ast.Str`, :class:`ast.Bytes`, - :class:`ast.NameConstant` and :class:`ast.Ellipsis` are still available, + Old classes :class:`!ast.Num`, :class:`!ast.Str`, :class:`!ast.Bytes`, + :class:`!ast.NameConstant` and :class:`!ast.Ellipsis` are still available, but they will be removed in future Python releases. In the meantime, instantiating them will return an instance of a different class. .. deprecated:: 3.9 - Old classes :class:`ast.Index` and :class:`ast.ExtSlice` are still + Old classes :class:`!ast.Index` and :class:`!ast.ExtSlice` are still available, but they will be removed in future Python releases. In the meantime, instantiating them will return an instance of a different class. @@ -585,7 +585,7 @@ Expressions :class:`Name` or :class:`Attribute` object. Of the arguments: * ``args`` holds a list of the arguments passed by position. - * ``keywords`` holds a list of :class:`keyword` objects representing + * ``keywords`` holds a list of :class:`.keyword` objects representing arguments passed by keyword. When creating a ``Call`` node, ``args`` and ``keywords`` are required, but @@ -650,10 +650,10 @@ Expressions .. class:: NamedExpr(target, value) - A named expression. This AST node is produced by the assignment expressions - operator (also known as the walrus operator). As opposed to the :class:`Assign` - node in which the first argument can be multiple nodes, in this case both - ``target`` and ``value`` must be single nodes. + A named expression. This AST node is produced by the assignment expressions + operator (also known as the walrus operator). As opposed to the :class:`Assign` + node in which the first argument can be multiple nodes, in this case both + ``target`` and ``value`` must be single nodes. .. doctest:: @@ -663,6 +663,7 @@ Expressions target=Name(id='x', ctx=Store()), value=Constant(value=4))) + .. versionadded:: 3.8 Subscripting ~~~~~~~~~~~~ @@ -1036,6 +1037,7 @@ Statements value=Name(id='int', ctx=Load()))], type_ignores=[]) + .. versionadded:: 3.12 Other statements which are only applicable inside functions or loops are described in other sections. @@ -1318,6 +1320,7 @@ Control flow finalbody=[])], type_ignores=[]) + .. versionadded:: 3.11 .. class:: ExceptHandler(type, name, body) @@ -1407,6 +1410,8 @@ Pattern matching that is being matched against the cases) and ``cases`` contains an iterable of :class:`match_case` nodes with the different cases. + .. versionadded:: 3.10 + .. class:: match_case(pattern, guard, body) A single case pattern in a ``match`` statement. ``pattern`` contains the @@ -1458,6 +1463,8 @@ Pattern matching value=Constant(value=Ellipsis))])])], type_ignores=[]) + .. versionadded:: 3.10 + .. class:: MatchValue(value) A match literal or value pattern that compares by equality. ``value`` is @@ -1485,6 +1492,8 @@ Pattern matching value=Constant(value=Ellipsis))])])], type_ignores=[]) + .. versionadded:: 3.10 + .. class:: MatchSingleton(value) A match literal pattern that compares by identity. ``value`` is the @@ -1510,6 +1519,8 @@ Pattern matching value=Constant(value=Ellipsis))])])], type_ignores=[]) + .. versionadded:: 3.10 + .. class:: MatchSequence(patterns) A match sequence pattern. ``patterns`` contains the patterns to be matched @@ -1541,6 +1552,8 @@ Pattern matching value=Constant(value=Ellipsis))])])], type_ignores=[]) + .. versionadded:: 3.10 + .. class:: MatchStar(name) Matches the rest of the sequence in a variable length match sequence pattern. @@ -1581,6 +1594,8 @@ Pattern matching value=Constant(value=Ellipsis))])])], type_ignores=[]) + .. versionadded:: 3.10 + .. class:: MatchMapping(keys, patterns, rest) A match mapping pattern. ``keys`` is a sequence of expression nodes. @@ -1627,6 +1642,8 @@ Pattern matching value=Constant(value=Ellipsis))])])], type_ignores=[]) + .. versionadded:: 3.10 + .. class:: MatchClass(cls, patterns, kwd_attrs, kwd_patterns) A match class pattern. ``cls`` is an expression giving the nominal class to @@ -1691,6 +1708,8 @@ Pattern matching value=Constant(value=Ellipsis))])])], type_ignores=[]) + .. versionadded:: 3.10 + .. class:: MatchAs(pattern, name) A match "as-pattern", capture pattern or wildcard pattern. ``pattern`` @@ -1732,6 +1751,8 @@ Pattern matching value=Constant(value=Ellipsis))])])], type_ignores=[]) + .. versionadded:: 3.10 + .. class:: MatchOr(patterns) A match "or-pattern". An or-pattern matches each of its subpatterns in turn @@ -1764,6 +1785,8 @@ Pattern matching value=Constant(value=Ellipsis))])])], type_ignores=[]) + .. versionadded:: 3.10 + .. _ast-type-params: Type parameters @@ -1795,6 +1818,8 @@ aliases. ctx=Load()))], type_ignores=[]) + .. versionadded:: 3.12 + .. class:: ParamSpec(name) A :class:`typing.ParamSpec`. ``name`` is the name of the parameter specification. @@ -1818,6 +1843,8 @@ aliases. ctx=Load()))], type_ignores=[]) + .. versionadded:: 3.12 + .. class:: TypeVarTuple(name) A :class:`typing.TypeVarTuple`. ``name`` is the name of the type variable tuple. @@ -1842,6 +1869,8 @@ aliases. ctx=Load()))], type_ignores=[]) + .. versionadded:: 3.12 + Function and class definitions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -1861,6 +1890,9 @@ Function and class definitions ``type_comment`` is an optional string with the type annotation as a comment. + .. versionchanged:: 3.12 + Added ``type_params``. + .. class:: Lambda(args, body) @@ -1903,8 +1935,7 @@ Function and class definitions .. class:: arg(arg, annotation, type_comment) A single argument in a list. ``arg`` is a raw string of the argument - name, ``annotation`` is its annotation, such as a :class:`Str` or - :class:`Name` node. + name; ``annotation`` is its annotation, such as a :class:`Name` node. .. attribute:: type_comment @@ -2024,7 +2055,7 @@ Function and class definitions * ``name`` is a raw string for the class name * ``bases`` is a list of nodes for explicitly specified base classes. - * ``keywords`` is a list of :class:`keyword` nodes, principally for 'metaclass'. + * ``keywords`` is a list of :class:`.keyword` nodes, principally for 'metaclass'. Other keywords will be passed to the metaclass, as per `PEP-3115 `_. * ``body`` is a list of nodes representing the code within the class @@ -2059,6 +2090,9 @@ Function and class definitions type_params=[])], type_ignores=[]) + .. versionchanged:: 3.12 + Added ``type_params``. + Async and await ^^^^^^^^^^^^^^^ @@ -2067,6 +2101,9 @@ Async and await An ``async def`` function definition. Has the same fields as :class:`FunctionDef`. + .. versionchanged:: 3.12 + Added ``type_params``. + .. class:: Await(value) @@ -2122,10 +2159,12 @@ Async and await Apart from the node classes, the :mod:`ast` module defines these utility functions and classes for traversing abstract syntax trees: -.. function:: parse(source, filename='', mode='exec', *, type_comments=False, feature_version=None) +.. function:: parse(source, filename='', mode='exec', *, type_comments=False, feature_version=None, optimize=-1) Parse the source into an AST node. Equivalent to ``compile(source, - filename, mode, ast.PyCF_ONLY_AST)``. + filename, mode, flags=FLAGS_VALUE, optimize=optimize)``, + where ``FLAGS_VALUE`` is ``ast.PyCF_ONLY_AST`` if ``optimize <= 0`` + and ``ast.PyCF_OPTIMIZED_AST`` otherwise. If ``type_comments=True`` is given, the parser is modified to check and return type comments as specified by :pep:`484` and :pep:`526`. @@ -2170,7 +2209,8 @@ and classes for traversing abstract syntax trees: Added ``type_comments``, ``mode='func_type'`` and ``feature_version``. .. versionchanged:: 3.13 - The minimum supported version for feature_version is now (3,7) + The minimum supported version for ``feature_version`` is now ``(3, 7)``. + The ``optimize`` argument was added. .. function:: unparse(ast_obj) @@ -2245,8 +2285,8 @@ and classes for traversing abstract syntax trees: .. function:: get_source_segment(source, node, *, padded=False) Get source code segment of the *source* that generated *node*. - If some location information (:attr:`lineno`, :attr:`end_lineno`, - :attr:`col_offset`, or :attr:`end_col_offset`) is missing, return ``None``. + If some location information (:attr:`~ast.AST.lineno`, :attr:`~ast.AST.end_lineno`, + :attr:`~ast.AST.col_offset`, or :attr:`~ast.AST.end_col_offset`) is missing, return ``None``. If *padded* is ``True``, the first line of a multi-line statement will be padded with spaces to match its original position. @@ -2257,7 +2297,7 @@ and classes for traversing abstract syntax trees: .. function:: fix_missing_locations(node) When you compile a node tree with :func:`compile`, the compiler expects - :attr:`lineno` and :attr:`col_offset` attributes for every node that supports + :attr:`~ast.AST.lineno` and :attr:`~ast.AST.col_offset` attributes for every node that supports them. This is rather tedious to fill in for generated nodes, so this helper adds these attributes recursively where not already set, by setting them to the values of the parent node. It works recursively starting at *node*. @@ -2272,8 +2312,8 @@ and classes for traversing abstract syntax trees: .. function:: copy_location(new_node, old_node) - Copy source location (:attr:`lineno`, :attr:`col_offset`, :attr:`end_lineno`, - and :attr:`end_col_offset`) from *old_node* to *new_node* if possible, + Copy source location (:attr:`~ast.AST.lineno`, :attr:`~ast.AST.col_offset`, :attr:`~ast.AST.end_lineno`, + and :attr:`~ast.AST.end_col_offset`) from *old_node* to *new_node* if possible, and return *new_node*. @@ -2319,14 +2359,18 @@ and classes for traversing abstract syntax trees: visited unless the visitor calls :meth:`generic_visit` or visits them itself. + .. method:: visit_Constant(node) + + Handles all constant nodes. + Don't use the :class:`NodeVisitor` if you want to apply changes to nodes during traversal. For this a special visitor exists (:class:`NodeTransformer`) that allows modifications. .. deprecated:: 3.8 - Methods :meth:`visit_Num`, :meth:`visit_Str`, :meth:`visit_Bytes`, - :meth:`visit_NameConstant` and :meth:`visit_Ellipsis` are deprecated + Methods :meth:`!visit_Num`, :meth:`!visit_Str`, :meth:`!visit_Bytes`, + :meth:`!visit_NameConstant` and :meth:`!visit_Ellipsis` are deprecated now and will not be called in future Python versions. Add the :meth:`visit_Constant` method to handle all constant nodes. @@ -2355,7 +2399,7 @@ and classes for traversing abstract syntax trees: ) Keep in mind that if the node you're operating on has child nodes you must - either transform the child nodes yourself or call the :meth:`generic_visit` + either transform the child nodes yourself or call the :meth:`~ast.NodeVisitor.generic_visit` method for the node first. For nodes that were part of a collection of statements (that applies to all @@ -2364,7 +2408,7 @@ and classes for traversing abstract syntax trees: If :class:`NodeTransformer` introduces new nodes (that weren't part of original tree) without giving them location information (such as - :attr:`lineno`), :func:`fix_missing_locations` should be called with + :attr:`~ast.AST.lineno`), :func:`fix_missing_locations` should be called with the new sub-tree to recalculate the location information:: tree = ast.parse('foo', mode='eval') @@ -2416,6 +2460,13 @@ effects on the compilation of a program: Generates and returns an abstract syntax tree instead of returning a compiled code object. +.. data:: PyCF_OPTIMIZED_AST + + The returned AST is optimized according to the *optimize* argument + in :func:`compile` or :func:`ast.parse`. + + .. versionadded:: 3.13 + .. data:: PyCF_TYPE_COMMENTS Enables support for :pep:`484` and :pep:`526` style type comments @@ -2442,26 +2493,26 @@ The following options are accepted: .. program:: ast -.. cmdoption:: -h, --help +.. option:: -h, --help Show the help message and exit. -.. cmdoption:: -m - --mode +.. option:: -m + --mode Specify what kind of code must be compiled, like the *mode* argument in :func:`parse`. -.. cmdoption:: --no-type-comments +.. option:: --no-type-comments Don't parse type comments. -.. cmdoption:: -a, --include-attributes +.. option:: -a, --include-attributes Include attributes such as line numbers and column offsets. -.. cmdoption:: -i - --indent +.. option:: -i + --indent Indentation of nodes in AST (number of spaces). diff --git a/Doc/library/asyncio-dev.rst b/Doc/library/asyncio-dev.rst index c7d97008fb490e..a9c3a0183bb72d 100644 --- a/Doc/library/asyncio-dev.rst +++ b/Doc/library/asyncio-dev.rst @@ -99,7 +99,7 @@ To schedule a coroutine object from a different OS thread, the # Wait for the result: result = future.result() -To handle signals and to execute subprocesses, the event loop must be +To handle signals the event loop must be run in the main thread. The :meth:`loop.run_in_executor` method can be used with a diff --git a/Doc/library/asyncio-eventloop.rst b/Doc/library/asyncio-eventloop.rst index 8f2d8f336c82bb..828e506a72c937 100644 --- a/Doc/library/asyncio-eventloop.rst +++ b/Doc/library/asyncio-eventloop.rst @@ -243,9 +243,9 @@ Scheduling callbacks See the :ref:`concurrency and multithreading ` section of the documentation. -.. versionchanged:: 3.7 - The *context* keyword-only parameter was added. See :pep:`567` - for more details. + .. versionchanged:: 3.7 + The *context* keyword-only parameter was added. See :pep:`567` + for more details. .. _asyncio-pass-keywords: @@ -509,7 +509,7 @@ Opening network connections .. versionchanged:: 3.6 - The socket option :py:const:`~socket.TCP_NODELAY` is set by default + The socket option :ref:`socket.TCP_NODELAY ` is set by default for all TCP connections. .. versionchanged:: 3.7 @@ -581,7 +581,7 @@ Opening network connections * *reuse_port* tells the kernel to allow this endpoint to be bound to the same port as other existing endpoints are bound to, so long as they all set this flag when being created. This option is not supported on Windows - and some Unixes. If the :py:const:`~socket.SO_REUSEPORT` constant is not + and some Unixes. If the :ref:`socket.SO_REUSEPORT ` constant is not defined then this capability is unsupported. * *allow_broadcast* tells the kernel to allow this endpoint to send @@ -607,7 +607,8 @@ Opening network connections .. versionchanged:: 3.8.1 The *reuse_address* parameter is no longer supported, as using - :py:const:`~sockets.SO_REUSEADDR` poses a significant security concern for + :ref:`socket.SO_REUSEADDR ` + poses a significant security concern for UDP. Explicitly passing ``reuse_address=True`` will raise an exception. When multiple processes with differing UIDs assign sockets to an @@ -616,7 +617,8 @@ Opening network connections For supported platforms, *reuse_port* can be used as a replacement for similar functionality. With *reuse_port*, - :py:const:`~sockets.SO_REUSEPORT` is used instead, which specifically + :ref:`socket.SO_REUSEPORT ` + is used instead, which specifically prevents processes with differing UIDs from assigning sockets to the same socket address. @@ -661,12 +663,15 @@ Opening network connections Creating network servers ^^^^^^^^^^^^^^^^^^^^^^^^ +.. _loop_create_server: + .. coroutinemethod:: loop.create_server(protocol_factory, \ host=None, port=None, *, \ family=socket.AF_UNSPEC, \ flags=socket.AI_PASSIVE, \ sock=None, backlog=100, ssl=None, \ reuse_address=None, reuse_port=None, \ + keep_alive=None, \ ssl_handshake_timeout=None, \ ssl_shutdown_timeout=None, \ start_serving=True) @@ -731,6 +736,13 @@ Creating network servers set this flag when being created. This option is not supported on Windows. + * *keep_alive* set to ``True`` keeps connections active by enabling the + periodic transmission of messages. + + .. versionchanged:: 3.13 + + Added the *keep_alive* parameter. + * *ssl_handshake_timeout* is (for a TLS server) the time in seconds to wait for the TLS handshake to complete before aborting the connection. ``60.0`` seconds if ``None`` (default). @@ -756,7 +768,7 @@ Creating network servers .. versionchanged:: 3.6 Added *ssl_handshake_timeout* and *start_serving* parameters. - The socket option :py:const:`~socket.TCP_NODELAY` is set by default + The socket option :ref:`socket.TCP_NODELAY ` is set by default for all TCP connections. .. versionchanged:: 3.11 @@ -774,7 +786,7 @@ Creating network servers *, sock=None, backlog=100, ssl=None, \ ssl_handshake_timeout=None, \ ssl_shutdown_timeout=None, \ - start_serving=True) + start_serving=True, cleanup_socket=True) Similar to :meth:`loop.create_server` but works with the :py:const:`~socket.AF_UNIX` socket family. @@ -784,6 +796,10 @@ Creating network servers :class:`str`, :class:`bytes`, and :class:`~pathlib.Path` paths are supported. + If *cleanup_socket* is True then the Unix socket will automatically + be removed from the filesystem when the server is closed, unless the + socket has been replaced after the server has been created. + See the documentation of the :meth:`loop.create_server` method for information about arguments to this method. @@ -798,6 +814,10 @@ Creating network servers Added the *ssl_shutdown_timeout* parameter. + .. versionchanged:: 3.13 + + Added the *cleanup_socket* parameter. + .. coroutinemethod:: loop.connect_accepted_socket(protocol_factory, \ sock, *, ssl=None, ssl_handshake_timeout=None, \ @@ -1191,6 +1211,8 @@ Working with pipes Unix signals ^^^^^^^^^^^^ +.. _loop_add_signal_handler: + .. method:: loop.add_signal_handler(signum, callback, *args) Set *callback* as the handler for the *signum* signal. @@ -1391,6 +1413,14 @@ Enabling debug mode The new :ref:`Python Development Mode ` can now also be used to enable the debug mode. +.. attribute:: loop.slow_callback_duration + + This attribute can be used to set the + minimum execution duration in seconds that is considered "slow". + When debug mode is enabled, "slow" callbacks are logged. + + Default value is 100 milliseconds. + .. seealso:: The :ref:`debug mode of asyncio `. @@ -1411,6 +1441,8 @@ async/await code consider using the high-level :ref:`Subprocess Support on Windows ` for details. +.. _loop_subprocess_exec: + .. coroutinemethod:: loop.subprocess_exec(protocol_factory, *args, \ stdin=subprocess.PIPE, stdout=subprocess.PIPE, \ stderr=subprocess.PIPE, **kwargs) @@ -1442,6 +1474,7 @@ async/await code consider using the high-level * *stdin* can be any of these: * a file-like object + * an existing file descriptor (a positive integer), for example those created with :meth:`os.pipe()` * the :const:`subprocess.PIPE` constant (default) which will create a new pipe and connect it, * the value ``None`` which will make the subprocess inherit the file @@ -1604,8 +1637,9 @@ Do not instantiate the :class:`Server` class directly. The sockets that represent existing incoming client connections are left open. - The server is closed asynchronously, use the :meth:`wait_closed` - coroutine to wait until the server is closed. + The server is closed asynchronously; use the :meth:`wait_closed` + coroutine to wait until the server is closed (and no more + connections are active). .. method:: get_loop() @@ -1663,7 +1697,8 @@ Do not instantiate the :class:`Server` class directly. .. coroutinemethod:: wait_closed() - Wait until the :meth:`close` method completes. + Wait until the :meth:`close` method completes and all active + connections have finished. .. attribute:: sockets @@ -1685,13 +1720,13 @@ Event Loop Implementations asyncio ships with two different event loop implementations: :class:`SelectorEventLoop` and :class:`ProactorEventLoop`. -By default asyncio is configured to use :class:`SelectorEventLoop` -on Unix and :class:`ProactorEventLoop` on Windows. +By default asyncio is configured to use :class:`EventLoop`. .. class:: SelectorEventLoop - An event loop based on the :mod:`selectors` module. + A subclass of :class:`AbstractEventLoop` based on the + :mod:`selectors` module. Uses the most efficient *selector* available for the given platform. It is also possible to manually configure the @@ -1713,7 +1748,7 @@ on Unix and :class:`ProactorEventLoop` on Windows. .. class:: ProactorEventLoop - An event loop for Windows that uses "I/O Completion Ports" (IOCP). + A subclass of :class:`AbstractEventLoop` for Windows that uses "I/O Completion Ports" (IOCP). .. availability:: Windows. @@ -1722,6 +1757,14 @@ on Unix and :class:`ProactorEventLoop` on Windows. `MSDN documentation on I/O Completion Ports `_. +.. class:: EventLoop + + An alias to the most efficient available subclass of :class:`AbstractEventLoop` for the given + platform. + + It is an alias to :class:`SelectorEventLoop` on Unix and :class:`ProactorEventLoop` on Windows. + + .. versionadded:: 3.13 .. class:: AbstractEventLoop @@ -1871,7 +1914,7 @@ Set signal handlers for SIGINT and SIGTERM (This ``signals`` example only works on Unix.) -Register handlers for signals :py:data:`SIGINT` and :py:data:`SIGTERM` +Register handlers for signals :const:`~signal.SIGINT` and :const:`~signal.SIGTERM` using the :meth:`loop.add_signal_handler` method:: import asyncio diff --git a/Doc/library/asyncio-llapi-index.rst b/Doc/library/asyncio-llapi-index.rst index 9ce48a24444e66..67136ba69ec875 100644 --- a/Doc/library/asyncio-llapi-index.rst +++ b/Doc/library/asyncio-llapi-index.rst @@ -484,19 +484,19 @@ Protocol classes can implement the following **callback methods**: :widths: 50 50 :class: full-width-table - * - ``callback`` :meth:`pipe_data_received() - ` + * - ``callback`` :meth:`~SubprocessProtocol.pipe_data_received` - Called when the child process writes data into its *stdout* or *stderr* pipe. - * - ``callback`` :meth:`pipe_connection_lost() - ` + * - ``callback`` :meth:`~SubprocessProtocol.pipe_connection_lost` - Called when one of the pipes communicating with the child process is closed. * - ``callback`` :meth:`process_exited() ` - - Called when the child process has exited. + - Called when the child process has exited. It can be called before + :meth:`~SubprocessProtocol.pipe_data_received` and + :meth:`~SubprocessProtocol.pipe_connection_lost` methods. Event Loop Policies diff --git a/Doc/library/asyncio-policy.rst b/Doc/library/asyncio-policy.rst index 0d7821e608ec98..346b740a8f757a 100644 --- a/Doc/library/asyncio-policy.rst +++ b/Doc/library/asyncio-policy.rst @@ -237,7 +237,7 @@ implementation used by the asyncio event loop: It works reliably even when the asyncio event loop is run in a non-main OS thread. - There is no noticeable overhead when handling a big number of children (*O(1)* each + There is no noticeable overhead when handling a big number of children (*O*\ (1) each time a child terminates), but starting a thread per process requires extra memory. This watcher is used by default. @@ -257,7 +257,7 @@ implementation used by the asyncio event loop: watcher is installed. The solution is safe but it has a significant overhead when - handling a big number of processes (*O(n)* each time a + handling a big number of processes (*O*\ (*n*) each time a :py:data:`SIGCHLD` is received). .. versionadded:: 3.8 @@ -273,7 +273,7 @@ implementation used by the asyncio event loop: The watcher avoids disrupting other code spawning processes by polling every process explicitly on a :py:data:`SIGCHLD` signal. - This solution is as safe as :class:`MultiLoopChildWatcher` and has the same *O(N)* + This solution is as safe as :class:`MultiLoopChildWatcher` and has the same *O*\ (*n*) complexity but requires a running event loop in the main thread to work. .. deprecated:: 3.12 @@ -285,7 +285,7 @@ implementation used by the asyncio event loop: processes and waiting for their termination. There is no noticeable overhead when handling a big number of - children (*O(1)* each time a child terminates). + children (*O*\ (1) each time a child terminates). This solution requires a running event loop in the main thread to work, as :class:`SafeChildWatcher`. diff --git a/Doc/library/asyncio-protocol.rst b/Doc/library/asyncio-protocol.rst index 7bc906eaafc1f2..3f734f544afe21 100644 --- a/Doc/library/asyncio-protocol.rst +++ b/Doc/library/asyncio-protocol.rst @@ -708,6 +708,9 @@ factories passed to the :meth:`loop.subprocess_exec` and Called when the child process has exited. + It can be called before :meth:`~SubprocessProtocol.pipe_data_received` and + :meth:`~SubprocessProtocol.pipe_connection_lost` methods. + Examples ======== @@ -746,7 +749,7 @@ received data, and close the connection:: loop = asyncio.get_running_loop() server = await loop.create_server( - lambda: EchoServerProtocol(), + EchoServerProtocol, '127.0.0.1', 8888) async with server: @@ -850,7 +853,7 @@ method, sends back received data:: # One protocol instance will be created to serve all # client requests. transport, protocol = await loop.create_datagram_endpoint( - lambda: EchoServerProtocol(), + EchoServerProtocol, local_addr=('127.0.0.1', 9999)) try: @@ -1003,12 +1006,26 @@ The subprocess is created by the :meth:`loop.subprocess_exec` method:: def __init__(self, exit_future): self.exit_future = exit_future self.output = bytearray() + self.pipe_closed = False + self.exited = False + + def pipe_connection_lost(self, fd, exc): + self.pipe_closed = True + self.check_for_exit() def pipe_data_received(self, fd, data): self.output.extend(data) def process_exited(self): - self.exit_future.set_result(True) + self.exited = True + # process_exited() method can be called before + # pipe_connection_lost() method: wait until both methods are + # called. + self.check_for_exit() + + def check_for_exit(self): + if self.pipe_closed and self.exited: + self.exit_future.set_result(True) async def get_date(): # Get a reference to the event loop as we plan to use diff --git a/Doc/library/asyncio-runner.rst b/Doc/library/asyncio-runner.rst index b68b2570ef071e..ec170dfde9e9aa 100644 --- a/Doc/library/asyncio-runner.rst +++ b/Doc/library/asyncio-runner.rst @@ -42,6 +42,8 @@ Running an asyncio Program This function should be used as a main entry point for asyncio programs, and should ideally only be called once. It is recommended to use *loop_factory* to configure the event loop instead of policies. + Passing :class:`asyncio.EventLoop` allows running asyncio without the + policy system. The executor is given a timeout duration of 5 minutes to shutdown. If the executor hasn't finished within that duration, a warning is diff --git a/Doc/library/asyncio-stream.rst b/Doc/library/asyncio-stream.rst index bbac1c32b5695f..0736e783bbc8c8 100644 --- a/Doc/library/asyncio-stream.rst +++ b/Doc/library/asyncio-stream.rst @@ -157,8 +157,8 @@ and work with streams: .. versionchanged:: 3.10 Removed the *loop* parameter. - .. versionchanged:: 3.11 - Added the *ssl_shutdown_timeout* parameter. + .. versionchanged:: 3.11 + Added the *ssl_shutdown_timeout* parameter. .. coroutinefunction:: start_unix_server(client_connected_cb, path=None, \ @@ -204,6 +204,10 @@ StreamReader directly; use :func:`open_connection` and :func:`start_server` instead. + .. method:: feed_eof() + + Acknowledge the EOF. + .. coroutinemethod:: read(n=-1) Read up to *n* bytes from the stream. diff --git a/Doc/library/asyncio-task.rst b/Doc/library/asyncio-task.rst index 0651ff7213e527..797065c8ccf894 100644 --- a/Doc/library/asyncio-task.rst +++ b/Doc/library/asyncio-task.rst @@ -631,9 +631,9 @@ Shielding From Cancellation Timeouts ======== -.. coroutinefunction:: timeout(delay) +.. function:: timeout(delay) - An :ref:`asynchronous context manager ` + Return an :ref:`asynchronous context manager ` that can be used to limit the amount of time spent waiting on something. @@ -724,7 +724,7 @@ Timeouts .. versionadded:: 3.11 -.. coroutinefunction:: timeout_at(when) +.. function:: timeout_at(when) Similar to :func:`asyncio.timeout`, except *when* is the absolute time to stop waiting, or ``None``. @@ -767,9 +767,6 @@ Timeouts If the wait is cancelled, the future *aw* is also cancelled. - .. versionchanged:: 3.10 - Removed the *loop* parameter. - .. _asyncio_example_waitfor: Example:: @@ -800,6 +797,9 @@ Timeouts .. versionchanged:: 3.10 Removed the *loop* parameter. + .. versionchanged:: 3.11 + Raises :exc:`TimeoutError` instead of :exc:`asyncio.TimeoutError`. + Waiting Primitives ================== diff --git a/Doc/library/asyncio.rst b/Doc/library/asyncio.rst index c6a046f534e9a1..5f33c6813e74c0 100644 --- a/Doc/library/asyncio.rst +++ b/Doc/library/asyncio.rst @@ -46,9 +46,9 @@ Additionally, there are **low-level** APIs for *library and framework developers* to: * create and manage :ref:`event loops `, which - provide asynchronous APIs for :meth:`networking `, - running :meth:`subprocesses `, - handling :meth:`OS signals `, etc; + provide asynchronous APIs for :ref:`networking `, + running :ref:`subprocesses `, + handling :ref:`OS signals `, etc; * implement efficient protocols using :ref:`transports `; @@ -56,6 +56,8 @@ Additionally, there are **low-level** APIs for * :ref:`bridge ` callback-based libraries and code with async/await syntax. +.. _asyncio-cli: + You can experiment with an ``asyncio`` concurrent context in the REPL: .. code-block:: pycon diff --git a/Doc/library/bdb.rst b/Doc/library/bdb.rst index d201dc963b5995..4ce5c9bcde38ff 100644 --- a/Doc/library/bdb.rst +++ b/Doc/library/bdb.rst @@ -294,7 +294,7 @@ The :mod:`bdb` module also defines two classes: .. method:: set_quit() Set the :attr:`quitting` attribute to ``True``. This raises :exc:`BdbQuit` in - the next call to one of the :meth:`dispatch_\*` methods. + the next call to one of the :meth:`!dispatch_\*` methods. Derived classes and clients can call the following methods to manipulate diff --git a/Doc/library/binascii.rst b/Doc/library/binascii.rst index e9f6f0e09de27b..39fabb59bb1984 100644 --- a/Doc/library/binascii.rst +++ b/Doc/library/binascii.rst @@ -57,10 +57,11 @@ The :mod:`binascii` module defines the following functions: data will raise :exc:`binascii.Error`. Valid base64: - * Conforms to :rfc:`3548`. - * Contains only characters from the base64 alphabet. - * Contains no excess data after padding (including excess padding, newlines, etc.). - * Does not start with a padding. + + * Conforms to :rfc:`3548`. + * Contains only characters from the base64 alphabet. + * Contains no excess data after padding (including excess padding, newlines, etc.). + * Does not start with a padding. .. versionchanged:: 3.11 Added the *strict_mode* parameter. diff --git a/Doc/library/bisect.rst b/Doc/library/bisect.rst index 8022c596f0af97..31c79b91061591 100644 --- a/Doc/library/bisect.rst +++ b/Doc/library/bisect.rst @@ -19,9 +19,9 @@ linear searches or frequent resorting. The module is called :mod:`bisect` because it uses a basic bisection algorithm to do its work. Unlike other bisection tools that search for a specific value, the functions in this module are designed to locate an -insertion point. Accordingly, the functions never call an :meth:`__eq__` +insertion point. Accordingly, the functions never call an :meth:`~object.__eq__` method to determine whether a value has been found. Instead, the -functions only call the :meth:`__lt__` method and will return an insertion +functions only call the :meth:`~object.__lt__` method and will return an insertion point between values in an array. .. _bisect functions: @@ -73,13 +73,13 @@ The following functions are provided: Insert *x* in *a* in sorted order. This function first runs :py:func:`~bisect.bisect_left` to locate an insertion point. - Next, it runs the :meth:`insert` method on *a* to insert *x* at the + Next, it runs the :meth:`!insert` method on *a* to insert *x* at the appropriate position to maintain sort order. To support inserting records in a table, the *key* function (if any) is applied to *x* for the search step but not for the insertion step. - Keep in mind that the ``O(log n)`` search is dominated by the slow O(n) + Keep in mind that the *O*\ (log *n*) search is dominated by the slow *O*\ (*n*) insertion step. .. versionchanged:: 3.10 @@ -93,13 +93,13 @@ The following functions are provided: entries of *x*. This function first runs :py:func:`~bisect.bisect_right` to locate an insertion point. - Next, it runs the :meth:`insert` method on *a* to insert *x* at the + Next, it runs the :meth:`!insert` method on *a* to insert *x* at the appropriate position to maintain sort order. To support inserting records in a table, the *key* function (if any) is applied to *x* for the search step but not for the insertion step. - Keep in mind that the ``O(log n)`` search is dominated by the slow O(n) + Keep in mind that the *O*\ (log *n*) search is dominated by the slow *O*\ (*n*) insertion step. .. versionchanged:: 3.10 @@ -115,7 +115,7 @@ thoughts in mind: * Bisection is effective for searching ranges of values. For locating specific values, dictionaries are more performant. -* The *insort()* functions are ``O(n)`` because the logarithmic search step +* The *insort()* functions are *O*\ (*n*) because the logarithmic search step is dominated by the linear time insertion step. * The search functions are stateless and discard key function results after diff --git a/Doc/library/bz2.rst b/Doc/library/bz2.rst index ec4aeaa04395ac..6a95a4a6e8d183 100644 --- a/Doc/library/bz2.rst +++ b/Doc/library/bz2.rst @@ -91,7 +91,7 @@ The :mod:`bz2` module contains: and :meth:`~io.IOBase.truncate`. Iteration and the :keyword:`with` statement are supported. - :class:`BZ2File` also provides the following method: + :class:`BZ2File` also provides the following methods: .. method:: peek([n]) @@ -106,14 +106,52 @@ The :mod:`bz2` module contains: .. versionadded:: 3.3 + .. method:: fileno() + + Return the file descriptor for the underlying file. + + .. versionadded:: 3.3 + + .. method:: readable() + + Return whether the file was opened for reading. + + .. versionadded:: 3.3 + + .. method:: seekable() + + Return whether the file supports seeking. + + .. versionadded:: 3.3 + + .. method:: writable() + + Return whether the file was opened for writing. + + .. versionadded:: 3.3 + + .. method:: read1(size=-1) + + Read up to *size* uncompressed bytes, while trying to avoid + making multiple reads from the underlying stream. Reads up to a + buffer's worth of data if size is negative. + + Returns ``b''`` if the file is at EOF. + + .. versionadded:: 3.3 + + .. method:: readinto(b) + + Read bytes into *b*. + + Returns the number of bytes read (0 for EOF). + + .. versionadded:: 3.3 + .. versionchanged:: 3.1 Support for the :keyword:`with` statement was added. - .. versionchanged:: 3.3 - The :meth:`fileno`, :meth:`readable`, :meth:`seekable`, :meth:`writable`, - :meth:`read1` and :meth:`readinto` methods were added. - .. versionchanged:: 3.3 Support was added for *filename* being a :term:`file object` instead of an actual filename. diff --git a/Doc/library/calendar.rst b/Doc/library/calendar.rst index 07d04a1c7b582a..6586f539a8da4f 100644 --- a/Doc/library/calendar.rst +++ b/Doc/library/calendar.rst @@ -28,58 +28,6 @@ interpreted as prescribed by the ISO 8601 standard. Year 0 is 1 BC, year -1 is 2 BC, and so on. -.. class:: Day - - Enumeration defining the days of the week as integer constants, from 0 to 6. - - .. attribute:: MONDAY - - .. attribute:: TUESDAY - - .. attribute:: WEDNESDAY - - .. attribute:: THURSDAY - - .. attribute:: FRIDAY - - .. attribute:: SATURDAY - - .. attribute:: SUNDAY - - .. versionadded:: 3.12 - - -.. class:: Month - - Enumeration defining months of the year as integer constants, from 1 to 12. - - .. attribute:: JANUARY - - .. attribute:: FEBRUARY - - .. attribute:: MARCH - - .. attribute:: APRIL - - .. attribute:: MAY - - .. attribute:: JUNE - - .. attribute:: JULY - - .. attribute:: AUGUST - - .. attribute:: SEPTEMBER - - .. attribute:: OCTOBER - - .. attribute:: NOVEMBER - - .. attribute:: DECEMBER - - .. versionadded:: 3.12 - - .. class:: Calendar(firstweekday=0) Creates a :class:`Calendar` object. *firstweekday* is an integer specifying the @@ -248,6 +196,13 @@ interpreted as prescribed by the ISO 8601 standard. Year 0 is 1 BC, year -1 is output (defaulting to the system default encoding). + .. method:: formatmonthname(theyear, themonth, withyear=True) + + Return a month name as an HTML table row. If *withyear* is true the year + will be included in the row, otherwise just the month name will be + used. + + :class:`!HTMLCalendar` has the following attributes you can override to customize the CSS classes used by the calendar: @@ -341,7 +296,7 @@ interpreted as prescribed by the ISO 8601 standard. Year 0 is 1 BC, year -1 is .. note:: - The constructor, :meth:`formatweekday` and :meth:`formatmonthname` methods + The constructor, :meth:`!formatweekday` and :meth:`!formatmonthname` methods of these two classes temporarily change the ``LC_TIME`` locale to the given *locale*. Because the current locale is a process-wide setting, they are not thread-safe. @@ -410,7 +365,7 @@ For simple text calendars this module provides the following functions. .. function:: month(theyear, themonth, w=0, l=0) - Returns a month's calendar in a multi-line string using the :meth:`formatmonth` + Returns a month's calendar in a multi-line string using the :meth:`~TextCalendar.formatmonth` of the :class:`TextCalendar` class. @@ -422,7 +377,7 @@ For simple text calendars this module provides the following functions. .. function:: calendar(year, w=2, l=1, c=6, m=3) Returns a 3-column calendar for an entire year as a multi-line string using - the :meth:`formatyear` of the :class:`TextCalendar` class. + the :meth:`~TextCalendar.formatyear` of the :class:`TextCalendar` class. .. function:: timegm(tuple) @@ -446,6 +401,29 @@ The :mod:`calendar` module exports the following data attributes: An array that represents the abbreviated days of the week in the current locale. +.. data:: MONDAY + TUESDAY + WEDNESDAY + THURSDAY + FRIDAY + SATURDAY + SUNDAY + + Aliases for the days of the week, + where ``MONDAY`` is ``0`` and ``SUNDAY`` is ``6``. + + .. versionadded:: 3.12 + + +.. class:: Day + + Enumeration defining days of the week as integer constants. + The members of this enumeration are exported to the module scope as + :data:`MONDAY` through :data:`SUNDAY`. + + .. versionadded:: 3.12 + + .. data:: month_name An array that represents the months of the year in the current locale. This @@ -459,15 +437,56 @@ The :mod:`calendar` module exports the following data attributes: locale. This follows normal convention of January being month number 1, so it has a length of 13 and ``month_abbr[0]`` is the empty string. -.. data:: MONDAY - TUESDAY - WEDNESDAY - THURSDAY - FRIDAY - SATURDAY - SUNDAY - Aliases for day numbers, where ``MONDAY`` is ``0`` and ``SUNDAY`` is ``6``. +.. data:: JANUARY + FEBRUARY + MARCH + APRIL + MAY + JUNE + JULY + AUGUST + SEPTEMBER + OCTOBER + NOVEMBER + DECEMBER + + Aliases for the months of the year, + where ``JANUARY`` is ``1`` and ``DECEMBER`` is ``12``. + + .. versionadded:: 3.12 + + +.. class:: Month + + Enumeration defining months of the year as integer constants. + The members of this enumeration are exported to the module scope as + :data:`JANUARY` through :data:`DECEMBER`. + + .. versionadded:: 3.12 + + +The :mod:`calendar` module defines the following exceptions: + +.. exception:: IllegalMonthError(month) + + A subclass of :exc:`ValueError`, + raised when the given month number is outside of the range 1-12 (inclusive). + + .. attribute:: month + + The invalid month number. + + +.. exception:: IllegalWeekdayError(weekday) + + A subclass of :exc:`ValueError`, + raised when the given weekday number is outside of the range 0-6 (inclusive). + + .. attribute:: weekday + + The invalid weekday number. + .. seealso:: @@ -477,3 +496,146 @@ The :mod:`calendar` module exports the following data attributes: Module :mod:`time` Low-level time related functions. + + +.. _calendar-cli: + +Command-Line Usage +------------------ + +.. versionadded:: 2.5 + +The :mod:`calendar` module can be executed as a script from the command line +to interactively print a calendar. + +.. code-block:: shell + + python -m calendar [-h] [-L LOCALE] [-e ENCODING] [-t {text,html}] + [-w WIDTH] [-l LINES] [-s SPACING] [-m MONTHS] [-c CSS] + [year] [month] + + +For example, to print a calendar for the year 2000: + +.. code-block:: console + + $ python -m calendar 2000 + 2000 + + January February March + Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su + 1 2 1 2 3 4 5 6 1 2 3 4 5 + 3 4 5 6 7 8 9 7 8 9 10 11 12 13 6 7 8 9 10 11 12 + 10 11 12 13 14 15 16 14 15 16 17 18 19 20 13 14 15 16 17 18 19 + 17 18 19 20 21 22 23 21 22 23 24 25 26 27 20 21 22 23 24 25 26 + 24 25 26 27 28 29 30 28 29 27 28 29 30 31 + 31 + + April May June + Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su + 1 2 1 2 3 4 5 6 7 1 2 3 4 + 3 4 5 6 7 8 9 8 9 10 11 12 13 14 5 6 7 8 9 10 11 + 10 11 12 13 14 15 16 15 16 17 18 19 20 21 12 13 14 15 16 17 18 + 17 18 19 20 21 22 23 22 23 24 25 26 27 28 19 20 21 22 23 24 25 + 24 25 26 27 28 29 30 29 30 31 26 27 28 29 30 + + July August September + Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su + 1 2 1 2 3 4 5 6 1 2 3 + 3 4 5 6 7 8 9 7 8 9 10 11 12 13 4 5 6 7 8 9 10 + 10 11 12 13 14 15 16 14 15 16 17 18 19 20 11 12 13 14 15 16 17 + 17 18 19 20 21 22 23 21 22 23 24 25 26 27 18 19 20 21 22 23 24 + 24 25 26 27 28 29 30 28 29 30 31 25 26 27 28 29 30 + 31 + + October November December + Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su + 1 1 2 3 4 5 1 2 3 + 2 3 4 5 6 7 8 6 7 8 9 10 11 12 4 5 6 7 8 9 10 + 9 10 11 12 13 14 15 13 14 15 16 17 18 19 11 12 13 14 15 16 17 + 16 17 18 19 20 21 22 20 21 22 23 24 25 26 18 19 20 21 22 23 24 + 23 24 25 26 27 28 29 27 28 29 30 25 26 27 28 29 30 31 + 30 31 + + +The following options are accepted: + +.. program:: calendar + + +.. option:: --help, -h + + Show the help message and exit. + + +.. option:: --locale LOCALE, -L LOCALE + + The locale to use for month and weekday names. + Defaults to English. + + +.. option:: --encoding ENCODING, -e ENCODING + + The encoding to use for output. + :option:`--encoding` is required if :option:`--locale` is set. + + +.. option:: --type {text,html}, -t {text,html} + + Print the calendar to the terminal as text, + or as an HTML document. + + +.. option:: year + + The year to print the calendar for. + Must be a number between 1 and 9999. + Defaults to the current year. + + +.. option:: month + + The month of the specified :option:`year` to print the calendar for. + Must be a number between 1 and 12, + and may only be used in text mode. + Defaults to printing a calendar for the full year. + + +*Text-mode options:* + +.. option:: --width WIDTH, -w WIDTH + + The width of the date column in terminal columns. + The date is printed centred in the column. + Any value lower than 2 is ignored. + Defaults to 2. + + +.. option:: --lines LINES, -l LINES + + The number of lines for each week in terminal rows. + The date is printed top-aligned. + Any value lower than 1 is ignored. + Defaults to 1. + + +.. option:: --spacing SPACING, -s SPACING + + The space between months in columns. + Any value lower than 2 is ignored. + Defaults to 6. + + +.. option:: --months MONTHS, -m MONTHS + + The number of months printed per row. + Defaults to 3. + + +*HTML-mode options:* + +.. option:: --css CSS, -c CSS + + The path of a CSS stylesheet to use for the calendar. + This must either be relative to the generated HTML, + or an absolute HTTP or ``file:///`` URL. diff --git a/Doc/library/cmd.rst b/Doc/library/cmd.rst index fd5df96dfd0b3d..39ef4b481478d1 100644 --- a/Doc/library/cmd.rst +++ b/Doc/library/cmd.rst @@ -26,6 +26,13 @@ interface. key; it defaults to :kbd:`Tab`. If *completekey* is not :const:`None` and :mod:`readline` is available, command completion is done automatically. + The default, ``'tab'``, is treated specially, so that it refers to the + :kbd:`Tab` key on every :data:`readline.backend`. + Specifically, if :data:`readline.backend` is ``editline``, + ``Cmd`` will use ``'^I'`` instead of ``'tab'``. + Note that other values are not treated this way, and might only work + with a specific backend. + The optional arguments *stdin* and *stdout* specify the input and output file objects that the Cmd instance or subclass instance will use for input and output. If not specified, they will default to :data:`sys.stdin` and @@ -35,6 +42,9 @@ interface. :attr:`use_rawinput` attribute to ``False``, otherwise *stdin* will be ignored. + .. versionchanged:: 3.13 + ``completekey='tab'`` is replaced by ``'^I'`` for ``editline``. + .. _cmd-objects: @@ -66,29 +76,32 @@ A :class:`Cmd` instance has the following methods: single: ! (exclamation); in a command interpreter An interpreter instance will recognize a command name ``foo`` if and only if it - has a method :meth:`do_foo`. As a special case, a line beginning with the + has a method :meth:`!do_foo`. As a special case, a line beginning with the character ``'?'`` is dispatched to the method :meth:`do_help`. As another special case, a line beginning with the character ``'!'`` is dispatched to the - method :meth:`do_shell` (if such a method is defined). + method :meth:`!do_shell` (if such a method is defined). This method will return when the :meth:`postcmd` method returns a true value. The *stop* argument to :meth:`postcmd` is the return value from the command's - corresponding :meth:`do_\*` method. + corresponding :meth:`!do_\*` method. If completion is enabled, completing commands will be done automatically, and - completing of commands args is done by calling :meth:`complete_foo` with + completing of commands args is done by calling :meth:`!complete_foo` with arguments *text*, *line*, *begidx*, and *endidx*. *text* is the string prefix we are attempting to match: all returned matches must begin with it. *line* is the current input line with leading whitespace removed, *begidx* and *endidx* are the beginning and ending indexes of the prefix text, which could be used to provide different completion depending upon which position the argument is in. - All subclasses of :class:`Cmd` inherit a predefined :meth:`do_help`. This + +.. method:: Cmd.do_help(arg) + + All subclasses of :class:`Cmd` inherit a predefined :meth:`!do_help`. This method, called with an argument ``'bar'``, invokes the corresponding method - :meth:`help_bar`, and if that is not present, prints the docstring of - :meth:`do_bar`, if available. With no argument, :meth:`do_help` lists all + :meth:`!help_bar`, and if that is not present, prints the docstring of + :meth:`!do_bar`, if available. With no argument, :meth:`!do_help` lists all available help topics (that is, all commands with corresponding - :meth:`help_\*` methods or commands that have docstrings), and also lists any + :meth:`!help_\*` methods or commands that have docstrings), and also lists any undocumented commands. @@ -98,7 +111,7 @@ A :class:`Cmd` instance has the following methods: This may be overridden, but should not normally need to be; see the :meth:`precmd` and :meth:`postcmd` methods for useful execution hooks. The return value is a flag indicating whether interpretation of commands by the - interpreter should stop. If there is a :meth:`do_\*` method for the command + interpreter should stop. If there is a :meth:`!do_\*` method for the command *str*, the return value of that method is returned, otherwise the return value from the :meth:`default` method is returned. @@ -118,7 +131,7 @@ A :class:`Cmd` instance has the following methods: .. method:: Cmd.completedefault(text, line, begidx, endidx) Method called to complete an input line when no command-specific - :meth:`complete_\*` method is available. By default, it returns an empty list. + :meth:`!complete_\*` method is available. By default, it returns an empty list. .. method:: Cmd.columnize(list, displaywidth=80) @@ -199,14 +212,14 @@ Instances of :class:`Cmd` subclasses have some public instance variables: .. attribute:: Cmd.misc_header The header to issue if the help output has a section for miscellaneous help - topics (that is, there are :meth:`help_\*` methods without corresponding - :meth:`do_\*` methods). + topics (that is, there are :meth:`!help_\*` methods without corresponding + :meth:`!do_\*` methods). .. attribute:: Cmd.undoc_header The header to issue if the help output has a section for undocumented commands - (that is, there are :meth:`do_\*` methods without corresponding :meth:`help_\*` + (that is, there are :meth:`!do_\*` methods without corresponding :meth:`!help_\*` methods). @@ -219,8 +232,8 @@ Instances of :class:`Cmd` subclasses have some public instance variables: .. attribute:: Cmd.use_rawinput A flag, defaulting to true. If true, :meth:`cmdloop` uses :func:`input` to - display a prompt and read the next command; if false, :meth:`sys.stdout.write` - and :meth:`sys.stdin.readline` are used. (This means that by importing + display a prompt and read the next command; if false, :data:`sys.stdout.write() ` + and :data:`sys.stdin.readline() ` are used. (This means that by importing :mod:`readline`, on systems that support it, the interpreter will automatically support :program:`Emacs`\ -like line editing and command-history keystrokes.) @@ -239,14 +252,14 @@ This section presents a simple example of how to build a shell around a few of the commands in the :mod:`turtle` module. Basic turtle commands such as :meth:`~turtle.forward` are added to a -:class:`Cmd` subclass with method named :meth:`do_forward`. The argument is +:class:`Cmd` subclass with method named :meth:`!do_forward`. The argument is converted to a number and dispatched to the turtle module. The docstring is used in the help utility provided by the shell. The example also includes a basic record and playback facility implemented with the :meth:`~Cmd.precmd` method which is responsible for converting the input to -lowercase and writing the commands to a file. The :meth:`do_playback` method -reads the file and adds the recorded commands to the :attr:`cmdqueue` for +lowercase and writing the commands to a file. The :meth:`!do_playback` method +reads the file and adds the recorded commands to the :attr:`~Cmd.cmdqueue` for immediate playback:: import cmd, sys diff --git a/Doc/library/cmdline.rst b/Doc/library/cmdline.rst new file mode 100644 index 00000000000000..b2379befeffcba --- /dev/null +++ b/Doc/library/cmdline.rst @@ -0,0 +1,57 @@ +++++++++++++++++++++++++++++++++++++ +Modules command-line interface (CLI) +++++++++++++++++++++++++++++++++++++ + +The following modules have a command-line interface. + +* :ref:`ast ` +* :ref:`asyncio ` +* :mod:`base64` +* :ref:`calendar ` +* :mod:`code` +* :ref:`compileall ` +* :mod:`cProfile`: see :ref:`profile ` +* :ref:`difflib ` +* :ref:`dis ` +* :mod:`doctest` +* :mod:`!encodings.rot_13` +* :mod:`ensurepip` +* :mod:`filecmp` +* :mod:`fileinput` +* :mod:`ftplib` +* :ref:`gzip ` +* :ref:`http.server ` +* :mod:`!idlelib` +* :ref:`inspect ` +* :ref:`json.tool ` +* :mod:`mimetypes` +* :mod:`pdb` +* :mod:`pickle` +* :ref:`pickletools ` +* :mod:`platform` +* :mod:`poplib` +* :ref:`profile ` +* :mod:`pstats` +* :ref:`py_compile ` +* :mod:`pyclbr` +* :mod:`pydoc` +* :mod:`quopri` +* :mod:`runpy` +* :ref:`site ` +* :ref:`sqlite3 ` +* :ref:`sysconfig ` +* :mod:`tabnanny` +* :ref:`tarfile ` +* :mod:`!this` +* :ref:`timeit ` +* :ref:`tokenize ` +* :ref:`trace ` +* :mod:`turtledemo` +* :ref:`unittest ` +* :ref:`uuid ` +* :mod:`venv` +* :mod:`webbrowser` +* :ref:`zipapp ` +* :ref:`zipfile ` + +See also the :ref:`Python command-line interface `. diff --git a/Doc/library/code.rst b/Doc/library/code.rst index 3d7f43c86a0557..091840781bd235 100644 --- a/Doc/library/code.rst +++ b/Doc/library/code.rst @@ -23,20 +23,25 @@ build applications which provide an interactive interpreter prompt. ``'__doc__'`` set to ``None``. -.. class:: InteractiveConsole(locals=None, filename="") +.. class:: InteractiveConsole(locals=None, filename="", local_exit=False) Closely emulate the behavior of the interactive Python interpreter. This class builds on :class:`InteractiveInterpreter` and adds prompting using the familiar - ``sys.ps1`` and ``sys.ps2``, and input buffering. + ``sys.ps1`` and ``sys.ps2``, and input buffering. If *local_exit* is True, + ``exit()`` and ``quit()`` in the console will not raise :exc:`SystemExit`, but + instead return to the calling code. + .. versionchanged:: 3.13 + Added *local_exit* parameter. -.. function:: interact(banner=None, readfunc=None, local=None, exitmsg=None) +.. function:: interact(banner=None, readfunc=None, local=None, exitmsg=None, local_exit=False) Convenience function to run a read-eval-print loop. This creates a new instance of :class:`InteractiveConsole` and sets *readfunc* to be used as the :meth:`InteractiveConsole.raw_input` method, if provided. If *local* is provided, it is passed to the :class:`InteractiveConsole` constructor for - use as the default namespace for the interpreter loop. The :meth:`interact` + use as the default namespace for the interpreter loop. If *local_exit* is provided, + it is passed to the :class:`InteractiveConsole` constructor. The :meth:`interact` method of the instance is then run with *banner* and *exitmsg* passed as the banner and exit message to use, if provided. The console object is discarded after use. @@ -44,6 +49,8 @@ build applications which provide an interactive interpreter prompt. .. versionchanged:: 3.6 Added *exitmsg* parameter. + .. versionchanged:: 3.13 + Added *local_exit* parameter. .. function:: compile_command(source, filename="", symbol="single") diff --git a/Doc/library/codecs.rst b/Doc/library/codecs.rst index 8225236350d22e..4617624686b1f3 100644 --- a/Doc/library/codecs.rst +++ b/Doc/library/codecs.rst @@ -345,9 +345,10 @@ The following error handlers can be used with all Python +-------------------------+-----------------------------------------------+ | ``'backslashreplace'`` | Replace with backslashed escape sequences. | | | On encoding, use hexadecimal form of Unicode | -| | code point with formats ``\xhh`` ``\uxxxx`` | -| | ``\Uxxxxxxxx``. On decoding, use hexadecimal | -| | form of byte value with format ``\xhh``. | +| | code point with formats :samp:`\\x{hh}` | +| | :samp:`\\u{xxxx}` :samp:`\\U{xxxxxxxx}`. | +| | On decoding, use hexadecimal form of byte | +| | value with format :samp:`\\x{hh}`. | | | Implemented in | | | :func:`backslashreplace_errors`. | +-------------------------+-----------------------------------------------+ @@ -373,8 +374,9 @@ The following error handlers are only applicable to encoding (within +=========================+===============================================+ | ``'xmlcharrefreplace'`` | Replace with XML/HTML numeric character | | | reference, which is a decimal form of Unicode | -| | code point with format ``&#num;`` Implemented | -| | in :func:`xmlcharrefreplace_errors`. | +| | code point with format :samp:`&#{num};`. | +| | Implemented in | +| | :func:`xmlcharrefreplace_errors`. | +-------------------------+-----------------------------------------------+ | ``'namereplace'`` | Replace with ``\N{...}`` escape sequences, | | | what appears in the braces is the Name | @@ -478,8 +480,9 @@ functions: Malformed data is replaced by a backslashed escape sequence. On encoding, use the hexadecimal form of Unicode code point with formats - ``\xhh`` ``\uxxxx`` ``\Uxxxxxxxx``. On decoding, use the hexadecimal form of - byte value with format ``\xhh``. + :samp:`\\x{hh}` :samp:`\\u{xxxx}` :samp:`\\U{xxxxxxxx}`. + On decoding, use the hexadecimal form of + byte value with format :samp:`\\x{hh}`. .. versionchanged:: 3.5 Works with decoding and translating. @@ -492,7 +495,7 @@ functions: The unencodable character is replaced by an appropriate XML/HTML numeric character reference, which is a decimal form of Unicode code point with - format ``&#num;`` . + format :samp:`&#{num};` . .. function:: namereplace_errors(exception) @@ -517,44 +520,46 @@ The base :class:`Codec` class defines these methods which also define the function interfaces of the stateless encoder and decoder: -.. method:: Codec.encode(input, errors='strict') +.. class:: Codec + + .. method:: encode(input, errors='strict') - Encodes the object *input* and returns a tuple (output object, length consumed). - For instance, :term:`text encoding` converts - a string object to a bytes object using a particular - character set encoding (e.g., ``cp1252`` or ``iso-8859-1``). + Encodes the object *input* and returns a tuple (output object, length consumed). + For instance, :term:`text encoding` converts + a string object to a bytes object using a particular + character set encoding (e.g., ``cp1252`` or ``iso-8859-1``). - The *errors* argument defines the error handling to apply. - It defaults to ``'strict'`` handling. + The *errors* argument defines the error handling to apply. + It defaults to ``'strict'`` handling. - The method may not store state in the :class:`Codec` instance. Use - :class:`StreamWriter` for codecs which have to keep state in order to make - encoding efficient. + The method may not store state in the :class:`Codec` instance. Use + :class:`StreamWriter` for codecs which have to keep state in order to make + encoding efficient. - The encoder must be able to handle zero length input and return an empty object - of the output object type in this situation. + The encoder must be able to handle zero length input and return an empty object + of the output object type in this situation. -.. method:: Codec.decode(input, errors='strict') + .. method:: decode(input, errors='strict') - Decodes the object *input* and returns a tuple (output object, length - consumed). For instance, for a :term:`text encoding`, decoding converts - a bytes object encoded using a particular - character set encoding to a string object. + Decodes the object *input* and returns a tuple (output object, length + consumed). For instance, for a :term:`text encoding`, decoding converts + a bytes object encoded using a particular + character set encoding to a string object. - For text encodings and bytes-to-bytes codecs, - *input* must be a bytes object or one which provides the read-only - buffer interface -- for example, buffer objects and memory mapped files. + For text encodings and bytes-to-bytes codecs, + *input* must be a bytes object or one which provides the read-only + buffer interface -- for example, buffer objects and memory mapped files. - The *errors* argument defines the error handling to apply. - It defaults to ``'strict'`` handling. + The *errors* argument defines the error handling to apply. + It defaults to ``'strict'`` handling. - The method may not store state in the :class:`Codec` instance. Use - :class:`StreamReader` for codecs which have to keep state in order to make - decoding efficient. + The method may not store state in the :class:`Codec` instance. Use + :class:`StreamReader` for codecs which have to keep state in order to make + decoding efficient. - The decoder must be able to handle zero length input and return an empty object - of the output object type in this situation. + The decoder must be able to handle zero length input and return an empty object + of the output object type in this situation. Incremental Encoding and Decoding @@ -702,7 +707,7 @@ Stream Encoding and Decoding The :class:`StreamWriter` and :class:`StreamReader` classes provide generic working interfaces which can be used to implement new encoding submodules very -easily. See :mod:`encodings.utf_8` for an example of how this is done. +easily. See :mod:`!encodings.utf_8` for an example of how this is done. .. _stream-writer-objects: @@ -892,9 +897,10 @@ The design is such that one can use the factory functions returned by the .. class:: StreamRecoder(stream, encode, decode, Reader, Writer, errors='strict') Creates a :class:`StreamRecoder` instance which implements a two-way conversion: - *encode* and *decode* work on the frontend — the data visible to - code calling :meth:`read` and :meth:`write`, while *Reader* and *Writer* - work on the backend — the data in *stream*. + *encode* and *decode* work on the frontend — the data visible to + code calling :meth:`~StreamReader.read` and :meth:`~StreamWriter.write`, + while *Reader* and *Writer* + work on the backend — the data in *stream*. You can use these objects to do transparent transcodings, e.g., from Latin-1 to UTF-8 and back. @@ -1346,9 +1352,10 @@ encodings. | | | supported. | +--------------------+---------+---------------------------+ | raw_unicode_escape | | Latin-1 encoding with | -| | | ``\uXXXX`` and | -| | | ``\UXXXXXXXX`` for other | -| | | code points. Existing | +| | | :samp:`\\u{XXXX}` and | +| | | :samp:`\\U{XXXXXXXX}` | +| | | for other code points. | +| | | Existing | | | | backslashes are not | | | | escaped in any way. | | | | It is used in the Python | @@ -1413,8 +1420,8 @@ to :class:`bytes` mappings. They are not supported by :meth:`bytes.decode` | | quotedprintable, | quoted printable. | ``quotetabs=True`` / | | | quoted_printable | | :meth:`quopri.decode` | +----------------------+------------------+------------------------------+------------------------------+ -| uu_codec | uu | Convert the operand using | :meth:`uu.encode` / | -| | | uuencode. | :meth:`uu.decode` | +| uu_codec | uu | Convert the operand using | | +| | | uuencode. | | +----------------------+------------------+------------------------------+------------------------------+ | zlib_codec | zip, zlib | Compress the operand using | :meth:`zlib.compress` / | | | | gzip. | :meth:`zlib.decompress` | diff --git a/Doc/library/collections.abc.rst b/Doc/library/collections.abc.rst index 43a3286ba832cf..582bb18f752bd5 100644 --- a/Doc/library/collections.abc.rst +++ b/Doc/library/collections.abc.rst @@ -22,7 +22,7 @@ This module provides :term:`abstract base classes ` that can be used to test whether a class provides a particular interface; for -example, whether it is :term:`hashable` or whether it is a mapping. +example, whether it is :term:`hashable` or whether it is a :term:`mapping`. An :func:`issubclass` or :func:`isinstance` test for an interface works in one of three ways. @@ -73,7 +73,7 @@ of the API: >>> isinstance(D(), Sequence) True -In this example, class :class:`D` does not need to define +In this example, class :class:`!D` does not need to define ``__contains__``, ``__iter__``, and ``__reversed__`` because the :ref:`in-operator `, the :term:`iteration ` logic, and the :func:`reversed` function automatically fall back to @@ -87,7 +87,7 @@ the required methods (unless those methods have been set to class E: def __iter__(self): ... - def __next__(next): ... + def __next__(self): ... .. doctest:: @@ -183,16 +183,16 @@ ABC Inherits from Abstract Methods Mi .. rubric:: Footnotes -.. [1] These ABCs override :meth:`object.__subclasshook__` to support +.. [1] These ABCs override :meth:`~abc.ABCMeta.__subclasshook__` to support testing an interface by verifying the required methods are present and have not been set to :const:`None`. This only works for simple interfaces. More complex interfaces require registration or direct subclassing. .. [2] Checking ``isinstance(obj, Iterable)`` detects classes that are - registered as :class:`Iterable` or that have an :meth:`__iter__` + registered as :class:`Iterable` or that have an :meth:`~container.__iter__` method, but it does not detect classes that iterate with the - :meth:`__getitem__` method. The only reliable way to determine + :meth:`~object.__getitem__` method. The only reliable way to determine whether an object is :term:`iterable` is to call ``iter(obj)``. @@ -202,27 +202,28 @@ Collections Abstract Base Classes -- Detailed Descriptions .. class:: Container - ABC for classes that provide the :meth:`__contains__` method. + ABC for classes that provide the :meth:`~object.__contains__` method. .. class:: Hashable - ABC for classes that provide the :meth:`__hash__` method. + ABC for classes that provide the :meth:`~object.__hash__` method. .. class:: Sized - ABC for classes that provide the :meth:`__len__` method. + ABC for classes that provide the :meth:`~object.__len__` method. .. class:: Callable - ABC for classes that provide the :meth:`__call__` method. + ABC for classes that provide the :meth:`~object.__call__` method. .. class:: Iterable - ABC for classes that provide the :meth:`__iter__` method. + ABC for classes that provide the :meth:`~container.__iter__` method. Checking ``isinstance(obj, Iterable)`` detects classes that are registered - as :class:`Iterable` or that have an :meth:`__iter__` method, but it does - not detect classes that iterate with the :meth:`__getitem__` method. + as :class:`Iterable` or that have an :meth:`~container.__iter__` method, + but it does + not detect classes that iterate with the :meth:`~object.__getitem__` method. The only reliable way to determine whether an object is :term:`iterable` is to call ``iter(obj)``. @@ -240,17 +241,17 @@ Collections Abstract Base Classes -- Detailed Descriptions .. class:: Reversible - ABC for iterable classes that also provide the :meth:`__reversed__` + ABC for iterable classes that also provide the :meth:`~object.__reversed__` method. .. versionadded:: 3.6 .. class:: Generator - ABC for generator classes that implement the protocol defined in - :pep:`342` that extends iterators with the :meth:`~generator.send`, + ABC for :term:`generator` classes that implement the protocol defined in + :pep:`342` that extends :term:`iterators ` with the + :meth:`~generator.send`, :meth:`~generator.throw` and :meth:`~generator.close` methods. - See also the definition of :term:`generator`. .. versionadded:: 3.5 @@ -261,9 +262,9 @@ Collections Abstract Base Classes -- Detailed Descriptions ABCs for read-only and mutable :term:`sequences `. Implementation note: Some of the mixin methods, such as - :meth:`__iter__`, :meth:`__reversed__` and :meth:`index`, make - repeated calls to the underlying :meth:`__getitem__` method. - Consequently, if :meth:`__getitem__` is implemented with constant + :meth:`~container.__iter__`, :meth:`~object.__reversed__` and :meth:`index`, make + repeated calls to the underlying :meth:`~object.__getitem__` method. + Consequently, if :meth:`~object.__getitem__` is implemented with constant access speed, the mixin methods will have linear performance; however, if the underlying method is linear (as it would be with a linked list), the mixins will have quadratic performance and will @@ -282,7 +283,7 @@ Collections Abstract Base Classes -- Detailed Descriptions .. class:: Set MutableSet - ABCs for read-only and mutable sets. + ABCs for read-only and mutable :ref:`sets `. .. class:: Mapping MutableMapping @@ -299,16 +300,16 @@ Collections Abstract Base Classes -- Detailed Descriptions .. class:: Awaitable ABC for :term:`awaitable` objects, which can be used in :keyword:`await` - expressions. Custom implementations must provide the :meth:`__await__` - method. + expressions. Custom implementations must provide the + :meth:`~object.__await__` method. :term:`Coroutine ` objects and instances of the :class:`~collections.abc.Coroutine` ABC are all instances of this ABC. .. note:: - In CPython, generator-based coroutines (generators decorated with - :func:`types.coroutine`) are - *awaitables*, even though they do not have an :meth:`__await__` method. + In CPython, generator-based coroutines (:term:`generators ` + decorated with :func:`@types.coroutine `) are + *awaitables*, even though they do not have an :meth:`~object.__await__` method. Using ``isinstance(gencoro, Awaitable)`` for them will return ``False``. Use :func:`inspect.isawaitable` to detect them. @@ -316,17 +317,17 @@ Collections Abstract Base Classes -- Detailed Descriptions .. class:: Coroutine - ABC for coroutine compatible classes. These implement the + ABC for :term:`coroutine` compatible classes. These implement the following methods, defined in :ref:`coroutine-objects`: :meth:`~coroutine.send`, :meth:`~coroutine.throw`, and :meth:`~coroutine.close`. Custom implementations must also implement - :meth:`__await__`. All :class:`Coroutine` instances are also instances of - :class:`Awaitable`. See also the definition of :term:`coroutine`. + :meth:`~object.__await__`. All :class:`Coroutine` instances are also + instances of :class:`Awaitable`. .. note:: - In CPython, generator-based coroutines (generators decorated with - :func:`types.coroutine`) are - *awaitables*, even though they do not have an :meth:`__await__` method. + In CPython, generator-based coroutines (:term:`generators ` + decorated with :func:`@types.coroutine `) are + *awaitables*, even though they do not have an :meth:`~object.__await__` method. Using ``isinstance(gencoro, Coroutine)`` for them will return ``False``. Use :func:`inspect.isawaitable` to detect them. @@ -334,7 +335,7 @@ Collections Abstract Base Classes -- Detailed Descriptions .. class:: AsyncIterable - ABC for classes that provide ``__aiter__`` method. See also the + ABC for classes that provide an ``__aiter__`` method. See also the definition of :term:`asynchronous iterable`. .. versionadded:: 3.5 @@ -348,7 +349,7 @@ Collections Abstract Base Classes -- Detailed Descriptions .. class:: AsyncGenerator - ABC for asynchronous generator classes that implement the protocol + ABC for :term:`asynchronous generator` classes that implement the protocol defined in :pep:`525` and :pep:`492`. .. versionadded:: 3.6 @@ -373,9 +374,9 @@ particular functionality, for example:: Several of the ABCs are also useful as mixins that make it easier to develop classes supporting container APIs. For example, to write a class supporting the full :class:`Set` API, it is only necessary to supply the three underlying -abstract methods: :meth:`__contains__`, :meth:`__iter__`, and :meth:`__len__`. -The ABC supplies the remaining methods such as :meth:`__and__` and -:meth:`isdisjoint`:: +abstract methods: :meth:`~object.__contains__`, :meth:`~container.__iter__`, and +:meth:`~object.__len__`. The ABC supplies the remaining methods such as +:meth:`!__and__` and :meth:`~frozenset.isdisjoint`:: class ListBasedSet(collections.abc.Set): ''' Alternate set implementation favoring space over speed @@ -403,23 +404,24 @@ Notes on using :class:`Set` and :class:`MutableSet` as a mixin: (1) Since some set operations create new sets, the default mixin methods need - a way to create new instances from an iterable. The class constructor is + a way to create new instances from an :term:`iterable`. The class constructor is assumed to have a signature in the form ``ClassName(iterable)``. - That assumption is factored-out to an internal classmethod called - :meth:`_from_iterable` which calls ``cls(iterable)`` to produce a new set. + That assumption is factored-out to an internal :class:`classmethod` called + :meth:`!_from_iterable` which calls ``cls(iterable)`` to produce a new set. If the :class:`Set` mixin is being used in a class with a different - constructor signature, you will need to override :meth:`_from_iterable` + constructor signature, you will need to override :meth:`!_from_iterable` with a classmethod or regular method that can construct new instances from an iterable argument. (2) To override the comparisons (presumably for speed, as the - semantics are fixed), redefine :meth:`__le__` and :meth:`__ge__`, + semantics are fixed), redefine :meth:`~object.__le__` and + :meth:`~object.__ge__`, then the other operations will automatically follow suit. (3) - The :class:`Set` mixin provides a :meth:`_hash` method to compute a hash value - for the set; however, :meth:`__hash__` is not defined because not all sets + The :class:`Set` mixin provides a :meth:`!_hash` method to compute a hash value + for the set; however, :meth:`~object.__hash__` is not defined because not all sets are :term:`hashable` or immutable. To add set hashability using mixins, inherit from both :meth:`Set` and :meth:`Hashable`, then define ``__hash__ = Set._hash``. diff --git a/Doc/library/collections.rst b/Doc/library/collections.rst index bb46782c06e1c8..c246173c1bbf53 100644 --- a/Doc/library/collections.rst +++ b/Doc/library/collections.rst @@ -120,26 +120,26 @@ The class can be used to simulate nested scopes and is useful in templating. .. seealso:: - * The `MultiContext class - `_ - in the Enthought `CodeTools package - `_ has options to support - writing to any mapping in the chain. + * The `MultiContext class + `_ + in the Enthought `CodeTools package + `_ has options to support + writing to any mapping in the chain. - * Django's `Context class - `_ - for templating is a read-only chain of mappings. It also features - pushing and popping of contexts similar to the - :meth:`~collections.ChainMap.new_child` method and the - :attr:`~collections.ChainMap.parents` property. + * Django's `Context class + `_ + for templating is a read-only chain of mappings. It also features + pushing and popping of contexts similar to the + :meth:`~collections.ChainMap.new_child` method and the + :attr:`~collections.ChainMap.parents` property. - * The `Nested Contexts recipe - `_ has options to control - whether writes and other mutations apply only to the first mapping or to - any mapping in the chain. + * The `Nested Contexts recipe + `_ has options to control + whether writes and other mutations apply only to the first mapping or to + any mapping in the chain. - * A `greatly simplified read-only version of Chainmap - `_. + * A `greatly simplified read-only version of Chainmap + `_. :class:`ChainMap` Examples and Recipes @@ -358,7 +358,7 @@ Common patterns for working with :class:`Counter` objects:: list(c) # list unique elements set(c) # convert to a set dict(c) # convert to a regular dictionary - c.items() # convert to a list of (elem, cnt) pairs + c.items() # access the (elem, cnt) pairs Counter(dict(list_of_pairs)) # convert from a list of (elem, cnt) pairs c.most_common()[:-n-1:-1] # n least common elements +c # remove zero and negative counts @@ -429,22 +429,22 @@ or subtracting from an empty counter. .. seealso:: - * `Bag class `_ - in Smalltalk. + * `Bag class `_ + in Smalltalk. - * Wikipedia entry for `Multisets `_. + * Wikipedia entry for `Multisets `_. - * `C++ multisets `_ - tutorial with examples. + * `C++ multisets `_ + tutorial with examples. - * For mathematical operations on multisets and their use cases, see - *Knuth, Donald. The Art of Computer Programming Volume II, - Section 4.6.3, Exercise 19*. + * For mathematical operations on multisets and their use cases, see + *Knuth, Donald. The Art of Computer Programming Volume II, + Section 4.6.3, Exercise 19*. - * To enumerate all distinct multisets of a given size over a given set of - elements, see :func:`itertools.combinations_with_replacement`:: + * To enumerate all distinct multisets of a given size over a given set of + elements, see :func:`itertools.combinations_with_replacement`:: - map(Counter, combinations_with_replacement('ABC', 2)) # --> AA AB AC BB BC CC + map(Counter, combinations_with_replacement('ABC', 2)) # --> AA AB AC BB BC CC :class:`deque` objects @@ -458,10 +458,10 @@ or subtracting from an empty counter. Deques are a generalization of stacks and queues (the name is pronounced "deck" and is short for "double-ended queue"). Deques support thread-safe, memory efficient appends and pops from either side of the deque with approximately the - same O(1) performance in either direction. + same *O*\ (1) performance in either direction. Though :class:`list` objects support similar operations, they are optimized for - fast fixed-length operations and incur O(n) memory movement costs for + fast fixed-length operations and incur *O*\ (*n*) memory movement costs for ``pop(0)`` and ``insert(0, v)`` operations which change both the size and position of the underlying data representation. @@ -585,7 +585,7 @@ or subtracting from an empty counter. In addition to the above, deques support iteration, pickling, ``len(d)``, ``reversed(d)``, ``copy.copy(d)``, ``copy.deepcopy(d)``, membership testing with the :keyword:`in` operator, and subscript references such as ``d[0]`` to access -the first element. Indexed access is O(1) at both ends but slows to O(n) in +the first element. Indexed access is *O*\ (1) at both ends but slows to *O*\ (*n*) in the middle. For fast random access, use lists instead. Starting in version 3.5, deques support ``__add__()``, ``__mul__()``, @@ -743,12 +743,12 @@ stack manipulations such as ``dup``, ``drop``, ``swap``, ``over``, ``pick``, If calling :attr:`default_factory` raises an exception this exception is propagated unchanged. - This method is called by the :meth:`__getitem__` method of the + This method is called by the :meth:`~object.__getitem__` method of the :class:`dict` class when the requested key is not found; whatever it - returns or raises is then returned or raised by :meth:`__getitem__`. + returns or raises is then returned or raised by :meth:`~object.__getitem__`. Note that :meth:`__missing__` is *not* called for any operations besides - :meth:`__getitem__`. This means that :meth:`get` will, like normal + :meth:`~object.__getitem__`. This means that :meth:`get` will, like normal dictionaries, return ``None`` as a default rather than using :attr:`default_factory`. @@ -979,6 +979,12 @@ field names, the method and attribute names start with an underscore. >>> for partnum, record in inventory.items(): ... inventory[partnum] = record._replace(price=newprices[partnum], timestamp=time.now()) + Named tuples are also supported by generic function :func:`copy.replace`. + + .. versionchanged:: 3.13 + Raise :exc:`TypeError` instead of :exc:`ValueError` for invalid + keyword arguments. + .. attribute:: somenamedtuple._fields Tuple of strings listing the field names. Useful for introspection @@ -1060,20 +1066,20 @@ fields: .. seealso:: - * See :class:`typing.NamedTuple` for a way to add type hints for named - tuples. It also provides an elegant notation using the :keyword:`class` - keyword:: + * See :class:`typing.NamedTuple` for a way to add type hints for named + tuples. It also provides an elegant notation using the :keyword:`class` + keyword:: - class Component(NamedTuple): - part_number: int - weight: float - description: Optional[str] = None + class Component(NamedTuple): + part_number: int + weight: float + description: Optional[str] = None - * See :meth:`types.SimpleNamespace` for a mutable namespace based on an - underlying dictionary instead of a tuple. + * See :meth:`types.SimpleNamespace` for a mutable namespace based on an + underlying dictionary instead of a tuple. - * The :mod:`dataclasses` module provides a decorator and functions for - automatically adding generated special methods to user-defined classes. + * The :mod:`dataclasses` module provides a decorator and functions for + automatically adding generated special methods to user-defined classes. :class:`OrderedDict` objects @@ -1224,7 +1230,7 @@ variants of :func:`functools.lru_cache`: result = self.func(*args) self.cache[args] = time(), result if len(self.cache) > self.maxsize: - self.cache.popitem(0) + self.cache.popitem(last=False) return result @@ -1256,12 +1262,12 @@ variants of :func:`functools.lru_cache`: if self.requests[args] <= self.cache_after: self.requests.move_to_end(args) if len(self.requests) > self.maxrequests: - self.requests.popitem(0) + self.requests.popitem(last=False) else: self.requests.pop(args, None) self.cache[args] = result if len(self.cache) > self.maxsize: - self.cache.popitem(0) + self.cache.popitem(last=False) return result .. doctest:: diff --git a/Doc/library/compileall.rst b/Doc/library/compileall.rst index 4226348a17240a..df1eefab839cc1 100644 --- a/Doc/library/compileall.rst +++ b/Doc/library/compileall.rst @@ -16,6 +16,8 @@ have write permission to the library directories. .. include:: ../includes/wasm-notavail.rst +.. _compileall-cli: + Command-line use ---------------- @@ -24,28 +26,28 @@ compile Python sources. .. program:: compileall -.. cmdoption:: directory ... - file ... +.. option:: directory ... + file ... Positional arguments are files to compile or directories that contain source files, traversed recursively. If no argument is given, behave as if - the command line was ``-l ``. + the command line was :samp:`-l {}`. -.. cmdoption:: -l +.. option:: -l Do not recurse into subdirectories, only compile source code files directly contained in the named or implied directories. -.. cmdoption:: -f +.. option:: -f Force rebuild even if timestamps are up-to-date. -.. cmdoption:: -q +.. option:: -q Do not print the list of files compiled. If passed once, error messages will still be printed. If passed twice (``-qq``), all output is suppressed. -.. cmdoption:: -d destdir +.. option:: -d destdir Directory prepended to the path to each file being compiled. This will appear in compilation time tracebacks, and is also compiled in to the @@ -53,45 +55,45 @@ compile Python sources. cases where the source file does not exist at the time the byte-code file is executed. -.. cmdoption:: -s strip_prefix -.. cmdoption:: -p prepend_prefix +.. option:: -s strip_prefix +.. option:: -p prepend_prefix Remove (``-s``) or append (``-p``) the given prefix of paths recorded in the ``.pyc`` files. Cannot be combined with ``-d``. -.. cmdoption:: -x regex +.. option:: -x regex regex is used to search the full path to each file considered for compilation, and if the regex produces a match, the file is skipped. -.. cmdoption:: -i list +.. option:: -i list Read the file ``list`` and add each line that it contains to the list of files and directories to compile. If ``list`` is ``-``, read lines from ``stdin``. -.. cmdoption:: -b +.. option:: -b Write the byte-code files to their legacy locations and names, which may overwrite byte-code files created by another version of Python. The default is to write files to their :pep:`3147` locations and names, which allows byte-code files from multiple versions of Python to coexist. -.. cmdoption:: -r +.. option:: -r Control the maximum recursion level for subdirectories. If this is given, then ``-l`` option will not be taken into account. :program:`python -m compileall -r 0` is equivalent to :program:`python -m compileall -l`. -.. cmdoption:: -j N +.. option:: -j N Use *N* workers to compile the files within the given directory. - If ``0`` is used, then the result of :func:`os.cpu_count()` + If ``0`` is used, then the result of :func:`os.process_cpu_count()` will be used. -.. cmdoption:: --invalidation-mode [timestamp|checked-hash|unchecked-hash] +.. option:: --invalidation-mode [timestamp|checked-hash|unchecked-hash] Control how the generated byte-code files are invalidated at runtime. The ``timestamp`` value, means that ``.pyc`` files with the source timestamp @@ -104,17 +106,17 @@ compile Python sources. variable is not set, and ``checked-hash`` if the ``SOURCE_DATE_EPOCH`` environment variable is set. -.. cmdoption:: -o level +.. option:: -o level Compile with the given optimization level. May be used multiple times to compile for multiple levels at a time (for example, ``compileall -o 1 -o 2``). -.. cmdoption:: -e dir +.. option:: -e dir Ignore symlinks pointing outside the given directory. -.. cmdoption:: --hardlink-dupes +.. option:: --hardlink-dupes If two ``.pyc`` files with different optimization level have the same content, use hard links to consolidate duplicate files. diff --git a/Doc/library/concurrent.futures.rst b/Doc/library/concurrent.futures.rst index 09c9fc4e6e227a..deefb8606ead84 100644 --- a/Doc/library/concurrent.futures.rst +++ b/Doc/library/concurrent.futures.rst @@ -29,83 +29,83 @@ Executor Objects An abstract class that provides methods to execute calls asynchronously. It should not be used directly, but through its concrete subclasses. - .. method:: submit(fn, /, *args, **kwargs) + .. method:: submit(fn, /, *args, **kwargs) - Schedules the callable, *fn*, to be executed as ``fn(*args, **kwargs)`` - and returns a :class:`Future` object representing the execution of the - callable. :: + Schedules the callable, *fn*, to be executed as ``fn(*args, **kwargs)`` + and returns a :class:`Future` object representing the execution of the + callable. :: - with ThreadPoolExecutor(max_workers=1) as executor: - future = executor.submit(pow, 323, 1235) - print(future.result()) + with ThreadPoolExecutor(max_workers=1) as executor: + future = executor.submit(pow, 323, 1235) + print(future.result()) - .. method:: map(func, *iterables, timeout=None, chunksize=1) + .. method:: map(func, *iterables, timeout=None, chunksize=1) - Similar to :func:`map(func, *iterables) ` except: + Similar to :func:`map(func, *iterables) ` except: - * the *iterables* are collected immediately rather than lazily; + * the *iterables* are collected immediately rather than lazily; - * *func* is executed asynchronously and several calls to - *func* may be made concurrently. + * *func* is executed asynchronously and several calls to + *func* may be made concurrently. - The returned iterator raises a :exc:`TimeoutError` - if :meth:`~iterator.__next__` is called and the result isn't available - after *timeout* seconds from the original call to :meth:`Executor.map`. - *timeout* can be an int or a float. If *timeout* is not specified or - ``None``, there is no limit to the wait time. + The returned iterator raises a :exc:`TimeoutError` + if :meth:`~iterator.__next__` is called and the result isn't available + after *timeout* seconds from the original call to :meth:`Executor.map`. + *timeout* can be an int or a float. If *timeout* is not specified or + ``None``, there is no limit to the wait time. - If a *func* call raises an exception, then that exception will be - raised when its value is retrieved from the iterator. + If a *func* call raises an exception, then that exception will be + raised when its value is retrieved from the iterator. - When using :class:`ProcessPoolExecutor`, this method chops *iterables* - into a number of chunks which it submits to the pool as separate - tasks. The (approximate) size of these chunks can be specified by - setting *chunksize* to a positive integer. For very long iterables, - using a large value for *chunksize* can significantly improve - performance compared to the default size of 1. With - :class:`ThreadPoolExecutor`, *chunksize* has no effect. + When using :class:`ProcessPoolExecutor`, this method chops *iterables* + into a number of chunks which it submits to the pool as separate + tasks. The (approximate) size of these chunks can be specified by + setting *chunksize* to a positive integer. For very long iterables, + using a large value for *chunksize* can significantly improve + performance compared to the default size of 1. With + :class:`ThreadPoolExecutor`, *chunksize* has no effect. - .. versionchanged:: 3.5 - Added the *chunksize* argument. + .. versionchanged:: 3.5 + Added the *chunksize* argument. - .. method:: shutdown(wait=True, *, cancel_futures=False) + .. method:: shutdown(wait=True, *, cancel_futures=False) - Signal the executor that it should free any resources that it is using - when the currently pending futures are done executing. Calls to - :meth:`Executor.submit` and :meth:`Executor.map` made after shutdown will - raise :exc:`RuntimeError`. + Signal the executor that it should free any resources that it is using + when the currently pending futures are done executing. Calls to + :meth:`Executor.submit` and :meth:`Executor.map` made after shutdown will + raise :exc:`RuntimeError`. - If *wait* is ``True`` then this method will not return until all the - pending futures are done executing and the resources associated with the - executor have been freed. If *wait* is ``False`` then this method will - return immediately and the resources associated with the executor will be - freed when all pending futures are done executing. Regardless of the - value of *wait*, the entire Python program will not exit until all - pending futures are done executing. + If *wait* is ``True`` then this method will not return until all the + pending futures are done executing and the resources associated with the + executor have been freed. If *wait* is ``False`` then this method will + return immediately and the resources associated with the executor will be + freed when all pending futures are done executing. Regardless of the + value of *wait*, the entire Python program will not exit until all + pending futures are done executing. - If *cancel_futures* is ``True``, this method will cancel all pending - futures that the executor has not started running. Any futures that - are completed or running won't be cancelled, regardless of the value - of *cancel_futures*. + If *cancel_futures* is ``True``, this method will cancel all pending + futures that the executor has not started running. Any futures that + are completed or running won't be cancelled, regardless of the value + of *cancel_futures*. - If both *cancel_futures* and *wait* are ``True``, all futures that the - executor has started running will be completed prior to this method - returning. The remaining futures are cancelled. + If both *cancel_futures* and *wait* are ``True``, all futures that the + executor has started running will be completed prior to this method + returning. The remaining futures are cancelled. - You can avoid having to call this method explicitly if you use the - :keyword:`with` statement, which will shutdown the :class:`Executor` - (waiting as if :meth:`Executor.shutdown` were called with *wait* set to - ``True``):: + You can avoid having to call this method explicitly if you use the + :keyword:`with` statement, which will shutdown the :class:`Executor` + (waiting as if :meth:`Executor.shutdown` were called with *wait* set to + ``True``):: - import shutil - with ThreadPoolExecutor(max_workers=4) as e: - e.submit(shutil.copy, 'src1.txt', 'dest1.txt') - e.submit(shutil.copy, 'src2.txt', 'dest2.txt') - e.submit(shutil.copy, 'src3.txt', 'dest3.txt') - e.submit(shutil.copy, 'src4.txt', 'dest4.txt') + import shutil + with ThreadPoolExecutor(max_workers=4) as e: + e.submit(shutil.copy, 'src1.txt', 'dest1.txt') + e.submit(shutil.copy, 'src2.txt', 'dest2.txt') + e.submit(shutil.copy, 'src3.txt', 'dest3.txt') + e.submit(shutil.copy, 'src4.txt', 'dest4.txt') - .. versionchanged:: 3.9 - Added *cancel_futures*. + .. versionchanged:: 3.9 + Added *cancel_futures*. ThreadPoolExecutor @@ -188,6 +188,10 @@ And:: ThreadPoolExecutor now reuses idle worker threads before starting *max_workers* worker threads too. + .. versionchanged:: 3.13 + Default value of *max_workers* is changed to + ``min(32, (os.process_cpu_count() or 1) + 4)``. + .. _threadpoolexecutor-example: @@ -243,7 +247,7 @@ to a :class:`ProcessPoolExecutor` will result in deadlock. An :class:`Executor` subclass that executes calls asynchronously using a pool of at most *max_workers* processes. If *max_workers* is ``None`` or not - given, it will default to the number of processors on the machine. + given, it will default to :func:`os.process_cpu_count`. If *max_workers* is less than or equal to ``0``, then a :exc:`ValueError` will be raised. On Windows, *max_workers* must be less than or equal to ``61``. If it is not @@ -293,6 +297,18 @@ to a :class:`ProcessPoolExecutor` will result in deadlock. The *max_tasks_per_child* argument was added to allow users to control the lifetime of workers in the pool. + .. versionchanged:: 3.12 + On POSIX systems, if your application has multiple threads and the + :mod:`multiprocessing` context uses the ``"fork"`` start method: + The :func:`os.fork` function called internally to spawn workers may raise a + :exc:`DeprecationWarning`. Pass a *mp_context* configured to use a + different start method. See the :func:`os.fork` documentation for + further explanation. + + .. versionchanged:: 3.13 + *max_workers* uses :func:`os.process_cpu_count` by default, instead of + :func:`os.cpu_count`. + .. _processpoolexecutor-example: ProcessPoolExecutor Example @@ -345,117 +361,117 @@ The :class:`Future` class encapsulates the asynchronous execution of a callable. instances are created by :meth:`Executor.submit` and should not be created directly except for testing. - .. method:: cancel() + .. method:: cancel() - Attempt to cancel the call. If the call is currently being executed or - finished running and cannot be cancelled then the method will return - ``False``, otherwise the call will be cancelled and the method will - return ``True``. + Attempt to cancel the call. If the call is currently being executed or + finished running and cannot be cancelled then the method will return + ``False``, otherwise the call will be cancelled and the method will + return ``True``. - .. method:: cancelled() + .. method:: cancelled() - Return ``True`` if the call was successfully cancelled. + Return ``True`` if the call was successfully cancelled. - .. method:: running() + .. method:: running() - Return ``True`` if the call is currently being executed and cannot be - cancelled. + Return ``True`` if the call is currently being executed and cannot be + cancelled. - .. method:: done() + .. method:: done() - Return ``True`` if the call was successfully cancelled or finished - running. + Return ``True`` if the call was successfully cancelled or finished + running. - .. method:: result(timeout=None) + .. method:: result(timeout=None) - Return the value returned by the call. If the call hasn't yet completed - then this method will wait up to *timeout* seconds. If the call hasn't - completed in *timeout* seconds, then a - :exc:`TimeoutError` will be raised. *timeout* can be - an int or float. If *timeout* is not specified or ``None``, there is no - limit to the wait time. + Return the value returned by the call. If the call hasn't yet completed + then this method will wait up to *timeout* seconds. If the call hasn't + completed in *timeout* seconds, then a + :exc:`TimeoutError` will be raised. *timeout* can be + an int or float. If *timeout* is not specified or ``None``, there is no + limit to the wait time. - If the future is cancelled before completing then :exc:`.CancelledError` - will be raised. + If the future is cancelled before completing then :exc:`.CancelledError` + will be raised. - If the call raised an exception, this method will raise the same exception. + If the call raised an exception, this method will raise the same exception. - .. method:: exception(timeout=None) + .. method:: exception(timeout=None) - Return the exception raised by the call. If the call hasn't yet - completed then this method will wait up to *timeout* seconds. If the - call hasn't completed in *timeout* seconds, then a - :exc:`TimeoutError` will be raised. *timeout* can be - an int or float. If *timeout* is not specified or ``None``, there is no - limit to the wait time. + Return the exception raised by the call. If the call hasn't yet + completed then this method will wait up to *timeout* seconds. If the + call hasn't completed in *timeout* seconds, then a + :exc:`TimeoutError` will be raised. *timeout* can be + an int or float. If *timeout* is not specified or ``None``, there is no + limit to the wait time. - If the future is cancelled before completing then :exc:`.CancelledError` - will be raised. + If the future is cancelled before completing then :exc:`.CancelledError` + will be raised. - If the call completed without raising, ``None`` is returned. + If the call completed without raising, ``None`` is returned. - .. method:: add_done_callback(fn) + .. method:: add_done_callback(fn) - Attaches the callable *fn* to the future. *fn* will be called, with the - future as its only argument, when the future is cancelled or finishes - running. + Attaches the callable *fn* to the future. *fn* will be called, with the + future as its only argument, when the future is cancelled or finishes + running. - Added callables are called in the order that they were added and are - always called in a thread belonging to the process that added them. If - the callable raises an :exc:`Exception` subclass, it will be logged and - ignored. If the callable raises a :exc:`BaseException` subclass, the - behavior is undefined. + Added callables are called in the order that they were added and are + always called in a thread belonging to the process that added them. If + the callable raises an :exc:`Exception` subclass, it will be logged and + ignored. If the callable raises a :exc:`BaseException` subclass, the + behavior is undefined. - If the future has already completed or been cancelled, *fn* will be - called immediately. + If the future has already completed or been cancelled, *fn* will be + called immediately. The following :class:`Future` methods are meant for use in unit tests and :class:`Executor` implementations. - .. method:: set_running_or_notify_cancel() + .. method:: set_running_or_notify_cancel() - This method should only be called by :class:`Executor` implementations - before executing the work associated with the :class:`Future` and by unit - tests. + This method should only be called by :class:`Executor` implementations + before executing the work associated with the :class:`Future` and by unit + tests. - If the method returns ``False`` then the :class:`Future` was cancelled, - i.e. :meth:`Future.cancel` was called and returned ``True``. Any threads - waiting on the :class:`Future` completing (i.e. through - :func:`as_completed` or :func:`wait`) will be woken up. + If the method returns ``False`` then the :class:`Future` was cancelled, + i.e. :meth:`Future.cancel` was called and returned ``True``. Any threads + waiting on the :class:`Future` completing (i.e. through + :func:`as_completed` or :func:`wait`) will be woken up. - If the method returns ``True`` then the :class:`Future` was not cancelled - and has been put in the running state, i.e. calls to - :meth:`Future.running` will return ``True``. + If the method returns ``True`` then the :class:`Future` was not cancelled + and has been put in the running state, i.e. calls to + :meth:`Future.running` will return ``True``. - This method can only be called once and cannot be called after - :meth:`Future.set_result` or :meth:`Future.set_exception` have been - called. + This method can only be called once and cannot be called after + :meth:`Future.set_result` or :meth:`Future.set_exception` have been + called. - .. method:: set_result(result) + .. method:: set_result(result) - Sets the result of the work associated with the :class:`Future` to - *result*. + Sets the result of the work associated with the :class:`Future` to + *result*. - This method should only be used by :class:`Executor` implementations and - unit tests. + This method should only be used by :class:`Executor` implementations and + unit tests. - .. versionchanged:: 3.8 - This method raises - :exc:`concurrent.futures.InvalidStateError` if the :class:`Future` is - already done. + .. versionchanged:: 3.8 + This method raises + :exc:`concurrent.futures.InvalidStateError` if the :class:`Future` is + already done. - .. method:: set_exception(exception) + .. method:: set_exception(exception) - Sets the result of the work associated with the :class:`Future` to the - :class:`Exception` *exception*. + Sets the result of the work associated with the :class:`Future` to the + :class:`Exception` *exception*. - This method should only be used by :class:`Executor` implementations and - unit tests. + This method should only be used by :class:`Executor` implementations and + unit tests. - .. versionchanged:: 3.8 - This method raises - :exc:`concurrent.futures.InvalidStateError` if the :class:`Future` is - already done. + .. versionchanged:: 3.8 + This method raises + :exc:`concurrent.futures.InvalidStateError` if the :class:`Future` is + already done. Module Functions ---------------- diff --git a/Doc/library/configparser.rst b/Doc/library/configparser.rst index a7f75fd6e84f4c..0031737853e7b4 100644 --- a/Doc/library/configparser.rst +++ b/Doc/library/configparser.rst @@ -208,7 +208,7 @@ converters and customize the provided ones. [1]_ Fallback Values --------------- -As with a dictionary, you can use a section's :meth:`get` method to +As with a dictionary, you can use a section's :meth:`~ConfigParser.get` method to provide fallback values: .. doctest:: @@ -232,7 +232,7 @@ even if we specify a fallback: >>> topsecret.get('CompressionLevel', '3') '9' -One more thing to be aware of is that the parser-level :meth:`get` method +One more thing to be aware of is that the parser-level :meth:`~ConfigParser.get` method provides a custom, more complex interface, maintained for backwards compatibility. When using this method, a fallback value can be provided via the ``fallback`` keyword-only argument: @@ -271,7 +271,7 @@ out. Values can also span multiple lines, as long as they are indented deeper than the first line of the value. Depending on the parser's mode, blank lines may be treated as parts of multiline values or ignored. -By default, a valid section name can be any string that does not contain '\\n' or ']'. +By default, a valid section name can be any string that does not contain '\\n'. To change this, see :attr:`ConfigParser.SECTCRE`. Configuration files may include comments, prefixed by specific @@ -481,7 +481,7 @@ historical background and it's very likely that you will want to customize some of the features. The most common way to change the way a specific config parser works is to use -the :meth:`__init__` options: +the :meth:`!__init__` options: * *defaults*, default value: ``None`` @@ -491,7 +491,7 @@ the :meth:`__init__` options: the documented default. Hint: if you want to specify default values for a specific section, use - :meth:`read_dict` before you read the actual file. + :meth:`~ConfigParser.read_dict` before you read the actual file. * *dict_type*, default value: :class:`dict` @@ -635,8 +635,8 @@ the :meth:`__init__` options: * *strict*, default value: ``True`` When set to ``True``, the parser will not allow for any section or option - duplicates while reading from a single source (using :meth:`read_file`, - :meth:`read_string` or :meth:`read_dict`). It is recommended to use strict + duplicates while reading from a single source (using :meth:`~ConfigParser.read_file`, + :meth:`~ConfigParser.read_string` or :meth:`~ConfigParser.read_dict`). It is recommended to use strict parsers in new applications. .. versionchanged:: 3.2 @@ -697,7 +697,7 @@ the :meth:`__init__` options: desirable, users may define them in a subclass or pass a dictionary where each key is a name of the converter and each value is a callable implementing said conversion. For instance, passing ``{'decimal': decimal.Decimal}`` would add - :meth:`getdecimal` on both the parser object and all section proxies. In + :meth:`!getdecimal` on both the parser object and all section proxies. In other words, it will be possible to write both ``parser_instance.getdecimal('section', 'key', fallback=0)`` and ``parser_instance['section'].getdecimal('key', 0)``. @@ -935,8 +935,10 @@ ConfigParser Objects When *default_section* is given, it specifies the name for the special section holding default values for other sections and interpolation purposes - (normally named ``"DEFAULT"``). This value can be retrieved and changed on - runtime using the ``default_section`` instance attribute. + (normally named ``"DEFAULT"``). This value can be retrieved and changed at + runtime using the ``default_section`` instance attribute. This won't + re-evaluate an already parsed config file, but will be used when writing + parsed settings to a new config file. Interpolation behaviour may be customized by providing a custom handler through the *interpolation* argument. ``None`` can be used to turn off @@ -953,7 +955,7 @@ ConfigParser Objects When *converters* is given, it should be a dictionary where each key represents the name of a type converter and each value is a callable implementing the conversion from string to the desired datatype. Every - converter gets its own corresponding :meth:`get*()` method on the parser + converter gets its own corresponding :meth:`!get*()` method on the parser object and section proxies. .. versionchanged:: 3.1 @@ -1060,11 +1062,11 @@ ConfigParser Objects yielding Unicode strings (for example files opened in text mode). Optional argument *source* specifies the name of the file being read. If - not given and *f* has a :attr:`name` attribute, that is used for + not given and *f* has a :attr:`!name` attribute, that is used for *source*; the default is ``''``. .. versionadded:: 3.2 - Replaces :meth:`readfp`. + Replaces :meth:`!readfp`. .. method:: read_string(string, source='') @@ -1212,7 +1214,7 @@ ConfigParser Objects .. data:: MAX_INTERPOLATION_DEPTH - The maximum depth for recursive interpolation for :meth:`get` when the *raw* + The maximum depth for recursive interpolation for :meth:`~configparser.ConfigParser.get` when the *raw* parameter is false. This is relevant only when the default *interpolation* is used. @@ -1285,13 +1287,13 @@ Exceptions .. exception:: DuplicateSectionError - Exception raised if :meth:`add_section` is called with the name of a section + Exception raised if :meth:`~ConfigParser.add_section` is called with the name of a section that is already present or in strict parsers when a section if found more than once in a single input file, string or dictionary. .. versionadded:: 3.2 Optional ``source`` and ``lineno`` attributes and arguments to - :meth:`__init__` were added. + :meth:`!__init__` were added. .. exception:: DuplicateOptionError @@ -1343,9 +1345,9 @@ Exceptions Exception raised when errors occur attempting to parse a file. -.. versionchanged:: 3.12 - The ``filename`` attribute and :meth:`__init__` constructor argument were - removed. They have been available using the name ``source`` since 3.2. + .. versionchanged:: 3.12 + The ``filename`` attribute and :meth:`!__init__` constructor argument were + removed. They have been available using the name ``source`` since 3.2. .. rubric:: Footnotes diff --git a/Doc/library/contextlib.rst b/Doc/library/contextlib.rst index 7cd081d1f54f43..aab319cbe7405e 100644 --- a/Doc/library/contextlib.rst +++ b/Doc/library/contextlib.rst @@ -45,7 +45,7 @@ Functions and classes provided: This function is a :term:`decorator` that can be used to define a factory function for :keyword:`with` statement context managers, without needing to - create a class or separate :meth:`__enter__` and :meth:`__exit__` methods. + create a class or separate :meth:`~object.__enter__` and :meth:`~object.__exit__` methods. While many objects natively support use in with statements, sometimes a resource needs to be managed that isn't a context manager in its own right, @@ -106,8 +106,8 @@ Functions and classes provided: This function is a :term:`decorator` that can be used to define a factory function for :keyword:`async with` statement asynchronous context managers, - without needing to create a class or separate :meth:`__aenter__` and - :meth:`__aexit__` methods. It must be applied to an :term:`asynchronous + without needing to create a class or separate :meth:`~object.__aenter__` and + :meth:`~object.__aexit__` methods. It must be applied to an :term:`asynchronous generator` function. A simple example:: @@ -304,15 +304,15 @@ Functions and classes provided: This context manager is :ref:`reentrant `. - If the code within the :keyword:`!with` block raises an - :exc:`ExceptionGroup`, suppressed exceptions are removed from the + If the code within the :keyword:`!with` block raises a + :exc:`BaseExceptionGroup`, suppressed exceptions are removed from the group. If any exceptions in the group are not suppressed, a group containing them is re-raised. .. versionadded:: 3.4 .. versionchanged:: 3.12 ``suppress`` now supports suppressing exceptions raised as - part of an :exc:`ExceptionGroup`. + part of an :exc:`BaseExceptionGroup`. .. function:: redirect_stdout(new_target) @@ -515,7 +515,7 @@ Functions and classes provided: # the with statement, even if attempts to open files later # in the list raise an exception - The :meth:`__enter__` method returns the :class:`ExitStack` instance, and + The :meth:`~object.__enter__` method returns the :class:`ExitStack` instance, and performs no additional operations. Each instance maintains a stack of registered callbacks that are called in @@ -543,9 +543,9 @@ Functions and classes provided: .. method:: enter_context(cm) - Enters a new context manager and adds its :meth:`__exit__` method to + Enters a new context manager and adds its :meth:`~object.__exit__` method to the callback stack. The return value is the result of the context - manager's own :meth:`__enter__` method. + manager's own :meth:`~object.__enter__` method. These context managers may suppress exceptions just as they normally would if used directly as part of a :keyword:`with` statement. @@ -556,18 +556,18 @@ Functions and classes provided: .. method:: push(exit) - Adds a context manager's :meth:`__exit__` method to the callback stack. + Adds a context manager's :meth:`~object.__exit__` method to the callback stack. As ``__enter__`` is *not* invoked, this method can be used to cover - part of an :meth:`__enter__` implementation with a context manager's own - :meth:`__exit__` method. + part of an :meth:`~object.__enter__` implementation with a context manager's own + :meth:`~object.__exit__` method. If passed an object that is not a context manager, this method assumes it is a callback with the same signature as a context manager's - :meth:`__exit__` method and adds it directly to the callback stack. + :meth:`~object.__exit__` method and adds it directly to the callback stack. By returning true values, these callbacks can suppress exceptions the - same way context manager :meth:`__exit__` methods can. + same way context manager :meth:`~object.__exit__` methods can. The passed in object is returned from the function, allowing this method to be used as a function decorator. @@ -616,12 +616,12 @@ Functions and classes provided: asynchronous context managers, as well as having coroutines for cleanup logic. - The :meth:`close` method is not implemented, :meth:`aclose` must be used + The :meth:`~ExitStack.close` method is not implemented; :meth:`aclose` must be used instead. .. coroutinemethod:: enter_async_context(cm) - Similar to :meth:`enter_context` but expects an asynchronous context + Similar to :meth:`ExitStack.enter_context` but expects an asynchronous context manager. .. versionchanged:: 3.11 @@ -630,16 +630,16 @@ Functions and classes provided: .. method:: push_async_exit(exit) - Similar to :meth:`push` but expects either an asynchronous context manager + Similar to :meth:`ExitStack.push` but expects either an asynchronous context manager or a coroutine function. .. method:: push_async_callback(callback, /, *args, **kwds) - Similar to :meth:`callback` but expects a coroutine function. + Similar to :meth:`ExitStack.callback` but expects a coroutine function. .. coroutinemethod:: aclose() - Similar to :meth:`close` but properly handles awaitables. + Similar to :meth:`ExitStack.close` but properly handles awaitables. Continuing the example for :func:`asynccontextmanager`:: @@ -714,7 +714,7 @@ Cleaning up in an ``__enter__`` implementation As noted in the documentation of :meth:`ExitStack.push`, this method can be useful in cleaning up an already allocated resource if later -steps in the :meth:`__enter__` implementation fail. +steps in the :meth:`~object.__enter__` implementation fail. Here's an example of doing this for a context manager that accepts resource acquisition and release functions, along with an optional validation function, @@ -871,7 +871,7 @@ And also as a function decorator:: Note that there is one additional limitation when using context managers as function decorators: there's no way to access the return value of -:meth:`__enter__`. If that value is needed, then it is still necessary to use +:meth:`~object.__enter__`. If that value is needed, then it is still necessary to use an explicit ``with`` statement. .. seealso:: diff --git a/Doc/library/contextvars.rst b/Doc/library/contextvars.rst index 0ac2f3d85749b7..647832447de946 100644 --- a/Doc/library/contextvars.rst +++ b/Doc/library/contextvars.rst @@ -131,7 +131,7 @@ Manual Context Management ctx: Context = copy_context() print(list(ctx.items())) - The function has an O(1) complexity, i.e. works equally fast for + The function has an *O*\ (1) complexity, i.e. works equally fast for contexts with a few context variables and for contexts that have a lot of them. diff --git a/Doc/library/copy.rst b/Doc/library/copy.rst index 8f32477ed508c3..74333b2e934814 100644 --- a/Doc/library/copy.rst +++ b/Doc/library/copy.rst @@ -17,14 +17,22 @@ operations (explained below). Interface summary: -.. function:: copy(x) +.. function:: copy(obj) - Return a shallow copy of *x*. + Return a shallow copy of *obj*. -.. function:: deepcopy(x[, memo]) +.. function:: deepcopy(obj[, memo]) - Return a deep copy of *x*. + Return a deep copy of *obj*. + + +.. function:: replace(obj, /, **changes) + + Creates a new object of the same type as *obj*, replacing fields with values + from *changes*. + + .. versionadded:: 3.13 .. exception:: Error @@ -79,14 +87,40 @@ pickle functions from the :mod:`copyreg` module. single: __copy__() (copy protocol) single: __deepcopy__() (copy protocol) +.. currentmodule:: None + In order for a class to define its own copy implementation, it can define -special methods :meth:`__copy__` and :meth:`__deepcopy__`. The former is called -to implement the shallow copy operation; no additional arguments are passed. -The latter is called to implement the deep copy operation; it is passed one -argument, the ``memo`` dictionary. If the :meth:`__deepcopy__` implementation needs -to make a deep copy of a component, it should call the :func:`deepcopy` function -with the component as first argument and the memo dictionary as second argument. -The memo dictionary should be treated as an opaque object. +special methods :meth:`~object.__copy__` and :meth:`~object.__deepcopy__`. + +.. method:: object.__copy__(self) + :noindexentry: + + Called to implement the shallow copy operation; + no additional arguments are passed. + +.. method:: object.__deepcopy__(self, memo) + :noindexentry: + + Called to implement the deep copy operation; it is passed one + argument, the *memo* dictionary. If the ``__deepcopy__`` implementation needs + to make a deep copy of a component, it should call the :func:`~copy.deepcopy` function + with the component as first argument and the *memo* dictionary as second argument. + The *memo* dictionary should be treated as an opaque object. + + +.. index:: + single: __replace__() (replace protocol) + +Function :func:`!copy.replace` is more limited +than :func:`~copy.copy` and :func:`~copy.deepcopy`, +and only supports named tuples created by :func:`~collections.namedtuple`, +:mod:`dataclasses`, and other classes which define method :meth:`~object.__replace__`. + +.. method:: object.__replace__(self, /, **changes) + :noindexentry: + + This method should create a new object of the same type, + replacing fields with values from *changes*. .. seealso:: diff --git a/Doc/library/csv.rst b/Doc/library/csv.rst index 64baa69be4af31..7a5589e68b3052 100644 --- a/Doc/library/csv.rst +++ b/Doc/library/csv.rst @@ -55,10 +55,11 @@ The :mod:`csv` module defines the following functions: .. function:: reader(csvfile, dialect='excel', **fmtparams) - Return a reader object which will iterate over lines in the given *csvfile*. - *csvfile* can be any object which supports the :term:`iterator` protocol and returns a - string each time its :meth:`!__next__` method is called --- :term:`file objects - ` and list objects are both suitable. If *csvfile* is a file object, + Return a :ref:`reader object ` that will process + lines from the given *csvfile*. A csvfile must be an iterable of + strings, each in the reader's defined csv format. + A csvfile is most commonly a file-like object or list. + If *csvfile* is a file object, it should be opened with ``newline=''``. [1]_ An optional *dialect* parameter can be given which is used to define a set of parameters specific to a particular CSV dialect. It may be an instance of a subclass of @@ -288,9 +289,9 @@ The :mod:`csv` module defines the following classes: Inspecting each column, one of two key criteria will be considered to estimate if the sample contains a header: - - the second through n-th rows contain numeric values - - the second through n-th rows contain strings where at least one value's - length differs from that of the putative header of that column. + - the second through n-th rows contain numeric values + - the second through n-th rows contain strings where at least one value's + length differs from that of the putative header of that column. Twenty rows after the first row are sampled; if more than half of columns + rows meet the criteria, :const:`True` is returned. @@ -309,6 +310,8 @@ An example for :class:`Sniffer` use:: # ... process CSV file contents here ... +.. _csv-constants: + The :mod:`csv` module defines the following constants: .. data:: QUOTE_ALL @@ -432,8 +435,8 @@ Dialects support the following attributes: .. attribute:: Dialect.quoting Controls when quotes should be generated by the writer and recognised by the - reader. It can take on any of the :const:`QUOTE_\*` constants (see section - :ref:`csv-contents`) and defaults to :const:`QUOTE_MINIMAL`. + reader. It can take on any of the :ref:`QUOTE_\* constants ` + and defaults to :const:`QUOTE_MINIMAL`. .. attribute:: Dialect.skipinitialspace @@ -447,6 +450,8 @@ Dialects support the following attributes: When ``True``, raise exception :exc:`Error` on bad CSV input. The default is ``False``. +.. _reader-objects: + Reader Objects -------------- diff --git a/Doc/library/ctypes.rst b/Doc/library/ctypes.rst index ea7873a885172e..ef3a9a0f5898af 100644 --- a/Doc/library/ctypes.rst +++ b/Doc/library/ctypes.rst @@ -41,7 +41,7 @@ You load libraries by accessing them as attributes of these objects. *cdll* loads libraries which export functions using the standard ``cdecl`` calling convention, while *windll* libraries call functions using the ``stdcall`` calling convention. *oledll* also uses the ``stdcall`` calling convention, and -assumes the functions return a Windows :c:type:`HRESULT` error code. The error +assumes the functions return a Windows :c:type:`!HRESULT` error code. The error code is used to automatically raise an :class:`OSError` exception when the function call fails. @@ -72,8 +72,9 @@ Windows appends the usual ``.dll`` file suffix automatically. On Linux, it is required to specify the filename *including* the extension to load a library, so attribute access can not be used to load libraries. Either the -:meth:`LoadLibrary` method of the dll loaders should be used, or you should load -the library by creating an instance of CDLL by calling the constructor:: +:meth:`~LibraryLoader.LoadLibrary` method of the dll loaders should be used, +or you should load the library by creating an instance of CDLL by calling +the constructor:: >>> cdll.LoadLibrary("libc.so.6") # doctest: +LINUX @@ -333,7 +334,7 @@ property:: 10 b'Hi\x00lo\x00\x00\x00\x00\x00' >>> -The :func:`create_string_buffer` function replaces the old :func:`c_buffer` +The :func:`create_string_buffer` function replaces the old :func:`!c_buffer` function (which is still available as an alias). To create a mutable memory block containing unicode characters of the C type :c:type:`wchar_t`, use the :func:`create_unicode_buffer` function. @@ -383,15 +384,15 @@ as calling functions with a fixed number of parameters. On some platforms, and i particular ARM64 for Apple Platforms, the calling convention for variadic functions is different than that for regular functions. -On those platforms it is required to specify the *argtypes* attribute for the -regular, non-variadic, function arguments: +On those platforms it is required to specify the :attr:`~_FuncPtr.argtypes` +attribute for the regular, non-variadic, function arguments: .. code-block:: python3 libc.printf.argtypes = [ctypes.c_char_p] Because specifying the attribute does not inhibit portability it is advised to always -specify ``argtypes`` for all variadic functions. +specify :attr:`~_FuncPtr.argtypes` for all variadic functions. .. _ctypes-calling-functions-with-own-custom-data-types: @@ -400,9 +401,10 @@ Calling functions with your own custom data types ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ You can also customize :mod:`ctypes` argument conversion to allow instances of -your own classes be used as function arguments. :mod:`ctypes` looks for an -:attr:`_as_parameter_` attribute and uses this as the function argument. Of -course, it must be one of integer, string, or bytes:: +your own classes be used as function arguments. :mod:`ctypes` looks for an +:attr:`!_as_parameter_` attribute and uses this as the function argument. The +attribute must be an integer, string, bytes, a :mod:`ctypes` instance, or an +object with an :attr:`!_as_parameter_` attribute:: >>> class Bottles: ... def __init__(self, number): @@ -414,7 +416,7 @@ course, it must be one of integer, string, or bytes:: 19 >>> -If you don't want to store the instance's data in the :attr:`_as_parameter_` +If you don't want to store the instance's data in the :attr:`!_as_parameter_` instance variable, you could define a :class:`property` which makes the attribute available on request. @@ -425,9 +427,9 @@ Specifying the required argument types (function prototypes) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ It is possible to specify the required argument types of functions exported from -DLLs by setting the :attr:`argtypes` attribute. +DLLs by setting the :attr:`~_FuncPtr.argtypes` attribute. -:attr:`argtypes` must be a sequence of C data types (the ``printf`` function is +:attr:`~_FuncPtr.argtypes` must be a sequence of C data types (the :func:`!printf` function is probably not a good example here, because it takes a variable number and different types of parameters depending on the format string, on the other hand this is quite handy to experiment with this feature):: @@ -451,14 +453,14 @@ prototype for a C function), and tries to convert the arguments to valid types:: >>> If you have defined your own classes which you pass to function calls, you have -to implement a :meth:`from_param` class method for them to be able to use them -in the :attr:`argtypes` sequence. The :meth:`from_param` class method receives +to implement a :meth:`~_CData.from_param` class method for them to be able to use them +in the :attr:`~_FuncPtr.argtypes` sequence. The :meth:`~_CData.from_param` class method receives the Python object passed to the function call, it should do a typecheck or whatever is needed to make sure this object is acceptable, and then return the -object itself, its :attr:`_as_parameter_` attribute, or whatever you want to +object itself, its :attr:`!_as_parameter_` attribute, or whatever you want to pass as the C function argument in this case. Again, the result should be an integer, string, bytes, a :mod:`ctypes` instance, or an object with an -:attr:`_as_parameter_` attribute. +:attr:`!_as_parameter_` attribute. .. _ctypes-return-types: @@ -475,16 +477,16 @@ Return types By default functions are assumed to return the C :c:expr:`int` type. Other -return types can be specified by setting the :attr:`restype` attribute of the +return types can be specified by setting the :attr:`~_FuncPtr.restype` attribute of the function object. -The C prototype of ``time()`` is ``time_t time(time_t *)``. Because :c:type:`time_t` -might be of a different type than the default return type ``int``, you should -specify the ``restype``:: +The C prototype of :c:func:`time` is ``time_t time(time_t *)``. Because :c:type:`time_t` +might be of a different type than the default return type :c:expr:`int`, you should +specify the :attr:`!restype` attribute:: >>> libc.time.restype = c_time_t -The argument types can be specified using ``argtypes``:: +The argument types can be specified using :attr:`~_FuncPtr.argtypes`:: >>> libc.time.argtypes = (POINTER(c_time_t),) @@ -493,7 +495,7 @@ To call the function with a ``NULL`` pointer as first argument, use ``None``:: >>> print(libc.time(None)) # doctest: +SKIP 1150640792 -Here is a more advanced example, it uses the ``strchr`` function, which expects +Here is a more advanced example, it uses the :func:`!strchr` function, which expects a string pointer and a char, and returns a pointer to a string:: >>> strchr = libc.strchr @@ -506,8 +508,8 @@ a string pointer and a char, and returns a pointer to a string:: None >>> -If you want to avoid the ``ord("x")`` calls above, you can set the -:attr:`argtypes` attribute, and the second argument will be converted from a +If you want to avoid the :func:`ord("x") ` calls above, you can set the +:attr:`~_FuncPtr.argtypes` attribute, and the second argument will be converted from a single character Python bytes object into a C char: .. doctest:: @@ -526,7 +528,7 @@ single character Python bytes object into a C char: >>> You can also use a callable Python object (a function or a class for example) as -the :attr:`restype` attribute, if the foreign function returns an integer. The +the :attr:`~_FuncPtr.restype` attribute, if the foreign function returns an integer. The callable will be called with the *integer* the C function returns, and the result of this call will be used as the result of your function call. This is useful to check for error return values and automatically raise an exception:: @@ -554,7 +556,8 @@ get the string representation of an error code, and *returns* an exception. :func:`GetLastError` to retrieve it. Please note that a much more powerful error checking mechanism is available -through the :attr:`errcheck` attribute; see the reference manual for details. +through the :attr:`~_FuncPtr.errcheck` attribute; +see the reference manual for details. .. _ctypes-passing-pointers: @@ -592,7 +595,7 @@ Structures and unions Structures and unions must derive from the :class:`Structure` and :class:`Union` base classes which are defined in the :mod:`ctypes` module. Each subclass must -define a :attr:`_fields_` attribute. :attr:`_fields_` must be a list of +define a :attr:`~Structure._fields_` attribute. :attr:`!_fields_` must be a list of *2-tuples*, containing a *field name* and a *field type*. The field type must be a :mod:`ctypes` type like :class:`c_int`, or any other @@ -664,9 +667,9 @@ Structure/union alignment and byte order By default, Structure and Union fields are aligned in the same way the C compiler does it. It is possible to override this behavior by specifying a -:attr:`_pack_` class attribute in the subclass definition. This must be set to a -positive integer and specifies the maximum alignment for the fields. This is -what ``#pragma pack(n)`` also does in MSVC. +:attr:`~Structure._pack_` class attribute in the subclass definition. +This must be set to a positive integer and specifies the maximum alignment for the fields. +This is what ``#pragma pack(n)`` also does in MSVC. :mod:`ctypes` uses the native byte order for Structures and Unions. To build structures with non-native byte order, you can use one of the @@ -682,7 +685,7 @@ Bit fields in structures and unions It is possible to create structures and unions containing bit fields. Bit fields are only possible for integer fields, the bit width is specified as the third -item in the :attr:`_fields_` tuples:: +item in the :attr:`~Structure._fields_` tuples:: >>> class Int(Structure): ... _fields_ = [("first_16", c_int, 16), @@ -853,7 +856,7 @@ Type conversions ^^^^^^^^^^^^^^^^ Usually, ctypes does strict type checking. This means, if you have -``POINTER(c_int)`` in the :attr:`argtypes` list of a function or as the type of +``POINTER(c_int)`` in the :attr:`~_FuncPtr.argtypes` list of a function or as the type of a member field in a structure definition, only instances of exactly the same type are accepted. There are some exceptions to this rule, where ctypes accepts other objects. For example, you can pass compatible array instances instead of @@ -874,7 +877,7 @@ pointer types. So, for ``POINTER(c_int)``, ctypes accepts an array of c_int:: >>> In addition, if a function argument is explicitly declared to be a pointer type -(such as ``POINTER(c_int)``) in :attr:`argtypes`, an object of the pointed +(such as ``POINTER(c_int)``) in :attr:`~_FuncPtr.argtypes`, an object of the pointed type (``c_int`` in this case) can be passed to the function. ctypes will apply the required :func:`byref` conversion in this case automatically. @@ -950,8 +953,8 @@ work:: >>> because the new ``class cell`` is not available in the class statement itself. -In :mod:`ctypes`, we can define the ``cell`` class and set the :attr:`_fields_` -attribute later, after the class statement:: +In :mod:`ctypes`, we can define the ``cell`` class and set the +:attr:`~Structure._fields_` attribute later, after the class statement:: >>> from ctypes import * >>> class cell(Structure): @@ -1001,8 +1004,8 @@ argument, and the callback functions expected argument types as the remaining arguments. I will present an example here which uses the standard C library's -:c:func:`qsort` function, that is used to sort items with the help of a callback -function. :c:func:`qsort` will be used to sort an array of integers:: +:c:func:`!qsort` function, that is used to sort items with the help of a callback +function. :c:func:`!qsort` will be used to sort an array of integers:: >>> IntArray5 = c_int * 5 >>> ia = IntArray5(5, 1, 7, 33, 99) @@ -1010,7 +1013,7 @@ function. :c:func:`qsort` will be used to sort an array of integers:: >>> qsort.restype = None >>> -:func:`qsort` must be called with a pointer to the data to sort, the number of +:func:`!qsort` must be called with a pointer to the data to sort, the number of items in the data array, the size of one item, and a pointer to the comparison function, the callback. The callback will then be called with two pointers to items, and it must return a negative integer if the first item is smaller than @@ -1102,7 +1105,7 @@ Some shared libraries not only export functions, they also export variables. An 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 +:mod:`ctypes` can access values like this with the :meth:`~_CData.in_dll` class methods of the type. *pythonapi* is a predefined symbol giving access to the Python C api:: @@ -1292,13 +1295,13 @@ Finding shared libraries When programming in a compiled language, shared libraries are accessed when compiling/linking a program, and when the program is run. -The purpose of the :func:`find_library` function is to locate a library in a way +The purpose of the :func:`~ctypes.util.find_library` function is to locate a library in a way similar to what the compiler or runtime loader does (on platforms with several versions of a shared library the most recent should be loaded), while the ctypes library loaders act like when a program is run, and call the runtime loader directly. -The :mod:`ctypes.util` module provides a function which can help to determine +The :mod:`!ctypes.util` module provides a function which can help to determine the library to load. @@ -1313,7 +1316,7 @@ the library to load. The exact functionality is system dependent. -On Linux, :func:`find_library` tries to run external programs +On Linux, :func:`~ctypes.util.find_library` tries to run external programs (``/sbin/ldconfig``, ``gcc``, ``objdump`` and ``ld``) to find the library file. It returns the filename of the library file. @@ -1332,7 +1335,7 @@ Here are some examples:: 'libbz2.so.1.0' >>> -On macOS, :func:`find_library` tries several predefined naming schemes and paths +On macOS, :func:`~ctypes.util.find_library` tries several predefined naming schemes and paths to locate the library, and returns a full pathname if successful:: >>> from ctypes.util import find_library @@ -1346,13 +1349,13 @@ to locate the library, and returns a full pathname if successful:: '/System/Library/Frameworks/AGL.framework/AGL' >>> -On Windows, :func:`find_library` searches along the system search path, and +On Windows, :func:`~ctypes.util.find_library` searches along the system search path, and returns the full pathname, but since there is no predefined naming scheme a call like ``find_library("c")`` will fail and return ``None``. If wrapping a shared library with :mod:`ctypes`, it *may* be better to determine the shared library name at development time, and hardcode that into the wrapper -module instead of using :func:`find_library` to locate the library at runtime. +module instead of using :func:`~ctypes.util.find_library` to locate the library at runtime. .. _ctypes-loading-shared-libraries: @@ -1400,7 +1403,8 @@ way is to instantiate one of the following classes: failure, an :class:`OSError` is automatically raised. .. versionchanged:: 3.3 - :exc:`WindowsError` used to be raised. + :exc:`WindowsError` used to be raised, + which is now an alias of :exc:`OSError`. .. versionchanged:: 3.12 @@ -1437,9 +1441,9 @@ function exported by these libraries, and reacquired afterwards. All these classes can be instantiated by calling them with at least one argument, the pathname of the shared library. If you have an existing handle to an already loaded shared library, it can be passed as the ``handle`` named -parameter, otherwise the underlying platforms ``dlopen`` or ``LoadLibrary`` -function is used to load the library into the process, and to get a handle to -it. +parameter, otherwise the underlying platforms :c:func:`!dlopen` or +:c:func:`!LoadLibrary` function is used to load the library into +the process, and to get a handle to it. The *mode* parameter can be used to specify how the library is loaded. For details, consult the :manpage:`dlopen(3)` manpage. On Windows, *mode* is @@ -1459,7 +1463,7 @@ to a new value and returns the former value. The *use_last_error* parameter, when set to true, enables the same mechanism for the Windows error code which is managed by the :func:`GetLastError` and -:func:`SetLastError` Windows API functions; :func:`ctypes.get_last_error` and +:func:`!SetLastError` Windows API functions; :func:`ctypes.get_last_error` and :func:`ctypes.set_last_error` are used to request and change the ctypes private copy of the windows error code. @@ -1522,8 +1526,8 @@ underscore to not clash with exported function names: Shared libraries can also be loaded by using one of the prefabricated objects, which are instances of the :class:`LibraryLoader` class, either by calling the -:meth:`LoadLibrary` method, or by retrieving the library as attribute of the -loader instance. +:meth:`~LibraryLoader.LoadLibrary` method, or by retrieving the library as +attribute of the loader instance. .. class:: LibraryLoader(dlltype) @@ -1531,7 +1535,7 @@ loader instance. Class which loads shared libraries. *dlltype* should be one of the :class:`CDLL`, :class:`PyDLL`, :class:`WinDLL`, or :class:`OleDLL` types. - :meth:`__getattr__` has special behavior: It allows loading a shared library by + :meth:`!__getattr__` has special behavior: It allows loading a shared library by accessing it as attribute of a library loader instance. The result is cached, so repeated attribute accesses return the same library each time. @@ -1576,7 +1580,7 @@ object is available: An instance of :class:`PyDLL` that exposes Python C API functions as attributes. Note that all these functions are assumed to return C :c:expr:`int`, which is of course not always the truth, so you have to assign - the correct :attr:`restype` attribute to use these functions. + the correct :attr:`!restype` attribute to use these functions. .. audit-event:: ctypes.dlopen name ctypes.LibraryLoader @@ -1628,7 +1632,7 @@ They are instances of a private class: the callable will be called with this integer, allowing further processing or error checking. Using this is deprecated, for more flexible post processing or error checking use a ctypes data type as - :attr:`restype` and assign a callable to the :attr:`errcheck` attribute. + :attr:`!restype` and assign a callable to the :attr:`errcheck` attribute. .. attribute:: argtypes @@ -1639,14 +1643,14 @@ They are instances of a private class: unspecified arguments as well. When a foreign function is called, each actual argument is passed to the - :meth:`from_param` class method of the items in the :attr:`argtypes` + :meth:`~_CData.from_param` class method of the items in the :attr:`argtypes` tuple, this method allows adapting the actual argument to an object that the foreign function accepts. For example, a :class:`c_char_p` item in the :attr:`argtypes` tuple will convert a string passed as argument into a bytes object using ctypes conversion rules. New: It is now possible to put items in argtypes which are not ctypes - types, but each item must have a :meth:`from_param` method which returns a + types, but each item must have a :meth:`~_CData.from_param` method which returns a value usable as argument (integer, string, ctypes instance). This allows defining adapters that can adapt custom objects as function parameters. @@ -1660,7 +1664,7 @@ They are instances of a private class: :module: *result* is what the foreign function returns, as specified by the - :attr:`restype` attribute. + :attr:`!restype` attribute. *func* is the foreign function object itself, this allows reusing the same callable object to check or post process the results of several @@ -1734,70 +1738,70 @@ See :ref:`ctypes-callback-functions` for examples. Function prototypes created by these factory functions can be instantiated in different ways, depending on the type and number of the parameters in the call: +.. function:: prototype(address) + :noindex: + :module: - .. function:: prototype(address) - :noindex: - :module: + Returns a foreign function at the specified address which must be an integer. - Returns a foreign function at the specified address which must be an integer. +.. function:: prototype(callable) + :noindex: + :module: - .. function:: prototype(callable) - :noindex: - :module: + Create a C callable function (a callback function) from a Python *callable*. - Create a C callable function (a callback function) from a Python *callable*. +.. function:: prototype(func_spec[, paramflags]) + :noindex: + :module: - .. function:: prototype(func_spec[, paramflags]) - :noindex: - :module: + Returns a foreign function exported by a shared library. *func_spec* must + be a 2-tuple ``(name_or_ordinal, library)``. The first item is the name of + the exported function as string, or the ordinal of the exported function + as small integer. The second item is the shared library instance. - Returns a foreign function exported by a shared library. *func_spec* must - be a 2-tuple ``(name_or_ordinal, library)``. The first item is the name of - the exported function as string, or the ordinal of the exported function - as small integer. The second item is the shared library instance. +.. function:: prototype(vtbl_index, name[, paramflags[, iid]]) + :noindex: + :module: - .. function:: prototype(vtbl_index, name[, paramflags[, iid]]) - :noindex: - :module: + Returns a foreign function that will call a COM method. *vtbl_index* is + the index into the virtual function table, a small non-negative + integer. *name* is name of the COM method. *iid* is an optional pointer to + the interface identifier which is used in extended error reporting. - Returns a foreign function that will call a COM method. *vtbl_index* is - the index into the virtual function table, a small non-negative - integer. *name* is name of the COM method. *iid* is an optional pointer to - the interface identifier which is used in extended error reporting. + COM methods use a special calling convention: They require a pointer to + the COM interface as first argument, in addition to those parameters that + are specified in the :attr:`!argtypes` tuple. - COM methods use a special calling convention: They require a pointer to - the COM interface as first argument, in addition to those parameters that - are specified in the :attr:`argtypes` tuple. +The optional *paramflags* parameter creates foreign function wrappers with much +more functionality than the features described above. - The optional *paramflags* parameter creates foreign function wrappers with much - more functionality than the features described above. +*paramflags* must be a tuple of the same length as :attr:`~_FuncPtr.argtypes`. - *paramflags* must be a tuple of the same length as :attr:`argtypes`. +Each item in this tuple contains further information about a parameter, it must +be a tuple containing one, two, or three items. - Each item in this tuple contains further information about a parameter, it must - be a tuple containing one, two, or three items. +The first item is an integer containing a combination of direction +flags for the parameter: - The first item is an integer containing a combination of direction - flags for the parameter: + 1 + Specifies an input parameter to the function. - 1 - Specifies an input parameter to the function. + 2 + Output parameter. The foreign function fills in a value. - 2 - Output parameter. The foreign function fills in a value. + 4 + Input parameter which defaults to the integer zero. - 4 - Input parameter which defaults to the integer zero. +The optional second item is the parameter name as string. If this is specified, +the foreign function can be called with named parameters. - The optional second item is the parameter name as string. If this is specified, - the foreign function can be called with named parameters. +The optional third item is the default value for this parameter. - The optional third item is the default value for this parameter. -This example demonstrates how to wrap the Windows ``MessageBoxW`` function so +The following example demonstrates how to wrap the Windows ``MessageBoxW`` function so that it supports default parameters and named arguments. The C declaration from the windows header file is this:: @@ -1845,7 +1849,7 @@ value if there is a single one, or a tuple containing the output parameter values when there are more than one, so the GetWindowRect function now returns a RECT instance, when called. -Output parameters can be combined with the :attr:`errcheck` protocol to do +Output parameters can be combined with the :attr:`~_FuncPtr.errcheck` protocol to do further output processing and error checking. The win32 ``GetWindowRect`` api function returns a ``BOOL`` to signal success or failure, so this function could do the error checking, and raises an exception when the api call failed:: @@ -1858,7 +1862,7 @@ do the error checking, and raises an exception when the api call failed:: >>> GetWindowRect.errcheck = errcheck >>> -If the :attr:`errcheck` function returns the argument tuple it receives +If the :attr:`~_FuncPtr.errcheck` function returns the argument tuple it receives unchanged, :mod:`ctypes` continues the normal processing it does on the output parameters. If you want to return a tuple of window coordinates instead of a ``RECT`` instance, you can retrieve the fields in the function and return them @@ -2008,7 +2012,7 @@ Utility functions .. function:: get_last_error() Windows only: returns the current value of the ctypes-private copy of the system - :data:`LastError` variable in the calling thread. + :data:`!LastError` variable in the calling thread. .. audit-event:: ctypes.get_last_error "" ctypes.get_last_error @@ -2026,17 +2030,17 @@ Utility functions specifying an address, or a ctypes instance. -.. function:: POINTER(type) +.. function:: POINTER(type, /) - This factory function creates and returns a new ctypes pointer type. Pointer - types are cached and reused internally, so calling this function repeatedly is - cheap. *type* must be a ctypes type. + Create and return a new ctypes pointer type. Pointer types are cached and + reused internally, so calling this function repeatedly is cheap. + *type* must be a ctypes type. -.. function:: pointer(obj) +.. function:: pointer(obj, /) - This function creates a new pointer instance, pointing to *obj*. The returned - object is of the type ``POINTER(type(obj))``. + Create a new pointer instance, pointing to *obj*. + The returned object is of the type ``POINTER(type(obj))``. Note: If you just want to pass a pointer to an object to a foreign function call, you should use ``byref(obj)`` which is much faster. @@ -2061,7 +2065,7 @@ Utility functions .. function:: set_last_error(value) Windows only: set the current value of the ctypes-private copy of the system - :data:`LastError` variable in the calling thread to *value* and return the + :data:`!LastError` variable in the calling thread to *value* and return the previous value. .. audit-event:: ctypes.set_last_error error ctypes.set_last_error @@ -2085,13 +2089,14 @@ Utility functions .. function:: WinError(code=None, descr=None) Windows only: this function is probably the worst-named thing in ctypes. It - creates an instance of OSError. If *code* is not specified, + creates an instance of :exc:`OSError`. If *code* is not specified, ``GetLastError`` is called to determine the error code. If *descr* is not specified, :func:`FormatError` is called to get a textual description of the error. .. versionchanged:: 3.3 - An instance of :exc:`WindowsError` used to be created. + An instance of :exc:`WindowsError` used to be created, which is now an + alias of :exc:`OSError`. .. function:: wstring_at(address, size=-1) @@ -2157,8 +2162,8 @@ Data types This method adapts *obj* to a ctypes type. It is called with the actual object used in a foreign function call when the type is present in the - foreign function's :attr:`argtypes` tuple; it must return an object that - can be used as a function call parameter. + foreign function's :attr:`~_FuncPtr.argtypes` tuple; + it must return an object that can be used as a function call parameter. All ctypes data types have a default implementation of this classmethod that normally returns *obj* if that is an instance of the type. Some @@ -2223,13 +2228,13 @@ Fundamental data types Fundamental data types, when returned as foreign function call results, or, for example, by retrieving structure field members or array items, are transparently converted to native Python types. In other words, if a foreign function has a -:attr:`restype` of :class:`c_char_p`, you will always receive a Python bytes +:attr:`~_FuncPtr.restype` of :class:`c_char_p`, you will always receive a Python bytes object, *not* a :class:`c_char_p` instance. .. XXX above is false, it actually returns a Unicode string Subclasses of fundamental data types do *not* inherit this behavior. So, if a -foreign functions :attr:`restype` is a subclass of :class:`c_void_p`, you will +foreign functions :attr:`!restype` is a subclass of :class:`c_void_p`, you will receive an instance of this subclass from the function call. Of course, you can get the value of the pointer by accessing the ``value`` attribute. @@ -2428,7 +2433,7 @@ These are the fundamental ctypes data types: .. class:: HRESULT - Windows only: Represents a :c:type:`HRESULT` value, which contains success or + Windows only: Represents a :c:type:`!HRESULT` value, which contains success or error information for a function or method call. @@ -2437,9 +2442,9 @@ These are the fundamental ctypes data types: Represents the C :c:expr:`PyObject *` datatype. Calling this without an argument creates a ``NULL`` :c:expr:`PyObject *` pointer. -The :mod:`ctypes.wintypes` module provides quite some other Windows specific -data types, for example :c:type:`HWND`, :c:type:`WPARAM`, or :c:type:`DWORD`. Some -useful structures like :c:type:`MSG` or :c:type:`RECT` are also defined. +The :mod:`!ctypes.wintypes` module provides quite some other Windows specific +data types, for example :c:type:`!HWND`, :c:type:`!WPARAM`, or :c:type:`!DWORD`. +Some useful structures like :c:type:`!MSG` or :c:type:`!RECT` are also defined. .. _ctypes-structured-data-types: diff --git a/Doc/library/curses.rst b/Doc/library/curses.rst index 9ab67c21975394..9b8a98f05f7cbb 100644 --- a/Doc/library/curses.rst +++ b/Doc/library/curses.rst @@ -1771,9 +1771,9 @@ The following table lists mouse button constants used by :meth:`getmouse`: | .. data:: BUTTON_ALT | Control was down during button state change | +----------------------------------+---------------------------------------------+ - .. versionchanged:: 3.10 - The ``BUTTON5_*`` constants are now exposed if they are provided by the - underlying curses library. +.. versionchanged:: 3.10 + The ``BUTTON5_*`` constants are now exposed if they are provided by the + underlying curses library. The following table lists the predefined colors: diff --git a/Doc/library/dataclasses.rst b/Doc/library/dataclasses.rst index 535a60ccca8d07..bbbbcb00d8fef8 100644 --- a/Doc/library/dataclasses.rst +++ b/Doc/library/dataclasses.rst @@ -319,13 +319,11 @@ Module contents module-level method (see below). Users should never instantiate a :class:`Field` object directly. Its documented attributes are: - - ``name``: The name of the field. - - - ``type``: The type of the field. - - - ``default``, ``default_factory``, ``init``, ``repr``, ``hash``, - ``compare``, ``metadata``, and ``kw_only`` have the identical - meaning and values as they do in the :func:`field` function. + - ``name``: The name of the field. + - ``type``: The type of the field. + - ``default``, ``default_factory``, ``init``, ``repr``, ``hash``, + ``compare``, ``metadata``, and ``kw_only`` have the identical + meaning and values as they do in the :func:`field` function. Other attributes may exist, but they are private and must not be inspected or relied on. @@ -456,6 +454,8 @@ Module contents ``replace()`` (or similarly named) method which handles instance copying. + Dataclass instances are also supported by generic function :func:`copy.replace`. + .. function:: is_dataclass(obj) Return ``True`` if its parameter is a dataclass or an instance of one, @@ -609,7 +609,7 @@ methods will raise a :exc:`FrozenInstanceError` when invoked. There is a tiny performance penalty when using ``frozen=True``: :meth:`~object.__init__` cannot use simple assignment to initialize fields, and -must use :meth:`~object.__setattr__`. +must use :meth:`!object.__setattr__`. Inheritance ----------- diff --git a/Doc/library/datetime.rst b/Doc/library/datetime.rst index bed19ad145a20c..3674b4bd97d39d 100644 --- a/Doc/library/datetime.rst +++ b/Doc/library/datetime.rst @@ -19,6 +19,10 @@ The :mod:`datetime` module supplies classes for manipulating dates and times. While date and time arithmetic is supported, the focus of the implementation is on efficient attribute extraction for output formatting and manipulation. +.. tip:: + + Skip to :ref:`the format codes `. + .. seealso:: Module :mod:`calendar` @@ -33,6 +37,11 @@ on efficient attribute extraction for output formatting and manipulation. Package `dateutil `_ Third-party library with expanded time zone and parsing support. + Package `DateType `_ + Third-party library that introduces distinct static types to e.g. allow + :term:`static type checkers ` + to differentiate between naive and aware datetimes. + .. _datetime-naive-aware: Aware and Naive Objects @@ -644,6 +653,9 @@ Instance methods: >>> d.replace(day=26) datetime.date(2002, 12, 26) + :class:`date` objects are also supported by generic function + :func:`copy.replace`. + .. method:: date.timetuple() @@ -1243,6 +1255,9 @@ Instance methods: ``tzinfo=None`` can be specified to create a naive datetime from an aware datetime with no conversion of date and time data. + :class:`datetime` objects are also supported by generic function + :func:`copy.replace`. + .. versionadded:: 3.6 Added the ``fold`` argument. @@ -1784,6 +1799,8 @@ Other constructor: Examples:: + .. doctest:: + >>> from datetime import time >>> time.fromisoformat('04:23:01') datetime.time(4, 23, 1) @@ -1793,7 +1810,7 @@ Other constructor: datetime.time(4, 23, 1) >>> time.fromisoformat('04:23:01.000384') datetime.time(4, 23, 1, 384) - >>> time.fromisoformat('04:23:01,000') + >>> time.fromisoformat('04:23:01,000384') datetime.time(4, 23, 1, 384) >>> time.fromisoformat('04:23:01+04:00') datetime.time(4, 23, 1, tzinfo=datetime.timezone(datetime.timedelta(seconds=14400))) @@ -1819,6 +1836,9 @@ Instance methods: ``tzinfo=None`` can be specified to create a naive :class:`.time` from an aware :class:`.time`, without conversion of the time data. + :class:`time` objects are also supported by generic function + :func:`copy.replace`. + .. versionadded:: 3.6 Added the ``fold`` argument. @@ -1967,7 +1987,8 @@ Examples of working with a :class:`.time` object:: American EST and EDT. Special requirement for pickling: A :class:`tzinfo` subclass must have an - :meth:`__init__` method that can be called with no arguments, otherwise it can be + :meth:`~object.__init__` method that can be called with no arguments, + otherwise it can be pickled but possibly not unpickled again. This is a technical requirement that may be relaxed in the future. @@ -2322,6 +2343,8 @@ versus :meth:`strptime`: +----------------+--------------------------------------------------------+------------------------------------------------------------------------------+ + .. _format-codes: + :meth:`strftime` and :meth:`strptime` Format Codes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/Doc/library/dbm.rst b/Doc/library/dbm.rst index 766847b971b645..cb95c61322582f 100644 --- a/Doc/library/dbm.rst +++ b/Doc/library/dbm.rst @@ -272,6 +272,13 @@ This module can be used with the "classic" ndbm interface or the GNU GDBM compatibility interface. On Unix, the :program:`configure` script will attempt to locate the appropriate header file to simplify building this module. +.. warning:: + + The ndbm library shipped as part of macOS has an undocumented limitation on the + size of values, which can result in corrupted database files + when storing values larger than this limit. Reading such corrupted files can + result in a hard crash (segmentation fault). + .. exception:: error Raised on :mod:`dbm.ndbm`-specific errors, such as I/O errors. :exc:`KeyError` is raised diff --git a/Doc/library/decimal.rst b/Doc/library/decimal.rst index c2b96954c5f8ef..fb8bbf72adf268 100644 --- a/Doc/library/decimal.rst +++ b/Doc/library/decimal.rst @@ -1396,10 +1396,10 @@ In addition to the three supplied contexts, new contexts can be created with the With three arguments, compute ``(x**y) % modulo``. For the three argument form, the following restrictions on the arguments hold: - - all three arguments must be integral - - ``y`` must be nonnegative - - at least one of ``x`` or ``y`` must be nonzero - - ``modulo`` must be nonzero and have at most 'precision' digits + - all three arguments must be integral + - ``y`` must be nonnegative + - at least one of ``x`` or ``y`` must be nonzero + - ``modulo`` must be nonzero and have at most 'precision' digits The value resulting from ``Context.power(x, y, modulo)`` is equal to the value that would be obtained by computing ``(x**y) diff --git a/Doc/library/devmode.rst b/Doc/library/devmode.rst index 914aa45cf9cbc3..5b8a9bd1908456 100644 --- a/Doc/library/devmode.rst +++ b/Doc/library/devmode.rst @@ -59,8 +59,9 @@ Effects of the Python Development Mode: ``default``. * Call :func:`faulthandler.enable` at Python startup to install handlers for - the :const:`SIGSEGV`, :const:`SIGFPE`, :const:`SIGABRT`, :const:`SIGBUS` and - :const:`SIGILL` signals to dump the Python traceback on a crash. + the :const:`~signal.SIGSEGV`, :const:`~signal.SIGFPE`, + :const:`~signal.SIGABRT`, :const:`~signal.SIGBUS` and + :const:`~signal.SIGILL` signals to dump the Python traceback on a crash. It behaves as if the :option:`-X faulthandler <-X>` command line option is used or if the :envvar:`PYTHONFAULTHANDLER` environment variable is set to diff --git a/Doc/library/dialog.rst b/Doc/library/dialog.rst index 53f98c1018988f..191e0da12103fa 100644 --- a/Doc/library/dialog.rst +++ b/Doc/library/dialog.rst @@ -27,15 +27,15 @@ functions for creating simple modal dialogs to get a value from the user. The base class for custom dialogs. - .. method:: body(master) + .. method:: body(master) - Override to construct the dialog's interface and return the widget that - should have initial focus. + Override to construct the dialog's interface and return the widget that + should have initial focus. - .. method:: buttonbox() + .. method:: buttonbox() - Default behaviour adds OK and Cancel buttons. Override for custom button - layouts. + Default behaviour adds OK and Cancel buttons. Override for custom button + layouts. diff --git a/Doc/library/difflib.rst b/Doc/library/difflib.rst index 5ee1f4a02c6816..9abf19557f989c 100644 --- a/Doc/library/difflib.rst +++ b/Doc/library/difflib.rst @@ -171,9 +171,12 @@ diffs. For comparing directories and files, see also, the :mod:`filecmp` module. expressed in the ISO 8601 format. If not specified, the strings default to blanks. + >>> import sys + >>> from difflib import * >>> s1 = ['bacon\n', 'eggs\n', 'ham\n', 'guido\n'] >>> s2 = ['python\n', 'eggy\n', 'hamster\n', 'guido\n'] - >>> sys.stdout.writelines(context_diff(s1, s2, fromfile='before.py', tofile='after.py')) + >>> sys.stdout.writelines(context_diff(s1, s2, fromfile='before.py', + ... tofile='after.py')) *** before.py --- after.py *************** @@ -294,13 +297,12 @@ diffs. For comparing directories and files, see also, the :mod:`filecmp` module. For inputs that do not have trailing newlines, set the *lineterm* argument to ``""`` so that the output will be uniformly newline free. - The context diff format normally has a header for filenames and modification + The unified diff format normally has a header for filenames and modification times. Any or all of these may be specified using strings for *fromfile*, *tofile*, *fromfiledate*, and *tofiledate*. The modification times are normally expressed in the ISO 8601 format. If not specified, the strings default to blanks. - >>> s1 = ['bacon\n', 'eggs\n', 'ham\n', 'guido\n'] >>> s2 = ['python\n', 'eggy\n', 'hamster\n', 'guido\n'] >>> sys.stdout.writelines(unified_diff(s1, s2, fromfile='before.py', tofile='after.py')) @@ -570,8 +572,8 @@ The :class:`SequenceMatcher` class has this constructor: The three methods that return the ratio of matching to total characters can give different results due to differing levels of approximation, although -:meth:`quick_ratio` and :meth:`real_quick_ratio` are always at least as large as -:meth:`ratio`: +:meth:`~SequenceMatcher.quick_ratio` and :meth:`~SequenceMatcher.real_quick_ratio` +are always at least as large as :meth:`~SequenceMatcher.ratio`: >>> s = SequenceMatcher(None, "abcd", "bcde") >>> s.ratio() @@ -593,15 +595,15 @@ This example compares two strings, considering blanks to be "junk": ... "private Thread currentThread;", ... "private volatile Thread currentThread;") -:meth:`ratio` returns a float in [0, 1], measuring the similarity of the -sequences. As a rule of thumb, a :meth:`ratio` value over 0.6 means the +:meth:`~SequenceMatcher.ratio` returns a float in [0, 1], measuring the similarity of the +sequences. As a rule of thumb, a :meth:`~SequenceMatcher.ratio` value over 0.6 means the sequences are close matches: >>> print(round(s.ratio(), 3)) 0.866 If you're only interested in where the sequences match, -:meth:`get_matching_blocks` is handy: +:meth:`~SequenceMatcher.get_matching_blocks` is handy: >>> for block in s.get_matching_blocks(): ... print("a[%d] and b[%d] match for %d elements" % block) @@ -609,12 +611,12 @@ If you're only interested in where the sequences match, a[8] and b[17] match for 21 elements a[29] and b[38] match for 0 elements -Note that the last tuple returned by :meth:`get_matching_blocks` is always a -dummy, ``(len(a), len(b), 0)``, and this is the only case in which the last +Note that the last tuple returned by :meth:`~SequenceMatcher.get_matching_blocks` +is always a dummy, ``(len(a), len(b), 0)``, and this is the only case in which the last tuple element (number of elements matched) is ``0``. If you want to know how to change the first sequence into the second, use -:meth:`get_opcodes`: +:meth:`~SequenceMatcher.get_opcodes`: >>> for opcode in s.get_opcodes(): ... print("%6s a[%d:%d] b[%d:%d]" % opcode) @@ -689,7 +691,7 @@ Differ Example This example compares two texts. First we set up the texts, sequences of individual single-line strings ending with newlines (such sequences can also be -obtained from the :meth:`~io.BaseIO.readlines` method of file-like objects): +obtained from the :meth:`~io.IOBase.readlines` method of file-like objects): >>> text1 = ''' 1. Beautiful is better than ugly. ... 2. Explicit is better than implicit. diff --git a/Doc/library/dis.rst b/Doc/library/dis.rst index 2217c3a8035459..7492ae85c4ea46 100644 --- a/Doc/library/dis.rst +++ b/Doc/library/dis.rst @@ -42,27 +42,70 @@ interpreter. bytecode to specialize it for different runtime conditions. The adaptive bytecode can be shown by passing ``adaptive=True``. + .. versionchanged:: 3.12 + The argument of a jump is the offset of the target instruction relative + to the instruction that appears immediately after the jump instruction's + :opcode:`CACHE` entries. + + As a consequence, the presence of the :opcode:`CACHE` instructions is + transparent for forward jumps but needs to be taken into account when + reasoning about backward jumps. -Example: Given the function :func:`myfunc`:: + .. versionchanged:: 3.13 + The output shows logical labels rather than instruction offsets + for jump targets and exception handlers. The ``-O`` command line + option and the ``show_offsets`` argument were added. + +Example: Given the function :func:`!myfunc`:: def myfunc(alist): return len(alist) the following command can be used to display the disassembly of -:func:`myfunc`: +:func:`!myfunc`: .. doctest:: >>> dis.dis(myfunc) - 2 0 RESUME 0 + 2 RESUME 0 - 3 2 LOAD_GLOBAL 1 (NULL + len) - 12 LOAD_FAST 0 (alist) - 14 CALL 1 - 22 RETURN_VALUE + 3 LOAD_GLOBAL 1 (len + NULL) + LOAD_FAST 0 (alist) + CALL 1 + RETURN_VALUE (The "2" is a line number). +.. _dis-cli: + +Command-line interface +---------------------- + +The :mod:`dis` module can be invoked as a script from the command line: + +.. code-block:: sh + + python -m dis [-h] [-C] [-O] [infile] + +The following options are accepted: + +.. program:: dis + +.. cmdoption:: -h, --help + + Display usage and exit. + +.. cmdoption:: -C, --show-caches + + Show inline caches. + +.. cmdoption:: -O, --show-offsets + + Show offsets of instructions. + +If :file:`infile` is specified, its disassembled code will be written to stdout. +Otherwise, disassembly is performed on compiled source code recieved from stdin. + Bytecode analysis ----------------- @@ -73,7 +116,7 @@ The bytecode analysis API allows pieces of Python code to be wrapped in a code. .. class:: Bytecode(x, *, first_line=None, current_offset=None,\ - show_caches=False, adaptive=False) + show_caches=False, adaptive=False, show_offsets=False) Analyse the bytecode corresponding to a function, generator, asynchronous generator, coroutine, method, string of source code, or a code object (as @@ -98,6 +141,9 @@ code. If *adaptive* is ``True``, :meth:`.dis` will display specialized bytecode that may be different from the original bytecode. + If *show_offsets* is ``True``, :meth:`.dis` will include instruction + offsets in the output. + .. classmethod:: from_traceback(tb, *, show_caches=False) Construct a :class:`Bytecode` instance from the given traceback, setting @@ -220,7 +266,8 @@ operation is being performed, so the intermediate analysis object isn't useful: Added the *show_caches* and *adaptive* parameters. -.. function:: distb(tb=None, *, file=None, show_caches=False, adaptive=False) +.. function:: distb(tb=None, *, file=None, show_caches=False, adaptive=False, + show_offset=False) Disassemble the top-of-stack function of a traceback, using the last traceback if none was passed. The instruction causing the exception is @@ -235,9 +282,12 @@ operation is being performed, so the intermediate analysis object isn't useful: .. versionchanged:: 3.11 Added the *show_caches* and *adaptive* parameters. + .. versionchanged:: 3.13 + Added the *show_offsets* parameter. .. function:: disassemble(code, lasti=-1, *, file=None, show_caches=False, adaptive=False) - disco(code, lasti=-1, *, file=None, show_caches=False, adaptive=False) + disco(code, lasti=-1, *, file=None, show_caches=False, adaptive=False, + show_offsets=False) Disassemble a code object, indicating the last instruction if *lasti* was provided. The output is divided in the following columns: @@ -262,6 +312,8 @@ operation is being performed, so the intermediate analysis object isn't useful: .. versionchanged:: 3.11 Added the *show_caches* and *adaptive* parameters. + .. versionchanged:: 3.13 + Added the *show_offsets* parameter. .. function:: get_instructions(x, *, first_line=None, show_caches=False, adaptive=False) @@ -276,26 +328,35 @@ operation is being performed, so the intermediate analysis object isn't useful: source line information (if any) is taken directly from the disassembled code object. - The *show_caches* and *adaptive* parameters work as they do in :func:`dis`. + The *adaptive* parameter works as it does in :func:`dis`. .. versionadded:: 3.4 .. versionchanged:: 3.11 Added the *show_caches* and *adaptive* parameters. + .. versionchanged:: 3.13 + The *show_caches* parameter is deprecated and has no effect. The *cache_info* + field of each instruction is populated regardless of its value. + .. function:: findlinestarts(code) - This generator function uses the ``co_lines`` method - of the code object *code* to find the offsets which are starts of + This generator function uses the :meth:`~codeobject.co_lines` method + of the :ref:`code object ` *code* to find the offsets which + are starts of lines in the source code. They are generated as ``(offset, lineno)`` pairs. .. versionchanged:: 3.6 Line numbers can be decreasing. Before, they were always increasing. .. versionchanged:: 3.10 - The :pep:`626` ``co_lines`` method is used instead of the ``co_firstlineno`` - and ``co_lnotab`` attributes of the code object. + The :pep:`626` :meth:`~codeobject.co_lines` method is used instead of the + :attr:`~codeobject.co_firstlineno` and :attr:`~codeobject.co_lnotab` + attributes of the :ref:`code object `. + + .. versionchanged:: 3.13 + Line numbers can be ``None`` for bytecode that does not map to source lines. .. function:: findlabels(code) @@ -402,7 +463,12 @@ details of bytecode instructions as :class:`Instruction` instances: .. data:: starts_line - line started by this opcode (if any), otherwise ``None`` + ``True`` if this opcode starts a source line, otherwise ``False`` + + + .. data:: line_number + + source line number associated with this opcode (if any), otherwise ``None`` .. data:: is_jump_target @@ -421,6 +487,14 @@ details of bytecode instructions as :class:`Instruction` instances: :class:`dis.Positions` object holding the start and end locations that are covered by this instruction. + .. data::cache_info + + Information about the cache entries of this instruction, as + triplets of the form ``(name, size, data)``, where the ``name`` + and ``size`` describe the cache format and data is the contents + of the cache. ``cache_info`` is ``None`` if the instruction does not have + caches. + .. versionadded:: 3.4 .. versionchanged:: 3.11 @@ -429,8 +503,11 @@ details of bytecode instructions as :class:`Instruction` instances: .. versionchanged:: 3.13 + Changed field ``starts_line``. + Added fields ``start_offset``, ``cache_offset``, ``end_offset``, - ``baseopname``, ``baseopcode``, ``jump_target`` and ``oparg``. + ``baseopname``, ``baseopcode``, ``jump_target``, ``oparg``, + ``line_number`` and ``cache_info``. .. class:: Positions @@ -476,6 +553,14 @@ operations on it as if it was a Python list. The top of the stack corresponds to .. versionadded:: 3.12 +.. opcode:: END_SEND + + Implements ``del STACK[-2]``. + Used to clean up when a generator exits. + + .. versionadded:: 3.12 + + .. opcode:: COPY (i) Push the i-th item to the top of the stack without removing it from its original @@ -586,7 +671,7 @@ not have to be) the original ``STACK[-2]``. key = STACK.pop() container = STACK.pop() - STACK.append(container[index]) + STACK.append(container[key]) .. opcode:: STORE_SUBSCR @@ -770,6 +855,9 @@ iterations of the loop. .. versionchanged:: 3.12 oparg set to be the exception block depth, for efficient closing of generators. + .. versionchanged:: 3.13 + oparg is ``1`` if this instruction is part of a yield-from or await, and ``0`` + otherwise. .. opcode:: SETUP_ANNOTATIONS @@ -791,8 +879,8 @@ iterations of the loop. .. opcode:: RERAISE Re-raises the exception currently on top of the stack. If oparg is non-zero, - pops an additional value from the stack which is used to set ``f_lasti`` - of the current frame. + pops an additional value from the stack which is used to set + :attr:`~frame.f_lasti` of the current frame. .. versionadded:: 3.9 @@ -851,7 +939,7 @@ iterations of the loop. .. opcode:: LOAD_BUILD_CLASS - Pushes :func:`builtins.__build_class__` onto the stack. It is later called + Pushes :func:`!builtins.__build_class__` onto the stack. It is later called to construct a class. @@ -909,14 +997,14 @@ iterations of the loop. .. opcode:: STORE_NAME (namei) Implements ``name = STACK.pop()``. *namei* is the index of *name* in the attribute - :attr:`co_names` of the code object. The compiler tries to use - :opcode:`STORE_FAST` or :opcode:`STORE_GLOBAL` if possible. + :attr:`~codeobject.co_names` of the :ref:`code object `. + The compiler tries to use :opcode:`STORE_FAST` or :opcode:`STORE_GLOBAL` if possible. .. opcode:: DELETE_NAME (namei) - Implements ``del name``, where *namei* is the index into :attr:`co_names` - attribute of the code object. + Implements ``del name``, where *namei* is the index into :attr:`~codeobject.co_names` + attribute of the :ref:`code object `. .. opcode:: UNPACK_SEQUENCE (count) @@ -955,7 +1043,8 @@ iterations of the loop. value = STACK.pop() obj.name = value - where *namei* is the index of name in :attr:`co_names`. + where *namei* is the index of name in :attr:`~codeobject.co_names` of the + :ref:`code object `. .. opcode:: DELETE_ATTR (namei) @@ -964,7 +1053,8 @@ iterations of the loop. obj = STACK.pop() del obj.name - where *namei* is the index of name into :attr:`co_names`. + where *namei* is the index of name into :attr:`~codeobject.co_names` of the + :ref:`code object `. .. opcode:: STORE_GLOBAL (namei) @@ -1109,7 +1199,8 @@ iterations of the loop. This bytecode distinguishes two cases: if ``STACK[-1]`` has a method with the correct name, the bytecode pushes the unbound method and ``STACK[-1]``. ``STACK[-1]`` will be used as the first argument (``self``) by :opcode:`CALL` - when calling the unbound method. Otherwise, ``NULL`` and the object returned by + or :opcode:`CALL_KW` when calling the unbound method. + Otherwise, ``NULL`` and the object returned by the attribute lookup are pushed. .. versionchanged:: 3.12 @@ -1119,15 +1210,22 @@ iterations of the loop. .. opcode:: LOAD_SUPER_ATTR (namei) - This opcode implements :func:`super` (e.g. ``super().method()`` and - ``super().attr``). It works the same as :opcode:`LOAD_ATTR`, except that - ``namei`` is shifted left by 2 bits instead of 1, and instead of expecting a - single receiver on the stack, it expects three objects (from top of stack - down): ``self`` (the first argument to the current method), ``cls`` (the - class within which the current method was defined), and the global ``super``. + This opcode implements :func:`super`, both in its zero-argument and + two-argument forms (e.g. ``super().method()``, ``super().attr`` and + ``super(cls, self).method()``, ``super(cls, self).attr``). + + It pops three values from the stack (from top of stack down): + + * ``self``: the first argument to the current method + * ``cls``: the class within which the current method was defined + * the global ``super`` + + With respect to its argument, it works similarly to :opcode:`LOAD_ATTR`, + except that ``namei`` is shifted left by 2 bits instead of 1. The low bit of ``namei`` signals to attempt a method load, as with - :opcode:`LOAD_ATTR`. + :opcode:`LOAD_ATTR`, which results in pushing ``None`` and the loaded method. + When it is unset a single value is pushed to the stack. The second-low bit of ``namei``, if set, means that this was a two-argument call to :func:`super` (unset means zero-argument). @@ -1319,7 +1417,7 @@ iterations of the loop. Pushes a reference to the object the cell contains on the stack. .. versionchanged:: 3.11 - ``i`` is no longer offset by the length of ``co_varnames``. + ``i`` is no longer offset by the length of :attr:`~codeobject.co_varnames`. .. opcode:: LOAD_FROM_DICT_OR_DEREF (i) @@ -1341,7 +1439,7 @@ iterations of the loop. storage. .. versionchanged:: 3.11 - ``i`` is no longer offset by the length of ``co_varnames``. + ``i`` is no longer offset by the length of :attr:`~codeobject.co_varnames`. .. opcode:: DELETE_DEREF (i) @@ -1352,7 +1450,7 @@ iterations of the loop. .. versionadded:: 3.2 .. versionchanged:: 3.11 - ``i`` is no longer offset by the length of ``co_varnames``. + ``i`` is no longer offset by the length of :attr:`~codeobject.co_varnames`. .. opcode:: COPY_FREE_VARS (n) @@ -1377,25 +1475,14 @@ iterations of the loop. .. opcode:: CALL (argc) - Calls a callable object with the number of arguments specified by ``argc``, - including the named arguments specified by the preceding - :opcode:`KW_NAMES`, if any. - On the stack are (in ascending order), either: + Calls a callable object with the number of arguments specified by ``argc``. + On the stack are (in ascending order): - * NULL * The callable - * The positional arguments - * The named arguments - - or: - - * The callable - * ``self`` + * ``self`` or ``NULL`` * The remaining positional arguments - * The named arguments - ``argc`` is the total of the positional and named arguments, excluding - ``self`` when a ``NULL`` is not present. + ``argc`` is the total of the positional arguments, excluding ``self``. ``CALL`` pops all arguments and the callable object off the stack, calls the callable object with those arguments, and pushes the return value @@ -1403,6 +1490,33 @@ iterations of the loop. .. versionadded:: 3.11 + .. versionchanged:: 3.13 + The callable now always appears at the same position on the stack. + + .. versionchanged:: 3.13 + Calls with keyword arguments are now handled by :opcode:`CALL_KW`. + + +.. opcode:: CALL_KW (argc) + + Calls a callable object with the number of arguments specified by ``argc``, + including one or more named arguments. On the stack are (in ascending order): + + * The callable + * ``self`` or ``NULL`` + * The remaining positional arguments + * The named arguments + * A :class:`tuple` of keyword argument names + + ``argc`` is the total of the positional and named arguments, excluding ``self``. + The length of the tuple of keyword argument names is the number of named arguments. + + ``CALL_KW`` pops all arguments, the keyword names, and the callable object + off the stack, calls the callable object with those arguments, and pushes the + return value returned by the callable object. + + .. versionadded:: 3.13 + .. opcode:: CALL_FUNCTION_EX (flags) @@ -1428,15 +1542,6 @@ iterations of the loop. .. versionadded:: 3.11 -.. opcode:: KW_NAMES (consti) - - Prefixes :opcode:`CALL`. - Stores a reference to ``co_consts[consti]`` into an internal variable - for use by :opcode:`CALL`. ``co_consts[consti]`` must be a tuple of strings. - - .. versionadded:: 3.11 - - .. opcode:: MAKE_FUNCTION Pushes a new function object on the stack built from the code object at ``STACK[1]``. @@ -1556,11 +1661,12 @@ iterations of the loop. success (``True``) or failure (``False``). -.. opcode:: RESUME (where) +.. opcode:: RESUME (context) A no-op. Performs internal tracing, debugging and optimization checks. - The ``where`` operand marks where the ``RESUME`` occurs: + The ``context`` oparand consists of two parts. The lowest two bits + indicate where the ``RESUME`` occurs: * ``0`` The start of a function, which is neither a generator, coroutine nor an async generator @@ -1568,8 +1674,14 @@ iterations of the loop. * ``2`` After a ``yield from`` expression * ``3`` After an ``await`` expression + The next bit is ``1`` if the RESUME is at except-depth ``1``, and ``0`` + otherwise. + .. versionadded:: 3.11 + .. versionchanged:: 3.13 + The oparg value changed to include information about except-depth + .. opcode:: RETURN_GENERATOR @@ -1585,9 +1697,9 @@ iterations of the loop. Equivalent to ``STACK[-1] = STACK[-2].send(STACK[-1])``. 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*. + If the call raises :exc:`StopIteration`, pop the top value from the stack, + push the exception's ``value`` attribute, and increment the bytecode counter + by *delta*. .. versionadded:: 3.11 @@ -1598,8 +1710,8 @@ iterations of the loop. opcodes in the range [0,255] which don't use their argument and those that do (``< HAVE_ARGUMENT`` and ``>= HAVE_ARGUMENT``, respectively). - If your application uses pseudo instructions, use the :data:`hasarg` - collection instead. + If your application uses pseudo instructions or specialized instructions, + use the :data:`hasarg` collection instead. .. versionchanged:: 3.6 Now every instruction has an argument, but opcodes ``< HAVE_ARGUMENT`` @@ -1610,12 +1722,14 @@ iterations of the loop. it is not true that comparison with ``HAVE_ARGUMENT`` indicates whether they use their arg. + .. deprecated:: 3.13 + Use :data:`hasarg` instead. .. opcode:: CALL_INTRINSIC_1 Calls an intrinsic function with one argument. Passes ``STACK[-1]`` as the argument and sets ``STACK[-1]`` to the result. Used to implement - functionality that is necessary but not performance critical. + functionality that is not performance critical. The operand determines which intrinsic function is called: @@ -1663,9 +1777,13 @@ iterations of the loop. .. opcode:: CALL_INTRINSIC_2 - Calls an intrinsic function with two arguments. Passes ``STACK[-2]``, ``STACK[-1]`` as the - arguments and sets ``STACK[-1]`` to the result. Used to implement functionality that is - necessary but not performance critical. + Calls an intrinsic function with two arguments. Used to implement functionality + that is not performance critical:: + + arg2 = STACK.pop() + arg1 = STACK.pop() + result = intrinsic2(arg1, arg2) + STACK.push(result) The operand determines which intrinsic function is called: @@ -1761,8 +1879,9 @@ These collections are provided for automatic introspection of bytecode instructions: .. versionchanged:: 3.12 - The collections now contain pseudo instructions as well. These are - opcodes with values ``>= MIN_PSEUDO_OPCODE``. + The collections now contain pseudo instructions and instrumented + instructions as well. These are opcodes with values ``>= MIN_PSEUDO_OPCODE`` + and ``>= MIN_INSTRUMENTED_OPCODE``. .. data:: opname diff --git a/Doc/library/doctest.rst b/Doc/library/doctest.rst index 92da6133f9bf09..e4bb6f5ec958c6 100644 --- a/Doc/library/doctest.rst +++ b/Doc/library/doctest.rst @@ -143,13 +143,13 @@ Simple Usage: Checking Examples in Docstrings --------------------------------------------- The simplest way to start using doctest (but not necessarily the way you'll -continue to do it) is to end each module :mod:`M` with:: +continue to do it) is to end each module :mod:`!M` with:: if __name__ == "__main__": import doctest doctest.testmod() -:mod:`doctest` then examines docstrings in module :mod:`M`. +:mod:`!doctest` then examines docstrings in module :mod:`!M`. Running the module as a script causes the examples in the docstrings to get executed and verified:: @@ -277,13 +277,34 @@ Which Docstrings Are Examined? The module docstring, and all function, class and method docstrings are searched. Objects imported into the module are not searched. -In addition, if ``M.__test__`` exists and "is true", it must be a dict, and each +In addition, there are cases when you want tests to be part of a module but not part +of the help text, which requires that the tests not be included in the docstring. +Doctest looks for a module-level variable called ``__test__`` and uses it to locate other +tests. If ``M.__test__`` exists, it must be a dict, and each entry maps a (string) name to a function object, class object, or string. Function and class object docstrings found from ``M.__test__`` are searched, and strings are treated as if they were docstrings. In output, a key ``K`` in -``M.__test__`` appears with name :: +``M.__test__`` appears with name ``M.__test__.K``. - .__test__.K +For example, place this block of code at the top of :file:`example.py`: + +.. code-block:: python + + __test__ = { + 'numbers': """ + >>> factorial(6) + 720 + + >>> [factorial(n) for n in range(6)] + [1, 1, 2, 6, 24, 120] + """ + } + +The value of ``example.__test__["numbers"]`` will be treated as a +docstring and all the tests inside it will be run. It is +important to note that the value can be mapped to a function, +class object, or module; if so, :mod:`!doctest` +searches them recursively for docstrings, which are then scanned for tests. Any classes found are recursively searched similarly, to test docstrings in their contained methods and nested classes. @@ -382,10 +403,10 @@ What's the Execution Context? ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ By default, each time :mod:`doctest` finds a docstring to test, it uses a -*shallow copy* of :mod:`M`'s globals, so that running tests doesn't change the -module's real globals, and so that one test in :mod:`M` can't leave behind +*shallow copy* of :mod:`!M`'s globals, so that running tests doesn't change the +module's real globals, and so that one test in :mod:`!M` can't leave behind crumbs that accidentally allow another test to work. This means examples can -freely use any names defined at top-level in :mod:`M`, and names defined earlier +freely use any names defined at top-level in :mod:`!M`, and names defined earlier in the docstring being run. Examples cannot see names defined in other docstrings. @@ -923,8 +944,8 @@ and :ref:`doctest-simple-testfile`. (or module :mod:`__main__` if *m* is not supplied or is ``None``), starting with ``m.__doc__``. - Also test examples reachable from dict ``m.__test__``, if it exists and is not - ``None``. ``m.__test__`` maps names (strings) to functions, classes and + Also test examples reachable from dict ``m.__test__``, if it exists. + ``m.__test__`` maps names (strings) to functions, classes and strings; function and class docstrings are searched for examples; strings are searched directly, as if they were docstrings. @@ -937,7 +958,8 @@ and :ref:`doctest-simple-testfile`. Optional argument *exclude_empty* defaults to false. If true, objects for which no doctests are found are excluded from consideration. The default is a backward - compatibility hack, so that code still using :meth:`doctest.master.summarize` in + compatibility hack, so that code still using + :meth:`doctest.master.summarize ` in conjunction with :func:`testmod` continues to get output for objects with no tests. The *exclude_empty* argument to the newer :class:`DocTestFinder` constructor defaults to true. @@ -976,7 +998,7 @@ As your collection of doctest'ed modules grows, you'll want a way to run all their doctests systematically. :mod:`doctest` provides two functions that can be used to create :mod:`unittest` test suites from modules and text files containing doctests. To integrate with :mod:`unittest` test discovery, include -a :func:`load_tests` function in your test module:: +a :ref:`load_tests ` function in your test module:: import unittest import doctest @@ -1090,19 +1112,24 @@ from text files and modules with doctests: :func:`DocTestSuite` returns an empty :class:`unittest.TestSuite` if *module* contains no docstrings instead of raising :exc:`ValueError`. +.. exception:: failureException + + When doctests which have been converted to unit tests by :func:`DocFileSuite` + or :func:`DocTestSuite` fail, this exception is raised showing the name of + the file containing the test and a (sometimes approximate) line number. Under the covers, :func:`DocTestSuite` creates a :class:`unittest.TestSuite` out -of :class:`doctest.DocTestCase` instances, and :class:`DocTestCase` is a -subclass of :class:`unittest.TestCase`. :class:`DocTestCase` isn't documented +of :class:`!doctest.DocTestCase` instances, and :class:`!DocTestCase` is a +subclass of :class:`unittest.TestCase`. :class:`!DocTestCase` isn't documented here (it's an internal detail), but studying its code can answer questions about the exact details of :mod:`unittest` integration. Similarly, :func:`DocFileSuite` creates a :class:`unittest.TestSuite` out of -:class:`doctest.DocFileCase` instances, and :class:`DocFileCase` is a subclass -of :class:`DocTestCase`. +:class:`!doctest.DocFileCase` instances, and :class:`!DocFileCase` is a subclass +of :class:`!DocTestCase`. So both ways of creating a :class:`unittest.TestSuite` run instances of -:class:`DocTestCase`. This is important for a subtle reason: when you run +:class:`!DocTestCase`. This is important for a subtle reason: when you run :mod:`doctest` functions yourself, you can control the :mod:`doctest` options in use directly, by passing option flags to :mod:`doctest` functions. However, if you're writing a :mod:`unittest` framework, :mod:`unittest` ultimately controls @@ -1123,14 +1150,14 @@ reporting flags specific to :mod:`unittest` support, via this function: section :ref:`doctest-options`. Only "reporting flags" can be used. This is a module-global setting, and affects all future doctests run by module - :mod:`unittest`: the :meth:`runTest` method of :class:`DocTestCase` looks at - the option flags specified for the test case when the :class:`DocTestCase` + :mod:`unittest`: the :meth:`!runTest` method of :class:`!DocTestCase` looks at + the option flags specified for the test case when the :class:`!DocTestCase` instance was constructed. If no reporting flags were specified (which is the - typical and expected case), :mod:`doctest`'s :mod:`unittest` reporting flags are + typical and expected case), :mod:`!doctest`'s :mod:`unittest` reporting flags are :ref:`bitwise ORed ` into the option flags, and the option flags so augmented are passed to the :class:`DocTestRunner` instance created to run the doctest. If any reporting flags were specified when the - :class:`DocTestCase` instance was constructed, :mod:`doctest`'s + :class:`!DocTestCase` instance was constructed, :mod:`!doctest`'s :mod:`unittest` reporting flags are ignored. The value of the :mod:`unittest` reporting flags in effect before the function @@ -1300,7 +1327,8 @@ Example Objects A dictionary mapping from option flags to ``True`` or ``False``, which is used to override default options for this example. Any option flags not contained in this dictionary are left at their default value (as specified by the - :class:`DocTestRunner`'s :attr:`optionflags`). By default, no options are set. + :class:`DocTestRunner`'s :ref:`optionflags `). + By default, no options are set. .. _doctest-doctestfinder: @@ -1409,6 +1437,27 @@ DocTestParser objects identifying this string, and is only used for error messages. +TestResults objects +^^^^^^^^^^^^^^^^^^^ + + +.. class:: TestResults(failed, attempted) + + .. attribute:: failed + + Number of failed tests. + + .. attribute:: attempted + + Number of attempted tests. + + .. attribute:: skipped + + Number of skipped tests. + + .. versionadded:: 3.13 + + .. _doctest-doctestrunner: DocTestRunner objects @@ -1427,7 +1476,7 @@ DocTestRunner objects passing a subclass of :class:`OutputChecker` to the constructor. The test runner's display output can be controlled in two ways. First, an output - function can be passed to :meth:`TestRunner.run`; this function will be called + function can be passed to :meth:`run`; this function will be called with strings that should be displayed. It defaults to ``sys.stdout.write``. If capturing the output is not sufficient, then the display output can be also customized by subclassing DocTestRunner, and overriding the methods @@ -1448,8 +1497,12 @@ DocTestRunner objects runner compares expected output to actual output, and how it displays failures. For more information, see section :ref:`doctest-options`. + The test runner accumulates statistics. The aggregated number of attempted, + failed and skipped examples is also available via the :attr:`tries`, + :attr:`failures` and :attr:`skips` attributes. The :meth:`run` and + :meth:`summarize` methods return a :class:`TestResults` instance. - :class:`DocTestParser` defines the following methods: + :class:`DocTestRunner` defines the following methods: .. method:: report_start(out, test, example) @@ -1500,7 +1553,8 @@ DocTestRunner objects .. method:: run(test, compileflags=None, out=None, clear_globs=True) Run the examples in *test* (a :class:`DocTest` object), and display the - results using the writer function *out*. + results using the writer function *out*. Return a :class:`TestResults` + instance. The examples are run in the namespace ``test.globs``. If *clear_globs* is true (the default), then this namespace will be cleared after the test runs, @@ -1513,18 +1567,35 @@ DocTestRunner objects The output of each example is checked using the :class:`DocTestRunner`'s output checker, and the results are formatted by the - :meth:`DocTestRunner.report_\*` methods. + :meth:`!DocTestRunner.report_\*` methods. .. method:: summarize(verbose=None) Print a summary of all the test cases that have been run by this DocTestRunner, - and return a :term:`named tuple` ``TestResults(failed, attempted)``. + and return a :class:`TestResults` instance. The optional *verbose* argument controls how detailed the summary is. If the verbosity is not specified, then the :class:`DocTestRunner`'s verbosity is used. + :class:`DocTestParser` has the following attributes: + + .. attribute:: tries + + Number of attempted examples. + + .. attribute:: failures + + Number of failed examples. + + .. attribute:: skips + + Number of skipped examples. + + .. versionadded:: 3.13 + + .. _doctest-outputchecker: OutputChecker objects @@ -1671,12 +1742,12 @@ code under the debugger: module) of the object with the doctests of interest. The result is a string, containing the object's docstring converted to a Python script, as described for :func:`script_from_examples` above. For example, if module :file:`a.py` - contains a top-level function :func:`f`, then :: + contains a top-level function :func:`!f`, then :: import a, doctest print(doctest.testsource(a, "a.f")) - prints a script version of function :func:`f`'s docstring, with doctests + prints a script version of function :func:`!f`'s docstring, with doctests converted to code, and the rest placed in comments. diff --git a/Doc/library/email.compat32-message.rst b/Doc/library/email.compat32-message.rst index 5bef155a4af310..c4c322a82e1f44 100644 --- a/Doc/library/email.compat32-message.rst +++ b/Doc/library/email.compat32-message.rst @@ -367,7 +367,7 @@ Here are the methods of the :class:`Message` class: .. method:: get(name, failobj=None) Return the value of the named header field. This is identical to - :meth:`__getitem__` except that optional *failobj* is returned if the + :meth:`~object.__getitem__` except that optional *failobj* is returned if the named header is missing (defaults to ``None``). Here are some additional useful methods: diff --git a/Doc/library/email.contentmanager.rst b/Doc/library/email.contentmanager.rst index 918fc55677e723..5b49339650f0e9 100644 --- a/Doc/library/email.contentmanager.rst +++ b/Doc/library/email.contentmanager.rst @@ -32,9 +32,9 @@ To find the handler, look for the following keys in the registry, stopping with the first one found: - * the string representing the full MIME type (``maintype/subtype``) - * the string representing the ``maintype`` - * the empty string + * the string representing the full MIME type (``maintype/subtype``) + * the string representing the ``maintype`` + * the empty string If none of these keys produce a handler, raise a :exc:`KeyError` for the full MIME type. @@ -55,11 +55,11 @@ look for the following keys in the registry, stopping with the first one found: - * the type itself (``typ``) - * the type's fully qualified name (``typ.__module__ + '.' + - typ.__qualname__``). - * the type's qualname (``typ.__qualname__``) - * the type's name (``typ.__name__``). + * the type itself (``typ``) + * the type's fully qualified name (``typ.__module__ + '.' + + typ.__qualname__``). + * the type's qualname (``typ.__qualname__``) + * the type's name (``typ.__name__``). If none of the above match, repeat all of the checks above for each of the types in the :term:`MRO` (``typ.__mro__``). Finally, if no other key @@ -132,15 +132,15 @@ Currently the email package provides only one concrete content manager, Add a :mailheader:`Content-Type` header with a ``maintype/subtype`` value. - * For ``str``, set the MIME ``maintype`` to ``text``, and set the - subtype to *subtype* if it is specified, or ``plain`` if it is not. - * For ``bytes``, use the specified *maintype* and *subtype*, or - raise a :exc:`TypeError` if they are not specified. - * For :class:`~email.message.EmailMessage` objects, set the maintype - to ``message``, and set the subtype to *subtype* if it is - specified or ``rfc822`` if it is not. If *subtype* is - ``partial``, raise an error (``bytes`` objects must be used to - construct ``message/partial`` parts). + * For ``str``, set the MIME ``maintype`` to ``text``, and set the + subtype to *subtype* if it is specified, or ``plain`` if it is not. + * For ``bytes``, use the specified *maintype* and *subtype*, or + raise a :exc:`TypeError` if they are not specified. + * For :class:`~email.message.EmailMessage` objects, set the maintype + to ``message``, and set the subtype to *subtype* if it is + specified or ``rfc822`` if it is not. If *subtype* is + ``partial``, raise an error (``bytes`` objects must be used to + construct ``message/partial`` parts). If *charset* is provided (which is valid only for ``str``), encode the string to bytes using the specified character set. The default is @@ -155,14 +155,14 @@ Currently the email package provides only one concrete content manager, ``7bit`` for an input that contains non-ASCII values), raise a :exc:`ValueError`. - * For ``str`` objects, if *cte* is not set use heuristics to - determine the most compact encoding. - * For :class:`~email.message.EmailMessage`, per :rfc:`2046`, raise - an error if a *cte* of ``quoted-printable`` or ``base64`` is - requested for *subtype* ``rfc822``, and for any *cte* other than - ``7bit`` for *subtype* ``external-body``. For - ``message/rfc822``, use ``8bit`` if *cte* is not specified. For - all other values of *subtype*, use ``7bit``. + * For ``str`` objects, if *cte* is not set use heuristics to + determine the most compact encoding. + * For :class:`~email.message.EmailMessage`, per :rfc:`2046`, raise + an error if a *cte* of ``quoted-printable`` or ``base64`` is + requested for *subtype* ``rfc822``, and for any *cte* other than + ``7bit`` for *subtype* ``external-body``. For + ``message/rfc822``, use ``8bit`` if *cte* is not specified. For + all other values of *subtype*, use ``7bit``. .. note:: A *cte* of ``binary`` does not actually work correctly yet. The ``EmailMessage`` object as modified by ``set_content`` is diff --git a/Doc/library/email.errors.rst b/Doc/library/email.errors.rst index 194a98696f437d..56aea6598b8615 100644 --- a/Doc/library/email.errors.rst +++ b/Doc/library/email.errors.rst @@ -58,6 +58,15 @@ The following exception classes are defined in the :mod:`email.errors` module: :class:`~email.mime.nonmultipart.MIMENonMultipart` (e.g. :class:`~email.mime.image.MIMEImage`). +.. exception:: MessageDefect() + + This is the base class for all defects found when parsing email messages. + It is derived from :exc:`ValueError`. + +.. exception:: HeaderDefect() + + This is the base class for all defects found when parsing email headers. + It is derived from :exc:`MessageDefect`. Here is the list of the defects that the :class:`~email.parser.FeedParser` can find while parsing messages. Note that the defects are added to the message diff --git a/Doc/library/email.message.rst b/Doc/library/email.message.rst index 225f498781fa86..f58d93da6ed687 100644 --- a/Doc/library/email.message.rst +++ b/Doc/library/email.message.rst @@ -247,7 +247,7 @@ message objects. .. method:: get(name, failobj=None) Return the value of the named header field. This is identical to - :meth:`__getitem__` except that optional *failobj* is returned if the + :meth:`~object.__getitem__` except that optional *failobj* is returned if the named header is missing (*failobj* defaults to ``None``). diff --git a/Doc/library/email.policy.rst b/Doc/library/email.policy.rst index 2439dee676c9b0..fd47dd0dc5df36 100644 --- a/Doc/library/email.policy.rst +++ b/Doc/library/email.policy.rst @@ -557,17 +557,17 @@ more closely to the RFCs relevant to their domains. With all of these :class:`EmailPolicies <.EmailPolicy>`, the effective API of the email package is changed from the Python 3.2 API in the following ways: - * Setting a header on a :class:`~email.message.Message` results in that - header being parsed and a header object created. +* Setting a header on a :class:`~email.message.Message` results in that + header being parsed and a header object created. - * Fetching a header value from a :class:`~email.message.Message` results - in that header being parsed and a header object created and - returned. +* Fetching a header value from a :class:`~email.message.Message` results + in that header being parsed and a header object created and + returned. - * Any header object, or any header that is refolded due to the - policy settings, is folded using an algorithm that fully implements the - RFC folding algorithms, including knowing where encoded words are required - and allowed. +* Any header object, or any header that is refolded due to the + policy settings, is folded using an algorithm that fully implements the + RFC folding algorithms, including knowing where encoded words are required + and allowed. From the application view, this means that any header obtained through the :class:`~email.message.EmailMessage` is a header object with extra diff --git a/Doc/library/email.utils.rst b/Doc/library/email.utils.rst index 345b64001c1ace..d693a9bc3933b5 100644 --- a/Doc/library/email.utils.rst +++ b/Doc/library/email.utils.rst @@ -58,13 +58,18 @@ of the new API. begins with angle brackets, they are stripped off. -.. function:: parseaddr(address) +.. function:: parseaddr(address, *, strict=True) Parse address -- which should be the value of some address-containing field such as :mailheader:`To` or :mailheader:`Cc` -- into its constituent *realname* and *email address* parts. Returns a tuple of that information, unless the parse fails, in which case a 2-tuple of ``('', '')`` is returned. + If *strict* is true, use a strict parser which rejects malformed inputs. + + .. versionchanged:: 3.13 + Add *strict* optional parameter and reject malformed inputs by default. + .. function:: formataddr(pair, charset='utf-8') @@ -82,12 +87,15 @@ of the new API. Added the *charset* option. -.. function:: getaddresses(fieldvalues) +.. function:: getaddresses(fieldvalues, *, strict=True) This method returns a list of 2-tuples of the form returned by ``parseaddr()``. *fieldvalues* is a sequence of header field values as might be returned by - :meth:`Message.get_all `. Here's a simple - example that gets all the recipients of a message:: + :meth:`Message.get_all `. + + If *strict* is true, use a strict parser which rejects malformed inputs. + + Here's a simple example that gets all the recipients of a message:: from email.utils import getaddresses @@ -97,6 +105,9 @@ of the new API. resent_ccs = msg.get_all('resent-cc', []) all_recipients = getaddresses(tos + ccs + resent_tos + resent_ccs) + .. versionchanged:: 3.13 + Add *strict* optional parameter and reject malformed inputs by default. + .. function:: parsedate(date) diff --git a/Doc/library/ensurepip.rst b/Doc/library/ensurepip.rst index d7f89cf96368b5..de3b93f5e61073 100644 --- a/Doc/library/ensurepip.rst +++ b/Doc/library/ensurepip.rst @@ -61,7 +61,7 @@ By default, ``pip`` is installed into the current virtual environment active virtual environment). The installation location can be controlled through two additional command line options: -* ``--root ``: Installs ``pip`` relative to the given root directory +* :samp:`--root {dir}`: Installs ``pip`` relative to the given root directory rather than the root of the currently active virtual environment (if any) or the default root for the current Python installation. * ``--user``: Installs ``pip`` into the user site packages directory rather diff --git a/Doc/library/enum.rst b/Doc/library/enum.rst index e9c4f0e2c5f59b..20222bfb3611ab 100644 --- a/Doc/library/enum.rst +++ b/Doc/library/enum.rst @@ -165,7 +165,7 @@ Data Types to subclass *EnumType* -- see :ref:`Subclassing EnumType ` for details. - *EnumType* is responsible for setting the correct :meth:`!__repr__`, + ``EnumType`` is responsible for setting the correct :meth:`!__repr__`, :meth:`!__str__`, :meth:`!__format__`, and :meth:`!__reduce__` methods on the final *enum*, as well as creating the enum members, properly handling duplicates, providing iteration over the enum class, etc. @@ -198,11 +198,12 @@ Data Types >>> some_var = Color.RED >>> some_var in Color True + >>> Color.RED.value in Color + True - .. note:: + .. versionchanged:: 3.12 - In Python 3.12 it will be possible to check for member values and not - just members; until then, a ``TypeError`` will be raised if a + Before Python 3.12, a ``TypeError`` is raised if a non-Enum-member is used in a containment check. .. method:: EnumType.__dir__(cls) @@ -234,6 +235,10 @@ Data Types >>> len(Color) 3 + .. attribute:: EnumType.__members__ + + Returns a mapping of every enum name to its member, including aliases + .. method:: EnumType.__reversed__(cls) Returns each member in *cls* in reverse definition order:: @@ -241,6 +246,20 @@ Data Types >>> list(reversed(Color)) [, , ] + .. method:: EnumType._add_alias_ + + Adds a new name as an alias to an existing member. Raises a + :exc:`NameError` if the name is already assigned to a different member. + + .. method:: EnumType._add_value_alias_ + + Adds a new value as an alias to an existing member. Raises a + :exc:`ValueError` if the value is already linked with a different member. + + .. versionadded:: 3.11 + + Before 3.11 ``EnumType`` was called ``EnumMeta``, which is still available as an alias. + .. class:: Enum @@ -401,7 +420,7 @@ Data Types .. class:: IntEnum - *IntEnum* is the same as *Enum*, but its members are also integers and can be + *IntEnum* is the same as :class:`Enum`, but its members are also integers and can be used anywhere that an integer can be used. If any integer operation is performed with an *IntEnum* member, the resulting value loses its enumeration status. @@ -432,7 +451,7 @@ Data Types .. class:: StrEnum - *StrEnum* is the same as *Enum*, but its members are also strings and can be used + ``StrEnum`` is the same as :class:`Enum`, but its members are also strings and can be used in most of the same places that a string can be used. The result of any string operation performed on or with a *StrEnum* member is not part of the enumeration. @@ -544,7 +563,7 @@ Data Types .. method:: __invert__(self): - Returns all the flags in *type(self)* that are not in self:: + Returns all the flags in *type(self)* that are not in *self*:: >>> ~white @@ -571,7 +590,7 @@ Data Types .. class:: IntFlag - *IntFlag* is the same as *Flag*, but its members are also integers and can be + ``IntFlag`` is the same as :class:`Flag`, but its members are also integers and can be used anywhere that an integer can be used. >>> from enum import IntFlag, auto @@ -591,12 +610,12 @@ Data Types >>> Color.RED + 2 3 - If a *Flag* operation is performed with an *IntFlag* member and: + If a :class:`Flag` operation is performed with an *IntFlag* member and: - * the result is a valid *IntFlag*: an *IntFlag* is returned - * the result is not a valid *IntFlag*: the result depends on the *FlagBoundary* setting + * the result is a valid *IntFlag*: an *IntFlag* is returned + * the result is not a valid *IntFlag*: the result depends on the :class:`FlagBoundary` setting - The *repr()* of unnamed zero-valued flags has changed. It is now: + The :func:`repr()` of unnamed zero-valued flags has changed. It is now: >>> Color(0) @@ -621,8 +640,8 @@ Data Types :class:`!ReprEnum` uses the :meth:`repr() ` of :class:`Enum`, but the :class:`str() ` of the mixed-in data type: - * :meth:`!int.__str__` for :class:`IntEnum` and :class:`IntFlag` - * :meth:`!str.__str__` for :class:`StrEnum` + * :meth:`!int.__str__` for :class:`IntEnum` and :class:`IntFlag` + * :meth:`!str.__str__` for :class:`StrEnum` Inherit from :class:`!ReprEnum` to keep the :class:`str() ` / :func:`format` of the mixed-in data type instead of using the @@ -692,7 +711,7 @@ Data Types .. class:: FlagBoundary - *FlagBoundary* controls how out-of-range values are handled in *Flag* and its + ``FlagBoundary`` controls how out-of-range values are handled in :class:`Flag` and its subclasses. .. attribute:: STRICT @@ -715,7 +734,7 @@ Data Types .. attribute:: CONFORM - Out-of-range values have invalid values removed, leaving a valid *Flag* + Out-of-range values have invalid values removed, leaving a valid :class:`Flag` value:: >>> from enum import Flag, CONFORM, auto @@ -729,7 +748,7 @@ Data Types .. attribute:: EJECT - Out-of-range values lose their *Flag* membership and revert to :class:`int`. + Out-of-range values lose their :class:`Flag` membership and revert to :class:`int`. >>> from enum import Flag, EJECT, auto >>> class EjectFlag(Flag, boundary=EJECT): @@ -742,7 +761,7 @@ Data Types .. attribute:: KEEP - Out-of-range values are kept, and the *Flag* membership is kept. + Out-of-range values are kept, and the :class:`Flag` membership is kept. This is the default for :class:`IntFlag`:: >>> from enum import Flag, KEEP, auto @@ -764,37 +783,41 @@ Supported ``__dunder__`` names :attr:`~EnumType.__members__` is a read-only ordered mapping of ``member_name``:``member`` items. It is only available on the class. -:meth:`~object.__new__`, if specified, must create and return the enum members; it is -also a very good idea to set the member's :attr:`!_value_` appropriately. Once -all the members are created it is no longer used. +:meth:`~object.__new__`, if specified, must create and return the enum members; +it is also a very good idea to set the member's :attr:`!_value_` appropriately. +Once all the members are created it is no longer used. Supported ``_sunder_`` names """""""""""""""""""""""""""" -- ``_name_`` -- name of the member -- ``_value_`` -- value of the member; can be set / modified in ``__new__`` - -- ``_missing_`` -- a lookup function used when a value is not found; may be - overridden -- ``_ignore_`` -- a list of names, either as a :class:`list` or a :class:`str`, - that will not be transformed into members, and will be removed from the final - class -- ``_order_`` -- used in Python 2/3 code to ensure member order is consistent - (class attribute, removed during class creation) -- ``_generate_next_value_`` -- used to get an appropriate value for an enum - member; may be overridden - - .. note:: - - For standard :class:`Enum` classes the next value chosen is the last value seen - incremented by one. - - For :class:`Flag` classes the next value chosen will be the next highest - power-of-two, regardless of the last value seen. +- :meth:`~EnumType._add_alias_` -- adds a new name as an alias to an existing + member. +- :meth:`~EnumType._add_value_alias_` -- adds a new value as an alias to an + existing member. +- :attr:`~Enum._name_` -- name of the member +- :attr:`~Enum._value_` -- value of the member; can be set in ``__new__`` +- :meth:`~Enum._missing_` -- a lookup function used when a value is not found; + may be overridden +- :attr:`~Enum._ignore_` -- a list of names, either as a :class:`list` or a + :class:`str`, that will not be transformed into members, and will be removed + from the final class +- :attr:`~Enum._order_` -- used in Python 2/3 code to ensure member order is + consistent (class attribute, removed during class creation) +- :meth:`~Enum._generate_next_value_` -- used to get an appropriate value for + an enum member; may be overridden + + .. note:: + + For standard :class:`Enum` classes the next value chosen is the highest + value seen incremented by one. + + For :class:`Flag` classes the next value chosen will be the next highest + power-of-two. .. versionadded:: 3.6 ``_missing_``, ``_order_``, ``_generate_next_value_`` .. versionadded:: 3.7 ``_ignore_`` +.. versionadded:: 3.13 ``_add_alias_``, ``_add_value_alias_`` --------------- @@ -804,20 +827,20 @@ Utilities and Decorators .. class:: auto *auto* can be used in place of a value. If used, the *Enum* machinery will - call an *Enum*'s :meth:`~Enum._generate_next_value_` to get an appropriate value. - For *Enum* and *IntEnum* that appropriate value will be the last value plus - one; for *Flag* and *IntFlag* it will be the first power-of-two greater - than the highest value; for *StrEnum* it will be the lower-cased version of + call an :class:`Enum`'s :meth:`~Enum._generate_next_value_` to get an appropriate value. + For :class:`Enum` and :class:`IntEnum` that appropriate value will be the last value plus + one; for :class:`Flag` and :class:`IntFlag` it will be the first power-of-two greater + than the highest value; for :class:`StrEnum` it will be the lower-cased version of the member's name. Care must be taken if mixing *auto()* with manually specified values. *auto* instances are only resolved when at the top level of an assignment: - * ``FIRST = auto()`` will work (auto() is replaced with ``1``); - * ``SECOND = auto(), -2`` will work (auto is replaced with ``2``, so ``2, -2`` is - used to create the ``SECOND`` enum member; - * ``THREE = [auto(), -3]`` will *not* work (``, -3`` is used to - create the ``THREE`` enum member) + * ``FIRST = auto()`` will work (auto() is replaced with ``1``); + * ``SECOND = auto(), -2`` will work (auto is replaced with ``2``, so ``2, -2`` is + used to create the ``SECOND`` enum member; + * ``THREE = [auto(), -3]`` will *not* work (``, -3`` is used to + create the ``THREE`` enum member) .. versionchanged:: 3.11.1 diff --git a/Doc/library/errno.rst b/Doc/library/errno.rst index 5122c69697ef91..283e8b013265d9 100644 --- a/Doc/library/errno.rst +++ b/Doc/library/errno.rst @@ -511,6 +511,13 @@ defined by the module. The specific list of defined symbols is available as Operation not supported on transport endpoint +.. data:: ENOTSUP + + Operation not supported + + .. versionadded:: 3.2 + + .. data:: EPFNOSUPPORT Protocol family not supported @@ -666,3 +673,24 @@ defined by the module. The specific list of defined symbols is available as .. availability:: WASI, FreeBSD .. versionadded:: 3.11.1 + + +.. data:: ECANCELED + + Operation canceled + + .. versionadded:: 3.2 + + +.. data:: EOWNERDEAD + + Owner died + + .. versionadded:: 3.2 + + +.. data:: ENOTRECOVERABLE + + State not recoverable + + .. versionadded:: 3.2 diff --git a/Doc/library/exceptions.rst b/Doc/library/exceptions.rst index fae0cf621323c8..f821776c286133 100644 --- a/Doc/library/exceptions.rst +++ b/Doc/library/exceptions.rst @@ -38,36 +38,48 @@ information on defining exceptions is available in the Python Tutorial under Exception context ----------------- -When raising a new exception while another exception -is already being handled, the new exception's -:attr:`__context__` attribute is automatically set to the handled -exception. An exception may be handled when an :keyword:`except` or -:keyword:`finally` clause, or a :keyword:`with` statement, is used. - -This implicit exception context can be -supplemented with an explicit cause by using :keyword:`!from` with -:keyword:`raise`:: - - raise new_exc from original_exc - -The expression following :keyword:`from` must be an exception or ``None``. It -will be set as :attr:`__cause__` on the raised exception. Setting -:attr:`__cause__` also implicitly sets the :attr:`__suppress_context__` -attribute to ``True``, so that using ``raise new_exc from None`` -effectively replaces the old exception with the new one for display -purposes (e.g. converting :exc:`KeyError` to :exc:`AttributeError`), while -leaving the old exception available in :attr:`__context__` for introspection -when debugging. - -The default traceback display code shows these chained exceptions in -addition to the traceback for the exception itself. An explicitly chained -exception in :attr:`__cause__` is always shown when present. An implicitly -chained exception in :attr:`__context__` is shown only if :attr:`__cause__` -is :const:`None` and :attr:`__suppress_context__` is false. - -In either case, the exception itself is always shown after any chained -exceptions so that the final line of the traceback always shows the last -exception that was raised. +.. index:: pair: exception; chaining + __cause__ (exception attribute) + __context__ (exception attribute) + __suppress_context__ (exception attribute) + +Three attributes on exception objects provide information about the context in +which the exception was raised: + +.. attribute:: BaseException.__context__ + BaseException.__cause__ + BaseException.__suppress_context__ + + When raising a new exception while another exception + is already being handled, the new exception's + :attr:`!__context__` attribute is automatically set to the handled + exception. An exception may be handled when an :keyword:`except` or + :keyword:`finally` clause, or a :keyword:`with` statement, is used. + + This implicit exception context can be + supplemented with an explicit cause by using :keyword:`!from` with + :keyword:`raise`:: + + raise new_exc from original_exc + + The expression following :keyword:`from` must be an exception or ``None``. It + will be set as :attr:`!__cause__` on the raised exception. Setting + :attr:`!__cause__` also implicitly sets the :attr:`!__suppress_context__` + attribute to ``True``, so that using ``raise new_exc from None`` + effectively replaces the old exception with the new one for display + purposes (e.g. converting :exc:`KeyError` to :exc:`AttributeError`), while + leaving the old exception available in :attr:`!__context__` for introspection + when debugging. + + The default traceback display code shows these chained exceptions in + addition to the traceback for the exception itself. An explicitly chained + exception in :attr:`!__cause__` is always shown when present. An implicitly + chained exception in :attr:`!__context__` is shown only if :attr:`!__cause__` + is :const:`None` and :attr:`!__suppress_context__` is false. + + In either case, the exception itself is always shown after any chained + exceptions so that the final line of the traceback always shows the last + exception that was raised. Inheriting from built-in exceptions @@ -126,6 +138,12 @@ The following exceptions are used mostly as base classes for other exceptions. tb = sys.exception().__traceback__ raise OtherException(...).with_traceback(tb) + .. attribute:: __traceback__ + + A writable field that holds the + :ref:`traceback object ` associated with this + exception. See also: :ref:`raise`. + .. method:: add_note(note) Add the string ``note`` to the exception's notes which appear in the standard @@ -220,10 +238,16 @@ The following exceptions are the exceptions that are usually raised. load a module. Also raised when the "from list" in ``from ... import`` has a name that cannot be found. - The :attr:`name` and :attr:`path` attributes can be set using keyword-only - arguments to the constructor. When set they represent the name of the module - that was attempted to be imported and the path to any file which triggered - the exception, respectively. + The optional *name* and *path* keyword-only arguments + set the corresponding attributes: + + .. attribute:: name + + The name of the module that was attempted to be imported. + + .. attribute:: path + + The path to any file which triggered the exception. .. versionchanged:: 3.3 Added the :attr:`name` and :attr:`path` attributes. @@ -423,9 +447,11 @@ The following exceptions are the exceptions that are usually raised. :meth:`~iterator.__next__` method to signal that there are no further items produced by the iterator. - The exception object has a single attribute :attr:`value`, which is - given as an argument when constructing the exception, and defaults - to :const:`None`. + .. attribute:: StopIteration.value + + The exception object has a single attribute :attr:`!value`, which is + given as an argument when constructing the exception, and defaults + to :const:`None`. When a :term:`generator` or :term:`coroutine` function returns, a new :exc:`StopIteration` instance is @@ -921,8 +947,10 @@ their subgroups based on the types of the contained exceptions. true for the exceptions that should be in the subgroup. The nesting structure of the current exception is preserved in the result, - as are the values of its :attr:`message`, :attr:`__traceback__`, - :attr:`__cause__`, :attr:`__context__` and :attr:`__notes__` fields. + as are the values of its :attr:`message`, + :attr:`~BaseException.__traceback__`, :attr:`~BaseException.__cause__`, + :attr:`~BaseException.__context__` and + :attr:`~BaseException.__notes__` fields. Empty nested groups are omitted from the result. The condition is checked for all exceptions in the nested exception group, @@ -948,10 +976,14 @@ their subgroups based on the types of the contained exceptions. and :meth:`split` return instances of the subclass rather than :exc:`ExceptionGroup`. - :meth:`subgroup` and :meth:`split` copy the :attr:`__traceback__`, - :attr:`__cause__`, :attr:`__context__` and :attr:`__notes__` fields from + :meth:`subgroup` and :meth:`split` copy the + :attr:`~BaseException.__traceback__`, + :attr:`~BaseException.__cause__`, :attr:`~BaseException.__context__` and + :attr:`~BaseException.__notes__` fields from the original exception group to the one returned by :meth:`derive`, so - these fields do not need to be updated by :meth:`derive`. :: + these fields do not need to be updated by :meth:`derive`. + + .. doctest:: >>> class MyGroup(ExceptionGroup): ... def derive(self, excs): @@ -977,9 +1009,9 @@ their subgroups based on the types of the contained exceptions. True - Note that :exc:`BaseExceptionGroup` defines :meth:`__new__`, so + Note that :exc:`BaseExceptionGroup` defines :meth:`~object.__new__`, so subclasses that need a different constructor signature need to - override that rather than :meth:`__init__`. For example, the following + override that rather than :meth:`~object.__init__`. For example, the following defines an exception group subclass which accepts an exit_code and and constructs the group's message from it. :: diff --git a/Doc/library/fcntl.rst b/Doc/library/fcntl.rst index 969a79fa873395..309ad652d4af34 100644 --- a/Doc/library/fcntl.rst +++ b/Doc/library/fcntl.rst @@ -18,7 +18,7 @@ interface to the :c:func:`fcntl` and :c:func:`ioctl` Unix routines. For a complete description of these calls, see :manpage:`fcntl(2)` and :manpage:`ioctl(2)` Unix manual pages. -.. include:: ../includes/wasm-notavail.rst +.. availability:: Unix, not Emscripten, not WASI. All functions in this module take a file descriptor *fd* as their first argument. This can be an integer file descriptor, such as returned by diff --git a/Doc/library/fractions.rst b/Doc/library/fractions.rst index 509c63686f5a7f..887c3844d20faa 100644 --- a/Doc/library/fractions.rst +++ b/Doc/library/fractions.rst @@ -106,6 +106,10 @@ another rational number, or from a string. presentation types ``"e"``, ``"E"``, ``"f"``, ``"F"``, ``"g"``, ``"G"`` and ``"%""``. + .. versionchanged:: 3.13 + Formatting of :class:`Fraction` instances without a presentation type + now supports fill, alignment, sign handling, minimum width and grouping. + .. attribute:: numerator Numerator of the Fraction in lowest term. @@ -201,17 +205,36 @@ another rational number, or from a string. .. method:: __format__(format_spec, /) - Provides support for float-style formatting of :class:`Fraction` - instances via the :meth:`str.format` method, the :func:`format` built-in - function, or :ref:`Formatted string literals `. The - presentation types ``"e"``, ``"E"``, ``"f"``, ``"F"``, ``"g"``, ``"G"`` - and ``"%"`` are supported. For these presentation types, formatting for a - :class:`Fraction` object ``x`` follows the rules outlined for - the :class:`float` type in the :ref:`formatspec` section. + Provides support for formatting of :class:`Fraction` instances via the + :meth:`str.format` method, the :func:`format` built-in function, or + :ref:`Formatted string literals `. + + If the ``format_spec`` format specification string does not end with one + of the presentation types ``'e'``, ``'E'``, ``'f'``, ``'F'``, ``'g'``, + ``'G'`` or ``'%'`` then formatting follows the general rules for fill, + alignment, sign handling, minimum width, and grouping as described in the + :ref:`format specification mini-language `. The "alternate + form" flag ``'#'`` is supported: if present, it forces the output string + to always include an explicit denominator, even when the value being + formatted is an exact integer. The zero-fill flag ``'0'`` is not + supported. + + If the ``format_spec`` format specification string ends with one of + the presentation types ``'e'``, ``'E'``, ``'f'``, ``'F'``, ``'g'``, + ``'G'`` or ``'%'`` then formatting follows the rules outlined for the + :class:`float` type in the :ref:`formatspec` section. Here are some examples:: >>> from fractions import Fraction + >>> format(Fraction(103993, 33102), '_') + '103_993/33_102' + >>> format(Fraction(1, 7), '.^+10') + '...+1/7...' + >>> format(Fraction(3, 1), '') + '3' + >>> format(Fraction(3, 1), '#') + '3/1' >>> format(Fraction(1, 7), '.40g') '0.1428571428571428571428571428571428571429' >>> format(Fraction('1234567.855'), '_.2f') diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst index b271067ae639c5..4682ec9c924757 100644 --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -57,7 +57,8 @@ are always available. They are listed here in alphabetical order. .. function:: abs(x) Return the absolute value of a number. The argument may be an - integer, a floating point number, or an object implementing :meth:`__abs__`. + integer, a floating point number, or an object implementing + :meth:`~object.__abs__`. If the argument is a complex number, its magnitude is returned. @@ -235,7 +236,7 @@ are always available. They are listed here in alphabetical order. :const:`False` if not. If this returns ``True``, it is still possible that a call fails, but if it is ``False``, calling *object* will never succeed. Note that classes are callable (calling a class returns a new instance); - instances are callable if their class has a :meth:`__call__` method. + instances are callable if their class has a :meth:`~object.__call__` method. .. versionadded:: 3.2 This function was first removed in Python 3.0 and then brought back @@ -285,7 +286,7 @@ are always available. They are listed here in alphabetical order. ``__name__``, ``__qualname__``, ``__doc__`` and ``__annotations__``) and have a new ``__wrapped__`` attribute. - .. versionchanged:: 3.11 + .. deprecated-removed:: 3.11 3.13 Class methods can no longer wrap other :term:`descriptors ` such as :func:`property`. @@ -432,15 +433,18 @@ are always available. They are listed here in alphabetical order. Without arguments, return the list of names in the current local scope. With an argument, attempt to return a list of valid attributes for that object. - If the object has a method named :meth:`__dir__`, this method will be called and + If the object has a method named :meth:`~object.__dir__`, + this method will be called and must return the list of attributes. This allows objects that implement a custom - :func:`__getattr__` or :func:`__getattribute__` function to customize the way + :func:`~object.__getattr__` or :func:`~object.__getattribute__` function + to customize the way :func:`dir` reports their attributes. - If the object does not provide :meth:`__dir__`, the function tries its best to - gather information from the object's :attr:`~object.__dict__` attribute, if defined, and + If the object does not provide :meth:`~object.__dir__`, + the function tries its best to gather information from the object's + :attr:`~object.__dict__` attribute, if defined, and from its type object. The resulting list is not necessarily complete and may - be inaccurate when the object has a custom :func:`__getattr__`. + be inaccurate when the object has a custom :func:`~object.__getattr__`. The default :func:`dir` mechanism behaves differently with different types of objects, as it attempts to produce the most relevant, rather than complete, @@ -664,7 +668,7 @@ are always available. They are listed here in alphabetical order. sign: "+" | "-" infinity: "Infinity" | "inf" nan: "nan" - digitpart: `digit` (["_"] `digit`)* + digitpart: `!digit` (["_"] `!digit`)* number: [`digitpart`] "." `digitpart` | `digitpart` ["."] exponent: ("e" | "E") ["+" | "-"] `digitpart` floatnumber: number [`exponent`] @@ -727,8 +731,8 @@ are always available. They are listed here in alphabetical order. A call to ``format(value, format_spec)`` is translated to ``type(value).__format__(value, format_spec)`` which bypasses the instance - dictionary when searching for the value's :meth:`__format__` method. A - :exc:`TypeError` exception is raised if the method search reaches + dictionary when searching for the value's :meth:`~object.__format__` method. + A :exc:`TypeError` exception is raised if the method search reaches :mod:`object` and the *format_spec* is non-empty, or if either the *format_spec* or the return value are not strings. @@ -792,9 +796,9 @@ are always available. They are listed here in alphabetical order. .. note:: - For objects with custom :meth:`__hash__` methods, note that :func:`hash` + For objects with custom :meth:`~object.__hash__` methods, + note that :func:`hash` truncates the return value based on the bit width of the host machine. - See :meth:`__hash__ ` for details. .. function:: help() help(request) @@ -982,8 +986,9 @@ are always available. They are listed here in alphabetical order. Return an :term:`iterator` object. The first argument is interpreted very differently depending on the presence of the second argument. Without a second argument, *object* must be a collection object which supports the - :term:`iterable` protocol (the :meth:`__iter__` method), or it must support - the sequence protocol (the :meth:`__getitem__` method with integer arguments + :term:`iterable` protocol (the :meth:`~object.__iter__` method), + or it must support + the sequence protocol (the :meth:`~object.__getitem__` method with integer arguments starting at ``0``). If it does not support either of those protocols, :exc:`TypeError` is raised. If the second argument, *sentinel*, is given, then *object* must be a callable object. The iterator created in this case @@ -1158,8 +1163,8 @@ are always available. They are listed here in alphabetical order. See also :func:`format` for more information. - .. index:: - single: file object; open() built-in function +.. index:: + single: file object; open() built-in function .. function:: open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None) @@ -1221,7 +1226,7 @@ are always available. They are listed here in alphabetical order. *buffering* is an optional integer used to set the buffering policy. Pass 0 to switch buffering off (only allowed in binary mode), 1 to select line - buffering (only usable in text mode), and an integer > 1 to indicate the size + buffering (only usable when writing in text mode), and an integer > 1 to indicate the size in bytes of a fixed-size chunk buffer. Note that specifying a buffer size this way applies for binary buffered I/O, but ``TextIOWrapper`` (i.e., files opened with ``mode='r+'``) would have another buffering. To disable buffering in @@ -1271,7 +1276,7 @@ are always available. They are listed here in alphabetical order. * ``'xmlcharrefreplace'`` is only supported when writing to a file. Characters not supported by the encoding are replaced with the - appropriate XML character reference ``&#nnn;``. + appropriate XML character reference :samp:`&#{nnn};`. * ``'backslashreplace'`` replaces malformed data by Python's backslashed escape sequences. @@ -1360,28 +1365,28 @@ are always available. They are listed here in alphabetical order. .. versionchanged:: 3.3 - * The *opener* parameter was added. - * The ``'x'`` mode was added. - * :exc:`IOError` used to be raised, it is now an alias of :exc:`OSError`. - * :exc:`FileExistsError` is now raised if the file opened in exclusive - creation mode (``'x'``) already exists. + * The *opener* parameter was added. + * The ``'x'`` mode was added. + * :exc:`IOError` used to be raised, it is now an alias of :exc:`OSError`. + * :exc:`FileExistsError` is now raised if the file opened in exclusive + creation mode (``'x'``) already exists. .. versionchanged:: 3.4 - * The file is now non-inheritable. + * The file is now non-inheritable. .. versionchanged:: 3.5 - * If the system call is interrupted and the signal handler does not raise an - exception, the function now retries the system call instead of raising an - :exc:`InterruptedError` exception (see :pep:`475` for the rationale). - * The ``'namereplace'`` error handler was added. + * If the system call is interrupted and the signal handler does not raise an + exception, the function now retries the system call instead of raising an + :exc:`InterruptedError` exception (see :pep:`475` for the rationale). + * The ``'namereplace'`` error handler was added. .. versionchanged:: 3.6 - * Support added to accept objects implementing :class:`os.PathLike`. - * On Windows, opening a console buffer may return a subclass of - :class:`io.RawIOBase` other than :class:`io.FileIO`. + * Support added to accept objects implementing :class:`os.PathLike`. + * On Windows, opening a console buffer may return a subclass of + :class:`io.RawIOBase` other than :class:`io.FileIO`. .. versionchanged:: 3.11 The ``'U'`` mode has been removed. @@ -1500,38 +1505,44 @@ are always available. They are listed here in alphabetical order. """Get the current voltage.""" return self._voltage - The ``@property`` decorator turns the :meth:`voltage` method into a "getter" + The ``@property`` decorator turns the :meth:`!voltage` method into a "getter" for a read-only attribute with the same name, and it sets the docstring for *voltage* to "Get the current voltage." - A property object has :attr:`~property.getter`, :attr:`~property.setter`, - and :attr:`~property.deleter` methods usable as decorators that create a - copy of the property with the corresponding accessor function set to the - decorated function. This is best explained with an example:: + .. decorator:: property.getter + .. decorator:: property.setter + .. decorator:: property.deleter - class C: - def __init__(self): - self._x = None + A property object has ``getter``, ``setter``, + and ``deleter`` methods usable as decorators that create a + copy of the property with the corresponding accessor function set to the + decorated function. This is best explained with an example: - @property - def x(self): - """I'm the 'x' property.""" - return self._x + .. testcode:: - @x.setter - def x(self, value): - self._x = value + class C: + def __init__(self): + self._x = None - @x.deleter - def x(self): - del self._x + @property + def x(self): + """I'm the 'x' property.""" + return self._x + + @x.setter + def x(self, value): + self._x = value - This code is exactly equivalent to the first example. Be sure to give the - additional functions the same name as the original property (``x`` in this - case.) + @x.deleter + def x(self): + del self._x - The returned property object also has the attributes ``fget``, ``fset``, and - ``fdel`` corresponding to the constructor arguments. + This code is exactly equivalent to the first example. Be sure to give the + additional functions the same name as the original property (``x`` in this + case.) + + The returned property object also has the attributes ``fget``, ``fset``, and + ``fdel`` corresponding to the constructor arguments. .. versionchanged:: 3.5 The docstrings of property objects are now writeable. @@ -1554,7 +1565,8 @@ are always available. They are listed here in alphabetical order. representation is a string enclosed in angle brackets that contains the name of the type of the object together with additional information often including the name and address of the object. A class can control what this - function returns for its instances by defining a :meth:`__repr__` method. + function returns for its instances + by defining a :meth:`~object.__repr__` method. If :func:`sys.displayhook` is not accessible, this function will raise :exc:`RuntimeError`. @@ -1562,9 +1574,9 @@ are always available. They are listed here in alphabetical order. .. function:: reversed(seq) Return a reverse :term:`iterator`. *seq* must be an object which has - a :meth:`__reversed__` method or supports the sequence protocol (the - :meth:`__len__` method and the :meth:`__getitem__` method with integer - arguments starting at ``0``). + a :meth:`~object.__reversed__` method or supports the sequence protocol (the + :meth:`~object.__len__` method and the :meth:`~object.__getitem__` method + with integer arguments starting at ``0``). .. function:: round(number, ndigits=None) @@ -1631,17 +1643,25 @@ are always available. They are listed here in alphabetical order. .. class:: slice(stop) - slice(start, stop, step=1) + slice(start, stop, step=None) Return a :term:`slice` object representing the set of indices specified by ``range(start, stop, step)``. The *start* and *step* arguments default to - ``None``. Slice objects have read-only data attributes :attr:`~slice.start`, - :attr:`~slice.stop`, and :attr:`~slice.step` which merely return the argument - values (or their default). They have no other explicit functionality; - however, they are used by NumPy and other third-party packages. + ``None``. + + .. attribute:: slice.start + .. attribute:: slice.stop + .. attribute:: slice.step + + Slice objects have read-only data attributes :attr:`!start`, + :attr:`!stop`, and :attr:`!step` which merely return the argument + values (or their default). They have no other explicit functionality; + however, they are used by NumPy and other third-party packages. + Slice objects are also generated when extended indexing syntax is used. For example: ``a[start:stop:step]`` or ``a[start:stop, i]``. See - :func:`itertools.islice` for an alternate version that returns an iterator. + :func:`itertools.islice` for an alternate version that returns an + :term:`iterator`. .. versionchanged:: 3.12 Slice objects are now :term:`hashable` (provided :attr:`~slice.start`, @@ -1752,7 +1772,7 @@ are always available. They are listed here in alphabetical order. The *start* parameter can be specified as a keyword argument. .. versionchanged:: 3.12 Summation of floats switched to an algorithm - that gives higher accuracy on most builds. + that gives higher accuracy and better commutativity on most builds. .. class:: super() @@ -1780,6 +1800,13 @@ are always available. They are listed here in alphabetical order. the second argument is a type, ``issubclass(type2, type)`` must be true (this is useful for classmethods). + When called directly within an ordinary method of a class, both arguments may + be omitted ("zero-argument :func:`!super`"). In this case, *type* will be the + enclosing class, and *obj* will be the first argument of the immediately + enclosing function (typically ``self``). (This means that zero-argument + :func:`!super` will not work as expected within nested functions, including + generator expressions, which implicitly create nested functions.) + There are two typical use cases for *super*. In a class hierarchy with single inheritance, *super* can be used to refer to parent classes without naming them explicitly, thus making the code more maintainable. This use @@ -1808,7 +1835,8 @@ are always available. They are listed here in alphabetical order. Note that :func:`super` is implemented as part of the binding process for explicit dotted attribute lookups such as ``super().__getitem__(name)``. - It does so by implementing its own :meth:`__getattribute__` method for searching + It does so by implementing its own :meth:`~object.__getattribute__` method + for searching classes in a predictable order that supports cooperative multiple inheritance. Accordingly, :func:`super` is undefined for implicit lookups using statements or operators such as ``super()[name]``. diff --git a/Doc/library/functools.rst b/Doc/library/functools.rst index 40f43f8b3519cd..6749a5137b446f 100644 --- a/Doc/library/functools.rst +++ b/Doc/library/functools.rst @@ -226,8 +226,9 @@ The :mod:`functools` module defines the following functions: In general, the LRU cache should only be used when you want to reuse previously computed values. Accordingly, it doesn't make sense to cache - functions with side-effects, functions that need to create distinct mutable - objects on each call, or impure functions such as time() or random(). + functions with side-effects, functions that need to create + distinct mutable objects on each call (such as generators and async functions), + or impure functions such as time() or random(). Example of an LRU cache for static web content:: @@ -402,25 +403,27 @@ The :mod:`functools` module defines the following functions: .. versionadded:: 3.4 -.. function:: reduce(function, iterable[, initializer]) +.. function:: reduce(function, iterable[, initial], /) Apply *function* of two arguments cumulatively to the items of *iterable*, from left to right, so as to reduce the iterable to a single value. For example, ``reduce(lambda x, y: x+y, [1, 2, 3, 4, 5])`` calculates ``((((1+2)+3)+4)+5)``. The left argument, *x*, is the accumulated value and the right argument, *y*, is - the update value from the *iterable*. If the optional *initializer* is present, + the update value from the *iterable*. If the optional *initial* is present, it is placed before the items of the iterable in the calculation, and serves as - a default when the iterable is empty. If *initializer* is not given and + a default when the iterable is empty. If *initial* is not given and *iterable* contains only one item, the first item is returned. Roughly equivalent to:: - def reduce(function, iterable, initializer=None): + initial_missing = object() + + def reduce(function, iterable, initial=initial_missing, /): it = iter(iterable) - if initializer is None: + if initial is initial_missing: value = next(it) else: - value = initializer + value = initial for element in it: value = function(value, element) return value @@ -739,7 +742,7 @@ have three read-only attributes: called. :class:`partial` objects are like :class:`function` objects in that they are -callable, weak referencable, and can have attributes. There are some important +callable, weak referenceable, and can have attributes. There are some important differences. For instance, the :attr:`~definition.__name__` and :attr:`__doc__` attributes are not created automatically. Also, :class:`partial` objects defined in classes behave like static methods and do not transform into bound methods diff --git a/Doc/library/gc.rst b/Doc/library/gc.rst index 331c071cda7692..e36a71af2b64ab 100644 --- a/Doc/library/gc.rst +++ b/Doc/library/gc.rst @@ -42,8 +42,8 @@ The :mod:`gc` module provides the following functions: With no arguments, run a full collection. The optional argument *generation* may be an integer specifying which generation to collect (from 0 to 2). A - :exc:`ValueError` is raised if the generation number is invalid. The number of - unreachable objects found is returned. + :exc:`ValueError` is raised if the generation number is invalid. The sum of + collected objects and uncollectable objects is returned. The free lists maintained for a number of built-in types are cleared whenever a full collection or collection of the highest generation (2) @@ -96,7 +96,7 @@ The :mod:`gc` module provides the following functions: .. versionadded:: 3.4 -.. function:: set_threshold(threshold0[, threshold1[, threshold2]]) +.. function:: set_threshold(threshold0, [threshold1, [threshold2]]) Set the garbage collection thresholds (the collection frequency). Setting *threshold0* to zero disables collection. diff --git a/Doc/library/getpass.rst b/Doc/library/getpass.rst index d5bbe67fb30a62..54c84d45a59856 100644 --- a/Doc/library/getpass.rst +++ b/Doc/library/getpass.rst @@ -43,10 +43,13 @@ The :mod:`getpass` module provides two functions: Return the "login name" of the user. This function checks the environment variables :envvar:`LOGNAME`, - :envvar:`USER`, :envvar:`LNAME` and :envvar:`USERNAME`, in order, and + :envvar:`USER`, :envvar:`!LNAME` and :envvar:`USERNAME`, in order, and returns the value of the first one which is set to a non-empty string. If none are set, the login name from the password database is returned on - systems which support the :mod:`pwd` module, otherwise, an exception is - raised. + systems which support the :mod:`pwd` module, otherwise, an :exc:`OSError` + is raised. In general, this function should be preferred over :func:`os.getlogin()`. + + .. versionchanged:: 3.13 + Previously, various exceptions beyond just :exc:`OSError` were raised. diff --git a/Doc/library/gettext.rst b/Doc/library/gettext.rst index 88a65b980d310f..41beac3e0c7396 100644 --- a/Doc/library/gettext.rst +++ b/Doc/library/gettext.rst @@ -58,7 +58,7 @@ class-based API instead. Return the localized translation of *message*, based on the current global domain, language, and locale directory. This function is usually aliased as - :func:`_` in the local namespace (see examples below). + :func:`!_` in the local namespace (see examples below). .. function:: dgettext(domain, message) @@ -98,7 +98,7 @@ class-based API instead. .. versionadded:: 3.8 -Note that GNU :program:`gettext` also defines a :func:`dcgettext` method, but +Note that GNU :program:`gettext` also defines a :func:`!dcgettext` method, but this was deemed not useful and so it is currently unimplemented. Here's an example of typical usage for this API:: @@ -119,7 +119,7 @@ greater convenience than the GNU :program:`gettext` API. It is the recommended way of localizing your Python applications and modules. :mod:`!gettext` defines a :class:`GNUTranslations` class which implements the parsing of GNU :file:`.mo` format files, and has methods for returning strings. Instances of this class can also -install themselves in the built-in namespace as the function :func:`_`. +install themselves in the built-in namespace as the function :func:`!_`. .. function:: find(domain, localedir=None, languages=None, all=False) @@ -150,15 +150,12 @@ install themselves in the built-in namespace as the function :func:`_`. .. function:: translation(domain, localedir=None, languages=None, class_=None, fallback=False) - Return a :class:`*Translations` instance based on the *domain*, *localedir*, + Return a ``*Translations`` instance based on the *domain*, *localedir*, and *languages*, which are first passed to :func:`find` to get a list of the associated :file:`.mo` file paths. Instances with identical :file:`.mo` file names are cached. The actual class instantiated is *class_* if provided, otherwise :class:`GNUTranslations`. The class's constructor must - take a single :term:`file object` argument. If provided, *codeset* will change - the charset used to encode translated strings in the - :meth:`~NullTranslations.lgettext` and :meth:`~NullTranslations.lngettext` - methods. + take a single :term:`file object` argument. If multiple files are found, later files are used as fallbacks for earlier ones. To allow setting the fallback, :func:`copy.copy` is used to clone each @@ -170,26 +167,26 @@ install themselves in the built-in namespace as the function :func:`_`. :class:`NullTranslations` instance if *fallback* is true. .. versionchanged:: 3.3 - :exc:`IOError` used to be raised instead of :exc:`OSError`. + :exc:`IOError` used to be raised, it is now an alias of :exc:`OSError`. .. versionchanged:: 3.11 *codeset* parameter is removed. .. function:: install(domain, localedir=None, *, names=None) - This installs the function :func:`_` in Python's builtins namespace, based on + This installs the function :func:`!_` in Python's builtins namespace, based on *domain* and *localedir* which are passed to the function :func:`translation`. For the *names* parameter, please see the description of the translation object's :meth:`~NullTranslations.install` method. As seen below, you usually mark the strings in your application that are - candidates for translation, by wrapping them in a call to the :func:`_` + candidates for translation, by wrapping them in a call to the :func:`!_` function, like this:: print(_('This string will be translated.')) - For convenience, you want the :func:`_` function to be installed in Python's + For convenience, you want the :func:`!_` function to be installed in Python's builtins namespace, so it is easily accessible in all modules of your application. @@ -260,7 +257,7 @@ are the methods of :class:`!NullTranslations`: .. method:: info() - Return the "protected" :attr:`_info` variable, a dictionary containing + Return a dictionary containing the metadata found in the message catalog file. @@ -276,20 +273,20 @@ are the methods of :class:`!NullTranslations`: If the *names* parameter is given, it must be a sequence containing the names of functions you want to install in the builtins namespace in - addition to :func:`_`. Supported names are ``'gettext'``, ``'ngettext'``, - ``'pgettext'``, ``'npgettext'``, ``'lgettext'``, and ``'lngettext'``. + addition to :func:`!_`. Supported names are ``'gettext'``, ``'ngettext'``, + ``'pgettext'``, and ``'npgettext'``. Note that this is only one way, albeit the most convenient way, to make - the :func:`_` function available to your application. Because it affects + the :func:`!_` function available to your application. Because it affects the entire application globally, and specifically the built-in namespace, - localized modules should never install :func:`_`. Instead, they should use - this code to make :func:`_` available to their module:: + localized modules should never install :func:`!_`. Instead, they should use + this code to make :func:`!_` available to their module:: import gettext t = gettext.translation('mymodule', ...) _ = t.gettext - This puts :func:`_` only in the module's global namespace and so only + This puts :func:`!_` only in the module's global namespace and so only affects calls within this module. .. versionchanged:: 3.8 @@ -299,9 +296,9 @@ are the methods of :class:`!NullTranslations`: The :class:`GNUTranslations` class ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -The :mod:`gettext` module provides one additional class derived from +The :mod:`!gettext` module provides one additional class derived from :class:`NullTranslations`: :class:`GNUTranslations`. This class overrides -:meth:`_parse` to enable reading GNU :program:`gettext` format :file:`.mo` files +:meth:`!_parse` to enable reading GNU :program:`gettext` format :file:`.mo` files in both big-endian and little-endian format. :class:`GNUTranslations` parses optional metadata out of the translation @@ -309,16 +306,16 @@ catalog. It is convention with GNU :program:`gettext` to include metadata as the translation for the empty string. This metadata is in :rfc:`822`\ -style ``key: value`` pairs, and should contain the ``Project-Id-Version`` key. If the key ``Content-Type`` is found, then the ``charset`` property is used to -initialize the "protected" :attr:`_charset` instance variable, defaulting to +initialize the "protected" :attr:`!_charset` instance variable, defaulting to ``None`` if not found. If the charset encoding is specified, then all message ids and message strings read from the catalog are converted to Unicode using this encoding, else ASCII is assumed. -Since message ids are read as Unicode strings too, all :meth:`*gettext` methods +Since message ids are read as Unicode strings too, all ``*gettext()`` methods will assume message ids as Unicode strings, not byte strings. The entire set of key/value pairs are placed into a dictionary and set as the -"protected" :attr:`_info` instance variable. +"protected" :attr:`!_info` instance variable. If the :file:`.mo` file's magic number is invalid, the major version number is unexpected, or if other problems occur while reading the file, instantiating a @@ -404,7 +401,7 @@ version has a slightly different API. Its documented usage was:: _ = cat.gettext print(_('hello world')) -For compatibility with this older module, the function :func:`Catalog` is an +For compatibility with this older module, the function :func:`!Catalog` is an alias for the :func:`translation` function described above. One difference between this module and Henstridge's: his catalog objects @@ -432,7 +429,7 @@ take the following steps: In order to prepare your code for I18N, you need to look at all the strings in your files. Any string that needs to be translated should be marked by wrapping -it in ``_('...')`` --- that is, a call to the function :func:`_`. For example:: +it in ``_('...')`` --- that is, a call to the function :func:`_ `. For example:: filename = 'mylog.txt' message = _('writing a log message') @@ -504,7 +501,7 @@ module:: Localizing your application ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -If you are localizing your application, you can install the :func:`_` function +If you are localizing your application, you can install the :func:`!_` function globally into the built-in namespace, usually in the main driver file of your application. This will let all your application-specific files just use ``_('...')`` without having to explicitly install it in each file. @@ -581,13 +578,13 @@ Here is one way you can handle this situation:: for a in animals: print(_(a)) -This works because the dummy definition of :func:`_` simply returns the string +This works because the dummy definition of :func:`!_` simply returns the string unchanged. And this dummy definition will temporarily override any definition -of :func:`_` in the built-in namespace (until the :keyword:`del` command). Take -care, though if you have a previous definition of :func:`_` in the local +of :func:`!_` in the built-in namespace (until the :keyword:`del` command). Take +care, though if you have a previous definition of :func:`!_` in the local namespace. -Note that the second use of :func:`_` will not identify "a" as being +Note that the second use of :func:`!_` will not identify "a" as being translatable to the :program:`gettext` program, because the parameter is not a string literal. @@ -606,13 +603,13 @@ Another way to handle this is with the following example:: print(_(a)) In this case, you are marking translatable strings with the function -:func:`N_`, which won't conflict with any definition of :func:`_`. +:func:`!N_`, which won't conflict with any definition of :func:`!_`. However, you will need to teach your message extraction program to -look for translatable strings marked with :func:`N_`. :program:`xgettext`, +look for translatable strings marked with :func:`!N_`. :program:`xgettext`, :program:`pygettext`, ``pybabel extract``, and :program:`xpot` all support this through the use of the :option:`!-k` command-line switch. -The choice of :func:`N_` here is totally arbitrary; it could have just -as easily been :func:`MarkThisStringForTranslation`. +The choice of :func:`!N_` here is totally arbitrary; it could have just +as easily been :func:`!MarkThisStringForTranslation`. Acknowledgements @@ -639,9 +636,9 @@ implementations, and valuable experience to the creation of this module: .. rubric:: Footnotes -.. [#] The default locale directory is system dependent; for example, on RedHat Linux +.. [#] The default locale directory is system dependent; for example, on Red Hat Linux it is :file:`/usr/share/locale`, but on Solaris it is :file:`/usr/lib/locale`. - The :mod:`gettext` module does not try to support these system dependent + The :mod:`!gettext` module does not try to support these system dependent defaults; instead its default is :file:`{sys.base_prefix}/share/locale` (see :data:`sys.base_prefix`). For this reason, it is always best to call :func:`bindtextdomain` with an explicit absolute path at the start of your diff --git a/Doc/library/glob.rst b/Doc/library/glob.rst index 0e4cfe7ebed797..6e4f72c19ff4c9 100644 --- a/Doc/library/glob.rst +++ b/Doc/library/glob.rst @@ -34,9 +34,7 @@ unlike :func:`fnmatch.fnmatch` or :func:`pathlib.Path.glob`. For a literal match, wrap the meta-characters in brackets. For example, ``'[?]'`` matches the character ``'?'``. - -.. seealso:: - The :mod:`pathlib` module offers high-level path objects. +The :mod:`glob` module defines the following functions: .. function:: glob(pathname, *, root_dir=None, dir_fd=None, recursive=False, \ @@ -117,7 +115,48 @@ For example, ``'[?]'`` matches the character ``'?'``. .. versionadded:: 3.4 -For example, consider a directory containing the following files: +.. function:: translate(pathname, *, recursive=False, include_hidden=False, seps=None) + + Convert the given path specification to a regular expression for use with + :func:`re.match`. The path specification can contain shell-style wildcards. + + For example: + + >>> import glob, re + >>> + >>> regex = glob.translate('**/*.txt', recursive=True, include_hidden=True) + >>> regex + '(?s:(?:.+/)?[^/]*\\.txt)\\Z' + >>> reobj = re.compile(regex) + >>> reobj.match('foo/bar/baz.txt') + + + Path separators and segments are meaningful to this function, unlike + :func:`fnmatch.translate`. By default wildcards do not match path + separators, and ``*`` pattern segments match precisely one path segment. + + If *recursive* is true, the pattern segment "``**``" will match any number + of path segments. If "``**``" occurs in any position other than a full + pattern segment, :exc:`ValueError` is raised. + + If *include_hidden* is true, wildcards can match path segments that start + with a dot (``.``). + + A sequence of path separators may be supplied to the *seps* argument. If + not given, :data:`os.sep` and :data:`~os.altsep` (if available) are used. + + .. seealso:: + + :meth:`pathlib.PurePath.match` and :meth:`pathlib.Path.glob` methods, + which call this function to implement pattern matching and globbing. + + .. versionadded:: 3.13 + + +Examples +-------- + +Consider a directory containing the following files: :file:`1.gif`, :file:`2.txt`, :file:`card.gif` and a subdirectory :file:`sub` which contains only the file :file:`3.txt`. :func:`glob` will produce the following results. Notice how any leading components of the path are @@ -146,6 +185,7 @@ default. For example, consider a directory containing :file:`card.gif` and ['.card.gif'] .. seealso:: + The :mod:`fnmatch` module offers shell-style filename (not path) expansion. - Module :mod:`fnmatch` - Shell-style filename (not path) expansion +.. seealso:: + The :mod:`pathlib` module offers high-level path objects. diff --git a/Doc/library/graphlib.rst b/Doc/library/graphlib.rst index fdd8f39ef4e1c4..5414d6370b78ce 100644 --- a/Doc/library/graphlib.rst +++ b/Doc/library/graphlib.rst @@ -37,14 +37,14 @@ In the general case, the steps required to perform the sorting of a given graph are as follows: - * Create an instance of the :class:`TopologicalSorter` with an optional - initial graph. - * Add additional nodes to the graph. - * Call :meth:`~TopologicalSorter.prepare` on the graph. - * While :meth:`~TopologicalSorter.is_active` is ``True``, iterate over - the nodes returned by :meth:`~TopologicalSorter.get_ready` and - process them. Call :meth:`~TopologicalSorter.done` on each node as it - finishes processing. + * Create an instance of the :class:`TopologicalSorter` with an optional + initial graph. + * Add additional nodes to the graph. + * Call :meth:`~TopologicalSorter.prepare` on the graph. + * While :meth:`~TopologicalSorter.is_active` is ``True``, iterate over + the nodes returned by :meth:`~TopologicalSorter.get_ready` and + process them. Call :meth:`~TopologicalSorter.done` on each node as it + finishes processing. In case just an immediate sorting of the nodes in the graph is required and no parallelism is involved, the convenience method diff --git a/Doc/library/grp.rst b/Doc/library/grp.rst index 8f88f82e1c21ad..274a353103b488 100644 --- a/Doc/library/grp.rst +++ b/Doc/library/grp.rst @@ -10,7 +10,7 @@ This module provides access to the Unix group database. It is available on all Unix versions. -.. include:: ../includes/wasm-notavail.rst +.. availability:: Unix, not Emscripten, not WASI. Group database entries are reported as a tuple-like object, whose attributes correspond to the members of the ``group`` structure (Attribute field below, see diff --git a/Doc/library/gzip.rst b/Doc/library/gzip.rst index 60236a1190e423..50cde09fa10a9d 100644 --- a/Doc/library/gzip.rst +++ b/Doc/library/gzip.rst @@ -105,7 +105,7 @@ The module defines the following items: should only be provided in compression mode. If omitted or ``None``, the current time is used. See the :attr:`mtime` attribute for more details. - Calling a :class:`GzipFile` object's :meth:`close` method does not close + Calling a :class:`GzipFile` object's :meth:`!close` method does not close *fileobj*, since you might wish to append more material after the compressed data. This also allows you to pass an :class:`io.BytesIO` object opened for writing as *fileobj*, and retrieve the resulting memory buffer using the @@ -250,6 +250,8 @@ Example of how to GZIP compress a binary string:: .. program:: gzip +.. _gzip-cli: + Command Line Interface ---------------------- @@ -266,23 +268,23 @@ Once executed the :mod:`gzip` module keeps the input file(s). Command line options ^^^^^^^^^^^^^^^^^^^^ -.. cmdoption:: file +.. option:: file If *file* is not specified, read from :data:`sys.stdin`. -.. cmdoption:: --fast +.. option:: --fast Indicates the fastest compression method (less compression). -.. cmdoption:: --best +.. option:: --best Indicates the slowest compression method (best compression). -.. cmdoption:: -d, --decompress +.. option:: -d, --decompress Decompress the given file. -.. cmdoption:: -h, --help +.. option:: -h, --help Show the help message. diff --git a/Doc/library/hashlib.rst b/Doc/library/hashlib.rst index 69fb79b49ca2a0..761dd84edee299 100644 --- a/Doc/library/hashlib.rst +++ b/Doc/library/hashlib.rst @@ -136,16 +136,16 @@ Using :func:`new` with an algorithm name: '031edd7d41651593c5fe5c006fa5752b37fddff7bc4e843aa6af0c950f4b9406' -.. function:: md5([, data], \*, usedforsecurity=True) -.. function:: sha1([, data], \*, usedforsecurity=True) -.. function:: sha224([, data], \*, usedforsecurity=True) -.. function:: sha256([, data], \*, usedforsecurity=True) -.. function:: sha384([, data], \*, usedforsecurity=True) -.. function:: sha512([, data], \*, usedforsecurity=True) -.. function:: sha3_224([, data], \*, usedforsecurity=True) -.. function:: sha3_256([, data], \*, usedforsecurity=True) -.. function:: sha3_384([, data], \*, usedforsecurity=True) -.. function:: sha3_512([, data], \*, usedforsecurity=True) +.. function:: md5([, data], *, usedforsecurity=True) +.. function:: sha1([, data], *, usedforsecurity=True) +.. function:: sha224([, data], *, usedforsecurity=True) +.. function:: sha256([, data], *, usedforsecurity=True) +.. function:: sha384([, data], *, usedforsecurity=True) +.. function:: sha512([, data], *, usedforsecurity=True) +.. function:: sha3_224([, data], *, usedforsecurity=True) +.. function:: sha3_256([, data], *, usedforsecurity=True) +.. function:: sha3_384([, data], *, usedforsecurity=True) +.. function:: sha3_512([, data], *, usedforsecurity=True) Named constructors such as these are faster than passing an algorithm name to :func:`new`. @@ -234,8 +234,8 @@ A hash object has the following methods: SHAKE variable length digests ----------------------------- -.. function:: shake_128([, data], \*, usedforsecurity=True) -.. function:: shake_256([, data], \*, usedforsecurity=True) +.. function:: shake_128([, data], *, usedforsecurity=True) +.. function:: shake_256([, data], *, usedforsecurity=True) The :func:`shake_128` and :func:`shake_256` algorithms provide variable length digests with length_in_bits//2 up to 128 or 256 bits of security. @@ -364,6 +364,8 @@ include a `salt `_. .. versionadded:: 3.6 +.. _hashlib-blake2: + BLAKE2 ------ diff --git a/Doc/library/heapq.rst b/Doc/library/heapq.rst index 8b00f7b27959b6..ddbada13bddf5b 100644 --- a/Doc/library/heapq.rst +++ b/Doc/library/heapq.rst @@ -270,7 +270,7 @@ winner. The simplest algorithmic way to remove it and find the "next" winner is to move some loser (let's say cell 30 in the diagram above) into the 0 position, and then percolate this new 0 down the tree, exchanging values, until the invariant is re-established. This is clearly logarithmic on the total number of -items in the tree. By iterating over all items, you get an O(n log n) sort. +items in the tree. By iterating over all items, you get an *O*\ (*n* log *n*) sort. A nice feature of this sort is that you can efficiently insert new items while the sort is going on, provided that the inserted items are not "better" than the diff --git a/Doc/library/hmac.rst b/Doc/library/hmac.rst index b2ca0455d3745c..43012e03c580e8 100644 --- a/Doc/library/hmac.rst +++ b/Doc/library/hmac.rst @@ -14,7 +14,7 @@ This module implements the HMAC algorithm as described by :rfc:`2104`. -.. function:: new(key, msg=None, digestmod='') +.. function:: new(key, msg=None, digestmod) Return a new hmac object. *key* is a bytes or bytearray object giving the secret key. If *msg* is present, the method call ``update(msg)`` is made. @@ -27,10 +27,9 @@ This module implements the HMAC algorithm as described by :rfc:`2104`. Parameter *msg* can be of any type supported by :mod:`hashlib`. Parameter *digestmod* can be the name of a hash algorithm. - .. deprecated-removed:: 3.4 3.8 - MD5 as implicit default digest for *digestmod* is deprecated. - The digestmod parameter is now required. Pass it as a keyword - argument to avoid awkwardness when you do not have an initial msg. + .. versionchanged:: 3.8 + The *digestmod* argument is now required. Pass it as a keyword + argument to avoid awkwardness when you do not have an initial *msg*. .. function:: digest(key, msg, digest) @@ -114,11 +113,9 @@ A hash object has the following attributes: .. versionadded:: 3.4 -.. deprecated:: 3.9 - - The undocumented attributes ``HMAC.digest_cons``, ``HMAC.inner``, and - ``HMAC.outer`` are internal implementation details and will be removed in - Python 3.10. +.. versionchanged:: 3.10 + Removed the undocumented attributes ``HMAC.digest_cons``, ``HMAC.inner``, + and ``HMAC.outer``. This module also provides the following helper function: diff --git a/Doc/library/html.parser.rst b/Doc/library/html.parser.rst index 03aff25ce6117a..d35090111e0822 100644 --- a/Doc/library/html.parser.rst +++ b/Doc/library/html.parser.rst @@ -173,7 +173,7 @@ implementations do nothing (except for :meth:`~HTMLParser.handle_startendtag`): .. method:: HTMLParser.handle_charref(name) This method is called to process decimal and hexadecimal numeric character - references of the form ``&#NNN;`` and ``&#xNNN;``. For example, the decimal + references of the form :samp:`&#{NNN};` and :samp:`&#x{NNN};`. For example, the decimal equivalent for ``>`` is ``>``, whereas the hexadecimal is ``>``; in this case the method will receive ``'62'`` or ``'x3E'``. This method is never called if *convert_charrefs* is ``True``. diff --git a/Doc/library/http.cookiejar.rst b/Doc/library/http.cookiejar.rst index 87ef156a0bed57..12a6d768437ea5 100644 --- a/Doc/library/http.cookiejar.rst +++ b/Doc/library/http.cookiejar.rst @@ -44,8 +44,8 @@ The module defines the following exception: cookies from a file. :exc:`LoadError` is a subclass of :exc:`OSError`. .. versionchanged:: 3.3 - LoadError was made a subclass of :exc:`OSError` instead of - :exc:`IOError`. + :exc:`LoadError` used to be a subtype of :exc:`IOError`, which is now an + alias of :exc:`OSError`. The following classes are provided: diff --git a/Doc/library/http.cookies.rst b/Doc/library/http.cookies.rst index a2c1eb00d8b33d..e91972fe621a48 100644 --- a/Doc/library/http.cookies.rst +++ b/Doc/library/http.cookies.rst @@ -18,16 +18,17 @@ cookie value. The module formerly strictly applied the parsing rules described in the :rfc:`2109` and :rfc:`2068` specifications. It has since been discovered that -MSIE 3.0x doesn't follow the character rules outlined in those specs and also -many current day browsers and servers have relaxed parsing rules when comes to -Cookie handling. As a result, the parsing rules used are a bit less strict. +MSIE 3.0x didn't follow the character rules outlined in those specs; many +current-day browsers and servers have also relaxed parsing rules when it comes +to cookie handling. As a result, this module now uses parsing rules that are a +bit less strict than they once were. The character set, :data:`string.ascii_letters`, :data:`string.digits` and ``!#$%&'*+-.^_`|~:`` denote the set of valid characters allowed by this module -in Cookie name (as :attr:`~Morsel.key`). +in a cookie name (as :attr:`~Morsel.key`). .. versionchanged:: 3.3 - Allowed ':' as a valid Cookie name character. + Allowed ':' as a valid cookie name character. .. note:: @@ -54,9 +55,10 @@ in Cookie name (as :attr:`~Morsel.key`). .. class:: SimpleCookie([input]) - This class derives from :class:`BaseCookie` and overrides :meth:`value_decode` - and :meth:`value_encode`. SimpleCookie supports strings as cookie values. - When setting the value, SimpleCookie calls the builtin :func:`str()` to convert + This class derives from :class:`BaseCookie` and overrides :meth:`~BaseCookie.value_decode` + and :meth:`~BaseCookie.value_encode`. :class:`!SimpleCookie` supports + strings as cookie values. When setting the value, :class:`!SimpleCookie` + calls the builtin :func:`str` to convert the value to a string. Values received from HTTP are kept as strings. .. seealso:: @@ -129,17 +131,17 @@ Morsel Objects Abstract a key/value pair, which has some :rfc:`2109` attributes. Morsels are dictionary-like objects, whose set of keys is constant --- the valid - :rfc:`2109` attributes, which are - - * ``expires`` - * ``path`` - * ``comment`` - * ``domain`` - * ``max-age`` - * ``secure`` - * ``version`` - * ``httponly`` - * ``samesite`` + :rfc:`2109` attributes, which are: + + .. attribute:: expires + path + comment + domain + max-age + secure + version + httponly + samesite The attribute :attr:`httponly` specifies that the cookie is only transferred in HTTP requests, and is not accessible through JavaScript. This is intended @@ -152,7 +154,7 @@ Morsel Objects The keys are case-insensitive and their default value is ``''``. .. versionchanged:: 3.5 - :meth:`~Morsel.__eq__` now takes :attr:`~Morsel.key` and :attr:`~Morsel.value` + :meth:`!__eq__` now takes :attr:`~Morsel.key` and :attr:`~Morsel.value` into account. .. versionchanged:: 3.7 diff --git a/Doc/library/http.server.rst b/Doc/library/http.server.rst index ae75e6dc5fdcf3..64bddd23f82933 100644 --- a/Doc/library/http.server.rst +++ b/Doc/library/http.server.rst @@ -65,10 +65,10 @@ provides three different variants: The handler will parse the request and the headers, then call a method specific to the request type. The method name is constructed from the - request. For example, for the request method ``SPAM``, the :meth:`do_SPAM` + request. For example, for the request method ``SPAM``, the :meth:`!do_SPAM` method will be called with no arguments. All of the relevant information is stored in instance variables of the handler. Subclasses should not need to - override or extend the :meth:`__init__` method. + override or extend the :meth:`!__init__` method. :class:`BaseHTTPRequestHandler` has the following instance variables: @@ -187,13 +187,13 @@ provides three different variants: Calls :meth:`handle_one_request` once (or, if persistent connections are enabled, multiple times) to handle incoming HTTP requests. You should - never need to override it; instead, implement appropriate :meth:`do_\*` + never need to override it; instead, implement appropriate :meth:`!do_\*` methods. .. method:: handle_one_request() This method will parse and dispatch the request to the appropriate - :meth:`do_\*` method. You should never need to override it. + :meth:`!do_\*` method. You should never need to override it. .. method:: handle_expect_100() @@ -217,7 +217,7 @@ provides three different variants: attribute holds the default values for *message* and *explain* that will be used if no value is provided; for unknown codes the default value for both is the string ``???``. The body will be empty if the method is - HEAD or the response code is one of the following: ``1xx``, + HEAD or the response code is one of the following: :samp:`1{xx}`, ``204 No Content``, ``205 Reset Content``, ``304 Not Modified``. .. versionchanged:: 3.4 @@ -502,11 +502,24 @@ following command runs an HTTP/1.1 conformant server:: Note that CGI scripts will be run with UID of user nobody, for security reasons. Problems with the CGI script will be translated to error 403. + .. deprecated-removed:: 3.13 3.15 + + :class:`CGIHTTPRequestHandler` is being removed in 3.15. CGI has not + been considered a good way to do things for well over a decade. This code + has been unmaintained for a while now and sees very little practical use. + Retaining it could lead to further :ref:`security considerations + `. + :class:`CGIHTTPRequestHandler` can be enabled in the command line by passing the ``--cgi`` option:: python -m http.server --cgi +.. deprecated-removed:: 3.13 3.15 + + :mod:`http.server` command line ``--cgi`` support is being removed + because :class:`CGIHTTPRequestHandler` is being removed. + .. _http.server-security: Security Considerations diff --git a/Doc/library/idle.rst b/Doc/library/idle.rst index 3058bcead661f3..e710d0bacf3fee 100644 --- a/Doc/library/idle.rst +++ b/Doc/library/idle.rst @@ -439,24 +439,24 @@ the :kbd:`Command` key on macOS. * Some useful Emacs bindings are inherited from Tcl/Tk: - * :kbd:`C-a` beginning of line + * :kbd:`C-a` beginning of line - * :kbd:`C-e` end of line + * :kbd:`C-e` end of line - * :kbd:`C-k` kill line (but doesn't put it in clipboard) + * :kbd:`C-k` kill line (but doesn't put it in clipboard) - * :kbd:`C-l` center window around the insertion point + * :kbd:`C-l` center window around the insertion point - * :kbd:`C-b` go backward one character without deleting (usually you can - also use the cursor key for this) + * :kbd:`C-b` go backward one character without deleting (usually you can + also use the cursor key for this) - * :kbd:`C-f` go forward one character without deleting (usually you can - also use the cursor key for this) + * :kbd:`C-f` go forward one character without deleting (usually you can + also use the cursor key for this) - * :kbd:`C-p` go up one line (usually you can also use the cursor key for - this) + * :kbd:`C-p` go up one line (usually you can also use the cursor key for + this) - * :kbd:`C-d` delete next character + * :kbd:`C-d` delete next character Standard keybindings (like :kbd:`C-c` to copy and :kbd:`C-v` to paste) may work. Keybindings are selected in the Configure IDLE dialog. @@ -479,7 +479,7 @@ Search and Replace Any selection becomes a search target. However, only selections within a line work because searches are only performed within lines with the -terminal newline removed. If ``[x] Regular expresion`` is checked, the +terminal newline removed. If ``[x] Regular expression`` is checked, the target is interpreted according to the Python re module. .. _completions: diff --git a/Doc/library/importlib.metadata.rst b/Doc/library/importlib.metadata.rst index d2cc769e2c8400..cc4a0da92da60a 100644 --- a/Doc/library/importlib.metadata.rst +++ b/Doc/library/importlib.metadata.rst @@ -41,7 +41,7 @@ and metadata defined by the `Core metadata specifications ` + You can use :ref:`packages_distributions() ` to get a mapping between them. By default, distribution metadata can live on the file system @@ -171,16 +171,18 @@ group. Read `the setuptools docs `_ for more information on entry points, their definition, and usage. -*Compatibility Note* - -The "selectable" entry points were introduced in ``importlib_metadata`` -3.6 and Python 3.10. Prior to those changes, ``entry_points`` accepted -no parameters and always returned a dictionary of entry points, keyed -by group. With ``importlib_metadata`` 5.0 and Python 3.12, -``entry_points`` always returns an ``EntryPoints`` object. See -`backports.entry_points_selectable `_ -for compatibility options. +.. versionchanged:: 3.12 + The "selectable" entry points were introduced in ``importlib_metadata`` + 3.6 and Python 3.10. Prior to those changes, ``entry_points`` accepted + no parameters and always returned a dictionary of entry points, keyed + by group. With ``importlib_metadata`` 5.0 and Python 3.12, + ``entry_points`` always returns an ``EntryPoints`` object. See + `backports.entry_points_selectable `_ + for compatibility options. +.. versionchanged:: 3.13 + ``EntryPoint`` objects no longer present a tuple-like interface + (:meth:`~object.__getitem__`). .. _metadata: @@ -342,9 +344,17 @@ instance:: >>> dist.metadata['License'] # doctest: +SKIP 'MIT' +For editable packages, an origin property may present :pep:`610` +metadata:: + + >>> dist.origin.url + 'file:///path/to/wheel-0.32.3.editable-py3-none-any.whl' + The full set of available metadata is not described here. See the `Core metadata specifications `_ for additional details. +.. versionadded:: 3.13 + The ``.origin`` property was added. Distribution Discovery ====================== diff --git a/Doc/library/importlib.resources.abc.rst b/Doc/library/importlib.resources.abc.rst index 65c42858bbbb7d..c508b6ba965cc0 100644 --- a/Doc/library/importlib.resources.abc.rst +++ b/Doc/library/importlib.resources.abc.rst @@ -43,8 +43,6 @@ :const:`None`. An object compatible with this ABC should only be returned when the specified module is a package. - .. versionadded:: 3.7 - .. deprecated-removed:: 3.12 3.14 Use :class:`importlib.resources.abc.TraversableResources` instead. @@ -95,11 +93,6 @@ For a representation of the object on the file-system, use :meth:`importlib.resources.as_file`. - .. versionadded:: 3.9 - - .. deprecated-removed:: 3.12 3.14 - Use :class:`importlib.resources.abc.Traversable` instead. - .. attribute:: name Abstract. The base name of this object without any parent references. @@ -153,11 +146,6 @@ Loaders that wish to support resource reading are expected to implement this interface. - .. versionadded:: 3.9 - - .. deprecated-removed:: 3.12 3.14 - Use :class:`importlib.resources.abc.TraversableResources` instead. - .. abstractmethod:: files() Returns a :class:`importlib.resources.abc.Traversable` object for the loaded diff --git a/Doc/library/importlib.resources.rst b/Doc/library/importlib.resources.rst index 76faf731144779..a5adf0b8546dbf 100644 --- a/Doc/library/importlib.resources.rst +++ b/Doc/library/importlib.resources.rst @@ -50,7 +50,7 @@ for example, a package and its resources can be imported from a zip file using ``get_resource_reader(fullname)`` method as specified by :class:`importlib.resources.abc.ResourceReader`. -.. data:: Anchor +.. class:: Anchor Represents an anchor for resources, either a :class:`module object ` or a module name as a string. Defined as @@ -63,7 +63,7 @@ for example, a package and its resources can be imported from a zip file using (think files). A Traversable may contain other containers (think subdirectories). - *anchor* is an optional :data:`Anchor`. If the anchor is a + *anchor* is an optional :class:`Anchor`. If the anchor is a package, resources are resolved from that package. If a module, resources are resolved adjacent to that module (in the same package or the package root). If the anchor is omitted, the caller's module @@ -72,25 +72,28 @@ for example, a package and its resources can be imported from a zip file using .. versionadded:: 3.9 .. versionchanged:: 3.12 - "package" parameter was renamed to "anchor". "anchor" can now + *package* parameter was renamed to *anchor*. *anchor* can now be a non-package module and if omitted will default to the caller's - module. "package" is still accepted for compatibility but will raise - a DeprecationWarning. Consider passing the anchor positionally or + module. *package* is still accepted for compatibility but will raise + a :exc:`DeprecationWarning`. Consider passing the anchor positionally or using ``importlib_resources >= 5.10`` for a compatible interface on older Pythons. .. function:: as_file(traversable) Given a :class:`~importlib.resources.abc.Traversable` object representing - a file, typically from :func:`importlib.resources.files`, return - a context manager for use in a :keyword:`with` statement. + a file or directory, typically from :func:`importlib.resources.files`, + return a context manager for use in a :keyword:`with` statement. The context manager provides a :class:`pathlib.Path` object. - Exiting the context manager cleans up any temporary file created when the - resource was extracted from e.g. a zip file. + Exiting the context manager cleans up any temporary file or directory + created when the resource was extracted from e.g. a zip file. Use ``as_file`` when the Traversable methods - (``read_text``, etc) are insufficient and an actual file on + (``read_text``, etc) are insufficient and an actual file or directory on the file system is required. .. versionadded:: 3.9 + + .. versionchanged:: 3.12 + Added support for *traversable* representing a directory. diff --git a/Doc/library/importlib.rst b/Doc/library/importlib.rst index 1d378dbbdace5d..2402bc5cd3ee2c 100644 --- a/Doc/library/importlib.rst +++ b/Doc/library/importlib.rst @@ -645,6 +645,160 @@ ABC hierarchy:: itself does not end in ``__init__``. +.. class:: ResourceReader + + *Superseded by TraversableResources* + + An :term:`abstract base class` to provide the ability to read + *resources*. + + From the perspective of this ABC, a *resource* is a binary + artifact that is shipped within a package. Typically this is + something like a data file that lives next to the ``__init__.py`` + file of the package. The purpose of this class is to help abstract + out the accessing of such data files so that it does not matter if + the package and its data file(s) are stored in a e.g. zip file + versus on the file system. + + For any of methods of this class, a *resource* argument is + expected to be a :term:`path-like object` which represents + conceptually just a file name. This means that no subdirectory + paths should be included in the *resource* argument. This is + because the location of the package the reader is for, acts as the + "directory". Hence the metaphor for directories and file + names is packages and resources, respectively. This is also why + instances of this class are expected to directly correlate to + a specific package (instead of potentially representing multiple + packages or a module). + + Loaders that wish to support resource reading are expected to + provide a method called ``get_resource_reader(fullname)`` which + returns an object implementing this ABC's interface. If the module + specified by fullname is not a package, this method should return + :const:`None`. An object compatible with this ABC should only be + returned when the specified module is a package. + + .. versionadded:: 3.7 + + .. deprecated-removed:: 3.12 3.14 + Use :class:`importlib.resources.abc.TraversableResources` instead. + + .. abstractmethod:: open_resource(resource) + + Returns an opened, :term:`file-like object` for binary reading + of the *resource*. + + If the resource cannot be found, :exc:`FileNotFoundError` is + raised. + + .. abstractmethod:: resource_path(resource) + + Returns the file system path to the *resource*. + + If the resource does not concretely exist on the file system, + raise :exc:`FileNotFoundError`. + + .. abstractmethod:: is_resource(name) + + Returns ``True`` if the named *name* is considered a resource. + :exc:`FileNotFoundError` is raised if *name* does not exist. + + .. abstractmethod:: contents() + + Returns an :term:`iterable` of strings over the contents of + the package. Do note that it is not required that all names + returned by the iterator be actual resources, e.g. it is + acceptable to return names for which :meth:`is_resource` would + be false. + + Allowing non-resource names to be returned is to allow for + situations where how a package and its resources are stored + are known a priori and the non-resource names would be useful. + For instance, returning subdirectory names is allowed so that + when it is known that the package and resources are stored on + the file system then those subdirectory names can be used + directly. + + The abstract method returns an iterable of no items. + + +.. class:: Traversable + + An object with a subset of :class:`pathlib.Path` methods suitable for + traversing directories and opening files. + + For a representation of the object on the file-system, use + :meth:`importlib.resources.as_file`. + + .. versionadded:: 3.9 + + .. deprecated-removed:: 3.12 3.14 + Use :class:`importlib.resources.abc.Traversable` instead. + + .. attribute:: name + + Abstract. The base name of this object without any parent references. + + .. abstractmethod:: iterdir() + + Yield ``Traversable`` objects in ``self``. + + .. abstractmethod:: is_dir() + + Return ``True`` if ``self`` is a directory. + + .. abstractmethod:: is_file() + + Return ``True`` if ``self`` is a file. + + .. abstractmethod:: joinpath(child) + + Return Traversable child in ``self``. + + .. abstractmethod:: __truediv__(child) + + Return ``Traversable`` child in ``self``. + + .. abstractmethod:: open(mode='r', *args, **kwargs) + + *mode* may be 'r' or 'rb' to open as text or binary. Return a handle + suitable for reading (same as :attr:`pathlib.Path.open`). + + When opening as text, accepts encoding parameters such as those + accepted by :attr:`io.TextIOWrapper`. + + .. method:: read_bytes() + + Read contents of ``self`` as bytes. + + .. method:: read_text(encoding=None) + + Read contents of ``self`` as text. + + +.. class:: TraversableResources + + An abstract base class for resource readers capable of serving + the :meth:`importlib.resources.files` interface. Subclasses + :class:`importlib.resources.abc.ResourceReader` and provides + concrete implementations of the :class:`importlib.resources.abc.ResourceReader`'s + abstract methods. Therefore, any loader supplying + :class:`importlib.abc.TraversableResources` also supplies ResourceReader. + + Loaders that wish to support resource reading are expected to + implement this interface. + + .. versionadded:: 3.9 + + .. deprecated-removed:: 3.12 3.14 + Use :class:`importlib.resources.abc.TraversableResources` instead. + + .. abstractmethod:: files() + + Returns a :class:`importlib.resources.abc.Traversable` object for the loaded + package. + + :mod:`importlib.machinery` -- Importers and path hooks ------------------------------------------------------ @@ -991,7 +1145,7 @@ find and load modules. .. versionadded:: 3.4 -.. class:: NamespaceLoader(name, path, path_finder): +.. class:: NamespaceLoader(name, path, path_finder) A concrete implementation of :class:`importlib.abc.InspectLoader` for namespace packages. This is an alias for a private class and is only made @@ -1270,7 +1424,7 @@ an :term:`importer`. You can get the same effect as this function by implementing the basic interface of multi-phase init (:pep:`489`) and lying about - support for mulitple interpreters (or per-interpreter GIL). + support for multiple interpreters (or per-interpreter GIL). .. warning:: Using this function to disable the check can lead to diff --git a/Doc/library/index.rst b/Doc/library/index.rst index d064b680f9aaa4..0b348ae6f5c8c0 100644 --- a/Doc/library/index.rst +++ b/Doc/library/index.rst @@ -73,5 +73,6 @@ the `Python Package Index `_. language.rst windows.rst unix.rst + cmdline.rst superseded.rst security_warnings.rst diff --git a/Doc/library/inspect.rst b/Doc/library/inspect.rst index 7884308a333020..f8b3e39c4f54f0 100644 --- a/Doc/library/inspect.rst +++ b/Doc/library/inspect.rst @@ -1,6 +1,11 @@ :mod:`inspect` --- Inspect live objects ======================================= +.. testsetup:: * + + import inspect + from inspect import * + .. module:: inspect :synopsis: Extract information and source code from live objects. @@ -268,7 +273,7 @@ attributes (see :ref:`import-mod-attrs` for module attributes): :func:`getmembers` will only return class attributes defined in the metaclass when the argument is a class and those attributes have been - listed in the metaclass' custom :meth:`__dir__`. + listed in the metaclass' custom :meth:`~object.__dir__`. .. function:: getmembers_static(object[, predicate]) @@ -387,7 +392,11 @@ attributes (see :ref:`import-mod-attrs` for module attributes): Return ``True`` if the object can be used in :keyword:`await` expression. Can also be used to distinguish generator-based coroutines from regular - generators:: + generators: + + .. testcode:: + + import types def gen(): yield @@ -404,13 +413,15 @@ attributes (see :ref:`import-mod-attrs` for module attributes): .. function:: isasyncgenfunction(object) Return ``True`` if the object is an :term:`asynchronous generator` function, - for example:: + for example: - >>> async def agen(): - ... yield 1 - ... - >>> inspect.isasyncgenfunction(agen) - True + .. doctest:: + + >>> async def agen(): + ... yield 1 + ... + >>> inspect.isasyncgenfunction(agen) + True .. versionadded:: 3.6 @@ -476,12 +487,13 @@ attributes (see :ref:`import-mod-attrs` for module attributes): has a :meth:`~object.__get__` method but not a :meth:`~object.__set__` method, but beyond that the set of attributes varies. A :attr:`~definition.__name__` attribute is usually - sensible, and :attr:`__doc__` often is. + sensible, and :attr:`!__doc__` often is. Methods implemented via descriptors that also pass one of the other tests return ``False`` from the :func:`ismethoddescriptor` test, simply because the other tests promise more -- you can, e.g., count on having the - :attr:`__func__` attribute (etc) when an object passes :func:`ismethod`. + :attr:`~method.__func__` attribute (etc) when an object passes + :func:`ismethod`. .. function:: isdatadescriptor(object) @@ -492,7 +504,7 @@ attributes (see :ref:`import-mod-attrs` for module attributes): Examples are properties (defined in Python), getsets, and members. The latter two are defined in C and there are more specific tests available for those types, which is robust across Python implementations. Typically, data - descriptors will also have :attr:`~definition.__name__` and :attr:`__doc__` attributes + descriptors will also have :attr:`~definition.__name__` and :attr:`!__doc__` attributes (properties, getsets, and members have both of these attributes), but this is not guaranteed. @@ -614,13 +626,16 @@ Introspecting callables with the Signature object .. versionadded:: 3.3 -The Signature object represents the call signature of a callable object and its -return annotation. To retrieve a Signature object, use the :func:`signature` +The :class:`Signature` object represents the call signature of a callable object +and its return annotation. To retrieve a :class:`!Signature` object, +use the :func:`!signature` function. .. function:: signature(callable, *, follow_wrapped=True, globals=None, locals=None, eval_str=False) - Return a :class:`Signature` object for the given ``callable``:: + Return a :class:`Signature` object for the given *callable*: + + .. doctest:: >>> from inspect import signature >>> def foo(a, *, b:int, **kwargs): @@ -629,10 +644,10 @@ function. >>> sig = signature(foo) >>> str(sig) - '(a, *, b:int, **kwargs)' + '(a, *, b: int, **kwargs)' >>> str(sig.parameters['b']) - 'b:int' + 'b: int' >>> sig.parameters['b'].annotation @@ -640,32 +655,36 @@ function. Accepts a wide range of Python callables, from plain functions and classes to :func:`functools.partial` objects. + If the passed object has a ``__signature__`` attribute, this function + returns it without further computations. + For objects defined in modules using stringized annotations (``from __future__ import annotations``), :func:`signature` will attempt to automatically un-stringize the annotations using - :func:`inspect.get_annotations()`. The - ``global``, ``locals``, and ``eval_str`` parameters are passed - into :func:`inspect.get_annotations()` when resolving the - annotations; see the documentation for :func:`inspect.get_annotations()` + :func:`get_annotations`. The + *globals*, *locals*, and *eval_str* parameters are passed + into :func:`get_annotations` when resolving the + annotations; see the documentation for :func:`get_annotations` for instructions on how to use these parameters. Raises :exc:`ValueError` if no signature can be provided, and :exc:`TypeError` if that type of object is not supported. Also, - if the annotations are stringized, and ``eval_str`` is not false, - the ``eval()`` call(s) to un-stringize the annotations could - potentially raise any kind of exception. + if the annotations are stringized, and *eval_str* is not false, + the ``eval()`` call(s) to un-stringize the annotations in :func:`get_annotations` + could potentially raise any kind of exception. A slash(/) in the signature of a function denotes that the parameters prior to it are positional-only. For more info, see :ref:`the FAQ entry on positional-only parameters `. - .. versionadded:: 3.5 - ``follow_wrapped`` parameter. Pass ``False`` to get a signature of - ``callable`` specifically (``callable.__wrapped__`` will not be used to + .. versionchanged:: 3.5 + The *follow_wrapped* parameter was added. + Pass ``False`` to get a signature of + *callable* specifically (``callable.__wrapped__`` will not be used to unwrap decorated callables.) - .. versionadded:: 3.10 - ``globals``, ``locals``, and ``eval_str`` parameters. + .. versionchanged:: 3.10 + The *globals*, *locals*, and *eval_str* parameters were added. .. note:: @@ -676,7 +695,8 @@ function. .. class:: Signature(parameters=None, *, return_annotation=Signature.empty) - A Signature object represents the call signature of a function and its return + A :class:`!Signature` object represents the call signature of a function + and its return annotation. For each parameter accepted by the function it stores a :class:`Parameter` object in its :attr:`parameters` collection. @@ -686,14 +706,14 @@ function. positional-only first, then positional-or-keyword, and that parameters with defaults follow parameters without defaults. - The optional *return_annotation* argument, can be an arbitrary Python object, - is the "return" annotation of the callable. + The optional *return_annotation* argument can be an arbitrary Python object. + It represents the "return" annotation of the callable. - Signature objects are *immutable*. Use :meth:`Signature.replace` to make a - modified copy. + :class:`!Signature` objects are *immutable*. Use :meth:`Signature.replace` or + :func:`copy.replace` to make a modified copy. .. versionchanged:: 3.5 - Signature objects are picklable and :term:`hashable`. + :class:`!Signature` objects are now picklable and :term:`hashable`. .. attribute:: Signature.empty @@ -730,13 +750,15 @@ function. .. method:: Signature.replace(*[, parameters][, return_annotation]) - Create a new Signature instance based on the instance replace was invoked - on. It is possible to pass different ``parameters`` and/or - ``return_annotation`` to override the corresponding properties of the base - signature. To remove return_annotation from the copied Signature, pass in + Create a new :class:`Signature` instance based on the instance + :meth:`replace` was invoked on. + It is possible to pass different *parameters* and/or + *return_annotation* to override the corresponding properties of the base + signature. To remove ``return_annotation`` from the copied + :class:`!Signature`, pass in :attr:`Signature.empty`. - :: + .. doctest:: >>> def test(a, b): ... pass @@ -746,33 +768,50 @@ function. >>> str(new_sig) "(a, b) -> 'new return anno'" - .. classmethod:: Signature.from_callable(obj, *, follow_wrapped=True, globalns=None, localns=None) + :class:`Signature` objects are also supported by the generic function + :func:`copy.replace`. + + .. method:: format(*, max_width=None) + + Create a string representation of the :class:`Signature` object. + + If *max_width* is passed, the method will attempt to fit + the signature into lines of at most *max_width* characters. + If the signature is longer than *max_width*, + all parameters will be on separate lines. + + .. versionadded:: 3.13 + + .. classmethod:: Signature.from_callable(obj, *, follow_wrapped=True, globals=None, locals=None, eval_str=False) Return a :class:`Signature` (or its subclass) object for a given callable - ``obj``. Pass ``follow_wrapped=False`` to get a signature of ``obj`` - without unwrapping its ``__wrapped__`` chain. ``globalns`` and - ``localns`` will be used as the namespaces when resolving annotations. + *obj*. + + This method simplifies subclassing of :class:`Signature`: - This method simplifies subclassing of :class:`Signature`:: + .. testcode:: - class MySignature(Signature): - pass - sig = MySignature.from_callable(min) - assert isinstance(sig, MySignature) + class MySignature(Signature): + pass + sig = MySignature.from_callable(sum) + assert isinstance(sig, MySignature) + + Its behavior is otherwise identical to that of :func:`signature`. .. versionadded:: 3.5 - .. versionadded:: 3.10 - ``globalns`` and ``localns`` parameters. + .. versionchanged:: 3.10 + The *globals*, *locals*, and *eval_str* parameters were added. .. class:: Parameter(name, kind, *, default=Parameter.empty, annotation=Parameter.empty) - Parameter objects are *immutable*. Instead of modifying a Parameter object, - you can use :meth:`Parameter.replace` to create a modified copy. + :class:`!Parameter` objects are *immutable*. + Instead of modifying a :class:`!Parameter` object, + you can use :meth:`Parameter.replace` or :func:`copy.replace` to create a modified copy. .. versionchanged:: 3.5 - Parameter objects are picklable and :term:`hashable`. + Parameter objects are now picklable and :term:`hashable`. .. attribute:: Parameter.empty @@ -791,7 +830,7 @@ function. expressions. .. versionchanged:: 3.6 - These parameter names are exposed by this module as names like + These parameter names are now exposed by this module as names like ``implicit0``. .. attribute:: Parameter.default @@ -841,7 +880,9 @@ function. | | definition. | +------------------------+----------------------------------------------+ - Example: print all keyword-only arguments without default values:: + Example: print all keyword-only arguments without default values: + + .. doctest:: >>> def foo(a, b, *, c, d=10): ... pass @@ -855,11 +896,13 @@ function. .. attribute:: Parameter.kind.description - Describes a enum value of Parameter.kind. + Describes a enum value of :attr:`Parameter.kind`. .. versionadded:: 3.8 - Example: print all descriptions of arguments:: + Example: print all descriptions of arguments: + + .. doctest:: >>> def foo(a, b, *, c, d=10): ... pass @@ -874,12 +917,12 @@ function. .. method:: Parameter.replace(*[, name][, kind][, default][, annotation]) - Create a new Parameter instance based on the instance replaced was invoked - on. To override a :class:`Parameter` attribute, pass the corresponding + Create a new :class:`Parameter` instance based on the instance replaced was invoked + on. To override a :class:`!Parameter` attribute, pass the corresponding argument. To remove a default value or/and an annotation from a - Parameter, pass :attr:`Parameter.empty`. + :class:`!Parameter`, pass :attr:`Parameter.empty`. - :: + .. doctest:: >>> from inspect import Parameter >>> param = Parameter('foo', Parameter.KEYWORD_ONLY, default=42) @@ -890,10 +933,13 @@ function. 'foo=42' >>> str(param.replace(default=Parameter.empty, annotation='spam')) - "foo:'spam'" + "foo: 'spam'" + + :class:`Parameter` objects are also supported by the generic function + :func:`copy.replace`. .. versionchanged:: 3.4 - In Python 3.3 Parameter objects were allowed to have ``name`` set + In Python 3.3 :class:`Parameter` objects were allowed to have ``name`` set to ``None`` if their ``kind`` was set to ``POSITIONAL_ONLY``. This is no longer permitted. @@ -946,18 +992,20 @@ function. For variable-keyword arguments (``**kwargs``) the default is an empty dict. - :: + .. doctest:: - >>> def foo(a, b='ham', *args): pass - >>> ba = inspect.signature(foo).bind('spam') - >>> ba.apply_defaults() - >>> ba.arguments - {'a': 'spam', 'b': 'ham', 'args': ()} + >>> def foo(a, b='ham', *args): pass + >>> ba = inspect.signature(foo).bind('spam') + >>> ba.apply_defaults() + >>> ba.arguments + {'a': 'spam', 'b': 'ham', 'args': ()} .. versionadded:: 3.5 The :attr:`args` and :attr:`kwargs` properties can be used to invoke - functions:: + functions: + + .. testcode:: def test(a, *, b): ... @@ -1076,20 +1124,22 @@ Classes and functions ``**`` arguments, if any) to their values from *args* and *kwds*. In case of invoking *func* incorrectly, i.e. whenever ``func(*args, **kwds)`` would raise an exception because of incompatible signature, an exception of the same type - and the same or similar message is raised. For example:: - - >>> from inspect import getcallargs - >>> def f(a, b=1, *pos, **named): - ... pass - ... - >>> getcallargs(f, 1, 2, 3) == {'a': 1, 'named': {}, 'b': 2, 'pos': (3,)} - True - >>> getcallargs(f, a=2, x=4) == {'a': 2, 'named': {'x': 4}, 'b': 1, 'pos': ()} - True - >>> getcallargs(f) - Traceback (most recent call last): - ... - TypeError: f() missing 1 required positional argument: 'a' + and the same or similar message is raised. For example: + + .. doctest:: + + >>> from inspect import getcallargs + >>> def f(a, b=1, *pos, **named): + ... pass + ... + >>> getcallargs(f, 1, 2, 3) == {'a': 1, 'named': {}, 'b': 2, 'pos': (3,)} + True + >>> getcallargs(f, a=2, x=4) == {'a': 2, 'named': {'x': 4}, 'b': 1, 'pos': ()} + True + >>> getcallargs(f) + Traceback (most recent call last): + ... + TypeError: f() missing 1 required positional argument: 'a' .. versionadded:: 3.2 @@ -1175,9 +1225,10 @@ Classes and functions * If ``obj`` is a class, ``globals`` defaults to ``sys.modules[obj.__module__].__dict__`` and ``locals`` defaults to the ``obj`` class namespace. - * If ``obj`` is a callable, ``globals`` defaults to ``obj.__globals__``, + * If ``obj`` is a callable, ``globals`` defaults to + :attr:`obj.__globals__ `, although if ``obj`` is a wrapped function (using - ``functools.update_wrapper()``) it is first unwrapped. + :func:`functools.update_wrapper`) it is first unwrapped. Calling ``get_annotations`` is best practice for accessing the annotations dict of any object. See :ref:`annotations-howto` for @@ -1391,7 +1442,8 @@ Fetching attributes statically Both :func:`getattr` and :func:`hasattr` can trigger code execution when fetching or checking for the existence of attributes. Descriptors, like -properties, will be invoked and :meth:`__getattr__` and :meth:`__getattribute__` +properties, will be invoked and :meth:`~object.__getattr__` and +:meth:`~object.__getattribute__` may be called. For cases where you want passive introspection, like documentation tools, this @@ -1401,7 +1453,8 @@ but avoids executing code when it fetches attributes. .. function:: getattr_static(obj, attr, default=None) Retrieve attributes without triggering dynamic lookup via the - descriptor protocol, :meth:`__getattr__` or :meth:`__getattribute__`. + descriptor protocol, :meth:`~object.__getattr__` + or :meth:`~object.__getattribute__`. Note: this function may not be able to retrieve all attributes that getattr can fetch (like dynamically created attributes) @@ -1458,10 +1511,11 @@ generator to be determined easily. Get current state of a generator-iterator. Possible states are: - * GEN_CREATED: Waiting to start execution. - * GEN_RUNNING: Currently being executed by the interpreter. - * GEN_SUSPENDED: Currently suspended at a yield expression. - * GEN_CLOSED: Execution has completed. + + * GEN_CREATED: Waiting to start execution. + * GEN_RUNNING: Currently being executed by the interpreter. + * GEN_SUSPENDED: Currently suspended at a yield expression. + * GEN_CLOSED: Execution has completed. .. versionadded:: 3.2 @@ -1473,10 +1527,11 @@ generator to be determined easily. ``cr_frame`` attributes. Possible states are: - * CORO_CREATED: Waiting to start execution. - * CORO_RUNNING: Currently being executed by the interpreter. - * CORO_SUSPENDED: Currently suspended at an await expression. - * CORO_CLOSED: Execution has completed. + + * CORO_CREATED: Waiting to start execution. + * CORO_RUNNING: Currently being executed by the interpreter. + * CORO_SUSPENDED: Currently suspended at an await expression. + * CORO_CLOSED: Execution has completed. .. versionadded:: 3.5 @@ -1489,10 +1544,11 @@ generator to be determined easily. ``ag_running`` and ``ag_frame`` attributes. Possible states are: - * AGEN_CREATED: Waiting to start execution. - * AGEN_RUNNING: Currently being executed by the interpreter. - * AGEN_SUSPENDED: Currently suspended at a yield expression. - * AGEN_CLOSED: Execution has completed. + + * AGEN_CREATED: Waiting to start execution. + * AGEN_RUNNING: Currently being executed by the interpreter. + * AGEN_SUSPENDED: Currently suspended at a yield expression. + * AGEN_CLOSED: Execution has completed. .. versionadded:: 3.12 @@ -1541,8 +1597,8 @@ updated as expected: Code Objects Bit Flags ---------------------- -Python code objects have a ``co_flags`` attribute, which is a bitmap of -the following flags: +Python code objects have a :attr:`~codeobject.co_flags` attribute, +which is a bitmap of the following flags: .. data:: CO_OPTIMIZED @@ -1550,8 +1606,8 @@ the following flags: .. data:: CO_NEWLOCALS - If set, a new dict will be created for the frame's ``f_locals`` when - the code object is executed. + If set, a new dict will be created for the frame's :attr:`~frame.f_locals` + when the code object is executed. .. data:: CO_VARARGS @@ -1650,6 +1706,6 @@ By default, accepts the name of a module and prints the source of that module. A class or function within the module can be printed instead by appended a colon and the qualified name of the target object. -.. cmdoption:: --details +.. option:: --details Print information about the specified object rather than the source code diff --git a/Doc/library/io.rst b/Doc/library/io.rst index 7eec1f87583b87..6736aa9ee2b0ef 100644 --- a/Doc/library/io.rst +++ b/Doc/library/io.rst @@ -38,9 +38,9 @@ location), or only sequential access (for example in the case of a socket or pipe). All streams are careful about the type of data you give to them. For example -giving a :class:`str` object to the ``write()`` method of a binary stream +giving a :class:`str` object to the :meth:`!write` method of a binary stream will raise a :exc:`TypeError`. So will giving a :class:`bytes` object to the -``write()`` method of a text stream. +:meth:`!write` method of a text stream. .. versionchanged:: 3.3 Operations that used to raise :exc:`IOError` now raise :exc:`OSError`, since @@ -146,7 +146,7 @@ Opt-in EncodingWarning See :pep:`597` for more details. To find where the default locale encoding is used, you can enable -the ``-X warn_default_encoding`` command line option or set the +the :option:`-X warn_default_encoding <-X>` command line option or set the :envvar:`PYTHONWARNDEFAULTENCODING` environment variable, which will emit an :exc:`EncodingWarning` when the default encoding is used. @@ -175,7 +175,7 @@ High-level Module Interface .. audit-event:: open path,mode,flags io.open This function raises an :ref:`auditing event ` ``open`` with - arguments ``path``, ``mode`` and ``flags``. The ``mode`` and ``flags`` + arguments *path*, *mode* and *flags*. The *mode* and *flags* arguments may have been modified or inferred from the original call. @@ -184,10 +184,10 @@ High-level Module Interface Opens the provided file with mode ``'rb'``. This function should be used when the intent is to treat the contents as executable code. - ``path`` should be a :class:`str` and an absolute path. + *path* should be a :class:`str` and an absolute path. The behavior of this function may be overridden by an earlier call to the - :c:func:`PyFile_SetOpenCodeHook`. However, assuming that ``path`` is a + :c:func:`PyFile_SetOpenCodeHook`. However, assuming that *path* is a :class:`str` and an absolute path, ``open_code(path)`` should always behave the same as ``open(path, 'rb')``. Overriding the behavior is intended for additional validation or preprocessing of the file. @@ -253,12 +253,12 @@ The implementation of I/O streams is organized as a hierarchy of classes. First specify the various categories of streams, then concrete classes providing the standard stream implementations. - .. note:: +.. note:: - The abstract base classes also provide default implementations of some - methods in order to help implementation of concrete stream classes. For - example, :class:`BufferedIOBase` provides unoptimized implementations of - :meth:`~IOBase.readinto` and :meth:`~IOBase.readline`. + The abstract base classes also provide default implementations of some + methods in order to help implementation of concrete stream classes. For + example, :class:`BufferedIOBase` provides unoptimized implementations of + :meth:`!readinto` and :meth:`!readline`. At the top of the I/O hierarchy is the abstract base class :class:`IOBase`. It defines the basic interface to a stream. Note, however, that there is no @@ -320,8 +320,8 @@ I/O Base Classes implementations represent a file that cannot be read, written or seeked. - Even though :class:`IOBase` does not declare :meth:`read` - or :meth:`write` because their signatures will vary, implementations and + Even though :class:`IOBase` does not declare :meth:`!read` + or :meth:`!write` because their signatures will vary, implementations and clients should consider those methods part of the interface. Also, implementations may raise a :exc:`ValueError` (or :exc:`UnsupportedOperation`) when operations they do not support are called. @@ -379,8 +379,8 @@ I/O Base Classes .. method:: readable() - Return ``True`` if the stream can be read from. If ``False``, :meth:`read` - will raise :exc:`OSError`. + Return ``True`` if the stream can be read from. + If ``False``, :meth:`!read` will raise :exc:`OSError`. .. method:: readline(size=-1, /) @@ -401,25 +401,24 @@ I/O Base Classes hint. Note that it's already possible to iterate on file objects using ``for - line in file: ...`` without calling ``file.readlines()``. + line in file: ...`` without calling :meth:`!file.readlines`. - .. method:: seek(offset, whence=SEEK_SET, /) + .. method:: seek(offset, whence=os.SEEK_SET, /) - Change the stream position to the given byte *offset*. *offset* is - interpreted relative to the position indicated by *whence*. The default - value for *whence* is :data:`SEEK_SET`. Values for *whence* are: + Change the stream position to the given byte *offset*, + interpreted relative to the position indicated by *whence*, + and return the new absolute position. + Values for *whence* are: - * :data:`SEEK_SET` or ``0`` -- start of the stream (the default); + * :data:`os.SEEK_SET` or ``0`` -- start of the stream (the default); *offset* should be zero or positive - * :data:`SEEK_CUR` or ``1`` -- current stream position; *offset* may - be negative - * :data:`SEEK_END` or ``2`` -- end of the stream; *offset* is usually - negative - - Return the new absolute position. + * :data:`os.SEEK_CUR` or ``1`` -- current stream position; + *offset* may be negative + * :data:`os.SEEK_END` or ``2`` -- end of the stream; + *offset* is usually negative .. versionadded:: 3.1 - The ``SEEK_*`` constants. + The :data:`!SEEK_*` constants. .. versionadded:: 3.3 Some operating systems could support additional values, like @@ -450,7 +449,7 @@ I/O Base Classes .. method:: writable() Return ``True`` if the stream supports writing. If ``False``, - :meth:`write` and :meth:`truncate` will raise :exc:`OSError`. + :meth:`!write` and :meth:`truncate` will raise :exc:`OSError`. .. method:: writelines(lines, /) @@ -654,8 +653,9 @@ Raw File I/O implies writing, so this mode behaves in a similar way to ``'w'``. Add a ``'+'`` to the mode to allow simultaneous reading and writing. - The :meth:`read` (when called with a positive argument), :meth:`readinto` - and :meth:`write` methods on this class will only make one system call. + The :meth:`~RawIOBase.read` (when called with a positive argument), + :meth:`~RawIOBase.readinto` and :meth:`~RawIOBase.write` methods on this + class will only make one system call. A custom opener can be used by passing a callable as *opener*. The underlying file descriptor for the file object is then obtained by calling *opener* with @@ -791,8 +791,8 @@ than raw I/O does. object under various conditions, including: * when the buffer gets too small for all pending data; - * when :meth:`flush()` is called; - * when a :meth:`seek()` is requested (for :class:`BufferedRandom` objects); + * when :meth:`flush` is called; + * when a :meth:`~IOBase.seek` is requested (for :class:`BufferedRandom` objects); * when the :class:`BufferedWriter` object is closed or destroyed. The constructor creates a :class:`BufferedWriter` for the given writeable @@ -826,8 +826,8 @@ than raw I/O does. :data:`DEFAULT_BUFFER_SIZE`. :class:`BufferedRandom` is capable of anything :class:`BufferedReader` or - :class:`BufferedWriter` can do. In addition, :meth:`seek` and :meth:`tell` - are guaranteed to be implemented. + :class:`BufferedWriter` can do. In addition, :meth:`~IOBase.seek` and + :meth:`~IOBase.tell` are guaranteed to be implemented. .. class:: BufferedRWPair(reader, writer, buffer_size=DEFAULT_BUFFER_SIZE, /) @@ -904,7 +904,7 @@ Text I/O .. method:: readline(size=-1, /) - Read until newline or EOF and return a single ``str``. If the stream is + Read until newline or EOF and return a single :class:`str`. If the stream is already at EOF, an empty string is returned. If *size* is specified, at most *size* characters will be read. @@ -913,22 +913,22 @@ Text I/O Change the stream position to the given *offset*. Behaviour depends on the *whence* parameter. The default value for *whence* is - :data:`SEEK_SET`. + :data:`!SEEK_SET`. - * :data:`SEEK_SET` or ``0``: seek from the start of the stream + * :data:`!SEEK_SET` or ``0``: seek from the start of the stream (the default); *offset* must either be a number returned by :meth:`TextIOBase.tell`, or zero. Any other *offset* value produces undefined behaviour. - * :data:`SEEK_CUR` or ``1``: "seek" to the current position; + * :data:`!SEEK_CUR` or ``1``: "seek" to the current position; *offset* must be zero, which is a no-operation (all other values are unsupported). - * :data:`SEEK_END` or ``2``: seek to the end of the stream; + * :data:`!SEEK_END` or ``2``: seek to the end of the stream; *offset* must be zero (all other values are unsupported). Return the new absolute position as an opaque number. .. versionadded:: 3.1 - The ``SEEK_*`` constants. + The :data:`!SEEK_*` constants. .. method:: tell() @@ -988,10 +988,10 @@ Text I/O takes place. If *newline* is any of the other legal values, any ``'\n'`` characters written are translated to the given string. - If *line_buffering* is ``True``, :meth:`flush` is implied when a call to + If *line_buffering* is ``True``, :meth:`~IOBase.flush` is implied when a call to write contains a newline character or a carriage return. - If *write_through* is ``True``, calls to :meth:`write` are guaranteed + If *write_through* is ``True``, calls to :meth:`~BufferedIOBase.write` are guaranteed not to be buffered: any data written on the :class:`TextIOWrapper` object is immediately handled to its underlying binary *buffer*. @@ -1043,6 +1043,33 @@ Text I/O .. versionchanged:: 3.11 The method supports ``encoding="locale"`` option. + .. method:: seek(cookie, whence=os.SEEK_SET, /) + + Set the stream position. + Return the new stream position as an :class:`int`. + + Four operations are supported, + given by the following argument combinations: + + * ``seek(0, SEEK_SET)``: Rewind to the start of the stream. + * ``seek(cookie, SEEK_SET)``: Restore a previous position; + *cookie* **must be** a number returned by :meth:`tell`. + * ``seek(0, SEEK_END)``: Fast-forward to the end of the stream. + * ``seek(0, SEEK_CUR)``: Leave the current stream position unchanged. + + Any other argument combinations are invalid, + and may raise exceptions. + + .. seealso:: + + :data:`os.SEEK_SET`, :data:`os.SEEK_CUR`, and :data:`os.SEEK_END`. + + .. method:: tell() + + Return the stream position as an opaque number. + The return value of :meth:`!tell` can be given as input to :meth:`seek`, + to restore a previous stream position. + .. class:: StringIO(initial_value='', newline='\n') @@ -1070,7 +1097,7 @@ Text I/O .. method:: getvalue() - Return a ``str`` containing the entire contents of the buffer. + Return a :class:`str` containing the entire contents of the buffer. Newlines are decoded as if by :meth:`~TextIOBase.read`, although the stream position is not changed. @@ -1125,7 +1152,7 @@ Text I/O over a binary storage (such as a file) is significantly slower than binary I/O over the same storage, because it requires conversions between unicode and binary data using a character codec. This can become noticeable handling huge amounts of text data like large log files. Also, -:meth:`TextIOWrapper.tell` and :meth:`TextIOWrapper.seek` are both quite slow +:meth:`~TextIOBase.tell` and :meth:`~TextIOBase.seek` are both quite slow due to the reconstruction algorithm used. :class:`StringIO`, however, is a native in-memory unicode container and will @@ -1135,7 +1162,7 @@ Multi-threading ^^^^^^^^^^^^^^^ :class:`FileIO` objects are thread-safe to the extent that the operating system -calls (such as ``read(2)`` under Unix) they wrap are thread-safe too. +calls (such as :manpage:`read(2)` under Unix) they wrap are thread-safe too. Binary buffered objects (instances of :class:`BufferedReader`, :class:`BufferedWriter`, :class:`BufferedRandom` and :class:`BufferedRWPair`) diff --git a/Doc/library/ipaddress.rst b/Doc/library/ipaddress.rst index 9c2dff55703273..1de36b643c4dca 100644 --- a/Doc/library/ipaddress.rst +++ b/Doc/library/ipaddress.rst @@ -219,6 +219,13 @@ write code that handles both IP versions correctly. Address objects are ``True`` if the address is reserved for link-local usage. See :RFC:`3927`. + .. attribute:: ipv6_mapped + + :class:`IPv4Address` object representing the IPv4-mapped IPv6 address. See :RFC:`4291`. + + .. versionadded:: 3.13 + + .. _iana-ipv4-special-registry: https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml .. _iana-ipv6-special-registry: https://www.iana.org/assignments/iana-ipv6-special-registry/iana-ipv6-special-registry.xhtml diff --git a/Doc/library/itertools.rst b/Doc/library/itertools.rst index 730736bbb59ed9..338a5f9615aae3 100644 --- a/Doc/library/itertools.rst +++ b/Doc/library/itertools.rst @@ -41,7 +41,7 @@ operator can be mapped across two vectors to form an efficient dot-product: ================== ================= ================================================= ========================================= Iterator Arguments Results Example ================== ================= ================================================= ========================================= -:func:`count` start, [step] start, start+step, start+2*step, ... ``count(10) --> 10 11 12 13 14 ...`` +:func:`count` [start[, step]] start, start+step, start+2*step, ... ``count(10) --> 10 11 12 13 14 ...`` :func:`cycle` p p0, p1, ... plast, p0, p1, ... ``cycle('ABCD') --> A B C D A B C D ...`` :func:`repeat` elem [,n] elem, elem, elem, ... endlessly or up to n times ``repeat(10, 3) --> 10 10 10`` ================== ================= ================================================= ========================================= @@ -164,11 +164,14 @@ loops that truncate the stream. Added the optional *initial* parameter. -.. function:: batched(iterable, n) +.. function:: batched(iterable, n, *, strict=False) Batch data from the *iterable* into tuples of length *n*. The last batch may be shorter than *n*. + If *strict* is true, will raise a :exc:`ValueError` if the final + batch is shorter than *n*. + Loops over the input iterable and accumulates data into tuples up to size *n*. The input is consumed lazily, just enough to fill a batch. The result is yielded as soon as the batch is full or when the input @@ -190,16 +193,21 @@ loops that truncate the stream. Roughly equivalent to:: - def batched(iterable, n): + def batched(iterable, n, *, strict=False): # batched('ABCDEFG', 3) --> ABC DEF G if n < 1: raise ValueError('n must be at least one') it = iter(iterable) while batch := tuple(islice(it, n)): + if strict and len(batch) != n: + raise ValueError('batched(): incomplete batch') yield batch .. versionadded:: 3.12 + .. versionchanged:: 3.13 + Added the *strict* option. + .. function:: chain(*iterables) @@ -795,13 +803,13 @@ which incur interpreter overhead. import random def take(n, iterable): - "Return first n items of the iterable as a list" + "Return first n items of the iterable as a list." return list(islice(iterable, n)) - def prepend(value, iterator): - "Prepend a single value in front of an iterator" + def prepend(value, iterable): + "Prepend a single value in front of an iterable." # prepend(1, [2, 3, 4]) --> 1 2 3 4 - return chain([value], iterator) + return chain([value], iterable) def tabulate(function, start=0): "Return function(0), function(1), ..." @@ -817,15 +825,15 @@ which incur interpreter overhead. return starmap(func, repeat(args, times)) def flatten(list_of_lists): - "Flatten one level of nesting" + "Flatten one level of nesting." return chain.from_iterable(list_of_lists) def ncycles(iterable, n): - "Returns the sequence elements n times" + "Returns the sequence elements n times." return chain.from_iterable(repeat(tuple(iterable), n)) def tail(n, iterable): - "Return an iterator over the last n items" + "Return an iterator over the last n items." # tail(3, 'ABCDEFG') --> E F G return iter(collections.deque(iterable, maxlen=n)) @@ -840,15 +848,15 @@ which incur interpreter overhead. next(islice(iterator, n, n), None) def nth(iterable, n, default=None): - "Returns the nth item or a default value" + "Returns the nth item or a default value." return next(islice(iterable, n, None), default) def quantify(iterable, pred=bool): - "Count how many times the predicate is True" + "Given a predicate that returns True or False, count the True results." return sum(map(pred, iterable)) def all_equal(iterable): - "Returns True if all the elements are equal to each other" + "Returns True if all the elements are equal to each other." g = groupby(iterable) return next(g, True) and not next(g, False) @@ -865,68 +873,52 @@ which incur interpreter overhead. # first_true([a,b], x, f) --> a if f(a) else b if f(b) else x return next(filter(pred, iterable), default) - def iter_index(iterable, value, start=0): + def unique_everseen(iterable, key=None): + "List unique elements, preserving order. Remember all elements ever seen." + # unique_everseen('AAAABBBCCDAABBB') --> A B C D + # unique_everseen('ABBcCAD', str.casefold) --> A B c D + seen = set() + if key is None: + for element in filterfalse(seen.__contains__, iterable): + seen.add(element) + yield element + else: + for element in iterable: + k = key(element) + if k not in seen: + seen.add(k) + yield element + + def unique_justseen(iterable, key=None): + "List unique elements, preserving order. Remember only the element just seen." + # unique_justseen('AAAABBBCCDAABBB') --> A B C D A B + # unique_justseen('ABBcCAD', str.casefold) --> A B c A D + if key is None: + return map(operator.itemgetter(0), groupby(iterable)) + return map(next, map(operator.itemgetter(1), groupby(iterable, key))) + + def iter_index(iterable, value, start=0, stop=None): "Return indices where a value occurs in a sequence or iterable." # iter_index('AABCADEAF', 'A') --> 0 1 4 7 - try: - seq_index = iterable.index - except AttributeError: + seq_index = getattr(iterable, 'index', None) + if seq_index is None: # Slow path for general iterables - it = islice(iterable, start, None) - i = start - 1 - try: - while True: - yield (i := i + operator.indexOf(it, value) + 1) - except ValueError: - pass + it = islice(iterable, start, stop) + for i, element in enumerate(it, start): + if element is value or element == value: + yield i else: # Fast path for sequences + stop = len(iterable) if stop is None else stop i = start - 1 try: while True: - yield (i := seq_index(value, i+1)) + yield (i := seq_index(value, i+1, stop)) except ValueError: pass - def iter_except(func, exception, first=None): - """ Call a function repeatedly until an exception is raised. - - Converts a call-until-exception interface to an iterator interface. - Like builtins.iter(func, sentinel) but uses an exception instead - of a sentinel to end the loop. - - Examples: - iter_except(functools.partial(heappop, h), IndexError) # priority queue iterator - iter_except(d.popitem, KeyError) # non-blocking dict iterator - iter_except(d.popleft, IndexError) # non-blocking deque iterator - iter_except(q.get_nowait, Queue.Empty) # loop over a producer Queue - iter_except(s.pop, KeyError) # non-blocking set iterator - - """ - try: - if first is not None: - yield first() # For database APIs needing an initial cast to db.first() - while True: - yield func() - except exception: - pass - - def grouper(iterable, n, *, incomplete='fill', fillvalue=None): - "Collect data into non-overlapping fixed-length chunks or blocks" - # grouper('ABCDEFG', 3, fillvalue='x') --> ABC DEF Gxx - # grouper('ABCDEFG', 3, incomplete='strict') --> ABC DEF ValueError - # grouper('ABCDEFG', 3, incomplete='ignore') --> ABC DEF - args = [iter(iterable)] * n - if incomplete == 'fill': - return zip_longest(*args, fillvalue=fillvalue) - if incomplete == 'strict': - return zip(*args, strict=True) - if incomplete == 'ignore': - return zip(*args) - else: - raise ValueError('Expected fill, strict, or ignore') - def sliding_window(iterable, n): + "Collect data into overlapping fixed-length chunks or blocks." # sliding_window('ABCDEFG', 4) --> ABCD BCDE CDEF DEFG it = iter(iterable) window = collections.deque(islice(it, n-1), maxlen=n) @@ -934,8 +926,25 @@ which incur interpreter overhead. window.append(x) yield tuple(window) + def grouper(iterable, n, *, incomplete='fill', fillvalue=None): + "Collect data into non-overlapping fixed-length chunks or blocks." + # grouper('ABCDEFG', 3, fillvalue='x') --> ABC DEF Gxx + # grouper('ABCDEFG', 3, incomplete='strict') --> ABC DEF ValueError + # grouper('ABCDEFG', 3, incomplete='ignore') --> ABC DEF + args = [iter(iterable)] * n + match incomplete: + case 'fill': + return zip_longest(*args, fillvalue=fillvalue) + case 'strict': + return zip(*args, strict=True) + case 'ignore': + return zip(*args) + case _: + raise ValueError('Expected fill, strict, or ignore') + def roundrobin(*iterables): - "roundrobin('ABC', 'D', 'EF') --> A D E B F C" + "Visit input iterables in a cycle until each is exhausted." + # roundrobin('ABC', 'D', 'EF') --> A D E B F C # Recipe credited to George Sakkis num_active = len(iterables) nexts = cycle(iter(it).__next__ for it in iterables) @@ -958,11 +967,43 @@ which incur interpreter overhead. return filterfalse(pred, t1), filter(pred, t2) def subslices(seq): - "Return all contiguous non-empty subslices of a sequence" + "Return all contiguous non-empty subslices of a sequence." # subslices('ABCD') --> A AB ABC ABCD B BC BCD C CD D slices = starmap(slice, combinations(range(len(seq) + 1), 2)) return map(operator.getitem, repeat(seq), slices) + def iter_except(func, exception, first=None): + """ Call a function repeatedly until an exception is raised. + + Converts a call-until-exception interface to an iterator interface. + Like builtins.iter(func, sentinel) but uses an exception instead + of a sentinel to end the loop. + + Priority queue iterator: + iter_except(functools.partial(heappop, h), IndexError) + + Non-blocking dictionary iterator: + iter_except(d.popitem, KeyError) + + Non-blocking deque iterator: + iter_except(d.popleft, IndexError) + + Non-blocking iterator over a producer Queue: + iter_except(q.get_nowait, Queue.Empty) + + Non-blocking set iterator: + iter_except(s.pop, KeyError) + + """ + try: + if first is not None: + # For database APIs needing an initial call to db.first() + yield first() + while True: + yield func() + except exception: + pass + def before_and_after(predicate, it): """ Variant of takewhile() that allows complete access to the remainder of the iterator. @@ -974,12 +1015,12 @@ which incur interpreter overhead. >>> ''.join(remainder) # takewhile() would lose the 'd' 'dEfGhI' - Note that the first iterator must be fully - consumed before the second iterator can - generate valid results. + Note that the true iterator must be fully consumed + before the remainder iterator can generate valid results. """ it = iter(it) transition = [] + def true_iterator(): for elem in it: if predicate(elem): @@ -987,39 +1028,8 @@ which incur interpreter overhead. else: transition.append(elem) return - def remainder_iterator(): - yield from transition - yield from it - return true_iterator(), remainder_iterator() - - def unique_everseen(iterable, key=None): - "List unique elements, preserving order. Remember all elements ever seen." - # unique_everseen('AAAABBBCCDAABBB') --> A B C D - # unique_everseen('ABBcCAD', str.lower) --> A B c D - seen = set() - if key is None: - for element in filterfalse(seen.__contains__, iterable): - seen.add(element) - yield element - # For order preserving deduplication, - # a faster but non-lazy solution is: - # yield from dict.fromkeys(iterable) - else: - for element in iterable: - k = key(element) - if k not in seen: - seen.add(k) - yield element - # For use cases that allow the last matching element to be returned, - # a faster but non-lazy solution is: - # t1, t2 = tee(iterable) - # yield from dict(zip(map(key, t1), t2)).values() - def unique_justseen(iterable, key=None): - "List unique elements, preserving order. Remember only the element just seen." - # unique_justseen('AAAABBBCCDAABBB') --> A B C D A B - # unique_justseen('ABBcCAD', str.lower) --> A B c A D - return map(next, map(operator.itemgetter(1), groupby(iterable, key))) + return true_iterator(), chain(transition, it) The following recipes have a more mathematical flavor: @@ -1031,42 +1041,20 @@ The following recipes have a more mathematical flavor: s = list(iterable) return chain.from_iterable(combinations(s, r) for r in range(len(s)+1)) - def sieve(n): - "Primes less than n." - # sieve(30) --> 2 3 5 7 11 13 17 19 23 29 - data = bytearray((0, 1)) * (n // 2) - data[:3] = 0, 0, 0 - limit = math.isqrt(n) + 1 - for p in compress(range(limit), data): - data[p*p : n : p+p] = bytes(len(range(p*p, n, p+p))) - data[2] = 1 - return iter_index(data, 1) if n > 2 else iter([]) - - def factor(n): - "Prime factors of n." - # factor(99) --> 3 3 11 - # factor(1_000_000_000_000_007) --> 47 59 360620266859 - # factor(1_000_000_000_000_403) --> 1000000000000403 - for prime in sieve(math.isqrt(n) + 1): - while True: - if n % prime: - break - yield prime - n //= prime - if n == 1: - return - if n > 1: - yield n - def sum_of_squares(it): "Add up the squares of the input values." # sum_of_squares([10, 20, 30]) -> 1400 return math.sumprod(*tee(it)) - def transpose(it): - "Swap the rows and columns of the input." + def reshape(matrix, cols): + "Reshape a 2-D matrix to have a given number of columns." + # reshape([(0, 1), (2, 3), (4, 5)], 3) --> (0, 1, 2), (3, 4, 5) + return batched(chain.from_iterable(matrix), cols, strict=True) + + def transpose(matrix): + "Swap the rows and columns of a 2-D matrix." # transpose([(1, 2, 3), (11, 22, 33)]) --> (1, 11) (2, 22) (3, 33) - return zip(*it, strict=True) + return zip(*matrix, strict=True) def matmul(m1, m2): "Multiply two matrices." @@ -1075,14 +1063,21 @@ The following recipes have a more mathematical flavor: return batched(starmap(math.sumprod, product(m1, transpose(m2))), n) def convolve(signal, kernel): - """Linear convolution of two iterables. + """Discrete linear convolution of two iterables. + + The kernel is fully consumed before the calculations begin. + The signal is consumed lazily and can be infinite. + + Convolutions are mathematically commutative. + If the signal and kernel are swapped, + the output will be the same. Article: https://betterexplained.com/articles/intuitive-convolution/ Video: https://www.youtube.com/watch?v=KuXjwB4LzSA """ # convolve(data, [0.25, 0.25, 0.25, 0.25]) --> Moving average (blur) - # convolve(data, [1, -1]) --> 1st finite difference (1st derivative) - # convolve(data, [1, -2, 1]) --> 2nd finite difference (2nd derivative) + # convolve(data, [1/2, 0, -1/2]) --> 1st derivative estimate + # convolve(data, [1, -2, 1]) --> 2nd derivative estimate kernel = tuple(kernel)[::-1] n = len(kernel) padded_signal = chain(repeat(0, n-1), signal, repeat(0, n-1)) @@ -1106,8 +1101,8 @@ The following recipes have a more mathematical flavor: # Evaluate x³ -4x² -17x + 60 at x = 2.5 # polynomial_eval([1, -4, -17, 60], x=2.5) --> 8.125 n = len(coefficients) - if n == 0: - return x * 0 # coerce zero to the type of x + if not n: + return type(x)(0) powers = map(pow, repeat(x), reversed(range(n))) return math.sumprod(coefficients, powers) @@ -1122,23 +1117,41 @@ The following recipes have a more mathematical flavor: powers = reversed(range(1, n)) return list(map(operator.mul, coefficients, powers)) - def nth_combination(iterable, r, index): - "Equivalent to list(combinations(iterable, r))[index]" - pool = tuple(iterable) - n = len(pool) - c = math.comb(n, r) - if index < 0: - index += c - if index < 0 or index >= c: - raise IndexError - result = [] - while r: - c, n, r = c*r//n, n-1, r-1 - while index >= c: - index -= c - c, n = c*(n-r)//n, n-1 - result.append(pool[-1-n]) - return tuple(result) + def sieve(n): + "Primes less than n." + # sieve(30) --> 2 3 5 7 11 13 17 19 23 29 + if n > 2: + yield 2 + start = 3 + data = bytearray((0, 1)) * (n // 2) + limit = math.isqrt(n) + 1 + for p in iter_index(data, 1, start, limit): + yield from iter_index(data, 1, start, p*p) + data[p*p : n : p+p] = bytes(len(range(p*p, n, p+p))) + start = p*p + yield from iter_index(data, 1, start) + + def factor(n): + "Prime factors of n." + # factor(99) --> 3 3 11 + # factor(1_000_000_000_000_007) --> 47 59 360620266859 + # factor(1_000_000_000_000_403) --> 1000000000000403 + for prime in sieve(math.isqrt(n) + 1): + while not n % prime: + yield prime + n //= prime + if n == 1: + return + if n > 1: + yield n + + def totient(n): + "Count of natural numbers up to n that are coprime to n." + # https://mathworld.wolfram.com/TotientFunction.html + # totient(12) --> 4 because len([1, 5, 7, 11]) == 4 + for p in unique_justseen(factor(n)): + n -= n // p + return n .. doctest:: @@ -1256,6 +1269,26 @@ The following recipes have a more mathematical flavor: >>> sum_of_squares([10, 20, 30]) 1400 + >>> list(reshape([(0, 1), (2, 3), (4, 5)], 3)) + [(0, 1, 2), (3, 4, 5)] + >>> M = [(0, 1, 2, 3), (4, 5, 6, 7), (8, 9, 10, 11)] + >>> list(reshape(M, 1)) + [(0,), (1,), (2,), (3,), (4,), (5,), (6,), (7,), (8,), (9,), (10,), (11,)] + >>> list(reshape(M, 2)) + [(0, 1), (2, 3), (4, 5), (6, 7), (8, 9), (10, 11)] + >>> list(reshape(M, 3)) + [(0, 1, 2), (3, 4, 5), (6, 7, 8), (9, 10, 11)] + >>> list(reshape(M, 4)) + [(0, 1, 2, 3), (4, 5, 6, 7), (8, 9, 10, 11)] + >>> list(reshape(M, 5)) + Traceback (most recent call last): + ... + ValueError: batched(): incomplete batch + >>> list(reshape(M, 6)) + [(0, 1, 2, 3, 4, 5), (6, 7, 8, 9, 10, 11)] + >>> list(reshape(M, 12)) + [(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11)] + >>> list(transpose([(1, 2, 3), (11, 22, 33)])) [(1, 11), (2, 22), (3, 33)] @@ -1297,7 +1330,7 @@ The following recipes have a more mathematical flavor: >>> polynomial_eval([], Fraction(2, 3)) Fraction(0, 1) >>> polynomial_eval([], Decimal('1.75')) - Decimal('0.00') + Decimal('0') >>> polynomial_eval([11], 7) == 11 True >>> polynomial_eval([11, 2], 7) == 11 * 7 + 2 @@ -1333,6 +1366,31 @@ The following recipes have a more mathematical flavor: [] >>> list(iter_index(iter('AABCADEAF'), 'A', 10)) [] + >>> list(iter_index('AABCADEAF', 'A', 1, 7)) + [1, 4] + >>> list(iter_index(iter('AABCADEAF'), 'A', 1, 7)) + [1, 4] + >>> # Verify that ValueErrors not swallowed (gh-107208) + >>> def assert_no_value(iterable, forbidden_value): + ... for item in iterable: + ... if item == forbidden_value: + ... raise ValueError + ... yield item + ... + >>> list(iter_index(assert_no_value('AABCADEAF', 'B'), 'A')) + Traceback (most recent call last): + ... + ValueError + >>> # Verify that both paths can find identical NaN values + >>> x = float('NaN') + >>> y = float('NaN') + >>> list(iter_index([0, x, x, y, 0], x)) + [1, 2] + >>> list(iter_index(iter([0, x, x, y, 0]), x)) + [1, 2] + >>> # Test list input. Lists do not support None for the stop argument + >>> list(iter_index(list('AABCADEAF'), 'A')) + [0, 1, 4, 7] >>> list(sieve(30)) [2, 3, 5, 7, 11, 13, 17, 19, 23, 29] @@ -1398,6 +1456,25 @@ The following recipes have a more mathematical flavor: >>> all(list(factor(n)) == sorted(factor(n)) for n in range(2_000)) True + >>> totient(0) # https://www.wolframalpha.com/input?i=totient+0 + 0 + >>> first_totients = [1, 1, 2, 2, 4, 2, 6, 4, 6, 4, 10, 4, 12, 6, 8, 8, 16, 6, + ... 18, 8, 12, 10, 22, 8, 20, 12, 18, 12, 28, 8, 30, 16, 20, 16, 24, 12, 36, 18, + ... 24, 16, 40, 12, 42, 20, 24, 22, 46, 16, 42, 20, 32, 24, 52, 18, 40, 24, 36, + ... 28, 58, 16, 60, 30, 36, 32, 48, 20, 66, 32, 44] # https://oeis.org/A000010 + ... + >>> list(map(totient, range(1, 70))) == first_totients + True + >>> reference_totient = lambda n: sum(math.gcd(t, n) == 1 for t in range(1, n+1)) + >>> all(totient(n) == reference_totient(n) for n in range(1000)) + True + >>> totient(128_884_753_939) == 128_884_753_938 # large prime + True + >>> totient(999953 * 999983) == 999952 * 999982 # large semiprime + True + >>> totient(6 ** 20) == 1 * 2**19 * 2 * 3**19 # repeated primes + True + >>> list(flatten([('a', 'b'), (), ('c', 'd', 'e'), ('f',), ('g', 'h', 'i')])) ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'] @@ -1487,16 +1564,16 @@ The following recipes have a more mathematical flavor: >>> list(unique_everseen('AAAABBBCCDAABBB')) ['A', 'B', 'C', 'D'] - >>> list(unique_everseen('ABBCcAD', str.lower)) + >>> list(unique_everseen('ABBCcAD', str.casefold)) ['A', 'B', 'C', 'D'] - >>> list(unique_everseen('ABBcCAD', str.lower)) + >>> list(unique_everseen('ABBcCAD', str.casefold)) ['A', 'B', 'c', 'D'] >>> list(unique_justseen('AAAABBBCCDAABBB')) ['A', 'B', 'C', 'D', 'A', 'B'] - >>> list(unique_justseen('ABBCcAD', str.lower)) + >>> list(unique_justseen('ABBCcAD', str.casefold)) ['A', 'B', 'C', 'A', 'D'] - >>> list(unique_justseen('ABBcCAD', str.lower)) + >>> list(unique_justseen('ABBcCAD', str.casefold)) ['A', 'B', 'c', 'A', 'D'] >>> d = dict(a=1, b=2, c=3) @@ -1519,20 +1596,6 @@ The following recipes have a more mathematical flavor: >>> first_true('ABC0DEF1', '9', str.isdigit) '0' - >>> population = 'ABCDEFGH' - >>> for r in range(len(population) + 1): - ... seq = list(combinations(population, r)) - ... for i in range(len(seq)): - ... assert nth_combination(population, r, i) == seq[i] - ... for i in range(-len(seq), 0): - ... assert nth_combination(population, r, i) == seq[i] - - >>> iterable = 'abcde' - >>> r = 3 - >>> combos = list(combinations(iterable, r)) - >>> all(nth_combination(iterable, r, i) == comb for i, comb in enumerate(combos)) - True - .. testcode:: :hide: @@ -1559,6 +1622,24 @@ The following recipes have a more mathematical flavor: for (a, _), (b, c) in pairwise(pairwise(iterable)): yield a, b, c + def nth_combination(iterable, r, index): + "Equivalent to list(combinations(iterable, r))[index]" + pool = tuple(iterable) + n = len(pool) + c = math.comb(n, r) + if index < 0: + index += c + if index < 0 or index >= c: + raise IndexError + result = [] + while r: + c, n, r = c*r//n, n-1, r-1 + while index >= c: + index -= c + c, n = c*(n-r)//n, n-1 + result.append(pool[-1-n]) + return tuple(result) + .. doctest:: :hide: @@ -1574,3 +1655,17 @@ The following recipes have a more mathematical flavor: >>> list(triplewise('ABCDEFG')) [('A', 'B', 'C'), ('B', 'C', 'D'), ('C', 'D', 'E'), ('D', 'E', 'F'), ('E', 'F', 'G')] + + >>> population = 'ABCDEFGH' + >>> for r in range(len(population) + 1): + ... seq = list(combinations(population, r)) + ... for i in range(len(seq)): + ... assert nth_combination(population, r, i) == seq[i] + ... for i in range(-len(seq), 0): + ... assert nth_combination(population, r, i) == seq[i] + + >>> iterable = 'abcde' + >>> r = 3 + >>> combos = list(combinations(iterable, r)) + >>> all(nth_combination(iterable, r, i) == comb for i, comb in enumerate(combos)) + True diff --git a/Doc/library/json.rst b/Doc/library/json.rst index 6c3059381776c9..0ce4b697145cb3 100644 --- a/Doc/library/json.rst +++ b/Doc/library/json.rst @@ -54,12 +54,23 @@ Compact encoding:: Pretty printing:: >>> import json - >>> print(json.dumps({'4': 5, '6': 7}, sort_keys=True, indent=4)) + >>> print(json.dumps({'6': 7, '4': 5}, sort_keys=True, indent=4)) { "4": 5, "6": 7 } +Specializing JSON object encoding:: + + >>> import json + >>> def custom_json(obj): + ... if isinstance(obj, complex): + ... return {'__complex__': True, 'real': obj.real, 'imag': obj.imag} + ... raise TypeError(f'Cannot serialize object of {type(obj)}') + ... + >>> json.dumps(1 + 2j, default=custom_json) + '{"__complex__": true, "real": 1.0, "imag": 2.0}' + Decoding JSON:: >>> import json @@ -703,7 +714,7 @@ specified, :data:`sys.stdin` and :data:`sys.stdout` will be used respectively: Command line options ^^^^^^^^^^^^^^^^^^^^ -.. cmdoption:: infile +.. option:: infile The JSON file to be validated or pretty-printed: @@ -723,36 +734,36 @@ Command line options If *infile* is not specified, read from :data:`sys.stdin`. -.. cmdoption:: outfile +.. option:: outfile Write the output of the *infile* to the given *outfile*. Otherwise, write it to :data:`sys.stdout`. -.. cmdoption:: --sort-keys +.. option:: --sort-keys Sort the output of dictionaries alphabetically by key. .. versionadded:: 3.5 -.. cmdoption:: --no-ensure-ascii +.. option:: --no-ensure-ascii Disable escaping of non-ascii characters, see :func:`json.dumps` for more information. .. versionadded:: 3.9 -.. cmdoption:: --json-lines +.. option:: --json-lines Parse every input line as separate JSON object. .. versionadded:: 3.8 -.. cmdoption:: --indent, --tab, --no-indent, --compact +.. option:: --indent, --tab, --no-indent, --compact Mutually exclusive options for whitespace control. .. versionadded:: 3.9 -.. cmdoption:: -h, --help +.. option:: -h, --help Show the help message. diff --git a/Doc/library/kde_example.png b/Doc/library/kde_example.png new file mode 100644 index 00000000000000..f4504895699974 Binary files /dev/null and b/Doc/library/kde_example.png differ diff --git a/Doc/library/locale.rst b/Doc/library/locale.rst index afd5677deac3f8..a7201199191215 100644 --- a/Doc/library/locale.rst +++ b/Doc/library/locale.rst @@ -303,13 +303,13 @@ The :mod:`locale` module defines the following exception and functions: *language code* and *encoding* may be ``None`` if their values cannot be determined. - .. deprecated-removed:: 3.11 3.13 + .. deprecated-removed:: 3.11 3.15 .. function:: getlocale(category=LC_CTYPE) Returns the current setting for the given locale category as sequence containing - *language code*, *encoding*. *category* may be one of the :const:`LC_\*` values + *language code*, *encoding*. *category* may be one of the :const:`!LC_\*` values except :const:`LC_ALL`. It defaults to :const:`LC_CTYPE`. Except for the code ``'C'``, the language code corresponds to :rfc:`1766`. @@ -454,11 +454,16 @@ The :mod:`locale` module defines the following exception and functions: .. data:: LC_CTYPE - .. index:: pair: module; string + Locale category for the character type functions. Most importantly, this + category defines the text encoding, i.e. how bytes are interpreted as + Unicode codepoints. See :pep:`538` and :pep:`540` for how this variable + might be automatically coerced to ``C.UTF-8`` to avoid issues created by + invalid settings in containers or incompatible settings passed over remote + SSH connections. - Locale category for the character type functions. Depending on the settings of - this category, the functions of module :mod:`string` dealing with case change - their behaviour. + Python doesn't internally use locale-dependent character transformation functions + from ``ctype.h``. Instead, an internal ``pyctype.h`` provides locale-independent + equivalents like :c:macro:`!Py_TOLOWER`. .. data:: LC_COLLATE diff --git a/Doc/library/logging.config.rst b/Doc/library/logging.config.rst index 448978f43b6d13..85a68cb11ee22c 100644 --- a/Doc/library/logging.config.rst +++ b/Doc/library/logging.config.rst @@ -93,8 +93,8 @@ in :mod:`logging` itself) and defining handlers which are declared either in :param fname: A filename, or a file-like object, or an instance derived from :class:`~configparser.RawConfigParser`. If a - ``RawConfigParser``-derived instance is passed, it is used as - is. Otherwise, a :class:`~configparser.Configparser` is + :class:`!RawConfigParser`-derived instance is passed, it is used as + is. Otherwise, a :class:`~configparser.ConfigParser` is instantiated, and the configuration read by it from the object passed in ``fname``. If that has a :meth:`readline` method, it is assumed to be a file-like object and read using @@ -103,7 +103,7 @@ in :mod:`logging` itself) and defining handlers which are declared either in :meth:`~configparser.ConfigParser.read`. - :param defaults: Defaults to be passed to the ConfigParser can be specified + :param defaults: Defaults to be passed to the :class:`!ConfigParser` can be specified in this argument. :param disable_existing_loggers: If specified as ``False``, loggers which @@ -257,11 +257,11 @@ otherwise, the context is used to determine what to instantiate. which correspond to the arguments passed to create a :class:`~logging.Formatter` object: - * ``format`` - * ``datefmt`` - * ``style`` - * ``validate`` (since version >=3.8) - * ``defaults`` (since version >=3.12) + * ``format`` + * ``datefmt`` + * ``style`` + * ``validate`` (since version >=3.8) + * ``defaults`` (since version >=3.12) An optional ``class`` key indicates the name of the formatter's class (as a dotted module and class name). The instantiation @@ -544,9 +544,9 @@ valid keyword parameter name, and so will not clash with the names of the keyword arguments used in the call. The ``'()'`` also serves as a mnemonic that the corresponding value is a callable. - .. versionchanged:: 3.11 - The ``filters`` member of ``handlers`` and ``loggers`` can take - filter instances in addition to ids. +.. versionchanged:: 3.11 + 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 @@ -685,7 +685,8 @@ resolve to ``'dev_team@domain.tld'`` and the string ``'support_team@domain.tld'``. The ``subject`` value could be accessed using either ``'cfg://handlers.email.subject'`` or, equivalently, ``'cfg://handlers.email[subject]'``. The latter form only needs to be -used if the key contains spaces or non-alphanumeric characters. If an +used if the key contains spaces or non-alphanumeric characters. Please note +that the characters ``[`` and ``]`` are not allowed in the keys. If an index value consists only of decimal digits, access will be attempted using the corresponding integer value, falling back to the string value if needed. diff --git a/Doc/library/logging.handlers.rst b/Doc/library/logging.handlers.rst index 2a825db54aed5c..2dd4bd081b0429 100644 --- a/Doc/library/logging.handlers.rst +++ b/Doc/library/logging.handlers.rst @@ -656,9 +656,7 @@ supports sending logging messages to a remote or local Unix syslog. to the other end. This method is called during handler initialization, but it's not regarded as an error if the other end isn't listening at this point - the method will be called again when emitting an event, if - but it's not regarded as an error if the other end isn't listening yet - --- the method will be called again when emitting an event, - if there is no socket at that point. + there is no socket at that point. .. versionadded:: 3.11 diff --git a/Doc/library/logging.rst b/Doc/library/logging.rst index 4c6e74ff66a11a..acdeb88a546261 100644 --- a/Doc/library/logging.rst +++ b/Doc/library/logging.rst @@ -397,21 +397,39 @@ have specific values relative to the predefined levels. If you define a level with the same numeric value, it overwrites the predefined value; the predefined name is lost. -+-----------------------+---------------+ -| Level | Numeric value | -+=======================+===============+ -| .. py:data:: CRITICAL | 50 | -+-----------------------+---------------+ -| .. py:data:: ERROR | 40 | -+-----------------------+---------------+ -| .. py:data:: WARNING | 30 | -+-----------------------+---------------+ -| .. py:data:: INFO | 20 | -+-----------------------+---------------+ -| .. py:data:: DEBUG | 10 | -+-----------------------+---------------+ -| .. py:data:: NOTSET | 0 | -+-----------------------+---------------+ ++-----------------------+---------------+-------------------------------------+ +| Level | Numeric value | What it means / When to use it | ++=======================+===============+=====================================+ +| .. py:data:: NOTSET | 0 | When set on a logger, indicates that| +| | | ancestor loggers are to be consulted| +| | | to determine the effective level. | +| | | If that still resolves to | +| | | :const:`!NOTSET`, then all events | +| | | are logged. When set on a handler, | +| | | all events are handled. | ++-----------------------+---------------+-------------------------------------+ +| .. py:data:: DEBUG | 10 | Detailed information, typically only| +| | | of interest to a developer trying to| +| | | diagnose a problem. | ++-----------------------+---------------+-------------------------------------+ +| .. py:data:: INFO | 20 | Confirmation that things are working| +| | | as expected. | ++-----------------------+---------------+-------------------------------------+ +| .. py:data:: WARNING | 30 | An indication that something | +| | | unexpected happened, or that a | +| | | problem might occur in the near | +| | | future (e.g. 'disk space low'). The | +| | | software is still working as | +| | | expected. | ++-----------------------+---------------+-------------------------------------+ +| .. py:data:: ERROR | 40 | Due to a more serious problem, the | +| | | software has not been able to | +| | | perform some function. | ++-----------------------+---------------+-------------------------------------+ +| .. py:data:: CRITICAL | 50 | A serious error, indicating that the| +| | | program itself may be unable to | +| | | continue running. | ++-----------------------+---------------+-------------------------------------+ .. _handler: @@ -421,7 +439,7 @@ Handler Objects Handlers have the following attributes and methods. Note that :class:`Handler` is never instantiated directly; this class acts as a base for more useful -subclasses. However, the :meth:`__init__` method in subclasses needs to call +subclasses. However, the :meth:`!__init__` method in subclasses needs to call :meth:`Handler.__init__`. .. class:: Handler @@ -889,7 +907,7 @@ you want to use. In the case of {}-formatting, you can specify formatting flags by placing them after the attribute name, separated from it with a colon. For example: a -placeholder of ``{msecs:03d}`` would format a millisecond value of ``4`` as +placeholder of ``{msecs:03.0f}`` would format a millisecond value of ``4`` as ``004``. Refer to the :meth:`str.format` documentation for full details on the options available to you. @@ -984,10 +1002,14 @@ LoggerAdapter Objects information into logging calls. For a usage example, see the section on :ref:`adding contextual information to your logging output `. -.. class:: LoggerAdapter(logger, extra) +.. class:: LoggerAdapter(logger, extra, merge_extra=False) Returns an instance of :class:`LoggerAdapter` initialized with an - underlying :class:`Logger` instance and a dict-like object. + underlying :class:`Logger` instance, a dict-like object (*extra*), and a + boolean (*merge_extra*) indicating whether or not the *extra* argument of + individual log calls should be merged with the :class:`LoggerAdapter` extra. + The default behavior is to ignore the *extra* argument of individual log + calls and only use the one of the :class:`LoggerAdapter` instance .. method:: process(msg, kwargs) @@ -997,27 +1019,42 @@ information into logging calls. For a usage example, see the section on 'extra'. The return value is a (*msg*, *kwargs*) tuple which has the (possibly modified) versions of the arguments passed in. -In addition to the above, :class:`LoggerAdapter` supports the following -methods of :class:`Logger`: :meth:`~Logger.debug`, :meth:`~Logger.info`, -:meth:`~Logger.warning`, :meth:`~Logger.error`, :meth:`~Logger.exception`, -:meth:`~Logger.critical`, :meth:`~Logger.log`, :meth:`~Logger.isEnabledFor`, -:meth:`~Logger.getEffectiveLevel`, :meth:`~Logger.setLevel` and -:meth:`~Logger.hasHandlers`. These methods have the same signatures as their -counterparts in :class:`Logger`, so you can use the two types of instances -interchangeably. + .. attribute:: manager -.. versionchanged:: 3.2 - The :meth:`~Logger.isEnabledFor`, :meth:`~Logger.getEffectiveLevel`, - :meth:`~Logger.setLevel` and :meth:`~Logger.hasHandlers` methods were added - to :class:`LoggerAdapter`. These methods delegate to the underlying logger. + Delegates to the underlying :attr:`!manager`` on *logger*. + + .. attribute:: _log + + Delegates to the underlying :meth:`!_log`` method on *logger*. + + In addition to the above, :class:`LoggerAdapter` supports the following + methods of :class:`Logger`: :meth:`~Logger.debug`, :meth:`~Logger.info`, + :meth:`~Logger.warning`, :meth:`~Logger.error`, :meth:`~Logger.exception`, + :meth:`~Logger.critical`, :meth:`~Logger.log`, :meth:`~Logger.isEnabledFor`, + :meth:`~Logger.getEffectiveLevel`, :meth:`~Logger.setLevel` and + :meth:`~Logger.hasHandlers`. These methods have the same signatures as their + counterparts in :class:`Logger`, so you can use the two types of instances + interchangeably. + + .. versionchanged:: 3.2 + + The :meth:`~Logger.isEnabledFor`, :meth:`~Logger.getEffectiveLevel`, + :meth:`~Logger.setLevel` and :meth:`~Logger.hasHandlers` methods were added + to :class:`LoggerAdapter`. These methods delegate to the underlying logger. -.. versionchanged:: 3.6 - Attribute :attr:`manager` and method :meth:`_log` were added, which - delegate to the underlying logger and allow adapters to be nested. + .. versionchanged:: 3.6 + + Attribute :attr:`!manager` and method :meth:`!_log` were added, which + delegate to the underlying logger and allow adapters to be nested. + + .. versionchanged:: 3.13 + + Remove the undocumented :meth:`!warn`` method which was an alias to the + :meth:`!warning` method. + + .. versionchanged:: 3.13 -.. versionchanged:: 3.13 - Remove the undocumented ``warn()`` method which was an alias to the - ``warning()`` method. + The *merge_extra* argument was added. Thread Safety @@ -1405,8 +1442,8 @@ functions. .. function:: setLoggerClass(klass) Tells the logging system to use the class *klass* when instantiating a logger. - The class should define :meth:`__init__` such that only a name argument is - required, and the :meth:`__init__` should call :meth:`Logger.__init__`. This + The class should define :meth:`!__init__` such that only a name argument is + required, and the :meth:`!__init__` should call :meth:`!Logger.__init__`. This function is typically called before any loggers are instantiated by applications which need to use custom logger behavior. After this call, as at any other time, do not instantiate loggers directly using the subclass: continue to use diff --git a/Doc/library/lzma.rst b/Doc/library/lzma.rst index 434e7ac9061186..0d69c3bc01d1e2 100644 --- a/Doc/library/lzma.rst +++ b/Doc/library/lzma.rst @@ -333,19 +333,22 @@ the key ``"id"``, and may contain additional keys to specify filter-dependent options. Valid filter IDs are as follows: * Compression filters: - * :const:`FILTER_LZMA1` (for use with :const:`FORMAT_ALONE`) - * :const:`FILTER_LZMA2` (for use with :const:`FORMAT_XZ` and :const:`FORMAT_RAW`) + + * :const:`FILTER_LZMA1` (for use with :const:`FORMAT_ALONE`) + * :const:`FILTER_LZMA2` (for use with :const:`FORMAT_XZ` and :const:`FORMAT_RAW`) * Delta filter: - * :const:`FILTER_DELTA` + + * :const:`FILTER_DELTA` * Branch-Call-Jump (BCJ) filters: - * :const:`FILTER_X86` - * :const:`FILTER_IA64` - * :const:`FILTER_ARM` - * :const:`FILTER_ARMTHUMB` - * :const:`FILTER_POWERPC` - * :const:`FILTER_SPARC` + + * :const:`FILTER_X86` + * :const:`FILTER_IA64` + * :const:`FILTER_ARM` + * :const:`FILTER_ARMTHUMB` + * :const:`FILTER_POWERPC` + * :const:`FILTER_SPARC` A filter chain can consist of up to 4 filters, and cannot be empty. The last filter in the chain must be a compression filter, and any other filters must be @@ -354,21 +357,21 @@ delta or BCJ filters. Compression filters support the following options (specified as additional entries in the dictionary representing the filter): - * ``preset``: A compression preset to use as a source of default values for - options that are not specified explicitly. - * ``dict_size``: Dictionary size in bytes. This should be between 4 KiB and - 1.5 GiB (inclusive). - * ``lc``: Number of literal context bits. - * ``lp``: Number of literal position bits. The sum ``lc + lp`` must be at - most 4. - * ``pb``: Number of position bits; must be at most 4. - * ``mode``: :const:`MODE_FAST` or :const:`MODE_NORMAL`. - * ``nice_len``: What should be considered a "nice length" for a match. - This should be 273 or less. - * ``mf``: What match finder to use -- :const:`MF_HC3`, :const:`MF_HC4`, - :const:`MF_BT2`, :const:`MF_BT3`, or :const:`MF_BT4`. - * ``depth``: Maximum search depth used by match finder. 0 (default) means to - select automatically based on other filter options. +* ``preset``: A compression preset to use as a source of default values for + options that are not specified explicitly. +* ``dict_size``: Dictionary size in bytes. This should be between 4 KiB and + 1.5 GiB (inclusive). +* ``lc``: Number of literal context bits. +* ``lp``: Number of literal position bits. The sum ``lc + lp`` must be at + most 4. +* ``pb``: Number of position bits; must be at most 4. +* ``mode``: :const:`MODE_FAST` or :const:`MODE_NORMAL`. +* ``nice_len``: What should be considered a "nice length" for a match. + This should be 273 or less. +* ``mf``: What match finder to use -- :const:`MF_HC3`, :const:`MF_HC4`, + :const:`MF_BT2`, :const:`MF_BT3`, or :const:`MF_BT4`. +* ``depth``: Maximum search depth used by match finder. 0 (default) means to + select automatically based on other filter options. The delta filter stores the differences between bytes, producing more repetitive input for the compressor in certain circumstances. It supports one option, diff --git a/Doc/library/mailbox.rst b/Doc/library/mailbox.rst index 91df07d914cae2..fa5b273093f583 100644 --- a/Doc/library/mailbox.rst +++ b/Doc/library/mailbox.rst @@ -13,8 +13,8 @@ This module defines two classes, :class:`Mailbox` and :class:`Message`, for accessing and manipulating on-disk mailboxes and the messages they contain. -:class:`Mailbox` offers a dictionary-like mapping from keys to messages. -:class:`Message` extends the :mod:`email.message` module's +:class:`!Mailbox` offers a dictionary-like mapping from keys to messages. +:class:`!Message` extends the :mod:`email.message` module's :class:`~email.message.Message` class with format-specific state and behavior. Supported mailbox formats are Maildir, mbox, MH, Babyl, and MMDF. @@ -27,37 +27,38 @@ Supported mailbox formats are Maildir, mbox, MH, Babyl, and MMDF. .. _mailbox-objects: -:class:`Mailbox` objects ------------------------- +:class:`!Mailbox` objects +------------------------- .. class:: Mailbox A mailbox, which may be inspected and modified. - The :class:`Mailbox` class defines an interface and is not intended to be + The :class:`!Mailbox` class defines an interface and is not intended to be instantiated. Instead, format-specific subclasses should inherit from - :class:`Mailbox` and your code should instantiate a particular subclass. + :class:`!Mailbox` and your code should instantiate a particular subclass. - The :class:`Mailbox` interface is dictionary-like, with small keys - corresponding to messages. Keys are issued by the :class:`Mailbox` instance - with which they will be used and are only meaningful to that :class:`Mailbox` + The :class:`!Mailbox` interface is dictionary-like, with small keys + corresponding to messages. Keys are issued by the :class:`!Mailbox` instance + with which they will be used and are only meaningful to that :class:`!Mailbox` instance. A key continues to identify a message even if the corresponding message is modified, such as by replacing it with another message. - Messages may be added to a :class:`Mailbox` instance using the set-like + Messages may be added to a :class:`!Mailbox` instance using the set-like method :meth:`add` and removed using a ``del`` statement or the set-like methods :meth:`remove` and :meth:`discard`. - :class:`Mailbox` interface semantics differ from dictionary semantics in some + :class:`!Mailbox` interface semantics differ from dictionary semantics in some noteworthy ways. Each time a message is requested, a new representation (typically a :class:`Message` instance) is generated based upon the current state of the mailbox. Similarly, when a message is added to a - :class:`Mailbox` instance, the provided message representation's contents are + :class:`!Mailbox` instance, the provided message representation's contents are copied. In neither case is a reference to the message representation kept by - the :class:`Mailbox` instance. + the :class:`!Mailbox` instance. - The default :class:`Mailbox` iterator iterates over message representations, - not keys as the default dictionary iterator does. Moreover, modification of a + The default :class:`!Mailbox` :term:`iterator` iterates over message + representations, not keys as the default :class:`dictionary ` + iterator does. Moreover, modification of a mailbox during iteration is safe and well-defined. Messages added to the mailbox after an iterator is created will not be seen by the iterator. Messages removed from the mailbox before the iterator yields them @@ -69,14 +70,15 @@ Supported mailbox formats are Maildir, mbox, MH, Babyl, and MMDF. Be very cautious when modifying mailboxes that might be simultaneously changed by some other process. The safest mailbox format to use for such - tasks is Maildir; try to avoid using single-file formats such as mbox for + tasks is :class:`Maildir`; try to avoid using single-file formats such as + :class:`mbox` for concurrent writing. If you're modifying a mailbox, you *must* lock it by calling the :meth:`lock` and :meth:`unlock` methods *before* reading any messages in the file or making any changes by adding or deleting a message. Failing to lock the mailbox runs the risk of losing messages or corrupting the entire mailbox. - :class:`Mailbox` instances have the following methods: + :class:`!Mailbox` instances have the following methods: .. method:: add(message) @@ -127,21 +129,23 @@ Supported mailbox formats are Maildir, mbox, MH, Babyl, and MMDF. .. method:: iterkeys() - keys() - Return an iterator over all keys if called as :meth:`iterkeys` or return a - list of keys if called as :meth:`keys`. + Return an :term:`iterator` over all keys + + + .. method:: keys() + + The same as :meth:`iterkeys`, except that a :class:`list` is returned + rather than an :term:`iterator` .. method:: itervalues() __iter__() - values() - Return an iterator over representations of all messages if called as - :meth:`itervalues` or :meth:`__iter__` or return a list of such - representations if called as :meth:`values`. The messages are represented + Return an :term:`iterator` over representations of all messages. + The messages are represented as instances of the appropriate format-specific :class:`Message` subclass - unless a custom message factory was specified when the :class:`Mailbox` + unless a custom message factory was specified when the :class:`!Mailbox` instance was initialized. .. note:: @@ -150,15 +154,25 @@ Supported mailbox formats are Maildir, mbox, MH, Babyl, and MMDF. iterate over keys. + .. method:: values() + + The same as :meth:`itervalues`, except that a :class:`list` is returned + rather than an :term:`iterator` + + .. method:: iteritems() - items() - Return an iterator over (*key*, *message*) pairs, where *key* is a key and - *message* is a message representation, if called as :meth:`iteritems` or - return a list of such pairs if called as :meth:`items`. The messages are + Return an :term:`iterator` over (*key*, *message*) pairs, where *key* is + a key and *message* is a message representation. The messages are represented as instances of the appropriate format-specific :class:`Message` subclass unless a custom message factory was specified - when the :class:`Mailbox` instance was initialized. + when the :class:`!Mailbox` instance was initialized. + + + .. method:: items() + + The same as :meth:`iteritems`, except that a :class:`list` of pairs is + returned rather than an :term:`iterator` of pairs. .. method:: get(key, default=None) @@ -167,9 +181,9 @@ Supported mailbox formats are Maildir, mbox, MH, Babyl, and MMDF. Return a representation of the message corresponding to *key*. If no such message exists, *default* is returned if the method was called as :meth:`get` and a :exc:`KeyError` exception is raised if the method was - called as :meth:`__getitem__`. The message is represented as an instance + called as :meth:`!__getitem__`. The message is represented as an instance of the appropriate format-specific :class:`Message` subclass unless a - custom message factory was specified when the :class:`Mailbox` instance + custom message factory was specified when the :class:`!Mailbox` instance was initialized. @@ -198,21 +212,23 @@ Supported mailbox formats are Maildir, mbox, MH, Babyl, and MMDF. .. method:: get_file(key) - Return a file-like representation of the message corresponding to *key*, + Return a :term:`file-like ` representation of the + message corresponding to *key*, or raise a :exc:`KeyError` exception if no such message exists. The file-like object behaves as if open in binary mode. This file should be closed once it is no longer needed. .. versionchanged:: 3.2 - The file object really is a binary file; previously it was incorrectly - returned in text mode. Also, the file-like object now supports the - context management protocol: you can use a :keyword:`with` statement to - automatically close it. + The file object really is a :term:`binary file`; previously it was + incorrectly returned in text mode. Also, the :term:`file-like object` + now supports the :term:`context manager` protocol: you can use a + :keyword:`with` statement to automatically close it. .. note:: - Unlike other representations of messages, file-like representations are - not necessarily independent of the :class:`Mailbox` instance that + Unlike other representations of messages, + :term:`file-like ` representations are not + necessarily independent of the :class:`!Mailbox` instance that created them or of the underlying mailbox. More specific documentation is provided by each subclass. @@ -238,7 +254,7 @@ Supported mailbox formats are Maildir, mbox, MH, Babyl, and MMDF. the message. If no such message exists, return *default*. The message is represented as an instance of the appropriate format-specific :class:`Message` subclass unless a custom message factory was specified - when the :class:`Mailbox` instance was initialized. + when the :class:`!Mailbox` instance was initialized. .. method:: popitem() @@ -248,7 +264,7 @@ Supported mailbox formats are Maildir, mbox, MH, Babyl, and MMDF. message. If the mailbox is empty, raise a :exc:`KeyError` exception. The message is represented as an instance of the appropriate format-specific :class:`Message` subclass unless a custom message factory was specified - when the :class:`Mailbox` instance was initialized. + when the :class:`!Mailbox` instance was initialized. .. method:: update(arg) @@ -259,7 +275,7 @@ Supported mailbox formats are Maildir, mbox, MH, Babyl, and MMDF. *message* as if by using :meth:`__setitem__`. As with :meth:`__setitem__`, each *key* must already correspond to a message in the mailbox or else a :exc:`KeyError` exception will be raised, so in general it is incorrect - for *arg* to be a :class:`Mailbox` instance. + for *arg* to be a :class:`!Mailbox` instance. .. note:: @@ -269,7 +285,7 @@ Supported mailbox formats are Maildir, mbox, MH, Babyl, and MMDF. .. method:: flush() Write any pending changes to the filesystem. For some :class:`Mailbox` - subclasses, changes are always written immediately and :meth:`flush` does + subclasses, changes are always written immediately and :meth:`!flush` does nothing, but you should still make a habit of calling this method. @@ -290,13 +306,13 @@ Supported mailbox formats are Maildir, mbox, MH, Babyl, and MMDF. .. method:: close() Flush the mailbox, unlock it if necessary, and close any open files. For - some :class:`Mailbox` subclasses, this method does nothing. + some :class:`!Mailbox` subclasses, this method does nothing. .. _mailbox-maildir: -:class:`Maildir` -^^^^^^^^^^^^^^^^ +:class:`!Maildir` objects +^^^^^^^^^^^^^^^^^^^^^^^^^ .. class:: Maildir(dirname, factory=None, create=True) @@ -330,11 +346,11 @@ Supported mailbox formats are Maildir, mbox, MH, Babyl, and MMDF. Folders of the style introduced by the Courier mail transfer agent are also supported. Any subdirectory of the main mailbox is considered a folder if ``'.'`` is the first character in its name. Folder names are represented by - :class:`Maildir` without the leading ``'.'``. Each folder is itself a Maildir + :class:`!Maildir` without the leading ``'.'``. Each folder is itself a Maildir mailbox but should not contain other folders. Instead, a logical nesting is indicated using ``'.'`` to delimit levels, e.g., "Archived.2005.07". - .. note:: + .. attribute:: Maildir.colon The Maildir specification requires the use of a colon (``':'``) in certain message file names. However, some operating systems do not permit this @@ -346,9 +362,12 @@ Supported mailbox formats are Maildir, mbox, MH, Babyl, and MMDF. import mailbox mailbox.Maildir.colon = '!' - The :attr:`colon` attribute may also be set on a per-instance basis. + The :attr:`!colon` attribute may also be set on a per-instance basis. - :class:`Maildir` instances have all of the methods of :class:`Mailbox` in + .. versionchanged:: 3.13 + :class:`Maildir` now ignores files with a leading dot. + + :class:`!Maildir` instances have all of the methods of :class:`Mailbox` in addition to the following: @@ -359,14 +378,14 @@ Supported mailbox formats are Maildir, mbox, MH, Babyl, and MMDF. .. method:: get_folder(folder) - Return a :class:`Maildir` instance representing the folder whose name is + Return a :class:`!Maildir` instance representing the folder whose name is *folder*. A :exc:`NoSuchMailboxError` exception is raised if the folder does not exist. .. method:: add_folder(folder) - Create a folder whose name is *folder* and return a :class:`Maildir` + Create a folder whose name is *folder* and return a :class:`!Maildir` instance representing it. @@ -383,7 +402,109 @@ Supported mailbox formats are Maildir, mbox, MH, Babyl, and MMDF. last 36 hours. The Maildir specification says that mail-reading programs should do this occasionally. - Some :class:`Mailbox` methods implemented by :class:`Maildir` deserve special + + .. method:: get_flags(key) + + Return as a string the flags that are set on the message + corresponding to *key*. + This is the same as ``get_message(key).get_flags()`` but much + faster, because it does not open the message file. + Use this method when iterating over the keys to determine which + messages are interesting to get. + + If you do have a :class:`MaildirMessage` object, use + its :meth:`~MaildirMessage.get_flags` method instead, because + changes made by the message's :meth:`~MaildirMessage.set_flags`, + :meth:`~MaildirMessage.add_flag` and :meth:`~MaildirMessage.remove_flag` + methods are not reflected here until the mailbox's + :meth:`__setitem__` method is called. + + .. versionadded:: 3.13 + + + .. method:: set_flags(key, flags) + + On the message corresponding to *key*, set the flags specified + by *flags* and unset all others. + Calling ``some_mailbox.set_flags(key, flags)`` is similar to :: + + one_message = some_mailbox.get_message(key) + one_message.set_flags(flags) + some_mailbox[key] = one_message + + but faster, because it does not open the message file. + + If you do have a :class:`MaildirMessage` object, use + its :meth:`~MaildirMessage.set_flags` method instead, because + changes made with this mailbox method will not be visible to the + message object's method, :meth:`~MaildirMessage.get_flags`. + + .. versionadded:: 3.13 + + + .. method:: add_flag(key, flag) + + On the message corresponding to *key*, set the flags specified + by *flag* without changing other flags. To add more than one + flag at a time, *flag* may be a string of more than one character. + + Considerations for using this method versus the message object's + :meth:`~MaildirMessage.add_flag` method are similar to + those for :meth:`set_flags`; see the discussion there. + + .. versionadded:: 3.13 + + + .. method:: remove_flag(key, flag) + + On the message corresponding to *key*, unset the flags specified + by *flag* without changing other flags. To remove more than one + flag at a time, *flag* may be a string of more than one character. + + Considerations for using this method versus the message object's + :meth:`~MaildirMessage.remove_flag` method are similar to + those for :meth:`set_flags`; see the discussion there. + + .. versionadded:: 3.13 + + + .. method:: get_info(key) + + Return a string containing the info for the message + corresponding to *key*. + This is the same as ``get_message(key).get_info()`` but much + faster, because it does not open the message file. + Use this method when iterating over the keys to determine which + messages are interesting to get. + + If you do have a :class:`MaildirMessage` object, use + its :meth:`~MaildirMessage.get_info` method instead, because + changes made by the message's :meth:`~MaildirMessage.set_info` method + are not reflected here until the mailbox's :meth:`__setitem__` method + is called. + + .. versionadded:: 3.13 + + + .. method:: set_info(key, info) + + Set the info of the message corresponding to *key* to *info*. + Calling ``some_mailbox.set_info(key, flags)`` is similar to :: + + one_message = some_mailbox.get_message(key) + one_message.set_info(info) + some_mailbox[key] = one_message + + but faster, because it does not open the message file. + + If you do have a :class:`MaildirMessage` object, use + its :meth:`~MaildirMessage.set_info` method instead, because + changes made with this mailbox method will not be visible to the + message object's method, :meth:`~MaildirMessage.get_info`. + + .. versionadded:: 3.13 + + Some :class:`Mailbox` methods implemented by :class:`!Maildir` deserve special remarks: @@ -414,7 +535,7 @@ Supported mailbox formats are Maildir, mbox, MH, Babyl, and MMDF. .. method:: close() - :class:`Maildir` instances do not keep any open files and the underlying + :class:`!Maildir` instances do not keep any open files and the underlying mailboxes do not support locking, so this method does nothing. @@ -437,8 +558,8 @@ Supported mailbox formats are Maildir, mbox, MH, Babyl, and MMDF. .. _mailbox-mbox: -:class:`mbox` -^^^^^^^^^^^^^ +:class:`!mbox` objects +^^^^^^^^^^^^^^^^^^^^^^ .. class:: mbox(path, factory=None, create=True) @@ -455,22 +576,22 @@ Supported mailbox formats are Maildir, mbox, MH, Babyl, and MMDF. each message indicated by a line whose first five characters are "From ". Several variations of the mbox format exist to address perceived shortcomings in - the original. In the interest of compatibility, :class:`mbox` implements the + the original. In the interest of compatibility, :class:`!mbox` implements the original format, which is sometimes referred to as :dfn:`mboxo`. This means that the :mailheader:`Content-Length` header, if present, is ignored and that any occurrences of "From " at the beginning of a line in a message body are transformed to ">From " when storing the message, although occurrences of ">From " are not transformed to "From " when reading the message. - Some :class:`Mailbox` methods implemented by :class:`mbox` deserve special + Some :class:`Mailbox` methods implemented by :class:`!mbox` deserve special remarks: .. method:: get_file(key) - Using the file after calling :meth:`flush` or :meth:`close` on the - :class:`mbox` instance may yield unpredictable results or raise an - exception. + Using the file after calling :meth:`~Mailbox.flush` or + :meth:`~Mailbox.close` on the :class:`!mbox` instance may yield + unpredictable results or raise an exception. .. method:: lock() @@ -494,8 +615,8 @@ Supported mailbox formats are Maildir, mbox, MH, Babyl, and MMDF. .. _mailbox-mh: -:class:`MH` -^^^^^^^^^^^ +:class:`!MH` objects +^^^^^^^^^^^^^^^^^^^^ .. class:: MH(path, factory=None, create=True) @@ -515,14 +636,18 @@ Supported mailbox formats are Maildir, mbox, MH, Babyl, and MMDF. messages without moving them to sub-folders. Sequences are defined in a file called :file:`.mh_sequences` in each folder. - The :class:`MH` class manipulates MH mailboxes, but it does not attempt to + The :class:`!MH` class manipulates MH mailboxes, but it does not attempt to emulate all of :program:`mh`'s behaviors. In particular, it does not modify and is not affected by the :file:`context` or :file:`.mh_profile` files that are used by :program:`mh` to store its state and configuration. - :class:`MH` instances have all of the methods of :class:`Mailbox` in addition + :class:`!MH` instances have all of the methods of :class:`Mailbox` in addition to the following: + .. versionchanged:: 3.13 + + Supported folders that don't contain a :file:`.mh_sequences` file. + .. method:: list_folders() @@ -531,14 +656,14 @@ Supported mailbox formats are Maildir, mbox, MH, Babyl, and MMDF. .. method:: get_folder(folder) - Return an :class:`MH` instance representing the folder whose name is + Return an :class:`!MH` instance representing the folder whose name is *folder*. A :exc:`NoSuchMailboxError` exception is raised if the folder does not exist. .. method:: add_folder(folder) - Create a folder whose name is *folder* and return an :class:`MH` instance + Create a folder whose name is *folder* and return an :class:`!MH` instance representing it. @@ -572,7 +697,7 @@ Supported mailbox formats are Maildir, mbox, MH, Babyl, and MMDF. Already-issued keys are invalidated by this operation and should not be subsequently used. - Some :class:`Mailbox` methods implemented by :class:`MH` deserve special + Some :class:`Mailbox` methods implemented by :class:`!MH` deserve special remarks: @@ -608,7 +733,7 @@ Supported mailbox formats are Maildir, mbox, MH, Babyl, and MMDF. .. method:: close() - :class:`MH` instances do not keep any open files, so this method is + :class:`!MH` instances do not keep any open files, so this method is equivalent to :meth:`unlock`. @@ -624,8 +749,8 @@ Supported mailbox formats are Maildir, mbox, MH, Babyl, and MMDF. .. _mailbox-babyl: -:class:`Babyl` -^^^^^^^^^^^^^^ +:class:`!Babyl` objects +^^^^^^^^^^^^^^^^^^^^^^^ .. class:: Babyl(path, factory=None, create=True) @@ -652,7 +777,7 @@ Supported mailbox formats are Maildir, mbox, MH, Babyl, and MMDF. message, and a list of all user-defined labels found in the mailbox is kept in the Babyl options section. - :class:`Babyl` instances have all of the methods of :class:`Mailbox` in + :class:`!Babyl` instances have all of the methods of :class:`Mailbox` in addition to the following: @@ -667,7 +792,7 @@ Supported mailbox formats are Maildir, mbox, MH, Babyl, and MMDF. options section, but the Babyl section is updated whenever the mailbox is modified. - Some :class:`Mailbox` methods implemented by :class:`Babyl` deserve special + Some :class:`Mailbox` methods implemented by :class:`!Babyl` deserve special remarks: @@ -700,8 +825,8 @@ Supported mailbox formats are Maildir, mbox, MH, Babyl, and MMDF. .. _mailbox-mmdf: -:class:`MMDF` -^^^^^^^^^^^^^ +:class:`!MMDF` objects +^^^^^^^^^^^^^^^^^^^^^^ .. class:: MMDF(path, factory=None, create=True) @@ -722,15 +847,15 @@ Supported mailbox formats are Maildir, mbox, MH, Babyl, and MMDF. ">From " when storing messages because the extra message separator lines prevent mistaking such occurrences for the starts of subsequent messages. - Some :class:`Mailbox` methods implemented by :class:`MMDF` deserve special + Some :class:`Mailbox` methods implemented by :class:`!MMDF` deserve special remarks: .. method:: get_file(key) - Using the file after calling :meth:`flush` or :meth:`close` on the - :class:`MMDF` instance may yield unpredictable results or raise an - exception. + Using the file after calling :meth:`~Mailbox.flush` or + :meth:`~Mailbox.close` on the :class:`!MMDF` instance may yield + unpredictable results or raise an exception. .. method:: lock() @@ -752,20 +877,20 @@ Supported mailbox formats are Maildir, mbox, MH, Babyl, and MMDF. .. _mailbox-message-objects: -:class:`Message` objects ------------------------- +:class:`!Message` objects +------------------------- .. class:: Message(message=None) A subclass of the :mod:`email.message` module's - :class:`~email.message.Message`. Subclasses of :class:`mailbox.Message` add + :class:`~email.message.Message`. Subclasses of :class:`!mailbox.Message` add mailbox-format-specific state and behavior. If *message* is omitted, the new instance is created in a default, empty state. If *message* is an :class:`email.message.Message` instance, its contents are copied; furthermore, any format-specific information is converted insofar as - possible if *message* is a :class:`Message` instance. If *message* is a string, + possible if *message* is a :class:`!Message` instance. If *message* is a string, a byte string, or a file, it should contain an :rfc:`2822`\ -compliant message, which is read and parsed. Files should be open in binary mode, but text mode files @@ -780,18 +905,18 @@ Supported mailbox formats are Maildir, mbox, MH, Babyl, and MMDF. such as whether a message has been read by the user or marked as important is retained, because it applies to the message itself. - There is no requirement that :class:`Message` instances be used to represent + There is no requirement that :class:`!Message` instances be used to represent messages retrieved using :class:`Mailbox` instances. In some situations, the - time and memory required to generate :class:`Message` representations might - not be acceptable. For such situations, :class:`Mailbox` instances also + time and memory required to generate :class:`!Message` representations might + not be acceptable. For such situations, :class:`!Mailbox` instances also offer string and file-like representations, and a custom message factory may - be specified when a :class:`Mailbox` instance is initialized. + be specified when a :class:`!Mailbox` instance is initialized. .. _mailbox-maildirmessage: -:class:`MaildirMessage` -^^^^^^^^^^^^^^^^^^^^^^^ +:class:`!MaildirMessage` objects +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. class:: MaildirMessage(message=None) @@ -826,7 +951,7 @@ Supported mailbox formats are Maildir, mbox, MH, Babyl, and MMDF. | T | Trashed | Marked for subsequent deletion | +------+---------+--------------------------------+ - :class:`MaildirMessage` instances offer the following methods: + :class:`!MaildirMessage` instances offer the following methods: .. method:: get_subdir() @@ -838,7 +963,7 @@ Supported mailbox formats are Maildir, mbox, MH, Babyl, and MMDF. .. note:: A message is typically moved from :file:`new` to :file:`cur` after its - mailbox has been accessed, whether or not the message is has been + mailbox has been accessed, whether or not the message has been read. A message ``msg`` has been read if ``"S" in msg.get_flags()`` is ``True``. @@ -903,7 +1028,7 @@ Supported mailbox formats are Maildir, mbox, MH, Babyl, and MMDF. Set "info" to *info*, which should be a string. -When a :class:`MaildirMessage` instance is created based upon an +When a :class:`!MaildirMessage` instance is created based upon an :class:`mboxMessage` or :class:`MMDFMessage` instance, the :mailheader:`Status` and :mailheader:`X-Status` headers are omitted and the following conversions take place: @@ -923,7 +1048,7 @@ take place: | T flag | D flag | +--------------------+----------------------------------------------+ -When a :class:`MaildirMessage` instance is created based upon an +When a :class:`!MaildirMessage` instance is created based upon an :class:`MHMessage` instance, the following conversions take place: +-------------------------------+--------------------------+ @@ -938,7 +1063,7 @@ When a :class:`MaildirMessage` instance is created based upon an | R flag | "replied" sequence | +-------------------------------+--------------------------+ -When a :class:`MaildirMessage` instance is created based upon a +When a :class:`!MaildirMessage` instance is created based upon a :class:`BabylMessage` instance, the following conversions take place: +-------------------------------+-------------------------------+ @@ -958,8 +1083,8 @@ When a :class:`MaildirMessage` instance is created based upon a .. _mailbox-mboxmessage: -:class:`mboxMessage` -^^^^^^^^^^^^^^^^^^^^ +:class:`!mboxMessage` objects +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. class:: mboxMessage(message=None) @@ -995,7 +1120,7 @@ When a :class:`MaildirMessage` instance is created based upon a "D", "F", and "A" flags are stored in the :mailheader:`X-Status` header. The flags and headers typically appear in the order mentioned. - :class:`mboxMessage` instances offer the following methods: + :class:`!mboxMessage` instances offer the following methods: .. method:: get_from() @@ -1043,7 +1168,7 @@ When a :class:`MaildirMessage` instance is created based upon a remove more than one flag at a time, *flag* maybe a string of more than one character. -When an :class:`mboxMessage` instance is created based upon a +When an :class:`!mboxMessage` instance is created based upon a :class:`MaildirMessage` instance, a "From " line is generated based upon the :class:`MaildirMessage` instance's delivery date, and the following conversions take place: @@ -1062,7 +1187,7 @@ take place: | A flag | R flag | +-----------------+-------------------------------+ -When an :class:`mboxMessage` instance is created based upon an +When an :class:`!mboxMessage` instance is created based upon an :class:`MHMessage` instance, the following conversions take place: +-------------------+--------------------------+ @@ -1077,7 +1202,7 @@ When an :class:`mboxMessage` instance is created based upon an | A flag | "replied" sequence | +-------------------+--------------------------+ -When an :class:`mboxMessage` instance is created based upon a +When an :class:`!mboxMessage` instance is created based upon a :class:`BabylMessage` instance, the following conversions take place: +-------------------+-----------------------------+ @@ -1092,7 +1217,8 @@ When an :class:`mboxMessage` instance is created based upon a | A flag | "answered" label | +-------------------+-----------------------------+ -When a :class:`Message` instance is created based upon an :class:`MMDFMessage` +When a :class:`!mboxMessage` instance is created based upon an +:class:`MMDFMessage` instance, the "From " line is copied and all flags directly correspond: +-----------------+----------------------------+ @@ -1112,8 +1238,8 @@ instance, the "From " line is copied and all flags directly correspond: .. _mailbox-mhmessage: -:class:`MHMessage` -^^^^^^^^^^^^^^^^^^ +:class:`!MHMessage` objects +^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. class:: MHMessage(message=None) @@ -1137,7 +1263,7 @@ instance, the "From " line is copied and all flags directly correspond: | flagged | Marked as important | +----------+------------------------------------------+ - :class:`MHMessage` instances offer the following methods: + :class:`!MHMessage` instances offer the following methods: .. method:: get_sequences() @@ -1159,7 +1285,7 @@ instance, the "From " line is copied and all flags directly correspond: Remove *sequence* from the list of sequences that include this message. -When an :class:`MHMessage` instance is created based upon a +When an :class:`!MHMessage` instance is created based upon a :class:`MaildirMessage` instance, the following conversions take place: +--------------------+-------------------------------+ @@ -1172,7 +1298,7 @@ When an :class:`MHMessage` instance is created based upon a | "flagged" sequence | F flag | +--------------------+-------------------------------+ -When an :class:`MHMessage` instance is created based upon an +When an :class:`!MHMessage` instance is created based upon an :class:`mboxMessage` or :class:`MMDFMessage` instance, the :mailheader:`Status` and :mailheader:`X-Status` headers are omitted and the following conversions take place: @@ -1188,7 +1314,7 @@ take place: | "flagged" sequence | F flag | +--------------------+----------------------------------------------+ -When an :class:`MHMessage` instance is created based upon a +When an :class:`!MHMessage` instance is created based upon a :class:`BabylMessage` instance, the following conversions take place: +--------------------+-----------------------------+ @@ -1202,8 +1328,8 @@ When an :class:`MHMessage` instance is created based upon a .. _mailbox-babylmessage: -:class:`BabylMessage` -^^^^^^^^^^^^^^^^^^^^^ +:class:`!BabylMessage` objects +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. class:: BabylMessage(message=None) @@ -1232,11 +1358,11 @@ When an :class:`MHMessage` instance is created based upon a | resent | Resent | +-----------+------------------------------------------+ - By default, Rmail displays only visible headers. The :class:`BabylMessage` + By default, Rmail displays only visible headers. The :class:`!BabylMessage` class, though, uses the original headers because they are more complete. Visible headers may be accessed explicitly if desired. - :class:`BabylMessage` instances offer the following methods: + :class:`!BabylMessage` instances offer the following methods: .. method:: get_labels() @@ -1275,7 +1401,7 @@ When an :class:`MHMessage` instance is created based upon a .. method:: update_visible() - When a :class:`BabylMessage` instance's original headers are modified, the + When a :class:`!BabylMessage` instance's original headers are modified, the visible headers are not automatically modified to correspond. This method updates the visible headers as follows: each visible header with a corresponding original header is set to the value of the original header, @@ -1285,7 +1411,7 @@ When an :class:`MHMessage` instance is created based upon a present in the original headers but not the visible headers are added to the visible headers. -When a :class:`BabylMessage` instance is created based upon a +When a :class:`!BabylMessage` instance is created based upon a :class:`MaildirMessage` instance, the following conversions take place: +-------------------+-------------------------------+ @@ -1300,7 +1426,7 @@ When a :class:`BabylMessage` instance is created based upon a | "forwarded" label | P flag | +-------------------+-------------------------------+ -When a :class:`BabylMessage` instance is created based upon an +When a :class:`!BabylMessage` instance is created based upon an :class:`mboxMessage` or :class:`MMDFMessage` instance, the :mailheader:`Status` and :mailheader:`X-Status` headers are omitted and the following conversions take place: @@ -1316,7 +1442,7 @@ take place: | "answered" label | A flag | +------------------+----------------------------------------------+ -When a :class:`BabylMessage` instance is created based upon an +When a :class:`!BabylMessage` instance is created based upon an :class:`MHMessage` instance, the following conversions take place: +------------------+--------------------------+ @@ -1330,8 +1456,8 @@ When a :class:`BabylMessage` instance is created based upon an .. _mailbox-mmdfmessage: -:class:`MMDFMessage` -^^^^^^^^^^^^^^^^^^^^ +:class:`!MMDFMessage` objects +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. class:: MMDFMessage(message=None) @@ -1365,7 +1491,7 @@ When a :class:`BabylMessage` instance is created based upon an "D", "F", and "A" flags are stored in the :mailheader:`X-Status` header. The flags and headers typically appear in the order mentioned. - :class:`MMDFMessage` instances offer the following methods, which are + :class:`!MMDFMessage` instances offer the following methods, which are identical to those offered by :class:`mboxMessage`: @@ -1414,7 +1540,7 @@ When a :class:`BabylMessage` instance is created based upon an remove more than one flag at a time, *flag* maybe a string of more than one character. -When an :class:`MMDFMessage` instance is created based upon a +When an :class:`!MMDFMessage` instance is created based upon a :class:`MaildirMessage` instance, a "From " line is generated based upon the :class:`MaildirMessage` instance's delivery date, and the following conversions take place: @@ -1433,7 +1559,7 @@ take place: | A flag | R flag | +-----------------+-------------------------------+ -When an :class:`MMDFMessage` instance is created based upon an +When an :class:`!MMDFMessage` instance is created based upon an :class:`MHMessage` instance, the following conversions take place: +-------------------+--------------------------+ @@ -1448,7 +1574,7 @@ When an :class:`MMDFMessage` instance is created based upon an | A flag | "replied" sequence | +-------------------+--------------------------+ -When an :class:`MMDFMessage` instance is created based upon a +When an :class:`!MMDFMessage` instance is created based upon a :class:`BabylMessage` instance, the following conversions take place: +-------------------+-----------------------------+ @@ -1463,7 +1589,7 @@ When an :class:`MMDFMessage` instance is created based upon a | A flag | "answered" label | +-------------------+-----------------------------+ -When an :class:`MMDFMessage` instance is created based upon an +When an :class:`!MMDFMessage` instance is created based upon an :class:`mboxMessage` instance, the "From " line is copied and all flags directly correspond: @@ -1485,7 +1611,7 @@ correspond: Exceptions ---------- -The following exception classes are defined in the :mod:`mailbox` module: +The following exception classes are defined in the :mod:`!mailbox` module: .. exception:: Error() diff --git a/Doc/library/mmap.rst b/Doc/library/mmap.rst index 69afadff1f5f42..1e8bfdf251e7da 100644 --- a/Doc/library/mmap.rst +++ b/Doc/library/mmap.rst @@ -19,7 +19,7 @@ the current file position, and :meth:`seek` through the file to different positi A memory-mapped file is created by the :class:`~mmap.mmap` constructor, which is different on Unix and on Windows. In either case you must provide a file descriptor for a file opened for update. If you wish to map an existing Python -file object, use its :meth:`fileno` method to obtain the correct value for the +file object, use its :meth:`~io.IOBase.fileno` method to obtain the correct value for the *fileno* parameter. Otherwise, you can open the file using the :func:`os.open` function, which returns a file descriptor directly (the file still needs to be closed when done). @@ -62,8 +62,8 @@ To map anonymous memory, -1 should be passed as the fileno along with the length the same file. If you specify the name of an existing tag, that tag is opened, otherwise a new tag of this name is created. If this parameter is omitted or ``None``, the mapping is created without a name. Avoiding the - use of the tag parameter will assist in keeping your code portable between - Unix and Windows. + use of the *tagname* parameter will assist in keeping your code portable + between Unix and Windows. *offset* may be specified as a non-negative integer offset. mmap references will be relative to the offset from the beginning of the file. *offset* @@ -285,6 +285,14 @@ To map anonymous memory, -1 should be passed as the fileno along with the length values are ``os.SEEK_CUR`` or ``1`` (seek relative to the current position) and ``os.SEEK_END`` or ``2`` (seek relative to the file's end). + .. versionchanged:: 3.13 + Return the new absolute position instead of ``None``. + + .. method:: seekable() + + Return whether the file supports seeking, and the return value is always ``True``. + + .. versionadded:: 3.13 .. method:: size() diff --git a/Doc/library/msvcrt.rst b/Doc/library/msvcrt.rst index 32693e3d007c05..2a6d980ab78a60 100644 --- a/Doc/library/msvcrt.rst +++ b/Doc/library/msvcrt.rst @@ -10,8 +10,8 @@ -------------- These functions provide access to some useful capabilities on Windows platforms. -Some higher-level modules use these functions to build the Windows -implementations of their services. For example, the :mod:`getpass` module uses +Some higher-level modules use these functions to build the Windows +implementations of their services. For example, the :mod:`getpass` module uses this in the implementation of the :func:`getpass` function. Further documentation on these functions can be found in the Platform API @@ -35,11 +35,11 @@ File Operations .. function:: locking(fd, mode, nbytes) - Lock part of a file based on file descriptor *fd* from the C runtime. Raises - :exc:`OSError` on failure. The locked region of the file extends from the + Lock part of a file based on file descriptor *fd* from the C runtime. Raises + :exc:`OSError` on failure. The locked region of the file extends from the current file position for *nbytes* bytes, and may continue beyond the end of the - file. *mode* must be one of the :const:`!LK_\*` constants listed below. Multiple - regions in a file may be locked at the same time, but may not overlap. Adjacent + file. *mode* must be one of the :const:`!LK_\*` constants listed below. Multiple + regions in a file may be locked at the same time, but may not overlap. Adjacent regions are not merged; they must be unlocked individually. .. audit-event:: msvcrt.locking fd,mode,nbytes msvcrt.locking @@ -49,7 +49,7 @@ File Operations LK_RLCK Locks the specified bytes. If the bytes cannot be locked, the program - immediately tries again after 1 second. If, after 10 attempts, the bytes cannot + immediately tries again after 1 second. If, after 10 attempts, the bytes cannot be locked, :exc:`OSError` is raised. @@ -74,17 +74,21 @@ File Operations .. function:: open_osfhandle(handle, flags) - Create a C runtime file descriptor from the file handle *handle*. The *flags* - parameter should be a bitwise OR of :const:`os.O_APPEND`, :const:`os.O_RDONLY`, - and :const:`os.O_TEXT`. The returned file descriptor may be used as a parameter + Create a C runtime file descriptor from the file handle *handle*. The *flags* + parameter should be a bitwise OR of :const:`os.O_APPEND`, + :const:`os.O_RDONLY`, :const:`os.O_TEXT` and :const:`os.O_NOINHERIT`. + The returned file descriptor may be used as a parameter to :func:`os.fdopen` to create a file object. + The file descriptor is inheritable by default. Pass :const:`os.O_NOINHERIT` + flag to make it non inheritable. + .. audit-event:: msvcrt.open_osfhandle handle,flags msvcrt.open_osfhandle .. function:: get_osfhandle(fd) - Return the file handle for the file descriptor *fd*. Raises :exc:`OSError` if + Return the file handle for the file descriptor *fd*. Raises :exc:`OSError` if *fd* is not recognized. .. audit-event:: msvcrt.get_osfhandle fd msvcrt.get_osfhandle @@ -98,13 +102,14 @@ Console I/O .. function:: kbhit() - Return ``True`` if a keypress is waiting to be read. + Returns a nonzero value if a keypress is waiting to be read. Otherwise, + return 0. .. function:: getch() Read a keypress and return the resulting character as a byte string. - Nothing is echoed to the console. This call will block if a keypress + Nothing is echoed to the console. This call will block if a keypress is not already available, but will not wait for :kbd:`Enter` to be pressed. If the pressed key was a special function key, this will return ``'\000'`` or ``'\xe0'``; the next call will return the keycode. @@ -118,7 +123,7 @@ Console I/O .. function:: getche() - Similar to :func:`getch`, but the keypress will be echoed if it represents a + Similar to :func:`getch`, but the keypress will be echoed if it represents a printable character. @@ -157,4 +162,93 @@ Other Functions .. function:: heapmin() Force the :c:func:`malloc` heap to clean itself up and return unused blocks to - the operating system. On failure, this raises :exc:`OSError`. + the operating system. On failure, this raises :exc:`OSError`. + + +.. function:: set_error_mode(mode) + + Changes the location where the C runtime writes an error message for an error + that might end the program. *mode* must be one of the :const:`!OUT_\*` + constants listed below or :const:`REPORT_ERRMODE`. Returns the old setting + or -1 if an error occurs. Only available in + :ref:`debug build of Python `. + + +.. data:: OUT_TO_DEFAULT + + Error sink is determined by the app's type. Only available in + :ref:`debug build of Python `. + + +.. data:: OUT_TO_STDERR + + Error sink is a standard error. Only available in + :ref:`debug build of Python `. + + +.. data:: OUT_TO_MSGBOX + + Error sink is a message box. Only available in + :ref:`debug build of Python `. + + +.. data:: REPORT_ERRMODE + + Report the current error mode value. Only available in + :ref:`debug build of Python `. + + +.. function:: CrtSetReportMode(type, mode) + + Specifies the destination or destinations for a specific report type + generated by :c:func:`!_CrtDbgReport` in the MS VC++ runtime. *type* must be + one of the :const:`!CRT_\*` constants listed below. *mode* must be one of the + :const:`!CRTDBG_\*` constants listed below. Only available in + :ref:`debug build of Python `. + + +.. function:: CrtSetReportFile(type, file) + + After you use :func:`CrtSetReportMode` to specify :const:`CRTDBG_MODE_FILE`, + you can specify the file handle to receive the message text. *type* must be + one of the :const:`!CRT_\*` constants listed below. *file* shuld be the file + handle your want specified. Only available in + :ref:`debug build of Python `. + + +.. data:: CRT_WARN + + Warnings, messages, and information that doesn't need immediate attention. + + +.. data:: CRT_ERROR + + Errors, unrecoverable problems, and issues that require immediate attention. + + +.. data:: CRT_ASSERT + + Assertion failures. + + +.. data:: CRTDBG_MODE_DEBUG + + Writes the message to the debugger's output window. + + +.. data:: CRTDBG_MODE_FILE + + Writes the message to a user-supplied file handle. :func:`CrtSetReportFile` + should be called to define the specific file or stream to use as + the destination. + + +.. data:: CRTDBG_MODE_WNDW + + Creates a message box to display the message along with the ``Abort``, + ``Retry``, and ``Ignore`` buttons. + + +.. data:: CRTDBG_REPORT_MODE + + Returns current *mode* for the specified *type*. diff --git a/Doc/library/multiprocessing.rst b/Doc/library/multiprocessing.rst index 2efc08f130af32..789a84b02d59d2 100644 --- a/Doc/library/multiprocessing.rst +++ b/Doc/library/multiprocessing.rst @@ -131,6 +131,12 @@ to start a process. These *start methods* are Code that requires *fork* should explicitly specify that via :func:`get_context` or :func:`set_start_method`. + .. versionchanged:: 3.12 + If Python is able to detect that your process has multiple threads, the + :func:`os.fork` function that this start method calls internally will + raise a :exc:`DeprecationWarning`. Use a different start method. + See the :func:`os.fork` documentation for further explanation. + *forkserver* When the program starts and selects the *forkserver* start method, a server process is spawned. From then on, whenever a new process @@ -990,13 +996,20 @@ Miscellaneous This number is not equivalent to the number of CPUs the current process can use. The number of usable CPUs can be obtained with - ``len(os.sched_getaffinity(0))`` + :func:`os.process_cpu_count` (or ``len(os.sched_getaffinity(0))``). When the number of CPUs cannot be determined a :exc:`NotImplementedError` is raised. .. seealso:: :func:`os.cpu_count` + :func:`os.process_cpu_count` + + .. versionchanged:: 3.13 + + The return value can also be overridden using the + :option:`-X cpu_count <-X>` flag or :envvar:`PYTHON_CPU_COUNT` as this is + merely a wrapper around the :mod:`os` cpu count APIs. .. function:: current_process() @@ -2208,7 +2221,7 @@ with the :class:`Pool` class. callbacks and has a parallel map implementation. *processes* is the number of worker processes to use. If *processes* is - ``None`` then the number returned by :func:`os.cpu_count` is used. + ``None`` then the number returned by :func:`os.process_cpu_count` is used. If *initializer* is not ``None`` then each worker process will call ``initializer(*initargs)`` when it starts. @@ -2243,6 +2256,10 @@ with the :class:`Pool` class. .. versionadded:: 3.4 *context* + .. versionchanged:: 3.13 + *processes* uses :func:`os.process_cpu_count` by default, instead of + :func:`os.cpu_count`. + .. note:: Worker processes within a :class:`Pool` typically live for the complete @@ -2565,7 +2582,7 @@ multiple connections at the same time. **Windows**: An item in *object_list* must either be an integer handle which is waitable (according to the definition used by the documentation of the Win32 function ``WaitForMultipleObjects()``) - or it can be an object with a :meth:`fileno` method which returns a + or it can be an object with a :meth:`~io.IOBase.fileno` method which returns a socket handle or pipe handle. (Note that pipe handles and socket handles are **not** waitable handles.) @@ -2613,7 +2630,6 @@ server:: The following code uses :func:`~multiprocessing.connection.wait` to wait for messages from multiple processes at once:: - import time, random from multiprocessing import Process, Pipe, current_process from multiprocessing.connection import wait @@ -2769,27 +2785,27 @@ worker threads rather than worker processes. :meth:`~multiprocessing.pool.Pool.terminate` manually. *processes* is the number of worker threads to use. If *processes* is - ``None`` then the number returned by :func:`os.cpu_count` is used. + ``None`` then the number returned by :func:`os.process_cpu_count` is used. If *initializer* is not ``None`` then each worker process will call ``initializer(*initargs)`` when it starts. Unlike :class:`Pool`, *maxtasksperchild* and *context* cannot be provided. - .. note:: + .. note:: - A :class:`ThreadPool` shares the same interface as :class:`Pool`, which - is designed around a pool of processes and predates the introduction of - the :class:`concurrent.futures` module. As such, it inherits some - operations that don't make sense for a pool backed by threads, and it - has its own type for representing the status of asynchronous jobs, - :class:`AsyncResult`, that is not understood by any other libraries. + A :class:`ThreadPool` shares the same interface as :class:`Pool`, which + is designed around a pool of processes and predates the introduction of + the :class:`concurrent.futures` module. As such, it inherits some + operations that don't make sense for a pool backed by threads, and it + has its own type for representing the status of asynchronous jobs, + :class:`AsyncResult`, that is not understood by any other libraries. - Users should generally prefer to use - :class:`concurrent.futures.ThreadPoolExecutor`, which has a simpler - interface that was designed around threads from the start, and which - returns :class:`concurrent.futures.Future` instances that are - compatible with many other libraries, including :mod:`asyncio`. + Users should generally prefer to use + :class:`concurrent.futures.ThreadPoolExecutor`, which has a simpler + interface that was designed around threads from the start, and which + returns :class:`concurrent.futures.Future` instances that are + compatible with many other libraries, including :mod:`asyncio`. .. _multiprocessing-programming: @@ -2988,7 +3004,7 @@ Global variables Safe importing of main module Make sure that the main module can be safely imported by a new Python - interpreter without causing unintended side effects (such a starting a new + interpreter without causing unintended side effects (such as starting a new process). For example, using the *spawn* or *forkserver* start method diff --git a/Doc/library/multiprocessing.shared_memory.rst b/Doc/library/multiprocessing.shared_memory.rst index f453e6403d932d..671130d9b29fc0 100644 --- a/Doc/library/multiprocessing.shared_memory.rst +++ b/Doc/library/multiprocessing.shared_memory.rst @@ -36,7 +36,7 @@ or other communications requiring the serialization/deserialization and copying of data. -.. class:: SharedMemory(name=None, create=False, size=0) +.. class:: SharedMemory(name=None, create=False, size=0, *, track=True) Creates a new shared memory block or attaches to an existing shared memory block. Each shared memory block is assigned a unique name. @@ -64,26 +64,45 @@ copying of data. memory block may be larger or equal to the size requested. When attaching to an existing shared memory block, the ``size`` parameter is ignored. + *track*, when enabled, registers the shared memory block with a resource + tracker process on platforms where the OS does not do this automatically. + The resource tracker ensures proper cleanup of the shared memory even + if all other processes with access to the memory exit without doing so. + Python processes created from a common ancestor using :mod:`multiprocessing` + facilities share a single resource tracker process, and the lifetime of + shared memory segments is handled automatically among these processes. + Python processes created in any other way will receive their own + resource tracker when accessing shared memory with *track* enabled. + This will cause the shared memory to be deleted by the resource tracker + of the first process that terminates. + To avoid this issue, users of :mod:`subprocess` or standalone Python + processes should set *track* to ``False`` when there is already another + process in place that does the bookkeeping. + *track* is ignored on Windows, which has its own tracking and + automatically deletes shared memory when all handles to it have been closed. + + .. versionchanged:: 3.13 Added *track* parameter. + .. method:: close() - Closes access to the shared memory from this instance. In order to - ensure proper cleanup of resources, all instances should call - ``close()`` once the instance is no longer needed. Note that calling - ``close()`` does not cause the shared memory block itself to be - destroyed. + Closes the file descriptor/handle to the shared memory from this + instance. :meth:`close()` should be called once access to the shared + memory block from this instance is no longer needed. Depending + on operating system, the underlying memory may or may not be freed + even if all handles to it have been closed. To ensure proper cleanup, + use the :meth:`unlink()` method. .. method:: unlink() - Requests that the underlying shared memory block be destroyed. In - order to ensure proper cleanup of resources, ``unlink()`` should be - called once (and only once) across all processes which have need - for the shared memory block. After requesting its destruction, a - shared memory block may or may not be immediately destroyed and - this behavior may differ across platforms. Attempts to access data - inside the shared memory block after ``unlink()`` has been called may - result in memory access errors. Note: the last process relinquishing - its hold on a shared memory block may call ``unlink()`` and - :meth:`close()` in either order. + Deletes the underlying shared memory block. This should be called only + once per shared memory block regardless of the number of handles to it, + even in other processes. + :meth:`unlink()` and :meth:`close()` can be called in any order, but + trying to access data inside a shared memory block after :meth:`unlink()` + may result in memory access errors, depending on platform. + + This method has no effect on Windows, where the only way to delete a + shared memory block is to close all handles. .. attribute:: buf diff --git a/Doc/library/numbers.rst b/Doc/library/numbers.rst index b3dce151aee289..17d1a275f04c9b 100644 --- a/Doc/library/numbers.rst +++ b/Doc/library/numbers.rst @@ -8,7 +8,7 @@ -------------- -The :mod:`numbers` module (:pep:`3141`) defines a hierarchy of numeric +The :mod:`!numbers` module (:pep:`3141`) defines a hierarchy of numeric :term:`abstract base classes ` which progressively define more operations. None of the types defined in this module are intended to be instantiated. @@ -45,7 +45,7 @@ The numeric tower .. class:: Real - To :class:`Complex`, :class:`Real` adds the operations that work on real + To :class:`Complex`, :class:`!Real` adds the operations that work on real numbers. In short, those are: a conversion to :class:`float`, :func:`math.trunc`, @@ -126,7 +126,8 @@ We want to implement the arithmetic operations so that mixed-mode operations either call an implementation whose author knew about the types of both arguments, or convert both to the nearest built in type and do the operation there. For subtypes of :class:`Integral`, this -means that :meth:`__add__` and :meth:`__radd__` should be defined as:: +means that :meth:`~object.__add__` and :meth:`~object.__radd__` should be +defined as:: class MyIntegral(Integral): @@ -160,27 +161,27 @@ refer to ``MyIntegral`` and ``OtherTypeIKnowAbout`` as of :class:`Complex` (``a : A <: Complex``), and ``b : B <: Complex``. I'll consider ``a + b``: - 1. If ``A`` defines an :meth:`__add__` which accepts ``b``, all is - well. - 2. If ``A`` falls back to the boilerplate code, and it were to - return a value from :meth:`__add__`, we'd miss the possibility - that ``B`` defines a more intelligent :meth:`__radd__`, so the - boilerplate should return :const:`NotImplemented` from - :meth:`__add__`. (Or ``A`` may not implement :meth:`__add__` at - all.) - 3. Then ``B``'s :meth:`__radd__` gets a chance. If it accepts - ``a``, all is well. - 4. If it falls back to the boilerplate, there are no more possible - methods to try, so this is where the default implementation - should live. - 5. If ``B <: A``, Python tries ``B.__radd__`` before - ``A.__add__``. This is ok, because it was implemented with - knowledge of ``A``, so it can handle those instances before - delegating to :class:`Complex`. +1. If ``A`` defines an :meth:`~object.__add__` which accepts ``b``, all is + well. +2. If ``A`` falls back to the boilerplate code, and it were to + return a value from :meth:`~object.__add__`, we'd miss the possibility + that ``B`` defines a more intelligent :meth:`~object.__radd__`, so the + boilerplate should return :const:`NotImplemented` from + :meth:`!__add__`. (Or ``A`` may not implement :meth:`!__add__` at + all.) +3. Then ``B``'s :meth:`~object.__radd__` gets a chance. If it accepts + ``a``, all is well. +4. If it falls back to the boilerplate, there are no more possible + methods to try, so this is where the default implementation + should live. +5. If ``B <: A``, Python tries ``B.__radd__`` before + ``A.__add__``. This is ok, because it was implemented with + knowledge of ``A``, so it can handle those instances before + delegating to :class:`Complex`. If ``A <: Complex`` and ``B <: Real`` without sharing any other knowledge, then the appropriate shared operation is the one involving the built -in :class:`complex`, and both :meth:`__radd__` s land there, so ``a+b +in :class:`complex`, and both :meth:`~object.__radd__` s land there, so ``a+b == b+a``. Because most of the operations on any given type will be very similar, diff --git a/Doc/library/operator.rst b/Doc/library/operator.rst index 57c67bcf3aa12e..96f2c287875d41 100644 --- a/Doc/library/operator.rst +++ b/Doc/library/operator.rst @@ -306,7 +306,7 @@ expect a function argument. itemgetter(*items) Return a callable object that fetches *item* from its operand using the - operand's :meth:`__getitem__` method. If multiple items are specified, + operand's :meth:`~object.__getitem__` method. If multiple items are specified, returns a tuple of lookup values. For example: * After ``f = itemgetter(2)``, the call ``f(r)`` returns ``r[2]``. @@ -326,7 +326,7 @@ expect a function argument. return tuple(obj[item] for item in items) return g - The items can be any type accepted by the operand's :meth:`__getitem__` + The items can be any type accepted by the operand's :meth:`~object.__getitem__` method. Dictionaries accept any :term:`hashable` value. Lists, tuples, and strings accept an index or a slice: diff --git a/Doc/library/os.path.rst b/Doc/library/os.path.rst index 6f9e0853bc8947..95933f56d50542 100644 --- a/Doc/library/os.path.rst +++ b/Doc/library/os.path.rst @@ -377,7 +377,8 @@ the :mod:`glob` module.) Return the canonical path of the specified filename, eliminating any symbolic links encountered in the path (if they are supported by the operating - system). + system). On Windows, this function will also resolve MS-DOS (also called 8.3) + style names such as ``C:\\PROGRA~1`` to ``C:\\Program Files``. If a path doesn't exist or a symlink loop is encountered, and *strict* is ``True``, :exc:`OSError` is raised. If *strict* is ``False``, the path is diff --git a/Doc/library/os.rst b/Doc/library/os.rst index 9735baa5bc0f3a..637191f2980a05 100644 --- a/Doc/library/os.rst +++ b/Doc/library/os.rst @@ -88,8 +88,8 @@ startup by the :c:func:`PyConfig_Read` function: see On some systems, conversion using the file system encoding may fail. In this case, Python uses the :ref:`surrogateescape encoding error handler `, which means that undecodable bytes are replaced by a - Unicode character U+DCxx on decoding, and these are again translated to the - original byte on encoding. + Unicode character U+DC\ *xx* on decoding, and these are again + translated to the original byte on encoding. The :term:`file system encoding ` must @@ -215,7 +215,7 @@ process and user. On some platforms, including FreeBSD and macOS, setting ``environ`` may cause memory leaks. Refer to the system documentation for - :c:func:`putenv`. + :c:func:`!putenv`. You can delete items in this mapping to unset environment variables. :func:`unsetenv` will be called automatically when an item is deleted from @@ -564,7 +564,7 @@ process and user. .. note:: On some platforms, including FreeBSD and macOS, setting ``environ`` may - cause memory leaks. Refer to the system documentation for :c:func:`putenv`. + cause memory leaks. Refer to the system documentation for :c:func:`!putenv`. .. audit-event:: os.putenv key,value os.putenv @@ -646,7 +646,7 @@ process and user. .. function:: setpgrp() - Call the system call :c:func:`setpgrp` or ``setpgrp(0, 0)`` depending on + Call the system call :c:func:`!setpgrp` or ``setpgrp(0, 0)`` depending on which version is implemented (if any). See the Unix manual for the semantics. .. availability:: Unix, not Emscripten, not WASI. @@ -654,7 +654,7 @@ process and user. .. function:: setpgid(pid, pgrp, /) - Call the system call :c:func:`setpgid` to set the process group id of the + Call the system call :c:func:`!setpgid` to set the process group id of the process with id *pid* to the process group with id *pgrp*. See the Unix manual for the semantics. @@ -1001,11 +1001,14 @@ as internal buffering of data. .. audit-event:: os.chmod path,mode,dir_fd os.fchmod - .. availability:: Unix. + .. availability:: Unix, Windows. The function is limited on Emscripten and WASI, see :ref:`wasm-availability` for more information. + .. versionchanged:: 3.13 + Added support on Windows. + .. function:: fchown(fd, uid, gid) @@ -1077,7 +1080,7 @@ as internal buffering of data. .. function:: fsync(fd) Force write of file with filedescriptor *fd* to disk. On Unix, this calls the - native :c:func:`fsync` function; on Windows, the MS :c:func:`_commit` function. + native :c:func:`!fsync` function; on Windows, the MS :c:func:`!_commit` function. If you're starting with a buffered Python :term:`file object` *f*, first do ``f.flush()``, and then do ``os.fsync(f.fileno())``, to ensure that all internal @@ -1163,25 +1166,65 @@ as internal buffering of data. .. versionadded:: 3.11 -.. function:: lseek(fd, pos, how, /) +.. function:: lseek(fd, pos, whence, /) Set the current position of file descriptor *fd* to position *pos*, modified - by *how*: :const:`SEEK_SET` or ``0`` to set the position relative to the - beginning of the file; :const:`SEEK_CUR` or ``1`` to set it relative to the - current position; :const:`SEEK_END` or ``2`` to set it relative to the end of - the file. Return the new cursor position in bytes, starting from the beginning. + by *whence*, and return the new position in bytes relative to + the start of the file. + Valid values for *whence* are: + + * :const:`SEEK_SET` or ``0`` -- set *pos* relative to the beginning of the file + * :const:`SEEK_CUR` or ``1`` -- set *pos* relative to the current file position + * :const:`SEEK_END` or ``2`` -- set *pos* relative to the end of the file + * :const:`SEEK_HOLE` -- set *pos* to the next data location, relative to *pos* + * :const:`SEEK_DATA` -- set *pos* to the next data hole, relative to *pos* + + .. versionchanged:: 3.3 + + Add support for :const:`!SEEK_HOLE` and :const:`!SEEK_DATA`. .. data:: SEEK_SET SEEK_CUR SEEK_END - Parameters to the :func:`lseek` function. Their values are 0, 1, and 2, - respectively. + Parameters to the :func:`lseek` function and the :meth:`~io.IOBase.seek` + method on :term:`file-like objects `, + for whence to adjust the file position indicator. + + :const:`SEEK_SET` + Adjust the file position relative to the beginning of the file. + :const:`SEEK_CUR` + Adjust the file position relative to the current file position. + :const:`SEEK_END` + Adjust the file position relative to the end of the file. + + Their values are 0, 1, and 2, respectively. + + +.. data:: SEEK_HOLE + SEEK_DATA + + Parameters to the :func:`lseek` function and the :meth:`~io.IOBase.seek` + method on :term:`file-like objects `, + for seeking file data and holes on sparsely allocated files. + + :data:`!SEEK_DATA` + Adjust the file offset to the next location containing data, + relative to the seek position. + + :data:`!SEEK_HOLE` + Adjust the file offset to the next location containing a hole, + relative to the seek position. + A hole is defined as a sequence of zeros. + + .. note:: + + These operations only make sense for filesystems that support them. + + .. availability:: Linux >= 3.1, macOS, Unix .. versionadded:: 3.3 - Some operating systems could support additional values, like - :const:`os.SEEK_HOLE` or :const:`os.SEEK_DATA`. .. function:: open(path, flags, mode=0o777, *, dir_fd=None) @@ -1578,25 +1621,6 @@ or `the MSDN `_ on Windo Parameters *out* and *in* was renamed to *out_fd* and *in_fd*. -.. function:: set_blocking(fd, blocking, /) - - Set the blocking mode of the specified file descriptor. Set the - :data:`O_NONBLOCK` flag if blocking is ``False``, clear the flag otherwise. - - See also :func:`get_blocking` and :meth:`socket.socket.setblocking`. - - .. availability:: Unix, Windows. - - The function is limited on Emscripten and WASI, see - :ref:`wasm-availability` for more information. - - On Windows, this function is limited to pipes. - - .. versionadded:: 3.5 - - .. versionchanged:: 3.12 - Added support for pipes on Windows. - .. data:: SF_NODISKIO SF_MNOWAIT SF_SYNC @@ -1618,6 +1642,26 @@ or `the MSDN `_ on Windo .. versionadded:: 3.11 +.. function:: set_blocking(fd, blocking, /) + + Set the blocking mode of the specified file descriptor. Set the + :data:`O_NONBLOCK` flag if blocking is ``False``, clear the flag otherwise. + + See also :func:`get_blocking` and :meth:`socket.socket.setblocking`. + + .. availability:: Unix, Windows. + + The function is limited on Emscripten and WASI, see + :ref:`wasm-availability` for more information. + + On Windows, this function is limited to pipes. + + .. versionadded:: 3.5 + + .. versionchanged:: 3.12 + Added support for pipes on Windows. + + .. function:: splice(src, dst, count, offset_src=None, offset_dst=None) Transfer *count* bytes from file descriptor *src*, starting from offset @@ -2021,6 +2065,7 @@ features: Although Windows supports :func:`chmod`, you can only set the file's read-only flag with it (via the ``stat.S_IWRITE`` and ``stat.S_IREAD`` constants or a corresponding integer value). All other bits are ignored. + The default value of *follow_symlinks* is ``False`` on Windows. The function is limited on Emscripten and WASI, see :ref:`wasm-availability` for more information. @@ -2034,6 +2079,10 @@ features: .. versionchanged:: 3.6 Accepts a :term:`path-like object`. + .. versionchanged:: 3.13 + Added support for a file descriptor and the *follow_symlinks* argument + on Windows. + .. function:: chown(path, uid, gid, *, dir_fd=None, follow_symlinks=True) @@ -2119,13 +2168,19 @@ features: for possible values of *mode*. As of Python 3.3, this is equivalent to ``os.chmod(path, mode, follow_symlinks=False)``. + ``lchmod()`` is not part of POSIX, but Unix implementations may have it if + changing the mode of symbolic links is supported. + .. audit-event:: os.chmod path,mode,dir_fd os.lchmod - .. availability:: Unix. + .. availability:: Unix, Windows, not Linux, FreeBSD >= 1.3, NetBSD >= 1.3, not OpenBSD .. versionchanged:: 3.6 Accepts a :term:`path-like object`. + .. versionchanged:: 3.13 + Added support on Windows. + .. function:: lchown(path, uid, gid) Change the owner and group id of *path* to the numeric *uid* and *gid*. This @@ -2264,7 +2319,7 @@ features: .. function:: lstat(path, *, dir_fd=None) - Perform the equivalent of an :c:func:`lstat` system call on the given path. + Perform the equivalent of an :c:func:`!lstat` system call on the given path. Similar to :func:`~os.stat`, but does not follow symbolic links. Return a :class:`stat_result` object. @@ -3107,14 +3162,16 @@ features: Windows file attributes: ``dwFileAttributes`` member of the ``BY_HANDLE_FILE_INFORMATION`` structure returned by - :c:func:`GetFileInformationByHandle`. See the ``FILE_ATTRIBUTE_*`` + :c:func:`!GetFileInformationByHandle`. + See the :const:`!FILE_ATTRIBUTE_* ` constants in the :mod:`stat` module. .. attribute:: st_reparse_tag - When :attr:`st_file_attributes` has the ``FILE_ATTRIBUTE_REPARSE_POINT`` + When :attr:`st_file_attributes` has the :const:`~stat.FILE_ATTRIBUTE_REPARSE_POINT` set, this field contains the tag identifying the type of reparse point. - See the ``IO_REPARSE_TAG_*`` constants in the :mod:`stat` module. + See the :const:`IO_REPARSE_TAG_* ` + constants in the :mod:`stat` module. The standard module :mod:`stat` defines functions and constants that are useful for extracting information from a :c:struct:`stat` structure. (On @@ -3172,7 +3229,7 @@ features: .. function:: statvfs(path) - Perform a :c:func:`statvfs` system call on the given path. The return value is + Perform a :c:func:`!statvfs` system call on the given path. The return value is an object whose attributes describe the filesystem on the given path, and correspond to the members of the :c:struct:`statvfs` structure, namely: :attr:`f_bsize`, :attr:`f_frsize`, :attr:`f_blocks`, :attr:`f_bfree`, @@ -3738,6 +3795,217 @@ features: .. versionadded:: 3.10 +Timer File Descriptors +~~~~~~~~~~~~~~~~~~~~~~ + +.. versionadded:: 3.13 + +These functions provide support for Linux's *timer file descriptor* API. +Naturally, they are all only available on Linux. + +.. function:: timerfd_create(clockid, /, *, flags=0) + + Create and return a timer file descriptor (*timerfd*). + + The file descriptor returned by :func:`timerfd_create` supports: + + - :func:`read` + - :func:`~select.select` + - :func:`~select.poll` + + The file descriptor's :func:`read` method can be called with a buffer size + of 8. If the timer has already expired one or more times, :func:`read` + returns the number of expirations with the host's endianness, which may be + converted to an :class:`int` by ``int.from_bytes(x, byteorder=sys.byteorder)``. + + :func:`~select.select` and :func:`~select.poll` can be used to wait until + timer expires and the file descriptor is readable. + + *clockid* must be a valid :ref:`clock ID `, + as defined in the :py:mod:`time` module: + + - :const:`time.CLOCK_REALTIME` + - :const:`time.CLOCK_MONOTONIC` + - :const:`time.CLOCK_BOOTTIME` (Since Linux 3.15 for timerfd_create) + + If *clockid* is :const:`time.CLOCK_REALTIME`, a settable system-wide + real-time clock is used. If system clock is changed, timer setting need + to be updated. To cancel timer when system clock is changed, see + :const:`TFD_TIMER_CANCEL_ON_SET`. + + If *clockid* is :const:`time.CLOCK_MONOTONIC`, a non-settable monotonically + increasing clock is used. Even if the system clock is changed, the timer + setting will not be affected. + + If *clockid* is :const:`time.CLOCK_BOOTTIME`, same as :const:`time.CLOCK_MONOTONIC` + except it includes any time that the system is suspended. + + The file descriptor's behaviour can be modified by specifying a *flags* value. + Any of the following variables may used, combined using bitwise OR + (the ``|`` operator): + + - :const:`TFD_NONBLOCK` + - :const:`TFD_CLOEXEC` + + If :const:`TFD_NONBLOCK` is not set as a flag, :func:`read` blocks until + the timer expires. If it is set as a flag, :func:`read` doesn't block, but + If there hasn't been an expiration since the last call to read, + :func:`read` raises :class:`OSError` with ``errno`` is set to + :const:`errno.EAGAIN`. + + :const:`TFD_CLOEXEC` is always set by Python automatically. + + The file descriptor must be closed with :func:`os.close` when it is no + longer needed, or else the file descriptor will be leaked. + + .. seealso:: The :manpage:`timerfd_create(2)` man page. + + .. availability:: Linux >= 2.6.27 with glibc >= 2.8 + + .. versionadded:: 3.13 + + +.. function:: timerfd_settime(fd, /, *, flags=flags, initial=0.0, interval=0.0) + + Alter a timer file descriptor's internal timer. + This function operates the same interval timer as :func:`timerfd_settime_ns`. + + *fd* must be a valid timer file descriptor. + + The timer's behaviour can be modified by specifying a *flags* value. + Any of the following variables may used, combined using bitwise OR + (the ``|`` operator): + + - :const:`TFD_TIMER_ABSTIME` + - :const:`TFD_TIMER_CANCEL_ON_SET` + + The timer is disabled by setting *initial* to zero (``0``). + If *initial* is equal to or greater than zero, the timer is enabled. + If *initial* is less than zero, it raises an :class:`OSError` exception + with ``errno`` set to :const:`errno.EINVAL` + + By default the timer will fire when *initial* seconds have elapsed. + (If *initial* is zero, timer will fire immediately.) + + However, if the :const:`TFD_TIMER_ABSTIME` flag is set, + the timer will fire when the timer's clock + (set by *clockid* in :func:`timerfd_create`) reaches *initial* seconds. + + The timer's interval is set by the *interval* :py:class:`float`. + If *interval* is zero, the timer only fires once, on the initial expiration. + If *interval* is greater than zero, the timer fires every time *interval* + seconds have elapsed since the previous expiration. + If *interval* is less than zero, it raises :class:`OSError` with ``errno`` + set to :const:`errno.EINVAL` + + If the :const:`TFD_TIMER_CANCEL_ON_SET` flag is set along with + :const:`TFD_TIMER_ABSTIME` and the clock for this timer is + :const:`time.CLOCK_REALTIME`, the timer is marked as cancelable if the + real-time clock is changed discontinuously. Reading the descriptor is + aborted with the error ECANCELED. + + Linux manages system clock as UTC. A daylight-savings time transition is + done by changing time offset only and doesn't cause discontinuous system + clock change. + + Discontinuous system clock change will be caused by the following events: + + - ``settimeofday`` + - ``clock_settime`` + - set the system date and time by ``date`` command + + Return a two-item tuple of (``next_expiration``, ``interval``) from + the previous timer state, before this function executed. + + .. seealso:: + + :manpage:`timerfd_create(2)`, :manpage:`timerfd_settime(2)`, + :manpage:`settimeofday(2)`, :manpage:`clock_settime(2)`, + and :manpage:`date(1)`. + + .. availability:: Linux >= 2.6.27 with glibc >= 2.8 + + .. versionadded:: 3.13 + + +.. function:: timerfd_settime_ns(fd, /, *, flags=0, initial=0, interval=0) + + Similar to :func:`timerfd_settime`, but use time as nanoseconds. + This function operates the same interval timer as :func:`timerfd_settime`. + + .. availability:: Linux >= 2.6.27 with glibc >= 2.8 + + .. versionadded:: 3.13 + + +.. function:: timerfd_gettime(fd, /) + + Return a two-item tuple of floats (``next_expiration``, ``interval``). + + ``next_expiration`` denotes the relative time until next the timer next fires, + regardless of if the :const:`TFD_TIMER_ABSTIME` flag is set. + + ``interval`` denotes the timer's interval. + If zero, the timer will only fire once, after ``next_expiration`` seconds + have elapsed. + + .. seealso:: :manpage:`timerfd_gettime(2)` + + .. availability:: Linux >= 2.6.27 with glibc >= 2.8 + + .. versionadded:: 3.13 + + +.. function:: timerfd_gettime_ns(fd, /) + + Similar to :func:`timerfd_gettime`, but return time as nanoseconds. + + .. availability:: Linux >= 2.6.27 with glibc >= 2.8 + + .. versionadded:: 3.13 + +.. data:: TFD_NONBLOCK + + A flag for the :func:`timerfd_create` function, + which sets the :const:`O_NONBLOCK` status flag for the new timer file + descriptor. If :const:`TFD_NONBLOCK` is not set as a flag, :func:`read` blocks. + + .. availability:: Linux >= 2.6.27 with glibc >= 2.8 + + .. versionadded:: 3.13 + +.. data:: TFD_CLOEXEC + + A flag for the :func:`timerfd_create` function, + If :const:`TFD_CLOEXEC` is set as a flag, set close-on-exec flag for new file + descriptor. + + .. availability:: Linux >= 2.6.27 with glibc >= 2.8 + + .. versionadded:: 3.13 + +.. data:: TFD_TIMER_ABSTIME + + A flag for the :func:`timerfd_settime` and :func:`timerfd_settime_ns` functions. + If this flag is set, *initial* is interpreted as an absolute value on the + timer's clock (in UTC seconds or nanoseconds since the Unix Epoch). + + .. availability:: Linux >= 2.6.27 with glibc >= 2.8 + + .. versionadded:: 3.13 + +.. data:: TFD_TIMER_CANCEL_ON_SET + + A flag for the :func:`timerfd_settime` and :func:`timerfd_settime_ns` + functions along with :const:`TFD_TIMER_ABSTIME`. + The timer is cancelled when the time of the underlying clock changes + discontinuously. + + .. availability:: Linux >= 2.6.27 with glibc >= 2.8 + + .. versionadded:: 3.13 + + Linux extended attributes ~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -3916,7 +4184,7 @@ to be ignored. The "l" and "v" variants of the :func:`exec\* ` functions differ in how command-line arguments are passed. The "l" variants are perhaps the easiest to work with if the number of parameters is fixed when the code is written; the - individual parameters simply become additional parameters to the :func:`execl\*` + individual parameters simply become additional parameters to the :func:`!execl\*` functions. The "v" variants are good when the number of parameters is variable, with the arguments being passed in a list or tuple as the *args* parameter. In either case, the arguments to the child process should start with @@ -4114,15 +4382,43 @@ written in Python, such as a mail server's external command delivery program. .. audit-event:: os.fork "" os.fork + .. warning:: + + If you use TLS sockets in an application calling ``fork()``, see + the warning in the :mod:`ssl` documentation. + + .. warning:: + + On macOS the use of this function is unsafe when mixed with using + higher-level system APIs, and that includes using :mod:`urllib.request`. + .. versionchanged:: 3.8 Calling ``fork()`` in a subinterpreter is no longer supported (:exc:`RuntimeError` is raised). - .. warning:: - - See :mod:`ssl` for applications that use the SSL module with fork(). + .. versionchanged:: 3.12 + If Python is able to detect that your process has multiple + threads, :func:`os.fork` now raises a :exc:`DeprecationWarning`. + + We chose to surface this as a warning, when detectable, to better + inform developers of a design problem that the POSIX platform + specifically notes as not supported. Even in code that + *appears* to work, it has never been safe to mix threading with + :func:`os.fork` on POSIX platforms. The CPython runtime itself has + always made API calls that are not safe for use in the child + process when threads existed in the parent (such as ``malloc`` and + ``free``). + + Users of macOS or users of libc or malloc implementations other + than those typically found in glibc to date are among those + already more likely to experience deadlocks running such code. + + See `this discussion on fork being incompatible with threads + `_ + for technical details of why we're surfacing this longstanding + platform compatibility problem to developers. - .. availability:: Unix, not Emscripten, not WASI. + .. availability:: POSIX, not Emscripten, not WASI. .. function:: forkpty() @@ -4135,6 +4431,16 @@ written in Python, such as a mail server's external command delivery program. .. audit-event:: os.forkpty "" os.forkpty + .. warning:: + + On macOS the use of this function is unsafe when mixed with using + higher-level system APIs, and that includes using :mod:`urllib.request`. + + .. versionchanged:: 3.12 + If Python is able to detect that your process has multiple + threads, this now raises a :exc:`DeprecationWarning`. See the + longer explanation on :func:`os.fork`. + .. versionchanged:: 3.8 Calling ``forkpty()`` in a subinterpreter is no longer supported (:exc:`RuntimeError` is raised). @@ -4263,12 +4569,13 @@ written in Python, such as a mail server's external command delivery program. setpgroup=None, resetids=False, setsid=False, setsigmask=(), \ setsigdef=(), scheduler=None) - Wraps the :c:func:`posix_spawn` C library API for use from Python. + Wraps the :c:func:`!posix_spawn` C library API for use from Python. Most users should use :func:`subprocess.run` instead of :func:`posix_spawn`. The positional-only arguments *path*, *args*, and *env* are similar to - :func:`execve`. + :func:`execve`. *env* is allowed to be ``None``, in which case current + process' environment is used. The *path* parameter is the path to the executable file. The *path* should contain a directory. Use :func:`posix_spawnp` to pass an executable file @@ -4298,17 +4605,24 @@ written in Python, such as a mail server's external command delivery program. Performs ``os.dup2(fd, new_fd)``. + .. data:: POSIX_SPAWN_CLOSEFROM + + (``os.POSIX_SPAWN_CLOSEFROM``, *fd*) + + Performs ``os.closerange(fd, INF)``. + These tuples correspond to the C library - :c:func:`posix_spawn_file_actions_addopen`, - :c:func:`posix_spawn_file_actions_addclose`, and - :c:func:`posix_spawn_file_actions_adddup2` API calls used to prepare - for the :c:func:`posix_spawn` call itself. + :c:func:`!posix_spawn_file_actions_addopen`, + :c:func:`!posix_spawn_file_actions_addclose`, + :c:func:`!posix_spawn_file_actions_adddup2`, and + :c:func:`!posix_spawn_file_actions_addclosefrom_np` API calls used to prepare + for the :c:func:`!posix_spawn` call itself. The *setpgroup* argument will set the process group of the child to the value specified. If the value specified is 0, the child's process group ID will be made the same as its process ID. If the value of *setpgroup* is not set, the child will inherit the parent's process group ID. This argument corresponds - to the C library :c:macro:`POSIX_SPAWN_SETPGROUP` flag. + to the C library :c:macro:`!POSIX_SPAWN_SETPGROUP` flag. If the *resetids* argument is ``True`` it will reset the effective UID and GID of the child to the real UID and GID of the parent process. If the @@ -4316,40 +4630,47 @@ written in Python, such as a mail server's external command delivery program. the parent. In either case, if the set-user-ID and set-group-ID permission bits are enabled on the executable file, their effect will override the setting of the effective UID and GID. This argument corresponds to the C - library :c:macro:`POSIX_SPAWN_RESETIDS` flag. + library :c:macro:`!POSIX_SPAWN_RESETIDS` flag. If the *setsid* argument is ``True``, it will create a new session ID - for ``posix_spawn``. *setsid* requires :c:macro:`POSIX_SPAWN_SETSID` - or :c:macro:`POSIX_SPAWN_SETSID_NP` flag. Otherwise, :exc:`NotImplementedError` + for ``posix_spawn``. *setsid* requires :c:macro:`!POSIX_SPAWN_SETSID` + or :c:macro:`!POSIX_SPAWN_SETSID_NP` flag. Otherwise, :exc:`NotImplementedError` is raised. The *setsigmask* argument will set the signal mask to the signal set specified. If the parameter is not used, then the child inherits the parent's signal mask. This argument corresponds to the C library - :c:macro:`POSIX_SPAWN_SETSIGMASK` flag. + :c:macro:`!POSIX_SPAWN_SETSIGMASK` flag. The *sigdef* argument will reset the disposition of all signals in the set specified. This argument corresponds to the C library - :c:macro:`POSIX_SPAWN_SETSIGDEF` flag. + :c:macro:`!POSIX_SPAWN_SETSIGDEF` flag. The *scheduler* argument must be a tuple containing the (optional) scheduler policy and an instance of :class:`sched_param` with the scheduler parameters. A value of ``None`` in the place of the scheduler policy indicates that is not being provided. This argument is a combination of the C library - :c:macro:`POSIX_SPAWN_SETSCHEDPARAM` and :c:macro:`POSIX_SPAWN_SETSCHEDULER` + :c:macro:`!POSIX_SPAWN_SETSCHEDPARAM` and :c:macro:`!POSIX_SPAWN_SETSCHEDULER` flags. .. audit-event:: os.posix_spawn path,argv,env os.posix_spawn .. versionadded:: 3.8 + .. versionchanged:: 3.13 + *env* parameter accepts ``None``. + + .. versionchanged:: 3.13 + ``os.POSIX_SPAWN_CLOSEFROM`` is available on platforms where + :c:func:`!posix_spawn_file_actions_addclosefrom_np` exists. + .. availability:: Unix, not Emscripten, not WASI. .. function:: posix_spawnp(path, argv, env, *, file_actions=None, \ setpgroup=None, resetids=False, setsid=False, setsigmask=(), \ setsigdef=(), scheduler=None) - Wraps the :c:func:`posix_spawnp` C library API for use from Python. + Wraps the :c:func:`!posix_spawnp` C library API for use from Python. Similar to :func:`posix_spawn` except that the system searches for the *executable* file in the list of directories specified by the @@ -4426,7 +4747,7 @@ written in Python, such as a mail server's external command delivery program. command-line arguments are passed. The "l" variants are perhaps the easiest to work with if the number of parameters is fixed when the code is written; the individual parameters simply become additional parameters to the - :func:`spawnl\*` functions. The "v" variants are good when the number of + :func:`!spawnl\*` functions. The "v" variants are good when the number of parameters is variable, with the arguments being passed in a list or tuple as the *args* parameter. In either case, the arguments to the child process must start with the name of the command being run. @@ -4476,7 +4797,7 @@ written in Python, such as a mail server's external command delivery program. P_NOWAITO Possible values for the *mode* parameter to the :func:`spawn\* ` family of - functions. If either of these values is given, the :func:`spawn\*` functions + functions. If either of these values is given, the :func:`spawn\* ` functions will return as soon as the new process has been created, with the process id as the return value. @@ -4486,7 +4807,7 @@ written in Python, such as a mail server's external command delivery program. .. data:: P_WAIT Possible value for the *mode* parameter to the :func:`spawn\* ` family of - functions. If this is given as *mode*, the :func:`spawn\*` functions will not + functions. If this is given as *mode*, the :func:`spawn\* ` functions will not return until the new process has run to completion and will return the exit code of the process the run is successful, or ``-signal`` if a signal kills the process. @@ -4530,7 +4851,7 @@ written in Python, such as a mail server's external command delivery program. Use *show_cmd* to override the default window style. Whether this has any effect will depend on the application being launched. Values are integers as - supported by the Win32 :c:func:`ShellExecute` function. + supported by the Win32 :c:func:`!ShellExecute` function. :func:`startfile` returns as soon as the associated application is launched. There is no option to wait for the application to close, and no way to retrieve @@ -4540,7 +4861,7 @@ written in Python, such as a mail server's external command delivery program. :func:`os.path.normpath` function to ensure that paths are properly encoded for Win32. - To reduce interpreter startup overhead, the Win32 :c:func:`ShellExecute` + To reduce interpreter startup overhead, the Win32 :c:func:`!ShellExecute` function is not resolved until this function is first called. If the function cannot be resolved, :exc:`NotImplementedError` will be raised. @@ -4667,6 +4988,9 @@ written in Python, such as a mail server's external command delivery program. .. versionadded:: 3.3 + .. versionchanged:: 3.13 + This function is now available on macOS as well. + .. function:: waitpid(pid, options, /) @@ -5070,8 +5394,12 @@ operating system. .. function:: sched_getaffinity(pid, /) - Return the set of CPUs the process with PID *pid* (or the current process - if zero) is restricted to. + Return the set of CPUs the process with PID *pid* is restricted to. + + If *pid* is zero, return the set of CPUs the calling thread of the current + process is restricted to. + + See also the :func:`process_cpu_count` function. .. _os-path: @@ -5112,15 +5440,18 @@ Miscellaneous System Information .. function:: cpu_count() - Return the number of CPUs in the system. Returns ``None`` if undetermined. - - This number is not equivalent to the number of CPUs the current process can - use. The number of usable CPUs can be obtained with - ``len(os.sched_getaffinity(0))`` + Return the number of logical CPUs in the **system**. Returns ``None`` if + undetermined. + The :func:`process_cpu_count` function can be used to get the number of + logical CPUs usable by the calling thread of the **current process**. .. versionadded:: 3.4 + .. versionchanged:: 3.13 + If :option:`-X cpu_count <-X>` is given or :envvar:`PYTHON_CPU_COUNT` is set, + :func:`cpu_count` returns the overridden value *n*. + .. function:: getloadavg() @@ -5131,6 +5462,23 @@ Miscellaneous System Information .. availability:: Unix. +.. function:: process_cpu_count() + + Get the number of logical CPUs usable by the calling thread of the **current + process**. Returns ``None`` if undetermined. It can be less than + :func:`cpu_count` depending on the CPU affinity. + + The :func:`cpu_count` function can be used to get the number of logical CPUs + in the **system**. + + If :option:`-X cpu_count <-X>` is given or :envvar:`PYTHON_CPU_COUNT` is set, + :func:`process_cpu_count` returns the overridden value *n*. + + See also the :func:`sched_getaffinity` functions. + + .. versionadded:: 3.13 + + .. function:: sysconf(name, /) Return integer-valued system configuration values. If the configuration value diff --git a/Doc/library/pathlib.rst b/Doc/library/pathlib.rst index 22360b22fd924b..60791725c2323d 100644 --- a/Doc/library/pathlib.rst +++ b/Doc/library/pathlib.rst @@ -306,7 +306,7 @@ Pure paths provide the following methods and properties: .. attribute:: PurePath.pathmod The implementation of the :mod:`os.path` module used for low-level path - operations: either ``posixpath`` or ``ntpath``. + operations: either :mod:`posixpath` or :mod:`ntpath`. .. versionadded:: 3.13 @@ -595,6 +595,9 @@ Pure paths provide the following methods and properties: >>> PurePath('a/b.py').match(pattern) True + .. versionchanged:: 3.12 + Accepts an object implementing the :class:`os.PathLike` interface. + As with other methods, case-sensitivity follows platform defaults:: >>> PurePosixPath('b.py').match('*.PY') @@ -850,6 +853,42 @@ call fails (for example because the path doesn't exist). .. versionadded:: 3.5 +.. classmethod:: Path.from_uri(uri) + + Return a new path object from parsing a 'file' URI conforming to + :rfc:`8089`. For example:: + + >>> p = Path.from_uri('file:///etc/hosts') + PosixPath('/etc/hosts') + + On Windows, DOS device and UNC paths may be parsed from URIs:: + + >>> p = Path.from_uri('file:///c:/windows') + WindowsPath('c:/windows') + >>> p = Path.from_uri('file://server/share') + WindowsPath('//server/share') + + Several variant forms are supported:: + + >>> p = Path.from_uri('file:////server/share') + WindowsPath('//server/share') + >>> p = Path.from_uri('file://///server/share') + WindowsPath('//server/share') + >>> p = Path.from_uri('file:c:/windows') + WindowsPath('c:/windows') + >>> p = Path.from_uri('file:/c|/windows') + WindowsPath('c:/windows') + + :exc:`ValueError` is raised if the URI does not start with ``file:``, or + the parsed path isn't absolute. + + :func:`os.fsdecode` is used to decode percent-escaped byte sequences, and + so file URIs are not portable across machines with different + :ref:`filesystem encodings `. + + .. versionadded:: 3.13 + + .. method:: Path.stat(*, follow_symlinks=True) Return a :class:`os.stat_result` object containing information about this path, like :func:`os.stat`. @@ -981,15 +1020,21 @@ call fails (for example because the path doesn't exist). future Python release, patterns with this ending will match both files and directories. Add a trailing slash to match only directories. -.. method:: Path.group() +.. method:: Path.group(*, follow_symlinks=True) - Return the name of the group owning the file. :exc:`KeyError` is raised + Return the name of the group owning the file. :exc:`KeyError` is raised if the file's gid isn't found in the system database. + This method normally follows symlinks; to get the group of the symlink, add + the argument ``follow_symlinks=False``. + .. versionchanged:: 3.13 Raises :exc:`UnsupportedOperation` if the :mod:`grp` module is not available. In previous versions, :exc:`NotImplementedError` was raised. + .. versionchanged:: 3.13 + The *follow_symlinks* parameter was added. + .. method:: Path.is_dir(*, follow_symlinks=True) @@ -1255,15 +1300,21 @@ call fails (for example because the path doesn't exist). '#!/usr/bin/env python3\n' -.. method:: Path.owner() +.. method:: Path.owner(*, follow_symlinks=True) - Return the name of the user owning the file. :exc:`KeyError` is raised + Return the name of the user owning the file. :exc:`KeyError` is raised if the file's uid isn't found in the system database. + This method normally follows symlinks; to get the owner of the symlink, add + the argument ``follow_symlinks=False``. + .. versionchanged:: 3.13 Raises :exc:`UnsupportedOperation` if the :mod:`pwd` module is not available. In previous versions, :exc:`NotImplementedError` was raised. + .. versionchanged:: 3.13 + The *follow_symlinks* parameter was added. + .. method:: Path.read_bytes() @@ -1278,7 +1329,7 @@ call fails (for example because the path doesn't exist). .. versionadded:: 3.5 -.. method:: Path.read_text(encoding=None, errors=None) +.. method:: Path.read_text(encoding=None, errors=None, newline=None) Return the decoded contents of the pointed-to file as a string:: @@ -1293,6 +1344,8 @@ call fails (for example because the path doesn't exist). .. versionadded:: 3.5 + .. versionchanged:: 3.13 + The *newline* parameter was added. .. method:: Path.readlink() @@ -1381,15 +1434,19 @@ call fails (for example because the path doesn't exist). >>> p.resolve() PosixPath('/home/antoine/pathlib/setup.py') - If the path doesn't exist and *strict* is ``True``, :exc:`FileNotFoundError` - is raised. If *strict* is ``False``, the path is resolved as far as possible - and any remainder is appended without checking whether it exists. If an - infinite loop is encountered along the resolution path, :exc:`RuntimeError` - is raised. + If a path doesn't exist or a symlink loop is encountered, and *strict* is + ``True``, :exc:`OSError` is raised. If *strict* is ``False``, the path is + resolved as far as possible and any remainder is appended without checking + whether it exists. .. versionchanged:: 3.6 The *strict* parameter was added (pre-3.6 behavior is strict). + .. versionchanged:: 3.13 + Symlink loops are treated like other errors: :exc:`OSError` is raised in + strict mode, and no exception is raised in non-strict mode. In previous + versions, :exc:`RuntimeError` is raised no matter the value of *strict*. + .. method:: Path.rglob(pattern, *, case_sensitive=None, follow_symlinks=None) Glob the given relative *pattern* recursively. This is like calling diff --git a/Doc/library/pdb.rst b/Doc/library/pdb.rst index ef52370bff8058..2495dcf50bb17f 100644 --- a/Doc/library/pdb.rst +++ b/Doc/library/pdb.rst @@ -175,8 +175,8 @@ slightly different way: .. function:: pm() - Enter post-mortem debugging of the traceback found in - :data:`sys.last_traceback`. + Enter post-mortem debugging of the exception found in + :data:`sys.last_exc`. The ``run*`` functions and :func:`set_trace` are aliases for instantiating the @@ -252,6 +252,10 @@ change a variable or call a function. When an exception occurs in such a statement, the exception name is printed but the debugger's state is not changed. +.. versionchanged:: 3.13 + Expressions/Statements whose prefix is a pdb command are now correctly + identified and executed. + The debugger supports :ref:`aliases `. Aliases can have parameters which allows one a certain level of adaptability to the context under examination. @@ -566,17 +570,34 @@ can be overridden by the local file. Start an interactive interpreter (using the :mod:`code` module) whose global namespace contains all the (global and local) names found in the current - scope. + scope. Use ``exit()`` or ``quit()`` to exit the interpreter and return to + the debugger. + + .. note:: + + Because interact creates a new global namespace with the current global + and local namespace for execution, assignment to variables will not + affect the original namespaces. + However, modification to the mutable objects will be reflected in the + original namespaces. .. versionadded:: 3.2 + .. versionadded:: 3.13 + ``exit()`` and ``quit()`` can be used to exit :pdbcmd:`interact` + command. + + .. versionchanged:: 3.13 + :pdbcmd:`interact` directs its output to the debugger's + output channel rather than :data:`sys.stderr`. + .. _debugger-aliases: .. pdbcommand:: alias [name [command]] Create an alias called *name* that executes *command*. The *command* must *not* be enclosed in quotes. Replaceable parameters can be indicated by - ``%1``, ``%2``, and so on, while ``%*`` is replaced by all the parameters. + ``%1``, ``%2``, ... and ``%9``, while ``%*`` is replaced by all the parameters. If *command* is omitted, the current alias for *name* is shown. If no arguments are given, all aliases are listed. @@ -639,6 +660,55 @@ can be overridden by the local file. Print the return value for the last return of the current function. +.. pdbcommand:: exceptions [excnumber] + + List or jump between chained exceptions. + + When using ``pdb.pm()`` or ``Pdb.post_mortem(...)`` with a chained exception + instead of a traceback, it allows the user to move between the + chained exceptions using ``exceptions`` command to list exceptions, and + ``exception `` to switch to that exception. + + + Example:: + + def out(): + try: + middle() + except Exception as e: + raise ValueError("reraise middle() error") from e + + def middle(): + try: + return inner(0) + except Exception as e: + raise ValueError("Middle fail") + + def inner(x): + 1 / x + + out() + + calling ``pdb.pm()`` will allow to move between exceptions:: + + > example.py(5)out() + -> raise ValueError("reraise middle() error") from e + + (Pdb) exceptions + 0 ZeroDivisionError('division by zero') + 1 ValueError('Middle fail') + > 2 ValueError('reraise middle() error') + + (Pdb) exceptions 0 + > example.py(16)inner() + -> 1 / x + + (Pdb) up + > example.py(10)middle() + -> return inner(0) + + .. versionadded:: 3.13 + .. rubric:: Footnotes .. [1] Whether a frame is considered to originate in a certain module diff --git a/Doc/library/pickle.rst b/Doc/library/pickle.rst index ba00ba29f5ba48..cfb251fca5c7cd 100644 --- a/Doc/library/pickle.rst +++ b/Doc/library/pickle.rst @@ -345,6 +345,10 @@ The :mod:`pickle` module exports three classes, :class:`Pickler`, See :ref:`pickle-persistent` for details and examples of uses. + .. versionchanged:: 3.13 + Add the default implementation of this method in the C implementation + of :class:`!Pickler`. + .. attribute:: dispatch_table A pickler object's dispatch table is a registry of *reduction @@ -446,6 +450,10 @@ The :mod:`pickle` module exports three classes, :class:`Pickler`, See :ref:`pickle-persistent` for details and examples of uses. + .. versionchanged:: 3.13 + Add the default implementation of this method in the C implementation + of :class:`!Unpickler`. + .. method:: find_class(module, name) Import *module* if necessary and return the object called *name* from it, @@ -494,7 +502,8 @@ What can be pickled and unpickled? The following types can be pickled: -* ``None``, ``True``, and ``False``; +* built-in constants (``None``, ``True``, ``False``, ``Ellipsis``, and + ``NotImplemented``); * integers, floating-point numbers, complex numbers; diff --git a/Doc/library/pickletools.rst b/Doc/library/pickletools.rst index 480f4a6d320815..41930f8cbe8412 100644 --- a/Doc/library/pickletools.rst +++ b/Doc/library/pickletools.rst @@ -17,6 +17,8 @@ are useful for Python core developers who are working on the :mod:`pickle`; ordinary users of the :mod:`pickle` module probably won't find the :mod:`pickletools` module relevant. +.. _pickletools-cli: + Command line usage ------------------ @@ -51,24 +53,24 @@ Command line options .. program:: pickletools -.. cmdoption:: -a, --annotate +.. option:: -a, --annotate Annotate each line with a short opcode description. -.. cmdoption:: -o, --output= +.. option:: -o, --output= Name of a file where the output should be written. -.. cmdoption:: -l, --indentlevel= +.. option:: -l, --indentlevel= The number of blanks by which to indent a new MARK level. -.. cmdoption:: -m, --memo +.. option:: -m, --memo When multiple objects are disassembled, preserve memo between disassemblies. -.. cmdoption:: -p, --preamble= +.. option:: -p, --preamble= When more than one pickle file are specified, print given preamble before each disassembly. diff --git a/Doc/library/plistlib.rst b/Doc/library/plistlib.rst index 732ef3536863cc..7416ca2650bab4 100644 --- a/Doc/library/plistlib.rst +++ b/Doc/library/plistlib.rst @@ -27,7 +27,7 @@ top level object is a dictionary. To write out and to parse a plist file, use the :func:`dump` and :func:`load` functions. -To work with plist data in bytes objects, use :func:`dumps` +To work with plist data in bytes or string objects, use :func:`dumps` and :func:`loads`. Values can be strings, integers, floats, booleans, tuples, lists, dictionaries @@ -52,7 +52,7 @@ or :class:`datetime.datetime` objects. This module defines the following functions: -.. function:: load(fp, *, fmt=None, dict_type=dict) +.. function:: load(fp, *, fmt=None, dict_type=dict, aware_datetime=False) Read a plist file. *fp* should be a readable and binary file object. Return the unpacked root object (which usually is a @@ -69,6 +69,10 @@ This module defines the following functions: The *dict_type* is the type used for dictionaries that are read from the plist file. + When *aware_datetime* is true, fields with type ``datetime.datetime`` will + be created as :ref:`aware object `, with + :attr:`!tzinfo` as :attr:`datetime.UTC`. + XML data for the :data:`FMT_XML` format is parsed using the Expat parser from :mod:`xml.parsers.expat` -- see its documentation for possible exceptions on ill-formed XML. Unknown elements will simply be ignored @@ -79,16 +83,21 @@ This module defines the following functions: .. versionadded:: 3.4 + .. versionchanged:: 3.13 + The keyword-only parameter *aware_datetime* has been added. + -.. function:: loads(data, *, fmt=None, dict_type=dict) +.. function:: loads(data, *, fmt=None, dict_type=dict, aware_datetime=False) - Load a plist from a bytes object. See :func:`load` for an explanation of - the keyword arguments. + Load a plist from a bytes or string object. See :func:`load` for an + explanation of the keyword arguments. .. versionadded:: 3.4 + .. versionchanged:: 3.13 + *data* can be a string when *fmt* equals :data:`FMT_XML`. -.. function:: dump(value, fp, *, fmt=FMT_XML, sort_keys=True, skipkeys=False) +.. function:: dump(value, fp, *, fmt=FMT_XML, sort_keys=True, skipkeys=False, aware_datetime=False) Write *value* to a plist file. *Fp* should be a writable, binary file object. @@ -107,6 +116,10 @@ This module defines the following functions: When *skipkeys* is false (the default) the function raises :exc:`TypeError` when a key of a dictionary is not a string, otherwise such keys are skipped. + When *aware_datetime* is true and any field with type ``datetime.datetime`` + is set as a :ref:`aware object `, it will convert to + UTC timezone before writing it. + A :exc:`TypeError` will be raised if the object is of an unsupported type or a container that contains objects of unsupported types. @@ -115,8 +128,11 @@ This module defines the following functions: .. versionadded:: 3.4 + .. versionchanged:: 3.13 + The keyword-only parameter *aware_datetime* has been added. + -.. function:: dumps(value, *, fmt=FMT_XML, sort_keys=True, skipkeys=False) +.. function:: dumps(value, *, fmt=FMT_XML, sort_keys=True, skipkeys=False, aware_datetime=False) Return *value* as a plist-formatted bytes object. See the documentation for :func:`dump` for an explanation of the keyword diff --git a/Doc/library/posix.rst b/Doc/library/posix.rst index 0413f9d02a8d57..5871574b442667 100644 --- a/Doc/library/posix.rst +++ b/Doc/library/posix.rst @@ -11,6 +11,8 @@ This module provides access to operating system functionality that is standardized by the C Standard and the POSIX standard (a thinly disguised Unix interface). +.. availability:: Unix. + .. index:: pair: module; os **Do not import this module directly.** Instead, import the module :mod:`os`, diff --git a/Doc/library/profile.rst b/Doc/library/profile.rst index 723f927135a0f4..cc059b66fcb84b 100644 --- a/Doc/library/profile.rst +++ b/Doc/library/profile.rst @@ -82,8 +82,8 @@ the following:: The first line indicates that 214 calls were monitored. Of those calls, 207 were :dfn:`primitive`, meaning that the call was not induced via recursion. The -next line: ``Ordered by: cumulative time``, indicates that the text string in the -far right column was used to sort the output. The column headings include: +next line: ``Ordered by: cumulative time`` indicates the output is sorted +by the ``cumtime`` values. The column headings include: ncalls for the number of calls. @@ -121,6 +121,8 @@ results to a file by specifying a filename to the :func:`run` function:: The :class:`pstats.Stats` class reads profile results from a file and formats them in various ways. +.. _profile-cli: + The files :mod:`cProfile` and :mod:`profile` can also be invoked as a script to profile another script. For example:: @@ -133,11 +135,11 @@ the output by. This only applies when ``-o`` is not supplied. ``-m`` specifies that a module is being profiled instead of a script. - .. versionadded:: 3.7 - Added the ``-m`` option to :mod:`cProfile`. +.. versionadded:: 3.7 + Added the ``-m`` option to :mod:`cProfile`. - .. versionadded:: 3.8 - Added the ``-m`` option to :mod:`profile`. +.. versionadded:: 3.8 + Added the ``-m`` option to :mod:`profile`. The :mod:`pstats` module's :class:`~pstats.Stats` class has a variety of methods for manipulating and printing the data saved into a profile results file:: diff --git a/Doc/library/pty.rst b/Doc/library/pty.rst index ad4981c97119fa..bd2f5ed45cb8b4 100644 --- a/Doc/library/pty.rst +++ b/Doc/library/pty.rst @@ -16,6 +16,8 @@ The :mod:`pty` module defines operations for handling the pseudo-terminal concept: starting another process and being able to write to and read from its controlling terminal programmatically. +.. availability:: Unix. + Pseudo-terminal handling is highly platform dependent. This code is mainly tested on Linux, FreeBSD, and macOS (it is supposed to work on other POSIX platforms but it's not been thoroughly tested). @@ -31,6 +33,9 @@ The :mod:`pty` module defines the following functions: file descriptor connected to the child's controlling terminal (and also to the child's standard input and output). + .. warning:: On macOS the use of this function is unsafe when mixed with using + higher-level system APIs, and that includes using :mod:`urllib.request`. + .. function:: openpty() diff --git a/Doc/library/pwd.rst b/Doc/library/pwd.rst index 300419301b9ff5..dbe68cd14ec4d4 100644 --- a/Doc/library/pwd.rst +++ b/Doc/library/pwd.rst @@ -10,7 +10,7 @@ This module provides access to the Unix user account and password database. It is available on all Unix versions. -.. include:: ../includes/wasm-notavail.rst +.. availability:: Unix, not Emscripten, not WASI. Password database entries are reported as a tuple-like object, whose attributes correspond to the members of the ``passwd`` structure (Attribute field below, diff --git a/Doc/library/py_compile.rst b/Doc/library/py_compile.rst index 69b93a3bdfcb26..38c416f9ad0305 100644 --- a/Doc/library/py_compile.rst +++ b/Doc/library/py_compile.rst @@ -125,6 +125,7 @@ byte-code cache files in the directory containing the source code. This option is useful when the ``.pycs`` are kept up to date by some system external to Python like a build system. +.. _py_compile-cli: Command-Line Interface ---------------------- @@ -138,13 +139,13 @@ not be compiled. .. program:: python -m py_compile -.. cmdoption:: ... - - +.. option:: ... + - Positional arguments are files to compile. If ``-`` is the only parameter, the list of files is taken from standard input. -.. cmdoption:: -q, --quiet +.. option:: -q, --quiet Suppress errors output. diff --git a/Doc/library/pyclbr.rst b/Doc/library/pyclbr.rst index 1c40ba4838ca75..1e9876849b02f3 100644 --- a/Doc/library/pyclbr.rst +++ b/Doc/library/pyclbr.rst @@ -58,106 +58,115 @@ of these classes. Function Objects ---------------- -Class :class:`Function` instances describe functions defined by def -statements. They have the following attributes: +.. class:: Function -.. attribute:: Function.file + Class :class:`!Function` instances describe functions defined by def + statements. They have the following attributes: - Name of the file in which the function is defined. + .. attribute:: file -.. attribute:: Function.module + Name of the file in which the function is defined. - The name of the module defining the function described. + .. attribute:: module -.. attribute:: Function.name + The name of the module defining the function described. - The name of the function. + .. attribute:: name -.. attribute:: Function.lineno + The name of the function. - The line number in the file where the definition starts. + .. attribute:: lineno -.. attribute:: Function.parent + The line number in the file where the definition starts. - For top-level functions, None. For nested functions, the parent. - .. versionadded:: 3.7 + .. attribute:: parent + For top-level functions, ``None``. For nested functions, the parent. -.. attribute:: Function.children + .. versionadded:: 3.7 - A dictionary mapping names to descriptors for nested functions and - classes. - .. versionadded:: 3.7 + .. attribute:: children + A :class:`dictionary ` mapping names to descriptors for nested functions and + classes. -.. attribute:: Function.is_async + .. versionadded:: 3.7 - ``True`` for functions that are defined with the ``async`` prefix, ``False`` otherwise. - .. versionadded:: 3.10 + .. attribute:: is_async + + ``True`` for functions that are defined with the + :keyword:`async ` prefix, ``False`` otherwise. + + .. versionadded:: 3.10 .. _pyclbr-class-objects: Class Objects ------------- -Class :class:`Class` instances describe classes defined by class -statements. They have the same attributes as Functions and two more. + +.. class:: Class + + Class :class:`!Class` instances describe classes defined by class + statements. They have the same attributes as :class:`Functions ` + and two more. -.. attribute:: Class.file + .. attribute:: file - Name of the file in which the class is defined. + Name of the file in which the class is defined. -.. attribute:: Class.module + .. attribute:: module - The name of the module defining the class described. + The name of the module defining the class described. -.. attribute:: Class.name + .. attribute:: name - The name of the class. + The name of the class. -.. attribute:: Class.lineno + .. attribute:: lineno - The line number in the file where the definition starts. + The line number in the file where the definition starts. -.. attribute:: Class.parent + .. attribute:: parent - For top-level classes, None. For nested classes, the parent. + For top-level classes, None. For nested classes, the parent. - .. versionadded:: 3.7 + .. versionadded:: 3.7 -.. attribute:: Class.children + .. attribute:: children - A dictionary mapping names to descriptors for nested functions and - classes. + A dictionary mapping names to descriptors for nested functions and + classes. - .. versionadded:: 3.7 + .. versionadded:: 3.7 -.. attribute:: Class.super + .. attribute:: super - A list of :class:`Class` objects which describe the immediate base - classes of the class being described. Classes which are named as - superclasses but which are not discoverable by :func:`readmodule_ex` - are listed as a string with the class name instead of as - :class:`Class` objects. + A list of :class:`!Class` objects which describe the immediate base + classes of the class being described. Classes which are named as + superclasses but which are not discoverable by :func:`readmodule_ex` + are listed as a string with the class name instead of as + :class:`!Class` objects. -.. attribute:: Class.methods + .. attribute:: methods - A dictionary mapping method names to line numbers. This can be - derived from the newer children dictionary, but remains for - back-compatibility. + A :class:`dictionary ` mapping method names to line numbers. + This can be derived from the newer :attr:`children` dictionary, + but remains for + back-compatibility. diff --git a/Doc/library/python.rst b/Doc/library/python.rst index f39613f572884f..610435999d9f48 100644 --- a/Doc/library/python.rst +++ b/Doc/library/python.rst @@ -12,6 +12,7 @@ overview: .. toctree:: sys.rst + sys.monitoring.rst sysconfig.rst builtins.rst __main__.rst diff --git a/Doc/library/random.rst b/Doc/library/random.rst index 76ae97a8be7e63..d0ced2416c9578 100644 --- a/Doc/library/random.rst +++ b/Doc/library/random.rst @@ -34,10 +34,8 @@ instance of the :class:`random.Random` class. You can instantiate your own instances of :class:`Random` to get generators that don't share state. Class :class:`Random` can also be subclassed if you want to use a different -basic generator of your own devising: in that case, override the :meth:`~Random.random`, -:meth:`~Random.seed`, :meth:`~Random.getstate`, and :meth:`~Random.setstate` methods. -Optionally, a new generator can supply a :meth:`~Random.getrandbits` method --- this -allows :meth:`randrange` to produce selections over an arbitrarily large range. +basic generator of your own devising: see the documentation on that class for +more details. The :mod:`random` module also provides the :class:`SystemRandom` class which uses the system function :func:`os.urandom` to generate random numbers @@ -88,7 +86,7 @@ Bookkeeping functions .. versionchanged:: 3.11 The *seed* must be one of the following types: - *NoneType*, :class:`int`, :class:`float`, :class:`str`, + ``None``, :class:`int`, :class:`float`, :class:`str`, :class:`bytes`, or :class:`bytearray`. .. function:: getstate() @@ -220,8 +218,8 @@ Functions for sequences generated. For example, a sequence of length 2080 is the largest that can fit within the period of the Mersenne Twister random number generator. - .. deprecated-removed:: 3.9 3.11 - The optional parameter *random*. + .. versionchanged:: 3.11 + Removed the optional parameter *random*. .. function:: sample(population, k, *, counts=None) @@ -407,11 +405,42 @@ Alternative Generator Class that implements the default pseudo-random number generator used by the :mod:`random` module. - .. deprecated-removed:: 3.9 3.11 + .. versionchanged:: 3.11 Formerly the *seed* could be any hashable object. Now it is limited to: - :class:`NoneType`, :class:`int`, :class:`float`, :class:`str`, + ``None``, :class:`int`, :class:`float`, :class:`str`, :class:`bytes`, or :class:`bytearray`. + Subclasses of :class:`!Random` should override the following methods if they + wish to make use of a different basic generator: + + .. method:: Random.seed(a=None, version=2) + + Override this method in subclasses to customise the :meth:`~random.seed` + behaviour of :class:`!Random` instances. + + .. method:: Random.getstate() + + Override this method in subclasses to customise the :meth:`~random.getstate` + behaviour of :class:`!Random` instances. + + .. method:: Random.setstate(state) + + Override this method in subclasses to customise the :meth:`~random.setstate` + behaviour of :class:`!Random` instances. + + .. method:: Random.random() + + Override this method in subclasses to customise the :meth:`~random.random` + behaviour of :class:`!Random` instances. + + Optionally, a custom generator subclass can also supply the following method: + + .. method:: Random.getrandbits(k) + + Override this method in subclasses to customise the + :meth:`~random.getrandbits` behaviour of :class:`!Random` instances. + + .. class:: SystemRandom([seed]) Class that uses the :func:`os.urandom` function for generating random numbers @@ -445,30 +474,30 @@ Examples Basic examples:: - >>> random() # Random float: 0.0 <= x < 1.0 + >>> random() # Random float: 0.0 <= x < 1.0 0.37444887175646646 - >>> uniform(2.5, 10.0) # Random float: 2.5 <= x <= 10.0 + >>> uniform(2.5, 10.0) # Random float: 2.5 <= x <= 10.0 3.1800146073117523 - >>> expovariate(1 / 5) # Interval between arrivals averaging 5 seconds + >>> expovariate(1 / 5) # Interval between arrivals averaging 5 seconds 5.148957571865031 - >>> randrange(10) # Integer from 0 to 9 inclusive + >>> randrange(10) # Integer from 0 to 9 inclusive 7 - >>> randrange(0, 101, 2) # Even integer from 0 to 100 inclusive + >>> randrange(0, 101, 2) # Even integer from 0 to 100 inclusive 26 - >>> choice(['win', 'lose', 'draw']) # Single random element from a sequence + >>> choice(['win', 'lose', 'draw']) # Single random element from a sequence 'draw' >>> deck = 'ace two three four'.split() - >>> shuffle(deck) # Shuffle a list + >>> shuffle(deck) # Shuffle a list >>> deck ['four', 'two', 'ace', 'three'] - >>> sample([10, 20, 30, 40, 50], k=4) # Four samples without replacement + >>> sample([10, 20, 30, 40, 50], k=4) # Four samples without replacement [40, 10, 50, 30] Simulations:: @@ -572,14 +601,14 @@ Simulation of arrival times and service deliveries for a multiserver queue:: including simulation, sampling, shuffling, and cross-validation. `Economics Simulation - `_ + `_ a simulation of a marketplace by `Peter Norvig `_ that shows effective use of many of the tools and distributions provided by this module (gauss, uniform, sample, betavariate, choice, triangular, and randrange). `A Concrete Introduction to Probability (using Python) - `_ + `_ a tutorial by `Peter Norvig `_ covering the basics of probability theory, how to write simulations, and how to perform data analysis using Python. diff --git a/Doc/library/re.rst b/Doc/library/re.rst index 367a14824f01ad..5bb93390aa5f79 100644 --- a/Doc/library/re.rst +++ b/Doc/library/re.rst @@ -176,7 +176,7 @@ The special characters are: ``x*+``, ``x++`` and ``x?+`` are equivalent to ``(?>x*)``, ``(?>x+)`` and ``(?>x?)`` correspondingly. - .. versionadded:: 3.11 + .. versionadded:: 3.11 .. index:: single: {} (curly brackets); in regular expressions @@ -697,7 +697,7 @@ three digits in length. Unknown escapes consisting of ``'\'`` and an ASCII letter now are errors. .. versionchanged:: 3.8 - The ``'\N{name}'`` escape sequence has been added. As in string literals, + The :samp:`'\\N\\{{name}\\}'` escape sequence has been added. As in string literals, it expands to the named Unicode character (e.g. ``'\N{EM DASH}'``). @@ -907,18 +907,17 @@ Functions .. function:: search(pattern, string, flags=0) Scan through *string* looking for the first location where the regular expression - *pattern* produces a match, and return a corresponding :ref:`match object - `. Return ``None`` if no position in the string matches the - pattern; note that this is different from finding a zero-length match at some - point in the string. + *pattern* produces a match, and return a corresponding :class:`~re.Match`. Return + ``None`` if no position in the string matches the pattern; note that this is + different from finding a zero-length match at some point in the string. .. function:: match(pattern, string, flags=0) If zero or more characters at the beginning of *string* match the regular - expression *pattern*, return a corresponding :ref:`match object - `. Return ``None`` if the string does not match the pattern; - note that this is different from a zero-length match. + expression *pattern*, return a corresponding :class:`~re.Match`. Return + ``None`` if the string does not match the pattern; note that this is + different from a zero-length match. Note that even in :const:`MULTILINE` mode, :func:`re.match` will only match at the beginning of the string and not at the beginning of each line. @@ -930,9 +929,8 @@ Functions .. function:: fullmatch(pattern, string, flags=0) If the whole *string* matches the regular expression *pattern*, return a - corresponding :ref:`match object `. Return ``None`` if the - string does not match the pattern; note that this is different from a - zero-length match. + corresponding :class:`~re.Match`. Return ``None`` if the string does not match + the pattern; note that this is different from a zero-length match. .. versionadded:: 3.4 @@ -949,7 +947,7 @@ Functions ['Words', 'words', 'words', ''] >>> re.split(r'(\W+)', 'Words, words, words.') ['Words', ', ', 'words', ', ', 'words', '.', ''] - >>> re.split(r'\W+', 'Words, words, words.', 1) + >>> re.split(r'\W+', 'Words, words, words.', maxsplit=1) ['Words', 'words, words.'] >>> re.split('[a-f]+', '0a3B9', flags=re.IGNORECASE) ['0', '3', '9'] @@ -982,6 +980,11 @@ Functions .. versionchanged:: 3.7 Added support of splitting on a pattern that could match an empty string. + .. deprecated:: 3.13 + Passing *maxsplit* and *flags* as positional arguments is deprecated. + In future Python versions they will be + :ref:`keyword-only parameters `. + .. function:: findall(pattern, string, flags=0) @@ -1007,7 +1010,7 @@ Functions .. function:: finditer(pattern, string, flags=0) - Return an :term:`iterator` yielding :ref:`match objects ` over + Return an :term:`iterator` yielding :class:`~re.Match` objects over all non-overlapping matches for the RE *pattern* in *string*. The *string* is scanned left-to-right, and matches are returned in the order found. Empty matches are included in the result. @@ -1035,8 +1038,8 @@ Functions 'static PyObject*\npy_myfunc(void)\n{' If *repl* is a function, it is called for every non-overlapping occurrence of - *pattern*. The function takes a single :ref:`match object ` - argument, and returns the replacement string. For example:: + *pattern*. The function takes a single :class:`~re.Match` argument, and returns + the replacement string. For example:: >>> def dashrepl(matchobj): ... if matchobj.group(0) == '-': return ' ' @@ -1047,7 +1050,7 @@ Functions >>> re.sub(r'\sAND\s', ' & ', 'Baked Beans And Spam', flags=re.IGNORECASE) 'Baked Beans & Spam' - The pattern may be a string or a :ref:`pattern object `. + The pattern may be a string or a :class:`~re.Pattern`. The optional argument *count* is the maximum number of pattern occurrences to be replaced; *count* must be a non-negative integer. If omitted or zero, all @@ -1080,8 +1083,6 @@ Functions .. versionchanged:: 3.7 Unknown escapes in *repl* consisting of ``'\'`` and an ASCII letter now are errors. - - .. versionchanged:: 3.7 Empty matches for the pattern are replaced when adjacent to a previous non-empty match. @@ -1090,18 +1091,17 @@ Functions In :class:`bytes` replacement strings, group *name* can only contain bytes in the ASCII range (``b'\x00'``-``b'\x7f'``). + .. deprecated:: 3.13 + Passing *count* and *flags* as positional arguments is deprecated. + In future Python versions they will be + :ref:`keyword-only parameters `. + .. function:: subn(pattern, repl, string, count=0, flags=0) Perform the same operation as :func:`sub`, but return a tuple ``(new_string, number_of_subs_made)``. - .. versionchanged:: 3.1 - Added the optional flags argument. - - .. versionchanged:: 3.5 - Unmatched groups are replaced with an empty string. - .. function:: escape(pattern) @@ -1146,12 +1146,12 @@ Functions Exceptions ^^^^^^^^^^ -.. exception:: error(msg, pattern=None, pos=None) +.. exception:: PatternError(msg, pattern=None, pos=None) Exception raised when a string passed to one of the functions here is not a valid regular expression (for example, it might contain unmatched parentheses) or when some other error occurs during compilation or matching. It is never an - error if a string contains no match for a pattern. The error instance has + error if a string contains no match for a pattern. The ``PatternError`` instance has the following additional attributes: .. attribute:: msg @@ -1177,21 +1177,29 @@ Exceptions .. versionchanged:: 3.5 Added additional attributes. + .. versionchanged:: 3.13 + ``PatternError`` was originally named ``error``; the latter is kept as an alias for + backward compatibility. + .. _re-objects: Regular Expression Objects -------------------------- -Compiled regular expression objects support the following methods and -attributes: +.. class:: Pattern + + Compiled regular expression object returned by :func:`re.compile`. + + .. versionchanged:: 3.9 + :py:class:`re.Pattern` supports ``[]`` to indicate a Unicode (str) or bytes pattern. + See :ref:`types-genericalias`. .. method:: Pattern.search(string[, pos[, endpos]]) Scan through *string* looking for the first location where this regular - expression produces a match, and return a corresponding :ref:`match object - `. Return ``None`` if no position in the string matches the - pattern; note that this is different from finding a zero-length match at some - point in the string. + expression produces a match, and return a corresponding :class:`~re.Match`. + Return ``None`` if no position in the string matches the pattern; note that + this is different from finding a zero-length match at some point in the string. The optional second parameter *pos* gives an index in the string where the search is to start; it defaults to ``0``. This is not completely equivalent to @@ -1215,9 +1223,9 @@ attributes: .. method:: Pattern.match(string[, pos[, endpos]]) If zero or more characters at the *beginning* of *string* match this regular - expression, return a corresponding :ref:`match object `. - Return ``None`` if the string does not match the pattern; note that this is - different from a zero-length match. + expression, return a corresponding :class:`~re.Match`. Return ``None`` if the + string does not match the pattern; note that this is different from a + zero-length match. The optional *pos* and *endpos* parameters have the same meaning as for the :meth:`~Pattern.search` method. :: @@ -1234,8 +1242,8 @@ attributes: .. method:: Pattern.fullmatch(string[, pos[, endpos]]) If the whole *string* matches this regular expression, return a corresponding - :ref:`match object `. Return ``None`` if the string does not - match the pattern; note that this is different from a zero-length match. + :class:`~re.Match`. Return ``None`` if the string does not match the pattern; + note that this is different from a zero-length match. The optional *pos* and *endpos* parameters have the same meaning as for the :meth:`~Pattern.search` method. :: @@ -1321,8 +1329,13 @@ when there is no match, you can test whether there was a match with a simple if match: process(match) -Match objects support the following methods and attributes: +.. class:: Match + + Match object returned by successful ``match``\ es and ``search``\ es. + .. versionchanged:: 3.9 + :py:class:`re.Match` supports ``[]`` to indicate a Unicode (str) or bytes match. + See :ref:`types-genericalias`. .. method:: Match.expand(template) @@ -1709,7 +1722,7 @@ because the address has spaces, our splitting pattern, in it: .. doctest:: :options: +NORMALIZE_WHITESPACE - >>> [re.split(":? ", entry, 3) for entry in entries] + >>> [re.split(":? ", entry, maxsplit=3) for entry in entries] [['Ross', 'McFluff', '834.345.1254', '155 Elm Street'], ['Ronald', 'Heathmore', '892.345.3428', '436 Finley Avenue'], ['Frank', 'Burger', '925.541.7625', '662 South Dogwood Way'], @@ -1722,7 +1735,7 @@ house number from the street name: .. doctest:: :options: +NORMALIZE_WHITESPACE - >>> [re.split(":? ", entry, 4) for entry in entries] + >>> [re.split(":? ", entry, maxsplit=4) for entry in entries] [['Ross', 'McFluff', '834.345.1254', '155', 'Elm Street'], ['Ronald', 'Heathmore', '892.345.3428', '436', 'Finley Avenue'], ['Frank', 'Burger', '925.541.7625', '662', 'South Dogwood Way'], @@ -1766,10 +1779,10 @@ Finding all Adverbs and their Positions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ If one wants more information about all matches of a pattern than the matched -text, :func:`finditer` is useful as it provides :ref:`match objects -` instead of strings. Continuing with the previous example, if -a writer wanted to find all of the adverbs *and their positions* in -some text, they would use :func:`finditer` in the following manner:: +text, :func:`finditer` is useful as it provides :class:`~re.Match` objects +instead of strings. Continuing with the previous example, if a writer wanted +to find all of the adverbs *and their positions* in some text, they would use +:func:`finditer` in the following manner:: >>> text = "He was carefully disguised but captured quickly by police." >>> for m in re.finditer(r"\w+ly\b", text): diff --git a/Doc/library/readline.rst b/Doc/library/readline.rst index 8fb0eca8df74d8..1adafcaa02eab9 100644 --- a/Doc/library/readline.rst +++ b/Doc/library/readline.rst @@ -27,16 +27,15 @@ Readline library in general. .. note:: The underlying Readline library API may be implemented by - the ``libedit`` library instead of GNU readline. + the ``editline`` (``libedit``) library instead of GNU readline. On macOS the :mod:`readline` module detects which library is being used at run time. - The configuration file for ``libedit`` is different from that + The configuration file for ``editline`` is different from that of GNU readline. If you programmatically load configuration strings - you can check for the text "libedit" in :const:`readline.__doc__` - to differentiate between GNU readline and libedit. + you can use :data:`backend` to determine which library is being used. - If you use *editline*/``libedit`` readline emulation on macOS, the + If you use ``editline``/``libedit`` readline emulation on macOS, the initialization file located in your home directory is named ``.editrc``. For example, the following content in ``~/.editrc`` will turn ON *vi* keybindings and TAB completion:: @@ -44,6 +43,12 @@ Readline library in general. python:bind -v python:bind ^I rl_complete +.. data:: backend + + The name of the underlying Readline library being used, either + ``"readline"`` or ``"editline"``. + + .. versionadded:: 3.13 Init file --------- @@ -213,6 +218,8 @@ Startup hooks if Python was compiled for a version of the library that supports it. +.. _readline-completion: + Completion ---------- diff --git a/Doc/library/reprlib.rst b/Doc/library/reprlib.rst index 5ebb0a7780c37b..678a11c6f45490 100644 --- a/Doc/library/reprlib.rst +++ b/Doc/library/reprlib.rst @@ -10,7 +10,7 @@ -------------- -The :mod:`reprlib` module provides a means for producing object representations +The :mod:`!reprlib` module provides a means for producing object representations with limits on the size of the resulting strings. This is used in the Python debugger and may be useful in other contexts as well. @@ -58,29 +58,31 @@ This module provides a class, an instance, and a function: limits on most sizes. In addition to size-limiting tools, the module also provides a decorator for -detecting recursive calls to :meth:`__repr__` and substituting a placeholder -string instead. +detecting recursive calls to :meth:`~object.__repr__` and substituting a +placeholder string instead. .. index:: single: ...; placeholder .. decorator:: recursive_repr(fillvalue="...") - Decorator for :meth:`__repr__` methods to detect recursive calls within the + Decorator for :meth:`~object.__repr__` methods to detect recursive calls within the same thread. If a recursive call is made, the *fillvalue* is returned, - otherwise, the usual :meth:`__repr__` call is made. For example: - - >>> from reprlib import recursive_repr - >>> class MyList(list): - ... @recursive_repr() - ... def __repr__(self): - ... return '<' + '|'.join(map(repr, self)) + '>' - ... - >>> m = MyList('abc') - >>> m.append(m) - >>> m.append('x') - >>> print(m) - <'a'|'b'|'c'|...|'x'> + otherwise, the usual :meth:`!__repr__` call is made. For example: + + .. doctest:: + + >>> from reprlib import recursive_repr + >>> class MyList(list): + ... @recursive_repr() + ... def __repr__(self): + ... return '<' + '|'.join(map(repr, self)) + '>' + ... + >>> m = MyList('abc') + >>> m.append(m) + >>> m.append('x') + >>> print(m) + <'a'|'b'|'c'|...|'x'> .. versionadded:: 3.2 @@ -148,10 +150,10 @@ which format specific object types. with no line breaks or indentation, like the standard :func:`repr`. For example: - .. code-block:: pycon + .. doctest:: indent >>> example = [ - 1, 'spam', {'a': 2, 'b': 'spam eggs', 'c': {3: 4.5, 6: []}}, 'ham'] + ... 1, 'spam', {'a': 2, 'b': 'spam eggs', 'c': {3: 4.5, 6: []}}, 'ham'] >>> import reprlib >>> aRepr = reprlib.Repr() >>> print(aRepr.repr(example)) @@ -160,7 +162,7 @@ which format specific object types. If :attr:`~Repr.indent` is set to a string, each recursion level is placed on its own line, indented by that string: - .. code-block:: pycon + .. doctest:: indent >>> aRepr.indent = '-->' >>> print(aRepr.repr(example)) @@ -181,7 +183,7 @@ which format specific object types. Setting :attr:`~Repr.indent` to a positive integer value behaves as if it was set to a string with that number of spaces: - .. code-block:: pycon + .. doctest:: indent >>> aRepr.indent = 4 >>> print(aRepr.repr(example)) @@ -234,7 +236,9 @@ Subclassing Repr Objects The use of dynamic dispatching by :meth:`Repr.repr1` allows subclasses of :class:`Repr` to add support for additional built-in object types or to modify the handling of types already supported. This example shows how special support -for file objects could be added:: +for file objects could be added: + +.. testcode:: import reprlib import sys @@ -248,3 +252,7 @@ for file objects could be added:: aRepr = MyRepr() print(aRepr.repr(sys.stdin)) # prints '' + +.. testoutput:: + + diff --git a/Doc/library/resource.rst b/Doc/library/resource.rst index a5324c82c63484..4e58b043f1da31 100644 --- a/Doc/library/resource.rst +++ b/Doc/library/resource.rst @@ -13,7 +13,7 @@ This module provides basic mechanisms for measuring and controlling system resources utilized by a program. -.. include:: ../includes/wasm-notavail.rst +.. availability:: Unix, not Emscripten, not WASI. Symbolic constants are used to specify particular system resources and to request usage information about either the current process or its children. @@ -277,7 +277,7 @@ These functions are used to retrieve resource usage information: This function returns an object that describes the resources consumed by either the current process or its children, as specified by the *who* parameter. The - *who* parameter should be specified using one of the :const:`RUSAGE_\*` + *who* parameter should be specified using one of the :const:`!RUSAGE_\*` constants described below. A simple example:: @@ -353,7 +353,7 @@ These functions are used to retrieve resource usage information: Returns the number of bytes in a system page. (This need not be the same as the hardware page size.) -The following :const:`RUSAGE_\*` symbols are passed to the :func:`getrusage` +The following :const:`!RUSAGE_\*` symbols are passed to the :func:`getrusage` function to specify which processes information should be provided for. diff --git a/Doc/library/rlcompleter.rst b/Doc/library/rlcompleter.rst index 40b09ce897880e..8287699c5f013e 100644 --- a/Doc/library/rlcompleter.rst +++ b/Doc/library/rlcompleter.rst @@ -10,12 +10,14 @@ -------------- -The :mod:`rlcompleter` module defines a completion function suitable for the -:mod:`readline` module by completing valid Python identifiers and keywords. +The :mod:`!rlcompleter` module defines a completion function suitable to be +passed to :func:`~readline.set_completer` in the :mod:`readline` module. When this module is imported on a Unix platform with the :mod:`readline` module available, an instance of the :class:`Completer` class is automatically created -and its :meth:`complete` method is set as the :mod:`readline` completer. +and its :meth:`~Completer.complete` method is set as the +:ref:`readline completer `. The method provides +completion of valid Python :ref:`identifiers and keywords `. Example:: @@ -28,7 +30,7 @@ Example:: readline.__name__ readline.parse_and_bind( >>> readline. -The :mod:`rlcompleter` module is designed for use with Python's +The :mod:`!rlcompleter` module is designed for use with Python's :ref:`interactive mode `. Unless Python is run with the :option:`-S` option, the module is automatically imported and configured (see :ref:`rlcompleter-config`). @@ -39,23 +41,25 @@ this module can still be used for custom purposes. .. _completer-objects: -Completer Objects ------------------ +.. class:: Completer -Completer objects have the following method: + Completer objects have the following method: + .. method:: Completer.complete(text, state) -.. method:: Completer.complete(text, state) + Return the next possible completion for *text*. - Return the *state*\ th completion for *text*. + When called by the :mod:`readline` module, this method is called + successively with ``state == 0, 1, 2, ...`` until the method returns + ``None``. - If called for *text* that doesn't include a period character (``'.'``), it will - complete from names currently defined in :mod:`__main__`, :mod:`builtins` and - keywords (as defined by the :mod:`keyword` module). - - If called for a dotted name, it will try to evaluate anything without obvious - side-effects (functions will not be evaluated, but it can generate calls to - :meth:`__getattr__`) up to the last part, and find matches for the rest via the - :func:`dir` function. Any exception raised during the evaluation of the - expression is caught, silenced and :const:`None` is returned. + If called for *text* that doesn't include a period character (``'.'``), it will + complete from names currently defined in :mod:`__main__`, :mod:`builtins` and + keywords (as defined by the :mod:`keyword` module). + If called for a dotted name, it will try to evaluate anything without obvious + side-effects (functions will not be evaluated, but it can generate calls to + :meth:`~object.__getattr__`) up to the last part, and find matches for the + rest via the :func:`dir` function. Any exception raised during the + evaluation of the expression is caught, silenced and :const:`None` is + returned. diff --git a/Doc/library/runpy.rst b/Doc/library/runpy.rst index 42ed8c253b8027..406b080b7be30f 100644 --- a/Doc/library/runpy.rst +++ b/Doc/library/runpy.rst @@ -39,7 +39,7 @@ The :mod:`runpy` module provides two functions: The *mod_name* argument should be an absolute module name. If the module name refers to a package rather than a normal - module, then that package is imported and the ``__main__`` submodule within + module, then that package is imported and the :mod:`__main__` submodule within that package is then executed and the resulting module globals dictionary returned. @@ -74,7 +74,7 @@ The :mod:`runpy` module provides two functions: Note that this manipulation of :mod:`sys` is not thread-safe. Other threads may see the partially initialised module, as well as the altered list of - arguments. It is recommended that the :mod:`sys` module be left alone when + arguments. It is recommended that the ``sys`` module be left alone when invoking this function from threaded code. .. seealso:: @@ -82,7 +82,7 @@ The :mod:`runpy` module provides two functions: command line. .. versionchanged:: 3.1 - Added ability to execute packages by looking for a ``__main__`` submodule. + Added ability to execute packages by looking for a :mod:`__main__` submodule. .. versionchanged:: 3.2 Added ``__cached__`` global variable (see :pep:`3147`). @@ -106,15 +106,16 @@ The :mod:`runpy` module provides two functions: Execute the code at the named filesystem location and return the resulting module globals dictionary. As with a script name supplied to the CPython command line, the supplied path may refer to a Python source file, a - compiled bytecode file or a valid sys.path entry containing a ``__main__`` - module (e.g. a zipfile containing a top-level ``__main__.py`` file). + compiled bytecode file or a valid :data:`sys.path` entry containing a + :mod:`__main__` module + (e.g. a zipfile containing a top-level ``__main__.py`` file). For a simple script, the specified code is simply executed in a fresh - module namespace. For a valid sys.path entry (typically a zipfile or + module namespace. For a valid :data:`sys.path` entry (typically a zipfile or directory), the entry is first added to the beginning of ``sys.path``. The function then looks for and executes a :mod:`__main__` module using the updated path. Note that there is no special protection against invoking - an existing :mod:`__main__` entry located elsewhere on ``sys.path`` if + an existing ``__main__`` entry located elsewhere on ``sys.path`` if there is no such module at the specified location. The optional dictionary argument *init_globals* may be used to pre-populate @@ -137,14 +138,14 @@ The :mod:`runpy` module provides two functions: supplied path, and ``__spec__``, ``__cached__``, ``__loader__`` and ``__package__`` will all be set to :const:`None`. - If the supplied path is a reference to a valid sys.path entry, then - ``__spec__`` will be set appropriately for the imported ``__main__`` + If the supplied path is a reference to a valid :data:`sys.path` entry, then + ``__spec__`` will be set appropriately for the imported :mod:`__main__` module (that is, ``__spec__.name`` will always be ``__main__``). ``__file__``, ``__cached__``, ``__loader__`` and ``__package__`` will be :ref:`set as normal ` based on the module spec. A number of alterations are also made to the :mod:`sys` module. Firstly, - ``sys.path`` may be altered as described above. ``sys.argv[0]`` is updated + :data:`sys.path` may be altered as described above. ``sys.argv[0]`` is updated with the value of ``path_name`` and ``sys.modules[__name__]`` is updated with a temporary module object for the module being executed. All modifications to items in :mod:`sys` are reverted before the function @@ -152,7 +153,7 @@ The :mod:`runpy` module provides two functions: Note that, unlike :func:`run_module`, the alterations made to :mod:`sys` are not optional in this function as these adjustments are essential to - allowing the execution of sys.path entries. As the thread-safety + allowing the execution of :data:`sys.path` entries. As the thread-safety limitations still apply, use of this function in threaded code should be either serialised with the import lock or delegated to a separate process. @@ -165,7 +166,7 @@ The :mod:`runpy` module provides two functions: .. versionchanged:: 3.4 Updated to take advantage of the module spec feature added by :pep:`451`. This allows ``__cached__`` to be set correctly in the - case where ``__main__`` is imported from a valid sys.path entry rather + case where ``__main__`` is imported from a valid :data:`sys.path` entry rather than being executed directly. .. versionchanged:: 3.12 diff --git a/Doc/library/select.rst b/Doc/library/select.rst index c2941e628d9d78..a0058046d0ce4c 100644 --- a/Doc/library/select.rst +++ b/Doc/library/select.rst @@ -185,8 +185,8 @@ The module defines the following: ----------------------------- Solaris and derivatives have ``/dev/poll``. While :c:func:`!select` is -O(highest file descriptor) and :c:func:`!poll` is O(number of file -descriptors), ``/dev/poll`` is O(active file descriptors). +*O*\ (*highest file descriptor*) and :c:func:`!poll` is *O*\ (*number of file +descriptors*), ``/dev/poll`` is *O*\ (*active file descriptors*). ``/dev/poll`` behaviour is very close to the standard :c:func:`!poll` object. @@ -381,8 +381,8 @@ scalability for network servers that service many, many clients at the same time. :c:func:`!poll` scales better because the system call only requires listing the file descriptors of interest, while :c:func:`!select` builds a bitmap, turns on bits for the fds of interest, and then afterward the whole bitmap has to be -linearly scanned again. :c:func:`!select` is O(highest file descriptor), while -:c:func:`!poll` is O(number of file descriptors). +linearly scanned again. :c:func:`!select` is *O*\ (*highest file descriptor*), while +:c:func:`!poll` is *O*\ (*number of file descriptors*). .. method:: poll.register(fd[, eventmask]) diff --git a/Doc/library/selectors.rst b/Doc/library/selectors.rst index dd50bac37e49b8..76cbf91412f763 100644 --- a/Doc/library/selectors.rst +++ b/Doc/library/selectors.rst @@ -21,7 +21,7 @@ It defines a :class:`BaseSelector` abstract base class, along with several concrete implementations (:class:`KqueueSelector`, :class:`EpollSelector`...), that can be used to wait for I/O readiness notification on multiple file objects. In the following, "file object" refers to any object with a -:meth:`fileno()` method, or a raw file descriptor. See :term:`file object`. +:meth:`~io.IOBase.fileno` method, or a raw file descriptor. See :term:`file object`. :class:`DefaultSelector` is an alias to the most efficient implementation available on the current platform: this should be the default choice for most diff --git a/Doc/library/shelve.rst b/Doc/library/shelve.rst index 01314f491f47a7..95c54991887022 100644 --- a/Doc/library/shelve.rst +++ b/Doc/library/shelve.rst @@ -94,9 +94,9 @@ Two additional methods are supported: Restrictions ------------ - .. index:: - pair: module; dbm.ndbm - pair: module; dbm.gnu +.. index:: + pair: module; dbm.ndbm + pair: module; dbm.gnu * The choice of which database package will be used (such as :mod:`dbm.ndbm` or :mod:`dbm.gnu`) depends on which interface is available. Therefore it is not @@ -113,6 +113,9 @@ Restrictions differs across Unix versions and requires knowledge about the database implementation used. +* On macOS :mod:`dbm.ndbm` can silently corrupt the database file on updates, + which can cause hard crashes when trying to read from the database. + .. class:: Shelf(dict, protocol=None, writeback=False, keyencoding='utf-8') @@ -149,13 +152,14 @@ Restrictions .. class:: BsdDbShelf(dict, protocol=None, writeback=False, keyencoding='utf-8') - A subclass of :class:`Shelf` which exposes :meth:`first`, :meth:`!next`, - :meth:`previous`, :meth:`last` and :meth:`set_location` which are available - in the third-party :mod:`bsddb` module from `pybsddb + A subclass of :class:`Shelf` which exposes :meth:`!first`, :meth:`!next`, + :meth:`!previous`, :meth:`!last` and :meth:`!set_location` methods. + These are available + in the third-party :mod:`!bsddb` module from `pybsddb `_ but not in other database modules. The *dict* object passed to the constructor must support those methods. This is generally accomplished by calling one of - :func:`bsddb.hashopen`, :func:`bsddb.btopen` or :func:`bsddb.rnopen`. The + :func:`!bsddb.hashopen`, :func:`!bsddb.btopen` or :func:`!bsddb.rnopen`. The optional *protocol*, *writeback*, and *keyencoding* parameters have the same interpretation as for the :class:`Shelf` class. diff --git a/Doc/library/shutil.rst b/Doc/library/shutil.rst index 4390a8e22306fa..f61ef8b0ecc7ba 100644 --- a/Doc/library/shutil.rst +++ b/Doc/library/shutil.rst @@ -343,6 +343,12 @@ Directory and files operations .. versionchanged:: 3.12 Added the *onexc* parameter, deprecated *onerror*. + .. versionchanged:: 3.13 + :func:`!rmtree` now ignores :exc:`FileNotFoundError` exceptions for all + but the top-level path. + Exceptions other than :exc:`OSError` and subclasses of :exc:`!OSError` + are now always propagated to the caller. + .. attribute:: rmtree.avoids_symlink_attacks Indicates whether the current platform and implementation provides a @@ -476,6 +482,12 @@ Directory and files operations or ends with an extension that is in ``PATHEXT``; and filenames that have no extension can now be found. + .. versionchanged:: 3.12.1 + On Windows, if *mode* includes ``os.X_OK``, executables with an + extension in ``PATHEXT`` will be preferred over executables without a + matching extension. + This brings behavior closer to that of Python 3.11. + .. exception:: Error This exception collects exceptions that are raised during a multi-file diff --git a/Doc/library/signal.rst b/Doc/library/signal.rst index 7ee5ece8859825..85a073aad233ac 100644 --- a/Doc/library/signal.rst +++ b/Doc/library/signal.rst @@ -157,6 +157,8 @@ The variables defined in the :mod:`signal` module are: Alias to :data:`SIGCHLD`. + .. availability:: not macOS. + .. data:: SIGCONT Continue the process if it is currently stopped diff --git a/Doc/library/site.rst b/Doc/library/site.rst index 44f90a3b9e496f..2dc9fb09d727e2 100644 --- a/Doc/library/site.rst +++ b/Doc/library/site.rst @@ -19,7 +19,7 @@ Importing this module will append site-specific paths to the module search path and add a few builtins, unless :option:`-S` was used. In that case, this module can be safely imported with no automatic modifications to the module search path or additions to the builtins. To explicitly trigger the usual site-specific -additions, call the :func:`site.main` function. +additions, call the :func:`main` function. .. versionchanged:: 3.3 Importing the module used to trigger paths manipulation even when using @@ -109,32 +109,40 @@ directory precedes the :file:`foo` directory because :file:`bar.pth` comes alphabetically before :file:`foo.pth`; and :file:`spam` is omitted because it is not mentioned in either path configuration file. -.. index:: pair: module; sitecustomize +:mod:`sitecustomize` +-------------------- + +.. module:: sitecustomize After these path manipulations, an attempt is made to import a module named :mod:`sitecustomize`, which can perform arbitrary site-specific customizations. It is typically created by a system administrator in the site-packages directory. If this import fails with an :exc:`ImportError` or its subclass -exception, and the exception's :attr:`name` attribute equals to ``'sitecustomize'``, +exception, and the exception's :attr:`~ImportError.name` +attribute equals to ``'sitecustomize'``, it is silently ignored. If Python is started without output streams available, as with :file:`pythonw.exe` on Windows (which is used by default to start IDLE), attempted output from :mod:`sitecustomize` is ignored. Any other exception causes a silent and perhaps mysterious failure of the process. -.. index:: pair: module; usercustomize +:mod:`usercustomize` +-------------------- + +.. module:: usercustomize After this, an attempt is made to import a module named :mod:`usercustomize`, which can perform arbitrary user-specific customizations, if -:data:`ENABLE_USER_SITE` is true. This file is intended to be created in the +:data:`~site.ENABLE_USER_SITE` is true. This file is intended to be created in the user site-packages directory (see below), which is part of ``sys.path`` unless disabled by :option:`-s`. If this import fails with an :exc:`ImportError` or -its subclass exception, and the exception's :attr:`name` attribute equals to -``'usercustomize'``, it is silently ignored. +its subclass exception, and the exception's :attr:`~ImportError.name` +attribute equals to ``'usercustomize'``, it is silently ignored. Note that for some non-Unix systems, ``sys.prefix`` and ``sys.exec_prefix`` are empty, and the path manipulations are skipped; however the import of :mod:`sitecustomize` and :mod:`usercustomize` is still attempted. +.. currentmodule:: site .. _rlcompleter-config: @@ -189,9 +197,9 @@ Module contents :func:`getuserbase` hasn't been called yet. Default value is :file:`~/.local` for UNIX and macOS non-framework builds, :file:`~/Library/Python/{X.Y}` for macOS framework builds, and - :file:`{%APPDATA%}\\Python` for Windows. This value is used by Distutils to + :file:`{%APPDATA%}\\Python` for Windows. This value is used to compute the installation directories for scripts, data files, Python modules, - etc. for the :ref:`user installation scheme `. + etc. for the :ref:`user installation scheme `. See also :envvar:`PYTHONUSERBASE`. @@ -258,11 +266,11 @@ If it is called without arguments, it will print the contents of :data:`USER_BASE` and whether the directory exists, then the same thing for :data:`USER_SITE`, and finally the value of :data:`ENABLE_USER_SITE`. -.. cmdoption:: --user-base +.. option:: --user-base Print the path to the user base directory. -.. cmdoption:: --user-site +.. option:: --user-site Print the path to the user site-packages directory. diff --git a/Doc/library/socket.rst b/Doc/library/socket.rst index 4f220e8a098979..4bfb0d8c2cfeac 100644 --- a/Doc/library/socket.rst +++ b/Doc/library/socket.rst @@ -23,7 +23,7 @@ all modern Unix systems, Windows, MacOS, and probably additional platforms. The Python interface is a straightforward transliteration of the Unix system call and library interface for sockets to Python's object-oriented style: the -:func:`.socket` function returns a :dfn:`socket object` whose methods implement +:func:`~socket.socket` function returns a :dfn:`socket object` whose methods implement the various socket system calls. Parameter types are somewhat higher-level than in the C interface: as with :meth:`read` and :meth:`write` operations on Python files, buffer allocation on receive operations is automatic, and buffer length @@ -185,7 +185,7 @@ created. Socket addresses are represented as follows: .. versionadded:: 3.7 - :const:`AF_PACKET` is a low-level interface directly to network devices. - The packets are represented by the tuple + The addresses are represented by the tuple ``(ifname, proto[, pkttype[, hatype[, addr]]])`` where: - *ifname* - String specifying the device name. @@ -193,7 +193,6 @@ created. Socket addresses are represented as follows: May be :data:`ETH_P_ALL` to capture all protocols, one of the :ref:`ETHERTYPE_* constants ` or any other Ethernet protocol number. - Value must be in network-byte-order. - *pkttype* - Optional integer specifying the packet type: - ``PACKET_HOST`` (the default) - Packet addressed to the local host. @@ -207,14 +206,14 @@ created. Socket addresses are represented as follows: - *addr* - Optional bytes-like object specifying the hardware physical address, whose interpretation depends on the device. - .. availability:: Linux >= 2.2. + .. availability:: Linux >= 2.2. - :const:`AF_QIPCRTR` is a Linux-only socket based interface for communicating with services running on co-processors in Qualcomm platforms. The address family is represented as a ``(node, port)`` tuple where the *node* and *port* are non-negative integers. - .. availability:: Linux >= 4.7. + .. availability:: Linux >= 4.7. .. versionadded:: 3.8 @@ -312,7 +311,7 @@ Exceptions The accompanying value is a pair ``(error, string)`` representing an error returned by a library call. *string* represents the description of *error*, as returned by the :c:func:`gai_strerror` C function. The - numeric *error* value will match one of the :const:`EAI_\*` constants + numeric *error* value will match one of the :const:`!EAI_\*` constants defined in this module. .. versionchanged:: 3.3 @@ -348,10 +347,15 @@ Constants AF_INET6 These constants represent the address (and protocol) families, used for the - first argument to :func:`.socket`. If the :const:`AF_UNIX` constant is not + first argument to :func:`~socket.socket`. If the :const:`AF_UNIX` constant is not defined then this protocol is unsupported. More constants may be available depending on the system. +.. data:: AF_UNSPEC + + :const:`AF_UNSPEC` means that + :func:`getaddrinfo` should return socket addresses for any + address family (either IPv4, IPv6, or any other) that can be used. .. data:: SOCK_STREAM SOCK_DGRAM @@ -360,7 +364,7 @@ Constants SOCK_SEQPACKET These constants represent the socket types, used for the second argument to - :func:`.socket`. More constants may be available depending on the system. + :func:`~socket.socket`. More constants may be available depending on the system. (Only :const:`SOCK_STREAM` and :const:`SOCK_DGRAM` appear to be generally useful.) @@ -380,6 +384,8 @@ Constants .. versionadded:: 3.2 +.. _socket-unix-constants: + .. data:: SO_* SOMAXCONN MSG_* @@ -397,7 +403,7 @@ Constants Many constants of these forms, documented in the Unix documentation on sockets and/or the IP protocol, are also defined in the socket module. They are - generally used in arguments to the :meth:`setsockopt` and :meth:`getsockopt` + generally used in arguments to the :meth:`~socket.setsockopt` and :meth:`~socket.getsockopt` methods of socket objects. In most cases, only those symbols that are defined in the Unix header files are defined; for a few symbols, default values are provided. @@ -763,7 +769,7 @@ The following functions all create :ref:`socket objects `. Build a pair of connected socket objects using the given address family, socket type, and protocol number. Address family, socket type, and protocol number are - as for the :func:`.socket` function above. The default family is :const:`AF_UNIX` + as for the :func:`~socket.socket` function above. The default family is :const:`AF_UNIX` if defined on the platform; otherwise, the default is :const:`AF_INET`. The newly created sockets are :ref:`non-inheritable `. @@ -858,8 +864,8 @@ The following functions all create :ref:`socket objects `. .. function:: fromfd(fd, family, type, proto=0) Duplicate the file descriptor *fd* (an integer as returned by a file object's - :meth:`fileno` method) and build a socket object from the result. Address - family, socket type and protocol number are as for the :func:`.socket` function + :meth:`~io.IOBase.fileno` method) and build a socket object from the result. Address + family, socket type and protocol number are as for the :func:`~socket.socket` function above. The file descriptor should refer to a socket, but this is not checked --- subsequent operations on the object may fail if the file descriptor is invalid. This function is rarely needed, but can be used to get or set socket options on @@ -924,7 +930,7 @@ The :mod:`socket` module also offers various network-related services: ``(family, type, proto, canonname, sockaddr)`` In these tuples, *family*, *type*, *proto* are all integers and are - meant to be passed to the :func:`.socket` function. *canonname* will be + meant to be passed to the :func:`~socket.socket` function. *canonname* will be a string representing the canonical name of the *host* if :const:`AI_CANONNAME` is part of the *flags* argument; else *canonname* will be empty. *sockaddr* is a tuple describing a socket address, whose @@ -979,7 +985,7 @@ The :mod:`socket` module also offers various network-related services: .. function:: gethostbyname_ex(hostname) Translate a host name to IPv4 address format, extended interface. Return a - triple ``(hostname, aliaslist, ipaddrlist)`` where *hostname* is the host's + 3-tuple ``(hostname, aliaslist, ipaddrlist)`` where *hostname* is the host's primary host name, *aliaslist* is a (possibly empty) list of alternative host names for the same address, and *ipaddrlist* is a list of IPv4 addresses for the same interface on the same host (often but not @@ -1007,7 +1013,7 @@ The :mod:`socket` module also offers various network-related services: .. function:: gethostbyaddr(ip_address) - Return a triple ``(hostname, aliaslist, ipaddrlist)`` where *hostname* is the + Return a 3-tuple ``(hostname, aliaslist, ipaddrlist)`` where *hostname* is the primary host name responding to the given *ip_address*, *aliaslist* is a (possibly empty) list of alternative host names for the same address, and *ipaddrlist* is a list of IPv4/v6 addresses for the same interface on the same @@ -1040,7 +1046,7 @@ The :mod:`socket` module also offers various network-related services: .. function:: getprotobyname(protocolname) Translate an internet protocol name (for example, ``'icmp'``) to a constant - suitable for passing as the (optional) third argument to the :func:`.socket` + suitable for passing as the (optional) third argument to the :func:`~socket.socket` function. This is usually only needed for sockets opened in "raw" mode (:const:`SOCK_RAW`); for the normal socket modes, the correct protocol is chosen automatically if the protocol is omitted or zero. @@ -1324,7 +1330,7 @@ The :mod:`socket` module also offers various network-related services: Send the list of file descriptors *fds* over an :const:`AF_UNIX` socket *sock*. The *fds* parameter is a sequence of file descriptors. - Consult :meth:`sendmsg` for the documentation of these parameters. + Consult :meth:`~socket.sendmsg` for the documentation of these parameters. .. availability:: Unix, Windows, not Emscripten, not WASI. @@ -1338,7 +1344,7 @@ The :mod:`socket` module also offers various network-related services: Receive up to *maxfds* file descriptors from an :const:`AF_UNIX` socket *sock*. Return ``(msg, list(fds), flags, addr)``. - Consult :meth:`recvmsg` for the documentation of these parameters. + Consult :meth:`~socket.recvmsg` for the documentation of these parameters. .. availability:: Unix, Windows, not Emscripten, not WASI. @@ -1511,7 +1517,7 @@ to sockets. .. method:: socket.getsockopt(level, optname[, buflen]) Return the value of the given socket option (see the Unix man page - :manpage:`getsockopt(2)`). The needed symbolic constants (:const:`SO_\*` etc.) + :manpage:`getsockopt(2)`). The needed symbolic constants (:ref:`SO_\* etc. `) are defined in this module. If *buflen* is absent, an integer option is assumed and its integer value is returned by the function. If *buflen* is present, it specifies the maximum length of the buffer used to receive the option in, and @@ -1931,8 +1937,8 @@ to sockets. .. index:: pair: module; struct Set the value of the given socket option (see the Unix manual page - :manpage:`setsockopt(2)`). The needed symbolic constants are defined in the - :mod:`socket` module (:const:`SO_\*` etc.). The value can be an integer, + :manpage:`setsockopt(2)`). The needed symbolic constants are defined in this + module (:ref:`!SO_\* etc. `). The value can be an integer, ``None`` or a :term:`bytes-like object` representing a buffer. In the later case it is up to the caller to ensure that the bytestring contains the proper bits (see the optional built-in module :mod:`struct` for a way to @@ -2057,10 +2063,10 @@ Example Here are four minimal example programs using the TCP/IP protocol: a server that echoes all data that it receives back (servicing only one client), and a client -using it. Note that a server must perform the sequence :func:`.socket`, +using it. Note that a server must perform the sequence :func:`~socket.socket`, :meth:`~socket.bind`, :meth:`~socket.listen`, :meth:`~socket.accept` (possibly repeating the :meth:`~socket.accept` to service more than one client), while a -client only needs the sequence :func:`.socket`, :meth:`~socket.connect`. Also +client only needs the sequence :func:`~socket.socket`, :meth:`~socket.connect`. Also note that the server does not :meth:`~socket.sendall`/:meth:`~socket.recv` on the socket it is listening on but on the new socket returned by :meth:`~socket.accept`. @@ -2100,7 +2106,7 @@ The next two examples are identical to the above two, but support both IPv4 and IPv6. The server side will listen to the first address family available (it should listen to both instead). On most of IPv6-ready systems, IPv6 will take precedence and the server may not accept IPv4 traffic. The client side will try -to connect to the all addresses returned as a result of the name resolution, and +to connect to all the addresses returned as a result of the name resolution, and sends traffic to the first one connected successfully. :: # Echo server program diff --git a/Doc/library/socketserver.rst b/Doc/library/socketserver.rst index d65e9fe81acf8b..5fd213fa613c8d 100644 --- a/Doc/library/socketserver.rst +++ b/Doc/library/socketserver.rst @@ -116,23 +116,28 @@ server is the address family. :class:`ForkingMixIn` and the Forking classes mentioned below are only available on POSIX platforms that support :func:`~os.fork`. - :meth:`socketserver.ForkingMixIn.server_close` waits until all child - processes complete, except if - :attr:`socketserver.ForkingMixIn.block_on_close` attribute is false. + .. attribute:: block_on_close - :meth:`socketserver.ThreadingMixIn.server_close` waits until all non-daemon - threads complete, except if - :attr:`socketserver.ThreadingMixIn.block_on_close` attribute is false. Use - daemonic threads by setting - :data:`ThreadingMixIn.daemon_threads` to ``True`` to not wait until threads - complete. + :meth:`ForkingMixIn.server_close ` + waits until all child processes complete, except if + :attr:`block_on_close` attribute is ``False``. + + :meth:`ThreadingMixIn.server_close ` + waits until all non-daemon threads complete, except if + :attr:`block_on_close` attribute is ``False``. + + .. attribute:: daemon_threads + + For :class:`ThreadingMixIn` use daemonic threads by setting + :data:`ThreadingMixIn.daemon_threads ` + to ``True`` to not wait until threads complete. .. versionchanged:: 3.7 - :meth:`socketserver.ForkingMixIn.server_close` and - :meth:`socketserver.ThreadingMixIn.server_close` now waits until all + :meth:`ForkingMixIn.server_close ` and + :meth:`ThreadingMixIn.server_close ` now waits until all child processes and non-daemonic threads complete. - Add a new :attr:`socketserver.ForkingMixIn.block_on_close` class + Add a new :attr:`ForkingMixIn.block_on_close ` class attribute to opt-in for the pre-3.7 behaviour. @@ -412,13 +417,13 @@ Request Handler Objects This function must do all the work required to service a request. The default implementation does nothing. Several instance attributes are - available to it; the request is available as :attr:`self.request`; the client - address as :attr:`self.client_address`; and the server instance as - :attr:`self.server`, in case it needs access to per-server information. + available to it; the request is available as :attr:`request`; the client + address as :attr:`client_address`; and the server instance as + :attr:`server`, in case it needs access to per-server information. - The type of :attr:`self.request` is different for datagram or stream - services. For stream services, :attr:`self.request` is a socket object; for - datagram services, :attr:`self.request` is a pair of string and socket. + The type of :attr:`request` is different for datagram or stream + services. For stream services, :attr:`request` is a socket object; for + datagram services, :attr:`request` is a pair of string and socket. .. method:: finish() @@ -428,20 +433,42 @@ Request Handler Objects raises an exception, this function will not be called. + .. attribute:: request + + The *new* :class:`socket.socket` object + to be used to communicate with the client. + + + .. attribute:: client_address + + Client address returned by :meth:`BaseServer.get_request`. + + + .. attribute:: server + + :class:`BaseServer` object used for handling the request. + + .. class:: StreamRequestHandler DatagramRequestHandler These :class:`BaseRequestHandler` subclasses override the :meth:`~BaseRequestHandler.setup` and :meth:`~BaseRequestHandler.finish` - methods, and provide :attr:`self.rfile` and :attr:`self.wfile` attributes. - The :attr:`self.rfile` and :attr:`self.wfile` attributes can be - read or written, respectively, to get the request data or return data - to the client. - The :attr:`!rfile` attributes support the :class:`io.BufferedIOBase` readable interface, - and :attr:`!wfile` attributes support the :class:`!io.BufferedIOBase` writable interface. + methods, and provide :attr:`rfile` and :attr:`wfile` attributes. + + .. attribute:: rfile + + A file object from which receives the request is read. + Support the :class:`io.BufferedIOBase` readable interface. + + .. attribute:: wfile + + A file object to which the reply is written. + Support the :class:`io.BufferedIOBase` writable interface + .. versionchanged:: 3.6 - :attr:`StreamRequestHandler.wfile` also supports the + :attr:`wfile` also supports the :class:`io.BufferedIOBase` writable interface. diff --git a/Doc/library/sqlite3.rst b/Doc/library/sqlite3.rst index 50344058c26041..6dbb34a84a4c40 100644 --- a/Doc/library/sqlite3.rst +++ b/Doc/library/sqlite3.rst @@ -235,11 +235,11 @@ inserted data and retrieved values from it in multiple ways. * :ref:`sqlite3-howtos` for further reading: - * :ref:`sqlite3-placeholders` - * :ref:`sqlite3-adapters` - * :ref:`sqlite3-converters` - * :ref:`sqlite3-connection-context-manager` - * :ref:`sqlite3-howto-row-factory` + * :ref:`sqlite3-placeholders` + * :ref:`sqlite3-adapters` + * :ref:`sqlite3-converters` + * :ref:`sqlite3-connection-context-manager` + * :ref:`sqlite3-howto-row-factory` * :ref:`sqlite3-explanation` for in-depth background on transaction control. @@ -355,6 +355,12 @@ Module functions .. versionadded:: 3.12 The *autocommit* parameter. + .. versionchanged:: 3.13 + Positional use of the parameters *timeout*, *detect_types*, + *isolation_level*, *check_same_thread*, *factory*, *cached_statements*, + and *uri* is deprecated. + They will become keyword-only parameters in Python 3.15. + .. function:: complete_statement(statement) Return ``True`` if the string *statement* appears to contain @@ -523,13 +529,13 @@ Module constants the default `threading mode `_ the underlying SQLite library is compiled with. The SQLite threading modes are: - 1. **Single-thread**: In this mode, all mutexes are disabled and SQLite is - unsafe to use in more than a single thread at once. - 2. **Multi-thread**: In this mode, SQLite can be safely used by multiple - threads provided that no single database connection is used - simultaneously in two or more threads. - 3. **Serialized**: In serialized mode, SQLite can be safely used by - multiple threads with no restriction. + 1. **Single-thread**: In this mode, all mutexes are disabled and SQLite is + unsafe to use in more than a single thread at once. + 2. **Multi-thread**: In this mode, SQLite can be safely used by multiple + threads provided that no single database connection is used + simultaneously in two or more threads. + 3. **Serialized**: In serialized mode, SQLite can be safely used by + multiple threads with no restriction. The mappings from SQLite threading modes to DB-API 2.0 threadsafety levels are as follows: @@ -624,6 +630,12 @@ Connection objects * :ref:`sqlite3-connection-shortcuts` * :ref:`sqlite3-connection-context-manager` + + .. versionchanged:: 3.13 + + A :exc:`ResourceWarning` is emitted if :meth:`close` is not called before + a :class:`!Connection` object is deleted. + An SQLite database connection has the following attributes and methods: .. method:: cursor(factory=Cursor) @@ -751,8 +763,13 @@ Connection objects ... print(row) ('acbd18db4cc2f85cedef654fccc4a4d8',) + .. versionchanged:: 3.13 + + Passing *name*, *narg*, and *func* as keyword arguments is deprecated. + These parameters will become positional-only in Python 3.15. - .. method:: create_aggregate(name, /, n_arg, aggregate_class) + + .. method:: create_aggregate(name, n_arg, aggregate_class) Create or remove a user-defined SQL aggregate function. @@ -805,6 +822,11 @@ Connection objects 3 + .. versionchanged:: 3.13 + + Passing *name*, *n_arg*, and *aggregate_class* as keyword arguments is deprecated. + These parameters will become positional-only in Python 3.15. + .. method:: create_window_function(name, num_params, aggregate_class, /) @@ -892,7 +914,7 @@ Connection objects [('a', 9), ('b', 12), ('c', 16), ('d', 12), ('e', 9)] - .. method:: create_collation(name, callable) + .. method:: create_collation(name, callable, /) Create a collation named *name* using the collating function *callable*. *callable* is passed two :class:`string ` arguments, @@ -969,6 +991,10 @@ Connection objects .. versionchanged:: 3.11 Added support for disabling the authorizer using ``None``. + .. versionchanged:: 3.13 + Passing *authorizer_callback* as a keyword argument is deprecated. + The parameter will become positional-only in Python 3.15. + .. method:: set_progress_handler(progress_handler, n) @@ -984,6 +1010,10 @@ Connection objects currently executing query and cause it to raise a :exc:`DatabaseError` exception. + .. versionchanged:: 3.13 + Passing *progress_handler* as a keyword argument is deprecated. + The parameter will become positional-only in Python 3.15. + .. method:: set_trace_callback(trace_callback) @@ -1008,6 +1038,10 @@ Connection objects .. versionadded:: 3.3 + .. versionchanged:: 3.13 + Passing *trace_callback* as a keyword argument is deprecated. + The parameter will become positional-only in Python 3.15. + .. method:: enable_load_extension(enabled, /) @@ -1120,6 +1154,10 @@ Connection objects f.write('%s\n' % line) con.close() + .. seealso:: + + :ref:`sqlite3-howto-encoding` + .. method:: backup(target, *, pages=-1, progress=None, name="main", sleep=0.250) @@ -1186,6 +1224,10 @@ Connection objects .. versionadded:: 3.7 + .. seealso:: + + :ref:`sqlite3-howto-encoding` + .. method:: getlimit(category, /) Get a connection runtime limit. @@ -1407,39 +1449,8 @@ Connection objects 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() + See :ref:`sqlite3-howto-encoding` for more details. .. attribute:: total_changes @@ -1491,7 +1502,7 @@ Cursor objects .. method:: execute(sql, parameters=(), /) - Execute SQL a single SQL statement, + Execute a single SQL statement, optionally binding Python values using :ref:`placeholders `. @@ -1544,7 +1555,7 @@ Cursor objects :raises ProgrammingError: If *sql* contains more than one SQL statement, - or is not a DML statment. + or is not a DML statement. Example: @@ -1598,7 +1609,6 @@ Cursor objects COMMIT; """) - .. method:: fetchone() If :attr:`~Cursor.row_factory` is ``None``, @@ -2403,9 +2413,9 @@ or if :attr:`~Connection.autocommit` is ``True``, the context manager does nothing. .. note:: - The context manager neither implicitly opens a new transaction - nor closes the connection. + nor closes the connection. If you need a closing context manager, consider + using :meth:`contextlib.closing`. .. testcode:: @@ -2577,6 +2587,47 @@ With some adjustments, the above recipe can be adapted to use a instead of a :class:`~collections.namedtuple`. +.. _sqlite3-howto-encoding: + +How to handle non-UTF-8 text encodings +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +By default, :mod:`!sqlite3` uses :class:`str` to adapt SQLite values +with the ``TEXT`` data type. +This works well for UTF-8 encoded text, but it might fail for other encodings +and invalid UTF-8. +You can use a custom :attr:`~Connection.text_factory` to handle such cases. + +Because of SQLite's `flexible typing`_, it is not uncommon to encounter table +columns with the ``TEXT`` data type containing non-UTF-8 encodings, +or even arbitrary data. +To demonstrate, let's assume we have a database with ISO-8859-2 (Latin-2) +encoded text, for example a table of Czech-English dictionary entries. +Assuming we now have a :class:`Connection` instance :py:data:`!con` +connected to this database, +we can decode the Latin-2 encoded text using this :attr:`~Connection.text_factory`: + +.. testcode:: + + con.text_factory = lambda data: str(data, encoding="latin2") + +For invalid UTF-8 or arbitrary data in stored in ``TEXT`` table columns, +you can use the following technique, borrowed from the :ref:`unicode-howto`: + +.. testcode:: + + con.text_factory = lambda data: str(data, errors="surrogateescape") + +.. note:: + + The :mod:`!sqlite3` module API does not support strings + containing surrogates. + +.. seealso:: + + :ref:`unicode-howto` + + .. _sqlite3-explanation: Explanation diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst index 5d6bc829d68878..e8709b516ae07a 100644 --- a/Doc/library/ssl.rst +++ b/Doc/library/ssl.rst @@ -25,7 +25,7 @@ probably additional platforms, as long as OpenSSL is installed on that platform. Some behavior may be platform dependent, since calls are made to the operating system socket APIs. The installed version of OpenSSL may also - cause variations in behavior. For example, TLSv1.3 with OpenSSL version + cause variations in behavior. For example, TLSv1.3 comes with OpenSSL version 1.1.1. .. warning:: @@ -43,8 +43,10 @@ This module provides a class, :class:`ssl.SSLSocket`, which is derived from the :class:`socket.socket` type, and provides a socket-like wrapper that also encrypts and decrypts the data going over the socket with SSL. It supports additional methods such as :meth:`getpeercert`, which retrieves the -certificate of the other side of the connection, and :meth:`cipher`, which -retrieves the cipher being used for the secure connection. +certificate of the other side of the connection, :meth:`cipher`, which +retrieves the cipher being used for the secure connection or +:meth:`get_verified_chain`, :meth:`get_unverified_chain` which retrieves +certificate chain. For more sophisticated applications, the :class:`ssl.SSLContext` class helps manage settings and certificates, which can then be inherited @@ -906,6 +908,12 @@ Constants .. versionadded:: 3.7 +.. data:: HAS_PSK + + Whether the OpenSSL library has built-in support for TLS-PSK. + + .. versionadded:: 3.13 + .. data:: CHANNEL_BINDING_TYPES List of supported TLS channel binding types. Strings in this list @@ -1210,6 +1218,22 @@ SSL sockets also have the following additional methods and attributes: .. versionchanged:: 3.9 IPv6 address strings no longer have a trailing new line. +.. method:: SSLSocket.get_verified_chain() + + Returns verified certificate chain provided by the other + end of the SSL channel as a list of DER-encoded bytes. + If certificate verification was disabled method acts the same as + :meth:`~SSLSocket.get_unverified_chain`. + + .. versionadded:: 3.13 + +.. method:: SSLSocket.get_unverified_chain() + + Returns raw certificate chain provided by the other + end of the SSL channel as a list of DER-encoded bytes. + + .. versionadded:: 3.13 + .. method:: SSLSocket.cipher() Returns a three-value tuple containing the name of the cipher being used, the @@ -1380,18 +1404,18 @@ to speed up repeated connections from the same clients. Here's a table showing which versions in a client (down the side) can connect to which versions in a server (along the top): - .. table:: + .. table:: - ======================== ============ ============ ============= ========= =========== =========== - *client* / **server** **SSLv2** **SSLv3** **TLS** [3]_ **TLSv1** **TLSv1.1** **TLSv1.2** - ------------------------ ------------ ------------ ------------- --------- ----------- ----------- - *SSLv2* yes no no [1]_ no no no - *SSLv3* no yes no [2]_ no no no - *TLS* (*SSLv23*) [3]_ no [1]_ no [2]_ yes yes yes yes - *TLSv1* no no yes yes no no - *TLSv1.1* no no yes no yes no - *TLSv1.2* no no yes no no yes - ======================== ============ ============ ============= ========= =========== =========== + ======================== ============ ============ ============= ========= =========== =========== + *client* / **server** **SSLv2** **SSLv3** **TLS** [3]_ **TLSv1** **TLSv1.1** **TLSv1.2** + ------------------------ ------------ ------------ ------------- --------- ----------- ----------- + *SSLv2* yes no no [1]_ no no no + *SSLv3* no yes no [2]_ no no no + *TLS* (*SSLv23*) [3]_ no [1]_ no [2]_ yes yes yes yes + *TLSv1* no no yes yes no no + *TLSv1.1* no no yes no yes no + *TLSv1.2* no no yes no no yes + ======================== ============ ============ ============= ========= =========== =========== .. rubric:: Footnotes .. [1] :class:`SSLContext` disables SSLv2 with :data:`OP_NO_SSLv2` by default. @@ -1656,8 +1680,9 @@ to speed up repeated connections from the same clients. Due to the early negotiation phase of the TLS connection, only limited methods and attributes are usable like :meth:`SSLSocket.selected_alpn_protocol` and :attr:`SSLSocket.context`. - The :meth:`SSLSocket.getpeercert`, - :meth:`SSLSocket.cipher` and :meth:`SSLSocket.compression` methods require that + The :meth:`SSLSocket.getpeercert`, :meth:`SSLSocket.get_verified_chain`, + :meth:`SSLSocket.get_unverified_chain` :meth:`SSLSocket.cipher` + and :meth:`SSLSocket.compression` methods require that the TLS connection has progressed beyond the TLS Client Hello and therefore will not return meaningful values nor can they be called safely. @@ -1987,6 +2012,100 @@ to speed up repeated connections from the same clients. >>> ssl.create_default_context().verify_mode # doctest: +SKIP +.. method:: SSLContext.set_psk_client_callback(callback) + + Enables TLS-PSK (pre-shared key) authentication on a client-side connection. + + In general, certificate based authentication should be preferred over this method. + + The parameter ``callback`` is a callable object with the signature: + ``def callback(hint: str | None) -> tuple[str | None, bytes]``. + The ``hint`` parameter is an optional identity hint sent by the server. + The return value is a tuple in the form (client-identity, psk). + Client-identity is an optional string which may be used by the server to + select a corresponding PSK for the client. The string must be less than or + equal to ``256`` octets when UTF-8 encoded. PSK is a + :term:`bytes-like object` representing the pre-shared key. Return a zero + length PSK to reject the connection. + + Setting ``callback`` to :const:`None` removes any existing callback. + + .. note:: + When using TLS 1.3: + + - the ``hint`` parameter is always :const:`None`. + - client-identity must be a non-empty string. + + Example usage:: + + context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) + context.check_hostname = False + context.verify_mode = ssl.CERT_NONE + context.maximum_version = ssl.TLSVersion.TLSv1_2 + context.set_ciphers('PSK') + + # A simple lambda: + psk = bytes.fromhex('c0ffee') + context.set_psk_client_callback(lambda hint: (None, psk)) + + # A table using the hint from the server: + psk_table = { 'ServerId_1': bytes.fromhex('c0ffee'), + 'ServerId_2': bytes.fromhex('facade') + } + def callback(hint): + return 'ClientId_1', psk_table.get(hint, b'') + context.set_psk_client_callback(callback) + + This method will raise :exc:`NotImplementedError` if :data:`HAS_PSK` is + ``False``. + + .. versionadded:: 3.13 + +.. method:: SSLContext.set_psk_server_callback(callback, identity_hint=None) + + Enables TLS-PSK (pre-shared key) authentication on a server-side connection. + + In general, certificate based authentication should be preferred over this method. + + The parameter ``callback`` is a callable object with the signature: + ``def callback(identity: str | None) -> bytes``. + The ``identity`` parameter is an optional identity sent by the client which can + be used to select a corresponding PSK. + The return value is a :term:`bytes-like object` representing the pre-shared key. + Return a zero length PSK to reject the connection. + + Setting ``callback`` to :const:`None` removes any existing callback. + + The parameter ``identity_hint`` is an optional identity hint string sent to + the client. The string must be less than or equal to ``256`` octets when + UTF-8 encoded. + + .. note:: + When using TLS 1.3 the ``identity_hint`` parameter is not sent to the client. + + Example usage:: + + context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) + context.maximum_version = ssl.TLSVersion.TLSv1_2 + context.set_ciphers('PSK') + + # A simple lambda: + psk = bytes.fromhex('c0ffee') + context.set_psk_server_callback(lambda identity: psk) + + # A table using the identity of the client: + psk_table = { 'ClientId_1': bytes.fromhex('c0ffee'), + 'ClientId_2': bytes.fromhex('facade') + } + def callback(identity): + return psk_table.get(identity, b'') + context.set_psk_server_callback(callback, 'ServerId_1') + + This method will raise :exc:`NotImplementedError` if :data:`HAS_PSK` is + ``False``. + + .. versionadded:: 3.13 + .. index:: single: certificates .. index:: single: X509 certificate @@ -2414,6 +2533,8 @@ provided. - :meth:`~SSLSocket.read` - :meth:`~SSLSocket.write` - :meth:`~SSLSocket.getpeercert` + - :meth:`~SSLSocket.get_verified_chain` + - :meth:`~SSLSocket.get_unverified_chain` - :meth:`~SSLSocket.selected_alpn_protocol` - :meth:`~SSLSocket.selected_npn_protocol` - :meth:`~SSLSocket.cipher` diff --git a/Doc/library/statistics.rst b/Doc/library/statistics.rst index 395b324c860389..0417b3f38a9807 100644 --- a/Doc/library/statistics.rst +++ b/Doc/library/statistics.rst @@ -14,6 +14,7 @@ .. testsetup:: * from statistics import * + import math __name__ = '' -------------- @@ -584,7 +585,7 @@ However, for reading convenience, most of the examples show sorted sequences. The *data* can be any iterable containing sample data. For meaningful results, the number of data points in *data* should be larger than *n*. - Raises :exc:`StatisticsError` if there are not at least two data points. + Raises :exc:`StatisticsError` if there is not at least one data point. The cut points are linearly interpolated from the two nearest data points. For example, if a cut point falls one-third @@ -624,6 +625,11 @@ However, for reading convenience, most of the examples show sorted sequences. .. versionadded:: 3.8 + .. versionchanged:: 3.13 + No longer raises an exception for an input with only a single data point. + This allows quantile estimates to be built up one sample point + at a time becoming gradually more refined with each new data point. + .. function:: covariance(x, y, /) Return the sample covariance of two inputs *x* and *y*. Covariance @@ -741,6 +747,24 @@ However, for reading convenience, most of the examples show sorted sequences. *y = slope \* x + noise* + Continuing the example from :func:`correlation`, we look to see + how well a model based on major planets can predict the orbital + distances for dwarf planets: + + .. doctest:: + + >>> model = linear_regression(period_squared, dist_cubed, proportional=True) + >>> slope = model.slope + + >>> # Dwarf planets: Pluto, Eris, Makemake, Haumea, Ceres + >>> orbital_periods = [90_560, 204_199, 111_845, 103_410, 1_680] # days + >>> predicted_dist = [math.cbrt(slope * (p * p)) for p in orbital_periods] + >>> list(map(round, predicted_dist)) + [5912, 10166, 6806, 6459, 414] + + >>> [5_906, 10_152, 6_796, 6_450, 414] # actual distance in million km + [5906, 10152, 6796, 6450, 414] + .. versionadded:: 3.10 .. versionchanged:: 3.11 @@ -828,6 +852,11 @@ of applications in statistics. number generator. This is useful for creating reproducible results, even in a multi-threading context. + .. versionchanged:: 3.13 + + Switched to a faster algorithm. To reproduce samples from previous + versions, use :func:`random.seed` and :func:`random.gauss`. + .. method:: NormalDist.pdf(x) Using a `probability density function (pdf) @@ -922,6 +951,10 @@ of applications in statistics. :class:`NormalDist` Examples and Recipes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Classic probability problems +**************************** + :class:`NormalDist` readily solves classic probability problems. For example, given `historical data for SAT exams @@ -947,6 +980,10 @@ Find the `quartiles `_ and `deciles >>> list(map(round, sat.quantiles(n=10))) [810, 896, 958, 1011, 1060, 1109, 1162, 1224, 1310] + +Monte Carlo inputs for simulations +********************************** + To estimate the distribution for a model than isn't easy to solve analytically, :class:`NormalDist` can generate input samples for a `Monte Carlo simulation `_: @@ -963,6 +1000,9 @@ Carlo simulation `_: >>> quantiles(map(model, X, Y, Z)) # doctest: +SKIP [1.4591308524824727, 1.8035946855390597, 2.175091447274739] +Approximating binomial distributions +************************************ + Normal distributions can be used to approximate `Binomial distributions `_ when the sample size is large and when the probability of a successful @@ -986,19 +1026,20 @@ probability that the Python room will stay within its capacity limits? >>> round(NormalDist(mu=n*p, sigma=sqrt(n*p*q)).cdf(k + 0.5), 4) 0.8402 - >>> # Solution using the cumulative binomial distribution + >>> # Exact solution using the cumulative binomial distribution >>> from math import comb, fsum >>> round(fsum(comb(n, r) * p**r * q**(n-r) for r in range(k+1)), 4) 0.8402 >>> # Approximation using a simulation - >>> from random import seed, choices + >>> from random import seed, binomialvariate >>> seed(8675309) - >>> def trial(): - ... return choices(('Python', 'Ruby'), (p, q), k=n).count('Python') - ... - >>> mean(trial() <= k for i in range(10_000)) - 0.8398 + >>> mean(binomialvariate(n, p) <= k for i in range(10_000)) + 0.8406 + + +Naive bayesian classifier +************************* Normal distributions commonly arise in machine learning problems. @@ -1054,6 +1095,46 @@ The final prediction goes to the largest posterior. This is known as the 'female' +Kernel density estimation +************************* + +It is possible to estimate a continuous probability density function +from a fixed number of discrete samples. + +The basic idea is to smooth the data using `a kernel function such as a +normal distribution, triangular distribution, or uniform distribution +`_. +The degree of smoothing is controlled by a scaling parameter, ``h``, +which is called the *bandwidth*. + +.. testcode:: + + def kde_normal(sample, h): + "Create a continuous probability density function from a sample." + # Smooth the sample with a normal distribution kernel scaled by h. + kernel_h = NormalDist(0.0, h).pdf + n = len(sample) + def pdf(x): + return sum(kernel_h(x - x_i) for x_i in sample) / n + return pdf + +`Wikipedia has an example +`_ +where we can use the ``kde_normal()`` recipe to generate and plot +a probability density function estimated from a small sample: + +.. doctest:: + + >>> sample = [-2.1, -1.3, -0.4, 1.9, 5.1, 6.2] + >>> f_hat = kde_normal(sample, h=1.5) + >>> xarr = [i/100 for i in range(-750, 1100)] + >>> yarr = [f_hat(x) for x in xarr] + +The points in ``xarr`` and ``yarr`` can be used to make a PDF plot: + +.. image:: kde_example.png + :alt: Scatter plot of the estimated probability density function. + .. # This modelines must appear within the last ten lines of the file. kate: indent-width 3; remove-trailing-space on; replace-tabs on; encoding utf-8; diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst index 6c07ee585480e9..9028ff5c134fa9 100644 --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -44,13 +44,14 @@ Any object can be tested for truth value, for use in an :keyword:`if` or .. index:: single: true By default, an object is considered true unless its class defines either a -:meth:`~object.__bool__` method that returns ``False`` or a :meth:`__len__` method that +:meth:`~object.__bool__` method that returns ``False`` or a +:meth:`~object.__len__` method that returns zero, when called with the object. [1]_ Here are most of the built-in objects considered false: - .. index:: - single: None (Built-in object) - single: False (Built-in object) +.. index:: + single: None (Built-in object) + single: False (Built-in object) * constants defined to be false: ``None`` and ``False`` @@ -197,7 +198,7 @@ exception. Two more operations with the same syntactic priority, :keyword:`in` and :keyword:`not in`, are supported by types that are :term:`iterable` or -implement the :meth:`__contains__` method. +implement the :meth:`~object.__contains__` method. .. _typesnumeric: @@ -282,7 +283,7 @@ the operations, see :ref:`operator-summary`): +---------------------+---------------------------------+---------+--------------------+ | ``x / y`` | quotient of *x* and *y* | | | +---------------------+---------------------------------+---------+--------------------+ -| ``x // y`` | floored quotient of *x* and | \(1) | | +| ``x // y`` | floored quotient of *x* and | \(1)\(2)| | | | *y* | | | +---------------------+---------------------------------+---------+--------------------+ | ``x % y`` | remainder of ``x / y`` | \(2) | | @@ -319,8 +320,10 @@ the operations, see :ref:`operator-summary`): Notes: (1) - Also referred to as integer division. The resultant value is a whole - integer, though the result's type is not necessarily int. The result is + Also referred to as integer division. For operands of type :class:`int`, + the result has type :class:`int`. For operands of type :class:`float`, + the result has type :class:`float`. In general, the result is a whole + integer, though the result's type is not necessarily :class:`int`. The result is always rounded towards minus infinity: ``1//2`` is ``0``, ``(-1)//2`` is ``-1``, ``1//(-2)`` is ``-1``, and ``(-1)//(-2)`` is ``0``. @@ -715,7 +718,7 @@ that's defined for any rational number, and hence applies to all instances of :class:`int` and :class:`fractions.Fraction`, and all finite instances of :class:`float` and :class:`decimal.Decimal`. Essentially, this function is given by reduction modulo ``P`` for a fixed prime ``P``. The value of ``P`` is -made available to Python as the :attr:`modulus` attribute of +made available to Python as the :attr:`~sys.hash_info.modulus` attribute of :data:`sys.hash_info`. .. impl-detail:: @@ -802,6 +805,7 @@ number, :class:`float`, or :class:`complex`:: hash_value = -2 return hash_value +.. _bltin-boolean-values: .. _typebool: Boolean Type - :class:`bool` @@ -903,9 +907,9 @@ Generator Types --------------- Python's :term:`generator`\s provide a convenient way to implement the iterator -protocol. If a container object's :meth:`__iter__` method is implemented as a +protocol. If a container object's :meth:`~iterator.__iter__` method is implemented as a generator, it will automatically return an iterator object (technically, a -generator object) supplying the :meth:`__iter__` and :meth:`~generator.__next__` +generator object) supplying the :meth:`!__iter__` and :meth:`~generator.__next__` methods. More information about generators can be found in :ref:`the documentation for the yield expression `. @@ -1639,7 +1643,7 @@ expression support in the :mod:`re` module). The casefolding algorithm is `described in section 3.13 'Default Case Folding' of the Unicode Standard - `__. + `__. .. versionadded:: 3.3 @@ -1803,7 +1807,7 @@ expression support in the :mod:`re` module). property being one of "Lm", "Lt", "Lu", "Ll", or "Lo". Note that this is different from the `Alphabetic property defined in the section 4.10 'Letters, Alphabetic, and Ideographic' of the Unicode Standard - `_. + `_. .. method:: str.isascii() @@ -1939,7 +1943,7 @@ expression support in the :mod:`re` module). The lowercasing algorithm used is `described in section 3.13 'Default Case Folding' of the Unicode Standard - `__. + `__. .. method:: str.lstrip([chars]) @@ -2264,7 +2268,7 @@ expression support in the :mod:`re` module). Return a copy of the string in which each character has been mapped through the given translation table. The table must be an object that implements - indexing via :meth:`__getitem__`, typically a :term:`mapping` or + indexing via :meth:`~object.__getitem__`, typically a :term:`mapping` or :term:`sequence`. When indexed by a Unicode ordinal (an integer), the table object can do any of the following: return a Unicode ordinal or a string, to map the character to one or more other characters; return @@ -2288,7 +2292,7 @@ expression support in the :mod:`re` module). The uppercasing algorithm used is `described in section 3.13 'Default Case Folding' of the Unicode Standard - `__. + `__. .. method:: str.zfill(width) @@ -3669,7 +3673,7 @@ The conversion types are: +------------+-----------------------------------------------------+-------+ | ``'b'`` | Bytes (any object that follows the | \(5) | | | :ref:`buffer protocol ` or has | | -| | :meth:`__bytes__`). | | +| | :meth:`~object.__bytes__`). | | +------------+-----------------------------------------------------+-------+ | ``'s'`` | ``'s'`` is an alias for ``'b'`` and should only | \(6) | | | be used for Python2/3 code bases. | | @@ -4407,7 +4411,8 @@ The constructors for both classes work the same: :meth:`symmetric_difference_update` methods will accept any iterable as an argument. - Note, the *elem* argument to the :meth:`__contains__`, :meth:`remove`, and + Note, the *elem* argument to the :meth:`~object.__contains__`, + :meth:`remove`, and :meth:`discard` methods may be a set. To support searching for an equivalent frozenset, a temporary one is created from *elem*. @@ -4752,14 +4757,17 @@ support membership tests: .. versionadded:: 3.10 -Keys views are set-like since their entries are unique and :term:`hashable`. If all -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 +Keys views are set-like since their entries are unique and :term:`hashable`. +Items views also have set-like operations since the (key, value) pairs +are unique and the keys are hashable. +If all values in an items view are hashable as well, +then the items view can interoperate with other sets. +(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 ``^``). While using set operators, -set-like views accept any iterable as the other operand, unlike sets which only -accept sets as the input. +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:: @@ -4854,7 +4862,7 @@ before the statement body is executed and exited when the statement ends: The exception passed in should never be reraised explicitly - instead, this method should return a false value to indicate that the method completed successfully and does not want to suppress the raised exception. This allows - context management code to easily detect whether or not an :meth:`__exit__` + context management code to easily detect whether or not an :meth:`~object.__exit__` method has actually failed. Python defines several context managers to support easy thread synchronisation, @@ -5230,9 +5238,11 @@ instantiated from the type:: TypeError: cannot create 'types.UnionType' instances .. note:: - The :meth:`__or__` method for type objects was added to support the syntax - ``X | Y``. If a metaclass implements :meth:`__or__`, the Union may - override it:: + The :meth:`!__or__` method for type objects was added to support the syntax + ``X | Y``. If a metaclass implements :meth:`!__or__`, the Union may + override it: + + .. doctest:: >>> class M(type): ... def __or__(self, other): @@ -5244,7 +5254,7 @@ instantiated from the type:: >>> C | int 'Hello' >>> int | C - int | __main__.C + int | C .. seealso:: @@ -5318,25 +5328,30 @@ Methods .. index:: pair: object; method Methods are functions that are called using the attribute notation. There are -two flavors: built-in methods (such as :meth:`append` on lists) and class -instance methods. Built-in methods are described with the types that support -them. +two flavors: :ref:`built-in methods ` (such as :meth:`append` +on lists) and :ref:`class instance method `. +Built-in methods are described with the types that support them. If you access a method (a function defined in a class namespace) through an instance, you get a special object: a :dfn:`bound method` (also called -:dfn:`instance method`) object. When called, it will add the ``self`` argument +:ref:`instance method `) object. When called, it will add +the ``self`` argument to the argument list. Bound methods have two special read-only attributes: -``m.__self__`` is the object on which the method operates, and ``m.__func__`` is +:attr:`m.__self__ ` is the object on which the method +operates, and :attr:`m.__func__ ` is the function implementing the method. Calling ``m(arg-1, arg-2, ..., arg-n)`` is completely equivalent to calling ``m.__func__(m.__self__, arg-1, arg-2, ..., arg-n)``. -Like function objects, bound method objects support getting arbitrary +Like :ref:`function objects `, bound method objects support +getting arbitrary attributes. However, since method attributes are actually stored on the -underlying function object (``meth.__func__``), setting method attributes on +underlying function object (:attr:`method.__func__`), setting method attributes on bound methods is disallowed. Attempting to set an attribute on a method results in an :exc:`AttributeError` being raised. In order to set a method -attribute, you need to explicitly set it on the underlying function object:: +attribute, you need to explicitly set it on the underlying function object: + +.. doctest:: >>> class C: ... def method(self): @@ -5351,7 +5366,7 @@ attribute, you need to explicitly set it on the underlying function object:: >>> c.method.whoami 'my name is method' -See :ref:`types` for more information. +See :ref:`instance-methods` for more information. .. index:: object; code, code object @@ -5369,10 +5384,10 @@ Code objects are used by the implementation to represent "pseudo-compiled" executable Python code such as a function body. They differ from function objects because they don't contain a reference to their global execution environment. Code objects are returned by the built-in :func:`compile` function -and can be extracted from function objects through their :attr:`__code__` -attribute. See also the :mod:`code` module. +and can be extracted from function objects through their +:attr:`~function.__code__` attribute. See also the :mod:`code` module. -Accessing ``__code__`` raises an :ref:`auditing event ` +Accessing :attr:`~function.__code__` raises an :ref:`auditing event ` ``object.__getattr__`` with arguments ``obj`` and ``"__code__"``. .. index:: @@ -5446,8 +5461,9 @@ It is written as ``NotImplemented``. Internal Objects ---------------- -See :ref:`types` for this information. It describes stack frame objects, -traceback objects, and slice objects. +See :ref:`types` for this information. It describes +:ref:`stack frame objects `, +:ref:`traceback objects `, and slice objects. .. _specialattrs: diff --git a/Doc/library/string.rst b/Doc/library/string.rst index 9b28f99536a3ae..1867678b2077fc 100644 --- a/Doc/library/string.rst +++ b/Doc/library/string.rst @@ -206,15 +206,15 @@ literal text, it can be escaped by doubling: ``{{`` and ``}}``. The grammar for a replacement field is as follows: - .. productionlist:: format-string - replacement_field: "{" [`field_name`] ["!" `conversion`] [":" `format_spec`] "}" - field_name: arg_name ("." `attribute_name` | "[" `element_index` "]")* - arg_name: [`identifier` | `digit`+] - attribute_name: `identifier` - element_index: `digit`+ | `index_string` - index_string: + - conversion: "r" | "s" | "a" - format_spec: +.. productionlist:: format-string + replacement_field: "{" [`field_name`] ["!" `conversion`] [":" `format_spec`] "}" + field_name: `arg_name` ("." `attribute_name` | "[" `element_index` "]")* + arg_name: [`~python-grammar:identifier` | `~python-grammar:digit`+] + attribute_name: `~python-grammar:identifier` + element_index: `~python-grammar:digit`+ | `index_string` + index_string: + + conversion: "r" | "s" | "a" + format_spec: `format-spec:format_spec` In less formal terms, the replacement field can start with a *field_name* that specifies the object whose value is to be formatted and inserted @@ -316,9 +316,9 @@ The general form of a *standard format specifier* is: fill: align: "<" | ">" | "=" | "^" sign: "+" | "-" | " " - width: `digit`+ + width: `~python-grammar:digit`+ grouping_option: "_" | "," - precision: `digit`+ + precision: `~python-grammar:digit`+ type: "b" | "c" | "d" | "e" | "E" | "f" | "F" | "g" | "G" | "n" | "o" | "s" | "x" | "X" | "%" If a valid *align* value is specified, it can be preceded by a *fill* @@ -332,30 +332,30 @@ affect the :func:`format` function. The meaning of the various alignment options is as follows: - .. index:: - single: < (less); in string formatting - single: > (greater); in string formatting - single: = (equals); in string formatting - single: ^ (caret); in string formatting - - +---------+----------------------------------------------------------+ - | Option | Meaning | - +=========+==========================================================+ - | ``'<'`` | Forces the field to be left-aligned within the available | - | | space (this is the default for most objects). | - +---------+----------------------------------------------------------+ - | ``'>'`` | Forces the field to be right-aligned within the | - | | available space (this is the default for numbers). | - +---------+----------------------------------------------------------+ - | ``'='`` | Forces the padding to be placed after the sign (if any) | - | | but before the digits. This is used for printing fields | - | | in the form '+000000120'. This alignment option is only | - | | valid for numeric types. It becomes the default for | - | | numbers when '0' immediately precedes the field width. | - +---------+----------------------------------------------------------+ - | ``'^'`` | Forces the field to be centered within the available | - | | space. | - +---------+----------------------------------------------------------+ +.. index:: + single: < (less); in string formatting + single: > (greater); in string formatting + single: = (equals); in string formatting + single: ^ (caret); in string formatting + ++---------+----------------------------------------------------------+ +| Option | Meaning | ++=========+==========================================================+ +| ``'<'`` | Forces the field to be left-aligned within the available | +| | space (this is the default for most objects). | ++---------+----------------------------------------------------------+ +| ``'>'`` | Forces the field to be right-aligned within the | +| | available space (this is the default for numbers). | ++---------+----------------------------------------------------------+ +| ``'='`` | Forces the padding to be placed after the sign (if any) | +| | but before the digits. This is used for printing fields | +| | in the form '+000000120'. This alignment option is only | +| | valid for numeric types. It becomes the default for | +| | numbers when '0' immediately precedes the field width. | ++---------+----------------------------------------------------------+ +| ``'^'`` | Forces the field to be centered within the available | +| | space. | ++---------+----------------------------------------------------------+ Note that unless a minimum field width is defined, the field width will always be the same size as the data to fill it, so that the alignment option has no @@ -364,23 +364,23 @@ meaning in this case. The *sign* option is only valid for number types, and can be one of the following: - .. index:: - single: + (plus); in string formatting - single: - (minus); in string formatting - single: space; in string formatting - - +---------+----------------------------------------------------------+ - | Option | Meaning | - +=========+==========================================================+ - | ``'+'`` | indicates that a sign should be used for both | - | | positive as well as negative numbers. | - +---------+----------------------------------------------------------+ - | ``'-'`` | indicates that a sign should be used only for negative | - | | numbers (this is the default behavior). | - +---------+----------------------------------------------------------+ - | space | indicates that a leading space should be used on | - | | positive numbers, and a minus sign on negative numbers. | - +---------+----------------------------------------------------------+ +.. index:: + single: + (plus); in string formatting + single: - (minus); in string formatting + single: space; in string formatting + ++---------+----------------------------------------------------------+ +| Option | Meaning | ++=========+==========================================================+ +| ``'+'`` | indicates that a sign should be used for both | +| | positive as well as negative numbers. | ++---------+----------------------------------------------------------+ +| ``'-'`` | indicates that a sign should be used only for negative | +| | numbers (this is the default behavior). | ++---------+----------------------------------------------------------+ +| space | indicates that a leading space should be used on | +| | positive numbers, and a minus sign on negative numbers. | ++---------+----------------------------------------------------------+ .. index:: single: z; in string formatting diff --git a/Doc/library/stringprep.rst b/Doc/library/stringprep.rst index 5cfb533d802db4..c6d78a356d97bc 100644 --- a/Doc/library/stringprep.rst +++ b/Doc/library/stringprep.rst @@ -27,7 +27,7 @@ procedure are part of the profile. One example of a ``stringprep`` profile is ``nameprep``, which is used for internationalized domain names. The module :mod:`stringprep` only exposes the tables from :rfc:`3454`. As these -tables would be very large to represent them as dictionaries or lists, the +tables would be very large to represent as dictionaries or lists, the module uses the Unicode character database internally. The module source code itself was generated using the ``mkstringprep.py`` utility. diff --git a/Doc/library/struct.rst b/Doc/library/struct.rst index c94dfde4d55763..e2e6fc542e3e67 100644 --- a/Doc/library/struct.rst +++ b/Doc/library/struct.rst @@ -1,6 +1,10 @@ :mod:`struct` --- Interpret bytes as packed binary data ======================================================= +.. testsetup:: * + + from struct import * + .. module:: struct :synopsis: Interpret bytes as packed binary data. @@ -597,6 +601,11 @@ The :mod:`struct` module also defines the following type: The calculated size of the struct (and hence of the bytes object produced by the :meth:`pack` method) corresponding to :attr:`format`. + .. versionchanged:: 3.13 The *repr()* of structs has changed. It + is now: + + >>> Struct('i') + Struct('i') .. _half precision format: https://en.wikipedia.org/wiki/Half-precision_floating-point_format diff --git a/Doc/library/subprocess.rst b/Doc/library/subprocess.rst index 04340cca9e4a59..91e9fcf0263d8d 100644 --- a/Doc/library/subprocess.rst +++ b/Doc/library/subprocess.rst @@ -666,18 +666,18 @@ functions. passed to the underlying ``CreateProcess`` function. *creationflags*, if given, can be one or more of the following flags: - * :data:`CREATE_NEW_CONSOLE` - * :data:`CREATE_NEW_PROCESS_GROUP` - * :data:`ABOVE_NORMAL_PRIORITY_CLASS` - * :data:`BELOW_NORMAL_PRIORITY_CLASS` - * :data:`HIGH_PRIORITY_CLASS` - * :data:`IDLE_PRIORITY_CLASS` - * :data:`NORMAL_PRIORITY_CLASS` - * :data:`REALTIME_PRIORITY_CLASS` - * :data:`CREATE_NO_WINDOW` - * :data:`DETACHED_PROCESS` - * :data:`CREATE_DEFAULT_ERROR_MODE` - * :data:`CREATE_BREAKAWAY_FROM_JOB` + * :data:`CREATE_NEW_CONSOLE` + * :data:`CREATE_NEW_PROCESS_GROUP` + * :data:`ABOVE_NORMAL_PRIORITY_CLASS` + * :data:`BELOW_NORMAL_PRIORITY_CLASS` + * :data:`HIGH_PRIORITY_CLASS` + * :data:`IDLE_PRIORITY_CLASS` + * :data:`NORMAL_PRIORITY_CLASS` + * :data:`REALTIME_PRIORITY_CLASS` + * :data:`CREATE_NO_WINDOW` + * :data:`DETACHED_PROCESS` + * :data:`CREATE_DEFAULT_ERROR_MODE` + * :data:`CREATE_BREAKAWAY_FROM_JOB` *pipesize* can be used to change the size of the pipe when :data:`PIPE` is used for *stdin*, *stdout* or *stderr*. The size of the pipe @@ -742,8 +742,8 @@ the timeout expires before the process exits. Exceptions defined in this module all inherit from :exc:`SubprocessError`. - .. versionadded:: 3.3 - The :exc:`SubprocessError` base class was added. +.. versionadded:: 3.3 + The :exc:`SubprocessError` base class was added. .. _subprocess-security: @@ -791,9 +791,10 @@ Instances of the :class:`Popen` class have the following methods: .. note:: - The function is implemented using a busy loop (non-blocking call and - short sleeps). Use the :mod:`asyncio` module for an asynchronous wait: - see :class:`asyncio.create_subprocess_exec`. + When the ``timeout`` parameter is not ``None``, then (on POSIX) the + function is implemented using a busy loop (non-blocking call and short + sleeps). Use the :mod:`asyncio` module for an asynchronous wait: see + :class:`asyncio.create_subprocess_exec`. .. versionchanged:: 3.3 *timeout* was added. @@ -1460,8 +1461,8 @@ Return code handling translates as follows:: print("There were some errors") -Replacing functions from the :mod:`popen2` module -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Replacing functions from the :mod:`!popen2` module +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. note:: diff --git a/Doc/library/superseded.rst b/Doc/library/superseded.rst index bd17039bc6f6b6..17bfa66f043302 100644 --- a/Doc/library/superseded.rst +++ b/Doc/library/superseded.rst @@ -4,10 +4,12 @@ Superseded Modules ****************** -The modules described in this chapter are deprecated and only kept for +The modules described in this chapter are deprecated or :term:`soft deprecated` and only kept for backwards compatibility. They have been superseded by other modules. .. toctree:: + :maxdepth: 1 + getopt.rst optparse.rst diff --git a/Doc/library/symtable.rst b/Doc/library/symtable.rst index 65ff5bfe7abd61..46159dcef940e7 100644 --- a/Doc/library/symtable.rst +++ b/Doc/library/symtable.rst @@ -38,7 +38,13 @@ Examining Symbol Tables .. method:: get_type() Return the type of the symbol table. Possible values are ``'class'``, - ``'module'``, and ``'function'``. + ``'module'``, ``'function'``, ``'annotation'``, ``'TypeVar bound'``, + ``'type alias'``, and ``'type parameter'``. The latter four refer to + different flavors of :ref:`annotation scopes `. + + .. versionchanged:: 3.12 + Added ``'annotation'``, ``'TypeVar bound'``, ``'type alias'``, + and ``'type parameter'`` as possible return values. .. method:: get_id() @@ -49,6 +55,10 @@ Examining Symbol Tables Return the table's name. This is the name of the class if the table is for a class, the name of the function if the table is for a function, or ``'top'`` if the table is global (:meth:`get_type` returns ``'module'``). + For type parameter scopes (which are used for generic classes, functions, + and type aliases), it is the name of the underlying class, function, or + type alias. For type alias scopes, it is the name of the type alias. + For :class:`~typing.TypeVar` bound scopes, it is the name of the ``TypeVar``. .. method:: get_lineno() @@ -197,3 +207,21 @@ Examining Symbol Tables Return the namespace bound to this name. If more than one or no namespace is bound to this name, a :exc:`ValueError` is raised. + + +.. _symtable-cli: + +Command-Line Usage +------------------ + +.. versionadded:: 3.13 + +The :mod:`symtable` module can be executed as a script from the command line. + +.. code-block:: sh + + python -m symtable [infile...] + +Symbol tables are generated for the specified Python source files and +dumped to stdout. +If no input file is specified, the content is read from stdin. diff --git a/Doc/library/sys.monitoring.rst b/Doc/library/sys.monitoring.rst new file mode 100644 index 00000000000000..762581b7eda7f1 --- /dev/null +++ b/Doc/library/sys.monitoring.rst @@ -0,0 +1,368 @@ +:mod:`sys.monitoring` --- Execution event monitoring +==================================================== + +.. module:: sys.monitoring + :synopsis: Access and control event monitoring + +.. versionadded:: 3.12 + +----------------- + +.. note:: + + :mod:`sys.monitoring` is a namespace within the :mod:`sys` module, + not an independent module, so there is no need to + ``import sys.monitoring``, simply ``import sys`` and then use + ``sys.monitoring``. + + +This namespace provides access to the functions and constants necessary to +activate and control event monitoring. + +As programs execute, events occur that might be of interest to tools that +monitor execution. The :mod:`sys.monitoring` namespace provides means to +receive callbacks when events of interest occur. + +The monitoring API consists of three components: + +* `Tool identifiers`_ +* `Events`_ +* :ref:`Callbacks ` + +Tool identifiers +---------------- + +A tool identifier is an integer and the associated name. +Tool identifiers are used to discourage tools from interfering with each +other and to allow multiple tools to operate at the same time. +Currently tools are completely independent and cannot be used to +monitor each other. This restriction may be lifted in the future. + +Before registering or activating events, a tool should choose an identifier. +Identifiers are integers in the range 0 to 5 inclusive. + +Registering and using tools +''''''''''''''''''''''''''' + +.. function:: use_tool_id(tool_id: int, name: str, /) -> None + + Must be called before *tool_id* can be used. + *tool_id* must be in the range 0 to 5 inclusive. + Raises a :exc:`ValueError` if *tool_id* is in use. + +.. function:: free_tool_id(tool_id: int, /) -> None + + Should be called once a tool no longer requires *tool_id*. + +.. note:: + + :func:`free_tool_id` will not disable global or local events associated + with *tool_id*, nor will it unregister any callback functions. This + function is only intended to be used to notify the VM that the + particular *tool_id* is no longer in use. + +.. function:: get_tool(tool_id: int, /) -> str | None + + Returns the name of the tool if *tool_id* is in use, + otherwise it returns ``None``. + *tool_id* must be in the range 0 to 5 inclusive. + +All IDs are treated the same by the VM with regard to events, but the +following IDs are pre-defined to make co-operation of tools easier:: + + sys.monitoring.DEBUGGER_ID = 0 + sys.monitoring.COVERAGE_ID = 1 + sys.monitoring.PROFILER_ID = 2 + sys.monitoring.OPTIMIZER_ID = 5 + +There is no obligation to set an ID, nor is there anything preventing a tool +from using an ID even it is already in use. +However, tools are encouraged to use a unique ID and respect other tools. + +Events +------ + +The following events are supported: + +.. monitoring-event:: BRANCH + + A conditional branch is taken (or not). + +.. monitoring-event:: CALL + + A call in Python code (event occurs before the call). + +.. monitoring-event:: C_RAISE + + An exception raised from any callable, except for Python functions (event occurs after the exit). + +.. monitoring-event:: C_RETURN + + Return from any callable, except for Python functions (event occurs after the return). + +.. monitoring-event:: EXCEPTION_HANDLED + + An exception is handled. + +.. monitoring-event:: INSTRUCTION + + A VM instruction is about to be executed. + +.. monitoring-event:: JUMP + + An unconditional jump in the control flow graph is made. + +.. monitoring-event:: LINE + + An instruction is about to be executed that has a different line number from the preceding instruction. + +.. monitoring-event:: PY_RESUME + + Resumption of a Python function (for generator and coroutine functions), except for ``throw()`` calls. + +.. monitoring-event:: PY_RETURN + + Return from a Python function (occurs immediately before the return, the callee's frame will be on the stack). + +.. monitoring-event:: PY_START + + Start of a Python function (occurs immediately after the call, the callee's frame will be on the stack) + +.. monitoring-event:: PY_THROW + + A Python function is resumed by a ``throw()`` call. + +.. monitoring-event:: PY_UNWIND + + Exit from a Python function during exception unwinding. + +.. monitoring-event:: PY_YIELD + + Yield from a Python function (occurs immediately before the yield, the callee's frame will be on the stack). + +.. monitoring-event:: RAISE + + An exception is raised, except those that cause a :monitoring-event:`STOP_ITERATION` event. + +.. monitoring-event:: RERAISE + + An exception is re-raised, for example at the end of a :keyword:`finally` block. + +.. monitoring-event:: STOP_ITERATION + + An artificial :exc:`StopIteration` is raised; see `the STOP_ITERATION event`_. + + +More events may be added in the future. + +These events are attributes of the :mod:`!sys.monitoring.events` namespace. +Each event is represented as a power-of-2 integer constant. +To define a set of events, simply bitwise or the individual events together. +For example, to specify both :monitoring-event:`PY_RETURN` and :monitoring-event:`PY_START` +events, use the expression ``PY_RETURN | PY_START``. + +.. monitoring-event:: NO_EVENTS + + An alias for ``0`` so users can do explict comparisions like:: + + if get_events(DEBUGGER_ID) == NO_EVENTS: + ... + +Events are divided into three groups: + +Local events +'''''''''''' + +Local events are associated with normal execution of the program and happen +at clearly defined locations. All local events can be disabled. +The local events are: + +* :monitoring-event:`PY_START` +* :monitoring-event:`PY_RESUME` +* :monitoring-event:`PY_RETURN` +* :monitoring-event:`PY_YIELD` +* :monitoring-event:`CALL` +* :monitoring-event:`LINE` +* :monitoring-event:`INSTRUCTION` +* :monitoring-event:`JUMP` +* :monitoring-event:`BRANCH` +* :monitoring-event:`STOP_ITERATION` + +Ancillary events +'''''''''''''''' + +Ancillary events can be monitored like other events, but are controlled +by another event: + +* :monitoring-event:`C_RAISE` +* :monitoring-event:`C_RETURN` + +The :monitoring-event:`C_RETURN` and :monitoring-event:`C_RAISE` events +are controlled by the :monitoring-event:`CALL` event. +:monitoring-event:`C_RETURN` and :monitoring-event:`C_RAISE` events will only be seen if the +corresponding :monitoring-event:`CALL` event is being monitored. + +Other events +'''''''''''' + +Other events are not necessarily tied to a specific location in the +program and cannot be individually disabled. + +The other events that can be monitored are: + +* :monitoring-event:`PY_THROW` +* :monitoring-event:`PY_UNWIND` +* :monitoring-event:`RAISE` +* :monitoring-event:`EXCEPTION_HANDLED` + + +The STOP_ITERATION event +'''''''''''''''''''''''' + +:pep:`PEP 380 <380#use-of-stopiteration-to-return-values>` +specifies that a :exc:`StopIteration` exception is raised when returning a value +from a generator or coroutine. However, this is a very inefficient way to +return a value, so some Python implementations, notably CPython 3.12+, do not +raise an exception unless it would be visible to other code. + +To allow tools to monitor for real exceptions without slowing down generators +and coroutines, the :monitoring-event:`STOP_ITERATION` event is provided. +:monitoring-event:`STOP_ITERATION` can be locally disabled, unlike :monitoring-event:`RAISE`. + + +Turning events on and off +------------------------- + +In order to monitor an event, it must be turned on and a corresponding callback +must be registered. +Events can be turned on or off by setting the events either globally or +for a particular code object. + + +Setting events globally +''''''''''''''''''''''' + +Events can be controlled globally by modifying the set of events being monitored. + +.. function:: get_events(tool_id: int, /) -> int + + Returns the ``int`` representing all the active events. + +.. function:: set_events(tool_id: int, event_set: int, /) -> None + + Activates all events which are set in *event_set*. + Raises a :exc:`ValueError` if *tool_id* is not in use. + +No events are active by default. + +Per code object events +'''''''''''''''''''''' + +Events can also be controlled on a per code object basis. + +.. function:: get_local_events(tool_id: int, code: CodeType, /) -> int + + Returns all the local events for *code* + +.. function:: set_local_events(tool_id: int, code: CodeType, event_set: int, /) -> None + + Activates all the local events for *code* which are set in *event_set*. + Raises a :exc:`ValueError` if *tool_id* is not in use. + +Local events add to global events, but do not mask them. +In other words, all global events will trigger for a code object, +regardless of the local events. + + +Disabling events +'''''''''''''''' + +.. data:: DISABLE + + A special value that can be returned from a callback function to disable + events for the current code location. + +Local events can be disabled for a specific code location by returning +:data:`sys.monitoring.DISABLE` from a callback function. This does not change +which events are set, or any other code locations for the same event. + +Disabling events for specific locations is very important for high +performance monitoring. For example, a program can be run under a +debugger with no overhead if the debugger disables all monitoring +except for a few breakpoints. + +.. function:: restart_events() -> None + + Enable all the events that were disabled by :data:`sys.monitoring.DISABLE` + for all tools. + + +.. _callbacks: + +Registering callback functions +------------------------------ + +To register a callable for events call + +.. function:: register_callback(tool_id: int, event: int, func: Callable | None, /) -> Callable | None + + Registers the callable *func* for the *event* with the given *tool_id* + + If another callback was registered for the given *tool_id* and *event*, + it is unregistered and returned. + Otherwise :func:`register_callback` returns ``None``. + + +Functions can be unregistered by calling +``sys.monitoring.register_callback(tool_id, event, None)``. + +Callback functions can be registered and unregistered at any time. + +Registering or unregistering a callback function will generate a :func:`sys.audit` event. + + +Callback function arguments +''''''''''''''''''''''''''' + +.. data:: MISSING + + A special value that is passed to a callback function to indicate + that there are no arguments to the call. + +When an active event occurs, the registered callback function is called. +Different events will provide the callback function with different arguments, as follows: + +* :monitoring-event:`PY_START` and :monitoring-event:`PY_RESUME`:: + + func(code: CodeType, instruction_offset: int) -> DISABLE | Any + +* :monitoring-event:`PY_RETURN` and :monitoring-event:`PY_YIELD`:: + + func(code: CodeType, instruction_offset: int, retval: object) -> DISABLE | Any + +* :monitoring-event:`CALL`, :monitoring-event:`C_RAISE` and :monitoring-event:`C_RETURN`:: + + func(code: CodeType, instruction_offset: int, callable: object, arg0: object | MISSING) -> DISABLE | Any + + If there are no arguments, *arg0* is set to :data:`sys.monitoring.MISSING`. + +* :monitoring-event:`RAISE`, :monitoring-event:`RERAISE`, :monitoring-event:`EXCEPTION_HANDLED`, + :monitoring-event:`PY_UNWIND`, :monitoring-event:`PY_THROW` and :monitoring-event:`STOP_ITERATION`:: + + func(code: CodeType, instruction_offset: int, exception: BaseException) -> DISABLE | Any + +* :monitoring-event:`LINE`:: + + func(code: CodeType, line_number: int) -> DISABLE | Any + +* :monitoring-event:`BRANCH` and :monitoring-event:`JUMP`:: + + func(code: CodeType, instruction_offset: int, destination_offset: int) -> DISABLE | Any + + Note that the *destination_offset* is where the code will next execute. + For an untaken branch this will be the offset of the instruction following + the branch. + +* :monitoring-event:`INSTRUCTION`:: + + func(code: CodeType, instruction_offset: int) -> DISABLE | Any diff --git a/Doc/library/sys.rst b/Doc/library/sys.rst index a61737383e3939..c371663934314a 100644 --- a/Doc/library/sys.rst +++ b/Doc/library/sys.rst @@ -22,6 +22,8 @@ always available. .. versionadded:: 3.2 + .. availability:: Unix. + .. function:: addaudithook(hook) @@ -173,7 +175,11 @@ always available. Call ``func(*args)``, while tracing is enabled. The tracing state is saved, and restored afterwards. This is intended to be called from a debugger from - a checkpoint, to recursively debug some other code. + a checkpoint, to recursively debug or profile some other code. + + Tracing is suspended while calling a tracing function set by + :func:`settrace` or :func:`setprofile` to avoid infinite recursion. + :func:`!call_tracing` enables explicit recursion of the tracing function. .. data:: copyright @@ -333,23 +339,21 @@ always available. *wasm32-emscripten* platform. The named tuple is provisional and may change in the future. - .. tabularcolumns:: |l|L| - - +-----------------------------+----------------------------------------------+ - | Attribute | Explanation | - +=============================+==============================================+ - | :const:`emscripten_version` | Emscripten version as tuple of ints | - | | (major, minor, micro), e.g. ``(3, 1, 8)``. | - +-----------------------------+----------------------------------------------+ - | :const:`runtime` | Runtime string, e.g. browser user agent, | - | | ``'Node.js v14.18.2'``, or ``'UNKNOWN'``. | - +-----------------------------+----------------------------------------------+ - | :const:`pthreads` | ``True`` if Python is compiled with | - | | Emscripten pthreads support. | - +-----------------------------+----------------------------------------------+ - | :const:`shared_memory` | ``True`` if Python is compiled with shared | - | | memory support. | - +-----------------------------+----------------------------------------------+ + .. attribute:: _emscripten_info.emscripten_version + + Emscripten version as tuple of ints (major, minor, micro), e.g. ``(3, 1, 8)``. + + .. attribute:: _emscripten_info.runtime + + Runtime string, e.g. browser user agent, ``'Node.js v14.18.2'``, or ``'UNKNOWN'``. + + .. attribute:: _emscripten_info.pthreads + + ``True`` if Python is compiled with Emscripten pthreads support. + + .. attribute:: _emscripten_info.shared_memory + + ``True`` if Python is compiled with shared memory support. .. availability:: Emscripten. @@ -380,7 +384,7 @@ always available. This function prints out a given traceback and exception to ``sys.stderr``. - When an exception is raised and uncaught, the interpreter calls + When an exception other than :exc:`SystemExit` is raised and uncaught, the interpreter calls ``sys.excepthook`` with three arguments, the exception class, exception instance, and a traceback object. In an interactive session this happens just before control is returned to the prompt; in a Python program this happens just @@ -515,28 +519,62 @@ 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` - :const:`isolated` :option:`-I` - :const:`optimize` :option:`-O` or :option:`-OO` - :const:`dont_write_bytecode` :option:`-B` - :const:`no_user_site` :option:`-s` - :const:`no_site` :option:`-S` - :const:`ignore_environment` :option:`-E` - :const:`verbose` :option:`-v` - :const:`bytes_warning` :option:`-b` - :const:`quiet` :option:`-q` - :const:`hash_randomization` :option:`-R` - :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 `) - :const:`warn_default_encoding` :option:`-X warn_default_encoding <-X>` - ============================== ============================================================================================================== + .. list-table:: + + * - .. attribute:: flags.debug + - :option:`-d` + + * - .. attribute:: flags.inspect + - :option:`-i` + + * - .. attribute:: flags.interactive + - :option:`-i` + + * - .. attribute:: flags.isolated + - :option:`-I` + + * - .. attribute:: flags.optimize + - :option:`-O` or :option:`-OO` + + * - .. attribute:: flags.dont_write_bytecode + - :option:`-B` + + * - .. attribute:: flags.no_user_site + - :option:`-s` + + * - .. attribute:: flags.no_site + - :option:`-S` + + * - .. attribute:: flags.ignore_environment + - :option:`-E` + + * - .. attribute:: flags.verbose + - :option:`-v` + + * - .. attribute:: flags.bytes_warning + - :option:`-b` + + * - .. attribute:: flags.quiet + - :option:`-q` + + * - .. attribute:: flags.hash_randomization + - :option:`-R` + + * - .. attribute:: flags.dev_mode + - :option:`-X dev <-X>` (:ref:`Python Development Mode `) + + * - .. attribute:: flags.utf8_mode + - :option:`-X utf8 <-X>` + + * - .. attribute:: flags.safe_path + - :option:`-P` + + * - .. attribute:: flags.int_max_str_digits + - :option:`-X int_max_str_digits <-X>` + (:ref:`integer string conversion length limitation `) + + * - .. attribute:: flags.warn_default_encoding + - :option:`-X warn_default_encoding <-X>` .. versionchanged:: 3.2 Added ``quiet`` attribute for the new :option:`-q` flag. @@ -574,61 +612,82 @@ always available. programming language; see section 5.2.4.2.2 of the 1999 ISO/IEC C standard [C99]_, 'Characteristics of floating types', for details. - .. tabularcolumns:: |l|l|L| - - +---------------------+---------------------+--------------------------------------------------+ - | attribute | float.h macro | explanation | - +=====================+=====================+==================================================+ - | ``epsilon`` | ``DBL_EPSILON`` | difference between 1.0 and the least value | - | | | greater than 1.0 that is representable as a float| - | | | | - | | | See also :func:`math.ulp`. | - +---------------------+---------------------+--------------------------------------------------+ - | ``dig`` | ``DBL_DIG`` | maximum number of decimal digits that can be | - | | | faithfully represented in a float; see below | - +---------------------+---------------------+--------------------------------------------------+ - | ``mant_dig`` | ``DBL_MANT_DIG`` | float precision: the number of base-``radix`` | - | | | digits in the significand of a float | - +---------------------+---------------------+--------------------------------------------------+ - | ``max`` | ``DBL_MAX`` | maximum representable positive finite float | - +---------------------+---------------------+--------------------------------------------------+ - | ``max_exp`` | ``DBL_MAX_EXP`` | maximum integer *e* such that ``radix**(e-1)`` is| - | | | a representable finite float | - +---------------------+---------------------+--------------------------------------------------+ - | ``max_10_exp`` | ``DBL_MAX_10_EXP`` | maximum integer *e* such that ``10**e`` is in the| - | | | range of representable finite floats | - +---------------------+---------------------+--------------------------------------------------+ - | ``min`` | ``DBL_MIN`` | minimum representable positive *normalized* float| - | | | | - | | | Use :func:`math.ulp(0.0) ` to get the | - | | | smallest positive *denormalized* representable | - | | | float. | - +---------------------+---------------------+--------------------------------------------------+ - | ``min_exp`` | ``DBL_MIN_EXP`` | minimum integer *e* such that ``radix**(e-1)`` is| - | | | a normalized float | - +---------------------+---------------------+--------------------------------------------------+ - | ``min_10_exp`` | ``DBL_MIN_10_EXP`` | minimum integer *e* such that ``10**e`` is a | - | | | normalized float | - +---------------------+---------------------+--------------------------------------------------+ - | ``radix`` | ``FLT_RADIX`` | radix of exponent representation | - +---------------------+---------------------+--------------------------------------------------+ - | ``rounds`` | ``FLT_ROUNDS`` | integer representing the rounding mode for | - | | | floating-point arithmetic. This reflects the | - | | | value of the system ``FLT_ROUNDS`` macro at | - | | | interpreter startup time: | - | | | ``-1`` indeterminable, | - | | | ``0`` toward zero, | - | | | ``1`` to nearest, | - | | | ``2`` toward positive infinity, | - | | | ``3`` toward negative infinity | - | | | | - | | | All other values for ``FLT_ROUNDS`` characterize | - | | | implementation-defined rounding behavior. | - +---------------------+---------------------+--------------------------------------------------+ + .. list-table:: Attributes of the :data:`!float_info` :term:`named tuple` + :header-rows: 1 + + * - attribute + - float.h macro + - explanation + + * - .. attribute:: float_info.epsilon + - :c:macro:`!DBL_EPSILON` + - difference between 1.0 and the least value greater than 1.0 that is + representable as a float. + + See also :func:`math.ulp`. + + * - .. attribute:: float_info.dig + - :c:macro:`!DBL_DIG` + - The maximum number of decimal digits that can be faithfully + represented in a float; see below. + + * - .. attribute:: float_info.mant_dig + - :c:macro:`!DBL_MANT_DIG` + - Float precision: the number of base-``radix`` digits in the + significand of a float. + + * - .. attribute:: float_info.max + - :c:macro:`!DBL_MAX` + - The maximum representable positive finite float. + + * - .. attribute:: float_info.max_exp + - :c:macro:`!DBL_MAX_EXP` + - The maximum integer *e* such that ``radix**(e-1)`` is a representable + finite float. + + * - .. attribute:: float_info.max_10_exp + - :c:macro:`!DBL_MAX_10_EXP` + - The maximum integer *e* such that ``10**e`` is in the range of + representable finite floats. + + * - .. attribute:: float_info.min + - :c:macro:`!DBL_MIN` + - The minimum representable positive *normalized* float. + + Use :func:`math.ulp(0.0) ` to get the smallest positive + *denormalized* representable float. + + * - .. attribute:: float_info.min_exp + - :c:macro:`!DBL_MIN_EXP` + - The minimum integer *e* such that ``radix**(e-1)`` is a normalized + float. + + * - .. attribute:: float_info.min_10_exp + - :c:macro:`!DBL_MIN_10_EXP` + - The minimum integer *e* such that ``10**e`` is a normalized float. + + * - .. attribute:: float_info.radix + - :c:macro:`!FLT_RADIX` + - The radix of exponent representation. + + * - .. attribute:: float_info.rounds + - :c:macro:`!FLT_ROUNDS` + - An integer representing the rounding mode for floating-point arithmetic. + This reflects the value of the system :c:macro:`!FLT_ROUNDS` macro + at interpreter startup time: + + * ``-1``: indeterminable + * ``0``: toward zero + * ``1``: to nearest + * ``2``: toward positive infinity + * ``3``: toward negative infinity + + All other values for :c:macro:`!FLT_ROUNDS` characterize + implementation-defined rounding behavior. The attribute :attr:`sys.float_info.dig` needs further explanation. If ``s`` is any string representing a decimal number with at most - :attr:`sys.float_info.dig` significant digits, then converting ``s`` to a + :attr:`!sys.float_info.dig` significant digits, then converting ``s`` to a float and back again will recover a string representing the same decimal value:: @@ -700,7 +759,7 @@ always available. Return the current value of the flags that are used for :c:func:`dlopen` calls. Symbolic names for the flag values can be - found in the :mod:`os` module (``RTLD_xxx`` constants, e.g. + found in the :mod:`os` module (:samp:`RTLD_{xxx}` constants, e.g. :const:`os.RTLD_LAZY`). .. availability:: Unix. @@ -770,6 +829,15 @@ always available. higher than you might expect, because it includes the (temporary) reference as an argument to :func:`getrefcount`. + Note that the returned value may not actually reflect how many + references to the object are actually held. For example, some + objects are :term:`immortal` and have a very high refcount that does not + reflect the actual number of references. Consequently, do not rely + on the returned value to be accurate, other than a value of 0 or 1. + + .. versionchanged:: 3.12 + Immortal objects have very large refcounts that do not match + the actual number of references to the object. .. function:: getrecursionlimit() @@ -893,8 +961,8 @@ always available. | | a domain controller. | +---------------------------------------+---------------------------------+ - This function wraps the Win32 :c:func:`GetVersionEx` function; see the - Microsoft documentation on :c:func:`OSVERSIONINFOEX` for more information + This function wraps the Win32 :c:func:`!GetVersionEx` function; see the + Microsoft documentation on :c:func:`!OSVERSIONINFOEX` for more information about these fields. *platform_version* returns the major version, minor version and @@ -952,28 +1020,37 @@ always available. implementation. For more details about hashing of numeric types, see :ref:`numeric-hash`. - +---------------------+--------------------------------------------------+ - | attribute | explanation | - +=====================+==================================================+ - | :const:`width` | width in bits used for hash values | - +---------------------+--------------------------------------------------+ - | :const:`modulus` | prime modulus P used for numeric hash scheme | - +---------------------+--------------------------------------------------+ - | :const:`inf` | hash value returned for a positive infinity | - +---------------------+--------------------------------------------------+ - | :const:`nan` | (this attribute is no longer used) | - +---------------------+--------------------------------------------------+ - | :const:`imag` | multiplier used for the imaginary part of a | - | | complex number | - +---------------------+--------------------------------------------------+ - | :const:`algorithm` | name of the algorithm for hashing of str, bytes, | - | | and memoryview | - +---------------------+--------------------------------------------------+ - | :const:`hash_bits` | internal output size of the hash algorithm | - +---------------------+--------------------------------------------------+ - | :const:`seed_bits` | size of the seed key of the hash algorithm | - +---------------------+--------------------------------------------------+ + .. attribute:: hash_info.width + + The width in bits used for hash values + + .. attribute:: hash_info.modulus + + The prime modulus P used for numeric hash scheme + + .. attribute:: hash_info.inf + + The hash value returned for a positive infinity + .. attribute:: hash_info.nan + + (This attribute is no longer used) + + .. attribute:: hash_info.imag + + The multiplier used for the imaginary part of a complex number + + .. attribute:: hash_info.algorithm + + The name of the algorithm for hashing of str, bytes, and memoryview + + .. attribute:: hash_info.hash_bits + + The internal output size of the hash algorithm + + .. attribute:: hash_info.seed_bits + + The size of the seed key of the hash algorithm .. versionadded:: 3.2 @@ -1051,32 +1128,31 @@ always available. A :term:`named tuple` that holds information about Python's internal representation of integers. The attributes are read only. - .. 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 | - +----------------------------------------+-----------------------------------------------+ - | :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>`. | - +----------------------------------------+-----------------------------------------------+ + .. attribute:: int_info.bits_per_digit + + The number of bits held in each digit. + Python integers are stored internally in base ``2**int_info.bits_per_digit``. + + .. attribute:: int_info.sizeof_digit + + The size in bytes of the C type used to represent a digit. + + .. attribute:: int_info.default_max_str_digits + + The default value for :func:`sys.get_int_max_str_digits` + when it is not otherwise explicitly configured. + + .. attribute:: int_info.str_digits_check_threshold + + The 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.11 - Added ``default_max_str_digits`` and ``str_digits_check_threshold``. + + Added :attr:`~int_info.default_max_str_digits` and + :attr:`~int_info.str_digits_check_threshold`. .. data:: __interactivehook__ @@ -1106,14 +1182,14 @@ always available. names used in Python programs are automatically interned, and the dictionaries used to hold module, class or instance attributes have interned keys. - Interned strings are not immortal; you must keep a reference to the return - value of :func:`intern` around to benefit from it. + Interned strings are not :term:`immortal`; you must keep a reference to the + return value of :func:`intern` around to benefit from it. .. function:: is_finalizing() - Return :const:`True` if the Python interpreter is - :term:`shutting down `, :const:`False` otherwise. + Return :const:`True` if the main Python interpreter is + :term:`shutting down `. Return :const:`False` otherwise. .. versionadded:: 3.5 @@ -1129,6 +1205,18 @@ always available. .. versionadded:: 3.12 +.. function:: _is_interned(string) + + Return :const:`True` if the given string is "interned", :const:`False` + otherwise. + + .. versionadded:: 3.13 + + .. impl-detail:: + + It is not guaranteed to exist in all implementations of Python. + + .. data:: last_type last_value last_traceback @@ -1180,10 +1268,13 @@ always available. .. versionchanged:: 3.4 :term:`Module specs ` were introduced in Python 3.4, by - :pep:`451`. Earlier versions of Python looked for a method called - :meth:`!find_module`. - This is still called as a fallback if a :data:`meta_path` entry doesn't - have a :meth:`~importlib.abc.MetaPathFinder.find_spec` method. + :pep:`451`. + + .. versionchanged:: 3.12 + + Removed the fallback that looked for a :meth:`!find_module` method + if a :data:`meta_path` entry didn't have a + :meth:`~importlib.abc.MetaPathFinder.find_spec` method. .. data:: modules @@ -1371,7 +1462,7 @@ always available. lazy resolving of symbols when importing a module, if called as ``sys.setdlopenflags(0)``. To share symbols across extension modules, call as ``sys.setdlopenflags(os.RTLD_GLOBAL)``. Symbolic names for the flag values - can be found in the :mod:`os` module (``RTLD_xxx`` constants, e.g. + can be found in the :mod:`os` module (:samp:`RTLD_{xxx}` constants, e.g. :const:`os.RTLD_LAZY`). .. availability:: Unix. @@ -1401,13 +1492,16 @@ always available. its return value is not used, so it can simply return ``None``. Error in the profile function will cause itself unset. + .. note:: + The same tracing mechanism is used for :func:`!setprofile` as :func:`settrace`. + To trace calls with :func:`!setprofile` inside a tracing function + (e.g. in a debugger breakpoint), see :func:`call_tracing`. + Profile functions should have three arguments: *frame*, *event*, and *arg*. *frame* is the current stack frame. *event* is a string: ``'call'``, ``'return'``, ``'c_call'``, ``'c_return'``, or ``'c_exception'``. *arg* depends on the event type. - .. audit-event:: sys.setprofile "" sys.setprofile - The events have the following meaning: ``'call'`` @@ -1429,6 +1523,9 @@ always available. ``'c_exception'`` A C function has raised an exception. *arg* is the C function object. + .. audit-event:: sys.setprofile "" sys.setprofile + + .. function:: setrecursionlimit(limit) Set the maximum depth of the Python interpreter stack to *limit*. This limit @@ -1482,13 +1579,16 @@ always available. function to be used for the new scope, or ``None`` if the scope shouldn't be traced. - The local trace function should return a reference to itself (or to another - function for further tracing in that scope), or ``None`` to turn off tracing - in that scope. + The local trace function should return a reference to itself, or to another + function which would then be used as the local trace function for the scope. If there is any error occurred in the trace function, it will be unset, just like ``settrace(None)`` is called. + .. note:: + Tracing is disabled while calling the trace function (e.g. a function set by + :func:`!settrace`). For recursive tracing see :func:`call_tracing`. + The events have the following meaning: ``'call'`` @@ -1503,7 +1603,8 @@ always available. :file:`Objects/lnotab_notes.txt` for a detailed explanation of how this works. Per-line events may be disabled for a frame by setting - :attr:`f_trace_lines` to :const:`False` on that frame. + :attr:`~frame.f_trace_lines` to :const:`False` on that + :ref:`frame `. ``'return'`` A function (or other code block) is about to return. The local trace @@ -1521,8 +1622,8 @@ always available. opcode details). The local trace function is called; *arg* is ``None``; the return value specifies the new local trace function. Per-opcode events are not emitted by default: they must be explicitly - requested by setting :attr:`f_trace_opcodes` to :const:`True` on the - frame. + requested by setting :attr:`~frame.f_trace_opcodes` to :const:`True` on the + :ref:`frame `. Note that as an exception is propagated down the chain of callers, an ``'exception'`` event is generated at each level. @@ -1551,8 +1652,8 @@ always available. .. versionchanged:: 3.7 - ``'opcode'`` event type added; :attr:`f_trace_lines` and - :attr:`f_trace_opcodes` attributes added to frames + ``'opcode'`` event type added; :attr:`~frame.f_trace_lines` and + :attr:`~frame.f_trace_opcodes` attributes added to frames .. function:: set_asyncgen_hooks(firstiter, finalizer) @@ -1646,9 +1747,17 @@ always available. .. availability:: Windows. + .. note:: + Changing the filesystem encoding after Python startup is risky because + the old fsencoding or paths encoded by the old fsencoding may be cached + somewhere. Use :envvar:`PYTHONLEGACYWINDOWSFSENCODING` instead. + .. versionadded:: 3.6 See :pep:`529` for more details. + .. deprecated-removed:: 3.13 3.16 + Use :envvar:`PYTHONLEGACYWINDOWSFSENCODING` instead. + .. data:: stdin stdout stderr @@ -1709,7 +1818,7 @@ always available. However, if you are writing a library (and do not control in which context its code will be executed), be aware that the standard streams may be replaced with file-like objects like :class:`io.StringIO` which - do not support the :attr:`~io.BufferedIOBase.buffer` attribute. + do not support the :attr:`!buffer` attribute. .. data:: __stdin__ @@ -1757,29 +1866,28 @@ always available. A :term:`named tuple` holding information about the thread implementation. - .. tabularcolumns:: |l|p{0.7\linewidth}| - - +------------------+---------------------------------------------------------+ - | Attribute | Explanation | - +==================+=========================================================+ - | :const:`name` | Name of the thread implementation: | - | | | - | | * ``'nt'``: Windows threads | - | | * ``'pthread'``: POSIX threads | - | | * ``'pthread-stubs'``: stub POSIX threads | - | | (on WebAssembly platforms without threading support) | - | | * ``'solaris'``: Solaris threads | - +------------------+---------------------------------------------------------+ - | :const:`lock` | Name of the lock implementation: | - | | | - | | * ``'semaphore'``: a lock uses a semaphore | - | | * ``'mutex+cond'``: a lock uses a mutex | - | | and a condition variable | - | | * ``None`` if this information is unknown | - +------------------+---------------------------------------------------------+ - | :const:`version` | Name and version of the thread library. It is a string, | - | | or ``None`` if this information is unknown. | - +------------------+---------------------------------------------------------+ + .. attribute:: thread_info.name + + The name of the thread implementation: + + * ``"nt"``: Windows threads + * ``"pthread"``: POSIX threads + * ``"pthread-stubs"``: stub POSIX threads + (on WebAssembly platforms without threading support) + * ``"solaris"``: Solaris threads + + .. attribute:: thread_info.lock + + The name of the lock implementation: + + * ``"semaphore"``: a lock uses a semaphore + * ``"mutex+cond"``: a lock uses a mutex and a condition variable + * ``None`` if this information is unknown + + .. attribute:: thread_info.version + + The name and version of the thread library. + It is a string, or ``None`` if this information is unknown. .. versionadded:: 3.3 @@ -1802,35 +1910,39 @@ always available. The *unraisable* argument has the following attributes: - * *exc_type*: Exception type. - * *exc_value*: Exception value, can be ``None``. - * *exc_traceback*: Exception traceback, can be ``None``. - * *err_msg*: Error message, can be ``None``. - * *object*: Object causing the exception, can be ``None``. + * :attr:`!exc_type`: Exception type. + * :attr:`!exc_value`: Exception value, can be ``None``. + * :attr:`!exc_traceback`: Exception traceback, can be ``None``. + * :attr:`!err_msg`: Error message, can be ``None``. + * :attr:`!object`: Object causing the exception, can be ``None``. - The default hook formats *err_msg* and *object* as: + The default hook formats :attr:`!err_msg` and :attr:`!object` as: ``f'{err_msg}: {object!r}'``; use "Exception ignored in" error message - if *err_msg* is ``None``. + if :attr:`!err_msg` is ``None``. :func:`sys.unraisablehook` can be overridden to control how unraisable exceptions are handled. - Storing *exc_value* using a custom hook can create a reference cycle. It - should be cleared explicitly to break the reference cycle when the - exception is no longer needed. + .. seealso:: + + :func:`excepthook` which handles uncaught exceptions. - Storing *object* using a custom hook can resurrect it if it is set to an - object which is being finalized. Avoid storing *object* after the custom - hook completes to avoid resurrecting objects. + .. warning:: - See also :func:`excepthook` which handles uncaught exceptions. + Storing :attr:`!exc_value` using a custom hook can create a reference cycle. + It should be cleared explicitly to break the reference cycle when the + exception is no longer needed. + + Storing :attr:`!object` using a custom hook can resurrect it if it is set to an + object which is being finalized. Avoid storing :attr:`!object` after the custom + hook completes to avoid resurrecting objects. .. audit-event:: sys.unraisablehook hook,unraisable sys.unraisablehook Raise an auditing event ``sys.unraisablehook`` with arguments - ``hook``, ``unraisable`` when an exception that cannot be handled occurs. - The ``unraisable`` object is the same as what will be passed to the hook. - If no hook has been set, ``hook`` may be ``None``. + *hook*, *unraisable* when an exception that cannot be handled occurs. + The *unraisable* object is the same as what will be passed to the hook. + If no hook has been set, *hook* may be ``None``. .. versionadded:: 3.8 @@ -1880,6 +1992,13 @@ always available. .. availability:: Windows. +.. data:: monitoring + :noindex: + + Namespace containing functions and constants for register callbacks + and controlling monitoring events. + See :mod:`sys.monitoring` for details. + .. data:: _xoptions A dictionary of the various implementation-specific flags passed through diff --git a/Doc/library/sysconfig.rst b/Doc/library/sysconfig.rst index c805c50ffc689f..2faab212e46eff 100644 --- a/Doc/library/sysconfig.rst +++ b/Doc/library/sysconfig.rst @@ -9,7 +9,7 @@ .. versionadded:: 3.2 -**Source code:** :source:`Lib/sysconfig.py` +**Source code:** :source:`Lib/sysconfig` .. index:: single: configuration information @@ -20,6 +20,7 @@ The :mod:`sysconfig` module provides access to Python's configuration information like the list of installation paths and the configuration variables relevant for the current platform. + Configuration variables ----------------------- @@ -60,6 +61,7 @@ Example of usage:: >>> sysconfig.get_config_vars('AR', 'CXX') ['ar', 'g++'] + .. _installation_paths: Installation paths @@ -68,29 +70,26 @@ Installation paths Python uses an installation scheme that differs depending on the platform and on the installation options. These schemes are stored in :mod:`sysconfig` under unique identifiers based on the value returned by :const:`os.name`. - -Every new component that is installed using :mod:`!distutils` or a -Distutils-based system will follow the same scheme to copy its file in the right -places. +The schemes are used by package installers to determine where to copy files to. Python currently supports nine schemes: - *posix_prefix*: scheme for POSIX platforms like Linux or macOS. This is the default scheme used when Python or a component is installed. -- *posix_home*: scheme for POSIX platforms used when a *home* option is used - upon installation. This scheme is used when a component is installed through - Distutils with a specific home prefix. -- *posix_user*: scheme for POSIX platforms used when a component is installed - through Distutils and the *user* option is used. This scheme defines paths - located under the user home directory. +- *posix_home*: scheme for POSIX platforms, when the *home* option is used. + This scheme defines paths located under a specific home prefix. +- *posix_user*: scheme for POSIX platforms, when the *user* option is used. + This scheme defines paths located under the user's home directory + (:const:`site.USER_BASE`). - *posix_venv*: scheme for :mod:`Python virtual environments ` on POSIX - platforms; by default it is the same as *posix_prefix* . -- *nt*: scheme for NT platforms like Windows. -- *nt_user*: scheme for NT platforms, when the *user* option is used. -- *nt_venv*: scheme for :mod:`Python virtual environments ` on NT - platforms; by default it is the same as *nt* . -- *venv*: a scheme with values from ether *posix_venv* or *nt_venv* depending - on the platform Python runs on + platforms; by default it is the same as *posix_prefix*. +- *nt*: scheme for Windows. + This is the default scheme used when Python or a component is installed. +- *nt_user*: scheme for Windows, when the *user* option is used. +- *nt_venv*: scheme for :mod:`Python virtual environments ` on Windows; + by default it is the same as *nt*. +- *venv*: a scheme with values from either *posix_venv* or *nt_venv* depending + on the platform Python runs on. - *osx_framework_user*: scheme for macOS, when the *user* option is used. Each scheme is itself composed of a series of paths and each path has a unique @@ -101,7 +100,7 @@ identifier. Python currently uses eight paths: - *platstdlib*: directory containing the standard Python library files that are platform-specific. - *platlib*: directory for site-specific, platform-specific files. -- *purelib*: directory for site-specific, non-platform-specific files. +- *purelib*: directory for site-specific, non-platform-specific files ('pure' Python). - *include*: directory for non-platform-specific header files for the Python C-API. - *platinclude*: directory for platform-specific header files for @@ -109,7 +108,157 @@ identifier. Python currently uses eight paths: - *scripts*: directory for script files. - *data*: directory for data files. -:mod:`sysconfig` provides some functions to determine these paths. + +.. _sysconfig-user-scheme: + +User scheme +--------------- + +This scheme is designed to be the most convenient solution for users that don't +have write permission to the global site-packages directory or don't want to +install into it. + +Files will be installed into subdirectories of :const:`site.USER_BASE` (written +as :file:`{userbase}` hereafter). This scheme installs pure Python modules and +extension modules in the same location (also known as :const:`site.USER_SITE`). + +``posix_user`` +^^^^^^^^^^^^^^ + +============== =========================================================== +Path Installation directory +============== =========================================================== +*stdlib* :file:`{userbase}/lib/python{X.Y}` +*platstdlib* :file:`{userbase}/lib/python{X.Y}` +*platlib* :file:`{userbase}/lib/python{X.Y}/site-packages` +*purelib* :file:`{userbase}/lib/python{X.Y}/site-packages` +*include* :file:`{userbase}/include/python{X.Y}` +*scripts* :file:`{userbase}/bin` +*data* :file:`{userbase}` +============== =========================================================== + +``nt_user`` +^^^^^^^^^^^ + +============== =========================================================== +Path Installation directory +============== =========================================================== +*stdlib* :file:`{userbase}\\Python{XY}` +*platstdlib* :file:`{userbase}\\Python{XY}` +*platlib* :file:`{userbase}\\Python{XY}\\site-packages` +*purelib* :file:`{userbase}\\Python{XY}\\site-packages` +*include* :file:`{userbase}\\Python{XY}\\Include` +*scripts* :file:`{userbase}\\Python{XY}\\Scripts` +*data* :file:`{userbase}` +============== =========================================================== + +``osx_framework_user`` +^^^^^^^^^^^^^^^^^^^^^^ + +============== =========================================================== +Path Installation directory +============== =========================================================== +*stdlib* :file:`{userbase}/lib/python` +*platstdlib* :file:`{userbase}/lib/python` +*platlib* :file:`{userbase}/lib/python/site-packages` +*purelib* :file:`{userbase}/lib/python/site-packages` +*include* :file:`{userbase}/include/python{X.Y}` +*scripts* :file:`{userbase}/bin` +*data* :file:`{userbase}` +============== =========================================================== + + +.. _sysconfig-home-scheme: + +Home scheme +----------- + +The idea behind the "home scheme" is that you build and maintain a personal +stash of Python modules. This scheme's name is derived from the idea of a +"home" directory on Unix, since it's not unusual for a Unix user to make their +home directory have a layout similar to :file:`/usr/` or :file:`/usr/local/`. +This scheme can be used by anyone, regardless of the operating system they +are installing for. + +``posix_home`` +^^^^^^^^^^^^^^ + +============== =========================================================== +Path Installation directory +============== =========================================================== +*stdlib* :file:`{home}/lib/python` +*platstdlib* :file:`{home}/lib/python` +*platlib* :file:`{home}/lib/python` +*purelib* :file:`{home}/lib/python` +*include* :file:`{home}/include/python` +*platinclude* :file:`{home}/include/python` +*scripts* :file:`{home}/bin` +*data* :file:`{home}` +============== =========================================================== + + +.. _sysconfig-prefix-scheme: + +Prefix scheme +------------- + +The "prefix scheme" is useful when you wish to use one Python installation to +perform the build/install (i.e., to run the setup script), but install modules +into the third-party module directory of a different Python installation (or +something that looks like a different Python installation). If this sounds a +trifle unusual, it is---that's why the user and home schemes come before. However, +there are at least two known cases where the prefix scheme will be useful. + +First, consider that many Linux distributions put Python in :file:`/usr`, rather +than the more traditional :file:`/usr/local`. This is entirely appropriate, +since in those cases Python is part of "the system" rather than a local add-on. +However, if you are installing Python modules from source, you probably want +them to go in :file:`/usr/local/lib/python2.{X}` rather than +:file:`/usr/lib/python2.{X}`. + +Another possibility is a network filesystem where the name used to write to a +remote directory is different from the name used to read it: for example, the +Python interpreter accessed as :file:`/usr/local/bin/python` might search for +modules in :file:`/usr/local/lib/python2.{X}`, but those modules would have to +be installed to, say, :file:`/mnt/{@server}/export/lib/python2.{X}`. + +``posix_prefix`` +^^^^^^^^^^^^^^^^ + +============== ========================================================== +Path Installation directory +============== ========================================================== +*stdlib* :file:`{prefix}/lib/python{X.Y}` +*platstdlib* :file:`{prefix}/lib/python{X.Y}` +*platlib* :file:`{prefix}/lib/python{X.Y}/site-packages` +*purelib* :file:`{prefix}/lib/python{X.Y}/site-packages` +*include* :file:`{prefix}/include/python{X.Y}` +*platinclude* :file:`{prefix}/include/python{X.Y}` +*scripts* :file:`{prefix}/bin` +*data* :file:`{prefix}` +============== ========================================================== + +``nt`` +^^^^^^ + +============== ========================================================== +Path Installation directory +============== ========================================================== +*stdlib* :file:`{prefix}\\Lib` +*platstdlib* :file:`{prefix}\\Lib` +*platlib* :file:`{prefix}\\Lib\\site-packages` +*purelib* :file:`{prefix}\\Lib\\site-packages` +*include* :file:`{prefix}\\Include` +*platinclude* :file:`{prefix}\\Include` +*scripts* :file:`{prefix}\\Scripts` +*data* :file:`{prefix}` +============== ========================================================== + + +Installation path functions +--------------------------- + +:mod:`sysconfig` provides some functions to determine these installation paths. .. function:: get_scheme_names() @@ -187,7 +336,7 @@ identifier. Python currently uses eight paths: platform is used. If *vars* is provided, it must be a dictionary of variables that will update - the dictionary return by :func:`get_config_vars`. + the dictionary returned by :func:`get_config_vars`. If *expand* is set to ``False``, the path will not be expanded using the variables. @@ -278,6 +427,7 @@ Other functions Return the path of :file:`Makefile`. +.. _sysconfig-cli: Using :mod:`sysconfig` as a script ---------------------------------- diff --git a/Doc/library/syslog.rst b/Doc/library/syslog.rst index f29ef03267b1ba..7b27fc7e85b62d 100644 --- a/Doc/library/syslog.rst +++ b/Doc/library/syslog.rst @@ -11,11 +11,11 @@ This module provides an interface to the Unix ``syslog`` library routines. Refer to the Unix manual pages for a detailed description of the ``syslog`` facility. +.. availability:: Unix, not Emscripten, not WASI. + This module wraps the system ``syslog`` family of routines. A pure Python library that can speak to a syslog server is available in the -:mod:`logging.handlers` module as :class:`SysLogHandler`. - -.. include:: ../includes/wasm-notavail.rst +:mod:`logging.handlers` module as :class:`~logging.handlers.SysLogHandler`. The module defines the following functions: @@ -107,22 +107,62 @@ The module defines the following functions: The module defines the following constants: -Priority levels (high to low): - :const:`LOG_EMERG`, :const:`LOG_ALERT`, :const:`LOG_CRIT`, :const:`LOG_ERR`, - :const:`LOG_WARNING`, :const:`LOG_NOTICE`, :const:`LOG_INFO`, - :const:`LOG_DEBUG`. - -Facilities: - :const:`LOG_KERN`, :const:`LOG_USER`, :const:`LOG_MAIL`, :const:`LOG_DAEMON`, - :const:`LOG_AUTH`, :const:`LOG_LPR`, :const:`LOG_NEWS`, :const:`LOG_UUCP`, - :const:`LOG_CRON`, :const:`LOG_SYSLOG`, :const:`LOG_LOCAL0` to - :const:`LOG_LOCAL7`, and, if defined in ````, - :const:`LOG_AUTHPRIV`. - -Log options: - :const:`LOG_PID`, :const:`LOG_CONS`, :const:`LOG_NDELAY`, and, if defined - in ````, :const:`LOG_ODELAY`, :const:`LOG_NOWAIT`, and - :const:`LOG_PERROR`. + +.. data:: LOG_EMERG + LOG_ALERT + LOG_CRIT + LOG_ERR + LOG_WARNING + LOG_NOTICE + LOG_INFO + LOG_DEBUG + + Priority levels (high to low). + + +.. data:: LOG_AUTH + LOG_AUTHPRIV + LOG_CRON + LOG_DAEMON + LOG_FTP + LOG_INSTALL + LOG_KERN + LOG_LAUNCHD + LOG_LPR + LOG_MAIL + LOG_NETINFO + LOG_NEWS + LOG_RAS + LOG_REMOTEAUTH + LOG_SYSLOG + LOG_USER + LOG_UUCP + LOG_LOCAL0 + LOG_LOCAL1 + LOG_LOCAL2 + LOG_LOCAL3 + LOG_LOCAL4 + LOG_LOCAL5 + LOG_LOCAL6 + LOG_LOCAL7 + + Facilities, depending on availability in ```` for :const:`LOG_AUTHPRIV`, + :const:`LOG_FTP`, :const:`LOG_NETINFO`, :const:`LOG_REMOTEAUTH`, + :const:`LOG_INSTALL` and :const:`LOG_RAS`. + + .. versionchanged:: 3.13 + Added :const:`LOG_FTP`, :const:`LOG_NETINFO`, :const:`LOG_REMOTEAUTH`, + :const:`LOG_INSTALL`, :const:`LOG_RAS`, and :const:`LOG_LAUNCHD`. + +.. data:: LOG_PID + LOG_CONS + LOG_NDELAY + LOG_ODELAY + LOG_NOWAIT + LOG_PERROR + + Log options, depending on availability in ```` for + :const:`LOG_ODELAY`, :const:`LOG_NOWAIT` and :const:`LOG_PERROR`. Examples diff --git a/Doc/library/tarfile.rst b/Doc/library/tarfile.rst index 00f3070324ec1e..7ba29d4a40dedb 100644 --- a/Doc/library/tarfile.rst +++ b/Doc/library/tarfile.rst @@ -116,10 +116,12 @@ Some facts and figures: ``'filemode|[compression]'``. :func:`tarfile.open` will return a :class:`TarFile` object that processes its data as a stream of blocks. No random seeking will be done on the file. If given, *fileobj* may be any object that has a - :meth:`read` or :meth:`write` method (depending on the *mode*). *bufsize* - specifies the blocksize and defaults to ``20 * 512`` bytes. Use this variant - in combination with e.g. ``sys.stdin``, a socket :term:`file object` or a tape - device. However, such a :class:`TarFile` object is limited in that it does + :meth:`~io.RawIOBase.read` or :meth:`~io.RawIOBase.write` method + (depending on the *mode*) that works with bytes. + *bufsize* specifies the blocksize and defaults to ``20 * 512`` bytes. + Use this variant in combination with e.g. ``sys.stdin.buffer``, a socket + :term:`file object` or a tape device. + However, such a :class:`TarFile` object is limited in that it does not allow random access, see :ref:`tar-examples`. The currently possible modes: @@ -255,6 +257,51 @@ The following constants are available at the module level: The default character encoding: ``'utf-8'`` on Windows, the value returned by :func:`sys.getfilesystemencoding` otherwise. +.. data:: REGTYPE + AREGTYPE + + A regular file :attr:`~TarInfo.type`. + +.. data:: LNKTYPE + + A link (inside tarfile) :attr:`~TarInfo.type`. + +.. data:: SYMTYPE + + A symbolic link :attr:`~TarInfo.type`. + +.. data:: CHRTYPE + + A character special device :attr:`~TarInfo.type`. + +.. data:: BLKTYPE + + A block special device :attr:`~TarInfo.type`. + +.. data:: DIRTYPE + + A directory :attr:`~TarInfo.type`. + +.. data:: FIFOTYPE + + A FIFO special device :attr:`~TarInfo.type`. + +.. data:: CONTTYPE + + A contiguous file :attr:`~TarInfo.type`. + +.. data:: GNUTYPE_LONGNAME + + A GNU tar longname :attr:`~TarInfo.type`. + +.. data:: GNUTYPE_LONGLINK + + A GNU tar longlink :attr:`~TarInfo.type`. + +.. data:: GNUTYPE_SPARSE + + A GNU tar sparse file :attr:`~TarInfo.type`. + Each of the following constants defines a tar archive format that the :mod:`tarfile` module is able to create. See section :ref:`tar-formats` for @@ -325,7 +372,7 @@ be finalized; only the internally used file object will be closed. See the *name* is the pathname of the archive. *name* may be a :term:`path-like object`. It can be omitted if *fileobj* is given. - In this case, the file object's :attr:`name` attribute is used if it exists. + In this case, the file object's :attr:`!name` attribute is used if it exists. *mode* is either ``'r'`` to read from an existing archive, ``'a'`` to append data to an existing file, ``'w'`` to create a new file overwriting an existing @@ -359,7 +406,7 @@ be finalized; only the internally used file object will be closed. See the messages). The messages are written to ``sys.stderr``. *errorlevel* controls how extraction errors are handled, - see :attr:`the corresponding attribute <~TarFile.errorlevel>`. + see :attr:`the corresponding attribute `. The *encoding* and *errors* arguments define the character encoding to be used for reading or writing the archive and how conversion errors are going @@ -645,8 +692,8 @@ It does *not* contain the file's data itself. :meth:`~TarFile.getmember`, :meth:`~TarFile.getmembers` and :meth:`~TarFile.gettarinfo`. -Modifying the objects returned by :meth:`~!TarFile.getmember` or -:meth:`~!TarFile.getmembers` will affect all subsequent +Modifying the objects returned by :meth:`~TarFile.getmember` or +:meth:`~TarFile.getmembers` will affect all subsequent operations on the archive. For cases where this is unwanted, you can use :mod:`copy.copy() ` or call the :meth:`~TarInfo.replace` method to create a modified copy in one step. @@ -740,6 +787,11 @@ A ``TarInfo`` object has the following public data attributes: Name of the target file name, which is only present in :class:`TarInfo` objects of type :const:`LNKTYPE` and :const:`SYMTYPE`. + For symbolic links (``SYMTYPE``), the *linkname* is relative to the directory + that contains the link. + For hard links (``LNKTYPE``), the *linkname* is relative to the root of + the archive. + .. attribute:: TarInfo.uid :type: int @@ -790,8 +842,8 @@ A ``TarInfo`` object has the following public data attributes: A dictionary containing key-value pairs of an associated pax extended header. -.. method:: TarInfo.replace(name=..., mtime=..., mode=..., linkname=..., - uid=..., gid=..., uname=..., gname=..., +.. method:: TarInfo.replace(name=..., mtime=..., mode=..., linkname=..., \ + uid=..., gid=..., uname=..., gname=..., \ deep=True) .. versionadded:: 3.12 @@ -811,7 +863,7 @@ A :class:`TarInfo` object also provides some convenient query methods: .. method:: TarInfo.isfile() - Return :const:`True` if the :class:`Tarinfo` object is a regular file. + Return :const:`True` if the :class:`TarInfo` object is a regular file. .. method:: TarInfo.isreg() @@ -947,7 +999,7 @@ reused in custom filters: path (after following symlinks) would end up outside the destination. This raises :class:`~tarfile.OutsideDestinationError`. - Clear high mode bits (setuid, setgid, sticky) and group/other write bits - (:const:`~stat.S_IWGRP`|:const:`~stat.S_IWOTH`). + (:const:`~stat.S_IWGRP` | :const:`~stat.S_IWOTH`). Return the modified ``TarInfo`` member. @@ -972,9 +1024,9 @@ reused in custom filters: - For regular files, including hard links: - Set the owner read and write permissions - (:const:`~stat.S_IRUSR`|:const:`~stat.S_IWUSR`). + (:const:`~stat.S_IRUSR` | :const:`~stat.S_IWUSR`). - Remove the group & other executable permission - (:const:`~stat.S_IXGRP`|:const:`~stat.S_IXOTH`) + (:const:`~stat.S_IXGRP` | :const:`~stat.S_IXOTH`) if the owner doesn’t have it (:const:`~stat.S_IXUSR`). - For other files (directories), set ``mode`` to ``None``, so @@ -1151,31 +1203,31 @@ For a list of the files in a tar archive, use the :option:`-l` option: Command-line options ~~~~~~~~~~~~~~~~~~~~ -.. cmdoption:: -l - --list +.. option:: -l + --list List files in a tarfile. -.. cmdoption:: -c ... - --create ... +.. option:: -c ... + --create ... Create tarfile from source files. -.. cmdoption:: -e [] - --extract [] +.. option:: -e [] + --extract [] Extract tarfile into the current directory if *output_dir* is not specified. -.. cmdoption:: -t - --test +.. option:: -t + --test Test whether the tarfile is valid or not. -.. cmdoption:: -v, --verbose +.. option:: -v, --verbose Verbose output. -.. cmdoption:: --filter +.. option:: --filter Specifies the *filter* for ``--extract``. See :ref:`tarfile-extraction-filter` for details. diff --git a/Doc/library/tempfile.rst b/Doc/library/tempfile.rst index 097f7087eccab9..9add8500c7788c 100644 --- a/Doc/library/tempfile.rst +++ b/Doc/library/tempfile.rst @@ -18,7 +18,7 @@ This module creates temporary files and directories. It works on all supported platforms. :class:`TemporaryFile`, :class:`NamedTemporaryFile`, :class:`TemporaryDirectory`, and :class:`SpooledTemporaryFile` are high-level interfaces which provide automatic cleanup and can be used as -context managers. :func:`mkstemp` and +:term:`context managers `. :func:`mkstemp` and :func:`mkdtemp` are lower-level functions which require manual cleanup. All the user-callable functions and constructors take additional arguments which @@ -41,7 +41,7 @@ The module defines the following user-callable items: this; your code should not rely on a temporary file created using this function having or not having a visible name in the file system. - The resulting object can be used as a context manager (see + The resulting object can be used as a :term:`context manager` (see :ref:`tempfile-examples`). On completion of the context or destruction of the file object the temporary file will be removed from the filesystem. @@ -87,9 +87,9 @@ The module defines the following user-callable items: determine whether and how the named file should be automatically deleted. The returned object is always a :term:`file-like object` whose :attr:`!file` - attribute is the underlying true file object. This :term:`file-like object` + attribute is the underlying true file object. This file-like object can be used in a :keyword:`with` statement, just like a normal file. The - name of the temporary file can be retrieved from the :attr:`name` attribute + name of the temporary file can be retrieved from the :attr:`!name` attribute of the returned file-like object. On Unix, unlike with the :func:`TemporaryFile`, the directory entry does not get unlinked immediately after the file creation. @@ -115,14 +115,14 @@ The module defines the following user-callable items: * On Windows, make sure that at least one of the following conditions are fulfilled: - * *delete* is false - * additional open shares delete access (e.g. by calling :func:`os.open` - with the flag ``O_TEMPORARY``) - * *delete* is true but *delete_on_close* is false. Note, that in this - case the additional opens that do not share delete access (e.g. - created via builtin :func:`open`) must be closed before exiting the - context manager, else the :func:`os.unlink` call on context manager - exit will fail with a :exc:`PermissionError`. + * *delete* is false + * additional open shares delete access (e.g. by calling :func:`os.open` + with the flag ``O_TEMPORARY``) + * *delete* is true but *delete_on_close* is false. Note, that in this + case the additional opens that do not share delete access (e.g. + created via builtin :func:`open`) must be closed before exiting the + context manager, else the :func:`os.unlink` call on context manager + exit will fail with a :exc:`PermissionError`. On Windows, if *delete_on_close* is false, and the file is created in a directory for which the user lacks delete access, then the :func:`os.unlink` @@ -147,22 +147,24 @@ The module defines the following user-callable items: This class operates exactly as :func:`TemporaryFile` does, except that data is spooled in memory until the file size exceeds *max_size*, or - until the file's :func:`fileno` method is called, at which point the + until the file's :func:`~io.IOBase.fileno` method is called, at which point the contents are written to disk and operation proceeds as with :func:`TemporaryFile`. - The resulting file has one additional method, :func:`rollover`, which - causes the file to roll over to an on-disk file regardless of its size. + .. method:: SpooledTemporaryFile.rollover - The returned object is a file-like object whose :attr:`_file` attribute + The resulting file has one additional method, :meth:`!rollover`, which + causes the file to roll over to an on-disk file regardless of its size. + + The returned object is a file-like object whose :attr:`!_file` attribute is either an :class:`io.BytesIO` or :class:`io.TextIOWrapper` object (depending on whether binary or text *mode* was specified) or a true file - object, depending on whether :func:`rollover` has been called. This + object, depending on whether :meth:`rollover` has been called. This file-like object can be used in a :keyword:`with` statement, just like a normal file. .. versionchanged:: 3.3 - the truncate method now accepts a ``size`` argument. + the truncate method now accepts a *size* argument. .. versionchanged:: 3.8 Added *errors* parameter. @@ -176,24 +178,28 @@ The module defines the following user-callable items: .. class:: TemporaryDirectory(suffix=None, prefix=None, dir=None, ignore_cleanup_errors=False, *, delete=True) This class securely creates a temporary directory using the same rules as :func:`mkdtemp`. - The resulting object can be used as a context manager (see + The resulting object can be used as a :term:`context manager` (see :ref:`tempfile-examples`). On completion of the context or destruction of the temporary directory object, the newly created temporary directory and all its contents are removed from the filesystem. - The directory name can be retrieved from the :attr:`name` attribute of the - returned object. When the returned object is used as a context manager, the - :attr:`name` will be assigned to the target of the :keyword:`!as` clause in - the :keyword:`with` statement, if there is one. + .. attribute:: TemporaryDirectory.name + + The directory name can be retrieved from the :attr:`!name` attribute of the + returned object. When the returned object is used as a :term:`context manager`, the + :attr:`!name` will be assigned to the target of the :keyword:`!as` clause in + the :keyword:`with` statement, if there is one. - The directory can be explicitly cleaned up by calling the - :func:`cleanup` method. If *ignore_cleanup_errors* is true, any unhandled - exceptions during explicit or implicit cleanup (such as a - :exc:`PermissionError` removing open files on Windows) will be ignored, - and the remaining removable items deleted on a "best-effort" basis. - Otherwise, errors will be raised in whatever context cleanup occurs - (the :func:`cleanup` call, exiting the context manager, when the object - is garbage-collected or during interpreter shutdown). + .. method:: TemporaryDirectory.cleanup + + The directory can be explicitly cleaned up by calling the + :meth:`!cleanup` method. If *ignore_cleanup_errors* is true, any unhandled + exceptions during explicit or implicit cleanup (such as a + :exc:`PermissionError` removing open files on Windows) will be ignored, + and the remaining removable items deleted on a "best-effort" basis. + Otherwise, errors will be raised in whatever context cleanup occurs + (the :meth:`!cleanup` call, exiting the context manager, when the object + is garbage-collected or during interpreter shutdown). The *delete* parameter can be used to disable cleanup of the directory tree upon exiting the context. While it may seem unusual for a context manager @@ -404,13 +410,13 @@ Here are some examples of typical usage of the :mod:`tempfile` module:: # create a temporary file using a context manager # close the file, use the name to open the file again - >>> with tempfile.TemporaryFile(delete_on_close=False) as fp: - ... fp.write(b'Hello world!') - ... fp.close() - # the file is closed, but not removed - # open the file again by using its name - ... with open(fp.name) as f - ... f.read() + >>> with tempfile.NamedTemporaryFile(delete_on_close=False) as fp: + ... fp.write(b'Hello world!') + ... fp.close() + ... # the file is closed, but not removed + ... # open the file again by using its name + ... with open(fp.name, mode='rb') as f: + ... f.read() b'Hello world!' >>> # file is now removed diff --git a/Doc/library/termios.rst b/Doc/library/termios.rst index fb1ff567d49e5c..57705ddc4e6470 100644 --- a/Doc/library/termios.rst +++ b/Doc/library/termios.rst @@ -16,6 +16,8 @@ complete description of these calls, see :manpage:`termios(3)` Unix manual page. It is only available for those Unix versions that support POSIX *termios* style tty I/O control configured during installation. +.. availability:: Unix. + All functions in this module take a file descriptor *fd* as their first argument. This can be an integer file descriptor, such as returned by ``sys.stdin.fileno()``, or a :term:`file object`, such as ``sys.stdin`` itself. @@ -43,10 +45,20 @@ The module defines the following functions: Set the tty attributes for file descriptor *fd* from the *attributes*, which is a list like the one returned by :func:`tcgetattr`. The *when* argument - determines when the attributes are changed: :const:`TCSANOW` to change - immediately, :const:`TCSADRAIN` to change after transmitting all queued output, - or :const:`TCSAFLUSH` to change after transmitting all queued output and - discarding all queued input. + determines when the attributes are changed: + + .. data:: TCSANOW + + Change attributes immediately. + + .. data:: TCSADRAIN + + Change attributes after transmitting all queued output. + + .. data:: TCSAFLUSH + + Change attributes after transmitting all queued output and + discarding all queued input. .. function:: tcsendbreak(fd, duration) diff --git a/Doc/library/test.rst b/Doc/library/test.rst index de60151bb32ce1..9173db07fd0071 100644 --- a/Doc/library/test.rst +++ b/Doc/library/test.rst @@ -159,6 +159,9 @@ guidelines to be followed: Running tests using the command-line interface ---------------------------------------------- +.. module:: test.regrtest + :synopsis: Drives the regression test suite. + The :mod:`test` package can be run as a script to drive Python's regression test suite, thanks to the :option:`-m` option: :program:`python -m test`. Under the hood, it uses :mod:`test.regrtest`; the call :program:`python -m @@ -498,44 +501,6 @@ The :mod:`test.support` module defines the following functions: rather than looking directly in the path directories. -.. function:: match_test(test) - - Determine whether *test* matches the patterns set in :func:`set_match_tests`. - - -.. function:: set_match_tests(accept_patterns=None, ignore_patterns=None) - - Define match patterns on test filenames and test method names for filtering tests. - - -.. function:: run_unittest(*classes) - - Execute :class:`unittest.TestCase` subclasses passed to the function. The - function scans the classes for methods starting with the prefix ``test_`` - and executes the tests individually. - - It is also legal to pass strings as parameters; these should be keys in - ``sys.modules``. Each associated module will be scanned by - ``unittest.TestLoader.loadTestsFromModule()``. This is usually seen in the - following :func:`test_main` function:: - - def test_main(): - support.run_unittest(__name__) - - This will run all tests defined in the named module. - - -.. function:: run_doctest(module, verbosity=None, optionflags=0) - - Run :func:`doctest.testmod` on the given *module*. Return - ``(failure_count, test_count)``. - - If *verbosity* is ``None``, :func:`doctest.testmod` is run with verbosity - set to :data:`verbose`. Otherwise, it is run with verbosity set to - ``None``. *optionflags* is passed as ``optionflags`` to - :func:`doctest.testmod`. - - .. function:: get_pagesize() Get size of a page in bytes. @@ -1043,7 +1008,7 @@ The :mod:`test.support` module defines the following classes: :const:`resource.RLIMIT_CORE`'s soft limit to 0 to prevent coredump file creation. - On both platforms, the old value is restored by :meth:`__exit__`. + On both platforms, the old value is restored by :meth:`~object.__exit__`. .. class:: SaveSignals() @@ -1443,7 +1408,8 @@ The :mod:`test.support.os_helper` module provides support for os tests. .. class:: FakePath(path) - Simple :term:`path-like object`. It implements the :meth:`__fspath__` + Simple :term:`path-like object`. It implements the + :meth:`~os.PathLike.__fspath__` method which just returns the *path* argument. If *path* is an exception, it will be raised in :meth:`!__fspath__`. diff --git a/Doc/library/textwrap.rst b/Doc/library/textwrap.rst index a150eefbf932ef..7445410f91808c 100644 --- a/Doc/library/textwrap.rst +++ b/Doc/library/textwrap.rst @@ -60,7 +60,7 @@ functions should be good enough; otherwise, you should use an instance of First the whitespace in *text* is collapsed (all whitespace is replaced by single spaces). If the result fits in the *width*, it is returned. Otherwise, enough words are dropped from the end so that the remaining words - plus the :attr:`.placeholder` fit within :attr:`.width`:: + plus the *placeholder* fit within *width*:: >>> textwrap.shorten("Hello world!", width=12) 'Hello world!' @@ -238,7 +238,7 @@ hyphenated words; only then will long words be broken if necessary, unless However, the sentence detection algorithm is imperfect: it assumes that a sentence ending consists of a lowercase letter followed by one of ``'.'``, ``'!'``, or ``'?'``, possibly followed by one of ``'"'`` or ``"'"``, - followed by a space. One problem with this is algorithm is that it is + followed by a space. One problem with this algorithm is that it is unable to detect the difference between "Dr." in :: [...] Dr. Frankenstein's monster [...] diff --git a/Doc/library/threading.rst b/Doc/library/threading.rst index 83ed48052704fb..b85b7f008d1594 100644 --- a/Doc/library/threading.rst +++ b/Doc/library/threading.rst @@ -127,10 +127,13 @@ This module defines the following functions: Its value may be used to uniquely identify this particular thread system-wide (until the thread terminates, after which the value may be recycled by the OS). - .. availability:: Windows, FreeBSD, Linux, macOS, OpenBSD, NetBSD, AIX, DragonFlyBSD. + .. availability:: Windows, FreeBSD, Linux, macOS, OpenBSD, NetBSD, AIX, DragonFlyBSD, GNU/kFreeBSD. .. versionadded:: 3.8 + .. versionchanged:: 3.13 + Added support for GNU/kFreeBSD. + .. function:: enumerate() @@ -272,7 +275,7 @@ The instance's values will be different for separate threads. A class that represents thread-local data. For more details and extensive examples, see the documentation string of the - :mod:`_threading_local` module: :source:`Lib/_threading_local.py`. + :mod:`!_threading_local` module: :source:`Lib/_threading_local.py`. .. _thread-objects: @@ -285,7 +288,7 @@ thread of control. There are two ways to specify the activity: by passing a callable object to the constructor, or by overriding the :meth:`~Thread.run` method in a subclass. No other methods (except for the constructor) should be overridden in a subclass. In other words, *only* override the -:meth:`~Thread.__init__` and :meth:`~Thread.run` methods of this class. +``__init__()`` and :meth:`~Thread.run` methods of this class. Once a thread object is created, its activity must be started by calling the thread's :meth:`~Thread.start` method. This invokes the :meth:`~Thread.run` @@ -337,7 +340,7 @@ since it is impossible to detect the termination of alien threads. are: *group* should be ``None``; reserved for future extension when a - :class:`ThreadGroup` class is implemented. + :class:`!ThreadGroup` class is implemented. *target* is the callable object to be invoked by the :meth:`run` method. Defaults to ``None``, meaning nothing is called. @@ -1009,7 +1012,7 @@ This class represents an action that should be run only after a certain amount of time has passed --- a timer. :class:`Timer` is a subclass of :class:`Thread` and as such also functions as an example of creating custom threads. -Timers are started, as with threads, by calling their :meth:`~Timer.start` +Timers are started, as with threads, by calling their :meth:`Timer.start ` method. The timer can be stopped (before its action has begun) by calling the :meth:`~Timer.cancel` method. The interval the timer will wait before executing its action may not be exactly the same as the interval specified by @@ -1147,10 +1150,10 @@ As an example, here is a simple way to synchronize a client and server thread:: Using locks, conditions, and semaphores in the :keyword:`!with` statement ------------------------------------------------------------------------- -All of the objects provided by this module that have :meth:`acquire` and -:meth:`release` methods can be used as context managers for a :keyword:`with` -statement. The :meth:`acquire` method will be called when the block is -entered, and :meth:`release` will be called when the block is exited. Hence, +All of the objects provided by this module that have ``acquire`` and +``release`` methods can be used as context managers for a :keyword:`with` +statement. The ``acquire`` method will be called when the block is +entered, and ``release`` will be called when the block is exited. Hence, the following snippet:: with some_lock: diff --git a/Doc/library/time.rst b/Doc/library/time.rst index 9f23a6fc7d5341..2782a961363666 100644 --- a/Doc/library/time.rst +++ b/Doc/library/time.rst @@ -71,8 +71,8 @@ An explanation of some terminology and conventions is in order. * On the other hand, the precision of :func:`.time` and :func:`sleep` is better than their Unix equivalents: times are expressed as floating point numbers, :func:`.time` returns the most accurate time available (using Unix - :c:func:`gettimeofday` where available), and :func:`sleep` will accept a time - with a nonzero fraction (Unix :c:func:`select` is used to implement this, where + :c:func:`!gettimeofday` where available), and :func:`sleep` will accept a time + with a nonzero fraction (Unix :c:func:`!select` is used to implement this, where available). * The time value as returned by :func:`gmtime`, :func:`localtime`, and @@ -84,12 +84,14 @@ An explanation of some terminology and conventions is in order. See :class:`struct_time` for a description of these objects. .. versionchanged:: 3.3 - The :class:`struct_time` type was extended to provide the :attr:`tm_gmtoff` - and :attr:`tm_zone` attributes when platform supports corresponding + The :class:`struct_time` type was extended to provide + the :attr:`~struct_time.tm_gmtoff` and :attr:`~struct_time.tm_zone` + attributes when platform supports corresponding ``struct tm`` members. .. versionchanged:: 3.6 - The :class:`struct_time` attributes :attr:`tm_gmtoff` and :attr:`tm_zone` + The :class:`struct_time` attributes + :attr:`~struct_time.tm_gmtoff` and :attr:`~struct_time.tm_zone` are now available on all platforms. * Use the following functions to convert between time representations: @@ -379,6 +381,8 @@ Functions * Or use ``nanosleep()`` if available (resolution: 1 nanosecond); * Or use ``select()`` (resolution: 1 microsecond). + .. audit-event:: time.sleep secs + .. versionchanged:: 3.11 On Unix, the ``clock_nanosleep()`` and ``nanosleep()`` functions are now used if available. On Windows, a waitable timer is now used. @@ -389,6 +393,9 @@ Functions :pep:`475` for the rationale). + .. versionchanged:: 3.13 + Raises an auditing event. + .. index:: single: % (percent); datetime format @@ -496,6 +503,8 @@ Functions When used with the :func:`strptime` function, the ``%p`` directive only affects the output hour field if the ``%I`` directive is used to parse the hour. + .. _leap-second: + (2) The range really is ``0`` to ``61``; value ``60`` is valid in timestamps representing `leap seconds`_ and value ``61`` is supported @@ -566,32 +575,55 @@ Functions tuple` interface: values can be accessed by index and by attribute name. The following values are present: - +-------+-------------------+---------------------------------+ - | Index | Attribute | Values | - +=======+===================+=================================+ - | 0 | :attr:`tm_year` | (for example, 1993) | - +-------+-------------------+---------------------------------+ - | 1 | :attr:`tm_mon` | range [1, 12] | - +-------+-------------------+---------------------------------+ - | 2 | :attr:`tm_mday` | range [1, 31] | - +-------+-------------------+---------------------------------+ - | 3 | :attr:`tm_hour` | range [0, 23] | - +-------+-------------------+---------------------------------+ - | 4 | :attr:`tm_min` | range [0, 59] | - +-------+-------------------+---------------------------------+ - | 5 | :attr:`tm_sec` | range [0, 61]; see **(2)** in | - | | | :func:`strftime` description | - +-------+-------------------+---------------------------------+ - | 6 | :attr:`tm_wday` | range [0, 6], Monday is 0 | - +-------+-------------------+---------------------------------+ - | 7 | :attr:`tm_yday` | range [1, 366] | - +-------+-------------------+---------------------------------+ - | 8 | :attr:`tm_isdst` | 0, 1 or -1; see below | - +-------+-------------------+---------------------------------+ - | N/A | :attr:`tm_zone` | abbreviation of timezone name | - +-------+-------------------+---------------------------------+ - | N/A | :attr:`tm_gmtoff` | offset east of UTC in seconds | - +-------+-------------------+---------------------------------+ + .. list-table:: + + * - Index + - Attribute + - Values + + * - 0 + - .. attribute:: tm_year + - (for example, 1993) + + * - 1 + - .. attribute:: tm_mon + - range [1, 12] + + * - 2 + - .. attribute:: tm_day + - range [1, 31] + + * - 3 + - .. attribute:: tm_hour + - range [0, 23] + + * - 4 + - .. attribute:: tm_min + - range [0, 59] + + * - 5 + - .. attribute:: tm_sec + - range [0, 61]; see :ref:`Note (2) ` in :func:`strftime` + + * - 6 + - .. attribute:: tm_wday + - range [0, 6]; Monday is 0 + + * - 7 + - .. attribute:: tm_yday + - range [1, 366] + + * - 8 + - .. attribute:: tm_isdst + - 0, 1 or -1; see below + + * - N/A + - .. attribute:: tm_zone + - abbreviation of timezone name + + * - N/A + - .. attribute:: tm_gmtoff + - offset east of UTC in seconds Note that unlike the C structure, the month value is a range of [1, 12], not [0, 11]. @@ -808,6 +840,15 @@ These constants are used as parameters for :func:`clock_getres` and .. versionadded:: 3.3 +.. data:: CLOCK_MONOTONIC_RAW_APPROX + + Similar to :data:`CLOCK_MONOTONIC_RAW`, but reads a value cached by + the system at context switch and hence has less accuracy. + + .. availability:: macOS >= 10.12. + + .. versionadded:: 3.13 + .. data:: CLOCK_PROCESS_CPUTIME_ID @@ -867,6 +908,15 @@ These constants are used as parameters for :func:`clock_getres` and .. versionadded:: 3.8 +.. data:: CLOCK_UPTIME_RAW_APPROX + + Like :data:`CLOCK_UPTIME_RAW`, but the value is cached by the system + at context switches and therefore has less accuracy. + + .. availability:: macOS >= 10.12. + + .. versionadded:: 3.13 + The following constant is the only parameter that can be sent to :func:`clock_settime`. @@ -912,8 +962,8 @@ Timezone Constants For the above Timezone constants (:data:`altzone`, :data:`daylight`, :data:`timezone`, and :data:`tzname`), the value is determined by the timezone rules in effect at module load time or the last time :func:`tzset` is called and may be incorrect - for times in the past. It is recommended to use the :attr:`tm_gmtoff` and - :attr:`tm_zone` results from :func:`localtime` to obtain timezone information. + for times in the past. It is recommended to use the :attr:`~struct_time.tm_gmtoff` and + :attr:`~struct_time.tm_zone` results from :func:`localtime` to obtain timezone information. .. seealso:: diff --git a/Doc/library/timeit.rst b/Doc/library/timeit.rst index a559e0a2eb3dad..616f8365b80f6c 100644 --- a/Doc/library/timeit.rst +++ b/Doc/library/timeit.rst @@ -86,9 +86,11 @@ The module defines three convenience functions and a public class: .. versionchanged:: 3.7 Default value of *repeat* changed from 3 to 5. + .. function:: default_timer() - The default timer, which is always :func:`time.perf_counter`. + The default timer, which is always time.perf_counter(), returns float seconds. + An alternative, time.perf_counter_ns, returns integer nanoseconds. .. versionchanged:: 3.3 :func:`time.perf_counter` is now the default timer. @@ -124,7 +126,7 @@ The module defines three convenience functions and a public class: Time *number* executions of the main statement. This executes the setup statement once, and then returns the time it takes to execute the main - statement a number of times, measured in seconds as a float. + statement a number of times. The default timer returns seconds as a float. The argument is the number of times through the loop, defaulting to one million. The main statement, the setup statement and the timer function to be used are passed to the constructor. @@ -149,7 +151,7 @@ The module defines three convenience functions and a public class: so that the total time >= 0.2 second, returning the eventual (number of loops, time taken for that number of loops). It calls :meth:`.timeit` with increasing numbers from the sequence 1, 2, 5, - 10, 20, 50, ... until the time taken is at least 0.2 second. + 10, 20, 50, ... until the time taken is at least 0.2 seconds. If *callback* is given and is not ``None``, it will be called after each trial with two arguments: ``callback(number, time_taken)``. @@ -212,36 +214,36 @@ Where the following options are understood: .. program:: timeit -.. cmdoption:: -n N, --number=N +.. option:: -n N, --number=N how many times to execute 'statement' -.. cmdoption:: -r N, --repeat=N +.. option:: -r N, --repeat=N how many times to repeat the timer (default 5) -.. cmdoption:: -s S, --setup=S +.. option:: -s S, --setup=S statement to be executed once initially (default ``pass``) -.. cmdoption:: -p, --process +.. option:: -p, --process measure process time, not wallclock time, using :func:`time.process_time` instead of :func:`time.perf_counter`, which is the default .. versionadded:: 3.3 -.. cmdoption:: -u, --unit=U +.. option:: -u, --unit=U specify a time unit for timer output; can select ``nsec``, ``usec``, ``msec``, or ``sec`` .. versionadded:: 3.5 -.. cmdoption:: -v, --verbose +.. option:: -v, --verbose print raw timing results; repeat for more digits precision -.. cmdoption:: -h, --help +.. option:: -h, --help print a short usage message and exit diff --git a/Doc/library/tkinter.messagebox.rst b/Doc/library/tkinter.messagebox.rst index 56c1d6c132afd2..56090a0a0e424b 100644 --- a/Doc/library/tkinter.messagebox.rst +++ b/Doc/library/tkinter.messagebox.rst @@ -11,7 +11,8 @@ The :mod:`tkinter.messagebox` module provides a template base class as well as a variety of convenience methods for commonly used configurations. The message -boxes are modal and will return a subset of (True, False, OK, None, Yes, No) based on +boxes are modal and will return a subset of (``True``, ``False``, ``None``, +:data:`OK`, :data:`CANCEL`, :data:`YES`, :data:`NO`) based on the user's selection. Common message box styles and layouts include but are not limited to: @@ -19,21 +20,175 @@ limited to: .. class:: Message(master=None, **options) - Create a default information message box. + Create a message window with an application-specified message, an icon + and a set of buttons. + Each of the buttons in the message window is identified by a unique symbolic name (see the *type* options). + + The following options are supported: + + *command* + Specifies the function to invoke when the user closes the dialog. + The name of the button clicked by the user to close the dialog is + passed as argument. + This is only available on macOS. + + *default* + Gives the :ref:`symbolic name ` of the default button + for this message window (:data:`OK`, :data:`CANCEL`, and so on). + If this option is not specified, the first button in the dialog will + be made the default. + + *detail* + Specifies an auxiliary message to the main message given by the + *message* option. + The message detail will be presented beneath the main message and, + where supported by the OS, in a less emphasized font than the main + message. + + *icon* + Specifies an :ref:`icon ` to display. + If this option is not specified, then the :data:`INFO` icon will be + displayed. + + *message* + Specifies the message to display in this message box. + The default value is an empty string. + + *parent* + Makes the specified window the logical parent of the message box. + The message box is displayed on top of its parent window. + + *title* + Specifies a string to display as the title of the message box. + This option is ignored on macOS, where platform guidelines forbid + the use of a title on this kind of dialog. + + *type* + Arranges for a :ref:`predefined set of buttons ` + to be displayed. + + .. method:: show(**options) + + Display a message window and wait for the user to select one of the buttons. Then return the symbolic name of the selected button. + Keyword arguments can override options specified in the constructor. + **Information message box** -.. method:: showinfo(title=None, message=None, **options) +.. function:: showinfo(title=None, message=None, **options) + + Creates and displays an information message box with the specified title + and message. **Warning message boxes** -.. method:: showwarning(title=None, message=None, **options) - showerror(title=None, message=None, **options) +.. function:: showwarning(title=None, message=None, **options) + + Creates and displays a warning message box with the specified title + and message. + +.. function:: showerror(title=None, message=None, **options) + + Creates and displays an error message box with the specified title + and message. **Question message boxes** -.. method:: askquestion(title=None, message=None, **options) - askokcancel(title=None, message=None, **options) - askretrycancel(title=None, message=None, **options) - askyesno(title=None, message=None, **options) - askyesnocancel(title=None, message=None, **options) +.. function:: askquestion(title=None, message=None, *, type=YESNO, **options) + + Ask a question. By default shows buttons :data:`YES` and :data:`NO`. + Returns the symbolic name of the selected button. + +.. function:: askokcancel(title=None, message=None, **options) + + Ask if operation should proceed. Shows buttons :data:`OK` and :data:`CANCEL`. + Returns ``True`` if the answer is ok and ``False`` otherwise. + +.. function:: askretrycancel(title=None, message=None, **options) + + Ask if operation should be retried. Shows buttons :data:`RETRY` and :data:`CANCEL`. + Return ``True`` if the answer is yes and ``False`` otherwise. + +.. function:: askyesno(title=None, message=None, **options) + + Ask a question. Shows buttons :data:`YES` and :data:`NO`. + Returns ``True`` if the answer is yes and ``False`` otherwise. + +.. function:: askyesnocancel(title=None, message=None, **options) + + Ask a question. Shows buttons :data:`YES`, :data:`NO` and :data:`CANCEL`. + Return ``True`` if the answer is yes, ``None`` if cancelled, and ``False`` + otherwise. + + +.. _messagebox-buttons: + +Symbolic names of buttons: + +.. data:: ABORT + :value: 'abort' +.. data:: RETRY + :value: 'retry' +.. data:: IGNORE + :value: 'ignore' +.. data:: OK + :value: 'ok' +.. data:: CANCEL + :value: 'cancel' +.. data:: YES + :value: 'yes' +.. data:: NO + :value: 'no' + +.. _messagebox-types: + +Predefined sets of buttons: + +.. data:: ABORTRETRYIGNORE + :value: 'abortretryignore' + + Displays three buttons whose symbolic names are :data:`ABORT`, + :data:`RETRY` and :data:`IGNORE`. + +.. data:: OK + :value: 'ok' + :noindex: + + Displays one button whose symbolic name is :data:`OK`. + +.. data:: OKCANCEL + :value: 'okcancel' + + Displays two buttons whose symbolic names are :data:`OK` and + :data:`CANCEL`. + +.. data:: RETRYCANCEL + :value: 'retrycancel' + + Displays two buttons whose symbolic names are :data:`RETRY` and + :data:`CANCEL`. + +.. data:: YESNO + :value: 'yesno' + + Displays two buttons whose symbolic names are :data:`YES` and + :data:`NO`. + +.. data:: YESNOCANCEL + :value: 'yesnocancel' + + Displays three buttons whose symbolic names are :data:`YES`, + :data:`NO` and :data:`CANCEL`. + +.. _messagebox-icons: + +Icon images: + +.. data:: ERROR + :value: 'error' +.. data:: INFO + :value: 'info' +.. data:: QUESTION + :value: 'question' +.. data:: WARNING + :value: 'warning' diff --git a/Doc/library/tkinter.rst b/Doc/library/tkinter.rst index 9f6c3e3e862c42..e084d8554c7c09 100644 --- a/Doc/library/tkinter.rst +++ b/Doc/library/tkinter.rst @@ -58,8 +58,8 @@ details that are unchanged. * `Modern Tkinter for Busy Python Developers `_ By Mark Roseman. (ISBN 978-1999149567) - * `Python and Tkinter Programming `_ - By Alan Moore. (ISBN 978-1788835886) + * `Python GUI programming with Tkinter `_ + By Alan D. Moore. (ISBN 978-1788835886) * `Programming Python `_ By Mark Lutz; has excellent coverage of Tkinter. (ISBN 978-0596158101) @@ -232,6 +232,9 @@ The modules that provide Tk support include: Additional modules: +.. module:: _tkinter + :synopsis: A binary module that contains the low-level interface to Tcl/Tk. + :mod:`_tkinter` A binary module that contains the low-level interface to Tcl/Tk. It is automatically imported by the main :mod:`tkinter` module, @@ -348,7 +351,7 @@ Understanding How Tkinter Wraps Tcl/Tk When your application uses Tkinter's classes and methods, internally Tkinter is assembling strings representing Tcl/Tk commands, and executing those -commands in the Tcl interpreter attached to your applicaton's :class:`Tk` +commands in the Tcl interpreter attached to your application's :class:`Tk` instance. Whether it's trying to navigate reference documentation, trying to find @@ -529,24 +532,24 @@ interpreter will fail. A number of special cases exist: - * Tcl/Tk libraries can be built so they are not thread-aware. In this case, - :mod:`tkinter` calls the library from the originating Python thread, even - if this is different than the thread that created the Tcl interpreter. A global - lock ensures only one call occurs at a time. +* Tcl/Tk libraries can be built so they are not thread-aware. In this case, + :mod:`tkinter` calls the library from the originating Python thread, even + if this is different than the thread that created the Tcl interpreter. A global + lock ensures only one call occurs at a time. - * While :mod:`tkinter` allows you to create more than one instance of a :class:`Tk` - object (with its own interpreter), all interpreters that are part of the same - thread share a common event queue, which gets ugly fast. In practice, don't create - more than one instance of :class:`Tk` at a time. Otherwise, it's best to create - them in separate threads and ensure you're running a thread-aware Tcl/Tk build. +* While :mod:`tkinter` allows you to create more than one instance of a :class:`Tk` + object (with its own interpreter), all interpreters that are part of the same + thread share a common event queue, which gets ugly fast. In practice, don't create + more than one instance of :class:`Tk` at a time. Otherwise, it's best to create + them in separate threads and ensure you're running a thread-aware Tcl/Tk build. - * Blocking event handlers are not the only way to prevent the Tcl interpreter from - reentering the event loop. It is even possible to run multiple nested event loops - or abandon the event loop entirely. If you're doing anything tricky when it comes - to events or threads, be aware of these possibilities. +* Blocking event handlers are not the only way to prevent the Tcl interpreter from + reentering the event loop. It is even possible to run multiple nested event loops + or abandon the event loop entirely. If you're doing anything tricky when it comes + to events or threads, be aware of these possibilities. - * There are a few select :mod:`tkinter` functions that presently work only when - called from the thread that created the Tcl interpreter. +* There are a few select :mod:`tkinter` functions that presently work only when + called from the thread that created the Tcl interpreter. Handy Reference diff --git a/Doc/library/tkinter.ttk.rst b/Doc/library/tkinter.ttk.rst index 9f2f9eb858afd4..1609dc2ce9218e 100644 --- a/Doc/library/tkinter.ttk.rst +++ b/Doc/library/tkinter.ttk.rst @@ -104,33 +104,33 @@ Standard Options All the :mod:`ttk` Widgets accept the following options: - .. tabularcolumns:: |l|L| - - +-----------+--------------------------------------------------------------+ - | Option | Description | - +===========+==============================================================+ - | class | Specifies the window class. The class is used when querying | - | | the option database for the window's other options, to | - | | determine the default bindtags for the window, and to select | - | | the widget's default layout and style. This option is | - | | read-only, and may only be specified when the window is | - | | created. | - +-----------+--------------------------------------------------------------+ - | cursor | Specifies the mouse cursor to be used for the widget. If set | - | | to the empty string (the default), the cursor is inherited | - | | for the parent widget. | - +-----------+--------------------------------------------------------------+ - | takefocus | Determines whether the window accepts the focus during | - | | keyboard traversal. 0, 1 or an empty string is returned. | - | | If 0 is returned, it means that the window should be skipped | - | | entirely during keyboard traversal. If 1, it means that the | - | | window should receive the input focus as long as it is | - | | viewable. And an empty string means that the traversal | - | | scripts make the decision about whether or not to focus | - | | on the window. | - +-----------+--------------------------------------------------------------+ - | style | May be used to specify a custom widget style. | - +-----------+--------------------------------------------------------------+ +.. tabularcolumns:: |l|L| + ++-----------+--------------------------------------------------------------+ +| Option | Description | ++===========+==============================================================+ +| class | Specifies the window class. The class is used when querying | +| | the option database for the window's other options, to | +| | determine the default bindtags for the window, and to select | +| | the widget's default layout and style. This option is | +| | read-only, and may only be specified when the window is | +| | created. | ++-----------+--------------------------------------------------------------+ +| cursor | Specifies the mouse cursor to be used for the widget. If set | +| | to the empty string (the default), the cursor is inherited | +| | for the parent widget. | ++-----------+--------------------------------------------------------------+ +| takefocus | Determines whether the window accepts the focus during | +| | keyboard traversal. 0, 1 or an empty string is returned. | +| | If 0 is returned, it means that the window should be skipped | +| | entirely during keyboard traversal. If 1, it means that the | +| | window should receive the input focus as long as it is | +| | viewable. And an empty string means that the traversal | +| | scripts make the decision about whether or not to focus | +| | on the window. | ++-----------+--------------------------------------------------------------+ +| style | May be used to specify a custom widget style. | ++-----------+--------------------------------------------------------------+ Scrollable Widget Options @@ -139,24 +139,24 @@ Scrollable Widget Options The following options are supported by widgets that are controlled by a scrollbar. - .. tabularcolumns:: |l|L| - - +----------------+---------------------------------------------------------+ - | Option | Description | - +================+=========================================================+ - | xscrollcommand | Used to communicate with horizontal scrollbars. | - | | | - | | When the view in the widget's window change, the widget | - | | will generate a Tcl command based on the scrollcommand. | - | | | - | | Usually this option consists of the method | - | | :meth:`Scrollbar.set` of some scrollbar. This will cause| - | | the scrollbar to be updated whenever the view in the | - | | window changes. | - +----------------+---------------------------------------------------------+ - | yscrollcommand | Used to communicate with vertical scrollbars. | - | | For some more information, see above. | - +----------------+---------------------------------------------------------+ +.. tabularcolumns:: |l|L| + ++----------------+---------------------------------------------------------+ +| Option | Description | ++================+=========================================================+ +| xscrollcommand | Used to communicate with horizontal scrollbars. | +| | | +| | When the view in the widget's window change, the widget | +| | will generate a Tcl command based on the scrollcommand. | +| | | +| | Usually this option consists of the method | +| | :meth:`Scrollbar.set` of some scrollbar. This will cause| +| | the scrollbar to be updated whenever the view in the | +| | window changes. | ++----------------+---------------------------------------------------------+ +| yscrollcommand | Used to communicate with vertical scrollbars. | +| | For some more information, see above. | ++----------------+---------------------------------------------------------+ Label Options @@ -165,93 +165,93 @@ Label Options The following options are supported by labels, buttons and other button-like widgets. - .. tabularcolumns:: |l|p{0.7\linewidth}| - - +--------------+-----------------------------------------------------------+ - | Option | Description | - +==============+===========================================================+ - | text | Specifies a text string to be displayed inside the widget.| - +--------------+-----------------------------------------------------------+ - | textvariable | Specifies a name whose value will be used in place of the | - | | text option resource. | - +--------------+-----------------------------------------------------------+ - | underline | If set, specifies the index (0-based) of a character to | - | | underline in the text string. The underline character is | - | | used for mnemonic activation. | - +--------------+-----------------------------------------------------------+ - | image | Specifies an image to display. This is a list of 1 or more| - | | elements. The first element is the default image name. The| - | | rest of the list if a sequence of statespec/value pairs as| - | | defined by :meth:`Style.map`, specifying different images | - | | to use when the widget is in a particular state or a | - | | combination of states. All images in the list should have | - | | the same size. | - +--------------+-----------------------------------------------------------+ - | compound | Specifies how to display the image relative to the text, | - | | in the case both text and images options are present. | - | | Valid values are: | - | | | - | | * text: display text only | - | | * image: display image only | - | | * top, bottom, left, right: display image above, below, | - | | left of, or right of the text, respectively. | - | | * none: the default. display the image if present, | - | | otherwise the text. | - +--------------+-----------------------------------------------------------+ - | width | If greater than zero, specifies how much space, in | - | | character widths, to allocate for the text label, if less | - | | than zero, specifies a minimum width. If zero or | - | | unspecified, the natural width of the text label is used. | - +--------------+-----------------------------------------------------------+ +.. tabularcolumns:: |l|p{0.7\linewidth}| + ++--------------+-----------------------------------------------------------+ +| Option | Description | ++==============+===========================================================+ +| text | Specifies a text string to be displayed inside the widget.| ++--------------+-----------------------------------------------------------+ +| textvariable | Specifies a name whose value will be used in place of the | +| | text option resource. | ++--------------+-----------------------------------------------------------+ +| underline | If set, specifies the index (0-based) of a character to | +| | underline in the text string. The underline character is | +| | used for mnemonic activation. | ++--------------+-----------------------------------------------------------+ +| image | Specifies an image to display. This is a list of 1 or more| +| | elements. The first element is the default image name. The| +| | rest of the list if a sequence of statespec/value pairs as| +| | defined by :meth:`Style.map`, specifying different images | +| | to use when the widget is in a particular state or a | +| | combination of states. All images in the list should have | +| | the same size. | ++--------------+-----------------------------------------------------------+ +| compound | Specifies how to display the image relative to the text, | +| | in the case both text and images options are present. | +| | Valid values are: | +| | | +| | * text: display text only | +| | * image: display image only | +| | * top, bottom, left, right: display image above, below, | +| | left of, or right of the text, respectively. | +| | * none: the default. display the image if present, | +| | otherwise the text. | ++--------------+-----------------------------------------------------------+ +| width | If greater than zero, specifies how much space, in | +| | character widths, to allocate for the text label, if less | +| | than zero, specifies a minimum width. If zero or | +| | unspecified, the natural width of the text label is used. | ++--------------+-----------------------------------------------------------+ Compatibility Options ^^^^^^^^^^^^^^^^^^^^^ - .. tabularcolumns:: |l|L| +.. tabularcolumns:: |l|L| - +--------+----------------------------------------------------------------+ - | Option | Description | - +========+================================================================+ - | state | May be set to "normal" or "disabled" to control the "disabled" | - | | state bit. This is a write-only option: setting it changes the | - | | widget state, but the :meth:`Widget.state` method does not | - | | affect this option. | - +--------+----------------------------------------------------------------+ ++--------+----------------------------------------------------------------+ +| Option | Description | ++========+================================================================+ +| state | May be set to "normal" or "disabled" to control the "disabled" | +| | state bit. This is a write-only option: setting it changes the | +| | widget state, but the :meth:`Widget.state` method does not | +| | affect this option. | ++--------+----------------------------------------------------------------+ Widget States ^^^^^^^^^^^^^ The widget state is a bitmap of independent state flags. - .. tabularcolumns:: |l|L| - - +------------+-------------------------------------------------------------+ - | Flag | Description | - +============+=============================================================+ - | active | The mouse cursor is over the widget and pressing a mouse | - | | button will cause some action to occur | - +------------+-------------------------------------------------------------+ - | disabled | Widget is disabled under program control | - +------------+-------------------------------------------------------------+ - | focus | Widget has keyboard focus | - +------------+-------------------------------------------------------------+ - | pressed | Widget is being pressed | - +------------+-------------------------------------------------------------+ - | selected | "On", "true", or "current" for things like Checkbuttons and | - | | radiobuttons | - +------------+-------------------------------------------------------------+ - | background | Windows and Mac have a notion of an "active" or foreground | - | | window. The *background* state is set for widgets in a | - | | background window, and cleared for those in the foreground | - | | window | - +------------+-------------------------------------------------------------+ - | readonly | Widget should not allow user modification | - +------------+-------------------------------------------------------------+ - | alternate | A widget-specific alternate display format | - +------------+-------------------------------------------------------------+ - | invalid | The widget's value is invalid | - +------------+-------------------------------------------------------------+ +.. tabularcolumns:: |l|L| + ++------------+-------------------------------------------------------------+ +| Flag | Description | ++============+=============================================================+ +| active | The mouse cursor is over the widget and pressing a mouse | +| | button will cause some action to occur | ++------------+-------------------------------------------------------------+ +| disabled | Widget is disabled under program control | ++------------+-------------------------------------------------------------+ +| focus | Widget has keyboard focus | ++------------+-------------------------------------------------------------+ +| pressed | Widget is being pressed | ++------------+-------------------------------------------------------------+ +| selected | "On", "true", or "current" for things like Checkbuttons and | +| | radiobuttons | ++------------+-------------------------------------------------------------+ +| background | Windows and Mac have a notion of an "active" or foreground | +| | window. The *background* state is set for widgets in a | +| | background window, and cleared for those in the foreground | +| | window | ++------------+-------------------------------------------------------------+ +| readonly | Widget should not allow user modification | ++------------+-------------------------------------------------------------+ +| alternate | A widget-specific alternate display format | ++------------+-------------------------------------------------------------+ +| invalid | The widget's value is invalid | ++------------+-------------------------------------------------------------+ A state specification is a sequence of state names, optionally prefixed with an exclamation point indicating that the bit is off. @@ -311,43 +311,43 @@ Options This widget accepts the following specific options: - .. tabularcolumns:: |l|L| - - +-----------------+--------------------------------------------------------+ - | Option | Description | - +=================+========================================================+ - | exportselection | Boolean value. If set, the widget selection is linked | - | | to the Window Manager selection (which can be returned | - | | by invoking Misc.selection_get, for example). | - +-----------------+--------------------------------------------------------+ - | justify | Specifies how the text is aligned within the widget. | - | | One of "left", "center", or "right". | - +-----------------+--------------------------------------------------------+ - | height | Specifies the height of the pop-down listbox, in rows. | - +-----------------+--------------------------------------------------------+ - | postcommand | A script (possibly registered with Misc.register) that | - | | is called immediately before displaying the values. It | - | | may specify which values to display. | - +-----------------+--------------------------------------------------------+ - | state | One of "normal", "readonly", or "disabled". In the | - | | "readonly" state, the value may not be edited directly,| - | | and the user can only selection of the values from the | - | | dropdown list. In the "normal" state, the text field is| - | | directly editable. In the "disabled" state, no | - | | interaction is possible. | - +-----------------+--------------------------------------------------------+ - | textvariable | Specifies a name whose value is linked to the widget | - | | value. Whenever the value associated with that name | - | | changes, the widget value is updated, and vice versa. | - | | See :class:`tkinter.StringVar`. | - +-----------------+--------------------------------------------------------+ - | values | Specifies the list of values to display in the | - | | drop-down listbox. | - +-----------------+--------------------------------------------------------+ - | width | Specifies an integer value indicating the desired width| - | | of the entry window, in average-size characters of the | - | | widget's font. | - +-----------------+--------------------------------------------------------+ +.. tabularcolumns:: |l|L| + ++-----------------+--------------------------------------------------------+ +| Option | Description | ++=================+========================================================+ +| exportselection | Boolean value. If set, the widget selection is linked | +| | to the Window Manager selection (which can be returned | +| | by invoking Misc.selection_get, for example). | ++-----------------+--------------------------------------------------------+ +| justify | Specifies how the text is aligned within the widget. | +| | One of "left", "center", or "right". | ++-----------------+--------------------------------------------------------+ +| height | Specifies the height of the pop-down listbox, in rows. | ++-----------------+--------------------------------------------------------+ +| postcommand | A script (possibly registered with Misc.register) that | +| | is called immediately before displaying the values. It | +| | may specify which values to display. | ++-----------------+--------------------------------------------------------+ +| state | One of "normal", "readonly", or "disabled". In the | +| | "readonly" state, the value may not be edited directly,| +| | and the user can only selection of the values from the | +| | dropdown list. In the "normal" state, the text field is| +| | directly editable. In the "disabled" state, no | +| | interaction is possible. | ++-----------------+--------------------------------------------------------+ +| textvariable | Specifies a name whose value is linked to the widget | +| | value. Whenever the value associated with that name | +| | changes, the widget value is updated, and vice versa. | +| | See :class:`tkinter.StringVar`. | ++-----------------+--------------------------------------------------------+ +| values | Specifies the list of values to display in the | +| | drop-down listbox. | ++-----------------+--------------------------------------------------------+ +| width | Specifies an integer value indicating the desired width| +| | of the entry window, in average-size characters of the | +| | widget's font. | ++-----------------+--------------------------------------------------------+ Virtual events @@ -397,7 +397,7 @@ Options This widget accepts the following specific options: - .. tabularcolumns:: |l|L| +.. tabularcolumns:: |l|L| +----------------------+------------------------------------------------------+ | Option | Description | @@ -473,25 +473,25 @@ Options This widget accepts the following specific options: - .. tabularcolumns:: |l|L| - - +---------+----------------------------------------------------------------+ - | Option | Description | - +=========+================================================================+ - | height | If present and greater than zero, specifies the desired height | - | | of the pane area (not including internal padding or tabs). | - | | Otherwise, the maximum height of all panes is used. | - +---------+----------------------------------------------------------------+ - | padding | Specifies the amount of extra space to add around the outside | - | | of the notebook. The padding is a list up to four length | - | | specifications left top right bottom. If fewer than four | - | | elements are specified, bottom defaults to top, right defaults | - | | to left, and top defaults to left. | - +---------+----------------------------------------------------------------+ - | width | If present and greater than zero, specified the desired width | - | | of the pane area (not including internal padding). Otherwise, | - | | the maximum width of all panes is used. | - +---------+----------------------------------------------------------------+ +.. tabularcolumns:: |l|L| + ++---------+----------------------------------------------------------------+ +| Option | Description | ++=========+================================================================+ +| height | If present and greater than zero, specifies the desired height | +| | of the pane area (not including internal padding or tabs). | +| | Otherwise, the maximum height of all panes is used. | ++---------+----------------------------------------------------------------+ +| padding | Specifies the amount of extra space to add around the outside | +| | of the notebook. The padding is a list up to four length | +| | specifications left top right bottom. If fewer than four | +| | elements are specified, bottom defaults to top, right defaults | +| | to left, and top defaults to left. | ++---------+----------------------------------------------------------------+ +| width | If present and greater than zero, specified the desired width | +| | of the pane area (not including internal padding). Otherwise, | +| | the maximum width of all panes is used. | ++---------+----------------------------------------------------------------+ Tab Options @@ -499,39 +499,39 @@ Tab Options There are also specific options for tabs: - .. tabularcolumns:: |l|L| - - +-----------+--------------------------------------------------------------+ - | Option | Description | - +===========+==============================================================+ - | state | Either "normal", "disabled" or "hidden". If "disabled", then | - | | the tab is not selectable. If "hidden", then the tab is not | - | | shown. | - +-----------+--------------------------------------------------------------+ - | sticky | Specifies how the child window is positioned within the pane | - | | area. Value is a string containing zero or more of the | - | | characters "n", "s", "e" or "w". Each letter refers to a | - | | side (north, south, east or west) that the child window will | - | | stick to, as per the :meth:`grid` geometry manager. | - +-----------+--------------------------------------------------------------+ - | padding | Specifies the amount of extra space to add between the | - | | notebook and this pane. Syntax is the same as for the option | - | | padding used by this widget. | - +-----------+--------------------------------------------------------------+ - | text | Specifies a text to be displayed in the tab. | - +-----------+--------------------------------------------------------------+ - | image | Specifies an image to display in the tab. See the option | - | | image described in :class:`Widget`. | - +-----------+--------------------------------------------------------------+ - | compound | Specifies how to display the image relative to the text, in | - | | the case both options text and image are present. See | - | | `Label Options`_ for legal values. | - +-----------+--------------------------------------------------------------+ - | underline | Specifies the index (0-based) of a character to underline in | - | | the text string. The underlined character is used for | - | | mnemonic activation if :meth:`Notebook.enable_traversal` is | - | | called. | - +-----------+--------------------------------------------------------------+ +.. tabularcolumns:: |l|L| + ++-----------+--------------------------------------------------------------+ +| Option | Description | ++===========+==============================================================+ +| state | Either "normal", "disabled" or "hidden". If "disabled", then | +| | the tab is not selectable. If "hidden", then the tab is not | +| | shown. | ++-----------+--------------------------------------------------------------+ +| sticky | Specifies how the child window is positioned within the pane | +| | area. Value is a string containing zero or more of the | +| | characters "n", "s", "e" or "w". Each letter refers to a | +| | side (north, south, east or west) that the child window will | +| | stick to, as per the :meth:`grid` geometry manager. | ++-----------+--------------------------------------------------------------+ +| padding | Specifies the amount of extra space to add between the | +| | notebook and this pane. Syntax is the same as for the option | +| | padding used by this widget. | ++-----------+--------------------------------------------------------------+ +| text | Specifies a text to be displayed in the tab. | ++-----------+--------------------------------------------------------------+ +| image | Specifies an image to display in the tab. See the option | +| | image described in :class:`Widget`. | ++-----------+--------------------------------------------------------------+ +| compound | Specifies how to display the image relative to the text, in | +| | the case both options text and image are present. See | +| | `Label Options`_ for legal values. | ++-----------+--------------------------------------------------------------+ +| underline | Specifies the index (0-based) of a character to underline in | +| | the text string. The underlined character is used for | +| | mnemonic activation if :meth:`Notebook.enable_traversal` is | +| | called. | ++-----------+--------------------------------------------------------------+ Tab Identifiers @@ -663,36 +663,36 @@ Options This widget accepts the following specific options: - .. tabularcolumns:: |l|L| - - +----------+---------------------------------------------------------------+ - | Option | Description | - +==========+===============================================================+ - | orient | One of "horizontal" or "vertical". Specifies the orientation | - | | of the progress bar. | - +----------+---------------------------------------------------------------+ - | length | Specifies the length of the long axis of the progress bar | - | | (width if horizontal, height if vertical). | - +----------+---------------------------------------------------------------+ - | mode | One of "determinate" or "indeterminate". | - +----------+---------------------------------------------------------------+ - | maximum | A number specifying the maximum value. Defaults to 100. | - +----------+---------------------------------------------------------------+ - | value | The current value of the progress bar. In "determinate" mode, | - | | this represents the amount of work completed. In | - | | "indeterminate" mode, it is interpreted as modulo *maximum*; | - | | that is, the progress bar completes one "cycle" when its value| - | | increases by *maximum*. | - +----------+---------------------------------------------------------------+ - | variable | A name which is linked to the option value. If specified, the | - | | value of the progress bar is automatically set to the value of| - | | this name whenever the latter is modified. | - +----------+---------------------------------------------------------------+ - | phase | Read-only option. The widget periodically increments the value| - | | of this option whenever its value is greater than 0 and, in | - | | determinate mode, less than maximum. This option may be used | - | | by the current theme to provide additional animation effects. | - +----------+---------------------------------------------------------------+ +.. tabularcolumns:: |l|L| + ++----------+---------------------------------------------------------------+ +| Option | Description | ++==========+===============================================================+ +| orient | One of "horizontal" or "vertical". Specifies the orientation | +| | of the progress bar. | ++----------+---------------------------------------------------------------+ +| length | Specifies the length of the long axis of the progress bar | +| | (width if horizontal, height if vertical). | ++----------+---------------------------------------------------------------+ +| mode | One of "determinate" or "indeterminate". | ++----------+---------------------------------------------------------------+ +| maximum | A number specifying the maximum value. Defaults to 100. | ++----------+---------------------------------------------------------------+ +| value | The current value of the progress bar. In "determinate" mode, | +| | this represents the amount of work completed. In | +| | "indeterminate" mode, it is interpreted as modulo *maximum*; | +| | that is, the progress bar completes one "cycle" when its value| +| | increases by *maximum*. | ++----------+---------------------------------------------------------------+ +| variable | A name which is linked to the option value. If specified, the | +| | value of the progress bar is automatically set to the value of| +| | this name whenever the latter is modified. | ++----------+---------------------------------------------------------------+ +| phase | Read-only option. The widget periodically increments the value| +| | of this option whenever its value is greater than 0 and, in | +| | determinate mode, less than maximum. This option may be used | +| | by the current theme to provide additional animation effects. | ++----------+---------------------------------------------------------------+ ttk.Progressbar @@ -734,14 +734,14 @@ Options This widget accepts the following specific option: - .. tabularcolumns:: |l|L| +.. tabularcolumns:: |l|L| - +--------+----------------------------------------------------------------+ - | Option | Description | - +========+================================================================+ - | orient | One of "horizontal" or "vertical". Specifies the orientation of| - | | the separator. | - +--------+----------------------------------------------------------------+ ++--------+----------------------------------------------------------------+ +| Option | Description | ++========+================================================================+ +| orient | One of "horizontal" or "vertical". Specifies the orientation of| +| | the separator. | ++--------+----------------------------------------------------------------+ Sizegrip @@ -802,49 +802,49 @@ Options This widget accepts the following specific options: - .. tabularcolumns:: |l|p{0.7\linewidth}| - - +----------------+--------------------------------------------------------+ - | Option | Description | - +================+========================================================+ - | columns | A list of column identifiers, specifying the number of | - | | columns and their names. | - +----------------+--------------------------------------------------------+ - | displaycolumns | A list of column identifiers (either symbolic or | - | | integer indices) specifying which data columns are | - | | displayed and the order in which they appear, or the | - | | string "#all". | - +----------------+--------------------------------------------------------+ - | height | Specifies the number of rows which should be visible. | - | | Note: the requested width is determined from the sum | - | | of the column widths. | - +----------------+--------------------------------------------------------+ - | padding | Specifies the internal padding for the widget. The | - | | padding is a list of up to four length specifications. | - +----------------+--------------------------------------------------------+ - | selectmode | Controls how the built-in class bindings manage the | - | | selection. One of "extended", "browse" or "none". | - | | If set to "extended" (the default), multiple items may | - | | be selected. If "browse", only a single item will be | - | | selected at a time. If "none", the selection will not | - | | be changed. | - | | | - | | Note that the application code and tag bindings can set| - | | the selection however they wish, regardless of the | - | | value of this option. | - +----------------+--------------------------------------------------------+ - | show | A list containing zero or more of the following values,| - | | specifying which elements of the tree to display. | - | | | - | | * tree: display tree labels in column #0. | - | | * headings: display the heading row. | - | | | - | | The default is "tree headings", i.e., show all | - | | elements. | - | | | - | | **Note**: Column #0 always refers to the tree column, | - | | even if show="tree" is not specified. | - +----------------+--------------------------------------------------------+ +.. tabularcolumns:: |l|p{0.7\linewidth}| + ++----------------+--------------------------------------------------------+ +| Option | Description | ++================+========================================================+ +| columns | A list of column identifiers, specifying the number of | +| | columns and their names. | ++----------------+--------------------------------------------------------+ +| displaycolumns | A list of column identifiers (either symbolic or | +| | integer indices) specifying which data columns are | +| | displayed and the order in which they appear, or the | +| | string "#all". | ++----------------+--------------------------------------------------------+ +| height | Specifies the number of rows which should be visible. | +| | Note: the requested width is determined from the sum | +| | of the column widths. | ++----------------+--------------------------------------------------------+ +| padding | Specifies the internal padding for the widget. The | +| | padding is a list of up to four length specifications. | ++----------------+--------------------------------------------------------+ +| selectmode | Controls how the built-in class bindings manage the | +| | selection. One of "extended", "browse" or "none". | +| | If set to "extended" (the default), multiple items may | +| | be selected. If "browse", only a single item will be | +| | selected at a time. If "none", the selection will not | +| | be changed. | +| | | +| | Note that the application code and tag bindings can set| +| | the selection however they wish, regardless of the | +| | value of this option. | ++----------------+--------------------------------------------------------+ +| show | A list containing zero or more of the following values,| +| | specifying which elements of the tree to display. | +| | | +| | * tree: display tree labels in column #0. | +| | * headings: display the heading row. | +| | | +| | The default is "tree headings", i.e., show all | +| | elements. | +| | | +| | **Note**: Column #0 always refers to the tree column, | +| | even if show="tree" is not specified. | ++----------------+--------------------------------------------------------+ Item Options @@ -853,27 +853,27 @@ Item Options The following item options may be specified for items in the insert and item widget commands. - .. tabularcolumns:: |l|L| - - +--------+---------------------------------------------------------------+ - | Option | Description | - +========+===============================================================+ - | text | The textual label to display for the item. | - +--------+---------------------------------------------------------------+ - | image | A Tk Image, displayed to the left of the label. | - +--------+---------------------------------------------------------------+ - | values | The list of values associated with the item. | - | | | - | | Each item should have the same number of values as the widget | - | | option columns. If there are fewer values than columns, the | - | | remaining values are assumed empty. If there are more values | - | | than columns, the extra values are ignored. | - +--------+---------------------------------------------------------------+ - | open | ``True``/``False`` value indicating whether the item's | - | | children should be displayed or hidden. | - +--------+---------------------------------------------------------------+ - | tags | A list of tags associated with this item. | - +--------+---------------------------------------------------------------+ +.. tabularcolumns:: |l|L| + ++--------+---------------------------------------------------------------+ +| Option | Description | ++========+===============================================================+ +| text | The textual label to display for the item. | ++--------+---------------------------------------------------------------+ +| image | A Tk Image, displayed to the left of the label. | ++--------+---------------------------------------------------------------+ +| values | The list of values associated with the item. | +| | | +| | Each item should have the same number of values as the widget | +| | option columns. If there are fewer values than columns, the | +| | remaining values are assumed empty. If there are more values | +| | than columns, the extra values are ignored. | ++--------+---------------------------------------------------------------+ +| open | ``True``/``False`` value indicating whether the item's | +| | children should be displayed or hidden. | ++--------+---------------------------------------------------------------+ +| tags | A list of tags associated with this item. | ++--------+---------------------------------------------------------------+ Tag Options @@ -881,20 +881,20 @@ Tag Options The following options may be specified on tags: - .. tabularcolumns:: |l|L| +.. tabularcolumns:: |l|L| - +------------+-----------------------------------------------------------+ - | Option | Description | - +============+===========================================================+ - | foreground | Specifies the text foreground color. | - +------------+-----------------------------------------------------------+ - | background | Specifies the cell or item background color. | - +------------+-----------------------------------------------------------+ - | font | Specifies the font to use when drawing text. | - +------------+-----------------------------------------------------------+ - | image | Specifies the item image, in case the item's image option | - | | is empty. | - +------------+-----------------------------------------------------------+ ++------------+-----------------------------------------------------------+ +| Option | Description | ++============+===========================================================+ +| foreground | Specifies the text foreground color. | ++------------+-----------------------------------------------------------+ +| background | Specifies the cell or item background color. | ++------------+-----------------------------------------------------------+ +| font | Specifies the font to use when drawing text. | ++------------+-----------------------------------------------------------+ +| image | Specifies the item image, in case the item's image option | +| | is empty. | ++------------+-----------------------------------------------------------+ Column Identifiers @@ -926,19 +926,19 @@ Virtual Events The Treeview widget generates the following virtual events. - .. tabularcolumns:: |l|L| +.. tabularcolumns:: |l|L| - +--------------------+--------------------------------------------------+ - | Event | Description | - +====================+==================================================+ - | <> | Generated whenever the selection changes. | - +--------------------+--------------------------------------------------+ - | <> | Generated just before settings the focus item to | - | | open=True. | - +--------------------+--------------------------------------------------+ - | <> | Generated just after setting the focus item to | - | | open=False. | - +--------------------+--------------------------------------------------+ ++--------------------+--------------------------------------------------+ +| Event | Description | ++====================+==================================================+ +| <> | Generated whenever the selection changes. | ++--------------------+--------------------------------------------------+ +| <> | Generated just before settings the focus item to | +| | open=True. | ++--------------------+--------------------------------------------------+ +| <> | Generated just after setting the focus item to | +| | open=False. | ++--------------------+--------------------------------------------------+ The :meth:`Treeview.focus` and :meth:`Treeview.selection` methods can be used to determine the affected item or items. @@ -986,19 +986,19 @@ ttk.Treeview The valid options/values are: - * id + *id* Returns the column name. This is a read-only option. - * anchor: One of the standard Tk anchor values. + *anchor*: One of the standard Tk anchor values. Specifies how the text in this column should be aligned with respect to the cell. - * minwidth: width + *minwidth*: width The minimum width of the column in pixels. The treeview widget will not make the column any smaller than specified by this option when the widget is resized or the user drags a column. - * stretch: ``True``/``False`` + *stretch*: ``True``/``False`` Specifies whether the column's width should be adjusted when the widget is resized. - * width: width + *width*: width The width of the column in pixels. To configure the tree column, call this with column = "#0" @@ -1041,14 +1041,14 @@ ttk.Treeview The valid options/values are: - * text: text + *text*: text The text to display in the column heading. - * image: imageName + *image*: imageName Specifies an image to display to the right of the column heading. - * anchor: anchor + *anchor*: anchor Specifies how the heading text should be aligned. One of the standard Tk anchor values. - * command: callback + *command*: callback A callback to be invoked when the heading label is pressed. To configure the tree column heading, call this with column = "#0". @@ -1391,32 +1391,42 @@ option. If you don't know the class name of a widget, use the method .. method:: element_create(elementname, etype, *args, **kw) Create a new element in the current theme, of the given *etype* which is - expected to be either "image", "from" or "vsapi". The latter is only - available in Tk 8.6a for Windows XP and Vista and is not described here. + expected to be either "image", "from" or "vsapi". + The latter is only available in Tk 8.6 on Windows. If "image" is used, *args* should contain the default image name followed by statespec/value pairs (this is the imagespec), and *kw* may have the following options: - * border=padding - padding is a list of up to four integers, specifying the left, top, - right, and bottom borders, respectively. + border=padding + padding is a list of up to four integers, specifying the left, top, + right, and bottom borders, respectively. - * height=height - Specifies a minimum height for the element. If less than zero, the - base image's height is used as a default. + height=height + Specifies a minimum height for the element. If less than zero, the + base image's height is used as a default. - * padding=padding - Specifies the element's interior padding. Defaults to border's value - if not specified. + padding=padding + Specifies the element's interior padding. Defaults to border's value + if not specified. - * sticky=spec - Specifies how the image is placed within the final parcel. spec - contains zero or more characters "n", "s", "w", or "e". + sticky=spec + Specifies how the image is placed within the final parcel. spec + contains zero or more characters "n", "s", "w", or "e". - * width=width - Specifies a minimum width for the element. If less than zero, the - base image's width is used as a default. + width=width + Specifies a minimum width for the element. If less than zero, the + base image's width is used as a default. + + Example:: + + img1 = tkinter.PhotoImage(master=root, file='button.png') + img1 = tkinter.PhotoImage(master=root, file='button-pressed.png') + img1 = tkinter.PhotoImage(master=root, file='button-active.png') + style = ttk.Style(root) + style.element_create('Button.button', 'image', + img1, ('pressed', img2), ('active', img3), + border=(2, 4), sticky='we') If "from" is used as the value of *etype*, :meth:`element_create` will clone an existing @@ -1425,6 +1435,68 @@ option. If you don't know the class name of a widget, use the method If this element to clone from is not specified, an empty element will be used. *kw* is discarded. + Example:: + + style = ttk.Style(root) + style.element_create('plain.background', 'from', 'default') + + If "vsapi" is used as the value of *etype*, :meth:`element_create` + will create a new element in the current theme whose visual appearance + is drawn using the Microsoft Visual Styles API which is responsible + for the themed styles on Windows XP and Vista. + *args* is expected to contain the Visual Styles class and part as + given in the Microsoft documentation followed by an optional sequence + of tuples of ttk states and the corresponding Visual Styles API state + value. + *kw* may have the following options: + + padding=padding + Specify the element's interior padding. + *padding* is a list of up to four integers specifying the left, + top, right and bottom padding quantities respectively. + If fewer than four elements are specified, bottom defaults to top, + right defaults to left, and top defaults to left. + In other words, a list of three numbers specify the left, vertical, + and right padding; a list of two numbers specify the horizontal + and the vertical padding; a single number specifies the same + padding all the way around the widget. + This option may not be mixed with any other options. + + margins=padding + Specifies the elements exterior padding. + *padding* is a list of up to four integers specifying the left, top, + right and bottom padding quantities respectively. + This option may not be mixed with any other options. + + width=width + Specifies the width for the element. + If this option is set then the Visual Styles API will not be queried + for the recommended size or the part. + If this option is set then *height* should also be set. + The *width* and *height* options cannot be mixed with the *padding* + or *margins* options. + + height=height + Specifies the height of the element. + See the comments for *width*. + + Example:: + + style = ttk.Style(root) + style.element_create('pin', 'vsapi', 'EXPLORERBAR', 3, [ + ('pressed', '!selected', 3), + ('active', '!selected', 2), + ('pressed', 'selected', 6), + ('active', 'selected', 5), + ('selected', 4), + ('', 1)]) + style.layout('Explorer.Pin', + [('Explorer.Pin.pin', {'sticky': 'news'})]) + pin = ttk.Checkbutton(style='Explorer.Pin') + pin.pack(expand=True, fill='both') + + .. versionchanged:: 3.13 + Added support of the "vsapi" element factory. .. method:: element_names() @@ -1501,25 +1573,26 @@ Layouts A layout can be just ``None``, if it takes no options, or a dict of options specifying how to arrange the element. The layout mechanism uses a simplified version of the pack geometry manager: given an -initial cavity, each element is allocated a parcel. Valid -options/values are: - - * side: whichside - Specifies which side of the cavity to place the element; one of - top, right, bottom or left. If omitted, the element occupies the - entire cavity. - - * sticky: nswe - Specifies where the element is placed inside its allocated parcel. - - * unit: 0 or 1 - If set to 1, causes the element and all of its descendants to be treated as - a single element for the purposes of :meth:`Widget.identify` et al. It's - used for things like scrollbar thumbs with grips. - - * children: [sublayout... ] - Specifies a list of elements to place inside the element. Each - element is a tuple (or other sequence type) where the first item is - the layout name, and the other is a `Layout`_. +initial cavity, each element is allocated a parcel. + +The valid options/values are: + +*side*: whichside + Specifies which side of the cavity to place the element; one of + top, right, bottom or left. If omitted, the element occupies the + entire cavity. + +*sticky*: nswe + Specifies where the element is placed inside its allocated parcel. + +*unit*: 0 or 1 + If set to 1, causes the element and all of its descendants to be treated as + a single element for the purposes of :meth:`Widget.identify` et al. It's + used for things like scrollbar thumbs with grips. + +*children*: [sublayout... ] + Specifies a list of elements to place inside the element. Each + element is a tuple (or other sequence type) where the first item is + the layout name, and the other is a `Layout`_. .. _Layout: `Layouts`_ diff --git a/Doc/library/tokenize.rst b/Doc/library/tokenize.rst index bffe93006edc7b..92bdb052267a68 100644 --- a/Doc/library/tokenize.rst +++ b/Doc/library/tokenize.rst @@ -166,11 +166,11 @@ The following options are accepted: .. program:: tokenize -.. cmdoption:: -h, --help +.. option:: -h, --help show this help message and exit -.. cmdoption:: -e, --exact +.. option:: -e, --exact display token names using the exact type diff --git a/Doc/library/tomllib.rst b/Doc/library/tomllib.rst index 918576eb37eaee..f9e2dfeb13dc87 100644 --- a/Doc/library/tomllib.rst +++ b/Doc/library/tomllib.rst @@ -95,7 +95,7 @@ Conversion Table +------------------+--------------------------------------------------------------------------------------+ | TOML | Python | +==================+======================================================================================+ -| table | dict | +| TOML document | dict | +------------------+--------------------------------------------------------------------------------------+ | string | str | +------------------+--------------------------------------------------------------------------------------+ @@ -115,3 +115,9 @@ Conversion Table +------------------+--------------------------------------------------------------------------------------+ | array | list | +------------------+--------------------------------------------------------------------------------------+ +| table | dict | ++------------------+--------------------------------------------------------------------------------------+ +| inline table | dict | ++------------------+--------------------------------------------------------------------------------------+ +| array of tables | list of dicts | ++------------------+--------------------------------------------------------------------------------------+ diff --git a/Doc/library/trace.rst b/Doc/library/trace.rst index 40cf198f1287d7..8854905e192b45 100644 --- a/Doc/library/trace.rst +++ b/Doc/library/trace.rst @@ -34,11 +34,11 @@ all Python modules imported during the execution into the current directory. .. program:: trace -.. cmdoption:: --help +.. option:: --help Display usage and exit. -.. cmdoption:: --version +.. option:: --version Display the version of the module and exit. @@ -56,28 +56,28 @@ the :option:`--trace <-t>` and :option:`--count <-c>` options. When .. program:: trace -.. cmdoption:: -c, --count +.. option:: -c, --count Produce a set of annotated listing files upon program completion that shows how many times each statement was executed. See also :option:`--coverdir <-C>`, :option:`--file <-f>` and :option:`--no-report <-R>` below. -.. cmdoption:: -t, --trace +.. option:: -t, --trace Display lines as they are executed. -.. cmdoption:: -l, --listfuncs +.. option:: -l, --listfuncs Display the functions executed by running the program. -.. cmdoption:: -r, --report +.. option:: -r, --report Produce an annotated list from an earlier program run that used the :option:`--count <-c>` and :option:`--file <-f>` option. This does not execute any code. -.. cmdoption:: -T, --trackcalls +.. option:: -T, --trackcalls Display the calling relationships exposed by running the program. @@ -86,33 +86,33 @@ Modifiers .. program:: trace -.. cmdoption:: -f, --file= +.. option:: -f, --file= Name of a file to accumulate counts over several tracing runs. Should be used with the :option:`--count <-c>` option. -.. cmdoption:: -C, --coverdir= +.. option:: -C, --coverdir= Directory where the report files go. The coverage report for ``package.module`` is written to file :file:`{dir}/{package}/{module}.cover`. -.. cmdoption:: -m, --missing +.. option:: -m, --missing When generating annotated listings, mark lines which were not executed with ``>>>>>>``. -.. cmdoption:: -s, --summary +.. option:: -s, --summary When using :option:`--count <-c>` or :option:`--report <-r>`, write a brief summary to stdout for each file processed. -.. cmdoption:: -R, --no-report +.. option:: -R, --no-report Do not generate annotated listings. This is useful if you intend to make several runs with :option:`--count <-c>`, and then produce a single set of annotated listings at the end. -.. cmdoption:: -g, --timing +.. option:: -g, --timing Prefix each line with the time since the program started. Only used while tracing. @@ -124,12 +124,12 @@ These options may be repeated multiple times. .. program:: trace -.. cmdoption:: --ignore-module= +.. option:: --ignore-module= Ignore each of the given module names and its submodules (if it is a package). The argument can be a list of names separated by a comma. -.. cmdoption:: --ignore-dir= +.. option:: --ignore-dir= Ignore all modules and packages in the named directory and subdirectories. The argument can be a list of directories separated by :data:`os.pathsep`. @@ -187,7 +187,8 @@ Programmatic Interface Merge in data from another :class:`CoverageResults` object. - .. method:: write_results(show_missing=True, summary=False, coverdir=None) + .. method:: write_results(show_missing=True, summary=False, coverdir=None,\ + *, ignore_missing_files=False) Write coverage results. Set *show_missing* to show lines that had no hits. Set *summary* to include in the output the coverage summary per @@ -195,6 +196,13 @@ Programmatic Interface result files will be output. If ``None``, the results for each source file are placed in its directory. + If *ignore_missing_files* is ``True``, coverage counts for files that no + longer exist are silently ignored. Otherwise, a missing file will + raise a :exc:`FileNotFoundError`. + + .. versionchanged:: 3.13 + Added *ignore_missing_files* parameter. + A simple example demonstrating the use of the programmatic interface:: import sys diff --git a/Doc/library/traceback.rst b/Doc/library/traceback.rst index 3eb77fc3df5709..ab83e0df10b709 100644 --- a/Doc/library/traceback.rst +++ b/Doc/library/traceback.rst @@ -16,8 +16,10 @@ interpreter. .. index:: pair: object; traceback -The module uses traceback objects --- these are objects of type :class:`types.TracebackType`, -which are assigned to the ``__traceback__`` field of :class:`BaseException` instances. +The module uses :ref:`traceback objects ` --- these are +objects of type :class:`types.TracebackType`, +which are assigned to the :attr:`~BaseException.__traceback__` field of +:class:`BaseException` instances. .. seealso:: @@ -31,11 +33,13 @@ The module defines the following functions: .. function:: print_tb(tb, limit=None, file=None) - Print up to *limit* stack trace entries from traceback object *tb* (starting + Print up to *limit* stack trace entries from + :ref:`traceback object ` *tb* (starting from the caller's frame) if *limit* is positive. Otherwise, print the last ``abs(limit)`` entries. If *limit* is omitted or ``None``, all entries are printed. If *file* is omitted or ``None``, the output goes to - ``sys.stderr``; otherwise it should be an open file or file-like object to + :data:`sys.stderr`; otherwise it should be an open + :term:`file ` or :term:`file-like object` to receive the output. .. versionchanged:: 3.5 @@ -45,7 +49,8 @@ The module defines the following functions: .. function:: print_exception(exc, /[, value, tb], limit=None, \ file=None, chain=True) - Print exception information and stack trace entries from traceback object + Print exception information and stack trace entries from + :ref:`traceback object ` *tb* to *file*. This differs from :func:`print_tb` in the following ways: @@ -66,7 +71,8 @@ The module defines the following functions: The optional *limit* argument has the same meaning as for :func:`print_tb`. If *chain* is true (the default), then chained exceptions (the - :attr:`__cause__` or :attr:`__context__` attributes of the exception) will be + :attr:`~BaseException.__cause__` or :attr:`~BaseException.__context__` + attributes of the exception) will be printed as well, like the interpreter itself does when printing an unhandled exception. @@ -96,7 +102,8 @@ The module defines the following functions: Print up to *limit* stack trace entries (starting from the invocation point) if *limit* is positive. Otherwise, print the last ``abs(limit)`` entries. If *limit* is omitted or ``None``, all entries are printed. - The optional *f* argument can be used to specify an alternate stack frame + The optional *f* argument can be used to specify an alternate + :ref:`stack frame ` to start. The optional *file* argument has the same meaning as for :func:`print_tb`. @@ -107,20 +114,20 @@ The module defines the following functions: .. function:: extract_tb(tb, limit=None) Return a :class:`StackSummary` object representing a list of "pre-processed" - stack trace entries extracted from the traceback object *tb*. It is useful + stack trace entries extracted from the + :ref:`traceback object ` *tb*. It is useful for alternate formatting of stack traces. The optional *limit* argument has the same meaning as for :func:`print_tb`. A "pre-processed" stack trace entry is a :class:`FrameSummary` object containing attributes :attr:`~FrameSummary.filename`, :attr:`~FrameSummary.lineno`, :attr:`~FrameSummary.name`, and :attr:`~FrameSummary.line` representing the - information that is usually printed for a stack trace. The - :attr:`~FrameSummary.line` is a string with leading and trailing - whitespace stripped; if the source is not available it is ``None``. + information that is usually printed for a stack trace. .. function:: extract_stack(f=None, limit=None) - Extract the raw traceback from the current stack frame. The return value has + Extract the raw traceback from the current + :ref:`stack frame `. The return value has the same format as for :func:`extract_tb`. The optional *f* and *limit* arguments have the same meaning as for :func:`print_stack`. @@ -135,24 +142,35 @@ The module defines the following functions: text line is not ``None``. -.. function:: format_exception_only(exc, /[, value]) +.. function:: format_exception_only(exc, /[, value], *, show_group=False) Format the exception part of a traceback using an exception value such as - given by ``sys.last_value``. The return value is a list of strings, each - ending in a newline. Normally, the list contains a single string; however, - for :exc:`SyntaxError` exceptions, it contains several lines that (when - printed) display detailed information about where the syntax error occurred. - The message indicating which exception occurred is the always last string in - the list. + given by :data:`sys.last_value`. The return value is a list of strings, each + ending in a newline. The list contains the exception's message, which is + normally a single string; however, for :exc:`SyntaxError` exceptions, it + contains several lines that (when printed) display detailed information + about where the syntax error occurred. Following the message, the list + contains the exception's :attr:`notes `. Since Python 3.10, instead of passing *value*, an exception object can be passed as the first argument. If *value* is provided, the first argument is ignored in order to provide backwards compatibility. + When *show_group* is ``True``, and the exception is an instance of + :exc:`BaseExceptionGroup`, the nested exceptions are included as + well, recursively, with indentation relative to their nesting depth. + .. versionchanged:: 3.10 The *etype* parameter has been renamed to *exc* and is now positional-only. + .. versionchanged:: 3.11 + The returned list now includes any + :attr:`notes ` attached to the exception. + + .. versionchanged:: 3.13 + *show_group* parameter was added. + .. function:: format_exception(exc, /[, value, tb], limit=None, chain=True) @@ -187,14 +205,17 @@ The module defines the following functions: .. function:: clear_frames(tb) - Clears the local variables of all the stack frames in a traceback *tb* - by calling the :meth:`clear` method of each frame object. + Clears the local variables of all the stack frames in a + :ref:`traceback ` *tb* + by calling the :meth:`~frame.clear` method of each + :ref:`frame object `. .. versionadded:: 3.4 .. function:: walk_stack(f) - Walk a stack following ``f.f_back`` from the given frame, yielding the frame + Walk a stack following :attr:`f.f_back ` from the given frame, + yielding the frame and line number for each frame. If *f* is ``None``, the current stack is used. This helper is used with :meth:`StackSummary.extract`. @@ -202,19 +223,20 @@ The module defines the following functions: .. function:: walk_tb(tb) - Walk a traceback following ``tb_next`` yielding the frame and line number + Walk a traceback following :attr:`~traceback.tb_next` yielding the frame and + line number for each frame. This helper is used with :meth:`StackSummary.extract`. .. versionadded:: 3.5 The module also defines the following classes: -:class:`TracebackException` Objects ------------------------------------ +:class:`!TracebackException` Objects +------------------------------------ .. versionadded:: 3.5 -:class:`TracebackException` objects are created from actual exceptions to +:class:`!TracebackException` objects are created from actual exceptions to capture data for later printing in a lightweight fashion. .. class:: TracebackException(exc_type, exc_value, exc_traceback, *, limit=None, lookup_lines=True, capture_locals=False, compact=False, max_group_width=15, max_group_depth=10) @@ -222,10 +244,11 @@ capture data for later printing in a lightweight fashion. Capture an exception for later rendering. *limit*, *lookup_lines* and *capture_locals* are as for the :class:`StackSummary` class. - If *compact* is true, only data that is required by :class:`TracebackException`'s - ``format`` method is saved in the class attributes. In particular, the - ``__context__`` field is calculated only if ``__cause__`` is ``None`` and - ``__suppress_context__`` is false. + If *compact* is true, only data that is required by + :class:`!TracebackException`'s :meth:`format` method + is saved in the class attributes. In particular, the + :attr:`__context__` field is calculated only if :attr:`__cause__` is + ``None`` and :attr:`__suppress_context__` is false. Note that when locals are captured, they are also shown in the traceback. @@ -235,29 +258,39 @@ capture data for later printing in a lightweight fashion. group's exceptions array. The formatted output is truncated when either limit is exceeded. + .. versionchanged:: 3.10 + Added the *compact* parameter. + + .. versionchanged:: 3.11 + Added the *max_group_width* and *max_group_depth* parameters. + .. attribute:: __cause__ - A :class:`TracebackException` of the original ``__cause__``. + A :class:`!TracebackException` of the original + :attr:`~BaseException.__cause__`. .. attribute:: __context__ - A :class:`TracebackException` of the original ``__context__``. + A :class:`!TracebackException` of the original + :attr:`~BaseException.__context__`. .. attribute:: exceptions If ``self`` represents an :exc:`ExceptionGroup`, this field holds a list of - :class:`TracebackException` instances representing the nested exceptions. + :class:`!TracebackException` instances representing the nested exceptions. Otherwise it is ``None``. .. versionadded:: 3.11 .. attribute:: __suppress_context__ - The ``__suppress_context__`` value from the original exception. + The :attr:`~BaseException.__suppress_context__` value from the original + exception. .. attribute:: __notes__ - The ``__notes__`` value from the original exception, or ``None`` + The :attr:`~BaseException.__notes__` value from the original exception, + or ``None`` if the exception does not have any notes. If it is not ``None`` is it formatted in the traceback after the exception string. @@ -271,6 +304,14 @@ capture data for later printing in a lightweight fashion. The class of the original traceback. + .. deprecated:: 3.13 + + .. attribute:: exc_type_str + + String display of the class of the original exception. + + .. versionadded:: 3.13 + .. attribute:: filename For syntax errors - the file name where the error occurred. @@ -323,64 +364,58 @@ capture data for later printing in a lightweight fashion. Format the exception. - If *chain* is not ``True``, ``__cause__`` and ``__context__`` will not - be formatted. + If *chain* is not ``True``, :attr:`__cause__` and :attr:`__context__` + will not be formatted. The return value is a generator of strings, each ending in a newline and some containing internal newlines. :func:`~traceback.print_exception` is a wrapper around this method which just prints the lines to a file. - The message indicating which exception occurred is always the last - string in the output. - .. method:: format_exception_only(*, show_group=False) Format the exception part of the traceback. The return value is a generator of strings, each ending in a newline. - When *show_group* is ``False``, the generator normally emits a single - string; however, for :exc:`SyntaxError` exceptions, it emits several - lines that (when printed) display detailed information about where - the syntax error occurred. The message indicating which exception - occurred is always the last string in the output. + When *show_group* is ``False``, the generator emits the exception's + message followed by its notes (if it has any). The exception message + is normally a single string; however, for :exc:`SyntaxError` exceptions, + it consists of several lines that (when printed) display detailed + information about where the syntax error occurred. When *show_group* is ``True``, and the exception is an instance of :exc:`BaseExceptionGroup`, the nested exceptions are included as well, recursively, with indentation relative to their nesting depth. + .. versionchanged:: 3.11 + The exception's :attr:`notes ` are now + included in the output. + .. versionchanged:: 3.13 Added the *show_group* parameter. - .. versionchanged:: 3.10 - Added the *compact* parameter. - - .. versionchanged:: 3.11 - Added the *max_group_width* and *max_group_depth* parameters. - - -:class:`StackSummary` Objects ------------------------------ +:class:`!StackSummary` Objects +------------------------------ .. versionadded:: 3.5 -:class:`StackSummary` objects represent a call stack ready for formatting. +:class:`!StackSummary` objects represent a call stack ready for formatting. .. class:: StackSummary .. classmethod:: extract(frame_gen, *, limit=None, lookup_lines=True, capture_locals=False) - Construct a :class:`StackSummary` object from a frame generator (such as + Construct a :class:`!StackSummary` object from a frame generator (such as is returned by :func:`~traceback.walk_stack` or :func:`~traceback.walk_tb`). If *limit* is supplied, only this many frames are taken from *frame_gen*. If *lookup_lines* is ``False``, the returned :class:`FrameSummary` objects will not have read their lines in yet, making the cost of - creating the :class:`StackSummary` cheaper (which may be valuable if it + creating the :class:`!StackSummary` cheaper (which may be valuable if it may not actually get formatted). If *capture_locals* is ``True`` the - local variables in each :class:`FrameSummary` are captured as object + local variables in each :class:`!FrameSummary` are captured as object representations. .. versionchanged:: 3.12 @@ -389,14 +424,16 @@ capture data for later printing in a lightweight fashion. .. classmethod:: from_list(a_list) - Construct a :class:`StackSummary` object from a supplied list of + Construct a :class:`!StackSummary` object from a supplied list of :class:`FrameSummary` objects or old-style list of tuples. Each tuple - should be a 4-tuple with filename, lineno, name, line as the elements. + should be a 4-tuple with *filename*, *lineno*, *name*, *line* as the + elements. .. method:: format() Returns a list of strings ready for printing. Each string in the - resulting list corresponds to a single frame from the stack. + resulting list corresponds to a single :ref:`frame ` from + the stack. Each string ends in a newline; the strings may contain internal newlines as well, for those items with source text lines. @@ -409,7 +446,8 @@ capture data for later printing in a lightweight fashion. .. method:: format_frame_summary(frame_summary) - Returns a string for printing one of the frames involved in the stack. + Returns a string for printing one of the :ref:`frames ` + involved in the stack. This method is called for each :class:`FrameSummary` object to be printed by :meth:`StackSummary.format`. If it returns ``None``, the frame is omitted from the output. @@ -417,25 +455,50 @@ capture data for later printing in a lightweight fashion. .. versionadded:: 3.11 -:class:`FrameSummary` Objects ------------------------------ +:class:`!FrameSummary` Objects +------------------------------ .. versionadded:: 3.5 -A :class:`FrameSummary` object represents a single frame in a traceback. +A :class:`!FrameSummary` object represents a single :ref:`frame ` +in a :ref:`traceback `. .. class:: FrameSummary(filename, lineno, name, lookup_line=True, locals=None, line=None) - Represent a single frame in the traceback or stack that is being formatted - or printed. It may optionally have a stringified version of the frames + Represents a single :ref:`frame ` in the + :ref:`traceback ` or stack that is being formatted + or printed. It may optionally have a stringified version of the frame's locals included in it. If *lookup_line* is ``False``, the source code is not - looked up until the :class:`FrameSummary` has the :attr:`~FrameSummary.line` - attribute accessed (which also happens when casting it to a tuple). + looked up until the :class:`!FrameSummary` has the :attr:`~FrameSummary.line` + attribute accessed (which also happens when casting it to a :class:`tuple`). :attr:`~FrameSummary.line` may be directly provided, and will prevent line lookups happening at all. *locals* is an optional local variable dictionary, and if supplied the variable representations are stored in the summary for later display. + :class:`!FrameSummary` instances have the following attributes: + + .. attribute:: FrameSummary.filename + + The filename of the source code for this frame. Equivalent to accessing + :attr:`f.f_code.co_filename ` on a + :ref:`frame object ` *f*. + + .. attribute:: FrameSummary.lineno + + The line number of the source code for this frame. + + .. attribute:: FrameSummary.name + + Equivalent to accessing :attr:`f.f_code.co_name ` on + a :ref:`frame object ` *f*. + + .. attribute:: FrameSummary.line + + A string representing the source code for this frame, with leading and + trailing whitespace stripped. + If the source is not available, it is ``None``. + .. _traceback-example: Traceback Examples @@ -506,27 +569,32 @@ The output for the example would look similar to this: *** print_tb: File "", line 10, in lumberjack() + ~~~~~~~~~~^^ *** print_exception: Traceback (most recent call last): File "", line 10, in lumberjack() + ~~~~~~~~~~^^ File "", line 4, in lumberjack 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_life() + ~~~~~~~~~~~~~~~~~~~^^ IndexError: tuple index out of range *** format_exc, first and last line: Traceback (most recent call last): IndexError: tuple index out of range *** format_exception: ['Traceback (most recent call last):\n', - ' File "", line 10, in \n lumberjack()\n', - ' File "", line 4, in lumberjack\n bright_side_of_life()\n', + ' File "", line 10, in \n lumberjack()\n ~~~~~~~~~~^^\n', + ' File "", line 4, in lumberjack\n bright_side_of_life()\n ~~~~~~~~~~~~~~~~~~~^^\n', ' File "", line 7, in bright_side_of_life\n return tuple()[0]\n ~~~~~~~^^^\n', 'IndexError: tuple index out of range\n'] *** extract_tb: @@ -534,8 +602,8 @@ The output for the example would look similar to this: , line 4 in lumberjack>, , 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_life()\n', + [' File "", line 10, in \n lumberjack()\n ~~~~~~~~~~^^\n', + ' File "", line 4, in lumberjack\n bright_side_of_life()\n ~~~~~~~~~~~~~~~~~~~^^\n', ' File "", line 7, in bright_side_of_life\n return tuple()[0]\n ~~~~~~~^^^\n'] *** tb_lineno: 10 diff --git a/Doc/library/tty.rst b/Doc/library/tty.rst index fc7f98c7931fa5..20ba7d7e0a45b3 100644 --- a/Doc/library/tty.rst +++ b/Doc/library/tty.rst @@ -15,6 +15,8 @@ The :mod:`tty` module defines functions for putting the tty into cbreak and raw modes. +.. availability:: Unix. + Because it requires the :mod:`termios` module, it will work only on Unix. The :mod:`tty` module defines the following functions: @@ -43,6 +45,9 @@ The :mod:`tty` module defines the following functions: :func:`termios.tcsetattr`. The return value of :func:`termios.tcgetattr` is saved before setting *fd* to raw mode; this value is returned. + .. versionchanged:: 3.12 + The return value is now the original tty attributes, instead of None. + .. function:: setcbreak(fd, when=termios.TCSAFLUSH) @@ -51,6 +56,9 @@ The :mod:`tty` module defines the following functions: :func:`termios.tcsetattr`. The return value of :func:`termios.tcgetattr` is saved before setting *fd* to cbreak mode; this value is returned. + .. versionchanged:: 3.12 + The return value is now the original tty attributes, instead of None. + .. seealso:: diff --git a/Doc/library/turtle.rst b/Doc/library/turtle.rst index 4c84ae6a820f02..88b1f09eb3c8b7 100644 --- a/Doc/library/turtle.rst +++ b/Doc/library/turtle.rst @@ -2315,7 +2315,7 @@ Public classes .. class:: RawTurtle(canvas) RawPen(canvas) - :param canvas: a :class:`tkinter.Canvas`, a :class:`ScrolledCanvas` or a + :param canvas: a :class:`!tkinter.Canvas`, a :class:`ScrolledCanvas` or a :class:`TurtleScreen` Create a turtle. The turtle has all methods described above as "methods of @@ -2330,7 +2330,7 @@ Public classes .. class:: TurtleScreen(cv) - :param cv: a :class:`tkinter.Canvas` + :param cv: a :class:`!tkinter.Canvas` Provides screen oriented methods like :func:`bgcolor` etc. that are described above. @@ -2414,7 +2414,7 @@ instance if one is not already present. ``Turtle`` is a subclass of :class:`RawTurtle`, which *doesn't* automatically create a drawing surface - a *canvas* will need to be provided or created for -it. The *canvas* can be a :class:`tkinter.Canvas`, :class:`ScrolledCanvas` +it. The *canvas* can be a :class:`!tkinter.Canvas`, :class:`ScrolledCanvas` or :class:`TurtleScreen`. @@ -2422,7 +2422,7 @@ or :class:`TurtleScreen`. turtle. :class:`Screen` is a subclass of ``TurtleScreen``, and includes :ref:`some additional methods ` for managing its appearance (including size and title) and behaviour. ``TurtleScreen``'s -constructor needs a :class:`tkinter.Canvas` or a +constructor needs a :class:`!tkinter.Canvas` or a :class:`ScrolledCanvas` as an argument. The functional interface for turtle graphics uses the various methods of diff --git a/Doc/library/types.rst b/Doc/library/types.rst index 8cbe17df16f107..8ce67cf77253c3 100644 --- a/Doc/library/types.rst +++ b/Doc/library/types.rst @@ -200,6 +200,8 @@ Standard names are defined for the following types: Return a copy of the code object with new values for the specified fields. + Code objects are also supported by generic function :func:`copy.replace`. + .. versionadded:: 3.8 .. data:: CellType @@ -376,17 +378,15 @@ Standard names are defined for the following types: .. data:: FrameType - The type of frame objects such as found in ``tb.tb_frame`` if ``tb`` is a - traceback object. - - See :ref:`the language reference ` for details of the - available attributes and operations. + The type of :ref:`frame objects ` such as found in + :attr:`tb.tb_frame ` if ``tb`` is a traceback object. .. data:: GetSetDescriptorType The type of objects defined in extension modules with ``PyGetSetDef``, such - as ``FrameType.f_locals`` or ``array.array.typecode``. This type is used as + as :attr:`FrameType.f_locals ` or ``array.array.typecode``. + This type is used as descriptor for object attributes; it has the same purpose as the :class:`property` type, but for classes defined in extension modules. @@ -470,6 +470,12 @@ Standard names are defined for the following types: .. versionadded:: 3.12 +.. class:: CapsuleType + + The type of :ref:`capsule objects `. + + .. versionadded:: 3.13 + Additional Utility Classes and Functions ---------------------------------------- @@ -502,6 +508,8 @@ Additional Utility Classes and Functions However, for a structured record type use :func:`~collections.namedtuple` instead. + :class:`!SimpleNamespace` objects are supported by :func:`copy.replace`. + .. versionadded:: 3.3 .. versionchanged:: 3.9 diff --git a/Doc/library/typing.rst b/Doc/library/typing.rst index fad945ffc8210a..63bd62d1f6679b 100644 --- a/Doc/library/typing.rst +++ b/Doc/library/typing.rst @@ -18,8 +18,8 @@ .. note:: The Python runtime does not enforce function and variable type annotations. - They can be used by third party tools such as type checkers, IDEs, linters, - etc. + They can be used by third party tools such as :term:`type checkers `, + IDEs, linters, etc. -------------- @@ -304,7 +304,7 @@ a callable with any arbitrary parameter list would be acceptable: x = concat # Also OK ``Callable`` cannot express complex signatures such as functions that take a -variadic number of arguments, :func:`overloaded functions `, or +variadic number of arguments, :ref:`overloaded functions `, or functions that have keyword-only parameters. However, these signatures can be expressed by defining a :class:`Protocol` class with a :meth:`~object.__call__` method: @@ -462,7 +462,7 @@ contrast, a variable annotated with ``type[C]`` (or themselves -- specifically, it will accept the *class object* of ``C``. For example:: - a = 3 # Has type ``int``` + a = 3 # Has type ``int`` b = int # Has type ``type[int]`` c = type(a) # Also has type ``type[int]`` @@ -526,7 +526,7 @@ A user-defined class can be defined as a generic class. self.logger.info('%s: %s', self.name, message) This syntax indicates that the class ``LoggedVar`` is parameterised around a -single :class:`type variable ` ``T`` . This also makes ``T`` valid as +single :ref:`type variable ` ``T`` . This also makes ``T`` valid as a type within the class body. Generic classes implicitly inherit from :class:`Generic`. For compatibility @@ -1145,16 +1145,13 @@ These can be used as types in annotations. They all support subscription using from collections.abc import Callable from threading import Lock - from typing import Concatenate, ParamSpec, TypeVar - - P = ParamSpec('P') - R = TypeVar('R') + from typing import Concatenate # Use this lock to ensure that only one thread is executing a function # at any time. my_lock = Lock() - def with_lock(f: Callable[Concatenate[Lock, P], R]) -> Callable[P, R]: + def with_lock[**P, R](f: Callable[Concatenate[Lock, P], R]) -> Callable[P, R]: '''A type-safe decorator which provides a lock.''' def inner(*args: P.args, **kwargs: P.kwargs) -> R: # Provide the lock as the first argument. @@ -1301,7 +1298,7 @@ These can be used as types in annotations. They all support subscription using completely disables typechecking for a function or class. The responsibility of how to interpret the metadata - lies with the the tool or library encountering an + lies with the tool or library encountering an ``Annotated`` annotation. A tool or library encountering an ``Annotated`` type can scan through the metadata elements to determine if they are of interest (e.g., using :func:`isinstance`). @@ -1493,7 +1490,7 @@ These can be used as types in annotations. They all support subscription using Typing operator to conceptually mark an object as having been unpacked. For example, using the unpack operator ``*`` on a - :class:`type variable tuple ` is equivalent to using ``Unpack`` + :ref:`type variable tuple ` is equivalent to using ``Unpack`` to mark the type variable tuple as having been unpacked:: Ts = TypeVarTuple('Ts') @@ -1584,6 +1581,8 @@ without the dedicated syntax, as documented below. ... # Etc. +.. _typevar: + .. class:: TypeVar(name, *constraints, bound=None, covariant=False, contravariant=False, infer_variance=False) Type variable. @@ -1728,9 +1727,11 @@ without the dedicated syntax, as documented below. :ref:`type parameter ` syntax introduced by :pep:`695`. The ``infer_variance`` parameter was added. +.. _typevartuple: + .. class:: TypeVarTuple(name) - Type variable tuple. A specialized form of :class:`type variable ` + Type variable tuple. A specialized form of :ref:`type variable ` that enables *variadic* generics. Type variable tuples can be declared in :ref:`type parameter lists ` @@ -1848,7 +1849,7 @@ without the dedicated syntax, as documented below. .. class:: ParamSpec(name, *, bound=None, covariant=False, contravariant=False) Parameter specification variable. A specialized version of - :class:`type variables `. + :ref:`type variables `. In :ref:`type parameter lists `, parameter specifications can be declared with two asterisks (``**``):: @@ -1950,7 +1951,7 @@ without the dedicated syntax, as documented below. .. doctest:: - >>> from typing import ParamSpec + >>> from typing import ParamSpec, get_origin >>> P = ParamSpec("P") >>> get_origin(P.args) is P True @@ -2404,6 +2405,13 @@ types. >>> Point3D.__total__ True + This attribute reflects *only* the value of the ``total`` argument + to the current ``TypedDict`` class, not whether the class is semantically + total. For example, a ``TypedDict`` with ``__total__`` set to True may + have keys marked with :data:`NotRequired`, or it may inherit from another + ``TypedDict`` with ``total=False``. Therefore, it is generally better to use + :attr:`__required_keys__` and :attr:`__optional_keys__` for introspection. + .. attribute:: __required_keys__ .. versionadded:: 3.9 @@ -2439,6 +2447,14 @@ types. .. versionadded:: 3.9 + .. note:: + + If ``from __future__ import annotations`` is used or if annotations + are given as strings, annotations are not evaluated when the + ``TypedDict`` is defined. Therefore, the runtime introspection that + ``__required_keys__`` and ``__optional_keys__`` rely on may not work + properly, and the values of the attributes may be incorrect. + See :pep:`589` for more examples and detailed rules of using ``TypedDict``. .. versionadded:: 3.8 @@ -2588,10 +2604,10 @@ Functions and decorators .. function:: reveal_type(obj, /) - Reveal the inferred static type of an expression. + Ask a static type checker to reveal the inferred type of an expression. When a static type checker encounters a call to this function, - it emits a diagnostic with the type of the argument. For example:: + it emits a diagnostic with the inferred type of the argument. For example:: x: int = 1 reveal_type(x) # Revealed type is "builtins.int" @@ -2599,22 +2615,21 @@ Functions and decorators This can be useful when you want to debug how your type checker handles a particular piece of code. - The function returns its argument unchanged, which allows using - it within an expression:: + At runtime, this function prints the runtime type of its argument to + :data:`sys.stderr` and returns the argument unchanged (allowing the call to + be used within an expression):: - x = reveal_type(1) # Revealed type is "builtins.int" + x = reveal_type(1) # prints "Runtime type is int" + print(x) # prints "1" + + Note that the runtime type may be different from (more or less specific + than) the type statically inferred by a type checker. Most type checkers support ``reveal_type()`` anywhere, even if the name is not imported from ``typing``. Importing the name from - ``typing`` allows your code to run without runtime errors and + ``typing``, however, allows your code to run without runtime errors and communicates intent more clearly. - At runtime, this function prints the runtime type of its argument to stderr - and returns it unchanged:: - - x = reveal_type(1) # prints "Runtime type is int" - print(x) # prints "1" - .. versionadded:: 3.11 .. decorator:: dataclass_transform(*, eq_default=True, order_default=False, \ @@ -2757,6 +2772,8 @@ Functions and decorators .. versionadded:: 3.11 +.. _overload: + .. decorator:: overload Decorator for creating overloaded functions and methods. @@ -3038,14 +3055,14 @@ Introspection helpers Return the set of members defined in a :class:`Protocol`. - :: + .. doctest:: >>> from typing import Protocol, get_protocol_members >>> class P(Protocol): ... def a(self) -> str: ... ... b: int - >>> get_protocol_members(P) - frozenset({'a', 'b'}) + >>> get_protocol_members(P) == frozenset({'a', 'b'}) + True Raise :exc:`TypeError` for arguments that are not Protocols. diff --git a/Doc/library/unicodedata.rst b/Doc/library/unicodedata.rst index 3a094f9c64d4a0..7db47d48022a0e 100644 --- a/Doc/library/unicodedata.rst +++ b/Doc/library/unicodedata.rst @@ -17,8 +17,8 @@ This module provides access to the Unicode Character Database (UCD) which defines character properties for all Unicode characters. The data contained in -this database is compiled from the `UCD version 15.0.0 -`_. +this database is compiled from the `UCD version 15.1.0 +`_. The module uses the same names and symbols as defined by Unicode Standard Annex #44, `"Unicode Character Database" @@ -175,6 +175,6 @@ Examples: .. rubric:: Footnotes -.. [#] https://www.unicode.org/Public/15.0.0/ucd/NameAliases.txt +.. [#] https://www.unicode.org/Public/15.1.0/ucd/NameAliases.txt -.. [#] https://www.unicode.org/Public/15.0.0/ucd/NamedSequences.txt +.. [#] https://www.unicode.org/Public/15.1.0/ucd/NamedSequences.txt diff --git a/Doc/library/unittest.mock-examples.rst b/Doc/library/unittest.mock-examples.rst index 895b9f9f07671b..f2bdde80bdbd64 100644 --- a/Doc/library/unittest.mock-examples.rst +++ b/Doc/library/unittest.mock-examples.rst @@ -339,7 +339,7 @@ instantiate the class in those tests. >>> mock.old_method() Traceback (most recent call last): ... - AttributeError: object has no attribute 'old_method' + AttributeError: Mock object has no attribute 'old_method'. Did you mean: 'class_method'? Using a specification also enables a smarter matching of calls made to the mock, regardless of whether some parameters were passed as positional or @@ -360,6 +360,30 @@ of arbitrary attributes as well as the getting of them then you can use *spec_set* instead of *spec*. +Using side_effect to return per file content +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:func:`mock_open` is used to patch :func:`open` method. :attr:`~Mock.side_effect` +can be used to return a new Mock object per call. This can be used to return different +contents per file stored in a dictionary:: + + DEFAULT = "default" + data_dict = {"file1": "data1", + "file2": "data2"} + + def open_side_effect(name): + return mock_open(read_data=data_dict.get(name, DEFAULT))() + + with patch("builtins.open", side_effect=open_side_effect): + with open("file1") as file1: + assert file1.read() == "data1" + + with open("file2") as file2: + assert file2.read() == "data2" + + with open("file3") as file2: + assert file2.read() == "default" + Patch Decorators ---------------- @@ -579,14 +603,14 @@ Partial mocking In some tests I wanted to mock out a call to :meth:`datetime.date.today` to return a known date, but I didn't want to prevent the code under test from creating new date objects. Unfortunately :class:`datetime.date` is written in C, and -so I couldn't just monkey-patch out the static :meth:`date.today` method. +so I couldn't just monkey-patch out the static :meth:`datetime.date.today` method. I found a simple way of doing this that involved effectively wrapping the date class with a mock, but passing through calls to the constructor to the real class (and returning real instances). The :func:`patch decorator ` is used here to -mock out the ``date`` class in the module under test. The :attr:`side_effect` +mock out the ``date`` class in the module under test. The :attr:`~Mock.side_effect` attribute on the mock date class is then set to a lambda function that returns a real date. When the mock date class is called a real date will be constructed and returned by ``side_effect``. :: @@ -766,15 +790,16 @@ mock has a nice API for making assertions about how your mock objects are used. >>> mock.foo_bar.assert_called_with('baz', spam='eggs') If your mock is only being called once you can use the -:meth:`assert_called_once_with` method that also asserts that the -:attr:`call_count` is one. +:meth:`~Mock.assert_called_once_with` method that also asserts that the +:attr:`~Mock.call_count` is one. >>> mock.foo_bar.assert_called_once_with('baz', spam='eggs') >>> mock.foo_bar() >>> mock.foo_bar.assert_called_once_with('baz', spam='eggs') Traceback (most recent call last): ... - AssertionError: Expected to be called once. Called 2 times. + AssertionError: Expected 'foo_bar' to be called once. Called 2 times. + Calls: [call('baz', spam='eggs'), call()]. Both ``assert_called_with`` and ``assert_called_once_with`` make assertions about the *most recent* call. If your mock is going to be called several times, and @@ -835,7 +860,7 @@ One possibility would be for mock to copy the arguments you pass in. This could then cause problems if you do assertions that rely on object identity for equality. -Here's one solution that uses the :attr:`side_effect` +Here's one solution that uses the :attr:`~Mock.side_effect` functionality. If you provide a ``side_effect`` function for a mock then ``side_effect`` will be called with the same args as the mock. This gives us an opportunity to copy the arguments and store them for later assertions. In this @@ -903,8 +928,9 @@ Here's an example implementation: >>> c.assert_called_with(arg) Traceback (most recent call last): ... - AssertionError: Expected call: mock({1}) - Actual call: mock(set()) + AssertionError: expected call not found. + Expected: mock({1}) + Actual: mock(set()) >>> c.foo @@ -971,7 +997,8 @@ We can do this with :class:`MagicMock`, which will behave like a dictionary, and using :data:`~Mock.side_effect` to delegate dictionary access to a real underlying dictionary that is under our control. -When the :meth:`__getitem__` and :meth:`__setitem__` methods of our ``MagicMock`` are called +When the :meth:`~object.__getitem__` and :meth:`~object.__setitem__` methods +of our ``MagicMock`` are called (normal dictionary access) then ``side_effect`` is called with the key (and in the case of ``__setitem__`` the value too). We can also control what is returned. @@ -1267,8 +1294,9 @@ sufficient: >>> mock.assert_called_with(Foo(1, 2)) Traceback (most recent call last): ... - AssertionError: Expected: call(<__main__.Foo object at 0x...>) - Actual call: call(<__main__.Foo object at 0x...>) + AssertionError: expected call not found. + Expected: mock(<__main__.Foo object at 0x...>) + Actual: mock(<__main__.Foo object at 0x...>) A comparison function for our ``Foo`` class might look something like this: diff --git a/Doc/library/unittest.mock.rst b/Doc/library/unittest.mock.rst index 836fd42ab71c81..f1cc482c5cfe2a 100644 --- a/Doc/library/unittest.mock.rst +++ b/Doc/library/unittest.mock.rst @@ -189,7 +189,7 @@ code if they are used incorrectly: >>> mock_function('wrong arguments') Traceback (most recent call last): ... - TypeError: () takes exactly 3 arguments (1 given) + TypeError: missing a required argument: 'b' :func:`create_autospec` can also be used on classes, where it copies the signature of the ``__init__`` method, and on callable objects where it copies the signature of @@ -315,6 +315,7 @@ the *new_callable* argument to :func:`patch`. Traceback (most recent call last): ... AssertionError: Expected 'method' to have been called once. Called 2 times. + Calls: [call(), call()]. .. versionadded:: 3.6 @@ -342,7 +343,7 @@ the *new_callable* argument to :func:`patch`. Traceback (most recent call last): ... AssertionError: Expected 'mock' to be called once. Called 2 times. - + Calls: [call('foo', bar='baz'), call('other', bar='values')]. .. method:: assert_any_call(*args, **kwargs) @@ -392,6 +393,7 @@ the *new_callable* argument to :func:`patch`. Traceback (most recent call last): ... AssertionError: Expected 'hello' to not have been called. Called 1 times. + Calls: [call()]. .. versionadded:: 3.5 @@ -816,14 +818,15 @@ This applies to :meth:`~Mock.assert_called_with`, :meth:`~Mock.assert_any_call`. When :ref:`auto-speccing`, it will also apply to method calls on the mock object. - .. versionchanged:: 3.4 - Added signature introspection on specced and autospecced mock objects. +.. versionchanged:: 3.4 + Added signature introspection on specced and autospecced mock objects. .. class:: PropertyMock(*args, **kwargs) - A mock intended to be used as a property, or other descriptor, on a class. - :class:`PropertyMock` provides :meth:`__get__` and :meth:`__set__` methods + A mock intended to be used as a :class:`property`, or other + :term:`descriptor`, on a class. :class:`PropertyMock` provides + :meth:`~object.__get__` and :meth:`~object.__set__` methods so you can specify a return value when it is fetched. Fetching a :class:`PropertyMock` instance from an object calls the mock, with @@ -954,7 +957,7 @@ object:: >>> asyncio.run(main()) >>> mock.assert_awaited_once() >>> asyncio.run(main()) - >>> mock.method.assert_awaited_once() + >>> mock.assert_awaited_once() Traceback (most recent call last): ... AssertionError: Expected mock to have been awaited once. Awaited 2 times. @@ -972,7 +975,7 @@ object:: >>> mock.assert_awaited_with('other') Traceback (most recent call last): ... - AssertionError: expected call not found. + AssertionError: expected await not found. Expected: mock('other') Actual: mock('foo', bar='bar') @@ -1128,7 +1131,7 @@ object:: .. method:: wait_until_any_call_with(*args, **kwargs) - Waits until the the mock is called with the specified arguments. + Waits until the mock is called with the specified arguments. If a timeout was passed at the creation of the mock the function raises an :exc:`AssertionError` if the call is not performed in time. @@ -1435,9 +1438,9 @@ patch .. note:: - .. versionchanged:: 3.5 - If you are patching builtins in a module then you don't - need to pass ``create=True``, it will be added by default. + .. versionchanged:: 3.5 + If you are patching builtins in a module then you don't + need to pass ``create=True``, it will be added by default. Patch can be used as a :class:`TestCase` class decorator. It works by decorating each test method in the class. This reduces the boilerplate @@ -1705,8 +1708,9 @@ Keywords can be used in the :func:`patch.dict` call to set values in the diction :func:`patch.dict` can be used with dictionary like objects that aren't actually dictionaries. At the very minimum they must support item getting, setting, deleting and either iteration or membership test. This corresponds to the -magic methods :meth:`__getitem__`, :meth:`__setitem__`, :meth:`__delitem__` and either -:meth:`__iter__` or :meth:`__contains__`. +magic methods :meth:`~object.__getitem__`, :meth:`~object.__setitem__`, +:meth:`~object.__delitem__` and either :meth:`~container.__iter__` or +:meth:`~object.__contains__`. >>> class Container: ... def __init__(self): @@ -2169,7 +2173,7 @@ For example: >>> object() in mock False -The two equality methods, :meth:`__eq__` and :meth:`__ne__`, are special. +The two equality methods, :meth:`!__eq__` and :meth:`!__ne__`, are special. They do the default equality comparison on identity, using the :attr:`~Mock.side_effect` attribute, unless you change their return value to return something else:: @@ -2519,8 +2523,8 @@ mock_open *read_data* is now reset on each call to the *mock*. .. versionchanged:: 3.8 - Added :meth:`__iter__` to implementation so that iteration (such as in for - loops) correctly consumes *read_data*. + Added :meth:`~container.__iter__` to implementation so that iteration + (such as in for loops) correctly consumes *read_data*. Using :func:`open` as a context manager is a great way to ensure your file handles are closed properly and is becoming common:: @@ -2529,8 +2533,8 @@ are closed properly and is becoming common:: f.write('something') The issue is that even if you mock out the call to :func:`open` it is the -*returned object* that is used as a context manager (and has :meth:`__enter__` and -:meth:`__exit__` called). +*returned object* that is used as a context manager (and has :meth:`~object.__enter__` and +:meth:`~object.__exit__` called). Mocking context managers with a :class:`MagicMock` is common enough and fiddly enough that a helper function is useful. :: @@ -2702,7 +2706,7 @@ able to use autospec. On the other hand it is much better to design your objects so that introspection is safe [#]_. A more serious problem is that it is common for instance attributes to be -created in the :meth:`__init__` method and not to exist on the class at all. +created in the :meth:`~object.__init__` method and not to exist on the class at all. *autospec* can't know about any dynamically created attributes and restricts the api to visible attributes. :: @@ -2743,8 +2747,9 @@ this particular scenario: AttributeError: Mock object has no attribute 'a' Probably the best way of solving the problem is to add class attributes as -default values for instance members initialised in :meth:`__init__`. Note that if -you are only setting default attributes in :meth:`__init__` then providing them via +default values for instance members initialised in :meth:`~object.__init__`. +Note that if +you are only setting default attributes in :meth:`!__init__` then providing them via class attributes (shared between instances of course) is faster too. e.g. .. code-block:: python diff --git a/Doc/library/unittest.rst b/Doc/library/unittest.rst index 518bf6b13bad54..491009769f5aa6 100644 --- a/Doc/library/unittest.rst +++ b/Doc/library/unittest.rst @@ -206,13 +206,13 @@ Command-line options .. program:: unittest -.. cmdoption:: -b, --buffer +.. option:: -b, --buffer The standard output and standard error streams are buffered during the test run. Output during a passing test is discarded. Output is echoed normally on test fail or error and is added to the failure messages. -.. cmdoption:: -c, --catch +.. option:: -c, --catch :kbd:`Control-C` during the test run waits for the current test to end and then reports all the results so far. A second :kbd:`Control-C` raises the normal @@ -220,11 +220,11 @@ Command-line options See `Signal Handling`_ for the functions that provide this functionality. -.. cmdoption:: -f, --failfast +.. option:: -f, --failfast Stop the test run on the first error or failure. -.. cmdoption:: -k +.. option:: -k Only run test methods and classes that match the pattern or substring. This option may be used multiple times, in which case all test cases that @@ -240,11 +240,11 @@ Command-line options For example, ``-k foo`` matches ``foo_tests.SomeTest.test_something``, ``bar_tests.SomeTest.test_foo``, but not ``bar_tests.FooTest.test_something``. -.. cmdoption:: --locals +.. option:: --locals Show local variables in tracebacks. -.. cmdoption:: --durations N +.. option:: --durations N Show the N slowest test cases (N=0 for all). @@ -292,19 +292,19 @@ The ``discover`` sub-command has the following options: .. program:: unittest discover -.. cmdoption:: -v, --verbose +.. option:: -v, --verbose Verbose output -.. cmdoption:: -s, --start-directory directory +.. option:: -s, --start-directory directory Directory to start discovery (``.`` default) -.. cmdoption:: -p, --pattern pattern +.. option:: -p, --pattern pattern Pattern to match test files (``test*.py`` default) -.. cmdoption:: -t, --top-level-directory directory +.. option:: -t, --top-level-directory directory Top level directory of project (defaults to start directory) @@ -346,8 +346,8 @@ the `load_tests protocol`_. ``python -m unittest discover -s root/namespace -t root``). .. versionchanged:: 3.11 - Python 3.11 dropped the :term:`namespace packages ` - support. It has been broken since Python 3.7. Start directory and + :mod:`unittest` dropped the :term:`namespace packages ` + support in Python 3.11. It has been broken since Python 3.7. Start directory and subdirectories containing tests must be regular package that have ``__init__.py`` file. @@ -390,8 +390,8 @@ testing code:: widget = Widget('The widget') self.assertEqual(widget.size(), (50, 50)) -Note that in order to test something, we use one of the :meth:`assert\*` -methods provided by the :class:`TestCase` base class. If the test fails, an +Note that in order to test something, we use one of the :ref:`assert\* methods ` +provided by the :class:`TestCase` base class. If the test fails, an exception will be raised with an explanatory message, and :mod:`unittest` will identify the test case as a :dfn:`failure`. Any other exceptions will be treated as :dfn:`errors`. @@ -1571,6 +1571,14 @@ Test cases .. versionadded:: 3.8 + .. attribute:: loop_factory + + The *loop_factory* passed to :class:`asyncio.Runner`. Override + in subclasses with :class:`asyncio.EventLoop` to avoid using the + asyncio policy system. + + .. versionadded:: 3.13 + .. coroutinemethod:: asyncSetUp() Method called to prepare the test fixture. This is called after :meth:`setUp`. @@ -1725,7 +1733,7 @@ Grouping tests .. method:: __iter__() Tests grouped by a :class:`TestSuite` are always accessed by iteration. - Subclasses can lazily provide tests by overriding :meth:`__iter__`. Note + Subclasses can lazily provide tests by overriding :meth:`!__iter__`. Note that this method may be called several times on a single suite (for example when counting tests or comparing for equality) so the tests returned by repeated iterations before :meth:`TestSuite.run` must be the @@ -1736,7 +1744,7 @@ Grouping tests .. versionchanged:: 3.2 In earlier versions the :class:`TestSuite` accessed tests directly rather - than through iteration, so overriding :meth:`__iter__` wasn't sufficient + than through iteration, so overriding :meth:`!__iter__` wasn't sufficient for providing tests. .. versionchanged:: 3.4 @@ -1932,14 +1940,14 @@ Loading and running tests String giving the prefix of method names which will be interpreted as test methods. The default value is ``'test'``. - This affects :meth:`getTestCaseNames` and all the :meth:`loadTestsFrom\*` + This affects :meth:`getTestCaseNames` and all the ``loadTestsFrom*`` methods. .. attribute:: sortTestMethodsUsing Function to be used to compare method names when sorting them in - :meth:`getTestCaseNames` and all the :meth:`loadTestsFrom\*` methods. + :meth:`getTestCaseNames` and all the ``loadTestsFrom*`` methods. .. attribute:: suiteClass @@ -1948,7 +1956,7 @@ Loading and running tests methods on the resulting object are needed. The default value is the :class:`TestSuite` class. - This affects all the :meth:`loadTestsFrom\*` methods. + This affects all the ``loadTestsFrom*`` methods. .. attribute:: testNamePatterns @@ -1961,7 +1969,7 @@ Loading and running tests so unlike patterns passed to the ``-k`` option, simple substring patterns will have to be converted using ``*`` wildcards. - This affects all the :meth:`loadTestsFrom\*` methods. + This affects all the ``loadTestsFrom*`` methods. .. versionadded:: 3.7 @@ -1995,7 +2003,7 @@ Loading and running tests A list containing 2-tuples of :class:`TestCase` instances and strings holding formatted tracebacks. Each tuple represents a test where a failure - was explicitly signalled using the :meth:`TestCase.assert\*` methods. + was explicitly signalled using the :ref:`assert\* methods `. .. attribute:: skipped @@ -2017,7 +2025,7 @@ Loading and running tests .. attribute:: collectedDurations - A list containing 2-tuples of :class:`TestCase` instances and floats + A list containing 2-tuples of test case names and floats representing the elapsed time of each test which was run. .. versionadded:: 3.12 @@ -2282,7 +2290,7 @@ Loading and running tests The *testRunner* argument can either be a test runner class or an already created instance of it. By default ``main`` calls :func:`sys.exit` with an exit code indicating success (0) or failure (1) of the tests run. - An exit code of 5 indicates that no tests were run. + An exit code of 5 indicates that no tests were run or skipped. The *testLoader* argument has to be a :class:`TestLoader` instance, and defaults to :data:`defaultTestLoader`. @@ -2318,6 +2326,8 @@ Loading and running tests test names. +.. _load_tests-protocol: + load_tests Protocol ################### diff --git a/Doc/library/urllib.error.rst b/Doc/library/urllib.error.rst index a5bcb5b1e643bf..facb11f42a40c5 100644 --- a/Doc/library/urllib.error.rst +++ b/Doc/library/urllib.error.rst @@ -27,8 +27,8 @@ The following exceptions are raised by :mod:`urllib.error` as appropriate: exception instance. .. versionchanged:: 3.3 - :exc:`URLError` has been made a subclass of :exc:`OSError` instead - of :exc:`IOError`. + :exc:`URLError` used to be a subtype of :exc:`IOError`, which is now an + alias of :exc:`OSError`. .. exception:: HTTPError(url, code, msg, hdrs, fp) diff --git a/Doc/library/urllib.parse.rst b/Doc/library/urllib.parse.rst index e1aa4ebb0964dd..53e5f0395715d7 100644 --- a/Doc/library/urllib.parse.rst +++ b/Doc/library/urllib.parse.rst @@ -598,7 +598,7 @@ task isn't already covered by the URL parsing functions above. .. function:: quote(string, safe='/', encoding=None, errors=None) - Replace special characters in *string* using the ``%xx`` escape. Letters, + Replace special characters in *string* using the :samp:`%{xx}` escape. Letters, digits, and the characters ``'_.-~'`` are never quoted. By default, this function is intended for quoting the path section of a URL. The optional *safe* parameter specifies additional ASCII characters that should not be @@ -645,7 +645,7 @@ task isn't already covered by the URL parsing functions above. .. function:: unquote(string, encoding='utf-8', errors='replace') - Replace ``%xx`` escapes with their single-character equivalent. + Replace :samp:`%{xx}` escapes with their single-character equivalent. The optional *encoding* and *errors* parameters specify how to decode percent-encoded sequences into Unicode characters, as accepted by the :meth:`bytes.decode` method. @@ -676,7 +676,7 @@ task isn't already covered by the URL parsing functions above. .. function:: unquote_to_bytes(string) - Replace ``%xx`` escapes with their single-octet equivalent, and return a + Replace :samp:`%{xx}` escapes with their single-octet equivalent, and return a :class:`bytes` object. *string* may be either a :class:`str` or a :class:`bytes` object. diff --git a/Doc/library/urllib.request.rst b/Doc/library/urllib.request.rst index a672d8753b7f2f..0e18db73280a63 100644 --- a/Doc/library/urllib.request.rst +++ b/Doc/library/urllib.request.rst @@ -21,6 +21,14 @@ authentication, redirections, cookies and more. The `Requests package `_ is recommended for a higher-level HTTP client interface. +.. warning:: + + On macOS it is unsafe to use this module in programs using + :func:`os.fork` because the :func:`getproxies` implementation for + macOS uses a higher-level system API. Set the environment variable + ``no_proxy`` to ``*`` to avoid this problem + (e.g. ``os.environ["no_proxy"] = "*"``). + .. include:: ../includes/wasm-notavail.rst The :mod:`urllib.request` module defines the following functions: @@ -304,10 +312,10 @@ The following classes are provided: list of hostname suffixes, optionally with ``:port`` appended, for example ``cern.ch,ncsa.uiuc.edu,some.host:8080``. - .. note:: + .. note:: - ``HTTP_PROXY`` will be ignored if a variable ``REQUEST_METHOD`` is set; - see the documentation on :func:`~urllib.request.getproxies`. + ``HTTP_PROXY`` will be ignored if a variable ``REQUEST_METHOD`` is set; + see the documentation on :func:`~urllib.request.getproxies`. .. class:: HTTPPasswordMgr() @@ -712,8 +720,8 @@ The following attribute and methods should only be used by classes derived from .. note:: The convention has been adopted that subclasses defining - :meth:`_request` or :meth:`_response` methods are named - :class:`\*Processor`; all others are named :class:`\*Handler`. + :meth:`!_request` or :meth:`!_response` methods are named + :class:`!\*Processor`; all others are named :class:`!\*Handler`. .. attribute:: BaseHandler.parent @@ -833,9 +841,9 @@ HTTPRedirectHandler Objects .. method:: HTTPRedirectHandler.redirect_request(req, fp, code, msg, hdrs, newurl) Return a :class:`Request` or ``None`` in response to a redirect. This is called - by the default implementations of the :meth:`http_error_30\*` methods when a + by the default implementations of the :meth:`!http_error_30\*` methods when a redirection is received from the server. If a redirection should take place, - return a new :class:`Request` to allow :meth:`http_error_30\*` to perform the + return a new :class:`Request` to allow :meth:`!http_error_30\*` to perform the redirect to *newurl*. Otherwise, raise :exc:`~urllib.error.HTTPError` if no other handler should try to handle this URL, or return ``None`` if you can't but another handler might. @@ -1525,9 +1533,9 @@ some point in the future. :mod:`urllib.request` Restrictions ---------------------------------- - .. index:: - pair: HTTP; protocol - pair: FTP; protocol +.. index:: + pair: HTTP; protocol + pair: FTP; protocol * Currently, only the following protocols are supported: HTTP (versions 0.9 and 1.0), FTP, local files, and data URLs. diff --git a/Doc/library/uuid.rst b/Doc/library/uuid.rst index 94b9a432372195..e2d231da38fd9a 100644 --- a/Doc/library/uuid.rst +++ b/Doc/library/uuid.rst @@ -22,7 +22,7 @@ random UUID. Depending on support from the underlying platform, :func:`uuid1` may or may not return a "safe" UUID. A safe UUID is one which is generated using synchronization methods that ensure no two processes can obtain the same -UUID. All instances of :class:`UUID` have an :attr:`is_safe` attribute +UUID. All instances of :class:`UUID` have an :attr:`~UUID.is_safe` attribute which relays any information about the UUID's safety, using this enumeration: .. class:: SafeUUID @@ -95,25 +95,34 @@ which relays any information about the UUID's safety, using this enumeration: A tuple of the six integer fields of the UUID, which are also available as six individual attributes and two derived attributes: - +------------------------------+-------------------------------+ - | Field | Meaning | - +==============================+===============================+ - | :attr:`time_low` | the first 32 bits of the UUID | - +------------------------------+-------------------------------+ - | :attr:`time_mid` | the next 16 bits of the UUID | - +------------------------------+-------------------------------+ - | :attr:`time_hi_version` | the next 16 bits of the UUID | - +------------------------------+-------------------------------+ - | :attr:`clock_seq_hi_variant` | the next 8 bits of the UUID | - +------------------------------+-------------------------------+ - | :attr:`clock_seq_low` | the next 8 bits of the UUID | - +------------------------------+-------------------------------+ - | :attr:`node` | the last 48 bits of the UUID | - +------------------------------+-------------------------------+ - | :attr:`time` | the 60-bit timestamp | - +------------------------------+-------------------------------+ - | :attr:`clock_seq` | the 14-bit sequence number | - +------------------------------+-------------------------------+ +.. list-table:: + + * - Field + - Meaning + + * - .. attribute:: UUID.time_low + - The first 32 bits of the UUID. + + * - .. attribute:: UUID.time_mid + - The next 16 bits of the UUID. + + * - .. attribute:: UUID.time_hi_version + - The next 16 bits of the UUID. + + * - .. attribute:: UUID.clock_seq_hi_variant + - The next 8 bits of the UUID. + + * - .. attribute:: UUID.clock_seq_low + - The next 8 bits of the UUID. + + * - .. attribute:: UUID.node + - The last 48 bits of the UUID. + + * - .. attribute:: UUID.time + - The 60-bit timestamp. + + * - .. attribute:: UUID.clock_seq + - The 14-bit sequence number. .. attribute:: UUID.hex @@ -233,7 +242,7 @@ The :mod:`uuid` module defines the following namespace identifiers for use with text output format. The :mod:`uuid` module defines the following constants for the possible values -of the :attr:`variant` attribute: +of the :attr:`~UUID.variant` attribute: .. data:: RESERVED_NCS @@ -280,25 +289,25 @@ The following options are accepted: .. program:: uuid -.. cmdoption:: -h, --help +.. option:: -h, --help Show the help message and exit. -.. cmdoption:: -u - --uuid +.. option:: -u + --uuid Specify the function name to use to generate the uuid. By default :func:`uuid4` is used. -.. cmdoption:: -n - --namespace +.. option:: -n + --namespace The namespace is a ``UUID``, or ``@ns`` where ``ns`` is a well-known predefined UUID addressed by namespace name. Such as ``@dns``, ``@url``, ``@oid``, and ``@x500``. Only required for :func:`uuid3` / :func:`uuid5` functions. -.. cmdoption:: -N - --name +.. option:: -N + --name The name used as part of generating the uuid. Only required for :func:`uuid3` / :func:`uuid5` functions. diff --git a/Doc/library/venv.rst b/Doc/library/venv.rst index 2482441d649790..da8942c554dea1 100644 --- a/Doc/library/venv.rst +++ b/Doc/library/venv.rst @@ -30,6 +30,25 @@ When used from within a virtual environment, common installation tools such as `pip`_ will install Python packages into a virtual environment without needing to be told to do so explicitly. +A virtual environment is (amongst other things): + +* Used to contain a specific Python interpreter and software libraries and + binaries which are needed to support a project (library or application). These + are by default isolated from software in other virtual environments and Python + interpreters and libraries installed in the operating system. + +* Contained in a directory, conventionally either named ``venv`` or ``.venv`` in + the project directory, or under a container directory for lots of virtual + environments, such as ``~/.virtualenvs``. + +* Not checked into source control systems such as Git. + +* Considered as disposable -- it should be simple to delete and recreate it from + scratch. You don't place any project code in the environment + +* Not considered as movable or copyable -- you just recreate the same + environment in the target location. + See :pep:`405` for more background on Python virtual environments. .. seealso:: @@ -143,7 +162,8 @@ creation according to their needs, the :class:`EnvBuilder` class. .. class:: EnvBuilder(system_site_packages=False, clear=False, \ symlinks=False, upgrade=False, with_pip=False, \ - prompt=None, upgrade_deps=False) + prompt=None, upgrade_deps=False, \ + *, scm_ignore_files=frozenset()) The :class:`EnvBuilder` class accepts the following keyword arguments on instantiation: @@ -172,6 +192,12 @@ creation according to their needs, the :class:`EnvBuilder` class. * ``upgrade_deps`` -- Update the base venv modules to the latest on PyPI + * ``scm_ignore_files`` -- Create ignore files based for the specified source + control managers (SCM) in the iterable. Support is defined by having a + method named ``create_{scm}_ignore_file``. The only value supported by + default is ``"git"`` via :meth:`create_git_ignore_file`. + + .. versionchanged:: 3.4 Added the ``with_pip`` parameter @@ -181,6 +207,9 @@ creation according to their needs, the :class:`EnvBuilder` class. .. versionadded:: 3.9 Added the ``upgrade_deps`` parameter + .. versionadded:: 3.13 + Added the ``scm_ignore_files`` parameter + Creators of third-party virtual environment tools will be free to use the provided :class:`EnvBuilder` class as a base class. @@ -339,11 +368,18 @@ creation according to their needs, the :class:`EnvBuilder` class. The directories are allowed to exist (for when an existing environment is being upgraded). + .. method:: create_git_ignore_file(context) + + Creates a ``.gitignore`` file within the virtual environment that causes + the entire directory to be ignored by the ``git`` source control manager. + + .. versionadded:: 3.13 + There is also a module-level convenience function: .. function:: create(env_dir, system_site_packages=False, clear=False, \ symlinks=False, with_pip=False, prompt=None, \ - upgrade_deps=False) + upgrade_deps=False, *, scm_ignore_files=frozenset()) Create an :class:`EnvBuilder` with the given keyword arguments, and call its :meth:`~EnvBuilder.create` method with the *env_dir* argument. @@ -359,6 +395,9 @@ There is also a module-level convenience function: .. versionchanged:: 3.9 Added the ``upgrade_deps`` parameter + .. versionchanged:: 3.13 + Added the ``scm_ignore_files`` parameter + An example of extending ``EnvBuilder`` -------------------------------------- diff --git a/Doc/library/warnings.rst b/Doc/library/warnings.rst index 884de08eab1b16..a9c469707e8227 100644 --- a/Doc/library/warnings.rst +++ b/Doc/library/warnings.rst @@ -522,6 +522,56 @@ Available Functions and calls to :func:`simplefilter`. +.. decorator:: deprecated(msg, *, category=DeprecationWarning, stacklevel=1) + + Decorator to indicate that a class, function or overload is deprecated. + + When this decorator is applied to an object, + deprecation warnings may be emitted at runtime when the object is used. + :term:`static type checkers ` + will also generate a diagnostic on usage of the deprecated object. + + Usage:: + + from warnings import deprecated + from typing import overload + + @deprecated("Use B instead") + class A: + pass + + @deprecated("Use g instead") + def f(): + pass + + @overload + @deprecated("int support is deprecated") + def g(x: int) -> int: ... + @overload + def g(x: str) -> int: ... + + The warning specified by *category* will be emitted at runtime + on use of deprecated objects. For functions, that happens on calls; + for classes, on instantiation and on creation of subclasses. + If the *category* is ``None``, no warning is emitted at runtime. + The *stacklevel* determines where the + warning is emitted. If it is ``1`` (the default), the warning + is emitted at the direct caller of the deprecated object; if it + is higher, it is emitted further up the stack. + Static type checker behavior is not affected by the *category* + and *stacklevel* arguments. + + The deprecation message passed to the decorator is saved in the + ``__deprecated__`` attribute on the decorated object. + If applied to an overload, the decorator + must be after the :func:`@overload ` decorator + for the attribute to exist on the overload as returned by + :func:`typing.get_overloads`. + + .. versionadded:: 3.13 + See :pep:`702`. + + Available Context Managers -------------------------- diff --git a/Doc/library/weakref.rst b/Doc/library/weakref.rst index 1406b663c6a8e2..d6e062df945c64 100644 --- a/Doc/library/weakref.rst +++ b/Doc/library/weakref.rst @@ -111,7 +111,7 @@ See :ref:`__slots__ documentation ` for details. Exceptions raised by the callback will be noted on the standard error output, but cannot be propagated; they are handled in exactly the same way as exceptions - raised from an object's :meth:`__del__` method. + raised from an object's :meth:`~object.__del__` method. Weak references are :term:`hashable` if the *object* is hashable. They will maintain their hash value even after the *object* was deleted. If @@ -221,8 +221,7 @@ than needed. Added support for ``|`` and ``|=`` operators, as specified in :pep:`584`. :class:`WeakValueDictionary` objects have an additional method that has the -same issues as the :meth:`keyrefs` method of :class:`WeakKeyDictionary` -objects. +same issues as the :meth:`WeakKeyDictionary.keyrefs` method. .. method:: WeakValueDictionary.valuerefs() @@ -281,7 +280,7 @@ objects. Exceptions raised by finalizer callbacks during garbage collection will be shown on the standard error output, but cannot be propagated. They are handled in the same way as exceptions raised - from an object's :meth:`__del__` method or a weak reference's + from an object's :meth:`~object.__del__` method or a weak reference's callback. When the program exits, each remaining live finalizer is called @@ -523,18 +522,18 @@ is still alive. For instance obj dead or exiting -Comparing finalizers with :meth:`__del__` methods -------------------------------------------------- +Comparing finalizers with :meth:`~object.__del__` methods +--------------------------------------------------------- Suppose we want to create a class whose instances represent temporary directories. The directories should be deleted with their contents when the first of the following events occurs: * the object is garbage collected, -* the object's :meth:`remove` method is called, or +* the object's :meth:`!remove` method is called, or * the program exits. -We might try to implement the class using a :meth:`__del__` method as +We might try to implement the class using a :meth:`~object.__del__` method as follows:: class TempDir: @@ -553,12 +552,12 @@ follows:: def __del__(self): self.remove() -Starting with Python 3.4, :meth:`__del__` methods no longer prevent +Starting with Python 3.4, :meth:`~object.__del__` methods no longer prevent reference cycles from being garbage collected, and module globals are no longer forced to :const:`None` during :term:`interpreter shutdown`. So this code should work without any issues on CPython. -However, handling of :meth:`__del__` methods is notoriously implementation +However, handling of :meth:`~object.__del__` methods is notoriously implementation specific, since it depends on internal details of the interpreter's garbage collector implementation. diff --git a/Doc/library/wsgiref.rst b/Doc/library/wsgiref.rst index 39a4c1ba142338..c2b0ba7046967e 100644 --- a/Doc/library/wsgiref.rst +++ b/Doc/library/wsgiref.rst @@ -180,7 +180,7 @@ also provides these miscellaneous utilities: print(chunk) .. versionchanged:: 3.11 - Support for :meth:`__getitem__` method has been removed. + Support for :meth:`~object.__getitem__` method has been removed. :mod:`wsgiref.headers` -- WSGI response header tools @@ -201,8 +201,9 @@ manipulation of WSGI response headers using a mapping-like interface. an empty list. :class:`Headers` objects support typical mapping operations including - :meth:`__getitem__`, :meth:`get`, :meth:`__setitem__`, :meth:`setdefault`, - :meth:`__delitem__` and :meth:`__contains__`. For each of + :meth:`~object.__getitem__`, :meth:`~dict.get`, :meth:`~object.__setitem__`, + :meth:`~dict.setdefault`, + :meth:`~object.__delitem__` and :meth:`~object.__contains__`. For each of these methods, the key is the header name (treated case-insensitively), and the value is the first value associated with that header name. Setting a header deletes any existing values for that header, then adds a new value at the end of @@ -520,8 +521,10 @@ input, output, and error streams. want to subclass this instead of :class:`BaseCGIHandler`. This class is a subclass of :class:`BaseHandler`. It overrides the - :meth:`__init__`, :meth:`get_stdin`, :meth:`get_stderr`, :meth:`add_cgi_vars`, - :meth:`_write`, and :meth:`_flush` methods to support explicitly setting the + :meth:`!__init__`, :meth:`~BaseHandler.get_stdin`, + :meth:`~BaseHandler.get_stderr`, :meth:`~BaseHandler.add_cgi_vars`, + :meth:`~BaseHandler._write`, and :meth:`~BaseHandler._flush` methods to + support explicitly setting the environment and streams via the constructor. The supplied environment and streams are stored in the :attr:`stdin`, :attr:`stdout`, :attr:`stderr`, and :attr:`environ` attributes. diff --git a/Doc/library/xml.dom.pulldom.rst b/Doc/library/xml.dom.pulldom.rst index d1df465a598e53..843c2fd7fdb937 100644 --- a/Doc/library/xml.dom.pulldom.rst +++ b/Doc/library/xml.dom.pulldom.rst @@ -115,7 +115,7 @@ DOMEventStream Objects .. class:: DOMEventStream(stream, parser, bufsize) .. versionchanged:: 3.11 - Support for :meth:`__getitem__` method has been removed. + Support for :meth:`~object.__getitem__` method has been removed. .. method:: getEvent() diff --git a/Doc/library/xml.dom.rst b/Doc/library/xml.dom.rst index b387240a3716cc..d0e1b248d595d1 100644 --- a/Doc/library/xml.dom.rst +++ b/Doc/library/xml.dom.rst @@ -734,7 +734,7 @@ NamedNodeMap Objects attribute node. Get its value with the :attr:`value` attribute. There are also experimental methods that give this class more mapping behavior. -You can use them or you can use the standardized :meth:`getAttribute\*` family +You can use them or you can use the standardized :meth:`!getAttribute\*` family of methods on the :class:`Element` objects. diff --git a/Doc/library/xml.etree.elementtree.rst b/Doc/library/xml.etree.elementtree.rst index f9290f528e5555..57cfbb8d92244b 100644 --- a/Doc/library/xml.etree.elementtree.rst +++ b/Doc/library/xml.etree.elementtree.rst @@ -17,7 +17,7 @@ for parsing and creating XML data. This module will use a fast implementation whenever available. .. deprecated:: 3.3 - The :mod:`xml.etree.cElementTree` module is deprecated. + The :mod:`!xml.etree.cElementTree` module is deprecated. .. warning:: @@ -154,6 +154,7 @@ elements, call :meth:`XMLPullParser.read_events`. Here is an example:: ... print(elem.tag, 'text=', elem.text) ... end + mytag text= sometext more text The obvious use case is applications that operate in a non-blocking fashion where the XML data is being received from a socket or read incrementally from @@ -621,7 +622,9 @@ Functions *parser* is an optional parser instance. If not given, the standard :class:`XMLParser` parser is used. *parser* must be a subclass of :class:`XMLParser` and can only use the default :class:`TreeBuilder` as a - target. Returns an :term:`iterator` providing ``(event, elem)`` pairs. + target. Returns an :term:`iterator` providing ``(event, elem)`` pairs; + it has a ``root`` attribute that references the root element of the + resulting XML tree once *source* is fully read. Note that while :func:`iterparse` builds the tree incrementally, it issues blocking reads on *source* (or the file it names). As such, it's unsuitable @@ -825,6 +828,8 @@ Reference Functions ^^^^^^^^^ +.. module:: xml.etree.ElementInclude + .. function:: xml.etree.ElementInclude.default_loader( href, parse, encoding=None) :module: @@ -862,6 +867,9 @@ Functions Element Objects ^^^^^^^^^^^^^^^ +.. module:: xml.etree.ElementTree + :noindex: + .. class:: Element(tag, attrib={}, **extra) Element class. This class defines the Element interface, and provides a diff --git a/Doc/library/xml.rst b/Doc/library/xml.rst index 1e49b6568dfc28..909022ea4ba6a4 100644 --- a/Doc/library/xml.rst +++ b/Doc/library/xml.rst @@ -73,7 +73,7 @@ decompression bomb Safe Safe Safe 1. Expat 2.4.1 and newer is not vulnerable to the "billion laughs" and "quadratic blowup" vulnerabilities. Items still listed as vulnerable due to potential reliance on system-provided libraries. Check - :const:`pyexpat.EXPAT_VERSION`. + :const:`!pyexpat.EXPAT_VERSION`. 2. :mod:`xml.etree.ElementTree` doesn't expand external entities and raises a :exc:`~xml.etree.ElementTree.ParseError` when an entity occurs. 3. :mod:`xml.dom.minidom` doesn't expand external entities and simply returns diff --git a/Doc/library/xmlrpc.client.rst b/Doc/library/xmlrpc.client.rst index 146c4fd768233b..f7f23007fb0522 100644 --- a/Doc/library/xmlrpc.client.rst +++ b/Doc/library/xmlrpc.client.rst @@ -269,8 +269,9 @@ DateTime Objects Write the XML-RPC encoding of this :class:`DateTime` item to the *out* stream object. - It also supports certain of Python's built-in operators through rich comparison - and :meth:`__repr__` methods. + It also supports certain of Python's built-in operators through + :meth:`rich comparison ` and :meth:`~object.__repr__` + methods. A working example follows. The server code:: @@ -334,8 +335,8 @@ Binary Objects which was the de facto standard base64 specification when the XML-RPC spec was written. - It also supports certain of Python's built-in operators through :meth:`__eq__` - and :meth:`__ne__` methods. + It also supports certain of Python's built-in operators through + :meth:`~object.__eq__` and :meth:`~object.__ne__` methods. Example usage of the binary objects. We're going to transfer an image over XMLRPC:: diff --git a/Doc/library/xmlrpc.server.rst b/Doc/library/xmlrpc.server.rst index 016369d2b89d2c..ca1ea455f0acfc 100644 --- a/Doc/library/xmlrpc.server.rst +++ b/Doc/library/xmlrpc.server.rst @@ -84,12 +84,12 @@ alone XML-RPC servers. Register a function that can respond to XML-RPC requests. If *name* is given, it will be the method name associated with *function*, otherwise - ``function.__name__`` will be used. *name* is a string, and may contain + :attr:`function.__name__` will be used. *name* is a string, and may contain characters not legal in Python identifiers, including the period character. This method can also be used as a decorator. When used as a decorator, *name* can only be given as a keyword argument to register *function* under - *name*. If no *name* is given, ``function.__name__`` will be used. + *name*. If no *name* is given, :attr:`function.__name__` will be used. .. versionchanged:: 3.7 :meth:`register_function` can be used as a decorator. @@ -298,12 +298,12 @@ requests sent to Python CGI scripts. Register a function that can respond to XML-RPC requests. If *name* is given, it will be the method name associated with *function*, otherwise - ``function.__name__`` will be used. *name* is a string, and may contain + :attr:`function.__name__` will be used. *name* is a string, and may contain characters not legal in Python identifiers, including the period character. This method can also be used as a decorator. When used as a decorator, *name* can only be given as a keyword argument to register *function* under - *name*. If no *name* is given, ``function.__name__`` will be used. + *name*. If no *name* is given, :attr:`function.__name__` will be used. .. versionchanged:: 3.7 :meth:`register_function` can be used as a decorator. diff --git a/Doc/library/zipapp.rst b/Doc/library/zipapp.rst index 8cee85b32d2a83..104afca23a20b4 100644 --- a/Doc/library/zipapp.rst +++ b/Doc/library/zipapp.rst @@ -54,7 +54,7 @@ The following options are understood: .. program:: zipapp -.. cmdoption:: -o , --output= +.. option:: -o , --output= Write the output to a file named *output*. If this option is not specified, the output filename will be the same as the input *source*, with the @@ -64,13 +64,13 @@ The following options are understood: An output filename must be specified if the *source* is an archive (and in that case, *output* must not be the same as *source*). -.. cmdoption:: -p , --python= +.. option:: -p , --python= Add a ``#!`` line to the archive specifying *interpreter* as the command to run. Also, on POSIX, make the archive executable. The default is to write no ``#!`` line, and not make the file executable. -.. cmdoption:: -m , --main= +.. option:: -m , --main= Write a ``__main__.py`` file to the archive that executes *mainfn*. The *mainfn* argument should have the form "pkg.mod:fn", where "pkg.mod" is a @@ -79,7 +79,7 @@ The following options are understood: :option:`--main` cannot be specified when copying an archive. -.. cmdoption:: -c, --compress +.. option:: -c, --compress Compress files with the deflate method, reducing the size of the output file. By default, files are stored uncompressed in the archive. @@ -88,13 +88,13 @@ The following options are understood: .. versionadded:: 3.7 -.. cmdoption:: --info +.. option:: --info Display the interpreter embedded in the archive, for diagnostic purposes. In this case, any other options are ignored and SOURCE must be an archive, not a directory. -.. cmdoption:: -h, --help +.. option:: -h, --help Print a short usage message and exit. @@ -281,12 +281,7 @@ The steps to create a standalone archive are as follows: file - if not, you can just list the dependencies manually on the pip command line). -3. Optionally, delete the ``.dist-info`` directories created by pip in the - ``myapp`` directory. These hold metadata for pip to manage the packages, and - as you won't be making any further use of pip they aren't required - - although it won't do any harm if you leave them. - -4. Package the application using: +3. Package the application using: .. code-block:: shell-session diff --git a/Doc/library/zipfile.rst b/Doc/library/zipfile.rst index bd951e4872f113..a77e49a7643826 100644 --- a/Doc/library/zipfile.rst +++ b/Doc/library/zipfile.rst @@ -906,27 +906,27 @@ For a list of the files in a ZIP archive, use the :option:`-l` option: Command-line options ~~~~~~~~~~~~~~~~~~~~ -.. cmdoption:: -l - --list +.. option:: -l + --list List files in a zipfile. -.. cmdoption:: -c ... - --create ... +.. option:: -c ... + --create ... Create zipfile from source files. -.. cmdoption:: -e - --extract +.. option:: -e + --extract Extract zipfile into target directory. -.. cmdoption:: -t - --test +.. option:: -t + --test Test whether the zipfile is valid or not. -.. cmdoption:: --metadata-encoding +.. option:: --metadata-encoding Specify encoding of member names for :option:`-l`, :option:`-e` and :option:`-t`. diff --git a/Doc/library/zipimport.rst b/Doc/library/zipimport.rst index 11d19e8c863e9f..47c81f0e63603d 100644 --- a/Doc/library/zipimport.rst +++ b/Doc/library/zipimport.rst @@ -113,7 +113,7 @@ zipimporter Objects file wasn't found. .. versionchanged:: 3.3 - :exc:`IOError` used to be raised instead of :exc:`OSError`. + :exc:`IOError` used to be raised, it is now an alias of :exc:`OSError`. .. method:: get_filename(fullname) diff --git a/Doc/license.rst b/Doc/license.rst index be8efa70611378..8aad93062a5a88 100644 --- a/Doc/license.rst +++ b/Doc/license.rst @@ -352,8 +352,8 @@ the verbatim comments from the original code:: Sockets ------- -The :mod:`socket` module uses the functions, :func:`getaddrinfo`, and -:func:`getnameinfo`, which are coded in separate source files from the WIDE +The :mod:`socket` module uses the functions, :c:func:`!getaddrinfo`, and +:c:func:`!getnameinfo`, which are coded in separate source files from the WIDE Project, https://www.wide.ad.jp/. :: Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. @@ -387,7 +387,7 @@ Project, https://www.wide.ad.jp/. :: Asynchronous socket services ---------------------------- -The :mod:`test.support.asynchat` and :mod:`test.support.asyncore` +The :mod:`!test.support.asynchat` and :mod:`!test.support.asyncore` modules contain the following notice:: Copyright 1996 by Sam Rushing @@ -539,7 +539,7 @@ The :mod:`xmlrpc.client` module contains the following notice:: test_epoll ---------- -The :mod:`test_epoll` module contains the following notice:: +The :mod:`!test.test_epoll` module contains the following notice:: Copyright (c) 2001-2006 Twisted Matrix Laboratories. @@ -844,7 +844,7 @@ and later releases derived from that, the Apache License v2 applies:: expat ----- -The :mod:`pyexpat` extension is built using an included copy of the expat +The :mod:`pyexpat ` extension is built using an included copy of the expat sources unless the build is configured ``--with-system-expat``:: Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd @@ -1040,3 +1040,29 @@ https://www.w3.org/TR/xml-c14n2-testcases/ and is distributed under the THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +mimalloc +-------- + +MIT License + +Copyright (c) 2018-2021 Microsoft Corporation, Daan Leijen + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Doc/reference/compound_stmts.rst b/Doc/reference/compound_stmts.rst index 12ad18d4119617..374404bf33abbe 100644 --- a/Doc/reference/compound_stmts.rst +++ b/Doc/reference/compound_stmts.rst @@ -489,37 +489,37 @@ The execution of the :keyword:`with` statement with one "item" proceeds as follo #. The context expression (the expression given in the :token:`~python-grammar:with_item`) is evaluated to obtain a context manager. -#. The context manager's :meth:`__enter__` is loaded for later use. +#. The context manager's :meth:`~object.__enter__` is loaded for later use. -#. The context manager's :meth:`__exit__` is loaded for later use. +#. The context manager's :meth:`~object.__exit__` is loaded for later use. -#. The context manager's :meth:`__enter__` method is invoked. +#. The context manager's :meth:`~object.__enter__` method is invoked. #. If a target was included in the :keyword:`with` statement, the return value - from :meth:`__enter__` is assigned to it. + from :meth:`~object.__enter__` is assigned to it. .. note:: - The :keyword:`with` statement guarantees that if the :meth:`__enter__` - method returns without an error, then :meth:`__exit__` will always be + The :keyword:`with` statement guarantees that if the :meth:`~object.__enter__` + method returns without an error, then :meth:`~object.__exit__` will always be called. Thus, if an error occurs during the assignment to the target list, it will be treated the same as an error occurring within the suite would be. See step 7 below. #. The suite is executed. -#. The context manager's :meth:`__exit__` method is invoked. If an exception +#. The context manager's :meth:`~object.__exit__` method is invoked. If an exception caused the suite to be exited, its type, value, and traceback are passed as - arguments to :meth:`__exit__`. Otherwise, three :const:`None` arguments are + arguments to :meth:`~object.__exit__`. Otherwise, three :const:`None` arguments are supplied. If the suite was exited due to an exception, and the return value from the - :meth:`__exit__` method was false, the exception is reraised. If the return + :meth:`~object.__exit__` method was false, the exception is reraised. If the return value was true, the exception is suppressed, and execution continues with the statement following the :keyword:`with` statement. If the suite was exited for any reason other than an exception, the return - value from :meth:`__exit__` is ignored, and execution proceeds at the normal + value from :meth:`~object.__exit__` is ignored, and execution proceeds at the normal location for the kind of exit that was taken. The following code:: @@ -642,14 +642,14 @@ Here's an overview of the logical flow of a match statement: specified below. **Name bindings made during a successful pattern match outlive the executed block and can be used after the match statement**. - .. note:: + .. note:: - During failed pattern matches, some subpatterns may succeed. Do not - rely on bindings being made for a failed match. Conversely, do not - rely on variables remaining unchanged after a failed match. The exact - behavior is dependent on implementation and may vary. This is an - intentional decision made to allow different implementations to add - optimizations. + During failed pattern matches, some subpatterns may succeed. Do not + rely on bindings being made for a failed match. Conversely, do not + rely on variables remaining unchanged after a failed match. The exact + behavior is dependent on implementation and may vary. This is an + intentional decision made to allow different implementations to add + optimizations. #. If the pattern succeeds, the corresponding guard (if present) is evaluated. In this case all name bindings are guaranteed to have happened. @@ -1058,7 +1058,7 @@ subject value: .. note:: Key-value pairs are matched using the two-argument form of the mapping subject's ``get()`` method. Matched key-value pairs must already be present in the mapping, and not created on-the-fly via :meth:`__missing__` or - :meth:`__getitem__`. + :meth:`~object.__getitem__`. In simple terms ``{KEY1: P1, KEY2: P2, ... }`` matches only if all the following happens: @@ -1170,8 +1170,10 @@ In simple terms ``CLS(P1, attr=P2)`` matches only if the following happens: * ``isinstance(, CLS)`` * convert ``P1`` to a keyword pattern using ``CLS.__match_args__`` * For each keyword argument ``attr=P2``: - * ``hasattr(, "attr")`` - * ``P2`` matches ``.attr`` + + * ``hasattr(, "attr")`` + * ``P2`` matches ``.attr`` + * ... and so on for the corresponding keyword argument/pattern pair. .. seealso:: @@ -1259,7 +1261,8 @@ except that the original function is not temporarily bound to the name ``func``. A list of :ref:`type parameters ` may be given in square brackets between the function's name and the opening parenthesis for its parameter list. This indicates to static type checkers that the function is generic. At runtime, -the type parameters can be retrieved from the function's ``__type_params__`` +the type parameters can be retrieved from the function's +:attr:`~function.__type_params__` attribute. See :ref:`generic-functions` for more. .. versionchanged:: 3.12 @@ -1359,12 +1362,15 @@ access the local variables of the function containing the def. See section :pep:`526` - Syntax for Variable Annotations Ability to type hint variable declarations, including class - variables and instance variables + variables and instance variables. :pep:`563` - Postponed Evaluation of Annotations Support for forward references within annotations by preserving annotations in a string form at runtime instead of eager evaluation. + :pep:`318` - Decorators for Functions and Methods + Function and method decorators were introduced. + Class decorators were introduced in :pep:`3129`. .. _class: @@ -1838,36 +1844,36 @@ like ``TYPE_PARAMS_OF_ListOrSet`` are not actually bound at runtime. .. [#] In pattern matching, a sequence is defined as one of the following: - * a class that inherits from :class:`collections.abc.Sequence` - * a Python class that has been registered as :class:`collections.abc.Sequence` - * a builtin class that has its (CPython) :c:macro:`Py_TPFLAGS_SEQUENCE` bit set - * a class that inherits from any of the above + * a class that inherits from :class:`collections.abc.Sequence` + * a Python class that has been registered as :class:`collections.abc.Sequence` + * a builtin class that has its (CPython) :c:macro:`Py_TPFLAGS_SEQUENCE` bit set + * a class that inherits from any of the above The following standard library classes are sequences: - * :class:`array.array` - * :class:`collections.deque` - * :class:`list` - * :class:`memoryview` - * :class:`range` - * :class:`tuple` + * :class:`array.array` + * :class:`collections.deque` + * :class:`list` + * :class:`memoryview` + * :class:`range` + * :class:`tuple` .. note:: Subject values of type ``str``, ``bytes``, and ``bytearray`` do not match sequence patterns. .. [#] In pattern matching, a mapping is defined as one of the following: - * a class that inherits from :class:`collections.abc.Mapping` - * a Python class that has been registered as :class:`collections.abc.Mapping` - * a builtin class that has its (CPython) :c:macro:`Py_TPFLAGS_MAPPING` bit set - * a class that inherits from any of the above + * a class that inherits from :class:`collections.abc.Mapping` + * a Python class that has been registered as :class:`collections.abc.Mapping` + * a builtin class that has its (CPython) :c:macro:`Py_TPFLAGS_MAPPING` bit set + * a class that inherits from any of the above The standard library classes :class:`dict` and :class:`types.MappingProxyType` are mappings. .. [#] A string literal appearing as the first statement in the function body is - transformed into the function's ``__doc__`` attribute and therefore the - function's :term:`docstring`. + transformed into the function's :attr:`~function.__doc__` attribute and + therefore the function's :term:`docstring`. .. [#] A string literal appearing as the first statement in the class body is transformed into the namespace's ``__doc__`` item and therefore the class's diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst index 229fa696c9142f..ddfcb00fd788d7 100644 --- a/Doc/reference/datamodel.rst +++ b/Doc/reference/datamodel.rst @@ -88,7 +88,7 @@ Some objects contain references to "external" resources such as open files or windows. It is understood that these resources are freed when the object is garbage-collected, but since garbage collection is not guaranteed to happen, such objects also provide an explicit way to release the external resource, -usually a :meth:`close` method. Programs are strongly recommended to explicitly +usually a :meth:`!close` method. Programs are strongly recommended to explicitly close such objects. The ':keyword:`try`...\ :keyword:`finally`' statement and the ':keyword:`with`' statement provide convenient ways to do this. @@ -141,1095 +141,1396 @@ Some of the type descriptions below contain a paragraph listing 'special attributes.' These are attributes that provide access to the implementation and are not intended for general use. Their definition may change in the future. + None - .. index:: pair: object; None +---- + +.. index:: pair: object; None + +This type has a single value. There is a single object with this value. This +object is accessed through the built-in name ``None``. It is used to signify the +absence of a value in many situations, e.g., it is returned from functions that +don't explicitly return anything. Its truth value is false. - This type has a single value. There is a single object with this value. This - object is accessed through the built-in name ``None``. It is used to signify the - absence of a value in many situations, e.g., it is returned from functions that - don't explicitly return anything. Its truth value is false. NotImplemented - .. index:: pair: object; NotImplemented +-------------- - This type has a single value. There is a single object with this value. This - object is accessed through the built-in name ``NotImplemented``. Numeric methods - and rich comparison methods should return this value if they do not implement the - operation for the operands provided. (The interpreter will then try the - reflected operation, or some other fallback, depending on the operator.) It - should not be evaluated in a boolean context. +.. index:: pair: object; NotImplemented - See - :ref:`implementing-the-arithmetic-operations` - for more details. +This type has a single value. There is a single object with this value. This +object is accessed through the built-in name ``NotImplemented``. Numeric methods +and rich comparison methods should return this value if they do not implement the +operation for the operands provided. (The interpreter will then try the +reflected operation, or some other fallback, depending on the operator.) It +should not be evaluated in a boolean context. - .. versionchanged:: 3.9 - Evaluating ``NotImplemented`` in a boolean context is deprecated. While - it currently evaluates as true, it will emit a :exc:`DeprecationWarning`. - It will raise a :exc:`TypeError` in a future version of Python. +See +:ref:`implementing-the-arithmetic-operations` +for more details. + +.. versionchanged:: 3.9 + Evaluating ``NotImplemented`` in a boolean context is deprecated. While + it currently evaluates as true, it will emit a :exc:`DeprecationWarning`. + It will raise a :exc:`TypeError` in a future version of Python. Ellipsis - .. index:: - pair: object; Ellipsis - single: ...; ellipsis literal +-------- +.. index:: + pair: object; Ellipsis + single: ...; ellipsis literal + +This type has a single value. There is a single object with this value. This +object is accessed through the literal ``...`` or the built-in name +``Ellipsis``. Its truth value is true. - This type has a single value. There is a single object with this value. This - object is accessed through the literal ``...`` or the built-in name - ``Ellipsis``. Its truth value is true. :class:`numbers.Number` - .. index:: pair: object; numeric +----------------------- + +.. index:: pair: object; numeric + +These are created by numeric literals and returned as results by arithmetic +operators and arithmetic built-in functions. Numeric objects are immutable; +once created their value never changes. Python numbers are of course strongly +related to mathematical numbers, but subject to the limitations of numerical +representation in computers. - These are created by numeric literals and returned as results by arithmetic - operators and arithmetic built-in functions. Numeric objects are immutable; - once created their value never changes. Python numbers are of course strongly - related to mathematical numbers, but subject to the limitations of numerical - representation in computers. +The string representations of the numeric classes, computed by +:meth:`~object.__repr__` and :meth:`~object.__str__`, have the following +properties: - The string representations of the numeric classes, computed by - :meth:`~object.__repr__` and :meth:`~object.__str__`, have the following - properties: +* They are valid numeric literals which, when passed to their + class constructor, produce an object having the value of the + original numeric. - * They are valid numeric literals which, when passed to their - class constructor, produce an object having the value of the - original numeric. +* The representation is in base 10, when possible. - * The representation is in base 10, when possible. +* Leading zeros, possibly excepting a single zero before a + decimal point, are not shown. - * Leading zeros, possibly excepting a single zero before a - decimal point, are not shown. +* Trailing zeros, possibly excepting a single zero after a + decimal point, are not shown. - * Trailing zeros, possibly excepting a single zero after a - decimal point, are not shown. +* A sign is shown only when the number is negative. - * A sign is shown only when the number is negative. +Python distinguishes between integers, floating point numbers, and complex +numbers: - Python distinguishes between integers, floating point numbers, and complex - numbers: - :class:`numbers.Integral` - .. index:: pair: object; integer +:class:`numbers.Integral` +^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. index:: pair: object; integer + +These represent elements from the mathematical set of integers (positive and +negative). + +.. note:: + .. index:: pair: integer; representation - These represent elements from the mathematical set of integers (positive and - negative). + The rules for integer representation are intended to give the most meaningful + interpretation of shift and mask operations involving negative integers. - There are two types of integers: +There are two types of integers: - Integers (:class:`int`) - These represent numbers in an unlimited range, subject to available (virtual) - memory only. For the purpose of shift and mask operations, a binary - representation is assumed, and negative numbers are represented in a variant of - 2's complement which gives the illusion of an infinite string of sign bits - extending to the left. +Integers (:class:`int`) + These represent numbers in an unlimited range, subject to available (virtual) + memory only. For the purpose of shift and mask operations, a binary + representation is assumed, and negative numbers are represented in a variant of + 2's complement which gives the illusion of an infinite string of sign bits + extending to the left. + +Booleans (:class:`bool`) + .. index:: + pair: object; Boolean + single: False + single: True + + These represent the truth values False and True. The two objects representing + the values ``False`` and ``True`` are the only Boolean objects. The Boolean type is a + subtype of the integer type, and Boolean values behave like the values 0 and 1, + respectively, in almost all contexts, the exception being that when converted to + a string, the strings ``"False"`` or ``"True"`` are returned, respectively. - Booleans (:class:`bool`) - .. index:: - pair: object; Boolean - single: False - single: True - These represent the truth values False and True. The two objects representing - the values ``False`` and ``True`` are the only Boolean objects. The Boolean type is a - subtype of the integer type, and Boolean values behave like the values 0 and 1, - respectively, in almost all contexts, the exception being that when converted to - a string, the strings ``"False"`` or ``"True"`` are returned, respectively. +:class:`numbers.Real` (:class:`float`) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. index:: + pair: object; floating point + pair: floating point; number + pair: C; language + pair: Java; language - .. index:: pair: integer; representation +These represent machine-level double precision floating point numbers. You are +at the mercy of the underlying machine architecture (and C or Java +implementation) for the accepted range and handling of overflow. Python does not +support single-precision floating point numbers; the savings in processor and +memory usage that are usually the reason for using these are dwarfed by the +overhead of using objects in Python, so there is no reason to complicate the +language with two kinds of floating point numbers. - The rules for integer representation are intended to give the most meaningful - interpretation of shift and mask operations involving negative integers. - :class:`numbers.Real` (:class:`float`) - .. index:: - pair: object; floating point - pair: floating point; number - pair: C; language - pair: Java; language +:class:`numbers.Complex` (:class:`complex`) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - These represent machine-level double precision floating point numbers. You are - at the mercy of the underlying machine architecture (and C or Java - implementation) for the accepted range and handling of overflow. Python does not - support single-precision floating point numbers; the savings in processor and - memory usage that are usually the reason for using these are dwarfed by the - overhead of using objects in Python, so there is no reason to complicate the - language with two kinds of floating point numbers. +.. index:: + pair: object; complex + pair: complex; number - :class:`numbers.Complex` (:class:`complex`) - .. index:: - pair: object; complex - pair: complex; number +These represent complex numbers as a pair of machine-level double precision +floating point numbers. The same caveats apply as for floating point numbers. +The real and imaginary parts of a complex number ``z`` can be retrieved through +the read-only attributes ``z.real`` and ``z.imag``. - These represent complex numbers as a pair of machine-level double precision - floating point numbers. The same caveats apply as for floating point numbers. - The real and imaginary parts of a complex number ``z`` can be retrieved through - the read-only attributes ``z.real`` and ``z.imag``. Sequences +--------- + +.. index:: + pair: built-in function; len + pair: object; sequence + single: index operation + single: item selection + single: subscription + +These represent finite ordered sets indexed by non-negative numbers. The +built-in function :func:`len` returns the number of items of a sequence. When +the length of a sequence is *n*, the index set contains the numbers 0, 1, +..., *n*-1. Item *i* of sequence *a* is selected by ``a[i]``. + +.. index:: single: slicing + +Sequences also support slicing: ``a[i:j]`` selects all items with index *k* such +that *i* ``<=`` *k* ``<`` *j*. When used as an expression, a slice is a +sequence of the same type. This implies that the index set is renumbered so +that it starts at 0. + +Some sequences also support "extended slicing" with a third "step" parameter: +``a[i:j:k]`` selects all items of *a* with index *x* where ``x = i + n*k``, *n* +``>=`` ``0`` and *i* ``<=`` *x* ``<`` *j*. + +Sequences are distinguished according to their mutability: + + +Immutable sequences +^^^^^^^^^^^^^^^^^^^ + +.. index:: + pair: object; immutable sequence + pair: object; immutable + +An object of an immutable sequence type cannot change once it is created. (If +the object contains references to other objects, these other objects may be +mutable and may be changed; however, the collection of objects directly +referenced by an immutable object cannot change.) + +The following types are immutable sequences: + +.. index:: + single: string; immutable sequences + +Strings .. index:: - pair: built-in function; len - pair: object; sequence - single: index operation - single: item selection - single: subscription - - These represent finite ordered sets indexed by non-negative numbers. The - built-in function :func:`len` returns the number of items of a sequence. When - the length of a sequence is *n*, the index set contains the numbers 0, 1, - ..., *n*-1. Item *i* of sequence *a* is selected by ``a[i]``. - - .. index:: single: slicing - - Sequences also support slicing: ``a[i:j]`` selects all items with index *k* such - that *i* ``<=`` *k* ``<`` *j*. When used as an expression, a slice is a - sequence of the same type. This implies that the index set is renumbered so - that it starts at 0. - - Some sequences also support "extended slicing" with a third "step" parameter: - ``a[i:j:k]`` selects all items of *a* with index *x* where ``x = i + n*k``, *n* - ``>=`` ``0`` and *i* ``<=`` *x* ``<`` *j*. - - Sequences are distinguished according to their mutability: - - Immutable sequences - .. index:: - pair: object; immutable sequence - pair: object; immutable - - An object of an immutable sequence type cannot change once it is created. (If - the object contains references to other objects, these other objects may be - mutable and may be changed; however, the collection of objects directly - referenced by an immutable object cannot change.) - - The following types are immutable sequences: - - .. index:: - single: string; immutable sequences - - Strings - .. index:: - pair: built-in function; chr - pair: built-in function; ord - single: character - single: integer - single: Unicode - - A string is a sequence of values that represent Unicode code points. - All the code points in the range ``U+0000 - U+10FFFF`` can be - represented in a string. Python doesn't have a :c:expr:`char` type; - instead, every code point in the string is represented as a string - object with length ``1``. The built-in function :func:`ord` - converts a code point from its string form to an integer in the - range ``0 - 10FFFF``; :func:`chr` converts an integer in the range - ``0 - 10FFFF`` to the corresponding length ``1`` string object. - :meth:`str.encode` can be used to convert a :class:`str` to - :class:`bytes` using the given text encoding, and - :meth:`bytes.decode` can be used to achieve the opposite. - - Tuples - .. index:: - pair: object; tuple - pair: singleton; tuple - pair: empty; tuple - - The items of a tuple are arbitrary Python objects. Tuples of two or - more items are formed by comma-separated lists of expressions. A tuple - of one item (a 'singleton') can be formed by affixing a comma to an - expression (an expression by itself does not create a tuple, since - parentheses must be usable for grouping of expressions). An empty - tuple can be formed by an empty pair of parentheses. - - Bytes - .. index:: bytes, byte - - A bytes object is an immutable array. The items are 8-bit bytes, - represented by integers in the range 0 <= x < 256. Bytes literals - (like ``b'abc'``) and the built-in :func:`bytes()` constructor - can be used to create bytes objects. Also, bytes objects can be - decoded to strings via the :meth:`~bytes.decode` method. - - Mutable sequences - .. index:: - pair: object; mutable sequence - pair: object; mutable - pair: assignment; statement - single: subscription - single: slicing - - Mutable sequences can be changed after they are created. The subscription and - slicing notations can be used as the target of assignment and :keyword:`del` - (delete) statements. - - There are currently two intrinsic mutable sequence types: - - Lists - .. index:: pair: object; list - - The items of a list are arbitrary Python objects. Lists are formed by - placing a comma-separated list of expressions in square brackets. (Note - that there are no special cases needed to form lists of length 0 or 1.) - - Byte Arrays - .. index:: bytearray - - A bytearray object is a mutable array. They are created by the built-in - :func:`bytearray` constructor. Aside from being mutable - (and hence unhashable), byte arrays otherwise provide the same interface - and functionality as immutable :class:`bytes` objects. - - .. index:: pair: module; array - - The extension module :mod:`array` provides an additional example of a - mutable sequence type, as does the :mod:`collections` module. + pair: built-in function; chr + pair: built-in function; ord + single: character + single: integer + single: Unicode + + A string is a sequence of values that represent Unicode code points. + All the code points in the range ``U+0000 - U+10FFFF`` can be + represented in a string. Python doesn't have a :c:expr:`char` type; + instead, every code point in the string is represented as a string + object with length ``1``. The built-in function :func:`ord` + converts a code point from its string form to an integer in the + range ``0 - 10FFFF``; :func:`chr` converts an integer in the range + ``0 - 10FFFF`` to the corresponding length ``1`` string object. + :meth:`str.encode` can be used to convert a :class:`str` to + :class:`bytes` using the given text encoding, and + :meth:`bytes.decode` can be used to achieve the opposite. + +Tuples + .. index:: + pair: object; tuple + pair: singleton; tuple + pair: empty; tuple + + The items of a tuple are arbitrary Python objects. Tuples of two or + more items are formed by comma-separated lists of expressions. A tuple + of one item (a 'singleton') can be formed by affixing a comma to an + expression (an expression by itself does not create a tuple, since + parentheses must be usable for grouping of expressions). An empty + tuple can be formed by an empty pair of parentheses. + +Bytes + .. index:: bytes, byte + + A bytes object is an immutable array. The items are 8-bit bytes, + represented by integers in the range 0 <= x < 256. Bytes literals + (like ``b'abc'``) and the built-in :func:`bytes()` constructor + can be used to create bytes objects. Also, bytes objects can be + decoded to strings via the :meth:`~bytes.decode` method. + + +Mutable sequences +^^^^^^^^^^^^^^^^^ + +.. index:: + pair: object; mutable sequence + pair: object; mutable + pair: assignment; statement + single: subscription + single: slicing + +Mutable sequences can be changed after they are created. The subscription and +slicing notations can be used as the target of assignment and :keyword:`del` +(delete) statements. + +.. note:: + .. index:: pair: module; array + .. index:: pair: module; collections + + The :mod:`collections` and :mod:`array` module provide + additional examples of mutable sequence types. + +There are currently two intrinsic mutable sequence types: + +Lists + .. index:: pair: object; list + + The items of a list are arbitrary Python objects. Lists are formed by + placing a comma-separated list of expressions in square brackets. (Note + that there are no special cases needed to form lists of length 0 or 1.) + +Byte Arrays + .. index:: bytearray + + A bytearray object is a mutable array. They are created by the built-in + :func:`bytearray` constructor. Aside from being mutable + (and hence unhashable), byte arrays otherwise provide the same interface + and functionality as immutable :class:`bytes` objects. + Set types - .. index:: - pair: built-in function; len - pair: object; set type +--------- - These represent unordered, finite sets of unique, immutable objects. As such, - they cannot be indexed by any subscript. However, they can be iterated over, and - the built-in function :func:`len` returns the number of items in a set. Common - uses for sets are fast membership testing, removing duplicates from a sequence, - and computing mathematical operations such as intersection, union, difference, - and symmetric difference. +.. index:: + pair: built-in function; len + pair: object; set type - For set elements, the same immutability rules apply as for dictionary keys. Note - that numeric types obey the normal rules for numeric comparison: if two numbers - compare equal (e.g., ``1`` and ``1.0``), only one of them can be contained in a - set. +These represent unordered, finite sets of unique, immutable objects. As such, +they cannot be indexed by any subscript. However, they can be iterated over, and +the built-in function :func:`len` returns the number of items in a set. Common +uses for sets are fast membership testing, removing duplicates from a sequence, +and computing mathematical operations such as intersection, union, difference, +and symmetric difference. - There are currently two intrinsic set types: +For set elements, the same immutability rules apply as for dictionary keys. Note +that numeric types obey the normal rules for numeric comparison: if two numbers +compare equal (e.g., ``1`` and ``1.0``), only one of them can be contained in a +set. - Sets - .. index:: pair: object; set +There are currently two intrinsic set types: - These represent a mutable set. They are created by the built-in :func:`set` - constructor and can be modified afterwards by several methods, such as - :meth:`~set.add`. - Frozen sets - .. index:: pair: object; frozenset +Sets + .. index:: pair: object; set + + These represent a mutable set. They are created by the built-in :func:`set` + constructor and can be modified afterwards by several methods, such as + :meth:`~set.add`. + + +Frozen sets + .. index:: pair: object; frozenset + + These represent an immutable set. They are created by the built-in + :func:`frozenset` constructor. As a frozenset is immutable and + :term:`hashable`, it can be used again as an element of another set, or as + a dictionary key. - These represent an immutable set. They are created by the built-in - :func:`frozenset` constructor. As a frozenset is immutable and - :term:`hashable`, it can be used again as an element of another set, or as - a dictionary key. Mappings - .. index:: - pair: built-in function; len - single: subscription - pair: object; mapping - - These represent finite sets of objects indexed by arbitrary index sets. The - subscript notation ``a[k]`` selects the item indexed by ``k`` from the mapping - ``a``; this can be used in expressions and as the target of assignments or - :keyword:`del` statements. The built-in function :func:`len` returns the number - of items in a mapping. - - There is currently a single intrinsic mapping type: - - Dictionaries - .. index:: pair: object; dictionary - - These represent finite sets of objects indexed by nearly arbitrary values. The - only types of values not acceptable as keys are values containing lists or - dictionaries or other mutable types that are compared by value rather than by - object identity, the reason being that the efficient implementation of - dictionaries requires a key's hash value to remain constant. Numeric types used - for keys obey the normal rules for numeric comparison: if two numbers compare - equal (e.g., ``1`` and ``1.0``) then they can be used interchangeably to index - the same dictionary entry. - - Dictionaries preserve insertion order, meaning that keys will be produced - in the same order they were added sequentially over the dictionary. - Replacing an existing key does not change the order, however removing a key - and re-inserting it will add it to the end instead of keeping its old place. - - Dictionaries are mutable; they can be created by the ``{...}`` notation (see - section :ref:`dict`). - - .. index:: - pair: module; dbm.ndbm - pair: module; dbm.gnu - - The extension modules :mod:`dbm.ndbm` and :mod:`dbm.gnu` provide - additional examples of mapping types, as does the :mod:`collections` - module. - - .. versionchanged:: 3.7 - Dictionaries did not preserve insertion order in versions of Python before 3.6. - In CPython 3.6, insertion order was preserved, but it was considered - an implementation detail at that time rather than a language guarantee. +-------- + +.. index:: + pair: built-in function; len + single: subscription + pair: object; mapping + +These represent finite sets of objects indexed by arbitrary index sets. The +subscript notation ``a[k]`` selects the item indexed by ``k`` from the mapping +``a``; this can be used in expressions and as the target of assignments or +:keyword:`del` statements. The built-in function :func:`len` returns the number +of items in a mapping. + +There is currently a single intrinsic mapping type: + + +Dictionaries +^^^^^^^^^^^^ + +.. index:: pair: object; dictionary + +These represent finite sets of objects indexed by nearly arbitrary values. The +only types of values not acceptable as keys are values containing lists or +dictionaries or other mutable types that are compared by value rather than by +object identity, the reason being that the efficient implementation of +dictionaries requires a key's hash value to remain constant. Numeric types used +for keys obey the normal rules for numeric comparison: if two numbers compare +equal (e.g., ``1`` and ``1.0``) then they can be used interchangeably to index +the same dictionary entry. + +Dictionaries preserve insertion order, meaning that keys will be produced +in the same order they were added sequentially over the dictionary. +Replacing an existing key does not change the order, however removing a key +and re-inserting it will add it to the end instead of keeping its old place. + +Dictionaries are mutable; they can be created by the ``{...}`` notation (see +section :ref:`dict`). + +.. index:: + pair: module; dbm.ndbm + pair: module; dbm.gnu + +The extension modules :mod:`dbm.ndbm` and :mod:`dbm.gnu` provide +additional examples of mapping types, as does the :mod:`collections` +module. + +.. versionchanged:: 3.7 + Dictionaries did not preserve insertion order in versions of Python before 3.6. + In CPython 3.6, insertion order was preserved, but it was considered + an implementation detail at that time rather than a language guarantee. + Callable types - .. index:: - pair: object; callable - pair: function; call - single: invocation - pair: function; argument - - These are the types to which the function call operation (see section - :ref:`calls`) can be applied: - - User-defined functions - .. index:: - pair: user-defined; function - pair: object; function - pair: object; user-defined function - - A user-defined function object is created by a function definition (see - section :ref:`function`). It should be called with an argument list - containing the same number of items as the function's formal parameter - list. - - Special attributes: - - .. tabularcolumns:: |l|L|l| - - .. index:: - single: __doc__ (function attribute) - single: __name__ (function attribute) - single: __module__ (function attribute) - single: __dict__ (function attribute) - single: __defaults__ (function attribute) - single: __closure__ (function attribute) - single: __code__ (function attribute) - single: __globals__ (function attribute) - single: __annotations__ (function attribute) - single: __kwdefaults__ (function attribute) - single: __type_params__ (function attribute) - pair: global; namespace - - +-------------------------+-------------------------------+-----------+ - | Attribute | Meaning | | - +=========================+===============================+===========+ - | :attr:`__doc__` | The function's documentation | Writable | - | | string, or ``None`` if | | - | | unavailable; not inherited by | | - | | subclasses. | | - +-------------------------+-------------------------------+-----------+ - | :attr:`~definition.\ | The function's name. | Writable | - | __name__` | | | - +-------------------------+-------------------------------+-----------+ - | :attr:`~definition.\ | The function's | Writable | - | __qualname__` | :term:`qualified name`. | | - | | | | - | | .. versionadded:: 3.3 | | - +-------------------------+-------------------------------+-----------+ - | :attr:`__module__` | The name of the module the | Writable | - | | function was defined in, or | | - | | ``None`` if unavailable. | | - +-------------------------+-------------------------------+-----------+ - | :attr:`__defaults__` | A tuple containing default | Writable | - | | argument values for those | | - | | arguments that have defaults, | | - | | or ``None`` if no arguments | | - | | have a default value. | | - +-------------------------+-------------------------------+-----------+ - | :attr:`__code__` | The code object representing | Writable | - | | the compiled function body. | | - +-------------------------+-------------------------------+-----------+ - | :attr:`__globals__` | A reference to the dictionary | Read-only | - | | that holds the function's | | - | | global variables --- the | | - | | global namespace of the | | - | | module in which the function | | - | | was defined. | | - +-------------------------+-------------------------------+-----------+ - | :attr:`~object.__dict__`| The namespace supporting | Writable | - | | arbitrary function | | - | | attributes. | | - +-------------------------+-------------------------------+-----------+ - | :attr:`__closure__` | ``None`` or a tuple of cells | Read-only | - | | that contain bindings for the | | - | | function's free variables. | | - | | See below for information on | | - | | the ``cell_contents`` | | - | | attribute. | | - +-------------------------+-------------------------------+-----------+ - | :attr:`__annotations__` | A dict containing annotations | Writable | - | | of parameters. The keys of | | - | | the dict are the parameter | | - | | names, and ``'return'`` for | | - | | the return annotation, if | | - | | provided. For more | | - | | information on working with | | - | | this attribute, see | | - | | :ref:`annotations-howto`. | | - +-------------------------+-------------------------------+-----------+ - | :attr:`__kwdefaults__` | A dict containing defaults | Writable | - | | for keyword-only parameters. | | - +-------------------------+-------------------------------+-----------+ - | :attr:`__type_params__` | A tuple containing the | Writable | - | | :ref:`type parameters | | - | | ` of a | | - | | :ref:`generic function | | - | | `. | | - +-------------------------+-------------------------------+-----------+ - - Most of the attributes labelled "Writable" check the type of the assigned value. - - Function objects also support getting and setting arbitrary attributes, which - can be used, for example, to attach metadata to functions. Regular attribute - dot-notation is used to get and set such attributes. *Note that the current - implementation only supports function attributes on user-defined functions. - Function attributes on built-in functions may be supported in the future.* - - A cell object has the attribute ``cell_contents``. This can be used to get - the value of the cell, as well as set the value. - - Additional information about a function's definition can be retrieved from its - code object; see the description of internal types below. The - :data:`cell ` type can be accessed in the :mod:`types` - module. - - Instance methods - .. index:: - pair: object; method - pair: object; user-defined method - pair: user-defined; method - - An instance method object combines a class, a class instance and any - callable object (normally a user-defined function). - - .. index:: - single: __func__ (method attribute) - single: __self__ (method attribute) - single: __doc__ (method attribute) - single: __name__ (method attribute) - single: __module__ (method attribute) - - Special read-only attributes: :attr:`__self__` is the class instance object, - :attr:`__func__` is the function object; :attr:`__doc__` is the method's - documentation (same as ``__func__.__doc__``); :attr:`~definition.__name__` is the - method name (same as ``__func__.__name__``); :attr:`__module__` is the - name of the module the method was defined in, or ``None`` if unavailable. - - Methods also support accessing (but not setting) the arbitrary function - attributes on the underlying function object. - - User-defined method objects may be created when getting an attribute of a - class (perhaps via an instance of that class), if that attribute is a - user-defined function object or a class method object. - - When an instance method object is created by retrieving a user-defined - function object from a class via one of its instances, its - :attr:`__self__` attribute is the instance, and the method object is said - to be bound. The new method's :attr:`__func__` attribute is the original - function object. - - When an instance method object is created by retrieving a class method - object from a class or instance, its :attr:`__self__` attribute is the - class itself, and its :attr:`__func__` attribute is the function object - underlying the class method. - - When an instance method object is called, the underlying function - (:attr:`__func__`) is called, inserting the class instance - (:attr:`__self__`) in front of the argument list. For instance, when - :class:`C` is a class which contains a definition for a function - :meth:`f`, and ``x`` is an instance of :class:`C`, calling ``x.f(1)`` is - equivalent to calling ``C.f(x, 1)``. - - When an instance method object is derived from a class method object, the - "class instance" stored in :attr:`__self__` will actually be the class - itself, so that calling either ``x.f(1)`` or ``C.f(1)`` is equivalent to - calling ``f(C,1)`` where ``f`` is the underlying function. - - Note that the transformation from function object to instance method - object happens each time the attribute is retrieved from the instance. In - some cases, a fruitful optimization is to assign the attribute to a local - variable and call that local variable. Also notice that this - transformation only happens for user-defined functions; other callable - objects (and all non-callable objects) are retrieved without - transformation. It is also important to note that user-defined functions - which are attributes of a class instance are not converted to bound - methods; this *only* happens when the function is an attribute of the - class. - - Generator functions - .. index:: - single: generator; function - single: generator; iterator - - A function or method which uses the :keyword:`yield` statement (see section - :ref:`yield`) is called a :dfn:`generator function`. Such a function, when - called, always returns an :term:`iterator` object which can be used to - execute the body of the function: calling the iterator's - :meth:`iterator.__next__` method will cause the function to execute until - it provides a value using the :keyword:`!yield` statement. When the - function executes a :keyword:`return` statement or falls off the end, a - :exc:`StopIteration` exception is raised and the iterator will have - reached the end of the set of values to be returned. - - Coroutine functions - .. index:: - single: coroutine; function - - A function or method which is defined using :keyword:`async def` is called - a :dfn:`coroutine function`. Such a function, when called, returns a - :term:`coroutine` object. It may contain :keyword:`await` expressions, - as well as :keyword:`async with` and :keyword:`async for` statements. See - also the :ref:`coroutine-objects` section. - - Asynchronous generator functions - .. index:: - single: asynchronous generator; function - single: asynchronous generator; asynchronous iterator - - A function or method which is defined using :keyword:`async def` and - which uses the :keyword:`yield` statement is called a - :dfn:`asynchronous generator function`. Such a function, when called, - returns an :term:`asynchronous iterator` object which can be used in an - :keyword:`async for` statement to execute the body of the function. - - Calling the asynchronous iterator's - :meth:`aiterator.__anext__ ` method - will return an :term:`awaitable` which when awaited - will execute until it provides a value using the :keyword:`yield` - expression. When the function executes an empty :keyword:`return` - statement or falls off the end, a :exc:`StopAsyncIteration` exception - is raised and the asynchronous iterator will have reached the end of - the set of values to be yielded. - - Built-in functions - .. index:: - pair: object; built-in function - pair: object; function - pair: C; language - - A built-in function object is a wrapper around a C function. Examples of - built-in functions are :func:`len` and :func:`math.sin` (:mod:`math` is a - standard built-in module). The number and type of the arguments are - determined by the C function. Special read-only attributes: - :attr:`__doc__` is the function's documentation string, or ``None`` if - unavailable; :attr:`~definition.__name__` is the function's name; :attr:`__self__` is - set to ``None`` (but see the next item); :attr:`__module__` is the name of - the module the function was defined in or ``None`` if unavailable. - - Built-in methods - .. index:: - pair: object; built-in method - pair: object; method - pair: built-in; method - - This is really a different disguise of a built-in function, this time containing - an object passed to the C function as an implicit extra argument. An example of - a built-in method is ``alist.append()``, assuming *alist* is a list object. In - this case, the special read-only attribute :attr:`__self__` is set to the object - denoted by *alist*. - - Classes - Classes are callable. These objects normally act as factories for new - instances of themselves, but variations are possible for class types that - override :meth:`~object.__new__`. The arguments of the call are passed to - :meth:`__new__` and, in the typical case, to :meth:`~object.__init__` to - initialize the new instance. - - Class Instances - Instances of arbitrary classes can be made callable by defining a - :meth:`~object.__call__` method in their class. +-------------- + +.. index:: + pair: object; callable + pair: function; call + single: invocation + pair: function; argument + +These are the types to which the function call operation (see section +:ref:`calls`) can be applied: + + +.. _user-defined-funcs: + +User-defined functions +^^^^^^^^^^^^^^^^^^^^^^ + +.. index:: + pair: user-defined; function + pair: object; function + pair: object; user-defined function + +A user-defined function object is created by a function definition (see +section :ref:`function`). It should be called with an argument list +containing the same number of items as the function's formal parameter +list. + +Special read-only attributes +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. index:: + single: __closure__ (function attribute) + single: __globals__ (function attribute) + pair: global; namespace + +.. list-table:: + :header-rows: 1 + + * - Attribute + - Meaning + + * - .. attribute:: function.__globals__ + - A reference to the :class:`dictionary ` that holds the function's + :ref:`global variables ` -- the global namespace of the module + in which the function was defined. + + * - .. attribute:: function.__closure__ + - ``None`` or a :class:`tuple` of cells that contain bindings for the + function's free variables. + + A cell object has the attribute ``cell_contents``. + This can be used to get the value of the cell, as well as set the value. + +Special writable attributes +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. index:: + single: __doc__ (function attribute) + single: __name__ (function attribute) + single: __module__ (function attribute) + single: __dict__ (function attribute) + single: __defaults__ (function attribute) + single: __code__ (function attribute) + single: __annotations__ (function attribute) + single: __kwdefaults__ (function attribute) + single: __type_params__ (function attribute) + +Most of these attributes check the type of the assigned value: + +.. list-table:: + :header-rows: 1 + + * - Attribute + - Meaning + + * - .. attribute:: function.__doc__ + - The function's documentation string, or ``None`` if unavailable. + Not inherited by subclasses. + + * - .. attribute:: function.__name__ + - The function's name. + See also: :attr:`__name__ attributes `. + + * - .. attribute:: function.__qualname__ + - The function's :term:`qualified name`. + See also: :attr:`__qualname__ attributes `. + + .. versionadded:: 3.3 + + * - .. attribute:: function.__module__ + - The name of the module the function was defined in, + or ``None`` if unavailable. + + * - .. attribute:: function.__defaults__ + - A :class:`tuple` containing default :term:`parameter` values + for those parameters that have defaults, + or ``None`` if no parameters have a default value. + + * - .. attribute:: function.__code__ + - The :ref:`code object ` representing + the compiled function body. + + * - .. attribute:: function.__dict__ + - The namespace supporting arbitrary function attributes. + See also: :attr:`__dict__ attributes `. + + * - .. attribute:: function.__annotations__ + - A :class:`dictionary ` containing annotations of + :term:`parameters `. + The keys of the dictionary are the parameter names, + and ``'return'`` for the return annotation, if provided. + See also: :ref:`annotations-howto`. + + * - .. attribute:: function.__kwdefaults__ + - A :class:`dictionary ` containing defaults for keyword-only + :term:`parameters `. + + * - .. attribute:: function.__type_params__ + - A :class:`tuple` containing the :ref:`type parameters ` of + a :ref:`generic function `. + + .. versionadded:: 3.12 + +Function objects also support getting and setting arbitrary attributes, which +can be used, for example, to attach metadata to functions. Regular attribute +dot-notation is used to get and set such attributes. + +.. impl-detail:: + + CPython's current implementation only supports function attributes + on user-defined functions. Function attributes on + :ref:`built-in functions ` may be supported in the + future. + +Additional information about a function's definition can be retrieved from its +:ref:`code object ` +(accessible via the :attr:`~function.__code__` attribute). + + +.. _instance-methods: + +Instance methods +^^^^^^^^^^^^^^^^ + +.. index:: + pair: object; method + pair: object; user-defined method + pair: user-defined; method + +An instance method object combines a class, a class instance and any +callable object (normally a user-defined function). + +.. index:: + single: __func__ (method attribute) + single: __self__ (method attribute) + single: __doc__ (method attribute) + single: __name__ (method attribute) + single: __module__ (method attribute) + +Special read-only attributes: + +.. list-table:: + + * - .. attribute:: method.__self__ + - Refers to the class instance object to which the method is + :ref:`bound ` + + * - .. attribute:: method.__func__ + - Refers to the original :ref:`function object ` + + * - .. attribute:: method.__doc__ + - The method's documentation + (same as :attr:`method.__func__.__doc__ `). + A :class:`string ` if the original function had a docstring, else + ``None``. + + * - .. attribute:: method.__name__ + - The name of the method + (same as :attr:`method.__func__.__name__ `) + + * - .. attribute:: method.__module__ + - The name of the module the method was defined in, or ``None`` if + unavailable. + +Methods also support accessing (but not setting) the arbitrary function +attributes on the underlying :ref:`function object `. + +User-defined method objects may be created when getting an attribute of a +class (perhaps via an instance of that class), if that attribute is a +user-defined :ref:`function object ` or a +:class:`classmethod` object. + +.. _method-binding: + +When an instance method object is created by retrieving a user-defined +:ref:`function object ` from a class via one of its +instances, its :attr:`~method.__self__` attribute is the instance, and the +method object is said to be *bound*. The new method's :attr:`~method.__func__` +attribute is the original function object. + +When an instance method object is created by retrieving a :class:`classmethod` +object from a class or instance, its :attr:`~method.__self__` attribute is the +class itself, and its :attr:`~method.__func__` attribute is the function object +underlying the class method. + +When an instance method object is called, the underlying function +(:attr:`~method.__func__`) is called, inserting the class instance +(:attr:`~method.__self__`) in front of the argument list. For instance, when +:class:`!C` is a class which contains a definition for a function +:meth:`!f`, and ``x`` is an instance of :class:`!C`, calling ``x.f(1)`` is +equivalent to calling ``C.f(x, 1)``. + +When an instance method object is derived from a :class:`classmethod` object, the +"class instance" stored in :attr:`~method.__self__` will actually be the class +itself, so that calling either ``x.f(1)`` or ``C.f(1)`` is equivalent to +calling ``f(C,1)`` where ``f`` is the underlying function. + +Note that the transformation from :ref:`function object ` +to instance method +object happens each time the attribute is retrieved from the instance. In +some cases, a fruitful optimization is to assign the attribute to a local +variable and call that local variable. Also notice that this +transformation only happens for user-defined functions; other callable +objects (and all non-callable objects) are retrieved without +transformation. It is also important to note that user-defined functions +which are attributes of a class instance are not converted to bound +methods; this *only* happens when the function is an attribute of the +class. + + +Generator functions +^^^^^^^^^^^^^^^^^^^ + +.. index:: + single: generator; function + single: generator; iterator + +A function or method which uses the :keyword:`yield` statement (see section +:ref:`yield`) is called a :dfn:`generator function`. Such a function, when +called, always returns an :term:`iterator` object which can be used to +execute the body of the function: calling the iterator's +:meth:`iterator.__next__` method will cause the function to execute until +it provides a value using the :keyword:`!yield` statement. When the +function executes a :keyword:`return` statement or falls off the end, a +:exc:`StopIteration` exception is raised and the iterator will have +reached the end of the set of values to be returned. + + +Coroutine functions +^^^^^^^^^^^^^^^^^^^ + +.. index:: + single: coroutine; function + +A function or method which is defined using :keyword:`async def` is called +a :dfn:`coroutine function`. Such a function, when called, returns a +:term:`coroutine` object. It may contain :keyword:`await` expressions, +as well as :keyword:`async with` and :keyword:`async for` statements. See +also the :ref:`coroutine-objects` section. + + +Asynchronous generator functions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. index:: + single: asynchronous generator; function + single: asynchronous generator; asynchronous iterator + +A function or method which is defined using :keyword:`async def` and +which uses the :keyword:`yield` statement is called a +:dfn:`asynchronous generator function`. Such a function, when called, +returns an :term:`asynchronous iterator` object which can be used in an +:keyword:`async for` statement to execute the body of the function. + +Calling the asynchronous iterator's +:meth:`aiterator.__anext__ ` method +will return an :term:`awaitable` which when awaited +will execute until it provides a value using the :keyword:`yield` +expression. When the function executes an empty :keyword:`return` +statement or falls off the end, a :exc:`StopAsyncIteration` exception +is raised and the asynchronous iterator will have reached the end of +the set of values to be yielded. + + +.. _builtin-functions: + +Built-in functions +^^^^^^^^^^^^^^^^^^ + +.. index:: + pair: object; built-in function + pair: object; function + pair: C; language + +A built-in function object is a wrapper around a C function. Examples of +built-in functions are :func:`len` and :func:`math.sin` (:mod:`math` is a +standard built-in module). The number and type of the arguments are +determined by the C function. Special read-only attributes: + +* :attr:`!__doc__` is the function's documentation string, or ``None`` if + unavailable. See :attr:`function.__doc__`. +* :attr:`!__name__` is the function's name. See :attr:`function.__name__`. +* :attr:`!__self__` is set to ``None`` (but see the next item). +* :attr:`!__module__` is the name of + the module the function was defined in or ``None`` if unavailable. + See :attr:`function.__module__`. + + +.. _builtin-methods: + +Built-in methods +^^^^^^^^^^^^^^^^ + +.. index:: + pair: object; built-in method + pair: object; method + pair: built-in; method + +This is really a different disguise of a built-in function, this time containing +an object passed to the C function as an implicit extra argument. An example of +a built-in method is ``alist.append()``, assuming *alist* is a list object. In +this case, the special read-only attribute :attr:`!__self__` is set to the object +denoted by *alist*. (The attribute has the same semantics as it does with +:attr:`other instance methods `.) + + +Classes +^^^^^^^ + +Classes are callable. These objects normally act as factories for new +instances of themselves, but variations are possible for class types that +override :meth:`~object.__new__`. The arguments of the call are passed to +:meth:`!__new__` and, in the typical case, to :meth:`~object.__init__` to +initialize the new instance. + + +Class Instances +^^^^^^^^^^^^^^^ + +Instances of arbitrary classes can be made callable by defining a +:meth:`~object.__call__` method in their class. Modules - .. index:: - pair: statement; import - pair: object; module - - Modules are a basic organizational unit of Python code, and are created by - the :ref:`import system ` as invoked either by the - :keyword:`import` statement, or by calling - functions such as :func:`importlib.import_module` and built-in - :func:`__import__`. A module object has a namespace implemented by a - dictionary object (this is the dictionary referenced by the ``__globals__`` - attribute of functions defined in the module). Attribute references are - translated to lookups in this dictionary, e.g., ``m.x`` is equivalent to - ``m.__dict__["x"]``. A module object does not contain the code object used - to initialize the module (since it isn't needed once the initialization is - done). - - Attribute assignment updates the module's namespace dictionary, e.g., - ``m.x = 1`` is equivalent to ``m.__dict__["x"] = 1``. +------- - .. index:: - single: __name__ (module attribute) - single: __doc__ (module attribute) - single: __file__ (module attribute) - single: __annotations__ (module attribute) - pair: module; namespace +.. index:: + pair: statement; import + pair: object; module + +Modules are a basic organizational unit of Python code, and are created by +the :ref:`import system ` as invoked either by the +:keyword:`import` statement, or by calling +functions such as :func:`importlib.import_module` and built-in +:func:`__import__`. A module object has a namespace implemented by a +:class:`dictionary ` object (this is the dictionary referenced by the +:attr:`~function.__globals__` +attribute of functions defined in the module). Attribute references are +translated to lookups in this dictionary, e.g., ``m.x`` is equivalent to +``m.__dict__["x"]``. A module object does not contain the code object used +to initialize the module (since it isn't needed once the initialization is +done). + +Attribute assignment updates the module's namespace dictionary, e.g., +``m.x = 1`` is equivalent to ``m.__dict__["x"] = 1``. - Predefined (writable) attributes: +.. index:: + single: __name__ (module attribute) + single: __doc__ (module attribute) + single: __file__ (module attribute) + single: __annotations__ (module attribute) + pair: module; namespace - :attr:`__name__` - The module's name. +Predefined (writable) attributes: - :attr:`__doc__` - The module's documentation string, or ``None`` if - unavailable. + :attr:`__name__` + The module's name. - :attr:`__file__` - The pathname of the file from which the - module was loaded, if it was loaded from a file. - The :attr:`__file__` - attribute may be missing for certain types of modules, such as C modules - that are statically linked into the interpreter. For extension modules - loaded dynamically from a shared library, it's the pathname of the shared - library file. + :attr:`__doc__` + The module's documentation string, or ``None`` if + unavailable. - :attr:`__annotations__` - A dictionary containing - :term:`variable annotations ` collected during - module body execution. For best practices on working - with :attr:`__annotations__`, please see :ref:`annotations-howto`. + :attr:`__file__` + The pathname of the file from which the + module was loaded, if it was loaded from a file. + The :attr:`__file__` + attribute may be missing for certain types of modules, such as C modules + that are statically linked into the interpreter. For extension modules + loaded dynamically from a shared library, it's the pathname of the shared + library file. - .. index:: single: __dict__ (module attribute) + :attr:`__annotations__` + A dictionary containing + :term:`variable annotations ` collected during + module body execution. For best practices on working + with :attr:`__annotations__`, please see :ref:`annotations-howto`. - Special read-only attribute: :attr:`~object.__dict__` is the module's - namespace as a dictionary object. +.. index:: single: __dict__ (module attribute) - .. impl-detail:: +Special read-only attribute: :attr:`~object.__dict__` is the module's +namespace as a dictionary object. + +.. impl-detail:: + + Because of the way CPython clears module dictionaries, the module + dictionary will be cleared when the module falls out of scope even if the + dictionary still has live references. To avoid this, copy the dictionary + or keep the module around while using its dictionary directly. - Because of the way CPython clears module dictionaries, the module - dictionary will be cleared when the module falls out of scope even if the - dictionary still has live references. To avoid this, copy the dictionary - or keep the module around while using its dictionary directly. Custom classes - Custom class types are typically created by class definitions (see section - :ref:`class`). A class has a namespace implemented by a dictionary object. - Class attribute references are translated to lookups in this dictionary, e.g., - ``C.x`` is translated to ``C.__dict__["x"]`` (although there are a number of - hooks which allow for other means of locating attributes). When the attribute - name is not found there, the attribute search continues in the base classes. - This search of the base classes uses the C3 method resolution order which - behaves correctly even in the presence of 'diamond' inheritance structures - where there are multiple inheritance paths leading back to a common ancestor. - Additional details on the C3 MRO used by Python can be found in the - documentation accompanying the 2.3 release at - https://www.python.org/download/releases/2.3/mro/. - - .. XXX: Could we add that MRO doc as an appendix to the language ref? +-------------- + +Custom class types are typically created by class definitions (see section +:ref:`class`). A class has a namespace implemented by a dictionary object. +Class attribute references are translated to lookups in this dictionary, e.g., +``C.x`` is translated to ``C.__dict__["x"]`` (although there are a number of +hooks which allow for other means of locating attributes). When the attribute +name is not found there, the attribute search continues in the base classes. +This search of the base classes uses the C3 method resolution order which +behaves correctly even in the presence of 'diamond' inheritance structures +where there are multiple inheritance paths leading back to a common ancestor. +Additional details on the C3 MRO used by Python can be found in the +documentation accompanying the 2.3 release at +https://www.python.org/download/releases/2.3/mro/. + +.. XXX: Could we add that MRO doc as an appendix to the language ref? - .. index:: - pair: object; class - pair: object; class instance - pair: object; instance - pair: class object; call - single: container - pair: object; dictionary - pair: class; attribute +.. index:: + pair: object; class + pair: object; class instance + pair: object; instance + pair: class object; call + single: container + pair: object; dictionary + pair: class; attribute - When a class attribute reference (for class :class:`C`, say) would yield a - class method object, it is transformed into an instance method object whose - :attr:`__self__` attribute is :class:`C`. When it would yield a static - method object, it is transformed into the object wrapped by the static method - object. See section :ref:`descriptors` for another way in which attributes - retrieved from a class may differ from those actually contained in its - :attr:`~object.__dict__`. +When a class attribute reference (for class :class:`!C`, say) would yield a +class method object, it is transformed into an instance method object whose +:attr:`~method.__self__` attribute is :class:`!C`. +When it would yield a :class:`staticmethod` object, +it is transformed into the object wrapped by the static method +object. See section :ref:`descriptors` for another way in which attributes +retrieved from a class may differ from those actually contained in its +:attr:`~object.__dict__`. - .. index:: triple: class; attribute; assignment +.. index:: triple: class; attribute; assignment - Class attribute assignments update the class's dictionary, never the dictionary - of a base class. +Class attribute assignments update the class's dictionary, never the dictionary +of a base class. - .. index:: pair: class object; call +.. index:: pair: class object; call - A class object can be called (see above) to yield a class instance (see below). +A class object can be called (see above) to yield a class instance (see below). - .. index:: - single: __name__ (class attribute) - single: __module__ (class attribute) - single: __dict__ (class attribute) - single: __bases__ (class attribute) - single: __doc__ (class attribute) - single: __annotations__ (class attribute) - single: __type_params__ (class attribute) +.. index:: + single: __name__ (class attribute) + single: __module__ (class attribute) + single: __dict__ (class attribute) + single: __bases__ (class attribute) + single: __doc__ (class attribute) + single: __annotations__ (class attribute) + single: __type_params__ (class attribute) - Special attributes: +Special attributes: - :attr:`~definition.__name__` - The class name. + :attr:`~definition.__name__` + The class name. - :attr:`__module__` - The name of the module in which the class was defined. + :attr:`__module__` + The name of the module in which the class was defined. - :attr:`~object.__dict__` - The dictionary containing the class's namespace. + :attr:`~object.__dict__` + The dictionary containing the class's namespace. + + :attr:`~class.__bases__` + A tuple containing the base classes, in the order of + their occurrence in the base class list. - :attr:`~class.__bases__` - A tuple containing the base classes, in the order of - their occurrence in the base class list. + :attr:`__doc__` + The class's documentation string, or ``None`` if undefined. - :attr:`__doc__` - The class's documentation string, or ``None`` if undefined. + :attr:`__annotations__` + A dictionary containing + :term:`variable annotations ` + collected during class body execution. For best practices on + working with :attr:`__annotations__`, please see + :ref:`annotations-howto`. - :attr:`__annotations__` - A dictionary containing - :term:`variable annotations ` - collected during class body execution. For best practices on - working with :attr:`__annotations__`, please see - :ref:`annotations-howto`. + :attr:`__type_params__` + A tuple containing the :ref:`type parameters ` of + a :ref:`generic class `. - :attr:`__type_params__` - A tuple containing the :ref:`type parameters ` of - a :ref:`generic class `. Class instances - .. index:: - pair: object; class instance - pair: object; instance - pair: class; instance - pair: class instance; attribute - - A class instance is created by calling a class object (see above). A class - instance has a namespace implemented as a dictionary which is the first place - in which attribute references are searched. When an attribute is not found - there, and the instance's class has an attribute by that name, the search - continues with the class attributes. If a class attribute is found that is a - user-defined function object, it is transformed into an instance method - object whose :attr:`__self__` attribute is the instance. Static method and - class method objects are also transformed; see above under "Classes". See - section :ref:`descriptors` for another way in which attributes of a class - retrieved via its instances may differ from the objects actually stored in - the class's :attr:`~object.__dict__`. If no class attribute is found, and the - object's class has a :meth:`~object.__getattr__` method, that is called to satisfy - the lookup. - - .. index:: triple: class instance; attribute; assignment - - Attribute assignments and deletions update the instance's dictionary, never a - class's dictionary. If the class has a :meth:`~object.__setattr__` or - :meth:`~object.__delattr__` method, this is called instead of updating the instance - dictionary directly. +--------------- - .. index:: - pair: object; numeric - pair: object; sequence - pair: object; mapping +.. index:: + pair: object; class instance + pair: object; instance + pair: class; instance + pair: class instance; attribute + +A class instance is created by calling a class object (see above). A class +instance has a namespace implemented as a dictionary which is the first place +in which attribute references are searched. When an attribute is not found +there, and the instance's class has an attribute by that name, the search +continues with the class attributes. If a class attribute is found that is a +user-defined function object, it is transformed into an instance method +object whose :attr:`~method.__self__` attribute is the instance. Static method and +class method objects are also transformed; see above under "Classes". See +section :ref:`descriptors` for another way in which attributes of a class +retrieved via its instances may differ from the objects actually stored in +the class's :attr:`~object.__dict__`. If no class attribute is found, and the +object's class has a :meth:`~object.__getattr__` method, that is called to satisfy +the lookup. + +.. index:: triple: class instance; attribute; assignment + +Attribute assignments and deletions update the instance's dictionary, never a +class's dictionary. If the class has a :meth:`~object.__setattr__` or +:meth:`~object.__delattr__` method, this is called instead of updating the instance +dictionary directly. - Class instances can pretend to be numbers, sequences, or mappings if they have - methods with certain special names. See section :ref:`specialnames`. +.. index:: + pair: object; numeric + pair: object; sequence + pair: object; mapping - .. index:: - single: __dict__ (instance attribute) - single: __class__ (instance attribute) +Class instances can pretend to be numbers, sequences, or mappings if they have +methods with certain special names. See section :ref:`specialnames`. + +.. index:: + single: __dict__ (instance attribute) + single: __class__ (instance attribute) + +Special attributes: :attr:`~object.__dict__` is the attribute dictionary; +:attr:`~instance.__class__` is the instance's class. - Special attributes: :attr:`~object.__dict__` is the attribute dictionary; - :attr:`~instance.__class__` is the instance's class. I/O objects (also known as file objects) - .. index:: - pair: built-in function; open - pair: module; io - single: popen() (in module os) - single: makefile() (socket method) - single: sys.stdin - single: sys.stdout - single: sys.stderr - single: stdio - single: stdin (in module sys) - single: stdout (in module sys) - single: stderr (in module sys) - - A :term:`file object` represents an open file. Various shortcuts are - available to create file objects: the :func:`open` built-in function, and - also :func:`os.popen`, :func:`os.fdopen`, and the - :meth:`~socket.socket.makefile` method of socket objects (and perhaps by - other functions or methods provided by extension modules). - - The objects ``sys.stdin``, ``sys.stdout`` and ``sys.stderr`` are - initialized to file objects corresponding to the interpreter's standard - input, output and error streams; they are all open in text mode and - therefore follow the interface defined by the :class:`io.TextIOBase` - abstract class. +---------------------------------------- + +.. index:: + pair: built-in function; open + pair: module; io + single: popen() (in module os) + single: makefile() (socket method) + single: sys.stdin + single: sys.stdout + single: sys.stderr + single: stdio + single: stdin (in module sys) + single: stdout (in module sys) + single: stderr (in module sys) + +A :term:`file object` represents an open file. Various shortcuts are +available to create file objects: the :func:`open` built-in function, and +also :func:`os.popen`, :func:`os.fdopen`, and the +:meth:`~socket.socket.makefile` method of socket objects (and perhaps by +other functions or methods provided by extension modules). + +The objects ``sys.stdin``, ``sys.stdout`` and ``sys.stderr`` are +initialized to file objects corresponding to the interpreter's standard +input, output and error streams; they are all open in text mode and +therefore follow the interface defined by the :class:`io.TextIOBase` +abstract class. + Internal types - .. index:: - single: internal type - single: types, internal - - A few types used internally by the interpreter are exposed to the user. Their - definitions may change with future versions of the interpreter, but they are - mentioned here for completeness. - - .. index:: bytecode, object; code, code object - - Code objects - Code objects represent *byte-compiled* executable Python code, or :term:`bytecode`. - The difference between a code object and a function object is that the function - object contains an explicit reference to the function's globals (the module in - which it was defined), while a code object contains no context; also the default - argument values are stored in the function object, not in the code object - (because they represent values calculated at run-time). Unlike function - objects, code objects are immutable and contain no references (directly or - indirectly) to mutable objects. - - .. index:: - single: co_argcount (code object attribute) - single: co_posonlyargcount (code object attribute) - single: co_kwonlyargcount (code object attribute) - single: co_code (code object attribute) - single: co_consts (code object attribute) - single: co_filename (code object attribute) - single: co_firstlineno (code object attribute) - single: co_flags (code object attribute) - single: co_lnotab (code object attribute) - single: co_name (code object attribute) - single: co_names (code object attribute) - single: co_nlocals (code object attribute) - single: co_stacksize (code object attribute) - single: co_varnames (code object attribute) - single: co_cellvars (code object attribute) - single: co_freevars (code object attribute) - single: co_qualname (code object attribute) - - Special read-only attributes: :attr:`co_name` gives the function name; - :attr:`co_qualname` gives the fully qualified function name; - :attr:`co_argcount` is the total number of positional arguments - (including positional-only arguments and arguments with default values); - :attr:`co_posonlyargcount` is the number of positional-only arguments - (including arguments with default values); :attr:`co_kwonlyargcount` is - the number of keyword-only arguments (including arguments with default - values); :attr:`co_nlocals` is the number of local variables used by the - function (including arguments); :attr:`co_varnames` is a tuple containing - the names of the local variables (starting with the argument names); - :attr:`co_cellvars` is a tuple containing the names of local variables - that are referenced by nested functions; :attr:`co_freevars` is a tuple - containing the names of free variables; :attr:`co_code` is a string - representing the sequence of bytecode instructions; :attr:`co_consts` is - a tuple containing the literals used by the bytecode; :attr:`co_names` is - a tuple containing the names used by the bytecode; :attr:`co_filename` is - the filename from which the code was compiled; :attr:`co_firstlineno` is - the first line number of the function; :attr:`co_lnotab` is a string - encoding the mapping from bytecode offsets to line numbers (for details - see the source code of the interpreter, is deprecated since 3.12 - and may be removed in 3.14); :attr:`co_stacksize` is the - required stack size; :attr:`co_flags` is an integer encoding a number - of flags for the interpreter. - - .. index:: pair: object; generator - - The following flag bits are defined for :attr:`co_flags`: bit ``0x04`` is set if - the function uses the ``*arguments`` syntax to accept an arbitrary number of - positional arguments; bit ``0x08`` is set if the function uses the - ``**keywords`` syntax to accept arbitrary keyword arguments; bit ``0x20`` is set - if the function is a generator. - - Future feature declarations (``from __future__ import division``) also use bits - in :attr:`co_flags` to indicate whether a code object was compiled with a - particular feature enabled: bit ``0x2000`` is set if the function was compiled - with future division enabled; bits ``0x10`` and ``0x1000`` were used in earlier - versions of Python. - - Other bits in :attr:`co_flags` are reserved for internal use. - - .. index:: single: documentation string - - If a code object represents a function, the first item in :attr:`co_consts` is - the documentation string of the function, or ``None`` if undefined. - - .. method:: codeobject.co_positions() - - Returns an iterable over the source code positions of each bytecode - instruction in the code object. - - The iterator returns tuples containing the ``(start_line, end_line, - start_column, end_column)``. The *i-th* tuple corresponds to the - position of the source code that compiled to the *i-th* instruction. - Column information is 0-indexed utf-8 byte offsets on the given source - line. - - This positional information can be missing. A non-exhaustive lists of - cases where this may happen: - - - Running the interpreter with :option:`-X` ``no_debug_ranges``. - - Loading a pyc file compiled while using :option:`-X` ``no_debug_ranges``. - - Position tuples corresponding to artificial instructions. - - Line and column numbers that can't be represented due to - implementation specific limitations. - - When this occurs, some or all of the tuple elements can be - :const:`None`. - - .. versionadded:: 3.11 - - .. note:: - This feature requires storing column positions in code objects which may - result in a small increase of disk usage of compiled Python files or - interpreter memory usage. To avoid storing the extra information and/or - deactivate printing the extra traceback information, the - :option:`-X` ``no_debug_ranges`` command line flag or the :envvar:`PYTHONNODEBUGRANGES` - environment variable can be used. - - .. _frame-objects: - - Frame objects - .. index:: pair: object; frame - - Frame objects represent execution frames. They may occur in traceback objects - (see below), and are also passed to registered trace functions. - - .. index:: - single: f_back (frame attribute) - single: f_code (frame attribute) - single: f_globals (frame attribute) - single: f_locals (frame attribute) - single: f_lasti (frame attribute) - single: f_builtins (frame attribute) - - Special read-only attributes: :attr:`f_back` is to the previous stack frame - (towards the caller), or ``None`` if this is the bottom stack frame; - :attr:`f_code` is the code object being executed in this frame; :attr:`f_locals` - is the dictionary used to look up local variables; :attr:`f_globals` is used for - global variables; :attr:`f_builtins` is used for built-in (intrinsic) names; - :attr:`f_lasti` gives the precise instruction (this is an index into the - bytecode string of the code object). - - Accessing ``f_code`` raises an :ref:`auditing event ` - ``object.__getattr__`` with arguments ``obj`` and ``"f_code"``. - - .. index:: - single: f_trace (frame attribute) - single: f_trace_lines (frame attribute) - single: f_trace_opcodes (frame attribute) - single: f_lineno (frame attribute) - - Special writable attributes: :attr:`f_trace`, if not ``None``, is a function - called for various events during code execution (this is used by the debugger). - Normally an event is triggered for each new source line - this can be - disabled by setting :attr:`f_trace_lines` to :const:`False`. - - Implementations *may* allow per-opcode events to be requested by setting - :attr:`f_trace_opcodes` to :const:`True`. Note that this may lead to - undefined interpreter behaviour if exceptions raised by the trace - function escape to the function being traced. - - :attr:`f_lineno` is the current line number of the frame --- writing to this - from within a trace function jumps to the given line (only for the bottom-most - frame). A debugger can implement a Jump command (aka Set Next Statement) - by writing to f_lineno. - - Frame objects support one method: - - .. method:: frame.clear() - - This method clears all references to local variables held by the - frame. Also, if the frame belonged to a generator, the generator - is finalized. This helps break reference cycles involving frame - objects (for example when catching an exception and storing its - traceback for later use). - - :exc:`RuntimeError` is raised if the frame is currently executing. - - .. versionadded:: 3.4 - - .. _traceback-objects: - - Traceback objects - .. index:: - pair: object; traceback - pair: stack; trace - pair: exception; handler - pair: execution; stack - single: exc_info (in module sys) - single: last_traceback (in module sys) - single: sys.exc_info - single: sys.exception - single: sys.last_traceback - - Traceback objects represent a stack trace of an exception. A traceback object - is implicitly created when an exception occurs, and may also be explicitly - created by calling :class:`types.TracebackType`. - - For implicitly created tracebacks, when the search for an exception handler - unwinds the execution stack, at each unwound level a traceback object is - inserted in front of the current traceback. When an exception handler is - entered, the stack trace is made available to the program. (See section - :ref:`try`.) It is accessible as the third item of the - tuple returned by ``sys.exc_info()``, and as the ``__traceback__`` attribute - of the caught exception. - - When the program contains no suitable - handler, the stack trace is written (nicely formatted) to the standard error - stream; if the interpreter is interactive, it is also made available to the user - as ``sys.last_traceback``. - - For explicitly created tracebacks, it is up to the creator of the traceback - to determine how the ``tb_next`` attributes should be linked to form a - full stack trace. - - .. index:: - single: tb_frame (traceback attribute) - single: tb_lineno (traceback attribute) - single: tb_lasti (traceback attribute) - pair: statement; try - - Special read-only attributes: - :attr:`tb_frame` points to the execution frame of the current level; - :attr:`tb_lineno` gives the line number where the exception occurred; - :attr:`tb_lasti` indicates the precise instruction. - The line number and last instruction in the traceback may differ from the - line number of its frame object if the exception occurred in a - :keyword:`try` statement with no matching except clause or with a - finally clause. - - Accessing ``tb_frame`` raises an :ref:`auditing event ` - ``object.__getattr__`` with arguments ``obj`` and ``"tb_frame"``. - - .. index:: - single: tb_next (traceback attribute) - - Special writable attribute: :attr:`tb_next` is the next level in the stack - trace (towards the frame where the exception occurred), or ``None`` if - there is no next level. - - .. versionchanged:: 3.7 - Traceback objects can now be explicitly instantiated from Python code, - and the ``tb_next`` attribute of existing instances can be updated. - - Slice objects - .. index:: pair: built-in function; slice - - Slice objects are used to represent slices for - :meth:`~object.__getitem__` - methods. They are also created by the built-in :func:`slice` function. - - .. index:: - single: start (slice object attribute) - single: stop (slice object attribute) - single: step (slice object attribute) - - Special read-only attributes: :attr:`~slice.start` is the lower bound; - :attr:`~slice.stop` is the upper bound; :attr:`~slice.step` is the step - value; each is ``None`` if omitted. These attributes can have any type. - - Slice objects support one method: - - .. method:: slice.indices(self, length) - - This method takes a single integer argument *length* and computes - information about the slice that the slice object would describe if - applied to a sequence of *length* items. It returns a tuple of three - integers; respectively these are the *start* and *stop* indices and the - *step* or stride length of the slice. Missing or out-of-bounds indices - are handled in a manner consistent with regular slices. - - Static method objects - Static method objects provide a way of defeating the transformation of function - objects to method objects described above. A static method object is a wrapper - around any other object, usually a user-defined method object. When a static - method object is retrieved from a class or a class instance, the object actually - returned is the wrapped object, which is not subject to any further - transformation. Static method objects are also callable. Static method - objects are created by the built-in :func:`staticmethod` constructor. - - Class method objects - A class method object, like a static method object, is a wrapper around another - object that alters the way in which that object is retrieved from classes and - class instances. The behaviour of class method objects upon such retrieval is - described above, under "User-defined methods". Class method objects are created - by the built-in :func:`classmethod` constructor. +-------------- + +.. index:: + single: internal type + single: types, internal + +A few types used internally by the interpreter are exposed to the user. Their +definitions may change with future versions of the interpreter, but they are +mentioned here for completeness. + + +.. _code-objects: + +Code objects +^^^^^^^^^^^^ + +.. index:: bytecode, object; code, code object + +Code objects represent *byte-compiled* executable Python code, or :term:`bytecode`. +The difference between a code object and a function object is that the function +object contains an explicit reference to the function's globals (the module in +which it was defined), while a code object contains no context; also the default +argument values are stored in the function object, not in the code object +(because they represent values calculated at run-time). Unlike function +objects, code objects are immutable and contain no references (directly or +indirectly) to mutable objects. + +.. index:: + single: co_argcount (code object attribute) + single: co_posonlyargcount (code object attribute) + single: co_kwonlyargcount (code object attribute) + single: co_code (code object attribute) + single: co_consts (code object attribute) + single: co_filename (code object attribute) + single: co_firstlineno (code object attribute) + single: co_flags (code object attribute) + single: co_lnotab (code object attribute) + single: co_name (code object attribute) + single: co_names (code object attribute) + single: co_nlocals (code object attribute) + single: co_stacksize (code object attribute) + single: co_varnames (code object attribute) + single: co_cellvars (code object attribute) + single: co_freevars (code object attribute) + single: co_qualname (code object attribute) + +Special read-only attributes +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. list-table:: + + * - .. attribute:: codeobject.co_name + - The function name + + * - .. attribute:: codeobject.co_qualname + - The fully qualified function name + + * - .. attribute:: codeobject.co_argcount + - The total number of positional :term:`parameters ` + (including positional-only parameters and parameters with default values) + that the function has + + * - .. attribute:: codeobject.co_posonlyargcount + - The number of positional-only :term:`parameters ` + (including arguments with default values) that the function has + + * - .. attribute:: codeobject.co_kwonlyargcount + - The number of keyword-only :term:`parameters ` + (including arguments with default values) that the function has + + * - .. attribute:: codeobject.co_nlocals + - The number of :ref:`local variables ` used by the function + (including parameters) + + * - .. attribute:: codeobject.co_varnames + - A :class:`tuple` containing the names of the local variables in the + function (starting with the parameter names) + + * - .. attribute:: codeobject.co_cellvars + - A :class:`tuple` containing the names of :ref:`local variables ` + that are referenced by nested functions inside the function + + * - .. attribute:: codeobject.co_freevars + - A :class:`tuple` containing the names of free variables in the function + + * - .. attribute:: codeobject.co_code + - A string representing the sequence of :term:`bytecode` instructions in + the function + + * - .. attribute:: codeobject.co_consts + - A :class:`tuple` containing the literals used by the :term:`bytecode` in + the function + + * - .. attribute:: codeobject.co_names + - A :class:`tuple` containing the names used by the :term:`bytecode` in + the function + + * - .. attribute:: codeobject.co_filename + - The name of the file from which the code was compiled + + * - .. attribute:: codeobject.co_firstlineno + - The line number of the first line of the function + + * - .. attribute:: codeobject.co_lnotab + - A string encoding the mapping from :term:`bytecode` offsets to line + numbers. For details, see the source code of the interpreter. + + .. deprecated:: 3.12 + This attribute of code objects is deprecated, and may be removed in + Python 3.14. + + * - .. attribute:: codeobject.co_stacksize + - The required stack size of the code object + + * - .. attribute:: codeobject.co_flags + - An :class:`integer ` encoding a number of flags for the + interpreter. + +.. index:: pair: object; generator + +The following flag bits are defined for :attr:`~codeobject.co_flags`: +bit ``0x04`` is set if +the function uses the ``*arguments`` syntax to accept an arbitrary number of +positional arguments; bit ``0x08`` is set if the function uses the +``**keywords`` syntax to accept arbitrary keyword arguments; bit ``0x20`` is set +if the function is a generator. See :ref:`inspect-module-co-flags` for details +on the semantics of each flags that might be present. + +Future feature declarations (``from __future__ import division``) also use bits +in :attr:`~codeobject.co_flags` to indicate whether a code object was compiled with a +particular feature enabled: bit ``0x2000`` is set if the function was compiled +with future division enabled; bits ``0x10`` and ``0x1000`` were used in earlier +versions of Python. + +Other bits in :attr:`~codeobject.co_flags` are reserved for internal use. + +.. index:: single: documentation string + +If a code object represents a function, the first item in +:attr:`~codeobject.co_consts` is +the documentation string of the function, or ``None`` if undefined. + +Methods on code objects +~~~~~~~~~~~~~~~~~~~~~~~ + +.. method:: codeobject.co_positions() + + Returns an iterable over the source code positions of each :term:`bytecode` + instruction in the code object. + + The iterator returns :class:`tuple`\s containing the ``(start_line, end_line, + start_column, end_column)``. The *i-th* tuple corresponds to the + position of the source code that compiled to the *i-th* instruction. + Column information is 0-indexed utf-8 byte offsets on the given source + line. + + This positional information can be missing. A non-exhaustive lists of + cases where this may happen: + + - Running the interpreter with :option:`-X` ``no_debug_ranges``. + - Loading a pyc file compiled while using :option:`-X` ``no_debug_ranges``. + - Position tuples corresponding to artificial instructions. + - Line and column numbers that can't be represented due to + implementation specific limitations. + + When this occurs, some or all of the tuple elements can be + :const:`None`. + + .. versionadded:: 3.11 + + .. note:: + This feature requires storing column positions in code objects which may + result in a small increase of disk usage of compiled Python files or + interpreter memory usage. To avoid storing the extra information and/or + deactivate printing the extra traceback information, the + :option:`-X` ``no_debug_ranges`` command line flag or the :envvar:`PYTHONNODEBUGRANGES` + environment variable can be used. + +.. method:: codeobject.co_lines() + + Returns an iterator that yields information about successive ranges of + :term:`bytecode`\s. Each item yielded is a ``(start, end, lineno)`` + :class:`tuple`: + + * ``start`` (an :class:`int`) represents the offset (inclusive) of the start + of the :term:`bytecode` range + * ``end`` (an :class:`int`) represents the offset (inclusive) of the end of + the :term:`bytecode` range + * ``lineno`` is an :class:`int` representing the line number of the + :term:`bytecode` range, or ``None`` if the bytecodes in the given range + have no line number + + The items yielded generated will have the following properties: + + * The first range yielded will have a ``start`` of 0. + * The ``(start, end)`` ranges will be non-decreasing and consecutive. That + is, for any pair of :class:`tuple`\s, the ``start`` of the second will be + equal to the ``end`` of the first. + * No range will be backwards: ``end >= start`` for all triples. + * The :class:`tuple` yielded will have ``end`` equal to the size of the + :term:`bytecode`. + + Zero-width ranges, where ``start == end``, are allowed. Zero-width ranges + are used for lines that are present in the source code, but have been + eliminated by the :term:`bytecode` compiler. + + .. versionadded:: 3.10 + + .. seealso:: + + :pep:`626` - Precise line numbers for debugging and other tools. + The PEP that introduced the :meth:`!co_lines` method. + + +.. _frame-objects: + +Frame objects +^^^^^^^^^^^^^ + +.. index:: pair: object; frame + +Frame objects represent execution frames. They may occur in +:ref:`traceback objects `, +and are also passed to registered trace functions. + +.. index:: + single: f_back (frame attribute) + single: f_code (frame attribute) + single: f_globals (frame attribute) + single: f_locals (frame attribute) + single: f_lasti (frame attribute) + single: f_builtins (frame attribute) + +Special read-only attributes +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. list-table:: + + * - .. attribute:: frame.f_back + - Points to the previous stack frame (towards the caller), + or ``None`` if this is the bottom stack frame + + * - .. attribute:: frame.f_code + - The :ref:`code object ` being executed in this frame. + Accessing this attribute raises an :ref:`auditing event ` + ``object.__getattr__`` with arguments ``obj`` and ``"f_code"``. + + * - .. attribute:: frame.f_locals + - The dictionary used by the frame to look up + :ref:`local variables ` + + * - .. attribute:: frame.f_globals + - The dictionary used by the frame to look up + :ref:`global variables ` + + * - .. attribute:: frame.f_builtins + - The dictionary used by the frame to look up + :ref:`built-in (intrinsic) names ` + + * - .. attribute:: frame.f_lasti + - The "precise instruction" of the frame object + (this is an index into the :term:`bytecode` string of the + :ref:`code object `) + +.. index:: + single: f_trace (frame attribute) + single: f_trace_lines (frame attribute) + single: f_trace_opcodes (frame attribute) + single: f_lineno (frame attribute) + +Special writable attributes +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. list-table:: + + * - .. attribute:: frame.f_trace + - If not ``None``, this is a function called for various events during + code execution (this is used by debuggers). Normally an event is + triggered for each new source line (see :attr:`~frame.f_trace_lines`). + + * - .. attribute:: frame.f_trace_lines + - Set this attribute to :const:`False` to disable triggering a tracing + event for each source line. + + * - .. attribute:: frame.f_trace_opcodes + - Set this attribute to :const:`True` to allow per-opcode events to be + requested. Note that this may lead to + undefined interpreter behaviour if exceptions raised by the trace + function escape to the function being traced. + + * - .. attribute:: frame.f_lineno + - The current line number of the frame -- writing to this + from within a trace function jumps to the given line (only for the bottom-most + frame). A debugger can implement a Jump command (aka Set Next Statement) + by writing to this attribute. + +Frame object methods +~~~~~~~~~~~~~~~~~~~~ + +Frame objects support one method: + +.. method:: frame.clear() + + This method clears all references to :ref:`local variables ` held by the + frame. Also, if the frame belonged to a :term:`generator`, the generator + is finalized. This helps break reference cycles involving frame + objects (for example when catching an :ref:`exception ` + and storing its :ref:`traceback ` for later use). + + :exc:`RuntimeError` is raised if the frame is currently executing + or suspended. + + .. versionadded:: 3.4 + + .. versionchanged:: 3.13 + Attempting to clear a suspended frame raises :exc:`RuntimeError` + (as has always been the case for executing frames). + + +.. _traceback-objects: + +Traceback objects +^^^^^^^^^^^^^^^^^ + +.. index:: + pair: object; traceback + pair: stack; trace + pair: exception; handler + pair: execution; stack + single: exc_info (in module sys) + single: last_traceback (in module sys) + single: sys.exc_info + single: sys.exception + single: sys.last_traceback + +Traceback objects represent the stack trace of an :ref:`exception `. +A traceback object +is implicitly created when an exception occurs, and may also be explicitly +created by calling :class:`types.TracebackType`. + +.. versionchanged:: 3.7 + Traceback objects can now be explicitly instantiated from Python code. + +For implicitly created tracebacks, when the search for an exception handler +unwinds the execution stack, at each unwound level a traceback object is +inserted in front of the current traceback. When an exception handler is +entered, the stack trace is made available to the program. (See section +:ref:`try`.) It is accessible as the third item of the +tuple returned by :func:`sys.exc_info`, and as the +:attr:`~BaseException.__traceback__` attribute +of the caught exception. + +When the program contains no suitable +handler, the stack trace is written (nicely formatted) to the standard error +stream; if the interpreter is interactive, it is also made available to the user +as :data:`sys.last_traceback`. + +For explicitly created tracebacks, it is up to the creator of the traceback +to determine how the :attr:`~traceback.tb_next` attributes should be linked to +form a full stack trace. + +.. index:: + single: tb_frame (traceback attribute) + single: tb_lineno (traceback attribute) + single: tb_lasti (traceback attribute) + pair: statement; try + +Special read-only attributes: + +.. list-table:: + + * - .. attribute:: traceback.tb_frame + - Points to the execution :ref:`frame ` of the current + level. + + Accessing this attribute raises an + :ref:`auditing event ` ``object.__getattr__`` with arguments + ``obj`` and ``"tb_frame"``. + + * - .. attribute:: traceback.tb_lineno + - Gives the line number where the exception occurred + + * - .. attribute:: traceback.tb_lasti + - Indicates the "precise instruction". + +The line number and last instruction in the traceback may differ from the +line number of its :ref:`frame object ` if the exception +occurred in a +:keyword:`try` statement with no matching except clause or with a +:keyword:`finally` clause. + +.. index:: + single: tb_next (traceback attribute) + +.. attribute:: traceback.tb_next + + The special writable attribute :attr:`!tb_next` is the next level in the + stack trace (towards the frame where the exception occurred), or ``None`` if + there is no next level. + + .. versionchanged:: 3.7 + This attribute is now writable + + +Slice objects +^^^^^^^^^^^^^ + +.. index:: pair: built-in function; slice + +Slice objects are used to represent slices for +:meth:`~object.__getitem__` +methods. They are also created by the built-in :func:`slice` function. + +.. index:: + single: start (slice object attribute) + single: stop (slice object attribute) + single: step (slice object attribute) + +Special read-only attributes: :attr:`~slice.start` is the lower bound; +:attr:`~slice.stop` is the upper bound; :attr:`~slice.step` is the step +value; each is ``None`` if omitted. These attributes can have any type. + +Slice objects support one method: + +.. method:: slice.indices(self, length) + + This method takes a single integer argument *length* and computes + information about the slice that the slice object would describe if + applied to a sequence of *length* items. It returns a tuple of three + integers; respectively these are the *start* and *stop* indices and the + *step* or stride length of the slice. Missing or out-of-bounds indices + are handled in a manner consistent with regular slices. + + +Static method objects +^^^^^^^^^^^^^^^^^^^^^ + +Static method objects provide a way of defeating the transformation of function +objects to method objects described above. A static method object is a wrapper +around any other object, usually a user-defined method object. When a static +method object is retrieved from a class or a class instance, the object actually +returned is the wrapped object, which is not subject to any further +transformation. Static method objects are also callable. Static method +objects are created by the built-in :func:`staticmethod` constructor. + + +Class method objects +^^^^^^^^^^^^^^^^^^^^ + +A class method object, like a static method object, is a wrapper around another +object that alters the way in which that object is retrieved from classes and +class instances. The behaviour of class method objects upon such retrieval is +described above, under "User-defined methods". Class method objects are created +by the built-in :func:`classmethod` constructor. .. _specialnames: @@ -1575,7 +1876,7 @@ Basic customization This is intended to provide protection against a denial-of-service caused by carefully chosen inputs that exploit the worst case performance of a - dict insertion, O(n\ :sup:`2`) complexity. See + dict insertion, *O*\ (*n*\ :sup:`2`) complexity. See http://ocert.org/advisories/ocert-2011-003.html for details. Changing hash values affects the iteration order of sets. @@ -1645,7 +1946,8 @@ access (use of, assignment to, or deletion of ``x.name``) for class instances. .. note:: This method may still be bypassed when looking up special methods as the - result of implicit invocation via language syntax or built-in functions. + result of implicit invocation via language syntax or + :ref:`built-in functions `. See :ref:`special-lookup`. .. audit-event:: object.__getattr__ obj,name object.__getattribute__ @@ -1790,13 +2092,17 @@ class' :attr:`~object.__dict__`. Called to delete the attribute on an instance *instance* of the owner class. +Instances of descriptors may also have the :attr:`!__objclass__` attribute +present: + +.. attribute:: object.__objclass__ -The attribute :attr:`__objclass__` is interpreted by the :mod:`inspect` module -as specifying the class where this object was defined (setting this -appropriately can assist in runtime introspection of dynamic class attributes). -For callables, it may indicate that an instance of the given type (or a -subclass) is expected or required as the first positional argument (for example, -CPython sets this attribute for unbound methods that are implemented in C). + The attribute :attr:`!__objclass__` is interpreted by the :mod:`inspect` module + as specifying the class where this object was defined (setting this + appropriately can assist in runtime introspection of dynamic class attributes). + For callables, it may indicate that an instance of the given type (or a + subclass) is expected or required as the first positional argument (for example, + CPython sets this attribute for unbound methods that are implemented in C). .. _descriptor-invocation: @@ -1877,13 +2183,14 @@ For instance bindings, the precedence of descriptor invocation depends on which descriptor methods are defined. A descriptor can define any combination of :meth:`~object.__get__`, :meth:`~object.__set__` and :meth:`~object.__delete__`. If it does not -define :meth:`__get__`, then accessing the attribute will return the descriptor +define :meth:`!__get__`, then accessing the attribute will return the descriptor object itself unless there is a value in the object's instance dictionary. If -the descriptor defines :meth:`__set__` and/or :meth:`__delete__`, it is a data +the descriptor defines :meth:`!__set__` and/or :meth:`!__delete__`, it is a data descriptor; if it defines neither, it is a non-data descriptor. Normally, data -descriptors define both :meth:`__get__` and :meth:`__set__`, while non-data -descriptors have just the :meth:`__get__` method. Data descriptors with -:meth:`__get__` and :meth:`__set__` (and/or :meth:`__delete__`) defined always override a redefinition in an +descriptors define both :meth:`!__get__` and :meth:`!__set__`, while non-data +descriptors have just the :meth:`!__get__` method. Data descriptors with +:meth:`!__get__` and :meth:`!__set__` (and/or :meth:`!__delete__`) defined +always override a redefinition in an instance dictionary. In contrast, non-data descriptors can be overridden by instances. @@ -1920,8 +2227,7 @@ Attribute lookup speed can be significantly improved as well. .. _datamodel-note-slots: -Notes on using *__slots__* -"""""""""""""""""""""""""" +Notes on using *__slots__*: * When inheriting from a class without *__slots__*, the :attr:`~object.__dict__` and @@ -2461,16 +2767,17 @@ either to emulate a sequence or to emulate a mapping; the difference is that for a sequence, the allowable keys should be the integers *k* for which ``0 <= k < N`` where *N* is the length of the sequence, or :class:`slice` objects, which define a range of items. It is also recommended that mappings provide the methods -:meth:`keys`, :meth:`values`, :meth:`items`, :meth:`get`, :meth:`clear`, -:meth:`setdefault`, :meth:`pop`, :meth:`popitem`, :meth:`!copy`, and -:meth:`update` behaving similar to those for Python's standard :class:`dictionary ` +:meth:`!keys`, :meth:`!values`, :meth:`!items`, :meth:`!get`, :meth:`!clear`, +:meth:`!setdefault`, :meth:`!pop`, :meth:`!popitem`, :meth:`!copy`, and +:meth:`!update` behaving similar to those for Python's standard :class:`dictionary ` objects. The :mod:`collections.abc` module provides a :class:`~collections.abc.MutableMapping` :term:`abstract base class` to help create those methods from a base set of -:meth:`~object.__getitem__`, :meth:`~object.__setitem__`, :meth:`~object.__delitem__`, and :meth:`keys`. -Mutable sequences should provide methods :meth:`append`, :meth:`count`, -:meth:`index`, :meth:`extend`, :meth:`insert`, :meth:`pop`, :meth:`remove`, -:meth:`reverse` and :meth:`sort`, like Python standard :class:`list` +:meth:`~object.__getitem__`, :meth:`~object.__setitem__`, +:meth:`~object.__delitem__`, and :meth:`!keys`. +Mutable sequences should provide methods :meth:`!append`, :meth:`!count`, +:meth:`!index`, :meth:`!extend`, :meth:`!insert`, :meth:`!pop`, :meth:`!remove`, +:meth:`!reverse` and :meth:`!sort`, like Python standard :class:`list` objects. Finally, sequence types should implement addition (meaning concatenation) and multiplication (meaning repetition) by defining the methods @@ -2483,7 +2790,7 @@ operator; for mappings, ``in`` should search the mapping's keys; for sequences, it should search through the values. It is further recommended that both mappings and sequences implement the :meth:`~object.__iter__` method to allow efficient iteration -through the container; for mappings, :meth:`__iter__` should iterate +through the container; for mappings, :meth:`!__iter__` should iterate through the object's keys; for sequences, it should iterate through the values. .. method:: object.__len__(self) @@ -2536,10 +2843,10 @@ through the object's keys; for sequences, it should iterate through the values. .. method:: object.__getitem__(self, key) Called to implement evaluation of ``self[key]``. For :term:`sequence` types, - the accepted keys should be integers and slice objects. Note that the - special interpretation of negative indexes (if the class wishes to emulate a - :term:`sequence` type) is up to the :meth:`__getitem__` method. If *key* is - of an inappropriate type, :exc:`TypeError` may be raised; if of a value + the accepted keys should be integers. Optionally, they may support + :class:`slice` objects as well. Negative index support is also optional. + If *key* is + of an inappropriate type, :exc:`TypeError` may be raised; if *key* is a value outside the set of indexes for the sequence (after any special interpretation of negative values), :exc:`IndexError` should be raised. For :term:`mapping` types, if *key* is missing (not in the container), @@ -2834,7 +3141,7 @@ For more information on context managers, see :ref:`typecontextmanager`. (i.e., prevent it from being propagated), it should return a true value. Otherwise, the exception will be processed normally upon exit from this method. - Note that :meth:`__exit__` methods should not reraise the passed-in exception; + Note that :meth:`~object.__exit__` methods should not reraise the passed-in exception; this is the caller's responsibility. @@ -3062,7 +3369,7 @@ generators, coroutines do not directly support iteration. to the :meth:`~generator.send` method of the iterator that caused the coroutine to suspend. The result (return value, :exc:`StopIteration`, or other exception) is the same as when - iterating over the :meth:`__await__` return value, described above. + iterating over the :meth:`!__await__` return value, described above. .. method:: coroutine.throw(value) coroutine.throw(type[, value[, traceback]]) @@ -3152,12 +3459,12 @@ Asynchronous context managers can be used in an :keyword:`async with` statement. .. method:: object.__aenter__(self) - Semantically similar to :meth:`__enter__`, the only + Semantically similar to :meth:`~object.__enter__`, the only difference being that it must return an *awaitable*. .. method:: object.__aexit__(self, exc_type, exc_value, traceback) - Semantically similar to :meth:`__exit__`, the only + Semantically similar to :meth:`~object.__exit__`, the only difference being that it must return an *awaitable*. An example of an asynchronous context manager class:: diff --git a/Doc/reference/expressions.rst b/Doc/reference/expressions.rst index 8e0346ccc718de..3f6d5bfafee9d1 100644 --- a/Doc/reference/expressions.rst +++ b/Doc/reference/expressions.rst @@ -499,8 +499,8 @@ the yield expression. It can be either set explicitly when raising :exc:`StopIteration`, or automatically when the subiterator is a generator (by returning a value from the subgenerator). - .. versionchanged:: 3.3 - Added ``yield from `` to delegate control flow to a subiterator. +.. versionchanged:: 3.3 + Added ``yield from `` to delegate control flow to a subiterator. The parentheses may be omitted when the yield expression is the sole expression on the right hand side of an assignment statement. @@ -823,12 +823,18 @@ An attribute reference is a primary followed by a period and a name: The primary must evaluate to an object of a type that supports attribute references, which most objects do. This object is then asked to produce the -attribute whose name is the identifier. This production can be customized by -overriding the :meth:`__getattr__` method. If this attribute is not available, -the exception :exc:`AttributeError` is raised. Otherwise, the type and value of -the object produced is determined by the object. Multiple evaluations of the -same attribute reference may yield different objects. +attribute whose name is the identifier. The type and value produced is +determined by the object. Multiple evaluations of the same attribute +reference may yield different objects. +This production can be customized by overriding the +:meth:`~object.__getattribute__` method or the :meth:`~object.__getattr__` +method. The :meth:`!__getattribute__` method is called first and either +returns a value or raises :exc:`AttributeError` if the attribute is not +available. + +If an :exc:`AttributeError` is raised and the object has a :meth:`!__getattr__` +method, that method is called as a fallback. .. _subscriptions: @@ -889,7 +895,7 @@ to the index so that, for example, ``x[-1]`` selects the last item of ``x``. The resulting value must be a nonnegative integer less than the number of items in the sequence, and the subscription selects the item whose index is that value (counting from zero). Since the support for negative indices and slicing -occurs in the object's :meth:`__getitem__` method, subclasses overriding +occurs in the object's :meth:`~object.__getitem__` method, subclasses overriding this method will need to explicitly add that support. .. index:: @@ -944,7 +950,7 @@ slice list contains no proper slice). single: step (slice object attribute) The semantics for a slicing are as follows. The primary is indexed (using the -same :meth:`__getitem__` method as +same :meth:`~object.__getitem__` method as normal subscription) with a key that is constructed from the slice list, as follows. If the slice list contains at least one comma, the key is a tuple containing the conversion of the slice items; otherwise, the conversion of the @@ -1670,7 +1676,7 @@ If an exception is raised during the iteration, it is as if :keyword:`in` raised that exception. Lastly, the old-style iteration protocol is tried: if a class defines -:meth:`__getitem__`, ``x in y`` is ``True`` if and only if there is a non-negative +:meth:`~object.__getitem__`, ``x in y`` is ``True`` if and only if there is a non-negative integer index *i* such that ``x is y[i] or x == y[i]``, and no lower integer index raises the :exc:`IndexError` exception. (If any other exception is raised, it is as if :keyword:`in` raised that exception). @@ -1781,10 +1787,11 @@ Or, when processing a file stream in chunks: while chunk := file.read(9000): process(chunk) -Assignment expressions must be surrounded by parentheses when used -as sub-expressions in slicing, conditional, lambda, -keyword-argument, and comprehension-if expressions -and in ``assert`` and ``with`` statements. +Assignment expressions must be surrounded by parentheses when +used as expression statements and when used as sub-expressions in +slicing, conditional, lambda, +keyword-argument, and comprehension-if expressions and +in ``assert``, ``with``, and ``assignment`` statements. In all other places where they can be used, parentheses are not required, including in ``if`` and ``while`` statements. diff --git a/Doc/reference/grammar.rst b/Doc/reference/grammar.rst index bc1db7b039cd5a..b9cca4444c9141 100644 --- a/Doc/reference/grammar.rst +++ b/Doc/reference/grammar.rst @@ -1,3 +1,5 @@ +.. _full-grammar-specification: + Full Grammar specification ========================== diff --git a/Doc/reference/import.rst b/Doc/reference/import.rst index 0f416a5c583f85..a7beeea29b4556 100644 --- a/Doc/reference/import.rst +++ b/Doc/reference/import.rst @@ -375,32 +375,32 @@ of what happens during the loading portion of import:: Note the following details: - * If there is an existing module object with the given name in - :data:`sys.modules`, import will have already returned it. +* If there is an existing module object with the given name in + :data:`sys.modules`, import will have already returned it. - * The module will exist in :data:`sys.modules` before the loader - executes the module code. This is crucial because the module code may - (directly or indirectly) import itself; adding it to :data:`sys.modules` - beforehand prevents unbounded recursion in the worst case and multiple - loading in the best. +* The module will exist in :data:`sys.modules` before the loader + executes the module code. This is crucial because the module code may + (directly or indirectly) import itself; adding it to :data:`sys.modules` + beforehand prevents unbounded recursion in the worst case and multiple + loading in the best. - * If loading fails, the failing module -- and only the failing module -- - gets removed from :data:`sys.modules`. Any module already in the - :data:`sys.modules` cache, and any module that was successfully loaded - as a side-effect, must remain in the cache. This contrasts with - reloading where even the failing module is left in :data:`sys.modules`. +* If loading fails, the failing module -- and only the failing module -- + gets removed from :data:`sys.modules`. Any module already in the + :data:`sys.modules` cache, and any module that was successfully loaded + as a side-effect, must remain in the cache. This contrasts with + reloading where even the failing module is left in :data:`sys.modules`. - * After the module is created but before execution, the import machinery - sets the import-related module attributes ("_init_module_attrs" in - the pseudo-code example above), as summarized in a - :ref:`later section `. +* After the module is created but before execution, the import machinery + sets the import-related module attributes ("_init_module_attrs" in + the pseudo-code example above), as summarized in a + :ref:`later section `. - * Module execution is the key moment of loading in which the module's - namespace gets populated. Execution is entirely delegated to the - loader, which gets to decide what gets populated and how. +* Module execution is the key moment of loading in which the module's + namespace gets populated. Execution is entirely delegated to the + loader, which gets to decide what gets populated and how. - * The module created during loading and passed to exec_module() may - not be the one returned at the end of import [#fnlo]_. +* The module created during loading and passed to exec_module() may + not be the one returned at the end of import [#fnlo]_. .. versionchanged:: 3.4 The import system has taken over the boilerplate responsibilities of @@ -417,13 +417,13 @@ returned from :meth:`~importlib.abc.Loader.exec_module` is ignored. Loaders must satisfy the following requirements: - * If the module is a Python module (as opposed to a built-in module or a - dynamically loaded extension), the loader should execute the module's code - in the module's global name space (``module.__dict__``). +* If the module is a Python module (as opposed to a built-in module or a + dynamically loaded extension), the loader should execute the module's code + in the module's global name space (``module.__dict__``). - * If the loader cannot execute the module, it should raise an - :exc:`ImportError`, although any other exception raised during - :meth:`~importlib.abc.Loader.exec_module` will be propagated. +* If the loader cannot execute the module, it should raise an + :exc:`ImportError`, although any other exception raised during + :meth:`~importlib.abc.Loader.exec_module` will be propagated. In many cases, the finder and loader can be the same object; in such cases the :meth:`~importlib.abc.MetaPathFinder.find_spec` method would just return a @@ -453,20 +453,20 @@ import machinery will create the new module itself. functionality described above in addition to executing the module. All the same constraints apply, with some additional clarification: - * If there is an existing module object with the given name in - :data:`sys.modules`, the loader must use that existing module. - (Otherwise, :func:`importlib.reload` will not work correctly.) If the - named module does not exist in :data:`sys.modules`, the loader - must create a new module object and add it to :data:`sys.modules`. + * If there is an existing module object with the given name in + :data:`sys.modules`, the loader must use that existing module. + (Otherwise, :func:`importlib.reload` will not work correctly.) If the + named module does not exist in :data:`sys.modules`, the loader + must create a new module object and add it to :data:`sys.modules`. - * The module *must* exist in :data:`sys.modules` before the loader - executes the module code, to prevent unbounded recursion or multiple - loading. + * The module *must* exist in :data:`sys.modules` before the loader + executes the module code, to prevent unbounded recursion or multiple + loading. - * If loading fails, the loader must remove any modules it has inserted - into :data:`sys.modules`, but it must remove **only** the failing - module(s), and only if the loader itself has loaded the module(s) - explicitly. + * If loading fails, the loader must remove any modules it has inserted + into :data:`sys.modules`, but it must remove **only** the failing + module(s), and only if the loader itself has loaded the module(s) + explicitly. .. versionchanged:: 3.5 A :exc:`DeprecationWarning` is raised when ``exec_module()`` is defined but @@ -559,7 +559,7 @@ listed below. functionality, for example getting data associated with a loader. It is **strongly** recommended that you rely on :attr:`__spec__` - instead instead of this attribute. + instead of this attribute. .. versionchanged:: 3.12 The value of ``__loader__`` is expected to be the same as @@ -580,7 +580,7 @@ listed below. relative imports for main modules, as defined in :pep:`366`. It is **strongly** recommended that you rely on :attr:`__spec__` - instead instead of this attribute. + instead of this attribute. .. versionchanged:: 3.6 The value of ``__package__`` is expected to be the same as @@ -650,7 +650,7 @@ listed below. from a file, that atypical scenario may be appropriate. It is **strongly** recommended that you rely on :attr:`__spec__` - instead instead of ``__cached__``. + instead of ``__cached__``. .. _package-path-rules: @@ -693,17 +693,17 @@ with defaults for whatever information is missing. Here are the exact rules used: - * If the module has a ``__spec__`` attribute, the information in the spec - is used to generate the repr. The "name", "loader", "origin", and - "has_location" attributes are consulted. +* If the module has a ``__spec__`` attribute, the information in the spec + is used to generate the repr. The "name", "loader", "origin", and + "has_location" attributes are consulted. - * If the module has a ``__file__`` attribute, this is used as part of the - module's repr. +* If the module has a ``__file__`` attribute, this is used as part of the + module's repr. - * If the module has no ``__file__`` but does have a ``__loader__`` that is not - ``None``, then the loader's repr is used as part of the module's repr. +* If the module has no ``__file__`` but does have a ``__loader__`` that is not + ``None``, then the loader's repr is used as part of the module's repr. - * Otherwise, just use the module's ``__name__`` in the repr. +* Otherwise, just use the module's ``__name__`` in the repr. .. versionchanged:: 3.12 Use of :meth:`!module_repr`, having been deprecated since Python 3.4, was diff --git a/Doc/reference/introduction.rst b/Doc/reference/introduction.rst index 81f0a5c5d43883..cf186705e6e987 100644 --- a/Doc/reference/introduction.rst +++ b/Doc/reference/introduction.rst @@ -90,7 +90,8 @@ Notation .. index:: BNF, grammar, syntax, notation -The descriptions of lexical analysis and syntax use a modified BNF grammar +The descriptions of lexical analysis and syntax use a modified +`Backus–Naur form (BNF) `_ grammar notation. This uses the following style of definition: .. productionlist:: notation diff --git a/Doc/reference/lexical_analysis.rst b/Doc/reference/lexical_analysis.rst index 83cd4402a36cf6..0adfb0365934e4 100644 --- a/Doc/reference/lexical_analysis.rst +++ b/Doc/reference/lexical_analysis.rst @@ -315,7 +315,7 @@ The Unicode category codes mentioned above stand for: * *Nd* - decimal numbers * *Pc* - connector punctuations * *Other_ID_Start* - explicit list of characters in `PropList.txt - `_ to support backwards + `_ to support backwards compatibility * *Other_ID_Continue* - likewise @@ -323,8 +323,8 @@ All identifiers are converted into the normal form NFKC while parsing; compariso of identifiers is based on NFKC. A non-normative HTML file listing all valid identifier characters for Unicode -15.0.0 can be found at -https://www.unicode.org/Public/15.0.0/ucd/DerivedCoreProperties.txt +15.1.0 can be found at +https://www.unicode.org/Public/15.1.0/ucd/DerivedCoreProperties.txt .. _keywords: @@ -557,51 +557,51 @@ Unless an ``'r'`` or ``'R'`` prefix is present, escape sequences in string and bytes literals are interpreted according to rules similar to those used by Standard C. The recognized escape sequences are: -+-----------------+---------------------------------+-------+ -| Escape Sequence | Meaning | Notes | -+=================+=================================+=======+ -| ``\``\ | Backslash and newline ignored | \(1) | -+-----------------+---------------------------------+-------+ -| ``\\`` | Backslash (``\``) | | -+-----------------+---------------------------------+-------+ -| ``\'`` | Single quote (``'``) | | -+-----------------+---------------------------------+-------+ -| ``\"`` | Double quote (``"``) | | -+-----------------+---------------------------------+-------+ -| ``\a`` | ASCII Bell (BEL) | | -+-----------------+---------------------------------+-------+ -| ``\b`` | ASCII Backspace (BS) | | -+-----------------+---------------------------------+-------+ -| ``\f`` | ASCII Formfeed (FF) | | -+-----------------+---------------------------------+-------+ -| ``\n`` | ASCII Linefeed (LF) | | -+-----------------+---------------------------------+-------+ -| ``\r`` | ASCII Carriage Return (CR) | | -+-----------------+---------------------------------+-------+ -| ``\t`` | ASCII Horizontal Tab (TAB) | | -+-----------------+---------------------------------+-------+ -| ``\v`` | ASCII Vertical Tab (VT) | | -+-----------------+---------------------------------+-------+ -| ``\ooo`` | Character with octal value | (2,4) | -| | *ooo* | | -+-----------------+---------------------------------+-------+ -| ``\xhh`` | Character with hex value *hh* | (3,4) | -+-----------------+---------------------------------+-------+ ++-------------------------+---------------------------------+-------+ +| Escape Sequence | Meaning | Notes | ++=========================+=================================+=======+ +| ``\``\ | Backslash and newline ignored | \(1) | ++-------------------------+---------------------------------+-------+ +| ``\\`` | Backslash (``\``) | | ++-------------------------+---------------------------------+-------+ +| ``\'`` | Single quote (``'``) | | ++-------------------------+---------------------------------+-------+ +| ``\"`` | Double quote (``"``) | | ++-------------------------+---------------------------------+-------+ +| ``\a`` | ASCII Bell (BEL) | | ++-------------------------+---------------------------------+-------+ +| ``\b`` | ASCII Backspace (BS) | | ++-------------------------+---------------------------------+-------+ +| ``\f`` | ASCII Formfeed (FF) | | ++-------------------------+---------------------------------+-------+ +| ``\n`` | ASCII Linefeed (LF) | | ++-------------------------+---------------------------------+-------+ +| ``\r`` | ASCII Carriage Return (CR) | | ++-------------------------+---------------------------------+-------+ +| ``\t`` | ASCII Horizontal Tab (TAB) | | ++-------------------------+---------------------------------+-------+ +| ``\v`` | ASCII Vertical Tab (VT) | | ++-------------------------+---------------------------------+-------+ +| :samp:`\\\\{ooo}` | Character with octal value | (2,4) | +| | *ooo* | | ++-------------------------+---------------------------------+-------+ +| :samp:`\\x{hh}` | Character with hex value *hh* | (3,4) | ++-------------------------+---------------------------------+-------+ Escape sequences only recognized in string literals are: -+-----------------+---------------------------------+-------+ -| Escape Sequence | Meaning | Notes | -+=================+=================================+=======+ -| ``\N{name}`` | Character named *name* in the | \(5) | -| | Unicode database | | -+-----------------+---------------------------------+-------+ -| ``\uxxxx`` | Character with 16-bit hex value | \(6) | -| | *xxxx* | | -+-----------------+---------------------------------+-------+ -| ``\Uxxxxxxxx`` | Character with 32-bit hex value | \(7) | -| | *xxxxxxxx* | | -+-----------------+---------------------------------+-------+ ++-------------------------+---------------------------------+-------+ +| Escape Sequence | Meaning | Notes | ++=========================+=================================+=======+ +| :samp:`\\N\\{{name}\\}` | Character named *name* in the | \(5) | +| | Unicode database | | ++-------------------------+---------------------------------+-------+ +| :samp:`\\u{xxxx}` | Character with 16-bit hex value | \(6) | +| | *xxxx* | | ++-------------------------+---------------------------------+-------+ +| :samp:`\\U{xxxxxxxx}` | Character with 32-bit hex value | \(7) | +| | *xxxxxxxx* | | ++-------------------------+---------------------------------+-------+ Notes: @@ -657,12 +657,12 @@ is more easily recognized as broken.) It is also important to note that the escape sequences only recognized in string literals fall into the category of unrecognized escapes for bytes literals. - .. versionchanged:: 3.6 - Unrecognized escape sequences produce a :exc:`DeprecationWarning`. +.. versionchanged:: 3.6 + Unrecognized escape sequences produce a :exc:`DeprecationWarning`. - .. versionchanged:: 3.12 - Unrecognized escape sequences produce a :exc:`SyntaxWarning`. In a future - Python version they will be eventually a :exc:`SyntaxError`. +.. versionchanged:: 3.12 + Unrecognized escape sequences produce a :exc:`SyntaxWarning`. In a future + Python version they will be eventually a :exc:`SyntaxError`. Even in a raw literal, quotes can be escaped with a backslash, but the backslash remains in the result; for example, ``r"\""`` is a valid string @@ -708,10 +708,12 @@ and formatted string literals may be concatenated with plain string literals. single: ! (exclamation); in formatted string literal single: : (colon); in formatted string literal single: = (equals); for help in debugging using string literals + .. _f-strings: +.. _formatted-string-literals: -Formatted string literals -------------------------- +f-strings +--------- .. versionadded:: 3.6 @@ -1045,4 +1047,4 @@ occurrence outside string literals and comments is an unconditional error: .. rubric:: Footnotes -.. [#] https://www.unicode.org/Public/15.0.0/ucd/NameAliases.txt +.. [#] https://www.unicode.org/Public/15.1.0/ucd/NameAliases.txt diff --git a/Doc/reference/simple_stmts.rst b/Doc/reference/simple_stmts.rst index a9e65be1eda340..04132c78ce77a6 100644 --- a/Doc/reference/simple_stmts.rst +++ b/Doc/reference/simple_stmts.rst @@ -214,7 +214,7 @@ Assignment of an object to a single target is recursively defined as follows. object. This can either replace an existing key/value pair with the same key value, or insert a new key/value pair (if no key with the same value existed). - For user-defined objects, the :meth:`__setitem__` method is called with + For user-defined objects, the :meth:`~object.__setitem__` method is called with appropriate arguments. .. index:: pair: slicing; assignment @@ -351,7 +351,7 @@ If the right hand side is present, an annotated assignment performs the actual assignment before evaluating annotations (where applicable). If the right hand side is not present for an expression target, then the interpreter evaluates the target except for the last -:meth:`__setitem__` or :meth:`__setattr__` call. +:meth:`~object.__setitem__` or :meth:`~object.__setattr__` call. .. seealso:: @@ -578,7 +578,7 @@ The :dfn:`type` of the exception is the exception instance's class, the .. index:: pair: object; traceback A traceback object is normally created automatically when an exception is raised -and attached to it as the :attr:`__traceback__` attribute, which is writable. +and attached to it as the :attr:`~BaseException.__traceback__` attribute. You can create an exception and set your own traceback in one step using the :meth:`~BaseException.with_traceback` exception method (which returns the same exception instance, with its traceback set to its argument), like so:: @@ -592,11 +592,13 @@ same exception instance, with its traceback set to its argument), like so:: The ``from`` clause is used for exception chaining: if given, the second *expression* must be another exception class or instance. If the second expression is an exception instance, it will be attached to the raised -exception as the :attr:`__cause__` attribute (which is writable). If the +exception as the :attr:`~BaseException.__cause__` attribute (which is writable). If the expression is an exception class, the class will be instantiated and the resulting exception instance will be attached to the raised exception as the -:attr:`__cause__` attribute. If the raised exception is not handled, both -exceptions will be printed:: +:attr:`!__cause__` attribute. If the raised exception is not handled, both +exceptions will be printed: + +.. code-block:: pycon >>> try: ... print(1 / 0) @@ -605,19 +607,24 @@ exceptions will be printed:: ... Traceback (most recent call last): File "", line 2, in + print(1 / 0) + ~~^~~ ZeroDivisionError: division by zero The above exception was the direct cause of the following exception: Traceback (most recent call last): File "", line 4, in + raise RuntimeError("Something bad happened") from exc RuntimeError: Something bad happened A similar mechanism works implicitly if a new exception is raised when an exception is already being handled. An exception may be handled when an :keyword:`except` or :keyword:`finally` clause, or a :keyword:`with` statement, is used. The previous exception is then -attached as the new exception's :attr:`__context__` attribute:: +attached as the new exception's :attr:`~BaseException.__context__` attribute: + +.. code-block:: pycon >>> try: ... print(1 / 0) @@ -626,16 +633,21 @@ attached as the new exception's :attr:`__context__` attribute:: ... Traceback (most recent call last): File "", line 2, in + print(1 / 0) + ~~^~~ ZeroDivisionError: division by zero During handling of the above exception, another exception occurred: Traceback (most recent call last): File "", line 4, in + raise RuntimeError("Something bad happened") RuntimeError: Something bad happened Exception chaining can be explicitly suppressed by specifying :const:`None` in -the ``from`` clause:: +the ``from`` clause: + +.. doctest:: >>> try: ... print(1 / 0) @@ -653,8 +665,8 @@ and information about handling exceptions is in section :ref:`try`. :const:`None` is now permitted as ``Y`` in ``raise X from Y``. .. versionadded:: 3.3 - The ``__suppress_context__`` attribute to suppress automatic display of the - exception context. + The :attr:`~BaseException.__suppress_context__` attribute to suppress + automatic display of the exception context. .. versionchanged:: 3.11 If the traceback of the active exception is modified in an :keyword:`except` @@ -920,7 +932,7 @@ That is not a future statement; it's an ordinary import statement with no special semantics or syntax restrictions. Code compiled by calls to the built-in functions :func:`exec` and :func:`compile` -that occur in a module :mod:`M` containing a future statement will, by default, +that occur in a module :mod:`!M` containing a future statement will, by default, use the new syntax or semantics associated with the future statement. This can be controlled by optional arguments to :func:`compile` --- see the documentation of that function for details. diff --git a/Doc/requirements-oldest-sphinx.txt b/Doc/requirements-oldest-sphinx.txt index 94611ca22f09fe..597341d99ffeaa 100644 --- a/Doc/requirements-oldest-sphinx.txt +++ b/Doc/requirements-oldest-sphinx.txt @@ -7,32 +7,29 @@ blurb python-docs-theme>=2022.1 # Generated from: -# pip install "Sphinx~=3.2.0" "docutils<0.17" "Jinja2<3" "MarkupSafe<2" +# pip install "Sphinx~=4.2.0" # pip freeze # -# Sphinx 3.2 comes from ``needs_sphinx = '3.2'`` in ``Doc/conf.py``. -# Docutils<0.17, Jinja2<3, and MarkupSafe<2 are additionally specified as -# Sphinx 3.2 is incompatible with newer releases of these packages. +# Sphinx 4.2 comes from ``needs_sphinx = '4.2'`` in ``Doc/conf.py``. alabaster==0.7.13 -Babel==2.12.1 +Babel==2.13.0 certifi==2023.7.22 -charset-normalizer==3.2.0 -colorama==0.4.6 -docutils==0.16 +charset-normalizer==3.3.0 +docutils==0.17.1 idna==3.4 imagesize==1.4.1 -Jinja2==2.11.3 -MarkupSafe==1.1.1 -packaging==23.1 -Pygments==2.15.1 +Jinja2==3.1.2 +MarkupSafe==2.1.3 +packaging==23.2 +Pygments==2.16.1 requests==2.31.0 snowballstemmer==2.2.0 -Sphinx==3.2.1 +Sphinx==4.2.0 sphinxcontrib-applehelp==1.0.4 sphinxcontrib-devhelp==1.0.2 sphinxcontrib-htmlhelp==2.0.1 sphinxcontrib-jsmath==1.0.1 sphinxcontrib-qthelp==1.0.3 sphinxcontrib-serializinghtml==1.1.5 -urllib3==2.0.4 +urllib3==2.0.7 diff --git a/Doc/requirements.txt b/Doc/requirements.txt index e9b6e56b122895..04334fd5a464d4 100644 --- a/Doc/requirements.txt +++ b/Doc/requirements.txt @@ -11,10 +11,12 @@ sphinx==6.2.1 blurb +sphinx-autobuild sphinxext-opengraph==0.7.5 +sphinx-notfound-page==1.0.0 # The theme used by the documentation is stored separately, so we need # to install that as well. -python-docs-theme>=2023.7 +python-docs-theme>=2023.3.1,!=2023.7 -c constraints.txt diff --git a/Doc/tools/.nitignore b/Doc/tools/.nitignore index df7dcd607489c8..d80af40bbdca4c 100644 --- a/Doc/tools/.nitignore +++ b/Doc/tools/.nitignore @@ -2,8 +2,6 @@ # as tested on the CI via check-warnings.py in reusable-docs.yml. # Keep lines sorted lexicographically to help avoid merge conflicts. -Doc/c-api/buffer.rst -Doc/c-api/datetime.rst Doc/c-api/descriptor.rst Doc/c-api/exceptions.rst Doc/c-api/file.rst @@ -16,61 +14,32 @@ Doc/c-api/memory.rst Doc/c-api/memoryview.rst Doc/c-api/module.rst Doc/c-api/object.rst -Doc/c-api/set.rst Doc/c-api/stable.rst Doc/c-api/structures.rst Doc/c-api/sys.rst Doc/c-api/type.rst Doc/c-api/typeobj.rst -Doc/c-api/unicode.rst Doc/extending/extending.rst -Doc/extending/newtypes.rst -Doc/faq/design.rst -Doc/faq/gui.rst -Doc/faq/library.rst -Doc/faq/programming.rst Doc/glossary.rst Doc/howto/descriptor.rst Doc/howto/enum.rst -Doc/howto/isolating-extensions.rst -Doc/howto/logging-cookbook.rst Doc/howto/logging.rst Doc/howto/urllib2.rst -Doc/library/__future__.rst -Doc/library/abc.rst Doc/library/ast.rst -Doc/library/asyncio-dev.rst -Doc/library/asyncio-eventloop.rst Doc/library/asyncio-extending.rst Doc/library/asyncio-policy.rst -Doc/library/asyncio-stream.rst Doc/library/asyncio-subprocess.rst Doc/library/asyncio-task.rst Doc/library/bdb.rst -Doc/library/bisect.rst -Doc/library/bz2.rst -Doc/library/calendar.rst -Doc/library/cmd.rst -Doc/library/codecs.rst -Doc/library/collections.abc.rst Doc/library/collections.rst Doc/library/concurrent.futures.rst -Doc/library/configparser.rst -Doc/library/contextlib.rst -Doc/library/copy.rst Doc/library/csv.rst -Doc/library/ctypes.rst Doc/library/datetime.rst Doc/library/dbm.rst Doc/library/decimal.rst -Doc/library/devmode.rst -Doc/library/difflib.rst -Doc/library/dis.rst -Doc/library/doctest.rst Doc/library/email.charset.rst Doc/library/email.compat32-message.rst Doc/library/email.errors.rst -Doc/library/email.headerregistry.rst Doc/library/email.mime.rst Doc/library/email.parser.rst Doc/library/email.policy.rst @@ -79,111 +48,64 @@ Doc/library/exceptions.rst Doc/library/faulthandler.rst Doc/library/fcntl.rst Doc/library/ftplib.rst -Doc/library/functions.rst Doc/library/functools.rst -Doc/library/getpass.rst -Doc/library/gettext.rst -Doc/library/gzip.rst Doc/library/http.client.rst Doc/library/http.cookiejar.rst -Doc/library/http.cookies.rst Doc/library/http.server.rst -Doc/library/importlib.resources.rst Doc/library/importlib.rst -Doc/library/inspect.rst -Doc/library/io.rst Doc/library/locale.rst Doc/library/logging.config.rst Doc/library/logging.handlers.rst -Doc/library/logging.rst Doc/library/lzma.rst -Doc/library/mailbox.rst Doc/library/mmap.rst Doc/library/multiprocessing.rst Doc/library/multiprocessing.shared_memory.rst -Doc/library/numbers.rst Doc/library/optparse.rst -Doc/library/os.path.rst Doc/library/os.rst Doc/library/pickle.rst Doc/library/pickletools.rst Doc/library/platform.rst Doc/library/plistlib.rst Doc/library/profile.rst -Doc/library/pyclbr.rst Doc/library/pydoc.rst Doc/library/pyexpat.rst -Doc/library/random.rst Doc/library/readline.rst -Doc/library/reprlib.rst Doc/library/resource.rst -Doc/library/rlcompleter.rst Doc/library/select.rst -Doc/library/selectors.rst -Doc/library/shelve.rst Doc/library/signal.rst -Doc/library/site.rst Doc/library/smtplib.rst Doc/library/socket.rst -Doc/library/socketserver.rst Doc/library/ssl.rst Doc/library/stdtypes.rst -Doc/library/string.rst Doc/library/subprocess.rst -Doc/library/sys.rst -Doc/library/sys_path_init.rst -Doc/library/syslog.rst -Doc/library/tarfile.rst -Doc/library/tempfile.rst Doc/library/termios.rst Doc/library/test.rst -Doc/library/threading.rst -Doc/library/time.rst Doc/library/tkinter.rst Doc/library/tkinter.scrolledtext.rst Doc/library/tkinter.ttk.rst -Doc/library/traceback.rst -Doc/library/tty.rst -Doc/library/turtle.rst -Doc/library/unittest.mock-examples.rst Doc/library/unittest.mock.rst Doc/library/unittest.rst Doc/library/urllib.parse.rst Doc/library/urllib.request.rst -Doc/library/uuid.rst -Doc/library/weakref.rst Doc/library/wsgiref.rst Doc/library/xml.dom.minidom.rst Doc/library/xml.dom.pulldom.rst Doc/library/xml.dom.rst -Doc/library/xml.etree.elementtree.rst -Doc/library/xml.rst Doc/library/xml.sax.handler.rst Doc/library/xml.sax.reader.rst Doc/library/xml.sax.rst Doc/library/xmlrpc.client.rst Doc/library/xmlrpc.server.rst Doc/library/zlib.rst -Doc/license.rst Doc/reference/compound_stmts.rst Doc/reference/datamodel.rst Doc/reference/expressions.rst Doc/reference/import.rst -Doc/reference/simple_stmts.rst -Doc/tutorial/appendix.rst -Doc/tutorial/classes.rst -Doc/tutorial/controlflow.rst Doc/tutorial/datastructures.rst -Doc/tutorial/inputoutput.rst -Doc/tutorial/introduction.rst -Doc/tutorial/modules.rst -Doc/using/cmdline.rst -Doc/using/configure.rst Doc/using/windows.rst Doc/whatsnew/2.0.rst Doc/whatsnew/2.1.rst Doc/whatsnew/2.2.rst -Doc/whatsnew/2.3.rst Doc/whatsnew/2.4.rst Doc/whatsnew/2.5.rst Doc/whatsnew/2.6.rst diff --git a/Doc/tools/check-warnings.py b/Doc/tools/check-warnings.py index c17d0f51cd1272..809a8d63087e12 100644 --- a/Doc/tools/check-warnings.py +++ b/Doc/tools/check-warnings.py @@ -2,12 +2,16 @@ """ Check the output of running Sphinx in nit-picky mode (missing references). """ +from __future__ import annotations + import argparse -import csv +import itertools import os import re +import subprocess import sys from pathlib import Path +from typing import TextIO # Exclude these whether they're dirty or clean, # because they trigger a rebuild of dirty files. @@ -24,28 +28,178 @@ "venv", } -PATTERN = re.compile(r"(?P[^:]+):(?P\d+): WARNING: (?P.+)") +# Regex pattern to match the parts of a Sphinx warning +WARNING_PATTERN = re.compile( + r"(?P([A-Za-z]:[\\/])?[^:]+):(?P\d+): WARNING: (?P.+)" +) + +# Regex pattern to match the line numbers in a Git unified diff +DIFF_PATTERN = re.compile( + r"^@@ -(?P\d+)(?:,(?P\d+))? \+(?P\d+)(?:,(?P\d+))? @@", + flags=re.MULTILINE, +) + + +def get_diff_files(ref_a: str, ref_b: str, filter_mode: str = "") -> set[Path]: + """List the files changed between two Git refs, filtered by change type.""" + added_files_result = subprocess.run( + [ + "git", + "diff", + f"--diff-filter={filter_mode}", + "--name-only", + f"{ref_a}...{ref_b}", + "--", + ], + stdout=subprocess.PIPE, + check=True, + text=True, + encoding="UTF-8", + ) + + added_files = added_files_result.stdout.strip().split("\n") + return {Path(file.strip()) for file in added_files if file.strip()} + + +def get_diff_lines(ref_a: str, ref_b: str, file: Path) -> list[int]: + """List the lines changed between two Git refs for a specific file.""" + diff_output = subprocess.run( + [ + "git", + "diff", + "--unified=0", + f"{ref_a}...{ref_b}", + "--", + str(file), + ], + stdout=subprocess.PIPE, + check=True, + text=True, + encoding="UTF-8", + ) + + # Scrape line offsets + lengths from diff and convert to line numbers + line_matches = DIFF_PATTERN.finditer(diff_output.stdout) + # Removed and added line counts are 1 if not printed + line_match_values = [ + line_match.groupdict(default=1) for line_match in line_matches + ] + line_ints = [ + (int(match_value["lineb"]), int(match_value["added"])) + for match_value in line_match_values + ] + line_ranges = [ + range(line_b, line_b + added) for line_b, added in line_ints + ] + line_numbers = list(itertools.chain(*line_ranges)) + + return line_numbers + + +def get_para_line_numbers(file_obj: TextIO) -> list[list[int]]: + """Get the line numbers of text in a file object, grouped by paragraph.""" + paragraphs = [] + prev_line = None + for lineno, line in enumerate(file_obj): + lineno = lineno + 1 + if prev_line is None or (line.strip() and not prev_line.strip()): + paragraph = [lineno - 1] + paragraphs.append(paragraph) + paragraph.append(lineno) + prev_line = line + return paragraphs + + +def filter_and_parse_warnings( + warnings: list[str], files: set[Path] +) -> list[re.Match[str]]: + """Get the warnings matching passed files and parse them with regex.""" + filtered_warnings = [ + warning + for warning in warnings + if any(str(file) in warning for file in files) + ] + warning_matches = [ + WARNING_PATTERN.fullmatch(warning.strip()) + for warning in filtered_warnings + ] + non_null_matches = [warning for warning in warning_matches if warning] + return non_null_matches + + +def filter_warnings_by_diff( + warnings: list[re.Match[str]], ref_a: str, ref_b: str, file: Path +) -> list[re.Match[str]]: + """Filter the passed per-file warnings to just those on changed lines.""" + diff_lines = get_diff_lines(ref_a, ref_b, file) + with file.open(encoding="UTF-8") as file_obj: + paragraphs = get_para_line_numbers(file_obj) + touched_paras = [ + para_lines + for para_lines in paragraphs + if set(diff_lines) & set(para_lines) + ] + touched_para_lines = set(itertools.chain(*touched_paras)) + warnings_infile = [ + warning for warning in warnings if str(file) in warning["file"] + ] + warnings_touched = [ + warning + for warning in warnings_infile + if int(warning["line"]) in touched_para_lines + ] + return warnings_touched + +def process_touched_warnings( + warnings: list[str], ref_a: str, ref_b: str +) -> list[re.Match[str]]: + """Filter a list of Sphinx warnings to those affecting touched lines.""" + added_files, modified_files = tuple( + get_diff_files(ref_a, ref_b, filter_mode=mode) for mode in ("A", "M") + ) + + warnings_added = filter_and_parse_warnings(warnings, added_files) + warnings_modified = filter_and_parse_warnings(warnings, modified_files) + + modified_files_warned = { + file + for file in modified_files + if any(str(file) in warning["file"] for warning in warnings_modified) + } -def check_and_annotate(warnings: list[str], files_to_check: str) -> None: + warnings_modified_touched = [ + filter_warnings_by_diff(warnings_modified, ref_a, ref_b, file) + for file in modified_files_warned + ] + warnings_touched = warnings_added + list( + itertools.chain(*warnings_modified_touched) + ) + + return warnings_touched + + +def annotate_diff( + warnings: list[str], ref_a: str = "main", ref_b: str = "HEAD" +) -> None: """ - Convert Sphinx warning messages to GitHub Actions. + Convert Sphinx warning messages to GitHub Actions for changed paragraphs. Converts lines like: .../Doc/library/cgi.rst:98: WARNING: reference target not found to: ::warning file=.../Doc/library/cgi.rst,line=98::reference target not found - Non-matching lines are echoed unchanged. - - see: + See: https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#setting-a-warning-message """ - files_to_check = next(csv.reader([files_to_check])) - for warning in warnings: - if any(filename in warning for filename in files_to_check): - if match := PATTERN.fullmatch(warning): - print("::warning file={file},line={line}::{msg}".format_map(match)) + warnings_touched = process_touched_warnings(warnings, ref_a, ref_b) + print("Emitting doc warnings matching modified lines:") + for warning in warnings_touched: + print("::warning file={file},line={line}::{msg}".format_map(warning)) + print(warning[0]) + if not warnings_touched: + print("None") def fail_if_regression( @@ -68,7 +222,7 @@ def fail_if_regression( print(filename) for warning in warnings: if filename in warning: - if match := PATTERN.fullmatch(warning): + if match := WARNING_PATTERN.fullmatch(warning): print(" {line}: {msg}".format_map(match)) return -1 return 0 @@ -91,12 +245,14 @@ def fail_if_improved( return 0 -def main() -> int: +def main(argv: list[str] | None = None) -> int: parser = argparse.ArgumentParser() parser.add_argument( - "--check-and-annotate", - help="Comma-separated list of files to check, " - "and annotate those with warnings on GitHub Actions", + "--annotate-diff", + nargs="*", + metavar=("BASE_REF", "HEAD_REF"), + help="Add GitHub Actions annotations on the diff for warnings on " + "lines changed between the given refs (main and HEAD, by default)", ) parser.add_argument( "--fail-if-regression", @@ -108,13 +264,19 @@ def main() -> int: action="store_true", help="Fail if new files with no nits are found", ) - args = parser.parse_args() + + args = parser.parse_args(argv) + if args.annotate_diff is not None and len(args.annotate_diff) > 2: + parser.error( + "--annotate-diff takes between 0 and 2 ref args, not " + f"{len(args.annotate_diff)} {tuple(args.annotate_diff)}" + ) exit_code = 0 wrong_directory_msg = "Must run this script from the repo root" assert Path("Doc").exists() and Path("Doc").is_dir(), wrong_directory_msg - with Path("Doc/sphinx-warnings.txt").open() as f: + with Path("Doc/sphinx-warnings.txt").open(encoding="UTF-8") as f: warnings = f.read().splitlines() cwd = str(Path.cwd()) + os.path.sep @@ -124,15 +286,15 @@ def main() -> int: if "Doc/" in warning } - with Path("Doc/tools/.nitignore").open() as clean_files: + with Path("Doc/tools/.nitignore").open(encoding="UTF-8") as clean_files: files_with_expected_nits = { filename.strip() for filename in clean_files if filename.strip() and not filename.startswith("#") } - if args.check_and_annotate: - check_and_annotate(warnings, args.check_and_annotate) + if args.annotate_diff is not None: + annotate_diff(warnings, *args.annotate_diff) if args.fail_if_regression: exit_code += fail_if_regression( diff --git a/Doc/tools/extensions/c_annotations.py b/Doc/tools/extensions/c_annotations.py index 3551bfa4c0f133..ba37634545c2cf 100644 --- a/Doc/tools/extensions/c_annotations.py +++ b/Doc/tools/extensions/c_annotations.py @@ -126,7 +126,8 @@ def add_annotations(self, app, doctree): f"Object type mismatch in limited API annotation " f"for {name}: {record['role']!r} != {objtype!r}") stable_added = record['added'] - message = ' Part of the ' + message = sphinx_gettext('Part of the') + message = message.center(len(message) + 2) emph_node = nodes.emphasis(message, message, classes=['stableabi']) ref_node = addnodes.pending_xref( @@ -134,40 +135,40 @@ def add_annotations(self, app, doctree): reftype='ref', refexplicit="False") struct_abi_kind = record['struct_abi_kind'] if struct_abi_kind in {'opaque', 'members'}: - ref_node += nodes.Text('Limited API') + ref_node += nodes.Text(sphinx_gettext('Limited API')) else: - ref_node += nodes.Text('Stable ABI') + ref_node += nodes.Text(sphinx_gettext('Stable ABI')) emph_node += ref_node if struct_abi_kind == 'opaque': - emph_node += nodes.Text(' (as an opaque struct)') + emph_node += nodes.Text(' ' + sphinx_gettext('(as an opaque struct)')) elif struct_abi_kind == 'full-abi': - emph_node += nodes.Text(' (including all members)') + emph_node += nodes.Text(' ' + sphinx_gettext('(including all members)')) if record['ifdef_note']: emph_node += nodes.Text(' ' + record['ifdef_note']) if stable_added == '3.2': # Stable ABI was introduced in 3.2. pass else: - emph_node += nodes.Text(f' since version {stable_added}') + emph_node += nodes.Text(' ' + sphinx_gettext('since version %s') % stable_added) emph_node += nodes.Text('.') if struct_abi_kind == 'members': emph_node += nodes.Text( - ' (Only some members are part of the stable ABI.)') + ' ' + sphinx_gettext('(Only some members are part of the stable ABI.)')) node.insert(0, emph_node) # Unstable API annotation. if name.startswith('PyUnstable'): warn_node = nodes.admonition( classes=['unstable-c-api', 'warning']) - message = 'This is ' + message = sphinx_gettext('This is') + ' ' emph_node = nodes.emphasis(message, message) ref_node = addnodes.pending_xref( 'Unstable API', refdomain="std", reftarget='unstable-c-api', reftype='ref', refexplicit="False") - ref_node += nodes.Text('Unstable API') + ref_node += nodes.Text(sphinx_gettext('Unstable API')) emph_node += ref_node - emph_node += nodes.Text('. It may change without warning in minor releases.') + emph_node += nodes.Text(sphinx_gettext('. It may change without warning in minor releases.')) warn_node += emph_node node.insert(0, warn_node) diff --git a/Doc/tools/extensions/pyspecific.py b/Doc/tools/extensions/pyspecific.py index 8d99b0bfa4f381..cd441836f62bde 100644 --- a/Doc/tools/extensions/pyspecific.py +++ b/Doc/tools/extensions/pyspecific.py @@ -39,7 +39,7 @@ ISSUE_URI = 'https://bugs.python.org/issue?@action=redirect&bpo=%s' GH_ISSUE_URI = 'https://github.com/python/cpython/issues/%s' -SOURCE_URI = 'https://github.com/python/cpython/tree/3.12/%s' +SOURCE_URI = 'https://github.com/python/cpython/tree/main/%s' # monkey-patch reST parser to disable alphabetic and roman enumerated lists from docutils.parsers.rst.states import Body @@ -48,6 +48,11 @@ Body.enum.converters['lowerroman'] = \ Body.enum.converters['upperroman'] = lambda x: None +# monkey-patch the productionlist directive to allow hyphens in group names +# https://github.com/sphinx-doc/sphinx/issues/11854 +from sphinx.domains import std + +std.token_re = re.compile(r'`((~?[\w-]*:)?\w+)`') # Support for marking up and linking to bugs.python.org issues @@ -98,14 +103,13 @@ class ImplementationDetail(Directive): final_argument_whitespace = True # This text is copied to templates/dummy.html - label_text = 'CPython implementation detail:' + label_text = sphinx_gettext('CPython implementation detail:') def run(self): self.assert_has_content() pnode = nodes.compound(classes=['impl-detail']) - label = sphinx_gettext(self.label_text) content = self.content - add_text = nodes.strong(label, label) + add_text = nodes.strong(self.label_text, self.label_text) self.state.nested_parse(content, self.content_offset, pnode) content = nodes.inline(pnode[0].rawsource, translatable=True) content.source = pnode[0].source @@ -128,8 +132,8 @@ class Availability(SphinxDirective): # known platform, libc, and threading implementations known_platforms = frozenset({ "AIX", "Android", "BSD", "DragonFlyBSD", "Emscripten", "FreeBSD", - "Linux", "NetBSD", "OpenBSD", "POSIX", "Solaris", "Unix", "VxWorks", - "WASI", "Windows", "macOS", + "GNU/kFreeBSD", "Linux", "NetBSD", "OpenBSD", "POSIX", "Solaris", + "Unix", "VxWorks", "WASI", "Windows", "macOS", # libc "BSD libc", "glibc", "musl", # POSIX platforms with pthreads @@ -180,7 +184,7 @@ def parse_platforms(self): if unknown: cls = type(self) logger = logging.getLogger(cls.__qualname__) - logger.warn( + logger.warning( f"Unknown platform(s) or syntax '{' '.join(sorted(unknown))}' " f"in '.. availability:: {self.arguments[0]}', see " f"{__file__}:{cls.__qualname__}.known_platforms for a set " @@ -234,9 +238,9 @@ class AuditEvent(Directive): final_argument_whitespace = True _label = [ - "Raises an :ref:`auditing event ` {name} with no arguments.", - "Raises an :ref:`auditing event ` {name} with argument {args}.", - "Raises an :ref:`auditing event ` {name} with arguments {args}.", + sphinx_gettext("Raises an :ref:`auditing event ` {name} with no arguments."), + sphinx_gettext("Raises an :ref:`auditing event ` {name} with argument {args}."), + sphinx_gettext("Raises an :ref:`auditing event ` {name} with arguments {args}."), ] @property @@ -252,7 +256,7 @@ def run(self): else: args = [] - label = sphinx_gettext(self._label[min(2, len(args))]) + label = self._label[min(2, len(args))] text = label.format(name="``{}``".format(name), args=", ".join("``{}``".format(a) for a in args if a)) @@ -267,7 +271,7 @@ def run(self): info = env.all_audit_events.setdefault(name, new_info) if info is not new_info: if not self._do_args_match(info['args'], new_info['args']): - self.logger.warn( + self.logger.warning( "Mismatched arguments for audit-event {}: {!r} != {!r}" .format(name, info['args'], new_info['args']) ) @@ -414,8 +418,8 @@ class DeprecatedRemoved(Directive): final_argument_whitespace = True option_spec = {} - _deprecated_label = 'Deprecated since version {deprecated}, will be removed in version {removed}' - _removed_label = 'Deprecated since version {deprecated}, removed in version {removed}' + _deprecated_label = sphinx_gettext('Deprecated since version {deprecated}, will be removed in version {removed}') + _removed_label = sphinx_gettext('Deprecated since version {deprecated}, removed in version {removed}') def run(self): node = addnodes.versionmodified() @@ -431,7 +435,6 @@ def run(self): else: label = self._removed_label - label = sphinx_gettext(label) text = label.format(deprecated=self.arguments[0], removed=self.arguments[1]) if len(self.arguments) == 3: inodes, messages = self.state.inline_text(self.arguments[2], @@ -544,7 +547,7 @@ def write(self, *ignored): 'building topics... ', length=len(pydoc_topic_labels)): if label not in self.env.domaindata['std']['labels']: - self.env.logger.warn('label %r not in documentation' % label) + self.env.logger.warning(f'label {label!r} not in documentation') continue docname, labelid, sectname = self.env.domaindata['std']['labels'][label] doctree = self.env.get_and_resolve_doctree(docname, self) @@ -609,6 +612,13 @@ def parse_pdb_command(env, sig, signode): return fullname +def parse_monitoring_event(env, sig, signode): + """Transform a monitoring event signature into RST nodes.""" + signode += addnodes.desc_addname('sys.monitoring.events.', 'sys.monitoring.events.') + signode += addnodes.desc_name(sig, sig) + return sig + + def process_audit_events(app, doctree, fromdocname): for node in doctree.traverse(audit_event_list): break @@ -709,6 +719,7 @@ def setup(app): app.add_builder(PydocTopicsBuilder) app.add_object_type('opcode', 'opcode', '%s (opcode)', parse_opcode_signature) app.add_object_type('pdbcommand', 'pdbcmd', '%s (pdb command)', parse_pdb_command) + app.add_object_type('monitoring-event', 'monitoring-event', '%s (monitoring event)', parse_monitoring_event) app.add_directive_to_domain('py', 'decorator', PyDecoratorFunction) app.add_directive_to_domain('py', 'decoratormethod', PyDecoratorMethod) app.add_directive_to_domain('py', 'coroutinefunction', PyCoroutineFunction) diff --git a/Doc/tools/templates/download.html b/Doc/tools/templates/download.html index 7920e0619f9337..b5353d6fb77ab4 100644 --- a/Doc/tools/templates/download.html +++ b/Doc/tools/templates/download.html @@ -49,12 +49,12 @@

Unpacking

Unix users should download the .tar.bz2 archives; these are bzipped tar archives and can be handled in the usual way using tar and the bzip2 -program. The InfoZIP unzip program can be +program. The Info-ZIP unzip program can be used to handle the ZIP archives if desired. The .tar.bz2 archives provide the best compression and fastest download times.

Windows users can use the ZIP archives since those are customary on that -platform. These are created on Unix using the InfoZIP zip program.

+platform. These are created on Unix using the Info-ZIP zip program.

Problems

diff --git a/Doc/tools/templates/dummy.html b/Doc/tools/templates/dummy.html index bab4aaeb4604b8..49c2a71a5e40cf 100644 --- a/Doc/tools/templates/dummy.html +++ b/Doc/tools/templates/dummy.html @@ -9,6 +9,16 @@ In extensions/c_annotations.py: +{% trans %}Part of the{% endtrans %} +{% trans %}Limited API{% endtrans %} +{% trans %}Stable ABI{% endtrans %} +{% trans %}(as an opaque struct){% endtrans %} +{% trans %}(including all members){% endtrans %} +{% trans %}since version %s{% endtrans %} +{% trans %}(Only some members are part of the stable ABI.){% endtrans %} +{% trans %}This is{% endtrans %} +{% trans %}Unstable API{% endtrans %} +{% trans %}. It may change without warning in minor releases.{% endtrans %} {% trans %}Return value: Always NULL.{% endtrans %} {% trans %}Return value: New reference.{% endtrans %} {% trans %}Return value: Borrowed reference.{% endtrans %} diff --git a/Doc/tools/templates/indexcontent.html b/Doc/tools/templates/indexcontent.html index a96746b69fd41b..1e3ab7cfe02fee 100644 --- a/Doc/tools/templates/indexcontent.html +++ b/Doc/tools/templates/indexcontent.html @@ -62,6 +62,7 @@

{{ docstitle|e }}

+ {% endblock %} diff --git a/Doc/tools/templates/layout.html b/Doc/tools/templates/layout.html index 80103158ea01e6..9498b2ccc5af92 100644 --- a/Doc/tools/templates/layout.html +++ b/Doc/tools/templates/layout.html @@ -26,9 +26,6 @@ {% endblock %} {% block extrahead %} - {% if builder == "html" %} - - {% endif %} {% if builder != "htmlhelp" %} {% if pagename == 'whatsnew/changelog' and not embedded %} diff --git a/Doc/tutorial/appendix.rst b/Doc/tutorial/appendix.rst index 241a812037469e..588591fcdb726f 100644 --- a/Doc/tutorial/appendix.rst +++ b/Doc/tutorial/appendix.rst @@ -101,8 +101,8 @@ in the script:: The Customization Modules ------------------------- -Python provides two hooks to let you customize it: :mod:`sitecustomize` and -:mod:`usercustomize`. To see how it works, you need first to find the location +Python provides two hooks to let you customize it: :index:`sitecustomize` and +:index:`usercustomize`. To see how it works, you need first to find the location of your user site-packages directory. Start Python and run this code:: >>> import site @@ -113,9 +113,9 @@ Now you can create a file named :file:`usercustomize.py` in that directory and put anything you want in it. It will affect every invocation of Python, unless it is started with the :option:`-s` option to disable the automatic import. -:mod:`sitecustomize` works in the same way, but is typically created by an +:index:`sitecustomize` works in the same way, but is typically created by an administrator of the computer in the global site-packages directory, and is -imported before :mod:`usercustomize`. See the documentation of the :mod:`site` +imported before :index:`usercustomize`. See the documentation of the :mod:`site` module for more details. diff --git a/Doc/tutorial/classes.rst b/Doc/tutorial/classes.rst index 06445e000c1ef6..3bf138ca225ee5 100644 --- a/Doc/tutorial/classes.rst +++ b/Doc/tutorial/classes.rst @@ -91,7 +91,7 @@ Attributes may be read-only or writable. In the latter case, assignment to attributes is possible. Module attributes are writable: you can write ``modname.the_answer = 42``. Writable attributes may also be deleted with the :keyword:`del` statement. For example, ``del modname.the_answer`` will remove -the attribute :attr:`the_answer` from the object named by ``modname``. +the attribute :attr:`!the_answer` from the object named by ``modname``. Namespaces are created at different moments and have different lifetimes. The namespace containing the built-in names is created when the Python interpreter @@ -249,7 +249,7 @@ created. This is basically a wrapper around the contents of the namespace created by the class definition; we'll learn more about class objects in the next section. The original local scope (the one in effect just before the class definition was entered) is reinstated, and the class object is bound here to the -class name given in the class definition header (:class:`ClassName` in the +class name given in the class definition header (:class:`!ClassName` in the example). @@ -276,7 +276,7 @@ definition looked like this:: then ``MyClass.i`` and ``MyClass.f`` are valid attribute references, returning an integer and a function object, respectively. Class attributes can also be assigned to, so you can change the value of ``MyClass.i`` by assignment. -:attr:`__doc__` is also a valid attribute, returning the docstring belonging to +:attr:`!__doc__` is also a valid attribute, returning the docstring belonging to the class: ``"A simple example class"``. Class *instantiation* uses function notation. Just pretend that the class @@ -291,20 +291,20 @@ variable ``x``. The instantiation operation ("calling" a class object) creates an empty object. Many classes like to create objects with instances customized to a specific initial state. Therefore a class may define a special method named -:meth:`__init__`, like this:: +:meth:`~object.__init__`, like this:: def __init__(self): self.data = [] -When a class defines an :meth:`__init__` method, class instantiation -automatically invokes :meth:`__init__` for the newly created class instance. So +When a class defines an :meth:`~object.__init__` method, class instantiation +automatically invokes :meth:`!__init__` for the newly created class instance. So in this example, a new, initialized instance can be obtained by:: x = MyClass() -Of course, the :meth:`__init__` method may have arguments for greater +Of course, the :meth:`~object.__init__` method may have arguments for greater flexibility. In that case, arguments given to the class instantiation operator -are passed on to :meth:`__init__`. For example, :: +are passed on to :meth:`!__init__`. For example, :: >>> class Complex: ... def __init__(self, realpart, imagpart): @@ -328,7 +328,7 @@ attribute names: data attributes and methods. *data attributes* correspond to "instance variables" in Smalltalk, and to "data members" in C++. Data attributes need not be declared; like local variables, they spring into existence when they are first assigned to. For example, if -``x`` is the instance of :class:`MyClass` created above, the following piece of +``x`` is the instance of :class:`!MyClass` created above, the following piece of code will print the value ``16``, without leaving a trace:: x.counter = 1 @@ -363,7 +363,7 @@ Usually, a method is called right after it is bound:: x.f() -In the :class:`MyClass` example, this will return the string ``'hello world'``. +In the :class:`!MyClass` example, this will return the string ``'hello world'``. However, it is not necessary to call a method right away: ``x.f`` is a method object, and can be stored away and called at a later time. For example:: @@ -375,7 +375,7 @@ will continue to print ``hello world`` until the end of time. What exactly happens when a method is called? You may have noticed that ``x.f()`` was called without an argument above, even though the function -definition for :meth:`f` specified an argument. What happened to the argument? +definition for :meth:`!f` specified an argument. What happened to the argument? Surely Python raises an exception when a function that requires an argument is called without any --- even if the argument isn't actually used... @@ -532,9 +532,9 @@ variable in the class is also ok. For example:: h = g -Now ``f``, ``g`` and ``h`` are all attributes of class :class:`C` that refer to +Now ``f``, ``g`` and ``h`` are all attributes of class :class:`!C` that refer to function objects, and consequently they are all methods of instances of -:class:`C` --- ``h`` being exactly equivalent to ``g``. Note that this practice +:class:`!C` --- ``h`` being exactly equivalent to ``g``. Note that this practice usually only serves to confuse the reader of a program. Methods may call other methods by using method attributes of the ``self`` @@ -581,7 +581,7 @@ this:: . -The name :class:`BaseClassName` must be defined in a +The name :class:`!BaseClassName` must be defined in a namespace accessible from the scope containing the derived class definition. In place of a base class name, other arbitrary expressions are also allowed. This can be useful, for example, when the base @@ -645,9 +645,9 @@ multiple base classes looks like this:: For most purposes, in the simplest cases, you can think of the search for attributes inherited from a parent class as depth-first, left-to-right, not searching twice in the same class where there is an overlap in the hierarchy. -Thus, if an attribute is not found in :class:`DerivedClassName`, it is searched -for in :class:`Base1`, then (recursively) in the base classes of :class:`Base1`, -and if it was not found there, it was searched for in :class:`Base2`, and so on. +Thus, if an attribute is not found in :class:`!DerivedClassName`, it is searched +for in :class:`!Base1`, then (recursively) in the base classes of :class:`!Base1`, +and if it was not found there, it was searched for in :class:`!Base2`, and so on. In fact, it is slightly more complex than that; the method resolution order changes dynamically to support cooperative calls to :func:`super`. This @@ -760,7 +760,8 @@ is to use :mod:`dataclasses` for this purpose:: A piece of Python code that expects a particular abstract data type can often be passed a class that emulates the methods of that data type instead. For instance, if you have a function that formats some data from a file object, you -can define a class with methods :meth:`read` and :meth:`!readline` that get the +can define a class with methods :meth:`~io.TextIOBase.read` and +:meth:`~io.TextIOBase.readline` that get the data from a string buffer instead, and pass it as an argument. .. (Unfortunately, this technique has its limitations: a class can't define @@ -768,8 +769,10 @@ data from a string buffer instead, and pass it as an argument. or arithmetic operators, and assigning such a "pseudo-file" to sys.stdin will not cause the interpreter to read further input from it.) -Instance method objects have attributes, too: ``m.__self__`` is the instance -object with the method :meth:`m`, and ``m.__func__`` is the function object +:ref:`Instance method objects ` have attributes, too: +:attr:`m.__self__ ` is the instance +object with the method :meth:`!m`, and :attr:`m.__func__ ` is +the :ref:`function object ` corresponding to the method. @@ -818,9 +821,9 @@ using the :func:`next` built-in function; this example shows how it all works:: StopIteration Having seen the mechanics behind the iterator protocol, it is easy to add -iterator behavior to your classes. Define an :meth:`__iter__` method which +iterator behavior to your classes. Define an :meth:`~container.__iter__` method which returns an object with a :meth:`~iterator.__next__` method. If the class -defines :meth:`__next__`, then :meth:`__iter__` can just return ``self``:: +defines :meth:`!__next__`, then :meth:`!__iter__` can just return ``self``:: class Reverse: """Iterator for looping over a sequence backwards.""" @@ -879,7 +882,7 @@ easy to create:: Anything that can be done with generators can also be done with class-based iterators as described in the previous section. What makes generators so -compact is that the :meth:`__iter__` and :meth:`~generator.__next__` methods +compact is that the :meth:`~iterator.__iter__` and :meth:`~generator.__next__` methods are created automatically. Another key feature is that the local variables and execution state are diff --git a/Doc/tutorial/controlflow.rst b/Doc/tutorial/controlflow.rst index 138d87f892e891..77444f9cb8358d 100644 --- a/Doc/tutorial/controlflow.rst +++ b/Doc/tutorial/controlflow.rst @@ -534,7 +534,7 @@ This example, as usual, demonstrates some new Python features: Different types define different methods. Methods of different types may have the same name without causing ambiguity. (It is possible to define your own object types and methods, using *classes*, see :ref:`tut-classes`) - The method :meth:`append` shown in the example is defined for list objects; it + The method :meth:`!append` shown in the example is defined for list objects; it adds a new element at the end of the list. In this example it is equivalent to ``result = result + [a]``, but more efficient. @@ -559,10 +559,10 @@ defined to allow. For example:: def ask_ok(prompt, retries=4, reminder='Please try again!'): while True: - ok = input(prompt) - if ok in ('y', 'ye', 'yes'): + reply = input(prompt) + if reply in {'y', 'ye', 'yes'}: return True - if ok in ('n', 'no', 'nop', 'nope'): + if reply in {'n', 'no', 'nop', 'nope'}: return False retries = retries - 1 if retries < 0: @@ -1046,7 +1046,7 @@ Function Annotations information about the types used by user-defined functions (see :pep:`3107` and :pep:`484` for more information). -:term:`Annotations ` are stored in the :attr:`__annotations__` +:term:`Annotations ` are stored in the :attr:`!__annotations__` attribute of the function as a dictionary and have no effect on any other part of the function. Parameter annotations are defined by a colon after the parameter name, followed by an expression evaluating to the value of the annotation. Return annotations are diff --git a/Doc/tutorial/datastructures.rst b/Doc/tutorial/datastructures.rst index c8e89d9b79bddd..87614d082a1d4e 100644 --- a/Doc/tutorial/datastructures.rst +++ b/Doc/tutorial/datastructures.rst @@ -143,8 +143,8 @@ Using Lists as Stacks The list methods make it very easy to use a list as a stack, where the last element added is the first element retrieved ("last-in, first-out"). To add an -item to the top of the stack, use :meth:`append`. To retrieve an item from the -top of the stack, use :meth:`pop` without an explicit index. For example:: +item to the top of the stack, use :meth:`~list.append`. To retrieve an item from the +top of the stack, use :meth:`~list.pop` without an explicit index. For example:: >>> stack = [3, 4, 5] >>> stack.append(6) @@ -341,7 +341,7 @@ The :keyword:`!del` statement ============================= There is a way to remove an item from a list given its index instead of its -value: the :keyword:`del` statement. This differs from the :meth:`pop` method +value: the :keyword:`del` statement. This differs from the :meth:`~list.pop` method which returns a value. The :keyword:`!del` statement can also be used to remove slices from a list or clear the entire list (which we did earlier by assignment of an empty list to the slice). For example:: @@ -501,8 +501,8 @@ any immutable type; strings and numbers can always be keys. Tuples can be used as keys if they contain only strings, numbers, or tuples; if a tuple contains any mutable object either directly or indirectly, it cannot be used as a key. You can't use lists as keys, since lists can be modified in place using index -assignments, slice assignments, or methods like :meth:`append` and -:meth:`extend`. +assignments, slice assignments, or methods like :meth:`~list.append` and +:meth:`~list.extend`. It is best to think of a dictionary as a set of *key: value* pairs, with the requirement that the keys are unique (within one dictionary). A pair of @@ -567,7 +567,7 @@ Looping Techniques ================== When looping through dictionaries, the key and corresponding value can be -retrieved at the same time using the :meth:`items` method. :: +retrieved at the same time using the :meth:`~dict.items` method. :: >>> knights = {'gallahad': 'the pure', 'robin': 'the brave'} >>> for k, v in knights.items(): diff --git a/Doc/tutorial/errors.rst b/Doc/tutorial/errors.rst index 1ec59767e9ce12..4058ebe8efdb42 100644 --- a/Doc/tutorial/errors.rst +++ b/Doc/tutorial/errors.rst @@ -108,8 +108,7 @@ The :keyword:`try` statement works as follows. * If an exception occurs which does not match the exception named in the *except clause*, it is passed on to outer :keyword:`try` statements; if no handler is - found, it is an *unhandled exception* and execution stops with a message as - shown above. + found, it is an *unhandled exception* and execution stops with an error message. A :keyword:`try` statement may have more than one *except clause*, to specify handlers for different exceptions. At most one handler will be executed. diff --git a/Doc/tutorial/floatingpoint.rst b/Doc/tutorial/floatingpoint.rst index b88055a41fd1ff..0795e2fef98830 100644 --- a/Doc/tutorial/floatingpoint.rst +++ b/Doc/tutorial/floatingpoint.rst @@ -137,7 +137,7 @@ the :func:`math.isclose` function can be useful for comparing inexact values: True Alternatively, the :func:`round` function can be used to compare rough -approximations:: +approximations: .. doctest:: @@ -150,7 +150,7 @@ section. See `Examples of Floating Point Problems `_ for a pleasant summary of how binary floating-point works and the kinds of problems commonly encountered in practice. Also see -`The Perils of Floating Point `_ +`The Perils of Floating Point `_ for a more complete account of other common surprises. As that says near the end, "there are no easy answers." Still, don't be unduly diff --git a/Doc/tutorial/inputoutput.rst b/Doc/tutorial/inputoutput.rst index f5cdd84cbadefe..fe9ca9ccb9c7e0 100644 --- a/Doc/tutorial/inputoutput.rst +++ b/Doc/tutorial/inputoutput.rst @@ -15,7 +15,7 @@ Fancier Output Formatting ========================= So far we've encountered two ways of writing values: *expression statements* and -the :func:`print` function. (A third way is using the :meth:`write` method +the :func:`print` function. (A third way is using the :meth:`~io.TextIOBase.write` method of file objects; the standard output file can be referenced as ``sys.stdout``. See the Library Reference for more information on this.) @@ -456,8 +456,8 @@ to the very file end with ``seek(0, 2)``) and the only valid *offset* values are those returned from the ``f.tell()``, or zero. Any other *offset* value produces undefined behaviour. -File objects have some additional methods, such as :meth:`~file.isatty` and -:meth:`~file.truncate` which are less frequently used; consult the Library +File objects have some additional methods, such as :meth:`~io.IOBase.isatty` and +:meth:`~io.IOBase.truncate` which are less frequently used; consult the Library Reference for a complete guide to file objects. @@ -469,7 +469,7 @@ Saving structured data with :mod:`json` .. index:: pair: module; json Strings can easily be written to and read from a file. Numbers take a bit more -effort, since the :meth:`read` method only returns strings, which will have to +effort, since the :meth:`~io.TextIOBase.read` method only returns strings, which will have to be passed to a function like :func:`int`, which takes a string like ``'123'`` and returns its numeric value 123. When you want to save more complex data types like nested lists and dictionaries, parsing and serializing by hand diff --git a/Doc/tutorial/interactive.rst b/Doc/tutorial/interactive.rst index 0d3896a4832b59..4e054c4e6c2c32 100644 --- a/Doc/tutorial/interactive.rst +++ b/Doc/tutorial/interactive.rst @@ -51,4 +51,4 @@ bpython_. .. _GNU Readline: https://tiswww.case.edu/php/chet/readline/rltop.html .. _IPython: https://ipython.org/ -.. _bpython: https://www.bpython-interpreter.org/ +.. _bpython: https://bpython-interpreter.org/ diff --git a/Doc/tutorial/introduction.rst b/Doc/tutorial/introduction.rst index 0fc75c7d7532e2..4536ab9486d39c 100644 --- a/Doc/tutorial/introduction.rst +++ b/Doc/tutorial/introduction.rst @@ -428,7 +428,7 @@ type, i.e. it is possible to change their content:: [1, 8, 27, 64, 125] You can also add new items at the end of the list, by using -the :meth:`~list.append` *method* (we will see more about methods later):: +the :meth:`!list.append` *method* (we will see more about methods later):: >>> cubes.append(216) # add the cube of 6 >>> cubes.append(7 ** 3) # and the cube of 7 @@ -480,7 +480,7 @@ First Steps Towards Programming Of course, we can use Python for more complicated tasks than adding two and two together. For instance, we can write an initial sub-sequence of the -`Fibonacci series `_ +`Fibonacci series `_ as follows:: >>> # Fibonacci series: diff --git a/Doc/tutorial/modules.rst b/Doc/tutorial/modules.rst index 734dd1cfe6871a..0316239e776a95 100644 --- a/Doc/tutorial/modules.rst +++ b/Doc/tutorial/modules.rst @@ -183,7 +183,7 @@ The Module Search Path .. index:: triple: module; search; path -When a module named :mod:`spam` is imported, the interpreter first searches for +When a module named :mod:`!spam` is imported, the interpreter first searches for a built-in module with that name. These module names are listed in :data:`sys.builtin_module_names`. If not found, it then searches for a file named :file:`spam.py` in a list of directories given by the variable @@ -389,7 +389,7 @@ Packages ======== Packages are a way of structuring Python's module namespace by using "dotted -module names". For example, the module name :mod:`A.B` designates a submodule +module names". For example, the module name :mod:`!A.B` designates a submodule named ``B`` in a package named ``A``. Just like the use of modules saves the authors of different modules from having to worry about each other's global variable names, the use of dotted module names saves the authors of multi-module @@ -437,7 +437,8 @@ When importing the package, Python searches through the directories on ``sys.path`` looking for the package subdirectory. The :file:`__init__.py` files are required to make Python treat directories -containing the file as packages. This prevents directories with a common name, +containing the file as packages (unless using a :term:`namespace package`, a +relatively advanced feature). This prevents directories with a common name, such as ``string``, from unintentionally hiding valid modules that occur later on the module search path. In the simplest case, :file:`__init__.py` can just be an empty file, but it can also execute initialization code for the package or @@ -448,7 +449,7 @@ example:: import sound.effects.echo -This loads the submodule :mod:`sound.effects.echo`. It must be referenced with +This loads the submodule :mod:`!sound.effects.echo`. It must be referenced with its full name. :: sound.effects.echo.echofilter(input, output, delay=0.7, atten=4) @@ -457,7 +458,7 @@ An alternative way of importing the submodule is:: from sound.effects import echo -This also loads the submodule :mod:`echo`, and makes it available without its +This also loads the submodule :mod:`!echo`, and makes it available without its package prefix, so it can be used as follows:: echo.echofilter(input, output, delay=0.7, atten=4) @@ -466,8 +467,8 @@ Yet another variation is to import the desired function or variable directly:: from sound.effects.echo import echofilter -Again, this loads the submodule :mod:`echo`, but this makes its function -:func:`echofilter` directly available:: +Again, this loads the submodule :mod:`!echo`, but this makes its function +:func:`!echofilter` directly available:: echofilter(input, output, delay=0.7, atten=4) @@ -510,7 +511,7 @@ code:: __all__ = ["echo", "surround", "reverse"] This would mean that ``from sound.effects import *`` would import the three -named submodules of the :mod:`sound.effects` package. +named submodules of the :mod:`!sound.effects` package. Be aware that submodules might become shadowed by locally defined names. For example, if you added a ``reverse`` function to the @@ -529,8 +530,8 @@ would only import the two submodules ``echo`` and ``surround``, but *not* the return msg[::-1] # in the case of a 'from sound.effects import *' If ``__all__`` is not defined, the statement ``from sound.effects import *`` -does *not* import all submodules from the package :mod:`sound.effects` into the -current namespace; it only ensures that the package :mod:`sound.effects` has +does *not* import all submodules from the package :mod:`!sound.effects` into the +current namespace; it only ensures that the package :mod:`!sound.effects` has been imported (possibly running any initialization code in :file:`__init__.py`) and then imports whatever names are defined in the package. This includes any names defined (and submodules explicitly loaded) by :file:`__init__.py`. It @@ -541,8 +542,8 @@ previous :keyword:`import` statements. Consider this code:: import sound.effects.surround from sound.effects import * -In this example, the :mod:`echo` and :mod:`surround` modules are imported in the -current namespace because they are defined in the :mod:`sound.effects` package +In this example, the :mod:`!echo` and :mod:`!surround` modules are imported in the +current namespace because they are defined in the :mod:`!sound.effects` package when the ``from...import`` statement is executed. (This also works when ``__all__`` is defined.) @@ -561,15 +562,15 @@ packages. Intra-package References ------------------------ -When packages are structured into subpackages (as with the :mod:`sound` package +When packages are structured into subpackages (as with the :mod:`!sound` package in the example), you can use absolute imports to refer to submodules of siblings -packages. For example, if the module :mod:`sound.filters.vocoder` needs to use -the :mod:`echo` module in the :mod:`sound.effects` package, it can use ``from +packages. For example, if the module :mod:`!sound.filters.vocoder` needs to use +the :mod:`!echo` module in the :mod:`!sound.effects` package, it can use ``from sound.effects import echo``. You can also write relative imports, with the ``from module import name`` form of import statement. These imports use leading dots to indicate the current and -parent packages involved in the relative import. From the :mod:`surround` +parent packages involved in the relative import. From the :mod:`!surround` module for example, you might use:: from . import echo diff --git a/Doc/tutorial/stdlib.rst b/Doc/tutorial/stdlib.rst index 6bae279c5e9cde..63f4b5e1ce0207 100644 --- a/Doc/tutorial/stdlib.rst +++ b/Doc/tutorial/stdlib.rst @@ -153,7 +153,7 @@ The :mod:`random` module provides tools for making random selections:: 'apple' >>> random.sample(range(100), 10) # sampling without replacement [30, 83, 16, 4, 8, 81, 41, 50, 18, 33] - >>> random.random() # random float + >>> random.random() # random float from the interval [0.0, 1.0) 0.17970987693706186 >>> random.randrange(6) # random integer chosen from range(6) 4 diff --git a/Doc/tutorial/venv.rst b/Doc/tutorial/venv.rst index d1bba098d7d23b..a6dead2eac11f6 100644 --- a/Doc/tutorial/venv.rst +++ b/Doc/tutorial/venv.rst @@ -207,4 +207,6 @@ necessary packages with ``install -r``: ``pip`` has many more options. Consult the :ref:`installing-index` guide for complete documentation for ``pip``. When you've written a package and want to make it available on the Python Package Index, -consult the :ref:`distributing-index` guide. +consult the `Python packaging user guide`_. + +.. _Python Packaging User Guide: https://packaging.python.org/en/latest/tutorials/packaging-projects/ diff --git a/Doc/using/cmdline.rst b/Doc/using/cmdline.rst index 4bf67eb439ec6c..df8b07c6118599 100644 --- a/Doc/using/cmdline.rst +++ b/Doc/using/cmdline.rst @@ -59,7 +59,7 @@ all consecutive arguments will end up in :data:`sys.argv` -- note that the first element, subscript zero (``sys.argv[0]``), is a string reflecting the program's source. -.. cmdoption:: -c +.. option:: -c Execute the Python code in *command*. *command* can be one or more statements separated by newlines, with significant leading whitespace as in @@ -72,7 +72,7 @@ source. .. audit-event:: cpython.run_command command cmdoption-c -.. cmdoption:: -m +.. option:: -m Search :data:`sys.path` for the named module and execute its contents as the :mod:`__main__` module. @@ -103,7 +103,7 @@ source. :option:`-I` option can be used to run the script in isolated mode where :data:`sys.path` contains neither the current directory nor the user's - site-packages directory. All :envvar:`PYTHON*` environment variables are + site-packages directory. All ``PYTHON*`` environment variables are ignored, too. Many standard library modules contain code that is invoked on their execution @@ -161,7 +161,7 @@ source. :option:`-I` option can be used to run the script in isolated mode where :data:`sys.path` contains neither the script's directory nor the user's - site-packages directory. All :envvar:`PYTHON*` environment variables are + site-packages directory. All ``PYTHON*`` environment variables are ignored, too. .. audit-event:: cpython.run_file filename @@ -188,35 +188,35 @@ automatically enabled, if available on your platform (see Generic options ~~~~~~~~~~~~~~~ -.. cmdoption:: -? - -h - --help +.. option:: -? + -h + --help Print a short description of all command line options and corresponding environment variables and exit. -.. cmdoption:: --help-env +.. option:: --help-env Print a short description of Python-specific environment variables and exit. .. versionadded:: 3.11 -.. cmdoption:: --help-xoptions +.. option:: --help-xoptions Print a description of implementation-specific :option:`-X` options and exit. .. versionadded:: 3.11 -.. cmdoption:: --help-all +.. option:: --help-all Print complete usage information and exit. .. versionadded:: 3.11 -.. cmdoption:: -V - --version +.. option:: -V + --version Print the Python version number and exit. Example output could be: @@ -240,7 +240,7 @@ Generic options Miscellaneous options ~~~~~~~~~~~~~~~~~~~~~ -.. cmdoption:: -b +.. option:: -b Issue a warning when comparing :class:`bytes` or :class:`bytearray` with :class:`str` or :class:`bytes` with :class:`int`. Issue an error when the @@ -249,13 +249,13 @@ Miscellaneous options .. versionchanged:: 3.5 Affects comparisons of :class:`bytes` with :class:`int`. -.. cmdoption:: -B +.. option:: -B If given, Python won't try to write ``.pyc`` files on the import of source modules. See also :envvar:`PYTHONDONTWRITEBYTECODE`. -.. cmdoption:: --check-hash-based-pycs default|always|never +.. option:: --check-hash-based-pycs default|always|never Control the validation behavior of hash-based ``.pyc`` files. See :ref:`pyc-invalidation`. When set to ``default``, checked and unchecked @@ -269,7 +269,7 @@ Miscellaneous options option. -.. cmdoption:: -d +.. option:: -d Turn on parser debugging output (for expert only). See also the :envvar:`PYTHONDEBUG` environment variable. @@ -278,15 +278,15 @@ Miscellaneous options it's ignored. -.. cmdoption:: -E +.. option:: -E - Ignore all :envvar:`PYTHON*` environment variables, e.g. + Ignore all ``PYTHON*`` environment variables, e.g. :envvar:`PYTHONPATH` and :envvar:`PYTHONHOME`, that might be set. See also the :option:`-P` and :option:`-I` (isolated) options. -.. cmdoption:: -i +.. option:: -i When a script is passed as first argument or the :option:`-c` option is used, enter interactive mode after executing the script or the command, even when @@ -297,20 +297,20 @@ Miscellaneous options raises an exception. See also :envvar:`PYTHONINSPECT`. -.. cmdoption:: -I +.. option:: -I Run Python in isolated mode. This also implies :option:`-E`, :option:`-P` and :option:`-s` options. In isolated mode :data:`sys.path` contains neither the script's directory nor - the user's site-packages directory. All :envvar:`PYTHON*` environment + the user's site-packages directory. All ``PYTHON*`` environment variables are ignored, too. Further restrictions may be imposed to prevent the user from injecting malicious code. .. versionadded:: 3.4 -.. cmdoption:: -O +.. option:: -O Remove assert statements and any code conditional on the value of :const:`__debug__`. Augment the filename for compiled @@ -321,7 +321,7 @@ Miscellaneous options Modify ``.pyc`` filenames according to :pep:`488`. -.. cmdoption:: -OO +.. option:: -OO Do :option:`-O` and also discard docstrings. Augment the filename for compiled (:term:`bytecode`) files by adding ``.opt-2`` before the @@ -331,7 +331,7 @@ Miscellaneous options Modify ``.pyc`` filenames according to :pep:`488`. -.. cmdoption:: -P +.. option:: -P Don't prepend a potentially unsafe path to :data:`sys.path`: @@ -348,28 +348,28 @@ Miscellaneous options .. versionadded:: 3.11 -.. cmdoption:: -q +.. option:: -q Don't display the copyright and version messages even in interactive mode. .. versionadded:: 3.2 -.. cmdoption:: -R +.. option:: -R Turn on hash randomization. This option only has an effect if the :envvar:`PYTHONHASHSEED` environment variable is set to ``0``, since hash randomization is enabled by default. On previous versions of Python, this option turns on hash randomization, - so that the :meth:`__hash__` values of str and bytes objects + so that the :meth:`~object.__hash__` values of str and bytes objects are "salted" with an unpredictable random value. Although they remain constant within an individual Python process, they are not predictable between repeated invocations of Python. Hash randomization is intended to provide protection against a denial-of-service caused by carefully chosen inputs that exploit the worst - case performance of a dict construction, O(n\ :sup:`2`) complexity. See + case performance of a dict construction, *O*\ (*n*\ :sup:`2`) complexity. See http://ocert.org/advisories/ocert-2011-003.html for details. :envvar:`PYTHONHASHSEED` allows you to set a fixed value for the hash @@ -381,7 +381,7 @@ Miscellaneous options .. versionadded:: 3.2.3 -.. cmdoption:: -s +.. option:: -s Don't add the :data:`user site-packages directory ` to :data:`sys.path`. @@ -391,7 +391,7 @@ Miscellaneous options :pep:`370` -- Per user site-packages directory -.. cmdoption:: -S +.. option:: -S Disable the import of the module :mod:`site` and the site-dependent manipulations of :data:`sys.path` that it entails. Also disable these @@ -399,7 +399,7 @@ Miscellaneous options :func:`site.main` if you want them to be triggered). -.. cmdoption:: -u +.. option:: -u Force the stdout and stderr streams to be unbuffered. This option has no effect on the stdin stream. @@ -410,7 +410,7 @@ Miscellaneous options The text layer of the stdout and stderr streams now is unbuffered. -.. cmdoption:: -v +.. option:: -v Print a message each time a module is initialized, showing the place (filename or built-in module) from which it is loaded. When given twice @@ -425,7 +425,7 @@ Miscellaneous options .. _using-on-warnings: -.. cmdoption:: -W arg +.. option:: -W arg Warning control. Python's warning machinery by default prints warning messages to :data:`sys.stderr`. @@ -484,13 +484,13 @@ Miscellaneous options details. -.. cmdoption:: -x +.. option:: -x Skip the first line of the source, allowing use of non-Unix forms of ``#!cmd``. This is intended for a DOS specific hack only. -.. cmdoption:: -X +.. option:: -X Reserved for various implementation-specific options. CPython currently defines the following possible values: @@ -535,17 +535,30 @@ Miscellaneous options location indicators when the interpreter displays tracebacks. See also :envvar:`PYTHONNODEBUGRANGES`. * ``-X frozen_modules`` determines whether or not frozen modules are - ignored by the import machinery. A value of "on" means they get - imported and "off" means they are ignored. The default is "on" + ignored by the import machinery. A value of ``on`` means they get + imported and ``off`` means they are ignored. The default is ``on`` if this is an installed Python (the normal case). If it's under - 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". + development (running from the source tree) then the default is ``off``. + Note that the :mod:`!importlib_bootstrap` and + :mod:`!importlib_bootstrap_external` frozen modules are always used, even + if this flag is set to ``off``. See also :envvar:`PYTHON_FROZEN_MODULES`. * ``-X perf`` enables support for the Linux ``perf`` profiler. When this option is provided, the ``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`. + * :samp:`-X cpu_count={n}` overrides :func:`os.cpu_count`, + :func:`os.process_cpu_count`, and :func:`multiprocessing.cpu_count`. + *n* must be greater than or equal to 1. + This option may be useful for users who need to limit CPU resources of a + container system. See also :envvar:`PYTHON_CPU_COUNT`. + If *n* is ``default``, nothing is overridden. + * :samp:`-X presite={package.module}` specifies a module that should be + imported before the :mod:`site` module is executed and before the + :mod:`__main__` module exists. Therefore, the imported module isn't + :mod:`__main__`. This can be used to execute code early during Python + initialization. Python needs to be :ref:`built in debug mode ` + for this option to exist. See also :envvar:`PYTHON_PRESITE`. It also allows passing arbitrary values and retrieving them through the :data:`sys._xoptions` dictionary. @@ -577,9 +590,7 @@ Miscellaneous options .. versionadded:: 3.10 The ``-X warn_default_encoding`` option. - - .. deprecated-removed:: 3.9 3.10 - The ``-X oldparser`` option. + Removed the ``-X oldparser`` option. .. versionadded:: 3.11 The ``-X no_debug_ranges`` option. @@ -593,11 +604,40 @@ Miscellaneous options .. versionadded:: 3.12 The ``-X perf`` option. + .. versionadded:: 3.13 + The ``-X cpu_count`` option. + + .. versionadded:: 3.13 + The ``-X presite`` option. + +.. _using-on-controlling-color: + +Controlling color +~~~~~~~~~~~~~~~~~ + +The Python interpreter is configured by default to use colors to highlight +output in certain situations such as when displaying tracebacks. This +behavior can be controlled by setting different environment variables. + +Setting the environment variable ``TERM`` to ``dumb`` will disable color. + +If the environment variable ``FORCE_COLOR`` is set, then color will be +enabled regardless of the value of TERM. This is useful on CI systems which +aren’t terminals but can none-the-less display ANSI escape sequences. + +If the environment variable ``NO_COLOR`` is set, Python will disable all color +in the output. This takes precedence over ``FORCE_COLOR``. + +All these environment variables are used also by other tools to control color +output. To control the color output only in the Python interpreter, the +:envvar:`PYTHON_COLORS` environment variable can be used. This variable takes +precedence over ``NO_COLOR``, which in turn takes precedence over +``FORCE_COLOR``. Options you shouldn't use ~~~~~~~~~~~~~~~~~~~~~~~~~ -.. cmdoption:: -J +.. option:: -J Reserved for use by Jython_. @@ -811,8 +851,8 @@ conflict. Defines the :data:`user base directory `, which is used to compute the path of the :data:`user site-packages directory ` - and :ref:`Distutils installation paths ` for - ``python setup.py install --user``. + and :ref:`installation paths ` for + ``python -m pip install --user``. .. seealso:: @@ -851,9 +891,10 @@ conflict. If this environment variable is set to a non-empty string, :func:`faulthandler.enable` is called at startup: install a handler for - :const:`SIGSEGV`, :const:`SIGFPE`, :const:`SIGABRT`, :const:`SIGBUS` and - :const:`SIGILL` signals to dump the Python traceback. This is equivalent to - :option:`-X` ``faulthandler`` option. + :const:`~signal.SIGSEGV`, :const:`~signal.SIGFPE`, + :const:`~signal.SIGABRT`, :const:`~signal.SIGBUS` and + :const:`~signal.SIGILL` signals to dump the Python traceback. + This is equivalent to :option:`-X` ``faulthandler`` option. .. versionadded:: 3.3 @@ -902,6 +943,9 @@ conflict. * ``pymalloc``: use the :ref:`pymalloc allocator ` for :c:macro:`PYMEM_DOMAIN_MEM` and :c:macro:`PYMEM_DOMAIN_OBJ` domains and use the :c:func:`malloc` function for the :c:macro:`PYMEM_DOMAIN_RAW` domain. + * ``mimalloc``: use the :ref:`mimalloc allocator ` for + :c:macro:`PYMEM_DOMAIN_MEM` and :c:macro:`PYMEM_DOMAIN_OBJ` domains and use + the :c:func:`malloc` function for the :c:macro:`PYMEM_DOMAIN_RAW` domain. Install :ref:`debug hooks `: @@ -909,6 +953,7 @@ conflict. allocators `. * ``malloc_debug``: same as ``malloc`` but also install debug hooks. * ``pymalloc_debug``: same as ``pymalloc`` but also install debug hooks. + * ``mimalloc_debug``: same as ``mimalloc`` but also install debug hooks. .. versionchanged:: 3.7 Added the ``"default"`` allocator. @@ -1063,6 +1108,44 @@ conflict. .. versionadded:: 3.12 +.. envvar:: PYTHON_CPU_COUNT + + If this variable is set to a positive integer, it overrides the return + values of :func:`os.cpu_count` and :func:`os.process_cpu_count`. + + See also the :option:`-X cpu_count <-X>` command-line option. + + .. versionadded:: 3.13 + +.. envvar:: PYTHON_FROZEN_MODULES + + If this variable is set to ``on`` or ``off``, it determines whether or not + frozen modules are ignored by the import machinery. A value of ``on`` means + they get imported and ``off`` means they are ignored. The default is ``on`` + for non-debug builds (the normal case) and ``off`` for debug builds. + Note that the :mod:`!importlib_bootstrap` and + :mod:`!importlib_bootstrap_external` frozen modules are always used, even + if this flag is set to ``off``. + + See also the :option:`-X frozen_modules <-X>` command-line option. + + .. versionadded:: 3.13 + +.. envvar:: PYTHON_COLORS + + If this variable is set to ``1``, the interpreter will colorize various kinds + of output. Setting it to ``0`` deactivates this behavior. + See also :ref:`using-on-controlling-color`. + + .. versionadded:: 3.13 + +.. envvar:: PYTHON_HISTORY + + This environment variable can be used to set the location of a + ``.python_history`` file (by default, it is ``.python_history`` in the + user's home directory). + + .. versionadded:: 3.13 Debug-mode variables ~~~~~~~~~~~~~~~~~~~~ @@ -1072,13 +1155,33 @@ Debug-mode variables If set, Python will dump objects and reference counts still alive after shutting down the interpreter. - Need Python configured with the :option:`--with-trace-refs` build option. + Needs Python configured with the :option:`--with-trace-refs` build option. -.. envvar:: PYTHONDUMPREFSFILE=FILENAME +.. envvar:: PYTHONDUMPREFSFILE If set, Python will dump objects and reference counts still alive - after shutting down the interpreter into a file called *FILENAME*. + after shutting down the interpreter into a file under the path given + as the value to this environment variable. - Need Python configured with the :option:`--with-trace-refs` build option. + Needs Python configured with the :option:`--with-trace-refs` build option. .. versionadded:: 3.11 + +.. envvar:: PYTHON_PRESITE + + If this variable is set to a module, that module will be imported + early in the interpreter lifecycle, before the :mod:`site` module is + executed, and before the :mod:`__main__` module is created. + Therefore, the imported module is not treated as :mod:`__main__`. + + This can be used to execute code early during Python initialization. + + To import a submodule, use ``package.module`` as the value, like in + an import statement. + + See also the :option:`-X presite <-X>` command-line option, + which takes precedence over this variable. + + Needs Python configured with the :option:`--with-pydebug` build option. + + .. versionadded:: 3.13 diff --git a/Doc/using/configure.rst b/Doc/using/configure.rst index 924e73dc54da2e..aab9469b44828a 100644 --- a/Doc/using/configure.rst +++ b/Doc/using/configure.rst @@ -5,29 +5,42 @@ Configure Python Build Requirements ================== -Features required to build CPython: +Features and minimum versions required to build CPython: * A `C11 `_ compiler. `Optional C11 features `_ are not required. +* On Windows, Microsoft Visual Studio 2017 or later is required. + * Support for `IEEE 754 `_ floating point numbers and `floating point Not-a-Number (NaN) `_. * Support for threads. -* OpenSSL 1.1.1 or newer for the :mod:`ssl` and :mod:`hashlib` modules. +* OpenSSL 1.1.1 is the minimum version and OpenSSL 3.0.9 is the recommended + minimum version for the :mod:`ssl` and :mod:`hashlib` extension modules. -* On Windows, Microsoft Visual Studio 2017 or later is required. +* SQLite 3.15.2 for the :mod:`sqlite3` extension module. + +* Tcl/Tk 8.5.12 for the :mod:`tkinter` module. + +* Autoconf 2.71 and aclocal 1.16.4 are required to regenerate the + :file:`configure` script. + +.. versionchanged:: 3.13: + Autoconf 2.71, aclocal 1.16.4 and SQLite 3.15.2 are now required. .. versionchanged:: 3.11 C11 compiler, IEEE 754 and NaN support are now required. On Windows, Visual Studio 2017 or later is required. + Tcl/Tk version 8.5.12 is now required for the :mod:`tkinter` module. .. versionchanged:: 3.10 OpenSSL 1.1.1 is now required. + Require SQLite 3.7.15. .. versionchanged:: 3.7 Thread support and OpenSSL 1.0.2 are now required. @@ -37,18 +50,52 @@ Features required to build CPython: inline`` functions. .. versionchanged:: 3.5 - On Windows, Visual Studio 2015 or later is required. + On Windows, Visual Studio 2015 or later is now required. + Tcl/Tk version 8.4 is now required. + +.. versionchanged:: 3.1 + Tcl/Tk version 8.3.1 is now required. See also :pep:`7` "Style Guide for C Code" and :pep:`11` "CPython platform support". +Generated files +=============== + +To reduce build dependencies, Python source code contains multiple generated +files. Commands to regenerate all generated files:: + + make regen-all + make regen-stdlib-module-names + make regen-limited-abi + make regen-configure + +The ``Makefile.pre.in`` file documents generated files, their inputs, and tools used +to regenerate them. Search for ``regen-*`` make targets. + +configure script +---------------- + +The ``make regen-configure`` command regenerates the ``aclocal.m4`` file and +the ``configure`` script using the ``Tools/build/regen-configure.sh`` shell +script which uses an Ubuntu container to get the same tools versions and have a +reproducible output. + +The container is optional, the following command can be run locally:: + + autoreconf -ivf -Werror + +The generated files can change depending on the exact ``autoconf-archive``, +``aclocal`` and ``pkg-config`` versions. + + .. _configure-options: Configure Options ================= -List all ``./configure`` script options using:: +List all :file:`configure` script options using:: ./configure --help @@ -57,22 +104,22 @@ See also the :file:`Misc/SpecialBuilds.txt` in the Python source distribution. General Options --------------- -.. cmdoption:: --enable-loadable-sqlite-extensions +.. option:: --enable-loadable-sqlite-extensions - Support loadable extensions in the :mod:`_sqlite` extension module (default - is no). + Support loadable extensions in the :mod:`!_sqlite` extension module (default + is no) of the :mod:`sqlite3` module. See the :meth:`sqlite3.Connection.enable_load_extension` method of the :mod:`sqlite3` module. .. versionadded:: 3.6 -.. cmdoption:: --disable-ipv6 +.. option:: --disable-ipv6 Disable IPv6 support (enabled by default if supported), see the :mod:`socket` module. -.. cmdoption:: --enable-big-digits=[15|30] +.. option:: --enable-big-digits=[15|30] Define the size in bits of Python :class:`int` digits: 15 or 30 bits. @@ -82,7 +129,7 @@ General Options See :data:`sys.int_info.bits_per_digit `. -.. cmdoption:: --with-suffix=SUFFIX +.. option:: --with-suffix=SUFFIX Set the Python executable suffix to *SUFFIX*. @@ -95,7 +142,7 @@ General Options The default suffix on WASM platform is one of ``.js``, ``.html`` or ``.wasm``. -.. cmdoption:: --with-tzpath= +.. option:: --with-tzpath= Select the default time zone search path for :const:`zoneinfo.TZPATH`. See the :ref:`Compile-time configuration @@ -107,7 +154,7 @@ General Options .. versionadded:: 3.9 -.. cmdoption:: --without-decimal-contextvar +.. option:: --without-decimal-contextvar Build the ``_decimal`` extension module using a thread-local context rather than a coroutine-local context (default), see the :mod:`decimal` module. @@ -116,7 +163,7 @@ General Options .. versionadded:: 3.9 -.. cmdoption:: --with-dbmliborder= +.. option:: --with-dbmliborder= Override order to check db backends for the :mod:`dbm` module @@ -126,7 +173,7 @@ General Options * ``gdbm``; * ``bdb``. -.. cmdoption:: --without-c-locale-coercion +.. option:: --without-c-locale-coercion Disable C locale coercion to a UTF-8 based locale (enabled by default). @@ -134,13 +181,13 @@ General Options See :envvar:`PYTHONCOERCECLOCALE` and the :pep:`538`. -.. cmdoption:: --without-freelists +.. option:: --without-freelists Disable all freelists except the empty tuple singleton. .. versionadded:: 3.11 -.. cmdoption:: --with-platlibdir=DIRNAME +.. option:: --with-platlibdir=DIRNAME Python library directory name (default is ``lib``). @@ -150,7 +197,7 @@ General Options .. versionadded:: 3.9 -.. cmdoption:: --with-wheel-pkg-dir=PATH +.. option:: --with-wheel-pkg-dir=PATH Directory of wheel packages used by the :mod:`ensurepip` module (none by default). @@ -158,11 +205,11 @@ General Options Some Linux distribution packaging policies recommend against bundling dependencies. For example, Fedora installs wheel packages in the ``/usr/share/python-wheels/`` directory and don't install the - :mod:`ensurepip._bundled` package. + :mod:`!ensurepip._bundled` package. .. versionadded:: 3.10 -.. cmdoption:: --with-pkg-config=[check|yes|no] +.. option:: --with-pkg-config=[check|yes|no] Whether configure should use :program:`pkg-config` to detect build dependencies. @@ -173,22 +220,221 @@ General Options .. versionadded:: 3.11 -.. cmdoption:: --enable-pystats +.. option:: --enable-pystats + + Turn on internal Python performance statistics gathering. + + By default, statistics gathering is off. Use ``python3 -X pystats`` command + or set ``PYTHONSTATS=1`` environment variable to turn on statistics + gathering at Python startup. + + At Python exit, dump statistics if statistics gathering was on and not + cleared. + + Effects: + + * Add :option:`-X pystats <-X>` command line option. + * Add :envvar:`!PYTHONSTATS` environment variable. + * Define the ``Py_STATS`` macro. + * Add functions to the :mod:`sys` module: - Turn on internal statistics gathering. + * :func:`!sys._stats_on`: Turns on statistics gathering. + * :func:`!sys._stats_off`: Turns off statistics gathering. + * :func:`!sys._stats_clear`: Clears the statistics. + * :func:`!sys._stats_dump`: Dump statistics to file, and clears the statistics. The statistics will be dumped to a arbitrary (probably unique) file in - ``/tmp/py_stats/``, or ``C:\temp\py_stats\`` on Windows. If that directory - does not exist, results will be printed on stdout. + ``/tmp/py_stats/`` (Unix) or ``C:\temp\py_stats\`` (Windows). If that + directory does not exist, results will be printed on stderr. Use ``Tools/scripts/summarize_stats.py`` to read the stats. + Statistics: + + * Opcode: + + * Specialization: success, failure, hit, deferred, miss, deopt, failures; + * Execution count; + * Pair count. + + * Call: + + * Inlined Python calls; + * PyEval calls; + * Frames pushed; + * Frame object created; + * Eval calls: vector, generator, legacy, function VECTORCALL, build class, + slot, function "ex", API, method. + + * Object: + + * incref and decref; + * interpreter incref and decref; + * allocations: all, 512 bytes, 4 kiB, big; + * free; + * to/from free lists; + * dictionary materialized/dematerialized; + * type cache; + * optimization attemps; + * optimization traces created/executed; + * uops executed. + + * Garbage collector: + + * Garbage collections; + * Objects visited; + * Objects collected. + .. versionadded:: 3.11 +.. _free-threading-build: + +.. option:: --disable-gil + + Enables **experimental** support for running Python without the + :term:`global interpreter lock` (GIL): free threading build. + + Defines the ``Py_GIL_DISABLED`` macro and adds ``"t"`` to + :data:`sys.abiflags`. + + See :pep:`703` "Making the Global Interpreter Lock Optional in CPython". + + .. versionadded:: 3.13 + +.. option:: PKG_CONFIG + + Path to ``pkg-config`` utility. + +.. option:: PKG_CONFIG_LIBDIR +.. option:: PKG_CONFIG_PATH + + ``pkg-config`` options. + + +C compiler options +------------------ + +.. option:: CC + + C compiler command. + +.. option:: CFLAGS + + C compiler flags. + +.. option:: CPP + + C preprocessor command. + +.. option:: CPPFLAGS + + C preprocessor flags, e.g. :samp:`-I{include_dir}`. + + +Linker options +-------------- + +.. option:: LDFLAGS + + Linker flags, e.g. :samp:`-L{library_directory}`. + +.. option:: LIBS + + Libraries to pass to the linker, e.g. :samp:`-l{library}`. + +.. option:: MACHDEP + + Name for machine-dependent library files. + + +Options for third-party dependencies +------------------------------------ + +.. versionadded:: 3.11 + +.. option:: BZIP2_CFLAGS +.. option:: BZIP2_LIBS + + C compiler and linker flags to link Python to ``libbz2``, used by :mod:`bz2` + module, overriding ``pkg-config``. + +.. option:: CURSES_CFLAGS +.. option:: CURSES_LIBS + + C compiler and linker flags for ``libncurses`` or ``libncursesw``, used by + :mod:`curses` module, overriding ``pkg-config``. + +.. option:: GDBM_CFLAGS +.. option:: GDBM_LIBS + + C compiler and linker flags for ``gdbm``. + +.. option:: LIBB2_CFLAGS +.. option:: LIBB2_LIBS + + C compiler and linker flags for ``libb2`` (:ref:`BLAKE2 `), + used by :mod:`hashlib` module, overriding ``pkg-config``. + +.. option:: LIBEDIT_CFLAGS +.. option:: LIBEDIT_LIBS + + C compiler and linker flags for ``libedit``, used by :mod:`readline` module, + overriding ``pkg-config``. + +.. option:: LIBFFI_CFLAGS +.. option:: LIBFFI_LIBS + + C compiler and linker flags for ``libffi``, used by :mod:`ctypes` module, + overriding ``pkg-config``. + +.. option:: LIBLZMA_CFLAGS +.. option:: LIBLZMA_LIBS + + C compiler and linker flags for ``liblzma``, used by :mod:`lzma` module, + overriding ``pkg-config``. + +.. option:: LIBREADLINE_CFLAGS +.. option:: LIBREADLINE_LIBS + + C compiler and linker flags for ``libreadline``, used by :mod:`readline` + module, overriding ``pkg-config``. + +.. option:: LIBSQLITE3_CFLAGS +.. option:: LIBSQLITE3_LIBS + + C compiler and linker flags for ``libsqlite3``, used by :mod:`sqlite3` + module, overriding ``pkg-config``. + +.. option:: LIBUUID_CFLAGS +.. option:: LIBUUID_LIBS + + C compiler and linker flags for ``libuuid``, used by :mod:`uuid` module, + overriding ``pkg-config``. + +.. option:: PANEL_CFLAGS +.. option:: PANEL_LIBS + + C compiler and Linker flags for PANEL, overriding ``pkg-config``. + + C compiler and linker flags for ``libpanel`` or ``libpanelw``, used by + :mod:`curses.panel` module, overriding ``pkg-config``. + +.. option:: TCLTK_CFLAGS +.. option:: TCLTK_LIBS + + C compiler and linker flags for TCLTK, overriding ``pkg-config``. + +.. option:: ZLIB_CFLAGS +.. option:: ZLIB_LIBS + + C compiler and linker flags for ``libzlib``, used by :mod:`gzip` module, + overriding ``pkg-config``. + + WebAssembly Options ------------------- -.. cmdoption:: --with-emscripten-target=[browser|node] +.. option:: --with-emscripten-target=[browser|node] Set build flavor for ``wasm32-emscripten``. @@ -197,7 +443,7 @@ WebAssembly Options .. versionadded:: 3.11 -.. cmdoption:: --enable-wasm-dynamic-linking +.. option:: --enable-wasm-dynamic-linking Turn on dynamic linking support for WASM. @@ -206,7 +452,7 @@ WebAssembly Options .. versionadded:: 3.11 -.. cmdoption:: --enable-wasm-pthreads +.. option:: --enable-wasm-pthreads Turn on pthreads support for WASM. @@ -216,30 +462,30 @@ WebAssembly Options Install Options --------------- -.. cmdoption:: --prefix=PREFIX +.. option:: --prefix=PREFIX Install architecture-independent files in PREFIX. On Unix, it defaults to :file:`/usr/local`. - This value can be retrived at runtime using :data:`sys.prefix`. + This value can be retrieved at runtime using :data:`sys.prefix`. As an example, one can use ``--prefix="$HOME/.local/"`` to install a Python in its home directory. -.. cmdoption:: --exec-prefix=EPREFIX +.. option:: --exec-prefix=EPREFIX Install architecture-dependent files in EPREFIX, defaults to :option:`--prefix`. - This value can be retrived at runtime using :data:`sys.exec_prefix`. + This value can be retrieved at runtime using :data:`sys.exec_prefix`. -.. cmdoption:: --disable-test-modules +.. option:: --disable-test-modules Don't build nor install test modules, like the :mod:`test` package or the - :mod:`_testcapi` extension module (built and installed by default). + :mod:`!_testcapi` extension module (built and installed by default). .. versionadded:: 3.10 -.. cmdoption:: --with-ensurepip=[upgrade|install|no] +.. option:: --with-ensurepip=[upgrade|install|no] Select the :mod:`ensurepip` command run on Python installation: @@ -258,7 +504,7 @@ Configuring Python using ``--enable-optimizations --with-lto`` (PGO + LTO) is recommended for best performance. The experimental ``--enable-bolt`` flag can also be used to improve performance. -.. cmdoption:: --enable-optimizations +.. option:: --enable-optimizations Enable Profile Guided Optimization (PGO) using :envvar:`PROFILE_TASK` (disabled by default). @@ -284,7 +530,10 @@ also be used to improve performance. .. versionadded:: 3.8 -.. cmdoption:: --with-lto=[full|thin|no|yes] + .. versionchanged:: 3.13 + Task failure is no longer ignored silently. + +.. option:: --with-lto=[full|thin|no|yes] Enable Link Time Optimization (LTO) in any build (disabled by default). @@ -299,7 +548,7 @@ also be used to improve performance. .. versionchanged:: 3.12 Use ThinLTO as the default optimization policy on Clang if the compiler accepts the flag. -.. cmdoption:: --enable-bolt +.. option:: --enable-bolt Enable usage of the `BOLT post-link binary optimizer `_ (disabled by @@ -324,19 +573,39 @@ also be used to improve performance. .. versionadded:: 3.12 -.. cmdoption:: --with-computed-gotos +.. option:: BOLT_APPLY_FLAGS + + Arguments to ``llvm-bolt`` when creating a `BOLT optimized binary + `_. + + .. versionadded:: 3.12 + +.. option:: BOLT_INSTRUMENT_FLAGS + + Arguments to ``llvm-bolt`` when instrumenting binaries. + + .. versionadded:: 3.12 + +.. option:: --with-computed-gotos Enable computed gotos in evaluation loop (enabled by default on supported compilers). -.. cmdoption:: --without-pymalloc +.. option:: --without-mimalloc + + Disable the fast mimalloc allocator :ref:`mimalloc ` + (enabled by default). + + See also :envvar:`PYTHONMALLOC` environment variable. + +.. option:: --without-pymalloc Disable the specialized Python memory allocator :ref:`pymalloc ` (enabled by default). See also :envvar:`PYTHONMALLOC` environment variable. -.. cmdoption:: --without-doc-strings +.. option:: --without-doc-strings Disable static documentation strings to reduce the memory footprint (enabled by default). Documentation strings defined in Python are not affected. @@ -345,11 +614,11 @@ also be used to improve performance. See the ``PyDoc_STRVAR()`` macro. -.. cmdoption:: --enable-profiling +.. option:: --enable-profiling Enable C-level code profiling with ``gprof`` (disabled by default). -.. cmdoption:: --with-strict-overflow +.. option:: --with-strict-overflow Add ``-fstrict-overflow`` to the C compiler flags (by default we add ``-fno-strict-overflow`` instead). @@ -368,7 +637,7 @@ Effects of a debug build: * Display all warnings by default: the list of default warning filters is empty in the :mod:`warnings` module. * Add ``d`` to :data:`sys.abiflags`. -* Add :func:`sys.gettotalrefcount` function. +* Add :func:`!sys.gettotalrefcount` function. * Add :option:`-X showrefcount <-X>` command line option. * Add :option:`-d` command line option and :envvar:`PYTHONDEBUG` environment variable to debug the parser. @@ -390,7 +659,7 @@ Effects of a debug build: * Check that deallocator functions don't change the current exception. * The garbage collector (:func:`gc.collect` function) runs some basic checks on objects consistency. - * The :c:macro:`Py_SAFE_DOWNCAST()` macro checks for integer underflow and + * The :c:macro:`!Py_SAFE_DOWNCAST()` macro checks for integer underflow and overflow when downcasting from wide types to narrow types. See also the :ref:`Python Development Mode ` and the @@ -399,34 +668,39 @@ See also the :ref:`Python Development Mode ` and the .. versionchanged:: 3.8 Release builds and debug builds are now ABI compatible: defining the ``Py_DEBUG`` macro no longer implies the ``Py_TRACE_REFS`` macro (see the - :option:`--with-trace-refs` option), which introduces the only ABI - incompatibility. + :option:`--with-trace-refs` option). Debug options ------------- -.. cmdoption:: --with-pydebug +.. option:: --with-pydebug :ref:`Build Python in debug mode `: define the ``Py_DEBUG`` macro (disabled by default). -.. cmdoption:: --with-trace-refs +.. option:: --with-trace-refs Enable tracing references for debugging purpose (disabled by default). Effects: * Define the ``Py_TRACE_REFS`` macro. - * Add :func:`sys.getobjects` function. + * Add :func:`!sys.getobjects` function. * Add :envvar:`PYTHONDUMPREFS` environment variable. - This build is not ABI compatible with release build (default build) or debug - build (``Py_DEBUG`` and ``Py_REF_DEBUG`` macros). + The :envvar:`PYTHONDUMPREFS` environment variable can be used to dump + objects and reference counts still alive at Python exit. + + :ref:`Statically allocated objects ` are not traced. + + .. versionchanged:: 3.13 + This build is now ABI compatible with release build and :ref:`debug build + `. .. versionadded:: 3.8 -.. cmdoption:: --with-assertions +.. option:: --with-assertions Build with C assertions enabled (default is no): ``assert(...);`` and ``_PyObject_ASSERT(...);``. @@ -439,11 +713,11 @@ Debug options .. versionadded:: 3.6 -.. cmdoption:: --with-valgrind +.. option:: --with-valgrind Enable Valgrind support (default is no). -.. cmdoption:: --with-dtrace +.. option:: --with-dtrace Enable DTrace support (default is no). @@ -452,34 +726,41 @@ Debug options .. versionadded:: 3.6 -.. cmdoption:: --with-address-sanitizer +.. option:: --with-address-sanitizer Enable AddressSanitizer memory error detector, ``asan`` (default is no). .. versionadded:: 3.6 -.. cmdoption:: --with-memory-sanitizer +.. option:: --with-memory-sanitizer Enable MemorySanitizer allocation error detector, ``msan`` (default is no). .. versionadded:: 3.6 -.. cmdoption:: --with-undefined-behavior-sanitizer +.. option:: --with-undefined-behavior-sanitizer Enable UndefinedBehaviorSanitizer undefined behaviour detector, ``ubsan`` (default is no). .. versionadded:: 3.6 +.. option:: --with-thread-sanitizer + + Enable ThreadSanitizer data race detector, ``tsan`` + (default is no). + + .. versionadded:: 3.13 + Linker options -------------- -.. cmdoption:: --enable-shared +.. option:: --enable-shared Enable building a shared Python library: ``libpython`` (default is no). -.. cmdoption:: --without-static-libpython +.. option:: --without-static-libpython Do not build ``libpythonMAJOR.MINOR.a`` and do not install ``python.o`` (built and enabled by default). @@ -490,31 +771,32 @@ Linker options Libraries options ----------------- -.. cmdoption:: --with-libs='lib1 ...' +.. option:: --with-libs='lib1 ...' Link against additional libraries (default is no). -.. cmdoption:: --with-system-expat +.. option:: --with-system-expat - Build the :mod:`pyexpat` module using an installed ``expat`` library + Build the :mod:`!pyexpat` module using an installed ``expat`` library (default is no). -.. cmdoption:: --with-system-libmpdec +.. option:: --with-system-libmpdec Build the ``_decimal`` extension module using an installed ``mpdec`` library, see the :mod:`decimal` module (default is no). .. versionadded:: 3.3 -.. cmdoption:: --with-readline=editline +.. option:: --with-readline=readline|editline - Use ``editline`` library for backend of the :mod:`readline` module. + Designate a backend library for the :mod:`readline` module. - Define the ``WITH_EDITLINE`` macro. + * readline: Use readline as the backend. + * editline: Use editline as the backend. .. versionadded:: 3.10 -.. cmdoption:: --without-readline +.. option:: --without-readline Don't build the :mod:`readline` module (built by default). @@ -522,21 +804,21 @@ Libraries options .. versionadded:: 3.10 -.. cmdoption:: --with-libm=STRING +.. option:: --with-libm=STRING Override ``libm`` math library to *STRING* (default is system-dependent). -.. cmdoption:: --with-libc=STRING +.. option:: --with-libc=STRING Override ``libc`` C library to *STRING* (default is system-dependent). -.. cmdoption:: --with-openssl=DIR +.. option:: --with-openssl=DIR Root of the OpenSSL directory. .. versionadded:: 3.7 -.. cmdoption:: --with-openssl-rpath=[no|auto|DIR] +.. option:: --with-openssl-rpath=[no|auto|DIR] Set runtime library directory (rpath) for OpenSSL libraries: @@ -551,7 +833,7 @@ Libraries options Security Options ---------------- -.. cmdoption:: --with-hash-algorithm=[fnv|siphash13|siphash24] +.. option:: --with-hash-algorithm=[fnv|siphash13|siphash24] Select hash algorithm for use in ``Python/pyhash.c``: @@ -564,7 +846,7 @@ Security Options .. versionadded:: 3.11 ``siphash13`` is added and it is the new default. -.. cmdoption:: --with-builtin-hashlib-hashes=md5,sha1,sha256,sha512,sha3,blake2 +.. option:: --with-builtin-hashlib-hashes=md5,sha1,sha256,sha512,sha3,blake2 Built-in hash modules: @@ -577,7 +859,7 @@ Security Options .. versionadded:: 3.9 -.. cmdoption:: --with-ssl-default-suites=[python|openssl|STRING] +.. option:: --with-ssl-default-suites=[python|openssl|STRING] Override the OpenSSL default cipher suites string: @@ -599,19 +881,19 @@ macOS Options See ``Mac/README.rst``. -.. cmdoption:: --enable-universalsdk -.. cmdoption:: --enable-universalsdk=SDKDIR +.. option:: --enable-universalsdk +.. option:: --enable-universalsdk=SDKDIR Create a universal binary build. *SDKDIR* specifies which macOS SDK should be used to perform the build (default is no). -.. cmdoption:: --enable-framework -.. cmdoption:: --enable-framework=INSTALLDIR +.. option:: --enable-framework +.. option:: --enable-framework=INSTALLDIR Create a Python.framework rather than a traditional Unix install. Optional *INSTALLDIR* specifies the installation path (default is no). -.. cmdoption:: --with-universal-archs=ARCH +.. option:: --with-universal-archs=ARCH Specify the kind of universal binary that should be created. This option is only valid when :option:`--enable-universalsdk` is set. @@ -627,7 +909,7 @@ See ``Mac/README.rst``. * ``intel-64``; * ``all``. -.. cmdoption:: --with-framework-name=FRAMEWORK +.. option:: --with-framework-name=FRAMEWORK Specify the name for the python framework on macOS only valid when :option:`--enable-framework` is set (default: ``Python``). @@ -641,21 +923,21 @@ for another CPU architecture or platform. Cross compiling requires a Python interpreter for the build platform. The version of the build Python must match the version of the cross compiled host Python. -.. cmdoption:: --build=BUILD +.. option:: --build=BUILD configure for building on BUILD, usually guessed by :program:`config.guess`. -.. cmdoption:: --host=HOST +.. option:: --host=HOST cross-compile to build programs to run on HOST (target platform) -.. cmdoption:: --with-build-python=path/to/python +.. option:: --with-build-python=path/to/python path to build ``python`` binary for cross compiling .. versionadded:: 3.11 -.. cmdoption:: CONFIG_SITE=file +.. option:: CONFIG_SITE=file An environment variable that points to a file with configure overrides. @@ -666,6 +948,12 @@ the version of the cross compiled host Python. ac_cv_file__dev_ptmx=yes ac_cv_file__dev_ptc=no +.. option:: HOSTRUNNER + + Program to run CPython for the host platform for cross-compilation. + + .. versionadded:: 3.11 + Cross compiling example:: @@ -686,7 +974,6 @@ Main files of the build system * :file:`pyconfig.h` (created by :file:`configure`); * :file:`Modules/Setup`: C extensions built by the Makefile using :file:`Module/makesetup` shell script; -* :file:`setup.py`: C extensions built using the ``setuptools`` package. Main build steps ---------------- @@ -695,8 +982,7 @@ Main build steps * A static ``libpython`` library (``.a``) is created from objects files. * ``python.o`` and the static ``libpython`` library are linked into the final ``python`` program. -* C extensions are built by the Makefile (see :file:`Modules/Setup`) - and ``python setup.py build``. +* C extensions are built by the Makefile (see :file:`Modules/Setup`). Main Makefile targets --------------------- @@ -708,9 +994,18 @@ Main Makefile targets You can use the configure :option:`--enable-optimizations` option to make this the default target of the ``make`` command (``make all`` or just ``make``). -* ``make buildbottest``: Build Python and run the Python test suite, the same - way than buildbots test Python. Set ``TESTTIMEOUT`` variable (in seconds) - to change the test timeout (1200 by default: 20 minutes). + +* ``make test``: Build Python and run the Python test suite with ``--fast-ci`` + option. Variables: + + * ``TESTOPTS``: additional regrtest command line options. + * ``TESTPYTHONOPTS``: additional Python command line options. + * ``TESTTIMEOUT``: timeout in seconds (default: 20 minutes). + +* ``make buildbottest``: Similar to ``make test``, but use ``--slow-ci`` + option and default timeout of 20 minutes, instead of ``--fast-ci`` option + and a default timeout of 10 minutes. + * ``make install``: Build and install Python. * ``make regen-all``: Regenerate (almost) all generated files; ``make regen-stdlib-module-names`` and ``autoconf`` must be run separately @@ -748,18 +1043,15 @@ Example on Linux x86-64:: At the beginning of the files, C extensions are built as built-in modules. Extensions defined after the ``*shared*`` marker are built as dynamic libraries. -The :file:`setup.py` script only builds C extensions as shared libraries using -the :mod:`distutils` module. - -The :c:macro:`PyAPI_FUNC()`, :c:macro:`PyAPI_API()` and -:c:macro:`PyMODINIT_FUNC()` macros of :file:`Include/pyport.h` are defined +The :c:macro:`!PyAPI_FUNC()`, :c:macro:`!PyAPI_DATA()` and +:c:macro:`PyMODINIT_FUNC` macros of :file:`Include/exports.h` are defined differently depending if the ``Py_BUILD_CORE_MODULE`` macro is defined: * Use ``Py_EXPORTED_SYMBOL`` if the ``Py_BUILD_CORE_MODULE`` is defined * Use ``Py_IMPORTED_SYMBOL`` otherwise. If the ``Py_BUILD_CORE_BUILTIN`` macro is used by mistake on a C extension -built as a shared library, its ``PyInit_xxx()`` function is not exported, +built as a shared library, its :samp:`PyInit_{xxx}()` function is not exported, causing an :exc:`ImportError` on import. @@ -780,11 +1072,11 @@ Preprocessor flags .. envvar:: CPPFLAGS - (Objective) C/C++ preprocessor flags, e.g. ``-I`` if you have - headers in a nonstandard directory ````. + (Objective) C/C++ preprocessor flags, e.g. :samp:`-I{include_dir}` if you have + headers in a nonstandard directory *include_dir*. Both :envvar:`CPPFLAGS` and :envvar:`LDFLAGS` need to contain the shell's - value for setup.py to be able to build extension modules using the + value to be able to build extension modules using the directories specified in the environment variables. .. envvar:: BASECPPFLAGS @@ -821,8 +1113,8 @@ Compiler flags .. envvar:: CFLAGS_NODIST :envvar:`CFLAGS_NODIST` is used for building the interpreter and stdlib C - extensions. Use it when a compiler flag should *not* be part of the - distutils :envvar:`CFLAGS` once Python is installed (:issue:`21121`). + extensions. Use it when a compiler flag should *not* be part of + :envvar:`CFLAGS` once Python is installed (:gh:`65320`). In particular, :envvar:`CFLAGS` should not contain: @@ -952,7 +1244,7 @@ Linker flags :envvar:`LDFLAGS_NODIST` is used in the same manner as :envvar:`CFLAGS_NODIST`. Use it when a linker flag should *not* be part of - the distutils :envvar:`LDFLAGS` once Python is installed (:issue:`35257`). + :envvar:`LDFLAGS` once Python is installed (:gh:`65320`). In particular, :envvar:`LDFLAGS` should not contain: @@ -970,11 +1262,11 @@ Linker flags .. envvar:: LDFLAGS - Linker flags, e.g. ``-L`` if you have libraries in a nonstandard - directory ````. + Linker flags, e.g. :samp:`-L{lib_dir}` if you have libraries in a nonstandard + directory *lib_dir*. Both :envvar:`CPPFLAGS` and :envvar:`LDFLAGS` need to contain the shell's - value for setup.py to be able to build extension modules using the + value to be able to build extension modules using the directories specified in the environment variables. .. envvar:: LIBS diff --git a/Doc/using/mac.rst b/Doc/using/mac.rst index 65178272862168..eb1413af2cbc3d 100644 --- a/Doc/using/mac.rst +++ b/Doc/using/mac.rst @@ -125,13 +125,9 @@ http://www.hashcollision.org/hkn/python/idle_intro/index.html. Installing Additional Python Packages ===================================== -There are several methods to install additional Python packages: +This section has moved to the `Python Packaging User Guide`_. -* Packages can be installed via the standard Python distutils mode (``python - setup.py install``). - -* Many packages can also be installed via the :program:`setuptools` extension - or :program:`pip` wrapper, see https://pip.pypa.io/. +.. _Python Packaging User Guide: https://packaging.python.org/en/latest/tutorials/installing-packages/ GUI Programming on the Mac diff --git a/Doc/using/unix.rst b/Doc/using/unix.rst index 0044eb07f56eec..58838c28e6eb86 100644 --- a/Doc/using/unix.rst +++ b/Doc/using/unix.rst @@ -30,9 +30,9 @@ following links: for Debian users https://en.opensuse.org/Portal:Packaging for OpenSuse users - https://docs-old.fedoraproject.org/en-US/Fedora_Draft_Documentation/0.1/html/RPM_Guide/ch-creating-rpms.html + https://docs.fedoraproject.org/en-US/package-maintainers/Packaging_Tutorial_GNU_Hello/ for Fedora users - http://www.slackbook.org/html/package-management-making-packages.html + https://slackbook.org/html/package-management-making-packages.html for Slackware users diff --git a/Doc/using/venv-create.inc b/Doc/using/venv-create.inc index 2fc90126482268..1cf438b198a9af 100644 --- a/Doc/using/venv-create.inc +++ b/Doc/using/venv-create.inc @@ -35,37 +35,48 @@ your :ref:`Python installation `:: The command, if run with ``-h``, will show the available options:: - usage: venv [-h] [--system-site-packages] [--symlinks | --copies] [--clear] - [--upgrade] [--without-pip] [--prompt PROMPT] [--upgrade-deps] - ENV_DIR [ENV_DIR ...] - - Creates virtual Python environments in one or more target directories. - - positional arguments: - ENV_DIR A directory to create the environment in. - - optional arguments: - -h, --help show this help message and exit - --system-site-packages - Give the virtual environment access to the system - site-packages dir. - --symlinks Try to use symlinks rather than copies, when symlinks - are not the default for the platform. - --copies Try to use copies rather than symlinks, even when - symlinks are the default for the platform. - --clear Delete the contents of the environment directory if it - already exists, before environment creation. - --upgrade Upgrade the environment directory to use this version - of Python, assuming Python has been upgraded in-place. - --without-pip Skips installing or upgrading pip in the virtual - environment (pip is bootstrapped by default) - --prompt PROMPT Provides an alternative prompt prefix for this - environment. - --upgrade-deps Upgrade core dependencies (pip) to the - latest version in PyPI - - Once an environment has been created, you may wish to activate it, e.g. by - sourcing an activate script in its bin directory. + usage: venv [-h] [--system-site-packages] [--symlinks | --copies] [--clear] + [--upgrade] [--without-pip] [--prompt PROMPT] [--upgrade-deps] + [--without-scm-ignore-file] + ENV_DIR [ENV_DIR ...] + + Creates virtual Python environments in one or more target directories. + + positional arguments: + ENV_DIR A directory to create the environment in. + + options: + -h, --help show this help message and exit + --system-site-packages + Give the virtual environment access to the system + site-packages dir. + --symlinks Try to use symlinks rather than copies, when + symlinks are not the default for the platform. + --copies Try to use copies rather than symlinks, even when + symlinks are the default for the platform. + --clear Delete the contents of the environment directory if + it already exists, before environment creation. + --upgrade Upgrade the environment directory to use this + version of Python, assuming Python has been upgraded + in-place. + --without-pip Skips installing or upgrading pip in the virtual + environment (pip is bootstrapped by default) + --prompt PROMPT Provides an alternative prompt prefix for this + environment. + --upgrade-deps Upgrade core dependencies (pip) to the latest + version in PyPI + --without-scm-ignore-file + Skips adding the default SCM ignore file to the + environment directory (the default is a .gitignore + file). + + Once an environment has been created, you may wish to activate it, e.g. by + sourcing an activate script in its bin directory. + +.. versionchanged:: 3.13 + + ``--without-scm-ignore-file`` was added along with creating an ignore file + for ``git`` by default. .. versionchanged:: 3.12 diff --git a/Doc/using/windows.rst b/Doc/using/windows.rst index d24450e2f963ff..598bf3ca9bcc04 100644 --- a/Doc/using/windows.rst +++ b/Doc/using/windows.rst @@ -867,17 +867,18 @@ For example, if the first line of your script starts with #! /usr/bin/python -The default Python will be located and used. As many Python scripts written -to work on Unix will already have this line, you should find these scripts can -be used by the launcher without modification. If you are writing a new script -on Windows which you hope will be useful on Unix, you should use one of the -shebang lines starting with ``/usr``. +The default Python or an active virtual environment will be located and used. +As many Python scripts written to work on Unix will already have this line, +you should find these scripts can be used by the launcher without modification. +If you are writing a new script on Windows which you hope will be useful on +Unix, you should use one of the shebang lines starting with ``/usr``. Any of the above virtual commands can be suffixed with an explicit version (either just the major version, or the major and minor version). Furthermore the 32-bit version can be requested by adding "-32" after the minor version. I.e. ``/usr/bin/python3.7-32`` will request usage of the -32-bit python 3.7. +32-bit Python 3.7. If a virtual environment is active, the version will be +ignored and the environment will be used. .. versionadded:: 3.7 @@ -889,7 +890,14 @@ minor version. I.e. ``/usr/bin/python3.7-32`` will request usage of the The "-64" suffix is deprecated, and now implies "any architecture that is not provably i386/32-bit". To request a specific environment, use the new - ``-V:`` argument with the complete tag. + :samp:`-V:{TAG}` argument with the complete tag. + +.. versionchanged:: 3.13 + + Virtual commands referencing ``python`` now prefer an active virtual + environment rather than searching :envvar:`PATH`. This handles cases where + the shebang specifies ``/usr/bin/env python3`` but :file:`python3.exe` is + not present in the active environment. The ``/usr/bin/env`` form of shebang line has one further special property. Before looking for installed Python interpreters, this form will search the @@ -1187,21 +1195,22 @@ Otherwise, your users may experience problems using your application. Note that the first suggestion is the best, as the others may still be susceptible to non-standard paths in the registry and user site-packages. -.. versionchanged:: - 3.6 +.. versionchanged:: 3.6 + + Add ``._pth`` file support and removes ``applocal`` option from + ``pyvenv.cfg``. + +.. versionchanged:: 3.6 - * Adds ``._pth`` file support and removes ``applocal`` option from - ``pyvenv.cfg``. - * Adds ``pythonXX.zip`` as a potential landmark when directly adjacent - to the executable. + Add :file:`python{XX}.zip` as a potential landmark when directly adjacent + to the executable. -.. deprecated:: - 3.6 +.. deprecated:: 3.6 - Modules specified in the registry under ``Modules`` (not ``PythonPath``) - may be imported by :class:`importlib.machinery.WindowsRegistryFinder`. - This finder is enabled on Windows in 3.6.0 and earlier, but may need to - be explicitly added to :data:`sys.meta_path` in the future. + Modules specified in the registry under ``Modules`` (not ``PythonPath``) + may be imported by :class:`importlib.machinery.WindowsRegistryFinder`. + This finder is enabled on Windows in 3.6.0 and earlier, but may need to + be explicitly added to :data:`sys.meta_path` in the future. Additional modules ================== @@ -1246,8 +1255,8 @@ shipped with PyWin32. It is an embeddable IDE with a built-in debugger. cx_Freeze --------- -`cx_Freeze `_ is a ``distutils`` -extension which wraps Python scripts into executable Windows programs +`cx_Freeze `_ +wraps Python scripts into executable Windows programs (:file:`{*}.exe` files). When you have done this, you can distribute your application without requiring your users to install Python. diff --git a/Doc/whatsnew/2.0.rst b/Doc/whatsnew/2.0.rst index 71f681881f446f..f4a9d23699de53 100644 --- a/Doc/whatsnew/2.0.rst +++ b/Doc/whatsnew/2.0.rst @@ -130,7 +130,7 @@ Guidelines": Read the rest of :pep:`1` for the details of the PEP editorial process, style, and format. PEPs are kept in the Python CVS tree on SourceForge, though they're not part of the Python 2.0 distribution, and are also available in HTML form from -https://peps.python.org/. As of September 2000, there are 25 PEPS, ranging +https://peps.python.org/. As of September 2000, there are 25 PEPs, ranging from :pep:`201`, "Lockstep Iteration", to PEP 225, "Elementwise/Objectwise Operators". @@ -153,9 +153,9 @@ Lundh. A detailed explanation of the interface was written up as :pep:`100`, significant points about the Unicode interfaces. In Python source code, Unicode strings are written as ``u"string"``. Arbitrary -Unicode characters can be written using a new escape sequence, ``\uHHHH``, where +Unicode characters can be written using a new escape sequence, :samp:`\\u{HHHH}`, where *HHHH* is a 4-digit hexadecimal number from 0000 to FFFF. The existing -``\xHHHH`` escape sequence can also be used, and octal escapes can be used for +:samp:`\\x{HH}` escape sequence can also be used, and octal escapes can be used for characters up to U+01FF, which is represented by ``\777``. Unicode strings, just like regular strings, are an immutable sequence type. @@ -671,9 +671,9 @@ errors. If you absolutely must use 2.0 but can't fix your code, you can edit ``NO_STRICT_LIST_APPEND`` to preserve the old behaviour; this isn't recommended. Some of the functions in the :mod:`socket` module are still forgiving in this -way. For example, :func:`socket.connect( ('hostname', 25) )` is the correct -form, passing a tuple representing an IP address, but :func:`socket.connect( -'hostname', 25 )` also works. :func:`socket.connect_ex` and :func:`socket.bind` +way. For example, ``socket.connect( ('hostname', 25) )`` is the correct +form, passing a tuple representing an IP address, but ``socket.connect('hostname', 25)`` +also works. :meth:`socket.connect_ex ` and :meth:`socket.bind ` are similarly easy-going. 2.0alpha1 tightened these functions up, but because the documentation actually used the erroneous multiple argument form, many people wrote code which would break with the stricter checking. GvR backed out @@ -1030,7 +1030,7 @@ Module changes Lots of improvements and bugfixes were made to Python's extensive standard library; some of the affected modules include :mod:`readline`, -:mod:`ConfigParser`, :mod:`!cgi`, :mod:`calendar`, :mod:`posix`, :mod:`readline`, +:mod:`ConfigParser `, :mod:`!cgi`, :mod:`calendar`, :mod:`posix`, :mod:`readline`, :mod:`xmllib`, :mod:`!aifc`, :mod:`!chunk`, :mod:`wave`, :mod:`random`, :mod:`shelve`, and :mod:`!nntplib`. Consult the CVS logs for the exact patch-by-patch details. @@ -1095,8 +1095,8 @@ module. GNU gettext message catalog library. (Integrated by Barry Warsaw, from separate contributions by Martin von Löwis, Peter Funk, and James Henstridge.) -* :mod:`linuxaudiodev`: Support for the :file:`/dev/audio` device on Linux, a - twin to the existing :mod:`sunaudiodev` module. (Contributed by Peter Bosch, +* :mod:`!linuxaudiodev`: Support for the :file:`/dev/audio` device on Linux, a + twin to the existing :mod:`!sunaudiodev` module. (Contributed by Peter Bosch, with fixes by Jeremy Hylton.) * :mod:`mmap`: An interface to memory-mapped files on both Windows and Unix. A @@ -1139,8 +1139,8 @@ module. Unix, not to be confused with :program:`gzip`\ -format files (which are supported by the :mod:`gzip` module) (Contributed by James C. Ahlstrom.) -* :mod:`imputil`: A module that provides a simpler way for writing customized - import hooks, in comparison to the existing :mod:`ihooks` module. (Implemented +* :mod:`!imputil`: A module that provides a simpler way for writing customized + import hooks, in comparison to the existing :mod:`!ihooks` module. (Implemented by Greg Stein, with much discussion on python-dev along the way.) .. ====================================================================== diff --git a/Doc/whatsnew/2.1.rst b/Doc/whatsnew/2.1.rst index f0e1ded75a9d27..6d2d3cc02b8768 100644 --- a/Doc/whatsnew/2.1.rst +++ b/Doc/whatsnew/2.1.rst @@ -424,7 +424,8 @@ PEP 232: Function Attributes In Python 2.1, functions can now have arbitrary information attached to them. People were often using docstrings to hold information about functions and -methods, because the ``__doc__`` attribute was the only way of attaching any +methods, because the :attr:`~function.__doc__` attribute was the only way of +attaching any information to a function. For example, in the Zope web application server, functions are marked as safe for public access by having a docstring, and in John Aycock's SPARK parsing framework, docstrings hold parts of the BNF grammar diff --git a/Doc/whatsnew/2.2.rst b/Doc/whatsnew/2.2.rst index 44e9bd8d492bfc..6efc23a82de923 100644 --- a/Doc/whatsnew/2.2.rst +++ b/Doc/whatsnew/2.2.rst @@ -143,8 +143,8 @@ To make the set of types complete, new type objects such as :func:`dict` and return fcntl.lockf(self.fileno(), operation, length, start, whence) -The now-obsolete :mod:`posixfile` module contained a class that emulated all of -a file object's methods and also added a :meth:`lock` method, but this class +The now-obsolete :mod:`!posixfile` module contained a class that emulated all of +a file object's methods and also added a :meth:`!lock` method, but this class couldn't be passed to internal functions that expected a built-in file, something which is possible with our new :class:`LockableFile`. @@ -424,22 +424,22 @@ Another significant addition to 2.2 is an iteration interface at both the C and Python levels. Objects can define how they can be looped over by callers. In Python versions up to 2.1, the usual way to make ``for item in obj`` work is -to define a :meth:`__getitem__` method that looks something like this:: +to define a :meth:`~object.__getitem__` method that looks something like this:: def __getitem__(self, index): return -:meth:`__getitem__` is more properly used to define an indexing operation on an +:meth:`~object.__getitem__` is more properly used to define an indexing operation on an object so that you can write ``obj[5]`` to retrieve the sixth element. It's a bit misleading when you're using this only to support :keyword:`for` loops. Consider some file-like object that wants to be looped over; the *index* parameter is essentially meaningless, as the class probably assumes that a -series of :meth:`__getitem__` calls will be made with *index* incrementing by -one each time. In other words, the presence of the :meth:`__getitem__` method +series of :meth:`~object.__getitem__` calls will be made with *index* incrementing by +one each time. In other words, the presence of the :meth:`~object.__getitem__` method doesn't mean that using ``file[5]`` to randomly access the sixth element will work, though it really should. -In Python 2.2, iteration can be implemented separately, and :meth:`__getitem__` +In Python 2.2, iteration can be implemented separately, and :meth:`~object.__getitem__` methods can be limited to classes that really do support random access. The basic idea of iterators is simple. A new built-in function, ``iter(obj)`` or ``iter(C, sentinel)``, is used to get an iterator. ``iter(obj)`` returns @@ -1078,17 +1078,17 @@ code, none of the changes described here will affect you very much. To upgrade an extension module to the new API, perform the following steps: -* Rename :c:func:`Py_TPFLAGS_GC` to :c:func:`PyTPFLAGS_HAVE_GC`. +* Rename :c:macro:`!Py_TPFLAGS_GC` to :c:macro:`Py_TPFLAGS_HAVE_GC`. * Use :c:func:`PyObject_GC_New` or :c:func:`PyObject_GC_NewVar` to allocate objects, and :c:func:`PyObject_GC_Del` to deallocate them. -* Rename :c:func:`PyObject_GC_Init` to :c:func:`PyObject_GC_Track` and - :c:func:`PyObject_GC_Fini` to :c:func:`PyObject_GC_UnTrack`. +* Rename :c:func:`!PyObject_GC_Init` to :c:func:`PyObject_GC_Track` and + :c:func:`!PyObject_GC_Fini` to :c:func:`PyObject_GC_UnTrack`. -* Remove :c:func:`PyGC_HEAD_SIZE` from object size calculations. +* Remove :c:macro:`!PyGC_HEAD_SIZE` from object size calculations. -* Remove calls to :c:func:`PyObject_AS_GC` and :c:func:`PyObject_FROM_GC`. +* Remove calls to :c:func:`!PyObject_AS_GC` and :c:func:`!PyObject_FROM_GC`. * A new ``et`` format sequence was added to :c:func:`PyArg_ParseTuple`; ``et`` takes both a parameter and an encoding name, and converts the parameter to the @@ -1109,7 +1109,7 @@ code, none of the changes described here will affect you very much. definition tables to simplify implementation of methods with no arguments or a single untyped argument. Calling such methods is more efficient than calling a corresponding method that uses :c:macro:`METH_VARARGS`. Also, the old - :c:macro:`METH_OLDARGS` style of writing C methods is now officially deprecated. + :c:macro:`!METH_OLDARGS` style of writing C methods is now officially deprecated. * Two new wrapper functions, :c:func:`PyOS_snprintf` and :c:func:`PyOS_vsnprintf` were added to provide cross-platform implementations for the relatively new @@ -1219,7 +1219,7 @@ Some of the more notable changes are: operator, but these features were rarely used and therefore buggy. The :meth:`tolist` method and the :attr:`start`, :attr:`stop`, and :attr:`step` attributes are also being deprecated. At the C level, the fourth argument to - the :c:func:`PyRange_New` function, ``repeat``, has also been deprecated. + the :c:func:`!PyRange_New` function, ``repeat``, has also been deprecated. * There were a bunch of patches to the dictionary implementation, mostly to fix potential core dumps if a dictionary contains objects that sneakily changed diff --git a/Doc/whatsnew/2.3.rst b/Doc/whatsnew/2.3.rst index a96c1061455e00..37cd41add8132c 100644 --- a/Doc/whatsnew/2.3.rst +++ b/Doc/whatsnew/2.3.rst @@ -40,10 +40,10 @@ new feature. PEP 218: A Standard Set Datatype ================================ -The new :mod:`sets` module contains an implementation of a set datatype. The +The new :mod:`!sets` module contains an implementation of a set datatype. The :class:`Set` class is for mutable sets, sets that can have members added and -removed. The :class:`ImmutableSet` class is for sets that can't be modified, -and instances of :class:`ImmutableSet` can therefore be used as dictionary keys. +removed. The :class:`!ImmutableSet` class is for sets that can't be modified, +and instances of :class:`!ImmutableSet` can therefore be used as dictionary keys. Sets are built on top of dictionaries, so the elements within a set must be hashable. @@ -63,10 +63,10 @@ Here's a simple example:: Set([1, 2, 5]) >>> -The union and intersection of sets can be computed with the :meth:`union` and -:meth:`intersection` methods; an alternative notation uses the bitwise operators +The union and intersection of sets can be computed with the :meth:`~frozenset.union` and +:meth:`~frozenset.intersection` methods; an alternative notation uses the bitwise operators ``&`` and ``|``. Mutable sets also have in-place versions of these methods, -:meth:`union_update` and :meth:`intersection_update`. :: +:meth:`!union_update` and :meth:`~frozenset.intersection_update`. :: >>> S1 = sets.Set([1,2,3]) >>> S2 = sets.Set([4,5,6]) @@ -87,7 +87,7 @@ It's also possible to take the symmetric difference of two sets. This is the set of all elements in the union that aren't in the intersection. Another way of putting it is that the symmetric difference contains all elements that are in exactly one set. Again, there's an alternative notation (``^``), and an -in-place version with the ungainly name :meth:`symmetric_difference_update`. :: +in-place version with the ungainly name :meth:`~frozenset.symmetric_difference_update`. :: >>> S1 = sets.Set([1,2,3,4]) >>> S2 = sets.Set([3,4,5,6]) @@ -97,7 +97,7 @@ in-place version with the ungainly name :meth:`symmetric_difference_update`. :: Set([1, 2, 5, 6]) >>> -There are also :meth:`issubset` and :meth:`issuperset` methods for checking +There are also :meth:`!issubset` and :meth:`!issuperset` methods for checking whether one set is a subset or superset of another:: >>> S1 = sets.Set([1,2,3]) @@ -166,7 +166,7 @@ statement isn't allowed inside the :keyword:`try` block of a :keyword:`!try`...\ :keyword:`!finally` statement; read :pep:`255` for a full explanation of the interaction between :keyword:`!yield` and exceptions.) -Here's a sample usage of the :func:`generate_ints` generator:: +Here's a sample usage of the :func:`!generate_ints` generator:: >>> gen = generate_ints(3) >>> gen @@ -227,7 +227,7 @@ like:: sentence := "Store it in the neighboring harbor" if (i := find("or", sentence)) > 5 then write(i) -In Icon the :func:`find` function returns the indexes at which the substring +In Icon the :func:`!find` function returns the indexes at which the substring "or" is found: 3, 23, 33. In the :keyword:`if` statement, ``i`` is first assigned a value of 3, but 3 is less than 5, so the comparison fails, and Icon retries it with the second value of 23. 23 is greater than 5, so the comparison @@ -345,7 +345,7 @@ Python now allows using arbitrary Unicode strings (within the limitations of the file system) for all functions that expect file names, most notably the :func:`open` built-in function. If a Unicode string is passed to :func:`os.listdir`, Python now returns a list of Unicode strings. A new -function, :func:`os.getcwdu`, returns the current directory as a Unicode string. +function, :func:`!os.getcwdu`, returns the current directory as a Unicode string. Byte strings still work as file names, and on Windows Python will transparently convert them to Unicode using the ``mbcs`` encoding. @@ -386,10 +386,10 @@ one followed by the platform on which Python is running. Opening a file with the mode ``'U'`` or ``'rU'`` will open a file for reading in :term:`universal newlines` mode. All three line ending conventions will be translated to a ``'\n'`` in the strings returned by the various file methods such as -:meth:`read` and :meth:`readline`. +:meth:`!read` and :meth:`!readline`. Universal newline support is also used when importing modules and when executing -a file with the :func:`execfile` function. This means that Python modules can +a file with the :func:`!execfile` function. This means that Python modules can be shared between all three operating systems without needing to convert the line-endings. @@ -450,16 +450,16 @@ records to standard error or to a file or socket, send them to the system log, or even e-mail them to a particular address; of course, it's also possible to write your own handler classes. -The :class:`Logger` class is the primary class. Most application code will deal -with one or more :class:`Logger` objects, each one used by a particular -subsystem of the application. Each :class:`Logger` is identified by a name, and +The :class:`~logging.Logger` class is the primary class. Most application code will deal +with one or more :class:`~logging.Logger` objects, each one used by a particular +subsystem of the application. Each :class:`~logging.Logger` is identified by a name, and names are organized into a hierarchy using ``.`` as the component separator. -For example, you might have :class:`Logger` instances named ``server``, +For example, you might have :class:`~logging.Logger` instances named ``server``, ``server.auth`` and ``server.network``. The latter two instances are below ``server`` in the hierarchy. This means that if you turn up the verbosity for ``server`` or direct ``server`` messages to a different handler, the changes will also apply to records logged to ``server.auth`` and ``server.network``. -There's also a root :class:`Logger` that's the parent of all other loggers. +There's also a root :class:`~logging.Logger` that's the parent of all other loggers. For simple uses, the :mod:`logging` package contains some convenience functions that always use the root log:: @@ -480,14 +480,14 @@ This produces the following output:: In the default configuration, informational and debugging messages are suppressed and the output is sent to standard error. You can enable the display -of informational and debugging messages by calling the :meth:`setLevel` method +of informational and debugging messages by calling the :meth:`~logging.Logger.setLevel` method on the root logger. -Notice the :func:`warning` call's use of string formatting operators; all of the +Notice the :func:`~logging.warning` call's use of string formatting operators; all of the functions for logging messages take the arguments ``(msg, arg1, arg2, ...)`` and log the string resulting from ``msg % (arg1, arg2, ...)``. -There's also an :func:`exception` function that records the most recent +There's also an :func:`~logging.exception` function that records the most recent traceback. Any of the other functions will also record the traceback if you specify a true value for the keyword argument *exc_info*. :: @@ -517,16 +517,16 @@ it if it doesn't exist yet. ``getLogger(None)`` returns the root logger. :: ... Log records are usually propagated up the hierarchy, so a message logged to -``server.auth`` is also seen by ``server`` and ``root``, but a :class:`Logger` -can prevent this by setting its :attr:`propagate` attribute to :const:`False`. +``server.auth`` is also seen by ``server`` and ``root``, but a :class:`~logging.Logger` +can prevent this by setting its :attr:`~logging.Logger.propagate` attribute to :const:`False`. There are more classes provided by the :mod:`logging` package that can be -customized. When a :class:`Logger` instance is told to log a message, it -creates a :class:`LogRecord` instance that is sent to any number of different -:class:`Handler` instances. Loggers and handlers can also have an attached list -of filters, and each filter can cause the :class:`LogRecord` to be ignored or +customized. When a :class:`~logging.Logger` instance is told to log a message, it +creates a :class:`~logging.LogRecord` instance that is sent to any number of different +:class:`~logging.Handler` instances. Loggers and handlers can also have an attached list +of filters, and each filter can cause the :class:`~logging.LogRecord` to be ignored or can modify the record before passing it along. When they're finally output, -:class:`LogRecord` instances are converted to text by a :class:`Formatter` +:class:`~logging.LogRecord` instances are converted to text by a :class:`~logging.Formatter` class. All of these classes can be replaced by your own specially written classes. @@ -550,7 +550,7 @@ PEP 285: A Boolean Type ======================= A Boolean type was added to Python 2.3. Two new constants were added to the -:mod:`__builtin__` module, :const:`True` and :const:`False`. (:const:`True` and +:mod:`!__builtin__` module, :const:`True` and :const:`False`. (:const:`True` and :const:`False` constants were added to the built-ins in Python 2.2.1, but the 2.2.1 versions are simply set to integer values of 1 and 0 and aren't a different type.) @@ -662,7 +662,7 @@ a central catalog server. The resulting catalog is available from https://pypi.org. To make the catalog a bit more useful, a new optional *classifiers* keyword -argument has been added to the Distutils :func:`setup` function. A list of +argument has been added to the Distutils :func:`!setup` function. A list of `Trove `_-style strings can be supplied to help classify the software. @@ -703,14 +703,14 @@ PEP 302: New Import Hooks ========================= While it's been possible to write custom import hooks ever since the -:mod:`ihooks` module was introduced in Python 1.3, no one has ever been really +:mod:`!ihooks` module was introduced in Python 1.3, no one has ever been really happy with it because writing new import hooks is difficult and messy. There -have been various proposed alternatives such as the :mod:`imputil` and :mod:`iu` +have been various proposed alternatives such as the :mod:`!imputil` and :mod:`!iu` modules, but none of them has ever gained much acceptance, and none of them were easily usable from C code. :pep:`302` borrows ideas from its predecessors, especially from Gordon -McMillan's :mod:`iu` module. Three new items are added to the :mod:`sys` +McMillan's :mod:`!iu` module. Three new items are added to the :mod:`sys` module: * ``sys.path_hooks`` is a list of callable objects; most often they'll be @@ -790,7 +790,7 @@ package is much simpler:: for line in reader: print line -The :func:`reader` function takes a number of different options. The field +The :func:`~csv.reader` function takes a number of different options. The field separator isn't limited to the comma and can be changed to any character, and so can the quoting and line-ending characters. @@ -814,7 +814,7 @@ of tuples or lists, quoting strings that contain the delimiter. PEP 307: Pickle Enhancements ============================ -The :mod:`pickle` and :mod:`cPickle` modules received some attention during the +The :mod:`pickle` and :mod:`!cPickle` modules received some attention during the 2.3 development cycle. In 2.2, new-style classes could be pickled without difficulty, but they weren't pickled very compactly; :pep:`307` quotes a trivial example where a new-style class results in a pickled string three times longer @@ -829,13 +829,13 @@ fanciest protocol available. Unpickling is no longer considered a safe operation. 2.2's :mod:`pickle` provided hooks for trying to prevent unsafe classes from being unpickled -(specifically, a :attr:`__safe_for_unpickling__` attribute), but none of this +(specifically, a :attr:`!__safe_for_unpickling__` attribute), but none of this code was ever audited and therefore it's all been ripped out in 2.3. You should not unpickle untrusted data in any version of Python. To reduce the pickling overhead for new-style classes, a new interface for customizing pickling was added using three special methods: -:meth:`__getstate__`, :meth:`__setstate__`, and :meth:`__getnewargs__`. Consult +:meth:`~object.__getstate__`, :meth:`~object.__setstate__`, and :meth:`~object.__getnewargs__`. Consult :pep:`307` for the full semantics of these methods. As a way to compress pickles yet further, it's now possible to use integer codes @@ -925,7 +925,7 @@ Deletion is more straightforward:: >>> a [1, 3] -One can also now pass slice objects to the :meth:`__getitem__` methods of the +One can also now pass slice objects to the :meth:`~object.__getitem__` methods of the built-in sequences:: >>> range(10).__getitem__(slice(0, 5, 2)) @@ -939,7 +939,7 @@ Or use slice objects directly in subscripts:: To simplify implementing sequences that support extended slicing, slice objects now have a method ``indices(length)`` which, given the length of a sequence, returns a ``(start, stop, step)`` tuple that can be passed directly to -:func:`range`. :meth:`indices` handles omitted and out-of-bounds indices in a +:func:`range`. :meth:`!indices` handles omitted and out-of-bounds indices in a manner consistent with regular slices (and this innocuous phrase hides a welter of confusing details!). The method is intended to be used like this:: @@ -1042,7 +1042,7 @@ Here are all of the changes that Python 2.3 makes to the core Python language. execute any assertions. * Most type objects are now callable, so you can use them to create new objects - such as functions, classes, and modules. (This means that the :mod:`new` module + such as functions, classes, and modules. (This means that the :mod:`!new` module can be deprecated in a future Python version, because you can now use the type objects available in the :mod:`types` module.) For example, you can create a new module object with the following code: @@ -1069,11 +1069,11 @@ Here are all of the changes that Python 2.3 makes to the core Python language. * Using ``None`` as a variable name will now result in a :exc:`SyntaxWarning` warning. In a future version of Python, ``None`` may finally become a keyword. -* The :meth:`xreadlines` method of file objects, introduced in Python 2.1, is no +* The :meth:`!xreadlines` method of file objects, introduced in Python 2.1, is no longer necessary because files now behave as their own iterator. - :meth:`xreadlines` was originally introduced as a faster way to loop over all + :meth:`!xreadlines` was originally introduced as a faster way to loop over all the lines in a file, but now you can simply write ``for line in file_obj``. - File objects also have a new read-only :attr:`encoding` attribute that gives the + File objects also have a new read-only :attr:`!encoding` attribute that gives the encoding used by the file; Unicode strings written to the file will be automatically converted to bytes using the given encoding. @@ -1096,12 +1096,12 @@ Here are all of the changes that Python 2.3 makes to the core Python language. switching overhead. Some multithreaded applications may suffer slower response time, but that's easily fixed by setting the limit back to a lower number using ``sys.setcheckinterval(N)``. The limit can be retrieved with the new - :func:`sys.getcheckinterval` function. + :func:`!sys.getcheckinterval` function. * One minor but far-reaching change is that the names of extension types defined by the modules included with Python now contain the module and a ``'.'`` in front of the type name. For example, in Python 2.2, if you created a socket and - printed its :attr:`__class__`, you'd get this output:: + printed its :attr:`!__class__`, you'd get this output:: >>> s = socket.socket() >>> s.__class__ @@ -1138,9 +1138,9 @@ String Changes True Note that this doesn't tell you where the substring starts; if you need that - information, use the :meth:`find` string method. + information, use the :meth:`~str.find` string method. -* The :meth:`strip`, :meth:`lstrip`, and :meth:`rstrip` string methods now have +* The :meth:`~str.strip`, :meth:`~str.lstrip`, and :meth:`~str.rstrip` string methods now have an optional argument for specifying the characters to strip. The default is still to remove all whitespace characters:: @@ -1156,13 +1156,13 @@ String Changes (Suggested by Simon Brunning and implemented by Walter Dörwald.) -* The :meth:`startswith` and :meth:`endswith` string methods now accept negative +* The :meth:`~str.startswith` and :meth:`~str.endswith` string methods now accept negative numbers for the *start* and *end* parameters. -* Another new string method is :meth:`zfill`, originally a function in the - :mod:`string` module. :meth:`zfill` pads a numeric string with zeros on the +* Another new string method is :meth:`~str.zfill`, originally a function in the + :mod:`string` module. :meth:`~str.zfill` pads a numeric string with zeros on the left until it's the specified width. Note that the ``%`` operator is still more - flexible and powerful than :meth:`zfill`. :: + flexible and powerful than :meth:`~str.zfill`. :: >>> '45'.zfill(4) '0045' @@ -1173,10 +1173,10 @@ String Changes (Contributed by Walter Dörwald.) -* A new type object, :class:`basestring`, has been added. Both 8-bit strings and +* A new type object, :class:`!basestring`, has been added. Both 8-bit strings and Unicode strings inherit from this type, so ``isinstance(obj, basestring)`` will return :const:`True` for either kind of string. It's a completely abstract - type, so you can't create :class:`basestring` instances. + type, so you can't create :class:`!basestring` instances. * Interned strings are no longer immortal and will now be garbage-collected in the usual way when the only reference to them is from the internal dictionary of @@ -1191,19 +1191,19 @@ Optimizations * The creation of new-style class instances has been made much faster; they're now faster than classic classes! -* The :meth:`sort` method of list objects has been extensively rewritten by Tim +* The :meth:`~list.sort` method of list objects has been extensively rewritten by Tim Peters, and the implementation is significantly faster. * Multiplication of large long integers is now much faster thanks to an implementation of Karatsuba multiplication, an algorithm that scales better than - the O(n\*n) required for the grade-school multiplication algorithm. (Original + the *O*\ (*n*\ :sup:`2`) required for the grade-school multiplication algorithm. (Original patch by Christopher A. Craig, and significantly reworked by Tim Peters.) * The ``SET_LINENO`` opcode is now gone. This may provide a small speed increase, depending on your compiler's idiosyncrasies. See section :ref:`23section-other` for a longer explanation. (Removed by Michael Hudson.) -* :func:`xrange` objects now have their own iterator, making ``for i in +* :func:`!xrange` objects now have their own iterator, making ``for i in xrange(n)`` slightly faster than ``for i in range(n)``. (Patch by Raymond Hettinger.) @@ -1230,21 +1230,21 @@ complete list of changes, or look through the CVS logs for all the details. operator to add another array's contents, and the ``*=`` assignment operator to repeat an array. (Contributed by Jason Orendorff.) -* The :mod:`bsddb` module has been replaced by version 4.1.6 of the `PyBSDDB +* The :mod:`!bsddb` module has been replaced by version 4.1.6 of the `PyBSDDB `_ package, providing a more complete interface to the transactional features of the BerkeleyDB library. - The old version of the module has been renamed to :mod:`bsddb185` and is no + The old version of the module has been renamed to :mod:`!bsddb185` and is no longer built automatically; you'll have to edit :file:`Modules/Setup` to enable - it. Note that the new :mod:`bsddb` package is intended to be compatible with + it. Note that the new :mod:`!bsddb` package is intended to be compatible with the old module, so be sure to file bugs if you discover any incompatibilities. When upgrading to Python 2.3, if the new interpreter is compiled with a new version of the underlying BerkeleyDB library, you will almost certainly have to convert your database files to the new version. You can do this fairly easily with the new scripts :file:`db2pickle.py` and :file:`pickle2db.py` which you will find in the distribution's :file:`Tools/scripts` directory. If you've - already been using the PyBSDDB package and importing it as :mod:`bsddb3`, you - will have to change your ``import`` statements to import it as :mod:`bsddb`. + already been using the PyBSDDB package and importing it as :mod:`!bsddb3`, you + will have to change your ``import`` statements to import it as :mod:`!bsddb`. * The new :mod:`bz2` module is an interface to the bz2 data compression library. bz2-compressed data is usually smaller than corresponding @@ -1253,11 +1253,11 @@ complete list of changes, or look through the CVS logs for all the details. * A set of standard date/time types has been added in the new :mod:`datetime` module. See the following section for more details. -* The Distutils :class:`Extension` class now supports an extra constructor +* The Distutils :class:`!Extension` class now supports an extra constructor argument named *depends* for listing additional source files that an extension depends on. This lets Distutils recompile the module if any of the dependency files are modified. For example, if :file:`sampmodule.c` includes the header - file :file:`sample.h`, you would create the :class:`Extension` object like + file :file:`sample.h`, you would create the :class:`!Extension` object like this:: ext = Extension("samp", @@ -1268,21 +1268,21 @@ complete list of changes, or look through the CVS logs for all the details. (Contributed by Jeremy Hylton.) * Other minor changes to Distutils: it now checks for the :envvar:`CC`, - :envvar:`CFLAGS`, :envvar:`CPP`, :envvar:`LDFLAGS`, and :envvar:`CPPFLAGS` + :envvar:`CFLAGS`, :envvar:`!CPP`, :envvar:`LDFLAGS`, and :envvar:`CPPFLAGS` environment variables, using them to override the settings in Python's configuration (contributed by Robert Weber). * Previously the :mod:`doctest` module would only search the docstrings of public methods and functions for test cases, but it now also examines private - ones as well. The :func:`DocTestSuite` function creates a + ones as well. The :func:`~doctest.DocTestSuite` function creates a :class:`unittest.TestSuite` object from a set of :mod:`doctest` tests. * The new ``gc.get_referents(object)`` function returns a list of all the objects referenced by *object*. -* The :mod:`getopt` module gained a new function, :func:`gnu_getopt`, that - supports the same arguments as the existing :func:`getopt` function but uses - GNU-style scanning mode. The existing :func:`getopt` stops processing options as +* The :mod:`getopt` module gained a new function, :func:`~getopt.gnu_getopt`, that + supports the same arguments as the existing :func:`~getopt.getopt` function but uses + GNU-style scanning mode. The existing :func:`~getopt.getopt` stops processing options as soon as a non-option argument is encountered, but in GNU-style mode processing continues, meaning that options and arguments can be mixed. For example:: @@ -1308,10 +1308,10 @@ complete list of changes, or look through the CVS logs for all the details. partially sorted order such that, for every index *k*, ``heap[k] <= heap[2*k+1]`` and ``heap[k] <= heap[2*k+2]``. This makes it quick to remove the smallest item, and inserting a new item while maintaining the heap property is - O(lg n). (See https://xlinux.nist.gov/dads//HTML/priorityque.html for more + *O*\ (log *n*). (See https://xlinux.nist.gov/dads//HTML/priorityque.html for more information about the priority queue data structure.) - The :mod:`heapq` module provides :func:`heappush` and :func:`heappop` functions + The :mod:`heapq` module provides :func:`~heapq.heappush` and :func:`~heapq.heappop` functions for adding and removing items while maintaining the heap property on top of some other mutable Python sequence type. Here's an example that uses a Python list:: @@ -1343,7 +1343,7 @@ complete list of changes, or look through the CVS logs for all the details. * The :mod:`itertools` contains a number of useful functions for use with iterators, inspired by various functions provided by the ML and Haskell languages. For example, ``itertools.ifilter(predicate, iterator)`` returns all - elements in the iterator for which the function :func:`predicate` returns + elements in the iterator for which the function :func:`!predicate` returns :const:`True`, and ``itertools.repeat(obj, N)`` returns ``obj`` *N* times. There are a number of other functions in the module; see the package's reference documentation for details. @@ -1356,21 +1356,21 @@ complete list of changes, or look through the CVS logs for all the details. was added to :func:`math.log` to make it easier to compute logarithms for bases other than ``e`` and ``10``. (Contributed by Raymond Hettinger.) -* Several new POSIX functions (:func:`getpgid`, :func:`killpg`, :func:`lchown`, - :func:`loadavg`, :func:`major`, :func:`makedev`, :func:`minor`, and - :func:`mknod`) were added to the :mod:`posix` module that underlies the +* Several new POSIX functions (:func:`!getpgid`, :func:`!killpg`, :func:`!lchown`, + :func:`!loadavg`, :func:`!major`, :func:`!makedev`, :func:`!minor`, and + :func:`!mknod`) were added to the :mod:`posix` module that underlies the :mod:`os` module. (Contributed by Gustavo Niemeyer, Geert Jansen, and Denis S. Otkidach.) -* In the :mod:`os` module, the :func:`\*stat` family of functions can now report +* In the :mod:`os` module, the :func:`!\*stat` family of functions can now report fractions of a second in a timestamp. Such time stamps are represented as floats, similar to the value returned by :func:`time.time`. During testing, it was found that some applications will break if time stamps are floats. For compatibility, when using the tuple interface of the - :class:`stat_result` time stamps will be represented as integers. When using + :class:`~os.stat_result` time stamps will be represented as integers. When using named fields (a feature first introduced in Python 2.2), time stamps are still - represented as integers, unless :func:`os.stat_float_times` is invoked to enable + represented as integers, unless :func:`!os.stat_float_times` is invoked to enable float return values:: >>> os.stat("/tmp").st_mtime @@ -1391,7 +1391,7 @@ complete list of changes, or look through the CVS logs for all the details. automatically generate a usage message. See the following section for more details. -* The old and never-documented :mod:`linuxaudiodev` module has been deprecated, +* The old and never-documented :mod:`!linuxaudiodev` module has been deprecated, and a new version named :mod:`!ossaudiodev` has been added. The module was renamed because the OSS sound drivers can be used on platforms other than Linux, and the interface has also been tidied and brought up to date in various ways. @@ -1402,14 +1402,14 @@ complete list of changes, or look through the CVS logs for all the details. functions for getting the architecture, CPU type, the Windows OS version, and even the Linux distribution version. (Contributed by Marc-André Lemburg.) -* The parser objects provided by the :mod:`pyexpat` module can now optionally +* The parser objects provided by the :mod:`pyexpat ` module can now optionally buffer character data, resulting in fewer calls to your character data handler and therefore faster performance. Setting the parser object's - :attr:`buffer_text` attribute to :const:`True` will enable buffering. + :attr:`~xml.parsers.expat.xmlparser.buffer_text` attribute to :const:`True` will enable buffering. * The ``sample(population, k)`` function was added to the :mod:`random` - module. *population* is a sequence or :class:`xrange` object containing the - elements of a population, and :func:`sample` chooses *k* elements from the + module. *population* is a sequence or :class:`!xrange` object containing the + elements of a population, and :func:`~random.sample` chooses *k* elements from the population without replacing chosen elements. *k* can be any value up to ``len(population)``. For example:: @@ -1436,20 +1436,20 @@ complete list of changes, or look through the CVS logs for all the details. (All changes contributed by Raymond Hettinger.) * The :mod:`readline` module also gained a number of new functions: - :func:`get_history_item`, :func:`get_current_history_length`, and - :func:`redisplay`. + :func:`~readline.get_history_item`, :func:`~readline.get_current_history_length`, and + :func:`~readline.redisplay`. -* The :mod:`rexec` and :mod:`Bastion` modules have been declared dead, and +* The :mod:`!rexec` and :mod:`!Bastion` modules have been declared dead, and attempts to import them will fail with a :exc:`RuntimeError`. New-style classes provide new ways to break out of the restricted execution environment provided - by :mod:`rexec`, and no one has interest in fixing them or time to do so. If - you have applications using :mod:`rexec`, rewrite them to use something else. + by :mod:`!rexec`, and no one has interest in fixing them or time to do so. If + you have applications using :mod:`!rexec`, rewrite them to use something else. (Sticking with Python 2.2 or 2.1 will not make your applications any safer - because there are known bugs in the :mod:`rexec` module in those versions. To - repeat: if you're using :mod:`rexec`, stop using it immediately.) + because there are known bugs in the :mod:`!rexec` module in those versions. To + repeat: if you're using :mod:`!rexec`, stop using it immediately.) -* The :mod:`rotor` module has been deprecated because the algorithm it uses for +* The :mod:`!rotor` module has been deprecated because the algorithm it uses for encryption is not believed to be secure. If you need encryption, use one of the several AES Python modules that are available separately. @@ -1474,9 +1474,9 @@ complete list of changes, or look through the CVS logs for all the details. * On Windows, the :mod:`socket` module now ships with Secure Sockets Layer (SSL) support. -* The value of the C :c:macro:`PYTHON_API_VERSION` macro is now exposed at the +* The value of the C :c:macro:`!PYTHON_API_VERSION` macro is now exposed at the Python level as ``sys.api_version``. The current exception can be cleared by - calling the new :func:`sys.exc_clear` function. + calling the new :func:`!sys.exc_clear` function. * The new :mod:`tarfile` module allows reading from and writing to :program:`tar`\ -format archive files. (Contributed by Lars Gustäbel.) @@ -1486,7 +1486,7 @@ complete list of changes, or look through the CVS logs for all the details. string and returns a list containing the text split into lines of no more than the chosen width. The ``fill(text, width)`` function returns a single string, reformatted to fit into lines no longer than the chosen width. (As you - can guess, :func:`fill` is built on top of :func:`wrap`. For example:: + can guess, :func:`~textwrap.fill` is built on top of :func:`~textwrap.wrap`. For example:: >>> import textwrap >>> paragraph = "Not a whit, we defy augury: ... more text ..." @@ -1503,15 +1503,15 @@ complete list of changes, or look through the CVS logs for all the details. it will come: the readiness is all. >>> - The module also contains a :class:`TextWrapper` class that actually implements - the text wrapping strategy. Both the :class:`TextWrapper` class and the - :func:`wrap` and :func:`fill` functions support a number of additional keyword + The module also contains a :class:`~textwrap.TextWrapper` class that actually implements + the text wrapping strategy. Both the :class:`~textwrap.TextWrapper` class and the + :func:`~textwrap.wrap` and :func:`~textwrap.fill` functions support a number of additional keyword arguments for fine-tuning the formatting; consult the module's documentation for details. (Contributed by Greg Ward.) -* The :mod:`thread` and :mod:`threading` modules now have companion modules, - :mod:`dummy_thread` and :mod:`dummy_threading`, that provide a do-nothing - implementation of the :mod:`thread` module's interface for platforms where +* The :mod:`!thread` and :mod:`threading` modules now have companion modules, + :mod:`!dummy_thread` and :mod:`!dummy_threading`, that provide a do-nothing + implementation of the :mod:`!thread` module's interface for platforms where threads are not supported. The intention is to simplify thread-aware modules (ones that *don't* rely on threads to run) by putting the following code at the top:: @@ -1521,26 +1521,26 @@ complete list of changes, or look through the CVS logs for all the details. except ImportError: import dummy_threading as _threading - In this example, :mod:`_threading` is used as the module name to make it clear + In this example, :mod:`!_threading` is used as the module name to make it clear that the module being used is not necessarily the actual :mod:`threading` - module. Code can call functions and use classes in :mod:`_threading` whether or + module. Code can call functions and use classes in :mod:`!_threading` whether or not threads are supported, avoiding an :keyword:`if` statement and making the code slightly clearer. This module will not magically make multithreaded code run without threads; code that waits for another thread to return or to do something will simply hang forever. -* The :mod:`time` module's :func:`strptime` function has long been an annoyance - because it uses the platform C library's :func:`strptime` implementation, and +* The :mod:`time` module's :func:`~time.strptime` function has long been an annoyance + because it uses the platform C library's :func:`~time.strptime` implementation, and different platforms sometimes have odd bugs. Brett Cannon contributed a portable implementation that's written in pure Python and should behave identically on all platforms. * The new :mod:`timeit` module helps measure how long snippets of Python code take to execute. The :file:`timeit.py` file can be run directly from the - command line, or the module's :class:`Timer` class can be imported and used + command line, or the module's :class:`~timeit.Timer` class can be imported and used directly. Here's a short example that figures out whether it's faster to convert an 8-bit string to Unicode by appending an empty Unicode string to it or - by using the :func:`unicode` function:: + by using the :func:`!unicode` function:: import timeit @@ -1558,46 +1558,46 @@ complete list of changes, or look through the CVS logs for all the details. * The :mod:`!Tix` module has received various bug fixes and updates for the current version of the Tix package. -* The :mod:`Tkinter` module now works with a thread-enabled version of Tcl. +* The :mod:`!Tkinter` module now works with a thread-enabled version of Tcl. Tcl's threading model requires that widgets only be accessed from the thread in which they're created; accesses from another thread can cause Tcl to panic. For - certain Tcl interfaces, :mod:`Tkinter` will now automatically avoid this when a + certain Tcl interfaces, :mod:`!Tkinter` will now automatically avoid this when a widget is accessed from a different thread by marshalling a command, passing it to the correct thread, and waiting for the results. Other interfaces can't be - handled automatically but :mod:`Tkinter` will now raise an exception on such an + handled automatically but :mod:`!Tkinter` will now raise an exception on such an access so that you can at least find out about the problem. See https://mail.python.org/pipermail/python-dev/2002-December/031107.html for a more detailed explanation of this change. (Implemented by Martin von Löwis.) -* Calling Tcl methods through :mod:`_tkinter` no longer returns only strings. +* Calling Tcl methods through :mod:`!_tkinter` no longer returns only strings. Instead, if Tcl returns other objects those objects are converted to their - Python equivalent, if one exists, or wrapped with a :class:`_tkinter.Tcl_Obj` + Python equivalent, if one exists, or wrapped with a :class:`!_tkinter.Tcl_Obj` object if no Python equivalent exists. This behavior can be controlled through - the :meth:`wantobjects` method of :class:`tkapp` objects. + the :meth:`!wantobjects` method of :class:`!tkapp` objects. - When using :mod:`_tkinter` through the :mod:`Tkinter` module (as most Tkinter + When using :mod:`!_tkinter` through the :mod:`!Tkinter` module (as most Tkinter applications will), this feature is always activated. It should not cause compatibility problems, since Tkinter would always convert string results to Python types where possible. If any incompatibilities are found, the old behavior can be restored by setting - the :attr:`wantobjects` variable in the :mod:`Tkinter` module to false before - creating the first :class:`tkapp` object. :: + the :attr:`!wantobjects` variable in the :mod:`!Tkinter` module to false before + creating the first :class:`!tkapp` object. :: import Tkinter Tkinter.wantobjects = 0 Any breakage caused by this change should be reported as a bug. -* The :mod:`UserDict` module has a new :class:`DictMixin` class which defines +* The :mod:`!UserDict` module has a new :class:`!DictMixin` class which defines all dictionary methods for classes that already have a minimum mapping interface. This greatly simplifies writing classes that need to be substitutable for dictionaries, such as the classes in the :mod:`shelve` module. Adding the mix-in as a superclass provides the full dictionary interface - whenever the class defines :meth:`__getitem__`, :meth:`__setitem__`, - :meth:`__delitem__`, and :meth:`keys`. For example:: + whenever the class defines :meth:`~object.__getitem__`, :meth:`~object.__setitem__`, + :meth:`~object.__delitem__`, and :meth:`!keys`. For example:: >>> import UserDict >>> class SeqDict(UserDict.DictMixin): @@ -1640,15 +1640,15 @@ complete list of changes, or look through the CVS logs for all the details. * The DOM implementation in :mod:`xml.dom.minidom` can now generate XML output in a particular encoding by providing an optional encoding argument to the - :meth:`toxml` and :meth:`toprettyxml` methods of DOM nodes. + :meth:`~xml.dom.minidom.Node.toxml` and :meth:`~xml.dom.minidom.Node.toprettyxml` methods of DOM nodes. -* The :mod:`xmlrpclib` module now supports an XML-RPC extension for handling nil +* The :mod:`!xmlrpclib` module now supports an XML-RPC extension for handling nil data values such as Python's ``None``. Nil values are always supported on unmarshalling an XML-RPC response. To generate requests containing ``None``, you must supply a true value for the *allow_none* parameter when creating a - :class:`Marshaller` instance. + :class:`!Marshaller` instance. -* The new :mod:`DocXMLRPCServer` module allows writing self-documenting XML-RPC +* The new :mod:`!DocXMLRPCServer` module allows writing self-documenting XML-RPC servers. Run it in demo mode (as a program) to see it in action. Pointing the web browser to the RPC server produces pydoc-style documentation; pointing xmlrpclib to the server allows invoking the actual methods. (Contributed by @@ -1663,8 +1663,8 @@ complete list of changes, or look through the CVS logs for all the details. The :mod:`socket` module has also been extended to transparently convert Unicode hostnames to the ACE version before passing them to the C library. - Modules that deal with hostnames such as :mod:`httplib` and :mod:`ftplib`) - also support Unicode host names; :mod:`httplib` also sends HTTP ``Host`` + Modules that deal with hostnames such as :mod:`!httplib` and :mod:`ftplib`) + also support Unicode host names; :mod:`!httplib` also sends HTTP ``Host`` headers using the ACE version of the domain name. :mod:`urllib` supports Unicode URLs with non-ASCII host names as long as the ``path`` part of the URL is ASCII only. @@ -1682,17 +1682,17 @@ Date and time types suitable for expressing timestamps were added as the :mod:`datetime` module. The types don't support different calendars or many fancy features, and just stick to the basics of representing time. -The three primary types are: :class:`date`, representing a day, month, and year; +The three primary types are: :class:`~datetime.date`, representing a day, month, and year; :class:`~datetime.time`, consisting of hour, minute, and second; and :class:`~datetime.datetime`, -which contains all the attributes of both :class:`date` and :class:`~datetime.time`. -There's also a :class:`timedelta` class representing differences between two +which contains all the attributes of both :class:`~datetime.date` and :class:`~datetime.time`. +There's also a :class:`~datetime.timedelta` class representing differences between two points in time, and time zone logic is implemented by classes inheriting from -the abstract :class:`tzinfo` class. +the abstract :class:`~datetime.tzinfo` class. -You can create instances of :class:`date` and :class:`~datetime.time` by either supplying +You can create instances of :class:`~datetime.date` and :class:`~datetime.time` by either supplying keyword arguments to the appropriate constructor, e.g. ``datetime.date(year=1972, month=10, day=15)``, or by using one of a number of -class methods. For example, the :meth:`date.today` class method returns the +class methods. For example, the :meth:`~datetime.date.today` class method returns the current local date. Once created, instances of the date/time classes are all immutable. There are a @@ -1707,8 +1707,8 @@ number of methods for producing formatted strings from objects:: >>> now.strftime('%Y %d %b') '2002 30 Dec' -The :meth:`replace` method allows modifying one or more fields of a -:class:`date` or :class:`~datetime.datetime` instance, returning a new instance:: +The :meth:`~datetime.datetime.replace` method allows modifying one or more fields of a +:class:`~datetime.date` or :class:`~datetime.datetime` instance, returning a new instance:: >>> d = datetime.datetime.now() >>> d @@ -1718,10 +1718,10 @@ The :meth:`replace` method allows modifying one or more fields of a >>> Instances can be compared, hashed, and converted to strings (the result is the -same as that of :meth:`isoformat`). :class:`date` and :class:`~datetime.datetime` -instances can be subtracted from each other, and added to :class:`timedelta` +same as that of :meth:`~datetime.datetime.isoformat`). :class:`~datetime.date` and :class:`~datetime.datetime` +instances can be subtracted from each other, and added to :class:`~datetime.timedelta` instances. The largest missing feature is that there's no standard library -support for parsing strings and getting back a :class:`date` or +support for parsing strings and getting back a :class:`~datetime.date` or :class:`~datetime.datetime`. For more information, refer to the module's reference documentation. @@ -1739,7 +1739,7 @@ command-line parsing that follows the Unix conventions, automatically creates the output for :option:`!--help`, and can perform different actions for different options. -You start by creating an instance of :class:`OptionParser` and telling it what +You start by creating an instance of :class:`~optparse.OptionParser` and telling it what your program's options are. :: import sys @@ -1753,7 +1753,7 @@ your program's options are. :: action='store', type='int', dest='length', help='set maximum length of output') -Parsing a command line is then done by calling the :meth:`parse_args` method. :: +Parsing a command line is then done by calling the :meth:`~optparse.OptionParser.parse_args` method. :: options, args = op.parse_args(sys.argv[1:]) print options @@ -1886,10 +1886,10 @@ Changes to Python's build process and to the C API include: (:file:`libpython2.3.so`) by supplying :option:`!--enable-shared` when running Python's :program:`configure` script. (Contributed by Ondrej Palkovsky.) -* The :c:macro:`DL_EXPORT` and :c:macro:`DL_IMPORT` macros are now deprecated. +* The :c:macro:`!DL_EXPORT` and :c:macro:`!DL_IMPORT` macros are now deprecated. Initialization functions for Python extension modules should now be declared using the new macro :c:macro:`PyMODINIT_FUNC`, while the Python core will - generally use the :c:macro:`PyAPI_FUNC` and :c:macro:`PyAPI_DATA` macros. + generally use the :c:macro:`!PyAPI_FUNC` and :c:macro:`!PyAPI_DATA` macros. * The interpreter can be compiled without any docstrings for the built-in functions and modules by supplying :option:`!--without-doc-strings` to the @@ -1897,7 +1897,7 @@ Changes to Python's build process and to the C API include: but will also mean that you can't get help for Python's built-ins. (Contributed by Gustavo Niemeyer.) -* The :c:func:`PyArg_NoArgs` macro is now deprecated, and code that uses it +* The :c:func:`!PyArg_NoArgs` macro is now deprecated, and code that uses it should be changed. For Python 2.2 and later, the method definition table can specify the :c:macro:`METH_NOARGS` flag, signalling that there are no arguments, and the argument checking can then be removed. If compatibility with pre-2.2 @@ -1925,7 +1925,7 @@ Changes to Python's build process and to the C API include: dependence on a system version or local installation of Expat. * If you dynamically allocate type objects in your extension, you should be - aware of a change in the rules relating to the :attr:`__module__` and + aware of a change in the rules relating to the :attr:`!__module__` and :attr:`~definition.__name__` attributes. In summary, you will want to ensure the type's dictionary contains a ``'__module__'`` key; making the module name the part of the type name leading up to the final period will no longer have the desired @@ -1940,7 +1940,7 @@ Port-Specific Changes Support for a port to IBM's OS/2 using the EMX runtime environment was merged into the main Python source tree. EMX is a POSIX emulation layer over the OS/2 system APIs. The Python port for EMX tries to support all the POSIX-like -capability exposed by the EMX runtime, and mostly succeeds; :func:`fork` and +capability exposed by the EMX runtime, and mostly succeeds; :func:`!fork` and :func:`fcntl` are restricted by the limitations of the underlying emulation layer. The standard OS/2 port, which uses IBM's Visual Age compiler, also gained support for case-sensitive import semantics as part of the integration of @@ -1998,13 +1998,13 @@ Some of the more notable changes are: It would be difficult to detect any resulting difference from Python code, apart from a slight speed up when Python is run without :option:`-O`. - C extensions that access the :attr:`f_lineno` field of frame objects should + C extensions that access the :attr:`~frame.f_lineno` field of frame objects should instead call ``PyCode_Addr2Line(f->f_code, f->f_lasti)``. This will have the added effect of making the code work as desired under "python -O" in earlier versions of Python. A nifty new feature is that trace functions can now assign to the - :attr:`f_lineno` attribute of frame objects, changing the line that will be + :attr:`~frame.f_lineno` attribute of frame objects, changing the line that will be executed next. A ``jump`` command has been added to the :mod:`pdb` debugger taking advantage of this new feature. (Implemented by Richie Hindle.) @@ -2031,9 +2031,9 @@ code: the file's encoding (UTF-8, Latin-1, or whatever) by adding a comment to the top of the file. See section :ref:`section-encodings` for more information. -* Calling Tcl methods through :mod:`_tkinter` no longer returns only strings. +* Calling Tcl methods through :mod:`!_tkinter` no longer returns only strings. Instead, if Tcl returns other objects those objects are converted to their - Python equivalent, if one exists, or wrapped with a :class:`_tkinter.Tcl_Obj` + Python equivalent, if one exists, or wrapped with a :class:`!_tkinter.Tcl_Obj` object if no Python equivalent exists. * Large octal and hex literals such as ``0xffffffff`` now trigger a @@ -2049,10 +2049,10 @@ code: * You can no longer disable assertions by assigning to ``__debug__``. -* The Distutils :func:`setup` function has gained various new keyword arguments +* The Distutils :func:`!setup` function has gained various new keyword arguments such as *depends*. Old versions of the Distutils will abort if passed unknown keywords. A solution is to check for the presence of the new - :func:`get_distutil_options` function in your :file:`setup.py` and only uses the + :func:`!get_distutil_options` function in your :file:`setup.py` and only uses the new keywords with a version of the Distutils that supports them:: from distutils import core diff --git a/Doc/whatsnew/2.4.rst b/Doc/whatsnew/2.4.rst index 9e8a9e6a622d00..15d4003622c506 100644 --- a/Doc/whatsnew/2.4.rst +++ b/Doc/whatsnew/2.4.rst @@ -324,7 +324,8 @@ function, as previously described. In other words, ``@A @B @C(args)`` becomes:: Getting this right can be slightly brain-bending, but it's not too difficult. -A small related change makes the :attr:`func_name` attribute of functions +A small related change makes the :attr:`func_name ` +attribute of functions writable. This attribute is used to display function names in tracebacks, so decorators should change the name of any new function that's constructed and returned. @@ -386,13 +387,13 @@ The standard library provides a number of ways to execute a subprocess, offering different features and different levels of complexity. ``os.system(command)`` is easy to use, but slow (it runs a shell process which executes the command) and dangerous (you have to be careful about escaping -the shell's metacharacters). The :mod:`popen2` module offers classes that can +the shell's metacharacters). The :mod:`!popen2` module offers classes that can capture standard output and standard error from the subprocess, but the naming is confusing. The :mod:`subprocess` module cleans this up, providing a unified interface that offers all the features you might need. -Instead of :mod:`popen2`'s collection of classes, :mod:`subprocess` contains a -single class called :class:`Popen` whose constructor supports a number of +Instead of :mod:`!popen2`'s collection of classes, :mod:`subprocess` contains a +single class called :class:`subprocess.Popen` whose constructor supports a number of different keyword arguments. :: class Popen(args, bufsize=0, executable=None, @@ -994,7 +995,7 @@ fixes. Here's a partial list of the most notable changes, sorted alphabetically by module name. Consult the :file:`Misc/NEWS` file in the source tree for a more complete list of changes, or look through the CVS logs for all the details. -* The :mod:`asyncore` module's :func:`loop` function now has a *count* parameter +* The :mod:`!asyncore` module's :func:`!loop` function now has a *count* parameter that lets you perform a limited number of passes through the polling loop. The default is still to loop forever. @@ -1051,9 +1052,9 @@ complete list of changes, or look through the CVS logs for all the details. advantage of :class:`collections.deque` for improved performance. (Contributed by Raymond Hettinger.) -* The :mod:`ConfigParser` classes have been enhanced slightly. The :meth:`read` +* The :mod:`ConfigParser ` classes have been enhanced slightly. The :meth:`~configparser.ConfigParser.read` method now returns a list of the files that were successfully parsed, and the - :meth:`set` method raises :exc:`TypeError` if passed a *value* argument that + :meth:`~configparser.ConfigParser.set` method raises :exc:`TypeError` if passed a *value* argument that isn't a string. (Contributed by John Belmonte and David Goodger.) * The :mod:`curses` module now supports the ncurses extension @@ -1163,7 +1164,7 @@ complete list of changes, or look through the CVS logs for all the details. * A number of functions were added to the :mod:`locale` module, such as :func:`bind_textdomain_codeset` to specify a particular encoding and a family of - :func:`l\*gettext` functions that return messages in the chosen encoding. + :func:`!l\*gettext` functions that return messages in the chosen encoding. (Contributed by Gustavo Niemeyer.) * Some keyword arguments were added to the :mod:`logging` package's @@ -1468,7 +1469,7 @@ Some of the changes to Python's build process and to the C API are: *X* is a NaN. (Contributed by Tim Peters.) * C code can avoid unnecessary locking by using the new - :c:func:`PyEval_ThreadsInitialized` function to tell if any thread operations + :c:func:`!PyEval_ThreadsInitialized` function to tell if any thread operations have been performed. If this function returns false, no lock operations are needed. (Contributed by Nick Coghlan.) @@ -1476,7 +1477,7 @@ Some of the changes to Python's build process and to the C API are: :c:func:`PyArg_ParseTupleAndKeywords` but takes a :c:type:`va_list` instead of a number of arguments. (Contributed by Greg Chapman.) -* A new method flag, :c:macro:`METH_COEXISTS`, allows a function defined in slots +* A new method flag, :c:macro:`METH_COEXIST`, allows a function defined in slots to co-exist with a :c:type:`PyCFunction` having the same name. This can halve the access time for a method such as :meth:`set.__contains__`. (Contributed by Raymond Hettinger.) @@ -1528,7 +1529,7 @@ code: will now always be unequal, and relative comparisons (``<``, ``>``) will raise a :exc:`TypeError`. -* :func:`dircache.listdir` now passes exceptions to the caller instead of +* :func:`!dircache.listdir` now passes exceptions to the caller instead of returning empty lists. * :func:`LexicalHandler.startDTD` used to receive the public and system IDs in diff --git a/Doc/whatsnew/2.5.rst b/Doc/whatsnew/2.5.rst index a47327d15fd79a..f45d70ea5a19a0 100644 --- a/Doc/whatsnew/2.5.rst +++ b/Doc/whatsnew/2.5.rst @@ -575,15 +575,15 @@ structure is:: with-block The expression is evaluated, and it should result in an object that supports the -context management protocol (that is, has :meth:`__enter__` and :meth:`__exit__` +context management protocol (that is, has :meth:`~object.__enter__` and :meth:`~object.__exit__` methods. -The object's :meth:`__enter__` is called before *with-block* is executed and +The object's :meth:`~object.__enter__` is called before *with-block* is executed and therefore can run set-up code. It also may return a value that is bound to the name *variable*, if given. (Note carefully that *variable* is *not* assigned the result of *expression*.) -After execution of the *with-block* is finished, the object's :meth:`__exit__` +After execution of the *with-block* is finished, the object's :meth:`~object.__exit__` method is called, even if the block raised an exception, and can therefore run clean-up code. @@ -609,7 +609,7 @@ part-way through the block. .. note:: In this case, *f* is the same object created by :func:`open`, because - :meth:`file.__enter__` returns *self*. + :meth:`~object.__enter__` returns *self*. The :mod:`threading` module's locks and condition variables also support the ':keyword:`with`' statement:: @@ -652,10 +652,10 @@ underlying implementation and should keep reading. A high-level explanation of the context management protocol is: * The expression is evaluated and should result in an object called a "context - manager". The context manager must have :meth:`__enter__` and :meth:`__exit__` + manager". The context manager must have :meth:`~object.__enter__` and :meth:`~object.__exit__` methods. -* The context manager's :meth:`__enter__` method is called. The value returned +* The context manager's :meth:`~object.__enter__` method is called. The value returned is assigned to *VAR*. If no ``'as VAR'`` clause is present, the value is simply discarded. @@ -669,7 +669,7 @@ A high-level explanation of the context management protocol is: if you do the author of the code containing the ':keyword:`with`' statement will never realize anything went wrong. -* If *BLOCK* didn't raise an exception, the :meth:`__exit__` method is still +* If *BLOCK* didn't raise an exception, the :meth:`~object.__exit__` method is still called, but *type*, *value*, and *traceback* are all ``None``. Let's think through an example. I won't present detailed code but will only @@ -703,7 +703,7 @@ rolled back if there's an exception. Here's the basic interface for def rollback (self): "Rolls back current transaction" -The :meth:`__enter__` method is pretty easy, having only to start a new +The :meth:`~object.__enter__` method is pretty easy, having only to start a new transaction. For this application the resulting cursor object would be a useful result, so the method will return it. The user can then add ``as cursor`` to their ':keyword:`with`' statement to bind the cursor to a variable name. :: @@ -715,7 +715,7 @@ their ':keyword:`with`' statement to bind the cursor to a variable name. :: cursor = self.cursor() return cursor -The :meth:`__exit__` method is the most complicated because it's where most of +The :meth:`~object.__exit__` method is the most complicated because it's where most of the work has to be done. The method has to check if an exception occurred. If there was no exception, the transaction is committed. The transaction is rolled back if there was an exception. @@ -748,10 +748,10 @@ are useful for writing objects for use with the ':keyword:`with`' statement. The decorator is called :func:`contextmanager`, and lets you write a single generator function instead of defining a new class. The generator should yield exactly one value. The code up to the :keyword:`yield` will be executed as the -:meth:`__enter__` method, and the value yielded will be the method's return +:meth:`~object.__enter__` method, and the value yielded will be the method's return value that will get bound to the variable in the ':keyword:`with`' statement's :keyword:`!as` clause, if any. The code after the :keyword:`yield` will be -executed in the :meth:`__exit__` method. Any exception raised in the block will +executed in the :meth:`~object.__exit__` method. Any exception raised in the block will be raised by the :keyword:`!yield` statement. Our database example from the previous section could be written using this @@ -1167,10 +1167,10 @@ marked in the following list. * It's now illegal to mix iterating over a file with ``for line in file`` and calling the file object's :meth:`read`/:meth:`readline`/:meth:`readlines` - methods. Iteration uses an internal buffer and the :meth:`read\*` methods + methods. Iteration uses an internal buffer and the :meth:`!read\*` methods don't use that buffer. Instead they would return the data following the buffer, causing the data to appear out of order. Mixing iteration and these - methods will now trigger a :exc:`ValueError` from the :meth:`read\*` method. + methods will now trigger a :exc:`ValueError` from the :meth:`!read\*` method. (Implemented by Thomas Wouters.) .. Patch 1397960 @@ -1347,7 +1347,7 @@ complete list of changes, or look through the SVN logs for all the details. :func:`input` function to allow opening files in binary or :term:`universal newlines` mode. Another new parameter, *openhook*, lets you use a function other than :func:`open` to open the input files. Once you're iterating over - the set of files, the :class:`FileInput` object's new :meth:`fileno` returns + the set of files, the :class:`FileInput` object's new :meth:`~fileinput.fileno` returns the file descriptor for the currently opened file. (Contributed by Georg Brandl.) @@ -1680,7 +1680,7 @@ The ctypes package The :mod:`ctypes` package, written by Thomas Heller, has been added to the standard library. :mod:`ctypes` lets you call arbitrary functions in shared -libraries or DLLs. Long-time users may remember the :mod:`dl` module, which +libraries or DLLs. Long-time users may remember the :mod:`!dl` module, which provides functions for loading shared libraries and calling functions in them. The :mod:`ctypes` package is much fancier. @@ -1877,12 +1877,12 @@ The hashlib package ------------------- A new :mod:`hashlib` module, written by Gregory P. Smith, has been added to -replace the :mod:`md5` and :mod:`sha` modules. :mod:`hashlib` adds support for +replace the :mod:`!md5` and :mod:`!sha` modules. :mod:`hashlib` adds support for additional secure hashes (SHA-224, SHA-256, SHA-384, and SHA-512). When available, the module uses OpenSSL for fast platform optimized implementations of algorithms. -The old :mod:`md5` and :mod:`sha` modules still exist as wrappers around hashlib +The old :mod:`!md5` and :mod:`!sha` modules still exist as wrappers around hashlib to preserve backwards compatibility. The new module's interface is very close to that of the old modules, but not identical. The most significant difference is that the constructor functions for creating new hashing objects are named @@ -2119,9 +2119,9 @@ Changes to Python's build process and to the C API include: the various AST nodes in :file:`Parser/Python.asdl`. A Python script reads this file and generates a set of C structure definitions in :file:`Include/Python-ast.h`. The :c:func:`PyParser_ASTFromString` and - :c:func:`PyParser_ASTFromFile`, defined in :file:`Include/pythonrun.h`, take + :c:func:`!PyParser_ASTFromFile`, defined in :file:`Include/pythonrun.h`, take Python source as input and return the root of an AST representing the contents. - This AST can then be turned into a code object by :c:func:`PyAST_Compile`. For + This AST can then be turned into a code object by :c:func:`!PyAST_Compile`. For more information, read the source code, and then ask questions on python-dev. The AST code was developed under Jeremy Hylton's management, and implemented by @@ -2172,7 +2172,7 @@ Changes to Python's build process and to the C API include: ``Py_LOCAL(type)`` declares the function as returning a value of the specified *type* and uses a fast-calling qualifier. ``Py_LOCAL_INLINE(type)`` does the same thing and also requests the - function be inlined. If :c:func:`PY_LOCAL_AGGRESSIVE` is defined before + function be inlined. If macro :c:macro:`!PY_LOCAL_AGGRESSIVE` is defined before :file:`python.h` is included, a set of more aggressive optimizations are enabled for the module; you should benchmark the results to find out if these optimizations actually make the code faster. (Contributed by Fredrik Lundh at @@ -2181,7 +2181,7 @@ Changes to Python's build process and to the C API include: * ``PyErr_NewException(name, base, dict)`` can now accept a tuple of base classes as its *base* argument. (Contributed by Georg Brandl.) -* The :c:func:`PyErr_Warn` function for issuing warnings is now deprecated in +* The :c:func:`!PyErr_Warn` function for issuing warnings is now deprecated in favour of ``PyErr_WarnEx(category, message, stacklevel)`` which lets you specify the number of stack frames separating this function and the caller. A *stacklevel* of 1 is the function calling :c:func:`PyErr_WarnEx`, 2 is the @@ -2191,7 +2191,7 @@ Changes to Python's build process and to the C API include: compiled with a C++ compiler without errors. (Implemented by Anthony Baxter, Martin von Löwis, Skip Montanaro.) -* The :c:func:`PyRange_New` function was removed. It was never documented, never +* The :c:func:`!PyRange_New` function was removed. It was never documented, never used in the core code, and had dangerously lax error checking. In the unlikely case that your extensions were using it, you can replace it by something like the following:: diff --git a/Doc/whatsnew/2.6.rst b/Doc/whatsnew/2.6.rst index ad899d53886c59..c6bab93b7efdda 100644 --- a/Doc/whatsnew/2.6.rst +++ b/Doc/whatsnew/2.6.rst @@ -4,8 +4,6 @@ What's New in Python 2.6 **************************** -.. XXX add trademark info for Apple, Microsoft, SourceForge. - :Author: A.M. Kuchling (amk at amk.ca) .. $Id$ @@ -121,14 +119,14 @@ about features that will be removed in Python 3.0. You can run code with this switch to see how much work will be necessary to port code to 3.0. The value of this switch is available to Python code as the boolean variable :data:`sys.py3kwarning`, -and to C extension code as :c:data:`Py_Py3kWarningFlag`. +and to C extension code as :c:data:`!Py_Py3kWarningFlag`. .. seealso:: - The 3xxx series of PEPs, which contains proposals for Python 3.0. + The 3\ *xxx* series of PEPs, which contains proposals for Python 3.0. :pep:`3000` describes the development process for Python 3.0. Start with :pep:`3100` that describes the general goals for Python - 3.0, and then explore the higher-numbered PEPS that propose + 3.0, and then explore the higher-numbered PEPs that propose specific features. @@ -269,15 +267,15 @@ structure is:: with-block The expression is evaluated, and it should result in an object that supports the -context management protocol (that is, has :meth:`__enter__` and :meth:`__exit__` +context management protocol (that is, has :meth:`~object.__enter__` and :meth:`~object.__exit__` methods). -The object's :meth:`__enter__` is called before *with-block* is executed and +The object's :meth:`~object.__enter__` is called before *with-block* is executed and therefore can run set-up code. It also may return a value that is bound to the name *variable*, if given. (Note carefully that *variable* is *not* assigned the result of *expression*.) -After execution of the *with-block* is finished, the object's :meth:`__exit__` +After execution of the *with-block* is finished, the object's :meth:`~object.__exit__` method is called, even if the block raised an exception, and can therefore run clean-up code. @@ -296,7 +294,7 @@ part-way through the block. .. note:: In this case, *f* is the same object created by :func:`open`, because - :meth:`file.__enter__` returns *self*. + :meth:`~object.__enter__` returns *self*. The :mod:`threading` module's locks and condition variables also support the ':keyword:`with`' statement:: @@ -339,16 +337,16 @@ underlying implementation and should keep reading. A high-level explanation of the context management protocol is: * The expression is evaluated and should result in an object called a "context - manager". The context manager must have :meth:`__enter__` and :meth:`__exit__` + manager". The context manager must have :meth:`~object.__enter__` and :meth:`~object.__exit__` methods. -* The context manager's :meth:`__enter__` method is called. The value returned +* The context manager's :meth:`~object.__enter__` method is called. The value returned is assigned to *VAR*. If no ``as VAR`` clause is present, the value is simply discarded. * The code in *BLOCK* is executed. -* If *BLOCK* raises an exception, the context manager's :meth:`__exit__` method +* If *BLOCK* raises an exception, the context manager's :meth:`~object.__exit__` method is called with three arguments, the exception details (``type, value, traceback``, the same values returned by :func:`sys.exc_info`, which can also be ``None`` if no exception occurred). The method's return value controls whether an exception @@ -357,7 +355,7 @@ A high-level explanation of the context management protocol is: if you do the author of the code containing the ':keyword:`with`' statement will never realize anything went wrong. -* If *BLOCK* didn't raise an exception, the :meth:`__exit__` method is still +* If *BLOCK* didn't raise an exception, the :meth:`~object.__exit__` method is still called, but *type*, *value*, and *traceback* are all ``None``. Let's think through an example. I won't present detailed code but will only @@ -391,7 +389,7 @@ rolled back if there's an exception. Here's the basic interface for def rollback(self): "Rolls back current transaction" -The :meth:`__enter__` method is pretty easy, having only to start a new +The :meth:`~object.__enter__` method is pretty easy, having only to start a new transaction. For this application the resulting cursor object would be a useful result, so the method will return it. The user can then add ``as cursor`` to their ':keyword:`with`' statement to bind the cursor to a variable name. :: @@ -403,7 +401,7 @@ their ':keyword:`with`' statement to bind the cursor to a variable name. :: cursor = self.cursor() return cursor -The :meth:`__exit__` method is the most complicated because it's where most of +The :meth:`~object.__exit__` method is the most complicated because it's where most of the work has to be done. The method has to check if an exception occurred. If there was no exception, the transaction is committed. The transaction is rolled back if there was an exception. @@ -436,10 +434,10 @@ are useful when writing objects for use with the ':keyword:`with`' statement. The decorator is called :func:`contextmanager`, and lets you write a single generator function instead of defining a new class. The generator should yield exactly one value. The code up to the :keyword:`yield` will be executed as the -:meth:`__enter__` method, and the value yielded will be the method's return +:meth:`~object.__enter__` method, and the value yielded will be the method's return value that will get bound to the variable in the ':keyword:`with`' statement's :keyword:`!as` clause, if any. The code after the :keyword:`!yield` will be -executed in the :meth:`__exit__` method. Any exception raised in the block will +executed in the :meth:`~object.__exit__` method. Any exception raised in the block will be raised by the :keyword:`!yield` statement. Using this decorator, our database example from the previous section @@ -875,11 +873,11 @@ The signature of the new function is:: The parameters are: - * *args*: positional arguments whose values will be printed out. - * *sep*: the separator, which will be printed between arguments. - * *end*: the ending text, which will be printed after all of the - arguments have been output. - * *file*: the file object to which the output will be sent. +* *args*: positional arguments whose values will be printed out. +* *sep*: the separator, which will be printed between arguments. +* *end*: the ending text, which will be printed after all of the + arguments have been output. +* *file*: the file object to which the output will be sent. .. seealso:: @@ -977,7 +975,7 @@ can be used to include Unicode characters:: print len(s) # 12 Unicode characters At the C level, Python 3.0 will rename the existing 8-bit -string type, called :c:type:`PyStringObject` in Python 2.x, +string type, called :c:type:`!PyStringObject` in Python 2.x, to :c:type:`PyBytesObject`. Python 2.6 uses ``#define`` to support using the names :c:func:`PyBytesObject`, :c:func:`PyBytes_Check`, :c:func:`PyBytes_FromStringAndSize`, @@ -1051,8 +1049,6 @@ the :mod:`io` module: sockets, but Python 2.6 hasn't restructured its file and socket objects in this way. - .. XXX should 2.6 register them in io.py? - * :class:`BufferedIOBase` is an abstract base class that buffers data in memory to reduce the number of system calls used, making I/O processing more efficient. @@ -1133,18 +1129,16 @@ while an external caller could be modifying the contents, so there's a corresponding ``PyBuffer_Release(Py_buffer *view)`` to indicate that the external caller is done. -.. XXX PyObject_GetBuffer not documented in c-api - The *flags* argument to :c:func:`PyObject_GetBuffer` specifies constraints upon the memory returned. Some examples are: - * :c:macro:`PyBUF_WRITABLE` indicates that the memory must be writable. +* :c:macro:`PyBUF_WRITABLE` indicates that the memory must be writable. - * :c:macro:`PyBUF_LOCK` requests a read-only or exclusive lock on the memory. +* :c:macro:`PyBUF_LOCK` requests a read-only or exclusive lock on the memory. - * :c:macro:`PyBUF_C_CONTIGUOUS` and :c:macro:`PyBUF_F_CONTIGUOUS` - requests a C-contiguous (last dimension varies the fastest) or - Fortran-contiguous (first dimension varies the fastest) array layout. +* :c:macro:`PyBUF_C_CONTIGUOUS` and :c:macro:`PyBUF_F_CONTIGUOUS` + requests a C-contiguous (last dimension varies the fastest) or + Fortran-contiguous (first dimension varies the fastest) array layout. Two new argument codes for :c:func:`PyArg_ParseTuple`, ``s*`` and ``z*``, return locked buffer objects for a parameter. @@ -1677,8 +1671,9 @@ Some smaller changes made to the core Python language are: (:issue:`1591665`) * Instance method objects have new attributes for the object and function - comprising the method; the new synonym for :attr:`im_self` is - :attr:`__self__`, and :attr:`im_func` is also available as :attr:`__func__`. + comprising the method; the new synonym for :attr:`!im_self` is + :attr:`~method.__self__`, and :attr:`!im_func` is also available as + :attr:`~method.__func__`. The old names are still supported in Python 2.6, but are gone in 3.0. * An obscure change: when you use the :func:`locals` function inside a @@ -1737,7 +1732,7 @@ Optimizations (Contributed by Antoine Pitrou.) Memory usage is reduced by using pymalloc for the Unicode string's data. -* The ``with`` statement now stores the :meth:`__exit__` method on the stack, +* The ``with`` statement now stores the :meth:`~object.__exit__` method on the stack, producing a small speedup. (Implemented by Jeffrey Yasskin.) * To reduce memory usage, the garbage collector will now clear internal @@ -1788,7 +1783,7 @@ changes, sorted alphabetically by module name. Consult the :file:`Misc/NEWS` file in the source tree for a more complete list of changes, or look through the Subversion logs for all the details. -* The :mod:`asyncore` and :mod:`asynchat` modules are +* The :mod:`!asyncore` and :mod:`!asynchat` modules are being actively maintained again, and a number of patches and bugfixes were applied. (Maintained by Josiah Carlson; see :issue:`1736190` for one patch.) @@ -1850,8 +1845,8 @@ changes, or look through the Subversion logs for all the details. special values and floating-point exceptions in a manner consistent with Annex 'G' of the C99 standard. -* A new data type in the :mod:`collections` module: :class:`namedtuple(typename, - fieldnames)` is a factory function that creates subclasses of the standard tuple +* A new data type in the :mod:`collections` module: ``namedtuple(typename, fieldnames)`` + is a factory function that creates subclasses of the standard tuple whose fields are accessible by name as well as index. For example:: >>> var_type = collections.namedtuple('variable', @@ -1873,7 +1868,7 @@ changes, or look through the Subversion logs for all the details. variable(id=1, name='amplitude', type='int', size=4) Several places in the standard library that returned tuples have - been modified to return :class:`namedtuple` instances. For example, + been modified to return :func:`namedtuple` instances. For example, the :meth:`Decimal.as_tuple` method now returns a named tuple with :attr:`sign`, :attr:`digits`, and :attr:`exponent` fields. @@ -2915,8 +2910,8 @@ Deprecations and Removals * Changes to the :class:`Exception` interface as dictated by :pep:`352` continue to be made. For 2.6, - the :attr:`message` attribute is being deprecated in favor of the - :attr:`args` attribute. + the :attr:`!message` attribute is being deprecated in favor of the + :attr:`~BaseException.args` attribute. * (3.0-warning mode) Python 3.0 will feature a reorganized standard library that will drop many outdated modules and rename others. @@ -2924,51 +2919,51 @@ Deprecations and Removals when they are imported. The list of deprecated modules is: - :mod:`audiodev`, - :mod:`bgenlocations`, - :mod:`buildtools`, - :mod:`bundlebuilder`, - :mod:`Canvas`, - :mod:`compiler`, - :mod:`dircache`, - :mod:`dl`, - :mod:`fpformat`, - :mod:`gensuitemodule`, - :mod:`ihooks`, - :mod:`imageop`, - :mod:`imgfile`, - :mod:`linuxaudiodev`, - :mod:`mhlib`, - :mod:`mimetools`, - :mod:`multifile`, - :mod:`new`, - :mod:`pure`, - :mod:`statvfs`, - :mod:`sunaudiodev`, - :mod:`test.testall`, and - :mod:`toaiff`. - -* The :mod:`gopherlib` module has been removed. - -* The :mod:`MimeWriter` module and :mod:`mimify` module + :mod:`!audiodev`, + :mod:`!bgenlocations`, + :mod:`!buildtools`, + :mod:`!bundlebuilder`, + :mod:`!Canvas`, + :mod:`!compiler`, + :mod:`!dircache`, + :mod:`!dl`, + :mod:`!fpformat`, + :mod:`!gensuitemodule`, + :mod:`!ihooks`, + :mod:`!imageop`, + :mod:`!imgfile`, + :mod:`!linuxaudiodev`, + :mod:`!mhlib`, + :mod:`!mimetools`, + :mod:`!multifile`, + :mod:`!new`, + :mod:`!pure`, + :mod:`!statvfs`, + :mod:`!sunaudiodev`, + :mod:`!test.testall`, and + :mod:`!toaiff`. + +* The :mod:`!gopherlib` module has been removed. + +* The :mod:`!MimeWriter` module and :mod:`!mimify` module have been deprecated; use the :mod:`email` package instead. -* The :mod:`md5` module has been deprecated; use the :mod:`hashlib` module +* The :mod:`!md5` module has been deprecated; use the :mod:`hashlib` module instead. -* The :mod:`posixfile` module has been deprecated; :func:`fcntl.lockf` +* The :mod:`!posixfile` module has been deprecated; :func:`fcntl.lockf` provides better locking. -* The :mod:`popen2` module has been deprecated; use the :mod:`subprocess` +* The :mod:`!popen2` module has been deprecated; use the :mod:`subprocess` module. -* The :mod:`rgbimg` module has been removed. +* The :mod:`!rgbimg` module has been removed. -* The :mod:`sets` module has been deprecated; it's better to +* The :mod:`!sets` module has been deprecated; it's better to use the built-in :class:`set` and :class:`frozenset` types. -* The :mod:`sha` module has been deprecated; use the :mod:`hashlib` module +* The :mod:`!sha` module has been deprecated; use the :mod:`hashlib` module instead. @@ -3012,11 +3007,11 @@ Changes to Python's build process and to the C API include: bug occurred if one thread closed a file object while another thread was reading from or writing to the object. In 2.6 file objects have a reference count, manipulated by the - :c:func:`PyFile_IncUseCount` and :c:func:`PyFile_DecUseCount` + :c:func:`!PyFile_IncUseCount` and :c:func:`!PyFile_DecUseCount` functions. File objects can't be closed unless the reference count - is zero. :c:func:`PyFile_IncUseCount` should be called while the GIL + is zero. :c:func:`!PyFile_IncUseCount` should be called while the GIL is still held, before carrying out an I/O operation using the - ``FILE *`` pointer, and :c:func:`PyFile_DecUseCount` should be called + ``FILE *`` pointer, and :c:func:`!PyFile_DecUseCount` should be called immediately after the GIL is re-acquired. (Contributed by Antoine Pitrou and Gregory P. Smith.) @@ -3060,9 +3055,9 @@ Changes to Python's build process and to the C API include: * Some macros were renamed in both 3.0 and 2.6 to make it clearer that they are macros, - not functions. :c:macro:`Py_Size()` became :c:macro:`Py_SIZE()`, - :c:macro:`Py_Type()` became :c:macro:`Py_TYPE()`, and - :c:macro:`Py_Refcnt()` became :c:macro:`Py_REFCNT()`. + not functions. :c:macro:`!Py_Size()` became :c:macro:`Py_SIZE()`, + :c:macro:`!Py_Type()` became :c:macro:`Py_TYPE()`, and + :c:macro:`!Py_Refcnt()` became :c:macro:`Py_REFCNT()`. The mixed-case macros are still available in Python 2.6 for backward compatibility. (:issue:`1629`) @@ -3109,8 +3104,8 @@ Port-Specific Changes: Windows * The :mod:`msvcrt` module now supports both the normal and wide char variants of the console I/O - API. The :func:`getwch` function reads a keypress and returns a Unicode - value, as does the :func:`getwche` function. The :func:`putwch` function + API. The :func:`~msvcrt.getwch` function reads a keypress and returns a Unicode + value, as does the :func:`~msvcrt.getwche` function. The :func:`~msvcrt.putwch` function takes a Unicode character and writes it to the console. (Contributed by Christian Heimes.) @@ -3119,24 +3114,24 @@ Port-Specific Changes: Windows directory path. (Contributed by Josiah Carlson; :issue:`957650`.) * The :mod:`socket` module's socket objects now have an - :meth:`ioctl` method that provides a limited interface to the + :meth:`~socket.socket.ioctl` method that provides a limited interface to the :c:func:`WSAIoctl` system interface. -* The :mod:`_winreg` module now has a function, - :func:`ExpandEnvironmentStrings`, +* The :mod:`_winreg ` module now has a function, + :func:`~winreg.ExpandEnvironmentStrings`, that expands environment variable references such as ``%NAME%`` in an input string. The handle objects provided by this module now support the context protocol, so they can be used in :keyword:`with` statements. (Contributed by Christian Heimes.) - :mod:`_winreg` also has better support for x64 systems, - exposing the :func:`DisableReflectionKey`, :func:`EnableReflectionKey`, - and :func:`QueryReflectionKey` functions, which enable and disable + :mod:`_winreg ` also has better support for x64 systems, + exposing the :func:`~winreg.DisableReflectionKey`, :func:`~winreg.EnableReflectionKey`, + and :func:`~winreg.QueryReflectionKey` functions, which enable and disable registry reflection for 32-bit processes running on 64-bit systems. (:issue:`1753245`) -* The :mod:`!msilib` module's :class:`Record` object - gained :meth:`GetInteger` and :meth:`GetString` methods that +* The :mod:`!msilib` module's :class:`!Record` object + gained :meth:`!GetInteger` and :meth:`!GetString` methods that return field values as an integer or a string. (Contributed by Floris Bruynooghe; :issue:`2125`.) @@ -3150,49 +3145,49 @@ Port-Specific Changes: Mac OS X :option:`!--with-framework-name=` option to the :program:`configure` script. -* The :mod:`macfs` module has been removed. This in turn required the - :func:`macostools.touched` function to be removed because it depended on the - :mod:`macfs` module. (:issue:`1490190`) +* The :mod:`!macfs` module has been removed. This in turn required the + :func:`!macostools.touched` function to be removed because it depended on the + :mod:`!macfs` module. (:issue:`1490190`) * Many other Mac OS modules have been deprecated and will be removed in Python 3.0: - :mod:`_builtinSuites`, - :mod:`aepack`, - :mod:`aetools`, - :mod:`aetypes`, - :mod:`applesingle`, - :mod:`appletrawmain`, - :mod:`appletrunner`, - :mod:`argvemulator`, - :mod:`Audio_mac`, - :mod:`autoGIL`, - :mod:`Carbon`, - :mod:`cfmfile`, - :mod:`CodeWarrior`, - :mod:`ColorPicker`, - :mod:`EasyDialogs`, - :mod:`Explorer`, - :mod:`Finder`, - :mod:`FrameWork`, - :mod:`findertools`, - :mod:`ic`, - :mod:`icglue`, - :mod:`icopen`, - :mod:`macerrors`, - :mod:`MacOS`, - :mod:`macfs`, - :mod:`macostools`, - :mod:`macresource`, - :mod:`MiniAEFrame`, - :mod:`Nav`, - :mod:`Netscape`, - :mod:`OSATerminology`, - :mod:`pimp`, - :mod:`PixMapWrapper`, - :mod:`StdSuites`, - :mod:`SystemEvents`, - :mod:`Terminal`, and - :mod:`terminalcommand`. + :mod:`!_builtinSuites`, + :mod:`!aepack`, + :mod:`!aetools`, + :mod:`!aetypes`, + :mod:`!applesingle`, + :mod:`!appletrawmain`, + :mod:`!appletrunner`, + :mod:`!argvemulator`, + :mod:`!Audio_mac`, + :mod:`!autoGIL`, + :mod:`!Carbon`, + :mod:`!cfmfile`, + :mod:`!CodeWarrior`, + :mod:`!ColorPicker`, + :mod:`!EasyDialogs`, + :mod:`!Explorer`, + :mod:`!Finder`, + :mod:`!FrameWork`, + :mod:`!findertools`, + :mod:`!ic`, + :mod:`!icglue`, + :mod:`!icopen`, + :mod:`!macerrors`, + :mod:`!MacOS`, + :mod:`!macfs`, + :mod:`!macostools`, + :mod:`!macresource`, + :mod:`!MiniAEFrame`, + :mod:`!Nav`, + :mod:`!Netscape`, + :mod:`!OSATerminology`, + :mod:`!pimp`, + :mod:`!PixMapWrapper`, + :mod:`!StdSuites`, + :mod:`!SystemEvents`, + :mod:`!Terminal`, and + :mod:`!terminalcommand`. .. ====================================================================== @@ -3201,29 +3196,29 @@ Port-Specific Changes: IRIX A number of old IRIX-specific modules were deprecated and will be removed in Python 3.0: -:mod:`al` and :mod:`AL`, -:mod:`cd`, -:mod:`cddb`, -:mod:`cdplayer`, -:mod:`CL` and :mod:`cl`, -:mod:`DEVICE`, -:mod:`ERRNO`, -:mod:`FILE`, -:mod:`FL` and :mod:`fl`, -:mod:`flp`, -:mod:`fm`, -:mod:`GET`, -:mod:`GLWS`, -:mod:`GL` and :mod:`gl`, -:mod:`IN`, -:mod:`IOCTL`, -:mod:`jpeg`, -:mod:`panelparser`, -:mod:`readcd`, -:mod:`SV` and :mod:`sv`, -:mod:`torgb`, -:mod:`videoreader`, and -:mod:`WAIT`. +:mod:`!al` and :mod:`!AL`, +:mod:`!cd`, +:mod:`!cddb`, +:mod:`!cdplayer`, +:mod:`!CL` and :mod:`!cl`, +:mod:`!DEVICE`, +:mod:`!ERRNO`, +:mod:`!FILE`, +:mod:`!FL` and :mod:`!fl`, +:mod:`!flp`, +:mod:`!fm`, +:mod:`!GET`, +:mod:`!GLWS`, +:mod:`!GL` and :mod:`!gl`, +:mod:`!IN`, +:mod:`!IOCTL`, +:mod:`!jpeg`, +:mod:`!panelparser`, +:mod:`!readcd`, +:mod:`!SV` and :mod:`!sv`, +:mod:`!torgb`, +:mod:`!videoreader`, and +:mod:`!WAIT`. .. ====================================================================== diff --git a/Doc/whatsnew/2.7.rst b/Doc/whatsnew/2.7.rst index 4b5a31f8a84810..241d58720399af 100644 --- a/Doc/whatsnew/2.7.rst +++ b/Doc/whatsnew/2.7.rst @@ -282,12 +282,12 @@ How does the :class:`~collections.OrderedDict` work? It maintains a doubly linked list of keys, appending new keys to the list as they're inserted. A secondary dictionary maps keys to their corresponding list node, so deletion doesn't have to traverse the entire linked list and therefore -remains O(1). +remains *O*\ (1). The standard library now supports use of ordered dictionaries in several modules. -* The :mod:`ConfigParser` module uses them by default, meaning that +* The :mod:`ConfigParser ` module uses them by default, meaning that configuration files can now be read, modified, and then written back in their original order. @@ -858,9 +858,11 @@ Some smaller changes made to the core Python language are: .. XXX bytearray doesn't seem to be documented -* When using ``@classmethod`` and ``@staticmethod`` to wrap +* When using :class:`@classmethod ` and + :class:`@staticmethod ` to wrap methods as class or static methods, the wrapper object now - exposes the wrapped function as their :attr:`__func__` attribute. + exposes the wrapped function as their :attr:`~method.__func__` + attribute. (Contributed by Amaury Forgeot d'Arc, after a suggestion by George Sakkis; :issue:`5982`.) @@ -930,8 +932,8 @@ Optimizations Several performance enhancements have been added: * A new opcode was added to perform the initial setup for - :keyword:`with` statements, looking up the :meth:`__enter__` and - :meth:`__exit__` methods. (Contributed by Benjamin Peterson.) + :keyword:`with` statements, looking up the :meth:`~object.__enter__` and + :meth:`~object.__exit__` methods. (Contributed by Benjamin Peterson.) * The garbage collector now performs better for one common usage pattern: when many objects are being allocated without deallocating @@ -1132,7 +1134,7 @@ changes, or look through the Subversion logs for all the details. another type that isn't a :class:`Mapping`. (Fixed by Daniel Stutzbach; :issue:`8729`.) -* Constructors for the parsing classes in the :mod:`ConfigParser` module now +* Constructors for the parsing classes in the :mod:`ConfigParser ` module now take an *allow_no_value* parameter, defaulting to false; if true, options without values will be allowed. For example:: @@ -1313,9 +1315,9 @@ changes, or look through the Subversion logs for all the details. giving the source address that will be used for the connection. (Contributed by Eldon Ziegler; :issue:`3972`.) -* The :mod:`ihooks` module now supports relative imports. Note that - :mod:`ihooks` is an older module for customizing imports, - superseded by the :mod:`imputil` module added in Python 2.0. +* The :mod:`!ihooks` module now supports relative imports. Note that + :mod:`!ihooks` is an older module for customizing imports, + superseded by the :mod:`!imputil` module added in Python 2.0. (Relative import support added by Neil Schemenauer.) .. revision 75423 @@ -1415,7 +1417,7 @@ changes, or look through the Subversion logs for all the details. :func:`~math.lgamma` for the natural log of the Gamma function. (Contributed by Mark Dickinson and nirinA raseliarison; :issue:`3366`.) -* The :mod:`multiprocessing` module's :class:`Manager*` classes +* The :mod:`multiprocessing` module's :class:`!Manager*` classes can now be passed a callable that will be called whenever a subprocess is started, along with a set of arguments that will be passed to the callable. @@ -2152,16 +2154,16 @@ Changes to Python's build process and to the C API include: * New function: stemming from the rewrite of string-to-float conversion, a new :c:func:`PyOS_string_to_double` function was added. The old - :c:func:`PyOS_ascii_strtod` and :c:func:`PyOS_ascii_atof` functions + :c:func:`!PyOS_ascii_strtod` and :c:func:`!PyOS_ascii_atof` functions are now deprecated. -* New function: :c:func:`PySys_SetArgvEx` sets the value of +* New function: :c:func:`!PySys_SetArgvEx` sets the value of ``sys.argv`` and can optionally update ``sys.path`` to include the directory containing the script named by ``sys.argv[0]`` depending on the value of an *updatepath* parameter. This function was added to close a security hole for applications - that embed Python. The old function, :c:func:`PySys_SetArgv`, would + that embed Python. The old function, :c:func:`!PySys_SetArgv`, would always update ``sys.path``, and sometimes it would add the current directory. This meant that, if you ran an application embedding Python in a directory controlled by someone else, attackers could @@ -2169,8 +2171,8 @@ Changes to Python's build process and to the C API include: :file:`os.py`) that your application would then import and run. If you maintain a C/C++ application that embeds Python, check - whether you're calling :c:func:`PySys_SetArgv` and carefully consider - whether the application should be using :c:func:`PySys_SetArgvEx` + whether you're calling :c:func:`!PySys_SetArgv` and carefully consider + whether the application should be using :c:func:`!PySys_SetArgvEx` with *updatepath* set to false. Security issue reported as `CVE-2008-5983 @@ -2195,13 +2197,13 @@ Changes to Python's build process and to the C API include: .. XXX these macros don't seem to be described in the c-api docs. -* Removed function: :c:macro:`PyEval_CallObject` is now only available +* Removed function: :c:func:`!PyEval_CallObject` is now only available as a macro. A function version was being kept around to preserve ABI linking compatibility, but that was in 1997; it can certainly be deleted by now. (Removed by Antoine Pitrou; :issue:`8276`.) -* New format codes: the :c:func:`PyFormat_FromString`, - :c:func:`PyFormat_FromStringV`, and :c:func:`PyErr_Format` functions now +* New format codes: the :c:func:`!PyString_FromFormat`, + :c:func:`!PyString_FromFormatV`, and :c:func:`PyErr_Format` functions now accept ``%lld`` and ``%llu`` format codes for displaying C's :c:expr:`long long` types. (Contributed by Mark Dickinson; :issue:`7228`.) @@ -2287,10 +2289,10 @@ object, and then get the ``void *`` pointer, which will usually point to an array of pointers to the module's various API functions. There is an existing data type already used for this, -:c:type:`PyCObject`, but it doesn't provide type safety. Evil code +:c:type:`!PyCObject`, but it doesn't provide type safety. Evil code written in pure Python could cause a segmentation fault by taking a -:c:type:`PyCObject` from module A and somehow substituting it for the -:c:type:`PyCObject` in module B. Capsules know their own name, +:c:type:`!PyCObject` from module A and somehow substituting it for the +:c:type:`!PyCObject` in module B. Capsules know their own name, and getting the pointer requires providing the name: .. code-block:: c @@ -2310,10 +2312,10 @@ detect the mismatched name and return false. Refer to :ref:`using-capsules` for more information on using these objects. Python 2.7 now uses capsules internally to provide various -extension-module APIs, but the :c:func:`PyCObject_AsVoidPtr` was +extension-module APIs, but the :c:func:`!PyCObject_AsVoidPtr` was modified to handle capsules, preserving compile-time compatibility -with the :c:type:`CObject` interface. Use of -:c:func:`PyCObject_AsVoidPtr` will signal a +with the :c:type:`!PyCObject` interface. Use of +:c:func:`!PyCObject_AsVoidPtr` will signal a :exc:`PendingDeprecationWarning`, which is silent by default. Implemented in Python 3.1 and backported to 2.7 by Larry Hastings; @@ -2368,7 +2370,7 @@ Port-Specific Changes: Mac OS X installation and a user-installed copy of the same version. (Changed by Ronald Oussoren; :issue:`4865`.) - .. versionchanged:: 2.7.13 + .. versionchanged:: 2.7.13 As of 2.7.13, this change was removed. ``/Library/Python/2.7/site-packages``, the site-packages directory @@ -2383,8 +2385,8 @@ Port-Specific Changes: Mac OS X Port-Specific Changes: FreeBSD ----------------------------------- -* FreeBSD 7.1's :const:`SO_SETFIB` constant, used with - :func:`~socket.getsockopt`/:func:`~socket.setsockopt` to select an +* FreeBSD 7.1's :const:`SO_SETFIB` constant, used with the :func:`~socket.socket` methods + :func:`~socket.socket.getsockopt`/:func:`~socket.socket.setsockopt` to select an alternate routing table, is now available in the :mod:`socket` module. (Added by Kyle VanderBeek; :issue:`8235`.) @@ -2404,7 +2406,7 @@ Other Changes and Fixes :issue:`5464`.) * When importing a module from a :file:`.pyc` or :file:`.pyo` file - with an existing :file:`.py` counterpart, the :attr:`co_filename` + with an existing :file:`.py` counterpart, the :attr:`~codeobject.co_filename` attributes of the resulting code objects are overwritten when the original filename is obsolete. This can happen if the file has been renamed, moved, or is accessed through different paths. (Patch by @@ -2449,13 +2451,13 @@ that may require changes to your code: (Changed by Eric Smith; :issue:`5920`.) * Because of an optimization for the :keyword:`with` statement, the special - methods :meth:`__enter__` and :meth:`__exit__` must belong to the object's + methods :meth:`~object.__enter__` and :meth:`~object.__exit__` must belong to the object's type, and cannot be directly attached to the object's instance. This affects new-style classes (derived from :class:`object`) and C extension types. (:issue:`6101`.) * Due to a bug in Python 2.6, the *exc_value* parameter to - :meth:`__exit__` methods was often the string representation of the + :meth:`~object.__exit__` methods was often the string representation of the exception, not an instance. This was fixed in 2.7, so *exc_value* will be an instance as expected. (Fixed by Florent Xicluna; :issue:`7853`.) @@ -2540,16 +2542,16 @@ For C extensions: instead of triggering a :exc:`DeprecationWarning` (:issue:`5080`). * Use the new :c:func:`PyOS_string_to_double` function instead of the old - :c:func:`PyOS_ascii_strtod` and :c:func:`PyOS_ascii_atof` functions, + :c:func:`!PyOS_ascii_strtod` and :c:func:`!PyOS_ascii_atof` functions, which are now deprecated. For applications that embed Python: -* The :c:func:`PySys_SetArgvEx` function was added, letting +* The :c:func:`!PySys_SetArgvEx` function was added, letting applications close a security hole when the existing - :c:func:`PySys_SetArgv` function was used. Check whether you're - calling :c:func:`PySys_SetArgv` and carefully consider whether the - application should be using :c:func:`PySys_SetArgvEx` with + :c:func:`!PySys_SetArgv` function was used. Check whether you're + calling :c:func:`!PySys_SetArgv` and carefully consider whether the + application should be using :c:func:`!PySys_SetArgvEx` with *updatepath* set to false. .. ====================================================================== diff --git a/Doc/whatsnew/3.0.rst b/Doc/whatsnew/3.0.rst index b767bbe177abeb..1df5209f22c6a5 100644 --- a/Doc/whatsnew/3.0.rst +++ b/Doc/whatsnew/3.0.rst @@ -555,8 +555,8 @@ very extensive changes to the standard library. :pep:`3108` is the reference for the major changes to the library. Here's a capsule review: -* Many old modules were removed. Some, like :mod:`gopherlib` (no - longer used) and :mod:`md5` (replaced by :mod:`hashlib`), were +* Many old modules were removed. Some, like :mod:`!gopherlib` (no + longer used) and :mod:`!md5` (replaced by :mod:`hashlib`), were already deprecated by :pep:`4`. Others were removed as a result of the removal of support for various platforms such as Irix, BeOS and Mac OS 9 (see :pep:`11`). Some modules were also selected for @@ -626,7 +626,7 @@ review: Some other changes to standard library modules, not covered by :pep:`3108`: -* Killed :mod:`sets`. Use the built-in :func:`set` class. +* Killed :mod:`!sets`. Use the built-in :func:`set` class. * Cleanup of the :mod:`sys` module: removed :func:`sys.exitfunc`, :func:`sys.exc_clear`, :data:`sys.exc_type`, :data:`sys.exc_value`, @@ -648,7 +648,7 @@ Some other changes to standard library modules, not covered by * Cleanup of the :mod:`random` module: removed the :func:`jumpahead` API. -* The :mod:`new` module is gone. +* The :mod:`!new` module is gone. * The functions :func:`os.tmpnam`, :func:`os.tempnam` and :func:`os.tmpfile` have been removed in favor of the :mod:`tempfile` @@ -711,7 +711,7 @@ new powerful features added: {Exception}({args})` instead of :samp:`raise {Exception}, {args}`. Additionally, you can no longer explicitly specify a traceback; instead, if you *have* to do this, you can assign directly to the - :attr:`__traceback__` attribute (see below). + :attr:`~BaseException.__traceback__` attribute (see below). * :pep:`3110`: Catching exceptions. You must now use :samp:`except {SomeException} as {variable}` instead @@ -725,7 +725,7 @@ new powerful features added: handler block. This usually happens due to a bug in the handler block; we call this a *secondary* exception. In this case, the original exception (that was being handled) is saved as the - :attr:`__context__` attribute of the secondary exception. + :attr:`~BaseException.__context__` attribute of the secondary exception. Explicit chaining is invoked with this syntax:: raise SecondaryException() from primary_exception @@ -733,14 +733,15 @@ new powerful features added: (where *primary_exception* is any expression that produces an exception object, probably an exception that was previously caught). In this case, the primary exception is stored on the - :attr:`__cause__` attribute of the secondary exception. The + :attr:`~BaseException.__cause__` attribute of the secondary exception. The traceback printed when an unhandled exception occurs walks the chain - of :attr:`__cause__` and :attr:`__context__` attributes and prints a + of :attr:`!__cause__` and :attr:`~BaseException.__context__` attributes and + prints a separate traceback for each component of the chain, with the primary exception at the top. (Java users may recognize this behavior.) * :pep:`3134`: Exception objects now store their traceback as the - :attr:`__traceback__` attribute. This means that an exception + :attr:`~BaseException.__traceback__` attribute. This means that an exception object now contains all the information pertaining to an exception, and there are fewer reasons to use :func:`sys.exc_info` (though the latter is not removed). @@ -779,14 +780,15 @@ Operators And Special Methods * Removed support for :attr:`__members__` and :attr:`__methods__`. -* The function attributes named :attr:`func_X` have been renamed to - use the :data:`__X__` form, freeing up these names in the function +* The function attributes named :attr:`!func_X` have been renamed to + use the :attr:`!__X__` form, freeing up these names in the function attribute namespace for user-defined attributes. To wit, - :attr:`func_closure`, :attr:`func_code`, :attr:`func_defaults`, - :attr:`func_dict`, :attr:`func_doc`, :attr:`func_globals`, - :attr:`func_name` were renamed to :attr:`__closure__`, - :attr:`__code__`, :attr:`__defaults__`, :attr:`~object.__dict__`, - :attr:`__doc__`, :attr:`__globals__`, :attr:`~definition.__name__`, + :attr:`!func_closure`, :attr:`!func_code`, :attr:`!func_defaults`, + :attr:`!func_dict`, :attr:`!func_doc`, :attr:`!func_globals`, + :attr:`!func_name` were renamed to :attr:`~function.__closure__`, + :attr:`~function.__code__`, :attr:`~function.__defaults__`, + :attr:`~function.__dict__`, :attr:`~function.__doc__`, + :attr:`~function.__globals__`, :attr:`~function.__name__`, respectively. * :meth:`!__nonzero__` is now :meth:`~object.__bool__`. @@ -865,8 +867,8 @@ to the C API. * No more C API support for restricted execution. -* :c:func:`PyNumber_Coerce`, :c:func:`PyNumber_CoerceEx`, - :c:func:`PyMember_Get`, and :c:func:`PyMember_Set` C APIs are removed. +* :c:func:`!PyNumber_Coerce`, :c:func:`!PyNumber_CoerceEx`, + :c:func:`!PyMember_Get`, and :c:func:`!PyMember_Set` C APIs are removed. * New C API :c:func:`PyImport_ImportModuleNoBlock`, works like :c:func:`PyImport_ImportModule` but won't block on the import lock @@ -875,7 +877,7 @@ to the C API. * Renamed the boolean conversion C-level slot and method: ``nb_nonzero`` is now ``nb_bool``. -* Removed :c:macro:`METH_OLDARGS` and :c:macro:`WITH_CYCLE_GC` from the C API. +* Removed :c:macro:`!METH_OLDARGS` and :c:macro:`!WITH_CYCLE_GC` from the C API. .. ====================================================================== diff --git a/Doc/whatsnew/3.1.rst b/Doc/whatsnew/3.1.rst index c399f007fd63fb..e237179f4b1829 100644 --- a/Doc/whatsnew/3.1.rst +++ b/Doc/whatsnew/3.1.rst @@ -501,16 +501,16 @@ Changes to Python's build process and to the C API include: (Contributed by Mark Dickinson and Lisandro Dalcrin; :issue:`5175`.) -* Deprecated :c:func:`PyNumber_Int`. Use :c:func:`PyNumber_Long` instead. +* Deprecated :c:func:`!PyNumber_Int`. Use :c:func:`PyNumber_Long` instead. (Contributed by Mark Dickinson; :issue:`4910`.) * Added a new :c:func:`PyOS_string_to_double` function to replace the - deprecated functions :c:func:`PyOS_ascii_strtod` and :c:func:`PyOS_ascii_atof`. + deprecated functions :c:func:`!PyOS_ascii_strtod` and :c:func:`!PyOS_ascii_atof`. (Contributed by Mark Dickinson; :issue:`5914`.) -* Added :c:type:`PyCapsule` as a replacement for the :c:type:`PyCObject` API. +* Added :c:type:`PyCapsule` as a replacement for the :c:type:`!PyCObject` API. The principal difference is that the new type has a well defined interface for passing typing safety information and a less complicated signature for calling a destructor. The old type had a problematic API and is now diff --git a/Doc/whatsnew/3.10.rst b/Doc/whatsnew/3.10.rst index e4ca3c4c81ba58..7dc06e9af694d9 100644 --- a/Doc/whatsnew/3.10.rst +++ b/Doc/whatsnew/3.10.rst @@ -221,116 +221,116 @@ have been incorporated. Some of the most notable ones are as follows: * Missing ``:`` before blocks: - .. code-block:: python + .. code-block:: python - >>> if rocket.position > event_horizon - File "", line 1 - if rocket.position > event_horizon - ^ - SyntaxError: expected ':' + >>> if rocket.position > event_horizon + File "", line 1 + if rocket.position > event_horizon + ^ + SyntaxError: expected ':' - (Contributed by Pablo Galindo in :issue:`42997`.) + (Contributed by Pablo Galindo in :issue:`42997`.) * Unparenthesised tuples in comprehensions targets: - .. code-block:: python + .. code-block:: python - >>> {x,y for x,y in zip('abcd', '1234')} - File "", line 1 - {x,y for x,y in zip('abcd', '1234')} - ^ - SyntaxError: did you forget parentheses around the comprehension target? + >>> {x,y for x,y in zip('abcd', '1234')} + File "", line 1 + {x,y for x,y in zip('abcd', '1234')} + ^ + SyntaxError: did you forget parentheses around the comprehension target? - (Contributed by Pablo Galindo in :issue:`43017`.) + (Contributed by Pablo Galindo in :issue:`43017`.) * Missing commas in collection literals and between expressions: - .. code-block:: python + .. code-block:: python - >>> items = { - ... x: 1, - ... y: 2 - ... z: 3, - File "", line 3 - y: 2 - ^ - SyntaxError: invalid syntax. Perhaps you forgot a comma? + >>> items = { + ... x: 1, + ... y: 2 + ... z: 3, + File "", line 3 + y: 2 + ^ + SyntaxError: invalid syntax. Perhaps you forgot a comma? - (Contributed by Pablo Galindo in :issue:`43822`.) + (Contributed by Pablo Galindo in :issue:`43822`.) * Multiple Exception types without parentheses: - .. code-block:: python + .. code-block:: python - >>> try: - ... build_dyson_sphere() - ... except NotEnoughScienceError, NotEnoughResourcesError: - File "", line 3 - except NotEnoughScienceError, NotEnoughResourcesError: - ^ - SyntaxError: multiple exception types must be parenthesized + >>> try: + ... build_dyson_sphere() + ... except NotEnoughScienceError, NotEnoughResourcesError: + File "", line 3 + except NotEnoughScienceError, NotEnoughResourcesError: + ^ + SyntaxError: multiple exception types must be parenthesized - (Contributed by Pablo Galindo in :issue:`43149`.) + (Contributed by Pablo Galindo in :issue:`43149`.) * Missing ``:`` and values in dictionary literals: - .. code-block:: python + .. code-block:: python - >>> values = { - ... x: 1, - ... y: 2, - ... z: - ... } - File "", line 4 - z: - ^ - SyntaxError: expression expected after dictionary key and ':' + >>> values = { + ... x: 1, + ... y: 2, + ... z: + ... } + File "", line 4 + z: + ^ + SyntaxError: expression expected after dictionary key and ':' - >>> values = {x:1, y:2, z w:3} - File "", line 1 - values = {x:1, y:2, z w:3} - ^ - SyntaxError: ':' expected after dictionary key + >>> values = {x:1, y:2, z w:3} + File "", line 1 + values = {x:1, y:2, z w:3} + ^ + SyntaxError: ':' expected after dictionary key - (Contributed by Pablo Galindo in :issue:`43823`.) + (Contributed by Pablo Galindo in :issue:`43823`.) * ``try`` blocks without ``except`` or ``finally`` blocks: - .. code-block:: python + .. code-block:: python - >>> try: - ... x = 2 - ... something = 3 - File "", line 3 - something = 3 - ^^^^^^^^^ - SyntaxError: expected 'except' or 'finally' block + >>> try: + ... x = 2 + ... something = 3 + File "", line 3 + something = 3 + ^^^^^^^^^ + SyntaxError: expected 'except' or 'finally' block - (Contributed by Pablo Galindo in :issue:`44305`.) + (Contributed by Pablo Galindo in :issue:`44305`.) * Usage of ``=`` instead of ``==`` in comparisons: - .. code-block:: python + .. code-block:: python - >>> if rocket.position = event_horizon: - File "", line 1 - if rocket.position = event_horizon: - ^ - SyntaxError: cannot assign to attribute here. Maybe you meant '==' instead of '='? + >>> if rocket.position = event_horizon: + File "", line 1 + if rocket.position = event_horizon: + ^ + SyntaxError: cannot assign to attribute here. Maybe you meant '==' instead of '='? - (Contributed by Pablo Galindo in :issue:`43797`.) + (Contributed by Pablo Galindo in :issue:`43797`.) * Usage of ``*`` in f-strings: - .. code-block:: python + .. code-block:: python - >>> f"Black holes {*all_black_holes} and revelations" - File "", line 1 - (*all_black_holes) - ^ - SyntaxError: f-string: cannot use starred expression here + >>> f"Black holes {*all_black_holes} and revelations" + File "", line 1 + (*all_black_holes) + ^ + SyntaxError: f-string: cannot use starred expression here - (Contributed by Pablo Galindo in :issue:`41064`.) + (Contributed by Pablo Galindo in :issue:`41064`.) IndentationErrors ~~~~~~~~~~~~~~~~~ @@ -365,10 +365,10 @@ raised from: (Contributed by Pablo Galindo in :issue:`38530`.) - .. warning:: - Notice this won't work if :c:func:`PyErr_Display` is not called to display the error - which can happen if some other custom error display function is used. This is a common - scenario in some REPLs like IPython. +.. warning:: + Notice this won't work if :c:func:`PyErr_Display` is not called to display the error + which can happen if some other custom error display function is used. This is a common + scenario in some REPLs like IPython. NameErrors ~~~~~~~~~~ @@ -387,10 +387,10 @@ was raised from: (Contributed by Pablo Galindo in :issue:`38530`.) - .. warning:: - Notice this won't work if :c:func:`PyErr_Display` is not called to display the error, - which can happen if some other custom error display function is used. This is a common - scenario in some REPLs like IPython. +.. warning:: + Notice this won't work if :c:func:`PyErr_Display` is not called to display the error, + which can happen if some other custom error display function is used. This is a common + scenario in some REPLs like IPython. PEP 626: Precise line numbers for debugging and other tools @@ -399,10 +399,14 @@ PEP 626: Precise line numbers for debugging and other tools PEP 626 brings more precise and reliable line numbers for debugging, profiling and coverage tools. Tracing events, with the correct line number, are generated for all lines of code executed and only for lines of code that are executed. -The ``f_lineno`` attribute of frame objects will always contain the expected line number. +The :attr:`~frame.f_lineno` attribute of frame objects will always contain the +expected line number. -The ``co_lnotab`` attribute of code objects is deprecated and will be removed in 3.12. -Code that needs to convert from offset to line number should use the new ``co_lines()`` method instead. +The :attr:`~codeobject.co_lnotab` attribute of +:ref:`code objects ` is deprecated and +will be removed in 3.12. +Code that needs to convert from offset to line number should use the new +:meth:`~codeobject.co_lines` method instead. PEP 634: Structural Pattern Matching ------------------------------------ @@ -433,16 +437,16 @@ A match statement takes an expression and compares its value to successive patterns given as one or more case blocks. Specifically, pattern matching operates by: - 1. using data with type and shape (the ``subject``) - 2. evaluating the ``subject`` in the ``match`` statement - 3. comparing the subject with each pattern in a ``case`` statement - from top to bottom until a match is confirmed. - 4. executing the action associated with the pattern of the confirmed - match - 5. If an exact match is not confirmed, the last case, a wildcard ``_``, - if provided, will be used as the matching case. If an exact match is - not confirmed and a wildcard case does not exist, the entire match - block is a no-op. +1. using data with type and shape (the ``subject``) +2. evaluating the ``subject`` in the ``match`` statement +3. comparing the subject with each pattern in a ``case`` statement + from top to bottom until a match is confirmed. +4. executing the action associated with the pattern of the confirmed + match +5. If an exact match is not confirmed, the last case, a wildcard ``_``, + if provided, will be used as the matching case. If an exact match is + not confirmed and a wildcard case does not exist, the entire match + block is a no-op. Declarative approach ~~~~~~~~~~~~~~~~~~~~ @@ -878,7 +882,7 @@ Other Language Changes (Contributed by Raymond Hettinger in :issue:`43475`.) * A :exc:`SyntaxError` (instead of a :exc:`NameError`) will be raised when deleting - the :const:`__debug__` constant. (Contributed by Dong-hee Na in :issue:`45000`.) + the :const:`__debug__` constant. (Contributed by Donghee Na in :issue:`45000`.) * :exc:`SyntaxError` exceptions now have ``end_lineno`` and ``end_offset`` attributes. They will be ``None`` if not determined. @@ -1255,7 +1259,7 @@ pipe. (Contributed by Pablo Galindo in :issue:`41625`.) Add :const:`~os.O_EVTONLY`, :const:`~os.O_FSYNC`, :const:`~os.O_SYMLINK` and :const:`~os.O_NOFOLLOW_ANY` for macOS. -(Contributed by Dong-hee Na in :issue:`43106`.) +(Contributed by Donghee Na in :issue:`43106`.) os.path ------- @@ -1276,7 +1280,7 @@ Add negative indexing support to :attr:`PurePath.parents (Contributed by Yaroslav Pankovych in :issue:`21041`.) Add :meth:`Path.hardlink_to ` method that -supersedes :meth:`~pathlib.Path.link_to`. The new method has the same argument +supersedes :meth:`!link_to`. The new method has the same argument order as :meth:`~pathlib.Path.symlink_to`. (Contributed by Barney Gale in :issue:`39950`.) @@ -1312,8 +1316,8 @@ pyclbr ------ Add an ``end_lineno`` attribute to the ``Function`` and ``Class`` -objects in the tree returned by :func:`pyclbr.readline` and -:func:`pyclbr.readline_ex`. It matches the existing (start) ``lineno``. +objects in the tree returned by :func:`pyclbr.readmodule` and +:func:`pyclbr.readmodule_ex`. It matches the existing (start) ``lineno``. (Contributed by Aviral Srivastava in :issue:`38307`.) shelve @@ -1582,7 +1586,7 @@ Optimizations * The following built-in functions now support the faster :pep:`590` vectorcall calling convention: :func:`map`, :func:`filter`, :func:`reversed`, :func:`bool` and :func:`float`. - (Contributed by Dong-hee Na and Jeroen Demeyer in :issue:`43575`, :issue:`43287`, :issue:`41922`, :issue:`41873` and :issue:`41870`.) + (Contributed by Donghee Na and Jeroen Demeyer in :issue:`43575`, :issue:`43287`, :issue:`41922`, :issue:`41873` and :issue:`41870`.) * :class:`BZ2File` performance is improved by removing internal ``RLock``. This makes :class:`BZ2File` thread unsafe in the face of multiple simultaneous @@ -1738,7 +1742,7 @@ Deprecated (Contributed by Jelle Zijlstra in :gh:`87889`.) -* :meth:`pathlib.Path.link_to` is deprecated and slated for removal in +* :meth:`!pathlib.Path.link_to` is deprecated and slated for removal in Python 3.12. Use :meth:`pathlib.Path.hardlink_to` instead. (Contributed by Barney Gale in :issue:`39950`.) @@ -1769,7 +1773,7 @@ Deprecated * NPN features like :meth:`ssl.SSLSocket.selected_npn_protocol` and :meth:`ssl.SSLContext.set_npn_protocols` are replaced by ALPN. -* The threading debug (:envvar:`PYTHONTHREADDEBUG` environment variable) is +* The threading debug (:envvar:`!PYTHONTHREADDEBUG` environment variable) is deprecated in Python 3.10 and will be removed in Python 3.12. This feature requires a :ref:`debug build of Python `. (Contributed by Victor Stinner in :issue:`44584`.) @@ -1817,10 +1821,10 @@ Removed scheduled to be removed in Python 3.6, but such removals were delayed until after Python 2.7 EOL. Existing users should copy whatever classes they use into their code. - (Contributed by Dong-hee Na and Terry J. Reedy in :issue:`42299`.) + (Contributed by Donghee Na and Terry J. Reedy in :issue:`42299`.) -* Removed the :c:func:`PyModule_GetWarningsModule` function that was useless - now due to the _warnings module was converted to a builtin module in 2.6. +* Removed the :c:func:`!PyModule_GetWarningsModule` function that was useless + now due to the :mod:`!_warnings` module was converted to a builtin module in 2.6. (Contributed by Hai Shi in :issue:`42599`.) * Remove deprecated aliases to :ref:`collections-abstract-base-classes` from @@ -1959,11 +1963,11 @@ Changes in the C API source_buf = PyBytes_AsString(source_bytes_object); code = Py_CompileString(source_buf, filename, Py_file_input); - * For ``FrameObject`` objects, the ``f_lasti`` member now represents a wordcode + * For ``FrameObject`` objects, the :attr:`~frame.f_lasti` member now represents a wordcode offset instead of a simple offset into the bytecode string. This means that this number needs to be multiplied by 2 to be used with APIs that expect a byte offset instead (like :c:func:`PyCode_Addr2Line` for example). Notice as well that the - ``f_lasti`` member of ``FrameObject`` objects is not considered stable: please + :attr:`!f_lasti` member of ``FrameObject`` objects is not considered stable: please use :c:func:`PyFrame_GetLineNumber` instead. CPython bytecode changes @@ -2211,16 +2215,16 @@ Removed * Removed ``Py_UNICODE_str*`` functions manipulating ``Py_UNICODE*`` strings. (Contributed by Inada Naoki in :issue:`41123`.) - * ``Py_UNICODE_strlen``: use :c:func:`PyUnicode_GetLength` or - :c:macro:`PyUnicode_GET_LENGTH` - * ``Py_UNICODE_strcat``: use :c:func:`PyUnicode_CopyCharacters` or - :c:func:`PyUnicode_FromFormat` - * ``Py_UNICODE_strcpy``, ``Py_UNICODE_strncpy``: use - :c:func:`PyUnicode_CopyCharacters` or :c:func:`PyUnicode_Substring` - * ``Py_UNICODE_strcmp``: use :c:func:`PyUnicode_Compare` - * ``Py_UNICODE_strncmp``: use :c:func:`PyUnicode_Tailmatch` - * ``Py_UNICODE_strchr``, ``Py_UNICODE_strrchr``: use - :c:func:`PyUnicode_FindChar` + * ``Py_UNICODE_strlen``: use :c:func:`PyUnicode_GetLength` or + :c:macro:`PyUnicode_GET_LENGTH` + * ``Py_UNICODE_strcat``: use :c:func:`PyUnicode_CopyCharacters` or + :c:func:`PyUnicode_FromFormat` + * ``Py_UNICODE_strcpy``, ``Py_UNICODE_strncpy``: use + :c:func:`PyUnicode_CopyCharacters` or :c:func:`PyUnicode_Substring` + * ``Py_UNICODE_strcmp``: use :c:func:`PyUnicode_Compare` + * ``Py_UNICODE_strncmp``: use :c:func:`PyUnicode_Tailmatch` + * ``Py_UNICODE_strchr``, ``Py_UNICODE_strrchr``: use + :c:func:`PyUnicode_FindChar` * Removed ``PyUnicode_GetMax()``. Please migrate to new (:pep:`393`) APIs. (Contributed by Inada Naoki in :issue:`41103`.) diff --git a/Doc/whatsnew/3.11.rst b/Doc/whatsnew/3.11.rst index ec5263ec35c52f..cb646a54df3607 100644 --- a/Doc/whatsnew/3.11.rst +++ b/Doc/whatsnew/3.11.rst @@ -45,7 +45,7 @@ when researching a change. This article explains the new features in Python 3.11, compared to 3.10. - +Python 3.11 was released on October 24, 2022. For full details, see the :ref:`changelog `. @@ -218,7 +218,7 @@ Windows ``py.exe`` launcher improvements The copy of the :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 ``-.``. +:samp:`-V:{}/{}` argument instead of the limited :samp:`-{}.{}`. This allows launching distributions other than ``PythonCore``, the one hosted on `python.org `_. @@ -227,8 +227,8 @@ 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 the legacy ``-``, ``-.``, -``--`` or ``-.-`` arguments, +When using the legacy :samp:`-{}`, :samp:`-{}.{}`, +:samp:`-{}-{}` or :samp:`-{}.{}-{}` arguments, all existing behaviour should be preserved from past versions, and only releases from ``PythonCore`` will be selected. However, the ``-64`` suffix now implies "not 32-bit" (not necessarily x86-64), @@ -459,6 +459,10 @@ Other Language Changes :class:`collections.OrderedDict`, :class:`collections.deque`, :class:`weakref.WeakSet`, and :class:`datetime.tzinfo` now copies and pickles instance attributes implemented as :term:`slots <__slots__>`. + This change has an unintended side effect: It trips up a small minority + of existing Python projects not expecting :meth:`object.__getstate__` to + exist. See the later comments on :gh:`70766` for discussions of what + workarounds such code may need. (Contributed by Serhiy Storchaka in :issue:`26579`.) .. _whatsnew311-pythonsafepath: @@ -495,7 +499,7 @@ Other CPython Implementation Changes * The special methods :meth:`~object.__complex__` for :class:`complex` and :meth:`~object.__bytes__` for :class:`bytes` are implemented to support the :class:`typing.SupportsComplex` and :class:`typing.SupportsBytes` protocols. - (Contributed by Mark Dickinson and Dong-hee Na in :issue:`24234`.) + (Contributed by Mark Dickinson and Donghee Na in :issue:`24234`.) * ``siphash13`` is added as a new internal hashing algorithm. It has similar security properties as ``siphash24``, @@ -893,7 +897,7 @@ os * On Windows, :func:`os.urandom` now uses ``BCryptGenRandom()``, instead of ``CryptGenRandom()`` which is deprecated. - (Contributed by Dong-hee Na in :issue:`44611`.) + (Contributed by Donghee Na in :issue:`44611`.) .. _whatsnew311-pathlib: @@ -1085,7 +1089,7 @@ time `_ which has a resolution of 100 nanoseconds (10\ :sup:`-7` seconds). Previously, 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`.) + (Contributed by Benjamin SzÅ‘ke, Donghee Na, Eryk Sun and Victor Stinner in :issue:`21302` and :issue:`45429`.) .. _whatsnew311-tkinter: @@ -1301,7 +1305,7 @@ This section covers specific optimizations independent of the * :func:`unicodedata.normalize` now normalizes pure-ASCII strings in constant time. - (Contributed by Dong-hee Na in :issue:`44987`.) + (Contributed by Donghee Na in :issue:`44987`.) .. _whatsnew311-faster-cpython: @@ -1448,7 +1452,7 @@ Bucher, with additional help from Irit Katriel and Dennis Sweeney.) | | | | (up to) | | +===============+====================+=======================================================+===================+===================+ | Binary | ``x + x`` | Binary add, multiply and subtract for common types | 10% | Mark Shannon, | -| operations | | such as :class:`int`, :class:`float` and :class:`str` | | Dong-hee Na, | +| operations | | such as :class:`int`, :class:`float` and :class:`str` | | Donghee Na, | | | ``x - x`` | take custom fast paths for their underlying types. | | Brandt Bucher, | | | | | | Dennis Sweeney | | | ``x * x`` | | | | @@ -1743,7 +1747,7 @@ Modules (Contributed by Brett Cannon in :issue:`47061` and Victor Stinner in :gh:`68966`.) -* The :mod:`asynchat`, :mod:`asyncore` and :mod:`smtpd` modules have been +* The :mod:`!asynchat`, :mod:`!asyncore` and :mod:`!smtpd` modules have been deprecated since at least Python 3.6. Their documentation and deprecation warnings have now been updated to note they will be removed in Python 3.12. (Contributed by Hugo van Kemenade in :issue:`47022`.) @@ -1769,7 +1773,7 @@ Standard Library * the :class:`!configparser.SafeConfigParser` class * the :attr:`!configparser.ParsingError.filename` property - * the :meth:`configparser.RawConfigParser.readfp` method + * the :meth:`!configparser.RawConfigParser.readfp` method (Contributed by Hugo van Kemenade in :issue:`45173`.) @@ -1794,7 +1798,7 @@ Standard Library * :func:`importlib.resources.path` * The :func:`locale.getdefaultlocale` function is deprecated and will be - removed in Python 3.13. Use :func:`locale.setlocale`, + removed in Python 3.15. Use :func:`locale.setlocale`, :func:`locale.getpreferredencoding(False) ` and :func:`locale.getlocale` functions instead. (Contributed by Victor Stinner in :gh:`90817`.) @@ -1835,7 +1839,7 @@ Standard Library * :class:`!webbrowser.MacOSX` is deprecated and will be removed in Python 3.13. It is untested, undocumented, and not used by :mod:`webbrowser` itself. - (Contributed by Dong-hee Na in :issue:`42255`.) + (Contributed by Donghee Na in :issue:`42255`.) * The behavior of returning a value from a :class:`~unittest.TestCase` and :class:`~unittest.IsolatedAsyncioTestCase` test methods (other than the @@ -1856,7 +1860,7 @@ Standard Library (Contributed by Erlend E. Aasland in :issue:`5846`.) -* :meth:`~!unittest.TestProgram.usageExit` is marked deprecated, to be removed +* :meth:`!unittest.TestProgram.usageExit` is marked deprecated, to be removed in 3.13. (Contributed by Carlos Damázio in :gh:`67048`.) @@ -1873,8 +1877,8 @@ and will be removed in Python 3.12. C APIs pending removal are :ref:`listed separately `. -* The :mod:`asynchat` module -* The :mod:`asyncore` module +* The :mod:`!asynchat` module +* The :mod:`!asyncore` module * The :ref:`entire distutils package ` * The :mod:`!imp` module * The :class:`typing.io ` namespace @@ -1898,10 +1902,10 @@ C APIs pending removal are * :func:`!importlib.util.set_package_wrapper` * :class:`!pkgutil.ImpImporter` * :class:`!pkgutil.ImpLoader` -* :meth:`pathlib.Path.link_to` +* :meth:`!pathlib.Path.link_to` * :func:`!sqlite3.enable_shared_cache` * :func:`!sqlite3.OptimizedUnicode` -* :envvar:`PYTHONTHREADDEBUG` environment variable +* :envvar:`!PYTHONTHREADDEBUG` environment variable * The following deprecated aliases in :mod:`unittest`: ============================ =============================== =============== @@ -1980,7 +1984,7 @@ Removed C APIs are :ref:`listed separately `. :meth:`!NullTranslations.set_output_charset` methods, and the *codeset* parameter of :func:`!translation` and :func:`!install`, since they are only used for the :func:`!l*gettext` functions. - (Contributed by Dong-hee Na and Serhiy Storchaka in :issue:`44235`.) + (Contributed by Donghee Na and Serhiy Storchaka in :issue:`44235`.) * Removed from the :mod:`inspect` module: @@ -2003,9 +2007,9 @@ Removed C APIs are :ref:`listed separately `. because it was not used and added by mistake in previous versions. (Contributed by Nikita Sobolev in :issue:`46483`.) -* Removed the :class:`!MailmanProxy` class in the :mod:`smtpd` module, +* Removed the :class:`!MailmanProxy` class in the :mod:`!smtpd` module, as it is unusable without the external :mod:`!mailman` package. - (Contributed by Dong-hee Na in :issue:`35800`.) + (Contributed by Donghee Na in :issue:`35800`.) * Removed the deprecated :meth:`!split` method of :class:`!_tkinter.TkappType`. (Contributed by Erlend E. Aasland in :issue:`38371`.) @@ -2147,7 +2151,7 @@ Build Changes * CPython can now be built with the `ThinLTO `_ option via passing ``thin`` to :option:`--with-lto`, i.e. ``--with-lto=thin``. - (Contributed by Dong-hee Na and Brett Holman in :issue:`44340`.) + (Contributed by Donghee Na and Brett Holman in :issue:`44340`.) * Freelists for object structs can now be disabled. A new :program:`configure` option :option:`--without-freelists` can be used to disable all freelists @@ -2216,7 +2220,7 @@ New Features * :c:func:`PyBuffer_SizeFromFormat` * :c:func:`PyBuffer_ToContiguous` * :c:func:`PyBuffer_FromContiguous` - * :c:func:`PyBuffer_CopyData` + * :c:func:`PyObject_CopyData` * :c:func:`PyBuffer_IsContiguous` * :c:func:`PyBuffer_FillContiguousStrides` * :c:func:`PyBuffer_FillInfo` @@ -2454,11 +2458,12 @@ Porting to Python 3.11 * ``f_valuestack``: removed. The Python frame object is now created lazily. A side effect is that the - ``f_back`` member must not be accessed directly, since its value is now also + :attr:`~frame.f_back` member must not be accessed directly, + since its value is now also computed lazily. The :c:func:`PyFrame_GetBack` function must be called instead. - Debuggers that accessed the ``f_locals`` directly *must* call + Debuggers that accessed the :attr:`~frame.f_locals` directly *must* call :c:func:`PyFrame_GetLocals` instead. They no longer need to call :c:func:`PyFrame_FastToLocalsWithError` or :c:func:`PyFrame_LocalsToFast`, in fact they should not call those functions. The necessary updating of the @@ -2562,18 +2567,18 @@ Deprecated * Deprecate the following functions to configure the Python initialization: - * :c:func:`PySys_AddWarnOptionUnicode` - * :c:func:`PySys_AddWarnOption` - * :c:func:`PySys_AddXOption` - * :c:func:`PySys_HasWarnOptions` - * :c:func:`PySys_SetArgvEx` - * :c:func:`PySys_SetArgv` - * :c:func:`PySys_SetPath` - * :c:func:`Py_SetPath` - * :c:func:`Py_SetProgramName` - * :c:func:`Py_SetPythonHome` - * :c:func:`Py_SetStandardStreamEncoding` - * :c:func:`_Py_SetProgramFullPath` + * :c:func:`!PySys_AddWarnOptionUnicode` + * :c:func:`!PySys_AddWarnOption` + * :c:func:`!PySys_AddXOption` + * :c:func:`!PySys_HasWarnOptions` + * :c:func:`!PySys_SetArgvEx` + * :c:func:`!PySys_SetArgv` + * :c:func:`!PySys_SetPath` + * :c:func:`!Py_SetPath` + * :c:func:`!Py_SetProgramName` + * :c:func:`!Py_SetPythonHome` + * :c:func:`!Py_SetStandardStreamEncoding` + * :c:func:`!_Py_SetProgramFullPath` Use the new :c:type:`PyConfig` API of the :ref:`Python Initialization Configuration ` instead (:pep:`587`). @@ -2591,22 +2596,22 @@ Pending Removal in Python 3.12 The following C APIs have been deprecated in earlier Python releases, and will be removed in Python 3.12. -* :c:func:`PyUnicode_AS_DATA` -* :c:func:`PyUnicode_AS_UNICODE` -* :c:func:`PyUnicode_AsUnicodeAndSize` -* :c:func:`PyUnicode_AsUnicode` -* :c:func:`PyUnicode_FromUnicode` -* :c:func:`PyUnicode_GET_DATA_SIZE` -* :c:func:`PyUnicode_GET_SIZE` -* :c:func:`PyUnicode_GetSize` +* :c:func:`!PyUnicode_AS_DATA` +* :c:func:`!PyUnicode_AS_UNICODE` +* :c:func:`!PyUnicode_AsUnicodeAndSize` +* :c:func:`!PyUnicode_AsUnicode` +* :c:func:`!PyUnicode_FromUnicode` +* :c:func:`!PyUnicode_GET_DATA_SIZE` +* :c:func:`!PyUnicode_GET_SIZE` +* :c:func:`!PyUnicode_GetSize` * :c:func:`PyUnicode_IS_COMPACT` * :c:func:`PyUnicode_IS_READY` * :c:func:`PyUnicode_READY` -* :c:func:`Py_UNICODE_WSTR_LENGTH` -* :c:func:`_PyUnicode_AsUnicode` -* :c:macro:`PyUnicode_WCHAR_KIND` +* :c:func:`!PyUnicode_WSTR_LENGTH` +* :c:func:`!_PyUnicode_AsUnicode` +* :c:macro:`!PyUnicode_WCHAR_KIND` * :c:type:`PyUnicodeObject` -* :c:func:`PyUnicode_InternImmortal()` +* :c:func:`!PyUnicode_InternImmortal` .. _whatsnew311-c-api-removed: @@ -2614,7 +2619,7 @@ and will be removed in Python 3.12. Removed ------- -* :c:func:`PyFrame_BlockSetup` and :c:func:`PyFrame_BlockPop` have been +* :c:func:`!PyFrame_BlockSetup` and :c:func:`!PyFrame_BlockPop` have been removed. (Contributed by Mark Shannon in :issue:`40222`.) diff --git a/Doc/whatsnew/3.12.rst b/Doc/whatsnew/3.12.rst index 6553013552d003..9a2ccf7ebc6a68 100644 --- a/Doc/whatsnew/3.12.rst +++ b/Doc/whatsnew/3.12.rst @@ -3,7 +3,7 @@ What's New In Python 3.12 **************************** -:Editor: TBD +:Editor: Adam Turner .. Rules for maintenance: @@ -46,15 +46,12 @@ researching a change. This article explains the new features in Python 3.12, compared to 3.11. - +Python 3.12 was released on October 2, 2023. For full details, see the :ref:`changelog `. -.. note:: - - Prerelease users should be aware that this document is currently in draft - form. It will be updated substantially as Python 3.12 moves towards release, - so it's worth checking back even after reading earlier versions. +.. seealso:: + :pep:`693` -- Python 3.12 Release Schedule Summary -- Release highlights ============================= @@ -62,102 +59,198 @@ Summary -- Release highlights .. This section singles out the most important changes in Python 3.12. Brevity is key. +Python 3.12 is the latest stable release of the Python programming language, +with a mix of changes to the language and the standard library. +The library changes focus on cleaning up deprecated APIs, usability, and correctness. +Of note, the :mod:`!distutils` package has been removed from the standard library. +Filesystem support in :mod:`os` and :mod:`pathlib` has seen a number of improvements, +and several modules have better performance. + +The language changes focus on usability, +as :term:`f-strings ` have had many limitations removed +and 'Did you mean ...' suggestions continue to improve. +The new :ref:`type parameter syntax ` +and :keyword:`type` statement improve ergonomics for using :term:`generic types +` and :term:`type aliases ` with static type checkers. + +This article doesn't attempt to provide a complete specification of all new features, +but instead gives a convenient overview. +For full details, you should refer to the documentation, +such as the :ref:`Library Reference ` +and :ref:`Language Reference `. +If you want to understand the complete implementation and design rationale for a change, +refer to the PEP for a particular new feature; +but note that PEPs usually are not kept up-to-date +once a feature has been fully implemented. + +-------------- .. PEP-sized items next. +New syntax features: + +* :ref:`PEP 695 `, type parameter syntax and the :keyword:`type` statement + New grammar features: -* :pep:`701`: Syntactic formalization of f-strings +* :ref:`PEP 701 `, :term:`f-strings ` in the grammar Interpreter improvements: -* :ref:`whatsnew312-pep684` +* :ref:`PEP 684 `, a unique per-interpreter :term:`GIL + ` +* :ref:`PEP 669 `, low impact monitoring +* `Improved 'Did you mean ...' suggestions `_ + for :exc:`NameError`, :exc:`ImportError`, and :exc:`SyntaxError` exceptions -New typing features: +Python data model improvements: + +* :ref:`PEP 688 `, using the :ref:`buffer protocol + ` from Python + +Significant improvements in the standard library: + +* The :class:`pathlib.Path` class now supports subclassing +* The :mod:`os` module received several improvements for Windows support +* A :ref:`command-line interface ` has been added to the + :mod:`sqlite3` module +* :func:`isinstance` checks against :func:`runtime-checkable protocols + ` enjoy a speed up of between two and 20 times +* The :mod:`asyncio` package has had a number of performance improvements, + with some benchmarks showing a 75% speed up. +* A :ref:`command-line interface ` has been added to the + :mod:`uuid` module +* Due to the changes in :ref:`PEP 701 `, + producing tokens via the :mod:`tokenize` module is up to 64% faster. + +Security improvements: + +* Replace the builtin :mod:`hashlib` implementations of + SHA1, SHA3, SHA2-384, SHA2-512, and MD5 with formally verified code from the + `HACL* `__ project. + These builtin implementations remain as fallbacks that are only used when + OpenSSL does not provide them. + +C API improvements: -* :pep:`688`: Making the buffer protocol accessible in Python +* :ref:`PEP 697 `, unstable C API tier +* :ref:`PEP 683 `, immortal objects -* :ref:`whatsnew312-pep692` +CPython implementation improvements: -* :ref:`whatsnew312-pep695` +* :ref:`PEP 709 `, comprehension inlining +* :ref:`CPython support ` for the Linux ``perf`` profiler +* Implement stack overflow protection on supported platforms -* :pep:`698`: Override Decorator for Static Typing +New typing features: + +* :ref:`PEP 692 `, using :class:`~typing.TypedDict` to + annotate :term:`**kwargs ` +* :ref:`PEP 698 `, :func:`typing.override` decorator Important deprecations, removals or restrictions: -* :pep:`623`: Remove wstr from Unicode +* :pep:`623`: Remove ``wstr`` from Unicode objects in Python's C API, + reducing the size of every :class:`str` object by at least 8 bytes. -* :pep:`632`: Remove the ``distutils`` package. See - `the migration guide `_ - for advice on its replacement. +* :pep:`632`: Remove the :mod:`!distutils` package. + See `the migration guide `_ + for advice replacing the APIs it provided. + The third-party `Setuptools `__ + package continues to provide :mod:`!distutils`, + if you still require it in Python 3.12 and beyond. -Improved Error Messages -======================= +* :gh:`95299`: Do not pre-install ``setuptools`` in virtual environments + created with :mod:`venv`. + This means that ``distutils``, ``setuptools``, ``pkg_resources``, + and ``easy_install`` will no longer available by default; to access these + run ``pip install setuptools`` in the :ref:`activated ` + virtual environment. -* Modules from the standard library are now potentially suggested as part of - the error messages displayed by the interpreter when a :exc:`NameError` is - raised to the top level. Contributed by Pablo Galindo in :gh:`98254`. +* The :mod:`!asynchat`, :mod:`!asyncore`, and :mod:`!imp` modules have been + removed, along with several :class:`unittest.TestCase` + `method aliases `_. - >>> sys.version_info - Traceback (most recent call last): - File "", line 1, in - NameError: name 'sys' is not defined. Did you forget to import 'sys'? -* Improve the error suggestion for :exc:`NameError` exceptions for instances. - Now if a :exc:`NameError` is raised in a method and the instance has an - attribute that's exactly equal to the name in the exception, the suggestion - will include ``self.`` instead of the closest match in the method - scope. Contributed by Pablo Galindo in :gh:`99139`. +New Features +============ - >>> class A: - ... def __init__(self): - ... self.blech = 1 - ... - ... def foo(self): - ... somethin = blech +.. _whatsnew312-pep695: - >>> A().foo() - Traceback (most recent call last): - File "", line 1 - somethin = blech - ^^^^^ - NameError: name 'blech' is not defined. Did you mean: 'self.blech'? +PEP 695: Type Parameter Syntax +------------------------------ + +Generic classes and functions under :pep:`484` were declared using a verbose syntax +that left the scope of type parameters unclear and required explicit declarations of +variance. +:pep:`695` introduces a new, more compact and explicit way to create +:ref:`generic classes ` and :ref:`functions `:: -* Improve the :exc:`SyntaxError` error message when the user types ``import x - from y`` instead of ``from y import x``. Contributed by Pablo Galindo in :gh:`98931`. + def max[T](args: Iterable[T]) -> T: + ... - >>> import a.y.z from b.y.z - Traceback (most recent call last): - File "", line 1 - import a.y.z from b.y.z - ^^^^^^^^^^^^^^^^^^^^^^^ - SyntaxError: Did you mean to use 'from ... import ...' instead? + class list[T]: + def __getitem__(self, index: int, /) -> T: + ... -* :exc:`ImportError` exceptions raised from failed ``from import - `` statements now include suggestions for the value of ```` based on the - available names in ````. Contributed by Pablo Galindo in :gh:`91058`. + def append(self, element: T) -> None: + ... - >>> from collections import chainmap - Traceback (most recent call last): - File "", line 1, in - ImportError: cannot import name 'chainmap' from 'collections'. Did you mean: 'ChainMap'? +In addition, the PEP introduces a new way to declare :ref:`type aliases ` +using the :keyword:`type` statement, which creates an instance of +:class:`~typing.TypeAliasType`:: + type Point = tuple[float, float] -New Features -============ +Type aliases can also be :ref:`generic `:: + + type Point[T] = tuple[T, T] + +The new syntax allows declaring :class:`~typing.TypeVarTuple` +and :class:`~typing.ParamSpec` parameters, as well as :class:`~typing.TypeVar` +parameters with bounds or constraints:: + + type IntFunc[**P] = Callable[P, int] # ParamSpec + type LabeledTuple[*Ts] = tuple[str, *Ts] # TypeVarTuple + type HashableSequence[T: Hashable] = Sequence[T] # TypeVar with bound + type IntOrStrSequence[T: (int, str)] = Sequence[T] # TypeVar with constraints + +The value of type aliases and the bound and constraints of type variables +created through this syntax are evaluated only on demand (see +:ref:`lazy evaluation `). This means type aliases are able to +refer to other types defined later in the file. + +Type parameters declared through a type parameter list are visible within the +scope of the declaration and any nested scopes, but not in the outer scope. For +example, they can be used in the type annotations for the methods of a generic +class or in the class body. However, they cannot be used in the module scope after +the class is defined. See :ref:`type-params` for a detailed description of the +runtime semantics of type parameters. + +In order to support these scoping semantics, a new kind of scope is introduced, +the :ref:`annotation scope `. Annotation scopes behave for the +most part like function scopes, but interact differently with enclosing class scopes. +In Python 3.13, :term:`annotations ` will also be evaluated in +annotation scopes. + +See :pep:`695` for more details. + +(PEP written by Eric Traut. Implementation by Jelle Zijlstra, Eric Traut, +and others in :gh:`103764`.) .. _whatsnew312-pep701: PEP 701: Syntactic formalization of f-strings --------------------------------------------- -:pep:`701` lifts some restrictions on the usage of f-strings. Expression components -inside f-strings can now be any valid Python expression including backslashes, -unicode escaped sequences, multi-line expressions, comments and strings reusing the -same quote as the containing f-string. Let's cover these in detail: +:pep:`701` lifts some restrictions on the usage of :term:`f-strings `. +Expression components inside f-strings can now be any valid Python expression, +including strings reusing the same quote as the containing f-string, +multi-line expressions, comments, backslashes, and unicode escape sequences. +Let's cover these in detail: -* Quote reuse: in Python 3.11, reusing the same quotes as the containing f-string +* Quote reuse: in Python 3.11, reusing the same quotes as the enclosing f-string raises a :exc:`SyntaxError`, forcing the user to either use other available quotes (like using double quotes or triple quotes if the f-string uses single quotes). In Python 3.12, you can now do things like this: @@ -180,11 +273,12 @@ same quote as the containing f-string. Let's cover these in detail: >>> f"{f"{f"{f"{f"{f"{1+1}"}"}"}"}"}" '2' -* Multi-line expressions and comments: In Python 3.11, f-strings expressions - must be defined in a single line even if outside f-strings expressions could - span multiple lines (like literal lists being defined over multiple lines), - making them harder to read. In Python 3.12 you can now define expressions - spanning multiple lines and include comments on them: +* Multi-line expressions and comments: In Python 3.11, f-string expressions + must be defined in a single line, even if the expression within the f-string + could normally span multiple lines + (like literal lists being defined over multiple lines), + making them harder to read. In Python 3.12 you can now define f-strings + spanning multiple lines, and add inline comments: >>> f"This is the playlist: {", ".join([ ... 'Take me back to Eden', # My, my, those eyes like fire @@ -194,10 +288,10 @@ same quote as the containing f-string. Let's cover these in detail: 'This is the playlist: Take me back to Eden, Alkaline, Ascensionism' * Backslashes and unicode characters: before Python 3.12 f-string expressions - couldn't contain any ``\`` character. This also affected unicode escaped - sequences (such as ``\N{snowman}``) as these contain the ``\N`` part that - previously could not be part of expression components of f-strings. Now, you - can define expressions like this: + couldn't contain any ``\`` character. This also affected unicode :ref:`escape + sequences ` (such as ``\N{snowman}``) as these contain + the ``\N`` part that previously could not be part of expression components of + f-strings. Now, you can define expressions like this: >>> print(f"This is the playlist: {"\n".join(songs)}") This is the playlist: Take me back to Eden @@ -209,7 +303,7 @@ same quote as the containing f-string. Let's cover these in detail: See :pep:`701` for more details. As a positive side-effect of how this feature has been implemented (by parsing f-strings -with the PEG parser (see :pep:`617`), now error messages for f-strings are more precise +with :pep:`the PEG parser <617>`), now error messages for f-strings are more precise and include the exact location of the error. For example, in Python 3.11, the following f-string raises a :exc:`SyntaxError`: @@ -237,6 +331,68 @@ are parsed with the PEG parser, error messages can be more precise and show the Maureira-Fredes and Marta Gómez in :gh:`102856`. PEP written by Pablo Galindo, Batuhan Taskaya, Lysandros Nikolaou and Marta Gómez). +.. _whatsnew312-pep684: + +PEP 684: A Per-Interpreter GIL +------------------------------ + +:pep:`684` introduces a per-interpreter :term:`GIL `, +so that sub-interpreters may now be created with a unique GIL per interpreter. +This allows Python programs to take full advantage of multiple CPU +cores. This is currently only available through the C-API, +though a Python API is :pep:`anticipated for 3.13 <554>`. + +Use the new :c:func:`Py_NewInterpreterFromConfig` function to +create an interpreter with its own GIL: + +.. code-block:: c + + PyInterpreterConfig config = { + .check_multi_interp_extensions = 1, + .gil = PyInterpreterConfig_OWN_GIL, + }; + PyThreadState *tstate = NULL; + PyStatus status = Py_NewInterpreterFromConfig(&tstate, &config); + if (PyStatus_Exception(status)) { + return -1; + } + /* The new interpreter is now active in the current thread. */ + +For further examples how to use the C-API for sub-interpreters with a +per-interpreter GIL, see :source:`Modules/_xxsubinterpretersmodule.c`. + +(Contributed by Eric Snow in :gh:`104210`, etc.) + +.. _whatsnew312-pep669: + +PEP 669: Low impact monitoring for CPython +------------------------------------------ + +:pep:`669` defines a new :mod:`API ` for profilers, +debuggers, and other tools to monitor events in CPython. +It covers a wide range of events, including calls, +returns, lines, exceptions, jumps, and more. +This means that you only pay for what you use, providing support +for near-zero overhead debuggers and coverage tools. +See :mod:`sys.monitoring` for details. + +(Contributed by Mark Shannon in :gh:`103082`.) + +.. _whatsnew312-pep688: + +PEP 688: Making the buffer protocol accessible in Python +-------------------------------------------------------- + +:pep:`688` introduces a way to use the :ref:`buffer protocol ` +from Python code. Classes that implement the :meth:`~object.__buffer__` method +are now usable as buffer types. + +The new :class:`collections.abc.Buffer` ABC provides a standard +way to represent buffer objects, for example in type annotations. +The new :class:`inspect.BufferFlags` enum represents the flags that +can be used to customize buffer creation. +(Contributed by Jelle Zijlstra in :gh:`102500`.) + .. _whatsnew312-pep709: PEP 709: Comprehension inlining @@ -244,17 +400,18 @@ PEP 709: Comprehension inlining Dictionary, list, and set comprehensions are now inlined, rather than creating a new single-use function object for each execution of the comprehension. This -speeds up execution of a comprehension by up to 2x. +speeds up execution of a comprehension by up to two times. +See :pep:`709` for further details. -Comprehension iteration variables remain isolated; they don't overwrite a +Comprehension iteration variables remain isolated and don't overwrite a variable of the same name in the outer scope, nor are they visible after the -comprehension. This isolation is now maintained via stack/locals manipulation, -not via separate function scope. - -Inlining does result in a few visible behavior changes: +comprehension. Inlining does result in a few visible behavior changes: * There is no longer a separate frame for the comprehension in tracebacks, and tracing/profiling no longer shows the comprehension as a function call. +* The :mod:`symtable` module will no longer produce child symbol tables for each + comprehension; instead, the comprehension's locals will be included in the + parent function's symbol table. * Calling :func:`locals` inside a comprehension now includes variables from outside the comprehension, and no longer includes the synthetic ``.0`` variable for the comprehension "argument". @@ -265,55 +422,64 @@ Inlining does result in a few visible behavior changes: create a list of keys to iterate over: ``keys = list(locals()); [k for k in keys]``. -Contributed by Carl Meyer and Vladimir Matveev in :pep:`709`. +(Contributed by Carl Meyer and Vladimir Matveev in :pep:`709`.) -PEP 688: Making the buffer protocol accessible in Python --------------------------------------------------------- - -:pep:`688` introduces a way to use the :ref:`buffer protocol ` -from Python code. Classes that implement the :meth:`~object.__buffer__` method -are now usable as buffer types. +Improved Error Messages +----------------------- -The new :class:`collections.abc.Buffer` ABC provides a standard -way to represent buffer objects, for example in type annotations. -The new :class:`inspect.BufferFlags` enum represents the flags that -can be used to customize buffer creation. -(Contributed by Jelle Zijlstra in :gh:`102500`.) +* Modules from the standard library are now potentially suggested as part of + the error messages displayed by the interpreter when a :exc:`NameError` is + raised to the top level. (Contributed by Pablo Galindo in :gh:`98254`.) -.. _whatsnew312-pep684: + >>> sys.version_info + Traceback (most recent call last): + File "", line 1, in + NameError: name 'sys' is not defined. Did you forget to import 'sys'? -PEP 684: A Per-Interpreter GIL ------------------------------- +* Improve the error suggestion for :exc:`NameError` exceptions for instances. + Now if a :exc:`NameError` is raised in a method and the instance has an + attribute that's exactly equal to the name in the exception, the suggestion + will include ``self.`` instead of the closest match in the method + scope. (Contributed by Pablo Galindo in :gh:`99139`.) -Sub-interpreters may now be created with a unique GIL per interpreter. -This allows Python programs to take full advantage of multiple CPU -cores. + >>> class A: + ... def __init__(self): + ... self.blech = 1 + ... + ... def foo(self): + ... somethin = blech + ... + >>> A().foo() + Traceback (most recent call last): + File "", line 1 + somethin = blech + ^^^^^ + NameError: name 'blech' is not defined. Did you mean: 'self.blech'? -Use the new :c:func:`Py_NewInterpreterFromConfig` function to -create an interpreter with its own GIL:: +* Improve the :exc:`SyntaxError` error message when the user types ``import x + from y`` instead of ``from y import x``. (Contributed by Pablo Galindo in :gh:`98931`.) - PyInterpreterConfig config = { - .check_multi_interp_extensions = 1, - .gil = PyInterpreterConfig_OWN_GIL, - }; - PyThreadState *tstate = NULL; - PyStatus status = Py_NewInterpreterFromConfig(&tstate, &config); - if (PyStatus_Exception(status)) { - return -1; - } - /* The new interpeter is now active in the current thread. */ + >>> import a.y.z from b.y.z + Traceback (most recent call last): + File "", line 1 + import a.y.z from b.y.z + ^^^^^^^^^^^^^^^^^^^^^^^ + SyntaxError: Did you mean to use 'from ... import ...' instead? -For further examples how to use the C-API for sub-interpreters with a -per-interpreter GIL, see :source:`Modules/_xxsubinterpretersmodule.c`. +* :exc:`ImportError` exceptions raised from failed ``from import + `` statements now include suggestions for the value of ```` based on the + available names in ````. (Contributed by Pablo Galindo in :gh:`91058`.) -A Python API is anticipated for 3.13. (See :pep:`554`.) + >>> from collections import chainmap + Traceback (most recent call last): + File "", line 1, in + ImportError: cannot import name 'chainmap' from 'collections'. Did you mean: 'ChainMap'? -(Contributed by Eric Snow in :gh:`104210`, etc.) New Features Related to Type Hints ================================== -This section covers major changes affecting :pep:`484` type hints and +This section covers major changes affecting :pep:`type hints <484>` and the :mod:`typing` module. .. _whatsnew312-pep692: @@ -325,7 +491,7 @@ Typing ``**kwargs`` in a function signature as introduced by :pep:`484` allowed for valid annotations only in cases where all of the ``**kwargs`` were of the same type. -This PEP specifies a more precise way of typing ``**kwargs`` by relying on +:pep:`692` specifies a more precise way of typing ``**kwargs`` by relying on typed dictionaries:: from typing import TypedDict, Unpack @@ -340,6 +506,8 @@ See :pep:`692` for more details. (Contributed by Franek Magiera in :gh:`103629`.) +.. _whatsnew312-pep698: + PEP 698: Override Decorator for Static Typing --------------------------------------------- @@ -367,119 +535,21 @@ Example:: def get_colour(self) -> str: return "red" -(Contributed by Steven Troxler in :gh:`101561`.) - -.. _whatsnew312-pep695: - -PEP 695: Type Parameter Syntax ------------------------------- - -Generic classes and functions under :pep:`484` were declared using a verbose syntax -that left the scope of type parameters unclear and required explicit declarations of -variance. - -:pep:`695` introduces a new, more compact and explicit way to create -:ref:`generic classes ` and :ref:`functions `:: - - def max[T](args: Iterable[T]) -> T: - ... - - class list[T]: - def __getitem__(self, index: int, /) -> T: - ... +See :pep:`698` for more details. - def append(self, element: T) -> None: - ... - -In addition, the PEP introduces a new way to declare :ref:`type aliases ` -using the :keyword:`type` statement, which creates an instance of -:class:`~typing.TypeAliasType`:: - - type Point = tuple[float, float] - -Type aliases can also be :ref:`generic `:: - - type Point[T] = tuple[T, T] - -The new syntax allows declaring :class:`~typing.TypeVarTuple` -and :class:`~typing.ParamSpec` parameters, as well as :class:`~typing.TypeVar` -parameters with bounds or constraints:: - - type IntFunc[**P] = Callable[P, int] # ParamSpec - type LabeledTuple[*Ts] = tuple[str, *Ts] # TypeVarTuple - type HashableSequence[T: Hashable] = Sequence[T] # TypeVar with bound - type IntOrStrSequence[T: (int, str)] = Sequence[T] # TypeVar with constraints - -The value of type aliases and the bound and constraints of type variables -created through this syntax are evaluated only on demand (see -:ref:`lazy-evaluation`). This means type aliases are able to refer to other -types defined later in the file. - -Type parameters declared through a type parameter list are visible within the -scope of the declaration and any nested scopes, but not in the outer scope. For -example, they can be used in the type annotations for the methods of a generic -class or in the class body. However, they cannot be used in the module scope after -the class is defined. See :ref:`type-params` for a detailed description of the -runtime semantics of type parameters. - -In order to support these scoping semantics, a new kind of scope is introduced, -the :ref:`annotation scope `. Annotation scopes behave for the -most part like function scopes, but interact differently with enclosing class scopes. -In Python 3.13, :term:`annotations ` will also be evaluated in -annotation scopes. - -See :pep:`695` for more details. - -(PEP written by Eric Traut. Implementation by Jelle Zijlstra, Eric Traut, -and others in :gh:`103764`.) +(Contributed by Steven Troxler in :gh:`101561`.) Other Language Changes ====================== -* Add :ref:`perf_profiling` through the new - environment variable :envvar:`PYTHONPERFSUPPORT`, - the new command-line option :option:`-X perf <-X>`, - as well as the new :func:`sys.activate_stack_trampoline`, - :func:`sys.deactivate_stack_trampoline`, - and :func:`sys.is_stack_trampoline_active` APIs. - (Design by Pablo Galindo. Contributed by Pablo Galindo and Christian Heimes - with contributions from Gregory P. Smith [Google] and Mark Shannon - in :gh:`96123`.) - -* The extraction methods in :mod:`tarfile`, and :func:`shutil.unpack_archive`, - have a new a *filter* argument that allows limiting tar features than may be - surprising or dangerous, such as creating files outside the destination - directory. - See :ref:`tarfile-extraction-filter` for details. - In Python 3.14, the default will switch to ``'data'``. - (Contributed by Petr Viktorin in :pep:`706`.) - -* :class:`types.MappingProxyType` instances are now hashable if the underlying - mapping is hashable. - (Contributed by Serhiy Storchaka in :gh:`87995`.) - -* :class:`memoryview` now supports the half-float type (the "e" format code). - (Contributed by Dong-hee Na and Antoine Pitrou in :gh:`90751`.) - * The parser now raises :exc:`SyntaxError` when parsing source code containing null bytes. (Contributed by Pablo Galindo in :gh:`96670`.) -* :func:`ast.parse` now raises :exc:`SyntaxError` instead of :exc:`ValueError` - when parsing source code containing null bytes. (Contributed by Pablo Galindo - in :gh:`96670`.) - -* The Garbage Collector now runs only on the eval breaker mechanism of the - Python bytecode evaluation loop instead of object allocations. The GC can - also run when :c:func:`PyErr_CheckSignals` is called so C extensions that - need to run for a long time without executing any Python code also have a - chance to execute the GC periodically. (Contributed by Pablo Galindo in - :gh:`97922`.) - * A backslash-character pair that is not a valid escape sequence now generates a :exc:`SyntaxWarning`, instead of :exc:`DeprecationWarning`. For example, ``re.compile("\d+\.\d+")`` now emits a :exc:`SyntaxWarning` - (``"\d"`` is an invalid escape sequence), use raw strings for regular - expression: ``re.compile(r"\d+\.\d+")``. + (``"\d"`` is an invalid escape sequence, use raw strings for regular + expression: ``re.compile(r"\d+\.\d+")``). In a future Python version, :exc:`SyntaxError` will eventually be raised, instead of :exc:`SyntaxWarning`. (Contributed by Victor Stinner in :gh:`98401`.) @@ -490,10 +560,6 @@ Other Language Changes In a future Python version they will be eventually a :exc:`SyntaxError`. (Contributed by Victor Stinner in :gh:`98401`.) -* All builtin and extension callables expecting boolean parameters now accept - arguments of any type instead of just :class:`bool` and :class:`int`. - (Contributed by Serhiy Storchaka in :gh:`60203`.) - * Variables used in the target part of comprehensions that are not stored to can now be used in assignment expressions (``:=``). For example, in ``[(b := 1) for a, b.prop in some_iter]``, the assignment to @@ -501,21 +567,61 @@ Other Language Changes part of comprehensions (like ``a``) is still disallowed, as per :pep:`572`. (Contributed by Nikita Sobolev in :gh:`100581`.) +* Exceptions raised in a class or type's ``__set_name__`` method are no longer + wrapped by a :exc:`RuntimeError`. Context information is added to the + exception as a :pep:`678` note. (Contributed by Irit Katriel in :gh:`77757`.) + +* When a ``try-except*`` construct handles the entire :exc:`ExceptionGroup` + and raises one other exception, that exception is no longer wrapped in an + :exc:`ExceptionGroup`. Also changed in version 3.11.4. (Contributed by Irit + Katriel in :gh:`103590`.) + +* The Garbage Collector now runs only on the eval breaker mechanism of the + Python bytecode evaluation loop instead of object allocations. The GC can + also run when :c:func:`PyErr_CheckSignals` is called so C extensions that + need to run for a long time without executing any Python code also have a + chance to execute the GC periodically. (Contributed by Pablo Galindo in + :gh:`97922`.) + +* All builtin and extension callables expecting boolean parameters now accept + arguments of any type instead of just :class:`bool` and :class:`int`. + (Contributed by Serhiy Storchaka in :gh:`60203`.) + +* :class:`memoryview` now supports the half-float type (the "e" format code). + (Contributed by Donghee Na and Antoine Pitrou in :gh:`90751`.) + * :class:`slice` objects are now hashable, allowing them to be used as dict keys and set items. (Contributed by Will Bradshaw, Furkan Onder, and Raymond Hettinger in :gh:`101264`.) -* :func:`sum` now uses Neumaier summation to improve accuracy when summing - floats or mixed ints and floats. +* :func:`sum` now uses Neumaier summation to improve accuracy and commutativity + when summing floats or mixed ints and floats. (Contributed by Raymond Hettinger in :gh:`100425`.) -* Exceptions raised in a typeobject's ``__set_name__`` method are no longer - wrapped by a :exc:`RuntimeError`. Context information is added to the - exception as a :pep:`678` note. (Contributed by Irit Katriel in :gh:`77757`.) +* :func:`ast.parse` now raises :exc:`SyntaxError` instead of :exc:`ValueError` + when parsing source code containing null bytes. (Contributed by Pablo Galindo + in :gh:`96670`.) + +* The extraction methods in :mod:`tarfile`, and :func:`shutil.unpack_archive`, + have a new a *filter* argument that allows limiting tar features than may be + surprising or dangerous, such as creating files outside the destination + directory. + See :ref:`tarfile extraction filters ` for details. + In Python 3.14, the default will switch to ``'data'``. + (Contributed by Petr Viktorin in :pep:`706`.) + +* :class:`types.MappingProxyType` instances are now hashable if the underlying + mapping is hashable. + (Contributed by Serhiy Storchaka in :gh:`87995`.) -* When a ``try-except*`` construct handles the entire :exc:`ExceptionGroup` - and raises one other exception, that exception is no longer wrapped in an - :exc:`ExceptionGroup`. Also changed in version 3.11.4. (Contributed by Irit - Katriel in :gh:`103590`.) +* Add :ref:`support for the perf profiler ` through the new + environment variable :envvar:`PYTHONPERFSUPPORT` + and command-line option :option:`-X perf <-X>`, + as well as the new :func:`sys.activate_stack_trampoline`, + :func:`sys.deactivate_stack_trampoline`, + and :func:`sys.is_stack_trampoline_active` functions. + (Design by Pablo Galindo. Contributed by Pablo Galindo and Christian Heimes + with contributions from Gregory P. Smith [Google] and Mark Shannon + in :gh:`96123`.) New Modules @@ -541,29 +647,20 @@ asyncio writing to sockets and uses :meth:`~socket.socket.sendmsg` if the platform supports it. (Contributed by Kumar Aditya in :gh:`91166`.) -* Added :func:`asyncio.eager_task_factory` and :func:`asyncio.create_eager_task_factory` +* Add :func:`asyncio.eager_task_factory` and :func:`asyncio.create_eager_task_factory` functions to allow opting an event loop in to eager task execution, making some use-cases 2x to 5x faster. - (Contributed by Jacob Bower & Itamar O in :gh:`102853`, :gh:`104140`, and :gh:`104138`) + (Contributed by Jacob Bower & Itamar Oren in :gh:`102853`, :gh:`104140`, and :gh:`104138`) -* On Linux, :mod:`asyncio` uses :class:`~asyncio.PidfdChildWatcher` by default +* On Linux, :mod:`asyncio` uses :class:`asyncio.PidfdChildWatcher` by default if :func:`os.pidfd_open` is available and functional instead of - :class:`~asyncio.ThreadedChildWatcher`. + :class:`asyncio.ThreadedChildWatcher`. (Contributed by Kumar Aditya in :gh:`98024`.) -* The child watcher classes :class:`~asyncio.MultiLoopChildWatcher`, - :class:`~asyncio.FastChildWatcher`, :class:`~asyncio.AbstractChildWatcher` - and :class:`~asyncio.SafeChildWatcher` are deprecated and - will be removed in Python 3.14. It is recommended to not manually - configure a child watcher as the event loop now uses the best available - child watcher for each platform (:class:`~asyncio.PidfdChildWatcher` - if supported and :class:`~asyncio.ThreadedChildWatcher` otherwise). - (Contributed by Kumar Aditya in :gh:`94597`.) - -* :func:`asyncio.set_child_watcher`, :func:`asyncio.get_child_watcher`, - :meth:`asyncio.AbstractEventLoopPolicy.set_child_watcher` and - :meth:`asyncio.AbstractEventLoopPolicy.get_child_watcher` are deprecated - and will be removed in Python 3.14. +* The event loop now uses the best available child watcher for each platform + (:class:`asyncio.PidfdChildWatcher` if supported and + :class:`asyncio.ThreadedChildWatcher` otherwise), so manually + configuring a child watcher is not recommended. (Contributed by Kumar Aditya in :gh:`94597`.) * Add *loop_factory* parameter to :func:`asyncio.run` to allow specifying @@ -571,7 +668,7 @@ asyncio (Contributed by Kumar Aditya in :gh:`99388`.) * Add C implementation of :func:`asyncio.current_task` for 4x-6x speedup. - (Contributed by Itamar Ostricher and Pranav Thulasiram Bhat in :gh:`100344`.) + (Contributed by Itamar Oren and Pranav Thulasiram Bhat in :gh:`100344`.) * :func:`asyncio.iscoroutine` now returns ``False`` for generators as :mod:`asyncio` does not support legacy generator-based coroutines. @@ -584,15 +681,16 @@ asyncio calendar -------- -* Add enums :data:`~calendar.Month` and :data:`~calendar.Day`. +* Add enums :data:`calendar.Month` and :data:`calendar.Day` + defining months of the year and days of the week. (Contributed by Prince Roshan in :gh:`103636`.) csv --- -* Add :const:`~csv.QUOTE_NOTNULL` and :const:`~csv.QUOTE_STRINGS` flags to +* Add :const:`csv.QUOTE_NOTNULL` and :const:`csv.QUOTE_STRINGS` flags to provide finer grained control of ``None`` and empty strings by - :class:`~csv.writer` objects. + :class:`csv.writer` objects. dis --- @@ -602,15 +700,27 @@ dis :mod:`dis` module. :opcode:`HAVE_ARGUMENT` is still relevant to real opcodes, but it is not useful for pseudo instructions. Use the new - :data:`~dis.hasarg` collection instead. + :data:`dis.hasarg` collection instead. (Contributed by Irit Katriel in :gh:`94216`.) +* Add the :data:`dis.hasexc` collection to signify instructions that set + an exception handler. (Contributed by Irit Katriel in :gh:`94216`.) + fractions --------- * Objects of type :class:`fractions.Fraction` now support float-style formatting. (Contributed by Mark Dickinson in :gh:`100161`.) +importlib.resources +------------------- + +* :func:`importlib.resources.as_file` now supports resource directories. + (Contributed by Jason R. Coombs in :gh:`97930`.) + +* Rename first parameter of :func:`importlib.resources.files` to *anchor*. + (Contributed by Jason R. Coombs in :gh:`100598`.) + inspect ------- @@ -620,7 +730,7 @@ inspect * Add :func:`inspect.getasyncgenstate` and :func:`inspect.getasyncgenlocals` for determining the current state of asynchronous generators. - (Contributed by Thomas Krennwallner in :issue:`35759`.) + (Contributed by Thomas Krennwallner in :gh:`79940`.) * The performance of :func:`inspect.getattr_static` has been considerably improved. Most calls to the function should be at least 2x faster than they @@ -630,17 +740,17 @@ inspect itertools --------- -* Added :class:`itertools.batched()` for collecting into even-sized +* Add :class:`itertools.batched()` for collecting into even-sized tuples where the last batch may be shorter than the rest. (Contributed by Raymond Hettinger in :gh:`98363`.) math ---- -* Added :func:`math.sumprod` for computing a sum of products. +* Add :func:`math.sumprod` for computing a sum of products. (Contributed by Raymond Hettinger in :gh:`100485`.) -* Extended :func:`math.nextafter` to include a *steps* argument +* Extend :func:`math.nextafter` to include a *steps* argument for moving up or down multiple steps at a time. (By Matthias Goergens, Mark Dickinson, and Raymond Hettinger in :gh:`94906`.) @@ -682,18 +792,18 @@ pathlib ------- * Add support for subclassing :class:`pathlib.PurePath` and - :class:`~pathlib.Path`, plus their Posix- and Windows-specific variants. - Subclasses may override the :meth:`~pathlib.PurePath.with_segments` method + :class:`pathlib.Path`, plus their Posix- and Windows-specific variants. + Subclasses may override the :meth:`pathlib.PurePath.with_segments` method to pass information between path instances. -* Add :meth:`~pathlib.Path.walk` for walking the directory trees and generating +* Add :meth:`pathlib.Path.walk` for walking the directory trees and generating all file or directory names within them, similar to :func:`os.walk`. (Contributed by Stanislav Zmiev in :gh:`90385`.) * Add *walk_up* optional parameter to :meth:`pathlib.PurePath.relative_to` to allow the insertion of ``..`` entries in the result; this behavior is more consistent with :func:`os.path.relpath`. - (Contributed by Domenico Ragusa in :issue:`40358`.) + (Contributed by Domenico Ragusa in :gh:`84538`.) * Add :meth:`pathlib.Path.is_junction` as a proxy to :func:`os.path.isjunction`. (Contributed by Charles Machalow in :gh:`99547`.) @@ -713,10 +823,10 @@ pdb random ------ -* Added :func:`random.binomialvariate`. +* Add :func:`random.binomialvariate`. (Contributed by Raymond Hettinger in :gh:`81620`.) -* Added a default of ``lamb=1.0`` to :func:`random.expovariate`. +* Add a default of ``lambd=1.0`` to :func:`random.expovariate`. (Contributed by Raymond Hettinger in :gh:`100234`.) shutil @@ -730,8 +840,7 @@ shutil * :func:`shutil.rmtree` now accepts a new argument *onexc* which is an error handler like *onerror* but which expects an exception instance - rather than a *(typ, val, tb)* triplet. *onerror* is deprecated and - will be removed in Python 3.14. + rather than a *(typ, val, tb)* triplet. *onerror* is deprecated. (Contributed by Irit Katriel in :gh:`102828`.) * :func:`shutil.which` now consults the *PATHEXT* environment variable to @@ -755,33 +864,37 @@ sqlite3 * Add a :ref:`command-line interface `. (Contributed by Erlend E. Aasland in :gh:`77617`.) -* Add the :attr:`~sqlite3.Connection.autocommit` attribute - to :class:`~sqlite3.Connection` - and the *autocommit* parameter to :func:`~sqlite3.connect` +* Add the :attr:`sqlite3.Connection.autocommit` attribute + to :class:`sqlite3.Connection` + and the *autocommit* parameter to :func:`sqlite3.connect` to control :pep:`249`-compliant :ref:`transaction handling `. (Contributed by Erlend E. Aasland in :gh:`83638`.) * Add *entrypoint* keyword-only parameter to - :meth:`~sqlite3.Connection.load_extension`, + :meth:`sqlite3.Connection.load_extension`, for overriding the SQLite extension entry point. (Contributed by Erlend E. Aasland in :gh:`103015`.) -* Add :meth:`~sqlite3.Connection.getconfig` and - :meth:`~sqlite3.Connection.setconfig` to :class:`~sqlite3.Connection` +* Add :meth:`sqlite3.Connection.getconfig` and + :meth:`sqlite3.Connection.setconfig` to :class:`sqlite3.Connection` to make configuration changes to a database connection. (Contributed by Erlend E. Aasland in :gh:`103489`.) statistics ---------- -* Extended :func:`statistics.correlation` to include as a ``ranked`` method +* Extend :func:`statistics.correlation` to include as a ``ranked`` method for computing the Spearman correlation of ranked data. (Contributed by Raymond Hettinger in :gh:`95861`.) sys --- +* Add the :mod:`sys.monitoring` namespace to expose the new :ref:`PEP 669 + ` monitoring API. + (Contributed by Mark Shannon in :gh:`103082`.) + * Add :func:`sys.activate_stack_trampoline` and :func:`sys.deactivate_stack_trampoline` for activating and deactivating stack profiler trampolines, @@ -838,8 +951,8 @@ tkinter tokenize -------- -* The :mod:`tokenize` module includes the changes introduced in :pep:`701`. ( - Contributed by Marta Gómez Macías and Pablo Galindo in :gh:`102856`.) +* The :mod:`tokenize` module includes the changes introduced in :pep:`701`. + (Contributed by Marta Gómez Macías and Pablo Galindo in :gh:`102856`.) See :ref:`whatsnew312-porting-to-python312` for more information on the changes to the :mod:`tokenize` module. @@ -913,7 +1026,7 @@ unicodedata unittest -------- -Added ``--durations`` command line option, showing the N slowest test cases:: +Add a ``--durations`` command line option, showing the N slowest test cases:: python3 -m unittest --durations=3 lib.tests.test_threading ..... @@ -929,7 +1042,7 @@ Added ``--durations`` command line option, showing the N slowest test cases:: OK (skipped=3) -(Contributed by Giampaolo Rodola in :issue:`4080`) +(Contributed by Giampaolo Rodola in :gh:`48330`) uuid ---- @@ -941,13 +1054,13 @@ uuid Optimizations ============= -* Removed ``wstr`` and ``wstr_length`` members from Unicode objects. +* Remove ``wstr`` and ``wstr_length`` members from Unicode objects. 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 +* Add 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` and tuned by Dong-hee Na in :gh:`101525`) + (Contributed by Kevin Modzelewski in :gh:`90536` and tuned by Donghee Na in :gh:`101525`) * Speed up the regular expression substitution (functions :func:`re.sub` and :func:`re.subn` and corresponding :class:`!re.Pattern` methods) for @@ -955,7 +1068,7 @@ Optimizations (Contributed by Serhiy Storchaka in :gh:`91524`.) * Speed up :class:`asyncio.Task` creation by deferring expensive string formatting. - (Contributed by Itamar O in :gh:`103793`.) + (Contributed by Itamar Oren in :gh:`103793`.) * The :func:`tokenize.tokenize` and :func:`tokenize.generate_tokens` functions are up to 64% faster as a side effect of the changes required to cover :pep:`701` in @@ -970,17 +1083,38 @@ Optimizations CPython bytecode changes ======================== -* Remove the :opcode:`LOAD_METHOD` instruction. It has been merged into +* Remove the :opcode:`!LOAD_METHOD` instruction. It has been merged into :opcode:`LOAD_ATTR`. :opcode:`LOAD_ATTR` will now behave like the old - :opcode:`LOAD_METHOD` instruction if the low bit of its oparg is set. + :opcode:`!LOAD_METHOD` instruction if the low bit of its oparg is set. (Contributed by Ken Jin in :gh:`93429`.) * Remove the :opcode:`!JUMP_IF_FALSE_OR_POP` and :opcode:`!JUMP_IF_TRUE_OR_POP` instructions. (Contributed by Irit Katriel in :gh:`102859`.) +* Remove the :opcode:`!PRECALL` instruction. (Contributed by Mark Shannon in + :gh:`92925`.) + +* Add the :opcode:`BINARY_SLICE` and :opcode:`STORE_SLICE` instructions. + (Contributed by Mark Shannon in :gh:`94163`.) + +* Add the :opcode:`CALL_INTRINSIC_1` instructions. + (Contributed by Mark Shannon in :gh:`99005`.) + +* Add the :opcode:`CALL_INTRINSIC_2` instruction. + (Contributed by Irit Katriel in :gh:`101799`.) + +* Add the :opcode:`CLEANUP_THROW` instruction. + (Contributed by Brandt Bucher in :gh:`90997`.) + +* Add the :opcode:`!END_SEND` instruction. + (Contributed by Mark Shannon in :gh:`103082`.) + * Add the :opcode:`LOAD_FAST_AND_CLEAR` instruction as part of the implementation of :pep:`709`. (Contributed by Carl Meyer in :gh:`101441`.) +* Add the :opcode:`LOAD_FAST_CHECK` instruction. + (Contributed by Dennis Sweeney in :gh:`93143`.) + * Add the :opcode:`LOAD_FROM_DICT_OR_DEREF`, :opcode:`LOAD_FROM_DICT_OR_GLOBALS`, and :opcode:`LOAD_LOCALS` opcodes as part of the implementation of :pep:`695`. Remove the :opcode:`!LOAD_CLASSDEREF` opcode, which can be replaced with @@ -990,6 +1124,8 @@ CPython bytecode changes * Add the :opcode:`LOAD_SUPER_ATTR` instruction. (Contributed by Carl Meyer and Vladimir Matveev in :gh:`103497`.) +* Add the :opcode:`RETURN_CONST` instruction. (Contributed by Wenyang Wang in :gh:`101632`.) + Demos and Tools =============== @@ -1007,15 +1143,52 @@ Demos and Tools Deprecated ========== -* :mod:`asyncio`: The :meth:`~asyncio.get_event_loop` method of the - default event loop policy now emits a :exc:`DeprecationWarning` if there - is no current event loop set and it decides to create one. - (Contributed by Serhiy Storchaka and Guido van Rossum in :gh:`100160`.) +* :mod:`argparse`: The *type*, *choices*, and *metavar* parameters + of :class:`!argparse.BooleanOptionalAction` are deprecated + and will be removed in 3.14. + (Contributed by Nikita Sobolev in :gh:`92248`.) + +* :mod:`ast`: The following :mod:`ast` features have been deprecated in documentation since + Python 3.8, now cause a :exc:`DeprecationWarning` to be emitted at runtime + when they are accessed or used, and will be removed in Python 3.14: + + * :class:`!ast.Num` + * :class:`!ast.Str` + * :class:`!ast.Bytes` + * :class:`!ast.NameConstant` + * :class:`!ast.Ellipsis` + + Use :class:`ast.Constant` instead. + (Contributed by Serhiy Storchaka in :gh:`90953`.) + +* :mod:`asyncio`: + + * The child watcher classes :class:`asyncio.MultiLoopChildWatcher`, + :class:`asyncio.FastChildWatcher`, :class:`asyncio.AbstractChildWatcher` + and :class:`asyncio.SafeChildWatcher` are deprecated and + will be removed in Python 3.14. + (Contributed by Kumar Aditya in :gh:`94597`.) + + * :func:`asyncio.set_child_watcher`, :func:`asyncio.get_child_watcher`, + :meth:`asyncio.AbstractEventLoopPolicy.set_child_watcher` and + :meth:`asyncio.AbstractEventLoopPolicy.get_child_watcher` are deprecated + and will be removed in Python 3.14. + (Contributed by Kumar Aditya in :gh:`94597`.) + + * The :meth:`~asyncio.get_event_loop` method of the + default event loop policy now emits a :exc:`DeprecationWarning` if there + is no current event loop set and it decides to create one. + (Contributed by Serhiy Storchaka and Guido van Rossum in :gh:`100160`.) * :mod:`calendar`: ``calendar.January`` and ``calendar.February`` constants are deprecated and - replaced by :data:`calendar.Month.JANUARY` and :data:`calendar.Month.FEBRUARY`. + replaced by :data:`calendar.JANUARY` and :data:`calendar.FEBRUARY`. (Contributed by Prince Roshan in :gh:`103636`.) +* :mod:`collections.abc`: Deprecated :class:`collections.abc.ByteString`. + Prefer :class:`Sequence` or :class:`collections.abc.Buffer`. + For use in typing, prefer a union, like ``bytes | bytearray``, or :class:`collections.abc.Buffer`. + (Contributed by Shantanu Jain in :gh:`91896`.) + * :mod:`datetime`: :class:`datetime.datetime`'s :meth:`~datetime.datetime.utcnow` and :meth:`~datetime.datetime.utcfromtimestamp` are deprecated and will be removed in a future version. Instead, use timezone-aware objects to represent @@ -1024,28 +1197,88 @@ Deprecated :const:`datetime.UTC`. (Contributed by Paul Ganssle in :gh:`103857`.) -* :mod:`os`: The ``st_ctime`` fields return by :func:`os.stat` and :func:`os.lstat` on - Windows are deprecated. In a future release, they will contain the last - metadata change time, consistent with other platforms. For now, they still - contain the creation time, which is also available in the new ``st_birthtime`` - field. (Contributed by Steve Dower in :gh:`99726`.) +* :mod:`email`: Deprecate the *isdst* parameter in :func:`email.utils.localtime`. + (Contributed by Alan Williams in :gh:`72346`.) + +* :mod:`importlib.abc`: Deprecated the following classes, scheduled for removal in + Python 3.14: + + * :class:`!importlib.abc.ResourceReader` + * :class:`!importlib.abc.Traversable` + * :class:`!importlib.abc.TraversableResources` + + Use :mod:`importlib.resources.abc` classes instead: + + * :class:`importlib.resources.abc.Traversable` + * :class:`importlib.resources.abc.TraversableResources` + + (Contributed by Jason R. Coombs and Hugo van Kemenade in :gh:`93963`.) + +* :mod:`itertools`: Deprecate the support for copy, deepcopy, and pickle operations, + which is undocumented, inefficient, historically buggy, and inconsistent. + This will be removed in 3.14 for a significant reduction in code + volume and maintenance burden. + (Contributed by Raymond Hettinger in :gh:`101588`.) + +* :mod:`multiprocessing`: In Python 3.14, the default :mod:`multiprocessing` + start method will change to a safer one on Linux, BSDs, + and other non-macOS POSIX platforms where ``'fork'`` is currently + the default (:gh:`84559`). Adding a runtime warning about this was deemed too + disruptive as the majority of code is not expected to care. Use the + :func:`~multiprocessing.get_context` or + :func:`~multiprocessing.set_start_method` APIs to explicitly specify when + your code *requires* ``'fork'``. See :ref:`contexts and start methods + `. + +* :mod:`pkgutil`: :func:`pkgutil.find_loader` and :func:`pkgutil.get_loader` + are deprecated and will be removed in Python 3.14; + use :func:`importlib.util.find_spec` instead. + (Contributed by Nikita Sobolev in :gh:`97850`.) + +* :mod:`pty`: The module has two undocumented ``master_open()`` and ``slave_open()`` + functions that have been deprecated since Python 2 but only gained a + proper :exc:`DeprecationWarning` in 3.12. Remove them in 3.14. + (Contributed by Soumendra Ganguly and Gregory P. Smith in :gh:`85984`.) + +* :mod:`os`: -* :mod:`shutil`: The *onerror* argument of :func:`shutil.rmtree` is deprecated as will be removed - in Python 3.14. Use *onexc* instead. (Contributed by Irit Katriel in :gh:`102828`.) + * The ``st_ctime`` fields return by :func:`os.stat` and :func:`os.lstat` on + Windows are deprecated. In a future release, they will contain the last + metadata change time, consistent with other platforms. For now, they still + contain the creation time, which is also available in the new ``st_birthtime`` + field. (Contributed by Steve Dower in :gh:`99726`.) + + * On POSIX platforms, :func:`os.fork` can now raise a + :exc:`DeprecationWarning` when it can detect being called from a + multithreaded process. There has always been a fundamental incompatibility + with the POSIX platform when doing so. Even if such code *appeared* to work. + We added the warning to to raise awareness as issues encounted by code doing + this are becoming more frequent. See the :func:`os.fork` documentation for + more details along with `this discussion on fork being incompatible with threads + `_ for *why* we're now surfacing this + longstanding platform compatibility problem to developers. + + When this warning appears due to usage of :mod:`multiprocessing` or + :mod:`concurrent.futures` the fix is to use a different + :mod:`multiprocessing` start method such as ``"spawn"`` or ``"forkserver"``. + +* :mod:`shutil`: The *onerror* argument of :func:`shutil.rmtree` is deprecated; + use *onexc* instead. (Contributed by Irit Katriel in :gh:`102828`.) * :mod:`sqlite3`: - * :ref:`default adapters and converters - ` are now deprecated. - Instead, use the :ref:`sqlite3-adapter-converter-recipes` - and tailor them to your needs. - (Contributed by Erlend E. Aasland in :gh:`90016`.) - - * In :meth:`~sqlite3.Cursor.execute`, :exc:`DeprecationWarning` is now emitted - when :ref:`named placeholders ` are used together with - parameters supplied as a :term:`sequence` instead of as a :class:`dict`. - Starting from Python 3.14, using named placeholders with parameters supplied - as a sequence will raise a :exc:`~sqlite3.ProgrammingError`. - (Contributed by Erlend E. Aasland in :gh:`101698`.) + + * :ref:`default adapters and converters + ` are now deprecated. + Instead, use the :ref:`sqlite3-adapter-converter-recipes` + and tailor them to your needs. + (Contributed by Erlend E. Aasland in :gh:`90016`.) + + * In :meth:`~sqlite3.Cursor.execute`, :exc:`DeprecationWarning` is now emitted + when :ref:`named placeholders ` are used together with + parameters supplied as a :term:`sequence` instead of as a :class:`dict`. + Starting from Python 3.14, using named placeholders with parameters supplied + as a sequence will raise a :exc:`~sqlite3.ProgrammingError`. + (Contributed by Erlend E. Aasland in :gh:`101698`.) * :mod:`sys`: The :data:`sys.last_type`, :data:`sys.last_value` and :data:`sys.last_traceback` fields are deprecated. Use :data:`sys.last_exc` instead. @@ -1055,16 +1288,25 @@ Deprecated Python 3.14, when ``'data'`` filter will become the default. See :ref:`tarfile-extraction-filter` for details. -* :mod:`typing`: :class:`typing.Hashable` and :class:`typing.Sized` aliases for :class:`collections.abc.Hashable` - and :class:`collections.abc.Sized`. (:gh:`94309`.) +* :mod:`typing`: + + * :class:`typing.Hashable` and :class:`typing.Sized`, aliases for + :class:`collections.abc.Hashable` and :class:`collections.abc.Sized` respectively, are + deprecated. (:gh:`94309`.) + + * :class:`typing.ByteString`, deprecated since Python 3.9, now causes a + :exc:`DeprecationWarning` to be emitted when it is used. + (Contributed by Alex Waygood in :gh:`91896`.) * :mod:`xml.etree.ElementTree`: The module now emits :exc:`DeprecationWarning` when testing the truth value of an :class:`xml.etree.ElementTree.Element`. Before, the Python implementation emitted :exc:`FutureWarning`, and the C implementation emitted nothing. + (Contributed by Jacob Walls in :gh:`83122`.) -* The 3-arg signatures (type, value, traceback) of :meth:`~coroutine.throw`, - :meth:`~generator.throw` and :meth:`~agen.athrow` are deprecated and +* The 3-arg signatures (type, value, traceback) of :meth:`coroutine throw() + `, :meth:`generator throw() ` and + :meth:`async generator throw() ` are deprecated and may be removed in a future version of Python. Use the single-arg versions of these functions instead. (Contributed by Ofey Chan in :gh:`89874`.) @@ -1073,17 +1315,22 @@ Deprecated :exc:`ImportWarning`). (Contributed by Brett Cannon in :gh:`65961`.) -* In accordance with :pep:`699`, the ``ma_version_tag`` field in :c:type:`PyDictObject` - is deprecated for extension modules. Accessing this field will generate a compiler - warning at compile time. This field will be removed in Python 3.14. - (Contributed by Ramvikrams and Kumar Aditya in :gh:`101193`. PEP by Ken Jin.) +* Setting ``__package__`` or ``__cached__`` on a module is deprecated, + and will cease to be set or taken into consideration by the import system in Python 3.14. + (Contributed by Brett Cannon in :gh:`65961`.) * The bitwise inversion operator (``~``) on bool is deprecated. It will throw an error in Python 3.14. Use ``not`` for logical negation of bools instead. In the rare case that you really need the bitwise inversion of the underlying - ``int``, convert to int explicitly with ``~int(x)``. (Contributed by Tim Hoffmann + ``int``, convert to int explicitly: ``~int(x)``. (Contributed by Tim Hoffmann in :gh:`103487`.) +* Accessing :attr:`~codeobject.co_lnotab` on code objects was deprecated in + Python 3.10 via :pep:`626`, + but it only got a proper :exc:`DeprecationWarning` in 3.12, + therefore it will be removed in 3.14. + (Contributed by Nikita Sobolev in :gh:`101866`.) + Pending Removal in Python 3.13 ------------------------------ @@ -1112,10 +1359,13 @@ Modules (see :pep:`594`): * :mod:`!uu` * :mod:`!xdrlib` +Other modules: + +* :mod:`!lib2to3`, and the :program:`2to3` program (:gh:`84540`) + APIs: * :class:`!configparser.LegacyInterpolation` (:gh:`90765`) -* :func:`locale.getdefaultlocale` (:gh:`90817`) * ``locale.resetlocale()`` (:gh:`90817`) * :meth:`!turtle.RawTurtle.settiltangle` (:gh:`50096`) * :func:`!unittest.findTestCases` (:gh:`50096`) @@ -1128,14 +1378,13 @@ APIs: Pending Removal in Python 3.14 ------------------------------ +The following APIs have been deprecated +and will be removed in Python 3.14. + * :mod:`argparse`: The *type*, *choices*, and *metavar* parameters - of :class:`!argparse.BooleanOptionalAction` are deprecated - and will be removed in 3.14. - (Contributed by Nikita Sobolev in :gh:`92248`.) + of :class:`!argparse.BooleanOptionalAction` -* :mod:`ast`: The following :mod:`ast` features have been deprecated in documentation since - Python 3.8, now cause a :exc:`DeprecationWarning` to be emitted at runtime - when they are accessed or used, and will be removed in Python 3.14: +* :mod:`ast`: * :class:`!ast.Num` * :class:`!ast.Str` @@ -1143,74 +1392,59 @@ Pending Removal in Python 3.14 * :class:`!ast.NameConstant` * :class:`!ast.Ellipsis` - Use :class:`ast.Constant` instead. - (Contributed by Serhiy Storchaka in :gh:`90953`.) +* :mod:`asyncio`: -* :mod:`collections.abc`: Deprecated :class:`collections.abc.ByteString`. - Prefer :class:`Sequence` or :class:`collections.abc.Buffer`. - For use in typing, prefer a union, like ``bytes | bytearray``, or :class:`collections.abc.Buffer`. - (Contributed by Shantanu Jain in :gh:`91896`.) + * :class:`!asyncio.MultiLoopChildWatcher` + * :class:`!asyncio.FastChildWatcher` + * :class:`!asyncio.AbstractChildWatcher` + * :class:`!asyncio.SafeChildWatcher` + * :func:`!asyncio.set_child_watcher` + * :func:`!asyncio.get_child_watcher`, + * :meth:`!asyncio.AbstractEventLoopPolicy.set_child_watcher` + * :meth:`!asyncio.AbstractEventLoopPolicy.get_child_watcher` -* :mod:`email`: Deprecated the *isdst* parameter in :func:`email.utils.localtime`. - (Contributed by Alan Williams in :gh:`72346`.) +* :mod:`collections.abc`: :class:`!collections.abc.ByteString`. -* :mod:`importlib.abc`: Deprecated the following classes, scheduled for removal in - Python 3.14: +* :mod:`email`: the *isdst* parameter in :func:`email.utils.localtime`. + +* :mod:`importlib.abc`: * :class:`!importlib.abc.ResourceReader` * :class:`!importlib.abc.Traversable` * :class:`!importlib.abc.TraversableResources` - Use :mod:`importlib.resources.abc` classes instead: +* :mod:`itertools`: Support for copy, deepcopy, and pickle operations. - * :class:`importlib.resources.abc.Traversable` - * :class:`importlib.resources.abc.TraversableResources` +* :mod:`pkgutil`: - (Contributed by Jason R. Coombs and Hugo van Kemenade in :gh:`93963`.) + * :func:`!pkgutil.find_loader` + * :func:`!pkgutil.get_loader`. -* :mod:`itertools`: The module had undocumented, inefficient, historically buggy, - and inconsistent support for copy, deepcopy, and pickle operations. - This will be removed in 3.14 for a significant reduction in code - volume and maintenance burden. - (Contributed by Raymond Hettinger in :gh:`101588`.) +* :mod:`pty`: -* :mod:`multiprocessing`: The default :mod:`multiprocessing` start method will change to a safer one on - Linux, BSDs, and other non-macOS POSIX platforms where ``'fork'`` is currently - the default (:gh:`84559`). Adding a runtime warning about this was deemed too - disruptive as the majority of code is not expected to care. Use the - :func:`~multiprocessing.get_context` or - :func:`~multiprocessing.set_start_method` APIs to explicitly specify when - your code *requires* ``'fork'``. See :ref:`multiprocessing-start-methods`. + * :func:`!pty.master_open` + * :func:`!pty.slave_open` -* :mod:`pkgutil`: :func:`pkgutil.find_loader` and :func:`pkgutil.get_loader` - now raise :exc:`DeprecationWarning`; - use :func:`importlib.util.find_spec` instead. - (Contributed by Nikita Sobolev in :gh:`97850`.) +* :mod:`shutil`: The *onerror* argument of :func:`shutil.rmtree` -* :mod:`pty`: The module has two undocumented ``master_open()`` and ``slave_open()`` - functions that have been deprecated since Python 2 but only gained a - proper :exc:`DeprecationWarning` in 3.12. Remove them in 3.14. +* :mod:`typing`: :class:`!typing.ByteString` -* :mod:`shutil`: The *onerror* argument of :func:`shutil.rmtree` is deprecated in 3.12, - and will be removed in 3.14. +* :mod:`xml.etree.ElementTree`: Testing the truth value of an :class:`xml.etree.ElementTree.Element`. -* :mod:`typing`: :class:`typing.ByteString`, deprecated since Python 3.9, now causes a - :exc:`DeprecationWarning` to be emitted when it is used. +* The ``__package__`` and ``__cached__`` attributes on module objects. -* :mod:`xml.etree.ElementTree`: Testing the truth value of an :class:`xml.etree.ElementTree.Element` - is deprecated and will raise an exception in Python 3.14. +* The :attr:`~codeobject.co_lnotab` attribute of code objects. -* Creating immutable types (:c:macro:`Py_TPFLAGS_IMMUTABLETYPE`) with mutable - bases using the C API. +Pending Removal in Python 3.15 +------------------------------ -* ``__package__`` and ``__cached__`` will cease to be set or taken - into consideration by the import system (:gh:`97879`). +The following APIs have been deprecated +and will be removed in Python 3.15. + +APIs: + +* :func:`locale.getdefaultlocale` (:gh:`90817`) -* Accessing ``co_lnotab`` was deprecated in :pep:`626` since 3.10 - and was planned to be removed in 3.12 - but it only got a proper :exc:`DeprecationWarning` in 3.12. - May be removed in 3.14. - (Contributed by Nikita Sobolev in :gh:`101866`.) Pending Removal in Future Versions ---------------------------------- @@ -1218,6 +1452,8 @@ Pending Removal in Future Versions The following APIs were deprecated in earlier Python versions and will be removed, although there is currently no date scheduled for their removal. +* :mod:`array`'s ``'u'`` format code (:gh:`57281`) + * :class:`typing.Text` (:gh:`92332`) * Currently Python accepts numeric literals immediately followed by keywords, @@ -1233,13 +1469,19 @@ although there is currently no date scheduled for their removal. Removed ======= -* ``asynchat`` and ``asyncore``: These two modules have been removed +asynchat and asyncore +--------------------- + +* These two modules have been removed according to the schedule in :pep:`594`, having been deprecated in Python 3.6. Use :mod:`asyncio` instead. (Contributed by Nikita Sobolev in :gh:`96580`.) -* :mod:`configparser`: Several names deprecated in the :mod:`configparser` way back in 3.2 have +configparser +------------ + +* Several names deprecated in the :mod:`configparser` way back in 3.2 have been removed per :gh:`89336`: * :class:`configparser.ParsingError` no longer has a ``filename`` attribute @@ -1249,13 +1491,19 @@ Removed * :class:`configparser.ConfigParser` no longer has a ``readfp`` method. Use :meth:`~configparser.ConfigParser.read_file` instead. -* ``distutils``: Remove the ``distutils`` package. It was deprecated in Python 3.10 by +distutils +--------- + +* Remove the :py:mod:`!distutils` package. It was deprecated in Python 3.10 by :pep:`632` "Deprecate distutils module". For projects still using ``distutils`` and cannot be updated to something else, the ``setuptools`` project can be installed: it still provides ``distutils``. (Contributed by Victor Stinner in :gh:`92584`.) -* :mod:`ensurepip`: Remove the bundled setuptools wheel from :mod:`ensurepip`, +ensurepip +--------- + +* Remove the bundled setuptools wheel from :mod:`ensurepip`, and stop installing setuptools in environments created by :mod:`venv`. ``pip (>= 22.1)`` does not require setuptools to be installed in the @@ -1273,34 +1521,50 @@ Removed (Contributed by Pradyun Gedam in :gh:`95299`.) -* :mod:`enum`: Remove ``EnumMeta.__getattr__``, which is no longer needed for +enum +---- + +* Remove :mod:`enum`'s ``EnumMeta.__getattr__``, which is no longer needed for enum attribute access. (Contributed by Ethan Furman in :gh:`95083`.) -* :mod:`ftplib`: Remove the ``FTP_TLS.ssl_version`` class attribute: use the +ftplib +------ + +* Remove :mod:`ftplib`'s ``FTP_TLS.ssl_version`` class attribute: use the *context* parameter instead. (Contributed by Victor Stinner in :gh:`94172`.) -* :mod:`gzip`: Remove the ``filename`` attribute of :class:`gzip.GzipFile`, +gzip +---- + +* Remove the ``filename`` attribute of :mod:`gzip`'s :class:`gzip.GzipFile`, deprecated since Python 2.6, use the :attr:`~gzip.GzipFile.name` attribute instead. In write mode, the ``filename`` attribute added ``'.gz'`` file extension if it was not present. (Contributed by Victor Stinner in :gh:`94196`.) -* :mod:`hashlib`: Remove the pure Python implementation of +hashlib +------- + +* Remove the pure Python implementation of :mod:`hashlib`'s :func:`hashlib.pbkdf2_hmac()`, deprecated in Python 3.10. Python 3.10 and newer requires OpenSSL 1.1.1 (:pep:`644`): this OpenSSL version provides a C implementation of :func:`~hashlib.pbkdf2_hmac()` which is faster. (Contributed by Victor Stinner in :gh:`94199`.) -* :mod:`importlib`: Many previously deprecated cleanups in :mod:`importlib` have now been +importlib +--------- + +* Many previously deprecated cleanups in :mod:`importlib` have now been completed: * References to, and support for :meth:`!module_repr()` has been removed. (Contributed by Barry Warsaw in :gh:`97850`.) - * ``importlib.util.set_package`` has been removed. (Contributed by Brett - Cannon in :gh:`65961`.) + * ``importlib.util.set_package``, ``importlib.util.set_loader`` and + ``importlib.util.module_for_loader`` have all been removed. (Contributed by + Brett Cannon and Nikita Sobolev in :gh:`65961` and :gh:`97850`.) * Support for ``find_loader()`` and ``find_module()`` APIs have been removed. (Contributed by Barry Warsaw in :gh:`98040`.) @@ -1308,10 +1572,13 @@ Removed * ``importlib.abc.Finder``, ``pkgutil.ImpImporter``, and ``pkgutil.ImpLoader`` have been removed. (Contributed by Barry Warsaw in :gh:`98040`.) - * The :mod:`!imp` module has been removed. (Contributed by Barry Warsaw in - :gh:`98040`.) +imp +--- + +* The :mod:`!imp` module has been removed. (Contributed by Barry Warsaw in + :gh:`98040`.) - * Replace removed :mod:`!imp` functions with :mod:`importlib` functions: + To migrate, consult the following correspondence table: ================================= ======================================= imp importlib @@ -1326,9 +1593,10 @@ Removed ``imp.new_module(name)`` ``types.ModuleType(name)`` ``imp.reload()`` :func:`importlib.reload` ``imp.source_from_cache()`` :func:`importlib.util.source_from_cache` + ``imp.load_source()`` *See below* ================================= ======================================= - * Replace ``imp.load_source()`` with:: + Replace ``imp.load_source()`` with:: import importlib.util import importlib.machinery @@ -1343,32 +1611,41 @@ Removed loader.exec_module(module) return module - * Removed :mod:`!imp` functions and attributes with no replacements: +* Remove :mod:`!imp` functions and attributes with no replacements: - * undocumented functions: + * Undocumented functions: - * ``imp.init_builtin()`` - * ``imp.load_compiled()`` - * ``imp.load_dynamic()`` - * ``imp.load_package()`` + * ``imp.init_builtin()`` + * ``imp.load_compiled()`` + * ``imp.load_dynamic()`` + * ``imp.load_package()`` - * ``imp.lock_held()``, ``imp.acquire_lock()``, ``imp.release_lock()``: - the locking scheme has changed in Python 3.3 to per-module locks. - * ``imp.find_module()`` constants: ``SEARCH_ERROR``, ``PY_SOURCE``, - ``PY_COMPILED``, ``C_EXTENSION``, ``PY_RESOURCE``, ``PKG_DIRECTORY``, - ``C_BUILTIN``, ``PY_FROZEN``, ``PY_CODERESOURCE``, ``IMP_HOOK``. + * ``imp.lock_held()``, ``imp.acquire_lock()``, ``imp.release_lock()``: + the locking scheme has changed in Python 3.3 to per-module locks. + * ``imp.find_module()`` constants: ``SEARCH_ERROR``, ``PY_SOURCE``, + ``PY_COMPILED``, ``C_EXTENSION``, ``PY_RESOURCE``, ``PKG_DIRECTORY``, + ``C_BUILTIN``, ``PY_FROZEN``, ``PY_CODERESOURCE``, ``IMP_HOOK``. + +io +-- -* :mod:`io`: Remove ``io.OpenWrapper`` and ``_pyio.OpenWrapper``, deprecated in Python +* Remove :mod:`io`'s ``io.OpenWrapper`` and ``_pyio.OpenWrapper``, deprecated in Python 3.10: just use :func:`open` instead. The :func:`open` (:func:`io.open`) function is a built-in function. Since Python 3.10, :func:`!_pyio.open` is also a static method. (Contributed by Victor Stinner in :gh:`94169`.) -* :mod:`locale`: Remove the :func:`!locale.format` function, deprecated in Python 3.7: +locale +------ + +* Remove :mod:`locale`'s :func:`!locale.format` function, deprecated in Python 3.7: use :func:`locale.format_string` instead. (Contributed by Victor Stinner in :gh:`94226`.) -* ``smtpd``: The module has been removed according to the schedule in :pep:`594`, +smtpd +----- + +* The ``smtpd`` module has been removed according to the schedule in :pep:`594`, having been deprecated in Python 3.4.7 and 3.5.4. Use aiosmtpd_ PyPI module or any other :mod:`asyncio`-based server instead. @@ -1376,7 +1653,10 @@ Removed .. _aiosmtpd: https://pypi.org/project/aiosmtpd/ -* :mod:`sqlite3`: The following undocumented :mod:`sqlite3` features, deprecated in Python +sqlite3 +------- + +* The following undocumented :mod:`sqlite3` features, deprecated in Python 3.10, are now removed: * ``sqlite3.enable_shared_cache()`` @@ -1392,30 +1672,36 @@ Removed (Contributed by Erlend E. Aasland in :gh:`92548`.) -* :mod:`ssl`: +ssl +--- + +* Remove :mod:`ssl`'s :func:`!ssl.RAND_pseudo_bytes` function, deprecated in Python 3.6: + use :func:`os.urandom` or :func:`ssl.RAND_bytes` instead. + (Contributed by Victor Stinner in :gh:`94199`.) + +* Remove the :func:`!ssl.match_hostname` function. + It was deprecated in Python 3.7. OpenSSL performs + hostname matching since Python 3.7, Python no longer uses the + :func:`!ssl.match_hostname` function. + (Contributed by Victor Stinner in :gh:`94199`.) - * Remove the :func:`!ssl.RAND_pseudo_bytes` function, deprecated in Python 3.6: - use :func:`os.urandom` or :func:`ssl.RAND_bytes` instead. - (Contributed by Victor Stinner in :gh:`94199`.) +* Remove the :func:`!ssl.wrap_socket` function, deprecated in Python 3.7: + instead, create a :class:`ssl.SSLContext` object and call its + :class:`ssl.SSLContext.wrap_socket` method. Any package that still uses + :func:`!ssl.wrap_socket` is broken and insecure. The function neither sends a + SNI TLS extension nor validates server hostname. Code is subject to `CWE-295 + `_: Improper Certificate + Validation. + (Contributed by Victor Stinner in :gh:`94199`.) - * Remove the :func:`!ssl.match_hostname` function. - It was deprecated in Python 3.7. OpenSSL performs - hostname matching since Python 3.7, Python no longer uses the - :func:`!ssl.match_hostname` function. - (Contributed by Victor Stinner in :gh:`94199`.) +unittest +-------- - * Remove the :func:`!ssl.wrap_socket` function, deprecated in Python 3.7: - instead, create a :class:`ssl.SSLContext` object and call its - :class:`ssl.SSLContext.wrap_socket` method. Any package that still uses - :func:`!ssl.wrap_socket` is broken and insecure. The function neither sends a - SNI TLS extension nor validates server hostname. Code is subject to `CWE-295 - `_: Improper Certificate - Validation. - (Contributed by Victor Stinner in :gh:`94199`.) +* Remove many long-deprecated :mod:`unittest` features: -* :mod:`unittest`: Removed many old deprecated :mod:`unittest` features: + .. _unittest-TestCase-removed-aliases: - - A number of :class:`~unittest.TestCase` method aliases: + * A number of :class:`~unittest.TestCase` method aliases: ============================ =============================== =============== Deprecated alias Method Name Deprecated in @@ -1440,35 +1726,47 @@ Removed You can use https://github.com/isidentical/teyit to automatically modernise your unit tests. - - Undocumented and broken :class:`~unittest.TestCase` method + * Undocumented and broken :class:`~unittest.TestCase` method ``assertDictContainsSubset`` (deprecated in Python 3.2). - - Undocumented :meth:`TestLoader.loadTestsFromModule + * Undocumented :meth:`TestLoader.loadTestsFromModule ` parameter *use_load_tests* (deprecated and ignored since Python 3.2). - - An alias of the :class:`~unittest.TextTestResult` class: + * An alias of the :class:`~unittest.TextTestResult` class: ``_TextTestResult`` (deprecated in Python 3.2). - (Contributed by Serhiy Storchaka in :issue:`45162`.) + (Contributed by Serhiy Storchaka in :gh:`89325`.) + +webbrowser +---------- -* :mod:`webbrowser`: Remove support for obsolete browsers from :mod:`webbrowser`. - Removed browsers include: Grail, Mosaic, Netscape, Galeon, Skipstone, +* Remove support for obsolete browsers from :mod:`webbrowser`. + The removed browsers include: Grail, Mosaic, Netscape, Galeon, Skipstone, Iceape, Firebird, and Firefox versions 35 and below (:gh:`102871`). -* :mod:`xml.etree.ElementTree`: Remove the ``ElementTree.Element.copy()`` method of the +xml.etree.ElementTree +--------------------- + +* Remove the ``ElementTree.Element.copy()`` method of the pure Python implementation, deprecated in Python 3.10, use the :func:`copy.copy` function instead. The C implementation of :mod:`xml.etree.ElementTree` has no ``copy()`` method, only a ``__copy__()`` method. (Contributed by Victor Stinner in :gh:`94383`.) -* :mod:`zipimport`: Remove ``find_loader()`` and ``find_module()`` methods, +zipimport +--------- + +* Remove :mod:`zipimport`'s ``find_loader()`` and ``find_module()`` methods, deprecated in Python 3.10: use the ``find_spec()`` method instead. See :pep:`451` for the rationale. (Contributed by Victor Stinner in :gh:`94379`.) -* Removed the ``suspicious`` rule from the documentation Makefile, and - removed ``Doc/tools/rstlint.py``, both in favor of `sphinx-lint +Others +------ + +* Remove the ``suspicious`` rule from the documentation :file:`Makefile` and + :file:`Doc/tools/rstlint.py`, both in favor of `sphinx-lint `_. (Contributed by Julien Palard in :gh:`98179`.) @@ -1480,6 +1778,14 @@ Removed (*ssl_context* in :mod:`imaplib`) instead. (Contributed by Victor Stinner in :gh:`94172`.) +* Remove ``Jython`` compatibility hacks from several stdlib modules and tests. + (Contributed by Nikita Sobolev in :gh:`99482`.) + +* Remove ``_use_broken_old_ctypes_structure_semantics_`` flag + from :mod:`ctypes` module. + (Contributed by Nikita Sobolev in :gh:`99285`.) + + .. _whatsnew312-porting-to-python312: Porting to Python 3.12 @@ -1498,7 +1804,7 @@ Changes in the Python API contain ASCII letters and digits and underscore. (Contributed by Serhiy Storchaka in :gh:`91760`.) -* Removed ``randrange()`` functionality deprecated since Python 3.10. Formerly, +* Remove ``randrange()`` functionality deprecated since Python 3.10. Formerly, ``randrange(10.0)`` losslessly converted to ``randrange(10)``. Now, it raises a :exc:`TypeError`. Also, the exception raised for non-integer values such as ``randrange(10.5)`` or ``randrange('10')`` has been changed from :exc:`ValueError` to @@ -1512,7 +1818,7 @@ Changes in the Python API to :term:`filesystem encoding and error handler`. Argument files should be encoded in UTF-8 instead of ANSI Codepage on Windows. -* Removed the ``asyncore``-based ``smtpd`` module deprecated in Python 3.4.7 +* Remove the ``asyncore``-based ``smtpd`` module deprecated in Python 3.4.7 and 3.5.4. A recommended replacement is the :mod:`asyncio`-based aiosmtpd_ PyPI module. @@ -1533,7 +1839,7 @@ Changes in the Python API so only a very small set of users might be affected. This change helps with interpreter isolation. Furthermore, :mod:`syslog` is a wrapper around process-global resources, which are best managed from the main interpreter. - (Contributed by Dong-hee Na in :gh:`99127`.) + (Contributed by Donghee Na in :gh:`99127`.) * The undocumented locking behavior of :func:`~functools.cached_property` is removed, because it locked across all instances of the class, leading to high @@ -1557,7 +1863,7 @@ Changes in the Python API functions is now changed due to the changes introduced in :pep:`701`. This means that ``STRING`` tokens are not emitted any more for f-strings and the tokens described in :pep:`701` are now produced instead: ``FSTRING_START``, - ``FSRING_MIDDLE`` and ``FSTRING_END`` are now emitted for f-string "string" + ``FSTRING_MIDDLE`` and ``FSTRING_END`` are now emitted for f-string "string" parts in addition to the appropriate tokens for the tokenization in the expression components. For example for the f-string ``f"start {1+1} end"`` the old version of the tokenizer emitted:: @@ -1576,7 +1882,7 @@ Changes in the Python API 1,13-1,17: FSTRING_MIDDLE ' end' 1,17-1,18: FSTRING_END '"' - Additionally, there may be some minor behavioral changes as a consecuence of the + Additionally, there may be some minor behavioral changes as a consequence of the changes required to support :pep:`701`. Some of these changes include: * The ``type`` attribute of the tokens emitted when tokenizing some invalid Python @@ -1591,12 +1897,21 @@ Changes in the Python API * Mixing tabs and spaces as indentation in the same file is not supported anymore and will raise a :exc:`TabError`. +* The :mod:`threading` module now expects the :mod:`!_thread` module to have + an ``_is_main_interpreter`` attribute. It is a function with no + arguments that returns ``True`` if the current interpreter is the + main interpreter. + + Any library or application that provides a custom ``_thread`` module + should provide ``_is_main_interpreter()``. + (See :gh:`112826`.) + Build Changes ============= -* Python no longer uses ``setup.py`` to build shared C extension modules. +* Python no longer uses :file:`setup.py` to build shared C extension modules. Build parameters like headers and libraries are detected in ``configure`` - script. Extensions are built by ``Makefile``. Most extensions use + script. Extensions are built by :file:`Makefile`. Most extensions use ``pkg-config`` and fall back to manual detection. (Contributed by Christian Heimes in :gh:`93939`.) @@ -1607,9 +1922,9 @@ Build Changes * CPython now uses the ThinLTO option as the default link time optimization policy if the Clang compiler accepts the flag. - (Contributed by Dong-hee Na in :gh:`89536`.) + (Contributed by Donghee Na in :gh:`89536`.) -* Add ``COMPILEALL_OPTS`` variable in Makefile to override :mod:`compileall` +* Add ``COMPILEALL_OPTS`` variable in :file:`Makefile` to override :mod:`compileall` options (default: ``-j0``) in ``make install``. Also merged the 3 ``compileall`` commands into a single command to build .pyc files for all optimization levels (0, 1, 2) at once. @@ -1636,8 +1951,9 @@ C API Changes New Features ------------ +.. _whatsnew312-pep697: -* :pep:`697`: Introduced the :ref:`Unstable C API tier `, +* :pep:`697`: Introduce the :ref:`Unstable C API tier `, intended for low-level tools like debuggers and JIT compilers. This API may change in each minor release of CPython without deprecation warnings. @@ -1659,7 +1975,7 @@ New Features (Contributed by Petr Viktorin in :gh:`101101`.) -* :pep:`697`: Added API for extending types whose instance memory layout is +* :pep:`697`: Add an API for extending types whose instance memory layout is opaque: - :c:member:`PyType_Spec.basicsize` can be zero or negative to specify @@ -1674,7 +1990,7 @@ New Features (Contributed by Petr Viktorin in :gh:`103509`.) -* Added the new :ref:`limited C API ` function :c:func:`PyType_FromMetaclass`, +* Add the new :ref:`limited C API ` function :c:func:`PyType_FromMetaclass`, which generalizes the existing :c:func:`PyType_FromModuleAndSpec` using an additional metaclass argument. (Contributed by Wenzel Jakob in :gh:`93012`.) @@ -1713,13 +2029,13 @@ New Features protocol are now available in the :ref:`Limited API `. (Contributed by Wenzel Jakob in :gh:`98586`.) -* Added two new public functions, +* Add two new public functions, :c:func:`PyEval_SetProfileAllThreads` and :c:func:`PyEval_SetTraceAllThreads`, that allow to set tracing and profiling functions in all running threads in addition to the calling one. (Contributed by Pablo Galindo in :gh:`93503`.) -* Added new function :c:func:`PyFunction_SetVectorcall` to the C API +* Add new function :c:func:`PyFunction_SetVectorcall` to the C API which sets the vectorcall field of a given :c:type:`PyFunctionObject`. (Contributed by Andrew Frost in :gh:`92257`.) @@ -1729,14 +2045,14 @@ New Features compilers, or debuggers. (Contributed by Carl Meyer in :gh:`91052`.) -* Added :c:func:`PyType_AddWatcher` and :c:func:`PyType_Watch` API to register +* Add :c:func:`PyType_AddWatcher` and :c:func:`PyType_Watch` API to register callbacks to receive notification on changes to a type. (Contributed by Carl Meyer in :gh:`91051`.) -* Added :c:func:`PyCode_AddWatcher` and :c:func:`PyCode_ClearWatcher` +* Add :c:func:`PyCode_AddWatcher` and :c:func:`PyCode_ClearWatcher` APIs to register callbacks to receive notification on creation and destruction of code objects. - (Contributed by Itamar Ostricher in :gh:`91054`.) + (Contributed by Itamar Oren in :gh:`91054`.) * Add :c:func:`PyFrame_GetVar` and :c:func:`PyFrame_GetVarString` functions to get a frame variable by its name. @@ -1763,8 +2079,10 @@ New Features to replace the legacy-api :c:func:`!PyErr_Display`. (Contributed by Irit Katriel in :gh:`102755`). -* :pep:`683`: Introduced Immortal Objects to Python which allows objects - to bypass reference counts and introduced changes to the C-API: +.. _whatsnew312-pep683: + +* :pep:`683`: Introduce *Immortal Objects*, which allows objects + to bypass reference counts, and related changes to the C-API: - ``_Py_IMMORTAL_REFCNT``: The reference count that defines an object as immortal. @@ -1776,12 +2094,12 @@ New Features - ``SSTATE_INTERNED_IMMORTAL_STATIC`` An identifier for interned unicode objects that are immortal and static - ``sys.getunicodeinternedsize`` This returns the total number of unicode - objects that have been interned. This is now needed for refleak.py to + objects that have been interned. This is now needed for :file:`refleak.py` to correctly track reference counts and allocated blocks (Contributed by Eddie Elizondo in :gh:`84436`.) -* :pep:`684`: Added the new :c:func:`Py_NewInterpreterFromConfig` +* :pep:`684`: Add the new :c:func:`Py_NewInterpreterFromConfig` function and :c:type:`PyInterpreterConfig`, which may be used to create sub-interpreters with their own GILs. (See :ref:`whatsnew312-pep684` for more info.) @@ -1830,7 +2148,7 @@ Porting to Python 3.12 copied as-is to the result string, and any extra arguments discarded. (Contributed by Serhiy Storchaka in :gh:`95781`.) -* Fixed wrong sign placement in :c:func:`PyUnicode_FromFormat` and +* Fix wrong sign placement in :c:func:`PyUnicode_FromFormat` and :c:func:`PyUnicode_FromFormatV`. (Contributed by Philip Georgi in :gh:`95504`.) @@ -1841,7 +2159,7 @@ Porting to Python 3.12 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 :c:macro:`Py_TPFLAGS_MANAGED_DICT` should call + Classes declaring :c:macro:`Py_TPFLAGS_MANAGED_DICT` must 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. @@ -1935,6 +2253,11 @@ Porting to Python 3.12 Deprecated ---------- +* In accordance with :pep:`699`, the ``ma_version_tag`` field in :c:type:`PyDictObject` + is deprecated for extension modules. Accessing this field will generate a compiler + warning at compile time. This field will be removed in Python 3.14. + (Contributed by Ramvikrams and Kumar Aditya in :gh:`101193`. PEP by Ken Jin.) + * Deprecate global configuration variable: * :c:var:`Py_DebugFlag`: use :c:member:`PyConfig.parser_debug` @@ -1964,13 +2287,13 @@ Deprecated :c:type:`PyConfig` instead. (Contributed by Victor Stinner in :gh:`77782`.) -* Creating immutable types (:c:macro:`Py_TPFLAGS_IMMUTABLETYPE`) with mutable - bases is deprecated and will be disabled in Python 3.14. +* Creating :c:data:`immutable types ` with mutable + bases is deprecated and will be disabled in Python 3.14. (:gh:`95388`) -* The ``structmember.h`` header is deprecated, though it continues to be +* The :file:`structmember.h` header is deprecated, though it continues to be available and there are no plans to remove it. - Its contents are now available just by including ``Python.h``, + Its contents are now available just by including :file:`Python.h`, with a ``Py`` prefix added if it was missing: - :c:struct:`PyMemberDef`, :c:func:`PyMember_GetOne` and @@ -1980,14 +2303,14 @@ Deprecated - The flags :c:macro:`Py_READONLY` (previously ``READONLY``) and :c:macro:`Py_AUDIT_READ` (previously all uppercase) - Several items are not exposed from ``Python.h``: + Several items are not exposed from :file:`Python.h`: - :c:macro:`T_OBJECT` (use :c:macro:`Py_T_OBJECT_EX`) - :c:macro:`T_NONE` (previously undocumented, and pretty quirky) - The macro ``WRITE_RESTRICTED`` which does nothing. - The macros ``RESTRICTED`` and ``READ_RESTRICTED``, equivalents of :c:macro:`Py_AUDIT_READ`. - - In some configurations, ```` is not included from ``Python.h``. + - In some configurations, ```` is not included from :file:`Python.h`. It should be included manually when using ``offsetof()``. The deprecated header continues to provide its original @@ -2014,32 +2337,112 @@ Deprecated overrides :c:member:`~PyTypeObject.tp_new` is deprecated. Call the metaclass instead. +Pending Removal in Python 3.14 +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +* The ``ma_version_tag`` field in :c:type:`PyDictObject` for extension modules + (:pep:`699`; :gh:`101193`). + +* Global configuration variables: + + * :c:var:`Py_DebugFlag`: use :c:member:`PyConfig.parser_debug` + * :c:var:`Py_VerboseFlag`: use :c:member:`PyConfig.verbose` + * :c:var:`Py_QuietFlag`: use :c:member:`PyConfig.quiet` + * :c:var:`Py_InteractiveFlag`: use :c:member:`PyConfig.interactive` + * :c:var:`Py_InspectFlag`: use :c:member:`PyConfig.inspect` + * :c:var:`Py_OptimizeFlag`: use :c:member:`PyConfig.optimization_level` + * :c:var:`Py_NoSiteFlag`: use :c:member:`PyConfig.site_import` + * :c:var:`Py_BytesWarningFlag`: use :c:member:`PyConfig.bytes_warning` + * :c:var:`Py_FrozenFlag`: use :c:member:`PyConfig.pathconfig_warnings` + * :c:var:`Py_IgnoreEnvironmentFlag`: use :c:member:`PyConfig.use_environment` + * :c:var:`Py_DontWriteBytecodeFlag`: use :c:member:`PyConfig.write_bytecode` + * :c:var:`Py_NoUserSiteDirectory`: use :c:member:`PyConfig.user_site_directory` + * :c:var:`Py_UnbufferedStdioFlag`: use :c:member:`PyConfig.buffered_stdio` + * :c:var:`Py_HashRandomizationFlag`: use :c:member:`PyConfig.use_hash_seed` + and :c:member:`PyConfig.hash_seed` + * :c:var:`Py_IsolatedFlag`: use :c:member:`PyConfig.isolated` + * :c:var:`Py_LegacyWindowsFSEncodingFlag`: use :c:member:`PyPreConfig.legacy_windows_fs_encoding` + * :c:var:`Py_LegacyWindowsStdioFlag`: use :c:member:`PyConfig.legacy_windows_stdio` + * :c:var:`!Py_FileSystemDefaultEncoding`: use :c:member:`PyConfig.filesystem_encoding` + * :c:var:`!Py_HasFileSystemDefaultEncoding`: use :c:member:`PyConfig.filesystem_encoding` + * :c:var:`!Py_FileSystemDefaultEncodeErrors`: use :c:member:`PyConfig.filesystem_errors` + * :c:var:`!Py_UTF8Mode`: use :c:member:`PyPreConfig.utf8_mode` (see :c:func:`Py_PreInitialize`) + + The :c:func:`Py_InitializeFromConfig` API should be used with + :c:type:`PyConfig` instead. + +* Creating :c:data:`immutable types ` with mutable + bases (:gh:`95388`). + +Pending Removal in Python 3.15 +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +* :c:func:`PyImport_ImportModuleNoBlock`: use :c:func:`PyImport_ImportModule` +* :c:type:`!Py_UNICODE_WIDE` type: use :c:type:`wchar_t` +* :c:type:`Py_UNICODE` type: use :c:type:`wchar_t` +* Python initialization functions: + + * :c:func:`PySys_ResetWarnOptions`: clear :data:`sys.warnoptions` and + :data:`!warnings.filters` + * :c:func:`Py_GetExecPrefix`: get :data:`sys.exec_prefix` + * :c:func:`Py_GetPath`: get :data:`sys.path` + * :c:func:`Py_GetPrefix`: get :data:`sys.prefix` + * :c:func:`Py_GetProgramFullPath`: get :data:`sys.executable` + * :c:func:`Py_GetProgramName`: get :data:`sys.executable` + * :c:func:`Py_GetPythonHome`: get :c:member:`PyConfig.home` or + the :envvar:`PYTHONHOME` environment variable + +Pending Removal in Future Versions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The following APIs are deprecated and will be removed, +although there is currently no date scheduled for their removal. + +* :c:macro:`Py_TPFLAGS_HAVE_FINALIZE`: unneeded since Python 3.8 +* :c:func:`PyErr_Fetch`: use :c:func:`PyErr_GetRaisedException` +* :c:func:`PyErr_NormalizeException`: use :c:func:`PyErr_GetRaisedException` +* :c:func:`PyErr_Restore`: use :c:func:`PyErr_SetRaisedException` +* :c:func:`PyModule_GetFilename`: use :c:func:`PyModule_GetFilenameObject` +* :c:func:`PyOS_AfterFork`: use :c:func:`PyOS_AfterFork_Child` +* :c:func:`PySlice_GetIndicesEx`: use :c:func:`PySlice_Unpack` and :c:func:`PySlice_AdjustIndices` +* :c:func:`!PyUnicode_AsDecodedObject`: use :c:func:`PyCodec_Decode` +* :c:func:`!PyUnicode_AsDecodedUnicode`: use :c:func:`PyCodec_Decode` +* :c:func:`!PyUnicode_AsEncodedObject`: use :c:func:`PyCodec_Encode` +* :c:func:`!PyUnicode_AsEncodedUnicode`: use :c:func:`PyCodec_Encode` +* :c:func:`PyUnicode_READY`: unneeded since Python 3.12 +* :c:func:`!PyErr_Display`: use :c:func:`PyErr_DisplayException` +* :c:func:`!_PyErr_ChainExceptions`: use ``_PyErr_ChainExceptions1`` +* :c:member:`!PyBytesObject.ob_shash` member: + call :c:func:`PyObject_Hash` instead +* :c:member:`!PyDictObject.ma_version_tag` member +* Thread Local Storage (TLS) API: + + * :c:func:`PyThread_create_key`: use :c:func:`PyThread_tss_alloc` + * :c:func:`PyThread_delete_key`: use :c:func:`PyThread_tss_free` + * :c:func:`PyThread_set_key_value`: use :c:func:`PyThread_tss_set` + * :c:func:`PyThread_get_key_value`: use :c:func:`PyThread_tss_get` + * :c:func:`PyThread_delete_key_value`: use :c:func:`PyThread_tss_delete` + * :c:func:`PyThread_ReInitTLS`: unneeded since Python 3.7 + Removed ------- -* Remove the ``token.h`` header file. There was never any public tokenizer C - API. The ``token.h`` header file was only designed to be used by Python +* Remove the :file:`token.h` header file. There was never any public tokenizer C + API. The :file:`token.h` header file was only designed to be used by Python internals. (Contributed by Victor Stinner in :gh:`92651`.) * Legacy Unicode APIs have been removed. See :pep:`623` for detail. - * :c:macro:`!PyUnicode_WCHAR_KIND` - * :c:func:`!PyUnicode_AS_UNICODE` - * :c:func:`!PyUnicode_AsUnicode` - * :c:func:`!PyUnicode_AsUnicodeAndSize` - * :c:func:`!PyUnicode_AS_DATA` - * :c:func:`!PyUnicode_FromUnicode` - * :c:func:`!PyUnicode_GET_SIZE` - * :c:func:`!PyUnicode_GetSize` - * :c:func:`!PyUnicode_GET_DATA_SIZE` + * :c:macro:`!PyUnicode_WCHAR_KIND` + * :c:func:`!PyUnicode_AS_UNICODE` + * :c:func:`!PyUnicode_AsUnicode` + * :c:func:`!PyUnicode_AsUnicodeAndSize` + * :c:func:`!PyUnicode_AS_DATA` + * :c:func:`!PyUnicode_FromUnicode` + * :c:func:`!PyUnicode_GET_SIZE` + * :c:func:`!PyUnicode_GetSize` + * :c:func:`!PyUnicode_GET_DATA_SIZE` * Remove the ``PyUnicode_InternImmortal()`` function macro. (Contributed by Victor Stinner in :gh:`85858`.) - -* Remove ``Jython`` compatibility hacks from several stdlib modules and tests. - (Contributed by Nikita Sobolev in :gh:`99482`.) - -* Remove ``_use_broken_old_ctypes_structure_semantics_`` flag - from :mod:`ctypes` module. - (Contributed by Nikita Sobolev in :gh:`99285`.) diff --git a/Doc/whatsnew/3.13.rst b/Doc/whatsnew/3.13.rst index 63cdee6cf1a4f3..59b9281e6d2b89 100644 --- a/Doc/whatsnew/3.13.rst +++ b/Doc/whatsnew/3.13.rst @@ -65,12 +65,34 @@ Summary -- Release highlights .. PEP-sized items next. +Important deprecations, removals or restrictions: + +* :ref:`PEP 594 `: The remaining 19 "dead batteries" + have been removed from the standard library: + :mod:`!aifc`, :mod:`!audioop`, :mod:`!cgi`, :mod:`!cgitb`, :mod:`!chunk`, + :mod:`!crypt`, :mod:`!imghdr`, :mod:`!mailcap`, :mod:`!msilib`, :mod:`!nis`, + :mod:`!nntplib`, :mod:`!ossaudiodev`, :mod:`!pipes`, :mod:`!sndhdr`, :mod:`!spwd`, + :mod:`!sunau`, :mod:`!telnetlib`, :mod:`!uu` and :mod:`!xdrlib`. + +* :pep:`602` ("Annual Release Cycle for Python") has been updated: + + * Python 3.9 - 3.12 have one and a half years of full support, + followed by three and a half years of security fixes. + * Python 3.13 and later have two years of full support, + followed by three years of security fixes. New Features ============ +Improved Error Messages +----------------------- +* The interpreter now colorizes error messages when displaying tracebacks by default. + This feature can be controlled via the new :envvar:`PYTHON_COLORS` environment + variable as well as the canonical ``NO_COLOR`` and ``FORCE_COLOR`` environment + variables. See also :ref:`using-on-controlling-color`. + (Contributed by Pablo Galindo Salgado in :gh:`112730`.) Other Language Changes ====================== @@ -85,6 +107,36 @@ Other Language Changes This change will affect tools using docstrings, like :mod:`doctest`. (Contributed by Inada Naoki in :gh:`81283`.) +* The :func:`compile` built-in can now accept a new flag, + ``ast.PyCF_OPTIMIZED_AST``, which is similar to ``ast.PyCF_ONLY_AST`` + except that the returned ``AST`` is optimized according to the value + of the ``optimize`` argument. + (Contributed by Irit Katriel in :gh:`108113`). + +* :mod:`multiprocessing`, :mod:`concurrent.futures`, :mod:`compileall`: + Replace :func:`os.cpu_count` with :func:`os.process_cpu_count` to select the + default number of worker threads and processes. Get the CPU affinity + if supported. + (Contributed by Victor Stinner in :gh:`109649`.) + +* :func:`os.path.realpath` now resolves MS-DOS style file names even if + the file is not accessible. + (Contributed by Moonsik Park in :gh:`82367`.) + +* Fixed a bug where a :keyword:`global` declaration in an :keyword:`except` block + is rejected when the global is used in the :keyword:`else` block. + (Contributed by Irit Katriel in :gh:`111123`.) + +* Added a new environment variable :envvar:`PYTHON_FROZEN_MODULES`. It + determines whether or not frozen modules are ignored by the import machinery, + equivalent of the :option:`-X frozen_modules <-X>` command-line option. + (Contributed by Yilei Yang in :gh:`111374`.) + +* The new :envvar:`PYTHON_HISTORY` environment variable can be used to change + the location of a ``.python_history`` file. + (Contributed by Levi Sabah, Zackery Spytz and Hugo van Kemenade in + :gh:`73965`.) + New Modules =========== @@ -94,6 +146,14 @@ New Modules Improved Modules ================ +ast +--- + +* :func:`ast.parse` now accepts an optional argument ``optimize`` + which is passed on to the :func:`compile` built-in. This makes it + possible to obtain an optimized ``AST``. + (Contributed by Irit Katriel in :gh:`108113`). + array ----- @@ -101,12 +161,76 @@ array It can be used instead of ``'u'`` type code, which is deprecated. (Contributed by Inada Naoki in :gh:`80480`.) +asyncio +------- + +* :meth:`asyncio.loop.create_unix_server` will now automatically remove + the Unix socket when the server is closed. + (Contributed by Pierre Ossman in :gh:`111246`.) + +copy +---- + +* Add :func:`copy.replace` function which allows to create a modified copy of + an object, which is especially useful for immutable objects. + It supports named tuples created with the factory function + :func:`collections.namedtuple`, :class:`~dataclasses.dataclass` instances, + various :mod:`datetime` objects, :class:`~inspect.Signature` objects, + :class:`~inspect.Parameter` objects, :ref:`code object `, and + any user classes which define the :meth:`!__replace__` method. + (Contributed by Serhiy Storchaka in :gh:`108751`.) + +dis +--- + +* Change the output of :mod:`dis` module functions to show logical + labels for jump targets and exception handlers, rather than offsets. + The offsets can be added with the new ``-O`` command line option or + the ``show_offsets`` parameter. + (Contributed by Irit Katriel in :gh:`112137`.) + dbm --- * Add :meth:`dbm.gnu.gdbm.clear` and :meth:`dbm.ndbm.ndbm.clear` methods that remove all items from the database. - (Contributed by Dong-hee Na in :gh:`107122`.) + (Contributed by Donghee Na in :gh:`107122`.) + +doctest +------- + +* The :meth:`doctest.DocTestRunner.run` method now counts the number of skipped + tests. Add :attr:`doctest.DocTestRunner.skips` and + :attr:`doctest.TestResults.skipped` attributes. + (Contributed by Victor Stinner in :gh:`108794`.) + +email +----- + +* :func:`email.utils.getaddresses` and :func:`email.utils.parseaddr` now return + ``('', '')`` 2-tuples in more situations where invalid email addresses are + encountered instead of potentially inaccurate values. Add optional *strict* + parameter to these two functions: use ``strict=False`` to get the old + behavior, accept malformed inputs. + ``getattr(email.utils, 'supports_strict_parsing', False)`` can be use to + check if the *strict* paramater is available. + (Contributed by Thomas Dwyer and Victor Stinner for :gh:`102988` to improve + the CVE-2023-27043 fix.) + +fractions +--------- + +* Formatting for objects of type :class:`fractions.Fraction` now supports + the standard format specification mini-language rules for fill, alignment, + sign handling, minimum width and grouping. (Contributed by Mark Dickinson + in :gh:`111320`) + +glob +---- + +* Add :func:`glob.translate` function that converts a path specification with + shell-style wildcards to a regular expression. + (Contributed by Barney Gale in :gh:`72904`.) io -- @@ -117,6 +241,20 @@ and only logged in :ref:`Python Development Mode ` or on :ref:`Python built on debug mode `. (Contributed by Victor Stinner in :gh:`62948`.) +ipaddress +--------- + +* Add the :attr:`ipaddress.IPv4Address.ipv6_mapped` property, which returns the IPv4-mapped IPv6 address. + (Contributed by Charles Machalow in :gh:`109466`.) + +mmap +---- + +* The :class:`mmap.mmap` class now has an :meth:`~mmap.mmap.seekable` method + that can be used where it requires a file-like object with seekable and + the :meth:`~mmap.mmap.seek` method return the new absolute position. + (Contributed by Donghee Na and Sylvie Liberman in :gh:`111835`.) + opcode ------ @@ -129,6 +267,46 @@ opcode documented or exposed through ``dis``, and were not intended to be used externally. +os +-- + +* Add :func:`os.process_cpu_count` function to get the number of logical CPUs + usable by the calling thread of the current process. + (Contributed by Victor Stinner in :gh:`109649`.) + +* Add a low level interface for Linux's timer notification file descriptors + via :func:`os.timerfd_create`, + :func:`os.timerfd_settime`, :func:`os.timerfd_settime_ns`, + :func:`os.timerfd_gettime`, and :func:`os.timerfd_gettime_ns`, + :const:`os.TFD_NONBLOCK`, :const:`os.TFD_CLOEXEC`, + :const:`os.TFD_TIMER_ABSTIME`, and :const:`os.TFD_TIMER_CANCEL_ON_SET` + (Contributed by Masaru Tsuchiyama in :gh:`108277`.) + +* :func:`os.cpu_count` and :func:`os.process_cpu_count` can be overridden through + the new environment variable :envvar:`PYTHON_CPU_COUNT` or the new command-line option + :option:`-X cpu_count <-X>`. This option is useful for users who need to limit + CPU resources of a container system without having to modify the container (application code). + (Contributed by Donghee Na in :gh:`109595`) + +* Add support of :func:`os.lchmod` and the *follow_symlinks* argument + in :func:`os.chmod` on Windows. + Note that the default value of *follow_symlinks* in :func:`!os.lchmod` is + ``False`` on Windows. + (Contributed by Serhiy Storchaka in :gh:`59616`) + +* Add support of :func:`os.fchmod` and a file descriptor + in :func:`os.chmod` on Windows. + (Contributed by Serhiy Storchaka in :gh:`113191`) + +* :func:`os.posix_spawn` now accepts ``env=None``, which makes the newly spawned + process use the current process environment. + (Contributed by Jakub Kulik in :gh:`113119`.) + +* :func:`os.posix_spawn` gains an :attr:`os.POSIX_SPAWN_CLOSEFROM` attribute for + use in ``file_actions=`` on platforms that support + :c:func:`!posix_spawn_file_actions_addclosefrom_np`. + (Contributed by Jakub Kulik in :gh:`113117`.) + pathlib ------- @@ -136,21 +314,97 @@ pathlib :exc:`NotImplementedError` when a path operation isn't supported. (Contributed by Barney Gale in :gh:`89812`.) +* Add :meth:`pathlib.Path.from_uri`, a new constructor to create a :class:`pathlib.Path` + object from a 'file' URI (``file:/``). + (Contributed by Barney Gale in :gh:`107465`.) + * Add support for recursive wildcards in :meth:`pathlib.PurePath.match`. (Contributed by Barney Gale in :gh:`73435`.) * Add *follow_symlinks* keyword-only argument to :meth:`pathlib.Path.glob`, - :meth:`~pathlib.Path.rglob`, :meth:`~pathlib.Path.is_file`, and - :meth:`~pathlib.Path.is_dir`. - (Contributed by Barney Gale in :gh:`77609` and :gh:`105793`.) + :meth:`~pathlib.Path.rglob`, :meth:`~pathlib.Path.is_file`, + :meth:`~pathlib.Path.is_dir`, :meth:`~pathlib.Path.owner`, + :meth:`~pathlib.Path.group`. + (Contributed by Barney Gale in :gh:`77609` and :gh:`105793`, and + Kamil Turek in :gh:`107962`). + +pdb +--- + +* Add ability to move between chained exceptions during post mortem debugging in :func:`~pdb.pm` using + the new ``exceptions [exc_number]`` command for Pdb. (Contributed by Matthias + Bussonnier in :gh:`106676`.) + +* Expressions/Statements whose prefix is a pdb command are now correctly + identified and executed. + (Contributed by Tian Gao in :gh:`108464`.) + +* ``sys.path[0]`` will no longer be replaced by the directory of the script + being debugged when ``sys.flags.safe_path`` is set (via the :option:`-P` + command line option or :envvar:`PYTHONSAFEPATH` environment variable). + (Contributed by Tian Gao and Christian Walther in :gh:`111762`.) + +re +-- +* Rename :exc:`!re.error` to :exc:`re.PatternError` for improved clarity. + :exc:`!re.error` is kept for backward compatibility. + +sqlite3 +------- + +* A :exc:`ResourceWarning` is now emitted if a :class:`sqlite3.Connection` + object is not :meth:`closed ` explicitly. + (Contributed by Erlend E. Aasland in :gh:`105539`.) + +subprocess +---------- + +* The :mod:`subprocess` module now uses the :func:`os.posix_spawn` function in + more situations. Notably in the default case of ``close_fds=True`` on more + recent versions of platforms including Linux, FreeBSD, and Solaris where the + C library provides :c:func:`!posix_spawn_file_actions_addclosefrom_np`. + On Linux this should perform similar to our existing Linux :c:func:`!vfork` + based code. A private control knob :attr:`!subprocess._USE_POSIX_SPAWN` can + be set to ``False`` if you need to force :mod:`subprocess` not to ever use + :func:`os.posix_spawn`. Please report your reason and platform details in + the CPython issue tracker if you set this so that we can improve our API + selection logic for everyone. + (Contributed by Jakub Kulik in :gh:`113117`.) + +sys +--- + +* Add the :func:`sys._is_interned` function to test if the string was interned. + This function is not guaranteed to exist in all implementations of Python. + (Contributed by Serhiy Storchaka in :gh:`78573`.) + +tkinter +------- + +* Add :mod:`tkinter` widget methods: + :meth:`!tk_busy_hold`, :meth:`!tk_busy_configure`, + :meth:`!tk_busy_cget`, :meth:`!tk_busy_forget`, + :meth:`!tk_busy_current`, and :meth:`!tk_busy_status`. + (Contributed by Miguel, klappnase and Serhiy Storchaka in :gh:`72684`.) + +* Add support of the "vsapi" element type in + the :meth:`~tkinter.ttk.Style.element_create` method of + :class:`tkinter.ttk.Style`. + (Contributed by Serhiy Storchaka in :gh:`68166`.) traceback --------- -* Add *show_group* paramter to :func:`traceback.TracebackException.format_exception_only` +* Add *show_group* parameter to :func:`traceback.TracebackException.format_exception_only` to format the nested exceptions of a :exc:`BaseExceptionGroup` instance, recursively. (Contributed by Irit Katriel in :gh:`105292`.) +* Add the field *exc_type_str* to :class:`~traceback.TracebackException`, which + holds a string display of the *exc_type*. Deprecate the field *exc_type* + which holds the type object itself. Add parameter *save_exc_type* (default + ``True``) to indicate whether ``exc_type`` should be saved. + (Contributed by Irit Katriel in :gh:`112332`.) + typing ------ @@ -159,12 +413,43 @@ typing check whether a class is a :class:`typing.Protocol`. (Contributed by Jelle Zijlstra in :gh:`104873`.) +unicodedata +----------- + +* The Unicode database has been updated to version 15.1.0. (Contributed by + James Gerity in :gh:`109559`.) + +venv +---- + +* Add support for adding source control management (SCM) ignore files to a + virtual environment's directory. By default, Git is supported. This is + implemented as opt-in via the API which can be extended to support other SCMs + (:class:`venv.EnvBuilder` and :func:`venv.create`), and opt-out via the CLI + (using ``--without-scm-ignore-files``). (Contributed by Brett Cannon in + :gh:`108125`.) + +warnings +-------- + +* The new :func:`warnings.deprecated` decorator provides a way to communicate + deprecations to :term:`static type checkers ` and + to warn on usage of deprecated classes and functions. A runtime deprecation + warning may also be emitted when a decorated function or class is used at runtime. + See :pep:`702`. (Contributed by Jelle Zijlstra in :gh:`104003`.) + Optimizations ============= * :func:`textwrap.indent` is now ~30% faster than before for large input. (Contributed by Inada Naoki in :gh:`107369`.) +* The :mod:`subprocess` module uses :func:`os.posix_spawn` in more situations + including the default where ``close_fds=True`` on many modern platforms. This + should provide a noteworthy performance increase launching processes on + FreeBSD and Solaris. See the ``subprocess`` section above for details. + (Contributed by Jakub Kulik in :gh:`113117`.) + Deprecated ========== @@ -187,10 +472,28 @@ Deprecated practice. (Contributed by Victor Stinner in :gh:`106535`.) -* :mod:`typing`: Creating a :class:`typing.NamedTuple` class using keyword arguments to denote - the fields (``NT = NamedTuple("NT", x=int, y=int)``) is deprecated, and will - be disallowed in Python 3.15. Use the class-based syntax or the functional - syntax instead. (Contributed by Alex Waygood in :gh:`105566`.) +* :mod:`http.server`: :class:`http.server.CGIHTTPRequestHandler` now emits a + :exc:`DeprecationWarning` as it will be removed in 3.15. Process based CGI + http servers have been out of favor for a very long time. This code was + outdated, unmaintained, and rarely used. It has a high potential for both + security and functionality bugs. This includes removal of the ``--cgi`` + flag to the ``python -m http.server`` command line in 3.15. + +* :mod:`sys`: :func:`sys._enablelegacywindowsfsencoding` function. + Replace it with :envvar:`PYTHONLEGACYWINDOWSFSENCODING` environment variable. + (Contributed by Inada Naoki in :gh:`73427`.) + +* :mod:`traceback`: + + * The field *exc_type* of :class:`traceback.TracebackException` is + deprecated. Use *exc_type_str* instead. + +* :mod:`typing`: + + * Creating a :class:`typing.NamedTuple` class using keyword arguments to denote + the fields (``NT = NamedTuple("NT", x=int, y=int)``) is deprecated, and will + be disallowed in Python 3.15. Use the class-based syntax or the functional + syntax instead. (Contributed by Alex Waygood in :gh:`105566`.) * When using the functional syntax to create a :class:`typing.NamedTuple` class or a :class:`typing.TypedDict` class, failing to pass a value to the @@ -219,6 +522,53 @@ Deprecated They will be removed in Python 3.15. (Contributed by Victor Stinner in :gh:`105096`.) +* Passing more than one positional argument to :func:`sqlite3.connect` and the + :class:`sqlite3.Connection` constructor is deprecated. The remaining + parameters will become keyword-only in Python 3.15. + + Deprecate passing name, number of arguments, and the callable as keyword + arguments, for the following :class:`sqlite3.Connection` APIs: + + * :meth:`~sqlite3.Connection.create_function` + * :meth:`~sqlite3.Connection.create_aggregate` + + Deprecate passing the callback callable by keyword for the following + :class:`sqlite3.Connection` APIs: + + * :meth:`~sqlite3.Connection.set_authorizer` + * :meth:`~sqlite3.Connection.set_progress_handler` + * :meth:`~sqlite3.Connection.set_trace_callback` + + The affected parameters will become positional-only in Python 3.15. + + (Contributed by Erlend E. Aasland in :gh:`107948` and :gh:`108278`.) + +* The ``dis.HAVE_ARGUMENT`` separator is deprecated. Check membership + in :data:`~dis.hasarg` instead. + (Contributed by Irit Katriel in :gh:`109319`.) + +* Deprecate non-standard format specifier "N" for :class:`decimal.Decimal`. + It was not documented and only supported in the C implementation. + (Contributed by Serhiy Storchaka in :gh:`89902`.) + +* Emit deprecation warning for non-integer numbers in :mod:`gettext` functions + and methods that consider plural forms even if the translation was not found. + (Contributed by Serhiy Storchaka in :gh:`88434`.) + +* Calling :meth:`frame.clear` on a suspended frame raises :exc:`RuntimeError` + (as has always been the case for an executing frame). + (Contributed by Irit Katriel in :gh:`79932`.) + +* Assignment to a function's :attr:`~function.__code__` attribute where the new code + object's type does not match the function's type, is deprecated. The + different types are: plain function, generator, async generator and + coroutine. + (Contributed by Irit Katriel in :gh:`81137`.) + +* Deprecate undocumented :func:`!pydoc.ispackage` function. + (Contributed by Zackery Spytz in :gh:`64020`.) + + Pending Removal in Python 3.14 ------------------------------ @@ -307,7 +657,8 @@ Pending Removal in Python 3.14 * date and datetime adapter, date and timestamp converter: see the :mod:`sqlite3` documentation for suggested replacement recipes. -* :class:`types.CodeType`: Accessing ``co_lnotab`` was deprecated in :pep:`626` +* :class:`types.CodeType`: Accessing :attr:`~codeobject.co_lnotab` was + deprecated in :pep:`626` since 3.10 and was planned to be removed in 3.12, but it only got a proper :exc:`DeprecationWarning` in 3.12. May be removed in 3.14. @@ -327,6 +678,18 @@ Pending Removal in Python 3.14 Pending Removal in Python 3.15 ------------------------------ +* :class:`http.server.CGIHTTPRequestHandler` will be removed along with its + related ``--cgi`` flag to ``python -m http.server``. It was obsolete and + rarely used. No direct replacement exists. *Anything* is better than CGI + to interface a web server with a request handler. + +* :class:`locale`: :func:`locale.getdefaultlocale` was deprecated in Python 3.11 + and originally planned for removal in Python 3.13 (:gh:`90817`), + but removal has been postponed to Python 3.15. + Use :func:`locale.setlocale()`, :func:`locale.getencoding()` and + :func:`locale.getlocale()` instead. + (Contributed by Hugo van Kemenade in :gh:`111187`.) + * :class:`typing.NamedTuple`: * The undocumented keyword argument syntax for creating NamedTuple classes @@ -352,6 +715,12 @@ Pending Removal in Python 3.15 They will be removed in Python 3.15. (Contributed by Victor Stinner in :gh:`105096`.) +* Passing any arguments to :func:`threading.RLock` is now deprecated. + C version allows any numbers of args and kwargs, + but they are just ignored. Python version does not allow any arguments. + All arguments will be removed from :func:`threading.RLock` in Python 3.15. + (Contributed by Nikita Sobolev in :gh:`102029`.) + Pending Removal in Python 3.16 ------------------------------ @@ -394,8 +763,8 @@ although there is currently no date scheduled for their removal. * Delegation of ``int()`` to ``__trunc__()`` method. * :mod:`calendar`: ``calendar.January`` and ``calendar.February`` constants are - deprecated and replaced by :data:`calendar.Month.JANUARY` and - :data:`calendar.Month.FEBRUARY`. + deprecated and replaced by :data:`calendar.JANUARY` and + :data:`calendar.FEBRUARY`. (Contributed by Prince Roshan in :gh:`103636`.) * :mod:`datetime`: @@ -418,25 +787,6 @@ although there is currently no date scheduled for their removal. * ``EntryPoints`` tuple interface. * Implicit ``None`` on return values. -* :mod:`importlib.resources`: First parameter to files is renamed to 'anchor'. -* :mod:`importlib.resources` deprecated methods: - - * ``contents()`` - * ``is_resource()`` - * ``open_binary()`` - * ``open_text()`` - * ``path()`` - * ``read_binary()`` - * ``read_text()`` - - Use ``files()`` instead. Refer to `importlib-resources: Migrating from Legacy - `_ - for migration advice. - -* :func:`locale.getdefaultlocale`: use :func:`locale.setlocale()`, - :func:`locale.getencoding()` and :func:`locale.getlocale()` instead - (:gh:`90817`) - * :mod:`mailbox`: Use of StringIO input and text mode is deprecated, use BytesIO and binary mode instead. @@ -471,7 +821,8 @@ although there is currently no date scheduled for their removal. * :mod:`!sre_compile`, :mod:`!sre_constants` and :mod:`!sre_parse` modules. -* ``types.CodeType.co_lnotab``: use the ``co_lines`` attribute instead. +* :attr:`codeobject.co_lnotab`: use the :meth:`codeobject.co_lines` method + instead. * :class:`typing.Text` (:gh:`92332`). @@ -521,178 +872,166 @@ although there is currently no date scheduled for their removal. Removed ======= -* :pep:`594`: Remove the :mod:`!telnetlib` module, deprecated in Python 3.11: - use the projects `telnetlib3 `_ or - `Exscript `_ instead. - (Contributed by Victor Stinner in :gh:`104773`.) +.. _whatsnew313-pep594: -* Remove the ``2to3`` program and the :mod:`!lib2to3` module, - deprecated in Python 3.11. - (Contributed by Victor Stinner in :gh:`104780`.) +PEP 594: dead batteries +----------------------- -* Namespaces ``typing.io`` and ``typing.re``, deprecated in Python 3.8, - are now removed. The items in those namespaces can be imported directly - from :mod:`typing`. (Contributed by Sebastian Rittau in :gh:`92871`.) +* :pep:`594` removed 19 modules from the standard library, + deprecated in Python 3.11: -* Remove the untested and undocumented :mod:`webbrowser` :class:`!MacOSX` class, - deprecated in Python 3.11. - Use the :class:`!MacOSXOSAScript` class (introduced in Python 3.2) instead. - (Contributed by Hugo van Kemenade in :gh:`104804`.) + * :mod:`!aifc`. + (Contributed by Victor Stinner in :gh:`104773`.) -* Remove support for using :class:`pathlib.Path` objects as context managers. - This functionality was deprecated and made a no-op in Python 3.9. + * :mod:`!audioop`. + (Contributed by Victor Stinner in :gh:`104773`.) -* Remove the undocumented :class:`!configparser.LegacyInterpolation` class, - deprecated in the docstring since Python 3.2, - and with a deprecation warning since Python 3.11. - (Contributed by Hugo van Kemenade in :gh:`104886`.) + * :mod:`!chunk`. + (Contributed by Victor Stinner in :gh:`104773`.) -* Remove the :meth:`!turtle.RawTurtle.settiltangle` method, - deprecated in docs since Python 3.1 - and with a deprecation warning since Python 3.11. - (Contributed by Hugo van Kemenade in :gh:`104876`.) - -* Removed the following :mod:`unittest` functions, deprecated in Python 3.11: - - * :func:`!unittest.findTestCases` - * :func:`!unittest.makeSuite` - * :func:`!unittest.getTestCaseNames` + * :mod:`!cgi` and :mod:`!cgitb`. - Use :class:`~unittest.TestLoader` methods instead: + * ``cgi.FieldStorage`` can typically be replaced with + :func:`urllib.parse.parse_qsl` for ``GET`` and ``HEAD`` requests, + and the :mod:`email.message` module or `multipart + `__ PyPI project for ``POST`` and + ``PUT``. - * :meth:`unittest.TestLoader.loadTestsFromModule` - * :meth:`unittest.TestLoader.loadTestsFromTestCase` - * :meth:`unittest.TestLoader.getTestCaseNames` + * ``cgi.parse()`` can be replaced by calling :func:`urllib.parse.parse_qs` + directly on the desired query string, except for ``multipart/form-data`` + input, which can be handled as described for ``cgi.parse_multipart()``. - (Contributed by Hugo van Kemenade in :gh:`104835`.) + * ``cgi.parse_header()`` can be replaced with the functionality in the + :mod:`email` package, which implements the same MIME RFCs. For example, + with :class:`email.message.EmailMessage`:: -* :pep:`594`: Remove the :mod:`!cgi` and :mod:`!cgitb` modules, - deprecated in Python 3.11. + from email.message import EmailMessage + msg = EmailMessage() + msg['content-type'] = 'application/json; charset="utf8"' + main, params = msg.get_content_type(), msg['content-type'].params - * ``cgi.FieldStorage`` can typically be replaced with - :func:`urllib.parse.parse_qsl` for ``GET`` and ``HEAD`` requests, and the - :mod:`email.message` module or `multipart - `__ PyPI project for ``POST`` and - ``PUT``. + * ``cgi.parse_multipart()`` can be replaced with the functionality in the + :mod:`email` package (e.g. :class:`email.message.EmailMessage` and + :class:`email.message.Message`) which implements the same MIME RFCs, or + with the `multipart `__ PyPI project. - * ``cgi.parse()`` can be replaced by calling :func:`urllib.parse.parse_qs` - directly on the desired query string, except for ``multipart/form-data`` - input, which can be handled as described for ``cgi.parse_multipart()``. + (Contributed by Victor Stinner in :gh:`104773`.) - * ``cgi.parse_multipart()`` can be replaced with the functionality in the - :mod:`email` package (e.g. :class:`email.message.EmailMessage` and - :class:`email.message.Message`) which implements the same MIME RFCs, or - with the `multipart `__ PyPI project. + * :mod:`!crypt` module and its private :mod:`!_crypt` extension. + The :mod:`hashlib` module is a potential replacement for certain use cases. + Otherwise, the following PyPI projects can be used: - * ``cgi.parse_header()`` can be replaced with the functionality in the - :mod:`email` package, which implements the same MIME RFCs. For example, - with :class:`email.message.EmailMessage`:: + * `bcrypt `_: + Modern password hashing for your software and your servers. + * `passlib `_: + Comprehensive password hashing framework supporting over 30 schemes. + * `argon2-cffi `_: + The secure Argon2 password hashing algorithm. + * `legacycrypt `_: + Wrapper to the POSIX crypt library call and associated functionality. - from email.message import EmailMessage - msg = EmailMessage() - msg['content-type'] = 'application/json; charset="utf8"' - main, params = msg.get_content_type(), msg['content-type'].params + (Contributed by Victor Stinner in :gh:`104773`.) - (Contributed by Victor Stinner in :gh:`104773`.) + * :mod:`!imghdr`: use the projects + `filetype `_, + `puremagic `_, + or `python-magic `_ instead. + (Contributed by Victor Stinner in :gh:`104773`.) -* :pep:`594`: Remove the :mod:`!sndhdr` module, deprecated in Python 3.11: use - the projects `filetype `_, `puremagic - `_, or `python-magic - `_ instead. - (Contributed by Victor Stinner in :gh:`104773`.) + * :mod:`!mailcap`. + The :mod:`mimetypes` module provides an alternative. + (Contributed by Victor Stinner in :gh:`104773`.) -* :pep:`594`: Remove the :mod:`!pipes` module, deprecated in Python 3.11: - use the :mod:`subprocess` module instead. - (Contributed by Victor Stinner in :gh:`104773`.) + * :mod:`!msilib`. + (Contributed by Zachary Ware in :gh:`104773`.) -* :pep:`594`: Remove the :mod:`!ossaudiodev` module, deprecated in Python 3.11: - use the `pygame project `_ for audio playback. - (Contributed by Victor Stinner in :gh:`104780`.) + * :mod:`!nis`. + (Contributed by Victor Stinner in :gh:`104773`.) -* :pep:`594`: Remove the :mod:`!sunau` module, deprecated in Python 3.11. - (Contributed by Victor Stinner in :gh:`104773`.) + * :mod:`!nntplib`: + the `PyPI nntplib project `_ + can be used instead. + (Contributed by Victor Stinner in :gh:`104773`.) -* :pep:`594`: Remove the :mod:`!mailcap` module, deprecated in Python 3.11. - The :mod:`mimetypes` module provides an alternative. - (Contributed by Victor Stinner in :gh:`104773`.) + * :mod:`!ossaudiodev`: use the + `pygame project `_ for audio playback. + (Contributed by Victor Stinner in :gh:`104780`.) -* :pep:`594`: Remove the :mod:`!spwd` module, deprecated in Python 3.11: - the `python-pam project `_ can be used - instead. - (Contributed by Victor Stinner in :gh:`104773`.) + * :mod:`!pipes`: use the :mod:`subprocess` module instead. + (Contributed by Victor Stinner in :gh:`104773`.) -* :pep:`594`: Remove the :mod:`!nntplib` module, deprecated in Python 3.11: - the `PyPI nntplib project `_ can be used - instead. - (Contributed by Victor Stinner in :gh:`104773`.) + * :mod:`!sndhdr`: use the projects + `filetype `_, + `puremagic `_, or + `python-magic `_ instead. + (Contributed by Victor Stinner in :gh:`104773`.) -* :pep:`594`: Remove the :mod:`!nis` module, deprecated in Python 3.11. - (Contributed by Victor Stinner in :gh:`104773`.) + * :mod:`!spwd`: + the `python-pam project `_ + can be used instead. + (Contributed by Victor Stinner in :gh:`104773`.) -* :pep:`594`: Remove the :mod:`!xdrlib` module, deprecated in Python 3.11. - (Contributed by Victor Stinner in :gh:`104773`.) + * :mod:`!sunau`. + (Contributed by Victor Stinner in :gh:`104773`.) -* :pep:`594`: Remove the :mod:`!msilib` module, deprecated in Python 3.11. - (Contributed by Zachary Ware in :gh:`104773`.) + * :mod:`!telnetlib`, use the projects + `telnetlib3 `_ or + `Exscript `_ instead. + (Contributed by Victor Stinner in :gh:`104773`.) -* :pep:`594`: Remove the :mod:`!crypt` module and its private :mod:`!_crypt` - extension, deprecated in Python 3.11. - The :mod:`hashlib` module is a potential replacement for certain use cases. - Otherwise, the following PyPI projects can be used: + * :mod:`!uu`: the :mod:`base64` module is a modern alternative. + (Contributed by Victor Stinner in :gh:`104773`.) - * `bcrypt `_: - Modern password hashing for your software and your servers. - * `passlib `_: - Comprehensive password hashing framework supporting over 30 schemes. - * `argon2-cffi `_: - The secure Argon2 password hashing algorithm. - * `legacycrypt `_: - Wrapper to the POSIX crypt library call and associated functionality. + * :mod:`!xdrlib`. + (Contributed by Victor Stinner in :gh:`104773`.) - (Contributed by Victor Stinner in :gh:`104773`.) +2to3 +---- -* :pep:`594`: Remove the :mod:`!uu` module, deprecated in Python 3.11: - the :mod:`base64` module is a modern alternative. - (Contributed by Victor Stinner in :gh:`104773`.) +* Remove the ``2to3`` program and the :mod:`!lib2to3` module, + deprecated in Python 3.11. + (Contributed by Victor Stinner in :gh:`104780`.) -* :pep:`594`: Remove the :mod:`!aifc` module, deprecated in Python 3.11. - (Contributed by Victor Stinner in :gh:`104773`.) +configparser +------------ -* :pep:`594`: Remove the :mod:`!audioop` module, deprecated in Python 3.11. - (Contributed by Victor Stinner in :gh:`104773`.) +* Remove the undocumented :class:`!configparser.LegacyInterpolation` class, + deprecated in the docstring since Python 3.2, + and with a deprecation warning since Python 3.11. + (Contributed by Hugo van Kemenade in :gh:`104886`.) -* :pep:`594`: Remove the :mod:`!chunk` module, deprecated in Python 3.11. - (Contributed by Victor Stinner in :gh:`104773`.) +importlib +--------- -* Remove support for the keyword-argument method of creating - :class:`typing.TypedDict` types, deprecated in Python 3.11. - (Contributed by Tomas Roun in :gh:`104786`.) +* Remove :mod:`importlib.resources` deprecated methods: -* :pep:`594`: Remove the :mod:`!imghdr` module, deprecated in Python 3.11: - use the projects - `filetype `_, - `puremagic `_, - or `python-magic `_ instead. - (Contributed by Victor Stinner in :gh:`104773`.) + * ``contents()`` + * ``is_resource()`` + * ``open_binary()`` + * ``open_text()`` + * ``path()`` + * ``read_binary()`` + * ``read_text()`` -* Remove the untested and undocumented :meth:`!unittest.TestProgram.usageExit` - method, deprecated in Python 3.11. - (Contributed by Hugo van Kemenade in :gh:`104992`.) + Use :func:`importlib.resources.files()` instead. Refer to `importlib-resources: Migrating from Legacy + `_ + for migration advice. + (Contributed by Jason R. Coombs in :gh:`106532`.) -* Remove the :mod:`!tkinter.tix` module, deprecated in Python 3.6. The - third-party Tix library which the module wrapped is unmaintained. - (Contributed by Zachary Ware in :gh:`75552`.) +* Remove deprecated :meth:`~object.__getitem__` access for + :class:`!importlib.metadata.EntryPoint` objects. + (Contributed by Jason R. Coombs in :gh:`113175`.) -* Remove the old trashcan macros ``Py_TRASHCAN_SAFE_BEGIN`` and - ``Py_TRASHCAN_SAFE_END``. They should be replaced by the new macros - ``Py_TRASHCAN_BEGIN`` and ``Py_TRASHCAN_END``. The new macros were - added in Python 3.8 and the old macros were deprecated in Python 3.11. - (Contributed by Irit Katriel in :gh:`105111`.) +locale +------ * Remove ``locale.resetlocale()`` function deprecated in Python 3.11: use ``locale.setlocale(locale.LC_ALL, "")`` instead. (Contributed by Victor Stinner in :gh:`104783`.) +logging +------- + * :mod:`logging`: Remove undocumented and untested ``Logger.warn()`` and ``LoggerAdapter.warn()`` methods and ``logging.warn()`` function. Deprecated since Python 3.3, they were aliases to the :meth:`logging.Logger.warning` @@ -700,6 +1039,69 @@ Removed :func:`logging.warning` function. (Contributed by Victor Stinner in :gh:`105376`.) +pathlib +------- + +* Remove support for using :class:`pathlib.Path` objects as context managers. + This functionality was deprecated and made a no-op in Python 3.9. + +re +-- + +* Remove undocumented, never working, and deprecated ``re.template`` function + and ``re.TEMPLATE`` flag (and ``re.T`` alias). + (Contributed by Serhiy Storchaka and Nikita Sobolev in :gh:`105687`.) + +tkinter +------- + +* Remove the :mod:`!tkinter.tix` module, deprecated in Python 3.6. The + third-party Tix library which the module wrapped is unmaintained. + (Contributed by Zachary Ware in :gh:`75552`.) + +turtle +------ + +* Remove the :meth:`!turtle.RawTurtle.settiltangle` method, + deprecated in docs since Python 3.1 + and with a deprecation warning since Python 3.11. + (Contributed by Hugo van Kemenade in :gh:`104876`.) + +typing +------ + +* Namespaces ``typing.io`` and ``typing.re``, deprecated in Python 3.8, + are now removed. The items in those namespaces can be imported directly + from :mod:`typing`. (Contributed by Sebastian Rittau in :gh:`92871`.) + +* Remove support for the keyword-argument method of creating + :class:`typing.TypedDict` types, deprecated in Python 3.11. + (Contributed by Tomas Roun in :gh:`104786`.) + +unittest +-------- + +* Removed the following :mod:`unittest` functions, deprecated in Python 3.11: + + * :func:`!unittest.findTestCases` + * :func:`!unittest.makeSuite` + * :func:`!unittest.getTestCaseNames` + + Use :class:`~unittest.TestLoader` methods instead: + + * :meth:`unittest.TestLoader.loadTestsFromModule` + * :meth:`unittest.TestLoader.loadTestsFromTestCase` + * :meth:`unittest.TestLoader.getTestCaseNames` + + (Contributed by Hugo van Kemenade in :gh:`104835`.) + +* Remove the untested and undocumented :meth:`!unittest.TestProgram.usageExit` + method, deprecated in Python 3.11. + (Contributed by Hugo van Kemenade in :gh:`104992`.) + +urllib +------ + * Remove *cafile*, *capath* and *cadefault* parameters of the :func:`urllib.request.urlopen` function, deprecated in Python 3.6: use the *context* parameter instead. Please use @@ -708,15 +1110,32 @@ Removed certificates for you. (Contributed by Victor Stinner in :gh:`105382`.) +webbrowser +---------- + +* Remove the untested and undocumented :mod:`webbrowser` :class:`!MacOSX` class, + deprecated in Python 3.11. + Use the :class:`!MacOSXOSAScript` class (introduced in Python 3.2) instead. + (Contributed by Hugo van Kemenade in :gh:`104804`.) + * Remove deprecated ``webbrowser.MacOSXOSAScript._name`` attribute. Use :attr:`webbrowser.MacOSXOSAScript.name ` attribute instead. (Contributed by Nikita Sobolev in :gh:`105546`.) -* Remove undocumented, never working, and deprecated ``re.template`` function - and ``re.TEMPLATE`` flag (and ``re.T`` alias). - (Contributed by Serhiy Storchaka and Nikita Sobolev in :gh:`105687`.) +Others +------ + +* None yet + +CPython bytecode changes +======================== +* The oparg of ``YIELD_VALUE`` is now ``1`` if the yield is part of a + yield-from or await, and ``0`` otherwise. The oparg of ``RESUME`` was + changed to add a bit indicating whether the except-depth is 1, which + is needed to optimize closing of generators. + (Contributed by Irit Katriel in :gh:`111354`.) Porting to Python 3.13 ====================== @@ -724,46 +1143,67 @@ Porting to Python 3.13 This section lists previously described changes and other bugfixes that may require changes to your code. -* The old trashcan macros ``Py_TRASHCAN_SAFE_BEGIN`` and ``Py_TRASHCAN_SAFE_END`` - were removed. They should be replaced by the new macros ``Py_TRASHCAN_BEGIN`` - and ``Py_TRASHCAN_END``. +Changes in the Python API +------------------------- - A tp_dealloc function that has the old macros, such as:: +* :meth:`!tkinter.Text.count` now always returns an integer if one or less + counting options are specified. + Previously it could return a single count as a 1-tuple, an integer (only if + option ``"update"`` was specified) or ``None`` if no items found. + The result is now the same if ``wantobjects`` is set to ``0``. + (Contributed by Serhiy Storchaka in :gh:`97928`.) - static void - mytype_dealloc(mytype *p) - { - PyObject_GC_UnTrack(p); - Py_TRASHCAN_SAFE_BEGIN(p); - ... - Py_TRASHCAN_SAFE_END - } +* Functions :c:func:`PyDict_GetItem`, :c:func:`PyDict_GetItemString`, + :c:func:`PyMapping_HasKey`, :c:func:`PyMapping_HasKeyString`, + :c:func:`PyObject_HasAttr`, :c:func:`PyObject_HasAttrString`, and + :c:func:`PySys_GetObject`, which clear all errors occurred during calling + the function, report now them using :func:`sys.unraisablehook`. + You can consider to replace these functions with other functions as + recomended in the documentation. + (Contributed by Serhiy Storchaka in :gh:`106672`.) - should migrate to the new macros as follows:: +* An :exc:`OSError` is now raised by :func:`getpass.getuser` for any failure to + retrieve a username, instead of :exc:`ImportError` on non-Unix platforms or + :exc:`KeyError` on Unix platforms where the password database is empty. - static void - mytype_dealloc(mytype *p) - { - PyObject_GC_UnTrack(p); - Py_TRASHCAN_BEGIN(p, mytype_dealloc) - ... - Py_TRASHCAN_END - } +* The :mod:`threading` module now expects the :mod:`!_thread` module to have + an ``_is_main_interpreter`` attribute. It is a function with no + arguments that returns ``True`` if the current interpreter is the + main interpreter. - Note that ``Py_TRASHCAN_BEGIN`` has a second argument which - should be the deallocation function it is in. + Any library or application that provides a custom ``_thread`` module + must provide ``_is_main_interpreter()``, just like the module's + other "private" attributes. + (See :gh:`112826`.) + +* :class:`mailbox.Maildir` now ignores files with a leading dot. + (Contributed by Zackery Spytz in :gh:`65559`.) Build Changes ============= * Autoconf 2.71 and aclocal 1.16.4 is now required to regenerate - :file:`!configure`. + the :file:`configure` script. (Contributed by Christian Heimes in :gh:`89886`.) * SQLite 3.15.2 or newer is required to build the :mod:`sqlite3` extension module. (Contributed by Erlend Aasland in :gh:`105875`.) +* Python built with :file:`configure` :option:`--with-trace-refs` (tracing + references) is now ABI compatible with Python release build and + :ref:`debug build `. + (Contributed by Victor Stinner in :gh:`108634`.) + +* Building CPython now requires a compiler with support for the C11 atomic + library, GCC built-in atomic functions, or MSVC interlocked intrinsics. + +* The ``errno``, ``md5``, ``resource``, ``winsound``, ``_ctypes_test``, + ``_multiprocessing.posixshmem``, ``_scproxy``, ``_stat``, + ``_testimportmultiple`` and ``_uuid`` C extensions are now built with the + :ref:`limited C API `. + (Contributed by Victor Stinner in :gh:`85283`.) + C API Changes ============= @@ -777,6 +1217,16 @@ New Features APIs accepting the format codes always use ``Py_ssize_t`` for ``#`` formats. (Contributed by Inada Naoki in :gh:`104922`.) +* The *keywords* parameter of :c:func:`PyArg_ParseTupleAndKeywords` and + :c:func:`PyArg_VaParseTupleAndKeywords` has now type :c:expr:`char * const *` + in C and :c:expr:`const char * const *` in C++, instead of :c:expr:`char **`. + It makes these functions compatible with arguments of type + :c:expr:`const char * const *`, :c:expr:`const char **` or + :c:expr:`char * const *` in C++ and :c:expr:`char * const *` in C + without an explicit type cast. + This can be overridden with the :c:macro:`PY_CXX_CONST` macro. + (Contributed by Serhiy Storchaka in :gh:`65210`.) + * Add :c:func:`PyImport_AddModuleRef`: similar to :c:func:`PyImport_AddModule`, but return a :term:`strong reference` instead of a :term:`borrowed reference`. @@ -803,10 +1253,21 @@ New Features be treated as a failure. (Contributed by Serhiy Storchaka in :gh:`106307`.) +* Add fixed variants of functions which silently ignore errors: + + - :c:func:`PyObject_HasAttrWithError` replaces :c:func:`PyObject_HasAttr`. + - :c:func:`PyObject_HasAttrStringWithError` replaces :c:func:`PyObject_HasAttrString`. + - :c:func:`PyMapping_HasKeyWithError` replaces :c:func:`PyMapping_HasKey`. + - :c:func:`PyMapping_HasKeyStringWithError` replaces :c:func:`PyMapping_HasKeyString`. + + New functions return not only ``1`` for true and ``0`` for false, but also + ``-1`` for error. + + (Contributed by Serhiy Storchaka in :gh:`108511`.) + * If Python is built in :ref:`debug mode ` or :option:`with assertions <--with-assertions>`, :c:func:`PyTuple_SET_ITEM` and :c:func:`PyList_SET_ITEM` now check the index argument with an assertion. - If the assertion fails, make sure that the size is set before. (Contributed by Victor Stinner in :gh:`106168`.) * Add :c:func:`PyModule_Add` function: similar to @@ -821,12 +1282,150 @@ New Features not needed. (Contributed by Victor Stinner in :gh:`106004`.) +* Added :c:func:`PyDict_ContainsString` function: same as + :c:func:`PyDict_Contains`, but *key* is specified as a :c:expr:`const char*` + UTF-8 encoded bytes string, rather than a :c:expr:`PyObject*`. + (Contributed by Victor Stinner in :gh:`108314`.) + +* Add :c:func:`Py_IsFinalizing` function: check if the main Python interpreter is + :term:`shutting down `. + (Contributed by Victor Stinner in :gh:`108014`.) + +* Add :c:func:`PyLong_AsInt` function: similar to :c:func:`PyLong_AsLong`, but + store the result in a C :c:expr:`int` instead of a C :c:expr:`long`. + Previously, it was known as the private function :c:func:`!_PyLong_AsInt` + (with an underscore prefix). + (Contributed by Victor Stinner in :gh:`108014`.) + +* Python built with :file:`configure` :option:`--with-trace-refs` (tracing + references) now supports the :ref:`Limited API `. + (Contributed by Victor Stinner in :gh:`108634`.) + +* Add :c:func:`PyObject_VisitManagedDict` and + :c:func:`PyObject_ClearManagedDict` functions which must be called by the + traverse and clear functions of a type using + :c:macro:`Py_TPFLAGS_MANAGED_DICT` flag. The `pythoncapi-compat project + `__ can be used to get these + functions on Python 3.11 and 3.12. + (Contributed by Victor Stinner in :gh:`107073`.) + +* Add :c:func:`PyUnicode_EqualToUTF8AndSize` and :c:func:`PyUnicode_EqualToUTF8` + functions: compare Unicode object with a :c:expr:`const char*` UTF-8 encoded + string and return true (``1``) if they are equal, or false (``0``) otherwise. + These functions do not raise exceptions. + (Contributed by Serhiy Storchaka in :gh:`110289`.) + +* Add :c:func:`PyThreadState_GetUnchecked()` function: similar to + :c:func:`PyThreadState_Get()`, but don't kill the process with a fatal error + if it is NULL. The caller is responsible to check if the result is NULL. + Previously, the function was private and known as + ``_PyThreadState_UncheckedGet()``. + (Contributed by Victor Stinner in :gh:`108867`.) + +* Add :c:func:`PySys_AuditTuple` function: similar to :c:func:`PySys_Audit`, + but pass event arguments as a Python :class:`tuple` object. + (Contributed by Victor Stinner in :gh:`85283`.) + +* :c:func:`PyArg_ParseTupleAndKeywords` now supports non-ASCII keyword + parameter names. + (Contributed by Serhiy Storchaka in :gh:`110815`.) + +* Add :c:func:`PyMem_RawMalloc`, :c:func:`PyMem_RawCalloc`, + :c:func:`PyMem_RawRealloc` and :c:func:`PyMem_RawFree` to the limited C API + (version 3.13). + (Contributed by Victor Stinner in :gh:`85283`.) + +* Add :c:func:`PySys_Audit` and :c:func:`PySys_AuditTuple` functions to the + limited C API. + (Contributed by Victor Stinner in :gh:`85283`.) + +* Add :c:func:`PyErr_FormatUnraisable` function: similar to + :c:func:`PyErr_WriteUnraisable`, but allow to customize the warning mesage. + (Contributed by Serhiy Storchaka in :gh:`108082`.) + +* Add :c:func:`PyList_Extend` and :c:func:`PyList_Clear` functions: similar to + Python ``list.extend()`` and ``list.clear()`` methods. + (Contributed by Victor Stinner in :gh:`111138`.) + +* Add :c:func:`PyDict_Pop` and :c:func:`PyDict_PopString` functions: remove a + key from a dictionary and optionally return the removed value. This is + similar to :meth:`dict.pop`, but without the default value and not raising + :exc:`KeyError` if the key missing. + (Contributed by Stefan Behnel and Victor Stinner in :gh:`111262`.) + +* Add :c:func:`Py_HashPointer` function to hash a pointer. + (Contributed by Victor Stinner in :gh:`111545`.) + + Porting to Python 3.13 ---------------------- +* ``Python.h`` no longer includes the ```` standard header. It was + included for the ``finite()`` function which is now provided by the + ```` header. It should now be included explicitly if needed. Remove + also the ``HAVE_IEEEFP_H`` macro. + (Contributed by Victor Stinner in :gh:`108765`.) + +* ``Python.h`` no longer includes these standard header files: ````, + ```` and ````. If needed, they should now be + included explicitly. For example, ```` provides the ``clock()`` and + ``gmtime()`` functions, ```` provides the ``select()`` + function, and ```` provides the ``futimes()``, ``gettimeofday()`` + and ``setitimer()`` functions. + (Contributed by Victor Stinner in :gh:`108765`.) + +* If the :c:macro:`Py_LIMITED_API` macro is defined, :c:macro:`!Py_BUILD_CORE`, + :c:macro:`!Py_BUILD_CORE_BUILTIN` and :c:macro:`!Py_BUILD_CORE_MODULE` macros + are now undefined by ````. + (Contributed by Victor Stinner in :gh:`85283`.) + +* The old trashcan macros ``Py_TRASHCAN_SAFE_BEGIN`` and ``Py_TRASHCAN_SAFE_END`` + were removed. They should be replaced by the new macros ``Py_TRASHCAN_BEGIN`` + and ``Py_TRASHCAN_END``. + + A tp_dealloc function that has the old macros, such as:: + + static void + mytype_dealloc(mytype *p) + { + PyObject_GC_UnTrack(p); + Py_TRASHCAN_SAFE_BEGIN(p); + ... + Py_TRASHCAN_SAFE_END + } + + should migrate to the new macros as follows:: + + static void + mytype_dealloc(mytype *p) + { + PyObject_GC_UnTrack(p); + Py_TRASHCAN_BEGIN(p, mytype_dealloc) + ... + Py_TRASHCAN_END + } + + Note that ``Py_TRASHCAN_BEGIN`` has a second argument which + should be the deallocation function it is in. + +* On Windows, ``Python.h`` no longer includes the ```` standard + header file. If needed, it should now be included explicitly. For example, it + provides ``offsetof()`` function, and ``size_t`` and ``ptrdiff_t`` types. + Including ```` explicitly was already needed by all other + platforms, the ``HAVE_STDDEF_H`` macro is only defined on Windows. + (Contributed by Victor Stinner in :gh:`108765`.) + + Deprecated ---------- +* Passing optional arguments *maxsplit*, *count* and *flags* in module-level + functions :func:`re.split`, :func:`re.sub` and :func:`re.subn` as positional + arguments is now deprecated. + In future Python versions these parameters will be + :ref:`keyword-only `. + (Contributed by Serhiy Storchaka in :gh:`56166`.) + * Deprecate the old ``Py_UNICODE`` and ``PY_UNICODE_TYPE`` types: use directly the :c:type:`wchar_t` type instead. Since Python 3.3, ``Py_UNICODE`` and ``PY_UNICODE_TYPE`` are just aliases to :c:type:`wchar_t`. @@ -863,6 +1462,14 @@ Deprecated Removed ------- +* Removed chained :class:`classmethod` descriptors (introduced in + :issue:`19072`). This can no longer be used to wrap other descriptors + such as :class:`property`. The core design of this feature was flawed + and caused a number of downstream problems. To "pass-through" a + :class:`classmethod`, consider using the :attr:`!__wrapped__` + attribute that was added in Python 3.10. (Contributed by Raymond + Hettinger in :gh:`89519`.) + * Remove many APIs (functions, macros, variables) with names prefixed by ``_Py`` or ``_PY`` (considered as private API). If your project is affected by one of these removals and you consider that the removed API should remain @@ -889,37 +1496,37 @@ Removed * Remove old buffer protocols deprecated in Python 3.0. Use :ref:`bufferobjects` instead. - * :c:func:`!PyObject_CheckReadBuffer`: Use :c:func:`PyObject_CheckBuffer` to - test if the object supports the buffer protocol. - Note that :c:func:`PyObject_CheckBuffer` doesn't guarantee that - :c:func:`PyObject_GetBuffer` will succeed. - To test if the object is actually readable, see the next example - of :c:func:`PyObject_GetBuffer`. + * :c:func:`!PyObject_CheckReadBuffer`: Use :c:func:`PyObject_CheckBuffer` to + test if the object supports the buffer protocol. + Note that :c:func:`PyObject_CheckBuffer` doesn't guarantee that + :c:func:`PyObject_GetBuffer` will succeed. + To test if the object is actually readable, see the next example + of :c:func:`PyObject_GetBuffer`. - * :c:func:`!PyObject_AsCharBuffer`, :c:func:`!PyObject_AsReadBuffer`: - :c:func:`PyObject_GetBuffer` and :c:func:`PyBuffer_Release` instead: + * :c:func:`!PyObject_AsCharBuffer`, :c:func:`!PyObject_AsReadBuffer`: + :c:func:`PyObject_GetBuffer` and :c:func:`PyBuffer_Release` instead: - .. code-block:: c + .. code-block:: c - Py_buffer view; - if (PyObject_GetBuffer(obj, &view, PyBUF_SIMPLE) < 0) { - return NULL; - } - // Use `view.buf` and `view.len` to read from the buffer. - // You may need to cast buf as `(const char*)view.buf`. - PyBuffer_Release(&view); + Py_buffer view; + if (PyObject_GetBuffer(obj, &view, PyBUF_SIMPLE) < 0) { + return NULL; + } + // Use `view.buf` and `view.len` to read from the buffer. + // You may need to cast buf as `(const char*)view.buf`. + PyBuffer_Release(&view); - * :c:func:`!PyObject_AsWriteBuffer`: Use - :c:func:`PyObject_GetBuffer` and :c:func:`PyBuffer_Release` instead: + * :c:func:`!PyObject_AsWriteBuffer`: Use + :c:func:`PyObject_GetBuffer` and :c:func:`PyBuffer_Release` instead: - .. code-block:: c + .. code-block:: c - Py_buffer view; - if (PyObject_GetBuffer(obj, &view, PyBUF_WRITABLE) < 0) { - return NULL; - } - // Use `view.buf` and `view.len` to write to the buffer. - PyBuffer_Release(&view); + Py_buffer view; + if (PyObject_GetBuffer(obj, &view, PyBUF_WRITABLE) < 0) { + return NULL; + } + // Use `view.buf` and `view.len` to write to the buffer. + PyBuffer_Release(&view); (Contributed by Inada Naoki in :gh:`85275`.) @@ -936,13 +1543,21 @@ Removed * ``Py_SetPath()``: set :c:member:`PyConfig.module_search_paths` instead. * ``Py_SetProgramName()``: set :c:member:`PyConfig.program_name` instead. * ``Py_SetPythonHome()``: set :c:member:`PyConfig.home` instead. - * ``Py_SetStandardStreamEncoding()``: set :c:member:`PyConfig.stdio_encoding` instead. + * ``Py_SetStandardStreamEncoding()``: set :c:member:`PyConfig.stdio_encoding` + instead, and set also maybe :c:member:`PyConfig.legacy_windows_stdio` (on + Windows). * ``_Py_SetProgramFullPath()``: set :c:member:`PyConfig.executable` instead. Use the new :c:type:`PyConfig` API of the :ref:`Python Initialization Configuration ` instead (:pep:`587`), added to Python 3.8. (Contributed by Victor Stinner in :gh:`105145`.) +* Remove the old trashcan macros ``Py_TRASHCAN_SAFE_BEGIN`` and + ``Py_TRASHCAN_SAFE_END``. They should be replaced by the new macros + ``Py_TRASHCAN_BEGIN`` and ``Py_TRASHCAN_END``. The new macros were + added in Python 3.8 and the old macros were deprecated in Python 3.11. + (Contributed by Irit Katriel in :gh:`105111`.) + * Remove ``PyEval_InitThreads()`` and ``PyEval_ThreadsInitialized()`` functions, deprecated in Python 3.9. Since Python 3.7, ``Py_Initialize()`` always creates the GIL: calling ``PyEval_InitThreads()`` did nothing and @@ -959,20 +1574,6 @@ Removed (Contributed by Victor Stinner in :gh:`105182`.) -* Remove the old aliases to functions calling functions which were kept for - backward compatibility with Python 3.8 provisional API: - - * ``_PyObject_CallMethodNoArgs()``: use ``PyObject_CallMethodNoArgs()`` - * ``_PyObject_CallMethodOneArg()``: use ``PyObject_CallMethodOneArg()`` - * ``_PyObject_CallOneArg()``: use ``PyObject_CallOneArg()`` - * ``_PyObject_FastCallDict()``: use ``PyObject_VectorcallDict()`` - * ``_PyObject_Vectorcall()``: use ``PyObject_Vectorcall()`` - * ``_PyObject_VectorcallMethod()``: use ``PyObject_VectorcallMethod()`` - * ``_PyVectorcall_Function()``: use ``PyVectorcall_Function()`` - - Just remove the underscore prefix to update your code. - (Contributed by Victor Stinner in :gh:`106084`.) - * Remove private ``_PyObject_FastCall()`` function: use ``PyObject_Vectorcall()`` which is available since Python 3.8 (:pep:`590`). @@ -1076,3 +1677,16 @@ removed, although there is currently no date scheduled for their removal. * :c:func:`PyThread_get_key_value`: use :c:func:`PyThread_tss_get`. * :c:func:`PyThread_delete_key_value`: use :c:func:`PyThread_tss_delete`. * :c:func:`PyThread_ReInitTLS`: no longer needed. + +* Remove undocumented ``PY_TIMEOUT_MAX`` constant from the limited C API. + (Contributed by Victor Stinner in :gh:`110014`.) + + +Regression Test Changes +======================= + +* Python built with :file:`configure` :option:`--with-pydebug` now + supports a :option:`-X presite=package.module <-X>` command-line + option. If used, it specifies a module that should be imported early + in the lifecycle of the interpreter, before ``site.py`` is executed. + (Contributed by Åukasz Langa in :gh:`110769`.) diff --git a/Doc/whatsnew/3.2.rst b/Doc/whatsnew/3.2.rst index ed1c1770fb0f51..9834bc03dc4b74 100644 --- a/Doc/whatsnew/3.2.rst +++ b/Doc/whatsnew/3.2.rst @@ -183,7 +183,7 @@ PEP 391: Dictionary Based Configuration for Logging The :mod:`logging` module provided two kinds of configuration, one style with function calls for each option or another style driven by an external file saved -in a :mod:`ConfigParser` format. Those options did not provide the flexibility +in a :mod:`configparser` format. Those options did not provide the flexibility to create configurations from JSON or YAML files, nor did they support incremental configuration, which is needed for specifying logger options from a command line. @@ -791,8 +791,9 @@ functools * The :func:`functools.wraps` decorator now adds a :attr:`__wrapped__` attribute pointing to the original callable function. This allows wrapped functions to - be introspected. It also copies :attr:`__annotations__` if defined. And now - it also gracefully skips over missing attributes such as :attr:`__doc__` which + be introspected. It also copies :attr:`~function.__annotations__` if + defined. And now it also gracefully skips over missing attributes such as + :attr:`~function.__doc__` which might not be defined for the wrapped callable. In the above example, the cache can be removed by recovering the original @@ -1857,12 +1858,12 @@ structure. asyncore -------- -:class:`asyncore.dispatcher` now provides a -:meth:`~asyncore.dispatcher.handle_accepted()` method +:class:`!asyncore.dispatcher` now provides a +:meth:`!handle_accepted()` method returning a ``(sock, addr)`` pair which is called when a connection has actually been established with a new remote endpoint. This is supposed to be used as a -replacement for old :meth:`~asyncore.dispatcher.handle_accept()` and avoids -the user to call :meth:`~asyncore.dispatcher.accept()` directly. +replacement for old :meth:`!handle_accept()` and avoids +the user to call :meth:`!accept()` directly. (Contributed by Giampaolo Rodolà; :issue:`6706`.) @@ -2133,7 +2134,7 @@ configparser The :mod:`configparser` module was modified to improve usability and predictability of the default parser and its supported INI syntax. The old -:class:`ConfigParser` class was removed in favor of :class:`SafeConfigParser` +:class:`!ConfigParser` class was removed in favor of :class:`!SafeConfigParser` which has in turn been renamed to :class:`~configparser.ConfigParser`. Support for inline comments is now turned off by default and section or option duplicates are not allowed in a single configuration source. @@ -2413,7 +2414,7 @@ when one operand is much larger than the other (patch by Andress Bennetts in (:issue:`1569291` by Alexander Belopolsky). The :class:`BaseHTTPRequestHandler` has more efficient buffering (:issue:`3709` by Andrew Schaaf). The :func:`operator.attrgetter` function has been sped-up (:issue:`10160` by -Christos Georgiou). And :class:`ConfigParser` loads multi-line arguments a bit +Christos Georgiou). And :class:`~configparser.ConfigParser` loads multi-line arguments a bit faster (:issue:`7113` by Åukasz Langa). @@ -2569,7 +2570,7 @@ Changes to Python's build process and to the C API include: to set :data:`sys.argv` without also modifying :data:`sys.path` (:issue:`5753`). -* :c:macro:`PyEval_CallObject` is now only available in macro form. The +* :c:func:`!PyEval_CallObject` is now only available in macro form. The function declaration, which was kept for backwards compatibility reasons, is now removed -- the macro was introduced in 1997 (:issue:`8276`). @@ -2613,8 +2614,8 @@ This section lists previously described changes and other bugfixes that may require changes to your code: * The :mod:`configparser` module has a number of clean-ups. The major change is - to replace the old :class:`ConfigParser` class with long-standing preferred - alternative :class:`SafeConfigParser`. In addition there are a number of + to replace the old :class:`!ConfigParser` class with long-standing preferred + alternative :class:`!SafeConfigParser`. In addition there are a number of smaller incompatibilities: * The interpolation syntax is now validated on @@ -2658,7 +2659,7 @@ require changes to your code: * "t#" format has been removed: use "s#" or "s*" instead * "w" and "w#" formats has been removed: use "w*" instead -* The :c:type:`PyCObject` type, deprecated in 3.1, has been removed. To wrap +* The :c:type:`!PyCObject` type, deprecated in 3.1, has been removed. To wrap opaque C pointers in Python objects, the :c:type:`PyCapsule` API should be used instead; the new type has a well-defined interface for passing typing safety information and a less complicated signature for calling a destructor. @@ -2731,15 +2732,15 @@ require changes to your code: (Contributed by Antoine Pitrou, :issue:`10272`.) -* The misleading functions :c:func:`PyEval_AcquireLock()` and - :c:func:`PyEval_ReleaseLock()` have been officially deprecated. The - thread-state aware APIs (such as :c:func:`PyEval_SaveThread()` - and :c:func:`PyEval_RestoreThread()`) should be used instead. +* The misleading functions :c:func:`!PyEval_AcquireLock` and + :c:func:`!PyEval_ReleaseLock` have been officially deprecated. The + thread-state aware APIs (such as :c:func:`PyEval_SaveThread` + and :c:func:`PyEval_RestoreThread`) should be used instead. -* Due to security risks, :func:`asyncore.handle_accept` has been deprecated, and - a new function, :func:`asyncore.handle_accepted`, was added to replace it. +* Due to security risks, :func:`!asyncore.handle_accept` has been deprecated, and + a new function, :func:`!asyncore.handle_accepted`, was added to replace it. (Contributed by Giampaolo Rodola in :issue:`6706`.) -* Due to the new :term:`GIL` implementation, :c:func:`PyEval_InitThreads()` - cannot be called before :c:func:`Py_Initialize()` anymore. +* Due to the new :term:`GIL` implementation, :c:func:`!PyEval_InitThreads` + cannot be called before :c:func:`Py_Initialize` anymore. diff --git a/Doc/whatsnew/3.3.rst b/Doc/whatsnew/3.3.rst index bcdc0222be6dea..29b4034e32821c 100644 --- a/Doc/whatsnew/3.3.rst +++ b/Doc/whatsnew/3.3.rst @@ -174,7 +174,7 @@ Features b or c are now hashable. (Contributed by Antoine Pitrou in :issue:`13411`.) * Arbitrary slicing of any 1-D arrays type is supported. For example, it - is now possible to reverse a memoryview in O(1) by using a negative step. + is now possible to reverse a memoryview in *O*\ (1) by using a negative step. API changes ----------- @@ -249,7 +249,7 @@ Changes introduced by :pep:`393` are the following: non-BMP code points. * The value of :data:`sys.maxunicode` is now always ``1114111`` (``0x10FFFF`` - in hexadecimal). The :c:func:`PyUnicode_GetMax` function still returns + in hexadecimal). The :c:func:`!PyUnicode_GetMax` function still returns either ``0xFFFF`` or ``0x10FFFF`` for backward compatibility, and it should not be used with the new Unicode API (see :issue:`13054`). @@ -917,12 +917,12 @@ abstract methods. The recommended approach to declaring abstract descriptors is now to provide :attr:`__isabstractmethod__` as a dynamically updated property. The built-in descriptors have been updated accordingly. - * :class:`abc.abstractproperty` has been deprecated, use :class:`property` - with :func:`abc.abstractmethod` instead. - * :class:`abc.abstractclassmethod` has been deprecated, use - :class:`classmethod` with :func:`abc.abstractmethod` instead. - * :class:`abc.abstractstaticmethod` has been deprecated, use - :class:`staticmethod` with :func:`abc.abstractmethod` instead. +* :class:`abc.abstractproperty` has been deprecated, use :class:`property` + with :func:`abc.abstractmethod` instead. +* :class:`abc.abstractclassmethod` has been deprecated, use + :class:`classmethod` with :func:`abc.abstractmethod` instead. +* :class:`abc.abstractstaticmethod` has been deprecated, use + :class:`staticmethod` with :func:`abc.abstractmethod` instead. (Contributed by Darren Dale in :issue:`11610`.) @@ -1052,7 +1052,7 @@ their ``__init__`` method (for example, file objects) or in their crypt ----- -Addition of salt and modular crypt format (hashing method) and the :func:`~!crypt.mksalt` +Addition of salt and modular crypt format (hashing method) and the :func:`!mksalt` function to the :mod:`!crypt` module. (:issue:`10924`) @@ -1060,32 +1060,32 @@ function to the :mod:`!crypt` module. curses ------ - * If the :mod:`curses` module is linked to the ncursesw library, use Unicode - functions when Unicode strings or characters are passed (e.g. - :c:func:`waddwstr`), and bytes functions otherwise (e.g. :c:func:`waddstr`). - * Use the locale encoding instead of ``utf-8`` to encode Unicode strings. - * :class:`curses.window` has a new :attr:`curses.window.encoding` attribute. - * The :class:`curses.window` class has a new :meth:`~curses.window.get_wch` - method to get a wide character - * The :mod:`curses` module has a new :meth:`~curses.unget_wch` function to - push a wide character so the next :meth:`~curses.window.get_wch` will return - it +* If the :mod:`curses` module is linked to the ncursesw library, use Unicode + functions when Unicode strings or characters are passed (e.g. + :c:func:`waddwstr`), and bytes functions otherwise (e.g. :c:func:`waddstr`). +* Use the locale encoding instead of ``utf-8`` to encode Unicode strings. +* :class:`curses.window` has a new :attr:`curses.window.encoding` attribute. +* The :class:`curses.window` class has a new :meth:`~curses.window.get_wch` + method to get a wide character +* The :mod:`curses` module has a new :meth:`~curses.unget_wch` function to + push a wide character so the next :meth:`~curses.window.get_wch` will return + it (Contributed by Iñigo Serna in :issue:`6755`.) datetime -------- - * Equality comparisons between naive and aware :class:`~datetime.datetime` - instances now return :const:`False` instead of raising :exc:`TypeError` - (:issue:`15006`). - * New :meth:`datetime.datetime.timestamp` method: Return POSIX timestamp - corresponding to the :class:`~datetime.datetime` instance. - * The :meth:`datetime.datetime.strftime` method supports formatting years - older than 1000. - * The :meth:`datetime.datetime.astimezone` method can now be - called without arguments to convert datetime instance to the system - timezone. +* Equality comparisons between naive and aware :class:`~datetime.datetime` + instances now return :const:`False` instead of raising :exc:`TypeError` + (:issue:`15006`). +* New :meth:`datetime.datetime.timestamp` method: Return POSIX timestamp + corresponding to the :class:`~datetime.datetime` instance. +* The :meth:`datetime.datetime.strftime` method supports formatting years + older than 1000. +* The :meth:`datetime.datetime.astimezone` method can now be + called without arguments to convert datetime instance to the system + timezone. .. _new-decimal: @@ -1210,25 +1210,25 @@ the ``Message`` object it is serializing. The default policy is The minimum set of controls implemented by all ``policy`` objects are: - .. tabularcolumns:: |l|L| +.. tabularcolumns:: |l|L| - =============== ======================================================= - max_line_length The maximum length, excluding the linesep character(s), - individual lines may have when a ``Message`` is - serialized. Defaults to 78. +=============== ======================================================= +max_line_length The maximum length, excluding the linesep character(s), + individual lines may have when a ``Message`` is + serialized. Defaults to 78. - linesep The character used to separate individual lines when a - ``Message`` is serialized. Defaults to ``\n``. +linesep The character used to separate individual lines when a + ``Message`` is serialized. Defaults to ``\n``. - cte_type ``7bit`` or ``8bit``. ``8bit`` applies only to a - ``Bytes`` ``generator``, and means that non-ASCII may - be used where allowed by the protocol (or where it - exists in the original input). +cte_type ``7bit`` or ``8bit``. ``8bit`` applies only to a + ``Bytes`` ``generator``, and means that non-ASCII may + be used where allowed by the protocol (or where it + exists in the original input). - raise_on_defect Causes a ``parser`` to raise error when defects are - encountered instead of adding them to the ``Message`` - object's ``defects`` list. - =============== ======================================================= +raise_on_defect Causes a ``parser`` to raise error when defects are + encountered instead of adding them to the ``Message`` + object's ``defects`` list. +=============== ======================================================= A new policy instance, with new settings, is created using the :meth:`~email.policy.Policy.clone` method of policy objects. ``clone`` takes @@ -1263,21 +1263,21 @@ removal of the code) may occur if deemed necessary by the core developers. The new policies are instances of :class:`~email.policy.EmailPolicy`, and add the following additional controls: - .. tabularcolumns:: |l|L| +.. tabularcolumns:: |l|L| - =============== ======================================================= - refold_source Controls whether or not headers parsed by a - :mod:`~email.parser` are refolded by the - :mod:`~email.generator`. It can be ``none``, ``long``, - or ``all``. The default is ``long``, which means that - source headers with a line longer than - ``max_line_length`` get refolded. ``none`` means no - line get refolded, and ``all`` means that all lines - get refolded. +=============== ======================================================= +refold_source Controls whether or not headers parsed by a + :mod:`~email.parser` are refolded by the + :mod:`~email.generator`. It can be ``none``, ``long``, + or ``all``. The default is ``long``, which means that + source headers with a line longer than + ``max_line_length`` get refolded. ``none`` means no + line get refolded, and ``all`` means that all lines + get refolded. - header_factory A callable that take a ``name`` and ``value`` and - produces a custom header object. - =============== ======================================================= +header_factory A callable that take a ``name`` and ``value`` and + produces a custom header object. +=============== ======================================================= The ``header_factory`` is the key to the new features provided by the new policies. When one of the new policies is used, any header retrieved from @@ -1352,18 +1352,18 @@ API. New utility functions: - * :func:`~email.utils.format_datetime`: given a :class:`~datetime.datetime`, - produce a string formatted for use in an email header. +* :func:`~email.utils.format_datetime`: given a :class:`~datetime.datetime`, + produce a string formatted for use in an email header. - * :func:`~email.utils.parsedate_to_datetime`: given a date string from - an email header, convert it into an aware :class:`~datetime.datetime`, - or a naive :class:`~datetime.datetime` if the offset is ``-0000``. +* :func:`~email.utils.parsedate_to_datetime`: given a date string from + an email header, convert it into an aware :class:`~datetime.datetime`, + or a naive :class:`~datetime.datetime` if the offset is ``-0000``. - * :func:`~email.utils.localtime`: With no argument, returns the - current local time as an aware :class:`~datetime.datetime` using the local - :class:`~datetime.timezone`. Given an aware :class:`~datetime.datetime`, - converts it into an aware :class:`~datetime.datetime` using the - local :class:`~datetime.timezone`. +* :func:`~email.utils.localtime`: With no argument, returns the + current local time as an aware :class:`~datetime.datetime` using the local + :class:`~datetime.timezone`. Given an aware :class:`~datetime.datetime`, + converts it into an aware :class:`~datetime.datetime` using the + local :class:`~datetime.timezone`. ftplib @@ -1845,7 +1845,7 @@ signal smtpd ----- -The :mod:`smtpd` module now supports :rfc:`5321` (extended SMTP) and :rfc:`1870` +The :mod:`!smtpd` module now supports :rfc:`5321` (extended SMTP) and :rfc:`1870` (size extension). Per the standard, these extensions are enabled if and only if the client initiates the session with an ``EHLO`` command. @@ -2067,7 +2067,7 @@ The :pep:`418` added new functions to the :mod:`time` module: Other new functions: * :func:`~time.clock_getres`, :func:`~time.clock_gettime` and - :func:`~time.clock_settime` functions with ``CLOCK_xxx`` constants. + :func:`~time.clock_settime` functions with :samp:`CLOCK_{xxx}` constants. (Contributed by Victor Stinner in :issue:`10278`.) To improve cross platform consistency, :func:`~time.sleep` now raises a @@ -2196,7 +2196,7 @@ Changes to Python's build process and to the C API include: * :c:macro:`PyUnicode_DATA`, :c:macro:`PyUnicode_1BYTE_DATA`, :c:macro:`PyUnicode_2BYTE_DATA`, :c:macro:`PyUnicode_4BYTE_DATA` * :c:macro:`PyUnicode_KIND` with :c:enum:`PyUnicode_Kind` enum: - :c:data:`PyUnicode_WCHAR_KIND`, :c:data:`PyUnicode_1BYTE_KIND`, + :c:data:`!PyUnicode_WCHAR_KIND`, :c:data:`PyUnicode_1BYTE_KIND`, :c:data:`PyUnicode_2BYTE_KIND`, :c:data:`PyUnicode_4BYTE_KIND` * :c:macro:`PyUnicode_READ`, :c:macro:`PyUnicode_READ_CHAR`, :c:macro:`PyUnicode_WRITE` * :c:macro:`PyUnicode_MAX_CHAR_VALUE` @@ -2270,58 +2270,58 @@ removed in Python 4. All functions using this type are deprecated: Unicode functions and methods using :c:type:`Py_UNICODE` and :c:expr:`Py_UNICODE*` types: -* :c:macro:`PyUnicode_FromUnicode`: use :c:func:`PyUnicode_FromWideChar` or +* :c:macro:`!PyUnicode_FromUnicode`: use :c:func:`PyUnicode_FromWideChar` or :c:func:`PyUnicode_FromKindAndData` -* :c:macro:`PyUnicode_AS_UNICODE`, :c:func:`PyUnicode_AsUnicode`, - :c:func:`PyUnicode_AsUnicodeAndSize`: use :c:func:`PyUnicode_AsWideCharString` -* :c:macro:`PyUnicode_AS_DATA`: use :c:macro:`PyUnicode_DATA` with +* :c:macro:`!PyUnicode_AS_UNICODE`, :c:func:`!PyUnicode_AsUnicode`, + :c:func:`!PyUnicode_AsUnicodeAndSize`: use :c:func:`PyUnicode_AsWideCharString` +* :c:macro:`!PyUnicode_AS_DATA`: use :c:macro:`PyUnicode_DATA` with :c:macro:`PyUnicode_READ` and :c:macro:`PyUnicode_WRITE` -* :c:macro:`PyUnicode_GET_SIZE`, :c:func:`PyUnicode_GetSize`: use +* :c:macro:`!PyUnicode_GET_SIZE`, :c:func:`!PyUnicode_GetSize`: use :c:macro:`PyUnicode_GET_LENGTH` or :c:func:`PyUnicode_GetLength` -* :c:macro:`PyUnicode_GET_DATA_SIZE`: use +* :c:macro:`!PyUnicode_GET_DATA_SIZE`: use ``PyUnicode_GET_LENGTH(str) * PyUnicode_KIND(str)`` (only work on ready strings) -* :c:func:`PyUnicode_AsUnicodeCopy`: use :c:func:`PyUnicode_AsUCS4Copy` or +* :c:func:`!PyUnicode_AsUnicodeCopy`: use :c:func:`PyUnicode_AsUCS4Copy` or :c:func:`PyUnicode_AsWideCharString` -* :c:func:`PyUnicode_GetMax` +* :c:func:`!PyUnicode_GetMax` Functions and macros manipulating Py_UNICODE* strings: -* :c:macro:`Py_UNICODE_strlen`: use :c:func:`PyUnicode_GetLength` or +* :c:macro:`!Py_UNICODE_strlen()`: use :c:func:`PyUnicode_GetLength` or :c:macro:`PyUnicode_GET_LENGTH` -* :c:macro:`Py_UNICODE_strcat`: use :c:func:`PyUnicode_CopyCharacters` or +* :c:macro:`!Py_UNICODE_strcat()`: use :c:func:`PyUnicode_CopyCharacters` or :c:func:`PyUnicode_FromFormat` -* :c:macro:`Py_UNICODE_strcpy`, :c:macro:`Py_UNICODE_strncpy`, - :c:macro:`Py_UNICODE_COPY`: use :c:func:`PyUnicode_CopyCharacters` or +* :c:macro:`!Py_UNICODE_strcpy()`, :c:macro:`!Py_UNICODE_strncpy()`, + :c:macro:`!Py_UNICODE_COPY()`: use :c:func:`PyUnicode_CopyCharacters` or :c:func:`PyUnicode_Substring` -* :c:macro:`Py_UNICODE_strcmp`: use :c:func:`PyUnicode_Compare` -* :c:macro:`Py_UNICODE_strncmp`: use :c:func:`PyUnicode_Tailmatch` -* :c:macro:`Py_UNICODE_strchr`, :c:macro:`Py_UNICODE_strrchr`: use +* :c:macro:`!Py_UNICODE_strcmp()`: use :c:func:`PyUnicode_Compare` +* :c:macro:`!Py_UNICODE_strncmp()`: use :c:func:`PyUnicode_Tailmatch` +* :c:macro:`!Py_UNICODE_strchr()`, :c:macro:`!Py_UNICODE_strrchr()`: use :c:func:`PyUnicode_FindChar` -* :c:macro:`Py_UNICODE_FILL`: use :c:func:`PyUnicode_Fill` -* :c:macro:`Py_UNICODE_MATCH` +* :c:macro:`!Py_UNICODE_FILL()`: use :c:func:`PyUnicode_Fill` +* :c:macro:`!Py_UNICODE_MATCH` Encoders: -* :c:func:`PyUnicode_Encode`: use :c:func:`PyUnicode_AsEncodedObject` -* :c:func:`PyUnicode_EncodeUTF7` -* :c:func:`PyUnicode_EncodeUTF8`: use :c:func:`PyUnicode_AsUTF8` or +* :c:func:`!PyUnicode_Encode`: use :c:func:`!PyUnicode_AsEncodedObject` +* :c:func:`!PyUnicode_EncodeUTF7` +* :c:func:`!PyUnicode_EncodeUTF8`: use :c:func:`PyUnicode_AsUTF8` or :c:func:`PyUnicode_AsUTF8String` -* :c:func:`PyUnicode_EncodeUTF32` -* :c:func:`PyUnicode_EncodeUTF16` -* :c:func:`PyUnicode_EncodeUnicodeEscape` use +* :c:func:`!PyUnicode_EncodeUTF32` +* :c:func:`!PyUnicode_EncodeUTF16` +* :c:func:`!PyUnicode_EncodeUnicodeEscape` use :c:func:`PyUnicode_AsUnicodeEscapeString` -* :c:func:`PyUnicode_EncodeRawUnicodeEscape` use +* :c:func:`!PyUnicode_EncodeRawUnicodeEscape` use :c:func:`PyUnicode_AsRawUnicodeEscapeString` -* :c:func:`PyUnicode_EncodeLatin1`: use :c:func:`PyUnicode_AsLatin1String` -* :c:func:`PyUnicode_EncodeASCII`: use :c:func:`PyUnicode_AsASCIIString` -* :c:func:`PyUnicode_EncodeCharmap` -* :c:func:`PyUnicode_TranslateCharmap` -* :c:func:`PyUnicode_EncodeMBCS`: use :c:func:`PyUnicode_AsMBCSString` or +* :c:func:`!PyUnicode_EncodeLatin1`: use :c:func:`PyUnicode_AsLatin1String` +* :c:func:`!PyUnicode_EncodeASCII`: use :c:func:`PyUnicode_AsASCIIString` +* :c:func:`!PyUnicode_EncodeCharmap` +* :c:func:`!PyUnicode_TranslateCharmap` +* :c:func:`!PyUnicode_EncodeMBCS`: use :c:func:`PyUnicode_AsMBCSString` or :c:func:`PyUnicode_EncodeCodePage` (with ``CP_ACP`` code_page) -* :c:func:`PyUnicode_EncodeDecimal`, - :c:func:`PyUnicode_TransformDecimalToASCII` +* :c:func:`!PyUnicode_EncodeDecimal`, + :c:func:`!PyUnicode_TransformDecimalToASCII` Deprecated features @@ -2462,7 +2462,7 @@ Porting C code -------------- * In the course of changes to the buffer API the undocumented - :c:member:`~Py_buffer.smalltable` member of the + :c:member:`!smalltable` member of the :c:type:`Py_buffer` structure has been removed and the layout of the :c:type:`PyMemoryViewObject` has changed. diff --git a/Doc/whatsnew/3.4.rst b/Doc/whatsnew/3.4.rst index 794271f3c32b89..e07eda985d9bad 100644 --- a/Doc/whatsnew/3.4.rst +++ b/Doc/whatsnew/3.4.rst @@ -605,15 +605,15 @@ Using ``ABC`` as a base class has essentially the same effect as specifying aifc ---- -The :meth:`~!aifc.aifc.getparams` method now returns a namedtuple rather than a +The :meth:`!getparams` method now returns a namedtuple rather than a plain tuple. (Contributed by Claudiu Popa in :issue:`17818`.) :func:`!aifc.open` now supports the context management protocol: when used in a -:keyword:`with` block, the :meth:`~!aifc.aifc.close` method of the returned +:keyword:`with` block, the :meth:`!close` method of the returned object will be called automatically at the end of the block. (Contributed by Serhiy Storchacha in :issue:`16486`.) -The :meth:`~!aifc.aifc.writeframesraw` and :meth:`~!aifc.aifc.writeframes` +The :meth:`!writeframesraw` and :meth:`!writeframes` methods now accept any :term:`bytes-like object`. (Contributed by Serhiy Storchaka in :issue:`8311`.) @@ -632,7 +632,7 @@ audioop :mod:`!audioop` now supports 24-bit samples. (Contributed by Serhiy Storchaka in :issue:`12866`.) -New :func:`~!audioop.byteswap` function converts big-endian samples to +New :func:`!byteswap` function converts big-endian samples to little-endian and vice versa. (Contributed by Serhiy Storchaka in :issue:`19641`.) @@ -1369,9 +1369,9 @@ error. (Contributed by Atsuo Ishimoto and Hynek Schlawack in smtpd ----- -The :class:`~smtpd.SMTPServer` and :class:`~smtpd.SMTPChannel` classes now +The :class:`!SMTPServer` and :class:`!SMTPChannel` classes now accept a *map* keyword argument which, if specified, is passed in to -:class:`asynchat.async_chat` as its *map* argument. This allows an application +:class:`!asynchat.async_chat` as its *map* argument. This allows an application to avoid affecting the global socket map. (Contributed by Vinay Sajip in :issue:`11959`.) @@ -1528,7 +1528,7 @@ work on Windows. This change was actually inadvertently made in 3.3.4. sunau ----- -The :meth:`~!sunau.getparams` method now returns a namedtuple rather than a +The :meth:`!getparams` method now returns a namedtuple rather than a plain tuple. (Contributed by Claudiu Popa in :issue:`18901`.) :meth:`!sunau.open` now supports the context management protocol: when used in a @@ -1540,8 +1540,8 @@ in :issue:`18878`.) support for writing 24 sample using the module. (Contributed by Serhiy Storchaka in :issue:`19261`.) -The :meth:`~!sunau.AU_write.writeframesraw` and -:meth:`~!sunau.AU_write.writeframes` methods now accept any :term:`bytes-like +The :meth:`!writeframesraw` and +:meth:`!writeframes` methods now accept any :term:`bytes-like object`. (Contributed by Serhiy Storchaka in :issue:`8311`.) @@ -1891,7 +1891,7 @@ Other Build and C API Changes allowing retrieval of function pointers from named type slots when using the limited API. (Contributed by Martin von Löwis in :issue:`17162`.) -* The new :c:func:`Py_SetStandardStreamEncoding` pre-initialization API +* The new :c:func:`!Py_SetStandardStreamEncoding` pre-initialization API allows applications embedding the CPython interpreter to reliably force a particular encoding and error handler for the standard streams. (Contributed by Bastien Montagne and Nick Coghlan in :issue:`16129`.) @@ -1936,7 +1936,7 @@ Other Improvements * The :ref:`python ` command has a new :ref:`option `, ``-I``, which causes it to run in "isolated mode", which means that :data:`sys.path` contains neither the script's directory nor - the user's ``site-packages`` directory, and all :envvar:`PYTHON*` environment + the user's ``site-packages`` directory, and all :envvar:`!PYTHON*` environment variables are ignored (it implies both ``-s`` and ``-E``). Other restrictions may also be applied in the future, with the goal being to isolate the execution of a script from the user's environment. This is @@ -2085,7 +2085,7 @@ Deprecations in the Python API :meth:`importlib.abc.MetaPathFinder.find_spec`; :meth:`!importlib.abc.PathEntryFinder.find_loader` and :meth:`!find_module` are replaced by - :meth:`importlib.abc.PathEntryFinder.find_spec`; all of the ``xxxLoader`` ABC + :meth:`importlib.abc.PathEntryFinder.find_spec`; all of the :samp:`{xxx}Loader` ABC ``load_module`` methods (:meth:`!importlib.abc.Loader.load_module`, :meth:`!importlib.abc.InspectLoader.load_module`, :meth:`!importlib.abc.FileLoader.load_module`, @@ -2370,7 +2370,7 @@ Changes in the Python API :issue:`18011`.) Note: this change was also inadvertently applied in Python 3.3.3. -* The :attr:`~cgi.FieldStorage.file` attribute is now automatically closed when +* The :attr:`!file` attribute is now automatically closed when the creating :class:`!cgi.FieldStorage` instance is garbage collected. If you were pulling the file object out separately from the :class:`!cgi.FieldStorage` instance and not keeping the instance alive, then you should either store the @@ -2405,8 +2405,8 @@ Changes in the Python API storage). (:issue:`17094`.) * Parameter names in ``__annotations__`` dicts are now mangled properly, - similarly to ``__kwdefaults__``. (Contributed by Yury Selivanov in - :issue:`20625`.) + similarly to :attr:`~function.__kwdefaults__`. + (Contributed by Yury Selivanov in :issue:`20625`.) * :attr:`hashlib.hash.name` now always returns the identifier in lower case. Previously some builtin hashes had uppercase names, but now that it is a diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst index 86bfdc4d478a02..1c7a9270af0aab 100644 --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -878,7 +878,7 @@ size of decompressed data. (Contributed by Nikolaus Rath in :issue:`15955`.) cgi --- -The :class:`~cgi.FieldStorage` class now supports the :term:`context manager` +The :class:`!FieldStorage` class now supports the :term:`context manager` protocol. (Contributed by Berker Peksag in :issue:`20289`.) @@ -921,7 +921,7 @@ and improves their substitutability for lists. Docstrings produced by :func:`~collections.namedtuple` can now be updated:: Point = namedtuple('Point', ['x', 'y']) - Point.__doc__ += ': Cartesian coodinate' + Point.__doc__ += ': Cartesian coordinate' Point.x.__doc__ = 'abscissa' Point.y.__doc__ = 'ordinate' @@ -1252,7 +1252,7 @@ Oberkirch in :issue:`21800`.) imghdr ------ -The :func:`~!imghdr.what` function now recognizes the +The :func:`!what` function now recognizes the `OpenEXR `_ format (contributed by Martin Vignali and Claudiu Popa in :issue:`20295`), and the `WebP `_ format @@ -1663,34 +1663,34 @@ during debugging, instead of integer "magic numbers". smtpd ----- -Both the :class:`~smtpd.SMTPServer` and :class:`~smtpd.SMTPChannel` classes now +Both the :class:`!SMTPServer` and :class:`!SMTPChannel` classes now accept a *decode_data* keyword argument to determine if the ``DATA`` portion of the SMTP transaction is decoded using the ``"utf-8"`` codec or is instead provided to the -:meth:`SMTPServer.process_message() ` +:meth:`!SMTPServer.process_message()` method as a byte string. The default is ``True`` for backward compatibility reasons, but will change to ``False`` in Python 3.6. If *decode_data* is set to ``False``, the ``process_message`` method must be prepared to accept keyword arguments. (Contributed by Maciej Szulik in :issue:`19662`.) -The :class:`~smtpd.SMTPServer` class now advertises the ``8BITMIME`` extension +The :class:`!SMTPServer` class now advertises the ``8BITMIME`` extension (:rfc:`6152`) if *decode_data* has been set ``True``. If the client specifies ``BODY=8BITMIME`` on the ``MAIL`` command, it is passed to -:meth:`SMTPServer.process_message() ` +:meth:`!SMTPServer.process_message()` via the *mail_options* keyword. (Contributed by Milan Oberkirch and R. David Murray in :issue:`21795`.) -The :class:`~smtpd.SMTPServer` class now also supports the ``SMTPUTF8`` +The :class:`!SMTPServer` class now also supports the ``SMTPUTF8`` extension (:rfc:`6531`: Internationalized Email). If the client specified ``SMTPUTF8 BODY=8BITMIME`` on the ``MAIL`` command, they are passed to -:meth:`SMTPServer.process_message() ` +:meth:`!SMTPServer.process_message()` via the *mail_options* keyword. It is the responsibility of the ``process_message`` method to correctly handle the ``SMTPUTF8`` data. (Contributed by Milan Oberkirch in :issue:`21725`.) It is now possible to provide, directly or via name resolution, IPv6 -addresses in the :class:`~smtpd.SMTPServer` constructor, and have it +addresses in the :class:`!SMTPServer` constructor, and have it successfully connect. (Contributed by Milan Oberkirch in :issue:`14758`.) @@ -1714,7 +1714,7 @@ support :rfc:`6531` (SMTPUTF8). sndhdr ------ -The :func:`~sndhdr.what` and :func:`~sndhdr.whathdr` functions now return +The :func:`!what` and :func:`!whathdr` functions now return a :func:`~collections.namedtuple`. (Contributed by Claudiu Popa in :issue:`18615`.) @@ -1947,7 +1947,8 @@ traceback --------- New :func:`~traceback.walk_stack` and :func:`~traceback.walk_tb` -functions to conveniently traverse frame and traceback objects. +functions to conveniently traverse frame and +:ref:`traceback objects `. (Contributed by Robert Collins in :issue:`17911`.) New lightweight classes: :class:`~traceback.TracebackException`, @@ -2295,9 +2296,9 @@ slated for removal in Python 3.6. The :func:`asyncio.async` function is deprecated in favor of :func:`~asyncio.ensure_future`. -The :mod:`smtpd` module has in the past always decoded the DATA portion of +The :mod:`!smtpd` module has in the past always decoded the DATA portion of email messages using the ``utf-8`` codec. This can now be controlled by the -new *decode_data* keyword to :class:`~smtpd.SMTPServer`. The default value is +new *decode_data* keyword to :class:`!SMTPServer`. The default value is ``True``, but this default is deprecated. Specify the *decode_data* keyword with an appropriate value to avoid the deprecation warning. @@ -2512,7 +2513,7 @@ Changes in the Python API Changes in the C API -------------------- -* The undocumented :c:member:`~PyMemoryViewObject.format` member of the +* The undocumented :c:member:`!format` member of the (non-public) :c:type:`PyMemoryViewObject` structure has been removed. All extensions relying on the relevant parts in ``memoryobject.h`` must be rebuilt. @@ -2520,7 +2521,7 @@ Changes in the C API * The :c:type:`PyMemAllocator` structure was renamed to :c:type:`PyMemAllocatorEx` and a new ``calloc`` field was added. -* Removed non-documented macro :c:macro:`PyObject_REPR` which leaked references. +* Removed non-documented macro :c:macro:`!PyObject_REPR()` which leaked references. Use format character ``%R`` in :c:func:`PyUnicode_FromFormat`-like functions to format the :func:`repr` of the object. (Contributed by Serhiy Storchaka in :issue:`22453`.) diff --git a/Doc/whatsnew/3.6.rst b/Doc/whatsnew/3.6.rst index 4359a9012dd53c..11e1d73232a96d 100644 --- a/Doc/whatsnew/3.6.rst +++ b/Doc/whatsnew/3.6.rst @@ -1961,14 +1961,14 @@ Deprecated Python modules, functions and methods asynchat ~~~~~~~~ -The :mod:`asynchat` has been deprecated in favor of :mod:`asyncio`. +The :mod:`!asynchat` has been deprecated in favor of :mod:`asyncio`. (Contributed by Mariatta in :issue:`25002`.) asyncore ~~~~~~~~ -The :mod:`asyncore` has been deprecated in favor of :mod:`asyncio`. +The :mod:`!asyncore` has been deprecated in favor of :mod:`asyncio`. (Contributed by Mariatta in :issue:`25002`.) @@ -2066,9 +2066,9 @@ environment. (Contributed by Brett Cannon in :issue:`25154`.) Deprecated functions and types of the C API ------------------------------------------- -Undocumented functions :c:func:`PyUnicode_AsEncodedObject`, -:c:func:`PyUnicode_AsDecodedObject`, :c:func:`PyUnicode_AsEncodedUnicode` -and :c:func:`PyUnicode_AsDecodedUnicode` are deprecated now. +Undocumented functions :c:func:`!PyUnicode_AsEncodedObject`, +:c:func:`!PyUnicode_AsDecodedObject`, :c:func:`!PyUnicode_AsEncodedUnicode` +and :c:func:`!PyUnicode_AsDecodedUnicode` are deprecated now. Use the :ref:`generic codec based API ` instead. @@ -2160,14 +2160,15 @@ Changes in the Python API * :c:func:`PyErr_SetImportError` now sets :exc:`TypeError` when its **msg** argument is not set. Previously only ``NULL`` was returned. -* The format of the ``co_lnotab`` attribute of code objects changed to support +* The format of the :attr:`~codeobject.co_lnotab` attribute of code objects + changed to support a negative line number delta. By default, Python does not emit bytecode with - a negative line number delta. Functions using ``frame.f_lineno``, + a negative line number delta. Functions using :attr:`frame.f_lineno`, ``PyFrame_GetLineNumber()`` or ``PyCode_Addr2Line()`` are not affected. - Functions directly decoding ``co_lnotab`` should be updated to use a signed + Functions directly decoding :attr:`!co_lnotab` should be updated to use a signed 8-bit integer type for the line number delta, but this is only required to support applications using a negative line number delta. See - ``Objects/lnotab_notes.txt`` for the ``co_lnotab`` format and how to decode + ``Objects/lnotab_notes.txt`` for the :attr:`!co_lnotab` format and how to decode it, and see the :pep:`511` for the rationale. * The functions in the :mod:`compileall` module now return booleans instead @@ -2188,7 +2189,7 @@ Changes in the Python API :mod:`calendar`, :mod:`!cgi`, :mod:`csv`, :mod:`~xml.etree.ElementTree`, :mod:`enum`, :mod:`fileinput`, :mod:`ftplib`, :mod:`logging`, :mod:`mailbox`, - :mod:`mimetypes`, :mod:`optparse`, :mod:`plistlib`, :mod:`smtpd`, + :mod:`mimetypes`, :mod:`optparse`, :mod:`plistlib`, :mod:`!smtpd`, :mod:`subprocess`, :mod:`tarfile`, :mod:`threading` and :mod:`wave`. This means they will export new symbols when ``import *`` is used. @@ -2218,11 +2219,11 @@ Changes in the Python API an error (e.g. ``EBADF``) was reported by the underlying system call. (Contributed by Martin Panter in :issue:`26685`.) -* The *decode_data* argument for the :class:`smtpd.SMTPChannel` and - :class:`smtpd.SMTPServer` constructors is now ``False`` by default. +* The *decode_data* argument for the :class:`!smtpd.SMTPChannel` and + :class:`!smtpd.SMTPServer` constructors is now ``False`` by default. This means that the argument passed to - :meth:`~smtpd.SMTPServer.process_message` is now a bytes object by - default, and ``process_message()`` will be passed keyword arguments. + :meth:`!process_message` is now a bytes object by + default, and :meth:`!process_message` will be passed keyword arguments. Code that has already been updated in accordance with the deprecation warning generated by 3.5 will not be affected. diff --git a/Doc/whatsnew/3.7.rst b/Doc/whatsnew/3.7.rst index 218a37cd264c7c..402b15a277e53d 100644 --- a/Doc/whatsnew/3.7.rst +++ b/Doc/whatsnew/3.7.rst @@ -525,8 +525,8 @@ Other Language Changes * In order to better support dynamic creation of stack traces, :class:`types.TracebackType` can now be instantiated from Python code, and - the ``tb_next`` attribute on :ref:`tracebacks ` is now - writable. + the :attr:`~traceback.tb_next` attribute on + :ref:`tracebacks ` is now writable. (Contributed by Nathaniel J. Smith in :issue:`30579`.) * When using the :option:`-m` switch, ``sys.path[0]`` is now eagerly expanded @@ -851,7 +851,7 @@ crypt The :mod:`!crypt` module now supports the Blowfish hashing method. (Contributed by Serhiy Storchaka in :issue:`31664`.) -The :func:`~!crypt.mksalt` function now allows specifying the number of rounds +The :func:`!mksalt` function now allows specifying the number of rounds for hashing. (Contributed by Serhiy Storchaka in :issue:`31702`.) @@ -1580,13 +1580,13 @@ The initialization of the default warnings filters has changed as follows: * warnings filters enabled via the command line or the environment now have the following order of precedence: - * the ``BytesWarning`` filter for :option:`-b` (or ``-bb``) - * any filters specified with the :option:`-W` option - * any filters specified with the :envvar:`PYTHONWARNINGS` environment - variable - * any other CPython specific filters (e.g. the ``default`` filter added - for the new ``-X dev`` mode) - * any implicit filters defined directly by the warnings machinery + * the ``BytesWarning`` filter for :option:`-b` (or ``-bb``) + * any filters specified with the :option:`-W` option + * any filters specified with the :envvar:`PYTHONWARNINGS` environment + variable + * any other CPython specific filters (e.g. the ``default`` filter added + for the new ``-X dev`` mode) + * any implicit filters defined directly by the warnings machinery * in :ref:`CPython debug builds `, all warnings are now displayed by default (the implicit filter list is empty) @@ -1891,7 +1891,7 @@ Other CPython Implementation Changes * Trace hooks may now opt out of receiving the ``line`` and opt into receiving the ``opcode`` events from the interpreter by setting the corresponding new - ``f_trace_lines`` and ``f_trace_opcodes`` attributes on the + :attr:`~frame.f_trace_lines` and :attr:`~frame.f_trace_opcodes` attributes on the frame being traced. (Contributed by Nick Coghlan in :issue:`31344`.) * Fixed some consistency problems with namespace package module attributes. @@ -2004,15 +2004,15 @@ importlib --------- Methods -:meth:`MetaPathFinder.find_module() ` +:meth:`!MetaPathFinder.find_module()` (replaced by :meth:`MetaPathFinder.find_spec() `) and -:meth:`PathEntryFinder.find_loader() ` +:meth:`!PathEntryFinder.find_loader()` (replaced by :meth:`PathEntryFinder.find_spec() `) both deprecated in Python 3.4 now emit :exc:`DeprecationWarning`. -(Contributed by Matthias Bussonnier in :issue:`29576`) +(Contributed by Matthias Bussonnier in :issue:`29576`.) The :class:`importlib.abc.ResourceLoader` ABC has been deprecated in favour of :class:`importlib.abc.ResourceReader`. @@ -2144,9 +2144,9 @@ The following features and APIs have been removed from Python 3.7: * Removed support of the *exclude* argument in :meth:`tarfile.TarFile.add`. It was deprecated in Python 2.7 and 3.2. Use the *filter* argument instead. -* The ``splitunc()`` function in the :mod:`ntpath` module was deprecated in - Python 3.1, and has now been removed. Use the :func:`~os.path.splitdrive` - function instead. +* The :func:`!ntpath.splitunc` function was deprecated in + Python 3.1, and has now been removed. Use :func:`~os.path.splitdrive` + instead. * :func:`collections.namedtuple` no longer supports the *verbose* parameter or ``_source`` attribute which showed the generated source code for the @@ -2304,9 +2304,9 @@ Changes in the Python API * The :attr:`struct.Struct.format` type is now :class:`str` instead of :class:`bytes`. (Contributed by Victor Stinner in :issue:`21071`.) -* :func:`~cgi.parse_multipart` now accepts the *encoding* and *errors* +* :func:`!cgi.parse_multipart` now accepts the *encoding* and *errors* arguments and returns the same results as - :class:`~FieldStorage`: for non-file fields, the value associated to a key + :class:`!FieldStorage`: for non-file fields, the value associated to a key is a list of strings, not bytes. (Contributed by Pierre Quentel in :issue:`29979`.) @@ -2495,12 +2495,12 @@ either in embedding applications, or in CPython itself. :issue:`22257`, and further updated by Nick, Eric, and Victor Stinner in a number of other issues). Some known details affected: -* :c:func:`PySys_AddWarnOptionUnicode` is not currently usable by embedding +* :c:func:`!PySys_AddWarnOptionUnicode` is not currently usable by embedding applications due to the requirement to create a Unicode object prior to - calling ``Py_Initialize``. Use :c:func:`PySys_AddWarnOption` instead. + calling ``Py_Initialize``. Use :c:func:`!PySys_AddWarnOption` instead. * warnings filters added by an embedding application with - :c:func:`PySys_AddWarnOption` should now more consistently take precedence + :c:func:`!PySys_AddWarnOption` should now more consistently take precedence over the default filters set by the interpreter Due to changes in the way the default warnings filters are configured, diff --git a/Doc/whatsnew/3.8.rst b/Doc/whatsnew/3.8.rst index c5fb5c53dfe350..d373fa163ff737 100644 --- a/Doc/whatsnew/3.8.rst +++ b/Doc/whatsnew/3.8.rst @@ -123,7 +123,7 @@ There is a new function parameter syntax ``/`` to indicate that some function parameters must be specified positionally and cannot be used as keyword arguments. This is the same notation shown by ``help()`` for C functions annotated with Larry Hastings' -:ref:`Argument Clinic ` tool. +`Argument Clinic `__ tool. In the following example, parameters *a* and *b* are positional-only, while *c* or *d* can be positional or keyword, and *e* or *f* are @@ -404,7 +404,7 @@ Other Language Changes or :meth:`~object.__complex__` is not available. (Contributed by Serhiy Storchaka in :issue:`20092`.) -* Added support of ``\N{name}`` escapes in :mod:`regular expressions `:: +* Added support of :samp:`\\N\\{{name}\\}` escapes in :mod:`regular expressions `:: >>> notice = 'Copyright © 2019' >>> copyright_year_pattern = re.compile(r'\N{copyright sign}\s*(\d{4})') @@ -947,7 +947,7 @@ This made it difficult to update, experiment with, or teach the various logging configuration options using the interactive prompt or a Jupyter notebook. -(Suggested by Raymond Hettinger, implemented by Dong-hee Na, and +(Suggested by Raymond Hettinger, implemented by Donghee Na, and reviewed by Vinay Sajip in :issue:`33897`.) @@ -1086,7 +1086,7 @@ pathlib contain characters unrepresentable at the OS level. (Contributed by Serhiy Storchaka in :issue:`33721`.) -Added :meth:`pathlib.Path.link_to()` which creates a hard link pointing +Added :meth:`!pathlib.Path.link_to()` which creates a hard link pointing to a path. (Contributed by Joannah Nanjekye in :issue:`26978`) Note that ``link_to`` was deprecated in 3.10 and removed in 3.12 in @@ -1574,12 +1574,12 @@ Build and C API Changes * :c:func:`Py_INCREF`, :c:func:`Py_DECREF` * :c:func:`Py_XINCREF`, :c:func:`Py_XDECREF` * :c:func:`PyObject_INIT`, :c:func:`PyObject_INIT_VAR` - * Private functions: :c:func:`_PyObject_GC_TRACK`, - :c:func:`_PyObject_GC_UNTRACK`, :c:func:`_Py_Dealloc` + * Private functions: :c:func:`!_PyObject_GC_TRACK`, + :c:func:`!_PyObject_GC_UNTRACK`, :c:func:`!_Py_Dealloc` (Contributed by Victor Stinner in :issue:`35059`.) -* The :c:func:`PyByteArray_Init` and :c:func:`PyByteArray_Fini` functions have +* The :c:func:`!PyByteArray_Init` and :c:func:`!PyByteArray_Fini` functions have been removed. They did nothing since Python 2.7.4 and Python 3.2.0, were excluded from the limited API (stable ABI), and were not documented. (Contributed by Victor Stinner in :issue:`35713`.) @@ -1628,7 +1628,7 @@ Build and C API Changes parameter for indicating the number of positional-only arguments. (Contributed by Pablo Galindo in :issue:`37221`.) -* :c:func:`Py_SetPath` now sets :data:`sys.executable` to the program full +* :c:func:`!Py_SetPath` now sets :data:`sys.executable` to the program full path (:c:func:`Py_GetProgramFullPath`) rather than to the program name (:c:func:`Py_GetProgramName`). (Contributed by Victor Stinner in :issue:`38234`.) @@ -1653,7 +1653,7 @@ Deprecated deprecated and will be prohibited in Python 3.9. (Contributed by Elvis Pranskevichus in :issue:`34075`.) -* The :meth:`__getitem__` methods of :class:`xml.dom.pulldom.DOMEventStream`, +* The :meth:`~object.__getitem__` methods of :class:`xml.dom.pulldom.DOMEventStream`, :class:`wsgiref.util.FileWrapper` and :class:`fileinput.FileInput` have been deprecated. @@ -1714,7 +1714,7 @@ Deprecated * The :meth:`~threading.Thread.isAlive()` method of :class:`threading.Thread` has been deprecated. - (Contributed by Dong-hee Na in :issue:`35283`.) + (Contributed by Donghee Na in :issue:`35283`.) * Many builtin and extension functions that take integer arguments will now emit a deprecation warning for :class:`~decimal.Decimal`\ s, @@ -1845,11 +1845,11 @@ Changes in Python behavior always use ``sys.platform.startswith('aix')``. (Contributed by M. Felt in :issue:`36588`.) -* :c:func:`PyEval_AcquireLock` and :c:func:`PyEval_AcquireThread` now +* :c:func:`!PyEval_AcquireLock` and :c:func:`!PyEval_AcquireThread` now terminate the current thread if called while the interpreter is finalizing, making them consistent with :c:func:`PyEval_RestoreThread`, :c:func:`Py_END_ALLOW_THREADS`, and :c:func:`PyGILState_Ensure`. If this - behavior is not desired, guard the call by checking :c:func:`_Py_IsFinalizing` + behavior is not desired, guard the call by checking :c:func:`!_Py_IsFinalizing` or :func:`sys.is_finalizing`. (Contributed by Joannah Nanjekye in :issue:`36475`.) @@ -2021,7 +2021,7 @@ Changes in the C API *cf_flags*. (Contributed by Guido van Rossum in :issue:`35766`.) -* The :c:func:`PyEval_ReInitThreads` function has been removed from the C API. +* The :c:func:`!PyEval_ReInitThreads` function has been removed from the C API. It should not be called explicitly: use :c:func:`PyOS_AfterFork_Child` instead. (Contributed by Victor Stinner in :issue:`36728`.) @@ -2121,7 +2121,7 @@ Changes in the C API (Contributed by Antoine Pitrou in :issue:`32388`.) -* The functions :c:func:`PyNode_AddChild` and :c:func:`PyParser_AddToken` now accept +* The functions :c:func:`!PyNode_AddChild` and :c:func:`!PyParser_AddToken` now accept two additional ``int`` arguments *end_lineno* and *end_col_offset*. * The :file:`libpython38.a` file to allow MinGW tools to link directly against diff --git a/Doc/whatsnew/3.9.rst b/Doc/whatsnew/3.9.rst index 3e3e0ff5c41f4f..f7ad4372325ccb 100644 --- a/Doc/whatsnew/3.9.rst +++ b/Doc/whatsnew/3.9.rst @@ -44,7 +44,6 @@ This article explains the new features in Python 3.9, compared to 3.8. Python 3.9 was released on October 5, 2020. - For full details, see the :ref:`changelog `. .. seealso:: @@ -415,7 +414,7 @@ datetime The :meth:`~datetime.date.isocalendar()` of :class:`datetime.date` and :meth:`~datetime.datetime.isocalendar()` of :class:`datetime.datetime` methods now returns a :func:`~collections.namedtuple` instead of a :class:`tuple`. -(Contributed by Dong-hee Na in :issue:`24416`.) +(Contributed by Donghee Na in :issue:`24416`.) distutils --------- @@ -429,14 +428,14 @@ fcntl Added constants :const:`~fcntl.F_OFD_GETLK`, :const:`~fcntl.F_OFD_SETLK` and :const:`~fcntl.F_OFD_SETLKW`. -(Contributed by Dong-hee Na in :issue:`38602`.) +(Contributed by Donghee Na in :issue:`38602`.) ftplib ------- :class:`~ftplib.FTP` and :class:`~ftplib.FTP_TLS` now raise a :class:`ValueError` if the given timeout for their constructor is zero to prevent the creation of -a non-blocking socket. (Contributed by Dong-hee Na in :issue:`39259`.) +a non-blocking socket. (Contributed by Donghee Na in :issue:`39259`.) gc -- @@ -468,7 +467,7 @@ http ---- HTTP status codes ``103 EARLY_HINTS``, ``418 IM_A_TEAPOT`` and ``425 TOO_EARLY`` are added to -:class:`http.HTTPStatus`. (Contributed by Dong-hee Na in :issue:`39509` and Ross Rhodes in :issue:`39507`.) +:class:`http.HTTPStatus`. (Contributed by Donghee Na in :issue:`39509` and Ross Rhodes in :issue:`39507`.) IDLE and idlelib ---------------- @@ -509,14 +508,14 @@ an optional *timeout* parameter for their constructors. Also, the :meth:`~imaplib.IMAP4.open` method now has an optional *timeout* parameter with this change. The overridden methods of :class:`~imaplib.IMAP4_SSL` and :class:`~imaplib.IMAP4_stream` were applied to this change. -(Contributed by Dong-hee Na in :issue:`38615`.) +(Contributed by Donghee Na in :issue:`38615`.) :meth:`imaplib.IMAP4.unselect` is added. :meth:`imaplib.IMAP4.unselect` frees server's resources associated with the selected mailbox and returns the server to the authenticated state. This command performs the same actions as :meth:`imaplib.IMAP4.close`, except that no messages are permanently removed from the currently -selected mailbox. (Contributed by Dong-hee Na in :issue:`40375`.) +selected mailbox. (Contributed by Donghee Na in :issue:`40375`.) importlib --------- @@ -586,15 +585,15 @@ queue. nntplib ------- -:class:`~!nntplib.NNTP` and :class:`~!nntplib.NNTP_SSL` now raise a :class:`ValueError` +:class:`!NNTP` and :class:`!NNTP_SSL` now raise a :class:`ValueError` if the given timeout for their constructor is zero to prevent the creation of -a non-blocking socket. (Contributed by Dong-hee Na in :issue:`39259`.) +a non-blocking socket. (Contributed by Donghee Na in :issue:`39259`.) os -- Added :const:`~os.CLD_KILLED` and :const:`~os.CLD_STOPPED` for :attr:`si_code`. -(Contributed by Dong-hee Na in :issue:`38493`.) +(Contributed by Donghee Na in :issue:`38493`.) Exposed the Linux-specific :func:`os.pidfd_open` (:issue:`38692`) and :const:`os.P_PIDFD` (:issue:`38713`) for process management with file @@ -629,7 +628,7 @@ poplib :class:`~poplib.POP3` and :class:`~poplib.POP3_SSL` now raise a :class:`ValueError` if the given timeout for their constructor is zero to prevent the creation of -a non-blocking socket. (Contributed by Dong-hee Na in :issue:`39259`.) +a non-blocking socket. (Contributed by Donghee Na in :issue:`39259`.) pprint ------ @@ -661,10 +660,10 @@ smtplib :class:`~smtplib.SMTP` and :class:`~smtplib.SMTP_SSL` now raise a :class:`ValueError` if the given timeout for their constructor is zero to prevent the creation of -a non-blocking socket. (Contributed by Dong-hee Na in :issue:`39259`.) +a non-blocking socket. (Contributed by Donghee Na in :issue:`39259`.) :class:`~smtplib.LMTP` constructor now has an optional *timeout* parameter. -(Contributed by Dong-hee Na in :issue:`39329`.) +(Contributed by Donghee Na in :issue:`39329`.) socket ------ @@ -777,7 +776,7 @@ Optimizations * A number of Python builtins (:class:`range`, :class:`tuple`, :class:`set`, :class:`frozenset`, :class:`list`, :class:`dict`) are now sped up by using :pep:`590` vectorcall protocol. - (Contributed by Dong-hee Na, Mark Shannon, Jeroen Demeyer and Petr Viktorin in :issue:`37207`.) + (Contributed by Donghee Na, Mark Shannon, Jeroen Demeyer and Petr Viktorin in :issue:`37207`.) * Optimized :func:`~set.difference_update` for the case when the other set is much larger than the base set. @@ -791,7 +790,7 @@ Optimizations * :term:`floor division` of float operation now has a better performance. Also the message of :exc:`ZeroDivisionError` for this operation is updated. - (Contributed by Dong-hee Na in :issue:`39434`.) + (Contributed by Donghee Na in :issue:`39434`.) * Decoding short ASCII strings with UTF-8 and ascii codecs is now about 15% faster. (Contributed by Inada Naoki in :issue:`37348`.) @@ -870,9 +869,9 @@ Deprecated users can leverage the Abstract Syntax Tree (AST) generation and compilation stage, using the :mod:`ast` module. -* The Public C API functions :c:func:`PyParser_SimpleParseStringFlags`, - :c:func:`PyParser_SimpleParseStringFlagsFilename`, - :c:func:`PyParser_SimpleParseFileFlags` and :c:func:`PyNode_Compile` +* The Public C API functions :c:func:`!PyParser_SimpleParseStringFlags`, + :c:func:`!PyParser_SimpleParseStringFlagsFilename`, + :c:func:`!PyParser_SimpleParseFileFlags` and :c:func:`!PyNode_Compile` are deprecated and will be removed in Python 3.10 together with the old parser. * Using :data:`NotImplemented` in a boolean context has been deprecated, @@ -923,16 +922,16 @@ Deprecated (Contributed by Batuhan Taskaya in :issue:`39639` and :issue:`39969` and Serhiy Storchaka in :issue:`39988`.) -* The :c:func:`PyEval_InitThreads` and :c:func:`PyEval_ThreadsInitialized` +* The :c:func:`!PyEval_InitThreads` and :c:func:`!PyEval_ThreadsInitialized` functions are now deprecated and will be removed in Python 3.11. Calling - :c:func:`PyEval_InitThreads` now does nothing. The :term:`GIL` is initialized - by :c:func:`Py_Initialize()` since Python 3.7. + :c:func:`!PyEval_InitThreads` now does nothing. The :term:`GIL` is initialized + by :c:func:`Py_Initialize` since Python 3.7. (Contributed by Victor Stinner in :issue:`39877`.) * Passing ``None`` as the first argument to the :func:`shlex.split` function has been deprecated. (Contributed by Zackery Spytz in :issue:`33262`.) -* :func:`smtpd.MailmanProxy` is now deprecated as it is unusable without +* :func:`!smtpd.MailmanProxy` is now deprecated as it is unusable without an external module, ``mailman``. (Contributed by Samuel Colvin in :issue:`35800`.) * The :mod:`!lib2to3` module now emits a :exc:`PendingDeprecationWarning`. @@ -961,7 +960,7 @@ Removed are not supported or not enabled by NNTP server administrators. For ``xgtitle()``, please use :meth:`!nntplib.NNTP.descriptions` or :meth:`!nntplib.NNTP.description` instead. - (Contributed by Dong-hee Na in :issue:`39366`.) + (Contributed by Donghee Na in :issue:`39366`.) * :class:`array.array`: ``tostring()`` and ``fromstring()`` methods have been removed. They were aliases to ``tobytes()`` and ``frombytes()``, deprecated @@ -994,7 +993,7 @@ Removed * The :meth:`~threading.Thread.isAlive()` method of :class:`threading.Thread` has been removed. It was deprecated since Python 3.8. Use :meth:`~threading.Thread.is_alive()` instead. - (Contributed by Dong-hee Na in :issue:`37804`.) + (Contributed by Donghee Na in :issue:`37804`.) * Methods ``getchildren()`` and ``getiterator()`` of classes :class:`~xml.etree.ElementTree.ElementTree` and @@ -1315,7 +1314,7 @@ New Features * The :c:func:`PyModule_AddType` function is added to help adding a type to a module. - (Contributed by Dong-hee Na in :issue:`40024`.) + (Contributed by Donghee Na in :issue:`40024`.) * Added the functions :c:func:`PyObject_GC_IsTracked` and :c:func:`PyObject_GC_IsFinalized` to the public API to allow to query if @@ -1370,8 +1369,8 @@ Porting to Python 3.9 (Contributed by Victor Stinner in :issue:`40241`.) * The ``Py_UNICODE_COPY``, ``Py_UNICODE_FILL``, ``PyUnicode_WSTR_LENGTH``, - :c:func:`PyUnicode_FromUnicode`, :c:func:`PyUnicode_AsUnicode`, - ``_PyUnicode_AsUnicode``, and :c:func:`PyUnicode_AsUnicodeAndSize` are + :c:func:`!PyUnicode_FromUnicode`, :c:func:`!PyUnicode_AsUnicode`, + ``_PyUnicode_AsUnicode``, and :c:func:`!PyUnicode_AsUnicodeAndSize` are marked as deprecated in C. They have been deprecated by :pep:`393` since Python 3.3. (Contributed by Inada Naoki in :issue:`36346`.) diff --git a/Grammar/python.gram b/Grammar/python.gram index e7c817856d514b..174b4dbb6f7842 100644 --- a/Grammar/python.gram +++ b/Grammar/python.gram @@ -19,8 +19,6 @@ _PyPegen_parse(Parser *p) result = eval_rule(p); } else if (p->start_rule == Py_func_type_input) { result = func_type_rule(p); - } else if (p->start_rule == Py_fstring_input) { - result = fstring_rule(p); } return result; @@ -89,7 +87,6 @@ file[mod_ty]: a=[statements] ENDMARKER { _PyPegen_make_module(p, a) } interactive[mod_ty]: a=statement_newline { _PyAST_Interactive(a, p->arena) } eval[mod_ty]: a=expressions NEWLINE* ENDMARKER { _PyAST_Expression(a, p->arena) } func_type[mod_ty]: '(' a=[type_expressions] ')' '->' b=expression NEWLINE* ENDMARKER { _PyAST_FunctionType(a, b, p->arena) } -fstring[expr_ty]: star_expressions # GENERAL STATEMENTS # ================== @@ -127,6 +124,7 @@ simple_stmt[stmt_ty] (memo): | &'nonlocal' nonlocal_stmt compound_stmt[stmt_ty]: + | invalid_compound_stmt | &('def' | '@' | 'async') function_def | &'if' if_stmt | &('class' | '@') class_def @@ -394,8 +392,8 @@ for_stmt[stmt_ty]: with_stmt[stmt_ty]: | invalid_with_stmt_indent - | 'with' '(' a[asdl_withitem_seq*]=','.with_item+ ','? ')' ':' b=block { - CHECK_VERSION(stmt_ty, 9, "Parenthesized context managers are", _PyAST_With(a, b, NULL, EXTRA)) } + | 'with' '(' a[asdl_withitem_seq*]=','.with_item+ ','? ')' ':' tc=[TYPE_COMMENT] b=block { + CHECK_VERSION(stmt_ty, 9, "Parenthesized context managers are", _PyAST_With(a, b, NEW_TYPE_COMMENT(p, tc), EXTRA)) } | 'with' a[asdl_withitem_seq*]=','.with_item+ ':' tc=[TYPE_COMMENT] b=block { _PyAST_With(a, b, NEW_TYPE_COMMENT(p, tc), EXTRA) } | 'async' 'with' '(' a[asdl_withitem_seq*]=','.with_item+ ','? ')' ':' b=block { @@ -647,20 +645,20 @@ type_param_seq[asdl_type_param_seq*]: a[asdl_type_param_seq*]=','.type_param+ [' type_param[type_param_ty] (memo): | a=NAME b=[type_param_bound] { _PyAST_TypeVar(a->v.Name.id, b, EXTRA) } - | '*' a=NAME colon=":" e=expression { + | '*' a=NAME colon=':' e=expression { RAISE_SYNTAX_ERROR_STARTING_FROM(colon, e->kind == Tuple_kind ? "cannot use constraints with TypeVarTuple" : "cannot use bound with TypeVarTuple") } | '*' a=NAME { _PyAST_TypeVarTuple(a->v.Name.id, EXTRA) } - | '**' a=NAME colon=":" e=expression { + | '**' a=NAME colon=':' e=expression { RAISE_SYNTAX_ERROR_STARTING_FROM(colon, e->kind == Tuple_kind ? "cannot use constraints with ParamSpec" : "cannot use bound with ParamSpec") } | '**' a=NAME { _PyAST_ParamSpec(a->v.Name.id, EXTRA) } -type_param_bound[expr_ty]: ":" e=expression { e } +type_param_bound[expr_ty]: ':' e=expression { e } # EXPRESSIONS # ----------- @@ -915,7 +913,7 @@ fstring_middle[expr_ty]: | fstring_replacement_field | t=FSTRING_MIDDLE { _PyPegen_constant_from_token(p, t) } fstring_replacement_field[expr_ty]: - | '{' a=(yield_expr | star_expressions) debug_expr="="? conversion=[fstring_conversion] format=[fstring_full_format_spec] rbrace='}' { + | '{' a=(yield_expr | star_expressions) debug_expr='='? conversion=[fstring_conversion] format=[fstring_full_format_spec] rbrace='}' { _PyPegen_formatted_value(p, a, debug_expr, conversion, format, rbrace, EXTRA) } | invalid_replacement_field fstring_conversion[ResultTokenWithMetadata*]: @@ -970,6 +968,8 @@ for_if_clause[comprehension_ty]: CHECK_VERSION(comprehension_ty, 6, "Async comprehensions are", _PyAST_comprehension(a, b, c, 1, p->arena)) } | 'for' a=star_targets 'in' ~ b=disjunction c[asdl_expr_seq*]=('if' z=disjunction { z })* { _PyAST_comprehension(a, b, c, 0, p->arena) } + | 'async'? 'for' (bitwise_or (',' bitwise_or)* [',']) !'in' { + RAISE_SYNTAX_ERROR("'in' expected after for-loop variables") } | invalid_for_target listcomp[expr_ty]: @@ -1131,7 +1131,8 @@ func_type_comment[Token*]: # From here on, there are rules for invalid syntax with specialised error messages invalid_arguments: - | a=args ',' '*' { RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "iterable argument unpacking follows keyword argument unpacking") } + | ((','.(starred_expression | ( assignment_expression | expression !':=') !'=')+ ',' kwargs) | kwargs) ',' b='*' { + RAISE_SYNTAX_ERROR_KNOWN_LOCATION(b, "iterable argument unpacking follows keyword argument unpacking") } | a=expression b=for_if_clauses ',' [args | expression for_if_clauses] { RAISE_SYNTAX_ERROR_KNOWN_RANGE(a, _PyPegen_get_last_comprehension_item(PyPegen_last_item(b, comprehension_ty)), "Generator expression must be parenthesized") } | a=NAME b='=' expression for_if_clauses { @@ -1170,7 +1171,7 @@ invalid_expression: _PyPegen_check_legacy_stmt(p, a) ? NULL : p->tokens[p->mark-1]->level == 0 ? NULL : RAISE_SYNTAX_ERROR_KNOWN_RANGE(a, b, "invalid syntax. Perhaps you forgot a comma?") } | a=disjunction 'if' b=disjunction !('else'|':') { RAISE_SYNTAX_ERROR_KNOWN_RANGE(a, b, "expected 'else' after 'if' expression") } - | a='lambda' [lambda_params] b=':' &(FSTRING_MIDDLE | fstring_replacement_field) { + | a='lambda' [lambda_params] b=':' &FSTRING_MIDDLE { RAISE_SYNTAX_ERROR_KNOWN_RANGE(a, b, "f-string: lambda expressions are not allowed without parentheses") } invalid_named_expression(memo): @@ -1300,6 +1301,10 @@ invalid_import_from_targets: | import_from_as_names ',' NEWLINE { RAISE_SYNTAX_ERROR("trailing comma not allowed without surrounding parentheses") } +invalid_compound_stmt: + | a='elif' named_expression ':' { RAISE_SYNTAX_ERROR_STARTING_FROM(a, "'elif' must match an if-statement here") } + | a='else' ':' { RAISE_SYNTAX_ERROR_STARTING_FROM(a, "'else' must match a valid statement here") } + invalid_with_stmt: | ['async'] 'with' ','.(expression ['as' star_target])+ NEWLINE { RAISE_SYNTAX_ERROR("expected ':'") } | ['async'] 'with' '(' ','.(expressions ['as' star_target])+ ','? ')' NEWLINE { RAISE_SYNTAX_ERROR("expected ':'") } @@ -1371,11 +1376,11 @@ invalid_for_stmt: | ['async'] a='for' star_targets 'in' star_expressions ':' NEWLINE !INDENT { RAISE_INDENTATION_ERROR("expected an indented block after 'for' statement on line %d", a->lineno) } invalid_def_raw: - | ['async'] a='def' NAME '(' [params] ')' ['->' expression] ':' NEWLINE !INDENT { + | ['async'] a='def' NAME [type_params] '(' [params] ')' ['->' expression] ':' NEWLINE !INDENT { RAISE_INDENTATION_ERROR("expected an indented block after function definition on line %d", a->lineno) } invalid_class_def_raw: - | 'class' NAME ['(' [arguments] ')'] NEWLINE { RAISE_SYNTAX_ERROR("expected ':'") } - | a='class' NAME ['(' [arguments] ')'] ':' NEWLINE !INDENT { + | 'class' NAME [type_params] ['(' [arguments] ')'] NEWLINE { RAISE_SYNTAX_ERROR("expected ':'") } + | a='class' NAME [type_params] ['(' [arguments] ')'] ':' NEWLINE !INDENT { RAISE_INDENTATION_ERROR("expected an indented block after class definition on line %d", a->lineno) } invalid_double_starred_kvpairs: diff --git a/Include/Python.h b/Include/Python.h index 07f6c202a7f126..196751c3201e62 100644 --- a/Include/Python.h +++ b/Include/Python.h @@ -5,42 +5,56 @@ #ifndef Py_PYTHON_H #define Py_PYTHON_H -// Since this is a "meta-include" file, no #ifdef __cplusplus / extern "C" { +// Since this is a "meta-include" file, "#ifdef __cplusplus / extern "C" {" +// is not needed. + // Include Python header files #include "patchlevel.h" #include "pyconfig.h" #include "pymacconfig.h" -#if defined(__sgi) && !defined(_SGI_MP_SOURCE) -# define _SGI_MP_SOURCE + +// Include standard header files +#include // assert() +#include // uintptr_t +#include // INT_MAX +#include // HUGE_VAL +#include // va_list +#include // wchar_t +#ifdef HAVE_SYS_TYPES_H +# include // ssize_t #endif -// stdlib.h, stdio.h, errno.h and string.h headers are not used by Python -// headers, but kept for backward compatibility. They are excluded from the -// limited C API of Python 3.11. +// , , and headers are no longer used +// by Python, but kept for the backward compatibility of existing third party C +// extensions. They are not included by limited C API version 3.11 and newer. +// +// The and headers are not included by limited C API +// version 3.13 and newer. #if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000 -# include -# include // FILE* # include // errno +# include // FILE* +# include // getenv() # include // memcpy() #endif -#ifndef MS_WINDOWS -# include -#endif -#ifdef HAVE_STDDEF_H -# include // size_t +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030d0000 +# include // tolower() +# ifndef MS_WINDOWS +# include // close() +# endif #endif -#include // assert() -#include // wchar_t +// Include Python header files #include "pyport.h" #include "pymacro.h" #include "pymath.h" #include "pymem.h" #include "pytypedefs.h" #include "pybuffer.h" +#include "pystats.h" +#include "pyatomic.h" #include "object.h" #include "objimpl.h" #include "typeslots.h" diff --git a/Include/abstract.h b/Include/abstract.h index dd915004e7834e..bd12a54963c13f 100644 --- a/Include/abstract.h +++ b/Include/abstract.h @@ -50,6 +50,25 @@ extern "C" { This function always succeeds. */ + +/* Implemented elsewhere: + + int PyObject_HasAttrStringWithError(PyObject *o, const char *attr_name); + + Returns 1 if object 'o' has the attribute attr_name, and 0 otherwise. + This is equivalent to the Python expression: hasattr(o,attr_name). + Returns -1 on failure. */ + + +/* Implemented elsewhere: + + int PyObject_HasAttrWithError(PyObject *o, PyObject *attr_name); + + Returns 1 if o has the attribute attr_name, and 0 otherwise. + This is equivalent to the Python expression: hasattr(o,attr_name). + Returns -1 on failure. */ + + /* Implemented elsewhere: PyObject* PyObject_GetAttr(PyObject *o, PyObject *attr_name); @@ -821,6 +840,18 @@ PyAPI_FUNC(int) PyMapping_HasKeyString(PyObject *o, const char *key); This function always succeeds. */ PyAPI_FUNC(int) PyMapping_HasKey(PyObject *o, PyObject *key); +/* Return 1 if the mapping object has the key 'key', and 0 otherwise. + This is equivalent to the Python expression: key in o. + On failure, return -1. */ + +PyAPI_FUNC(int) PyMapping_HasKeyWithError(PyObject *o, PyObject *key); + +/* Return 1 if the mapping object has the key 'key', and 0 otherwise. + This is equivalent to the Python expression: key in o. + On failure, return -1. */ + +PyAPI_FUNC(int) PyMapping_HasKeyStringWithError(PyObject *o, const char *key); + /* On success, return a list or tuple of the keys in mapping object 'o'. On failure, return NULL. */ PyAPI_FUNC(PyObject *) PyMapping_Keys(PyObject *o); diff --git a/Include/boolobject.h b/Include/boolobject.h index 976fa35201d035..19aef5b1b87c6a 100644 --- a/Include/boolobject.h +++ b/Include/boolobject.h @@ -7,7 +7,7 @@ extern "C" { #endif -PyAPI_DATA(PyTypeObject) PyBool_Type; +// PyBool_Type is declared by object.h #define PyBool_Check(x) Py_IS_TYPE((x), &PyBool_Type) diff --git a/Include/bytesobject.h b/Include/bytesobject.h index ee448cd02bdab3..c5a24195be6bc3 100644 --- a/Include/bytesobject.h +++ b/Include/bytesobject.h @@ -1,5 +1,4 @@ - -/* Bytes object interface */ +// Bytes object interface #ifndef Py_BYTESOBJECT_H #define Py_BYTESOBJECT_H @@ -7,8 +6,6 @@ extern "C" { #endif -#include // va_list - /* Type PyBytesObject represents a byte string. An extra zero byte is reserved at the end to ensure it is zero-terminated, but a size is diff --git a/Include/compile.h b/Include/compile.h index 3c5acd7209f763..52d0bc76c9fca4 100644 --- a/Include/compile.h +++ b/Include/compile.h @@ -10,9 +10,6 @@ extern "C" { #define Py_eval_input 258 #define Py_func_type_input 345 -/* This doesn't need to match anything */ -#define Py_fstring_input 800 - #ifndef Py_LIMITED_API # define Py_CPYTHON_COMPILE_H # include "cpython/compile.h" diff --git a/Include/cpython/abstract.h b/Include/cpython/abstract.h index dd924dfd3d8fcc..4e7b7a46703a6d 100644 --- a/Include/cpython/abstract.h +++ b/Include/cpython/abstract.h @@ -2,6 +2,28 @@ # error "this header file must not be included directly" #endif +/* === Object Protocol ================================================== */ + +/* Like PyObject_CallMethod(), but expect a _Py_Identifier* + as the method name. */ +PyAPI_FUNC(PyObject*) _PyObject_CallMethodId( + PyObject *obj, + _Py_Identifier *name, + const char *format, ...); + +/* Convert keyword arguments from the FASTCALL (stack: C array, kwnames: tuple) + format to a Python dictionary ("kwargs" dict). + + The type of kwnames keys is not checked. The final function getting + arguments is responsible to check if all keys are strings, for example using + PyArg_ParseTupleAndKeywords() or PyArg_ValidateKeywordArguments(). + + Duplicate keys are merged using the last value. If duplicate keys must raise + an exception, the caller is responsible to implement an explicit keys on + kwnames. */ +PyAPI_FUNC(PyObject*) _PyStack_AsDict(PyObject *const *values, PyObject *kwnames); + + /* === Vectorcall protocol (PEP 590) ============================= */ // PyVectorcall_NARGS() is exported as a function for the stable ABI. @@ -16,6 +38,16 @@ _PyVectorcall_NARGS(size_t n) PyAPI_FUNC(vectorcallfunc) PyVectorcall_Function(PyObject *callable); +// Backwards compatibility aliases (PEP 590) for API that was provisional +// in Python 3.8 +#define _PyObject_Vectorcall PyObject_Vectorcall +#define _PyObject_VectorcallMethod PyObject_VectorcallMethod +#define _PyObject_FastCallDict PyObject_VectorcallDict +#define _PyVectorcall_Function PyVectorcall_Function +#define _PyObject_CallOneArg PyObject_CallOneArg +#define _PyObject_CallMethodNoArgs PyObject_CallMethodNoArgs +#define _PyObject_CallMethodOneArg PyObject_CallMethodOneArg + /* Same as PyObject_Vectorcall except that keyword arguments are passed as dict, which may be NULL if there are no keyword arguments. */ PyAPI_FUNC(PyObject *) PyObject_VectorcallDict( @@ -53,13 +85,3 @@ PyAPI_FUNC(Py_ssize_t) PyObject_LengthHint(PyObject *o, Py_ssize_t); need to be corrected for a negative index. */ #define PySequence_ITEM(o, i)\ ( Py_TYPE(o)->tp_as_sequence->sq_item((o), (i)) ) - -/* === Mapping protocol ================================================= */ - -// Convert Python int to Py_ssize_t. Do nothing if the argument is None. -// Cannot be moved to the internal C API: used by Argument Clinic. -PyAPI_FUNC(int) _Py_convert_optional_to_ssize_t(PyObject *, void *); - -// Same as PyNumber_Index but can return an instance of a subclass of int. -// Cannot be moved to the internal C API: used by Argument Clinic. -PyAPI_FUNC(PyObject *) _PyNumber_Index(PyObject *o); diff --git a/Include/cpython/ceval.h b/Include/cpython/ceval.h index 5255d715142b97..78f7405661662f 100644 --- a/Include/cpython/ceval.h +++ b/Include/cpython/ceval.h @@ -4,14 +4,9 @@ PyAPI_FUNC(void) PyEval_SetProfile(Py_tracefunc, PyObject *); PyAPI_FUNC(void) PyEval_SetProfileAllThreads(Py_tracefunc, PyObject *); -PyAPI_FUNC(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 */ -PyAPI_FUNC(PyObject *) _PyEval_GetBuiltin(PyObject *); -PyAPI_FUNC(PyObject *) _PyEval_GetBuiltinId(_Py_Identifier *); /* Look at the current frame's (if any) code's co_flags, and turn on the corresponding compiler flags in cf->cf_flags. Return 1 if any flag was set, else return 0. */ @@ -19,11 +14,6 @@ PyAPI_FUNC(int) PyEval_MergeCompilerFlags(PyCompilerFlags *cf); PyAPI_FUNC(PyObject *) _PyEval_EvalFrameDefault(PyThreadState *tstate, struct _PyInterpreterFrame *f, int exc); -PyAPI_FUNC(void) _PyEval_SetSwitchInterval(unsigned long microseconds); -PyAPI_FUNC(unsigned long) _PyEval_GetSwitchInterval(void); - -PyAPI_FUNC(int) _PyEval_MakePendingCalls(PyThreadState *); - PyAPI_FUNC(Py_ssize_t) PyUnstable_Eval_RequestCodeExtraIndex(freefunc); // Old name -- remove when this API changes: _Py_DEPRECATED_EXTERNALLY(3.12) static inline Py_ssize_t diff --git a/Include/cpython/code.h b/Include/cpython/code.h index 24c5ec23590c94..1f47d99fb60443 100644 --- a/Include/cpython/code.h +++ b/Include/cpython/code.h @@ -8,16 +8,21 @@ extern "C" { #endif - +/* Count of all local monitoring events */ +#define _PY_MONITORING_LOCAL_EVENTS 10 /* Count of all "real" monitoring events (not derived from other events) */ #define _PY_MONITORING_UNGROUPED_EVENTS 15 /* Count of all monitoring events */ #define _PY_MONITORING_EVENTS 17 -/* Table of which tools are active for each monitored event. */ -typedef struct _Py_Monitors { +/* Tables of which tools are active for each monitored event. */ +typedef struct _Py_LocalMonitors { + uint8_t tools[_PY_MONITORING_LOCAL_EVENTS]; +} _Py_LocalMonitors; + +typedef struct _Py_GlobalMonitors { uint8_t tools[_PY_MONITORING_UNGROUPED_EVENTS]; -} _Py_Monitors; +} _Py_GlobalMonitors; /* Each instruction in a code object is a fixed-width value, * currently 2 bytes: 1-byte opcode + 1-byte oparg. The EXTENDED_ARG @@ -88,9 +93,9 @@ typedef struct { */ typedef struct { /* Monitoring specific to this code object */ - _Py_Monitors local_monitors; + _Py_LocalMonitors local_monitors; /* Monitoring that is active on this code object */ - _Py_Monitors active_monitors; + _Py_LocalMonitors active_monitors; /* The tools that are to be notified for events for the matching code unit */ uint8_t *tools; /* Information to support line events */ @@ -162,7 +167,7 @@ typedef struct { PyObject *co_weakreflist; /* to support weakrefs to code objects */ \ _PyExecutorArray *co_executors; /* executors from optimizer */ \ _PyCoCached *_co_cached; /* cached co_* attributes */ \ - uint64_t _co_instrumentation_version; /* current instrumentation version */ \ + uintptr_t _co_instrumentation_version; /* current instrumentation version */ \ _PyCoMonitoringData *_co_monitoring; /* Monitoring data */ \ int _co_firsttraceable; /* index of first traceable instruction */ \ /* Scratch space for extra data relating to the code object. \ @@ -203,6 +208,8 @@ struct PyCodeObject _PyCode_DEF(1); #define CO_FUTURE_GENERATOR_STOP 0x800000 #define CO_FUTURE_ANNOTATIONS 0x1000000 +#define CO_NO_MONITORING_EVENTS 0x2000000 + /* This should be defined if a future statement modifies the syntax. For example, when a keyword is added. */ diff --git a/Include/cpython/compile.h b/Include/cpython/compile.h index e6cd39af2ba739..0d587505ef7f85 100644 --- a/Include/cpython/compile.h +++ b/Include/cpython/compile.h @@ -19,9 +19,10 @@ #define PyCF_TYPE_COMMENTS 0x1000 #define PyCF_ALLOW_TOP_LEVEL_AWAIT 0x2000 #define PyCF_ALLOW_INCOMPLETE_INPUT 0x4000 +#define PyCF_OPTIMIZED_AST (0x8000 | PyCF_ONLY_AST) #define PyCF_COMPILE_MASK (PyCF_ONLY_AST | PyCF_ALLOW_TOP_LEVEL_AWAIT | \ PyCF_TYPE_COMMENTS | PyCF_DONT_IMPLY_DEDENT | \ - PyCF_ALLOW_INCOMPLETE_INPUT) + PyCF_ALLOW_INCOMPLETE_INPUT | PyCF_OPTIMIZED_AST) typedef struct { int cf_flags; /* bitmask of CO_xxx flags relevant to future */ @@ -67,15 +68,3 @@ typedef struct { #define PY_INVALID_STACK_EFFECT INT_MAX PyAPI_FUNC(int) PyCompile_OpcodeStackEffect(int opcode, int oparg); PyAPI_FUNC(int) PyCompile_OpcodeStackEffectWithJump(int opcode, int oparg, int jump); - -PyAPI_FUNC(int) PyUnstable_OpcodeIsValid(int opcode); -PyAPI_FUNC(int) PyUnstable_OpcodeHasArg(int opcode); -PyAPI_FUNC(int) PyUnstable_OpcodeHasConst(int opcode); -PyAPI_FUNC(int) PyUnstable_OpcodeHasName(int opcode); -PyAPI_FUNC(int) PyUnstable_OpcodeHasJump(int opcode); -PyAPI_FUNC(int) PyUnstable_OpcodeHasFree(int opcode); -PyAPI_FUNC(int) PyUnstable_OpcodeHasLocal(int opcode); -PyAPI_FUNC(int) PyUnstable_OpcodeHasExc(int opcode); - -PyAPI_FUNC(PyObject*) _PyUnstable_GetUnaryIntrinsicName(int index); -PyAPI_FUNC(PyObject*) _PyUnstable_GetBinaryIntrinsicName(int index); diff --git a/Include/cpython/complexobject.h b/Include/cpython/complexobject.h index b524ec42c24371..fbdc6a91fe895c 100644 --- a/Include/cpython/complexobject.h +++ b/Include/cpython/complexobject.h @@ -7,6 +7,16 @@ typedef struct { double imag; } Py_complex; +// Operations on complex numbers. +PyAPI_FUNC(Py_complex) _Py_c_sum(Py_complex, Py_complex); +PyAPI_FUNC(Py_complex) _Py_c_diff(Py_complex, Py_complex); +PyAPI_FUNC(Py_complex) _Py_c_neg(Py_complex); +PyAPI_FUNC(Py_complex) _Py_c_prod(Py_complex, Py_complex); +PyAPI_FUNC(Py_complex) _Py_c_quot(Py_complex, Py_complex); +PyAPI_FUNC(Py_complex) _Py_c_pow(Py_complex, Py_complex); +PyAPI_FUNC(double) _Py_c_abs(Py_complex); + + /* Complex object interface */ /* diff --git a/Include/cpython/context.h b/Include/cpython/context.h index 9879fc7192ebb8..a3249fc29b082e 100644 --- a/Include/cpython/context.h +++ b/Include/cpython/context.h @@ -67,10 +67,6 @@ PyAPI_FUNC(PyObject *) PyContextVar_Set(PyObject *var, PyObject *value); PyAPI_FUNC(int) PyContextVar_Reset(PyObject *var, PyObject *token); -/* This method is exposed only for CPython tests. Don not use it. */ -PyAPI_FUNC(PyObject *) _PyContext_NewHamtForTests(void); - - #ifdef __cplusplus } #endif diff --git a/Include/cpython/dictobject.h b/Include/cpython/dictobject.h index 2a42794fdf0c85..944965fb9e5351 100644 --- a/Include/cpython/dictobject.h +++ b/Include/cpython/dictobject.h @@ -33,19 +33,10 @@ typedef struct { } PyDictObject; PyAPI_FUNC(PyObject *) _PyDict_GetItem_KnownHash(PyObject *mp, PyObject *key, - Py_hash_t hash); -PyAPI_FUNC(PyObject *) _PyDict_GetItemIdWithError(PyObject *dp, - _Py_Identifier *key); + Py_hash_t hash); PyAPI_FUNC(PyObject *) _PyDict_GetItemStringWithError(PyObject *, const char *); PyAPI_FUNC(PyObject *) PyDict_SetDefault( PyObject *mp, PyObject *key, PyObject *defaultobj); -PyAPI_FUNC(int) _PyDict_SetItem_KnownHash(PyObject *mp, PyObject *key, - PyObject *item, Py_hash_t hash); -PyAPI_FUNC(int) _PyDict_DelItem_KnownHash(PyObject *mp, PyObject *key, - Py_hash_t hash); - -PyAPI_FUNC(int) _PyDict_Next( - PyObject *mp, Py_ssize_t *pos, PyObject **key, PyObject **value, Py_hash_t *hash); /* Get the number of items of a dictionary. */ static inline Py_ssize_t PyDict_GET_SIZE(PyObject *op) { @@ -56,26 +47,13 @@ static inline Py_ssize_t PyDict_GET_SIZE(PyObject *op) { } #define PyDict_GET_SIZE(op) PyDict_GET_SIZE(_PyObject_CAST(op)) -PyAPI_FUNC(int) _PyDict_ContainsId(PyObject *, _Py_Identifier *); +PyAPI_FUNC(int) PyDict_ContainsString(PyObject *mp, const char *key); PyAPI_FUNC(PyObject *) _PyDict_NewPresized(Py_ssize_t minused); -PyAPI_FUNC(Py_ssize_t) _PyDict_SizeOf(PyDictObject *); -PyAPI_FUNC(PyObject *) _PyDict_Pop(PyObject *, PyObject *, PyObject *); -#define _PyDict_HasSplitTable(d) ((d)->ma_values != NULL) - -PyAPI_FUNC(int) _PyDict_SetItemId(PyObject *dp, _Py_Identifier *key, PyObject *item); - -PyAPI_FUNC(int) _PyDict_DelItemId(PyObject *mp, _Py_Identifier *key); - -/* _PyDictView */ - -typedef struct { - PyObject_HEAD - PyDictObject *dv_dict; -} _PyDictViewObject; -PyAPI_FUNC(PyObject *) _PyDictView_New(PyObject *, PyTypeObject *); -PyAPI_FUNC(PyObject *) _PyDictView_Intersect(PyObject* self, PyObject *other); +PyAPI_FUNC(int) PyDict_Pop(PyObject *dict, PyObject *key, PyObject **result); +PyAPI_FUNC(int) PyDict_PopString(PyObject *dict, const char *key, PyObject **result); +PyAPI_FUNC(PyObject *) _PyDict_Pop(PyObject *dict, PyObject *key, PyObject *default_value); /* Dictionary watchers */ diff --git a/Include/cpython/fileobject.h b/Include/cpython/fileobject.h index b70ec318986d82..e2d89c522bdd13 100644 --- a/Include/cpython/fileobject.h +++ b/Include/cpython/fileobject.h @@ -3,7 +3,6 @@ #endif PyAPI_FUNC(char *) Py_UniversalNewlineFgets(char *, int, FILE*, PyObject *); -PyAPI_FUNC(char *) _Py_UniversalNewlineFgetsWithSize(char *, int, FILE*, PyObject *, size_t*); /* The std printer acts as a preliminary sys.stderr until the new io infrastructure is in place. */ @@ -15,5 +14,3 @@ typedef PyObject * (*Py_OpenCodeHookFunction)(PyObject *, void *); PyAPI_FUNC(PyObject *) PyFile_OpenCode(const char *utf8path); PyAPI_FUNC(PyObject *) PyFile_OpenCodeObject(PyObject *path); PyAPI_FUNC(int) PyFile_SetOpenCodeHook(Py_OpenCodeHookFunction hook, void *userData); - -PyAPI_FUNC(int) _PyLong_FileDescriptor_Converter(PyObject *, void *); diff --git a/Include/cpython/import.h b/Include/cpython/import.h index cdfdd15bfa48d2..7daf0b84fcf71b 100644 --- a/Include/cpython/import.h +++ b/Include/cpython/import.h @@ -17,7 +17,6 @@ struct _frozen { const unsigned char *code; int size; int is_package; - PyObject *(*get_code)(void); }; /* Embedding apps may change this pointer to point to their favorite diff --git a/Include/cpython/initconfig.h b/Include/cpython/initconfig.h index cbae97f12f5377..87c059c521cbc9 100644 --- a/Include/cpython/initconfig.h +++ b/Include/cpython/initconfig.h @@ -25,7 +25,6 @@ PyAPI_FUNC(PyStatus) PyStatus_Exit(int exitcode); PyAPI_FUNC(int) PyStatus_IsError(PyStatus err); PyAPI_FUNC(int) PyStatus_IsExit(PyStatus err); PyAPI_FUNC(int) PyStatus_Exception(PyStatus err); -PyAPI_FUNC(PyObject *) _PyErr_SetFromPyStatus(PyStatus status); /* --- PyWideStringList ------------------------------------------------ */ @@ -181,6 +180,8 @@ typedef struct PyConfig { int safe_path; int int_max_str_digits; + int cpu_count; + /* --- Path configuration inputs ------------ */ int pathconfig_warnings; wchar_t *program_name; @@ -205,6 +206,9 @@ typedef struct PyConfig { wchar_t *run_module; wchar_t *run_filename; + /* --- Set by Py_Main() -------------------------- */ + wchar_t *sys_path_0; + /* --- Private fields ---------------------------- */ // Install importlib? If equals to 0, importlib is not initialized at all. @@ -216,6 +220,17 @@ typedef struct PyConfig { // If non-zero, we believe we're running from a source tree. int _is_python_build; + +#ifdef Py_STATS + // If non-zero, turns on statistics gathering. + int _pystats; +#endif + +#ifdef Py_DEBUG + // If not empty, import a non-__main__ module before site.py is executed. + // PYTHON_PRESITE=package.module or -X presite=package.module + wchar_t *run_presite; +#endif } PyConfig; PyAPI_FUNC(void) PyConfig_InitPythonConfig(PyConfig *config); diff --git a/Include/cpython/listobject.h b/Include/cpython/listobject.h index b3b23985de7a66..8ade1b164681f9 100644 --- a/Include/cpython/listobject.h +++ b/Include/cpython/listobject.h @@ -21,9 +21,6 @@ typedef struct { Py_ssize_t allocated; } PyListObject; -PyAPI_FUNC(PyObject *) _PyList_Extend(PyListObject *, PyObject *); -PyAPI_FUNC(void) _PyList_DebugMallocStats(FILE *out); - /* Cast argument to PyListObject* type. */ #define _PyList_CAST(op) \ (assert(PyList_Check(op)), _Py_CAST(PyListObject*, (op))) @@ -42,8 +39,11 @@ static inline void PyList_SET_ITEM(PyObject *op, Py_ssize_t index, PyObject *value) { PyListObject *list = _PyList_CAST(op); assert(0 <= index); - assert(index < Py_SIZE(list)); + assert(index < list->allocated); list->ob_item[index] = value; } #define PyList_SET_ITEM(op, index, value) \ PyList_SET_ITEM(_PyObject_CAST(op), (index), _PyObject_CAST(value)) + +PyAPI_FUNC(int) PyList_Extend(PyObject *self, PyObject *iterable); +PyAPI_FUNC(int) PyList_Clear(PyObject *self); diff --git a/Include/cpython/longintrepr.h b/Include/cpython/longintrepr.h index 692c69ba76db2f..f5ccbb704e8bb8 100644 --- a/Include/cpython/longintrepr.h +++ b/Include/cpython/longintrepr.h @@ -89,13 +89,15 @@ struct _longobject { _PyLongValue long_value; }; -PyAPI_FUNC(PyLongObject *) _PyLong_New(Py_ssize_t); +PyAPI_FUNC(PyLongObject*) _PyLong_New(Py_ssize_t); -/* Return a copy of src. */ -PyAPI_FUNC(PyObject *) _PyLong_Copy(PyLongObject *src); +// Return a copy of src. +PyAPI_FUNC(PyObject*) _PyLong_Copy(PyLongObject *src); -PyAPI_FUNC(PyLongObject *) -_PyLong_FromDigits(int negative, Py_ssize_t digit_count, digit *digits); +PyAPI_FUNC(PyLongObject*) _PyLong_FromDigits( + int negative, + Py_ssize_t digit_count, + digit *digits); /* Inline some internals for speed. These should be in pycore_long.h diff --git a/Include/cpython/longobject.h b/Include/cpython/longobject.h index 90cc0f267ae833..fd1be29ed397d1 100644 --- a/Include/cpython/longobject.h +++ b/Include/cpython/longobject.h @@ -2,48 +2,16 @@ # error "this header file must not be included directly" #endif -PyAPI_FUNC(int) _PyLong_AsInt(PyObject *); +PyAPI_FUNC(PyObject*) PyLong_FromUnicodeObject(PyObject *u, int base); -PyAPI_FUNC(int) _PyLong_UnsignedShort_Converter(PyObject *, void *); -PyAPI_FUNC(int) _PyLong_UnsignedInt_Converter(PyObject *, void *); -PyAPI_FUNC(int) _PyLong_UnsignedLong_Converter(PyObject *, void *); -PyAPI_FUNC(int) _PyLong_UnsignedLongLong_Converter(PyObject *, void *); -PyAPI_FUNC(int) _PyLong_Size_t_Converter(PyObject *, void *); - -/* _PyLong_Frexp returns a double x and an exponent e such that the - true value is approximately equal to x * 2**e. e is >= 0. x is - 0.0 if and only if the input is 0 (in which case, e and x are both - zeroes); otherwise, 0.5 <= abs(x) < 1.0. On overflow, which is - possible if the number of bits doesn't fit into a Py_ssize_t, sets - OverflowError and returns -1.0 for x, 0 for e. */ -PyAPI_FUNC(double) _PyLong_Frexp(PyLongObject *a, Py_ssize_t *e); - -PyAPI_FUNC(PyObject *) PyLong_FromUnicodeObject(PyObject *u, int base); -PyAPI_FUNC(PyObject *) _PyLong_FromBytes(const char *, Py_ssize_t, int); +PyAPI_FUNC(int) PyUnstable_Long_IsCompact(const PyLongObject* op); +PyAPI_FUNC(Py_ssize_t) PyUnstable_Long_CompactValue(const PyLongObject* op); -/* _PyLong_Sign. Return 0 if v is 0, -1 if v < 0, +1 if v > 0. - v must not be NULL, and must be a normalized long. - There are no error cases. -*/ +// _PyLong_Sign. Return 0 if v is 0, -1 if v < 0, +1 if v > 0. +// v must not be NULL, and must be a normalized long. +// There are no error cases. PyAPI_FUNC(int) _PyLong_Sign(PyObject *v); -/* _PyLong_NumBits. Return the number of bits needed to represent the - absolute value of a long. For example, this returns 1 for 1 and -1, 2 - for 2 and -2, and 2 for 3 and -3. It returns 0 for 0. - v must not be NULL, and must be a normalized long. - (size_t)-1 is returned and OverflowError set if the true result doesn't - fit in a size_t. -*/ -PyAPI_FUNC(size_t) _PyLong_NumBits(PyObject *v); - -/* _PyLong_DivmodNear. Given integers a and b, compute the nearest - integer q to the exact quotient a / b, rounding to the nearest even integer - in the case of a tie. Return (q, r), where r = a - q*b. The remainder r - will satisfy abs(r) <= abs(b)/2, with equality possible only if q is - even. -*/ -PyAPI_FUNC(PyObject *) _PyLong_DivmodNear(PyObject *, PyObject *); - /* _PyLong_FromByteArray: View the n unsigned bytes as a binary integer in base 256, and return a Python int with the same numeric value. If n is 0, the integer is 0. Else: @@ -84,17 +52,5 @@ PyAPI_FUNC(int) _PyLong_AsByteArray(PyLongObject* v, unsigned char* bytes, size_t n, int little_endian, int is_signed); -/* _PyLong_Format: Convert the long to a string object with given base, - appending a base prefix of 0[box] if base is 2, 8 or 16. */ -PyAPI_FUNC(PyObject *) _PyLong_Format(PyObject *obj, int base); - /* For use by the gcd function in mathmodule.c */ PyAPI_FUNC(PyObject *) _PyLong_GCD(PyObject *, PyObject *); - -PyAPI_FUNC(PyObject *) _PyLong_Rshift(PyObject *, size_t); -PyAPI_FUNC(PyObject *) _PyLong_Lshift(PyObject *, size_t); - - -PyAPI_FUNC(int) PyUnstable_Long_IsCompact(const PyLongObject* op); -PyAPI_FUNC(Py_ssize_t) PyUnstable_Long_CompactValue(const PyLongObject* op); - diff --git a/Include/cpython/memoryobject.h b/Include/cpython/memoryobject.h index 3837fa8c6ab5aa..961161b70f2058 100644 --- a/Include/cpython/memoryobject.h +++ b/Include/cpython/memoryobject.h @@ -2,8 +2,6 @@ # error "this header file must not be included directly" #endif -PyAPI_DATA(PyTypeObject) _PyManagedBuffer_Type; - /* The structs are declared here so that macros can work, but they shouldn't be considered public. Don't access their fields directly, use the macros and functions instead! */ diff --git a/Include/cpython/modsupport.h b/Include/cpython/modsupport.h deleted file mode 100644 index cfc2c2cdb5a7f4..00000000000000 --- a/Include/cpython/modsupport.h +++ /dev/null @@ -1,73 +0,0 @@ -#ifndef Py_CPYTHON_MODSUPPORT_H -# error "this header file must not be included directly" -#endif - -PyAPI_FUNC(int) _PyArg_UnpackStack( - PyObject *const *args, - Py_ssize_t nargs, - const char *name, - Py_ssize_t min, - Py_ssize_t max, - ...); - -PyAPI_FUNC(int) _PyArg_NoKeywords(const char *funcname, PyObject *kwargs); -PyAPI_FUNC(int) _PyArg_NoPositional(const char *funcname, PyObject *args); -#define _PyArg_NoKeywords(funcname, kwargs) \ - ((kwargs) == NULL || _PyArg_NoKeywords((funcname), (kwargs))) -#define _PyArg_NoPositional(funcname, args) \ - ((args) == NULL || _PyArg_NoPositional((funcname), (args))) - -#define _Py_ANY_VARARGS(n) ((n) == PY_SSIZE_T_MAX) - -PyAPI_FUNC(void) _PyArg_BadArgument(const char *, const char *, const char *, PyObject *); -PyAPI_FUNC(int) _PyArg_CheckPositional(const char *, Py_ssize_t, - Py_ssize_t, Py_ssize_t); -#define _PyArg_CheckPositional(funcname, nargs, min, max) \ - ((!_Py_ANY_VARARGS(max) && (min) <= (nargs) && (nargs) <= (max)) \ - || _PyArg_CheckPositional((funcname), (nargs), (min), (max))) - -typedef struct _PyArg_Parser { - int initialized; - const char *format; - const char * const *keywords; - const char *fname; - const char *custom_msg; - int pos; /* number of positional-only arguments */ - int min; /* minimal number of arguments */ - int max; /* maximal number of positional arguments */ - PyObject *kwtuple; /* tuple of keyword parameter names */ - struct _PyArg_Parser *next; -} _PyArg_Parser; - -PyAPI_FUNC(int) _PyArg_ParseTupleAndKeywordsFast(PyObject *, PyObject *, - struct _PyArg_Parser *, ...); -PyAPI_FUNC(int) _PyArg_ParseStack( - PyObject *const *args, - Py_ssize_t nargs, - const char *format, - ...); -PyAPI_FUNC(int) _PyArg_ParseStackAndKeywords( - PyObject *const *args, - Py_ssize_t nargs, - PyObject *kwnames, - struct _PyArg_Parser *, - ...); -PyAPI_FUNC(PyObject * const *) _PyArg_UnpackKeywords( - PyObject *const *args, Py_ssize_t nargs, - PyObject *kwargs, PyObject *kwnames, - struct _PyArg_Parser *parser, - int minpos, int maxpos, int minkw, - PyObject **buf); - -PyAPI_FUNC(PyObject * const *) _PyArg_UnpackKeywordsWithVararg( - PyObject *const *args, Py_ssize_t nargs, - PyObject *kwargs, PyObject *kwnames, - struct _PyArg_Parser *parser, - int minpos, int maxpos, int minkw, - int vararg, PyObject **buf); - -#define _PyArg_UnpackKeywords(args, nargs, kwargs, kwnames, parser, minpos, maxpos, minkw, buf) \ - (((minkw) == 0 && (kwargs) == NULL && (kwnames) == NULL && \ - (minpos) <= (nargs) && (nargs) <= (maxpos) && (args) != NULL) ? (args) : \ - _PyArg_UnpackKeywords((args), (nargs), (kwargs), (kwnames), (parser), \ - (minpos), (maxpos), (minkw), (buf))) diff --git a/Include/cpython/object.h b/Include/cpython/object.h index fd45fa57e6282b..c93931634fee05 100644 --- a/Include/cpython/object.h +++ b/Include/cpython/object.h @@ -4,11 +4,7 @@ PyAPI_FUNC(void) _Py_NewReference(PyObject *op); PyAPI_FUNC(void) _Py_NewReferenceNoTotal(PyObject *op); - -#ifdef Py_TRACE_REFS -/* Py_TRACE_REFS is such major surgery that we call external routines. */ -PyAPI_FUNC(void) _Py_ForgetReference(PyObject *); -#endif +PyAPI_FUNC(void) _Py_ResurrectReference(PyObject *op); #ifdef Py_REF_DEBUG /* These are useful as debugging aids when chasing down refleaks. */ @@ -44,6 +40,10 @@ typedef struct _Py_Identifier { // Index in PyInterpreterState.unicode.ids.array. It is process-wide // unique and must be initialized to -1. Py_ssize_t index; + // Hidden PyMutex struct for non free-threaded build. + struct { + uint8_t v; + } mutex; } _Py_Identifier; #ifndef Py_BUILD_CORE @@ -56,6 +56,7 @@ typedef struct _Py_Identifier { #endif /* !Py_BUILD_CORE */ + typedef struct { /* Number implementations must check *both* arguments for proper type and implement the necessary conversions @@ -227,7 +228,7 @@ struct _typeobject { vectorcallfunc tp_vectorcall; /* bitset of which type-watchers care about this type */ - char tp_watched; + unsigned char tp_watched; }; /* This struct is used by the specializer @@ -273,8 +274,6 @@ typedef struct _heaptypeobject { PyAPI_FUNC(const char *) _PyType_Name(PyTypeObject *); PyAPI_FUNC(PyObject *) _PyType_Lookup(PyTypeObject *, PyObject *); -PyAPI_FUNC(PyObject *) _PyType_LookupId(PyTypeObject *, _Py_Identifier *); -PyAPI_FUNC(PyObject *) _PyObject_LookupSpecialId(PyObject *, _Py_Identifier *); PyAPI_FUNC(PyObject *) PyType_GetModuleByDef(PyTypeObject *, PyModuleDef *); PyAPI_FUNC(PyObject *) PyType_GetDict(PyTypeObject *); @@ -282,8 +281,7 @@ PyAPI_FUNC(int) PyObject_Print(PyObject *, FILE *, int); PyAPI_FUNC(void) _Py_BreakPoint(void); PyAPI_FUNC(void) _PyObject_Dump(PyObject *); -PyAPI_FUNC(PyObject *) _PyObject_GetAttrId(PyObject *, _Py_Identifier *); -PyAPI_FUNC(int) _PyObject_SetAttrId(PyObject *, _Py_Identifier *, PyObject *); +PyAPI_FUNC(PyObject*) _PyObject_GetAttrId(PyObject *, _Py_Identifier *); PyAPI_FUNC(PyObject **) _PyObject_GetDictPtr(PyObject *); PyAPI_FUNC(void) PyObject_CallFinalizer(PyObject *); @@ -472,7 +470,7 @@ PyAPI_FUNC(int) _PyTrash_cond(PyObject *op, destructor dealloc); /* If "cond" is false, then _tstate remains NULL and the deallocator \ * is run normally without involving the trashcan */ \ if (cond) { \ - _tstate = _PyThreadState_UncheckedGet(); \ + _tstate = PyThreadState_GetUnchecked(); \ if (_PyTrash_begin(_tstate, _PyObject_CAST(op))) { \ break; \ } \ @@ -491,8 +489,8 @@ PyAPI_FUNC(int) _PyTrash_cond(PyObject *op, destructor dealloc); PyAPI_FUNC(void *) PyObject_GetItemData(PyObject *obj); -PyAPI_FUNC(int) _PyObject_VisitManagedDict(PyObject *obj, visitproc visit, void *arg); -PyAPI_FUNC(void) _PyObject_ClearManagedDict(PyObject *obj); +PyAPI_FUNC(int) PyObject_VisitManagedDict(PyObject *obj, visitproc visit, void *arg); +PyAPI_FUNC(void) PyObject_ClearManagedDict(PyObject *obj); #define TYPE_MAX_WATCHERS 8 diff --git a/Include/cpython/optimizer.h b/Include/cpython/optimizer.h index da34ec1882a539..0e7bc9fdd7a07d 100644 --- a/Include/cpython/optimizer.h +++ b/Include/cpython/optimizer.h @@ -6,15 +6,31 @@ extern "C" { #endif +typedef struct _PyExecutorLinkListNode { + struct _PyExecutorObject *next; + struct _PyExecutorObject *previous; +} _PyExecutorLinkListNode; + + +/* Bloom filter with m = 256 + * https://en.wikipedia.org/wiki/Bloom_filter */ +#define BLOOM_FILTER_WORDS 8 + +typedef struct _bloom_filter { + uint32_t bits[BLOOM_FILTER_WORDS]; +} _PyBloomFilter; + typedef struct { uint8_t opcode; uint8_t oparg; + uint8_t valid; + uint8_t linked; + _PyBloomFilter bloom; + _PyExecutorLinkListNode links; } _PyVMData; typedef struct _PyExecutorObject { PyObject_VAR_HEAD - /* WARNING: execute consumes a reference to self. This is necessary to allow executors to tail call into each other. */ - struct _PyInterpreterFrame *(*execute)(struct _PyExecutorObject *self, struct _PyInterpreterFrame *frame, PyObject **stack_pointer); _PyVMData vm_data; /* Used by the VM, but opaque to the optimizer */ /* Data needed by the executor goes here, but is opaque to the VM */ } _PyExecutorObject; @@ -22,34 +38,52 @@ typedef struct _PyExecutorObject { typedef struct _PyOptimizerObject _PyOptimizerObject; /* Should return > 0 if a new executor is created. O if no executor is produced and < 0 if an error occurred. */ -typedef int (*optimize_func)(_PyOptimizerObject* self, PyCodeObject *code, _Py_CODEUNIT *instr, _PyExecutorObject **); +typedef int (*optimize_func)(_PyOptimizerObject* self, PyCodeObject *code, _Py_CODEUNIT *instr, _PyExecutorObject **, int curr_stackentries); typedef struct _PyOptimizerObject { PyObject_HEAD optimize_func optimize; + /* These thresholds are treated as signed so do not exceed INT16_MAX + * Use INT16_MAX to indicate that the optimizer should never be called */ uint16_t resume_threshold; uint16_t backedge_threshold; /* Data needed by the optimizer goes here, but is opaque to the VM */ } _PyOptimizerObject; +/** Test support **/ +typedef struct { + _PyOptimizerObject base; + int64_t count; +} _PyCounterOptimizerObject; + PyAPI_FUNC(int) PyUnstable_Replace_Executor(PyCodeObject *code, _Py_CODEUNIT *instr, _PyExecutorObject *executor); PyAPI_FUNC(void) PyUnstable_SetOptimizer(_PyOptimizerObject* optimizer); PyAPI_FUNC(_PyOptimizerObject *) PyUnstable_GetOptimizer(void); -PyAPI_FUNC(_PyExecutorObject *)PyUnstable_GetExecutor(PyCodeObject *code, int offset); +PyAPI_FUNC(_PyExecutorObject *) PyUnstable_GetExecutor(PyCodeObject *code, int offset); -struct _PyInterpreterFrame * -_PyOptimizer_BackEdge(struct _PyInterpreterFrame *frame, _Py_CODEUNIT *src, _Py_CODEUNIT *dest, PyObject **stack_pointer); +int +_PyOptimizer_Optimize(struct _PyInterpreterFrame *frame, _Py_CODEUNIT *start, PyObject **stack_pointer); extern _PyOptimizerObject _PyOptimizer_Default; +void _Py_ExecutorInit(_PyExecutorObject *, _PyBloomFilter *); +void _Py_ExecutorClear(_PyExecutorObject *); +void _Py_BloomFilter_Init(_PyBloomFilter *); +void _Py_BloomFilter_Add(_PyBloomFilter *bloom, void *obj); +PyAPI_FUNC(void) _Py_Executor_DependsOn(_PyExecutorObject *executor, void *obj); +PyAPI_FUNC(void) _Py_Executors_InvalidateDependency(PyInterpreterState *interp, void *obj); +extern void _Py_Executors_InvalidateAll(PyInterpreterState *interp); + /* For testing */ PyAPI_FUNC(PyObject *)PyUnstable_Optimizer_NewCounter(void); PyAPI_FUNC(PyObject *)PyUnstable_Optimizer_NewUOpOptimizer(void); #define OPTIMIZER_BITS_IN_COUNTER 4 +/* Minimum of 16 additional executions before retry */ +#define MINIMUM_TIER2_BACKOFF 4 #ifdef __cplusplus } diff --git a/Include/cpython/pthread_stubs.h b/Include/cpython/pthread_stubs.h index d95ee03d8308ce..e542eaa5bff0cf 100644 --- a/Include/cpython/pthread_stubs.h +++ b/Include/cpython/pthread_stubs.h @@ -21,13 +21,29 @@ #ifdef __wasi__ // WASI's bits/alltypes.h provides type definitions when __NEED_ is set. // The header file can be included multiple times. -# define __NEED_pthread_cond_t 1 -# define __NEED_pthread_condattr_t 1 -# define __NEED_pthread_mutex_t 1 -# define __NEED_pthread_mutexattr_t 1 -# define __NEED_pthread_key_t 1 -# define __NEED_pthread_t 1 -# define __NEED_pthread_attr_t 1 +// +// may also define these macros. +# ifndef __NEED_pthread_cond_t +# define __NEED_pthread_cond_t 1 +# endif +# ifndef __NEED_pthread_condattr_t +# define __NEED_pthread_condattr_t 1 +# endif +# ifndef __NEED_pthread_mutex_t +# define __NEED_pthread_mutex_t 1 +# endif +# ifndef __NEED_pthread_mutexattr_t +# define __NEED_pthread_mutexattr_t 1 +# endif +# ifndef __NEED_pthread_key_t +# define __NEED_pthread_key_t 1 +# endif +# ifndef __NEED_pthread_t +# define __NEED_pthread_t 1 +# endif +# ifndef __NEED_pthread_attr_t +# define __NEED_pthread_attr_t 1 +# endif # include #else typedef struct { void *__x; } pthread_cond_t; @@ -67,6 +83,7 @@ PyAPI_FUNC(int) pthread_create(pthread_t *restrict thread, void *(*start_routine)(void *), void *restrict arg); PyAPI_FUNC(int) pthread_detach(pthread_t thread); +PyAPI_FUNC(int) pthread_join(pthread_t thread, void** value_ptr); PyAPI_FUNC(pthread_t) pthread_self(void); PyAPI_FUNC(int) pthread_exit(void *retval) __attribute__ ((__noreturn__)); PyAPI_FUNC(int) pthread_attr_init(pthread_attr_t *attr); diff --git a/Include/cpython/pyatomic.h b/Include/cpython/pyatomic.h new file mode 100644 index 00000000000000..5314a70436bfc3 --- /dev/null +++ b/Include/cpython/pyatomic.h @@ -0,0 +1,534 @@ +// This header provides cross-platform low-level atomic operations +// similar to C11 atomics. +// +// Operations are sequentially consistent unless they have a suffix indicating +// otherwise. If in doubt, prefer the sequentially consistent operations. +// +// The "_relaxed" suffix for load and store operations indicates the "relaxed" +// memory order. They don't provide synchronization, but (roughly speaking) +// guarantee somewhat sane behavior for races instead of undefined behavior. +// In practice, they correspond to "normal" hardware load and store +// instructions, so they are almost as inexpensive as plain loads and stores +// in C. +// +// Note that atomic read-modify-write operations like _Py_atomic_add_* return +// the previous value of the atomic variable, not the new value. +// +// See https://en.cppreference.com/w/c/atomic for more information on C11 +// atomics. +// See https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p2055r0.pdf +// "A Relaxed Guide to memory_order_relaxed" for discussion of and common usage +// or relaxed atomics. +// +// Functions with pseudo Python code: +// +// def _Py_atomic_load(obj): +// return obj # sequential consistency +// +// def _Py_atomic_load_relaxed(obj): +// return obj # relaxed consistency +// +// def _Py_atomic_store(obj, value): +// obj = value # sequential consistency +// +// def _Py_atomic_store_relaxed(obj, value): +// obj = value # relaxed consistency +// +// def _Py_atomic_exchange(obj, value): +// # sequential consistency +// old_obj = obj +// obj = value +// return old_obj +// +// def _Py_atomic_compare_exchange(obj, expected, desired): +// # sequential consistency +// if obj == expected: +// obj = desired +// return True +// else: +// expected = obj +// return False +// +// def _Py_atomic_add(obj, value): +// # sequential consistency +// old_obj = obj +// obj += value +// return old_obj +// +// def _Py_atomic_and(obj, value): +// # sequential consistency +// old_obj = obj +// obj &= value +// return old_obj +// +// def _Py_atomic_or(obj, value): +// # sequential consistency +// old_obj = obj +// obj |= value +// return old_obj +// +// Other functions: +// +// def _Py_atomic_load_ptr_acquire(obj): +// return obj # acquire +// +// def _Py_atomic_store_ptr_release(obj): +// return obj # release +// +// def _Py_atomic_fence_seq_cst(): +// # sequential consistency +// ... +// +// def _Py_atomic_fence_release(): +// # release +// ... + +#ifndef Py_CPYTHON_ATOMIC_H +# error "this header file must not be included directly" +#endif + +// --- _Py_atomic_add -------------------------------------------------------- +// Atomically adds `value` to `obj` and returns the previous value + +static inline int +_Py_atomic_add_int(int *obj, int value); + +static inline int8_t +_Py_atomic_add_int8(int8_t *obj, int8_t value); + +static inline int16_t +_Py_atomic_add_int16(int16_t *obj, int16_t value); + +static inline int32_t +_Py_atomic_add_int32(int32_t *obj, int32_t value); + +static inline int64_t +_Py_atomic_add_int64(int64_t *obj, int64_t value); + +static inline intptr_t +_Py_atomic_add_intptr(intptr_t *obj, intptr_t value); + +static inline unsigned int +_Py_atomic_add_uint(unsigned int *obj, unsigned int value); + +static inline uint8_t +_Py_atomic_add_uint8(uint8_t *obj, uint8_t value); + +static inline uint16_t +_Py_atomic_add_uint16(uint16_t *obj, uint16_t value); + +static inline uint32_t +_Py_atomic_add_uint32(uint32_t *obj, uint32_t value); + +static inline uint64_t +_Py_atomic_add_uint64(uint64_t *obj, uint64_t value); + +static inline uintptr_t +_Py_atomic_add_uintptr(uintptr_t *obj, uintptr_t value); + +static inline Py_ssize_t +_Py_atomic_add_ssize(Py_ssize_t *obj, Py_ssize_t value); + + +// --- _Py_atomic_compare_exchange ------------------------------------------- +// Performs an atomic compare-and-exchange. +// +// - If `*obj` and `*expected` are equal, store `desired` into `*obj` +// and return 1 (success). +// - Otherwise, store the `*obj` current value into `*expected` +// and return 0 (failure). +// +// These correspond to the C11 atomic_compare_exchange_strong() function. + +static inline int +_Py_atomic_compare_exchange_int(int *obj, int *expected, int desired); + +static inline int +_Py_atomic_compare_exchange_int8(int8_t *obj, int8_t *expected, int8_t desired); + +static inline int +_Py_atomic_compare_exchange_int16(int16_t *obj, int16_t *expected, int16_t desired); + +static inline int +_Py_atomic_compare_exchange_int32(int32_t *obj, int32_t *expected, int32_t desired); + +static inline int +_Py_atomic_compare_exchange_int64(int64_t *obj, int64_t *expected, int64_t desired); + +static inline int +_Py_atomic_compare_exchange_intptr(intptr_t *obj, intptr_t *expected, intptr_t desired); + +static inline int +_Py_atomic_compare_exchange_uint(unsigned int *obj, unsigned int *expected, unsigned int desired); + +static inline int +_Py_atomic_compare_exchange_uint8(uint8_t *obj, uint8_t *expected, uint8_t desired); + +static inline int +_Py_atomic_compare_exchange_uint16(uint16_t *obj, uint16_t *expected, uint16_t desired); + +static inline int +_Py_atomic_compare_exchange_uint32(uint32_t *obj, uint32_t *expected, uint32_t desired); + +static inline int +_Py_atomic_compare_exchange_uint64(uint64_t *obj, uint64_t *expected, uint64_t desired); + +static inline int +_Py_atomic_compare_exchange_uintptr(uintptr_t *obj, uintptr_t *expected, uintptr_t desired); + +static inline int +_Py_atomic_compare_exchange_ssize(Py_ssize_t *obj, Py_ssize_t *expected, Py_ssize_t desired); + +// NOTE: `obj` and `expected` are logically `void**` types, but we use `void*` +// so that we can pass types like `PyObject**` without a cast. +static inline int +_Py_atomic_compare_exchange_ptr(void *obj, void *expected, void *value); + + +// --- _Py_atomic_exchange --------------------------------------------------- +// Atomically replaces `*obj` with `value` and returns the previous value of `*obj`. + +static inline int +_Py_atomic_exchange_int(int *obj, int value); + +static inline int8_t +_Py_atomic_exchange_int8(int8_t *obj, int8_t value); + +static inline int16_t +_Py_atomic_exchange_int16(int16_t *obj, int16_t value); + +static inline int32_t +_Py_atomic_exchange_int32(int32_t *obj, int32_t value); + +static inline int64_t +_Py_atomic_exchange_int64(int64_t *obj, int64_t value); + +static inline intptr_t +_Py_atomic_exchange_intptr(intptr_t *obj, intptr_t value); + +static inline unsigned int +_Py_atomic_exchange_uint(unsigned int *obj, unsigned int value); + +static inline uint8_t +_Py_atomic_exchange_uint8(uint8_t *obj, uint8_t value); + +static inline uint16_t +_Py_atomic_exchange_uint16(uint16_t *obj, uint16_t value); + +static inline uint32_t +_Py_atomic_exchange_uint32(uint32_t *obj, uint32_t value); + +static inline uint64_t +_Py_atomic_exchange_uint64(uint64_t *obj, uint64_t value); + +static inline uintptr_t +_Py_atomic_exchange_uintptr(uintptr_t *obj, uintptr_t value); + +static inline Py_ssize_t +_Py_atomic_exchange_ssize(Py_ssize_t *obj, Py_ssize_t value); + +static inline void * +_Py_atomic_exchange_ptr(void *obj, void *value); + + +// --- _Py_atomic_and -------------------------------------------------------- +// Performs `*obj &= value` atomically and returns the previous value of `*obj`. + +static inline uint8_t +_Py_atomic_and_uint8(uint8_t *obj, uint8_t value); + +static inline uint16_t +_Py_atomic_and_uint16(uint16_t *obj, uint16_t value); + +static inline uint32_t +_Py_atomic_and_uint32(uint32_t *obj, uint32_t value); + +static inline uint64_t +_Py_atomic_and_uint64(uint64_t *obj, uint64_t value); + +static inline uintptr_t +_Py_atomic_and_uintptr(uintptr_t *obj, uintptr_t value); + + +// --- _Py_atomic_or --------------------------------------------------------- +// Performs `*obj |= value` atomically and returns the previous value of `*obj`. + +static inline uint8_t +_Py_atomic_or_uint8(uint8_t *obj, uint8_t value); + +static inline uint16_t +_Py_atomic_or_uint16(uint16_t *obj, uint16_t value); + +static inline uint32_t +_Py_atomic_or_uint32(uint32_t *obj, uint32_t value); + +static inline uint64_t +_Py_atomic_or_uint64(uint64_t *obj, uint64_t value); + +static inline uintptr_t +_Py_atomic_or_uintptr(uintptr_t *obj, uintptr_t value); + + +// --- _Py_atomic_load ------------------------------------------------------- +// Atomically loads `*obj` (sequential consistency) + +static inline int +_Py_atomic_load_int(const int *obj); + +static inline int8_t +_Py_atomic_load_int8(const int8_t *obj); + +static inline int16_t +_Py_atomic_load_int16(const int16_t *obj); + +static inline int32_t +_Py_atomic_load_int32(const int32_t *obj); + +static inline int64_t +_Py_atomic_load_int64(const int64_t *obj); + +static inline intptr_t +_Py_atomic_load_intptr(const intptr_t *obj); + +static inline uint8_t +_Py_atomic_load_uint8(const uint8_t *obj); + +static inline uint16_t +_Py_atomic_load_uint16(const uint16_t *obj); + +static inline uint32_t +_Py_atomic_load_uint32(const uint32_t *obj); + +static inline uint64_t +_Py_atomic_load_uint64(const uint64_t *obj); + +static inline uintptr_t +_Py_atomic_load_uintptr(const uintptr_t *obj); + +static inline unsigned int +_Py_atomic_load_uint(const unsigned int *obj); + +static inline Py_ssize_t +_Py_atomic_load_ssize(const Py_ssize_t *obj); + +static inline void * +_Py_atomic_load_ptr(const void *obj); + + +// --- _Py_atomic_load_relaxed ----------------------------------------------- +// Loads `*obj` (relaxed consistency, i.e., no ordering) + +static inline int +_Py_atomic_load_int_relaxed(const int *obj); + +static inline int8_t +_Py_atomic_load_int8_relaxed(const int8_t *obj); + +static inline int16_t +_Py_atomic_load_int16_relaxed(const int16_t *obj); + +static inline int32_t +_Py_atomic_load_int32_relaxed(const int32_t *obj); + +static inline int64_t +_Py_atomic_load_int64_relaxed(const int64_t *obj); + +static inline intptr_t +_Py_atomic_load_intptr_relaxed(const intptr_t *obj); + +static inline uint8_t +_Py_atomic_load_uint8_relaxed(const uint8_t *obj); + +static inline uint16_t +_Py_atomic_load_uint16_relaxed(const uint16_t *obj); + +static inline uint32_t +_Py_atomic_load_uint32_relaxed(const uint32_t *obj); + +static inline uint64_t +_Py_atomic_load_uint64_relaxed(const uint64_t *obj); + +static inline uintptr_t +_Py_atomic_load_uintptr_relaxed(const uintptr_t *obj); + +static inline unsigned int +_Py_atomic_load_uint_relaxed(const unsigned int *obj); + +static inline Py_ssize_t +_Py_atomic_load_ssize_relaxed(const Py_ssize_t *obj); + +static inline void * +_Py_atomic_load_ptr_relaxed(const void *obj); + + +// --- _Py_atomic_store ------------------------------------------------------ +// Atomically performs `*obj = value` (sequential consistency) + +static inline void +_Py_atomic_store_int(int *obj, int value); + +static inline void +_Py_atomic_store_int8(int8_t *obj, int8_t value); + +static inline void +_Py_atomic_store_int16(int16_t *obj, int16_t value); + +static inline void +_Py_atomic_store_int32(int32_t *obj, int32_t value); + +static inline void +_Py_atomic_store_int64(int64_t *obj, int64_t value); + +static inline void +_Py_atomic_store_intptr(intptr_t *obj, intptr_t value); + +static inline void +_Py_atomic_store_uint8(uint8_t *obj, uint8_t value); + +static inline void +_Py_atomic_store_uint16(uint16_t *obj, uint16_t value); + +static inline void +_Py_atomic_store_uint32(uint32_t *obj, uint32_t value); + +static inline void +_Py_atomic_store_uint64(uint64_t *obj, uint64_t value); + +static inline void +_Py_atomic_store_uintptr(uintptr_t *obj, uintptr_t value); + +static inline void +_Py_atomic_store_uint(unsigned int *obj, unsigned int value); + +static inline void +_Py_atomic_store_ptr(void *obj, void *value); + +static inline void +_Py_atomic_store_ssize(Py_ssize_t* obj, Py_ssize_t value); + + +// --- _Py_atomic_store_relaxed ---------------------------------------------- +// Stores `*obj = value` (relaxed consistency, i.e., no ordering) + +static inline void +_Py_atomic_store_int_relaxed(int *obj, int value); + +static inline void +_Py_atomic_store_int8_relaxed(int8_t *obj, int8_t value); + +static inline void +_Py_atomic_store_int16_relaxed(int16_t *obj, int16_t value); + +static inline void +_Py_atomic_store_int32_relaxed(int32_t *obj, int32_t value); + +static inline void +_Py_atomic_store_int64_relaxed(int64_t *obj, int64_t value); + +static inline void +_Py_atomic_store_intptr_relaxed(intptr_t *obj, intptr_t value); + +static inline void +_Py_atomic_store_uint8_relaxed(uint8_t* obj, uint8_t value); + +static inline void +_Py_atomic_store_uint16_relaxed(uint16_t *obj, uint16_t value); + +static inline void +_Py_atomic_store_uint32_relaxed(uint32_t *obj, uint32_t value); + +static inline void +_Py_atomic_store_uint64_relaxed(uint64_t *obj, uint64_t value); + +static inline void +_Py_atomic_store_uintptr_relaxed(uintptr_t *obj, uintptr_t value); + +static inline void +_Py_atomic_store_uint_relaxed(unsigned int *obj, unsigned int value); + +static inline void +_Py_atomic_store_ptr_relaxed(void *obj, void *value); + +static inline void +_Py_atomic_store_ssize_relaxed(Py_ssize_t *obj, Py_ssize_t value); + + +// --- _Py_atomic_load_ptr_acquire / _Py_atomic_store_ptr_release ------------ + +// Loads `*obj` (acquire operation) +static inline void * +_Py_atomic_load_ptr_acquire(const void *obj); + +// Stores `*obj = value` (release operation) +static inline void +_Py_atomic_store_ptr_release(void *obj, void *value); + +static inline void +_Py_atomic_store_int_release(int *obj, int value); + +static inline int +_Py_atomic_load_int_acquire(const int *obj); + + +// --- _Py_atomic_fence ------------------------------------------------------ + +// Sequential consistency fence. C11 fences have complex semantics. When +// possible, use the atomic operations on variables defined above, which +// generally do not require explicit use of a fence. +// See https://en.cppreference.com/w/cpp/atomic/atomic_thread_fence +static inline void _Py_atomic_fence_seq_cst(void); + +// Release fence +static inline void _Py_atomic_fence_release(void); + + +#ifndef _Py_USE_GCC_BUILTIN_ATOMICS +# if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)) +# define _Py_USE_GCC_BUILTIN_ATOMICS 1 +# elif defined(__clang__) +# if __has_builtin(__atomic_load) +# define _Py_USE_GCC_BUILTIN_ATOMICS 1 +# endif +# endif +#endif + +#if _Py_USE_GCC_BUILTIN_ATOMICS +# define Py_ATOMIC_GCC_H +# include "cpython/pyatomic_gcc.h" +# undef Py_ATOMIC_GCC_H +#elif __STDC_VERSION__ >= 201112L && !defined(__STDC_NO_ATOMICS__) +# define Py_ATOMIC_STD_H +# include "cpython/pyatomic_std.h" +# undef Py_ATOMIC_STD_H +#elif defined(_MSC_VER) +# define Py_ATOMIC_MSC_H +# include "cpython/pyatomic_msc.h" +# undef Py_ATOMIC_MSC_H +#else +# error "no available pyatomic implementation for this platform/compiler" +#endif + + +// --- aliases --------------------------------------------------------------- + +#if SIZEOF_LONG == 8 +# define _Py_atomic_load_ulong(p) \ + _Py_atomic_load_uint64((uint64_t *)p) +# define _Py_atomic_load_ulong_relaxed(p) \ + _Py_atomic_load_uint64_relaxed((uint64_t *)p) +# define _Py_atomic_store_ulong(p, v) \ + _Py_atomic_store_uint64((uint64_t *)p, v) +# define _Py_atomic_store_ulong_relaxed(p, v) \ + _Py_atomic_store_uint64_relaxed((uint64_t *)p, v) +#elif SIZEOF_LONG == 4 +# define _Py_atomic_load_ulong(p) \ + _Py_atomic_load_uint32((uint32_t *)p) +# define _Py_atomic_load_ulong_relaxed(p) \ + _Py_atomic_load_uint32_relaxed((uint32_t *)p) +# define _Py_atomic_store_ulong(p, v) \ + _Py_atomic_store_uint32((uint32_t *)p, v) +# define _Py_atomic_store_ulong_relaxed(p, v) \ + _Py_atomic_store_uint32_relaxed((uint32_t *)p, v) +#else +# error "long must be 4 or 8 bytes in size" +#endif // SIZEOF_LONG diff --git a/Include/cpython/pyatomic_gcc.h b/Include/cpython/pyatomic_gcc.h new file mode 100644 index 00000000000000..70f2b7e1b5706a --- /dev/null +++ b/Include/cpython/pyatomic_gcc.h @@ -0,0 +1,507 @@ +// This is the implementation of Python atomic operations using GCC's built-in +// functions that match the C+11 memory model. This implementation is preferred +// for GCC compatible compilers, such as Clang. These functions are available +// in GCC 4.8+ without needing to compile with --std=c11 or --std=gnu11. + +#ifndef Py_ATOMIC_GCC_H +# error "this header file must not be included directly" +#endif + + +// --- _Py_atomic_add -------------------------------------------------------- + +static inline int +_Py_atomic_add_int(int *obj, int value) +{ return __atomic_fetch_add(obj, value, __ATOMIC_SEQ_CST); } + +static inline int8_t +_Py_atomic_add_int8(int8_t *obj, int8_t value) +{ return __atomic_fetch_add(obj, value, __ATOMIC_SEQ_CST); } + +static inline int16_t +_Py_atomic_add_int16(int16_t *obj, int16_t value) +{ return __atomic_fetch_add(obj, value, __ATOMIC_SEQ_CST); } + +static inline int32_t +_Py_atomic_add_int32(int32_t *obj, int32_t value) +{ return __atomic_fetch_add(obj, value, __ATOMIC_SEQ_CST); } + +static inline int64_t +_Py_atomic_add_int64(int64_t *obj, int64_t value) +{ return __atomic_fetch_add(obj, value, __ATOMIC_SEQ_CST); } + +static inline intptr_t +_Py_atomic_add_intptr(intptr_t *obj, intptr_t value) +{ return __atomic_fetch_add(obj, value, __ATOMIC_SEQ_CST); } + +static inline unsigned int +_Py_atomic_add_uint(unsigned int *obj, unsigned int value) +{ return __atomic_fetch_add(obj, value, __ATOMIC_SEQ_CST); } + +static inline uint8_t +_Py_atomic_add_uint8(uint8_t *obj, uint8_t value) +{ return __atomic_fetch_add(obj, value, __ATOMIC_SEQ_CST); } + +static inline uint16_t +_Py_atomic_add_uint16(uint16_t *obj, uint16_t value) +{ return __atomic_fetch_add(obj, value, __ATOMIC_SEQ_CST); } + +static inline uint32_t +_Py_atomic_add_uint32(uint32_t *obj, uint32_t value) +{ return __atomic_fetch_add(obj, value, __ATOMIC_SEQ_CST); } + +static inline uint64_t +_Py_atomic_add_uint64(uint64_t *obj, uint64_t value) +{ return __atomic_fetch_add(obj, value, __ATOMIC_SEQ_CST); } + +static inline uintptr_t +_Py_atomic_add_uintptr(uintptr_t *obj, uintptr_t value) +{ return __atomic_fetch_add(obj, value, __ATOMIC_SEQ_CST); } + +static inline Py_ssize_t +_Py_atomic_add_ssize(Py_ssize_t *obj, Py_ssize_t value) +{ return __atomic_fetch_add(obj, value, __ATOMIC_SEQ_CST); } + + +// --- _Py_atomic_compare_exchange ------------------------------------------- + +static inline int +_Py_atomic_compare_exchange_int(int *obj, int *expected, int desired) +{ return __atomic_compare_exchange_n(obj, expected, desired, 0, + __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); } + +static inline int +_Py_atomic_compare_exchange_int8(int8_t *obj, int8_t *expected, int8_t desired) +{ return __atomic_compare_exchange_n(obj, expected, desired, 0, + __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); } + +static inline int +_Py_atomic_compare_exchange_int16(int16_t *obj, int16_t *expected, int16_t desired) +{ return __atomic_compare_exchange_n(obj, expected, desired, 0, + __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); } + +static inline int +_Py_atomic_compare_exchange_int32(int32_t *obj, int32_t *expected, int32_t desired) +{ return __atomic_compare_exchange_n(obj, expected, desired, 0, + __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); } + +static inline int +_Py_atomic_compare_exchange_int64(int64_t *obj, int64_t *expected, int64_t desired) +{ return __atomic_compare_exchange_n(obj, expected, desired, 0, + __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); } + +static inline int +_Py_atomic_compare_exchange_intptr(intptr_t *obj, intptr_t *expected, intptr_t desired) +{ return __atomic_compare_exchange_n(obj, expected, desired, 0, + __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); } + +static inline int +_Py_atomic_compare_exchange_uint(unsigned int *obj, unsigned int *expected, unsigned int desired) +{ return __atomic_compare_exchange_n(obj, expected, desired, 0, + __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); } + +static inline int +_Py_atomic_compare_exchange_uint8(uint8_t *obj, uint8_t *expected, uint8_t desired) +{ return __atomic_compare_exchange_n(obj, expected, desired, 0, + __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); } + +static inline int +_Py_atomic_compare_exchange_uint16(uint16_t *obj, uint16_t *expected, uint16_t desired) +{ return __atomic_compare_exchange_n(obj, expected, desired, 0, + __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); } + +static inline int +_Py_atomic_compare_exchange_uint32(uint32_t *obj, uint32_t *expected, uint32_t desired) +{ return __atomic_compare_exchange_n(obj, expected, desired, 0, + __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); } + +static inline int +_Py_atomic_compare_exchange_uint64(uint64_t *obj, uint64_t *expected, uint64_t desired) +{ return __atomic_compare_exchange_n(obj, expected, desired, 0, + __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); } + +static inline int +_Py_atomic_compare_exchange_uintptr(uintptr_t *obj, uintptr_t *expected, uintptr_t desired) +{ return __atomic_compare_exchange_n(obj, expected, desired, 0, + __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); } + +static inline int +_Py_atomic_compare_exchange_ssize(Py_ssize_t *obj, Py_ssize_t *expected, Py_ssize_t desired) +{ return __atomic_compare_exchange_n(obj, expected, desired, 0, + __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); } + +static inline int +_Py_atomic_compare_exchange_ptr(void *obj, void *expected, void *desired) +{ return __atomic_compare_exchange_n((void **)obj, (void **)expected, desired, 0, + __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); } + + +// --- _Py_atomic_exchange --------------------------------------------------- + +static inline int +_Py_atomic_exchange_int(int *obj, int value) +{ return __atomic_exchange_n(obj, value, __ATOMIC_SEQ_CST); } + +static inline int8_t +_Py_atomic_exchange_int8(int8_t *obj, int8_t value) +{ return __atomic_exchange_n(obj, value, __ATOMIC_SEQ_CST); } + +static inline int16_t +_Py_atomic_exchange_int16(int16_t *obj, int16_t value) +{ return __atomic_exchange_n(obj, value, __ATOMIC_SEQ_CST); } + +static inline int32_t +_Py_atomic_exchange_int32(int32_t *obj, int32_t value) +{ return __atomic_exchange_n(obj, value, __ATOMIC_SEQ_CST); } + +static inline int64_t +_Py_atomic_exchange_int64(int64_t *obj, int64_t value) +{ return __atomic_exchange_n(obj, value, __ATOMIC_SEQ_CST); } + +static inline intptr_t +_Py_atomic_exchange_intptr(intptr_t *obj, intptr_t value) +{ return __atomic_exchange_n(obj, value, __ATOMIC_SEQ_CST); } + +static inline unsigned int +_Py_atomic_exchange_uint(unsigned int *obj, unsigned int value) +{ return __atomic_exchange_n(obj, value, __ATOMIC_SEQ_CST); } + +static inline uint8_t +_Py_atomic_exchange_uint8(uint8_t *obj, uint8_t value) +{ return __atomic_exchange_n(obj, value, __ATOMIC_SEQ_CST); } + +static inline uint16_t +_Py_atomic_exchange_uint16(uint16_t *obj, uint16_t value) +{ return __atomic_exchange_n(obj, value, __ATOMIC_SEQ_CST); } + +static inline uint32_t +_Py_atomic_exchange_uint32(uint32_t *obj, uint32_t value) +{ return __atomic_exchange_n(obj, value, __ATOMIC_SEQ_CST); } + +static inline uint64_t +_Py_atomic_exchange_uint64(uint64_t *obj, uint64_t value) +{ return __atomic_exchange_n(obj, value, __ATOMIC_SEQ_CST); } + +static inline uintptr_t +_Py_atomic_exchange_uintptr(uintptr_t *obj, uintptr_t value) +{ return __atomic_exchange_n(obj, value, __ATOMIC_SEQ_CST); } + +static inline Py_ssize_t +_Py_atomic_exchange_ssize(Py_ssize_t *obj, Py_ssize_t value) +{ return __atomic_exchange_n(obj, value, __ATOMIC_SEQ_CST); } + +static inline void * +_Py_atomic_exchange_ptr(void *obj, void *value) +{ return __atomic_exchange_n((void **)obj, value, __ATOMIC_SEQ_CST); } + + +// --- _Py_atomic_and -------------------------------------------------------- + +static inline uint8_t +_Py_atomic_and_uint8(uint8_t *obj, uint8_t value) +{ return __atomic_fetch_and(obj, value, __ATOMIC_SEQ_CST); } + +static inline uint16_t +_Py_atomic_and_uint16(uint16_t *obj, uint16_t value) +{ return __atomic_fetch_and(obj, value, __ATOMIC_SEQ_CST); } + +static inline uint32_t +_Py_atomic_and_uint32(uint32_t *obj, uint32_t value) +{ return __atomic_fetch_and(obj, value, __ATOMIC_SEQ_CST); } + +static inline uint64_t +_Py_atomic_and_uint64(uint64_t *obj, uint64_t value) +{ return __atomic_fetch_and(obj, value, __ATOMIC_SEQ_CST); } + +static inline uintptr_t +_Py_atomic_and_uintptr(uintptr_t *obj, uintptr_t value) +{ return __atomic_fetch_and(obj, value, __ATOMIC_SEQ_CST); } + + +// --- _Py_atomic_or --------------------------------------------------------- + +static inline uint8_t +_Py_atomic_or_uint8(uint8_t *obj, uint8_t value) +{ return __atomic_fetch_or(obj, value, __ATOMIC_SEQ_CST); } + +static inline uint16_t +_Py_atomic_or_uint16(uint16_t *obj, uint16_t value) +{ return __atomic_fetch_or(obj, value, __ATOMIC_SEQ_CST); } + +static inline uint32_t +_Py_atomic_or_uint32(uint32_t *obj, uint32_t value) +{ return __atomic_fetch_or(obj, value, __ATOMIC_SEQ_CST); } + +static inline uint64_t +_Py_atomic_or_uint64(uint64_t *obj, uint64_t value) +{ return __atomic_fetch_or(obj, value, __ATOMIC_SEQ_CST); } + +static inline uintptr_t +_Py_atomic_or_uintptr(uintptr_t *obj, uintptr_t value) +{ return __atomic_fetch_or(obj, value, __ATOMIC_SEQ_CST); } + + +// --- _Py_atomic_load ------------------------------------------------------- + +static inline int +_Py_atomic_load_int(const int *obj) +{ return __atomic_load_n(obj, __ATOMIC_SEQ_CST); } + +static inline int8_t +_Py_atomic_load_int8(const int8_t *obj) +{ return __atomic_load_n(obj, __ATOMIC_SEQ_CST); } + +static inline int16_t +_Py_atomic_load_int16(const int16_t *obj) +{ return __atomic_load_n(obj, __ATOMIC_SEQ_CST); } + +static inline int32_t +_Py_atomic_load_int32(const int32_t *obj) +{ return __atomic_load_n(obj, __ATOMIC_SEQ_CST); } + +static inline int64_t +_Py_atomic_load_int64(const int64_t *obj) +{ return __atomic_load_n(obj, __ATOMIC_SEQ_CST); } + +static inline intptr_t +_Py_atomic_load_intptr(const intptr_t *obj) +{ return __atomic_load_n(obj, __ATOMIC_SEQ_CST); } + +static inline uint8_t +_Py_atomic_load_uint8(const uint8_t *obj) +{ return __atomic_load_n(obj, __ATOMIC_SEQ_CST); } + +static inline uint16_t +_Py_atomic_load_uint16(const uint16_t *obj) +{ return __atomic_load_n(obj, __ATOMIC_SEQ_CST); } + +static inline uint32_t +_Py_atomic_load_uint32(const uint32_t *obj) +{ return __atomic_load_n(obj, __ATOMIC_SEQ_CST); } + +static inline uint64_t +_Py_atomic_load_uint64(const uint64_t *obj) +{ return __atomic_load_n(obj, __ATOMIC_SEQ_CST); } + +static inline uintptr_t +_Py_atomic_load_uintptr(const uintptr_t *obj) +{ return __atomic_load_n(obj, __ATOMIC_SEQ_CST); } + +static inline unsigned int +_Py_atomic_load_uint(const unsigned int *obj) +{ return __atomic_load_n(obj, __ATOMIC_SEQ_CST); } + +static inline Py_ssize_t +_Py_atomic_load_ssize(const Py_ssize_t *obj) +{ return __atomic_load_n(obj, __ATOMIC_SEQ_CST); } + +static inline void * +_Py_atomic_load_ptr(const void *obj) +{ return (void *)__atomic_load_n((void **)obj, __ATOMIC_SEQ_CST); } + + +// --- _Py_atomic_load_relaxed ----------------------------------------------- + +static inline int +_Py_atomic_load_int_relaxed(const int *obj) +{ return __atomic_load_n(obj, __ATOMIC_RELAXED); } + +static inline int8_t +_Py_atomic_load_int8_relaxed(const int8_t *obj) +{ return __atomic_load_n(obj, __ATOMIC_RELAXED); } + +static inline int16_t +_Py_atomic_load_int16_relaxed(const int16_t *obj) +{ return __atomic_load_n(obj, __ATOMIC_RELAXED); } + +static inline int32_t +_Py_atomic_load_int32_relaxed(const int32_t *obj) +{ return __atomic_load_n(obj, __ATOMIC_RELAXED); } + +static inline int64_t +_Py_atomic_load_int64_relaxed(const int64_t *obj) +{ return __atomic_load_n(obj, __ATOMIC_RELAXED); } + +static inline intptr_t +_Py_atomic_load_intptr_relaxed(const intptr_t *obj) +{ return __atomic_load_n(obj, __ATOMIC_RELAXED); } + +static inline uint8_t +_Py_atomic_load_uint8_relaxed(const uint8_t *obj) +{ return __atomic_load_n(obj, __ATOMIC_RELAXED); } + +static inline uint16_t +_Py_atomic_load_uint16_relaxed(const uint16_t *obj) +{ return __atomic_load_n(obj, __ATOMIC_RELAXED); } + +static inline uint32_t +_Py_atomic_load_uint32_relaxed(const uint32_t *obj) +{ return __atomic_load_n(obj, __ATOMIC_RELAXED); } + +static inline uint64_t +_Py_atomic_load_uint64_relaxed(const uint64_t *obj) +{ return __atomic_load_n(obj, __ATOMIC_RELAXED); } + +static inline uintptr_t +_Py_atomic_load_uintptr_relaxed(const uintptr_t *obj) +{ return __atomic_load_n(obj, __ATOMIC_RELAXED); } + +static inline unsigned int +_Py_atomic_load_uint_relaxed(const unsigned int *obj) +{ return __atomic_load_n(obj, __ATOMIC_RELAXED); } + +static inline Py_ssize_t +_Py_atomic_load_ssize_relaxed(const Py_ssize_t *obj) +{ return __atomic_load_n(obj, __ATOMIC_RELAXED); } + +static inline void * +_Py_atomic_load_ptr_relaxed(const void *obj) +{ return (void *)__atomic_load_n((const void **)obj, __ATOMIC_RELAXED); } + + +// --- _Py_atomic_store ------------------------------------------------------ + +static inline void +_Py_atomic_store_int(int *obj, int value) +{ __atomic_store_n(obj, value, __ATOMIC_SEQ_CST); } + +static inline void +_Py_atomic_store_int8(int8_t *obj, int8_t value) +{ __atomic_store_n(obj, value, __ATOMIC_SEQ_CST); } + +static inline void +_Py_atomic_store_int16(int16_t *obj, int16_t value) +{ __atomic_store_n(obj, value, __ATOMIC_SEQ_CST); } + +static inline void +_Py_atomic_store_int32(int32_t *obj, int32_t value) +{ __atomic_store_n(obj, value, __ATOMIC_SEQ_CST); } + +static inline void +_Py_atomic_store_int64(int64_t *obj, int64_t value) +{ __atomic_store_n(obj, value, __ATOMIC_SEQ_CST); } + +static inline void +_Py_atomic_store_intptr(intptr_t *obj, intptr_t value) +{ __atomic_store_n(obj, value, __ATOMIC_SEQ_CST); } + +static inline void +_Py_atomic_store_uint8(uint8_t *obj, uint8_t value) +{ __atomic_store_n(obj, value, __ATOMIC_SEQ_CST); } + +static inline void +_Py_atomic_store_uint16(uint16_t *obj, uint16_t value) +{ __atomic_store_n(obj, value, __ATOMIC_SEQ_CST); } + +static inline void +_Py_atomic_store_uint32(uint32_t *obj, uint32_t value) +{ __atomic_store_n(obj, value, __ATOMIC_SEQ_CST); } + +static inline void +_Py_atomic_store_uint64(uint64_t *obj, uint64_t value) +{ __atomic_store_n(obj, value, __ATOMIC_SEQ_CST); } + +static inline void +_Py_atomic_store_uintptr(uintptr_t *obj, uintptr_t value) +{ __atomic_store_n(obj, value, __ATOMIC_SEQ_CST); } + +static inline void +_Py_atomic_store_uint(unsigned int *obj, unsigned int value) +{ __atomic_store_n(obj, value, __ATOMIC_SEQ_CST); } + +static inline void +_Py_atomic_store_ptr(void *obj, void *value) +{ __atomic_store_n((void **)obj, value, __ATOMIC_SEQ_CST); } + +static inline void +_Py_atomic_store_ssize(Py_ssize_t *obj, Py_ssize_t value) +{ __atomic_store_n(obj, value, __ATOMIC_SEQ_CST); } + + +// --- _Py_atomic_store_relaxed ---------------------------------------------- + +static inline void +_Py_atomic_store_int_relaxed(int *obj, int value) +{ __atomic_store_n(obj, value, __ATOMIC_RELAXED); } + +static inline void +_Py_atomic_store_int8_relaxed(int8_t *obj, int8_t value) +{ __atomic_store_n(obj, value, __ATOMIC_RELAXED); } + +static inline void +_Py_atomic_store_int16_relaxed(int16_t *obj, int16_t value) +{ __atomic_store_n(obj, value, __ATOMIC_RELAXED); } + +static inline void +_Py_atomic_store_int32_relaxed(int32_t *obj, int32_t value) +{ __atomic_store_n(obj, value, __ATOMIC_RELAXED); } + +static inline void +_Py_atomic_store_int64_relaxed(int64_t *obj, int64_t value) +{ __atomic_store_n(obj, value, __ATOMIC_RELAXED); } + +static inline void +_Py_atomic_store_intptr_relaxed(intptr_t *obj, intptr_t value) +{ __atomic_store_n(obj, value, __ATOMIC_RELAXED); } + +static inline void +_Py_atomic_store_uint8_relaxed(uint8_t *obj, uint8_t value) +{ __atomic_store_n(obj, value, __ATOMIC_RELAXED); } + +static inline void +_Py_atomic_store_uint16_relaxed(uint16_t *obj, uint16_t value) +{ __atomic_store_n(obj, value, __ATOMIC_RELAXED); } + +static inline void +_Py_atomic_store_uint32_relaxed(uint32_t *obj, uint32_t value) +{ __atomic_store_n(obj, value, __ATOMIC_RELAXED); } + +static inline void +_Py_atomic_store_uint64_relaxed(uint64_t *obj, uint64_t value) +{ __atomic_store_n(obj, value, __ATOMIC_RELAXED); } + +static inline void +_Py_atomic_store_uintptr_relaxed(uintptr_t *obj, uintptr_t value) +{ __atomic_store_n(obj, value, __ATOMIC_RELAXED); } + +static inline void +_Py_atomic_store_uint_relaxed(unsigned int *obj, unsigned int value) +{ __atomic_store_n(obj, value, __ATOMIC_RELAXED); } + +static inline void +_Py_atomic_store_ptr_relaxed(void *obj, void *value) +{ __atomic_store_n((void **)obj, value, __ATOMIC_RELAXED); } + +static inline void +_Py_atomic_store_ssize_relaxed(Py_ssize_t *obj, Py_ssize_t value) +{ __atomic_store_n(obj, value, __ATOMIC_RELAXED); } + + +// --- _Py_atomic_load_ptr_acquire / _Py_atomic_store_ptr_release ------------ + +static inline void * +_Py_atomic_load_ptr_acquire(const void *obj) +{ return (void *)__atomic_load_n((void **)obj, __ATOMIC_ACQUIRE); } + +static inline void +_Py_atomic_store_ptr_release(void *obj, void *value) +{ __atomic_store_n((void **)obj, value, __ATOMIC_RELEASE); } + +static inline void +_Py_atomic_store_int_release(int *obj, int value) +{ __atomic_store_n(obj, value, __ATOMIC_RELEASE); } + +static inline int +_Py_atomic_load_int_acquire(const int *obj) +{ return __atomic_load_n(obj, __ATOMIC_ACQUIRE); } + + +// --- _Py_atomic_fence ------------------------------------------------------ + +static inline void +_Py_atomic_fence_seq_cst(void) +{ __atomic_thread_fence(__ATOMIC_SEQ_CST); } + + static inline void +_Py_atomic_fence_release(void) +{ __atomic_thread_fence(__ATOMIC_RELEASE); } diff --git a/Include/cpython/pyatomic_msc.h b/Include/cpython/pyatomic_msc.h new file mode 100644 index 00000000000000..601a0cf65afc1c --- /dev/null +++ b/Include/cpython/pyatomic_msc.h @@ -0,0 +1,970 @@ +// This is the implementation of Python atomic operations for MSVC if the +// compiler does not support C11 or C++11 atomics. +// +// MSVC intrinsics are defined on char, short, long, __int64, and pointer +// types. Note that long and int are both 32-bits even on 64-bit Windows, +// so operations on int are cast to long. +// +// The volatile keyword has additional memory ordering semantics on MSVC. On +// x86 and x86-64, volatile accesses have acquire-release semantics. On ARM64, +// volatile accesses behave like C11's memory_order_relaxed. + +#ifndef Py_ATOMIC_MSC_H +# error "this header file must not be included directly" +#endif + +#include + +#define _Py_atomic_ASSERT_ARG_TYPE(TYPE) \ + Py_BUILD_ASSERT(sizeof(*obj) == sizeof(TYPE)) + + +// --- _Py_atomic_add -------------------------------------------------------- + +static inline int8_t +_Py_atomic_add_int8(int8_t *obj, int8_t value) +{ + _Py_atomic_ASSERT_ARG_TYPE(char); + return (int8_t)_InterlockedExchangeAdd8((volatile char *)obj, (char)value); +} + +static inline int16_t +_Py_atomic_add_int16(int16_t *obj, int16_t value) +{ + _Py_atomic_ASSERT_ARG_TYPE(short); + return (int16_t)_InterlockedExchangeAdd16((volatile short *)obj, (short)value); +} + +static inline int32_t +_Py_atomic_add_int32(int32_t *obj, int32_t value) +{ + _Py_atomic_ASSERT_ARG_TYPE(long); + return (int32_t)_InterlockedExchangeAdd((volatile long *)obj, (long)value); +} + +static inline int64_t +_Py_atomic_add_int64(int64_t *obj, int64_t value) +{ +#if defined(_M_X64) || defined(_M_ARM64) + _Py_atomic_ASSERT_ARG_TYPE(__int64); + return (int64_t)_InterlockedExchangeAdd64((volatile __int64 *)obj, (__int64)value); +#else + int64_t old_value = _Py_atomic_load_int64_relaxed(obj); + for (;;) { + int64_t new_value = old_value + value; + if (_Py_atomic_compare_exchange_int64(obj, &old_value, new_value)) { + return old_value; + } + } +#endif +} + + +static inline uint8_t +_Py_atomic_add_uint8(uint8_t *obj, uint8_t value) +{ + return (uint8_t)_Py_atomic_add_int8((int8_t *)obj, (int8_t)value); +} + +static inline uint16_t +_Py_atomic_add_uint16(uint16_t *obj, uint16_t value) +{ + return (uint16_t)_Py_atomic_add_int16((int16_t *)obj, (int16_t)value); +} + +static inline uint32_t +_Py_atomic_add_uint32(uint32_t *obj, uint32_t value) +{ + return (uint32_t)_Py_atomic_add_int32((int32_t *)obj, (int32_t)value); +} + +static inline int +_Py_atomic_add_int(int *obj, int value) +{ + _Py_atomic_ASSERT_ARG_TYPE(int32_t); + return (int)_Py_atomic_add_int32((int32_t *)obj, (int32_t)value); +} + +static inline unsigned int +_Py_atomic_add_uint(unsigned int *obj, unsigned int value) +{ + _Py_atomic_ASSERT_ARG_TYPE(int32_t); + return (unsigned int)_Py_atomic_add_int32((int32_t *)obj, (int32_t)value); +} + +static inline uint64_t +_Py_atomic_add_uint64(uint64_t *obj, uint64_t value) +{ + return (uint64_t)_Py_atomic_add_int64((int64_t *)obj, (int64_t)value); +} + +static inline intptr_t +_Py_atomic_add_intptr(intptr_t *obj, intptr_t value) +{ +#if SIZEOF_VOID_P == 8 + _Py_atomic_ASSERT_ARG_TYPE(int64_t); + return (intptr_t)_Py_atomic_add_int64((int64_t *)obj, (int64_t)value); +#else + _Py_atomic_ASSERT_ARG_TYPE(int32_t); + return (intptr_t)_Py_atomic_add_int32((int32_t *)obj, (int32_t)value); +#endif +} + +static inline uintptr_t +_Py_atomic_add_uintptr(uintptr_t *obj, uintptr_t value) +{ + _Py_atomic_ASSERT_ARG_TYPE(intptr_t); + return (uintptr_t)_Py_atomic_add_intptr((intptr_t *)obj, (intptr_t)value); +} + +static inline Py_ssize_t +_Py_atomic_add_ssize(Py_ssize_t *obj, Py_ssize_t value) +{ + _Py_atomic_ASSERT_ARG_TYPE(intptr_t); + return (Py_ssize_t)_Py_atomic_add_intptr((intptr_t *)obj, (intptr_t)value); +} + + +// --- _Py_atomic_compare_exchange ------------------------------------------- + +static inline int +_Py_atomic_compare_exchange_int8(int8_t *obj, int8_t *expected, int8_t value) +{ + _Py_atomic_ASSERT_ARG_TYPE(char); + int8_t initial = (int8_t)_InterlockedCompareExchange8( + (volatile char *)obj, + (char)value, + (char)*expected); + if (initial == *expected) { + return 1; + } + *expected = initial; + return 0; +} + +static inline int +_Py_atomic_compare_exchange_int16(int16_t *obj, int16_t *expected, int16_t value) +{ + _Py_atomic_ASSERT_ARG_TYPE(short); + int16_t initial = (int16_t)_InterlockedCompareExchange16( + (volatile short *)obj, + (short)value, + (short)*expected); + if (initial == *expected) { + return 1; + } + *expected = initial; + return 0; +} + +static inline int +_Py_atomic_compare_exchange_int32(int32_t *obj, int32_t *expected, int32_t value) +{ + _Py_atomic_ASSERT_ARG_TYPE(long); + int32_t initial = (int32_t)_InterlockedCompareExchange( + (volatile long *)obj, + (long)value, + (long)*expected); + if (initial == *expected) { + return 1; + } + *expected = initial; + return 0; +} + +static inline int +_Py_atomic_compare_exchange_int64(int64_t *obj, int64_t *expected, int64_t value) +{ + _Py_atomic_ASSERT_ARG_TYPE(__int64); + int64_t initial = (int64_t)_InterlockedCompareExchange64( + (volatile __int64 *)obj, + (__int64)value, + (__int64)*expected); + if (initial == *expected) { + return 1; + } + *expected = initial; + return 0; +} + +static inline int +_Py_atomic_compare_exchange_ptr(void *obj, void *expected, void *value) +{ + void *initial = _InterlockedCompareExchangePointer( + (void**)obj, + value, + *(void**)expected); + if (initial == *(void**)expected) { + return 1; + } + *(void**)expected = initial; + return 0; +} + + +static inline int +_Py_atomic_compare_exchange_uint8(uint8_t *obj, uint8_t *expected, uint8_t value) +{ + return _Py_atomic_compare_exchange_int8((int8_t *)obj, + (int8_t *)expected, + (int8_t)value); +} + +static inline int +_Py_atomic_compare_exchange_uint16(uint16_t *obj, uint16_t *expected, uint16_t value) +{ + return _Py_atomic_compare_exchange_int16((int16_t *)obj, + (int16_t *)expected, + (int16_t)value); +} + +static inline int +_Py_atomic_compare_exchange_uint32(uint32_t *obj, uint32_t *expected, uint32_t value) +{ + return _Py_atomic_compare_exchange_int32((int32_t *)obj, + (int32_t *)expected, + (int32_t)value); +} + +static inline int +_Py_atomic_compare_exchange_int(int *obj, int *expected, int value) +{ + _Py_atomic_ASSERT_ARG_TYPE(int32_t); + return _Py_atomic_compare_exchange_int32((int32_t *)obj, + (int32_t *)expected, + (int32_t)value); +} + +static inline int +_Py_atomic_compare_exchange_uint(unsigned int *obj, unsigned int *expected, unsigned int value) +{ + _Py_atomic_ASSERT_ARG_TYPE(int32_t); + return _Py_atomic_compare_exchange_int32((int32_t *)obj, + (int32_t *)expected, + (int32_t)value); +} + +static inline int +_Py_atomic_compare_exchange_uint64(uint64_t *obj, uint64_t *expected, uint64_t value) +{ + return _Py_atomic_compare_exchange_int64((int64_t *)obj, + (int64_t *)expected, + (int64_t)value); +} + +static inline int +_Py_atomic_compare_exchange_intptr(intptr_t *obj, intptr_t *expected, intptr_t value) +{ + _Py_atomic_ASSERT_ARG_TYPE(void*); + return _Py_atomic_compare_exchange_ptr((void**)obj, + (void**)expected, + (void*)value); +} + +static inline int +_Py_atomic_compare_exchange_uintptr(uintptr_t *obj, uintptr_t *expected, uintptr_t value) +{ + _Py_atomic_ASSERT_ARG_TYPE(void*); + return _Py_atomic_compare_exchange_ptr((void**)obj, + (void**)expected, + (void*)value); +} + +static inline int +_Py_atomic_compare_exchange_ssize(Py_ssize_t *obj, Py_ssize_t *expected, Py_ssize_t value) +{ + _Py_atomic_ASSERT_ARG_TYPE(void*); + return _Py_atomic_compare_exchange_ptr((void**)obj, + (void**)expected, + (void*)value); +} + + +// --- _Py_atomic_exchange --------------------------------------------------- + +static inline int8_t +_Py_atomic_exchange_int8(int8_t *obj, int8_t value) +{ + _Py_atomic_ASSERT_ARG_TYPE(char); + return (int8_t)_InterlockedExchange8((volatile char *)obj, (char)value); +} + +static inline int16_t +_Py_atomic_exchange_int16(int16_t *obj, int16_t value) +{ + _Py_atomic_ASSERT_ARG_TYPE(short); + return (int16_t)_InterlockedExchange16((volatile short *)obj, (short)value); +} + +static inline int32_t +_Py_atomic_exchange_int32(int32_t *obj, int32_t value) +{ + _Py_atomic_ASSERT_ARG_TYPE(long); + return (int32_t)_InterlockedExchange((volatile long *)obj, (long)value); +} + +static inline int64_t +_Py_atomic_exchange_int64(int64_t *obj, int64_t value) +{ +#if defined(_M_X64) || defined(_M_ARM64) + _Py_atomic_ASSERT_ARG_TYPE(__int64); + return (int64_t)_InterlockedExchange64((volatile __int64 *)obj, (__int64)value); +#else + int64_t old_value = _Py_atomic_load_int64_relaxed(obj); + for (;;) { + if (_Py_atomic_compare_exchange_int64(obj, &old_value, value)) { + return old_value; + } + } +#endif +} + +static inline void* +_Py_atomic_exchange_ptr(void *obj, void *value) +{ + return (void*)_InterlockedExchangePointer((void * volatile *)obj, (void *)value); +} + + +static inline uint8_t +_Py_atomic_exchange_uint8(uint8_t *obj, uint8_t value) +{ + return (uint8_t)_Py_atomic_exchange_int8((int8_t *)obj, + (int8_t)value); +} + +static inline uint16_t +_Py_atomic_exchange_uint16(uint16_t *obj, uint16_t value) +{ + return (uint16_t)_Py_atomic_exchange_int16((int16_t *)obj, + (int16_t)value); +} + +static inline uint32_t +_Py_atomic_exchange_uint32(uint32_t *obj, uint32_t value) +{ + return (uint32_t)_Py_atomic_exchange_int32((int32_t *)obj, + (int32_t)value); +} + +static inline int +_Py_atomic_exchange_int(int *obj, int value) +{ + _Py_atomic_ASSERT_ARG_TYPE(int32_t); + return (int)_Py_atomic_exchange_int32((int32_t *)obj, + (int32_t)value); +} + +static inline unsigned int +_Py_atomic_exchange_uint(unsigned int *obj, unsigned int value) +{ + _Py_atomic_ASSERT_ARG_TYPE(int32_t); + return (unsigned int)_Py_atomic_exchange_int32((int32_t *)obj, + (int32_t)value); +} + +static inline uint64_t +_Py_atomic_exchange_uint64(uint64_t *obj, uint64_t value) +{ + return (uint64_t)_Py_atomic_exchange_int64((int64_t *)obj, + (int64_t)value); +} + +static inline intptr_t +_Py_atomic_exchange_intptr(intptr_t *obj, intptr_t value) +{ + _Py_atomic_ASSERT_ARG_TYPE(void*); + return (intptr_t)_Py_atomic_exchange_ptr((void**)obj, + (void*)value); +} + +static inline uintptr_t +_Py_atomic_exchange_uintptr(uintptr_t *obj, uintptr_t value) +{ + _Py_atomic_ASSERT_ARG_TYPE(void*); + return (uintptr_t)_Py_atomic_exchange_ptr((void**)obj, + (void*)value); +} + +static inline Py_ssize_t +_Py_atomic_exchange_ssize(Py_ssize_t *obj, Py_ssize_t value) +{ + _Py_atomic_ASSERT_ARG_TYPE(void*); + return (Py_ssize_t)_Py_atomic_exchange_ptr((void**)obj, + (void*)value); +} + + +// --- _Py_atomic_and -------------------------------------------------------- + +static inline uint8_t +_Py_atomic_and_uint8(uint8_t *obj, uint8_t value) +{ + _Py_atomic_ASSERT_ARG_TYPE(char); + return (uint8_t)_InterlockedAnd8((volatile char *)obj, (char)value); +} + +static inline uint16_t +_Py_atomic_and_uint16(uint16_t *obj, uint16_t value) +{ + _Py_atomic_ASSERT_ARG_TYPE(short); + return (uint16_t)_InterlockedAnd16((volatile short *)obj, (short)value); +} + +static inline uint32_t +_Py_atomic_and_uint32(uint32_t *obj, uint32_t value) +{ + _Py_atomic_ASSERT_ARG_TYPE(long); + return (uint32_t)_InterlockedAnd((volatile long *)obj, (long)value); +} + +static inline uint64_t +_Py_atomic_and_uint64(uint64_t *obj, uint64_t value) +{ +#if defined(_M_X64) || defined(_M_ARM64) + _Py_atomic_ASSERT_ARG_TYPE(__int64); + return (uint64_t)_InterlockedAnd64((volatile __int64 *)obj, (__int64)value); +#else + uint64_t old_value = _Py_atomic_load_uint64_relaxed(obj); + for (;;) { + uint64_t new_value = old_value & value; + if (_Py_atomic_compare_exchange_uint64(obj, &old_value, new_value)) { + return old_value; + } + } +#endif +} + +static inline uintptr_t +_Py_atomic_and_uintptr(uintptr_t *obj, uintptr_t value) +{ +#if SIZEOF_VOID_P == 8 + _Py_atomic_ASSERT_ARG_TYPE(uint64_t); + return (uintptr_t)_Py_atomic_and_uint64((uint64_t *)obj, + (uint64_t)value); +#else + _Py_atomic_ASSERT_ARG_TYPE(uint32_t); + return (uintptr_t)_Py_atomic_and_uint32((uint32_t *)obj, + (uint32_t)value); +#endif +} + + +// --- _Py_atomic_or --------------------------------------------------------- + +static inline uint8_t +_Py_atomic_or_uint8(uint8_t *obj, uint8_t value) +{ + _Py_atomic_ASSERT_ARG_TYPE(char); + return (uint8_t)_InterlockedOr8((volatile char *)obj, (char)value); +} + +static inline uint16_t +_Py_atomic_or_uint16(uint16_t *obj, uint16_t value) +{ + _Py_atomic_ASSERT_ARG_TYPE(short); + return (uint16_t)_InterlockedOr16((volatile short *)obj, (short)value); +} + +static inline uint32_t +_Py_atomic_or_uint32(uint32_t *obj, uint32_t value) +{ + _Py_atomic_ASSERT_ARG_TYPE(long); + return (uint32_t)_InterlockedOr((volatile long *)obj, (long)value); +} + +static inline uint64_t +_Py_atomic_or_uint64(uint64_t *obj, uint64_t value) +{ +#if defined(_M_X64) || defined(_M_ARM64) + _Py_atomic_ASSERT_ARG_TYPE(__int64); + return (uint64_t)_InterlockedOr64((volatile __int64 *)obj, (__int64)value); +#else + uint64_t old_value = _Py_atomic_load_uint64_relaxed(obj); + for (;;) { + uint64_t new_value = old_value | value; + if (_Py_atomic_compare_exchange_uint64(obj, &old_value, new_value)) { + return old_value; + } + } +#endif +} + + +static inline uintptr_t +_Py_atomic_or_uintptr(uintptr_t *obj, uintptr_t value) +{ +#if SIZEOF_VOID_P == 8 + _Py_atomic_ASSERT_ARG_TYPE(uint64_t); + return (uintptr_t)_Py_atomic_or_uint64((uint64_t *)obj, + (uint64_t)value); +#else + _Py_atomic_ASSERT_ARG_TYPE(uint32_t); + return (uintptr_t)_Py_atomic_or_uint32((uint32_t *)obj, + (uint32_t)value); +#endif +} + + +// --- _Py_atomic_load ------------------------------------------------------- + +static inline uint8_t +_Py_atomic_load_uint8(const uint8_t *obj) +{ +#if defined(_M_X64) || defined(_M_IX86) + return *(volatile uint8_t *)obj; +#elif defined(_M_ARM64) + return (uint8_t)__ldar8((unsigned __int8 volatile *)obj); +#else +# error "no implementation of _Py_atomic_load_uint8" +#endif +} + +static inline uint16_t +_Py_atomic_load_uint16(const uint16_t *obj) +{ +#if defined(_M_X64) || defined(_M_IX86) + return *(volatile uint16_t *)obj; +#elif defined(_M_ARM64) + return (uint16_t)__ldar16((unsigned __int16 volatile *)obj); +#else +# error "no implementation of _Py_atomic_load_uint16" +#endif +} + +static inline uint32_t +_Py_atomic_load_uint32(const uint32_t *obj) +{ +#if defined(_M_X64) || defined(_M_IX86) + return *(volatile uint32_t *)obj; +#elif defined(_M_ARM64) + return (uint32_t)__ldar32((unsigned __int32 volatile *)obj); +#else +# error "no implementation of _Py_atomic_load_uint32" +#endif +} + +static inline uint64_t +_Py_atomic_load_uint64(const uint64_t *obj) +{ +#if defined(_M_X64) || defined(_M_IX86) + return *(volatile uint64_t *)obj; +#elif defined(_M_ARM64) + return (uint64_t)__ldar64((unsigned __int64 volatile *)obj); +#else +# error "no implementation of _Py_atomic_load_uint64" +#endif +} + +static inline int8_t +_Py_atomic_load_int8(const int8_t *obj) +{ + return (int8_t)_Py_atomic_load_uint8((const uint8_t *)obj); +} + +static inline int16_t +_Py_atomic_load_int16(const int16_t *obj) +{ + return (int16_t)_Py_atomic_load_uint16((const uint16_t *)obj); +} + +static inline int32_t +_Py_atomic_load_int32(const int32_t *obj) +{ + return (int32_t)_Py_atomic_load_uint32((const uint32_t *)obj); +} + +static inline int +_Py_atomic_load_int(const int *obj) +{ + _Py_atomic_ASSERT_ARG_TYPE(uint32_t); + return (int)_Py_atomic_load_uint32((uint32_t *)obj); +} + +static inline unsigned int +_Py_atomic_load_uint(const unsigned int *obj) +{ + _Py_atomic_ASSERT_ARG_TYPE(uint32_t); + return (unsigned int)_Py_atomic_load_uint32((uint32_t *)obj); +} + +static inline int64_t +_Py_atomic_load_int64(const int64_t *obj) +{ + return (int64_t)_Py_atomic_load_uint64((const uint64_t *)obj); +} + +static inline void* +_Py_atomic_load_ptr(const void *obj) +{ +#if SIZEOF_VOID_P == 8 + return (void*)_Py_atomic_load_uint64((const uint64_t *)obj); +#else + return (void*)_Py_atomic_load_uint32((const uint32_t *)obj); +#endif +} + +static inline intptr_t +_Py_atomic_load_intptr(const intptr_t *obj) +{ + _Py_atomic_ASSERT_ARG_TYPE(void*); + return (intptr_t)_Py_atomic_load_ptr((void*)obj); +} + +static inline uintptr_t +_Py_atomic_load_uintptr(const uintptr_t *obj) +{ + _Py_atomic_ASSERT_ARG_TYPE(void*); + return (uintptr_t)_Py_atomic_load_ptr((void*)obj); +} + +static inline Py_ssize_t +_Py_atomic_load_ssize(const Py_ssize_t *obj) +{ + _Py_atomic_ASSERT_ARG_TYPE(void*); + return (Py_ssize_t)_Py_atomic_load_ptr((void*)obj); +} + + +// --- _Py_atomic_load_relaxed ----------------------------------------------- + +static inline int +_Py_atomic_load_int_relaxed(const int *obj) +{ + return *(volatile int *)obj; +} + +static inline int8_t +_Py_atomic_load_int8_relaxed(const int8_t *obj) +{ + return *(volatile int8_t *)obj; +} + +static inline int16_t +_Py_atomic_load_int16_relaxed(const int16_t *obj) +{ + return *(volatile int16_t *)obj; +} + +static inline int32_t +_Py_atomic_load_int32_relaxed(const int32_t *obj) +{ + return *(volatile int32_t *)obj; +} + +static inline int64_t +_Py_atomic_load_int64_relaxed(const int64_t *obj) +{ + return *(volatile int64_t *)obj; +} + +static inline intptr_t +_Py_atomic_load_intptr_relaxed(const intptr_t *obj) +{ + return *(volatile intptr_t *)obj; +} + +static inline uint8_t +_Py_atomic_load_uint8_relaxed(const uint8_t *obj) +{ + return *(volatile uint8_t *)obj; +} + +static inline uint16_t +_Py_atomic_load_uint16_relaxed(const uint16_t *obj) +{ + return *(volatile uint16_t *)obj; +} + +static inline uint32_t +_Py_atomic_load_uint32_relaxed(const uint32_t *obj) +{ + return *(volatile uint32_t *)obj; +} + +static inline uint64_t +_Py_atomic_load_uint64_relaxed(const uint64_t *obj) +{ + return *(volatile uint64_t *)obj; +} + +static inline uintptr_t +_Py_atomic_load_uintptr_relaxed(const uintptr_t *obj) +{ + return *(volatile uintptr_t *)obj; +} + +static inline unsigned int +_Py_atomic_load_uint_relaxed(const unsigned int *obj) +{ + return *(volatile unsigned int *)obj; +} + +static inline Py_ssize_t +_Py_atomic_load_ssize_relaxed(const Py_ssize_t *obj) +{ + return *(volatile Py_ssize_t *)obj; +} + +static inline void* +_Py_atomic_load_ptr_relaxed(const void *obj) +{ + return *(void * volatile *)obj; +} + + +// --- _Py_atomic_store ------------------------------------------------------ + +static inline void +_Py_atomic_store_int(int *obj, int value) +{ + (void)_Py_atomic_exchange_int(obj, value); +} + +static inline void +_Py_atomic_store_int8(int8_t *obj, int8_t value) +{ + (void)_Py_atomic_exchange_int8(obj, value); +} + +static inline void +_Py_atomic_store_int16(int16_t *obj, int16_t value) +{ + (void)_Py_atomic_exchange_int16(obj, value); +} + +static inline void +_Py_atomic_store_int32(int32_t *obj, int32_t value) +{ + (void)_Py_atomic_exchange_int32(obj, value); +} + +static inline void +_Py_atomic_store_int64(int64_t *obj, int64_t value) +{ + (void)_Py_atomic_exchange_int64(obj, value); +} + +static inline void +_Py_atomic_store_intptr(intptr_t *obj, intptr_t value) +{ + (void)_Py_atomic_exchange_intptr(obj, value); +} + +static inline void +_Py_atomic_store_uint8(uint8_t *obj, uint8_t value) +{ + (void)_Py_atomic_exchange_uint8(obj, value); +} + +static inline void +_Py_atomic_store_uint16(uint16_t *obj, uint16_t value) +{ + (void)_Py_atomic_exchange_uint16(obj, value); +} + +static inline void +_Py_atomic_store_uint32(uint32_t *obj, uint32_t value) +{ + (void)_Py_atomic_exchange_uint32(obj, value); +} + +static inline void +_Py_atomic_store_uint64(uint64_t *obj, uint64_t value) +{ + (void)_Py_atomic_exchange_uint64(obj, value); +} + +static inline void +_Py_atomic_store_uintptr(uintptr_t *obj, uintptr_t value) +{ + (void)_Py_atomic_exchange_uintptr(obj, value); +} + +static inline void +_Py_atomic_store_uint(unsigned int *obj, unsigned int value) +{ + (void)_Py_atomic_exchange_uint(obj, value); +} + +static inline void +_Py_atomic_store_ptr(void *obj, void *value) +{ + (void)_Py_atomic_exchange_ptr(obj, value); +} + +static inline void +_Py_atomic_store_ssize(Py_ssize_t *obj, Py_ssize_t value) +{ + (void)_Py_atomic_exchange_ssize(obj, value); +} + + +// --- _Py_atomic_store_relaxed ---------------------------------------------- + +static inline void +_Py_atomic_store_int_relaxed(int *obj, int value) +{ + *(volatile int *)obj = value; +} + +static inline void +_Py_atomic_store_int8_relaxed(int8_t *obj, int8_t value) +{ + *(volatile int8_t *)obj = value; +} + +static inline void +_Py_atomic_store_int16_relaxed(int16_t *obj, int16_t value) +{ + *(volatile int16_t *)obj = value; +} + +static inline void +_Py_atomic_store_int32_relaxed(int32_t *obj, int32_t value) +{ + *(volatile int32_t *)obj = value; +} + +static inline void +_Py_atomic_store_int64_relaxed(int64_t *obj, int64_t value) +{ + *(volatile int64_t *)obj = value; +} + +static inline void +_Py_atomic_store_intptr_relaxed(intptr_t *obj, intptr_t value) +{ + *(volatile intptr_t *)obj = value; +} + +static inline void +_Py_atomic_store_uint8_relaxed(uint8_t *obj, uint8_t value) +{ + *(volatile uint8_t *)obj = value; +} + +static inline void +_Py_atomic_store_uint16_relaxed(uint16_t *obj, uint16_t value) +{ + *(volatile uint16_t *)obj = value; +} + +static inline void +_Py_atomic_store_uint32_relaxed(uint32_t *obj, uint32_t value) +{ + *(volatile uint32_t *)obj = value; +} + +static inline void +_Py_atomic_store_uint64_relaxed(uint64_t *obj, uint64_t value) +{ + *(volatile uint64_t *)obj = value; +} + +static inline void +_Py_atomic_store_uintptr_relaxed(uintptr_t *obj, uintptr_t value) +{ + *(volatile uintptr_t *)obj = value; +} + +static inline void +_Py_atomic_store_uint_relaxed(unsigned int *obj, unsigned int value) +{ + *(volatile unsigned int *)obj = value; +} + +static inline void +_Py_atomic_store_ptr_relaxed(void *obj, void* value) +{ + *(void * volatile *)obj = value; +} + +static inline void +_Py_atomic_store_ssize_relaxed(Py_ssize_t *obj, Py_ssize_t value) +{ + *(volatile Py_ssize_t *)obj = value; +} + +// --- _Py_atomic_load_ptr_acquire / _Py_atomic_store_ptr_release ------------ + +static inline void * +_Py_atomic_load_ptr_acquire(const void *obj) +{ +#if defined(_M_X64) || defined(_M_IX86) + return *(void * volatile *)obj; +#elif defined(_M_ARM64) + return (void *)__ldar64((unsigned __int64 volatile *)obj); +#else +# error "no implementation of _Py_atomic_load_ptr_acquire" +#endif +} + +static inline void +_Py_atomic_store_ptr_release(void *obj, void *value) +{ +#if defined(_M_X64) || defined(_M_IX86) + *(void * volatile *)obj = value; +#elif defined(_M_ARM64) + __stlr64((unsigned __int64 volatile *)obj, (uintptr_t)value); +#else +# error "no implementation of _Py_atomic_store_ptr_release" +#endif +} + +static inline void +_Py_atomic_store_int_release(int *obj, int value) +{ +#if defined(_M_X64) || defined(_M_IX86) + *(int volatile *)obj = value; +#elif defined(_M_ARM64) + _Py_atomic_ASSERT_ARG_TYPE(unsigned __int32); + __stlr32((unsigned __int32 volatile *)obj, (unsigned __int32)value); +#else +# error "no implementation of _Py_atomic_store_int_release" +#endif +} + +static inline int +_Py_atomic_load_int_acquire(const int *obj) +{ +#if defined(_M_X64) || defined(_M_IX86) + return *(int volatile *)obj; +#elif defined(_M_ARM64) + _Py_atomic_ASSERT_ARG_TYPE(unsigned __int32); + return (int)__ldar32((unsigned __int32 volatile *)obj); +#else +# error "no implementation of _Py_atomic_load_int_acquire" +#endif +} + + +// --- _Py_atomic_fence ------------------------------------------------------ + + static inline void +_Py_atomic_fence_seq_cst(void) +{ +#if defined(_M_ARM64) + __dmb(_ARM64_BARRIER_ISH); +#elif defined(_M_X64) + __faststorefence(); +#elif defined(_M_IX86) + _mm_mfence(); +#else +# error "no implementation of _Py_atomic_fence_seq_cst" +#endif +} + + static inline void +_Py_atomic_fence_release(void) +{ +#if defined(_M_ARM64) + __dmb(_ARM64_BARRIER_ISH); +#elif defined(_M_X64) || defined(_M_IX86) + _ReadWriteBarrier(); +#else +# error "no implementation of _Py_atomic_fence_release" +#endif +} + +#undef _Py_atomic_ASSERT_ARG_TYPE diff --git a/Include/cpython/pyatomic_std.h b/Include/cpython/pyatomic_std.h new file mode 100644 index 00000000000000..a05bfaec47e89d --- /dev/null +++ b/Include/cpython/pyatomic_std.h @@ -0,0 +1,889 @@ +// This is the implementation of Python atomic operations using C++11 or C11 +// atomics. Note that the pyatomic_gcc.h implementation is preferred for GCC +// compatible compilers, even if they support C++11 atomics. + +#ifndef Py_ATOMIC_STD_H +# error "this header file must not be included directly" +#endif + +#ifdef __cplusplus +extern "C++" { +# include +} +# define _Py_USING_STD using namespace std +# define _Atomic(tp) atomic +#else +# define _Py_USING_STD +# include +#endif + + +// --- _Py_atomic_add -------------------------------------------------------- + +static inline int +_Py_atomic_add_int(int *obj, int value) +{ + _Py_USING_STD; + return atomic_fetch_add((_Atomic(int)*)obj, value); +} + +static inline int8_t +_Py_atomic_add_int8(int8_t *obj, int8_t value) +{ + _Py_USING_STD; + return atomic_fetch_add((_Atomic(int8_t)*)obj, value); +} + +static inline int16_t +_Py_atomic_add_int16(int16_t *obj, int16_t value) +{ + _Py_USING_STD; + return atomic_fetch_add((_Atomic(int16_t)*)obj, value); +} + +static inline int32_t +_Py_atomic_add_int32(int32_t *obj, int32_t value) +{ + _Py_USING_STD; + return atomic_fetch_add((_Atomic(int32_t)*)obj, value); +} + +static inline int64_t +_Py_atomic_add_int64(int64_t *obj, int64_t value) +{ + _Py_USING_STD; + return atomic_fetch_add((_Atomic(int64_t)*)obj, value); +} + +static inline intptr_t +_Py_atomic_add_intptr(intptr_t *obj, intptr_t value) +{ + _Py_USING_STD; + return atomic_fetch_add((_Atomic(intptr_t)*)obj, value); +} + +static inline unsigned int +_Py_atomic_add_uint(unsigned int *obj, unsigned int value) +{ + _Py_USING_STD; + return atomic_fetch_add((_Atomic(unsigned int)*)obj, value); +} + +static inline uint8_t +_Py_atomic_add_uint8(uint8_t *obj, uint8_t value) +{ + _Py_USING_STD; + return atomic_fetch_add((_Atomic(uint8_t)*)obj, value); +} + +static inline uint16_t +_Py_atomic_add_uint16(uint16_t *obj, uint16_t value) +{ + _Py_USING_STD; + return atomic_fetch_add((_Atomic(uint16_t)*)obj, value); +} + +static inline uint32_t +_Py_atomic_add_uint32(uint32_t *obj, uint32_t value) +{ + _Py_USING_STD; + return atomic_fetch_add((_Atomic(uint32_t)*)obj, value); +} + +static inline uint64_t +_Py_atomic_add_uint64(uint64_t *obj, uint64_t value) +{ + _Py_USING_STD; + return atomic_fetch_add((_Atomic(uint64_t)*)obj, value); +} + +static inline uintptr_t +_Py_atomic_add_uintptr(uintptr_t *obj, uintptr_t value) +{ + _Py_USING_STD; + return atomic_fetch_add((_Atomic(uintptr_t)*)obj, value); +} + +static inline Py_ssize_t +_Py_atomic_add_ssize(Py_ssize_t *obj, Py_ssize_t value) +{ + _Py_USING_STD; + return atomic_fetch_add((_Atomic(Py_ssize_t)*)obj, value); +} + + +// --- _Py_atomic_compare_exchange ------------------------------------------- + +static inline int +_Py_atomic_compare_exchange_int(int *obj, int *expected, int desired) +{ + _Py_USING_STD; + return atomic_compare_exchange_strong((_Atomic(int)*)obj, + expected, desired); +} + +static inline int +_Py_atomic_compare_exchange_int8(int8_t *obj, int8_t *expected, int8_t desired) +{ + _Py_USING_STD; + return atomic_compare_exchange_strong((_Atomic(int8_t)*)obj, + expected, desired); +} + +static inline int +_Py_atomic_compare_exchange_int16(int16_t *obj, int16_t *expected, int16_t desired) +{ + _Py_USING_STD; + return atomic_compare_exchange_strong((_Atomic(int16_t)*)obj, + expected, desired); +} + +static inline int +_Py_atomic_compare_exchange_int32(int32_t *obj, int32_t *expected, int32_t desired) +{ + _Py_USING_STD; + return atomic_compare_exchange_strong((_Atomic(int32_t)*)obj, + expected, desired); +} + +static inline int +_Py_atomic_compare_exchange_int64(int64_t *obj, int64_t *expected, int64_t desired) +{ + _Py_USING_STD; + return atomic_compare_exchange_strong((_Atomic(int64_t)*)obj, + expected, desired); +} + +static inline int +_Py_atomic_compare_exchange_intptr(intptr_t *obj, intptr_t *expected, intptr_t desired) +{ + _Py_USING_STD; + return atomic_compare_exchange_strong((_Atomic(intptr_t)*)obj, + expected, desired); +} + +static inline int +_Py_atomic_compare_exchange_uint(unsigned int *obj, unsigned int *expected, unsigned int desired) +{ + _Py_USING_STD; + return atomic_compare_exchange_strong((_Atomic(unsigned int)*)obj, + expected, desired); +} + +static inline int +_Py_atomic_compare_exchange_uint8(uint8_t *obj, uint8_t *expected, uint8_t desired) +{ + _Py_USING_STD; + return atomic_compare_exchange_strong((_Atomic(uint8_t)*)obj, + expected, desired); +} + +static inline int +_Py_atomic_compare_exchange_uint16(uint16_t *obj, uint16_t *expected, uint16_t desired) +{ + _Py_USING_STD; + return atomic_compare_exchange_strong((_Atomic(uint16_t)*)obj, + expected, desired); +} + +static inline int +_Py_atomic_compare_exchange_uint32(uint32_t *obj, uint32_t *expected, uint32_t desired) +{ + _Py_USING_STD; + return atomic_compare_exchange_strong((_Atomic(uint32_t)*)obj, + expected, desired); +} + +static inline int +_Py_atomic_compare_exchange_uint64(uint64_t *obj, uint64_t *expected, uint64_t desired) +{ + _Py_USING_STD; + return atomic_compare_exchange_strong((_Atomic(uint64_t)*)obj, + expected, desired); +} + +static inline int +_Py_atomic_compare_exchange_uintptr(uintptr_t *obj, uintptr_t *expected, uintptr_t desired) +{ + _Py_USING_STD; + return atomic_compare_exchange_strong((_Atomic(uintptr_t)*)obj, + expected, desired); +} + +static inline int +_Py_atomic_compare_exchange_ssize(Py_ssize_t *obj, Py_ssize_t *expected, Py_ssize_t desired) +{ + _Py_USING_STD; + return atomic_compare_exchange_strong((_Atomic(Py_ssize_t)*)obj, + expected, desired); +} + +static inline int +_Py_atomic_compare_exchange_ptr(void *obj, void *expected, void *desired) +{ + _Py_USING_STD; + return atomic_compare_exchange_strong((_Atomic(void *)*)obj, + (void **)expected, desired); +} + + +// --- _Py_atomic_exchange --------------------------------------------------- + +static inline int +_Py_atomic_exchange_int(int *obj, int value) +{ + _Py_USING_STD; + return atomic_exchange((_Atomic(int)*)obj, value); +} + +static inline int8_t +_Py_atomic_exchange_int8(int8_t *obj, int8_t value) +{ + _Py_USING_STD; + return atomic_exchange((_Atomic(int8_t)*)obj, value); +} + +static inline int16_t +_Py_atomic_exchange_int16(int16_t *obj, int16_t value) +{ + _Py_USING_STD; + return atomic_exchange((_Atomic(int16_t)*)obj, value); +} + +static inline int32_t +_Py_atomic_exchange_int32(int32_t *obj, int32_t value) +{ + _Py_USING_STD; + return atomic_exchange((_Atomic(int32_t)*)obj, value); +} + +static inline int64_t +_Py_atomic_exchange_int64(int64_t *obj, int64_t value) +{ + _Py_USING_STD; + return atomic_exchange((_Atomic(int64_t)*)obj, value); +} + +static inline intptr_t +_Py_atomic_exchange_intptr(intptr_t *obj, intptr_t value) +{ + _Py_USING_STD; + return atomic_exchange((_Atomic(intptr_t)*)obj, value); +} + +static inline unsigned int +_Py_atomic_exchange_uint(unsigned int *obj, unsigned int value) +{ + _Py_USING_STD; + return atomic_exchange((_Atomic(unsigned int)*)obj, value); +} + +static inline uint8_t +_Py_atomic_exchange_uint8(uint8_t *obj, uint8_t value) +{ + _Py_USING_STD; + return atomic_exchange((_Atomic(uint8_t)*)obj, value); +} + +static inline uint16_t +_Py_atomic_exchange_uint16(uint16_t *obj, uint16_t value) +{ + _Py_USING_STD; + return atomic_exchange((_Atomic(uint16_t)*)obj, value); +} + +static inline uint32_t +_Py_atomic_exchange_uint32(uint32_t *obj, uint32_t value) +{ + _Py_USING_STD; + return atomic_exchange((_Atomic(uint32_t)*)obj, value); +} + +static inline uint64_t +_Py_atomic_exchange_uint64(uint64_t *obj, uint64_t value) +{ + _Py_USING_STD; + return atomic_exchange((_Atomic(uint64_t)*)obj, value); +} + +static inline uintptr_t +_Py_atomic_exchange_uintptr(uintptr_t *obj, uintptr_t value) +{ + _Py_USING_STD; + return atomic_exchange((_Atomic(uintptr_t)*)obj, value); +} + +static inline Py_ssize_t +_Py_atomic_exchange_ssize(Py_ssize_t *obj, Py_ssize_t value) +{ + _Py_USING_STD; + return atomic_exchange((_Atomic(Py_ssize_t)*)obj, value); +} + +static inline void* +_Py_atomic_exchange_ptr(void *obj, void *value) +{ + _Py_USING_STD; + return atomic_exchange((_Atomic(void *)*)obj, value); +} + + +// --- _Py_atomic_and -------------------------------------------------------- + +static inline uint8_t +_Py_atomic_and_uint8(uint8_t *obj, uint8_t value) +{ + _Py_USING_STD; + return atomic_fetch_and((_Atomic(uint8_t)*)obj, value); +} + +static inline uint16_t +_Py_atomic_and_uint16(uint16_t *obj, uint16_t value) +{ + _Py_USING_STD; + return atomic_fetch_and((_Atomic(uint16_t)*)obj, value); +} + +static inline uint32_t +_Py_atomic_and_uint32(uint32_t *obj, uint32_t value) +{ + _Py_USING_STD; + return atomic_fetch_and((_Atomic(uint32_t)*)obj, value); +} + +static inline uint64_t +_Py_atomic_and_uint64(uint64_t *obj, uint64_t value) +{ + _Py_USING_STD; + return atomic_fetch_and((_Atomic(uint64_t)*)obj, value); +} + +static inline uintptr_t +_Py_atomic_and_uintptr(uintptr_t *obj, uintptr_t value) +{ + _Py_USING_STD; + return atomic_fetch_and((_Atomic(uintptr_t)*)obj, value); +} + + +// --- _Py_atomic_or --------------------------------------------------------- + +static inline uint8_t +_Py_atomic_or_uint8(uint8_t *obj, uint8_t value) +{ + _Py_USING_STD; + return atomic_fetch_or((_Atomic(uint8_t)*)obj, value); +} + +static inline uint16_t +_Py_atomic_or_uint16(uint16_t *obj, uint16_t value) +{ + _Py_USING_STD; + return atomic_fetch_or((_Atomic(uint16_t)*)obj, value); +} + +static inline uint32_t +_Py_atomic_or_uint32(uint32_t *obj, uint32_t value) +{ + _Py_USING_STD; + return atomic_fetch_or((_Atomic(uint32_t)*)obj, value); +} + +static inline uint64_t +_Py_atomic_or_uint64(uint64_t *obj, uint64_t value) +{ + _Py_USING_STD; + return atomic_fetch_or((_Atomic(uint64_t)*)obj, value); +} + +static inline uintptr_t +_Py_atomic_or_uintptr(uintptr_t *obj, uintptr_t value) +{ + _Py_USING_STD; + return atomic_fetch_or((_Atomic(uintptr_t)*)obj, value); +} + + +// --- _Py_atomic_load ------------------------------------------------------- + +static inline int +_Py_atomic_load_int(const int *obj) +{ + _Py_USING_STD; + return atomic_load((const _Atomic(int)*)obj); +} + +static inline int8_t +_Py_atomic_load_int8(const int8_t *obj) +{ + _Py_USING_STD; + return atomic_load((const _Atomic(int8_t)*)obj); +} + +static inline int16_t +_Py_atomic_load_int16(const int16_t *obj) +{ + _Py_USING_STD; + return atomic_load((const _Atomic(int16_t)*)obj); +} + +static inline int32_t +_Py_atomic_load_int32(const int32_t *obj) +{ + _Py_USING_STD; + return atomic_load((const _Atomic(int32_t)*)obj); +} + +static inline int64_t +_Py_atomic_load_int64(const int64_t *obj) +{ + _Py_USING_STD; + return atomic_load((const _Atomic(int64_t)*)obj); +} + +static inline intptr_t +_Py_atomic_load_intptr(const intptr_t *obj) +{ + _Py_USING_STD; + return atomic_load((const _Atomic(intptr_t)*)obj); +} + +static inline uint8_t +_Py_atomic_load_uint8(const uint8_t *obj) +{ + _Py_USING_STD; + return atomic_load((const _Atomic(uint8_t)*)obj); +} + +static inline uint16_t +_Py_atomic_load_uint16(const uint16_t *obj) +{ + _Py_USING_STD; + return atomic_load((const _Atomic(uint32_t)*)obj); +} + +static inline uint32_t +_Py_atomic_load_uint32(const uint32_t *obj) +{ + _Py_USING_STD; + return atomic_load((const _Atomic(uint32_t)*)obj); +} + +static inline uint64_t +_Py_atomic_load_uint64(const uint64_t *obj) +{ + _Py_USING_STD; + return atomic_load((const _Atomic(uint64_t)*)obj); +} + +static inline uintptr_t +_Py_atomic_load_uintptr(const uintptr_t *obj) +{ + _Py_USING_STD; + return atomic_load((const _Atomic(uintptr_t)*)obj); +} + +static inline unsigned int +_Py_atomic_load_uint(const unsigned int *obj) +{ + _Py_USING_STD; + return atomic_load((const _Atomic(unsigned int)*)obj); +} + +static inline Py_ssize_t +_Py_atomic_load_ssize(const Py_ssize_t *obj) +{ + _Py_USING_STD; + return atomic_load((const _Atomic(Py_ssize_t)*)obj); +} + +static inline void* +_Py_atomic_load_ptr(const void *obj) +{ + _Py_USING_STD; + return atomic_load((const _Atomic(void*)*)obj); +} + + +// --- _Py_atomic_load_relaxed ----------------------------------------------- + +static inline int +_Py_atomic_load_int_relaxed(const int *obj) +{ + _Py_USING_STD; + return atomic_load_explicit((const _Atomic(int)*)obj, + memory_order_relaxed); +} + +static inline int8_t +_Py_atomic_load_int8_relaxed(const int8_t *obj) +{ + _Py_USING_STD; + return atomic_load_explicit((const _Atomic(int8_t)*)obj, + memory_order_relaxed); +} + +static inline int16_t +_Py_atomic_load_int16_relaxed(const int16_t *obj) +{ + _Py_USING_STD; + return atomic_load_explicit((const _Atomic(int16_t)*)obj, + memory_order_relaxed); +} + +static inline int32_t +_Py_atomic_load_int32_relaxed(const int32_t *obj) +{ + _Py_USING_STD; + return atomic_load_explicit((const _Atomic(int32_t)*)obj, + memory_order_relaxed); +} + +static inline int64_t +_Py_atomic_load_int64_relaxed(const int64_t *obj) +{ + _Py_USING_STD; + return atomic_load_explicit((const _Atomic(int64_t)*)obj, + memory_order_relaxed); +} + +static inline intptr_t +_Py_atomic_load_intptr_relaxed(const intptr_t *obj) +{ + _Py_USING_STD; + return atomic_load_explicit((const _Atomic(intptr_t)*)obj, + memory_order_relaxed); +} + +static inline uint8_t +_Py_atomic_load_uint8_relaxed(const uint8_t *obj) +{ + _Py_USING_STD; + return atomic_load_explicit((const _Atomic(uint8_t)*)obj, + memory_order_relaxed); +} + +static inline uint16_t +_Py_atomic_load_uint16_relaxed(const uint16_t *obj) +{ + _Py_USING_STD; + return atomic_load_explicit((const _Atomic(uint16_t)*)obj, + memory_order_relaxed); +} + +static inline uint32_t +_Py_atomic_load_uint32_relaxed(const uint32_t *obj) +{ + _Py_USING_STD; + return atomic_load_explicit((const _Atomic(uint32_t)*)obj, + memory_order_relaxed); +} + +static inline uint64_t +_Py_atomic_load_uint64_relaxed(const uint64_t *obj) +{ + _Py_USING_STD; + return atomic_load_explicit((const _Atomic(uint64_t)*)obj, + memory_order_relaxed); +} + +static inline uintptr_t +_Py_atomic_load_uintptr_relaxed(const uintptr_t *obj) +{ + _Py_USING_STD; + return atomic_load_explicit((const _Atomic(uintptr_t)*)obj, + memory_order_relaxed); +} + +static inline unsigned int +_Py_atomic_load_uint_relaxed(const unsigned int *obj) +{ + _Py_USING_STD; + return atomic_load_explicit((const _Atomic(unsigned int)*)obj, + memory_order_relaxed); +} + +static inline Py_ssize_t +_Py_atomic_load_ssize_relaxed(const Py_ssize_t *obj) +{ + _Py_USING_STD; + return atomic_load_explicit((const _Atomic(Py_ssize_t)*)obj, + memory_order_relaxed); +} + +static inline void* +_Py_atomic_load_ptr_relaxed(const void *obj) +{ + _Py_USING_STD; + return atomic_load_explicit((const _Atomic(void*)*)obj, + memory_order_relaxed); +} + + +// --- _Py_atomic_store ------------------------------------------------------ + +static inline void +_Py_atomic_store_int(int *obj, int value) +{ + _Py_USING_STD; + atomic_store((_Atomic(int)*)obj, value); +} + +static inline void +_Py_atomic_store_int8(int8_t *obj, int8_t value) +{ + _Py_USING_STD; + atomic_store((_Atomic(int8_t)*)obj, value); +} + +static inline void +_Py_atomic_store_int16(int16_t *obj, int16_t value) +{ + _Py_USING_STD; + atomic_store((_Atomic(int16_t)*)obj, value); +} + +static inline void +_Py_atomic_store_int32(int32_t *obj, int32_t value) +{ + _Py_USING_STD; + atomic_store((_Atomic(int32_t)*)obj, value); +} + +static inline void +_Py_atomic_store_int64(int64_t *obj, int64_t value) +{ + _Py_USING_STD; + atomic_store((_Atomic(int64_t)*)obj, value); +} + +static inline void +_Py_atomic_store_intptr(intptr_t *obj, intptr_t value) +{ + _Py_USING_STD; + atomic_store((_Atomic(intptr_t)*)obj, value); +} + +static inline void +_Py_atomic_store_uint8(uint8_t *obj, uint8_t value) +{ + _Py_USING_STD; + atomic_store((_Atomic(uint8_t)*)obj, value); +} + +static inline void +_Py_atomic_store_uint16(uint16_t *obj, uint16_t value) +{ + _Py_USING_STD; + atomic_store((_Atomic(uint16_t)*)obj, value); +} + +static inline void +_Py_atomic_store_uint32(uint32_t *obj, uint32_t value) +{ + _Py_USING_STD; + atomic_store((_Atomic(uint32_t)*)obj, value); +} + +static inline void +_Py_atomic_store_uint64(uint64_t *obj, uint64_t value) +{ + _Py_USING_STD; + atomic_store((_Atomic(uint64_t)*)obj, value); +} + +static inline void +_Py_atomic_store_uintptr(uintptr_t *obj, uintptr_t value) +{ + _Py_USING_STD; + atomic_store((_Atomic(uintptr_t)*)obj, value); +} + +static inline void +_Py_atomic_store_uint(unsigned int *obj, unsigned int value) +{ + _Py_USING_STD; + atomic_store((_Atomic(unsigned int)*)obj, value); +} + +static inline void +_Py_atomic_store_ptr(void *obj, void *value) +{ + _Py_USING_STD; + atomic_store((_Atomic(void*)*)obj, value); +} + +static inline void +_Py_atomic_store_ssize(Py_ssize_t *obj, Py_ssize_t value) +{ + _Py_USING_STD; + atomic_store((_Atomic(Py_ssize_t)*)obj, value); +} + + +// --- _Py_atomic_store_relaxed ---------------------------------------------- + +static inline void +_Py_atomic_store_int_relaxed(int *obj, int value) +{ + _Py_USING_STD; + atomic_store_explicit((_Atomic(int)*)obj, value, + memory_order_relaxed); +} + +static inline void +_Py_atomic_store_int8_relaxed(int8_t *obj, int8_t value) +{ + _Py_USING_STD; + atomic_store_explicit((_Atomic(int8_t)*)obj, value, + memory_order_relaxed); +} + +static inline void +_Py_atomic_store_int16_relaxed(int16_t *obj, int16_t value) +{ + _Py_USING_STD; + atomic_store_explicit((_Atomic(int16_t)*)obj, value, + memory_order_relaxed); +} + +static inline void +_Py_atomic_store_int32_relaxed(int32_t *obj, int32_t value) +{ + _Py_USING_STD; + atomic_store_explicit((_Atomic(int32_t)*)obj, value, + memory_order_relaxed); +} + +static inline void +_Py_atomic_store_int64_relaxed(int64_t *obj, int64_t value) +{ + _Py_USING_STD; + atomic_store_explicit((_Atomic(int64_t)*)obj, value, + memory_order_relaxed); +} + +static inline void +_Py_atomic_store_intptr_relaxed(intptr_t *obj, intptr_t value) +{ + _Py_USING_STD; + atomic_store_explicit((_Atomic(intptr_t)*)obj, value, + memory_order_relaxed); +} + +static inline void +_Py_atomic_store_uint8_relaxed(uint8_t *obj, uint8_t value) +{ + _Py_USING_STD; + atomic_store_explicit((_Atomic(uint8_t)*)obj, value, + memory_order_relaxed); +} + +static inline void +_Py_atomic_store_uint16_relaxed(uint16_t *obj, uint16_t value) +{ + _Py_USING_STD; + atomic_store_explicit((_Atomic(uint16_t)*)obj, value, + memory_order_relaxed); +} + +static inline void +_Py_atomic_store_uint32_relaxed(uint32_t *obj, uint32_t value) +{ + _Py_USING_STD; + atomic_store_explicit((_Atomic(uint32_t)*)obj, value, + memory_order_relaxed); +} + +static inline void +_Py_atomic_store_uint64_relaxed(uint64_t *obj, uint64_t value) +{ + _Py_USING_STD; + atomic_store_explicit((_Atomic(uint64_t)*)obj, value, + memory_order_relaxed); +} + +static inline void +_Py_atomic_store_uintptr_relaxed(uintptr_t *obj, uintptr_t value) +{ + _Py_USING_STD; + atomic_store_explicit((_Atomic(uintptr_t)*)obj, value, + memory_order_relaxed); +} + +static inline void +_Py_atomic_store_uint_relaxed(unsigned int *obj, unsigned int value) +{ + _Py_USING_STD; + atomic_store_explicit((_Atomic(unsigned int)*)obj, value, + memory_order_relaxed); +} + +static inline void +_Py_atomic_store_ptr_relaxed(void *obj, void *value) +{ + _Py_USING_STD; + atomic_store_explicit((_Atomic(void*)*)obj, value, + memory_order_relaxed); +} + +static inline void +_Py_atomic_store_ssize_relaxed(Py_ssize_t *obj, Py_ssize_t value) +{ + _Py_USING_STD; + atomic_store_explicit((_Atomic(Py_ssize_t)*)obj, value, + memory_order_relaxed); +} + + +// --- _Py_atomic_load_ptr_acquire / _Py_atomic_store_ptr_release ------------ + +static inline void * +_Py_atomic_load_ptr_acquire(const void *obj) +{ + _Py_USING_STD; + return atomic_load_explicit((const _Atomic(void*)*)obj, + memory_order_acquire); +} + +static inline void +_Py_atomic_store_ptr_release(void *obj, void *value) +{ + _Py_USING_STD; + atomic_store_explicit((_Atomic(void*)*)obj, value, + memory_order_release); +} + +static inline void +_Py_atomic_store_int_release(int *obj, int value) +{ + _Py_USING_STD; + atomic_store_explicit((_Atomic(int)*)obj, value, + memory_order_release); +} + +static inline int +_Py_atomic_load_int_acquire(const int *obj) +{ + _Py_USING_STD; + return atomic_load_explicit((const _Atomic(int)*)obj, + memory_order_acquire); +} + + + +// --- _Py_atomic_fence ------------------------------------------------------ + + static inline void +_Py_atomic_fence_seq_cst(void) +{ + _Py_USING_STD; + atomic_thread_fence(memory_order_seq_cst); +} + + static inline void +_Py_atomic_fence_release(void) +{ + _Py_USING_STD; + atomic_thread_fence(memory_order_release); +} diff --git a/Include/cpython/pyerrors.h b/Include/cpython/pyerrors.h index 5c128211bd525a..479b908fb7058a 100644 --- a/Include/cpython/pyerrors.h +++ b/Include/cpython/pyerrors.h @@ -88,15 +88,6 @@ typedef PyOSErrorObject PyEnvironmentErrorObject; typedef PyOSErrorObject PyWindowsErrorObject; #endif -/* Error handling definitions */ - -PyAPI_FUNC(void) _PyErr_SetKeyError(PyObject *); - -/* Context manipulation (PEP 3134) */ - -Py_DEPRECATED(3.12) PyAPI_FUNC(void) _PyErr_ChainExceptions(PyObject *, PyObject *, PyObject *); -PyAPI_FUNC(void) _PyErr_ChainExceptions1(PyObject *); - /* In exceptions.c */ PyAPI_FUNC(PyObject*) PyUnstable_Exc_PrepReraiseStar( @@ -125,12 +116,10 @@ PyAPI_FUNC(PyObject *) PyErr_ProgramTextObject( PyObject *filename, int lineno); -PyAPI_FUNC(void) _PyErr_WriteUnraisableMsg( - const char *err_msg, - PyObject *obj); - PyAPI_FUNC(void) _Py_NO_RETURN _Py_FatalErrorFunc( const char *func, const char *message); +PyAPI_FUNC(void) PyErr_FormatUnraisable(const char *, ...); + #define Py_FatalError(message) _Py_FatalErrorFunc(__func__, (message)) diff --git a/Include/cpython/pyframe.h b/Include/cpython/pyframe.h index 0e2afff925e31f..c5adbbe4868f69 100644 --- a/Include/cpython/pyframe.h +++ b/Include/cpython/pyframe.h @@ -33,3 +33,11 @@ PyAPI_FUNC(int) PyUnstable_InterpreterFrame_GetLasti(struct _PyInterpreterFrame /* Returns the currently executing line number, or -1 if there is no line number. * Does not raise an exception. */ PyAPI_FUNC(int) PyUnstable_InterpreterFrame_GetLine(struct _PyInterpreterFrame *frame); + +#define PyUnstable_EXECUTABLE_KIND_SKIP 0 +#define PyUnstable_EXECUTABLE_KIND_PY_FUNCTION 1 +#define PyUnstable_EXECUTABLE_KIND_BUILTIN_FUNCTION 3 +#define PyUnstable_EXECUTABLE_KIND_METHOD_DESCRIPTOR 4 +#define PyUnstable_EXECUTABLE_KINDS 5 + +PyAPI_DATA(const PyTypeObject *) const PyUnstable_ExecutableKinds[PyUnstable_EXECUTABLE_KINDS+1]; diff --git a/Include/cpython/pyhash.h b/Include/cpython/pyhash.h new file mode 100644 index 00000000000000..396c208e1b106a --- /dev/null +++ b/Include/cpython/pyhash.h @@ -0,0 +1,39 @@ +#ifndef Py_CPYTHON_HASH_H +# error "this header file must not be included directly" +#endif + +/* Prime multiplier used in string and various other hashes. */ +#define _PyHASH_MULTIPLIER 1000003UL /* 0xf4243 */ + +/* Parameters used for the numeric hash implementation. See notes for + _Py_HashDouble in Python/pyhash.c. Numeric hashes are based on + reduction modulo the prime 2**_PyHASH_BITS - 1. */ + +#if SIZEOF_VOID_P >= 8 +# define _PyHASH_BITS 61 +#else +# define _PyHASH_BITS 31 +#endif + +#define _PyHASH_MODULUS (((size_t)1 << _PyHASH_BITS) - 1) +#define _PyHASH_INF 314159 +#define _PyHASH_IMAG _PyHASH_MULTIPLIER + +/* Helpers for hash functions */ +PyAPI_FUNC(Py_hash_t) _Py_HashDouble(PyObject *, double); + +// Kept for backward compatibility +#define _Py_HashPointer Py_HashPointer + + +/* hash function definition */ +typedef struct { + Py_hash_t (*const hash)(const void *, Py_ssize_t); + const char *name; + const int hash_bits; + const int seed_bits; +} PyHash_FuncDef; + +PyAPI_FUNC(PyHash_FuncDef*) PyHash_GetFuncDef(void); + +PyAPI_FUNC(Py_hash_t) Py_HashPointer(const void *ptr); diff --git a/Include/cpython/pymem.h b/Include/cpython/pymem.h index b75f1c4d2425dd..76b3221f7b9f39 100644 --- a/Include/cpython/pymem.h +++ b/Include/cpython/pymem.h @@ -2,12 +2,6 @@ # error "this header file must not be included directly" #endif -PyAPI_FUNC(void *) PyMem_RawMalloc(size_t size); -PyAPI_FUNC(void *) PyMem_RawCalloc(size_t nelem, size_t elsize); -PyAPI_FUNC(void *) PyMem_RawRealloc(void *ptr, size_t new_size); -PyAPI_FUNC(void) PyMem_RawFree(void *ptr); - - typedef enum { /* PyMem_RawMalloc(), PyMem_RawRealloc() and PyMem_RawFree() */ PYMEM_DOMAIN_RAW, @@ -29,6 +23,10 @@ typedef enum { PYMEM_ALLOCATOR_PYMALLOC = 5, PYMEM_ALLOCATOR_PYMALLOC_DEBUG = 6, #endif +#ifdef WITH_MIMALLOC + PYMEM_ALLOCATOR_MIMALLOC = 7, + PYMEM_ALLOCATOR_MIMALLOC_DEBUG = 8, +#endif } PyMemAllocatorName; diff --git a/Include/cpython/pystate.h b/Include/cpython/pystate.h index 56e473cc5e42d5..ed7dd829d4b6f0 100644 --- a/Include/cpython/pystate.h +++ b/Include/cpython/pystate.h @@ -29,24 +29,6 @@ typedef int (*Py_tracefunc)(PyObject *, PyFrameObject *, int, PyObject *); #define PyTrace_C_RETURN 6 #define PyTrace_OPCODE 7 -// Internal structure: you should not use it directly, but use public functions -// like PyThreadState_EnterTracing() and PyThreadState_LeaveTracing(). -typedef struct _PyCFrame { - /* This struct will be threaded through the C stack - * allowing fast access to per-thread state that needs - * to be accessed quickly by the interpreter, but can - * be modified outside of the interpreter. - * - * WARNING: This makes data on the C stack accessible from - * heap objects. Care must be taken to maintain stack - * discipline and make sure that instances of this struct cannot - * accessed outside of their lifetime. - */ - /* Pointer to the currently executing frame (it can be NULL) */ - struct _PyInterpreterFrame *current_frame; - struct _PyCFrame *previous; -} _PyCFrame; - typedef struct _err_stackitem { /* This struct represents a single execution context where we might * be currently handling an exception. It is a per-coroutine state @@ -110,6 +92,19 @@ struct _ts { /* padding to align to 4 bytes */ unsigned int :24; } _status; +#ifdef Py_BUILD_CORE +# define _PyThreadState_WHENCE_NOTSET -1 +# define _PyThreadState_WHENCE_UNKNOWN 0 +# define _PyThreadState_WHENCE_INTERP 1 +# define _PyThreadState_WHENCE_THREADING 2 +# define _PyThreadState_WHENCE_GILSTATE 3 +# define _PyThreadState_WHENCE_EXEC 4 +#endif + int _whence; + + /* Thread state (_Py_THREAD_ATTACHED, _Py_THREAD_DETACHED, _Py_THREAD_GC). + See Include/internal/pycore_pystate.h for more details. */ + int state; int py_recursion_remaining; int py_recursion_limit; @@ -123,9 +118,8 @@ struct _ts { int tracing; int what_event; /* The event currently being monitored, if any. */ - /* Pointer to current _PyCFrame in the C stack frame of the currently, - * or most recently, executing _PyEval_EvalFrameDefault. */ - _PyCFrame *cframe; + /* Pointer to currently executing frame. */ + struct _PyInterpreterFrame *current_frame; Py_tracefunc c_profilefunc; Py_tracefunc c_tracefunc; @@ -155,6 +149,13 @@ struct _ts { struct _py_trashcan trash; + /* Tagged pointer to top-most critical section, or zero if there is no + * active critical section. Critical sections are only used in + * `--disable-gil` builds (i.e., when Py_GIL_DISABLED is defined to 1). In the + * default build, this field is always zero. + */ + uintptr_t critical_section; + /* Called when a thread state is deleted normally, but not when it * is destroyed after fork(). * Pain: to prevent rare but fatal shutdown errors (issue 18808), @@ -211,27 +212,34 @@ struct _ts { /* The thread's exception stack entry. (Always the last entry.) */ _PyErr_StackItem exc_state; - /* The bottom-most frame on the stack. */ - _PyCFrame root_cframe; }; -/* WASI has limited call stack. Python's recursion limit depends on code - layout, optimization, and WASI runtime. Wasmtime can handle about 700 - recursions, sometimes less. 500 is a more conservative limit. */ -#ifndef C_RECURSION_LIMIT -# ifdef __wasi__ -# define C_RECURSION_LIMIT 500 -# else - // This value is duplicated in Lib/test/support/__init__.py -# define C_RECURSION_LIMIT 1500 -# endif +#ifdef Py_DEBUG + // A debug build is likely built with low optimization level which implies + // higher stack memory usage than a release build: use a lower limit. +# define Py_C_RECURSION_LIMIT 500 +#elif defined(__wasi__) + // WASI has limited call stack. Python's recursion limit depends on code + // layout, optimization, and WASI runtime. Wasmtime can handle about 700 + // recursions, sometimes less. 500 is a more conservative limit. +# define Py_C_RECURSION_LIMIT 500 +#elif defined(__s390x__) +# define Py_C_RECURSION_LIMIT 1200 +#else + // This value is duplicated in Lib/test/support/__init__.py +# define Py_C_RECURSION_LIMIT 8000 #endif + /* other API */ /* Similar to PyThreadState_Get(), but don't issue a fatal error * if it is NULL. */ -PyAPI_FUNC(PyThreadState *) _PyThreadState_UncheckedGet(void); +PyAPI_FUNC(PyThreadState *) PyThreadState_GetUnchecked(void); + +// Alias kept for backward compatibility +#define _PyThreadState_UncheckedGet PyThreadState_GetUnchecked + // Disable tracing and profiling. PyAPI_FUNC(void) PyThreadState_EnterTracing(PyThreadState *tstate); @@ -248,14 +256,10 @@ PyAPI_FUNC(void) PyThreadState_LeaveTracing(PyThreadState *tstate); The function returns 1 if _PyGILState_check_enabled is non-zero. */ PyAPI_FUNC(int) PyGILState_Check(void); -/* Get the single PyInterpreterState used by this process' GILState - implementation. - - This function doesn't check for error. Return NULL before _PyGILState_Init() - is called and after _PyGILState_Fini() is called. - - See also PyInterpreterState_Get() and _PyInterpreterState_GET(). */ -PyAPI_FUNC(PyInterpreterState *) _PyGILState_GetInterpreterStateUnsafe(void); +/* The implementation of sys._current_frames() Returns a dict mapping + thread id to that thread's current frame. +*/ +PyAPI_FUNC(PyObject*) _PyThread_CurrentFrames(void); /* Routines for advanced debuggers, requested by David Beazley. Don't use unless you know what you are doing! */ @@ -275,79 +279,3 @@ PyAPI_FUNC(_PyFrameEvalFunction) _PyInterpreterState_GetEvalFrameFunc( PyAPI_FUNC(void) _PyInterpreterState_SetEvalFrameFunc( PyInterpreterState *interp, _PyFrameEvalFunction eval_frame); - - -/* cross-interpreter data */ - -// _PyCrossInterpreterData is similar to Py_buffer as an effectively -// opaque struct that holds data outside the object machinery. This -// is necessary to pass safely between interpreters in the same process. -typedef struct _xid _PyCrossInterpreterData; - -typedef PyObject *(*xid_newobjectfunc)(_PyCrossInterpreterData *); -typedef void (*xid_freefunc)(void *); - -struct _xid { - // data is the cross-interpreter-safe derivation of a Python object - // (see _PyObject_GetCrossInterpreterData). It will be NULL if the - // new_object func (below) encodes the data. - void *data; - // obj is the Python object from which the data was derived. This - // is non-NULL only if the data remains bound to the object in some - // way, such that the object must be "released" (via a decref) when - // the data is released. In that case the code that sets the field, - // likely a registered "crossinterpdatafunc", is responsible for - // ensuring it owns the reference (i.e. incref). - PyObject *obj; - // interp is the ID of the owning interpreter of the original - // object. It corresponds to the active interpreter when - // _PyObject_GetCrossInterpreterData() was called. This should only - // be set by the cross-interpreter machinery. - // - // We use the ID rather than the PyInterpreterState to avoid issues - // with deleted interpreters. Note that IDs are never re-used, so - // each one will always correspond to a specific interpreter - // (whether still alive or not). - int64_t interp; - // new_object is a function that returns a new object in the current - // interpreter given the data. The resulting object (a new - // reference) will be equivalent to the original object. This field - // is required. - xid_newobjectfunc new_object; - // free is called when the data is released. If it is NULL then - // nothing will be done to free the data. For some types this is - // okay (e.g. bytes) and for those types this field should be set - // to NULL. However, for most the data was allocated just for - // cross-interpreter use, so it must be freed when - // _PyCrossInterpreterData_Release is called or the memory will - // leak. In that case, at the very least this field should be set - // to PyMem_RawFree (the default if not explicitly set to NULL). - // The call will happen with the original interpreter activated. - xid_freefunc free; -}; - -PyAPI_FUNC(void) _PyCrossInterpreterData_Init( - _PyCrossInterpreterData *data, - PyInterpreterState *interp, void *shared, PyObject *obj, - xid_newobjectfunc new_object); -PyAPI_FUNC(int) _PyCrossInterpreterData_InitWithSize( - _PyCrossInterpreterData *, - PyInterpreterState *interp, const size_t, PyObject *, - xid_newobjectfunc); -PyAPI_FUNC(void) _PyCrossInterpreterData_Clear( - PyInterpreterState *, _PyCrossInterpreterData *); - -PyAPI_FUNC(int) _PyObject_GetCrossInterpreterData(PyObject *, _PyCrossInterpreterData *); -PyAPI_FUNC(PyObject *) _PyCrossInterpreterData_NewObject(_PyCrossInterpreterData *); -PyAPI_FUNC(int) _PyCrossInterpreterData_Release(_PyCrossInterpreterData *); - -PyAPI_FUNC(int) _PyObject_CheckCrossInterpreterData(PyObject *); - -/* cross-interpreter data registry */ - -typedef int (*crossinterpdatafunc)(PyThreadState *tstate, PyObject *, - _PyCrossInterpreterData *); - -PyAPI_FUNC(int) _PyCrossInterpreterData_RegisterClass(PyTypeObject *, crossinterpdatafunc); -PyAPI_FUNC(int) _PyCrossInterpreterData_UnregisterClass(PyTypeObject *); -PyAPI_FUNC(crossinterpdatafunc) _PyCrossInterpreterData_Lookup(PyObject *); diff --git a/Include/cpython/pystats.h b/Include/cpython/pystats.h new file mode 100644 index 00000000000000..ba67eefef3e37a --- /dev/null +++ b/Include/cpython/pystats.h @@ -0,0 +1,143 @@ +// Statistics on Python performance. +// +// API: +// +// - _Py_INCREF_STAT_INC() and _Py_DECREF_STAT_INC() used by Py_INCREF() +// and Py_DECREF(). +// - _Py_stats variable +// +// Functions of the sys module: +// +// - sys._stats_on() +// - sys._stats_off() +// - sys._stats_clear() +// - sys._stats_dump() +// +// Python must be built with ./configure --enable-pystats to define the +// Py_STATS macro. +// +// Define _PY_INTERPRETER macro to increment interpreter_increfs and +// interpreter_decrefs. Otherwise, increment increfs and decrefs. + +#ifndef Py_CPYTHON_PYSTATS_H +# error "this header file must not be included directly" +#endif + +#define SPECIALIZATION_FAILURE_KINDS 36 + +/* Stats for determining who is calling PyEval_EvalFrame */ +#define EVAL_CALL_TOTAL 0 +#define EVAL_CALL_VECTOR 1 +#define EVAL_CALL_GENERATOR 2 +#define EVAL_CALL_LEGACY 3 +#define EVAL_CALL_FUNCTION_VECTORCALL 4 +#define EVAL_CALL_BUILD_CLASS 5 +#define EVAL_CALL_SLOT 6 +#define EVAL_CALL_FUNCTION_EX 7 +#define EVAL_CALL_API 8 +#define EVAL_CALL_METHOD 9 + +#define EVAL_CALL_KINDS 10 + +typedef struct _specialization_stats { + uint64_t success; + uint64_t failure; + uint64_t hit; + uint64_t deferred; + uint64_t miss; + uint64_t deopt; + uint64_t failure_kinds[SPECIALIZATION_FAILURE_KINDS]; +} SpecializationStats; + +typedef struct _opcode_stats { + SpecializationStats specialization; + uint64_t execution_count; + uint64_t pair_count[256]; +} OpcodeStats; + +typedef struct _call_stats { + uint64_t inlined_py_calls; + uint64_t pyeval_calls; + uint64_t frames_pushed; + uint64_t frame_objects_created; + uint64_t eval_calls[EVAL_CALL_KINDS]; +} CallStats; + +typedef struct _object_stats { + uint64_t increfs; + uint64_t decrefs; + uint64_t interpreter_increfs; + uint64_t interpreter_decrefs; + uint64_t allocations; + uint64_t allocations512; + uint64_t allocations4k; + uint64_t allocations_big; + uint64_t frees; + uint64_t to_freelist; + uint64_t from_freelist; + uint64_t new_values; + uint64_t dict_materialized_on_request; + uint64_t dict_materialized_new_key; + uint64_t dict_materialized_too_big; + uint64_t dict_materialized_str_subclass; + uint64_t dict_dematerialized; + uint64_t type_cache_hits; + uint64_t type_cache_misses; + uint64_t type_cache_dunder_hits; + uint64_t type_cache_dunder_misses; + uint64_t type_cache_collisions; + /* Temporary value used during GC */ + uint64_t object_visits; +} ObjectStats; + +typedef struct _gc_stats { + uint64_t collections; + uint64_t object_visits; + uint64_t objects_collected; +} GCStats; + +typedef struct _uop_stats { + uint64_t execution_count; + uint64_t miss; +} UOpStats; + +#define _Py_UOP_HIST_SIZE 32 + +typedef struct _optimization_stats { + uint64_t attempts; + uint64_t traces_created; + uint64_t traces_executed; + uint64_t uops_executed; + uint64_t trace_stack_overflow; + uint64_t trace_stack_underflow; + uint64_t trace_too_long; + uint64_t trace_too_short; + uint64_t inner_loop; + uint64_t recursive_call; + uint64_t low_confidence; + UOpStats opcode[512]; + uint64_t unsupported_opcode[256]; + uint64_t trace_length_hist[_Py_UOP_HIST_SIZE]; + uint64_t trace_run_length_hist[_Py_UOP_HIST_SIZE]; + uint64_t optimized_trace_length_hist[_Py_UOP_HIST_SIZE]; +} OptimizationStats; + +typedef struct _stats { + OpcodeStats opcode_stats[256]; + CallStats call_stats; + ObjectStats object_stats; + OptimizationStats optimization_stats; + GCStats *gc_stats; +} PyStats; + + +// Export for shared extensions like 'math' +PyAPI_DATA(PyStats*) _Py_stats; + +#ifdef _PY_INTERPRETER +# define _Py_INCREF_STAT_INC() do { if (_Py_stats) _Py_stats->object_stats.interpreter_increfs++; } while (0) +# define _Py_DECREF_STAT_INC() do { if (_Py_stats) _Py_stats->object_stats.interpreter_decrefs++; } while (0) +#else +# define _Py_INCREF_STAT_INC() do { if (_Py_stats) _Py_stats->object_stats.increfs++; } while (0) +# define _Py_DECREF_STAT_INC() do { if (_Py_stats) _Py_stats->object_stats.decrefs++; } while (0) +#endif diff --git a/Include/cpython/pythonrun.h b/Include/cpython/pythonrun.h index 3b2537e01b83b1..edc40952254029 100644 --- a/Include/cpython/pythonrun.h +++ b/Include/cpython/pythonrun.h @@ -3,21 +3,11 @@ #endif PyAPI_FUNC(int) PyRun_SimpleStringFlags(const char *, PyCompilerFlags *); -PyAPI_FUNC(int) _PyRun_SimpleFileObject( - FILE *fp, - PyObject *filename, - int closeit, - PyCompilerFlags *flags); PyAPI_FUNC(int) PyRun_AnyFileExFlags( FILE *fp, const char *filename, /* decoded from the filesystem encoding */ int closeit, PyCompilerFlags *flags); -PyAPI_FUNC(int) _PyRun_AnyFileObject( - FILE *fp, - PyObject *filename, - int closeit, - PyCompilerFlags *flags); PyAPI_FUNC(int) PyRun_SimpleFileExFlags( FILE *fp, const char *filename, /* decoded from the filesystem encoding */ @@ -35,10 +25,6 @@ PyAPI_FUNC(int) PyRun_InteractiveLoopFlags( FILE *fp, const char *filename, /* decoded from the filesystem encoding */ PyCompilerFlags *flags); -PyAPI_FUNC(int) _PyRun_InteractiveLoopObject( - FILE *fp, - PyObject *filename, - PyCompilerFlags *flags); PyAPI_FUNC(PyObject *) PyRun_StringFlags(const char *, int, PyObject *, @@ -69,15 +55,6 @@ PyAPI_FUNC(PyObject *) Py_CompileStringObject( #define Py_CompileString(str, p, s) Py_CompileStringExFlags((str), (p), (s), NULL, -1) #define Py_CompileStringFlags(str, p, s, f) Py_CompileStringExFlags((str), (p), (s), (f), -1) - -PyAPI_FUNC(const char *) _Py_SourceAsString( - PyObject *cmd, - const char *funcname, - const char *what, - PyCompilerFlags *cf, - PyObject **cmd_copy); - - /* A function flavor is also exported by libpython. It is required when libpython is accessed directly rather than using header files which defines macros below. On Windows, for example, PyAPI_FUNC() uses dllexport to @@ -114,7 +91,6 @@ PyAPI_FUNC(PyObject *) PyRun_FileFlags(FILE *fp, const char *p, int s, PyObject #define PyRun_FileFlags(fp, p, s, g, l, flags) \ PyRun_FileExFlags((fp), (p), (s), (g), (l), 0, (flags)) - /* Stuff with no proper home (yet) */ PyAPI_FUNC(char *) PyOS_Readline(FILE *, FILE *, const char *); PyAPI_DATA(char) *(*PyOS_ReadlineFunctionPointer)(FILE *, FILE *, const char *); diff --git a/Include/cpython/pythread.h b/Include/cpython/pythread.h index ce4ec8f65b15ea..03f710a9f7ef2e 100644 --- a/Include/cpython/pythread.h +++ b/Include/cpython/pythread.h @@ -2,14 +2,15 @@ # error "this header file must not be included directly" #endif -#define PYTHREAD_INVALID_THREAD_ID ((unsigned long)-1) +// PY_TIMEOUT_MAX is the highest usable value (in microseconds) of PY_TIMEOUT_T +// type, and depends on the system threading API. +// +// NOTE: this isn't the same value as `_thread.TIMEOUT_MAX`. The _thread module +// exposes a higher-level API, with timeouts expressed in seconds and +// floating-point numbers allowed. +PyAPI_DATA(const long long) PY_TIMEOUT_MAX; -#ifdef HAVE_FORK -/* Private function to reinitialize a lock at fork in the child process. - Reset the lock to the unlocked state. - Return 0 on success, return -1 on error. */ -PyAPI_FUNC(int) _PyThread_at_fork_reinit(PyThread_type_lock *lock); -#endif /* HAVE_FORK */ +#define PYTHREAD_INVALID_THREAD_ID ((unsigned long)-1) #ifdef HAVE_PTHREAD_H /* Darwin needs pthread.h to know type name the pthread_key_t. */ diff --git a/Include/cpython/sysmodule.h b/Include/cpython/sysmodule.h index 19d9dddc344a4f..a3ac07f538a94f 100644 --- a/Include/cpython/sysmodule.h +++ b/Include/cpython/sysmodule.h @@ -2,15 +2,21 @@ # error "this header file must not be included directly" #endif -PyAPI_FUNC(PyObject *) _PySys_GetAttr(PyThreadState *tstate, - PyObject *name); - -PyAPI_FUNC(size_t) _PySys_GetSizeOf(PyObject *); - typedef int(*Py_AuditHookFunction)(const char *, PyObject *, void *); -PyAPI_FUNC(int) PySys_Audit( - const char *event, - const char *argFormat, - ...); PyAPI_FUNC(int) PySys_AddAuditHook(Py_AuditHookFunction, void*); + +typedef struct { + FILE* perf_map; + PyThread_type_lock map_lock; +} PerfMapState; + +PyAPI_FUNC(int) PyUnstable_PerfMapState_Init(void); +PyAPI_FUNC(int) PyUnstable_WritePerfMapEntry( + const void *code_addr, + unsigned int code_size, + const char *entry_name); +PyAPI_FUNC(void) PyUnstable_PerfMapState_Fini(void); +PyAPI_FUNC(int) PyUnstable_CopyPerfMapFile(const char* parent_filename); +PyAPI_FUNC(int) PyUnstable_PerfTrampoline_CompileCode(PyCodeObject *); +PyAPI_FUNC(int) PyUnstable_PerfTrampoline_SetPersistAfterFork(int enable); diff --git a/Include/cpython/traceback.h b/Include/cpython/traceback.h index a4e087b2b4eced..81c51944f136f2 100644 --- a/Include/cpython/traceback.h +++ b/Include/cpython/traceback.h @@ -11,6 +11,3 @@ struct _traceback { int tb_lasti; int tb_lineno; }; - -PyAPI_FUNC(int) _Py_DisplaySourceLine(PyObject *, PyObject *, int, int, int *, PyObject **); -PyAPI_FUNC(void) _PyTraceback_Add(const char *, const char *, int); diff --git a/Include/cpython/unicodeobject.h b/Include/cpython/unicodeobject.h index 859ab7178e920a..d9b54bce83202d 100644 --- a/Include/cpython/unicodeobject.h +++ b/Include/cpython/unicodeobject.h @@ -9,6 +9,7 @@ Py_DEPRECATED(3.13) typedef wchar_t PY_UNICODE_TYPE; Py_DEPRECATED(3.13) typedef wchar_t Py_UNICODE; + /* --- Internal Unicode Operations ---------------------------------------- */ // Static inline functions to work with surrogates @@ -43,6 +44,7 @@ static inline Py_UCS4 Py_UNICODE_LOW_SURROGATE(Py_UCS4 ch) { return (0xDC00 + (ch & 0x3FF)); } + /* --- Unicode Type ------------------------------------------------------- */ /* ASCII-only strings created through PyUnicode_New use the PyASCIIObject @@ -375,6 +377,7 @@ static inline Py_UCS4 PyUnicode_MAX_CHAR_VALUE(PyObject *op) #define PyUnicode_MAX_CHAR_VALUE(op) \ PyUnicode_MAX_CHAR_VALUE(_PyObject_CAST(op)) + /* === Public API ========================================================= */ /* With PEP 393, this is the recommended way to allocate a new unicode object. @@ -440,6 +443,123 @@ PyAPI_FUNC(PyObject*) PyUnicode_FromKindAndData( const void *buffer, Py_ssize_t size); + +/* --- _PyUnicodeWriter API ----------------------------------------------- */ + +typedef struct { + PyObject *buffer; + void *data; + int kind; + Py_UCS4 maxchar; + Py_ssize_t size; + Py_ssize_t pos; + + /* minimum number of allocated characters (default: 0) */ + Py_ssize_t min_length; + + /* minimum character (default: 127, ASCII) */ + Py_UCS4 min_char; + + /* If non-zero, overallocate the buffer (default: 0). */ + unsigned char overallocate; + + /* If readonly is 1, buffer is a shared string (cannot be modified) + and size is set to 0. */ + unsigned char readonly; +} _PyUnicodeWriter ; + +// Initialize a Unicode writer. +// +// By default, the minimum buffer size is 0 character and overallocation is +// disabled. Set min_length, min_char and overallocate attributes to control +// the allocation of the buffer. +PyAPI_FUNC(void) +_PyUnicodeWriter_Init(_PyUnicodeWriter *writer); + +/* Prepare the buffer to write 'length' characters + with the specified maximum character. + + Return 0 on success, raise an exception and return -1 on error. */ +#define _PyUnicodeWriter_Prepare(WRITER, LENGTH, MAXCHAR) \ + (((MAXCHAR) <= (WRITER)->maxchar \ + && (LENGTH) <= (WRITER)->size - (WRITER)->pos) \ + ? 0 \ + : (((LENGTH) == 0) \ + ? 0 \ + : _PyUnicodeWriter_PrepareInternal((WRITER), (LENGTH), (MAXCHAR)))) + +/* Don't call this function directly, use the _PyUnicodeWriter_Prepare() macro + instead. */ +PyAPI_FUNC(int) +_PyUnicodeWriter_PrepareInternal(_PyUnicodeWriter *writer, + Py_ssize_t length, Py_UCS4 maxchar); + +/* Prepare the buffer to have at least the kind KIND. + For example, kind=PyUnicode_2BYTE_KIND ensures that the writer will + support characters in range U+000-U+FFFF. + + Return 0 on success, raise an exception and return -1 on error. */ +#define _PyUnicodeWriter_PrepareKind(WRITER, KIND) \ + ((KIND) <= (WRITER)->kind \ + ? 0 \ + : _PyUnicodeWriter_PrepareKindInternal((WRITER), (KIND))) + +/* Don't call this function directly, use the _PyUnicodeWriter_PrepareKind() + macro instead. */ +PyAPI_FUNC(int) +_PyUnicodeWriter_PrepareKindInternal(_PyUnicodeWriter *writer, + int kind); + +/* Append a Unicode character. + Return 0 on success, raise an exception and return -1 on error. */ +PyAPI_FUNC(int) +_PyUnicodeWriter_WriteChar(_PyUnicodeWriter *writer, + Py_UCS4 ch + ); + +/* Append a Unicode string. + Return 0 on success, raise an exception and return -1 on error. */ +PyAPI_FUNC(int) +_PyUnicodeWriter_WriteStr(_PyUnicodeWriter *writer, + PyObject *str /* Unicode string */ + ); + +/* Append a substring of a Unicode string. + Return 0 on success, raise an exception and return -1 on error. */ +PyAPI_FUNC(int) +_PyUnicodeWriter_WriteSubstring(_PyUnicodeWriter *writer, + PyObject *str, /* Unicode string */ + Py_ssize_t start, + Py_ssize_t end + ); + +/* Append an ASCII-encoded byte string. + Return 0 on success, raise an exception and return -1 on error. */ +PyAPI_FUNC(int) +_PyUnicodeWriter_WriteASCIIString(_PyUnicodeWriter *writer, + const char *str, /* ASCII-encoded byte string */ + Py_ssize_t len /* number of bytes, or -1 if unknown */ + ); + +/* Append a latin1-encoded byte string. + Return 0 on success, raise an exception and return -1 on error. */ +PyAPI_FUNC(int) +_PyUnicodeWriter_WriteLatin1String(_PyUnicodeWriter *writer, + const char *str, /* latin1-encoded byte string */ + Py_ssize_t len /* length in bytes */ + ); + +/* Get the value of the writer as a Unicode string. Clear the + buffer of the writer. Raise an exception and return NULL + on error. */ +PyAPI_FUNC(PyObject *) +_PyUnicodeWriter_Finish(_PyUnicodeWriter *writer); + +/* Deallocate memory of a writer (clear its internal buffer). */ +PyAPI_FUNC(void) +_PyUnicodeWriter_Dealloc(_PyUnicodeWriter *writer); + + /* --- Manage the default encoding ---------------------------------------- */ /* Returns a pointer to the default encoding (UTF-8) of the @@ -448,12 +568,19 @@ PyAPI_FUNC(PyObject*) PyUnicode_FromKindAndData( Like PyUnicode_AsUTF8AndSize(), this also caches the UTF-8 representation in the unicodeobject. + _PyUnicode_AsString is a #define for PyUnicode_AsUTF8 to + support the previous internal function with the same behaviour. + Use of this API is DEPRECATED since no size information can be extracted from the returned data. */ PyAPI_FUNC(const char *) PyUnicode_AsUTF8(PyObject *unicode); +// Alias kept for backward compatibility +#define _PyUnicode_AsString PyUnicode_AsUTF8 + + /* === Characters Type APIs =============================================== */ /* These should not be used directly. Use the Py_UNICODE_IS* and @@ -567,3 +694,10 @@ static inline int Py_UNICODE_ISALNUM(Py_UCS4 ch) { || Py_UNICODE_ISDIGIT(ch) || Py_UNICODE_ISNUMERIC(ch)); } + + +/* === Misc functions ===================================================== */ + +// Return an interned Unicode object for an Identifier; may fail if there is no +// memory. +PyAPI_FUNC(PyObject*) _PyUnicode_FromId(_Py_Identifier*); diff --git a/Include/errcode.h b/Include/errcode.h index 8d44e9ae559193..dac5cf068c99d6 100644 --- a/Include/errcode.h +++ b/Include/errcode.h @@ -19,24 +19,25 @@ extern "C" { #endif -#define E_OK 10 /* No error */ -#define E_EOF 11 /* End Of File */ -#define E_INTR 12 /* Interrupted */ -#define E_TOKEN 13 /* Bad token */ -#define E_SYNTAX 14 /* Syntax error */ -#define E_NOMEM 15 /* Ran out of memory */ -#define E_DONE 16 /* Parsing complete */ -#define E_ERROR 17 /* Execution error */ -#define E_TABSPACE 18 /* Inconsistent mixing of tabs and spaces */ -#define E_OVERFLOW 19 /* Node had too many children */ -#define E_TOODEEP 20 /* Too many indentation levels */ -#define E_DEDENT 21 /* No matching outer block for dedent */ -#define E_DECODE 22 /* Error in decoding into Unicode */ -#define E_EOFS 23 /* EOF in triple-quoted string */ -#define E_EOLS 24 /* EOL in single-quoted string */ -#define E_LINECONT 25 /* Unexpected characters after a line continuation */ -#define E_BADSINGLE 27 /* Ill-formed single statement input */ -#define E_INTERACT_STOP 28 /* Interactive mode stopped tokenization */ +#define E_OK 10 /* No error */ +#define E_EOF 11 /* End Of File */ +#define E_INTR 12 /* Interrupted */ +#define E_TOKEN 13 /* Bad token */ +#define E_SYNTAX 14 /* Syntax error */ +#define E_NOMEM 15 /* Ran out of memory */ +#define E_DONE 16 /* Parsing complete */ +#define E_ERROR 17 /* Execution error */ +#define E_TABSPACE 18 /* Inconsistent mixing of tabs and spaces */ +#define E_OVERFLOW 19 /* Node had too many children */ +#define E_TOODEEP 20 /* Too many indentation levels */ +#define E_DEDENT 21 /* No matching outer block for dedent */ +#define E_DECODE 22 /* Error in decoding into Unicode */ +#define E_EOFS 23 /* EOF in triple-quoted string */ +#define E_EOLS 24 /* EOL in single-quoted string */ +#define E_LINECONT 25 /* Unexpected characters after a line continuation */ +#define E_BADSINGLE 27 /* Ill-formed single statement input */ +#define E_INTERACT_STOP 28 /* Interactive mode stopped tokenization */ +#define E_COLUMNOVERFLOW 29 /* Column offset overflow */ #ifdef __cplusplus } diff --git a/Include/exports.h b/Include/exports.h index 59373c39ff757c..ce601216f17156 100644 --- a/Include/exports.h +++ b/Include/exports.h @@ -1,6 +1,29 @@ #ifndef Py_EXPORTS_H #define Py_EXPORTS_H +/* Declarations for symbol visibility. + + PyAPI_FUNC(type): Declares a public Python API function and return type + PyAPI_DATA(type): Declares public Python data and its type + PyMODINIT_FUNC: A Python module init function. If these functions are + inside the Python core, they are private to the core. + If in an extension module, it may be declared with + external linkage depending on the platform. + + As a number of platforms support/require "__declspec(dllimport/dllexport)", + we support a HAVE_DECLSPEC_DLL macro to save duplication. +*/ + +/* + All windows ports, except cygwin, are handled in PC/pyconfig.h. + + Cygwin is the only other autoconf platform requiring special + linkage handling and it uses __declspec(). +*/ +#if defined(__CYGWIN__) +# define HAVE_DECLSPEC_DLL +#endif + #if defined(_WIN32) || defined(__CYGWIN__) #if defined(Py_ENABLE_SHARED) #define Py_IMPORTED_SYMBOL __declspec(dllimport) @@ -33,4 +56,53 @@ #endif #endif +/* only get special linkage if built as shared or platform is Cygwin */ +#if defined(Py_ENABLE_SHARED) || defined(__CYGWIN__) +# if defined(HAVE_DECLSPEC_DLL) +# if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) +# define PyAPI_FUNC(RTYPE) Py_EXPORTED_SYMBOL RTYPE +# define PyAPI_DATA(RTYPE) extern Py_EXPORTED_SYMBOL RTYPE + /* module init functions inside the core need no external linkage */ + /* except for Cygwin to handle embedding */ +# if defined(__CYGWIN__) +# define PyMODINIT_FUNC Py_EXPORTED_SYMBOL PyObject* +# else /* __CYGWIN__ */ +# define PyMODINIT_FUNC PyObject* +# endif /* __CYGWIN__ */ +# else /* Py_BUILD_CORE */ + /* Building an extension module, or an embedded situation */ + /* public Python functions and data are imported */ + /* Under Cygwin, auto-import functions to prevent compilation */ + /* failures similar to those described at the bottom of 4.1: */ + /* http://docs.python.org/extending/windows.html#a-cookbook-approach */ +# if !defined(__CYGWIN__) +# define PyAPI_FUNC(RTYPE) Py_IMPORTED_SYMBOL RTYPE +# endif /* !__CYGWIN__ */ +# define PyAPI_DATA(RTYPE) extern Py_IMPORTED_SYMBOL RTYPE + /* module init functions outside the core must be exported */ +# if defined(__cplusplus) +# define PyMODINIT_FUNC extern "C" Py_EXPORTED_SYMBOL PyObject* +# else /* __cplusplus */ +# define PyMODINIT_FUNC Py_EXPORTED_SYMBOL PyObject* +# endif /* __cplusplus */ +# endif /* Py_BUILD_CORE */ +# endif /* HAVE_DECLSPEC_DLL */ +#endif /* Py_ENABLE_SHARED */ + +/* If no external linkage macros defined by now, create defaults */ +#ifndef PyAPI_FUNC +# define PyAPI_FUNC(RTYPE) Py_EXPORTED_SYMBOL RTYPE +#endif +#ifndef PyAPI_DATA +# define PyAPI_DATA(RTYPE) extern Py_EXPORTED_SYMBOL RTYPE +#endif +#ifndef PyMODINIT_FUNC +# if defined(__cplusplus) +# define PyMODINIT_FUNC extern "C" Py_EXPORTED_SYMBOL PyObject* +# else /* __cplusplus */ +# define PyMODINIT_FUNC Py_EXPORTED_SYMBOL PyObject* +# endif /* __cplusplus */ +#endif + + #endif /* Py_EXPORTS_H */ diff --git a/Include/fileutils.h b/Include/fileutils.h index ba5acc84fcb185..1509198e45f0ca 100644 --- a/Include/fileutils.h +++ b/Include/fileutils.h @@ -1,5 +1,41 @@ #ifndef Py_FILEUTILS_H #define Py_FILEUTILS_H + +/******************************* + * stat() and fstat() fiddling * + *******************************/ + +#ifdef HAVE_SYS_STAT_H +# include // S_ISREG() +#elif defined(HAVE_STAT_H) +# include // S_ISREG() +#endif + +#ifndef S_IFMT + // VisualAge C/C++ Failed to Define MountType Field in sys/stat.h. +# define S_IFMT 0170000 +#endif +#ifndef S_IFLNK + // Windows doesn't define S_IFLNK, but posixmodule.c maps + // IO_REPARSE_TAG_SYMLINK to S_IFLNK. +# define S_IFLNK 0120000 +#endif +#ifndef S_ISREG +# define S_ISREG(x) (((x) & S_IFMT) == S_IFREG) +#endif +#ifndef S_ISDIR +# define S_ISDIR(x) (((x) & S_IFMT) == S_IFDIR) +#endif +#ifndef S_ISCHR +# define S_ISCHR(x) (((x) & S_IFMT) == S_IFCHR) +#endif +#ifndef S_ISLNK +# define S_ISLNK(x) (((x) & S_IFMT) == S_IFLNK) +#endif + + +// Move this down here since some C++ #include's don't like to be included +// inside an extern "C". #ifdef __cplusplus extern "C" { #endif diff --git a/Include/internal/mimalloc/mimalloc.h b/Include/internal/mimalloc/mimalloc.h new file mode 100644 index 00000000000000..821129e7690b1b --- /dev/null +++ b/Include/internal/mimalloc/mimalloc.h @@ -0,0 +1,565 @@ +/* ---------------------------------------------------------------------------- +Copyright (c) 2018-2023, Microsoft Research, Daan Leijen +This is free software; you can redistribute it and/or modify it under the +terms of the MIT license. A copy of the license can be found in the file +"LICENSE" at the root of this distribution. +-----------------------------------------------------------------------------*/ +#pragma once +#ifndef MIMALLOC_H +#define MIMALLOC_H + +#define MI_MALLOC_VERSION 212 // major + 2 digits minor + +// ------------------------------------------------------ +// Compiler specific attributes +// ------------------------------------------------------ + +#ifdef __cplusplus + #if (__cplusplus >= 201103L) || (_MSC_VER > 1900) // C++11 + #define mi_attr_noexcept noexcept + #else + #define mi_attr_noexcept throw() + #endif +#else + #define mi_attr_noexcept +#endif + +#if defined(__cplusplus) && (__cplusplus >= 201703) + #define mi_decl_nodiscard [[nodiscard]] +#elif (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__) // includes clang, icc, and clang-cl + #define mi_decl_nodiscard __attribute__((warn_unused_result)) +#elif defined(_HAS_NODISCARD) + #define mi_decl_nodiscard _NODISCARD +#elif (_MSC_VER >= 1700) + #define mi_decl_nodiscard _Check_return_ +#else + #define mi_decl_nodiscard +#endif + +#if defined(_MSC_VER) || defined(__MINGW32__) + #if !defined(MI_SHARED_LIB) + #define mi_decl_export + #elif defined(MI_SHARED_LIB_EXPORT) + #define mi_decl_export __declspec(dllexport) + #else + #define mi_decl_export __declspec(dllimport) + #endif + #if defined(__MINGW32__) + #define mi_decl_restrict + #define mi_attr_malloc __attribute__((malloc)) + #else + #if (_MSC_VER >= 1900) && !defined(__EDG__) + #define mi_decl_restrict __declspec(allocator) __declspec(restrict) + #else + #define mi_decl_restrict __declspec(restrict) + #endif + #define mi_attr_malloc + #endif + #define mi_cdecl __cdecl + #define mi_attr_alloc_size(s) + #define mi_attr_alloc_size2(s1,s2) + #define mi_attr_alloc_align(p) +#elif defined(__GNUC__) // includes clang and icc + #if defined(MI_SHARED_LIB) && defined(MI_SHARED_LIB_EXPORT) + #define mi_decl_export __attribute__((visibility("default"))) + #else + #define mi_decl_export + #endif + #define mi_cdecl // leads to warnings... __attribute__((cdecl)) + #define mi_decl_restrict + #define mi_attr_malloc __attribute__((malloc)) + #if (defined(__clang_major__) && (__clang_major__ < 4)) || (__GNUC__ < 5) + #define mi_attr_alloc_size(s) + #define mi_attr_alloc_size2(s1,s2) + #define mi_attr_alloc_align(p) + #elif defined(__INTEL_COMPILER) + #define mi_attr_alloc_size(s) __attribute__((alloc_size(s))) + #define mi_attr_alloc_size2(s1,s2) __attribute__((alloc_size(s1,s2))) + #define mi_attr_alloc_align(p) + #else + #define mi_attr_alloc_size(s) __attribute__((alloc_size(s))) + #define mi_attr_alloc_size2(s1,s2) __attribute__((alloc_size(s1,s2))) + #define mi_attr_alloc_align(p) __attribute__((alloc_align(p))) + #endif +#else + #define mi_cdecl + #define mi_decl_export + #define mi_decl_restrict + #define mi_attr_malloc + #define mi_attr_alloc_size(s) + #define mi_attr_alloc_size2(s1,s2) + #define mi_attr_alloc_align(p) +#endif + +// ------------------------------------------------------ +// Includes +// ------------------------------------------------------ + +#include // size_t +#include // bool +#include // INTPTR_MAX + +#ifdef __cplusplus +extern "C" { +#endif + +// ------------------------------------------------------ +// Standard malloc interface +// ------------------------------------------------------ + +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_malloc(size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1); +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_calloc(size_t count, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2(1,2); +mi_decl_nodiscard mi_decl_export void* mi_realloc(void* p, size_t newsize) mi_attr_noexcept mi_attr_alloc_size(2); +mi_decl_export void* mi_expand(void* p, size_t newsize) mi_attr_noexcept mi_attr_alloc_size(2); + +mi_decl_export void mi_free(void* p) mi_attr_noexcept; +mi_decl_nodiscard mi_decl_export mi_decl_restrict char* mi_strdup(const char* s) mi_attr_noexcept mi_attr_malloc; +mi_decl_nodiscard mi_decl_export mi_decl_restrict char* mi_strndup(const char* s, size_t n) mi_attr_noexcept mi_attr_malloc; +mi_decl_nodiscard mi_decl_export mi_decl_restrict char* mi_realpath(const char* fname, char* resolved_name) mi_attr_noexcept mi_attr_malloc; + +// ------------------------------------------------------ +// Extended functionality +// ------------------------------------------------------ +#define MI_SMALL_WSIZE_MAX (128) +#define MI_SMALL_SIZE_MAX (MI_SMALL_WSIZE_MAX*sizeof(void*)) + +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_malloc_small(size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1); +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_zalloc_small(size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1); +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_zalloc(size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1); + +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_mallocn(size_t count, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2(1,2); +mi_decl_nodiscard mi_decl_export void* mi_reallocn(void* p, size_t count, size_t size) mi_attr_noexcept mi_attr_alloc_size2(2,3); +mi_decl_nodiscard mi_decl_export void* mi_reallocf(void* p, size_t newsize) mi_attr_noexcept mi_attr_alloc_size(2); + +mi_decl_nodiscard mi_decl_export size_t mi_usable_size(const void* p) mi_attr_noexcept; +mi_decl_nodiscard mi_decl_export size_t mi_good_size(size_t size) mi_attr_noexcept; + + +// ------------------------------------------------------ +// Internals +// ------------------------------------------------------ + +typedef void (mi_cdecl mi_deferred_free_fun)(bool force, unsigned long long heartbeat, void* arg); +mi_decl_export void mi_register_deferred_free(mi_deferred_free_fun* deferred_free, void* arg) mi_attr_noexcept; + +typedef void (mi_cdecl mi_output_fun)(const char* msg, void* arg); +mi_decl_export void mi_register_output(mi_output_fun* out, void* arg) mi_attr_noexcept; + +typedef void (mi_cdecl mi_error_fun)(int err, void* arg); +mi_decl_export void mi_register_error(mi_error_fun* fun, void* arg); + +mi_decl_export void mi_collect(bool force) mi_attr_noexcept; +mi_decl_export int mi_version(void) mi_attr_noexcept; +mi_decl_export void mi_stats_reset(void) mi_attr_noexcept; +mi_decl_export void mi_stats_merge(void) mi_attr_noexcept; +mi_decl_export void mi_stats_print(void* out) mi_attr_noexcept; // backward compatibility: `out` is ignored and should be NULL +mi_decl_export void mi_stats_print_out(mi_output_fun* out, void* arg) mi_attr_noexcept; + +mi_decl_export void mi_process_init(void) mi_attr_noexcept; +mi_decl_export void mi_thread_init(void) mi_attr_noexcept; +mi_decl_export void mi_thread_done(void) mi_attr_noexcept; +mi_decl_export void mi_thread_stats_print_out(mi_output_fun* out, void* arg) mi_attr_noexcept; + +mi_decl_export void mi_process_info(size_t* elapsed_msecs, size_t* user_msecs, size_t* system_msecs, + size_t* current_rss, size_t* peak_rss, + size_t* current_commit, size_t* peak_commit, size_t* page_faults) mi_attr_noexcept; + +// ------------------------------------------------------------------------------------- +// Aligned allocation +// Note that `alignment` always follows `size` for consistency with unaligned +// allocation, but unfortunately this differs from `posix_memalign` and `aligned_alloc`. +// ------------------------------------------------------------------------------------- + +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_malloc_aligned(size_t size, size_t alignment) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1) mi_attr_alloc_align(2); +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_malloc_aligned_at(size_t size, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1); +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_zalloc_aligned(size_t size, size_t alignment) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1) mi_attr_alloc_align(2); +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_zalloc_aligned_at(size_t size, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1); +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_calloc_aligned(size_t count, size_t size, size_t alignment) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2(1,2) mi_attr_alloc_align(3); +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_calloc_aligned_at(size_t count, size_t size, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2(1,2); +mi_decl_nodiscard mi_decl_export void* mi_realloc_aligned(void* p, size_t newsize, size_t alignment) mi_attr_noexcept mi_attr_alloc_size(2) mi_attr_alloc_align(3); +mi_decl_nodiscard mi_decl_export void* mi_realloc_aligned_at(void* p, size_t newsize, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_alloc_size(2); + + +// ------------------------------------------------------------------------------------- +// Heaps: first-class, but can only allocate from the same thread that created it. +// ------------------------------------------------------------------------------------- + +struct mi_heap_s; +typedef struct mi_heap_s mi_heap_t; + +mi_decl_nodiscard mi_decl_export mi_heap_t* mi_heap_new(void); +mi_decl_export void mi_heap_delete(mi_heap_t* heap); +mi_decl_export void mi_heap_destroy(mi_heap_t* heap); +mi_decl_export mi_heap_t* mi_heap_set_default(mi_heap_t* heap); +mi_decl_export mi_heap_t* mi_heap_get_default(void); +mi_decl_export mi_heap_t* mi_heap_get_backing(void); +mi_decl_export void mi_heap_collect(mi_heap_t* heap, bool force) mi_attr_noexcept; + +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_heap_malloc(mi_heap_t* heap, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2); +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_heap_zalloc(mi_heap_t* heap, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2); +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_heap_calloc(mi_heap_t* heap, size_t count, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2(2, 3); +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_heap_mallocn(mi_heap_t* heap, size_t count, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2(2, 3); +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_heap_malloc_small(mi_heap_t* heap, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2); + +mi_decl_nodiscard mi_decl_export void* mi_heap_realloc(mi_heap_t* heap, void* p, size_t newsize) mi_attr_noexcept mi_attr_alloc_size(3); +mi_decl_nodiscard mi_decl_export void* mi_heap_reallocn(mi_heap_t* heap, void* p, size_t count, size_t size) mi_attr_noexcept mi_attr_alloc_size2(3,4); +mi_decl_nodiscard mi_decl_export void* mi_heap_reallocf(mi_heap_t* heap, void* p, size_t newsize) mi_attr_noexcept mi_attr_alloc_size(3); + +mi_decl_nodiscard mi_decl_export mi_decl_restrict char* mi_heap_strdup(mi_heap_t* heap, const char* s) mi_attr_noexcept mi_attr_malloc; +mi_decl_nodiscard mi_decl_export mi_decl_restrict char* mi_heap_strndup(mi_heap_t* heap, const char* s, size_t n) mi_attr_noexcept mi_attr_malloc; +mi_decl_nodiscard mi_decl_export mi_decl_restrict char* mi_heap_realpath(mi_heap_t* heap, const char* fname, char* resolved_name) mi_attr_noexcept mi_attr_malloc; + +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_heap_malloc_aligned(mi_heap_t* heap, size_t size, size_t alignment) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2) mi_attr_alloc_align(3); +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_heap_malloc_aligned_at(mi_heap_t* heap, size_t size, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2); +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_heap_zalloc_aligned(mi_heap_t* heap, size_t size, size_t alignment) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2) mi_attr_alloc_align(3); +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_heap_zalloc_aligned_at(mi_heap_t* heap, size_t size, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2); +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_heap_calloc_aligned(mi_heap_t* heap, size_t count, size_t size, size_t alignment) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2(2, 3) mi_attr_alloc_align(4); +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_heap_calloc_aligned_at(mi_heap_t* heap, size_t count, size_t size, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2(2, 3); +mi_decl_nodiscard mi_decl_export void* mi_heap_realloc_aligned(mi_heap_t* heap, void* p, size_t newsize, size_t alignment) mi_attr_noexcept mi_attr_alloc_size(3) mi_attr_alloc_align(4); +mi_decl_nodiscard mi_decl_export void* mi_heap_realloc_aligned_at(mi_heap_t* heap, void* p, size_t newsize, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_alloc_size(3); + + +// -------------------------------------------------------------------------------- +// Zero initialized re-allocation. +// Only valid on memory that was originally allocated with zero initialization too. +// e.g. `mi_calloc`, `mi_zalloc`, `mi_zalloc_aligned` etc. +// see +// -------------------------------------------------------------------------------- + +mi_decl_nodiscard mi_decl_export void* mi_rezalloc(void* p, size_t newsize) mi_attr_noexcept mi_attr_alloc_size(2); +mi_decl_nodiscard mi_decl_export void* mi_recalloc(void* p, size_t newcount, size_t size) mi_attr_noexcept mi_attr_alloc_size2(2,3); + +mi_decl_nodiscard mi_decl_export void* mi_rezalloc_aligned(void* p, size_t newsize, size_t alignment) mi_attr_noexcept mi_attr_alloc_size(2) mi_attr_alloc_align(3); +mi_decl_nodiscard mi_decl_export void* mi_rezalloc_aligned_at(void* p, size_t newsize, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_alloc_size(2); +mi_decl_nodiscard mi_decl_export void* mi_recalloc_aligned(void* p, size_t newcount, size_t size, size_t alignment) mi_attr_noexcept mi_attr_alloc_size2(2,3) mi_attr_alloc_align(4); +mi_decl_nodiscard mi_decl_export void* mi_recalloc_aligned_at(void* p, size_t newcount, size_t size, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_alloc_size2(2,3); + +mi_decl_nodiscard mi_decl_export void* mi_heap_rezalloc(mi_heap_t* heap, void* p, size_t newsize) mi_attr_noexcept mi_attr_alloc_size(3); +mi_decl_nodiscard mi_decl_export void* mi_heap_recalloc(mi_heap_t* heap, void* p, size_t newcount, size_t size) mi_attr_noexcept mi_attr_alloc_size2(3,4); + +mi_decl_nodiscard mi_decl_export void* mi_heap_rezalloc_aligned(mi_heap_t* heap, void* p, size_t newsize, size_t alignment) mi_attr_noexcept mi_attr_alloc_size(3) mi_attr_alloc_align(4); +mi_decl_nodiscard mi_decl_export void* mi_heap_rezalloc_aligned_at(mi_heap_t* heap, void* p, size_t newsize, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_alloc_size(3); +mi_decl_nodiscard mi_decl_export void* mi_heap_recalloc_aligned(mi_heap_t* heap, void* p, size_t newcount, size_t size, size_t alignment) mi_attr_noexcept mi_attr_alloc_size2(3,4) mi_attr_alloc_align(5); +mi_decl_nodiscard mi_decl_export void* mi_heap_recalloc_aligned_at(mi_heap_t* heap, void* p, size_t newcount, size_t size, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_alloc_size2(3,4); + + +// ------------------------------------------------------ +// Analysis +// ------------------------------------------------------ + +mi_decl_export bool mi_heap_contains_block(mi_heap_t* heap, const void* p); +mi_decl_export bool mi_heap_check_owned(mi_heap_t* heap, const void* p); +mi_decl_export bool mi_check_owned(const void* p); + +// An area of heap space contains blocks of a single size. +typedef struct mi_heap_area_s { + void* blocks; // start of the area containing heap blocks + size_t reserved; // bytes reserved for this area (virtual) + size_t committed; // current available bytes for this area + size_t used; // number of allocated blocks + size_t block_size; // size in bytes of each block + size_t full_block_size; // size in bytes of a full block including padding and metadata. +} mi_heap_area_t; + +typedef bool (mi_cdecl mi_block_visit_fun)(const mi_heap_t* heap, const mi_heap_area_t* area, void* block, size_t block_size, void* arg); + +mi_decl_export bool mi_heap_visit_blocks(const mi_heap_t* heap, bool visit_all_blocks, mi_block_visit_fun* visitor, void* arg); + +// Experimental +mi_decl_nodiscard mi_decl_export bool mi_is_in_heap_region(const void* p) mi_attr_noexcept; +mi_decl_nodiscard mi_decl_export bool mi_is_redirected(void) mi_attr_noexcept; + +mi_decl_export int mi_reserve_huge_os_pages_interleave(size_t pages, size_t numa_nodes, size_t timeout_msecs) mi_attr_noexcept; +mi_decl_export int mi_reserve_huge_os_pages_at(size_t pages, int numa_node, size_t timeout_msecs) mi_attr_noexcept; + +mi_decl_export int mi_reserve_os_memory(size_t size, bool commit, bool allow_large) mi_attr_noexcept; +mi_decl_export bool mi_manage_os_memory(void* start, size_t size, bool is_committed, bool is_large, bool is_zero, int numa_node) mi_attr_noexcept; + +mi_decl_export void mi_debug_show_arenas(void) mi_attr_noexcept; + +// Experimental: heaps associated with specific memory arena's +typedef int mi_arena_id_t; +mi_decl_export void* mi_arena_area(mi_arena_id_t arena_id, size_t* size); +mi_decl_export int mi_reserve_huge_os_pages_at_ex(size_t pages, int numa_node, size_t timeout_msecs, bool exclusive, mi_arena_id_t* arena_id) mi_attr_noexcept; +mi_decl_export int mi_reserve_os_memory_ex(size_t size, bool commit, bool allow_large, bool exclusive, mi_arena_id_t* arena_id) mi_attr_noexcept; +mi_decl_export bool mi_manage_os_memory_ex(void* start, size_t size, bool is_committed, bool is_large, bool is_zero, int numa_node, bool exclusive, mi_arena_id_t* arena_id) mi_attr_noexcept; + +#if MI_MALLOC_VERSION >= 182 +// Create a heap that only allocates in the specified arena +mi_decl_nodiscard mi_decl_export mi_heap_t* mi_heap_new_in_arena(mi_arena_id_t arena_id); +#endif + +// deprecated +mi_decl_export int mi_reserve_huge_os_pages(size_t pages, double max_secs, size_t* pages_reserved) mi_attr_noexcept; + + +// ------------------------------------------------------ +// Convenience +// ------------------------------------------------------ + +#define mi_malloc_tp(tp) ((tp*)mi_malloc(sizeof(tp))) +#define mi_zalloc_tp(tp) ((tp*)mi_zalloc(sizeof(tp))) +#define mi_calloc_tp(tp,n) ((tp*)mi_calloc(n,sizeof(tp))) +#define mi_mallocn_tp(tp,n) ((tp*)mi_mallocn(n,sizeof(tp))) +#define mi_reallocn_tp(p,tp,n) ((tp*)mi_reallocn(p,n,sizeof(tp))) +#define mi_recalloc_tp(p,tp,n) ((tp*)mi_recalloc(p,n,sizeof(tp))) + +#define mi_heap_malloc_tp(hp,tp) ((tp*)mi_heap_malloc(hp,sizeof(tp))) +#define mi_heap_zalloc_tp(hp,tp) ((tp*)mi_heap_zalloc(hp,sizeof(tp))) +#define mi_heap_calloc_tp(hp,tp,n) ((tp*)mi_heap_calloc(hp,n,sizeof(tp))) +#define mi_heap_mallocn_tp(hp,tp,n) ((tp*)mi_heap_mallocn(hp,n,sizeof(tp))) +#define mi_heap_reallocn_tp(hp,p,tp,n) ((tp*)mi_heap_reallocn(hp,p,n,sizeof(tp))) +#define mi_heap_recalloc_tp(hp,p,tp,n) ((tp*)mi_heap_recalloc(hp,p,n,sizeof(tp))) + + +// ------------------------------------------------------ +// Options +// ------------------------------------------------------ + +typedef enum mi_option_e { + // stable options + mi_option_show_errors, // print error messages + mi_option_show_stats, // print statistics on termination + mi_option_verbose, // print verbose messages + // the following options are experimental (see src/options.h) + mi_option_eager_commit, // eager commit segments? (after `eager_commit_delay` segments) (=1) + mi_option_arena_eager_commit, // eager commit arenas? Use 2 to enable just on overcommit systems (=2) + mi_option_purge_decommits, // should a memory purge decommit (or only reset) (=1) + mi_option_allow_large_os_pages, // allow large (2MiB) OS pages, implies eager commit + mi_option_reserve_huge_os_pages, // reserve N huge OS pages (1GiB/page) at startup + mi_option_reserve_huge_os_pages_at, // reserve huge OS pages at a specific NUMA node + mi_option_reserve_os_memory, // reserve specified amount of OS memory in an arena at startup + mi_option_deprecated_segment_cache, + mi_option_deprecated_page_reset, + mi_option_abandoned_page_purge, // immediately purge delayed purges on thread termination + mi_option_deprecated_segment_reset, + mi_option_eager_commit_delay, + mi_option_purge_delay, // memory purging is delayed by N milli seconds; use 0 for immediate purging or -1 for no purging at all. + mi_option_use_numa_nodes, // 0 = use all available numa nodes, otherwise use at most N nodes. + mi_option_limit_os_alloc, // 1 = do not use OS memory for allocation (but only programmatically reserved arenas) + mi_option_os_tag, // tag used for OS logging (macOS only for now) + mi_option_max_errors, // issue at most N error messages + mi_option_max_warnings, // issue at most N warning messages + mi_option_max_segment_reclaim, + mi_option_destroy_on_exit, // if set, release all memory on exit; sometimes used for dynamic unloading but can be unsafe. + mi_option_arena_reserve, // initial memory size in KiB for arena reservation (1GiB on 64-bit) + mi_option_arena_purge_mult, + mi_option_purge_extend_delay, + _mi_option_last, + // legacy option names + mi_option_large_os_pages = mi_option_allow_large_os_pages, + mi_option_eager_region_commit = mi_option_arena_eager_commit, + mi_option_reset_decommits = mi_option_purge_decommits, + mi_option_reset_delay = mi_option_purge_delay, + mi_option_abandoned_page_reset = mi_option_abandoned_page_purge +} mi_option_t; + + +mi_decl_nodiscard mi_decl_export bool mi_option_is_enabled(mi_option_t option); +mi_decl_export void mi_option_enable(mi_option_t option); +mi_decl_export void mi_option_disable(mi_option_t option); +mi_decl_export void mi_option_set_enabled(mi_option_t option, bool enable); +mi_decl_export void mi_option_set_enabled_default(mi_option_t option, bool enable); + +mi_decl_nodiscard mi_decl_export long mi_option_get(mi_option_t option); +mi_decl_nodiscard mi_decl_export long mi_option_get_clamp(mi_option_t option, long min, long max); +mi_decl_nodiscard mi_decl_export size_t mi_option_get_size(mi_option_t option); +mi_decl_export void mi_option_set(mi_option_t option, long value); +mi_decl_export void mi_option_set_default(mi_option_t option, long value); + + +// ------------------------------------------------------------------------------------------------------- +// "mi" prefixed implementations of various posix, Unix, Windows, and C++ allocation functions. +// (This can be convenient when providing overrides of these functions as done in `mimalloc-override.h`.) +// note: we use `mi_cfree` as "checked free" and it checks if the pointer is in our heap before free-ing. +// ------------------------------------------------------------------------------------------------------- + +mi_decl_export void mi_cfree(void* p) mi_attr_noexcept; +mi_decl_export void* mi__expand(void* p, size_t newsize) mi_attr_noexcept; +mi_decl_nodiscard mi_decl_export size_t mi_malloc_size(const void* p) mi_attr_noexcept; +mi_decl_nodiscard mi_decl_export size_t mi_malloc_good_size(size_t size) mi_attr_noexcept; +mi_decl_nodiscard mi_decl_export size_t mi_malloc_usable_size(const void *p) mi_attr_noexcept; + +mi_decl_export int mi_posix_memalign(void** p, size_t alignment, size_t size) mi_attr_noexcept; +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_memalign(size_t alignment, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2) mi_attr_alloc_align(1); +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_valloc(size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1); +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_pvalloc(size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1); +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_aligned_alloc(size_t alignment, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2) mi_attr_alloc_align(1); + +mi_decl_nodiscard mi_decl_export void* mi_reallocarray(void* p, size_t count, size_t size) mi_attr_noexcept mi_attr_alloc_size2(2,3); +mi_decl_nodiscard mi_decl_export int mi_reallocarr(void* p, size_t count, size_t size) mi_attr_noexcept; +mi_decl_nodiscard mi_decl_export void* mi_aligned_recalloc(void* p, size_t newcount, size_t size, size_t alignment) mi_attr_noexcept; +mi_decl_nodiscard mi_decl_export void* mi_aligned_offset_recalloc(void* p, size_t newcount, size_t size, size_t alignment, size_t offset) mi_attr_noexcept; + +mi_decl_nodiscard mi_decl_export mi_decl_restrict unsigned short* mi_wcsdup(const unsigned short* s) mi_attr_noexcept mi_attr_malloc; +mi_decl_nodiscard mi_decl_export mi_decl_restrict unsigned char* mi_mbsdup(const unsigned char* s) mi_attr_noexcept mi_attr_malloc; +mi_decl_export int mi_dupenv_s(char** buf, size_t* size, const char* name) mi_attr_noexcept; +mi_decl_export int mi_wdupenv_s(unsigned short** buf, size_t* size, const unsigned short* name) mi_attr_noexcept; + +mi_decl_export void mi_free_size(void* p, size_t size) mi_attr_noexcept; +mi_decl_export void mi_free_size_aligned(void* p, size_t size, size_t alignment) mi_attr_noexcept; +mi_decl_export void mi_free_aligned(void* p, size_t alignment) mi_attr_noexcept; + +// The `mi_new` wrappers implement C++ semantics on out-of-memory instead of directly returning `NULL`. +// (and call `std::get_new_handler` and potentially raise a `std::bad_alloc` exception). +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_new(size_t size) mi_attr_malloc mi_attr_alloc_size(1); +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_new_aligned(size_t size, size_t alignment) mi_attr_malloc mi_attr_alloc_size(1) mi_attr_alloc_align(2); +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_new_nothrow(size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1); +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_new_aligned_nothrow(size_t size, size_t alignment) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1) mi_attr_alloc_align(2); +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_new_n(size_t count, size_t size) mi_attr_malloc mi_attr_alloc_size2(1, 2); +mi_decl_nodiscard mi_decl_export void* mi_new_realloc(void* p, size_t newsize) mi_attr_alloc_size(2); +mi_decl_nodiscard mi_decl_export void* mi_new_reallocn(void* p, size_t newcount, size_t size) mi_attr_alloc_size2(2, 3); + +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_heap_alloc_new(mi_heap_t* heap, size_t size) mi_attr_malloc mi_attr_alloc_size(2); +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_heap_alloc_new_n(mi_heap_t* heap, size_t count, size_t size) mi_attr_malloc mi_attr_alloc_size2(2, 3); + +#ifdef __cplusplus +} +#endif + +// --------------------------------------------------------------------------------------------- +// Implement the C++ std::allocator interface for use in STL containers. +// (note: see `mimalloc-new-delete.h` for overriding the new/delete operators globally) +// --------------------------------------------------------------------------------------------- +#ifdef __cplusplus + +#include // std::size_t +#include // PTRDIFF_MAX +#if (__cplusplus >= 201103L) || (_MSC_VER > 1900) // C++11 +#include // std::true_type +#include // std::forward +#endif + +template struct _mi_stl_allocator_common { + typedef T value_type; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + typedef value_type& reference; + typedef value_type const& const_reference; + typedef value_type* pointer; + typedef value_type const* const_pointer; + + #if ((__cplusplus >= 201103L) || (_MSC_VER > 1900)) // C++11 + using propagate_on_container_copy_assignment = std::true_type; + using propagate_on_container_move_assignment = std::true_type; + using propagate_on_container_swap = std::true_type; + template void construct(U* p, Args&& ...args) { ::new(p) U(std::forward(args)...); } + template void destroy(U* p) mi_attr_noexcept { p->~U(); } + #else + void construct(pointer p, value_type const& val) { ::new(p) value_type(val); } + void destroy(pointer p) { p->~value_type(); } + #endif + + size_type max_size() const mi_attr_noexcept { return (PTRDIFF_MAX/sizeof(value_type)); } + pointer address(reference x) const { return &x; } + const_pointer address(const_reference x) const { return &x; } +}; + +template struct mi_stl_allocator : public _mi_stl_allocator_common { + using typename _mi_stl_allocator_common::size_type; + using typename _mi_stl_allocator_common::value_type; + using typename _mi_stl_allocator_common::pointer; + template struct rebind { typedef mi_stl_allocator other; }; + + mi_stl_allocator() mi_attr_noexcept = default; + mi_stl_allocator(const mi_stl_allocator&) mi_attr_noexcept = default; + template mi_stl_allocator(const mi_stl_allocator&) mi_attr_noexcept { } + mi_stl_allocator select_on_container_copy_construction() const { return *this; } + void deallocate(T* p, size_type) { mi_free(p); } + + #if (__cplusplus >= 201703L) // C++17 + mi_decl_nodiscard T* allocate(size_type count) { return static_cast(mi_new_n(count, sizeof(T))); } + mi_decl_nodiscard T* allocate(size_type count, const void*) { return allocate(count); } + #else + mi_decl_nodiscard pointer allocate(size_type count, const void* = 0) { return static_cast(mi_new_n(count, sizeof(value_type))); } + #endif + + #if ((__cplusplus >= 201103L) || (_MSC_VER > 1900)) // C++11 + using is_always_equal = std::true_type; + #endif +}; + +template bool operator==(const mi_stl_allocator& , const mi_stl_allocator& ) mi_attr_noexcept { return true; } +template bool operator!=(const mi_stl_allocator& , const mi_stl_allocator& ) mi_attr_noexcept { return false; } + + +#if (__cplusplus >= 201103L) || (_MSC_VER >= 1900) // C++11 +#define MI_HAS_HEAP_STL_ALLOCATOR 1 + +#include // std::shared_ptr + +// Common base class for STL allocators in a specific heap +template struct _mi_heap_stl_allocator_common : public _mi_stl_allocator_common { + using typename _mi_stl_allocator_common::size_type; + using typename _mi_stl_allocator_common::value_type; + using typename _mi_stl_allocator_common::pointer; + + _mi_heap_stl_allocator_common(mi_heap_t* hp) : heap(hp) { } /* will not delete nor destroy the passed in heap */ + + #if (__cplusplus >= 201703L) // C++17 + mi_decl_nodiscard T* allocate(size_type count) { return static_cast(mi_heap_alloc_new_n(this->heap.get(), count, sizeof(T))); } + mi_decl_nodiscard T* allocate(size_type count, const void*) { return allocate(count); } + #else + mi_decl_nodiscard pointer allocate(size_type count, const void* = 0) { return static_cast(mi_heap_alloc_new_n(this->heap.get(), count, sizeof(value_type))); } + #endif + + #if ((__cplusplus >= 201103L) || (_MSC_VER > 1900)) // C++11 + using is_always_equal = std::false_type; + #endif + + void collect(bool force) { mi_heap_collect(this->heap.get(), force); } + template bool is_equal(const _mi_heap_stl_allocator_common& x) const { return (this->heap == x.heap); } + +protected: + std::shared_ptr heap; + template friend struct _mi_heap_stl_allocator_common; + + _mi_heap_stl_allocator_common() { + mi_heap_t* hp = mi_heap_new(); + this->heap.reset(hp, (_mi_destroy ? &heap_destroy : &heap_delete)); /* calls heap_delete/destroy when the refcount drops to zero */ + } + _mi_heap_stl_allocator_common(const _mi_heap_stl_allocator_common& x) mi_attr_noexcept : heap(x.heap) { } + template _mi_heap_stl_allocator_common(const _mi_heap_stl_allocator_common& x) mi_attr_noexcept : heap(x.heap) { } + +private: + static void heap_delete(mi_heap_t* hp) { if (hp != NULL) { mi_heap_delete(hp); } } + static void heap_destroy(mi_heap_t* hp) { if (hp != NULL) { mi_heap_destroy(hp); } } +}; + +// STL allocator allocation in a specific heap +template struct mi_heap_stl_allocator : public _mi_heap_stl_allocator_common { + using typename _mi_heap_stl_allocator_common::size_type; + mi_heap_stl_allocator() : _mi_heap_stl_allocator_common() { } // creates fresh heap that is deleted when the destructor is called + mi_heap_stl_allocator(mi_heap_t* hp) : _mi_heap_stl_allocator_common(hp) { } // no delete nor destroy on the passed in heap + template mi_heap_stl_allocator(const mi_heap_stl_allocator& x) mi_attr_noexcept : _mi_heap_stl_allocator_common(x) { } + + mi_heap_stl_allocator select_on_container_copy_construction() const { return *this; } + void deallocate(T* p, size_type) { mi_free(p); } + template struct rebind { typedef mi_heap_stl_allocator other; }; +}; + +template bool operator==(const mi_heap_stl_allocator& x, const mi_heap_stl_allocator& y) mi_attr_noexcept { return (x.is_equal(y)); } +template bool operator!=(const mi_heap_stl_allocator& x, const mi_heap_stl_allocator& y) mi_attr_noexcept { return (!x.is_equal(y)); } + + +// STL allocator allocation in a specific heap, where `free` does nothing and +// the heap is destroyed in one go on destruction -- use with care! +template struct mi_heap_destroy_stl_allocator : public _mi_heap_stl_allocator_common { + using typename _mi_heap_stl_allocator_common::size_type; + mi_heap_destroy_stl_allocator() : _mi_heap_stl_allocator_common() { } // creates fresh heap that is destroyed when the destructor is called + mi_heap_destroy_stl_allocator(mi_heap_t* hp) : _mi_heap_stl_allocator_common(hp) { } // no delete nor destroy on the passed in heap + template mi_heap_destroy_stl_allocator(const mi_heap_destroy_stl_allocator& x) mi_attr_noexcept : _mi_heap_stl_allocator_common(x) { } + + mi_heap_destroy_stl_allocator select_on_container_copy_construction() const { return *this; } + void deallocate(T*, size_type) { /* do nothing as we destroy the heap on destruct. */ } + template struct rebind { typedef mi_heap_destroy_stl_allocator other; }; +}; + +template bool operator==(const mi_heap_destroy_stl_allocator& x, const mi_heap_destroy_stl_allocator& y) mi_attr_noexcept { return (x.is_equal(y)); } +template bool operator!=(const mi_heap_destroy_stl_allocator& x, const mi_heap_destroy_stl_allocator& y) mi_attr_noexcept { return (!x.is_equal(y)); } + +#endif // C++11 + +#endif // __cplusplus + +#endif diff --git a/Include/internal/mimalloc/mimalloc/atomic.h b/Include/internal/mimalloc/mimalloc/atomic.h new file mode 100644 index 00000000000000..eb8478ceed6adf --- /dev/null +++ b/Include/internal/mimalloc/mimalloc/atomic.h @@ -0,0 +1,385 @@ +/* ---------------------------------------------------------------------------- +Copyright (c) 2018-2023 Microsoft Research, Daan Leijen +This is free software; you can redistribute it and/or modify it under the +terms of the MIT license. A copy of the license can be found in the file +"LICENSE" at the root of this distribution. +-----------------------------------------------------------------------------*/ +#pragma once +#ifndef MIMALLOC_ATOMIC_H +#define MIMALLOC_ATOMIC_H + +// -------------------------------------------------------------------------------------------- +// Atomics +// We need to be portable between C, C++, and MSVC. +// We base the primitives on the C/C++ atomics and create a mimimal wrapper for MSVC in C compilation mode. +// This is why we try to use only `uintptr_t` and `*` as atomic types. +// To gain better insight in the range of used atomics, we use explicitly named memory order operations +// instead of passing the memory order as a parameter. +// ----------------------------------------------------------------------------------------------- + +#if defined(__cplusplus) +// Use C++ atomics +#include +#define _Atomic(tp) std::atomic +#define mi_atomic(name) std::atomic_##name +#define mi_memory_order(name) std::memory_order_##name +#if !defined(ATOMIC_VAR_INIT) || (__cplusplus >= 202002L) // c++20, see issue #571 + #define MI_ATOMIC_VAR_INIT(x) x +#else + #define MI_ATOMIC_VAR_INIT(x) ATOMIC_VAR_INIT(x) +#endif +#elif defined(_MSC_VER) +// Use MSVC C wrapper for C11 atomics +#define _Atomic(tp) tp +#define MI_ATOMIC_VAR_INIT(x) x +#define mi_atomic(name) mi_atomic_##name +#define mi_memory_order(name) mi_memory_order_##name +#else +// Use C11 atomics +#include +#define mi_atomic(name) atomic_##name +#define mi_memory_order(name) memory_order_##name +#if !defined(ATOMIC_VAR_INIT) || (__STDC_VERSION__ >= 201710L) // c17, see issue #735 + #define MI_ATOMIC_VAR_INIT(x) x +#else + #define MI_ATOMIC_VAR_INIT(x) ATOMIC_VAR_INIT(x) +#endif +#endif + +// Various defines for all used memory orders in mimalloc +#define mi_atomic_cas_weak(p,expected,desired,mem_success,mem_fail) \ + mi_atomic(compare_exchange_weak_explicit)(p,expected,desired,mem_success,mem_fail) + +#define mi_atomic_cas_strong(p,expected,desired,mem_success,mem_fail) \ + mi_atomic(compare_exchange_strong_explicit)(p,expected,desired,mem_success,mem_fail) + +#define mi_atomic_load_acquire(p) mi_atomic(load_explicit)(p,mi_memory_order(acquire)) +#define mi_atomic_load_relaxed(p) mi_atomic(load_explicit)(p,mi_memory_order(relaxed)) +#define mi_atomic_store_release(p,x) mi_atomic(store_explicit)(p,x,mi_memory_order(release)) +#define mi_atomic_store_relaxed(p,x) mi_atomic(store_explicit)(p,x,mi_memory_order(relaxed)) +#define mi_atomic_exchange_release(p,x) mi_atomic(exchange_explicit)(p,x,mi_memory_order(release)) +#define mi_atomic_exchange_acq_rel(p,x) mi_atomic(exchange_explicit)(p,x,mi_memory_order(acq_rel)) +#define mi_atomic_cas_weak_release(p,exp,des) mi_atomic_cas_weak(p,exp,des,mi_memory_order(release),mi_memory_order(relaxed)) +#define mi_atomic_cas_weak_acq_rel(p,exp,des) mi_atomic_cas_weak(p,exp,des,mi_memory_order(acq_rel),mi_memory_order(acquire)) +#define mi_atomic_cas_strong_release(p,exp,des) mi_atomic_cas_strong(p,exp,des,mi_memory_order(release),mi_memory_order(relaxed)) +#define mi_atomic_cas_strong_acq_rel(p,exp,des) mi_atomic_cas_strong(p,exp,des,mi_memory_order(acq_rel),mi_memory_order(acquire)) + +#define mi_atomic_add_relaxed(p,x) mi_atomic(fetch_add_explicit)(p,x,mi_memory_order(relaxed)) +#define mi_atomic_sub_relaxed(p,x) mi_atomic(fetch_sub_explicit)(p,x,mi_memory_order(relaxed)) +#define mi_atomic_add_acq_rel(p,x) mi_atomic(fetch_add_explicit)(p,x,mi_memory_order(acq_rel)) +#define mi_atomic_sub_acq_rel(p,x) mi_atomic(fetch_sub_explicit)(p,x,mi_memory_order(acq_rel)) +#define mi_atomic_and_acq_rel(p,x) mi_atomic(fetch_and_explicit)(p,x,mi_memory_order(acq_rel)) +#define mi_atomic_or_acq_rel(p,x) mi_atomic(fetch_or_explicit)(p,x,mi_memory_order(acq_rel)) + +#define mi_atomic_increment_relaxed(p) mi_atomic_add_relaxed(p,(uintptr_t)1) +#define mi_atomic_decrement_relaxed(p) mi_atomic_sub_relaxed(p,(uintptr_t)1) +#define mi_atomic_increment_acq_rel(p) mi_atomic_add_acq_rel(p,(uintptr_t)1) +#define mi_atomic_decrement_acq_rel(p) mi_atomic_sub_acq_rel(p,(uintptr_t)1) + +static inline void mi_atomic_yield(void); +static inline intptr_t mi_atomic_addi(_Atomic(intptr_t)*p, intptr_t add); +static inline intptr_t mi_atomic_subi(_Atomic(intptr_t)*p, intptr_t sub); + + +#if defined(__cplusplus) || !defined(_MSC_VER) + +// In C++/C11 atomics we have polymorphic atomics so can use the typed `ptr` variants (where `tp` is the type of atomic value) +// We use these macros so we can provide a typed wrapper in MSVC in C compilation mode as well +#define mi_atomic_load_ptr_acquire(tp,p) mi_atomic_load_acquire(p) +#define mi_atomic_load_ptr_relaxed(tp,p) mi_atomic_load_relaxed(p) + +// In C++ we need to add casts to help resolve templates if NULL is passed +#if defined(__cplusplus) +#define mi_atomic_store_ptr_release(tp,p,x) mi_atomic_store_release(p,(tp*)x) +#define mi_atomic_store_ptr_relaxed(tp,p,x) mi_atomic_store_relaxed(p,(tp*)x) +#define mi_atomic_cas_ptr_weak_release(tp,p,exp,des) mi_atomic_cas_weak_release(p,exp,(tp*)des) +#define mi_atomic_cas_ptr_weak_acq_rel(tp,p,exp,des) mi_atomic_cas_weak_acq_rel(p,exp,(tp*)des) +#define mi_atomic_cas_ptr_strong_release(tp,p,exp,des) mi_atomic_cas_strong_release(p,exp,(tp*)des) +#define mi_atomic_exchange_ptr_release(tp,p,x) mi_atomic_exchange_release(p,(tp*)x) +#define mi_atomic_exchange_ptr_acq_rel(tp,p,x) mi_atomic_exchange_acq_rel(p,(tp*)x) +#else +#define mi_atomic_store_ptr_release(tp,p,x) mi_atomic_store_release(p,x) +#define mi_atomic_store_ptr_relaxed(tp,p,x) mi_atomic_store_relaxed(p,x) +#define mi_atomic_cas_ptr_weak_release(tp,p,exp,des) mi_atomic_cas_weak_release(p,exp,des) +#define mi_atomic_cas_ptr_weak_acq_rel(tp,p,exp,des) mi_atomic_cas_weak_acq_rel(p,exp,des) +#define mi_atomic_cas_ptr_strong_release(tp,p,exp,des) mi_atomic_cas_strong_release(p,exp,des) +#define mi_atomic_exchange_ptr_release(tp,p,x) mi_atomic_exchange_release(p,x) +#define mi_atomic_exchange_ptr_acq_rel(tp,p,x) mi_atomic_exchange_acq_rel(p,x) +#endif + +// These are used by the statistics +static inline int64_t mi_atomic_addi64_relaxed(volatile int64_t* p, int64_t add) { + return mi_atomic(fetch_add_explicit)((_Atomic(int64_t)*)p, add, mi_memory_order(relaxed)); +} +static inline void mi_atomic_maxi64_relaxed(volatile int64_t* p, int64_t x) { + int64_t current = mi_atomic_load_relaxed((_Atomic(int64_t)*)p); + while (current < x && !mi_atomic_cas_weak_release((_Atomic(int64_t)*)p, ¤t, x)) { /* nothing */ }; +} + +// Used by timers +#define mi_atomic_loadi64_acquire(p) mi_atomic(load_explicit)(p,mi_memory_order(acquire)) +#define mi_atomic_loadi64_relaxed(p) mi_atomic(load_explicit)(p,mi_memory_order(relaxed)) +#define mi_atomic_storei64_release(p,x) mi_atomic(store_explicit)(p,x,mi_memory_order(release)) +#define mi_atomic_storei64_relaxed(p,x) mi_atomic(store_explicit)(p,x,mi_memory_order(relaxed)) + +#define mi_atomic_casi64_strong_acq_rel(p,e,d) mi_atomic_cas_strong_acq_rel(p,e,d) +#define mi_atomic_addi64_acq_rel(p,i) mi_atomic_add_acq_rel(p,i) + + +#elif defined(_MSC_VER) + +// MSVC C compilation wrapper that uses Interlocked operations to model C11 atomics. +#define WIN32_LEAN_AND_MEAN +#include +#include +#ifdef _WIN64 +typedef LONG64 msc_intptr_t; +#define MI_64(f) f##64 +#else +typedef LONG msc_intptr_t; +#define MI_64(f) f +#endif + +typedef enum mi_memory_order_e { + mi_memory_order_relaxed, + mi_memory_order_consume, + mi_memory_order_acquire, + mi_memory_order_release, + mi_memory_order_acq_rel, + mi_memory_order_seq_cst +} mi_memory_order; + +static inline uintptr_t mi_atomic_fetch_add_explicit(_Atomic(uintptr_t)*p, uintptr_t add, mi_memory_order mo) { + (void)(mo); + return (uintptr_t)MI_64(_InterlockedExchangeAdd)((volatile msc_intptr_t*)p, (msc_intptr_t)add); +} +static inline uintptr_t mi_atomic_fetch_sub_explicit(_Atomic(uintptr_t)*p, uintptr_t sub, mi_memory_order mo) { + (void)(mo); + return (uintptr_t)MI_64(_InterlockedExchangeAdd)((volatile msc_intptr_t*)p, -((msc_intptr_t)sub)); +} +static inline uintptr_t mi_atomic_fetch_and_explicit(_Atomic(uintptr_t)*p, uintptr_t x, mi_memory_order mo) { + (void)(mo); + return (uintptr_t)MI_64(_InterlockedAnd)((volatile msc_intptr_t*)p, (msc_intptr_t)x); +} +static inline uintptr_t mi_atomic_fetch_or_explicit(_Atomic(uintptr_t)*p, uintptr_t x, mi_memory_order mo) { + (void)(mo); + return (uintptr_t)MI_64(_InterlockedOr)((volatile msc_intptr_t*)p, (msc_intptr_t)x); +} +static inline bool mi_atomic_compare_exchange_strong_explicit(_Atomic(uintptr_t)*p, uintptr_t* expected, uintptr_t desired, mi_memory_order mo1, mi_memory_order mo2) { + (void)(mo1); (void)(mo2); + uintptr_t read = (uintptr_t)MI_64(_InterlockedCompareExchange)((volatile msc_intptr_t*)p, (msc_intptr_t)desired, (msc_intptr_t)(*expected)); + if (read == *expected) { + return true; + } + else { + *expected = read; + return false; + } +} +static inline bool mi_atomic_compare_exchange_weak_explicit(_Atomic(uintptr_t)*p, uintptr_t* expected, uintptr_t desired, mi_memory_order mo1, mi_memory_order mo2) { + return mi_atomic_compare_exchange_strong_explicit(p, expected, desired, mo1, mo2); +} +static inline uintptr_t mi_atomic_exchange_explicit(_Atomic(uintptr_t)*p, uintptr_t exchange, mi_memory_order mo) { + (void)(mo); + return (uintptr_t)MI_64(_InterlockedExchange)((volatile msc_intptr_t*)p, (msc_intptr_t)exchange); +} +static inline void mi_atomic_thread_fence(mi_memory_order mo) { + (void)(mo); + _Atomic(uintptr_t) x = 0; + mi_atomic_exchange_explicit(&x, 1, mo); +} +static inline uintptr_t mi_atomic_load_explicit(_Atomic(uintptr_t) const* p, mi_memory_order mo) { + (void)(mo); +#if defined(_M_IX86) || defined(_M_X64) + return *p; +#else + uintptr_t x = *p; + if (mo > mi_memory_order_relaxed) { + while (!mi_atomic_compare_exchange_weak_explicit((_Atomic(uintptr_t)*)p, &x, x, mo, mi_memory_order_relaxed)) { /* nothing */ }; + } + return x; +#endif +} +static inline void mi_atomic_store_explicit(_Atomic(uintptr_t)*p, uintptr_t x, mi_memory_order mo) { + (void)(mo); +#if defined(_M_IX86) || defined(_M_X64) + *p = x; +#else + mi_atomic_exchange_explicit(p, x, mo); +#endif +} +static inline int64_t mi_atomic_loadi64_explicit(_Atomic(int64_t)*p, mi_memory_order mo) { + (void)(mo); +#if defined(_M_X64) + return *p; +#else + int64_t old = *p; + int64_t x = old; + while ((old = InterlockedCompareExchange64(p, x, old)) != x) { + x = old; + } + return x; +#endif +} +static inline void mi_atomic_storei64_explicit(_Atomic(int64_t)*p, int64_t x, mi_memory_order mo) { + (void)(mo); +#if defined(x_M_IX86) || defined(_M_X64) + *p = x; +#else + InterlockedExchange64(p, x); +#endif +} + +// These are used by the statistics +static inline int64_t mi_atomic_addi64_relaxed(volatile _Atomic(int64_t)*p, int64_t add) { +#ifdef _WIN64 + return (int64_t)mi_atomic_addi((int64_t*)p, add); +#else + int64_t current; + int64_t sum; + do { + current = *p; + sum = current + add; + } while (_InterlockedCompareExchange64(p, sum, current) != current); + return current; +#endif +} +static inline void mi_atomic_maxi64_relaxed(volatile _Atomic(int64_t)*p, int64_t x) { + int64_t current; + do { + current = *p; + } while (current < x && _InterlockedCompareExchange64(p, x, current) != current); +} + +static inline void mi_atomic_addi64_acq_rel(volatile _Atomic(int64_t*)p, int64_t i) { + mi_atomic_addi64_relaxed(p, i); +} + +static inline bool mi_atomic_casi64_strong_acq_rel(volatile _Atomic(int64_t*)p, int64_t* exp, int64_t des) { + int64_t read = _InterlockedCompareExchange64(p, des, *exp); + if (read == *exp) { + return true; + } + else { + *exp = read; + return false; + } +} + +// The pointer macros cast to `uintptr_t`. +#define mi_atomic_load_ptr_acquire(tp,p) (tp*)mi_atomic_load_acquire((_Atomic(uintptr_t)*)(p)) +#define mi_atomic_load_ptr_relaxed(tp,p) (tp*)mi_atomic_load_relaxed((_Atomic(uintptr_t)*)(p)) +#define mi_atomic_store_ptr_release(tp,p,x) mi_atomic_store_release((_Atomic(uintptr_t)*)(p),(uintptr_t)(x)) +#define mi_atomic_store_ptr_relaxed(tp,p,x) mi_atomic_store_relaxed((_Atomic(uintptr_t)*)(p),(uintptr_t)(x)) +#define mi_atomic_cas_ptr_weak_release(tp,p,exp,des) mi_atomic_cas_weak_release((_Atomic(uintptr_t)*)(p),(uintptr_t*)exp,(uintptr_t)des) +#define mi_atomic_cas_ptr_weak_acq_rel(tp,p,exp,des) mi_atomic_cas_weak_acq_rel((_Atomic(uintptr_t)*)(p),(uintptr_t*)exp,(uintptr_t)des) +#define mi_atomic_cas_ptr_strong_release(tp,p,exp,des) mi_atomic_cas_strong_release((_Atomic(uintptr_t)*)(p),(uintptr_t*)exp,(uintptr_t)des) +#define mi_atomic_exchange_ptr_release(tp,p,x) (tp*)mi_atomic_exchange_release((_Atomic(uintptr_t)*)(p),(uintptr_t)x) +#define mi_atomic_exchange_ptr_acq_rel(tp,p,x) (tp*)mi_atomic_exchange_acq_rel((_Atomic(uintptr_t)*)(p),(uintptr_t)x) + +#define mi_atomic_loadi64_acquire(p) mi_atomic(loadi64_explicit)(p,mi_memory_order(acquire)) +#define mi_atomic_loadi64_relaxed(p) mi_atomic(loadi64_explicit)(p,mi_memory_order(relaxed)) +#define mi_atomic_storei64_release(p,x) mi_atomic(storei64_explicit)(p,x,mi_memory_order(release)) +#define mi_atomic_storei64_relaxed(p,x) mi_atomic(storei64_explicit)(p,x,mi_memory_order(relaxed)) + + +#endif + + +// Atomically add a signed value; returns the previous value. +static inline intptr_t mi_atomic_addi(_Atomic(intptr_t)*p, intptr_t add) { + return (intptr_t)mi_atomic_add_acq_rel((_Atomic(uintptr_t)*)p, (uintptr_t)add); +} + +// Atomically subtract a signed value; returns the previous value. +static inline intptr_t mi_atomic_subi(_Atomic(intptr_t)*p, intptr_t sub) { + return (intptr_t)mi_atomic_addi(p, -sub); +} + +typedef _Atomic(uintptr_t) mi_atomic_once_t; + +// Returns true only on the first invocation +static inline bool mi_atomic_once( mi_atomic_once_t* once ) { + if (mi_atomic_load_relaxed(once) != 0) return false; // quick test + uintptr_t expected = 0; + return mi_atomic_cas_strong_acq_rel(once, &expected, (uintptr_t)1); // try to set to 1 +} + +typedef _Atomic(uintptr_t) mi_atomic_guard_t; + +// Allows only one thread to execute at a time +#define mi_atomic_guard(guard) \ + uintptr_t _mi_guard_expected = 0; \ + for(bool _mi_guard_once = true; \ + _mi_guard_once && mi_atomic_cas_strong_acq_rel(guard,&_mi_guard_expected,(uintptr_t)1); \ + (mi_atomic_store_release(guard,(uintptr_t)0), _mi_guard_once = false) ) + + + +// Yield +#if defined(__cplusplus) +#include +static inline void mi_atomic_yield(void) { + std::this_thread::yield(); +} +#elif defined(_WIN32) +#define WIN32_LEAN_AND_MEAN +#include +static inline void mi_atomic_yield(void) { + YieldProcessor(); +} +#elif defined(__SSE2__) +#include +static inline void mi_atomic_yield(void) { + _mm_pause(); +} +#elif (defined(__GNUC__) || defined(__clang__)) && \ + (defined(__x86_64__) || defined(__i386__) || defined(__arm__) || defined(__armel__) || defined(__ARMEL__) || \ + defined(__aarch64__) || defined(__powerpc__) || defined(__ppc__) || defined(__PPC__)) || defined(__POWERPC__) +#if defined(__x86_64__) || defined(__i386__) +static inline void mi_atomic_yield(void) { + __asm__ volatile ("pause" ::: "memory"); +} +#elif defined(__aarch64__) +static inline void mi_atomic_yield(void) { + __asm__ volatile("wfe"); +} +#elif (defined(__arm__) && __ARM_ARCH__ >= 7) +static inline void mi_atomic_yield(void) { + __asm__ volatile("yield" ::: "memory"); +} +#elif defined(__powerpc__) || defined(__ppc__) || defined(__PPC__) || defined(__POWERPC__) +#ifdef __APPLE__ +static inline void mi_atomic_yield(void) { + __asm__ volatile ("or r27,r27,r27" ::: "memory"); +} +#else +static inline void mi_atomic_yield(void) { + __asm__ __volatile__ ("or 27,27,27" ::: "memory"); +} +#endif +#elif defined(__armel__) || defined(__ARMEL__) +static inline void mi_atomic_yield(void) { + __asm__ volatile ("nop" ::: "memory"); +} +#endif +#elif defined(__sun) +// Fallback for other archs +#include +static inline void mi_atomic_yield(void) { + smt_pause(); +} +#elif defined(__wasi__) +#include +static inline void mi_atomic_yield(void) { + sched_yield(); +} +#else +#include +static inline void mi_atomic_yield(void) { + sleep(0); +} +#endif + + +#endif // __MIMALLOC_ATOMIC_H diff --git a/Include/internal/mimalloc/mimalloc/internal.h b/Include/internal/mimalloc/mimalloc/internal.h new file mode 100644 index 00000000000000..887bf26c956982 --- /dev/null +++ b/Include/internal/mimalloc/mimalloc/internal.h @@ -0,0 +1,965 @@ +/* ---------------------------------------------------------------------------- +Copyright (c) 2018-2023, Microsoft Research, Daan Leijen +This is free software; you can redistribute it and/or modify it under the +terms of the MIT license. A copy of the license can be found in the file +"LICENSE" at the root of this distribution. +-----------------------------------------------------------------------------*/ +#pragma once +#ifndef MIMALLOC_INTERNAL_H +#define MIMALLOC_INTERNAL_H + + +// -------------------------------------------------------------------------- +// This file contains the interal API's of mimalloc and various utility +// functions and macros. +// -------------------------------------------------------------------------- + +#include "mimalloc/types.h" +#include "mimalloc/track.h" + +#if (MI_DEBUG>0) +#define mi_trace_message(...) _mi_trace_message(__VA_ARGS__) +#else +#define mi_trace_message(...) +#endif + +#if defined(__EMSCRIPTEN__) && !defined(__wasi__) +#define __wasi__ +#endif + +#if defined(__cplusplus) +#define mi_decl_externc extern "C" +#else +#define mi_decl_externc +#endif + +// pthreads +#if !defined(_WIN32) && !defined(__wasi__) +#define MI_USE_PTHREADS +#include +#endif + +// "options.c" +void _mi_fputs(mi_output_fun* out, void* arg, const char* prefix, const char* message); +void _mi_fprintf(mi_output_fun* out, void* arg, const char* fmt, ...); +void _mi_warning_message(const char* fmt, ...); +void _mi_verbose_message(const char* fmt, ...); +void _mi_trace_message(const char* fmt, ...); +void _mi_options_init(void); +void _mi_error_message(int err, const char* fmt, ...); + +// random.c +void _mi_random_init(mi_random_ctx_t* ctx); +void _mi_random_init_weak(mi_random_ctx_t* ctx); +void _mi_random_reinit_if_weak(mi_random_ctx_t * ctx); +void _mi_random_split(mi_random_ctx_t* ctx, mi_random_ctx_t* new_ctx); +uintptr_t _mi_random_next(mi_random_ctx_t* ctx); +uintptr_t _mi_heap_random_next(mi_heap_t* heap); +uintptr_t _mi_os_random_weak(uintptr_t extra_seed); +static inline uintptr_t _mi_random_shuffle(uintptr_t x); + +// init.c +extern mi_decl_cache_align mi_stats_t _mi_stats_main; +extern mi_decl_cache_align const mi_page_t _mi_page_empty; +bool _mi_is_main_thread(void); +size_t _mi_current_thread_count(void); +bool _mi_preloading(void); // true while the C runtime is not initialized yet +mi_threadid_t _mi_thread_id(void) mi_attr_noexcept; +mi_heap_t* _mi_heap_main_get(void); // statically allocated main backing heap +void _mi_thread_done(mi_heap_t* heap); +void _mi_thread_data_collect(void); +void _mi_tld_init(mi_tld_t* tld, mi_heap_t* bheap); + +// os.c +void _mi_os_init(void); // called from process init +void* _mi_os_alloc(size_t size, mi_memid_t* memid, mi_stats_t* stats); +void _mi_os_free(void* p, size_t size, mi_memid_t memid, mi_stats_t* stats); +void _mi_os_free_ex(void* p, size_t size, bool still_committed, mi_memid_t memid, mi_stats_t* stats); + +size_t _mi_os_page_size(void); +size_t _mi_os_good_alloc_size(size_t size); +bool _mi_os_has_overcommit(void); +bool _mi_os_has_virtual_reserve(void); + +bool _mi_os_purge(void* p, size_t size, mi_stats_t* stats); +bool _mi_os_reset(void* addr, size_t size, mi_stats_t* tld_stats); +bool _mi_os_commit(void* p, size_t size, bool* is_zero, mi_stats_t* stats); +bool _mi_os_decommit(void* addr, size_t size, mi_stats_t* stats); +bool _mi_os_protect(void* addr, size_t size); +bool _mi_os_unprotect(void* addr, size_t size); +bool _mi_os_purge(void* p, size_t size, mi_stats_t* stats); +bool _mi_os_purge_ex(void* p, size_t size, bool allow_reset, mi_stats_t* stats); + +void* _mi_os_alloc_aligned(size_t size, size_t alignment, bool commit, bool allow_large, mi_memid_t* memid, mi_stats_t* stats); +void* _mi_os_alloc_aligned_at_offset(size_t size, size_t alignment, size_t align_offset, bool commit, bool allow_large, mi_memid_t* memid, mi_stats_t* tld_stats); + +void* _mi_os_get_aligned_hint(size_t try_alignment, size_t size); +bool _mi_os_use_large_page(size_t size, size_t alignment); +size_t _mi_os_large_page_size(void); + +void* _mi_os_alloc_huge_os_pages(size_t pages, int numa_node, mi_msecs_t max_secs, size_t* pages_reserved, size_t* psize, mi_memid_t* memid); + +// arena.c +mi_arena_id_t _mi_arena_id_none(void); +void _mi_arena_free(void* p, size_t size, size_t still_committed_size, mi_memid_t memid, mi_stats_t* stats); +void* _mi_arena_alloc(size_t size, bool commit, bool allow_large, mi_arena_id_t req_arena_id, mi_memid_t* memid, mi_os_tld_t* tld); +void* _mi_arena_alloc_aligned(size_t size, size_t alignment, size_t align_offset, bool commit, bool allow_large, mi_arena_id_t req_arena_id, mi_memid_t* memid, mi_os_tld_t* tld); +bool _mi_arena_memid_is_suitable(mi_memid_t memid, mi_arena_id_t request_arena_id); +bool _mi_arena_contains(const void* p); +void _mi_arena_collect(bool force_purge, mi_stats_t* stats); +void _mi_arena_unsafe_destroy_all(mi_stats_t* stats); + +// "segment-map.c" +void _mi_segment_map_allocated_at(const mi_segment_t* segment); +void _mi_segment_map_freed_at(const mi_segment_t* segment); + +// "segment.c" +extern mi_abandoned_pool_t _mi_abandoned_default; // global abandoned pool +mi_page_t* _mi_segment_page_alloc(mi_heap_t* heap, size_t block_size, size_t page_alignment, mi_segments_tld_t* tld, mi_os_tld_t* os_tld); +void _mi_segment_page_free(mi_page_t* page, bool force, mi_segments_tld_t* tld); +void _mi_segment_page_abandon(mi_page_t* page, mi_segments_tld_t* tld); +bool _mi_segment_try_reclaim_abandoned( mi_heap_t* heap, bool try_all, mi_segments_tld_t* tld); +void _mi_segment_thread_collect(mi_segments_tld_t* tld); + +#if MI_HUGE_PAGE_ABANDON +void _mi_segment_huge_page_free(mi_segment_t* segment, mi_page_t* page, mi_block_t* block); +#else +void _mi_segment_huge_page_reset(mi_segment_t* segment, mi_page_t* page, mi_block_t* block); +#endif + +uint8_t* _mi_segment_page_start(const mi_segment_t* segment, const mi_page_t* page, size_t* page_size); // page start for any page +void _mi_abandoned_reclaim_all(mi_heap_t* heap, mi_segments_tld_t* tld); +void _mi_abandoned_await_readers(mi_abandoned_pool_t *pool); +void _mi_abandoned_collect(mi_heap_t* heap, bool force, mi_segments_tld_t* tld); + +// "page.c" +void* _mi_malloc_generic(mi_heap_t* heap, size_t size, bool zero, size_t huge_alignment) mi_attr_noexcept mi_attr_malloc; + +void _mi_page_retire(mi_page_t* page) mi_attr_noexcept; // free the page if there are no other pages with many free blocks +void _mi_page_unfull(mi_page_t* page); +void _mi_page_free(mi_page_t* page, mi_page_queue_t* pq, bool force); // free the page +void _mi_page_abandon(mi_page_t* page, mi_page_queue_t* pq); // abandon the page, to be picked up by another thread... +void _mi_heap_delayed_free_all(mi_heap_t* heap); +bool _mi_heap_delayed_free_partial(mi_heap_t* heap); +void _mi_heap_collect_retired(mi_heap_t* heap, bool force); + +void _mi_page_use_delayed_free(mi_page_t* page, mi_delayed_t delay, bool override_never); +bool _mi_page_try_use_delayed_free(mi_page_t* page, mi_delayed_t delay, bool override_never); +size_t _mi_page_queue_append(mi_heap_t* heap, mi_page_queue_t* pq, mi_page_queue_t* append); +void _mi_deferred_free(mi_heap_t* heap, bool force); + +void _mi_page_free_collect(mi_page_t* page,bool force); +void _mi_page_reclaim(mi_heap_t* heap, mi_page_t* page); // callback from segments + +size_t _mi_bin_size(uint8_t bin); // for stats +uint8_t _mi_bin(size_t size); // for stats + +// "heap.c" +void _mi_heap_init_ex(mi_heap_t* heap, mi_tld_t* tld, mi_arena_id_t arena_id, bool no_reclaim, uint8_t tag); +void _mi_heap_destroy_pages(mi_heap_t* heap); +void _mi_heap_collect_abandon(mi_heap_t* heap); +void _mi_heap_set_default_direct(mi_heap_t* heap); +bool _mi_heap_memid_is_suitable(mi_heap_t* heap, mi_memid_t memid); +void _mi_heap_unsafe_destroy_all(void); + +// "stats.c" +void _mi_stats_done(mi_stats_t* stats); +mi_msecs_t _mi_clock_now(void); +mi_msecs_t _mi_clock_end(mi_msecs_t start); +mi_msecs_t _mi_clock_start(void); + +// "alloc.c" +void* _mi_page_malloc(mi_heap_t* heap, mi_page_t* page, size_t size, bool zero) mi_attr_noexcept; // called from `_mi_malloc_generic` +void* _mi_heap_malloc_zero(mi_heap_t* heap, size_t size, bool zero) mi_attr_noexcept; +void* _mi_heap_malloc_zero_ex(mi_heap_t* heap, size_t size, bool zero, size_t huge_alignment) mi_attr_noexcept; // called from `_mi_heap_malloc_aligned` +void* _mi_heap_realloc_zero(mi_heap_t* heap, void* p, size_t newsize, bool zero) mi_attr_noexcept; +mi_block_t* _mi_page_ptr_unalign(const mi_segment_t* segment, const mi_page_t* page, const void* p); +bool _mi_free_delayed_block(mi_block_t* block); +void _mi_free_generic(const mi_segment_t* segment, mi_page_t* page, bool is_local, void* p) mi_attr_noexcept; // for runtime integration +void _mi_padding_shrink(const mi_page_t* page, const mi_block_t* block, const size_t min_size); + +// option.c, c primitives +char _mi_toupper(char c); +int _mi_strnicmp(const char* s, const char* t, size_t n); +void _mi_strlcpy(char* dest, const char* src, size_t dest_size); +void _mi_strlcat(char* dest, const char* src, size_t dest_size); +size_t _mi_strlen(const char* s); +size_t _mi_strnlen(const char* s, size_t max_len); + + +#if MI_DEBUG>1 +bool _mi_page_is_valid(mi_page_t* page); +#endif + + +// ------------------------------------------------------ +// Branches +// ------------------------------------------------------ + +#if defined(__GNUC__) || defined(__clang__) +#define mi_unlikely(x) (__builtin_expect(!!(x),false)) +#define mi_likely(x) (__builtin_expect(!!(x),true)) +#elif (defined(__cplusplus) && (__cplusplus >= 202002L)) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L) +#define mi_unlikely(x) (x) [[unlikely]] +#define mi_likely(x) (x) [[likely]] +#else +#define mi_unlikely(x) (x) +#define mi_likely(x) (x) +#endif + +#ifndef __has_builtin +#define __has_builtin(x) 0 +#endif + + +/* ----------------------------------------------------------- + Error codes passed to `_mi_fatal_error` + All are recoverable but EFAULT is a serious error and aborts by default in secure mode. + For portability define undefined error codes using common Unix codes: + +----------------------------------------------------------- */ +#include +#ifndef EAGAIN // double free +#define EAGAIN (11) +#endif +#ifndef ENOMEM // out of memory +#define ENOMEM (12) +#endif +#ifndef EFAULT // corrupted free-list or meta-data +#define EFAULT (14) +#endif +#ifndef EINVAL // trying to free an invalid pointer +#define EINVAL (22) +#endif +#ifndef EOVERFLOW // count*size overflow +#define EOVERFLOW (75) +#endif + + +/* ----------------------------------------------------------- + Inlined definitions +----------------------------------------------------------- */ +#define MI_UNUSED(x) (void)(x) +#if (MI_DEBUG>0) +#define MI_UNUSED_RELEASE(x) +#else +#define MI_UNUSED_RELEASE(x) MI_UNUSED(x) +#endif + +#define MI_INIT4(x) x(),x(),x(),x() +#define MI_INIT8(x) MI_INIT4(x),MI_INIT4(x) +#define MI_INIT16(x) MI_INIT8(x),MI_INIT8(x) +#define MI_INIT32(x) MI_INIT16(x),MI_INIT16(x) +#define MI_INIT64(x) MI_INIT32(x),MI_INIT32(x) +#define MI_INIT128(x) MI_INIT64(x),MI_INIT64(x) +#define MI_INIT256(x) MI_INIT128(x),MI_INIT128(x) + + +#include +// initialize a local variable to zero; use memset as compilers optimize constant sized memset's +#define _mi_memzero_var(x) memset(&x,0,sizeof(x)) + +// Is `x` a power of two? (0 is considered a power of two) +static inline bool _mi_is_power_of_two(uintptr_t x) { + return ((x & (x - 1)) == 0); +} + +// Is a pointer aligned? +static inline bool _mi_is_aligned(void* p, size_t alignment) { + mi_assert_internal(alignment != 0); + return (((uintptr_t)p % alignment) == 0); +} + +// Align upwards +static inline uintptr_t _mi_align_up(uintptr_t sz, size_t alignment) { + mi_assert_internal(alignment != 0); + uintptr_t mask = alignment - 1; + if ((alignment & mask) == 0) { // power of two? + return ((sz + mask) & ~mask); + } + else { + return (((sz + mask)/alignment)*alignment); + } +} + +// Align downwards +static inline uintptr_t _mi_align_down(uintptr_t sz, size_t alignment) { + mi_assert_internal(alignment != 0); + uintptr_t mask = alignment - 1; + if ((alignment & mask) == 0) { // power of two? + return (sz & ~mask); + } + else { + return ((sz / alignment) * alignment); + } +} + +// Divide upwards: `s <= _mi_divide_up(s,d)*d < s+d`. +static inline uintptr_t _mi_divide_up(uintptr_t size, size_t divider) { + mi_assert_internal(divider != 0); + return (divider == 0 ? size : ((size + divider - 1) / divider)); +} + +// Is memory zero initialized? +static inline bool mi_mem_is_zero(const void* p, size_t size) { + for (size_t i = 0; i < size; i++) { + if (((uint8_t*)p)[i] != 0) return false; + } + return true; +} + + +// Align a byte size to a size in _machine words_, +// i.e. byte size == `wsize*sizeof(void*)`. +static inline size_t _mi_wsize_from_size(size_t size) { + mi_assert_internal(size <= SIZE_MAX - sizeof(uintptr_t)); + return (size + sizeof(uintptr_t) - 1) / sizeof(uintptr_t); +} + +// Overflow detecting multiply +#if __has_builtin(__builtin_umul_overflow) || (defined(__GNUC__) && (__GNUC__ >= 5)) +#include // UINT_MAX, ULONG_MAX +#if defined(_CLOCK_T) // for Illumos +#undef _CLOCK_T +#endif +static inline bool mi_mul_overflow(size_t count, size_t size, size_t* total) { + #if (SIZE_MAX == ULONG_MAX) + return __builtin_umull_overflow(count, size, (unsigned long *)total); + #elif (SIZE_MAX == UINT_MAX) + return __builtin_umul_overflow(count, size, (unsigned int *)total); + #else + return __builtin_umulll_overflow(count, size, (unsigned long long *)total); + #endif +} +#else /* __builtin_umul_overflow is unavailable */ +static inline bool mi_mul_overflow(size_t count, size_t size, size_t* total) { + #define MI_MUL_NO_OVERFLOW ((size_t)1 << (4*sizeof(size_t))) // sqrt(SIZE_MAX) + *total = count * size; + // note: gcc/clang optimize this to directly check the overflow flag + return ((size >= MI_MUL_NO_OVERFLOW || count >= MI_MUL_NO_OVERFLOW) && size > 0 && (SIZE_MAX / size) < count); +} +#endif + +// Safe multiply `count*size` into `total`; return `true` on overflow. +static inline bool mi_count_size_overflow(size_t count, size_t size, size_t* total) { + if (count==1) { // quick check for the case where count is one (common for C++ allocators) + *total = size; + return false; + } + else if mi_unlikely(mi_mul_overflow(count, size, total)) { + #if MI_DEBUG > 0 + _mi_error_message(EOVERFLOW, "allocation request is too large (%zu * %zu bytes)\n", count, size); + #endif + *total = SIZE_MAX; + return true; + } + else return false; +} + + +/*---------------------------------------------------------------------------------------- + Heap functions +------------------------------------------------------------------------------------------- */ + +extern const mi_heap_t _mi_heap_empty; // read-only empty heap, initial value of the thread local default heap + +static inline bool mi_heap_is_backing(const mi_heap_t* heap) { + return (heap->tld->heap_backing == heap); +} + +static inline bool mi_heap_is_initialized(mi_heap_t* heap) { + mi_assert_internal(heap != NULL); + return (heap != &_mi_heap_empty); +} + +static inline uintptr_t _mi_ptr_cookie(const void* p) { + extern mi_heap_t _mi_heap_main; + mi_assert_internal(_mi_heap_main.cookie != 0); + return ((uintptr_t)p ^ _mi_heap_main.cookie); +} + +/* ----------------------------------------------------------- + Pages +----------------------------------------------------------- */ + +static inline mi_page_t* _mi_heap_get_free_small_page(mi_heap_t* heap, size_t size) { + mi_assert_internal(size <= (MI_SMALL_SIZE_MAX + MI_PADDING_SIZE)); + const size_t idx = _mi_wsize_from_size(size); + mi_assert_internal(idx < MI_PAGES_DIRECT); + return heap->pages_free_direct[idx]; +} + +// Segment that contains the pointer +// Large aligned blocks may be aligned at N*MI_SEGMENT_SIZE (inside a huge segment > MI_SEGMENT_SIZE), +// and we need align "down" to the segment info which is `MI_SEGMENT_SIZE` bytes before it; +// therefore we align one byte before `p`. +static inline mi_segment_t* _mi_ptr_segment(const void* p) { + mi_assert_internal(p != NULL); + return (mi_segment_t*)(((uintptr_t)p - 1) & ~MI_SEGMENT_MASK); +} + +static inline mi_page_t* mi_slice_to_page(mi_slice_t* s) { + mi_assert_internal(s->slice_offset== 0 && s->slice_count > 0); + return (mi_page_t*)(s); +} + +static inline mi_slice_t* mi_page_to_slice(mi_page_t* p) { + mi_assert_internal(p->slice_offset== 0 && p->slice_count > 0); + return (mi_slice_t*)(p); +} + +// Segment belonging to a page +static inline mi_segment_t* _mi_page_segment(const mi_page_t* page) { + mi_segment_t* segment = _mi_ptr_segment(page); + mi_assert_internal(segment == NULL || ((mi_slice_t*)page >= segment->slices && (mi_slice_t*)page < segment->slices + segment->slice_entries)); + return segment; +} + +static inline mi_slice_t* mi_slice_first(const mi_slice_t* slice) { + mi_slice_t* start = (mi_slice_t*)((uint8_t*)slice - slice->slice_offset); + mi_assert_internal(start >= _mi_ptr_segment(slice)->slices); + mi_assert_internal(start->slice_offset == 0); + mi_assert_internal(start + start->slice_count > slice); + return start; +} + +// Get the page containing the pointer (performance critical as it is called in mi_free) +static inline mi_page_t* _mi_segment_page_of(const mi_segment_t* segment, const void* p) { + mi_assert_internal(p > (void*)segment); + ptrdiff_t diff = (uint8_t*)p - (uint8_t*)segment; + mi_assert_internal(diff > 0 && diff <= (ptrdiff_t)MI_SEGMENT_SIZE); + size_t idx = (size_t)diff >> MI_SEGMENT_SLICE_SHIFT; + mi_assert_internal(idx <= segment->slice_entries); + mi_slice_t* slice0 = (mi_slice_t*)&segment->slices[idx]; + mi_slice_t* slice = mi_slice_first(slice0); // adjust to the block that holds the page data + mi_assert_internal(slice->slice_offset == 0); + mi_assert_internal(slice >= segment->slices && slice < segment->slices + segment->slice_entries); + return mi_slice_to_page(slice); +} + +// Quick page start for initialized pages +static inline uint8_t* _mi_page_start(const mi_segment_t* segment, const mi_page_t* page, size_t* page_size) { + return _mi_segment_page_start(segment, page, page_size); +} + +// Get the page containing the pointer +static inline mi_page_t* _mi_ptr_page(void* p) { + return _mi_segment_page_of(_mi_ptr_segment(p), p); +} + +// Get the block size of a page (special case for huge objects) +static inline size_t mi_page_block_size(const mi_page_t* page) { + const size_t bsize = page->xblock_size; + mi_assert_internal(bsize > 0); + if mi_likely(bsize < MI_HUGE_BLOCK_SIZE) { + return bsize; + } + else { + size_t psize; + _mi_segment_page_start(_mi_page_segment(page), page, &psize); + return psize; + } +} + +static inline bool mi_page_is_huge(const mi_page_t* page) { + return (_mi_page_segment(page)->kind == MI_SEGMENT_HUGE); +} + +// Get the usable block size of a page without fixed padding. +// This may still include internal padding due to alignment and rounding up size classes. +static inline size_t mi_page_usable_block_size(const mi_page_t* page) { + return mi_page_block_size(page) - MI_PADDING_SIZE; +} + +// size of a segment +static inline size_t mi_segment_size(mi_segment_t* segment) { + return segment->segment_slices * MI_SEGMENT_SLICE_SIZE; +} + +static inline uint8_t* mi_segment_end(mi_segment_t* segment) { + return (uint8_t*)segment + mi_segment_size(segment); +} + +// Thread free access +static inline mi_block_t* mi_page_thread_free(const mi_page_t* page) { + return (mi_block_t*)(mi_atomic_load_relaxed(&((mi_page_t*)page)->xthread_free) & ~3); +} + +static inline mi_delayed_t mi_page_thread_free_flag(const mi_page_t* page) { + return (mi_delayed_t)(mi_atomic_load_relaxed(&((mi_page_t*)page)->xthread_free) & 3); +} + +// Heap access +static inline mi_heap_t* mi_page_heap(const mi_page_t* page) { + return (mi_heap_t*)(mi_atomic_load_relaxed(&((mi_page_t*)page)->xheap)); +} + +static inline void mi_page_set_heap(mi_page_t* page, mi_heap_t* heap) { + mi_assert_internal(mi_page_thread_free_flag(page) != MI_DELAYED_FREEING); + mi_atomic_store_release(&page->xheap,(uintptr_t)heap); +} + +// Thread free flag helpers +static inline mi_block_t* mi_tf_block(mi_thread_free_t tf) { + return (mi_block_t*)(tf & ~0x03); +} +static inline mi_delayed_t mi_tf_delayed(mi_thread_free_t tf) { + return (mi_delayed_t)(tf & 0x03); +} +static inline mi_thread_free_t mi_tf_make(mi_block_t* block, mi_delayed_t delayed) { + return (mi_thread_free_t)((uintptr_t)block | (uintptr_t)delayed); +} +static inline mi_thread_free_t mi_tf_set_delayed(mi_thread_free_t tf, mi_delayed_t delayed) { + return mi_tf_make(mi_tf_block(tf),delayed); +} +static inline mi_thread_free_t mi_tf_set_block(mi_thread_free_t tf, mi_block_t* block) { + return mi_tf_make(block, mi_tf_delayed(tf)); +} + +// are all blocks in a page freed? +// note: needs up-to-date used count, (as the `xthread_free` list may not be empty). see `_mi_page_collect_free`. +static inline bool mi_page_all_free(const mi_page_t* page) { + mi_assert_internal(page != NULL); + return (page->used == 0); +} + +// are there any available blocks? +static inline bool mi_page_has_any_available(const mi_page_t* page) { + mi_assert_internal(page != NULL && page->reserved > 0); + return (page->used < page->reserved || (mi_page_thread_free(page) != NULL)); +} + +// are there immediately available blocks, i.e. blocks available on the free list. +static inline bool mi_page_immediate_available(const mi_page_t* page) { + mi_assert_internal(page != NULL); + return (page->free != NULL); +} + +// is more than 7/8th of a page in use? +static inline bool mi_page_mostly_used(const mi_page_t* page) { + if (page==NULL) return true; + uint16_t frac = page->reserved / 8U; + return (page->reserved - page->used <= frac); +} + +static inline mi_page_queue_t* mi_page_queue(const mi_heap_t* heap, size_t size) { + return &((mi_heap_t*)heap)->pages[_mi_bin(size)]; +} + + + +//----------------------------------------------------------- +// Page flags +//----------------------------------------------------------- +static inline bool mi_page_is_in_full(const mi_page_t* page) { + return page->flags.x.in_full; +} + +static inline void mi_page_set_in_full(mi_page_t* page, bool in_full) { + page->flags.x.in_full = in_full; +} + +static inline bool mi_page_has_aligned(const mi_page_t* page) { + return page->flags.x.has_aligned; +} + +static inline void mi_page_set_has_aligned(mi_page_t* page, bool has_aligned) { + page->flags.x.has_aligned = has_aligned; +} + + +/* ------------------------------------------------------------------- +Encoding/Decoding the free list next pointers + +This is to protect against buffer overflow exploits where the +free list is mutated. Many hardened allocators xor the next pointer `p` +with a secret key `k1`, as `p^k1`. This prevents overwriting with known +values but might be still too weak: if the attacker can guess +the pointer `p` this can reveal `k1` (since `p^k1^p == k1`). +Moreover, if multiple blocks can be read as well, the attacker can +xor both as `(p1^k1) ^ (p2^k1) == p1^p2` which may reveal a lot +about the pointers (and subsequently `k1`). + +Instead mimalloc uses an extra key `k2` and encodes as `((p^k2)<<> (MI_INTPTR_BITS - shift)))); +} +static inline uintptr_t mi_rotr(uintptr_t x, uintptr_t shift) { + shift %= MI_INTPTR_BITS; + return (shift==0 ? x : ((x >> shift) | (x << (MI_INTPTR_BITS - shift)))); +} + +static inline void* mi_ptr_decode(const void* null, const mi_encoded_t x, const uintptr_t* keys) { + void* p = (void*)(mi_rotr(x - keys[0], keys[0]) ^ keys[1]); + return (p==null ? NULL : p); +} + +static inline mi_encoded_t mi_ptr_encode(const void* null, const void* p, const uintptr_t* keys) { + uintptr_t x = (uintptr_t)(p==NULL ? null : p); + return mi_rotl(x ^ keys[1], keys[0]) + keys[0]; +} + +static inline mi_block_t* mi_block_nextx( const void* null, const mi_block_t* block, const uintptr_t* keys ) { + mi_track_mem_defined(block,sizeof(mi_block_t)); + mi_block_t* next; + #ifdef MI_ENCODE_FREELIST + next = (mi_block_t*)mi_ptr_decode(null, block->next, keys); + #else + MI_UNUSED(keys); MI_UNUSED(null); + next = (mi_block_t*)block->next; + #endif + mi_track_mem_noaccess(block,sizeof(mi_block_t)); + return next; +} + +static inline void mi_block_set_nextx(const void* null, mi_block_t* block, const mi_block_t* next, const uintptr_t* keys) { + mi_track_mem_undefined(block,sizeof(mi_block_t)); + #ifdef MI_ENCODE_FREELIST + block->next = mi_ptr_encode(null, next, keys); + #else + MI_UNUSED(keys); MI_UNUSED(null); + block->next = (mi_encoded_t)next; + #endif + mi_track_mem_noaccess(block,sizeof(mi_block_t)); +} + +static inline mi_block_t* mi_block_next(const mi_page_t* page, const mi_block_t* block) { + #ifdef MI_ENCODE_FREELIST + mi_block_t* next = mi_block_nextx(page,block,page->keys); + // check for free list corruption: is `next` at least in the same page? + // TODO: check if `next` is `page->block_size` aligned? + if mi_unlikely(next!=NULL && !mi_is_in_same_page(block, next)) { + _mi_error_message(EFAULT, "corrupted free list entry of size %zub at %p: value 0x%zx\n", mi_page_block_size(page), block, (uintptr_t)next); + next = NULL; + } + return next; + #else + MI_UNUSED(page); + return mi_block_nextx(page,block,NULL); + #endif +} + +static inline void mi_block_set_next(const mi_page_t* page, mi_block_t* block, const mi_block_t* next) { + #ifdef MI_ENCODE_FREELIST + mi_block_set_nextx(page,block,next, page->keys); + #else + MI_UNUSED(page); + mi_block_set_nextx(page,block,next,NULL); + #endif +} + + +// ------------------------------------------------------------------- +// commit mask +// ------------------------------------------------------------------- + +static inline void mi_commit_mask_create_empty(mi_commit_mask_t* cm) { + for (size_t i = 0; i < MI_COMMIT_MASK_FIELD_COUNT; i++) { + cm->mask[i] = 0; + } +} + +static inline void mi_commit_mask_create_full(mi_commit_mask_t* cm) { + for (size_t i = 0; i < MI_COMMIT_MASK_FIELD_COUNT; i++) { + cm->mask[i] = ~((size_t)0); + } +} + +static inline bool mi_commit_mask_is_empty(const mi_commit_mask_t* cm) { + for (size_t i = 0; i < MI_COMMIT_MASK_FIELD_COUNT; i++) { + if (cm->mask[i] != 0) return false; + } + return true; +} + +static inline bool mi_commit_mask_is_full(const mi_commit_mask_t* cm) { + for (size_t i = 0; i < MI_COMMIT_MASK_FIELD_COUNT; i++) { + if (cm->mask[i] != ~((size_t)0)) return false; + } + return true; +} + +// defined in `segment.c`: +size_t _mi_commit_mask_committed_size(const mi_commit_mask_t* cm, size_t total); +size_t _mi_commit_mask_next_run(const mi_commit_mask_t* cm, size_t* idx); + +#define mi_commit_mask_foreach(cm,idx,count) \ + idx = 0; \ + while ((count = _mi_commit_mask_next_run(cm,&idx)) > 0) { + +#define mi_commit_mask_foreach_end() \ + idx += count; \ + } + + + +/* ----------------------------------------------------------- + memory id's +----------------------------------------------------------- */ + +static inline mi_memid_t _mi_memid_create(mi_memkind_t memkind) { + mi_memid_t memid; + _mi_memzero_var(memid); + memid.memkind = memkind; + return memid; +} + +static inline mi_memid_t _mi_memid_none(void) { + return _mi_memid_create(MI_MEM_NONE); +} + +static inline mi_memid_t _mi_memid_create_os(bool committed, bool is_zero, bool is_large) { + mi_memid_t memid = _mi_memid_create(MI_MEM_OS); + memid.initially_committed = committed; + memid.initially_zero = is_zero; + memid.is_pinned = is_large; + return memid; +} + + +// ------------------------------------------------------------------- +// Fast "random" shuffle +// ------------------------------------------------------------------- + +static inline uintptr_t _mi_random_shuffle(uintptr_t x) { + if (x==0) { x = 17; } // ensure we don't get stuck in generating zeros +#if (MI_INTPTR_SIZE==8) + // by Sebastiano Vigna, see: + x ^= x >> 30; + x *= 0xbf58476d1ce4e5b9UL; + x ^= x >> 27; + x *= 0x94d049bb133111ebUL; + x ^= x >> 31; +#elif (MI_INTPTR_SIZE==4) + // by Chris Wellons, see: + x ^= x >> 16; + x *= 0x7feb352dUL; + x ^= x >> 15; + x *= 0x846ca68bUL; + x ^= x >> 16; +#endif + return x; +} + +// ------------------------------------------------------------------- +// Optimize numa node access for the common case (= one node) +// ------------------------------------------------------------------- + +int _mi_os_numa_node_get(mi_os_tld_t* tld); +size_t _mi_os_numa_node_count_get(void); + +extern _Atomic(size_t) _mi_numa_node_count; +static inline int _mi_os_numa_node(mi_os_tld_t* tld) { + if mi_likely(mi_atomic_load_relaxed(&_mi_numa_node_count) == 1) { return 0; } + else return _mi_os_numa_node_get(tld); +} +static inline size_t _mi_os_numa_node_count(void) { + const size_t count = mi_atomic_load_relaxed(&_mi_numa_node_count); + if mi_likely(count > 0) { return count; } + else return _mi_os_numa_node_count_get(); +} + + + +// ----------------------------------------------------------------------- +// Count bits: trailing or leading zeros (with MI_INTPTR_BITS on all zero) +// ----------------------------------------------------------------------- + +#if defined(__GNUC__) + +#include // LONG_MAX +#define MI_HAVE_FAST_BITSCAN +static inline size_t mi_clz(uintptr_t x) { + if (x==0) return MI_INTPTR_BITS; +#if (INTPTR_MAX == LONG_MAX) + return __builtin_clzl(x); +#else + return __builtin_clzll(x); +#endif +} +static inline size_t mi_ctz(uintptr_t x) { + if (x==0) return MI_INTPTR_BITS; +#if (INTPTR_MAX == LONG_MAX) + return __builtin_ctzl(x); +#else + return __builtin_ctzll(x); +#endif +} + +#elif defined(_MSC_VER) + +#include // LONG_MAX +#include // BitScanReverse64 +#define MI_HAVE_FAST_BITSCAN +static inline size_t mi_clz(uintptr_t x) { + if (x==0) return MI_INTPTR_BITS; + unsigned long idx; +#if (INTPTR_MAX == LONG_MAX) + _BitScanReverse(&idx, x); +#else + _BitScanReverse64(&idx, x); +#endif + return ((MI_INTPTR_BITS - 1) - idx); +} +static inline size_t mi_ctz(uintptr_t x) { + if (x==0) return MI_INTPTR_BITS; + unsigned long idx; +#if (INTPTR_MAX == LONG_MAX) + _BitScanForward(&idx, x); +#else + _BitScanForward64(&idx, x); +#endif + return idx; +} + +#else +static inline size_t mi_ctz32(uint32_t x) { + // de Bruijn multiplication, see + static const unsigned char debruijn[32] = { + 0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8, + 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9 + }; + if (x==0) return 32; + return debruijn[((x & -(int32_t)x) * 0x077CB531UL) >> 27]; +} +static inline size_t mi_clz32(uint32_t x) { + // de Bruijn multiplication, see + static const uint8_t debruijn[32] = { + 31, 22, 30, 21, 18, 10, 29, 2, 20, 17, 15, 13, 9, 6, 28, 1, + 23, 19, 11, 3, 16, 14, 7, 24, 12, 4, 8, 25, 5, 26, 27, 0 + }; + if (x==0) return 32; + x |= x >> 1; + x |= x >> 2; + x |= x >> 4; + x |= x >> 8; + x |= x >> 16; + return debruijn[(uint32_t)(x * 0x07C4ACDDUL) >> 27]; +} + +static inline size_t mi_clz(uintptr_t x) { + if (x==0) return MI_INTPTR_BITS; +#if (MI_INTPTR_BITS <= 32) + return mi_clz32((uint32_t)x); +#else + size_t count = mi_clz32((uint32_t)(x >> 32)); + if (count < 32) return count; + return (32 + mi_clz32((uint32_t)x)); +#endif +} +static inline size_t mi_ctz(uintptr_t x) { + if (x==0) return MI_INTPTR_BITS; +#if (MI_INTPTR_BITS <= 32) + return mi_ctz32((uint32_t)x); +#else + size_t count = mi_ctz32((uint32_t)x); + if (count < 32) return count; + return (32 + mi_ctz32((uint32_t)(x>>32))); +#endif +} + +#endif + +// "bit scan reverse": Return index of the highest bit (or MI_INTPTR_BITS if `x` is zero) +static inline size_t mi_bsr(uintptr_t x) { + return (x==0 ? MI_INTPTR_BITS : MI_INTPTR_BITS - 1 - mi_clz(x)); +} + + +// --------------------------------------------------------------------------------- +// Provide our own `_mi_memcpy` for potential performance optimizations. +// +// For now, only on Windows with msvc/clang-cl we optimize to `rep movsb` if +// we happen to run on x86/x64 cpu's that have "fast short rep movsb" (FSRM) support +// (AMD Zen3+ (~2020) or Intel Ice Lake+ (~2017). See also issue #201 and pr #253. +// --------------------------------------------------------------------------------- + +#if !MI_TRACK_ENABLED && defined(_WIN32) && (defined(_M_IX86) || defined(_M_X64)) +#include +extern bool _mi_cpu_has_fsrm; +static inline void _mi_memcpy(void* dst, const void* src, size_t n) { + if (_mi_cpu_has_fsrm) { + __movsb((unsigned char*)dst, (const unsigned char*)src, n); + } + else { + memcpy(dst, src, n); + } +} +static inline void _mi_memzero(void* dst, size_t n) { + if (_mi_cpu_has_fsrm) { + __stosb((unsigned char*)dst, 0, n); + } + else { + memset(dst, 0, n); + } +} +#else +static inline void _mi_memcpy(void* dst, const void* src, size_t n) { + memcpy(dst, src, n); +} +static inline void _mi_memzero(void* dst, size_t n) { + memset(dst, 0, n); +} +#endif + +// ------------------------------------------------------------------------------- +// The `_mi_memcpy_aligned` can be used if the pointers are machine-word aligned +// This is used for example in `mi_realloc`. +// ------------------------------------------------------------------------------- + +#if (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__) +// On GCC/CLang we provide a hint that the pointers are word aligned. +static inline void _mi_memcpy_aligned(void* dst, const void* src, size_t n) { + mi_assert_internal(((uintptr_t)dst % MI_INTPTR_SIZE == 0) && ((uintptr_t)src % MI_INTPTR_SIZE == 0)); + void* adst = __builtin_assume_aligned(dst, MI_INTPTR_SIZE); + const void* asrc = __builtin_assume_aligned(src, MI_INTPTR_SIZE); + _mi_memcpy(adst, asrc, n); +} + +static inline void _mi_memzero_aligned(void* dst, size_t n) { + mi_assert_internal((uintptr_t)dst % MI_INTPTR_SIZE == 0); + void* adst = __builtin_assume_aligned(dst, MI_INTPTR_SIZE); + _mi_memzero(adst, n); +} +#else +// Default fallback on `_mi_memcpy` +static inline void _mi_memcpy_aligned(void* dst, const void* src, size_t n) { + mi_assert_internal(((uintptr_t)dst % MI_INTPTR_SIZE == 0) && ((uintptr_t)src % MI_INTPTR_SIZE == 0)); + _mi_memcpy(dst, src, n); +} + +static inline void _mi_memzero_aligned(void* dst, size_t n) { + mi_assert_internal((uintptr_t)dst % MI_INTPTR_SIZE == 0); + _mi_memzero(dst, n); +} +#endif + + +#endif diff --git a/Include/internal/mimalloc/mimalloc/prim.h b/Include/internal/mimalloc/mimalloc/prim.h new file mode 100644 index 00000000000000..4b9e4dc4194d77 --- /dev/null +++ b/Include/internal/mimalloc/mimalloc/prim.h @@ -0,0 +1,323 @@ +/* ---------------------------------------------------------------------------- +Copyright (c) 2018-2023, Microsoft Research, Daan Leijen +This is free software; you can redistribute it and/or modify it under the +terms of the MIT license. A copy of the license can be found in the file +"LICENSE" at the root of this distribution. +-----------------------------------------------------------------------------*/ +#pragma once +#ifndef MIMALLOC_PRIM_H +#define MIMALLOC_PRIM_H + + +// -------------------------------------------------------------------------- +// This file specifies the primitive portability API. +// Each OS/host needs to implement these primitives, see `src/prim` +// for implementations on Window, macOS, WASI, and Linux/Unix. +// +// note: on all primitive functions, we always have result parameters != NUL, and: +// addr != NULL and page aligned +// size > 0 and page aligned +// return value is an error code an int where 0 is success. +// -------------------------------------------------------------------------- + +// OS memory configuration +typedef struct mi_os_mem_config_s { + size_t page_size; // 4KiB + size_t large_page_size; // 2MiB + size_t alloc_granularity; // smallest allocation size (on Windows 64KiB) + bool has_overcommit; // can we reserve more memory than can be actually committed? + bool must_free_whole; // must allocated blocks be freed as a whole (false for mmap, true for VirtualAlloc) + bool has_virtual_reserve; // supports virtual address space reservation? (if true we can reserve virtual address space without using commit or physical memory) +} mi_os_mem_config_t; + +// Initialize +void _mi_prim_mem_init( mi_os_mem_config_t* config ); + +// Free OS memory +int _mi_prim_free(void* addr, size_t size ); + +// Allocate OS memory. Return NULL on error. +// The `try_alignment` is just a hint and the returned pointer does not have to be aligned. +// If `commit` is false, the virtual memory range only needs to be reserved (with no access) +// which will later be committed explicitly using `_mi_prim_commit`. +// `is_zero` is set to true if the memory was zero initialized (as on most OS's) +// pre: !commit => !allow_large +// try_alignment >= _mi_os_page_size() and a power of 2 +int _mi_prim_alloc(size_t size, size_t try_alignment, bool commit, bool allow_large, bool* is_large, bool* is_zero, void** addr); + +// Commit memory. Returns error code or 0 on success. +// For example, on Linux this would make the memory PROT_READ|PROT_WRITE. +// `is_zero` is set to true if the memory was zero initialized (e.g. on Windows) +int _mi_prim_commit(void* addr, size_t size, bool* is_zero); + +// Decommit memory. Returns error code or 0 on success. The `needs_recommit` result is true +// if the memory would need to be re-committed. For example, on Windows this is always true, +// but on Linux we could use MADV_DONTNEED to decommit which does not need a recommit. +// pre: needs_recommit != NULL +int _mi_prim_decommit(void* addr, size_t size, bool* needs_recommit); + +// Reset memory. The range keeps being accessible but the content might be reset. +// Returns error code or 0 on success. +int _mi_prim_reset(void* addr, size_t size); + +// Protect memory. Returns error code or 0 on success. +int _mi_prim_protect(void* addr, size_t size, bool protect); + +// Allocate huge (1GiB) pages possibly associated with a NUMA node. +// `is_zero` is set to true if the memory was zero initialized (as on most OS's) +// pre: size > 0 and a multiple of 1GiB. +// numa_node is either negative (don't care), or a numa node number. +int _mi_prim_alloc_huge_os_pages(void* hint_addr, size_t size, int numa_node, bool* is_zero, void** addr); + +// Return the current NUMA node +size_t _mi_prim_numa_node(void); + +// Return the number of logical NUMA nodes +size_t _mi_prim_numa_node_count(void); + +// Clock ticks +mi_msecs_t _mi_prim_clock_now(void); + +// Return process information (only for statistics) +typedef struct mi_process_info_s { + mi_msecs_t elapsed; + mi_msecs_t utime; + mi_msecs_t stime; + size_t current_rss; + size_t peak_rss; + size_t current_commit; + size_t peak_commit; + size_t page_faults; +} mi_process_info_t; + +void _mi_prim_process_info(mi_process_info_t* pinfo); + +// Default stderr output. (only for warnings etc. with verbose enabled) +// msg != NULL && _mi_strlen(msg) > 0 +void _mi_prim_out_stderr( const char* msg ); + +// Get an environment variable. (only for options) +// name != NULL, result != NULL, result_size >= 64 +bool _mi_prim_getenv(const char* name, char* result, size_t result_size); + + +// Fill a buffer with strong randomness; return `false` on error or if +// there is no strong randomization available. +bool _mi_prim_random_buf(void* buf, size_t buf_len); + +// Called on the first thread start, and should ensure `_mi_thread_done` is called on thread termination. +void _mi_prim_thread_init_auto_done(void); + +// Called on process exit and may take action to clean up resources associated with the thread auto done. +void _mi_prim_thread_done_auto_done(void); + +// Called when the default heap for a thread changes +void _mi_prim_thread_associate_default_heap(mi_heap_t* heap); + + +//------------------------------------------------------------------- +// Thread id: `_mi_prim_thread_id()` +// +// Getting the thread id should be performant as it is called in the +// fast path of `_mi_free` and we specialize for various platforms as +// inlined definitions. Regular code should call `init.c:_mi_thread_id()`. +// We only require _mi_prim_thread_id() to return a unique id +// for each thread (unequal to zero). +//------------------------------------------------------------------- + +// defined in `init.c`; do not use these directly +extern mi_decl_thread mi_heap_t* _mi_heap_default; // default heap to allocate from +extern bool _mi_process_is_initialized; // has mi_process_init been called? + +static inline mi_threadid_t _mi_prim_thread_id(void) mi_attr_noexcept; + +#if defined(_WIN32) + +#define WIN32_LEAN_AND_MEAN +#include +static inline mi_threadid_t _mi_prim_thread_id(void) mi_attr_noexcept { + // Windows: works on Intel and ARM in both 32- and 64-bit + return (uintptr_t)NtCurrentTeb(); +} + +// We use assembly for a fast thread id on the main platforms. The TLS layout depends on +// both the OS and libc implementation so we use specific tests for each main platform. +// If you test on another platform and it works please send a PR :-) +// see also https://akkadia.org/drepper/tls.pdf for more info on the TLS register. +#elif defined(__GNUC__) && ( \ + (defined(__GLIBC__) && (defined(__x86_64__) || defined(__i386__) || defined(__arm__) || defined(__aarch64__))) \ + || (defined(__APPLE__) && (defined(__x86_64__) || defined(__aarch64__))) \ + || (defined(__BIONIC__) && (defined(__x86_64__) || defined(__i386__) || defined(__arm__) || defined(__aarch64__))) \ + || (defined(__FreeBSD__) && (defined(__x86_64__) || defined(__i386__) || defined(__aarch64__))) \ + || (defined(__OpenBSD__) && (defined(__x86_64__) || defined(__i386__) || defined(__aarch64__))) \ + ) + +static inline void* mi_prim_tls_slot(size_t slot) mi_attr_noexcept { + void* res; + const size_t ofs = (slot*sizeof(void*)); + #if defined(__i386__) + __asm__("movl %%gs:%1, %0" : "=r" (res) : "m" (*((void**)ofs)) : ); // x86 32-bit always uses GS + #elif defined(__APPLE__) && defined(__x86_64__) + __asm__("movq %%gs:%1, %0" : "=r" (res) : "m" (*((void**)ofs)) : ); // x86_64 macOSX uses GS + #elif defined(__x86_64__) && (MI_INTPTR_SIZE==4) + __asm__("movl %%fs:%1, %0" : "=r" (res) : "m" (*((void**)ofs)) : ); // x32 ABI + #elif defined(__x86_64__) + __asm__("movq %%fs:%1, %0" : "=r" (res) : "m" (*((void**)ofs)) : ); // x86_64 Linux, BSD uses FS + #elif defined(__arm__) + void** tcb; MI_UNUSED(ofs); + __asm__ volatile ("mrc p15, 0, %0, c13, c0, 3\nbic %0, %0, #3" : "=r" (tcb)); + res = tcb[slot]; + #elif defined(__aarch64__) + void** tcb; MI_UNUSED(ofs); + #if defined(__APPLE__) // M1, issue #343 + __asm__ volatile ("mrs %0, tpidrro_el0\nbic %0, %0, #7" : "=r" (tcb)); + #else + __asm__ volatile ("mrs %0, tpidr_el0" : "=r" (tcb)); + #endif + res = tcb[slot]; + #endif + return res; +} + +// setting a tls slot is only used on macOS for now +static inline void mi_prim_tls_slot_set(size_t slot, void* value) mi_attr_noexcept { + const size_t ofs = (slot*sizeof(void*)); + #if defined(__i386__) + __asm__("movl %1,%%gs:%0" : "=m" (*((void**)ofs)) : "rn" (value) : ); // 32-bit always uses GS + #elif defined(__APPLE__) && defined(__x86_64__) + __asm__("movq %1,%%gs:%0" : "=m" (*((void**)ofs)) : "rn" (value) : ); // x86_64 macOS uses GS + #elif defined(__x86_64__) && (MI_INTPTR_SIZE==4) + __asm__("movl %1,%%fs:%0" : "=m" (*((void**)ofs)) : "rn" (value) : ); // x32 ABI + #elif defined(__x86_64__) + __asm__("movq %1,%%fs:%0" : "=m" (*((void**)ofs)) : "rn" (value) : ); // x86_64 Linux, BSD uses FS + #elif defined(__arm__) + void** tcb; MI_UNUSED(ofs); + __asm__ volatile ("mrc p15, 0, %0, c13, c0, 3\nbic %0, %0, #3" : "=r" (tcb)); + tcb[slot] = value; + #elif defined(__aarch64__) + void** tcb; MI_UNUSED(ofs); + #if defined(__APPLE__) // M1, issue #343 + __asm__ volatile ("mrs %0, tpidrro_el0\nbic %0, %0, #7" : "=r" (tcb)); + #else + __asm__ volatile ("mrs %0, tpidr_el0" : "=r" (tcb)); + #endif + tcb[slot] = value; + #endif +} + +static inline mi_threadid_t _mi_prim_thread_id(void) mi_attr_noexcept { + #if defined(__BIONIC__) + // issue #384, #495: on the Bionic libc (Android), slot 1 is the thread id + // see: https://github.com/aosp-mirror/platform_bionic/blob/c44b1d0676ded732df4b3b21c5f798eacae93228/libc/platform/bionic/tls_defines.h#L86 + return (uintptr_t)mi_prim_tls_slot(1); + #else + // in all our other targets, slot 0 is the thread id + // glibc: https://sourceware.org/git/?p=glibc.git;a=blob_plain;f=sysdeps/x86_64/nptl/tls.h + // apple: https://github.com/apple/darwin-xnu/blob/main/libsyscall/os/tsd.h#L36 + return (uintptr_t)mi_prim_tls_slot(0); + #endif +} + +#else + +// otherwise use portable C, taking the address of a thread local variable (this is still very fast on most platforms). +static inline mi_threadid_t _mi_prim_thread_id(void) mi_attr_noexcept { + return (uintptr_t)&_mi_heap_default; +} + +#endif + + + +/* ---------------------------------------------------------------------------------------- +The thread local default heap: `_mi_prim_get_default_heap()` +This is inlined here as it is on the fast path for allocation functions. + +On most platforms (Windows, Linux, FreeBSD, NetBSD, etc), this just returns a +__thread local variable (`_mi_heap_default`). With the initial-exec TLS model this ensures +that the storage will always be available (allocated on the thread stacks). + +On some platforms though we cannot use that when overriding `malloc` since the underlying +TLS implementation (or the loader) will call itself `malloc` on a first access and recurse. +We try to circumvent this in an efficient way: +- macOSX : we use an unused TLS slot from the OS allocated slots (MI_TLS_SLOT). On OSX, the + loader itself calls `malloc` even before the modules are initialized. +- OpenBSD: we use an unused slot from the pthread block (MI_TLS_PTHREAD_SLOT_OFS). +- DragonFly: defaults are working but seem slow compared to freeBSD (see PR #323) +------------------------------------------------------------------------------------------- */ + +static inline mi_heap_t* mi_prim_get_default_heap(void); + +#if defined(MI_MALLOC_OVERRIDE) +#if defined(__APPLE__) // macOS + #define MI_TLS_SLOT 89 // seems unused? + // #define MI_TLS_RECURSE_GUARD 1 + // other possible unused ones are 9, 29, __PTK_FRAMEWORK_JAVASCRIPTCORE_KEY4 (94), __PTK_FRAMEWORK_GC_KEY9 (112) and __PTK_FRAMEWORK_OLDGC_KEY9 (89) + // see +#elif defined(__OpenBSD__) + // use end bytes of a name; goes wrong if anyone uses names > 23 characters (ptrhread specifies 16) + // see + #define MI_TLS_PTHREAD_SLOT_OFS (6*sizeof(int) + 4*sizeof(void*) + 24) + // #elif defined(__DragonFly__) + // #warning "mimalloc is not working correctly on DragonFly yet." + // #define MI_TLS_PTHREAD_SLOT_OFS (4 + 1*sizeof(void*)) // offset `uniqueid` (also used by gdb?) +#elif defined(__ANDROID__) + // See issue #381 + #define MI_TLS_PTHREAD +#endif +#endif + + +#if defined(MI_TLS_SLOT) + +static inline mi_heap_t* mi_prim_get_default_heap(void) { + mi_heap_t* heap = (mi_heap_t*)mi_prim_tls_slot(MI_TLS_SLOT); + if mi_unlikely(heap == NULL) { + #ifdef __GNUC__ + __asm(""); // prevent conditional load of the address of _mi_heap_empty + #endif + heap = (mi_heap_t*)&_mi_heap_empty; + } + return heap; +} + +#elif defined(MI_TLS_PTHREAD_SLOT_OFS) + +static inline mi_heap_t** mi_prim_tls_pthread_heap_slot(void) { + pthread_t self = pthread_self(); + #if defined(__DragonFly__) + if (self==NULL) return NULL; + #endif + return (mi_heap_t**)((uint8_t*)self + MI_TLS_PTHREAD_SLOT_OFS); +} + +static inline mi_heap_t* mi_prim_get_default_heap(void) { + mi_heap_t** pheap = mi_prim_tls_pthread_heap_slot(); + if mi_unlikely(pheap == NULL) return _mi_heap_main_get(); + mi_heap_t* heap = *pheap; + if mi_unlikely(heap == NULL) return (mi_heap_t*)&_mi_heap_empty; + return heap; +} + +#elif defined(MI_TLS_PTHREAD) + +extern pthread_key_t _mi_heap_default_key; +static inline mi_heap_t* mi_prim_get_default_heap(void) { + mi_heap_t* heap = (mi_unlikely(_mi_heap_default_key == (pthread_key_t)(-1)) ? _mi_heap_main_get() : (mi_heap_t*)pthread_getspecific(_mi_heap_default_key)); + return (mi_unlikely(heap == NULL) ? (mi_heap_t*)&_mi_heap_empty : heap); +} + +#else // default using a thread local variable; used on most platforms. + +static inline mi_heap_t* mi_prim_get_default_heap(void) { + #if defined(MI_TLS_RECURSE_GUARD) + if (mi_unlikely(!_mi_process_is_initialized)) return _mi_heap_main_get(); + #endif + return _mi_heap_default; +} + +#endif // mi_prim_get_default_heap() + + + +#endif // MIMALLOC_PRIM_H diff --git a/Include/internal/mimalloc/mimalloc/track.h b/Include/internal/mimalloc/mimalloc/track.h new file mode 100644 index 00000000000000..fa1a048d846a9c --- /dev/null +++ b/Include/internal/mimalloc/mimalloc/track.h @@ -0,0 +1,147 @@ +/* ---------------------------------------------------------------------------- +Copyright (c) 2018-2023, Microsoft Research, Daan Leijen +This is free software; you can redistribute it and/or modify it under the +terms of the MIT license. A copy of the license can be found in the file +"LICENSE" at the root of this distribution. +-----------------------------------------------------------------------------*/ +#pragma once +#ifndef MIMALLOC_TRACK_H +#define MIMALLOC_TRACK_H + +/* ------------------------------------------------------------------------------------------------------ +Track memory ranges with macros for tools like Valgrind address sanitizer, or other memory checkers. +These can be defined for tracking allocation: + + #define mi_track_malloc_size(p,reqsize,size,zero) + #define mi_track_free_size(p,_size) + +The macros are set up such that the size passed to `mi_track_free_size` +always matches the size of `mi_track_malloc_size`. (currently, `size == mi_usable_size(p)`). +The `reqsize` is what the user requested, and `size >= reqsize`. +The `size` is either byte precise (and `size==reqsize`) if `MI_PADDING` is enabled, +or otherwise it is the usable block size which may be larger than the original request. +Use `_mi_block_size_of(void* p)` to get the full block size that was allocated (including padding etc). +The `zero` parameter is `true` if the allocated block is zero initialized. + +Optional: + + #define mi_track_align(p,alignedp,offset,size) + #define mi_track_resize(p,oldsize,newsize) + #define mi_track_init() + +The `mi_track_align` is called right after a `mi_track_malloc` for aligned pointers in a block. +The corresponding `mi_track_free` still uses the block start pointer and original size (corresponding to the `mi_track_malloc`). +The `mi_track_resize` is currently unused but could be called on reallocations within a block. +`mi_track_init` is called at program start. + +The following macros are for tools like asan and valgrind to track whether memory is +defined, undefined, or not accessible at all: + + #define mi_track_mem_defined(p,size) + #define mi_track_mem_undefined(p,size) + #define mi_track_mem_noaccess(p,size) + +-------------------------------------------------------------------------------------------------------*/ + +#if MI_TRACK_VALGRIND +// valgrind tool + +#define MI_TRACK_ENABLED 1 +#define MI_TRACK_HEAP_DESTROY 1 // track free of individual blocks on heap_destroy +#define MI_TRACK_TOOL "valgrind" + +#include +#include + +#define mi_track_malloc_size(p,reqsize,size,zero) VALGRIND_MALLOCLIKE_BLOCK(p,size,MI_PADDING_SIZE /*red zone*/,zero) +#define mi_track_free_size(p,_size) VALGRIND_FREELIKE_BLOCK(p,MI_PADDING_SIZE /*red zone*/) +#define mi_track_resize(p,oldsize,newsize) VALGRIND_RESIZEINPLACE_BLOCK(p,oldsize,newsize,MI_PADDING_SIZE /*red zone*/) +#define mi_track_mem_defined(p,size) VALGRIND_MAKE_MEM_DEFINED(p,size) +#define mi_track_mem_undefined(p,size) VALGRIND_MAKE_MEM_UNDEFINED(p,size) +#define mi_track_mem_noaccess(p,size) VALGRIND_MAKE_MEM_NOACCESS(p,size) + +#elif MI_TRACK_ASAN +// address sanitizer + +#define MI_TRACK_ENABLED 1 +#define MI_TRACK_HEAP_DESTROY 0 +#define MI_TRACK_TOOL "asan" + +#include + +#define mi_track_malloc_size(p,reqsize,size,zero) ASAN_UNPOISON_MEMORY_REGION(p,size) +#define mi_track_free_size(p,size) ASAN_POISON_MEMORY_REGION(p,size) +#define mi_track_mem_defined(p,size) ASAN_UNPOISON_MEMORY_REGION(p,size) +#define mi_track_mem_undefined(p,size) ASAN_UNPOISON_MEMORY_REGION(p,size) +#define mi_track_mem_noaccess(p,size) ASAN_POISON_MEMORY_REGION(p,size) + +#elif MI_TRACK_ETW +// windows event tracing + +#define MI_TRACK_ENABLED 1 +#define MI_TRACK_HEAP_DESTROY 1 +#define MI_TRACK_TOOL "ETW" + +#define WIN32_LEAN_AND_MEAN +#include +#include "../src/prim/windows/etw.h" + +#define mi_track_init() EventRegistermicrosoft_windows_mimalloc(); +#define mi_track_malloc_size(p,reqsize,size,zero) EventWriteETW_MI_ALLOC((UINT64)(p), size) +#define mi_track_free_size(p,size) EventWriteETW_MI_FREE((UINT64)(p), size) + +#else +// no tracking + +#define MI_TRACK_ENABLED 0 +#define MI_TRACK_HEAP_DESTROY 0 +#define MI_TRACK_TOOL "none" + +#define mi_track_malloc_size(p,reqsize,size,zero) +#define mi_track_free_size(p,_size) + +#endif + +// ------------------- +// Utility definitions + +#ifndef mi_track_resize +#define mi_track_resize(p,oldsize,newsize) mi_track_free_size(p,oldsize); mi_track_malloc(p,newsize,false) +#endif + +#ifndef mi_track_align +#define mi_track_align(p,alignedp,offset,size) mi_track_mem_noaccess(p,offset) +#endif + +#ifndef mi_track_init +#define mi_track_init() +#endif + +#ifndef mi_track_mem_defined +#define mi_track_mem_defined(p,size) +#endif + +#ifndef mi_track_mem_undefined +#define mi_track_mem_undefined(p,size) +#endif + +#ifndef mi_track_mem_noaccess +#define mi_track_mem_noaccess(p,size) +#endif + + +#if MI_PADDING +#define mi_track_malloc(p,reqsize,zero) \ + if ((p)!=NULL) { \ + mi_assert_internal(mi_usable_size(p)==(reqsize)); \ + mi_track_malloc_size(p,reqsize,reqsize,zero); \ + } +#else +#define mi_track_malloc(p,reqsize,zero) \ + if ((p)!=NULL) { \ + mi_assert_internal(mi_usable_size(p)>=(reqsize)); \ + mi_track_malloc_size(p,reqsize,mi_usable_size(p),zero); \ + } +#endif + +#endif diff --git a/Include/internal/mimalloc/mimalloc/types.h b/Include/internal/mimalloc/mimalloc/types.h new file mode 100644 index 00000000000000..b8cae24507fc5e --- /dev/null +++ b/Include/internal/mimalloc/mimalloc/types.h @@ -0,0 +1,712 @@ +/* ---------------------------------------------------------------------------- +Copyright (c) 2018-2023, Microsoft Research, Daan Leijen +This is free software; you can redistribute it and/or modify it under the +terms of the MIT license. A copy of the license can be found in the file +"LICENSE" at the root of this distribution. +-----------------------------------------------------------------------------*/ +#pragma once +#ifndef MIMALLOC_TYPES_H +#define MIMALLOC_TYPES_H + +// -------------------------------------------------------------------------- +// This file contains the main type definitions for mimalloc: +// mi_heap_t : all data for a thread-local heap, contains +// lists of all managed heap pages. +// mi_segment_t : a larger chunk of memory (32GiB) from where pages +// are allocated. +// mi_page_t : a mimalloc page (usually 64KiB or 512KiB) from +// where objects are allocated. +// -------------------------------------------------------------------------- + + +#include // ptrdiff_t +#include // uintptr_t, uint16_t, etc +#include "mimalloc/atomic.h" // _Atomic + +#ifdef _MSC_VER +#pragma warning(disable:4214) // bitfield is not int +#endif + +// Minimal alignment necessary. On most platforms 16 bytes are needed +// due to SSE registers for example. This must be at least `sizeof(void*)` +#ifndef MI_MAX_ALIGN_SIZE +#define MI_MAX_ALIGN_SIZE 16 // sizeof(max_align_t) +#endif + +#define MI_CACHE_LINE 64 +#if defined(_MSC_VER) +#pragma warning(disable:4127) // suppress constant conditional warning (due to MI_SECURE paths) +#pragma warning(disable:26812) // unscoped enum warning +#define mi_decl_noinline __declspec(noinline) +#define mi_decl_thread __declspec(thread) +#define mi_decl_cache_align __declspec(align(MI_CACHE_LINE)) +#elif (defined(__GNUC__) && (__GNUC__ >= 3)) || defined(__clang__) // includes clang and icc +#define mi_decl_noinline __attribute__((noinline)) +#define mi_decl_thread __thread +#define mi_decl_cache_align __attribute__((aligned(MI_CACHE_LINE))) +#else +#define mi_decl_noinline +#define mi_decl_thread __thread // hope for the best :-) +#define mi_decl_cache_align +#endif + +// ------------------------------------------------------ +// Variants +// ------------------------------------------------------ + +// Define NDEBUG in the release version to disable assertions. +// #define NDEBUG + +// Define MI_TRACK_ to enable tracking support +// #define MI_TRACK_VALGRIND 1 +// #define MI_TRACK_ASAN 1 +// #define MI_TRACK_ETW 1 + +// Define MI_STAT as 1 to maintain statistics; set it to 2 to have detailed statistics (but costs some performance). +// #define MI_STAT 1 + +// Define MI_SECURE to enable security mitigations +// #define MI_SECURE 1 // guard page around metadata +// #define MI_SECURE 2 // guard page around each mimalloc page +// #define MI_SECURE 3 // encode free lists (detect corrupted free list (buffer overflow), and invalid pointer free) +// #define MI_SECURE 4 // checks for double free. (may be more expensive) + +#if !defined(MI_SECURE) +#define MI_SECURE 0 +#endif + +// Define MI_DEBUG for debug mode +// #define MI_DEBUG 1 // basic assertion checks and statistics, check double free, corrupted free list, and invalid pointer free. +// #define MI_DEBUG 2 // + internal assertion checks +// #define MI_DEBUG 3 // + extensive internal invariant checking (cmake -DMI_DEBUG_FULL=ON) +#if !defined(MI_DEBUG) +#if !defined(NDEBUG) || defined(_DEBUG) +#define MI_DEBUG 2 +#else +#define MI_DEBUG 0 +#endif +#endif + +// Reserve extra padding at the end of each block to be more resilient against heap block overflows. +// The padding can detect buffer overflow on free. +#if !defined(MI_PADDING) && (MI_SECURE>=3 || MI_DEBUG>=1 || (MI_TRACK_VALGRIND || MI_TRACK_ASAN || MI_TRACK_ETW)) +#define MI_PADDING 1 +#endif + +// Check padding bytes; allows byte-precise buffer overflow detection +#if !defined(MI_PADDING_CHECK) && MI_PADDING && (MI_SECURE>=3 || MI_DEBUG>=1) +#define MI_PADDING_CHECK 1 +#endif + + +// Encoded free lists allow detection of corrupted free lists +// and can detect buffer overflows, modify after free, and double `free`s. +#if (MI_SECURE>=3 || MI_DEBUG>=1) +#define MI_ENCODE_FREELIST 1 +#endif + + +// We used to abandon huge pages but to eagerly deallocate if freed from another thread, +// but that makes it not possible to visit them during a heap walk or include them in a +// `mi_heap_destroy`. We therefore instead reset/decommit the huge blocks if freed from +// another thread so most memory is available until it gets properly freed by the owning thread. +// #define MI_HUGE_PAGE_ABANDON 1 + + +// ------------------------------------------------------ +// Platform specific values +// ------------------------------------------------------ + +// ------------------------------------------------------ +// Size of a pointer. +// We assume that `sizeof(void*)==sizeof(intptr_t)` +// and it holds for all platforms we know of. +// +// However, the C standard only requires that: +// p == (void*)((intptr_t)p)) +// but we also need: +// i == (intptr_t)((void*)i) +// or otherwise one might define an intptr_t type that is larger than a pointer... +// ------------------------------------------------------ + +#if INTPTR_MAX > INT64_MAX +# define MI_INTPTR_SHIFT (4) // assume 128-bit (as on arm CHERI for example) +#elif INTPTR_MAX == INT64_MAX +# define MI_INTPTR_SHIFT (3) +#elif INTPTR_MAX == INT32_MAX +# define MI_INTPTR_SHIFT (2) +#else +#error platform pointers must be 32, 64, or 128 bits +#endif + +#if SIZE_MAX == UINT64_MAX +# define MI_SIZE_SHIFT (3) +typedef int64_t mi_ssize_t; +#elif SIZE_MAX == UINT32_MAX +# define MI_SIZE_SHIFT (2) +typedef int32_t mi_ssize_t; +#else +#error platform objects must be 32 or 64 bits +#endif + +#if (SIZE_MAX/2) > LONG_MAX +# define MI_ZU(x) x##ULL +# define MI_ZI(x) x##LL +#else +# define MI_ZU(x) x##UL +# define MI_ZI(x) x##L +#endif + +#define MI_INTPTR_SIZE (1< 4 +#define MI_SEGMENT_SHIFT ( 9 + MI_SEGMENT_SLICE_SHIFT) // 32MiB +#else +#define MI_SEGMENT_SHIFT ( 7 + MI_SEGMENT_SLICE_SHIFT) // 4MiB on 32-bit +#endif + +#define MI_SMALL_PAGE_SHIFT (MI_SEGMENT_SLICE_SHIFT) // 64KiB +#define MI_MEDIUM_PAGE_SHIFT ( 3 + MI_SMALL_PAGE_SHIFT) // 512KiB + + +// Derived constants +#define MI_SEGMENT_SIZE (MI_ZU(1)<= 655360) +#error "mimalloc internal: define more bins" +#endif + +// Maximum slice offset (15) +#define MI_MAX_SLICE_OFFSET ((MI_ALIGNMENT_MAX / MI_SEGMENT_SLICE_SIZE) - 1) + +// Used as a special value to encode block sizes in 32 bits. +#define MI_HUGE_BLOCK_SIZE ((uint32_t)(2*MI_GiB)) + +// blocks up to this size are always allocated aligned +#define MI_MAX_ALIGN_GUARANTEE (8*MI_MAX_ALIGN_SIZE) + +// Alignments over MI_ALIGNMENT_MAX are allocated in dedicated huge page segments +#define MI_ALIGNMENT_MAX (MI_SEGMENT_SIZE >> 1) + + +// ------------------------------------------------------ +// Mimalloc pages contain allocated blocks +// ------------------------------------------------------ + +// The free lists use encoded next fields +// (Only actually encodes when MI_ENCODED_FREELIST is defined.) +typedef uintptr_t mi_encoded_t; + +// thread id's +typedef size_t mi_threadid_t; + +// free lists contain blocks +typedef struct mi_block_s { + mi_encoded_t next; +} mi_block_t; + + +// The delayed flags are used for efficient multi-threaded free-ing +typedef enum mi_delayed_e { + MI_USE_DELAYED_FREE = 0, // push on the owning heap thread delayed list + MI_DELAYED_FREEING = 1, // temporary: another thread is accessing the owning heap + MI_NO_DELAYED_FREE = 2, // optimize: push on page local thread free queue if another block is already in the heap thread delayed free list + MI_NEVER_DELAYED_FREE = 3 // sticky, only resets on page reclaim +} mi_delayed_t; + + +// The `in_full` and `has_aligned` page flags are put in a union to efficiently +// test if both are false (`full_aligned == 0`) in the `mi_free` routine. +#if !MI_TSAN +typedef union mi_page_flags_s { + uint8_t full_aligned; + struct { + uint8_t in_full : 1; + uint8_t has_aligned : 1; + } x; +} mi_page_flags_t; +#else +// under thread sanitizer, use a byte for each flag to suppress warning, issue #130 +typedef union mi_page_flags_s { + uint16_t full_aligned; + struct { + uint8_t in_full; + uint8_t has_aligned; + } x; +} mi_page_flags_t; +#endif + +// Thread free list. +// We use the bottom 2 bits of the pointer for mi_delayed_t flags +typedef uintptr_t mi_thread_free_t; + +// A page contains blocks of one specific size (`block_size`). +// Each page has three list of free blocks: +// `free` for blocks that can be allocated, +// `local_free` for freed blocks that are not yet available to `mi_malloc` +// `thread_free` for freed blocks by other threads +// The `local_free` and `thread_free` lists are migrated to the `free` list +// when it is exhausted. The separate `local_free` list is necessary to +// implement a monotonic heartbeat. The `thread_free` list is needed for +// avoiding atomic operations in the common case. +// +// +// `used - |thread_free|` == actual blocks that are in use (alive) +// `used - |thread_free| + |free| + |local_free| == capacity` +// +// We don't count `freed` (as |free|) but use `used` to reduce +// the number of memory accesses in the `mi_page_all_free` function(s). +// +// Notes: +// - Access is optimized for `mi_free` and `mi_page_alloc` (in `alloc.c`) +// - Using `uint16_t` does not seem to slow things down +// - The size is 8 words on 64-bit which helps the page index calculations +// (and 10 words on 32-bit, and encoded free lists add 2 words. Sizes 10 +// and 12 are still good for address calculation) +// - To limit the structure size, the `xblock_size` is 32-bits only; for +// blocks > MI_HUGE_BLOCK_SIZE the size is determined from the segment page size +// - `thread_free` uses the bottom bits as a delayed-free flags to optimize +// concurrent frees where only the first concurrent free adds to the owning +// heap `thread_delayed_free` list (see `alloc.c:mi_free_block_mt`). +// The invariant is that no-delayed-free is only set if there is +// at least one block that will be added, or as already been added, to +// the owning heap `thread_delayed_free` list. This guarantees that pages +// will be freed correctly even if only other threads free blocks. +typedef struct mi_page_s { + // "owned" by the segment + uint32_t slice_count; // slices in this page (0 if not a page) + uint32_t slice_offset; // distance from the actual page data slice (0 if a page) + uint8_t is_committed : 1; // `true` if the page virtual memory is committed + uint8_t is_zero_init : 1; // `true` if the page was initially zero initialized + uint8_t tag : 4; // tag from the owning heap + + // layout like this to optimize access in `mi_malloc` and `mi_free` + uint16_t capacity; // number of blocks committed, must be the first field, see `segment.c:page_clear` + uint16_t reserved; // number of blocks reserved in memory + mi_page_flags_t flags; // `in_full` and `has_aligned` flags (8 bits) + uint8_t free_is_zero : 1; // `true` if the blocks in the free list are zero initialized + uint8_t retire_expire : 7; // expiration count for retired blocks + + mi_block_t* free; // list of available free blocks (`malloc` allocates from this list) + uint32_t used; // number of blocks in use (including blocks in `local_free` and `thread_free`) + uint32_t xblock_size; // size available in each block (always `>0`) + mi_block_t* local_free; // list of deferred free blocks by this thread (migrates to `free`) + + #if (MI_ENCODE_FREELIST || MI_PADDING) + uintptr_t keys[2]; // two random keys to encode the free lists (see `_mi_block_next`) or padding canary + #endif + + _Atomic(mi_thread_free_t) xthread_free; // list of deferred free blocks freed by other threads + _Atomic(uintptr_t) xheap; + + struct mi_page_s* next; // next page owned by this thread with the same `block_size` + struct mi_page_s* prev; // previous page owned by this thread with the same `block_size` + + // 64-bit 9 words, 32-bit 12 words, (+2 for secure) + #if MI_INTPTR_SIZE==8 + uintptr_t padding[1]; + #endif +} mi_page_t; + + + +// ------------------------------------------------------ +// Mimalloc segments contain mimalloc pages +// ------------------------------------------------------ + +typedef enum mi_page_kind_e { + MI_PAGE_SMALL, // small blocks go into 64KiB pages inside a segment + MI_PAGE_MEDIUM, // medium blocks go into medium pages inside a segment + MI_PAGE_LARGE, // larger blocks go into a page of just one block + MI_PAGE_HUGE, // huge blocks (> 16 MiB) are put into a single page in a single segment. +} mi_page_kind_t; + +typedef enum mi_segment_kind_e { + MI_SEGMENT_NORMAL, // MI_SEGMENT_SIZE size with pages inside. + MI_SEGMENT_HUGE, // > MI_LARGE_SIZE_MAX segment with just one huge page inside. +} mi_segment_kind_t; + +// ------------------------------------------------------ +// A segment holds a commit mask where a bit is set if +// the corresponding MI_COMMIT_SIZE area is committed. +// The MI_COMMIT_SIZE must be a multiple of the slice +// size. If it is equal we have the most fine grained +// decommit (but setting it higher can be more efficient). +// The MI_MINIMAL_COMMIT_SIZE is the minimal amount that will +// be committed in one go which can be set higher than +// MI_COMMIT_SIZE for efficiency (while the decommit mask +// is still tracked in fine-grained MI_COMMIT_SIZE chunks) +// ------------------------------------------------------ + +#define MI_MINIMAL_COMMIT_SIZE (1*MI_SEGMENT_SLICE_SIZE) +#define MI_COMMIT_SIZE (MI_SEGMENT_SLICE_SIZE) // 64KiB +#define MI_COMMIT_MASK_BITS (MI_SEGMENT_SIZE / MI_COMMIT_SIZE) +#define MI_COMMIT_MASK_FIELD_BITS MI_SIZE_BITS +#define MI_COMMIT_MASK_FIELD_COUNT (MI_COMMIT_MASK_BITS / MI_COMMIT_MASK_FIELD_BITS) + +#if (MI_COMMIT_MASK_BITS != (MI_COMMIT_MASK_FIELD_COUNT * MI_COMMIT_MASK_FIELD_BITS)) +#error "the segment size must be exactly divisible by the (commit size * size_t bits)" +#endif + +typedef struct mi_commit_mask_s { + size_t mask[MI_COMMIT_MASK_FIELD_COUNT]; +} mi_commit_mask_t; + +typedef mi_page_t mi_slice_t; +typedef int64_t mi_msecs_t; + + +// Memory can reside in arena's, direct OS allocated, or statically allocated. The memid keeps track of this. +typedef enum mi_memkind_e { + MI_MEM_NONE, // not allocated + MI_MEM_EXTERNAL, // not owned by mimalloc but provided externally (via `mi_manage_os_memory` for example) + MI_MEM_STATIC, // allocated in a static area and should not be freed (for arena meta data for example) + MI_MEM_OS, // allocated from the OS + MI_MEM_OS_HUGE, // allocated as huge os pages + MI_MEM_OS_REMAP, // allocated in a remapable area (i.e. using `mremap`) + MI_MEM_ARENA // allocated from an arena (the usual case) +} mi_memkind_t; + +static inline bool mi_memkind_is_os(mi_memkind_t memkind) { + return (memkind >= MI_MEM_OS && memkind <= MI_MEM_OS_REMAP); +} + +typedef struct mi_memid_os_info { + void* base; // actual base address of the block (used for offset aligned allocations) + size_t alignment; // alignment at allocation +} mi_memid_os_info_t; + +typedef struct mi_memid_arena_info { + size_t block_index; // index in the arena + mi_arena_id_t id; // arena id (>= 1) + bool is_exclusive; // the arena can only be used for specific arena allocations +} mi_memid_arena_info_t; + +typedef struct mi_memid_s { + union { + mi_memid_os_info_t os; // only used for MI_MEM_OS + mi_memid_arena_info_t arena; // only used for MI_MEM_ARENA + } mem; + bool is_pinned; // `true` if we cannot decommit/reset/protect in this memory (e.g. when allocated using large OS pages) + bool initially_committed;// `true` if the memory was originally allocated as committed + bool initially_zero; // `true` if the memory was originally zero initialized + mi_memkind_t memkind; +} mi_memid_t; + + +// Segments are large allocated memory blocks (8mb on 64 bit) from +// the OS. Inside segments we allocated fixed size _pages_ that +// contain blocks. +typedef struct mi_segment_s { + // constant fields + mi_memid_t memid; // memory id for arena allocation + bool allow_decommit; + bool allow_purge; + size_t segment_size; + + // segment fields + mi_msecs_t purge_expire; + mi_commit_mask_t purge_mask; + mi_commit_mask_t commit_mask; + + _Atomic(struct mi_segment_s*) abandoned_next; + + // from here is zero initialized + struct mi_segment_s* next; // the list of freed segments in the cache (must be first field, see `segment.c:mi_segment_init`) + + size_t abandoned; // abandoned pages (i.e. the original owning thread stopped) (`abandoned <= used`) + size_t abandoned_visits; // count how often this segment is visited in the abandoned list (to force reclaim it it is too long) + size_t used; // count of pages in use + uintptr_t cookie; // verify addresses in debug mode: `mi_ptr_cookie(segment) == segment->cookie` + + size_t segment_slices; // for huge segments this may be different from `MI_SLICES_PER_SEGMENT` + size_t segment_info_slices; // initial slices we are using segment info and possible guard pages. + + // layout like this to optimize access in `mi_free` + mi_segment_kind_t kind; + size_t slice_entries; // entries in the `slices` array, at most `MI_SLICES_PER_SEGMENT` + _Atomic(mi_threadid_t) thread_id; // unique id of the thread owning this segment + + mi_slice_t slices[MI_SLICES_PER_SEGMENT+1]; // one more for huge blocks with large alignment +} mi_segment_t; + +typedef uintptr_t mi_tagged_segment_t; + +// Segments unowned by any thread are put in a shared pool +typedef struct mi_abandoned_pool_s { + // This is a list of visited abandoned pages that were full at the time. + // this list migrates to `abandoned` when that becomes NULL. The use of + // this list reduces contention and the rate at which segments are visited. + mi_decl_cache_align _Atomic(mi_segment_t*) abandoned_visited; // = NULL + + // The abandoned page list (tagged as it supports pop) + mi_decl_cache_align _Atomic(mi_tagged_segment_t) abandoned; // = NULL + + // Maintain these for debug purposes (these counts may be a bit off) + mi_decl_cache_align _Atomic(size_t) abandoned_count; + mi_decl_cache_align _Atomic(size_t) abandoned_visited_count; + + // We also maintain a count of current readers of the abandoned list + // in order to prevent resetting/decommitting segment memory if it might + // still be read. + mi_decl_cache_align _Atomic(size_t) abandoned_readers; // = 0 +} mi_abandoned_pool_t; + + +// ------------------------------------------------------ +// Heaps +// Provide first-class heaps to allocate from. +// A heap just owns a set of pages for allocation and +// can only be allocate/reallocate from the thread that created it. +// Freeing blocks can be done from any thread though. +// Per thread, the segments are shared among its heaps. +// Per thread, there is always a default heap that is +// used for allocation; it is initialized to statically +// point to an empty heap to avoid initialization checks +// in the fast path. +// ------------------------------------------------------ + +// Thread local data +typedef struct mi_tld_s mi_tld_t; + +// Pages of a certain block size are held in a queue. +typedef struct mi_page_queue_s { + mi_page_t* first; + mi_page_t* last; + size_t block_size; +} mi_page_queue_t; + +#define MI_BIN_FULL (MI_BIN_HUGE+1) + +// Random context +typedef struct mi_random_cxt_s { + uint32_t input[16]; + uint32_t output[16]; + int output_available; + bool weak; +} mi_random_ctx_t; + + +// In debug mode there is a padding structure at the end of the blocks to check for buffer overflows +#if (MI_PADDING) +typedef struct mi_padding_s { + uint32_t canary; // encoded block value to check validity of the padding (in case of overflow) + uint32_t delta; // padding bytes before the block. (mi_usable_size(p) - delta == exact allocated bytes) +} mi_padding_t; +#define MI_PADDING_SIZE (sizeof(mi_padding_t)) +#define MI_PADDING_WSIZE ((MI_PADDING_SIZE + MI_INTPTR_SIZE - 1) / MI_INTPTR_SIZE) +#else +#define MI_PADDING_SIZE 0 +#define MI_PADDING_WSIZE 0 +#endif + +#define MI_PAGES_DIRECT (MI_SMALL_WSIZE_MAX + MI_PADDING_WSIZE + 1) + + +// A heap owns a set of pages. +struct mi_heap_s { + mi_tld_t* tld; + mi_page_t* pages_free_direct[MI_PAGES_DIRECT]; // optimize: array where every entry points a page with possibly free blocks in the corresponding queue for that size. + mi_page_queue_t pages[MI_BIN_FULL + 1]; // queue of pages for each size class (or "bin") + _Atomic(mi_block_t*) thread_delayed_free; + mi_threadid_t thread_id; // thread this heap belongs too + mi_arena_id_t arena_id; // arena id if the heap belongs to a specific arena (or 0) + uintptr_t cookie; // random cookie to verify pointers (see `_mi_ptr_cookie`) + uintptr_t keys[2]; // two random keys used to encode the `thread_delayed_free` list + mi_random_ctx_t random; // random number context used for secure allocation + size_t page_count; // total number of pages in the `pages` queues. + size_t page_retired_min; // smallest retired index (retired pages are fully free, but still in the page queues) + size_t page_retired_max; // largest retired index into the `pages` array. + mi_heap_t* next; // list of heaps per thread + bool no_reclaim; // `true` if this heap should not reclaim abandoned pages + uint8_t tag; // custom identifier for this heap +}; + + + +// ------------------------------------------------------ +// Debug +// ------------------------------------------------------ + +#if !defined(MI_DEBUG_UNINIT) +#define MI_DEBUG_UNINIT (0xD0) +#endif +#if !defined(MI_DEBUG_FREED) +#define MI_DEBUG_FREED (0xDF) +#endif +#if !defined(MI_DEBUG_PADDING) +#define MI_DEBUG_PADDING (0xDE) +#endif + +#if (MI_DEBUG) +// use our own assertion to print without memory allocation +void _mi_assert_fail(const char* assertion, const char* fname, unsigned int line, const char* func ); +#define mi_assert(expr) ((expr) ? (void)0 : _mi_assert_fail(#expr,__FILE__,__LINE__,__func__)) +#else +#define mi_assert(x) +#endif + +#if (MI_DEBUG>1) +#define mi_assert_internal mi_assert +#else +#define mi_assert_internal(x) +#endif + +#if (MI_DEBUG>2) +#define mi_assert_expensive mi_assert +#else +#define mi_assert_expensive(x) +#endif + +// ------------------------------------------------------ +// Statistics +// ------------------------------------------------------ + +#ifndef MI_STAT +#if (MI_DEBUG>0) +#define MI_STAT 2 +#else +#define MI_STAT 0 +#endif +#endif + +typedef struct mi_stat_count_s { + int64_t allocated; + int64_t freed; + int64_t peak; + int64_t current; +} mi_stat_count_t; + +typedef struct mi_stat_counter_s { + int64_t total; + int64_t count; +} mi_stat_counter_t; + +typedef struct mi_stats_s { + mi_stat_count_t segments; + mi_stat_count_t pages; + mi_stat_count_t reserved; + mi_stat_count_t committed; + mi_stat_count_t reset; + mi_stat_count_t purged; + mi_stat_count_t page_committed; + mi_stat_count_t segments_abandoned; + mi_stat_count_t pages_abandoned; + mi_stat_count_t threads; + mi_stat_count_t normal; + mi_stat_count_t huge; + mi_stat_count_t large; + mi_stat_count_t malloc; + mi_stat_count_t segments_cache; + mi_stat_counter_t pages_extended; + mi_stat_counter_t mmap_calls; + mi_stat_counter_t commit_calls; + mi_stat_counter_t reset_calls; + mi_stat_counter_t purge_calls; + mi_stat_counter_t page_no_retire; + mi_stat_counter_t searches; + mi_stat_counter_t normal_count; + mi_stat_counter_t huge_count; + mi_stat_counter_t large_count; +#if MI_STAT>1 + mi_stat_count_t normal_bins[MI_BIN_HUGE+1]; +#endif +} mi_stats_t; + + +void _mi_stat_increase(mi_stat_count_t* stat, size_t amount); +void _mi_stat_decrease(mi_stat_count_t* stat, size_t amount); +void _mi_stat_counter_increase(mi_stat_counter_t* stat, size_t amount); + +#if (MI_STAT) +#define mi_stat_increase(stat,amount) _mi_stat_increase( &(stat), amount) +#define mi_stat_decrease(stat,amount) _mi_stat_decrease( &(stat), amount) +#define mi_stat_counter_increase(stat,amount) _mi_stat_counter_increase( &(stat), amount) +#else +#define mi_stat_increase(stat,amount) (void)0 +#define mi_stat_decrease(stat,amount) (void)0 +#define mi_stat_counter_increase(stat,amount) (void)0 +#endif + +#define mi_heap_stat_counter_increase(heap,stat,amount) mi_stat_counter_increase( (heap)->tld->stats.stat, amount) +#define mi_heap_stat_increase(heap,stat,amount) mi_stat_increase( (heap)->tld->stats.stat, amount) +#define mi_heap_stat_decrease(heap,stat,amount) mi_stat_decrease( (heap)->tld->stats.stat, amount) + +// ------------------------------------------------------ +// Thread Local data +// ------------------------------------------------------ + +// A "span" is is an available range of slices. The span queues keep +// track of slice spans of at most the given `slice_count` (but more than the previous size class). +typedef struct mi_span_queue_s { + mi_slice_t* first; + mi_slice_t* last; + size_t slice_count; +} mi_span_queue_t; + +#define MI_SEGMENT_BIN_MAX (35) // 35 == mi_segment_bin(MI_SLICES_PER_SEGMENT) + +// OS thread local data +typedef struct mi_os_tld_s { + size_t region_idx; // start point for next allocation + mi_stats_t* stats; // points to tld stats +} mi_os_tld_t; + + +// Segments thread local data +typedef struct mi_segments_tld_s { + mi_span_queue_t spans[MI_SEGMENT_BIN_MAX+1]; // free slice spans inside segments + size_t count; // current number of segments; + size_t peak_count; // peak number of segments + size_t current_size; // current size of all segments + size_t peak_size; // peak size of all segments + mi_stats_t* stats; // points to tld stats + mi_os_tld_t* os; // points to os stats + mi_abandoned_pool_t* abandoned; // pool of abandoned segments +} mi_segments_tld_t; + +// Thread local data +struct mi_tld_s { + unsigned long long heartbeat; // monotonic heartbeat count + bool recurse; // true if deferred was called; used to prevent infinite recursion. + mi_heap_t* heap_backing; // backing heap of this thread (cannot be deleted) + mi_heap_t* heaps; // list of heaps in this thread (so we can abandon all when the thread terminates) + mi_segments_tld_t segments; // segment tld + mi_os_tld_t os; // os tld + mi_stats_t stats; // statistics +}; + +#endif diff --git a/Include/internal/pycore_abstract.h b/Include/internal/pycore_abstract.h index 2733d8102e5ef4..3cc0afac4bd5b4 100644 --- a/Include/internal/pycore_abstract.h +++ b/Include/internal/pycore_abstract.h @@ -47,6 +47,13 @@ extern int _PyObject_RealIsInstance(PyObject *inst, PyObject *cls); extern int _PyObject_RealIsSubclass(PyObject *derived, PyObject *cls); +// Convert Python int to Py_ssize_t. Do nothing if the argument is None. +// Export for '_bisect' shared extension. +PyAPI_FUNC(int) _Py_convert_optional_to_ssize_t(PyObject *, void *); + +// Same as PyNumber_Index() but can return an instance of a subclass of int. +// Export for 'math' shared extension. +PyAPI_FUNC(PyObject*) _PyNumber_Index(PyObject *o); #ifdef __cplusplus } diff --git a/Include/internal/pycore_ast.h b/Include/internal/pycore_ast.h index b568902bb1e381..f222d485e0b54b 100644 --- a/Include/internal/pycore_ast.h +++ b/Include/internal/pycore_ast.h @@ -10,7 +10,7 @@ extern "C" { # error "this header requires Py_BUILD_CORE define" #endif -#include "pycore_asdl.h" +#include "pycore_asdl.h" // _ASDL_SEQ_HEAD typedef struct _mod *mod_ty; diff --git a/Include/internal/pycore_ast_state.h b/Include/internal/pycore_ast_state.h index 0c0d53f3e5d7e9..f1b1786264803b 100644 --- a/Include/internal/pycore_ast_state.h +++ b/Include/internal/pycore_ast_state.h @@ -2,6 +2,9 @@ #ifndef Py_INTERNAL_AST_STATE_H #define Py_INTERNAL_AST_STATE_H + +#include "pycore_lock.h" // _PyOnceFlag + #ifdef __cplusplus extern "C" { #endif @@ -11,9 +14,8 @@ extern "C" { #endif struct ast_state { - int initialized; - int recursion_depth; - int recursion_limit; + _PyOnceFlag once; + int finalized; PyObject *AST_type; PyObject *Add_singleton; PyObject *Add_type; diff --git a/Include/internal/pycore_atexit.h b/Include/internal/pycore_atexit.h index 3966df70e2616f..4dcda8f517c787 100644 --- a/Include/internal/pycore_atexit.h +++ b/Include/internal/pycore_atexit.h @@ -1,5 +1,8 @@ #ifndef Py_INTERNAL_ATEXIT_H #define Py_INTERNAL_ATEXIT_H + +#include "pycore_lock.h" // PyMutex + #ifdef __cplusplus extern "C" { #endif @@ -15,7 +18,7 @@ extern "C" { typedef void (*atexit_callbackfunc)(void); struct _atexit_runtime_state { - PyThread_type_lock mutex; + PyMutex mutex; #define NEXITFUNCS 32 atexit_callbackfunc callbacks[NEXITFUNCS]; int ncallbacks; diff --git a/Include/internal/pycore_atomic.h b/Include/internal/pycore_atomic.h deleted file mode 100644 index 425d69f868b52b..00000000000000 --- a/Include/internal/pycore_atomic.h +++ /dev/null @@ -1,557 +0,0 @@ -#ifndef Py_ATOMIC_H -#define Py_ATOMIC_H -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef Py_BUILD_CORE -# error "this header requires Py_BUILD_CORE define" -#endif - -#include "dynamic_annotations.h" /* _Py_ANNOTATE_MEMORY_ORDER */ -#include "pyconfig.h" - -#ifdef HAVE_STD_ATOMIC -# include -#endif - - -#if defined(_MSC_VER) -#include -#if defined(_M_IX86) || defined(_M_X64) -# include -#endif -#endif - -/* This is modeled after the atomics interface from C1x, according to - * the draft at - * http://www.open-std.org/JTC1/SC22/wg14/www/docs/n1425.pdf. - * Operations and types are named the same except with a _Py_ prefix - * and have the same semantics. - * - * Beware, the implementations here are deep magic. - */ - -#if defined(HAVE_STD_ATOMIC) - -typedef enum _Py_memory_order { - _Py_memory_order_relaxed = memory_order_relaxed, - _Py_memory_order_acquire = memory_order_acquire, - _Py_memory_order_release = memory_order_release, - _Py_memory_order_acq_rel = memory_order_acq_rel, - _Py_memory_order_seq_cst = memory_order_seq_cst -} _Py_memory_order; - -typedef struct _Py_atomic_address { - atomic_uintptr_t _value; -} _Py_atomic_address; - -typedef struct _Py_atomic_int { - atomic_int _value; -} _Py_atomic_int; - -#define _Py_atomic_signal_fence(/*memory_order*/ ORDER) \ - atomic_signal_fence(ORDER) - -#define _Py_atomic_thread_fence(/*memory_order*/ ORDER) \ - atomic_thread_fence(ORDER) - -#define _Py_atomic_store_explicit(ATOMIC_VAL, NEW_VAL, ORDER) \ - atomic_store_explicit(&((ATOMIC_VAL)->_value), NEW_VAL, ORDER) - -#define _Py_atomic_load_explicit(ATOMIC_VAL, ORDER) \ - atomic_load_explicit(&((ATOMIC_VAL)->_value), ORDER) - -// Use builtin atomic operations in GCC >= 4.7 and clang -#elif defined(HAVE_BUILTIN_ATOMIC) - -typedef enum _Py_memory_order { - _Py_memory_order_relaxed = __ATOMIC_RELAXED, - _Py_memory_order_acquire = __ATOMIC_ACQUIRE, - _Py_memory_order_release = __ATOMIC_RELEASE, - _Py_memory_order_acq_rel = __ATOMIC_ACQ_REL, - _Py_memory_order_seq_cst = __ATOMIC_SEQ_CST -} _Py_memory_order; - -typedef struct _Py_atomic_address { - uintptr_t _value; -} _Py_atomic_address; - -typedef struct _Py_atomic_int { - int _value; -} _Py_atomic_int; - -#define _Py_atomic_signal_fence(/*memory_order*/ ORDER) \ - __atomic_signal_fence(ORDER) - -#define _Py_atomic_thread_fence(/*memory_order*/ ORDER) \ - __atomic_thread_fence(ORDER) - -#define _Py_atomic_store_explicit(ATOMIC_VAL, NEW_VAL, ORDER) \ - (assert((ORDER) == __ATOMIC_RELAXED \ - || (ORDER) == __ATOMIC_SEQ_CST \ - || (ORDER) == __ATOMIC_RELEASE), \ - __atomic_store_n(&((ATOMIC_VAL)->_value), NEW_VAL, ORDER)) - -#define _Py_atomic_load_explicit(ATOMIC_VAL, ORDER) \ - (assert((ORDER) == __ATOMIC_RELAXED \ - || (ORDER) == __ATOMIC_SEQ_CST \ - || (ORDER) == __ATOMIC_ACQUIRE \ - || (ORDER) == __ATOMIC_CONSUME), \ - __atomic_load_n(&((ATOMIC_VAL)->_value), ORDER)) - -/* Only support GCC (for expression statements) and x86 (for simple - * atomic semantics) and MSVC x86/x64/ARM */ -#elif defined(__GNUC__) && (defined(__i386__) || defined(__amd64)) -typedef enum _Py_memory_order { - _Py_memory_order_relaxed, - _Py_memory_order_acquire, - _Py_memory_order_release, - _Py_memory_order_acq_rel, - _Py_memory_order_seq_cst -} _Py_memory_order; - -typedef struct _Py_atomic_address { - uintptr_t _value; -} _Py_atomic_address; - -typedef struct _Py_atomic_int { - int _value; -} _Py_atomic_int; - - -static __inline__ void -_Py_atomic_signal_fence(_Py_memory_order order) -{ - if (order != _Py_memory_order_relaxed) - __asm__ volatile("":::"memory"); -} - -static __inline__ void -_Py_atomic_thread_fence(_Py_memory_order order) -{ - if (order != _Py_memory_order_relaxed) - __asm__ volatile("mfence":::"memory"); -} - -/* Tell the race checker about this operation's effects. */ -static __inline__ void -_Py_ANNOTATE_MEMORY_ORDER(const volatile void *address, _Py_memory_order order) -{ - (void)address; /* shut up -Wunused-parameter */ - switch(order) { - case _Py_memory_order_release: - case _Py_memory_order_acq_rel: - case _Py_memory_order_seq_cst: - _Py_ANNOTATE_HAPPENS_BEFORE(address); - break; - case _Py_memory_order_relaxed: - case _Py_memory_order_acquire: - break; - } - switch(order) { - case _Py_memory_order_acquire: - case _Py_memory_order_acq_rel: - case _Py_memory_order_seq_cst: - _Py_ANNOTATE_HAPPENS_AFTER(address); - break; - case _Py_memory_order_relaxed: - case _Py_memory_order_release: - break; - } -} - -#define _Py_atomic_store_explicit(ATOMIC_VAL, NEW_VAL, ORDER) \ - __extension__ ({ \ - __typeof__(ATOMIC_VAL) atomic_val = ATOMIC_VAL; \ - __typeof__(atomic_val->_value) new_val = NEW_VAL;\ - volatile __typeof__(new_val) *volatile_data = &atomic_val->_value; \ - _Py_memory_order order = ORDER; \ - _Py_ANNOTATE_MEMORY_ORDER(atomic_val, order); \ - \ - /* Perform the operation. */ \ - _Py_ANNOTATE_IGNORE_WRITES_BEGIN(); \ - switch(order) { \ - case _Py_memory_order_release: \ - _Py_atomic_signal_fence(_Py_memory_order_release); \ - /* fallthrough */ \ - case _Py_memory_order_relaxed: \ - *volatile_data = new_val; \ - break; \ - \ - case _Py_memory_order_acquire: \ - case _Py_memory_order_acq_rel: \ - case _Py_memory_order_seq_cst: \ - __asm__ volatile("xchg %0, %1" \ - : "+r"(new_val) \ - : "m"(atomic_val->_value) \ - : "memory"); \ - break; \ - } \ - _Py_ANNOTATE_IGNORE_WRITES_END(); \ - }) - -#define _Py_atomic_load_explicit(ATOMIC_VAL, ORDER) \ - __extension__ ({ \ - __typeof__(ATOMIC_VAL) atomic_val = ATOMIC_VAL; \ - __typeof__(atomic_val->_value) result; \ - volatile __typeof__(result) *volatile_data = &atomic_val->_value; \ - _Py_memory_order order = ORDER; \ - _Py_ANNOTATE_MEMORY_ORDER(atomic_val, order); \ - \ - /* Perform the operation. */ \ - _Py_ANNOTATE_IGNORE_READS_BEGIN(); \ - switch(order) { \ - case _Py_memory_order_release: \ - case _Py_memory_order_acq_rel: \ - case _Py_memory_order_seq_cst: \ - /* Loads on x86 are not releases by default, so need a */ \ - /* thread fence. */ \ - _Py_atomic_thread_fence(_Py_memory_order_release); \ - break; \ - default: \ - /* No fence */ \ - break; \ - } \ - result = *volatile_data; \ - switch(order) { \ - case _Py_memory_order_acquire: \ - case _Py_memory_order_acq_rel: \ - case _Py_memory_order_seq_cst: \ - /* Loads on x86 are automatically acquire operations so */ \ - /* can get by with just a compiler fence. */ \ - _Py_atomic_signal_fence(_Py_memory_order_acquire); \ - break; \ - default: \ - /* No fence */ \ - break; \ - } \ - _Py_ANNOTATE_IGNORE_READS_END(); \ - result; \ - }) - -#elif defined(_MSC_VER) -/* _Interlocked* functions provide a full memory barrier and are therefore - enough for acq_rel and seq_cst. If the HLE variants aren't available - in hardware they will fall back to a full memory barrier as well. - - This might affect performance but likely only in some very specific and - hard to measure scenario. -*/ -#if defined(_M_IX86) || defined(_M_X64) -typedef enum _Py_memory_order { - _Py_memory_order_relaxed, - _Py_memory_order_acquire, - _Py_memory_order_release, - _Py_memory_order_acq_rel, - _Py_memory_order_seq_cst -} _Py_memory_order; - -typedef struct _Py_atomic_address { - volatile uintptr_t _value; -} _Py_atomic_address; - -typedef struct _Py_atomic_int { - volatile int _value; -} _Py_atomic_int; - - -#if defined(_M_X64) -#define _Py_atomic_store_64bit(ATOMIC_VAL, NEW_VAL, ORDER) \ - switch (ORDER) { \ - case _Py_memory_order_acquire: \ - _InterlockedExchange64_HLEAcquire((__int64 volatile*)&((ATOMIC_VAL)->_value), (__int64)(NEW_VAL)); \ - break; \ - case _Py_memory_order_release: \ - _InterlockedExchange64_HLERelease((__int64 volatile*)&((ATOMIC_VAL)->_value), (__int64)(NEW_VAL)); \ - break; \ - default: \ - _InterlockedExchange64((__int64 volatile*)&((ATOMIC_VAL)->_value), (__int64)(NEW_VAL)); \ - break; \ - } -#else -#define _Py_atomic_store_64bit(ATOMIC_VAL, NEW_VAL, ORDER) ((void)0); -#endif - -#define _Py_atomic_store_32bit(ATOMIC_VAL, NEW_VAL, ORDER) \ - switch (ORDER) { \ - case _Py_memory_order_acquire: \ - _InterlockedExchange_HLEAcquire((volatile long*)&((ATOMIC_VAL)->_value), (int)(NEW_VAL)); \ - break; \ - case _Py_memory_order_release: \ - _InterlockedExchange_HLERelease((volatile long*)&((ATOMIC_VAL)->_value), (int)(NEW_VAL)); \ - break; \ - default: \ - _InterlockedExchange((volatile long*)&((ATOMIC_VAL)->_value), (int)(NEW_VAL)); \ - break; \ - } - -#if defined(_M_X64) -/* This has to be an intptr_t for now. - gil_created() uses -1 as a sentinel value, if this returns - a uintptr_t it will do an unsigned compare and crash -*/ -inline intptr_t _Py_atomic_load_64bit_impl(volatile uintptr_t* value, int order) { - __int64 old; - switch (order) { - case _Py_memory_order_acquire: - { - do { - old = *value; - } while(_InterlockedCompareExchange64_HLEAcquire((volatile __int64*)value, old, old) != old); - break; - } - case _Py_memory_order_release: - { - do { - old = *value; - } while(_InterlockedCompareExchange64_HLERelease((volatile __int64*)value, old, old) != old); - break; - } - case _Py_memory_order_relaxed: - old = *value; - break; - default: - { - do { - old = *value; - } while(_InterlockedCompareExchange64((volatile __int64*)value, old, old) != old); - break; - } - } - return old; -} - -#define _Py_atomic_load_64bit(ATOMIC_VAL, ORDER) \ - _Py_atomic_load_64bit_impl((volatile uintptr_t*)&((ATOMIC_VAL)->_value), (ORDER)) - -#else -#define _Py_atomic_load_64bit(ATOMIC_VAL, ORDER) ((ATOMIC_VAL)->_value) -#endif - -inline int _Py_atomic_load_32bit_impl(volatile int* value, int order) { - long old; - switch (order) { - case _Py_memory_order_acquire: - { - do { - old = *value; - } while(_InterlockedCompareExchange_HLEAcquire((volatile long*)value, old, old) != old); - break; - } - case _Py_memory_order_release: - { - do { - old = *value; - } while(_InterlockedCompareExchange_HLERelease((volatile long*)value, old, old) != old); - break; - } - case _Py_memory_order_relaxed: - old = *value; - break; - default: - { - do { - old = *value; - } while(_InterlockedCompareExchange((volatile long*)value, old, old) != old); - break; - } - } - return old; -} - -#define _Py_atomic_load_32bit(ATOMIC_VAL, ORDER) \ - _Py_atomic_load_32bit_impl((volatile int*)&((ATOMIC_VAL)->_value), (ORDER)) - -#define _Py_atomic_store_explicit(ATOMIC_VAL, NEW_VAL, ORDER) \ - if (sizeof((ATOMIC_VAL)->_value) == 8) { \ - _Py_atomic_store_64bit((ATOMIC_VAL), NEW_VAL, ORDER) } else { \ - _Py_atomic_store_32bit((ATOMIC_VAL), NEW_VAL, ORDER) } - -#define _Py_atomic_load_explicit(ATOMIC_VAL, ORDER) \ - ( \ - sizeof((ATOMIC_VAL)->_value) == 8 ? \ - _Py_atomic_load_64bit((ATOMIC_VAL), ORDER) : \ - _Py_atomic_load_32bit((ATOMIC_VAL), ORDER) \ - ) -#elif defined(_M_ARM) || defined(_M_ARM64) -typedef enum _Py_memory_order { - _Py_memory_order_relaxed, - _Py_memory_order_acquire, - _Py_memory_order_release, - _Py_memory_order_acq_rel, - _Py_memory_order_seq_cst -} _Py_memory_order; - -typedef struct _Py_atomic_address { - volatile uintptr_t _value; -} _Py_atomic_address; - -typedef struct _Py_atomic_int { - volatile int _value; -} _Py_atomic_int; - - -#if defined(_M_ARM64) -#define _Py_atomic_store_64bit(ATOMIC_VAL, NEW_VAL, ORDER) \ - switch (ORDER) { \ - case _Py_memory_order_acquire: \ - _InterlockedExchange64_acq((__int64 volatile*)&((ATOMIC_VAL)->_value), (__int64)NEW_VAL); \ - break; \ - case _Py_memory_order_release: \ - _InterlockedExchange64_rel((__int64 volatile*)&((ATOMIC_VAL)->_value), (__int64)NEW_VAL); \ - break; \ - default: \ - _InterlockedExchange64((__int64 volatile*)&((ATOMIC_VAL)->_value), (__int64)NEW_VAL); \ - break; \ - } -#else -#define _Py_atomic_store_64bit(ATOMIC_VAL, NEW_VAL, ORDER) ((void)0); -#endif - -#define _Py_atomic_store_32bit(ATOMIC_VAL, NEW_VAL, ORDER) \ - switch (ORDER) { \ - case _Py_memory_order_acquire: \ - _InterlockedExchange_acq((volatile long*)&((ATOMIC_VAL)->_value), (int)NEW_VAL); \ - break; \ - case _Py_memory_order_release: \ - _InterlockedExchange_rel((volatile long*)&((ATOMIC_VAL)->_value), (int)NEW_VAL); \ - break; \ - default: \ - _InterlockedExchange((volatile long*)&((ATOMIC_VAL)->_value), (int)NEW_VAL); \ - break; \ - } - -#if defined(_M_ARM64) -/* This has to be an intptr_t for now. - gil_created() uses -1 as a sentinel value, if this returns - a uintptr_t it will do an unsigned compare and crash -*/ -inline intptr_t _Py_atomic_load_64bit_impl(volatile uintptr_t* value, int order) { - uintptr_t old; - switch (order) { - case _Py_memory_order_acquire: - { - do { - old = *value; - } while(_InterlockedCompareExchange64_acq(value, old, old) != old); - break; - } - case _Py_memory_order_release: - { - do { - old = *value; - } while(_InterlockedCompareExchange64_rel(value, old, old) != old); - break; - } - case _Py_memory_order_relaxed: - old = *value; - break; - default: - { - do { - old = *value; - } while(_InterlockedCompareExchange64(value, old, old) != old); - break; - } - } - return old; -} - -#define _Py_atomic_load_64bit(ATOMIC_VAL, ORDER) \ - _Py_atomic_load_64bit_impl((volatile uintptr_t*)&((ATOMIC_VAL)->_value), (ORDER)) - -#else -#define _Py_atomic_load_64bit(ATOMIC_VAL, ORDER) ((ATOMIC_VAL)->_value) -#endif - -inline int _Py_atomic_load_32bit_impl(volatile int* value, int order) { - int old; - switch (order) { - case _Py_memory_order_acquire: - { - do { - old = *value; - } while(_InterlockedCompareExchange_acq(value, old, old) != old); - break; - } - case _Py_memory_order_release: - { - do { - old = *value; - } while(_InterlockedCompareExchange_rel(value, old, old) != old); - break; - } - case _Py_memory_order_relaxed: - old = *value; - break; - default: - { - do { - old = *value; - } while(_InterlockedCompareExchange(value, old, old) != old); - break; - } - } - return old; -} - -#define _Py_atomic_load_32bit(ATOMIC_VAL, ORDER) \ - _Py_atomic_load_32bit_impl((volatile int*)&((ATOMIC_VAL)->_value), (ORDER)) - -#define _Py_atomic_store_explicit(ATOMIC_VAL, NEW_VAL, ORDER) \ - if (sizeof((ATOMIC_VAL)->_value) == 8) { \ - _Py_atomic_store_64bit((ATOMIC_VAL), (NEW_VAL), (ORDER)) } else { \ - _Py_atomic_store_32bit((ATOMIC_VAL), (NEW_VAL), (ORDER)) } - -#define _Py_atomic_load_explicit(ATOMIC_VAL, ORDER) \ - ( \ - sizeof((ATOMIC_VAL)->_value) == 8 ? \ - _Py_atomic_load_64bit((ATOMIC_VAL), (ORDER)) : \ - _Py_atomic_load_32bit((ATOMIC_VAL), (ORDER)) \ - ) -#endif -#else /* !gcc x86 !_msc_ver */ -typedef enum _Py_memory_order { - _Py_memory_order_relaxed, - _Py_memory_order_acquire, - _Py_memory_order_release, - _Py_memory_order_acq_rel, - _Py_memory_order_seq_cst -} _Py_memory_order; - -typedef struct _Py_atomic_address { - uintptr_t _value; -} _Py_atomic_address; - -typedef struct _Py_atomic_int { - int _value; -} _Py_atomic_int; -/* Fall back to other compilers and processors by assuming that simple - volatile accesses are atomic. This is false, so people should port - this. */ -#define _Py_atomic_signal_fence(/*memory_order*/ ORDER) ((void)0) -#define _Py_atomic_thread_fence(/*memory_order*/ ORDER) ((void)0) -#define _Py_atomic_store_explicit(ATOMIC_VAL, NEW_VAL, ORDER) \ - ((ATOMIC_VAL)->_value = NEW_VAL) -#define _Py_atomic_load_explicit(ATOMIC_VAL, ORDER) \ - ((ATOMIC_VAL)->_value) -#endif - -/* Standardized shortcuts. */ -#define _Py_atomic_store(ATOMIC_VAL, NEW_VAL) \ - _Py_atomic_store_explicit((ATOMIC_VAL), (NEW_VAL), _Py_memory_order_seq_cst) -#define _Py_atomic_load(ATOMIC_VAL) \ - _Py_atomic_load_explicit((ATOMIC_VAL), _Py_memory_order_seq_cst) - -/* Python-local extensions */ - -#define _Py_atomic_store_relaxed(ATOMIC_VAL, NEW_VAL) \ - _Py_atomic_store_explicit((ATOMIC_VAL), (NEW_VAL), _Py_memory_order_relaxed) -#define _Py_atomic_load_relaxed(ATOMIC_VAL) \ - _Py_atomic_load_explicit((ATOMIC_VAL), _Py_memory_order_relaxed) - -#ifdef __cplusplus -} -#endif -#endif /* Py_ATOMIC_H */ diff --git a/Include/internal/pycore_atomic_funcs.h b/Include/internal/pycore_atomic_funcs.h deleted file mode 100644 index a708789cea733b..00000000000000 --- a/Include/internal/pycore_atomic_funcs.h +++ /dev/null @@ -1,94 +0,0 @@ -/* Atomic functions: similar to pycore_atomic.h, but don't need - to declare variables as atomic. - - Py_ssize_t type: - - * value = _Py_atomic_size_get(&var) - * _Py_atomic_size_set(&var, value) - - Use sequentially-consistent ordering (__ATOMIC_SEQ_CST memory order): - enforce total ordering with all other atomic functions. -*/ -#ifndef Py_ATOMIC_FUNC_H -#define Py_ATOMIC_FUNC_H -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef Py_BUILD_CORE -# error "this header requires Py_BUILD_CORE define" -#endif - -#if defined(_MSC_VER) -# include // _InterlockedExchange() -#endif - - -// Use builtin atomic operations in GCC >= 4.7 and clang -#ifdef HAVE_BUILTIN_ATOMIC - -static inline Py_ssize_t _Py_atomic_size_get(Py_ssize_t *var) -{ - return __atomic_load_n(var, __ATOMIC_SEQ_CST); -} - -static inline void _Py_atomic_size_set(Py_ssize_t *var, Py_ssize_t value) -{ - __atomic_store_n(var, value, __ATOMIC_SEQ_CST); -} - -#elif defined(_MSC_VER) - -static inline Py_ssize_t _Py_atomic_size_get(Py_ssize_t *var) -{ -#if SIZEOF_VOID_P == 8 - Py_BUILD_ASSERT(sizeof(__int64) == sizeof(*var)); - volatile __int64 *volatile_var = (volatile __int64 *)var; - __int64 old; - do { - old = *volatile_var; - } while(_InterlockedCompareExchange64(volatile_var, old, old) != old); -#else - Py_BUILD_ASSERT(sizeof(long) == sizeof(*var)); - volatile long *volatile_var = (volatile long *)var; - long old; - do { - old = *volatile_var; - } while(_InterlockedCompareExchange(volatile_var, old, old) != old); -#endif - return old; -} - -static inline void _Py_atomic_size_set(Py_ssize_t *var, Py_ssize_t value) -{ -#if SIZEOF_VOID_P == 8 - Py_BUILD_ASSERT(sizeof(__int64) == sizeof(*var)); - volatile __int64 *volatile_var = (volatile __int64 *)var; - _InterlockedExchange64(volatile_var, value); -#else - Py_BUILD_ASSERT(sizeof(long) == sizeof(*var)); - volatile long *volatile_var = (volatile long *)var; - _InterlockedExchange(volatile_var, value); -#endif -} - -#else -// Fallback implementation using volatile - -static inline Py_ssize_t _Py_atomic_size_get(Py_ssize_t *var) -{ - volatile Py_ssize_t *volatile_var = (volatile Py_ssize_t *)var; - return *volatile_var; -} - -static inline void _Py_atomic_size_set(Py_ssize_t *var, Py_ssize_t value) -{ - volatile Py_ssize_t *volatile_var = (volatile Py_ssize_t *)var; - *volatile_var = value; -} -#endif - -#ifdef __cplusplus -} -#endif -#endif /* Py_ATOMIC_FUNC_H */ diff --git a/Include/internal/pycore_bitutils.h b/Include/internal/pycore_bitutils.h index e6bf61ef425bd8..50f69377523818 100644 --- a/Include/internal/pycore_bitutils.h +++ b/Include/internal/pycore_bitutils.h @@ -26,10 +26,10 @@ extern "C" { #endif #ifdef _MSC_VER - /* Get _byteswap_ushort(), _byteswap_ulong(), _byteswap_uint64() */ -# include +# include // _byteswap_uint64() #endif + static inline uint16_t _Py_bswap16(uint16_t word) { diff --git a/Include/internal/pycore_blocks_output_buffer.h b/Include/internal/pycore_blocks_output_buffer.h index 28cf6fba4eeba2..573e10359b7bd2 100644 --- a/Include/internal/pycore_blocks_output_buffer.h +++ b/Include/internal/pycore_blocks_output_buffer.h @@ -40,6 +40,10 @@ extern "C" { #include "Python.h" +#ifndef Py_BUILD_CORE +# error "this header requires Py_BUILD_CORE define" +#endif + typedef struct { // List of bytes objects PyObject *list; @@ -314,4 +318,4 @@ _BlocksOutputBuffer_OnError(_BlocksOutputBuffer *buffer) #ifdef __cplusplus } #endif -#endif /* Py_INTERNAL_BLOCKS_OUTPUT_BUFFER_H */ \ No newline at end of file +#endif /* Py_INTERNAL_BLOCKS_OUTPUT_BUFFER_H */ diff --git a/Include/internal/pycore_bytesobject.h b/Include/internal/pycore_bytesobject.h index 980065a65f399e..94d421a9eb742a 100644 --- a/Include/internal/pycore_bytesobject.h +++ b/Include/internal/pycore_bytesobject.h @@ -28,34 +28,37 @@ PyAPI_FUNC(PyObject*) _PyBytes_DecodeEscape(const char *, Py_ssize_t, extern PyObject* _PyBytes_Join(PyObject *sep, PyObject *x); -/* Substring Search. - - Returns the index of the first occurrence of - a substring ("needle") in a larger text ("haystack"). - If the needle is not found, return -1. - If the needle is found, add offset to the index. -*/ - +// Substring Search. +// +// Returns the index of the first occurrence of +// a substring ("needle") in a larger text ("haystack"). +// If the needle is not found, return -1. +// If the needle is found, add offset to the index. +// +// Export for 'mmap' shared extension. PyAPI_FUNC(Py_ssize_t) _PyBytes_Find(const char *haystack, Py_ssize_t len_haystack, const char *needle, Py_ssize_t len_needle, Py_ssize_t offset); -/* Same as above, but search right-to-left */ +// Same as above, but search right-to-left. +// Export for 'mmap' shared extension. PyAPI_FUNC(Py_ssize_t) _PyBytes_ReverseFind(const char *haystack, Py_ssize_t len_haystack, const char *needle, Py_ssize_t len_needle, Py_ssize_t offset); -/** Helper function to implement the repeat and inplace repeat methods on a buffer - * - * len_dest is assumed to be an integer multiple of len_src. - * If src equals dest, then assume the operation is inplace. - * - * This method repeately doubles the number of bytes copied to reduce - * the number of invocations of memcpy. - */ +// Helper function to implement the repeat and inplace repeat methods on a +// buffer. +// +// len_dest is assumed to be an integer multiple of len_src. +// If src equals dest, then assume the operation is inplace. +// +// This method repeately doubles the number of bytes copied to reduce +// the number of invocations of memcpy. +// +// Export for 'array' shared extension. PyAPI_FUNC(void) _PyBytes_Repeat(char* dest, Py_ssize_t len_dest, const char* src, Py_ssize_t len_src); @@ -91,7 +94,9 @@ typedef struct { /* Initialize a bytes writer By default, the overallocation is disabled. Set the overallocate attribute - to control the allocation of the buffer. */ + to control the allocation of the buffer. + + Export _PyBytesWriter API for '_pickle' shared extension. */ PyAPI_FUNC(void) _PyBytesWriter_Init(_PyBytesWriter *writer); /* Get the buffer content and reset the writer. diff --git a/Include/internal/pycore_call.h b/Include/internal/pycore_call.h index c0d61785802f64..c92028a01299e2 100644 --- a/Include/internal/pycore_call.h +++ b/Include/internal/pycore_call.h @@ -8,6 +8,7 @@ extern "C" { # error "this header requires Py_BUILD_CORE define" #endif +#include "pycore_identifier.h" // _Py_Identifier #include "pycore_pystate.h" // _PyThreadState_GET() /* Suggested size (number of positional arguments) for arrays of PyObject* @@ -22,26 +23,14 @@ extern "C" { #define _PY_FASTCALL_SMALL_STACK 5 -// Export for 'math' shared extension, function used -// via inlined _PyObject_VectorcallTstate() function. +// Export for 'math' shared extension, used via _PyObject_VectorcallTstate() +// static inline function. PyAPI_FUNC(PyObject*) _Py_CheckFunctionResult( PyThreadState *tstate, PyObject *callable, PyObject *result, const char *where); -/* Convert keyword arguments from the FASTCALL (stack: C array, kwnames: tuple) - format to a Python dictionary ("kwargs" dict). - - The type of kwnames keys is not checked. The final function getting - arguments is responsible to check if all keys are strings, for example using - PyArg_ParseTupleAndKeywords() or PyArg_ValidateKeywordArguments(). - - Duplicate keys are merged using the last value. If duplicate keys must raise - an exception, the caller is responsible to implement an explicit keys on - kwnames. */ -extern PyObject* _PyStack_AsDict(PyObject *const *values, PyObject *kwnames); - extern PyObject* _PyObject_Call_Prepend( PyThreadState *tstate, PyObject *callable, @@ -74,13 +63,6 @@ PyAPI_FUNC(PyObject*) _PyObject_CallMethod( PyObject *name, const char *format, ...); -/* Like PyObject_CallMethod(), but expect a _Py_Identifier* - as the method name. */ -extern PyObject* _PyObject_CallMethodId( - PyObject *obj, - _Py_Identifier *name, - const char *format, ...); - extern PyObject* _PyObject_CallMethodIdObjArgs( PyObject *obj, _Py_Identifier *name, @@ -120,8 +102,8 @@ _PyObject_CallMethodIdOneArg(PyObject *self, _Py_Identifier *name, PyObject *arg // Call callable using tp_call. Arguments are like PyObject_Vectorcall(), // except that nargs is plainly the number of arguments without flags. // -// Export for 'math' shared extension, function used -// via inlined _PyObject_VectorcallTstate() function. +// Export for 'math' shared extension, used via _PyObject_VectorcallTstate() +// static inline function. PyAPI_FUNC(PyObject*) _PyObject_MakeTpCall( PyThreadState *tstate, PyObject *callable, diff --git a/Include/internal/pycore_capsule.h b/Include/internal/pycore_capsule.h new file mode 100644 index 00000000000000..aa2c67f3a8f002 --- /dev/null +++ b/Include/internal/pycore_capsule.h @@ -0,0 +1,17 @@ +#ifndef Py_INTERNAL_PYCAPSULE_H +#define Py_INTERNAL_PYCAPSULE_H +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef Py_BUILD_CORE +# error "this header requires Py_BUILD_CORE define" +#endif + +// Export for '_socket' shared extension +PyAPI_FUNC(int) _PyCapsule_SetTraverse(PyObject *op, traverseproc traverse_func, inquiry clear_func); + +#ifdef __cplusplus +} +#endif +#endif /* !Py_INTERNAL_PYCAPSULE_H */ diff --git a/Include/internal/pycore_ceval.h b/Include/internal/pycore_ceval.h index 05b7380597812b..a357bfa3a26064 100644 --- a/Include/internal/pycore_ceval.h +++ b/Include/internal/pycore_ceval.h @@ -8,28 +8,53 @@ extern "C" { # error "this header requires Py_BUILD_CORE define" #endif +#include "dynamic_annotations.h" // _Py_ANNOTATE_RWLOCK_CREATE + +#include "pycore_interp.h" // PyInterpreterState.eval_frame +#include "pycore_pystate.h" // _PyThreadState_GET() + /* Forward declarations */ struct pyruntimestate; struct _ceval_runtime_state; +// Export for '_lsprof' shared extension +PyAPI_FUNC(int) _PyEval_SetProfile(PyThreadState *tstate, Py_tracefunc func, PyObject *arg); + +extern int _PyEval_SetTrace(PyThreadState *tstate, Py_tracefunc func, PyObject *arg); + +extern int _PyEval_SetOpcodeTrace(PyFrameObject *f, bool enable); + +// Helper to look up a builtin object +// Export for 'array' shared extension +PyAPI_FUNC(PyObject*) _PyEval_GetBuiltin(PyObject *); + +extern PyObject* _PyEval_GetBuiltinId(_Py_Identifier *); + +extern void _PyEval_SetSwitchInterval(unsigned long microseconds); +extern unsigned long _PyEval_GetSwitchInterval(void); + +// Export for '_queue' shared extension +PyAPI_FUNC(int) _PyEval_MakePendingCalls(PyThreadState *); + #ifndef Py_DEFAULT_RECURSION_LIMIT # define Py_DEFAULT_RECURSION_LIMIT 1000 #endif -#include "pycore_interp.h" // PyInterpreterState.eval_frame -#include "pycore_pystate.h" // _PyThreadState_GET() - - extern void _Py_FinishPendingCalls(PyThreadState *tstate); -extern void _PyEval_InitState(PyInterpreterState *, PyThread_type_lock); -extern void _PyEval_FiniState(struct _ceval_state *ceval); +extern void _PyEval_InitState(PyInterpreterState *); extern void _PyEval_SignalReceived(PyInterpreterState *interp); + +// bitwise flags: +#define _Py_PENDING_MAINTHREADONLY 1 +#define _Py_PENDING_RAWFREE 2 + // Export for '_testinternalcapi' shared extension PyAPI_FUNC(int) _PyEval_AddPendingCall( PyInterpreterState *interp, - int (*func)(void *), + _Py_pending_call_func func, void *arg, - int mainthreadonly); + int flags); + extern void _PyEval_SignalAsyncExc(PyInterpreterState *interp); #ifdef HAVE_FORK extern PyStatus _PyEval_ReInitThreads(PyThreadState *tstate); @@ -75,6 +100,7 @@ extern int _PyPerfTrampoline_SetCallbacks(_PyPerf_Callbacks *); extern void _PyPerfTrampoline_GetCallbacks(_PyPerf_Callbacks *); extern int _PyPerfTrampoline_Init(int activate); extern int _PyPerfTrampoline_Fini(void); +extern void _PyPerfTrampoline_FreeArenas(void); extern int _PyIsPerfTrampolineActive(void); extern PyStatus _PyPerfTrampoline_AfterFork_Child(void); #ifdef PY_HAVE_PERF_TRAMPOLINE @@ -98,12 +124,11 @@ _PyEval_Vector(PyThreadState *tstate, PyObject *kwnames); extern int _PyEval_ThreadsInitialized(void); -extern PyStatus _PyEval_InitGIL(PyThreadState *tstate, int own_gil); +extern void _PyEval_InitGIL(PyThreadState *tstate, int own_gil); extern void _PyEval_FiniGIL(PyInterpreterState *interp); extern void _PyEval_AcquireLock(PyThreadState *tstate); extern void _PyEval_ReleaseLock(PyInterpreterState *, PyThreadState *); -extern PyThreadState * _PyThreadState_SwapNoGIL(PyThreadState *); extern void _PyEval_DeactivateOpCache(void); @@ -123,7 +148,8 @@ static inline int _Py_MakeRecCheck(PyThreadState *tstate) { } #endif -// Export for _Py_EnterRecursiveCall() +// Export for '_json' shared extension, used via _Py_EnterRecursiveCall() +// static inline function. PyAPI_FUNC(int) _Py_CheckRecursiveCall( PyThreadState *tstate, const char *where); @@ -171,6 +197,40 @@ void _PyEval_FormatKwargsError(PyThreadState *tstate, PyObject *func, PyObject * PyObject *_PyEval_MatchClass(PyThreadState *tstate, PyObject *subject, PyObject *type, Py_ssize_t nargs, PyObject *kwargs); PyObject *_PyEval_MatchKeys(PyThreadState *tstate, PyObject *map, PyObject *keys); int _PyEval_UnpackIterable(PyThreadState *tstate, PyObject *v, int argcnt, int argcntafter, PyObject **sp); +void _PyEval_FrameClearAndPop(PyThreadState *tstate, _PyInterpreterFrame *frame); + + +#define _PY_GIL_DROP_REQUEST_BIT 0 +#define _PY_SIGNALS_PENDING_BIT 1 +#define _PY_CALLS_TO_DO_BIT 2 +#define _PY_ASYNC_EXCEPTION_BIT 3 +#define _PY_GC_SCHEDULED_BIT 4 + +/* Reserve a few bits for future use */ +#define _PY_EVAL_EVENTS_BITS 8 +#define _PY_EVAL_EVENTS_MASK ((1 << _PY_EVAL_EVENTS_BITS)-1) + +static inline void +_Py_set_eval_breaker_bit(PyInterpreterState *interp, uint32_t bit, uint32_t set) +{ + assert(set == 0 || set == 1); + uintptr_t to_set = set << bit; + uintptr_t mask = ((uintptr_t)1) << bit; + uintptr_t old = _Py_atomic_load_uintptr(&interp->ceval.eval_breaker); + if ((old & mask) == to_set) { + return; + } + uintptr_t new; + do { + new = (old & ~mask) | to_set; + } while (!_Py_atomic_compare_exchange_uintptr(&interp->ceval.eval_breaker, &old, new)); +} + +static inline bool +_Py_eval_breaker_bit_is_set(PyInterpreterState *interp, int32_t bit) +{ + return _Py_atomic_load_uintptr_relaxed(&interp->ceval.eval_breaker) & (((uintptr_t)1) << bit); +} #ifdef __cplusplus diff --git a/Include/internal/pycore_ceval_state.h b/Include/internal/pycore_ceval_state.h index 1ebfcc9bebd0ab..28738980eb49be 100644 --- a/Include/internal/pycore_ceval_state.h +++ b/Include/internal/pycore_ceval_state.h @@ -8,24 +8,22 @@ extern "C" { # error "this header requires Py_BUILD_CORE define" #endif - -#include "pycore_atomic.h" /* _Py_atomic_address */ +#include "pycore_lock.h" // PyMutex #include "pycore_gil.h" // struct _gil_runtime_state +typedef int (*_Py_pending_call_func)(void *); + struct _pending_calls { int busy; - PyThread_type_lock lock; + PyMutex mutex; /* Request for running pending calls. */ - _Py_atomic_int calls_to_do; - /* Request for looking at the `async_exc` field of the current - thread state. - Guarded by the GIL. */ - int async_exc; + int32_t calls_to_do; #define NPENDINGCALLS 32 struct _pending_call { - int (*func)(void *); + _Py_pending_call_func func; void *arg; + int flags; } calls[NPENDINGCALLS]; int first; int last; @@ -58,15 +56,11 @@ struct _ceval_runtime_state { struct code_arena_st *code_arena; struct trampoline_api_st trampoline_api; FILE *map_file; + Py_ssize_t persist_after_fork; #else int _not_used; #endif } perf; - /* Request for checking signals. It is shared by all interpreters (see - bpo-40513). Any thread of any interpreter can receive a signal, but only - the main thread of the main interpreter can handle signals: see - _Py_ThreadCanHandleSignals(). */ - _Py_atomic_int signals_pending; /* Pending calls to be made only on the main thread. */ struct _pending_calls pending_mainthread; }; @@ -76,6 +70,7 @@ struct _ceval_runtime_state { { \ .status = PERF_STATUS_NO_INIT, \ .extra_code_index = -1, \ + .persist_after_fork = 0, \ } #else # define _PyEval_RUNTIME_PERF_INIT {0} @@ -87,14 +82,12 @@ struct _ceval_state { * the fast path in the eval loop. * It is by far the hottest field in this struct and * should be placed at the beginning. */ - _Py_atomic_int eval_breaker; - /* Request for dropping the GIL */ - _Py_atomic_int gil_drop_request; + uintptr_t eval_breaker; + /* Avoid false sharing */ + int64_t padding[7]; int recursion_limit; struct _gil_runtime_state *gil; int own_gil; - /* The GC is ready to be executed */ - _Py_atomic_int gc_scheduled; struct _pending_calls pending; }; diff --git a/Include/internal/pycore_code.h b/Include/internal/pycore_code.h index 00099376635e9b..73df6c3568ffe0 100644 --- a/Include/internal/pycore_code.h +++ b/Include/internal/pycore_code.h @@ -4,6 +4,10 @@ extern "C" { #endif +#ifndef Py_BUILD_CORE +# error "this header requires Py_BUILD_CORE define" +#endif + #define CODE_MAX_WATCHERS 8 /* PEP 659 @@ -229,6 +233,9 @@ extern void _PyLineTable_InitAddressRange( extern int _PyLineTable_NextAddressRange(PyCodeAddressRange *range); extern int _PyLineTable_PreviousAddressRange(PyCodeAddressRange *range); +/** API for executors */ +extern void _PyCode_Clear_Executors(PyCodeObject *code); + #define ENABLE_SPECIALIZATION 1 /* Specialization functions */ @@ -246,7 +253,7 @@ extern void _Py_Specialize_BinarySubscr(PyObject *sub, PyObject *container, extern void _Py_Specialize_StoreSubscr(PyObject *container, PyObject *sub, _Py_CODEUNIT *instr); extern void _Py_Specialize_Call(PyObject *callable, _Py_CODEUNIT *instr, - int nargs, PyObject *kwnames); + int nargs); extern void _Py_Specialize_BinaryOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr, int oparg, PyObject **locals); extern void _Py_Specialize_CompareOp(PyObject *lhs, PyObject *rhs, @@ -264,17 +271,30 @@ extern int _PyStaticCode_Init(PyCodeObject *co); #ifdef Py_STATS -#define STAT_INC(opname, name) do { if (_py_stats) _py_stats->opcode_stats[opname].specialization.name++; } while (0) -#define STAT_DEC(opname, name) do { if (_py_stats) _py_stats->opcode_stats[opname].specialization.name--; } while (0) -#define OPCODE_EXE_INC(opname) do { if (_py_stats) _py_stats->opcode_stats[opname].execution_count++; } while (0) -#define CALL_STAT_INC(name) do { if (_py_stats) _py_stats->call_stats.name++; } while (0) -#define OBJECT_STAT_INC(name) do { if (_py_stats) _py_stats->object_stats.name++; } while (0) +#include "pycore_bitutils.h" // _Py_bit_length + +#define STAT_INC(opname, name) do { if (_Py_stats) _Py_stats->opcode_stats[opname].specialization.name++; } while (0) +#define STAT_DEC(opname, name) do { if (_Py_stats) _Py_stats->opcode_stats[opname].specialization.name--; } while (0) +#define OPCODE_EXE_INC(opname) do { if (_Py_stats) _Py_stats->opcode_stats[opname].execution_count++; } while (0) +#define CALL_STAT_INC(name) do { if (_Py_stats) _Py_stats->call_stats.name++; } while (0) +#define OBJECT_STAT_INC(name) do { if (_Py_stats) _Py_stats->object_stats.name++; } while (0) #define OBJECT_STAT_INC_COND(name, cond) \ - do { if (_py_stats && cond) _py_stats->object_stats.name++; } while (0) -#define EVAL_CALL_STAT_INC(name) do { if (_py_stats) _py_stats->call_stats.eval_calls[name]++; } while (0) + do { if (_Py_stats && cond) _Py_stats->object_stats.name++; } while (0) +#define EVAL_CALL_STAT_INC(name) do { if (_Py_stats) _Py_stats->call_stats.eval_calls[name]++; } while (0) #define EVAL_CALL_STAT_INC_IF_FUNCTION(name, callable) \ - do { if (_py_stats && PyFunction_Check(callable)) _py_stats->call_stats.eval_calls[name]++; } while (0) -#define GC_STAT_ADD(gen, name, n) do { if (_py_stats) _py_stats->gc_stats[(gen)].name += (n); } while (0) + do { if (_Py_stats && PyFunction_Check(callable)) _Py_stats->call_stats.eval_calls[name]++; } while (0) +#define GC_STAT_ADD(gen, name, n) do { if (_Py_stats) _Py_stats->gc_stats[(gen)].name += (n); } while (0) +#define OPT_STAT_INC(name) do { if (_Py_stats) _Py_stats->optimization_stats.name++; } while (0) +#define UOP_STAT_INC(opname, name) do { if (_Py_stats) { assert(opname < 512); _Py_stats->optimization_stats.opcode[opname].name++; } } while (0) +#define OPT_UNSUPPORTED_OPCODE(opname) do { if (_Py_stats) _Py_stats->optimization_stats.unsupported_opcode[opname]++; } while (0) +#define OPT_HIST(length, name) \ + do { \ + if (_Py_stats) { \ + int bucket = _Py_bit_length(length >= 1 ? length - 1 : 0); \ + bucket = (bucket >= _Py_UOP_HIST_SIZE) ? _Py_UOP_HIST_SIZE - 1 : bucket; \ + _Py_stats->optimization_stats.name[bucket]++; \ + } \ + } while (0) // Export for '_opcode' shared extension PyAPI_FUNC(PyObject*) _Py_GetSpecializationStats(void); @@ -289,6 +309,10 @@ PyAPI_FUNC(PyObject*) _Py_GetSpecializationStats(void); #define EVAL_CALL_STAT_INC(name) ((void)0) #define EVAL_CALL_STAT_INC_IF_FUNCTION(name, callable) ((void)0) #define GC_STAT_ADD(gen, name, n) ((void)0) +#define OPT_STAT_INC(name) ((void)0) +#define UOP_STAT_INC(opname, name) ((void)0) +#define OPT_UNSUPPORTED_OPCODE(opname) ((void)0) +#define OPT_HIST(length, name) ((void)0) #endif // !Py_STATS // Utility functions for reading/writing 32/64-bit values in the inline caches. @@ -370,27 +394,29 @@ write_varint(uint8_t *ptr, unsigned int val) val >>= 6; written++; } - *ptr = val; + *ptr = (uint8_t)val; return written; } static inline int write_signed_varint(uint8_t *ptr, int val) { + unsigned int uval; if (val < 0) { - val = ((-val)<<1) | 1; + // (unsigned int)(-val) has an undefined behavior for INT_MIN + uval = ((0 - (unsigned int)val) << 1) | 1; } else { - val = val << 1; + uval = (unsigned int)val << 1; } - return write_varint(ptr, val); + return write_varint(ptr, uval); } static inline int write_location_entry_start(uint8_t *ptr, int code, int length) { assert((code & 15) == code); - *ptr = 128 | (code << 3) | (length - 1); + *ptr = 128 | (uint8_t)(code << 3) | (uint8_t)(length - 1); return 1; } @@ -430,9 +456,9 @@ write_location_entry_start(uint8_t *ptr, int code, int length) static inline uint16_t -adaptive_counter_bits(int value, int backoff) { - return (value << ADAPTIVE_BACKOFF_BITS) | - (backoff & ((1< MAX_BACKOFF_VALUE) { backoff = MAX_BACKOFF_VALUE; } - unsigned int value = (1 << backoff) - 1; + uint16_t value = (uint16_t)(1 << backoff) - 1; return adaptive_counter_bits(value, backoff); } -extern uint32_t _Py_next_func_version; - /* Comparison bit masks. */ diff --git a/Include/internal/pycore_codecs.h b/Include/internal/pycore_codecs.h index a2465192eacd5e..a2a7151d50ade7 100644 --- a/Include/internal/pycore_codecs.h +++ b/Include/internal/pycore_codecs.h @@ -4,6 +4,10 @@ extern "C" { #endif +#ifndef Py_BUILD_CORE +# error "this header requires Py_BUILD_CORE define" +#endif + extern PyObject* _PyCodec_Lookup(const char *encoding); /* Text codec specific encoding and decoding API. diff --git a/Include/internal/pycore_compile.h b/Include/internal/pycore_compile.h index fa2f64021e73c9..e5870759ba74f1 100644 --- a/Include/internal/pycore_compile.h +++ b/Include/internal/pycore_compile.h @@ -19,6 +19,14 @@ PyAPI_FUNC(PyCodeObject*) _PyAST_Compile( int optimize, struct _arena *arena); +/* AST optimizations */ +extern int _PyCompile_AstOptimize( + struct _mod *mod, + PyObject *filename, + PyCompilerFlags *flags, + int optimize, + struct _arena *arena); + static const _PyCompilerSrcLocation NO_LOCATION = {-1, -1, -1, -1}; extern int _PyAST_Optimize( @@ -54,6 +62,11 @@ typedef struct { int s_next_free_label; /* next free label id */ } _PyCompile_InstructionSequence; +int _PyCompile_InstructionSequence_UseLabel(_PyCompile_InstructionSequence *seq, int lbl); +int _PyCompile_InstructionSequence_Addop(_PyCompile_InstructionSequence *seq, + int opcode, int oparg, + _PyCompilerSrcLocation loc); + typedef struct { PyObject *u_name; PyObject *u_qualname; /* dot-separated qualified name (lazy) */ @@ -89,11 +102,26 @@ int _PyCompile_EnsureArrayLargeEnough( int _PyCompile_ConstCacheMergeOne(PyObject *const_cache, PyObject **obj); + +// Export for '_opcode' extention module +PyAPI_FUNC(int) _PyCompile_OpcodeIsValid(int opcode); +PyAPI_FUNC(int) _PyCompile_OpcodeHasArg(int opcode); +PyAPI_FUNC(int) _PyCompile_OpcodeHasConst(int opcode); +PyAPI_FUNC(int) _PyCompile_OpcodeHasName(int opcode); +PyAPI_FUNC(int) _PyCompile_OpcodeHasJump(int opcode); +PyAPI_FUNC(int) _PyCompile_OpcodeHasFree(int opcode); +PyAPI_FUNC(int) _PyCompile_OpcodeHasLocal(int opcode); +PyAPI_FUNC(int) _PyCompile_OpcodeHasExc(int opcode); + +PyAPI_FUNC(PyObject*) _PyCompile_GetUnaryIntrinsicName(int index); +PyAPI_FUNC(PyObject*) _PyCompile_GetBinaryIntrinsicName(int index); + /* Access compiler internals for unit testing */ // Export for '_testinternalcapi' shared extension PyAPI_FUNC(PyObject*) _PyCompile_CleanDoc(PyObject *doc); +// Export for '_testinternalcapi' shared extension PyAPI_FUNC(PyObject*) _PyCompile_CodeGen( PyObject *ast, PyObject *filename, @@ -101,11 +129,13 @@ PyAPI_FUNC(PyObject*) _PyCompile_CodeGen( int optimize, int compile_mode); +// Export for '_testinternalcapi' shared extension PyAPI_FUNC(PyObject*) _PyCompile_OptimizeCfg( PyObject *instructions, PyObject *consts, int nlocals); +// Export for '_testinternalcapi' shared extension PyAPI_FUNC(PyCodeObject*) _PyCompile_Assemble(_PyCompile_CodeUnitMetadata *umd, PyObject *filename, PyObject *instructions); diff --git a/Include/internal/pycore_complexobject.h b/Include/internal/pycore_complexobject.h index 7843c0a008ebb6..54713536eedc46 100644 --- a/Include/internal/pycore_complexobject.h +++ b/Include/internal/pycore_complexobject.h @@ -10,16 +10,6 @@ extern "C" { #include "pycore_unicodeobject.h" // _PyUnicodeWriter -/* Operations on complex numbers from complexmodule.c */ - -PyAPI_FUNC(Py_complex) _Py_c_sum(Py_complex, Py_complex); -PyAPI_FUNC(Py_complex) _Py_c_diff(Py_complex, Py_complex); -PyAPI_FUNC(Py_complex) _Py_c_neg(Py_complex); -PyAPI_FUNC(Py_complex) _Py_c_prod(Py_complex, Py_complex); -PyAPI_FUNC(Py_complex) _Py_c_quot(Py_complex, Py_complex); -PyAPI_FUNC(Py_complex) _Py_c_pow(Py_complex, Py_complex); -PyAPI_FUNC(double) _Py_c_abs(Py_complex); - /* Format the object based on the format_spec, as defined in PEP 3101 (Advanced String Formatting). */ extern int _PyComplex_FormatAdvancedWriter( diff --git a/Include/internal/pycore_condvar.h b/Include/internal/pycore_condvar.h index 981c962bf7dfdf..34c21aaad43197 100644 --- a/Include/internal/pycore_condvar.h +++ b/Include/internal/pycore_condvar.h @@ -5,14 +5,8 @@ # error "this header requires Py_BUILD_CORE define" #endif -#ifndef _POSIX_THREADS -/* This means pthreads are not implemented in libc headers, hence the macro - not present in unistd.h. But they still can be implemented as an external - library (e.g. gnu pth in pthread emulation) */ -# ifdef HAVE_PTHREAD_H -# include /* _POSIX_THREADS */ -# endif -#endif +#include "pycore_pythread.h" // _POSIX_THREADS + #ifdef _POSIX_THREADS /* @@ -21,7 +15,7 @@ #define Py_HAVE_CONDVAR #ifdef HAVE_PTHREAD_H -# include +# include // pthread_mutex_t #endif #define PyMUTEX_T pthread_mutex_t @@ -38,7 +32,7 @@ /* include windows if it hasn't been done before */ #define WIN32_LEAN_AND_MEAN -#include +#include // CRITICAL_SECTION /* options */ /* non-emulated condition variables are provided for those that want diff --git a/Include/internal/pycore_context.h b/Include/internal/pycore_context.h index 52dfe3ef233874..ec884e9e0f55a9 100644 --- a/Include/internal/pycore_context.h +++ b/Include/internal/pycore_context.h @@ -5,7 +5,7 @@ # error "this header requires Py_BUILD_CORE define" #endif -#include "pycore_hamt.h" /* PyHamtObject */ +#include "pycore_hamt.h" // PyHamtObject extern PyTypeObject _PyContextTokenMissing_Type; @@ -68,4 +68,9 @@ struct _pycontexttokenobject { }; +// _testinternalcapi.hamt() used by tests. +// Export for '_testcapi' shared extension +PyAPI_FUNC(PyObject*) _PyContext_NewHamtForTests(void); + + #endif /* !Py_INTERNAL_CONTEXT_H */ diff --git a/Include/internal/pycore_critical_section.h b/Include/internal/pycore_critical_section.h new file mode 100644 index 00000000000000..bf2bbfffc38bd0 --- /dev/null +++ b/Include/internal/pycore_critical_section.h @@ -0,0 +1,242 @@ +#ifndef Py_INTERNAL_CRITICAL_SECTION_H +#define Py_INTERNAL_CRITICAL_SECTION_H + +#ifndef Py_BUILD_CORE +# error "this header requires Py_BUILD_CORE define" +#endif + +#include "pycore_lock.h" // PyMutex +#include "pycore_pystate.h" // _PyThreadState_GET() +#include + +#ifdef __cplusplus +extern "C" { +#endif + +// Implementation of Python critical sections +// +// Conceptually, critical sections are a deadlock avoidance layer on top of +// per-object locks. These helpers, in combination with those locks, replace +// our usage of the global interpreter lock to provide thread-safety for +// otherwise thread-unsafe objects, such as dict. +// +// NOTE: These APIs are no-ops in non-free-threaded builds. +// +// Straightforward per-object locking could introduce deadlocks that were not +// present when running with the GIL. Threads may hold locks for multiple +// objects simultaneously because Python operations can nest. If threads were +// to acquire the same locks in different orders, they would deadlock. +// +// One way to avoid deadlocks is to allow threads to hold only the lock (or +// locks) for a single operation at a time (typically a single lock, but some +// operations involve two locks). When a thread begins a nested operation it +// could suspend the locks for any outer operation: before beginning the nested +// operation, the locks for the outer operation are released and when the +// nested operation completes, the locks for the outer operation are +// reacquired. +// +// To improve performance, this API uses a variation of the above scheme. +// Instead of immediately suspending locks any time a nested operation begins, +// locks are only suspended if the thread would block. This reduces the number +// of lock acquisitions and releases for nested operations, while still +// avoiding deadlocks. +// +// Additionally, the locks for any active operation are suspended around +// other potentially blocking operations, such as I/O. This is because the +// interaction between locks and blocking operations can lead to deadlocks in +// the same way as the interaction between multiple locks. +// +// Each thread's critical sections and their corresponding locks are tracked in +// a stack in `PyThreadState.critical_section`. When a thread calls +// `_PyThreadState_Detach()`, such as before a blocking I/O operation or when +// waiting to acquire a lock, the thread suspends all of its active critical +// sections, temporarily releasing the associated locks. When the thread calls +// `_PyThreadState_Attach()`, it resumes the top-most (i.e., most recent) +// critical section by reacquiring the associated lock or locks. See +// `_PyCriticalSection_Resume()`. +// +// NOTE: Only the top-most critical section is guaranteed to be active. +// Operations that need to lock two objects at once must use +// `Py_BEGIN_CRITICAL_SECTION2()`. You *CANNOT* use nested critical sections +// to lock more than one object at once, because the inner critical section +// may suspend the outer critical sections. This API does not provide a way +// to lock more than two objects at once (though it could be added later +// if actually needed). +// +// NOTE: Critical sections implicitly behave like reentrant locks because +// attempting to acquire the same lock will suspend any outer (earlier) +// critical sections. However, they are less efficient for this use case than +// purposefully designed reentrant locks. +// +// Example usage: +// Py_BEGIN_CRITICAL_SECTION(op); +// ... +// Py_END_CRITICAL_SECTION(); +// +// To lock two objects at once: +// Py_BEGIN_CRITICAL_SECTION2(op1, op2); +// ... +// Py_END_CRITICAL_SECTION2(); + + +// Tagged pointers to critical sections use the two least significant bits to +// mark if the pointed-to critical section is inactive and whether it is a +// _PyCriticalSection2 object. +#define _Py_CRITICAL_SECTION_INACTIVE 0x1 +#define _Py_CRITICAL_SECTION_TWO_MUTEXES 0x2 +#define _Py_CRITICAL_SECTION_MASK 0x3 + +#ifdef Py_GIL_DISABLED +# define Py_BEGIN_CRITICAL_SECTION(op) \ + { \ + _PyCriticalSection _cs; \ + _PyCriticalSection_Begin(&_cs, &_PyObject_CAST(op)->ob_mutex) + +# define Py_END_CRITICAL_SECTION() \ + _PyCriticalSection_End(&_cs); \ + } + +# define Py_BEGIN_CRITICAL_SECTION2(a, b) \ + { \ + _PyCriticalSection2 _cs2; \ + _PyCriticalSection2_Begin(&_cs2, &_PyObject_CAST(a)->ob_mutex, &_PyObject_CAST(b)->ob_mutex) + +# define Py_END_CRITICAL_SECTION2() \ + _PyCriticalSection2_End(&_cs2); \ + } +#else /* !Py_GIL_DISABLED */ +// The critical section APIs are no-ops with the GIL. +# define Py_BEGIN_CRITICAL_SECTION(op) +# define Py_END_CRITICAL_SECTION() +# define Py_BEGIN_CRITICAL_SECTION2(a, b) +# define Py_END_CRITICAL_SECTION2() +#endif /* !Py_GIL_DISABLED */ + +typedef struct { + // Tagged pointer to an outer active critical section (or 0). + // The two least-significant-bits indicate whether the pointed-to critical + // section is inactive and whether it is a _PyCriticalSection2 object. + uintptr_t prev; + + // Mutex used to protect critical section + PyMutex *mutex; +} _PyCriticalSection; + +// A critical section protected by two mutexes. Use +// _PyCriticalSection2_Begin and _PyCriticalSection2_End. +typedef struct { + _PyCriticalSection base; + + PyMutex *mutex2; +} _PyCriticalSection2; + +static inline int +_PyCriticalSection_IsActive(uintptr_t tag) +{ + return tag != 0 && (tag & _Py_CRITICAL_SECTION_INACTIVE) == 0; +} + +// Resumes the top-most critical section. +PyAPI_FUNC(void) +_PyCriticalSection_Resume(PyThreadState *tstate); + +// (private) slow path for locking the mutex +PyAPI_FUNC(void) +_PyCriticalSection_BeginSlow(_PyCriticalSection *c, PyMutex *m); + +PyAPI_FUNC(void) +_PyCriticalSection2_BeginSlow(_PyCriticalSection2 *c, PyMutex *m1, PyMutex *m2, + int is_m1_locked); + +static inline void +_PyCriticalSection_Begin(_PyCriticalSection *c, PyMutex *m) +{ + if (PyMutex_LockFast(&m->v)) { + PyThreadState *tstate = _PyThreadState_GET(); + c->mutex = m; + c->prev = tstate->critical_section; + tstate->critical_section = (uintptr_t)c; + } + else { + _PyCriticalSection_BeginSlow(c, m); + } +} + +// Removes the top-most critical section from the thread's stack of critical +// sections. If the new top-most critical section is inactive, then it is +// resumed. +static inline void +_PyCriticalSection_Pop(_PyCriticalSection *c) +{ + PyThreadState *tstate = _PyThreadState_GET(); + uintptr_t prev = c->prev; + tstate->critical_section = prev; + + if ((prev & _Py_CRITICAL_SECTION_INACTIVE) != 0) { + _PyCriticalSection_Resume(tstate); + } +} + +static inline void +_PyCriticalSection_End(_PyCriticalSection *c) +{ + PyMutex_Unlock(c->mutex); + _PyCriticalSection_Pop(c); +} + +static inline void +_PyCriticalSection2_Begin(_PyCriticalSection2 *c, PyMutex *m1, PyMutex *m2) +{ + if (m1 == m2) { + // If the two mutex arguments are the same, treat this as a critical + // section with a single mutex. + c->mutex2 = NULL; + _PyCriticalSection_Begin(&c->base, m1); + return; + } + + if ((uintptr_t)m2 < (uintptr_t)m1) { + // Sort the mutexes so that the lower address is locked first. + // The exact order does not matter, but we need to acquire the mutexes + // in a consistent order to avoid lock ordering deadlocks. + PyMutex *tmp = m1; + m1 = m2; + m2 = tmp; + } + + if (PyMutex_LockFast(&m1->v)) { + if (PyMutex_LockFast(&m2->v)) { + PyThreadState *tstate = _PyThreadState_GET(); + c->base.mutex = m1; + c->mutex2 = m2; + c->base.prev = tstate->critical_section; + + uintptr_t p = (uintptr_t)c | _Py_CRITICAL_SECTION_TWO_MUTEXES; + tstate->critical_section = p; + } + else { + _PyCriticalSection2_BeginSlow(c, m1, m2, 1); + } + } + else { + _PyCriticalSection2_BeginSlow(c, m1, m2, 0); + } +} + +static inline void +_PyCriticalSection2_End(_PyCriticalSection2 *c) +{ + if (c->mutex2) { + PyMutex_Unlock(c->mutex2); + } + PyMutex_Unlock(c->base.mutex); + _PyCriticalSection_Pop(&c->base); +} + +PyAPI_FUNC(void) +_PyCriticalSection_SuspendAll(PyThreadState *tstate); + +#ifdef __cplusplus +} +#endif +#endif /* !Py_INTERNAL_CRITICAL_SECTION_H */ diff --git a/Include/internal/pycore_crossinterp.h b/Include/internal/pycore_crossinterp.h new file mode 100644 index 00000000000000..d6e297a7e8e6db --- /dev/null +++ b/Include/internal/pycore_crossinterp.h @@ -0,0 +1,293 @@ +#ifndef Py_INTERNAL_CROSSINTERP_H +#define Py_INTERNAL_CROSSINTERP_H +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef Py_BUILD_CORE +# error "this header requires Py_BUILD_CORE define" +#endif + +#include "pycore_lock.h" // PyMutex +#include "pycore_pyerrors.h" + +/**************/ +/* exceptions */ +/**************/ + +PyAPI_DATA(PyObject *) PyExc_InterpreterError; +PyAPI_DATA(PyObject *) PyExc_InterpreterNotFoundError; + + +/***************************/ +/* cross-interpreter calls */ +/***************************/ + +typedef int (*_Py_simple_func)(void *); +extern int _Py_CallInInterpreter( + PyInterpreterState *interp, + _Py_simple_func func, + void *arg); +extern int _Py_CallInInterpreterAndRawFree( + PyInterpreterState *interp, + _Py_simple_func func, + void *arg); + + +/**************************/ +/* cross-interpreter data */ +/**************************/ + +typedef struct _xid _PyCrossInterpreterData; +typedef PyObject *(*xid_newobjectfunc)(_PyCrossInterpreterData *); +typedef void (*xid_freefunc)(void *); + +// _PyCrossInterpreterData is similar to Py_buffer as an effectively +// opaque struct that holds data outside the object machinery. This +// is necessary to pass safely between interpreters in the same process. +struct _xid { + // data is the cross-interpreter-safe derivation of a Python object + // (see _PyObject_GetCrossInterpreterData). It will be NULL if the + // new_object func (below) encodes the data. + void *data; + // obj is the Python object from which the data was derived. This + // is non-NULL only if the data remains bound to the object in some + // way, such that the object must be "released" (via a decref) when + // the data is released. In that case the code that sets the field, + // likely a registered "crossinterpdatafunc", is responsible for + // ensuring it owns the reference (i.e. incref). + PyObject *obj; + // interp is the ID of the owning interpreter of the original + // object. It corresponds to the active interpreter when + // _PyObject_GetCrossInterpreterData() was called. This should only + // be set by the cross-interpreter machinery. + // + // We use the ID rather than the PyInterpreterState to avoid issues + // with deleted interpreters. Note that IDs are never re-used, so + // each one will always correspond to a specific interpreter + // (whether still alive or not). + int64_t interpid; + // new_object is a function that returns a new object in the current + // interpreter given the data. The resulting object (a new + // reference) will be equivalent to the original object. This field + // is required. + xid_newobjectfunc new_object; + // free is called when the data is released. If it is NULL then + // nothing will be done to free the data. For some types this is + // okay (e.g. bytes) and for those types this field should be set + // to NULL. However, for most the data was allocated just for + // cross-interpreter use, so it must be freed when + // _PyCrossInterpreterData_Release is called or the memory will + // leak. In that case, at the very least this field should be set + // to PyMem_RawFree (the default if not explicitly set to NULL). + // The call will happen with the original interpreter activated. + xid_freefunc free; +}; + +PyAPI_FUNC(_PyCrossInterpreterData *) _PyCrossInterpreterData_New(void); +PyAPI_FUNC(void) _PyCrossInterpreterData_Free(_PyCrossInterpreterData *data); + + +/* defining cross-interpreter data */ + +PyAPI_FUNC(void) _PyCrossInterpreterData_Init( + _PyCrossInterpreterData *data, + PyInterpreterState *interp, void *shared, PyObject *obj, + xid_newobjectfunc new_object); +PyAPI_FUNC(int) _PyCrossInterpreterData_InitWithSize( + _PyCrossInterpreterData *, + PyInterpreterState *interp, const size_t, PyObject *, + xid_newobjectfunc); +PyAPI_FUNC(void) _PyCrossInterpreterData_Clear( + PyInterpreterState *, _PyCrossInterpreterData *); + + +/* using cross-interpreter data */ + +PyAPI_FUNC(int) _PyObject_CheckCrossInterpreterData(PyObject *); +PyAPI_FUNC(int) _PyObject_GetCrossInterpreterData(PyObject *, _PyCrossInterpreterData *); +PyAPI_FUNC(PyObject *) _PyCrossInterpreterData_NewObject(_PyCrossInterpreterData *); +PyAPI_FUNC(int) _PyCrossInterpreterData_Release(_PyCrossInterpreterData *); +PyAPI_FUNC(int) _PyCrossInterpreterData_ReleaseAndRawFree(_PyCrossInterpreterData *); + + +/* cross-interpreter data registry */ + +// For now we use a global registry of shareable classes. An +// alternative would be to add a tp_* slot for a class's +// crossinterpdatafunc. It would be simpler and more efficient. + +typedef int (*crossinterpdatafunc)(PyThreadState *tstate, PyObject *, + _PyCrossInterpreterData *); + +struct _xidregitem; + +struct _xidregitem { + struct _xidregitem *prev; + struct _xidregitem *next; + /* This can be a dangling pointer, but only if weakref is set. */ + PyTypeObject *cls; + /* This is NULL for builtin types. */ + PyObject *weakref; + size_t refcount; + crossinterpdatafunc getdata; +}; + +struct _xidregistry { + int global; /* builtin types or heap types */ + int initialized; + PyMutex mutex; + struct _xidregitem *head; +}; + +PyAPI_FUNC(int) _PyCrossInterpreterData_RegisterClass(PyTypeObject *, crossinterpdatafunc); +PyAPI_FUNC(int) _PyCrossInterpreterData_UnregisterClass(PyTypeObject *); +PyAPI_FUNC(crossinterpdatafunc) _PyCrossInterpreterData_Lookup(PyObject *); + + +/*****************************/ +/* runtime state & lifecycle */ +/*****************************/ + +struct _xi_runtime_state { + // builtin types + // XXX Remove this field once we have a tp_* slot. + struct _xidregistry registry; +}; + +struct _xi_state { + // heap types + // XXX Remove this field once we have a tp_* slot. + struct _xidregistry registry; + + // heap types + PyObject *PyExc_NotShareableError; +}; + +extern PyStatus _PyXI_Init(PyInterpreterState *interp); +extern void _PyXI_Fini(PyInterpreterState *interp); + +extern PyStatus _PyXI_InitTypes(PyInterpreterState *interp); +extern void _PyXI_FiniTypes(PyInterpreterState *interp); + + +/***************************/ +/* short-term data sharing */ +/***************************/ + +// Ultimately we'd like to preserve enough information about the +// exception and traceback that we could re-constitute (or at least +// simulate, a la traceback.TracebackException), and even chain, a copy +// of the exception in the calling interpreter. + +typedef struct _excinfo { + struct _excinfo_type { + PyTypeObject *builtin; + const char *name; + const char *qualname; + const char *module; + } type; + const char *msg; + const char *errdisplay; +} _PyXI_excinfo; + + +typedef enum error_code { + _PyXI_ERR_NO_ERROR = 0, + _PyXI_ERR_UNCAUGHT_EXCEPTION = -1, + _PyXI_ERR_OTHER = -2, + _PyXI_ERR_NO_MEMORY = -3, + _PyXI_ERR_ALREADY_RUNNING = -4, + _PyXI_ERR_MAIN_NS_FAILURE = -5, + _PyXI_ERR_APPLY_NS_FAILURE = -6, + _PyXI_ERR_NOT_SHAREABLE = -7, +} _PyXI_errcode; + + +typedef struct _sharedexception { + // The originating interpreter. + PyInterpreterState *interp; + // The kind of error to propagate. + _PyXI_errcode code; + // The exception information to propagate, if applicable. + // This is populated only for some error codes, + // but always for _PyXI_ERR_UNCAUGHT_EXCEPTION. + _PyXI_excinfo uncaught; +} _PyXI_error; + +PyAPI_FUNC(PyObject *) _PyXI_ApplyError(_PyXI_error *err); + + +typedef struct xi_session _PyXI_session; +typedef struct _sharedns _PyXI_namespace; + +PyAPI_FUNC(void) _PyXI_FreeNamespace(_PyXI_namespace *ns); +PyAPI_FUNC(_PyXI_namespace *) _PyXI_NamespaceFromNames(PyObject *names); +PyAPI_FUNC(int) _PyXI_FillNamespaceFromDict( + _PyXI_namespace *ns, + PyObject *nsobj, + _PyXI_session *session); +PyAPI_FUNC(int) _PyXI_ApplyNamespace( + _PyXI_namespace *ns, + PyObject *nsobj, + PyObject *dflt); + + +// A cross-interpreter session involves entering an interpreter +// (_PyXI_Enter()), doing some work with it, and finally exiting +// that interpreter (_PyXI_Exit()). +// +// At the boundaries of the session, both entering and exiting, +// data may be exchanged between the previous interpreter and the +// target one in a thread-safe way that does not violate the +// isolation between interpreters. This includes setting objects +// in the target's __main__ module on the way in, and capturing +// uncaught exceptions on the way out. +struct xi_session { + // Once a session has been entered, this is the tstate that was + // current before the session. If it is different from cur_tstate + // then we must have switched interpreters. Either way, this will + // be the current tstate once we exit the session. + PyThreadState *prev_tstate; + // Once a session has been entered, this is the current tstate. + // It must be current when the session exits. + PyThreadState *init_tstate; + // This is true if init_tstate needs cleanup during exit. + int own_init_tstate; + + // This is true if, while entering the session, init_thread took + // "ownership" of the interpreter's __main__ module. This means + // it is the only thread that is allowed to run code there. + // (Caveat: for now, users may still run exec() against the + // __main__ module's dict, though that isn't advisable.) + int running; + // This is a cached reference to the __dict__ of the entered + // interpreter's __main__ module. It is looked up when at the + // beginning of the session as a convenience. + PyObject *main_ns; + + // This is set if the interpreter is entered and raised an exception + // that needs to be handled in some special way during exit. + _PyXI_errcode *error_override; + // This is set if exit captured an exception to propagate. + _PyXI_error *error; + + // -- pre-allocated memory -- + _PyXI_error _error; + _PyXI_errcode _error_override; +}; + +PyAPI_FUNC(int) _PyXI_Enter( + _PyXI_session *session, + PyInterpreterState *interp, + PyObject *nsupdates); +PyAPI_FUNC(void) _PyXI_Exit(_PyXI_session *session); + +PyAPI_FUNC(PyObject *) _PyXI_ApplyCapturedException(_PyXI_session *session); +PyAPI_FUNC(int) _PyXI_HasCapturedException(_PyXI_session *session); + + +#ifdef __cplusplus +} +#endif +#endif /* !Py_INTERNAL_CROSSINTERP_H */ diff --git a/Include/internal/pycore_dict.h b/Include/internal/pycore_dict.h index 26a913435ef9cf..d96870e9197bbf 100644 --- a/Include/internal/pycore_dict.h +++ b/Include/internal/pycore_dict.h @@ -9,21 +9,43 @@ extern "C" { # error "this header requires Py_BUILD_CORE define" #endif -#include "pycore_dict_state.h" -#include "pycore_runtime.h" // _PyRuntime +#include "pycore_identifier.h" // _Py_Identifier +#include "pycore_object.h" // PyDictOrValues // Unsafe flavor of PyDict_GetItemWithError(): no error checking extern PyObject* _PyDict_GetItemWithError(PyObject *dp, PyObject *key); -extern int _PyDict_Contains_KnownHash(PyObject *, PyObject *, Py_hash_t); - extern int _PyDict_DelItemIf(PyObject *mp, PyObject *key, int (*predicate)(PyObject *value)); +// "KnownHash" variants +// Export for '_asyncio' shared extension +PyAPI_FUNC(int) _PyDict_SetItem_KnownHash(PyObject *mp, PyObject *key, + PyObject *item, Py_hash_t hash); +// Export for '_asyncio' shared extension +PyAPI_FUNC(int) _PyDict_DelItem_KnownHash(PyObject *mp, PyObject *key, + Py_hash_t hash); +extern int _PyDict_Contains_KnownHash(PyObject *, PyObject *, Py_hash_t); + +// "Id" variants +extern PyObject* _PyDict_GetItemIdWithError(PyObject *dp, + _Py_Identifier *key); +extern int _PyDict_ContainsId(PyObject *, _Py_Identifier *); +extern int _PyDict_SetItemId(PyObject *dp, _Py_Identifier *key, PyObject *item); +extern int _PyDict_DelItemId(PyObject *mp, _Py_Identifier *key); + +extern int _PyDict_Next( + PyObject *mp, Py_ssize_t *pos, PyObject **key, PyObject **value, Py_hash_t *hash); + extern int _PyDict_HasOnlyStringKeys(PyObject *mp); extern void _PyDict_MaybeUntrack(PyObject *mp); +// Export for '_ctypes' shared extension +PyAPI_FUNC(Py_ssize_t) _PyDict_SizeOf(PyDictObject *); + +#define _PyDict_HasSplitTable(d) ((d)->ma_values != NULL) + /* Like PyDict_Merge, but override can be 0, 1 or 2. If override is 0, the first occurrence of a key wins, if override is 1, the last occurrence of a key wins, if override is 2, a KeyError with conflicting key as @@ -33,6 +55,18 @@ extern int _PyDict_MergeEx(PyObject *mp, PyObject *other, int override); extern void _PyDict_DebugMallocStats(FILE *out); + +/* _PyDictView */ + +typedef struct { + PyObject_HEAD + PyDictObject *dv_dict; +} _PyDictViewObject; + +extern PyObject* _PyDictView_New(PyObject *, PyTypeObject *); +extern PyObject* _PyDictView_Intersect(PyObject* self, PyObject *other); + + /* runtime lifecycle */ extern void _PyDict_Fini(PyInterpreterState *interp); @@ -62,6 +96,8 @@ extern uint32_t _PyDictKeys_GetVersionForCurrentState( extern size_t _PyDict_KeysSize(PyDictKeysObject *keys); +extern void _PyDictKeys_DecRef(PyDictKeysObject *keys); + /* _Py_dict_lookup() returns index of entry which can be used like DK_ENTRIES(dk)[index]. * -1 when no entry found, -3 when compare raises error. */ @@ -75,7 +111,11 @@ extern PyObject *_PyDict_LoadGlobal(PyDictObject *, PyDictObject *, PyObject *); extern int _PyDict_SetItem_Take2(PyDictObject *op, PyObject *key, PyObject *value); extern int _PyObjectDict_SetItem(PyTypeObject *tp, PyObject **dictptr, PyObject *name, PyObject *value); -extern PyObject *_PyDict_Pop_KnownHash(PyObject *, PyObject *, Py_hash_t, PyObject *); +extern int _PyDict_Pop_KnownHash( + PyDictObject *dict, + PyObject *key, + Py_hash_t hash, + PyObject **result); #define DKIX_EMPTY (-1) #define DKIX_DUMMY (-2) /* Used internally */ @@ -196,6 +236,7 @@ _PyDict_NotifyEvent(PyInterpreterState *interp, } extern PyObject *_PyObject_MakeDictFromInstanceAttributes(PyObject *obj, PyDictValues *values); +extern bool _PyObject_MakeInstanceAttributesFromDict(PyObject *obj, PyDictOrValues *dorv); extern PyObject *_PyDict_FromItems( PyObject *const *keys, Py_ssize_t keys_offset, PyObject *const *values, Py_ssize_t values_offset, diff --git a/Include/internal/pycore_dtoa.h b/Include/internal/pycore_dtoa.h index ac62a4d300720a..c5cfdf4ce8f823 100644 --- a/Include/internal/pycore_dtoa.h +++ b/Include/internal/pycore_dtoa.h @@ -35,6 +35,9 @@ struct _dtoa_state { /* The size of the Bigint freelist */ #define Bigint_Kmax 7 +/* The size of the cached powers of 5 array */ +#define Bigint_Pow5size 8 + #ifndef PRIVATE_MEM #define PRIVATE_MEM 2304 #endif @@ -42,9 +45,10 @@ struct _dtoa_state { ((PRIVATE_MEM+sizeof(double)-1)/sizeof(double)) struct _dtoa_state { - /* p5s is a linked list of powers of 5 of the form 5**(2**i), i >= 2 */ + // p5s is an array of powers of 5 of the form: + // 5**(2**(i+2)) for 0 <= i < Bigint_Pow5size + struct Bigint *p5s[Bigint_Pow5size]; // XXX This should be freed during runtime fini. - struct Bigint *p5s; struct Bigint *freelist[Bigint_Kmax+1]; double preallocated[Bigint_PREALLOC_SIZE]; double *preallocated_next; @@ -57,9 +61,6 @@ struct _dtoa_state { #endif // !Py_USING_MEMORY_DEBUGGER -/* These functions are used by modules compiled as C extension like math: - they must be exported. */ - extern double _Py_dg_strtod(const char *str, char **ptr); extern char* _Py_dg_dtoa(double d, int mode, int ndigits, int *decpt, int *sign, char **rve); @@ -67,6 +68,11 @@ extern void _Py_dg_freedtoa(char *s); #endif // _PY_SHORT_FLOAT_REPR == 1 + +extern PyStatus _PyDtoa_Init(PyInterpreterState *interp); +extern void _PyDtoa_Fini(PyInterpreterState *interp); + + #ifdef __cplusplus } #endif diff --git a/Include/internal/pycore_emscripten_signal.h b/Include/internal/pycore_emscripten_signal.h index 8b3287d85da4b2..754193e21dec5a 100644 --- a/Include/internal/pycore_emscripten_signal.h +++ b/Include/internal/pycore_emscripten_signal.h @@ -3,6 +3,10 @@ #if defined(__EMSCRIPTEN__) +#ifndef Py_BUILD_CORE +# error "this header requires Py_BUILD_CORE define" +#endif + void _Py_CheckEmscriptenSignals(void); @@ -14,6 +18,7 @@ _Py_CheckEmscriptenSignalsPeriodically(void); #define _Py_CHECK_EMSCRIPTEN_SIGNALS_PERIODICALLY() _Py_CheckEmscriptenSignalsPeriodically() extern int Py_EMSCRIPTEN_SIGNAL_HANDLING; +extern int _Py_emscripten_signal_clock; #else diff --git a/Include/internal/pycore_emscripten_trampoline.h b/Include/internal/pycore_emscripten_trampoline.h new file mode 100644 index 00000000000000..e519c99ad86cce --- /dev/null +++ b/Include/internal/pycore_emscripten_trampoline.h @@ -0,0 +1,81 @@ +#ifndef Py_EMSCRIPTEN_TRAMPOLINE_H +#define Py_EMSCRIPTEN_TRAMPOLINE_H + +#include "pycore_runtime.h" // _PyRuntimeState + +/** + * C function call trampolines to mitigate bad function pointer casts. + * + * Section 6.3.2.3, paragraph 8 reads: + * + * A pointer to a function of one type may be converted to a pointer to a + * function of another type and back again; the result shall compare equal to + * the original pointer. If a converted pointer is used to call a function + * whose type is not compatible with the pointed-to type, the behavior is + * undefined. + * + * Typical native ABIs ignore additional arguments or fill in missing values + * with 0/NULL in function pointer cast. Compilers do not show warnings when a + * function pointer is explicitly casted to an incompatible type. + * + * Bad fpcasts are an issue in WebAssembly. WASM's indirect_call has strict + * function signature checks. Argument count, types, and return type must match. + * + * Third party code unintentionally rely on problematic fpcasts. The call + * trampoline mitigates common occurrences of bad fpcasts on Emscripten. + */ + +#if defined(__EMSCRIPTEN__) && defined(PY_CALL_TRAMPOLINE) + +void _Py_EmscriptenTrampoline_Init(_PyRuntimeState *runtime); + +PyObject* +_PyEM_TrampolineCall_JavaScript(PyCFunctionWithKeywords func, + PyObject* self, + PyObject* args, + PyObject* kw); + +PyObject* +_PyEM_TrampolineCall_Reflection(PyCFunctionWithKeywords func, + PyObject* self, + PyObject* args, + PyObject* kw); + +#define _PyEM_TrampolineCall(meth, self, args, kw) \ + ((_PyRuntime.wasm_type_reflection_available) ? \ + (_PyEM_TrampolineCall_Reflection((PyCFunctionWithKeywords)(meth), (self), (args), (kw))) : \ + (_PyEM_TrampolineCall_JavaScript((PyCFunctionWithKeywords)(meth), (self), (args), (kw)))) + +#define _PyCFunction_TrampolineCall(meth, self, args) \ + _PyEM_TrampolineCall( \ + (*(PyCFunctionWithKeywords)(void(*)(void))(meth)), (self), (args), NULL) + +#define _PyCFunctionWithKeywords_TrampolineCall(meth, self, args, kw) \ + _PyEM_TrampolineCall((meth), (self), (args), (kw)) + +#define descr_set_trampoline_call(set, obj, value, closure) \ + ((int)_PyEM_TrampolineCall((PyCFunctionWithKeywords)(set), (obj), (value), (PyObject*)(closure))) + +#define descr_get_trampoline_call(get, obj, closure) \ + _PyEM_TrampolineCall((PyCFunctionWithKeywords)(get), (obj), (PyObject*)(closure), NULL) + + +#else // defined(__EMSCRIPTEN__) && defined(PY_CALL_TRAMPOLINE) + +#define _Py_EmscriptenTrampoline_Init(runtime) + +#define _PyCFunction_TrampolineCall(meth, self, args) \ + (meth)((self), (args)) + +#define _PyCFunctionWithKeywords_TrampolineCall(meth, self, args, kw) \ + (meth)((self), (args), (kw)) + +#define descr_set_trampoline_call(set, obj, value, closure) \ + (set)((obj), (value), (closure)) + +#define descr_get_trampoline_call(get, obj, closure) \ + (get)((obj), (closure)) + +#endif // defined(__EMSCRIPTEN__) && defined(PY_CALL_TRAMPOLINE) + +#endif // ndef Py_EMSCRIPTEN_SIGNAL_H diff --git a/Include/internal/pycore_faulthandler.h b/Include/internal/pycore_faulthandler.h index e6aec7745a6479..6dd7d8d7ca9792 100644 --- a/Include/internal/pycore_faulthandler.h +++ b/Include/internal/pycore_faulthandler.h @@ -9,7 +9,7 @@ extern "C" { #endif #ifdef HAVE_SIGACTION -# include +# include // sigaction #endif diff --git a/Include/internal/pycore_fileutils.h b/Include/internal/pycore_fileutils.h index daa32c0dff6097..5c55282fa39e6f 100644 --- a/Include/internal/pycore_fileutils.h +++ b/Include/internal/pycore_fileutils.h @@ -5,10 +5,11 @@ extern "C" { #endif #ifndef Py_BUILD_CORE -# error "Py_BUILD_CORE must be defined to include this header" +# error "this header requires Py_BUILD_CORE define" #endif -#include /* struct lconv */ +#include // struct lconv + /* A routine to check if a file descriptor can be select()-ed. */ #ifdef _MSC_VER @@ -34,8 +35,10 @@ typedef enum { _Py_ERROR_OTHER } _Py_error_handler; +// Export for '_testinternalcapi' shared extension PyAPI_FUNC(_Py_error_handler) _Py_GetErrorHandler(const char *errors); +// Export for '_testinternalcapi' shared extension PyAPI_FUNC(int) _Py_DecodeLocaleEx( const char *arg, wchar_t **wstr, @@ -44,6 +47,7 @@ PyAPI_FUNC(int) _Py_DecodeLocaleEx( int current_locale, _Py_error_handler errors); +// Export for '_testinternalcapi' shared extension PyAPI_FUNC(int) _Py_EncodeLocaleEx( const wchar_t *text, char **str, @@ -97,22 +101,27 @@ struct _Py_stat_struct { # define _Py_stat_struct stat #endif +// Export for 'mmap' shared extension PyAPI_FUNC(int) _Py_fstat( int fd, struct _Py_stat_struct *status); +// Export for 'mmap' shared extension PyAPI_FUNC(int) _Py_fstat_noraise( int fd, struct _Py_stat_struct *status); +// Export for '_tkinter' shared extension PyAPI_FUNC(int) _Py_stat( PyObject *path, struct stat *status); -extern int _Py_open( +// Export for 'select' shared extension (Solaris newDevPollObject()) +PyAPI_FUNC(int) _Py_open( const char *pathname, int flags); +// Export for '_posixsubprocess' shared extension PyAPI_FUNC(int) _Py_open_noraise( const char *pathname, int flags); @@ -126,11 +135,13 @@ extern Py_ssize_t _Py_read( void *buf, size_t count); -extern Py_ssize_t _Py_write( +// Export for 'select' shared extension (Solaris devpoll_flush()) +PyAPI_FUNC(Py_ssize_t) _Py_write( int fd, const void *buf, size_t count); +// Export for '_posixsubprocess' shared extension PyAPI_FUNC(Py_ssize_t) _Py_write_noraise( int fd, const void *buf, @@ -162,12 +173,15 @@ extern wchar_t* _Py_wgetcwd( extern int _Py_get_inheritable(int fd); +// Export for '_socket' shared extension PyAPI_FUNC(int) _Py_set_inheritable(int fd, int inheritable, int *atomic_flag_works); +// Export for '_posixsubprocess' shared extension PyAPI_FUNC(int) _Py_set_inheritable_async_safe(int fd, int inheritable, int *atomic_flag_works); +// Export for '_socket' shared extension PyAPI_FUNC(int) _Py_dup(int fd); extern int _Py_get_blocking(int fd); @@ -177,6 +191,7 @@ extern int _Py_set_blocking(int fd, int blocking); #ifdef MS_WINDOWS extern void* _Py_get_osfhandle_noraise(int fd); +// Export for '_testconsole' shared extension PyAPI_FUNC(void*) _Py_get_osfhandle(int fd); extern int _Py_open_osfhandle_noraise(void *handle, int flags); @@ -231,6 +246,7 @@ extern int _Py_GetLocaleconvNumeric( PyObject **decimal_point, PyObject **thousands_sep); +// Export for '_posixsubprocess' (on macOS) PyAPI_FUNC(void) _Py_closerange(int first, int last); extern wchar_t* _Py_GetLocaleEncoding(void); @@ -259,13 +275,17 @@ extern int _Py_add_relfile(wchar_t *dirname, const wchar_t *relfile, size_t bufsize); extern size_t _Py_find_basename(const wchar_t *filename); + +// Export for '_testinternalcapi' shared extension PyAPI_FUNC(wchar_t*) _Py_normpath(wchar_t *path, Py_ssize_t size); +extern wchar_t *_Py_normpath_and_size(wchar_t *path, Py_ssize_t size, Py_ssize_t *length); + // The Windows Games API family does not provide these functions // so provide our own implementations. Remove them in case they get added // to the Games API family #if defined(MS_WINDOWS_GAMES) && !defined(MS_WINDOWS_DESKTOP) -#include +#include // HRESULT extern HRESULT PathCchSkipRoot(const wchar_t *pszPath, const wchar_t **ppszRootEnd); #endif /* defined(MS_WINDOWS_GAMES) && !defined(MS_WINDOWS_DESKTOP) */ @@ -292,6 +312,18 @@ extern HRESULT PathCchSkipRoot(const wchar_t *pszPath, const wchar_t **ppszRootE # define _Py_END_SUPPRESS_IPH #endif /* _MSC_VER >= 1900 */ +// Export for 'select' shared extension (Argument Clinic code) +PyAPI_FUNC(int) _PyLong_FileDescriptor_Converter(PyObject *, void *); + +// Export for test_peg_generator +PyAPI_FUNC(char*) _Py_UniversalNewlineFgetsWithSize(char *, int, FILE*, PyObject *, size_t*); + +extern int _PyFile_Flush(PyObject *); + +#ifndef MS_WINDOWS +extern int _Py_GetTicksPerSecond(long *ticks_per_second); +#endif + #ifdef __cplusplus } #endif diff --git a/Include/internal/pycore_fileutils_windows.h b/Include/internal/pycore_fileutils_windows.h index e804d385e76708..b79aa9fb465376 100644 --- a/Include/internal/pycore_fileutils_windows.h +++ b/Include/internal/pycore_fileutils_windows.h @@ -5,7 +5,7 @@ extern "C" { #endif #ifndef Py_BUILD_CORE -# error "Py_BUILD_CORE must be defined to include this header" +# error "this header requires Py_BUILD_CORE define" #endif #ifdef MS_WINDOWS diff --git a/Include/internal/pycore_floatobject.h b/Include/internal/pycore_floatobject.h index 6b9af03c25ec36..038578e1f9680a 100644 --- a/Include/internal/pycore_floatobject.h +++ b/Include/internal/pycore_floatobject.h @@ -8,14 +8,14 @@ extern "C" { # error "this header requires Py_BUILD_CORE define" #endif - +#include "pycore_freelist.h" // _PyFreeListState #include "pycore_unicodeobject.h" // _PyUnicodeWriter /* runtime lifecycle */ extern void _PyFloat_InitState(PyInterpreterState *); extern PyStatus _PyFloat_InitTypes(PyInterpreterState *); -extern void _PyFloat_Fini(PyInterpreterState *); +extern void _PyFloat_Fini(_PyFreeListState *); extern void _PyFloat_FiniType(PyInterpreterState *); @@ -33,24 +33,7 @@ struct _Py_float_runtime_state { }; -#ifndef WITH_FREELISTS -// without freelists -# define PyFloat_MAXFREELIST 0 -#endif -#ifndef PyFloat_MAXFREELIST -# define PyFloat_MAXFREELIST 100 -#endif - -struct _Py_float_state { -#if PyFloat_MAXFREELIST > 0 - /* Special free list - free_list is a singly-linked list of available PyFloatObjects, - linked via abuse of their ob_type members. */ - int numfree; - PyFloatObject *free_list; -#endif -}; void _PyFloat_ExactDealloc(PyObject *op); @@ -67,6 +50,13 @@ extern int _PyFloat_FormatAdvancedWriter( Py_ssize_t start, Py_ssize_t end); +extern PyObject* _Py_string_to_number_with_underscores( + const char *str, Py_ssize_t len, const char *what, PyObject *obj, void *arg, + PyObject *(*innerfunc)(const char *, Py_ssize_t, void *)); + +extern double _Py_parse_inf_or_nan(const char *p, char **endptr); + + #ifdef __cplusplus } #endif diff --git a/Include/internal/pycore_flowgraph.h b/Include/internal/pycore_flowgraph.h index cb55f8712e7ad6..58fed46886ea45 100644 --- a/Include/internal/pycore_flowgraph.h +++ b/Include/internal/pycore_flowgraph.h @@ -11,88 +11,26 @@ extern "C" { #include "pycore_opcode_utils.h" #include "pycore_compile.h" - -typedef struct { - int i_opcode; - int i_oparg; - _PyCompilerSrcLocation i_loc; - struct _PyCfgBasicblock_ *i_target; /* target block (if jump instruction) */ - struct _PyCfgBasicblock_ *i_except; /* target block when exception is raised */ -} _PyCfgInstruction; - typedef struct { int id; } _PyCfgJumpTargetLabel; +struct _PyCfgBuilder; -typedef struct { - struct _PyCfgBasicblock_ *handlers[CO_MAXBLOCKS+1]; - int depth; -} _PyCfgExceptStack; - -typedef struct _PyCfgBasicblock_ { - /* Each basicblock in a compilation unit is linked via b_list in the - reverse order that the block are allocated. b_list points to the next - block in this list, not to be confused with b_next, which is next by - control flow. */ - struct _PyCfgBasicblock_ *b_list; - /* The label of this block if it is a jump target, -1 otherwise */ - _PyCfgJumpTargetLabel b_label; - /* Exception stack at start of block, used by assembler to create the exception handling table */ - _PyCfgExceptStack *b_exceptstack; - /* pointer to an array of instructions, initially NULL */ - _PyCfgInstruction *b_instr; - /* If b_next is non-NULL, it is a pointer to the next - block reached by normal control flow. */ - struct _PyCfgBasicblock_ *b_next; - /* number of instructions used */ - int b_iused; - /* length of instruction array (b_instr) */ - int b_ialloc; - /* Used by add_checks_for_loads_of_unknown_variables */ - uint64_t b_unsafe_locals_mask; - /* Number of predecessors that a block has. */ - int b_predecessors; - /* depth of stack upon entry of block, computed by stackdepth() */ - int b_startdepth; - /* Basic block is an exception handler that preserves lasti */ - unsigned b_preserve_lasti : 1; - /* Used by compiler passes to mark whether they have visited a basic block. */ - unsigned b_visited : 1; - /* b_except_handler is used by the cold-detection algorithm to mark exception targets */ - unsigned b_except_handler : 1; - /* b_cold is true if this block is not perf critical (like an exception handler) */ - unsigned b_cold : 1; - /* b_warm is used by the cold-detection algorithm to mark blocks which are definitely not cold */ - unsigned b_warm : 1; -} _PyCfgBasicblock; +int _PyCfgBuilder_UseLabel(struct _PyCfgBuilder *g, _PyCfgJumpTargetLabel lbl); +int _PyCfgBuilder_Addop(struct _PyCfgBuilder *g, int opcode, int oparg, _PyCompilerSrcLocation loc); -int _PyBasicblock_InsertInstruction(_PyCfgBasicblock *block, int pos, _PyCfgInstruction *instr); +struct _PyCfgBuilder* _PyCfgBuilder_New(void); +void _PyCfgBuilder_Free(struct _PyCfgBuilder *g); +int _PyCfgBuilder_CheckSize(struct _PyCfgBuilder* g); -typedef struct cfg_builder_ { - /* The entryblock, at which control flow begins. All blocks of the - CFG are reachable through the b_next links */ - _PyCfgBasicblock *g_entryblock; - /* Pointer to the most recently allocated block. By following - b_list links, you can reach all allocated blocks. */ - _PyCfgBasicblock *g_block_list; - /* pointer to the block currently being constructed */ - _PyCfgBasicblock *g_curblock; - /* label for the next instruction to be placed */ - _PyCfgJumpTargetLabel g_current_label; -} _PyCfgBuilder; - -int _PyCfgBuilder_UseLabel(_PyCfgBuilder *g, _PyCfgJumpTargetLabel lbl); -int _PyCfgBuilder_Addop(_PyCfgBuilder *g, int opcode, int oparg, _PyCompilerSrcLocation loc); - -int _PyCfgBuilder_Init(_PyCfgBuilder *g); -void _PyCfgBuilder_Fini(_PyCfgBuilder *g); - -int _PyCfg_OptimizeCodeUnit(_PyCfgBuilder *g, PyObject *consts, PyObject *const_cache, +int _PyCfg_OptimizeCodeUnit(struct _PyCfgBuilder *g, PyObject *consts, PyObject *const_cache, int nlocals, int nparams, int firstlineno); -int _PyCfg_Stackdepth(_PyCfgBuilder *g); -void _PyCfg_ConvertPseudoOps(_PyCfgBasicblock *entryblock); -int _PyCfg_ResolveJumps(_PyCfgBuilder *g); + +int _PyCfg_ToInstructionSequence(struct _PyCfgBuilder *g, _PyCompile_InstructionSequence *seq); +int _PyCfg_OptimizedCfgToInstructionSequence(struct _PyCfgBuilder *g, _PyCompile_CodeUnitMetadata *umd, + int code_flags, int *stackdepth, int *nlocalsplus, + _PyCompile_InstructionSequence *seq); PyCodeObject * _PyAssemble_MakeCodeObject(_PyCompile_CodeUnitMetadata *u, PyObject *const_cache, diff --git a/Include/internal/pycore_frame.h b/Include/internal/pycore_frame.h index 5ff20ef845ab10..0f9e7333cf1e1c 100644 --- a/Include/internal/pycore_frame.h +++ b/Include/internal/pycore_frame.h @@ -4,6 +4,10 @@ extern "C" { #endif +#ifndef Py_BUILD_CORE +# error "this header requires Py_BUILD_CORE define" +#endif + #include #include // offsetof() #include "pycore_code.h" // STATS @@ -32,13 +36,17 @@ extern PyFrameObject* _PyFrame_New_NoTrack(PyCodeObject *code); /* other API */ typedef enum _framestate { - FRAME_CREATED = -2, - FRAME_SUSPENDED = -1, + FRAME_CREATED = -3, + FRAME_SUSPENDED = -2, + FRAME_SUSPENDED_YIELD_FROM = -1, FRAME_EXECUTING = 0, FRAME_COMPLETED = 1, FRAME_CLEARED = 4 } PyFrameState; +#define FRAME_STATE_SUSPENDED(S) ((S) == FRAME_SUSPENDED || (S) == FRAME_SUSPENDED_YIELD_FROM) +#define FRAME_STATE_FINISHED(S) ((S) >= FRAME_COMPLETED) + enum _frameowner { FRAME_OWNED_BY_THREAD = 0, FRAME_OWNED_BY_GENERATOR = 1, @@ -54,26 +62,16 @@ typedef struct _PyInterpreterFrame { PyObject *f_builtins; /* Borrowed reference. Only valid if not on C stack */ PyObject *f_locals; /* Strong reference, may be NULL. Only valid if not on C stack */ PyFrameObject *frame_obj; /* Strong reference, may be NULL. Only valid if not on C stack */ - // NOTE: This is not necessarily the last instruction started in the given - // frame. Rather, it is the code unit *prior to* the *next* instruction. For - // example, it may be an inline CACHE entry, an instruction we just jumped - // over, or (in the case of a newly-created frame) a totally invalid value: - _Py_CODEUNIT *prev_instr; + _Py_CODEUNIT *instr_ptr; /* Instruction currently executing (or about to begin) */ int stacktop; /* Offset of TOS from localsplus */ - /* The return_offset determines where a `RETURN` should go in the caller, - * relative to `prev_instr`. - * It is only meaningful to the callee, - * so it needs to be set in any CALL (to a Python function) - * or SEND (to a coroutine or generator). - * If there is no callee, then it is meaningless. */ - uint16_t return_offset; + uint16_t return_offset; /* Only relevant during a function call */ char owner; /* Locals and stack */ PyObject *localsplus[1]; } _PyInterpreterFrame; #define _PyInterpreterFrame_LASTI(IF) \ - ((int)((IF)->prev_instr - _PyCode_CODE(_PyFrame_GetCode(IF)))) + ((int)((IF)->instr_ptr - _PyCode_CODE(_PyFrame_GetCode(IF)))) static inline PyCodeObject *_PyFrame_GetCode(_PyInterpreterFrame *f) { assert(PyCode_Check(f->f_executable)); @@ -130,7 +128,7 @@ _PyFrame_Initialize( frame->f_locals = locals; frame->stacktop = code->co_nlocalsplus; frame->frame_obj = NULL; - frame->prev_instr = _PyCode_CODE(code) - 1; + frame->instr_ptr = _PyCode_CODE(code); frame->return_offset = 0; frame->owner = FRAME_OWNED_BY_THREAD; @@ -181,7 +179,7 @@ _PyFrame_IsIncomplete(_PyInterpreterFrame *frame) return true; } return frame->owner != FRAME_OWNED_BY_GENERATOR && - frame->prev_instr < _PyCode_CODE(_PyFrame_GetCode(frame)) + _PyFrame_GetCode(frame)->_co_firsttraceable; + frame->instr_ptr < _PyCode_CODE(_PyFrame_GetCode(frame)) + _PyFrame_GetCode(frame)->_co_firsttraceable; } static inline _PyInterpreterFrame * @@ -196,7 +194,7 @@ _PyFrame_GetFirstComplete(_PyInterpreterFrame *frame) static inline _PyInterpreterFrame * _PyThreadState_GetFrame(PyThreadState *tstate) { - return _PyFrame_GetFirstComplete(tstate->cframe->current_frame); + return _PyFrame_GetFirstComplete(tstate->current_frame); } /* For use by _PyFrame_GetFrameObject @@ -278,7 +276,7 @@ _PyFrame_PushUnchecked(PyThreadState *tstate, PyFunctionObject *func, int null_l /* Pushes a trampoline frame without checking for space. * Must be guarded by _PyThreadState_HasStackSpace() */ static inline _PyInterpreterFrame * -_PyFrame_PushTrampolineUnchecked(PyThreadState *tstate, PyCodeObject *code, int stackdepth, int prev_instr) +_PyFrame_PushTrampolineUnchecked(PyThreadState *tstate, PyCodeObject *code, int stackdepth) { CALL_STAT_INC(frames_pushed); _PyInterpreterFrame *frame = (_PyInterpreterFrame *)tstate->datastack_top; @@ -293,7 +291,7 @@ _PyFrame_PushTrampolineUnchecked(PyThreadState *tstate, PyCodeObject *code, int frame->f_locals = NULL; frame->stacktop = code->co_nlocalsplus + stackdepth; frame->frame_obj = NULL; - frame->prev_instr = _PyCode_CODE(code) + prev_instr; + frame->instr_ptr = _PyCode_CODE(code); frame->owner = FRAME_OWNED_BY_THREAD; frame->return_offset = 0; return frame; @@ -307,14 +305,6 @@ PyGenObject *_PyFrame_GetGenerator(_PyInterpreterFrame *frame) return (PyGenObject *)(((char *)frame) - offset_in_gen); } -#define PY_EXECUTABLE_KIND_SKIP 0 -#define PY_EXECUTABLE_KIND_PY_FUNCTION 1 -#define PY_EXECUTABLE_KIND_BUILTIN_FUNCTION 3 -#define PY_EXECUTABLE_KIND_METHOD_DESCRIPTOR 4 -#define PY_EXECUTABLE_KINDS 5 - -PyAPI_DATA(const PyTypeObject *) const PyUnstable_ExecutableKinds[PY_EXECUTABLE_KINDS+1]; - #ifdef __cplusplus } #endif diff --git a/Include/internal/pycore_freelist.h b/Include/internal/pycore_freelist.h new file mode 100644 index 00000000000000..34009435910d99 --- /dev/null +++ b/Include/internal/pycore_freelist.h @@ -0,0 +1,71 @@ +#ifndef Py_INTERNAL_FREELIST_H +#define Py_INTERNAL_FREELIST_H +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef Py_BUILD_CORE +# error "this header requires Py_BUILD_CORE define" +#endif + +// PyTuple_MAXSAVESIZE - largest tuple to save on free list +// PyTuple_MAXFREELIST - maximum number of tuples of each size to save + +#ifdef WITH_FREELISTS +// with freelists +# define PyTuple_MAXSAVESIZE 20 +# define PyTuple_NFREELISTS PyTuple_MAXSAVESIZE +# define PyTuple_MAXFREELIST 2000 +# define PyList_MAXFREELIST 80 +# define PyFloat_MAXFREELIST 100 +#else +# define PyTuple_NFREELISTS 0 +# define PyTuple_MAXFREELIST 0 +# define PyList_MAXFREELIST 0 +# define PyFloat_MAXFREELIST 0 +#endif + +struct _Py_list_state { +#ifdef WITH_FREELISTS + PyListObject *free_list[PyList_MAXFREELIST]; + int numfree; +#endif +}; + +struct _Py_tuple_state { +#if WITH_FREELISTS + /* There is one freelist for each size from 1 to PyTuple_MAXSAVESIZE. + The empty tuple is handled separately. + + Each tuple stored in the array is the head of the linked list + (and the next available tuple) for that size. The actual tuple + object is used as the linked list node, with its first item + (ob_item[0]) pointing to the next node (i.e. the previous head). + Each linked list is initially NULL. */ + PyTupleObject *free_list[PyTuple_NFREELISTS]; + int numfree[PyTuple_NFREELISTS]; +#else + char _unused; // Empty structs are not allowed. +#endif +}; + +struct _Py_float_state { +#ifdef WITH_FREELISTS + /* Special free list + free_list is a singly-linked list of available PyFloatObjects, + linked via abuse of their ob_type members. */ + int numfree; + PyFloatObject *free_list; +#endif +}; + +typedef struct _Py_freelist_state { + struct _Py_float_state float_state; + struct _Py_tuple_state tuple_state; + struct _Py_list_state list_state; +} _PyFreeListState; + +#ifdef __cplusplus +} +#endif +#endif /* !Py_INTERNAL_FREELIST_H */ diff --git a/Include/internal/pycore_function.h b/Include/internal/pycore_function.h index e844d323ec7927..3f3da8a44b77e4 100644 --- a/Include/internal/pycore_function.h +++ b/Include/internal/pycore_function.h @@ -16,13 +16,22 @@ extern PyObject* _PyFunction_Vectorcall( #define FUNC_MAX_WATCHERS 8 +#define FUNC_VERSION_CACHE_SIZE (1<<12) /* Must be a power of 2 */ struct _py_func_state { uint32_t next_version; + // Borrowed references to function objects whose + // func_version % FUNC_VERSION_CACHE_SIZE + // once was equal to the index in the table. + // They are cleared when the function is deallocated. + PyFunctionObject *func_version_cache[FUNC_VERSION_CACHE_SIZE]; }; extern PyFunctionObject* _PyFunction_FromConstructor(PyFrameConstructor *constr); extern uint32_t _PyFunction_GetVersionForCurrentState(PyFunctionObject *func); +extern void _PyFunction_SetVersion(PyFunctionObject *func, uint32_t version); +PyFunctionObject *_PyFunction_LookupByVersion(uint32_t version); + extern PyObject *_Py_set_function_type_params( PyThreadState* unused, PyObject *func, PyObject *type_params); diff --git a/Include/internal/pycore_gc.h b/Include/internal/pycore_gc.h index 2d33aa76d78229..c029b239306648 100644 --- a/Include/internal/pycore_gc.h +++ b/Include/internal/pycore_gc.h @@ -8,6 +8,8 @@ extern "C" { # error "this header requires Py_BUILD_CORE define" #endif +#include "pycore_freelist.h" // _PyFreeListState + /* GC information is stored BEFORE the object structure. */ typedef struct { // Pointer to next object in the list. @@ -64,6 +66,26 @@ static inline int _PyObject_GC_MAY_BE_TRACKED(PyObject *obj) { #define _PyGC_PREV_SHIFT (2) #define _PyGC_PREV_MASK (((uintptr_t) -1) << _PyGC_PREV_SHIFT) +/* set for debugging information */ +#define _PyGC_DEBUG_STATS (1<<0) /* print collection statistics */ +#define _PyGC_DEBUG_COLLECTABLE (1<<1) /* print collectable objects */ +#define _PyGC_DEBUG_UNCOLLECTABLE (1<<2) /* print uncollectable objects */ +#define _PyGC_DEBUG_SAVEALL (1<<5) /* save all garbage in gc.garbage */ +#define _PyGC_DEBUG_LEAK _PyGC_DEBUG_COLLECTABLE | \ + _PyGC_DEBUG_UNCOLLECTABLE | \ + _PyGC_DEBUG_SAVEALL + +typedef enum { + // GC was triggered by heap allocation + _Py_GC_REASON_HEAP, + + // GC was called during shutdown + _Py_GC_REASON_SHUTDOWN, + + // GC was called by gc.collect() or PyGC_Collect() + _Py_GC_REASON_MANUAL +} _PyGC_Reason; + // Lowest bit of _gc_next is used for flags only in GC. // But it is always 0 for normal code. static inline PyGC_Head* _PyGCHead_NEXT(PyGC_Head *gc) { @@ -100,6 +122,10 @@ static inline void _PyGC_SET_FINALIZED(PyObject *op) { PyGC_Head *gc = _Py_AS_GC(op); _PyGCHead_SET_FINALIZED(gc); } +static inline void _PyGC_CLEAR_FINALIZED(PyObject *op) { + PyGC_Head *gc = _Py_AS_GC(op); + gc->_gc_prev &= ~_PyGC_PREV_MASK_FINALIZED; +} /* GC runtime state */ @@ -203,13 +229,26 @@ struct _gc_runtime_state { extern void _PyGC_InitState(struct _gc_runtime_state *); +extern Py_ssize_t _PyGC_Collect(PyThreadState *tstate, int generation, + _PyGC_Reason reason); extern Py_ssize_t _PyGC_CollectNoFail(PyThreadState *tstate); +/* Freeze objects tracked by the GC and ignore them in future collections. */ +extern void _PyGC_Freeze(PyInterpreterState *interp); +/* Unfreezes objects placing them in the oldest generation */ +extern void _PyGC_Unfreeze(PyInterpreterState *interp); +/* Number of frozen objects */ +extern Py_ssize_t _PyGC_GetFreezeCount(PyInterpreterState *interp); + +extern PyObject *_PyGC_GetObjects(PyInterpreterState *interp, Py_ssize_t generation); +extern PyObject *_PyGC_GetReferrers(PyInterpreterState *interp, PyObject *objs); // Functions to clear types free lists -extern void _PyTuple_ClearFreeList(PyInterpreterState *interp); -extern void _PyFloat_ClearFreeList(PyInterpreterState *interp); -extern void _PyList_ClearFreeList(PyInterpreterState *interp); +extern void _PyGC_ClearAllFreeLists(PyInterpreterState *interp); +extern void _Py_ClearFreeLists(_PyFreeListState *state, int is_finalization); +extern void _PyTuple_ClearFreeList(_PyFreeListState *state, int is_finalization); +extern void _PyFloat_ClearFreeList(_PyFreeListState *state, int is_finalization); +extern void _PyList_ClearFreeList(_PyFreeListState *state, int is_finalization); extern void _PyDict_ClearFreeList(PyInterpreterState *interp); extern void _PyAsyncGen_ClearFreeLists(PyInterpreterState *interp); extern void _PyContext_ClearFreeList(PyInterpreterState *interp); diff --git a/Include/internal/pycore_genobject.h b/Include/internal/pycore_genobject.h index 96a6ec43d7a08a..cf58a2750a31f9 100644 --- a/Include/internal/pycore_genobject.h +++ b/Include/internal/pycore_genobject.h @@ -13,6 +13,7 @@ extern void _PyGen_Finalize(PyObject *self); // Export for '_asyncio' shared extension PyAPI_FUNC(int) _PyGen_SetStopIterationValue(PyObject *); + // Export for '_asyncio' shared extension PyAPI_FUNC(int) _PyGen_FetchStopIterationValue(PyObject **); diff --git a/Include/internal/pycore_gil.h b/Include/internal/pycore_gil.h index 8ebad37b686cd4..19b0d23a68568a 100644 --- a/Include/internal/pycore_gil.h +++ b/Include/internal/pycore_gil.h @@ -8,8 +8,7 @@ extern "C" { # error "this header requires Py_BUILD_CORE define" #endif -#include "pycore_atomic.h" /* _Py_atomic_address */ -#include "pycore_condvar.h" /* PyCOND_T */ +#include "pycore_condvar.h" // PyCOND_T #ifndef Py_HAVE_CONDVAR # error You need either a POSIX-compatible or a Windows system! @@ -25,10 +24,10 @@ struct _gil_runtime_state { unsigned long interval; /* Last PyThreadState holding / having held the GIL. This helps us know whether anyone else was scheduled after we dropped the GIL. */ - _Py_atomic_address last_holder; + PyThreadState* last_holder; /* Whether the GIL is already taken (-1 if uninitialized). This is atomic because it can be read without any lock taken in ceval.c. */ - _Py_atomic_int locked; + int locked; /* Number of GIL switches since the beginning. */ unsigned long switch_number; /* This condition variable allows one or several threads to wait diff --git a/Include/internal/pycore_global_objects.h b/Include/internal/pycore_global_objects.h index 442f8516278b02..327fcc24cb29f1 100644 --- a/Include/internal/pycore_global_objects.h +++ b/Include/internal/pycore_global_objects.h @@ -8,11 +8,11 @@ extern "C" { # error "this header requires Py_BUILD_CORE define" #endif -#include "pycore_hashtable.h" // _Py_hashtable_t -#include "pycore_gc.h" // PyGC_Head +#include "pycore_context.h" // _PyContextTokenMissing +#include "pycore_gc.h" // _PyGC_Head_UNUSED #include "pycore_global_strings.h" // struct _Py_global_strings #include "pycore_hamt.h" // PyHamtNode_Bitmap -#include "pycore_context.h" // _PyContextTokenMissing +#include "pycore_hashtable.h" // _Py_hashtable_t #include "pycore_typeobject.h" // pytype_slotdef diff --git a/Include/internal/pycore_global_objects_fini_generated.h b/Include/internal/pycore_global_objects_fini_generated.h index 6d50ffd0a02f1f..1fd67ceb3c05fb 100644 --- a/Include/internal/pycore_global_objects_fini_generated.h +++ b/Include/internal/pycore_global_objects_fini_generated.h @@ -547,6 +547,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_STR(anon_lambda)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_STR(anon_listcomp)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_STR(anon_module)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_STR(anon_null)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_STR(anon_setcomp)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_STR(anon_string)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_STR(anon_unknown)); @@ -786,11 +787,8 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(after_in_child)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(after_in_parent)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(aggregate_class)); - _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(alias)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(append)); - _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(arg)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(argdefs)); - _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(args)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(arguments)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(argv)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(as_integer_ratio)); @@ -828,6 +826,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(call)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(call_exception_handler)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(call_soon)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(callback)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(cancel)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(capath)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(category)); @@ -898,7 +897,6 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(dont_inherit)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(dst)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(dst_dir_fd)); - _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(duration)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(e)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(eager_start)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(effective_ids)); @@ -914,14 +912,13 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(errors)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(event)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(eventmask)); - _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(exc_type)); - _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(exc_value)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(excepthook)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(exception)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(existing_file_name)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(exp)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(extend)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(extra_tokens)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(f)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(facility)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(factory)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(false)); @@ -945,7 +942,6 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(flush)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(follow_symlinks)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(format)); - _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(frequency)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(from_param)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(fromlist)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(fromtimestamp)); @@ -953,6 +949,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(fset)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(func)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(future)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(g)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(generation)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(genexpr)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(get)); @@ -966,6 +963,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(globals)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(groupindex)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(groups)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(h)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(handle)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(hash_name)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(header)); @@ -974,6 +972,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(hook)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(id)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(ident)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(identity_hint)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(ignore)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(imag)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(importlib)); @@ -994,6 +993,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(instructions)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(intern)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(intersection)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(interval)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(is_running)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(isatty)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(isinstance)); @@ -1015,6 +1015,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(kw)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(kw1)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(kw2)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(kwdefaults)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(lambda)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(last)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(last_exc)); @@ -1164,7 +1165,6 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(seek)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(seekable)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(selectors)); - _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(self)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(send)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(sep)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(sequence)); @@ -1186,7 +1186,6 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(sleep)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(sock)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(sort)); - _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(sound)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(source)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(source_traceback)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(src)); @@ -1228,7 +1227,6 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(timetuple)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(top)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(trace_callback)); - _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(traceback)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(trailers)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(translate)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(true)); diff --git a/Include/internal/pycore_global_strings.h b/Include/internal/pycore_global_strings.h index bb1fb13f342fc6..da1f9b67bdfb6a 100644 --- a/Include/internal/pycore_global_strings.h +++ b/Include/internal/pycore_global_strings.h @@ -33,6 +33,7 @@ struct _Py_global_strings { STRUCT_FOR_STR(anon_lambda, "") STRUCT_FOR_STR(anon_listcomp, "") STRUCT_FOR_STR(anon_module, "") + STRUCT_FOR_STR(anon_null, "") STRUCT_FOR_STR(anon_setcomp, "") STRUCT_FOR_STR(anon_string, "") STRUCT_FOR_STR(anon_unknown, "") @@ -275,11 +276,8 @@ struct _Py_global_strings { STRUCT_FOR_ID(after_in_child) STRUCT_FOR_ID(after_in_parent) STRUCT_FOR_ID(aggregate_class) - STRUCT_FOR_ID(alias) STRUCT_FOR_ID(append) - STRUCT_FOR_ID(arg) STRUCT_FOR_ID(argdefs) - STRUCT_FOR_ID(args) STRUCT_FOR_ID(arguments) STRUCT_FOR_ID(argv) STRUCT_FOR_ID(as_integer_ratio) @@ -317,6 +315,7 @@ struct _Py_global_strings { STRUCT_FOR_ID(call) STRUCT_FOR_ID(call_exception_handler) STRUCT_FOR_ID(call_soon) + STRUCT_FOR_ID(callback) STRUCT_FOR_ID(cancel) STRUCT_FOR_ID(capath) STRUCT_FOR_ID(category) @@ -387,7 +386,6 @@ struct _Py_global_strings { STRUCT_FOR_ID(dont_inherit) STRUCT_FOR_ID(dst) STRUCT_FOR_ID(dst_dir_fd) - STRUCT_FOR_ID(duration) STRUCT_FOR_ID(e) STRUCT_FOR_ID(eager_start) STRUCT_FOR_ID(effective_ids) @@ -403,14 +401,13 @@ struct _Py_global_strings { STRUCT_FOR_ID(errors) STRUCT_FOR_ID(event) STRUCT_FOR_ID(eventmask) - STRUCT_FOR_ID(exc_type) - STRUCT_FOR_ID(exc_value) STRUCT_FOR_ID(excepthook) STRUCT_FOR_ID(exception) STRUCT_FOR_ID(existing_file_name) STRUCT_FOR_ID(exp) STRUCT_FOR_ID(extend) STRUCT_FOR_ID(extra_tokens) + STRUCT_FOR_ID(f) STRUCT_FOR_ID(facility) STRUCT_FOR_ID(factory) STRUCT_FOR_ID(false) @@ -434,7 +431,6 @@ struct _Py_global_strings { STRUCT_FOR_ID(flush) STRUCT_FOR_ID(follow_symlinks) STRUCT_FOR_ID(format) - STRUCT_FOR_ID(frequency) STRUCT_FOR_ID(from_param) STRUCT_FOR_ID(fromlist) STRUCT_FOR_ID(fromtimestamp) @@ -442,6 +438,7 @@ struct _Py_global_strings { STRUCT_FOR_ID(fset) STRUCT_FOR_ID(func) STRUCT_FOR_ID(future) + STRUCT_FOR_ID(g) STRUCT_FOR_ID(generation) STRUCT_FOR_ID(genexpr) STRUCT_FOR_ID(get) @@ -455,6 +452,7 @@ struct _Py_global_strings { STRUCT_FOR_ID(globals) STRUCT_FOR_ID(groupindex) STRUCT_FOR_ID(groups) + STRUCT_FOR_ID(h) STRUCT_FOR_ID(handle) STRUCT_FOR_ID(hash_name) STRUCT_FOR_ID(header) @@ -463,6 +461,7 @@ struct _Py_global_strings { STRUCT_FOR_ID(hook) STRUCT_FOR_ID(id) STRUCT_FOR_ID(ident) + STRUCT_FOR_ID(identity_hint) STRUCT_FOR_ID(ignore) STRUCT_FOR_ID(imag) STRUCT_FOR_ID(importlib) @@ -483,6 +482,7 @@ struct _Py_global_strings { STRUCT_FOR_ID(instructions) STRUCT_FOR_ID(intern) STRUCT_FOR_ID(intersection) + STRUCT_FOR_ID(interval) STRUCT_FOR_ID(is_running) STRUCT_FOR_ID(isatty) STRUCT_FOR_ID(isinstance) @@ -504,6 +504,7 @@ struct _Py_global_strings { STRUCT_FOR_ID(kw) STRUCT_FOR_ID(kw1) STRUCT_FOR_ID(kw2) + STRUCT_FOR_ID(kwdefaults) STRUCT_FOR_ID(lambda) STRUCT_FOR_ID(last) STRUCT_FOR_ID(last_exc) @@ -653,7 +654,6 @@ struct _Py_global_strings { STRUCT_FOR_ID(seek) STRUCT_FOR_ID(seekable) STRUCT_FOR_ID(selectors) - STRUCT_FOR_ID(self) STRUCT_FOR_ID(send) STRUCT_FOR_ID(sep) STRUCT_FOR_ID(sequence) @@ -675,7 +675,6 @@ struct _Py_global_strings { STRUCT_FOR_ID(sleep) STRUCT_FOR_ID(sock) STRUCT_FOR_ID(sort) - STRUCT_FOR_ID(sound) STRUCT_FOR_ID(source) STRUCT_FOR_ID(source_traceback) STRUCT_FOR_ID(src) @@ -717,7 +716,6 @@ struct _Py_global_strings { STRUCT_FOR_ID(timetuple) STRUCT_FOR_ID(top) STRUCT_FOR_ID(trace_callback) - STRUCT_FOR_ID(traceback) STRUCT_FOR_ID(trailers) STRUCT_FOR_ID(translate) STRUCT_FOR_ID(true) diff --git a/Include/internal/pycore_hashtable.h b/Include/internal/pycore_hashtable.h index f57978a8d614fb..369d49c42bbfcc 100644 --- a/Include/internal/pycore_hashtable.h +++ b/Include/internal/pycore_hashtable.h @@ -70,6 +70,11 @@ struct _Py_hashtable_t { _Py_hashtable_allocator_t alloc; }; +// Export _Py_hashtable functions for '_testinternalcapi' shared extension +PyAPI_FUNC(_Py_hashtable_t *) _Py_hashtable_new( + _Py_hashtable_hash_func hash_func, + _Py_hashtable_compare_func compare_func); + /* Hash a pointer (void*) */ PyAPI_FUNC(Py_uhash_t) _Py_hashtable_hash_ptr(const void *key); @@ -78,10 +83,6 @@ PyAPI_FUNC(int) _Py_hashtable_compare_direct( const void *key1, const void *key2); -PyAPI_FUNC(_Py_hashtable_t *) _Py_hashtable_new( - _Py_hashtable_hash_func hash_func, - _Py_hashtable_compare_func compare_func); - PyAPI_FUNC(_Py_hashtable_t *) _Py_hashtable_new_full( _Py_hashtable_hash_func hash_func, _Py_hashtable_compare_func compare_func, diff --git a/Include/internal/pycore_identifier.h b/Include/internal/pycore_identifier.h new file mode 100644 index 00000000000000..cda28810a48196 --- /dev/null +++ b/Include/internal/pycore_identifier.h @@ -0,0 +1,20 @@ +/* String Literals: _Py_Identifier API */ + +#ifndef Py_INTERNAL_IDENTIFIER_H +#define Py_INTERNAL_IDENTIFIER_H +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef Py_BUILD_CORE +# error "this header requires Py_BUILD_CORE define" +#endif + +extern PyObject* _PyType_LookupId(PyTypeObject *, _Py_Identifier *); +extern PyObject* _PyObject_LookupSpecialId(PyObject *, _Py_Identifier *); +extern int _PyObject_SetAttrId(PyObject *, _Py_Identifier *, PyObject *); + +#ifdef __cplusplus +} +#endif +#endif // !Py_INTERNAL_IDENTIFIER_H diff --git a/Include/internal/pycore_import.h b/Include/internal/pycore_import.h index 077508e6c58f6c..c84f87a831bf38 100644 --- a/Include/internal/pycore_import.h +++ b/Include/internal/pycore_import.h @@ -5,12 +5,19 @@ extern "C" { #endif +#ifndef Py_BUILD_CORE +# error "this header requires Py_BUILD_CORE define" +#endif + +#include "pycore_lock.h" // PyMutex #include "pycore_hashtable.h" // _Py_hashtable_t #include "pycore_time.h" // _PyTime_t extern int _PyImport_IsInitialized(PyInterpreterState *); +// Export for 'pyexpat' shared extension PyAPI_FUNC(int) _PyImport_SetModule(PyObject *name, PyObject *module); + extern int _PyImport_SetModuleString(const char *name, PyObject* module); extern void _PyImport_AcquireLock(PyInterpreterState *interp); @@ -24,7 +31,10 @@ extern int _PyImport_FixupBuiltin( extern int _PyImport_FixupExtensionObject(PyObject*, PyObject *, PyObject *, PyObject *); +// Export for many shared extensions, like '_json' PyAPI_FUNC(PyObject*) _PyImport_GetModuleAttr(PyObject *, PyObject *); + +// Export for many shared extensions, like '_datetime' PyAPI_FUNC(PyObject*) _PyImport_GetModuleAttrString(const char *, const char *); @@ -38,7 +48,7 @@ struct _import_runtime_state { Py_ssize_t last_module_index; struct { /* A lock to guard the cache. */ - PyThread_type_lock mutex; + PyMutex mutex; /* The actual cache of (filename, name, PyModuleDef) for modules. Only legacy (single-phase init) extension modules are added and only if they support multiple initialization (m_size >- 0) @@ -99,7 +109,7 @@ struct _import_state { }; #ifdef HAVE_DLOPEN -# include +# include // RTLD_NOW, RTLD_LAZY # if HAVE_DECL_RTLD_NOW # define _Py_DLOPEN_FLAGS RTLD_NOW # else @@ -183,11 +193,9 @@ struct _module_alias { const char *orig; /* ASCII encoded string */ }; -// Export for test_ctypes +// Export these 3 symbols for test_ctypes PyAPI_DATA(const struct _frozen*) _PyImport_FrozenBootstrap; -// Export for test_ctypes PyAPI_DATA(const struct _frozen*) _PyImport_FrozenStdlib; -// Export for test_ctypes PyAPI_DATA(const struct _frozen*) _PyImport_FrozenTest; extern const struct _module_alias * _PyImport_FrozenAliases; diff --git a/Include/internal/pycore_importdl.h b/Include/internal/pycore_importdl.h new file mode 100644 index 00000000000000..c8583582b358ac --- /dev/null +++ b/Include/internal/pycore_importdl.h @@ -0,0 +1,57 @@ +#ifndef Py_INTERNAL_IMPORTDL_H +#define Py_INTERNAL_IMPORTDL_H + +#include "patchlevel.h" // PY_MAJOR_VERSION + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef Py_BUILD_CORE +# error "this header requires Py_BUILD_CORE define" +#endif + + +extern const char *_PyImport_DynLoadFiletab[]; + +extern PyObject *_PyImport_LoadDynamicModuleWithSpec(PyObject *spec, FILE *); + +typedef PyObject *(*PyModInitFunction)(void); + +/* Max length of module suffix searched for -- accommodates "module.slb" */ +#define MAXSUFFIXSIZE 12 + +#ifdef MS_WINDOWS +#include +typedef FARPROC dl_funcptr; + +#ifdef _DEBUG +# define PYD_DEBUG_SUFFIX "_d" +#else +# define PYD_DEBUG_SUFFIX "" +#endif + +#ifdef Py_GIL_DISABLED +# define PYD_THREADING_TAG "t" +#else +# define PYD_THREADING_TAG "" +#endif + +#ifdef PYD_PLATFORM_TAG +# define PYD_SOABI "cp" Py_STRINGIFY(PY_MAJOR_VERSION) Py_STRINGIFY(PY_MINOR_VERSION) PYD_THREADING_TAG "-" PYD_PLATFORM_TAG +#else +# define PYD_SOABI "cp" Py_STRINGIFY(PY_MAJOR_VERSION) Py_STRINGIFY(PY_MINOR_VERSION) PYD_THREADING_TAG +#endif + +#define PYD_TAGGED_SUFFIX PYD_DEBUG_SUFFIX "." PYD_SOABI ".pyd" +#define PYD_UNTAGGED_SUFFIX PYD_DEBUG_SUFFIX ".pyd" + +#else +typedef void (*dl_funcptr)(void); +#endif + + +#ifdef __cplusplus +} +#endif +#endif /* !Py_INTERNAL_IMPORTDL_H */ diff --git a/Include/internal/pycore_initconfig.h b/Include/internal/pycore_initconfig.h index 0945bb0936f039..c86988234f6a05 100644 --- a/Include/internal/pycore_initconfig.h +++ b/Include/internal/pycore_initconfig.h @@ -22,7 +22,7 @@ struct pyruntimestate; #endif #define _PyStatus_OK() \ - (PyStatus){._type = _PyStatus_TYPE_OK,} + (PyStatus){._type = _PyStatus_TYPE_OK} /* other fields are set to 0 */ #define _PyStatus_ERR(ERR_MSG) \ (PyStatus){ \ @@ -30,7 +30,8 @@ struct pyruntimestate; .func = _PyStatus_GET_FUNC(), \ .err_msg = (ERR_MSG)} /* other fields are set to 0 */ -#define _PyStatus_NO_MEMORY() _PyStatus_ERR("memory allocation failed") +#define _PyStatus_NO_MEMORY_ERRMSG "memory allocation failed" +#define _PyStatus_NO_MEMORY() _PyStatus_ERR(_PyStatus_NO_MEMORY_ERRMSG) #define _PyStatus_EXIT(EXITCODE) \ (PyStatus){ \ ._type = _PyStatus_TYPE_EXIT, \ @@ -44,6 +45,10 @@ struct pyruntimestate; #define _PyStatus_UPDATE_FUNC(err) \ do { (err).func = _PyStatus_GET_FUNC(); } while (0) +// Export for '_testinternalcapi' shared extension +PyAPI_FUNC(void) _PyErr_SetFromPyStatus(PyStatus status); + + /* --- PyWideStringList ------------------------------------------------ */ #define _PyWideStringList_INIT (PyWideStringList){.length = 0, .items = NULL} @@ -124,6 +129,7 @@ extern PyStatus _PyPreCmdline_Read(_PyPreCmdline *cmdline, // Export for '_testembed' program PyAPI_FUNC(void) _PyPreConfig_InitCompatConfig(PyPreConfig *preconfig); + extern void _PyPreConfig_InitFromConfig( PyPreConfig *preconfig, const PyConfig *config); @@ -149,6 +155,7 @@ typedef enum { // Export for '_testembed' program PyAPI_FUNC(void) _PyConfig_InitCompatConfig(PyConfig *config); + extern PyStatus _PyConfig_Copy( PyConfig *config, const PyConfig *config2); @@ -163,16 +170,16 @@ extern PyStatus _PyConfig_SetPyArgv( PyConfig *config, const _PyArgv *args); -PyAPI_FUNC(PyObject*) _PyConfig_AsDict(const PyConfig *config); -PyAPI_FUNC(int) _PyConfig_FromDict(PyConfig *config, PyObject *dict); extern void _Py_DumpPathConfig(PyThreadState *tstate); -PyAPI_FUNC(PyObject*) _Py_Get_Getpath_CodeObject(void); - /* --- Function used for testing ---------------------------------- */ +// Export these functions for '_testinternalcapi' shared extension +PyAPI_FUNC(PyObject*) _PyConfig_AsDict(const PyConfig *config); +PyAPI_FUNC(int) _PyConfig_FromDict(PyConfig *config, PyObject *dict); +PyAPI_FUNC(PyObject*) _Py_Get_Getpath_CodeObject(void); PyAPI_FUNC(PyObject*) _Py_GetConfigsAsDict(void); #ifdef __cplusplus diff --git a/Include/internal/pycore_instruments.h b/Include/internal/pycore_instruments.h index ccccd54a2f70a2..eae8371ef7f9b8 100644 --- a/Include/internal/pycore_instruments.h +++ b/Include/internal/pycore_instruments.h @@ -1,12 +1,11 @@ - #ifndef Py_INTERNAL_INSTRUMENT_H #define Py_INTERNAL_INSTRUMENT_H +#ifndef Py_BUILD_CORE +# error "this header requires Py_BUILD_CORE define" +#endif -#include "pycore_bitutils.h" // _Py_popcount32 -#include "pycore_frame.h" - -#include "cpython/code.h" +#include "pycore_frame.h" // _PyInterpreterFrame #ifdef __cplusplus extern "C" { @@ -29,7 +28,7 @@ extern "C" { #define PY_MONITORING_EVENT_STOP_ITERATION 9 #define PY_MONITORING_IS_INSTRUMENTED_EVENT(ev) \ - ((ev) <= PY_MONITORING_EVENT_STOP_ITERATION) + ((ev) < _PY_MONITORING_LOCAL_EVENTS) /* Other events, mainly exceptions */ @@ -64,6 +63,8 @@ typedef uint32_t _PyMonitoringEventSet; PyObject *_PyMonitoring_RegisterCallback(int tool_id, int event_id, PyObject *obj); int _PyMonitoring_SetEvents(int tool_id, _PyMonitoringEventSet events); +int _PyMonitoring_SetLocalEvents(PyCodeObject *code, int tool_id, _PyMonitoringEventSet events); +int _PyMonitoring_GetLocalEvents(PyCodeObject *code, int tool_id, _PyMonitoringEventSet *events); extern int _Py_call_instrumentation(PyThreadState *tstate, int event, @@ -90,10 +91,6 @@ extern int _Py_call_instrumentation_2args(PyThreadState *tstate, int event, _PyInterpreterFrame *frame, _Py_CODEUNIT *instr, PyObject *arg0, PyObject *arg1); -extern void -_Py_call_instrumentation_exc0(PyThreadState *tstate, int event, - _PyInterpreterFrame *frame, _Py_CODEUNIT *instr); - extern void _Py_call_instrumentation_exc2(PyThreadState *tstate, int event, _PyInterpreterFrame *frame, _Py_CODEUNIT *instr, PyObject *arg0, PyObject *arg1); diff --git a/Include/internal/pycore_interp.h b/Include/internal/pycore_interp.h index 91c473e58eaba2..dadc8e3b91a75d 100644 --- a/Include/internal/pycore_interp.h +++ b/Include/internal/pycore_interp.h @@ -8,29 +8,31 @@ extern "C" { # error "this header requires Py_BUILD_CORE define" #endif -#include +#include // bool #include "pycore_ast_state.h" // struct ast_state #include "pycore_atexit.h" // struct atexit_state -#include "pycore_atomic.h" // _Py_atomic_address #include "pycore_ceval_state.h" // struct _ceval_state #include "pycore_code.h" // struct callable_cache #include "pycore_context.h" // struct _Py_context_state +#include "pycore_crossinterp.h" // struct _xidregistry #include "pycore_dict_state.h" // struct _Py_dict_state #include "pycore_dtoa.h" // struct _dtoa_state #include "pycore_exceptions.h" // struct _Py_exc_state #include "pycore_floatobject.h" // struct _Py_float_state #include "pycore_function.h" // FUNC_MAX_WATCHERS -#include "pycore_genobject.h" // struct _Py_async_gen_state #include "pycore_gc.h" // struct _gc_runtime_state -#include "pycore_global_objects.h" // struct _Py_interp_static_objects +#include "pycore_genobject.h" // struct _Py_async_gen_state +#include "pycore_global_objects.h"// struct _Py_interp_cached_objects #include "pycore_import.h" // struct _import_state #include "pycore_instruments.h" // _PY_MONITORING_EVENTS #include "pycore_list.h" // struct _Py_list_state -#include "pycore_object_state.h" // struct _py_object_state -#include "pycore_obmalloc.h" // struct obmalloc_state +#include "pycore_mimalloc.h" // struct _mimalloc_interp_state +#include "pycore_object_state.h" // struct _py_object_state +#include "pycore_obmalloc.h" // struct _obmalloc_state +#include "pycore_tstate.h" // _PyThreadStateImpl #include "pycore_tuple.h" // struct _Py_tuple_state -#include "pycore_typeobject.h" // struct type_cache +#include "pycore_typeobject.h" // struct types_state #include "pycore_unicodeobject.h" // struct _Py_unicode_state #include "pycore_warnings.h" // struct _warnings_runtime_state @@ -39,6 +41,10 @@ struct _Py_long_state { int max_str_digits; }; + +/* cross-interpreter data registry */ + + /* interpreter state */ /* PyInterpreterState holds the global state for one of the runtime's @@ -67,12 +73,13 @@ struct _is { int _initialized; int finalizing; - uint64_t monitoring_version; - uint64_t last_restart_version; + uintptr_t last_restart_version; struct pythreads { uint64_t next_unique_id; /* The linked list of threads, newest first. */ PyThreadState *head; + /* The thread currently executing in the __main__ module, if any. */ + PyThreadState *main; /* Used in Modules/_threadmodule.c. */ long count; /* Support for runtime thread stack size tuning. @@ -92,7 +99,9 @@ struct _is { Use _PyInterpreterState_GetFinalizing() and _PyInterpreterState_SetFinalizing() to access it, don't access it directly. */ - _Py_atomic_address _finalizing; + PyThreadState* _finalizing; + /* The ID of the OS thread in which we are finalizing. */ + unsigned long _finalizing_id; struct _gc_runtime_state gc; @@ -146,6 +155,9 @@ struct _is { Py_ssize_t co_extra_user_count; freefunc co_extra_freefuncs[MAX_CO_EXTRA_USERS]; + /* cross-interpreter data and utils */ + struct _xi_state xi; + #ifdef HAVE_FORK PyObject *before_forkers; PyObject *after_forkers_parent; @@ -155,6 +167,10 @@ struct _is { struct _warnings_runtime_state warnings; struct atexit_state atexit; +#if defined(Py_GIL_DISABLED) + struct _mimalloc_interp_state mimalloc; +#endif + struct _obmalloc_state obmalloc; PyObject *audit_hooks; @@ -163,9 +179,11 @@ struct _is { // One bit is set for each non-NULL entry in code_watchers uint8_t active_code_watchers; +#if !defined(Py_GIL_DISABLED) + struct _Py_freelist_state freelist_state; +#endif struct _py_object_state object_state; struct _Py_unicode_state unicode; - struct _Py_float_state float_state; struct _Py_long_state long_state; struct _dtoa_state dtoa; struct _py_func_state func_state; @@ -174,7 +192,6 @@ struct _is { PySliceObject *slice_cache; struct _Py_tuple_state tuple; - struct _Py_list_state list; struct _Py_dict_state dict_state; struct _Py_async_gen_state async_gen; struct _Py_context_state context; @@ -184,11 +201,12 @@ struct _is { struct types_state types; struct callable_cache callable_cache; _PyOptimizerObject *optimizer; + _PyExecutorObject *executor_list_head; uint16_t optimizer_resume_threshold; uint16_t optimizer_backedge_threshold; + uint32_t next_func_version; - _Py_Monitors monitors; - bool f_opcode_trace_set; + _Py_GlobalMonitors monitors; bool sys_profile_initialized; bool sys_trace_initialized; Py_ssize_t sys_profiling_threads; /* Count of threads with c_profilefunc set */ @@ -199,8 +217,9 @@ struct _is { struct _Py_interp_cached_objects cached_objects; struct _Py_interp_static_objects static_objects; - /* the initial PyInterpreterState.threads.head */ - PyThreadState _initial_thread; + /* the initial PyInterpreterState.threads.head */ + _PyThreadStateImpl _initial_thread; + Py_ssize_t _interactive_src_count; }; @@ -211,72 +230,72 @@ extern void _PyInterpreterState_Clear(PyThreadState *tstate); static inline PyThreadState* _PyInterpreterState_GetFinalizing(PyInterpreterState *interp) { - return (PyThreadState*)_Py_atomic_load_relaxed(&interp->_finalizing); + return (PyThreadState*)_Py_atomic_load_ptr_relaxed(&interp->_finalizing); +} + +static inline unsigned long +_PyInterpreterState_GetFinalizingID(PyInterpreterState *interp) { + return _Py_atomic_load_ulong_relaxed(&interp->_finalizing_id); } static inline void _PyInterpreterState_SetFinalizing(PyInterpreterState *interp, PyThreadState *tstate) { - _Py_atomic_store_relaxed(&interp->_finalizing, (uintptr_t)tstate); + _Py_atomic_store_ptr_relaxed(&interp->_finalizing, tstate); + if (tstate == NULL) { + _Py_atomic_store_ulong_relaxed(&interp->_finalizing_id, 0); + } + else { + // XXX Re-enable this assert once gh-109860 is fixed. + //assert(tstate->thread_id == PyThread_get_thread_ident()); + _Py_atomic_store_ulong_relaxed(&interp->_finalizing_id, + tstate->thread_id); + } } -/* cross-interpreter data registry */ - -/* For now we use a global registry of shareable classes. An - alternative would be to add a tp_* slot for a class's - crossinterpdatafunc. It would be simpler and more efficient. */ - -struct _xidregitem; +// Export for the _xxinterpchannels module. +PyAPI_FUNC(PyInterpreterState *) _PyInterpreterState_LookUpID(int64_t); -struct _xidregitem { - struct _xidregitem *prev; - struct _xidregitem *next; - PyObject *cls; // weakref to a PyTypeObject - crossinterpdatafunc getdata; -}; - -extern PyInterpreterState* _PyInterpreterState_LookUpID(int64_t); - -extern int _PyInterpreterState_IDInitref(PyInterpreterState *); -extern int _PyInterpreterState_IDIncref(PyInterpreterState *); -extern void _PyInterpreterState_IDDecref(PyInterpreterState *); +PyAPI_FUNC(int) _PyInterpreterState_IDInitref(PyInterpreterState *); +PyAPI_FUNC(int) _PyInterpreterState_IDIncref(PyInterpreterState *); +PyAPI_FUNC(void) _PyInterpreterState_IDDecref(PyInterpreterState *); extern const PyConfig* _PyInterpreterState_GetConfig(PyInterpreterState *interp); -/* Get a copy of the current interpreter configuration. - - Return 0 on success. Raise an exception and return -1 on error. - - The caller must initialize 'config', using PyConfig_InitPythonConfig() - for example. - - Python must be preinitialized to call this method. - The caller must hold the GIL. - - Once done with the configuration, PyConfig_Clear() must be called to clear - it. - - Export for '_testinternalcapi' shared extension. */ +// Get a copy of the current interpreter configuration. +// +// Return 0 on success. Raise an exception and return -1 on error. +// +// The caller must initialize 'config', using PyConfig_InitPythonConfig() +// for example. +// +// Python must be preinitialized to call this method. +// The caller must hold the GIL. +// +// Once done with the configuration, PyConfig_Clear() must be called to clear +// it. +// +// Export for '_testinternalcapi' shared extension. PyAPI_FUNC(int) _PyInterpreterState_GetConfigCopy( struct PyConfig *config); -/* Set the configuration of the current interpreter. - - This function should be called during or just after the Python - initialization. - - Update the sys module with the new configuration. If the sys module was - modified directly after the Python initialization, these changes are lost. - - Some configuration like faulthandler or warnoptions can be updated in the - configuration, but don't reconfigure Python (don't enable/disable - faulthandler and don't reconfigure warnings filters). - - Return 0 on success. Raise an exception and return -1 on error. - - The configuration should come from _PyInterpreterState_GetConfigCopy(). - - Export for '_testinternalcapi' shared extension. */ +// Set the configuration of the current interpreter. +// +// This function should be called during or just after the Python +// initialization. +// +// Update the sys module with the new configuration. If the sys module was +// modified directly after the Python initialization, these changes are lost. +// +// Some configuration like faulthandler or warnoptions can be updated in the +// configuration, but don't reconfigure Python (don't enable/disable +// faulthandler and don't reconfigure warnings filters). +// +// Return 0 on success. Raise an exception and return -1 on error. +// +// The configuration should come from _PyInterpreterState_GetConfigCopy(). +// +// Export for '_testinternalcapi' shared extension. PyAPI_FUNC(int) _PyInterpreterState_SetConfig( const struct PyConfig *config); @@ -311,6 +330,10 @@ might not be allowed in the current interpreter (i.e. os.fork() would fail). extern int _PyInterpreterState_HasFeature(PyInterpreterState *interp, unsigned long feature); +PyAPI_FUNC(PyStatus) _PyInterpreterState_New( + PyThreadState *tstate, + PyInterpreterState **pinterp); + #ifdef __cplusplus } diff --git a/Include/internal/pycore_intrinsics.h b/Include/internal/pycore_intrinsics.h index 37d4efc12bb771..3a8dd95cff8e5d 100644 --- a/Include/internal/pycore_intrinsics.h +++ b/Include/internal/pycore_intrinsics.h @@ -1,3 +1,9 @@ +#ifndef Py_INTERNAL_INTRINSIC_H +#define Py_INTERNAL_INTRINSIC_H + +#ifndef Py_BUILD_CORE +# error "this header requires Py_BUILD_CORE define" +#endif /* Unary Functions: */ #define INTRINSIC_1_INVALID 0 @@ -40,3 +46,5 @@ typedef struct { extern const intrinsic_func1_info _PyIntrinsics_UnaryFunctions[]; extern const intrinsic_func2_info _PyIntrinsics_BinaryFunctions[]; + +#endif // !Py_INTERNAL_INTRINSIC_H diff --git a/Include/internal/pycore_list.h b/Include/internal/pycore_list.h index b2e503c87542bf..6c29d882335512 100644 --- a/Include/internal/pycore_list.h +++ b/Include/internal/pycore_list.h @@ -8,32 +8,16 @@ extern "C" { # error "this header requires Py_BUILD_CORE define" #endif -#include "listobject.h" // _PyList_CAST() +#include "pycore_freelist.h" // _PyFreeListState - -/* runtime lifecycle */ - -extern void _PyList_Fini(PyInterpreterState *); +extern PyObject* _PyList_Extend(PyListObject *, PyObject *); +extern void _PyList_DebugMallocStats(FILE *out); -/* other API */ - -#ifndef WITH_FREELISTS -// without freelists -# define PyList_MAXFREELIST 0 -#endif +/* runtime lifecycle */ -/* Empty list reuse scheme to save calls to malloc and free */ -#ifndef PyList_MAXFREELIST -# define PyList_MAXFREELIST 80 -#endif +extern void _PyList_Fini(_PyFreeListState *); -struct _Py_list_state { -#if PyList_MAXFREELIST > 0 - PyListObject *free_list[PyList_MAXFREELIST]; - int numfree; -#endif -}; #define _PyList_ITEMS(op) _Py_RVALUE(_PyList_CAST(op)->ob_item) @@ -49,8 +33,8 @@ _PyList_AppendTakeRef(PyListObject *self, PyObject *newitem) Py_ssize_t allocated = self->allocated; assert((size_t)len + 1 < PY_SSIZE_T_MAX); if (allocated > len) { - Py_SET_SIZE(self, len + 1); PyList_SET_ITEM(self, len, newitem); + Py_SET_SIZE(self, len + 1); return 0; } return _PyList_AppendTakeRefListResize(self, newitem); diff --git a/Include/internal/pycore_llist.h b/Include/internal/pycore_llist.h new file mode 100644 index 00000000000000..5fd261da05fa5d --- /dev/null +++ b/Include/internal/pycore_llist.h @@ -0,0 +1,107 @@ +// A doubly-linked list that can be embedded in a struct. +// +// Usage: +// struct llist_node head = LLIST_INIT(head); +// typedef struct { +// ... +// struct llist_node node; +// ... +// } MyObj; +// +// llist_insert_tail(&head, &obj->node); +// llist_remove(&obj->node); +// +// struct llist_node *node; +// llist_for_each(node, &head) { +// MyObj *obj = llist_data(node, MyObj, node); +// ... +// } +// + +#ifndef Py_INTERNAL_LLIST_H +#define Py_INTERNAL_LLIST_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef Py_BUILD_CORE +# error "Py_BUILD_CORE must be defined to include this header" +#endif + +struct llist_node { + struct llist_node *next; + struct llist_node *prev; +}; + +// Get the struct containing a node. +#define llist_data(node, type, member) \ + (type*)((char*)node - offsetof(type, member)) + +// Iterate over a list. +#define llist_for_each(node, head) \ + for (node = (head)->next; node != (head); node = node->next) + +// Iterate over a list, but allow removal of the current node. +#define llist_for_each_safe(node, head) \ + for (struct llist_node *_next = (node = (head)->next, node->next); \ + node != (head); node = _next, _next = node->next) + +#define LLIST_INIT(head) { &head, &head } + +static inline void +llist_init(struct llist_node *head) +{ + head->next = head; + head->prev = head; +} + +// Returns 1 if the list is empty, 0 otherwise. +static inline int +llist_empty(struct llist_node *head) +{ + return head->next == head; +} + +// Appends to the tail of the list. +static inline void +llist_insert_tail(struct llist_node *head, struct llist_node *node) +{ + node->prev = head->prev; + node->next = head; + head->prev->next = node; + head->prev = node; +} + +// Remove a node from the list. +static inline void +llist_remove(struct llist_node *node) +{ + struct llist_node *prev = node->prev; + struct llist_node *next = node->next; + prev->next = next; + next->prev = prev; + node->prev = NULL; + node->next = NULL; +} + +// Append all nodes from head2 onto head1. head2 is left empty. +static inline void +llist_concat(struct llist_node *head1, struct llist_node *head2) +{ + if (!llist_empty(head2)) { + head1->prev->next = head2->next; + head2->next->prev = head1->prev; + + head1->prev = head2->prev; + head2->prev->next = head1; + llist_init(head2); + } +} + +#ifdef __cplusplus +} +#endif +#endif /* !Py_INTERNAL_LLIST_H */ diff --git a/Include/internal/pycore_lock.h b/Include/internal/pycore_lock.h new file mode 100644 index 00000000000000..18a8896d97a548 --- /dev/null +++ b/Include/internal/pycore_lock.h @@ -0,0 +1,258 @@ +// Lightweight locks and other synchronization mechanisms. +// +// These implementations are based on WebKit's WTF::Lock. See +// https://webkit.org/blog/6161/locking-in-webkit/ for a description of the +// design. +#ifndef Py_INTERNAL_LOCK_H +#define Py_INTERNAL_LOCK_H +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef Py_BUILD_CORE +# error "this header requires Py_BUILD_CORE define" +#endif + +#include "pycore_time.h" // _PyTime_t + + +// A mutex that occupies one byte. The lock can be zero initialized. +// +// Only the two least significant bits are used. The remaining bits should be +// zero: +// 0b00: unlocked +// 0b01: locked +// 0b10: unlocked and has parked threads +// 0b11: locked and has parked threads +// +// Typical initialization: +// PyMutex m = (PyMutex){0}; +// +// Typical usage: +// PyMutex_Lock(&m); +// ... +// PyMutex_Unlock(&m); + +// NOTE: In Py_GIL_DISABLED builds, `struct _PyMutex` is defined in Include/object.h. +// The Py_GIL_DISABLED builds need the definition in Include/object.h for the +// `ob_mutex` field in PyObject. For the default (non-free-threaded) build, +// we define the struct here to avoid exposing it in the public API. +#ifndef Py_GIL_DISABLED +struct _PyMutex { uint8_t v; }; +#endif + +typedef struct _PyMutex PyMutex; + +#define _Py_UNLOCKED 0 +#define _Py_LOCKED 1 +#define _Py_HAS_PARKED 2 +#define _Py_ONCE_INITIALIZED 4 + +// (private) slow path for locking the mutex +PyAPI_FUNC(void) _PyMutex_LockSlow(PyMutex *m); + +// (private) slow path for unlocking the mutex +PyAPI_FUNC(void) _PyMutex_UnlockSlow(PyMutex *m); + +static inline int +PyMutex_LockFast(uint8_t *lock_bits) +{ + uint8_t expected = _Py_UNLOCKED; + return _Py_atomic_compare_exchange_uint8(lock_bits, &expected, _Py_LOCKED); +} + +// Locks the mutex. +// +// If the mutex is currently locked, the calling thread will be parked until +// the mutex is unlocked. If the current thread holds the GIL, then the GIL +// will be released while the thread is parked. +static inline void +PyMutex_Lock(PyMutex *m) +{ + uint8_t expected = _Py_UNLOCKED; + if (!_Py_atomic_compare_exchange_uint8(&m->v, &expected, _Py_LOCKED)) { + _PyMutex_LockSlow(m); + } +} + +// Unlocks the mutex. +static inline void +PyMutex_Unlock(PyMutex *m) +{ + uint8_t expected = _Py_LOCKED; + if (!_Py_atomic_compare_exchange_uint8(&m->v, &expected, _Py_UNLOCKED)) { + _PyMutex_UnlockSlow(m); + } +} + +// Checks if the mutex is currently locked. +static inline int +PyMutex_IsLocked(PyMutex *m) +{ + return (_Py_atomic_load_uint8(&m->v) & _Py_LOCKED) != 0; +} + +// Re-initializes the mutex after a fork to the unlocked state. +static inline void +_PyMutex_at_fork_reinit(PyMutex *m) +{ + memset(m, 0, sizeof(*m)); +} + +typedef enum _PyLockFlags { + // Do not detach/release the GIL when waiting on the lock. + _Py_LOCK_DONT_DETACH = 0, + + // Detach/release the GIL while waiting on the lock. + _PY_LOCK_DETACH = 1, + + // Handle signals if interrupted while waiting on the lock. + _PY_LOCK_HANDLE_SIGNALS = 2, +} _PyLockFlags; + +// Lock a mutex with an optional timeout and additional options. See +// _PyLockFlags for details. +extern PyLockStatus +_PyMutex_LockTimed(PyMutex *m, _PyTime_t timeout_ns, _PyLockFlags flags); + +// Lock a mutex with aditional options. See _PyLockFlags for details. +static inline void +PyMutex_LockFlags(PyMutex *m, _PyLockFlags flags) +{ + uint8_t expected = _Py_UNLOCKED; + if (!_Py_atomic_compare_exchange_uint8(&m->v, &expected, _Py_LOCKED)) { + _PyMutex_LockTimed(m, -1, flags); + } +} + +// Unlock a mutex, returns 0 if the mutex is not locked (used for improved +// error messages). +extern int _PyMutex_TryUnlock(PyMutex *m); + + +// PyEvent is a one-time event notification +typedef struct { + uint8_t v; +} PyEvent; + +// Set the event and notify any waiting threads. +// Export for '_testinternalcapi' shared extension +PyAPI_FUNC(void) _PyEvent_Notify(PyEvent *evt); + +// Wait for the event to be set. If the event is already set, then this returns +// immediately. +PyAPI_FUNC(void) PyEvent_Wait(PyEvent *evt); + +// Wait for the event to be set, or until the timeout expires. If the event is +// already set, then this returns immediately. Returns 1 if the event was set, +// and 0 if the timeout expired or thread was interrupted. +PyAPI_FUNC(int) PyEvent_WaitTimed(PyEvent *evt, _PyTime_t timeout_ns); + + +// _PyRawMutex implements a word-sized mutex that that does not depend on the +// parking lot API, and therefore can be used in the parking lot +// implementation. +// +// The mutex uses a packed representation: the least significant bit is used to +// indicate whether the mutex is locked or not. The remaining bits are either +// zero or a pointer to a `struct raw_mutex_entry` (see lock.c). +typedef struct { + uintptr_t v; +} _PyRawMutex; + +// Slow paths for lock/unlock +extern void _PyRawMutex_LockSlow(_PyRawMutex *m); +extern void _PyRawMutex_UnlockSlow(_PyRawMutex *m); + +static inline void +_PyRawMutex_Lock(_PyRawMutex *m) +{ + uintptr_t unlocked = _Py_UNLOCKED; + if (_Py_atomic_compare_exchange_uintptr(&m->v, &unlocked, _Py_LOCKED)) { + return; + } + _PyRawMutex_LockSlow(m); +} + +static inline void +_PyRawMutex_Unlock(_PyRawMutex *m) +{ + uintptr_t locked = _Py_LOCKED; + if (_Py_atomic_compare_exchange_uintptr(&m->v, &locked, _Py_UNLOCKED)) { + return; + } + _PyRawMutex_UnlockSlow(m); +} + +// A data structure that can be used to run initialization code once in a +// thread-safe manner. The C++11 equivalent is std::call_once. +typedef struct { + uint8_t v; +} _PyOnceFlag; + +// Type signature for one-time initialization functions. The function should +// return 0 on success and -1 on failure. +typedef int _Py_once_fn_t(void *arg); + +// (private) slow path for one time initialization +PyAPI_FUNC(int) +_PyOnceFlag_CallOnceSlow(_PyOnceFlag *flag, _Py_once_fn_t *fn, void *arg); + +// Calls `fn` once using `flag`. The `arg` is passed to the call to `fn`. +// +// Returns 0 on success and -1 on failure. +// +// If `fn` returns 0 (success), then subsequent calls immediately return 0. +// If `fn` returns -1 (failure), then subsequent calls will retry the call. +static inline int +_PyOnceFlag_CallOnce(_PyOnceFlag *flag, _Py_once_fn_t *fn, void *arg) +{ + if (_Py_atomic_load_uint8(&flag->v) == _Py_ONCE_INITIALIZED) { + return 0; + } + return _PyOnceFlag_CallOnceSlow(flag, fn, arg); +} + +// A readers-writer (RW) lock. The lock supports multiple concurrent readers or +// a single writer. The lock is write-preferring: if a writer is waiting while +// the lock is read-locked then, new readers will be blocked. This avoids +// starvation of writers. +// +// In C++, the equivalent synchronization primitive is std::shared_mutex +// with shared ("read") and exclusive ("write") locking. +// +// The two least significant bits are used to indicate if the lock is +// write-locked and if there are parked threads (either readers or writers) +// waiting to acquire the lock. The remaining bits are used to indicate the +// number of readers holding the lock. +// +// 0b000..00000: unlocked +// 0bnnn..nnn00: nnn..nnn readers holding the lock +// 0bnnn..nnn10: nnn..nnn readers holding the lock and a writer is waiting +// 0b00000..010: unlocked with awoken writer about to acquire lock +// 0b00000..001: write-locked +// 0b00000..011: write-locked and readers or other writers are waiting +// +// Note that reader_count must be zero if the lock is held by a writer, and +// vice versa. The lock can only be held by readers or a writer, but not both. +// +// The design is optimized for simplicity of the implementation. The lock is +// not fair: if fairness is desired, use an additional PyMutex to serialize +// writers. The lock is also not reentrant. +typedef struct { + uintptr_t bits; +} _PyRWMutex; + +// Read lock (i.e., shared lock) +PyAPI_FUNC(void) _PyRWMutex_RLock(_PyRWMutex *rwmutex); +PyAPI_FUNC(void) _PyRWMutex_RUnlock(_PyRWMutex *rwmutex); + +// Write lock (i.e., exclusive lock) +PyAPI_FUNC(void) _PyRWMutex_Lock(_PyRWMutex *rwmutex); +PyAPI_FUNC(void) _PyRWMutex_Unlock(_PyRWMutex *rwmutex); + + +#ifdef __cplusplus +} +#endif +#endif /* !Py_INTERNAL_LOCK_H */ diff --git a/Include/internal/pycore_long.h b/Include/internal/pycore_long.h index 3dc00ec7e04c6f..ec27df9e416c58 100644 --- a/Include/internal/pycore_long.h +++ b/Include/internal/pycore_long.h @@ -47,6 +47,16 @@ extern "C" { # error "_PY_LONG_DEFAULT_MAX_STR_DIGITS smaller than threshold." #endif +// _PyLong_NumBits. Return the number of bits needed to represent the +// absolute value of a long. For example, this returns 1 for 1 and -1, 2 +// for 2 and -2, and 2 for 3 and -3. It returns 0 for 0. +// v must not be NULL, and must be a normalized long. +// (size_t)-1 is returned and OverflowError set if the true result doesn't +// fit in a size_t. +// +// Export for 'math' shared extension. +PyAPI_FUNC(size_t) _PyLong_NumBits(PyObject *v); + /* runtime lifecycle */ @@ -79,11 +89,42 @@ static inline PyObject* _PyLong_FromUnsignedChar(unsigned char i) return (PyObject *)&_PyLong_SMALL_INTS[_PY_NSMALLNEGINTS+i]; } -extern PyObject *_PyLong_Add(PyLongObject *left, PyLongObject *right); -extern PyObject *_PyLong_Multiply(PyLongObject *left, PyLongObject *right); -extern PyObject *_PyLong_Subtract(PyLongObject *left, PyLongObject *right); +// _PyLong_Frexp returns a double x and an exponent e such that the +// true value is approximately equal to x * 2**e. e is >= 0. x is +// 0.0 if and only if the input is 0 (in which case, e and x are both +// zeroes); otherwise, 0.5 <= abs(x) < 1.0. On overflow, which is +// possible if the number of bits doesn't fit into a Py_ssize_t, sets +// OverflowError and returns -1.0 for x, 0 for e. +// +// Export for 'math' shared extension +PyAPI_DATA(double) _PyLong_Frexp(PyLongObject *a, Py_ssize_t *e); + +extern PyObject* _PyLong_FromBytes(const char *, Py_ssize_t, int); + +// _PyLong_DivmodNear. Given integers a and b, compute the nearest +// integer q to the exact quotient a / b, rounding to the nearest even integer +// in the case of a tie. Return (q, r), where r = a - q*b. The remainder r +// will satisfy abs(r) <= abs(b)/2, with equality possible only if q is +// even. +// +// Export for '_datetime' shared extension. +PyAPI_DATA(PyObject*) _PyLong_DivmodNear(PyObject *, PyObject *); + +// _PyLong_Format: Convert the long to a string object with given base, +// appending a base prefix of 0[box] if base is 2, 8 or 16. +// Export for '_tkinter' shared extension. +PyAPI_DATA(PyObject*) _PyLong_Format(PyObject *obj, int base); + +// Export for 'math' shared extension +PyAPI_DATA(PyObject*) _PyLong_Rshift(PyObject *, size_t); + +// Export for 'math' shared extension +PyAPI_DATA(PyObject*) _PyLong_Lshift(PyObject *, size_t); + +extern PyObject* _PyLong_Add(PyLongObject *left, PyLongObject *right); +extern PyObject* _PyLong_Multiply(PyLongObject *left, PyLongObject *right); +extern PyObject* _PyLong_Subtract(PyLongObject *left, PyLongObject *right); -// Used by _PyBytes_FromHex(), _PyBytes_DecodeEscape(), Python/mystrtoul.c. // Export for 'binascii' shared extension. PyAPI_DATA(unsigned char) _PyLong_DigitValue[256]; @@ -109,6 +150,23 @@ extern char* _PyLong_FormatBytesWriter( int base, int alternate); +// Argument converters used by Argument Clinic + +// Export for 'select' shared extension (Argument Clinic code) +PyAPI_FUNC(int) _PyLong_UnsignedShort_Converter(PyObject *, void *); + +// Export for '_testclinic' shared extension (Argument Clinic code) +PyAPI_FUNC(int) _PyLong_UnsignedInt_Converter(PyObject *, void *); + +// Export for '_blake2' shared extension (Argument Clinic code) +PyAPI_FUNC(int) _PyLong_UnsignedLong_Converter(PyObject *, void *); + +// Export for '_blake2' shared extension (Argument Clinic code) +PyAPI_FUNC(int) _PyLong_UnsignedLongLong_Converter(PyObject *, void *); + +// Export for '_testclinic' shared extension (Argument Clinic code) +PyAPI_FUNC(int) _PyLong_Size_t_Converter(PyObject *, void *); + /* Long value tag bits: * 0-1: Sign bits value = (1-sign), ie. negative=2, positive=0, zero=1. * 2: Reserved for immortality bit @@ -241,7 +299,7 @@ _PyLong_FlipSign(PyLongObject *op) { #define _PyLong_DIGIT_INIT(val) \ { \ - .ob_base = _PyObject_HEAD_INIT(&PyLong_Type) \ + .ob_base = _PyObject_HEAD_INIT(&PyLong_Type), \ .long_value = { \ .lv_tag = TAG_FROM_SIGN_AND_SIZE( \ (val) == 0 ? 0 : ((val) < 0 ? -1 : 1), \ diff --git a/Include/internal/pycore_memoryobject.h b/Include/internal/pycore_memoryobject.h index fe19e3f9611a16..62e204fcbf6533 100644 --- a/Include/internal/pycore_memoryobject.h +++ b/Include/internal/pycore_memoryobject.h @@ -8,6 +8,8 @@ extern "C" { # error "this header requires Py_BUILD_CORE define" #endif +extern PyTypeObject _PyManagedBuffer_Type; + PyObject * _PyMemoryView_FromBufferProc(PyObject *v, int flags, getbufferproc bufferproc); diff --git a/Include/internal/pycore_mimalloc.h b/Include/internal/pycore_mimalloc.h new file mode 100644 index 00000000000000..1e7ed5a4ca62e2 --- /dev/null +++ b/Include/internal/pycore_mimalloc.h @@ -0,0 +1,51 @@ +#ifndef Py_INTERNAL_MIMALLOC_H +#define Py_INTERNAL_MIMALLOC_H + +#ifndef Py_BUILD_CORE +# error "this header requires Py_BUILD_CORE define" +#endif + +#if defined(MIMALLOC_H) || defined(MIMALLOC_TYPES_H) +# error "pycore_mimalloc.h must be included before mimalloc.h" +#endif + +typedef enum { + _Py_MIMALLOC_HEAP_MEM = 0, // PyMem_Malloc() and friends + _Py_MIMALLOC_HEAP_OBJECT = 1, // non-GC objects + _Py_MIMALLOC_HEAP_GC = 2, // GC objects without pre-header + _Py_MIMALLOC_HEAP_GC_PRE = 3, // GC objects with pre-header + _Py_MIMALLOC_HEAP_COUNT +} _Py_mimalloc_heap_id; + +#include "pycore_pymem.h" + +#ifdef WITH_MIMALLOC +#define MI_DEBUG_UNINIT PYMEM_CLEANBYTE +#define MI_DEBUG_FREED PYMEM_DEADBYTE +#define MI_DEBUG_PADDING PYMEM_FORBIDDENBYTE +#ifdef Py_DEBUG +# define MI_DEBUG 1 +#else +# define MI_DEBUG 0 +#endif + +#include "mimalloc.h" +#include "mimalloc/types.h" +#include "mimalloc/internal.h" +#endif + +#ifdef Py_GIL_DISABLED +struct _mimalloc_interp_state { + // When exiting, threads place any segments with live blocks in this + // shared pool for other threads to claim and reuse. + mi_abandoned_pool_t abandoned_pool; +}; + +struct _mimalloc_thread_state { + mi_heap_t *current_object_heap; + mi_heap_t heaps[_Py_MIMALLOC_HEAP_COUNT]; + mi_tld_t tld; +}; +#endif + +#endif // Py_INTERNAL_MIMALLOC_H diff --git a/Include/internal/pycore_modsupport.h b/Include/internal/pycore_modsupport.h index e577c6ba856b77..3d3cd6722528e9 100644 --- a/Include/internal/pycore_modsupport.h +++ b/Include/internal/pycore_modsupport.h @@ -1,5 +1,8 @@ #ifndef Py_INTERNAL_MODSUPPORT_H #define Py_INTERNAL_MODSUPPORT_H + +#include "pycore_lock.h" // _PyOnceFlag + #ifdef __cplusplus extern "C" { #endif @@ -13,6 +16,24 @@ extern int _PyArg_NoKwnames(const char *funcname, PyObject *kwnames); #define _PyArg_NoKwnames(funcname, kwnames) \ ((kwnames) == NULL || _PyArg_NoKwnames((funcname), (kwnames))) +// Export for '_bz2' shared extension +PyAPI_FUNC(int) _PyArg_NoPositional(const char *funcname, PyObject *args); +#define _PyArg_NoPositional(funcname, args) \ + ((args) == NULL || _PyArg_NoPositional((funcname), (args))) + +// Export for '_asyncio' shared extension +PyAPI_FUNC(int) _PyArg_NoKeywords(const char *funcname, PyObject *kwargs); +#define _PyArg_NoKeywords(funcname, kwargs) \ + ((kwargs) == NULL || _PyArg_NoKeywords((funcname), (kwargs))) + +// Export for 'zlib' shared extension +PyAPI_FUNC(int) _PyArg_CheckPositional(const char *, Py_ssize_t, + Py_ssize_t, Py_ssize_t); +#define _Py_ANY_VARARGS(n) ((n) == PY_SSIZE_T_MAX) +#define _PyArg_CheckPositional(funcname, nargs, min, max) \ + ((!_Py_ANY_VARARGS(max) && (min) <= (nargs) && (nargs) <= (max)) \ + || _PyArg_CheckPositional((funcname), (nargs), (min), (max))) + extern PyObject ** _Py_VaBuildStack( PyObject **small_stack, Py_ssize_t small_stack_len, @@ -22,6 +43,81 @@ extern PyObject ** _Py_VaBuildStack( extern PyObject* _PyModule_CreateInitialized(PyModuleDef*, int apiver); +// Export for '_curses' shared extension +PyAPI_FUNC(int) _PyArg_ParseStack( + PyObject *const *args, + Py_ssize_t nargs, + const char *format, + ...); + +extern int _PyArg_UnpackStack( + PyObject *const *args, + Py_ssize_t nargs, + const char *name, + Py_ssize_t min, + Py_ssize_t max, + ...); + +// Export for '_heapq' shared extension +PyAPI_FUNC(void) _PyArg_BadArgument( + const char *fname, + const char *displayname, + const char *expected, + PyObject *arg); + +// --- _PyArg_Parser API --------------------------------------------------- + +typedef struct _PyArg_Parser { + const char *format; + const char * const *keywords; + const char *fname; + const char *custom_msg; + _PyOnceFlag once; /* atomic one-time initialization flag */ + int is_kwtuple_owned; /* does this parser own the kwtuple object? */ + int pos; /* number of positional-only arguments */ + int min; /* minimal number of arguments */ + int max; /* maximal number of positional arguments */ + PyObject *kwtuple; /* tuple of keyword parameter names */ + struct _PyArg_Parser *next; +} _PyArg_Parser; + +// Export for '_testclinic' shared extension +PyAPI_FUNC(int) _PyArg_ParseTupleAndKeywordsFast(PyObject *, PyObject *, + struct _PyArg_Parser *, ...); + +// Export for '_dbm' shared extension +PyAPI_FUNC(int) _PyArg_ParseStackAndKeywords( + PyObject *const *args, + Py_ssize_t nargs, + PyObject *kwnames, + struct _PyArg_Parser *, + ...); + +// Export for 'math' shared extension +PyAPI_FUNC(PyObject * const *) _PyArg_UnpackKeywords( + PyObject *const *args, + Py_ssize_t nargs, + PyObject *kwargs, + PyObject *kwnames, + struct _PyArg_Parser *parser, + int minpos, + int maxpos, + int minkw, + PyObject **buf); +#define _PyArg_UnpackKeywords(args, nargs, kwargs, kwnames, parser, minpos, maxpos, minkw, buf) \ + (((minkw) == 0 && (kwargs) == NULL && (kwnames) == NULL && \ + (minpos) <= (nargs) && (nargs) <= (maxpos) && (args) != NULL) ? (args) : \ + _PyArg_UnpackKeywords((args), (nargs), (kwargs), (kwnames), (parser), \ + (minpos), (maxpos), (minkw), (buf))) + +// Export for '_testclinic' shared extension +PyAPI_FUNC(PyObject * const *) _PyArg_UnpackKeywordsWithVararg( + PyObject *const *args, Py_ssize_t nargs, + PyObject *kwargs, PyObject *kwnames, + struct _PyArg_Parser *parser, + int minpos, int maxpos, int minkw, + int vararg, PyObject **buf); + #ifdef __cplusplus } #endif diff --git a/Include/internal/pycore_object.h b/Include/internal/pycore_object.h index 76b3cd69cbf5a7..f413b8451e5ab4 100644 --- a/Include/internal/pycore_object.h +++ b/Include/internal/pycore_object.h @@ -10,9 +10,9 @@ extern "C" { #include #include "pycore_gc.h" // _PyObject_GC_IS_TRACKED() +#include "pycore_emscripten_trampoline.h" // _PyCFunction_TrampolineCall() #include "pycore_interp.h" // PyInterpreterState.gc #include "pycore_pystate.h" // _PyInterpreterState_GET() -#include "pycore_runtime.h" // _PyRuntime /* Check if an object is consistent. For example, ensure that the reference counter is greater than or equal to 1, and ensure that ob_type is not NULL. @@ -32,6 +32,17 @@ extern void _PyDebugAllocatorStats(FILE *out, const char *block_name, extern void _PyObject_DebugTypeStats(FILE *out); +#ifdef Py_TRACE_REFS +// Forget a reference registered by _Py_NewReference(). Function called by +// _Py_Dealloc(). +// +// On a free list, the function can be used before modifying an object to +// remove the object from traced objects. Then _Py_NewReference() or +// _Py_NewReferenceNoTotal() should be called again on the object to trace +// it again. +extern void _Py_ForgetReference(PyObject *); +#endif + // Export for shared _testinternalcapi extension PyAPI_FUNC(int) _PyObject_IsFreed(PyObject *); @@ -43,19 +54,26 @@ PyAPI_FUNC(int) _PyObject_IsFreed(PyObject *); Furthermore, we can't use designated initializers in Extensions since these are not supported pre-C++20. Thus, keeping an internal copy here is the most backwards compatible solution */ +#if defined(Py_GIL_DISABLED) +#define _PyObject_HEAD_INIT(type) \ + { \ + .ob_ref_local = _Py_IMMORTAL_REFCNT_LOCAL, \ + .ob_type = (type) \ + } +#else #define _PyObject_HEAD_INIT(type) \ { \ - _PyObject_EXTRA_INIT \ .ob_refcnt = _Py_IMMORTAL_REFCNT, \ .ob_type = (type) \ - }, + } +#endif #define _PyVarObject_HEAD_INIT(type, size) \ { \ - .ob_base = _PyObject_HEAD_INIT(type) \ + .ob_base = _PyObject_HEAD_INIT(type), \ .ob_size = size \ - }, + } -PyAPI_FUNC(void) _Py_NO_RETURN _Py_FatalRefcountErrorFunc( +extern void _Py_NO_RETURN _Py_FatalRefcountErrorFunc( const char *func, const char *message); @@ -85,24 +103,63 @@ static inline void _Py_RefcntAdd(PyObject* op, Py_ssize_t n) #ifdef Py_REF_DEBUG _Py_AddRefTotal(_PyInterpreterState_GET(), n); #endif +#if !defined(Py_GIL_DISABLED) op->ob_refcnt += n; +#else + if (_Py_IsOwnedByCurrentThread(op)) { + uint32_t local = op->ob_ref_local; + Py_ssize_t refcnt = (Py_ssize_t)local + n; +# if PY_SSIZE_T_MAX > UINT32_MAX + if (refcnt > (Py_ssize_t)UINT32_MAX) { + // Make the object immortal if the 32-bit local reference count + // would overflow. + refcnt = _Py_IMMORTAL_REFCNT_LOCAL; + } +# endif + _Py_atomic_store_uint32_relaxed(&op->ob_ref_local, (uint32_t)refcnt); + } + else { + _Py_atomic_add_ssize(&op->ob_ref_shared, (n << _Py_REF_SHARED_SHIFT)); + } +#endif } #define _Py_RefcntAdd(op, n) _Py_RefcntAdd(_PyObject_CAST(op), n) static inline void _Py_SetImmortal(PyObject *op) { if (op) { +#ifdef Py_GIL_DISABLED + op->ob_tid = _Py_UNOWNED_TID; + op->ob_ref_local = _Py_IMMORTAL_REFCNT_LOCAL; + op->ob_ref_shared = 0; +#else op->ob_refcnt = _Py_IMMORTAL_REFCNT; +#endif } } #define _Py_SetImmortal(op) _Py_SetImmortal(_PyObject_CAST(op)) +// Makes an immortal object mortal again with the specified refcnt. Should only +// be used during runtime finalization. +static inline void _Py_SetMortal(PyObject *op, Py_ssize_t refcnt) +{ + if (op) { + assert(_Py_IsImmortal(op)); +#ifdef Py_GIL_DISABLED + op->ob_tid = _Py_UNOWNED_TID; + op->ob_ref_local = 0; + op->ob_ref_shared = _Py_REF_SHARED(refcnt, _Py_REF_MERGED); +#else + op->ob_refcnt = refcnt; +#endif + } +} + /* _Py_ClearImmortal() should only be used during runtime finalization. */ static inline void _Py_ClearImmortal(PyObject *op) { if (op) { - assert(op->ob_refcnt == _Py_IMMORTAL_REFCNT); - op->ob_refcnt = 1; + _Py_SetMortal(op, 1); Py_DECREF(op); } } @@ -112,6 +169,7 @@ static inline void _Py_ClearImmortal(PyObject *op) op = NULL; \ } while (0) +#if !defined(Py_GIL_DISABLED) static inline void _Py_DECREF_SPECIALIZED(PyObject *op, const destructor destruct) { @@ -151,6 +209,37 @@ _Py_DECREF_NO_DEALLOC(PyObject *op) #endif } +#else +// TODO: implement Py_DECREF specializations for Py_GIL_DISABLED build +static inline void +_Py_DECREF_SPECIALIZED(PyObject *op, const destructor destruct) +{ + Py_DECREF(op); +} + +static inline void +_Py_DECREF_NO_DEALLOC(PyObject *op) +{ + Py_DECREF(op); +} + +static inline int +_Py_REF_IS_MERGED(Py_ssize_t ob_ref_shared) +{ + return (ob_ref_shared & _Py_REF_SHARED_FLAG_MASK) == _Py_REF_MERGED; +} + +static inline int +_Py_REF_IS_QUEUED(Py_ssize_t ob_ref_shared) +{ + return (ob_ref_shared & _Py_REF_SHARED_FLAG_MASK) == _Py_REF_QUEUED; +} + +// Merge the local and shared reference count fields and add `extra` to the +// refcount when merging. +Py_ssize_t _Py_ExplicitMergeRefcount(PyObject *op, Py_ssize_t extra); +#endif // !defined(Py_GIL_DISABLED) + #ifdef Py_REF_DEBUG # undef _Py_DEC_REFTOTAL #endif @@ -173,6 +262,9 @@ _PyType_HasFeature(PyTypeObject *type, unsigned long feature) { extern void _PyType_InitCache(PyInterpreterState *interp); +extern PyStatus _PyObject_InitState(PyInterpreterState *interp); +extern void _PyObject_FiniState(PyInterpreterState *interp); +extern bool _PyRefchain_IsTraced(PyInterpreterState *interp, PyObject *obj); /* Inline functions trading binary compatibility for speed: _PyObject_Init() is the fast version of PyObject_Init(), and @@ -291,7 +383,7 @@ extern void _PyDebug_PrintTotalRefs(void); #endif #ifdef Py_TRACE_REFS -extern void _Py_AddToAllObjects(PyObject *op, int force); +extern void _Py_AddToAllObjects(PyObject *op); extern void _Py_PrintReferences(PyInterpreterState *, FILE *); extern void _Py_PrintReferenceAddresses(PyInterpreterState *, FILE *); #endif @@ -380,7 +472,7 @@ extern PyObject *_PyType_NewManagedObject(PyTypeObject *type); extern PyTypeObject* _PyType_CalculateMetaclass(PyTypeObject *, PyObject *); extern PyObject* _PyType_GetDocFromInternalDoc(const char *, const char *); -extern PyObject* _PyType_GetTextSignatureFromInternalDoc(const char *, const char *); +extern PyObject* _PyType_GetTextSignatureFromInternalDoc(const char *, const char *, int); extern int _PyObject_InitializeDict(PyObject *obj); int _PyObject_InitInlineValues(PyObject *obj, PyTypeObject *tp); @@ -442,6 +534,10 @@ extern int _PyObject_IsAbstract(PyObject *); extern int _PyObject_GetMethod(PyObject *obj, PyObject *name, PyObject **method); extern PyObject* _PyObject_NextNotImplemented(PyObject *); +// Pickle support. +// Export for '_datetime' shared extension +PyAPI_FUNC(PyObject*) _PyObject_GetState(PyObject *); + /* C function call trampolines to mitigate bad function pointer casts. * * Typical native ABIs ignore additional arguments or fill in missing @@ -469,13 +565,11 @@ extern PyObject* _PyCFunctionWithKeywords_TrampolineCall( (meth)((self), (args), (kw)) #endif // __EMSCRIPTEN__ && PY_CALL_TRAMPOLINE -// Export for '_pickle' shared extension +// Export these 2 symbols for '_pickle' shared extension PyAPI_DATA(PyTypeObject) _PyNone_Type; -// Export for '_pickle' shared extension PyAPI_DATA(PyTypeObject) _PyNotImplemented_Type; // Maps Py_LT to Py_GT, ..., Py_GE to Py_LE. -// Defined in Objects/object.c. // Export for the stable ABI. PyAPI_DATA(int) _Py_SwappedOp[]; diff --git a/Include/internal/pycore_object_state.h b/Include/internal/pycore_object_state.h index 65feb5af969f8b..9eac27b1a9a4e3 100644 --- a/Include/internal/pycore_object_state.h +++ b/Include/internal/pycore_object_state.h @@ -8,6 +8,8 @@ extern "C" { # error "this header requires Py_BUILD_CORE define" #endif +#include "pycore_hashtable.h" // _Py_hashtable_t + struct _py_object_runtime_state { #ifdef Py_REF_DEBUG Py_ssize_t interpreter_leaks; @@ -20,11 +22,10 @@ struct _py_object_state { Py_ssize_t reftotal; #endif #ifdef Py_TRACE_REFS - /* Head of circular doubly-linked list of all objects. These are linked - * together via the _ob_prev and _ob_next members of a PyObject, which - * exist only in a Py_TRACE_REFS build. - */ - PyObject refchain; + // Hash table storing all objects. The key is the object pointer + // (PyObject*) and the value is always the number 1 (as uintptr_t). + // See _PyRefchain_IsTraced() and _PyRefchain_Trace() functions. + _Py_hashtable_t *refchain; #endif int _not_used; }; diff --git a/Include/internal/pycore_obmalloc.h b/Include/internal/pycore_obmalloc.h index ca2a0419b4f038..17572dba65487d 100644 --- a/Include/internal/pycore_obmalloc.h +++ b/Include/internal/pycore_obmalloc.h @@ -665,7 +665,9 @@ struct _obmalloc_global_state { struct _obmalloc_state { struct _obmalloc_pools pools; struct _obmalloc_mgmt mgmt; +#if WITH_PYMALLOC_RADIX_TREE struct _obmalloc_usage usage; +#endif }; @@ -687,7 +689,7 @@ extern void _PyInterpreterState_FinalizeAllocatedBlocks(PyInterpreterState *); #ifdef WITH_PYMALLOC -// Export the symbol for the 3rd party guppy3 project +// Export the symbol for the 3rd party 'guppy3' project PyAPI_FUNC(int) _PyObject_DebugMallocStats(FILE *out); #endif diff --git a/Include/internal/pycore_opcode.h b/Include/internal/pycore_opcode.h deleted file mode 100644 index aff09a2a926aec..00000000000000 --- a/Include/internal/pycore_opcode.h +++ /dev/null @@ -1,580 +0,0 @@ -// Auto-generated by Tools/build/generate_opcode_h.py from Lib/opcode.py - -#ifndef Py_INTERNAL_OPCODE_H -#define Py_INTERNAL_OPCODE_H -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef Py_BUILD_CORE -# error "this header requires Py_BUILD_CORE define" -#endif - -#include "opcode.h" - -extern const uint8_t _PyOpcode_Caches[256]; - -extern const uint8_t _PyOpcode_Deopt[256]; - -#ifdef NEED_OPCODE_TABLES - -const uint8_t _PyOpcode_Caches[256] = { - [LOAD_GLOBAL] = 4, - [BINARY_OP] = 1, - [UNPACK_SEQUENCE] = 1, - [COMPARE_OP] = 1, - [BINARY_SUBSCR] = 1, - [FOR_ITER] = 1, - [LOAD_SUPER_ATTR] = 1, - [LOAD_ATTR] = 9, - [STORE_ATTR] = 4, - [CALL] = 3, - [STORE_SUBSCR] = 1, - [SEND] = 1, - [JUMP_BACKWARD] = 1, - [TO_BOOL] = 3, -}; - -const uint8_t _PyOpcode_Deopt[256] = { - [BEFORE_ASYNC_WITH] = BEFORE_ASYNC_WITH, - [BEFORE_WITH] = BEFORE_WITH, - [BINARY_OP] = BINARY_OP, - [BINARY_OP_ADD_FLOAT] = BINARY_OP, - [BINARY_OP_ADD_INT] = BINARY_OP, - [BINARY_OP_ADD_UNICODE] = BINARY_OP, - [BINARY_OP_INPLACE_ADD_UNICODE] = BINARY_OP, - [BINARY_OP_MULTIPLY_FLOAT] = BINARY_OP, - [BINARY_OP_MULTIPLY_INT] = BINARY_OP, - [BINARY_OP_SUBTRACT_FLOAT] = BINARY_OP, - [BINARY_OP_SUBTRACT_INT] = BINARY_OP, - [BINARY_SLICE] = BINARY_SLICE, - [BINARY_SUBSCR] = BINARY_SUBSCR, - [BINARY_SUBSCR_DICT] = BINARY_SUBSCR, - [BINARY_SUBSCR_GETITEM] = BINARY_SUBSCR, - [BINARY_SUBSCR_LIST_INT] = BINARY_SUBSCR, - [BINARY_SUBSCR_TUPLE_INT] = BINARY_SUBSCR, - [BUILD_CONST_KEY_MAP] = BUILD_CONST_KEY_MAP, - [BUILD_LIST] = BUILD_LIST, - [BUILD_MAP] = BUILD_MAP, - [BUILD_SET] = BUILD_SET, - [BUILD_SLICE] = BUILD_SLICE, - [BUILD_STRING] = BUILD_STRING, - [BUILD_TUPLE] = BUILD_TUPLE, - [CACHE] = CACHE, - [CALL] = CALL, - [CALL_BOUND_METHOD_EXACT_ARGS] = CALL, - [CALL_BUILTIN_CLASS] = CALL, - [CALL_BUILTIN_FAST_WITH_KEYWORDS] = CALL, - [CALL_FUNCTION_EX] = CALL_FUNCTION_EX, - [CALL_INTRINSIC_1] = CALL_INTRINSIC_1, - [CALL_INTRINSIC_2] = CALL_INTRINSIC_2, - [CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS] = CALL, - [CALL_NO_KW_ALLOC_AND_ENTER_INIT] = CALL, - [CALL_NO_KW_BUILTIN_FAST] = CALL, - [CALL_NO_KW_BUILTIN_O] = CALL, - [CALL_NO_KW_ISINSTANCE] = CALL, - [CALL_NO_KW_LEN] = CALL, - [CALL_NO_KW_LIST_APPEND] = CALL, - [CALL_NO_KW_METHOD_DESCRIPTOR_FAST] = CALL, - [CALL_NO_KW_METHOD_DESCRIPTOR_NOARGS] = CALL, - [CALL_NO_KW_METHOD_DESCRIPTOR_O] = CALL, - [CALL_NO_KW_STR_1] = CALL, - [CALL_NO_KW_TUPLE_1] = CALL, - [CALL_NO_KW_TYPE_1] = CALL, - [CALL_PY_EXACT_ARGS] = CALL, - [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_FLOAT] = COMPARE_OP, - [COMPARE_OP_INT] = COMPARE_OP, - [COMPARE_OP_STR] = COMPARE_OP, - [CONTAINS_OP] = CONTAINS_OP, - [CONVERT_VALUE] = CONVERT_VALUE, - [COPY] = COPY, - [COPY_FREE_VARS] = COPY_FREE_VARS, - [DELETE_ATTR] = DELETE_ATTR, - [DELETE_DEREF] = DELETE_DEREF, - [DELETE_FAST] = DELETE_FAST, - [DELETE_GLOBAL] = DELETE_GLOBAL, - [DELETE_NAME] = DELETE_NAME, - [DELETE_SUBSCR] = DELETE_SUBSCR, - [DICT_MERGE] = DICT_MERGE, - [DICT_UPDATE] = DICT_UPDATE, - [END_ASYNC_FOR] = END_ASYNC_FOR, - [END_FOR] = END_FOR, - [END_SEND] = END_SEND, - [ENTER_EXECUTOR] = ENTER_EXECUTOR, - [EXIT_INIT_CHECK] = EXIT_INIT_CHECK, - [EXTENDED_ARG] = EXTENDED_ARG, - [FORMAT_SIMPLE] = FORMAT_SIMPLE, - [FORMAT_WITH_SPEC] = FORMAT_WITH_SPEC, - [FOR_ITER] = FOR_ITER, - [FOR_ITER_GEN] = FOR_ITER, - [FOR_ITER_LIST] = FOR_ITER, - [FOR_ITER_RANGE] = FOR_ITER, - [FOR_ITER_TUPLE] = FOR_ITER, - [GET_AITER] = GET_AITER, - [GET_ANEXT] = GET_ANEXT, - [GET_AWAITABLE] = GET_AWAITABLE, - [GET_ITER] = GET_ITER, - [GET_LEN] = GET_LEN, - [GET_YIELD_FROM_ITER] = GET_YIELD_FROM_ITER, - [IMPORT_FROM] = IMPORT_FROM, - [IMPORT_NAME] = IMPORT_NAME, - [INSTRUMENTED_CALL] = INSTRUMENTED_CALL, - [INSTRUMENTED_CALL_FUNCTION_EX] = INSTRUMENTED_CALL_FUNCTION_EX, - [INSTRUMENTED_END_FOR] = INSTRUMENTED_END_FOR, - [INSTRUMENTED_END_SEND] = INSTRUMENTED_END_SEND, - [INSTRUMENTED_FOR_ITER] = INSTRUMENTED_FOR_ITER, - [INSTRUMENTED_INSTRUCTION] = INSTRUMENTED_INSTRUCTION, - [INSTRUMENTED_JUMP_BACKWARD] = INSTRUMENTED_JUMP_BACKWARD, - [INSTRUMENTED_JUMP_FORWARD] = INSTRUMENTED_JUMP_FORWARD, - [INSTRUMENTED_LINE] = INSTRUMENTED_LINE, - [INSTRUMENTED_LOAD_SUPER_ATTR] = INSTRUMENTED_LOAD_SUPER_ATTR, - [INSTRUMENTED_POP_JUMP_IF_FALSE] = INSTRUMENTED_POP_JUMP_IF_FALSE, - [INSTRUMENTED_POP_JUMP_IF_NONE] = INSTRUMENTED_POP_JUMP_IF_NONE, - [INSTRUMENTED_POP_JUMP_IF_NOT_NONE] = INSTRUMENTED_POP_JUMP_IF_NOT_NONE, - [INSTRUMENTED_POP_JUMP_IF_TRUE] = INSTRUMENTED_POP_JUMP_IF_TRUE, - [INSTRUMENTED_RESUME] = INSTRUMENTED_RESUME, - [INSTRUMENTED_RETURN_CONST] = INSTRUMENTED_RETURN_CONST, - [INSTRUMENTED_RETURN_VALUE] = INSTRUMENTED_RETURN_VALUE, - [INSTRUMENTED_YIELD_VALUE] = INSTRUMENTED_YIELD_VALUE, - [INTERPRETER_EXIT] = INTERPRETER_EXIT, - [IS_OP] = IS_OP, - [JUMP_BACKWARD] = JUMP_BACKWARD, - [JUMP_BACKWARD_NO_INTERRUPT] = JUMP_BACKWARD_NO_INTERRUPT, - [JUMP_FORWARD] = JUMP_FORWARD, - [KW_NAMES] = KW_NAMES, - [LIST_APPEND] = LIST_APPEND, - [LIST_EXTEND] = LIST_EXTEND, - [LOAD_ASSERTION_ERROR] = LOAD_ASSERTION_ERROR, - [LOAD_ATTR] = 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, - [LOAD_ATTR_METHOD_WITH_VALUES] = LOAD_ATTR, - [LOAD_ATTR_MODULE] = LOAD_ATTR, - [LOAD_ATTR_NONDESCRIPTOR_NO_DICT] = LOAD_ATTR, - [LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES] = LOAD_ATTR, - [LOAD_ATTR_PROPERTY] = LOAD_ATTR, - [LOAD_ATTR_SLOT] = LOAD_ATTR, - [LOAD_ATTR_WITH_HINT] = LOAD_ATTR, - [LOAD_BUILD_CLASS] = LOAD_BUILD_CLASS, - [LOAD_CONST] = LOAD_CONST, - [LOAD_DEREF] = LOAD_DEREF, - [LOAD_FAST] = LOAD_FAST, - [LOAD_FAST_AND_CLEAR] = LOAD_FAST_AND_CLEAR, - [LOAD_FAST_CHECK] = LOAD_FAST_CHECK, - [LOAD_FAST_LOAD_FAST] = LOAD_FAST_LOAD_FAST, - [LOAD_FROM_DICT_OR_DEREF] = LOAD_FROM_DICT_OR_DEREF, - [LOAD_FROM_DICT_OR_GLOBALS] = LOAD_FROM_DICT_OR_GLOBALS, - [LOAD_GLOBAL] = LOAD_GLOBAL, - [LOAD_GLOBAL_BUILTIN] = LOAD_GLOBAL, - [LOAD_GLOBAL_MODULE] = LOAD_GLOBAL, - [LOAD_LOCALS] = LOAD_LOCALS, - [LOAD_NAME] = LOAD_NAME, - [LOAD_SUPER_ATTR] = LOAD_SUPER_ATTR, - [LOAD_SUPER_ATTR_ATTR] = LOAD_SUPER_ATTR, - [LOAD_SUPER_ATTR_METHOD] = LOAD_SUPER_ATTR, - [MAKE_CELL] = MAKE_CELL, - [MAKE_FUNCTION] = MAKE_FUNCTION, - [MAP_ADD] = MAP_ADD, - [MATCH_CLASS] = MATCH_CLASS, - [MATCH_KEYS] = MATCH_KEYS, - [MATCH_MAPPING] = MATCH_MAPPING, - [MATCH_SEQUENCE] = MATCH_SEQUENCE, - [NOP] = NOP, - [POP_EXCEPT] = POP_EXCEPT, - [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, - [PUSH_EXC_INFO] = PUSH_EXC_INFO, - [PUSH_NULL] = PUSH_NULL, - [RAISE_VARARGS] = RAISE_VARARGS, - [RERAISE] = RERAISE, - [RESERVED] = RESERVED, - [RESUME] = RESUME, - [RETURN_CONST] = RETURN_CONST, - [RETURN_GENERATOR] = RETURN_GENERATOR, - [RETURN_VALUE] = RETURN_VALUE, - [SEND] = SEND, - [SEND_GEN] = SEND, - [SETUP_ANNOTATIONS] = SETUP_ANNOTATIONS, - [SET_ADD] = SET_ADD, - [SET_FUNCTION_ATTRIBUTE] = SET_FUNCTION_ATTRIBUTE, - [SET_UPDATE] = SET_UPDATE, - [STORE_ATTR] = STORE_ATTR, - [STORE_ATTR_INSTANCE_VALUE] = STORE_ATTR, - [STORE_ATTR_SLOT] = STORE_ATTR, - [STORE_ATTR_WITH_HINT] = STORE_ATTR, - [STORE_DEREF] = STORE_DEREF, - [STORE_FAST] = STORE_FAST, - [STORE_FAST_LOAD_FAST] = STORE_FAST_LOAD_FAST, - [STORE_FAST_STORE_FAST] = STORE_FAST_STORE_FAST, - [STORE_GLOBAL] = STORE_GLOBAL, - [STORE_NAME] = STORE_NAME, - [STORE_SLICE] = STORE_SLICE, - [STORE_SUBSCR] = STORE_SUBSCR, - [STORE_SUBSCR_DICT] = STORE_SUBSCR, - [STORE_SUBSCR_LIST_INT] = STORE_SUBSCR, - [SWAP] = SWAP, - [TO_BOOL] = TO_BOOL, - [TO_BOOL_ALWAYS_TRUE] = TO_BOOL, - [TO_BOOL_BOOL] = TO_BOOL, - [TO_BOOL_INT] = TO_BOOL, - [TO_BOOL_LIST] = TO_BOOL, - [TO_BOOL_NONE] = TO_BOOL, - [TO_BOOL_STR] = TO_BOOL, - [UNARY_INVERT] = UNARY_INVERT, - [UNARY_NEGATIVE] = UNARY_NEGATIVE, - [UNARY_NOT] = UNARY_NOT, - [UNPACK_EX] = UNPACK_EX, - [UNPACK_SEQUENCE] = UNPACK_SEQUENCE, - [UNPACK_SEQUENCE_LIST] = UNPACK_SEQUENCE, - [UNPACK_SEQUENCE_TUPLE] = UNPACK_SEQUENCE, - [UNPACK_SEQUENCE_TWO_TUPLE] = UNPACK_SEQUENCE, - [WITH_EXCEPT_START] = WITH_EXCEPT_START, - [YIELD_VALUE] = YIELD_VALUE, -}; -#endif // NEED_OPCODE_TABLES - - -extern const char *const _PyOpcode_OpName[268]; - -#ifdef NEED_OPCODE_TABLES -const char *const _PyOpcode_OpName[268] = { - [CACHE] = "CACHE", - [POP_TOP] = "POP_TOP", - [PUSH_NULL] = "PUSH_NULL", - [INTERPRETER_EXIT] = "INTERPRETER_EXIT", - [END_FOR] = "END_FOR", - [END_SEND] = "END_SEND", - [TO_BOOL] = "TO_BOOL", - [TO_BOOL_ALWAYS_TRUE] = "TO_BOOL_ALWAYS_TRUE", - [TO_BOOL_BOOL] = "TO_BOOL_BOOL", - [NOP] = "NOP", - [TO_BOOL_INT] = "TO_BOOL_INT", - [UNARY_NEGATIVE] = "UNARY_NEGATIVE", - [UNARY_NOT] = "UNARY_NOT", - [TO_BOOL_LIST] = "TO_BOOL_LIST", - [TO_BOOL_NONE] = "TO_BOOL_NONE", - [UNARY_INVERT] = "UNARY_INVERT", - [EXIT_INIT_CHECK] = "EXIT_INIT_CHECK", - [RESERVED] = "RESERVED", - [TO_BOOL_STR] = "TO_BOOL_STR", - [BINARY_OP_MULTIPLY_INT] = "BINARY_OP_MULTIPLY_INT", - [BINARY_OP_ADD_INT] = "BINARY_OP_ADD_INT", - [BINARY_OP_SUBTRACT_INT] = "BINARY_OP_SUBTRACT_INT", - [BINARY_OP_MULTIPLY_FLOAT] = "BINARY_OP_MULTIPLY_FLOAT", - [BINARY_OP_ADD_FLOAT] = "BINARY_OP_ADD_FLOAT", - [MAKE_FUNCTION] = "MAKE_FUNCTION", - [BINARY_SUBSCR] = "BINARY_SUBSCR", - [BINARY_SLICE] = "BINARY_SLICE", - [STORE_SLICE] = "STORE_SLICE", - [BINARY_OP_SUBTRACT_FLOAT] = "BINARY_OP_SUBTRACT_FLOAT", - [BINARY_OP_ADD_UNICODE] = "BINARY_OP_ADD_UNICODE", - [GET_LEN] = "GET_LEN", - [MATCH_MAPPING] = "MATCH_MAPPING", - [MATCH_SEQUENCE] = "MATCH_SEQUENCE", - [MATCH_KEYS] = "MATCH_KEYS", - [BINARY_OP_INPLACE_ADD_UNICODE] = "BINARY_OP_INPLACE_ADD_UNICODE", - [PUSH_EXC_INFO] = "PUSH_EXC_INFO", - [CHECK_EXC_MATCH] = "CHECK_EXC_MATCH", - [CHECK_EG_MATCH] = "CHECK_EG_MATCH", - [BINARY_SUBSCR_DICT] = "BINARY_SUBSCR_DICT", - [BINARY_SUBSCR_GETITEM] = "BINARY_SUBSCR_GETITEM", - [FORMAT_SIMPLE] = "FORMAT_SIMPLE", - [FORMAT_WITH_SPEC] = "FORMAT_WITH_SPEC", - [BINARY_SUBSCR_LIST_INT] = "BINARY_SUBSCR_LIST_INT", - [BINARY_SUBSCR_TUPLE_INT] = "BINARY_SUBSCR_TUPLE_INT", - [STORE_SUBSCR_DICT] = "STORE_SUBSCR_DICT", - [STORE_SUBSCR_LIST_INT] = "STORE_SUBSCR_LIST_INT", - [SEND_GEN] = "SEND_GEN", - [UNPACK_SEQUENCE_TWO_TUPLE] = "UNPACK_SEQUENCE_TWO_TUPLE", - [UNPACK_SEQUENCE_TUPLE] = "UNPACK_SEQUENCE_TUPLE", - [WITH_EXCEPT_START] = "WITH_EXCEPT_START", - [GET_AITER] = "GET_AITER", - [GET_ANEXT] = "GET_ANEXT", - [BEFORE_ASYNC_WITH] = "BEFORE_ASYNC_WITH", - [BEFORE_WITH] = "BEFORE_WITH", - [END_ASYNC_FOR] = "END_ASYNC_FOR", - [CLEANUP_THROW] = "CLEANUP_THROW", - [UNPACK_SEQUENCE_LIST] = "UNPACK_SEQUENCE_LIST", - [STORE_ATTR_INSTANCE_VALUE] = "STORE_ATTR_INSTANCE_VALUE", - [STORE_ATTR_SLOT] = "STORE_ATTR_SLOT", - [STORE_ATTR_WITH_HINT] = "STORE_ATTR_WITH_HINT", - [STORE_SUBSCR] = "STORE_SUBSCR", - [DELETE_SUBSCR] = "DELETE_SUBSCR", - [LOAD_GLOBAL_MODULE] = "LOAD_GLOBAL_MODULE", - [LOAD_GLOBAL_BUILTIN] = "LOAD_GLOBAL_BUILTIN", - [LOAD_SUPER_ATTR_ATTR] = "LOAD_SUPER_ATTR_ATTR", - [LOAD_SUPER_ATTR_METHOD] = "LOAD_SUPER_ATTR_METHOD", - [LOAD_ATTR_INSTANCE_VALUE] = "LOAD_ATTR_INSTANCE_VALUE", - [LOAD_ATTR_MODULE] = "LOAD_ATTR_MODULE", - [GET_ITER] = "GET_ITER", - [GET_YIELD_FROM_ITER] = "GET_YIELD_FROM_ITER", - [LOAD_ATTR_WITH_HINT] = "LOAD_ATTR_WITH_HINT", - [LOAD_BUILD_CLASS] = "LOAD_BUILD_CLASS", - [LOAD_ATTR_SLOT] = "LOAD_ATTR_SLOT", - [LOAD_ATTR_CLASS] = "LOAD_ATTR_CLASS", - [LOAD_ASSERTION_ERROR] = "LOAD_ASSERTION_ERROR", - [RETURN_GENERATOR] = "RETURN_GENERATOR", - [LOAD_ATTR_PROPERTY] = "LOAD_ATTR_PROPERTY", - [LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN] = "LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN", - [LOAD_ATTR_METHOD_WITH_VALUES] = "LOAD_ATTR_METHOD_WITH_VALUES", - [LOAD_ATTR_METHOD_NO_DICT] = "LOAD_ATTR_METHOD_NO_DICT", - [LOAD_ATTR_METHOD_LAZY_DICT] = "LOAD_ATTR_METHOD_LAZY_DICT", - [LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES] = "LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES", - [LOAD_ATTR_NONDESCRIPTOR_NO_DICT] = "LOAD_ATTR_NONDESCRIPTOR_NO_DICT", - [RETURN_VALUE] = "RETURN_VALUE", - [COMPARE_OP_FLOAT] = "COMPARE_OP_FLOAT", - [SETUP_ANNOTATIONS] = "SETUP_ANNOTATIONS", - [COMPARE_OP_INT] = "COMPARE_OP_INT", - [LOAD_LOCALS] = "LOAD_LOCALS", - [COMPARE_OP_STR] = "COMPARE_OP_STR", - [POP_EXCEPT] = "POP_EXCEPT", - [STORE_NAME] = "STORE_NAME", - [DELETE_NAME] = "DELETE_NAME", - [UNPACK_SEQUENCE] = "UNPACK_SEQUENCE", - [FOR_ITER] = "FOR_ITER", - [UNPACK_EX] = "UNPACK_EX", - [STORE_ATTR] = "STORE_ATTR", - [DELETE_ATTR] = "DELETE_ATTR", - [STORE_GLOBAL] = "STORE_GLOBAL", - [DELETE_GLOBAL] = "DELETE_GLOBAL", - [SWAP] = "SWAP", - [LOAD_CONST] = "LOAD_CONST", - [LOAD_NAME] = "LOAD_NAME", - [BUILD_TUPLE] = "BUILD_TUPLE", - [BUILD_LIST] = "BUILD_LIST", - [BUILD_SET] = "BUILD_SET", - [BUILD_MAP] = "BUILD_MAP", - [LOAD_ATTR] = "LOAD_ATTR", - [COMPARE_OP] = "COMPARE_OP", - [IMPORT_NAME] = "IMPORT_NAME", - [IMPORT_FROM] = "IMPORT_FROM", - [JUMP_FORWARD] = "JUMP_FORWARD", - [FOR_ITER_LIST] = "FOR_ITER_LIST", - [FOR_ITER_TUPLE] = "FOR_ITER_TUPLE", - [FOR_ITER_RANGE] = "FOR_ITER_RANGE", - [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", - [RETURN_CONST] = "RETURN_CONST", - [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_IF_NOT_NONE] = "POP_JUMP_IF_NOT_NONE", - [POP_JUMP_IF_NONE] = "POP_JUMP_IF_NONE", - [RAISE_VARARGS] = "RAISE_VARARGS", - [GET_AWAITABLE] = "GET_AWAITABLE", - [FOR_ITER_GEN] = "FOR_ITER_GEN", - [BUILD_SLICE] = "BUILD_SLICE", - [JUMP_BACKWARD_NO_INTERRUPT] = "JUMP_BACKWARD_NO_INTERRUPT", - [MAKE_CELL] = "MAKE_CELL", - [CALL_BOUND_METHOD_EXACT_ARGS] = "CALL_BOUND_METHOD_EXACT_ARGS", - [LOAD_DEREF] = "LOAD_DEREF", - [STORE_DEREF] = "STORE_DEREF", - [DELETE_DEREF] = "DELETE_DEREF", - [JUMP_BACKWARD] = "JUMP_BACKWARD", - [LOAD_SUPER_ATTR] = "LOAD_SUPER_ATTR", - [CALL_FUNCTION_EX] = "CALL_FUNCTION_EX", - [LOAD_FAST_AND_CLEAR] = "LOAD_FAST_AND_CLEAR", - [EXTENDED_ARG] = "EXTENDED_ARG", - [LIST_APPEND] = "LIST_APPEND", - [SET_ADD] = "SET_ADD", - [MAP_ADD] = "MAP_ADD", - [CALL_PY_EXACT_ARGS] = "CALL_PY_EXACT_ARGS", - [COPY_FREE_VARS] = "COPY_FREE_VARS", - [YIELD_VALUE] = "YIELD_VALUE", - [RESUME] = "RESUME", - [MATCH_CLASS] = "MATCH_CLASS", - [CALL_PY_WITH_DEFAULTS] = "CALL_PY_WITH_DEFAULTS", - [CALL_NO_KW_TYPE_1] = "CALL_NO_KW_TYPE_1", - [CALL_NO_KW_STR_1] = "CALL_NO_KW_STR_1", - [BUILD_CONST_KEY_MAP] = "BUILD_CONST_KEY_MAP", - [BUILD_STRING] = "BUILD_STRING", - [CONVERT_VALUE] = "CONVERT_VALUE", - [CALL_NO_KW_TUPLE_1] = "CALL_NO_KW_TUPLE_1", - [CALL_BUILTIN_CLASS] = "CALL_BUILTIN_CLASS", - [CALL_NO_KW_BUILTIN_O] = "CALL_NO_KW_BUILTIN_O", - [LIST_EXTEND] = "LIST_EXTEND", - [SET_UPDATE] = "SET_UPDATE", - [DICT_MERGE] = "DICT_MERGE", - [DICT_UPDATE] = "DICT_UPDATE", - [CALL_NO_KW_BUILTIN_FAST] = "CALL_NO_KW_BUILTIN_FAST", - [CALL_BUILTIN_FAST_WITH_KEYWORDS] = "CALL_BUILTIN_FAST_WITH_KEYWORDS", - [LOAD_FAST_LOAD_FAST] = "LOAD_FAST_LOAD_FAST", - [STORE_FAST_LOAD_FAST] = "STORE_FAST_LOAD_FAST", - [STORE_FAST_STORE_FAST] = "STORE_FAST_STORE_FAST", - [CALL] = "CALL", - [KW_NAMES] = "KW_NAMES", - [CALL_INTRINSIC_1] = "CALL_INTRINSIC_1", - [CALL_INTRINSIC_2] = "CALL_INTRINSIC_2", - [LOAD_FROM_DICT_OR_GLOBALS] = "LOAD_FROM_DICT_OR_GLOBALS", - [LOAD_FROM_DICT_OR_DEREF] = "LOAD_FROM_DICT_OR_DEREF", - [SET_FUNCTION_ATTRIBUTE] = "SET_FUNCTION_ATTRIBUTE", - [CALL_NO_KW_LEN] = "CALL_NO_KW_LEN", - [CALL_NO_KW_ISINSTANCE] = "CALL_NO_KW_ISINSTANCE", - [CALL_NO_KW_LIST_APPEND] = "CALL_NO_KW_LIST_APPEND", - [CALL_NO_KW_METHOD_DESCRIPTOR_O] = "CALL_NO_KW_METHOD_DESCRIPTOR_O", - [CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS] = "CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS", - [CALL_NO_KW_METHOD_DESCRIPTOR_NOARGS] = "CALL_NO_KW_METHOD_DESCRIPTOR_NOARGS", - [CALL_NO_KW_METHOD_DESCRIPTOR_FAST] = "CALL_NO_KW_METHOD_DESCRIPTOR_FAST", - [CALL_NO_KW_ALLOC_AND_ENTER_INIT] = "CALL_NO_KW_ALLOC_AND_ENTER_INIT", - [186] = "<186>", - [187] = "<187>", - [188] = "<188>", - [189] = "<189>", - [190] = "<190>", - [191] = "<191>", - [192] = "<192>", - [193] = "<193>", - [194] = "<194>", - [195] = "<195>", - [196] = "<196>", - [197] = "<197>", - [198] = "<198>", - [199] = "<199>", - [200] = "<200>", - [201] = "<201>", - [202] = "<202>", - [203] = "<203>", - [204] = "<204>", - [205] = "<205>", - [206] = "<206>", - [207] = "<207>", - [208] = "<208>", - [209] = "<209>", - [210] = "<210>", - [211] = "<211>", - [212] = "<212>", - [213] = "<213>", - [214] = "<214>", - [215] = "<215>", - [216] = "<216>", - [217] = "<217>", - [218] = "<218>", - [219] = "<219>", - [220] = "<220>", - [221] = "<221>", - [222] = "<222>", - [223] = "<223>", - [224] = "<224>", - [225] = "<225>", - [226] = "<226>", - [227] = "<227>", - [228] = "<228>", - [229] = "<229>", - [ENTER_EXECUTOR] = "ENTER_EXECUTOR", - [231] = "<231>", - [232] = "<232>", - [233] = "<233>", - [234] = "<234>", - [235] = "<235>", - [236] = "<236>", - [INSTRUMENTED_LOAD_SUPER_ATTR] = "INSTRUMENTED_LOAD_SUPER_ATTR", - [INSTRUMENTED_POP_JUMP_IF_NONE] = "INSTRUMENTED_POP_JUMP_IF_NONE", - [INSTRUMENTED_POP_JUMP_IF_NOT_NONE] = "INSTRUMENTED_POP_JUMP_IF_NOT_NONE", - [INSTRUMENTED_RESUME] = "INSTRUMENTED_RESUME", - [INSTRUMENTED_CALL] = "INSTRUMENTED_CALL", - [INSTRUMENTED_RETURN_VALUE] = "INSTRUMENTED_RETURN_VALUE", - [INSTRUMENTED_YIELD_VALUE] = "INSTRUMENTED_YIELD_VALUE", - [INSTRUMENTED_CALL_FUNCTION_EX] = "INSTRUMENTED_CALL_FUNCTION_EX", - [INSTRUMENTED_JUMP_FORWARD] = "INSTRUMENTED_JUMP_FORWARD", - [INSTRUMENTED_JUMP_BACKWARD] = "INSTRUMENTED_JUMP_BACKWARD", - [INSTRUMENTED_RETURN_CONST] = "INSTRUMENTED_RETURN_CONST", - [INSTRUMENTED_FOR_ITER] = "INSTRUMENTED_FOR_ITER", - [INSTRUMENTED_POP_JUMP_IF_FALSE] = "INSTRUMENTED_POP_JUMP_IF_FALSE", - [INSTRUMENTED_POP_JUMP_IF_TRUE] = "INSTRUMENTED_POP_JUMP_IF_TRUE", - [INSTRUMENTED_END_FOR] = "INSTRUMENTED_END_FOR", - [INSTRUMENTED_END_SEND] = "INSTRUMENTED_END_SEND", - [INSTRUMENTED_INSTRUCTION] = "INSTRUMENTED_INSTRUCTION", - [INSTRUMENTED_LINE] = "INSTRUMENTED_LINE", - [255] = "<255>", - [SETUP_FINALLY] = "SETUP_FINALLY", - [SETUP_CLEANUP] = "SETUP_CLEANUP", - [SETUP_WITH] = "SETUP_WITH", - [POP_BLOCK] = "POP_BLOCK", - [JUMP] = "JUMP", - [JUMP_NO_INTERRUPT] = "JUMP_NO_INTERRUPT", - [LOAD_METHOD] = "LOAD_METHOD", - [LOAD_SUPER_METHOD] = "LOAD_SUPER_METHOD", - [LOAD_ZERO_SUPER_METHOD] = "LOAD_ZERO_SUPER_METHOD", - [LOAD_ZERO_SUPER_ATTR] = "LOAD_ZERO_SUPER_ATTR", - [STORE_FAST_MAYBE_NULL] = "STORE_FAST_MAYBE_NULL", - [LOAD_CLOSURE] = "LOAD_CLOSURE", -}; -#endif // NEED_OPCODE_TABLES - -#define EXTRA_CASES \ - case 186: \ - case 187: \ - case 188: \ - case 189: \ - case 190: \ - case 191: \ - case 192: \ - case 193: \ - case 194: \ - case 195: \ - case 196: \ - case 197: \ - case 198: \ - case 199: \ - case 200: \ - case 201: \ - case 202: \ - case 203: \ - case 204: \ - case 205: \ - case 206: \ - case 207: \ - case 208: \ - case 209: \ - case 210: \ - case 211: \ - case 212: \ - case 213: \ - case 214: \ - case 215: \ - case 216: \ - case 217: \ - case 218: \ - case 219: \ - case 220: \ - case 221: \ - case 222: \ - case 223: \ - case 224: \ - case 225: \ - case 226: \ - case 227: \ - case 228: \ - case 229: \ - case 231: \ - case 232: \ - case 233: \ - case 234: \ - case 235: \ - case 236: \ - case 255: \ - ; - -#ifdef __cplusplus -} -#endif -#endif // !Py_INTERNAL_OPCODE_H diff --git a/Include/internal/pycore_opcode_metadata.h b/Include/internal/pycore_opcode_metadata.h index 1cab6c984f3ace..a9d698da25a1db 100644 --- a/Include/internal/pycore_opcode_metadata.h +++ b/Include/internal/pycore_opcode_metadata.h @@ -1,9 +1,20 @@ -// This file is generated by Tools/cases_generator/generate_cases.py +// This file is generated by Tools/cases_generator/opcode_metadata_generator.py // from: // Python/bytecodes.c // Do not edit! -#include +#ifndef Py_CORE_OPCODE_METADATA_H +#define Py_CORE_OPCODE_METADATA_H +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef Py_BUILD_CORE +# error "this header requires Py_BUILD_CORE define" +#endif + +#include // bool +#include "opcode_ids.h" #define IS_PSEUDO_INSTR(OP) ( \ @@ -21,944 +32,871 @@ ((OP) == POP_BLOCK) || \ 0) -#define EXIT_TRACE 300 -#define SAVE_IP 301 -#define _GUARD_BOTH_INT 302 -#define _BINARY_OP_MULTIPLY_INT 303 -#define _BINARY_OP_ADD_INT 304 -#define _BINARY_OP_SUBTRACT_INT 305 -#define _GUARD_BOTH_FLOAT 306 -#define _BINARY_OP_MULTIPLY_FLOAT 307 -#define _BINARY_OP_ADD_FLOAT 308 -#define _BINARY_OP_SUBTRACT_FLOAT 309 -#define _GUARD_BOTH_UNICODE 310 -#define _BINARY_OP_ADD_UNICODE 311 -#define _LOAD_LOCALS 312 -#define _LOAD_FROM_DICT_OR_GLOBALS 313 -#define _GUARD_GLOBALS_VERSION 314 -#define _GUARD_BUILTINS_VERSION 315 -#define _LOAD_GLOBAL_MODULE 316 -#define _LOAD_GLOBAL_BUILTINS 317 -#define _GUARD_TYPE_VERSION 318 -#define _CHECK_MANAGED_OBJECT_HAS_VALUES 319 -#define _LOAD_ATTR_INSTANCE_VALUE 320 -#define IS_NONE 321 -#define _ITER_CHECK_LIST 322 -#define _IS_ITER_EXHAUSTED_LIST 323 -#define _ITER_NEXT_LIST 324 -#define _ITER_CHECK_TUPLE 325 -#define _IS_ITER_EXHAUSTED_TUPLE 326 -#define _ITER_NEXT_TUPLE 327 -#define _ITER_CHECK_RANGE 328 -#define _IS_ITER_EXHAUSTED_RANGE 329 -#define _ITER_NEXT_RANGE 330 -#define _POP_JUMP_IF_FALSE 331 -#define _POP_JUMP_IF_TRUE 332 -#define JUMP_TO_TOP 333 - -#ifndef NEED_OPCODE_METADATA -extern int _PyOpcode_num_popped(int opcode, int oparg, bool jump); -#else -int -_PyOpcode_num_popped(int opcode, int oparg, bool jump) { +#include "pycore_uop_ids.h" +extern int _PyOpcode_num_popped(int opcode, int oparg); +#ifdef NEED_OPCODE_METADATA +int _PyOpcode_num_popped(int opcode, int oparg) { switch(opcode) { - case NOP: - return 0; - case RESUME: - return 0; - case INSTRUMENTED_RESUME: - return 0; - case LOAD_CLOSURE: - return 0; - case LOAD_FAST_CHECK: - return 0; - case LOAD_FAST: - return 0; - case LOAD_FAST_AND_CLEAR: - return 0; - case LOAD_FAST_LOAD_FAST: - return 0; - case LOAD_CONST: - return 0; - case STORE_FAST: - return 1; - case STORE_FAST_MAYBE_NULL: + case BEFORE_ASYNC_WITH: return 1; - case STORE_FAST_LOAD_FAST: + case BEFORE_WITH: return 1; - case STORE_FAST_STORE_FAST: + case BINARY_OP: return 2; - case POP_TOP: - return 1; - case PUSH_NULL: - return 0; - case END_FOR: + case BINARY_OP_ADD_FLOAT: return 2; - case INSTRUMENTED_END_FOR: + case BINARY_OP_ADD_INT: return 2; - case END_SEND: + case BINARY_OP_ADD_UNICODE: return 2; - case INSTRUMENTED_END_SEND: + case BINARY_OP_INPLACE_ADD_UNICODE: + return 2; + case BINARY_OP_MULTIPLY_FLOAT: return 2; - case UNARY_NEGATIVE: - return 1; - case UNARY_NOT: - return 1; - case TO_BOOL: - return 1; - case TO_BOOL_BOOL: - return 1; - case TO_BOOL_INT: - return 1; - case TO_BOOL_LIST: - return 1; - case TO_BOOL_NONE: - return 1; - case TO_BOOL_STR: - return 1; - case TO_BOOL_ALWAYS_TRUE: - return 1; - case UNARY_INVERT: - return 1; case BINARY_OP_MULTIPLY_INT: return 2; - case BINARY_OP_ADD_INT: + case BINARY_OP_SUBTRACT_FLOAT: return 2; case BINARY_OP_SUBTRACT_INT: return 2; - case BINARY_OP_MULTIPLY_FLOAT: + case BINARY_SLICE: + return 3; + case BINARY_SUBSCR: return 2; - case BINARY_OP_ADD_FLOAT: + case BINARY_SUBSCR_DICT: return 2; - case BINARY_OP_SUBTRACT_FLOAT: + case BINARY_SUBSCR_GETITEM: return 2; - case BINARY_OP_ADD_UNICODE: + case BINARY_SUBSCR_LIST_INT: return 2; - case BINARY_OP_INPLACE_ADD_UNICODE: + case BINARY_SUBSCR_STR_INT: return 2; - case BINARY_SUBSCR: + case BINARY_SUBSCR_TUPLE_INT: return 2; - case BINARY_SLICE: + case BUILD_CONST_KEY_MAP: + return 1 + oparg; + case BUILD_LIST: + return oparg; + case BUILD_MAP: + return oparg*2; + case BUILD_SET: + return oparg; + case BUILD_SLICE: + return 2 + ((oparg == 3) ? 1 : 0); + case BUILD_STRING: + return oparg; + case BUILD_TUPLE: + return oparg; + case CACHE: + return 0; + case CALL: + return 2 + oparg; + case CALL_ALLOC_AND_ENTER_INIT: + return 2 + oparg; + case CALL_BOUND_METHOD_EXACT_ARGS: + return 2 + oparg; + case CALL_BUILTIN_CLASS: + return 2 + oparg; + case CALL_BUILTIN_FAST: + return 2 + oparg; + case CALL_BUILTIN_FAST_WITH_KEYWORDS: + return 2 + oparg; + case CALL_BUILTIN_O: + return 2 + oparg; + case CALL_FUNCTION_EX: + return 3 + (oparg & 1); + case CALL_INTRINSIC_1: + return 1; + case CALL_INTRINSIC_2: + return 2; + case CALL_ISINSTANCE: + return 2 + oparg; + case CALL_KW: + return 3 + oparg; + case CALL_LEN: + return 2 + oparg; + case CALL_LIST_APPEND: + return 2 + oparg; + case CALL_METHOD_DESCRIPTOR_FAST: + return 2 + oparg; + case CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS: + return 2 + oparg; + case CALL_METHOD_DESCRIPTOR_NOARGS: + return 2 + oparg; + case CALL_METHOD_DESCRIPTOR_O: + return 2 + oparg; + case CALL_PY_EXACT_ARGS: + return 2 + oparg; + case CALL_PY_WITH_DEFAULTS: + return 2 + oparg; + case CALL_STR_1: + return 2 + oparg; + case CALL_TUPLE_1: + return 2 + oparg; + case CALL_TYPE_1: + return 2 + oparg; + case CHECK_EG_MATCH: + return 2; + case CHECK_EXC_MATCH: + return 2; + case CLEANUP_THROW: return 3; - case STORE_SLICE: - return 4; - case BINARY_SUBSCR_LIST_INT: + case COMPARE_OP: return 2; - case BINARY_SUBSCR_TUPLE_INT: + case COMPARE_OP_FLOAT: return 2; - case BINARY_SUBSCR_DICT: + case COMPARE_OP_INT: return 2; - case BINARY_SUBSCR_GETITEM: + case COMPARE_OP_STR: return 2; - case LIST_APPEND: - return (oparg-1) + 2; - case SET_ADD: - return (oparg-1) + 2; - case STORE_SUBSCR: - return 3; - case STORE_SUBSCR_LIST_INT: - return 3; - case STORE_SUBSCR_DICT: - return 3; + case CONTAINS_OP: + return 2; + case CONVERT_VALUE: + return 1; + case COPY: + return 1 + (oparg-1); + case COPY_FREE_VARS: + return 0; + case DELETE_ATTR: + return 1; + case DELETE_DEREF: + return 0; + case DELETE_FAST: + return 0; + case DELETE_GLOBAL: + return 0; + case DELETE_NAME: + return 0; case DELETE_SUBSCR: return 2; - case CALL_INTRINSIC_1: + case DICT_MERGE: + return 5 + (oparg - 1); + case DICT_UPDATE: + return 2 + (oparg - 1); + case END_ASYNC_FOR: + return 2; + case END_FOR: + return 2; + case END_SEND: + return 2; + case ENTER_EXECUTOR: + return 0; + case EXIT_INIT_CHECK: return 1; - case CALL_INTRINSIC_2: + case EXTENDED_ARG: + return 0; + case FORMAT_SIMPLE: + return 1; + case FORMAT_WITH_SPEC: return 2; - case RAISE_VARARGS: - return oparg; - case INTERPRETER_EXIT: + case FOR_ITER: return 1; - case RETURN_VALUE: + case FOR_ITER_GEN: return 1; - case INSTRUMENTED_RETURN_VALUE: + case FOR_ITER_LIST: + return 1; + case FOR_ITER_RANGE: + return 1; + case FOR_ITER_TUPLE: return 1; - case RETURN_CONST: - return 0; - case INSTRUMENTED_RETURN_CONST: - return 0; case GET_AITER: return 1; case GET_ANEXT: return 1; case GET_AWAITABLE: return 1; - case SEND: - return 2; - case SEND_GEN: - return 2; - case INSTRUMENTED_YIELD_VALUE: + case GET_ITER: return 1; - case YIELD_VALUE: + case GET_LEN: return 1; - case POP_EXCEPT: + case GET_YIELD_FROM_ITER: return 1; - case RERAISE: - return oparg + 1; - case END_ASYNC_FOR: + case IMPORT_FROM: + return 1; + case IMPORT_NAME: return 2; - case CLEANUP_THROW: - return 3; - case LOAD_ASSERTION_ERROR: + case INSTRUMENTED_CALL: return 0; - case LOAD_BUILD_CLASS: + case INSTRUMENTED_CALL_FUNCTION_EX: return 0; - case STORE_NAME: - return 1; - case DELETE_NAME: + case INSTRUMENTED_CALL_KW: return 0; - case UNPACK_SEQUENCE: - return 1; - case UNPACK_SEQUENCE_TWO_TUPLE: - return 1; - case UNPACK_SEQUENCE_TUPLE: - return 1; - case UNPACK_SEQUENCE_LIST: - return 1; - case UNPACK_EX: - return 1; - case STORE_ATTR: + case INSTRUMENTED_END_FOR: return 2; - case DELETE_ATTR: - return 1; - case STORE_GLOBAL: - return 1; - case DELETE_GLOBAL: + case INSTRUMENTED_END_SEND: + return 2; + case INSTRUMENTED_FOR_ITER: return 0; - case LOAD_LOCALS: + case INSTRUMENTED_INSTRUCTION: return 0; - case LOAD_NAME: + case INSTRUMENTED_JUMP_BACKWARD: return 0; - case LOAD_FROM_DICT_OR_GLOBALS: - return 1; - case LOAD_GLOBAL: + case INSTRUMENTED_JUMP_FORWARD: return 0; - case LOAD_GLOBAL_MODULE: + case INSTRUMENTED_LOAD_SUPER_ATTR: + return 3; + case INSTRUMENTED_POP_JUMP_IF_FALSE: return 0; - case LOAD_GLOBAL_BUILTIN: + case INSTRUMENTED_POP_JUMP_IF_NONE: return 0; - case DELETE_FAST: + case INSTRUMENTED_POP_JUMP_IF_NOT_NONE: return 0; - case MAKE_CELL: + case INSTRUMENTED_POP_JUMP_IF_TRUE: return 0; - case DELETE_DEREF: + case INSTRUMENTED_RESUME: return 0; - case LOAD_FROM_DICT_OR_DEREF: - return 1; - case LOAD_DEREF: + case INSTRUMENTED_RETURN_CONST: return 0; - case STORE_DEREF: + case INSTRUMENTED_RETURN_VALUE: return 1; - case COPY_FREE_VARS: - return 0; - case BUILD_STRING: - return oparg; - case BUILD_TUPLE: - return oparg; - case BUILD_LIST: - return oparg; - case LIST_EXTEND: - return (oparg-1) + 2; - case SET_UPDATE: - return (oparg-1) + 2; - case BUILD_SET: - return oparg; - case BUILD_MAP: - return oparg*2; - case SETUP_ANNOTATIONS: - return 0; - case BUILD_CONST_KEY_MAP: - return oparg + 1; - case DICT_UPDATE: + case INSTRUMENTED_YIELD_VALUE: return 1; - case DICT_MERGE: + case INTERPRETER_EXIT: return 1; - case MAP_ADD: + case IS_OP: return 2; - case INSTRUMENTED_LOAD_SUPER_ATTR: - return 3; - case LOAD_SUPER_ATTR: - return 3; - case LOAD_SUPER_METHOD: - return 3; - case LOAD_ZERO_SUPER_METHOD: - return 3; - case LOAD_ZERO_SUPER_ATTR: - return 3; - case LOAD_SUPER_ATTR_ATTR: - return 3; - case LOAD_SUPER_ATTR_METHOD: - return 3; + case JUMP_BACKWARD: + return 0; + case JUMP_BACKWARD_NO_INTERRUPT: + return 0; + case JUMP_FORWARD: + return 0; + case LIST_APPEND: + return 2 + (oparg-1); + case LIST_EXTEND: + return 2 + (oparg-1); + case LOAD_ASSERTION_ERROR: + return 0; case LOAD_ATTR: return 1; - case LOAD_METHOD: + case LOAD_ATTR_CLASS: + return 1; + case LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN: return 1; case LOAD_ATTR_INSTANCE_VALUE: return 1; - case LOAD_ATTR_MODULE: + case LOAD_ATTR_METHOD_LAZY_DICT: return 1; - case LOAD_ATTR_WITH_HINT: + case LOAD_ATTR_METHOD_NO_DICT: return 1; - case LOAD_ATTR_SLOT: + case LOAD_ATTR_METHOD_WITH_VALUES: return 1; - case LOAD_ATTR_CLASS: + case LOAD_ATTR_MODULE: + return 1; + case LOAD_ATTR_NONDESCRIPTOR_NO_DICT: + return 1; + case LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES: return 1; case LOAD_ATTR_PROPERTY: return 1; - case LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN: + case LOAD_ATTR_SLOT: return 1; - case STORE_ATTR_INSTANCE_VALUE: - return 2; - case STORE_ATTR_WITH_HINT: - return 2; - case STORE_ATTR_SLOT: - return 2; - case COMPARE_OP: - return 2; - case COMPARE_OP_FLOAT: - return 2; - case COMPARE_OP_INT: - return 2; - case COMPARE_OP_STR: - return 2; - case IS_OP: - return 2; - case CONTAINS_OP: - return 2; - case CHECK_EG_MATCH: - return 2; - case CHECK_EXC_MATCH: - return 2; - case IMPORT_NAME: - return 2; - case IMPORT_FROM: + case LOAD_ATTR_WITH_HINT: return 1; - case JUMP_FORWARD: + case LOAD_BUILD_CLASS: return 0; - case JUMP_BACKWARD: + case LOAD_CONST: return 0; - case JUMP: + case LOAD_DEREF: return 0; - case JUMP_NO_INTERRUPT: + case LOAD_FAST: return 0; - case ENTER_EXECUTOR: + case LOAD_FAST_AND_CLEAR: return 0; - case POP_JUMP_IF_FALSE: - return 1; - case POP_JUMP_IF_TRUE: - return 1; - case POP_JUMP_IF_NONE: + case LOAD_FAST_CHECK: + return 0; + case LOAD_FAST_LOAD_FAST: + return 0; + case LOAD_FROM_DICT_OR_DEREF: return 1; - case POP_JUMP_IF_NOT_NONE: + case LOAD_FROM_DICT_OR_GLOBALS: return 1; - case JUMP_BACKWARD_NO_INTERRUPT: + case LOAD_GLOBAL: return 0; - case GET_LEN: + case LOAD_GLOBAL_BUILTIN: + return 0; + case LOAD_GLOBAL_MODULE: + return 0; + case LOAD_LOCALS: + return 0; + case LOAD_NAME: + return 0; + case LOAD_SUPER_ATTR: + return 3; + case LOAD_SUPER_ATTR_ATTR: + return 3; + case LOAD_SUPER_ATTR_METHOD: + return 3; + case MAKE_CELL: + return 0; + case MAKE_FUNCTION: return 1; + case MAP_ADD: + return 3 + (oparg - 1); case MATCH_CLASS: return 3; - case MATCH_MAPPING: - return 1; - case MATCH_SEQUENCE: - return 1; case MATCH_KEYS: return 2; - case GET_ITER: - return 1; - case GET_YIELD_FROM_ITER: + case MATCH_MAPPING: return 1; - case FOR_ITER: + case MATCH_SEQUENCE: return 1; - case INSTRUMENTED_FOR_ITER: + case NOP: return 0; - case FOR_ITER_LIST: + case POP_EXCEPT: return 1; - case FOR_ITER_TUPLE: + case POP_JUMP_IF_FALSE: return 1; - case FOR_ITER_RANGE: + case POP_JUMP_IF_NONE: return 1; - case FOR_ITER_GEN: + case POP_JUMP_IF_NOT_NONE: return 1; - case BEFORE_ASYNC_WITH: + case POP_JUMP_IF_TRUE: return 1; - case BEFORE_WITH: + case POP_TOP: return 1; - case WITH_EXCEPT_START: - return 4; - case SETUP_FINALLY: + case PUSH_EXC_INFO: + return 1; + case PUSH_NULL: return 0; - case SETUP_CLEANUP: + case RAISE_VARARGS: + return oparg; + case RERAISE: + return 1 + oparg; + case RESERVED: return 0; - case SETUP_WITH: + case RESUME: return 0; - case POP_BLOCK: + case RESUME_CHECK: return 0; - case PUSH_EXC_INFO: - return 1; - case LOAD_ATTR_METHOD_WITH_VALUES: - return 1; - case LOAD_ATTR_METHOD_NO_DICT: - return 1; - case LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES: - return 1; - case LOAD_ATTR_NONDESCRIPTOR_NO_DICT: - return 1; - case LOAD_ATTR_METHOD_LAZY_DICT: - return 1; - case KW_NAMES: + case RETURN_CONST: return 0; - case INSTRUMENTED_CALL: + case RETURN_GENERATOR: return 0; - case CALL: - return oparg + 2; - case CALL_BOUND_METHOD_EXACT_ARGS: - return oparg + 2; - case CALL_PY_EXACT_ARGS: - return oparg + 2; - case CALL_PY_WITH_DEFAULTS: - return oparg + 2; - case CALL_NO_KW_TYPE_1: - return oparg + 2; - case CALL_NO_KW_STR_1: - return oparg + 2; - case CALL_NO_KW_TUPLE_1: - return oparg + 2; - case CALL_NO_KW_ALLOC_AND_ENTER_INIT: - return oparg + 2; - case EXIT_INIT_CHECK: + case RETURN_VALUE: return 1; - case CALL_BUILTIN_CLASS: - return oparg + 2; - case CALL_NO_KW_BUILTIN_O: - return oparg + 2; - case CALL_NO_KW_BUILTIN_FAST: - return oparg + 2; - case CALL_BUILTIN_FAST_WITH_KEYWORDS: - return oparg + 2; - case CALL_NO_KW_LEN: - return oparg + 2; - case CALL_NO_KW_ISINSTANCE: - return oparg + 2; - case CALL_NO_KW_LIST_APPEND: - return oparg + 2; - case CALL_NO_KW_METHOD_DESCRIPTOR_O: - return oparg + 2; - case CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS: - return oparg + 2; - case CALL_NO_KW_METHOD_DESCRIPTOR_NOARGS: - return oparg + 2; - case CALL_NO_KW_METHOD_DESCRIPTOR_FAST: - return oparg + 2; - case INSTRUMENTED_CALL_FUNCTION_EX: + case SEND: + return 2; + case SEND_GEN: + return 2; + case SETUP_ANNOTATIONS: return 0; - case CALL_FUNCTION_EX: - return ((oparg & 1) ? 1 : 0) + 3; - case MAKE_FUNCTION: - return 1; + case SET_ADD: + return 2 + (oparg-1); case SET_FUNCTION_ATTRIBUTE: return 2; - case RETURN_GENERATOR: - return 0; - case BUILD_SLICE: - return ((oparg == 3) ? 1 : 0) + 2; - case CONVERT_VALUE: + case SET_UPDATE: + return 2 + (oparg-1); + case STORE_ATTR: + return 2; + case STORE_ATTR_INSTANCE_VALUE: + return 2; + case STORE_ATTR_SLOT: + return 2; + case STORE_ATTR_WITH_HINT: + return 2; + case STORE_DEREF: return 1; - case FORMAT_SIMPLE: + case STORE_FAST: return 1; - case FORMAT_WITH_SPEC: - return 2; - case COPY: - return (oparg-1) + 1; - case BINARY_OP: + case STORE_FAST_LOAD_FAST: + return 1; + case STORE_FAST_STORE_FAST: return 2; + case STORE_GLOBAL: + return 1; + case STORE_NAME: + return 1; + case STORE_SLICE: + return 4; + case STORE_SUBSCR: + return 3; + case STORE_SUBSCR_DICT: + return 3; + case STORE_SUBSCR_LIST_INT: + return 3; case SWAP: - return (oparg-2) + 2; - case INSTRUMENTED_INSTRUCTION: - return 0; - case INSTRUMENTED_JUMP_FORWARD: - return 0; - case INSTRUMENTED_JUMP_BACKWARD: - return 0; - case INSTRUMENTED_POP_JUMP_IF_TRUE: - return 0; - case INSTRUMENTED_POP_JUMP_IF_FALSE: - return 0; - case INSTRUMENTED_POP_JUMP_IF_NONE: - return 0; - case INSTRUMENTED_POP_JUMP_IF_NOT_NONE: - return 0; - case EXTENDED_ARG: - return 0; - case CACHE: - return 0; - case RESERVED: - return 0; + return 2 + (oparg-2); + case TO_BOOL: + return 1; + case TO_BOOL_ALWAYS_TRUE: + return 1; + case TO_BOOL_BOOL: + return 1; + case TO_BOOL_INT: + return 1; + case TO_BOOL_LIST: + return 1; + case TO_BOOL_NONE: + return 1; + case TO_BOOL_STR: + return 1; + case UNARY_INVERT: + return 1; + case UNARY_NEGATIVE: + return 1; + case UNARY_NOT: + return 1; + case UNPACK_EX: + return 1; + case UNPACK_SEQUENCE: + return 1; + case UNPACK_SEQUENCE_LIST: + return 1; + case UNPACK_SEQUENCE_TUPLE: + return 1; + case UNPACK_SEQUENCE_TWO_TUPLE: + return 1; + case WITH_EXCEPT_START: + return 4; + case YIELD_VALUE: + return 1; default: return -1; } } + #endif -#ifndef NEED_OPCODE_METADATA -extern int _PyOpcode_num_pushed(int opcode, int oparg, bool jump); -#else -int -_PyOpcode_num_pushed(int opcode, int oparg, bool jump) { +extern int _PyOpcode_num_pushed(int opcode, int oparg); +#ifdef NEED_OPCODE_METADATA +int _PyOpcode_num_pushed(int opcode, int oparg) { switch(opcode) { - case NOP: - return 0; - case RESUME: - return 0; - case INSTRUMENTED_RESUME: + case BEFORE_ASYNC_WITH: + return 2; + case BEFORE_WITH: + return 2; + case BINARY_OP: + return 1; + case BINARY_OP_ADD_FLOAT: + return 1; + case BINARY_OP_ADD_INT: + return 1; + case BINARY_OP_ADD_UNICODE: + return 1; + case BINARY_OP_INPLACE_ADD_UNICODE: return 0; - case LOAD_CLOSURE: + case BINARY_OP_MULTIPLY_FLOAT: return 1; - case LOAD_FAST_CHECK: + case BINARY_OP_MULTIPLY_INT: return 1; - case LOAD_FAST: + case BINARY_OP_SUBTRACT_FLOAT: return 1; - case LOAD_FAST_AND_CLEAR: + case BINARY_OP_SUBTRACT_INT: return 1; - case LOAD_FAST_LOAD_FAST: - return 2; - case LOAD_CONST: + case BINARY_SLICE: return 1; - case STORE_FAST: - return 0; - case STORE_FAST_MAYBE_NULL: - return 0; - case STORE_FAST_LOAD_FAST: + case BINARY_SUBSCR: return 1; - case STORE_FAST_STORE_FAST: - return 0; - case POP_TOP: - return 0; - case PUSH_NULL: + case BINARY_SUBSCR_DICT: return 1; - case END_FOR: - return 0; - case INSTRUMENTED_END_FOR: + case BINARY_SUBSCR_GETITEM: + return 1; + case BINARY_SUBSCR_LIST_INT: + return 1; + case BINARY_SUBSCR_STR_INT: + return 1; + case BINARY_SUBSCR_TUPLE_INT: + return 1; + case BUILD_CONST_KEY_MAP: + return 1; + case BUILD_LIST: + return 1; + case BUILD_MAP: + return 1; + case BUILD_SET: + return 1; + case BUILD_SLICE: + return 1; + case BUILD_STRING: + return 1; + case BUILD_TUPLE: + return 1; + case CACHE: return 0; - case END_SEND: + case CALL: return 1; - case INSTRUMENTED_END_SEND: + case CALL_ALLOC_AND_ENTER_INIT: return 1; - case UNARY_NEGATIVE: + case CALL_BOUND_METHOD_EXACT_ARGS: + return ((0) ? 1 : 0); + case CALL_BUILTIN_CLASS: return 1; - case UNARY_NOT: + case CALL_BUILTIN_FAST: return 1; - case TO_BOOL: + case CALL_BUILTIN_FAST_WITH_KEYWORDS: return 1; - case TO_BOOL_BOOL: + case CALL_BUILTIN_O: return 1; - case TO_BOOL_INT: + case CALL_FUNCTION_EX: return 1; - case TO_BOOL_LIST: + case CALL_INTRINSIC_1: return 1; - case TO_BOOL_NONE: + case CALL_INTRINSIC_2: + return 1; + case CALL_ISINSTANCE: + return 1; + case CALL_KW: return 1; - case TO_BOOL_STR: + case CALL_LEN: return 1; - case TO_BOOL_ALWAYS_TRUE: + case CALL_LIST_APPEND: return 1; - case UNARY_INVERT: + case CALL_METHOD_DESCRIPTOR_FAST: return 1; - case BINARY_OP_MULTIPLY_INT: + case CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS: return 1; - case BINARY_OP_ADD_INT: + case CALL_METHOD_DESCRIPTOR_NOARGS: return 1; - case BINARY_OP_SUBTRACT_INT: + case CALL_METHOD_DESCRIPTOR_O: return 1; - case BINARY_OP_MULTIPLY_FLOAT: + case CALL_PY_EXACT_ARGS: + return ((0) ? 1 : 0); + case CALL_PY_WITH_DEFAULTS: return 1; - case BINARY_OP_ADD_FLOAT: + case CALL_STR_1: return 1; - case BINARY_OP_SUBTRACT_FLOAT: + case CALL_TUPLE_1: return 1; - case BINARY_OP_ADD_UNICODE: + case CALL_TYPE_1: return 1; - case BINARY_OP_INPLACE_ADD_UNICODE: - return 0; - case BINARY_SUBSCR: + case CHECK_EG_MATCH: + return 2; + case CHECK_EXC_MATCH: + return 2; + case CLEANUP_THROW: + return 2; + case COMPARE_OP: return 1; - case BINARY_SLICE: + case COMPARE_OP_FLOAT: return 1; - case STORE_SLICE: - return 0; - case BINARY_SUBSCR_LIST_INT: + case COMPARE_OP_INT: return 1; - case BINARY_SUBSCR_TUPLE_INT: + case COMPARE_OP_STR: return 1; - case BINARY_SUBSCR_DICT: + case CONTAINS_OP: return 1; - case BINARY_SUBSCR_GETITEM: + case CONVERT_VALUE: return 1; - case LIST_APPEND: - return (oparg-1) + 1; - case SET_ADD: - return (oparg-1) + 1; - case STORE_SUBSCR: + case COPY: + return 2 + (oparg-1); + case COPY_FREE_VARS: return 0; - case STORE_SUBSCR_LIST_INT: + case DELETE_ATTR: return 0; - case STORE_SUBSCR_DICT: + case DELETE_DEREF: return 0; - case DELETE_SUBSCR: + case DELETE_FAST: return 0; - case CALL_INTRINSIC_1: - return 1; - case CALL_INTRINSIC_2: - return 1; - case RAISE_VARARGS: + case DELETE_GLOBAL: return 0; - case INTERPRETER_EXIT: + case DELETE_NAME: return 0; - case RETURN_VALUE: + case DELETE_SUBSCR: return 0; - case INSTRUMENTED_RETURN_VALUE: + case DICT_MERGE: + return 4 + (oparg - 1); + case DICT_UPDATE: + return 1 + (oparg - 1); + case END_ASYNC_FOR: return 0; - case RETURN_CONST: + case END_FOR: return 0; - case INSTRUMENTED_RETURN_CONST: + case END_SEND: + return 1; + case ENTER_EXECUTOR: + return 0; + case EXIT_INIT_CHECK: return 0; + case EXTENDED_ARG: + return 0; + case FORMAT_SIMPLE: + return 1; + case FORMAT_WITH_SPEC: + return 1; + case FOR_ITER: + return 2; + case FOR_ITER_GEN: + return 2; + case FOR_ITER_LIST: + return 2; + case FOR_ITER_RANGE: + return 2; + case FOR_ITER_TUPLE: + return 2; case GET_AITER: return 1; case GET_ANEXT: return 2; case GET_AWAITABLE: return 1; - case SEND: - return 2; - case SEND_GEN: + case GET_ITER: + return 1; + case GET_LEN: return 2; - case INSTRUMENTED_YIELD_VALUE: + case GET_YIELD_FROM_ITER: return 1; - case YIELD_VALUE: + case IMPORT_FROM: + return 2; + case IMPORT_NAME: return 1; - case POP_EXCEPT: + case INSTRUMENTED_CALL: return 0; - case RERAISE: - return oparg; - case END_ASYNC_FOR: + case INSTRUMENTED_CALL_FUNCTION_EX: return 0; - case CLEANUP_THROW: - return 2; - case LOAD_ASSERTION_ERROR: - return 1; - case LOAD_BUILD_CLASS: + case INSTRUMENTED_CALL_KW: + return 0; + case INSTRUMENTED_END_FOR: + return 0; + case INSTRUMENTED_END_SEND: return 1; - case STORE_NAME: + case INSTRUMENTED_FOR_ITER: return 0; - case DELETE_NAME: + case INSTRUMENTED_INSTRUCTION: return 0; - case UNPACK_SEQUENCE: - return oparg; - case UNPACK_SEQUENCE_TWO_TUPLE: - return oparg; - case UNPACK_SEQUENCE_TUPLE: - return oparg; - case UNPACK_SEQUENCE_LIST: - return oparg; - case UNPACK_EX: - return (oparg & 0xFF) + (oparg >> 8) + 1; - case STORE_ATTR: + case INSTRUMENTED_JUMP_BACKWARD: return 0; - case DELETE_ATTR: + case INSTRUMENTED_JUMP_FORWARD: return 0; - case STORE_GLOBAL: + case INSTRUMENTED_LOAD_SUPER_ATTR: + return 1 + (oparg & 1); + case INSTRUMENTED_POP_JUMP_IF_FALSE: return 0; - case DELETE_GLOBAL: + case INSTRUMENTED_POP_JUMP_IF_NONE: return 0; - case LOAD_LOCALS: - return 1; - case LOAD_NAME: - return 1; - case LOAD_FROM_DICT_OR_GLOBALS: - return 1; - case LOAD_GLOBAL: - return ((oparg & 1) ? 1 : 0) + 1; - case LOAD_GLOBAL_MODULE: - return (oparg & 1 ? 1 : 0) + 1; - case LOAD_GLOBAL_BUILTIN: - return (oparg & 1 ? 1 : 0) + 1; - case DELETE_FAST: + case INSTRUMENTED_POP_JUMP_IF_NOT_NONE: return 0; - case MAKE_CELL: + case INSTRUMENTED_POP_JUMP_IF_TRUE: return 0; - case DELETE_DEREF: + case INSTRUMENTED_RESUME: return 0; - case LOAD_FROM_DICT_OR_DEREF: - return 1; - case LOAD_DEREF: - return 1; - case STORE_DEREF: + case INSTRUMENTED_RETURN_CONST: return 0; - case COPY_FREE_VARS: + case INSTRUMENTED_RETURN_VALUE: return 0; - case BUILD_STRING: - return 1; - case BUILD_TUPLE: - return 1; - case BUILD_LIST: - return 1; - case LIST_EXTEND: - return (oparg-1) + 1; - case SET_UPDATE: - return (oparg-1) + 1; - case BUILD_SET: - return 1; - case BUILD_MAP: + case INSTRUMENTED_YIELD_VALUE: return 1; - case SETUP_ANNOTATIONS: + case INTERPRETER_EXIT: return 0; - case BUILD_CONST_KEY_MAP: + case IS_OP: return 1; - case DICT_UPDATE: + case JUMP_BACKWARD: return 0; - case DICT_MERGE: + case JUMP_BACKWARD_NO_INTERRUPT: return 0; - case MAP_ADD: + case JUMP_FORWARD: return 0; - case INSTRUMENTED_LOAD_SUPER_ATTR: - return ((oparg & 1) ? 1 : 0) + 1; - case LOAD_SUPER_ATTR: - return ((oparg & 1) ? 1 : 0) + 1; - case LOAD_SUPER_METHOD: - return ((oparg & 1) ? 1 : 0) + 1; - case LOAD_ZERO_SUPER_METHOD: - return ((oparg & 1) ? 1 : 0) + 1; - case LOAD_ZERO_SUPER_ATTR: - return ((oparg & 1) ? 1 : 0) + 1; - case LOAD_SUPER_ATTR_ATTR: - return ((oparg & 1) ? 1 : 0) + 1; - case LOAD_SUPER_ATTR_METHOD: - return 2; + case LIST_APPEND: + return 1 + (oparg-1); + case LIST_EXTEND: + return 1 + (oparg-1); + case LOAD_ASSERTION_ERROR: + return 1; case LOAD_ATTR: - return ((oparg & 1) ? 1 : 0) + 1; - case LOAD_METHOD: - return ((oparg & 1) ? 1 : 0) + 1; + return 1 + (oparg & 1); + case LOAD_ATTR_CLASS: + return 1 + (oparg & 1); + case LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN: + return 1 + ((0) ? 1 : 0); case LOAD_ATTR_INSTANCE_VALUE: - return (oparg & 1 ? 1 : 0) + 1; + return 1 + (oparg & 1); + case LOAD_ATTR_METHOD_LAZY_DICT: + return 1 + ((1) ? 1 : 0); + case LOAD_ATTR_METHOD_NO_DICT: + return 1 + ((1) ? 1 : 0); + case LOAD_ATTR_METHOD_WITH_VALUES: + return 1 + ((1) ? 1 : 0); case LOAD_ATTR_MODULE: - return ((oparg & 1) ? 1 : 0) + 1; - case LOAD_ATTR_WITH_HINT: - return ((oparg & 1) ? 1 : 0) + 1; - case LOAD_ATTR_SLOT: - return ((oparg & 1) ? 1 : 0) + 1; - case LOAD_ATTR_CLASS: - return ((oparg & 1) ? 1 : 0) + 1; + return 1 + (oparg & 1); + case LOAD_ATTR_NONDESCRIPTOR_NO_DICT: + return 1 + ((0) ? 1 : 0); + case LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES: + return 1 + ((0) ? 1 : 0); case LOAD_ATTR_PROPERTY: - return ((oparg & 1) ? 1 : 0) + 1; - case LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN: - return ((oparg & 1) ? 1 : 0) + 1; - case STORE_ATTR_INSTANCE_VALUE: - return 0; - case STORE_ATTR_WITH_HINT: - return 0; - case STORE_ATTR_SLOT: - return 0; - case COMPARE_OP: + return 1 + ((0) ? 1 : 0); + case LOAD_ATTR_SLOT: + return 1 + (oparg & 1); + case LOAD_ATTR_WITH_HINT: + return 1 + (oparg & 1); + case LOAD_BUILD_CLASS: return 1; - case COMPARE_OP_FLOAT: + case LOAD_CONST: return 1; - case COMPARE_OP_INT: + case LOAD_DEREF: return 1; - case COMPARE_OP_STR: + case LOAD_FAST: return 1; - case IS_OP: + case LOAD_FAST_AND_CLEAR: return 1; - case CONTAINS_OP: + case LOAD_FAST_CHECK: return 1; - case CHECK_EG_MATCH: - return 2; - case CHECK_EXC_MATCH: + case LOAD_FAST_LOAD_FAST: return 2; - case IMPORT_NAME: + case LOAD_FROM_DICT_OR_DEREF: return 1; - case IMPORT_FROM: + case LOAD_FROM_DICT_OR_GLOBALS: + return 1; + case LOAD_GLOBAL: + return 1 + (oparg & 1); + case LOAD_GLOBAL_BUILTIN: + return 1 + (oparg & 1); + case LOAD_GLOBAL_MODULE: + return 1 + (oparg & 1); + case LOAD_LOCALS: + return 1; + case LOAD_NAME: + return 1; + case LOAD_SUPER_ATTR: + return 1 + (oparg & 1); + case LOAD_SUPER_ATTR_ATTR: + return 1 + ((0) ? 1 : 0); + case LOAD_SUPER_ATTR_METHOD: return 2; - case JUMP_FORWARD: - return 0; - case JUMP_BACKWARD: - return 0; - case JUMP: + case MAKE_CELL: return 0; - case JUMP_NO_INTERRUPT: + case MAKE_FUNCTION: + return 1; + case MAP_ADD: + return 1 + (oparg - 1); + case MATCH_CLASS: + return 1; + case MATCH_KEYS: + return 3; + case MATCH_MAPPING: + return 2; + case MATCH_SEQUENCE: + return 2; + case NOP: return 0; - case ENTER_EXECUTOR: + case POP_EXCEPT: return 0; case POP_JUMP_IF_FALSE: return 0; - case POP_JUMP_IF_TRUE: - return 0; case POP_JUMP_IF_NONE: return 0; case POP_JUMP_IF_NOT_NONE: return 0; - case JUMP_BACKWARD_NO_INTERRUPT: + case POP_JUMP_IF_TRUE: return 0; - case GET_LEN: - return 2; - case MATCH_CLASS: - return 1; - case MATCH_MAPPING: - return 2; - case MATCH_SEQUENCE: + case POP_TOP: + return 0; + case PUSH_EXC_INFO: return 2; - case MATCH_KEYS: - return 3; - case GET_ITER: - return 1; - case GET_YIELD_FROM_ITER: + case PUSH_NULL: return 1; - case FOR_ITER: - return 2; - case INSTRUMENTED_FOR_ITER: + case RAISE_VARARGS: return 0; - case FOR_ITER_LIST: - return 2; - case FOR_ITER_TUPLE: - return 2; - case FOR_ITER_RANGE: - return 2; - case FOR_ITER_GEN: - return 2; - case BEFORE_ASYNC_WITH: - return 2; - case BEFORE_WITH: - return 2; - case WITH_EXCEPT_START: - return 5; - case SETUP_FINALLY: + case RERAISE: + return oparg; + case RESERVED: return 0; - case SETUP_CLEANUP: + case RESUME: return 0; - case SETUP_WITH: + case RESUME_CHECK: return 0; - case POP_BLOCK: + case RETURN_CONST: return 0; - case PUSH_EXC_INFO: - return 2; - case LOAD_ATTR_METHOD_WITH_VALUES: + case RETURN_GENERATOR: + return 0; + case RETURN_VALUE: + return 0; + case SEND: return 2; - case LOAD_ATTR_METHOD_NO_DICT: + case SEND_GEN: return 2; - case LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES: - return 1; - case LOAD_ATTR_NONDESCRIPTOR_NO_DICT: + case SETUP_ANNOTATIONS: + return 0; + case SET_ADD: + return 1 + (oparg-1); + case SET_FUNCTION_ATTRIBUTE: return 1; - case LOAD_ATTR_METHOD_LAZY_DICT: - return 2; - case KW_NAMES: + case SET_UPDATE: + return 1 + (oparg-1); + case STORE_ATTR: return 0; - case INSTRUMENTED_CALL: + case STORE_ATTR_INSTANCE_VALUE: return 0; - case CALL: - return 1; - case CALL_BOUND_METHOD_EXACT_ARGS: - return 1; - case CALL_PY_EXACT_ARGS: - return 1; - case CALL_PY_WITH_DEFAULTS: - return 1; - case CALL_NO_KW_TYPE_1: - return 1; - case CALL_NO_KW_STR_1: - return 1; - case CALL_NO_KW_TUPLE_1: - return 1; - case CALL_NO_KW_ALLOC_AND_ENTER_INIT: - return 1; - case EXIT_INIT_CHECK: + case STORE_ATTR_SLOT: return 0; - case CALL_BUILTIN_CLASS: - return 1; - case CALL_NO_KW_BUILTIN_O: - return 1; - case CALL_NO_KW_BUILTIN_FAST: - return 1; - case CALL_BUILTIN_FAST_WITH_KEYWORDS: - return 1; - case CALL_NO_KW_LEN: - return 1; - case CALL_NO_KW_ISINSTANCE: - return 1; - case CALL_NO_KW_LIST_APPEND: - return 1; - case CALL_NO_KW_METHOD_DESCRIPTOR_O: + case STORE_ATTR_WITH_HINT: + return 0; + case STORE_DEREF: + return 0; + case STORE_FAST: + return 0; + case STORE_FAST_LOAD_FAST: return 1; - case CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS: + case STORE_FAST_STORE_FAST: + return 0; + case STORE_GLOBAL: + return 0; + case STORE_NAME: + return 0; + case STORE_SLICE: + return 0; + case STORE_SUBSCR: + return 0; + case STORE_SUBSCR_DICT: + return 0; + case STORE_SUBSCR_LIST_INT: + return 0; + case SWAP: + return 2 + (oparg-2); + case TO_BOOL: return 1; - case CALL_NO_KW_METHOD_DESCRIPTOR_NOARGS: + case TO_BOOL_ALWAYS_TRUE: return 1; - case CALL_NO_KW_METHOD_DESCRIPTOR_FAST: + case TO_BOOL_BOOL: return 1; - case INSTRUMENTED_CALL_FUNCTION_EX: - return 0; - case CALL_FUNCTION_EX: + case TO_BOOL_INT: return 1; - case MAKE_FUNCTION: + case TO_BOOL_LIST: return 1; - case SET_FUNCTION_ATTRIBUTE: + case TO_BOOL_NONE: return 1; - case RETURN_GENERATOR: - return 0; - case BUILD_SLICE: + case TO_BOOL_STR: return 1; - case CONVERT_VALUE: + case UNARY_INVERT: return 1; - case FORMAT_SIMPLE: + case UNARY_NEGATIVE: return 1; - case FORMAT_WITH_SPEC: + case UNARY_NOT: return 1; - case COPY: - return (oparg-1) + 2; - case BINARY_OP: + case UNPACK_EX: + return 1 + (oparg >> 8) + (oparg & 0xFF); + case UNPACK_SEQUENCE: + return oparg; + case UNPACK_SEQUENCE_LIST: + return oparg; + case UNPACK_SEQUENCE_TUPLE: + return oparg; + case UNPACK_SEQUENCE_TWO_TUPLE: + return oparg; + case WITH_EXCEPT_START: + return 5; + case YIELD_VALUE: return 1; - case SWAP: - return (oparg-2) + 2; - case INSTRUMENTED_INSTRUCTION: - return 0; - case INSTRUMENTED_JUMP_FORWARD: - return 0; - case INSTRUMENTED_JUMP_BACKWARD: - return 0; - case INSTRUMENTED_POP_JUMP_IF_TRUE: - return 0; - case INSTRUMENTED_POP_JUMP_IF_FALSE: - return 0; - case INSTRUMENTED_POP_JUMP_IF_NONE: - return 0; - case INSTRUMENTED_POP_JUMP_IF_NOT_NONE: - return 0; - case EXTENDED_ARG: - return 0; - case CACHE: - return 0; - case RESERVED: - return 0; default: return -1; } } + #endif enum InstructionFormat { - INSTR_FMT_IB, - INSTR_FMT_IBC, - INSTR_FMT_IBC00, - INSTR_FMT_IBC000, - INSTR_FMT_IBC00000000, - INSTR_FMT_IX, - INSTR_FMT_IXC, - INSTR_FMT_IXC0, - INSTR_FMT_IXC00, - INSTR_FMT_IXC000, + INSTR_FMT_IB = 1, + INSTR_FMT_IBC = 2, + INSTR_FMT_IBC00 = 3, + INSTR_FMT_IBC000 = 4, + INSTR_FMT_IBC00000000 = 5, + INSTR_FMT_IX = 6, + INSTR_FMT_IXC = 7, + INSTR_FMT_IXC00 = 8, + INSTR_FMT_IXC000 = 9, }; #define IS_VALID_OPCODE(OP) \ - (((OP) >= 0) && ((OP) < OPCODE_METADATA_SIZE) && \ + (((OP) >= 0) && ((OP) < 268) && \ (_PyOpcode_opcode_metadata[(OP)].valid_entry)) #define HAS_ARG_FLAG (1) @@ -967,23 +905,20 @@ enum InstructionFormat { #define HAS_JUMP_FLAG (8) #define HAS_FREE_FLAG (16) #define HAS_LOCAL_FLAG (32) +#define HAS_EVAL_BREAK_FLAG (64) +#define HAS_DEOPT_FLAG (128) +#define HAS_ERROR_FLAG (256) +#define HAS_ESCAPES_FLAG (512) #define OPCODE_HAS_ARG(OP) (_PyOpcode_opcode_metadata[OP].flags & (HAS_ARG_FLAG)) #define OPCODE_HAS_CONST(OP) (_PyOpcode_opcode_metadata[OP].flags & (HAS_CONST_FLAG)) #define OPCODE_HAS_NAME(OP) (_PyOpcode_opcode_metadata[OP].flags & (HAS_NAME_FLAG)) #define OPCODE_HAS_JUMP(OP) (_PyOpcode_opcode_metadata[OP].flags & (HAS_JUMP_FLAG)) #define OPCODE_HAS_FREE(OP) (_PyOpcode_opcode_metadata[OP].flags & (HAS_FREE_FLAG)) #define OPCODE_HAS_LOCAL(OP) (_PyOpcode_opcode_metadata[OP].flags & (HAS_LOCAL_FLAG)) - -struct opcode_metadata { - bool valid_entry; - enum InstructionFormat instr_format; - int flags; -}; - -struct opcode_macro_expansion { - int nuops; - struct { int16_t uop; int8_t size; int8_t offset; } uops[8]; -}; +#define OPCODE_HAS_EVAL_BREAK(OP) (_PyOpcode_opcode_metadata[OP].flags & (HAS_EVAL_BREAK_FLAG)) +#define OPCODE_HAS_DEOPT(OP) (_PyOpcode_opcode_metadata[OP].flags & (HAS_DEOPT_FLAG)) +#define OPCODE_HAS_ERROR(OP) (_PyOpcode_opcode_metadata[OP].flags & (HAS_ERROR_FLAG)) +#define OPCODE_HAS_ESCAPES(OP) (_PyOpcode_opcode_metadata[OP].flags & (HAS_ESCAPES_FLAG)) #define OPARG_FULL 0 #define OPARG_CACHE_1 1 @@ -991,400 +926,959 @@ struct opcode_macro_expansion { #define OPARG_CACHE_4 4 #define OPARG_TOP 5 #define OPARG_BOTTOM 6 +#define OPARG_SAVE_RETURN_OFFSET 7 +#define OPARG_REPLACED 9 -#define OPCODE_METADATA_FMT(OP) (_PyOpcode_opcode_metadata[(OP)].instr_format) -#define SAME_OPCODE_METADATA(OP1, OP2) \ - (OPCODE_METADATA_FMT(OP1) == OPCODE_METADATA_FMT(OP2)) - -#define OPCODE_METADATA_SIZE 512 -#define OPCODE_UOP_NAME_SIZE 512 -#define OPCODE_MACRO_EXPANSION_SIZE 256 +struct opcode_metadata { + uint8_t valid_entry; + int8_t instr_format; + int16_t flags; +}; -#ifndef NEED_OPCODE_METADATA -extern const struct opcode_metadata _PyOpcode_opcode_metadata[OPCODE_METADATA_SIZE]; -extern const struct opcode_macro_expansion _PyOpcode_macro_expansion[OPCODE_MACRO_EXPANSION_SIZE]; -extern const char * const _PyOpcode_uop_name[OPCODE_UOP_NAME_SIZE]; -#else // if NEED_OPCODE_METADATA -const struct opcode_metadata _PyOpcode_opcode_metadata[OPCODE_METADATA_SIZE] = { - [NOP] = { true, INSTR_FMT_IX, 0 }, - [RESUME] = { true, INSTR_FMT_IB, HAS_ARG_FLAG }, - [INSTRUMENTED_RESUME] = { true, INSTR_FMT_IB, HAS_ARG_FLAG }, - [LOAD_CLOSURE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_LOCAL_FLAG }, - [LOAD_FAST_CHECK] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_LOCAL_FLAG }, - [LOAD_FAST] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_LOCAL_FLAG }, - [LOAD_FAST_AND_CLEAR] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_LOCAL_FLAG }, - [LOAD_FAST_LOAD_FAST] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_LOCAL_FLAG }, - [LOAD_CONST] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_CONST_FLAG }, - [STORE_FAST] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_LOCAL_FLAG }, - [STORE_FAST_MAYBE_NULL] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_LOCAL_FLAG }, - [STORE_FAST_LOAD_FAST] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_LOCAL_FLAG }, - [STORE_FAST_STORE_FAST] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_LOCAL_FLAG }, - [POP_TOP] = { true, INSTR_FMT_IX, 0 }, - [PUSH_NULL] = { true, INSTR_FMT_IX, 0 }, - [END_FOR] = { true, INSTR_FMT_IB, 0 }, - [INSTRUMENTED_END_FOR] = { true, INSTR_FMT_IX, 0 }, - [END_SEND] = { true, INSTR_FMT_IX, 0 }, - [INSTRUMENTED_END_SEND] = { true, INSTR_FMT_IX, 0 }, - [UNARY_NEGATIVE] = { true, INSTR_FMT_IX, 0 }, - [UNARY_NOT] = { true, INSTR_FMT_IX, 0 }, - [TO_BOOL] = { true, INSTR_FMT_IXC00, 0 }, - [TO_BOOL_BOOL] = { true, INSTR_FMT_IXC00, 0 }, - [TO_BOOL_INT] = { true, INSTR_FMT_IXC00, 0 }, - [TO_BOOL_LIST] = { true, INSTR_FMT_IXC00, 0 }, - [TO_BOOL_NONE] = { true, INSTR_FMT_IXC00, 0 }, - [TO_BOOL_STR] = { true, INSTR_FMT_IXC00, 0 }, - [TO_BOOL_ALWAYS_TRUE] = { true, INSTR_FMT_IXC00, 0 }, - [UNARY_INVERT] = { true, INSTR_FMT_IX, 0 }, - [BINARY_OP_MULTIPLY_INT] = { true, INSTR_FMT_IBC, 0 }, - [BINARY_OP_ADD_INT] = { true, INSTR_FMT_IBC, 0 }, - [BINARY_OP_SUBTRACT_INT] = { true, INSTR_FMT_IBC, 0 }, - [BINARY_OP_MULTIPLY_FLOAT] = { true, INSTR_FMT_IBC, 0 }, - [BINARY_OP_ADD_FLOAT] = { true, INSTR_FMT_IBC, 0 }, - [BINARY_OP_SUBTRACT_FLOAT] = { true, INSTR_FMT_IBC, 0 }, - [BINARY_OP_ADD_UNICODE] = { true, INSTR_FMT_IBC, 0 }, - [BINARY_OP_INPLACE_ADD_UNICODE] = { true, INSTR_FMT_IB, HAS_LOCAL_FLAG }, - [BINARY_SUBSCR] = { true, INSTR_FMT_IXC, 0 }, - [BINARY_SLICE] = { true, INSTR_FMT_IX, 0 }, - [STORE_SLICE] = { true, INSTR_FMT_IX, 0 }, - [BINARY_SUBSCR_LIST_INT] = { true, INSTR_FMT_IXC, 0 }, - [BINARY_SUBSCR_TUPLE_INT] = { true, INSTR_FMT_IXC, 0 }, - [BINARY_SUBSCR_DICT] = { true, INSTR_FMT_IXC, 0 }, - [BINARY_SUBSCR_GETITEM] = { true, INSTR_FMT_IXC, 0 }, - [LIST_APPEND] = { true, INSTR_FMT_IB, HAS_ARG_FLAG }, - [SET_ADD] = { true, INSTR_FMT_IB, HAS_ARG_FLAG }, - [STORE_SUBSCR] = { true, INSTR_FMT_IXC, 0 }, - [STORE_SUBSCR_LIST_INT] = { true, INSTR_FMT_IXC, 0 }, - [STORE_SUBSCR_DICT] = { true, INSTR_FMT_IXC, 0 }, - [DELETE_SUBSCR] = { true, INSTR_FMT_IX, 0 }, - [CALL_INTRINSIC_1] = { true, INSTR_FMT_IB, HAS_ARG_FLAG }, - [CALL_INTRINSIC_2] = { true, INSTR_FMT_IB, HAS_ARG_FLAG }, - [RAISE_VARARGS] = { true, INSTR_FMT_IB, HAS_ARG_FLAG }, - [INTERPRETER_EXIT] = { true, INSTR_FMT_IX, 0 }, - [RETURN_VALUE] = { true, INSTR_FMT_IX, 0 }, - [INSTRUMENTED_RETURN_VALUE] = { true, INSTR_FMT_IX, 0 }, - [RETURN_CONST] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_CONST_FLAG }, - [INSTRUMENTED_RETURN_CONST] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_CONST_FLAG }, - [GET_AITER] = { true, INSTR_FMT_IX, 0 }, - [GET_ANEXT] = { true, INSTR_FMT_IX, 0 }, - [GET_AWAITABLE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG }, - [SEND] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG }, - [SEND_GEN] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG }, - [INSTRUMENTED_YIELD_VALUE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG }, - [YIELD_VALUE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG }, - [POP_EXCEPT] = { true, INSTR_FMT_IX, 0 }, - [RERAISE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG }, - [END_ASYNC_FOR] = { true, INSTR_FMT_IX, 0 }, - [CLEANUP_THROW] = { true, INSTR_FMT_IX, 0 }, - [LOAD_ASSERTION_ERROR] = { true, INSTR_FMT_IX, 0 }, - [LOAD_BUILD_CLASS] = { true, INSTR_FMT_IX, 0 }, - [STORE_NAME] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_NAME_FLAG }, - [DELETE_NAME] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_NAME_FLAG }, - [UNPACK_SEQUENCE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG }, - [UNPACK_SEQUENCE_TWO_TUPLE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG }, - [UNPACK_SEQUENCE_TUPLE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG }, - [UNPACK_SEQUENCE_LIST] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG }, - [UNPACK_EX] = { true, INSTR_FMT_IB, HAS_ARG_FLAG }, - [STORE_ATTR] = { true, INSTR_FMT_IBC000, HAS_ARG_FLAG | HAS_NAME_FLAG }, - [DELETE_ATTR] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_NAME_FLAG }, - [STORE_GLOBAL] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_NAME_FLAG }, - [DELETE_GLOBAL] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_NAME_FLAG }, - [LOAD_LOCALS] = { true, INSTR_FMT_IB, 0 }, - [LOAD_NAME] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_NAME_FLAG }, - [LOAD_FROM_DICT_OR_GLOBALS] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_NAME_FLAG }, - [LOAD_GLOBAL] = { true, INSTR_FMT_IBC000, HAS_ARG_FLAG | HAS_NAME_FLAG }, - [LOAD_GLOBAL_MODULE] = { true, INSTR_FMT_IBC000, HAS_ARG_FLAG }, - [LOAD_GLOBAL_BUILTIN] = { true, INSTR_FMT_IBC000, HAS_ARG_FLAG }, - [DELETE_FAST] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_LOCAL_FLAG }, - [MAKE_CELL] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_FREE_FLAG }, - [DELETE_DEREF] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_FREE_FLAG }, - [LOAD_FROM_DICT_OR_DEREF] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_FREE_FLAG }, - [LOAD_DEREF] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_FREE_FLAG }, - [STORE_DEREF] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_FREE_FLAG }, +extern const struct opcode_metadata _PyOpcode_opcode_metadata[268]; +#ifdef NEED_OPCODE_METADATA +const struct opcode_metadata _PyOpcode_opcode_metadata[268] = { + [BEFORE_ASYNC_WITH] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [BEFORE_WITH] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [BINARY_OP] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [BINARY_OP_ADD_FLOAT] = { true, INSTR_FMT_IXC, HAS_DEOPT_FLAG }, + [BINARY_OP_ADD_INT] = { true, INSTR_FMT_IXC, HAS_DEOPT_FLAG | HAS_ERROR_FLAG }, + [BINARY_OP_ADD_UNICODE] = { true, INSTR_FMT_IXC, HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [BINARY_OP_INPLACE_ADD_UNICODE] = { true, INSTR_FMT_IXC, HAS_LOCAL_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [BINARY_OP_MULTIPLY_FLOAT] = { true, INSTR_FMT_IXC, HAS_DEOPT_FLAG }, + [BINARY_OP_MULTIPLY_INT] = { true, INSTR_FMT_IXC, HAS_DEOPT_FLAG | HAS_ERROR_FLAG }, + [BINARY_OP_SUBTRACT_FLOAT] = { true, INSTR_FMT_IXC, HAS_DEOPT_FLAG }, + [BINARY_OP_SUBTRACT_INT] = { true, INSTR_FMT_IXC, HAS_DEOPT_FLAG | HAS_ERROR_FLAG }, + [BINARY_SLICE] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [BINARY_SUBSCR] = { true, INSTR_FMT_IXC, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [BINARY_SUBSCR_DICT] = { true, INSTR_FMT_IXC, HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [BINARY_SUBSCR_GETITEM] = { true, INSTR_FMT_IXC, HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG }, + [BINARY_SUBSCR_LIST_INT] = { true, INSTR_FMT_IXC, HAS_DEOPT_FLAG }, + [BINARY_SUBSCR_STR_INT] = { true, INSTR_FMT_IXC, HAS_DEOPT_FLAG }, + [BINARY_SUBSCR_TUPLE_INT] = { true, INSTR_FMT_IXC, HAS_DEOPT_FLAG }, + [BUILD_CONST_KEY_MAP] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [BUILD_LIST] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [BUILD_MAP] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [BUILD_SET] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [BUILD_SLICE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [BUILD_STRING] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [BUILD_TUPLE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [CACHE] = { true, INSTR_FMT_IX, HAS_ESCAPES_FLAG }, + [CALL] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [CALL_ALLOC_AND_ENTER_INIT] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [CALL_BOUND_METHOD_EXACT_ARGS] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG }, + [CALL_BUILTIN_CLASS] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG }, + [CALL_BUILTIN_FAST] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [CALL_BUILTIN_FAST_WITH_KEYWORDS] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [CALL_BUILTIN_O] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [CALL_FUNCTION_EX] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [CALL_INTRINSIC_1] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [CALL_INTRINSIC_2] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [CALL_ISINSTANCE] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [CALL_KW] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [CALL_LEN] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [CALL_LIST_APPEND] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG }, + [CALL_METHOD_DESCRIPTOR_FAST] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [CALL_METHOD_DESCRIPTOR_NOARGS] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [CALL_METHOD_DESCRIPTOR_O] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [CALL_PY_EXACT_ARGS] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG }, + [CALL_PY_WITH_DEFAULTS] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG }, + [CALL_STR_1] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [CALL_TUPLE_1] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [CALL_TYPE_1] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_DEOPT_FLAG }, + [CHECK_EG_MATCH] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [CHECK_EXC_MATCH] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [CLEANUP_THROW] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [COMPARE_OP] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [COMPARE_OP_FLOAT] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG }, + [COMPARE_OP_INT] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG }, + [COMPARE_OP_STR] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG }, + [CONTAINS_OP] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [CONVERT_VALUE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG }, + [COPY] = { true, INSTR_FMT_IB, HAS_ARG_FLAG }, [COPY_FREE_VARS] = { true, INSTR_FMT_IB, HAS_ARG_FLAG }, - [BUILD_STRING] = { true, INSTR_FMT_IB, HAS_ARG_FLAG }, - [BUILD_TUPLE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG }, - [BUILD_LIST] = { true, INSTR_FMT_IB, HAS_ARG_FLAG }, - [LIST_EXTEND] = { true, INSTR_FMT_IB, HAS_ARG_FLAG }, - [SET_UPDATE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG }, - [BUILD_SET] = { true, INSTR_FMT_IB, HAS_ARG_FLAG }, - [BUILD_MAP] = { true, INSTR_FMT_IB, HAS_ARG_FLAG }, - [SETUP_ANNOTATIONS] = { true, INSTR_FMT_IX, 0 }, - [BUILD_CONST_KEY_MAP] = { true, INSTR_FMT_IB, HAS_ARG_FLAG }, - [DICT_UPDATE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG }, - [DICT_MERGE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG }, - [MAP_ADD] = { true, INSTR_FMT_IB, HAS_ARG_FLAG }, - [INSTRUMENTED_LOAD_SUPER_ATTR] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG }, - [LOAD_SUPER_ATTR] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_NAME_FLAG }, - [LOAD_SUPER_METHOD] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_NAME_FLAG }, - [LOAD_ZERO_SUPER_METHOD] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_NAME_FLAG }, - [LOAD_ZERO_SUPER_ATTR] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_NAME_FLAG }, - [LOAD_SUPER_ATTR_ATTR] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_NAME_FLAG }, - [LOAD_SUPER_ATTR_METHOD] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_NAME_FLAG }, - [LOAD_ATTR] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_NAME_FLAG }, - [LOAD_METHOD] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_NAME_FLAG }, - [LOAD_ATTR_INSTANCE_VALUE] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG }, - [LOAD_ATTR_MODULE] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG }, - [LOAD_ATTR_WITH_HINT] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_NAME_FLAG }, - [LOAD_ATTR_SLOT] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG }, - [LOAD_ATTR_CLASS] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG }, - [LOAD_ATTR_PROPERTY] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG }, - [LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_NAME_FLAG }, - [STORE_ATTR_INSTANCE_VALUE] = { true, INSTR_FMT_IXC000, 0 }, - [STORE_ATTR_WITH_HINT] = { true, INSTR_FMT_IBC000, HAS_ARG_FLAG | HAS_NAME_FLAG }, - [STORE_ATTR_SLOT] = { true, INSTR_FMT_IXC000, 0 }, - [COMPARE_OP] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG }, - [COMPARE_OP_FLOAT] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG }, - [COMPARE_OP_INT] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG }, - [COMPARE_OP_STR] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG }, + [DELETE_ATTR] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [DELETE_DEREF] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_FREE_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [DELETE_FAST] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_LOCAL_FLAG | HAS_ERROR_FLAG }, + [DELETE_GLOBAL] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [DELETE_NAME] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [DELETE_SUBSCR] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [DICT_MERGE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [DICT_UPDATE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [END_ASYNC_FOR] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [END_FOR] = { true, INSTR_FMT_IX, 0 }, + [END_SEND] = { true, INSTR_FMT_IX, 0 }, + [ENTER_EXECUTOR] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG }, + [EXIT_INIT_CHECK] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [EXTENDED_ARG] = { true, INSTR_FMT_IB, HAS_ARG_FLAG }, + [FORMAT_SIMPLE] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [FORMAT_WITH_SPEC] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [FOR_ITER] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [FOR_ITER_GEN] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG }, + [FOR_ITER_LIST] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_DEOPT_FLAG }, + [FOR_ITER_RANGE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [FOR_ITER_TUPLE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_DEOPT_FLAG }, + [GET_AITER] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [GET_ANEXT] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [GET_AWAITABLE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [GET_ITER] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [GET_LEN] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [GET_YIELD_FROM_ITER] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [IMPORT_FROM] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [IMPORT_NAME] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [INSTRUMENTED_CALL] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [INSTRUMENTED_CALL_FUNCTION_EX] = { true, INSTR_FMT_IX, 0 }, + [INSTRUMENTED_CALL_KW] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [INSTRUMENTED_END_FOR] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [INSTRUMENTED_END_SEND] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [INSTRUMENTED_FOR_ITER] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [INSTRUMENTED_INSTRUCTION] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [INSTRUMENTED_JUMP_BACKWARD] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG }, + [INSTRUMENTED_JUMP_FORWARD] = { true, INSTR_FMT_IB, HAS_ARG_FLAG }, + [INSTRUMENTED_LOAD_SUPER_ATTR] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG }, + [INSTRUMENTED_POP_JUMP_IF_FALSE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG }, + [INSTRUMENTED_POP_JUMP_IF_NONE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG }, + [INSTRUMENTED_POP_JUMP_IF_NOT_NONE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG }, + [INSTRUMENTED_POP_JUMP_IF_TRUE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG }, + [INSTRUMENTED_RESUME] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [INSTRUMENTED_RETURN_CONST] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_CONST_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [INSTRUMENTED_RETURN_VALUE] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [INSTRUMENTED_YIELD_VALUE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [INTERPRETER_EXIT] = { true, INSTR_FMT_IX, HAS_ESCAPES_FLAG }, [IS_OP] = { true, INSTR_FMT_IB, HAS_ARG_FLAG }, - [CONTAINS_OP] = { true, INSTR_FMT_IB, HAS_ARG_FLAG }, - [CHECK_EG_MATCH] = { true, INSTR_FMT_IX, 0 }, - [CHECK_EXC_MATCH] = { true, INSTR_FMT_IX, 0 }, - [IMPORT_NAME] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_NAME_FLAG }, - [IMPORT_FROM] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_NAME_FLAG }, - [JUMP_FORWARD] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_JUMP_FLAG }, - [JUMP_BACKWARD] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_JUMP_FLAG }, - [JUMP] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_JUMP_FLAG }, - [JUMP_NO_INTERRUPT] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_JUMP_FLAG }, - [ENTER_EXECUTOR] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_JUMP_FLAG }, - [POP_JUMP_IF_FALSE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_JUMP_FLAG }, - [POP_JUMP_IF_TRUE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_JUMP_FLAG }, - [POP_JUMP_IF_NONE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_JUMP_FLAG }, - [POP_JUMP_IF_NOT_NONE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_JUMP_FLAG }, + [JUMP_BACKWARD] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_EVAL_BREAK_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [JUMP_BACKWARD_NO_INTERRUPT] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_JUMP_FLAG }, - [GET_LEN] = { true, INSTR_FMT_IX, 0 }, - [MATCH_CLASS] = { true, INSTR_FMT_IB, HAS_ARG_FLAG }, + [JUMP_FORWARD] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_JUMP_FLAG }, + [LIST_APPEND] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG }, + [LIST_EXTEND] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [LOAD_ASSERTION_ERROR] = { true, INSTR_FMT_IX, 0 }, + [LOAD_ATTR] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [LOAD_ATTR_CLASS] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_DEOPT_FLAG }, + [LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG }, + [LOAD_ATTR_INSTANCE_VALUE] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_DEOPT_FLAG }, + [LOAD_ATTR_METHOD_LAZY_DICT] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG }, + [LOAD_ATTR_METHOD_NO_DICT] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG }, + [LOAD_ATTR_METHOD_WITH_VALUES] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG }, + [LOAD_ATTR_MODULE] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_DEOPT_FLAG }, + [LOAD_ATTR_NONDESCRIPTOR_NO_DICT] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_DEOPT_FLAG }, + [LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_DEOPT_FLAG }, + [LOAD_ATTR_PROPERTY] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG }, + [LOAD_ATTR_SLOT] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_DEOPT_FLAG }, + [LOAD_ATTR_WITH_HINT] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG }, + [LOAD_BUILD_CLASS] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [LOAD_CONST] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_CONST_FLAG }, + [LOAD_DEREF] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_FREE_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [LOAD_FAST] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_LOCAL_FLAG }, + [LOAD_FAST_AND_CLEAR] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_LOCAL_FLAG }, + [LOAD_FAST_CHECK] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_LOCAL_FLAG | HAS_ERROR_FLAG }, + [LOAD_FAST_LOAD_FAST] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_LOCAL_FLAG }, + [LOAD_FROM_DICT_OR_DEREF] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_FREE_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [LOAD_FROM_DICT_OR_GLOBALS] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [LOAD_GLOBAL] = { true, INSTR_FMT_IBC000, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [LOAD_GLOBAL_BUILTIN] = { true, INSTR_FMT_IBC000, HAS_ARG_FLAG | HAS_DEOPT_FLAG }, + [LOAD_GLOBAL_MODULE] = { true, INSTR_FMT_IBC000, HAS_ARG_FLAG | HAS_DEOPT_FLAG }, + [LOAD_LOCALS] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [LOAD_NAME] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [LOAD_SUPER_ATTR] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [LOAD_SUPER_ATTR_ATTR] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [LOAD_SUPER_ATTR_METHOD] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [MAKE_CELL] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_FREE_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [MAKE_FUNCTION] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [MAP_ADD] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [MATCH_CLASS] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [MATCH_KEYS] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [MATCH_MAPPING] = { true, INSTR_FMT_IX, 0 }, [MATCH_SEQUENCE] = { true, INSTR_FMT_IX, 0 }, - [MATCH_KEYS] = { true, INSTR_FMT_IX, 0 }, - [GET_ITER] = { true, INSTR_FMT_IX, 0 }, - [GET_YIELD_FROM_ITER] = { true, INSTR_FMT_IX, 0 }, - [FOR_ITER] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG }, - [INSTRUMENTED_FOR_ITER] = { true, INSTR_FMT_IB, HAS_ARG_FLAG }, - [FOR_ITER_LIST] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG }, - [FOR_ITER_TUPLE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG }, - [FOR_ITER_RANGE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG }, - [FOR_ITER_GEN] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG }, - [BEFORE_ASYNC_WITH] = { true, INSTR_FMT_IX, 0 }, - [BEFORE_WITH] = { true, INSTR_FMT_IX, 0 }, - [WITH_EXCEPT_START] = { true, INSTR_FMT_IX, 0 }, - [SETUP_FINALLY] = { true, INSTR_FMT_IX, 0 }, - [SETUP_CLEANUP] = { true, INSTR_FMT_IX, 0 }, - [SETUP_WITH] = { true, INSTR_FMT_IX, 0 }, - [POP_BLOCK] = { true, INSTR_FMT_IX, 0 }, + [NOP] = { true, INSTR_FMT_IX, 0 }, + [POP_EXCEPT] = { true, INSTR_FMT_IX, HAS_ESCAPES_FLAG }, + [POP_JUMP_IF_FALSE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG }, + [POP_JUMP_IF_NONE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG }, + [POP_JUMP_IF_NOT_NONE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG }, + [POP_JUMP_IF_TRUE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG }, + [POP_TOP] = { true, INSTR_FMT_IX, 0 }, [PUSH_EXC_INFO] = { true, INSTR_FMT_IX, 0 }, - [LOAD_ATTR_METHOD_WITH_VALUES] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG }, - [LOAD_ATTR_METHOD_NO_DICT] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG }, - [LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG }, - [LOAD_ATTR_NONDESCRIPTOR_NO_DICT] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG }, - [LOAD_ATTR_METHOD_LAZY_DICT] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG }, - [KW_NAMES] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_CONST_FLAG }, - [INSTRUMENTED_CALL] = { true, INSTR_FMT_IB, HAS_ARG_FLAG }, - [CALL] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG }, - [CALL_BOUND_METHOD_EXACT_ARGS] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG }, - [CALL_PY_EXACT_ARGS] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG }, - [CALL_PY_WITH_DEFAULTS] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG }, - [CALL_NO_KW_TYPE_1] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG }, - [CALL_NO_KW_STR_1] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG }, - [CALL_NO_KW_TUPLE_1] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG }, - [CALL_NO_KW_ALLOC_AND_ENTER_INIT] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG }, - [EXIT_INIT_CHECK] = { true, INSTR_FMT_IX, 0 }, - [CALL_BUILTIN_CLASS] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG }, - [CALL_NO_KW_BUILTIN_O] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG }, - [CALL_NO_KW_BUILTIN_FAST] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG }, - [CALL_BUILTIN_FAST_WITH_KEYWORDS] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG }, - [CALL_NO_KW_LEN] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG }, - [CALL_NO_KW_ISINSTANCE] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG }, - [CALL_NO_KW_LIST_APPEND] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG }, - [CALL_NO_KW_METHOD_DESCRIPTOR_O] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG }, - [CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG }, - [CALL_NO_KW_METHOD_DESCRIPTOR_NOARGS] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG }, - [CALL_NO_KW_METHOD_DESCRIPTOR_FAST] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG }, - [INSTRUMENTED_CALL_FUNCTION_EX] = { true, INSTR_FMT_IX, 0 }, - [CALL_FUNCTION_EX] = { true, INSTR_FMT_IB, HAS_ARG_FLAG }, - [MAKE_FUNCTION] = { true, INSTR_FMT_IX, 0 }, - [SET_FUNCTION_ATTRIBUTE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG }, - [RETURN_GENERATOR] = { true, INSTR_FMT_IX, 0 }, - [BUILD_SLICE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG }, - [CONVERT_VALUE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG }, - [FORMAT_SIMPLE] = { true, INSTR_FMT_IX, 0 }, - [FORMAT_WITH_SPEC] = { true, INSTR_FMT_IX, 0 }, - [COPY] = { true, INSTR_FMT_IB, HAS_ARG_FLAG }, - [BINARY_OP] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG }, + [PUSH_NULL] = { true, INSTR_FMT_IX, 0 }, + [RAISE_VARARGS] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [RERAISE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [RESERVED] = { true, INSTR_FMT_IX, HAS_ESCAPES_FLAG }, + [RESUME] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [RESUME_CHECK] = { true, INSTR_FMT_IX, HAS_DEOPT_FLAG }, + [RETURN_CONST] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_CONST_FLAG | HAS_ESCAPES_FLAG }, + [RETURN_GENERATOR] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [RETURN_VALUE] = { true, INSTR_FMT_IX, HAS_ESCAPES_FLAG }, + [SEND] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [SEND_GEN] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG }, + [SETUP_ANNOTATIONS] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [SET_ADD] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [SET_FUNCTION_ATTRIBUTE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ESCAPES_FLAG }, + [SET_UPDATE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [STORE_ATTR] = { true, INSTR_FMT_IBC000, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [STORE_ATTR_INSTANCE_VALUE] = { true, INSTR_FMT_IXC000, HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG }, + [STORE_ATTR_SLOT] = { true, INSTR_FMT_IXC000, HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG }, + [STORE_ATTR_WITH_HINT] = { true, INSTR_FMT_IBC000, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG }, + [STORE_DEREF] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_FREE_FLAG | HAS_ESCAPES_FLAG }, + [STORE_FAST] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_LOCAL_FLAG }, + [STORE_FAST_LOAD_FAST] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_LOCAL_FLAG }, + [STORE_FAST_STORE_FAST] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_LOCAL_FLAG }, + [STORE_GLOBAL] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [STORE_NAME] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [STORE_SLICE] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [STORE_SUBSCR] = { true, INSTR_FMT_IXC, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [STORE_SUBSCR_DICT] = { true, INSTR_FMT_IXC, HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [STORE_SUBSCR_LIST_INT] = { true, INSTR_FMT_IXC, HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG }, [SWAP] = { true, INSTR_FMT_IB, HAS_ARG_FLAG }, - [INSTRUMENTED_INSTRUCTION] = { true, INSTR_FMT_IX, 0 }, - [INSTRUMENTED_JUMP_FORWARD] = { true, INSTR_FMT_IB, HAS_ARG_FLAG }, - [INSTRUMENTED_JUMP_BACKWARD] = { true, INSTR_FMT_IB, HAS_ARG_FLAG }, - [INSTRUMENTED_POP_JUMP_IF_TRUE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG }, - [INSTRUMENTED_POP_JUMP_IF_FALSE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG }, - [INSTRUMENTED_POP_JUMP_IF_NONE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG }, - [INSTRUMENTED_POP_JUMP_IF_NOT_NONE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG }, - [EXTENDED_ARG] = { true, INSTR_FMT_IB, HAS_ARG_FLAG }, - [CACHE] = { true, INSTR_FMT_IX, 0 }, - [RESERVED] = { true, INSTR_FMT_IX, 0 }, + [TO_BOOL] = { true, INSTR_FMT_IXC00, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [TO_BOOL_ALWAYS_TRUE] = { true, INSTR_FMT_IXC00, HAS_DEOPT_FLAG }, + [TO_BOOL_BOOL] = { true, INSTR_FMT_IXC00, HAS_DEOPT_FLAG }, + [TO_BOOL_INT] = { true, INSTR_FMT_IXC00, HAS_DEOPT_FLAG }, + [TO_BOOL_LIST] = { true, INSTR_FMT_IXC00, HAS_DEOPT_FLAG }, + [TO_BOOL_NONE] = { true, INSTR_FMT_IXC00, HAS_DEOPT_FLAG }, + [TO_BOOL_STR] = { true, INSTR_FMT_IXC00, HAS_DEOPT_FLAG }, + [UNARY_INVERT] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [UNARY_NEGATIVE] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [UNARY_NOT] = { true, INSTR_FMT_IX, 0 }, + [UNPACK_EX] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [UNPACK_SEQUENCE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [UNPACK_SEQUENCE_LIST] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_DEOPT_FLAG }, + [UNPACK_SEQUENCE_TUPLE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_DEOPT_FLAG }, + [UNPACK_SEQUENCE_TWO_TUPLE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_DEOPT_FLAG }, + [WITH_EXCEPT_START] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [YIELD_VALUE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ESCAPES_FLAG }, + [JUMP] = { true, -1, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_EVAL_BREAK_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [JUMP_NO_INTERRUPT] = { true, -1, HAS_ARG_FLAG | HAS_JUMP_FLAG }, + [LOAD_CLOSURE] = { true, -1, HAS_ARG_FLAG | HAS_LOCAL_FLAG }, + [LOAD_METHOD] = { true, -1, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [LOAD_SUPER_METHOD] = { true, -1, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [LOAD_ZERO_SUPER_ATTR] = { true, -1, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [LOAD_ZERO_SUPER_METHOD] = { true, -1, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [POP_BLOCK] = { true, -1, 0 }, + [SETUP_CLEANUP] = { true, -1, HAS_ARG_FLAG }, + [SETUP_FINALLY] = { true, -1, HAS_ARG_FLAG }, + [SETUP_WITH] = { true, -1, HAS_ARG_FLAG }, + [STORE_FAST_MAYBE_NULL] = { true, -1, HAS_ARG_FLAG | HAS_LOCAL_FLAG }, }; -const struct opcode_macro_expansion _PyOpcode_macro_expansion[OPCODE_MACRO_EXPANSION_SIZE] = { - [NOP] = { .nuops = 1, .uops = { { NOP, 0, 0 } } }, - [LOAD_FAST_CHECK] = { .nuops = 1, .uops = { { LOAD_FAST_CHECK, 0, 0 } } }, - [LOAD_FAST] = { .nuops = 1, .uops = { { LOAD_FAST, 0, 0 } } }, - [LOAD_FAST_AND_CLEAR] = { .nuops = 1, .uops = { { LOAD_FAST_AND_CLEAR, 0, 0 } } }, - [LOAD_FAST_LOAD_FAST] = { .nuops = 2, .uops = { { LOAD_FAST, 5, 0 }, { LOAD_FAST, 6, 0 } } }, - [LOAD_CONST] = { .nuops = 1, .uops = { { LOAD_CONST, 0, 0 } } }, - [STORE_FAST] = { .nuops = 1, .uops = { { STORE_FAST, 0, 0 } } }, - [STORE_FAST_LOAD_FAST] = { .nuops = 2, .uops = { { STORE_FAST, 5, 0 }, { LOAD_FAST, 6, 0 } } }, - [STORE_FAST_STORE_FAST] = { .nuops = 2, .uops = { { STORE_FAST, 5, 0 }, { STORE_FAST, 6, 0 } } }, - [POP_TOP] = { .nuops = 1, .uops = { { POP_TOP, 0, 0 } } }, - [PUSH_NULL] = { .nuops = 1, .uops = { { PUSH_NULL, 0, 0 } } }, - [END_FOR] = { .nuops = 2, .uops = { { POP_TOP, 0, 0 }, { POP_TOP, 0, 0 } } }, - [END_SEND] = { .nuops = 1, .uops = { { END_SEND, 0, 0 } } }, - [UNARY_NEGATIVE] = { .nuops = 1, .uops = { { UNARY_NEGATIVE, 0, 0 } } }, - [UNARY_NOT] = { .nuops = 1, .uops = { { UNARY_NOT, 0, 0 } } }, - [TO_BOOL] = { .nuops = 1, .uops = { { TO_BOOL, 0, 0 } } }, - [TO_BOOL_BOOL] = { .nuops = 1, .uops = { { TO_BOOL_BOOL, 0, 0 } } }, - [TO_BOOL_INT] = { .nuops = 1, .uops = { { TO_BOOL_INT, 0, 0 } } }, - [TO_BOOL_LIST] = { .nuops = 1, .uops = { { TO_BOOL_LIST, 0, 0 } } }, - [TO_BOOL_NONE] = { .nuops = 1, .uops = { { TO_BOOL_NONE, 0, 0 } } }, - [TO_BOOL_STR] = { .nuops = 1, .uops = { { TO_BOOL_STR, 0, 0 } } }, - [TO_BOOL_ALWAYS_TRUE] = { .nuops = 1, .uops = { { TO_BOOL_ALWAYS_TRUE, 2, 1 } } }, - [UNARY_INVERT] = { .nuops = 1, .uops = { { UNARY_INVERT, 0, 0 } } }, - [BINARY_OP_MULTIPLY_INT] = { .nuops = 2, .uops = { { _GUARD_BOTH_INT, 0, 0 }, { _BINARY_OP_MULTIPLY_INT, 0, 0 } } }, +#endif + +#define MAX_UOP_PER_EXPANSION 8 +struct opcode_macro_expansion { + int nuops; + struct { int16_t uop; int8_t size; int8_t offset; } uops[MAX_UOP_PER_EXPANSION]; +}; +extern const struct opcode_macro_expansion _PyOpcode_macro_expansion[256]; + +#ifdef NEED_OPCODE_METADATA +const struct opcode_macro_expansion +_PyOpcode_macro_expansion[256] = { + [BEFORE_ASYNC_WITH] = { .nuops = 1, .uops = { { _BEFORE_ASYNC_WITH, 0, 0 } } }, + [BEFORE_WITH] = { .nuops = 1, .uops = { { _BEFORE_WITH, 0, 0 } } }, + [BINARY_OP] = { .nuops = 1, .uops = { { _BINARY_OP, 0, 0 } } }, + [BINARY_OP_ADD_FLOAT] = { .nuops = 2, .uops = { { _GUARD_BOTH_FLOAT, 0, 0 }, { _BINARY_OP_ADD_FLOAT, 0, 0 } } }, [BINARY_OP_ADD_INT] = { .nuops = 2, .uops = { { _GUARD_BOTH_INT, 0, 0 }, { _BINARY_OP_ADD_INT, 0, 0 } } }, - [BINARY_OP_SUBTRACT_INT] = { .nuops = 2, .uops = { { _GUARD_BOTH_INT, 0, 0 }, { _BINARY_OP_SUBTRACT_INT, 0, 0 } } }, + [BINARY_OP_ADD_UNICODE] = { .nuops = 2, .uops = { { _GUARD_BOTH_UNICODE, 0, 0 }, { _BINARY_OP_ADD_UNICODE, 0, 0 } } }, [BINARY_OP_MULTIPLY_FLOAT] = { .nuops = 2, .uops = { { _GUARD_BOTH_FLOAT, 0, 0 }, { _BINARY_OP_MULTIPLY_FLOAT, 0, 0 } } }, - [BINARY_OP_ADD_FLOAT] = { .nuops = 2, .uops = { { _GUARD_BOTH_FLOAT, 0, 0 }, { _BINARY_OP_ADD_FLOAT, 0, 0 } } }, + [BINARY_OP_MULTIPLY_INT] = { .nuops = 2, .uops = { { _GUARD_BOTH_INT, 0, 0 }, { _BINARY_OP_MULTIPLY_INT, 0, 0 } } }, [BINARY_OP_SUBTRACT_FLOAT] = { .nuops = 2, .uops = { { _GUARD_BOTH_FLOAT, 0, 0 }, { _BINARY_OP_SUBTRACT_FLOAT, 0, 0 } } }, - [BINARY_OP_ADD_UNICODE] = { .nuops = 2, .uops = { { _GUARD_BOTH_UNICODE, 0, 0 }, { _BINARY_OP_ADD_UNICODE, 0, 0 } } }, - [BINARY_SUBSCR] = { .nuops = 1, .uops = { { BINARY_SUBSCR, 0, 0 } } }, - [BINARY_SLICE] = { .nuops = 1, .uops = { { BINARY_SLICE, 0, 0 } } }, - [STORE_SLICE] = { .nuops = 1, .uops = { { STORE_SLICE, 0, 0 } } }, - [BINARY_SUBSCR_LIST_INT] = { .nuops = 1, .uops = { { BINARY_SUBSCR_LIST_INT, 0, 0 } } }, - [BINARY_SUBSCR_TUPLE_INT] = { .nuops = 1, .uops = { { BINARY_SUBSCR_TUPLE_INT, 0, 0 } } }, - [BINARY_SUBSCR_DICT] = { .nuops = 1, .uops = { { BINARY_SUBSCR_DICT, 0, 0 } } }, - [LIST_APPEND] = { .nuops = 1, .uops = { { LIST_APPEND, 0, 0 } } }, - [SET_ADD] = { .nuops = 1, .uops = { { SET_ADD, 0, 0 } } }, - [STORE_SUBSCR] = { .nuops = 1, .uops = { { STORE_SUBSCR, 0, 0 } } }, - [STORE_SUBSCR_LIST_INT] = { .nuops = 1, .uops = { { STORE_SUBSCR_LIST_INT, 0, 0 } } }, - [STORE_SUBSCR_DICT] = { .nuops = 1, .uops = { { STORE_SUBSCR_DICT, 0, 0 } } }, - [DELETE_SUBSCR] = { .nuops = 1, .uops = { { DELETE_SUBSCR, 0, 0 } } }, - [CALL_INTRINSIC_1] = { .nuops = 1, .uops = { { CALL_INTRINSIC_1, 0, 0 } } }, - [CALL_INTRINSIC_2] = { .nuops = 1, .uops = { { CALL_INTRINSIC_2, 0, 0 } } }, - [GET_AITER] = { .nuops = 1, .uops = { { GET_AITER, 0, 0 } } }, - [GET_ANEXT] = { .nuops = 1, .uops = { { GET_ANEXT, 0, 0 } } }, - [GET_AWAITABLE] = { .nuops = 1, .uops = { { GET_AWAITABLE, 0, 0 } } }, - [POP_EXCEPT] = { .nuops = 1, .uops = { { POP_EXCEPT, 0, 0 } } }, - [LOAD_ASSERTION_ERROR] = { .nuops = 1, .uops = { { LOAD_ASSERTION_ERROR, 0, 0 } } }, - [LOAD_BUILD_CLASS] = { .nuops = 1, .uops = { { LOAD_BUILD_CLASS, 0, 0 } } }, - [STORE_NAME] = { .nuops = 1, .uops = { { STORE_NAME, 0, 0 } } }, - [DELETE_NAME] = { .nuops = 1, .uops = { { DELETE_NAME, 0, 0 } } }, - [UNPACK_SEQUENCE] = { .nuops = 1, .uops = { { UNPACK_SEQUENCE, 0, 0 } } }, - [UNPACK_SEQUENCE_TWO_TUPLE] = { .nuops = 1, .uops = { { UNPACK_SEQUENCE_TWO_TUPLE, 0, 0 } } }, - [UNPACK_SEQUENCE_TUPLE] = { .nuops = 1, .uops = { { UNPACK_SEQUENCE_TUPLE, 0, 0 } } }, - [UNPACK_SEQUENCE_LIST] = { .nuops = 1, .uops = { { UNPACK_SEQUENCE_LIST, 0, 0 } } }, - [UNPACK_EX] = { .nuops = 1, .uops = { { UNPACK_EX, 0, 0 } } }, - [STORE_ATTR] = { .nuops = 1, .uops = { { STORE_ATTR, 0, 0 } } }, - [DELETE_ATTR] = { .nuops = 1, .uops = { { DELETE_ATTR, 0, 0 } } }, - [STORE_GLOBAL] = { .nuops = 1, .uops = { { STORE_GLOBAL, 0, 0 } } }, - [DELETE_GLOBAL] = { .nuops = 1, .uops = { { DELETE_GLOBAL, 0, 0 } } }, - [LOAD_LOCALS] = { .nuops = 1, .uops = { { _LOAD_LOCALS, 0, 0 } } }, - [LOAD_NAME] = { .nuops = 2, .uops = { { _LOAD_LOCALS, 0, 0 }, { _LOAD_FROM_DICT_OR_GLOBALS, 0, 0 } } }, + [BINARY_OP_SUBTRACT_INT] = { .nuops = 2, .uops = { { _GUARD_BOTH_INT, 0, 0 }, { _BINARY_OP_SUBTRACT_INT, 0, 0 } } }, + [BINARY_SLICE] = { .nuops = 1, .uops = { { _BINARY_SLICE, 0, 0 } } }, + [BINARY_SUBSCR] = { .nuops = 1, .uops = { { _BINARY_SUBSCR, 0, 0 } } }, + [BINARY_SUBSCR_DICT] = { .nuops = 1, .uops = { { _BINARY_SUBSCR_DICT, 0, 0 } } }, + [BINARY_SUBSCR_LIST_INT] = { .nuops = 1, .uops = { { _BINARY_SUBSCR_LIST_INT, 0, 0 } } }, + [BINARY_SUBSCR_STR_INT] = { .nuops = 1, .uops = { { _BINARY_SUBSCR_STR_INT, 0, 0 } } }, + [BINARY_SUBSCR_TUPLE_INT] = { .nuops = 1, .uops = { { _BINARY_SUBSCR_TUPLE_INT, 0, 0 } } }, + [BUILD_CONST_KEY_MAP] = { .nuops = 1, .uops = { { _BUILD_CONST_KEY_MAP, 0, 0 } } }, + [BUILD_LIST] = { .nuops = 1, .uops = { { _BUILD_LIST, 0, 0 } } }, + [BUILD_MAP] = { .nuops = 1, .uops = { { _BUILD_MAP, 0, 0 } } }, + [BUILD_SET] = { .nuops = 1, .uops = { { _BUILD_SET, 0, 0 } } }, + [BUILD_SLICE] = { .nuops = 1, .uops = { { _BUILD_SLICE, 0, 0 } } }, + [BUILD_STRING] = { .nuops = 1, .uops = { { _BUILD_STRING, 0, 0 } } }, + [BUILD_TUPLE] = { .nuops = 1, .uops = { { _BUILD_TUPLE, 0, 0 } } }, + [CALL_BOUND_METHOD_EXACT_ARGS] = { .nuops = 8, .uops = { { _CHECK_PEP_523, 0, 0 }, { _CHECK_CALL_BOUND_METHOD_EXACT_ARGS, 0, 0 }, { _INIT_CALL_BOUND_METHOD_EXACT_ARGS, 0, 0 }, { _CHECK_FUNCTION_EXACT_ARGS, 2, 1 }, { _CHECK_STACK_SPACE, 0, 0 }, { _INIT_CALL_PY_EXACT_ARGS, 0, 0 }, { _SAVE_RETURN_OFFSET, 7, 3 }, { _PUSH_FRAME, 0, 0 } } }, + [CALL_BUILTIN_CLASS] = { .nuops = 1, .uops = { { _CALL_BUILTIN_CLASS, 0, 0 } } }, + [CALL_BUILTIN_FAST] = { .nuops = 1, .uops = { { _CALL_BUILTIN_FAST, 0, 0 } } }, + [CALL_BUILTIN_FAST_WITH_KEYWORDS] = { .nuops = 1, .uops = { { _CALL_BUILTIN_FAST_WITH_KEYWORDS, 0, 0 } } }, + [CALL_BUILTIN_O] = { .nuops = 1, .uops = { { _CALL_BUILTIN_O, 0, 0 } } }, + [CALL_INTRINSIC_1] = { .nuops = 1, .uops = { { _CALL_INTRINSIC_1, 0, 0 } } }, + [CALL_INTRINSIC_2] = { .nuops = 1, .uops = { { _CALL_INTRINSIC_2, 0, 0 } } }, + [CALL_ISINSTANCE] = { .nuops = 1, .uops = { { _CALL_ISINSTANCE, 0, 0 } } }, + [CALL_LEN] = { .nuops = 1, .uops = { { _CALL_LEN, 0, 0 } } }, + [CALL_METHOD_DESCRIPTOR_FAST] = { .nuops = 1, .uops = { { _CALL_METHOD_DESCRIPTOR_FAST, 0, 0 } } }, + [CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS] = { .nuops = 1, .uops = { { _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS, 0, 0 } } }, + [CALL_METHOD_DESCRIPTOR_NOARGS] = { .nuops = 1, .uops = { { _CALL_METHOD_DESCRIPTOR_NOARGS, 0, 0 } } }, + [CALL_METHOD_DESCRIPTOR_O] = { .nuops = 1, .uops = { { _CALL_METHOD_DESCRIPTOR_O, 0, 0 } } }, + [CALL_PY_EXACT_ARGS] = { .nuops = 6, .uops = { { _CHECK_PEP_523, 0, 0 }, { _CHECK_FUNCTION_EXACT_ARGS, 2, 1 }, { _CHECK_STACK_SPACE, 0, 0 }, { _INIT_CALL_PY_EXACT_ARGS, 0, 0 }, { _SAVE_RETURN_OFFSET, 7, 3 }, { _PUSH_FRAME, 0, 0 } } }, + [CALL_STR_1] = { .nuops = 1, .uops = { { _CALL_STR_1, 0, 0 } } }, + [CALL_TUPLE_1] = { .nuops = 1, .uops = { { _CALL_TUPLE_1, 0, 0 } } }, + [CALL_TYPE_1] = { .nuops = 1, .uops = { { _CALL_TYPE_1, 0, 0 } } }, + [CHECK_EG_MATCH] = { .nuops = 1, .uops = { { _CHECK_EG_MATCH, 0, 0 } } }, + [CHECK_EXC_MATCH] = { .nuops = 1, .uops = { { _CHECK_EXC_MATCH, 0, 0 } } }, + [COMPARE_OP] = { .nuops = 1, .uops = { { _COMPARE_OP, 0, 0 } } }, + [COMPARE_OP_FLOAT] = { .nuops = 1, .uops = { { _COMPARE_OP_FLOAT, 0, 0 } } }, + [COMPARE_OP_INT] = { .nuops = 1, .uops = { { _COMPARE_OP_INT, 0, 0 } } }, + [COMPARE_OP_STR] = { .nuops = 1, .uops = { { _COMPARE_OP_STR, 0, 0 } } }, + [CONTAINS_OP] = { .nuops = 1, .uops = { { _CONTAINS_OP, 0, 0 } } }, + [CONVERT_VALUE] = { .nuops = 1, .uops = { { _CONVERT_VALUE, 0, 0 } } }, + [COPY] = { .nuops = 1, .uops = { { _COPY, 0, 0 } } }, + [COPY_FREE_VARS] = { .nuops = 1, .uops = { { _COPY_FREE_VARS, 0, 0 } } }, + [DELETE_ATTR] = { .nuops = 1, .uops = { { _DELETE_ATTR, 0, 0 } } }, + [DELETE_DEREF] = { .nuops = 1, .uops = { { _DELETE_DEREF, 0, 0 } } }, + [DELETE_FAST] = { .nuops = 1, .uops = { { _DELETE_FAST, 0, 0 } } }, + [DELETE_GLOBAL] = { .nuops = 1, .uops = { { _DELETE_GLOBAL, 0, 0 } } }, + [DELETE_NAME] = { .nuops = 1, .uops = { { _DELETE_NAME, 0, 0 } } }, + [DELETE_SUBSCR] = { .nuops = 1, .uops = { { _DELETE_SUBSCR, 0, 0 } } }, + [DICT_MERGE] = { .nuops = 1, .uops = { { _DICT_MERGE, 0, 0 } } }, + [DICT_UPDATE] = { .nuops = 1, .uops = { { _DICT_UPDATE, 0, 0 } } }, + [END_FOR] = { .nuops = 2, .uops = { { _POP_TOP, 0, 0 }, { _POP_TOP, 0, 0 } } }, + [END_SEND] = { .nuops = 1, .uops = { { _END_SEND, 0, 0 } } }, + [EXIT_INIT_CHECK] = { .nuops = 1, .uops = { { _EXIT_INIT_CHECK, 0, 0 } } }, + [FORMAT_SIMPLE] = { .nuops = 1, .uops = { { _FORMAT_SIMPLE, 0, 0 } } }, + [FORMAT_WITH_SPEC] = { .nuops = 1, .uops = { { _FORMAT_WITH_SPEC, 0, 0 } } }, + [FOR_ITER] = { .nuops = 1, .uops = { { _FOR_ITER, 9, 0 } } }, + [FOR_ITER_LIST] = { .nuops = 3, .uops = { { _ITER_CHECK_LIST, 0, 0 }, { _ITER_JUMP_LIST, 9, 1 }, { _ITER_NEXT_LIST, 0, 0 } } }, + [FOR_ITER_RANGE] = { .nuops = 3, .uops = { { _ITER_CHECK_RANGE, 0, 0 }, { _ITER_JUMP_RANGE, 9, 1 }, { _ITER_NEXT_RANGE, 0, 0 } } }, + [FOR_ITER_TUPLE] = { .nuops = 3, .uops = { { _ITER_CHECK_TUPLE, 0, 0 }, { _ITER_JUMP_TUPLE, 9, 1 }, { _ITER_NEXT_TUPLE, 0, 0 } } }, + [GET_AITER] = { .nuops = 1, .uops = { { _GET_AITER, 0, 0 } } }, + [GET_ANEXT] = { .nuops = 1, .uops = { { _GET_ANEXT, 0, 0 } } }, + [GET_AWAITABLE] = { .nuops = 1, .uops = { { _GET_AWAITABLE, 0, 0 } } }, + [GET_ITER] = { .nuops = 1, .uops = { { _GET_ITER, 0, 0 } } }, + [GET_LEN] = { .nuops = 1, .uops = { { _GET_LEN, 0, 0 } } }, + [GET_YIELD_FROM_ITER] = { .nuops = 1, .uops = { { _GET_YIELD_FROM_ITER, 0, 0 } } }, + [IS_OP] = { .nuops = 1, .uops = { { _IS_OP, 0, 0 } } }, + [LIST_APPEND] = { .nuops = 1, .uops = { { _LIST_APPEND, 0, 0 } } }, + [LIST_EXTEND] = { .nuops = 1, .uops = { { _LIST_EXTEND, 0, 0 } } }, + [LOAD_ASSERTION_ERROR] = { .nuops = 1, .uops = { { _LOAD_ASSERTION_ERROR, 0, 0 } } }, + [LOAD_ATTR] = { .nuops = 1, .uops = { { _LOAD_ATTR, 0, 0 } } }, + [LOAD_ATTR_CLASS] = { .nuops = 2, .uops = { { _CHECK_ATTR_CLASS, 2, 1 }, { _LOAD_ATTR_CLASS, 4, 5 } } }, + [LOAD_ATTR_INSTANCE_VALUE] = { .nuops = 3, .uops = { { _GUARD_TYPE_VERSION, 2, 1 }, { _CHECK_MANAGED_OBJECT_HAS_VALUES, 0, 0 }, { _LOAD_ATTR_INSTANCE_VALUE, 1, 3 } } }, + [LOAD_ATTR_METHOD_LAZY_DICT] = { .nuops = 3, .uops = { { _GUARD_TYPE_VERSION, 2, 1 }, { _CHECK_ATTR_METHOD_LAZY_DICT, 0, 0 }, { _LOAD_ATTR_METHOD_LAZY_DICT, 4, 5 } } }, + [LOAD_ATTR_METHOD_NO_DICT] = { .nuops = 2, .uops = { { _GUARD_TYPE_VERSION, 2, 1 }, { _LOAD_ATTR_METHOD_NO_DICT, 4, 5 } } }, + [LOAD_ATTR_METHOD_WITH_VALUES] = { .nuops = 4, .uops = { { _GUARD_TYPE_VERSION, 2, 1 }, { _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT, 0, 0 }, { _GUARD_KEYS_VERSION, 2, 3 }, { _LOAD_ATTR_METHOD_WITH_VALUES, 4, 5 } } }, + [LOAD_ATTR_MODULE] = { .nuops = 2, .uops = { { _CHECK_ATTR_MODULE, 2, 1 }, { _LOAD_ATTR_MODULE, 1, 3 } } }, + [LOAD_ATTR_NONDESCRIPTOR_NO_DICT] = { .nuops = 2, .uops = { { _GUARD_TYPE_VERSION, 2, 1 }, { _LOAD_ATTR_NONDESCRIPTOR_NO_DICT, 4, 5 } } }, + [LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES] = { .nuops = 4, .uops = { { _GUARD_TYPE_VERSION, 2, 1 }, { _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT, 0, 0 }, { _GUARD_KEYS_VERSION, 2, 3 }, { _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES, 4, 5 } } }, + [LOAD_ATTR_SLOT] = { .nuops = 2, .uops = { { _GUARD_TYPE_VERSION, 2, 1 }, { _LOAD_ATTR_SLOT, 1, 3 } } }, + [LOAD_ATTR_WITH_HINT] = { .nuops = 3, .uops = { { _GUARD_TYPE_VERSION, 2, 1 }, { _CHECK_ATTR_WITH_HINT, 0, 0 }, { _LOAD_ATTR_WITH_HINT, 1, 3 } } }, + [LOAD_BUILD_CLASS] = { .nuops = 1, .uops = { { _LOAD_BUILD_CLASS, 0, 0 } } }, + [LOAD_CONST] = { .nuops = 1, .uops = { { _LOAD_CONST, 0, 0 } } }, + [LOAD_DEREF] = { .nuops = 1, .uops = { { _LOAD_DEREF, 0, 0 } } }, + [LOAD_FAST] = { .nuops = 1, .uops = { { _LOAD_FAST, 0, 0 } } }, + [LOAD_FAST_AND_CLEAR] = { .nuops = 1, .uops = { { _LOAD_FAST_AND_CLEAR, 0, 0 } } }, + [LOAD_FAST_CHECK] = { .nuops = 1, .uops = { { _LOAD_FAST_CHECK, 0, 0 } } }, + [LOAD_FAST_LOAD_FAST] = { .nuops = 2, .uops = { { _LOAD_FAST, 5, 0 }, { _LOAD_FAST, 6, 0 } } }, + [LOAD_FROM_DICT_OR_DEREF] = { .nuops = 1, .uops = { { _LOAD_FROM_DICT_OR_DEREF, 0, 0 } } }, [LOAD_FROM_DICT_OR_GLOBALS] = { .nuops = 1, .uops = { { _LOAD_FROM_DICT_OR_GLOBALS, 0, 0 } } }, - [LOAD_GLOBAL] = { .nuops = 1, .uops = { { LOAD_GLOBAL, 0, 0 } } }, - [LOAD_GLOBAL_MODULE] = { .nuops = 2, .uops = { { _GUARD_GLOBALS_VERSION, 1, 1 }, { _LOAD_GLOBAL_MODULE, 1, 3 } } }, + [LOAD_GLOBAL] = { .nuops = 1, .uops = { { _LOAD_GLOBAL, 0, 0 } } }, [LOAD_GLOBAL_BUILTIN] = { .nuops = 3, .uops = { { _GUARD_GLOBALS_VERSION, 1, 1 }, { _GUARD_BUILTINS_VERSION, 1, 2 }, { _LOAD_GLOBAL_BUILTINS, 1, 3 } } }, - [DELETE_FAST] = { .nuops = 1, .uops = { { DELETE_FAST, 0, 0 } } }, - [DELETE_DEREF] = { .nuops = 1, .uops = { { DELETE_DEREF, 0, 0 } } }, - [LOAD_FROM_DICT_OR_DEREF] = { .nuops = 1, .uops = { { LOAD_FROM_DICT_OR_DEREF, 0, 0 } } }, - [LOAD_DEREF] = { .nuops = 1, .uops = { { LOAD_DEREF, 0, 0 } } }, - [STORE_DEREF] = { .nuops = 1, .uops = { { STORE_DEREF, 0, 0 } } }, - [COPY_FREE_VARS] = { .nuops = 1, .uops = { { COPY_FREE_VARS, 0, 0 } } }, - [BUILD_STRING] = { .nuops = 1, .uops = { { BUILD_STRING, 0, 0 } } }, - [BUILD_TUPLE] = { .nuops = 1, .uops = { { BUILD_TUPLE, 0, 0 } } }, - [BUILD_LIST] = { .nuops = 1, .uops = { { BUILD_LIST, 0, 0 } } }, - [LIST_EXTEND] = { .nuops = 1, .uops = { { LIST_EXTEND, 0, 0 } } }, - [SET_UPDATE] = { .nuops = 1, .uops = { { SET_UPDATE, 0, 0 } } }, - [BUILD_SET] = { .nuops = 1, .uops = { { BUILD_SET, 0, 0 } } }, - [BUILD_MAP] = { .nuops = 1, .uops = { { BUILD_MAP, 0, 0 } } }, - [SETUP_ANNOTATIONS] = { .nuops = 1, .uops = { { SETUP_ANNOTATIONS, 0, 0 } } }, - [BUILD_CONST_KEY_MAP] = { .nuops = 1, .uops = { { BUILD_CONST_KEY_MAP, 0, 0 } } }, - [DICT_UPDATE] = { .nuops = 1, .uops = { { DICT_UPDATE, 0, 0 } } }, - [DICT_MERGE] = { .nuops = 1, .uops = { { DICT_MERGE, 0, 0 } } }, - [MAP_ADD] = { .nuops = 1, .uops = { { MAP_ADD, 0, 0 } } }, - [LOAD_SUPER_ATTR_ATTR] = { .nuops = 1, .uops = { { LOAD_SUPER_ATTR_ATTR, 0, 0 } } }, - [LOAD_SUPER_ATTR_METHOD] = { .nuops = 1, .uops = { { LOAD_SUPER_ATTR_METHOD, 0, 0 } } }, - [LOAD_ATTR] = { .nuops = 1, .uops = { { LOAD_ATTR, 0, 0 } } }, - [LOAD_ATTR_INSTANCE_VALUE] = { .nuops = 3, .uops = { { _GUARD_TYPE_VERSION, 2, 1 }, { _CHECK_MANAGED_OBJECT_HAS_VALUES, 0, 0 }, { _LOAD_ATTR_INSTANCE_VALUE, 1, 3 } } }, - [COMPARE_OP] = { .nuops = 1, .uops = { { COMPARE_OP, 0, 0 } } }, - [COMPARE_OP_FLOAT] = { .nuops = 1, .uops = { { COMPARE_OP_FLOAT, 0, 0 } } }, - [COMPARE_OP_INT] = { .nuops = 1, .uops = { { COMPARE_OP_INT, 0, 0 } } }, - [COMPARE_OP_STR] = { .nuops = 1, .uops = { { COMPARE_OP_STR, 0, 0 } } }, - [IS_OP] = { .nuops = 1, .uops = { { IS_OP, 0, 0 } } }, - [CONTAINS_OP] = { .nuops = 1, .uops = { { CONTAINS_OP, 0, 0 } } }, - [CHECK_EG_MATCH] = { .nuops = 1, .uops = { { CHECK_EG_MATCH, 0, 0 } } }, - [CHECK_EXC_MATCH] = { .nuops = 1, .uops = { { CHECK_EXC_MATCH, 0, 0 } } }, - [GET_LEN] = { .nuops = 1, .uops = { { GET_LEN, 0, 0 } } }, - [MATCH_CLASS] = { .nuops = 1, .uops = { { MATCH_CLASS, 0, 0 } } }, - [MATCH_MAPPING] = { .nuops = 1, .uops = { { MATCH_MAPPING, 0, 0 } } }, - [MATCH_SEQUENCE] = { .nuops = 1, .uops = { { MATCH_SEQUENCE, 0, 0 } } }, - [MATCH_KEYS] = { .nuops = 1, .uops = { { MATCH_KEYS, 0, 0 } } }, - [GET_ITER] = { .nuops = 1, .uops = { { GET_ITER, 0, 0 } } }, - [GET_YIELD_FROM_ITER] = { .nuops = 1, .uops = { { GET_YIELD_FROM_ITER, 0, 0 } } }, - [WITH_EXCEPT_START] = { .nuops = 1, .uops = { { WITH_EXCEPT_START, 0, 0 } } }, - [PUSH_EXC_INFO] = { .nuops = 1, .uops = { { PUSH_EXC_INFO, 0, 0 } } }, - [CALL_NO_KW_TYPE_1] = { .nuops = 1, .uops = { { CALL_NO_KW_TYPE_1, 0, 0 } } }, - [CALL_NO_KW_STR_1] = { .nuops = 1, .uops = { { CALL_NO_KW_STR_1, 0, 0 } } }, - [CALL_NO_KW_TUPLE_1] = { .nuops = 1, .uops = { { CALL_NO_KW_TUPLE_1, 0, 0 } } }, - [EXIT_INIT_CHECK] = { .nuops = 1, .uops = { { EXIT_INIT_CHECK, 0, 0 } } }, - [CALL_NO_KW_BUILTIN_O] = { .nuops = 1, .uops = { { CALL_NO_KW_BUILTIN_O, 0, 0 } } }, - [CALL_NO_KW_BUILTIN_FAST] = { .nuops = 1, .uops = { { CALL_NO_KW_BUILTIN_FAST, 0, 0 } } }, - [CALL_NO_KW_LEN] = { .nuops = 1, .uops = { { CALL_NO_KW_LEN, 0, 0 } } }, - [CALL_NO_KW_ISINSTANCE] = { .nuops = 1, .uops = { { CALL_NO_KW_ISINSTANCE, 0, 0 } } }, - [CALL_NO_KW_METHOD_DESCRIPTOR_O] = { .nuops = 1, .uops = { { CALL_NO_KW_METHOD_DESCRIPTOR_O, 0, 0 } } }, - [CALL_NO_KW_METHOD_DESCRIPTOR_NOARGS] = { .nuops = 1, .uops = { { CALL_NO_KW_METHOD_DESCRIPTOR_NOARGS, 0, 0 } } }, - [CALL_NO_KW_METHOD_DESCRIPTOR_FAST] = { .nuops = 1, .uops = { { CALL_NO_KW_METHOD_DESCRIPTOR_FAST, 0, 0 } } }, - [MAKE_FUNCTION] = { .nuops = 1, .uops = { { MAKE_FUNCTION, 0, 0 } } }, - [SET_FUNCTION_ATTRIBUTE] = { .nuops = 1, .uops = { { SET_FUNCTION_ATTRIBUTE, 0, 0 } } }, - [BUILD_SLICE] = { .nuops = 1, .uops = { { BUILD_SLICE, 0, 0 } } }, - [CONVERT_VALUE] = { .nuops = 1, .uops = { { CONVERT_VALUE, 0, 0 } } }, - [FORMAT_SIMPLE] = { .nuops = 1, .uops = { { FORMAT_SIMPLE, 0, 0 } } }, - [FORMAT_WITH_SPEC] = { .nuops = 1, .uops = { { FORMAT_WITH_SPEC, 0, 0 } } }, - [COPY] = { .nuops = 1, .uops = { { COPY, 0, 0 } } }, - [BINARY_OP] = { .nuops = 1, .uops = { { BINARY_OP, 0, 0 } } }, - [SWAP] = { .nuops = 1, .uops = { { SWAP, 0, 0 } } }, + [LOAD_GLOBAL_MODULE] = { .nuops = 2, .uops = { { _GUARD_GLOBALS_VERSION, 1, 1 }, { _LOAD_GLOBAL_MODULE, 1, 3 } } }, + [LOAD_LOCALS] = { .nuops = 1, .uops = { { _LOAD_LOCALS, 0, 0 } } }, + [LOAD_NAME] = { .nuops = 1, .uops = { { _LOAD_NAME, 0, 0 } } }, + [LOAD_SUPER_ATTR_ATTR] = { .nuops = 1, .uops = { { _LOAD_SUPER_ATTR_ATTR, 0, 0 } } }, + [LOAD_SUPER_ATTR_METHOD] = { .nuops = 1, .uops = { { _LOAD_SUPER_ATTR_METHOD, 0, 0 } } }, + [MAKE_CELL] = { .nuops = 1, .uops = { { _MAKE_CELL, 0, 0 } } }, + [MAKE_FUNCTION] = { .nuops = 1, .uops = { { _MAKE_FUNCTION, 0, 0 } } }, + [MAP_ADD] = { .nuops = 1, .uops = { { _MAP_ADD, 0, 0 } } }, + [MATCH_CLASS] = { .nuops = 1, .uops = { { _MATCH_CLASS, 0, 0 } } }, + [MATCH_KEYS] = { .nuops = 1, .uops = { { _MATCH_KEYS, 0, 0 } } }, + [MATCH_MAPPING] = { .nuops = 1, .uops = { { _MATCH_MAPPING, 0, 0 } } }, + [MATCH_SEQUENCE] = { .nuops = 1, .uops = { { _MATCH_SEQUENCE, 0, 0 } } }, + [NOP] = { .nuops = 1, .uops = { { _NOP, 0, 0 } } }, + [POP_EXCEPT] = { .nuops = 1, .uops = { { _POP_EXCEPT, 0, 0 } } }, + [POP_JUMP_IF_FALSE] = { .nuops = 1, .uops = { { _POP_JUMP_IF_FALSE, 9, 1 } } }, + [POP_JUMP_IF_NONE] = { .nuops = 2, .uops = { { _IS_NONE, 0, 0 }, { _POP_JUMP_IF_TRUE, 9, 1 } } }, + [POP_JUMP_IF_NOT_NONE] = { .nuops = 2, .uops = { { _IS_NONE, 0, 0 }, { _POP_JUMP_IF_FALSE, 9, 1 } } }, + [POP_JUMP_IF_TRUE] = { .nuops = 1, .uops = { { _POP_JUMP_IF_TRUE, 9, 1 } } }, + [POP_TOP] = { .nuops = 1, .uops = { { _POP_TOP, 0, 0 } } }, + [PUSH_EXC_INFO] = { .nuops = 1, .uops = { { _PUSH_EXC_INFO, 0, 0 } } }, + [PUSH_NULL] = { .nuops = 1, .uops = { { _PUSH_NULL, 0, 0 } } }, + [RESUME_CHECK] = { .nuops = 1, .uops = { { _RESUME_CHECK, 0, 0 } } }, + [RETURN_CONST] = { .nuops = 2, .uops = { { _LOAD_CONST, 0, 0 }, { _POP_FRAME, 0, 0 } } }, + [RETURN_VALUE] = { .nuops = 1, .uops = { { _POP_FRAME, 0, 0 } } }, + [SETUP_ANNOTATIONS] = { .nuops = 1, .uops = { { _SETUP_ANNOTATIONS, 0, 0 } } }, + [SET_ADD] = { .nuops = 1, .uops = { { _SET_ADD, 0, 0 } } }, + [SET_FUNCTION_ATTRIBUTE] = { .nuops = 1, .uops = { { _SET_FUNCTION_ATTRIBUTE, 0, 0 } } }, + [SET_UPDATE] = { .nuops = 1, .uops = { { _SET_UPDATE, 0, 0 } } }, + [STORE_ATTR] = { .nuops = 1, .uops = { { _STORE_ATTR, 0, 0 } } }, + [STORE_ATTR_INSTANCE_VALUE] = { .nuops = 3, .uops = { { _GUARD_TYPE_VERSION, 2, 1 }, { _GUARD_DORV_VALUES, 0, 0 }, { _STORE_ATTR_INSTANCE_VALUE, 1, 3 } } }, + [STORE_ATTR_SLOT] = { .nuops = 2, .uops = { { _GUARD_TYPE_VERSION, 2, 1 }, { _STORE_ATTR_SLOT, 1, 3 } } }, + [STORE_DEREF] = { .nuops = 1, .uops = { { _STORE_DEREF, 0, 0 } } }, + [STORE_FAST] = { .nuops = 1, .uops = { { _STORE_FAST, 0, 0 } } }, + [STORE_FAST_LOAD_FAST] = { .nuops = 2, .uops = { { _STORE_FAST, 5, 0 }, { _LOAD_FAST, 6, 0 } } }, + [STORE_FAST_STORE_FAST] = { .nuops = 2, .uops = { { _STORE_FAST, 5, 0 }, { _STORE_FAST, 6, 0 } } }, + [STORE_GLOBAL] = { .nuops = 1, .uops = { { _STORE_GLOBAL, 0, 0 } } }, + [STORE_NAME] = { .nuops = 1, .uops = { { _STORE_NAME, 0, 0 } } }, + [STORE_SLICE] = { .nuops = 1, .uops = { { _STORE_SLICE, 0, 0 } } }, + [STORE_SUBSCR] = { .nuops = 1, .uops = { { _STORE_SUBSCR, 0, 0 } } }, + [STORE_SUBSCR_DICT] = { .nuops = 1, .uops = { { _STORE_SUBSCR_DICT, 0, 0 } } }, + [STORE_SUBSCR_LIST_INT] = { .nuops = 1, .uops = { { _STORE_SUBSCR_LIST_INT, 0, 0 } } }, + [SWAP] = { .nuops = 1, .uops = { { _SWAP, 0, 0 } } }, + [TO_BOOL] = { .nuops = 1, .uops = { { _TO_BOOL, 0, 0 } } }, + [TO_BOOL_ALWAYS_TRUE] = { .nuops = 1, .uops = { { _TO_BOOL_ALWAYS_TRUE, 2, 1 } } }, + [TO_BOOL_BOOL] = { .nuops = 1, .uops = { { _TO_BOOL_BOOL, 0, 0 } } }, + [TO_BOOL_INT] = { .nuops = 1, .uops = { { _TO_BOOL_INT, 0, 0 } } }, + [TO_BOOL_LIST] = { .nuops = 1, .uops = { { _TO_BOOL_LIST, 0, 0 } } }, + [TO_BOOL_NONE] = { .nuops = 1, .uops = { { _TO_BOOL_NONE, 0, 0 } } }, + [TO_BOOL_STR] = { .nuops = 1, .uops = { { _TO_BOOL_STR, 0, 0 } } }, + [UNARY_INVERT] = { .nuops = 1, .uops = { { _UNARY_INVERT, 0, 0 } } }, + [UNARY_NEGATIVE] = { .nuops = 1, .uops = { { _UNARY_NEGATIVE, 0, 0 } } }, + [UNARY_NOT] = { .nuops = 1, .uops = { { _UNARY_NOT, 0, 0 } } }, + [UNPACK_EX] = { .nuops = 1, .uops = { { _UNPACK_EX, 0, 0 } } }, + [UNPACK_SEQUENCE] = { .nuops = 1, .uops = { { _UNPACK_SEQUENCE, 0, 0 } } }, + [UNPACK_SEQUENCE_LIST] = { .nuops = 1, .uops = { { _UNPACK_SEQUENCE_LIST, 0, 0 } } }, + [UNPACK_SEQUENCE_TUPLE] = { .nuops = 1, .uops = { { _UNPACK_SEQUENCE_TUPLE, 0, 0 } } }, + [UNPACK_SEQUENCE_TWO_TUPLE] = { .nuops = 1, .uops = { { _UNPACK_SEQUENCE_TWO_TUPLE, 0, 0 } } }, + [WITH_EXCEPT_START] = { .nuops = 1, .uops = { { _WITH_EXCEPT_START, 0, 0 } } }, +}; +#endif // NEED_OPCODE_METADATA + +extern const char *_PyOpcode_OpName[268]; +#ifdef NEED_OPCODE_METADATA +const char *_PyOpcode_OpName[268] = { + [BEFORE_ASYNC_WITH] = "BEFORE_ASYNC_WITH", + [BEFORE_WITH] = "BEFORE_WITH", + [BINARY_OP] = "BINARY_OP", + [BINARY_OP_ADD_FLOAT] = "BINARY_OP_ADD_FLOAT", + [BINARY_OP_ADD_INT] = "BINARY_OP_ADD_INT", + [BINARY_OP_ADD_UNICODE] = "BINARY_OP_ADD_UNICODE", + [BINARY_OP_INPLACE_ADD_UNICODE] = "BINARY_OP_INPLACE_ADD_UNICODE", + [BINARY_OP_MULTIPLY_FLOAT] = "BINARY_OP_MULTIPLY_FLOAT", + [BINARY_OP_MULTIPLY_INT] = "BINARY_OP_MULTIPLY_INT", + [BINARY_OP_SUBTRACT_FLOAT] = "BINARY_OP_SUBTRACT_FLOAT", + [BINARY_OP_SUBTRACT_INT] = "BINARY_OP_SUBTRACT_INT", + [BINARY_SLICE] = "BINARY_SLICE", + [BINARY_SUBSCR] = "BINARY_SUBSCR", + [BINARY_SUBSCR_DICT] = "BINARY_SUBSCR_DICT", + [BINARY_SUBSCR_GETITEM] = "BINARY_SUBSCR_GETITEM", + [BINARY_SUBSCR_LIST_INT] = "BINARY_SUBSCR_LIST_INT", + [BINARY_SUBSCR_STR_INT] = "BINARY_SUBSCR_STR_INT", + [BINARY_SUBSCR_TUPLE_INT] = "BINARY_SUBSCR_TUPLE_INT", + [BUILD_CONST_KEY_MAP] = "BUILD_CONST_KEY_MAP", + [BUILD_LIST] = "BUILD_LIST", + [BUILD_MAP] = "BUILD_MAP", + [BUILD_SET] = "BUILD_SET", + [BUILD_SLICE] = "BUILD_SLICE", + [BUILD_STRING] = "BUILD_STRING", + [BUILD_TUPLE] = "BUILD_TUPLE", + [CACHE] = "CACHE", + [CALL] = "CALL", + [CALL_ALLOC_AND_ENTER_INIT] = "CALL_ALLOC_AND_ENTER_INIT", + [CALL_BOUND_METHOD_EXACT_ARGS] = "CALL_BOUND_METHOD_EXACT_ARGS", + [CALL_BUILTIN_CLASS] = "CALL_BUILTIN_CLASS", + [CALL_BUILTIN_FAST] = "CALL_BUILTIN_FAST", + [CALL_BUILTIN_FAST_WITH_KEYWORDS] = "CALL_BUILTIN_FAST_WITH_KEYWORDS", + [CALL_BUILTIN_O] = "CALL_BUILTIN_O", + [CALL_FUNCTION_EX] = "CALL_FUNCTION_EX", + [CALL_INTRINSIC_1] = "CALL_INTRINSIC_1", + [CALL_INTRINSIC_2] = "CALL_INTRINSIC_2", + [CALL_ISINSTANCE] = "CALL_ISINSTANCE", + [CALL_KW] = "CALL_KW", + [CALL_LEN] = "CALL_LEN", + [CALL_LIST_APPEND] = "CALL_LIST_APPEND", + [CALL_METHOD_DESCRIPTOR_FAST] = "CALL_METHOD_DESCRIPTOR_FAST", + [CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS] = "CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS", + [CALL_METHOD_DESCRIPTOR_NOARGS] = "CALL_METHOD_DESCRIPTOR_NOARGS", + [CALL_METHOD_DESCRIPTOR_O] = "CALL_METHOD_DESCRIPTOR_O", + [CALL_PY_EXACT_ARGS] = "CALL_PY_EXACT_ARGS", + [CALL_PY_WITH_DEFAULTS] = "CALL_PY_WITH_DEFAULTS", + [CALL_STR_1] = "CALL_STR_1", + [CALL_TUPLE_1] = "CALL_TUPLE_1", + [CALL_TYPE_1] = "CALL_TYPE_1", + [CHECK_EG_MATCH] = "CHECK_EG_MATCH", + [CHECK_EXC_MATCH] = "CHECK_EXC_MATCH", + [CLEANUP_THROW] = "CLEANUP_THROW", + [COMPARE_OP] = "COMPARE_OP", + [COMPARE_OP_FLOAT] = "COMPARE_OP_FLOAT", + [COMPARE_OP_INT] = "COMPARE_OP_INT", + [COMPARE_OP_STR] = "COMPARE_OP_STR", + [CONTAINS_OP] = "CONTAINS_OP", + [CONVERT_VALUE] = "CONVERT_VALUE", + [COPY] = "COPY", + [COPY_FREE_VARS] = "COPY_FREE_VARS", + [DELETE_ATTR] = "DELETE_ATTR", + [DELETE_DEREF] = "DELETE_DEREF", + [DELETE_FAST] = "DELETE_FAST", + [DELETE_GLOBAL] = "DELETE_GLOBAL", + [DELETE_NAME] = "DELETE_NAME", + [DELETE_SUBSCR] = "DELETE_SUBSCR", + [DICT_MERGE] = "DICT_MERGE", + [DICT_UPDATE] = "DICT_UPDATE", + [END_ASYNC_FOR] = "END_ASYNC_FOR", + [END_FOR] = "END_FOR", + [END_SEND] = "END_SEND", + [ENTER_EXECUTOR] = "ENTER_EXECUTOR", + [EXIT_INIT_CHECK] = "EXIT_INIT_CHECK", + [EXTENDED_ARG] = "EXTENDED_ARG", + [FORMAT_SIMPLE] = "FORMAT_SIMPLE", + [FORMAT_WITH_SPEC] = "FORMAT_WITH_SPEC", + [FOR_ITER] = "FOR_ITER", + [FOR_ITER_GEN] = "FOR_ITER_GEN", + [FOR_ITER_LIST] = "FOR_ITER_LIST", + [FOR_ITER_RANGE] = "FOR_ITER_RANGE", + [FOR_ITER_TUPLE] = "FOR_ITER_TUPLE", + [GET_AITER] = "GET_AITER", + [GET_ANEXT] = "GET_ANEXT", + [GET_AWAITABLE] = "GET_AWAITABLE", + [GET_ITER] = "GET_ITER", + [GET_LEN] = "GET_LEN", + [GET_YIELD_FROM_ITER] = "GET_YIELD_FROM_ITER", + [IMPORT_FROM] = "IMPORT_FROM", + [IMPORT_NAME] = "IMPORT_NAME", + [INSTRUMENTED_CALL] = "INSTRUMENTED_CALL", + [INSTRUMENTED_CALL_FUNCTION_EX] = "INSTRUMENTED_CALL_FUNCTION_EX", + [INSTRUMENTED_CALL_KW] = "INSTRUMENTED_CALL_KW", + [INSTRUMENTED_END_FOR] = "INSTRUMENTED_END_FOR", + [INSTRUMENTED_END_SEND] = "INSTRUMENTED_END_SEND", + [INSTRUMENTED_FOR_ITER] = "INSTRUMENTED_FOR_ITER", + [INSTRUMENTED_INSTRUCTION] = "INSTRUMENTED_INSTRUCTION", + [INSTRUMENTED_JUMP_BACKWARD] = "INSTRUMENTED_JUMP_BACKWARD", + [INSTRUMENTED_JUMP_FORWARD] = "INSTRUMENTED_JUMP_FORWARD", + [INSTRUMENTED_LINE] = "INSTRUMENTED_LINE", + [INSTRUMENTED_LOAD_SUPER_ATTR] = "INSTRUMENTED_LOAD_SUPER_ATTR", + [INSTRUMENTED_POP_JUMP_IF_FALSE] = "INSTRUMENTED_POP_JUMP_IF_FALSE", + [INSTRUMENTED_POP_JUMP_IF_NONE] = "INSTRUMENTED_POP_JUMP_IF_NONE", + [INSTRUMENTED_POP_JUMP_IF_NOT_NONE] = "INSTRUMENTED_POP_JUMP_IF_NOT_NONE", + [INSTRUMENTED_POP_JUMP_IF_TRUE] = "INSTRUMENTED_POP_JUMP_IF_TRUE", + [INSTRUMENTED_RESUME] = "INSTRUMENTED_RESUME", + [INSTRUMENTED_RETURN_CONST] = "INSTRUMENTED_RETURN_CONST", + [INSTRUMENTED_RETURN_VALUE] = "INSTRUMENTED_RETURN_VALUE", + [INSTRUMENTED_YIELD_VALUE] = "INSTRUMENTED_YIELD_VALUE", + [INTERPRETER_EXIT] = "INTERPRETER_EXIT", + [IS_OP] = "IS_OP", + [JUMP] = "JUMP", + [JUMP_BACKWARD] = "JUMP_BACKWARD", + [JUMP_BACKWARD_NO_INTERRUPT] = "JUMP_BACKWARD_NO_INTERRUPT", + [JUMP_FORWARD] = "JUMP_FORWARD", + [JUMP_NO_INTERRUPT] = "JUMP_NO_INTERRUPT", + [LIST_APPEND] = "LIST_APPEND", + [LIST_EXTEND] = "LIST_EXTEND", + [LOAD_ASSERTION_ERROR] = "LOAD_ASSERTION_ERROR", + [LOAD_ATTR] = "LOAD_ATTR", + [LOAD_ATTR_CLASS] = "LOAD_ATTR_CLASS", + [LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN] = "LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN", + [LOAD_ATTR_INSTANCE_VALUE] = "LOAD_ATTR_INSTANCE_VALUE", + [LOAD_ATTR_METHOD_LAZY_DICT] = "LOAD_ATTR_METHOD_LAZY_DICT", + [LOAD_ATTR_METHOD_NO_DICT] = "LOAD_ATTR_METHOD_NO_DICT", + [LOAD_ATTR_METHOD_WITH_VALUES] = "LOAD_ATTR_METHOD_WITH_VALUES", + [LOAD_ATTR_MODULE] = "LOAD_ATTR_MODULE", + [LOAD_ATTR_NONDESCRIPTOR_NO_DICT] = "LOAD_ATTR_NONDESCRIPTOR_NO_DICT", + [LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES] = "LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES", + [LOAD_ATTR_PROPERTY] = "LOAD_ATTR_PROPERTY", + [LOAD_ATTR_SLOT] = "LOAD_ATTR_SLOT", + [LOAD_ATTR_WITH_HINT] = "LOAD_ATTR_WITH_HINT", + [LOAD_BUILD_CLASS] = "LOAD_BUILD_CLASS", + [LOAD_CLOSURE] = "LOAD_CLOSURE", + [LOAD_CONST] = "LOAD_CONST", + [LOAD_DEREF] = "LOAD_DEREF", + [LOAD_FAST] = "LOAD_FAST", + [LOAD_FAST_AND_CLEAR] = "LOAD_FAST_AND_CLEAR", + [LOAD_FAST_CHECK] = "LOAD_FAST_CHECK", + [LOAD_FAST_LOAD_FAST] = "LOAD_FAST_LOAD_FAST", + [LOAD_FROM_DICT_OR_DEREF] = "LOAD_FROM_DICT_OR_DEREF", + [LOAD_FROM_DICT_OR_GLOBALS] = "LOAD_FROM_DICT_OR_GLOBALS", + [LOAD_GLOBAL] = "LOAD_GLOBAL", + [LOAD_GLOBAL_BUILTIN] = "LOAD_GLOBAL_BUILTIN", + [LOAD_GLOBAL_MODULE] = "LOAD_GLOBAL_MODULE", + [LOAD_LOCALS] = "LOAD_LOCALS", + [LOAD_METHOD] = "LOAD_METHOD", + [LOAD_NAME] = "LOAD_NAME", + [LOAD_SUPER_ATTR] = "LOAD_SUPER_ATTR", + [LOAD_SUPER_ATTR_ATTR] = "LOAD_SUPER_ATTR_ATTR", + [LOAD_SUPER_ATTR_METHOD] = "LOAD_SUPER_ATTR_METHOD", + [LOAD_SUPER_METHOD] = "LOAD_SUPER_METHOD", + [LOAD_ZERO_SUPER_ATTR] = "LOAD_ZERO_SUPER_ATTR", + [LOAD_ZERO_SUPER_METHOD] = "LOAD_ZERO_SUPER_METHOD", + [MAKE_CELL] = "MAKE_CELL", + [MAKE_FUNCTION] = "MAKE_FUNCTION", + [MAP_ADD] = "MAP_ADD", + [MATCH_CLASS] = "MATCH_CLASS", + [MATCH_KEYS] = "MATCH_KEYS", + [MATCH_MAPPING] = "MATCH_MAPPING", + [MATCH_SEQUENCE] = "MATCH_SEQUENCE", + [NOP] = "NOP", + [POP_BLOCK] = "POP_BLOCK", + [POP_EXCEPT] = "POP_EXCEPT", + [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", + [PUSH_EXC_INFO] = "PUSH_EXC_INFO", + [PUSH_NULL] = "PUSH_NULL", + [RAISE_VARARGS] = "RAISE_VARARGS", + [RERAISE] = "RERAISE", + [RESERVED] = "RESERVED", + [RESUME] = "RESUME", + [RESUME_CHECK] = "RESUME_CHECK", + [RETURN_CONST] = "RETURN_CONST", + [RETURN_GENERATOR] = "RETURN_GENERATOR", + [RETURN_VALUE] = "RETURN_VALUE", + [SEND] = "SEND", + [SEND_GEN] = "SEND_GEN", + [SETUP_ANNOTATIONS] = "SETUP_ANNOTATIONS", + [SETUP_CLEANUP] = "SETUP_CLEANUP", + [SETUP_FINALLY] = "SETUP_FINALLY", + [SETUP_WITH] = "SETUP_WITH", + [SET_ADD] = "SET_ADD", + [SET_FUNCTION_ATTRIBUTE] = "SET_FUNCTION_ATTRIBUTE", + [SET_UPDATE] = "SET_UPDATE", + [STORE_ATTR] = "STORE_ATTR", + [STORE_ATTR_INSTANCE_VALUE] = "STORE_ATTR_INSTANCE_VALUE", + [STORE_ATTR_SLOT] = "STORE_ATTR_SLOT", + [STORE_ATTR_WITH_HINT] = "STORE_ATTR_WITH_HINT", + [STORE_DEREF] = "STORE_DEREF", + [STORE_FAST] = "STORE_FAST", + [STORE_FAST_LOAD_FAST] = "STORE_FAST_LOAD_FAST", + [STORE_FAST_MAYBE_NULL] = "STORE_FAST_MAYBE_NULL", + [STORE_FAST_STORE_FAST] = "STORE_FAST_STORE_FAST", + [STORE_GLOBAL] = "STORE_GLOBAL", + [STORE_NAME] = "STORE_NAME", + [STORE_SLICE] = "STORE_SLICE", + [STORE_SUBSCR] = "STORE_SUBSCR", + [STORE_SUBSCR_DICT] = "STORE_SUBSCR_DICT", + [STORE_SUBSCR_LIST_INT] = "STORE_SUBSCR_LIST_INT", + [SWAP] = "SWAP", + [TO_BOOL] = "TO_BOOL", + [TO_BOOL_ALWAYS_TRUE] = "TO_BOOL_ALWAYS_TRUE", + [TO_BOOL_BOOL] = "TO_BOOL_BOOL", + [TO_BOOL_INT] = "TO_BOOL_INT", + [TO_BOOL_LIST] = "TO_BOOL_LIST", + [TO_BOOL_NONE] = "TO_BOOL_NONE", + [TO_BOOL_STR] = "TO_BOOL_STR", + [UNARY_INVERT] = "UNARY_INVERT", + [UNARY_NEGATIVE] = "UNARY_NEGATIVE", + [UNARY_NOT] = "UNARY_NOT", + [UNPACK_EX] = "UNPACK_EX", + [UNPACK_SEQUENCE] = "UNPACK_SEQUENCE", + [UNPACK_SEQUENCE_LIST] = "UNPACK_SEQUENCE_LIST", + [UNPACK_SEQUENCE_TUPLE] = "UNPACK_SEQUENCE_TUPLE", + [UNPACK_SEQUENCE_TWO_TUPLE] = "UNPACK_SEQUENCE_TWO_TUPLE", + [WITH_EXCEPT_START] = "WITH_EXCEPT_START", + [YIELD_VALUE] = "YIELD_VALUE", +}; +#endif + +extern const uint8_t _PyOpcode_Caches[256]; +#ifdef NEED_OPCODE_METADATA +const uint8_t _PyOpcode_Caches[256] = { + [JUMP_BACKWARD] = 1, + [TO_BOOL] = 3, + [BINARY_SUBSCR] = 1, + [STORE_SUBSCR] = 1, + [SEND] = 1, + [UNPACK_SEQUENCE] = 1, + [STORE_ATTR] = 4, + [LOAD_GLOBAL] = 4, + [LOAD_SUPER_ATTR] = 1, + [LOAD_ATTR] = 9, + [COMPARE_OP] = 1, + [POP_JUMP_IF_TRUE] = 1, + [POP_JUMP_IF_FALSE] = 1, + [POP_JUMP_IF_NONE] = 1, + [POP_JUMP_IF_NOT_NONE] = 1, + [FOR_ITER] = 1, + [CALL] = 3, + [BINARY_OP] = 1, +}; +#endif + +extern const uint8_t _PyOpcode_Deopt[256]; +#ifdef NEED_OPCODE_METADATA +const uint8_t _PyOpcode_Deopt[256] = { + [BEFORE_ASYNC_WITH] = BEFORE_ASYNC_WITH, + [BEFORE_WITH] = BEFORE_WITH, + [BINARY_OP] = BINARY_OP, + [BINARY_OP_ADD_FLOAT] = BINARY_OP, + [BINARY_OP_ADD_INT] = BINARY_OP, + [BINARY_OP_ADD_UNICODE] = BINARY_OP, + [BINARY_OP_INPLACE_ADD_UNICODE] = BINARY_OP, + [BINARY_OP_MULTIPLY_FLOAT] = BINARY_OP, + [BINARY_OP_MULTIPLY_INT] = BINARY_OP, + [BINARY_OP_SUBTRACT_FLOAT] = BINARY_OP, + [BINARY_OP_SUBTRACT_INT] = BINARY_OP, + [BINARY_SLICE] = BINARY_SLICE, + [BINARY_SUBSCR] = BINARY_SUBSCR, + [BINARY_SUBSCR_DICT] = BINARY_SUBSCR, + [BINARY_SUBSCR_GETITEM] = BINARY_SUBSCR, + [BINARY_SUBSCR_LIST_INT] = BINARY_SUBSCR, + [BINARY_SUBSCR_STR_INT] = BINARY_SUBSCR, + [BINARY_SUBSCR_TUPLE_INT] = BINARY_SUBSCR, + [BUILD_CONST_KEY_MAP] = BUILD_CONST_KEY_MAP, + [BUILD_LIST] = BUILD_LIST, + [BUILD_MAP] = BUILD_MAP, + [BUILD_SET] = BUILD_SET, + [BUILD_SLICE] = BUILD_SLICE, + [BUILD_STRING] = BUILD_STRING, + [BUILD_TUPLE] = BUILD_TUPLE, + [CACHE] = CACHE, + [CALL] = CALL, + [CALL_ALLOC_AND_ENTER_INIT] = CALL, + [CALL_BOUND_METHOD_EXACT_ARGS] = CALL, + [CALL_BUILTIN_CLASS] = CALL, + [CALL_BUILTIN_FAST] = CALL, + [CALL_BUILTIN_FAST_WITH_KEYWORDS] = CALL, + [CALL_BUILTIN_O] = CALL, + [CALL_FUNCTION_EX] = CALL_FUNCTION_EX, + [CALL_INTRINSIC_1] = CALL_INTRINSIC_1, + [CALL_INTRINSIC_2] = CALL_INTRINSIC_2, + [CALL_ISINSTANCE] = CALL, + [CALL_KW] = CALL_KW, + [CALL_LEN] = CALL, + [CALL_LIST_APPEND] = CALL, + [CALL_METHOD_DESCRIPTOR_FAST] = CALL, + [CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS] = CALL, + [CALL_METHOD_DESCRIPTOR_NOARGS] = CALL, + [CALL_METHOD_DESCRIPTOR_O] = CALL, + [CALL_PY_EXACT_ARGS] = CALL, + [CALL_PY_WITH_DEFAULTS] = CALL, + [CALL_STR_1] = CALL, + [CALL_TUPLE_1] = CALL, + [CALL_TYPE_1] = CALL, + [CHECK_EG_MATCH] = CHECK_EG_MATCH, + [CHECK_EXC_MATCH] = CHECK_EXC_MATCH, + [CLEANUP_THROW] = CLEANUP_THROW, + [COMPARE_OP] = COMPARE_OP, + [COMPARE_OP_FLOAT] = COMPARE_OP, + [COMPARE_OP_INT] = COMPARE_OP, + [COMPARE_OP_STR] = COMPARE_OP, + [CONTAINS_OP] = CONTAINS_OP, + [CONVERT_VALUE] = CONVERT_VALUE, + [COPY] = COPY, + [COPY_FREE_VARS] = COPY_FREE_VARS, + [DELETE_ATTR] = DELETE_ATTR, + [DELETE_DEREF] = DELETE_DEREF, + [DELETE_FAST] = DELETE_FAST, + [DELETE_GLOBAL] = DELETE_GLOBAL, + [DELETE_NAME] = DELETE_NAME, + [DELETE_SUBSCR] = DELETE_SUBSCR, + [DICT_MERGE] = DICT_MERGE, + [DICT_UPDATE] = DICT_UPDATE, + [END_ASYNC_FOR] = END_ASYNC_FOR, + [END_FOR] = END_FOR, + [END_SEND] = END_SEND, + [ENTER_EXECUTOR] = ENTER_EXECUTOR, + [EXIT_INIT_CHECK] = EXIT_INIT_CHECK, + [EXTENDED_ARG] = EXTENDED_ARG, + [FORMAT_SIMPLE] = FORMAT_SIMPLE, + [FORMAT_WITH_SPEC] = FORMAT_WITH_SPEC, + [FOR_ITER] = FOR_ITER, + [FOR_ITER_GEN] = FOR_ITER, + [FOR_ITER_LIST] = FOR_ITER, + [FOR_ITER_RANGE] = FOR_ITER, + [FOR_ITER_TUPLE] = FOR_ITER, + [GET_AITER] = GET_AITER, + [GET_ANEXT] = GET_ANEXT, + [GET_AWAITABLE] = GET_AWAITABLE, + [GET_ITER] = GET_ITER, + [GET_LEN] = GET_LEN, + [GET_YIELD_FROM_ITER] = GET_YIELD_FROM_ITER, + [IMPORT_FROM] = IMPORT_FROM, + [IMPORT_NAME] = IMPORT_NAME, + [INSTRUMENTED_CALL] = INSTRUMENTED_CALL, + [INSTRUMENTED_CALL_FUNCTION_EX] = INSTRUMENTED_CALL_FUNCTION_EX, + [INSTRUMENTED_CALL_KW] = INSTRUMENTED_CALL_KW, + [INSTRUMENTED_END_FOR] = INSTRUMENTED_END_FOR, + [INSTRUMENTED_END_SEND] = INSTRUMENTED_END_SEND, + [INSTRUMENTED_FOR_ITER] = INSTRUMENTED_FOR_ITER, + [INSTRUMENTED_INSTRUCTION] = INSTRUMENTED_INSTRUCTION, + [INSTRUMENTED_JUMP_BACKWARD] = INSTRUMENTED_JUMP_BACKWARD, + [INSTRUMENTED_JUMP_FORWARD] = INSTRUMENTED_JUMP_FORWARD, + [INSTRUMENTED_LINE] = INSTRUMENTED_LINE, + [INSTRUMENTED_LOAD_SUPER_ATTR] = INSTRUMENTED_LOAD_SUPER_ATTR, + [INSTRUMENTED_POP_JUMP_IF_FALSE] = INSTRUMENTED_POP_JUMP_IF_FALSE, + [INSTRUMENTED_POP_JUMP_IF_NONE] = INSTRUMENTED_POP_JUMP_IF_NONE, + [INSTRUMENTED_POP_JUMP_IF_NOT_NONE] = INSTRUMENTED_POP_JUMP_IF_NOT_NONE, + [INSTRUMENTED_POP_JUMP_IF_TRUE] = INSTRUMENTED_POP_JUMP_IF_TRUE, + [INSTRUMENTED_RESUME] = INSTRUMENTED_RESUME, + [INSTRUMENTED_RETURN_CONST] = INSTRUMENTED_RETURN_CONST, + [INSTRUMENTED_RETURN_VALUE] = INSTRUMENTED_RETURN_VALUE, + [INSTRUMENTED_YIELD_VALUE] = INSTRUMENTED_YIELD_VALUE, + [INTERPRETER_EXIT] = INTERPRETER_EXIT, + [IS_OP] = IS_OP, + [JUMP_BACKWARD] = JUMP_BACKWARD, + [JUMP_BACKWARD_NO_INTERRUPT] = JUMP_BACKWARD_NO_INTERRUPT, + [JUMP_FORWARD] = JUMP_FORWARD, + [LIST_APPEND] = LIST_APPEND, + [LIST_EXTEND] = LIST_EXTEND, + [LOAD_ASSERTION_ERROR] = LOAD_ASSERTION_ERROR, + [LOAD_ATTR] = 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, + [LOAD_ATTR_METHOD_WITH_VALUES] = LOAD_ATTR, + [LOAD_ATTR_MODULE] = LOAD_ATTR, + [LOAD_ATTR_NONDESCRIPTOR_NO_DICT] = LOAD_ATTR, + [LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES] = LOAD_ATTR, + [LOAD_ATTR_PROPERTY] = LOAD_ATTR, + [LOAD_ATTR_SLOT] = LOAD_ATTR, + [LOAD_ATTR_WITH_HINT] = LOAD_ATTR, + [LOAD_BUILD_CLASS] = LOAD_BUILD_CLASS, + [LOAD_CONST] = LOAD_CONST, + [LOAD_DEREF] = LOAD_DEREF, + [LOAD_FAST] = LOAD_FAST, + [LOAD_FAST_AND_CLEAR] = LOAD_FAST_AND_CLEAR, + [LOAD_FAST_CHECK] = LOAD_FAST_CHECK, + [LOAD_FAST_LOAD_FAST] = LOAD_FAST_LOAD_FAST, + [LOAD_FROM_DICT_OR_DEREF] = LOAD_FROM_DICT_OR_DEREF, + [LOAD_FROM_DICT_OR_GLOBALS] = LOAD_FROM_DICT_OR_GLOBALS, + [LOAD_GLOBAL] = LOAD_GLOBAL, + [LOAD_GLOBAL_BUILTIN] = LOAD_GLOBAL, + [LOAD_GLOBAL_MODULE] = LOAD_GLOBAL, + [LOAD_LOCALS] = LOAD_LOCALS, + [LOAD_NAME] = LOAD_NAME, + [LOAD_SUPER_ATTR] = LOAD_SUPER_ATTR, + [LOAD_SUPER_ATTR_ATTR] = LOAD_SUPER_ATTR, + [LOAD_SUPER_ATTR_METHOD] = LOAD_SUPER_ATTR, + [MAKE_CELL] = MAKE_CELL, + [MAKE_FUNCTION] = MAKE_FUNCTION, + [MAP_ADD] = MAP_ADD, + [MATCH_CLASS] = MATCH_CLASS, + [MATCH_KEYS] = MATCH_KEYS, + [MATCH_MAPPING] = MATCH_MAPPING, + [MATCH_SEQUENCE] = MATCH_SEQUENCE, + [NOP] = NOP, + [POP_EXCEPT] = POP_EXCEPT, + [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, + [PUSH_EXC_INFO] = PUSH_EXC_INFO, + [PUSH_NULL] = PUSH_NULL, + [RAISE_VARARGS] = RAISE_VARARGS, + [RERAISE] = RERAISE, + [RESERVED] = RESERVED, + [RESUME] = RESUME, + [RESUME_CHECK] = RESUME, + [RETURN_CONST] = RETURN_CONST, + [RETURN_GENERATOR] = RETURN_GENERATOR, + [RETURN_VALUE] = RETURN_VALUE, + [SEND] = SEND, + [SEND_GEN] = SEND, + [SETUP_ANNOTATIONS] = SETUP_ANNOTATIONS, + [SET_ADD] = SET_ADD, + [SET_FUNCTION_ATTRIBUTE] = SET_FUNCTION_ATTRIBUTE, + [SET_UPDATE] = SET_UPDATE, + [STORE_ATTR] = STORE_ATTR, + [STORE_ATTR_INSTANCE_VALUE] = STORE_ATTR, + [STORE_ATTR_SLOT] = STORE_ATTR, + [STORE_ATTR_WITH_HINT] = STORE_ATTR, + [STORE_DEREF] = STORE_DEREF, + [STORE_FAST] = STORE_FAST, + [STORE_FAST_LOAD_FAST] = STORE_FAST_LOAD_FAST, + [STORE_FAST_STORE_FAST] = STORE_FAST_STORE_FAST, + [STORE_GLOBAL] = STORE_GLOBAL, + [STORE_NAME] = STORE_NAME, + [STORE_SLICE] = STORE_SLICE, + [STORE_SUBSCR] = STORE_SUBSCR, + [STORE_SUBSCR_DICT] = STORE_SUBSCR, + [STORE_SUBSCR_LIST_INT] = STORE_SUBSCR, + [SWAP] = SWAP, + [TO_BOOL] = TO_BOOL, + [TO_BOOL_ALWAYS_TRUE] = TO_BOOL, + [TO_BOOL_BOOL] = TO_BOOL, + [TO_BOOL_INT] = TO_BOOL, + [TO_BOOL_LIST] = TO_BOOL, + [TO_BOOL_NONE] = TO_BOOL, + [TO_BOOL_STR] = TO_BOOL, + [UNARY_INVERT] = UNARY_INVERT, + [UNARY_NEGATIVE] = UNARY_NEGATIVE, + [UNARY_NOT] = UNARY_NOT, + [UNPACK_EX] = UNPACK_EX, + [UNPACK_SEQUENCE] = UNPACK_SEQUENCE, + [UNPACK_SEQUENCE_LIST] = UNPACK_SEQUENCE, + [UNPACK_SEQUENCE_TUPLE] = UNPACK_SEQUENCE, + [UNPACK_SEQUENCE_TWO_TUPLE] = UNPACK_SEQUENCE, + [WITH_EXCEPT_START] = WITH_EXCEPT_START, + [YIELD_VALUE] = YIELD_VALUE, +}; + +#endif // NEED_OPCODE_METADATA + +#define EXTRA_CASES \ + case 119: \ + case 120: \ + case 121: \ + case 122: \ + case 123: \ + case 124: \ + case 125: \ + case 126: \ + case 127: \ + case 128: \ + case 129: \ + case 130: \ + case 131: \ + case 132: \ + case 133: \ + case 134: \ + case 135: \ + case 136: \ + case 137: \ + case 138: \ + case 139: \ + case 140: \ + case 141: \ + case 142: \ + case 143: \ + case 144: \ + case 145: \ + case 146: \ + case 147: \ + case 148: \ + case 219: \ + case 220: \ + case 221: \ + case 222: \ + case 223: \ + case 224: \ + case 225: \ + case 226: \ + case 227: \ + case 228: \ + case 229: \ + case 230: \ + case 231: \ + case 232: \ + case 233: \ + case 234: \ + case 235: \ + case 255: \ + ; +struct pseudo_targets { + uint8_t targets[3]; }; -const char * const _PyOpcode_uop_name[OPCODE_UOP_NAME_SIZE] = { - [EXIT_TRACE] = "EXIT_TRACE", - [SAVE_IP] = "SAVE_IP", - [_GUARD_BOTH_INT] = "_GUARD_BOTH_INT", - [_BINARY_OP_MULTIPLY_INT] = "_BINARY_OP_MULTIPLY_INT", - [_BINARY_OP_ADD_INT] = "_BINARY_OP_ADD_INT", - [_BINARY_OP_SUBTRACT_INT] = "_BINARY_OP_SUBTRACT_INT", - [_GUARD_BOTH_FLOAT] = "_GUARD_BOTH_FLOAT", - [_BINARY_OP_MULTIPLY_FLOAT] = "_BINARY_OP_MULTIPLY_FLOAT", - [_BINARY_OP_ADD_FLOAT] = "_BINARY_OP_ADD_FLOAT", - [_BINARY_OP_SUBTRACT_FLOAT] = "_BINARY_OP_SUBTRACT_FLOAT", - [_GUARD_BOTH_UNICODE] = "_GUARD_BOTH_UNICODE", - [_BINARY_OP_ADD_UNICODE] = "_BINARY_OP_ADD_UNICODE", - [_LOAD_LOCALS] = "_LOAD_LOCALS", - [_LOAD_FROM_DICT_OR_GLOBALS] = "_LOAD_FROM_DICT_OR_GLOBALS", - [_GUARD_GLOBALS_VERSION] = "_GUARD_GLOBALS_VERSION", - [_GUARD_BUILTINS_VERSION] = "_GUARD_BUILTINS_VERSION", - [_LOAD_GLOBAL_MODULE] = "_LOAD_GLOBAL_MODULE", - [_LOAD_GLOBAL_BUILTINS] = "_LOAD_GLOBAL_BUILTINS", - [_GUARD_TYPE_VERSION] = "_GUARD_TYPE_VERSION", - [_CHECK_MANAGED_OBJECT_HAS_VALUES] = "_CHECK_MANAGED_OBJECT_HAS_VALUES", - [_LOAD_ATTR_INSTANCE_VALUE] = "_LOAD_ATTR_INSTANCE_VALUE", - [IS_NONE] = "IS_NONE", - [_ITER_CHECK_LIST] = "_ITER_CHECK_LIST", - [_IS_ITER_EXHAUSTED_LIST] = "_IS_ITER_EXHAUSTED_LIST", - [_ITER_NEXT_LIST] = "_ITER_NEXT_LIST", - [_ITER_CHECK_TUPLE] = "_ITER_CHECK_TUPLE", - [_IS_ITER_EXHAUSTED_TUPLE] = "_IS_ITER_EXHAUSTED_TUPLE", - [_ITER_NEXT_TUPLE] = "_ITER_NEXT_TUPLE", - [_ITER_CHECK_RANGE] = "_ITER_CHECK_RANGE", - [_IS_ITER_EXHAUSTED_RANGE] = "_IS_ITER_EXHAUSTED_RANGE", - [_ITER_NEXT_RANGE] = "_ITER_NEXT_RANGE", - [_POP_JUMP_IF_FALSE] = "_POP_JUMP_IF_FALSE", - [_POP_JUMP_IF_TRUE] = "_POP_JUMP_IF_TRUE", - [JUMP_TO_TOP] = "JUMP_TO_TOP", +extern const struct pseudo_targets _PyOpcode_PseudoTargets[12]; +#ifdef NEED_OPCODE_METADATA +const struct pseudo_targets _PyOpcode_PseudoTargets[12] = { + [LOAD_CLOSURE-256] = { { LOAD_FAST, 0, 0 } }, + [STORE_FAST_MAYBE_NULL-256] = { { STORE_FAST, 0, 0 } }, + [LOAD_SUPER_METHOD-256] = { { LOAD_SUPER_ATTR, 0, 0 } }, + [LOAD_ZERO_SUPER_METHOD-256] = { { LOAD_SUPER_ATTR, 0, 0 } }, + [LOAD_ZERO_SUPER_ATTR-256] = { { LOAD_SUPER_ATTR, 0, 0 } }, + [LOAD_METHOD-256] = { { LOAD_ATTR, 0, 0 } }, + [JUMP-256] = { { JUMP_FORWARD, JUMP_BACKWARD, 0 } }, + [JUMP_NO_INTERRUPT-256] = { { JUMP_FORWARD, JUMP_BACKWARD_NO_INTERRUPT, 0 } }, + [SETUP_FINALLY-256] = { { NOP, 0, 0 } }, + [SETUP_CLEANUP-256] = { { NOP, 0, 0 } }, + [SETUP_WITH-256] = { { NOP, 0, 0 } }, + [POP_BLOCK-256] = { { NOP, 0, 0 } }, }; + #endif // NEED_OPCODE_METADATA +static inline bool +is_pseudo_target(int pseudo, int target) { + if (pseudo < 256 || pseudo >= 268) { + return false; + } + for (int i = 0; _PyOpcode_PseudoTargets[pseudo-256].targets[i]; i++) { + if (_PyOpcode_PseudoTargets[pseudo-256].targets[i] == target) return true; + } + return false; +} + + +#ifdef __cplusplus +} +#endif +#endif /* !Py_CORE_OPCODE_METADATA_H */ diff --git a/Include/internal/pycore_opcode_utils.h b/Include/internal/pycore_opcode_utils.h index 50ff2af38d2cbe..208bfb2f75308b 100644 --- a/Include/internal/pycore_opcode_utils.h +++ b/Include/internal/pycore_opcode_utils.h @@ -8,8 +8,7 @@ extern "C" { # error "this header requires Py_BUILD_CORE define" #endif -#include "pycore_opcode.h" // _PyOpcode_Jump - +#include "opcode_ids.h" #define MAX_REAL_OPCODE 254 @@ -59,6 +58,14 @@ extern "C" { #define MAKE_FUNCTION_ANNOTATIONS 0x04 #define MAKE_FUNCTION_CLOSURE 0x08 +/* Values used in the oparg for RESUME */ +#define RESUME_AT_FUNC_START 0 +#define RESUME_AFTER_YIELD 1 +#define RESUME_AFTER_YIELD_FROM 2 +#define RESUME_AFTER_AWAIT 3 + +#define RESUME_OPARG_LOCATION_MASK 0x3 +#define RESUME_OPARG_DEPTH1_MASK 0x4 #ifdef __cplusplus } diff --git a/Include/internal/pycore_optimizer.h b/Include/internal/pycore_optimizer.h new file mode 100644 index 00000000000000..b052460b44b791 --- /dev/null +++ b/Include/internal/pycore_optimizer.h @@ -0,0 +1,25 @@ +#ifndef Py_INTERNAL_OPTIMIZER_H +#define Py_INTERNAL_OPTIMIZER_H +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef Py_BUILD_CORE +# error "this header requires Py_BUILD_CORE define" +#endif + +#include "pycore_uops.h" // _PyUOpInstruction + +int _Py_uop_analyze_and_optimize(PyCodeObject *code, + _PyUOpInstruction *trace, int trace_len, int curr_stackentries); + +extern PyTypeObject _PyCounterExecutor_Type; +extern PyTypeObject _PyCounterOptimizer_Type; +extern PyTypeObject _PyDefaultOptimizer_Type; +extern PyTypeObject _PyUOpExecutor_Type; +extern PyTypeObject _PyUOpOptimizer_Type; + +#ifdef __cplusplus +} +#endif +#endif /* !Py_INTERNAL_OPTIMIZER_H */ diff --git a/Include/internal/pycore_parking_lot.h b/Include/internal/pycore_parking_lot.h new file mode 100644 index 00000000000000..f444da730055e8 --- /dev/null +++ b/Include/internal/pycore_parking_lot.h @@ -0,0 +1,99 @@ +// ParkingLot is an internal API for building efficient synchronization +// primitives like mutexes and events. +// +// The API and name is inspired by WebKit's WTF::ParkingLot, which in turn +// is inspired Linux's futex API. +// See https://webkit.org/blog/6161/locking-in-webkit/. +// +// The core functionality is an atomic "compare-and-sleep" operation along with +// an atomic "wake-up" operation. + +#ifndef Py_INTERNAL_PARKING_LOT_H +#define Py_INTERNAL_PARKING_LOT_H +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef Py_BUILD_CORE +# error "this header requires Py_BUILD_CORE define" +#endif + +#include "pycore_time.h" // _PyTime_t + + +enum { + // The thread was unparked by another thread. + Py_PARK_OK = 0, + + // The value of `address` did not match `expected`. + Py_PARK_AGAIN = -1, + + // The thread was unparked due to a timeout. + Py_PARK_TIMEOUT = -2, + + // The thread was interrupted by a signal. + Py_PARK_INTR = -3, +}; + +// Checks that `*address == *expected` and puts the thread to sleep until an +// unpark operation is called on the same `address`. Otherwise, the function +// returns `Py_PARK_AGAIN`. The comparison behaves like memcmp, but is +// performed atomically with respect to unpark operations. +// +// The `address_size` argument is the size of the data pointed to by the +// `address` and `expected` pointers (i.e., sizeof(*address)). It must be +// 1, 2, 4, or 8. +// +// The `timeout_ns` argument specifies the maximum amount of time to wait, with +// -1 indicating an infinite wait. +// +// `park_arg`, which can be NULL, is passed to the unpark operation. +// +// If `detach` is true, then the thread will detach/release the GIL while +// waiting. +// +// Example usage: +// +// if (_Py_atomic_compare_exchange_uint8(address, &expected, new_value)) { +// int res = _PyParkingLot_Park(address, &new_value, sizeof(*address), +// timeout_ns, NULL, 1); +// ... +// } +PyAPI_FUNC(int) +_PyParkingLot_Park(const void *address, const void *expected, + size_t address_size, _PyTime_t timeout_ns, + void *park_arg, int detach); + +// Callback for _PyParkingLot_Unpark: +// +// `arg` is the data of the same name provided to the _PyParkingLot_Unpark() +// call. +// `park_arg` is the data provided to _PyParkingLot_Park() call or NULL if +// no waiting thread was found. +// `has_more_waiters` is true if there are more threads waiting on the same +// address. May be true in cases where threads are waiting on a different +// address that map to the same internal bucket. +typedef void _Py_unpark_fn_t(void *arg, void *park_arg, int has_more_waiters); + +// Unparks a single thread waiting on `address`. +// +// Note that fn() is called regardless of whether a thread was unparked. If +// no threads are waiting on `address` then the `park_arg` argument to fn() +// will be NULL. +// +// Example usage: +// void callback(void *arg, void *park_arg, int has_more_waiters); +// _PyParkingLot_Unpark(address, &callback, arg); +PyAPI_FUNC(void) +_PyParkingLot_Unpark(const void *address, _Py_unpark_fn_t *fn, void *arg); + +// Unparks all threads waiting on `address`. +PyAPI_FUNC(void) _PyParkingLot_UnparkAll(const void *address); + +// Resets the parking lot state after a fork. Forgets all parked threads. +PyAPI_FUNC(void) _PyParkingLot_AfterFork(void); + +#ifdef __cplusplus +} +#endif +#endif /* !Py_INTERNAL_PARKING_LOT_H */ diff --git a/Include/internal/pycore_parser.h b/Include/internal/pycore_parser.h index dd51b92801aebf..067b34c12c4e7f 100644 --- a/Include/internal/pycore_parser.h +++ b/Include/internal/pycore_parser.h @@ -58,7 +58,17 @@ extern struct _mod* _PyParser_ASTFromFile( PyCompilerFlags *flags, int *errcode, PyArena *arena); - +extern struct _mod* _PyParser_InteractiveASTFromFile( + FILE *fp, + PyObject *filename_ob, + const char *enc, + int mode, + const char *ps1, + const char *ps2, + PyCompilerFlags *flags, + int *errcode, + PyObject **interactive_src, + PyArena *arena); #ifdef __cplusplus } diff --git a/Include/internal/pycore_pathconfig.h b/Include/internal/pycore_pathconfig.h index 729f3e09ce1ca4..a1ce1b19a00283 100644 --- a/Include/internal/pycore_pathconfig.h +++ b/Include/internal/pycore_pathconfig.h @@ -10,6 +10,7 @@ extern "C" { // Export for '_testinternalcapi' shared extension PyAPI_FUNC(void) _PyPathConfig_ClearGlobal(void); + extern PyStatus _PyPathConfig_ReadGlobal(PyConfig *config); extern PyStatus _PyPathConfig_UpdateGlobal(const PyConfig *config); extern const wchar_t * _PyPathConfig_GetGlobalModuleSearchPath(void); diff --git a/Include/internal/pycore_pyarena.h b/Include/internal/pycore_pyarena.h index 08262fba2daeee..1f07479fb2ca27 100644 --- a/Include/internal/pycore_pyarena.h +++ b/Include/internal/pycore_pyarena.h @@ -1,7 +1,4 @@ -/* An arena-like memory interface for the compiler. - * - * Export symbols for test_peg_generator. - */ +// An arena-like memory interface for the compiler. #ifndef Py_INTERNAL_PYARENA_H #define Py_INTERNAL_PYARENA_H @@ -15,49 +12,54 @@ extern "C" { typedef struct _arena PyArena; -/* _PyArena_New() and _PyArena_Free() create a new arena and free it, - respectively. Once an arena has been created, it can be used - to allocate memory via _PyArena_Malloc(). Pointers to PyObject can - also be registered with the arena via _PyArena_AddPyObject(), and the - arena will ensure that the PyObjects stay alive at least until - _PyArena_Free() is called. When an arena is freed, all the memory it - allocated is freed, the arena releases internal references to registered - PyObject*, and none of its pointers are valid. - XXX (tim) What does "none of its pointers are valid" mean? Does it - XXX mean that pointers previously obtained via _PyArena_Malloc() are - XXX no longer valid? (That's clearly true, but not sure that's what - XXX the text is trying to say.) - - _PyArena_New() returns an arena pointer. On error, it - returns a negative number and sets an exception. - XXX (tim): Not true. On error, _PyArena_New() actually returns NULL, - XXX and looks like it may or may not set an exception (e.g., if the - XXX internal PyList_New(0) returns NULL, _PyArena_New() passes that on - XXX and an exception is set; OTOH, if the internal - XXX block_new(DEFAULT_BLOCK_SIZE) returns NULL, that's passed on but - XXX an exception is not set in that case). -*/ +// _PyArena_New() and _PyArena_Free() create a new arena and free it, +// respectively. Once an arena has been created, it can be used +// to allocate memory via _PyArena_Malloc(). Pointers to PyObject can +// also be registered with the arena via _PyArena_AddPyObject(), and the +// arena will ensure that the PyObjects stay alive at least until +// _PyArena_Free() is called. When an arena is freed, all the memory it +// allocated is freed, the arena releases internal references to registered +// PyObject*, and none of its pointers are valid. +// XXX (tim) What does "none of its pointers are valid" mean? Does it +// XXX mean that pointers previously obtained via _PyArena_Malloc() are +// XXX no longer valid? (That's clearly true, but not sure that's what +// XXX the text is trying to say.) +// +// _PyArena_New() returns an arena pointer. On error, it +// returns a negative number and sets an exception. +// XXX (tim): Not true. On error, _PyArena_New() actually returns NULL, +// XXX and looks like it may or may not set an exception (e.g., if the +// XXX internal PyList_New(0) returns NULL, _PyArena_New() passes that on +// XXX and an exception is set; OTOH, if the internal +// XXX block_new(DEFAULT_BLOCK_SIZE) returns NULL, that's passed on but +// XXX an exception is not set in that case). +// +// Export for test_peg_generator PyAPI_FUNC(PyArena*) _PyArena_New(void); + +// Export for test_peg_generator PyAPI_FUNC(void) _PyArena_Free(PyArena *); -/* Mostly like malloc(), return the address of a block of memory spanning - * `size` bytes, or return NULL (without setting an exception) if enough - * new memory can't be obtained. Unlike malloc(0), _PyArena_Malloc() with - * size=0 does not guarantee to return a unique pointer (the pointer - * returned may equal one or more other pointers obtained from - * _PyArena_Malloc()). - * Note that pointers obtained via _PyArena_Malloc() must never be passed to - * the system free() or realloc(), or to any of Python's similar memory- - * management functions. _PyArena_Malloc()-obtained pointers remain valid - * until _PyArena_Free(ar) is called, at which point all pointers obtained - * from the arena `ar` become invalid simultaneously. - */ +// Mostly like malloc(), return the address of a block of memory spanning +// `size` bytes, or return NULL (without setting an exception) if enough +// new memory can't be obtained. Unlike malloc(0), _PyArena_Malloc() with +// size=0 does not guarantee to return a unique pointer (the pointer +// returned may equal one or more other pointers obtained from +// _PyArena_Malloc()). +// Note that pointers obtained via _PyArena_Malloc() must never be passed to +// the system free() or realloc(), or to any of Python's similar memory- +// management functions. _PyArena_Malloc()-obtained pointers remain valid +// until _PyArena_Free(ar) is called, at which point all pointers obtained +// from the arena `ar` become invalid simultaneously. +// +// Export for test_peg_generator PyAPI_FUNC(void*) _PyArena_Malloc(PyArena *, size_t size); -/* This routine isn't a proper arena allocation routine. It takes - * a PyObject* and records it so that it can be DECREFed when the - * arena is freed. - */ +// This routine isn't a proper arena allocation routine. It takes +// a PyObject* and records it so that it can be DECREFed when the +// arena is freed. +// +// Export for test_peg_generator PyAPI_FUNC(int) _PyArena_AddPyObject(PyArena *, PyObject *); #ifdef __cplusplus diff --git a/Include/internal/pycore_pybuffer.h b/Include/internal/pycore_pybuffer.h new file mode 100644 index 00000000000000..3cbc290b2ea3ee --- /dev/null +++ b/Include/internal/pycore_pybuffer.h @@ -0,0 +1,21 @@ +#ifndef Py_INTERNAL_PYBUFFER_H +#define Py_INTERNAL_PYBUFFER_H +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef Py_BUILD_CORE +# error "this header requires Py_BUILD_CORE define" +#endif + + +// Exported for the _xxinterpchannels module. +PyAPI_FUNC(int) _PyBuffer_ReleaseInInterpreter( + PyInterpreterState *interp, Py_buffer *view); +PyAPI_FUNC(int) _PyBuffer_ReleaseInInterpreterAndRawFree( + PyInterpreterState *interp, Py_buffer *view); + +#ifdef __cplusplus +} +#endif +#endif /* !Py_INTERNAL_PYBUFFER_H */ diff --git a/Include/internal/pycore_pyerrors.h b/Include/internal/pycore_pyerrors.h index 45929f40a05496..0f16fb894d17e1 100644 --- a/Include/internal/pycore_pyerrors.h +++ b/Include/internal/pycore_pyerrors.h @@ -16,6 +16,10 @@ extern PyObject* _PyErr_GetHandledException(PyThreadState *); extern void _PyErr_SetHandledException(PyThreadState *, PyObject *); extern void _PyErr_GetExcInfo(PyThreadState *, PyObject **, PyObject **, PyObject **); +// Export for '_testinternalcapi' shared extension +PyAPI_FUNC(void) _PyErr_SetKeyError(PyObject *); + + // Like PyErr_Format(), but saves current exception as __context__ and // __cause__. // Export for '_sqlite3' shared extension. @@ -150,14 +154,22 @@ extern PyObject* _PyExc_PrepReraiseStar( extern int _PyErr_CheckSignalsTstate(PyThreadState *tstate); extern void _Py_DumpExtensionModules(int fd, PyInterpreterState *interp); - +extern PyObject* _Py_CalculateSuggestions(PyObject *dir, PyObject *name); extern PyObject* _Py_Offer_Suggestions(PyObject* exception); + // Export for '_testinternalcapi' shared extension PyAPI_FUNC(Py_ssize_t) _Py_UTF8_Edit_Cost(PyObject *str_a, PyObject *str_b, Py_ssize_t max_cost); void _PyErr_FormatNote(const char *format, ...); +/* Context manipulation (PEP 3134) */ + +Py_DEPRECATED(3.12) extern void _PyErr_ChainExceptions(PyObject *, PyObject *, PyObject *); + +// Export for '_zoneinfo' shared extension +PyAPI_FUNC(void) _PyErr_ChainExceptions1(PyObject *); + #ifdef __cplusplus } #endif diff --git a/Include/internal/pycore_pyhash.h b/Include/internal/pycore_pyhash.h index da9abd28b499a2..0ce08900e96f0b 100644 --- a/Include/internal/pycore_pyhash.h +++ b/Include/internal/pycore_pyhash.h @@ -5,32 +5,24 @@ # error "this header requires Py_BUILD_CORE define" #endif -/* Helpers for hash functions */ -extern Py_hash_t _Py_HashDouble(PyObject *, double); -// _decimal shared extensions uses _Py_HashPointer() -PyAPI_FUNC(Py_hash_t) _Py_HashPointer(const void*); -// Similar to _Py_HashPointer(), but don't replace -1 with -2 -extern Py_hash_t _Py_HashPointerRaw(const void*); -// _datetime shared extension uses _Py_HashBytes() +// Similar to Py_HashPointer(), but don't replace -1 with -2. +static inline Py_hash_t +_Py_HashPointerRaw(const void *ptr) +{ + uintptr_t x = (uintptr_t)ptr; + Py_BUILD_ASSERT(sizeof(x) == sizeof(ptr)); + + // Bottom 3 or 4 bits are likely to be 0; rotate x by 4 to the right + // to avoid excessive hash collisions for dicts and sets. + x = (x >> 4) | (x << (8 * sizeof(uintptr_t) - 4)); + + Py_BUILD_ASSERT(sizeof(x) == sizeof(Py_hash_t)); + return (Py_hash_t)x; +} + +// Export for '_datetime' shared extension PyAPI_FUNC(Py_hash_t) _Py_HashBytes(const void*, Py_ssize_t); -/* Prime multiplier used in string and various other hashes. */ -#define _PyHASH_MULTIPLIER 1000003UL /* 0xf4243 */ - -/* Parameters used for the numeric hash implementation. See notes for - _Py_HashDouble in Python/pyhash.c. Numeric hashes are based on - reduction modulo the prime 2**_PyHASH_BITS - 1. */ - -#if SIZEOF_VOID_P >= 8 -# define _PyHASH_BITS 61 -#else -# define _PyHASH_BITS 31 -#endif - -#define _PyHASH_MODULUS (((size_t)1 << _PyHASH_BITS) - 1) -#define _PyHASH_INF 314159 -#define _PyHASH_IMAG _PyHASH_MULTIPLIER - /* Hash secret * * memory layout on 64 bit systems diff --git a/Include/internal/pycore_pylifecycle.h b/Include/internal/pycore_pylifecycle.h index b4d5b1f1239e1d..c675098685764c 100644 --- a/Include/internal/pycore_pylifecycle.h +++ b/Include/internal/pycore_pylifecycle.h @@ -40,7 +40,6 @@ extern void _PySys_FiniTypes(PyInterpreterState *interp); extern int _PyBuiltins_AddExceptions(PyObject * bltinmod); extern PyStatus _Py_HashRandomization_Init(const PyConfig *); -extern PyStatus _PyTime_Init(void); extern PyStatus _PyGC_Init(PyInterpreterState *interp); extern PyStatus _PyAtExit_Init(PyInterpreterState *interp); extern int _Py_Deepfreeze_Init(void); @@ -64,7 +63,7 @@ extern void _PyArg_Fini(void); extern void _Py_FinalizeAllocatedBlocks(_PyRuntimeState *); extern PyStatus _PyGILState_Init(PyInterpreterState *interp); -extern PyStatus _PyGILState_SetTstate(PyThreadState *tstate); +extern void _PyGILState_SetTstate(PyThreadState *tstate); extern void _PyGILState_Fini(PyInterpreterState *interp); extern void _PyGC_DumpShutdownStats(PyInterpreterState *interp); @@ -98,19 +97,25 @@ extern int _Py_FdIsInteractive(FILE *fp, PyObject *filename); extern const char* _Py_gitidentifier(void); extern const char* _Py_gitversion(void); -extern int _Py_IsFinalizing(void); +// Export for '_asyncio' shared extension PyAPI_FUNC(int) _Py_IsInterpreterFinalizing(PyInterpreterState *interp); /* Random */ extern int _PyOS_URandom(void *buffer, Py_ssize_t size); + // Export for '_random' shared extension PyAPI_FUNC(int) _PyOS_URandomNonblock(void *buffer, Py_ssize_t size); /* Legacy locale support */ extern int _Py_CoerceLegacyLocale(int warn); extern int _Py_LegacyLocaleDetected(int warn); + +// Export for 'readline' shared extension PyAPI_FUNC(char*) _Py_SetLocaleFromEnv(int category); +// Export for special main.c string compiling with source tracebacks +int _PyRun_SimpleStringFlagsWithName(const char *command, const char* name, PyCompilerFlags *flags); + #ifdef __cplusplus } #endif diff --git a/Include/internal/pycore_pymem.h b/Include/internal/pycore_pymem.h index 6b5113714dbeb2..8631ca34a5e616 100644 --- a/Include/internal/pycore_pymem.h +++ b/Include/internal/pycore_pymem.h @@ -1,5 +1,8 @@ #ifndef Py_INTERNAL_PYMEM_H #define Py_INTERNAL_PYMEM_H + +#include "pycore_lock.h" // PyMutex + #ifdef __cplusplus extern "C" { #endif @@ -30,7 +33,7 @@ typedef struct { } debug_alloc_api_t; struct _pymem_allocators { - PyThread_type_lock mutex; + PyMutex mutex; struct { PyMemAllocatorEx raw; PyMemAllocatorEx mem; diff --git a/Include/internal/pycore_pymem_init.h b/Include/internal/pycore_pymem_init.h index 78232738cb09d5..360fb9218a9cda 100644 --- a/Include/internal/pycore_pymem_init.h +++ b/Include/internal/pycore_pymem_init.h @@ -8,8 +8,6 @@ extern "C" { # error "this header requires Py_BUILD_CORE define" #endif -#include "pycore_pymem.h" - /********************************/ /* the allocators' initializers */ @@ -20,17 +18,30 @@ extern void * _PyMem_RawRealloc(void *, void *, size_t); extern void _PyMem_RawFree(void *, void *); #define PYRAW_ALLOC {NULL, _PyMem_RawMalloc, _PyMem_RawCalloc, _PyMem_RawRealloc, _PyMem_RawFree} -#ifdef WITH_PYMALLOC +#ifdef Py_GIL_DISABLED +// Py_GIL_DISABLED requires mimalloc +extern void* _PyObject_MiMalloc(void *, size_t); +extern void* _PyObject_MiCalloc(void *, size_t, size_t); +extern void _PyObject_MiFree(void *, void *); +extern void* _PyObject_MiRealloc(void *, void *, size_t); +# define PYOBJ_ALLOC {NULL, _PyObject_MiMalloc, _PyObject_MiCalloc, _PyObject_MiRealloc, _PyObject_MiFree} +extern void* _PyMem_MiMalloc(void *, size_t); +extern void* _PyMem_MiCalloc(void *, size_t, size_t); +extern void _PyMem_MiFree(void *, void *); +extern void* _PyMem_MiRealloc(void *, void *, size_t); +# define PYMEM_ALLOC {NULL, _PyMem_MiMalloc, _PyMem_MiCalloc, _PyMem_MiRealloc, _PyMem_MiFree} +#elif defined(WITH_PYMALLOC) extern void* _PyObject_Malloc(void *, size_t); extern void* _PyObject_Calloc(void *, size_t, size_t); extern void _PyObject_Free(void *, void *); extern void* _PyObject_Realloc(void *, void *, size_t); # define PYOBJ_ALLOC {NULL, _PyObject_Malloc, _PyObject_Calloc, _PyObject_Realloc, _PyObject_Free} +# define PYMEM_ALLOC PYOBJ_ALLOC #else # define PYOBJ_ALLOC PYRAW_ALLOC +# define PYMEM_ALLOC PYOBJ_ALLOC #endif // WITH_PYMALLOC -#define PYMEM_ALLOC PYOBJ_ALLOC extern void* _PyMem_DebugRawMalloc(void *, size_t); extern void* _PyMem_DebugRawCalloc(void *, size_t, size_t); diff --git a/Include/internal/pycore_pystate.h b/Include/internal/pycore_pystate.h index acc6cf953343fb..348c5c634284b0 100644 --- a/Include/internal/pycore_pystate.h +++ b/Include/internal/pycore_pystate.h @@ -8,7 +8,36 @@ extern "C" { # error "this header requires Py_BUILD_CORE define" #endif -#include "pycore_runtime.h" /* PyRuntimeState */ +#include "pycore_freelist.h" // _PyFreeListState +#include "pycore_runtime.h" // _PyRuntime +#include "pycore_tstate.h" // _PyThreadStateImpl + + +// Values for PyThreadState.state. A thread must be in the "attached" state +// before calling most Python APIs. If the GIL is enabled, then "attached" +// implies that the thread holds the GIL and "detached" implies that the +// thread does not hold the GIL (or is in the process of releasing it). In +// `--disable-gil` builds, multiple threads may be "attached" to the same +// interpreter at the same time. Only the "bound" thread may perform the +// transitions between "attached" and "detached" on its own PyThreadState. +// +// The "gc" state is used to implement stop-the-world pauses, such as for +// cyclic garbage collection. It is only used in `--disable-gil` builds. It is +// similar to the "detached" state, but only the thread performing a +// stop-the-world pause may transition threads between the "detached" and "gc" +// states. A thread trying to "attach" from the "gc" state will block until +// it is transitioned back to "detached" when the stop-the-world pause is +// complete. +// +// State transition diagram: +// +// (bound thread) (stop-the-world thread) +// [attached] <-> [detached] <-> [gc] +// +// See `_PyThreadState_Attach()` and `_PyThreadState_Detach()`. +#define _Py_THREAD_DETACHED 0 +#define _Py_THREAD_ATTACHED 1 +#define _Py_THREAD_GC 2 /* Check if the current thread is the main thread. @@ -36,10 +65,20 @@ _Py_IsMainInterpreter(PyInterpreterState *interp) static inline int _Py_IsMainInterpreterFinalizing(PyInterpreterState *interp) { - return (_PyRuntimeState_GetFinalizing(interp->runtime) != NULL && - interp == &interp->runtime->_main_interpreter); + /* 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. */ + return (_PyRuntimeState_GetFinalizing(&_PyRuntime) != NULL && + interp == &_PyRuntime._main_interpreter); } +// Export for _xxsubinterpreters module. +PyAPI_FUNC(int) _PyInterpreterState_SetRunningMain(PyInterpreterState *); +PyAPI_FUNC(void) _PyInterpreterState_SetNotRunningMain(PyInterpreterState *); +PyAPI_FUNC(int) _PyInterpreterState_IsRunningMain(PyInterpreterState *); +PyAPI_FUNC(int) _PyInterpreterState_FailIfRunningMain(PyInterpreterState *); + static inline const PyConfig * _Py_GetMainConfig(void) @@ -66,6 +105,15 @@ _Py_ThreadCanHandleSignals(PyInterpreterState *interp) #if defined(HAVE_THREAD_LOCAL) && !defined(Py_BUILD_CORE_MODULE) extern _Py_thread_local PyThreadState *_Py_tss_tstate; #endif + +#ifndef NDEBUG +extern int _PyThreadState_CheckConsistency(PyThreadState *tstate); +#endif + +int _PyThreadState_MustExit(PyThreadState *tstate); + +// Export for most shared extensions, used via _PyThreadState_GET() static +// inline function. PyAPI_FUNC(PyThreadState *) _PyThreadState_GetCurrent(void); /* Get the current Python thread state. @@ -74,7 +122,7 @@ PyAPI_FUNC(PyThreadState *) _PyThreadState_GetCurrent(void); The caller must hold the GIL. - See also PyThreadState_Get() and _PyThreadState_UncheckedGet(). */ + See also PyThreadState_Get() and PyThreadState_GetUnchecked(). */ static inline PyThreadState* _PyThreadState_GET(void) { @@ -85,6 +133,21 @@ _PyThreadState_GET(void) #endif } +// Attaches the current thread to the interpreter. +// +// This may block while acquiring the GIL (if the GIL is enabled) or while +// waiting for a stop-the-world pause (if the GIL is disabled). +// +// High-level code should generally call PyEval_RestoreThread() instead, which +// calls this function. +void _PyThreadState_Attach(PyThreadState *tstate); + +// Detaches the current thread from the interpreter. +// +// High-level code should generally call PyEval_SaveThread() instead, which +// calls this function. +void _PyThreadState_Detach(PyThreadState *tstate); + static inline void _Py_EnsureFuncTstateNotNULL(const char *func, PyThreadState *tstate) @@ -121,18 +184,16 @@ static inline PyInterpreterState* _PyInterpreterState_GET(void) { // PyThreadState functions -extern PyThreadState * _PyThreadState_New(PyInterpreterState *interp); +extern PyThreadState * _PyThreadState_New( + PyInterpreterState *interp, + int whence); extern void _PyThreadState_Bind(PyThreadState *tstate); extern void _PyThreadState_DeleteExcept(PyThreadState *tstate); +extern void _PyThreadState_ClearMimallocHeaps(PyThreadState *tstate); // Export for '_testinternalcapi' shared extension PyAPI_FUNC(PyObject*) _PyThreadState_GetDict(PyThreadState *tstate); -/* The implementation of sys._current_frames() Returns a dict mapping - thread id to that thread's current frame. -*/ -extern PyObject* _PyThread_CurrentFrames(void); - /* The implementation of sys._current_exceptions() Returns a dict mapping thread id to that thread's current exception. */ @@ -162,15 +223,37 @@ PyAPI_FUNC(int) _PyState_AddModule( extern int _PyOS_InterruptOccurred(PyThreadState *tstate); #define HEAD_LOCK(runtime) \ - PyThread_acquire_lock((runtime)->interpreters.mutex, WAIT_LOCK) + PyMutex_LockFlags(&(runtime)->interpreters.mutex, _Py_LOCK_DONT_DETACH) #define HEAD_UNLOCK(runtime) \ - PyThread_release_lock((runtime)->interpreters.mutex) + PyMutex_Unlock(&(runtime)->interpreters.mutex) // Get the configuration of the current interpreter. // The caller must hold the GIL. // Export for test_peg_generator. PyAPI_FUNC(const PyConfig*) _Py_GetConfig(void); +// Get the single PyInterpreterState used by this process' GILState +// implementation. +// +// This function doesn't check for error. Return NULL before _PyGILState_Init() +// is called and after _PyGILState_Fini() is called. +// +// See also PyInterpreterState_Get() and _PyInterpreterState_GET(). +extern PyInterpreterState* _PyGILState_GetInterpreterStateUnsafe(void); + +static inline _PyFreeListState* _PyFreeListState_GET(void) +{ + PyThreadState *tstate = _PyThreadState_GET(); +#ifdef Py_DEBUG + _Py_EnsureTstateNotNULL(tstate); +#endif + +#ifdef Py_GIL_DISABLED + return &((_PyThreadStateImpl*)tstate)->freelist_state; +#else + return &tstate->interp->freelist_state; +#endif +} #ifdef __cplusplus } diff --git a/Include/internal/pycore_pystats.h b/Include/internal/pycore_pystats.h new file mode 100644 index 00000000000000..f8af398a560586 --- /dev/null +++ b/Include/internal/pycore_pystats.h @@ -0,0 +1,21 @@ +#ifndef Py_INTERNAL_PYSTATS_H +#define Py_INTERNAL_PYSTATS_H +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef Py_BUILD_CORE +# error "this header requires Py_BUILD_CORE define" +#endif + +#ifdef Py_STATS +extern void _Py_StatsOn(void); +extern void _Py_StatsOff(void); +extern void _Py_StatsClear(void); +extern int _Py_PrintSpecializationStats(int to_file); +#endif + +#ifdef __cplusplus +} +#endif +#endif // !Py_INTERNAL_PYSTATS_H diff --git a/Include/internal/pycore_pythonrun.h b/Include/internal/pycore_pythonrun.h new file mode 100644 index 00000000000000..0bfc5704dc4c59 --- /dev/null +++ b/Include/internal/pycore_pythonrun.h @@ -0,0 +1,39 @@ +#ifndef Py_INTERNAL_PYTHONRUN_H +#define Py_INTERNAL_PYTHONRUN_H +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef Py_BUILD_CORE +# error "this header requires Py_BUILD_CORE define" +#endif + +extern int _PyRun_SimpleFileObject( + FILE *fp, + PyObject *filename, + int closeit, + PyCompilerFlags *flags); + +extern int _PyRun_AnyFileObject( + FILE *fp, + PyObject *filename, + int closeit, + PyCompilerFlags *flags); + +extern int _PyRun_InteractiveLoopObject( + FILE *fp, + PyObject *filename, + PyCompilerFlags *flags); + +extern const char* _Py_SourceAsString( + PyObject *cmd, + const char *funcname, + const char *what, + PyCompilerFlags *cf, + PyObject **cmd_copy); + +#ifdef __cplusplus +} +#endif +#endif // !Py_INTERNAL_PYTHONRUN_H + diff --git a/Include/internal/pycore_pythread.h b/Include/internal/pycore_pythread.h index f53921494c158f..9c9a09f60f3441 100644 --- a/Include/internal/pycore_pythread.h +++ b/Include/internal/pycore_pythread.h @@ -8,42 +8,45 @@ extern "C" { # error "this header requires Py_BUILD_CORE define" #endif +#include "dynamic_annotations.h" // _Py_ANNOTATE_PURE_HAPPENS_BEFORE_MUTEX + +// Get _POSIX_THREADS and _POSIX_SEMAPHORES macros if available +#if (defined(HAVE_UNISTD_H) && !defined(_POSIX_THREADS) \ + && !defined(_POSIX_SEMAPHORES)) +# include // _POSIX_THREADS, _POSIX_SEMAPHORES +#endif +#if (defined(HAVE_PTHREAD_H) && !defined(_POSIX_THREADS) \ + && !defined(_POSIX_SEMAPHORES)) + // This means pthreads are not implemented in libc headers, hence the macro + // not present in . But they still can be implemented as an + // external library (e.g. gnu pth in pthread emulation) +# include // _POSIX_THREADS, _POSIX_SEMAPHORES +#endif +#if !defined(_POSIX_THREADS) && defined(__hpux) && defined(_SC_THREADS) + // Check if we're running on HP-UX and _SC_THREADS is defined. If so, then + // enough of the POSIX threads package is implemented to support Python + // threads. + // + // This is valid for HP-UX 11.23 running on an ia64 system. If needed, add + // a check of __ia64 to verify that we're running on an ia64 system instead + // of a pa-risc system. +# define _POSIX_THREADS +#endif -#ifndef _POSIX_THREADS -/* This means pthreads are not implemented in libc headers, hence the macro - not present in unistd.h. But they still can be implemented as an external - library (e.g. gnu pth in pthread emulation) */ -# ifdef HAVE_PTHREAD_H -# include /* _POSIX_THREADS */ -# endif -# ifndef _POSIX_THREADS -/* Check if we're running on HP-UX and _SC_THREADS is defined. If so, then - enough of the Posix threads package is implemented to support python - threads. - - This is valid for HP-UX 11.23 running on an ia64 system. If needed, add - a check of __ia64 to verify that we're running on an ia64 system instead - of a pa-risc system. -*/ -# ifdef __hpux -# ifdef _SC_THREADS -# define _POSIX_THREADS -# endif -# endif -# endif /* _POSIX_THREADS */ -#endif /* _POSIX_THREADS */ #if defined(_POSIX_THREADS) || defined(HAVE_PTHREAD_STUBS) -# define _USE_PTHREADS +# define _USE_PTHREADS #endif #if defined(_USE_PTHREADS) && defined(HAVE_PTHREAD_CONDATTR_SETCLOCK) && defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC) // monotonic is supported statically. It doesn't mean it works on runtime. -# define CONDATTR_MONOTONIC +# define CONDATTR_MONOTONIC #endif #if defined(HAVE_PTHREAD_STUBS) +#include // bool + // pthread_key struct py_stub_tls_entry { bool in_use; @@ -75,6 +78,77 @@ struct _pythread_runtime_state { }; +#ifdef HAVE_FORK +/* Private function to reinitialize a lock at fork in the child process. + Reset the lock to the unlocked state. + Return 0 on success, return -1 on error. */ +extern int _PyThread_at_fork_reinit(PyThread_type_lock *lock); +#endif /* HAVE_FORK */ + + +// unset: -1 seconds, in nanoseconds +#define PyThread_UNSET_TIMEOUT ((_PyTime_t)(-1 * 1000 * 1000 * 1000)) + +// Exported for the _xxinterpchannels module. +PyAPI_FUNC(int) PyThread_ParseTimeoutArg( + PyObject *arg, + int blocking, + PY_TIMEOUT_T *timeout); + +/* Helper to acquire an interruptible lock with a timeout. If the lock acquire + * is interrupted, signal handlers are run, and if they raise an exception, + * PY_LOCK_INTR is returned. Otherwise, PY_LOCK_ACQUIRED or PY_LOCK_FAILURE + * are returned, depending on whether the lock can be acquired within the + * timeout. + */ +// Exported for the _xxinterpchannels module. +PyAPI_FUNC(PyLockStatus) PyThread_acquire_lock_timed_with_retries( + PyThread_type_lock, + PY_TIMEOUT_T microseconds); + +typedef unsigned long long PyThread_ident_t; +typedef Py_uintptr_t PyThread_handle_t; + +#define PY_FORMAT_THREAD_IDENT_T "llu" +#define Py_PARSE_THREAD_IDENT_T "K" + +PyAPI_FUNC(PyThread_ident_t) PyThread_get_thread_ident_ex(void); + +/* Thread joining APIs. + * + * These APIs have a strict contract: + * - Either PyThread_join_thread or PyThread_detach_thread must be called + * exactly once with the given handle. + * - Calling neither PyThread_join_thread nor PyThread_detach_thread results + * in a resource leak until the end of the process. + * - Any other usage, such as calling both PyThread_join_thread and + * PyThread_detach_thread, or calling them more than once (including + * simultaneously), results in undefined behavior. + */ +PyAPI_FUNC(int) PyThread_start_joinable_thread(void (*func)(void *), + void *arg, + PyThread_ident_t* ident, + PyThread_handle_t* handle); +/* + * Join a thread started with `PyThread_start_joinable_thread`. + * This function cannot be interrupted. It returns 0 on success, + * a non-zero value on failure. + */ +PyAPI_FUNC(int) PyThread_join_thread(PyThread_handle_t); +/* + * Detach a thread started with `PyThread_start_joinable_thread`, such + * that its resources are relased as soon as it exits. + * This function cannot be interrupted. It returns 0 on success, + * a non-zero value on failure. + */ +PyAPI_FUNC(int) PyThread_detach_thread(PyThread_handle_t); + +/* + * Obtain the new thread ident and handle in a forked child process. + */ +PyAPI_FUNC(void) PyThread_update_thread_after_fork(PyThread_ident_t* ident, + PyThread_handle_t* handle); + #ifdef __cplusplus } #endif diff --git a/Include/internal/pycore_runtime.h b/Include/internal/pycore_runtime.h index 0ec86ee6c50ca3..e3348296ea61b7 100644 --- a/Include/internal/pycore_runtime.h +++ b/Include/internal/pycore_runtime.h @@ -8,27 +8,24 @@ extern "C" { # error "this header requires Py_BUILD_CORE define" #endif -#include "pycore_atexit.h" // struct atexit_runtime_state -#include "pycore_atomic.h" /* _Py_atomic_address */ +#include "pycore_atexit.h" // struct _atexit_runtime_state #include "pycore_ceval_state.h" // struct _ceval_runtime_state -#include "pycore_floatobject.h" // struct _Py_float_runtime_state +#include "pycore_crossinterp.h" // struct _xidregistry #include "pycore_faulthandler.h" // struct _faulthandler_runtime_state -#include "pycore_global_objects.h" // struct _Py_global_objects +#include "pycore_floatobject.h" // struct _Py_float_runtime_state #include "pycore_import.h" // struct _import_runtime_state #include "pycore_interp.h" // PyInterpreterState #include "pycore_object_state.h" // struct _py_object_runtime_state #include "pycore_parser.h" // struct _parser_runtime_state -#include "pycore_pymem.h" // struct _pymem_allocators #include "pycore_pyhash.h" // struct pyhash_runtime_state +#include "pycore_pymem.h" // struct _pymem_allocators #include "pycore_pythread.h" // struct _pythread_runtime_state #include "pycore_signal.h" // struct _signals_runtime_state -#include "pycore_time.h" // struct _time_runtime_state #include "pycore_tracemalloc.h" // struct _tracemalloc_runtime_state -#include "pycore_typeobject.h" // struct types_runtime_state -#include "pycore_unicodeobject.h" // struct _Py_unicode_runtime_ids +#include "pycore_typeobject.h" // struct _types_runtime_state +#include "pycore_unicodeobject.h" // struct _Py_unicode_runtime_state struct _getargs_runtime_state { - PyThread_type_lock mutex; struct _PyArg_Parser *static_parsers; }; @@ -80,7 +77,7 @@ typedef struct _Py_DebugOffsets { off_t prev; off_t next; off_t interp; - off_t cframe; + off_t current_frame; off_t thread_id; off_t native_thread_id; } thread_state; @@ -89,7 +86,7 @@ typedef struct _Py_DebugOffsets { struct _interpreter_frame { off_t previous; off_t executable; - off_t prev_instr; + off_t instr_ptr; off_t localsplus; off_t owner; } interpreter_frame; @@ -171,10 +168,12 @@ typedef struct pyruntimestate { Use _PyRuntimeState_GetFinalizing() and _PyRuntimeState_SetFinalizing() to access it, don't access it directly. */ - _Py_atomic_address _finalizing; + PyThreadState *_finalizing; + /* The ID of the OS thread in which we are finalizing. */ + unsigned long _finalizing_id; struct pyinterpreters { - PyThread_type_lock mutex; + PyMutex mutex; /* The linked list of interpreters, newest first. */ PyInterpreterState *head; /* The runtime's initial interpreter, which has a special role @@ -199,16 +198,12 @@ typedef struct pyruntimestate { possible to facilitate out-of-process observability tools. */ - // XXX Remove this field once we have a tp_* slot. - struct _xidregistry { - PyThread_type_lock mutex; - struct _xidregitem *head; - } xidregistry; + /* cross-interpreter data and utils */ + struct _xi_runtime_state xi; struct _pymem_allocators allocators; struct _obmalloc_global_state obmalloc; struct pyhash_runtime_state pyhash_state; - struct _time_runtime_state time; struct _pythread_runtime_state threads; struct _signals_runtime_state signals; @@ -239,7 +234,7 @@ typedef struct pyruntimestate { Py_OpenCodeHookFunction open_code_hook; void *open_code_userdata; struct { - PyThread_type_lock mutex; + PyMutex mutex; _Py_AuditHookEntry *head; } audit_hooks; @@ -268,11 +263,21 @@ typedef struct pyruntimestate { /* PyInterpreterState.interpreters.main */ PyInterpreterState _main_interpreter; + +#if defined(__EMSCRIPTEN__) && defined(PY_CALL_TRAMPOLINE) + // Used in "Python/emscripten_trampoline.c" to choose between type + // reflection trampoline and EM_JS trampoline. + bool wasm_type_reflection_available; +#endif + } _PyRuntimeState; /* other API */ +// Export _PyRuntime for shared extensions which use it in static inline +// functions for best performance, like _Py_IsMainThread() or _Py_ID(). +// It's also made accessible for debuggers and profilers. PyAPI_DATA(_PyRuntimeState) _PyRuntime; extern PyStatus _PyRuntimeState_Init(_PyRuntimeState *runtime); @@ -291,12 +296,26 @@ extern void _PyRuntime_Finalize(void); static inline PyThreadState* _PyRuntimeState_GetFinalizing(_PyRuntimeState *runtime) { - return (PyThreadState*)_Py_atomic_load_relaxed(&runtime->_finalizing); + return (PyThreadState*)_Py_atomic_load_ptr_relaxed(&runtime->_finalizing); +} + +static inline unsigned long +_PyRuntimeState_GetFinalizingID(_PyRuntimeState *runtime) { + return _Py_atomic_load_ulong_relaxed(&runtime->_finalizing_id); } static inline void _PyRuntimeState_SetFinalizing(_PyRuntimeState *runtime, PyThreadState *tstate) { - _Py_atomic_store_relaxed(&runtime->_finalizing, (uintptr_t)tstate); + _Py_atomic_store_ptr_relaxed(&runtime->_finalizing, tstate); + if (tstate == NULL) { + _Py_atomic_store_ulong_relaxed(&runtime->_finalizing_id, 0); + } + else { + // XXX Re-enable this assert once gh-109860 is fixed. + //assert(tstate->thread_id == PyThread_get_thread_ident()); + _Py_atomic_store_ulong_relaxed(&runtime->_finalizing_id, + tstate->thread_id); + } } #ifdef __cplusplus diff --git a/Include/internal/pycore_runtime_init.h b/Include/internal/pycore_runtime_init.h index e89d368be07aa7..d324a94278839c 100644 --- a/Include/internal/pycore_runtime_init.h +++ b/Include/internal/pycore_runtime_init.h @@ -8,11 +8,17 @@ extern "C" { # error "this header requires Py_BUILD_CORE define" #endif -#include "pycore_long.h" -#include "pycore_object.h" -#include "pycore_parser.h" -#include "pycore_pymem_init.h" -#include "pycore_obmalloc_init.h" +#include "pycore_ceval_state.h" // _PyEval_RUNTIME_PERF_INIT +#include "pycore_faulthandler.h" // _faulthandler_runtime_state_INIT +#include "pycore_floatobject.h" // _py_float_format_unknown +#include "pycore_object.h" // _PyObject_HEAD_INIT +#include "pycore_obmalloc_init.h" // _obmalloc_global_state_INIT +#include "pycore_parser.h" // _parser_runtime_state_INIT +#include "pycore_pyhash.h" // pyhash_state_INIT +#include "pycore_pymem_init.h" // _pymem_allocators_standard_INIT +#include "pycore_runtime_init_generated.h" // _Py_bytes_characters_INIT +#include "pycore_signal.h" // _signals_RUNTIME_INIT +#include "pycore_tracemalloc.h" // _tracemalloc_runtime_state_INIT extern PyTypeObject _PyExc_MemoryError; @@ -45,21 +51,17 @@ extern PyTypeObject _PyExc_MemoryError; .prev = offsetof(PyThreadState, prev), \ .next = offsetof(PyThreadState, next), \ .interp = offsetof(PyThreadState, interp), \ - .cframe = offsetof(PyThreadState, cframe), \ + .current_frame = offsetof(PyThreadState, current_frame), \ .thread_id = offsetof(PyThreadState, thread_id), \ .native_thread_id = offsetof(PyThreadState, native_thread_id), \ }, \ .interpreter_frame = { \ .previous = offsetof(_PyInterpreterFrame, previous), \ .executable = offsetof(_PyInterpreterFrame, f_executable), \ - .prev_instr = offsetof(_PyInterpreterFrame, prev_instr), \ + .instr_ptr = offsetof(_PyInterpreterFrame, instr_ptr), \ .localsplus = offsetof(_PyInterpreterFrame, localsplus), \ .owner = offsetof(_PyInterpreterFrame, owner), \ }, \ - .cframe = { \ - .current_frame = offsetof(_PyCFrame, current_frame), \ - .previous = offsetof(_PyCFrame, previous), \ - }, \ .code_object = { \ .filename = offsetof(PyCodeObject, co_filename), \ .name = offsetof(PyCodeObject, co_name), \ @@ -93,6 +95,11 @@ extern PyTypeObject _PyExc_MemoryError; until _PyInterpreterState_Enable() is called. */ \ .next_id = -1, \ }, \ + .xi = { \ + .registry = { \ + .global = 1, \ + }, \ + }, \ /* A TSS key must be initialized with Py_tss_NEEDS_INIT \ in accordance with the specification. */ \ .autoTSSkey = Py_tss_NEEDS_INIT, \ @@ -127,13 +134,13 @@ extern PyTypeObject _PyExc_MemoryError; .latin1 = _Py_str_latin1_INIT, \ }, \ .tuple_empty = { \ - .ob_base = _PyVarObject_HEAD_INIT(&PyTuple_Type, 0) \ + .ob_base = _PyVarObject_HEAD_INIT(&PyTuple_Type, 0), \ }, \ .hamt_bitmap_node_empty = { \ - .ob_base = _PyVarObject_HEAD_INIT(&_PyHamt_BitmapNode_Type, 0) \ + .ob_base = _PyVarObject_HEAD_INIT(&_PyHamt_BitmapNode_Type, 0), \ }, \ .context_token_missing = { \ - .ob_base = _PyObject_HEAD_INIT(&_PyContextTokenMissing_Type) \ + .ob_base = _PyObject_HEAD_INIT(&_PyContextTokenMissing_Type), \ }, \ }, \ }, \ @@ -170,19 +177,26 @@ extern PyTypeObject _PyExc_MemoryError; .singletons = { \ ._not_used = 1, \ .hamt_empty = { \ - .ob_base = _PyObject_HEAD_INIT(&_PyHamt_Type) \ + .ob_base = _PyObject_HEAD_INIT(&_PyHamt_Type), \ .h_root = (PyHamtNode*)&_Py_SINGLETON(hamt_bitmap_node_empty), \ }, \ .last_resort_memory_error = { \ - _PyObject_HEAD_INIT(&_PyExc_MemoryError) \ + _PyObject_HEAD_INIT(&_PyExc_MemoryError), \ + .args = (PyObject*)&_Py_SINGLETON(tuple_empty) \ }, \ }, \ }, \ - ._initial_thread = _PyThreadState_INIT, \ + ._initial_thread = _PyThreadStateImpl_INIT, \ + } + +#define _PyThreadStateImpl_INIT \ + { \ + .base = _PyThreadState_INIT, \ } #define _PyThreadState_INIT \ { \ + ._whence = _PyThreadState_WHENCE_NOTSET, \ .py_recursion_limit = Py_DEFAULT_RECURSION_LIMIT, \ .context_ver = 1, \ } @@ -190,7 +204,7 @@ extern PyTypeObject _PyExc_MemoryError; #ifdef Py_TRACE_REFS # define _py_object_state_INIT(INTERP) \ { \ - .refchain = {&INTERP.object_state.refchain, &INTERP.object_state.refchain}, \ + .refchain = NULL, \ } #else # define _py_object_state_INIT(INTERP) \ @@ -202,7 +216,7 @@ extern PyTypeObject _PyExc_MemoryError; #define _PyBytes_SIMPLE_INIT(CH, LEN) \ { \ - _PyVarObject_HEAD_INIT(&PyBytes_Type, (LEN)) \ + _PyVarObject_HEAD_INIT(&PyBytes_Type, (LEN)), \ .ob_shash = -1, \ .ob_sval = { (CH) }, \ } @@ -213,7 +227,7 @@ extern PyTypeObject _PyExc_MemoryError; #define _PyUnicode_ASCII_BASE_INIT(LITERAL, ASCII) \ { \ - .ob_base = _PyObject_HEAD_INIT(&PyUnicode_Type) \ + .ob_base = _PyObject_HEAD_INIT(&PyUnicode_Type), \ .length = sizeof(LITERAL) - 1, \ .hash = -1, \ .state = { \ diff --git a/Include/internal/pycore_runtime_init_generated.h b/Include/internal/pycore_runtime_init_generated.h index 2d66647438b193..e285d02b48a9f4 100644 --- a/Include/internal/pycore_runtime_init_generated.h +++ b/Include/internal/pycore_runtime_init_generated.h @@ -8,6 +8,9 @@ extern "C" { # error "this header requires Py_BUILD_CORE define" #endif +#include "pycore_long.h" // _PyLong_DIGIT_INIT() + + /* The following is auto-generated by Tools/build/generate_global_objects.py. */ #define _Py_small_ints_INIT { \ _PyLong_DIGIT_INIT(-5), \ @@ -539,6 +542,7 @@ extern "C" { INIT_STR(anon_lambda, ""), \ INIT_STR(anon_listcomp, ""), \ INIT_STR(anon_module, ""), \ + INIT_STR(anon_null, ""), \ INIT_STR(anon_setcomp, ""), \ INIT_STR(anon_string, ""), \ INIT_STR(anon_unknown, ""), \ @@ -781,11 +785,8 @@ extern "C" { INIT_ID(after_in_child), \ INIT_ID(after_in_parent), \ INIT_ID(aggregate_class), \ - INIT_ID(alias), \ INIT_ID(append), \ - INIT_ID(arg), \ INIT_ID(argdefs), \ - INIT_ID(args), \ INIT_ID(arguments), \ INIT_ID(argv), \ INIT_ID(as_integer_ratio), \ @@ -823,6 +824,7 @@ extern "C" { INIT_ID(call), \ INIT_ID(call_exception_handler), \ INIT_ID(call_soon), \ + INIT_ID(callback), \ INIT_ID(cancel), \ INIT_ID(capath), \ INIT_ID(category), \ @@ -893,7 +895,6 @@ extern "C" { INIT_ID(dont_inherit), \ INIT_ID(dst), \ INIT_ID(dst_dir_fd), \ - INIT_ID(duration), \ INIT_ID(e), \ INIT_ID(eager_start), \ INIT_ID(effective_ids), \ @@ -909,14 +910,13 @@ extern "C" { INIT_ID(errors), \ INIT_ID(event), \ INIT_ID(eventmask), \ - INIT_ID(exc_type), \ - INIT_ID(exc_value), \ INIT_ID(excepthook), \ INIT_ID(exception), \ INIT_ID(existing_file_name), \ INIT_ID(exp), \ INIT_ID(extend), \ INIT_ID(extra_tokens), \ + INIT_ID(f), \ INIT_ID(facility), \ INIT_ID(factory), \ INIT_ID(false), \ @@ -940,7 +940,6 @@ extern "C" { INIT_ID(flush), \ INIT_ID(follow_symlinks), \ INIT_ID(format), \ - INIT_ID(frequency), \ INIT_ID(from_param), \ INIT_ID(fromlist), \ INIT_ID(fromtimestamp), \ @@ -948,6 +947,7 @@ extern "C" { INIT_ID(fset), \ INIT_ID(func), \ INIT_ID(future), \ + INIT_ID(g), \ INIT_ID(generation), \ INIT_ID(genexpr), \ INIT_ID(get), \ @@ -961,6 +961,7 @@ extern "C" { INIT_ID(globals), \ INIT_ID(groupindex), \ INIT_ID(groups), \ + INIT_ID(h), \ INIT_ID(handle), \ INIT_ID(hash_name), \ INIT_ID(header), \ @@ -969,6 +970,7 @@ extern "C" { INIT_ID(hook), \ INIT_ID(id), \ INIT_ID(ident), \ + INIT_ID(identity_hint), \ INIT_ID(ignore), \ INIT_ID(imag), \ INIT_ID(importlib), \ @@ -989,6 +991,7 @@ extern "C" { INIT_ID(instructions), \ INIT_ID(intern), \ INIT_ID(intersection), \ + INIT_ID(interval), \ INIT_ID(is_running), \ INIT_ID(isatty), \ INIT_ID(isinstance), \ @@ -1010,6 +1013,7 @@ extern "C" { INIT_ID(kw), \ INIT_ID(kw1), \ INIT_ID(kw2), \ + INIT_ID(kwdefaults), \ INIT_ID(lambda), \ INIT_ID(last), \ INIT_ID(last_exc), \ @@ -1159,7 +1163,6 @@ extern "C" { INIT_ID(seek), \ INIT_ID(seekable), \ INIT_ID(selectors), \ - INIT_ID(self), \ INIT_ID(send), \ INIT_ID(sep), \ INIT_ID(sequence), \ @@ -1181,7 +1184,6 @@ extern "C" { INIT_ID(sleep), \ INIT_ID(sock), \ INIT_ID(sort), \ - INIT_ID(sound), \ INIT_ID(source), \ INIT_ID(source_traceback), \ INIT_ID(src), \ @@ -1223,7 +1225,6 @@ extern "C" { INIT_ID(timetuple), \ INIT_ID(top), \ INIT_ID(trace_callback), \ - INIT_ID(traceback), \ INIT_ID(trailers), \ INIT_ID(translate), \ INIT_ID(true), \ diff --git a/Include/internal/pycore_semaphore.h b/Include/internal/pycore_semaphore.h new file mode 100644 index 00000000000000..4c37df7b39a48a --- /dev/null +++ b/Include/internal/pycore_semaphore.h @@ -0,0 +1,66 @@ +// The _PySemaphore API a simplified cross-platform semaphore used to implement +// wakeup/sleep. +#ifndef Py_INTERNAL_SEMAPHORE_H +#define Py_INTERNAL_SEMAPHORE_H + +#ifndef Py_BUILD_CORE +# error "this header requires Py_BUILD_CORE define" +#endif + +#include "pycore_pythread.h" // _POSIX_SEMAPHORES +#include "pycore_time.h" // _PyTime_t + +#ifdef MS_WINDOWS +# define WIN32_LEAN_AND_MEAN +# include +#elif defined(HAVE_PTHREAD_H) +# include +#elif defined(HAVE_PTHREAD_STUBS) +# include "cpython/pthread_stubs.h" +#else +# error "Require native threads. See https://bugs.python.org/issue31370" +#endif + +#if (defined(_POSIX_SEMAPHORES) && (_POSIX_SEMAPHORES+0) != -1 && \ + defined(HAVE_SEM_TIMEDWAIT)) +# define _Py_USE_SEMAPHORES +# include +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct _PySemaphore { +#if defined(MS_WINDOWS) + HANDLE platform_sem; +#elif defined(_Py_USE_SEMAPHORES) + sem_t platform_sem; +#else + pthread_mutex_t mutex; + pthread_cond_t cond; + int counter; +#endif +} _PySemaphore; + +// Puts the current thread to sleep until _PySemaphore_Wakeup() is called. +// If `detach` is true, then the thread will detach/release the GIL while +// sleeping. +PyAPI_FUNC(int) +_PySemaphore_Wait(_PySemaphore *sema, _PyTime_t timeout_ns, int detach); + +// Wakes up a single thread waiting on sema. Note that _PySemaphore_Wakeup() +// can be called before _PySemaphore_Wait(). +PyAPI_FUNC(void) +_PySemaphore_Wakeup(_PySemaphore *sema); + +// Initializes/destroys a semaphore +PyAPI_FUNC(void) _PySemaphore_Init(_PySemaphore *sema); +PyAPI_FUNC(void) _PySemaphore_Destroy(_PySemaphore *sema); + + +#ifdef __cplusplus +} +#endif +#endif /* !Py_INTERNAL_SEMAPHORE_H */ diff --git a/Include/internal/pycore_setobject.h b/Include/internal/pycore_setobject.h index 1b63479e774412..34a00e6d45fe69 100644 --- a/Include/internal/pycore_setobject.h +++ b/Include/internal/pycore_setobject.h @@ -8,17 +8,17 @@ extern "C" { # error "this header requires Py_BUILD_CORE define" #endif -// Export for 'pickle' shared extension +// Export for '_pickle' shared extension PyAPI_FUNC(int) _PySet_NextEntry( PyObject *set, Py_ssize_t *pos, PyObject **key, Py_hash_t *hash); -// Export for 'pickle' shared extension +// Export for '_pickle' shared extension PyAPI_FUNC(int) _PySet_Update(PyObject *set, PyObject *iterable); -// Export _PySet_Dummy for the gdb plugin's benefit +// Export for the gdb plugin's (python-gdb.py) benefit PyAPI_DATA(PyObject *) _PySet_Dummy; #ifdef __cplusplus diff --git a/Include/internal/pycore_signal.h b/Include/internal/pycore_signal.h index 46b57d556e5ef4..47213a34ab77b5 100644 --- a/Include/internal/pycore_signal.h +++ b/Include/internal/pycore_signal.h @@ -10,8 +10,7 @@ extern "C" { # error "this header requires Py_BUILD_CORE define" #endif -#include "pycore_atomic.h" // _Py_atomic_address -#include // NSIG +#include // NSIG // Restore signals that the interpreter has called SIG_IGN on to SIG_DFL. @@ -38,12 +37,10 @@ PyAPI_FUNC(void) _Py_RestoreSignals(void); #define INVALID_FD (-1) struct _signals_runtime_state { - volatile struct { - _Py_atomic_int tripped; - /* func is atomic to ensure that PyErr_SetInterrupt is async-signal-safe - * (even though it would probably be otherwise, anyway). - */ - _Py_atomic_address func; + struct { + // tripped and func should be accessed using atomic ops. + int tripped; + PyObject* func; } handlers[Py_NSIG]; volatile struct { @@ -63,8 +60,9 @@ struct _signals_runtime_state { #endif } wakeup; - /* Speed up sigcheck() when none tripped */ - _Py_atomic_int is_tripped; + /* Speed up sigcheck() when none tripped. + is_tripped should be accessed using atomic ops. */ + int is_tripped; /* These objects necessarily belong to the main interpreter. */ PyObject *default_handler; @@ -95,6 +93,15 @@ struct _signals_runtime_state { } +// Export for '_multiprocessing' shared extension +PyAPI_FUNC(int) _PyOS_IsMainThread(void); + +#ifdef MS_WINDOWS +// is not included by Python.h so use void* instead of HANDLE. +// Export for '_multiprocessing' shared extension +PyAPI_FUNC(void*) _PyOS_SigintEvent(void); +#endif + #ifdef __cplusplus } #endif diff --git a/Include/internal/pycore_strhex.h b/Include/internal/pycore_strhex.h index f427b4d695bd29..225f423912f2c2 100644 --- a/Include/internal/pycore_strhex.h +++ b/Include/internal/pycore_strhex.h @@ -9,21 +9,24 @@ extern "C" { #endif // Returns a str() containing the hex representation of argbuf. +// Export for '_hashlib' shared extension. PyAPI_FUNC(PyObject*) _Py_strhex(const char* argbuf, const Py_ssize_t arglen); // Returns a bytes() containing the ASCII hex representation of argbuf. -PyAPI_FUNC(PyObject*) _Py_strhex_bytes( +extern PyObject* _Py_strhex_bytes( const char* argbuf, const Py_ssize_t arglen); // These variants include support for a separator between every N bytes: -PyAPI_FUNC(PyObject*) _Py_strhex_with_sep( +extern PyObject* _Py_strhex_with_sep( const char* argbuf, const Py_ssize_t arglen, PyObject* sep, const int bytes_per_group); + +// Export for 'binascii' shared extension PyAPI_FUNC(PyObject*) _Py_strhex_bytes_with_sep( const char* argbuf, const Py_ssize_t arglen, diff --git a/Include/internal/pycore_sysmodule.h b/Include/internal/pycore_sysmodule.h index 89a2f7628645b9..9b8eafd3d6cfd3 100644 --- a/Include/internal/pycore_sysmodule.h +++ b/Include/internal/pycore_sysmodule.h @@ -8,14 +8,20 @@ extern "C" { # error "this header requires Py_BUILD_CORE define" #endif +// Export for '_pickle' shared extension +PyAPI_FUNC(PyObject*) _PySys_GetAttr(PyThreadState *tstate, PyObject *name); + +// Export for '_pickle' shared extension +PyAPI_FUNC(size_t) _PySys_GetSizeOf(PyObject *); + extern int _PySys_Audit( PyThreadState *tstate, const char *event, const char *argFormat, ...); -/* We want minimal exposure of this function, so use extern rather than - PyAPI_FUNC() to not export the symbol. */ +// _PySys_ClearAuditHooks() must not be exported: use extern rather than +// PyAPI_FUNC(). We want minimal exposure of this function. extern void _PySys_ClearAuditHooks(PyThreadState *tstate); extern int _PySys_SetAttr(PyObject *, PyObject *); diff --git a/Include/internal/pycore_time.h b/Include/internal/pycore_time.h index 318fe4b3a32239..dabbd7b41556cd 100644 --- a/Include/internal/pycore_time.h +++ b/Include/internal/pycore_time.h @@ -52,23 +52,13 @@ extern "C" { #endif -struct _time_runtime_state { -#ifdef HAVE_TIMES - int ticks_per_second_initialized; - long ticks_per_second; -#else - int _not_used; -#endif -}; - - #ifdef __clang__ struct timeval; #endif -/* _PyTime_t: Python timestamp with subsecond precision. It can be used to - store a duration, and so indirectly a date (related to another date, like - UNIX epoch). */ +// _PyTime_t: Python timestamp with subsecond precision. It can be used to +// store a duration, and so indirectly a date (related to another date, like +// UNIX epoch). typedef int64_t _PyTime_t; // _PyTime_MIN nanoseconds is around -292.3 years #define _PyTime_MIN INT64_MIN @@ -77,52 +67,61 @@ typedef int64_t _PyTime_t; #define _SIZEOF_PYTIME_T 8 typedef enum { - /* Round towards minus infinity (-inf). - For example, used to read a clock. */ + // Round towards minus infinity (-inf). + // For example, used to read a clock. _PyTime_ROUND_FLOOR=0, - /* Round towards infinity (+inf). - For example, used for timeout to wait "at least" N seconds. */ + + // Round towards infinity (+inf). + // For example, used for timeout to wait "at least" N seconds. _PyTime_ROUND_CEILING=1, - /* Round to nearest with ties going to nearest even integer. - For example, used to round from a Python float. */ + + // Round to nearest with ties going to nearest even integer. + // For example, used to round from a Python float. _PyTime_ROUND_HALF_EVEN=2, - /* Round away from zero - For example, used for timeout. _PyTime_ROUND_CEILING rounds - -1e-9 to 0 milliseconds which causes bpo-31786 issue. - _PyTime_ROUND_UP rounds -1e-9 to -1 millisecond which keeps - the timeout sign as expected. select.poll(timeout) must block - for negative values." */ + + // Round away from zero + // For example, used for timeout. _PyTime_ROUND_CEILING rounds + // -1e-9 to 0 milliseconds which causes bpo-31786 issue. + // _PyTime_ROUND_UP rounds -1e-9 to -1 millisecond which keeps + // the timeout sign as expected. select.poll(timeout) must block + // for negative values. _PyTime_ROUND_UP=3, - /* _PyTime_ROUND_TIMEOUT (an alias for _PyTime_ROUND_UP) should be - used for timeouts. */ + + // _PyTime_ROUND_TIMEOUT (an alias for _PyTime_ROUND_UP) should be + // used for timeouts. _PyTime_ROUND_TIMEOUT = _PyTime_ROUND_UP } _PyTime_round_t; -/* Convert a time_t to a PyLong. */ +// Convert a time_t to a PyLong. +// Export for '_testinternalcapi' shared extension PyAPI_FUNC(PyObject*) _PyLong_FromTime_t(time_t sec); -/* Convert a PyLong to a time_t. */ +// Convert a PyLong to a time_t. +// Export for '_datetime' shared extension PyAPI_FUNC(time_t) _PyLong_AsTime_t(PyObject *obj); -/* Convert a number of seconds, int or float, to time_t. */ +// Convert a number of seconds, int or float, to time_t. +// Export for '_datetime' shared extension. PyAPI_FUNC(int) _PyTime_ObjectToTime_t( PyObject *obj, time_t *sec, _PyTime_round_t); -/* Convert a number of seconds, int or float, to a timeval structure. - usec is in the range [0; 999999] and rounded towards zero. - For example, -1.2 is converted to (-2, 800000). */ +// Convert a number of seconds, int or float, to a timeval structure. +// usec is in the range [0; 999999] and rounded towards zero. +// For example, -1.2 is converted to (-2, 800000). +// Export for '_datetime' shared extension. PyAPI_FUNC(int) _PyTime_ObjectToTimeval( PyObject *obj, time_t *sec, long *usec, _PyTime_round_t); -/* Convert a number of seconds, int or float, to a timespec structure. - nsec is in the range [0; 999999999] and rounded towards zero. - For example, -1.2 is converted to (-2, 800000000). */ +// Convert a number of seconds, int or float, to a timespec structure. +// nsec is in the range [0; 999999999] and rounded towards zero. +// For example, -1.2 is converted to (-2, 800000000). +// Export for '_testinternalcapi' shared extension. PyAPI_FUNC(int) _PyTime_ObjectToTimespec( PyObject *obj, time_t *sec, @@ -130,50 +129,62 @@ PyAPI_FUNC(int) _PyTime_ObjectToTimespec( _PyTime_round_t); -/* Create a timestamp from a number of seconds. */ +// Create a timestamp from a number of seconds. +// Export for '_socket' shared extension. PyAPI_FUNC(_PyTime_t) _PyTime_FromSeconds(int seconds); -/* Macro to create a timestamp from a number of seconds, no integer overflow. - Only use the macro for small values, prefer _PyTime_FromSeconds(). */ +// Create a timestamp from a number of seconds in double. +// Export for '_socket' shared extension. +PyAPI_FUNC(_PyTime_t) _PyTime_FromSecondsDouble(double seconds, _PyTime_round_t round); + +// Macro to create a timestamp from a number of seconds, no integer overflow. +// Only use the macro for small values, prefer _PyTime_FromSeconds(). #define _PYTIME_FROMSECONDS(seconds) \ ((_PyTime_t)(seconds) * (1000 * 1000 * 1000)) -/* Create a timestamp from a number of nanoseconds. */ +// Create a timestamp from a number of nanoseconds. +// Export for '_testinternalcapi' shared extension. PyAPI_FUNC(_PyTime_t) _PyTime_FromNanoseconds(_PyTime_t ns); -/* Create a timestamp from a number of microseconds. - * Clamp to [_PyTime_MIN; _PyTime_MAX] on overflow. */ +// Create a timestamp from a number of microseconds. +// Clamp to [_PyTime_MIN; _PyTime_MAX] on overflow. extern _PyTime_t _PyTime_FromMicrosecondsClamp(_PyTime_t us); -/* Create a timestamp from nanoseconds (Python int). */ +// Create a timestamp from nanoseconds (Python int). +// Export for '_lsprof' shared extension. PyAPI_FUNC(int) _PyTime_FromNanosecondsObject(_PyTime_t *t, PyObject *obj); -/* Convert a number of seconds (Python float or int) to a timestamp. - Raise an exception and return -1 on error, return 0 on success. */ +// Convert a number of seconds (Python float or int) to a timestamp. +// Raise an exception and return -1 on error, return 0 on success. +// Export for '_socket' shared extension. PyAPI_FUNC(int) _PyTime_FromSecondsObject(_PyTime_t *t, PyObject *obj, _PyTime_round_t round); -/* Convert a number of milliseconds (Python float or int, 10^-3) to a timestamp. - Raise an exception and return -1 on error, return 0 on success. */ +// Convert a number of milliseconds (Python float or int, 10^-3) to a timestamp. +// Raise an exception and return -1 on error, return 0 on success. +// Export for 'select' shared extension. PyAPI_FUNC(int) _PyTime_FromMillisecondsObject(_PyTime_t *t, PyObject *obj, _PyTime_round_t round); -/* Convert a timestamp to a number of seconds as a C double. */ +// Convert a timestamp to a number of seconds as a C double. +// Export for '_socket' shared extension. PyAPI_FUNC(double) _PyTime_AsSecondsDouble(_PyTime_t t); -/* Convert timestamp to a number of milliseconds (10^-3 seconds). */ +// Convert timestamp to a number of milliseconds (10^-3 seconds). +// Export for '_ssl' shared extension. PyAPI_FUNC(_PyTime_t) _PyTime_AsMilliseconds(_PyTime_t t, _PyTime_round_t round); -/* Convert timestamp to a number of microseconds (10^-6 seconds). */ +// Convert timestamp to a number of microseconds (10^-6 seconds). +// Export for '_queue' shared extension. PyAPI_FUNC(_PyTime_t) _PyTime_AsMicroseconds(_PyTime_t t, _PyTime_round_t round); -/* Convert timestamp to a number of nanoseconds (10^-9 seconds). */ -PyAPI_FUNC(_PyTime_t) _PyTime_AsNanoseconds(_PyTime_t t); +// Convert timestamp to a number of nanoseconds (10^-9 seconds). +extern _PyTime_t _PyTime_AsNanoseconds(_PyTime_t t); #ifdef MS_WINDOWS // Convert timestamp to a number of 100 nanoseconds (10^-7 seconds). @@ -181,36 +192,40 @@ extern _PyTime_t _PyTime_As100Nanoseconds(_PyTime_t t, _PyTime_round_t round); #endif -/* Convert timestamp to a number of nanoseconds (10^-9 seconds) as a Python int - object. */ +// Convert timestamp to a number of nanoseconds (10^-9 seconds) as a Python int +// object. +// Export for '_testinternalcapi' shared extension. PyAPI_FUNC(PyObject*) _PyTime_AsNanosecondsObject(_PyTime_t t); #ifndef MS_WINDOWS -/* Create a timestamp from a timeval structure. - Raise an exception and return -1 on overflow, return 0 on success. */ +// Create a timestamp from a timeval structure. +// Raise an exception and return -1 on overflow, return 0 on success. extern int _PyTime_FromTimeval(_PyTime_t *tp, struct timeval *tv); #endif -/* Convert a timestamp to a timeval structure (microsecond resolution). - tv_usec is always positive. - Raise an exception and return -1 if the conversion overflowed, - return 0 on success. */ +// Convert a timestamp to a timeval structure (microsecond resolution). +// tv_usec is always positive. +// Raise an exception and return -1 if the conversion overflowed, +// return 0 on success. +// Export for 'select' shared extension. PyAPI_FUNC(int) _PyTime_AsTimeval(_PyTime_t t, struct timeval *tv, _PyTime_round_t round); -/* Similar to _PyTime_AsTimeval() but don't raise an exception on overflow. - On overflow, clamp tv_sec to _PyTime_t min/max. */ +// Similar to _PyTime_AsTimeval() but don't raise an exception on overflow. +// On overflow, clamp tv_sec to _PyTime_t min/max. +// Export for 'select' shared extension. PyAPI_FUNC(void) _PyTime_AsTimeval_clamp(_PyTime_t t, struct timeval *tv, _PyTime_round_t round); -/* Convert a timestamp to a number of seconds (secs) and microseconds (us). - us is always positive. This function is similar to _PyTime_AsTimeval() - except that secs is always a time_t type, whereas the timeval structure - uses a C long for tv_sec on Windows. - Raise an exception and return -1 if the conversion overflowed, - return 0 on success. */ +// Convert a timestamp to a number of seconds (secs) and microseconds (us). +// us is always positive. This function is similar to _PyTime_AsTimeval() +// except that secs is always a time_t type, whereas the timeval structure +// uses a C long for tv_sec on Windows. +// Raise an exception and return -1 if the conversion overflowed, +// return 0 on success. +// Export for '_datetime' shared extension. PyAPI_FUNC(int) _PyTime_AsTimevalTime_t( _PyTime_t t, time_t *secs, @@ -218,17 +233,19 @@ PyAPI_FUNC(int) _PyTime_AsTimevalTime_t( _PyTime_round_t round); #if defined(HAVE_CLOCK_GETTIME) || defined(HAVE_KQUEUE) -/* Create a timestamp from a timespec structure. - Raise an exception and return -1 on overflow, return 0 on success. */ -extern int _PyTime_FromTimespec(_PyTime_t *tp, struct timespec *ts); - -/* Convert a timestamp to a timespec structure (nanosecond resolution). - tv_nsec is always positive. - Raise an exception and return -1 on error, return 0 on success. */ +// Create a timestamp from a timespec structure. +// Raise an exception and return -1 on overflow, return 0 on success. +extern int _PyTime_FromTimespec(_PyTime_t *tp, const struct timespec *ts); + +// Convert a timestamp to a timespec structure (nanosecond resolution). +// tv_nsec is always positive. +// Raise an exception and return -1 on error, return 0 on success. +// Export for '_testinternalcapi' shared extension. PyAPI_FUNC(int) _PyTime_AsTimespec(_PyTime_t t, struct timespec *ts); -/* Similar to _PyTime_AsTimespec() but don't raise an exception on overflow. - On overflow, clamp tv_sec to _PyTime_t min/max. */ +// Similar to _PyTime_AsTimespec() but don't raise an exception on overflow. +// On overflow, clamp tv_sec to _PyTime_t min/max. +// Export for '_testinternalcapi' shared extension. PyAPI_FUNC(void) _PyTime_AsTimespec_clamp(_PyTime_t t, struct timespec *ts); #endif @@ -236,14 +253,7 @@ PyAPI_FUNC(void) _PyTime_AsTimespec_clamp(_PyTime_t t, struct timespec *ts); // Compute t1 + t2. Clamp to [_PyTime_MIN; _PyTime_MAX] on overflow. extern _PyTime_t _PyTime_Add(_PyTime_t t1, _PyTime_t t2); -/* Compute ticks * mul / div. - Clamp to [_PyTime_MIN; _PyTime_MAX] on overflow. - The caller must ensure that ((div - 1) * mul) cannot overflow. */ -extern _PyTime_t _PyTime_MulDiv(_PyTime_t ticks, - _PyTime_t mul, - _PyTime_t div); - -/* Structure used by time.get_clock_info() */ +// Structure used by time.get_clock_info() typedef struct { const char *implementation; int monotonic; @@ -251,72 +261,77 @@ typedef struct { double resolution; } _Py_clock_info_t; -/* Get the current time from the system clock. - - If the internal clock fails, silently ignore the error and return 0. - On integer overflow, silently ignore the overflow and clamp the clock to - [_PyTime_MIN; _PyTime_MAX]. - - Use _PyTime_GetSystemClockWithInfo() to check for failure. */ +// Get the current time from the system clock. +// +// If the internal clock fails, silently ignore the error and return 0. +// On integer overflow, silently ignore the overflow and clamp the clock to +// [_PyTime_MIN; _PyTime_MAX]. +// +// Use _PyTime_GetSystemClockWithInfo() to check for failure. +// Export for '_random' shared extension. PyAPI_FUNC(_PyTime_t) _PyTime_GetSystemClock(void); -/* Get the current time from the system clock. - * On success, set *t and *info (if not NULL), and return 0. - * On error, raise an exception and return -1. - */ -PyAPI_FUNC(int) _PyTime_GetSystemClockWithInfo( +// Get the current time from the system clock. +// On success, set *t and *info (if not NULL), and return 0. +// On error, raise an exception and return -1. +extern int _PyTime_GetSystemClockWithInfo( _PyTime_t *t, _Py_clock_info_t *info); -/* Get the time of a monotonic clock, i.e. a clock that cannot go backwards. - The clock is not affected by system clock updates. The reference point of - the returned value is undefined, so that only the difference between the - results of consecutive calls is valid. - - If the internal clock fails, silently ignore the error and return 0. - On integer overflow, silently ignore the overflow and clamp the clock to - [_PyTime_MIN; _PyTime_MAX]. - - Use _PyTime_GetMonotonicClockWithInfo() to check for failure. */ +// Get the time of a monotonic clock, i.e. a clock that cannot go backwards. +// The clock is not affected by system clock updates. The reference point of +// the returned value is undefined, so that only the difference between the +// results of consecutive calls is valid. +// +// If the internal clock fails, silently ignore the error and return 0. +// On integer overflow, silently ignore the overflow and clamp the clock to +// [_PyTime_MIN; _PyTime_MAX]. +// +// Use _PyTime_GetMonotonicClockWithInfo() to check for failure. +// Export for '_random' shared extension. PyAPI_FUNC(_PyTime_t) _PyTime_GetMonotonicClock(void); -/* Get the time of a monotonic clock, i.e. a clock that cannot go backwards. - The clock is not affected by system clock updates. The reference point of - the returned value is undefined, so that only the difference between the - results of consecutive calls is valid. - - Fill info (if set) with information of the function used to get the time. - - Return 0 on success, raise an exception and return -1 on error. */ +// Get the time of a monotonic clock, i.e. a clock that cannot go backwards. +// The clock is not affected by system clock updates. The reference point of +// the returned value is undefined, so that only the difference between the +// results of consecutive calls is valid. +// +// Fill info (if set) with information of the function used to get the time. +// +// Return 0 on success, raise an exception and return -1 on error. +// Export for '_testsinglephase' shared extension. PyAPI_FUNC(int) _PyTime_GetMonotonicClockWithInfo( _PyTime_t *t, _Py_clock_info_t *info); -/* Converts a timestamp to the Gregorian time, using the local time zone. - Return 0 on success, raise an exception and return -1 on error. */ +// Converts a timestamp to the Gregorian time, using the local time zone. +// Return 0 on success, raise an exception and return -1 on error. +// Export for '_datetime' shared extension. PyAPI_FUNC(int) _PyTime_localtime(time_t t, struct tm *tm); -/* Converts a timestamp to the Gregorian time, assuming UTC. - Return 0 on success, raise an exception and return -1 on error. */ +// Converts a timestamp to the Gregorian time, assuming UTC. +// Return 0 on success, raise an exception and return -1 on error. +// Export for '_datetime' shared extension. PyAPI_FUNC(int) _PyTime_gmtime(time_t t, struct tm *tm); -/* Get the performance counter: clock with the highest available resolution to - measure a short duration. - - If the internal clock fails, silently ignore the error and return 0. - On integer overflow, silently ignore the overflow and clamp the clock to - [_PyTime_MIN; _PyTime_MAX]. - - Use _PyTime_GetPerfCounterWithInfo() to check for failure. */ +// Get the performance counter: clock with the highest available resolution to +// measure a short duration. +// +// If the internal clock fails, silently ignore the error and return 0. +// On integer overflow, silently ignore the overflow and clamp the clock to +// [_PyTime_MIN; _PyTime_MAX]. +// +// Use _PyTime_GetPerfCounterWithInfo() to check for failure. +// Export for '_lsprof' shared extension. PyAPI_FUNC(_PyTime_t) _PyTime_GetPerfCounter(void); -/* Get the performance counter: clock with the highest available resolution to - measure a short duration. - - Fill info (if set) with information of the function used to get the time. - - Return 0 on success, raise an exception and return -1 on error. */ +// Get the performance counter: clock with the highest available resolution to +// measure a short duration. +// +// Fill info (if set) with information of the function used to get the time. +// +// Return 0 on success, raise an exception and return -1 on error. extern int _PyTime_GetPerfCounterWithInfo( _PyTime_t *t, _Py_clock_info_t *info); @@ -333,7 +348,33 @@ PyAPI_FUNC(_PyTime_t) _PyDeadline_Init(_PyTime_t timeout); PyAPI_FUNC(_PyTime_t) _PyDeadline_Get(_PyTime_t deadline); +// --- _PyTimeFraction ------------------------------------------------------- + +typedef struct { + _PyTime_t numer; + _PyTime_t denom; +} _PyTimeFraction; + +// Set a fraction. +// Return 0 on success. +// Return -1 if the fraction is invalid. +extern int _PyTimeFraction_Set( + _PyTimeFraction *frac, + _PyTime_t numer, + _PyTime_t denom); + +// Compute ticks * frac.numer / frac.denom. +// Clamp to [_PyTime_MIN; _PyTime_MAX] on overflow. +extern _PyTime_t _PyTimeFraction_Mul( + _PyTime_t ticks, + const _PyTimeFraction *frac); + +// Compute a clock resolution: frac.numer / frac.denom / 1e9. +extern double _PyTimeFraction_Resolution( + const _PyTimeFraction *frac); + + #ifdef __cplusplus } #endif -#endif /* !Py_INTERNAL_TIME_H */ +#endif // !Py_INTERNAL_TIME_H diff --git a/Include/internal/pycore_token.h b/Include/internal/pycore_token.h index 9c65cd802d597c..571cd6249f2812 100644 --- a/Include/internal/pycore_token.h +++ b/Include/internal/pycore_token.h @@ -1,4 +1,4 @@ -/* Auto-generated by Tools/build/generate_token.py */ +// Auto-generated by Tools/build/generate_token.py /* Token types */ #ifndef Py_INTERNAL_TOKEN_H @@ -94,7 +94,7 @@ extern "C" { (x) == FSTRING_MIDDLE) -// Symbols exported for test_peg_generator +// Export these 4 symbols for 'test_peg_generator' PyAPI_DATA(const char * const) _PyParser_TokenNames[]; /* Token names */ PyAPI_FUNC(int) _PyToken_OneChar(int); PyAPI_FUNC(int) _PyToken_TwoChars(int, int); diff --git a/Include/internal/pycore_traceback.h b/Include/internal/pycore_traceback.h index 21fb4a25a0face..10922bff98bd4b 100644 --- a/Include/internal/pycore_traceback.h +++ b/Include/internal/pycore_traceback.h @@ -8,6 +8,12 @@ extern "C" { # error "this header requires Py_BUILD_CORE define" #endif +// Export for '_ctypes' shared extension +PyAPI_FUNC(int) _Py_DisplaySourceLine(PyObject *, PyObject *, int, int, int *, PyObject **); + +// Export for 'pyexact' shared extension +PyAPI_FUNC(void) _PyTraceback_Add(const char *, const char *, int); + /* Write the Python traceback into the file 'fd'. For example: Traceback (most recent call first): @@ -89,9 +95,8 @@ extern PyObject* _PyTraceBack_FromFrame( /* Write the traceback tb to file f. Prefix each line with indent spaces followed by the margin (if it is not NULL). */ -extern int _PyTraceBack_Print_Indented( - PyObject *tb, int indent, const char* margin, - const char *header_margin, const char *header, PyObject *f); +extern int _PyTraceBack_Print( + PyObject *tb, const char *header, PyObject *f); extern int _Py_WriteIndentedMargin(int, const char*, PyObject *); extern int _Py_WriteIndent(int, PyObject *); diff --git a/Include/internal/pycore_tstate.h b/Include/internal/pycore_tstate.h new file mode 100644 index 00000000000000..472fa08154e8f9 --- /dev/null +++ b/Include/internal/pycore_tstate.h @@ -0,0 +1,33 @@ +#ifndef Py_INTERNAL_TSTATE_H +#define Py_INTERNAL_TSTATE_H +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef Py_BUILD_CORE +# error "this header requires Py_BUILD_CORE define" +#endif + +#include "pycore_freelist.h" // struct _Py_freelist_state +#include "pycore_mimalloc.h" // struct _mimalloc_thread_state + + +// Every PyThreadState is actually allocated as a _PyThreadStateImpl. The +// PyThreadState fields are exposed as part of the C API, although most fields +// are intended to be private. The _PyThreadStateImpl fields not exposed. +typedef struct _PyThreadStateImpl { + // semi-public fields are in PyThreadState. + PyThreadState base; + +#ifdef Py_GIL_DISABLED + struct _mimalloc_thread_state mimalloc; + struct _Py_freelist_state freelist_state; +#endif + +} _PyThreadStateImpl; + + +#ifdef __cplusplus +} +#endif +#endif /* !Py_INTERNAL_TSTATE_H */ diff --git a/Include/internal/pycore_tuple.h b/Include/internal/pycore_tuple.h index 4fa7a12206bcb2..b348339a505b0f 100644 --- a/Include/internal/pycore_tuple.h +++ b/Include/internal/pycore_tuple.h @@ -14,59 +14,16 @@ extern void _PyTuple_DebugMallocStats(FILE *out); /* runtime lifecycle */ extern PyStatus _PyTuple_InitGlobalObjects(PyInterpreterState *); -extern void _PyTuple_Fini(PyInterpreterState *); +extern void _PyTuple_Fini(_PyFreeListState *); /* other API */ -// PyTuple_MAXSAVESIZE - largest tuple to save on free list -// PyTuple_MAXFREELIST - maximum number of tuples of each size to save - -#if defined(PyTuple_MAXSAVESIZE) && PyTuple_MAXSAVESIZE <= 0 - // A build indicated that tuple freelists should not be used. -# define PyTuple_NFREELISTS 0 -# undef PyTuple_MAXSAVESIZE -# undef PyTuple_MAXFREELIST - -#elif !defined(WITH_FREELISTS) -# define PyTuple_NFREELISTS 0 -# undef PyTuple_MAXSAVESIZE -# undef PyTuple_MAXFREELIST - -#else - // We are using a freelist for tuples. -# ifndef PyTuple_MAXSAVESIZE -# define PyTuple_MAXSAVESIZE 20 -# endif -# define PyTuple_NFREELISTS PyTuple_MAXSAVESIZE -# ifndef PyTuple_MAXFREELIST -# define PyTuple_MAXFREELIST 2000 -# endif -#endif - -struct _Py_tuple_state { -#if PyTuple_NFREELISTS > 0 - /* There is one freelist for each size from 1 to PyTuple_MAXSAVESIZE. - The empty tuple is handled separately. - - Each tuple stored in the array is the head of the linked list - (and the next available tuple) for that size. The actual tuple - object is used as the linked list node, with its first item - (ob_item[0]) pointing to the next node (i.e. the previous head). - Each linked list is initially NULL. */ - PyTupleObject *free_list[PyTuple_NFREELISTS]; - int numfree[PyTuple_NFREELISTS]; -#else - char _unused; // Empty structs are not allowed. -#endif -}; - #define _PyTuple_ITEMS(op) _Py_RVALUE(_PyTuple_CAST(op)->ob_item) extern PyObject *_PyTuple_FromArray(PyObject *const *, Py_ssize_t); extern PyObject *_PyTuple_FromArraySteal(PyObject *const *, Py_ssize_t); - typedef struct { PyObject_HEAD Py_ssize_t it_index; diff --git a/Include/internal/pycore_typeobject.h b/Include/internal/pycore_typeobject.h index aba672effe3928..c03c3d766bef61 100644 --- a/Include/internal/pycore_typeobject.h +++ b/Include/internal/pycore_typeobject.h @@ -4,12 +4,12 @@ extern "C" { #endif -#include "pycore_moduleobject.h" - #ifndef Py_BUILD_CORE # error "this header requires Py_BUILD_CORE define" #endif +#include "pycore_moduleobject.h" // PyModuleObject + /* state */ @@ -114,8 +114,10 @@ extern static_builtin_state * _PyStaticType_GetState(PyInterpreterState *, PyTyp extern void _PyStaticType_ClearWeakRefs(PyInterpreterState *, PyTypeObject *type); extern void _PyStaticType_Dealloc(PyInterpreterState *, PyTypeObject *); -// Export for 'math' shared extension via _PyType_IsReady() function +// Export for 'math' shared extension, used via _PyType_IsReady() static inline +// function PyAPI_FUNC(PyObject *) _PyType_GetDict(PyTypeObject *); + extern PyObject * _PyType_GetBases(PyTypeObject *type); extern PyObject * _PyType_GetMRO(PyTypeObject *type); extern PyObject* _PyType_GetSubclasses(PyTypeObject *); @@ -131,7 +133,9 @@ _PyType_IsReady(PyTypeObject *type) extern PyObject* _Py_type_getattro_impl(PyTypeObject *type, PyObject *name, int *suppress_missing_attribute); -extern PyObject* _Py_type_getattro(PyTypeObject *type, PyObject *name); +extern PyObject* _Py_type_getattro(PyObject *type, PyObject *name); + +extern PyObject* _Py_BaseObject_RichCompare(PyObject* self, PyObject* other, int op); extern PyObject* _Py_slot_tp_getattro(PyObject *self, PyObject *name); extern PyObject* _Py_slot_tp_getattr_hook(PyObject *self, PyObject *name); @@ -141,6 +145,11 @@ extern PyTypeObject _PyBufferWrapper_Type; extern PyObject* _PySuper_Lookup(PyTypeObject *su_type, PyObject *su_obj, PyObject *name, int *meth_found); + +// This is exported for the _testinternalcapi module. +PyAPI_FUNC(PyObject *) _PyType_GetModuleName(PyTypeObject *); + + #ifdef __cplusplus } #endif diff --git a/Include/internal/pycore_ucnhash.h b/Include/internal/pycore_ucnhash.h index 187dd68e7347ff..1561dfbb3150d3 100644 --- a/Include/internal/pycore_ucnhash.h +++ b/Include/internal/pycore_ucnhash.h @@ -28,6 +28,8 @@ typedef struct { } _PyUnicode_Name_CAPI; +extern _PyUnicode_Name_CAPI* _PyUnicode_GetNameCAPI(void); + #ifdef __cplusplus } #endif diff --git a/Include/internal/pycore_unicodeobject.h b/Include/internal/pycore_unicodeobject.h index 8ec80ddb83d10f..7ee540154b23d8 100644 --- a/Include/internal/pycore_unicodeobject.h +++ b/Include/internal/pycore_unicodeobject.h @@ -8,7 +8,9 @@ extern "C" { # error "this header requires Py_BUILD_CORE define" #endif +#include "pycore_lock.h" // PyMutex #include "pycore_fileutils.h" // _Py_error_handler +#include "pycore_identifier.h" // _Py_Identifier #include "pycore_ucnhash.h" // _PyUnicode_Name_CAPI /* --- Characters Type APIs ----------------------------------------------- */ @@ -24,6 +26,7 @@ extern int _PyUnicode_IsCased(Py_UCS4 ch); /* --- Unicode API -------------------------------------------------------- */ +// Export for '_json' shared extension PyAPI_FUNC(int) _PyUnicode_CheckConsistency( PyObject *op, int check_content); @@ -31,10 +34,10 @@ PyAPI_FUNC(int) _PyUnicode_CheckConsistency( extern void _PyUnicode_ExactDealloc(PyObject *op); extern Py_ssize_t _PyUnicode_InternedSize(void); -/* Get a copy of a Unicode string. */ +// Get a copy of a Unicode string. +// Export for '_datetime' shared extension. PyAPI_FUNC(PyObject*) _PyUnicode_Copy( - PyObject *unicode - ); + PyObject *unicode); /* Unsafe version of PyUnicode_Fill(): don't check arguments and so may crash if parameters are invalid (e.g. if length is longer than the string). */ @@ -71,120 +74,6 @@ extern Py_UCS4 _PyUnicode_FindMaxChar ( /* --- _PyUnicodeWriter API ----------------------------------------------- */ -typedef struct { - PyObject *buffer; - void *data; - int kind; - Py_UCS4 maxchar; - Py_ssize_t size; - Py_ssize_t pos; - - /* minimum number of allocated characters (default: 0) */ - Py_ssize_t min_length; - - /* minimum character (default: 127, ASCII) */ - Py_UCS4 min_char; - - /* If non-zero, overallocate the buffer (default: 0). */ - unsigned char overallocate; - - /* If readonly is 1, buffer is a shared string (cannot be modified) - and size is set to 0. */ - unsigned char readonly; -} _PyUnicodeWriter ; - -/* Initialize a Unicode writer. - * - * By default, the minimum buffer size is 0 character and overallocation is - * disabled. Set min_length, min_char and overallocate attributes to control - * the allocation of the buffer. */ -PyAPI_FUNC(void) -_PyUnicodeWriter_Init(_PyUnicodeWriter *writer); - -/* Prepare the buffer to write 'length' characters - with the specified maximum character. - - Return 0 on success, raise an exception and return -1 on error. */ -#define _PyUnicodeWriter_Prepare(WRITER, LENGTH, MAXCHAR) \ - (((MAXCHAR) <= (WRITER)->maxchar \ - && (LENGTH) <= (WRITER)->size - (WRITER)->pos) \ - ? 0 \ - : (((LENGTH) == 0) \ - ? 0 \ - : _PyUnicodeWriter_PrepareInternal((WRITER), (LENGTH), (MAXCHAR)))) - -/* Don't call this function directly, use the _PyUnicodeWriter_Prepare() macro - instead. */ -PyAPI_FUNC(int) -_PyUnicodeWriter_PrepareInternal(_PyUnicodeWriter *writer, - Py_ssize_t length, Py_UCS4 maxchar); - -/* Prepare the buffer to have at least the kind KIND. - For example, kind=PyUnicode_2BYTE_KIND ensures that the writer will - support characters in range U+000-U+FFFF. - - Return 0 on success, raise an exception and return -1 on error. */ -#define _PyUnicodeWriter_PrepareKind(WRITER, KIND) \ - ((KIND) <= (WRITER)->kind \ - ? 0 \ - : _PyUnicodeWriter_PrepareKindInternal((WRITER), (KIND))) - -/* Don't call this function directly, use the _PyUnicodeWriter_PrepareKind() - macro instead. */ -PyAPI_FUNC(int) -_PyUnicodeWriter_PrepareKindInternal(_PyUnicodeWriter *writer, - int kind); - -/* Append a Unicode character. - Return 0 on success, raise an exception and return -1 on error. */ -PyAPI_FUNC(int) -_PyUnicodeWriter_WriteChar(_PyUnicodeWriter *writer, - Py_UCS4 ch - ); - -/* Append a Unicode string. - Return 0 on success, raise an exception and return -1 on error. */ -PyAPI_FUNC(int) -_PyUnicodeWriter_WriteStr(_PyUnicodeWriter *writer, - PyObject *str /* Unicode string */ - ); - -/* Append a substring of a Unicode string. - Return 0 on success, raise an exception and return -1 on error. */ -PyAPI_FUNC(int) -_PyUnicodeWriter_WriteSubstring(_PyUnicodeWriter *writer, - PyObject *str, /* Unicode string */ - Py_ssize_t start, - Py_ssize_t end - ); - -/* Append an ASCII-encoded byte string. - Return 0 on success, raise an exception and return -1 on error. */ -PyAPI_FUNC(int) -_PyUnicodeWriter_WriteASCIIString(_PyUnicodeWriter *writer, - const char *str, /* ASCII-encoded byte string */ - Py_ssize_t len /* number of bytes, or -1 if unknown */ - ); - -/* Append a latin1-encoded byte string. - Return 0 on success, raise an exception and return -1 on error. */ -PyAPI_FUNC(int) -_PyUnicodeWriter_WriteLatin1String(_PyUnicodeWriter *writer, - const char *str, /* latin1-encoded byte string */ - Py_ssize_t len /* length in bytes */ - ); - -/* Get the value of the writer as a Unicode string. Clear the - buffer of the writer. Raise an exception and return NULL - on error. */ -PyAPI_FUNC(PyObject *) -_PyUnicodeWriter_Finish(_PyUnicodeWriter *writer); - -/* Deallocate memory of a writer (clear its internal buffer). */ -PyAPI_FUNC(void) -_PyUnicodeWriter_Dealloc(_PyUnicodeWriter *writer); - - /* Format the object based on the format_spec, as defined in PEP 3101 (Advanced String Formatting). */ extern int _PyUnicode_FormatAdvancedWriter( @@ -204,12 +93,14 @@ extern PyObject* _PyUnicode_EncodeUTF7( /* --- UTF-8 Codecs ------------------------------------------------------- */ +// Export for '_tkinter' shared extension. PyAPI_FUNC(PyObject*) _PyUnicode_AsUTF8String( PyObject *unicode, const char *errors); /* --- UTF-32 Codecs ------------------------------------------------------ */ +// Export for '_tkinter' shared extension PyAPI_FUNC(PyObject*) _PyUnicode_EncodeUTF32( PyObject *object, /* Unicode object */ const char *errors, /* error handling */ @@ -217,20 +108,21 @@ PyAPI_FUNC(PyObject*) _PyUnicode_EncodeUTF32( /* --- UTF-16 Codecs ------------------------------------------------------ */ -/* Returns a Python string object holding the UTF-16 encoded value of - the Unicode data. - - If byteorder is not 0, output is written according to the following - byte order: - - byteorder == -1: little endian - byteorder == 0: native byte order (writes a BOM mark) - byteorder == 1: big endian - - If byteorder is 0, the output string will always start with the - Unicode BOM mark (U+FEFF). In the other two modes, no BOM mark is - prepended. -*/ +// Returns a Python string object holding the UTF-16 encoded value of +// the Unicode data. +// +// If byteorder is not 0, output is written according to the following +// byte order: +// +// byteorder == -1: little endian +// byteorder == 0: native byte order (writes a BOM mark) +// byteorder == 1: big endian +// +// If byteorder is 0, the output string will always start with the +// Unicode BOM mark (U+FEFF). In the other two modes, no BOM mark is +// prepended. +// +// Export for '_tkinter' shared extension PyAPI_FUNC(PyObject*) _PyUnicode_EncodeUTF16( PyObject* unicode, /* Unicode object */ const char *errors, /* error handling */ @@ -297,13 +189,14 @@ extern PyObject* _PyUnicode_EncodeCharmap( /* --- Decimal Encoder ---------------------------------------------------- */ -/* Coverts a Unicode object holding a decimal value to an ASCII string - for using in int, float and complex parsers. - Transforms code points that have decimal digit property to the - corresponding ASCII digit code points. Transforms spaces to ASCII. - Transforms code points starting from the first non-ASCII code point that - is neither a decimal digit nor a space to the end into '?'. */ - +// Coverts a Unicode object holding a decimal value to an ASCII string +// for using in int, float and complex parsers. +// Transforms code points that have decimal digit property to the +// corresponding ASCII digit code points. Transforms spaces to ASCII. +// Transforms code points starting from the first non-ASCII code point that +// is neither a decimal digit nor a space to the end into '?'. +// +// Export for '_testinternalcapi' shared extension. PyAPI_FUNC(PyObject*) _PyUnicode_TransformDecimalAndSpaceToASCII( PyObject *unicode); /* Unicode object */ @@ -323,9 +216,10 @@ extern int _PyUnicode_EqualToASCIIId( _Py_Identifier *right /* Right identifier */ ); -/* Test whether a unicode is equal to ASCII string. Return 1 if true, - 0 otherwise. The right argument must be ASCII-encoded string. - Any error occurs inside will be cleared before return. */ +// Test whether a unicode is equal to ASCII string. Return 1 if true, +// 0 otherwise. The right argument must be ASCII-encoded string. +// Any error occurs inside will be cleared before return. +// Export for '_ctypes' shared extension PyAPI_FUNC(int) _PyUnicode_EqualToASCIIString( PyObject *left, const char *right /* ASCII-encoded string */ @@ -357,14 +251,12 @@ extern Py_ssize_t _PyUnicode_InsertThousandsGrouping( extern PyObject* _PyUnicode_FormatLong(PyObject *, int, int, int); -/* Return an interned Unicode object for an Identifier; may fail if there is no memory.*/ -PyAPI_FUNC(PyObject*) _PyUnicode_FromId(_Py_Identifier*); - /* Fast equality check when the inputs are known to be exact unicode types and where the hash values are equal (i.e. a very probable match) */ extern int _PyUnicode_EQ(PyObject *, PyObject *); -/* Equality check. */ +// Equality check. +// Export for '_pickle' shared extension. PyAPI_FUNC(int) _PyUnicode_Equal(PyObject *, PyObject *); extern int _PyUnicode_WideCharString_Converter(PyObject *, void *); @@ -386,7 +278,7 @@ extern PyTypeObject _PyUnicodeASCIIIter_Type; /* --- Other API ---------------------------------------------------------- */ struct _Py_unicode_runtime_ids { - PyThread_type_lock lock; + PyMutex mutex; // next_index value must be preserved when Py_Initialize()/Py_Finalize() // is called multiple times: see _PyUnicode_FromId() implementation. Py_ssize_t next_index; @@ -422,6 +314,10 @@ struct _Py_unicode_state { extern void _PyUnicode_InternInPlace(PyInterpreterState *interp, PyObject **p); extern void _PyUnicode_ClearInterned(PyInterpreterState *interp); +// Like PyUnicode_AsUTF8(), but check for embedded null characters. +// Export for '_sqlite3' shared extension. +PyAPI_FUNC(const char *) _PyUnicode_AsUTF8NoNUL(PyObject *); + #ifdef __cplusplus } diff --git a/Include/internal/pycore_unicodeobject_generated.h b/Include/internal/pycore_unicodeobject_generated.h index 59f40075f93983..2f9874029fb8f1 100644 --- a/Include/internal/pycore_unicodeobject_generated.h +++ b/Include/internal/pycore_unicodeobject_generated.h @@ -669,21 +669,12 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { string = &_Py_ID(aggregate_class); assert(_PyUnicode_CheckConsistency(string, 1)); _PyUnicode_InternInPlace(interp, &string); - string = &_Py_ID(alias); - assert(_PyUnicode_CheckConsistency(string, 1)); - _PyUnicode_InternInPlace(interp, &string); string = &_Py_ID(append); assert(_PyUnicode_CheckConsistency(string, 1)); _PyUnicode_InternInPlace(interp, &string); - string = &_Py_ID(arg); - assert(_PyUnicode_CheckConsistency(string, 1)); - _PyUnicode_InternInPlace(interp, &string); string = &_Py_ID(argdefs); assert(_PyUnicode_CheckConsistency(string, 1)); _PyUnicode_InternInPlace(interp, &string); - string = &_Py_ID(args); - assert(_PyUnicode_CheckConsistency(string, 1)); - _PyUnicode_InternInPlace(interp, &string); string = &_Py_ID(arguments); assert(_PyUnicode_CheckConsistency(string, 1)); _PyUnicode_InternInPlace(interp, &string); @@ -795,6 +786,9 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { string = &_Py_ID(call_soon); assert(_PyUnicode_CheckConsistency(string, 1)); _PyUnicode_InternInPlace(interp, &string); + string = &_Py_ID(callback); + assert(_PyUnicode_CheckConsistency(string, 1)); + _PyUnicode_InternInPlace(interp, &string); string = &_Py_ID(cancel); assert(_PyUnicode_CheckConsistency(string, 1)); _PyUnicode_InternInPlace(interp, &string); @@ -1005,9 +999,6 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { string = &_Py_ID(dst_dir_fd); assert(_PyUnicode_CheckConsistency(string, 1)); _PyUnicode_InternInPlace(interp, &string); - string = &_Py_ID(duration); - assert(_PyUnicode_CheckConsistency(string, 1)); - _PyUnicode_InternInPlace(interp, &string); string = &_Py_ID(e); assert(_PyUnicode_CheckConsistency(string, 1)); _PyUnicode_InternInPlace(interp, &string); @@ -1053,12 +1044,6 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { string = &_Py_ID(eventmask); assert(_PyUnicode_CheckConsistency(string, 1)); _PyUnicode_InternInPlace(interp, &string); - string = &_Py_ID(exc_type); - assert(_PyUnicode_CheckConsistency(string, 1)); - _PyUnicode_InternInPlace(interp, &string); - string = &_Py_ID(exc_value); - assert(_PyUnicode_CheckConsistency(string, 1)); - _PyUnicode_InternInPlace(interp, &string); string = &_Py_ID(excepthook); assert(_PyUnicode_CheckConsistency(string, 1)); _PyUnicode_InternInPlace(interp, &string); @@ -1077,6 +1062,9 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { string = &_Py_ID(extra_tokens); assert(_PyUnicode_CheckConsistency(string, 1)); _PyUnicode_InternInPlace(interp, &string); + string = &_Py_ID(f); + assert(_PyUnicode_CheckConsistency(string, 1)); + _PyUnicode_InternInPlace(interp, &string); string = &_Py_ID(facility); assert(_PyUnicode_CheckConsistency(string, 1)); _PyUnicode_InternInPlace(interp, &string); @@ -1146,9 +1134,6 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { string = &_Py_ID(format); assert(_PyUnicode_CheckConsistency(string, 1)); _PyUnicode_InternInPlace(interp, &string); - string = &_Py_ID(frequency); - assert(_PyUnicode_CheckConsistency(string, 1)); - _PyUnicode_InternInPlace(interp, &string); string = &_Py_ID(from_param); assert(_PyUnicode_CheckConsistency(string, 1)); _PyUnicode_InternInPlace(interp, &string); @@ -1170,6 +1155,9 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { string = &_Py_ID(future); assert(_PyUnicode_CheckConsistency(string, 1)); _PyUnicode_InternInPlace(interp, &string); + string = &_Py_ID(g); + assert(_PyUnicode_CheckConsistency(string, 1)); + _PyUnicode_InternInPlace(interp, &string); string = &_Py_ID(generation); assert(_PyUnicode_CheckConsistency(string, 1)); _PyUnicode_InternInPlace(interp, &string); @@ -1209,6 +1197,9 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { string = &_Py_ID(groups); assert(_PyUnicode_CheckConsistency(string, 1)); _PyUnicode_InternInPlace(interp, &string); + string = &_Py_ID(h); + assert(_PyUnicode_CheckConsistency(string, 1)); + _PyUnicode_InternInPlace(interp, &string); string = &_Py_ID(handle); assert(_PyUnicode_CheckConsistency(string, 1)); _PyUnicode_InternInPlace(interp, &string); @@ -1233,6 +1224,9 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { string = &_Py_ID(ident); assert(_PyUnicode_CheckConsistency(string, 1)); _PyUnicode_InternInPlace(interp, &string); + string = &_Py_ID(identity_hint); + assert(_PyUnicode_CheckConsistency(string, 1)); + _PyUnicode_InternInPlace(interp, &string); string = &_Py_ID(ignore); assert(_PyUnicode_CheckConsistency(string, 1)); _PyUnicode_InternInPlace(interp, &string); @@ -1293,6 +1287,9 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { string = &_Py_ID(intersection); assert(_PyUnicode_CheckConsistency(string, 1)); _PyUnicode_InternInPlace(interp, &string); + string = &_Py_ID(interval); + assert(_PyUnicode_CheckConsistency(string, 1)); + _PyUnicode_InternInPlace(interp, &string); string = &_Py_ID(is_running); assert(_PyUnicode_CheckConsistency(string, 1)); _PyUnicode_InternInPlace(interp, &string); @@ -1356,6 +1353,9 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { string = &_Py_ID(kw2); assert(_PyUnicode_CheckConsistency(string, 1)); _PyUnicode_InternInPlace(interp, &string); + string = &_Py_ID(kwdefaults); + assert(_PyUnicode_CheckConsistency(string, 1)); + _PyUnicode_InternInPlace(interp, &string); string = &_Py_ID(lambda); assert(_PyUnicode_CheckConsistency(string, 1)); _PyUnicode_InternInPlace(interp, &string); @@ -1803,9 +1803,6 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { string = &_Py_ID(selectors); assert(_PyUnicode_CheckConsistency(string, 1)); _PyUnicode_InternInPlace(interp, &string); - string = &_Py_ID(self); - assert(_PyUnicode_CheckConsistency(string, 1)); - _PyUnicode_InternInPlace(interp, &string); string = &_Py_ID(send); assert(_PyUnicode_CheckConsistency(string, 1)); _PyUnicode_InternInPlace(interp, &string); @@ -1869,9 +1866,6 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { string = &_Py_ID(sort); assert(_PyUnicode_CheckConsistency(string, 1)); _PyUnicode_InternInPlace(interp, &string); - string = &_Py_ID(sound); - assert(_PyUnicode_CheckConsistency(string, 1)); - _PyUnicode_InternInPlace(interp, &string); string = &_Py_ID(source); assert(_PyUnicode_CheckConsistency(string, 1)); _PyUnicode_InternInPlace(interp, &string); @@ -1995,9 +1989,6 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { string = &_Py_ID(trace_callback); assert(_PyUnicode_CheckConsistency(string, 1)); _PyUnicode_InternInPlace(interp, &string); - string = &_Py_ID(traceback); - assert(_PyUnicode_CheckConsistency(string, 1)); - _PyUnicode_InternInPlace(interp, &string); string = &_Py_ID(trailers); assert(_PyUnicode_CheckConsistency(string, 1)); _PyUnicode_InternInPlace(interp, &string); diff --git a/Include/internal/pycore_uop_ids.h b/Include/internal/pycore_uop_ids.h new file mode 100644 index 00000000000000..b3b36327c480cc --- /dev/null +++ b/Include/internal/pycore_uop_ids.h @@ -0,0 +1,241 @@ +// This file is generated by Tools/cases_generator/uop_id_generator.py +// from: +// Python/bytecodes.c +// Do not edit! + +#ifndef Py_CORE_UOP_IDS_H +#define Py_CORE_UOP_IDS_H +#ifdef __cplusplus +extern "C" { +#endif + +#define _EXIT_TRACE 300 +#define _SET_IP 301 +#define _NOP NOP +#define _RESUME_CHECK RESUME_CHECK +#define _INSTRUMENTED_RESUME INSTRUMENTED_RESUME +#define _LOAD_FAST_CHECK LOAD_FAST_CHECK +#define _LOAD_FAST LOAD_FAST +#define _LOAD_FAST_AND_CLEAR LOAD_FAST_AND_CLEAR +#define _LOAD_FAST_LOAD_FAST LOAD_FAST_LOAD_FAST +#define _LOAD_CONST LOAD_CONST +#define _STORE_FAST STORE_FAST +#define _STORE_FAST_LOAD_FAST STORE_FAST_LOAD_FAST +#define _STORE_FAST_STORE_FAST STORE_FAST_STORE_FAST +#define _POP_TOP POP_TOP +#define _PUSH_NULL PUSH_NULL +#define _END_SEND END_SEND +#define _UNARY_NEGATIVE UNARY_NEGATIVE +#define _UNARY_NOT UNARY_NOT +#define _TO_BOOL 302 +#define _TO_BOOL_BOOL TO_BOOL_BOOL +#define _TO_BOOL_INT TO_BOOL_INT +#define _TO_BOOL_LIST TO_BOOL_LIST +#define _TO_BOOL_NONE TO_BOOL_NONE +#define _TO_BOOL_STR TO_BOOL_STR +#define _TO_BOOL_ALWAYS_TRUE TO_BOOL_ALWAYS_TRUE +#define _UNARY_INVERT UNARY_INVERT +#define _GUARD_BOTH_INT 303 +#define _BINARY_OP_MULTIPLY_INT 304 +#define _BINARY_OP_ADD_INT 305 +#define _BINARY_OP_SUBTRACT_INT 306 +#define _GUARD_BOTH_FLOAT 307 +#define _BINARY_OP_MULTIPLY_FLOAT 308 +#define _BINARY_OP_ADD_FLOAT 309 +#define _BINARY_OP_SUBTRACT_FLOAT 310 +#define _GUARD_BOTH_UNICODE 311 +#define _BINARY_OP_ADD_UNICODE 312 +#define _BINARY_SUBSCR 313 +#define _BINARY_SLICE BINARY_SLICE +#define _STORE_SLICE STORE_SLICE +#define _BINARY_SUBSCR_LIST_INT BINARY_SUBSCR_LIST_INT +#define _BINARY_SUBSCR_STR_INT BINARY_SUBSCR_STR_INT +#define _BINARY_SUBSCR_TUPLE_INT BINARY_SUBSCR_TUPLE_INT +#define _BINARY_SUBSCR_DICT BINARY_SUBSCR_DICT +#define _BINARY_SUBSCR_GETITEM BINARY_SUBSCR_GETITEM +#define _LIST_APPEND LIST_APPEND +#define _SET_ADD SET_ADD +#define _STORE_SUBSCR 314 +#define _STORE_SUBSCR_LIST_INT STORE_SUBSCR_LIST_INT +#define _STORE_SUBSCR_DICT STORE_SUBSCR_DICT +#define _DELETE_SUBSCR DELETE_SUBSCR +#define _CALL_INTRINSIC_1 CALL_INTRINSIC_1 +#define _CALL_INTRINSIC_2 CALL_INTRINSIC_2 +#define _POP_FRAME 315 +#define _INSTRUMENTED_RETURN_VALUE INSTRUMENTED_RETURN_VALUE +#define _INSTRUMENTED_RETURN_CONST INSTRUMENTED_RETURN_CONST +#define _GET_AITER GET_AITER +#define _GET_ANEXT GET_ANEXT +#define _GET_AWAITABLE GET_AWAITABLE +#define _SEND 316 +#define _SEND_GEN SEND_GEN +#define _INSTRUMENTED_YIELD_VALUE INSTRUMENTED_YIELD_VALUE +#define _POP_EXCEPT POP_EXCEPT +#define _LOAD_ASSERTION_ERROR LOAD_ASSERTION_ERROR +#define _LOAD_BUILD_CLASS LOAD_BUILD_CLASS +#define _STORE_NAME STORE_NAME +#define _DELETE_NAME DELETE_NAME +#define _UNPACK_SEQUENCE 317 +#define _UNPACK_SEQUENCE_TWO_TUPLE UNPACK_SEQUENCE_TWO_TUPLE +#define _UNPACK_SEQUENCE_TUPLE UNPACK_SEQUENCE_TUPLE +#define _UNPACK_SEQUENCE_LIST UNPACK_SEQUENCE_LIST +#define _UNPACK_EX UNPACK_EX +#define _STORE_ATTR 318 +#define _DELETE_ATTR DELETE_ATTR +#define _STORE_GLOBAL STORE_GLOBAL +#define _DELETE_GLOBAL DELETE_GLOBAL +#define _LOAD_LOCALS LOAD_LOCALS +#define _LOAD_FROM_DICT_OR_GLOBALS LOAD_FROM_DICT_OR_GLOBALS +#define _LOAD_NAME LOAD_NAME +#define _LOAD_GLOBAL 319 +#define _GUARD_GLOBALS_VERSION 320 +#define _GUARD_BUILTINS_VERSION 321 +#define _LOAD_GLOBAL_MODULE 322 +#define _LOAD_GLOBAL_BUILTINS 323 +#define _DELETE_FAST DELETE_FAST +#define _MAKE_CELL MAKE_CELL +#define _DELETE_DEREF DELETE_DEREF +#define _LOAD_FROM_DICT_OR_DEREF LOAD_FROM_DICT_OR_DEREF +#define _LOAD_DEREF LOAD_DEREF +#define _STORE_DEREF STORE_DEREF +#define _COPY_FREE_VARS COPY_FREE_VARS +#define _BUILD_STRING BUILD_STRING +#define _BUILD_TUPLE BUILD_TUPLE +#define _BUILD_LIST BUILD_LIST +#define _LIST_EXTEND LIST_EXTEND +#define _SET_UPDATE SET_UPDATE +#define _BUILD_SET BUILD_SET +#define _BUILD_MAP BUILD_MAP +#define _SETUP_ANNOTATIONS SETUP_ANNOTATIONS +#define _BUILD_CONST_KEY_MAP BUILD_CONST_KEY_MAP +#define _DICT_UPDATE DICT_UPDATE +#define _DICT_MERGE DICT_MERGE +#define _MAP_ADD MAP_ADD +#define _INSTRUMENTED_LOAD_SUPER_ATTR INSTRUMENTED_LOAD_SUPER_ATTR +#define _LOAD_SUPER_ATTR_ATTR LOAD_SUPER_ATTR_ATTR +#define _LOAD_SUPER_ATTR_METHOD LOAD_SUPER_ATTR_METHOD +#define _LOAD_ATTR 324 +#define _GUARD_TYPE_VERSION 325 +#define _CHECK_MANAGED_OBJECT_HAS_VALUES 326 +#define _LOAD_ATTR_INSTANCE_VALUE 327 +#define _CHECK_ATTR_MODULE 328 +#define _LOAD_ATTR_MODULE 329 +#define _CHECK_ATTR_WITH_HINT 330 +#define _LOAD_ATTR_WITH_HINT 331 +#define _LOAD_ATTR_SLOT 332 +#define _CHECK_ATTR_CLASS 333 +#define _LOAD_ATTR_CLASS 334 +#define _LOAD_ATTR_PROPERTY LOAD_ATTR_PROPERTY +#define _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN +#define _GUARD_DORV_VALUES 335 +#define _STORE_ATTR_INSTANCE_VALUE 336 +#define _STORE_ATTR_WITH_HINT STORE_ATTR_WITH_HINT +#define _STORE_ATTR_SLOT 337 +#define _COMPARE_OP 338 +#define _COMPARE_OP_FLOAT COMPARE_OP_FLOAT +#define _COMPARE_OP_INT COMPARE_OP_INT +#define _COMPARE_OP_STR COMPARE_OP_STR +#define _IS_OP IS_OP +#define _CONTAINS_OP CONTAINS_OP +#define _CHECK_EG_MATCH CHECK_EG_MATCH +#define _CHECK_EXC_MATCH CHECK_EXC_MATCH +#define _JUMP_BACKWARD JUMP_BACKWARD +#define _POP_JUMP_IF_FALSE 339 +#define _POP_JUMP_IF_TRUE 340 +#define _IS_NONE 341 +#define _GET_LEN GET_LEN +#define _MATCH_CLASS MATCH_CLASS +#define _MATCH_MAPPING MATCH_MAPPING +#define _MATCH_SEQUENCE MATCH_SEQUENCE +#define _MATCH_KEYS MATCH_KEYS +#define _GET_ITER GET_ITER +#define _GET_YIELD_FROM_ITER GET_YIELD_FROM_ITER +#define _FOR_ITER 342 +#define _FOR_ITER_TIER_TWO 343 +#define _INSTRUMENTED_FOR_ITER INSTRUMENTED_FOR_ITER +#define _ITER_CHECK_LIST 344 +#define _ITER_JUMP_LIST 345 +#define _GUARD_NOT_EXHAUSTED_LIST 346 +#define _ITER_NEXT_LIST 347 +#define _ITER_CHECK_TUPLE 348 +#define _ITER_JUMP_TUPLE 349 +#define _GUARD_NOT_EXHAUSTED_TUPLE 350 +#define _ITER_NEXT_TUPLE 351 +#define _ITER_CHECK_RANGE 352 +#define _ITER_JUMP_RANGE 353 +#define _GUARD_NOT_EXHAUSTED_RANGE 354 +#define _ITER_NEXT_RANGE 355 +#define _FOR_ITER_GEN FOR_ITER_GEN +#define _BEFORE_ASYNC_WITH BEFORE_ASYNC_WITH +#define _BEFORE_WITH BEFORE_WITH +#define _WITH_EXCEPT_START WITH_EXCEPT_START +#define _PUSH_EXC_INFO PUSH_EXC_INFO +#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT 356 +#define _GUARD_KEYS_VERSION 357 +#define _LOAD_ATTR_METHOD_WITH_VALUES 358 +#define _LOAD_ATTR_METHOD_NO_DICT 359 +#define _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES 360 +#define _LOAD_ATTR_NONDESCRIPTOR_NO_DICT 361 +#define _CHECK_ATTR_METHOD_LAZY_DICT 362 +#define _LOAD_ATTR_METHOD_LAZY_DICT 363 +#define _INSTRUMENTED_CALL INSTRUMENTED_CALL +#define _CALL 364 +#define _CHECK_CALL_BOUND_METHOD_EXACT_ARGS 365 +#define _INIT_CALL_BOUND_METHOD_EXACT_ARGS 366 +#define _CHECK_PEP_523 367 +#define _CHECK_FUNCTION_EXACT_ARGS 368 +#define _CHECK_STACK_SPACE 369 +#define _INIT_CALL_PY_EXACT_ARGS 370 +#define _PUSH_FRAME 371 +#define _CALL_PY_WITH_DEFAULTS CALL_PY_WITH_DEFAULTS +#define _CALL_TYPE_1 CALL_TYPE_1 +#define _CALL_STR_1 CALL_STR_1 +#define _CALL_TUPLE_1 CALL_TUPLE_1 +#define _CALL_ALLOC_AND_ENTER_INIT CALL_ALLOC_AND_ENTER_INIT +#define _EXIT_INIT_CHECK EXIT_INIT_CHECK +#define _CALL_BUILTIN_CLASS CALL_BUILTIN_CLASS +#define _CALL_BUILTIN_O CALL_BUILTIN_O +#define _CALL_BUILTIN_FAST CALL_BUILTIN_FAST +#define _CALL_BUILTIN_FAST_WITH_KEYWORDS CALL_BUILTIN_FAST_WITH_KEYWORDS +#define _CALL_LEN CALL_LEN +#define _CALL_ISINSTANCE CALL_ISINSTANCE +#define _CALL_METHOD_DESCRIPTOR_O CALL_METHOD_DESCRIPTOR_O +#define _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS +#define _CALL_METHOD_DESCRIPTOR_NOARGS CALL_METHOD_DESCRIPTOR_NOARGS +#define _CALL_METHOD_DESCRIPTOR_FAST CALL_METHOD_DESCRIPTOR_FAST +#define _INSTRUMENTED_CALL_KW INSTRUMENTED_CALL_KW +#define _CALL_KW CALL_KW +#define _INSTRUMENTED_CALL_FUNCTION_EX INSTRUMENTED_CALL_FUNCTION_EX +#define _CALL_FUNCTION_EX CALL_FUNCTION_EX +#define _MAKE_FUNCTION MAKE_FUNCTION +#define _SET_FUNCTION_ATTRIBUTE SET_FUNCTION_ATTRIBUTE +#define _BUILD_SLICE BUILD_SLICE +#define _CONVERT_VALUE CONVERT_VALUE +#define _FORMAT_SIMPLE FORMAT_SIMPLE +#define _FORMAT_WITH_SPEC FORMAT_WITH_SPEC +#define _COPY COPY +#define _BINARY_OP 372 +#define _SWAP SWAP +#define _INSTRUMENTED_INSTRUCTION INSTRUMENTED_INSTRUCTION +#define _INSTRUMENTED_JUMP_FORWARD INSTRUMENTED_JUMP_FORWARD +#define _INSTRUMENTED_JUMP_BACKWARD INSTRUMENTED_JUMP_BACKWARD +#define _INSTRUMENTED_POP_JUMP_IF_TRUE INSTRUMENTED_POP_JUMP_IF_TRUE +#define _INSTRUMENTED_POP_JUMP_IF_FALSE INSTRUMENTED_POP_JUMP_IF_FALSE +#define _INSTRUMENTED_POP_JUMP_IF_NONE INSTRUMENTED_POP_JUMP_IF_NONE +#define _INSTRUMENTED_POP_JUMP_IF_NOT_NONE INSTRUMENTED_POP_JUMP_IF_NOT_NONE +#define _GUARD_IS_TRUE_POP 373 +#define _GUARD_IS_FALSE_POP 374 +#define _GUARD_IS_NONE_POP 375 +#define _GUARD_IS_NOT_NONE_POP 376 +#define _JUMP_TO_TOP 377 +#define _SAVE_RETURN_OFFSET 378 +#define _INSERT 379 +#define _CHECK_VALIDITY 380 +#define _LOAD_CONST_INLINE_BORROW 381 +#define _INTERNAL_INCREMENT_OPT_COUNTER 382 +#define MAX_UOP_ID 382 + +#ifdef __cplusplus +} +#endif +#endif /* !Py_CORE_UOP_IDS_H */ diff --git a/Include/internal/pycore_uop_metadata.h b/Include/internal/pycore_uop_metadata.h new file mode 100644 index 00000000000000..ab498e9cefde22 --- /dev/null +++ b/Include/internal/pycore_uop_metadata.h @@ -0,0 +1,407 @@ +// This file is generated by Tools/cases_generator/uop_metadata_generator.py +// from: +// Python/bytecodes.c +// Do not edit! + +#ifndef Py_CORE_UOP_METADATA_H +#define Py_CORE_UOP_METADATA_H +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include "pycore_uop_ids.h" +extern const uint16_t _PyUop_Flags[MAX_UOP_ID+1]; +extern const char * const _PyOpcode_uop_name[MAX_UOP_ID+1]; + +#ifdef NEED_OPCODE_METADATA +const uint16_t _PyUop_Flags[MAX_UOP_ID+1] = { + [_NOP] = 0, + [_RESUME_CHECK] = HAS_DEOPT_FLAG, + [_LOAD_FAST_CHECK] = HAS_ARG_FLAG | HAS_LOCAL_FLAG | HAS_ERROR_FLAG, + [_LOAD_FAST] = HAS_ARG_FLAG | HAS_LOCAL_FLAG, + [_LOAD_FAST_AND_CLEAR] = HAS_ARG_FLAG | HAS_LOCAL_FLAG, + [_LOAD_FAST_LOAD_FAST] = HAS_ARG_FLAG | HAS_LOCAL_FLAG, + [_LOAD_CONST] = HAS_ARG_FLAG | HAS_CONST_FLAG, + [_STORE_FAST] = HAS_ARG_FLAG | HAS_LOCAL_FLAG, + [_STORE_FAST_LOAD_FAST] = HAS_ARG_FLAG | HAS_LOCAL_FLAG, + [_STORE_FAST_STORE_FAST] = HAS_ARG_FLAG | HAS_LOCAL_FLAG, + [_POP_TOP] = 0, + [_PUSH_NULL] = 0, + [_END_SEND] = 0, + [_UNARY_NEGATIVE] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_UNARY_NOT] = 0, + [_TO_BOOL] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_TO_BOOL_BOOL] = HAS_DEOPT_FLAG, + [_TO_BOOL_INT] = HAS_DEOPT_FLAG, + [_TO_BOOL_LIST] = HAS_DEOPT_FLAG, + [_TO_BOOL_NONE] = HAS_DEOPT_FLAG, + [_TO_BOOL_STR] = HAS_DEOPT_FLAG, + [_TO_BOOL_ALWAYS_TRUE] = HAS_DEOPT_FLAG, + [_UNARY_INVERT] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_GUARD_BOTH_INT] = HAS_DEOPT_FLAG, + [_BINARY_OP_MULTIPLY_INT] = HAS_ERROR_FLAG, + [_BINARY_OP_ADD_INT] = HAS_ERROR_FLAG, + [_BINARY_OP_SUBTRACT_INT] = HAS_ERROR_FLAG, + [_GUARD_BOTH_FLOAT] = HAS_DEOPT_FLAG, + [_BINARY_OP_MULTIPLY_FLOAT] = 0, + [_BINARY_OP_ADD_FLOAT] = 0, + [_BINARY_OP_SUBTRACT_FLOAT] = 0, + [_GUARD_BOTH_UNICODE] = HAS_DEOPT_FLAG, + [_BINARY_OP_ADD_UNICODE] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_BINARY_SUBSCR] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_BINARY_SLICE] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_STORE_SLICE] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_BINARY_SUBSCR_LIST_INT] = HAS_DEOPT_FLAG, + [_BINARY_SUBSCR_STR_INT] = HAS_DEOPT_FLAG, + [_BINARY_SUBSCR_TUPLE_INT] = HAS_DEOPT_FLAG, + [_BINARY_SUBSCR_DICT] = HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_LIST_APPEND] = HAS_ARG_FLAG | HAS_ERROR_FLAG, + [_SET_ADD] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_STORE_SUBSCR] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_STORE_SUBSCR_LIST_INT] = HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG, + [_STORE_SUBSCR_DICT] = HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_DELETE_SUBSCR] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_CALL_INTRINSIC_1] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_CALL_INTRINSIC_2] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_POP_FRAME] = HAS_ESCAPES_FLAG, + [_GET_AITER] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_GET_ANEXT] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_GET_AWAITABLE] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_POP_EXCEPT] = HAS_ESCAPES_FLAG, + [_LOAD_ASSERTION_ERROR] = 0, + [_LOAD_BUILD_CLASS] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_STORE_NAME] = HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_DELETE_NAME] = HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_UNPACK_SEQUENCE] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_UNPACK_SEQUENCE_TWO_TUPLE] = HAS_ARG_FLAG | HAS_DEOPT_FLAG, + [_UNPACK_SEQUENCE_TUPLE] = HAS_ARG_FLAG | HAS_DEOPT_FLAG, + [_UNPACK_SEQUENCE_LIST] = HAS_ARG_FLAG | HAS_DEOPT_FLAG, + [_UNPACK_EX] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_STORE_ATTR] = HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_DELETE_ATTR] = HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_STORE_GLOBAL] = HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_DELETE_GLOBAL] = HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_LOAD_LOCALS] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_LOAD_FROM_DICT_OR_GLOBALS] = HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_LOAD_NAME] = HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_LOAD_GLOBAL] = HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_GUARD_GLOBALS_VERSION] = HAS_DEOPT_FLAG, + [_GUARD_BUILTINS_VERSION] = HAS_DEOPT_FLAG, + [_LOAD_GLOBAL_MODULE] = HAS_ARG_FLAG | HAS_DEOPT_FLAG, + [_LOAD_GLOBAL_BUILTINS] = HAS_ARG_FLAG | HAS_DEOPT_FLAG, + [_DELETE_FAST] = HAS_ARG_FLAG | HAS_LOCAL_FLAG | HAS_ERROR_FLAG, + [_MAKE_CELL] = HAS_ARG_FLAG | HAS_FREE_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_DELETE_DEREF] = HAS_ARG_FLAG | HAS_FREE_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_LOAD_FROM_DICT_OR_DEREF] = HAS_ARG_FLAG | HAS_FREE_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_LOAD_DEREF] = HAS_ARG_FLAG | HAS_FREE_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_STORE_DEREF] = HAS_ARG_FLAG | HAS_FREE_FLAG | HAS_ESCAPES_FLAG, + [_COPY_FREE_VARS] = HAS_ARG_FLAG, + [_BUILD_STRING] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_BUILD_TUPLE] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_BUILD_LIST] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_LIST_EXTEND] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_SET_UPDATE] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_BUILD_SET] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_BUILD_MAP] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_SETUP_ANNOTATIONS] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_BUILD_CONST_KEY_MAP] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_DICT_UPDATE] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_DICT_MERGE] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_MAP_ADD] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_LOAD_SUPER_ATTR_ATTR] = HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_LOAD_SUPER_ATTR_METHOD] = HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_LOAD_ATTR] = HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_GUARD_TYPE_VERSION] = HAS_DEOPT_FLAG, + [_CHECK_MANAGED_OBJECT_HAS_VALUES] = HAS_DEOPT_FLAG, + [_LOAD_ATTR_INSTANCE_VALUE] = HAS_ARG_FLAG | HAS_DEOPT_FLAG, + [_CHECK_ATTR_MODULE] = HAS_DEOPT_FLAG, + [_LOAD_ATTR_MODULE] = HAS_ARG_FLAG | HAS_DEOPT_FLAG, + [_CHECK_ATTR_WITH_HINT] = HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG, + [_LOAD_ATTR_WITH_HINT] = HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG, + [_LOAD_ATTR_SLOT] = HAS_ARG_FLAG | HAS_DEOPT_FLAG, + [_CHECK_ATTR_CLASS] = HAS_DEOPT_FLAG, + [_LOAD_ATTR_CLASS] = HAS_ARG_FLAG, + [_GUARD_DORV_VALUES] = HAS_DEOPT_FLAG, + [_STORE_ATTR_INSTANCE_VALUE] = HAS_ESCAPES_FLAG, + [_STORE_ATTR_SLOT] = HAS_ESCAPES_FLAG, + [_COMPARE_OP] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_COMPARE_OP_FLOAT] = HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG, + [_COMPARE_OP_INT] = HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG, + [_COMPARE_OP_STR] = HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG, + [_IS_OP] = HAS_ARG_FLAG, + [_CONTAINS_OP] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_CHECK_EG_MATCH] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_CHECK_EXC_MATCH] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_IS_NONE] = 0, + [_GET_LEN] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_MATCH_CLASS] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_MATCH_MAPPING] = 0, + [_MATCH_SEQUENCE] = 0, + [_MATCH_KEYS] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_GET_ITER] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_GET_YIELD_FROM_ITER] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_FOR_ITER_TIER_TWO] = HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_ITER_CHECK_LIST] = HAS_DEOPT_FLAG, + [_GUARD_NOT_EXHAUSTED_LIST] = HAS_DEOPT_FLAG, + [_ITER_NEXT_LIST] = 0, + [_ITER_CHECK_TUPLE] = HAS_DEOPT_FLAG, + [_GUARD_NOT_EXHAUSTED_TUPLE] = HAS_DEOPT_FLAG, + [_ITER_NEXT_TUPLE] = 0, + [_ITER_CHECK_RANGE] = HAS_DEOPT_FLAG, + [_GUARD_NOT_EXHAUSTED_RANGE] = HAS_DEOPT_FLAG, + [_ITER_NEXT_RANGE] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_BEFORE_ASYNC_WITH] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_BEFORE_WITH] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_WITH_EXCEPT_START] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_PUSH_EXC_INFO] = 0, + [_GUARD_DORV_VALUES_INST_ATTR_FROM_DICT] = HAS_DEOPT_FLAG, + [_GUARD_KEYS_VERSION] = HAS_DEOPT_FLAG, + [_LOAD_ATTR_METHOD_WITH_VALUES] = HAS_ARG_FLAG | HAS_ESCAPES_FLAG, + [_LOAD_ATTR_METHOD_NO_DICT] = HAS_ARG_FLAG | HAS_ESCAPES_FLAG, + [_LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES] = HAS_ARG_FLAG, + [_LOAD_ATTR_NONDESCRIPTOR_NO_DICT] = HAS_ARG_FLAG, + [_CHECK_ATTR_METHOD_LAZY_DICT] = HAS_DEOPT_FLAG, + [_LOAD_ATTR_METHOD_LAZY_DICT] = HAS_ARG_FLAG | HAS_ESCAPES_FLAG, + [_CHECK_CALL_BOUND_METHOD_EXACT_ARGS] = HAS_ARG_FLAG | HAS_DEOPT_FLAG, + [_INIT_CALL_BOUND_METHOD_EXACT_ARGS] = HAS_ARG_FLAG, + [_CHECK_PEP_523] = HAS_DEOPT_FLAG, + [_CHECK_FUNCTION_EXACT_ARGS] = HAS_ARG_FLAG | HAS_DEOPT_FLAG, + [_CHECK_STACK_SPACE] = HAS_ARG_FLAG | HAS_DEOPT_FLAG, + [_INIT_CALL_PY_EXACT_ARGS] = HAS_ARG_FLAG | HAS_ESCAPES_FLAG, + [_PUSH_FRAME] = 0, + [_CALL_TYPE_1] = HAS_ARG_FLAG | HAS_DEOPT_FLAG, + [_CALL_STR_1] = HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_CALL_TUPLE_1] = HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_EXIT_INIT_CHECK] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_CALL_BUILTIN_CLASS] = HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG, + [_CALL_BUILTIN_O] = HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_CALL_BUILTIN_FAST] = HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_CALL_BUILTIN_FAST_WITH_KEYWORDS] = HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_CALL_LEN] = HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_CALL_ISINSTANCE] = HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_CALL_METHOD_DESCRIPTOR_O] = HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS] = HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_CALL_METHOD_DESCRIPTOR_NOARGS] = HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_CALL_METHOD_DESCRIPTOR_FAST] = HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_MAKE_FUNCTION] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_SET_FUNCTION_ATTRIBUTE] = HAS_ARG_FLAG | HAS_ESCAPES_FLAG, + [_BUILD_SLICE] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_CONVERT_VALUE] = HAS_ARG_FLAG | HAS_ERROR_FLAG, + [_FORMAT_SIMPLE] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_FORMAT_WITH_SPEC] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_COPY] = HAS_ARG_FLAG, + [_BINARY_OP] = HAS_ARG_FLAG | HAS_ERROR_FLAG, + [_SWAP] = HAS_ARG_FLAG, + [_GUARD_IS_TRUE_POP] = HAS_DEOPT_FLAG, + [_GUARD_IS_FALSE_POP] = HAS_DEOPT_FLAG, + [_GUARD_IS_NONE_POP] = HAS_DEOPT_FLAG, + [_GUARD_IS_NOT_NONE_POP] = HAS_DEOPT_FLAG, + [_JUMP_TO_TOP] = HAS_EVAL_BREAK_FLAG, + [_SET_IP] = HAS_ARG_FLAG | HAS_ESCAPES_FLAG, + [_SAVE_RETURN_OFFSET] = HAS_ARG_FLAG, + [_EXIT_TRACE] = HAS_DEOPT_FLAG, + [_INSERT] = HAS_ARG_FLAG, + [_CHECK_VALIDITY] = HAS_DEOPT_FLAG, + [_LOAD_CONST_INLINE_BORROW] = 0, + [_INTERNAL_INCREMENT_OPT_COUNTER] = 0, +}; + +const char *const _PyOpcode_uop_name[MAX_UOP_ID+1] = { + [_BEFORE_ASYNC_WITH] = "_BEFORE_ASYNC_WITH", + [_BEFORE_WITH] = "_BEFORE_WITH", + [_BINARY_OP] = "_BINARY_OP", + [_BINARY_OP_ADD_FLOAT] = "_BINARY_OP_ADD_FLOAT", + [_BINARY_OP_ADD_INT] = "_BINARY_OP_ADD_INT", + [_BINARY_OP_ADD_UNICODE] = "_BINARY_OP_ADD_UNICODE", + [_BINARY_OP_MULTIPLY_FLOAT] = "_BINARY_OP_MULTIPLY_FLOAT", + [_BINARY_OP_MULTIPLY_INT] = "_BINARY_OP_MULTIPLY_INT", + [_BINARY_OP_SUBTRACT_FLOAT] = "_BINARY_OP_SUBTRACT_FLOAT", + [_BINARY_OP_SUBTRACT_INT] = "_BINARY_OP_SUBTRACT_INT", + [_BINARY_SLICE] = "_BINARY_SLICE", + [_BINARY_SUBSCR] = "_BINARY_SUBSCR", + [_BINARY_SUBSCR_DICT] = "_BINARY_SUBSCR_DICT", + [_BINARY_SUBSCR_LIST_INT] = "_BINARY_SUBSCR_LIST_INT", + [_BINARY_SUBSCR_STR_INT] = "_BINARY_SUBSCR_STR_INT", + [_BINARY_SUBSCR_TUPLE_INT] = "_BINARY_SUBSCR_TUPLE_INT", + [_BUILD_CONST_KEY_MAP] = "_BUILD_CONST_KEY_MAP", + [_BUILD_LIST] = "_BUILD_LIST", + [_BUILD_MAP] = "_BUILD_MAP", + [_BUILD_SET] = "_BUILD_SET", + [_BUILD_SLICE] = "_BUILD_SLICE", + [_BUILD_STRING] = "_BUILD_STRING", + [_BUILD_TUPLE] = "_BUILD_TUPLE", + [_CALL_BUILTIN_CLASS] = "_CALL_BUILTIN_CLASS", + [_CALL_BUILTIN_FAST] = "_CALL_BUILTIN_FAST", + [_CALL_BUILTIN_FAST_WITH_KEYWORDS] = "_CALL_BUILTIN_FAST_WITH_KEYWORDS", + [_CALL_BUILTIN_O] = "_CALL_BUILTIN_O", + [_CALL_INTRINSIC_1] = "_CALL_INTRINSIC_1", + [_CALL_INTRINSIC_2] = "_CALL_INTRINSIC_2", + [_CALL_ISINSTANCE] = "_CALL_ISINSTANCE", + [_CALL_LEN] = "_CALL_LEN", + [_CALL_METHOD_DESCRIPTOR_FAST] = "_CALL_METHOD_DESCRIPTOR_FAST", + [_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS] = "_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS", + [_CALL_METHOD_DESCRIPTOR_NOARGS] = "_CALL_METHOD_DESCRIPTOR_NOARGS", + [_CALL_METHOD_DESCRIPTOR_O] = "_CALL_METHOD_DESCRIPTOR_O", + [_CALL_STR_1] = "_CALL_STR_1", + [_CALL_TUPLE_1] = "_CALL_TUPLE_1", + [_CALL_TYPE_1] = "_CALL_TYPE_1", + [_CHECK_ATTR_CLASS] = "_CHECK_ATTR_CLASS", + [_CHECK_ATTR_METHOD_LAZY_DICT] = "_CHECK_ATTR_METHOD_LAZY_DICT", + [_CHECK_ATTR_MODULE] = "_CHECK_ATTR_MODULE", + [_CHECK_ATTR_WITH_HINT] = "_CHECK_ATTR_WITH_HINT", + [_CHECK_CALL_BOUND_METHOD_EXACT_ARGS] = "_CHECK_CALL_BOUND_METHOD_EXACT_ARGS", + [_CHECK_EG_MATCH] = "_CHECK_EG_MATCH", + [_CHECK_EXC_MATCH] = "_CHECK_EXC_MATCH", + [_CHECK_FUNCTION_EXACT_ARGS] = "_CHECK_FUNCTION_EXACT_ARGS", + [_CHECK_MANAGED_OBJECT_HAS_VALUES] = "_CHECK_MANAGED_OBJECT_HAS_VALUES", + [_CHECK_PEP_523] = "_CHECK_PEP_523", + [_CHECK_STACK_SPACE] = "_CHECK_STACK_SPACE", + [_CHECK_VALIDITY] = "_CHECK_VALIDITY", + [_COMPARE_OP] = "_COMPARE_OP", + [_COMPARE_OP_FLOAT] = "_COMPARE_OP_FLOAT", + [_COMPARE_OP_INT] = "_COMPARE_OP_INT", + [_COMPARE_OP_STR] = "_COMPARE_OP_STR", + [_CONTAINS_OP] = "_CONTAINS_OP", + [_CONVERT_VALUE] = "_CONVERT_VALUE", + [_COPY] = "_COPY", + [_COPY_FREE_VARS] = "_COPY_FREE_VARS", + [_DELETE_ATTR] = "_DELETE_ATTR", + [_DELETE_DEREF] = "_DELETE_DEREF", + [_DELETE_FAST] = "_DELETE_FAST", + [_DELETE_GLOBAL] = "_DELETE_GLOBAL", + [_DELETE_NAME] = "_DELETE_NAME", + [_DELETE_SUBSCR] = "_DELETE_SUBSCR", + [_DICT_MERGE] = "_DICT_MERGE", + [_DICT_UPDATE] = "_DICT_UPDATE", + [_END_SEND] = "_END_SEND", + [_EXIT_INIT_CHECK] = "_EXIT_INIT_CHECK", + [_EXIT_TRACE] = "_EXIT_TRACE", + [_FORMAT_SIMPLE] = "_FORMAT_SIMPLE", + [_FORMAT_WITH_SPEC] = "_FORMAT_WITH_SPEC", + [_FOR_ITER_TIER_TWO] = "_FOR_ITER_TIER_TWO", + [_GET_AITER] = "_GET_AITER", + [_GET_ANEXT] = "_GET_ANEXT", + [_GET_AWAITABLE] = "_GET_AWAITABLE", + [_GET_ITER] = "_GET_ITER", + [_GET_LEN] = "_GET_LEN", + [_GET_YIELD_FROM_ITER] = "_GET_YIELD_FROM_ITER", + [_GUARD_BOTH_FLOAT] = "_GUARD_BOTH_FLOAT", + [_GUARD_BOTH_INT] = "_GUARD_BOTH_INT", + [_GUARD_BOTH_UNICODE] = "_GUARD_BOTH_UNICODE", + [_GUARD_BUILTINS_VERSION] = "_GUARD_BUILTINS_VERSION", + [_GUARD_DORV_VALUES] = "_GUARD_DORV_VALUES", + [_GUARD_DORV_VALUES_INST_ATTR_FROM_DICT] = "_GUARD_DORV_VALUES_INST_ATTR_FROM_DICT", + [_GUARD_GLOBALS_VERSION] = "_GUARD_GLOBALS_VERSION", + [_GUARD_IS_FALSE_POP] = "_GUARD_IS_FALSE_POP", + [_GUARD_IS_NONE_POP] = "_GUARD_IS_NONE_POP", + [_GUARD_IS_NOT_NONE_POP] = "_GUARD_IS_NOT_NONE_POP", + [_GUARD_IS_TRUE_POP] = "_GUARD_IS_TRUE_POP", + [_GUARD_KEYS_VERSION] = "_GUARD_KEYS_VERSION", + [_GUARD_NOT_EXHAUSTED_LIST] = "_GUARD_NOT_EXHAUSTED_LIST", + [_GUARD_NOT_EXHAUSTED_RANGE] = "_GUARD_NOT_EXHAUSTED_RANGE", + [_GUARD_NOT_EXHAUSTED_TUPLE] = "_GUARD_NOT_EXHAUSTED_TUPLE", + [_GUARD_TYPE_VERSION] = "_GUARD_TYPE_VERSION", + [_INIT_CALL_BOUND_METHOD_EXACT_ARGS] = "_INIT_CALL_BOUND_METHOD_EXACT_ARGS", + [_INIT_CALL_PY_EXACT_ARGS] = "_INIT_CALL_PY_EXACT_ARGS", + [_INSERT] = "_INSERT", + [_INTERNAL_INCREMENT_OPT_COUNTER] = "_INTERNAL_INCREMENT_OPT_COUNTER", + [_IS_NONE] = "_IS_NONE", + [_IS_OP] = "_IS_OP", + [_ITER_CHECK_LIST] = "_ITER_CHECK_LIST", + [_ITER_CHECK_RANGE] = "_ITER_CHECK_RANGE", + [_ITER_CHECK_TUPLE] = "_ITER_CHECK_TUPLE", + [_ITER_NEXT_LIST] = "_ITER_NEXT_LIST", + [_ITER_NEXT_RANGE] = "_ITER_NEXT_RANGE", + [_ITER_NEXT_TUPLE] = "_ITER_NEXT_TUPLE", + [_JUMP_TO_TOP] = "_JUMP_TO_TOP", + [_LIST_APPEND] = "_LIST_APPEND", + [_LIST_EXTEND] = "_LIST_EXTEND", + [_LOAD_ASSERTION_ERROR] = "_LOAD_ASSERTION_ERROR", + [_LOAD_ATTR] = "_LOAD_ATTR", + [_LOAD_ATTR_CLASS] = "_LOAD_ATTR_CLASS", + [_LOAD_ATTR_INSTANCE_VALUE] = "_LOAD_ATTR_INSTANCE_VALUE", + [_LOAD_ATTR_METHOD_LAZY_DICT] = "_LOAD_ATTR_METHOD_LAZY_DICT", + [_LOAD_ATTR_METHOD_NO_DICT] = "_LOAD_ATTR_METHOD_NO_DICT", + [_LOAD_ATTR_METHOD_WITH_VALUES] = "_LOAD_ATTR_METHOD_WITH_VALUES", + [_LOAD_ATTR_MODULE] = "_LOAD_ATTR_MODULE", + [_LOAD_ATTR_NONDESCRIPTOR_NO_DICT] = "_LOAD_ATTR_NONDESCRIPTOR_NO_DICT", + [_LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES] = "_LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES", + [_LOAD_ATTR_SLOT] = "_LOAD_ATTR_SLOT", + [_LOAD_ATTR_WITH_HINT] = "_LOAD_ATTR_WITH_HINT", + [_LOAD_BUILD_CLASS] = "_LOAD_BUILD_CLASS", + [_LOAD_CONST] = "_LOAD_CONST", + [_LOAD_CONST_INLINE_BORROW] = "_LOAD_CONST_INLINE_BORROW", + [_LOAD_DEREF] = "_LOAD_DEREF", + [_LOAD_FAST] = "_LOAD_FAST", + [_LOAD_FAST_AND_CLEAR] = "_LOAD_FAST_AND_CLEAR", + [_LOAD_FAST_CHECK] = "_LOAD_FAST_CHECK", + [_LOAD_FAST_LOAD_FAST] = "_LOAD_FAST_LOAD_FAST", + [_LOAD_FROM_DICT_OR_DEREF] = "_LOAD_FROM_DICT_OR_DEREF", + [_LOAD_FROM_DICT_OR_GLOBALS] = "_LOAD_FROM_DICT_OR_GLOBALS", + [_LOAD_GLOBAL] = "_LOAD_GLOBAL", + [_LOAD_GLOBAL_BUILTINS] = "_LOAD_GLOBAL_BUILTINS", + [_LOAD_GLOBAL_MODULE] = "_LOAD_GLOBAL_MODULE", + [_LOAD_LOCALS] = "_LOAD_LOCALS", + [_LOAD_NAME] = "_LOAD_NAME", + [_LOAD_SUPER_ATTR_ATTR] = "_LOAD_SUPER_ATTR_ATTR", + [_LOAD_SUPER_ATTR_METHOD] = "_LOAD_SUPER_ATTR_METHOD", + [_MAKE_CELL] = "_MAKE_CELL", + [_MAKE_FUNCTION] = "_MAKE_FUNCTION", + [_MAP_ADD] = "_MAP_ADD", + [_MATCH_CLASS] = "_MATCH_CLASS", + [_MATCH_KEYS] = "_MATCH_KEYS", + [_MATCH_MAPPING] = "_MATCH_MAPPING", + [_MATCH_SEQUENCE] = "_MATCH_SEQUENCE", + [_NOP] = "_NOP", + [_POP_EXCEPT] = "_POP_EXCEPT", + [_POP_FRAME] = "_POP_FRAME", + [_POP_TOP] = "_POP_TOP", + [_PUSH_EXC_INFO] = "_PUSH_EXC_INFO", + [_PUSH_FRAME] = "_PUSH_FRAME", + [_PUSH_NULL] = "_PUSH_NULL", + [_RESUME_CHECK] = "_RESUME_CHECK", + [_SAVE_RETURN_OFFSET] = "_SAVE_RETURN_OFFSET", + [_SETUP_ANNOTATIONS] = "_SETUP_ANNOTATIONS", + [_SET_ADD] = "_SET_ADD", + [_SET_FUNCTION_ATTRIBUTE] = "_SET_FUNCTION_ATTRIBUTE", + [_SET_IP] = "_SET_IP", + [_SET_UPDATE] = "_SET_UPDATE", + [_STORE_ATTR] = "_STORE_ATTR", + [_STORE_ATTR_INSTANCE_VALUE] = "_STORE_ATTR_INSTANCE_VALUE", + [_STORE_ATTR_SLOT] = "_STORE_ATTR_SLOT", + [_STORE_DEREF] = "_STORE_DEREF", + [_STORE_FAST] = "_STORE_FAST", + [_STORE_FAST_LOAD_FAST] = "_STORE_FAST_LOAD_FAST", + [_STORE_FAST_STORE_FAST] = "_STORE_FAST_STORE_FAST", + [_STORE_GLOBAL] = "_STORE_GLOBAL", + [_STORE_NAME] = "_STORE_NAME", + [_STORE_SLICE] = "_STORE_SLICE", + [_STORE_SUBSCR] = "_STORE_SUBSCR", + [_STORE_SUBSCR_DICT] = "_STORE_SUBSCR_DICT", + [_STORE_SUBSCR_LIST_INT] = "_STORE_SUBSCR_LIST_INT", + [_SWAP] = "_SWAP", + [_TO_BOOL] = "_TO_BOOL", + [_TO_BOOL_ALWAYS_TRUE] = "_TO_BOOL_ALWAYS_TRUE", + [_TO_BOOL_BOOL] = "_TO_BOOL_BOOL", + [_TO_BOOL_INT] = "_TO_BOOL_INT", + [_TO_BOOL_LIST] = "_TO_BOOL_LIST", + [_TO_BOOL_NONE] = "_TO_BOOL_NONE", + [_TO_BOOL_STR] = "_TO_BOOL_STR", + [_UNARY_INVERT] = "_UNARY_INVERT", + [_UNARY_NEGATIVE] = "_UNARY_NEGATIVE", + [_UNARY_NOT] = "_UNARY_NOT", + [_UNPACK_EX] = "_UNPACK_EX", + [_UNPACK_SEQUENCE] = "_UNPACK_SEQUENCE", + [_UNPACK_SEQUENCE_LIST] = "_UNPACK_SEQUENCE_LIST", + [_UNPACK_SEQUENCE_TUPLE] = "_UNPACK_SEQUENCE_TUPLE", + [_UNPACK_SEQUENCE_TWO_TUPLE] = "_UNPACK_SEQUENCE_TWO_TUPLE", + [_WITH_EXCEPT_START] = "_WITH_EXCEPT_START", +}; +#endif // NEED_OPCODE_METADATA + + +#ifdef __cplusplus +} +#endif +#endif /* !Py_CORE_UOP_METADATA_H */ diff --git a/Include/internal/pycore_uops.h b/Include/internal/pycore_uops.h index 57a5970353b360..eb10002d34ce51 100644 --- a/Include/internal/pycore_uops.h +++ b/Include/internal/pycore_uops.h @@ -8,11 +8,14 @@ extern "C" { # error "this header requires Py_BUILD_CORE define" #endif -#define _Py_UOP_MAX_TRACE_LENGTH 32 +#include "pycore_frame.h" // _PyInterpreterFrame + +#define _Py_UOP_MAX_TRACE_LENGTH 512 typedef struct { - uint32_t opcode; - uint32_t oparg; + uint16_t opcode; + uint16_t oparg; + uint32_t target; uint64_t operand; // A cache entry } _PyUOpInstruction; @@ -21,11 +24,6 @@ typedef struct { _PyUOpInstruction trace[1]; } _PyUOpExecutorObject; -_PyInterpreterFrame *_PyUopExecute( - _PyExecutorObject *executor, - _PyInterpreterFrame *frame, - PyObject **stack_pointer); - #ifdef __cplusplus } #endif diff --git a/Include/internal/pycore_weakref.h b/Include/internal/pycore_weakref.h index 51b2bb6b11ede9..dea267b49039e7 100644 --- a/Include/internal/pycore_weakref.h +++ b/Include/internal/pycore_weakref.h @@ -8,42 +8,67 @@ extern "C" { # error "this header requires Py_BUILD_CORE define" #endif -static inline PyObject* _PyWeakref_GET_REF(PyObject *ref_obj) { - assert(PyWeakref_Check(ref_obj)); - PyWeakReference *ref = _Py_CAST(PyWeakReference*, ref_obj); - PyObject *obj = ref->wr_object; - - if (obj == Py_None) { - // clear_weakref() was called - return NULL; - } +#include "pycore_critical_section.h" // Py_BEGIN_CRITICAL_SECTION() +#include "pycore_object.h" // _Py_REF_IS_MERGED() +static inline int _is_dead(PyObject *obj) +{ // Explanation for the Py_REFCNT() check: when a weakref's target is part // of a long chain of deallocations which triggers the trashcan mechanism, // clearing the weakrefs can be delayed long after the target's refcount // has dropped to zero. In the meantime, code accessing the weakref will // be able to "see" the target object even though it is supposed to be // unreachable. See issue gh-60806. - Py_ssize_t refcnt = Py_REFCNT(obj); - if (refcnt == 0) { - return NULL; +#if defined(Py_GIL_DISABLED) + Py_ssize_t shared = _Py_atomic_load_ssize_relaxed(&obj->ob_ref_shared); + return shared == _Py_REF_SHARED(0, _Py_REF_MERGED); +#else + return (Py_REFCNT(obj) == 0); +#endif +} + +static inline PyObject* _PyWeakref_GET_REF(PyObject *ref_obj) +{ + assert(PyWeakref_Check(ref_obj)); + PyObject *ret = NULL; + Py_BEGIN_CRITICAL_SECTION(ref_obj); + PyWeakReference *ref = _Py_CAST(PyWeakReference*, ref_obj); + PyObject *obj = ref->wr_object; + + if (obj == Py_None) { + // clear_weakref() was called + goto end; } - assert(refcnt > 0); - return Py_NewRef(obj); + if (_is_dead(obj)) { + goto end; + } +#if !defined(Py_GIL_DISABLED) + assert(Py_REFCNT(obj) > 0); +#endif + ret = Py_NewRef(obj); +end: + Py_END_CRITICAL_SECTION(); + return ret; } -static inline int _PyWeakref_IS_DEAD(PyObject *ref_obj) { +static inline int _PyWeakref_IS_DEAD(PyObject *ref_obj) +{ assert(PyWeakref_Check(ref_obj)); + int ret = 0; + Py_BEGIN_CRITICAL_SECTION(ref_obj); PyWeakReference *ref = _Py_CAST(PyWeakReference*, ref_obj); PyObject *obj = ref->wr_object; if (obj == Py_None) { // clear_weakref() was called - return 1; + ret = 1; } - - // See _PyWeakref_GET_REF() for the rationale of this test - return (Py_REFCNT(obj) == 0); + else { + // See _PyWeakref_GET_REF() for the rationale of this test + ret = _is_dead(obj); + } + Py_END_CRITICAL_SECTION(); + return ret; } extern Py_ssize_t _PyWeakref_GetWeakrefCount(PyWeakReference *head); diff --git a/Include/intrcheck.h b/Include/intrcheck.h index b8cc65601683cb..1d1feee83de483 100644 --- a/Include/intrcheck.h +++ b/Include/intrcheck.h @@ -5,6 +5,7 @@ extern "C" { #endif PyAPI_FUNC(int) PyOS_InterruptOccurred(void); + #ifdef HAVE_FORK #if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03070000 PyAPI_FUNC(void) PyOS_BeforeFork(void); @@ -12,18 +13,10 @@ PyAPI_FUNC(void) PyOS_AfterFork_Parent(void); PyAPI_FUNC(void) PyOS_AfterFork_Child(void); #endif #endif + /* Deprecated, please use PyOS_AfterFork_Child() instead */ Py_DEPRECATED(3.7) PyAPI_FUNC(void) PyOS_AfterFork(void); -#ifndef Py_LIMITED_API -PyAPI_FUNC(int) _PyOS_IsMainThread(void); - -#ifdef MS_WINDOWS -/* windows.h is not included by Python.h so use void* instead of HANDLE */ -PyAPI_FUNC(void*) _PyOS_SigintEvent(void); -#endif -#endif /* !Py_LIMITED_API */ - #ifdef __cplusplus } #endif diff --git a/Include/iterobject.h b/Include/iterobject.h index fff30f7176fdeb..e69d09719bb4d1 100644 --- a/Include/iterobject.h +++ b/Include/iterobject.h @@ -7,9 +7,6 @@ extern "C" { PyAPI_DATA(PyTypeObject) PySeqIter_Type; PyAPI_DATA(PyTypeObject) PyCallIter_Type; -#ifdef Py_BUILD_CORE -extern PyTypeObject _PyAnextAwaitable_Type; -#endif #define PySeqIter_Check(op) Py_IS_TYPE((op), &PySeqIter_Type) diff --git a/Include/longobject.h b/Include/longobject.h index e559e238ae5a35..51005efff636fa 100644 --- a/Include/longobject.h +++ b/Include/longobject.h @@ -7,7 +7,7 @@ extern "C" { /* Long (arbitrary precision) integer object interface */ -PyAPI_DATA(PyTypeObject) PyLong_Type; +// PyLong_Type is declared by object.h #define PyLong_Check(op) \ PyType_FastSubclass(Py_TYPE(op), Py_TPFLAGS_LONG_SUBCLASS) @@ -18,12 +18,18 @@ PyAPI_FUNC(PyObject *) PyLong_FromUnsignedLong(unsigned long); PyAPI_FUNC(PyObject *) PyLong_FromSize_t(size_t); PyAPI_FUNC(PyObject *) PyLong_FromSsize_t(Py_ssize_t); PyAPI_FUNC(PyObject *) PyLong_FromDouble(double); + PyAPI_FUNC(long) PyLong_AsLong(PyObject *); PyAPI_FUNC(long) PyLong_AsLongAndOverflow(PyObject *, int *); PyAPI_FUNC(Py_ssize_t) PyLong_AsSsize_t(PyObject *); PyAPI_FUNC(size_t) PyLong_AsSize_t(PyObject *); PyAPI_FUNC(unsigned long) PyLong_AsUnsignedLong(PyObject *); PyAPI_FUNC(unsigned long) PyLong_AsUnsignedLongMask(PyObject *); + +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x030d0000 +PyAPI_FUNC(int) PyLong_AsInt(PyObject *); +#endif + PyAPI_FUNC(PyObject *) PyLong_GetInfo(void); /* It may be useful in the future. I've added it in the PyInt -> PyLong diff --git a/Include/modsupport.h b/Include/modsupport.h index 88577e027b5275..ea4c0fce9f4562 100644 --- a/Include/modsupport.h +++ b/Include/modsupport.h @@ -1,3 +1,4 @@ +// Module support interface #ifndef Py_MODSUPPORT_H #define Py_MODSUPPORT_H @@ -5,17 +6,13 @@ extern "C" { #endif -/* Module support interface */ - -#include // va_list - PyAPI_FUNC(int) PyArg_Parse(PyObject *, const char *, ...); PyAPI_FUNC(int) PyArg_ParseTuple(PyObject *, const char *, ...); PyAPI_FUNC(int) PyArg_ParseTupleAndKeywords(PyObject *, PyObject *, - const char *, char **, ...); + const char *, PY_CXX_CONST char * const *, ...); PyAPI_FUNC(int) PyArg_VaParse(PyObject *, const char *, va_list); PyAPI_FUNC(int) PyArg_VaParseTupleAndKeywords(PyObject *, PyObject *, - const char *, char **, va_list); + const char *, PY_CXX_CONST char * const *, va_list); PyAPI_FUNC(int) PyArg_ValidateKeywordArguments(PyObject *); PyAPI_FUNC(int) PyArg_UnpackTuple(PyObject *, const char *, Py_ssize_t, Py_ssize_t, ...); @@ -111,14 +108,6 @@ PyAPI_FUNC(int) PyModule_ExecDef(PyObject *module, PyModuleDef *def); #define PYTHON_ABI_VERSION 3 #define PYTHON_ABI_STRING "3" -#ifdef Py_TRACE_REFS - /* When we are tracing reference counts, rename module creation functions so - modules compiled with incompatible settings will generate a - link-time error. */ - #define PyModule_Create2 PyModule_Create2TraceRefs - #define PyModule_FromDefAndSpec2 PyModule_FromDefAndSpec2TraceRefs -#endif - PyAPI_FUNC(PyObject *) PyModule_Create2(PyModuleDef*, int apiver); #ifdef Py_LIMITED_API @@ -145,12 +134,6 @@ PyAPI_FUNC(PyObject *) PyModule_FromDefAndSpec2(PyModuleDef *def, #endif /* New in 3.5 */ -#ifndef Py_LIMITED_API -# define Py_CPYTHON_MODSUPPORT_H -# include "cpython/modsupport.h" -# undef Py_CPYTHON_MODSUPPORT_H -#endif - #ifdef __cplusplus } #endif diff --git a/Include/moduleobject.h b/Include/moduleobject.h index ea08145381cee6..42b87cc4e91012 100644 --- a/Include/moduleobject.h +++ b/Include/moduleobject.h @@ -73,19 +73,23 @@ struct PyModuleDef_Slot { #define Py_mod_create 1 #define Py_mod_exec 2 -#define Py_mod_multiple_interpreters 3 +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x030c0000 +# define Py_mod_multiple_interpreters 3 +#endif #ifndef Py_LIMITED_API #define _Py_mod_LAST_SLOT 3 #endif -/* for Py_mod_multiple_interpreters: */ -#define Py_MOD_MULTIPLE_INTERPRETERS_NOT_SUPPORTED ((void *)0) -#define Py_MOD_MULTIPLE_INTERPRETERS_SUPPORTED ((void *)1) -#define Py_MOD_PER_INTERPRETER_GIL_SUPPORTED ((void *)2) - #endif /* New in 3.5 */ +/* for Py_mod_multiple_interpreters: */ +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x030c0000 +# define Py_MOD_MULTIPLE_INTERPRETERS_NOT_SUPPORTED ((void *)0) +# define Py_MOD_MULTIPLE_INTERPRETERS_SUPPORTED ((void *)1) +# define Py_MOD_PER_INTERPRETER_GIL_SUPPORTED ((void *)2) +#endif + struct PyModuleDef { PyModuleDef_Base m_base; const char* m_name; diff --git a/Include/object.h b/Include/object.h index e26cedf8ca3c97..48f1ddf7510887 100644 --- a/Include/object.h +++ b/Include/object.h @@ -51,30 +51,11 @@ A standard interface exists for objects that contain an array of items whose size is determined when the object is allocated. */ -#include "pystats.h" - /* Py_DEBUG implies Py_REF_DEBUG. */ #if defined(Py_DEBUG) && !defined(Py_REF_DEBUG) # define Py_REF_DEBUG #endif -#if defined(Py_LIMITED_API) && defined(Py_TRACE_REFS) -# error Py_LIMITED_API is incompatible with Py_TRACE_REFS -#endif - -#ifdef Py_TRACE_REFS -/* Define pointers to support a doubly-linked list of all live heap objects. */ -#define _PyObject_HEAD_EXTRA \ - PyObject *_ob_next; \ - PyObject *_ob_prev; - -#define _PyObject_EXTRA_INIT _Py_NULL, _Py_NULL, - -#else -# define _PyObject_HEAD_EXTRA -# define _PyObject_EXTRA_INIT -#endif - /* PyObject_HEAD defines the initial segment of every PyObject. */ #define PyObject_HEAD PyObject ob_base; @@ -107,7 +88,7 @@ having all the lower 32 bits set, which will avoid the reference count to go beyond the refcount limit. Immortality checks for reference count decreases will be done by checking the bit sign flag in the lower 32 bits. */ -#define _Py_IMMORTAL_REFCNT UINT_MAX +#define _Py_IMMORTAL_REFCNT _Py_CAST(Py_ssize_t, UINT_MAX) #else /* @@ -122,22 +103,40 @@ immortality, but the execution would still be correct. Reference count increases and decreases will first go through an immortality check by comparing the reference count field to the immortality reference count. */ -#define _Py_IMMORTAL_REFCNT (UINT_MAX >> 2) +#define _Py_IMMORTAL_REFCNT _Py_CAST(Py_ssize_t, UINT_MAX >> 2) +#endif + +// Py_GIL_DISABLED builds indicate immortal objects using `ob_ref_local`, which is +// always 32-bits. +#ifdef Py_GIL_DISABLED +#define _Py_IMMORTAL_REFCNT_LOCAL UINT32_MAX #endif +// Kept for backward compatibility. It was needed by Py_TRACE_REFS build. +#define _PyObject_EXTRA_INIT + // Make all internal uses of PyObject_HEAD_INIT immortal while preserving the // C-API expectation that the refcnt will be set to 1. -#ifdef Py_BUILD_CORE +#if defined(Py_GIL_DISABLED) +#define PyObject_HEAD_INIT(type) \ + { \ + 0, \ + 0, \ + { 0 }, \ + 0, \ + _Py_IMMORTAL_REFCNT_LOCAL, \ + 0, \ + (type), \ + }, +#elif defined(Py_BUILD_CORE) #define PyObject_HEAD_INIT(type) \ { \ - _PyObject_EXTRA_INIT \ { _Py_IMMORTAL_REFCNT }, \ (type) \ }, #else #define PyObject_HEAD_INIT(type) \ { \ - _PyObject_EXTRA_INIT \ { 1 }, \ (type) \ }, @@ -163,9 +162,8 @@ check by comparing the reference count field to the immortality reference count. * by hand. Similarly every pointer to a variable-size Python object can, * in addition, be cast to PyVarObject*. */ +#ifndef Py_GIL_DISABLED struct _object { - _PyObject_HEAD_EXTRA - #if (defined(__GNUC__) || defined(__clang__)) \ && !(defined __STDC_VERSION__ && __STDC_VERSION__ >= 201112L) // On C99 and older, anonymous union is a GCC and clang extension @@ -189,6 +187,40 @@ struct _object { PyTypeObject *ob_type; }; +#else +// Objects that are not owned by any thread use a thread id (tid) of zero. +// This includes both immortal objects and objects whose reference count +// fields have been merged. +#define _Py_UNOWNED_TID 0 + +// The shared reference count uses the two least-significant bits to store +// flags. The remaining bits are used to store the reference count. +#define _Py_REF_SHARED_SHIFT 2 +#define _Py_REF_SHARED_FLAG_MASK 0x3 + +// The shared flags are initialized to zero. +#define _Py_REF_SHARED_INIT 0x0 +#define _Py_REF_MAYBE_WEAKREF 0x1 +#define _Py_REF_QUEUED 0x2 +#define _Py_REF_MERGED 0x3 + +// Create a shared field from a refcnt and desired flags +#define _Py_REF_SHARED(refcnt, flags) (((refcnt) << _Py_REF_SHARED_SHIFT) + (flags)) + +// NOTE: In non-free-threaded builds, `struct _PyMutex` is defined in +// pycore_lock.h. See pycore_lock.h for more details. +struct _PyMutex { uint8_t v; }; + +struct _object { + uintptr_t ob_tid; // thread id (or zero) + uint16_t _padding; + struct _PyMutex ob_mutex; // per-object lock + uint8_t ob_gc_bits; // gc-related state + uint32_t ob_ref_local; // local reference count + Py_ssize_t ob_ref_shared; // shared (atomic) reference count + PyTypeObject *ob_type; +}; +#endif /* Cast argument to PyObject* type. */ #define _PyObject_CAST(op) _Py_CAST(PyObject*, (op)) @@ -206,9 +238,87 @@ typedef struct { PyAPI_FUNC(int) Py_Is(PyObject *x, PyObject *y); #define Py_Is(x, y) ((x) == (y)) +#if defined(Py_GIL_DISABLED) && !defined(Py_LIMITED_API) +PyAPI_FUNC(uintptr_t) _Py_GetThreadLocal_Addr(void); + +static inline uintptr_t +_Py_ThreadId(void) +{ + uintptr_t tid; +#if defined(_MSC_VER) && defined(_M_X64) + tid = __readgsqword(48); +#elif defined(_MSC_VER) && defined(_M_IX86) + tid = __readfsdword(24); +#elif defined(_MSC_VER) && defined(_M_ARM64) + tid = __getReg(18); +#elif defined(__i386__) + __asm__("movl %%gs:0, %0" : "=r" (tid)); // 32-bit always uses GS +#elif defined(__MACH__) && defined(__x86_64__) + __asm__("movq %%gs:0, %0" : "=r" (tid)); // x86_64 macOSX uses GS +#elif defined(__x86_64__) + __asm__("movq %%fs:0, %0" : "=r" (tid)); // x86_64 Linux, BSD uses FS +#elif defined(__arm__) + __asm__ ("mrc p15, 0, %0, c13, c0, 3\nbic %0, %0, #3" : "=r" (tid)); +#elif defined(__aarch64__) && defined(__APPLE__) + __asm__ ("mrs %0, tpidrro_el0" : "=r" (tid)); +#elif defined(__aarch64__) + __asm__ ("mrs %0, tpidr_el0" : "=r" (tid)); +#elif defined(__powerpc64__) + #if defined(__clang__) && _Py__has_builtin(__builtin_thread_pointer) + tid = (uintptr_t)__builtin_thread_pointer(); + #else + // r13 is reserved for use as system thread ID by the Power 64-bit ABI. + register uintptr_t tp __asm__ ("r13"); + __asm__("" : "=r" (tp)); + tid = tp; + #endif +#elif defined(__powerpc__) + #if defined(__clang__) && _Py__has_builtin(__builtin_thread_pointer) + tid = (uintptr_t)__builtin_thread_pointer(); + #else + // r2 is reserved for use as system thread ID by the Power 32-bit ABI. + register uintptr_t tp __asm__ ("r2"); + __asm__ ("" : "=r" (tp)); + tid = tp; + #endif +#elif defined(__s390__) && defined(__GNUC__) + // Both GCC and Clang have supported __builtin_thread_pointer + // for s390 from long time ago. + tid = (uintptr_t)__builtin_thread_pointer(); +#elif defined(__riscv) + #if defined(__clang__) && _Py__has_builtin(__builtin_thread_pointer) + tid = (uintptr_t)__builtin_thread_pointer(); + #else + // tp is Thread Pointer provided by the RISC-V ABI. + __asm__ ("mv %0, tp" : "=r" (tid)); + #endif +#else + // Fallback to a portable implementation if we do not have a faster + // platform-specific implementation. + tid = _Py_GetThreadLocal_Addr(); +#endif + return tid; +} + +static inline Py_ALWAYS_INLINE int +_Py_IsOwnedByCurrentThread(PyObject *ob) +{ + return ob->ob_tid == _Py_ThreadId(); +} +#endif static inline Py_ssize_t Py_REFCNT(PyObject *ob) { +#if !defined(Py_GIL_DISABLED) return ob->ob_refcnt; +#else + uint32_t local = _Py_atomic_load_uint32_relaxed(&ob->ob_ref_local); + if (local == _Py_IMMORTAL_REFCNT_LOCAL) { + return _Py_IMMORTAL_REFCNT; + } + Py_ssize_t shared = _Py_atomic_load_ssize_relaxed(&ob->ob_ref_shared); + return _Py_STATIC_CAST(Py_ssize_t, local) + + Py_ARITHMETIC_RIGHT_SHIFT(Py_ssize_t, shared, _Py_REF_SHARED_SHIFT); +#endif } #if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000 # define Py_REFCNT(ob) Py_REFCNT(_PyObject_CAST(ob)) @@ -239,10 +349,12 @@ static inline Py_ssize_t Py_SIZE(PyObject *ob) { static inline Py_ALWAYS_INLINE int _Py_IsImmortal(PyObject *op) { -#if SIZEOF_VOID_P > 4 - return _Py_CAST(PY_INT32_T, op->ob_refcnt) < 0; +#if defined(Py_GIL_DISABLED) + return (op->ob_ref_local == _Py_IMMORTAL_REFCNT_LOCAL); +#elif SIZEOF_VOID_P > 4 + return (_Py_CAST(PY_INT32_T, op->ob_refcnt) < 0); #else - return op->ob_refcnt == _Py_IMMORTAL_REFCNT; + return (op->ob_refcnt == _Py_IMMORTAL_REFCNT); #endif } #define _Py_IsImmortal(op) _Py_IsImmortal(_PyObject_CAST(op)) @@ -255,7 +367,15 @@ static inline int Py_IS_TYPE(PyObject *ob, PyTypeObject *type) { #endif +// Py_SET_REFCNT() implementation for stable ABI +PyAPI_FUNC(void) _Py_SetRefcnt(PyObject *ob, Py_ssize_t refcnt); + static inline void Py_SET_REFCNT(PyObject *ob, Py_ssize_t refcnt) { +#if defined(Py_LIMITED_API) && Py_LIMITED_API+0 >= 0x030d0000 + // Stable ABI implements Py_SET_REFCNT() as a function call + // on limited C API version 3.13 and newer. + _Py_SetRefcnt(ob, refcnt); +#else // This immortal check is for code that is unaware of immortal objects. // The runtime tracks these objects and we should avoid as much // as possible having extensions inadvertently change the refcnt @@ -263,7 +383,33 @@ static inline void Py_SET_REFCNT(PyObject *ob, Py_ssize_t refcnt) { if (_Py_IsImmortal(ob)) { return; } + +#ifndef Py_GIL_DISABLED ob->ob_refcnt = refcnt; +#else + if (_Py_IsOwnedByCurrentThread(ob)) { + if ((size_t)refcnt > (size_t)UINT32_MAX) { + // On overflow, make the object immortal + ob->ob_tid = _Py_UNOWNED_TID; + ob->ob_ref_local = _Py_IMMORTAL_REFCNT_LOCAL; + ob->ob_ref_shared = 0; + } + else { + // Set local refcount to desired refcount and shared refcount + // to zero, but preserve the shared refcount flags. + ob->ob_ref_local = _Py_STATIC_CAST(uint32_t, refcnt); + ob->ob_ref_shared &= _Py_REF_SHARED_FLAG_MASK; + } + } + else { + // Set local refcount to zero and shared refcount to desired refcount. + // Mark the object as merged. + ob->ob_tid = _Py_UNOWNED_TID; + ob->ob_ref_local = 0; + ob->ob_ref_shared = _Py_REF_SHARED(refcnt, _Py_REF_MERGED); + } +#endif // Py_GIL_DISABLED +#endif // Py_LIMITED_API+0 < 0x030d0000 } #if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000 # define Py_SET_REFCNT(ob, refcnt) Py_SET_REFCNT(_PyObject_CAST(ob), (refcnt)) @@ -417,6 +563,10 @@ PyAPI_FUNC(int) PyObject_GetOptionalAttrString(PyObject *, const char *, PyObjec PyAPI_FUNC(int) PyObject_SetAttr(PyObject *, PyObject *, PyObject *); PyAPI_FUNC(int) PyObject_DelAttr(PyObject *v, PyObject *name); PyAPI_FUNC(int) PyObject_HasAttr(PyObject *, PyObject *); +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x030d0000 +PyAPI_FUNC(int) PyObject_HasAttrWithError(PyObject *, PyObject *); +PyAPI_FUNC(int) PyObject_HasAttrStringWithError(PyObject *, const char *); +#endif PyAPI_FUNC(PyObject *) PyObject_SelfIter(PyObject *); PyAPI_FUNC(PyObject *) PyObject_GenericGetAttr(PyObject *, PyObject *); PyAPI_FUNC(int) PyObject_GenericSetAttr(PyObject *, PyObject *, PyObject *); @@ -437,12 +587,6 @@ PyAPI_FUNC(void) PyObject_ClearWeakRefs(PyObject *); */ PyAPI_FUNC(PyObject *) PyObject_Dir(PyObject *); -/* Pickle support. */ -#ifndef Py_LIMITED_API -PyAPI_FUNC(PyObject *) _PyObject_GetState(PyObject *); -#endif - - /* Helpers for printing recursive container types */ PyAPI_FUNC(int) Py_ReprEnter(PyObject *); PyAPI_FUNC(void) Py_ReprLeave(PyObject *); @@ -643,11 +787,26 @@ static inline Py_ALWAYS_INLINE void Py_INCREF(PyObject *op) #else // Non-limited C API and limited C API for Python 3.9 and older access // directly PyObject.ob_refcnt. -#if SIZEOF_VOID_P > 4 +#if defined(Py_GIL_DISABLED) + uint32_t local = _Py_atomic_load_uint32_relaxed(&op->ob_ref_local); + uint32_t new_local = local + 1; + if (new_local == 0) { + // local is equal to _Py_IMMORTAL_REFCNT: do nothing + return; + } + if (_Py_IsOwnedByCurrentThread(op)) { + _Py_atomic_store_uint32_relaxed(&op->ob_ref_local, new_local); + } + else { + _Py_atomic_add_ssize(&op->ob_ref_shared, (1 << _Py_REF_SHARED_SHIFT)); + } +#elif SIZEOF_VOID_P > 4 // Portable saturated add, branching on the carry flag and set low bits PY_UINT32_T cur_refcnt = op->ob_refcnt_split[PY_BIG_ENDIAN]; PY_UINT32_T new_refcnt = cur_refcnt + 1; if (new_refcnt == 0) { + // cur_refcnt is equal to _Py_IMMORTAL_REFCNT: the object is immortal, + // do nothing return; } op->ob_refcnt_split[PY_BIG_ENDIAN] = new_refcnt; @@ -668,6 +827,19 @@ static inline Py_ALWAYS_INLINE void Py_INCREF(PyObject *op) # define Py_INCREF(op) Py_INCREF(_PyObject_CAST(op)) #endif + +#if !defined(Py_LIMITED_API) && defined(Py_GIL_DISABLED) +// Implements Py_DECREF on objects not owned by the current thread. +PyAPI_FUNC(void) _Py_DecRefShared(PyObject *); +PyAPI_FUNC(void) _Py_DecRefSharedDebug(PyObject *, const char *, int); + +// Called from Py_DECREF by the owning thread when the local refcount reaches +// zero. The call will deallocate the object if the shared refcount is also +// zero. Otherwise, the thread gives up ownership and merges the reference +// count fields. +PyAPI_FUNC(void) _Py_MergeZeroLocalRefcount(PyObject *); +#endif + #if defined(Py_LIMITED_API) && (Py_LIMITED_API+0 >= 0x030c0000 || defined(Py_REF_DEBUG)) // Stable ABI implements Py_DECREF() as a function call on limited C API // version 3.12 and newer, and on Python built in debug mode. _Py_DecRef() was @@ -682,20 +854,64 @@ static inline void Py_DECREF(PyObject *op) { } #define Py_DECREF(op) Py_DECREF(_PyObject_CAST(op)) -#elif defined(Py_REF_DEBUG) +#elif defined(Py_GIL_DISABLED) && defined(Py_REF_DEBUG) static inline void Py_DECREF(const char *filename, int lineno, PyObject *op) { - if (_Py_IsImmortal(op)) { + uint32_t local = _Py_atomic_load_uint32_relaxed(&op->ob_ref_local); + if (local == _Py_IMMORTAL_REFCNT_LOCAL) { return; } _Py_DECREF_STAT_INC(); _Py_DECREF_DecRefTotal(); - if (--op->ob_refcnt != 0) { - if (op->ob_refcnt < 0) { + if (_Py_IsOwnedByCurrentThread(op)) { + if (local == 0) { _Py_NegativeRefcount(filename, lineno, op); } + local--; + _Py_atomic_store_uint32_relaxed(&op->ob_ref_local, local); + if (local == 0) { + _Py_MergeZeroLocalRefcount(op); + } + } + else { + _Py_DecRefSharedDebug(op, filename, lineno); + } +} +#define Py_DECREF(op) Py_DECREF(__FILE__, __LINE__, _PyObject_CAST(op)) + +#elif defined(Py_GIL_DISABLED) +static inline void Py_DECREF(PyObject *op) +{ + uint32_t local = _Py_atomic_load_uint32_relaxed(&op->ob_ref_local); + if (local == _Py_IMMORTAL_REFCNT_LOCAL) { + return; + } + _Py_DECREF_STAT_INC(); + if (_Py_IsOwnedByCurrentThread(op)) { + local--; + _Py_atomic_store_uint32_relaxed(&op->ob_ref_local, local); + if (local == 0) { + _Py_MergeZeroLocalRefcount(op); + } } else { + _Py_DecRefShared(op); + } +} +#define Py_DECREF(op) Py_DECREF(_PyObject_CAST(op)) + +#elif defined(Py_REF_DEBUG) +static inline void Py_DECREF(const char *filename, int lineno, PyObject *op) +{ + if (op->ob_refcnt <= 0) { + _Py_NegativeRefcount(filename, lineno, op); + } + if (_Py_IsImmortal(op)) { + return; + } + _Py_DECREF_STAT_INC(); + _Py_DECREF_DecRefTotal(); + if (--op->ob_refcnt == 0) { _Py_Dealloc(op); } } @@ -845,8 +1061,6 @@ static inline PyObject* _Py_XNewRef(PyObject *obj) /* _Py_NoneStruct is an object of undefined type which can be used in contexts where NULL (nil) is not suitable (since NULL often means 'error'). - -Don't forget to apply Py_INCREF() when returning this value!!! */ PyAPI_DATA(PyObject) _Py_NoneStruct; /* Don't use this directly */ #define Py_None (&_Py_NoneStruct) diff --git a/Include/objimpl.h b/Include/objimpl.h index ef871c5ea93ebe..ff5fa7a8c1d3d8 100644 --- a/Include/objimpl.h +++ b/Include/objimpl.h @@ -1,12 +1,8 @@ -/* The PyObject_ memory family: high-level object memory interfaces. - See pymem.h for the low-level PyMem_ family. -*/ +// The PyObject_ memory family: high-level object memory interfaces. +// See pymem.h for the low-level PyMem_ family. #ifndef Py_OBJIMPL_H #define Py_OBJIMPL_H - -#include "pymem.h" - #ifdef __cplusplus extern "C" { #endif @@ -39,7 +35,7 @@ Functions and macros for modules that implement new object types. fields, this also fills in the ob_size field. - PyObject_Free(op) releases the memory allocated for an object. It does not - run a destructor -- it only frees the memory. PyObject_Free is identical. + run a destructor -- it only frees the memory. - PyObject_Init(op, typeobj) and PyObject_InitVar(op, typeobj, n) don't allocate memory. Instead of a 'type' parameter, they take a pointer to a @@ -231,4 +227,4 @@ PyAPI_FUNC(int) PyObject_GC_IsFinalized(PyObject *); #ifdef __cplusplus } #endif -#endif /* !Py_OBJIMPL_H */ +#endif // !Py_OBJIMPL_H diff --git a/Include/opcode.h b/Include/opcode.h index ede1518b6fd25c..2619b690019acc 100644 --- a/Include/opcode.h +++ b/Include/opcode.h @@ -1,231 +1,11 @@ -// Auto-generated by Tools/build/generate_opcode_h.py from Lib/opcode.py - #ifndef Py_OPCODE_H #define Py_OPCODE_H #ifdef __cplusplus extern "C" { #endif +#include "opcode_ids.h" -/* Instruction opcodes for compiled code */ -#define CACHE 0 -#define POP_TOP 1 -#define PUSH_NULL 2 -#define INTERPRETER_EXIT 3 -#define END_FOR 4 -#define END_SEND 5 -#define TO_BOOL 6 -#define NOP 9 -#define UNARY_NEGATIVE 11 -#define UNARY_NOT 12 -#define UNARY_INVERT 15 -#define EXIT_INIT_CHECK 16 -#define RESERVED 17 -#define MAKE_FUNCTION 24 -#define BINARY_SUBSCR 25 -#define BINARY_SLICE 26 -#define STORE_SLICE 27 -#define GET_LEN 30 -#define MATCH_MAPPING 31 -#define MATCH_SEQUENCE 32 -#define MATCH_KEYS 33 -#define PUSH_EXC_INFO 35 -#define CHECK_EXC_MATCH 36 -#define CHECK_EG_MATCH 37 -#define FORMAT_SIMPLE 40 -#define FORMAT_WITH_SPEC 41 -#define WITH_EXCEPT_START 49 -#define GET_AITER 50 -#define GET_ANEXT 51 -#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 -#define GET_YIELD_FROM_ITER 69 -#define LOAD_BUILD_CLASS 71 -#define LOAD_ASSERTION_ERROR 74 -#define RETURN_GENERATOR 75 -#define RETURN_VALUE 83 -#define SETUP_ANNOTATIONS 85 -#define LOAD_LOCALS 87 -#define POP_EXCEPT 89 -#define STORE_NAME 90 -#define DELETE_NAME 91 -#define UNPACK_SEQUENCE 92 -#define FOR_ITER 93 -#define UNPACK_EX 94 -#define STORE_ATTR 95 -#define DELETE_ATTR 96 -#define STORE_GLOBAL 97 -#define DELETE_GLOBAL 98 -#define SWAP 99 -#define LOAD_CONST 100 -#define LOAD_NAME 101 -#define BUILD_TUPLE 102 -#define BUILD_LIST 103 -#define BUILD_SET 104 -#define BUILD_MAP 105 -#define LOAD_ATTR 106 -#define COMPARE_OP 107 -#define IMPORT_NAME 108 -#define IMPORT_FROM 109 -#define JUMP_FORWARD 110 -#define POP_JUMP_IF_FALSE 114 -#define POP_JUMP_IF_TRUE 115 -#define LOAD_GLOBAL 116 -#define IS_OP 117 -#define CONTAINS_OP 118 -#define RERAISE 119 -#define COPY 120 -#define RETURN_CONST 121 -#define BINARY_OP 122 -#define SEND 123 -#define LOAD_FAST 124 -#define STORE_FAST 125 -#define DELETE_FAST 126 -#define LOAD_FAST_CHECK 127 -#define POP_JUMP_IF_NOT_NONE 128 -#define POP_JUMP_IF_NONE 129 -#define RAISE_VARARGS 130 -#define GET_AWAITABLE 131 -#define BUILD_SLICE 133 -#define JUMP_BACKWARD_NO_INTERRUPT 134 -#define MAKE_CELL 135 -#define LOAD_DEREF 137 -#define STORE_DEREF 138 -#define DELETE_DEREF 139 -#define JUMP_BACKWARD 140 -#define LOAD_SUPER_ATTR 141 -#define CALL_FUNCTION_EX 142 -#define LOAD_FAST_AND_CLEAR 143 -#define EXTENDED_ARG 144 -#define LIST_APPEND 145 -#define SET_ADD 146 -#define MAP_ADD 147 -#define COPY_FREE_VARS 149 -#define YIELD_VALUE 150 -#define RESUME 151 -#define MATCH_CLASS 152 -#define BUILD_CONST_KEY_MAP 156 -#define BUILD_STRING 157 -#define CONVERT_VALUE 158 -#define LIST_EXTEND 162 -#define SET_UPDATE 163 -#define DICT_MERGE 164 -#define DICT_UPDATE 165 -#define LOAD_FAST_LOAD_FAST 168 -#define STORE_FAST_LOAD_FAST 169 -#define STORE_FAST_STORE_FAST 170 -#define CALL 171 -#define KW_NAMES 172 -#define CALL_INTRINSIC_1 173 -#define CALL_INTRINSIC_2 174 -#define LOAD_FROM_DICT_OR_GLOBALS 175 -#define LOAD_FROM_DICT_OR_DEREF 176 -#define SET_FUNCTION_ATTRIBUTE 177 -#define ENTER_EXECUTOR 230 -#define MIN_INSTRUMENTED_OPCODE 237 -#define INSTRUMENTED_LOAD_SUPER_ATTR 237 -#define INSTRUMENTED_POP_JUMP_IF_NONE 238 -#define INSTRUMENTED_POP_JUMP_IF_NOT_NONE 239 -#define INSTRUMENTED_RESUME 240 -#define INSTRUMENTED_CALL 241 -#define INSTRUMENTED_RETURN_VALUE 242 -#define INSTRUMENTED_YIELD_VALUE 243 -#define INSTRUMENTED_CALL_FUNCTION_EX 244 -#define INSTRUMENTED_JUMP_FORWARD 245 -#define INSTRUMENTED_JUMP_BACKWARD 246 -#define INSTRUMENTED_RETURN_CONST 247 -#define INSTRUMENTED_FOR_ITER 248 -#define INSTRUMENTED_POP_JUMP_IF_FALSE 249 -#define INSTRUMENTED_POP_JUMP_IF_TRUE 250 -#define INSTRUMENTED_END_FOR 251 -#define INSTRUMENTED_END_SEND 252 -#define INSTRUMENTED_INSTRUCTION 253 -#define INSTRUMENTED_LINE 254 -#define SETUP_FINALLY 256 -#define SETUP_CLEANUP 257 -#define SETUP_WITH 258 -#define POP_BLOCK 259 -#define JUMP 260 -#define JUMP_NO_INTERRUPT 261 -#define LOAD_METHOD 262 -#define LOAD_SUPER_METHOD 263 -#define LOAD_ZERO_SUPER_METHOD 264 -#define LOAD_ZERO_SUPER_ATTR 265 -#define STORE_FAST_MAYBE_NULL 266 -#define LOAD_CLOSURE 267 -#define TO_BOOL_ALWAYS_TRUE 7 -#define TO_BOOL_BOOL 8 -#define TO_BOOL_INT 10 -#define TO_BOOL_LIST 13 -#define TO_BOOL_NONE 14 -#define TO_BOOL_STR 18 -#define BINARY_OP_MULTIPLY_INT 19 -#define BINARY_OP_ADD_INT 20 -#define BINARY_OP_SUBTRACT_INT 21 -#define BINARY_OP_MULTIPLY_FLOAT 22 -#define BINARY_OP_ADD_FLOAT 23 -#define BINARY_OP_SUBTRACT_FLOAT 28 -#define BINARY_OP_ADD_UNICODE 29 -#define BINARY_OP_INPLACE_ADD_UNICODE 34 -#define BINARY_SUBSCR_DICT 38 -#define BINARY_SUBSCR_GETITEM 39 -#define BINARY_SUBSCR_LIST_INT 42 -#define BINARY_SUBSCR_TUPLE_INT 43 -#define STORE_SUBSCR_DICT 44 -#define STORE_SUBSCR_LIST_INT 45 -#define SEND_GEN 46 -#define UNPACK_SEQUENCE_TWO_TUPLE 47 -#define UNPACK_SEQUENCE_TUPLE 48 -#define UNPACK_SEQUENCE_LIST 56 -#define STORE_ATTR_INSTANCE_VALUE 57 -#define STORE_ATTR_SLOT 58 -#define STORE_ATTR_WITH_HINT 59 -#define LOAD_GLOBAL_MODULE 62 -#define LOAD_GLOBAL_BUILTIN 63 -#define LOAD_SUPER_ATTR_ATTR 64 -#define LOAD_SUPER_ATTR_METHOD 65 -#define LOAD_ATTR_INSTANCE_VALUE 66 -#define LOAD_ATTR_MODULE 67 -#define LOAD_ATTR_WITH_HINT 70 -#define LOAD_ATTR_SLOT 72 -#define LOAD_ATTR_CLASS 73 -#define LOAD_ATTR_PROPERTY 76 -#define LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN 77 -#define LOAD_ATTR_METHOD_WITH_VALUES 78 -#define LOAD_ATTR_METHOD_NO_DICT 79 -#define LOAD_ATTR_METHOD_LAZY_DICT 80 -#define LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES 81 -#define LOAD_ATTR_NONDESCRIPTOR_NO_DICT 82 -#define COMPARE_OP_FLOAT 84 -#define COMPARE_OP_INT 86 -#define COMPARE_OP_STR 88 -#define FOR_ITER_LIST 111 -#define FOR_ITER_TUPLE 112 -#define FOR_ITER_RANGE 113 -#define FOR_ITER_GEN 132 -#define CALL_BOUND_METHOD_EXACT_ARGS 136 -#define CALL_PY_EXACT_ARGS 148 -#define CALL_PY_WITH_DEFAULTS 153 -#define CALL_NO_KW_TYPE_1 154 -#define CALL_NO_KW_STR_1 155 -#define CALL_NO_KW_TUPLE_1 159 -#define CALL_BUILTIN_CLASS 160 -#define CALL_NO_KW_BUILTIN_O 161 -#define CALL_NO_KW_BUILTIN_FAST 166 -#define CALL_BUILTIN_FAST_WITH_KEYWORDS 167 -#define CALL_NO_KW_LEN 178 -#define CALL_NO_KW_ISINSTANCE 179 -#define CALL_NO_KW_LIST_APPEND 180 -#define CALL_NO_KW_METHOD_DESCRIPTOR_O 181 -#define CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS 182 -#define CALL_NO_KW_METHOD_DESCRIPTOR_NOARGS 183 -#define CALL_NO_KW_METHOD_DESCRIPTOR_FAST 184 -#define CALL_NO_KW_ALLOC_AND_ENTER_INIT 185 #define NB_ADD 0 #define NB_AND 1 @@ -254,6 +34,7 @@ extern "C" { #define NB_INPLACE_TRUE_DIVIDE 24 #define NB_INPLACE_XOR 25 +#define NB_OPARG_LAST 25 #ifdef __cplusplus } diff --git a/Include/opcode_ids.h b/Include/opcode_ids.h new file mode 100644 index 00000000000000..fe969342ee79e7 --- /dev/null +++ b/Include/opcode_ids.h @@ -0,0 +1,240 @@ +// This file is generated by Tools/cases_generator/opcode_id_generator.py +// from: +// Python/bytecodes.c +// Do not edit! + +#ifndef Py_OPCODE_IDS_H +#define Py_OPCODE_IDS_H +#ifdef __cplusplus +extern "C" { +#endif + +/* Instruction opcodes for compiled code */ +#define CACHE 0 +#define BEFORE_ASYNC_WITH 1 +#define BEFORE_WITH 2 +#define BINARY_OP_INPLACE_ADD_UNICODE 3 +#define BINARY_SLICE 4 +#define BINARY_SUBSCR 5 +#define CHECK_EG_MATCH 6 +#define CHECK_EXC_MATCH 7 +#define CLEANUP_THROW 8 +#define DELETE_SUBSCR 9 +#define END_ASYNC_FOR 10 +#define END_FOR 11 +#define END_SEND 12 +#define EXIT_INIT_CHECK 13 +#define FORMAT_SIMPLE 14 +#define FORMAT_WITH_SPEC 15 +#define GET_AITER 16 +#define RESERVED 17 +#define GET_ANEXT 18 +#define GET_ITER 19 +#define GET_LEN 20 +#define GET_YIELD_FROM_ITER 21 +#define INTERPRETER_EXIT 22 +#define LOAD_ASSERTION_ERROR 23 +#define LOAD_BUILD_CLASS 24 +#define LOAD_LOCALS 25 +#define MAKE_FUNCTION 26 +#define MATCH_KEYS 27 +#define MATCH_MAPPING 28 +#define MATCH_SEQUENCE 29 +#define NOP 30 +#define POP_EXCEPT 31 +#define POP_TOP 32 +#define PUSH_EXC_INFO 33 +#define PUSH_NULL 34 +#define RETURN_GENERATOR 35 +#define RETURN_VALUE 36 +#define SETUP_ANNOTATIONS 37 +#define STORE_SLICE 38 +#define STORE_SUBSCR 39 +#define TO_BOOL 40 +#define UNARY_INVERT 41 +#define UNARY_NEGATIVE 42 +#define UNARY_NOT 43 +#define WITH_EXCEPT_START 44 +#define BINARY_OP 45 +#define BUILD_CONST_KEY_MAP 46 +#define BUILD_LIST 47 +#define BUILD_MAP 48 +#define BUILD_SET 49 +#define BUILD_SLICE 50 +#define BUILD_STRING 51 +#define BUILD_TUPLE 52 +#define CALL 53 +#define CALL_FUNCTION_EX 54 +#define CALL_INTRINSIC_1 55 +#define CALL_INTRINSIC_2 56 +#define CALL_KW 57 +#define COMPARE_OP 58 +#define CONTAINS_OP 59 +#define CONVERT_VALUE 60 +#define COPY 61 +#define COPY_FREE_VARS 62 +#define DELETE_ATTR 63 +#define DELETE_DEREF 64 +#define DELETE_FAST 65 +#define DELETE_GLOBAL 66 +#define DELETE_NAME 67 +#define DICT_MERGE 68 +#define DICT_UPDATE 69 +#define ENTER_EXECUTOR 70 +#define EXTENDED_ARG 71 +#define FOR_ITER 72 +#define GET_AWAITABLE 73 +#define IMPORT_FROM 74 +#define IMPORT_NAME 75 +#define IS_OP 76 +#define JUMP_BACKWARD 77 +#define JUMP_BACKWARD_NO_INTERRUPT 78 +#define JUMP_FORWARD 79 +#define LIST_APPEND 80 +#define LIST_EXTEND 81 +#define LOAD_ATTR 82 +#define LOAD_CONST 83 +#define LOAD_DEREF 84 +#define LOAD_FAST 85 +#define LOAD_FAST_AND_CLEAR 86 +#define LOAD_FAST_CHECK 87 +#define LOAD_FAST_LOAD_FAST 88 +#define LOAD_FROM_DICT_OR_DEREF 89 +#define LOAD_FROM_DICT_OR_GLOBALS 90 +#define LOAD_GLOBAL 91 +#define LOAD_NAME 92 +#define LOAD_SUPER_ATTR 93 +#define MAKE_CELL 94 +#define MAP_ADD 95 +#define MATCH_CLASS 96 +#define POP_JUMP_IF_FALSE 97 +#define POP_JUMP_IF_NONE 98 +#define POP_JUMP_IF_NOT_NONE 99 +#define POP_JUMP_IF_TRUE 100 +#define RAISE_VARARGS 101 +#define RERAISE 102 +#define RETURN_CONST 103 +#define SEND 104 +#define SET_ADD 105 +#define SET_FUNCTION_ATTRIBUTE 106 +#define SET_UPDATE 107 +#define STORE_ATTR 108 +#define STORE_DEREF 109 +#define STORE_FAST 110 +#define STORE_FAST_LOAD_FAST 111 +#define STORE_FAST_STORE_FAST 112 +#define STORE_GLOBAL 113 +#define STORE_NAME 114 +#define SWAP 115 +#define UNPACK_EX 116 +#define UNPACK_SEQUENCE 117 +#define YIELD_VALUE 118 +#define RESUME 149 +#define BINARY_OP_ADD_FLOAT 150 +#define BINARY_OP_ADD_INT 151 +#define BINARY_OP_ADD_UNICODE 152 +#define BINARY_OP_MULTIPLY_FLOAT 153 +#define BINARY_OP_MULTIPLY_INT 154 +#define BINARY_OP_SUBTRACT_FLOAT 155 +#define BINARY_OP_SUBTRACT_INT 156 +#define BINARY_SUBSCR_DICT 157 +#define BINARY_SUBSCR_GETITEM 158 +#define BINARY_SUBSCR_LIST_INT 159 +#define BINARY_SUBSCR_STR_INT 160 +#define BINARY_SUBSCR_TUPLE_INT 161 +#define CALL_ALLOC_AND_ENTER_INIT 162 +#define CALL_BOUND_METHOD_EXACT_ARGS 163 +#define CALL_BUILTIN_CLASS 164 +#define CALL_BUILTIN_FAST 165 +#define CALL_BUILTIN_FAST_WITH_KEYWORDS 166 +#define CALL_BUILTIN_O 167 +#define CALL_ISINSTANCE 168 +#define CALL_LEN 169 +#define CALL_LIST_APPEND 170 +#define CALL_METHOD_DESCRIPTOR_FAST 171 +#define CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS 172 +#define CALL_METHOD_DESCRIPTOR_NOARGS 173 +#define CALL_METHOD_DESCRIPTOR_O 174 +#define CALL_PY_EXACT_ARGS 175 +#define CALL_PY_WITH_DEFAULTS 176 +#define CALL_STR_1 177 +#define CALL_TUPLE_1 178 +#define CALL_TYPE_1 179 +#define COMPARE_OP_FLOAT 180 +#define COMPARE_OP_INT 181 +#define COMPARE_OP_STR 182 +#define FOR_ITER_GEN 183 +#define FOR_ITER_LIST 184 +#define FOR_ITER_RANGE 185 +#define FOR_ITER_TUPLE 186 +#define LOAD_ATTR_CLASS 187 +#define LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN 188 +#define LOAD_ATTR_INSTANCE_VALUE 189 +#define LOAD_ATTR_METHOD_LAZY_DICT 190 +#define LOAD_ATTR_METHOD_NO_DICT 191 +#define LOAD_ATTR_METHOD_WITH_VALUES 192 +#define LOAD_ATTR_MODULE 193 +#define LOAD_ATTR_NONDESCRIPTOR_NO_DICT 194 +#define LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES 195 +#define LOAD_ATTR_PROPERTY 196 +#define LOAD_ATTR_SLOT 197 +#define LOAD_ATTR_WITH_HINT 198 +#define LOAD_GLOBAL_BUILTIN 199 +#define LOAD_GLOBAL_MODULE 200 +#define LOAD_SUPER_ATTR_ATTR 201 +#define LOAD_SUPER_ATTR_METHOD 202 +#define RESUME_CHECK 203 +#define SEND_GEN 204 +#define STORE_ATTR_INSTANCE_VALUE 205 +#define STORE_ATTR_SLOT 206 +#define STORE_ATTR_WITH_HINT 207 +#define STORE_SUBSCR_DICT 208 +#define STORE_SUBSCR_LIST_INT 209 +#define TO_BOOL_ALWAYS_TRUE 210 +#define TO_BOOL_BOOL 211 +#define TO_BOOL_INT 212 +#define TO_BOOL_LIST 213 +#define TO_BOOL_NONE 214 +#define TO_BOOL_STR 215 +#define UNPACK_SEQUENCE_LIST 216 +#define UNPACK_SEQUENCE_TUPLE 217 +#define UNPACK_SEQUENCE_TWO_TUPLE 218 +#define INSTRUMENTED_RESUME 236 +#define INSTRUMENTED_END_FOR 237 +#define INSTRUMENTED_END_SEND 238 +#define INSTRUMENTED_RETURN_VALUE 239 +#define INSTRUMENTED_RETURN_CONST 240 +#define INSTRUMENTED_YIELD_VALUE 241 +#define INSTRUMENTED_LOAD_SUPER_ATTR 242 +#define INSTRUMENTED_FOR_ITER 243 +#define INSTRUMENTED_CALL 244 +#define INSTRUMENTED_CALL_KW 245 +#define INSTRUMENTED_CALL_FUNCTION_EX 246 +#define INSTRUMENTED_INSTRUCTION 247 +#define INSTRUMENTED_JUMP_FORWARD 248 +#define INSTRUMENTED_JUMP_BACKWARD 249 +#define INSTRUMENTED_POP_JUMP_IF_TRUE 250 +#define INSTRUMENTED_POP_JUMP_IF_FALSE 251 +#define INSTRUMENTED_POP_JUMP_IF_NONE 252 +#define INSTRUMENTED_POP_JUMP_IF_NOT_NONE 253 +#define INSTRUMENTED_LINE 254 +#define JUMP 256 +#define JUMP_NO_INTERRUPT 257 +#define LOAD_CLOSURE 258 +#define LOAD_METHOD 259 +#define LOAD_SUPER_METHOD 260 +#define LOAD_ZERO_SUPER_ATTR 261 +#define LOAD_ZERO_SUPER_METHOD 262 +#define POP_BLOCK 263 +#define SETUP_CLEANUP 264 +#define SETUP_FINALLY 265 +#define SETUP_WITH 266 +#define STORE_FAST_MAYBE_NULL 267 + +#define HAVE_ARGUMENT 44 +#define MIN_INSTRUMENTED_OPCODE 236 + +#ifdef __cplusplus +} +#endif +#endif /* !Py_OPCODE_IDS_H */ diff --git a/Include/osdefs.h b/Include/osdefs.h index 3243944a1483e9..2599e87a9d7c4b 100644 --- a/Include/osdefs.h +++ b/Include/osdefs.h @@ -1,51 +1,57 @@ +// Operating system dependencies. +// +// Define constants: +// +// - ALTSEP +// - DELIM +// - MAXPATHLEN +// - SEP + #ifndef Py_OSDEFS_H #define Py_OSDEFS_H #ifdef __cplusplus extern "C" { #endif - -/* Operating system dependencies */ - #ifdef MS_WINDOWS -#define SEP L'\\' -#define ALTSEP L'/' -#define MAXPATHLEN 256 -#define DELIM L';' +# define SEP L'\\' +# define ALTSEP L'/' +# define MAXPATHLEN 256 +# define DELIM L';' #endif #ifdef __VXWORKS__ -#define DELIM L';' +# define DELIM L';' #endif /* Filename separator */ #ifndef SEP -#define SEP L'/' +# define SEP L'/' #endif /* Max pathname length */ #ifdef __hpux -#include -#include -#ifndef PATH_MAX -#define PATH_MAX MAXPATHLEN -#endif +# include +# include +# ifndef PATH_MAX +# define PATH_MAX MAXPATHLEN +# endif #endif #ifndef MAXPATHLEN -#if defined(PATH_MAX) && PATH_MAX > 1024 -#define MAXPATHLEN PATH_MAX -#else -#define MAXPATHLEN 1024 -#endif +# if defined(PATH_MAX) && PATH_MAX > 1024 +# define MAXPATHLEN PATH_MAX +# else +# define MAXPATHLEN 1024 +# endif #endif /* Search path entry delimiter */ #ifndef DELIM -#define DELIM L':' +# define DELIM L':' #endif #ifdef __cplusplus } #endif -#endif /* !Py_OSDEFS_H */ +#endif // !Py_OSDEFS_H diff --git a/Include/patchlevel.h b/Include/patchlevel.h index ae9d36c12d6eaf..fad79ecfda7b28 100644 --- a/Include/patchlevel.h +++ b/Include/patchlevel.h @@ -20,10 +20,10 @@ #define PY_MINOR_VERSION 13 #define PY_MICRO_VERSION 0 #define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_ALPHA -#define PY_RELEASE_SERIAL 0 +#define PY_RELEASE_SERIAL 2 /* Version as a string */ -#define PY_VERSION "3.13.0a0" +#define PY_VERSION "3.13.0a2+" /*--end constants--*/ /* Version as a single 4-byte hex number, e.g. 0x010502B2 == 1.5.2b2. diff --git a/Include/pyatomic.h b/Include/pyatomic.h new file mode 100644 index 00000000000000..2ce2c81cf5251a --- /dev/null +++ b/Include/pyatomic.h @@ -0,0 +1,16 @@ +#ifndef Py_ATOMIC_H +#define Py_ATOMIC_H +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef Py_LIMITED_API +# define Py_CPYTHON_ATOMIC_H +# include "cpython/pyatomic.h" +# undef Py_CPYTHON_ATOMIC_H +#endif + +#ifdef __cplusplus +} +#endif +#endif /* !Py_ATOMIC_H */ diff --git a/Include/pycapsule.h b/Include/pycapsule.h index 929a9a685259fb..666b9f86739670 100644 --- a/Include/pycapsule.h +++ b/Include/pycapsule.h @@ -52,7 +52,6 @@ PyAPI_FUNC(void *) PyCapsule_Import( const char *name, /* UTF-8 encoded string */ int no_block); - #ifdef __cplusplus } #endif diff --git a/Include/pyerrors.h b/Include/pyerrors.h index d089fa71779330..5d0028c116e2d8 100644 --- a/Include/pyerrors.h +++ b/Include/pyerrors.h @@ -1,13 +1,11 @@ +// Error handling definitions + #ifndef Py_ERRORS_H #define Py_ERRORS_H #ifdef __cplusplus extern "C" { #endif -#include // va_list - -/* Error handling definitions */ - PyAPI_FUNC(void) PyErr_SetNone(PyObject *); PyAPI_FUNC(void) PyErr_SetObject(PyObject *, PyObject *); PyAPI_FUNC(void) PyErr_SetString( diff --git a/Include/pyhash.h b/Include/pyhash.h index 6e969f86fa2625..3e23e2758808d7 100644 --- a/Include/pyhash.h +++ b/Include/pyhash.h @@ -4,19 +4,6 @@ extern "C" { #endif -#ifndef Py_LIMITED_API -/* hash function definition */ -typedef struct { - Py_hash_t (*const hash)(const void *, Py_ssize_t); - const char *name; - const int hash_bits; - const int seed_bits; -} PyHash_FuncDef; - -PyAPI_FUNC(PyHash_FuncDef*) PyHash_GetFuncDef(void); -#endif - - /* Cutoff for small string DJBX33A optimization in range [1, cutoff). * * About 50% of the strings in a typical Python application are smaller than @@ -60,6 +47,12 @@ PyAPI_FUNC(PyHash_FuncDef*) PyHash_GetFuncDef(void); # endif /* uint64_t && uint32_t && aligned */ #endif /* Py_HASH_ALGORITHM */ +#ifndef Py_LIMITED_API +# define Py_CPYTHON_HASH_H +# include "cpython/pyhash.h" +# undef Py_CPYTHON_HASH_H +#endif + #ifdef __cplusplus } #endif diff --git a/Include/pylifecycle.h b/Include/pylifecycle.h index 34f32a5000e9d5..c1e2bc5e323358 100644 --- a/Include/pylifecycle.h +++ b/Include/pylifecycle.h @@ -60,6 +60,10 @@ PyAPI_FUNC(PyOS_sighandler_t) PyOS_setsig(int, PyOS_sighandler_t); PyAPI_DATA(const unsigned long) Py_Version; #endif +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x030D0000 +PyAPI_FUNC(int) Py_IsFinalizing(void); +#endif + #ifndef Py_LIMITED_API # define Py_CPYTHON_PYLIFECYCLE_H # include "cpython/pylifecycle.h" diff --git a/Include/pymacconfig.h b/Include/pymacconfig.h index 00459a03b980be..615abe103ca038 100644 --- a/Include/pymacconfig.h +++ b/Include/pymacconfig.h @@ -1,90 +1,91 @@ -#ifndef PYMACCONFIG_H -#define PYMACCONFIG_H - /* - * This file moves some of the autoconf magic to compile-time - * when building on MacOSX. This is needed for building 4-way - * universal binaries and for 64-bit universal binaries because - * the values redefined below aren't configure-time constant but - * only compile-time constant in these scenarios. - */ +// This file moves some of the autoconf magic to compile-time when building on +// macOS. This is needed for building 4-way universal binaries and for 64-bit +// universal binaries because the values redefined below aren't configure-time +// constant but only compile-time constant in these scenarios. -#if defined(__APPLE__) +#ifndef PY_MACCONFIG_H +#define PY_MACCONFIG_H +#ifdef __APPLE__ -# undef SIZEOF_LONG -# undef SIZEOF_PTHREAD_T -# undef SIZEOF_SIZE_T -# undef SIZEOF_TIME_T -# undef SIZEOF_VOID_P -# undef SIZEOF__BOOL -# undef SIZEOF_UINTPTR_T -# undef SIZEOF_PTHREAD_T -# undef WORDS_BIGENDIAN -# undef DOUBLE_IS_ARM_MIXED_ENDIAN_IEEE754 -# undef DOUBLE_IS_BIG_ENDIAN_IEEE754 -# undef DOUBLE_IS_LITTLE_ENDIAN_IEEE754 -# undef HAVE_GCC_ASM_FOR_X87 +#undef ALIGNOF_MAX_ALIGN_T +#undef SIZEOF_LONG +#undef SIZEOF_LONG_DOUBLE +#undef SIZEOF_PTHREAD_T +#undef SIZEOF_SIZE_T +#undef SIZEOF_TIME_T +#undef SIZEOF_VOID_P +#undef SIZEOF__BOOL +#undef SIZEOF_UINTPTR_T +#undef SIZEOF_PTHREAD_T +#undef WORDS_BIGENDIAN +#undef DOUBLE_IS_ARM_MIXED_ENDIAN_IEEE754 +#undef DOUBLE_IS_BIG_ENDIAN_IEEE754 +#undef DOUBLE_IS_LITTLE_ENDIAN_IEEE754 +#undef HAVE_GCC_ASM_FOR_X87 +#undef HAVE_GCC_ASM_FOR_X64 -# undef VA_LIST_IS_ARRAY -# if defined(__LP64__) && defined(__x86_64__) -# define VA_LIST_IS_ARRAY 1 -# endif - -# undef HAVE_LARGEFILE_SUPPORT -# ifndef __LP64__ -# define HAVE_LARGEFILE_SUPPORT 1 -# endif - -# undef SIZEOF_LONG -# ifdef __LP64__ -# define SIZEOF__BOOL 1 -# define SIZEOF__BOOL 1 -# define SIZEOF_LONG 8 -# define SIZEOF_PTHREAD_T 8 -# define SIZEOF_SIZE_T 8 -# define SIZEOF_TIME_T 8 -# define SIZEOF_VOID_P 8 -# define SIZEOF_UINTPTR_T 8 -# define SIZEOF_PTHREAD_T 8 -# else -# ifdef __ppc__ -# define SIZEOF__BOOL 4 -# else -# define SIZEOF__BOOL 1 -# endif -# define SIZEOF_LONG 4 -# define SIZEOF_PTHREAD_T 4 -# define SIZEOF_SIZE_T 4 -# define SIZEOF_TIME_T 4 -# define SIZEOF_VOID_P 4 -# define SIZEOF_UINTPTR_T 4 -# define SIZEOF_PTHREAD_T 4 -# endif +#undef VA_LIST_IS_ARRAY +#if defined(__LP64__) && defined(__x86_64__) +# define VA_LIST_IS_ARRAY 1 +#endif -# if defined(__LP64__) - /* MacOSX 10.4 (the first release to support 64-bit code - * at all) only supports 64-bit in the UNIX layer. - * Therefore suppress the toolbox-glue in 64-bit mode. - */ +#undef HAVE_LARGEFILE_SUPPORT +#ifndef __LP64__ +# define HAVE_LARGEFILE_SUPPORT 1 +#endif - /* In 64-bit mode setpgrp always has no arguments, in 32-bit - * mode that depends on the compilation environment - */ -# undef SETPGRP_HAVE_ARG +#undef SIZEOF_LONG +#ifdef __LP64__ +# define SIZEOF__BOOL 1 +# define SIZEOF__BOOL 1 +# define SIZEOF_LONG 8 +# define SIZEOF_PTHREAD_T 8 +# define SIZEOF_SIZE_T 8 +# define SIZEOF_TIME_T 8 +# define SIZEOF_VOID_P 8 +# define SIZEOF_UINTPTR_T 8 +# define SIZEOF_PTHREAD_T 8 +#else +# ifdef __ppc__ +# define SIZEOF__BOOL 4 +# else +# define SIZEOF__BOOL 1 +# endif +# define SIZEOF_LONG 4 +# define SIZEOF_PTHREAD_T 4 +# define SIZEOF_SIZE_T 4 +# define SIZEOF_TIME_T 4 +# define SIZEOF_VOID_P 4 +# define SIZEOF_UINTPTR_T 4 +# define SIZEOF_PTHREAD_T 4 +#endif -# endif +// macOS 10.4 (the first release to support 64-bit code +// at all) only supports 64-bit in the UNIX layer. +// Therefore suppress the toolbox-glue in 64-bit mode. +// +// In 64-bit mode setpgrp always has no arguments, in 32-bit +// mode that depends on the compilation environment +#if defined(__LP64__) +# undef SETPGRP_HAVE_ARG +#endif #ifdef __BIG_ENDIAN__ -#define WORDS_BIGENDIAN 1 -#define DOUBLE_IS_BIG_ENDIAN_IEEE754 +# define WORDS_BIGENDIAN 1 +# define DOUBLE_IS_BIG_ENDIAN_IEEE754 #else -#define DOUBLE_IS_LITTLE_ENDIAN_IEEE754 -#endif /* __BIG_ENDIAN */ - -#ifdef __i386__ -# define HAVE_GCC_ASM_FOR_X87 +# define DOUBLE_IS_LITTLE_ENDIAN_IEEE754 #endif +#if defined(__i386__) || defined(__x86_64__) +# define HAVE_GCC_ASM_FOR_X87 +# define ALIGNOF_MAX_ALIGN_T 16 +# define HAVE_GCC_ASM_FOR_X64 1 +# define SIZEOF_LONG_DOUBLE 16 +#else +# define ALIGNOF_MAX_ALIGN_T 8 +# define SIZEOF_LONG_DOUBLE 8 +#endif -#endif /* defined(_APPLE__) */ - -#endif /* PYMACCONFIG_H */ +#endif // __APPLE__ +#endif // !PY_MACCONFIG_H diff --git a/Include/pymem.h b/Include/pymem.h index e882645757bfd3..a80da99e1dd7fc 100644 --- a/Include/pymem.h +++ b/Include/pymem.h @@ -1,12 +1,8 @@ -/* The PyMem_ family: low-level memory allocation interfaces. - See objimpl.h for the PyObject_ memory family. -*/ +// The PyMem_ family: low-level memory allocation interfaces. +// See objimpl.h for the PyObject_ memory family. #ifndef Py_PYMEM_H #define Py_PYMEM_H - -#include "pyport.h" - #ifdef __cplusplus extern "C" { #endif @@ -91,6 +87,17 @@ PyAPI_FUNC(void) PyMem_Free(void *ptr); #define PyMem_DEL(p) PyMem_Free((p)) +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x030d0000 +// Memory allocator which doesn't require the GIL to be held. +// Usually, it's just a thin wrapper to functions of the standard C library: +// malloc(), calloc(), realloc() and free(). The difference is that +// tracemalloc can track these memory allocations. +PyAPI_FUNC(void *) PyMem_RawMalloc(size_t size); +PyAPI_FUNC(void *) PyMem_RawCalloc(size_t nelem, size_t elsize); +PyAPI_FUNC(void *) PyMem_RawRealloc(void *ptr, size_t new_size); +PyAPI_FUNC(void) PyMem_RawFree(void *ptr); +#endif + #ifndef Py_LIMITED_API # define Py_CPYTHON_PYMEM_H # include "cpython/pymem.h" @@ -100,5 +107,4 @@ PyAPI_FUNC(void) PyMem_Free(void *ptr); #ifdef __cplusplus } #endif - -#endif /* !Py_PYMEM_H */ +#endif // !Py_PYMEM_H diff --git a/Include/pyport.h b/Include/pyport.h index d7c6ae64f2bf2f..9d7ef0061806ad 100644 --- a/Include/pyport.h +++ b/Include/pyport.h @@ -1,13 +1,8 @@ #ifndef Py_PYPORT_H #define Py_PYPORT_H -#include "pyconfig.h" /* include for defines */ - -#include - -#include #ifndef UCHAR_MAX -# error "limits.h must define UCHAR_MAX" +# error " header must define UCHAR_MAX" #endif #if UCHAR_MAX != 255 # error "Python's source code assumes C's unsigned char is an 8-bit type" @@ -24,9 +19,10 @@ #define _Py_CAST(type, expr) ((type)(expr)) // Static inline functions should use _Py_NULL rather than using directly NULL -// to prevent C++ compiler warnings. On C++11 and newer, _Py_NULL is defined as -// nullptr. -#if defined(__cplusplus) && __cplusplus >= 201103 +// to prevent C++ compiler warnings. On C23 and newer and on C++11 and newer, +// _Py_NULL is defined as nullptr. +#if (defined (__STDC_VERSION__) && __STDC_VERSION__ > 201710L) \ + || (defined(__cplusplus) && __cplusplus >= 201103) # define _Py_NULL nullptr #else # define _Py_NULL NULL @@ -188,68 +184,6 @@ typedef Py_ssize_t Py_ssize_clean_t; # define Py_MEMCPY memcpy #endif -#ifdef HAVE_IEEEFP_H -#include /* needed for 'finite' declaration on some platforms */ -#endif - -#include /* Moved here from the math section, before extern "C" */ - -/******************************************** - * WRAPPER FOR and/or * - ********************************************/ - -#ifdef HAVE_SYS_TIME_H -#include -#endif -#include - -/****************************** - * WRAPPER FOR * - ******************************/ - -/* NB caller must include */ - -#ifdef HAVE_SYS_SELECT_H -#include -#endif /* !HAVE_SYS_SELECT_H */ - -/******************************* - * stat() and fstat() fiddling * - *******************************/ - -#ifdef HAVE_SYS_STAT_H -#include -#elif defined(HAVE_STAT_H) -#include -#endif - -#ifndef S_IFMT -/* VisualAge C/C++ Failed to Define MountType Field in sys/stat.h */ -#define S_IFMT 0170000 -#endif - -#ifndef S_IFLNK -/* Windows doesn't define S_IFLNK but posixmodule.c maps - * IO_REPARSE_TAG_SYMLINK to S_IFLNK */ -# define S_IFLNK 0120000 -#endif - -#ifndef S_ISREG -#define S_ISREG(x) (((x) & S_IFMT) == S_IFREG) -#endif - -#ifndef S_ISDIR -#define S_ISDIR(x) (((x) & S_IFMT) == S_IFDIR) -#endif - -#ifndef S_ISCHR -#define S_ISCHR(x) (((x) & S_IFMT) == S_IFCHR) -#endif - -#ifndef S_ISLNK -#define S_ISLNK(x) (((x) & S_IFMT) == S_IFLNK) -#endif - #ifdef __cplusplus /* Move this down here since some C++ #include's don't like to be included inside an extern "C" */ @@ -421,141 +355,15 @@ extern "C" { # define Py_NO_INLINE #endif -/************************************************************************** -Prototypes that are missing from the standard include files on some systems -(and possibly only some versions of such systems.) - -Please be conservative with adding new ones, document them and enclose them -in platform-specific #ifdefs. -**************************************************************************/ - -#ifdef SOLARIS -/* Unchecked */ -extern int gethostname(char *, int); -#endif - -#ifdef HAVE__GETPTY -#include /* we need to import mode_t */ -extern char * _getpty(int *, int, mode_t, int); -#endif - -/* On QNX 6, struct termio must be declared by including sys/termio.h - if TCGETA, TCSETA, TCSETAW, or TCSETAF are used. sys/termio.h must - be included before termios.h or it will generate an error. */ -#if defined(HAVE_SYS_TERMIO_H) && !defined(__hpux) -#include -#endif - - -/* On 4.4BSD-descendants, ctype functions serves the whole range of - * wchar_t character set rather than single byte code points only. - * This characteristic can break some operations of string object - * including str.upper() and str.split() on UTF-8 locales. This - * workaround was provided by Tim Robbins of FreeBSD project. - */ - -#if defined(__APPLE__) -# define _PY_PORT_CTYPE_UTF8_ISSUE -#endif - -#ifdef _PY_PORT_CTYPE_UTF8_ISSUE -#ifndef __cplusplus - /* The workaround below is unsafe in C++ because - * the defines these symbols as real functions, - * with a slightly different signature. - * See issue #10910 - */ -#include -#include -#undef isalnum -#define isalnum(c) iswalnum(btowc(c)) -#undef isalpha -#define isalpha(c) iswalpha(btowc(c)) -#undef islower -#define islower(c) iswlower(btowc(c)) -#undef isspace -#define isspace(c) iswspace(btowc(c)) -#undef isupper -#define isupper(c) iswupper(btowc(c)) -#undef tolower -#define tolower(c) towlower(btowc(c)) -#undef toupper -#define toupper(c) towupper(btowc(c)) -#endif -#endif - - -/* Declarations for symbol visibility. - - PyAPI_FUNC(type): Declares a public Python API function and return type - PyAPI_DATA(type): Declares public Python data and its type - PyMODINIT_FUNC: A Python module init function. If these functions are - inside the Python core, they are private to the core. - If in an extension module, it may be declared with - external linkage depending on the platform. - - As a number of platforms support/require "__declspec(dllimport/dllexport)", - we support a HAVE_DECLSPEC_DLL macro to save duplication. -*/ - -/* - All windows ports, except cygwin, are handled in PC/pyconfig.h. - - Cygwin is the only other autoconf platform requiring special - linkage handling and it uses __declspec(). -*/ -#if defined(__CYGWIN__) -# define HAVE_DECLSPEC_DLL -#endif - #include "exports.h" -/* only get special linkage if built as shared or platform is Cygwin */ -#if defined(Py_ENABLE_SHARED) || defined(__CYGWIN__) -# if defined(HAVE_DECLSPEC_DLL) -# if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) -# define PyAPI_FUNC(RTYPE) Py_EXPORTED_SYMBOL RTYPE -# define PyAPI_DATA(RTYPE) extern Py_EXPORTED_SYMBOL RTYPE - /* module init functions inside the core need no external linkage */ - /* except for Cygwin to handle embedding */ -# if defined(__CYGWIN__) -# define PyMODINIT_FUNC Py_EXPORTED_SYMBOL PyObject* -# else /* __CYGWIN__ */ -# define PyMODINIT_FUNC PyObject* -# endif /* __CYGWIN__ */ -# else /* Py_BUILD_CORE */ - /* Building an extension module, or an embedded situation */ - /* public Python functions and data are imported */ - /* Under Cygwin, auto-import functions to prevent compilation */ - /* failures similar to those described at the bottom of 4.1: */ - /* http://docs.python.org/extending/windows.html#a-cookbook-approach */ -# if !defined(__CYGWIN__) -# define PyAPI_FUNC(RTYPE) Py_IMPORTED_SYMBOL RTYPE -# endif /* !__CYGWIN__ */ -# define PyAPI_DATA(RTYPE) extern Py_IMPORTED_SYMBOL RTYPE - /* module init functions outside the core must be exported */ -# if defined(__cplusplus) -# define PyMODINIT_FUNC extern "C" Py_EXPORTED_SYMBOL PyObject* -# else /* __cplusplus */ -# define PyMODINIT_FUNC Py_EXPORTED_SYMBOL PyObject* -# endif /* __cplusplus */ -# endif /* Py_BUILD_CORE */ -# endif /* HAVE_DECLSPEC_DLL */ -#endif /* Py_ENABLE_SHARED */ - -/* If no external linkage macros defined by now, create defaults */ -#ifndef PyAPI_FUNC -# define PyAPI_FUNC(RTYPE) Py_EXPORTED_SYMBOL RTYPE -#endif -#ifndef PyAPI_DATA -# define PyAPI_DATA(RTYPE) extern Py_EXPORTED_SYMBOL RTYPE -#endif -#ifndef PyMODINIT_FUNC -# if defined(__cplusplus) -# define PyMODINIT_FUNC extern "C" Py_EXPORTED_SYMBOL PyObject* -# else /* __cplusplus */ -# define PyMODINIT_FUNC Py_EXPORTED_SYMBOL PyObject* -# endif /* __cplusplus */ +#ifdef Py_LIMITED_API + // The internal C API must not be used with the limited C API: make sure + // that Py_BUILD_CORE macro is not defined in this case. These 3 macros are + // used by exports.h, so only undefine them afterwards. +# undef Py_BUILD_CORE +# undef Py_BUILD_CORE_BUILTIN +# undef Py_BUILD_CORE_MODULE #endif /* limits.h constants that may be missing */ @@ -662,6 +470,14 @@ extern char * _getpty(int *, int, mode_t, int); # define WITH_THREAD #endif +/* Some WebAssembly platforms do not provide a working pthread implementation. + * Thread support is stubbed and any attempt to create a new thread fails. + */ +#if (!defined(HAVE_PTHREAD_STUBS) && \ + (!defined(__EMSCRIPTEN__) || defined(__EMSCRIPTEN_PTHREADS__))) +# define Py_CAN_START_THREADS 1 +#endif + #ifdef WITH_THREAD # ifdef Py_BUILD_CORE # ifdef HAVE_THREAD_LOCAL @@ -683,12 +499,6 @@ extern char * _getpty(int *, int, mode_t, int); # endif #endif -/* Check that ALT_SOABI is consistent with Py_TRACE_REFS: - ./configure --with-trace-refs should must be used to define Py_TRACE_REFS */ -#if defined(ALT_SOABI) && defined(Py_TRACE_REFS) -# error "Py_TRACE_REFS ABI is not compatible with release and debug ABI" -#endif - #if defined(__ANDROID__) || defined(__VXWORKS__) // Use UTF-8 as the locale encoding, ignore the LC_CTYPE locale. // See _Py_GetLocaleEncoding(), PyUnicode_DecodeLocale() @@ -753,6 +563,11 @@ extern char * _getpty(int *, int, mode_t, int); # define _Py_ADDRESS_SANITIZER # endif # endif +# if __has_feature(thread_sanitizer) +# if !defined(_Py_THREAD_SANITIZER) +# define _Py_THREAD_SANITIZER +# endif +# endif #elif defined(__GNUC__) # if defined(__SANITIZE_ADDRESS__) # define _Py_ADDRESS_SANITIZER @@ -776,4 +591,16 @@ extern char * _getpty(int *, int, mode_t, int); # define ALIGNOF_MAX_ALIGN_T _Alignof(long double) #endif +#ifndef PY_CXX_CONST +# ifdef __cplusplus +# define PY_CXX_CONST const +# else +# define PY_CXX_CONST +# endif +#endif + +#if defined(__sgi) && !defined(_SGI_MP_SOURCE) +# define _SGI_MP_SOURCE +#endif + #endif /* Py_PYPORT_H */ diff --git a/Include/pystate.h b/Include/pystate.h index e6b4de979c87b8..727b8fbfffe0e6 100644 --- a/Include/pystate.h +++ b/Include/pystate.h @@ -56,7 +56,7 @@ PyAPI_FUNC(void) PyThreadState_Delete(PyThreadState *); The caller must hold the GIL. - See also _PyThreadState_UncheckedGet() and _PyThreadState_GET(). */ + See also PyThreadState_GetUnchecked() and _PyThreadState_GET(). */ PyAPI_FUNC(PyThreadState *) PyThreadState_Get(void); // Alias to PyThreadState_Get() diff --git a/Include/pystats.h b/Include/pystats.h index e24aef5fe8072b..acfa32201711e0 100644 --- a/Include/pystats.h +++ b/Include/pystats.h @@ -1,4 +1,9 @@ - +// Statistics on Python performance (public API). +// +// Define _Py_INCREF_STAT_INC() and _Py_DECREF_STAT_INC() used by Py_INCREF() +// and Py_DECREF(). +// +// See Include/cpython/pystats.h for the full API. #ifndef Py_PYSTATS_H #define Py_PYSTATS_H @@ -6,118 +11,16 @@ extern "C" { #endif -#ifdef Py_STATS - -#define SPECIALIZATION_FAILURE_KINDS 36 - -/* Stats for determining who is calling PyEval_EvalFrame */ -#define EVAL_CALL_TOTAL 0 -#define EVAL_CALL_VECTOR 1 -#define EVAL_CALL_GENERATOR 2 -#define EVAL_CALL_LEGACY 3 -#define EVAL_CALL_FUNCTION_VECTORCALL 4 -#define EVAL_CALL_BUILD_CLASS 5 -#define EVAL_CALL_SLOT 6 -#define EVAL_CALL_FUNCTION_EX 7 -#define EVAL_CALL_API 8 -#define EVAL_CALL_METHOD 9 - -#define EVAL_CALL_KINDS 10 - -typedef struct _specialization_stats { - uint64_t success; - uint64_t failure; - uint64_t hit; - uint64_t deferred; - uint64_t miss; - uint64_t deopt; - uint64_t failure_kinds[SPECIALIZATION_FAILURE_KINDS]; -} SpecializationStats; - -typedef struct _opcode_stats { - SpecializationStats specialization; - uint64_t execution_count; - uint64_t pair_count[256]; -} OpcodeStats; - -typedef struct _call_stats { - uint64_t inlined_py_calls; - uint64_t pyeval_calls; - uint64_t frames_pushed; - uint64_t frame_objects_created; - uint64_t eval_calls[EVAL_CALL_KINDS]; -} CallStats; - -typedef struct _object_stats { - uint64_t increfs; - uint64_t decrefs; - uint64_t interpreter_increfs; - uint64_t interpreter_decrefs; - uint64_t allocations; - uint64_t allocations512; - uint64_t allocations4k; - uint64_t allocations_big; - uint64_t frees; - uint64_t to_freelist; - uint64_t from_freelist; - uint64_t new_values; - uint64_t dict_materialized_on_request; - uint64_t dict_materialized_new_key; - uint64_t dict_materialized_too_big; - uint64_t dict_materialized_str_subclass; - uint64_t type_cache_hits; - uint64_t type_cache_misses; - uint64_t type_cache_dunder_hits; - uint64_t type_cache_dunder_misses; - uint64_t type_cache_collisions; - uint64_t optimization_attempts; - uint64_t optimization_traces_created; - uint64_t optimization_traces_executed; - uint64_t optimization_uops_executed; - /* Temporary value used during GC */ - uint64_t object_visits; -} ObjectStats; - -typedef struct _gc_stats { - uint64_t collections; - uint64_t object_visits; - uint64_t objects_collected; -} GCStats; - -typedef struct _stats { - OpcodeStats opcode_stats[256]; - CallStats call_stats; - ObjectStats object_stats; - GCStats *gc_stats; -} PyStats; - - -PyAPI_DATA(PyStats) _py_stats_struct; -PyAPI_DATA(PyStats *) _py_stats; - -extern void _Py_StatsClear(void); -extern void _Py_PrintSpecializationStats(int to_file); - -#ifdef _PY_INTERPRETER - -#define _Py_INCREF_STAT_INC() do { if (_py_stats) _py_stats->object_stats.interpreter_increfs++; } while (0) -#define _Py_DECREF_STAT_INC() do { if (_py_stats) _py_stats->object_stats.interpreter_decrefs++; } while (0) - +#if defined(Py_STATS) && !defined(Py_LIMITED_API) +# define Py_CPYTHON_PYSTATS_H +# include "cpython/pystats.h" +# undef Py_CPYTHON_PYSTATS_H #else - -#define _Py_INCREF_STAT_INC() do { if (_py_stats) _py_stats->object_stats.increfs++; } while (0) -#define _Py_DECREF_STAT_INC() do { if (_py_stats) _py_stats->object_stats.decrefs++; } while (0) - -#endif - -#else - -#define _Py_INCREF_STAT_INC() ((void)0) -#define _Py_DECREF_STAT_INC() ((void)0) - +# define _Py_INCREF_STAT_INC() ((void)0) +# define _Py_DECREF_STAT_INC() ((void)0) #endif // !Py_STATS #ifdef __cplusplus } #endif -#endif /* !Py_PYSTATs_H */ +#endif // !Py_PYSTATS_H diff --git a/Include/pystrtod.h b/Include/pystrtod.h index fa056d17b6395f..e83d245eb623af 100644 --- a/Include/pystrtod.h +++ b/Include/pystrtod.h @@ -18,15 +18,6 @@ PyAPI_FUNC(char *) PyOS_double_to_string(double val, int flags, int *type); -#ifndef Py_LIMITED_API -PyAPI_FUNC(PyObject *) _Py_string_to_number_with_underscores( - const char *str, Py_ssize_t len, const char *what, PyObject *obj, void *arg, - PyObject *(*innerfunc)(const char *, Py_ssize_t, void *)); - -PyAPI_FUNC(double) _Py_parse_inf_or_nan(const char *p, char **endptr); -#endif - - /* PyOS_double_to_string's "flags" parameter can be set to 0 or more of: */ #define Py_DTSF_SIGN 0x01 /* always add the sign */ #define Py_DTSF_ADD_DOT_0 0x02 /* if the result is an integer add ".0" */ diff --git a/Include/pythread.h b/Include/pythread.h index 63714437c496b7..a3216c51d66165 100644 --- a/Include/pythread.h +++ b/Include/pythread.h @@ -21,7 +21,8 @@ PyAPI_FUNC(void) _Py_NO_RETURN PyThread_exit_thread(void); PyAPI_FUNC(unsigned long) PyThread_get_thread_ident(void); #if (defined(__APPLE__) || defined(__linux__) || defined(_WIN32) \ - || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) \ + || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) \ + || defined(__OpenBSD__) || defined(__NetBSD__) \ || defined(__DragonFly__) || defined(_AIX)) #define PY_HAVE_THREAD_NATIVE_ID PyAPI_FUNC(unsigned long) PyThread_get_thread_native_id(void); @@ -33,42 +34,18 @@ PyAPI_FUNC(int) PyThread_acquire_lock(PyThread_type_lock, int); #define WAIT_LOCK 1 #define NOWAIT_LOCK 0 -/* PY_TIMEOUT_T is the integral type used to specify timeouts when waiting - on a lock (see PyThread_acquire_lock_timed() below). - PY_TIMEOUT_MAX is the highest usable value (in microseconds) of that - type, and depends on the system threading API. - - NOTE: this isn't the same value as `_thread.TIMEOUT_MAX`. The _thread - module exposes a higher-level API, with timeouts expressed in seconds - and floating-point numbers allowed. -*/ +// PY_TIMEOUT_T is the integral type used to specify timeouts when waiting +// on a lock (see PyThread_acquire_lock_timed() below). #define PY_TIMEOUT_T long long -#if defined(_POSIX_THREADS) - /* PyThread_acquire_lock_timed() uses _PyTime_FromNanoseconds(us * 1000), - convert microseconds to nanoseconds. */ -# define PY_TIMEOUT_MAX (LLONG_MAX / 1000) -#elif defined (NT_THREADS) - // WaitForSingleObject() accepts timeout in milliseconds in the range - // [0; 0xFFFFFFFE] (DWORD type). INFINITE value (0xFFFFFFFF) means no - // timeout. 0xFFFFFFFE milliseconds is around 49.7 days. -# if 0xFFFFFFFELL * 1000 < LLONG_MAX -# define PY_TIMEOUT_MAX (0xFFFFFFFELL * 1000) -# else -# define PY_TIMEOUT_MAX LLONG_MAX -# endif -#else -# define PY_TIMEOUT_MAX LLONG_MAX -#endif - /* If microseconds == 0, the call is non-blocking: it returns immediately even when the lock can't be acquired. If microseconds > 0, the call waits up to the specified duration. If microseconds < 0, the call waits until success (or abnormal failure) - microseconds must be less than PY_TIMEOUT_MAX. Behaviour otherwise is - undefined. + If *microseconds* is greater than PY_TIMEOUT_MAX, clamp the timeout to + PY_TIMEOUT_MAX microseconds. If intr_flag is true and the acquire is interrupted by a signal, then the call will return PY_LOCK_INTR. The caller may reattempt to acquire the diff --git a/Include/sysmodule.h b/Include/sysmodule.h index 225e0602d191e1..7b14f72ee2e494 100644 --- a/Include/sysmodule.h +++ b/Include/sysmodule.h @@ -1,6 +1,3 @@ - -/* System module interface */ - #ifndef Py_SYSMODULE_H #define Py_SYSMODULE_H #ifdef __cplusplus @@ -21,17 +18,15 @@ Py_DEPRECATED(3.13) PyAPI_FUNC(void) PySys_ResetWarnOptions(void); PyAPI_FUNC(PyObject *) PySys_GetXOptions(void); -#if !defined(Py_LIMITED_API) -typedef struct { - FILE* perf_map; - PyThread_type_lock map_lock; -} PerfMapState; - -PyAPI_FUNC(int) PyUnstable_PerfMapState_Init(void); - -PyAPI_FUNC(int) PyUnstable_WritePerfMapEntry(const void *code_addr, unsigned int code_size, const char *entry_name); +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x030d0000 +PyAPI_FUNC(int) PySys_Audit( + const char *event, + const char *argFormat, + ...); -PyAPI_FUNC(void) PyUnstable_PerfMapState_Fini(void); +PyAPI_FUNC(int) PySys_AuditTuple( + const char *event, + PyObject *args); #endif #ifndef Py_LIMITED_API diff --git a/Include/unicodeobject.h b/Include/unicodeobject.h index 5839c747a29275..dee00715b3c51d 100644 --- a/Include/unicodeobject.h +++ b/Include/unicodeobject.h @@ -1,8 +1,6 @@ #ifndef Py_UNICODEOBJECT_H #define Py_UNICODEOBJECT_H -#include // va_list - /* Unicode implementation based on original code by Fredrik Lundh, @@ -55,8 +53,6 @@ Copyright (c) Corporation for National Research Initiatives. * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * -------------------------------------------------------------------- */ -#include - /* === Internal API ======================================================= */ /* --- Internal Unicode Format -------------------------------------------- */ @@ -93,10 +89,6 @@ Copyright (c) Corporation for National Research Initiatives. # endif #endif -#ifdef HAVE_WCHAR_H -# include -#endif - /* Py_UCS4 and Py_UCS2 are typedefs for the respective unicode representations. */ typedef uint32_t Py_UCS4; @@ -965,6 +957,15 @@ PyAPI_FUNC(int) PyUnicode_CompareWithASCIIString( const char *right /* ASCII-encoded string */ ); +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x030D0000 +/* Compare a Unicode object with UTF-8 encoded C string. + Return 1 if they are equal, or 0 otherwise. + This function does not raise exceptions. */ + +PyAPI_FUNC(int) PyUnicode_EqualToUTF8(PyObject *, const char *); +PyAPI_FUNC(int) PyUnicode_EqualToUTF8AndSize(PyObject *, const char *, Py_ssize_t); +#endif + /* Rich compare two strings and return one of the following: - NULL in case an exception was raised diff --git a/Lib/_opcode_metadata.py b/Lib/_opcode_metadata.py index fd8ecdb5c980f3..fdb099bd0c2ecf 100644 --- a/Lib/_opcode_metadata.py +++ b/Lib/_opcode_metadata.py @@ -1,9 +1,11 @@ -# This file is generated by Tools/cases_generator/generate_cases.py +# This file is generated by Tools/cases_generator/py_metadata_generator.py # from: # Python/bytecodes.c # Do not edit! - _specializations = { + "RESUME": [ + "RESUME_CHECK", + ], "TO_BOOL": [ "TO_BOOL_ALWAYS_TRUE", "TO_BOOL_BOOL", @@ -20,11 +22,13 @@ "BINARY_OP_ADD_FLOAT", "BINARY_OP_SUBTRACT_FLOAT", "BINARY_OP_ADD_UNICODE", + "BINARY_OP_INPLACE_ADD_UNICODE", ], "BINARY_SUBSCR": [ "BINARY_SUBSCR_DICT", "BINARY_SUBSCR_GETITEM", "BINARY_SUBSCR_LIST_INT", + "BINARY_SUBSCR_STR_INT", "BINARY_SUBSCR_TUPLE_INT", ], "STORE_SUBSCR": [ @@ -81,25 +85,249 @@ "CALL_BOUND_METHOD_EXACT_ARGS", "CALL_PY_EXACT_ARGS", "CALL_PY_WITH_DEFAULTS", - "CALL_NO_KW_TYPE_1", - "CALL_NO_KW_STR_1", - "CALL_NO_KW_TUPLE_1", + "CALL_TYPE_1", + "CALL_STR_1", + "CALL_TUPLE_1", "CALL_BUILTIN_CLASS", - "CALL_NO_KW_BUILTIN_O", - "CALL_NO_KW_BUILTIN_FAST", + "CALL_BUILTIN_O", + "CALL_BUILTIN_FAST", "CALL_BUILTIN_FAST_WITH_KEYWORDS", - "CALL_NO_KW_LEN", - "CALL_NO_KW_ISINSTANCE", - "CALL_NO_KW_LIST_APPEND", - "CALL_NO_KW_METHOD_DESCRIPTOR_O", + "CALL_LEN", + "CALL_ISINSTANCE", + "CALL_LIST_APPEND", + "CALL_METHOD_DESCRIPTOR_O", "CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS", - "CALL_NO_KW_METHOD_DESCRIPTOR_NOARGS", - "CALL_NO_KW_METHOD_DESCRIPTOR_FAST", - "CALL_NO_KW_ALLOC_AND_ENTER_INIT", + "CALL_METHOD_DESCRIPTOR_NOARGS", + "CALL_METHOD_DESCRIPTOR_FAST", + "CALL_ALLOC_AND_ENTER_INIT", ], } -# An irregular case: -_specializations["BINARY_OP"].append("BINARY_OP_INPLACE_ADD_UNICODE") +_specialized_opmap = { + 'BINARY_OP_ADD_FLOAT': 150, + 'BINARY_OP_ADD_INT': 151, + 'BINARY_OP_ADD_UNICODE': 152, + 'BINARY_OP_INPLACE_ADD_UNICODE': 3, + 'BINARY_OP_MULTIPLY_FLOAT': 153, + 'BINARY_OP_MULTIPLY_INT': 154, + 'BINARY_OP_SUBTRACT_FLOAT': 155, + 'BINARY_OP_SUBTRACT_INT': 156, + 'BINARY_SUBSCR_DICT': 157, + 'BINARY_SUBSCR_GETITEM': 158, + 'BINARY_SUBSCR_LIST_INT': 159, + 'BINARY_SUBSCR_STR_INT': 160, + 'BINARY_SUBSCR_TUPLE_INT': 161, + 'CALL_ALLOC_AND_ENTER_INIT': 162, + 'CALL_BOUND_METHOD_EXACT_ARGS': 163, + 'CALL_BUILTIN_CLASS': 164, + 'CALL_BUILTIN_FAST': 165, + 'CALL_BUILTIN_FAST_WITH_KEYWORDS': 166, + 'CALL_BUILTIN_O': 167, + 'CALL_ISINSTANCE': 168, + 'CALL_LEN': 169, + 'CALL_LIST_APPEND': 170, + 'CALL_METHOD_DESCRIPTOR_FAST': 171, + 'CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS': 172, + 'CALL_METHOD_DESCRIPTOR_NOARGS': 173, + 'CALL_METHOD_DESCRIPTOR_O': 174, + 'CALL_PY_EXACT_ARGS': 175, + 'CALL_PY_WITH_DEFAULTS': 176, + 'CALL_STR_1': 177, + 'CALL_TUPLE_1': 178, + 'CALL_TYPE_1': 179, + 'COMPARE_OP_FLOAT': 180, + 'COMPARE_OP_INT': 181, + 'COMPARE_OP_STR': 182, + 'FOR_ITER_GEN': 183, + 'FOR_ITER_LIST': 184, + 'FOR_ITER_RANGE': 185, + 'FOR_ITER_TUPLE': 186, + 'LOAD_ATTR_CLASS': 187, + 'LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN': 188, + 'LOAD_ATTR_INSTANCE_VALUE': 189, + 'LOAD_ATTR_METHOD_LAZY_DICT': 190, + 'LOAD_ATTR_METHOD_NO_DICT': 191, + 'LOAD_ATTR_METHOD_WITH_VALUES': 192, + 'LOAD_ATTR_MODULE': 193, + 'LOAD_ATTR_NONDESCRIPTOR_NO_DICT': 194, + 'LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES': 195, + 'LOAD_ATTR_PROPERTY': 196, + 'LOAD_ATTR_SLOT': 197, + 'LOAD_ATTR_WITH_HINT': 198, + 'LOAD_GLOBAL_BUILTIN': 199, + 'LOAD_GLOBAL_MODULE': 200, + 'LOAD_SUPER_ATTR_ATTR': 201, + 'LOAD_SUPER_ATTR_METHOD': 202, + 'RESUME_CHECK': 203, + 'SEND_GEN': 204, + 'STORE_ATTR_INSTANCE_VALUE': 205, + 'STORE_ATTR_SLOT': 206, + 'STORE_ATTR_WITH_HINT': 207, + 'STORE_SUBSCR_DICT': 208, + 'STORE_SUBSCR_LIST_INT': 209, + 'TO_BOOL_ALWAYS_TRUE': 210, + 'TO_BOOL_BOOL': 211, + 'TO_BOOL_INT': 212, + 'TO_BOOL_LIST': 213, + 'TO_BOOL_NONE': 214, + 'TO_BOOL_STR': 215, + 'UNPACK_SEQUENCE_LIST': 216, + 'UNPACK_SEQUENCE_TUPLE': 217, + 'UNPACK_SEQUENCE_TWO_TUPLE': 218, +} + +opmap = { + 'CACHE': 0, + 'RESERVED': 17, + 'RESUME': 149, + 'INSTRUMENTED_LINE': 254, + 'BEFORE_ASYNC_WITH': 1, + 'BEFORE_WITH': 2, + 'BINARY_SLICE': 4, + 'BINARY_SUBSCR': 5, + 'CHECK_EG_MATCH': 6, + 'CHECK_EXC_MATCH': 7, + 'CLEANUP_THROW': 8, + 'DELETE_SUBSCR': 9, + 'END_ASYNC_FOR': 10, + 'END_FOR': 11, + 'END_SEND': 12, + 'EXIT_INIT_CHECK': 13, + 'FORMAT_SIMPLE': 14, + 'FORMAT_WITH_SPEC': 15, + 'GET_AITER': 16, + 'GET_ANEXT': 18, + 'GET_ITER': 19, + 'GET_LEN': 20, + 'GET_YIELD_FROM_ITER': 21, + 'INTERPRETER_EXIT': 22, + 'LOAD_ASSERTION_ERROR': 23, + 'LOAD_BUILD_CLASS': 24, + 'LOAD_LOCALS': 25, + 'MAKE_FUNCTION': 26, + 'MATCH_KEYS': 27, + 'MATCH_MAPPING': 28, + 'MATCH_SEQUENCE': 29, + 'NOP': 30, + 'POP_EXCEPT': 31, + 'POP_TOP': 32, + 'PUSH_EXC_INFO': 33, + 'PUSH_NULL': 34, + 'RETURN_GENERATOR': 35, + 'RETURN_VALUE': 36, + 'SETUP_ANNOTATIONS': 37, + 'STORE_SLICE': 38, + 'STORE_SUBSCR': 39, + 'TO_BOOL': 40, + 'UNARY_INVERT': 41, + 'UNARY_NEGATIVE': 42, + 'UNARY_NOT': 43, + 'WITH_EXCEPT_START': 44, + 'BINARY_OP': 45, + 'BUILD_CONST_KEY_MAP': 46, + 'BUILD_LIST': 47, + 'BUILD_MAP': 48, + 'BUILD_SET': 49, + 'BUILD_SLICE': 50, + 'BUILD_STRING': 51, + 'BUILD_TUPLE': 52, + 'CALL': 53, + 'CALL_FUNCTION_EX': 54, + 'CALL_INTRINSIC_1': 55, + 'CALL_INTRINSIC_2': 56, + 'CALL_KW': 57, + 'COMPARE_OP': 58, + 'CONTAINS_OP': 59, + 'CONVERT_VALUE': 60, + 'COPY': 61, + 'COPY_FREE_VARS': 62, + 'DELETE_ATTR': 63, + 'DELETE_DEREF': 64, + 'DELETE_FAST': 65, + 'DELETE_GLOBAL': 66, + 'DELETE_NAME': 67, + 'DICT_MERGE': 68, + 'DICT_UPDATE': 69, + 'ENTER_EXECUTOR': 70, + 'EXTENDED_ARG': 71, + 'FOR_ITER': 72, + 'GET_AWAITABLE': 73, + 'IMPORT_FROM': 74, + 'IMPORT_NAME': 75, + 'IS_OP': 76, + 'JUMP_BACKWARD': 77, + 'JUMP_BACKWARD_NO_INTERRUPT': 78, + 'JUMP_FORWARD': 79, + 'LIST_APPEND': 80, + 'LIST_EXTEND': 81, + 'LOAD_ATTR': 82, + 'LOAD_CONST': 83, + 'LOAD_DEREF': 84, + 'LOAD_FAST': 85, + 'LOAD_FAST_AND_CLEAR': 86, + 'LOAD_FAST_CHECK': 87, + 'LOAD_FAST_LOAD_FAST': 88, + 'LOAD_FROM_DICT_OR_DEREF': 89, + 'LOAD_FROM_DICT_OR_GLOBALS': 90, + 'LOAD_GLOBAL': 91, + 'LOAD_NAME': 92, + 'LOAD_SUPER_ATTR': 93, + 'MAKE_CELL': 94, + 'MAP_ADD': 95, + 'MATCH_CLASS': 96, + 'POP_JUMP_IF_FALSE': 97, + 'POP_JUMP_IF_NONE': 98, + 'POP_JUMP_IF_NOT_NONE': 99, + 'POP_JUMP_IF_TRUE': 100, + 'RAISE_VARARGS': 101, + 'RERAISE': 102, + 'RETURN_CONST': 103, + 'SEND': 104, + 'SET_ADD': 105, + 'SET_FUNCTION_ATTRIBUTE': 106, + 'SET_UPDATE': 107, + 'STORE_ATTR': 108, + 'STORE_DEREF': 109, + 'STORE_FAST': 110, + 'STORE_FAST_LOAD_FAST': 111, + 'STORE_FAST_STORE_FAST': 112, + 'STORE_GLOBAL': 113, + 'STORE_NAME': 114, + 'SWAP': 115, + 'UNPACK_EX': 116, + 'UNPACK_SEQUENCE': 117, + 'YIELD_VALUE': 118, + 'INSTRUMENTED_RESUME': 236, + 'INSTRUMENTED_END_FOR': 237, + 'INSTRUMENTED_END_SEND': 238, + 'INSTRUMENTED_RETURN_VALUE': 239, + 'INSTRUMENTED_RETURN_CONST': 240, + 'INSTRUMENTED_YIELD_VALUE': 241, + 'INSTRUMENTED_LOAD_SUPER_ATTR': 242, + 'INSTRUMENTED_FOR_ITER': 243, + 'INSTRUMENTED_CALL': 244, + 'INSTRUMENTED_CALL_KW': 245, + 'INSTRUMENTED_CALL_FUNCTION_EX': 246, + 'INSTRUMENTED_INSTRUCTION': 247, + 'INSTRUMENTED_JUMP_FORWARD': 248, + 'INSTRUMENTED_JUMP_BACKWARD': 249, + 'INSTRUMENTED_POP_JUMP_IF_TRUE': 250, + 'INSTRUMENTED_POP_JUMP_IF_FALSE': 251, + 'INSTRUMENTED_POP_JUMP_IF_NONE': 252, + 'INSTRUMENTED_POP_JUMP_IF_NOT_NONE': 253, + 'JUMP': 256, + 'JUMP_NO_INTERRUPT': 257, + 'LOAD_CLOSURE': 258, + 'LOAD_METHOD': 259, + 'LOAD_SUPER_METHOD': 260, + 'LOAD_ZERO_SUPER_ATTR': 261, + 'LOAD_ZERO_SUPER_METHOD': 262, + 'POP_BLOCK': 263, + 'SETUP_CLEANUP': 264, + 'SETUP_FINALLY': 265, + 'SETUP_WITH': 266, + 'STORE_FAST_MAYBE_NULL': 267, +} -_specialized_instructions = [opcode for family in _specializations.values() for opcode in family] +HAVE_ARGUMENT = 44 +MIN_INSTRUMENTED_OPCODE = 236 diff --git a/Lib/_osx_support.py b/Lib/_osx_support.py index aa66c8b9f4189f..0cb064fcd791be 100644 --- a/Lib/_osx_support.py +++ b/Lib/_osx_support.py @@ -507,6 +507,11 @@ def get_platform_osx(_config_vars, osname, release, machine): # MACOSX_DEPLOYMENT_TARGET. macver = _config_vars.get('MACOSX_DEPLOYMENT_TARGET', '') + if macver and '.' not in macver: + # Ensure that the version includes at least a major + # and minor version, even if MACOSX_DEPLOYMENT_TARGET + # is set to a single-label version like "14". + macver += '.0' macrelease = _get_system_version() or macver macver = macver or macrelease diff --git a/Lib/_pydatetime.py b/Lib/_pydatetime.py index f4fc2c58e5e293..bca2acf1fc88cf 100644 --- a/Lib/_pydatetime.py +++ b/Lib/_pydatetime.py @@ -1015,13 +1015,9 @@ def fromisocalendar(cls, year, week, day): def __repr__(self): """Convert to formal string, for repr(). - >>> dt = datetime(2010, 1, 1) - >>> repr(dt) - 'datetime.datetime(2010, 1, 1, 0, 0)' - - >>> dt = datetime(2010, 1, 1, tzinfo=timezone.utc) - >>> repr(dt) - 'datetime.datetime(2010, 1, 1, 0, 0, tzinfo=datetime.timezone.utc)' + >>> d = date(2010, 1, 1) + >>> repr(d) + 'datetime.date(2010, 1, 1)' """ return "%s.%s(%d, %d, %d)" % (_get_class_module(self), self.__class__.__qualname__, @@ -1112,6 +1108,8 @@ def replace(self, year=None, month=None, day=None): day = self._day return type(self)(year, month, day) + __replace__ = replace + # Comparisons of date objects with other. def __eq__(self, other): @@ -1236,7 +1234,7 @@ def __reduce__(self): class tzinfo: """Abstract base class for time zone info classes. - Subclasses must override the name(), utcoffset() and dst() methods. + Subclasses must override the tzname(), utcoffset() and dst() methods. """ __slots__ = () @@ -1637,6 +1635,8 @@ def replace(self, hour=None, minute=None, second=None, microsecond=None, fold = self._fold return type(self)(hour, minute, second, microsecond, tzinfo, fold=fold) + __replace__ = replace + # Pickle support. def _getstate(self, protocol=3): @@ -1684,7 +1684,7 @@ class datetime(date): The year, month and day arguments are required. tzinfo may be None, or an instance of a tzinfo subclass. The remaining arguments may be ints. """ - __slots__ = date.__slots__ + time.__slots__ + __slots__ = time.__slots__ def __new__(cls, year, month=None, day=None, hour=0, minute=0, second=0, microsecond=0, tzinfo=None, *, fold=0): @@ -1812,7 +1812,7 @@ def utcfromtimestamp(cls, t): warnings.warn("datetime.utcfromtimestamp() is deprecated and scheduled " "for removal in a future version. Use timezone-aware " "objects to represent datetimes in UTC: " - "datetime.fromtimestamp(t, datetime.UTC).", + "datetime.datetime.fromtimestamp(t, datetime.UTC).", DeprecationWarning, stacklevel=2) return cls._fromtimestamp(t, True, None) @@ -1830,7 +1830,7 @@ def utcnow(cls): warnings.warn("datetime.utcnow() is deprecated and scheduled for " "removal in a future version. Instead, Use timezone-aware " "objects to represent datetimes in UTC: " - "datetime.now(datetime.UTC).", + "datetime.datetime.now(datetime.UTC).", DeprecationWarning, stacklevel=2) t = _time.time() @@ -1983,6 +1983,8 @@ def replace(self, year=None, month=None, day=None, hour=None, return type(self)(year, month, day, hour, minute, second, microsecond, tzinfo, fold=fold) + __replace__ = replace + def _local_timezone(self): if self.tzinfo is None: ts = self._mktime() diff --git a/Lib/_pyio.py b/Lib/_pyio.py index 32698abac78d25..df2c29bfa9caee 100644 --- a/Lib/_pyio.py +++ b/Lib/_pyio.py @@ -2198,8 +2198,9 @@ def write(self, s): self.buffer.write(b) if self._line_buffering and (haslf or "\r" in s): self.flush() - self._set_decoded_chars('') - self._snapshot = None + if self._snapshot is not None: + self._set_decoded_chars('') + self._snapshot = None if self._decoder: self._decoder.reset() return length @@ -2513,8 +2514,9 @@ def read(self, size=None): # Read everything. result = (self._get_decoded_chars() + decoder.decode(self.buffer.read(), final=True)) - self._set_decoded_chars('') - self._snapshot = None + if self._snapshot is not None: + self._set_decoded_chars('') + self._snapshot = None return result else: # Keep reading chunks until we have size characters to return. diff --git a/Lib/_strptime.py b/Lib/_strptime.py index 77ccdc9e1d789b..798cf9f9d3fffe 100644 --- a/Lib/_strptime.py +++ b/Lib/_strptime.py @@ -342,8 +342,6 @@ def _strptime(data_string, format="%a %b %d %H:%M:%S %Y"): tz = -1 gmtoff = None gmtoff_fraction = 0 - # Default to -1 to signify that values not known; not critical to have, - # though iso_week = week_of_year = None week_of_year_start = None # weekday and julian defaulted to None so as to signal need to calculate @@ -470,17 +468,17 @@ def _strptime(data_string, format="%a %b %d %H:%M:%S %Y"): # Deal with the cases where ambiguities arise # don't assume default values for ISO week/year - if year is None and iso_year is not None: - if iso_week is None or weekday is None: - raise ValueError("ISO year directive '%G' must be used with " - "the ISO week directive '%V' and a weekday " - "directive ('%A', '%a', '%w', or '%u').") + if iso_year is not None: if julian is not None: raise ValueError("Day of the year directive '%j' is not " "compatible with ISO year directive '%G'. " "Use '%Y' instead.") - elif week_of_year is None and iso_week is not None: - if weekday is None: + elif iso_week is None or weekday is None: + raise ValueError("ISO year directive '%G' must be used with " + "the ISO week directive '%V' and a weekday " + "directive ('%A', '%a', '%w', or '%u').") + elif iso_week is not None: + if year is None or weekday is None: raise ValueError("ISO week directive '%V' must be used with " "the ISO year directive '%G' and a weekday " "directive ('%A', '%a', '%w', or '%u').") @@ -490,11 +488,12 @@ def _strptime(data_string, format="%a %b %d %H:%M:%S %Y"): "instead.") leap_year_fix = False - if year is None and month == 2 and day == 29: - year = 1904 # 1904 is first leap year of 20th century - leap_year_fix = True - elif year is None: - year = 1900 + if year is None: + if month == 2 and day == 29: + year = 1904 # 1904 is first leap year of 20th century + leap_year_fix = True + else: + year = 1900 # If we know the week of the year and what day of that week, we can figure # out the Julian day of the year. diff --git a/Lib/argparse.py b/Lib/argparse.py index dfc98695f64e0a..a32884db80d1ea 100644 --- a/Lib/argparse.py +++ b/Lib/argparse.py @@ -89,8 +89,6 @@ import re as _re import sys as _sys -import warnings - from gettext import gettext as _, ngettext SUPPRESS = '==SUPPRESS==' @@ -910,6 +908,7 @@ def __init__(self, # parser.add_argument('-f', action=BooleanOptionalAction, type=int) for field_name in ('type', 'choices', 'metavar'): if locals()[field_name] is not _deprecated_default: + import warnings warnings._deprecated( field_name, "{name!r} is deprecated as of Python 3.12 and will be " @@ -1700,6 +1699,7 @@ def _remove_action(self, action): self._group_actions.remove(action) def add_argument_group(self, *args, **kwargs): + import warnings warnings.warn( "Nesting argument groups is deprecated.", category=DeprecationWarning, @@ -1728,6 +1728,7 @@ def _remove_action(self, action): self._group_actions.remove(action) def add_mutually_exclusive_group(self, *args, **kwargs): + import warnings warnings.warn( "Nesting mutually exclusive groups is deprecated.", category=DeprecationWarning, diff --git a/Lib/ast.py b/Lib/ast.py index a307f3ecd06175..7d3cd489942393 100644 --- a/Lib/ast.py +++ b/Lib/ast.py @@ -32,13 +32,15 @@ def parse(source, filename='', mode='exec', *, - type_comments=False, feature_version=None): + type_comments=False, feature_version=None, optimize=-1): """ Parse the source into an AST node. Equivalent to compile(source, filename, mode, PyCF_ONLY_AST). Pass type_comments=True to get back type comments where the syntax allows. """ flags = PyCF_ONLY_AST + if optimize > 0: + flags |= PyCF_OPTIMIZED_AST if type_comments: flags |= PyCF_TYPE_COMMENTS if feature_version is None: @@ -50,7 +52,7 @@ def parse(source, filename='', mode='exec', *, feature_version = minor # Else it should be an int giving the minor version for 3.x. return compile(source, filename, mode, flags, - _feature_version=feature_version) + _feature_version=feature_version, optimize=optimize) def literal_eval(node_or_string): @@ -1223,17 +1225,7 @@ def _write_str_avoiding_backslashes(self, string, *, quote_types=_ALL_QUOTES): def visit_JoinedStr(self, node): self.write("f") - if self._avoid_backslashes: - with self.buffered() as buffer: - self._write_fstring_inner(node) - return self._write_str_avoiding_backslashes("".join(buffer)) - - # If we don't need to avoid backslashes globally (i.e., we only need - # to avoid them inside FormattedValues), it's cosmetically preferred - # to use escaped whitespace. That is, it's preferred to use backslashes - # for cases like: f"{x}\n". To accomplish this, we keep track of what - # in our buffer corresponds to FormattedValues and what corresponds to - # Constant parts of the f-string, and allow escapes accordingly. + fstring_parts = [] for value in node.values: with self.buffered() as buffer: @@ -1244,25 +1236,49 @@ def visit_JoinedStr(self, node): new_fstring_parts = [] quote_types = list(_ALL_QUOTES) + fallback_to_repr = False for value, is_constant in fstring_parts: - value, quote_types = self._str_literal_helper( - value, - quote_types=quote_types, - escape_special_whitespace=is_constant, - ) + if is_constant: + value, new_quote_types = self._str_literal_helper( + value, + quote_types=quote_types, + escape_special_whitespace=True, + ) + if set(new_quote_types).isdisjoint(quote_types): + fallback_to_repr = True + break + quote_types = new_quote_types + elif "\n" in value: + quote_types = [q for q in quote_types if q in _MULTI_QUOTES] + assert quote_types new_fstring_parts.append(value) + if fallback_to_repr: + # If we weren't able to find a quote type that works for all parts + # of the JoinedStr, fallback to using repr and triple single quotes. + quote_types = ["'''"] + new_fstring_parts.clear() + for value, is_constant in fstring_parts: + if is_constant: + value = repr('"' + value) # force repr to use single quotes + expected_prefix = "'\"" + assert value.startswith(expected_prefix), repr(value) + value = value[len(expected_prefix):-1] + new_fstring_parts.append(value) + value = "".join(new_fstring_parts) quote_type = quote_types[0] self.write(f"{quote_type}{value}{quote_type}") - def _write_fstring_inner(self, node): + def _write_fstring_inner(self, node, scape_newlines=False): if isinstance(node, JoinedStr): # for both the f-string itself, and format_spec for value in node.values: - self._write_fstring_inner(value) + self._write_fstring_inner(value, scape_newlines=scape_newlines) elif isinstance(node, Constant) and isinstance(node.value, str): value = node.value.replace("{", "{{").replace("}", "}}") + if scape_newlines: + value = value.replace("\n", "\\n") self.write(value) elif isinstance(node, FormattedValue): self.visit_FormattedValue(node) @@ -1271,16 +1287,12 @@ def _write_fstring_inner(self, node): def visit_FormattedValue(self, node): def unparse_inner(inner): - unparser = type(self)(_avoid_backslashes=True) + unparser = type(self)() unparser.set_precedence(_Precedence.TEST.next(), inner) return unparser.visit(inner) with self.delimit("{", "}"): expr = unparse_inner(node.value) - if "\\" in expr: - raise ValueError( - "Unable to avoid backslash in f-string expression part" - ) if expr.startswith("{"): # Separate pair of opening brackets as "{ {" self.write(" ") @@ -1289,7 +1301,10 @@ def unparse_inner(inner): self.write(f"!{chr(node.conversion)}") if node.format_spec: self.write(":") - self._write_fstring_inner(node.format_spec) + self._write_fstring_inner( + node.format_spec, + scape_newlines=True + ) def visit_Name(self, node): self.write(node.id) @@ -1797,8 +1812,7 @@ def main(): import argparse parser = argparse.ArgumentParser(prog='python -m ast') - parser.add_argument('infile', type=argparse.FileType(mode='rb'), nargs='?', - default='-', + parser.add_argument('infile', nargs='?', default='-', help='the file to parse; defaults to stdin') parser.add_argument('-m', '--mode', default='exec', choices=('exec', 'single', 'eval', 'func_type'), @@ -1812,9 +1826,14 @@ def main(): help='indentation of nodes (number of spaces)') args = parser.parse_args() - with args.infile as infile: - source = infile.read() - tree = parse(source, args.infile.name, args.mode, type_comments=args.no_type_comments) + if args.infile == '-': + name = '' + source = sys.stdin.buffer.read() + else: + name = args.infile + with open(args.infile, 'rb') as infile: + source = infile.read() + tree = parse(source, name, args.mode, type_comments=args.no_type_comments) print(dump(tree, include_attributes=args.include_attributes, indent=args.indent)) if __name__ == '__main__': diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py index b092c9343634e2..a8870b636d1df5 100644 --- a/Lib/asyncio/base_events.py +++ b/Lib/asyncio/base_events.py @@ -305,7 +305,7 @@ def _wakeup(self): self._waiters = None for waiter in waiters: if not waiter.done(): - waiter.set_result(waiter) + waiter.set_result(None) def _start_serving(self): if self._serving: @@ -377,7 +377,27 @@ async def serve_forever(self): self._serving_forever_fut = None async def wait_closed(self): - if self._waiters is None or self._active_count == 0: + """Wait until server is closed and all connections are dropped. + + - If the server is not closed, wait. + - If it is closed, but there are still active connections, wait. + + Anyone waiting here will be unblocked once both conditions + (server is closed and all connections have been dropped) + have become true, in either order. + + Historical note: In 3.11 and before, this was broken, returning + immediately if the server was already closed, even if there + were still active connections. An attempted fix in 3.12.0 was + still broken, returning immediately if the server was still + open and there were no active connections. Hopefully in 3.12.1 + we have it right. + """ + # Waiters are unblocked by self._wakeup(), which is called + # from two places: self.close() and self._detach(), but only + # when both conditions have become true. To signal that this + # has happened, self._wakeup() sets self._waiters to None. + if self._waiters is None: return waiter = self._loop.create_future() self._waiters.append(waiter) @@ -400,6 +420,8 @@ def __init__(self): self._clock_resolution = time.get_clock_info('monotonic').resolution self._exception_handler = None self.set_debug(coroutines._is_debug_mode()) + # The preserved state of async generator hooks. + self._old_agen_hooks = None # In debug mode, if the execution of a callback or a step of a task # exceed this duration in seconds, the slow callback/task is logged. self.slow_callback_duration = 0.1 @@ -601,29 +623,52 @@ def _check_running(self): raise RuntimeError( 'Cannot run the event loop while another loop is running') - def run_forever(self): - """Run until stop() is called.""" + def _run_forever_setup(self): + """Prepare the run loop to process events. + + This method exists so that custom custom event loop subclasses (e.g., event loops + that integrate a GUI event loop with Python's event loop) have access to all the + loop setup logic. + """ self._check_closed() self._check_running() self._set_coroutine_origin_tracking(self._debug) - old_agen_hooks = sys.get_asyncgen_hooks() - try: - self._thread_id = threading.get_ident() - sys.set_asyncgen_hooks(firstiter=self._asyncgen_firstiter_hook, - finalizer=self._asyncgen_finalizer_hook) + self._old_agen_hooks = sys.get_asyncgen_hooks() + self._thread_id = threading.get_ident() + sys.set_asyncgen_hooks( + firstiter=self._asyncgen_firstiter_hook, + finalizer=self._asyncgen_finalizer_hook + ) - events._set_running_loop(self) + events._set_running_loop(self) + + def _run_forever_cleanup(self): + """Clean up after an event loop finishes the looping over events. + + This method exists so that custom custom event loop subclasses (e.g., event loops + that integrate a GUI event loop with Python's event loop) have access to all the + loop cleanup logic. + """ + self._stopping = False + self._thread_id = None + events._set_running_loop(None) + self._set_coroutine_origin_tracking(False) + # Restore any pre-existing async generator hooks. + if self._old_agen_hooks is not None: + sys.set_asyncgen_hooks(*self._old_agen_hooks) + self._old_agen_hooks = None + + def run_forever(self): + """Run until stop() is called.""" + try: + self._run_forever_setup() while True: self._run_once() if self._stopping: break finally: - self._stopping = False - self._thread_id = None - events._set_running_loop(None) - self._set_coroutine_origin_tracking(False) - sys.set_asyncgen_hooks(*old_agen_hooks) + self._run_forever_cleanup() def run_until_complete(self, future): """Run until the Future is done. @@ -1451,6 +1496,7 @@ async def create_server( ssl=None, reuse_address=None, reuse_port=None, + keep_alive=None, ssl_handshake_timeout=None, ssl_shutdown_timeout=None, start_serving=True): @@ -1524,6 +1570,9 @@ async def create_server( socket.SOL_SOCKET, socket.SO_REUSEADDR, True) if reuse_port: _set_reuseport(sock) + if keep_alive: + sock.setsockopt( + socket.SOL_SOCKET, socket.SO_KEEPALIVE, True) # Disable IPv4/IPv6 dual stack support (enabled by # default on Linux) which makes a single socket # listen on both address families. @@ -1907,8 +1956,11 @@ def _run_once(self): timeout = 0 elif self._scheduled: # Compute the desired timeout. - when = self._scheduled[0]._when - timeout = min(max(0, when - self.time()), MAXIMUM_SELECT_TIMEOUT) + timeout = self._scheduled[0]._when - self.time() + if timeout > MAXIMUM_SELECT_TIMEOUT: + timeout = MAXIMUM_SELECT_TIMEOUT + elif timeout < 0: + timeout = 0 event_list = self._selector.select(timeout) self._process_events(event_list) diff --git a/Lib/asyncio/base_subprocess.py b/Lib/asyncio/base_subprocess.py index 4c9b0dd5653c0c..6dbde2b696ad1f 100644 --- a/Lib/asyncio/base_subprocess.py +++ b/Lib/asyncio/base_subprocess.py @@ -115,7 +115,8 @@ def close(self): try: self._proc.kill() - except ProcessLookupError: + except (ProcessLookupError, PermissionError): + # the process may have already exited or may be running setuid pass # Don't clear the _proc reference yet: _post_init() may still run diff --git a/Lib/asyncio/events.py b/Lib/asyncio/events.py index 0ccf85105e6673..ebc3836bdc0c4d 100644 --- a/Lib/asyncio/events.py +++ b/Lib/asyncio/events.py @@ -316,6 +316,7 @@ async def create_server( *, family=socket.AF_UNSPEC, flags=socket.AI_PASSIVE, sock=None, backlog=100, ssl=None, reuse_address=None, reuse_port=None, + keep_alive=None, ssl_handshake_timeout=None, ssl_shutdown_timeout=None, start_serving=True): @@ -354,6 +355,9 @@ async def create_server( they all set this flag when being created. This option is not supported on Windows. + keep_alive set to True keeps connections active by enabling the + periodic transmission of messages. + ssl_handshake_timeout is the time in seconds that an SSL server will wait for completion of the SSL handshake before aborting the connection. Default is 60s. diff --git a/Lib/asyncio/futures.py b/Lib/asyncio/futures.py index 97fc4e3fcb60ee..5d35321db7943b 100644 --- a/Lib/asyncio/futures.py +++ b/Lib/asyncio/futures.py @@ -138,9 +138,6 @@ def _make_cancelled_error(self): exc = exceptions.CancelledError() else: exc = exceptions.CancelledError(self._cancel_message) - exc.__context__ = self._cancelled_exc - # Remove the reference since we don't need this anymore. - self._cancelled_exc = None return exc def cancel(self, msg=None): @@ -272,9 +269,13 @@ def set_exception(self, exception): raise exceptions.InvalidStateError(f'{self._state}: {self!r}') if isinstance(exception, type): exception = exception() - if type(exception) is StopIteration: - raise TypeError("StopIteration interacts badly with generators " - "and cannot be raised into a Future") + if isinstance(exception, StopIteration): + new_exc = RuntimeError("StopIteration interacts badly with " + "generators and cannot be raised into a " + "Future") + new_exc.__cause__ = exception + new_exc.__context__ = exception + exception = new_exc self._exception = exception self._exception_tb = exception.__traceback__ self._state = _FINISHED diff --git a/Lib/asyncio/locks.py b/Lib/asyncio/locks.py index ce5d8d5bfb2e81..04158e667a895f 100644 --- a/Lib/asyncio/locks.py +++ b/Lib/asyncio/locks.py @@ -95,6 +95,8 @@ async def acquire(self): This method blocks until the lock is unlocked, then sets it to locked and returns True. """ + # Implement fair scheduling, where thread always waits + # its turn. Jumping the queue if all are cancelled is an optimization. if (not self._locked and (self._waiters is None or all(w.cancelled() for w in self._waiters))): self._locked = True @@ -105,19 +107,22 @@ async def acquire(self): fut = self._get_loop().create_future() self._waiters.append(fut) - # Finally block should be called before the CancelledError - # handling as we don't want CancelledError to call - # _wake_up_first() and attempt to wake up itself. try: try: await fut finally: self._waiters.remove(fut) except exceptions.CancelledError: + # Currently the only exception designed be able to occur here. + + # Ensure the lock invariant: If lock is not claimed (or about + # to be claimed by us) and there is a Task in waiters, + # ensure that the Task at the head will run. if not self._locked: self._wake_up_first() raise + # assert self._locked is False self._locked = True return True @@ -139,7 +144,7 @@ def release(self): raise RuntimeError('Lock is not acquired.') def _wake_up_first(self): - """Wake up the first waiter if it isn't done.""" + """Ensure that the first waiter will wake up.""" if not self._waiters: return try: @@ -147,9 +152,7 @@ def _wake_up_first(self): except StopIteration: return - # .done() necessarily means that a waiter will wake up later on and - # either take the lock, or, if it was cancelled and lock wasn't - # taken already, will hit this again and wake up a new waiter. + # .done() means that the waiter is already set to wake up. if not fut.done(): fut.set_result(True) @@ -269,17 +272,22 @@ async def wait(self): self._waiters.remove(fut) finally: - # Must reacquire lock even if wait is cancelled - cancelled = False + # Must re-acquire lock even if wait is cancelled. + # We only catch CancelledError here, since we don't want any + # other (fatal) errors with the future to cause us to spin. + err = None while True: try: await self.acquire() break - except exceptions.CancelledError: - cancelled = True + except exceptions.CancelledError as e: + err = e - if cancelled: - raise exceptions.CancelledError + if err: + try: + raise err # Re-raise most recent exception instance. + finally: + err = None # Break reference cycles. async def wait_for(self, predicate): """Wait until a predicate becomes true. @@ -357,6 +365,7 @@ def __repr__(self): def locked(self): """Returns True if semaphore cannot be acquired immediately.""" + # Due to state, or FIFO rules (must allow others to run first). return self._value == 0 or ( any(not w.cancelled() for w in (self._waiters or ()))) @@ -370,6 +379,7 @@ async def acquire(self): True. """ if not self.locked(): + # Maintain FIFO, wait for others to start even if _value > 0. self._value -= 1 return True @@ -378,22 +388,27 @@ async def acquire(self): fut = self._get_loop().create_future() self._waiters.append(fut) - # Finally block should be called before the CancelledError - # handling as we don't want CancelledError to call - # _wake_up_first() and attempt to wake up itself. try: try: await fut finally: self._waiters.remove(fut) except exceptions.CancelledError: - if not fut.cancelled(): + # Currently the only exception designed be able to occur here. + if fut.done() and not fut.cancelled(): + # Our Future was successfully set to True via _wake_up_next(), + # but we are not about to successfully acquire(). Therefore we + # must undo the bookkeeping already done and attempt to wake + # up someone else. self._value += 1 - self._wake_up_next() raise - if self._value > 0: - self._wake_up_next() + finally: + # New waiters may have arrived but had to wait due to FIFO. + # Wake up as many as are allowed. + while self._value > 0: + if not self._wake_up_next(): + break # There was no-one to wake up. return True def release(self): @@ -408,13 +423,15 @@ def release(self): def _wake_up_next(self): """Wake up the first waiter that isn't done.""" if not self._waiters: - return + return False for fut in self._waiters: if not fut.done(): self._value -= 1 fut.set_result(True) - return + # `fut` is now `done()` and not `cancelled()`. + return True + return False class BoundedSemaphore(Semaphore): diff --git a/Lib/asyncio/selector_events.py b/Lib/asyncio/selector_events.py index d521b4e2e255a9..dcd5e0aa345029 100644 --- a/Lib/asyncio/selector_events.py +++ b/Lib/asyncio/selector_events.py @@ -261,15 +261,11 @@ def _ensure_fd_no_transport(self, fd): except (AttributeError, TypeError, ValueError): # This code matches selectors._fileobj_to_fd function. raise ValueError(f"Invalid file object: {fd!r}") from None - try: - transport = self._transports[fileno] - except KeyError: - pass - else: - if not transport.is_closing(): - raise RuntimeError( - f'File descriptor {fd!r} is used by transport ' - f'{transport!r}') + transport = self._transports.get(fileno) + if transport and not transport.is_closing(): + raise RuntimeError( + f'File descriptor {fd!r} is used by transport ' + f'{transport!r}') def _add_reader(self, fd, callback, *args): self._check_closed() diff --git a/Lib/asyncio/sslproto.py b/Lib/asyncio/sslproto.py index 488e17d8bccd5b..cbb6527d0b28e0 100644 --- a/Lib/asyncio/sslproto.py +++ b/Lib/asyncio/sslproto.py @@ -243,13 +243,12 @@ def abort(self): The protocol's connection_lost() method will (eventually) be called with None as its argument. """ - self._closed = True - if self._ssl_protocol is not None: - self._ssl_protocol._abort() + self._force_close(None) def _force_close(self, exc): self._closed = True - self._ssl_protocol._abort(exc) + if self._ssl_protocol is not None: + self._ssl_protocol._abort(exc) def _test__append_write_backlog(self, data): # for test only @@ -539,7 +538,7 @@ def _start_handshake(self): # start handshake timeout count down self._handshake_timeout_handle = \ self._loop.call_later(self._ssl_handshake_timeout, - lambda: self._check_handshake_timeout()) + self._check_handshake_timeout) self._do_handshake() @@ -614,12 +613,12 @@ def _start_shutdown(self): if self._app_transport is not None: self._app_transport._closed = True if self._state == SSLProtocolState.DO_HANDSHAKE: - self._abort() + self._abort(None) else: self._set_state(SSLProtocolState.FLUSHING) self._shutdown_timeout_handle = self._loop.call_later( self._ssl_shutdown_timeout, - lambda: self._check_shutdown_timeout() + self._check_shutdown_timeout ) self._do_flush() @@ -661,10 +660,10 @@ def _on_shutdown_complete(self, shutdown_exc): else: self._loop.call_soon(self._transport.close) - def _abort(self): + def _abort(self, exc): self._set_state(SSLProtocolState.UNWRAPPED) if self._transport is not None: - self._transport.abort() + self._transport._force_close(exc) # Outgoing flow @@ -758,7 +757,7 @@ def _do_read__buffered(self): else: break else: - self._loop.call_soon(lambda: self._do_read()) + self._loop.call_soon(self._do_read) except SSLAgainErrors: pass if offset > 0: diff --git a/Lib/asyncio/streams.py b/Lib/asyncio/streams.py index b7ad365709b19e..df58b7a799a5ad 100644 --- a/Lib/asyncio/streams.py +++ b/Lib/asyncio/streams.py @@ -67,9 +67,8 @@ async def start_server(client_connected_cb, host=None, port=None, *, positional host and port, with various optional keyword arguments following. The return value is the same as loop.create_server(). - Additional optional keyword arguments are loop (to set the event loop - instance to use) and limit (to set the buffer limit passed to the - StreamReader). + Additional optional keyword argument is limit (to set the buffer + limit passed to the StreamReader). The return value is the same as loop.create_server(), i.e. a Server object which can be used to stop the service. @@ -246,7 +245,22 @@ def connection_made(self, transport): res = self._client_connected_cb(reader, self._stream_writer) if coroutines.iscoroutine(res): + def callback(task): + if task.cancelled(): + transport.close() + return + exc = task.exception() + if exc is not None: + self._loop.call_exception_handler({ + 'message': 'Unhandled exception in client_connected_cb', + 'exception': exc, + 'transport': transport, + }) + transport.close() + self._task = self._loop.create_task(res) + self._task.add_done_callback(callback) + self._strong_reader = None def connection_lost(self, exc): @@ -395,9 +409,11 @@ async def start_tls(self, sslcontext, *, def __del__(self, warnings=warnings): if not self._transport.is_closing(): - self.close() - warnings.warn(f"unclosed {self!r}", ResourceWarning) - + if self._loop.is_closed(): + warnings.warn("loop is closed", ResourceWarning) + else: + self.close() + warnings.warn(f"unclosed {self!r}", ResourceWarning) class StreamReader: diff --git a/Lib/asyncio/subprocess.py b/Lib/asyncio/subprocess.py index c4e5ba2061cffc..043359bbd03f8a 100644 --- a/Lib/asyncio/subprocess.py +++ b/Lib/asyncio/subprocess.py @@ -147,15 +147,17 @@ def kill(self): async def _feed_stdin(self, input): debug = self._loop.get_debug() - if input is not None: - self.stdin.write(input) - if debug: - logger.debug( - '%r communicate: feed stdin (%s bytes)', self, len(input)) try: + if input is not None: + self.stdin.write(input) + if debug: + logger.debug( + '%r communicate: feed stdin (%s bytes)', self, len(input)) + await self.stdin.drain() except (BrokenPipeError, ConnectionResetError) as exc: - # communicate() ignores BrokenPipeError and ConnectionResetError + # communicate() ignores BrokenPipeError and ConnectionResetError. + # write() and drain() can raise these exceptions. if debug: logger.debug('%r communicate: stdin got %r', self, exc) diff --git a/Lib/asyncio/taskgroups.py b/Lib/asyncio/taskgroups.py index 24238c4f5f998d..e1c56d140bef7d 100644 --- a/Lib/asyncio/taskgroups.py +++ b/Lib/asyncio/taskgroups.py @@ -54,16 +54,14 @@ def __repr__(self): async def __aenter__(self): if self._entered: raise RuntimeError( - f"TaskGroup {self!r} has been already entered") - self._entered = True - + f"TaskGroup {self!r} has already been entered") if self._loop is None: self._loop = events.get_running_loop() - self._parent_task = tasks.current_task(self._loop) if self._parent_task is None: raise RuntimeError( f'TaskGroup {self!r} cannot determine the parent task') + self._entered = True return self @@ -75,8 +73,10 @@ async def __aexit__(self, et, exc, tb): self._base_error is None): self._base_error = exc - propagate_cancellation_error = \ - exc if et is exceptions.CancelledError else None + if et is not None and issubclass(et, exceptions.CancelledError): + propagate_cancellation_error = exc + else: + propagate_cancellation_error = None if self._parent_cancel_requested: # If this flag is set we *must* call uncancel(). if self._parent_task.uncancel() == 0: @@ -135,7 +135,7 @@ async def __aexit__(self, et, exc, tb): if propagate_cancellation_error and not self._errors: raise propagate_cancellation_error - if et is not None and et is not exceptions.CancelledError: + if et is not None and not issubclass(et, exceptions.CancelledError): self._errors.append(exc) if self._errors: @@ -160,10 +160,10 @@ def create_task(self, coro, *, name=None, context=None): if self._aborting: raise RuntimeError(f"TaskGroup {self!r} is shutting down") if context is None: - task = self._loop.create_task(coro) + task = self._loop.create_task(coro, name=name) else: - task = self._loop.create_task(coro, context=context) - task.set_name(name) + task = self._loop.create_task(coro, name=name, context=context) + # optimization: Immediately call the done callback if the task is # already done (e.g. if the coro was able to complete eagerly), # and skip scheduling a done callback diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py index 75dd3cb6c2e987..fafee3e738f6aa 100644 --- a/Lib/asyncio/tasks.py +++ b/Lib/asyncio/tasks.py @@ -17,7 +17,6 @@ import itertools import math import types -import warnings import weakref from types import GenericAlias @@ -74,15 +73,25 @@ class Task(futures._PyFuture): # Inherit Python Task implementation """A coroutine wrapped in a Future.""" # An important invariant maintained while a Task not done: + # _fut_waiter is either None or a Future. The Future + # can be either done() or not done(). + # The task can be in any of 3 states: # - # - Either _fut_waiter is None, and _step() is scheduled; - # - or _fut_waiter is some Future, and _step() is *not* scheduled. + # - 1: _fut_waiter is not None and not _fut_waiter.done(): + # __step() is *not* scheduled and the Task is waiting for _fut_waiter. + # - 2: (_fut_waiter is None or _fut_waiter.done()) and __step() is scheduled: + # the Task is waiting for __step() to be executed. + # - 3: _fut_waiter is None and __step() is *not* scheduled: + # the Task is currently executing (in __step()). # - # The only transition from the latter to the former is through - # _wakeup(). When _fut_waiter is not None, one of its callbacks - # must be _wakeup(). - - # If False, don't log a message if the task is destroyed whereas its + # * In state 1, one of the callbacks of __fut_waiter must be __wakeup(). + # * The transition from 1 to 2 happens when _fut_waiter becomes done(), + # as it schedules __wakeup() to be called (which calls __step() so + # we way that __step() is scheduled). + # * It transitions from 2 to 3 when __step() is executed, and it clears + # _fut_waiter to None. + + # If False, don't log a message if the task is destroyed while its # status is still pending _log_destroy_pending = True @@ -395,11 +404,10 @@ def create_task(coro, *, name=None, context=None): loop = events.get_running_loop() if context is None: # Use legacy API if context is not needed - task = loop.create_task(coro) + task = loop.create_task(coro, name=name) else: - task = loop.create_task(coro, context=context) + task = loop.create_task(coro, name=name, context=context) - task.set_name(name) return task @@ -415,8 +423,6 @@ async def wait(fs, *, timeout=None, return_when=ALL_COMPLETED): The fs iterable must not be empty. - Coroutines will be wrapped in Tasks. - Returns two sets of Future: (done, pending). Usage: @@ -935,21 +941,21 @@ def callback(): def create_eager_task_factory(custom_task_constructor): """Create a function suitable for use as a task factory on an event-loop. - Example usage: + Example usage: - loop.set_task_factory( - asyncio.create_eager_task_factory(my_task_constructor)) + loop.set_task_factory( + asyncio.create_eager_task_factory(my_task_constructor)) - Now, tasks created will be started immediately (rather than being first - scheduled to an event loop). The constructor argument can be any callable - that returns a Task-compatible object and has a signature compatible - with `Task.__init__`; it must have the `eager_start` keyword argument. + Now, tasks created will be started immediately (rather than being first + scheduled to an event loop). The constructor argument can be any callable + that returns a Task-compatible object and has a signature compatible + with `Task.__init__`; it must have the `eager_start` keyword argument. - Most applications will use `Task` for `custom_task_constructor` and in + Most applications will use `Task` for `custom_task_constructor` and in this case there's no need to call `create_eager_task_factory()` directly. Instead the global `eager_task_factory` instance can be used. E.g. `loop.set_task_factory(asyncio.eager_task_factory)`. - """ + """ def factory(loop, coro, *, name=None, context=None): return custom_task_constructor( diff --git a/Lib/asyncio/timeouts.py b/Lib/asyncio/timeouts.py index 029c468739bf2d..e6f5100691d362 100644 --- a/Lib/asyncio/timeouts.py +++ b/Lib/asyncio/timeouts.py @@ -49,8 +49,9 @@ def when(self) -> Optional[float]: def reschedule(self, when: Optional[float]) -> None: """Reschedule the timeout.""" - assert self._state is not _State.CREATED if self._state is not _State.ENTERED: + if self._state is _State.CREATED: + raise RuntimeError("Timeout has not been entered") raise RuntimeError( f"Cannot change state of {self._state.value} Timeout", ) @@ -82,11 +83,14 @@ def __repr__(self) -> str: return f"" async def __aenter__(self) -> "Timeout": + if self._state is not _State.CREATED: + raise RuntimeError("Timeout has already been entered") + task = tasks.current_task() + if task is None: + raise RuntimeError("Timeout should be used inside a task") self._state = _State.ENTERED - self._task = tasks.current_task() + self._task = task self._cancelling = self._task.cancelling() - if self._task is None: - raise RuntimeError("Timeout should be used inside a task") self.reschedule(self._when) return self @@ -105,10 +109,16 @@ async def __aexit__( if self._state is _State.EXPIRING: self._state = _State.EXPIRED - if self._task.uncancel() <= self._cancelling and exc_type is exceptions.CancelledError: + if self._task.uncancel() <= self._cancelling and exc_type is not None: # Since there are no new cancel requests, we're # handling this. - raise TimeoutError from exc_val + if issubclass(exc_type, exceptions.CancelledError): + raise TimeoutError from exc_val + elif exc_val is not None: + self._insert_timeout_error(exc_val) + if isinstance(exc_val, ExceptionGroup): + for exc in exc_val.exceptions: + self._insert_timeout_error(exc) elif self._state is _State.ENTERED: self._state = _State.EXITED @@ -121,6 +131,16 @@ def _on_timeout(self) -> None: # drop the reference early self._timeout_handler = None + @staticmethod + def _insert_timeout_error(exc_val: BaseException) -> None: + while exc_val.__context__ is not None: + if isinstance(exc_val.__context__, exceptions.CancelledError): + te = TimeoutError() + te.__context__ = te.__cause__ = exc_val.__context__ + exc_val.__context__ = te + break + exc_val = exc_val.__context__ + def timeout(delay: Optional[float]) -> Timeout: """Timeout async context manager. diff --git a/Lib/asyncio/unix_events.py b/Lib/asyncio/unix_events.py index a2680865ed968f..41ccf1b78fb93b 100644 --- a/Lib/asyncio/unix_events.py +++ b/Lib/asyncio/unix_events.py @@ -32,6 +32,7 @@ 'FastChildWatcher', 'PidfdChildWatcher', 'MultiLoopChildWatcher', 'ThreadedChildWatcher', 'DefaultEventLoopPolicy', + 'EventLoop', ) @@ -63,6 +64,7 @@ class _UnixSelectorEventLoop(selector_events.BaseSelectorEventLoop): def __init__(self, selector=None): super().__init__(selector) self._signal_handlers = {} + self._unix_server_sockets = {} def close(self): super().close() @@ -226,8 +228,7 @@ async def _make_subprocess_transport(self, protocol, args, shell, return transp def _child_watcher_callback(self, pid, returncode, transp): - # Skip one iteration for callbacks to be executed - self.call_soon_threadsafe(self.call_soon, transp._process_exited, returncode) + self.call_soon_threadsafe(transp._process_exited, returncode) async def create_unix_connection( self, protocol_factory, path=None, *, @@ -284,7 +285,7 @@ async def create_unix_server( sock=None, backlog=100, ssl=None, ssl_handshake_timeout=None, ssl_shutdown_timeout=None, - start_serving=True): + start_serving=True, cleanup_socket=True): if isinstance(ssl, bool): raise TypeError('ssl argument must be an SSLContext or None') @@ -340,6 +341,15 @@ async def create_unix_server( raise ValueError( f'A UNIX Domain Stream Socket was expected, got {sock!r}') + if cleanup_socket: + path = sock.getsockname() + # Check for abstract socket. `str` and `bytes` paths are supported. + if path[0] not in (0, '\x00'): + try: + self._unix_server_sockets[sock] = os.stat(path).st_ino + except FileNotFoundError: + pass + sock.setblocking(False) server = base_events.Server(self, [sock], protocol_factory, ssl, backlog, ssl_handshake_timeout, @@ -460,6 +470,27 @@ def cb(fut): self.remove_writer(fd) fut.add_done_callback(cb) + def _stop_serving(self, sock): + # Is this a unix socket that needs cleanup? + if sock in self._unix_server_sockets: + path = sock.getsockname() + else: + path = None + + super()._stop_serving(sock) + + if path is not None: + prev_ino = self._unix_server_sockets[sock] + del self._unix_server_sockets[sock] + try: + if os.stat(path).st_ino == prev_ino: + os.unlink(path) + except FileNotFoundError: + pass + except OSError as err: + logger.error('Unable to clean up listening UNIX socket ' + '%r: %r', path, err) + class _UnixReadPipeTransport(transports.ReadTransport): @@ -1371,14 +1402,7 @@ def is_active(self): return True def close(self): - self._join_threads() - - def _join_threads(self): - """Internal: Join all non-daemon threads""" - threads = [thread for thread in list(self._threads.values()) - if thread.is_alive() and not thread.daemon] - for thread in threads: - thread.join() + pass def __enter__(self): return self @@ -1397,7 +1421,7 @@ def __del__(self, _warn=warnings.warn): def add_child_handler(self, pid, callback, *args): loop = events.get_running_loop() thread = threading.Thread(target=self._do_waitpid, - name=f"waitpid-{next(self._pid_counter)}", + name=f"asyncio-waitpid-{next(self._pid_counter)}", args=(loop, pid, callback, args), daemon=True) self._threads[pid] = thread @@ -1465,8 +1489,6 @@ def _init_watcher(self): self._watcher = PidfdChildWatcher() else: self._watcher = ThreadedChildWatcher() - if threading.current_thread() is threading.main_thread(): - self._watcher.attach_loop(self._local._loop) def set_event_loop(self, loop): """Set the event loop. @@ -1511,3 +1533,4 @@ def set_child_watcher(self, watcher): SelectorEventLoop = _UnixSelectorEventLoop DefaultEventLoopPolicy = _UnixDefaultEventLoopPolicy +EventLoop = SelectorEventLoop diff --git a/Lib/asyncio/windows_events.py b/Lib/asyncio/windows_events.py index c9a5fb841cb134..b62ea75fee3858 100644 --- a/Lib/asyncio/windows_events.py +++ b/Lib/asyncio/windows_events.py @@ -29,7 +29,7 @@ __all__ = ( 'SelectorEventLoop', 'ProactorEventLoop', 'IocpProactor', 'DefaultEventLoopPolicy', 'WindowsSelectorEventLoopPolicy', - 'WindowsProactorEventLoopPolicy', + 'WindowsProactorEventLoopPolicy', 'EventLoop', ) @@ -314,24 +314,25 @@ def __init__(self, proactor=None): proactor = IocpProactor() super().__init__(proactor) - def run_forever(self): - try: - assert self._self_reading_future is None - self.call_soon(self._loop_self_reading) - super().run_forever() - finally: - if self._self_reading_future is not None: - ov = self._self_reading_future._ov - self._self_reading_future.cancel() - # self_reading_future was just cancelled so if it hasn't been - # finished yet, it never will be (it's possible that it has - # already finished and its callback is waiting in the queue, - # where it could still happen if the event loop is restarted). - # Unregister it otherwise IocpProactor.close will wait for it - # forever - if ov is not None: - self._proactor._unregister(ov) - self._self_reading_future = None + def _run_forever_setup(self): + assert self._self_reading_future is None + self.call_soon(self._loop_self_reading) + super()._run_forever_setup() + + def _run_forever_cleanup(self): + super()._run_forever_cleanup() + if self._self_reading_future is not None: + ov = self._self_reading_future._ov + self._self_reading_future.cancel() + # self_reading_future was just cancelled so if it hasn't been + # finished yet, it never will be (it's possible that it has + # already finished and its callback is waiting in the queue, + # where it could still happen if the event loop is restarted). + # Unregister it otherwise IocpProactor.close will wait for it + # forever + if ov is not None: + self._proactor._unregister(ov) + self._self_reading_future = None async def create_pipe_connection(self, protocol_factory, address): f = self._proactor.connect_pipe(address) @@ -894,3 +895,4 @@ class WindowsProactorEventLoopPolicy(events.BaseDefaultEventLoopPolicy): DefaultEventLoopPolicy = WindowsProactorEventLoopPolicy +EventLoop = ProactorEventLoop diff --git a/Lib/base64.py b/Lib/base64.py index e233647ee76639..e3e983b3064fe7 100755 --- a/Lib/base64.py +++ b/Lib/base64.py @@ -164,7 +164,6 @@ def urlsafe_b64decode(s): _b32rev = {} def _b32encode(alphabet, s): - global _b32tab2 # Delay the initialization of the table to not waste memory # if the function is never called if alphabet not in _b32tab2: @@ -200,7 +199,6 @@ def _b32encode(alphabet, s): return bytes(encoded) def _b32decode(alphabet, s, casefold=False, map01=None): - global _b32rev # Delay the initialization of the table to not waste memory # if the function is never called if alphabet not in _b32rev: diff --git a/Lib/bdb.py b/Lib/bdb.py index 0f3eec653baaad..1acf7957f0d669 100644 --- a/Lib/bdb.py +++ b/Lib/bdb.py @@ -32,6 +32,7 @@ def __init__(self, skip=None): self.skip = set(skip) if skip else None self.breaks = {} self.fncache = {} + self.frame_trace_lines = {} self.frame_returning = None self._load_breaks() @@ -331,6 +332,9 @@ def set_trace(self, frame=None): while frame: frame.f_trace = self.trace_dispatch self.botframe = frame + # We need f_trace_liens == True for the debugger to work + self.frame_trace_lines[frame] = frame.f_trace_lines + frame.f_trace_lines = True frame = frame.f_back self.set_step() sys.settrace(self.trace_dispatch) @@ -349,6 +353,9 @@ def set_continue(self): while frame and frame is not self.botframe: del frame.f_trace frame = frame.f_back + for frame, prev_trace_lines in self.frame_trace_lines.items(): + frame.f_trace_lines = prev_trace_lines + self.frame_trace_lines = {} def set_quit(self): """Set quitting attribute to True. diff --git a/Lib/calendar.py b/Lib/calendar.py index e43ba4a078bcac..03469d8ac96bcd 100644 --- a/Lib/calendar.py +++ b/Lib/calendar.py @@ -10,7 +10,6 @@ from enum import IntEnum, global_enum import locale as _locale from itertools import repeat -import warnings __all__ = ["IllegalMonthError", "IllegalWeekdayError", "setfirstweekday", "firstweekday", "isleap", "leapdays", "weekday", "monthrange", @@ -44,6 +43,7 @@ def __str__(self): def __getattr__(name): if name in ('January', 'February'): + import warnings warnings.warn(f"The '{name}' attribute is deprecated, use '{name.upper()}' instead", DeprecationWarning, stacklevel=2) if name == 'January': @@ -721,7 +721,7 @@ def main(args=None): parser.add_argument( "-L", "--locale", default=None, - help="locale to be used from month and weekday names" + help="locale to use for month and weekday names" ) parser.add_argument( "-e", "--encoding", diff --git a/Lib/cmd.py b/Lib/cmd.py index 88ee7d3ddc4694..a37d16cd7bde16 100644 --- a/Lib/cmd.py +++ b/Lib/cmd.py @@ -42,7 +42,7 @@ functions respectively. """ -import string, sys +import inspect, string, sys __all__ = ["Cmd"] @@ -108,7 +108,15 @@ def cmdloop(self, intro=None): import readline self.old_completer = readline.get_completer() readline.set_completer(self.complete) - readline.parse_and_bind(self.completekey+": complete") + if readline.backend == "editline": + if self.completekey == 'tab': + # libedit uses "^I" instead of "tab" + command_string = "bind ^I rl_complete" + else: + command_string = f"bind {self.completekey} rl_complete" + else: + command_string = f"{self.completekey}: complete" + readline.parse_and_bind(command_string) except ImportError: pass try: @@ -210,9 +218,8 @@ def onecmd(self, line): if cmd == '': return self.default(line) else: - try: - func = getattr(self, 'do_' + cmd) - except AttributeError: + func = getattr(self, 'do_' + cmd, None) + if func is None: return self.default(line) return func(arg) @@ -298,6 +305,7 @@ def do_help(self, arg): except AttributeError: try: doc=getattr(self, 'do_' + arg).__doc__ + doc = inspect.cleandoc(doc) if doc: self.stdout.write("%s\n"%str(doc)) return diff --git a/Lib/code.py b/Lib/code.py index 2bd5fa3e795a61..f4aecddeca7813 100644 --- a/Lib/code.py +++ b/Lib/code.py @@ -5,6 +5,7 @@ # Inspired by similar code by Jeff Epler and Fredrik Lundh. +import builtins import sys import traceback from codeop import CommandCompiler, compile_command @@ -169,7 +170,7 @@ class InteractiveConsole(InteractiveInterpreter): """ - def __init__(self, locals=None, filename=""): + def __init__(self, locals=None, filename="", local_exit=False): """Constructor. The optional locals argument will be passed to the @@ -181,6 +182,7 @@ def __init__(self, locals=None, filename=""): """ InteractiveInterpreter.__init__(self, locals) self.filename = filename + self.local_exit = local_exit self.resetbuffer() def resetbuffer(self): @@ -219,27 +221,64 @@ def interact(self, banner=None, exitmsg=None): elif banner: self.write("%s\n" % str(banner)) more = 0 - while 1: - try: - if more: - prompt = sys.ps2 - else: - prompt = sys.ps1 + + # When the user uses exit() or quit() in their interactive shell + # they probably just want to exit the created shell, not the whole + # process. exit and quit in builtins closes sys.stdin which makes + # it super difficult to restore + # + # When self.local_exit is True, we overwrite the builtins so + # exit() and quit() only raises SystemExit and we can catch that + # to only exit the interactive shell + + _exit = None + _quit = None + + if self.local_exit: + if hasattr(builtins, "exit"): + _exit = builtins.exit + builtins.exit = Quitter("exit") + + if hasattr(builtins, "quit"): + _quit = builtins.quit + builtins.quit = Quitter("quit") + + try: + while True: try: - line = self.raw_input(prompt) - except EOFError: - self.write("\n") - break - else: - more = self.push(line) - except KeyboardInterrupt: - self.write("\nKeyboardInterrupt\n") - self.resetbuffer() - more = 0 - if exitmsg is None: - self.write('now exiting %s...\n' % self.__class__.__name__) - elif exitmsg != '': - self.write('%s\n' % exitmsg) + if more: + prompt = sys.ps2 + else: + prompt = sys.ps1 + try: + line = self.raw_input(prompt) + except EOFError: + self.write("\n") + break + else: + more = self.push(line) + except KeyboardInterrupt: + self.write("\nKeyboardInterrupt\n") + self.resetbuffer() + more = 0 + except SystemExit as e: + if self.local_exit: + self.write("\n") + break + else: + raise e + finally: + # restore exit and quit in builtins if they were modified + if _exit is not None: + builtins.exit = _exit + + if _quit is not None: + builtins.quit = _quit + + if exitmsg is None: + self.write('now exiting %s...\n' % self.__class__.__name__) + elif exitmsg != '': + self.write('%s\n' % exitmsg) def push(self, line): """Push a line to the interpreter. @@ -276,8 +315,22 @@ def raw_input(self, prompt=""): return input(prompt) +class Quitter: + def __init__(self, name): + self.name = name + if sys.platform == "win32": + self.eof = 'Ctrl-Z plus Return' + else: + self.eof = 'Ctrl-D (i.e. EOF)' + + def __repr__(self): + return f'Use {self.name} or {self.eof} to exit' + + def __call__(self, code=None): + raise SystemExit(code) + -def interact(banner=None, readfunc=None, local=None, exitmsg=None): +def interact(banner=None, readfunc=None, local=None, exitmsg=None, local_exit=False): """Closely emulate the interactive Python interpreter. This is a backwards compatible interface to the InteractiveConsole @@ -290,9 +343,10 @@ def interact(banner=None, readfunc=None, local=None, exitmsg=None): readfunc -- if not None, replaces InteractiveConsole.raw_input() local -- passed to InteractiveInterpreter.__init__() exitmsg -- passed to InteractiveConsole.interact() + local_exit -- passed to InteractiveConsole.__init__() """ - console = InteractiveConsole(local) + console = InteractiveConsole(local, local_exit=local_exit) if readfunc is not None: console.raw_input = readfunc else: diff --git a/Lib/codecs.py b/Lib/codecs.py index c1c55d8afef389..9b35b6127dd01c 100644 --- a/Lib/codecs.py +++ b/Lib/codecs.py @@ -111,6 +111,9 @@ def __repr__(self): (self.__class__.__module__, self.__class__.__qualname__, self.name, id(self)) + def __getnewargs__(self): + return tuple(self) + class Codec: """ Defines the interface for stateless encoders/decoders. @@ -414,6 +417,9 @@ def __enter__(self): def __exit__(self, type, value, tb): self.stream.close() + def __reduce_ex__(self, proto): + raise TypeError("can't serialize %s" % self.__class__.__name__) + ### class StreamReader(Codec): @@ -663,6 +669,9 @@ def __enter__(self): def __exit__(self, type, value, tb): self.stream.close() + def __reduce_ex__(self, proto): + raise TypeError("can't serialize %s" % self.__class__.__name__) + ### class StreamReaderWriter: @@ -750,6 +759,9 @@ def __enter__(self): def __exit__(self, type, value, tb): self.stream.close() + def __reduce_ex__(self, proto): + raise TypeError("can't serialize %s" % self.__class__.__name__) + ### class StreamRecoder: @@ -866,6 +878,9 @@ def __enter__(self): def __exit__(self, type, value, tb): self.stream.close() + def __reduce_ex__(self, proto): + raise TypeError("can't serialize %s" % self.__class__.__name__) + ### Shortcuts def open(filename, mode='r', encoding=None, errors='strict', buffering=-1): diff --git a/Lib/codeop.py b/Lib/codeop.py index a574aa4b70f1a8..91146be2c438e2 100644 --- a/Lib/codeop.py +++ b/Lib/codeop.py @@ -70,10 +70,14 @@ def _maybe_compile(compiler, source, filename, symbol): return None # fallthrough - return compiler(source, filename, symbol) + return compiler(source, filename, symbol, incomplete_input=False) -def _compile(source, filename, symbol): - return compile(source, filename, symbol, PyCF_DONT_IMPLY_DEDENT | PyCF_ALLOW_INCOMPLETE_INPUT) +def _compile(source, filename, symbol, incomplete_input=True): + flags = 0 + if incomplete_input: + flags |= PyCF_ALLOW_INCOMPLETE_INPUT + flags |= PyCF_DONT_IMPLY_DEDENT + return compile(source, filename, symbol, flags) def compile_command(source, filename="", symbol="single"): r"""Compile a command and determine whether it is incomplete. @@ -104,8 +108,12 @@ class Compile: def __init__(self): self.flags = PyCF_DONT_IMPLY_DEDENT | PyCF_ALLOW_INCOMPLETE_INPUT - def __call__(self, source, filename, symbol): - codeob = compile(source, filename, symbol, self.flags, True) + def __call__(self, source, filename, symbol, **kwargs): + flags = self.flags + if kwargs.get('incomplete_input', True) is False: + flags &= ~PyCF_DONT_IMPLY_DEDENT + flags &= ~PyCF_ALLOW_INCOMPLETE_INPUT + codeob = compile(source, filename, symbol, flags, True) for feature in _features: if codeob.co_flags & feature.compiler_flag: self.flags |= feature.compiler_flag diff --git a/Lib/collections/__init__.py b/Lib/collections/__init__.py index 03ca2d7e18f6f0..2e527dfd810c43 100644 --- a/Lib/collections/__init__.py +++ b/Lib/collections/__init__.py @@ -95,17 +95,19 @@ class OrderedDict(dict): # Individual links are kept alive by the hard reference in self.__map. # Those hard references disappear when a key is deleted from an OrderedDict. + def __new__(cls, /, *args, **kwds): + "Create the ordered dict object and set up the underlying structures." + self = dict.__new__(cls) + self.__hardroot = _Link() + self.__root = root = _proxy(self.__hardroot) + root.prev = root.next = root + self.__map = {} + return self + def __init__(self, other=(), /, **kwds): '''Initialize an ordered dictionary. The signature is the same as regular dictionaries. Keyword argument order is preserved. ''' - try: - self.__root - except AttributeError: - self.__hardroot = _Link() - self.__root = root = _proxy(self.__hardroot) - root.prev = root.next = root - self.__map = {} self.__update(other, **kwds) def __setitem__(self, key, value, @@ -455,7 +457,7 @@ def _make(cls, iterable): def _replace(self, /, **kwds): result = self._make(_map(kwds.pop, field_names, self)) if kwds: - raise ValueError(f'Got unexpected field names: {list(kwds)!r}') + raise TypeError(f'Got unexpected field names: {list(kwds)!r}') return result _replace.__doc__ = (f'Return a new {typename} object replacing specified ' @@ -493,6 +495,7 @@ def __getnewargs__(self): '_field_defaults': field_defaults, '__new__': __new__, '_make': _make, + '__replace__': _replace, '_replace': _replace, '__repr__': __repr__, '_asdict': _asdict, diff --git a/Lib/compileall.py b/Lib/compileall.py index d394156cedc4e7..9b53086bf41380 100644 --- a/Lib/compileall.py +++ b/Lib/compileall.py @@ -172,13 +172,13 @@ def compile_file(fullname, ddir=None, force=False, rx=None, quiet=0, if stripdir is not None: fullname_parts = fullname.split(os.path.sep) stripdir_parts = stripdir.split(os.path.sep) - ddir_parts = list(fullname_parts) - for spart, opart in zip(stripdir_parts, fullname_parts): - if spart == opart: - ddir_parts.remove(spart) - - dfile = os.path.join(*ddir_parts) + if stripdir_parts != fullname_parts[:len(stripdir_parts)]: + if quiet < 2: + print("The stripdir path {!r} is not a valid prefix for " + "source path {!r}; ignoring".format(stripdir, fullname)) + else: + dfile = os.path.join(*fullname_parts[len(stripdir_parts):]) if prependdir is not None: if dfile is None: diff --git a/Lib/concurrent/futures/process.py b/Lib/concurrent/futures/process.py index 301207f59de37a..ffaffdb8b3d0aa 100644 --- a/Lib/concurrent/futures/process.py +++ b/Lib/concurrent/futures/process.py @@ -71,6 +71,11 @@ def __init__(self): self._reader, self._writer = mp.Pipe(duplex=False) def close(self): + # Please note that we do not take the shutdown lock when + # calling clear() (to avoid deadlocking) so this method can + # only be called safely from the same thread as all calls to + # clear() even if you hold the shutdown lock. Otherwise we + # might try to read from the closed pipe. if not self._closed: self._closed = True self._writer.close() @@ -336,7 +341,14 @@ def run(self): # Main loop for the executor manager thread. while True: - self.add_call_item_to_queue() + # gh-109047: During Python finalization, self.call_queue.put() + # creation of a thread can fail with RuntimeError. + try: + self.add_call_item_to_queue() + except BaseException as exc: + cause = format_exception(exc) + self.terminate_broken(cause) + return result_item, is_broken, cause = self.wait_result_broken_or_wakeup() @@ -420,14 +432,18 @@ def wait_result_broken_or_wakeup(self): try: result_item = result_reader.recv() is_broken = False - except BaseException as e: - cause = format_exception(type(e), e, e.__traceback__) + except BaseException as exc: + cause = format_exception(exc) elif wakeup_reader in ready: is_broken = False - with self.shutdown_lock: - self.thread_wakeup.clear() + # No need to hold the _shutdown_lock here because: + # 1. we're the only thread to use the wakeup reader + # 2. we're also the only thread to call thread_wakeup.close() + # 3. we want to avoid a possible deadlock when both reader and writer + # would block (gh-105829) + self.thread_wakeup.clear() return result_item, is_broken, cause @@ -435,24 +451,14 @@ def process_result_item(self, result_item): # Process the received a result_item. This can be either the PID of a # worker that exited gracefully or a _ResultItem - if isinstance(result_item, int): - # Clean shutdown of a worker using its PID - # (avoids marking the executor broken) - assert self.is_shutting_down() - p = self.processes.pop(result_item) - p.join() - if not self.processes: - self.join_executor_internals() - return - else: - # Received a _ResultItem so mark the future as completed. - work_item = self.pending_work_items.pop(result_item.work_id, None) - # work_item can be None if another process terminated (see above) - if work_item is not None: - if result_item.exception: - work_item.future.set_exception(result_item.exception) - else: - work_item.future.set_result(result_item.result) + # Received a _ResultItem so mark the future as completed. + work_item = self.pending_work_items.pop(result_item.work_id, None) + # work_item can be None if another process terminated (see above) + if work_item is not None: + if result_item.exception: + work_item.future.set_exception(result_item.exception) + else: + work_item.future.set_result(result_item.result) def is_shutting_down(self): # Check whether we should start shutting down the executor. @@ -464,7 +470,7 @@ def is_shutting_down(self): return (_global_shutdown or executor is None or executor._shutdown_thread) - def terminate_broken(self, cause): + def _terminate_broken(self, cause): # Terminate the executor because it is in a broken state. The cause # argument can be used to display more information on the error that # lead the executor into becoming broken. @@ -489,7 +495,14 @@ def terminate_broken(self, cause): # Mark pending tasks as failed. for work_id, work_item in self.pending_work_items.items(): - work_item.future.set_exception(bpe) + try: + work_item.future.set_exception(bpe) + except _base.InvalidStateError: + # set_exception() fails if the future is cancelled: ignore it. + # Trying to check if the future is cancelled before calling + # set_exception() would leave a race condition if the future is + # cancelled between the check and set_exception(). + pass # Delete references to object. See issue16284 del work_item self.pending_work_items.clear() @@ -499,12 +512,14 @@ def terminate_broken(self, cause): for p in self.processes.values(): p.terminate() - # Prevent queue writing to a pipe which is no longer read. - # https://github.com/python/cpython/issues/94777 - self.call_queue._reader.close() + self.call_queue._terminate_broken() # clean up resources - self.join_executor_internals() + self._join_executor_internals(broken=True) + + def terminate_broken(self, cause): + with self.shutdown_lock: + self._terminate_broken(cause) def flag_executor_shutting_down(self): # Flag the executor as shutting down and cancel remaining tasks if @@ -547,15 +562,24 @@ def shutdown_workers(self): break def join_executor_internals(self): - self.shutdown_workers() + with self.shutdown_lock: + self._join_executor_internals() + + def _join_executor_internals(self, broken=False): + # If broken, call_queue was closed and so can no longer be used. + if not broken: + self.shutdown_workers() + # Release the queue's resources as soon as possible. self.call_queue.close() self.call_queue.join_thread() - with self.shutdown_lock: - self.thread_wakeup.close() + self.thread_wakeup.close() + # If .join() is not called on the created processes then # some ctx.Queue methods may deadlock on Mac OS X. for p in self.processes.values(): + if broken: + p.terminate() p.join() def get_n_children_alive(self): @@ -642,7 +666,7 @@ def __init__(self, max_workers=None, mp_context=None, _check_system_limits() if max_workers is None: - self._max_workers = os.cpu_count() or 1 + self._max_workers = os.process_cpu_count() or 1 if sys.platform == 'win32': self._max_workers = min(_MAX_WINDOWS_WORKERS, self._max_workers) @@ -706,7 +730,10 @@ def __init__(self, max_workers=None, mp_context=None, # as it could result in a deadlock if a worker process dies with the # _result_queue write lock still acquired. # - # _shutdown_lock must be locked to access _ThreadWakeup. + # _shutdown_lock must be locked to access _ThreadWakeup.close() and + # .wakeup(). Care must also be taken to not call clear or close from + # more than one thread since _ThreadWakeup.clear() is not protected by + # the _shutdown_lock self._executor_manager_thread_wakeup = _ThreadWakeup() # Create communication channels for the executor diff --git a/Lib/concurrent/futures/thread.py b/Lib/concurrent/futures/thread.py index 3b3a36a5093336..a024033f35fb54 100644 --- a/Lib/concurrent/futures/thread.py +++ b/Lib/concurrent/futures/thread.py @@ -139,10 +139,10 @@ def __init__(self, max_workers=None, thread_name_prefix='', # * CPU bound task which releases GIL # * I/O bound task (which releases GIL, of course) # - # We use cpu_count + 4 for both types of tasks. + # We use process_cpu_count + 4 for both types of tasks. # But we limit it to 32 to avoid consuming surprisingly large resource # on many core machine. - max_workers = min(32, (os.cpu_count() or 1) + 4) + max_workers = min(32, (os.process_cpu_count() or 1) + 4) if max_workers <= 0: raise ValueError("max_workers must be greater than 0") diff --git a/Lib/contextlib.py b/Lib/contextlib.py index f82e7bca35735b..5b646fabca0225 100644 --- a/Lib/contextlib.py +++ b/Lib/contextlib.py @@ -149,7 +149,10 @@ def __exit__(self, typ, value, traceback): except StopIteration: return False else: - raise RuntimeError("generator didn't stop") + try: + raise RuntimeError("generator didn't stop") + finally: + self.gen.close() else: if value is None: # Need to force instantiation so we can reliably @@ -191,7 +194,10 @@ def __exit__(self, typ, value, traceback): raise exc.__traceback__ = traceback return False - raise RuntimeError("generator didn't stop after throw()") + try: + raise RuntimeError("generator didn't stop after throw()") + finally: + self.gen.close() class _AsyncGeneratorContextManager( _GeneratorContextManagerBase, @@ -216,7 +222,10 @@ async def __aexit__(self, typ, value, traceback): except StopAsyncIteration: return False else: - raise RuntimeError("generator didn't stop") + try: + raise RuntimeError("generator didn't stop") + finally: + await self.gen.aclose() else: if value is None: # Need to force instantiation so we can reliably @@ -258,7 +267,10 @@ async def __aexit__(self, typ, value, traceback): raise exc.__traceback__ = traceback return False - raise RuntimeError("generator didn't stop after athrow()") + try: + raise RuntimeError("generator didn't stop after athrow()") + finally: + await self.gen.aclose() def contextmanager(func): @@ -449,7 +461,7 @@ def __exit__(self, exctype, excinst, exctb): return if issubclass(exctype, self._exceptions): return True - if issubclass(exctype, ExceptionGroup): + if issubclass(exctype, BaseExceptionGroup): match, rest = excinst.split(self._exceptions) if rest is None: return True diff --git a/Lib/copy.py b/Lib/copy.py index da2908ef623d8c..a69bc4e78c20b3 100644 --- a/Lib/copy.py +++ b/Lib/copy.py @@ -121,13 +121,13 @@ def deepcopy(x, memo=None, _nil=[]): See the module's __doc__ string for more info. """ + d = id(x) if memo is None: memo = {} - - d = id(x) - y = memo.get(d, _nil) - if y is not _nil: - return y + else: + y = memo.get(d, _nil) + if y is not _nil: + return y cls = type(x) @@ -290,3 +290,16 @@ def _reconstruct(x, memo, func, args, return y del types, weakref + + +def replace(obj, /, **changes): + """Return a new object replacing specified fields with new values. + + This is especially useful for immutable objects, like named tuples or + frozen dataclasses. + """ + cls = obj.__class__ + func = getattr(cls, '__replace__', None) + if func is None: + raise TypeError(f"replace() does not support {cls.__name__} objects") + return func(obj, **changes) diff --git a/Lib/dataclasses.py b/Lib/dataclasses.py index 3c72c289e43882..2fba32b5ffbc1e 100644 --- a/Lib/dataclasses.py +++ b/Lib/dataclasses.py @@ -575,15 +575,15 @@ def _init_fn(fields, std_fields, kw_only_fields, frozen, has_post_init, # message, and future-proofs us in case we build up the function # using ast. - seen_default = False + seen_default = None for f in std_fields: # Only consider the non-kw-only fields in the __init__ call. if f.init: if not (f.default is MISSING and f.default_factory is MISSING): - seen_default = True + seen_default = f elif seen_default: raise TypeError(f'non-default argument {f.name!r} ' - 'follows default argument') + f'follows default argument {seen_default.name!r}') locals = {f'__dataclass_type_{f.name}__': f.type for f in fields} locals.update({ @@ -944,8 +944,11 @@ def _process_class(cls, init, repr, eq, order, unsafe_hash, frozen, # Find our base classes in reverse MRO order, and exclude # ourselves. In reversed order so that more derived classes # override earlier field definitions in base classes. As long as - # we're iterating over them, see if any are frozen. + # we're iterating over them, see if all or any of them are frozen. any_frozen_base = False + # By default `all_frozen_bases` is `None` to represent a case, + # where some dataclasses does not have any bases with `_FIELDS` + all_frozen_bases = None has_dataclass_bases = False for b in cls.__mro__[-1:0:-1]: # Only process classes that have been processed by our @@ -955,8 +958,11 @@ def _process_class(cls, init, repr, eq, order, unsafe_hash, frozen, has_dataclass_bases = True for f in base_fields.values(): fields[f.name] = f - if getattr(b, _PARAMS).frozen: - any_frozen_base = True + if all_frozen_bases is None: + all_frozen_bases = True + current_frozen = getattr(b, _PARAMS).frozen + all_frozen_bases = all_frozen_bases and current_frozen + any_frozen_base = any_frozen_base or current_frozen # Annotations defined specifically in this class (not in base classes). # @@ -1025,7 +1031,7 @@ def _process_class(cls, init, repr, eq, order, unsafe_hash, frozen, 'frozen one') # Raise an exception if we're frozen, but none of our bases are. - if not any_frozen_base and frozen: + if all_frozen_bases is False and frozen: raise TypeError('cannot inherit frozen dataclass from a ' 'non-frozen one') @@ -1073,6 +1079,7 @@ def _process_class(cls, init, repr, eq, order, unsafe_hash, frozen, globals, slots, )) + _set_new_attribute(cls, '__replace__', _replace) # Get the fields as a list, and include only real fields. This is # used in all of the following methods. @@ -1546,13 +1553,15 @@ class C: c1 = replace(c, x=3) assert c1.x == 3 and c1.y == 2 """ + if not _is_dataclass_instance(obj): + raise TypeError("replace() should be called on dataclass instances") + return _replace(obj, **changes) + +def _replace(obj, /, **changes): # We're going to mutate 'changes', but that's okay because it's a # new dict, even if called with 'replace(obj, **my_changes)'. - if not _is_dataclass_instance(obj): - raise TypeError("replace() should be called on dataclass instances") - # It's an error to have init=False fields in 'changes'. # If a field is not in 'changes', read its value from the provided obj. @@ -1564,15 +1573,15 @@ class C: if not f.init: # Error if this field is specified in changes. if f.name in changes: - raise ValueError(f'field {f.name} is declared with ' - 'init=False, it cannot be specified with ' - 'replace()') + raise TypeError(f'field {f.name} is declared with ' + f'init=False, it cannot be specified with ' + f'replace()') continue if f.name not in changes: if f._field_type is _FIELD_INITVAR and f.default is MISSING: - raise ValueError(f"InitVar {f.name!r} " - 'must be specified with replace()') + raise TypeError(f"InitVar {f.name!r} " + f'must be specified with replace()') changes[f.name] = getattr(obj, f.name) # Create the new object, which calls __init__() and diff --git a/Lib/dis.py b/Lib/dis.py index b167773dfe7b0c..f05ea1a24f45a7 100644 --- a/Lib/dis.py +++ b/Lib/dis.py @@ -14,7 +14,7 @@ _intrinsic_1_descs, _intrinsic_2_descs, _specializations, - _specialized_instructions, + _specialized_opmap, ) __all__ = ["code_info", "dis", "disassemble", "distb", "disco", @@ -30,6 +30,7 @@ SET_FUNCTION_ATTRIBUTE = opmap['SET_FUNCTION_ATTRIBUTE'] FUNCTION_ATTR_FLAGS = ('defaults', 'kwdefaults', 'annotations', 'closure') +ENTER_EXECUTOR = opmap['ENTER_EXECUTOR'] LOAD_CONST = opmap['LOAD_CONST'] RETURN_CONST = opmap['RETURN_CONST'] LOAD_GLOBAL = opmap['LOAD_GLOBAL'] @@ -49,11 +50,11 @@ _all_opname = list(opname) _all_opmap = dict(opmap) -_empty_slot = [slot for slot, name in enumerate(_all_opname) if name.startswith("<")] -for spec_op, specialized in zip(_empty_slot, _specialized_instructions): +for name, op in _specialized_opmap.items(): # fill opname and opmap - _all_opname[spec_op] = specialized - _all_opmap[specialized] = spec_op + assert op < len(_all_opname) + _all_opname[op] = name + _all_opmap[name] = op deoptmap = { specialized: base for base, family in _specializations.items() for specialized in family @@ -72,7 +73,8 @@ def _try_compile(source, name): pass return compile(source, name, 'exec') -def dis(x=None, *, file=None, depth=None, show_caches=False, adaptive=False): +def dis(x=None, *, file=None, depth=None, show_caches=False, adaptive=False, + show_offsets=False): """Disassemble classes, methods, functions, and other compiled objects. With no argument, disassemble the last traceback. @@ -82,7 +84,8 @@ def dis(x=None, *, file=None, depth=None, show_caches=False, adaptive=False): in a special attribute. """ if x is None: - distb(file=file, show_caches=show_caches, adaptive=adaptive) + distb(file=file, show_caches=show_caches, adaptive=adaptive, + show_offsets=show_offsets) return # Extract functions from methods. if hasattr(x, '__func__'): @@ -103,21 +106,28 @@ def dis(x=None, *, file=None, depth=None, show_caches=False, adaptive=False): if isinstance(x1, _have_code): print("Disassembly of %s:" % name, file=file) try: - dis(x1, file=file, depth=depth, show_caches=show_caches, adaptive=adaptive) + dis(x1, file=file, depth=depth, show_caches=show_caches, adaptive=adaptive, show_offsets=show_offsets) except TypeError as msg: print("Sorry:", msg, file=file) print(file=file) elif hasattr(x, 'co_code'): # Code object - _disassemble_recursive(x, file=file, depth=depth, show_caches=show_caches, adaptive=adaptive) + _disassemble_recursive(x, file=file, depth=depth, show_caches=show_caches, adaptive=adaptive, show_offsets=show_offsets) elif isinstance(x, (bytes, bytearray)): # Raw bytecode - _disassemble_bytes(x, file=file, show_caches=show_caches) + labels_map = _make_labels_map(x) + label_width = 4 + len(str(len(labels_map))) + formatter = Formatter(file=file, + offset_width=len(str(max(len(x) - 2, 9999))) if show_offsets else 0, + label_width=label_width, + show_caches=show_caches) + arg_resolver = ArgResolver(labels_map=labels_map) + _disassemble_bytes(x, arg_resolver=arg_resolver, formatter=formatter) elif isinstance(x, str): # Source code - _disassemble_str(x, file=file, depth=depth, show_caches=show_caches, adaptive=adaptive) + _disassemble_str(x, file=file, depth=depth, show_caches=show_caches, adaptive=adaptive, show_offsets=show_offsets) else: raise TypeError("don't know how to disassemble %s objects" % type(x).__name__) -def distb(tb=None, *, file=None, show_caches=False, adaptive=False): +def distb(tb=None, *, file=None, show_caches=False, adaptive=False, show_offsets=False): """Disassemble a traceback (default: last traceback).""" if tb is None: try: @@ -128,7 +138,7 @@ def distb(tb=None, *, file=None, show_caches=False, adaptive=False): except AttributeError: raise RuntimeError("no last traceback to disassemble") from None while tb.tb_next: tb = tb.tb_next - disassemble(tb.tb_frame.f_code, tb.tb_lasti, file=file, show_caches=show_caches, adaptive=adaptive) + disassemble(tb.tb_frame.f_code, tb.tb_lasti, file=file, show_caches=show_caches, adaptive=adaptive, show_offsets=show_offsets) # The inspect module interrogates this dictionary to build its # list of CO_* constants. It is also used by pretty_flags to @@ -262,10 +272,12 @@ def show_code(co, *, file=None): 'offset', 'start_offset', 'starts_line', - 'is_jump_target', - 'positions' + 'line_number', + 'label', + 'positions', + 'cache_info', ], - defaults=[None] + defaults=[None, None, None] ) _Instruction.opname.__doc__ = "Human readable name for operation" @@ -278,13 +290,18 @@ def show_code(co, *, file=None): "Start index of operation within bytecode sequence, including extended args if present; " "otherwise equal to Instruction.offset" ) -_Instruction.starts_line.__doc__ = "Line started by this opcode (if any), otherwise None" -_Instruction.is_jump_target.__doc__ = "True if other code jumps to here, otherwise False" +_Instruction.starts_line.__doc__ = "True if this opcode starts a source line, otherwise False" +_Instruction.line_number.__doc__ = "source line number associated with this opcode (if any), otherwise None" +_Instruction.label.__doc__ = "A label (int > 0) if this instruction is a jump target, otherwise None" _Instruction.positions.__doc__ = "dis.Positions object holding the span of source code covered by this instruction" +_Instruction.cache_info.__doc__ = "list of (name, size, data), one for each cache entry of the instruction" -_ExceptionTableEntry = collections.namedtuple("_ExceptionTableEntry", +_ExceptionTableEntryBase = collections.namedtuple("_ExceptionTableEntryBase", "start end target depth lasti") +class _ExceptionTableEntry(_ExceptionTableEntryBase): + pass + _OPNAME_WIDTH = 20 _OPARG_WIDTH = 5 @@ -321,10 +338,13 @@ class Instruction(_Instruction): offset - start index of operation within bytecode sequence start_offset - start index of operation within bytecode sequence including extended args if present; otherwise equal to Instruction.offset - starts_line - line started by this opcode (if any), otherwise None - is_jump_target - True if other code jumps to here, otherwise False + starts_line - True if this opcode starts a source line, otherwise False + line_number - source line number associated with this opcode (if any), otherwise None + label - A label if this instruction is a jump target, otherwise None positions - Optional dis.Positions object holding the span of source code covered by this instruction + cache_info - information about the format and content of the instruction's cache + entries (if any) """ @property @@ -366,52 +386,196 @@ def jump_target(self): """ return _get_jump_target(self.opcode, self.arg, self.offset) - def _disassemble(self, lineno_width=3, mark_as_current=False, offset_width=4): - """Format instruction details for inclusion in disassembly output. + @property + def is_jump_target(self): + """True if other code jumps to here, otherwise False""" + return self.label is not None + + def __str__(self): + output = io.StringIO() + formatter = Formatter(file=output) + formatter.print_instruction(self, False) + return output.getvalue() + +class Formatter: + + def __init__(self, file=None, lineno_width=0, offset_width=0, label_width=0, + line_offset=0, show_caches=False): + """Create a Formatter + + *file* where to write the output *lineno_width* sets the width of the line number field (0 omits it) - *mark_as_current* inserts a '-->' marker arrow as part of the line *offset_width* sets the width of the instruction offset field + *label_width* sets the width of the label field + *show_caches* is a boolean indicating whether to display cache lines + """ + self.file = file + self.lineno_width = lineno_width + self.offset_width = offset_width + self.label_width = label_width + self.show_caches = show_caches + + def print_instruction(self, instr, mark_as_current=False): + self.print_instruction_line(instr, mark_as_current) + if self.show_caches and instr.cache_info: + offset = instr.offset + for name, size, data in instr.cache_info: + for i in range(size): + offset += 2 + # Only show the fancy argrepr for a CACHE instruction when it's + # the first entry for a particular cache value: + if i == 0: + argrepr = f"{name}: {int.from_bytes(data, sys.byteorder)}" + else: + argrepr = "" + self.print_instruction_line( + Instruction("CACHE", CACHE, 0, None, argrepr, offset, offset, + False, None, None, instr.positions), + False) + + def print_instruction_line(self, instr, mark_as_current): + """Format instruction details for inclusion in disassembly output.""" + lineno_width = self.lineno_width + offset_width = self.offset_width + label_width = self.label_width + + new_source_line = (lineno_width > 0 and + instr.starts_line and + instr.offset > 0) + if new_source_line: + print(file=self.file) + fields = [] # Column: Source code line number if lineno_width: - if self.starts_line is not None: - lineno_fmt = "%%%dd" % lineno_width - fields.append(lineno_fmt % self.starts_line) + if instr.starts_line: + lineno_fmt = "%%%dd" if instr.line_number is not None else "%%%ds" + lineno_fmt = lineno_fmt % lineno_width + lineno = _NO_LINENO if instr.line_number is None else instr.line_number + fields.append(lineno_fmt % lineno) else: fields.append(' ' * lineno_width) + # Column: Label + if instr.label is not None: + lbl = f"L{instr.label}:" + fields.append(f"{lbl:>{label_width}}") + else: + fields.append(' ' * label_width) + # Column: Instruction offset from start of code sequence + if offset_width > 0: + fields.append(f"{repr(instr.offset):>{offset_width}} ") # Column: Current instruction indicator if mark_as_current: fields.append('-->') else: fields.append(' ') - # Column: Jump target marker - if self.is_jump_target: - fields.append('>>') - else: - fields.append(' ') - # Column: Instruction offset from start of code sequence - fields.append(repr(self.offset).rjust(offset_width)) # Column: Opcode name - fields.append(self.opname.ljust(_OPNAME_WIDTH)) + fields.append(instr.opname.ljust(_OPNAME_WIDTH)) # Column: Opcode argument - if self.arg is not None: - arg = repr(self.arg) + if instr.arg is not None: + arg = repr(instr.arg) # If opname is longer than _OPNAME_WIDTH, we allow it to overflow into # the space reserved for oparg. This results in fewer misaligned opargs # in the disassembly output. - opname_excess = max(0, len(self.opname) - _OPNAME_WIDTH) - fields.append(repr(self.arg).rjust(_OPARG_WIDTH - opname_excess)) + opname_excess = max(0, len(instr.opname) - _OPNAME_WIDTH) + fields.append(repr(instr.arg).rjust(_OPARG_WIDTH - opname_excess)) # Column: Opcode argument details - if self.argrepr: - fields.append('(' + self.argrepr + ')') - return ' '.join(fields).rstrip() - - def __str__(self): - return self._disassemble() + if instr.argrepr: + fields.append('(' + instr.argrepr + ')') + print(' '.join(fields).rstrip(), file=self.file) + + def print_exception_table(self, exception_entries): + file = self.file + if exception_entries: + print("ExceptionTable:", file=file) + for entry in exception_entries: + lasti = " lasti" if entry.lasti else "" + start = entry.start_label + end = entry.end_label + target = entry.target_label + print(f" L{start} to L{end} -> L{target} [{entry.depth}]{lasti}", file=file) + + +class ArgResolver: + def __init__(self, co_consts=None, names=None, varname_from_oparg=None, labels_map=None): + self.co_consts = co_consts + self.names = names + self.varname_from_oparg = varname_from_oparg + self.labels_map = labels_map or {} + + def get_label_for_offset(self, offset): + return self.labels_map.get(offset, None) + + def get_argval_argrepr(self, op, arg, offset): + get_name = None if self.names is None else self.names.__getitem__ + argval = None + argrepr = '' + deop = _deoptop(op) + if arg is not None: + # Set argval to the dereferenced value of the argument when + # available, and argrepr to the string representation of argval. + # _disassemble_bytes needs the string repr of the + # raw name index for LOAD_GLOBAL, LOAD_CONST, etc. + argval = arg + if deop in hasconst: + argval, argrepr = _get_const_info(deop, arg, self.co_consts) + elif deop in hasname: + if deop == LOAD_GLOBAL: + argval, argrepr = _get_name_info(arg//2, get_name) + if (arg & 1) and argrepr: + argrepr = f"{argrepr} + NULL" + elif deop == LOAD_ATTR: + argval, argrepr = _get_name_info(arg//2, get_name) + if (arg & 1) and argrepr: + argrepr = f"{argrepr} + NULL|self" + elif deop == LOAD_SUPER_ATTR: + argval, argrepr = _get_name_info(arg//4, get_name) + if (arg & 1) and argrepr: + argrepr = f"{argrepr} + NULL|self" + else: + argval, argrepr = _get_name_info(arg, get_name) + elif deop in hasjabs: + argval = arg*2 + argrepr = f"to L{self.labels_map[argval]}" + elif deop in hasjrel: + signed_arg = -arg if _is_backward_jump(deop) else arg + argval = offset + 2 + signed_arg*2 + caches = _get_cache_size(_all_opname[deop]) + argval += 2 * caches + if deop == ENTER_EXECUTOR: + argval += 2 + argrepr = f"to L{self.labels_map[argval]}" + elif deop in (LOAD_FAST_LOAD_FAST, STORE_FAST_LOAD_FAST, STORE_FAST_STORE_FAST): + arg1 = arg >> 4 + arg2 = arg & 15 + val1, argrepr1 = _get_name_info(arg1, self.varname_from_oparg) + val2, argrepr2 = _get_name_info(arg2, self.varname_from_oparg) + argrepr = argrepr1 + ", " + argrepr2 + argval = val1, val2 + elif deop in haslocal or deop in hasfree: + argval, argrepr = _get_name_info(arg, self.varname_from_oparg) + elif deop in hascompare: + argval = cmp_op[arg >> 5] + argrepr = argval + if arg & 16: + argrepr = f"bool({argrepr})" + elif deop == CONVERT_VALUE: + argval = (None, str, repr, ascii)[arg] + argrepr = ('', 'str', 'repr', 'ascii')[arg] + elif deop == SET_FUNCTION_ATTRIBUTE: + argrepr = ', '.join(s for i, s in enumerate(FUNCTION_ATTR_FLAGS) + if arg & (1<> 4 - arg2 = arg & 15 - val1, argrepr1 = _get_name_info(arg1, varname_from_oparg) - val2, argrepr2 = _get_name_info(arg2, varname_from_oparg) - argrepr = argrepr1 + ", " + argrepr2 - argval = val1, val2 - elif deop in haslocal or deop in hasfree: - argval, argrepr = _get_name_info(arg, varname_from_oparg) - elif deop in hascompare: - argval = cmp_op[arg >> 5] - argrepr = argval - if arg & 16: - argrepr = f"bool({argrepr})" - elif deop == CONVERT_VALUE: - argval = (None, str, repr, ascii)[arg] - argrepr = ('', 'str', 'repr', 'ascii')[arg] - elif deop == SET_FUNCTION_ATTRIBUTE: - argrepr = ', '.join(s for i, s in enumerate(FUNCTION_ATTR_FLAGS) - if arg & (1< 0: if depth is not None: depth = depth - 1 @@ -643,54 +759,66 @@ def _disassemble_recursive(co, *, file=None, depth=None, show_caches=False, adap print(file=file) print("Disassembly of %r:" % (x,), file=file) _disassemble_recursive( - x, file=file, depth=depth, show_caches=show_caches, adaptive=adaptive + x, file=file, depth=depth, show_caches=show_caches, + adaptive=adaptive, show_offsets=show_offsets ) -def _disassemble_bytes(code, lasti=-1, varname_from_oparg=None, - names=None, co_consts=None, linestarts=None, - *, file=None, line_offset=0, exception_entries=(), - co_positions=None, show_caches=False, original_code=None): - # Omit the line number column entirely if we have no line number info - show_lineno = bool(linestarts) - if show_lineno: - maxlineno = max(linestarts.values()) + line_offset - if maxlineno >= 1000: - lineno_width = len(str(maxlineno)) - else: - lineno_width = 3 - else: - lineno_width = 0 - maxoffset = len(code) - 2 - if maxoffset >= 10000: - offset_width = len(str(maxoffset)) - else: - offset_width = 4 - for instr in _get_instructions_bytes(code, varname_from_oparg, names, - co_consts, linestarts, - line_offset=line_offset, - exception_entries=exception_entries, - co_positions=co_positions, - show_caches=show_caches, - original_code=original_code): - new_source_line = (show_lineno and - instr.starts_line is not None and - instr.offset > 0) - if new_source_line: - print(file=file) - if show_caches: - is_current_instr = instr.offset == lasti - else: - # Each CACHE takes 2 bytes - is_current_instr = instr.offset <= lasti \ - <= instr.offset + 2 * _get_cache_size(_all_opname[_deoptop(instr.opcode)]) - print(instr._disassemble(lineno_width, is_current_instr, offset_width), - file=file) - if exception_entries: - print("ExceptionTable:", file=file) - for entry in exception_entries: - lasti = " lasti" if entry.lasti else "" - end = entry.end-2 - print(f" {entry.start} to {end} -> {entry.target} [{entry.depth}]{lasti}", file=file) + +def _make_labels_map(original_code, exception_entries=()): + jump_targets = set(findlabels(original_code)) + labels = set(jump_targets) + for start, end, target, _, _ in exception_entries: + labels.add(start) + labels.add(end) + labels.add(target) + labels = sorted(labels) + labels_map = {offset: i+1 for (i, offset) in enumerate(sorted(labels))} + for e in exception_entries: + e.start_label = labels_map[e.start] + e.end_label = labels_map[e.end] + e.target_label = labels_map[e.target] + return labels_map + +_NO_LINENO = ' --' + +def _get_lineno_width(linestarts): + if linestarts is None: + return 0 + maxlineno = max(filter(None, linestarts.values()), default=-1) + if maxlineno == -1: + # Omit the line number column entirely if we have no line number info + return 0 + lineno_width = max(3, len(str(maxlineno))) + if lineno_width < len(_NO_LINENO) and None in linestarts.values(): + lineno_width = len(_NO_LINENO) + return lineno_width + + +def _disassemble_bytes(code, lasti=-1, linestarts=None, + *, line_offset=0, exception_entries=(), + co_positions=None, original_code=None, + arg_resolver=None, formatter=None): + + assert formatter is not None + assert arg_resolver is not None + + instrs = _get_instructions_bytes(code, linestarts=linestarts, + line_offset=line_offset, + co_positions=co_positions, + original_code=original_code, + arg_resolver=arg_resolver) + + print_instructions(instrs, exception_entries, formatter, lasti=lasti) + + +def print_instructions(instrs, exception_entries, formatter, lasti=-1): + for instr in instrs: + # Each CACHE takes 2 bytes + is_current_instr = instr.offset <= lasti \ + <= instr.offset + 2 * _get_cache_size(_all_opname[_deoptop(instr.opcode)]) + formatter.print_instruction(instr, is_current_instr) + + formatter.print_exception_table(exception_entries) def _disassemble_str(source, **kwargs): """Compile the source string, then disassemble the code object.""" @@ -755,10 +883,12 @@ def findlinestarts(code): """Find the offsets in a byte code which are start of lines in the source. Generate pairs (offset, lineno) + lineno will be an integer or None the offset does not have a source line. """ - lastline = None + + lastline = False # None is a valid line number for start, end, line in code.co_lines(): - if line is not None and line != lastline: + if line is not lastline: lastline = line yield start, line return @@ -809,7 +939,7 @@ class Bytecode: Iterating over this yields the bytecode operations as Instruction instances. """ - def __init__(self, x, *, first_line=None, current_offset=None, show_caches=False, adaptive=False): + def __init__(self, x, *, first_line=None, current_offset=None, show_caches=False, adaptive=False, show_offsets=False): self.codeobj = co = _get_code_object(x) if first_line is None: self.first_line = co.co_firstlineno @@ -823,18 +953,22 @@ def __init__(self, x, *, first_line=None, current_offset=None, show_caches=False self.exception_entries = _parse_exception_table(co) self.show_caches = show_caches self.adaptive = adaptive + self.show_offsets = show_offsets def __iter__(self): co = self.codeobj + original_code = co.co_code + labels_map = _make_labels_map(original_code, self.exception_entries) + arg_resolver = ArgResolver(co_consts=co.co_consts, + names=co.co_names, + varname_from_oparg=co._varname_from_oparg, + labels_map=labels_map) return _get_instructions_bytes(_get_code_array(co, self.adaptive), - co._varname_from_oparg, - co.co_names, co.co_consts, - self._linestarts, + linestarts=self._linestarts, line_offset=self._line_offset, - exception_entries=self.exception_entries, co_positions=co.co_positions(), - show_caches=self.show_caches, - original_code=co.co_code) + original_code=original_code, + arg_resolver=arg_resolver) def __repr__(self): return "{}({!r})".format(self.__class__.__name__, @@ -861,31 +995,54 @@ def dis(self): else: offset = -1 with io.StringIO() as output: - _disassemble_bytes(_get_code_array(co, self.adaptive), - varname_from_oparg=co._varname_from_oparg, - names=co.co_names, co_consts=co.co_consts, + code = _get_code_array(co, self.adaptive) + offset_width = len(str(max(len(code) - 2, 9999))) if self.show_offsets else 0 + + + labels_map = _make_labels_map(co.co_code, self.exception_entries) + label_width = 4 + len(str(len(labels_map))) + formatter = Formatter(file=output, + lineno_width=_get_lineno_width(self._linestarts), + offset_width=offset_width, + label_width=label_width, + line_offset=self._line_offset, + show_caches=self.show_caches) + + arg_resolver = ArgResolver(co_consts=co.co_consts, + names=co.co_names, + varname_from_oparg=co._varname_from_oparg, + labels_map=labels_map) + _disassemble_bytes(code, linestarts=self._linestarts, line_offset=self._line_offset, - file=output, lasti=offset, exception_entries=self.exception_entries, co_positions=co.co_positions(), - show_caches=self.show_caches, - original_code=co.co_code) + original_code=co.co_code, + arg_resolver=arg_resolver, + formatter=formatter) return output.getvalue() -def _test(): - """Simple test program to disassemble a file.""" +def main(): import argparse parser = argparse.ArgumentParser() - parser.add_argument('infile', type=argparse.FileType('rb'), nargs='?', default='-') + parser.add_argument('-C', '--show-caches', action='store_true', + help='show inline caches') + parser.add_argument('-O', '--show-offsets', action='store_true', + help='show instruction offsets') + parser.add_argument('infile', nargs='?', default='-') args = parser.parse_args() - with args.infile as infile: - source = infile.read() - code = compile(source, args.infile.name, "exec") - dis(code) + if args.infile == '-': + name = '' + source = sys.stdin.buffer.read() + else: + name = args.infile + with open(args.infile, 'rb') as infile: + source = infile.read() + code = compile(source, name, "exec") + dis(code, show_caches=args.show_caches, show_offsets=args.show_offsets) if __name__ == "__main__": - _test() + main() diff --git a/Lib/doctest.py b/Lib/doctest.py index 2776d74bf9b586..114aac62a34e95 100644 --- a/Lib/doctest.py +++ b/Lib/doctest.py @@ -105,7 +105,23 @@ def _test(): from io import StringIO, IncrementalNewlineDecoder from collections import namedtuple -TestResults = namedtuple('TestResults', 'failed attempted') + +class TestResults(namedtuple('TestResults', 'failed attempted')): + def __new__(cls, failed, attempted, *, skipped=0): + results = super().__new__(cls, failed, attempted) + results.skipped = skipped + return results + + def __repr__(self): + if self.skipped: + return (f'TestResults(failed={self.failed}, ' + f'attempted={self.attempted}, ' + f'skipped={self.skipped})') + else: + # Leave the repr() unchanged for backward compatibility + # if skipped is zero + return super().__repr__() + # There are 4 basic classes: # - Example: a pair, plus an intra-docstring line number. @@ -575,9 +591,11 @@ def __hash__(self): def __lt__(self, other): if not isinstance(other, DocTest): return NotImplemented - return ((self.name, self.filename, self.lineno, id(self)) + self_lno = self.lineno if self.lineno is not None else -1 + other_lno = other.lineno if other.lineno is not None else -1 + return ((self.name, self.filename, self_lno, id(self)) < - (other.name, other.filename, other.lineno, id(other))) + (other.name, other.filename, other_lno, id(other))) ###################################################################### ## 3. DocTestParser @@ -1110,7 +1128,7 @@ def _find_lineno(self, obj, source_lines): if source_lines is None: return None pat = re.compile(r'^\s*class\s*%s\b' % - getattr(obj, '__name__', '-')) + re.escape(getattr(obj, '__name__', '-'))) for i, line in enumerate(source_lines): if pat.match(line): lineno = i @@ -1118,6 +1136,8 @@ def _find_lineno(self, obj, source_lines): # Find the line number for functions & methods. if inspect.ismethod(obj): obj = obj.__func__ + if isinstance(obj, property): + obj = obj.fget if inspect.isfunction(obj) and getattr(obj, '__doc__', None): # We don't use `docstring` var here, because `obj` can be changed. obj = obj.__code__ @@ -1150,8 +1170,7 @@ class DocTestRunner: """ A class used to run DocTest test cases, and accumulate statistics. The `run` method is used to process a single DocTest case. It - returns a tuple `(f, t)`, where `t` is the number of test cases - tried, and `f` is the number of test cases that failed. + returns a TestResults instance. >>> tests = DocTestFinder().find(_TestClass) >>> runner = DocTestRunner(verbose=False) @@ -1164,8 +1183,8 @@ class DocTestRunner: _TestClass.square -> TestResults(failed=0, attempted=1) The `summarize` method prints a summary of all the test cases that - have been run by the runner, and returns an aggregated `(f, t)` - tuple: + have been run by the runner, and returns an aggregated TestResults + instance: >>> runner.summarize(verbose=1) 4 items passed all tests: @@ -1178,13 +1197,15 @@ class DocTestRunner: Test passed. TestResults(failed=0, attempted=7) - The aggregated number of tried examples and failed examples is - also available via the `tries` and `failures` attributes: + The aggregated number of tried examples and failed examples is also + available via the `tries`, `failures` and `skips` attributes: >>> runner.tries 7 >>> runner.failures 0 + >>> runner.skips + 0 The comparison between expected outputs and actual outputs is done by an `OutputChecker`. This comparison may be customized with a @@ -1233,7 +1254,8 @@ def __init__(self, checker=None, verbose=None, optionflags=0): # Keep track of the examples we've run. self.tries = 0 self.failures = 0 - self._name2ft = {} + self.skips = 0 + self._stats = {} # Create a fake output target for capturing doctest output. self._fakeout = _SpoofOut() @@ -1302,13 +1324,11 @@ def __run(self, test, compileflags, out): Run the examples in `test`. Write the outcome of each example with one of the `DocTestRunner.report_*` methods, using the writer function `out`. `compileflags` is the set of compiler - flags that should be used to execute examples. Return a tuple - `(f, t)`, where `t` is the number of examples tried, and `f` - is the number of examples that failed. The examples are run - in the namespace `test.globs`. + flags that should be used to execute examples. Return a TestResults + instance. The examples are run in the namespace `test.globs`. """ - # Keep track of the number of failures and tries. - failures = tries = 0 + # Keep track of the number of failed, attempted, skipped examples. + failures = attempted = skips = 0 # Save the option flags (since option directives can be used # to modify them). @@ -1320,6 +1340,7 @@ def __run(self, test, compileflags, out): # Process each example. for examplenum, example in enumerate(test.examples): + attempted += 1 # If REPORT_ONLY_FIRST_FAILURE is set, then suppress # reporting after the first failure. @@ -1337,10 +1358,10 @@ def __run(self, test, compileflags, out): # If 'SKIP' is set, then skip this example. if self.optionflags & SKIP: + skips += 1 continue # Record that we started this example. - tries += 1 if not quiet: self.report_start(out, test, example) @@ -1376,7 +1397,24 @@ def __run(self, test, compileflags, out): # The example raised an exception: check if it was expected. else: - exc_msg = traceback.format_exception_only(*exception[:2])[-1] + formatted_ex = traceback.format_exception_only(*exception[:2]) + if issubclass(exception[0], SyntaxError): + # SyntaxError / IndentationError is special: + # we don't care about the carets / suggestions / etc + # We only care about the error message and notes. + # They start with `SyntaxError:` (or any other class name) + exception_line_prefixes = ( + f"{exception[0].__qualname__}:", + f"{exception[0].__module__}.{exception[0].__qualname__}:", + ) + exc_msg_index = next( + index + for index, line in enumerate(formatted_ex) + if line.startswith(exception_line_prefixes) + ) + formatted_ex = formatted_ex[exc_msg_index:] + + exc_msg = "".join(formatted_ex) if not quiet: got += _exception_traceback(exception) @@ -1418,19 +1456,22 @@ def __run(self, test, compileflags, out): # Restore the option flags (in case they were modified) self.optionflags = original_optionflags - # Record and return the number of failures and tries. - self.__record_outcome(test, failures, tries) - return TestResults(failures, tries) + # Record and return the number of failures and attempted. + self.__record_outcome(test, failures, attempted, skips) + return TestResults(failures, attempted, skipped=skips) - def __record_outcome(self, test, f, t): + def __record_outcome(self, test, failures, tries, skips): """ - Record the fact that the given DocTest (`test`) generated `f` - failures out of `t` tried examples. + Record the fact that the given DocTest (`test`) generated `failures` + failures out of `tries` tried examples. """ - f2, t2 = self._name2ft.get(test.name, (0,0)) - self._name2ft[test.name] = (f+f2, t+t2) - self.failures += f - self.tries += t + failures2, tries2, skips2 = self._stats.get(test.name, (0, 0, 0)) + self._stats[test.name] = (failures + failures2, + tries + tries2, + skips + skips2) + self.failures += failures + self.tries += tries + self.skips += skips __LINECACHE_FILENAME_RE = re.compile(r'.+)' @@ -1519,9 +1560,7 @@ def out(s): def summarize(self, verbose=None): """ Print a summary of all the test cases that have been run by - this DocTestRunner, and return a tuple `(f, t)`, where `f` is - the total number of failed examples, and `t` is the total - number of tried examples. + this DocTestRunner, and return a TestResults instance. The optional `verbose` argument controls how detailed the summary is. If the verbosity is not specified, then the @@ -1532,59 +1571,61 @@ def summarize(self, verbose=None): notests = [] passed = [] failed = [] - totalt = totalf = 0 - for x in self._name2ft.items(): - name, (f, t) = x - assert f <= t - totalt += t - totalf += f - if t == 0: + total_tries = total_failures = total_skips = 0 + for item in self._stats.items(): + name, (failures, tries, skips) = item + assert failures <= tries + total_tries += tries + total_failures += failures + total_skips += skips + if tries == 0: notests.append(name) - elif f == 0: - passed.append( (name, t) ) + elif failures == 0: + passed.append((name, tries)) else: - failed.append(x) + failed.append(item) if verbose: if notests: - print(len(notests), "items had no tests:") + print(f"{len(notests)} items had no tests:") notests.sort() - for thing in notests: - print(" ", thing) + for name in notests: + print(f" {name}") if passed: - print(len(passed), "items passed all tests:") + print(f"{len(passed)} items passed all tests:") passed.sort() - for thing, count in passed: - print(" %3d tests in %s" % (count, thing)) + for name, count in passed: + print(f" {count:3d} tests in {name}") if failed: print(self.DIVIDER) - print(len(failed), "items had failures:") + print(f"{len(failed)} items had failures:") failed.sort() - for thing, (f, t) in failed: - print(" %3d of %3d in %s" % (f, t, thing)) + for name, (failures, tries, skips) in failed: + print(f" {failures:3d} of {tries:3d} in {name}") if verbose: - print(totalt, "tests in", len(self._name2ft), "items.") - print(totalt - totalf, "passed and", totalf, "failed.") - if totalf: - print("***Test Failed***", totalf, "failures.") + print(f"{total_tries} tests in {len(self._stats)} items.") + print(f"{total_tries - total_failures} passed and {total_failures} failed.") + if total_failures: + msg = f"***Test Failed*** {total_failures} failures" + if total_skips: + msg = f"{msg} and {total_skips} skipped tests" + print(f"{msg}.") elif verbose: print("Test passed.") - return TestResults(totalf, totalt) + return TestResults(total_failures, total_tries, skipped=total_skips) #///////////////////////////////////////////////////////////////// # Backward compatibility cruft to maintain doctest.master. #///////////////////////////////////////////////////////////////// def merge(self, other): - d = self._name2ft - for name, (f, t) in other._name2ft.items(): + d = self._stats + for name, (failures, tries, skips) in other._stats.items(): if name in d: - # Don't print here by default, since doing - # so breaks some of the buildbots - #print("*** DocTestRunner.merge: '" + name + "' in both" \ - # " testers; summing outcomes.") - f2, t2 = d[name] - f = f + f2 - t = t + t2 - d[name] = f, t + failures2, tries2, skips2 = d[name] + failures = failures + failures2 + tries = tries + tries2 + skips = skips + skips2 + d[name] = (failures, tries, skips) + class OutputChecker: """ @@ -1984,7 +2025,8 @@ class doctest.Tester, then merges the results into (or creates) else: master.merge(runner) - return TestResults(runner.failures, runner.tries) + return TestResults(runner.failures, runner.tries, skipped=runner.skips) + def testfile(filename, module_relative=True, name=None, package=None, globs=None, verbose=None, report=True, optionflags=0, @@ -2107,7 +2149,8 @@ class doctest.Tester, then merges the results into (or creates) else: master.merge(runner) - return TestResults(runner.failures, runner.tries) + return TestResults(runner.failures, runner.tries, skipped=runner.skips) + def run_docstring_examples(f, globs, verbose=False, name="NoName", compileflags=None, optionflags=0): diff --git a/Lib/email/_header_value_parser.py b/Lib/email/_header_value_parser.py index 0d6bd812475eea..5b653f66c18554 100644 --- a/Lib/email/_header_value_parser.py +++ b/Lib/email/_header_value_parser.py @@ -2766,6 +2766,7 @@ def _refold_parse_tree(parse_tree, *, policy): encoding = 'utf-8' if policy.utf8 else 'us-ascii' lines = [''] last_ew = None + last_charset = None wrap_as_ew_blocked = 0 want_encoding = False end_ew_not_allowed = Terminal('', 'wrap_as_ew_blocked') @@ -2820,8 +2821,14 @@ def _refold_parse_tree(parse_tree, *, policy): else: # It's a terminal, wrap it as an encoded word, possibly # combining it with previously encoded words if allowed. + if (last_ew is not None and + charset != last_charset and + (last_charset == 'unknown-8bit' or + last_charset == 'utf-8' and charset != 'us-ascii')): + last_ew = None last_ew = _fold_as_ew(tstr, lines, maxlen, last_ew, part.ew_combine_allowed, charset) + last_charset = charset want_encoding = False continue if len(tstr) <= maxlen - len(lines[-1]): diff --git a/Lib/email/message.py b/Lib/email/message.py index 411118c74dabb4..fe769580fed5d0 100644 --- a/Lib/email/message.py +++ b/Lib/email/message.py @@ -289,25 +289,26 @@ def get_payload(self, i=None, decode=False): # cte might be a Header, so for now stringify it. cte = str(self.get('content-transfer-encoding', '')).lower() # payload may be bytes here. - if isinstance(payload, str): - if utils._has_surrogates(payload): - bpayload = payload.encode('ascii', 'surrogateescape') - if not decode: + if not decode: + if isinstance(payload, str) and utils._has_surrogates(payload): + try: + bpayload = payload.encode('ascii', 'surrogateescape') try: payload = bpayload.decode(self.get_param('charset', 'ascii'), 'replace') except LookupError: payload = bpayload.decode('ascii', 'replace') - elif decode: - try: - bpayload = payload.encode('ascii') - except UnicodeError: - # This won't happen for RFC compliant messages (messages - # containing only ASCII code points in the unicode input). - # If it does happen, turn the string into bytes in a way - # guaranteed not to fail. - bpayload = payload.encode('raw-unicode-escape') - if not decode: + except UnicodeEncodeError: + pass return payload + if isinstance(payload, str): + try: + bpayload = payload.encode('ascii', 'surrogateescape') + except UnicodeEncodeError: + # This won't happen for RFC compliant messages (messages + # containing only ASCII code points in the unicode input). + # If it does happen, turn the string into bytes in a way + # guaranteed not to fail. + bpayload = payload.encode('raw-unicode-escape') if cte == 'quoted-printable': return quopri.decodestring(bpayload) elif cte == 'base64': diff --git a/Lib/email/utils.py b/Lib/email/utils.py index 81da5394ea1695..103cef61a83538 100644 --- a/Lib/email/utils.py +++ b/Lib/email/utils.py @@ -25,8 +25,6 @@ import os import re import time -import random -import socket import datetime import urllib.parse @@ -36,9 +34,6 @@ from email._parseaddr import parsedate, parsedate_tz, _parsedate_tz -# Intrapackage imports -from email.charset import Charset - COMMASPACE = ', ' EMPTYSTRING = '' UEMPTYSTRING = '' @@ -48,11 +43,12 @@ specialsre = re.compile(r'[][\\()<>@,:;".]') escapesre = re.compile(r'[\\"]') + def _has_surrogates(s): - """Return True if s contains surrogate-escaped binary data.""" + """Return True if s may contain surrogate-escaped binary data.""" # This check is based on the fact that unless there are surrogates, utf8 # (Python's default encoding) can encode any string. This is the fastest - # way to check for surrogates, see issue 11454 for timings. + # way to check for surrogates, see bpo-11454 (moved to gh-55663) for timings. try: s.encode() return False @@ -94,6 +90,8 @@ def formataddr(pair, charset='utf-8'): name.encode('ascii') except UnicodeEncodeError: if isinstance(charset, str): + # lazy import to improve module import time + from email.charset import Charset charset = Charset(charset) encoded_name = charset.header_encode(name) return "%s <%s>" % (encoded_name, address) @@ -106,12 +104,127 @@ def formataddr(pair, charset='utf-8'): return address +def _iter_escaped_chars(addr): + pos = 0 + escape = False + for pos, ch in enumerate(addr): + if escape: + yield (pos, '\\' + ch) + escape = False + elif ch == '\\': + escape = True + else: + yield (pos, ch) + if escape: + yield (pos, '\\') + + +def _strip_quoted_realnames(addr): + """Strip real names between quotes.""" + if '"' not in addr: + # Fast path + return addr + + start = 0 + open_pos = None + result = [] + for pos, ch in _iter_escaped_chars(addr): + if ch == '"': + if open_pos is None: + open_pos = pos + else: + if start != open_pos: + result.append(addr[start:open_pos]) + start = pos + 1 + open_pos = None + + if start < len(addr): + result.append(addr[start:]) + + return ''.join(result) + + +supports_strict_parsing = True -def getaddresses(fieldvalues): - """Return a list of (REALNAME, EMAIL) for each fieldvalue.""" - all = COMMASPACE.join(str(v) for v in fieldvalues) - a = _AddressList(all) - return a.addresslist +def getaddresses(fieldvalues, *, strict=True): + """Return a list of (REALNAME, EMAIL) or ('','') for each fieldvalue. + + When parsing fails for a fieldvalue, a 2-tuple of ('', '') is returned in + its place. + + If strict is true, use a strict parser which rejects malformed inputs. + """ + + # If strict is true, if the resulting list of parsed addresses is greater + # than the number of fieldvalues in the input list, a parsing error has + # occurred and consequently a list containing a single empty 2-tuple [('', + # '')] is returned in its place. This is done to avoid invalid output. + # + # Malformed input: getaddresses(['alice@example.com ']) + # Invalid output: [('', 'alice@example.com'), ('', 'bob@example.com')] + # Safe output: [('', '')] + + if not strict: + all = COMMASPACE.join(str(v) for v in fieldvalues) + a = _AddressList(all) + return a.addresslist + + fieldvalues = [str(v) for v in fieldvalues] + fieldvalues = _pre_parse_validation(fieldvalues) + addr = COMMASPACE.join(fieldvalues) + a = _AddressList(addr) + result = _post_parse_validation(a.addresslist) + + # Treat output as invalid if the number of addresses is not equal to the + # expected number of addresses. + n = 0 + for v in fieldvalues: + # When a comma is used in the Real Name part it is not a deliminator. + # So strip those out before counting the commas. + v = _strip_quoted_realnames(v) + # Expected number of addresses: 1 + number of commas + n += 1 + v.count(',') + if len(result) != n: + return [('', '')] + + return result + + +def _check_parenthesis(addr): + # Ignore parenthesis in quoted real names. + addr = _strip_quoted_realnames(addr) + + opens = 0 + for pos, ch in _iter_escaped_chars(addr): + if ch == '(': + opens += 1 + elif ch == ')': + opens -= 1 + if opens < 0: + return False + return (opens == 0) + + +def _pre_parse_validation(email_header_fields): + accepted_values = [] + for v in email_header_fields: + if not _check_parenthesis(v): + v = "('', '')" + accepted_values.append(v) + + return accepted_values + + +def _post_parse_validation(parsed_email_header_tuples): + accepted_values = [] + # The parser would have parsed a correctly formatted domain-literal + # The existence of an [ after parsing indicates a parsing failure + for v in parsed_email_header_tuples: + if '[' in v[1]: + v = ('', '') + accepted_values.append(v) + + return accepted_values def _format_timetuple_and_zone(timetuple, zone): @@ -181,6 +294,11 @@ def make_msgid(idstring=None, domain=None): portion of the message id after the '@'. It defaults to the locally defined hostname. """ + # Lazy imports to speedup module import time + # (no other functions in email.utils need these modules) + import random + import socket + timeval = int(time.time()*100) pid = os.getpid() randint = random.getrandbits(64) @@ -205,16 +323,33 @@ def parsedate_to_datetime(data): tzinfo=datetime.timezone(datetime.timedelta(seconds=tz))) -def parseaddr(addr): +def parseaddr(addr, *, strict=True): """ Parse addr into its constituent realname and email address parts. Return a tuple of realname and email address, unless the parse fails, in which case return a 2-tuple of ('', ''). + + If strict is True, use a strict parser which rejects malformed inputs. """ - addrs = _AddressList(addr).addresslist - if not addrs: - return '', '' + if not strict: + addrs = _AddressList(addr).addresslist + if not addrs: + return ('', '') + return addrs[0] + + if isinstance(addr, list): + addr = addr[0] + + if not isinstance(addr, str): + return ('', '') + + addr = _pre_parse_validation([addr])[0] + addrs = _post_parse_validation(_AddressList(addr).addresslist) + + if not addrs or len(addrs) > 1: + return ('', '') + return addrs[0] diff --git a/Lib/ensurepip/__init__.py b/Lib/ensurepip/__init__.py index 1fb1d505cfd0c5..a09bf3201e1fb7 100644 --- a/Lib/ensurepip/__init__.py +++ b/Lib/ensurepip/__init__.py @@ -10,7 +10,7 @@ __all__ = ["version", "bootstrap"] _PACKAGE_NAMES = ('pip',) -_PIP_VERSION = "23.2.1" +_PIP_VERSION = "23.3.2" _PROJECTS = [ ("pip", _PIP_VERSION, "py3"), ] diff --git a/Lib/ensurepip/_bundled/pip-23.2.1-py3-none-any.whl b/Lib/ensurepip/_bundled/pip-23.2.1-py3-none-any.whl deleted file mode 100644 index ba28ef02e265f0..00000000000000 Binary files a/Lib/ensurepip/_bundled/pip-23.2.1-py3-none-any.whl and /dev/null differ diff --git a/Lib/ensurepip/_bundled/pip-23.3.2-py3-none-any.whl b/Lib/ensurepip/_bundled/pip-23.3.2-py3-none-any.whl new file mode 100644 index 00000000000000..ae78b8a6ce0737 Binary files /dev/null and b/Lib/ensurepip/_bundled/pip-23.3.2-py3-none-any.whl differ diff --git a/Lib/enum.py b/Lib/enum.py index 0c985b2c778569..a8a50a58380375 100644 --- a/Lib/enum.py +++ b/Lib/enum.py @@ -1,12 +1,10 @@ import sys import builtins as bltns from types import MappingProxyType, DynamicClassAttribute -from operator import or_ as _or_ -from functools import reduce __all__ = [ - 'EnumType', 'EnumMeta', + 'EnumType', 'EnumMeta', 'EnumDict', 'Enum', 'IntEnum', 'StrEnum', 'Flag', 'IntFlag', 'ReprEnum', 'auto', 'unique', 'property', 'verify', 'member', 'nonmember', 'FlagBoundary', 'STRICT', 'CONFORM', 'EJECT', 'KEEP', @@ -63,8 +61,8 @@ def _is_sunder(name): return ( len(name) > 2 and name[0] == name[-1] == '_' and - name[1:2] != '_' and - name[-2:-1] != '_' + name[1] != '_' and + name[-2] != '_' ) def _is_internal_class(cls_name, obj): @@ -83,7 +81,6 @@ def _is_private(cls_name, name): if ( len(name) > pat_len and name.startswith(pattern) - and name[pat_len:pat_len+1] != ['_'] and (name[-1] != '_' or name[-2] != '_') ): return True @@ -158,7 +155,6 @@ def _dedent(text): Like textwrap.dedent. Rewritten because we cannot import textwrap. """ lines = text.split('\n') - blanks = 0 for i, ch in enumerate(lines[0]): if ch != ' ': break @@ -317,45 +313,8 @@ def __set_name__(self, enum_class, member_name): ): # no other instances found, record this member in _member_names_ enum_class._member_names_.append(member_name) - # if necessary, get redirect in place and then add it to _member_map_ - found_descriptor = None - descriptor_type = None - class_type = None - for base in enum_class.__mro__[1:]: - attr = base.__dict__.get(member_name) - if attr is not None: - if isinstance(attr, (property, DynamicClassAttribute)): - found_descriptor = attr - class_type = base - descriptor_type = 'enum' - break - elif _is_descriptor(attr): - found_descriptor = attr - descriptor_type = descriptor_type or 'desc' - class_type = class_type or base - continue - else: - descriptor_type = 'attr' - class_type = base - if found_descriptor: - redirect = property() - redirect.member = enum_member - redirect.__set_name__(enum_class, member_name) - if descriptor_type in ('enum','desc'): - # earlier descriptor found; copy fget, fset, fdel to this one. - redirect.fget = getattr(found_descriptor, 'fget', None) - redirect._get = getattr(found_descriptor, '__get__', None) - redirect.fset = getattr(found_descriptor, 'fset', None) - redirect._set = getattr(found_descriptor, '__set__', None) - redirect.fdel = getattr(found_descriptor, 'fdel', None) - redirect._del = getattr(found_descriptor, '__delete__', None) - redirect._attr_type = descriptor_type - redirect._cls_type = class_type - setattr(enum_class, member_name, redirect) - else: - setattr(enum_class, member_name, enum_member) - # now add to _member_map_ (even aliases) - enum_class._member_map_[member_name] = enum_member + + enum_class._add_member_(member_name, enum_member) try: # This may fail if value is not hashable. We can't add the value # to the map, and by-value lookups for this value will be @@ -364,9 +323,10 @@ def __set_name__(self, enum_class, member_name): except TypeError: # keep track of the value in a list so containment checks are quick enum_class._unhashable_values_.append(value) + enum_class._unhashable_values_map_.setdefault(member_name, []).append(value) -class _EnumDict(dict): +class EnumDict(dict): """ Track enum member order and ensure member names are not reused. @@ -375,7 +335,7 @@ class _EnumDict(dict): """ def __init__(self): super().__init__() - self._member_names = {} # use a dict to keep insertion order + self._member_names = {} # use a dict -- faster look-up than a list, and keeps insertion order since 3.7 self._last_values = [] self._ignore = [] self._auto_called = False @@ -397,6 +357,7 @@ def __setitem__(self, key, value): '_order_', '_generate_next_value_', '_numeric_repr_', '_missing_', '_ignore_', '_iter_member_', '_iter_member_by_value_', '_iter_member_by_def_', + '_add_alias_', '_add_value_alias_', ): raise ValueError( '_sunder_ names, such as %r, are reserved for future Enum use' @@ -472,6 +433,10 @@ def __setitem__(self, key, value): self._last_values.append(value) super().__setitem__(key, value) + @property + def member_names(self): + return list(self._member_names) + def update(self, members, **more_members): try: for name in members.keys(): @@ -482,6 +447,8 @@ def update(self, members, **more_members): for name, value in more_members.items(): self[name] = value +_EnumDict = EnumDict # keep private name for backwards compatibility + class EnumType(type): """ @@ -493,7 +460,7 @@ def __prepare__(metacls, cls, bases, **kwds): # check that previous enum members do not exist metacls._check_for_existing_members_(cls, bases) # create the namespace dict - enum_dict = _EnumDict() + enum_dict = EnumDict() enum_dict._cls_name = cls # inherit previous flags and _generate_next_value_ function member_type, first_enum = metacls._get_mixins_(cls, bases) @@ -556,6 +523,7 @@ def __new__(metacls, cls, bases, classdict, *, boundary=None, _simple=False, **k classdict['_member_map_'] = {} classdict['_value2member_map_'] = {} classdict['_unhashable_values_'] = [] + classdict['_unhashable_values_map_'] = {} classdict['_member_type_'] = member_type # now set the __repr__ for the value classdict['_value_repr_'] = metacls._find_data_repr_(cls, bases) @@ -572,12 +540,16 @@ def __new__(metacls, cls, bases, classdict, *, boundary=None, _simple=False, **k try: exc = None enum_class = super().__new__(metacls, cls, bases, classdict, **kwds) - except RuntimeError as e: - # any exceptions raised by member.__new__ will get converted to a - # RuntimeError, so get that original exception back and raise it instead - exc = e.__cause__ or e + except Exception as e: + # since 3.12 the line "Error calling __set_name__ on '_proto_member' instance ..." + # is tacked on to the error instead of raising a RuntimeError + # recreate the exception to discard + exc = type(e)(str(e)) + exc.__cause__ = e.__cause__ + exc.__context__ = e.__context__ + tb = e.__traceback__ if exc is not None: - raise exc + raise exc.with_traceback(tb) # # update classdict with any changes made by __init_subclass__ classdict.update(enum_class.__dict__) @@ -730,6 +702,11 @@ def __call__(cls, value, names=None, *values, module=None, qualname=None, type=N value = (value, names) + values return cls.__new__(cls, value) # otherwise, functional API: we're creating a new Enum type + if names is None and type is None: + # no body? no data-type? possibly wrong usage + raise TypeError( + f"{cls} has no members; specify `names=()` if you meant to create a new, empty, enum" + ) return cls._create_( class_name=value, names=names, @@ -749,7 +726,10 @@ def __contains__(cls, value): """ if isinstance(value, cls): return True - return value in cls._value2member_map_ or value in cls._unhashable_values_ + try: + return value in cls._value2member_map_ + except TypeError: + return value in cls._unhashable_values_ def __delattr__(cls, attr): # nicer error message when someone tries to delete an attribute @@ -856,6 +836,8 @@ def _create_(cls, class_name, names, *, module=None, qualname=None, type=None, s value = first_enum._generate_next_value_(name, start, count, last_values[:]) last_values.append(value) names.append((name, value)) + if names is None: + names = () # Here, names is either an iterable of (name, value) or a mapping. for item in names: @@ -1043,7 +1025,57 @@ def _find_new_(mcls, classdict, member_type, first_enum): else: use_args = True return __new__, save_new, use_args -EnumMeta = EnumType + + def _add_member_(cls, name, member): + # _value_ structures are not updated + if name in cls._member_map_: + if cls._member_map_[name] is not member: + raise NameError('%r is already bound: %r' % (name, cls._member_map_[name])) + return + # + # if necessary, get redirect in place and then add it to _member_map_ + found_descriptor = None + descriptor_type = None + class_type = None + for base in cls.__mro__[1:]: + attr = base.__dict__.get(name) + if attr is not None: + if isinstance(attr, (property, DynamicClassAttribute)): + found_descriptor = attr + class_type = base + descriptor_type = 'enum' + break + elif _is_descriptor(attr): + found_descriptor = attr + descriptor_type = descriptor_type or 'desc' + class_type = class_type or base + continue + else: + descriptor_type = 'attr' + class_type = base + if found_descriptor: + redirect = property() + redirect.member = member + redirect.__set_name__(cls, name) + if descriptor_type in ('enum', 'desc'): + # earlier descriptor found; copy fget, fset, fdel to this one. + redirect.fget = getattr(found_descriptor, 'fget', None) + redirect._get = getattr(found_descriptor, '__get__', None) + redirect.fset = getattr(found_descriptor, 'fset', None) + redirect._set = getattr(found_descriptor, '__set__', None) + redirect.fdel = getattr(found_descriptor, 'fdel', None) + redirect._del = getattr(found_descriptor, '__delete__', None) + redirect._attr_type = descriptor_type + redirect._cls_type = class_type + setattr(cls, name, redirect) + else: + setattr(cls, name, member) + # now add to _member_map_ (even aliases) + cls._member_map_[name] = member + # + cls._member_map_[name] = member + +EnumMeta = EnumType # keep EnumMeta name for backwards compatibility class Enum(metaclass=EnumType): @@ -1109,9 +1141,14 @@ def __new__(cls, value): pass except TypeError: # not there, now do long search -- O(n) behavior - for member in cls._member_map_.values(): - if member._value_ == value: - return member + for name, values in cls._unhashable_values_map_.items(): + if value in values: + return cls[name] + # still not found -- verify that members exist, in-case somebody got here mistakenly + # (such as via super when trying to override __new__) + if not cls._member_map_: + raise TypeError("%r has no members defined" % cls) + # # still not found -- try _missing_ hook try: exc = None @@ -1147,6 +1184,33 @@ def __new__(cls, value): def __init__(self, *args, **kwds): pass + def _add_alias_(self, name): + self.__class__._add_member_(name, self) + + def _add_value_alias_(self, value): + cls = self.__class__ + try: + if value in cls._value2member_map_: + if cls._value2member_map_[value] is not self: + raise ValueError('%r is already bound: %r' % (value, cls._value2member_map_[value])) + return + except TypeError: + # unhashable value, do long search + for m in cls._member_map_.values(): + if m._value_ == value: + if m is not self: + raise ValueError('%r is already bound: %r' % (value, cls._value2member_map_[value])) + return + try: + # This may fail if value is not hashable. We can't add the value + # to the map, and by-value lookups for this value will be + # linear. + cls._value2member_map_.setdefault(value, self) + except TypeError: + # keep track of the value in a list so containment checks are quick + cls._unhashable_values_.append(value) + cls._unhashable_values_map_.setdefault(self.name, []).append(value) + @staticmethod def _generate_next_value_(name, start, count, last_values): """ @@ -1181,14 +1245,13 @@ def __str__(self): def __dir__(self): """ - Returns all members and all public methods + Returns public methods and other interesting attributes. """ - if self.__class__._member_type_ is object: - interesting = set(['__class__', '__doc__', '__eq__', '__hash__', '__module__', 'name', 'value']) - else: + interesting = set() + if self.__class__._member_type_ is not object: interesting = set(object.__dir__(self)) for name in getattr(self, '__dict__', []): - if name[0] != '_': + if name[0] != '_' and name not in self._member_map_: interesting.add(name) for cls in self.__class__.mro(): for name, obj in cls.__dict__.items(): @@ -1201,7 +1264,7 @@ def __dir__(self): else: # in case it was added by `dir(self)` interesting.discard(name) - else: + elif name not in self._member_map_: interesting.add(name) names = sorted( set(['__class__', '__doc__', '__eq__', '__hash__', '__module__']) @@ -1629,7 +1692,7 @@ def _simple_enum(etype=Enum, *, boundary=None, use_args=None): Class decorator that converts a normal class into an :class:`Enum`. No safety checks are done, and some advanced behavior (such as :func:`__init_subclass__`) is not available. Enum creation can be faster - using :func:`simple_enum`. + using :func:`_simple_enum`. >>> from enum import Enum, _simple_enum >>> @_simple_enum(Enum) @@ -1660,7 +1723,8 @@ def convert_class(cls): body['_member_names_'] = member_names = [] body['_member_map_'] = member_map = {} body['_value2member_map_'] = value2member_map = {} - body['_unhashable_values_'] = [] + body['_unhashable_values_'] = unhashable_values = [] + body['_unhashable_values_map_'] = {} body['_member_type_'] = member_type = etype._member_type_ body['_value_repr_'] = etype._value_repr_ if issubclass(etype, Flag): @@ -1707,14 +1771,9 @@ def convert_class(cls): for name, value in attrs.items(): if isinstance(value, auto) and auto.value is _auto_null: value = gnv(name, 1, len(member_names), gnv_last_values) - if value in value2member_map: + if value in value2member_map or value in unhashable_values: # an alias to an existing member - member = value2member_map[value] - redirect = property() - redirect.member = member - redirect.__set_name__(enum_class, name) - setattr(enum_class, name, redirect) - member_map[name] = member + enum_class(value)._add_alias_(name) else: # create the member if use_args: @@ -1729,12 +1788,12 @@ def convert_class(cls): member._name_ = name member.__objclass__ = enum_class member.__init__(value) - redirect = property() - redirect.member = member - redirect.__set_name__(enum_class, name) - setattr(enum_class, name, redirect) - member_map[name] = member member._sort_order_ = len(member_names) + if name not in ('name', 'value'): + setattr(enum_class, name, member) + member_map[name] = member + else: + enum_class._add_member_(name, member) value2member_map[value] = member if _is_single_bit(value): # not a multi-bit alias, record in _member_names_ and _flag_mask_ @@ -1757,14 +1816,13 @@ def convert_class(cls): if value.value is _auto_null: value.value = gnv(name, 1, len(member_names), gnv_last_values) value = value.value - if value in value2member_map: + try: + contained = value in value2member_map + except TypeError: + contained = value in unhashable_values + if contained: # an alias to an existing member - member = value2member_map[value] - redirect = property() - redirect.member = member - redirect.__set_name__(enum_class, name) - setattr(enum_class, name, redirect) - member_map[name] = member + enum_class(value)._add_alias_(name) else: # create the member if use_args: @@ -1780,14 +1838,22 @@ def convert_class(cls): member.__objclass__ = enum_class member.__init__(value) member._sort_order_ = len(member_names) - redirect = property() - redirect.member = member - redirect.__set_name__(enum_class, name) - setattr(enum_class, name, redirect) - member_map[name] = member - value2member_map[value] = member + if name not in ('name', 'value'): + setattr(enum_class, name, member) + member_map[name] = member + else: + enum_class._add_member_(name, member) member_names.append(name) gnv_last_values.append(value) + try: + # This may fail if value is not hashable. We can't add the value + # to the map, and by-value lookups for this value will be + # linear. + enum_class._value2member_map_.setdefault(value, member) + except TypeError: + # keep track of the value in a list so containment checks are quick + enum_class._unhashable_values_.append(value) + enum_class._unhashable_values_map_.setdefault(name, []).append(value) if '__new__' in body: enum_class.__new_member__ = enum_class.__new__ enum_class.__new__ = Enum.__new__ @@ -1872,7 +1938,8 @@ def __call__(self, enumeration): missed = [v for v in values if v not in member_values] if missed: missing_names.append(name) - missing_value |= reduce(_or_, missed) + for val in missed: + missing_value |= val if missing_names: if len(missing_names) == 1: alias = 'alias %s is missing' % missing_names[0] diff --git a/Lib/fnmatch.py b/Lib/fnmatch.py index d5e296f7748c1c..73acb1fe8d4106 100644 --- a/Lib/fnmatch.py +++ b/Lib/fnmatch.py @@ -78,6 +78,11 @@ def translate(pat): """ STAR = object() + parts = _translate(pat, STAR, '.') + return _join_translated_parts(parts, STAR) + + +def _translate(pat, STAR, QUESTION_MARK): res = [] add = res.append i, n = 0, len(pat) @@ -89,7 +94,7 @@ def translate(pat): if (not res) or res[-1] is not STAR: add(STAR) elif c == '?': - add('.') + add(QUESTION_MARK) elif c == '[': j = i if j < n and pat[j] == '!': @@ -146,9 +151,11 @@ def translate(pat): else: add(re.escape(c)) assert i == n + return res + +def _join_translated_parts(inp, STAR): # Deal with STARs. - inp = res res = [] add = res.append i, n = 0, len(inp) diff --git a/Lib/fractions.py b/Lib/fractions.py index c95db0730e5b6d..6532d5d54e3c35 100644 --- a/Lib/fractions.py +++ b/Lib/fractions.py @@ -139,6 +139,23 @@ def _round_to_figures(n, d, figures): return sign, significand, exponent +# Pattern for matching non-float-style format specifications. +_GENERAL_FORMAT_SPECIFICATION_MATCHER = re.compile(r""" + (?: + (?P.)? + (?P[<>=^]) + )? + (?P[-+ ]?) + # Alt flag forces a slash and denominator in the output, even for + # integer-valued Fraction objects. + (?P\#)? + # We don't implement the zeropad flag since there's no single obvious way + # to interpret it. + (?P0|[1-9][0-9]*)? + (?P[,_])? +""", re.DOTALL | re.VERBOSE).fullmatch + + # Pattern for matching float-style format specifications; # supports 'e', 'E', 'f', 'F', 'g', 'G' and '%' presentation types. _FLOAT_FORMAT_SPECIFICATION_MATCHER = re.compile(r""" @@ -414,27 +431,42 @@ def __str__(self): else: return '%s/%s' % (self._numerator, self._denominator) - def __format__(self, format_spec, /): - """Format this fraction according to the given format specification.""" - - # Backwards compatiblility with existing formatting. - if not format_spec: - return str(self) + def _format_general(self, match): + """Helper method for __format__. + Handles fill, alignment, signs, and thousands separators in the + case of no presentation type. + """ # Validate and parse the format specifier. - match = _FLOAT_FORMAT_SPECIFICATION_MATCHER(format_spec) - if match is None: - raise ValueError( - f"Invalid format specifier {format_spec!r} " - f"for object of type {type(self).__name__!r}" - ) - elif match["align"] is not None and match["zeropad"] is not None: - # Avoid the temptation to guess. - raise ValueError( - f"Invalid format specifier {format_spec!r} " - f"for object of type {type(self).__name__!r}; " - "can't use explicit alignment when zero-padding" - ) + fill = match["fill"] or " " + align = match["align"] or ">" + pos_sign = "" if match["sign"] == "-" else match["sign"] + alternate_form = bool(match["alt"]) + minimumwidth = int(match["minimumwidth"] or "0") + thousands_sep = match["thousands_sep"] or '' + + # Determine the body and sign representation. + n, d = self._numerator, self._denominator + if d > 1 or alternate_form: + body = f"{abs(n):{thousands_sep}}/{d:{thousands_sep}}" + else: + body = f"{abs(n):{thousands_sep}}" + sign = '-' if n < 0 else pos_sign + + # Pad with fill character if necessary and return. + padding = fill * (minimumwidth - len(sign) - len(body)) + if align == ">": + return padding + sign + body + elif align == "<": + return sign + body + padding + elif align == "^": + half = len(padding) // 2 + return padding[:half] + sign + body + padding[half:] + else: # align == "=" + return sign + padding + body + + def _format_float_style(self, match): + """Helper method for __format__; handles float presentation types.""" fill = match["fill"] or " " align = match["align"] or ">" pos_sign = "" if match["sign"] == "-" else match["sign"] @@ -530,6 +562,23 @@ def __format__(self, format_spec, /): else: # align == "=" return sign + padding + body + def __format__(self, format_spec, /): + """Format this fraction according to the given format specification.""" + + if match := _GENERAL_FORMAT_SPECIFICATION_MATCHER(format_spec): + return self._format_general(match) + + if match := _FLOAT_FORMAT_SPECIFICATION_MATCHER(format_spec): + # Refuse the temptation to guess if both alignment _and_ + # zero padding are specified. + if match["align"] is None or match["zeropad"] is None: + return self._format_float_style(match) + + raise ValueError( + f"Invalid format specifier {format_spec!r} " + f"for object of type {type(self).__name__!r}" + ) + def _operator_fallbacks(monomorphic_operator, fallback_operator): """Generates forward and reverse operators given a purely-rational operator and a function from the operator module. diff --git a/Lib/functools.py b/Lib/functools.py index 8518450a8d499d..55990e742bf23f 100644 --- a/Lib/functools.py +++ b/Lib/functools.py @@ -19,8 +19,9 @@ # import types, weakref # Deferred to single_dispatch() from reprlib import recursive_repr from _thread import RLock -from types import GenericAlias +# Avoid importing types, so we can speedup import time +GenericAlias = type(list[int]) ################################################################################ ### update_wrapper() and wraps() decorator @@ -236,7 +237,7 @@ def __ge__(self, other): def reduce(function, sequence, initial=_initial_missing): """ - reduce(function, iterable[, initial]) -> value + reduce(function, iterable[, initial], /) -> value Apply a function of two arguments cumulatively to the items of a sequence or iterable, from left to right, so as to reduce the iterable to a single @@ -934,6 +935,9 @@ def __init__(self, func): self.dispatcher = singledispatch(func) self.func = func + import weakref # see comment in singledispatch function + self._method_cache = weakref.WeakKeyDictionary() + def register(self, cls, method=None): """generic_method.register(cls, func) -> func @@ -942,13 +946,27 @@ def register(self, cls, method=None): return self.dispatcher.register(cls, func=method) def __get__(self, obj, cls=None): + if self._method_cache is not None: + try: + _method = self._method_cache[obj] + except TypeError: + self._method_cache = None + except KeyError: + pass + else: + return _method + + dispatch = self.dispatcher.dispatch def _method(*args, **kwargs): - method = self.dispatcher.dispatch(args[0].__class__) - return method.__get__(obj, cls)(*args, **kwargs) + return dispatch(args[0].__class__).__get__(obj, cls)(*args, **kwargs) _method.__isabstractmethod__ = self.__isabstractmethod__ _method.register = self.register update_wrapper(_method, self.func) + + if self._method_cache is not None: + self._method_cache[obj] = _method + return _method @property @@ -967,6 +985,7 @@ def __init__(self, func): self.func = func self.attrname = None self.__doc__ = func.__doc__ + self.__module__ = func.__module__ def __set_name__(self, owner, name): if self.attrname is None: diff --git a/Lib/getpass.py b/Lib/getpass.py index 6970d8adfbab36..bd0097ced94c5e 100644 --- a/Lib/getpass.py +++ b/Lib/getpass.py @@ -18,7 +18,6 @@ import io import os import sys -import warnings __all__ = ["getpass","getuser","GetPassWarning"] @@ -118,6 +117,7 @@ def win_getpass(prompt='Password: ', stream=None): def fallback_getpass(prompt='Password: ', stream=None): + import warnings warnings.warn("Can not control echo on the terminal.", GetPassWarning, stacklevel=2) if not stream: @@ -156,7 +156,11 @@ def getuser(): First try various environment variables, then the password database. This works on Windows as long as USERNAME is set. + Any failure to find a username raises OSError. + .. versionchanged:: 3.13 + Previously, various exceptions beyond just :exc:`OSError` + were raised. """ for name in ('LOGNAME', 'USER', 'LNAME', 'USERNAME'): @@ -164,9 +168,12 @@ def getuser(): if user: return user - # If this fails, the exception will "explain" why - import pwd - return pwd.getpwuid(os.getuid())[0] + try: + import pwd + return pwd.getpwuid(os.getuid())[0] + except (ImportError, KeyError) as e: + raise OSError('No username set in the environment') from e + # Bind the name getpass to the appropriate function try: diff --git a/Lib/gettext.py b/Lib/gettext.py index b72b15f82d4355..62cff81b7b3d49 100644 --- a/Lib/gettext.py +++ b/Lib/gettext.py @@ -46,6 +46,7 @@ # find this format documented anywhere. +import operator import os import re import sys @@ -166,14 +167,28 @@ def _parse(tokens, priority=-1): def _as_int(n): try: - i = round(n) + round(n) except TypeError: raise TypeError('Plural value must be an integer, got %s' % (n.__class__.__name__,)) from None + return _as_int2(n) + +def _as_int2(n): + try: + return operator.index(n) + except TypeError: + pass + import warnings + frame = sys._getframe(1) + stacklevel = 2 + while frame.f_back is not None and frame.f_globals.get('__name__') == __name__: + stacklevel += 1 + frame = frame.f_back warnings.warn('Plural value must be an integer, got %s' % (n.__class__.__name__,), - DeprecationWarning, 4) + DeprecationWarning, + stacklevel) return n @@ -200,7 +215,7 @@ def c2py(plural): elif c == ')': depth -= 1 - ns = {'_as_int': _as_int} + ns = {'_as_int': _as_int, '__name__': __name__} exec('''if True: def func(n): if not isinstance(n, int): @@ -280,6 +295,7 @@ def gettext(self, message): def ngettext(self, msgid1, msgid2, n): if self._fallback: return self._fallback.ngettext(msgid1, msgid2, n) + n = _as_int2(n) if n == 1: return msgid1 else: @@ -293,6 +309,7 @@ def pgettext(self, context, message): def npgettext(self, context, msgid1, msgid2, n): if self._fallback: return self._fallback.npgettext(context, msgid1, msgid2, n) + n = _as_int2(n) if n == 1: return msgid1 else: @@ -579,6 +596,7 @@ def dngettext(domain, msgid1, msgid2, n): try: t = translation(domain, _localedirs.get(domain, None)) except OSError: + n = _as_int2(n) if n == 1: return msgid1 else: @@ -598,6 +616,7 @@ def dnpgettext(domain, context, msgid1, msgid2, n): try: t = translation(domain, _localedirs.get(domain, None)) except OSError: + n = _as_int2(n) if n == 1: return msgid1 else: diff --git a/Lib/glob.py b/Lib/glob.py index a7256422d520fb..4a335a10766cf4 100644 --- a/Lib/glob.py +++ b/Lib/glob.py @@ -249,3 +249,63 @@ def escape(pathname): _dir_open_flags = os.O_RDONLY | getattr(os, 'O_DIRECTORY', 0) + + +def translate(pat, *, recursive=False, include_hidden=False, seps=None): + """Translate a pathname with shell wildcards to a regular expression. + + If `recursive` is true, the pattern segment '**' will match any number of + path segments; if '**' appears outside its own segment, ValueError will be + raised. + + If `include_hidden` is true, wildcards can match path segments beginning + with a dot ('.'). + + If a sequence of separator characters is given to `seps`, they will be + used to split the pattern into segments and match path separators. If not + given, os.path.sep and os.path.altsep (where available) are used. + """ + if not seps: + if os.path.altsep: + seps = (os.path.sep, os.path.altsep) + else: + seps = os.path.sep + escaped_seps = ''.join(map(re.escape, seps)) + any_sep = f'[{escaped_seps}]' if len(seps) > 1 else escaped_seps + not_sep = f'[^{escaped_seps}]' + if include_hidden: + one_last_segment = f'{not_sep}+' + one_segment = f'{one_last_segment}{any_sep}' + any_segments = f'(?:.+{any_sep})?' + any_last_segments = '.*' + else: + one_last_segment = f'[^{escaped_seps}.]{not_sep}*' + one_segment = f'{one_last_segment}{any_sep}' + any_segments = f'(?:{one_segment})*' + any_last_segments = f'{any_segments}(?:{one_last_segment})?' + + results = [] + parts = re.split(any_sep, pat) + last_part_idx = len(parts) - 1 + for idx, part in enumerate(parts): + if part == '*': + results.append(one_segment if idx < last_part_idx else one_last_segment) + continue + if recursive: + if part == '**': + if idx < last_part_idx: + if parts[idx + 1] != '**': + results.append(any_segments) + else: + results.append(any_last_segments) + continue + elif '**' in part: + raise ValueError("Invalid pattern: '**' can only be an entire path component") + if part: + if not include_hidden and part[0] in '*?': + results.append(r'(?!\.)') + results.extend(fnmatch._translate(part, f'{not_sep}*', not_sep)) + if idx < last_part_idx: + results.append(any_sep) + res = ''.join(results) + return fr'(?s:{res})\Z' diff --git a/Lib/gzip.py b/Lib/gzip.py index cf8b675064ce89..177f9080dc5af8 100644 --- a/Lib/gzip.py +++ b/Lib/gzip.py @@ -401,6 +401,9 @@ def seekable(self): def seek(self, offset, whence=io.SEEK_SET): if self.mode == WRITE: + self._check_not_closed() + # Flush buffer to ensure validity of self.offset + self._buffer.flush() if whence != io.SEEK_SET: if whence == io.SEEK_CUR: offset = self.offset + offset diff --git a/Lib/hmac.py b/Lib/hmac.py index 8b4f920db954ca..8b4eb2fe741e60 100644 --- a/Lib/hmac.py +++ b/Lib/hmac.py @@ -53,7 +53,7 @@ def __init__(self, key, msg=None, digestmod=''): raise TypeError("key: expected bytes or bytearray, but got %r" % type(key).__name__) if not digestmod: - raise TypeError("Missing required parameter 'digestmod'.") + raise TypeError("Missing required argument 'digestmod'.") if _hashopenssl and isinstance(digestmod, (str, _functype)): try: diff --git a/Lib/http/client.py b/Lib/http/client.py index b35b1d6368aae7..5eebfccafbca59 100644 --- a/Lib/http/client.py +++ b/Lib/http/client.py @@ -172,6 +172,13 @@ def _encode(data, name='data'): "if you want to send it encoded in UTF-8." % (name.title(), data[err.start:err.end], name)) from None +def _strip_ipv6_iface(enc_name: bytes) -> bytes: + """Remove interface scope from IPv6 address.""" + enc_name, percent, _ = enc_name.partition(b"%") + if percent: + assert enc_name.startswith(b'['), enc_name + enc_name += b']' + return enc_name class HTTPMessage(email.message.Message): # XXX The only usage of this method is in @@ -658,6 +665,8 @@ def read1(self, n=-1): self._close_conn() elif self.length is not None: self.length -= len(result) + if not self.length: + self._close_conn() return result def peek(self, n=-1): @@ -682,6 +691,8 @@ def readline(self, limit=-1): self._close_conn() elif self.length is not None: self.length -= len(result) + if not self.length: + self._close_conn() return result def _read1_chunked(self, n): @@ -1194,7 +1205,7 @@ def putrequest(self, method, url, skip_host=False, netloc_enc = netloc.encode("ascii") except UnicodeEncodeError: netloc_enc = netloc.encode("idna") - self.putheader('Host', netloc_enc) + self.putheader('Host', _strip_ipv6_iface(netloc_enc)) else: if self._tunnel_host: host = self._tunnel_host @@ -1211,8 +1222,9 @@ def putrequest(self, method, url, skip_host=False, # As per RFC 273, IPv6 address should be wrapped with [] # when used as Host header - if host.find(':') >= 0: + if ":" in host: host_enc = b'[' + host_enc + b']' + host_enc = _strip_ipv6_iface(host_enc) if port == self.default_port: self.putheader('Host', host_enc) diff --git a/Lib/http/server.py b/Lib/http/server.py index ca6240d9a921e6..ee7a9b6aa55b88 100644 --- a/Lib/http/server.py +++ b/Lib/http/server.py @@ -2,18 +2,18 @@ Note: BaseHTTPRequestHandler doesn't implement any HTTP request; see SimpleHTTPRequestHandler for simple implementations of GET, HEAD and POST, -and CGIHTTPRequestHandler for CGI scripts. +and (deprecated) CGIHTTPRequestHandler for CGI scripts. -It does, however, optionally implement HTTP/1.1 persistent connections, -as of version 0.3. +It does, however, optionally implement HTTP/1.1 persistent connections. Notes on CGIHTTPRequestHandler ------------------------------ -This class implements GET and POST requests to cgi-bin scripts. +This class is deprecated. It implements GET and POST requests to cgi-bin scripts. -If the os.fork() function is not present (e.g. on Windows), -subprocess.Popen() is used as a fallback, with slightly altered semantics. +If the os.fork() function is not present (Windows), subprocess.Popen() is used, +with slightly altered but never documented semantics. Use from a threaded +process is likely to trigger a warning at os.fork() time. In all cases, the implementation is intentionally naive -- all requests are executed synchronously. @@ -986,6 +986,12 @@ class CGIHTTPRequestHandler(SimpleHTTPRequestHandler): """ + def __init__(self, *args, **kwargs): + import warnings + warnings._deprecated("http.server.CGIHTTPRequestHandler", + remove=(3, 15)) + super().__init__(*args, **kwargs) + # Determine platform specifics have_fork = hasattr(os, 'fork') diff --git a/Lib/idlelib/NEWS.txt b/Lib/idlelib/NEWS.txt deleted file mode 100644 index f258797c6e0fb3..00000000000000 --- a/Lib/idlelib/NEWS.txt +++ /dev/null @@ -1,1340 +0,0 @@ -What's New in IDLE 3.12.0 -(since 3.11.0) -Released on 2023-10-02 -========================= - - -gh-104719: Remove IDLE's modification of tokenize.tabsize and test -other uses of tokenize data and methods. - -gh-104499: Fix completions for Tk Aqua 8.7 (currently blank). - -gh-104486: Make About print both tcl and tk versions if different, -as is expected someday. - -gh-88496 Fix IDLE test hang on macOS. - -gh-103314 Support sys.last_exc after exceptions in Shell. -Patch by Irit Katriel. - - -What's New in IDLE 3.11.0 -(since 3.10.0) -Released on 2022-10-24 -========================= - -gh-97527: Fix a bug in the previous bugfix that caused IDLE to not -start when run with 3.10.8, 3.12.0a1, and at least Microsoft Python -3.10.2288.0 installed without the Lib/test package. 3.11.0 was never -affected. - -gh-65802: Document handling of extensions in Save As dialogs. - -gh-95191: Include prompts when saving Shell (interactive input/output). - -gh-95511: Fix the Shell context menu copy-with-prompts bug of copying -an extra line when one selects whole lines. - -gh-95471: Tweak Edit menu. Move 'Select All' above 'Cut' as it is used -with 'Cut' and 'Copy' but not 'Paste'. Add a separator between 'Replace' -and 'Go to Line' to help IDLE issue triagers. - -gh-95411: Enable using IDLE's module browser with .pyw files. - -gh-89610: Add .pyi as a recognized extension for IDLE on macOS. This allows -opening stub files by double clicking on them in the Finder. - -bpo-28950: Apply IDLE syntax highlighting to `.pyi` files. Add util.py -for common components. Patch by Alex Waygood and Terry Jan Reedy. - -bpo-46630: Make query dialogs on Windows start with a cursor in the -entry box. - -bpo-46591: Make the IDLE doc URL on the About IDLE dialog clickable. - -bpo-45296: Clarify close, quit, and exit in IDLE. In the File menu, -'Close' and 'Exit' are now 'Close Window' (the current one) and 'Exit' -is now 'Exit IDLE' (by closing all windows). In Shell, 'quit()' and -'exit()' mean 'close Shell'. If there are no other windows, -this also exits IDLE. - -bpo-45495: Add context keywords 'case' and 'match' to completions list. - -bpo-45296: On Windows, change exit/quit message to suggest Ctrl-D, which -works, instead of , which does not work in IDLE. - - -What's New in IDLE 3.10.0 -(since 3.9.0) -Released on 2021-10-04 -========================= - -bpo-45193: Make completion boxes appear on Ubuntu again. - -bpo-40128: Mostly fix completions on macOS when not using tcl/tk 8.6.11 -(as with 3.9). - -bpo-33962: Move the indent space setting from the Font tab to the new Windows -tab. Patch by Mark Roseman and Terry Jan Reedy. - -bpo-40468: Split the settings dialog General tab into Windows and Shell/Ed -tabs. Move help sources, which extend the Help menu, to the Extensions tab. -Make space for new options and shorten the dialog. The latter makes the -dialog better fit small screens. - -bpo-44010: Highlight the new match statement's soft keywords: match, case, -and _. This highlighting is not perfect and will be incorrect in some rare -cases, especially for some _s in case patterns. - -bpo-44026: Include interpreter's typo fix suggestions in message line -for NameErrors and AttributeErrors. Patch by E. Paine. - -bpo-41611: Avoid occasional uncaught exceptions and freezing when using -completions on macOS. - -bpo-37903: Add mouse actions to the shell sidebar. Left click and -optional drag selects one or more lines of text, as with the -editor line number sidebar. Right click after selecting text lines -displays a context menu with 'copy with prompts'. This zips together -prompts from the sidebar with lines from the selected text. This option -also appears on the context menu for the text. - -bpo-43981: Fix reference leaks in test_sidebar and test_squeezer. -Patches by Terry Jan Reedy and Pablo Galindo - -bpo-37892: Change Shell input indents from tabs to spaces. Shell input -now 'looks right'. Making this feasible motivated the shell sidebar. - -bpo-37903: Move the Shell input prompt to a side bar. - -bpo-43655: Make window managers on macOS and X Window recognize -IDLE dialog windows as dialogs. - -bpo-42225: Document that IDLE can fail on Unix either from misconfigured IP -masquerade rules or failure displaying complex colored (non-ascii) characters. - -bpo-43283: Document why printing to IDLE's Shell is often slower than -printing to a system terminal and that it can be made faster by -pre-formatting a single string before printing. - -bpo-23544: Disable Debug=>Stack Viewer when user code is running or -Debugger is active, to prevent hang or crash. Patch by Zackery Spytz. - -bpo-43008: Make IDLE invoke :func:`sys.excepthook` in normal, -2-process mode. User hooks were previously ignored. -Patch by Ken Hilton. - -bpo-33065: Fix problem debugging user classes with __repr__ method. - -bpo-32631: Finish zzdummy example extension module: make menu entries -work; add docstrings and tests with 100% coverage. - -bpo-42508: Keep IDLE running on macOS. Remove obsolete workaround -that prevented running files with shortcuts when using new universal2 -installers built on macOS 11. - -bpo-42426: Fix reporting offset of the RE error in searchengine. - -bpo-42416: Display docstrings in IDLE calltips in more cases, -by using inspect.getdoc. - -bpo-33987: Mostly finish using ttk widgets, mainly for editor, -settings, and searches. Some patches by Mark Roseman. - -bpo-40511: Stop unnecessary "flashing" when typing opening and closing -parentheses inside the parentheses of a function call. - -bpo-38439: Add a 256x256 pixel IDLE icon to the Windows .ico file. Created by -Andrew Clover. Remove the low-color gif variations from the .ico file. - -bpo-41775: Make 'IDLE Shell' the shell title. - -bpo-35764: Rewrite the Calltips doc section. - -bpo-40181: In calltips, stop reminding that '/' marks the end of -positional-only arguments. - - -What's New in IDLE 3.9.0 (since 3.8.0) -Released on 2020-10-05? -====================================== - -bpo-41468: Improve IDLE run crash error message (which users should -never see). - -bpo-41373: Save files loaded with no line ending, as when blank, or -different line endings, by setting its line ending to the system -default. Fix regression in 3.8.4 and 3.9.0b4. - -bpo-41300: Save files with non-ascii chars. Fix regression in -3.9.0b4 and 3.8.4. - -bpo-37765: Add keywords to module name completion list. Rewrite -Completions section of IDLE doc. - -bpo-41152: The encoding of ``stdin``, ``stdout`` and ``stderr`` in IDLE -is now always UTF-8. - -bpo-41144: Make Open Module open a special module such as os.path. - -bpo-40723: Make test_idle pass when run after import. -Patch by Florian Dahlitz. - -bpo-38689: IDLE will no longer freeze when inspect.signature fails -when fetching a calltip. - -bpo-27115: For 'Go to Line', use a Query entry box subclass with -IDLE standard behavior and improved error checking. - -bpo-39885: When a context menu is invoked by right-clicking outside -of a selection, clear the selection and move the cursor. Cut and -Copy require that the click be within the selection. - -bpo-39852: Edit "Go to line" now clears any selection, preventing -accidental deletion. It also updates Ln and Col on the status bar. - -bpo-39781: Selecting code context lines no longer causes a jump. - -bpo-39663: Add tests for pyparse find_good_parse_start(). - -bpo-39600: Remove duplicate font names from configuration list. - -bpo-38792: Close a shell calltip if a :exc:`KeyboardInterrupt` -or shell restart occurs. Patch by Zackery Spytz. - -bpo-30780: Add remaining configdialog tests for buttons and -highlights and keys tabs. - -bpo-39388: Settings dialog Cancel button cancels pending changes. - -bpo-39050: Settings dialog Help button again displays help text. - -bpo-32989: Add tests for editor newline_and_indent_event method. -Remove unneeded arguments and dead code from pyparse -find_good_parse_start method. - -bpo-38943: Fix autocomplete windows not always appearing on some -systems. Patch by Johnny Najera. - -bpo-38944: Escape key now closes IDLE completion windows. Patch by -Johnny Najera. - -bpo-38862: 'Strip Trailing Whitespace' on the Format menu removes extra -newlines at the end of non-shell files. - -bpo-38636: Fix IDLE Format menu tab toggle and file indent width. These -functions (default shortcuts Alt-T and Alt-U) were mistakenly disabled -in 3.7.5 and 3.8.0. - -bpo-4630: Add an option to toggle IDLE's cursor blink for shell, -editor, and output windows. See Settings, General, Window Preferences, -Cursor Blink. Patch by Zackery Spytz. - -bpo-26353: Stop adding newline when saving an IDLE shell window. - -bpo-38598: Do not try to compile IDLE shell or output windows. - - -What's New in IDLE 3.8.0 (since 3.7.0) -Released on 2019-10-14 -====================================== - -bpo-36698: IDLE no longer fails when writing non-encodable characters -to stderr. It now escapes them with a backslash, like the regular -Python interpreter. Add an errors field to the standard streams. - -bpo-13153: Improve tkinter's handing of non-BMP (astral) unicode -characters, such as 'rocket \U0001f680'. Whether a proper glyph or -replacement char is displayed depends on the OS and font. For IDLE, -astral chars in code interfere with editing. - -bpo-35379: When exiting IDLE, catch any AttributeError. One happens -when EditorWindow.close is called twice. Printing a traceback, when -IDLE is run from a terminal, is useless and annoying. - -bpo-38183: To avoid test issues, test_idle ignores the user config -directory. It no longer tries to create or access .idlerc or any files -within. Users must run IDLE to discover problems with saving settings. - -bpo-38077: IDLE no longer adds 'argv' to the user namespace when -initializing it. This bug only affected 3.7.4 and 3.8.0b2 to 3.8.0b4. - -bpo-38401: Shell restart lines now fill the window width, always start -with '=', and avoid wrapping unnecessarily. The line will still wrap -if the included file name is long relative to the width. - -bpo-37092: Add mousewheel scrolling for IDLE module, path, and stack -browsers. Patch by George Zhang. - -bpo-35771: To avoid occasional spurious test_idle failures on slower -machines, increase the ``hover_delay`` in test_tooltip. - -bpo-37824: Properly handle user input warnings in IDLE shell. -Cease turning SyntaxWarnings into SyntaxErrors. - -bpo-37929: IDLE Settings dialog now closes properly when there is no -shell window. - -bpo-37849: Fix completions list appearing too high or low when shown -above the current line. - -bpo-36419: Refactor autocompete and improve testing. - -bpo-37748: Reorder the Run menu. Put the most common choice, -Run Module, at the top. - -bpo-37692: Improve highlight config sample with example shell -interaction and better labels for shell elements. - -bpo-37628: Settings dialog no longer expands with font size. -The font and highlight sample boxes gain scrollbars instead. - -bpo-17535: Add optional line numbers for IDLE editor windows. - -bpo-37627: Initialize the Customize Run dialog with the command line -arguments most recently entered before. The user can optionally edit -before submitting them. - -bpo-33610: Code context always shows the correct context when toggled on. - -bpo-36390: Gather Format menu functions into format.py. Combine -paragraph.py, rstrip.py, and format methods from editor.py. - -bpo-37530: Optimize code context to reduce unneeded background activity. -Font and highlight changes now occur along with text changes instead -of after a random delay. - -bpo-27452: Cleanup config.py by inlining RemoveFile and simplifying -the handling of __file__ in CreateConfigHandlers/ - -bpo-26806: To compensate for stack frames added by IDLE and avoid -possible problems with low recursion limits, add 30 to limits in the -user code execution process. Subtract 30 when reporting recursion -limits to make this addition mostly transparent. - -bpo-37325: Fix tab focus traversal order for help source and custom -run dialogs. - -bpo-37321: Both subprocess connection error messages now refer to -the 'Startup failure' section of the IDLE doc. - -bpo-37177: Properly attach search dialogs to their main window so -that they behave like other dialogs and do not get hidden behind -their main window. - -bpo-37039: Adjust "Zoom Height" to individual screens by momentarily -maximizing the window on first use with a particular screen. Changing -screen settings may invalidate the saved height. While a window is -maximized, "Zoom Height" has no effect. - -bpo-35763: Make calltip reminder about '/' meaning positional-only less -obtrusive by only adding it when there is room on the first line. - -bpo-5680: Add 'Run Customized' to the Run menu to run a module with -customized settings. Any command line arguments entered are added -to sys.argv. One can suppress the normal Shell main module restart. - -bpo-35610: Replace now redundant editor.context_use_ps1 with -.prompt_last_line. This finishes change started in bpo-31858. - -bpo-32411: Stop sorting dict created with desired line order. - -bpo-37038: Make idlelib.run runnable; add test clause. - -bpo-36958: Print any argument other than None or int passed to -SystemExit or sys.exit(). - -bpo-36807: When saving a file, call file.flush() and os.fsync() -so bits are flushed to e.g. a USB drive. - -bpo-36429: Fix starting IDLE with pyshell. -Add idlelib.pyshell alias at top; remove pyshell alias at bottom. -Remove obsolete __name__=='__main__' command. - -bpo-30348: Increase test coverage of idlelib.autocomplete by 30%. -Patch by Louie Lu. - -bpo-23205: Add tests and refactor grep's findfiles. - -bpo-36405: Use dict unpacking in idlelib. - -bpo-36396: Remove fgBg param of idlelib.config.GetHighlight(). -This param was only used twice and changed the return type. - -bpo-23216: IDLE: Add docstrings to search modules. - -bpo-36176: Fix IDLE autocomplete & calltip popup colors. -Prevent conflicts with Linux dark themes -(and slightly darken calltip background). - -bpo-36152: Remove colorizer.ColorDelegator.close_when_done and the -corresponding argument of .close(). In IDLE, both have always been -None or False since 2007. - -bpo-36096: Make colorizer state variables instance-only. - -bpo-32129: Avoid blurry IDLE application icon on macOS with Tk 8.6. -Patch by Kevin Walzer. - -bpo-24310: Document settings dialog font tab sample. - -bpo-35689: Add docstrings and tests for colorizer. - -bpo-35833: Revise IDLE doc for control codes sent to Shell. -Add a code example block. - -bpo-35770: IDLE macosx deletes Options => Configure IDLE. -It previously deleted Window => Zoom Height by mistake. -(Zoom Height is now on the Options menu). On Mac, the settings -dialog is accessed via Preferences on the IDLE menu. - -bpo-35769: Change new file name from 'Untitled' to 'untitled'. - -bpo-35660: Fix imports in window module. - -bpo-35641: Properly format calltip for function without docstring. - -bpo-33987: Use ttk Frame for ttk widgets. - -bpo-34055: Fix erroneous 'smart' indents and newlines in IDLE Shell. - -bpo-28097: Add Previous/Next History entries to Shell menu. - -bpo-35591: Find Selection now works when selection not found. - -bpo-35598: Update config_key: use PEP 8 names and ttk widgets, -make some objects global, and add tests. - -bpo-35196: Speed up squeezer line counting. - -bpo-35208: Squeezer now counts wrapped lines before newlines. - -bpo-35555: Gray out Code Context menu entry when it's not applicable. - -bpo-22703: Improve the Code Context and Zoom Height menu labels. -The Code Context menu label now toggles between Show/Hide Code Context. -The Zoom Height menu now toggles between Zoom/Restore Height. -Zoom Height has moved from the Window menu to the Options menu. - -bpo-35521: Document the editor code context feature. -Add some internal references within the IDLE doc. - -bpo-34864: When starting IDLE on MacOS, warn if the system setting -"Prefer tabs when opening documents" is "Always". As previous -documented for this issue, running IDLE with this setting causes -problems. If the setting is changed while IDLE is running, -there will be no warning until IDLE is restarted. - -bpo-35213: Where appropriate, use 'macOS' in idlelib. - -bpo-34864: Document two IDLE on MacOS issues. The System Preferences -Dock "prefer tabs always" setting disables some IDLE features. -Menus are a bit different than as described for Windows and Linux. - -bpo-35202: Remove unused imports in idlelib. - -bpo-33000: Document that IDLE's shell has no line limit. -A program that runs indefinitely can overfill memory. - -bpo-23220: Explain how IDLE's Shell displays output. -Add new subsection "User output in Shell". - -bpo-35099: Improve the doc about IDLE running user code. -"IDLE -- console differences" is renamed "Running user code". -It mostly covers the implications of using custom sys.stdxxx objects. - -bpo-35097: Add IDLE doc subsection explaining editor windows. -Topics include opening, title and status bars, .py* extension, and running. - -Issue 35093: Document the IDLE document viewer in the IDLE doc. -Add a paragraph in "Help and preferences", "Help sources" subsection. - -bpo-1529353: Explain Shell text squeezing in the IDLE doc. - -bpo-35088: Update idlelib.help.copy_string docstring. -We now use git and backporting instead of hg and forward merging. - -bpo-35087: Update idlelib help files for the current doc build. -The main change is the elimination of chapter-section numbers. - -bpo-1529353: Output over N lines (50 by default) is squeezed down to a button. -N can be changed in the PyShell section of the General page of the -Settings dialog. Fewer, but possibly extra long, lines can be squeezed by -right clicking on the output. Squeezed output can be expanded in place -by double-clicking the button or into the clipboard or a separate window -by right-clicking the button. - -bpo-34548: Use configured color theme for read-only text views. - -bpo-33839: Refactor ToolTip and CallTip classes; add documentation -and tests. - -bpo-34047: Fix mouse wheel scrolling direction on macOS. - -bpo-34275: Make calltips always visible on Mac. -Patch by Kevin Walzer. - -bpo-34120: Fix freezing after closing some dialogs on Mac. -This is one of multiple regressions from using newer tcl/tk. - -bpo-33975: Avoid small type when running htests. -Since part of the purpose of human-viewed tests is to determine that -widgets look right, it is important that they look the same for -testing as when running IDLE. - -bpo-33905: Add test for idlelib.stackview.StackBrowser. - -bpo-33924: Change mainmenu.menudefs key 'windows' to 'window'. -Every other menudef key is the lowercase version of the -corresponding main menu entry (in this case, 'Window'). - -bpo-33906: Rename idlelib.windows as window -Match Window on the main menu and remove last plural module name. -Change imports, test, and attribute references to match new name. - -bpo-33917: Fix and document idlelib/idle_test/template.py. -The revised file compiles, runs, and tests OK. idle_test/README.txt -explains how to use it to create new IDLE test files. - -bpo-33904: In rstrip module, rename class RstripExtension as Rstrip. - -bpo-33907: For consistency and clarity, rename calltip objects. -Module calltips and its class CallTips are now calltip and Calltip. -In module calltip_w, class CallTip is now CalltipWindow. - -bpo-33855: Minimally test all IDLE modules. -Standardize the test file format. Add missing test files that import -the tested module and perform at least one test. Check and record the -coverage of each test. - -bpo-33856: Add 'help' to Shell's initial welcome message. - - -What's New in IDLE 3.7.0 (since 3.6.0) -Released on 2018-06-27 -====================================== - -bpo-33656: On Windows, add API call saying that tk scales for DPI. -On Windows 8.1+ or 10, with DPI compatibility properties of the Python -binary unchanged, and a monitor resolution greater than 96 DPI, this -should make text and lines sharper and some colors brighter. -On other systems, it should have no effect. If you have a custom theme, -you may want to adjust a color or two. If perchance it make text worse -on your monitor, you can disable the ctypes.OleDLL call near the top of -pyshell.py and report the problem on python-list or idle-dev@python.org. - -bpo-33768: Clicking on a context line moves that line to the top -of the editor window. - -bpo-33763: Replace the code context label widget with a text widget. - -bpo-33664: Scroll IDLE editor text by lines. -(Previously, the mouse wheel and scrollbar slider moved text by a fixed -number of pixels, resulting in partial lines at the top of the editor -box.) This change also applies to the shell and grep output windows, -but currently not to read-only text views. - -bpo-33679: Enable theme-specific color configuration for Code Context. -(Previously, there was one code context foreground and background font -color setting, default or custom, on the extensions tab, that applied -to all themes.) For built-in themes, the foreground is the same as -normal text and the background is a contrasting gray. Context colors for -custom themes are set on the Hightlights tab along with other colors. -When one starts IDLE from a console and loads a custom theme without -definitions for 'context', one will see a warning message on the -console. - -bpo-33642: Display up to maxlines non-blank lines for Code Context. -If there is no current context, show a single blank line. (Previously, -the Code Contex had numlines lines, usually with some blank.) The use -of a new option, 'maxlines' (default 15), avoids possible interference -with user settings of the old option, 'numlines' (default 3). - -bpo-33628: Cleanup codecontext.py and its test. - -bpo-32831: Add docstrings and tests for codecontext.py. -Coverage is 100%. Patch by Cheryl Sabella. - -bpo-33564: Code context now recognizes async as a block opener. - -bpo-21474: Update word/identifier definition from ascii to unicode. -In text and entry boxes, this affects selection by double-click, -movement left/right by control-left/right, and deletion left/right -by control-BACKSPACE/DEL. - -bpo-33204: Consistently color invalid string prefixes. -A 'u' string prefix cannot be paired with either 'r' or 'f'. -IDLE now consistently colors as much of the prefix, starting at the -right, as is valid. Revise and extend colorizer test. - -bpo-32984: Set __file__ while running a startup file. -Like Python, IDLE optionally runs 1 startup file in the Shell window -before presenting the first interactive input prompt. For IDLE, -option -s runs a file named in environmental variable IDLESTARTUP or -PYTHONSTARTUP; -r file runs file. Python sets __file__ to the startup -file name before running the file and unsets it before the first -prompt. IDLE now does the same when run normally, without the -n -option. - -bpo-32940: Replace StringTranslatePseudoMapping with faster code. - -bpo-32916: Change 'str' to 'code' in idlelib.pyparse and users. - -bpo-32905: Remove unused code in pyparse module. - -bpo-32874: IDLE - add pyparse tests with 97% coverage. - -bpo-32837: IDLE - require encoding argument for textview.view_file. -Using the system and place-dependent default encoding for open() -is a bad idea for IDLE's system and location-independent files. - -bpo-32826: Add "encoding=utf-8" to open() in IDLE's test_help_about. -GUI test test_file_buttons() only looks at initial ascii-only lines, -but failed on systems where open() defaults to 'ascii' because -readline() internally reads and decodes far enough ahead to encounter -a non-ascii character in CREDITS.txt. - -bpo-32765: Update configdialog General tab create page docstring. -Add new widgets to the widget list. - -bpo-32207: Improve tk event exception tracebacks in IDLE. -When tk event handling is driven by IDLE's run loop, a confusing -and distracting queue.EMPTY traceback context is no longer added -to tk event exception tracebacks. The traceback is now the same -as when event handling is driven by user code. Patch based on -a suggestion by Serhiy Storchaka. - -bpo-32164: Delete unused file idlelib/tabbedpages.py. -Use of TabbedPageSet in configdialog was replaced by ttk.Notebook. - -bpo-32100: Fix old and new bugs in pathbrowser; improve tests. -Patch mostly by Cheryl Sabella. - -bpo-31860: The font sample in the settings dialog is now editable. -Edits persist while IDLE remains open. -Patch by Serhiy Storchake and Terry Jan Reedy. - -bpo-31858: Restrict shell prompt manipulation to the shell. -Editor and output windows only see an empty last prompt line. This -simplifies the code and fixes a minor bug when newline is inserted. -Sys.ps1, if present, is read on Shell start-up, but is not set or changed. -Patch by Terry Jan Reedy. - -bpo-28603: Fix a TypeError that caused a shell restart when printing -a traceback that includes an exception that is unhashable. -Patch by Zane Bitter. - -bpo-13802: Use non-Latin characters in the Font settings sample. -Even if one selects a font that defines a limited subset of the unicode -Basic Multilingual Plane, tcl/tk will use other fonts that define a -character. The expanded example give users of non-Latin characters -a better idea of what they might see in the shell and editors. - -To make room for the expanded sample, frames on the Font tab are -re-arranged. The Font/Tabs help explains a bit about the additions. -Patch by Terry Jan Reedy - -bpo-31460: Simplify the API of IDLE's Module Browser. -Passing a widget instead of an flist with a root widget opens the -option of creating a browser frame that is only part of a window. -Passing a full file name instead of pieces assumed to come from a -.py file opens the possibility of browsing python files that do not -end in .py. - -bpo-31649: Make _htest and _utest parameters keyword-only. -These are used to adjust code for human and unit tests. - -bpo-31459: Rename module browser from Class Browser to Module Browser. -The original module-level class and method browser became a module -browser, with the addition of module-level functions, years ago. -Nested classes and functions were added yesterday. For back- -compatibility, the virtual event <>, which -appears on the Keys tab of the Settings dialog, is not changed. -Patch by Cheryl Sabella. - -bpo-1612262: Module browser now shows nested classes and functions. -Original patches for code and tests by Guilherme Polo and -Cheryl Sabella, respectively. Revisions by Terry Jan Reedy. - -bpo-31500: Tk's default fonts now are scaled on HiDPI displays. -This affects all dialogs. Patch by Serhiy Storchaka. - -bpo-31493: Fix code context update and font update timers. -Canceling timers prevents a warning message when test_idle completes. - -bpo-31488: Update non-key options in former extension classes. -When applying configdialog changes, call .reload for each feature class. -Change ParenMatch so updated options affect existing instances attached -to existing editor windows. - -bpo-31477: Improve rstrip entry in IDLE doc. -Strip Trailing Whitespace strips more than blank spaces. -Multiline string literals are not skipped. - -bpo-31480: fix tests to pass with zzdummy extension disabled. (#3590) -To see the example in action, enable it on options extensions tab. - -bpo-31421: Document how IDLE runs tkinter programs. -IDLE calls tcl/tk update in the background in order to make live -interaction and experimentation with tkinter applications much easier. - -bpo-31414: Fix tk entry box tests by deleting first. -Adding to an int entry is not the same as deleting and inserting -because int('') will fail. Patch by Terry Jan Reedy. - -bpo-27099: Convert IDLE's built-in 'extensions' to regular features. - About 10 IDLE features were implemented as supposedly optional -extensions. Their different behavior could be confusing or worse for -users and not good for maintenance. Hence the conversion. - The main difference for users is that user configurable key bindings -for builtin features are now handled uniformly. Now, editing a binding -in a keyset only affects its value in the keyset. All bindings are -defined together in the system-specific default keysets in config- -extensions.def. All custom keysets are saved as a whole in config- -extension.cfg. All take effect as soon as one clicks Apply or Ok. - The affected events are '<>', -'<>', '<>', '<>', -'<>', '<>', '<>', and -'<>'. Any (global) customizations made before 3.6.3 will -not affect their keyset-specific customization after 3.6.3. and vice -versa. - Initial patch by Charles Wohlganger, revised by Terry Jan Reedy. - -bpo-31051: Rearrange condigdialog General tab. -Sort non-Help options into Window (Shell+Editor) and Editor (only). -Leave room for the addition of new options. -Patch by Terry Jan Reedy. - -bpo-30617: Add docstrings and tests for outwin subclass of editor. -Move some data and functions from the class to module level. -Patch by Cheryl Sabella. - -bpo-31287: Do not modify tkinter.messagebox in test_configdialog. -Instead, mask it with an instance mock that can be deleted. -Patch by Terry Jan Reedy. - -bpo-30781: Use ttk widgets in ConfigDialog pages. -These should especially look better on MacOSX. -Patches by Terry Jan Reedy and Cheryl Sabella. - -bpo-31206: Factor HighPage(Frame) class from ConfigDialog. -Patch by Cheryl Sabella. - -bp0-31001: Add tests for configdialog highlight tab. -Patch by Cheryl Sabella. - -bpo-31205: Factor KeysPage(Frame) class from ConfigDialog. -The slightly modified tests continue to pass. -Patch by Cheryl Sabella. - -bpo-31002: Add tests for configdialog keys tab. -Patch by Cheryl Sabella. - -bpo-19903: Change calltipes to use inspect.signature. -Idlelib.calltips.get_argspec now uses inspect.signature instead of -inspect.getfullargspec, like help() does. This improves the signature -in the call tip in a few different cases, including builtins converted -to provide a signature. A message is added if the object is not -callable, has an invalid signature, or if it has positional-only -parameters. Patch by Louie Lu. - -bop-31083: Add an outline of a TabPage class in configdialog. -Add template as comment. Update existing classes to match outline. -Initial patch by Cheryl Sabella. - -bpo-31050: Factor GenPage(Frame) class from ConfigDialog. -The slightly modified tests for the General tab continue to pass. -Patch by Cheryl Sabella. - -bpo-31004: Factor FontPage(Frame) class from ConfigDialog. -The slightly modified tests continue to pass. The General test -broken by the switch to ttk.Notebook is fixed. -Patch mostly by Cheryl Sabella. - -bpo-30781: IDLE - Use ttk Notebook in ConfigDialog. -This improves navigation by tabbing. -Patch by Terry Jan Reedy. - -bpo-31060: IDLE - Finish rearranging methods of ConfigDialog. -Grouping methods pertaining to each tab and the buttons will aid -writing tests and improving the tabs and will enable splitting the -groups into classes. -Patch by Terry Jan Reedy. - -bpo-30853: IDLE -- Factor a VarTrace class out of ConfigDialog. -Instance tracers manages pairs consisting of a tk variable and a -callback function. When tracing is turned on, setting the variable -calls the function. Test coverage for the new class is 100%. -Patch by Terry Jan Reedy. - -bpo-31003: IDLE: Add more tests for General tab. -Patch by Terry Jan Reedy. - -bpo-30993: IDLE - Improve configdialog font page and tests. -*In configdialog: Document causal pathways in create_font_tab -docstring. Simplify some attribute names. Move set_samples calls to -var_changed_font (idea from Cheryl Sabella). Move related functions to -positions after the create widgets function. -* In test_configdialog: Fix test_font_set so not order dependent. Fix -renamed test_indent_scale so it tests the widget. Adjust tests for -movement of set_samples call. Add tests for load functions. Put all -font tests in one class and tab indent tests in another. Except for -two lines, these tests completely cover the related functions. -Patch by Terry Jan Reedy. - -bpo-30981: IDLE -- Add more configdialog font page tests. - -bpo-28523: IDLE: replace 'colour' with 'color' in configdialog. - -bpo-30917: Add tests for idlelib.config.IdleConf. -Increase coverage from 46% to 96%. -Patch by Louie Lu. - -bpo-30913: Document ConfigDialog tk Vars, methods, and widgets in docstrings -This will facilitate improving the dialog and splitting up the class. -Original patch by Cheryl Sabella. - -bpo-30899: Add tests for ConfigParser subclasses in config. -Coverage is 100% for those classes and ConfigChanges. -Patch by Louie Lu. - -bpo-30881: Add docstrings to browser.py. -Patch by Cheryl Sabella. - -bpo-30851: Remove unused tk variables in configdialog. -One is a duplicate, one is set but cannot be altered by users. -Patch by Cheryl Sabella. - -bpo-30870: Select font option with Up and Down keys, as well as with mouse. -Added test increases configdialog coverage to 60% -Patches mostly by Louie Lu. - -bpo-8231: Call config.IdleConf.GetUserCfgDir only once per process. - -bpo-30779: Factor ConfigChanges class from configdialog, put in config; test. -* In config, put dump test code in a function; run it and unittest in - 'if __name__ == '__main__'. -* Add class config.ConfigChanges based on changes_class_v4.py on bpo issue. -* Add class test_config.ChangesTest, partly using configdialog_tests_v1.py. -* Revise configdialog to use ConfigChanges; see tracker msg297804. -* Revise test_configdialog to match configdialog changes. -* Remove configdialog functions unused or moved to ConfigChanges. -Cheryl Sabella contributed parts of the patch. - -bpo-30777: Configdialog - add docstrings and improve comments. -Patch by Cheryl Sabella. - -bpo-30495: Improve textview with docstrings, PEP8 names, and more tests. -Split TextViewer class into ViewWindow, ViewFrame, and TextFrame classes -so that instances of the latter two can be placed with other widgets -within a multiframe window. -Patches by Cheryl Sabella and Terry Jan Reedy. - -bpo-30723: Make several improvements to parenmatch. -* Add 'parens' style to highlight both opener and closer. -* Make 'default' style, which is not default, a synonym for 'opener'. -* Make time-delay work the same with all styles. -* Add help for config dialog extensions tab, including parenmatch. -* Add new tests. -Original patch by Charles Wohlganger. Revisions by Terry Jan Reedy - -bpo-30674: Grep -- Add docstrings. Patch by Cheryl Sabella. - -bpo-21519: IDLE's basic custom key entry dialog now detects -duplicates properly. Original patch by Saimadhav Heblikar. - -bpo-29910: IDLE no longer deletes a character after commenting out a -region by a key shortcut. Add "return 'break'" for this and other -potential conflicts between IDLE and default key bindings. -Patch by Serhiy Storchaka. - -bpo-30728: Modernize idlelib.configdialog: -* replace import * with specific imports; -* lowercase method and attribute lines. -Patch by Cheryl Sabella. - -bpo-6739: Verify user-entered key sequences by trying to bind them -with to a tk widget. Add tests for all 3 validation functions. -Original patch by G Polo. Tests added by Cheryl Sabella. -Code revised and more tests added by Terry Jan Reedy - -bpo-24813: Add icon to help_about and make other changes. - -bpo-15786: Fix several problems with IDLE's autocompletion box. -The following should now work: clicking on selection box items; -using the scrollbar; selecting an item by hitting Return. -Hangs on MacOSX should no longer happen. Patch by Louie Lu. - -bpo-25514: Add doc subsubsection about IDLE failure to start. -Popup no-connection message directs users to this section. - -bpo-30642: Fix reference leaks in IDLE tests. -Patches by Louie Lu and Terry Jan Reedy. - -bpo-30495: Add docstrings for textview.py and use PEP8 names. -Patches by Cheryl Sabella and Terry Jan Reedy. - -bpo-30290: Help-about: use pep8 names and add tests. -Increase coverage to 100%. -Patches by Louie Lu, Cheryl Sabella, and Terry Jan Reedy. - -bpo-30303: Add _utest option to textview; add new tests. -Increase coverage to 100%. -Patches by Louie Lu and Terry Jan Reedy. - -Issue #29071: IDLE colors f-string prefixes but not invalid ur prefixes. - -Issue #28572: Add 10% to coverage of IDLE's test_configdialog. -Update and augment description of the configuration system. - - -What's New in IDLE 3.6.0 (since 3.5.0) -Released on 2016-12-23 -====================================== - -- Issue #15308: Add 'interrupt execution' (^C) to Shell menu. - Patch by Roger Serwy, updated by Bayard Randel. - -- Issue #27922: Stop IDLE tests from 'flashing' gui widgets on the screen. - -- Issue #27891: Consistently group and sort imports within idlelib modules. - -- Issue #17642: add larger font sizes for classroom projection. - -- Add version to title of IDLE help window. - -- Issue #25564: In section on IDLE -- console differences, mention that - using exec means that __builtins__ is defined for each statement. - -- Issue #27821: Fix 3.6.0a3 regression that prevented custom key sets - from being selected when no custom theme was defined. - -- Issue #27714: text_textview and test_autocomplete now pass when re-run - in the same process. This occurs when test_idle fails when run with the - -w option but without -jn. Fix warning from test_config. - -- Issue #27621: Put query response validation error messages in the query - box itself instead of in a separate messagebox. Redo tests to match. - Add Mac OSX refinements. Original patch by Mark Roseman. - -- Issue #27620: Escape key now closes Query box as cancelled. - -- Issue #27609: IDLE: tab after initial whitespace should tab, not - autocomplete. This fixes problem with writing docstrings at least - twice indented. - -- Issue #27609: Explicitly return None when there are also non-None - returns. In a few cases, reverse a condition and eliminate a return. - -- Issue #25507: IDLE no longer runs buggy code because of its tkinter imports. - Users must include the same imports required to run directly in Python. - -- Issue #27173: Add 'IDLE Modern Unix' to the built-in key sets. - Make the default key set depend on the platform. - Add tests for the changes to the config module. - -- Issue #27452: add line counter and crc to IDLE configHandler test dump. - -- Issue #27477: IDLE search dialogs now use ttk widgets. - -- Issue #27173: Add 'IDLE Modern Unix' to the built-in key sets. - Make the default key set depend on the platform. - Add tests for the changes to the config module. - -- Issue #27452: make command line "idle-test> python test_help.py" work. - __file__ is relative when python is started in the file's directory. - -- Issue #27452: add line counter and crc to IDLE configHandler test dump. - -- Issue #27380: IDLE: add query.py with base Query dialog and ttk widgets. - Module had subclasses SectionName, ModuleName, and HelpSource, which are - used to get information from users by configdialog and file =>Load Module. - Each subclass has itw own validity checks. Using ModuleName allows users - to edit bad module names instead of starting over. - Add tests and delete the two files combined into the new one. - -- Issue #27372: Test_idle no longer changes the locale. - -- Issue #27365: Allow non-ascii chars in IDLE NEWS.txt, for contributor names. - -- Issue #27245: IDLE: Cleanly delete custom themes and key bindings. - Previously, when IDLE was started from a console or by import, a cascade - of warnings was emitted. Patch by Serhiy Storchaka. - -- Issue #24137: Run IDLE, test_idle, and htest with tkinter default root disabled. - Fix code and tests that fail with this restriction. - Fix htests to not create a second and redundant root and mainloop. - -- Issue #27310: Fix IDLE.app failure to launch on OS X due to vestigial import. - -- Issue #5124: Paste with text selected now replaces the selection on X11. - This matches how paste works on Windows, Mac, most modern Linux apps, - and ttk widgets. Original patch by Serhiy Storchaka. - -- Issue #24750: Switch all scrollbars in IDLE to ttk versions. - Where needed, minimal tests are added to cover changes. - -- Issue #24759: IDLE requires tk 8.5 and availability ttk widgets. - Delete now unneeded tk version tests and code for older versions. - Add test for IDLE syntax colorizer. - -- Issue #27239: idlelib.macosx.isXyzTk functions initialize as needed. - -- Issue #27262: move Aqua unbinding code, which enable context menus, to macosx. - -- Issue #24759: Make clear in idlelib.idle_test.__init__ that the directory - is a private implementation of test.test_idle and tool for maintainers. - -- Issue #27196: Stop 'ThemeChanged' warnings when running IDLE tests. - These persisted after other warnings were suppressed in #20567. - Apply Serhiy Storchaka's update_idletasks solution to four test files. - Record this additional advice in idle_test/README.txt - -- Issue #20567: Revise idle_test/README.txt with advice about avoiding - tk warning messages from tests. Apply advice to several IDLE tests. - -- Issue # 24225: Update idlelib/README.txt with new file names - and event handlers. - -- Issue #27156: Remove obsolete code not used by IDLE. Replacements: - 1. help.txt, replaced by help.html, is out-of-date and should not be used. - Its dedicated viewer has be replaced by the html viewer in help.py. - 2. 'import idlever; I = idlever.IDLE_VERSION' is the same as - 'import sys; I = version[:version.index(' ')]' - 3. After 'ob = stackviewer.VariablesTreeItem(*args)', - 'ob.keys()' == 'list(ob.object.keys). - 4. In macosc, runningAsOSXAPP == isAquaTk; idCarbonAquaTk == isCarbonTk - -- Issue #27117: Make colorizer htest and turtledemo work with dark themes. - Move code for configuring text widget colors to a new function. - -- Issue #24225: Rename many idlelib/*.py and idle_test/test_*.py files. - Edit files to replace old names with new names when the old name - referred to the module rather than the class it contained. - See the issue and IDLE section in What's New in 3.6 for more. - -- Issue #26673: When tk reports font size as 0, change to size 10. - Such fonts on Linux prevented the configuration dialog from opening. - -- Issue #21939: Add test for IDLE's percolator. - Original patch by Saimadhav Heblikar. - -- Issue #21676: Add test for IDLE's replace dialog. - Original patch by Saimadhav Heblikar. - -- Issue #18410: Add test for IDLE's search dialog. - Original patch by Westley Martínez. - -- Issue #21703: Add test for undo delegator. Patch mostly by - Saimadhav Heblikar . - -- Issue #27044: Add ConfigDialog.remove_var_callbacks to stop memory leaks. - -- Issue #23977: Add more asserts to test_delegator. - -- Issue #20640: Add tests for idlelib.configHelpSourceEdit. - Patch by Saimadhav Heblikar. - -- In the 'IDLE-console differences' section of the IDLE doc, clarify - how running with IDLE affects sys.modules and the standard streams. - -- Issue #25507: fix incorrect change in IOBinding that prevented printing. - Augment IOBinding htest to include all major IOBinding functions. - -- Issue #25905: Revert unwanted conversion of ' to ’ RIGHT SINGLE QUOTATION - MARK in README.txt and open this and NEWS.txt with 'ascii'. - Re-encode CREDITS.txt to utf-8 and open it with 'utf-8'. - -- Issue 15348: Stop the debugger engine (normally in a user process) - before closing the debugger window (running in the IDLE process). - This prevents the RuntimeErrors that were being caught and ignored. - -- Issue #24455: Prevent IDLE from hanging when a) closing the shell while the - debugger is active (15347); b) closing the debugger with the [X] button - (15348); and c) activating the debugger when already active (24455). - The patch by Mark Roseman does this by making two changes. - 1. Suspend and resume the gui.interaction method with the tcl vwait - mechanism intended for this purpose (instead of root.mainloop & .quit). - 2. In gui.run, allow any existing interaction to terminate first. - -- Change 'The program' to 'Your program' in an IDLE 'kill program?' message - to make it clearer that the program referred to is the currently running - user program, not IDLE itself. - -- Issue #24750: Improve the appearance of the IDLE editor window status bar. - Patch by Mark Roseman. - -- Issue #25313: Change the handling of new built-in text color themes to better - address the compatibility problem introduced by the addition of IDLE Dark. - Consistently use the revised idleConf.CurrentTheme everywhere in idlelib. - -- Issue #24782: Extension configuration is now a tab in the IDLE Preferences - dialog rather than a separate dialog. The former tabs are now a sorted - list. Patch by Mark Roseman. - -- Issue #22726: Re-activate the config dialog help button with some content - about the other buttons and the new IDLE Dark theme. - -- Issue #24820: IDLE now has an 'IDLE Dark' built-in text color theme. - It is more or less IDLE Classic inverted, with a cobalt blue background. - Strings, comments, keywords, ... are still green, red, orange, ... . - To use it with IDLEs released before November 2015, hit the - 'Save as New Custom Theme' button and enter a new name, - such as 'Custom Dark'. The custom theme will work with any IDLE - release, and can be modified. - -- Issue #25224: README.txt is now an idlelib index for IDLE developers and - curious users. The previous user content is now in the IDLE doc chapter. - 'IDLE' now means 'Integrated Development and Learning Environment'. - -- Issue #24820: Users can now set breakpoint colors in - Settings -> Custom Highlighting. Original patch by Mark Roseman. - -- Issue #24972: Inactive selection background now matches active selection - background, as configured by users, on all systems. Found items are now - always highlighted on Windows. Initial patch by Mark Roseman. - -- Issue #24570: Idle: make calltip and completion boxes appear on Macs - affected by a tk regression. Initial patch by Mark Roseman. - -- Issue #24988: Idle ScrolledList context menus (used in debugger) - now work on Mac Aqua. Patch by Mark Roseman. - -- Issue #24801: Make right-click for context menu work on Mac Aqua. - Patch by Mark Roseman. - -- Issue #25173: Associate tkinter messageboxes with a specific widget. - For Mac OSX, make them a 'sheet'. Patch by Mark Roseman. - -- Issue #25198: Enhance the initial html viewer now used for Idle Help. - * Properly indent fixed-pitch text (patch by Mark Roseman). - * Give code snippet a very Sphinx-like light blueish-gray background. - * Re-use initial width and height set by users for shell and editor. - * When the Table of Contents (TOC) menu is used, put the section header - at the top of the screen. - -- Issue #25225: Condense and rewrite Idle doc section on text colors. - -- Issue #21995: Explain some differences between IDLE and console Python. - -- Issue #22820: Explain need for *print* when running file from Idle editor. - -- Issue #25224: Doc: augment Idle feature list and no-subprocess section. - -- Issue #25219: Update doc for Idle command line options. - Some were missing and notes were not correct. - -- Issue #24861: Most of idlelib is private and subject to change. - Use idleib.idle.* to start Idle. See idlelib.__init__.__doc__. - -- Issue #25199: Idle: add synchronization comments for future maintainers. - -- Issue #16893: Replace help.txt with help.html for Idle doc display. - The new idlelib/help.html is rstripped Doc/build/html/library/idle.html. - It looks better than help.txt and will better document Idle as released. - The tkinter html viewer that works for this file was written by Mark Roseman. - The now unused EditorWindow.HelpDialog class and helt.txt file are deprecated. - -- Issue #24199: Deprecate unused idlelib.idlever with possible removal in 3.6. - -- Issue #24790: Remove extraneous code (which also create 2 & 3 conflicts). - - -What's New in IDLE 3.5.0? -========================= -*Release date: 2015-09-13* - -- Issue #23672: Allow Idle to edit and run files with astral chars in name. - Patch by Mohd Sanad Zaki Rizvi. - -- Issue 24745: Idle editor default font. Switch from Courier to - platform-sensitive TkFixedFont. This should not affect current customized - font selections. If there is a problem, edit $HOME/.idlerc/config-main.cfg - and remove 'fontxxx' entries from [Editor Window]. Patch by Mark Roseman. - -- Issue #21192: Idle editor. When a file is run, put its name in the restart bar. - Do not print false prompts. Original patch by Adnan Umer. - -- Issue #13884: Idle menus. Remove tearoff lines. Patch by Roger Serwy. - -- Issue #23184: remove unused names and imports in idlelib. - Initial patch by Al Sweigart. - -- Issue #20577: Configuration of the max line length for the FormatParagraph - extension has been moved from the General tab of the Idle preferences dialog - to the FormatParagraph tab of the Config Extensions dialog. - Patch by Tal Einat. - -- Issue #16893: Update Idle doc chapter to match current Idle and add new - information. - -- Issue #3068: Add Idle extension configuration dialog to Options menu. - Changes are written to HOME/.idlerc/config-extensions.cfg. - Original patch by Tal Einat. - -- Issue #16233: A module browser (File : Class Browser, Alt+C) requires an - editor window with a filename. When Class Browser is requested otherwise, - from a shell, output window, or 'Untitled' editor, Idle no longer displays - an error box. It now pops up an Open Module box (Alt+M). If a valid name - is entered and a module is opened, a corresponding browser is also opened. - -- Issue #4832: Save As to type Python files automatically adds .py to the - name you enter (even if your system does not display it). Some systems - automatically add .txt when type is Text files. - -- Issue #21986: Code objects are not normally pickled by the pickle module. - To match this, they are no longer pickled when running under Idle. - -- Issue #23180: Rename IDLE "Windows" menu item to "Window". - Patch by Al Sweigart. - -- Issue #17390: Adjust Editor window title; remove 'Python', - move version to end. - -- Issue #14105: Idle debugger breakpoints no longer disappear - when inserting or deleting lines. - -- Issue #17172: Turtledemo can now be run from Idle. - Currently, the entry is on the Help menu, but it may move to Run. - Patch by Ramchandra Apt and Lita Cho. - -- Issue #21765: Add support for non-ascii identifiers to HyperParser. - -- Issue #21940: Add unittest for WidgetRedirector. Initial patch by Saimadhav - Heblikar. - -- Issue #18592: Add unittest for SearchDialogBase. Patch by Phil Webster. - -- Issue #21694: Add unittest for ParenMatch. Patch by Saimadhav Heblikar. - -- Issue #21686: add unittest for HyperParser. Original patch by Saimadhav - Heblikar. - -- Issue #12387: Add missing upper(lower)case versions of default Windows key - bindings for Idle so Caps Lock does not disable them. Patch by Roger Serwy. - -- Issue #21695: Closing a Find-in-files output window while the search is - still in progress no longer closes Idle. - -- Issue #18910: Add unittest for textView. Patch by Phil Webster. - -- Issue #18292: Add unittest for AutoExpand. Patch by Saihadhav Heblikar. - -- Issue #18409: Add unittest for AutoComplete. Patch by Phil Webster. - -- Issue #21477: htest.py - Improve framework, complete set of tests. - Patches by Saimadhav Heblikar - -- Issue #18104: Add idlelib/idle_test/htest.py with a few sample tests to begin - consolidating and improving human-validated tests of Idle. Change other files - as needed to work with htest. Running the module as __main__ runs all tests. - -- Issue #21139: Change default paragraph width to 72, the PEP 8 recommendation. - -- Issue #21284: Paragraph reformat test passes after user changes reformat width. - -- Issue #17654: Ensure IDLE menus are customized properly on OS X for - non-framework builds and for all variants of Tk. - - -What's New in IDLE 3.4.0? -========================= -*Release date: 2014-03-16* - -- Issue #17390: Display Python version on Idle title bar. - Initial patch by Edmond Burnett. - -- Issue #5066: Update IDLE docs. Patch by Todd Rovito. - -- Issue #17625: Close the replace dialog after it is used. - -- Issue #16226: Fix IDLE Path Browser crash. - (Patch by Roger Serwy) - -- Issue #15853: Prevent IDLE crash on OS X when opening Preferences menu - with certain versions of Tk 8.5. Initial patch by Kevin Walzer. - - -What's New in IDLE 3.3.0? -========================= -*Release date: 2012-09-29* - -- Issue #17625: Close the replace dialog after it is used. - -- Issue #7163: Propagate return value of sys.stdout.write. - -- Issue #15318: Prevent writing to sys.stdin. - -- Issue #4832: Modify IDLE to save files with .py extension by - default on Windows and OS X (Tk 8.5) as it already does with X11 Tk. - -- Issue #13532, #15319: Check that arguments to sys.stdout.write are strings. - -- Issue # 12510: Attempt to get certain tool tips no longer crashes IDLE. - Erroneous tool tips have been corrected. Default added for callables. - -- Issue #10365: File open dialog now works instead of crashing even when - parent window is closed while dialog is open. - -- Issue 14876: use user-selected font for highlight configuration. - -- Issue #14937: Perform auto-completion of filenames in strings even for - non-ASCII filenames. Likewise for identifiers. - -- Issue #8515: Set __file__ when run file in IDLE. - Initial patch by Bruce Frederiksen. - -- IDLE can be launched as `python -m idlelib` - -- Issue #14409: IDLE now properly executes commands in the Shell window - when it cannot read the normal config files on startup and - has to use the built-in default key bindings. - There was previously a bug in one of the defaults. - -- Issue #3573: IDLE hangs when passing invalid command line args - (directory(ies) instead of file(s)). - -- Issue #14018: Update checks for unstable system Tcl/Tk versions on OS X - to include versions shipped with OS X 10.7 and 10.8 in addition to 10.6. - - -What's New in IDLE 3.2.1? -========================= -*Release date: 15-May-11* - -- Issue #6378: Further adjust idle.bat to start associated Python - -- Issue #11896: Save on Close failed despite selecting "Yes" in dialog. - -- Issue #1028: Ctrl-space binding to show completions was causing IDLE to exit. - Tk < 8.5 was sending invalid Unicode null; replaced with valid null. - -- Issue #4676: toggle failing on Tk 8.5, causing IDLE exits and strange selection - behavior. Improve selection extension behaviour. - -- Issue #3851: toggle non-functional when NumLock set on Windows. - - -What's New in IDLE 3.1b1? -========================= -*Release date: 06-May-09* - -- Issue #5707: Use of 'filter' in keybindingDialog.py was causing custom key assignment to - fail. Patch by Amaury Forgeot d'Arc. - -- Issue #4815: Offer conversion to UTF-8 if source files have - no encoding declaration and are not encoded in UTF-8. - -- Issue #4008: Fix problems with non-ASCII source files. - -- Issue #4323: Always encode source as UTF-8 without asking - the user (unless a different encoding is declared); remove - user configuration of source encoding; all according to - PEP 3120. - -- Issue #2665: On Windows, an IDLE installation upgraded from an old version - would not start if a custom theme was defined. - ------------------------------------------------------------------------- -Refer to NEWS2x.txt and HISTORY.txt for information on earlier releases. ------------------------------------------------------------------------- diff --git a/Lib/idlelib/News3.txt b/Lib/idlelib/News3.txt new file mode 100644 index 00000000000000..84484571a49cf7 --- /dev/null +++ b/Lib/idlelib/News3.txt @@ -0,0 +1,1360 @@ +What's New in IDLE 3.13.0 +(since 3.12.0) +Released on 2024-10-xx +========================= + + +gh-113729: Fix the "Help -> IDLE Doc" menu bug in 3.11.7 and 3.12.1. + +gh-57795: Enter selected text into the Find box when opening +a Replace dialog. Patch by Roger Serwy and Zackery Spytz. + +gh-113269: Fix test_editor hang on macOS Catalina. +Patch by Terry Reedy. + +gh-112939: Fix processing unsaved files when quitting IDLE on macOS. +Patch by Ronald Oussoren and Christopher Chavez. + +gh-79871: Add docstrings to debugger.py. Fix two bugs in +test_debugger and expand coverage by 47%. Patch by Anthony Shaw. + + +What's New in IDLE 3.12.0 +(since 3.11.0) +Released on 2023-10-02 +========================= + +gh-104719: Remove IDLE's modification of tokenize.tabsize and test +other uses of tokenize data and methods. + +gh-104499: Fix completions for Tk Aqua 8.7 (currently blank). + +gh-104486: Make About print both tcl and tk versions if different, +as is expected someday. + +gh-88496 Fix IDLE test hang on macOS. + +gh-103314 Support sys.last_exc after exceptions in Shell. +Patch by Irit Katriel. + + +What's New in IDLE 3.11.0 +(since 3.10.0) +Released on 2022-10-24 +========================= + +gh-97527: Fix a bug in the previous bugfix that caused IDLE to not +start when run with 3.10.8, 3.12.0a1, and at least Microsoft Python +3.10.2288.0 installed without the Lib/test package. 3.11.0 was never +affected. + +gh-65802: Document handling of extensions in Save As dialogs. + +gh-95191: Include prompts when saving Shell (interactive input/output). + +gh-95511: Fix the Shell context menu copy-with-prompts bug of copying +an extra line when one selects whole lines. + +gh-95471: Tweak Edit menu. Move 'Select All' above 'Cut' as it is used +with 'Cut' and 'Copy' but not 'Paste'. Add a separator between 'Replace' +and 'Go to Line' to help IDLE issue triagers. + +gh-95411: Enable using IDLE's module browser with .pyw files. + +gh-89610: Add .pyi as a recognized extension for IDLE on macOS. This allows +opening stub files by double clicking on them in the Finder. + +bpo-28950: Apply IDLE syntax highlighting to `.pyi` files. Add util.py +for common components. Patch by Alex Waygood and Terry Jan Reedy. + +bpo-46630: Make query dialogs on Windows start with a cursor in the +entry box. + +bpo-46591: Make the IDLE doc URL on the About IDLE dialog clickable. + +bpo-45296: Clarify close, quit, and exit in IDLE. In the File menu, +'Close' and 'Exit' are now 'Close Window' (the current one) and 'Exit' +is now 'Exit IDLE' (by closing all windows). In Shell, 'quit()' and +'exit()' mean 'close Shell'. If there are no other windows, +this also exits IDLE. + +bpo-45495: Add context keywords 'case' and 'match' to completions list. + +bpo-45296: On Windows, change exit/quit message to suggest Ctrl-D, which +works, instead of , which does not work in IDLE. + + +What's New in IDLE 3.10.0 +(since 3.9.0) +Released on 2021-10-04 +========================= + +bpo-45193: Make completion boxes appear on Ubuntu again. + +bpo-40128: Mostly fix completions on macOS when not using tcl/tk 8.6.11 +(as with 3.9). + +bpo-33962: Move the indent space setting from the Font tab to the new Windows +tab. Patch by Mark Roseman and Terry Jan Reedy. + +bpo-40468: Split the settings dialog General tab into Windows and Shell/Ed +tabs. Move help sources, which extend the Help menu, to the Extensions tab. +Make space for new options and shorten the dialog. The latter makes the +dialog better fit small screens. + +bpo-44010: Highlight the new match statement's soft keywords: match, case, +and _. This highlighting is not perfect and will be incorrect in some rare +cases, especially for some _s in case patterns. + +bpo-44026: Include interpreter's typo fix suggestions in message line +for NameErrors and AttributeErrors. Patch by E. Paine. + +bpo-41611: Avoid occasional uncaught exceptions and freezing when using +completions on macOS. + +bpo-37903: Add mouse actions to the shell sidebar. Left click and +optional drag selects one or more lines of text, as with the +editor line number sidebar. Right click after selecting text lines +displays a context menu with 'copy with prompts'. This zips together +prompts from the sidebar with lines from the selected text. This option +also appears on the context menu for the text. + +bpo-43981: Fix reference leaks in test_sidebar and test_squeezer. +Patches by Terry Jan Reedy and Pablo Galindo + +bpo-37892: Change Shell input indents from tabs to spaces. Shell input +now 'looks right'. Making this feasible motivated the shell sidebar. + +bpo-37903: Move the Shell input prompt to a side bar. + +bpo-43655: Make window managers on macOS and X Window recognize +IDLE dialog windows as dialogs. + +bpo-42225: Document that IDLE can fail on Unix either from misconfigured IP +masquerade rules or failure displaying complex colored (non-ascii) characters. + +bpo-43283: Document why printing to IDLE's Shell is often slower than +printing to a system terminal and that it can be made faster by +pre-formatting a single string before printing. + +bpo-23544: Disable Debug=>Stack Viewer when user code is running or +Debugger is active, to prevent hang or crash. Patch by Zackery Spytz. + +bpo-43008: Make IDLE invoke :func:`sys.excepthook` in normal, +2-process mode. User hooks were previously ignored. +Patch by Ken Hilton. + +bpo-33065: Fix problem debugging user classes with __repr__ method. + +bpo-32631: Finish zzdummy example extension module: make menu entries +work; add docstrings and tests with 100% coverage. + +bpo-42508: Keep IDLE running on macOS. Remove obsolete workaround +that prevented running files with shortcuts when using new universal2 +installers built on macOS 11. + +bpo-42426: Fix reporting offset of the RE error in searchengine. + +bpo-42416: Display docstrings in IDLE calltips in more cases, +by using inspect.getdoc. + +bpo-33987: Mostly finish using ttk widgets, mainly for editor, +settings, and searches. Some patches by Mark Roseman. + +bpo-40511: Stop unnecessary "flashing" when typing opening and closing +parentheses inside the parentheses of a function call. + +bpo-38439: Add a 256x256 pixel IDLE icon to the Windows .ico file. Created by +Andrew Clover. Remove the low-color gif variations from the .ico file. + +bpo-41775: Make 'IDLE Shell' the shell title. + +bpo-35764: Rewrite the Calltips doc section. + +bpo-40181: In calltips, stop reminding that '/' marks the end of +positional-only arguments. + + +What's New in IDLE 3.9.0 (since 3.8.0) +Released on 2020-10-05? +====================================== + +bpo-41468: Improve IDLE run crash error message (which users should +never see). + +bpo-41373: Save files loaded with no line ending, as when blank, or +different line endings, by setting its line ending to the system +default. Fix regression in 3.8.4 and 3.9.0b4. + +bpo-41300: Save files with non-ascii chars. Fix regression in +3.9.0b4 and 3.8.4. + +bpo-37765: Add keywords to module name completion list. Rewrite +Completions section of IDLE doc. + +bpo-41152: The encoding of ``stdin``, ``stdout`` and ``stderr`` in IDLE +is now always UTF-8. + +bpo-41144: Make Open Module open a special module such as os.path. + +bpo-40723: Make test_idle pass when run after import. +Patch by Florian Dahlitz. + +bpo-38689: IDLE will no longer freeze when inspect.signature fails +when fetching a calltip. + +bpo-27115: For 'Go to Line', use a Query entry box subclass with +IDLE standard behavior and improved error checking. + +bpo-39885: When a context menu is invoked by right-clicking outside +of a selection, clear the selection and move the cursor. Cut and +Copy require that the click be within the selection. + +bpo-39852: Edit "Go to line" now clears any selection, preventing +accidental deletion. It also updates Ln and Col on the status bar. + +bpo-39781: Selecting code context lines no longer causes a jump. + +bpo-39663: Add tests for pyparse find_good_parse_start(). + +bpo-39600: Remove duplicate font names from configuration list. + +bpo-38792: Close a shell calltip if a :exc:`KeyboardInterrupt` +or shell restart occurs. Patch by Zackery Spytz. + +bpo-30780: Add remaining configdialog tests for buttons and +highlights and keys tabs. + +bpo-39388: Settings dialog Cancel button cancels pending changes. + +bpo-39050: Settings dialog Help button again displays help text. + +bpo-32989: Add tests for editor newline_and_indent_event method. +Remove unneeded arguments and dead code from pyparse +find_good_parse_start method. + +bpo-38943: Fix autocomplete windows not always appearing on some +systems. Patch by Johnny Najera. + +bpo-38944: Escape key now closes IDLE completion windows. Patch by +Johnny Najera. + +bpo-38862: 'Strip Trailing Whitespace' on the Format menu removes extra +newlines at the end of non-shell files. + +bpo-38636: Fix IDLE Format menu tab toggle and file indent width. These +functions (default shortcuts Alt-T and Alt-U) were mistakenly disabled +in 3.7.5 and 3.8.0. + +bpo-4630: Add an option to toggle IDLE's cursor blink for shell, +editor, and output windows. See Settings, General, Window Preferences, +Cursor Blink. Patch by Zackery Spytz. + +bpo-26353: Stop adding newline when saving an IDLE shell window. + +bpo-38598: Do not try to compile IDLE shell or output windows. + + +What's New in IDLE 3.8.0 (since 3.7.0) +Released on 2019-10-14 +====================================== + +bpo-36698: IDLE no longer fails when writing non-encodable characters +to stderr. It now escapes them with a backslash, like the regular +Python interpreter. Add an errors field to the standard streams. + +bpo-13153: Improve tkinter's handing of non-BMP (astral) unicode +characters, such as 'rocket \U0001f680'. Whether a proper glyph or +replacement char is displayed depends on the OS and font. For IDLE, +astral chars in code interfere with editing. + +bpo-35379: When exiting IDLE, catch any AttributeError. One happens +when EditorWindow.close is called twice. Printing a traceback, when +IDLE is run from a terminal, is useless and annoying. + +bpo-38183: To avoid test issues, test_idle ignores the user config +directory. It no longer tries to create or access .idlerc or any files +within. Users must run IDLE to discover problems with saving settings. + +bpo-38077: IDLE no longer adds 'argv' to the user namespace when +initializing it. This bug only affected 3.7.4 and 3.8.0b2 to 3.8.0b4. + +bpo-38401: Shell restart lines now fill the window width, always start +with '=', and avoid wrapping unnecessarily. The line will still wrap +if the included file name is long relative to the width. + +bpo-37092: Add mousewheel scrolling for IDLE module, path, and stack +browsers. Patch by George Zhang. + +bpo-35771: To avoid occasional spurious test_idle failures on slower +machines, increase the ``hover_delay`` in test_tooltip. + +bpo-37824: Properly handle user input warnings in IDLE shell. +Cease turning SyntaxWarnings into SyntaxErrors. + +bpo-37929: IDLE Settings dialog now closes properly when there is no +shell window. + +bpo-37849: Fix completions list appearing too high or low when shown +above the current line. + +bpo-36419: Refactor autocompete and improve testing. + +bpo-37748: Reorder the Run menu. Put the most common choice, +Run Module, at the top. + +bpo-37692: Improve highlight config sample with example shell +interaction and better labels for shell elements. + +bpo-37628: Settings dialog no longer expands with font size. +The font and highlight sample boxes gain scrollbars instead. + +bpo-17535: Add optional line numbers for IDLE editor windows. + +bpo-37627: Initialize the Customize Run dialog with the command line +arguments most recently entered before. The user can optionally edit +before submitting them. + +bpo-33610: Code context always shows the correct context when toggled on. + +bpo-36390: Gather Format menu functions into format.py. Combine +paragraph.py, rstrip.py, and format methods from editor.py. + +bpo-37530: Optimize code context to reduce unneeded background activity. +Font and highlight changes now occur along with text changes instead +of after a random delay. + +bpo-27452: Cleanup config.py by inlining RemoveFile and simplifying +the handling of __file__ in CreateConfigHandlers/ + +bpo-26806: To compensate for stack frames added by IDLE and avoid +possible problems with low recursion limits, add 30 to limits in the +user code execution process. Subtract 30 when reporting recursion +limits to make this addition mostly transparent. + +bpo-37325: Fix tab focus traversal order for help source and custom +run dialogs. + +bpo-37321: Both subprocess connection error messages now refer to +the 'Startup failure' section of the IDLE doc. + +bpo-37177: Properly attach search dialogs to their main window so +that they behave like other dialogs and do not get hidden behind +their main window. + +bpo-37039: Adjust "Zoom Height" to individual screens by momentarily +maximizing the window on first use with a particular screen. Changing +screen settings may invalidate the saved height. While a window is +maximized, "Zoom Height" has no effect. + +bpo-35763: Make calltip reminder about '/' meaning positional-only less +obtrusive by only adding it when there is room on the first line. + +bpo-5680: Add 'Run Customized' to the Run menu to run a module with +customized settings. Any command line arguments entered are added +to sys.argv. One can suppress the normal Shell main module restart. + +bpo-35610: Replace now redundant editor.context_use_ps1 with +.prompt_last_line. This finishes change started in bpo-31858. + +bpo-32411: Stop sorting dict created with desired line order. + +bpo-37038: Make idlelib.run runnable; add test clause. + +bpo-36958: Print any argument other than None or int passed to +SystemExit or sys.exit(). + +bpo-36807: When saving a file, call file.flush() and os.fsync() +so bits are flushed to e.g. a USB drive. + +bpo-36429: Fix starting IDLE with pyshell. +Add idlelib.pyshell alias at top; remove pyshell alias at bottom. +Remove obsolete __name__=='__main__' command. + +bpo-30348: Increase test coverage of idlelib.autocomplete by 30%. +Patch by Louie Lu. + +bpo-23205: Add tests and refactor grep's findfiles. + +bpo-36405: Use dict unpacking in idlelib. + +bpo-36396: Remove fgBg param of idlelib.config.GetHighlight(). +This param was only used twice and changed the return type. + +bpo-23216: IDLE: Add docstrings to search modules. + +bpo-36176: Fix IDLE autocomplete & calltip popup colors. +Prevent conflicts with Linux dark themes +(and slightly darken calltip background). + +bpo-36152: Remove colorizer.ColorDelegator.close_when_done and the +corresponding argument of .close(). In IDLE, both have always been +None or False since 2007. + +bpo-36096: Make colorizer state variables instance-only. + +bpo-32129: Avoid blurry IDLE application icon on macOS with Tk 8.6. +Patch by Kevin Walzer. + +bpo-24310: Document settings dialog font tab sample. + +bpo-35689: Add docstrings and tests for colorizer. + +bpo-35833: Revise IDLE doc for control codes sent to Shell. +Add a code example block. + +bpo-35770: IDLE macosx deletes Options => Configure IDLE. +It previously deleted Window => Zoom Height by mistake. +(Zoom Height is now on the Options menu). On Mac, the settings +dialog is accessed via Preferences on the IDLE menu. + +bpo-35769: Change new file name from 'Untitled' to 'untitled'. + +bpo-35660: Fix imports in window module. + +bpo-35641: Properly format calltip for function without docstring. + +bpo-33987: Use ttk Frame for ttk widgets. + +bpo-34055: Fix erroneous 'smart' indents and newlines in IDLE Shell. + +bpo-28097: Add Previous/Next History entries to Shell menu. + +bpo-35591: Find Selection now works when selection not found. + +bpo-35598: Update config_key: use PEP 8 names and ttk widgets, +make some objects global, and add tests. + +bpo-35196: Speed up squeezer line counting. + +bpo-35208: Squeezer now counts wrapped lines before newlines. + +bpo-35555: Gray out Code Context menu entry when it's not applicable. + +bpo-22703: Improve the Code Context and Zoom Height menu labels. +The Code Context menu label now toggles between Show/Hide Code Context. +The Zoom Height menu now toggles between Zoom/Restore Height. +Zoom Height has moved from the Window menu to the Options menu. + +bpo-35521: Document the editor code context feature. +Add some internal references within the IDLE doc. + +bpo-34864: When starting IDLE on MacOS, warn if the system setting +"Prefer tabs when opening documents" is "Always". As previous +documented for this issue, running IDLE with this setting causes +problems. If the setting is changed while IDLE is running, +there will be no warning until IDLE is restarted. + +bpo-35213: Where appropriate, use 'macOS' in idlelib. + +bpo-34864: Document two IDLE on MacOS issues. The System Preferences +Dock "prefer tabs always" setting disables some IDLE features. +Menus are a bit different than as described for Windows and Linux. + +bpo-35202: Remove unused imports in idlelib. + +bpo-33000: Document that IDLE's shell has no line limit. +A program that runs indefinitely can overfill memory. + +bpo-23220: Explain how IDLE's Shell displays output. +Add new subsection "User output in Shell". + +bpo-35099: Improve the doc about IDLE running user code. +"IDLE -- console differences" is renamed "Running user code". +It mostly covers the implications of using custom sys.stdxxx objects. + +bpo-35097: Add IDLE doc subsection explaining editor windows. +Topics include opening, title and status bars, .py* extension, and running. + +Issue 35093: Document the IDLE document viewer in the IDLE doc. +Add a paragraph in "Help and preferences", "Help sources" subsection. + +bpo-1529353: Explain Shell text squeezing in the IDLE doc. + +bpo-35088: Update idlelib.help.copy_string docstring. +We now use git and backporting instead of hg and forward merging. + +bpo-35087: Update idlelib help files for the current doc build. +The main change is the elimination of chapter-section numbers. + +bpo-1529353: Output over N lines (50 by default) is squeezed down to a button. +N can be changed in the PyShell section of the General page of the +Settings dialog. Fewer, but possibly extra long, lines can be squeezed by +right clicking on the output. Squeezed output can be expanded in place +by double-clicking the button or into the clipboard or a separate window +by right-clicking the button. + +bpo-34548: Use configured color theme for read-only text views. + +bpo-33839: Refactor ToolTip and CallTip classes; add documentation +and tests. + +bpo-34047: Fix mouse wheel scrolling direction on macOS. + +bpo-34275: Make calltips always visible on Mac. +Patch by Kevin Walzer. + +bpo-34120: Fix freezing after closing some dialogs on Mac. +This is one of multiple regressions from using newer tcl/tk. + +bpo-33975: Avoid small type when running htests. +Since part of the purpose of human-viewed tests is to determine that +widgets look right, it is important that they look the same for +testing as when running IDLE. + +bpo-33905: Add test for idlelib.stackview.StackBrowser. + +bpo-33924: Change mainmenu.menudefs key 'windows' to 'window'. +Every other menudef key is the lowercase version of the +corresponding main menu entry (in this case, 'Window'). + +bpo-33906: Rename idlelib.windows as window +Match Window on the main menu and remove last plural module name. +Change imports, test, and attribute references to match new name. + +bpo-33917: Fix and document idlelib/idle_test/template.py. +The revised file compiles, runs, and tests OK. idle_test/README.txt +explains how to use it to create new IDLE test files. + +bpo-33904: In rstrip module, rename class RstripExtension as Rstrip. + +bpo-33907: For consistency and clarity, rename calltip objects. +Module calltips and its class CallTips are now calltip and Calltip. +In module calltip_w, class CallTip is now CalltipWindow. + +bpo-33855: Minimally test all IDLE modules. +Standardize the test file format. Add missing test files that import +the tested module and perform at least one test. Check and record the +coverage of each test. + +bpo-33856: Add 'help' to Shell's initial welcome message. + + +What's New in IDLE 3.7.0 (since 3.6.0) +Released on 2018-06-27 +====================================== + +bpo-33656: On Windows, add API call saying that tk scales for DPI. +On Windows 8.1+ or 10, with DPI compatibility properties of the Python +binary unchanged, and a monitor resolution greater than 96 DPI, this +should make text and lines sharper and some colors brighter. +On other systems, it should have no effect. If you have a custom theme, +you may want to adjust a color or two. If perchance it make text worse +on your monitor, you can disable the ctypes.OleDLL call near the top of +pyshell.py and report the problem on python-list or idle-dev@python.org. + +bpo-33768: Clicking on a context line moves that line to the top +of the editor window. + +bpo-33763: Replace the code context label widget with a text widget. + +bpo-33664: Scroll IDLE editor text by lines. +(Previously, the mouse wheel and scrollbar slider moved text by a fixed +number of pixels, resulting in partial lines at the top of the editor +box.) This change also applies to the shell and grep output windows, +but currently not to read-only text views. + +bpo-33679: Enable theme-specific color configuration for Code Context. +(Previously, there was one code context foreground and background font +color setting, default or custom, on the extensions tab, that applied +to all themes.) For built-in themes, the foreground is the same as +normal text and the background is a contrasting gray. Context colors for +custom themes are set on the Hightlights tab along with other colors. +When one starts IDLE from a console and loads a custom theme without +definitions for 'context', one will see a warning message on the +console. + +bpo-33642: Display up to maxlines non-blank lines for Code Context. +If there is no current context, show a single blank line. (Previously, +the Code Contex had numlines lines, usually with some blank.) The use +of a new option, 'maxlines' (default 15), avoids possible interference +with user settings of the old option, 'numlines' (default 3). + +bpo-33628: Cleanup codecontext.py and its test. + +bpo-32831: Add docstrings and tests for codecontext.py. +Coverage is 100%. Patch by Cheryl Sabella. + +bpo-33564: Code context now recognizes async as a block opener. + +bpo-21474: Update word/identifier definition from ascii to unicode. +In text and entry boxes, this affects selection by double-click, +movement left/right by control-left/right, and deletion left/right +by control-BACKSPACE/DEL. + +bpo-33204: Consistently color invalid string prefixes. +A 'u' string prefix cannot be paired with either 'r' or 'f'. +IDLE now consistently colors as much of the prefix, starting at the +right, as is valid. Revise and extend colorizer test. + +bpo-32984: Set __file__ while running a startup file. +Like Python, IDLE optionally runs 1 startup file in the Shell window +before presenting the first interactive input prompt. For IDLE, +option -s runs a file named in environmental variable IDLESTARTUP or +PYTHONSTARTUP; -r file runs file. Python sets __file__ to the startup +file name before running the file and unsets it before the first +prompt. IDLE now does the same when run normally, without the -n +option. + +bpo-32940: Replace StringTranslatePseudoMapping with faster code. + +bpo-32916: Change 'str' to 'code' in idlelib.pyparse and users. + +bpo-32905: Remove unused code in pyparse module. + +bpo-32874: IDLE - add pyparse tests with 97% coverage. + +bpo-32837: IDLE - require encoding argument for textview.view_file. +Using the system and place-dependent default encoding for open() +is a bad idea for IDLE's system and location-independent files. + +bpo-32826: Add "encoding=utf-8" to open() in IDLE's test_help_about. +GUI test test_file_buttons() only looks at initial ascii-only lines, +but failed on systems where open() defaults to 'ascii' because +readline() internally reads and decodes far enough ahead to encounter +a non-ascii character in CREDITS.txt. + +bpo-32765: Update configdialog General tab create page docstring. +Add new widgets to the widget list. + +bpo-32207: Improve tk event exception tracebacks in IDLE. +When tk event handling is driven by IDLE's run loop, a confusing +and distracting queue.EMPTY traceback context is no longer added +to tk event exception tracebacks. The traceback is now the same +as when event handling is driven by user code. Patch based on +a suggestion by Serhiy Storchaka. + +bpo-32164: Delete unused file idlelib/tabbedpages.py. +Use of TabbedPageSet in configdialog was replaced by ttk.Notebook. + +bpo-32100: Fix old and new bugs in pathbrowser; improve tests. +Patch mostly by Cheryl Sabella. + +bpo-31860: The font sample in the settings dialog is now editable. +Edits persist while IDLE remains open. +Patch by Serhiy Storchake and Terry Jan Reedy. + +bpo-31858: Restrict shell prompt manipulation to the shell. +Editor and output windows only see an empty last prompt line. This +simplifies the code and fixes a minor bug when newline is inserted. +Sys.ps1, if present, is read on Shell start-up, but is not set or changed. +Patch by Terry Jan Reedy. + +bpo-28603: Fix a TypeError that caused a shell restart when printing +a traceback that includes an exception that is unhashable. +Patch by Zane Bitter. + +bpo-13802: Use non-Latin characters in the Font settings sample. +Even if one selects a font that defines a limited subset of the unicode +Basic Multilingual Plane, tcl/tk will use other fonts that define a +character. The expanded example give users of non-Latin characters +a better idea of what they might see in the shell and editors. + +To make room for the expanded sample, frames on the Font tab are +re-arranged. The Font/Tabs help explains a bit about the additions. +Patch by Terry Jan Reedy + +bpo-31460: Simplify the API of IDLE's Module Browser. +Passing a widget instead of an flist with a root widget opens the +option of creating a browser frame that is only part of a window. +Passing a full file name instead of pieces assumed to come from a +.py file opens the possibility of browsing python files that do not +end in .py. + +bpo-31649: Make _htest and _utest parameters keyword-only. +These are used to adjust code for human and unit tests. + +bpo-31459: Rename module browser from Class Browser to Module Browser. +The original module-level class and method browser became a module +browser, with the addition of module-level functions, years ago. +Nested classes and functions were added yesterday. For back- +compatibility, the virtual event <>, which +appears on the Keys tab of the Settings dialog, is not changed. +Patch by Cheryl Sabella. + +bpo-1612262: Module browser now shows nested classes and functions. +Original patches for code and tests by Guilherme Polo and +Cheryl Sabella, respectively. Revisions by Terry Jan Reedy. + +bpo-31500: Tk's default fonts now are scaled on HiDPI displays. +This affects all dialogs. Patch by Serhiy Storchaka. + +bpo-31493: Fix code context update and font update timers. +Canceling timers prevents a warning message when test_idle completes. + +bpo-31488: Update non-key options in former extension classes. +When applying configdialog changes, call .reload for each feature class. +Change ParenMatch so updated options affect existing instances attached +to existing editor windows. + +bpo-31477: Improve rstrip entry in IDLE doc. +Strip Trailing Whitespace strips more than blank spaces. +Multiline string literals are not skipped. + +bpo-31480: fix tests to pass with zzdummy extension disabled. (#3590) +To see the example in action, enable it on options extensions tab. + +bpo-31421: Document how IDLE runs tkinter programs. +IDLE calls tcl/tk update in the background in order to make live +interaction and experimentation with tkinter applications much easier. + +bpo-31414: Fix tk entry box tests by deleting first. +Adding to an int entry is not the same as deleting and inserting +because int('') will fail. Patch by Terry Jan Reedy. + +bpo-27099: Convert IDLE's built-in 'extensions' to regular features. + About 10 IDLE features were implemented as supposedly optional +extensions. Their different behavior could be confusing or worse for +users and not good for maintenance. Hence the conversion. + The main difference for users is that user configurable key bindings +for builtin features are now handled uniformly. Now, editing a binding +in a keyset only affects its value in the keyset. All bindings are +defined together in the system-specific default keysets in config- +extensions.def. All custom keysets are saved as a whole in config- +extension.cfg. All take effect as soon as one clicks Apply or Ok. + The affected events are '<>', +'<>', '<>', '<>', +'<>', '<>', '<>', and +'<>'. Any (global) customizations made before 3.6.3 will +not affect their keyset-specific customization after 3.6.3. and vice +versa. + Initial patch by Charles Wohlganger, revised by Terry Jan Reedy. + +bpo-31051: Rearrange condigdialog General tab. +Sort non-Help options into Window (Shell+Editor) and Editor (only). +Leave room for the addition of new options. +Patch by Terry Jan Reedy. + +bpo-30617: Add docstrings and tests for outwin subclass of editor. +Move some data and functions from the class to module level. +Patch by Cheryl Sabella. + +bpo-31287: Do not modify tkinter.messagebox in test_configdialog. +Instead, mask it with an instance mock that can be deleted. +Patch by Terry Jan Reedy. + +bpo-30781: Use ttk widgets in ConfigDialog pages. +These should especially look better on MacOSX. +Patches by Terry Jan Reedy and Cheryl Sabella. + +bpo-31206: Factor HighPage(Frame) class from ConfigDialog. +Patch by Cheryl Sabella. + +bp0-31001: Add tests for configdialog highlight tab. +Patch by Cheryl Sabella. + +bpo-31205: Factor KeysPage(Frame) class from ConfigDialog. +The slightly modified tests continue to pass. +Patch by Cheryl Sabella. + +bpo-31002: Add tests for configdialog keys tab. +Patch by Cheryl Sabella. + +bpo-19903: Change calltipes to use inspect.signature. +Idlelib.calltips.get_argspec now uses inspect.signature instead of +inspect.getfullargspec, like help() does. This improves the signature +in the call tip in a few different cases, including builtins converted +to provide a signature. A message is added if the object is not +callable, has an invalid signature, or if it has positional-only +parameters. Patch by Louie Lu. + +bop-31083: Add an outline of a TabPage class in configdialog. +Add template as comment. Update existing classes to match outline. +Initial patch by Cheryl Sabella. + +bpo-31050: Factor GenPage(Frame) class from ConfigDialog. +The slightly modified tests for the General tab continue to pass. +Patch by Cheryl Sabella. + +bpo-31004: Factor FontPage(Frame) class from ConfigDialog. +The slightly modified tests continue to pass. The General test +broken by the switch to ttk.Notebook is fixed. +Patch mostly by Cheryl Sabella. + +bpo-30781: IDLE - Use ttk Notebook in ConfigDialog. +This improves navigation by tabbing. +Patch by Terry Jan Reedy. + +bpo-31060: IDLE - Finish rearranging methods of ConfigDialog. +Grouping methods pertaining to each tab and the buttons will aid +writing tests and improving the tabs and will enable splitting the +groups into classes. +Patch by Terry Jan Reedy. + +bpo-30853: IDLE -- Factor a VarTrace class out of ConfigDialog. +Instance tracers manages pairs consisting of a tk variable and a +callback function. When tracing is turned on, setting the variable +calls the function. Test coverage for the new class is 100%. +Patch by Terry Jan Reedy. + +bpo-31003: IDLE: Add more tests for General tab. +Patch by Terry Jan Reedy. + +bpo-30993: IDLE - Improve configdialog font page and tests. +*In configdialog: Document causal pathways in create_font_tab +docstring. Simplify some attribute names. Move set_samples calls to +var_changed_font (idea from Cheryl Sabella). Move related functions to +positions after the create widgets function. +* In test_configdialog: Fix test_font_set so not order dependent. Fix +renamed test_indent_scale so it tests the widget. Adjust tests for +movement of set_samples call. Add tests for load functions. Put all +font tests in one class and tab indent tests in another. Except for +two lines, these tests completely cover the related functions. +Patch by Terry Jan Reedy. + +bpo-30981: IDLE -- Add more configdialog font page tests. + +bpo-28523: IDLE: replace 'colour' with 'color' in configdialog. + +bpo-30917: Add tests for idlelib.config.IdleConf. +Increase coverage from 46% to 96%. +Patch by Louie Lu. + +bpo-30913: Document ConfigDialog tk Vars, methods, and widgets in docstrings +This will facilitate improving the dialog and splitting up the class. +Original patch by Cheryl Sabella. + +bpo-30899: Add tests for ConfigParser subclasses in config. +Coverage is 100% for those classes and ConfigChanges. +Patch by Louie Lu. + +bpo-30881: Add docstrings to browser.py. +Patch by Cheryl Sabella. + +bpo-30851: Remove unused tk variables in configdialog. +One is a duplicate, one is set but cannot be altered by users. +Patch by Cheryl Sabella. + +bpo-30870: Select font option with Up and Down keys, as well as with mouse. +Added test increases configdialog coverage to 60% +Patches mostly by Louie Lu. + +bpo-8231: Call config.IdleConf.GetUserCfgDir only once per process. + +bpo-30779: Factor ConfigChanges class from configdialog, put in config; test. +* In config, put dump test code in a function; run it and unittest in + 'if __name__ == '__main__'. +* Add class config.ConfigChanges based on changes_class_v4.py on bpo issue. +* Add class test_config.ChangesTest, partly using configdialog_tests_v1.py. +* Revise configdialog to use ConfigChanges; see tracker msg297804. +* Revise test_configdialog to match configdialog changes. +* Remove configdialog functions unused or moved to ConfigChanges. +Cheryl Sabella contributed parts of the patch. + +bpo-30777: Configdialog - add docstrings and improve comments. +Patch by Cheryl Sabella. + +bpo-30495: Improve textview with docstrings, PEP8 names, and more tests. +Split TextViewer class into ViewWindow, ViewFrame, and TextFrame classes +so that instances of the latter two can be placed with other widgets +within a multiframe window. +Patches by Cheryl Sabella and Terry Jan Reedy. + +bpo-30723: Make several improvements to parenmatch. +* Add 'parens' style to highlight both opener and closer. +* Make 'default' style, which is not default, a synonym for 'opener'. +* Make time-delay work the same with all styles. +* Add help for config dialog extensions tab, including parenmatch. +* Add new tests. +Original patch by Charles Wohlganger. Revisions by Terry Jan Reedy + +bpo-30674: Grep -- Add docstrings. Patch by Cheryl Sabella. + +bpo-21519: IDLE's basic custom key entry dialog now detects +duplicates properly. Original patch by Saimadhav Heblikar. + +bpo-29910: IDLE no longer deletes a character after commenting out a +region by a key shortcut. Add "return 'break'" for this and other +potential conflicts between IDLE and default key bindings. +Patch by Serhiy Storchaka. + +bpo-30728: Modernize idlelib.configdialog: +* replace import * with specific imports; +* lowercase method and attribute lines. +Patch by Cheryl Sabella. + +bpo-6739: Verify user-entered key sequences by trying to bind them +with to a tk widget. Add tests for all 3 validation functions. +Original patch by G Polo. Tests added by Cheryl Sabella. +Code revised and more tests added by Terry Jan Reedy + +bpo-24813: Add icon to help_about and make other changes. + +bpo-15786: Fix several problems with IDLE's autocompletion box. +The following should now work: clicking on selection box items; +using the scrollbar; selecting an item by hitting Return. +Hangs on MacOSX should no longer happen. Patch by Louie Lu. + +bpo-25514: Add doc subsubsection about IDLE failure to start. +Popup no-connection message directs users to this section. + +bpo-30642: Fix reference leaks in IDLE tests. +Patches by Louie Lu and Terry Jan Reedy. + +bpo-30495: Add docstrings for textview.py and use PEP8 names. +Patches by Cheryl Sabella and Terry Jan Reedy. + +bpo-30290: Help-about: use pep8 names and add tests. +Increase coverage to 100%. +Patches by Louie Lu, Cheryl Sabella, and Terry Jan Reedy. + +bpo-30303: Add _utest option to textview; add new tests. +Increase coverage to 100%. +Patches by Louie Lu and Terry Jan Reedy. + +Issue #29071: IDLE colors f-string prefixes but not invalid ur prefixes. + +Issue #28572: Add 10% to coverage of IDLE's test_configdialog. +Update and augment description of the configuration system. + + +What's New in IDLE 3.6.0 (since 3.5.0) +Released on 2016-12-23 +====================================== + +- Issue #15308: Add 'interrupt execution' (^C) to Shell menu. + Patch by Roger Serwy, updated by Bayard Randel. + +- Issue #27922: Stop IDLE tests from 'flashing' gui widgets on the screen. + +- Issue #27891: Consistently group and sort imports within idlelib modules. + +- Issue #17642: add larger font sizes for classroom projection. + +- Add version to title of IDLE help window. + +- Issue #25564: In section on IDLE -- console differences, mention that + using exec means that __builtins__ is defined for each statement. + +- Issue #27821: Fix 3.6.0a3 regression that prevented custom key sets + from being selected when no custom theme was defined. + +- Issue #27714: text_textview and test_autocomplete now pass when re-run + in the same process. This occurs when test_idle fails when run with the + -w option but without -jn. Fix warning from test_config. + +- Issue #27621: Put query response validation error messages in the query + box itself instead of in a separate messagebox. Redo tests to match. + Add Mac OSX refinements. Original patch by Mark Roseman. + +- Issue #27620: Escape key now closes Query box as cancelled. + +- Issue #27609: IDLE: tab after initial whitespace should tab, not + autocomplete. This fixes problem with writing docstrings at least + twice indented. + +- Issue #27609: Explicitly return None when there are also non-None + returns. In a few cases, reverse a condition and eliminate a return. + +- Issue #25507: IDLE no longer runs buggy code because of its tkinter imports. + Users must include the same imports required to run directly in Python. + +- Issue #27173: Add 'IDLE Modern Unix' to the built-in key sets. + Make the default key set depend on the platform. + Add tests for the changes to the config module. + +- Issue #27452: add line counter and crc to IDLE configHandler test dump. + +- Issue #27477: IDLE search dialogs now use ttk widgets. + +- Issue #27173: Add 'IDLE Modern Unix' to the built-in key sets. + Make the default key set depend on the platform. + Add tests for the changes to the config module. + +- Issue #27452: make command line "idle-test> python test_help.py" work. + __file__ is relative when python is started in the file's directory. + +- Issue #27452: add line counter and crc to IDLE configHandler test dump. + +- Issue #27380: IDLE: add query.py with base Query dialog and ttk widgets. + Module had subclasses SectionName, ModuleName, and HelpSource, which are + used to get information from users by configdialog and file =>Load Module. + Each subclass has itw own validity checks. Using ModuleName allows users + to edit bad module names instead of starting over. + Add tests and delete the two files combined into the new one. + +- Issue #27372: Test_idle no longer changes the locale. + +- Issue #27365: Allow non-ascii chars in IDLE NEWS.txt, for contributor names. + +- Issue #27245: IDLE: Cleanly delete custom themes and key bindings. + Previously, when IDLE was started from a console or by import, a cascade + of warnings was emitted. Patch by Serhiy Storchaka. + +- Issue #24137: Run IDLE, test_idle, and htest with tkinter default root disabled. + Fix code and tests that fail with this restriction. + Fix htests to not create a second and redundant root and mainloop. + +- Issue #27310: Fix IDLE.app failure to launch on OS X due to vestigial import. + +- Issue #5124: Paste with text selected now replaces the selection on X11. + This matches how paste works on Windows, Mac, most modern Linux apps, + and ttk widgets. Original patch by Serhiy Storchaka. + +- Issue #24750: Switch all scrollbars in IDLE to ttk versions. + Where needed, minimal tests are added to cover changes. + +- Issue #24759: IDLE requires tk 8.5 and availability ttk widgets. + Delete now unneeded tk version tests and code for older versions. + Add test for IDLE syntax colorizer. + +- Issue #27239: idlelib.macosx.isXyzTk functions initialize as needed. + +- Issue #27262: move Aqua unbinding code, which enable context menus, to macosx. + +- Issue #24759: Make clear in idlelib.idle_test.__init__ that the directory + is a private implementation of test.test_idle and tool for maintainers. + +- Issue #27196: Stop 'ThemeChanged' warnings when running IDLE tests. + These persisted after other warnings were suppressed in #20567. + Apply Serhiy Storchaka's update_idletasks solution to four test files. + Record this additional advice in idle_test/README.txt + +- Issue #20567: Revise idle_test/README.txt with advice about avoiding + tk warning messages from tests. Apply advice to several IDLE tests. + +- Issue # 24225: Update idlelib/README.txt with new file names + and event handlers. + +- Issue #27156: Remove obsolete code not used by IDLE. Replacements: + 1. help.txt, replaced by help.html, is out-of-date and should not be used. + Its dedicated viewer has be replaced by the html viewer in help.py. + 2. 'import idlever; I = idlever.IDLE_VERSION' is the same as + 'import sys; I = version[:version.index(' ')]' + 3. After 'ob = stackviewer.VariablesTreeItem(*args)', + 'ob.keys()' == 'list(ob.object.keys). + 4. In macosc, runningAsOSXAPP == isAquaTk; idCarbonAquaTk == isCarbonTk + +- Issue #27117: Make colorizer htest and turtledemo work with dark themes. + Move code for configuring text widget colors to a new function. + +- Issue #24225: Rename many idlelib/*.py and idle_test/test_*.py files. + Edit files to replace old names with new names when the old name + referred to the module rather than the class it contained. + See the issue and IDLE section in What's New in 3.6 for more. + +- Issue #26673: When tk reports font size as 0, change to size 10. + Such fonts on Linux prevented the configuration dialog from opening. + +- Issue #21939: Add test for IDLE's percolator. + Original patch by Saimadhav Heblikar. + +- Issue #21676: Add test for IDLE's replace dialog. + Original patch by Saimadhav Heblikar. + +- Issue #18410: Add test for IDLE's search dialog. + Original patch by Westley Martínez. + +- Issue #21703: Add test for undo delegator. Patch mostly by + Saimadhav Heblikar . + +- Issue #27044: Add ConfigDialog.remove_var_callbacks to stop memory leaks. + +- Issue #23977: Add more asserts to test_delegator. + +- Issue #20640: Add tests for idlelib.configHelpSourceEdit. + Patch by Saimadhav Heblikar. + +- In the 'IDLE-console differences' section of the IDLE doc, clarify + how running with IDLE affects sys.modules and the standard streams. + +- Issue #25507: fix incorrect change in IOBinding that prevented printing. + Augment IOBinding htest to include all major IOBinding functions. + +- Issue #25905: Revert unwanted conversion of ' to ’ RIGHT SINGLE QUOTATION + MARK in README.txt and open this and NEWS.txt with 'ascii'. + Re-encode CREDITS.txt to utf-8 and open it with 'utf-8'. + +- Issue 15348: Stop the debugger engine (normally in a user process) + before closing the debugger window (running in the IDLE process). + This prevents the RuntimeErrors that were being caught and ignored. + +- Issue #24455: Prevent IDLE from hanging when a) closing the shell while the + debugger is active (15347); b) closing the debugger with the [X] button + (15348); and c) activating the debugger when already active (24455). + The patch by Mark Roseman does this by making two changes. + 1. Suspend and resume the gui.interaction method with the tcl vwait + mechanism intended for this purpose (instead of root.mainloop & .quit). + 2. In gui.run, allow any existing interaction to terminate first. + +- Change 'The program' to 'Your program' in an IDLE 'kill program?' message + to make it clearer that the program referred to is the currently running + user program, not IDLE itself. + +- Issue #24750: Improve the appearance of the IDLE editor window status bar. + Patch by Mark Roseman. + +- Issue #25313: Change the handling of new built-in text color themes to better + address the compatibility problem introduced by the addition of IDLE Dark. + Consistently use the revised idleConf.CurrentTheme everywhere in idlelib. + +- Issue #24782: Extension configuration is now a tab in the IDLE Preferences + dialog rather than a separate dialog. The former tabs are now a sorted + list. Patch by Mark Roseman. + +- Issue #22726: Re-activate the config dialog help button with some content + about the other buttons and the new IDLE Dark theme. + +- Issue #24820: IDLE now has an 'IDLE Dark' built-in text color theme. + It is more or less IDLE Classic inverted, with a cobalt blue background. + Strings, comments, keywords, ... are still green, red, orange, ... . + To use it with IDLEs released before November 2015, hit the + 'Save as New Custom Theme' button and enter a new name, + such as 'Custom Dark'. The custom theme will work with any IDLE + release, and can be modified. + +- Issue #25224: README.txt is now an idlelib index for IDLE developers and + curious users. The previous user content is now in the IDLE doc chapter. + 'IDLE' now means 'Integrated Development and Learning Environment'. + +- Issue #24820: Users can now set breakpoint colors in + Settings -> Custom Highlighting. Original patch by Mark Roseman. + +- Issue #24972: Inactive selection background now matches active selection + background, as configured by users, on all systems. Found items are now + always highlighted on Windows. Initial patch by Mark Roseman. + +- Issue #24570: Idle: make calltip and completion boxes appear on Macs + affected by a tk regression. Initial patch by Mark Roseman. + +- Issue #24988: Idle ScrolledList context menus (used in debugger) + now work on Mac Aqua. Patch by Mark Roseman. + +- Issue #24801: Make right-click for context menu work on Mac Aqua. + Patch by Mark Roseman. + +- Issue #25173: Associate tkinter messageboxes with a specific widget. + For Mac OSX, make them a 'sheet'. Patch by Mark Roseman. + +- Issue #25198: Enhance the initial html viewer now used for Idle Help. + * Properly indent fixed-pitch text (patch by Mark Roseman). + * Give code snippet a very Sphinx-like light blueish-gray background. + * Re-use initial width and height set by users for shell and editor. + * When the Table of Contents (TOC) menu is used, put the section header + at the top of the screen. + +- Issue #25225: Condense and rewrite Idle doc section on text colors. + +- Issue #21995: Explain some differences between IDLE and console Python. + +- Issue #22820: Explain need for *print* when running file from Idle editor. + +- Issue #25224: Doc: augment Idle feature list and no-subprocess section. + +- Issue #25219: Update doc for Idle command line options. + Some were missing and notes were not correct. + +- Issue #24861: Most of idlelib is private and subject to change. + Use idleib.idle.* to start Idle. See idlelib.__init__.__doc__. + +- Issue #25199: Idle: add synchronization comments for future maintainers. + +- Issue #16893: Replace help.txt with help.html for Idle doc display. + The new idlelib/help.html is rstripped Doc/build/html/library/idle.html. + It looks better than help.txt and will better document Idle as released. + The tkinter html viewer that works for this file was written by Mark Roseman. + The now unused EditorWindow.HelpDialog class and helt.txt file are deprecated. + +- Issue #24199: Deprecate unused idlelib.idlever with possible removal in 3.6. + +- Issue #24790: Remove extraneous code (which also create 2 & 3 conflicts). + + +What's New in IDLE 3.5.0? +========================= +*Release date: 2015-09-13* + +- Issue #23672: Allow Idle to edit and run files with astral chars in name. + Patch by Mohd Sanad Zaki Rizvi. + +- Issue 24745: Idle editor default font. Switch from Courier to + platform-sensitive TkFixedFont. This should not affect current customized + font selections. If there is a problem, edit $HOME/.idlerc/config-main.cfg + and remove 'fontxxx' entries from [Editor Window]. Patch by Mark Roseman. + +- Issue #21192: Idle editor. When a file is run, put its name in the restart bar. + Do not print false prompts. Original patch by Adnan Umer. + +- Issue #13884: Idle menus. Remove tearoff lines. Patch by Roger Serwy. + +- Issue #23184: remove unused names and imports in idlelib. + Initial patch by Al Sweigart. + +- Issue #20577: Configuration of the max line length for the FormatParagraph + extension has been moved from the General tab of the Idle preferences dialog + to the FormatParagraph tab of the Config Extensions dialog. + Patch by Tal Einat. + +- Issue #16893: Update Idle doc chapter to match current Idle and add new + information. + +- Issue #3068: Add Idle extension configuration dialog to Options menu. + Changes are written to HOME/.idlerc/config-extensions.cfg. + Original patch by Tal Einat. + +- Issue #16233: A module browser (File : Class Browser, Alt+C) requires an + editor window with a filename. When Class Browser is requested otherwise, + from a shell, output window, or 'Untitled' editor, Idle no longer displays + an error box. It now pops up an Open Module box (Alt+M). If a valid name + is entered and a module is opened, a corresponding browser is also opened. + +- Issue #4832: Save As to type Python files automatically adds .py to the + name you enter (even if your system does not display it). Some systems + automatically add .txt when type is Text files. + +- Issue #21986: Code objects are not normally pickled by the pickle module. + To match this, they are no longer pickled when running under Idle. + +- Issue #23180: Rename IDLE "Windows" menu item to "Window". + Patch by Al Sweigart. + +- Issue #17390: Adjust Editor window title; remove 'Python', + move version to end. + +- Issue #14105: Idle debugger breakpoints no longer disappear + when inserting or deleting lines. + +- Issue #17172: Turtledemo can now be run from Idle. + Currently, the entry is on the Help menu, but it may move to Run. + Patch by Ramchandra Apt and Lita Cho. + +- Issue #21765: Add support for non-ascii identifiers to HyperParser. + +- Issue #21940: Add unittest for WidgetRedirector. Initial patch by Saimadhav + Heblikar. + +- Issue #18592: Add unittest for SearchDialogBase. Patch by Phil Webster. + +- Issue #21694: Add unittest for ParenMatch. Patch by Saimadhav Heblikar. + +- Issue #21686: add unittest for HyperParser. Original patch by Saimadhav + Heblikar. + +- Issue #12387: Add missing upper(lower)case versions of default Windows key + bindings for Idle so Caps Lock does not disable them. Patch by Roger Serwy. + +- Issue #21695: Closing a Find-in-files output window while the search is + still in progress no longer closes Idle. + +- Issue #18910: Add unittest for textView. Patch by Phil Webster. + +- Issue #18292: Add unittest for AutoExpand. Patch by Saihadhav Heblikar. + +- Issue #18409: Add unittest for AutoComplete. Patch by Phil Webster. + +- Issue #21477: htest.py - Improve framework, complete set of tests. + Patches by Saimadhav Heblikar + +- Issue #18104: Add idlelib/idle_test/htest.py with a few sample tests to begin + consolidating and improving human-validated tests of Idle. Change other files + as needed to work with htest. Running the module as __main__ runs all tests. + +- Issue #21139: Change default paragraph width to 72, the PEP 8 recommendation. + +- Issue #21284: Paragraph reformat test passes after user changes reformat width. + +- Issue #17654: Ensure IDLE menus are customized properly on OS X for + non-framework builds and for all variants of Tk. + + +What's New in IDLE 3.4.0? +========================= +*Release date: 2014-03-16* + +- Issue #17390: Display Python version on Idle title bar. + Initial patch by Edmond Burnett. + +- Issue #5066: Update IDLE docs. Patch by Todd Rovito. + +- Issue #17625: Close the replace dialog after it is used. + +- Issue #16226: Fix IDLE Path Browser crash. + (Patch by Roger Serwy) + +- Issue #15853: Prevent IDLE crash on OS X when opening Preferences menu + with certain versions of Tk 8.5. Initial patch by Kevin Walzer. + + +What's New in IDLE 3.3.0? +========================= +*Release date: 2012-09-29* + +- Issue #17625: Close the replace dialog after it is used. + +- Issue #7163: Propagate return value of sys.stdout.write. + +- Issue #15318: Prevent writing to sys.stdin. + +- Issue #4832: Modify IDLE to save files with .py extension by + default on Windows and OS X (Tk 8.5) as it already does with X11 Tk. + +- Issue #13532, #15319: Check that arguments to sys.stdout.write are strings. + +- Issue # 12510: Attempt to get certain tool tips no longer crashes IDLE. + Erroneous tool tips have been corrected. Default added for callables. + +- Issue #10365: File open dialog now works instead of crashing even when + parent window is closed while dialog is open. + +- Issue 14876: use user-selected font for highlight configuration. + +- Issue #14937: Perform auto-completion of filenames in strings even for + non-ASCII filenames. Likewise for identifiers. + +- Issue #8515: Set __file__ when run file in IDLE. + Initial patch by Bruce Frederiksen. + +- IDLE can be launched as `python -m idlelib` + +- Issue #14409: IDLE now properly executes commands in the Shell window + when it cannot read the normal config files on startup and + has to use the built-in default key bindings. + There was previously a bug in one of the defaults. + +- Issue #3573: IDLE hangs when passing invalid command line args + (directory(ies) instead of file(s)). + +- Issue #14018: Update checks for unstable system Tcl/Tk versions on OS X + to include versions shipped with OS X 10.7 and 10.8 in addition to 10.6. + + +What's New in IDLE 3.2.1? +========================= +*Release date: 15-May-11* + +- Issue #6378: Further adjust idle.bat to start associated Python + +- Issue #11896: Save on Close failed despite selecting "Yes" in dialog. + +- Issue #1028: Ctrl-space binding to show completions was causing IDLE to exit. + Tk < 8.5 was sending invalid Unicode null; replaced with valid null. + +- Issue #4676: toggle failing on Tk 8.5, causing IDLE exits and strange selection + behavior. Improve selection extension behaviour. + +- Issue #3851: toggle non-functional when NumLock set on Windows. + + +What's New in IDLE 3.1b1? +========================= +*Release date: 06-May-09* + +- Issue #5707: Use of 'filter' in keybindingDialog.py was causing custom key assignment to + fail. Patch by Amaury Forgeot d'Arc. + +- Issue #4815: Offer conversion to UTF-8 if source files have + no encoding declaration and are not encoded in UTF-8. + +- Issue #4008: Fix problems with non-ASCII source files. + +- Issue #4323: Always encode source as UTF-8 without asking + the user (unless a different encoding is declared); remove + user configuration of source encoding; all according to + PEP 3120. + +- Issue #2665: On Windows, an IDLE installation upgraded from an old version + would not start if a custom theme was defined. + +------------------------------------------------------------------------ +Refer to NEWS2x.txt and HISTORY.txt for information on earlier releases. +------------------------------------------------------------------------ diff --git a/Lib/idlelib/browser.py b/Lib/idlelib/browser.py index 4fe64dced60aca..8b9060e57072ea 100644 --- a/Lib/idlelib/browser.py +++ b/Lib/idlelib/browser.py @@ -250,9 +250,11 @@ def closure(): class Nested_in_closure: pass ModuleBrowser(parent, file, _htest=True) + if __name__ == "__main__": if len(sys.argv) == 1: # If pass file on command line, unittest fails. from unittest import main main('idlelib.idle_test.test_browser', verbosity=2, exit=False) + from idlelib.idle_test.htest import run run(_module_browser) diff --git a/Lib/idlelib/calltip_w.py b/Lib/idlelib/calltip_w.py index 278546064adde2..9386376058c791 100644 --- a/Lib/idlelib/calltip_w.py +++ b/Lib/idlelib/calltip_w.py @@ -193,6 +193,7 @@ def calltip_hide(event): text.focus_set() + if __name__ == '__main__': from unittest import main main('idlelib.idle_test.test_calltip_w', verbosity=2, exit=False) diff --git a/Lib/idlelib/config.py b/Lib/idlelib/config.py index 2b09d79470b47c..92992fd9cce9cd 100644 --- a/Lib/idlelib/config.py +++ b/Lib/idlelib/config.py @@ -597,7 +597,9 @@ def GetCoreKeys(self, keySetName=None): problem getting any core binding there will be an 'ultimate last resort fallback' to the CUA-ish bindings defined here. """ + # TODO: = dict(sorted([(v-event, keys), ...]))? keyBindings={ + # vitual-event: list of key events. '<>': ['', ''], '<>': ['', ''], '<>': ['', ''], @@ -880,7 +882,7 @@ def _dump(): # htest # (not really, but ignore in coverage) line, crc = 0, 0 def sprint(obj): - global line, crc + nonlocal line, crc txt = str(obj) line += 1 crc = crc32(txt.encode(encoding='utf-8'), crc) @@ -889,7 +891,7 @@ def sprint(obj): def dumpCfg(cfg): print('\n', cfg, '\n') # Cfg has variable '0xnnnnnnnn' address. - for key in sorted(cfg.keys()): + for key in sorted(cfg): sections = cfg[key].sections() sprint(key) sprint(sections) @@ -904,8 +906,11 @@ def dumpCfg(cfg): dumpCfg(idleConf.userCfg) print('\nlines = ', line, ', crc = ', crc, sep='') + if __name__ == '__main__': from unittest import main main('idlelib.idle_test.test_config', verbosity=2, exit=False) - # Run revised _dump() as htest? + _dump() + # Run revised _dump() (700+ lines) as htest? More sorting. + # Perhaps as window with tabs for textviews, making it config viewer. diff --git a/Lib/idlelib/config_key.py b/Lib/idlelib/config_key.py index bb07231cd590b6..e5f67e8d4069ee 100644 --- a/Lib/idlelib/config_key.py +++ b/Lib/idlelib/config_key.py @@ -351,4 +351,4 @@ def cancel(self, event=None): main('idlelib.idle_test.test_config_key', verbosity=2, exit=False) from idlelib.idle_test.htest import run - run(GetKeysDialog) + run(GetKeysWindow) diff --git a/Lib/idlelib/configdialog.py b/Lib/idlelib/configdialog.py index cda7966d558a51..eedf97bf74fe6a 100644 --- a/Lib/idlelib/configdialog.py +++ b/Lib/idlelib/configdialog.py @@ -211,14 +211,8 @@ def help(self): contents=help_common+help_pages.get(page, '')) def deactivate_current_config(self): - """Remove current key bindings. - Iterate over window instances defined in parent and remove - the keybindings. - """ - # Before a config is saved, some cleanup of current - # config must be done - remove the previous keybindings. - win_instances = self.parent.instance_dict.keys() - for instance in win_instances: + """Remove current key bindings in current windows.""" + for instance in self.parent.instance_dict: instance.RemoveKeybindings() def activate_config_changes(self): @@ -227,8 +221,7 @@ def activate_config_changes(self): Dynamically update the current parent window instances with some of the configuration changes. """ - win_instances = self.parent.instance_dict.keys() - for instance in win_instances: + for instance in self.parent.instance_dict: instance.ResetColorizer() instance.ResetFont() instance.set_notabs_indentwidth() @@ -583,22 +576,23 @@ def create_page_highlight(self): (*)theme_message: Label """ self.theme_elements = { - 'Normal Code or Text': ('normal', '00'), - 'Code Context': ('context', '01'), - 'Python Keywords': ('keyword', '02'), - 'Python Definitions': ('definition', '03'), - 'Python Builtins': ('builtin', '04'), - 'Python Comments': ('comment', '05'), - 'Python Strings': ('string', '06'), - 'Selected Text': ('hilite', '07'), - 'Found Text': ('hit', '08'), - 'Cursor': ('cursor', '09'), - 'Editor Breakpoint': ('break', '10'), - 'Shell Prompt': ('console', '11'), - 'Error Text': ('error', '12'), - 'Shell User Output': ('stdout', '13'), - 'Shell User Exception': ('stderr', '14'), - 'Line Number': ('linenumber', '16'), + # Display-name: internal-config-tag-name. + 'Normal Code or Text': 'normal', + 'Code Context': 'context', + 'Python Keywords': 'keyword', + 'Python Definitions': 'definition', + 'Python Builtins': 'builtin', + 'Python Comments': 'comment', + 'Python Strings': 'string', + 'Selected Text': 'hilite', + 'Found Text': 'hit', + 'Cursor': 'cursor', + 'Editor Breakpoint': 'break', + 'Shell Prompt': 'console', + 'Error Text': 'error', + 'Shell User Output': 'stdout', + 'Shell User Exception': 'stderr', + 'Line Number': 'linenumber', } self.builtin_name = tracers.add( StringVar(self), self.var_changed_builtin_name) @@ -658,7 +652,7 @@ def tem(event, elem=element): # event.widget.winfo_top_level().highlight_target.set(elem) self.highlight_target.set(elem) text.tag_bind( - self.theme_elements[element][0], '', tem) + self.theme_elements[element], '', tem) text['state'] = 'disabled' self.style.configure('frame_color_set.TFrame', borderwidth=1, relief='solid') @@ -765,8 +759,7 @@ def load_theme_cfg(self): self.builtinlist.SetMenu(item_list, item_list[0]) self.set_theme_type() # Load theme element option menu. - theme_names = list(self.theme_elements.keys()) - theme_names.sort(key=lambda x: self.theme_elements[x][1]) + theme_names = list(self.theme_elements) self.targetlist.SetMenu(theme_names, theme_names[0]) self.paint_theme_sample() self.set_highlight_target() @@ -893,7 +886,7 @@ def on_new_color_set(self): new_color = self.color.get() self.style.configure('frame_color_set.TFrame', background=new_color) plane = 'foreground' if self.fg_bg_toggle.get() else 'background' - sample_element = self.theme_elements[self.highlight_target.get()][0] + sample_element = self.theme_elements[self.highlight_target.get()] self.highlight_sample.tag_config(sample_element, **{plane: new_color}) theme = self.custom_name.get() theme_element = sample_element + '-' + plane @@ -1007,7 +1000,7 @@ def set_color_sample(self): frame_color_set """ # Set the color sample area. - tag = self.theme_elements[self.highlight_target.get()][0] + tag = self.theme_elements[self.highlight_target.get()] plane = 'foreground' if self.fg_bg_toggle.get() else 'background' color = self.highlight_sample.tag_cget(tag, plane) self.style.configure('frame_color_set.TFrame', background=color) @@ -1037,7 +1030,7 @@ def paint_theme_sample(self): else: # User theme theme = self.custom_name.get() for element_title in self.theme_elements: - element = self.theme_elements[element_title][0] + element = self.theme_elements[element_title] colors = idleConf.GetHighlight(theme, element) if element == 'cursor': # Cursor sample needs special painting. colors['background'] = idleConf.GetHighlight( @@ -1477,12 +1470,13 @@ def load_keys_list(self, keyset_name): reselect = True list_index = self.bindingslist.index(ANCHOR) keyset = idleConf.GetKeySet(keyset_name) - bind_names = list(keyset.keys()) + # 'set' is dict mapping virtual event to list of key events. + bind_names = list(keyset) bind_names.sort() self.bindingslist.delete(0, END) for bind_name in bind_names: key = ' '.join(keyset[bind_name]) - bind_name = bind_name[2:-2] # Trim off the angle brackets. + bind_name = bind_name[2:-2] # Trim double angle brackets. if keyset_name in changes['keys']: # Handle any unsaved changes to this key set. if bind_name in changes['keys'][keyset_name]: diff --git a/Lib/idlelib/debugger.py b/Lib/idlelib/debugger.py index 452c62b42655b3..f487b4c4b16a60 100644 --- a/Lib/idlelib/debugger.py +++ b/Lib/idlelib/debugger.py @@ -1,3 +1,20 @@ +"""Debug user code with a GUI interface to a subclass of bdb.Bdb. + +The Idb idb and Debugger gui instances each need a reference to each +other or to an rpc proxy for each other. + +If IDLE is started with '-n', so that user code and idb both run in the +IDLE process, Debugger is called without an idb. Debugger.__init__ +calls Idb with its incomplete self. Idb.__init__ stores gui and gui +then stores idb. + +If IDLE is started normally, so that user code executes in a separate +process, debugger_r.start_remote_debugger is called, executing in the +IDLE process. It calls 'start the debugger' in the remote process, +which calls Idb with a gui proxy. Then Debugger is called in the IDLE +for more. +""" + import bdb import os @@ -10,66 +27,95 @@ class Idb(bdb.Bdb): + "Supply user_line and user_exception functions for Bdb." def __init__(self, gui): - self.gui = gui # An instance of Debugger or proxy of remote. - bdb.Bdb.__init__(self) + self.gui = gui # An instance of Debugger or proxy thereof. + super().__init__() def user_line(self, frame): - if self.in_rpc_code(frame): + """Handle a user stopping or breaking at a line. + + Convert frame to a string and send it to gui. + """ + if _in_rpc_code(frame): self.set_step() return - message = self.__frame2message(frame) + message = _frame2message(frame) try: self.gui.interaction(message, frame) except TclError: # When closing debugger window with [x] in 3.x pass - def user_exception(self, frame, info): - if self.in_rpc_code(frame): + def user_exception(self, frame, exc_info): + """Handle an the occurrence of an exception.""" + if _in_rpc_code(frame): self.set_step() return - message = self.__frame2message(frame) - self.gui.interaction(message, frame, info) - - def in_rpc_code(self, frame): - if frame.f_code.co_filename.count('rpc.py'): - return True - else: - prev_frame = frame.f_back - prev_name = prev_frame.f_code.co_filename - if 'idlelib' in prev_name and 'debugger' in prev_name: - # catch both idlelib/debugger.py and idlelib/debugger_r.py - # on both Posix and Windows - return False - return self.in_rpc_code(prev_frame) - - def __frame2message(self, frame): - code = frame.f_code - filename = code.co_filename - lineno = frame.f_lineno - basename = os.path.basename(filename) - message = f"{basename}:{lineno}" - if code.co_name != "?": - message = f"{message}: {code.co_name}()" - return message + message = _frame2message(frame) + self.gui.interaction(message, frame, exc_info) + +def _in_rpc_code(frame): + "Determine if debugger is within RPC code." + if frame.f_code.co_filename.count('rpc.py'): + return True # Skip this frame. + else: + prev_frame = frame.f_back + if prev_frame is None: + return False + prev_name = prev_frame.f_code.co_filename + if 'idlelib' in prev_name and 'debugger' in prev_name: + # catch both idlelib/debugger.py and idlelib/debugger_r.py + # on both Posix and Windows + return False + return _in_rpc_code(prev_frame) + +def _frame2message(frame): + """Return a message string for frame.""" + code = frame.f_code + filename = code.co_filename + lineno = frame.f_lineno + basename = os.path.basename(filename) + message = f"{basename}:{lineno}" + if code.co_name != "?": + message = f"{message}: {code.co_name}()" + return message class Debugger: - - vstack = vsource = vlocals = vglobals = None + """The debugger interface. + + This class handles the drawing of the debugger window and + the interactions with the underlying debugger session. + """ + vstack = None + vsource = None + vlocals = None + vglobals = None + stackviewer = None + localsviewer = None + globalsviewer = None def __init__(self, pyshell, idb=None): + """Instantiate and draw a debugger window. + + :param pyshell: An instance of the PyShell Window + :type pyshell: :class:`idlelib.pyshell.PyShell` + + :param idb: An instance of the IDLE debugger (optional) + :type idb: :class:`idlelib.debugger.Idb` + """ if idb is None: idb = Idb(self) self.pyshell = pyshell self.idb = idb # If passed, a proxy of remote instance. self.frame = None self.make_gui() - self.interacting = 0 + self.interacting = False self.nesting_level = 0 def run(self, *args): + """Run the debugger.""" # Deal with the scenario where we've already got a program running # in the debugger and we want to start another. If that is the case, # our second 'run' was invoked from an event dispatched not from @@ -104,12 +150,13 @@ def run(self, *args): self.root.after(100, lambda: self.run(*args)) return try: - self.interacting = 1 + self.interacting = True return self.idb.run(*args) finally: - self.interacting = 0 + self.interacting = False def close(self, event=None): + """Close the debugger and window.""" try: self.quit() except Exception: @@ -127,6 +174,7 @@ def close(self, event=None): self.top.destroy() def make_gui(self): + """Draw the debugger gui on the screen.""" pyshell = self.pyshell self.flist = pyshell.flist self.root = root = pyshell.root @@ -135,11 +183,11 @@ def make_gui(self): self.top.wm_iconname("Debug") top.wm_protocol("WM_DELETE_WINDOW", self.close) self.top.bind("", self.close) - # + self.bframe = bframe = Frame(top) self.bframe.pack(anchor="w") self.buttons = bl = [] - # + self.bcont = b = Button(bframe, text="Go", command=self.cont) bl.append(b) self.bstep = b = Button(bframe, text="Step", command=self.step) @@ -150,14 +198,14 @@ def make_gui(self): bl.append(b) self.bret = b = Button(bframe, text="Quit", command=self.quit) bl.append(b) - # + for b in bl: b.configure(state="disabled") b.pack(side="left") - # + self.cframe = cframe = Frame(bframe) self.cframe.pack(side="left") - # + if not self.vstack: self.__class__.vstack = BooleanVar(top) self.vstack.set(1) @@ -180,20 +228,20 @@ def make_gui(self): self.bglobals = Checkbutton(cframe, text="Globals", command=self.show_globals, variable=self.vglobals) self.bglobals.grid(row=1, column=1) - # + self.status = Label(top, anchor="w") self.status.pack(anchor="w") self.error = Label(top, anchor="w") self.error.pack(anchor="w", fill="x") self.errorbg = self.error.cget("background") - # + self.fstack = Frame(top, height=1) self.fstack.pack(expand=1, fill="both") self.flocals = Frame(top) self.flocals.pack(expand=1, fill="both") self.fglobals = Frame(top, height=1) self.fglobals.pack(expand=1, fill="both") - # + if self.vstack.get(): self.show_stack() if self.vlocals.get(): @@ -204,7 +252,7 @@ def make_gui(self): def interaction(self, message, frame, info=None): self.frame = frame self.status.configure(text=message) - # + if info: type, value, tb = info try: @@ -223,28 +271,28 @@ def interaction(self, message, frame, info=None): tb = None bg = self.errorbg self.error.configure(text=m1, background=bg) - # + sv = self.stackviewer if sv: stack, i = self.idb.get_stack(self.frame, tb) sv.load_stack(stack, i) - # + self.show_variables(1) - # + if self.vsource.get(): self.sync_source_line() - # + for b in self.buttons: b.configure(state="normal") - # + self.top.wakeup() # Nested main loop: Tkinter's main loop is not reentrant, so use # Tcl's vwait facility, which reenters the event loop until an - # event handler sets the variable we're waiting on + # event handler sets the variable we're waiting on. self.nesting_level += 1 self.root.tk.call('vwait', '::idledebugwait') self.nesting_level -= 1 - # + for b in self.buttons: b.configure(state="disabled") self.status.configure(text="") @@ -288,8 +336,6 @@ def quit(self): def abort_loop(self): self.root.tk.call('set', '::idledebugwait', '1') - stackviewer = None - def show_stack(self): if not self.stackviewer and self.vstack.get(): self.stackviewer = sv = StackViewer(self.fstack, self.flist, self) @@ -311,9 +357,6 @@ def show_frame(self, stackitem): self.frame = stackitem[0] # lineno is stackitem[1] self.show_variables() - localsviewer = None - globalsviewer = None - def show_locals(self): lv = self.localsviewer if self.vlocals.get(): @@ -354,26 +397,32 @@ def show_variables(self, force=0): if gv: gv.load_dict(gdict, force, self.pyshell.interp.rpcclt) - def set_breakpoint_here(self, filename, lineno): + def set_breakpoint(self, filename, lineno): + """Set a filename-lineno breakpoint in the debugger. + + Called from self.load_breakpoints and EW.setbreakpoint + """ self.idb.set_break(filename, lineno) - def clear_breakpoint_here(self, filename, lineno): + def clear_breakpoint(self, filename, lineno): self.idb.clear_break(filename, lineno) def clear_file_breaks(self, filename): self.idb.clear_all_file_breaks(filename) def load_breakpoints(self): - "Load PyShellEditorWindow breakpoints into subprocess debugger" + """Load PyShellEditorWindow breakpoints into subprocess debugger.""" for editwin in self.pyshell.flist.inversedict: filename = editwin.io.filename try: for lineno in editwin.breakpoints: - self.set_breakpoint_here(filename, lineno) + self.set_breakpoint(filename, lineno) except AttributeError: continue + class StackViewer(ScrolledList): + "Code stack viewer for debugger GUI." def __init__(self, master, flist, gui): if macosx.isAquaTk(): @@ -414,12 +463,12 @@ def load_stack(self, stack, index=None): self.select(index) def popup_event(self, event): - "override base method" + "Override base method." if self.stack: return ScrolledList.popup_event(self, event) def fill_menu(self): - "override base method" + "Override base method." menu = self.menu menu.add_command(label="Go to source line", command=self.goto_source_line) @@ -427,12 +476,12 @@ def fill_menu(self): command=self.show_stack_frame) def on_select(self, index): - "override base method" + "Override base method." if 0 <= index < len(self.stack): self.gui.show_frame(self.stack[index]) def on_double(self, index): - "override base method" + "Override base method." self.show_source(index) def goto_source_line(self): @@ -457,6 +506,7 @@ def show_source(self, index): class NamespaceViewer: + "Global/local namespace viewer for debugger GUI." def __init__(self, master, title, dict=None): width = 0 @@ -509,7 +559,7 @@ def load_dict(self, dict, force=0, rpc_client=None): # There is also an obscure bug in sorted(dict) where the # interpreter gets into a loop requesting non-existing dict[0], # dict[1], dict[2], etc from the debugger_r.DictProxy. - ### + # TODO recheck above; see debugger_r 159ff, debugobj 60. keys_list = dict.keys() names = sorted(keys_list) ### @@ -544,6 +594,7 @@ def load_dict(self, dict, force=0, rpc_client=None): def close(self): self.frame.destroy() + if __name__ == "__main__": from unittest import main main('idlelib.idle_test.test_debugger', verbosity=2, exit=False) diff --git a/Lib/idlelib/debugobj.py b/Lib/idlelib/debugobj.py index 71d01c7070df54..156377f8ed26ac 100644 --- a/Lib/idlelib/debugobj.py +++ b/Lib/idlelib/debugobj.py @@ -93,7 +93,8 @@ def setfunction(value, key=key, object=self.object): class DictTreeItem(SequenceTreeItem): def keys(self): - keys = list(self.object.keys()) + # TODO return sorted(self.object) + keys = list(self.object) try: keys.sort() except: @@ -119,7 +120,7 @@ def make_objecttreeitem(labeltext, object, setfunction=None): return c(labeltext, object, setfunction) -def _object_browser(parent): # htest # +def _debug_object_browser(parent): # htest # import sys from tkinter import Toplevel top = Toplevel(parent) @@ -134,9 +135,10 @@ def _object_browser(parent): # htest # node = TreeNode(sc.canvas, None, item) node.update() + if __name__ == '__main__': from unittest import main main('idlelib.idle_test.test_debugobj', verbosity=2, exit=False) from idlelib.idle_test.htest import run - run(_object_browser) + run(_debug_object_browser) diff --git a/Lib/idlelib/delegator.py b/Lib/idlelib/delegator.py index 55c95da8532f47..93ae8bbd43ff44 100644 --- a/Lib/idlelib/delegator.py +++ b/Lib/idlelib/delegator.py @@ -28,6 +28,7 @@ def setdelegate(self, delegate): self.resetcache() self.delegate = delegate + if __name__ == '__main__': from unittest import main main('idlelib.idle_test.test_delegator', verbosity=2) diff --git a/Lib/idlelib/dynoption.py b/Lib/idlelib/dynoption.py index d5dfc3eda13f60..b8937f7106ca75 100644 --- a/Lib/idlelib/dynoption.py +++ b/Lib/idlelib/dynoption.py @@ -29,6 +29,7 @@ def SetMenu(self,valueList,value=None): if value: self.variable.set(value) + def _dyn_option_menu(parent): # htest # from tkinter import Toplevel # + StringVar, Button @@ -49,6 +50,7 @@ def update(): button = Button(top, text="Change option set", command=update) button.pack() + if __name__ == '__main__': # Only module without unittests because of intention to replace. from idlelib.idle_test.htest import run diff --git a/Lib/idlelib/editor.py b/Lib/idlelib/editor.py index 69b27d0683a104..6ad383f460c7ee 100644 --- a/Lib/idlelib/editor.py +++ b/Lib/idlelib/editor.py @@ -1748,6 +1748,7 @@ def _editor_window(parent): # htest # # Does not stop error, neither does following # edit.text.bind("<>", edit.close_event) + if __name__ == '__main__': from unittest import main main('idlelib.idle_test.test_editor', verbosity=2, exit=False) diff --git a/Lib/idlelib/filelist.py b/Lib/idlelib/filelist.py index f87781d2570fe0..e27e5d32a0ff63 100644 --- a/Lib/idlelib/filelist.py +++ b/Lib/idlelib/filelist.py @@ -124,6 +124,7 @@ def _test(): # TODO check and convert to htest if flist.inversedict: root.mainloop() + if __name__ == '__main__': from unittest import main main('idlelib.idle_test.test_filelist', verbosity=2) diff --git a/Lib/idlelib/grep.py b/Lib/idlelib/grep.py index 12513594b76f8f..ef14349960bfa2 100644 --- a/Lib/idlelib/grep.py +++ b/Lib/idlelib/grep.py @@ -204,15 +204,17 @@ def _grep_dialog(parent): # htest # frame.pack() text = Text(frame, height=5) text.pack() + text.insert('1.0', 'import grep') def show_grep_dialog(): - text.tag_add(SEL, "1.0", END) + text.tag_add(SEL, "1.0", '1.end') grep(text, flist=flist) - text.tag_remove(SEL, "1.0", END) + text.tag_remove(SEL, "1.0", '1.end') button = Button(frame, text="Show GrepDialog", command=show_grep_dialog) button.pack() + if __name__ == "__main__": from unittest import main main('idlelib.idle_test.test_grep', verbosity=2, exit=False) diff --git a/Lib/idlelib/help.py b/Lib/idlelib/help.py index cc027b9cef4f5b..dfccfcb9bda89a 100644 --- a/Lib/idlelib/help.py +++ b/Lib/idlelib/help.py @@ -241,12 +241,13 @@ def __init__(self, parent, filename, title): Toplevel.__init__(self, parent) self.wm_title(title) self.protocol("WM_DELETE_WINDOW", self.destroy) - HelpFrame(self, filename).grid(column=0, row=0, sticky='nsew') + self.frame = HelpFrame(self, filename) + self.frame.grid(column=0, row=0, sticky='nsew') self.grid_columnconfigure(0, weight=1) self.grid_rowconfigure(0, weight=1) -def copy_strip(): +def copy_strip(): # pragma: no cover """Copy idle.html to idlelib/help.html, stripping trailing whitespace. Files with trailing whitespace cannot be pushed to the git cpython @@ -278,13 +279,15 @@ def copy_strip(): out.write(line.rstrip() + b'\n') print(f'{src} copied to {dst}') + def show_idlehelp(parent): "Create HelpWindow; called from Idle Help event handler." filename = join(abspath(dirname(__file__)), 'help.html') - if not isfile(filename): + if not isfile(filename): # pragma: no cover # Try copy_strip, present message. return - HelpWindow(parent, filename, 'IDLE Help (%s)' % python_version()) + return HelpWindow(parent, filename, 'IDLE Doc (%s)' % python_version()) + if __name__ == '__main__': from unittest import main diff --git a/Lib/idlelib/help_about.py b/Lib/idlelib/help_about.py index cfa4ca781f087d..aa1c352897f9e7 100644 --- a/Lib/idlelib/help_about.py +++ b/Lib/idlelib/help_about.py @@ -129,11 +129,11 @@ def create_widgets(self): idle.grid(row=12, column=0, sticky=W, padx=10, pady=0) idle_buttons = Frame(frame_background, bg=self.bg) idle_buttons.grid(row=13, column=0, columnspan=3, sticky=NSEW) - self.readme = Button(idle_buttons, text='README', width=8, + self.readme = Button(idle_buttons, text='Readme', width=8, highlightbackground=self.bg, command=self.show_readme) self.readme.pack(side=LEFT, padx=10, pady=10) - self.idle_news = Button(idle_buttons, text='NEWS', width=8, + self.idle_news = Button(idle_buttons, text='News', width=8, highlightbackground=self.bg, command=self.show_idle_news) self.idle_news.pack(side=LEFT, padx=10, pady=10) @@ -167,7 +167,7 @@ def show_readme(self): def show_idle_news(self): "Handle News button event." - self.display_file_text('About - NEWS', 'NEWS.txt', 'utf-8') + self.display_file_text('About - News', 'News3.txt', 'utf-8') def display_printer_text(self, title, printer): """Create textview for built-in constants. diff --git a/Lib/idlelib/idle_test/example_stub.pyi b/Lib/idlelib/idle_test/example_stub.pyi index a9811a78d10a6e..17b58010a9d8de 100644 --- a/Lib/idlelib/idle_test/example_stub.pyi +++ b/Lib/idlelib/idle_test/example_stub.pyi @@ -1,2 +1,4 @@ +" Example to test recognition of .pyi file as Python source code. + class Example: def method(self, argument1: str, argument2: list[int]) -> None: ... diff --git a/Lib/idlelib/idle_test/htest.py b/Lib/idlelib/idle_test/htest.py index d297f8aa0094ee..a7293774eecaeb 100644 --- a/Lib/idlelib/idle_test/htest.py +++ b/Lib/idlelib/idle_test/htest.py @@ -1,38 +1,36 @@ -'''Run human tests of Idle's window, dialog, and popup widgets. - -run(*tests) -Create a master Tk window. Within that, run each callable in tests -after finding the matching test spec in this file. If tests is empty, -run an htest for each spec dict in this file after finding the matching -callable in the module named in the spec. Close the window to skip or -end the test. - -In a tested module, let X be a global name bound to a callable (class -or function) whose .__name__ attribute is also X (the usual situation). -The first parameter of X must be 'parent'. When called, the parent -argument will be the root window. X must create a child Toplevel -window (or subclass thereof). The Toplevel may be a test widget or -dialog, in which case the callable is the corresponding class. Or the -Toplevel may contain the widget to be tested or set up a context in -which a test widget is invoked. In this latter case, the callable is a -wrapper function that sets up the Toplevel and other objects. Wrapper -function names, such as _editor_window', should start with '_'. +"""Run human tests of Idle's window, dialog, and popup widgets. + +run(*tests) Create a master Tk() htest window. Within that, run each +callable in tests after finding the matching test spec in this file. If +tests is empty, run an htest for each spec dict in this file after +finding the matching callable in the module named in the spec. Close +the master window to end testing. + +In a tested module, let X be a global name bound to a callable (class or +function) whose .__name__ attribute is also X (the usual situation). The +first parameter of X must be 'parent' or 'master'. When called, the +first argument will be the root window. X must create a child +Toplevel(parent/master) (or subclass thereof). The Toplevel may be a +test widget or dialog, in which case the callable is the corresponding +class. Or the Toplevel may contain the widget to be tested or set up a +context in which a test widget is invoked. In this latter case, the +callable is a wrapper function that sets up the Toplevel and other +objects. Wrapper function names, such as _editor_window', should start +with '_' and be lowercase. End the module with if __name__ == '__main__': - + from idlelib.idle_test.htest import run - run(X) + run(callable) # There could be multiple comma-separated callables. -To have wrapper functions and test invocation code ignored by coveragepy -reports, put '# htest #' on the def statement header line. - -def _wrapper(parent): # htest # - -Also make sure that the 'if __name__' line matches the above. Then have -make sure that .coveragerc includes the following. +To have wrapper functions ignored by coverage reports, tag the def +header like so: "def _wrapper(parent): # htest #". Use the same tag +for htest lines in widget code. Make sure that the 'if __name__' line +matches the above. Then have make sure that .coveragerc includes the +following: [report] exclude_lines = @@ -46,7 +44,7 @@ def _wrapper(parent): # htest # following template, with X.__name__ prepended to '_spec'. When all tests are run, the prefix is use to get X. -_spec = { +callable_spec = { 'file': '', 'kwds': {'title': ''}, 'msg': "" @@ -54,16 +52,16 @@ def _wrapper(parent): # htest # file (no .py): run() imports file.py. kwds: augmented with {'parent':root} and passed to X as **kwds. -title: an example kwd; some widgets need this, delete if not. +title: an example kwd; some widgets need this, delete line if not. msg: master window hints about testing the widget. -Modules and classes not being tested at the moment: -pyshell.PyShellEditorWindow -debugger.Debugger -autocomplete_w.AutoCompleteWindow -outwin.OutputWindow (indirectly being tested with grep test) -''' +TODO test these modules and classes: + autocomplete_w.AutoCompleteWindow + debugger.Debugger + outwin.OutputWindow (indirectly being tested with grep test) + pyshell.PyShellEditorWindow +""" import idlelib.pyshell # Set Windows DPI awareness before Tk(). from importlib import import_module @@ -91,15 +89,6 @@ def _wrapper(parent): # htest # "Force-open-calltip does not work here.\n" } -_module_browser_spec = { - 'file': 'browser', - 'kwds': {}, - 'msg': "Inspect names of module, class(with superclass if " - "applicable), methods and functions.\nToggle nested items.\n" - "Double clicking on items prints a traceback for an exception " - "that is ignored." - } - _color_delegator_spec = { 'file': 'colorizer', 'kwds': {}, @@ -109,16 +98,6 @@ def _wrapper(parent): # htest # "The default color scheme is in idlelib/config-highlight.def" } -CustomRun_spec = { - 'file': 'query', - 'kwds': {'title': 'Customize query.py Run', - '_htest': True}, - 'msg': "Enter with or [Run]. Print valid entry to Shell\n" - "Arguments are parsed into a list\n" - "Mode is currently restart True or False\n" - "Close dialog with valid entry, , [Cancel], [X]" - } - ConfigDialog_spec = { 'file': 'configdialog', 'kwds': {'title': 'ConfigDialogTest', @@ -135,6 +114,24 @@ def _wrapper(parent): # htest # "changes made have persisted." } +CustomRun_spec = { + 'file': 'query', + 'kwds': {'title': 'Customize query.py Run', + '_htest': True}, + 'msg': "Enter with or [OK]. Print valid entry to Shell\n" + "Arguments are parsed into a list\n" + "Mode is currently restart True or False\n" + "Close dialog with valid entry, , [Cancel], [X]" + } + +_debug_object_browser_spec = { + 'file': 'debugobj', + 'kwds': {}, + 'msg': "Double click on items up to the lowest level.\n" + "Attributes of the objects and related information " + "will be displayed side-by-side at each level." + } + # TODO Improve message _dyn_option_menu_spec = { 'file': 'dynoption', @@ -152,7 +149,7 @@ def _wrapper(parent): # htest # "Best to close editor first." } -GetKeysDialog_spec = { +GetKeysWindow_spec = { 'file': 'config_key', 'kwds': {'title': 'Test keybindings', 'action': 'find-again', @@ -173,8 +170,8 @@ def _wrapper(parent): # htest # 'msg': "Click the 'Show GrepDialog' button.\n" "Test the various 'Find-in-files' functions.\n" "The results should be displayed in a new '*Output*' window.\n" - "'Right-click'->'Go to file/line' anywhere in the search results " - "should open that file \nin a new EditorWindow." + "'Right-click'->'Go to file/line' in the search results\n " + "should open that file in a new EditorWindow." } HelpSource_spec = { @@ -190,7 +187,7 @@ def _wrapper(parent): # htest # "Any url ('www...', 'http...') is accepted.\n" "Test Browse with and without path, as cannot unittest.\n" "[Ok] or prints valid entry to shell\n" - "[Cancel] or prints None to shell" + ", [Cancel], or [X] prints None to shell" } _io_binding_spec = { @@ -206,56 +203,36 @@ def _wrapper(parent): # htest # "Check that changes were saved by opening the file elsewhere." } -_linenumbers_drag_scrolling_spec = { - 'file': 'sidebar', +_multi_call_spec = { + 'file': 'multicall', 'kwds': {}, - 'msg': textwrap.dedent("""\ - 1. Click on the line numbers and drag down below the edge of the - window, moving the mouse a bit and then leaving it there for a while. - The text and line numbers should gradually scroll down, with the - selection updated continuously. - - 2. With the lines still selected, click on a line number above the - selected lines. Only the line whose number was clicked should be - selected. - - 3. Repeat step #1, dragging to above the window. The text and line - numbers should gradually scroll up, with the selection updated - continuously. - - 4. Repeat step #2, clicking a line number below the selection."""), + 'msg': "The following should trigger a print to console or IDLE Shell.\n" + "Entering and leaving the text area, key entry, ,\n" + ", , , \n" + ", and focusing elsewhere." } -_multi_call_spec = { - 'file': 'multicall', +_module_browser_spec = { + 'file': 'browser', 'kwds': {}, - 'msg': "The following actions should trigger a print to console or IDLE" - " Shell.\nEntering and leaving the text area, key entry, " - ",\n, , " - ", \n, and " - "focusing out of the window\nare sequences to be tested." + 'msg': textwrap.dedent(""" + "Inspect names of module, class(with superclass if applicable), + "methods and functions. Toggle nested items. Double clicking + "on items prints a traceback for an exception that is ignored.""") } _multistatus_bar_spec = { 'file': 'statusbar', 'kwds': {}, 'msg': "Ensure presence of multi-status bar below text area.\n" - "Click 'Update Status' to change the multi-status text" + "Click 'Update Status' to change the status text" } -_object_browser_spec = { - 'file': 'debugobj', - 'kwds': {}, - 'msg': "Double click on items up to the lowest level.\n" - "Attributes of the objects and related information " - "will be displayed side-by-side at each level." - } - -_path_browser_spec = { +PathBrowser_spec = { 'file': 'pathbrowser', - 'kwds': {}, + 'kwds': {'_htest': True}, 'msg': "Test for correct display of all paths in sys.path.\n" - "Toggle nested items up to the lowest level.\n" + "Toggle nested items out to the lowest level.\n" "Double clicking on an item prints a traceback\n" "for an exception that is ignored." } @@ -291,6 +268,15 @@ def _wrapper(parent): # htest # "Click [Close] or [X] to close the 'Replace Dialog'." } +_scrolled_list_spec = { + 'file': 'scrolledlist', + 'kwds': {}, + 'msg': "You should see a scrollable list of items\n" + "Selecting (clicking) or double clicking an item " + "prints the name to the console or Idle shell.\n" + "Right clicking an item will display a popup." + } + _search_dialog_spec = { 'file': 'search', 'kwds': {}, @@ -306,15 +292,6 @@ def _wrapper(parent): # htest # "Its only action is to close." } -_scrolled_list_spec = { - 'file': 'scrolledlist', - 'kwds': {}, - 'msg': "You should see a scrollable list of items\n" - "Selecting (clicking) or double clicking an item " - "prints the name to the console or Idle shell.\n" - "Right clicking an item will display a popup." - } - show_idlehelp_spec = { 'file': 'help', 'kwds': {}, @@ -322,12 +299,31 @@ def _wrapper(parent): # htest # "Text is selectable. Window is scrollable." } -_stack_viewer_spec = { +_sidebar_number_scrolling_spec = { + 'file': 'sidebar', + 'kwds': {}, + 'msg': textwrap.dedent("""\ + 1. Click on the line numbers and drag down below the edge of the + window, moving the mouse a bit and then leaving it there for a + while. The text and line numbers should gradually scroll down, + with the selection updated continuously. + + 2. With the lines still selected, click on a line number above + or below the selected lines. Only the line whose number was + clicked should be selected. + + 3. Repeat step #1, dragging to above the window. The text and + line numbers should gradually scroll up, with the selection + updated continuously. + + 4. Repeat step #2, clicking a line number below the selection."""), + } + +_stackbrowser_spec = { 'file': 'stackviewer', 'kwds': {}, 'msg': "A stacktrace for a NameError exception.\n" - "Expand 'idlelib ...' and ''.\n" - "Check that exc_value, exc_tb, and exc_type are correct.\n" + "Should have NameError and 1 traceback line." } _tooltip_spec = { @@ -370,11 +366,12 @@ def _wrapper(parent): # htest # } def run(*tests): + "Run callables in tests." root = tk.Tk() root.title('IDLE htest') root.resizable(0, 0) - # a scrollable Label like constant width text widget. + # A scrollable Label-like constant width text widget. frameLabel = tk.Frame(root, padx=10) frameLabel.pack() text = tk.Text(frameLabel, wrap='word') @@ -384,45 +381,44 @@ def run(*tests): scrollbar.pack(side='right', fill='y', expand=False) text.pack(side='left', fill='both', expand=True) - test_list = [] # List of tuples of the form (spec, callable widget) + test_list = [] # Make list of (spec, callable) tuples. if tests: for test in tests: test_spec = globals()[test.__name__ + '_spec'] test_spec['name'] = test.__name__ test_list.append((test_spec, test)) else: - for k, d in globals().items(): - if k.endswith('_spec'): - test_name = k[:-5] - test_spec = d + for key, dic in globals().items(): + if key.endswith('_spec'): + test_name = key[:-5] + test_spec = dic test_spec['name'] = test_name mod = import_module('idlelib.' + test_spec['file']) test = getattr(mod, test_name) test_list.append((test_spec, test)) + test_list.reverse() # So can pop in proper order in next_test. test_name = tk.StringVar(root) callable_object = None test_kwds = None def next_test(): - nonlocal test_name, callable_object, test_kwds if len(test_list) == 1: next_button.pack_forget() test_spec, callable_object = test_list.pop() test_kwds = test_spec['kwds'] - test_kwds['parent'] = root test_name.set('Test ' + test_spec['name']) - text.configure(state='normal') # enable text editing - text.delete('1.0','end') - text.insert("1.0",test_spec['msg']) - text.configure(state='disabled') # preserve read-only property + text['state'] = 'normal' # Enable text replacement. + text.delete('1.0', 'end') + text.insert("1.0", test_spec['msg']) + text['state'] = 'disabled' # Restore read-only property. def run_test(_=None): - widget = callable_object(**test_kwds) + widget = callable_object(root, **test_kwds) try: - print(widget.result) + print(widget.result) # Only true for query classes(?). except AttributeError: pass @@ -441,5 +437,6 @@ def close(_=None): next_test() root.mainloop() + if __name__ == '__main__': run() diff --git a/Lib/idlelib/idle_test/test_calltip.py b/Lib/idlelib/idle_test/test_calltip.py index 1ccb63b9dbd65f..15e1ff3f3cf717 100644 --- a/Lib/idlelib/idle_test/test_calltip.py +++ b/Lib/idlelib/idle_test/test_calltip.py @@ -7,6 +7,7 @@ import types import re from idlelib.idle_test.mock_tk import Text +from test.support import MISSING_C_DOCSTRINGS # Test Class TC is used in multiple get_argspec test methods @@ -50,6 +51,8 @@ class Get_argspecTest(unittest.TestCase): # but a red buildbot is better than a user crash (as has happened). # For a simple mismatch, change the expected output to the actual. + @unittest.skipIf(MISSING_C_DOCSTRINGS, + "Signature information for builtins requires docstrings") def test_builtins(self): def tiptest(obj, out): @@ -143,6 +146,8 @@ def f(): pass f.__doc__ = 'a'*300 self.assertEqual(get_spec(f), f"()\n{'a'*(calltip._MAX_COLS-3) + '...'}") + @unittest.skipIf(MISSING_C_DOCSTRINGS, + "Signature information for builtins requires docstrings") def test_multiline_docstring(self): # Test fewer lines than max. self.assertEqual(get_spec(range), @@ -157,6 +162,7 @@ def test_multiline_docstring(self): bytes(int) -> bytes object of size given by the parameter initialized with null bytes bytes() -> empty bytes object''') + def test_multiline_docstring_2(self): # Test more than max lines def f(): pass f.__doc__ = 'a\n' * 15 diff --git a/Lib/idlelib/idle_test/test_config.py b/Lib/idlelib/idle_test/test_config.py index 08ed76fe288294..6d75cf7aa67dcc 100644 --- a/Lib/idlelib/idle_test/test_config.py +++ b/Lib/idlelib/idle_test/test_config.py @@ -85,8 +85,8 @@ def test_load_nothing(self): self.assertEqual(parser.sections(), []) def test_load_file(self): - # Borrow test/cfgparser.1 from test_configparser. - config_path = findfile('cfgparser.1') + # Borrow test/configdata/cfgparser.1 from test_configparser. + config_path = findfile('cfgparser.1', subdir='configdata') parser = config.IdleConfParser(config_path) parser.Load() @@ -274,8 +274,8 @@ def test_create_config_handlers(self): conf.CreateConfigHandlers() # Check keys are equal - self.assertCountEqual(conf.defaultCfg.keys(), conf.config_types) - self.assertCountEqual(conf.userCfg.keys(), conf.config_types) + self.assertCountEqual(conf.defaultCfg, conf.config_types) + self.assertCountEqual(conf.userCfg, conf.config_types) # Check conf parser are correct type for default_parser in conf.defaultCfg.values(): @@ -294,8 +294,8 @@ def test_create_config_handlers(self): def test_load_cfg_files(self): conf = self.new_config(_utest=True) - # Borrow test/cfgparser.1 from test_configparser. - config_path = findfile('cfgparser.1') + # Borrow test/configdata/cfgparser.1 from test_configparser. + config_path = findfile('cfgparser.1', subdir='configdata') conf.defaultCfg['foo'] = config.IdleConfParser(config_path) conf.userCfg['foo'] = config.IdleUserConfParser(config_path) diff --git a/Lib/idlelib/idle_test/test_configdialog.py b/Lib/idlelib/idle_test/test_configdialog.py index e5d5b4013fca57..6f8518a9bb19d0 100644 --- a/Lib/idlelib/idle_test/test_configdialog.py +++ b/Lib/idlelib/idle_test/test_configdialog.py @@ -430,7 +430,7 @@ def test_highlight_target_text_mouse(self): def tag_to_element(elem): for element, tag in d.theme_elements.items(): - elem[tag[0]] = element + elem[tag] = element def click_it(start): x, y, dx, dy = hs.bbox(start) diff --git a/Lib/idlelib/idle_test/test_debugger.py b/Lib/idlelib/idle_test/test_debugger.py index 35efb3411c73b5..d1c9638dd5d711 100644 --- a/Lib/idlelib/idle_test/test_debugger.py +++ b/Lib/idlelib/idle_test/test_debugger.py @@ -1,16 +1,286 @@ -"Test debugger, coverage 19%" +"""Test debugger, coverage 66% + +Try to make tests pass with draft bdbx, which may replace bdb in 3.13+. +""" from idlelib import debugger -import unittest -from test.support import requires -requires('gui') +from collections import namedtuple +from textwrap import dedent from tkinter import Tk +from test.support import requires +import unittest +from unittest import mock +from unittest.mock import Mock, patch + +"""A test python script for the debug tests.""" +TEST_CODE = dedent(""" + i = 1 + i += 2 + if i == 3: + print(i) + """) + + +class MockFrame: + "Minimal mock frame." + + def __init__(self, code, lineno): + self.f_code = code + self.f_lineno = lineno + + +class IdbTest(unittest.TestCase): + + @classmethod + def setUpClass(cls): + cls.gui = Mock() + cls.idb = debugger.Idb(cls.gui) + + # Create test and code objects to simulate a debug session. + code_obj = compile(TEST_CODE, 'idlelib/file.py', mode='exec') + frame1 = MockFrame(code_obj, 1) + frame1.f_back = None + frame2 = MockFrame(code_obj, 2) + frame2.f_back = frame1 + cls.frame = frame2 + cls.msg = 'file.py:2: ()' + + def test_init(self): + self.assertIs(self.idb.gui, self.gui) + # Won't test super call since two Bdbs are very different. + + def test_user_line(self): + # Test that .user_line() creates a string message for a frame. + self.gui.interaction = Mock() + self.idb.user_line(self.frame) + self.gui.interaction.assert_called_once_with(self.msg, self.frame) + + def test_user_exception(self): + # Test that .user_exception() creates a string message for a frame. + exc_info = (type(ValueError), ValueError(), None) + self.gui.interaction = Mock() + self.idb.user_exception(self.frame, exc_info) + self.gui.interaction.assert_called_once_with( + self.msg, self.frame, exc_info) + + +class FunctionTest(unittest.TestCase): + # Test module functions together. + + def test_functions(self): + rpc_obj = compile(TEST_CODE,'rpc.py', mode='exec') + rpc_frame = MockFrame(rpc_obj, 2) + rpc_frame.f_back = rpc_frame + self.assertTrue(debugger._in_rpc_code(rpc_frame)) + self.assertEqual(debugger._frame2message(rpc_frame), + 'rpc.py:2: ()') + + code_obj = compile(TEST_CODE, 'idlelib/debugger.py', mode='exec') + code_frame = MockFrame(code_obj, 1) + code_frame.f_back = None + self.assertFalse(debugger._in_rpc_code(code_frame)) + self.assertEqual(debugger._frame2message(code_frame), + 'debugger.py:1: ()') + + code_frame.f_back = code_frame + self.assertFalse(debugger._in_rpc_code(code_frame)) + code_frame.f_back = rpc_frame + self.assertTrue(debugger._in_rpc_code(code_frame)) + + +class DebuggerTest(unittest.TestCase): + "Tests for Debugger that do not need a real root." + + @classmethod + def setUpClass(cls): + cls.pyshell = Mock() + cls.pyshell.root = Mock() + cls.idb = Mock() + with patch.object(debugger.Debugger, 'make_gui'): + cls.debugger = debugger.Debugger(cls.pyshell, cls.idb) + cls.debugger.root = Mock() + + def test_cont(self): + self.debugger.cont() + self.idb.set_continue.assert_called_once() + + def test_step(self): + self.debugger.step() + self.idb.set_step.assert_called_once() + + def test_quit(self): + self.debugger.quit() + self.idb.set_quit.assert_called_once() + + def test_next(self): + with patch.object(self.debugger, 'frame') as frame: + self.debugger.next() + self.idb.set_next.assert_called_once_with(frame) + + def test_ret(self): + with patch.object(self.debugger, 'frame') as frame: + self.debugger.ret() + self.idb.set_return.assert_called_once_with(frame) + + def test_clear_breakpoint(self): + self.debugger.clear_breakpoint('test.py', 4) + self.idb.clear_break.assert_called_once_with('test.py', 4) + + def test_clear_file_breaks(self): + self.debugger.clear_file_breaks('test.py') + self.idb.clear_all_file_breaks.assert_called_once_with('test.py') + + def test_set_load_breakpoints(self): + # Test the .load_breakpoints() method calls idb. + FileIO = namedtuple('FileIO', 'filename') + + class MockEditWindow(object): + def __init__(self, fn, breakpoints): + self.io = FileIO(fn) + self.breakpoints = breakpoints + + self.pyshell.flist = Mock() + self.pyshell.flist.inversedict = ( + MockEditWindow('test1.py', [4, 4]), + MockEditWindow('test2.py', [13, 44, 45]), + ) + self.debugger.set_breakpoint('test0.py', 1) + self.idb.set_break.assert_called_once_with('test0.py', 1) + self.debugger.load_breakpoints() # Call set_breakpoint 5 times. + self.idb.set_break.assert_has_calls( + [mock.call('test0.py', 1), + mock.call('test1.py', 4), + mock.call('test1.py', 4), + mock.call('test2.py', 13), + mock.call('test2.py', 44), + mock.call('test2.py', 45)]) + + def test_sync_source_line(self): + # Test that .sync_source_line() will set the flist.gotofileline with fixed frame. + test_code = compile(TEST_CODE, 'test_sync.py', 'exec') + test_frame = MockFrame(test_code, 1) + self.debugger.frame = test_frame + + self.debugger.flist = Mock() + with patch('idlelib.debugger.os.path.exists', return_value=True): + self.debugger.sync_source_line() + self.debugger.flist.gotofileline.assert_called_once_with('test_sync.py', 1) + + +class DebuggerGuiTest(unittest.TestCase): + """Tests for debugger.Debugger that need tk root. + + close needs debugger.top set in make_gui. + """ + + @classmethod + def setUpClass(cls): + requires('gui') + cls.root = root = Tk() + root.withdraw() + cls.pyshell = Mock() + cls.pyshell.root = root + cls.idb = Mock() +# stack tests fail with debugger here. +## cls.debugger = debugger.Debugger(cls.pyshell, cls.idb) +## cls.debugger.root = root +## # real root needed for real make_gui +## # run, interacting, abort_loop + + @classmethod + def tearDownClass(cls): + cls.root.destroy() + del cls.root + + def setUp(self): + self.debugger = debugger.Debugger(self.pyshell, self.idb) + self.debugger.root = self.root + # real root needed for real make_gui + # run, interacting, abort_loop + + def test_run_debugger(self): + self.debugger.run(1, 'two') + self.idb.run.assert_called_once_with(1, 'two') + self.assertEqual(self.debugger.interacting, 0) + + def test_close(self): + # Test closing the window in an idle state. + self.debugger.close() + self.pyshell.close_debugger.assert_called_once() + + def test_show_stack(self): + self.debugger.show_stack() + self.assertEqual(self.debugger.stackviewer.gui, self.debugger) + + def test_show_stack_with_frame(self): + test_frame = MockFrame(None, None) + self.debugger.frame = test_frame + + # Reset the stackviewer to force it to be recreated. + self.debugger.stackviewer = None + self.idb.get_stack.return_value = ([], 0) + self.debugger.show_stack() + + # Check that the newly created stackviewer has the test gui as a field. + self.assertEqual(self.debugger.stackviewer.gui, self.debugger) + self.idb.get_stack.assert_called_once_with(test_frame, None) + + +class StackViewerTest(unittest.TestCase): + + @classmethod + def setUpClass(cls): + requires('gui') + cls.root = Tk() + cls.root.withdraw() + + @classmethod + def tearDownClass(cls): + cls.root.destroy() + del cls.root + + def setUp(self): + self.code = compile(TEST_CODE, 'test_stackviewer.py', 'exec') + self.stack = [ + (MockFrame(self.code, 1), 1), + (MockFrame(self.code, 2), 2) + ] + # Create a stackviewer and load the test stack. + self.sv = debugger.StackViewer(self.root, None, None) + self.sv.load_stack(self.stack) + + def test_init(self): + # Test creation of StackViewer. + gui = None + flist = None + master_window = self.root + sv = debugger.StackViewer(master_window, flist, gui) + self.assertTrue(hasattr(sv, 'stack')) + + def test_load_stack(self): + # Test the .load_stack() method against a fixed test stack. + # Check the test stack is assigned and the list contains the repr of them. + self.assertEqual(self.sv.stack, self.stack) + self.assertTrue('?.(), line 1:' in self.sv.get(0)) + self.assertEqual(self.sv.get(1), '?.(), line 2: ') + + def test_show_source(self): + # Test the .show_source() method against a fixed test stack. + # Patch out the file list to monitor it + self.sv.flist = Mock() + # Patch out isfile to pretend file exists. + with patch('idlelib.debugger.os.path.isfile', return_value=True) as isfile: + self.sv.show_source(1) + isfile.assert_called_once_with('test_stackviewer.py') + self.sv.flist.open.assert_called_once_with('test_stackviewer.py') + class NameSpaceTest(unittest.TestCase): @classmethod def setUpClass(cls): + requires('gui') cls.root = Tk() cls.root.withdraw() @@ -23,7 +293,5 @@ def test_init(self): debugger.NamespaceViewer(self.root, 'Test') -# Other classes are Idb, Debugger, and StackViewer. - if __name__ == '__main__': unittest.main(verbosity=2) diff --git a/Lib/idlelib/idle_test/test_debugobj.py b/Lib/idlelib/idle_test/test_debugobj.py index 131ce22b8bb69b..90ace4e1bc4f9e 100644 --- a/Lib/idlelib/idle_test/test_debugobj.py +++ b/Lib/idlelib/idle_test/test_debugobj.py @@ -37,7 +37,7 @@ def test_isexpandable(self): def test_keys(self): ti = debugobj.SequenceTreeItem('label', 'abc') - self.assertEqual(list(ti.keys()), [0, 1, 2]) + self.assertEqual(list(ti.keys()), [0, 1, 2]) # keys() is a range. class DictTreeItemTest(unittest.TestCase): @@ -50,7 +50,7 @@ def test_isexpandable(self): def test_keys(self): ti = debugobj.DictTreeItem('label', {1:1, 0:0, 2:2}) - self.assertEqual(ti.keys(), [0, 1, 2]) + self.assertEqual(ti.keys(), [0, 1, 2]) # keys() is a sorted list. if __name__ == '__main__': diff --git a/Lib/idlelib/idle_test/test_editor.py b/Lib/idlelib/idle_test/test_editor.py index 9296a6d235fbbe..0dfe2f3c58befa 100644 --- a/Lib/idlelib/idle_test/test_editor.py +++ b/Lib/idlelib/idle_test/test_editor.py @@ -95,7 +95,7 @@ def test_tabwidth_8(self): def insert(text, string): text.delete('1.0', 'end') text.insert('end', string) - text.update() # Force update for colorizer to finish. + text.update_idletasks() # Force update for colorizer to finish. class IndentAndNewlineTest(unittest.TestCase): diff --git a/Lib/idlelib/idle_test/test_help.py b/Lib/idlelib/idle_test/test_help.py index b542659981894d..c528d4e77f8ca7 100644 --- a/Lib/idlelib/idle_test/test_help.py +++ b/Lib/idlelib/idle_test/test_help.py @@ -1,4 +1,4 @@ -"Test help, coverage 87%." +"Test help, coverage 94%." from idlelib import help import unittest @@ -8,25 +8,27 @@ from tkinter import Tk -class HelpFrameTest(unittest.TestCase): +class IdleDocTest(unittest.TestCase): @classmethod def setUpClass(cls): "By itself, this tests that file parsed without exception." cls.root = root = Tk() root.withdraw() - helpfile = join(dirname(dirname(abspath(__file__))), 'help.html') - cls.frame = help.HelpFrame(root, helpfile) + cls.window = help.show_idlehelp(root) @classmethod def tearDownClass(cls): - del cls.frame + del cls.window cls.root.update_idletasks() cls.root.destroy() del cls.root - def test_line1(self): - text = self.frame.text + def test_1window(self): + self.assertIn('IDLE Doc', self.window.wm_title()) + + def test_4text(self): + text = self.window.frame.text self.assertEqual(text.get('1.0', '1.end'), ' IDLE ') diff --git a/Lib/idlelib/idle_test/test_help_about.py b/Lib/idlelib/idle_test/test_help_about.py index 8b79487b15d4cd..7e16abdb7c9f96 100644 --- a/Lib/idlelib/idle_test/test_help_about.py +++ b/Lib/idlelib/idle_test/test_help_about.py @@ -71,7 +71,7 @@ def test_file_buttons(self): """Test buttons that display files.""" dialog = self.dialog button_sources = [(self.dialog.readme, 'README.txt', 'readme'), - (self.dialog.idle_news, 'NEWS.txt', 'news'), + (self.dialog.idle_news, 'News3.txt', 'news'), (self.dialog.idle_credits, 'CREDITS.txt', 'credits')] for button, filename, name in button_sources: diff --git a/Lib/idlelib/iomenu.py b/Lib/idlelib/iomenu.py index af8159c2b33f51..464126e2df0668 100644 --- a/Lib/idlelib/iomenu.py +++ b/Lib/idlelib/iomenu.py @@ -7,7 +7,7 @@ from tkinter import filedialog from tkinter import messagebox -from tkinter.simpledialog import askstring +from tkinter.simpledialog import askstring # loadfile encoding. from idlelib.config import idleConf from idlelib.util import py_extensions @@ -180,24 +180,25 @@ def loadfile(self, filename): return True def maybesave(self): + """Return 'yes', 'no', 'cancel' as appropriate. + + Tkinter messagebox.askyesnocancel converts these tk responses + to True, False, None. Convert back, as now expected elsewhere. + """ if self.get_saved(): return "yes" - message = "Do you want to save %s before closing?" % ( - self.filename or "this untitled document") + message = ("Do you want to save " + f"{self.filename or 'this untitled document'}" + " before closing?") confirm = messagebox.askyesnocancel( title="Save On Close", message=message, default=messagebox.YES, parent=self.text) if confirm: - reply = "yes" self.save(None) - if not self.get_saved(): - reply = "cancel" - elif confirm is None: - reply = "cancel" - else: - reply = "no" + reply = "yes" if self.get_saved() else "cancel" + else: reply = "cancel" if confirm is None else "no" self.text.focus_set() return reply @@ -393,13 +394,15 @@ def updaterecentfileslist(self,filename): if self.editwin.flist: self.editwin.update_recent_files_list(filename) + def _io_binding(parent): # htest # from tkinter import Toplevel, Text - root = Toplevel(parent) - root.title("Test IOBinding") + top = Toplevel(parent) + top.title("Test IOBinding") x, y = map(int, parent.geometry().split('+')[1:]) - root.geometry("+%d+%d" % (x, y + 175)) + top.geometry("+%d+%d" % (x, y + 175)) + class MyEditWin: def __init__(self, text): self.text = text @@ -423,12 +426,13 @@ def saveas(self, event): def savecopy(self, event): self.text.event_generate("<>") - text = Text(root) + text = Text(top) text.pack() text.focus_set() editwin = MyEditWin(text) IOBinding(editwin) + if __name__ == "__main__": from unittest import main main('idlelib.idle_test.test_iomenu', verbosity=2, exit=False) diff --git a/Lib/idlelib/macosx.py b/Lib/idlelib/macosx.py index 2ea02ec04d661a..332952f4572cbd 100644 --- a/Lib/idlelib/macosx.py +++ b/Lib/idlelib/macosx.py @@ -221,7 +221,7 @@ def help_dialog(event=None): # The binding above doesn't reliably work on all versions of Tk # on macOS. Adding command definition below does seem to do the # right thing for now. - root.createcommand('exit', flist.close_all_callback) + root.createcommand('::tk::mac::Quit', flist.close_all_callback) if isCarbonTk(): # for Carbon AquaTk, replace the default Tk apple menu diff --git a/Lib/idlelib/multicall.py b/Lib/idlelib/multicall.py index 0200f445cc9340..41f81813113062 100644 --- a/Lib/idlelib/multicall.py +++ b/Lib/idlelib/multicall.py @@ -421,6 +421,8 @@ def _multi_call(parent): # htest # top.geometry("+%d+%d" % (x, y + 175)) text = MultiCallCreator(tkinter.Text)(top) text.pack() + text.focus_set() + def bindseq(seq, n=[0]): def handler(event): print(seq) @@ -440,6 +442,7 @@ def handler(event): bindseq("") bindseq("") + if __name__ == "__main__": from unittest import main main('idlelib.idle_test.test_mainmenu', verbosity=2, exit=False) diff --git a/Lib/idlelib/outwin.py b/Lib/idlelib/outwin.py index 610031e26f1dff..5ed3f35a7af655 100644 --- a/Lib/idlelib/outwin.py +++ b/Lib/idlelib/outwin.py @@ -182,6 +182,7 @@ def setup(self): text.tag_raise('sel') self.write = self.owin.write + if __name__ == '__main__': from unittest import main main('idlelib.idle_test.test_outwin', verbosity=2, exit=False) diff --git a/Lib/idlelib/pathbrowser.py b/Lib/idlelib/pathbrowser.py index 6de242d0000bed..48a77875ba5801 100644 --- a/Lib/idlelib/pathbrowser.py +++ b/Lib/idlelib/pathbrowser.py @@ -99,13 +99,9 @@ def listmodules(self, allnames): return sorted -def _path_browser(parent): # htest # - PathBrowser(parent, _htest=True) - parent.mainloop() - if __name__ == "__main__": from unittest import main main('idlelib.idle_test.test_pathbrowser', verbosity=2, exit=False) from idlelib.idle_test.htest import run - run(_path_browser) + run(PathBrowser) diff --git a/Lib/idlelib/percolator.py b/Lib/idlelib/percolator.py index 1fe34d29f54eb2..aa73427c4915c8 100644 --- a/Lib/idlelib/percolator.py +++ b/Lib/idlelib/percolator.py @@ -86,11 +86,11 @@ def delete(self, *args): print(self.name, ": delete", args) self.delegate.delete(*args) - box = tk.Toplevel(parent) - box.title("Test Percolator") + top = tk.Toplevel(parent) + top.title("Test Percolator") x, y = map(int, parent.geometry().split('+')[1:]) - box.geometry("+%d+%d" % (x, y + 175)) - text = tk.Text(box) + top.geometry("+%d+%d" % (x, y + 175)) + text = tk.Text(top) p = Percolator(text) pin = p.insertfilter pout = p.removefilter @@ -103,13 +103,15 @@ def toggle2(): (pin if var2.get() else pout)(t2) text.pack() + text.focus_set() var1 = tk.IntVar(parent) - cb1 = tk.Checkbutton(box, text="Tracer1", command=toggle1, variable=var1) + cb1 = tk.Checkbutton(top, text="Tracer1", command=toggle1, variable=var1) cb1.pack() var2 = tk.IntVar(parent) - cb2 = tk.Checkbutton(box, text="Tracer2", command=toggle2, variable=var2) + cb2 = tk.Checkbutton(top, text="Tracer2", command=toggle2, variable=var2) cb2.pack() + if __name__ == "__main__": from unittest import main main('idlelib.idle_test.test_percolator', verbosity=2, exit=False) diff --git a/Lib/idlelib/pyshell.py b/Lib/idlelib/pyshell.py index 6028700356b171..1524fccd5d20f8 100755 --- a/Lib/idlelib/pyshell.py +++ b/Lib/idlelib/pyshell.py @@ -133,8 +133,8 @@ class PyShellEditorWindow(EditorWindow): def __init__(self, *args): self.breakpoints = [] EditorWindow.__init__(self, *args) - self.text.bind("<>", self.set_breakpoint_here) - self.text.bind("<>", self.clear_breakpoint_here) + self.text.bind("<>", self.set_breakpoint_event) + self.text.bind("<>", self.clear_breakpoint_event) self.text.bind("<>", self.flist.open_shell) #TODO: don't read/write this from/to .idlerc when testing @@ -155,8 +155,8 @@ def filename_changed_hook(old_hook=self.io.filename_change_hook, ("Copy", "<>", "rmenu_check_copy"), ("Paste", "<>", "rmenu_check_paste"), (None, None, None), - ("Set Breakpoint", "<>", None), - ("Clear Breakpoint", "<>", None) + ("Set Breakpoint", "<>", None), + ("Clear Breakpoint", "<>", None) ] def color_breakpoint_text(self, color=True): @@ -181,11 +181,11 @@ def set_breakpoint(self, lineno): self.breakpoints.append(lineno) try: # update the subprocess debugger debug = self.flist.pyshell.interp.debugger - debug.set_breakpoint_here(filename, lineno) + debug.set_breakpoint(filename, lineno) except: # but debugger may not be active right now.... pass - def set_breakpoint_here(self, event=None): + def set_breakpoint_event(self, event=None): text = self.text filename = self.io.filename if not filename: @@ -194,7 +194,7 @@ def set_breakpoint_here(self, event=None): lineno = int(float(text.index("insert"))) self.set_breakpoint(lineno) - def clear_breakpoint_here(self, event=None): + def clear_breakpoint_event(self, event=None): text = self.text filename = self.io.filename if not filename: @@ -209,7 +209,7 @@ def clear_breakpoint_here(self, event=None): "insert lineend +1char") try: debug = self.flist.pyshell.interp.debugger - debug.clear_breakpoint_here(filename, lineno) + debug.clear_breakpoint(filename, lineno) except: pass @@ -747,10 +747,11 @@ def showtraceback(self): self.tkconsole.open_stack_viewer() def checklinecache(self): - c = linecache.cache - for key in list(c.keys()): + "Remove keys other than ''." + cache = linecache.cache + for key in list(cache): # Iterate list because mutate cache. if key[:1] + key[-1:] != "<>": - del c[key] + del cache[key] def runcommand(self, code): "Run the code without invoking the debugger" @@ -1693,6 +1694,7 @@ def main(): root.destroy() capture_warnings(False) + if __name__ == "__main__": main() diff --git a/Lib/idlelib/query.py b/Lib/idlelib/query.py index df02f2123ab02f..57230e2aaca66d 100644 --- a/Lib/idlelib/query.py +++ b/Lib/idlelib/query.py @@ -368,7 +368,7 @@ def create_extra(self): sticky='we') def cli_args_ok(self): - "Validity check and parsing for command line arguments." + "Return command line arg list or None if error." cli_string = self.entry.get().strip() try: cli_args = shlex.split(cli_string, posix=True) diff --git a/Lib/idlelib/redirector.py b/Lib/idlelib/redirector.py index 4928340e98df68..08728956abd900 100644 --- a/Lib/idlelib/redirector.py +++ b/Lib/idlelib/redirector.py @@ -164,6 +164,7 @@ def my_insert(*args): original_insert(*args) original_insert = redir.register("insert", my_insert) + if __name__ == "__main__": from unittest import main main('idlelib.idle_test.test_redirector', verbosity=2, exit=False) diff --git a/Lib/idlelib/replace.py b/Lib/idlelib/replace.py index ca83173877ad1d..3716d841568d30 100644 --- a/Lib/idlelib/replace.py +++ b/Lib/idlelib/replace.py @@ -25,7 +25,8 @@ def replace(text, insert_tags=None): if not hasattr(engine, "_replacedialog"): engine._replacedialog = ReplaceDialog(root, engine) dialog = engine._replacedialog - dialog.open(text, insert_tags=insert_tags) + searchphrase = text.get("sel.first", "sel.last") + dialog.open(text, searchphrase, insert_tags=insert_tags) class ReplaceDialog(SearchDialogBase): @@ -51,27 +52,17 @@ def __init__(self, root, engine): self.replvar = StringVar(root) self.insert_tags = None - def open(self, text, insert_tags=None): + def open(self, text, searchphrase=None, *, insert_tags=None): """Make dialog visible on top of others and ready to use. - Also, highlight the currently selected text and set the - search to include the current selection (self.ok). + Also, set the search to include the current selection + (self.ok). Args: text: Text widget being searched. + searchphrase: String phrase to search. """ - SearchDialogBase.open(self, text) - try: - first = text.index("sel.first") - except TclError: - first = None - try: - last = text.index("sel.last") - except TclError: - last = None - first = first or text.index("insert") - last = last or first - self.show_hit(first, last) + SearchDialogBase.open(self, text, searchphrase) self.ok = True self.insert_tags = insert_tags @@ -120,7 +111,7 @@ def _replace_expand(self, m, repl): if self.engine.isre(): try: new = m.expand(repl) - except re.error: + except re.PatternError: self.engine.report_error(repl, 'Invalid Replace Expression') new = None else: @@ -299,6 +290,7 @@ def show_replace(): button = Button(frame, text="Replace", command=show_replace) button.pack() + if __name__ == '__main__': from unittest import main main('idlelib.idle_test.test_replace', verbosity=2, exit=False) diff --git a/Lib/idlelib/scrolledlist.py b/Lib/idlelib/scrolledlist.py index 71fd18ab19ec8a..4fb418db326255 100644 --- a/Lib/idlelib/scrolledlist.py +++ b/Lib/idlelib/scrolledlist.py @@ -132,6 +132,7 @@ def _scrolled_list(parent): # htest # top = Toplevel(parent) x, y = map(int, parent.geometry().split('+')[1:]) top.geometry("+%d+%d" % (x+200, y + 175)) + class MyScrolledList(ScrolledList): def fill_menu(self): self.menu.add_command(label="right click") def on_select(self, index): print("select", self.get(index)) @@ -141,9 +142,10 @@ def on_double(self, index): print("double", self.get(index)) for i in range(30): scrolled_list.append("Item %02d" % i) + if __name__ == '__main__': from unittest import main - main('idlelib.idle_test.test_scrolledlist', verbosity=2,) + main('idlelib.idle_test.test_scrolledlist', verbosity=2, exit=False) from idlelib.idle_test.htest import run run(_scrolled_list) diff --git a/Lib/idlelib/search.py b/Lib/idlelib/search.py index b35f3b59c3d2e8..935a4832257fa4 100644 --- a/Lib/idlelib/search.py +++ b/Lib/idlelib/search.py @@ -156,6 +156,7 @@ def show_find(): button = Button(frame, text="Search (selection ignored)", command=show_find) button.pack() + if __name__ == '__main__': from unittest import main main('idlelib.idle_test.test_search', verbosity=2, exit=False) diff --git a/Lib/idlelib/searchengine.py b/Lib/idlelib/searchengine.py index 0684142f43644a..ceb38cfaef900b 100644 --- a/Lib/idlelib/searchengine.py +++ b/Lib/idlelib/searchengine.py @@ -84,7 +84,7 @@ def getprog(self): flags = flags | re.IGNORECASE try: prog = re.compile(pat, flags) - except re.error as e: + except re.PatternError as e: self.report_error(pat, e.msg, e.pos) return None return prog diff --git a/Lib/idlelib/sidebar.py b/Lib/idlelib/sidebar.py index fb1084dbf3f18b..ff77b568a786e0 100644 --- a/Lib/idlelib/sidebar.py +++ b/Lib/idlelib/sidebar.py @@ -25,10 +25,9 @@ def get_end_linenumber(text): def get_displaylines(text, index): """Display height, in lines, of a logical line in a Tk text widget.""" - res = text.count(f"{index} linestart", - f"{index} lineend", - "displaylines") - return res[0] if res else 0 + return text.count(f"{index} linestart", + f"{index} lineend", + "displaylines") def get_widget_padding(widget): """Get the total padding of a Tk widget, including its border.""" @@ -514,16 +513,16 @@ def update_colors(self): self.change_callback() -def _linenumbers_drag_scrolling(parent): # htest # +def _sidebar_number_scrolling(parent): # htest # from idlelib.idle_test.test_sidebar import Dummy_editwin - toplevel = tk.Toplevel(parent) - text_frame = tk.Frame(toplevel) + top = tk.Toplevel(parent) + text_frame = tk.Frame(top) text_frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=True) text_frame.rowconfigure(1, weight=1) text_frame.columnconfigure(1, weight=1) - font = idleConf.GetFont(toplevel, 'main', 'EditorWindow') + font = idleConf.GetFont(top, 'main', 'EditorWindow') text = tk.Text(text_frame, width=80, height=24, wrap=tk.NONE, font=font) text.grid(row=1, column=1, sticky=tk.NSEW) @@ -541,4 +540,4 @@ def _linenumbers_drag_scrolling(parent): # htest # main('idlelib.idle_test.test_sidebar', verbosity=2, exit=False) from idlelib.idle_test.htest import run - run(_linenumbers_drag_scrolling) + run(_sidebar_number_scrolling) diff --git a/Lib/idlelib/stackviewer.py b/Lib/idlelib/stackviewer.py index 7b00c4cdb7d033..977c56ef15f2ae 100644 --- a/Lib/idlelib/stackviewer.py +++ b/Lib/idlelib/stackviewer.py @@ -1,3 +1,5 @@ +# Rename to stackbrowser or possibly consolidate with browser. + import linecache import os @@ -99,7 +101,7 @@ def IsExpandable(self): def GetSubList(self): sublist = [] - for key in self.object.keys(): + for key in self.object.keys(): # self.object not necessarily dict. try: value = self.object[key] except KeyError: @@ -111,7 +113,7 @@ def setfunction(value, key=key, object=self.object): return sublist -def _stack_viewer(parent): # htest # +def _stackbrowser(parent): # htest # from idlelib.pyshell import PyShellFileList top = tk.Toplevel(parent) top.title("Test StackViewer") @@ -129,4 +131,4 @@ def _stack_viewer(parent): # htest # main('idlelib.idle_test.test_stackviewer', verbosity=2, exit=False) from idlelib.idle_test.htest import run - run(_stack_viewer) + run(_stackbrowser) diff --git a/Lib/idlelib/statusbar.py b/Lib/idlelib/statusbar.py index 755fafb0ac6438..8445d4cc8dfdb9 100644 --- a/Lib/idlelib/statusbar.py +++ b/Lib/idlelib/statusbar.py @@ -26,6 +26,7 @@ def _multistatus_bar(parent): # htest # x, y = map(int, parent.geometry().split('+')[1:]) top.geometry("+%d+%d" %(x, y + 175)) top.title("Test multistatus bar") + frame = Frame(top) text = Text(frame, height=5, width=40) text.pack() @@ -42,6 +43,7 @@ def change(): button.pack(side='bottom') frame.pack() + if __name__ == '__main__': from unittest import main main('idlelib.idle_test.test_statusbar', verbosity=2, exit=False) diff --git a/Lib/idlelib/tree.py b/Lib/idlelib/tree.py index 5f30f0f6092bfa..9c2eb47b24aec9 100644 --- a/Lib/idlelib/tree.py +++ b/Lib/idlelib/tree.py @@ -492,6 +492,7 @@ def _tree_widget(parent): # htest # node = TreeNode(sc.canvas, None, item) node.expand() + if __name__ == '__main__': from unittest import main main('idlelib.idle_test.test_tree', verbosity=2, exit=False) diff --git a/Lib/idlelib/undo.py b/Lib/idlelib/undo.py index 5f10c0f05c1acb..f52446d5fcdcf8 100644 --- a/Lib/idlelib/undo.py +++ b/Lib/idlelib/undo.py @@ -339,25 +339,26 @@ def bump_depth(self, incr=1): def _undo_delegator(parent): # htest # from tkinter import Toplevel, Text, Button from idlelib.percolator import Percolator - undowin = Toplevel(parent) - undowin.title("Test UndoDelegator") + top = Toplevel(parent) + top.title("Test UndoDelegator") x, y = map(int, parent.geometry().split('+')[1:]) - undowin.geometry("+%d+%d" % (x, y + 175)) + top.geometry("+%d+%d" % (x, y + 175)) - text = Text(undowin, height=10) + text = Text(top, height=10) text.pack() text.focus_set() p = Percolator(text) d = UndoDelegator() p.insertfilter(d) - undo = Button(undowin, text="Undo", command=lambda:d.undo_event(None)) + undo = Button(top, text="Undo", command=lambda:d.undo_event(None)) undo.pack(side='left') - redo = Button(undowin, text="Redo", command=lambda:d.redo_event(None)) + redo = Button(top, text="Redo", command=lambda:d.redo_event(None)) redo.pack(side='left') - dump = Button(undowin, text="Dump", command=lambda:d.dump_event(None)) + dump = Button(top, text="Dump", command=lambda:d.dump_event(None)) dump.pack(side='left') + if __name__ == "__main__": from unittest import main main('idlelib.idle_test.test_undo', verbosity=2, exit=False) diff --git a/Lib/idlelib/util.py b/Lib/idlelib/util.py index ede670a4db5536..a7ae74b0579004 100644 --- a/Lib/idlelib/util.py +++ b/Lib/idlelib/util.py @@ -13,8 +13,9 @@ * warning stuff (pyshell, run). """ -# .pyw is for Windows; .pyi is for stub files. -py_extensions = ('.py', '.pyw', '.pyi') # Order needed for open/save dialogs. +# .pyw is for Windows; .pyi is for typing stub files. +# The extension order is needed for iomenu open/save dialogs. +py_extensions = ('.py', '.pyw', '.pyi') if __name__ == '__main__': from unittest import main diff --git a/Lib/importlib/_bootstrap.py b/Lib/importlib/_bootstrap.py index c48fd506a0e4eb..d942045f3de666 100644 --- a/Lib/importlib/_bootstrap.py +++ b/Lib/importlib/_bootstrap.py @@ -51,18 +51,106 @@ def _new_module(name): # Module-level locking ######################################################## -# A dict mapping module names to weakrefs of _ModuleLock instances -# Dictionary protected by the global import lock +# For a list that can have a weakref to it. +class _List(list): + pass + + +# Copied from weakref.py with some simplifications and modifications unique to +# bootstrapping importlib. Many methods were simply deleting for simplicity, so if they +# are needed in the future they may work if simply copied back in. +class _WeakValueDictionary: + + def __init__(self): + self_weakref = _weakref.ref(self) + + # Inlined to avoid issues with inheriting from _weakref.ref before _weakref is + # set by _setup(). Since there's only one instance of this class, this is + # not expensive. + class KeyedRef(_weakref.ref): + + __slots__ = "key", + + def __new__(type, ob, key): + self = super().__new__(type, ob, type.remove) + self.key = key + return self + + def __init__(self, ob, key): + super().__init__(ob, self.remove) + + @staticmethod + def remove(wr): + nonlocal self_weakref + + self = self_weakref() + if self is not None: + if self._iterating: + self._pending_removals.append(wr.key) + else: + _weakref._remove_dead_weakref(self.data, wr.key) + + self._KeyedRef = KeyedRef + self.clear() + + def clear(self): + self._pending_removals = [] + self._iterating = set() + self.data = {} + + def _commit_removals(self): + pop = self._pending_removals.pop + d = self.data + while True: + try: + key = pop() + except IndexError: + return + _weakref._remove_dead_weakref(d, key) + + def get(self, key, default=None): + if self._pending_removals: + self._commit_removals() + try: + wr = self.data[key] + except KeyError: + return default + else: + if (o := wr()) is None: + return default + else: + return o + + def setdefault(self, key, default=None): + try: + o = self.data[key]() + except KeyError: + o = None + if o is None: + if self._pending_removals: + self._commit_removals() + self.data[key] = self._KeyedRef(default, key) + return default + else: + return o + + +# A dict mapping module names to weakrefs of _ModuleLock instances. +# Dictionary protected by the global import lock. _module_locks = {} -# A dict mapping thread IDs to lists of _ModuleLock instances. This maps a -# thread to the module locks it is blocking on acquiring. The values are -# lists because a single thread could perform a re-entrant import and be "in -# the process" of blocking on locks for more than one module. A thread can -# be "in the process" because a thread cannot actually block on acquiring -# more than one lock but it can have set up bookkeeping that reflects that -# it intends to block on acquiring more than one lock. -_blocking_on = {} +# A dict mapping thread IDs to weakref'ed lists of _ModuleLock instances. +# This maps a thread to the module locks it is blocking on acquiring. The +# values are lists because a single thread could perform a re-entrant import +# and be "in the process" of blocking on locks for more than one module. A +# thread can be "in the process" because a thread cannot actually block on +# acquiring more than one lock but it can have set up bookkeeping that reflects +# that it intends to block on acquiring more than one lock. +# +# The dictionary uses a WeakValueDictionary to avoid keeping unnecessary +# lists around, regardless of GC runs. This way there's no memory leak if +# the list is no longer needed (GH-106176). +_blocking_on = None class _BlockingOnManager: @@ -79,7 +167,7 @@ def __enter__(self): # re-entrant (i.e., a single thread may take it more than once) so it # wouldn't help us be correct in the face of re-entrancy either. - self.blocked_on = _blocking_on.setdefault(self.thread_id, []) + self.blocked_on = _blocking_on.setdefault(self.thread_id, _List()) self.blocked_on.append(self.lock) def __exit__(self, *args, **kwargs): @@ -736,10 +824,16 @@ def _module_repr_from_spec(spec): """Return the repr to use for the module.""" name = '?' if spec.name is None else spec.name if spec.origin is None: - if spec.loader is None: + loader = spec.loader + if loader is None: return f'' + elif ( + _bootstrap_external is not None + and isinstance(loader, _bootstrap_external.NamespaceLoader) + ): + return f'' else: - return f'' + return f'' else: if spec.has_location: return f'' @@ -1409,7 +1503,7 @@ def _setup(sys_module, _imp_module): modules, those two modules must be explicitly passed in. """ - global _imp, sys + global _imp, sys, _blocking_on _imp = _imp_module sys = sys_module @@ -1437,6 +1531,9 @@ def _setup(sys_module, _imp_module): builtin_module = sys.modules[builtin_name] setattr(self_module, builtin_name, builtin_module) + # Instantiation requires _weakref to have been set. + _blocking_on = _WeakValueDictionary() + def _install(sys_module, _imp_module): """Install importers for builtin and frozen modules""" diff --git a/Lib/importlib/_bootstrap_external.py b/Lib/importlib/_bootstrap_external.py index 16a82bef2ba71f..97858ee83f790f 100644 --- a/Lib/importlib/_bootstrap_external.py +++ b/Lib/importlib/_bootstrap_external.py @@ -413,6 +413,7 @@ def _write_atomic(path, data, mode=0o666): # Python 3.11a7 3492 (make POP_JUMP_IF_NONE/NOT_NONE/TRUE/FALSE relative) # Python 3.11a7 3493 (Make JUMP_IF_TRUE_OR_POP/JUMP_IF_FALSE_OR_POP relative) # Python 3.11a7 3494 (New location info table) +# Python 3.11b4 3495 (Set line number of module's RESUME instr to 0 per PEP 626) # Python 3.12a1 3500 (Remove PRECALL opcode) # Python 3.12a1 3501 (YIELD_VALUE oparg == stack_depth) # Python 3.12a1 3502 (LOAD_FAST_CHECK, no NULL-check in LOAD_FAST) @@ -453,6 +454,15 @@ def _write_atomic(path, data, mode=0o666): # Python 3.13a1 3555 (generate specialized opcodes metadata from bytecodes.c) # Python 3.13a1 3556 (Convert LOAD_CLOSURE to a pseudo-op) # Python 3.13a1 3557 (Make the conversion to boolean in jumps explicit) +# Python 3.13a1 3558 (Reorder the stack items for CALL) +# Python 3.13a1 3559 (Generate opcode IDs from bytecodes.c) +# Python 3.13a1 3560 (Add RESUME_CHECK instruction) +# Python 3.13a1 3561 (Add cache entry to branch instructions) +# Python 3.13a1 3562 (Assign opcode IDs for internal ops in separate range) +# Python 3.13a1 3563 (Add CALL_KW and remove KW_NAMES) +# Python 3.13a1 3564 (Removed oparg from YIELD_VALUE, changed oparg values of RESUME) +# Python 3.13a1 3565 (Oparg of YIELD_VALUE indicates whether it is in a yield-from) +# Python 3.13a1 3566 (Emit JUMP_NO_INTERRUPT instead of JUMP for non-loop no-lineno cases) # Python 3.14 will start with 3600 @@ -469,7 +479,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 = (3557).to_bytes(2, 'little') + b'\r\n' +MAGIC_NUMBER = (3566).to_bytes(2, 'little') + b'\r\n' _RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little') # For import.c diff --git a/Lib/importlib/metadata/__init__.py b/Lib/importlib/metadata/__init__.py index 5c09666b6a40d9..7b142e786e829e 100644 --- a/Lib/importlib/metadata/__init__.py +++ b/Lib/importlib/metadata/__init__.py @@ -3,7 +3,10 @@ import abc import csv import sys +import json import email +import types +import inspect import pathlib import zipfile import operator @@ -13,7 +16,6 @@ import itertools import posixpath import collections -import inspect from . import _adapters, _meta from ._collections import FreezableDefaultDict, Pair @@ -25,8 +27,7 @@ from importlib import import_module from importlib.abc import MetaPathFinder from itertools import starmap -from typing import List, Mapping, Optional, cast - +from typing import Iterable, List, Mapping, Optional, Set, Union, cast __all__ = [ 'Distribution', @@ -47,11 +48,11 @@ class PackageNotFoundError(ModuleNotFoundError): """The package was not found.""" - def __str__(self): + def __str__(self) -> str: return f"No package metadata was found for {self.name}" @property - def name(self): + def name(self) -> str: # type: ignore[override] (name,) = self.args return name @@ -117,38 +118,11 @@ def read(text, filter_=None): yield Pair(name, value) @staticmethod - def valid(line): + def valid(line: str): return line and not line.startswith('#') -class DeprecatedTuple: - """ - Provide subscript item access for backward compatibility. - - >>> recwarn = getfixture('recwarn') - >>> ep = EntryPoint(name='name', value='value', group='group') - >>> ep[:] - ('name', 'value', 'group') - >>> ep[0] - 'name' - >>> len(recwarn) - 1 - """ - - # Do not remove prior to 2023-05-01 or Python 3.13 - _warn = functools.partial( - warnings.warn, - "EntryPoint tuple interface is deprecated. Access members by name.", - DeprecationWarning, - stacklevel=2, - ) - - def __getitem__(self, item): - self._warn() - return self._key()[item] - - -class EntryPoint(DeprecatedTuple): +class EntryPoint: """An entry point as defined by Python packaging conventions. See `the packaging docs on entry points @@ -192,7 +166,7 @@ class EntryPoint(DeprecatedTuple): dist: Optional['Distribution'] = None - def __init__(self, name, value, group): + def __init__(self, name: str, value: str, group: str) -> None: vars(self).update(name=name, value=value, group=group) def load(self): @@ -206,18 +180,21 @@ def load(self): return functools.reduce(getattr, attrs, module) @property - def module(self): + def module(self) -> str: match = self.pattern.match(self.value) + assert match is not None return match.group('module') @property - def attr(self): + def attr(self) -> str: match = self.pattern.match(self.value) + assert match is not None return match.group('attr') @property - def extras(self): + def extras(self) -> List[str]: match = self.pattern.match(self.value) + assert match is not None return re.findall(r'\w+', match.group('extras') or '') def _for(self, dist): @@ -265,7 +242,7 @@ def __repr__(self): f'group={self.group!r})' ) - def __hash__(self): + def __hash__(self) -> int: return hash(self._key()) @@ -276,7 +253,7 @@ class EntryPoints(tuple): __slots__ = () - def __getitem__(self, name): # -> EntryPoint: + def __getitem__(self, name: str) -> EntryPoint: # type: ignore[override] """ Get the EntryPoint in self matching name. """ @@ -285,6 +262,13 @@ def __getitem__(self, name): # -> EntryPoint: except StopIteration: raise KeyError(name) + def __repr__(self): + """ + Repr with classname and tuple constructor to + signal that we deviate from regular tuple behavior. + """ + return '%s(%r)' % (self.__class__.__name__, tuple(self)) + def select(self, **params): """ Select entry points from self that match the @@ -293,14 +277,14 @@ def select(self, **params): return EntryPoints(ep for ep in self if ep.matches(**params)) @property - def names(self): + def names(self) -> Set[str]: """ Return the set of all names of all entry points. """ return {ep.name for ep in self} @property - def groups(self): + def groups(self) -> Set[str]: """ Return the set of all groups of all entry points. """ @@ -321,24 +305,28 @@ def _from_text(text): class PackagePath(pathlib.PurePosixPath): """A reference to a path in a package""" - def read_text(self, encoding='utf-8'): + hash: Optional["FileHash"] + size: int + dist: "Distribution" + + def read_text(self, encoding: str = 'utf-8') -> str: # type: ignore[override] with self.locate().open(encoding=encoding) as stream: return stream.read() - def read_binary(self): + def read_binary(self) -> bytes: with self.locate().open('rb') as stream: return stream.read() - def locate(self): + def locate(self) -> pathlib.Path: """Return a path-like object for this path""" return self.dist.locate_file(self) class FileHash: - def __init__(self, spec): + def __init__(self, spec: str) -> None: self.mode, _, self.value = spec.partition('=') - def __repr__(self): + def __repr__(self) -> str: return f'' @@ -373,14 +361,14 @@ def read_text(self, filename) -> Optional[str]: """ @abc.abstractmethod - def locate_file(self, path): + def locate_file(self, path: Union[str, os.PathLike[str]]) -> pathlib.Path: """ Given a path to a file in this distribution, return a path to it. """ @classmethod - def from_name(cls, name: str): + def from_name(cls, name: str) -> "Distribution": """Return the Distribution for the given package name. :param name: The name of the distribution package to search for. @@ -393,12 +381,12 @@ def from_name(cls, name: str): if not name: raise ValueError("A distribution name is required.") try: - return next(cls.discover(name=name)) + return next(iter(cls.discover(name=name))) except StopIteration: raise PackageNotFoundError(name) @classmethod - def discover(cls, **kwargs): + def discover(cls, **kwargs) -> Iterable["Distribution"]: """Return an iterable of Distribution objects for all packages. Pass a ``context`` or pass keyword arguments for constructing @@ -416,7 +404,7 @@ def discover(cls, **kwargs): ) @staticmethod - def at(path): + def at(path: Union[str, os.PathLike[str]]) -> "Distribution": """Return a Distribution for the indicated metadata path :param path: a string or path-like object @@ -451,7 +439,7 @@ def metadata(self) -> _meta.PackageMetadata: return _adapters.Message(email.message_from_string(text)) @property - def name(self): + def name(self) -> str: """Return the 'Name' metadata for the distribution package.""" return self.metadata['Name'] @@ -461,16 +449,16 @@ def _normalized_name(self): return Prepared.normalize(self.name) @property - def version(self): + def version(self) -> str: """Return the 'Version' metadata for the distribution package.""" return self.metadata['Version'] @property - def entry_points(self): + def entry_points(self) -> EntryPoints: return EntryPoints._from_text_for(self.read_text('entry_points.txt'), self) @property - def files(self): + def files(self) -> Optional[List[PackagePath]]: """Files in this distribution. :return: List of PackagePath for this distribution or None @@ -555,7 +543,7 @@ def _read_files_egginfo_sources(self): return text and map('"{}"'.format, text.splitlines()) @property - def requires(self): + def requires(self) -> Optional[List[str]]: """Generated requirements specified for this Distribution""" reqs = self._read_dist_info_reqs() or self._read_egg_info_reqs() return reqs and list(reqs) @@ -606,6 +594,16 @@ def url_req_space(req): space = url_req_space(section.value) yield section.value + space + quoted_marker(section.name) + @property + def origin(self): + return self._load_json('direct_url.json') + + def _load_json(self, filename): + return pass_none(json.loads)( + self.read_text(filename), + object_hook=lambda data: types.SimpleNamespace(**data), + ) + class DistributionFinder(MetaPathFinder): """ @@ -634,7 +632,7 @@ def __init__(self, **kwargs): vars(self).update(kwargs) @property - def path(self): + def path(self) -> List[str]: """ The sequence of directory path that a distribution finder should search. @@ -645,7 +643,7 @@ def path(self): return vars(self).get('path', sys.path) @abc.abstractmethod - def find_distributions(self, context=Context()): + def find_distributions(self, context=Context()) -> Iterable[Distribution]: """ Find distributions. @@ -774,7 +772,9 @@ def __bool__(self): class MetadataPathFinder(DistributionFinder): @classmethod - def find_distributions(cls, context=DistributionFinder.Context()): + def find_distributions( + cls, context=DistributionFinder.Context() + ) -> Iterable["PathDistribution"]: """ Find distributions. @@ -794,19 +794,19 @@ def _search_paths(cls, name, paths): path.search(prepared) for path in map(FastPath, paths) ) - def invalidate_caches(cls): + def invalidate_caches(cls) -> None: FastPath.__new__.cache_clear() class PathDistribution(Distribution): - def __init__(self, path: SimplePath): + def __init__(self, path: SimplePath) -> None: """Construct a distribution. :param path: SimplePath indicating the metadata directory. """ self._path = path - def read_text(self, filename): + def read_text(self, filename: Union[str, os.PathLike[str]]) -> Optional[str]: with suppress( FileNotFoundError, IsADirectoryError, @@ -816,9 +816,11 @@ def read_text(self, filename): ): return self._path.joinpath(filename).read_text(encoding='utf-8') + return None + read_text.__doc__ = Distribution.read_text.__doc__ - def locate_file(self, path): + def locate_file(self, path: Union[str, os.PathLike[str]]) -> pathlib.Path: return self._path.parent / path @property @@ -851,7 +853,7 @@ def _name_from_stem(stem): return name -def distribution(distribution_name): +def distribution(distribution_name: str) -> Distribution: """Get the ``Distribution`` instance for the named package. :param distribution_name: The name of the distribution package as a string. @@ -860,7 +862,7 @@ def distribution(distribution_name): return Distribution.from_name(distribution_name) -def distributions(**kwargs): +def distributions(**kwargs) -> Iterable[Distribution]: """Get all ``Distribution`` instances in the current environment. :return: An iterable of ``Distribution`` instances. @@ -868,7 +870,7 @@ def distributions(**kwargs): return Distribution.discover(**kwargs) -def metadata(distribution_name) -> _meta.PackageMetadata: +def metadata(distribution_name: str) -> _meta.PackageMetadata: """Get the metadata for the named package. :param distribution_name: The name of the distribution package to query. @@ -877,7 +879,7 @@ def metadata(distribution_name) -> _meta.PackageMetadata: return Distribution.from_name(distribution_name).metadata -def version(distribution_name): +def version(distribution_name: str) -> str: """Get the version string for the named package. :param distribution_name: The name of the distribution package to query. @@ -911,7 +913,7 @@ def entry_points(**params) -> EntryPoints: return EntryPoints(eps).select(**params) -def files(distribution_name): +def files(distribution_name: str) -> Optional[List[PackagePath]]: """Return a list of files for the named package. :param distribution_name: The name of the distribution package to query. @@ -920,11 +922,11 @@ def files(distribution_name): return distribution(distribution_name).files -def requires(distribution_name): +def requires(distribution_name: str) -> Optional[List[str]]: """ Return a list of requirements for the named package. - :return: An iterator of requirements, suitable for + :return: An iterable of requirements, suitable for packaging.requirement.Requirement. """ return distribution(distribution_name).requires @@ -951,13 +953,42 @@ def _top_level_declared(dist): return (dist.read_text('top_level.txt') or '').split() +def _topmost(name: PackagePath) -> Optional[str]: + """ + Return the top-most parent as long as there is a parent. + """ + top, *rest = name.parts + return top if rest else None + + +def _get_toplevel_name(name: PackagePath) -> str: + """ + Infer a possibly importable module name from a name presumed on + sys.path. + + >>> _get_toplevel_name(PackagePath('foo.py')) + 'foo' + >>> _get_toplevel_name(PackagePath('foo')) + 'foo' + >>> _get_toplevel_name(PackagePath('foo.pyc')) + 'foo' + >>> _get_toplevel_name(PackagePath('foo/__init__.py')) + 'foo' + >>> _get_toplevel_name(PackagePath('foo.pth')) + 'foo.pth' + >>> _get_toplevel_name(PackagePath('foo.dist-info')) + 'foo.dist-info' + """ + return _topmost(name) or ( + # python/typeshed#10328 + inspect.getmodulename(name) # type: ignore + or str(name) + ) + + def _top_level_inferred(dist): - opt_names = { - f.parts[0] if len(f.parts) > 1 else inspect.getmodulename(f) - for f in always_iterable(dist.files) - } + opt_names = set(map(_get_toplevel_name, always_iterable(dist.files))) - @pass_none def importable_name(name): return '.' not in name diff --git a/Lib/importlib/metadata/_adapters.py b/Lib/importlib/metadata/_adapters.py index 6aed69a30857e4..591168808953ba 100644 --- a/Lib/importlib/metadata/_adapters.py +++ b/Lib/importlib/metadata/_adapters.py @@ -53,7 +53,7 @@ def __iter__(self): def __getitem__(self, item): """ Warn users that a ``KeyError`` can be expected when a - mising key is supplied. Ref python/importlib_metadata#371. + missing key is supplied. Ref python/importlib_metadata#371. """ res = super().__getitem__(item) if res is None: diff --git a/Lib/importlib/metadata/_meta.py b/Lib/importlib/metadata/_meta.py index c9a7ef906a8a8c..f670016de7fef2 100644 --- a/Lib/importlib/metadata/_meta.py +++ b/Lib/importlib/metadata/_meta.py @@ -49,7 +49,7 @@ class SimplePath(Protocol[_T]): A minimal subset of pathlib.Path required by PathDistribution. """ - def joinpath(self) -> _T: + def joinpath(self, other: Union[str, _T]) -> _T: ... # pragma: no cover def __truediv__(self, other: Union[str, _T]) -> _T: diff --git a/Lib/importlib/metadata/diagnose.py b/Lib/importlib/metadata/diagnose.py new file mode 100644 index 00000000000000..e405471ac4d943 --- /dev/null +++ b/Lib/importlib/metadata/diagnose.py @@ -0,0 +1,21 @@ +import sys + +from . import Distribution + + +def inspect(path): + print("Inspecting", path) + dists = list(Distribution.discover(path=[path])) + if not dists: + return + print("Found", len(dists), "packages:", end=' ') + print(', '.join(dist.name for dist in dists)) + + +def run(): + for path in sys.path: + inspect(path) + + +if __name__ == '__main__': + run() diff --git a/Lib/importlib/util.py b/Lib/importlib/util.py index f4d6e82331516f..3ad71d31c2f438 100644 --- a/Lib/importlib/util.py +++ b/Lib/importlib/util.py @@ -135,7 +135,7 @@ class _incompatible_extension_module_restrictions: may not be imported in a subinterpreter. That implies modules that do not implement multi-phase init or that explicitly of out. - Likewise for modules import in a subinterpeter with its own GIL + Likewise for modules import in a subinterpreter with its own GIL when the extension does not support a per-interpreter GIL. This implies the module does not have a Py_mod_multiple_interpreters slot set to Py_MOD_PER_INTERPRETER_GIL_SUPPORTED. diff --git a/Lib/inspect.py b/Lib/inspect.py index c8211833dd0831..f0b72662a9a0b2 100644 --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -2870,6 +2870,8 @@ def __str__(self): return formatted + __replace__ = replace + def __repr__(self): return '<{} "{}">'.format(self.__class__.__name__, self) @@ -3130,6 +3132,8 @@ def replace(self, *, parameters=_void, return_annotation=_void): return type(self)(parameters, return_annotation=return_annotation) + __replace__ = replace + def _hash_basis(self): params = tuple(param for param in self.parameters.values() if param.kind != _KEYWORD_ONLY) @@ -3312,6 +3316,16 @@ def __repr__(self): return '<{} {}>'.format(self.__class__.__name__, self) def __str__(self): + return self.format() + + def format(self, *, max_width=None): + """Create a string representation of the Signature object. + + If *max_width* integer is passed, + signature will try to fit into the *max_width*. + If signature is longer than *max_width*, + all parameters will be on separate lines. + """ result = [] render_pos_only_separator = False render_kw_only_separator = True @@ -3349,6 +3363,8 @@ def __str__(self): result.append('/') rendered = '({})'.format(', '.join(result)) + if max_width is not None and len(rendered) > max_width: + rendered = '(\n {}\n)'.format(',\n '.join(result)) if self.return_annotation is not _empty: anno = formatannotation(self.return_annotation) diff --git a/Lib/io.py b/Lib/io.py index 50ce97436ac1d1..f0e2fa15d5abcf 100644 --- a/Lib/io.py +++ b/Lib/io.py @@ -45,7 +45,8 @@ "FileIO", "BytesIO", "StringIO", "BufferedIOBase", "BufferedReader", "BufferedWriter", "BufferedRWPair", "BufferedRandom", "TextIOBase", "TextIOWrapper", - "UnsupportedOperation", "SEEK_SET", "SEEK_CUR", "SEEK_END"] + "UnsupportedOperation", "SEEK_SET", "SEEK_CUR", "SEEK_END", + "DEFAULT_BUFFER_SIZE", "text_encoding", "IncrementalNewlineDecoder"] import _io diff --git a/Lib/ipaddress.py b/Lib/ipaddress.py index f5aba434fd4253..e398cc138308d9 100644 --- a/Lib/ipaddress.py +++ b/Lib/ipaddress.py @@ -1389,6 +1389,16 @@ def is_link_local(self): """ return self in self._constants._linklocal_network + @property + def ipv6_mapped(self): + """Return the IPv4-mapped IPv6 address. + + Returns: + The IPv4-mapped IPv6 address per RFC 4291. + + """ + return IPv6Address(f'::ffff:{self}') + class IPv4Interface(IPv4Address): @@ -1970,6 +1980,9 @@ def __eq__(self, other): return False return self._scope_id == getattr(other, '_scope_id', None) + def __reduce__(self): + return (self.__class__, (str(self),)) + @property def scope_id(self): """Identifier of a particular zone of the address's scope. diff --git a/Lib/json/decoder.py b/Lib/json/decoder.py index c5d9ae2d0d5d04..d69a45d6793069 100644 --- a/Lib/json/decoder.py +++ b/Lib/json/decoder.py @@ -200,10 +200,13 @@ def JSONObject(s_and_end, strict, scan_once, object_hook, object_pairs_hook, break elif nextchar != ',': raise JSONDecodeError("Expecting ',' delimiter", s, end - 1) + comma_idx = end - 1 end = _w(s, end).end() nextchar = s[end:end + 1] end += 1 if nextchar != '"': + if nextchar == '}': + raise JSONDecodeError("Illegal trailing comma before end of object", s, comma_idx) raise JSONDecodeError( "Expecting property name enclosed in double quotes", s, end - 1) if object_pairs_hook is not None: @@ -240,13 +243,17 @@ def JSONArray(s_and_end, scan_once, _w=WHITESPACE.match, _ws=WHITESPACE_STR): break elif nextchar != ',': raise JSONDecodeError("Expecting ',' delimiter", s, end - 1) + comma_idx = end - 1 try: if s[end] in _ws: end += 1 if s[end] in _ws: end = _w(s, end + 1).end() + nextchar = s[end:end + 1] except IndexError: pass + if nextchar == ']': + raise JSONDecodeError("Illegal trailing comma before end of array", s, comma_idx) return values, end diff --git a/Lib/json/tool.py b/Lib/json/tool.py index 0490b8c0be11df..fdfc3372bcca02 100644 --- a/Lib/json/tool.py +++ b/Lib/json/tool.py @@ -13,7 +13,6 @@ import argparse import json import sys -from pathlib import Path def main(): @@ -22,11 +21,9 @@ def main(): 'to validate and pretty-print JSON objects.') parser = argparse.ArgumentParser(prog=prog, description=description) parser.add_argument('infile', nargs='?', - type=argparse.FileType(encoding="utf-8"), help='a JSON file to be validated or pretty-printed', - default=sys.stdin) + default='-') parser.add_argument('outfile', nargs='?', - type=Path, help='write the output of infile to outfile', default=None) parser.add_argument('--sort-keys', action='store_true', default=False, @@ -59,23 +56,30 @@ def main(): dump_args['indent'] = None dump_args['separators'] = ',', ':' - with options.infile as infile: + try: + if options.infile == '-': + infile = sys.stdin + else: + infile = open(options.infile, encoding='utf-8') try: if options.json_lines: objs = (json.loads(line) for line in infile) else: objs = (json.load(infile),) + finally: + if infile is not sys.stdin: + infile.close() - if options.outfile is None: - out = sys.stdout - else: - out = options.outfile.open('w', encoding='utf-8') - with out as outfile: - for obj in objs: - json.dump(obj, outfile, **dump_args) - outfile.write('\n') - except ValueError as e: - raise SystemExit(e) + if options.outfile is None: + outfile = sys.stdout + else: + outfile = open(options.outfile, 'w', encoding='utf-8') + with outfile: + for obj in objs: + json.dump(obj, outfile, **dump_args) + outfile.write('\n') + except ValueError as e: + raise SystemExit(e) if __name__ == '__main__': diff --git a/Lib/linecache.py b/Lib/linecache.py index 97644a8e3794e1..329a14053458b7 100644 --- a/Lib/linecache.py +++ b/Lib/linecache.py @@ -5,10 +5,8 @@ that name. """ -import functools import sys import os -import tokenize __all__ = ["getline", "clearcache", "checkcache", "lazycache"] @@ -82,6 +80,8 @@ def updatecache(filename, module_globals=None): If something's wrong, print a message, discard the cache entry, and return an empty list.""" + import tokenize + if filename in cache: if len(cache[filename]) != 1: cache.pop(filename, None) @@ -176,7 +176,16 @@ def lazycache(filename, module_globals): get_source = getattr(loader, 'get_source', None) if name and get_source: - get_lines = functools.partial(get_source, name) + def get_lines(name=name, *args, **kwargs): + return get_source(name, *args, **kwargs) cache[filename] = (get_lines,) return True return False + + +def _register_code(code, string, name): + cache[code] = ( + len(string), + None, + [line + '\n' for line in string.splitlines()], + name) diff --git a/Lib/locale.py b/Lib/locale.py index 55c819ca80a160..e0cb4c5449d556 100644 --- a/Lib/locale.py +++ b/Lib/locale.py @@ -541,12 +541,14 @@ def getdefaultlocale(envvars=('LC_ALL', 'LC_CTYPE', 'LANG', 'LANGUAGE')): """ import warnings - warnings.warn( - "Use setlocale(), getencoding() and getlocale() instead", - DeprecationWarning, stacklevel=2 - ) + warnings._deprecated( + "locale.getdefaultlocale", + "{name!r} is deprecated and slated for removal in Python {remove}. " + "Use setlocale(), getencoding() and getlocale() instead.", + remove=(3, 15)) return _getdefaultlocale(envvars) + def _getdefaultlocale(envvars=('LC_ALL', 'LC_CTYPE', 'LANG', 'LANGUAGE')): try: # check if it's supported by the _locale module diff --git a/Lib/logging/__init__.py b/Lib/logging/__init__.py index 46e86cb87ecfcb..eb7e020d1edfc0 100644 --- a/Lib/logging/__init__.py +++ b/Lib/logging/__init__.py @@ -159,12 +159,9 @@ def addLevelName(level, levelName): This is used when converting levels to text during message formatting. """ - _acquireLock() - try: #unlikely to cause an exception, but you never know... + with _lock: _levelToName[level] = levelName _nameToLevel[levelName] = level - finally: - _releaseLock() if hasattr(sys, "_getframe"): currentframe = lambda: sys._getframe(1) @@ -231,25 +228,27 @@ def _checkLevel(level): # _lock = threading.RLock() -def _acquireLock(): +def _prepareFork(): """ - Acquire the module-level lock for serializing access to shared data. + Prepare to fork a new child process by acquiring the module-level lock. - This should be released with _releaseLock(). + This should be used in conjunction with _afterFork(). """ - if _lock: - try: - _lock.acquire() - except BaseException: - _lock.release() - raise + # Wrap the lock acquisition in a try-except to prevent the lock from being + # abandoned in the event of an asynchronous exception. See gh-106238. + try: + _lock.acquire() + except BaseException: + _lock.release() + raise -def _releaseLock(): +def _afterFork(): """ - Release the module-level lock acquired by calling _acquireLock(). + After a new child process has been forked, release the module-level lock. + + This should be used in conjunction with _prepareFork(). """ - if _lock: - _lock.release() + _lock.release() # Prevent a held logging lock from blocking a child from logging. @@ -264,23 +263,20 @@ def _register_at_fork_reinit_lock(instance): _at_fork_reinit_lock_weakset = weakref.WeakSet() def _register_at_fork_reinit_lock(instance): - _acquireLock() - try: + with _lock: _at_fork_reinit_lock_weakset.add(instance) - finally: - _releaseLock() def _after_at_fork_child_reinit_locks(): for handler in _at_fork_reinit_lock_weakset: handler._at_fork_reinit() - # _acquireLock() was called in the parent before forking. + # _prepareFork() was called in the parent before forking. # The lock is reinitialized to unlocked state. _lock._at_fork_reinit() - os.register_at_fork(before=_acquireLock, + os.register_at_fork(before=_prepareFork, after_in_child=_after_at_fork_child_reinit_locks, - after_in_parent=_releaseLock) + after_in_parent=_afterFork) #--------------------------------------------------------------------------- @@ -883,25 +879,20 @@ def _removeHandlerRef(wr): # set to None. It can also be called from another thread. So we need to # pre-emptively grab the necessary globals and check if they're None, # to prevent race conditions and failures during interpreter shutdown. - acquire, release, handlers = _acquireLock, _releaseLock, _handlerList - if acquire and release and handlers: - acquire() - try: - handlers.remove(wr) - except ValueError: - pass - finally: - release() + handlers, lock = _handlerList, _lock + if lock and handlers: + with lock: + try: + handlers.remove(wr) + except ValueError: + pass def _addHandlerRef(handler): """ Add a handler to the internal cleanup list using a weak reference. """ - _acquireLock() - try: + with _lock: _handlerList.append(weakref.ref(handler, _removeHandlerRef)) - finally: - _releaseLock() def getHandlerByName(name): @@ -916,8 +907,7 @@ def getHandlerNames(): """ Return all known handler names as an immutable set. """ - result = set(_handlers.keys()) - return frozenset(result) + return frozenset(_handlers) class Handler(Filterer): @@ -947,15 +937,12 @@ def get_name(self): return self._name def set_name(self, name): - _acquireLock() - try: + with _lock: if self._name in _handlers: del _handlers[self._name] self._name = name if name: _handlers[name] = self - finally: - _releaseLock() name = property(get_name, set_name) @@ -1027,11 +1014,8 @@ def handle(self, record): if isinstance(rv, LogRecord): record = rv if rv: - self.acquire() - try: + with self.lock: self.emit(record) - finally: - self.release() return rv def setFormatter(self, fmt): @@ -1059,13 +1043,10 @@ def close(self): methods. """ #get the module data lock, as we're updating a shared structure. - _acquireLock() - try: #unlikely to raise an exception, but you never know... + with _lock: self._closed = True if self._name and self._name in _handlers: del _handlers[self._name] - finally: - _releaseLock() def handleError(self, record): """ @@ -1142,12 +1123,9 @@ def flush(self): """ Flushes the stream. """ - self.acquire() - try: + with self.lock: if self.stream and hasattr(self.stream, "flush"): self.stream.flush() - finally: - self.release() def emit(self, record): """ @@ -1183,12 +1161,9 @@ def setStream(self, stream): result = None else: result = self.stream - self.acquire() - try: + with self.lock: self.flush() self.stream = stream - finally: - self.release() return result def __repr__(self): @@ -1238,8 +1213,7 @@ def close(self): """ Closes the stream. """ - self.acquire() - try: + with self.lock: try: if self.stream: try: @@ -1255,8 +1229,6 @@ def close(self): # Also see Issue #42378: we also rely on # self._closed being set to True there StreamHandler.close(self) - finally: - self.release() def _open(self): """ @@ -1392,8 +1364,7 @@ def getLogger(self, name): rv = None if not isinstance(name, str): raise TypeError('A logger name must be a string') - _acquireLock() - try: + with _lock: if name in self.loggerDict: rv = self.loggerDict[name] if isinstance(rv, PlaceHolder): @@ -1408,8 +1379,6 @@ def getLogger(self, name): rv.manager = self self.loggerDict[name] = rv self._fixupParents(rv) - finally: - _releaseLock() return rv def setLoggerClass(self, klass): @@ -1472,12 +1441,11 @@ def _clear_cache(self): Called when level changes are made """ - _acquireLock() - for logger in self.loggerDict.values(): - if isinstance(logger, Logger): - logger._cache.clear() - self.root._cache.clear() - _releaseLock() + with _lock: + for logger in self.loggerDict.values(): + if isinstance(logger, Logger): + logger._cache.clear() + self.root._cache.clear() #--------------------------------------------------------------------------- # Logger classes and functions @@ -1702,23 +1670,17 @@ def addHandler(self, hdlr): """ Add the specified handler to this logger. """ - _acquireLock() - try: + with _lock: if not (hdlr in self.handlers): self.handlers.append(hdlr) - finally: - _releaseLock() def removeHandler(self, hdlr): """ Remove the specified handler from this logger. """ - _acquireLock() - try: + with _lock: if hdlr in self.handlers: self.handlers.remove(hdlr) - finally: - _releaseLock() def hasHandlers(self): """ @@ -1796,16 +1758,13 @@ def isEnabledFor(self, level): try: return self._cache[level] except KeyError: - _acquireLock() - try: + with _lock: if self.manager.disable >= level: is_enabled = self._cache[level] = False else: is_enabled = self._cache[level] = ( level >= self.getEffectiveLevel() ) - finally: - _releaseLock() return is_enabled def getChild(self, suffix): @@ -1835,16 +1794,13 @@ def _hierlevel(logger): return 1 + logger.name.count('.') d = self.manager.loggerDict - _acquireLock() - try: + with _lock: # 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()) @@ -1880,7 +1836,7 @@ class LoggerAdapter(object): information in logging output. """ - def __init__(self, logger, extra=None): + def __init__(self, logger, extra=None, merge_extra=False): """ Initialize the adapter with a logger and a dict-like object which provides contextual information. This constructor signature allows @@ -1890,9 +1846,20 @@ def __init__(self, logger, extra=None): following example: adapter = LoggerAdapter(someLogger, dict(p1=v1, p2="v2")) + + By default, LoggerAdapter objects will drop the "extra" argument + passed on the individual log calls to use its own instead. + + Initializing it with merge_extra=True will instead merge both + maps when logging, the individual call extra taking precedence + over the LoggerAdapter instance extra + + .. versionchanged:: 3.13 + The *merge_extra* argument was added. """ self.logger = logger self.extra = extra + self.merge_extra = merge_extra def process(self, msg, kwargs): """ @@ -1904,7 +1871,10 @@ def process(self, msg, kwargs): Normally, you'll only need to override this one method in a LoggerAdapter subclass for your specific needs. """ - kwargs["extra"] = self.extra + if self.merge_extra and "extra" in kwargs: + kwargs["extra"] = {**self.extra, **kwargs["extra"]} + else: + kwargs["extra"] = self.extra return msg, kwargs # @@ -2089,8 +2059,7 @@ def basicConfig(**kwargs): """ # Add thread safety in case someone mistakenly calls # basicConfig() from multiple threads - _acquireLock() - try: + with _lock: force = kwargs.pop('force', False) encoding = kwargs.pop('encoding', None) errors = kwargs.pop('errors', 'backslashreplace') @@ -2139,8 +2108,6 @@ def basicConfig(**kwargs): if kwargs: keys = ', '.join(kwargs.keys()) raise ValueError('Unrecognised argument(s): %s' % keys) - finally: - _releaseLock() #--------------------------------------------------------------------------- # Utility functions at module level. diff --git a/Lib/logging/config.py b/Lib/logging/config.py index a68281d3e359fd..de06090942d965 100644 --- a/Lib/logging/config.py +++ b/Lib/logging/config.py @@ -1,4 +1,4 @@ -# Copyright 2001-2022 by Vinay Sajip. All Rights Reserved. +# Copyright 2001-2023 by Vinay Sajip. All Rights Reserved. # # Permission to use, copy, modify, and distribute this software and its # documentation for any purpose and without fee is hereby granted, @@ -83,15 +83,12 @@ def fileConfig(fname, defaults=None, disable_existing_loggers=True, encoding=Non formatters = _create_formatters(cp) # critical section - logging._acquireLock() - try: + with logging._lock: _clearExistingHandlers() # Handlers add themselves to logging._handlers handlers = _install_handlers(cp, formatters) _install_loggers(cp, handlers, disable_existing_loggers) - finally: - logging._releaseLock() def _resolve(name): @@ -378,7 +375,7 @@ class BaseConfigurator(object): WORD_PATTERN = re.compile(r'^\s*(\w+)\s*') DOT_PATTERN = re.compile(r'^\.\s*(\w+)\s*') - INDEX_PATTERN = re.compile(r'^\[\s*(\w+)\s*\]\s*') + INDEX_PATTERN = re.compile(r'^\[([^\[\]]*)\]\s*') DIGIT_PATTERN = re.compile(r'^\d+$') value_converters = { @@ -485,10 +482,10 @@ def configure_custom(self, config): c = config.pop('()') if not callable(c): c = self.resolve(c) - props = config.pop('.', None) # Check for valid identifiers - kwargs = {k: config[k] for k in config if valid_ident(k)} + kwargs = {k: config[k] for k in config if (k != '.' and valid_ident(k))} result = c(**kwargs) + props = config.pop('.', None) if props: for name, value in props.items(): setattr(result, name, value) @@ -516,8 +513,7 @@ def configure(self): raise ValueError("Unsupported version: %s" % config['version']) incremental = config.pop('incremental', False) EMPTY_DICT = {} - logging._acquireLock() - try: + with logging._lock: if incremental: handlers = config.get('handlers', EMPTY_DICT) for name in handlers: @@ -661,8 +657,6 @@ def configure(self): except Exception as e: raise ValueError('Unable to configure root ' 'logger') from e - finally: - logging._releaseLock() def configure_formatter(self, config): """Configure a formatter from a dictionary.""" @@ -740,7 +734,7 @@ def _configure_queue_handler(self, klass, **kwargs): lklass = kwargs['listener'] else: lklass = logging.handlers.QueueListener - listener = lklass(q, *kwargs['handlers'], respect_handler_level=rhl) + listener = lklass(q, *kwargs.get('handlers', []), respect_handler_level=rhl) handler = klass(q) handler.listener = listener return handler @@ -782,11 +776,12 @@ def configure_handler(self, config): raise ValueError('Unable to set target handler %r' % tn) from e elif issubclass(klass, logging.handlers.QueueHandler): # Another special case for handler which refers to other handlers - if 'handlers' not in config: - raise ValueError('No handlers specified for a QueueHandler') + # if 'handlers' not in config: + # raise ValueError('No handlers specified for a QueueHandler') if 'queue' in config: + from multiprocessing.queues import Queue as MPQueue qspec = config['queue'] - if not isinstance(qspec, queue.Queue): + if not isinstance(qspec, (queue.Queue, MPQueue)): if isinstance(qspec, str): q = self.resolve(qspec) if not callable(q): @@ -819,18 +814,19 @@ def configure_handler(self, config): if not callable(listener): raise TypeError('Invalid listener specifier %r' % lspec) config['listener'] = listener - hlist = [] - try: - for hn in config['handlers']: - h = self.config['handlers'][hn] - if not isinstance(h, logging.Handler): - config.update(config_copy) # restore for deferred cfg - raise TypeError('Required handler %r ' - 'is not configured yet' % hn) - hlist.append(h) - except Exception as e: - raise ValueError('Unable to set required handler %r' % hn) from e - config['handlers'] = hlist + if 'handlers' in config: + hlist = [] + try: + for hn in config['handlers']: + h = self.config['handlers'][hn] + if not isinstance(h, logging.Handler): + config.update(config_copy) # restore for deferred cfg + raise TypeError('Required handler %r ' + 'is not configured yet' % hn) + hlist.append(h) + except Exception as e: + raise ValueError('Unable to set required handler %r' % hn) from e + config['handlers'] = hlist elif issubclass(klass, logging.handlers.SMTPHandler) and\ 'mailhost' in config: config['mailhost'] = self.as_tuple(config['mailhost']) @@ -841,8 +837,7 @@ def configure_handler(self, config): factory = functools.partial(self._configure_queue_handler, klass) else: factory = klass - props = config.pop('.', None) - kwargs = {k: config[k] for k in config if valid_ident(k)} + kwargs = {k: config[k] for k in config if (k != '.' and valid_ident(k))} try: result = factory(**kwargs) except TypeError as te: @@ -860,6 +855,7 @@ def configure_handler(self, config): result.setLevel(logging._checkLevel(level)) if filters: self.add_filters(result, filters) + props = config.pop('.', None) if props: for name, value in props.items(): setattr(result, name, value) @@ -988,9 +984,8 @@ class ConfigSocketReceiver(ThreadingTCPServer): def __init__(self, host='localhost', port=DEFAULT_LOGGING_CONFIG_PORT, handler=None, ready=None, verify=None): ThreadingTCPServer.__init__(self, (host, port), handler) - logging._acquireLock() - self.abort = 0 - logging._releaseLock() + with logging._lock: + self.abort = 0 self.timeout = 1 self.ready = ready self.verify = verify @@ -1004,9 +999,8 @@ def serve_until_stopped(self): self.timeout) if rd: self.handle_request() - logging._acquireLock() - abort = self.abort - logging._releaseLock() + with logging._lock: + abort = self.abort self.server_close() class Server(threading.Thread): @@ -1027,9 +1021,8 @@ def run(self): self.port = server.server_address[1] self.ready.set() global _listener - logging._acquireLock() - _listener = server - logging._releaseLock() + with logging._lock: + _listener = server server.serve_until_stopped() return Server(ConfigSocketReceiver, ConfigStreamHandler, port, verify) @@ -1039,10 +1032,7 @@ def stopListening(): Stop the listening server which was created with a call to listen(). """ global _listener - logging._acquireLock() - try: + with logging._lock: if _listener: _listener.abort = 1 _listener = None - finally: - logging._releaseLock() diff --git a/Lib/logging/handlers.py b/Lib/logging/handlers.py index 671cc9596b02dd..9840b7b0aeba88 100644 --- a/Lib/logging/handlers.py +++ b/Lib/logging/handlers.py @@ -683,15 +683,12 @@ def close(self): """ Closes the socket. """ - self.acquire() - try: + with self.lock: sock = self.sock if sock: self.sock = None sock.close() logging.Handler.close(self) - finally: - self.release() class DatagramHandler(SocketHandler): """ @@ -833,10 +830,8 @@ class SysLogHandler(logging.Handler): "local7": LOG_LOCAL7, } - #The map below appears to be trivially lowercasing the key. However, - #there's more to it than meets the eye - in some locales, lowercasing - #gives unexpected results. See SF #1524081: in the Turkish locale, - #"INFO".lower() != "info" + # Originally added to work around GH-43683. Unnecessary since GH-50043 but kept + # for backwards compatibility. priority_map = { "DEBUG" : "debug", "INFO" : "info", @@ -953,15 +948,12 @@ def close(self): """ Closes the socket. """ - self.acquire() - try: + with self.lock: sock = self.socket if sock: self.socket = None sock.close() logging.Handler.close(self) - finally: - self.release() def mapPriority(self, levelName): """ @@ -1333,11 +1325,8 @@ def flush(self): This version just zaps the buffer to empty. """ - self.acquire() - try: + with self.lock: self.buffer.clear() - finally: - self.release() def close(self): """ @@ -1387,11 +1376,8 @@ def setTarget(self, target): """ Set the target handler for this handler. """ - self.acquire() - try: + with self.lock: self.target = target - finally: - self.release() def flush(self): """ @@ -1401,14 +1387,11 @@ def flush(self): The record buffer is only cleared if a target has been set. """ - self.acquire() - try: + with self.lock: if self.target: for record in self.buffer: self.target.handle(record) self.buffer.clear() - finally: - self.release() def close(self): """ @@ -1419,12 +1402,9 @@ def close(self): if self.flushOnClose: self.flush() finally: - self.acquire() - try: + with self.lock: self.target = None BufferingHandler.close(self) - finally: - self.release() class QueueHandler(logging.Handler): diff --git a/Lib/mailbox.py b/Lib/mailbox.py index 59834a2b3b5243..81ea210cf815a4 100644 --- a/Lib/mailbox.py +++ b/Lib/mailbox.py @@ -395,6 +395,56 @@ def get_file(self, key): f = open(os.path.join(self._path, self._lookup(key)), 'rb') return _ProxyFile(f) + def get_info(self, key): + """Get the keyed message's "info" as a string.""" + subpath = self._lookup(key) + if self.colon in subpath: + return subpath.split(self.colon)[-1] + return '' + + def set_info(self, key, info: str): + """Set the keyed message's "info" string.""" + if not isinstance(info, str): + raise TypeError(f'info must be a string: {type(info)}') + old_subpath = self._lookup(key) + new_subpath = old_subpath.split(self.colon)[0] + if info: + new_subpath += self.colon + info + if new_subpath == old_subpath: + return + old_path = os.path.join(self._path, old_subpath) + new_path = os.path.join(self._path, new_subpath) + os.rename(old_path, new_path) + self._toc[key] = new_subpath + + def get_flags(self, key): + """Return as a string the standard flags that are set on the keyed message.""" + info = self.get_info(key) + if info.startswith('2,'): + return info[2:] + return '' + + def set_flags(self, key, flags: str): + """Set the given flags and unset all others on the keyed message.""" + if not isinstance(flags, str): + raise TypeError(f'flags must be a string: {type(flags)}') + # TODO: check if flags are valid standard flag characters? + self.set_info(key, '2,' + ''.join(sorted(set(flags)))) + + def add_flag(self, key, flag: str): + """Set the given flag(s) without changing others on the keyed message.""" + if not isinstance(flag, str): + raise TypeError(f'flag must be a string: {type(flag)}') + # TODO: check that flag is a valid standard flag character? + self.set_flags(key, ''.join(set(self.get_flags(key)) | set(flag))) + + def remove_flag(self, key, flag: str): + """Unset the given string flag(s) without changing others on the keyed message.""" + if not isinstance(flag, str): + raise TypeError(f'flag must be a string: {type(flag)}') + if self.get_flags(key): + self.set_flags(key, ''.join(set(self.get_flags(key)) - set(flag))) + def iterkeys(self): """Return an iterator over keys.""" self._refresh() @@ -540,6 +590,8 @@ def _refresh(self): for subdir in self._toc_mtimes: path = self._paths[subdir] for entry in os.listdir(path): + if entry.startswith('.'): + continue p = os.path.join(path, entry) if os.path.isdir(p): continue @@ -1089,10 +1141,24 @@ def __len__(self): """Return a count of messages in the mailbox.""" return len(list(self.iterkeys())) + def _open_mh_sequences_file(self, text): + mode = '' if text else 'b' + kwargs = {'encoding': 'ASCII'} if text else {} + path = os.path.join(self._path, '.mh_sequences') + while True: + try: + return open(path, 'r+' + mode, **kwargs) + except FileNotFoundError: + pass + try: + return open(path, 'x+' + mode, **kwargs) + except FileExistsError: + pass + def lock(self): """Lock the mailbox.""" if not self._locked: - self._file = open(os.path.join(self._path, '.mh_sequences'), 'rb+') + self._file = self._open_mh_sequences_file(text=False) _lock_file(self._file) self._locked = True @@ -1146,7 +1212,11 @@ def remove_folder(self, folder): def get_sequences(self): """Return a name-to-key-list dictionary to define each sequence.""" results = {} - with open(os.path.join(self._path, '.mh_sequences'), 'r', encoding='ASCII') as f: + try: + f = open(os.path.join(self._path, '.mh_sequences'), 'r', encoding='ASCII') + except FileNotFoundError: + return results + with f: all_keys = set(self.keys()) for line in f: try: @@ -1169,7 +1239,7 @@ def get_sequences(self): def set_sequences(self, sequences): """Set sequences using the given name-to-key-list dictionary.""" - f = open(os.path.join(self._path, '.mh_sequences'), 'r+', encoding='ASCII') + f = self._open_mh_sequences_file(text=True) try: os.close(os.open(f.name, os.O_WRONLY | os.O_TRUNC)) for name, keys in sequences.items(): diff --git a/Lib/multiprocessing/connection.py b/Lib/multiprocessing/connection.py index 04eaea811cfbbe..dbbf106f680964 100644 --- a/Lib/multiprocessing/connection.py +++ b/Lib/multiprocessing/connection.py @@ -9,6 +9,7 @@ __all__ = [ 'Client', 'Listener', 'Pipe', 'wait' ] +import errno import io import os import sys @@ -271,12 +272,22 @@ class PipeConnection(_ConnectionBase): with FILE_FLAG_OVERLAPPED. """ _got_empty_message = False + _send_ov = None def _close(self, _CloseHandle=_winapi.CloseHandle): + ov = self._send_ov + if ov is not None: + # Interrupt WaitForMultipleObjects() in _send_bytes() + ov.cancel() _CloseHandle(self._handle) def _send_bytes(self, buf): + if self._send_ov is not None: + # A connection should only be used by a single thread + raise ValueError("concurrent send_bytes() calls " + "are not supported") ov, err = _winapi.WriteFile(self._handle, buf, overlapped=True) + self._send_ov = ov try: if err == _winapi.ERROR_IO_PENDING: waitres = _winapi.WaitForMultipleObjects( @@ -286,7 +297,13 @@ def _send_bytes(self, buf): ov.cancel() raise finally: + self._send_ov = None nwritten, err = ov.GetOverlappedResult(True) + if err == _winapi.ERROR_OPERATION_ABORTED: + # close() was called by another thread while + # WaitForMultipleObjects() was waiting for the overlapped + # operation. + raise OSError(errno.EPIPE, "handle is closed") assert err == 0 assert nwritten == len(buf) diff --git a/Lib/multiprocessing/forkserver.py b/Lib/multiprocessing/forkserver.py index 22a911a7a29cdc..4642707dae2f4e 100644 --- a/Lib/multiprocessing/forkserver.py +++ b/Lib/multiprocessing/forkserver.py @@ -61,7 +61,7 @@ def _stop_unlocked(self): def set_forkserver_preload(self, modules_names): '''Set list of module names to try to load in forkserver process.''' - if not all(type(mod) is str for mod in self._preload_modules): + if not all(type(mod) is str for mod in modules_names): raise TypeError('module_names must be a list of strings') self._preload_modules = modules_names diff --git a/Lib/multiprocessing/managers.py b/Lib/multiprocessing/managers.py index b6534939b4d98b..96cebc6eabec89 100644 --- a/Lib/multiprocessing/managers.py +++ b/Lib/multiprocessing/managers.py @@ -90,7 +90,10 @@ def dispatch(c, id, methodname, args=(), kwds={}): kind, result = c.recv() if kind == '#RETURN': return result - raise convert_to_error(kind, result) + try: + raise convert_to_error(kind, result) + finally: + del result # break reference cycle def convert_to_error(kind, result): if kind == '#ERROR': @@ -833,7 +836,10 @@ def _callmethod(self, methodname, args=(), kwds={}): conn = self._Client(token.address, authkey=self._authkey) dispatch(conn, None, 'decref', (token.id,)) return proxy - raise convert_to_error(kind, result) + try: + raise convert_to_error(kind, result) + finally: + del result # break reference cycle def _getvalue(self): ''' @@ -1159,15 +1165,19 @@ def __imul__(self, value): self._callmethod('__imul__', (value,)) return self + __class_getitem__ = classmethod(types.GenericAlias) + -DictProxy = MakeProxyType('DictProxy', ( +_BaseDictProxy = MakeProxyType('DictProxy', ( '__contains__', '__delitem__', '__getitem__', '__iter__', '__len__', '__setitem__', 'clear', 'copy', 'get', 'items', 'keys', 'pop', 'popitem', 'setdefault', 'update', 'values' )) -DictProxy._method_to_typeid_ = { +_BaseDictProxy._method_to_typeid_ = { '__iter__': 'Iterator', } +class DictProxy(_BaseDictProxy): + __class_getitem__ = classmethod(types.GenericAlias) ArrayProxy = MakeProxyType('ArrayProxy', ( diff --git a/Lib/multiprocessing/pool.py b/Lib/multiprocessing/pool.py index 4f5d88cb975cb7..f979890170b1a1 100644 --- a/Lib/multiprocessing/pool.py +++ b/Lib/multiprocessing/pool.py @@ -200,7 +200,7 @@ def __init__(self, processes=None, initializer=None, initargs=(), self._initargs = initargs if processes is None: - processes = os.cpu_count() or 1 + processes = os.process_cpu_count() or 1 if processes < 1: raise ValueError("Number of processes must be at least 1") if maxtasksperchild is not None: diff --git a/Lib/multiprocessing/popen_spawn_win32.py b/Lib/multiprocessing/popen_spawn_win32.py index 4d60ffc030bea6..49d4c7eea22411 100644 --- a/Lib/multiprocessing/popen_spawn_win32.py +++ b/Lib/multiprocessing/popen_spawn_win32.py @@ -14,6 +14,7 @@ # # +# Exit code used by Popen.terminate() TERMINATE = 0x10000 WINEXE = (sys.platform == 'win32' and getattr(sys, 'frozen', False)) WINSERVICE = sys.executable.lower().endswith("pythonservice.exe") @@ -100,18 +101,20 @@ def duplicate_for_child(self, handle): return reduction.duplicate(handle, self.sentinel) def wait(self, timeout=None): - if self.returncode is None: - if timeout is None: - msecs = _winapi.INFINITE - else: - msecs = max(0, int(timeout * 1000 + 0.5)) - - res = _winapi.WaitForSingleObject(int(self._handle), msecs) - if res == _winapi.WAIT_OBJECT_0: - code = _winapi.GetExitCodeProcess(self._handle) - if code == TERMINATE: - code = -signal.SIGTERM - self.returncode = code + if self.returncode is not None: + return self.returncode + + if timeout is None: + msecs = _winapi.INFINITE + else: + msecs = max(0, int(timeout * 1000 + 0.5)) + + res = _winapi.WaitForSingleObject(int(self._handle), msecs) + if res == _winapi.WAIT_OBJECT_0: + code = _winapi.GetExitCodeProcess(self._handle) + if code == TERMINATE: + code = -signal.SIGTERM + self.returncode = code return self.returncode @@ -119,12 +122,22 @@ def poll(self): return self.wait(timeout=0) def terminate(self): - if self.returncode is None: - try: - _winapi.TerminateProcess(int(self._handle), TERMINATE) - except OSError: - if self.wait(timeout=1.0) is None: - raise + if self.returncode is not None: + return + + try: + _winapi.TerminateProcess(int(self._handle), TERMINATE) + except PermissionError: + # ERROR_ACCESS_DENIED (winerror 5) is received when the + # process already died. + code = _winapi.GetExitCodeProcess(int(self._handle)) + if code == _winapi.STILL_ACTIVE: + raise + + # gh-113009: Don't set self.returncode. Even if GetExitCodeProcess() + # returns an exit code different than STILL_ACTIVE, the process can + # still be running. Only set self.returncode once WaitForSingleObject() + # returns WAIT_OBJECT_0 in wait(). kill = terminate diff --git a/Lib/multiprocessing/queues.py b/Lib/multiprocessing/queues.py index daf9ee94a19431..852ae87b276861 100644 --- a/Lib/multiprocessing/queues.py +++ b/Lib/multiprocessing/queues.py @@ -158,6 +158,20 @@ def cancel_join_thread(self): except AttributeError: pass + def _terminate_broken(self): + # Close a Queue on error. + + # gh-94777: Prevent queue writing to a pipe which is no longer read. + self._reader.close() + + # gh-107219: Close the connection writer which can unblock + # Queue._feed() if it was stuck in send_bytes(). + if sys.platform == 'win32': + self._writer.close() + + self.close() + self.join_thread() + def _start_thread(self): debug('Queue._start_thread()') @@ -169,13 +183,19 @@ def _start_thread(self): self._wlock, self._reader.close, self._writer.close, self._ignore_epipe, self._on_queue_feeder_error, self._sem), - name='QueueFeederThread' + name='QueueFeederThread', + daemon=True, ) - self._thread.daemon = True - debug('doing self._thread.start()') - self._thread.start() - debug('... done self._thread.start()') + try: + debug('doing self._thread.start()') + self._thread.start() + debug('... done self._thread.start()') + except: + # gh-109047: During Python finalization, creating a thread + # can fail with RuntimeError. + self._thread = None + raise if not self._joincancelled: self._jointhread = Finalize( diff --git a/Lib/multiprocessing/resource_tracker.py b/Lib/multiprocessing/resource_tracker.py index 3783c1ffc6e4a9..8e41f461cc934e 100644 --- a/Lib/multiprocessing/resource_tracker.py +++ b/Lib/multiprocessing/resource_tracker.py @@ -51,15 +51,31 @@ }) +class ReentrantCallError(RuntimeError): + pass + + class ResourceTracker(object): def __init__(self): - self._lock = threading.Lock() + self._lock = threading.RLock() self._fd = None self._pid = None + def _reentrant_call_error(self): + # gh-109629: this happens if an explicit call to the ResourceTracker + # gets interrupted by a garbage collection, invoking a finalizer (*) + # that itself calls back into ResourceTracker. + # (*) for example the SemLock finalizer + raise ReentrantCallError( + "Reentrant call into the multiprocessing resource tracker") + def _stop(self): with self._lock: + # This should not happen (_stop() isn't called by a finalizer) + # but we check for it anyway. + if self._lock._recursion_count() > 1: + return self._reentrant_call_error() if self._fd is None: # not running return @@ -81,6 +97,9 @@ def ensure_running(self): This can be run from any process. Usually a child process will use the resource created by its parent.''' with self._lock: + if self._lock._recursion_count() > 1: + # The code below is certainly not reentrant-safe, so bail out + return self._reentrant_call_error() if self._fd is not None: # resource tracker was launched before, is it still running? if self._check_alive(): @@ -159,7 +178,17 @@ def unregister(self, name, rtype): self._send('UNREGISTER', name, rtype) def _send(self, cmd, name, rtype): - self.ensure_running() + try: + self.ensure_running() + except ReentrantCallError: + # The code below might or might not work, depending on whether + # the resource tracker was already running and still alive. + # Better warn the user. + # (XXX is warnings.warn itself reentrant-safe? :-) + warnings.warn( + f"ResourceTracker called reentrantly for resource cleanup, " + f"which is unsupported. " + f"The {rtype} object {name!r} might leak.") msg = '{0}:{1}:{2}\n'.format(cmd, name, rtype).encode('ascii') if len(msg) > 512: # posix guarantees that writes to a pipe of less than PIPE_BUF @@ -176,6 +205,7 @@ def _send(self, cmd, name, rtype): unregister = _resource_tracker.unregister getfd = _resource_tracker.getfd + def main(fd): '''Run resource tracker.''' # protect the process from ^C and "killall python" etc diff --git a/Lib/multiprocessing/shared_memory.py b/Lib/multiprocessing/shared_memory.py index 9a1e5aa17b87a2..67e70fdc27cf31 100644 --- a/Lib/multiprocessing/shared_memory.py +++ b/Lib/multiprocessing/shared_memory.py @@ -71,8 +71,9 @@ class SharedMemory: _flags = os.O_RDWR _mode = 0o600 _prepend_leading_slash = True if _USE_POSIX else False + _track = True - def __init__(self, name=None, create=False, size=0): + def __init__(self, name=None, create=False, size=0, *, track=True): if not size >= 0: raise ValueError("'size' must be a positive integer") if create: @@ -82,6 +83,7 @@ def __init__(self, name=None, create=False, size=0): if name is None and not self._flags & os.O_EXCL: raise ValueError("'name' can only be None if create=True") + self._track = track if _USE_POSIX: # POSIX Shared Memory @@ -116,8 +118,8 @@ def __init__(self, name=None, create=False, size=0): except OSError: self.unlink() raise - - resource_tracker.register(self._name, "shared_memory") + if self._track: + resource_tracker.register(self._name, "shared_memory") else: @@ -236,12 +238,20 @@ def close(self): def unlink(self): """Requests that the underlying shared memory block be destroyed. - In order to ensure proper cleanup of resources, unlink should be - called once (and only once) across all processes which have access - to the shared memory block.""" + Unlink should be called once (and only once) across all handles + which have access to the shared memory block, even if these + handles belong to different processes. Closing and unlinking may + happen in any order, but trying to access data inside a shared + memory block after unlinking may result in memory errors, + depending on platform. + + This method has no effect on Windows, where the only way to + delete a shared memory block is to close all handles.""" + if _USE_POSIX and self._name: _posixshmem.shm_unlink(self._name) - resource_tracker.unregister(self._name, "shared_memory") + if self._track: + resource_tracker.unregister(self._name, "shared_memory") _encoding = "utf8" diff --git a/Lib/multiprocessing/spawn.py b/Lib/multiprocessing/spawn.py index f1af7709104714..daac1ecc34b55e 100644 --- a/Lib/multiprocessing/spawn.py +++ b/Lib/multiprocessing/spawn.py @@ -150,7 +150,11 @@ def _check_not_importing_main(): ... The "freeze_support()" line can be omitted if the program - is not going to be frozen to produce an executable.''') + is not going to be frozen to produce an executable. + + To fix this issue, refer to the "Safe importing of main module" + section in https://docs.python.org/3/library/multiprocessing.html + ''') def get_preparation_data(name): diff --git a/Lib/multiprocessing/synchronize.py b/Lib/multiprocessing/synchronize.py index 42624b543601a1..3ccbfe311c71f3 100644 --- a/Lib/multiprocessing/synchronize.py +++ b/Lib/multiprocessing/synchronize.py @@ -50,8 +50,8 @@ class SemLock(object): def __init__(self, kind, value, maxvalue, *, ctx): if ctx is None: ctx = context._default_context.get_context() - name = ctx.get_start_method() - unlink_now = sys.platform == 'win32' or name == 'fork' + self._is_fork_ctx = ctx.get_start_method() == 'fork' + unlink_now = sys.platform == 'win32' or self._is_fork_ctx for i in range(100): try: sl = self._semlock = _multiprocessing.SemLock( @@ -103,6 +103,11 @@ def __getstate__(self): if sys.platform == 'win32': h = context.get_spawning_popen().duplicate_for_child(sl.handle) else: + if self._is_fork_ctx: + raise RuntimeError('A SemLock created in a fork context is being ' + 'shared with a process in a spawn context. This is ' + 'not supported. Please use the same context to create ' + 'multiprocessing objects and Process.') h = sl.handle return (h, sl.kind, sl.maxvalue, sl.name) @@ -110,6 +115,8 @@ def __setstate__(self, state): self._semlock = _multiprocessing.SemLock._rebuild(*state) util.debug('recreated blocker with handle %r' % state[0]) self._make_methods() + # Ensure that deserialized SemLock can be serialized again (gh-108520). + self._is_fork_ctx = False @staticmethod def _make_name(): diff --git a/Lib/multiprocessing/util.py b/Lib/multiprocessing/util.py index 6ee0d33e88a060..32871850ddec8b 100644 --- a/Lib/multiprocessing/util.py +++ b/Lib/multiprocessing/util.py @@ -43,19 +43,19 @@ def sub_debug(msg, *args): if _logger: - _logger.log(SUBDEBUG, msg, *args) + _logger.log(SUBDEBUG, msg, *args, stacklevel=2) def debug(msg, *args): if _logger: - _logger.log(DEBUG, msg, *args) + _logger.log(DEBUG, msg, *args, stacklevel=2) def info(msg, *args): if _logger: - _logger.log(INFO, msg, *args) + _logger.log(INFO, msg, *args, stacklevel=2) def sub_warning(msg, *args): if _logger: - _logger.log(SUBWARNING, msg, *args) + _logger.log(SUBWARNING, msg, *args, stacklevel=2) def get_logger(): ''' @@ -64,8 +64,7 @@ def get_logger(): global _logger import logging - logging._acquireLock() - try: + with logging._lock: if not _logger: _logger = logging.getLogger(LOGGER_NAME) @@ -79,9 +78,6 @@ def get_logger(): atexit._exithandlers.remove((_exit_function, (), {})) atexit._exithandlers.append((_exit_function, (), {})) - finally: - logging._releaseLock() - return _logger def log_to_stderr(level=None): diff --git a/Lib/ntpath.py b/Lib/ntpath.py index dadcdc0c495da1..3061a4a5ef4c56 100644 --- a/Lib/ntpath.py +++ b/Lib/ntpath.py @@ -23,7 +23,6 @@ import genericpath from genericpath import * - __all__ = ["normcase","isabs","join","splitdrive","splitroot","split","splitext", "basename","dirname","commonprefix","getsize","getmtime", "getatime","getctime", "islink","exists","lexists","isdir","isfile", @@ -601,7 +600,7 @@ def abspath(path): return _abspath_fallback(path) try: - from nt import _getfinalpathname, readlink as _nt_readlink + from nt import _findfirstfile, _getfinalpathname, readlink as _nt_readlink except ImportError: # realpath is a no-op on systems without _getfinalpathname support. realpath = abspath @@ -688,10 +687,15 @@ def _getfinalpathname_nonstrict(path): except OSError: # If we fail to readlink(), let's keep traversing pass - path, name = split(path) - # TODO (bpo-38186): Request the real file name from the directory - # entry using FindFirstFileW. For now, we will return the path - # as best we have it + # If we get these errors, try to get the real name of the file without accessing it. + if ex.winerror in (1, 5, 32, 50, 87, 1920, 1921): + try: + name = _findfirstfile(path) + path, _ = split(path) + except OSError: + path, name = split(path) + else: + path, name = split(path) if path and not name: return path + tail tail = join(name, tail) if tail else name @@ -721,6 +725,14 @@ def realpath(path, *, strict=False): try: path = _getfinalpathname(path) initial_winerror = 0 + except ValueError as ex: + # gh-106242: Raised for embedded null characters + # In strict mode, we convert into an OSError. + # Non-strict mode returns the path as-is, since we've already + # made it absolute. + if strict: + raise OSError(str(ex)) from None + path = normpath(path) except OSError as ex: if strict: raise @@ -740,6 +752,10 @@ def realpath(path, *, strict=False): try: if _getfinalpathname(spath) == path: path = spath + except ValueError as ex: + # Unexpected, as an invalid path should not have gained a prefix + # at any point, but we ignore this error just in case. + pass except OSError as ex: # If the path does not exist and originally did not exist, then # strip the prefix anyway. diff --git a/Lib/opcode.py b/Lib/opcode.py index 5a9f8ddd0738db..88f4df7c0e8c38 100644 --- a/Lib/opcode.py +++ b/Lib/opcode.py @@ -5,275 +5,40 @@ """ -# Note that __all__ is further extended below -__all__ = ["cmp_op", "opname", "opmap", "stack_effect", "hascompare", - "HAVE_ARGUMENT", "EXTENDED_ARG"] +__all__ = ["cmp_op", "stack_effect", "hascompare", "opname", "opmap", + "HAVE_ARGUMENT", "EXTENDED_ARG", "hasarg", "hasconst", "hasname", + "hasjump", "hasjrel", "hasjabs", "hasfree", "haslocal", "hasexc"] import _opcode from _opcode import stack_effect -import sys -# The build uses older versions of Python which do not have _opcode_metadata -if sys.version_info[:2] >= (3, 13): - from _opcode_metadata import _specializations, _specialized_instructions - -cmp_op = ('<', '<=', '==', '!=', '>', '>=') - -opmap = {} - -def def_op(name, op): - opmap[name] = op - -# Instruction opcodes for compiled code -# Blank lines correspond to available opcodes - -def_op('CACHE', 0) -def_op('POP_TOP', 1) -def_op('PUSH_NULL', 2) -def_op('INTERPRETER_EXIT', 3) -def_op('END_FOR', 4) -def_op('END_SEND', 5) -def_op('TO_BOOL', 6) - -def_op('NOP', 9) - -def_op('UNARY_NEGATIVE', 11) -def_op('UNARY_NOT', 12) - -def_op('UNARY_INVERT', 15) -def_op('EXIT_INIT_CHECK', 16) - -# We reserve 17 as it is the initial value for the specializing counter -# This helps us catch cases where we attempt to execute a cache. -def_op('RESERVED', 17) - -def_op('MAKE_FUNCTION', 24) -def_op('BINARY_SUBSCR', 25) -def_op('BINARY_SLICE', 26) -def_op('STORE_SLICE', 27) - -def_op('GET_LEN', 30) -def_op('MATCH_MAPPING', 31) -def_op('MATCH_SEQUENCE', 32) -def_op('MATCH_KEYS', 33) - -def_op('PUSH_EXC_INFO', 35) -def_op('CHECK_EXC_MATCH', 36) -def_op('CHECK_EG_MATCH', 37) - -def_op('FORMAT_SIMPLE', 40) -def_op('FORMAT_WITH_SPEC', 41) - -def_op('WITH_EXCEPT_START', 49) -def_op('GET_AITER', 50) -def_op('GET_ANEXT', 51) -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) - -def_op('GET_ITER', 68) -def_op('GET_YIELD_FROM_ITER', 69) - -def_op('LOAD_BUILD_CLASS', 71) - -def_op('LOAD_ASSERTION_ERROR', 74) -def_op('RETURN_GENERATOR', 75) - -def_op('RETURN_VALUE', 83) - -def_op('SETUP_ANNOTATIONS', 85) - -def_op('LOAD_LOCALS', 87) - -def_op('POP_EXCEPT', 89) - -HAVE_ARGUMENT = 90 # real opcodes from here have an argument: - -def_op('STORE_NAME', 90) # Index in name list -def_op('DELETE_NAME', 91) # "" -def_op('UNPACK_SEQUENCE', 92) # Number of tuple items -def_op('FOR_ITER', 93) -def_op('UNPACK_EX', 94) -def_op('STORE_ATTR', 95) # Index in name list -def_op('DELETE_ATTR', 96) # "" -def_op('STORE_GLOBAL', 97) # "" -def_op('DELETE_GLOBAL', 98) # "" -def_op('SWAP', 99) -def_op('LOAD_CONST', 100) # Index in const list -def_op('LOAD_NAME', 101) # Index in name list -def_op('BUILD_TUPLE', 102) # Number of tuple items -def_op('BUILD_LIST', 103) # Number of list items -def_op('BUILD_SET', 104) # Number of set items -def_op('BUILD_MAP', 105) # Number of dict entries -def_op('LOAD_ATTR', 106) # Index in name list -def_op('COMPARE_OP', 107) # Comparison operator -def_op('IMPORT_NAME', 108) # Index in name list -def_op('IMPORT_FROM', 109) # Index in name list -def_op('JUMP_FORWARD', 110) # Number of words to skip - -def_op('POP_JUMP_IF_FALSE', 114) -def_op('POP_JUMP_IF_TRUE', 115) -def_op('LOAD_GLOBAL', 116) # Index in name list -def_op('IS_OP', 117) -def_op('CONTAINS_OP', 118) -def_op('RERAISE', 119) -def_op('COPY', 120) -def_op('RETURN_CONST', 121) -def_op('BINARY_OP', 122) -def_op('SEND', 123) # Number of words to skip -def_op('LOAD_FAST', 124) # Local variable number, no null check -def_op('STORE_FAST', 125) # Local variable number -def_op('DELETE_FAST', 126) # Local variable number -def_op('LOAD_FAST_CHECK', 127) # Local variable number -def_op('POP_JUMP_IF_NOT_NONE', 128) -def_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('BUILD_SLICE', 133) # Number of items -def_op('JUMP_BACKWARD_NO_INTERRUPT', 134) # Number of words to skip (backwards) -def_op('MAKE_CELL', 135) -def_op('LOAD_DEREF', 137) -def_op('STORE_DEREF', 138) -def_op('DELETE_DEREF', 139) -def_op('JUMP_BACKWARD', 140) # Number of words to skip (backwards) -def_op('LOAD_SUPER_ATTR', 141) -def_op('CALL_FUNCTION_EX', 142) # Flags -def_op('LOAD_FAST_AND_CLEAR', 143) # Local variable number -def_op('EXTENDED_ARG', 144) +from _opcode_metadata import (_specializations, _specialized_opmap, opmap, + HAVE_ARGUMENT, MIN_INSTRUMENTED_OPCODE) EXTENDED_ARG = opmap['EXTENDED_ARG'] -def_op('LIST_APPEND', 145) -def_op('SET_ADD', 146) -def_op('MAP_ADD', 147) -def_op('COPY_FREE_VARS', 149) -def_op('YIELD_VALUE', 150) -def_op('RESUME', 151) # This must be kept in sync with deepfreeze.py -def_op('MATCH_CLASS', 152) - -def_op('BUILD_CONST_KEY_MAP', 156) -def_op('BUILD_STRING', 157) -def_op('CONVERT_VALUE', 158) - -def_op('LIST_EXTEND', 162) -def_op('SET_UPDATE', 163) -def_op('DICT_MERGE', 164) -def_op('DICT_UPDATE', 165) - -def_op('LOAD_FAST_LOAD_FAST', 168) -def_op('STORE_FAST_LOAD_FAST', 169) -def_op('STORE_FAST_STORE_FAST', 170) -def_op('CALL', 171) -def_op('KW_NAMES', 172) -def_op('CALL_INTRINSIC_1', 173) -def_op('CALL_INTRINSIC_2', 174) -def_op('LOAD_FROM_DICT_OR_GLOBALS', 175) -def_op('LOAD_FROM_DICT_OR_DEREF', 176) -def_op('SET_FUNCTION_ATTRIBUTE', 177) # Attribute - -# Optimizer hook -def_op('ENTER_EXECUTOR', 230) - -# Instrumented instructions -MIN_INSTRUMENTED_OPCODE = 237 - -def_op('INSTRUMENTED_LOAD_SUPER_ATTR', 237) -def_op('INSTRUMENTED_POP_JUMP_IF_NONE', 238) -def_op('INSTRUMENTED_POP_JUMP_IF_NOT_NONE', 239) -def_op('INSTRUMENTED_RESUME', 240) -def_op('INSTRUMENTED_CALL', 241) -def_op('INSTRUMENTED_RETURN_VALUE', 242) -def_op('INSTRUMENTED_YIELD_VALUE', 243) -def_op('INSTRUMENTED_CALL_FUNCTION_EX', 244) -def_op('INSTRUMENTED_JUMP_FORWARD', 245) -def_op('INSTRUMENTED_JUMP_BACKWARD', 246) -def_op('INSTRUMENTED_RETURN_CONST', 247) -def_op('INSTRUMENTED_FOR_ITER', 248) -def_op('INSTRUMENTED_POP_JUMP_IF_FALSE', 249) -def_op('INSTRUMENTED_POP_JUMP_IF_TRUE', 250) -def_op('INSTRUMENTED_END_FOR', 251) -def_op('INSTRUMENTED_END_SEND', 252) -def_op('INSTRUMENTED_INSTRUCTION', 253) -def_op('INSTRUMENTED_LINE', 254) -# 255 is reserved - - -# Pseudo ops are above 255: - -def_op('SETUP_FINALLY', 256) -def_op('SETUP_CLEANUP', 257) -def_op('SETUP_WITH', 258) -def_op('POP_BLOCK', 259) - -def_op('JUMP', 260) -def_op('JUMP_NO_INTERRUPT', 261) - -def_op('LOAD_METHOD', 262) -def_op('LOAD_SUPER_METHOD', 263) -def_op('LOAD_ZERO_SUPER_METHOD', 264) -def_op('LOAD_ZERO_SUPER_ATTR', 265) - -def_op('STORE_FAST_MAYBE_NULL', 266) -def_op('LOAD_CLOSURE', 267) - -del def_op opname = ['<%r>' % (op,) for op in range(max(opmap.values()) + 1)] for op, i in opmap.items(): opname[i] = op -# The build uses older versions of Python which do not have _opcode.has_* functions -if sys.version_info[:2] >= (3, 13): - # These lists are documented as part of the dis module's API - hasarg = [op for op in opmap.values() if _opcode.has_arg(op)] - hasconst = [op for op in opmap.values() if _opcode.has_const(op)] - hasname = [op for op in opmap.values() if _opcode.has_name(op)] - hasjump = [op for op in opmap.values() if _opcode.has_jump(op)] - hasjrel = hasjump # for backward compatibility - hasjabs = [] - hasfree = [op for op in opmap.values() if _opcode.has_free(op)] - haslocal = [op for op in opmap.values() if _opcode.has_local(op)] - hasexc = [op for op in opmap.values() if _opcode.has_exc(op)] - - __all__.extend(["hasarg", "hasconst", "hasname", "hasjump", "hasjrel", - "hasjabs", "hasfree", "haslocal", "hasexc"]) +cmp_op = ('<', '<=', '==', '!=', '>', '>=') - _intrinsic_1_descs = _opcode.get_intrinsic1_descs() - _intrinsic_2_descs = _opcode.get_intrinsic2_descs() +# These lists are documented as part of the dis module's API +hasarg = [op for op in opmap.values() if _opcode.has_arg(op)] +hasconst = [op for op in opmap.values() if _opcode.has_const(op)] +hasname = [op for op in opmap.values() if _opcode.has_name(op)] +hasjump = [op for op in opmap.values() if _opcode.has_jump(op)] +hasjrel = hasjump # for backward compatibility +hasjabs = [] +hasfree = [op for op in opmap.values() if _opcode.has_free(op)] +haslocal = [op for op in opmap.values() if _opcode.has_local(op)] +hasexc = [op for op in opmap.values() if _opcode.has_exc(op)] -hascompare = [opmap["COMPARE_OP"]] -_nb_ops = [ - ("NB_ADD", "+"), - ("NB_AND", "&"), - ("NB_FLOOR_DIVIDE", "//"), - ("NB_LSHIFT", "<<"), - ("NB_MATRIX_MULTIPLY", "@"), - ("NB_MULTIPLY", "*"), - ("NB_REMAINDER", "%"), - ("NB_OR", "|"), - ("NB_POWER", "**"), - ("NB_RSHIFT", ">>"), - ("NB_SUBTRACT", "-"), - ("NB_TRUE_DIVIDE", "/"), - ("NB_XOR", "^"), - ("NB_INPLACE_ADD", "+="), - ("NB_INPLACE_AND", "&="), - ("NB_INPLACE_FLOOR_DIVIDE", "//="), - ("NB_INPLACE_LSHIFT", "<<="), - ("NB_INPLACE_MATRIX_MULTIPLY", "@="), - ("NB_INPLACE_MULTIPLY", "*="), - ("NB_INPLACE_REMAINDER", "%="), - ("NB_INPLACE_OR", "|="), - ("NB_INPLACE_POWER", "**="), - ("NB_INPLACE_RSHIFT", ">>="), - ("NB_INPLACE_SUBTRACT", "-="), - ("NB_INPLACE_TRUE_DIVIDE", "/="), - ("NB_INPLACE_XOR", "^="), -] +_intrinsic_1_descs = _opcode.get_intrinsic1_descs() +_intrinsic_2_descs = _opcode.get_intrinsic2_descs() +_nb_ops = _opcode.get_nb_ops() +hascompare = [opmap["COMPARE_OP"]] _cache_format = { "LOAD_GLOBAL": { @@ -328,6 +93,18 @@ def def_op(name, op): "counter": 1, "version": 2, }, + "POP_JUMP_IF_TRUE": { + "counter": 1, + }, + "POP_JUMP_IF_FALSE": { + "counter": 1, + }, + "POP_JUMP_IF_NONE": { + "counter": 1, + }, + "POP_JUMP_IF_NOT_NONE": { + "counter": 1, + }, } _inline_cache_entries = { diff --git a/Lib/os.py b/Lib/os.py index d8c9ba4b15400a..7f38e14e7bdd96 100644 --- a/Lib/os.py +++ b/Lib/os.py @@ -131,6 +131,7 @@ def _add(str, fn): _set = set() _add("HAVE_FCHDIR", "chdir") _add("HAVE_FCHMOD", "chmod") + _add("MS_WINDOWS", "chmod") _add("HAVE_FCHOWN", "chown") _add("HAVE_FDOPENDIR", "listdir") _add("HAVE_FDOPENDIR", "scandir") @@ -171,6 +172,7 @@ def _add(str, fn): _add("HAVE_FSTATAT", "stat") _add("HAVE_LCHFLAGS", "chflags") _add("HAVE_LCHMOD", "chmod") + _add("MS_WINDOWS", "chmod") if _exists("lchown"): # mac os x10.3 _add("HAVE_LCHOWN", "chown") _add("HAVE_LINKAT", "link") @@ -1136,3 +1138,17 @@ def add_dll_directory(path): cookie, nt._remove_dll_directory ) + + +if _exists('sched_getaffinity') and sys._get_cpu_count_config() < 0: + def process_cpu_count(): + """ + Get the number of CPUs of the current process. + + Return the number of logical CPUs usable by the calling thread of the + current process. Return None if indeterminable. + """ + return len(sched_getaffinity(0)) +else: + # Just an alias to cpu_count() (same docstring) + process_cpu_count = cpu_count diff --git a/Lib/pathlib.py b/Lib/pathlib.py deleted file mode 100644 index 758f70f5ba7077..00000000000000 --- a/Lib/pathlib.py +++ /dev/null @@ -1,1435 +0,0 @@ -"""Object-oriented filesystem paths. - -This module provides classes to represent abstract paths and concrete -paths with operations that have semantics appropriate for different -operating systems. -""" - -import fnmatch -import functools -import io -import ntpath -import os -import posixpath -import re -import sys -import warnings -from _collections_abc import Sequence -from errno import ENOENT, ENOTDIR, EBADF, ELOOP -from stat import S_ISDIR, S_ISLNK, S_ISREG, S_ISSOCK, S_ISBLK, S_ISCHR, S_ISFIFO -from urllib.parse import quote_from_bytes as urlquote_from_bytes - - -__all__ = [ - "UnsupportedOperation", - "PurePath", "PurePosixPath", "PureWindowsPath", - "Path", "PosixPath", "WindowsPath", - ] - -# -# Internals -# - -# Reference for Windows paths can be found at -# https://learn.microsoft.com/en-gb/windows/win32/fileio/naming-a-file . -_WIN_RESERVED_NAMES = frozenset( - {'CON', 'PRN', 'AUX', 'NUL', 'CONIN$', 'CONOUT$'} | - {f'COM{c}' for c in '123456789\xb9\xb2\xb3'} | - {f'LPT{c}' for c in '123456789\xb9\xb2\xb3'} -) - -_WINERROR_NOT_READY = 21 # drive exists but is not accessible -_WINERROR_INVALID_NAME = 123 # fix for bpo-35306 -_WINERROR_CANT_RESOLVE_FILENAME = 1921 # broken symlink pointing to itself - -# EBADF - guard against macOS `stat` throwing EBADF -_IGNORED_ERRNOS = (ENOENT, ENOTDIR, EBADF, ELOOP) - -_IGNORED_WINERRORS = ( - _WINERROR_NOT_READY, - _WINERROR_INVALID_NAME, - _WINERROR_CANT_RESOLVE_FILENAME) - -def _ignore_error(exception): - return (getattr(exception, 'errno', None) in _IGNORED_ERRNOS or - getattr(exception, 'winerror', None) in _IGNORED_WINERRORS) - - -@functools.cache -def _is_case_sensitive(pathmod): - return pathmod.normcase('Aa') == 'Aa' - -# -# Globbing helpers -# - - -# fnmatch.translate() returns a regular expression that includes a prefix and -# a suffix, which enable matching newlines and ensure the end of the string is -# matched, respectively. These features are undesirable for our implementation -# of PurePatch.match(), which represents path separators as newlines and joins -# pattern segments together. As a workaround, we define a slice object that -# can remove the prefix and suffix from any translate() result. See the -# _compile_pattern_lines() function for more details. -_FNMATCH_PREFIX, _FNMATCH_SUFFIX = fnmatch.translate('_').split('_') -_FNMATCH_SLICE = slice(len(_FNMATCH_PREFIX), -len(_FNMATCH_SUFFIX)) -_SWAP_SEP_AND_NEWLINE = { - '/': str.maketrans({'/': '\n', '\n': '/'}), - '\\': str.maketrans({'\\': '\n', '\n': '\\'}), -} - - -@functools.lru_cache(maxsize=256) -def _compile_pattern(pat, case_sensitive): - """Compile given glob pattern to a re.Pattern object (observing case - sensitivity), or None if the pattern should match everything.""" - if pat == '*': - return None - flags = re.NOFLAG if case_sensitive else re.IGNORECASE - return re.compile(fnmatch.translate(pat), flags).match - - -@functools.lru_cache() -def _compile_pattern_lines(pattern_lines, case_sensitive): - """Compile the given pattern lines to an `re.Pattern` object. - - The *pattern_lines* argument is a glob-style pattern (e.g. '**/*.py') with - its path separators and newlines swapped (e.g. '**\n*.py`). By using - newlines to separate path components, and not setting `re.DOTALL`, we - ensure that the `*` wildcard cannot match path separators. - - The returned `re.Pattern` object may have its `match()` method called to - match a complete pattern, or `search()` to match from the right. The - argument supplied to these methods must also have its path separators and - newlines swapped. - """ - - # Match the start of the path, or just after a path separator - parts = ['^'] - for part in pattern_lines.splitlines(keepends=True): - if part == '*\n': - part = r'.+\n' - elif part == '*': - part = r'.+' - elif part == '**\n': - # '**/' component: we use '[\s\S]' rather than '.' so that path - # separators (i.e. newlines) are matched. The trailing '^' ensures - # we terminate after a path separator (i.e. on a new line). - part = r'[\s\S]*^' - elif part == '**': - # '**' component. - part = r'[\s\S]*' - elif '**' in part: - raise ValueError("Invalid pattern: '**' can only be an entire path component") - else: - # Any other component: pass to fnmatch.translate(). We slice off - # the common prefix and suffix added by translate() to ensure that - # re.DOTALL is not set, and the end of the string not matched, - # respectively. With DOTALL not set, '*' wildcards will not match - # path separators, because the '.' characters in the pattern will - # not match newlines. - part = fnmatch.translate(part)[_FNMATCH_SLICE] - parts.append(part) - # Match the end of the path, always. - parts.append(r'\Z') - flags = re.MULTILINE - if not case_sensitive: - flags |= re.IGNORECASE - return re.compile(''.join(parts), flags=flags) - - -def _select_children(parent_paths, dir_only, follow_symlinks, match): - """Yield direct children of given paths, filtering by name and type.""" - if follow_symlinks is None: - follow_symlinks = True - for parent_path in parent_paths: - try: - # We must close the scandir() object before proceeding to - # avoid exhausting file descriptors when globbing deep trees. - with parent_path._scandir() as scandir_it: - entries = list(scandir_it) - except OSError: - pass - else: - for entry in entries: - if dir_only: - try: - if not entry.is_dir(follow_symlinks=follow_symlinks): - continue - except OSError: - continue - name = entry.name - if match is None or match(name): - yield parent_path._make_child_relpath(name) - - -def _select_recursive(parent_paths, dir_only, follow_symlinks): - """Yield given paths and all their subdirectories, recursively.""" - if follow_symlinks is None: - follow_symlinks = False - for parent_path in parent_paths: - paths = [parent_path] - while paths: - path = paths.pop() - yield path - try: - # We must close the scandir() object before proceeding to - # avoid exhausting file descriptors when globbing deep trees. - with path._scandir() as scandir_it: - entries = list(scandir_it) - except OSError: - pass - else: - for entry in entries: - try: - if entry.is_dir(follow_symlinks=follow_symlinks): - paths.append(path._make_child_relpath(entry.name)) - continue - except OSError: - pass - if not dir_only: - yield path._make_child_relpath(entry.name) - - -def _select_unique(paths): - """Yields the given paths, filtering out duplicates.""" - yielded = set() - try: - for path in paths: - path_str = str(path) - if path_str not in yielded: - yield path - yielded.add(path_str) - finally: - yielded.clear() - - -# -# Public API -# - -class UnsupportedOperation(NotImplementedError): - """An exception that is raised when an unsupported operation is called on - a path object. - """ - pass - - -class _PathParents(Sequence): - """This object provides sequence-like access to the logical ancestors - of a path. Don't try to construct it yourself.""" - __slots__ = ('_path', '_drv', '_root', '_tail') - - def __init__(self, path): - self._path = path - self._drv = path.drive - self._root = path.root - self._tail = path._tail - - def __len__(self): - return len(self._tail) - - def __getitem__(self, idx): - if isinstance(idx, slice): - return tuple(self[i] for i in range(*idx.indices(len(self)))) - - if idx >= len(self) or idx < -len(self): - raise IndexError(idx) - if idx < 0: - idx += len(self) - return self._path._from_parsed_parts(self._drv, self._root, - self._tail[:-idx - 1]) - - def __repr__(self): - return "<{}.parents>".format(type(self._path).__name__) - - -class PurePath: - """Base class for manipulating paths without I/O. - - PurePath represents a filesystem path and offers operations which - don't imply any actual filesystem I/O. Depending on your system, - instantiating a PurePath will return either a PurePosixPath or a - PureWindowsPath object. You can also instantiate either of these classes - directly, regardless of your system. - """ - - __slots__ = ( - # The `_raw_paths` slot stores unnormalized string paths. This is set - # in the `__init__()` method. - '_raw_paths', - - # The `_drv`, `_root` and `_tail_cached` slots store parsed and - # normalized parts of the path. They are set when any of the `drive`, - # `root` or `_tail` properties are accessed for the first time. The - # three-part division corresponds to the result of - # `os.path.splitroot()`, except that the tail is further split on path - # separators (i.e. it is a list of strings), and that the root and - # tail are normalized. - '_drv', '_root', '_tail_cached', - - # The `_str` slot stores the string representation of the path, - # computed from the drive, root and tail when `__str__()` is called - # for the first time. It's used to implement `_str_normcase` - '_str', - - # The `_str_normcase_cached` slot stores the string path with - # normalized case. It is set when the `_str_normcase` property is - # accessed for the first time. It's used to implement `__eq__()` - # `__hash__()`, and `_parts_normcase` - '_str_normcase_cached', - - # The `_parts_normcase_cached` slot stores the case-normalized - # string path after splitting on path separators. It's set when the - # `_parts_normcase` property is accessed for the first time. It's used - # to implement comparison methods like `__lt__()`. - '_parts_normcase_cached', - - # The `_lines_cached` slot stores the string path with path separators - # and newlines swapped. This is used to implement `match()`. - '_lines_cached', - - # The `_hash` slot stores the hash of the case-normalized string - # path. It's set when `__hash__()` is called for the first time. - '_hash', - ) - pathmod = os.path - - def __new__(cls, *args, **kwargs): - """Construct a PurePath from one or several strings and or existing - PurePath objects. The strings and path objects are combined so as - to yield a canonicalized path, which is incorporated into the - new PurePath object. - """ - if cls is PurePath: - cls = PureWindowsPath if os.name == 'nt' else PurePosixPath - return object.__new__(cls) - - def __reduce__(self): - # Using the parts tuple helps share interned path parts - # when pickling related paths. - return (self.__class__, self.parts) - - def __init__(self, *args): - paths = [] - for arg in args: - if isinstance(arg, PurePath): - if arg.pathmod is ntpath and self.pathmod is posixpath: - # GH-103631: Convert separators for backwards compatibility. - paths.extend(path.replace('\\', '/') for path in arg._raw_paths) - else: - paths.extend(arg._raw_paths) - else: - try: - path = os.fspath(arg) - except TypeError: - path = arg - if not isinstance(path, str): - raise TypeError( - "argument should be a str or an os.PathLike " - "object where __fspath__ returns a str, " - f"not {type(path).__name__!r}") - paths.append(path) - self._raw_paths = paths - - def with_segments(self, *pathsegments): - """Construct a new path object from any number of path-like objects. - Subclasses may override this method to customize how new path objects - are created from methods like `iterdir()`. - """ - return type(self)(*pathsegments) - - @classmethod - def _parse_path(cls, path): - if not path: - return '', '', [] - sep = cls.pathmod.sep - altsep = cls.pathmod.altsep - if altsep: - path = path.replace(altsep, sep) - drv, root, rel = cls.pathmod.splitroot(path) - if not root and drv.startswith(sep) and not drv.endswith(sep): - drv_parts = drv.split(sep) - if len(drv_parts) == 4 and drv_parts[2] not in '?.': - # e.g. //server/share - root = sep - elif len(drv_parts) == 6: - # e.g. //?/unc/server/share - root = sep - parsed = [sys.intern(str(x)) for x in rel.split(sep) if x and x != '.'] - return drv, root, parsed - - def _load_parts(self): - paths = self._raw_paths - if len(paths) == 0: - path = '' - elif len(paths) == 1: - path = paths[0] - else: - path = self.pathmod.join(*paths) - drv, root, tail = self._parse_path(path) - self._drv = drv - self._root = root - self._tail_cached = tail - - def _from_parsed_parts(self, drv, root, tail): - path_str = self._format_parsed_parts(drv, root, tail) - path = self.with_segments(path_str) - path._str = path_str or '.' - path._drv = drv - path._root = root - path._tail_cached = tail - return path - - @classmethod - def _format_parsed_parts(cls, drv, root, tail): - if drv or root: - return drv + root + cls.pathmod.sep.join(tail) - elif tail and cls.pathmod.splitdrive(tail[0])[0]: - tail = ['.'] + tail - return cls.pathmod.sep.join(tail) - - def __str__(self): - """Return the string representation of the path, suitable for - passing to system calls.""" - try: - return self._str - except AttributeError: - self._str = self._format_parsed_parts(self.drive, self.root, - self._tail) or '.' - return self._str - - def __fspath__(self): - return str(self) - - def as_posix(self): - """Return the string representation of the path with forward (/) - slashes.""" - return str(self).replace(self.pathmod.sep, '/') - - def __bytes__(self): - """Return the bytes representation of the path. This is only - recommended to use under Unix.""" - return os.fsencode(self) - - def __repr__(self): - return "{}({!r})".format(self.__class__.__name__, self.as_posix()) - - def as_uri(self): - """Return the path as a 'file' URI.""" - if not self.is_absolute(): - raise ValueError("relative path can't be expressed as a file URI") - - drive = self.drive - if len(drive) == 2 and drive[1] == ':': - # It's a path on a local drive => 'file:///c:/a/b' - prefix = 'file:///' + drive - path = self.as_posix()[2:] - elif drive: - # It's a path on a network drive => 'file://host/share/a/b' - prefix = 'file:' - path = self.as_posix() - else: - # It's a posix path => 'file:///etc/hosts' - prefix = 'file://' - path = str(self) - return prefix + urlquote_from_bytes(os.fsencode(path)) - - @property - def _str_normcase(self): - # String with normalized case, for hashing and equality checks - try: - return self._str_normcase_cached - except AttributeError: - if _is_case_sensitive(self.pathmod): - self._str_normcase_cached = str(self) - else: - self._str_normcase_cached = str(self).lower() - return self._str_normcase_cached - - @property - def _parts_normcase(self): - # Cached parts with normalized case, for comparisons. - try: - return self._parts_normcase_cached - except AttributeError: - self._parts_normcase_cached = self._str_normcase.split(self.pathmod.sep) - return self._parts_normcase_cached - - @property - def _lines(self): - # Path with separators and newlines swapped, for pattern matching. - try: - return self._lines_cached - except AttributeError: - path_str = str(self) - if path_str == '.': - self._lines_cached = '' - else: - trans = _SWAP_SEP_AND_NEWLINE[self.pathmod.sep] - self._lines_cached = path_str.translate(trans) - return self._lines_cached - - def __eq__(self, other): - if not isinstance(other, PurePath): - return NotImplemented - return self._str_normcase == other._str_normcase and self.pathmod is other.pathmod - - def __hash__(self): - try: - return self._hash - except AttributeError: - self._hash = hash(self._str_normcase) - return self._hash - - def __lt__(self, other): - if not isinstance(other, PurePath) or self.pathmod is not other.pathmod: - return NotImplemented - return self._parts_normcase < other._parts_normcase - - def __le__(self, other): - if not isinstance(other, PurePath) or self.pathmod is not other.pathmod: - return NotImplemented - return self._parts_normcase <= other._parts_normcase - - def __gt__(self, other): - if not isinstance(other, PurePath) or self.pathmod is not other.pathmod: - return NotImplemented - return self._parts_normcase > other._parts_normcase - - def __ge__(self, other): - if not isinstance(other, PurePath) or self.pathmod is not other.pathmod: - return NotImplemented - return self._parts_normcase >= other._parts_normcase - - @property - def drive(self): - """The drive prefix (letter or UNC path), if any.""" - try: - return self._drv - except AttributeError: - self._load_parts() - return self._drv - - @property - def root(self): - """The root of the path, if any.""" - try: - return self._root - except AttributeError: - self._load_parts() - return self._root - - @property - def _tail(self): - try: - return self._tail_cached - except AttributeError: - self._load_parts() - return self._tail_cached - - @property - def anchor(self): - """The concatenation of the drive and root, or ''.""" - anchor = self.drive + self.root - return anchor - - @property - def name(self): - """The final path component, if any.""" - tail = self._tail - if not tail: - return '' - return tail[-1] - - @property - def suffix(self): - """ - The final component's last suffix, if any. - - This includes the leading period. For example: '.txt' - """ - name = self.name - i = name.rfind('.') - if 0 < i < len(name) - 1: - return name[i:] - else: - return '' - - @property - def suffixes(self): - """ - A list of the final component's suffixes, if any. - - These include the leading periods. For example: ['.tar', '.gz'] - """ - name = self.name - if name.endswith('.'): - return [] - name = name.lstrip('.') - return ['.' + suffix for suffix in name.split('.')[1:]] - - @property - def stem(self): - """The final path component, minus its last suffix.""" - name = self.name - i = name.rfind('.') - if 0 < i < len(name) - 1: - return name[:i] - else: - return name - - def with_name(self, name): - """Return a new path with the file name changed.""" - if not self.name: - raise ValueError("%r has an empty name" % (self,)) - m = self.pathmod - drv, root, tail = m.splitroot(name) - if drv or root or not tail or m.sep in tail or (m.altsep and m.altsep in tail): - raise ValueError("Invalid name %r" % (name)) - return self._from_parsed_parts(self.drive, self.root, - self._tail[:-1] + [name]) - - def with_stem(self, stem): - """Return a new path with the stem changed.""" - return self.with_name(stem + self.suffix) - - def with_suffix(self, suffix): - """Return a new path with the file suffix changed. If the path - has no suffix, add given suffix. If the given suffix is an empty - string, remove the suffix from the path. - """ - m = self.pathmod - if m.sep in suffix or m.altsep and m.altsep in suffix: - raise ValueError("Invalid suffix %r" % (suffix,)) - if suffix and not suffix.startswith('.') or suffix == '.': - raise ValueError("Invalid suffix %r" % (suffix)) - name = self.name - if not name: - raise ValueError("%r has an empty name" % (self,)) - old_suffix = self.suffix - if not old_suffix: - name = name + suffix - else: - name = name[:-len(old_suffix)] + suffix - return self._from_parsed_parts(self.drive, self.root, - self._tail[:-1] + [name]) - - def relative_to(self, other, /, *_deprecated, walk_up=False): - """Return the relative path to another path identified by the passed - arguments. If the operation is not possible (because this is not - related to the other path), raise ValueError. - - The *walk_up* parameter controls whether `..` may be used to resolve - the path. - """ - if _deprecated: - msg = ("support for supplying more than one positional argument " - "to pathlib.PurePath.relative_to() is deprecated and " - "scheduled for removal in Python {remove}") - warnings._deprecated("pathlib.PurePath.relative_to(*args)", msg, - remove=(3, 14)) - other = self.with_segments(other, *_deprecated) - for step, path in enumerate([other] + list(other.parents)): - if self.is_relative_to(path): - break - elif not walk_up: - raise ValueError(f"{str(self)!r} is not in the subpath of {str(other)!r}") - elif path.name == '..': - raise ValueError(f"'..' segment in {str(other)!r} cannot be walked") - else: - raise ValueError(f"{str(self)!r} and {str(other)!r} have different anchors") - parts = ['..'] * step + self._tail[len(path._tail):] - return self.with_segments(*parts) - - def is_relative_to(self, other, /, *_deprecated): - """Return True if the path is relative to another path or False. - """ - if _deprecated: - msg = ("support for supplying more than one argument to " - "pathlib.PurePath.is_relative_to() is deprecated and " - "scheduled for removal in Python {remove}") - warnings._deprecated("pathlib.PurePath.is_relative_to(*args)", - msg, remove=(3, 14)) - other = self.with_segments(other, *_deprecated) - return other == self or other in self.parents - - @property - def parts(self): - """An object providing sequence-like access to the - components in the filesystem path.""" - if self.drive or self.root: - return (self.drive + self.root,) + tuple(self._tail) - else: - return tuple(self._tail) - - def joinpath(self, *pathsegments): - """Combine this path with one or several arguments, and return a - new path representing either a subpath (if all arguments are relative - paths) or a totally different path (if one of the arguments is - anchored). - """ - return self.with_segments(self, *pathsegments) - - def __truediv__(self, key): - try: - return self.joinpath(key) - except TypeError: - return NotImplemented - - def __rtruediv__(self, key): - try: - return self.with_segments(key, self) - except TypeError: - return NotImplemented - - @property - def parent(self): - """The logical parent of the path.""" - drv = self.drive - root = self.root - tail = self._tail - if not tail: - return self - return self._from_parsed_parts(drv, root, tail[:-1]) - - @property - def parents(self): - """A sequence of this path's logical parents.""" - # The value of this property should not be cached on the path object, - # as doing so would introduce a reference cycle. - return _PathParents(self) - - def is_absolute(self): - """True if the path is absolute (has both a root and, if applicable, - a drive).""" - if self.pathmod is ntpath: - # ntpath.isabs() is defective - see GH-44626. - return bool(self.drive and self.root) - elif self.pathmod is posixpath: - # Optimization: work with raw paths on POSIX. - for path in self._raw_paths: - if path.startswith('/'): - return True - return False - else: - return self.pathmod.isabs(str(self)) - - def is_reserved(self): - """Return True if the path contains one of the special names reserved - by the system, if any.""" - if self.pathmod is posixpath or not self._tail: - return False - - # NOTE: the rules for reserved names seem somewhat complicated - # (e.g. r"..\NUL" is reserved but not r"foo\NUL" if "foo" does not - # exist). We err on the side of caution and return True for paths - # which are not considered reserved by Windows. - if self.drive.startswith('\\\\'): - # UNC paths are never reserved. - return False - name = self._tail[-1].partition('.')[0].partition(':')[0].rstrip(' ') - return name.upper() in _WIN_RESERVED_NAMES - - def match(self, path_pattern, *, case_sensitive=None): - """ - Return True if this path matches the given pattern. - """ - if not isinstance(path_pattern, PurePath): - path_pattern = self.with_segments(path_pattern) - if case_sensitive is None: - case_sensitive = _is_case_sensitive(self.pathmod) - pattern = _compile_pattern_lines(path_pattern._lines, case_sensitive) - if path_pattern.drive or path_pattern.root: - return pattern.match(self._lines) is not None - elif path_pattern._tail: - return pattern.search(self._lines) is not None - else: - raise ValueError("empty pattern") - - -# Subclassing os.PathLike makes isinstance() checks slower, -# which in turn makes Path construction slower. Register instead! -os.PathLike.register(PurePath) - - -class PurePosixPath(PurePath): - """PurePath subclass for non-Windows systems. - - On a POSIX system, instantiating a PurePath should return this object. - However, you can also instantiate it directly on any system. - """ - pathmod = posixpath - __slots__ = () - - -class PureWindowsPath(PurePath): - """PurePath subclass for Windows systems. - - On a Windows system, instantiating a PurePath should return this object. - However, you can also instantiate it directly on any system. - """ - pathmod = ntpath - __slots__ = () - - -# Filesystem-accessing classes - - -class Path(PurePath): - """PurePath subclass that can make system calls. - - Path represents a filesystem path but unlike PurePath, also offers - methods to do system calls on path objects. Depending on your system, - instantiating a Path will return either a PosixPath or a WindowsPath - object. You can also instantiate a PosixPath or WindowsPath directly, - but cannot instantiate a WindowsPath on a POSIX system or vice versa. - """ - __slots__ = () - - def stat(self, *, follow_symlinks=True): - """ - Return the result of the stat() system call on this path, like - os.stat() does. - """ - return os.stat(self, follow_symlinks=follow_symlinks) - - def lstat(self): - """ - Like stat(), except if the path points to a symlink, the symlink's - status information is returned, rather than its target's. - """ - return self.stat(follow_symlinks=False) - - - # Convenience functions for querying the stat results - - def exists(self, *, follow_symlinks=True): - """ - Whether this path exists. - - This method normally follows symlinks; to check whether a symlink exists, - add the argument follow_symlinks=False. - """ - try: - self.stat(follow_symlinks=follow_symlinks) - except OSError as e: - if not _ignore_error(e): - raise - return False - except ValueError: - # Non-encodable path - return False - return True - - def is_dir(self, *, follow_symlinks=True): - """ - Whether this path is a directory. - """ - try: - return S_ISDIR(self.stat(follow_symlinks=follow_symlinks).st_mode) - except OSError as e: - if not _ignore_error(e): - raise - # Path doesn't exist or is a broken symlink - # (see http://web.archive.org/web/20200623061726/https://bitbucket.org/pitrou/pathlib/issues/12/ ) - return False - except ValueError: - # Non-encodable path - return False - - def is_file(self, *, follow_symlinks=True): - """ - Whether this path is a regular file (also True for symlinks pointing - to regular files). - """ - try: - return S_ISREG(self.stat(follow_symlinks=follow_symlinks).st_mode) - except OSError as e: - if not _ignore_error(e): - raise - # Path doesn't exist or is a broken symlink - # (see http://web.archive.org/web/20200623061726/https://bitbucket.org/pitrou/pathlib/issues/12/ ) - return False - except ValueError: - # Non-encodable path - return False - - def is_mount(self): - """ - Check if this path is a mount point - """ - return os.path.ismount(self) - - def is_symlink(self): - """ - Whether this path is a symbolic link. - """ - try: - return S_ISLNK(self.lstat().st_mode) - except OSError as e: - if not _ignore_error(e): - raise - # Path doesn't exist - return False - except ValueError: - # Non-encodable path - return False - - def is_junction(self): - """ - Whether this path is a junction. - """ - return os.path.isjunction(self) - - def is_block_device(self): - """ - Whether this path is a block device. - """ - try: - return S_ISBLK(self.stat().st_mode) - except OSError as e: - if not _ignore_error(e): - raise - # Path doesn't exist or is a broken symlink - # (see http://web.archive.org/web/20200623061726/https://bitbucket.org/pitrou/pathlib/issues/12/ ) - return False - except ValueError: - # Non-encodable path - return False - - def is_char_device(self): - """ - Whether this path is a character device. - """ - try: - return S_ISCHR(self.stat().st_mode) - except OSError as e: - if not _ignore_error(e): - raise - # Path doesn't exist or is a broken symlink - # (see http://web.archive.org/web/20200623061726/https://bitbucket.org/pitrou/pathlib/issues/12/ ) - return False - except ValueError: - # Non-encodable path - return False - - def is_fifo(self): - """ - Whether this path is a FIFO. - """ - try: - return S_ISFIFO(self.stat().st_mode) - except OSError as e: - if not _ignore_error(e): - raise - # Path doesn't exist or is a broken symlink - # (see http://web.archive.org/web/20200623061726/https://bitbucket.org/pitrou/pathlib/issues/12/ ) - return False - except ValueError: - # Non-encodable path - return False - - def is_socket(self): - """ - Whether this path is a socket. - """ - try: - return S_ISSOCK(self.stat().st_mode) - except OSError as e: - if not _ignore_error(e): - raise - # Path doesn't exist or is a broken symlink - # (see http://web.archive.org/web/20200623061726/https://bitbucket.org/pitrou/pathlib/issues/12/ ) - return False - except ValueError: - # Non-encodable path - return False - - def samefile(self, other_path): - """Return whether other_path is the same or not as this file - (as returned by os.path.samefile()). - """ - st = self.stat() - try: - other_st = other_path.stat() - except AttributeError: - other_st = self.with_segments(other_path).stat() - return (st.st_ino == other_st.st_ino and - st.st_dev == other_st.st_dev) - - def open(self, mode='r', buffering=-1, encoding=None, - errors=None, newline=None): - """ - Open the file pointed by this path and return a file object, as - the built-in open() function does. - """ - if "b" not in mode: - encoding = io.text_encoding(encoding) - return io.open(self, mode, buffering, encoding, errors, newline) - - def read_bytes(self): - """ - Open the file in bytes mode, read it, and close the file. - """ - with self.open(mode='rb') as f: - return f.read() - - def read_text(self, encoding=None, errors=None): - """ - Open the file in text mode, read it, and close the file. - """ - encoding = io.text_encoding(encoding) - with self.open(mode='r', encoding=encoding, errors=errors) as f: - return f.read() - - def write_bytes(self, data): - """ - Open the file in bytes mode, write to it, and close the file. - """ - # type-check for the buffer interface before truncating the file - view = memoryview(data) - with self.open(mode='wb') as f: - return f.write(view) - - def write_text(self, data, encoding=None, errors=None, newline=None): - """ - Open the file in text mode, write to it, and close the file. - """ - if not isinstance(data, str): - raise TypeError('data must be str, not %s' % - data.__class__.__name__) - encoding = io.text_encoding(encoding) - with self.open(mode='w', encoding=encoding, errors=errors, newline=newline) as f: - return f.write(data) - - def iterdir(self): - """Yield path objects of the directory contents. - - The children are yielded in arbitrary order, and the - special entries '.' and '..' are not included. - """ - for name in os.listdir(self): - yield self._make_child_relpath(name) - - def _scandir(self): - # bpo-24132: a future version of pathlib will support subclassing of - # pathlib.Path to customize how the filesystem is accessed. This - # includes scandir(), which is used to implement glob(). - return os.scandir(self) - - def _make_child_relpath(self, name): - sep = self.pathmod.sep - lines_name = name.replace('\n', sep) - lines_str = self._lines - path_str = str(self) - tail = self._tail - if tail: - path_str = f'{path_str}{sep}{name}' - lines_str = f'{lines_str}\n{lines_name}' - elif path_str != '.': - path_str = f'{path_str}{name}' - lines_str = f'{lines_str}{lines_name}' - else: - path_str = name - lines_str = lines_name - path = self.with_segments(path_str) - path._str = path_str - path._drv = self.drive - path._root = self.root - path._tail_cached = tail + [name] - path._lines_cached = lines_str - return path - - def glob(self, pattern, *, case_sensitive=None, follow_symlinks=None): - """Iterate over this subtree and yield all existing files (of any - kind, including directories) matching the given relative pattern. - """ - sys.audit("pathlib.Path.glob", self, pattern) - return self._glob(pattern, case_sensitive, follow_symlinks) - - def rglob(self, pattern, *, case_sensitive=None, follow_symlinks=None): - """Recursively yield all existing files (of any kind, including - directories) matching the given relative pattern, anywhere in - this subtree. - """ - sys.audit("pathlib.Path.rglob", self, pattern) - return self._glob(f'**/{pattern}', case_sensitive, follow_symlinks) - - def _glob(self, pattern, case_sensitive, follow_symlinks): - path_pattern = self.with_segments(pattern) - if path_pattern.drive or path_pattern.root: - raise NotImplementedError("Non-relative patterns are unsupported") - elif not path_pattern._tail: - raise ValueError("Unacceptable pattern: {!r}".format(pattern)) - - pattern_parts = list(path_pattern._tail) - if pattern[-1] in (self.pathmod.sep, self.pathmod.altsep): - # GH-65238: pathlib doesn't preserve trailing slash. Add it back. - pattern_parts.append('') - if pattern_parts[-1] == '**': - # GH-70303: '**' only matches directories. Add trailing slash. - warnings.warn( - "Pattern ending '**' will match files and directories in a " - "future Python release. Add a trailing slash to match only " - "directories and remove this warning.", - FutureWarning, 3) - pattern_parts.append('') - - if case_sensitive is None: - # TODO: evaluate case-sensitivity of each directory in _select_children(). - case_sensitive = _is_case_sensitive(self.pathmod) - - # If symlinks are handled consistently, and the pattern does not - # contain '..' components, then we can use a 'walk-and-match' strategy - # when expanding '**' wildcards. When a '**' wildcard is encountered, - # all following pattern parts are immediately consumed and used to - # build a `re.Pattern` object. This pattern is used to filter the - # recursive walk. As a result, pattern parts following a '**' wildcard - # do not perform any filesystem access, which can be much faster! - filter_paths = follow_symlinks is not None and '..' not in pattern_parts - deduplicate_paths = False - paths = iter([self] if self.is_dir() else []) - part_idx = 0 - while part_idx < len(pattern_parts): - part = pattern_parts[part_idx] - part_idx += 1 - if part == '': - # Trailing slash. - pass - elif part == '..': - paths = (path._make_child_relpath('..') for path in paths) - elif part == '**': - # Consume adjacent '**' components. - while part_idx < len(pattern_parts) and pattern_parts[part_idx] == '**': - part_idx += 1 - - if filter_paths and part_idx < len(pattern_parts) and pattern_parts[part_idx] != '': - dir_only = pattern_parts[-1] == '' - paths = _select_recursive(paths, dir_only, follow_symlinks) - - # Filter out paths that don't match pattern. - prefix_len = len(self._make_child_relpath('_')._lines) - 1 - match = _compile_pattern_lines(path_pattern._lines, case_sensitive).match - paths = (path for path in paths if match(path._lines[prefix_len:])) - return paths - - dir_only = part_idx < len(pattern_parts) - paths = _select_recursive(paths, dir_only, follow_symlinks) - if deduplicate_paths: - # De-duplicate if we've already seen a '**' component. - paths = _select_unique(paths) - deduplicate_paths = True - elif '**' in part: - raise ValueError("Invalid pattern: '**' can only be an entire path component") - else: - dir_only = part_idx < len(pattern_parts) - match = _compile_pattern(part, case_sensitive) - paths = _select_children(paths, dir_only, follow_symlinks, match) - return paths - - def walk(self, top_down=True, on_error=None, follow_symlinks=False): - """Walk the directory tree from this directory, similar to os.walk().""" - sys.audit("pathlib.Path.walk", self, on_error, follow_symlinks) - paths = [self] - - while paths: - path = paths.pop() - if isinstance(path, tuple): - yield path - continue - - # We may not have read permission for self, in which case we can't - # get a list of the files the directory contains. os.walk() - # always suppressed the exception in that instance, rather than - # blow up for a minor reason when (say) a thousand readable - # directories are still left to visit. That logic is copied here. - try: - scandir_it = path._scandir() - except OSError as error: - if on_error is not None: - on_error(error) - continue - - with scandir_it: - dirnames = [] - filenames = [] - for entry in scandir_it: - try: - is_dir = entry.is_dir(follow_symlinks=follow_symlinks) - except OSError: - # Carried over from os.path.isdir(). - is_dir = False - - if is_dir: - dirnames.append(entry.name) - else: - filenames.append(entry.name) - - if top_down: - yield path, dirnames, filenames - else: - paths.append((path, dirnames, filenames)) - - paths += [path._make_child_relpath(d) for d in reversed(dirnames)] - - def __init__(self, *args, **kwargs): - if kwargs: - msg = ("support for supplying keyword arguments to pathlib.PurePath " - "is deprecated and scheduled for removal in Python {remove}") - warnings._deprecated("pathlib.PurePath(**kwargs)", msg, remove=(3, 14)) - super().__init__(*args) - - def __new__(cls, *args, **kwargs): - if cls is Path: - cls = WindowsPath if os.name == 'nt' else PosixPath - return object.__new__(cls) - - @classmethod - def cwd(cls): - """Return a new path pointing to the current working directory.""" - # We call 'absolute()' rather than using 'os.getcwd()' directly to - # enable users to replace the implementation of 'absolute()' in a - # subclass and benefit from the new behaviour here. This works because - # os.path.abspath('.') == os.getcwd(). - return cls().absolute() - - @classmethod - def home(cls): - """Return a new path pointing to the user's home directory (as - returned by os.path.expanduser('~')). - """ - return cls("~").expanduser() - - def absolute(self): - """Return an absolute version of this path by prepending the current - working directory. No normalization or symlink resolution is performed. - - Use resolve() to get the canonical path to a file. - """ - if self.is_absolute(): - return self - elif self.drive: - # There is a CWD on each drive-letter drive. - cwd = os.path.abspath(self.drive) - else: - cwd = os.getcwd() - # Fast path for "empty" paths, e.g. Path("."), Path("") or Path(). - # We pass only one argument to with_segments() to avoid the cost - # of joining, and we exploit the fact that getcwd() returns a - # fully-normalized string by storing it in _str. This is used to - # implement Path.cwd(). - if not self.root and not self._tail: - result = self.with_segments(cwd) - result._str = cwd - return result - return self.with_segments(cwd, self) - - def resolve(self, strict=False): - """ - Make the path absolute, resolving all symlinks on the way and also - normalizing it. - """ - - def check_eloop(e): - winerror = getattr(e, 'winerror', 0) - if e.errno == ELOOP or winerror == _WINERROR_CANT_RESOLVE_FILENAME: - raise RuntimeError("Symlink loop from %r" % e.filename) - - try: - s = os.path.realpath(self, strict=strict) - except OSError as e: - check_eloop(e) - raise - p = self.with_segments(s) - - # In non-strict mode, realpath() doesn't raise on symlink loops. - # Ensure we get an exception by calling stat() - if not strict: - try: - p.stat() - except OSError as e: - check_eloop(e) - return p - - def owner(self): - """ - Return the login name of the file owner. - """ - try: - import pwd - return pwd.getpwuid(self.stat().st_uid).pw_name - except ImportError: - raise UnsupportedOperation("Path.owner() is unsupported on this system") - - def group(self): - """ - Return the group name of the file gid. - """ - - try: - import grp - return grp.getgrgid(self.stat().st_gid).gr_name - except ImportError: - raise UnsupportedOperation("Path.group() is unsupported on this system") - - def readlink(self): - """ - Return the path to which the symbolic link points. - """ - if not hasattr(os, "readlink"): - raise UnsupportedOperation("os.readlink() not available on this system") - return self.with_segments(os.readlink(self)) - - def touch(self, mode=0o666, exist_ok=True): - """ - Create this file with the given access mode, if it doesn't exist. - """ - - if exist_ok: - # First try to bump modification time - # Implementation note: GNU touch uses the UTIME_NOW option of - # the utimensat() / futimens() functions. - try: - os.utime(self, None) - except OSError: - # Avoid exception chaining - pass - else: - return - flags = os.O_CREAT | os.O_WRONLY - if not exist_ok: - flags |= os.O_EXCL - fd = os.open(self, flags, mode) - os.close(fd) - - def mkdir(self, mode=0o777, parents=False, exist_ok=False): - """ - Create a new directory at this given path. - """ - try: - os.mkdir(self, mode) - except FileNotFoundError: - if not parents or self.parent == self: - raise - self.parent.mkdir(parents=True, exist_ok=True) - self.mkdir(mode, parents=False, exist_ok=exist_ok) - except OSError: - # Cannot rely on checking for EEXIST, since the operating system - # could give priority to other errors like EACCES or EROFS - if not exist_ok or not self.is_dir(): - raise - - def chmod(self, mode, *, follow_symlinks=True): - """ - Change the permissions of the path, like os.chmod(). - """ - os.chmod(self, mode, follow_symlinks=follow_symlinks) - - def lchmod(self, mode): - """ - Like chmod(), except if the path points to a symlink, the symlink's - permissions are changed, rather than its target's. - """ - self.chmod(mode, follow_symlinks=False) - - def unlink(self, missing_ok=False): - """ - Remove this file or link. - If the path is a directory, use rmdir() instead. - """ - try: - os.unlink(self) - except FileNotFoundError: - if not missing_ok: - raise - - def rmdir(self): - """ - Remove this directory. The directory must be empty. - """ - os.rmdir(self) - - def rename(self, target): - """ - Rename this path to the target path. - - The target path may be absolute or relative. Relative paths are - interpreted relative to the current working directory, *not* the - directory of the Path object. - - Returns the new Path instance pointing to the target path. - """ - os.rename(self, target) - return self.with_segments(target) - - def replace(self, target): - """ - Rename this path to the target path, overwriting if that path exists. - - The target path may be absolute or relative. Relative paths are - interpreted relative to the current working directory, *not* the - directory of the Path object. - - Returns the new Path instance pointing to the target path. - """ - os.replace(self, target) - return self.with_segments(target) - - def symlink_to(self, target, target_is_directory=False): - """ - Make this path a symlink pointing to the target path. - Note the order of arguments (link, target) is the reverse of os.symlink. - """ - if not hasattr(os, "symlink"): - raise UnsupportedOperation("os.symlink() not available on this system") - os.symlink(target, self, target_is_directory) - - def hardlink_to(self, target): - """ - Make this path a hard link pointing to the same file as *target*. - - Note the order of arguments (self, target) is the reverse of os.link's. - """ - if not hasattr(os, "link"): - raise UnsupportedOperation("os.link() not available on this system") - os.link(target, self) - - def expanduser(self): - """ Return a new path with expanded ~ and ~user constructs - (as returned by os.path.expanduser) - """ - if (not (self.drive or self.root) and - self._tail and self._tail[0][:1] == '~'): - homedir = os.path.expanduser(self._tail[0]) - if homedir[:1] == "~": - raise RuntimeError("Could not determine home directory.") - drv, root, tail = self._parse_path(homedir) - return self._from_parsed_parts(drv, root, tail + self._tail[1:]) - - return self - - -class PosixPath(Path, PurePosixPath): - """Path subclass for non-Windows systems. - - On a POSIX system, instantiating a Path should return this object. - """ - __slots__ = () - - if os.name == 'nt': - def __new__(cls, *args, **kwargs): - raise UnsupportedOperation( - f"cannot instantiate {cls.__name__!r} on your system") - -class WindowsPath(Path, PureWindowsPath): - """Path subclass for Windows systems. - - On a Windows system, instantiating a Path should return this object. - """ - __slots__ = () - - if os.name != 'nt': - def __new__(cls, *args, **kwargs): - raise UnsupportedOperation( - f"cannot instantiate {cls.__name__!r} on your system") diff --git a/Lib/pathlib/__init__.py b/Lib/pathlib/__init__.py new file mode 100644 index 00000000000000..9d3fcd894164e5 --- /dev/null +++ b/Lib/pathlib/__init__.py @@ -0,0 +1,816 @@ +"""Object-oriented filesystem paths. + +This module provides classes to represent abstract paths and concrete +paths with operations that have semantics appropriate for different +operating systems. +""" + +import io +import ntpath +import os +import posixpath +import sys +import warnings +from itertools import chain +from _collections_abc import Sequence + +try: + import pwd +except ImportError: + pwd = None +try: + import grp +except ImportError: + grp = None + +from . import _abc + + +__all__ = [ + "UnsupportedOperation", + "PurePath", "PurePosixPath", "PureWindowsPath", + "Path", "PosixPath", "WindowsPath", + ] + + +class _PathParents(Sequence): + """This object provides sequence-like access to the logical ancestors + of a path. Don't try to construct it yourself.""" + __slots__ = ('_path', '_drv', '_root', '_tail') + + def __init__(self, path): + self._path = path + self._drv = path.drive + self._root = path.root + self._tail = path._tail + + def __len__(self): + return len(self._tail) + + def __getitem__(self, idx): + if isinstance(idx, slice): + return tuple(self[i] for i in range(*idx.indices(len(self)))) + + if idx >= len(self) or idx < -len(self): + raise IndexError(idx) + if idx < 0: + idx += len(self) + return self._path._from_parsed_parts(self._drv, self._root, + self._tail[:-idx - 1]) + + def __repr__(self): + return "<{}.parents>".format(type(self._path).__name__) + + +UnsupportedOperation = _abc.UnsupportedOperation + + +class PurePath(_abc.PurePathBase): + """Base class for manipulating paths without I/O. + + PurePath represents a filesystem path and offers operations which + don't imply any actual filesystem I/O. Depending on your system, + instantiating a PurePath will return either a PurePosixPath or a + PureWindowsPath object. You can also instantiate either of these classes + directly, regardless of your system. + """ + + __slots__ = ( + # The `_drv`, `_root` and `_tail_cached` slots store parsed and + # normalized parts of the path. They are set when any of the `drive`, + # `root` or `_tail` properties are accessed for the first time. The + # three-part division corresponds to the result of + # `os.path.splitroot()`, except that the tail is further split on path + # separators (i.e. it is a list of strings), and that the root and + # tail are normalized. + '_drv', '_root', '_tail_cached', + + # The `_str` slot stores the string representation of the path, + # computed from the drive, root and tail when `__str__()` is called + # for the first time. It's used to implement `_str_normcase` + '_str', + + # The `_str_normcase_cached` slot stores the string path with + # normalized case. It is set when the `_str_normcase` property is + # accessed for the first time. It's used to implement `__eq__()` + # `__hash__()`, and `_parts_normcase` + '_str_normcase_cached', + + # The `_parts_normcase_cached` slot stores the case-normalized + # string path after splitting on path separators. It's set when the + # `_parts_normcase` property is accessed for the first time. It's used + # to implement comparison methods like `__lt__()`. + '_parts_normcase_cached', + + # The `_hash` slot stores the hash of the case-normalized string + # path. It's set when `__hash__()` is called for the first time. + '_hash', + ) + pathmod = os.path + + def __new__(cls, *args, **kwargs): + """Construct a PurePath from one or several strings and or existing + PurePath objects. The strings and path objects are combined so as + to yield a canonicalized path, which is incorporated into the + new PurePath object. + """ + if cls is PurePath: + cls = PureWindowsPath if os.name == 'nt' else PurePosixPath + return object.__new__(cls) + + def __init__(self, *args): + paths = [] + for arg in args: + if isinstance(arg, PurePath): + if arg.pathmod is ntpath and self.pathmod is posixpath: + # GH-103631: Convert separators for backwards compatibility. + paths.extend(path.replace('\\', '/') for path in arg._raw_paths) + else: + paths.extend(arg._raw_paths) + else: + try: + path = os.fspath(arg) + except TypeError: + path = arg + if not isinstance(path, str): + raise TypeError( + "argument should be a str or an os.PathLike " + "object where __fspath__ returns a str, " + f"not {type(path).__name__!r}") + paths.append(path) + # Avoid calling super().__init__, as an optimisation + self._raw_paths = paths + + def __reduce__(self): + # Using the parts tuple helps share interned path parts + # when pickling related paths. + return (self.__class__, self.parts) + + def __repr__(self): + return "{}({!r})".format(self.__class__.__name__, self.as_posix()) + + def __fspath__(self): + return str(self) + + def __bytes__(self): + """Return the bytes representation of the path. This is only + recommended to use under Unix.""" + return os.fsencode(self) + + @property + def _str_normcase(self): + # String with normalized case, for hashing and equality checks + try: + return self._str_normcase_cached + except AttributeError: + if _abc._is_case_sensitive(self.pathmod): + self._str_normcase_cached = str(self) + else: + self._str_normcase_cached = str(self).lower() + return self._str_normcase_cached + + def __hash__(self): + try: + return self._hash + except AttributeError: + self._hash = hash(self._str_normcase) + return self._hash + + def __eq__(self, other): + if not isinstance(other, PurePath): + return NotImplemented + return self._str_normcase == other._str_normcase and self.pathmod is other.pathmod + + @property + def _parts_normcase(self): + # Cached parts with normalized case, for comparisons. + try: + return self._parts_normcase_cached + except AttributeError: + self._parts_normcase_cached = self._str_normcase.split(self.pathmod.sep) + return self._parts_normcase_cached + + def __lt__(self, other): + if not isinstance(other, PurePath) or self.pathmod is not other.pathmod: + return NotImplemented + return self._parts_normcase < other._parts_normcase + + def __le__(self, other): + if not isinstance(other, PurePath) or self.pathmod is not other.pathmod: + return NotImplemented + return self._parts_normcase <= other._parts_normcase + + def __gt__(self, other): + if not isinstance(other, PurePath) or self.pathmod is not other.pathmod: + return NotImplemented + return self._parts_normcase > other._parts_normcase + + def __ge__(self, other): + if not isinstance(other, PurePath) or self.pathmod is not other.pathmod: + return NotImplemented + return self._parts_normcase >= other._parts_normcase + + def __str__(self): + """Return the string representation of the path, suitable for + passing to system calls.""" + try: + return self._str + except AttributeError: + self._str = self._format_parsed_parts(self.drive, self.root, + self._tail) or '.' + return self._str + + @classmethod + def _format_parsed_parts(cls, drv, root, tail): + if drv or root: + return drv + root + cls.pathmod.sep.join(tail) + elif tail and cls.pathmod.splitdrive(tail[0])[0]: + tail = ['.'] + tail + return cls.pathmod.sep.join(tail) + + def _from_parsed_parts(self, drv, root, tail): + path_str = self._format_parsed_parts(drv, root, tail) + path = self.with_segments(path_str) + path._str = path_str or '.' + path._drv = drv + path._root = root + path._tail_cached = tail + return path + + @classmethod + def _parse_path(cls, path): + if not path: + return '', '', [] + sep = cls.pathmod.sep + altsep = cls.pathmod.altsep + if altsep: + path = path.replace(altsep, sep) + drv, root, rel = cls.pathmod.splitroot(path) + if not root and drv.startswith(sep) and not drv.endswith(sep): + drv_parts = drv.split(sep) + if len(drv_parts) == 4 and drv_parts[2] not in '?.': + # e.g. //server/share + root = sep + elif len(drv_parts) == 6: + # e.g. //?/unc/server/share + root = sep + parsed = [sys.intern(str(x)) for x in rel.split(sep) if x and x != '.'] + return drv, root, parsed + + def _load_parts(self): + paths = self._raw_paths + if len(paths) == 0: + path = '' + elif len(paths) == 1: + path = paths[0] + else: + path = self.pathmod.join(*paths) + self._drv, self._root, self._tail_cached = self._parse_path(path) + + @property + def drive(self): + """The drive prefix (letter or UNC path), if any.""" + try: + return self._drv + except AttributeError: + self._load_parts() + return self._drv + + @property + def root(self): + """The root of the path, if any.""" + try: + return self._root + except AttributeError: + self._load_parts() + return self._root + + @property + def _tail(self): + try: + return self._tail_cached + except AttributeError: + self._load_parts() + return self._tail_cached + + @property + def anchor(self): + """The concatenation of the drive and root, or ''.""" + return self.drive + self.root + + @property + def parts(self): + """An object providing sequence-like access to the + components in the filesystem path.""" + if self.drive or self.root: + return (self.drive + self.root,) + tuple(self._tail) + else: + return tuple(self._tail) + + @property + def parent(self): + """The logical parent of the path.""" + drv = self.drive + root = self.root + tail = self._tail + if not tail: + return self + return self._from_parsed_parts(drv, root, tail[:-1]) + + @property + def parents(self): + """A sequence of this path's logical parents.""" + # The value of this property should not be cached on the path object, + # as doing so would introduce a reference cycle. + return _PathParents(self) + + @property + def name(self): + """The final path component, if any.""" + tail = self._tail + if not tail: + return '' + return tail[-1] + + def with_name(self, name): + """Return a new path with the file name changed.""" + m = self.pathmod + if not name or m.sep in name or (m.altsep and m.altsep in name) or name == '.': + raise ValueError(f"Invalid name {name!r}") + tail = self._tail.copy() + if not tail: + raise ValueError(f"{self!r} has an empty name") + tail[-1] = name + return self._from_parsed_parts(self.drive, self.root, tail) + + def relative_to(self, other, /, *_deprecated, walk_up=False): + """Return the relative path to another path identified by the passed + arguments. If the operation is not possible (because this is not + related to the other path), raise ValueError. + + The *walk_up* parameter controls whether `..` may be used to resolve + the path. + """ + if _deprecated: + msg = ("support for supplying more than one positional argument " + "to pathlib.PurePath.relative_to() is deprecated and " + "scheduled for removal in Python 3.14") + warnings.warn(msg, DeprecationWarning, stacklevel=2) + other = self.with_segments(other, *_deprecated) + elif not isinstance(other, PurePath): + other = self.with_segments(other) + for step, path in enumerate(chain([other], other.parents)): + if path == self or path in self.parents: + break + elif not walk_up: + raise ValueError(f"{str(self)!r} is not in the subpath of {str(other)!r}") + elif path.name == '..': + raise ValueError(f"'..' segment in {str(other)!r} cannot be walked") + else: + raise ValueError(f"{str(self)!r} and {str(other)!r} have different anchors") + parts = ['..'] * step + self._tail[len(path._tail):] + return self._from_parsed_parts('', '', parts) + + def is_relative_to(self, other, /, *_deprecated): + """Return True if the path is relative to another path or False. + """ + if _deprecated: + msg = ("support for supplying more than one argument to " + "pathlib.PurePath.is_relative_to() is deprecated and " + "scheduled for removal in Python 3.14") + warnings.warn(msg, DeprecationWarning, stacklevel=2) + other = self.with_segments(other, *_deprecated) + elif not isinstance(other, PurePath): + other = self.with_segments(other) + return other == self or other in self.parents + + def as_uri(self): + """Return the path as a URI.""" + if not self.is_absolute(): + raise ValueError("relative path can't be expressed as a file URI") + + drive = self.drive + if len(drive) == 2 and drive[1] == ':': + # It's a path on a local drive => 'file:///c:/a/b' + prefix = 'file:///' + drive + path = self.as_posix()[2:] + elif drive: + # It's a path on a network drive => 'file://host/share/a/b' + prefix = 'file:' + path = self.as_posix() + else: + # It's a posix path => 'file:///etc/hosts' + prefix = 'file://' + path = str(self) + from urllib.parse import quote_from_bytes + return prefix + quote_from_bytes(os.fsencode(path)) + + +# Subclassing os.PathLike makes isinstance() checks slower, +# which in turn makes Path construction slower. Register instead! +os.PathLike.register(PurePath) + + +class PurePosixPath(PurePath): + """PurePath subclass for non-Windows systems. + + On a POSIX system, instantiating a PurePath should return this object. + However, you can also instantiate it directly on any system. + """ + pathmod = posixpath + __slots__ = () + + +class PureWindowsPath(PurePath): + """PurePath subclass for Windows systems. + + On a Windows system, instantiating a PurePath should return this object. + However, you can also instantiate it directly on any system. + """ + pathmod = ntpath + __slots__ = () + + +class Path(_abc.PathBase, PurePath): + """PurePath subclass that can make system calls. + + Path represents a filesystem path but unlike PurePath, also offers + methods to do system calls on path objects. Depending on your system, + instantiating a Path will return either a PosixPath or a WindowsPath + object. You can also instantiate a PosixPath or WindowsPath directly, + but cannot instantiate a WindowsPath on a POSIX system or vice versa. + """ + __slots__ = () + as_uri = PurePath.as_uri + + @classmethod + def _unsupported(cls, method_name): + msg = f"{cls.__name__}.{method_name}() is unsupported on this system" + raise UnsupportedOperation(msg) + + def __init__(self, *args, **kwargs): + if kwargs: + msg = ("support for supplying keyword arguments to pathlib.PurePath " + "is deprecated and scheduled for removal in Python {remove}") + warnings._deprecated("pathlib.PurePath(**kwargs)", msg, remove=(3, 14)) + super().__init__(*args) + + def __new__(cls, *args, **kwargs): + if cls is Path: + cls = WindowsPath if os.name == 'nt' else PosixPath + return object.__new__(cls) + + def stat(self, *, follow_symlinks=True): + """ + Return the result of the stat() system call on this path, like + os.stat() does. + """ + return os.stat(self, follow_symlinks=follow_symlinks) + + def is_mount(self): + """ + Check if this path is a mount point + """ + return os.path.ismount(self) + + def is_junction(self): + """ + Whether this path is a junction. + """ + return os.path.isjunction(self) + + def open(self, mode='r', buffering=-1, encoding=None, + errors=None, newline=None): + """ + Open the file pointed by this path and return a file object, as + the built-in open() function does. + """ + if "b" not in mode: + encoding = io.text_encoding(encoding) + return io.open(self, mode, buffering, encoding, errors, newline) + + def read_text(self, encoding=None, errors=None, newline=None): + """ + Open the file in text mode, read it, and close the file. + """ + # Call io.text_encoding() here to ensure any warning is raised at an + # appropriate stack level. + encoding = io.text_encoding(encoding) + return _abc.PathBase.read_text(self, encoding, errors, newline) + + def write_text(self, data, encoding=None, errors=None, newline=None): + """ + Open the file in text mode, write to it, and close the file. + """ + # Call io.text_encoding() here to ensure any warning is raised at an + # appropriate stack level. + encoding = io.text_encoding(encoding) + return _abc.PathBase.write_text(self, data, encoding, errors, newline) + + def iterdir(self): + """Yield path objects of the directory contents. + + The children are yielded in arbitrary order, and the + special entries '.' and '..' are not included. + """ + return (self._make_child_relpath(name) for name in os.listdir(self)) + + def _scandir(self): + return os.scandir(self) + + def _make_child_entry(self, entry, is_dir=False): + # Transform an entry yielded from _scandir() into a path object. + path_str = entry.name if str(self) == '.' else entry.path + path = self.with_segments(path_str) + path._str = path_str + path._drv = self.drive + path._root = self.root + path._tail_cached = self._tail + [entry.name] + return path + + def _make_child_relpath(self, name): + path_str = str(self) + tail = self._tail + if tail: + path_str = f'{path_str}{self.pathmod.sep}{name}' + elif path_str != '.': + path_str = f'{path_str}{name}' + else: + path_str = name + path = self.with_segments(path_str) + path._str = path_str + path._drv = self.drive + path._root = self.root + path._tail_cached = tail + [name] + return path + + def glob(self, pattern, *, case_sensitive=None, follow_symlinks=None): + """Iterate over this subtree and yield all existing files (of any + kind, including directories) matching the given relative pattern. + """ + sys.audit("pathlib.Path.glob", self, pattern) + if pattern.endswith('**'): + # GH-70303: '**' only matches directories. Add trailing slash. + warnings.warn( + "Pattern ending '**' will match files and directories in a " + "future Python release. Add a trailing slash to match only " + "directories and remove this warning.", + FutureWarning, 2) + pattern = f'{pattern}/' + return _abc.PathBase.glob( + self, pattern, case_sensitive=case_sensitive, follow_symlinks=follow_symlinks) + + def rglob(self, pattern, *, case_sensitive=None, follow_symlinks=None): + """Recursively yield all existing files (of any kind, including + directories) matching the given relative pattern, anywhere in + this subtree. + """ + sys.audit("pathlib.Path.rglob", self, pattern) + if pattern.endswith('**'): + # GH-70303: '**' only matches directories. Add trailing slash. + warnings.warn( + "Pattern ending '**' will match files and directories in a " + "future Python release. Add a trailing slash to match only " + "directories and remove this warning.", + FutureWarning, 2) + pattern = f'{pattern}/' + pattern = f'**/{pattern}' + return _abc.PathBase.glob( + self, pattern, case_sensitive=case_sensitive, follow_symlinks=follow_symlinks) + + def walk(self, top_down=True, on_error=None, follow_symlinks=False): + """Walk the directory tree from this directory, similar to os.walk().""" + sys.audit("pathlib.Path.walk", self, on_error, follow_symlinks) + return _abc.PathBase.walk( + self, top_down=top_down, on_error=on_error, follow_symlinks=follow_symlinks) + + def absolute(self): + """Return an absolute version of this path + No normalization or symlink resolution is performed. + + Use resolve() to resolve symlinks and remove '..' segments. + """ + if self.is_absolute(): + return self + if self.root: + drive = os.path.splitroot(os.getcwd())[0] + return self._from_parsed_parts(drive, self.root, self._tail) + if self.drive: + # There is a CWD on each drive-letter drive. + cwd = os.path.abspath(self.drive) + else: + cwd = os.getcwd() + if not self._tail: + # Fast path for "empty" paths, e.g. Path("."), Path("") or Path(). + # We pass only one argument to with_segments() to avoid the cost + # of joining, and we exploit the fact that getcwd() returns a + # fully-normalized string by storing it in _str. This is used to + # implement Path.cwd(). + result = self.with_segments(cwd) + result._str = cwd + return result + drive, root, rel = os.path.splitroot(cwd) + if not rel: + return self._from_parsed_parts(drive, root, self._tail) + tail = rel.split(self.pathmod.sep) + tail.extend(self._tail) + return self._from_parsed_parts(drive, root, tail) + + def resolve(self, strict=False): + """ + Make the path absolute, resolving all symlinks on the way and also + normalizing it. + """ + + return self.with_segments(os.path.realpath(self, strict=strict)) + + if pwd: + def owner(self, *, follow_symlinks=True): + """ + Return the login name of the file owner. + """ + uid = self.stat(follow_symlinks=follow_symlinks).st_uid + return pwd.getpwuid(uid).pw_name + + if grp: + def group(self, *, follow_symlinks=True): + """ + Return the group name of the file gid. + """ + gid = self.stat(follow_symlinks=follow_symlinks).st_gid + return grp.getgrgid(gid).gr_name + + if hasattr(os, "readlink"): + def readlink(self): + """ + Return the path to which the symbolic link points. + """ + return self.with_segments(os.readlink(self)) + + def touch(self, mode=0o666, exist_ok=True): + """ + Create this file with the given access mode, if it doesn't exist. + """ + + if exist_ok: + # First try to bump modification time + # Implementation note: GNU touch uses the UTIME_NOW option of + # the utimensat() / futimens() functions. + try: + os.utime(self, None) + except OSError: + # Avoid exception chaining + pass + else: + return + flags = os.O_CREAT | os.O_WRONLY + if not exist_ok: + flags |= os.O_EXCL + fd = os.open(self, flags, mode) + os.close(fd) + + def mkdir(self, mode=0o777, parents=False, exist_ok=False): + """ + Create a new directory at this given path. + """ + try: + os.mkdir(self, mode) + except FileNotFoundError: + if not parents or self.parent == self: + raise + self.parent.mkdir(parents=True, exist_ok=True) + self.mkdir(mode, parents=False, exist_ok=exist_ok) + except OSError: + # Cannot rely on checking for EEXIST, since the operating system + # could give priority to other errors like EACCES or EROFS + if not exist_ok or not self.is_dir(): + raise + + def chmod(self, mode, *, follow_symlinks=True): + """ + Change the permissions of the path, like os.chmod(). + """ + os.chmod(self, mode, follow_symlinks=follow_symlinks) + + def unlink(self, missing_ok=False): + """ + Remove this file or link. + If the path is a directory, use rmdir() instead. + """ + try: + os.unlink(self) + except FileNotFoundError: + if not missing_ok: + raise + + def rmdir(self): + """ + Remove this directory. The directory must be empty. + """ + os.rmdir(self) + + def rename(self, target): + """ + Rename this path to the target path. + + The target path may be absolute or relative. Relative paths are + interpreted relative to the current working directory, *not* the + directory of the Path object. + + Returns the new Path instance pointing to the target path. + """ + os.rename(self, target) + return self.with_segments(target) + + def replace(self, target): + """ + Rename this path to the target path, overwriting if that path exists. + + The target path may be absolute or relative. Relative paths are + interpreted relative to the current working directory, *not* the + directory of the Path object. + + Returns the new Path instance pointing to the target path. + """ + os.replace(self, target) + return self.with_segments(target) + + if hasattr(os, "symlink"): + def symlink_to(self, target, target_is_directory=False): + """ + Make this path a symlink pointing to the target path. + Note the order of arguments (link, target) is the reverse of os.symlink. + """ + os.symlink(target, self, target_is_directory) + + if hasattr(os, "link"): + def hardlink_to(self, target): + """ + Make this path a hard link pointing to the same file as *target*. + + Note the order of arguments (self, target) is the reverse of os.link's. + """ + os.link(target, self) + + def expanduser(self): + """ Return a new path with expanded ~ and ~user constructs + (as returned by os.path.expanduser) + """ + if (not (self.drive or self.root) and + self._tail and self._tail[0][:1] == '~'): + homedir = os.path.expanduser(self._tail[0]) + if homedir[:1] == "~": + raise RuntimeError("Could not determine home directory.") + drv, root, tail = self._parse_path(homedir) + return self._from_parsed_parts(drv, root, tail + self._tail[1:]) + + return self + + @classmethod + def from_uri(cls, uri): + """Return a new path from the given 'file' URI.""" + if not uri.startswith('file:'): + raise ValueError(f"URI does not start with 'file:': {uri!r}") + path = uri[5:] + if path[:3] == '///': + # Remove empty authority + path = path[2:] + elif path[:12] == '//localhost/': + # Remove 'localhost' authority + path = path[11:] + if path[:3] == '///' or (path[:1] == '/' and path[2:3] in ':|'): + # Remove slash before DOS device/UNC path + path = path[1:] + if path[1:2] == '|': + # Replace bar with colon in DOS drive + path = path[:1] + ':' + path[2:] + from urllib.parse import unquote_to_bytes + path = cls(os.fsdecode(unquote_to_bytes(path))) + if not path.is_absolute(): + raise ValueError(f"URI is not absolute: {uri!r}") + return path + + +class PosixPath(Path, PurePosixPath): + """Path subclass for non-Windows systems. + + On a POSIX system, instantiating a Path should return this object. + """ + __slots__ = () + + if os.name == 'nt': + def __new__(cls, *args, **kwargs): + raise UnsupportedOperation( + f"cannot instantiate {cls.__name__!r} on your system") + +class WindowsPath(Path, PureWindowsPath): + """Path subclass for Windows systems. + + On a Windows system, instantiating a Path should return this object. + """ + __slots__ = () + + if os.name != 'nt': + def __new__(cls, *args, **kwargs): + raise UnsupportedOperation( + f"cannot instantiate {cls.__name__!r} on your system") diff --git a/Lib/pathlib/_abc.py b/Lib/pathlib/_abc.py new file mode 100644 index 00000000000000..2fc087d13aee85 --- /dev/null +++ b/Lib/pathlib/_abc.py @@ -0,0 +1,1019 @@ +import functools +import ntpath +import posixpath +from errno import ENOENT, ENOTDIR, EBADF, ELOOP, EINVAL +from stat import S_ISDIR, S_ISLNK, S_ISREG, S_ISSOCK, S_ISBLK, S_ISCHR, S_ISFIFO + +# +# Internals +# + +# Reference for Windows paths can be found at +# https://learn.microsoft.com/en-gb/windows/win32/fileio/naming-a-file . +_WIN_RESERVED_NAMES = frozenset( + {'CON', 'PRN', 'AUX', 'NUL', 'CONIN$', 'CONOUT$'} | + {f'COM{c}' for c in '123456789\xb9\xb2\xb3'} | + {f'LPT{c}' for c in '123456789\xb9\xb2\xb3'} +) + +_WINERROR_NOT_READY = 21 # drive exists but is not accessible +_WINERROR_INVALID_NAME = 123 # fix for bpo-35306 +_WINERROR_CANT_RESOLVE_FILENAME = 1921 # broken symlink pointing to itself + +# EBADF - guard against macOS `stat` throwing EBADF +_IGNORED_ERRNOS = (ENOENT, ENOTDIR, EBADF, ELOOP) + +_IGNORED_WINERRORS = ( + _WINERROR_NOT_READY, + _WINERROR_INVALID_NAME, + _WINERROR_CANT_RESOLVE_FILENAME) + +def _ignore_error(exception): + return (getattr(exception, 'errno', None) in _IGNORED_ERRNOS or + getattr(exception, 'winerror', None) in _IGNORED_WINERRORS) + + +@functools.cache +def _is_case_sensitive(pathmod): + return pathmod.normcase('Aa') == 'Aa' + +# +# Globbing helpers +# + +re = glob = None + + +@functools.lru_cache(maxsize=256) +def _compile_pattern(pat, sep, case_sensitive): + """Compile given glob pattern to a re.Pattern object (observing case + sensitivity).""" + global re, glob + if re is None: + import re, glob + + flags = re.NOFLAG if case_sensitive else re.IGNORECASE + regex = glob.translate(pat, recursive=True, include_hidden=True, seps=sep) + # The string representation of an empty path is a single dot ('.'). Empty + # paths shouldn't match wildcards, so we consume it with an atomic group. + regex = r'(\.\Z)?+' + regex + return re.compile(regex, flags=flags).match + + +def _select_children(parent_paths, dir_only, follow_symlinks, match): + """Yield direct children of given paths, filtering by name and type.""" + if follow_symlinks is None: + follow_symlinks = True + for parent_path in parent_paths: + try: + # We must close the scandir() object before proceeding to + # avoid exhausting file descriptors when globbing deep trees. + with parent_path._scandir() as scandir_it: + entries = list(scandir_it) + except OSError: + pass + else: + for entry in entries: + if dir_only: + try: + if not entry.is_dir(follow_symlinks=follow_symlinks): + continue + except OSError: + continue + if match(entry.name): + yield parent_path._make_child_entry(entry, dir_only) + + +def _select_recursive(parent_paths, dir_only, follow_symlinks): + """Yield given paths and all their subdirectories, recursively.""" + if follow_symlinks is None: + follow_symlinks = False + for parent_path in parent_paths: + paths = [parent_path] + while paths: + path = paths.pop() + yield path + try: + # We must close the scandir() object before proceeding to + # avoid exhausting file descriptors when globbing deep trees. + with path._scandir() as scandir_it: + entries = list(scandir_it) + except OSError: + pass + else: + for entry in entries: + try: + if entry.is_dir(follow_symlinks=follow_symlinks): + paths.append(path._make_child_entry(entry, dir_only)) + continue + except OSError: + pass + if not dir_only: + yield path._make_child_entry(entry) + + +def _select_unique(paths): + """Yields the given paths, filtering out duplicates.""" + yielded = set() + try: + for path in paths: + path_str = str(path) + if path_str not in yielded: + yield path + yielded.add(path_str) + finally: + yielded.clear() + + +class UnsupportedOperation(NotImplementedError): + """An exception that is raised when an unsupported operation is called on + a path object. + """ + pass + + +class PurePathBase: + """Base class for pure path objects. + + This class *does not* provide several magic methods that are defined in + its subclass PurePath. They are: __fspath__, __bytes__, __reduce__, + __hash__, __eq__, __lt__, __le__, __gt__, __ge__. Its initializer and path + joining methods accept only strings, not os.PathLike objects more broadly. + """ + + __slots__ = ( + # The `_raw_paths` slot stores unnormalized string paths. This is set + # in the `__init__()` method. + '_raw_paths', + + # The '_resolving' slot stores a boolean indicating whether the path + # is being processed by `PathBase.resolve()`. This prevents duplicate + # work from occurring when `resolve()` calls `stat()` or `readlink()`. + '_resolving', + ) + pathmod = posixpath + + def __init__(self, *paths): + self._raw_paths = paths + self._resolving = False + + def with_segments(self, *pathsegments): + """Construct a new path object from any number of path-like objects. + Subclasses may override this method to customize how new path objects + are created from methods like `iterdir()`. + """ + return type(self)(*pathsegments) + + def __str__(self): + """Return the string representation of the path, suitable for + passing to system calls.""" + return self.pathmod.join(*self._raw_paths) + + def as_posix(self): + """Return the string representation of the path with forward (/) + slashes.""" + return str(self).replace(self.pathmod.sep, '/') + + @property + def drive(self): + """The drive prefix (letter or UNC path), if any.""" + return self.pathmod.splitdrive(str(self))[0] + + @property + def root(self): + """The root of the path, if any.""" + return self.pathmod.splitroot(str(self))[1] + + @property + def anchor(self): + """The concatenation of the drive and root, or ''.""" + drive, root, _ = self.pathmod.splitroot(str(self)) + return drive + root + + @property + def name(self): + """The final path component, if any.""" + return self.pathmod.basename(str(self)) + + @property + def suffix(self): + """ + The final component's last suffix, if any. + + This includes the leading period. For example: '.txt' + """ + name = self.name + i = name.rfind('.') + if 0 < i < len(name) - 1: + return name[i:] + else: + return '' + + @property + def suffixes(self): + """ + A list of the final component's suffixes, if any. + + These include the leading periods. For example: ['.tar', '.gz'] + """ + name = self.name + if name.endswith('.'): + return [] + name = name.lstrip('.') + return ['.' + suffix for suffix in name.split('.')[1:]] + + @property + def stem(self): + """The final path component, minus its last suffix.""" + name = self.name + i = name.rfind('.') + if 0 < i < len(name) - 1: + return name[:i] + else: + return name + + def with_name(self, name): + """Return a new path with the file name changed.""" + dirname = self.pathmod.dirname + if dirname(name): + raise ValueError(f"Invalid name {name!r}") + return self.with_segments(dirname(str(self)), name) + + def with_stem(self, stem): + """Return a new path with the stem changed.""" + return self.with_name(stem + self.suffix) + + def with_suffix(self, suffix): + """Return a new path with the file suffix changed. If the path + has no suffix, add given suffix. If the given suffix is an empty + string, remove the suffix from the path. + """ + if not suffix: + return self.with_name(self.stem) + elif suffix.startswith('.') and len(suffix) > 1: + return self.with_name(self.stem + suffix) + else: + raise ValueError(f"Invalid suffix {suffix!r}") + + def relative_to(self, other, *, walk_up=False): + """Return the relative path to another path identified by the passed + arguments. If the operation is not possible (because this is not + related to the other path), raise ValueError. + + The *walk_up* parameter controls whether `..` may be used to resolve + the path. + """ + if not isinstance(other, PurePathBase): + other = self.with_segments(other) + anchor0, parts0 = self._stack + anchor1, parts1 = other._stack + if anchor0 != anchor1: + raise ValueError(f"{str(self)!r} and {str(other)!r} have different anchors") + while parts0 and parts1 and parts0[-1] == parts1[-1]: + parts0.pop() + parts1.pop() + for part in parts1: + if not part or part == '.': + pass + elif not walk_up: + raise ValueError(f"{str(self)!r} is not in the subpath of {str(other)!r}") + elif part == '..': + raise ValueError(f"'..' segment in {str(other)!r} cannot be walked") + else: + parts0.append('..') + return self.with_segments('', *reversed(parts0)) + + def is_relative_to(self, other): + """Return True if the path is relative to another path or False. + """ + if not isinstance(other, PurePathBase): + other = self.with_segments(other) + anchor0, parts0 = self._stack + anchor1, parts1 = other._stack + if anchor0 != anchor1: + return False + while parts0 and parts1 and parts0[-1] == parts1[-1]: + parts0.pop() + parts1.pop() + for part in parts1: + if part and part != '.': + return False + return True + + @property + def parts(self): + """An object providing sequence-like access to the + components in the filesystem path.""" + anchor, parts = self._stack + if anchor: + parts.append(anchor) + return tuple(reversed(parts)) + + def joinpath(self, *pathsegments): + """Combine this path with one or several arguments, and return a + new path representing either a subpath (if all arguments are relative + paths) or a totally different path (if one of the arguments is + anchored). + """ + return self.with_segments(*self._raw_paths, *pathsegments) + + def __truediv__(self, key): + try: + return self.joinpath(key) + except TypeError: + return NotImplemented + + def __rtruediv__(self, key): + try: + return self.with_segments(key, *self._raw_paths) + except TypeError: + return NotImplemented + + @property + def _stack(self): + """ + Split the path into a 2-tuple (anchor, parts), where *anchor* is the + uppermost parent of the path (equivalent to path.parents[-1]), and + *parts* is a reversed list of parts following the anchor. + """ + split = self.pathmod.split + path = str(self) + parent, name = split(path) + names = [] + while path != parent: + names.append(name) + path = parent + parent, name = split(path) + return path, names + + @property + def parent(self): + """The logical parent of the path.""" + path = str(self) + parent = self.pathmod.dirname(path) + if path != parent: + parent = self.with_segments(parent) + parent._resolving = self._resolving + return parent + return self + + @property + def parents(self): + """A sequence of this path's logical parents.""" + dirname = self.pathmod.dirname + path = str(self) + parent = dirname(path) + parents = [] + while path != parent: + parents.append(self.with_segments(parent)) + path = parent + parent = dirname(path) + return tuple(parents) + + def is_absolute(self): + """True if the path is absolute (has both a root and, if applicable, + a drive).""" + if self.pathmod is ntpath: + # ntpath.isabs() is defective - see GH-44626. + return bool(self.drive and self.root) + elif self.pathmod is posixpath: + # Optimization: work with raw paths on POSIX. + for path in self._raw_paths: + if path.startswith('/'): + return True + return False + else: + return self.pathmod.isabs(str(self)) + + def is_reserved(self): + """Return True if the path contains one of the special names reserved + by the system, if any.""" + if self.pathmod is posixpath or not self.name: + return False + + # NOTE: the rules for reserved names seem somewhat complicated + # (e.g. r"..\NUL" is reserved but not r"foo\NUL" if "foo" does not + # exist). We err on the side of caution and return True for paths + # which are not considered reserved by Windows. + if self.drive.startswith('\\\\'): + # UNC paths are never reserved. + return False + name = self.name.partition('.')[0].partition(':')[0].rstrip(' ') + return name.upper() in _WIN_RESERVED_NAMES + + def match(self, path_pattern, *, case_sensitive=None): + """ + Return True if this path matches the given pattern. + """ + if not isinstance(path_pattern, PurePathBase): + path_pattern = self.with_segments(path_pattern) + if case_sensitive is None: + case_sensitive = _is_case_sensitive(self.pathmod) + sep = path_pattern.pathmod.sep + pattern_str = str(path_pattern) + if path_pattern.anchor: + pass + elif path_pattern.parts: + pattern_str = f'**{sep}{pattern_str}' + else: + raise ValueError("empty pattern") + match = _compile_pattern(pattern_str, sep, case_sensitive) + return match(str(self)) is not None + + + +class PathBase(PurePathBase): + """Base class for concrete path objects. + + This class provides dummy implementations for many methods that derived + classes can override selectively; the default implementations raise + UnsupportedOperation. The most basic methods, such as stat() and open(), + directly raise UnsupportedOperation; these basic methods are called by + other methods such as is_dir() and read_text(). + + The Path class derives this class to implement local filesystem paths. + Users may derive their own classes to implement virtual filesystem paths, + such as paths in archive files or on remote storage systems. + """ + __slots__ = () + + # Maximum number of symlinks to follow in resolve() + _max_symlinks = 40 + + @classmethod + def _unsupported(cls, method_name): + msg = f"{cls.__name__}.{method_name}() is unsupported" + raise UnsupportedOperation(msg) + + def stat(self, *, follow_symlinks=True): + """ + Return the result of the stat() system call on this path, like + os.stat() does. + """ + self._unsupported("stat") + + def lstat(self): + """ + Like stat(), except if the path points to a symlink, the symlink's + status information is returned, rather than its target's. + """ + return self.stat(follow_symlinks=False) + + + # Convenience functions for querying the stat results + + def exists(self, *, follow_symlinks=True): + """ + Whether this path exists. + + This method normally follows symlinks; to check whether a symlink exists, + add the argument follow_symlinks=False. + """ + try: + self.stat(follow_symlinks=follow_symlinks) + except OSError as e: + if not _ignore_error(e): + raise + return False + except ValueError: + # Non-encodable path + return False + return True + + def is_dir(self, *, follow_symlinks=True): + """ + Whether this path is a directory. + """ + try: + return S_ISDIR(self.stat(follow_symlinks=follow_symlinks).st_mode) + except OSError as e: + if not _ignore_error(e): + raise + # Path doesn't exist or is a broken symlink + # (see http://web.archive.org/web/20200623061726/https://bitbucket.org/pitrou/pathlib/issues/12/ ) + return False + except ValueError: + # Non-encodable path + return False + + def is_file(self, *, follow_symlinks=True): + """ + Whether this path is a regular file (also True for symlinks pointing + to regular files). + """ + try: + return S_ISREG(self.stat(follow_symlinks=follow_symlinks).st_mode) + except OSError as e: + if not _ignore_error(e): + raise + # Path doesn't exist or is a broken symlink + # (see http://web.archive.org/web/20200623061726/https://bitbucket.org/pitrou/pathlib/issues/12/ ) + return False + except ValueError: + # Non-encodable path + return False + + def is_mount(self): + """ + Check if this path is a mount point + """ + # Need to exist and be a dir + if not self.exists() or not self.is_dir(): + return False + + try: + parent_dev = self.parent.stat().st_dev + except OSError: + return False + + dev = self.stat().st_dev + if dev != parent_dev: + return True + ino = self.stat().st_ino + parent_ino = self.parent.stat().st_ino + return ino == parent_ino + + def is_symlink(self): + """ + Whether this path is a symbolic link. + """ + try: + return S_ISLNK(self.lstat().st_mode) + except OSError as e: + if not _ignore_error(e): + raise + # Path doesn't exist + return False + except ValueError: + # Non-encodable path + return False + + def is_junction(self): + """ + Whether this path is a junction. + """ + # Junctions are a Windows-only feature, not present in POSIX nor the + # majority of virtual filesystems. There is no cross-platform idiom + # to check for junctions (using stat().st_mode). + return False + + def is_block_device(self): + """ + Whether this path is a block device. + """ + try: + return S_ISBLK(self.stat().st_mode) + except OSError as e: + if not _ignore_error(e): + raise + # Path doesn't exist or is a broken symlink + # (see http://web.archive.org/web/20200623061726/https://bitbucket.org/pitrou/pathlib/issues/12/ ) + return False + except ValueError: + # Non-encodable path + return False + + def is_char_device(self): + """ + Whether this path is a character device. + """ + try: + return S_ISCHR(self.stat().st_mode) + except OSError as e: + if not _ignore_error(e): + raise + # Path doesn't exist or is a broken symlink + # (see http://web.archive.org/web/20200623061726/https://bitbucket.org/pitrou/pathlib/issues/12/ ) + return False + except ValueError: + # Non-encodable path + return False + + def is_fifo(self): + """ + Whether this path is a FIFO. + """ + try: + return S_ISFIFO(self.stat().st_mode) + except OSError as e: + if not _ignore_error(e): + raise + # Path doesn't exist or is a broken symlink + # (see http://web.archive.org/web/20200623061726/https://bitbucket.org/pitrou/pathlib/issues/12/ ) + return False + except ValueError: + # Non-encodable path + return False + + def is_socket(self): + """ + Whether this path is a socket. + """ + try: + return S_ISSOCK(self.stat().st_mode) + except OSError as e: + if not _ignore_error(e): + raise + # Path doesn't exist or is a broken symlink + # (see http://web.archive.org/web/20200623061726/https://bitbucket.org/pitrou/pathlib/issues/12/ ) + return False + except ValueError: + # Non-encodable path + return False + + def samefile(self, other_path): + """Return whether other_path is the same or not as this file + (as returned by os.path.samefile()). + """ + st = self.stat() + try: + other_st = other_path.stat() + except AttributeError: + other_st = self.with_segments(other_path).stat() + return (st.st_ino == other_st.st_ino and + st.st_dev == other_st.st_dev) + + def open(self, mode='r', buffering=-1, encoding=None, + errors=None, newline=None): + """ + Open the file pointed by this path and return a file object, as + the built-in open() function does. + """ + self._unsupported("open") + + def read_bytes(self): + """ + Open the file in bytes mode, read it, and close the file. + """ + with self.open(mode='rb') as f: + return f.read() + + def read_text(self, encoding=None, errors=None, newline=None): + """ + Open the file in text mode, read it, and close the file. + """ + with self.open(mode='r', encoding=encoding, errors=errors, newline=newline) as f: + return f.read() + + def write_bytes(self, data): + """ + Open the file in bytes mode, write to it, and close the file. + """ + # type-check for the buffer interface before truncating the file + view = memoryview(data) + with self.open(mode='wb') as f: + return f.write(view) + + def write_text(self, data, encoding=None, errors=None, newline=None): + """ + Open the file in text mode, write to it, and close the file. + """ + if not isinstance(data, str): + raise TypeError('data must be str, not %s' % + data.__class__.__name__) + with self.open(mode='w', encoding=encoding, errors=errors, newline=newline) as f: + return f.write(data) + + def iterdir(self): + """Yield path objects of the directory contents. + + The children are yielded in arbitrary order, and the + special entries '.' and '..' are not included. + """ + self._unsupported("iterdir") + + def _scandir(self): + # Emulate os.scandir(), which returns an object that can be used as a + # context manager. This method is called by walk() and glob(). + from contextlib import nullcontext + return nullcontext(self.iterdir()) + + def _make_child_entry(self, entry, is_dir=False): + # Transform an entry yielded from _scandir() into a path object. + if is_dir: + return entry.joinpath('') + return entry + + def _make_child_relpath(self, name): + return self.joinpath(name) + + def glob(self, pattern, *, case_sensitive=None, follow_symlinks=None): + """Iterate over this subtree and yield all existing files (of any + kind, including directories) matching the given relative pattern. + """ + path_pattern = self.with_segments(pattern) + if path_pattern.anchor: + raise NotImplementedError("Non-relative patterns are unsupported") + elif not path_pattern.parts: + raise ValueError("Unacceptable pattern: {!r}".format(pattern)) + + pattern_parts = list(path_pattern.parts) + if not self.pathmod.basename(pattern): + # GH-65238: pathlib doesn't preserve trailing slash. Add it back. + pattern_parts.append('') + + if case_sensitive is None: + # TODO: evaluate case-sensitivity of each directory in _select_children(). + case_sensitive = _is_case_sensitive(self.pathmod) + + # If symlinks are handled consistently, and the pattern does not + # contain '..' components, then we can use a 'walk-and-match' strategy + # when expanding '**' wildcards. When a '**' wildcard is encountered, + # all following pattern parts are immediately consumed and used to + # build a `re.Pattern` object. This pattern is used to filter the + # recursive walk. As a result, pattern parts following a '**' wildcard + # do not perform any filesystem access, which can be much faster! + filter_paths = follow_symlinks is not None and '..' not in pattern_parts + deduplicate_paths = False + sep = self.pathmod.sep + paths = iter([self.joinpath('')] if self.is_dir() else []) + part_idx = 0 + while part_idx < len(pattern_parts): + part = pattern_parts[part_idx] + part_idx += 1 + if part == '': + # Trailing slash. + pass + elif part == '..': + paths = (path._make_child_relpath('..') for path in paths) + elif part == '**': + # Consume adjacent '**' components. + while part_idx < len(pattern_parts) and pattern_parts[part_idx] == '**': + part_idx += 1 + + if filter_paths and part_idx < len(pattern_parts) and pattern_parts[part_idx] != '': + dir_only = pattern_parts[-1] == '' + paths = _select_recursive(paths, dir_only, follow_symlinks) + + # Filter out paths that don't match pattern. + prefix_len = len(str(self._make_child_relpath('_'))) - 1 + match = _compile_pattern(str(path_pattern), sep, case_sensitive) + paths = (path for path in paths if match(str(path), prefix_len)) + return paths + + dir_only = part_idx < len(pattern_parts) + paths = _select_recursive(paths, dir_only, follow_symlinks) + if deduplicate_paths: + # De-duplicate if we've already seen a '**' component. + paths = _select_unique(paths) + deduplicate_paths = True + elif '**' in part: + raise ValueError("Invalid pattern: '**' can only be an entire path component") + else: + dir_only = part_idx < len(pattern_parts) + match = _compile_pattern(part, sep, case_sensitive) + paths = _select_children(paths, dir_only, follow_symlinks, match) + return paths + + def rglob(self, pattern, *, case_sensitive=None, follow_symlinks=None): + """Recursively yield all existing files (of any kind, including + directories) matching the given relative pattern, anywhere in + this subtree. + """ + return self.glob( + f'**/{pattern}', case_sensitive=case_sensitive, follow_symlinks=follow_symlinks) + + def walk(self, top_down=True, on_error=None, follow_symlinks=False): + """Walk the directory tree from this directory, similar to os.walk().""" + paths = [self] + + while paths: + path = paths.pop() + if isinstance(path, tuple): + yield path + continue + + # We may not have read permission for self, in which case we can't + # get a list of the files the directory contains. os.walk() + # always suppressed the exception in that instance, rather than + # blow up for a minor reason when (say) a thousand readable + # directories are still left to visit. That logic is copied here. + try: + scandir_obj = path._scandir() + except OSError as error: + if on_error is not None: + on_error(error) + continue + + with scandir_obj as scandir_it: + dirnames = [] + filenames = [] + for entry in scandir_it: + try: + is_dir = entry.is_dir(follow_symlinks=follow_symlinks) + except OSError: + # Carried over from os.path.isdir(). + is_dir = False + + if is_dir: + dirnames.append(entry.name) + else: + filenames.append(entry.name) + + if top_down: + yield path, dirnames, filenames + else: + paths.append((path, dirnames, filenames)) + + paths += [path._make_child_relpath(d) for d in reversed(dirnames)] + + def absolute(self): + """Return an absolute version of this path + No normalization or symlink resolution is performed. + + Use resolve() to resolve symlinks and remove '..' segments. + """ + self._unsupported("absolute") + + @classmethod + def cwd(cls): + """Return a new path pointing to the current working directory.""" + # We call 'absolute()' rather than using 'os.getcwd()' directly to + # enable users to replace the implementation of 'absolute()' in a + # subclass and benefit from the new behaviour here. This works because + # os.path.abspath('.') == os.getcwd(). + return cls('').absolute() + + def expanduser(self): + """ Return a new path with expanded ~ and ~user constructs + (as returned by os.path.expanduser) + """ + self._unsupported("expanduser") + + @classmethod + def home(cls): + """Return a new path pointing to expanduser('~'). + """ + return cls("~").expanduser() + + def readlink(self): + """ + Return the path to which the symbolic link points. + """ + self._unsupported("readlink") + readlink._supported = False + + def resolve(self, strict=False): + """ + Make the path absolute, resolving all symlinks on the way and also + normalizing it. + """ + if self._resolving: + return self + path_root, parts = self._stack + path = self.with_segments(path_root) + try: + path = path.absolute() + except UnsupportedOperation: + path_tail = [] + else: + path_root, path_tail = path._stack + path_tail.reverse() + + # If the user has *not* overridden the `readlink()` method, then symlinks are unsupported + # and (in non-strict mode) we can improve performance by not calling `stat()`. + querying = strict or getattr(self.readlink, '_supported', True) + link_count = 0 + while parts: + part = parts.pop() + if not part or part == '.': + continue + if part == '..': + if not path_tail: + if path_root: + # Delete '..' segment immediately following root + continue + elif path_tail[-1] != '..': + # Delete '..' segment and its predecessor + path_tail.pop() + continue + path_tail.append(part) + if querying and part != '..': + path = self.with_segments(path_root + self.pathmod.sep.join(path_tail)) + path._resolving = True + try: + st = path.stat(follow_symlinks=False) + if S_ISLNK(st.st_mode): + # Like Linux and macOS, raise OSError(errno.ELOOP) if too many symlinks are + # encountered during resolution. + link_count += 1 + if link_count >= self._max_symlinks: + raise OSError(ELOOP, "Too many symbolic links in path", str(self)) + target_root, target_parts = path.readlink()._stack + # If the symlink target is absolute (like '/etc/hosts'), set the current + # path to its uppermost parent (like '/'). + if target_root: + path_root = target_root + path_tail.clear() + else: + path_tail.pop() + # Add the symlink target's reversed tail parts (like ['hosts', 'etc']) to + # the stack of unresolved path parts. + parts.extend(target_parts) + continue + elif parts and not S_ISDIR(st.st_mode): + raise NotADirectoryError(ENOTDIR, "Not a directory", str(self)) + except OSError: + if strict: + raise + else: + querying = False + return self.with_segments(path_root + self.pathmod.sep.join(path_tail)) + + def symlink_to(self, target, target_is_directory=False): + """ + Make this path a symlink pointing to the target path. + Note the order of arguments (link, target) is the reverse of os.symlink. + """ + self._unsupported("symlink_to") + + def hardlink_to(self, target): + """ + Make this path a hard link pointing to the same file as *target*. + + Note the order of arguments (self, target) is the reverse of os.link's. + """ + self._unsupported("hardlink_to") + + def touch(self, mode=0o666, exist_ok=True): + """ + Create this file with the given access mode, if it doesn't exist. + """ + self._unsupported("touch") + + def mkdir(self, mode=0o777, parents=False, exist_ok=False): + """ + Create a new directory at this given path. + """ + self._unsupported("mkdir") + + def rename(self, target): + """ + Rename this path to the target path. + + The target path may be absolute or relative. Relative paths are + interpreted relative to the current working directory, *not* the + directory of the Path object. + + Returns the new Path instance pointing to the target path. + """ + self._unsupported("rename") + + def replace(self, target): + """ + Rename this path to the target path, overwriting if that path exists. + + The target path may be absolute or relative. Relative paths are + interpreted relative to the current working directory, *not* the + directory of the Path object. + + Returns the new Path instance pointing to the target path. + """ + self._unsupported("replace") + + def chmod(self, mode, *, follow_symlinks=True): + """ + Change the permissions of the path, like os.chmod(). + """ + self._unsupported("chmod") + + def lchmod(self, mode): + """ + Like chmod(), except if the path points to a symlink, the symlink's + permissions are changed, rather than its target's. + """ + self.chmod(mode, follow_symlinks=False) + + def unlink(self, missing_ok=False): + """ + Remove this file or link. + If the path is a directory, use rmdir() instead. + """ + self._unsupported("unlink") + + def rmdir(self): + """ + Remove this directory. The directory must be empty. + """ + self._unsupported("rmdir") + + def owner(self, *, follow_symlinks=True): + """ + Return the login name of the file owner. + """ + self._unsupported("owner") + + def group(self, *, follow_symlinks=True): + """ + Return the group name of the file gid. + """ + self._unsupported("group") + + @classmethod + def from_uri(cls, uri): + """Return a new path from the given 'file' URI.""" + cls._unsupported("from_uri") + + def as_uri(self): + """Return the path as a URI.""" + self._unsupported("as_uri") diff --git a/Lib/pdb.py b/Lib/pdb.py index 3db3e6a5be1a7b..83b7fefec63636 100755 --- a/Lib/pdb.py +++ b/Lib/pdb.py @@ -85,6 +85,7 @@ import traceback import linecache +from contextlib import contextmanager from typing import Union @@ -137,9 +138,14 @@ def check(self): if not os.path.exists(self): print('Error:', self.orig, 'does not exist') sys.exit(1) + if os.path.isdir(self): + print('Error:', self.orig, 'is a directory') + sys.exit(1) - # Replace pdb's dir with script's dir in front of module search path. - sys.path[0] = os.path.dirname(self) + # If safe_path(-P) is not set, sys.path[0] is the directory + # of pdb, and we should replace it with the directory of the script + if not sys.flags.safe_path: + sys.path[0] = os.path.dirname(self) @property def filename(self): @@ -163,6 +169,9 @@ class _ModuleTarget(str): def check(self): try: self._details + except ImportError as e: + print(f"ImportError: {e}") + sys.exit(1) except Exception: traceback.print_exc() sys.exit(1) @@ -198,6 +207,15 @@ def namespace(self): ) +class _PdbInteractiveConsole(code.InteractiveConsole): + def __init__(self, ns, message): + self._message = message + super().__init__(locals=ns, local_exit=True) + + def write(self, data): + self._message(data, end='') + + # Interaction prompt line will separate file and call info from code # text using value of line_prefix string. A newline and arrow may # be to your liking. You can set it once pdb is imported using the @@ -205,10 +223,15 @@ def namespace(self): # line_prefix = ': ' # Use this to get the old situation back line_prefix = '\n-> ' # Probably a better default -class Pdb(bdb.Bdb, cmd.Cmd): + +class Pdb(bdb.Bdb, cmd.Cmd): _previous_sigint_handler = None + # Limit the maximum depth of chained exceptions, we should be handling cycles, + # but in case there are recursions, we stop at 999. + MAX_CHAINED_EXCEPTION_DEPTH = 999 + def __init__(self, completekey='tab', stdin=None, stdout=None, skip=None, nosigint=False, readrc=True): bdb.Bdb.__init__(self, skip=skip) @@ -226,11 +249,14 @@ def __init__(self, completekey='tab', stdin=None, stdout=None, skip=None, try: import readline # remove some common file name delimiters - readline.set_completer_delims(' \t\n`@#$%^&*()=+[{]}\\|;:\'",<>?') + readline.set_completer_delims(' \t\n`@#%^&*()=+[{]}\\|;:\'",<>?') except ImportError: pass self.allow_kbdint = False self.nosigint = nosigint + # Consider these characters as part of the command so when the users type + # c.a or c['a'], it won't be recognized as a c(ontinue) command + self.identchars = cmd.Cmd.identchars + '=.[](),"\'+-*/%@&|<>~^' # Read ~/.pdbrc and ./.pdbrc self.rcLines = [] @@ -256,6 +282,9 @@ def __init__(self, completekey='tab', stdin=None, stdout=None, skip=None, self.commands_bnum = None # The breakpoint number for which we are # defining a list + self._chained_exceptions = tuple() + self._chained_exception_index = 0 + def sigint_handler(self, signum, frame): if self.allow_kbdint: raise KeyboardInterrupt @@ -292,6 +321,14 @@ def setup(self, f, tb): # cache it here to ensure that modifications are not overwritten. self.curframe_locals = self.curframe.f_locals self.set_convenience_variable(self.curframe, '_frame', self.curframe) + + if self._chained_exceptions: + self.set_convenience_variable( + self.curframe, + '_exception', + self._chained_exceptions[self._chained_exception_index], + ) + return self.execRcLines() # Can be executed earlier than 'setup' if desired @@ -411,10 +448,68 @@ def preloop(self): # fields are changed to be displayed if newvalue is not oldvalue and newvalue != oldvalue: displaying[expr] = newvalue - self.message('display %s: %r [old: %r]' % - (expr, newvalue, oldvalue)) + self.message('display %s: %s [old: %s]' % + (expr, self._safe_repr(newvalue, expr), + self._safe_repr(oldvalue, expr))) + + def _get_tb_and_exceptions(self, tb_or_exc): + """ + Given a tracecack or an exception, return a tuple of chained exceptions + and current traceback to inspect. + + This will deal with selecting the right ``__cause__`` or ``__context__`` + as well as handling cycles, and return a flattened list of exceptions we + can jump to with do_exceptions. + + """ + _exceptions = [] + if isinstance(tb_or_exc, BaseException): + traceback, current = tb_or_exc.__traceback__, tb_or_exc - def interaction(self, frame, traceback): + while current is not None: + if current in _exceptions: + break + _exceptions.append(current) + if current.__cause__ is not None: + current = current.__cause__ + elif ( + current.__context__ is not None and not current.__suppress_context__ + ): + current = current.__context__ + + if len(_exceptions) >= self.MAX_CHAINED_EXCEPTION_DEPTH: + self.message( + f"More than {self.MAX_CHAINED_EXCEPTION_DEPTH}" + " chained exceptions found, not all exceptions" + "will be browsable with `exceptions`." + ) + break + else: + traceback = tb_or_exc + return tuple(reversed(_exceptions)), traceback + + @contextmanager + def _hold_exceptions(self, exceptions): + """ + Context manager to ensure proper cleaning of exceptions references + + When given a chained exception instead of a traceback, + pdb may hold references to many objects which may leak memory. + + We use this context manager to make sure everything is properly cleaned + + """ + try: + self._chained_exceptions = exceptions + self._chained_exception_index = len(exceptions) - 1 + yield + finally: + # we can't put those in forget as otherwise they would + # be cleared on exception change + self._chained_exceptions = tuple() + self._chained_exception_index = 0 + + def interaction(self, frame, tb_or_exc): # Restore the previous signal handler at the Pdb prompt. if Pdb._previous_sigint_handler: try: @@ -423,14 +518,19 @@ def interaction(self, frame, traceback): pass else: Pdb._previous_sigint_handler = None - if self.setup(frame, traceback): - # no interaction desired at this time (happens if .pdbrc contains - # a command like "continue") + + _chained_exceptions, tb = self._get_tb_and_exceptions(tb_or_exc) + if isinstance(tb_or_exc, BaseException): + assert tb is not None, "main exception must have a traceback" + with self._hold_exceptions(_chained_exceptions): + if self.setup(frame, tb): + # no interaction desired at this time (happens if .pdbrc contains + # a command like "continue") + self.forget() + return + self.print_stack_entry(self.stack[self.curindex]) + self._cmdloop() self.forget() - return - self.print_stack_entry(self.stack[self.curindex]) - self._cmdloop() - self.forget() def displayhook(self, obj): """Custom displayhook for the exec in default(), which prevents @@ -440,6 +540,22 @@ def displayhook(self, obj): if obj is not None: self.message(repr(obj)) + @contextmanager + def _disable_tab_completion(self): + if self.use_rawinput and self.completekey == 'tab': + try: + import readline + except ImportError: + yield + return + try: + readline.parse_and_bind('tab: self-insert') + yield + finally: + readline.parse_and_bind('tab: complete') + else: + yield + def default(self, line): if line[:1] == '!': line = line[1:].strip() locals = self.curframe_locals @@ -447,28 +563,29 @@ def default(self, line): try: if (code := codeop.compile_command(line + '\n', '', 'single')) is None: # Multi-line mode - buffer = line - continue_prompt = "... " - while (code := codeop.compile_command(buffer, '', 'single')) is None: - if self.use_rawinput: - try: - line = input(continue_prompt) - except (EOFError, KeyboardInterrupt): - self.lastcmd = "" - print('\n') - return - else: - self.stdout.write(continue_prompt) - self.stdout.flush() - line = self.stdin.readline() - if not len(line): - self.lastcmd = "" - self.stdout.write('\n') - self.stdout.flush() - return + with self._disable_tab_completion(): + buffer = line + continue_prompt = "... " + while (code := codeop.compile_command(buffer, '', 'single')) is None: + if self.use_rawinput: + try: + line = input(continue_prompt) + except (EOFError, KeyboardInterrupt): + self.lastcmd = "" + print('\n') + return else: - line = line.rstrip('\r\n') - buffer += '\n' + line + self.stdout.write(continue_prompt) + self.stdout.flush() + line = self.stdin.readline() + if not len(line): + self.lastcmd = "" + self.stdout.write('\n') + self.stdout.flush() + return + else: + line = line.rstrip('\r\n') + buffer += '\n' + line save_stdout = sys.stdout save_stdin = sys.stdin save_displayhook = sys.displayhook @@ -491,11 +608,20 @@ def precmd(self, line): args = line.split() while args[0] in self.aliases: line = self.aliases[args[0]] - ii = 1 - for tmpArg in args[1:]: - line = line.replace("%" + str(ii), - tmpArg) - ii += 1 + for idx in range(1, 10): + if f'%{idx}' in line: + if idx >= len(args): + self.error(f"Not enough arguments for alias '{args[0]}'") + # This is a no-op + return "!" + line = line.replace(f'%{idx}', args[idx]) + elif '%*' not in line: + if idx < len(args): + self.error(f"Too many arguments for alias '{args[0]}'") + # This is a no-op + return "!" + break + line = line.replace("%*", ' '.join(args[1:])) args = line.split() # split into ';;' separated commands @@ -510,6 +636,7 @@ def precmd(self, line): # Replace all the convenience variables line = re.sub(r'\$([a-zA-Z_][a-zA-Z0-9_]*)', r'__pdb_convenience_variables["\1"]', line) + return line def onecmd(self, line): @@ -554,8 +681,8 @@ def handle_command_def(self, line): # interface abstraction functions - def message(self, msg): - print(msg, file=self.stdout) + def message(self, msg, end='\n'): + print(msg, end=end, file=self.stdout) def error(self, msg): print('***', msg, file=self.stdout) @@ -570,6 +697,18 @@ def set_convenience_variable(self, frame, name, value): # Generic completion functions. Individual complete_foo methods can be # assigned below to one of these functions. + def completenames(self, text, line, begidx, endidx): + # Overwrite completenames() of cmd so for the command completion, + # if no current command matches, check for expressions as well + commands = super().completenames(text, line, begidx, endidx) + for alias in self.aliases: + if alias.startswith(text): + commands.append(alias) + if commands: + return commands + else: + return self._complete_expression(text, line, begidx, endidx) + def _complete_location(self, text, line, begidx, endidx): # Complete a file/module/function location for break/tbreak/clear. if line.strip().endswith((':', ',')): @@ -604,6 +743,10 @@ def _complete_expression(self, text, line, begidx, endidx): # complete builtins, and they clutter the namespace quite heavily, so we # leave them out. ns = {**self.curframe.f_globals, **self.curframe_locals} + if text.startswith("$"): + # Complete convenience variables + conv_vars = self.curframe.f_globals.get('__pdb_convenience_variables', {}) + return [f"${name}" for name in conv_vars if name.startswith(text[1:])] if '.' in text: # Walk an attribute chain up to the last part, similar to what # rlcompleter does. This will bail if any of the parts are not @@ -781,7 +924,7 @@ def do_break(self, arg, temporary = 0): #use co_name to identify the bkpt (function names #could be aliased, but co_name is invariant) funcname = code.co_name - lineno = code.co_firstlineno + lineno = self._find_first_executable_line(code) filename = code.co_filename except: # last thing to try @@ -884,6 +1027,23 @@ def checkline(self, filename, lineno): return 0 return lineno + def _find_first_executable_line(self, code): + """ Try to find the first executable line of the code object. + + Equivalently, find the line number of the instruction that's + after RESUME + + Return code.co_firstlineno if no executable line is found. + """ + prev = None + for instr in dis.get_instructions(code): + if prev is not None and prev.opname == 'RESUME': + if instr.positions.lineno is not None: + return instr.positions.lineno + return code.co_firstlineno + prev = instr + return code.co_firstlineno + def do_enable(self, arg): """enable bpnumber [bpnumber ...] @@ -1073,6 +1233,53 @@ def _select_frame(self, number): self.print_stack_entry(self.stack[self.curindex]) self.lineno = None + def do_exceptions(self, arg): + """exceptions [number] + + List or change current exception in an exception chain. + + Without arguments, list all the current exception in the exception + chain. Exceptions will be numbered, with the current exception indicated + with an arrow. + + If given an integer as argument, switch to the exception at that index. + """ + if not self._chained_exceptions: + self.message( + "Did not find chained exceptions. To move between" + " exceptions, pdb/post_mortem must be given an exception" + " object rather than a traceback." + ) + return + if not arg: + for ix, exc in enumerate(self._chained_exceptions): + prompt = ">" if ix == self._chained_exception_index else " " + rep = repr(exc) + if len(rep) > 80: + rep = rep[:77] + "..." + indicator = ( + " -" + if self._chained_exceptions[ix].__traceback__ is None + else f"{ix:>3}" + ) + self.message(f"{prompt} {indicator} {rep}") + else: + try: + number = int(arg) + except ValueError: + self.error("Argument must be an integer") + return + if 0 <= number < len(self._chained_exceptions): + if self._chained_exceptions[number].__traceback__ is None: + self.error("This exception does not have a traceback, cannot jump to it") + return + + self._chained_exception_index = number + self.setup(None, self._chained_exceptions[number].__traceback__) + self.print_stack_entry(self.stack[self.curindex]) + else: + self.error("No exception with that number") + def do_up(self, arg): """u(p) [count] @@ -1314,7 +1521,7 @@ def do_args(self, arg): for i in range(n): name = co.co_varnames[i] if name in dict: - self.message('%s = %r' % (name, dict[name])) + self.message('%s = %s' % (name, self._safe_repr(dict[name], name))) else: self.message('%s = *** undefined ***' % (name,)) do_a = do_args @@ -1328,7 +1535,7 @@ def do_retval(self, arg): self._print_invalid_arg(arg) return if '__return__' in self.curframe_locals: - self.message(repr(self.curframe_locals['__return__'])) + self.message(self._safe_repr(self.curframe_locals['__return__'], "retval")) else: self.error('Not yet returned!') do_rv = do_retval @@ -1363,6 +1570,12 @@ def _msg_val_func(self, arg, func): except: self._error_exc() + def _safe_repr(self, obj, expr): + try: + return repr(obj) + except Exception as e: + return _rstr(f"*** repr({expr}) failed: {self._format_exc(e)} ***") + def do_p(self, arg): """p expression @@ -1542,8 +1755,8 @@ def do_display(self, arg): if not arg: if self.displaying: self.message('Currently displaying:') - for item in self.displaying.get(self.curframe, {}).items(): - self.message('%s: %r' % item) + for key, val in self.displaying.get(self.curframe, {}).items(): + self.message('%s: %s' % (key, self._safe_repr(val, key))) else: self.message('No expression is being displayed') else: @@ -1552,7 +1765,7 @@ def do_display(self, arg): else: val = self._getval_except(arg) self.displaying.setdefault(self.curframe, {})[arg] = val - self.message('display %s: %r' % (arg, val)) + self.message('display %s: %s' % (arg, self._safe_repr(val, arg))) complete_display = _complete_expression @@ -1582,7 +1795,9 @@ def do_interact(self, arg): contains all the (global and local) names found in the current scope. """ ns = {**self.curframe.f_globals, **self.curframe_locals} - code.interact("*interactive*", local=ns) + console = _PdbInteractiveConsole(ns, message=self.message) + console.interact(banner="*pdb interact start*", + exitmsg="*exit from pdb interact command*") def do_alias(self, arg): """alias [name [command]] @@ -1615,10 +1830,24 @@ def do_alias(self, arg): for alias in keys: self.message("%s = %s" % (alias, self.aliases[alias])) return - if args[0] in self.aliases and len(args) == 1: - self.message("%s = %s" % (args[0], self.aliases[args[0]])) + if len(args) == 1: + if args[0] in self.aliases: + self.message("%s = %s" % (args[0], self.aliases[args[0]])) + else: + self.error(f"Unknown alias '{args[0]}'") else: - self.aliases[args[0]] = ' '.join(args[1:]) + # Do a validation check to make sure no replaceable parameters + # are skipped if %* is not used. + alias = ' '.join(args[1:]) + if '%*' not in alias: + consecutive = True + for idx in range(1, 10): + if f'%{idx}' not in alias: + consecutive = False + if f'%{idx}' in alias and not consecutive: + self.error("Replaceable parameters must be consecutive") + return + self.aliases[args[0]] = alias def do_unalias(self, arg): """unalias name @@ -1890,11 +2119,23 @@ def set_trace(*, header=None): # Post-Mortem interface def post_mortem(t=None): - """Enter post-mortem debugging of the given *traceback* object. + """Enter post-mortem debugging of the given *traceback*, or *exception* + object. If no traceback is given, it uses the one of the exception that is currently being handled (an exception must be being handled if the default is to be used). + + If `t` is an exception object, the `exceptions` command makes it possible to + list and inspect its chained exceptions (if any). + """ + return _post_mortem(t, Pdb()) + + +def _post_mortem(t, pdb_instance): + """ + Private version of post_mortem, which allow to pass a pdb instance + for testing purposes. """ # handling the default if t is None: @@ -1902,21 +2143,17 @@ def post_mortem(t=None): if exc is not None: t = exc.__traceback__ - if t is None: + if t is None or (isinstance(t, BaseException) and t.__traceback__ is None): raise ValueError("A valid traceback must be passed if no " "exception is being handled") - p = Pdb() - p.reset() - p.interaction(None, t) + pdb_instance.reset() + pdb_instance.interaction(None, t) + def pm(): - """Enter post-mortem debugging of the traceback found in sys.last_traceback.""" - if hasattr(sys, 'last_exc'): - tb = sys.last_exc.__traceback__ - else: - tb = sys.last_traceback - post_mortem(tb) + """Enter post-mortem debugging of the traceback found in sys.last_exc.""" + post_mortem(sys.last_exc) # Main program for testing @@ -1932,8 +2169,6 @@ def help(): pydoc.pager(__doc__) _usage = """\ -usage: pdb.py [-c command] ... [-m module | pyfile] [arg] ... - Debug the Python program given by pyfile. Alternatively, an executable module or package to debug can be specified using the -m switch. @@ -1948,40 +2183,47 @@ def help(): def main(): - import getopt - - opts, args = getopt.getopt(sys.argv[1:], 'mhc:', ['help', 'command=']) - - if not args: - print(_usage) + import argparse + + parser = argparse.ArgumentParser(prog="pdb", + description=_usage, + formatter_class=argparse.RawDescriptionHelpFormatter, + allow_abbrev=False) + + parser.add_argument('-c', '--command', action='append', default=[], metavar='command') + group = parser.add_mutually_exclusive_group(required=True) + group.add_argument('-m', metavar='module') + group.add_argument('pyfile', nargs='?') + parser.add_argument('args', nargs="*") + + if len(sys.argv) == 1: + # If no arguments were given (python -m pdb), print the whole help message. + # Without this check, argparse would only complain about missing required arguments. + parser.print_help() sys.exit(2) - if any(opt in ['-h', '--help'] for opt, optarg in opts): - print(_usage) - sys.exit() + opts = parser.parse_args() - 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 - target = cls(args[0]) + if opts.m: + file = opts.m + target = _ModuleTarget(file) + else: + file = opts.pyfile + target = _ScriptTarget(file) target.check() - sys.argv[:] = args # Hide "pdb.py" and pdb options from argument list + sys.argv[:] = [file] + opts.args # Hide "pdb.py" and pdb options from argument list # Note on saving/restoring sys.argv: it's a good idea when sys.argv was # modified by the script being debugged. It's a bad idea when it was # changed by the user from the command line. There is a "restart" command # which allows explicit specification of command line arguments. pdb = Pdb() - pdb.rcLines.extend(commands) + pdb.rcLines.extend(opts.command) while True: try: pdb._run(target) - if pdb._user_requested_quit: - break - print("The program finished and will be restarted") except Restart: print("Restarting", target, "with arguments:") print("\t" + " ".join(sys.argv[1:])) @@ -1989,17 +2231,16 @@ def main(): # In most cases SystemExit does not warrant a post-mortem session. print("The program exited via sys.exit(). Exit status:", end=' ') print(e) - except SyntaxError: - traceback.print_exc() - sys.exit(1) except BaseException as e: traceback.print_exc() print("Uncaught exception. Entering post mortem debugging") print("Running 'cont' or 'step' will restart the program") - t = e.__traceback__ - pdb.interaction(None, t) + pdb.interaction(None, e) print("Post mortem debugger finished. The " + target + " will be restarted") + if pdb._user_requested_quit: + break + print("The program finished and will be restarted") # When invoked as main program, invoke the debugger on a script diff --git a/Lib/pickle.py b/Lib/pickle.py index fe86f80f51d3b9..33c97c8c5efb28 100644 --- a/Lib/pickle.py +++ b/Lib/pickle.py @@ -396,6 +396,8 @@ def decode_long(data): return int.from_bytes(data, byteorder='little', signed=True) +_NoValue = object() + # Pickling machinery class _Pickler: @@ -542,8 +544,8 @@ def save(self, obj, save_persistent_id=True): return rv = NotImplemented - reduce = getattr(self, "reducer_override", None) - if reduce is not None: + reduce = getattr(self, "reducer_override", _NoValue) + if reduce is not _NoValue: rv = reduce(obj) if rv is NotImplemented: @@ -556,8 +558,8 @@ def save(self, obj, save_persistent_id=True): # Check private dispatch table if any, or else # copyreg.dispatch_table - reduce = getattr(self, 'dispatch_table', dispatch_table).get(t) - if reduce is not None: + reduce = getattr(self, 'dispatch_table', dispatch_table).get(t, _NoValue) + if reduce is not _NoValue: rv = reduce(obj) else: # Check for a class with a custom metaclass; treat as regular @@ -567,12 +569,12 @@ def save(self, obj, save_persistent_id=True): return # Check for a __reduce_ex__ method, fall back to __reduce__ - reduce = getattr(obj, "__reduce_ex__", None) - if reduce is not None: + reduce = getattr(obj, "__reduce_ex__", _NoValue) + if reduce is not _NoValue: rv = reduce(self.proto) else: - reduce = getattr(obj, "__reduce__", None) - if reduce is not None: + reduce = getattr(obj, "__reduce__", _NoValue) + if reduce is not _NoValue: rv = reduce() else: raise PicklingError("Can't pickle %r object: %r" % @@ -855,13 +857,13 @@ def save_str(self, obj): else: self.write(BINUNICODE + pack(" 1: + name = '' if arg == '-' else arg + preamble = args.preamble.format(name=name) + output.write(preamble + '\n') + if arg == '-': + dis(sys.stdin.buffer, output, memo, args.indentlevel, annotate) + else: + with open(arg, 'rb') as f: + dis(f, output, memo, args.indentlevel, annotate) + finally: + if output is not sys.stdout: + output.close() diff --git a/Lib/platform.py b/Lib/platform.py index 7bb222088d5061..75aa55510858fd 100755 --- a/Lib/platform.py +++ b/Lib/platform.py @@ -118,6 +118,10 @@ import sys import functools import itertools +try: + import _wmi +except ImportError: + _wmi = None ### Globals & Constants @@ -312,24 +316,26 @@ def _syscmd_ver(system='', release='', version='', version = _norm_version(version) return system, release, version -try: - import _wmi -except ImportError: - def _wmi_query(*keys): + +def _wmi_query(table, *keys): + global _wmi + if not _wmi: raise OSError("not supported") -else: - def _wmi_query(table, *keys): - table = { - "OS": "Win32_OperatingSystem", - "CPU": "Win32_Processor", - }[table] + table = { + "OS": "Win32_OperatingSystem", + "CPU": "Win32_Processor", + }[table] + try: 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) + except OSError: + _wmi = None + raise OSError("not supported") + 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 = [ diff --git a/Lib/plistlib.py b/Lib/plistlib.py index 3292c30d5fb29b..188a0b399b587b 100644 --- a/Lib/plistlib.py +++ b/Lib/plistlib.py @@ -140,7 +140,7 @@ def _decode_base64(s): _dateParser = re.compile(r"(?P\d\d\d\d)(?:-(?P\d\d)(?:-(?P\d\d)(?:T(?P\d\d)(?::(?P\d\d)(?::(?P\d\d))?)?)?)?)?Z", re.ASCII) -def _date_from_string(s): +def _date_from_string(s, aware_datetime): order = ('year', 'month', 'day', 'hour', 'minute', 'second') gd = _dateParser.match(s).groupdict() lst = [] @@ -149,10 +149,14 @@ def _date_from_string(s): if val is None: break lst.append(int(val)) + if aware_datetime: + return datetime.datetime(*lst, tzinfo=datetime.UTC) return datetime.datetime(*lst) -def _date_to_string(d): +def _date_to_string(d, aware_datetime): + if aware_datetime: + d = d.astimezone(datetime.UTC) return '%04d-%02d-%02dT%02d:%02d:%02dZ' % ( d.year, d.month, d.day, d.hour, d.minute, d.second @@ -171,11 +175,12 @@ def _escape(text): return text class _PlistParser: - def __init__(self, dict_type): + def __init__(self, dict_type, aware_datetime=False): self.stack = [] self.current_key = None self.root = None self._dict_type = dict_type + self._aware_datetime = aware_datetime def parse(self, fileobj): self.parser = ParserCreate() @@ -277,7 +282,8 @@ def end_data(self): self.add_object(_decode_base64(self.get_data())) def end_date(self): - self.add_object(_date_from_string(self.get_data())) + self.add_object(_date_from_string(self.get_data(), + aware_datetime=self._aware_datetime)) class _DumbXMLWriter: @@ -321,13 +327,14 @@ def writeln(self, line): class _PlistWriter(_DumbXMLWriter): def __init__( self, file, indent_level=0, indent=b"\t", writeHeader=1, - sort_keys=True, skipkeys=False): + sort_keys=True, skipkeys=False, aware_datetime=False): if writeHeader: file.write(PLISTHEADER) _DumbXMLWriter.__init__(self, file, indent_level, indent) self._sort_keys = sort_keys self._skipkeys = skipkeys + self._aware_datetime = aware_datetime def write(self, value): self.writeln("") @@ -360,7 +367,8 @@ def write_value(self, value): self.write_bytes(value) elif isinstance(value, datetime.datetime): - self.simple_element("date", _date_to_string(value)) + self.simple_element("date", + _date_to_string(value, self._aware_datetime)) elif isinstance(value, (tuple, list)): self.write_array(value) @@ -461,8 +469,9 @@ class _BinaryPlistParser: see also: http://opensource.apple.com/source/CF/CF-744.18/CFBinaryPList.c """ - def __init__(self, dict_type): + def __init__(self, dict_type, aware_datetime=False): self._dict_type = dict_type + self._aware_datime = aware_datetime def parse(self, fp): try: @@ -556,8 +565,11 @@ def _read_object(self, ref): f = struct.unpack('>d', self._fp.read(8))[0] # timestamp 0 of binary plists corresponds to 1/1/2001 # (year of Mac OS X 10.0), instead of 1/1/1970. - result = (datetime.datetime(2001, 1, 1) + - datetime.timedelta(seconds=f)) + if self._aware_datime: + epoch = datetime.datetime(2001, 1, 1, tzinfo=datetime.UTC) + else: + epoch = datetime.datetime(2001, 1, 1) + result = epoch + datetime.timedelta(seconds=f) elif tokenH == 0x40: # data s = self._get_size(tokenL) @@ -629,10 +641,11 @@ def _count_to_size(count): _scalars = (str, int, float, datetime.datetime, bytes) class _BinaryPlistWriter (object): - def __init__(self, fp, sort_keys, skipkeys): + def __init__(self, fp, sort_keys, skipkeys, aware_datetime=False): self._fp = fp self._sort_keys = sort_keys self._skipkeys = skipkeys + self._aware_datetime = aware_datetime def write(self, value): @@ -778,7 +791,12 @@ def _write_object(self, value): self._fp.write(struct.pack('>Bd', 0x23, value)) elif isinstance(value, datetime.datetime): - f = (value - datetime.datetime(2001, 1, 1)).total_seconds() + if self._aware_datetime: + dt = value.astimezone(datetime.UTC) + offset = dt - datetime.datetime(2001, 1, 1, tzinfo=datetime.UTC) + f = offset.total_seconds() + else: + f = (value - datetime.datetime(2001, 1, 1)).total_seconds() self._fp.write(struct.pack('>Bd', 0x33, f)) elif isinstance(value, (bytes, bytearray)): @@ -862,7 +880,7 @@ def _is_fmt_binary(header): } -def load(fp, *, fmt=None, dict_type=dict): +def load(fp, *, fmt=None, dict_type=dict, aware_datetime=False): """Read a .plist file. 'fp' should be a readable and binary file object. Return the unpacked root object (which usually is a dictionary). """ @@ -880,32 +898,41 @@ def load(fp, *, fmt=None, dict_type=dict): else: P = _FORMATS[fmt]['parser'] - p = P(dict_type=dict_type) + p = P(dict_type=dict_type, aware_datetime=aware_datetime) return p.parse(fp) -def loads(value, *, fmt=None, dict_type=dict): +def loads(value, *, fmt=None, dict_type=dict, aware_datetime=False): """Read a .plist file from a bytes object. Return the unpacked root object (which usually is a dictionary). """ + if isinstance(value, str): + if fmt == FMT_BINARY: + raise TypeError("value must be bytes-like object when fmt is " + "FMT_BINARY") + value = value.encode() fp = BytesIO(value) - return load(fp, fmt=fmt, dict_type=dict_type) + return load(fp, fmt=fmt, dict_type=dict_type, aware_datetime=aware_datetime) -def dump(value, fp, *, fmt=FMT_XML, sort_keys=True, skipkeys=False): +def dump(value, fp, *, fmt=FMT_XML, sort_keys=True, skipkeys=False, + aware_datetime=False): """Write 'value' to a .plist file. 'fp' should be a writable, binary file object. """ if fmt not in _FORMATS: raise ValueError("Unsupported format: %r"%(fmt,)) - writer = _FORMATS[fmt]["writer"](fp, sort_keys=sort_keys, skipkeys=skipkeys) + writer = _FORMATS[fmt]["writer"](fp, sort_keys=sort_keys, skipkeys=skipkeys, + aware_datetime=aware_datetime) writer.write(value) -def dumps(value, *, fmt=FMT_XML, skipkeys=False, sort_keys=True): +def dumps(value, *, fmt=FMT_XML, skipkeys=False, sort_keys=True, + aware_datetime=False): """Return a bytes object with the contents for a .plist file. """ fp = BytesIO() - dump(value, fp, fmt=fmt, skipkeys=skipkeys, sort_keys=sort_keys) + dump(value, fp, fmt=fmt, skipkeys=skipkeys, sort_keys=sort_keys, + aware_datetime=aware_datetime) return fp.getvalue() diff --git a/Lib/pprint.py b/Lib/pprint.py index 34ed12637e2288..9314701db340c7 100644 --- a/Lib/pprint.py +++ b/Lib/pprint.py @@ -128,6 +128,9 @@ def __init__(self, indent=1, width=80, depth=None, stream=None, *, sort_dicts If true, dict keys are sorted. + underscore_numbers + If true, digit groups are separated with underscores. + """ indent = int(indent) width = int(width) diff --git a/Lib/pstats.py b/Lib/pstats.py index 51bcca84188740..2f054bb4011e7f 100644 --- a/Lib/pstats.py +++ b/Lib/pstats.py @@ -329,7 +329,7 @@ def eval_print_amount(self, sel, list, msg): if isinstance(sel, str): try: rex = re.compile(sel) - except re.error: + except re.PatternError: msg += " \n" % sel return new_list, msg new_list = [] diff --git a/Lib/pydoc.py b/Lib/pydoc.py index 185f09e603df2e..96aa1dfc1aacf6 100755 --- a/Lib/pydoc.py +++ b/Lib/pydoc.py @@ -197,6 +197,27 @@ def splitdoc(doc): return lines[0], '\n'.join(lines[2:]) return '', '\n'.join(lines) +def _getargspec(object): + try: + signature = inspect.signature(object) + if signature: + name = getattr(object, '__name__', '') + # function are always single-line and should not be formatted + max_width = (80 - len(name)) if name != '' else None + return signature.format(max_width=max_width) + except (ValueError, TypeError): + argspec = getattr(object, '__text_signature__', None) + if argspec: + if argspec[:2] == '($': + argspec = '(' + argspec[2:] + if getattr(object, '__self__', None) is not None: + # Strip the bound argument. + m = re.match(r'\(\w+(?:(?=\))|,\s*(?:/(?:(?=\))|,\s*))?)', argspec) + if m: + argspec = '(' + argspec[m.end():] + return argspec + return None + def classname(object, modname): """Get a class name and qualify it with a module name if necessary.""" name = object.__name__ @@ -324,6 +345,8 @@ def sort_attributes(attrs, object): def ispackage(path): """Guess whether a path refers to a package directory.""" + warnings.warn('The pydoc.ispackage() function is deprecated', + DeprecationWarning, stacklevel=2) if os.path.isdir(path): for ext in ('.py', '.pyc'): if os.path.isfile(os.path.join(path, '__init__' + ext)): @@ -1003,14 +1026,9 @@ def spilldata(msg, attrs, predicate): title = title + '(%s)' % ', '.join(parents) decl = '' - try: - signature = inspect.signature(object) - except (ValueError, TypeError): - signature = None - if signature: - argspec = str(signature) - if argspec and argspec != '()': - decl = name + self.escape(argspec) + '\n\n' + argspec = _getargspec(object) + if argspec and argspec != '()': + decl = name + self.escape(argspec) + '\n\n' doc = getdoc(object) if decl: @@ -1063,18 +1081,13 @@ def docroutine(self, object, name=None, mod=None, anchor, name, reallink) argspec = None if inspect.isroutine(object): - try: - signature = inspect.signature(object) - except (ValueError, TypeError): - signature = None - if signature: - argspec = str(signature) - if realname == '': - title = '%s lambda ' % name - # XXX lambda's won't usually have func_annotations['return'] - # since the syntax doesn't support but it is possible. - # So removing parentheses isn't truly safe. - argspec = argspec[1:-1] # remove parentheses + argspec = _getargspec(object) + if argspec and realname == '': + title = '%s lambda ' % name + # XXX lambda's won't usually have func_annotations['return'] + # since the syntax doesn't support but it is possible. + # So removing parentheses isn't truly safe. + argspec = argspec[1:-1] # remove parentheses if not argspec: argspec = '(...)' @@ -1321,14 +1334,9 @@ def makename(c, m=object.__module__): contents = [] push = contents.append - try: - signature = inspect.signature(object) - except (ValueError, TypeError): - signature = None - if signature: - argspec = str(signature) - if argspec and argspec != '()': - push(name + argspec + '\n') + argspec = _getargspec(object) + if argspec and argspec != '()': + push(name + argspec + '\n') doc = getdoc(object) if doc: @@ -1492,18 +1500,13 @@ def docroutine(self, object, name=None, mod=None, cl=None): argspec = None if inspect.isroutine(object): - try: - signature = inspect.signature(object) - except (ValueError, TypeError): - signature = None - if signature: - argspec = str(signature) - if realname == '': - title = self.bold(name) + ' lambda ' - # XXX lambda's won't usually have func_annotations['return'] - # since the syntax doesn't support but it is possible. - # So removing parentheses isn't truly safe. - argspec = argspec[1:-1] # remove parentheses + argspec = _getargspec(object) + if argspec and realname == '': + title = self.bold(name) + ' lambda ' + # XXX lambda's won't usually have func_annotations['return'] + # since the syntax doesn't support but it is possible. + # So removing parentheses isn't truly safe. + argspec = argspec[1:-1] # remove parentheses if not argspec: argspec = '(...)' decl = asyncqualifier + title + argspec + note @@ -2075,20 +2078,22 @@ def help(self, request, is_cli=False): self.output.write('\n') def intro(self): - self.output.write(''' -Welcome to Python {0}'s help utility! - -If this is your first time using Python, you should definitely check out -the tutorial on the internet at https://docs.python.org/{0}/tutorial/. + self.output.write('''\ +Welcome to Python {0}'s help utility! If this is your first time using +Python, you should definitely check out the tutorial at +https://docs.python.org/{0}/tutorial/. Enter the name of any module, keyword, or topic to get help on writing -Python programs and using Python modules. To quit this help utility and -return to the interpreter, just type "quit". +Python programs and using Python modules. To get a list of available +modules, keywords, symbols, or topics, enter "modules", "keywords", +"symbols", or "topics". + +Each module also comes with a one-line summary of what it does; to list +the modules whose name or summary contain a given string such as "spam", +enter "modules spam". -To get a list of available modules, keywords, symbols, or topics, type -"modules", "keywords", "symbols", or "topics". Each module also comes -with a one-line summary of what it does; to list the modules whose name -or summary contain a given string such as "spam", type "modules spam". +To quit this help utility and return to the interpreter, +enter "q" or "quit". '''.format('%d.%d' % sys.version_info[:2])) def list(self, items, columns=4, width=80): diff --git a/Lib/pydoc_data/topics.py b/Lib/pydoc_data/topics.py index cb742992a48e8f..7c1bdc4dff2ec4 100644 --- a/Lib/pydoc_data/topics.py +++ b/Lib/pydoc_data/topics.py @@ -1,5 +1,6 @@ # -*- coding: utf-8 -*- -# Autogenerated by Sphinx on Mon May 22 14:02:15 2023 +# Autogenerated by Sphinx on Wed Nov 22 11:44:32 2023 +# as part of the release process. topics = {'assert': 'The "assert" statement\n' '**********************\n' '\n' @@ -208,7 +209,7 @@ 'the\n' ' subscript must have a type compatible with the mapping’s key ' 'type,\n' - ' and the mapping is then asked to create a key/datum pair ' + ' and the mapping is then asked to create a key/value pair ' 'which maps\n' ' the subscript to the assigned object. This can either ' 'replace an\n' @@ -538,77 +539,7 @@ ' **PEP 492** - Coroutines with async and await syntax\n' ' The proposal that made coroutines a proper standalone concept ' 'in\n' - ' Python, and added supporting syntax.\n' - '\n' - '-[ Footnotes ]-\n' - '\n' - '[1] The exception is propagated to the invocation stack unless ' - 'there\n' - ' is a "finally" clause which happens to raise another ' - 'exception.\n' - ' That new exception causes the old one to be lost.\n' - '\n' - '[2] In pattern matching, a sequence is defined as one of the\n' - ' following:\n' - '\n' - ' * a class that inherits from "collections.abc.Sequence"\n' - '\n' - ' * a Python class that has been registered as\n' - ' "collections.abc.Sequence"\n' - '\n' - ' * a builtin class that has its (CPython) ' - '"Py_TPFLAGS_SEQUENCE"\n' - ' bit set\n' - '\n' - ' * a class that inherits from any of the above\n' - '\n' - ' The following standard library classes are sequences:\n' - '\n' - ' * "array.array"\n' - '\n' - ' * "collections.deque"\n' - '\n' - ' * "list"\n' - '\n' - ' * "memoryview"\n' - '\n' - ' * "range"\n' - '\n' - ' * "tuple"\n' - '\n' - ' Note:\n' - '\n' - ' Subject values of type "str", "bytes", and "bytearray" do ' - 'not\n' - ' match sequence patterns.\n' - '\n' - '[3] In pattern matching, a mapping is defined as one of the ' - 'following:\n' - '\n' - ' * a class that inherits from "collections.abc.Mapping"\n' - '\n' - ' * a Python class that has been registered as\n' - ' "collections.abc.Mapping"\n' - '\n' - ' * a builtin class that has its (CPython) ' - '"Py_TPFLAGS_MAPPING"\n' - ' bit set\n' - '\n' - ' * a class that inherits from any of the above\n' - '\n' - ' The standard library classes "dict" and ' - '"types.MappingProxyType"\n' - ' are mappings.\n' - '\n' - '[4] A string literal appearing as the first statement in the ' - 'function\n' - ' body is transformed into the function’s "__doc__" attribute ' - 'and\n' - ' therefore the function’s *docstring*.\n' - '\n' - '[5] A string literal appearing as the first statement in the class\n' - ' body is transformed into the namespace’s "__doc__" item and\n' - ' therefore the class’s *docstring*.\n', + ' Python, and added supporting syntax.\n', 'atom-identifiers': 'Identifiers (Names)\n' '*******************\n' '\n' @@ -713,7 +644,7 @@ '"__getattr__()" would have\n' ' no way to access other attributes of the instance. ' 'Note that at\n' - ' least for instance variables, you can fake total ' + ' least for instance variables, you can take total ' 'control by not\n' ' inserting any values in the instance attribute ' 'dictionary (but\n' @@ -1075,9 +1006,7 @@ 'for each\n' ' instance.\n' '\n' - '\n' - 'Notes on using *__slots__*\n' - '--------------------------\n' + 'Notes on using *__slots__*:\n' '\n' '* When inheriting from a class without *__slots__*, the ' '"__dict__" and\n' @@ -1748,8 +1677,8 @@ 'standard\n' 'type hierarchy):\n' '\n' - ' classdef ::= [decorators] "class" classname [inheritance] ":" ' - 'suite\n' + ' classdef ::= [decorators] "class" classname [type_params] ' + '[inheritance] ":" suite\n' ' inheritance ::= "(" [argument_list] ")"\n' ' classname ::= identifier\n' '\n' @@ -1813,6 +1742,19 @@ '"assignment_expression". Previously, the grammar was much more\n' 'restrictive; see **PEP 614** for details.\n' '\n' + 'A list of type parameters may be given in square brackets ' + 'immediately\n' + 'after the class’s name. This indicates to static type checkers ' + 'that\n' + 'the class is generic. At runtime, the type parameters can be ' + 'retrieved\n' + 'from the class’s "__type_params__" attribute. See Generic classes ' + 'for\n' + 'more.\n' + '\n' + 'Changed in version 3.12: Type parameter lists are new in Python ' + '3.12.\n' + '\n' '**Programmer’s note:** Variables defined in the class definition ' 'are\n' 'class attributes; they are shared by instances. Instance ' @@ -2870,18 +2812,19 @@ ' bindings made during a successful pattern match outlive the\n' ' executed block and can be used after the match statement**.\n' '\n' - ' Note:\n' + ' Note:\n' '\n' - ' During failed pattern matches, some subpatterns may ' - 'succeed.\n' - ' Do not rely on bindings being made for a failed match.\n' - ' Conversely, do not rely on variables remaining unchanged ' - 'after\n' - ' a failed match. The exact behavior is dependent on\n' - ' implementation and may vary. This is an intentional ' - 'decision\n' - ' made to allow different implementations to add ' - 'optimizations.\n' + ' During failed pattern matches, some subpatterns may ' + 'succeed. Do\n' + ' not rely on bindings being made for a failed match. ' + 'Conversely,\n' + ' do not rely on variables remaining unchanged after a ' + 'failed\n' + ' match. The exact behavior is dependent on implementation ' + 'and may\n' + ' vary. This is an intentional decision made to allow ' + 'different\n' + ' implementations to add optimizations.\n' '\n' '3. If the pattern succeeds, the corresponding guard (if present) ' 'is\n' @@ -3533,9 +3476,10 @@ '* convert "P1" to a keyword pattern using "CLS.__match_args__"\n' '\n' '* For each keyword argument "attr=P2":\n' - ' * "hasattr(, "attr")"\n' '\n' - ' * "P2" matches ".attr"\n' + ' * "hasattr(, "attr")"\n' + '\n' + ' * "P2" matches ".attr"\n' '\n' '* … and so on for the corresponding keyword argument/pattern ' 'pair.\n' @@ -3554,8 +3498,8 @@ '(see\n' 'section The standard type hierarchy):\n' '\n' - ' funcdef ::= [decorators] "def" funcname "(" ' - '[parameter_list] ")"\n' + ' funcdef ::= [decorators] "def" funcname ' + '[type_params] "(" [parameter_list] ")"\n' ' ["->" expression] ":" suite\n' ' decorators ::= decorator+\n' ' decorator ::= "@" assignment_expression ' @@ -3617,6 +3561,19 @@ '"assignment_expression". Previously, the grammar was much more\n' 'restrictive; see **PEP 614** for details.\n' '\n' + 'A list of type parameters may be given in square brackets ' + 'between the\n' + 'function’s name and the opening parenthesis for its parameter ' + 'list.\n' + 'This indicates to static type checkers that the function is ' + 'generic.\n' + 'At runtime, the type parameters can be retrieved from the ' + 'function’s\n' + '"__type_params__" attribute. See Generic functions for more.\n' + '\n' + 'Changed in version 3.12: Type parameter lists are new in Python ' + '3.12.\n' + '\n' 'When one or more *parameters* have the form *parameter* "="\n' '*expression*, the function is said to have “default parameter ' 'values.â€\n' @@ -3759,8 +3716,8 @@ 'standard\n' 'type hierarchy):\n' '\n' - ' classdef ::= [decorators] "class" classname [inheritance] ' - '":" suite\n' + ' classdef ::= [decorators] "class" classname [type_params] ' + '[inheritance] ":" suite\n' ' inheritance ::= "(" [argument_list] ")"\n' ' classname ::= identifier\n' '\n' @@ -3828,6 +3785,19 @@ '"assignment_expression". Previously, the grammar was much more\n' 'restrictive; see **PEP 614** for details.\n' '\n' + 'A list of type parameters may be given in square brackets ' + 'immediately\n' + 'after the class’s name. This indicates to static type checkers ' + 'that\n' + 'the class is generic. At runtime, the type parameters can be ' + 'retrieved\n' + 'from the class’s "__type_params__" attribute. See Generic ' + 'classes for\n' + 'more.\n' + '\n' + 'Changed in version 3.12: Type parameter lists are new in Python ' + '3.12.\n' + '\n' '**Programmer’s note:** Variables defined in the class definition ' 'are\n' 'class attributes; they are shared by instances. Instance ' @@ -3985,6 +3955,272 @@ 'concept in\n' ' Python, and added supporting syntax.\n' '\n' + '\n' + 'Type parameter lists\n' + '====================\n' + '\n' + 'New in version 3.12.\n' + '\n' + ' type_params ::= "[" type_param ("," type_param)* "]"\n' + ' type_param ::= typevar | typevartuple | paramspec\n' + ' typevar ::= identifier (":" expression)?\n' + ' typevartuple ::= "*" identifier\n' + ' paramspec ::= "**" identifier\n' + '\n' + 'Functions (including coroutines), classes and type aliases may ' + 'contain\n' + 'a type parameter list:\n' + '\n' + ' def max[T](args: list[T]) -> T:\n' + ' ...\n' + '\n' + ' async def amax[T](args: list[T]) -> T:\n' + ' ...\n' + '\n' + ' class Bag[T]:\n' + ' def __iter__(self) -> Iterator[T]:\n' + ' ...\n' + '\n' + ' def add(self, arg: T) -> None:\n' + ' ...\n' + '\n' + ' type ListOrSet[T] = list[T] | set[T]\n' + '\n' + 'Semantically, this indicates that the function, class, or type ' + 'alias\n' + 'is generic over a type variable. This information is primarily ' + 'used by\n' + 'static type checkers, and at runtime, generic objects behave ' + 'much like\n' + 'their non-generic counterparts.\n' + '\n' + 'Type parameters are declared in square brackets ("[]") ' + 'immediately\n' + 'after the name of the function, class, or type alias. The type\n' + 'parameters are accessible within the scope of the generic ' + 'object, but\n' + 'not elsewhere. Thus, after a declaration "def func[T](): pass", ' + 'the\n' + 'name "T" is not available in the module scope. Below, the ' + 'semantics of\n' + 'generic objects are described with more precision. The scope of ' + 'type\n' + 'parameters is modeled with a special function (technically, an\n' + 'annotation scope) that wraps the creation of the generic ' + 'object.\n' + '\n' + 'Generic functions, classes, and type aliases have a ' + '"__type_params__"\n' + 'attribute listing their type parameters.\n' + '\n' + 'Type parameters come in three kinds:\n' + '\n' + '* "typing.TypeVar", introduced by a plain name (e.g., "T").\n' + ' Semantically, this represents a single type to a type ' + 'checker.\n' + '\n' + '* "typing.TypeVarTuple", introduced by a name prefixed with a ' + 'single\n' + ' asterisk (e.g., "*Ts"). Semantically, this stands for a tuple ' + 'of any\n' + ' number of types.\n' + '\n' + '* "typing.ParamSpec", introduced by a name prefixed with two ' + 'asterisks\n' + ' (e.g., "**P"). Semantically, this stands for the parameters of ' + 'a\n' + ' callable.\n' + '\n' + '"typing.TypeVar" declarations can define *bounds* and ' + '*constraints*\n' + 'with a colon (":") followed by an expression. A single ' + 'expression\n' + 'after the colon indicates a bound (e.g. "T: int"). Semantically, ' + 'this\n' + 'means that the "typing.TypeVar" can only represent types that ' + 'are a\n' + 'subtype of this bound. A parenthesized tuple of expressions ' + 'after the\n' + 'colon indicates a set of constraints (e.g. "T: (str, bytes)"). ' + 'Each\n' + 'member of the tuple should be a type (again, this is not ' + 'enforced at\n' + 'runtime). Constrained type variables can only take on one of the ' + 'types\n' + 'in the list of constraints.\n' + '\n' + 'For "typing.TypeVar"s declared using the type parameter list ' + 'syntax,\n' + 'the bound and constraints are not evaluated when the generic ' + 'object is\n' + 'created, but only when the value is explicitly accessed through ' + 'the\n' + 'attributes "__bound__" and "__constraints__". To accomplish ' + 'this, the\n' + 'bounds or constraints are evaluated in a separate annotation ' + 'scope.\n' + '\n' + '"typing.TypeVarTuple"s and "typing.ParamSpec"s cannot have ' + 'bounds or\n' + 'constraints.\n' + '\n' + 'The following example indicates the full set of allowed type ' + 'parameter\n' + 'declarations:\n' + '\n' + ' def overly_generic[\n' + ' SimpleTypeVar,\n' + ' TypeVarWithBound: int,\n' + ' TypeVarWithConstraints: (str, bytes),\n' + ' *SimpleTypeVarTuple,\n' + ' **SimpleParamSpec,\n' + ' ](\n' + ' a: SimpleTypeVar,\n' + ' b: TypeVarWithBound,\n' + ' c: Callable[SimpleParamSpec, TypeVarWithConstraints],\n' + ' *d: SimpleTypeVarTuple,\n' + ' ): ...\n' + '\n' + '\n' + 'Generic functions\n' + '-----------------\n' + '\n' + 'Generic functions are declared as follows:\n' + '\n' + ' def func[T](arg: T): ...\n' + '\n' + 'This syntax is equivalent to:\n' + '\n' + ' annotation-def TYPE_PARAMS_OF_func():\n' + ' T = typing.TypeVar("T")\n' + ' def func(arg: T): ...\n' + ' func.__type_params__ = (T,)\n' + ' return func\n' + ' func = TYPE_PARAMS_OF_func()\n' + '\n' + 'Here "annotation-def" indicates an annotation scope, which is ' + 'not\n' + 'actually bound to any name at runtime. (One other liberty is ' + 'taken in\n' + 'the translation: the syntax does not go through attribute access ' + 'on\n' + 'the "typing" module, but creates an instance of ' + '"typing.TypeVar"\n' + 'directly.)\n' + '\n' + 'The annotations of generic functions are evaluated within the\n' + 'annotation scope used for declaring the type parameters, but ' + 'the\n' + 'function’s defaults and decorators are not.\n' + '\n' + 'The following example illustrates the scoping rules for these ' + 'cases,\n' + 'as well as for additional flavors of type parameters:\n' + '\n' + ' @decorator\n' + ' def func[T: int, *Ts, **P](*args: *Ts, arg: Callable[P, T] = ' + 'some_default):\n' + ' ...\n' + '\n' + 'Except for the lazy evaluation of the "TypeVar" bound, this is\n' + 'equivalent to:\n' + '\n' + ' DEFAULT_OF_arg = some_default\n' + '\n' + ' annotation-def TYPE_PARAMS_OF_func():\n' + '\n' + ' annotation-def BOUND_OF_T():\n' + ' return int\n' + ' # In reality, BOUND_OF_T() is evaluated only on demand.\n' + ' T = typing.TypeVar("T", bound=BOUND_OF_T())\n' + '\n' + ' Ts = typing.TypeVarTuple("Ts")\n' + ' P = typing.ParamSpec("P")\n' + '\n' + ' def func(*args: *Ts, arg: Callable[P, T] = ' + 'DEFAULT_OF_arg):\n' + ' ...\n' + '\n' + ' func.__type_params__ = (T, Ts, P)\n' + ' return func\n' + ' func = decorator(TYPE_PARAMS_OF_func())\n' + '\n' + 'The capitalized names like "DEFAULT_OF_arg" are not actually ' + 'bound at\n' + 'runtime.\n' + '\n' + '\n' + 'Generic classes\n' + '---------------\n' + '\n' + 'Generic classes are declared as follows:\n' + '\n' + ' class Bag[T]: ...\n' + '\n' + 'This syntax is equivalent to:\n' + '\n' + ' annotation-def TYPE_PARAMS_OF_Bag():\n' + ' T = typing.TypeVar("T")\n' + ' class Bag(typing.Generic[T]):\n' + ' __type_params__ = (T,)\n' + ' ...\n' + ' return Bag\n' + ' Bag = TYPE_PARAMS_OF_Bag()\n' + '\n' + 'Here again "annotation-def" (not a real keyword) indicates an\n' + 'annotation scope, and the name "TYPE_PARAMS_OF_Bag" is not ' + 'actually\n' + 'bound at runtime.\n' + '\n' + 'Generic classes implicitly inherit from "typing.Generic". The ' + 'base\n' + 'classes and keyword arguments of generic classes are evaluated ' + 'within\n' + 'the type scope for the type parameters, and decorators are ' + 'evaluated\n' + 'outside that scope. This is illustrated by this example:\n' + '\n' + ' @decorator\n' + ' class Bag(Base[T], arg=T): ...\n' + '\n' + 'This is equivalent to:\n' + '\n' + ' annotation-def TYPE_PARAMS_OF_Bag():\n' + ' T = typing.TypeVar("T")\n' + ' class Bag(Base[T], typing.Generic[T], arg=T):\n' + ' __type_params__ = (T,)\n' + ' ...\n' + ' return Bag\n' + ' Bag = decorator(TYPE_PARAMS_OF_Bag())\n' + '\n' + '\n' + 'Generic type aliases\n' + '--------------------\n' + '\n' + 'The "type" statement can also be used to create a generic type ' + 'alias:\n' + '\n' + ' type ListOrSet[T] = list[T] | set[T]\n' + '\n' + 'Except for the lazy evaluation of the value, this is equivalent ' + 'to:\n' + '\n' + ' annotation-def TYPE_PARAMS_OF_ListOrSet():\n' + ' T = typing.TypeVar("T")\n' + '\n' + ' annotation-def VALUE_OF_ListOrSet():\n' + ' return list[T] | set[T]\n' + ' # In reality, the value is lazily evaluated\n' + ' return typing.TypeAliasType("ListOrSet", ' + 'VALUE_OF_ListOrSet(), type_params=(T,))\n' + ' ListOrSet = TYPE_PARAMS_OF_ListOrSet()\n' + '\n' + 'Here, "annotation-def" (not a real keyword) indicates an ' + 'annotation\n' + 'scope. The capitalized names like "TYPE_PARAMS_OF_ListOrSet" are ' + 'not\n' + 'actually bound at runtime.\n' + '\n' '-[ Footnotes ]-\n' '\n' '[1] The exception is propagated to the invocation stack unless ' @@ -3996,30 +4232,30 @@ '[2] In pattern matching, a sequence is defined as one of the\n' ' following:\n' '\n' - ' * a class that inherits from "collections.abc.Sequence"\n' + ' * a class that inherits from "collections.abc.Sequence"\n' '\n' - ' * a Python class that has been registered as\n' - ' "collections.abc.Sequence"\n' + ' * a Python class that has been registered as\n' + ' "collections.abc.Sequence"\n' '\n' - ' * a builtin class that has its (CPython) ' - '"Py_TPFLAGS_SEQUENCE"\n' - ' bit set\n' + ' * a builtin class that has its (CPython) ' + '"Py_TPFLAGS_SEQUENCE" bit\n' + ' set\n' '\n' - ' * a class that inherits from any of the above\n' + ' * a class that inherits from any of the above\n' '\n' ' The following standard library classes are sequences:\n' '\n' - ' * "array.array"\n' + ' * "array.array"\n' '\n' - ' * "collections.deque"\n' + ' * "collections.deque"\n' '\n' - ' * "list"\n' + ' * "list"\n' '\n' - ' * "memoryview"\n' + ' * "memoryview"\n' '\n' - ' * "range"\n' + ' * "range"\n' '\n' - ' * "tuple"\n' + ' * "tuple"\n' '\n' ' Note:\n' '\n' @@ -4030,16 +4266,16 @@ '[3] In pattern matching, a mapping is defined as one of the ' 'following:\n' '\n' - ' * a class that inherits from "collections.abc.Mapping"\n' + ' * a class that inherits from "collections.abc.Mapping"\n' '\n' - ' * a Python class that has been registered as\n' - ' "collections.abc.Mapping"\n' + ' * a Python class that has been registered as\n' + ' "collections.abc.Mapping"\n' '\n' - ' * a builtin class that has its (CPython) ' - '"Py_TPFLAGS_MAPPING"\n' - ' bit set\n' + ' * a builtin class that has its (CPython) ' + '"Py_TPFLAGS_MAPPING" bit\n' + ' set\n' '\n' - ' * a class that inherits from any of the above\n' + ' * a class that inherits from any of the above\n' '\n' ' The standard library classes "dict" and ' '"types.MappingProxyType"\n' @@ -4817,8 +5053,8 @@ '\n' 'pdb.pm()\n' '\n' - ' Enter post-mortem debugging of the traceback found in\n' - ' "sys.last_traceback".\n' + ' Enter post-mortem debugging of the exception found in\n' + ' "sys.last_exc".\n' '\n' 'The "run*" functions and "set_trace()" are aliases for ' 'instantiating\n' @@ -4914,6 +5150,10 @@ 'is\n' 'printed but the debugger’s state is not changed.\n' '\n' + 'Changed in version 3.13: Expressions/Statements whose prefix is ' + 'a pdb\n' + 'command are now correctly identified and executed.\n' + '\n' 'The debugger supports aliases. Aliases can have parameters ' 'which\n' 'allows one a certain level of adaptability to the context under\n' @@ -5334,7 +5574,7 @@ ' Create an alias called *name* that executes *command*. The\n' ' *command* must *not* be enclosed in quotes. Replaceable ' 'parameters\n' - ' can be indicated by "%1", "%2", and so on, while "%*" is ' + ' can be indicated by "%1", "%2", … and "%9", while "%*" is ' 'replaced\n' ' by all the parameters. If *command* is omitted, the current ' 'alias\n' @@ -5415,6 +5655,57 @@ ' Print the return value for the last return of the current ' 'function.\n' '\n' + 'exceptions [excnumber]\n' + '\n' + ' List or jump between chained exceptions.\n' + '\n' + ' When using "pdb.pm()" or "Pdb.post_mortem(...)" with a ' + 'chained\n' + ' exception instead of a traceback, it allows the user to move\n' + ' between the chained exceptions using "exceptions" command to ' + 'list\n' + ' exceptions, and "exception " to switch to that ' + 'exception.\n' + '\n' + ' Example:\n' + '\n' + ' def out():\n' + ' try:\n' + ' middle()\n' + ' except Exception as e:\n' + ' raise ValueError("reraise middle() error") from e\n' + '\n' + ' def middle():\n' + ' try:\n' + ' return inner(0)\n' + ' except Exception as e:\n' + ' raise ValueError("Middle fail")\n' + '\n' + ' def inner(x):\n' + ' 1 / x\n' + '\n' + ' out()\n' + '\n' + ' calling "pdb.pm()" will allow to move between exceptions:\n' + '\n' + ' > example.py(5)out()\n' + ' -> raise ValueError("reraise middle() error") from e\n' + '\n' + ' (Pdb) exceptions\n' + " 0 ZeroDivisionError('division by zero')\n" + " 1 ValueError('Middle fail')\n" + " > 2 ValueError('reraise middle() error')\n" + '\n' + ' (Pdb) exceptions 0\n' + ' > example.py(16)inner()\n' + ' -> 1 / x\n' + '\n' + ' (Pdb) up\n' + ' > example.py(10)middle()\n' + ' -> return inner(0)\n' + '\n' + ' New in version 3.13.\n' + '\n' '-[ Footnotes ]-\n' '\n' '[1] Whether a frame is considered to originate in a certain ' @@ -5452,30 +5743,31 @@ 'dict': 'Dictionary displays\n' '*******************\n' '\n' - 'A dictionary display is a possibly empty series of key/datum pairs\n' - 'enclosed in curly braces:\n' + 'A dictionary display is a possibly empty series of dict items\n' + '(key/value pairs) enclosed in curly braces:\n' '\n' - ' dict_display ::= "{" [key_datum_list | dict_comprehension] ' + ' dict_display ::= "{" [dict_item_list | dict_comprehension] ' '"}"\n' - ' key_datum_list ::= key_datum ("," key_datum)* [","]\n' - ' key_datum ::= expression ":" expression | "**" or_expr\n' + ' dict_item_list ::= dict_item ("," dict_item)* [","]\n' + ' dict_item ::= expression ":" expression | "**" or_expr\n' ' dict_comprehension ::= expression ":" expression comp_for\n' '\n' 'A dictionary display yields a new dictionary object.\n' '\n' - 'If a comma-separated sequence of key/datum pairs is given, they are\n' + 'If a comma-separated sequence of dict items is given, they are\n' 'evaluated from left to right to define the entries of the ' 'dictionary:\n' 'each key object is used as a key into the dictionary to store the\n' - 'corresponding datum. This means that you can specify the same key\n' - 'multiple times in the key/datum list, and the final dictionary’s ' + 'corresponding value. This means that you can specify the same key\n' + 'multiple times in the dict item list, and the final dictionary’s ' 'value\n' 'for that key will be the last one given.\n' '\n' 'A double asterisk "**" denotes *dictionary unpacking*. Its operand\n' 'must be a *mapping*. Each mapping item is added to the new\n' - 'dictionary. Later values replace values already set by earlier\n' - 'key/datum pairs and earlier dictionary unpackings.\n' + 'dictionary. Later values replace values already set by earlier ' + 'dict\n' + 'items and earlier dictionary unpackings.\n' '\n' 'New in version 3.5: Unpacking into dictionary displays, originally\n' 'proposed by **PEP 448**.\n' @@ -5491,7 +5783,7 @@ 'Restrictions on the types of the key values are listed earlier in\n' 'section The standard type hierarchy. (To summarize, the key type\n' 'should be *hashable*, which excludes all mutable objects.) Clashes\n' - 'between duplicate keys are not detected; the last datum (textually\n' + 'between duplicate keys are not detected; the last value (textually\n' 'rightmost in the display) stored for a given key value prevails.\n' '\n' 'Changed in version 3.8: Prior to Python 3.8, in dict ' @@ -5692,6 +5984,10 @@ '\n' '* "import" statements.\n' '\n' + '* "type" statements.\n' + '\n' + '* type parameter lists.\n' + '\n' 'The "import" statement of the form "from ... import *" binds ' 'all names\n' 'defined in the imported module, except those beginning with an\n' @@ -5798,7 +6094,9 @@ 'scope.\n' '"SyntaxError" is raised at compile time if the given name does ' 'not\n' - 'exist in any enclosing function scope.\n' + 'exist in any enclosing function scope. Type parameters cannot ' + 'be\n' + 'rebound with the "nonlocal" statement.\n' '\n' 'The namespace for a module is automatically created the first ' 'time a\n' @@ -5821,17 +6119,162 @@ 'the class. The scope of names defined in a class block is ' 'limited to\n' 'the class block; it does not extend to the code blocks of ' - 'methods –\n' - 'this includes comprehensions and generator expressions since ' - 'they are\n' - 'implemented using a function scope. This means that the ' - 'following\n' - 'will fail:\n' + 'methods.\n' + 'This includes comprehensions and generator expressions, but it ' + 'does\n' + 'not include annotation scopes, which have access to their ' + 'enclosing\n' + 'class scopes. This means that the following will fail:\n' '\n' ' class A:\n' ' a = 42\n' ' b = list(a + i for i in range(10))\n' '\n' + 'However, the following will succeed:\n' + '\n' + ' class A:\n' + ' type Alias = Nested\n' + ' class Nested: pass\n' + '\n' + " print(A.Alias.__value__) # \n" + '\n' + '\n' + 'Annotation scopes\n' + '-----------------\n' + '\n' + 'Type parameter lists and "type" statements introduce ' + '*annotation\n' + 'scopes*, which behave mostly like function scopes, but with ' + 'some\n' + 'exceptions discussed below. *Annotations* currently do not use\n' + 'annotation scopes, but they are expected to use annotation ' + 'scopes in\n' + 'Python 3.13 when **PEP 649** is implemented.\n' + '\n' + 'Annotation scopes are used in the following contexts:\n' + '\n' + '* Type parameter lists for generic type aliases.\n' + '\n' + '* Type parameter lists for generic functions. A generic ' + 'function’s\n' + ' annotations are executed within the annotation scope, but ' + 'its\n' + ' defaults and decorators are not.\n' + '\n' + '* Type parameter lists for generic classes. A generic class’s ' + 'base\n' + ' classes and keyword arguments are executed within the ' + 'annotation\n' + ' scope, but its decorators are not.\n' + '\n' + '* The bounds and constraints for type variables (lazily ' + 'evaluated).\n' + '\n' + '* The value of type aliases (lazily evaluated).\n' + '\n' + 'Annotation scopes differ from function scopes in the following ' + 'ways:\n' + '\n' + '* Annotation scopes have access to their enclosing class ' + 'namespace. If\n' + ' an annotation scope is immediately within a class scope, or ' + 'within\n' + ' another annotation scope that is immediately within a class ' + 'scope,\n' + ' the code in the annotation scope can use names defined in the ' + 'class\n' + ' scope as if it were executed directly within the class body. ' + 'This\n' + ' contrasts with regular functions defined within classes, ' + 'which\n' + ' cannot access names defined in the class scope.\n' + '\n' + '* Expressions in annotation scopes cannot contain "yield", ' + '"yield\n' + ' from", "await", or ":=" expressions. (These expressions are ' + 'allowed\n' + ' in other scopes contained within the annotation scope.)\n' + '\n' + '* Names defined in annotation scopes cannot be rebound with ' + '"nonlocal"\n' + ' statements in inner scopes. This includes only type ' + 'parameters, as\n' + ' no other syntactic elements that can appear within annotation ' + 'scopes\n' + ' can introduce new names.\n' + '\n' + '* While annotation scopes have an internal name, that name is ' + 'not\n' + ' reflected in the *__qualname__* of objects defined within the ' + 'scope.\n' + ' Instead, the "__qualname__" of such objects is as if the ' + 'object were\n' + ' defined in the enclosing scope.\n' + '\n' + 'New in version 3.12: Annotation scopes were introduced in ' + 'Python 3.12\n' + 'as part of **PEP 695**.\n' + '\n' + '\n' + 'Lazy evaluation\n' + '---------------\n' + '\n' + 'The values of type aliases created through the "type" statement ' + 'are\n' + '*lazily evaluated*. The same applies to the bounds and ' + 'constraints of\n' + 'type variables created through the type parameter syntax. This ' + 'means\n' + 'that they are not evaluated when the type alias or type ' + 'variable is\n' + 'created. Instead, they are only evaluated when doing so is ' + 'necessary\n' + 'to resolve an attribute access.\n' + '\n' + 'Example:\n' + '\n' + ' >>> type Alias = 1/0\n' + ' >>> Alias.__value__\n' + ' Traceback (most recent call last):\n' + ' ...\n' + ' ZeroDivisionError: division by zero\n' + ' >>> def func[T: 1/0](): pass\n' + ' >>> T = func.__type_params__[0]\n' + ' >>> T.__bound__\n' + ' Traceback (most recent call last):\n' + ' ...\n' + ' ZeroDivisionError: division by zero\n' + '\n' + 'Here the exception is raised only when the "__value__" ' + 'attribute of\n' + 'the type alias or the "__bound__" attribute of the type ' + 'variable is\n' + 'accessed.\n' + '\n' + 'This behavior is primarily useful for references to types that ' + 'have\n' + 'not yet been defined when the type alias or type variable is ' + 'created.\n' + 'For example, lazy evaluation enables creation of mutually ' + 'recursive\n' + 'type aliases:\n' + '\n' + ' from typing import Literal\n' + '\n' + ' type SimpleExpr = int | Parenthesized\n' + ' type Parenthesized = tuple[Literal["("], Expr, ' + 'Literal[")"]]\n' + ' type Expr = SimpleExpr | tuple[SimpleExpr, Literal["+", ' + '"-"], Expr]\n' + '\n' + 'Lazily evaluated values are evaluated in annotation scope, ' + 'which means\n' + 'that names that appear inside the lazily evaluated value are ' + 'looked up\n' + 'as if they were used in the immediately enclosing scope.\n' + '\n' + 'New in version 3.12.\n' + '\n' '\n' 'Builtins and restricted execution\n' '---------------------------------\n' @@ -6101,18 +6544,17 @@ '\n' 'The grammar for a replacement field is as follows:\n' '\n' - ' replacement_field ::= "{" [field_name] ["!" ' - 'conversion] [":" format_spec] "}"\n' - ' field_name ::= arg_name ("." attribute_name | ' - '"[" element_index "]")*\n' - ' arg_name ::= [identifier | digit+]\n' - ' attribute_name ::= identifier\n' - ' element_index ::= digit+ | index_string\n' - ' index_string ::= +\n' - ' conversion ::= "r" | "s" | "a"\n' - ' format_spec ::= \n' + ' replacement_field ::= "{" [field_name] ["!" conversion] ' + '[":" format_spec] "}"\n' + ' field_name ::= arg_name ("." attribute_name | "[" ' + 'element_index "]")*\n' + ' arg_name ::= [identifier | digit+]\n' + ' attribute_name ::= identifier\n' + ' element_index ::= digit+ | index_string\n' + ' index_string ::= ' + '+\n' + ' conversion ::= "r" | "s" | "a"\n' + ' format_spec ::= \n' '\n' 'In less formal terms, the replacement field can start with ' 'a\n' @@ -6136,22 +6578,26 @@ 'positional\n' 'argument, and if it’s a keyword, it refers to a named ' 'keyword\n' - 'argument. If the numerical arg_names in a format string ' - 'are 0, 1, 2,\n' - '… in sequence, they can all be omitted (not just some) and ' - 'the numbers\n' - '0, 1, 2, … will be automatically inserted in that order. ' - 'Because\n' - '*arg_name* is not quote-delimited, it is not possible to ' - 'specify\n' - 'arbitrary dictionary keys (e.g., the strings "\'10\'" or ' - '"\':-]\'") within\n' - 'a format string. The *arg_name* can be followed by any ' - 'number of index\n' - 'or attribute expressions. An expression of the form ' - '"\'.name\'" selects\n' - 'the named attribute using "getattr()", while an expression ' - 'of the form\n' + 'argument. An *arg_name* is treated as a number if a call ' + 'to\n' + '"str.isdecimal()" on the string would return true. If the ' + 'numerical\n' + 'arg_names in a format string are 0, 1, 2, … in sequence, ' + 'they can all\n' + 'be omitted (not just some) and the numbers 0, 1, 2, … will ' + 'be\n' + 'automatically inserted in that order. Because *arg_name* is ' + 'not quote-\n' + 'delimited, it is not possible to specify arbitrary ' + 'dictionary keys\n' + '(e.g., the strings "\'10\'" or "\':-]\'") within a format ' + 'string. The\n' + '*arg_name* can be followed by any number of index or ' + 'attribute\n' + 'expressions. An expression of the form "\'.name\'" selects ' + 'the named\n' + 'attribute using "getattr()", while an expression of the ' + 'form\n' '"\'[index]\'" does an index lookup using "__getitem__()".\n' '\n' 'Changed in version 3.1: The positional argument specifiers ' @@ -6294,43 +6740,37 @@ 'The meaning of the various alignment options is as ' 'follows:\n' '\n' - ' ' '+-----------+------------------------------------------------------------+\n' - ' | Option | ' + '| Option | ' 'Meaning ' '|\n' - ' ' '|===========|============================================================|\n' - ' | "\'<\'" | Forces the field to be left-aligned ' - 'within the available |\n' - ' | | space (this is the default for most ' + '| "\'<\'" | Forces the field to be left-aligned within ' + 'the available |\n' + '| | space (this is the default for most ' 'objects). |\n' - ' ' '+-----------+------------------------------------------------------------+\n' - ' | "\'>\'" | Forces the field to be right-aligned ' - 'within the available |\n' - ' | | space (this is the default for ' + '| "\'>\'" | Forces the field to be right-aligned within ' + 'the available |\n' + '| | space (this is the default for ' 'numbers). |\n' - ' ' '+-----------+------------------------------------------------------------+\n' - ' | "\'=\'" | Forces the padding to be placed after ' - 'the sign (if any) |\n' - ' | | but before the digits. This is used for ' + '| "\'=\'" | Forces the padding to be placed after the ' + 'sign (if any) |\n' + '| | but before the digits. This is used for ' 'printing fields |\n' - ' | | in the form ‘+000000120’. This alignment ' + '| | in the form ‘+000000120’. This alignment ' 'option is only |\n' - ' | | valid for numeric types. It becomes the ' + '| | valid for numeric types. It becomes the ' 'default for |\n' - ' | | numbers when ‘0’ immediately precedes the ' + '| | numbers when ‘0’ immediately precedes the ' 'field width. |\n' - ' ' '+-----------+------------------------------------------------------------+\n' - ' | "\'^\'" | Forces the field to be centered within ' - 'the available |\n' - ' | | ' + '| "\'^\'" | Forces the field to be centered within the ' + 'available |\n' + '| | ' 'space. ' '|\n' - ' ' '+-----------+------------------------------------------------------------+\n' '\n' 'Note that unless a minimum field width is defined, the ' @@ -6343,30 +6783,25 @@ 'be one of\n' 'the following:\n' '\n' - ' ' '+-----------+------------------------------------------------------------+\n' - ' | Option | ' + '| Option | ' 'Meaning ' '|\n' - ' ' '|===========|============================================================|\n' - ' | "\'+\'" | indicates that a sign should be used for ' + '| "\'+\'" | indicates that a sign should be used for ' 'both positive as |\n' - ' | | well as negative ' + '| | well as negative ' 'numbers. |\n' - ' ' '+-----------+------------------------------------------------------------+\n' - ' | "\'-\'" | indicates that a sign should be used ' - 'only for negative |\n' - ' | | numbers (this is the default ' + '| "\'-\'" | indicates that a sign should be used only ' + 'for negative |\n' + '| | numbers (this is the default ' 'behavior). |\n' - ' ' '+-----------+------------------------------------------------------------+\n' - ' | space | indicates that a leading space should be ' - 'used on positive |\n' - ' | | numbers, and a minus sign on negative ' + '| space | indicates that a leading space should be used ' + 'on positive |\n' + '| | numbers, and a minus sign on negative ' 'numbers. |\n' - ' ' '+-----------+------------------------------------------------------------+\n' '\n' 'The "\'z\'" option coerces negative zero floating-point ' @@ -6872,8 +7307,8 @@ '(see\n' 'section The standard type hierarchy):\n' '\n' - ' funcdef ::= [decorators] "def" funcname "(" ' - '[parameter_list] ")"\n' + ' funcdef ::= [decorators] "def" funcname ' + '[type_params] "(" [parameter_list] ")"\n' ' ["->" expression] ":" suite\n' ' decorators ::= decorator+\n' ' decorator ::= "@" assignment_expression ' @@ -6935,6 +7370,19 @@ '"assignment_expression". Previously, the grammar was much more\n' 'restrictive; see **PEP 614** for details.\n' '\n' + 'A list of type parameters may be given in square brackets ' + 'between the\n' + 'function’s name and the opening parenthesis for its parameter ' + 'list.\n' + 'This indicates to static type checkers that the function is ' + 'generic.\n' + 'At runtime, the type parameters can be retrieved from the ' + 'function’s\n' + '"__type_params__" attribute. See Generic functions for more.\n' + '\n' + 'Changed in version 3.12: Type parameter lists are new in Python ' + '3.12.\n' + '\n' 'When one or more *parameters* have the form *parameter* "="\n' '*expression*, the function is said to have “default parameter ' 'values.â€\n' @@ -7248,8 +7696,8 @@ '\n' 'A non-normative HTML file listing all valid identifier ' 'characters for\n' - 'Unicode 15.0.0 can be found at\n' - 'https://www.unicode.org/Public/15.0.0/ucd/DerivedCoreProperties.txt\n' + 'Unicode 15.1.0 can be found at\n' + 'https://www.unicode.org/Public/15.1.0/ucd/DerivedCoreProperties.txt\n' '\n' '\n' 'Keywords\n' @@ -7277,19 +7725,24 @@ '\n' 'Some identifiers are only reserved under specific contexts. ' 'These are\n' - 'known as *soft keywords*. The identifiers "match", "case" ' - 'and "_" can\n' - 'syntactically act as keywords in contexts related to the ' - 'pattern\n' - 'matching statement, but this distinction is done at the ' - 'parser level,\n' - 'not when tokenizing.\n' + 'known as *soft keywords*. The identifiers "match", "case", ' + '"type" and\n' + '"_" can syntactically act as keywords in certain contexts, ' + 'but this\n' + 'distinction is done at the parser level, not when ' + 'tokenizing.\n' + '\n' + 'As soft keywords, their use in the grammar is possible while ' + 'still\n' + 'preserving compatibility with existing code that uses these ' + 'names as\n' + 'identifier names.\n' + '\n' + '"match", "case", and "_" are used in the "match" statement. ' + '"type" is\n' + 'used in the "type" statement.\n' '\n' - 'As soft keywords, their use with pattern matching is possible ' - 'while\n' - 'still preserving compatibility with existing code that uses ' - '"match",\n' - '"case" and "_" as identifier names.\n' + 'Changed in version 3.12: "type" is now a soft keyword.\n' '\n' '\n' 'Reserved classes of identifiers\n' @@ -7809,6 +8262,10 @@ '\n' '* "import" statements.\n' '\n' + '* "type" statements.\n' + '\n' + '* type parameter lists.\n' + '\n' 'The "import" statement of the form "from ... import *" binds all ' 'names\n' 'defined in the imported module, except those beginning with an\n' @@ -7908,7 +8365,8 @@ 'scope.\n' '"SyntaxError" is raised at compile time if the given name does ' 'not\n' - 'exist in any enclosing function scope.\n' + 'exist in any enclosing function scope. Type parameters cannot be\n' + 'rebound with the "nonlocal" statement.\n' '\n' 'The namespace for a module is automatically created the first time ' 'a\n' @@ -7930,18 +8388,156 @@ 'of\n' 'the class. The scope of names defined in a class block is limited ' 'to\n' - 'the class block; it does not extend to the code blocks of methods ' - '–\n' - 'this includes comprehensions and generator expressions since they ' - 'are\n' - 'implemented using a function scope. This means that the ' - 'following\n' - 'will fail:\n' + 'the class block; it does not extend to the code blocks of ' + 'methods.\n' + 'This includes comprehensions and generator expressions, but it ' + 'does\n' + 'not include annotation scopes, which have access to their ' + 'enclosing\n' + 'class scopes. This means that the following will fail:\n' '\n' ' class A:\n' ' a = 42\n' ' b = list(a + i for i in range(10))\n' '\n' + 'However, the following will succeed:\n' + '\n' + ' class A:\n' + ' type Alias = Nested\n' + ' class Nested: pass\n' + '\n' + " print(A.Alias.__value__) # \n" + '\n' + '\n' + 'Annotation scopes\n' + '=================\n' + '\n' + 'Type parameter lists and "type" statements introduce *annotation\n' + 'scopes*, which behave mostly like function scopes, but with some\n' + 'exceptions discussed below. *Annotations* currently do not use\n' + 'annotation scopes, but they are expected to use annotation scopes ' + 'in\n' + 'Python 3.13 when **PEP 649** is implemented.\n' + '\n' + 'Annotation scopes are used in the following contexts:\n' + '\n' + '* Type parameter lists for generic type aliases.\n' + '\n' + '* Type parameter lists for generic functions. A generic ' + 'function’s\n' + ' annotations are executed within the annotation scope, but its\n' + ' defaults and decorators are not.\n' + '\n' + '* Type parameter lists for generic classes. A generic class’s ' + 'base\n' + ' classes and keyword arguments are executed within the ' + 'annotation\n' + ' scope, but its decorators are not.\n' + '\n' + '* The bounds and constraints for type variables (lazily ' + 'evaluated).\n' + '\n' + '* The value of type aliases (lazily evaluated).\n' + '\n' + 'Annotation scopes differ from function scopes in the following ' + 'ways:\n' + '\n' + '* Annotation scopes have access to their enclosing class ' + 'namespace. If\n' + ' an annotation scope is immediately within a class scope, or ' + 'within\n' + ' another annotation scope that is immediately within a class ' + 'scope,\n' + ' the code in the annotation scope can use names defined in the ' + 'class\n' + ' scope as if it were executed directly within the class body. ' + 'This\n' + ' contrasts with regular functions defined within classes, which\n' + ' cannot access names defined in the class scope.\n' + '\n' + '* Expressions in annotation scopes cannot contain "yield", "yield\n' + ' from", "await", or ":=" expressions. (These expressions are ' + 'allowed\n' + ' in other scopes contained within the annotation scope.)\n' + '\n' + '* Names defined in annotation scopes cannot be rebound with ' + '"nonlocal"\n' + ' statements in inner scopes. This includes only type parameters, ' + 'as\n' + ' no other syntactic elements that can appear within annotation ' + 'scopes\n' + ' can introduce new names.\n' + '\n' + '* While annotation scopes have an internal name, that name is not\n' + ' reflected in the *__qualname__* of objects defined within the ' + 'scope.\n' + ' Instead, the "__qualname__" of such objects is as if the object ' + 'were\n' + ' defined in the enclosing scope.\n' + '\n' + 'New in version 3.12: Annotation scopes were introduced in Python ' + '3.12\n' + 'as part of **PEP 695**.\n' + '\n' + '\n' + 'Lazy evaluation\n' + '===============\n' + '\n' + 'The values of type aliases created through the "type" statement ' + 'are\n' + '*lazily evaluated*. The same applies to the bounds and constraints ' + 'of\n' + 'type variables created through the type parameter syntax. This ' + 'means\n' + 'that they are not evaluated when the type alias or type variable ' + 'is\n' + 'created. Instead, they are only evaluated when doing so is ' + 'necessary\n' + 'to resolve an attribute access.\n' + '\n' + 'Example:\n' + '\n' + ' >>> type Alias = 1/0\n' + ' >>> Alias.__value__\n' + ' Traceback (most recent call last):\n' + ' ...\n' + ' ZeroDivisionError: division by zero\n' + ' >>> def func[T: 1/0](): pass\n' + ' >>> T = func.__type_params__[0]\n' + ' >>> T.__bound__\n' + ' Traceback (most recent call last):\n' + ' ...\n' + ' ZeroDivisionError: division by zero\n' + '\n' + 'Here the exception is raised only when the "__value__" attribute ' + 'of\n' + 'the type alias or the "__bound__" attribute of the type variable ' + 'is\n' + 'accessed.\n' + '\n' + 'This behavior is primarily useful for references to types that ' + 'have\n' + 'not yet been defined when the type alias or type variable is ' + 'created.\n' + 'For example, lazy evaluation enables creation of mutually ' + 'recursive\n' + 'type aliases:\n' + '\n' + ' from typing import Literal\n' + '\n' + ' type SimpleExpr = int | Parenthesized\n' + ' type Parenthesized = tuple[Literal["("], Expr, Literal[")"]]\n' + ' type Expr = SimpleExpr | tuple[SimpleExpr, Literal["+", "-"], ' + 'Expr]\n' + '\n' + 'Lazily evaluated values are evaluated in annotation scope, which ' + 'means\n' + 'that names that appear inside the lazily evaluated value are ' + 'looked up\n' + 'as if they were used in the immediately enclosing scope.\n' + '\n' + 'New in version 3.12.\n' + '\n' '\n' 'Builtins and restricted execution\n' '=================================\n' @@ -9105,6 +9701,14 @@ '\n' ' New in version 3.3.\n' '\n' + 'definition.__type_params__\n' + '\n' + ' The type parameters of generic classes, functions, and ' + 'type\n' + ' aliases.\n' + '\n' + ' New in version 3.12.\n' + '\n' 'class.__mro__\n' '\n' ' This attribute is a tuple of classes that are considered ' @@ -9128,7 +9732,8 @@ ' still alive. The list is in definition order. Example:\n' '\n' ' >>> int.__subclasses__()\n' - " []\n", + " [, , , " + "]\n", 'specialnames': 'Special method names\n' '********************\n' '\n' @@ -9661,7 +10266,7 @@ 'would have\n' ' no way to access other attributes of the instance. Note ' 'that at\n' - ' least for instance variables, you can fake total control ' + ' least for instance variables, you can take total control ' 'by not\n' ' inserting any values in the instance attribute dictionary ' '(but\n' @@ -10019,9 +10624,7 @@ 'each\n' ' instance.\n' '\n' - '\n' - 'Notes on using *__slots__*\n' - '~~~~~~~~~~~~~~~~~~~~~~~~~~\n' + 'Notes on using *__slots__*:\n' '\n' '* When inheriting from a class without *__slots__*, the ' '"__dict__" and\n' @@ -11951,13 +12554,19 @@ '\n' ' New in version 3.9.\n' '\n' - 'str.replace(old, new[, count])\n' + 'str.replace(old, new, count=-1)\n' '\n' ' Return a copy of the string with all occurrences of ' 'substring *old*\n' - ' replaced by *new*. If the optional argument *count* is ' - 'given, only\n' - ' the first *count* occurrences are replaced.\n' + ' replaced by *new*. If *count* is given, only the first ' + '*count*\n' + ' occurrences are replaced. If *count* is not specified ' + 'or "-1", then\n' + ' all occurrences are replaced.\n' + '\n' + ' Changed in version 3.13: *count* is now supported as a ' + 'keyword\n' + ' argument.\n' '\n' 'str.rfind(sub[, start[, end]])\n' '\n' @@ -11997,7 +12606,7 @@ 'followed by\n' ' the string itself.\n' '\n' - 'str.rsplit(sep=None, maxsplit=- 1)\n' + 'str.rsplit(sep=None, maxsplit=-1)\n' '\n' ' Return a list of the words in the string, using *sep* ' 'as the\n' @@ -12038,7 +12647,7 @@ " >>> 'Monty Python'.removesuffix(' Python')\n" " 'Monty'\n" '\n' - 'str.split(sep=None, maxsplit=- 1)\n' + 'str.split(sep=None, maxsplit=-1)\n' '\n' ' Return a list of the words in the string, using *sep* ' 'as the\n' @@ -12448,77 +13057,81 @@ 'the\n' 'literal, i.e. either "\'" or """.)\n' '\n' + '\n' + 'Escape sequences\n' + '================\n' + '\n' 'Unless an "\'r\'" or "\'R\'" prefix is present, escape sequences ' 'in string\n' 'and bytes literals are interpreted according to rules similar to ' 'those\n' 'used by Standard C. The recognized escape sequences are:\n' '\n' - '+-------------------+-----------------------------------+---------+\n' - '| Escape Sequence | Meaning | Notes ' - '|\n' - '|===================|===================================|=========|\n' - '| "\\" | Backslash and newline ignored | ' - '(1) |\n' - '+-------------------+-----------------------------------+---------+\n' - '| "\\\\" | Backslash ("\\") ' - '| |\n' - '+-------------------+-----------------------------------+---------+\n' - '| "\\\'" | Single quote ("\'") ' + '+---------------------------+-----------------------------------+---------+\n' + '| Escape Sequence | Meaning | ' + 'Notes |\n' + '|===========================|===================================|=========|\n' + '| "\\" | Backslash and newline ignored ' + '| (1) |\n' + '+---------------------------+-----------------------------------+---------+\n' + '| "\\\\" | Backslash ' + '("\\") | |\n' + '+---------------------------+-----------------------------------+---------+\n' + '| "\\\'" | Single quote ' + '("\'") | |\n' + '+---------------------------+-----------------------------------+---------+\n' + '| "\\"" | Double quote (""") ' '| |\n' - '+-------------------+-----------------------------------+---------+\n' - '| "\\"" | Double quote (""") ' + '+---------------------------+-----------------------------------+---------+\n' + '| "\\a" | ASCII Bell (BEL) ' '| |\n' - '+-------------------+-----------------------------------+---------+\n' - '| "\\a" | ASCII Bell (BEL) ' + '+---------------------------+-----------------------------------+---------+\n' + '| "\\b" | ASCII Backspace (BS) ' '| |\n' - '+-------------------+-----------------------------------+---------+\n' - '| "\\b" | ASCII Backspace (BS) ' + '+---------------------------+-----------------------------------+---------+\n' + '| "\\f" | ASCII Formfeed (FF) ' '| |\n' - '+-------------------+-----------------------------------+---------+\n' - '| "\\f" | ASCII Formfeed (FF) ' + '+---------------------------+-----------------------------------+---------+\n' + '| "\\n" | ASCII Linefeed (LF) ' '| |\n' - '+-------------------+-----------------------------------+---------+\n' - '| "\\n" | ASCII Linefeed (LF) ' + '+---------------------------+-----------------------------------+---------+\n' + '| "\\r" | ASCII Carriage Return (CR) ' '| |\n' - '+-------------------+-----------------------------------+---------+\n' - '| "\\r" | ASCII Carriage Return (CR) ' + '+---------------------------+-----------------------------------+---------+\n' + '| "\\t" | ASCII Horizontal Tab (TAB) ' '| |\n' - '+-------------------+-----------------------------------+---------+\n' - '| "\\t" | ASCII Horizontal Tab (TAB) ' + '+---------------------------+-----------------------------------+---------+\n' + '| "\\v" | ASCII Vertical Tab (VT) ' '| |\n' - '+-------------------+-----------------------------------+---------+\n' - '| "\\v" | ASCII Vertical Tab (VT) ' - '| |\n' - '+-------------------+-----------------------------------+---------+\n' - '| "\\ooo" | Character with octal value *ooo* | ' - '(2,4) |\n' - '+-------------------+-----------------------------------+---------+\n' - '| "\\xhh" | Character with hex value *hh* | ' - '(3,4) |\n' - '+-------------------+-----------------------------------+---------+\n' + '+---------------------------+-----------------------------------+---------+\n' + '| "\\*ooo*" | Character with octal value *ooo* ' + '| (2,4) |\n' + '+---------------------------+-----------------------------------+---------+\n' + '| "\\x*hh*" | Character with hex value *hh* ' + '| (3,4) |\n' + '+---------------------------+-----------------------------------+---------+\n' '\n' 'Escape sequences only recognized in string literals are:\n' '\n' - '+-------------------+-----------------------------------+---------+\n' - '| Escape Sequence | Meaning | Notes ' - '|\n' - '|===================|===================================|=========|\n' - '| "\\N{name}" | Character named *name* in the | ' - '(5) |\n' - '| | Unicode database | ' - '|\n' - '+-------------------+-----------------------------------+---------+\n' - '| "\\uxxxx" | Character with 16-bit hex value | ' - '(6) |\n' - '| | *xxxx* | ' - '|\n' - '+-------------------+-----------------------------------+---------+\n' - '| "\\Uxxxxxxxx" | Character with 32-bit hex value | ' - '(7) |\n' - '| | *xxxxxxxx* | ' - '|\n' - '+-------------------+-----------------------------------+---------+\n' + '+---------------------------+-----------------------------------+---------+\n' + '| Escape Sequence | Meaning | ' + 'Notes |\n' + '|===========================|===================================|=========|\n' + '| "\\N{*name*}" | Character named *name* in the ' + '| (5) |\n' + '| | Unicode database ' + '| |\n' + '+---------------------------+-----------------------------------+---------+\n' + '| "\\u*xxxx*" | Character with 16-bit hex value ' + '| (6) |\n' + '| | *xxxx* ' + '| |\n' + '+---------------------------+-----------------------------------+---------+\n' + '| "\\U*xxxxxxxx*" | Character with 32-bit hex value ' + '| (7) |\n' + '| | *xxxxxxxx* ' + '| |\n' + '+---------------------------+-----------------------------------+---------+\n' '\n' 'Notes:\n' '\n' @@ -12575,15 +13188,13 @@ 'bytes\n' 'literals.\n' '\n' - ' Changed in version 3.6: Unrecognized escape sequences produce ' - 'a\n' - ' "DeprecationWarning".\n' + 'Changed in version 3.6: Unrecognized escape sequences produce a\n' + '"DeprecationWarning".\n' '\n' - ' Changed in version 3.12: Unrecognized escape sequences produce ' - 'a\n' - ' "SyntaxWarning". In a future Python version they will be ' - 'eventually\n' - ' a "SyntaxError".\n' + 'Changed in version 3.12: Unrecognized escape sequences produce a\n' + '"SyntaxWarning". In a future Python version they will be ' + 'eventually a\n' + '"SyntaxError".\n' '\n' 'Even in a raw literal, quotes can be escaped with a backslash, ' 'but the\n' @@ -12697,7 +13308,7 @@ 'are\n' 'most of the built-in objects considered false:\n' '\n' - '* constants defined to be false: "None" and "False".\n' + '* constants defined to be false: "None" and "False"\n' '\n' '* zero of any numeric type: "0", "0.0", "0j", "Decimal(0)",\n' ' "Fraction(0, 1)"\n' @@ -12978,1144 +13589,1191 @@ 'definition\n' 'may change in the future.\n' '\n' + '\n' 'None\n' - ' This type has a single value. There is a single object with ' - 'this\n' - ' value. This object is accessed through the built-in name "None". ' - 'It\n' - ' is used to signify the absence of a value in many situations, ' - 'e.g.,\n' - ' it is returned from functions that don’t explicitly return\n' - ' anything. Its truth value is false.\n' + '====\n' + '\n' + 'This type has a single value. There is a single object with this\n' + 'value. This object is accessed through the built-in name "None". It ' + 'is\n' + 'used to signify the absence of a value in many situations, e.g., it ' + 'is\n' + 'returned from functions that don’t explicitly return anything. Its\n' + 'truth value is false.\n' + '\n' '\n' 'NotImplemented\n' - ' This type has a single value. There is a single object with ' - 'this\n' - ' value. This object is accessed through the built-in name\n' - ' "NotImplemented". Numeric methods and rich comparison methods\n' - ' should return this value if they do not implement the operation ' - 'for\n' - ' the operands provided. (The interpreter will then try the\n' - ' reflected operation, or some other fallback, depending on the\n' - ' operator.) It should not be evaluated in a boolean context.\n' + '==============\n' + '\n' + 'This type has a single value. There is a single object with this\n' + 'value. This object is accessed through the built-in name\n' + '"NotImplemented". Numeric methods and rich comparison methods ' + 'should\n' + 'return this value if they do not implement the operation for the\n' + 'operands provided. (The interpreter will then try the reflected\n' + 'operation, or some other fallback, depending on the operator.) It\n' + 'should not be evaluated in a boolean context.\n' '\n' - ' See Implementing the arithmetic operations for more details.\n' + 'See Implementing the arithmetic operations for more details.\n' + '\n' + 'Changed in version 3.9: Evaluating "NotImplemented" in a boolean\n' + 'context is deprecated. While it currently evaluates as true, it ' + 'will\n' + 'emit a "DeprecationWarning". It will raise a "TypeError" in a ' + 'future\n' + 'version of Python.\n' '\n' - ' Changed in version 3.9: Evaluating "NotImplemented" in a ' - 'boolean\n' - ' context is deprecated. While it currently evaluates as true, it\n' - ' will emit a "DeprecationWarning". It will raise a "TypeError" in ' - 'a\n' - ' future version of Python.\n' '\n' 'Ellipsis\n' - ' This type has a single value. There is a single object with ' - 'this\n' - ' value. This object is accessed through the literal "..." or the\n' - ' built-in name "Ellipsis". Its truth value is true.\n' + '========\n' '\n' - '"numbers.Number"\n' - ' These are created by numeric literals and returned as results ' - 'by\n' - ' arithmetic operators and arithmetic built-in functions. ' - 'Numeric\n' - ' objects are immutable; once created their value never changes.\n' - ' Python numbers are of course strongly related to mathematical\n' - ' numbers, but subject to the limitations of numerical ' - 'representation\n' - ' in computers.\n' - '\n' - ' The string representations of the numeric classes, computed by\n' - ' "__repr__()" and "__str__()", have the following properties:\n' - '\n' - ' * They are valid numeric literals which, when passed to their ' - 'class\n' - ' constructor, produce an object having the value of the ' - 'original\n' - ' numeric.\n' + 'This type has a single value. There is a single object with this\n' + 'value. This object is accessed through the literal "..." or the ' + 'built-\n' + 'in name "Ellipsis". Its truth value is true.\n' '\n' - ' * The representation is in base 10, when possible.\n' '\n' - ' * Leading zeros, possibly excepting a single zero before a ' - 'decimal\n' - ' point, are not shown.\n' + '"numbers.Number"\n' + '================\n' '\n' - ' * Trailing zeros, possibly excepting a single zero after a ' - 'decimal\n' - ' point, are not shown.\n' + 'These are created by numeric literals and returned as results by\n' + 'arithmetic operators and arithmetic built-in functions. Numeric\n' + 'objects are immutable; once created their value never changes. ' + 'Python\n' + 'numbers are of course strongly related to mathematical numbers, ' + 'but\n' + 'subject to the limitations of numerical representation in ' + 'computers.\n' '\n' - ' * A sign is shown only when the number is negative.\n' + 'The string representations of the numeric classes, computed by\n' + '"__repr__()" and "__str__()", have the following properties:\n' '\n' - ' Python distinguishes between integers, floating point numbers, ' - 'and\n' - ' complex numbers:\n' + '* They are valid numeric literals which, when passed to their ' + 'class\n' + ' constructor, produce an object having the value of the original\n' + ' numeric.\n' '\n' - ' "numbers.Integral"\n' - ' These represent elements from the mathematical set of ' - 'integers\n' - ' (positive and negative).\n' + '* The representation is in base 10, when possible.\n' '\n' - ' There are two types of integers:\n' + '* Leading zeros, possibly excepting a single zero before a decimal\n' + ' point, are not shown.\n' '\n' - ' Integers ("int")\n' - ' These represent numbers in an unlimited range, subject to\n' - ' available (virtual) memory only. For the purpose of ' - 'shift\n' - ' and mask operations, a binary representation is assumed, ' - 'and\n' - ' negative numbers are represented in a variant of 2’s\n' - ' complement which gives the illusion of an infinite string ' - 'of\n' - ' sign bits extending to the left.\n' + '* Trailing zeros, possibly excepting a single zero after a decimal\n' + ' point, are not shown.\n' '\n' - ' Booleans ("bool")\n' - ' These represent the truth values False and True. The two\n' - ' objects representing the values "False" and "True" are ' - 'the\n' - ' only Boolean objects. The Boolean type is a subtype of ' + '* A sign is shown only when the number is negative.\n' + '\n' + 'Python distinguishes between integers, floating point numbers, and\n' + 'complex numbers:\n' + '\n' + '\n' + '"numbers.Integral"\n' + '------------------\n' + '\n' + 'These represent elements from the mathematical set of integers\n' + '(positive and negative).\n' + '\n' + 'Note:\n' + '\n' + ' The rules for integer representation are intended to give the ' + 'most\n' + ' meaningful interpretation of shift and mask operations involving\n' + ' negative integers.\n' + '\n' + 'There are two types of integers:\n' + '\n' + 'Integers ("int")\n' + ' These represent numbers in an unlimited range, subject to ' + 'available\n' + ' (virtual) memory only. For the purpose of shift and mask\n' + ' operations, a binary representation is assumed, and negative\n' + ' numbers are represented in a variant of 2’s complement which ' + 'gives\n' + ' the illusion of an infinite string of sign bits extending to ' 'the\n' - ' integer type, and Boolean values behave like the values 0 ' - 'and\n' - ' 1, respectively, in almost all contexts, the exception ' - 'being\n' - ' that when converted to a string, the strings ""False"" or\n' - ' ""True"" are returned, respectively.\n' + ' left.\n' + '\n' + 'Booleans ("bool")\n' + ' These represent the truth values False and True. The two ' + 'objects\n' + ' representing the values "False" and "True" are the only Boolean\n' + ' objects. The Boolean type is a subtype of the integer type, and\n' + ' Boolean values behave like the values 0 and 1, respectively, in\n' + ' almost all contexts, the exception being that when converted to ' + 'a\n' + ' string, the strings ""False"" or ""True"" are returned,\n' + ' respectively.\n' + '\n' '\n' - ' The rules for integer representation are intended to give ' + '"numbers.Real" ("float")\n' + '------------------------\n' + '\n' + 'These represent machine-level double precision floating point ' + 'numbers.\n' + 'You are at the mercy of the underlying machine architecture (and C ' + 'or\n' + 'Java implementation) for the accepted range and handling of ' + 'overflow.\n' + 'Python does not support single-precision floating point numbers; ' 'the\n' - ' most meaningful interpretation of shift and mask operations\n' - ' involving negative integers.\n' - '\n' - ' "numbers.Real" ("float")\n' - ' These represent machine-level double precision floating ' - 'point\n' - ' numbers. You are at the mercy of the underlying machine\n' - ' architecture (and C or Java implementation) for the accepted\n' - ' range and handling of overflow. Python does not support ' - 'single-\n' - ' precision floating point numbers; the savings in processor ' - 'and\n' - ' memory usage that are usually the reason for using these are\n' - ' dwarfed by the overhead of using objects in Python, so there ' - 'is\n' - ' no reason to complicate the language with two kinds of ' - 'floating\n' - ' point numbers.\n' - '\n' - ' "numbers.Complex" ("complex")\n' - ' These represent complex numbers as a pair of machine-level\n' - ' double precision floating point numbers. The same caveats ' - 'apply\n' - ' as for floating point numbers. The real and imaginary parts ' - 'of a\n' - ' complex number "z" can be retrieved through the read-only\n' - ' attributes "z.real" and "z.imag".\n' + 'savings in processor and memory usage that are usually the reason ' + 'for\n' + 'using these are dwarfed by the overhead of using objects in Python, ' + 'so\n' + 'there is no reason to complicate the language with two kinds of\n' + 'floating point numbers.\n' + '\n' + '\n' + '"numbers.Complex" ("complex")\n' + '-----------------------------\n' + '\n' + 'These represent complex numbers as a pair of machine-level double\n' + 'precision floating point numbers. The same caveats apply as for\n' + 'floating point numbers. The real and imaginary parts of a complex\n' + 'number "z" can be retrieved through the read-only attributes ' + '"z.real"\n' + 'and "z.imag".\n' + '\n' '\n' 'Sequences\n' - ' These represent finite ordered sets indexed by non-negative\n' - ' numbers. The built-in function "len()" returns the number of ' - 'items\n' - ' of a sequence. When the length of a sequence is *n*, the index ' + '=========\n' + '\n' + 'These represent finite ordered sets indexed by non-negative ' + 'numbers.\n' + 'The built-in function "len()" returns the number of items of a\n' + 'sequence. When the length of a sequence is *n*, the index set ' + 'contains\n' + 'the numbers 0, 1, …, *n*-1. Item *i* of sequence *a* is selected ' + 'by\n' + '"a[i]".\n' + '\n' + 'Sequences also support slicing: "a[i:j]" selects all items with ' + 'index\n' + '*k* such that *i* "<=" *k* "<" *j*. When used as an expression, a\n' + 'slice is a sequence of the same type. This implies that the index ' 'set\n' - ' contains the numbers 0, 1, …, *n*-1. Item *i* of sequence *a* ' - 'is\n' - ' selected by "a[i]".\n' + 'is renumbered so that it starts at 0.\n' '\n' - ' Sequences also support slicing: "a[i:j]" selects all items with\n' - ' index *k* such that *i* "<=" *k* "<" *j*. When used as an\n' - ' expression, a slice is a sequence of the same type. This ' - 'implies\n' - ' that the index set is renumbered so that it starts at 0.\n' + 'Some sequences also support “extended slicing†with a third “stepâ€\n' + 'parameter: "a[i:j:k]" selects all items of *a* with index *x* where ' + '"x\n' + '= i + n*k", *n* ">=" "0" and *i* "<=" *x* "<" *j*.\n' '\n' - ' Some sequences also support “extended slicing†with a third ' - '“stepâ€\n' - ' parameter: "a[i:j:k]" selects all items of *a* with index *x* ' - 'where\n' - ' "x = i + n*k", *n* ">=" "0" and *i* "<=" *x* "<" *j*.\n' + 'Sequences are distinguished according to their mutability:\n' '\n' - ' Sequences are distinguished according to their mutability:\n' '\n' - ' Immutable sequences\n' - ' An object of an immutable sequence type cannot change once it ' - 'is\n' - ' created. (If the object contains references to other ' - 'objects,\n' - ' these other objects may be mutable and may be changed; ' - 'however,\n' - ' the collection of objects directly referenced by an ' - 'immutable\n' - ' object cannot change.)\n' + 'Immutable sequences\n' + '-------------------\n' '\n' - ' The following types are immutable sequences:\n' + 'An object of an immutable sequence type cannot change once it is\n' + 'created. (If the object contains references to other objects, ' + 'these\n' + 'other objects may be mutable and may be changed; however, the\n' + 'collection of objects directly referenced by an immutable object\n' + 'cannot change.)\n' '\n' - ' Strings\n' - ' A string is a sequence of values that represent Unicode ' - 'code\n' - ' points. All the code points in the range "U+0000 - ' - 'U+10FFFF"\n' - ' can be represented in a string. Python doesn’t have a ' - 'char\n' - ' type; instead, every code point in the string is ' - 'represented\n' - ' as a string object with length "1". The built-in ' - 'function\n' - ' "ord()" converts a code point from its string form to an\n' - ' integer in the range "0 - 10FFFF"; "chr()" converts an\n' - ' integer in the range "0 - 10FFFF" to the corresponding ' - 'length\n' - ' "1" string object. "str.encode()" can be used to convert ' - 'a\n' - ' "str" to "bytes" using the given text encoding, and\n' - ' "bytes.decode()" can be used to achieve the opposite.\n' + 'The following types are immutable sequences:\n' '\n' - ' Tuples\n' - ' The items of a tuple are arbitrary Python objects. Tuples ' - 'of\n' - ' two or more items are formed by comma-separated lists of\n' - ' expressions. A tuple of one item (a ‘singleton’) can be\n' - ' formed by affixing a comma to an expression (an expression ' - 'by\n' - ' itself does not create a tuple, since parentheses must be\n' - ' usable for grouping of expressions). An empty tuple can ' + 'Strings\n' + ' A string is a sequence of values that represent Unicode code\n' + ' points. All the code points in the range "U+0000 - U+10FFFF" can ' 'be\n' - ' formed by an empty pair of parentheses.\n' - '\n' - ' Bytes\n' - ' A bytes object is an immutable array. The items are ' - '8-bit\n' - ' bytes, represented by integers in the range 0 <= x < 256.\n' - ' Bytes literals (like "b\'abc\'") and the built-in ' - '"bytes()"\n' - ' constructor can be used to create bytes objects. Also, ' - 'bytes\n' - ' objects can be decoded to strings via the "decode()" ' - 'method.\n' + ' represented in a string. Python doesn’t have a char type; ' + 'instead,\n' + ' every code point in the string is represented as a string ' + 'object\n' + ' with length "1". The built-in function "ord()" converts a code\n' + ' point from its string form to an integer in the range "0 - ' + '10FFFF";\n' + ' "chr()" converts an integer in the range "0 - 10FFFF" to the\n' + ' corresponding length "1" string object. "str.encode()" can be ' + 'used\n' + ' to convert a "str" to "bytes" using the given text encoding, ' + 'and\n' + ' "bytes.decode()" can be used to achieve the opposite.\n' '\n' - ' Mutable sequences\n' - ' Mutable sequences can be changed after they are created. ' - 'The\n' - ' subscription and slicing notations can be used as the target ' + 'Tuples\n' + ' The items of a tuple are arbitrary Python objects. Tuples of two ' + 'or\n' + ' more items are formed by comma-separated lists of expressions. ' + 'A\n' + ' tuple of one item (a ‘singleton’) can be formed by affixing a ' + 'comma\n' + ' to an expression (an expression by itself does not create a ' + 'tuple,\n' + ' since parentheses must be usable for grouping of expressions). ' + 'An\n' + ' empty tuple can be formed by an empty pair of parentheses.\n' + '\n' + 'Bytes\n' + ' A bytes object is an immutable array. The items are 8-bit ' + 'bytes,\n' + ' represented by integers in the range 0 <= x < 256. Bytes ' + 'literals\n' + ' (like "b\'abc\'") and the built-in "bytes()" constructor can be ' + 'used\n' + ' to create bytes objects. Also, bytes objects can be decoded to\n' + ' strings via the "decode()" method.\n' + '\n' + '\n' + 'Mutable sequences\n' + '-----------------\n' + '\n' + 'Mutable sequences can be changed after they are created. The\n' + 'subscription and slicing notations can be used as the target of\n' + 'assignment and "del" (delete) statements.\n' + '\n' + 'Note:\n' + '\n' + ' The "collections" and "array" module provide additional examples ' 'of\n' - ' assignment and "del" (delete) statements.\n' + ' mutable sequence types.\n' '\n' - ' There are currently two intrinsic mutable sequence types:\n' + 'There are currently two intrinsic mutable sequence types:\n' '\n' - ' Lists\n' - ' The items of a list are arbitrary Python objects. Lists ' - 'are\n' - ' formed by placing a comma-separated list of expressions ' - 'in\n' - ' square brackets. (Note that there are no special cases ' - 'needed\n' - ' to form lists of length 0 or 1.)\n' + 'Lists\n' + ' The items of a list are arbitrary Python objects. Lists are ' + 'formed\n' + ' by placing a comma-separated list of expressions in square\n' + ' brackets. (Note that there are no special cases needed to form\n' + ' lists of length 0 or 1.)\n' '\n' - ' Byte Arrays\n' - ' A bytearray object is a mutable array. They are created ' - 'by\n' - ' the built-in "bytearray()" constructor. Aside from being\n' - ' mutable (and hence unhashable), byte arrays otherwise ' - 'provide\n' - ' the same interface and functionality as immutable "bytes"\n' - ' objects.\n' + 'Byte Arrays\n' + ' A bytearray object is a mutable array. They are created by the\n' + ' built-in "bytearray()" constructor. Aside from being mutable ' + '(and\n' + ' hence unhashable), byte arrays otherwise provide the same ' + 'interface\n' + ' and functionality as immutable "bytes" objects.\n' '\n' - ' The extension module "array" provides an additional example ' - 'of a\n' - ' mutable sequence type, as does the "collections" module.\n' '\n' 'Set types\n' - ' These represent unordered, finite sets of unique, immutable\n' - ' objects. As such, they cannot be indexed by any subscript. ' - 'However,\n' - ' they can be iterated over, and the built-in function "len()"\n' - ' returns the number of items in a set. Common uses for sets are ' - 'fast\n' - ' membership testing, removing duplicates from a sequence, and\n' - ' computing mathematical operations such as intersection, union,\n' - ' difference, and symmetric difference.\n' - '\n' - ' For set elements, the same immutability rules apply as for\n' - ' dictionary keys. Note that numeric types obey the normal rules ' - 'for\n' - ' numeric comparison: if two numbers compare equal (e.g., "1" and\n' - ' "1.0"), only one of them can be contained in a set.\n' + '=========\n' '\n' - ' There are currently two intrinsic set types:\n' + 'These represent unordered, finite sets of unique, immutable ' + 'objects.\n' + 'As such, they cannot be indexed by any subscript. However, they can ' + 'be\n' + 'iterated over, and the built-in function "len()" returns the number ' + 'of\n' + 'items in a set. Common uses for sets are fast membership testing,\n' + 'removing duplicates from a sequence, and computing mathematical\n' + 'operations such as intersection, union, difference, and symmetric\n' + 'difference.\n' + '\n' + 'For set elements, the same immutability rules apply as for ' + 'dictionary\n' + 'keys. Note that numeric types obey the normal rules for numeric\n' + 'comparison: if two numbers compare equal (e.g., "1" and "1.0"), ' + 'only\n' + 'one of them can be contained in a set.\n' + '\n' + 'There are currently two intrinsic set types:\n' '\n' - ' Sets\n' - ' These represent a mutable set. They are created by the ' + 'Sets\n' + ' These represent a mutable set. They are created by the built-in\n' + ' "set()" constructor and can be modified afterwards by several\n' + ' methods, such as "add()".\n' + '\n' + 'Frozen sets\n' + ' These represent an immutable set. They are created by the ' 'built-in\n' - ' "set()" constructor and can be modified afterwards by ' - 'several\n' - ' methods, such as "add()".\n' - '\n' - ' Frozen sets\n' - ' These represent an immutable set. They are created by the\n' - ' built-in "frozenset()" constructor. As a frozenset is ' - 'immutable\n' - ' and *hashable*, it can be used again as an element of ' - 'another\n' - ' set, or as a dictionary key.\n' + ' "frozenset()" constructor. As a frozenset is immutable and\n' + ' *hashable*, it can be used again as an element of another set, ' + 'or\n' + ' as a dictionary key.\n' + '\n' '\n' 'Mappings\n' - ' These represent finite sets of objects indexed by arbitrary ' - 'index\n' - ' sets. The subscript notation "a[k]" selects the item indexed by ' + '========\n' + '\n' + 'These represent finite sets of objects indexed by arbitrary index\n' + 'sets. The subscript notation "a[k]" selects the item indexed by ' '"k"\n' - ' from the mapping "a"; this can be used in expressions and as ' - 'the\n' - ' target of assignments or "del" statements. The built-in ' - 'function\n' - ' "len()" returns the number of items in a mapping.\n' + 'from the mapping "a"; this can be used in expressions and as the\n' + 'target of assignments or "del" statements. The built-in function\n' + '"len()" returns the number of items in a mapping.\n' '\n' - ' There is currently a single intrinsic mapping type:\n' + 'There is currently a single intrinsic mapping type:\n' '\n' - ' Dictionaries\n' - ' These represent finite sets of objects indexed by nearly\n' - ' arbitrary values. The only types of values not acceptable ' - 'as\n' - ' keys are values containing lists or dictionaries or other\n' - ' mutable types that are compared by value rather than by ' - 'object\n' - ' identity, the reason being that the efficient implementation ' - 'of\n' - ' dictionaries requires a key’s hash value to remain constant.\n' - ' Numeric types used for keys obey the normal rules for ' - 'numeric\n' - ' comparison: if two numbers compare equal (e.g., "1" and ' - '"1.0")\n' - ' then they can be used interchangeably to index the same\n' - ' dictionary entry.\n' - '\n' - ' Dictionaries preserve insertion order, meaning that keys will ' - 'be\n' - ' produced in the same order they were added sequentially over ' - 'the\n' - ' dictionary. Replacing an existing key does not change the ' - 'order,\n' - ' however removing a key and re-inserting it will add it to ' + '\n' + 'Dictionaries\n' + '------------\n' + '\n' + 'These represent finite sets of objects indexed by nearly arbitrary\n' + 'values. The only types of values not acceptable as keys are ' + 'values\n' + 'containing lists or dictionaries or other mutable types that are\n' + 'compared by value rather than by object identity, the reason being\n' + 'that the efficient implementation of dictionaries requires a key’s\n' + 'hash value to remain constant. Numeric types used for keys obey ' 'the\n' - ' end instead of keeping its old place.\n' + 'normal rules for numeric comparison: if two numbers compare equal\n' + '(e.g., "1" and "1.0") then they can be used interchangeably to ' + 'index\n' + 'the same dictionary entry.\n' '\n' - ' Dictionaries are mutable; they can be created by the "{...}"\n' - ' notation (see section Dictionary displays).\n' + 'Dictionaries preserve insertion order, meaning that keys will be\n' + 'produced in the same order they were added sequentially over the\n' + 'dictionary. Replacing an existing key does not change the order,\n' + 'however removing a key and re-inserting it will add it to the end\n' + 'instead of keeping its old place.\n' '\n' - ' The extension modules "dbm.ndbm" and "dbm.gnu" provide\n' - ' additional examples of mapping types, as does the ' - '"collections"\n' - ' module.\n' + 'Dictionaries are mutable; they can be created by the "{...}" ' + 'notation\n' + '(see section Dictionary displays).\n' + '\n' + 'The extension modules "dbm.ndbm" and "dbm.gnu" provide additional\n' + 'examples of mapping types, as does the "collections" module.\n' + '\n' + 'Changed in version 3.7: Dictionaries did not preserve insertion ' + 'order\n' + 'in versions of Python before 3.6. In CPython 3.6, insertion order ' + 'was\n' + 'preserved, but it was considered an implementation detail at that ' + 'time\n' + 'rather than a language guarantee.\n' '\n' - ' Changed in version 3.7: Dictionaries did not preserve ' - 'insertion\n' - ' order in versions of Python before 3.6. In CPython 3.6,\n' - ' insertion order was preserved, but it was considered an\n' - ' implementation detail at that time rather than a language\n' - ' guarantee.\n' '\n' 'Callable types\n' - ' These are the types to which the function call operation (see\n' - ' section Calls) can be applied:\n' + '==============\n' '\n' - ' User-defined functions\n' - ' A user-defined function object is created by a function\n' - ' definition (see section Function definitions). It should be\n' - ' called with an argument list containing the same number of ' - 'items\n' - ' as the function’s formal parameter list.\n' + 'These are the types to which the function call operation (see ' + 'section\n' + 'Calls) can be applied:\n' '\n' - ' Special attributes:\n' '\n' - ' ' + 'User-defined functions\n' + '----------------------\n' + '\n' + 'A user-defined function object is created by a function definition\n' + '(see section Function definitions). It should be called with an\n' + 'argument list containing the same number of items as the ' + 'function’s\n' + 'formal parameter list.\n' + '\n' + 'Special attributes:\n' + '\n' '+---------------------------+---------------------------------+-------------+\n' - ' | Attribute | Meaning ' + '| Attribute | Meaning ' '| |\n' - ' ' '|===========================|=================================|=============|\n' - ' | "__doc__" | The function’s documentation ' - '| Writable |\n' - ' | | string, or "None" if ' + '| "__doc__" | The function’s documentation | ' + 'Writable |\n' + '| | string, or "None" if ' '| |\n' - ' | | unavailable; not inherited by ' + '| | unavailable; not inherited by ' '| |\n' - ' | | subclasses. ' + '| | subclasses. ' '| |\n' - ' ' '+---------------------------+---------------------------------+-------------+\n' - ' | "__name__" | The function’s name. ' - '| Writable |\n' - ' ' + '| "__name__" | The function’s name. | ' + 'Writable |\n' '+---------------------------+---------------------------------+-------------+\n' - ' | "__qualname__" | The function’s *qualified ' - '| Writable |\n' - ' | | name*. New in version 3.3. ' + '| "__qualname__" | The function’s *qualified | ' + 'Writable |\n' + '| | name*. New in version 3.3. ' '| |\n' - ' ' '+---------------------------+---------------------------------+-------------+\n' - ' | "__module__" | The name of the module the ' - '| Writable |\n' - ' | | function was defined in, or ' + '| "__module__" | The name of the module the | ' + 'Writable |\n' + '| | function was defined in, or ' '| |\n' - ' | | "None" if unavailable. ' + '| | "None" if unavailable. ' '| |\n' - ' ' '+---------------------------+---------------------------------+-------------+\n' - ' | "__defaults__" | A tuple containing default ' - '| Writable |\n' - ' | | argument values for those ' + '| "__defaults__" | A tuple containing default | ' + 'Writable |\n' + '| | argument values for those ' '| |\n' - ' | | arguments that have defaults, ' + '| | arguments that have defaults, ' '| |\n' - ' | | or "None" if no arguments have ' + '| | or "None" if no arguments have ' '| |\n' - ' | | a default value. ' + '| | a default value. ' '| |\n' - ' ' '+---------------------------+---------------------------------+-------------+\n' - ' | "__code__" | The code object representing ' - '| Writable |\n' - ' | | the compiled function body. ' + '| "__code__" | The code object representing | ' + 'Writable |\n' + '| | the compiled function body. ' '| |\n' - ' ' '+---------------------------+---------------------------------+-------------+\n' - ' | "__globals__" | A reference to the dictionary ' - '| Read-only |\n' - ' | | that holds the function’s ' + '| "__globals__" | A reference to the dictionary | ' + 'Read-only |\n' + '| | that holds the function’s ' '| |\n' - ' | | global variables — the global ' + '| | global variables — the global ' '| |\n' - ' | | namespace of the module in ' + '| | namespace of the module in ' '| |\n' - ' | | which the function was defined. ' + '| | which the function was defined. ' '| |\n' - ' ' '+---------------------------+---------------------------------+-------------+\n' - ' | "__dict__" | The namespace supporting ' - '| Writable |\n' - ' | | arbitrary function attributes. ' + '| "__dict__" | The namespace supporting | ' + 'Writable |\n' + '| | arbitrary function attributes. ' '| |\n' - ' ' '+---------------------------+---------------------------------+-------------+\n' - ' | "__closure__" | "None" or a tuple of cells that ' - '| Read-only |\n' - ' | | contain bindings for the ' + '| "__closure__" | "None" or a tuple of cells that | ' + 'Read-only |\n' + '| | contain bindings for the ' '| |\n' - ' | | function’s free variables. See ' + '| | function’s free variables. See ' '| |\n' - ' | | below for information on the ' + '| | below for information on the ' '| |\n' - ' | | "cell_contents" attribute. ' + '| | "cell_contents" attribute. ' '| |\n' - ' ' '+---------------------------+---------------------------------+-------------+\n' - ' | "__annotations__" | A dict containing annotations ' - '| Writable |\n' - ' | | of parameters. The keys of the ' + '| "__annotations__" | A dict containing annotations | ' + 'Writable |\n' + '| | of parameters. The keys of the ' + '| |\n' + '| | dict are the parameter names, ' '| |\n' - ' | | dict are the parameter names, ' + '| | and "\'return\'" for the return ' '| |\n' - ' | | and "\'return\'" for the ' - 'return | |\n' - ' | | annotation, if provided. For ' + '| | annotation, if provided. For ' '| |\n' - ' | | more information on working ' + '| | more information on working ' '| |\n' - ' | | with this attribute, see ' + '| | with this attribute, see ' '| |\n' - ' | | Annotations Best Practices. ' + '| | Annotations Best Practices. ' '| |\n' - ' ' '+---------------------------+---------------------------------+-------------+\n' - ' | "__kwdefaults__" | A dict containing defaults for ' - '| Writable |\n' - ' | | keyword-only parameters. ' + '| "__kwdefaults__" | A dict containing defaults for | ' + 'Writable |\n' + '| | keyword-only parameters. ' + '| |\n' + '+---------------------------+---------------------------------+-------------+\n' + '| "__type_params__" | A tuple containing the type | ' + 'Writable |\n' + '| | parameters of a generic ' + '| |\n' + '| | function. ' '| |\n' - ' ' '+---------------------------+---------------------------------+-------------+\n' '\n' - ' Most of the attributes labelled “Writable†check the type of ' - 'the\n' - ' assigned value.\n' + 'Most of the attributes labelled “Writable†check the type of the\n' + 'assigned value.\n' '\n' - ' Function objects also support getting and setting arbitrary\n' - ' attributes, which can be used, for example, to attach ' - 'metadata\n' - ' to functions. Regular attribute dot-notation is used to get ' - 'and\n' - ' set such attributes. *Note that the current implementation ' - 'only\n' - ' supports function attributes on user-defined functions. ' - 'Function\n' - ' attributes on built-in functions may be supported in the\n' - ' future.*\n' - '\n' - ' A cell object has the attribute "cell_contents". This can be\n' - ' used to get the value of the cell, as well as set the value.\n' - '\n' - ' Additional information about a function’s definition can be\n' - ' retrieved from its code object; see the description of ' - 'internal\n' - ' types below. The "cell" type can be accessed in the "types"\n' - ' module.\n' - '\n' - ' Instance methods\n' - ' An instance method object combines a class, a class instance ' - 'and\n' - ' any callable object (normally a user-defined function).\n' - '\n' - ' Special read-only attributes: "__self__" is the class ' - 'instance\n' - ' object, "__func__" is the function object; "__doc__" is the\n' - ' method’s documentation (same as "__func__.__doc__"); ' - '"__name__"\n' - ' is the method name (same as "__func__.__name__"); ' - '"__module__"\n' - ' is the name of the module the method was defined in, or ' - '"None"\n' - ' if unavailable.\n' + 'Function objects also support getting and setting arbitrary\n' + 'attributes, which can be used, for example, to attach metadata to\n' + 'functions. Regular attribute dot-notation is used to get and set ' + 'such\n' + 'attributes. *Note that the current implementation only supports\n' + 'function attributes on user-defined functions. Function attributes ' + 'on\n' + 'built-in functions may be supported in the future.*\n' '\n' - ' Methods also support accessing (but not setting) the ' - 'arbitrary\n' - ' function attributes on the underlying function object.\n' + 'A cell object has the attribute "cell_contents". This can be used ' + 'to\n' + 'get the value of the cell, as well as set the value.\n' '\n' - ' User-defined method objects may be created when getting an\n' - ' attribute of a class (perhaps via an instance of that class), ' - 'if\n' - ' that attribute is a user-defined function object or a class\n' - ' method object.\n' - '\n' - ' When an instance method object is created by retrieving a ' - 'user-\n' - ' defined function object from a class via one of its ' - 'instances,\n' - ' its "__self__" attribute is the instance, and the method ' - 'object\n' - ' is said to be bound. The new method’s "__func__" attribute ' - 'is\n' - ' the original function object.\n' + 'Additional information about a function’s definition can be ' + 'retrieved\n' + 'from its code object; see the description of internal types below. ' + 'The\n' + '"cell" type can be accessed in the "types" module.\n' '\n' - ' When an instance method object is created by retrieving a ' - 'class\n' - ' method object from a class or instance, its "__self__" ' - 'attribute\n' - ' is the class itself, and its "__func__" attribute is the\n' - ' function object underlying the class method.\n' '\n' - ' When an instance method object is called, the underlying\n' - ' function ("__func__") is called, inserting the class ' - 'instance\n' - ' ("__self__") in front of the argument list. For instance, ' - 'when\n' - ' "C" is a class which contains a definition for a function ' - '"f()",\n' - ' and "x" is an instance of "C", calling "x.f(1)" is equivalent ' - 'to\n' - ' calling "C.f(x, 1)".\n' + 'Instance methods\n' + '----------------\n' '\n' - ' When an instance method object is derived from a class ' + 'An instance method object combines a class, a class instance and ' + 'any\n' + 'callable object (normally a user-defined function).\n' + '\n' + 'Special read-only attributes: "__self__" is the class instance ' + 'object,\n' + '"__func__" is the function object; "__doc__" is the method’s\n' + 'documentation (same as "__func__.__doc__"); "__name__" is the ' 'method\n' - ' object, the “class instance†stored in "__self__" will ' - 'actually\n' - ' be the class itself, so that calling either "x.f(1)" or ' - '"C.f(1)"\n' - ' is equivalent to calling "f(C,1)" where "f" is the ' - 'underlying\n' - ' function.\n' - '\n' - ' Note that the transformation from function object to ' - 'instance\n' - ' method object happens each time the attribute is retrieved ' - 'from\n' - ' the instance. In some cases, a fruitful optimization is to\n' - ' assign the attribute to a local variable and call that local\n' - ' variable. Also notice that this transformation only happens ' - 'for\n' - ' user-defined functions; other callable objects (and all non-\n' - ' callable objects) are retrieved without transformation. It ' - 'is\n' - ' also important to note that user-defined functions which are\n' - ' attributes of a class instance are not converted to bound\n' - ' methods; this *only* happens when the function is an ' + 'name (same as "__func__.__name__"); "__module__" is the name of ' + 'the\n' + 'module the method was defined in, or "None" if unavailable.\n' + '\n' + 'Methods also support accessing (but not setting) the arbitrary\n' + 'function attributes on the underlying function object.\n' + '\n' + 'User-defined method objects may be created when getting an ' + 'attribute\n' + 'of a class (perhaps via an instance of that class), if that ' 'attribute\n' - ' of the class.\n' + 'is a user-defined function object or a class method object.\n' '\n' - ' Generator functions\n' - ' A function or method which uses the "yield" statement (see\n' - ' section The yield statement) is called a *generator ' - 'function*.\n' - ' Such a function, when called, always returns an *iterator*\n' - ' object which can be used to execute the body of the ' - 'function:\n' - ' calling the iterator’s "iterator.__next__()" method will ' - 'cause\n' - ' the function to execute until it provides a value using the\n' - ' "yield" statement. When the function executes a "return"\n' - ' statement or falls off the end, a "StopIteration" exception ' - 'is\n' - ' raised and the iterator will have reached the end of the set ' + 'When an instance method object is created by retrieving a ' + 'user-defined\n' + 'function object from a class via one of its instances, its ' + '"__self__"\n' + 'attribute is the instance, and the method object is said to be ' + 'bound.\n' + 'The new method’s "__func__" attribute is the original function ' + 'object.\n' + '\n' + 'When an instance method object is created by retrieving a class ' + 'method\n' + 'object from a class or instance, its "__self__" attribute is the ' + 'class\n' + 'itself, and its "__func__" attribute is the function object ' + 'underlying\n' + 'the class method.\n' + '\n' + 'When an instance method object is called, the underlying function\n' + '("__func__") is called, inserting the class instance ("__self__") ' + 'in\n' + 'front of the argument list. For instance, when "C" is a class ' + 'which\n' + 'contains a definition for a function "f()", and "x" is an instance ' 'of\n' - ' values to be returned.\n' - '\n' - ' Coroutine functions\n' - ' A function or method which is defined using "async def" is\n' - ' called a *coroutine function*. Such a function, when ' - 'called,\n' - ' returns a *coroutine* object. It may contain "await"\n' - ' expressions, as well as "async with" and "async for" ' - 'statements.\n' - ' See also the Coroutine Objects section.\n' - '\n' - ' Asynchronous generator functions\n' - ' A function or method which is defined using "async def" and\n' - ' which uses the "yield" statement is called a *asynchronous\n' - ' generator function*. Such a function, when called, returns ' - 'an\n' - ' *asynchronous iterator* object which can be used in an ' - '"async\n' - ' for" statement to execute the body of the function.\n' + '"C", calling "x.f(1)" is equivalent to calling "C.f(x, 1)".\n' + '\n' + 'When an instance method object is derived from a class method ' + 'object,\n' + 'the “class instance†stored in "__self__" will actually be the ' + 'class\n' + 'itself, so that calling either "x.f(1)" or "C.f(1)" is equivalent ' + 'to\n' + 'calling "f(C,1)" where "f" is the underlying function.\n' '\n' - ' Calling the asynchronous iterator’s "aiterator.__anext__" ' + 'Note that the transformation from function object to instance ' 'method\n' - ' will return an *awaitable* which when awaited will execute ' + 'object happens each time the attribute is retrieved from the ' + 'instance.\n' + 'In some cases, a fruitful optimization is to assign the attribute ' + 'to a\n' + 'local variable and call that local variable. Also notice that this\n' + 'transformation only happens for user-defined functions; other ' + 'callable\n' + 'objects (and all non-callable objects) are retrieved without\n' + 'transformation. It is also important to note that user-defined\n' + 'functions which are attributes of a class instance are not ' + 'converted\n' + 'to bound methods; this *only* happens when the function is an\n' + 'attribute of the class.\n' + '\n' + '\n' + 'Generator functions\n' + '-------------------\n' + '\n' + 'A function or method which uses the "yield" statement (see section ' + 'The\n' + 'yield statement) is called a *generator function*. Such a ' + 'function,\n' + 'when called, always returns an *iterator* object which can be used ' + 'to\n' + 'execute the body of the function: calling the iterator’s\n' + '"iterator.__next__()" method will cause the function to execute ' 'until\n' - ' it provides a value using the "yield" expression. When the\n' - ' function executes an empty "return" statement or falls off ' + 'it provides a value using the "yield" statement. When the ' + 'function\n' + 'executes a "return" statement or falls off the end, a ' + '"StopIteration"\n' + 'exception is raised and the iterator will have reached the end of ' 'the\n' - ' end, a "StopAsyncIteration" exception is raised and the\n' - ' asynchronous iterator will have reached the end of the set ' - 'of\n' - ' values to be yielded.\n' + 'set of values to be returned.\n' '\n' - ' Built-in functions\n' - ' A built-in function object is a wrapper around a C function.\n' - ' Examples of built-in functions are "len()" and "math.sin()"\n' - ' ("math" is a standard built-in module). The number and type ' - 'of\n' - ' the arguments are determined by the C function. Special ' - 'read-\n' - ' only attributes: "__doc__" is the function’s documentation\n' - ' string, or "None" if unavailable; "__name__" is the ' - 'function’s\n' - ' name; "__self__" is set to "None" (but see the next item);\n' - ' "__module__" is the name of the module the function was ' - 'defined\n' - ' in or "None" if unavailable.\n' '\n' - ' Built-in methods\n' - ' This is really a different disguise of a built-in function, ' - 'this\n' - ' time containing an object passed to the C function as an\n' - ' implicit extra argument. An example of a built-in method is\n' - ' "alist.append()", assuming *alist* is a list object. In this\n' - ' case, the special read-only attribute "__self__" is set to ' + 'Coroutine functions\n' + '-------------------\n' + '\n' + 'A function or method which is defined using "async def" is called ' + 'a\n' + '*coroutine function*. Such a function, when called, returns a\n' + '*coroutine* object. It may contain "await" expressions, as well ' + 'as\n' + '"async with" and "async for" statements. See also the Coroutine\n' + 'Objects section.\n' + '\n' + '\n' + 'Asynchronous generator functions\n' + '--------------------------------\n' + '\n' + 'A function or method which is defined using "async def" and which ' + 'uses\n' + 'the "yield" statement is called a *asynchronous generator ' + 'function*.\n' + 'Such a function, when called, returns an *asynchronous iterator*\n' + 'object which can be used in an "async for" statement to execute ' 'the\n' - ' object denoted by *alist*.\n' + 'body of the function.\n' '\n' - ' Classes\n' - ' Classes are callable. These objects normally act as ' - 'factories\n' - ' for new instances of themselves, but variations are possible ' - 'for\n' - ' class types that override "__new__()". The arguments of the\n' - ' call are passed to "__new__()" and, in the typical case, to\n' - ' "__init__()" to initialize the new instance.\n' + 'Calling the asynchronous iterator’s "aiterator.__anext__" method ' + 'will\n' + 'return an *awaitable* which when awaited will execute until it\n' + 'provides a value using the "yield" expression. When the function\n' + 'executes an empty "return" statement or falls off the end, a\n' + '"StopAsyncIteration" exception is raised and the asynchronous ' + 'iterator\n' + 'will have reached the end of the set of values to be yielded.\n' + '\n' + '\n' + 'Built-in functions\n' + '------------------\n' + '\n' + 'A built-in function object is a wrapper around a C function. ' + 'Examples\n' + 'of built-in functions are "len()" and "math.sin()" ("math" is a\n' + 'standard built-in module). The number and type of the arguments ' + 'are\n' + 'determined by the C function. Special read-only attributes: ' + '"__doc__"\n' + 'is the function’s documentation string, or "None" if unavailable;\n' + '"__name__" is the function’s name; "__self__" is set to "None" ' + '(but\n' + 'see the next item); "__module__" is the name of the module the\n' + 'function was defined in or "None" if unavailable.\n' + '\n' + '\n' + 'Built-in methods\n' + '----------------\n' + '\n' + 'This is really a different disguise of a built-in function, this ' + 'time\n' + 'containing an object passed to the C function as an implicit extra\n' + 'argument. An example of a built-in method is "alist.append()",\n' + 'assuming *alist* is a list object. In this case, the special ' + 'read-only\n' + 'attribute "__self__" is set to the object denoted by *alist*.\n' + '\n' + '\n' + 'Classes\n' + '-------\n' + '\n' + 'Classes are callable. These objects normally act as factories for ' + 'new\n' + 'instances of themselves, but variations are possible for class ' + 'types\n' + 'that override "__new__()". The arguments of the call are passed ' + 'to\n' + '"__new__()" and, in the typical case, to "__init__()" to ' + 'initialize\n' + 'the new instance.\n' + '\n' + '\n' + 'Class Instances\n' + '---------------\n' + '\n' + 'Instances of arbitrary classes can be made callable by defining a\n' + '"__call__()" method in their class.\n' '\n' - ' Class Instances\n' - ' Instances of arbitrary classes can be made callable by ' - 'defining\n' - ' a "__call__()" method in their class.\n' '\n' 'Modules\n' - ' Modules are a basic organizational unit of Python code, and are\n' - ' created by the import system as invoked either by the "import"\n' - ' statement, or by calling functions such as\n' - ' "importlib.import_module()" and built-in "__import__()". A ' - 'module\n' - ' object has a namespace implemented by a dictionary object (this ' - 'is\n' - ' the dictionary referenced by the "__globals__" attribute of\n' - ' functions defined in the module). Attribute references are\n' - ' translated to lookups in this dictionary, e.g., "m.x" is ' - 'equivalent\n' - ' to "m.__dict__["x"]". A module object does not contain the code\n' - ' object used to initialize the module (since it isn’t needed ' - 'once\n' - ' the initialization is done).\n' + '=======\n' + '\n' + 'Modules are a basic organizational unit of Python code, and are\n' + 'created by the import system as invoked either by the "import"\n' + 'statement, or by calling functions such as ' + '"importlib.import_module()"\n' + 'and built-in "__import__()". A module object has a namespace\n' + 'implemented by a dictionary object (this is the dictionary ' + 'referenced\n' + 'by the "__globals__" attribute of functions defined in the ' + 'module).\n' + 'Attribute references are translated to lookups in this dictionary,\n' + 'e.g., "m.x" is equivalent to "m.__dict__["x"]". A module object ' + 'does\n' + 'not contain the code object used to initialize the module (since ' + 'it\n' + 'isn’t needed once the initialization is done).\n' + '\n' + 'Attribute assignment updates the module’s namespace dictionary, ' + 'e.g.,\n' + '"m.x = 1" is equivalent to "m.__dict__["x"] = 1".\n' '\n' - ' Attribute assignment updates the module’s namespace dictionary,\n' - ' e.g., "m.x = 1" is equivalent to "m.__dict__["x"] = 1".\n' + 'Predefined (writable) attributes:\n' '\n' - ' Predefined (writable) attributes:\n' + ' "__name__"\n' + ' The module’s name.\n' '\n' - ' "__name__"\n' - ' The module’s name.\n' + ' "__doc__"\n' + ' The module’s documentation string, or "None" if unavailable.\n' '\n' - ' "__doc__"\n' - ' The module’s documentation string, or "None" if ' - 'unavailable.\n' + ' "__file__"\n' + ' The pathname of the file from which the module was loaded, if ' + 'it\n' + ' was loaded from a file. The "__file__" attribute may be ' + 'missing\n' + ' for certain types of modules, such as C modules that are\n' + ' statically linked into the interpreter. For extension ' + 'modules\n' + ' loaded dynamically from a shared library, it’s the pathname ' + 'of\n' + ' the shared library file.\n' '\n' - ' "__file__"\n' - ' The pathname of the file from which the module was loaded, ' - 'if\n' - ' it was loaded from a file. The "__file__" attribute may ' - 'be\n' - ' missing for certain types of modules, such as C modules ' - 'that\n' - ' are statically linked into the interpreter. For ' - 'extension\n' - ' modules loaded dynamically from a shared library, it’s ' - 'the\n' - ' pathname of the shared library file.\n' - '\n' - ' "__annotations__"\n' - ' A dictionary containing *variable annotations* collected\n' - ' during module body execution. For best practices on ' - 'working\n' - ' with "__annotations__", please see Annotations Best\n' - ' Practices.\n' - '\n' - ' Special read-only attribute: "__dict__" is the module’s ' - 'namespace\n' - ' as a dictionary object.\n' - '\n' - ' **CPython implementation detail:** Because of the way CPython\n' - ' clears module dictionaries, the module dictionary will be ' - 'cleared\n' - ' when the module falls out of scope even if the dictionary still ' - 'has\n' - ' live references. To avoid this, copy the dictionary or keep ' + ' "__annotations__"\n' + ' A dictionary containing *variable annotations* collected ' + 'during\n' + ' module body execution. For best practices on working with\n' + ' "__annotations__", please see Annotations Best Practices.\n' + '\n' + 'Special read-only attribute: "__dict__" is the module’s namespace ' + 'as a\n' + 'dictionary object.\n' + '\n' + '**CPython implementation detail:** Because of the way CPython ' + 'clears\n' + 'module dictionaries, the module dictionary will be cleared when ' 'the\n' - ' module around while using its dictionary directly.\n' + 'module falls out of scope even if the dictionary still has live\n' + 'references. To avoid this, copy the dictionary or keep the module\n' + 'around while using its dictionary directly.\n' + '\n' '\n' 'Custom classes\n' - ' Custom class types are typically created by class definitions ' - '(see\n' - ' section Class definitions). A class has a namespace implemented ' - 'by\n' - ' a dictionary object. Class attribute references are translated ' - 'to\n' - ' lookups in this dictionary, e.g., "C.x" is translated to\n' - ' "C.__dict__["x"]" (although there are a number of hooks which ' + '==============\n' + '\n' + 'Custom class types are typically created by class definitions (see\n' + 'section Class definitions). A class has a namespace implemented by ' + 'a\n' + 'dictionary object. Class attribute references are translated to\n' + 'lookups in this dictionary, e.g., "C.x" is translated to\n' + '"C.__dict__["x"]" (although there are a number of hooks which ' 'allow\n' - ' for other means of locating attributes). When the attribute name ' + 'for other means of locating attributes). When the attribute name ' 'is\n' - ' not found there, the attribute search continues in the base\n' - ' classes. This search of the base classes uses the C3 method\n' - ' resolution order which behaves correctly even in the presence ' - 'of\n' - ' ‘diamond’ inheritance structures where there are multiple\n' - ' inheritance paths leading back to a common ancestor. Additional\n' - ' details on the C3 MRO used by Python can be found in the\n' - ' documentation accompanying the 2.3 release at\n' - ' https://www.python.org/download/releases/2.3/mro/.\n' - '\n' - ' When a class attribute reference (for class "C", say) would ' - 'yield a\n' - ' class method object, it is transformed into an instance method\n' - ' object whose "__self__" attribute is "C". When it would yield ' + 'not found there, the attribute search continues in the base ' + 'classes.\n' + 'This search of the base classes uses the C3 method resolution ' + 'order\n' + 'which behaves correctly even in the presence of ‘diamond’ ' + 'inheritance\n' + 'structures where there are multiple inheritance paths leading back ' + 'to\n' + 'a common ancestor. Additional details on the C3 MRO used by Python ' + 'can\n' + 'be found in the documentation accompanying the 2.3 release at\n' + 'https://www.python.org/download/releases/2.3/mro/.\n' + '\n' + 'When a class attribute reference (for class "C", say) would yield ' 'a\n' - ' static method object, it is transformed into the object wrapped ' - 'by\n' - ' the static method object. See section Implementing Descriptors ' - 'for\n' - ' another way in which attributes retrieved from a class may ' - 'differ\n' - ' from those actually contained in its "__dict__".\n' + 'class method object, it is transformed into an instance method ' + 'object\n' + 'whose "__self__" attribute is "C". When it would yield a static\n' + 'method object, it is transformed into the object wrapped by the ' + 'static\n' + 'method object. See section Implementing Descriptors for another way ' + 'in\n' + 'which attributes retrieved from a class may differ from those ' + 'actually\n' + 'contained in its "__dict__".\n' + '\n' + 'Class attribute assignments update the class’s dictionary, never ' + 'the\n' + 'dictionary of a base class.\n' + '\n' + 'A class object can be called (see above) to yield a class instance\n' + '(see below).\n' '\n' - ' Class attribute assignments update the class’s dictionary, ' - 'never\n' - ' the dictionary of a base class.\n' + 'Special attributes:\n' '\n' - ' A class object can be called (see above) to yield a class ' - 'instance\n' - ' (see below).\n' + ' "__name__"\n' + ' The class name.\n' '\n' - ' Special attributes:\n' + ' "__module__"\n' + ' The name of the module in which the class was defined.\n' '\n' - ' "__name__"\n' - ' The class name.\n' + ' "__dict__"\n' + ' The dictionary containing the class’s namespace.\n' '\n' - ' "__module__"\n' - ' The name of the module in which the class was defined.\n' + ' "__bases__"\n' + ' A tuple containing the base classes, in the order of their\n' + ' occurrence in the base class list.\n' '\n' - ' "__dict__"\n' - ' The dictionary containing the class’s namespace.\n' + ' "__doc__"\n' + ' The class’s documentation string, or "None" if undefined.\n' '\n' - ' "__bases__"\n' - ' A tuple containing the base classes, in the order of ' - 'their\n' - ' occurrence in the base class list.\n' + ' "__annotations__"\n' + ' A dictionary containing *variable annotations* collected ' + 'during\n' + ' class body execution. For best practices on working with\n' + ' "__annotations__", please see Annotations Best Practices.\n' '\n' - ' "__doc__"\n' - ' The class’s documentation string, or "None" if undefined.\n' + ' "__type_params__"\n' + ' A tuple containing the type parameters of a generic class.\n' '\n' - ' "__annotations__"\n' - ' A dictionary containing *variable annotations* collected\n' - ' during class body execution. For best practices on ' - 'working\n' - ' with "__annotations__", please see Annotations Best\n' - ' Practices.\n' '\n' 'Class instances\n' - ' A class instance is created by calling a class object (see ' - 'above).\n' - ' A class instance has a namespace implemented as a dictionary ' - 'which\n' - ' is the first place in which attribute references are searched.\n' - ' When an attribute is not found there, and the instance’s class ' - 'has\n' - ' an attribute by that name, the search continues with the class\n' - ' attributes. If a class attribute is found that is a ' - 'user-defined\n' - ' function object, it is transformed into an instance method ' - 'object\n' - ' whose "__self__" attribute is the instance. Static method and\n' - ' class method objects are also transformed; see above under\n' - ' “Classesâ€. See section Implementing Descriptors for another way ' - 'in\n' - ' which attributes of a class retrieved via its instances may ' - 'differ\n' - ' from the objects actually stored in the class’s "__dict__". If ' - 'no\n' - ' class attribute is found, and the object’s class has a\n' - ' "__getattr__()" method, that is called to satisfy the lookup.\n' + '===============\n' + '\n' + 'A class instance is created by calling a class object (see above). ' + 'A\n' + 'class instance has a namespace implemented as a dictionary which ' + 'is\n' + 'the first place in which attribute references are searched. When ' + 'an\n' + 'attribute is not found there, and the instance’s class has an\n' + 'attribute by that name, the search continues with the class\n' + 'attributes. If a class attribute is found that is a user-defined\n' + 'function object, it is transformed into an instance method object\n' + 'whose "__self__" attribute is the instance. Static method and ' + 'class\n' + 'method objects are also transformed; see above under “Classesâ€. ' + 'See\n' + 'section Implementing Descriptors for another way in which ' + 'attributes\n' + 'of a class retrieved via its instances may differ from the objects\n' + 'actually stored in the class’s "__dict__". If no class attribute ' + 'is\n' + 'found, and the object’s class has a "__getattr__()" method, that ' + 'is\n' + 'called to satisfy the lookup.\n' '\n' - ' Attribute assignments and deletions update the instance’s\n' - ' dictionary, never a class’s dictionary. If the class has a\n' - ' "__setattr__()" or "__delattr__()" method, this is called ' - 'instead\n' - ' of updating the instance dictionary directly.\n' + 'Attribute assignments and deletions update the instance’s ' + 'dictionary,\n' + 'never a class’s dictionary. If the class has a "__setattr__()" or\n' + '"__delattr__()" method, this is called instead of updating the\n' + 'instance dictionary directly.\n' '\n' - ' Class instances can pretend to be numbers, sequences, or ' - 'mappings\n' - ' if they have methods with certain special names. See section\n' - ' Special method names.\n' + 'Class instances can pretend to be numbers, sequences, or mappings ' + 'if\n' + 'they have methods with certain special names. See section Special\n' + 'method names.\n' + '\n' + 'Special attributes: "__dict__" is the attribute dictionary;\n' + '"__class__" is the instance’s class.\n' '\n' - ' Special attributes: "__dict__" is the attribute dictionary;\n' - ' "__class__" is the instance’s class.\n' '\n' 'I/O objects (also known as file objects)\n' - ' A *file object* represents an open file. Various shortcuts are\n' - ' available to create file objects: the "open()" built-in ' - 'function,\n' - ' and also "os.popen()", "os.fdopen()", and the "makefile()" ' - 'method\n' - ' of socket objects (and perhaps by other functions or methods\n' - ' provided by extension modules).\n' + '========================================\n' + '\n' + 'A *file object* represents an open file. Various shortcuts are\n' + 'available to create file objects: the "open()" built-in function, ' + 'and\n' + 'also "os.popen()", "os.fdopen()", and the "makefile()" method of\n' + 'socket objects (and perhaps by other functions or methods provided ' + 'by\n' + 'extension modules).\n' + '\n' + 'The objects "sys.stdin", "sys.stdout" and "sys.stderr" are ' + 'initialized\n' + 'to file objects corresponding to the interpreter’s standard input,\n' + 'output and error streams; they are all open in text mode and ' + 'therefore\n' + 'follow the interface defined by the "io.TextIOBase" abstract ' + 'class.\n' '\n' - ' The objects "sys.stdin", "sys.stdout" and "sys.stderr" are\n' - ' initialized to file objects corresponding to the interpreter’s\n' - ' standard input, output and error streams; they are all open in ' - 'text\n' - ' mode and therefore follow the interface defined by the\n' - ' "io.TextIOBase" abstract class.\n' '\n' 'Internal types\n' - ' A few types used internally by the interpreter are exposed to ' - 'the\n' - ' user. Their definitions may change with future versions of the\n' - ' interpreter, but they are mentioned here for completeness.\n' - '\n' - ' Code objects\n' - ' Code objects represent *byte-compiled* executable Python ' - 'code,\n' - ' or *bytecode*. The difference between a code object and a\n' - ' function object is that the function object contains an ' - 'explicit\n' - ' reference to the function’s globals (the module in which it ' - 'was\n' - ' defined), while a code object contains no context; also the\n' - ' default argument values are stored in the function object, ' - 'not\n' - ' in the code object (because they represent values calculated ' - 'at\n' - ' run-time). Unlike function objects, code objects are ' - 'immutable\n' - ' and contain no references (directly or indirectly) to ' - 'mutable\n' - ' objects.\n' - '\n' - ' Special read-only attributes: "co_name" gives the function ' - 'name;\n' - ' "co_qualname" gives the fully qualified function name;\n' - ' "co_argcount" is the total number of positional arguments\n' - ' (including positional-only arguments and arguments with ' - 'default\n' - ' values); "co_posonlyargcount" is the number of ' - 'positional-only\n' - ' arguments (including arguments with default values);\n' - ' "co_kwonlyargcount" is the number of keyword-only arguments\n' - ' (including arguments with default values); "co_nlocals" is ' - 'the\n' - ' number of local variables used by the function (including\n' - ' arguments); "co_varnames" is a tuple containing the names of ' - 'the\n' - ' local variables (starting with the argument names);\n' - ' "co_cellvars" is a tuple containing the names of local ' - 'variables\n' - ' that are referenced by nested functions; "co_freevars" is a\n' - ' tuple containing the names of free variables; "co_code" is a\n' - ' string representing the sequence of bytecode instructions;\n' - ' "co_consts" is a tuple containing the literals used by the\n' - ' bytecode; "co_names" is a tuple containing the names used by ' - 'the\n' - ' bytecode; "co_filename" is the filename from which the code ' - 'was\n' - ' compiled; "co_firstlineno" is the first line number of the\n' - ' function; "co_lnotab" is a string encoding the mapping from\n' - ' bytecode offsets to line numbers (for details see the source\n' - ' code of the interpreter, is deprecated since 3.12 and may be\n' - ' removed in 3.14); "co_stacksize" is the required stack size;\n' - ' "co_flags" is an integer encoding a number of flags for the\n' - ' interpreter.\n' - '\n' - ' The following flag bits are defined for "co_flags": bit ' - '"0x04"\n' - ' is set if the function uses the "*arguments" syntax to accept ' - 'an\n' - ' arbitrary number of positional arguments; bit "0x08" is set ' - 'if\n' - ' the function uses the "**keywords" syntax to accept ' - 'arbitrary\n' - ' keyword arguments; bit "0x20" is set if the function is a\n' - ' generator.\n' + '==============\n' + '\n' + 'A few types used internally by the interpreter are exposed to the\n' + 'user. Their definitions may change with future versions of the\n' + 'interpreter, but they are mentioned here for completeness.\n' + '\n' + '\n' + 'Code objects\n' + '------------\n' '\n' - ' Future feature declarations ("from __future__ import ' - 'division")\n' - ' also use bits in "co_flags" to indicate whether a code ' + 'Code objects represent *byte-compiled* executable Python code, or\n' + '*bytecode*. The difference between a code object and a function ' 'object\n' - ' was compiled with a particular feature enabled: bit "0x2000" ' + 'is that the function object contains an explicit reference to the\n' + 'function’s globals (the module in which it was defined), while a ' + 'code\n' + 'object contains no context; also the default argument values are\n' + 'stored in the function object, not in the code object (because ' + 'they\n' + 'represent values calculated at run-time). Unlike function ' + 'objects,\n' + 'code objects are immutable and contain no references (directly or\n' + 'indirectly) to mutable objects.\n' + '\n' + 'Special read-only attributes: "co_name" gives the function name;\n' + '"co_qualname" gives the fully qualified function name; ' + '"co_argcount"\n' + 'is the total number of positional arguments (including ' + 'positional-only\n' + 'arguments and arguments with default values); "co_posonlyargcount" ' 'is\n' - ' set if the function was compiled with future division ' - 'enabled;\n' - ' bits "0x10" and "0x1000" were used in earlier versions of\n' - ' Python.\n' + 'the number of positional-only arguments (including arguments with\n' + 'default values); "co_kwonlyargcount" is the number of keyword-only\n' + 'arguments (including arguments with default values); "co_nlocals" ' + 'is\n' + 'the number of local variables used by the function (including\n' + 'arguments); "co_varnames" is a tuple containing the names of the ' + 'local\n' + 'variables (starting with the argument names); "co_cellvars" is a ' + 'tuple\n' + 'containing the names of local variables that are referenced by ' + 'nested\n' + 'functions; "co_freevars" is a tuple containing the names of free\n' + 'variables; "co_code" is a string representing the sequence of ' + 'bytecode\n' + 'instructions; "co_consts" is a tuple containing the literals used ' + 'by\n' + 'the bytecode; "co_names" is a tuple containing the names used by ' + 'the\n' + 'bytecode; "co_filename" is the filename from which the code was\n' + 'compiled; "co_firstlineno" is the first line number of the ' + 'function;\n' + '"co_lnotab" is a string encoding the mapping from bytecode offsets ' + 'to\n' + 'line numbers (for details see the source code of the interpreter, ' + 'is\n' + 'deprecated since 3.12 and may be removed in 3.14); "co_stacksize" ' + 'is\n' + 'the required stack size; "co_flags" is an integer encoding a number ' + 'of\n' + 'flags for the interpreter.\n' + '\n' + 'The following flag bits are defined for "co_flags": bit "0x04" is ' + 'set\n' + 'if the function uses the "*arguments" syntax to accept an ' + 'arbitrary\n' + 'number of positional arguments; bit "0x08" is set if the function ' + 'uses\n' + 'the "**keywords" syntax to accept arbitrary keyword arguments; bit\n' + '"0x20" is set if the function is a generator.\n' + '\n' + 'Future feature declarations ("from __future__ import division") ' + 'also\n' + 'use bits in "co_flags" to indicate whether a code object was ' + 'compiled\n' + 'with a particular feature enabled: bit "0x2000" is set if the ' + 'function\n' + 'was compiled with future division enabled; bits "0x10" and ' + '"0x1000"\n' + 'were used in earlier versions of Python.\n' '\n' - ' Other bits in "co_flags" are reserved for internal use.\n' + 'Other bits in "co_flags" are reserved for internal use.\n' '\n' - ' If a code object represents a function, the first item in\n' - ' "co_consts" is the documentation string of the function, or\n' - ' "None" if undefined.\n' + 'If a code object represents a function, the first item in ' + '"co_consts"\n' + 'is the documentation string of the function, or "None" if ' + 'undefined.\n' '\n' - ' codeobject.co_positions()\n' + 'codeobject.co_positions()\n' '\n' - ' Returns an iterable over the source code positions of ' - 'each\n' - ' bytecode instruction in the code object.\n' + ' Returns an iterable over the source code positions of each ' + 'bytecode\n' + ' instruction in the code object.\n' '\n' - ' The iterator returns tuples containing the "(start_line,\n' - ' end_line, start_column, end_column)". The *i-th* tuple\n' - ' corresponds to the position of the source code that ' - 'compiled\n' - ' to the *i-th* instruction. Column information is ' - '0-indexed\n' - ' utf-8 byte offsets on the given source line.\n' + ' The iterator returns tuples containing the "(start_line, ' + 'end_line,\n' + ' start_column, end_column)". The *i-th* tuple corresponds to the\n' + ' position of the source code that compiled to the *i-th*\n' + ' instruction. Column information is 0-indexed utf-8 byte offsets ' + 'on\n' + ' the given source line.\n' '\n' - ' This positional information can be missing. A ' - 'non-exhaustive\n' - ' lists of cases where this may happen:\n' + ' This positional information can be missing. A non-exhaustive ' + 'lists\n' + ' of cases where this may happen:\n' '\n' - ' * Running the interpreter with "-X" "no_debug_ranges".\n' + ' * Running the interpreter with "-X" "no_debug_ranges".\n' '\n' - ' * Loading a pyc file compiled while using "-X"\n' - ' "no_debug_ranges".\n' + ' * Loading a pyc file compiled while using "-X" ' + '"no_debug_ranges".\n' '\n' - ' * Position tuples corresponding to artificial ' - 'instructions.\n' + ' * Position tuples corresponding to artificial instructions.\n' '\n' - ' * Line and column numbers that can’t be represented due ' - 'to\n' - ' implementation specific limitations.\n' + ' * Line and column numbers that can’t be represented due to\n' + ' implementation specific limitations.\n' '\n' - ' When this occurs, some or all of the tuple elements can ' - 'be\n' - ' "None".\n' + ' When this occurs, some or all of the tuple elements can be ' + '"None".\n' '\n' - ' New in version 3.11.\n' + ' New in version 3.11.\n' '\n' - ' Note:\n' + ' Note:\n' '\n' - ' This feature requires storing column positions in code\n' - ' objects which may result in a small increase of disk ' - 'usage\n' - ' of compiled Python files or interpreter memory usage. ' - 'To\n' - ' avoid storing the extra information and/or deactivate\n' - ' printing the extra traceback information, the "-X"\n' - ' "no_debug_ranges" command line flag or the\n' - ' "PYTHONNODEBUGRANGES" environment variable can be used.\n' + ' This feature requires storing column positions in code ' + 'objects\n' + ' which may result in a small increase of disk usage of ' + 'compiled\n' + ' Python files or interpreter memory usage. To avoid storing ' + 'the\n' + ' extra information and/or deactivate printing the extra ' + 'traceback\n' + ' information, the "-X" "no_debug_ranges" command line flag or ' + 'the\n' + ' "PYTHONNODEBUGRANGES" environment variable can be used.\n' + '\n' + '\n' + 'Frame objects\n' + '-------------\n' + '\n' + 'Frame objects represent execution frames. They may occur in ' + 'traceback\n' + 'objects (see below), and are also passed to registered trace\n' + 'functions.\n' + '\n' + 'Special read-only attributes: "f_back" is to the previous stack ' + 'frame\n' + '(towards the caller), or "None" if this is the bottom stack frame;\n' + '"f_code" is the code object being executed in this frame; ' + '"f_locals"\n' + 'is the dictionary used to look up local variables; "f_globals" is ' + 'used\n' + 'for global variables; "f_builtins" is used for built-in ' + '(intrinsic)\n' + 'names; "f_lasti" gives the precise instruction (this is an index ' + 'into\n' + 'the bytecode string of the code object).\n' + '\n' + 'Accessing "f_code" raises an auditing event "object.__getattr__" ' + 'with\n' + 'arguments "obj" and ""f_code"".\n' + '\n' + 'Special writable attributes: "f_trace", if not "None", is a ' + 'function\n' + 'called for various events during code execution (this is used by ' + 'the\n' + 'debugger). Normally an event is triggered for each new source line ' + '-\n' + 'this can be disabled by setting "f_trace_lines" to "False".\n' '\n' - ' Frame objects\n' - ' Frame objects represent execution frames. They may occur in\n' - ' traceback objects (see below), and are also passed to ' - 'registered\n' - ' trace functions.\n' + 'Implementations *may* allow per-opcode events to be requested by\n' + 'setting "f_trace_opcodes" to "True". Note that this may lead to\n' + 'undefined interpreter behaviour if exceptions raised by the trace\n' + 'function escape to the function being traced.\n' '\n' - ' Special read-only attributes: "f_back" is to the previous ' - 'stack\n' - ' frame (towards the caller), or "None" if this is the bottom\n' - ' stack frame; "f_code" is the code object being executed in ' + '"f_lineno" is the current line number of the frame — writing to ' 'this\n' - ' frame; "f_locals" is the dictionary used to look up local\n' - ' variables; "f_globals" is used for global variables;\n' - ' "f_builtins" is used for built-in (intrinsic) names; ' - '"f_lasti"\n' - ' gives the precise instruction (this is an index into the\n' - ' bytecode string of the code object).\n' - '\n' - ' Accessing "f_code" raises an auditing event ' - '"object.__getattr__"\n' - ' with arguments "obj" and ""f_code"".\n' - '\n' - ' Special writable attributes: "f_trace", if not "None", is a\n' - ' function called for various events during code execution ' - '(this\n' - ' is used by the debugger). Normally an event is triggered for\n' - ' each new source line - this can be disabled by setting\n' - ' "f_trace_lines" to "False".\n' - '\n' - ' Implementations *may* allow per-opcode events to be requested ' - 'by\n' - ' setting "f_trace_opcodes" to "True". Note that this may lead ' - 'to\n' - ' undefined interpreter behaviour if exceptions raised by the\n' - ' trace function escape to the function being traced.\n' + 'from within a trace function jumps to the given line (only for the\n' + 'bottom-most frame). A debugger can implement a Jump command (aka ' + 'Set\n' + 'Next Statement) by writing to f_lineno.\n' '\n' - ' "f_lineno" is the current line number of the frame — writing ' - 'to\n' - ' this from within a trace function jumps to the given line ' - '(only\n' - ' for the bottom-most frame). A debugger can implement a Jump\n' - ' command (aka Set Next Statement) by writing to f_lineno.\n' + 'Frame objects support one method:\n' + '\n' + 'frame.clear()\n' + '\n' + ' This method clears all references to local variables held by ' + 'the\n' + ' frame. Also, if the frame belonged to a generator, the ' + 'generator\n' + ' is finalized. This helps break reference cycles involving ' + 'frame\n' + ' objects (for example when catching an exception and storing its\n' + ' traceback for later use).\n' '\n' - ' Frame objects support one method:\n' + ' "RuntimeError" is raised if the frame is currently executing or\n' + ' suspended.\n' '\n' - ' frame.clear()\n' + ' New in version 3.4.\n' '\n' - ' This method clears all references to local variables held ' - 'by\n' - ' the frame. Also, if the frame belonged to a generator, ' + ' Changed in version 3.13: Attempting to clear a suspended frame\n' + ' raises "RuntimeError" (as has always been the case for ' + 'executing\n' + ' frames).\n' + '\n' + '\n' + 'Traceback objects\n' + '-----------------\n' + '\n' + 'Traceback objects represent a stack trace of an exception. A\n' + 'traceback object is implicitly created when an exception occurs, ' + 'and\n' + 'may also be explicitly created by calling "types.TracebackType".\n' + '\n' + 'For implicitly created tracebacks, when the search for an ' + 'exception\n' + 'handler unwinds the execution stack, at each unwound level a ' + 'traceback\n' + 'object is inserted in front of the current traceback. When an\n' + 'exception handler is entered, the stack trace is made available to ' 'the\n' - ' generator is finalized. This helps break reference ' - 'cycles\n' - ' involving frame objects (for example when catching an\n' - ' exception and storing its traceback for later use).\n' + 'program. (See section The try statement.) It is accessible as the\n' + 'third item of the tuple returned by "sys.exc_info()", and as the\n' + '"__traceback__" attribute of the caught exception.\n' '\n' - ' "RuntimeError" is raised if the frame is currently ' - 'executing.\n' + 'When the program contains no suitable handler, the stack trace is\n' + 'written (nicely formatted) to the standard error stream; if the\n' + 'interpreter is interactive, it is also made available to the user ' + 'as\n' + '"sys.last_traceback".\n' '\n' - ' New in version 3.4.\n' + 'For explicitly created tracebacks, it is up to the creator of the\n' + 'traceback to determine how the "tb_next" attributes should be ' + 'linked\n' + 'to form a full stack trace.\n' '\n' - ' Traceback objects\n' - ' Traceback objects represent a stack trace of an exception. ' - 'A\n' - ' traceback object is implicitly created when an exception ' - 'occurs,\n' - ' and may also be explicitly created by calling\n' - ' "types.TracebackType".\n' - '\n' - ' For implicitly created tracebacks, when the search for an\n' - ' exception handler unwinds the execution stack, at each ' - 'unwound\n' - ' level a traceback object is inserted in front of the current\n' - ' traceback. When an exception handler is entered, the stack\n' - ' trace is made available to the program. (See section The try\n' - ' statement.) It is accessible as the third item of the tuple\n' - ' returned by "sys.exc_info()", and as the "__traceback__"\n' - ' attribute of the caught exception.\n' - '\n' - ' When the program contains no suitable handler, the stack ' - 'trace\n' - ' is written (nicely formatted) to the standard error stream; ' - 'if\n' - ' the interpreter is interactive, it is also made available to ' + 'Special read-only attributes: "tb_frame" points to the execution ' + 'frame\n' + 'of the current level; "tb_lineno" gives the line number where the\n' + 'exception occurred; "tb_lasti" indicates the precise instruction. ' + 'The\n' + 'line number and last instruction in the traceback may differ from ' 'the\n' - ' user as "sys.last_traceback".\n' + 'line number of its frame object if the exception occurred in a ' + '"try"\n' + 'statement with no matching except clause or with a finally clause.\n' '\n' - ' For explicitly created tracebacks, it is up to the creator ' - 'of\n' - ' the traceback to determine how the "tb_next" attributes ' - 'should\n' - ' be linked to form a full stack trace.\n' - '\n' - ' Special read-only attributes: "tb_frame" points to the ' - 'execution\n' - ' frame of the current level; "tb_lineno" gives the line ' - 'number\n' - ' where the exception occurred; "tb_lasti" indicates the ' - 'precise\n' - ' instruction. The line number and last instruction in the\n' - ' traceback may differ from the line number of its frame object ' + 'Accessing "tb_frame" raises an auditing event "object.__getattr__"\n' + 'with arguments "obj" and ""tb_frame"".\n' + '\n' + 'Special writable attribute: "tb_next" is the next level in the ' + 'stack\n' + 'trace (towards the frame where the exception occurred), or "None" ' 'if\n' - ' the exception occurred in a "try" statement with no matching\n' - ' except clause or with a finally clause.\n' + 'there is no next level.\n' '\n' - ' Accessing "tb_frame" raises an auditing event\n' - ' "object.__getattr__" with arguments "obj" and ""tb_frame"".\n' + 'Changed in version 3.7: Traceback objects can now be explicitly\n' + 'instantiated from Python code, and the "tb_next" attribute of ' + 'existing\n' + 'instances can be updated.\n' '\n' - ' Special writable attribute: "tb_next" is the next level in ' - 'the\n' - ' stack trace (towards the frame where the exception occurred), ' - 'or\n' - ' "None" if there is no next level.\n' '\n' - ' Changed in version 3.7: Traceback objects can now be ' - 'explicitly\n' - ' instantiated from Python code, and the "tb_next" attribute ' - 'of\n' - ' existing instances can be updated.\n' + 'Slice objects\n' + '-------------\n' '\n' - ' Slice objects\n' - ' Slice objects are used to represent slices for ' - '"__getitem__()"\n' - ' methods. They are also created by the built-in "slice()"\n' - ' function.\n' + 'Slice objects are used to represent slices for "__getitem__()"\n' + 'methods. They are also created by the built-in "slice()" ' + 'function.\n' '\n' - ' Special read-only attributes: "start" is the lower bound; ' - '"stop"\n' - ' is the upper bound; "step" is the step value; each is "None" ' - 'if\n' - ' omitted. These attributes can have any type.\n' + 'Special read-only attributes: "start" is the lower bound; "stop" ' + 'is\n' + 'the upper bound; "step" is the step value; each is "None" if ' + 'omitted.\n' + 'These attributes can have any type.\n' '\n' - ' Slice objects support one method:\n' + 'Slice objects support one method:\n' '\n' - ' slice.indices(self, length)\n' + 'slice.indices(self, length)\n' '\n' - ' This method takes a single integer argument *length* and\n' - ' computes information about the slice that the slice ' - 'object\n' - ' would describe if applied to a sequence of *length* ' - 'items.\n' - ' It returns a tuple of three integers; respectively these ' - 'are\n' - ' the *start* and *stop* indices and the *step* or stride\n' - ' length of the slice. Missing or out-of-bounds indices are\n' - ' handled in a manner consistent with regular slices.\n' - '\n' - ' Static method objects\n' - ' Static method objects provide a way of defeating the\n' - ' transformation of function objects to method objects ' - 'described\n' - ' above. A static method object is a wrapper around any other\n' - ' object, usually a user-defined method object. When a static\n' - ' method object is retrieved from a class or a class instance, ' - 'the\n' - ' object actually returned is the wrapped object, which is not\n' - ' subject to any further transformation. Static method objects ' - 'are\n' - ' also callable. Static method objects are created by the ' - 'built-in\n' - ' "staticmethod()" constructor.\n' + ' This method takes a single integer argument *length* and ' + 'computes\n' + ' information about the slice that the slice object would describe ' + 'if\n' + ' applied to a sequence of *length* items. It returns a tuple of\n' + ' three integers; respectively these are the *start* and *stop*\n' + ' indices and the *step* or stride length of the slice. Missing ' + 'or\n' + ' out-of-bounds indices are handled in a manner consistent with\n' + ' regular slices.\n' '\n' - ' Class method objects\n' - ' A class method object, like a static method object, is a ' - 'wrapper\n' - ' around another object that alters the way in which that ' - 'object\n' - ' is retrieved from classes and class instances. The behaviour ' + '\n' + 'Static method objects\n' + '---------------------\n' + '\n' + 'Static method objects provide a way of defeating the transformation ' 'of\n' - ' class method objects upon such retrieval is described above,\n' - ' under “User-defined methodsâ€. Class method objects are ' - 'created\n' - ' by the built-in "classmethod()" constructor.\n', + 'function objects to method objects described above. A static ' + 'method\n' + 'object is a wrapper around any other object, usually a ' + 'user-defined\n' + 'method object. When a static method object is retrieved from a ' + 'class\n' + 'or a class instance, the object actually returned is the wrapped\n' + 'object, which is not subject to any further transformation. Static\n' + 'method objects are also callable. Static method objects are created ' + 'by\n' + 'the built-in "staticmethod()" constructor.\n' + '\n' + '\n' + 'Class method objects\n' + '--------------------\n' + '\n' + 'A class method object, like a static method object, is a wrapper\n' + 'around another object that alters the way in which that object is\n' + 'retrieved from classes and class instances. The behaviour of class\n' + 'method objects upon such retrieval is described above, under ' + '“User-\n' + 'defined methodsâ€. Class method objects are created by the built-in\n' + '"classmethod()" constructor.\n', 'typesfunctions': 'Functions\n' '*********\n' '\n' @@ -14564,21 +15222,23 @@ '\n' 'Keys views are set-like since their entries are unique and ' '*hashable*.\n' - 'If all values are hashable, so that "(key, value)" pairs are ' - 'unique\n' - 'and hashable, then the items view is also set-like. (Values ' - 'views are\n' - 'not treated as set-like since the entries are generally not ' - 'unique.)\n' - 'For set-like views, all of the operations defined for the ' - 'abstract\n' - 'base class "collections.abc.Set" are available (for example, ' - '"==",\n' - '"<", or "^"). While using set operators, set-like views ' - 'accept any\n' - 'iterable as the other operand, unlike sets which only accept ' - 'sets as\n' - 'the input.\n' + 'Items views also have set-like operations since the (key, ' + 'value) pairs\n' + 'are unique and the keys are hashable. If all values in an ' + 'items view\n' + 'are hashable as well, then the items view can interoperate ' + 'with other\n' + 'sets. (Values views are not treated as set-like since the ' + 'entries are\n' + 'generally not unique.) For set-like views, all of the ' + 'operations\n' + 'defined for the abstract base class "collections.abc.Set" ' + 'are\n' + 'available (for example, "==", "<", or "^"). While using ' + 'set\n' + 'operators, set-like views accept any iterable as the other ' + 'operand,\n' + 'unlike sets which only accept sets as the input.\n' '\n' 'An example of dictionary view usage:\n' '\n' @@ -14611,10 +15271,12 @@ ' >>> # set operations\n' " >>> keys & {'eggs', 'bacon', 'salad'}\n" " {'bacon'}\n" - " >>> keys ^ {'sausage', 'juice'}\n" - " {'juice', 'sausage', 'bacon', 'spam'}\n" - " >>> keys | ['juice', 'juice', 'juice']\n" - " {'juice', 'sausage', 'bacon', 'spam', 'eggs'}\n" + " >>> keys ^ {'sausage', 'juice'} == {'juice', 'sausage', " + "'bacon', 'spam'}\n" + ' True\n' + " >>> keys | ['juice', 'juice', 'juice'] == {'bacon', " + "'spam', 'juice'}\n" + ' True\n' '\n' ' >>> # get back a read-only proxy for the original ' 'dictionary\n' diff --git a/Lib/random.py b/Lib/random.py index 586c3f7f9da938..875beb2f8cf41c 100644 --- a/Lib/random.py +++ b/Lib/random.py @@ -50,7 +50,6 @@ # Adrian Baddeley. Adapted by Raymond Hettinger for use with # the Mersenne Twister and os.urandom() core generators. -from warnings import warn as _warn from math import log as _log, exp as _exp, pi as _pi, e as _e, ceil as _ceil from math import sqrt as _sqrt, acos as _acos, cos as _cos, sin as _sin from math import tau as TWOPI, floor as _floor, isfinite as _isfinite @@ -63,13 +62,6 @@ import os as _os import _random -try: - # hashlib is pretty heavy to load, try lean internal module first - from _sha512 import sha512 as _sha512 -except ImportError: - # fallback to official implementation - from hashlib import sha512 as _sha512 - __all__ = [ "Random", "SystemRandom", @@ -105,6 +97,7 @@ BPF = 53 # Number of bits in a float RECIP_BPF = 2 ** -BPF _ONE = 1 +_sha512 = None class Random(_random.Random): @@ -159,13 +152,23 @@ def seed(self, a=None, version=2): a = -2 if x == -1 else x elif version == 2 and isinstance(a, (str, bytes, bytearray)): + global _sha512 + if _sha512 is None: + try: + # hashlib is pretty heavy to load, try lean internal + # module first + from _sha2 import sha512 as _sha512 + except ImportError: + # fallback to official implementation + from hashlib import sha512 as _sha512 + if isinstance(a, str): a = a.encode() a = int.from_bytes(a + _sha512(a).digest()) elif not isinstance(a, (type(None), int, float, str, bytes, bytearray)): - raise TypeError('The only supported seed types are: None,\n' - 'int, float, str, bytes, and bytearray.') + raise TypeError('The only supported seed types are:\n' + 'None, int, float, str, bytes, and bytearray.') super().seed(a) self.gauss_next = None @@ -257,9 +260,10 @@ def _randbelow_without_getrandbits(self, n, maxsize=1<= maxsize: - _warn("Underlying random() generator does not supply \n" - "enough bits to choose from a population range this large.\n" - "To remove the range limitation, add a getrandbits() method.") + from warnings import warn + warn("Underlying random() generator does not supply \n" + "enough bits to choose from a population range this large.\n" + "To remove the range limitation, add a getrandbits() method.") return _floor(random() * n) rem = maxsize % n limit = (maxsize - rem) / maxsize # int(limit * maxsize) % n == 0 @@ -492,7 +496,14 @@ def choices(self, population, weights=None, *, cum_weights=None, k=1): ## -------------------- real-valued distributions ------------------- def uniform(self, a, b): - "Get a random number in the range [a, b) or [a, b] depending on rounding." + """Get a random number in the range [a, b) or [a, b] depending on rounding. + + The mean (expected value) and variance of the random variable are: + + E[X] = (a + b) / 2 + Var[X] = (b - a) ** 2 / 12 + + """ return a + (b - a) * self.random() def triangular(self, low=0.0, high=1.0, mode=None): @@ -503,6 +514,11 @@ def triangular(self, low=0.0, high=1.0, mode=None): http://en.wikipedia.org/wiki/Triangular_distribution + The mean (expected value) and variance of the random variable are: + + E[X] = (low + high + mode) / 3 + Var[X] = (low**2 + high**2 + mode**2 - low*high - low*mode - high*mode) / 18 + """ u = self.random() try: @@ -593,12 +609,15 @@ def expovariate(self, lambd=1.0): positive infinity if lambd is positive, and from negative infinity to 0 if lambd is negative. - """ - # lambd: rate lambd = 1/mean - # ('lambda' is a Python reserved word) + The mean (expected value) and variance of the random variable are: + E[X] = 1 / lambd + Var[X] = 1 / lambd ** 2 + + """ # we use 1-random() instead of random() to preclude the # possibility of taking the log of zero. + return -_log(1.0 - self.random()) / lambd def vonmisesvariate(self, mu, kappa): @@ -654,8 +673,12 @@ def gammavariate(self, alpha, beta): pdf(x) = -------------------------------------- math.gamma(alpha) * beta ** alpha + The mean (expected value) and variance of the random variable are: + + E[X] = alpha * beta + Var[X] = alpha * beta ** 2 + """ - # alpha > 0, beta > 0, mean is alpha*beta, variance is alpha*beta**2 # Warning: a few older sources define the gamma distribution in terms # of alpha > -1.0 @@ -714,6 +737,11 @@ def betavariate(self, alpha, beta): Conditions on the parameters are alpha > 0 and beta > 0. Returned values range between 0 and 1. + The mean (expected value) and variance of the random variable are: + + E[X] = alpha / (alpha + beta) + Var[X] = alpha * beta / ((alpha + beta)**2 * (alpha + beta + 1)) + """ ## See ## http://mail.python.org/pipermail/python-bugs-list/2001-January/003752.html @@ -766,6 +794,11 @@ def binomialvariate(self, n=1, p=0.5): Returns an integer in the range: 0 <= X <= n + The mean (expected value) and variance of the random variable are: + + E[X] = n * p + Var[x] = n * p * (1 - p) + """ # Error check inputs and handle edge cases if n < 0: @@ -827,7 +860,7 @@ def binomialvariate(self, n=1, p=0.5): return k # Acceptance-rejection test. - # Note, the original paper errorneously omits the call to log(v) + # Note, the original paper erroneously omits the call to log(v) # when comparing to the log of the rescaled binomial distribution. if not setup_complete: alpha = (2.83 + 5.1 / b) * spq diff --git a/Lib/re/__init__.py b/Lib/re/__init__.py index d6fccd5bc97cc0..7e8abbf6ffe155 100644 --- a/Lib/re/__init__.py +++ b/Lib/re/__init__.py @@ -117,7 +117,8 @@ U UNICODE For compatibility only. Ignored for string patterns (it is the default), and forbidden for bytes patterns. -This module also defines an exception 'error'. +This module also defines exception 'PatternError', aliased to 'error' for +backward compatibility. """ @@ -133,7 +134,7 @@ "findall", "finditer", "compile", "purge", "escape", "error", "Pattern", "Match", "A", "I", "L", "M", "S", "X", "U", "ASCII", "IGNORECASE", "LOCALE", "MULTILINE", "DOTALL", "VERBOSE", - "UNICODE", "NOFLAG", "RegexFlag", + "UNICODE", "NOFLAG", "RegexFlag", "PatternError" ] __version__ = "2.2.1" @@ -155,7 +156,7 @@ class RegexFlag: _numeric_repr_ = hex # sre exception -error = _compiler.error +PatternError = error = _compiler.PatternError # -------------------------------------------------------------------- # public interface @@ -175,16 +176,39 @@ def search(pattern, string, flags=0): a Match object, or None if no match was found.""" return _compile(pattern, flags).search(string) -def sub(pattern, repl, string, count=0, flags=0): +class _ZeroSentinel(int): + pass +_zero_sentinel = _ZeroSentinel() + +def sub(pattern, repl, string, *args, count=_zero_sentinel, flags=_zero_sentinel): """Return the string obtained by replacing the leftmost non-overlapping occurrences of the pattern in string by the replacement repl. repl can be either a string or a callable; if a string, backslash escapes in it are processed. If it is a callable, it's passed the Match object and must return a replacement string to be used.""" + if args: + if count is not _zero_sentinel: + raise TypeError("sub() got multiple values for argument 'count'") + count, *args = args + if args: + if flags is not _zero_sentinel: + raise TypeError("sub() got multiple values for argument 'flags'") + flags, *args = args + if args: + raise TypeError("sub() takes from 3 to 5 positional arguments " + "but %d were given" % (5 + len(args))) + + import warnings + warnings.warn( + "'count' is passed as positional argument", + DeprecationWarning, stacklevel=2 + ) + return _compile(pattern, flags).sub(repl, string, count) +sub.__text_signature__ = '(pattern, repl, string, count=0, flags=0)' -def subn(pattern, repl, string, count=0, flags=0): +def subn(pattern, repl, string, *args, count=_zero_sentinel, flags=_zero_sentinel): """Return a 2-tuple containing (new_string, number). new_string is the string obtained by replacing the leftmost non-overlapping occurrences of the pattern in the source @@ -193,9 +217,28 @@ def subn(pattern, repl, string, count=0, flags=0): callable; if a string, backslash escapes in it are processed. If it is a callable, it's passed the Match object and must return a replacement string to be used.""" + if args: + if count is not _zero_sentinel: + raise TypeError("subn() got multiple values for argument 'count'") + count, *args = args + if args: + if flags is not _zero_sentinel: + raise TypeError("subn() got multiple values for argument 'flags'") + flags, *args = args + if args: + raise TypeError("subn() takes from 3 to 5 positional arguments " + "but %d were given" % (5 + len(args))) + + import warnings + warnings.warn( + "'count' is passed as positional argument", + DeprecationWarning, stacklevel=2 + ) + return _compile(pattern, flags).subn(repl, string, count) +subn.__text_signature__ = '(pattern, repl, string, count=0, flags=0)' -def split(pattern, string, maxsplit=0, flags=0): +def split(pattern, string, *args, maxsplit=_zero_sentinel, flags=_zero_sentinel): """Split the source string by the occurrences of the pattern, returning a list containing the resulting substrings. If capturing parentheses are used in pattern, then the text of all @@ -203,7 +246,26 @@ def split(pattern, string, maxsplit=0, flags=0): list. If maxsplit is nonzero, at most maxsplit splits occur, and the remainder of the string is returned as the final element of the list.""" + if args: + if maxsplit is not _zero_sentinel: + raise TypeError("split() got multiple values for argument 'maxsplit'") + maxsplit, *args = args + if args: + if flags is not _zero_sentinel: + raise TypeError("split() got multiple values for argument 'flags'") + flags, *args = args + if args: + raise TypeError("split() takes from 2 to 4 positional arguments " + "but %d were given" % (4 + len(args))) + + import warnings + warnings.warn( + "'maxsplit' is passed as positional argument", + DeprecationWarning, stacklevel=2 + ) + return _compile(pattern, flags).split(string, maxsplit) +split.__text_signature__ = '(pattern, string, maxsplit=0, flags=0)' def findall(pattern, string, flags=0): """Return a list of all non-overlapping matches in the string. diff --git a/Lib/re/_compiler.py b/Lib/re/_compiler.py index d0a4c55caf6e41..7b888f877eb3dc 100644 --- a/Lib/re/_compiler.py +++ b/Lib/re/_compiler.py @@ -147,8 +147,10 @@ def _compile(code, pattern, flags): emit(0) # look ahead else: lo, hi = av[1].getwidth() + if lo > MAXCODE: + raise error("looks too much behind") if lo != hi: - raise error("look-behind requires fixed-width pattern") + raise PatternError("look-behind requires fixed-width pattern") emit(lo) # look behind _compile(code, av[1], flags) emit(SUCCESS) @@ -207,7 +209,7 @@ def _compile(code, pattern, flags): else: code[skipyes] = _len(code) - skipyes + 1 else: - raise error("internal: unsupported operand type %r" % (op,)) + raise PatternError(f"internal: unsupported operand type {op!r}") def _compile_charset(charset, flags, code): # compile charset subprogram @@ -233,7 +235,7 @@ def _compile_charset(charset, flags, code): else: emit(av) else: - raise error("internal: unsupported set operator %r" % (op,)) + raise PatternError(f"internal: unsupported set operator {op!r}") emit(FAILURE) def _optimize_charset(charset, iscased=None, fixup=None, fixes=None): @@ -547,7 +549,7 @@ def _compile_info(code, pattern, flags): else: emit(MAXCODE) prefix = prefix[:MAXCODE] - emit(min(hi, MAXCODE)) + emit(hi) # add literal prefix if prefix: emit(len(prefix)) # length diff --git a/Lib/re/_constants.py b/Lib/re/_constants.py index d8e483ac4f23b4..9c3c294ba448b4 100644 --- a/Lib/re/_constants.py +++ b/Lib/re/_constants.py @@ -20,7 +20,7 @@ # SRE standard exception (access as sre.error) # should this really be here? -class error(Exception): +class PatternError(Exception): """Exception raised for invalid regular expressions. Attributes: @@ -53,6 +53,9 @@ def __init__(self, msg, pattern=None, pos=None): super().__init__(msg) +# Backward compatibility after renaming in 3.13 +error = PatternError + class _NamedIntConstant(int): def __new__(cls, value, name): self = super(_NamedIntConstant, cls).__new__(cls, value) diff --git a/Lib/re/_parser.py b/Lib/re/_parser.py index 22d10ab6e31d37..f3c779340fe230 100644 --- a/Lib/re/_parser.py +++ b/Lib/re/_parser.py @@ -67,6 +67,10 @@ TYPE_FLAGS = SRE_FLAG_ASCII | SRE_FLAG_LOCALE | SRE_FLAG_UNICODE GLOBAL_FLAGS = SRE_FLAG_DEBUG +# Maximal value returned by SubPattern.getwidth(). +# Must be larger than MAXREPEAT, MAXCODE and sys.maxsize. +MAXWIDTH = 1 << 64 + class State: # keeps track of state for parsing def __init__(self): @@ -177,7 +181,7 @@ def getwidth(self): lo = hi = 0 for op, av in self.data: if op is BRANCH: - i = MAXREPEAT - 1 + i = MAXWIDTH j = 0 for av in av[1]: l, h = av.getwidth() @@ -196,7 +200,10 @@ def getwidth(self): elif op in _REPEATCODES: i, j = av[2].getwidth() lo = lo + i * av[0] - hi = hi + j * av[1] + if av[1] == MAXREPEAT and j: + hi = MAXWIDTH + else: + hi = hi + j * av[1] elif op in _UNITCODES: lo = lo + 1 hi = hi + 1 @@ -216,7 +223,7 @@ def getwidth(self): hi = hi + j elif op is SUCCESS: break - self.width = min(lo, MAXREPEAT - 1), min(hi, MAXREPEAT) + self.width = min(lo, MAXWIDTH), min(hi, MAXWIDTH) return self.width class Tokenizer: @@ -773,8 +780,10 @@ def _parse(source, state, verbose, nested, first=False): source.tell() - start) if char == "=": subpatternappend((ASSERT, (dir, p))) - else: + elif p: subpatternappend((ASSERT_NOT, (dir, p))) + else: + subpatternappend((FAILURE, ())) continue elif char == "(": diff --git a/Lib/reprlib.py b/Lib/reprlib.py index a92b3e3dbb613a..05bb1a0eb01795 100644 --- a/Lib/reprlib.py +++ b/Lib/reprlib.py @@ -29,6 +29,8 @@ def wrapper(self): wrapper.__name__ = getattr(user_function, '__name__') wrapper.__qualname__ = getattr(user_function, '__qualname__') wrapper.__annotations__ = getattr(user_function, '__annotations__', {}) + wrapper.__type_params__ = getattr(user_function, '__type_params__', ()) + wrapper.__wrapped__ = user_function return wrapper return decorating_function diff --git a/Lib/selectors.py b/Lib/selectors.py index 20367c9152f331..b8e5f6a4f77d89 100644 --- a/Lib/selectors.py +++ b/Lib/selectors.py @@ -491,6 +491,7 @@ class KqueueSelector(_BaseSelectorImpl): def __init__(self): super().__init__() self._selector = select.kqueue() + self._max_events = 0 def fileno(self): return self._selector.fileno() @@ -502,10 +503,12 @@ def register(self, fileobj, events, data=None): kev = select.kevent(key.fd, select.KQ_FILTER_READ, select.KQ_EV_ADD) self._selector.control([kev], 0, 0) + self._max_events += 1 if events & EVENT_WRITE: kev = select.kevent(key.fd, select.KQ_FILTER_WRITE, select.KQ_EV_ADD) self._selector.control([kev], 0, 0) + self._max_events += 1 except: super().unregister(fileobj) raise @@ -516,6 +519,7 @@ def unregister(self, fileobj): if key.events & EVENT_READ: kev = select.kevent(key.fd, select.KQ_FILTER_READ, select.KQ_EV_DELETE) + self._max_events -= 1 try: self._selector.control([kev], 0, 0) except OSError: @@ -525,6 +529,7 @@ def unregister(self, fileobj): if key.events & EVENT_WRITE: kev = select.kevent(key.fd, select.KQ_FILTER_WRITE, select.KQ_EV_DELETE) + self._max_events -= 1 try: self._selector.control([kev], 0, 0) except OSError: @@ -537,7 +542,7 @@ def select(self, timeout=None): # If max_ev is 0, kqueue will ignore the timeout. For consistent # behavior with the other selector classes, we prevent that here # (using max). See https://bugs.python.org/issue29255 - max_ev = len(self._fd_to_key) or 1 + max_ev = self._max_events or 1 ready = [] try: kev_list = self._selector.control(None, max_ev, timeout) diff --git a/Lib/shutil.py b/Lib/shutil.py index 3f2864af517e7d..acc9419be4dfca 100644 --- a/Lib/shutil.py +++ b/Lib/shutil.py @@ -10,7 +10,6 @@ import fnmatch import collections import errno -import warnings try: import zlib @@ -307,7 +306,12 @@ def copymode(src, dst, *, follow_symlinks=True): else: return else: - stat_func, chmod_func = _stat, os.chmod + stat_func = _stat + if os.name == 'nt' and os.path.islink(dst): + def chmod_func(*args): + os.chmod(*args, follow_symlinks=True) + else: + chmod_func = os.chmod st = stat_func(src) chmod_func(dst, stat.S_IMODE(st.st_mode)) @@ -481,7 +485,7 @@ def _copytree(entries, src, dst, symlinks, ignore, copy_function, if ignore is not None: ignored_names = ignore(os.fspath(src), [x.name for x in entries]) else: - ignored_names = set() + ignored_names = () os.makedirs(dst, exist_ok=dirs_exist_ok) errors = [] @@ -591,23 +595,21 @@ def copytree(src, dst, symlinks=False, ignore=None, copy_function=copy2, dirs_exist_ok=dirs_exist_ok) if hasattr(os.stat_result, 'st_file_attributes'): - def _rmtree_islink(path): - try: - st = os.lstat(path) - return (stat.S_ISLNK(st.st_mode) or - (st.st_file_attributes & stat.FILE_ATTRIBUTE_REPARSE_POINT - and st.st_reparse_tag == stat.IO_REPARSE_TAG_MOUNT_POINT)) - except OSError: - return False + def _rmtree_islink(st): + return (stat.S_ISLNK(st.st_mode) or + (st.st_file_attributes & stat.FILE_ATTRIBUTE_REPARSE_POINT + and st.st_reparse_tag == stat.IO_REPARSE_TAG_MOUNT_POINT)) else: - def _rmtree_islink(path): - return os.path.islink(path) + def _rmtree_islink(st): + return stat.S_ISLNK(st.st_mode) # version vulnerable to race conditions def _rmtree_unsafe(path, onexc): try: with os.scandir(path) as scandir_it: entries = list(scandir_it) + except FileNotFoundError: + return except OSError as err: onexc(os.scandir, path, err) entries = [] @@ -615,6 +617,8 @@ def _rmtree_unsafe(path, onexc): fullname = entry.path try: is_dir = entry.is_dir(follow_symlinks=False) + except FileNotFoundError: + continue except OSError: is_dir = False @@ -625,6 +629,8 @@ def _rmtree_unsafe(path, onexc): # a directory with a symlink after the call to # os.scandir or entry.is_dir above. raise OSError("Cannot call rmtree on a symbolic link") + except FileNotFoundError: + continue except OSError as err: onexc(os.path.islink, fullname, err) continue @@ -632,10 +638,14 @@ def _rmtree_unsafe(path, onexc): else: try: os.unlink(fullname) + except FileNotFoundError: + continue except OSError as err: onexc(os.unlink, fullname, err) try: os.rmdir(path) + except FileNotFoundError: + pass except OSError as err: onexc(os.rmdir, path, err) @@ -644,6 +654,8 @@ def _rmtree_safe_fd(topfd, path, onexc): try: with os.scandir(topfd) as scandir_it: entries = list(scandir_it) + except FileNotFoundError: + return except OSError as err: err.filename = path onexc(os.scandir, path, err) @@ -652,6 +664,8 @@ def _rmtree_safe_fd(topfd, path, onexc): fullname = os.path.join(path, entry.name) try: is_dir = entry.is_dir(follow_symlinks=False) + except FileNotFoundError: + continue except OSError: is_dir = False else: @@ -659,6 +673,8 @@ def _rmtree_safe_fd(topfd, path, onexc): try: orig_st = entry.stat(follow_symlinks=False) is_dir = stat.S_ISDIR(orig_st.st_mode) + except FileNotFoundError: + continue except OSError as err: onexc(os.lstat, fullname, err) continue @@ -666,6 +682,8 @@ def _rmtree_safe_fd(topfd, path, onexc): try: dirfd = os.open(entry.name, os.O_RDONLY, dir_fd=topfd) dirfd_closed = False + except FileNotFoundError: + continue except OSError as err: onexc(os.open, fullname, err) else: @@ -674,8 +692,15 @@ def _rmtree_safe_fd(topfd, path, onexc): _rmtree_safe_fd(dirfd, fullname, onexc) try: os.close(dirfd) + except OSError as err: + # close() should not be retried after an error. dirfd_closed = True + onexc(os.close, fullname, err) + dirfd_closed = True + try: os.rmdir(entry.name, dir_fd=topfd) + except FileNotFoundError: + continue except OSError as err: onexc(os.rmdir, fullname, err) else: @@ -689,10 +714,15 @@ def _rmtree_safe_fd(topfd, path, onexc): onexc(os.path.islink, fullname, err) finally: if not dirfd_closed: - os.close(dirfd) + try: + os.close(dirfd) + except OSError as err: + onexc(os.close, fullname, err) else: try: os.unlink(entry.name, dir_fd=topfd) + except FileNotFoundError: + continue except OSError as err: onexc(os.unlink, fullname, err) @@ -722,10 +752,6 @@ def rmtree(path, ignore_errors=False, onerror=None, *, onexc=None, dir_fd=None): If both onerror and onexc are set, onerror is ignored and onexc is used. """ - if onerror is not None: - warnings.warn("onerror argument is deprecated, use onexc instead", - DeprecationWarning, stacklevel=2) - sys.audit("shutil.rmtree", path, dir_fd) if ignore_errors: def onexc(*args): @@ -755,13 +781,13 @@ def onexc(*args): # lstat()/open()/fstat() trick. try: orig_st = os.lstat(path, dir_fd=dir_fd) - except Exception as err: + except OSError as err: onexc(os.lstat, path, err) return try: fd = os.open(path, os.O_RDONLY, dir_fd=dir_fd) fd_closed = False - except Exception as err: + except OSError as err: onexc(os.open, path, err) return try: @@ -769,7 +795,12 @@ def onexc(*args): _rmtree_safe_fd(fd, path, onexc) try: os.close(fd) + except OSError as err: + # close() should not be retried after an error. fd_closed = True + onexc(os.close, path, err) + fd_closed = True + try: os.rmdir(path, dir_fd=dir_fd) except OSError as err: onexc(os.rmdir, path, err) @@ -781,12 +812,20 @@ def onexc(*args): onexc(os.path.islink, path, err) finally: if not fd_closed: - os.close(fd) + try: + os.close(fd) + except OSError as err: + onexc(os.close, path, err) else: if dir_fd is not None: raise NotImplementedError("dir_fd unavailable on this platform") try: - if _rmtree_islink(path): + st = os.lstat(path) + except OSError as err: + onexc(os.lstat, path, err) + return + try: + if _rmtree_islink(st): # symlinks to directories are forbidden, see bug #1669 raise OSError("Cannot call rmtree on a symbolic link") except OSError as err: @@ -846,7 +885,7 @@ def move(src, dst, copy_function=copy2): sys.audit("shutil.move", src, dst) real_dst = dst if os.path.isdir(dst): - if _samefile(src, dst): + if _samefile(src, dst) and not os.path.islink(src): # We might be on a case insensitive filesystem, # perform the rename anyway. os.rename(src, dst) @@ -1156,6 +1195,10 @@ def make_archive(base_name, format, root_dir=None, base_dir=None, verbose=0, supports_root_dir = getattr(func, 'supports_root_dir', False) save_cwd = None if root_dir is not None: + stmd = os.stat(root_dir).st_mode + if not stat.S_ISDIR(stmd): + raise NotADirectoryError(errno.ENOTDIR, 'Not a directory', root_dir) + if supports_root_dir: # Support path-like base_name here for backwards-compatibility. base_name = os.fspath(base_name) @@ -1550,8 +1593,16 @@ def which(cmd, mode=os.F_OK | os.X_OK, path=None): if use_bytes: pathext = [os.fsencode(ext) for ext in pathext] - # Always try checking the originally given cmd, if it doesn't match, try pathext - files = [cmd] + [cmd + ext for ext in pathext] + files = ([cmd] + [cmd + ext for ext in pathext]) + + # gh-109590. If we are looking for an executable, we need to look + # for a PATHEXT match. The first cmd is the direct match + # (e.g. python.exe instead of python) + # Check that direct match first if and only if the extension is in PATHEXT + # Otherwise check it last + suffix = os.path.splitext(files[0])[1].upper() + if mode & os.X_OK and not any(suffix == ext.upper() for ext in pathext): + files.append(files.pop(0)) else: # On other platforms you don't have things like PATHEXT to tell you # what file suffixes are executable, so just pass on cmd as-is. diff --git a/Lib/signal.py b/Lib/signal.py index 50b215b29d2fad..c8cd3d4f597ca5 100644 --- a/Lib/signal.py +++ b/Lib/signal.py @@ -22,9 +22,11 @@ def _int_to_enum(value, enum_klass): - """Convert a numeric value to an IntEnum member. - If it's not a known member, return the numeric value itself. + """Convert a possible numeric value to an IntEnum member. + If it's not a known member, return the value itself. """ + if not isinstance(value, int): + return value try: return enum_klass(value) except ValueError: diff --git a/Lib/site.py b/Lib/site.py index 672fa7b000ad02..eea92dfc194333 100644 --- a/Lib/site.py +++ b/Lib/site.py @@ -260,6 +260,10 @@ def check_enableusersite(): # # See https://bugs.python.org/issue29585 +# Copy of sysconfig._get_implementation() +def _get_implementation(): + return 'Python' + # Copy of sysconfig._getuserbase() def _getuserbase(): env_base = os.environ.get("PYTHONUSERBASE", None) @@ -275,7 +279,7 @@ def joinuser(*args): if os.name == "nt": base = os.environ.get("APPDATA") or "~" - return joinuser(base, "Python") + return joinuser(base, _get_implementation()) if sys.platform == "darwin" and sys._framework: return joinuser("~", "Library", sys._framework, @@ -288,12 +292,14 @@ def joinuser(*args): def _get_path(userbase): version = sys.version_info + implementation = _get_implementation() + implementation_lower = implementation.lower() if os.name == 'nt': ver_nodot = sys.winver.replace('.', '') - return f'{userbase}\\Python{ver_nodot}\\site-packages' + return f'{userbase}\\{implementation}{ver_nodot}\\site-packages' if sys.platform == 'darwin' and sys._framework: - return f'{userbase}/lib/python/site-packages' + return f'{userbase}/lib/{implementation_lower}/site-packages' return f'{userbase}/lib/python{version[0]}.{version[1]}/site-packages' @@ -361,6 +367,8 @@ def getsitepackages(prefixes=None): continue seen.add(prefix) + implementation = _get_implementation().lower() + ver = sys.version_info if os.sep == '/': libdirs = [sys.platlibdir] if sys.platlibdir != "lib": @@ -368,7 +376,7 @@ def getsitepackages(prefixes=None): for libdir in libdirs: path = os.path.join(prefix, libdir, - "python%d.%d" % sys.version_info[:2], + f"{implementation}{ver[0]}.{ver[1]}", "site-packages") sitepackages.append(path) else: @@ -425,6 +433,20 @@ def setcopyright(): def sethelper(): builtins.help = _sitebuiltins._Helper() + +def gethistoryfile(): + """Check if the PYTHON_HISTORY environment variable is set and define + it as the .python_history file. If PYTHON_HISTORY is not set, use the + default .python_history file. + """ + if not sys.flags.ignore_environment: + history = os.environ.get("PYTHON_HISTORY") + if history: + return history + return os.path.join(os.path.expanduser('~'), + '.python_history') + + def enablerlcompleter(): """Enable default readline configuration on interactive prompts, by registering a sys.__interactivehook__. @@ -444,8 +466,7 @@ def register_readline(): # Reading the initialization (config) file may not be enough to set a # completion key, so we set one first and then read the file. - readline_doc = getattr(readline, '__doc__', '') - if readline_doc is not None and 'libedit' in readline_doc: + if readline.backend == 'editline': readline.parse_and_bind('bind ^I rl_complete') else: readline.parse_and_bind('tab: complete') @@ -460,13 +481,13 @@ def register_readline(): pass if readline.get_current_history_length() == 0: - # If no history was loaded, default to .python_history. + # If no history was loaded, default to .python_history, + # or PYTHON_HISTORY. # The guard is necessary to avoid doubling history size at # each interpreter exit when readline was already configured # through a PYTHONSTARTUP hook, see: # http://bugs.python.org/issue5845#msg198636 - history = os.path.join(os.path.expanduser('~'), - '.python_history') + history = gethistoryfile() try: readline.read_history_file(history) except OSError: diff --git a/Lib/socket.py b/Lib/socket.py index 321fcda51505c1..5f0a1f40e25b94 100644 --- a/Lib/socket.py +++ b/Lib/socket.py @@ -702,16 +702,15 @@ def readinto(self, b): self._checkReadable() if self._timeout_occurred: raise OSError("cannot read from timed out object") - while True: - try: - return self._sock.recv_into(b) - except timeout: - self._timeout_occurred = True - raise - except error as e: - if e.errno in _blocking_errnos: - return None - raise + try: + return self._sock.recv_into(b) + except timeout: + self._timeout_occurred = True + raise + except error as e: + if e.errno in _blocking_errnos: + return None + raise def write(self, b): """Write the given bytes or bytearray object *b* to the socket diff --git a/Lib/sqlite3/__main__.py b/Lib/sqlite3/__main__.py index 3228dbc09d502a..b93b84384a0925 100644 --- a/Lib/sqlite3/__main__.py +++ b/Lib/sqlite3/__main__.py @@ -62,7 +62,7 @@ def runsource(self, source, filename="", symbol="single"): return False -def main(): +def main(*args): parser = ArgumentParser( description="Python sqlite3 CLI", prog="python -m sqlite3", @@ -86,7 +86,7 @@ def main(): version=f"SQLite version {sqlite3.sqlite_version}", help="Print underlying SQLite library version", ) - args = parser.parse_args() + args = parser.parse_args(*args) if args.filename == ":memory:": db_name = "a transient in-memory database" @@ -116,9 +116,16 @@ def main(): else: # No SQL provided; start the REPL. console = SqliteInteractiveConsole(con) + try: + import readline + except ImportError: + pass console.interact(banner, exitmsg="") finally: con.close() + sys.exit(0) -main() + +if __name__ == "__main__": + main(sys.argv[1:]) diff --git a/Lib/sqlite3/dump.py b/Lib/sqlite3/dump.py index 07b9da10b920f9..ead3360ce67608 100644 --- a/Lib/sqlite3/dump.py +++ b/Lib/sqlite3/dump.py @@ -7,6 +7,14 @@ # future enhancements, you should normally quote any identifier that # is an English language word, even if you do not have to." +def _quote_name(name): + return '"{0}"'.format(name.replace('"', '""')) + + +def _quote_value(value): + return "'{0}'".format(value.replace("'", "''")) + + def _iterdump(connection): """ Returns an iterator to the dump of the database in an SQL text format. @@ -16,6 +24,7 @@ def _iterdump(connection): directly but instead called from the Connection method, iterdump(). """ + writeable_schema = False cu = connection.cursor() yield('BEGIN TRANSACTION;') @@ -31,34 +40,39 @@ def _iterdump(connection): sqlite_sequence = [] for table_name, type, sql in schema_res.fetchall(): if table_name == 'sqlite_sequence': - rows = cu.execute('SELECT * FROM "sqlite_sequence";').fetchall() + rows = cu.execute('SELECT * FROM "sqlite_sequence";') sqlite_sequence = ['DELETE FROM "sqlite_sequence"'] sqlite_sequence += [ - f'INSERT INTO "sqlite_sequence" VALUES(\'{row[0]}\',{row[1]})' - for row in rows + f'INSERT INTO "sqlite_sequence" VALUES({_quote_value(table_name)},{seq_value})' + for table_name, seq_value in rows.fetchall() ] continue elif table_name == 'sqlite_stat1': yield('ANALYZE "sqlite_master";') elif table_name.startswith('sqlite_'): continue - # NOTE: Virtual table support not implemented - #elif sql.startswith('CREATE VIRTUAL TABLE'): - # qtable = table_name.replace("'", "''") - # yield("INSERT INTO sqlite_master(type,name,tbl_name,rootpage,sql)"\ - # "VALUES('table','{0}','{0}',0,'{1}');".format( - # qtable, - # sql.replace("''"))) + elif sql.startswith('CREATE VIRTUAL TABLE'): + if not writeable_schema: + writeable_schema = True + yield('PRAGMA writable_schema=ON;') + yield("INSERT INTO sqlite_master(type,name,tbl_name,rootpage,sql)" + "VALUES('table',{0},{0},0,{1});".format( + _quote_value(table_name), + _quote_value(sql), + )) else: yield('{0};'.format(sql)) # Build the insert statement for each row of the current table - table_name_ident = table_name.replace('"', '""') - res = cu.execute('PRAGMA table_info("{0}")'.format(table_name_ident)) + table_name_ident = _quote_name(table_name) + res = cu.execute(f'PRAGMA table_info({table_name_ident})') column_names = [str(table_info[1]) for table_info in res.fetchall()] - q = """SELECT 'INSERT INTO "{0}" VALUES({1})' FROM "{0}";""".format( + q = "SELECT 'INSERT INTO {0} VALUES('{1}')' FROM {0};".format( table_name_ident, - ",".join("""'||quote("{0}")||'""".format(col.replace('"', '""')) for col in column_names)) + "','".join( + "||quote({0})||".format(_quote_name(col)) for col in column_names + ) + ) query_res = cu.execute(q) for row in query_res: yield("{0};".format(row[0])) @@ -74,6 +88,9 @@ def _iterdump(connection): for name, type, sql in schema_res.fetchall(): yield('{0};'.format(sql)) + if writeable_schema: + yield('PRAGMA writable_schema=OFF;') + # gh-79009: Yield statements concerning the sqlite_sequence table at the # end of the transaction. for row in sqlite_sequence: diff --git a/Lib/ssl.py b/Lib/ssl.py index 1d5873726441e4..74a9d2d8fd4fb0 100644 --- a/Lib/ssl.py +++ b/Lib/ssl.py @@ -110,13 +110,13 @@ try: from _ssl import RAND_egd except ImportError: - # LibreSSL does not provide RAND_egd + # RAND_egd is not supported on some platforms pass from _ssl import ( HAS_SNI, HAS_ECDH, HAS_NPN, HAS_ALPN, HAS_SSLv2, HAS_SSLv3, HAS_TLSv1, - HAS_TLSv1_1, HAS_TLSv1_2, HAS_TLSv1_3 + HAS_TLSv1_1, HAS_TLSv1_2, HAS_TLSv1_3, HAS_PSK ) from _ssl import _DEFAULT_CIPHERS, _OPENSSL_API_VERSION @@ -876,6 +876,31 @@ def getpeercert(self, binary_form=False): """ return self._sslobj.getpeercert(binary_form) + def get_verified_chain(self): + """Returns verified certificate chain provided by the other + end of the SSL channel as a list of DER-encoded bytes. + + If certificate verification was disabled method acts the same as + ``SSLSocket.get_unverified_chain``. + """ + chain = self._sslobj.get_verified_chain() + + if chain is None: + return [] + + return [cert.public_bytes(_ssl.ENCODING_DER) for cert in chain] + + def get_unverified_chain(self): + """Returns raw certificate chain provided by the other + end of the SSL channel as a list of DER-encoded bytes. + """ + chain = self._sslobj.get_unverified_chain() + + if chain is None: + return [] + + return [cert.public_bytes(_ssl.ENCODING_DER) for cert in chain] + def selected_npn_protocol(self): """Return the currently selected NPN protocol as a string, or ``None`` if a next protocol was not negotiated or if NPN is not supported by one @@ -975,7 +1000,7 @@ def _create(cls, sock, server_side=False, do_handshake_on_connect=True, ) self = cls.__new__(cls, **kwargs) super(SSLSocket, self).__init__(**kwargs) - self.settimeout(sock.gettimeout()) + sock_timeout = sock.gettimeout() sock.detach() self._context = context @@ -994,9 +1019,42 @@ def _create(cls, sock, server_side=False, do_handshake_on_connect=True, if e.errno != errno.ENOTCONN: raise connected = False + blocking = self.getblocking() + self.setblocking(False) + try: + # We are not connected so this is not supposed to block, but + # testing revealed otherwise on macOS and Windows so we do + # the non-blocking dance regardless. Our raise when any data + # is found means consuming the data is harmless. + notconn_pre_handshake_data = self.recv(1) + except OSError as e: + # EINVAL occurs for recv(1) on non-connected on unix sockets. + if e.errno not in (errno.ENOTCONN, errno.EINVAL): + raise + notconn_pre_handshake_data = b'' + self.setblocking(blocking) + if notconn_pre_handshake_data: + # This prevents pending data sent to the socket before it was + # closed from escaping to the caller who could otherwise + # presume it came through a successful TLS connection. + reason = "Closed before TLS handshake with data in recv buffer." + notconn_pre_handshake_data_error = SSLError(e.errno, reason) + # Add the SSLError attributes that _ssl.c always adds. + notconn_pre_handshake_data_error.reason = reason + notconn_pre_handshake_data_error.library = None + try: + self.close() + except OSError: + pass + try: + raise notconn_pre_handshake_data_error + finally: + # Explicitly break the reference cycle. + notconn_pre_handshake_data_error = None else: connected = True + self.settimeout(sock_timeout) # Must come after setblocking() calls. self._connected = connected if connected: # create the SSL object @@ -1096,6 +1154,14 @@ def getpeercert(self, binary_form=False): self._check_connected() return self._sslobj.getpeercert(binary_form) + @_sslcopydoc + def get_verified_chain(self): + return self._sslobj.get_verified_chain() + + @_sslcopydoc + def get_unverified_chain(self): + return self._sslobj.get_unverified_chain() + @_sslcopydoc def selected_npn_protocol(self): self._checkClosed() @@ -1204,10 +1270,14 @@ def recv(self, buflen=1024, flags=0): def recv_into(self, buffer, nbytes=None, flags=0): self._checkClosed() - if buffer and (nbytes is None): - nbytes = len(buffer) - elif nbytes is None: - nbytes = 1024 + if nbytes is None: + if buffer is not None: + with memoryview(buffer) as view: + nbytes = view.nbytes + if not nbytes: + nbytes = 1024 + else: + nbytes = 1024 if self._sslobj is not None: if flags != 0: raise ValueError( diff --git a/Lib/stat.py b/Lib/stat.py index fc024db3f4fbee..52cadbf04f6c88 100644 --- a/Lib/stat.py +++ b/Lib/stat.py @@ -126,6 +126,8 @@ def S_ISWHT(mode): _filemode_table = ( + # File type chars according to: + # http://en.wikibooks.org/wiki/C_Programming/POSIX_Reference/sys/stat.h ((S_IFLNK, "l"), (S_IFSOCK, "s"), # Must appear before IFREG and IFDIR as IFSOCK == IFREG | IFDIR (S_IFREG, "-"), @@ -156,13 +158,17 @@ def S_ISWHT(mode): def filemode(mode): """Convert a file's mode to a string of the form '-rwxrwxrwx'.""" perm = [] - for table in _filemode_table: + for index, table in enumerate(_filemode_table): for bit, char in table: if mode & bit == bit: perm.append(char) break else: - perm.append("-") + if index == 0: + # Unknown filetype + perm.append("?") + else: + perm.append("-") return "".join(perm) diff --git a/Lib/statistics.py b/Lib/statistics.py index 6bd214bbfe2ff5..83aaedb04515e0 100644 --- a/Lib/statistics.py +++ b/Lib/statistics.py @@ -137,6 +137,7 @@ from itertools import count, groupby, repeat from bisect import bisect_left, bisect_right from math import hypot, sqrt, fabs, exp, erf, tau, log, fsum, sumprod +from math import isfinite, isinf from functools import reduce from operator import itemgetter from collections import Counter, namedtuple, defaultdict @@ -526,8 +527,10 @@ def count(iterable): def geometric_mean(data): """Convert data to floats and compute the geometric mean. - Raises a StatisticsError if the input dataset is empty, - if it contains a zero, or if it contains a negative value. + Raises a StatisticsError if the input dataset is empty + or if it contains a negative value. + + Returns zero if the product of inputs is zero. No special efforts are made to achieve exact results. (However, this may change in the future.) @@ -535,11 +538,25 @@ def geometric_mean(data): >>> round(geometric_mean([54, 24, 36]), 9) 36.0 """ - try: - return exp(fmean(map(log, data))) - except ValueError: - raise StatisticsError('geometric mean requires a non-empty dataset ' - 'containing positive numbers') from None + n = 0 + found_zero = False + def count_positive(iterable): + nonlocal n, found_zero + for n, x in enumerate(iterable, start=1): + if x > 0.0 or math.isnan(x): + yield x + elif x == 0.0: + found_zero = True + else: + raise StatisticsError('No negative inputs allowed', x) + total = fsum(map(log, count_positive(data))) + if not n: + raise StatisticsError('Must have a non-empty dataset') + if math.isnan(total): + return math.nan + if found_zero: + return math.nan if total == math.inf else 0.0 + return exp(total / n) def harmonic_mean(data, weights=None): @@ -843,7 +860,9 @@ def quantiles(data, *, n=4, method='exclusive'): data = sorted(data) ld = len(data) if ld < 2: - raise StatisticsError('must have at least two data points') + if ld == 1: + return data * (n - 1) + raise StatisticsError('must have at least one data point') if method == 'inclusive': m = ld - 1 result = [] @@ -1004,6 +1023,27 @@ def _mean_stdev(data): # Handle Nans and Infs gracefully return float(xbar), float(xbar) / float(ss) +def _sqrtprod(x: float, y: float) -> float: + "Return sqrt(x * y) computed with improved accuracy and without overflow/underflow." + h = sqrt(x * y) + if not isfinite(h): + if isinf(h) and not isinf(x) and not isinf(y): + # Finite inputs overflowed, so scale down, and recompute. + scale = 2.0 ** -512 # sqrt(1 / sys.float_info.max) + return _sqrtprod(scale * x, scale * y) / scale + return h + if not h: + if x and y: + # Non-zero inputs underflowed, so scale up, and recompute. + # Scale: 1 / sqrt(sys.float_info.min * sys.float_info.epsilon) + scale = 2.0 ** 537 + return _sqrtprod(scale * x, scale * y) / scale + return h + # Improve accuracy with a differential correction. + # https://www.wolframalpha.com/input/?i=Maclaurin+series+sqrt%28h**2+%2B+x%29+at+x%3D0 + d = sumprod((x, h), (y, -h)) + return h + d / (2.0 * h) + # === Statistics for relations between two inputs === @@ -1083,7 +1123,7 @@ def correlation(x, y, /, *, method='linear'): sxx = sumprod(x, x) syy = sumprod(y, y) try: - return sxy / sqrt(sxx * syy) + return sxy / _sqrtprod(sxx, syy) except ZeroDivisionError: raise StatisticsError('at least one of the inputs is constant') @@ -1113,7 +1153,7 @@ def linear_regression(x, y, /, *, proportional=False): >>> noise = NormalDist().samples(5, seed=42) >>> y = [3 * x[i] + 2 + noise[i] for i in range(5)] >>> linear_regression(x, y) #doctest: +ELLIPSIS - LinearRegression(slope=3.09078914170..., intercept=1.75684970486...) + LinearRegression(slope=3.17495..., intercept=1.00925...) If *proportional* is true, the independent variable *x* and the dependent variable *y* are assumed to be directly proportional. @@ -1126,7 +1166,7 @@ def linear_regression(x, y, /, *, proportional=False): >>> y = [3 * x[i] + noise[i] for i in range(5)] >>> linear_regression(x, y, proportional=True) #doctest: +ELLIPSIS - LinearRegression(slope=3.02447542484..., intercept=0.0) + LinearRegression(slope=2.90475..., intercept=0.0) """ n = len(x) @@ -1257,9 +1297,11 @@ def from_samples(cls, data): def samples(self, n, *, seed=None): "Generate *n* samples for a given mean and standard deviation." - gauss = random.gauss if seed is None else random.Random(seed).gauss - mu, sigma = self._mu, self._sigma - return [gauss(mu, sigma) for _ in repeat(None, n)] + rnd = random.random if seed is None else random.Random(seed).random + inv_cdf = _normal_dist_inv_cdf + mu = self._mu + sigma = self._sigma + return [inv_cdf(rnd(), mu, sigma) for _ in repeat(None, n)] def pdf(self, x): "Probability density function. P(x <= X < x+dx) / dx" diff --git a/Lib/subprocess.py b/Lib/subprocess.py index 6df5dd551ea67e..d5bd9a9e31aa04 100644 --- a/Lib/subprocess.py +++ b/Lib/subprocess.py @@ -74,8 +74,8 @@ else: _mswindows = True -# wasm32-emscripten and wasm32-wasi do not support processes -_can_fork_exec = sys.platform not in {"emscripten", "wasi"} +# some platforms do not support subprocesses +_can_fork_exec = sys.platform not in {"emscripten", "wasi", "ios", "tvos", "watchos"} if _mswindows: import _winapi @@ -103,18 +103,22 @@ if _can_fork_exec: from _posixsubprocess import fork_exec as _fork_exec # used in methods that are called by __del__ - _waitpid = os.waitpid - _waitstatus_to_exitcode = os.waitstatus_to_exitcode - _WIFSTOPPED = os.WIFSTOPPED - _WSTOPSIG = os.WSTOPSIG - _WNOHANG = os.WNOHANG + class _del_safe: + waitpid = os.waitpid + waitstatus_to_exitcode = os.waitstatus_to_exitcode + WIFSTOPPED = os.WIFSTOPPED + WSTOPSIG = os.WSTOPSIG + WNOHANG = os.WNOHANG + ECHILD = errno.ECHILD else: - _fork_exec = None - _waitpid = None - _waitstatus_to_exitcode = None - _WIFSTOPPED = None - _WSTOPSIG = None - _WNOHANG = None + class _del_safe: + waitpid = None + waitstatus_to_exitcode = None + WIFSTOPPED = None + WSTOPSIG = None + WNOHANG = None + ECHILD = errno.ECHILD + import select import selectors @@ -744,6 +748,7 @@ def _use_posix_spawn(): # guarantee the given libc/syscall API will be used. _USE_POSIX_SPAWN = _use_posix_spawn() _USE_VFORK = True +_HAVE_POSIX_SPAWN_CLOSEFROM = hasattr(os, 'POSIX_SPAWN_CLOSEFROM') class Popen: @@ -1747,14 +1752,11 @@ def _get_handles(self, stdin, stdout, stderr): errread, errwrite) - def _posix_spawn(self, args, executable, env, restore_signals, + def _posix_spawn(self, args, executable, env, restore_signals, close_fds, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite): """Execute program using os.posix_spawn().""" - if env is None: - env = os.environ - kwargs = {} if restore_signals: # See _Py_RestoreSignals() in Python/pylifecycle.c @@ -1776,6 +1778,10 @@ def _posix_spawn(self, args, executable, env, restore_signals, ): if fd != -1: file_actions.append((os.POSIX_SPAWN_DUP2, fd, fd2)) + + if close_fds: + file_actions.append((os.POSIX_SPAWN_CLOSEFROM, 3)) + if file_actions: kwargs['file_actions'] = file_actions @@ -1823,7 +1829,7 @@ def _execute_child(self, args, executable, preexec_fn, close_fds, if (_USE_POSIX_SPAWN and os.path.dirname(executable) and preexec_fn is None - and not close_fds + and (not close_fds or _HAVE_POSIX_SPAWN_CLOSEFROM) and not pass_fds and cwd is None and (p2cread == -1 or p2cread > 2) @@ -1835,7 +1841,7 @@ def _execute_child(self, args, executable, preexec_fn, close_fds, and gids is None and uid is None and umask < 0): - self._posix_spawn(args, executable, env, restore_signals, + self._posix_spawn(args, executable, env, restore_signals, close_fds, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite) @@ -1951,20 +1957,16 @@ def _execute_child(self, args, executable, preexec_fn, close_fds, raise child_exception_type(err_msg) - def _handle_exitstatus(self, sts, - _waitstatus_to_exitcode=_waitstatus_to_exitcode, - _WIFSTOPPED=_WIFSTOPPED, - _WSTOPSIG=_WSTOPSIG): + def _handle_exitstatus(self, sts, _del_safe=_del_safe): """All callers to this function MUST hold self._waitpid_lock.""" # This method is called (indirectly) by __del__, so it cannot # refer to anything outside of its local scope. - if _WIFSTOPPED(sts): - self.returncode = -_WSTOPSIG(sts) + if _del_safe.WIFSTOPPED(sts): + self.returncode = -_del_safe.WSTOPSIG(sts) else: - self.returncode = _waitstatus_to_exitcode(sts) + self.returncode = _del_safe.waitstatus_to_exitcode(sts) - def _internal_poll(self, _deadstate=None, _waitpid=_waitpid, - _WNOHANG=_WNOHANG, _ECHILD=errno.ECHILD): + def _internal_poll(self, _deadstate=None, _del_safe=_del_safe): """Check if child process has terminated. Returns returncode attribute. @@ -1980,13 +1982,13 @@ def _internal_poll(self, _deadstate=None, _waitpid=_waitpid, try: if self.returncode is not None: return self.returncode # Another thread waited. - pid, sts = _waitpid(self.pid, _WNOHANG) + pid, sts = _del_safe.waitpid(self.pid, _del_safe.WNOHANG) if pid == self.pid: self._handle_exitstatus(sts) except OSError as e: if _deadstate is not None: self.returncode = _deadstate - elif e.errno == _ECHILD: + elif e.errno == _del_safe.ECHILD: # This happens if SIGCLD is set to be ignored or # waiting for child processes has otherwise been # disabled for our process. This child is dead, we diff --git a/Lib/symtable.py b/Lib/symtable.py index 5dd71ffc6b4f19..17f820abd56660 100644 --- a/Lib/symtable.py +++ b/Lib/symtable.py @@ -62,8 +62,8 @@ def __repr__(self): def get_type(self): """Return the type of the symbol table. - The values returned are 'class', 'module' and - 'function'. + The values returned are 'class', 'module', 'function', + 'annotation', 'TypeVar bound', 'type alias', and 'type parameter'. """ if self._table.type == _symtable.TYPE_MODULE: return "module" @@ -71,8 +71,15 @@ def get_type(self): return "function" if self._table.type == _symtable.TYPE_CLASS: return "class" - assert self._table.type in (1, 2, 3), \ - "unexpected type: {0}".format(self._table.type) + if self._table.type == _symtable.TYPE_ANNOTATION: + return "annotation" + if self._table.type == _symtable.TYPE_TYPE_VAR_BOUND: + return "TypeVar bound" + if self._table.type == _symtable.TYPE_TYPE_ALIAS: + return "type alias" + if self._table.type == _symtable.TYPE_TYPE_PARAM: + return "type parameter" + assert False, f"unexpected type: {self._table.type}" def get_id(self): """Return an identifier for the table. @@ -226,7 +233,16 @@ def __init__(self, name, flags, namespaces=None, *, module_scope=False): self.__module_scope = module_scope def __repr__(self): - return "".format(self.__name) + flags_str = '|'.join(self._flags_str()) + return f'' + + def _scope_str(self): + return _scopes_value_to_name.get(self.__scope) or str(self.__scope) + + def _flags_str(self): + for flagname, flagvalue in _flags: + if self.__flags & flagvalue == flagvalue: + yield flagname def get_name(self): """Return a name of a symbol. @@ -316,11 +332,43 @@ def get_namespace(self): else: return self.__namespaces[0] + +_flags = [('USE', USE)] +_flags.extend(kv for kv in globals().items() if kv[0].startswith('DEF_')) +_scopes_names = ('FREE', 'LOCAL', 'GLOBAL_IMPLICIT', 'GLOBAL_EXPLICIT', 'CELL') +_scopes_value_to_name = {globals()[n]: n for n in _scopes_names} + + +def main(args): + import sys + def print_symbols(table, level=0): + indent = ' ' * level + nested = "nested " if table.is_nested() else "" + if table.get_type() == 'module': + what = f'from file {table._filename!r}' + else: + what = f'{table.get_name()!r}' + print(f'{indent}symbol table for {nested}{table.get_type()} {what}:') + for ident in table.get_identifiers(): + symbol = table.lookup(ident) + flags = ', '.join(symbol._flags_str()).lower() + print(f' {indent}{symbol._scope_str().lower()} symbol {symbol.get_name()!r}: {flags}') + print() + + for table2 in table.get_children(): + print_symbols(table2, level + 1) + + for filename in args or ['-']: + if filename == '-': + src = sys.stdin.read() + filename = '' + else: + with open(filename, 'rb') as f: + src = f.read() + mod = symtable(src, filename, 'exec') + print_symbols(mod) + + if __name__ == "__main__": - import os, sys - with open(sys.argv[0]) as f: - src = f.read() - mod = symtable(src, os.path.split(sys.argv[0])[1], "exec") - for ident in mod.get_identifiers(): - info = mod.lookup(ident) - print(info, info.is_local(), info.is_namespace()) + import sys + main(sys.argv[1:]) diff --git a/Lib/sysconfig.py b/Lib/sysconfig.py deleted file mode 100644 index a8b5c5f7dfba5b..00000000000000 --- a/Lib/sysconfig.py +++ /dev/null @@ -1,880 +0,0 @@ -"""Access to Python's configuration information.""" - -import os -import sys -import threading -from os.path import realpath - -__all__ = [ - 'get_config_h_filename', - 'get_config_var', - 'get_config_vars', - 'get_makefile_filename', - 'get_path', - 'get_path_names', - 'get_paths', - 'get_platform', - 'get_python_version', - 'get_scheme_names', - 'parse_config_h', -] - -# Keys for get_config_var() that are never converted to Python integers. -_ALWAYS_STR = { - 'MACOSX_DEPLOYMENT_TARGET', -} - -_INSTALL_SCHEMES = { - 'posix_prefix': { - 'stdlib': '{installed_base}/{platlibdir}/python{py_version_short}', - 'platstdlib': '{platbase}/{platlibdir}/python{py_version_short}', - 'purelib': '{base}/lib/python{py_version_short}/site-packages', - 'platlib': '{platbase}/{platlibdir}/python{py_version_short}/site-packages', - 'include': - '{installed_base}/include/python{py_version_short}{abiflags}', - 'platinclude': - '{installed_platbase}/include/python{py_version_short}{abiflags}', - 'scripts': '{base}/bin', - 'data': '{base}', - }, - 'posix_home': { - 'stdlib': '{installed_base}/lib/python', - 'platstdlib': '{base}/lib/python', - 'purelib': '{base}/lib/python', - 'platlib': '{base}/lib/python', - 'include': '{installed_base}/include/python', - 'platinclude': '{installed_base}/include/python', - 'scripts': '{base}/bin', - 'data': '{base}', - }, - 'nt': { - 'stdlib': '{installed_base}/Lib', - 'platstdlib': '{base}/Lib', - 'purelib': '{base}/Lib/site-packages', - 'platlib': '{base}/Lib/site-packages', - 'include': '{installed_base}/Include', - 'platinclude': '{installed_base}/Include', - 'scripts': '{base}/Scripts', - 'data': '{base}', - }, - # Downstream distributors can overwrite the default install scheme. - # This is done to support downstream modifications where distributors change - # the installation layout (eg. different site-packages directory). - # So, distributors will change the default scheme to one that correctly - # represents their layout. - # This presents an issue for projects/people that need to bootstrap virtual - # environments, like virtualenv. As distributors might now be customizing - # the default install scheme, there is no guarantee that the information - # returned by sysconfig.get_default_scheme/get_paths is correct for - # a virtual environment, the only guarantee we have is that it is correct - # for the *current* environment. When bootstrapping a virtual environment, - # we need to know its layout, so that we can place the files in the - # correct locations. - # The "*_venv" install scheme is a scheme to bootstrap virtual environments, - # essentially identical to the default posix_prefix/nt schemes. - # Downstream distributors who patch posix_prefix/nt scheme are encouraged to - # leave the following schemes unchanged - 'posix_venv': { - 'stdlib': '{installed_base}/{platlibdir}/python{py_version_short}', - 'platstdlib': '{platbase}/{platlibdir}/python{py_version_short}', - 'purelib': '{base}/lib/python{py_version_short}/site-packages', - 'platlib': '{platbase}/{platlibdir}/python{py_version_short}/site-packages', - 'include': - '{installed_base}/include/python{py_version_short}{abiflags}', - 'platinclude': - '{installed_platbase}/include/python{py_version_short}{abiflags}', - 'scripts': '{base}/bin', - 'data': '{base}', - }, - 'nt_venv': { - 'stdlib': '{installed_base}/Lib', - 'platstdlib': '{base}/Lib', - 'purelib': '{base}/Lib/site-packages', - 'platlib': '{base}/Lib/site-packages', - 'include': '{installed_base}/Include', - 'platinclude': '{installed_base}/Include', - 'scripts': '{base}/Scripts', - 'data': '{base}', - }, - } - -# For the OS-native venv scheme, we essentially provide an alias: -if os.name == 'nt': - _INSTALL_SCHEMES['venv'] = _INSTALL_SCHEMES['nt_venv'] -else: - _INSTALL_SCHEMES['venv'] = _INSTALL_SCHEMES['posix_venv'] - - -# NOTE: site.py has copy of this function. -# Sync it when modify this function. -def _getuserbase(): - env_base = os.environ.get("PYTHONUSERBASE", None) - if env_base: - return env_base - - # Emscripten, VxWorks, and WASI have no home directories - if sys.platform in {"emscripten", "vxworks", "wasi"}: - return None - - def joinuser(*args): - return os.path.expanduser(os.path.join(*args)) - - if os.name == "nt": - base = os.environ.get("APPDATA") or "~" - return joinuser(base, "Python") - - if sys.platform == "darwin" and sys._framework: - return joinuser("~", "Library", sys._framework, - f"{sys.version_info[0]}.{sys.version_info[1]}") - - return joinuser("~", ".local") - -_HAS_USER_BASE = (_getuserbase() is not None) - -if _HAS_USER_BASE: - _INSTALL_SCHEMES |= { - # NOTE: When modifying "purelib" scheme, update site._get_path() too. - 'nt_user': { - 'stdlib': '{userbase}/Python{py_version_nodot_plat}', - 'platstdlib': '{userbase}/Python{py_version_nodot_plat}', - 'purelib': '{userbase}/Python{py_version_nodot_plat}/site-packages', - 'platlib': '{userbase}/Python{py_version_nodot_plat}/site-packages', - 'include': '{userbase}/Python{py_version_nodot_plat}/Include', - 'scripts': '{userbase}/Python{py_version_nodot_plat}/Scripts', - 'data': '{userbase}', - }, - 'posix_user': { - 'stdlib': '{userbase}/{platlibdir}/python{py_version_short}', - 'platstdlib': '{userbase}/{platlibdir}/python{py_version_short}', - 'purelib': '{userbase}/lib/python{py_version_short}/site-packages', - 'platlib': '{userbase}/lib/python{py_version_short}/site-packages', - 'include': '{userbase}/include/python{py_version_short}', - 'scripts': '{userbase}/bin', - 'data': '{userbase}', - }, - 'osx_framework_user': { - 'stdlib': '{userbase}/lib/python', - 'platstdlib': '{userbase}/lib/python', - 'purelib': '{userbase}/lib/python/site-packages', - 'platlib': '{userbase}/lib/python/site-packages', - 'include': '{userbase}/include/python{py_version_short}', - 'scripts': '{userbase}/bin', - 'data': '{userbase}', - }, - } - -_SCHEME_KEYS = ('stdlib', 'platstdlib', 'purelib', 'platlib', 'include', - 'scripts', 'data') - -_PY_VERSION = sys.version.split()[0] -_PY_VERSION_SHORT = f'{sys.version_info[0]}.{sys.version_info[1]}' -_PY_VERSION_SHORT_NO_DOT = f'{sys.version_info[0]}{sys.version_info[1]}' -_PREFIX = os.path.normpath(sys.prefix) -_BASE_PREFIX = os.path.normpath(sys.base_prefix) -_EXEC_PREFIX = os.path.normpath(sys.exec_prefix) -_BASE_EXEC_PREFIX = os.path.normpath(sys.base_exec_prefix) -# Mutex guarding initialization of _CONFIG_VARS. -_CONFIG_VARS_LOCK = threading.RLock() -_CONFIG_VARS = None -# True iff _CONFIG_VARS has been fully initialized. -_CONFIG_VARS_INITIALIZED = False -_USER_BASE = None - -# Regexes needed for parsing Makefile (and similar syntaxes, -# like old-style Setup files). -_variable_rx = r"([a-zA-Z][a-zA-Z0-9_]+)\s*=\s*(.*)" -_findvar1_rx = r"\$\(([A-Za-z][A-Za-z0-9_]*)\)" -_findvar2_rx = r"\${([A-Za-z][A-Za-z0-9_]*)}" - - -def _safe_realpath(path): - try: - return realpath(path) - except OSError: - return path - -if sys.executable: - _PROJECT_BASE = os.path.dirname(_safe_realpath(sys.executable)) -else: - # sys.executable can be empty if argv[0] has been changed and Python is - # unable to retrieve the real program name - _PROJECT_BASE = _safe_realpath(os.getcwd()) - -# In a virtual environment, `sys._home` gives us the target directory -# `_PROJECT_BASE` for the executable that created it when the virtual -# python is an actual executable ('venv --copies' or Windows). -_sys_home = getattr(sys, '_home', None) -if _sys_home: - _PROJECT_BASE = _sys_home - -if os.name == 'nt': - # In a source build, the executable is in a subdirectory of the root - # that we want (\PCbuild\). - # `_BASE_PREFIX` is used as the base installation is where the source - # will be. The realpath is needed to prevent mount point confusion - # that can occur with just string comparisons. - if _safe_realpath(_PROJECT_BASE).startswith( - _safe_realpath(f'{_BASE_PREFIX}\\PCbuild')): - _PROJECT_BASE = _BASE_PREFIX - -# set for cross builds -if "_PYTHON_PROJECT_BASE" in os.environ: - _PROJECT_BASE = _safe_realpath(os.environ["_PYTHON_PROJECT_BASE"]) - -def is_python_build(check_home=None): - if check_home is not None: - import warnings - warnings.warn("check_home argument is deprecated and ignored.", - DeprecationWarning, stacklevel=2) - for fn in ("Setup", "Setup.local"): - if os.path.isfile(os.path.join(_PROJECT_BASE, "Modules", fn)): - return True - return False - -_PYTHON_BUILD = is_python_build() - -if _PYTHON_BUILD: - for scheme in ('posix_prefix', 'posix_home'): - # On POSIX-y platforms, Python will: - # - Build from .h files in 'headers' (which is only added to the - # scheme when building CPython) - # - Install .h files to 'include' - scheme = _INSTALL_SCHEMES[scheme] - scheme['headers'] = scheme['include'] - scheme['include'] = '{srcdir}/Include' - scheme['platinclude'] = '{projectbase}/.' - del scheme - - -def _subst_vars(s, local_vars): - try: - return s.format(**local_vars) - except KeyError as var: - try: - return s.format(**os.environ) - except KeyError: - raise AttributeError(f'{var}') from None - -def _extend_dict(target_dict, other_dict): - target_keys = target_dict.keys() - for key, value in other_dict.items(): - if key in target_keys: - continue - target_dict[key] = value - - -def _expand_vars(scheme, vars): - res = {} - if vars is None: - vars = {} - _extend_dict(vars, get_config_vars()) - if os.name == 'nt': - # On Windows we want to substitute 'lib' for schemes rather - # than the native value (without modifying vars, in case it - # was passed in) - vars = vars | {'platlibdir': 'lib'} - - for key, value in _INSTALL_SCHEMES[scheme].items(): - if os.name in ('posix', 'nt'): - value = os.path.expanduser(value) - res[key] = os.path.normpath(_subst_vars(value, vars)) - return res - - -def _get_preferred_schemes(): - if os.name == 'nt': - return { - 'prefix': 'nt', - 'home': 'posix_home', - 'user': 'nt_user', - } - if sys.platform == 'darwin' and sys._framework: - return { - 'prefix': 'posix_prefix', - 'home': 'posix_home', - 'user': 'osx_framework_user', - } - return { - 'prefix': 'posix_prefix', - 'home': 'posix_home', - 'user': 'posix_user', - } - - -def get_preferred_scheme(key): - if key == 'prefix' and sys.prefix != sys.base_prefix: - return 'venv' - scheme = _get_preferred_schemes()[key] - if scheme not in _INSTALL_SCHEMES: - raise ValueError( - f"{key!r} returned {scheme!r}, which is not a valid scheme " - f"on this platform" - ) - return scheme - - -def get_default_scheme(): - return get_preferred_scheme('prefix') - - -def _parse_makefile(filename, vars=None, keep_unresolved=True): - """Parse a Makefile-style file. - - A dictionary containing name/value pairs is returned. If an - optional dictionary is passed in as the second argument, it is - used instead of a new dictionary. - """ - import re - - if vars is None: - vars = {} - done = {} - notdone = {} - - with open(filename, encoding=sys.getfilesystemencoding(), - errors="surrogateescape") as f: - lines = f.readlines() - - for line in lines: - if line.startswith('#') or line.strip() == '': - continue - m = re.match(_variable_rx, line) - if m: - n, v = m.group(1, 2) - v = v.strip() - # `$$' is a literal `$' in make - tmpv = v.replace('$$', '') - - if "$" in tmpv: - notdone[n] = v - else: - try: - if n in _ALWAYS_STR: - raise ValueError - - v = int(v) - except ValueError: - # insert literal `$' - done[n] = v.replace('$$', '$') - else: - done[n] = v - - # do variable interpolation here - variables = list(notdone.keys()) - - # Variables with a 'PY_' prefix in the makefile. These need to - # be made available without that prefix through sysconfig. - # Special care is needed to ensure that variable expansion works, even - # if the expansion uses the name without a prefix. - renamed_variables = ('CFLAGS', 'LDFLAGS', 'CPPFLAGS') - - while len(variables) > 0: - for name in tuple(variables): - value = notdone[name] - m1 = re.search(_findvar1_rx, value) - m2 = re.search(_findvar2_rx, value) - if m1 and m2: - m = m1 if m1.start() < m2.start() else m2 - else: - m = m1 if m1 else m2 - if m is not None: - n = m.group(1) - found = True - if n in done: - item = str(done[n]) - elif n in notdone: - # get it on a subsequent round - found = False - elif n in os.environ: - # do it like make: fall back to environment - item = os.environ[n] - - elif n in renamed_variables: - if (name.startswith('PY_') and - name[3:] in renamed_variables): - item = "" - - elif 'PY_' + n in notdone: - found = False - - else: - item = str(done['PY_' + n]) - - else: - done[n] = item = "" - - if found: - after = value[m.end():] - value = value[:m.start()] + item + after - if "$" in after: - notdone[name] = value - else: - try: - if name in _ALWAYS_STR: - raise ValueError - value = int(value) - except ValueError: - done[name] = value.strip() - else: - done[name] = value - variables.remove(name) - - if name.startswith('PY_') \ - and name[3:] in renamed_variables: - - name = name[3:] - if name not in done: - done[name] = value - - else: - # Adds unresolved variables to the done dict. - # This is disabled when called from distutils.sysconfig - if keep_unresolved: - done[name] = value - # bogus variable reference (e.g. "prefix=$/opt/python"); - # just drop it since we can't deal - variables.remove(name) - - # strip spurious spaces - for k, v in done.items(): - if isinstance(v, str): - done[k] = v.strip() - - # save the results in the global dictionary - vars.update(done) - return vars - - -def get_makefile_filename(): - """Return the path of the Makefile.""" - if _PYTHON_BUILD: - return os.path.join(_PROJECT_BASE, "Makefile") - if hasattr(sys, 'abiflags'): - config_dir_name = f'config-{_PY_VERSION_SHORT}{sys.abiflags}' - else: - config_dir_name = 'config' - if hasattr(sys.implementation, '_multiarch'): - config_dir_name += f'-{sys.implementation._multiarch}' - return os.path.join(get_path('stdlib'), config_dir_name, 'Makefile') - - -def _get_sysconfigdata_name(): - multiarch = getattr(sys.implementation, '_multiarch', '') - return os.environ.get( - '_PYTHON_SYSCONFIGDATA_NAME', - f'_sysconfigdata_{sys.abiflags}_{sys.platform}_{multiarch}', - ) - -def _print_config_dict(d, stream): - print ("{", file=stream) - for k, v in sorted(d.items()): - print(f" {k!r}: {v!r},", file=stream) - print ("}", file=stream) - -def _generate_posix_vars(): - """Generate the Python module containing build-time variables.""" - vars = {} - # load the installed Makefile: - makefile = get_makefile_filename() - try: - _parse_makefile(makefile, vars) - except OSError as e: - msg = f"invalid Python installation: unable to open {makefile}" - if hasattr(e, "strerror"): - msg = f"{msg} ({e.strerror})" - raise OSError(msg) - # load the installed pyconfig.h: - config_h = get_config_h_filename() - try: - with open(config_h, encoding="utf-8") as f: - parse_config_h(f, vars) - except OSError as e: - msg = f"invalid Python installation: unable to open {config_h}" - if hasattr(e, "strerror"): - msg = f"{msg} ({e.strerror})" - raise OSError(msg) - # On AIX, there are wrong paths to the linker scripts in the Makefile - # -- these paths are relative to the Python source, but when installed - # the scripts are in another directory. - if _PYTHON_BUILD: - vars['BLDSHARED'] = vars['LDSHARED'] - - # There's a chicken-and-egg situation on OS X with regards to the - # _sysconfigdata module after the changes introduced by #15298: - # get_config_vars() is called by get_platform() as part of the - # `make pybuilddir.txt` target -- which is a precursor to the - # _sysconfigdata.py module being constructed. Unfortunately, - # get_config_vars() eventually calls _init_posix(), which attempts - # to import _sysconfigdata, which we won't have built yet. In order - # for _init_posix() to work, if we're on Darwin, just mock up the - # _sysconfigdata module manually and populate it with the build vars. - # This is more than sufficient for ensuring the subsequent call to - # get_platform() succeeds. - name = _get_sysconfigdata_name() - if 'darwin' in sys.platform: - import types - module = types.ModuleType(name) - module.build_time_vars = vars - sys.modules[name] = module - - pybuilddir = f'build/lib.{get_platform()}-{_PY_VERSION_SHORT}' - if hasattr(sys, "gettotalrefcount"): - pybuilddir += '-pydebug' - os.makedirs(pybuilddir, exist_ok=True) - destfile = os.path.join(pybuilddir, name + '.py') - - with open(destfile, 'w', encoding='utf8') as f: - f.write('# system configuration generated and used by' - ' the sysconfig module\n') - f.write('build_time_vars = ') - _print_config_dict(vars, stream=f) - - # Create file used for sys.path fixup -- see Modules/getpath.c - with open('pybuilddir.txt', 'w', encoding='utf8') as f: - f.write(pybuilddir) - -def _init_posix(vars): - """Initialize the module as appropriate for POSIX systems.""" - # _sysconfigdata is generated at build time, see _generate_posix_vars() - name = _get_sysconfigdata_name() - _temp = __import__(name, globals(), locals(), ['build_time_vars'], 0) - build_time_vars = _temp.build_time_vars - vars.update(build_time_vars) - -def _init_non_posix(vars): - """Initialize the module as appropriate for NT""" - # set basic install directories - import _imp - vars['LIBDEST'] = get_path('stdlib') - vars['BINLIBDEST'] = get_path('platstdlib') - vars['INCLUDEPY'] = get_path('include') - try: - # GH-99201: _imp.extension_suffixes may be empty when - # HAVE_DYNAMIC_LOADING is not set. In this case, don't set EXT_SUFFIX. - vars['EXT_SUFFIX'] = _imp.extension_suffixes()[0] - except IndexError: - pass - vars['EXE'] = '.exe' - vars['VERSION'] = _PY_VERSION_SHORT_NO_DOT - vars['BINDIR'] = os.path.dirname(_safe_realpath(sys.executable)) - vars['TZPATH'] = '' - -# -# public APIs -# - - -def parse_config_h(fp, vars=None): - """Parse a config.h-style file. - - A dictionary containing name/value pairs is returned. If an - optional dictionary is passed in as the second argument, it is - used instead of a new dictionary. - """ - if vars is None: - vars = {} - import re - define_rx = re.compile("#define ([A-Z][A-Za-z0-9_]+) (.*)\n") - undef_rx = re.compile("/[*] #undef ([A-Z][A-Za-z0-9_]+) [*]/\n") - - while True: - line = fp.readline() - if not line: - break - m = define_rx.match(line) - if m: - n, v = m.group(1, 2) - try: - if n in _ALWAYS_STR: - raise ValueError - v = int(v) - except ValueError: - pass - vars[n] = v - else: - m = undef_rx.match(line) - if m: - vars[m.group(1)] = 0 - return vars - - -def get_config_h_filename(): - """Return the path of pyconfig.h.""" - if _PYTHON_BUILD: - if os.name == "nt": - inc_dir = os.path.join(_PROJECT_BASE, "PC") - else: - inc_dir = _PROJECT_BASE - else: - inc_dir = get_path('platinclude') - return os.path.join(inc_dir, 'pyconfig.h') - - -def get_scheme_names(): - """Return a tuple containing the schemes names.""" - return tuple(sorted(_INSTALL_SCHEMES)) - - -def get_path_names(): - """Return a tuple containing the paths names.""" - return _SCHEME_KEYS - - -def get_paths(scheme=get_default_scheme(), vars=None, expand=True): - """Return a mapping containing an install scheme. - - ``scheme`` is the install scheme name. If not provided, it will - return the default scheme for the current platform. - """ - if expand: - return _expand_vars(scheme, vars) - else: - return _INSTALL_SCHEMES[scheme] - - -def get_path(name, scheme=get_default_scheme(), vars=None, expand=True): - """Return a path corresponding to the scheme. - - ``scheme`` is the install scheme name. - """ - return get_paths(scheme, vars, expand)[name] - - -def _init_config_vars(): - global _CONFIG_VARS - _CONFIG_VARS = {} - # Normalized versions of prefix and exec_prefix are handy to have; - # in fact, these are the standard versions used most places in the - # Distutils. - _CONFIG_VARS['prefix'] = _PREFIX - _CONFIG_VARS['exec_prefix'] = _EXEC_PREFIX - _CONFIG_VARS['py_version'] = _PY_VERSION - _CONFIG_VARS['py_version_short'] = _PY_VERSION_SHORT - _CONFIG_VARS['py_version_nodot'] = _PY_VERSION_SHORT_NO_DOT - _CONFIG_VARS['installed_base'] = _BASE_PREFIX - _CONFIG_VARS['base'] = _PREFIX - _CONFIG_VARS['installed_platbase'] = _BASE_EXEC_PREFIX - _CONFIG_VARS['platbase'] = _EXEC_PREFIX - _CONFIG_VARS['projectbase'] = _PROJECT_BASE - _CONFIG_VARS['platlibdir'] = sys.platlibdir - try: - _CONFIG_VARS['abiflags'] = sys.abiflags - except AttributeError: - # sys.abiflags may not be defined on all platforms. - _CONFIG_VARS['abiflags'] = '' - try: - _CONFIG_VARS['py_version_nodot_plat'] = sys.winver.replace('.', '') - except AttributeError: - _CONFIG_VARS['py_version_nodot_plat'] = '' - - if os.name == 'nt': - _init_non_posix(_CONFIG_VARS) - _CONFIG_VARS['VPATH'] = sys._vpath - if os.name == 'posix': - _init_posix(_CONFIG_VARS) - if _HAS_USER_BASE: - # Setting 'userbase' is done below the call to the - # init function to enable using 'get_config_var' in - # the init-function. - _CONFIG_VARS['userbase'] = _getuserbase() - - # Always convert srcdir to an absolute path - srcdir = _CONFIG_VARS.get('srcdir', _PROJECT_BASE) - if os.name == 'posix': - if _PYTHON_BUILD: - # If srcdir is a relative path (typically '.' or '..') - # then it should be interpreted relative to the directory - # containing Makefile. - base = os.path.dirname(get_makefile_filename()) - srcdir = os.path.join(base, srcdir) - else: - # srcdir is not meaningful since the installation is - # spread about the filesystem. We choose the - # directory containing the Makefile since we know it - # exists. - srcdir = os.path.dirname(get_makefile_filename()) - _CONFIG_VARS['srcdir'] = _safe_realpath(srcdir) - - # OS X platforms require special customization to handle - # multi-architecture, multi-os-version installers - if sys.platform == 'darwin': - import _osx_support - _osx_support.customize_config_vars(_CONFIG_VARS) - - global _CONFIG_VARS_INITIALIZED - _CONFIG_VARS_INITIALIZED = True - - -def get_config_vars(*args): - """With no arguments, return a dictionary of all configuration - variables relevant for the current platform. - - On Unix, this means every variable defined in Python's installed Makefile; - On Windows it's a much smaller set. - - With arguments, return a list of values that result from looking up - each argument in the configuration variable dictionary. - """ - - # Avoid claiming the lock once initialization is complete. - if not _CONFIG_VARS_INITIALIZED: - with _CONFIG_VARS_LOCK: - # Test again with the lock held to avoid races. Note that - # we test _CONFIG_VARS here, not _CONFIG_VARS_INITIALIZED, - # to ensure that recursive calls to get_config_vars() - # don't re-enter init_config_vars(). - if _CONFIG_VARS is None: - _init_config_vars() - - if args: - vals = [] - for name in args: - vals.append(_CONFIG_VARS.get(name)) - return vals - else: - return _CONFIG_VARS - - -def get_config_var(name): - """Return the value of a single variable using the dictionary returned by - 'get_config_vars()'. - - Equivalent to get_config_vars().get(name) - """ - return get_config_vars().get(name) - - -def get_platform(): - """Return a string that identifies the current platform. - - This is used mainly to distinguish platform-specific build directories and - platform-specific built distributions. Typically includes the OS name and - version and the architecture (as supplied by 'os.uname()'), although the - exact information included depends on the OS; on Linux, the kernel version - isn't particularly important. - - Examples of returned values: - linux-i586 - linux-alpha (?) - solaris-2.6-sun4u - - Windows will return one of: - win-amd64 (64bit Windows on AMD64 (aka x86_64, Intel64, EM64T, etc) - win32 (all others - specifically, sys.platform is returned) - - For other non-POSIX platforms, currently just returns 'sys.platform'. - - """ - if os.name == 'nt': - if 'amd64' in sys.version.lower(): - return 'win-amd64' - if '(arm)' in sys.version.lower(): - return 'win-arm32' - if '(arm64)' in sys.version.lower(): - return 'win-arm64' - return sys.platform - - if os.name != "posix" or not hasattr(os, 'uname'): - # XXX what about the architecture? NT is Intel or Alpha - return sys.platform - - # Set for cross builds explicitly - if "_PYTHON_HOST_PLATFORM" in os.environ: - return os.environ["_PYTHON_HOST_PLATFORM"] - - # Try to distinguish various flavours of Unix - osname, host, release, version, machine = os.uname() - - # Convert the OS name to lowercase, remove '/' characters, and translate - # spaces (for "Power Macintosh") - osname = osname.lower().replace('/', '') - machine = machine.replace(' ', '_') - machine = machine.replace('/', '-') - - if osname[:5] == "linux": - # At least on Linux/Intel, 'machine' is the processor -- - # i386, etc. - # XXX what about Alpha, SPARC, etc? - return f"{osname}-{machine}" - elif osname[:5] == "sunos": - if release[0] >= "5": # SunOS 5 == Solaris 2 - osname = "solaris" - release = f"{int(release[0]) - 3}.{release[2:]}" - # We can't use "platform.architecture()[0]" because a - # bootstrap problem. We use a dict to get an error - # if some suspicious happens. - bitness = {2147483647:"32bit", 9223372036854775807:"64bit"} - machine += f".{bitness[sys.maxsize]}" - # fall through to standard osname-release-machine representation - elif osname[:3] == "aix": - from _aix_support import aix_platform - return aix_platform() - elif osname[:6] == "cygwin": - osname = "cygwin" - import re - rel_re = re.compile(r'[\d.]+') - m = rel_re.match(release) - if m: - release = m.group() - elif osname[:6] == "darwin": - import _osx_support - osname, release, machine = _osx_support.get_platform_osx( - get_config_vars(), - osname, release, machine) - - return f"{osname}-{release}-{machine}" - - -def get_python_version(): - return _PY_VERSION_SHORT - - -def expand_makefile_vars(s, vars): - """Expand Makefile-style variables -- "${foo}" or "$(foo)" -- in - 'string' according to 'vars' (a dictionary mapping variable names to - values). Variables not present in 'vars' are silently expanded to the - empty string. The variable values in 'vars' should not contain further - variable expansions; if 'vars' is the output of 'parse_makefile()', - you're fine. Returns a variable-expanded version of 's'. - """ - import re - - # This algorithm does multiple expansion, so if vars['foo'] contains - # "${bar}", it will expand ${foo} to ${bar}, and then expand - # ${bar}... and so forth. This is fine as long as 'vars' comes from - # 'parse_makefile()', which takes care of such expansions eagerly, - # according to make's variable expansion semantics. - - while True: - m = re.search(_findvar1_rx, s) or re.search(_findvar2_rx, s) - if m: - (beg, end) = m.span() - s = s[0:beg] + vars.get(m.group(1)) + s[end:] - else: - break - return s - - -def _print_dict(title, data): - for index, (key, value) in enumerate(sorted(data.items())): - if index == 0: - print(f'{title}: ') - print(f'\t{key} = "{value}"') - - -def _main(): - """Display all information sysconfig detains.""" - if '--generate-posix-vars' in sys.argv: - _generate_posix_vars() - return - print(f'Platform: "{get_platform()}"') - print(f'Python version: "{get_python_version()}"') - print(f'Current installation scheme: "{get_default_scheme()}"') - print() - _print_dict('Paths', get_paths()) - print() - _print_dict('Variables', get_config_vars()) - - -if __name__ == '__main__': - _main() diff --git a/Lib/sysconfig/__init__.py b/Lib/sysconfig/__init__.py new file mode 100644 index 00000000000000..07ab27c7fb0c35 --- /dev/null +++ b/Lib/sysconfig/__init__.py @@ -0,0 +1,661 @@ +"""Access to Python's configuration information.""" + +import os +import sys +import threading +from os.path import realpath + +__all__ = [ + 'get_config_h_filename', + 'get_config_var', + 'get_config_vars', + 'get_makefile_filename', + 'get_path', + 'get_path_names', + 'get_paths', + 'get_platform', + 'get_python_version', + 'get_scheme_names', + 'parse_config_h', +] + +# Keys for get_config_var() that are never converted to Python integers. +_ALWAYS_STR = { + 'MACOSX_DEPLOYMENT_TARGET', +} + +_INSTALL_SCHEMES = { + 'posix_prefix': { + 'stdlib': '{installed_base}/{platlibdir}/{implementation_lower}{py_version_short}', + 'platstdlib': '{platbase}/{platlibdir}/{implementation_lower}{py_version_short}', + 'purelib': '{base}/lib/{implementation_lower}{py_version_short}/site-packages', + 'platlib': '{platbase}/{platlibdir}/{implementation_lower}{py_version_short}/site-packages', + 'include': + '{installed_base}/include/{implementation_lower}{py_version_short}{abiflags}', + 'platinclude': + '{installed_platbase}/include/{implementation_lower}{py_version_short}{abiflags}', + 'scripts': '{base}/bin', + 'data': '{base}', + }, + 'posix_home': { + 'stdlib': '{installed_base}/lib/{implementation_lower}', + 'platstdlib': '{base}/lib/{implementation_lower}', + 'purelib': '{base}/lib/{implementation_lower}', + 'platlib': '{base}/lib/{implementation_lower}', + 'include': '{installed_base}/include/{implementation_lower}', + 'platinclude': '{installed_base}/include/{implementation_lower}', + 'scripts': '{base}/bin', + 'data': '{base}', + }, + 'nt': { + 'stdlib': '{installed_base}/Lib', + 'platstdlib': '{base}/Lib', + 'purelib': '{base}/Lib/site-packages', + 'platlib': '{base}/Lib/site-packages', + 'include': '{installed_base}/Include', + 'platinclude': '{installed_base}/Include', + 'scripts': '{base}/Scripts', + 'data': '{base}', + }, + # Downstream distributors can overwrite the default install scheme. + # This is done to support downstream modifications where distributors change + # the installation layout (eg. different site-packages directory). + # So, distributors will change the default scheme to one that correctly + # represents their layout. + # This presents an issue for projects/people that need to bootstrap virtual + # environments, like virtualenv. As distributors might now be customizing + # the default install scheme, there is no guarantee that the information + # returned by sysconfig.get_default_scheme/get_paths is correct for + # a virtual environment, the only guarantee we have is that it is correct + # for the *current* environment. When bootstrapping a virtual environment, + # we need to know its layout, so that we can place the files in the + # correct locations. + # The "*_venv" install scheme is a scheme to bootstrap virtual environments, + # essentially identical to the default posix_prefix/nt schemes. + # Downstream distributors who patch posix_prefix/nt scheme are encouraged to + # leave the following schemes unchanged + 'posix_venv': { + 'stdlib': '{installed_base}/{platlibdir}/{implementation_lower}{py_version_short}', + 'platstdlib': '{platbase}/{platlibdir}/{implementation_lower}{py_version_short}', + 'purelib': '{base}/lib/{implementation_lower}{py_version_short}/site-packages', + 'platlib': '{platbase}/{platlibdir}/{implementation_lower}{py_version_short}/site-packages', + 'include': + '{installed_base}/include/{implementation_lower}{py_version_short}{abiflags}', + 'platinclude': + '{installed_platbase}/include/{implementation_lower}{py_version_short}{abiflags}', + 'scripts': '{base}/bin', + 'data': '{base}', + }, + 'nt_venv': { + 'stdlib': '{installed_base}/Lib', + 'platstdlib': '{base}/Lib', + 'purelib': '{base}/Lib/site-packages', + 'platlib': '{base}/Lib/site-packages', + 'include': '{installed_base}/Include', + 'platinclude': '{installed_base}/Include', + 'scripts': '{base}/Scripts', + 'data': '{base}', + }, + } + +# For the OS-native venv scheme, we essentially provide an alias: +if os.name == 'nt': + _INSTALL_SCHEMES['venv'] = _INSTALL_SCHEMES['nt_venv'] +else: + _INSTALL_SCHEMES['venv'] = _INSTALL_SCHEMES['posix_venv'] + +def _get_implementation(): + return 'Python' + +# NOTE: site.py has copy of this function. +# Sync it when modify this function. +def _getuserbase(): + env_base = os.environ.get("PYTHONUSERBASE", None) + if env_base: + return env_base + + # Emscripten, VxWorks, and WASI have no home directories + if sys.platform in {"emscripten", "vxworks", "wasi"}: + return None + + def joinuser(*args): + return os.path.expanduser(os.path.join(*args)) + + if os.name == "nt": + base = os.environ.get("APPDATA") or "~" + return joinuser(base, _get_implementation()) + + if sys.platform == "darwin" and sys._framework: + return joinuser("~", "Library", sys._framework, + f"{sys.version_info[0]}.{sys.version_info[1]}") + + return joinuser("~", ".local") + +_HAS_USER_BASE = (_getuserbase() is not None) + +if _HAS_USER_BASE: + _INSTALL_SCHEMES |= { + # NOTE: When modifying "purelib" scheme, update site._get_path() too. + 'nt_user': { + 'stdlib': '{userbase}/{implementation}{py_version_nodot_plat}', + 'platstdlib': '{userbase}/{implementation}{py_version_nodot_plat}', + 'purelib': '{userbase}/{implementation}{py_version_nodot_plat}/site-packages', + 'platlib': '{userbase}/{implementation}{py_version_nodot_plat}/site-packages', + 'include': '{userbase}/{implementation}{py_version_nodot_plat}/Include', + 'scripts': '{userbase}/{implementation}{py_version_nodot_plat}/Scripts', + 'data': '{userbase}', + }, + 'posix_user': { + 'stdlib': '{userbase}/{platlibdir}/{implementation_lower}{py_version_short}', + 'platstdlib': '{userbase}/{platlibdir}/{implementation_lower}{py_version_short}', + 'purelib': '{userbase}/lib/{implementation_lower}{py_version_short}/site-packages', + 'platlib': '{userbase}/lib/{implementation_lower}{py_version_short}/site-packages', + 'include': '{userbase}/include/{implementation_lower}{py_version_short}', + 'scripts': '{userbase}/bin', + 'data': '{userbase}', + }, + 'osx_framework_user': { + 'stdlib': '{userbase}/lib/{implementation_lower}', + 'platstdlib': '{userbase}/lib/{implementation_lower}', + 'purelib': '{userbase}/lib/{implementation_lower}/site-packages', + 'platlib': '{userbase}/lib/{implementation_lower}/site-packages', + 'include': '{userbase}/include/{implementation_lower}{py_version_short}', + 'scripts': '{userbase}/bin', + 'data': '{userbase}', + }, + } + +_SCHEME_KEYS = ('stdlib', 'platstdlib', 'purelib', 'platlib', 'include', + 'scripts', 'data') + +_PY_VERSION = sys.version.split()[0] +_PY_VERSION_SHORT = f'{sys.version_info[0]}.{sys.version_info[1]}' +_PY_VERSION_SHORT_NO_DOT = f'{sys.version_info[0]}{sys.version_info[1]}' +_PREFIX = os.path.normpath(sys.prefix) +_BASE_PREFIX = os.path.normpath(sys.base_prefix) +_EXEC_PREFIX = os.path.normpath(sys.exec_prefix) +_BASE_EXEC_PREFIX = os.path.normpath(sys.base_exec_prefix) +# Mutex guarding initialization of _CONFIG_VARS. +_CONFIG_VARS_LOCK = threading.RLock() +_CONFIG_VARS = None +# True iff _CONFIG_VARS has been fully initialized. +_CONFIG_VARS_INITIALIZED = False +_USER_BASE = None + + +def _safe_realpath(path): + try: + return realpath(path) + except OSError: + return path + +if sys.executable: + _PROJECT_BASE = os.path.dirname(_safe_realpath(sys.executable)) +else: + # sys.executable can be empty if argv[0] has been changed and Python is + # unable to retrieve the real program name + _PROJECT_BASE = _safe_realpath(os.getcwd()) + +# In a virtual environment, `sys._home` gives us the target directory +# `_PROJECT_BASE` for the executable that created it when the virtual +# python is an actual executable ('venv --copies' or Windows). +_sys_home = getattr(sys, '_home', None) +if _sys_home: + _PROJECT_BASE = _sys_home + +if os.name == 'nt': + # In a source build, the executable is in a subdirectory of the root + # that we want (\PCbuild\). + # `_BASE_PREFIX` is used as the base installation is where the source + # will be. The realpath is needed to prevent mount point confusion + # that can occur with just string comparisons. + if _safe_realpath(_PROJECT_BASE).startswith( + _safe_realpath(f'{_BASE_PREFIX}\\PCbuild')): + _PROJECT_BASE = _BASE_PREFIX + +# set for cross builds +if "_PYTHON_PROJECT_BASE" in os.environ: + _PROJECT_BASE = _safe_realpath(os.environ["_PYTHON_PROJECT_BASE"]) + +def is_python_build(check_home=None): + if check_home is not None: + import warnings + warnings.warn("check_home argument is deprecated and ignored.", + DeprecationWarning, stacklevel=2) + for fn in ("Setup", "Setup.local"): + if os.path.isfile(os.path.join(_PROJECT_BASE, "Modules", fn)): + return True + return False + +_PYTHON_BUILD = is_python_build() + +if _PYTHON_BUILD: + for scheme in ('posix_prefix', 'posix_home'): + # On POSIX-y platforms, Python will: + # - Build from .h files in 'headers' (which is only added to the + # scheme when building CPython) + # - Install .h files to 'include' + scheme = _INSTALL_SCHEMES[scheme] + scheme['headers'] = scheme['include'] + scheme['include'] = '{srcdir}/Include' + scheme['platinclude'] = '{projectbase}/.' + del scheme + + +def _subst_vars(s, local_vars): + try: + return s.format(**local_vars) + except KeyError as var: + try: + return s.format(**os.environ) + except KeyError: + raise AttributeError(f'{var}') from None + +def _extend_dict(target_dict, other_dict): + target_keys = target_dict.keys() + for key, value in other_dict.items(): + if key in target_keys: + continue + target_dict[key] = value + + +def _expand_vars(scheme, vars): + res = {} + if vars is None: + vars = {} + _extend_dict(vars, get_config_vars()) + if os.name == 'nt': + # On Windows we want to substitute 'lib' for schemes rather + # than the native value (without modifying vars, in case it + # was passed in) + vars = vars | {'platlibdir': 'lib'} + + for key, value in _INSTALL_SCHEMES[scheme].items(): + if os.name in ('posix', 'nt'): + value = os.path.expanduser(value) + res[key] = os.path.normpath(_subst_vars(value, vars)) + return res + + +def _get_preferred_schemes(): + if os.name == 'nt': + return { + 'prefix': 'nt', + 'home': 'posix_home', + 'user': 'nt_user', + } + if sys.platform == 'darwin' and sys._framework: + return { + 'prefix': 'posix_prefix', + 'home': 'posix_home', + 'user': 'osx_framework_user', + } + return { + 'prefix': 'posix_prefix', + 'home': 'posix_home', + 'user': 'posix_user', + } + + +def get_preferred_scheme(key): + if key == 'prefix' and sys.prefix != sys.base_prefix: + return 'venv' + scheme = _get_preferred_schemes()[key] + if scheme not in _INSTALL_SCHEMES: + raise ValueError( + f"{key!r} returned {scheme!r}, which is not a valid scheme " + f"on this platform" + ) + return scheme + + +def get_default_scheme(): + return get_preferred_scheme('prefix') + + +def get_makefile_filename(): + """Return the path of the Makefile.""" + if _PYTHON_BUILD: + return os.path.join(_PROJECT_BASE, "Makefile") + if hasattr(sys, 'abiflags'): + config_dir_name = f'config-{_PY_VERSION_SHORT}{sys.abiflags}' + else: + config_dir_name = 'config' + if hasattr(sys.implementation, '_multiarch'): + config_dir_name += f'-{sys.implementation._multiarch}' + return os.path.join(get_path('stdlib'), config_dir_name, 'Makefile') + + +def _get_sysconfigdata_name(): + multiarch = getattr(sys.implementation, '_multiarch', '') + return os.environ.get( + '_PYTHON_SYSCONFIGDATA_NAME', + f'_sysconfigdata_{sys.abiflags}_{sys.platform}_{multiarch}', + ) + +def _init_posix(vars): + """Initialize the module as appropriate for POSIX systems.""" + # _sysconfigdata is generated at build time, see _generate_posix_vars() + name = _get_sysconfigdata_name() + _temp = __import__(name, globals(), locals(), ['build_time_vars'], 0) + build_time_vars = _temp.build_time_vars + vars.update(build_time_vars) + +def _init_non_posix(vars): + """Initialize the module as appropriate for NT""" + # set basic install directories + import _winapi + import _sysconfig + vars['LIBDEST'] = get_path('stdlib') + vars['BINLIBDEST'] = get_path('platstdlib') + vars['INCLUDEPY'] = get_path('include') + + # Add EXT_SUFFIX, SOABI, and Py_GIL_DISABLED + vars.update(_sysconfig.config_vars()) + + vars['LIBDIR'] = _safe_realpath(os.path.join(get_config_var('installed_base'), 'libs')) + if hasattr(sys, 'dllhandle'): + dllhandle = _winapi.GetModuleFileName(sys.dllhandle) + vars['LIBRARY'] = os.path.basename(_safe_realpath(dllhandle)) + vars['LDLIBRARY'] = vars['LIBRARY'] + vars['EXE'] = '.exe' + vars['VERSION'] = _PY_VERSION_SHORT_NO_DOT + vars['BINDIR'] = os.path.dirname(_safe_realpath(sys.executable)) + vars['TZPATH'] = '' + +# +# public APIs +# + + +def parse_config_h(fp, vars=None): + """Parse a config.h-style file. + + A dictionary containing name/value pairs is returned. If an + optional dictionary is passed in as the second argument, it is + used instead of a new dictionary. + """ + if vars is None: + vars = {} + import re + define_rx = re.compile("#define ([A-Z][A-Za-z0-9_]+) (.*)\n") + undef_rx = re.compile("/[*] #undef ([A-Z][A-Za-z0-9_]+) [*]/\n") + + while True: + line = fp.readline() + if not line: + break + m = define_rx.match(line) + if m: + n, v = m.group(1, 2) + try: + if n in _ALWAYS_STR: + raise ValueError + v = int(v) + except ValueError: + pass + vars[n] = v + else: + m = undef_rx.match(line) + if m: + vars[m.group(1)] = 0 + return vars + + +def get_config_h_filename(): + """Return the path of pyconfig.h.""" + if _PYTHON_BUILD: + if os.name == "nt": + inc_dir = os.path.dirname(sys._base_executable) + else: + inc_dir = _PROJECT_BASE + else: + inc_dir = get_path('platinclude') + return os.path.join(inc_dir, 'pyconfig.h') + + +def get_scheme_names(): + """Return a tuple containing the schemes names.""" + return tuple(sorted(_INSTALL_SCHEMES)) + + +def get_path_names(): + """Return a tuple containing the paths names.""" + return _SCHEME_KEYS + + +def get_paths(scheme=get_default_scheme(), vars=None, expand=True): + """Return a mapping containing an install scheme. + + ``scheme`` is the install scheme name. If not provided, it will + return the default scheme for the current platform. + """ + if expand: + return _expand_vars(scheme, vars) + else: + return _INSTALL_SCHEMES[scheme] + + +def get_path(name, scheme=get_default_scheme(), vars=None, expand=True): + """Return a path corresponding to the scheme. + + ``scheme`` is the install scheme name. + """ + return get_paths(scheme, vars, expand)[name] + + +def _init_config_vars(): + global _CONFIG_VARS + _CONFIG_VARS = {} + # Normalized versions of prefix and exec_prefix are handy to have; + # in fact, these are the standard versions used most places in the + # Distutils. + _CONFIG_VARS['prefix'] = _PREFIX + _CONFIG_VARS['exec_prefix'] = _EXEC_PREFIX + _CONFIG_VARS['py_version'] = _PY_VERSION + _CONFIG_VARS['py_version_short'] = _PY_VERSION_SHORT + _CONFIG_VARS['py_version_nodot'] = _PY_VERSION_SHORT_NO_DOT + _CONFIG_VARS['installed_base'] = _BASE_PREFIX + _CONFIG_VARS['base'] = _PREFIX + _CONFIG_VARS['installed_platbase'] = _BASE_EXEC_PREFIX + _CONFIG_VARS['platbase'] = _EXEC_PREFIX + _CONFIG_VARS['projectbase'] = _PROJECT_BASE + _CONFIG_VARS['platlibdir'] = sys.platlibdir + _CONFIG_VARS['implementation'] = _get_implementation() + _CONFIG_VARS['implementation_lower'] = _get_implementation().lower() + try: + _CONFIG_VARS['abiflags'] = sys.abiflags + except AttributeError: + # sys.abiflags may not be defined on all platforms. + _CONFIG_VARS['abiflags'] = '' + try: + _CONFIG_VARS['py_version_nodot_plat'] = sys.winver.replace('.', '') + except AttributeError: + _CONFIG_VARS['py_version_nodot_plat'] = '' + + if os.name == 'nt': + _init_non_posix(_CONFIG_VARS) + _CONFIG_VARS['VPATH'] = sys._vpath + if os.name == 'posix': + _init_posix(_CONFIG_VARS) + if _HAS_USER_BASE: + # Setting 'userbase' is done below the call to the + # init function to enable using 'get_config_var' in + # the init-function. + _CONFIG_VARS['userbase'] = _getuserbase() + + # Always convert srcdir to an absolute path + srcdir = _CONFIG_VARS.get('srcdir', _PROJECT_BASE) + if os.name == 'posix': + if _PYTHON_BUILD: + # If srcdir is a relative path (typically '.' or '..') + # then it should be interpreted relative to the directory + # containing Makefile. + base = os.path.dirname(get_makefile_filename()) + srcdir = os.path.join(base, srcdir) + else: + # srcdir is not meaningful since the installation is + # spread about the filesystem. We choose the + # directory containing the Makefile since we know it + # exists. + srcdir = os.path.dirname(get_makefile_filename()) + _CONFIG_VARS['srcdir'] = _safe_realpath(srcdir) + + # OS X platforms require special customization to handle + # multi-architecture, multi-os-version installers + if sys.platform == 'darwin': + import _osx_support + _osx_support.customize_config_vars(_CONFIG_VARS) + + global _CONFIG_VARS_INITIALIZED + _CONFIG_VARS_INITIALIZED = True + + +def get_config_vars(*args): + """With no arguments, return a dictionary of all configuration + variables relevant for the current platform. + + On Unix, this means every variable defined in Python's installed Makefile; + On Windows it's a much smaller set. + + With arguments, return a list of values that result from looking up + each argument in the configuration variable dictionary. + """ + + # Avoid claiming the lock once initialization is complete. + if not _CONFIG_VARS_INITIALIZED: + with _CONFIG_VARS_LOCK: + # Test again with the lock held to avoid races. Note that + # we test _CONFIG_VARS here, not _CONFIG_VARS_INITIALIZED, + # to ensure that recursive calls to get_config_vars() + # don't re-enter init_config_vars(). + if _CONFIG_VARS is None: + _init_config_vars() + + if args: + vals = [] + for name in args: + vals.append(_CONFIG_VARS.get(name)) + return vals + else: + return _CONFIG_VARS + + +def get_config_var(name): + """Return the value of a single variable using the dictionary returned by + 'get_config_vars()'. + + Equivalent to get_config_vars().get(name) + """ + return get_config_vars().get(name) + + +def get_platform(): + """Return a string that identifies the current platform. + + This is used mainly to distinguish platform-specific build directories and + platform-specific built distributions. Typically includes the OS name and + version and the architecture (as supplied by 'os.uname()'), although the + exact information included depends on the OS; on Linux, the kernel version + isn't particularly important. + + Examples of returned values: + linux-i586 + linux-alpha (?) + solaris-2.6-sun4u + + Windows will return one of: + win-amd64 (64bit Windows on AMD64 (aka x86_64, Intel64, EM64T, etc) + win32 (all others - specifically, sys.platform is returned) + + For other non-POSIX platforms, currently just returns 'sys.platform'. + + """ + if os.name == 'nt': + if 'amd64' in sys.version.lower(): + return 'win-amd64' + if '(arm)' in sys.version.lower(): + return 'win-arm32' + if '(arm64)' in sys.version.lower(): + return 'win-arm64' + return sys.platform + + if os.name != "posix" or not hasattr(os, 'uname'): + # XXX what about the architecture? NT is Intel or Alpha + return sys.platform + + # Set for cross builds explicitly + if "_PYTHON_HOST_PLATFORM" in os.environ: + return os.environ["_PYTHON_HOST_PLATFORM"] + + # Try to distinguish various flavours of Unix + osname, host, release, version, machine = os.uname() + + # Convert the OS name to lowercase, remove '/' characters, and translate + # spaces (for "Power Macintosh") + osname = osname.lower().replace('/', '') + machine = machine.replace(' ', '_') + machine = machine.replace('/', '-') + + if osname[:5] == "linux": + # At least on Linux/Intel, 'machine' is the processor -- + # i386, etc. + # XXX what about Alpha, SPARC, etc? + return f"{osname}-{machine}" + elif osname[:5] == "sunos": + if release[0] >= "5": # SunOS 5 == Solaris 2 + osname = "solaris" + release = f"{int(release[0]) - 3}.{release[2:]}" + # We can't use "platform.architecture()[0]" because a + # bootstrap problem. We use a dict to get an error + # if some suspicious happens. + bitness = {2147483647:"32bit", 9223372036854775807:"64bit"} + machine += f".{bitness[sys.maxsize]}" + # fall through to standard osname-release-machine representation + elif osname[:3] == "aix": + from _aix_support import aix_platform + return aix_platform() + elif osname[:6] == "cygwin": + osname = "cygwin" + import re + rel_re = re.compile(r'[\d.]+') + m = rel_re.match(release) + if m: + release = m.group() + elif osname[:6] == "darwin": + import _osx_support + osname, release, machine = _osx_support.get_platform_osx( + get_config_vars(), + osname, release, machine) + + return f"{osname}-{release}-{machine}" + + +def get_python_version(): + return _PY_VERSION_SHORT + + +def expand_makefile_vars(s, vars): + """Expand Makefile-style variables -- "${foo}" or "$(foo)" -- in + 'string' according to 'vars' (a dictionary mapping variable names to + values). Variables not present in 'vars' are silently expanded to the + empty string. The variable values in 'vars' should not contain further + variable expansions; if 'vars' is the output of 'parse_makefile()', + you're fine. Returns a variable-expanded version of 's'. + """ + import re + + # This algorithm does multiple expansion, so if vars['foo'] contains + # "${bar}", it will expand ${foo} to ${bar}, and then expand + # ${bar}... and so forth. This is fine as long as 'vars' comes from + # 'parse_makefile()', which takes care of such expansions eagerly, + # according to make's variable expansion semantics. + + while True: + m = re.search(_findvar1_rx, s) or re.search(_findvar2_rx, s) + if m: + (beg, end) = m.span() + s = s[0:beg] + vars.get(m.group(1)) + s[end:] + else: + break + return s diff --git a/Lib/sysconfig/__main__.py b/Lib/sysconfig/__main__.py new file mode 100644 index 00000000000000..d7257b9d2d00db --- /dev/null +++ b/Lib/sysconfig/__main__.py @@ -0,0 +1,248 @@ +import os +import sys +from sysconfig import ( + _ALWAYS_STR, + _PYTHON_BUILD, + _get_sysconfigdata_name, + get_config_h_filename, + get_config_vars, + get_default_scheme, + get_makefile_filename, + get_paths, + get_platform, + get_python_version, + parse_config_h, +) + + +# Regexes needed for parsing Makefile (and similar syntaxes, +# like old-style Setup files). +_variable_rx = r"([a-zA-Z][a-zA-Z0-9_]+)\s*=\s*(.*)" +_findvar1_rx = r"\$\(([A-Za-z][A-Za-z0-9_]*)\)" +_findvar2_rx = r"\${([A-Za-z][A-Za-z0-9_]*)}" + + +def _parse_makefile(filename, vars=None, keep_unresolved=True): + """Parse a Makefile-style file. + + A dictionary containing name/value pairs is returned. If an + optional dictionary is passed in as the second argument, it is + used instead of a new dictionary. + """ + import re + + if vars is None: + vars = {} + done = {} + notdone = {} + + with open(filename, encoding=sys.getfilesystemencoding(), + errors="surrogateescape") as f: + lines = f.readlines() + + for line in lines: + if line.startswith('#') or line.strip() == '': + continue + m = re.match(_variable_rx, line) + if m: + n, v = m.group(1, 2) + v = v.strip() + # `$$' is a literal `$' in make + tmpv = v.replace('$$', '') + + if "$" in tmpv: + notdone[n] = v + else: + try: + if n in _ALWAYS_STR: + raise ValueError + + v = int(v) + except ValueError: + # insert literal `$' + done[n] = v.replace('$$', '$') + else: + done[n] = v + + # do variable interpolation here + variables = list(notdone.keys()) + + # Variables with a 'PY_' prefix in the makefile. These need to + # be made available without that prefix through sysconfig. + # Special care is needed to ensure that variable expansion works, even + # if the expansion uses the name without a prefix. + renamed_variables = ('CFLAGS', 'LDFLAGS', 'CPPFLAGS') + + while len(variables) > 0: + for name in tuple(variables): + value = notdone[name] + m1 = re.search(_findvar1_rx, value) + m2 = re.search(_findvar2_rx, value) + if m1 and m2: + m = m1 if m1.start() < m2.start() else m2 + else: + m = m1 if m1 else m2 + if m is not None: + n = m.group(1) + found = True + if n in done: + item = str(done[n]) + elif n in notdone: + # get it on a subsequent round + found = False + elif n in os.environ: + # do it like make: fall back to environment + item = os.environ[n] + + elif n in renamed_variables: + if (name.startswith('PY_') and + name[3:] in renamed_variables): + item = "" + + elif 'PY_' + n in notdone: + found = False + + else: + item = str(done['PY_' + n]) + + else: + done[n] = item = "" + + if found: + after = value[m.end():] + value = value[:m.start()] + item + after + if "$" in after: + notdone[name] = value + else: + try: + if name in _ALWAYS_STR: + raise ValueError + value = int(value) + except ValueError: + done[name] = value.strip() + else: + done[name] = value + variables.remove(name) + + if name.startswith('PY_') \ + and name[3:] in renamed_variables: + + name = name[3:] + if name not in done: + done[name] = value + + else: + # Adds unresolved variables to the done dict. + # This is disabled when called from distutils.sysconfig + if keep_unresolved: + done[name] = value + # bogus variable reference (e.g. "prefix=$/opt/python"); + # just drop it since we can't deal + variables.remove(name) + + # strip spurious spaces + for k, v in done.items(): + if isinstance(v, str): + done[k] = v.strip() + + # save the results in the global dictionary + vars.update(done) + return vars + + +def _print_config_dict(d, stream): + print ("{", file=stream) + for k, v in sorted(d.items()): + print(f" {k!r}: {v!r},", file=stream) + print ("}", file=stream) + + +def _generate_posix_vars(): + """Generate the Python module containing build-time variables.""" + vars = {} + # load the installed Makefile: + makefile = get_makefile_filename() + try: + _parse_makefile(makefile, vars) + except OSError as e: + msg = f"invalid Python installation: unable to open {makefile}" + if hasattr(e, "strerror"): + msg = f"{msg} ({e.strerror})" + raise OSError(msg) + # load the installed pyconfig.h: + config_h = get_config_h_filename() + try: + with open(config_h, encoding="utf-8") as f: + parse_config_h(f, vars) + except OSError as e: + msg = f"invalid Python installation: unable to open {config_h}" + if hasattr(e, "strerror"): + msg = f"{msg} ({e.strerror})" + raise OSError(msg) + # On AIX, there are wrong paths to the linker scripts in the Makefile + # -- these paths are relative to the Python source, but when installed + # the scripts are in another directory. + if _PYTHON_BUILD: + vars['BLDSHARED'] = vars['LDSHARED'] + + # There's a chicken-and-egg situation on OS X with regards to the + # _sysconfigdata module after the changes introduced by #15298: + # get_config_vars() is called by get_platform() as part of the + # `make pybuilddir.txt` target -- which is a precursor to the + # _sysconfigdata.py module being constructed. Unfortunately, + # get_config_vars() eventually calls _init_posix(), which attempts + # to import _sysconfigdata, which we won't have built yet. In order + # for _init_posix() to work, if we're on Darwin, just mock up the + # _sysconfigdata module manually and populate it with the build vars. + # This is more than sufficient for ensuring the subsequent call to + # get_platform() succeeds. + name = _get_sysconfigdata_name() + if 'darwin' in sys.platform: + import types + module = types.ModuleType(name) + module.build_time_vars = vars + sys.modules[name] = module + + pybuilddir = f'build/lib.{get_platform()}-{get_python_version()}' + if hasattr(sys, "gettotalrefcount"): + pybuilddir += '-pydebug' + os.makedirs(pybuilddir, exist_ok=True) + destfile = os.path.join(pybuilddir, name + '.py') + + with open(destfile, 'w', encoding='utf8') as f: + f.write('# system configuration generated and used by' + ' the sysconfig module\n') + f.write('build_time_vars = ') + _print_config_dict(vars, stream=f) + + # Create file used for sys.path fixup -- see Modules/getpath.c + with open('pybuilddir.txt', 'w', encoding='utf8') as f: + f.write(pybuilddir) + + +def _print_dict(title, data): + for index, (key, value) in enumerate(sorted(data.items())): + if index == 0: + print(f'{title}: ') + print(f'\t{key} = "{value}"') + + +def _main(): + """Display all information sysconfig detains.""" + if '--generate-posix-vars' in sys.argv: + _generate_posix_vars() + return + print(f'Platform: "{get_platform()}"') + print(f'Python version: "{get_python_version()}"') + print(f'Current installation scheme: "{get_default_scheme()}"') + print() + _print_dict('Paths', get_paths()) + print() + _print_dict('Variables', get_config_vars()) + + +if __name__ == '__main__': + try: + _main() + except BrokenPipeError: + pass diff --git a/Lib/tarfile.py b/Lib/tarfile.py index df4e41f7a0d23a..20e0394507f5db 100755 --- a/Lib/tarfile.py +++ b/Lib/tarfile.py @@ -46,7 +46,6 @@ import struct import copy import re -import warnings try: import pwd @@ -331,10 +330,11 @@ def write(self, s): class _Stream: """Class that serves as an adapter between TarFile and a stream-like object. The stream-like object only - needs to have a read() or write() method and is accessed - blockwise. Use of gzip or bzip2 compression is possible. - A stream-like object could be for example: sys.stdin, - sys.stdout, a socket, a tape device etc. + needs to have a read() or write() method that works with bytes, + and the method is accessed blockwise. + Use of gzip or bzip2 compression is possible. + A stream-like object could be for example: sys.stdin.buffer, + sys.stdout.buffer, a socket, a tape device etc. _Stream is intended to be used only internally. """ @@ -372,8 +372,8 @@ def __init__(self, name, mode, comptype, fileobj, bufsize, self.zlib = zlib self.crc = zlib.crc32(b"") if mode == "r": - self._init_read_gz() self.exception = zlib.error + self._init_read_gz() else: self._init_write_gz(compresslevel) @@ -742,7 +742,7 @@ def __init__(self, tarinfo): class AbsoluteLinkError(FilterError): def __init__(self, tarinfo): self.tarinfo = tarinfo - super().__init__(f'{tarinfo.name!r} is a symlink to an absolute path') + super().__init__(f'{tarinfo.name!r} is a link to an absolute path') class LinkOutsideDestinationError(FilterError): def __init__(self, tarinfo, path): @@ -802,7 +802,14 @@ def _get_filtered_attrs(member, dest_path, for_data=True): if member.islnk() or member.issym(): if os.path.isabs(member.linkname): raise AbsoluteLinkError(member) - target_path = os.path.realpath(os.path.join(dest_path, member.linkname)) + if member.issym(): + target_path = os.path.join(dest_path, + os.path.dirname(name), + member.linkname) + else: + target_path = os.path.join(dest_path, + member.linkname) + target_path = os.path.realpath(target_path) if os.path.commonpath([target_path, dest_path]) != dest_path: raise LinkOutsideDestinationError(member, target_path) return new_attrs @@ -2100,6 +2107,10 @@ def list(self, verbose=True, *, members=None): output is produced. `members' is optional and must be a subset of the list returned by getmembers(). """ + # Convert tarinfo type to stat type. + type2mode = {REGTYPE: stat.S_IFREG, SYMTYPE: stat.S_IFLNK, + FIFOTYPE: stat.S_IFIFO, CHRTYPE: stat.S_IFCHR, + DIRTYPE: stat.S_IFDIR, BLKTYPE: stat.S_IFBLK} self._check() if members is None: @@ -2109,7 +2120,8 @@ def list(self, verbose=True, *, members=None): if tarinfo.mode is None: _safe_print("??????????") else: - _safe_print(stat.filemode(tarinfo.mode)) + modetype = type2mode.get(tarinfo.type, 0) + _safe_print(stat.filemode(modetype | tarinfo.mode)) _safe_print("%s/%s" % (tarinfo.uname or tarinfo.uid, tarinfo.gname or tarinfo.gid)) if tarinfo.ischr() or tarinfo.isblk(): @@ -2212,6 +2224,7 @@ def _get_filter_function(self, filter): if filter is None: filter = self.extraction_filter if filter is None: + import warnings warnings.warn( 'Python 3.14 will, by default, filter extracted tar ' + 'archives and reject files or modify their metadata. ' @@ -2550,7 +2563,8 @@ def chown(self, tarinfo, targetpath, numeric_owner): os.lchown(targetpath, u, g) else: os.chown(targetpath, u, g) - except OSError as e: + except (OSError, OverflowError) as e: + # OverflowError can be raised if an ID doesn't fit in `id_t` raise ExtractError("could not change owner") from e def chmod(self, tarinfo, targetpath): diff --git a/Lib/tempfile.py b/Lib/tempfile.py index 2b4f4313247128..b5a15f7b72c872 100644 --- a/Lib/tempfile.py +++ b/Lib/tempfile.py @@ -269,6 +269,22 @@ def _mkstemp_inner(dir, pre, suf, flags, output_type): raise FileExistsError(_errno.EEXIST, "No usable temporary file name found") +def _dont_follow_symlinks(func, path, *args): + # Pass follow_symlinks=False, unless not supported on this platform. + if func in _os.supports_follow_symlinks: + func(path, *args, follow_symlinks=False) + elif not _os.path.islink(path): + func(path, *args) + +def _resetperms(path): + try: + chflags = _os.chflags + except AttributeError: + pass + else: + _dont_follow_symlinks(chflags, path, 0) + _dont_follow_symlinks(_os.chmod, path, 0o700) + # User visible interfaces. @@ -872,26 +888,37 @@ def __init__(self, suffix=None, prefix=None, dir=None, ignore_errors=self._ignore_cleanup_errors, delete=self._delete) @classmethod - def _rmtree(cls, name, ignore_errors=False): + def _rmtree(cls, name, ignore_errors=False, repeated=False): def onexc(func, path, exc): if isinstance(exc, PermissionError): - def resetperms(path): - try: - _os.chflags(path, 0) - except AttributeError: - pass - _os.chmod(path, 0o700) + if repeated and path == name: + if ignore_errors: + return + raise try: if path != name: - resetperms(_os.path.dirname(path)) - resetperms(path) + _resetperms(_os.path.dirname(path)) + _resetperms(path) try: _os.unlink(path) - # PermissionError is raised on FreeBSD for directories - except (IsADirectoryError, PermissionError): + except IsADirectoryError: cls._rmtree(path, ignore_errors=ignore_errors) + except PermissionError: + # The PermissionError handler was originally added for + # FreeBSD in directories, but it seems that it is raised + # on Windows too. + # bpo-43153: Calling _rmtree again may + # raise NotADirectoryError and mask the PermissionError. + # So we must re-raise the current PermissionError if + # path is not a directory. + if not _os.path.isdir(path) or _os.path.isjunction(path): + if ignore_errors: + return + raise + cls._rmtree(path, ignore_errors=ignore_errors, + repeated=(path == name)) except FileNotFoundError: pass elif isinstance(exc, FileNotFoundError): diff --git a/Lib/test/.ruff.toml b/Lib/test/.ruff.toml new file mode 100644 index 00000000000000..74ab215ee8ee28 --- /dev/null +++ b/Lib/test/.ruff.toml @@ -0,0 +1,24 @@ +fix = true +select = [ + "F811", # Redefinition of unused variable (useful for finding test methods with the same name) +] +extend-exclude = [ + # Excluded (run with the other AC files in its own separate ruff job in pre-commit) + "test_clinic.py", + # Excluded (these aren't actually executed, they're just "data files") + "tokenizedata/*.py", + # Failed to lint + "encoded_modules/module_iso_8859_1.py", + "encoded_modules/module_koi8_r.py", + # TODO Fix: F811 Redefinition of unused name + "test_buffer.py", + "test_dataclasses/__init__.py", + "test_descr.py", + "test_enum.py", + "test_functools.py", + "test_grammar.py", + "test_import/__init__.py", + "test_pkg.py", + "test_yield_from.py", + "time_hashlib.py", +] diff --git a/Lib/test/__main__.py b/Lib/test/__main__.py index 19a6b2b8904526..82b50ad2c6e777 100644 --- a/Lib/test/__main__.py +++ b/Lib/test/__main__.py @@ -1,2 +1,2 @@ -from test.libregrtest import main -main() +from test.libregrtest.main import main +main(_add_python_opts=True) diff --git a/Lib/test/_test_atexit.py b/Lib/test/_test_atexit.py index 55d28083349175..f618c1fcbca52b 100644 --- a/Lib/test/_test_atexit.py +++ b/Lib/test/_test_atexit.py @@ -19,7 +19,9 @@ def assert_raises_unraisable(self, exc_type, func, *args): atexit.register(func, *args) atexit._run_exitfuncs() - self.assertEqual(cm.unraisable.object, func) + self.assertIsNone(cm.unraisable.object) + self.assertEqual(cm.unraisable.err_msg, + f'Exception ignored in atexit callback {func!r}') self.assertEqual(cm.unraisable.exc_type, exc_type) self.assertEqual(type(cm.unraisable.exc_value), exc_type) @@ -125,7 +127,9 @@ def func(): try: with support.catch_unraisable_exception() as cm: atexit._run_exitfuncs() - self.assertEqual(cm.unraisable.object, func) + self.assertIsNone(cm.unraisable.object) + self.assertEqual(cm.unraisable.err_msg, + f'Exception ignored in atexit callback {func!r}') self.assertEqual(cm.unraisable.exc_type, ZeroDivisionError) self.assertEqual(type(cm.unraisable.exc_value), ZeroDivisionError) finally: diff --git a/Lib/test/_test_eintr.py b/Lib/test/_test_eintr.py index 006581f7cc6a9a..15586f15dfab30 100644 --- a/Lib/test/_test_eintr.py +++ b/Lib/test/_test_eintr.py @@ -25,6 +25,12 @@ from test.support import os_helper from test.support import socket_helper + +# gh-109592: Tolerate a difference of 20 ms when comparing timings +# (clock resolution) +CLOCK_RES = 0.020 + + @contextlib.contextmanager def kill_on_error(proc): """Context manager killing the subprocess if a Python exception is raised.""" @@ -75,6 +81,9 @@ def subprocess(self, *args, **kw): cmd_args = (sys.executable, '-c') + args return subprocess.Popen(cmd_args, **kw) + def check_elapsed_time(self, elapsed): + self.assertGreaterEqual(elapsed, self.sleep_time - CLOCK_RES) + @unittest.skipUnless(hasattr(signal, "setitimer"), "requires setitimer()") class OSEINTRTest(EINTRBaseTest): @@ -373,7 +382,7 @@ def test_sleep(self): time.sleep(self.sleep_time) self.stop_alarm() dt = time.monotonic() - t0 - self.assertGreaterEqual(dt, self.sleep_time) + self.check_elapsed_time(dt) @unittest.skipUnless(hasattr(signal, "setitimer"), "requires setitimer()") @@ -435,7 +444,7 @@ def test_select(self): select.select([], [], [], self.sleep_time) dt = time.monotonic() - t0 self.stop_alarm() - self.assertGreaterEqual(dt, self.sleep_time) + self.check_elapsed_time(dt) @unittest.skipIf(sys.platform == "darwin", "poll may fail on macOS; see issue #28087") @@ -447,7 +456,7 @@ def test_poll(self): poller.poll(self.sleep_time * 1e3) dt = time.monotonic() - t0 self.stop_alarm() - self.assertGreaterEqual(dt, self.sleep_time) + self.check_elapsed_time(dt) @unittest.skipUnless(hasattr(select, 'epoll'), 'need select.epoll') def test_epoll(self): @@ -458,7 +467,7 @@ def test_epoll(self): poller.poll(self.sleep_time) dt = time.monotonic() - t0 self.stop_alarm() - self.assertGreaterEqual(dt, self.sleep_time) + self.check_elapsed_time(dt) @unittest.skipUnless(hasattr(select, 'kqueue'), 'need select.kqueue') def test_kqueue(self): @@ -469,7 +478,7 @@ def test_kqueue(self): kqueue.control(None, 1, self.sleep_time) dt = time.monotonic() - t0 self.stop_alarm() - self.assertGreaterEqual(dt, self.sleep_time) + self.check_elapsed_time(dt) @unittest.skipUnless(hasattr(select, 'devpoll'), 'need select.devpoll') def test_devpoll(self): @@ -480,7 +489,7 @@ def test_devpoll(self): poller.poll(self.sleep_time * 1e3) dt = time.monotonic() - t0 self.stop_alarm() - self.assertGreaterEqual(dt, self.sleep_time) + self.check_elapsed_time(dt) class FNTLEINTRTest(EINTRBaseTest): @@ -512,8 +521,8 @@ def _lock(self, lock_func, lock_name): # potential context switch delay lock_func(f, fcntl.LOCK_EX) dt = time.monotonic() - start_time - self.assertGreaterEqual(dt, self.sleep_time) self.stop_alarm() + self.check_elapsed_time(dt) proc.wait() # Issue 35633: See https://bugs.python.org/issue35633#msg333662 diff --git a/Lib/test/_test_embed_set_config.py b/Lib/test/_test_embed_set_config.py index 0c016b5d75d734..a2ddd133cf47c8 100644 --- a/Lib/test/_test_embed_set_config.py +++ b/Lib/test/_test_embed_set_config.py @@ -9,9 +9,9 @@ import os import sys import unittest +from test.support import MS_WINDOWS -MS_WINDOWS = (os.name == 'nt') MAX_HASH_SEED = 4294967295 class SetConfigTests(unittest.TestCase): diff --git a/Lib/test/_test_multiprocessing.py b/Lib/test/_test_multiprocessing.py index c1f9487ae80511..8e4e0765d46809 100644 --- a/Lib/test/_test_multiprocessing.py +++ b/Lib/test/_test_multiprocessing.py @@ -78,10 +78,15 @@ msvcrt = None -if support.check_sanitizer(address=True): - # bpo-45200: Skip multiprocessing tests if Python is built with ASAN to +if support.HAVE_ASAN_FORK_BUG: + # gh-89363: Skip multiprocessing tests if Python is built with ASAN to # work around a libasan race condition: dead lock in pthread_create(). - raise unittest.SkipTest("libasan has a pthread_create() dead lock") + raise unittest.SkipTest("libasan has a pthread_create() dead lock related to thread+fork") + + +# gh-110666: Tolerate a difference of 100 ms when comparing timings +# (clock resolution) +CLOCK_RES = 0.100 def latin(s): @@ -329,6 +334,7 @@ def test_set_executable(self): p.join() self.assertEqual(p.exitcode, 0) + @support.requires_resource('cpu') def test_args_argument(self): # bpo-45735: Using list or tuple as *args* in constructor could # achieve the same effect. @@ -556,13 +562,14 @@ def handler(*args): def test_terminate(self): exitcode = self._kill_process(multiprocessing.Process.terminate) - if os.name != 'nt': - self.assertEqual(exitcode, -signal.SIGTERM) + self.assertEqual(exitcode, -signal.SIGTERM) def test_kill(self): exitcode = self._kill_process(multiprocessing.Process.kill) if os.name != 'nt': self.assertEqual(exitcode, -signal.SIGKILL) + else: + self.assertEqual(exitcode, -signal.SIGTERM) def test_cpu_count(self): try: @@ -674,6 +681,7 @@ def test_close(self): close_queue(q) + @support.requires_resource('walltime') def test_many_processes(self): if self.TYPE == 'threads': self.skipTest('test not appropriate for {}'.format(self.TYPE)) @@ -1648,12 +1656,11 @@ def test_waitfor(self): def _test_waitfor_timeout_f(cls, cond, state, success, sem): sem.release() with cond: - expected = 0.1 + expected = 0.100 dt = time.monotonic() result = cond.wait_for(lambda : state.value==4, timeout=expected) dt = time.monotonic() - dt - # borrow logic in assertTimeout() from test/lock_tests.py - if not result and expected * 0.6 < dt < expected * 10.0: + if not result and (expected - CLOCK_RES) <= dt: success.value = True @unittest.skipUnless(HAS_SHAREDCTYPES, 'needs sharedctypes') @@ -1672,7 +1679,7 @@ def test_waitfor_timeout(self): # Only increment 3 times, so state == 4 is never reached. for i in range(3): - time.sleep(0.01) + time.sleep(0.010) with cond: state.value += 1 cond.notify() @@ -2431,8 +2438,11 @@ def test_namespace(self): # # -def sqr(x, wait=0.0): - time.sleep(wait) +def sqr(x, wait=0.0, event=None): + if event is None: + time.sleep(wait) + else: + event.wait(wait) return x*x def mul(x, y): @@ -2571,10 +2581,18 @@ def test_async(self): self.assertTimingAlmostEqual(get.elapsed, TIMEOUT1) def test_async_timeout(self): - res = self.pool.apply_async(sqr, (6, TIMEOUT2 + 1.0)) - get = TimingWrapper(res.get) - self.assertRaises(multiprocessing.TimeoutError, get, timeout=TIMEOUT2) - self.assertTimingAlmostEqual(get.elapsed, TIMEOUT2) + p = self.Pool(3) + try: + event = threading.Event() if self.TYPE == 'threads' else None + res = p.apply_async(sqr, (6, TIMEOUT2 + support.SHORT_TIMEOUT, event)) + get = TimingWrapper(res.get) + self.assertRaises(multiprocessing.TimeoutError, get, timeout=TIMEOUT2) + self.assertTimingAlmostEqual(get.elapsed, TIMEOUT2) + finally: + if event is not None: + event.set() + p.terminate() + p.join() def test_imap(self): it = self.pool.imap(sqr, list(range(10))) @@ -2675,14 +2693,15 @@ def test_make_pool(self): p.join() def test_terminate(self): - result = self.pool.map_async( - time.sleep, [0.1 for i in range(10000)], chunksize=1 - ) - self.pool.terminate() - join = TimingWrapper(self.pool.join) - join() - # Sanity check the pool didn't wait for all tasks to finish - self.assertLess(join.elapsed, 2.0) + if self.TYPE == 'threads': + self.skipTest("Threads cannot be terminated") + + # Simulate slow tasks which take "forever" to complete + p = self.Pool(3) + args = [support.LONG_TIMEOUT for i in range(10_000)] + result = p.map_async(time.sleep, args, chunksize=1) + p.terminate() + p.join() def test_empty_iterable(self): # See Issue 12157 @@ -3149,6 +3168,44 @@ def test_rapid_restart(self): if hasattr(manager, "shutdown"): self.addCleanup(manager.shutdown) + +class FakeConnection: + def send(self, payload): + pass + + def recv(self): + return '#ERROR', pyqueue.Empty() + +class TestManagerExceptions(unittest.TestCase): + # Issue 106558: Manager exceptions avoids creating cyclic references. + def setUp(self): + self.mgr = multiprocessing.Manager() + + def tearDown(self): + self.mgr.shutdown() + self.mgr.join() + + def test_queue_get(self): + queue = self.mgr.Queue() + if gc.isenabled(): + gc.disable() + self.addCleanup(gc.enable) + try: + queue.get_nowait() + except pyqueue.Empty as e: + wr = weakref.ref(e) + self.assertEqual(wr(), None) + + def test_dispatch(self): + if gc.isenabled(): + gc.disable() + self.addCleanup(gc.enable) + try: + multiprocessing.managers.dispatch(FakeConnection(), None, None) + except pyqueue.Empty as e: + wr = weakref.ref(e) + self.assertEqual(wr(), None) + # # # @@ -4398,6 +4455,59 @@ def test_shared_memory_cleaned_after_process_termination(self): "resource_tracker: There appear to be 1 leaked " "shared_memory objects to clean up at shutdown", err) + @unittest.skipIf(os.name != "posix", "resource_tracker is posix only") + def test_shared_memory_untracking(self): + # gh-82300: When a separate Python process accesses shared memory + # with track=False, it must not cause the memory to be deleted + # when terminating. + cmd = '''if 1: + import sys + from multiprocessing.shared_memory import SharedMemory + mem = SharedMemory(create=False, name=sys.argv[1], track=False) + mem.close() + ''' + mem = shared_memory.SharedMemory(create=True, size=10) + # The resource tracker shares pipes with the subprocess, and so + # err existing means that the tracker process has terminated now. + try: + rc, out, err = script_helper.assert_python_ok("-c", cmd, mem.name) + self.assertNotIn(b"resource_tracker", err) + self.assertEqual(rc, 0) + mem2 = shared_memory.SharedMemory(create=False, name=mem.name) + mem2.close() + finally: + try: + mem.unlink() + except OSError: + pass + mem.close() + + @unittest.skipIf(os.name != "posix", "resource_tracker is posix only") + def test_shared_memory_tracking(self): + # gh-82300: When a separate Python process accesses shared memory + # with track=True, it must cause the memory to be deleted when + # terminating. + cmd = '''if 1: + import sys + from multiprocessing.shared_memory import SharedMemory + mem = SharedMemory(create=False, name=sys.argv[1], track=True) + mem.close() + ''' + mem = shared_memory.SharedMemory(create=True, size=10) + try: + rc, out, err = script_helper.assert_python_ok("-c", cmd, mem.name) + self.assertEqual(rc, 0) + self.assertIn( + b"resource_tracker: There appear to be 1 leaked " + b"shared_memory objects to clean up at shutdown", err) + finally: + try: + mem.unlink() + except OSError: + pass + resource_tracker.unregister(mem._name, "shared_memory") + mem.close() + # # Test to verify that `Finalize` works. # @@ -4466,6 +4576,7 @@ def test_finalize(self): result = [obj for obj in iter(conn.recv, 'STOP')] self.assertEqual(result, ['a', 'b', 'd10', 'd03', 'd02', 'd01', 'e']) + @support.requires_resource('cpu') def test_thread_safety(self): # bpo-24484: _run_finalizers() should be thread-safe def cb(): @@ -4613,6 +4724,29 @@ def test_level(self): root_logger.setLevel(root_level) logger.setLevel(level=LOG_LEVEL) + def test_filename(self): + logger = multiprocessing.get_logger() + original_level = logger.level + try: + logger.setLevel(util.DEBUG) + stream = io.StringIO() + handler = logging.StreamHandler(stream) + logging_format = '[%(levelname)s] [%(filename)s] %(message)s' + handler.setFormatter(logging.Formatter(logging_format)) + logger.addHandler(handler) + logger.info('1') + util.info('2') + logger.debug('3') + filename = os.path.basename(__file__) + log_record = stream.getvalue() + self.assertIn(f'[INFO] [{filename}] 1', log_record) + self.assertIn(f'[INFO] [{filename}] 2', log_record) + self.assertIn(f'[DEBUG] [{filename}] 3', log_record) + finally: + logger.setLevel(original_level) + logger.removeHandler(handler) + handler.close() + # class _TestLoggingProcessName(BaseTestCase): # @@ -4866,7 +5000,7 @@ class TestWait(unittest.TestCase): def _child_test_wait(cls, w, slow): for i in range(10): if slow: - time.sleep(random.random()*0.1) + time.sleep(random.random() * 0.100) w.send((i, os.getpid())) w.close() @@ -4906,7 +5040,7 @@ def _child_test_wait_socket(cls, address, slow): s.connect(address) for i in range(10): if slow: - time.sleep(random.random()*0.1) + time.sleep(random.random() * 0.100) s.sendall(('%s\n' % i).encode('ascii')) s.close() @@ -4951,34 +5085,30 @@ def test_wait_slow(self): def test_wait_socket_slow(self): self.test_wait_socket(True) + @support.requires_resource('walltime') def test_wait_timeout(self): from multiprocessing.connection import wait - expected = 5 + timeout = 5.0 # seconds a, b = multiprocessing.Pipe() start = time.monotonic() - res = wait([a, b], expected) + res = wait([a, b], timeout) delta = time.monotonic() - start self.assertEqual(res, []) - self.assertLess(delta, expected * 2) - self.assertGreater(delta, expected * 0.5) + self.assertGreater(delta, timeout - CLOCK_RES) b.send(None) - - start = time.monotonic() res = wait([a, b], 20) - delta = time.monotonic() - start - self.assertEqual(res, [a]) - self.assertLess(delta, 0.4) @classmethod def signal_and_sleep(cls, sem, period): sem.release() time.sleep(period) + @support.requires_resource('walltime') def test_wait_integer(self): from multiprocessing.connection import wait @@ -5331,6 +5461,14 @@ def test_context(self): self.assertRaises(ValueError, ctx.set_start_method, None) self.check_context(ctx) + def test_context_check_module_types(self): + try: + ctx = multiprocessing.get_context('forkserver') + except ValueError: + raise unittest.SkipTest('forkserver should be available') + with self.assertRaisesRegex(TypeError, 'module_names must be a list of strings'): + ctx.set_forkserver_preload([1, 2, 3]) + def test_set_get(self): multiprocessing.set_forkserver_preload(PRELOAD) count = 0 @@ -5375,6 +5513,56 @@ def test_preload_resources(self): print(err) self.fail("failed spawning forkserver or grandchild") + @unittest.skipIf(sys.platform == "win32", + "Only Spawn on windows so no risk of mixing") + @only_run_in_spawn_testsuite("avoids redundant testing.") + def test_mixed_startmethod(self): + # Fork-based locks cannot be used with spawned process + for process_method in ["spawn", "forkserver"]: + queue = multiprocessing.get_context("fork").Queue() + process_ctx = multiprocessing.get_context(process_method) + p = process_ctx.Process(target=close_queue, args=(queue,)) + err_msg = "A SemLock created in a fork" + with self.assertRaisesRegex(RuntimeError, err_msg): + p.start() + + # non-fork-based locks can be used with all other start methods + for queue_method in ["spawn", "forkserver"]: + for process_method in multiprocessing.get_all_start_methods(): + queue = multiprocessing.get_context(queue_method).Queue() + process_ctx = multiprocessing.get_context(process_method) + p = process_ctx.Process(target=close_queue, args=(queue,)) + p.start() + p.join() + + @classmethod + def _put_one_in_queue(cls, queue): + queue.put(1) + + @classmethod + def _put_two_and_nest_once(cls, queue): + queue.put(2) + process = multiprocessing.Process(target=cls._put_one_in_queue, args=(queue,)) + process.start() + process.join() + + def test_nested_startmethod(self): + # gh-108520: Regression test to ensure that child process can send its + # arguments to another process + queue = multiprocessing.Queue() + + process = multiprocessing.Process(target=self._put_two_and_nest_once, args=(queue,)) + process.start() + process.join() + + results = [] + while not queue.empty(): + results.append(queue.get()) + + # gh-109706: queue.put(1) can write into the queue before queue.put(2), + # there is no synchronization in the test. + self.assertSetEqual(set(results), set([2, 1])) + @unittest.skipIf(sys.platform == "win32", "test semantics don't make sense on Windows") @@ -6058,7 +6246,8 @@ class ThreadsMixin(BaseMixin): # Functions used to create test cases from the base ones in this module # -def install_tests_in_module_dict(remote_globs, start_method): +def install_tests_in_module_dict(remote_globs, start_method, + only_type=None, exclude_types=False): __module__ = remote_globs['__name__'] local_globs = globals() ALL_TYPES = {'processes', 'threads', 'manager'} @@ -6071,6 +6260,10 @@ def install_tests_in_module_dict(remote_globs, start_method): continue assert set(base.ALLOWED_TYPES) <= ALL_TYPES, base.ALLOWED_TYPES for type_ in base.ALLOWED_TYPES: + if only_type and type_ != only_type: + continue + if exclude_types: + continue newname = 'With' + type_.capitalize() + name[1:] Mixin = local_globs[type_.capitalize() + 'Mixin'] class Temp(base, Mixin, unittest.TestCase): @@ -6081,6 +6274,9 @@ class Temp(base, Mixin, unittest.TestCase): Temp.__module__ = __module__ remote_globs[newname] = Temp elif issubclass(base, unittest.TestCase): + if only_type: + continue + class Temp(base, object): pass Temp.__name__ = Temp.__qualname__ = name diff --git a/Lib/test/_testcppext.cpp b/Lib/test/_testcppext.cpp deleted file mode 100644 index 82b471312dd2b9..00000000000000 --- a/Lib/test/_testcppext.cpp +++ /dev/null @@ -1,258 +0,0 @@ -// gh-91321: Very basic C++ test extension to check that the Python C API is -// compatible with C++ and does not emit C++ compiler warnings. - -// Always enable assertions -#undef NDEBUG - -#include "Python.h" - -#if __cplusplus >= 201103 -# define NAME _testcpp11ext -#else -# define NAME _testcpp03ext -#endif - -#define _STR(NAME) #NAME -#define STR(NAME) _STR(NAME) - -PyDoc_STRVAR(_testcppext_add_doc, -"add(x, y)\n" -"\n" -"Return the sum of two integers: x + y."); - -static PyObject * -_testcppext_add(PyObject *Py_UNUSED(module), PyObject *args) -{ - long i, j; - if (!PyArg_ParseTuple(args, "ll:foo", &i, &j)) { - return _Py_NULL; - } - long res = i + j; - return PyLong_FromLong(res); -} - - -// Class to test operator casting an object to PyObject* -class StrongRef -{ -public: - StrongRef(PyObject *obj) : m_obj(obj) { - Py_INCREF(this->m_obj); - } - - ~StrongRef() { - Py_DECREF(this->m_obj); - } - - // Cast to PyObject*: get a borrowed reference - inline operator PyObject*() const { return this->m_obj; } - -private: - PyObject *m_obj; // Strong reference -}; - - -static PyObject * -test_api_casts(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args)) -{ - PyObject *obj = Py_BuildValue("(ii)", 1, 2); - if (obj == _Py_NULL) { - return _Py_NULL; - } - Py_ssize_t refcnt = Py_REFCNT(obj); - assert(refcnt >= 1); - - // gh-92138: For backward compatibility, functions of Python C API accepts - // "const PyObject*". Check that using it does not emit C++ compiler - // warnings. - const PyObject *const_obj = obj; - Py_INCREF(const_obj); - Py_DECREF(const_obj); - PyTypeObject *type = Py_TYPE(const_obj); - assert(Py_REFCNT(const_obj) == refcnt); - assert(type == &PyTuple_Type); - assert(PyTuple_GET_SIZE(const_obj) == 2); - PyObject *one = PyTuple_GET_ITEM(const_obj, 0); - assert(PyLong_AsLong(one) == 1); - - // gh-92898: StrongRef doesn't inherit from PyObject but has an operator to - // cast to PyObject*. - StrongRef strong_ref(obj); - assert(Py_TYPE(strong_ref) == &PyTuple_Type); - assert(Py_REFCNT(strong_ref) == (refcnt + 1)); - Py_INCREF(strong_ref); - Py_DECREF(strong_ref); - - // gh-93442: Pass 0 as NULL for PyObject* - Py_XINCREF(0); - Py_XDECREF(0); -#if __cplusplus >= 201103 - // Test nullptr passed as PyObject* - Py_XINCREF(nullptr); - Py_XDECREF(nullptr); -#endif - - Py_DECREF(obj); - Py_RETURN_NONE; -} - - -static PyObject * -test_unicode(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args)) -{ - PyObject *str = PyUnicode_FromString("abc"); - if (str == _Py_NULL) { - return _Py_NULL; - } - - assert(PyUnicode_Check(str)); - assert(PyUnicode_GET_LENGTH(str) == 3); - - // gh-92800: test PyUnicode_READ() - const void* data = PyUnicode_DATA(str); - assert(data != _Py_NULL); - int kind = PyUnicode_KIND(str); - assert(kind == PyUnicode_1BYTE_KIND); - assert(PyUnicode_READ(kind, data, 0) == 'a'); - - // gh-92800: test PyUnicode_READ() casts - const void* const_data = PyUnicode_DATA(str); - unsigned int ukind = static_cast(kind); - assert(PyUnicode_READ(ukind, const_data, 2) == 'c'); - - assert(PyUnicode_READ_CHAR(str, 1) == 'b'); - - Py_DECREF(str); - Py_RETURN_NONE; -} - -/* Test a `new`-allocated object with a virtual method. - * (https://github.com/python/cpython/issues/94731) */ - -class VirtualPyObject : public PyObject { -public: - VirtualPyObject(); - virtual ~VirtualPyObject() { - delete [] internal_data; - --instance_count; - } - virtual void set_internal_data() { - internal_data[0] = 1; - } - static void dealloc(PyObject* o) { - delete static_cast(o); - } - - // Number of "living" instances - static int instance_count; -private: - // buffer that can get corrupted - int* internal_data; -}; - -int VirtualPyObject::instance_count = 0; - -PyType_Slot VirtualPyObject_Slots[] = { - {Py_tp_free, (void*)VirtualPyObject::dealloc}, - {0, _Py_NULL}, -}; - -PyType_Spec VirtualPyObject_Spec = { - /* .name */ STR(NAME) ".VirtualPyObject", - /* .basicsize */ sizeof(VirtualPyObject), - /* .itemsize */ 0, - /* .flags */ Py_TPFLAGS_DEFAULT, - /* .slots */ VirtualPyObject_Slots, -}; - -VirtualPyObject::VirtualPyObject() { - // Create a temporary type (just so we don't need to store it) - PyObject *type = PyType_FromSpec(&VirtualPyObject_Spec); - // no good way to signal failure from a C++ constructor, so use assert - // for error handling - assert(type); - assert(PyObject_Init(this, (PyTypeObject *)type)); - Py_DECREF(type); - internal_data = new int[50]; - ++instance_count; -} - -static PyObject * -test_virtual_object(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args)) -{ - VirtualPyObject* obj = new VirtualPyObject(); - obj->set_internal_data(); - Py_DECREF(obj); - if (VirtualPyObject::instance_count != 0) { - return PyErr_Format( - PyExc_AssertionError, - "instance_count should be 0, got %d", - VirtualPyObject::instance_count); - } - Py_RETURN_NONE; -} - -static PyMethodDef _testcppext_methods[] = { - {"add", _testcppext_add, METH_VARARGS, _testcppext_add_doc}, - {"test_api_casts", test_api_casts, METH_NOARGS, _Py_NULL}, - {"test_unicode", test_unicode, METH_NOARGS, _Py_NULL}, - {"test_virtual_object", test_virtual_object, METH_NOARGS, _Py_NULL}, - // Note: _testcppext_exec currently runs all test functions directly. - // When adding a new one, add a call there. - - {_Py_NULL, _Py_NULL, 0, _Py_NULL} /* sentinel */ -}; - - -static int -_testcppext_exec(PyObject *module) -{ - if (PyModule_AddIntMacro(module, __cplusplus) < 0) { - return -1; - } - - PyObject *result; - - result = PyObject_CallMethod(module, "test_api_casts", ""); - if (!result) return -1; - Py_DECREF(result); - - result = PyObject_CallMethod(module, "test_unicode", ""); - if (!result) return -1; - Py_DECREF(result); - - result = PyObject_CallMethod(module, "test_virtual_object", ""); - if (!result) return -1; - Py_DECREF(result); - - return 0; -} - -static PyModuleDef_Slot _testcppext_slots[] = { - {Py_mod_exec, reinterpret_cast(_testcppext_exec)}, - {0, _Py_NULL} -}; - - -PyDoc_STRVAR(_testcppext_doc, "C++ test extension."); - -static struct PyModuleDef _testcppext_module = { - PyModuleDef_HEAD_INIT, // m_base - STR(NAME), // m_name - _testcppext_doc, // m_doc - 0, // m_size - _testcppext_methods, // m_methods - _testcppext_slots, // m_slots - _Py_NULL, // m_traverse - _Py_NULL, // m_clear - _Py_NULL, // m_free -}; - -#define _FUNC_NAME(NAME) PyInit_ ## NAME -#define FUNC_NAME(NAME) _FUNC_NAME(NAME) - -PyMODINIT_FUNC -FUNC_NAME(NAME)(void) -{ - return PyModuleDef_Init(&_testcppext_module); -} diff --git a/Lib/test/archivetestdata/README.md b/Lib/test/archivetestdata/README.md new file mode 100644 index 00000000000000..7b555fa32765bf --- /dev/null +++ b/Lib/test/archivetestdata/README.md @@ -0,0 +1,36 @@ +# Test data for `test_zipfile`, `test_tarfile` (and even some others) + +## `test_zipfile` + +The test executables in this directory are created manually from `header.sh` and +the `testdata_module_inside_zip.py` file. You must have Info-ZIP's zip utility +installed (`apt install zip` on Debian). + +### Purpose of `exe_with_zip` and `exe_with_z64` + +These are used to test executable files with an appended zipfile, in a scenario +where the executable is _not_ a Python interpreter itself so our automatic +zipimport machinery (that'd look for `__main__.py`) is not being used. + +### Updating the test executables + +If you update header.sh or the testdata_module_inside_zip.py file, rerun the +commands below. These are expected to be rarely changed, if ever. + +#### Standard old format (2.0) zip file + +``` +zip -0 zip2.zip testdata_module_inside_zip.py +cat header.sh zip2.zip >exe_with_zip +rm zip2.zip +``` + +#### Modern format (4.5) zip64 file + +Redirecting from stdin forces Info-ZIP's zip tool to create a zip64. + +``` +zip -0 zip64.zip +cat header.sh zip64.zip >exe_with_z64 +rm zip64.zip +``` diff --git a/Lib/test/ziptestdata/exe_with_z64 b/Lib/test/archivetestdata/exe_with_z64 similarity index 100% rename from Lib/test/ziptestdata/exe_with_z64 rename to Lib/test/archivetestdata/exe_with_z64 diff --git a/Lib/test/ziptestdata/exe_with_zip b/Lib/test/archivetestdata/exe_with_zip similarity index 100% rename from Lib/test/ziptestdata/exe_with_zip rename to Lib/test/archivetestdata/exe_with_zip diff --git a/Lib/test/ziptestdata/header.sh b/Lib/test/archivetestdata/header.sh similarity index 100% rename from Lib/test/ziptestdata/header.sh rename to Lib/test/archivetestdata/header.sh diff --git a/Lib/test/recursion.tar b/Lib/test/archivetestdata/recursion.tar similarity index 100% rename from Lib/test/recursion.tar rename to Lib/test/archivetestdata/recursion.tar diff --git a/Lib/test/ziptestdata/testdata_module_inside_zip.py b/Lib/test/archivetestdata/testdata_module_inside_zip.py similarity index 100% rename from Lib/test/ziptestdata/testdata_module_inside_zip.py rename to Lib/test/archivetestdata/testdata_module_inside_zip.py diff --git a/Lib/test/testtar.tar b/Lib/test/archivetestdata/testtar.tar similarity index 100% rename from Lib/test/testtar.tar rename to Lib/test/archivetestdata/testtar.tar diff --git a/Lib/test/testtar.tar.xz b/Lib/test/archivetestdata/testtar.tar.xz similarity index 100% rename from Lib/test/testtar.tar.xz rename to Lib/test/archivetestdata/testtar.tar.xz diff --git a/Lib/test/zip_cp437_header.zip b/Lib/test/archivetestdata/zip_cp437_header.zip similarity index 100% rename from Lib/test/zip_cp437_header.zip rename to Lib/test/archivetestdata/zip_cp437_header.zip diff --git a/Lib/test/zipdir.zip b/Lib/test/archivetestdata/zipdir.zip similarity index 100% rename from Lib/test/zipdir.zip rename to Lib/test/archivetestdata/zipdir.zip diff --git a/Lib/test/audit-tests.py b/Lib/test/audit-tests.py index 0edc9d9c472766..ce4a11b119c900 100644 --- a/Lib/test/audit-tests.py +++ b/Lib/test/audit-tests.py @@ -186,7 +186,7 @@ class C(A): ) -def test_open(): +def test_open(testfn): # SSLContext.load_dh_params uses _Py_fopen_obj rather than normal open() try: import ssl @@ -199,11 +199,11 @@ def test_open(): # All of them should fail with TestHook(raise_on_events={"open"}) as hook: for fn, *args in [ - (open, sys.argv[2], "r"), + (open, testfn, "r"), (open, sys.executable, "rb"), (open, 3, "wb"), - (open, sys.argv[2], "w", -1, None, None, None, False, lambda *a: 1), - (load_dh_params, sys.argv[2]), + (open, testfn, "w", -1, None, None, None, False, lambda *a: 1), + (load_dh_params, testfn), ]: if not fn: continue @@ -216,11 +216,11 @@ def test_open(): [ i for i in [ - (sys.argv[2], "r"), + (testfn, "r"), (sys.executable, "r"), (3, "w"), - (sys.argv[2], "w"), - (sys.argv[2], "rb") if load_dh_params else None, + (testfn, "w"), + (testfn, "rb") if load_dh_params else None, ] if i is not None ], @@ -289,7 +289,7 @@ def hook(event, args): def test_unraisablehook(): - from _testcapi import write_unraisable_exc + from _testcapi import err_formatunraisable def unraisablehook(hookargs): pass @@ -302,7 +302,8 @@ def hook(event, args): sys.addaudithook(hook) sys.unraisablehook = unraisablehook - write_unraisable_exc(RuntimeError("nonfatal-error"), "for audit hook test", None) + err_formatunraisable(RuntimeError("nonfatal-error"), + "Exception ignored for audit hook test") def test_winreg(): @@ -398,15 +399,18 @@ def hook(event, *args): cx2 = sqlite3.Connection(":memory:") # Configured without --enable-loadable-sqlite-extensions - if hasattr(sqlite3.Connection, "enable_load_extension"): - cx1.enable_load_extension(False) - try: - cx1.load_extension("test") - except sqlite3.OperationalError: - pass - else: - raise RuntimeError("Expected sqlite3.load_extension to fail") - + try: + if hasattr(sqlite3.Connection, "enable_load_extension"): + cx1.enable_load_extension(False) + try: + cx1.load_extension("test") + except sqlite3.OperationalError: + pass + else: + raise RuntimeError("Expected sqlite3.load_extension to fail") + finally: + cx1.close() + cx2.close() def test_sys_getframe(): import sys @@ -451,6 +455,9 @@ def __call__(self): i = _thread.start_new_thread(test_func(), ()) lock.acquire() + handle = _thread.start_joinable_thread(test_func()) + handle.join() + def test_threading_abort(): # Ensures that aborting PyThreadState_New raises the correct exception @@ -514,10 +521,39 @@ def test_not_in_gc(): assert hook not in o +def test_time(mode): + import time + + def hook(event, args): + if event.startswith("time."): + if mode == 'print': + print(event, *args) + elif mode == 'fail': + raise AssertionError('hook failed') + sys.addaudithook(hook) + + time.sleep(0) + time.sleep(0.0625) # 1/16, a small exact float + try: + time.sleep(-1) + except ValueError: + pass + +def test_sys_monitoring_register_callback(): + import sys + + def hook(event, args): + if event.startswith("sys.monitoring"): + print(event, args) + + sys.addaudithook(hook) + sys.monitoring.register_callback(1, 1, None) + + if __name__ == "__main__": from test.support import suppress_msvcrt_asserts suppress_msvcrt_asserts() test = sys.argv[1] - globals()[test]() + globals()[test](*sys.argv[2:]) diff --git a/Lib/test/autotest.py b/Lib/test/autotest.py index fa85cc153a133a..b5a1fab404c72d 100644 --- a/Lib/test/autotest.py +++ b/Lib/test/autotest.py @@ -1,5 +1,5 @@ # This should be equivalent to running regrtest.py from the cmdline. # It can be especially handy if you're in an interactive shell, e.g., # from test import autotest. -from test.libregrtest import main +from test.libregrtest.main import main main() diff --git a/Lib/test/badsyntax_future3.py b/Lib/test/badsyntax_future3.py deleted file mode 100644 index f1c8417edaa297..00000000000000 --- a/Lib/test/badsyntax_future3.py +++ /dev/null @@ -1,10 +0,0 @@ -"""This is a test""" -from __future__ import nested_scopes -from __future__ import rested_snopes - -def f(x): - def g(y): - return x + y - return g - -result = f(2)(4) diff --git a/Lib/test/badsyntax_future4.py b/Lib/test/badsyntax_future4.py deleted file mode 100644 index b5f4c98e922ac2..00000000000000 --- a/Lib/test/badsyntax_future4.py +++ /dev/null @@ -1,10 +0,0 @@ -"""This is a test""" -import __future__ -from __future__ import nested_scopes - -def f(x): - def g(y): - return x + y - return g - -result = f(2)(4) diff --git a/Lib/test/badsyntax_future5.py b/Lib/test/badsyntax_future5.py deleted file mode 100644 index 8a7e5fcb70ff2e..00000000000000 --- a/Lib/test/badsyntax_future5.py +++ /dev/null @@ -1,12 +0,0 @@ -"""This is a test""" -from __future__ import nested_scopes -import foo -from __future__ import nested_scopes - - -def f(x): - def g(y): - return x + y - return g - -result = f(2)(4) diff --git a/Lib/test/badsyntax_future6.py b/Lib/test/badsyntax_future6.py deleted file mode 100644 index 5a8b55a02c41bf..00000000000000 --- a/Lib/test/badsyntax_future6.py +++ /dev/null @@ -1,10 +0,0 @@ -"""This is a test""" -"this isn't a doc string" -from __future__ import nested_scopes - -def f(x): - def g(y): - return x + y - return g - -result = f(2)(4) diff --git a/Lib/test/badsyntax_future7.py b/Lib/test/badsyntax_future7.py deleted file mode 100644 index 131db2c2164cf2..00000000000000 --- a/Lib/test/badsyntax_future7.py +++ /dev/null @@ -1,11 +0,0 @@ -"""This is a test""" - -from __future__ import nested_scopes; import string; from __future__ import \ - nested_scopes - -def f(x): - def g(y): - return x + y - return g - -result = f(2)(4) diff --git a/Lib/test/badsyntax_future8.py b/Lib/test/badsyntax_future8.py deleted file mode 100644 index ca45289e2e5a4f..00000000000000 --- a/Lib/test/badsyntax_future8.py +++ /dev/null @@ -1,10 +0,0 @@ -"""This is a test""" - -from __future__ import * - -def f(x): - def g(y): - return x + y - return g - -print(f(2)(4)) diff --git a/Lib/test/badsyntax_future9.py b/Lib/test/badsyntax_future9.py deleted file mode 100644 index 916de06ab71e97..00000000000000 --- a/Lib/test/badsyntax_future9.py +++ /dev/null @@ -1,10 +0,0 @@ -"""This is a test""" - -from __future__ import nested_scopes, braces - -def f(x): - def g(y): - return x + y - return g - -print(f(2)(4)) diff --git a/Lib/test/bisect_cmd.py b/Lib/test/bisect_cmd.py index 0bdd7a43c03f7b..5cb804bd469dc3 100755 --- a/Lib/test/bisect_cmd.py +++ b/Lib/test/bisect_cmd.py @@ -109,9 +109,10 @@ def parse_args(): def main(): args = parse_args() - if '-w' in args.test_args or '--verbose2' in args.test_args: - print("WARNING: -w/--verbose2 option should not be used to bisect!") - print() + for opt in ('-w', '--rerun', '--verbose2'): + if opt in args.test_args: + print(f"WARNING: {opt} option should not be used to bisect!") + print() if args.input: with open(args.input) as fp: diff --git a/Lib/test/allsans.pem b/Lib/test/certdata/allsans.pem similarity index 100% rename from Lib/test/allsans.pem rename to Lib/test/certdata/allsans.pem diff --git a/Lib/test/badcert.pem b/Lib/test/certdata/badcert.pem similarity index 100% rename from Lib/test/badcert.pem rename to Lib/test/certdata/badcert.pem diff --git a/Lib/test/badkey.pem b/Lib/test/certdata/badkey.pem similarity index 100% rename from Lib/test/badkey.pem rename to Lib/test/certdata/badkey.pem diff --git a/Lib/test/capath/4e1295a3.0 b/Lib/test/certdata/capath/4e1295a3.0 similarity index 100% rename from Lib/test/capath/4e1295a3.0 rename to Lib/test/certdata/capath/4e1295a3.0 diff --git a/Lib/test/capath/5ed36f99.0 b/Lib/test/certdata/capath/5ed36f99.0 similarity index 100% rename from Lib/test/capath/5ed36f99.0 rename to Lib/test/certdata/capath/5ed36f99.0 diff --git a/Lib/test/capath/6e88d7b8.0 b/Lib/test/certdata/capath/6e88d7b8.0 similarity index 100% rename from Lib/test/capath/6e88d7b8.0 rename to Lib/test/certdata/capath/6e88d7b8.0 diff --git a/Lib/test/capath/99d0fa06.0 b/Lib/test/certdata/capath/99d0fa06.0 similarity index 100% rename from Lib/test/capath/99d0fa06.0 rename to Lib/test/certdata/capath/99d0fa06.0 diff --git a/Lib/test/capath/b1930218.0 b/Lib/test/certdata/capath/b1930218.0 similarity index 100% rename from Lib/test/capath/b1930218.0 rename to Lib/test/certdata/capath/b1930218.0 diff --git a/Lib/test/capath/ceff1710.0 b/Lib/test/certdata/capath/ceff1710.0 similarity index 100% rename from Lib/test/capath/ceff1710.0 rename to Lib/test/certdata/capath/ceff1710.0 diff --git a/Lib/test/ffdh3072.pem b/Lib/test/certdata/ffdh3072.pem similarity index 100% rename from Lib/test/ffdh3072.pem rename to Lib/test/certdata/ffdh3072.pem diff --git a/Lib/test/idnsans.pem b/Lib/test/certdata/idnsans.pem similarity index 100% rename from Lib/test/idnsans.pem rename to Lib/test/certdata/idnsans.pem diff --git a/Lib/test/keycert.passwd.pem b/Lib/test/certdata/keycert.passwd.pem similarity index 100% rename from Lib/test/keycert.passwd.pem rename to Lib/test/certdata/keycert.passwd.pem diff --git a/Lib/test/keycert.pem b/Lib/test/certdata/keycert.pem similarity index 100% rename from Lib/test/keycert.pem rename to Lib/test/certdata/keycert.pem diff --git a/Lib/test/keycert2.pem b/Lib/test/certdata/keycert2.pem similarity index 100% rename from Lib/test/keycert2.pem rename to Lib/test/certdata/keycert2.pem diff --git a/Lib/test/keycert3.pem b/Lib/test/certdata/keycert3.pem similarity index 100% rename from Lib/test/keycert3.pem rename to Lib/test/certdata/keycert3.pem diff --git a/Lib/test/keycert4.pem b/Lib/test/certdata/keycert4.pem similarity index 100% rename from Lib/test/keycert4.pem rename to Lib/test/certdata/keycert4.pem diff --git a/Lib/test/keycertecc.pem b/Lib/test/certdata/keycertecc.pem similarity index 100% rename from Lib/test/keycertecc.pem rename to Lib/test/certdata/keycertecc.pem diff --git a/Lib/test/make_ssl_certs.py b/Lib/test/certdata/make_ssl_certs.py similarity index 100% rename from Lib/test/make_ssl_certs.py rename to Lib/test/certdata/make_ssl_certs.py diff --git a/Lib/test/nokia.pem b/Lib/test/certdata/nokia.pem similarity index 100% rename from Lib/test/nokia.pem rename to Lib/test/certdata/nokia.pem diff --git a/Lib/test/nosan.pem b/Lib/test/certdata/nosan.pem similarity index 100% rename from Lib/test/nosan.pem rename to Lib/test/certdata/nosan.pem diff --git a/Lib/test/nullbytecert.pem b/Lib/test/certdata/nullbytecert.pem similarity index 100% rename from Lib/test/nullbytecert.pem rename to Lib/test/certdata/nullbytecert.pem diff --git a/Lib/test/nullcert.pem b/Lib/test/certdata/nullcert.pem similarity index 100% rename from Lib/test/nullcert.pem rename to Lib/test/certdata/nullcert.pem diff --git a/Lib/test/pycacert.pem b/Lib/test/certdata/pycacert.pem similarity index 100% rename from Lib/test/pycacert.pem rename to Lib/test/certdata/pycacert.pem diff --git a/Lib/test/pycakey.pem b/Lib/test/certdata/pycakey.pem similarity index 100% rename from Lib/test/pycakey.pem rename to Lib/test/certdata/pycakey.pem diff --git a/Lib/test/revocation.crl b/Lib/test/certdata/revocation.crl similarity index 100% rename from Lib/test/revocation.crl rename to Lib/test/certdata/revocation.crl diff --git a/Lib/test/secp384r1.pem b/Lib/test/certdata/secp384r1.pem similarity index 100% rename from Lib/test/secp384r1.pem rename to Lib/test/certdata/secp384r1.pem diff --git a/Lib/test/selfsigned_pythontestdotnet.pem b/Lib/test/certdata/selfsigned_pythontestdotnet.pem similarity index 100% rename from Lib/test/selfsigned_pythontestdotnet.pem rename to Lib/test/certdata/selfsigned_pythontestdotnet.pem diff --git a/Lib/test/ssl_cert.pem b/Lib/test/certdata/ssl_cert.pem similarity index 100% rename from Lib/test/ssl_cert.pem rename to Lib/test/certdata/ssl_cert.pem diff --git a/Lib/test/ssl_key.passwd.pem b/Lib/test/certdata/ssl_key.passwd.pem similarity index 100% rename from Lib/test/ssl_key.passwd.pem rename to Lib/test/certdata/ssl_key.passwd.pem diff --git a/Lib/test/ssl_key.pem b/Lib/test/certdata/ssl_key.pem similarity index 100% rename from Lib/test/ssl_key.pem rename to Lib/test/certdata/ssl_key.pem diff --git a/Lib/test/talos-2019-0758.pem b/Lib/test/certdata/talos-2019-0758.pem similarity index 100% rename from Lib/test/talos-2019-0758.pem rename to Lib/test/certdata/talos-2019-0758.pem diff --git a/Lib/test/clinic.test.c b/Lib/test/clinic.test.c index d2ad1a0482c304..b15aeb898d35a1 100644 --- a/Lib/test/clinic.test.c +++ b/Lib/test/clinic.test.c @@ -4,9 +4,11 @@ output preset block /*[clinic end generated code: output=da39a3ee5e6b4b0d input=3c81ac2402d06a8b]*/ /*[clinic input] +module m +class m.T "TestObj *" "TestType" class Test "TestObj *" "TestType" [clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=fc7e50384d12b83f]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=f761b4d55cb179cf]*/ /*[clinic input] test_object_converter @@ -471,7 +473,7 @@ test_bool_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (nargs < 3) { goto skip_optional; } - c = _PyLong_AsInt(args[2]); + c = PyLong_AsInt(args[2]); if (c == -1 && PyErr_Occurred()) { goto exit; } @@ -484,7 +486,7 @@ test_bool_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) static PyObject * test_bool_converter_impl(PyObject *module, int a, int b, int c) -/*[clinic end generated code: output=27f0e653a70b9be3 input=939854fa9f248c60]*/ +/*[clinic end generated code: output=3190e46490de0644 input=939854fa9f248c60]*/ /*[clinic input] @@ -1007,14 +1009,14 @@ test_int_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (nargs < 1) { goto skip_optional; } - a = _PyLong_AsInt(args[0]); + a = PyLong_AsInt(args[0]); if (a == -1 && PyErr_Occurred()) { goto exit; } if (nargs < 2) { goto skip_optional; } - b = _PyLong_AsInt(args[1]); + b = PyLong_AsInt(args[1]); if (b == -1 && PyErr_Occurred()) { goto exit; } @@ -1033,7 +1035,7 @@ test_int_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (nargs < 4) { goto skip_optional; } - d = _PyLong_AsInt(args[3]); + d = PyLong_AsInt(args[3]); if (d == -1 && PyErr_Occurred()) { goto exit; } @@ -1046,7 +1048,7 @@ test_int_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) static PyObject * test_int_converter_impl(PyObject *module, int a, int b, int c, myenum d) -/*[clinic end generated code: output=375eedba5ca9a5b3 input=d20541fc1ca0553e]*/ +/*[clinic end generated code: output=5aed87a7589eefb2 input=d20541fc1ca0553e]*/ /*[clinic input] @@ -4507,7 +4509,7 @@ Test_cls_with_param(TestObj *self, PyTypeObject *cls, PyObject *const *args, Py_ if (!args) { goto exit; } - a = _PyLong_AsInt(args[0]); + a = PyLong_AsInt(args[0]); if (a == -1 && PyErr_Occurred()) { goto exit; } @@ -4519,7 +4521,7 @@ Test_cls_with_param(TestObj *self, PyTypeObject *cls, PyObject *const *args, Py_ static PyObject * Test_cls_with_param_impl(TestObj *self, PyTypeObject *cls, int a) -/*[clinic end generated code: output=00218e7f583e6c81 input=af158077bd237ef9]*/ +/*[clinic end generated code: output=d89b99e83d442be0 input=af158077bd237ef9]*/ /*[clinic input] @@ -4701,7 +4703,7 @@ Test_an_metho_arg_named_arg(TestObj *self, PyObject *arg_) PyObject *return_value = NULL; int arg; - arg = _PyLong_AsInt(arg_); + arg = PyLong_AsInt(arg_); if (arg == -1 && PyErr_Occurred()) { goto exit; } @@ -4713,7 +4715,7 @@ Test_an_metho_arg_named_arg(TestObj *self, PyObject *arg_) static PyObject * Test_an_metho_arg_named_arg_impl(TestObj *self, int arg) -/*[clinic end generated code: output=7d590626642194ae input=2a53a57cf5624f95]*/ +/*[clinic end generated code: output=9f04de4a62287e28 input=2a53a57cf5624f95]*/ /*[clinic input] @@ -4949,6 +4951,65 @@ static PyObject * Test_meth_coexist_impl(TestObj *self) /*[clinic end generated code: output=808a293d0cd27439 input=2a1d75b5e6fec6dd]*/ +/*[clinic input] +@getter +Test.property +[clinic start generated code]*/ + +#if defined(Test_property_HAS_DOCSTR) +# define Test_property_DOCSTR Test_property__doc__ +#else +# define Test_property_DOCSTR NULL +#endif +#if defined(TEST_PROPERTY_GETSETDEF) +# undef TEST_PROPERTY_GETSETDEF +# define TEST_PROPERTY_GETSETDEF {"property", (getter)Test_property_get, (setter)Test_property_set, Test_property_DOCSTR}, +#else +# define TEST_PROPERTY_GETSETDEF {"property", (getter)Test_property_get, NULL, Test_property_DOCSTR}, +#endif + +static PyObject * +Test_property_get_impl(TestObj *self); + +static PyObject * +Test_property_get(TestObj *self, void *Py_UNUSED(context)) +{ + return Test_property_get_impl(self); +} + +static PyObject * +Test_property_get_impl(TestObj *self) +/*[clinic end generated code: output=27b519719d992e03 input=2d92b3449fbc7d2b]*/ + +/*[clinic input] +@setter +Test.property +[clinic start generated code]*/ + +#if defined(TEST_PROPERTY_HAS_DOCSTR) +# define Test_property_DOCSTR Test_property__doc__ +#else +# define Test_property_DOCSTR NULL +#endif +#if defined(TEST_PROPERTY_GETSETDEF) +# undef TEST_PROPERTY_GETSETDEF +# define TEST_PROPERTY_GETSETDEF {"property", (getter)Test_property_get, (setter)Test_property_set, Test_property_DOCSTR}, +#else +# define TEST_PROPERTY_GETSETDEF {"property", NULL, (setter)Test_property_set, NULL}, +#endif + +static int +Test_property_set_impl(TestObj *self, PyObject *value); + +static int +Test_property_set(TestObj *self, PyObject *value, void *Py_UNUSED(context)) +{ + return Test_property_set_impl(self, value); +} + +static int +Test_property_set_impl(TestObj *self, PyObject *value) +/*[clinic end generated code: output=9797cd03c5204ddb input=3bc3f46a23c83a88]*/ /*[clinic input] output push @@ -5060,7 +5121,7 @@ mangled_c_keyword_identifier(PyObject *module, PyObject *const *args, Py_ssize_t if (!args) { goto exit; } - int_value = _PyLong_AsInt(args[0]); + int_value = PyLong_AsInt(args[0]); if (int_value == -1 && PyErr_Occurred()) { goto exit; } @@ -5072,7 +5133,7 @@ mangled_c_keyword_identifier(PyObject *module, PyObject *const *args, Py_ssize_t static PyObject * mangled_c_keyword_identifier_impl(PyObject *module, int int_value) -/*[clinic end generated code: output=c049d7d79be26cda input=060876448ab567a2]*/ +/*[clinic end generated code: output=f24b37e0368e0eb8 input=060876448ab567a2]*/ /*[clinic input] @@ -5380,6 +5441,7 @@ static PyObject * fn_with_default_binop_expr_impl(PyObject *module, PyObject *arg) /*[clinic end generated code: output=018672772e4092ff input=1b55c8ae68d89453]*/ + /*[python input] class Custom_converter(CConverter): type = "str" @@ -5464,3 +5526,248 @@ docstr_fallback_to_converter_default(PyObject *module, PyObject *const *args, Py static PyObject * docstr_fallback_to_converter_default_impl(PyObject *module, str a) /*[clinic end generated code: output=ae24a9c6f60ee8a6 input=0cbe6a4d24bc2274]*/ + + +/*[clinic input] +@critical_section +test_critical_section +[clinic start generated code]*/ + +PyDoc_STRVAR(test_critical_section__doc__, +"test_critical_section($module, /)\n" +"--\n" +"\n"); + +#define TEST_CRITICAL_SECTION_METHODDEF \ + {"test_critical_section", (PyCFunction)test_critical_section, METH_NOARGS, test_critical_section__doc__}, + +static PyObject * +test_critical_section_impl(PyObject *module); + +static PyObject * +test_critical_section(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + PyObject *return_value = NULL; + + Py_BEGIN_CRITICAL_SECTION(module); + return_value = test_critical_section_impl(module); + Py_END_CRITICAL_SECTION(); + + return return_value; +} + +static PyObject * +test_critical_section_impl(PyObject *module) +/*[clinic end generated code: output=9d5a87bb28aa3f0c input=8c58956d6ff00f80]*/ + + +/*[clinic input] +@critical_section +test_critical_section_meth_o + a: object(subclass_of="&PyUnicode_Type") + / +[clinic start generated code]*/ + +PyDoc_STRVAR(test_critical_section_meth_o__doc__, +"test_critical_section_meth_o($module, a, /)\n" +"--\n" +"\n"); + +#define TEST_CRITICAL_SECTION_METH_O_METHODDEF \ + {"test_critical_section_meth_o", (PyCFunction)test_critical_section_meth_o, METH_O, test_critical_section_meth_o__doc__}, + +static PyObject * +test_critical_section_meth_o_impl(PyObject *module, PyObject *a); + +static PyObject * +test_critical_section_meth_o(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + PyObject *a; + + if (!PyUnicode_Check(arg)) { + _PyArg_BadArgument("test_critical_section_meth_o", "argument", "str", arg); + goto exit; + } + a = arg; + Py_BEGIN_CRITICAL_SECTION(module); + return_value = test_critical_section_meth_o_impl(module, a); + Py_END_CRITICAL_SECTION(); + +exit: + return return_value; +} + +static PyObject * +test_critical_section_meth_o_impl(PyObject *module, PyObject *a) +/*[clinic end generated code: output=7a9d7420802d1202 input=376533f51eceb6c3]*/ + +/*[clinic input] +@critical_section a +test_critical_section_object + a: object(subclass_of="&PyUnicode_Type") + / +test_critical_section_object +[clinic start generated code]*/ + +PyDoc_STRVAR(test_critical_section_object__doc__, +"test_critical_section_object($module, a, /)\n" +"--\n" +"\n" +"test_critical_section_object"); + +#define TEST_CRITICAL_SECTION_OBJECT_METHODDEF \ + {"test_critical_section_object", (PyCFunction)test_critical_section_object, METH_O, test_critical_section_object__doc__}, + +static PyObject * +test_critical_section_object_impl(PyObject *module, PyObject *a); + +static PyObject * +test_critical_section_object(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + PyObject *a; + + if (!PyUnicode_Check(arg)) { + _PyArg_BadArgument("test_critical_section_object", "argument", "str", arg); + goto exit; + } + a = arg; + Py_BEGIN_CRITICAL_SECTION(a); + return_value = test_critical_section_object_impl(module, a); + Py_END_CRITICAL_SECTION(); + +exit: + return return_value; +} + +static PyObject * +test_critical_section_object_impl(PyObject *module, PyObject *a) +/*[clinic end generated code: output=ec06df92232b0fb5 input=6f67f91b523c875f]*/ + +PyDoc_STRVAR(test_critical_section_object__doc__, +"test_critical_section_object($module, a, /)\n" +"--\n" +"\n" +"test_critical_section_object"); + +#define TEST_CRITICAL_SECTION_OBJECT_METHODDEF \ + {"test_critical_section_object", (PyCFunction)test_critical_section_object, METH_O, test_critical_section_object__doc__}, + +static PyObject * +test_critical_section_object_impl(PyObject *module, PyObject *a); + +static PyObject * +test_critical_section_object(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + PyObject *a; + + if (!PyUnicode_Check(arg)) { + _PyArg_BadArgument("test_critical_section_object", "argument", "str", arg); + goto exit; + } + a = arg; + Py_BEGIN_CRITICAL_SECTION(a); + return_value = test_critical_section_object_impl(module, a); + Py_END_CRITICAL_SECTION(); + +exit: + return return_value; +} + +/*[clinic input] +@critical_section a b +test_critical_section_object2 + a: object(subclass_of="&PyUnicode_Type") + b: object(subclass_of="&PyUnicode_Type") + / +test_critical_section_object2 +[clinic start generated code]*/ + +PyDoc_STRVAR(test_critical_section_object2__doc__, +"test_critical_section_object2($module, a, b, /)\n" +"--\n" +"\n" +"test_critical_section_object2"); + +#define TEST_CRITICAL_SECTION_OBJECT2_METHODDEF \ + {"test_critical_section_object2", _PyCFunction_CAST(test_critical_section_object2), METH_FASTCALL, test_critical_section_object2__doc__}, + +static PyObject * +test_critical_section_object2_impl(PyObject *module, PyObject *a, + PyObject *b); + +static PyObject * +test_critical_section_object2(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *a; + PyObject *b; + + if (!_PyArg_CheckPositional("test_critical_section_object2", nargs, 2, 2)) { + goto exit; + } + if (!PyUnicode_Check(args[0])) { + _PyArg_BadArgument("test_critical_section_object2", "argument 1", "str", args[0]); + goto exit; + } + a = args[0]; + if (!PyUnicode_Check(args[1])) { + _PyArg_BadArgument("test_critical_section_object2", "argument 2", "str", args[1]); + goto exit; + } + b = args[1]; + Py_BEGIN_CRITICAL_SECTION2(a, b); + return_value = test_critical_section_object2_impl(module, a, b); + Py_END_CRITICAL_SECTION2(); + +exit: + return return_value; +} + +static PyObject * +test_critical_section_object2_impl(PyObject *module, PyObject *a, + PyObject *b) +/*[clinic end generated code: output=d73a1657c18df17a input=638824e41419a466]*/ + +PyDoc_STRVAR(test_critical_section_object2__doc__, +"test_critical_section_object2($module, a, b, /)\n" +"--\n" +"\n" +"test_critical_section_object2"); + +#define TEST_CRITICAL_SECTION_OBJECT2_METHODDEF \ + {"test_critical_section_object2", _PyCFunction_CAST(test_critical_section_object2), METH_FASTCALL, test_critical_section_object2__doc__}, + +static PyObject * +test_critical_section_object2_impl(PyObject *module, PyObject *a, + PyObject *b); + +static PyObject * +test_critical_section_object2(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *a; + PyObject *b; + + if (!_PyArg_CheckPositional("test_critical_section_object2", nargs, 2, 2)) { + goto exit; + } + if (!PyUnicode_Check(args[0])) { + _PyArg_BadArgument("test_critical_section_object2", "argument 1", "str", args[0]); + goto exit; + } + a = args[0]; + if (!PyUnicode_Check(args[1])) { + _PyArg_BadArgument("test_critical_section_object2", "argument 2", "str", args[1]); + goto exit; + } + b = args[1]; + Py_BEGIN_CRITICAL_SECTION2(a, b); + return_value = test_critical_section_object2_impl(module, a, b); + Py_END_CRITICAL_SECTION2(); + +exit: + return return_value; +} diff --git a/Lib/test/cfgparser.1 b/Lib/test/configdata/cfgparser.1 similarity index 100% rename from Lib/test/cfgparser.1 rename to Lib/test/configdata/cfgparser.1 diff --git a/Lib/test/cfgparser.2 b/Lib/test/configdata/cfgparser.2 similarity index 100% rename from Lib/test/cfgparser.2 rename to Lib/test/configdata/cfgparser.2 diff --git a/Lib/test/cfgparser.3 b/Lib/test/configdata/cfgparser.3 similarity index 100% rename from Lib/test/cfgparser.3 rename to Lib/test/configdata/cfgparser.3 diff --git a/Lib/test/cov.py b/Lib/test/cov.py new file mode 100644 index 00000000000000..e4699c7afe174a --- /dev/null +++ b/Lib/test/cov.py @@ -0,0 +1,48 @@ +"""A minimal hook for gathering line coverage of the standard library. + +Designed to be used with -Xpresite= which means: +* it installs itself on import +* it's not imported as `__main__` so can't use the ifmain idiom +* it can't import anything besides `sys` to avoid tainting gathered coverage +* filenames are not normalized + +To get gathered coverage back, look for 'test.cov' in `sys.modules` +instead of importing directly. That way you can determine if the module +was already in use. + +If you need to disable the hook, call the `disable()` function. +""" + +import sys + +mon = sys.monitoring + +FileName = str +LineNo = int +Location = tuple[FileName, LineNo] + +coverage: set[Location] = set() + + +# `types` and `typing` aren't imported to avoid invalid coverage +def add_line( + code: "types.CodeType", + lineno: int, +) -> "typing.Literal[sys.monitoring.DISABLE]": + coverage.add((code.co_filename, lineno)) + return mon.DISABLE + + +def enable(): + mon.use_tool_id(mon.COVERAGE_ID, "regrtest coverage") + mon.register_callback(mon.COVERAGE_ID, mon.events.LINE, add_line) + mon.set_events(mon.COVERAGE_ID, mon.events.LINE) + + +def disable(): + mon.set_events(mon.COVERAGE_ID, 0) + mon.register_callback(mon.COVERAGE_ID, mon.events.LINE, None) + mon.free_tool_id(mon.COVERAGE_ID) + + +enable() diff --git a/Lib/test/datetimetester.py b/Lib/test/datetimetester.py index 55e061950ff280..8bda17358db87f 100644 --- a/Lib/test/datetimetester.py +++ b/Lib/test/datetimetester.py @@ -1699,22 +1699,23 @@ def test_replace(self): cls = self.theclass args = [1, 2, 3] base = cls(*args) - self.assertEqual(base, base.replace()) + self.assertEqual(base.replace(), base) + self.assertEqual(copy.replace(base), base) - i = 0 - for name, newval in (("year", 2), - ("month", 3), - ("day", 4)): + changes = (("year", 2), + ("month", 3), + ("day", 4)) + for i, (name, newval) in enumerate(changes): newargs = args[:] newargs[i] = newval expected = cls(*newargs) - got = base.replace(**{name: newval}) - self.assertEqual(expected, got) - i += 1 + self.assertEqual(base.replace(**{name: newval}), expected) + self.assertEqual(copy.replace(base, **{name: newval}), expected) # Out of bounds. base = cls(2000, 2, 29) self.assertRaises(ValueError, base.replace, year=2001) + self.assertRaises(ValueError, copy.replace, base, year=2001) def test_subclass_replace(self): class DateSubclass(self.theclass): @@ -1722,6 +1723,7 @@ class DateSubclass(self.theclass): dt = DateSubclass(2012, 1, 1) self.assertIs(type(dt.replace(year=2013)), DateSubclass) + self.assertIs(type(copy.replace(dt, year=2013)), DateSubclass) def test_subclass_date(self): @@ -2856,26 +2858,27 @@ def test_replace(self): cls = self.theclass args = [1, 2, 3, 4, 5, 6, 7] base = cls(*args) - self.assertEqual(base, base.replace()) - - i = 0 - for name, newval in (("year", 2), - ("month", 3), - ("day", 4), - ("hour", 5), - ("minute", 6), - ("second", 7), - ("microsecond", 8)): + self.assertEqual(base.replace(), base) + self.assertEqual(copy.replace(base), base) + + changes = (("year", 2), + ("month", 3), + ("day", 4), + ("hour", 5), + ("minute", 6), + ("second", 7), + ("microsecond", 8)) + for i, (name, newval) in enumerate(changes): newargs = args[:] newargs[i] = newval expected = cls(*newargs) - got = base.replace(**{name: newval}) - self.assertEqual(expected, got) - i += 1 + self.assertEqual(base.replace(**{name: newval}), expected) + self.assertEqual(copy.replace(base, **{name: newval}), expected) # Out of bounds. base = cls(2000, 2, 29) self.assertRaises(ValueError, base.replace, year=2001) + self.assertRaises(ValueError, copy.replace, base, year=2001) @support.run_with_tz('EDT4') def test_astimezone(self): @@ -3671,19 +3674,19 @@ def test_replace(self): cls = self.theclass args = [1, 2, 3, 4] base = cls(*args) - self.assertEqual(base, base.replace()) - - i = 0 - for name, newval in (("hour", 5), - ("minute", 6), - ("second", 7), - ("microsecond", 8)): + self.assertEqual(base.replace(), base) + self.assertEqual(copy.replace(base), base) + + changes = (("hour", 5), + ("minute", 6), + ("second", 7), + ("microsecond", 8)) + for i, (name, newval) in enumerate(changes): newargs = args[:] newargs[i] = newval expected = cls(*newargs) - got = base.replace(**{name: newval}) - self.assertEqual(expected, got) - i += 1 + self.assertEqual(base.replace(**{name: newval}), expected) + self.assertEqual(copy.replace(base, **{name: newval}), expected) # Out of bounds. base = cls(1) @@ -3691,6 +3694,10 @@ def test_replace(self): self.assertRaises(ValueError, base.replace, minute=-1) self.assertRaises(ValueError, base.replace, second=100) self.assertRaises(ValueError, base.replace, microsecond=1000000) + self.assertRaises(ValueError, copy.replace, base, hour=24) + self.assertRaises(ValueError, copy.replace, base, minute=-1) + self.assertRaises(ValueError, copy.replace, base, second=100) + self.assertRaises(ValueError, copy.replace, base, microsecond=1000000) def test_subclass_replace(self): class TimeSubclass(self.theclass): @@ -3698,6 +3705,7 @@ class TimeSubclass(self.theclass): ctime = TimeSubclass(12, 30) self.assertIs(type(ctime.replace(hour=10)), TimeSubclass) + self.assertIs(type(copy.replace(ctime, hour=10)), TimeSubclass) def test_subclass_time(self): @@ -4085,31 +4093,37 @@ def test_replace(self): zm200 = FixedOffset(timedelta(minutes=-200), "-200") args = [1, 2, 3, 4, z100] base = cls(*args) - self.assertEqual(base, base.replace()) - - i = 0 - for name, newval in (("hour", 5), - ("minute", 6), - ("second", 7), - ("microsecond", 8), - ("tzinfo", zm200)): + self.assertEqual(base.replace(), base) + self.assertEqual(copy.replace(base), base) + + changes = (("hour", 5), + ("minute", 6), + ("second", 7), + ("microsecond", 8), + ("tzinfo", zm200)) + for i, (name, newval) in enumerate(changes): newargs = args[:] newargs[i] = newval expected = cls(*newargs) - got = base.replace(**{name: newval}) - self.assertEqual(expected, got) - i += 1 + self.assertEqual(base.replace(**{name: newval}), expected) + self.assertEqual(copy.replace(base, **{name: newval}), expected) # Ensure we can get rid of a tzinfo. self.assertEqual(base.tzname(), "+100") base2 = base.replace(tzinfo=None) self.assertIsNone(base2.tzinfo) self.assertIsNone(base2.tzname()) + base22 = copy.replace(base, tzinfo=None) + self.assertIsNone(base22.tzinfo) + self.assertIsNone(base22.tzname()) # Ensure we can add one. base3 = base2.replace(tzinfo=z100) self.assertEqual(base, base3) self.assertIs(base.tzinfo, base3.tzinfo) + base32 = copy.replace(base22, tzinfo=z100) + self.assertEqual(base, base32) + self.assertIs(base.tzinfo, base32.tzinfo) # Out of bounds. base = cls(1) @@ -4117,6 +4131,10 @@ def test_replace(self): self.assertRaises(ValueError, base.replace, minute=-1) self.assertRaises(ValueError, base.replace, second=100) self.assertRaises(ValueError, base.replace, microsecond=1000000) + self.assertRaises(ValueError, copy.replace, base, hour=24) + self.assertRaises(ValueError, copy.replace, base, minute=-1) + self.assertRaises(ValueError, copy.replace, base, second=100) + self.assertRaises(ValueError, copy.replace, base, microsecond=1000000) def test_mixed_compare(self): t1 = self.theclass(1, 2, 3) @@ -4885,38 +4903,45 @@ def test_replace(self): zm200 = FixedOffset(timedelta(minutes=-200), "-200") args = [1, 2, 3, 4, 5, 6, 7, z100] base = cls(*args) - self.assertEqual(base, base.replace()) - - i = 0 - for name, newval in (("year", 2), - ("month", 3), - ("day", 4), - ("hour", 5), - ("minute", 6), - ("second", 7), - ("microsecond", 8), - ("tzinfo", zm200)): + self.assertEqual(base.replace(), base) + self.assertEqual(copy.replace(base), base) + + changes = (("year", 2), + ("month", 3), + ("day", 4), + ("hour", 5), + ("minute", 6), + ("second", 7), + ("microsecond", 8), + ("tzinfo", zm200)) + for i, (name, newval) in enumerate(changes): newargs = args[:] newargs[i] = newval expected = cls(*newargs) - got = base.replace(**{name: newval}) - self.assertEqual(expected, got) - i += 1 + self.assertEqual(base.replace(**{name: newval}), expected) + self.assertEqual(copy.replace(base, **{name: newval}), expected) # Ensure we can get rid of a tzinfo. self.assertEqual(base.tzname(), "+100") base2 = base.replace(tzinfo=None) self.assertIsNone(base2.tzinfo) self.assertIsNone(base2.tzname()) + base22 = copy.replace(base, tzinfo=None) + self.assertIsNone(base22.tzinfo) + self.assertIsNone(base22.tzname()) # Ensure we can add one. base3 = base2.replace(tzinfo=z100) self.assertEqual(base, base3) self.assertIs(base.tzinfo, base3.tzinfo) + base32 = copy.replace(base22, tzinfo=z100) + self.assertEqual(base, base32) + self.assertIs(base.tzinfo, base32.tzinfo) # Out of bounds. base = cls(2000, 2, 29) self.assertRaises(ValueError, base.replace, year=2001) + self.assertRaises(ValueError, copy.replace, base, year=2001) def test_more_astimezone(self): # The inherited test_astimezone covered some trivial and error cases. diff --git a/Lib/test/doctest_lineno.py b/Lib/test/doctest_lineno.py index 729a68aceaa990..677c569cf710eb 100644 --- a/Lib/test/doctest_lineno.py +++ b/Lib/test/doctest_lineno.py @@ -49,5 +49,21 @@ def method_with_doctest(self): 'method_with_doctest' """ + @classmethod + def classmethod_with_doctest(cls): + """ + This has a doctest! + >>> MethodWrapper.classmethod_with_doctest.__name__ + 'classmethod_with_doctest' + """ + + @property + def property_with_doctest(self): + """ + This has a doctest! + >>> MethodWrapper.property_with_doctest.__name__ + 'property_with_doctest' + """ + # https://github.com/python/cpython/issues/99433 str_wrapper = object().__str__ diff --git a/Lib/test/imp_dummy.py b/Lib/test/imp_dummy.py deleted file mode 100644 index 2a4deb49547cf4..00000000000000 --- a/Lib/test/imp_dummy.py +++ /dev/null @@ -1,3 +0,0 @@ -# Fodder for test of issue24748 in test_imp - -dummy_name = True diff --git a/Lib/test/libregrtest/__init__.py b/Lib/test/libregrtest/__init__.py index 5e8dba5dbde71a..e69de29bb2d1d6 100644 --- a/Lib/test/libregrtest/__init__.py +++ b/Lib/test/libregrtest/__init__.py @@ -1,2 +0,0 @@ -from test.libregrtest.cmdline import _parse_args, RESOURCE_NAMES, ALL_RESOURCES -from test.libregrtest.main import main diff --git a/Lib/test/libregrtest/cmdline.py b/Lib/test/libregrtest/cmdline.py index ebe57920d9185c..0053bce4292f64 100644 --- a/Lib/test/libregrtest/cmdline.py +++ b/Lib/test/libregrtest/cmdline.py @@ -1,8 +1,9 @@ import argparse -import os +import os.path import shlex import sys -from test.support import os_helper +from test.support import os_helper, Py_DEBUG +from .utils import ALL_RESOURCES, RESOURCE_NAMES, TestFilter USAGE = """\ @@ -27,8 +28,10 @@ Additional option details: -r randomizes test execution order. You can use --randseed=int to provide an -int seed value for the randomizer; this is useful for reproducing troublesome -test orders. +int seed value for the randomizer. The randseed value will be used +to set seeds for all random usages in tests +(including randomizing the tests order if -r is set). +By default we always set random seed, but do not randomize test order. -s On the first invocation of regrtest using -s, the first test file found or the first test file given on the command line is run, and the name of @@ -107,6 +110,8 @@ cpu - Used for certain CPU-heavy tests. + walltime - Long running but not CPU-bound tests. + subprocess Run all tests for the subprocess module. urlfetch - It is okay to download files required on testing. @@ -128,25 +133,17 @@ """ -ALL_RESOURCES = ('audio', 'curses', 'largefile', 'network', - 'decimal', 'cpu', 'subprocess', 'urlfetch', 'gui') - -# Other resources excluded from --use=all: -# -# - extralagefile (ex: test_zipfile64): really too slow to be enabled -# "by default" -# - tzdata: while needed to validate fully test_datetime, it makes -# test_datetime too slow (15-20 min on some buildbots) and so is disabled by -# default (see bpo-30822). -RESOURCE_NAMES = ALL_RESOURCES + ('extralargefile', 'tzdata') - - class Namespace(argparse.Namespace): def __init__(self, **kwargs) -> None: + self.ci = False self.testdir = None self.verbose = 0 self.quiet = False self.exclude = False + self.cleanup = False + self.wait = False + self.list_cases = False + self.list_tests = False self.single = False self.randomize = False self.fromfile = None @@ -155,8 +152,8 @@ def __init__(self, **kwargs) -> None: self.trace = False self.coverdir = 'coverage' self.runleaks = False - self.huntrleaks = False - self.verbose2 = False + self.huntrleaks: tuple[int, int, str] | None = None + self.rerun = False self.verbose3 = False self.print_slow = False self.random_seed = None @@ -164,10 +161,17 @@ def __init__(self, **kwargs) -> None: self.forever = False self.header = False self.failfast = False - self.match_tests = None - self.ignore_tests = None + self.match_tests: TestFilter = [] self.pgo = False self.pgo_extended = False + self.worker_json = None + self.start = None + self.timeout = None + self.memlimit = None + self.threshold = None + self.fail_rerun = False + self.tempdir = None + self._add_python_opts = True super().__init__(**kwargs) @@ -178,6 +182,20 @@ def error(self, message): super().error(message + "\nPass -h or --help for complete help.") +class FilterAction(argparse.Action): + def __call__(self, parser, namespace, value, option_string=None): + items = getattr(namespace, self.dest) + items.append((value, self.const)) + + +class FromFileFilterAction(argparse.Action): + def __call__(self, parser, namespace, value, option_string=None): + items = getattr(namespace, self.dest) + with open(value, encoding='utf-8') as fp: + for line in fp: + items.append((line.strip(), self.const)) + + def _create_parser(): # Set prog to prevent the uninformative "__main__.py" from displaying in # error messages when using "python -m test ...". @@ -187,6 +205,7 @@ def _create_parser(): epilog=EPILOG, add_help=False, formatter_class=argparse.RawDescriptionHelpFormatter) + parser.set_defaults(match_tests=[]) # Arguments with this clause added to its help are described further in # the epilog's "Additional option details" section. @@ -196,25 +215,35 @@ def _create_parser(): # We add help explicitly to control what argument group it renders under. group.add_argument('-h', '--help', action='help', help='show this help message and exit') - group.add_argument('--timeout', metavar='TIMEOUT', type=float, + group.add_argument('--fast-ci', action='store_true', + help='Fast Continuous Integration (CI) mode used by ' + 'GitHub Actions') + group.add_argument('--slow-ci', action='store_true', + help='Slow Continuous Integration (CI) mode used by ' + 'buildbot workers') + group.add_argument('--timeout', metavar='TIMEOUT', help='dump the traceback and exit if a test takes ' 'more than TIMEOUT seconds; disabled if TIMEOUT ' 'is negative or equals to zero') group.add_argument('--wait', action='store_true', help='wait for user input, e.g., allow a debugger ' 'to be attached') - group.add_argument('--worker-args', metavar='ARGS') group.add_argument('-S', '--start', metavar='START', help='the name of the test at which to start.' + more_details) group.add_argument('-p', '--python', metavar='PYTHON', help='Command to run Python test subprocesses with.') + group.add_argument('--randseed', metavar='SEED', + dest='random_seed', type=int, + help='pass a global random seed') group = parser.add_argument_group('Verbosity') group.add_argument('-v', '--verbose', action='count', help='run tests in verbose mode with output to stdout') - group.add_argument('-w', '--verbose2', action='store_true', + group.add_argument('-w', '--rerun', action='store_true', help='re-run failed tests in verbose mode') + group.add_argument('--verbose2', action='store_true', dest='rerun', + help='deprecated alias to --rerun') group.add_argument('-W', '--verbose3', action='store_true', help='display test output on failure') group.add_argument('-q', '--quiet', action='store_true', @@ -227,10 +256,6 @@ def _create_parser(): group = parser.add_argument_group('Selecting tests') group.add_argument('-r', '--randomize', action='store_true', help='randomize test execution order.' + more_details) - group.add_argument('--randseed', metavar='SEED', - dest='random_seed', type=int, - help='pass a random seed to reproduce a previous ' - 'random run') group.add_argument('-f', '--fromfile', metavar='FILE', help='read names of tests to run from a file.' + more_details) @@ -240,17 +265,19 @@ def _create_parser(): help='single step through a set of tests.' + more_details) group.add_argument('-m', '--match', metavar='PAT', - dest='match_tests', action='append', + dest='match_tests', action=FilterAction, const=True, help='match test cases and methods with glob pattern PAT') group.add_argument('-i', '--ignore', metavar='PAT', - dest='ignore_tests', action='append', + dest='match_tests', action=FilterAction, const=False, help='ignore test cases and methods with glob pattern PAT') group.add_argument('--matchfile', metavar='FILENAME', - dest='match_filename', + dest='match_tests', + action=FromFileFilterAction, const=True, help='similar to --match but get patterns from a ' 'text file, one pattern per line') group.add_argument('--ignorefile', metavar='FILENAME', - dest='ignore_filename', + dest='match_tests', + action=FromFileFilterAction, const=False, help='similar to --matchfile but it receives patterns ' 'from text file to ignore') group.add_argument('-G', '--failfast', action='store_true', @@ -309,6 +336,9 @@ def _create_parser(): group.add_argument('--fail-env-changed', action='store_true', help='if a test file alters the environment, mark ' 'the test as failed') + group.add_argument('--fail-rerun', action='store_true', + help='if a test failed and then passed when re-run, ' + 'mark the tests as failed') group.add_argument('--junit-xml', dest='xmlpath', metavar='FILENAME', help='writes JUnit-style XML results to the specified ' @@ -317,6 +347,9 @@ def _create_parser(): help='override the working directory for the test run') group.add_argument('--cleanup', action='store_true', help='remove old test_python_* directories') + group.add_argument('--dont-add-python-opts', dest='_add_python_opts', + action='store_false', + help="internal option, don't use it") return parser @@ -367,12 +400,64 @@ def _parse_args(args, **kwargs): for arg in ns.args: if arg.startswith('-'): parser.error("unrecognized arguments: %s" % arg) - sys.exit(1) + + if ns.timeout is not None: + # Support "--timeout=" (no value) so Makefile.pre.pre TESTTIMEOUT + # can be used by "make buildbottest" and "make test". + if ns.timeout != "": + try: + ns.timeout = float(ns.timeout) + except ValueError: + parser.error(f"invalid timeout value: {ns.timeout!r}") + else: + ns.timeout = None + + # Continuous Integration (CI): common options for fast/slow CI modes + if ns.slow_ci or ns.fast_ci: + # Similar to options: + # + # -j0 --randomize --fail-env-changed --fail-rerun --rerun + # --slowest --verbose3 + if ns.use_mp is None: + ns.use_mp = 0 + ns.randomize = True + ns.fail_env_changed = True + if ns.python is None: + ns.rerun = True + ns.print_slow = True + ns.verbose3 = True + else: + ns._add_python_opts = False + + # When both --slow-ci and --fast-ci options are present, + # --slow-ci has the priority + if ns.slow_ci: + # Similar to: -u "all" --timeout=1200 + if ns.use is None: + ns.use = [] + ns.use.insert(0, ['all']) + if ns.timeout is None: + ns.timeout = 1200 # 20 minutes + elif ns.fast_ci: + # Similar to: -u "all,-cpu" --timeout=600 + if ns.use is None: + ns.use = [] + ns.use.insert(0, ['all', '-cpu']) + if ns.timeout is None: + ns.timeout = 600 # 10 minutes if ns.single and ns.fromfile: parser.error("-s and -f don't go together!") - if ns.use_mp is not None and ns.trace: - parser.error("-T and -j don't go together!") + if ns.trace: + if ns.use_mp is not None: + if not Py_DEBUG: + parser.error("need --with-pydebug to use -T and -j together") + else: + print( + "Warning: collecting coverage without -j is imprecise. Configure" + " --with-pydebug and run -m test -T -j for best results.", + file=sys.stderr + ) if ns.python is not None: if ns.use_mp is None: parser.error("-p requires -j!") @@ -380,7 +465,7 @@ def _parse_args(args, **kwargs): ns.python = shlex.split(ns.python) if ns.failfast and not (ns.verbose or ns.verbose3): parser.error("-G/--failfast needs either -v or -W") - if ns.pgo and (ns.verbose or ns.verbose2 or ns.verbose3): + if ns.pgo and (ns.verbose or ns.rerun or ns.verbose3): parser.error("--pgo/-v don't go together!") if ns.pgo_extended: ns.pgo = True # pgo_extended implies pgo @@ -394,10 +479,6 @@ def _parse_args(args, **kwargs): if ns.timeout is not None: if ns.timeout <= 0: ns.timeout = None - if ns.use_mp is not None: - if ns.use_mp <= 0: - # Use all cores + extras for tests that like to sleep - ns.use_mp = 2 + (os.cpu_count() or 1) if ns.use: for a in ns.use: for r in a: @@ -420,25 +501,28 @@ def _parse_args(args, **kwargs): ns.randomize = True if ns.verbose: ns.header = True - if ns.huntrleaks and ns.verbose3: + # When -jN option is used, a worker process does not use --verbose3 + # and so -R 3:3 -jN --verbose3 just works as expected: there is no false + # alarm about memory leak. + if ns.huntrleaks and ns.verbose3 and ns.use_mp is None: ns.verbose3 = False + # run_single_test() replaces sys.stdout with io.StringIO if verbose3 + # is true. In this case, huntrleaks sees an write into StringIO as + # a memory leak, whereas it is not (gh-71290). print("WARNING: Disable --verbose3 because it's incompatible with " - "--huntrleaks: see http://bugs.python.org/issue27103", + "--huntrleaks without -jN option", file=sys.stderr) - if ns.match_filename: - if ns.match_tests is None: - ns.match_tests = [] - with open(ns.match_filename) as fp: - for line in fp: - ns.match_tests.append(line.strip()) - if ns.ignore_filename: - if ns.ignore_tests is None: - ns.ignore_tests = [] - with open(ns.ignore_filename) as fp: - for line in fp: - ns.ignore_tests.append(line.strip()) if ns.forever: # --forever implies --failfast ns.failfast = True + if ns.huntrleaks: + warmup, repetitions, _ = ns.huntrleaks + if warmup < 1 or repetitions < 1: + msg = ("Invalid values for the --huntrleaks/-R parameters. The " + "number of warmups and repetitions must be at least 1 " + "each (1:1).") + print(msg, file=sys.stderr, flush=True) + sys.exit(2) + return ns diff --git a/Lib/test/libregrtest/filter.py b/Lib/test/libregrtest/filter.py new file mode 100644 index 00000000000000..817624d79e9263 --- /dev/null +++ b/Lib/test/libregrtest/filter.py @@ -0,0 +1,72 @@ +import itertools +import operator +import re + + +# By default, don't filter tests +_test_matchers = () +_test_patterns = () + + +def match_test(test): + # Function used by support.run_unittest() and regrtest --list-cases + result = False + for matcher, result in reversed(_test_matchers): + if matcher(test.id()): + return result + return not result + + +def _is_full_match_test(pattern): + # If a pattern contains at least one dot, it's considered + # as a full test identifier. + # Example: 'test.test_os.FileTests.test_access'. + # + # ignore patterns which contain fnmatch patterns: '*', '?', '[...]' + # or '[!...]'. For example, ignore 'test_access*'. + return ('.' in pattern) and (not re.search(r'[?*\[\]]', pattern)) + + +def set_match_tests(patterns): + global _test_matchers, _test_patterns + + if not patterns: + _test_matchers = () + _test_patterns = () + else: + itemgetter = operator.itemgetter + patterns = tuple(patterns) + if patterns != _test_patterns: + _test_matchers = [ + (_compile_match_function(map(itemgetter(0), it)), result) + for result, it in itertools.groupby(patterns, itemgetter(1)) + ] + _test_patterns = patterns + + +def _compile_match_function(patterns): + patterns = list(patterns) + + if all(map(_is_full_match_test, patterns)): + # Simple case: all patterns are full test identifier. + # The test.bisect_cmd utility only uses such full test identifiers. + return set(patterns).__contains__ + else: + import fnmatch + regex = '|'.join(map(fnmatch.translate, patterns)) + # The search *is* case sensitive on purpose: + # don't use flags=re.IGNORECASE + regex_match = re.compile(regex).match + + def match_test_regex(test_id, regex_match=regex_match): + if regex_match(test_id): + # The regex matches the whole identifier, for example + # 'test.test_os.FileTests.test_access'. + return True + else: + # Try to match parts of the test identifier. + # For example, split 'test.test_os.FileTests.test_access' + # into: 'test', 'test_os', 'FileTests' and 'test_access'. + return any(map(regex_match, test_id.split("."))) + + return match_test_regex diff --git a/Lib/test/libregrtest/findtests.py b/Lib/test/libregrtest/findtests.py new file mode 100644 index 00000000000000..78343775bc5b99 --- /dev/null +++ b/Lib/test/libregrtest/findtests.py @@ -0,0 +1,106 @@ +import os +import sys +import unittest + +from test import support + +from .filter import match_test, set_match_tests +from .utils import ( + StrPath, TestName, TestTuple, TestList, TestFilter, + abs_module_name, count, printlist) + + +# If these test directories are encountered recurse into them and treat each +# "test_*.py" file or each sub-directory as a separate test module. This can +# increase parallelism. +# +# Beware this can't generally be done for any directory with sub-tests as the +# __init__.py may do things which alter what tests are to be run. +SPLITTESTDIRS: set[TestName] = { + "test_asyncio", + "test_concurrent_futures", + "test_future_stmt", + "test_gdb", + "test_inspect", + "test_multiprocessing_fork", + "test_multiprocessing_forkserver", + "test_multiprocessing_spawn", +} + + +def findtestdir(path: StrPath | None = None) -> StrPath: + return path or os.path.dirname(os.path.dirname(__file__)) or os.curdir + + +def findtests(*, testdir: StrPath | None = None, exclude=(), + split_test_dirs: set[TestName] = SPLITTESTDIRS, + base_mod: str = "") -> TestList: + """Return a list of all applicable test modules.""" + testdir = findtestdir(testdir) + tests = [] + for name in os.listdir(testdir): + mod, ext = os.path.splitext(name) + if (not mod.startswith("test_")) or (mod in exclude): + continue + if base_mod: + fullname = f"{base_mod}.{mod}" + else: + fullname = mod + if fullname in split_test_dirs: + subdir = os.path.join(testdir, mod) + if not base_mod: + fullname = f"test.{mod}" + tests.extend(findtests(testdir=subdir, exclude=exclude, + split_test_dirs=split_test_dirs, + base_mod=fullname)) + elif ext in (".py", ""): + tests.append(fullname) + return sorted(tests) + + +def split_test_packages(tests, *, testdir: StrPath | None = None, exclude=(), + split_test_dirs=SPLITTESTDIRS): + testdir = findtestdir(testdir) + splitted = [] + for name in tests: + if name in split_test_dirs: + subdir = os.path.join(testdir, name) + splitted.extend(findtests(testdir=subdir, exclude=exclude, + split_test_dirs=split_test_dirs, + base_mod=name)) + else: + splitted.append(name) + return splitted + + +def _list_cases(suite): + for test in suite: + if isinstance(test, unittest.loader._FailedTest): + continue + if isinstance(test, unittest.TestSuite): + _list_cases(test) + elif isinstance(test, unittest.TestCase): + if match_test(test): + print(test.id()) + +def list_cases(tests: TestTuple, *, + match_tests: TestFilter | None = None, + test_dir: StrPath | None = None): + support.verbose = False + set_match_tests(match_tests) + + skipped = [] + for test_name in tests: + module_name = abs_module_name(test_name, test_dir) + try: + suite = unittest.defaultTestLoader.loadTestsFromName(module_name) + _list_cases(suite) + except unittest.SkipTest: + skipped.append(test_name) + + if skipped: + sys.stdout.flush() + stderr = sys.stderr + print(file=stderr) + print(count(len(skipped), "test"), "skipped:", file=stderr) + printlist(skipped, file=stderr) diff --git a/Lib/test/libregrtest/logger.py b/Lib/test/libregrtest/logger.py new file mode 100644 index 00000000000000..a125706927393c --- /dev/null +++ b/Lib/test/libregrtest/logger.py @@ -0,0 +1,86 @@ +import os +import time + +from test.support import MS_WINDOWS +from .results import TestResults +from .runtests import RunTests +from .utils import print_warning + +if MS_WINDOWS: + from .win_utils import WindowsLoadTracker + + +class Logger: + def __init__(self, results: TestResults, quiet: bool, pgo: bool): + self.start_time = time.perf_counter() + self.test_count_text = '' + self.test_count_width = 3 + self.win_load_tracker: WindowsLoadTracker | None = None + self._results: TestResults = results + self._quiet: bool = quiet + self._pgo: bool = pgo + + def log(self, line: str = '') -> None: + empty = not line + + # add the system load prefix: "load avg: 1.80 " + load_avg = self.get_load_avg() + if load_avg is not None: + line = f"load avg: {load_avg:.2f} {line}" + + # add the timestamp prefix: "0:01:05 " + log_time = time.perf_counter() - self.start_time + + mins, secs = divmod(int(log_time), 60) + hours, mins = divmod(mins, 60) + formatted_log_time = "%d:%02d:%02d" % (hours, mins, secs) + + line = f"{formatted_log_time} {line}" + if empty: + line = line[:-1] + + print(line, flush=True) + + def get_load_avg(self) -> float | None: + if hasattr(os, 'getloadavg'): + return os.getloadavg()[0] + if self.win_load_tracker is not None: + return self.win_load_tracker.getloadavg() + return None + + def display_progress(self, test_index: int, text: str) -> None: + if self._quiet: + return + results = self._results + + # "[ 51/405/1] test_tcl passed" + line = f"{test_index:{self.test_count_width}}{self.test_count_text}" + fails = len(results.bad) + len(results.env_changed) + if fails and not self._pgo: + line = f"{line}/{fails}" + self.log(f"[{line}] {text}") + + def set_tests(self, runtests: RunTests) -> None: + if runtests.forever: + self.test_count_text = '' + self.test_count_width = 3 + else: + self.test_count_text = '/{}'.format(len(runtests.tests)) + self.test_count_width = len(self.test_count_text) - 1 + + def start_load_tracker(self) -> None: + if not MS_WINDOWS: + return + + try: + self.win_load_tracker = WindowsLoadTracker() + except PermissionError as error: + # Standard accounts may not have access to the performance + # counters. + print_warning(f'Failed to create WindowsLoadTracker: {error}') + + def stop_load_tracker(self) -> None: + if self.win_load_tracker is None: + return + self.win_load_tracker.close() + self.win_load_tracker = None diff --git a/Lib/test/libregrtest/main.py b/Lib/test/libregrtest/main.py index 9001ca33b6166a..7ca1b1cb65ae40 100644 --- a/Lib/test/libregrtest/main.py +++ b/Lib/test/libregrtest/main.py @@ -1,46 +1,31 @@ -import faulthandler -import locale import os -import platform import random import re +import shlex import sys import sysconfig -import tempfile import time -import unittest -from test.libregrtest.cmdline import _parse_args -from test.libregrtest.runtest import ( - findtests, runtest, get_abs_module, is_failed, - STDTESTS, NOTTESTS, PROGRESS_MIN_TIME, - Passed, Failed, EnvChanged, Skipped, ResourceDenied, Interrupted, - ChildError, DidNotRun) -from test.libregrtest.setup import setup_tests -from test.libregrtest.pgo import setup_pgo_tests -from test.libregrtest.utils import (removepy, count, format_duration, - printlist, get_build_info) -from test import support -from test.support import os_helper -from test.support import threading_helper - - -# bpo-38203: Maximum delay in seconds to exit Python (call Py_Finalize()). -# Used to protect against threading._shutdown() hang. -# Must be smaller than buildbot "1200 seconds without output" limit. -EXIT_TIMEOUT = 120.0 - -# gh-90681: When rerunning tests, we might need to rerun the whole -# class or module suite if some its life-cycle hooks fail. -# Test level hooks are not affected. -_TEST_LIFECYCLE_HOOKS = frozenset(( - 'setUpClass', 'tearDownClass', - 'setUpModule', 'tearDownModule', -)) +import trace -EXITCODE_BAD_TEST = 2 -EXITCODE_INTERRUPTED = 130 -EXITCODE_ENV_CHANGED = 3 -EXITCODE_NO_TESTS_RAN = 4 +from test import support +from test.support import os_helper, MS_WINDOWS + +from .cmdline import _parse_args, Namespace +from .findtests import findtests, split_test_packages, list_cases +from .logger import Logger +from .pgo import setup_pgo_tests +from .result import State, TestResult +from .results import TestResults, EXITCODE_INTERRUPTED +from .runtests import RunTests, HuntRefleak +from .setup import setup_process, setup_test_dir +from .single import run_single_test, PROGRESS_MIN_TIME +from .utils import ( + StrPath, StrJSON, TestName, TestList, TestTuple, TestFilter, + strip_py_suffix, count, format_duration, + printlist, get_temp_dir, get_work_dir, exit_timeout, + display_header, cleanup_temp_dir, print_warning, + is_cross_compiled, get_host_runner, + EXIT_TIMEOUT) class Regrtest: @@ -66,263 +51,210 @@ class Regrtest: directly to set the values that would normally be set by flags on the command line. """ - def __init__(self): - # Namespace of command line options - self.ns = None + def __init__(self, ns: Namespace, _add_python_opts: bool = False): + # Log verbosity + self.verbose: int = int(ns.verbose) + self.quiet: bool = ns.quiet + self.pgo: bool = ns.pgo + self.pgo_extended: bool = ns.pgo_extended + + # Test results + self.results: TestResults = TestResults() + self.first_state: str | None = None + + # Logger + self.logger = Logger(self.results, self.quiet, self.pgo) + + # Actions + self.want_header: bool = ns.header + self.want_list_tests: bool = ns.list_tests + self.want_list_cases: bool = ns.list_cases + self.want_wait: bool = ns.wait + self.want_cleanup: bool = ns.cleanup + self.want_rerun: bool = ns.rerun + self.want_run_leaks: bool = ns.runleaks + + self.ci_mode: bool = (ns.fast_ci or ns.slow_ci) + self.want_add_python_opts: bool = (_add_python_opts + and ns._add_python_opts) + + # Select tests + self.match_tests: TestFilter = ns.match_tests + self.exclude: bool = ns.exclude + self.fromfile: StrPath | None = ns.fromfile + self.starting_test: TestName | None = ns.start + self.cmdline_args: TestList = ns.args + + # Workers + if ns.use_mp is None: + num_workers = 0 # run sequentially + elif ns.use_mp <= 0: + num_workers = -1 # use the number of CPUs + else: + num_workers = ns.use_mp + self.num_workers: int = num_workers + self.worker_json: StrJSON | None = ns.worker_json + + # Options to run tests + self.fail_fast: bool = ns.failfast + self.fail_env_changed: bool = ns.fail_env_changed + self.fail_rerun: bool = ns.fail_rerun + self.forever: bool = ns.forever + self.output_on_failure: bool = ns.verbose3 + self.timeout: float | None = ns.timeout + if ns.huntrleaks: + warmups, runs, filename = ns.huntrleaks + filename = os.path.abspath(filename) + self.hunt_refleak: HuntRefleak | None = HuntRefleak(warmups, runs, filename) + else: + self.hunt_refleak = None + self.test_dir: StrPath | None = ns.testdir + self.junit_filename: StrPath | None = ns.xmlpath + self.memory_limit: str | None = ns.memlimit + self.gc_threshold: int | None = ns.threshold + self.use_resources: tuple[str, ...] = tuple(ns.use_resources) + if ns.python: + self.python_cmd: tuple[str, ...] | None = tuple(ns.python) + else: + self.python_cmd = None + self.coverage: bool = ns.trace + self.coverage_dir: StrPath | None = ns.coverdir + self.tmp_dir: StrPath | None = ns.tempdir + + # Randomize + self.randomize: bool = ns.randomize + if ('SOURCE_DATE_EPOCH' in os.environ + # don't use the variable if empty + and os.environ['SOURCE_DATE_EPOCH'] + ): + self.randomize = False + # SOURCE_DATE_EPOCH should be an integer, but use a string to not + # fail if it's not integer. random.seed() accepts a string. + # https://reproducible-builds.org/docs/source-date-epoch/ + self.random_seed: int | str = os.environ['SOURCE_DATE_EPOCH'] + elif ns.random_seed is None: + self.random_seed = random.getrandbits(32) + else: + self.random_seed = ns.random_seed # tests - self.tests = [] - self.selected = [] - - # test results - self.good = [] - self.bad = [] - self.skipped = [] - self.resource_denieds = [] - self.environment_changed = [] - self.run_no_tests = [] - self.need_rerun = [] - self.rerun = [] - self.first_result = None - self.interrupted = False - - # used by --slow - self.test_times = [] - - # used by --coverage, trace.Trace instance - self.tracer = None + self.first_runtests: RunTests | None = None + + # used by --slowest + self.print_slowest: bool = ns.print_slow # used to display the progress bar "[ 3/100]" - self.start_time = time.monotonic() - self.test_count = '' - self.test_count_width = 1 + self.start_time = time.perf_counter() # used by --single - self.next_single_test = None - self.next_single_filename = None - - # used by --junit-xml - self.testsuite_xml = None - - # misc - self.win_load_tracker = None - self.tmp_dir = None - self.worker_test_name = None - - def get_executed(self): - return (set(self.good) | set(self.bad) | set(self.skipped) - | set(self.resource_denieds) | set(self.environment_changed) - | set(self.run_no_tests)) - - def accumulate_result(self, result, rerun=False): - test_name = result.name - - if not isinstance(result, (ChildError, Interrupted)) and not rerun: - self.test_times.append((result.duration_sec, test_name)) - - if isinstance(result, Passed): - self.good.append(test_name) - elif isinstance(result, ResourceDenied): - self.skipped.append(test_name) - self.resource_denieds.append(test_name) - elif isinstance(result, Skipped): - self.skipped.append(test_name) - elif isinstance(result, EnvChanged): - self.environment_changed.append(test_name) - elif isinstance(result, Failed): - if not rerun: - self.bad.append(test_name) - self.need_rerun.append(result) - elif isinstance(result, DidNotRun): - self.run_no_tests.append(test_name) - elif isinstance(result, Interrupted): - self.interrupted = True - else: - raise ValueError("invalid test result: %r" % result) - - if rerun and not isinstance(result, (Failed, Interrupted)): - self.bad.remove(test_name) - - xml_data = result.xml_data - if xml_data: - import xml.etree.ElementTree as ET - for e in xml_data: - try: - self.testsuite_xml.append(ET.fromstring(e)) - except ET.ParseError: - print(xml_data, file=sys.__stderr__) - raise + self.single_test_run: bool = ns.single + self.next_single_test: TestName | None = None + self.next_single_filename: StrPath | None = None def log(self, line=''): - empty = not line - - # add the system load prefix: "load avg: 1.80 " - load_avg = self.getloadavg() - if load_avg is not None: - line = f"load avg: {load_avg:.2f} {line}" - - # add the timestamp prefix: "0:01:05 " - test_time = time.monotonic() - self.start_time - - mins, secs = divmod(int(test_time), 60) - hours, mins = divmod(mins, 60) - test_time = "%d:%02d:%02d" % (hours, mins, secs) - - line = f"{test_time} {line}" - if empty: - line = line[:-1] - - print(line, flush=True) - - def display_progress(self, test_index, text): - if self.ns.quiet: - return - - # "[ 51/405/1] test_tcl passed" - line = f"{test_index:{self.test_count_width}}{self.test_count}" - fails = len(self.bad) + len(self.environment_changed) - if fails and not self.ns.pgo: - line = f"{line}/{fails}" - self.log(f"[{line}] {text}") - - def parse_args(self, kwargs): - ns = _parse_args(sys.argv[1:], **kwargs) - - if ns.xmlpath: - support.junit_xml_list = self.testsuite_xml = [] + self.logger.log(line) - worker_args = ns.worker_args - if worker_args is not None: - from test.libregrtest.runtest_mp import parse_worker_args - ns, test_name = parse_worker_args(ns.worker_args) - ns.worker_args = worker_args - self.worker_test_name = test_name - - # Strip .py extensions. - removepy(ns.args) - - if ns.huntrleaks: - warmup, repetitions, _ = ns.huntrleaks - if warmup < 1 or repetitions < 1: - msg = ("Invalid values for the --huntrleaks/-R parameters. The " - "number of warmups and repetitions must be at least 1 " - "each (1:1).") - print(msg, file=sys.stderr, flush=True) - sys.exit(2) - - if ns.tempdir: - ns.tempdir = os.path.expanduser(ns.tempdir) - - self.ns = ns - - def find_tests(self, tests): - self.tests = tests - - if self.ns.single: + def find_tests(self, tests: TestList | None = None) -> tuple[TestTuple, TestList | None]: + if self.single_test_run: self.next_single_filename = os.path.join(self.tmp_dir, 'pynexttest') try: with open(self.next_single_filename, 'r') as fp: next_test = fp.read().strip() - self.tests = [next_test] + tests = [next_test] except OSError: pass - if self.ns.fromfile: - self.tests = [] + if self.fromfile: + tests = [] # regex to match 'test_builtin' in line: # '0:00:00 [ 4/400] test_builtin -- test_dict took 1 sec' regex = re.compile(r'\btest_[a-zA-Z0-9_]+\b') - with open(os.path.join(os_helper.SAVEDCWD, self.ns.fromfile)) as fp: + with open(os.path.join(os_helper.SAVEDCWD, self.fromfile)) as fp: for line in fp: line = line.split('#', 1)[0] line = line.strip() match = regex.search(line) if match is not None: - self.tests.append(match.group()) + tests.append(match.group()) - removepy(self.tests) + strip_py_suffix(tests) - if self.ns.pgo: + if self.pgo: # add default PGO tests if no tests are specified - setup_pgo_tests(self.ns) - - stdtests = STDTESTS[:] - nottests = NOTTESTS.copy() - if self.ns.exclude: - for arg in self.ns.args: - if arg in stdtests: - stdtests.remove(arg) - nottests.add(arg) - self.ns.args = [] - - # if testdir is set, then we are not running the python tests suite, so - # don't add default tests to be executed or skipped (pass empty values) - if self.ns.testdir: - alltests = findtests(self.ns.testdir, list(), set()) - else: - alltests = findtests(self.ns.testdir, stdtests, nottests) + setup_pgo_tests(self.cmdline_args, self.pgo_extended) + + exclude_tests = set() + if self.exclude: + for arg in self.cmdline_args: + exclude_tests.add(arg) + self.cmdline_args = [] + + alltests = findtests(testdir=self.test_dir, + exclude=exclude_tests) - if not self.ns.fromfile: - self.selected = self.tests or self.ns.args or alltests + if not self.fromfile: + selected = tests or self.cmdline_args + if selected: + selected = split_test_packages(selected) + else: + selected = alltests else: - self.selected = self.tests - if self.ns.single: - self.selected = self.selected[:1] + selected = tests + + if self.single_test_run: + selected = selected[:1] try: - pos = alltests.index(self.selected[0]) + pos = alltests.index(selected[0]) self.next_single_test = alltests[pos + 1] except IndexError: pass # Remove all the selected tests that precede start if it's set. - if self.ns.start: + if self.starting_test: try: - del self.selected[:self.selected.index(self.ns.start)] + del selected[:selected.index(self.starting_test)] except ValueError: - print("Couldn't find starting test (%s), using all tests" - % self.ns.start, file=sys.stderr) + print(f"Cannot find starting test: {self.starting_test}") + sys.exit(1) - if self.ns.randomize: - if self.ns.random_seed is None: - self.ns.random_seed = random.randrange(10000000) - random.seed(self.ns.random_seed) - random.shuffle(self.selected) + random.seed(self.random_seed) + if self.randomize: + random.shuffle(selected) - def list_tests(self): - for name in self.selected: - print(name) + return (tuple(selected), tests) - def _list_cases(self, suite): - for test in suite: - if isinstance(test, unittest.loader._FailedTest): - continue - if isinstance(test, unittest.TestSuite): - self._list_cases(test) - elif isinstance(test, unittest.TestCase): - if support.match_test(test): - print(test.id()) - - def list_cases(self): - support.verbose = False - support.set_match_tests(self.ns.match_tests, self.ns.ignore_tests) - - for test_name in self.selected: - abstest = get_abs_module(self.ns, test_name) - try: - suite = unittest.defaultTestLoader.loadTestsFromName(abstest) - self._list_cases(suite) - except unittest.SkipTest: - self.skipped.append(test_name) - - if self.skipped: - print(file=sys.stderr) - print(count(len(self.skipped), "test"), "skipped:", file=sys.stderr) - printlist(self.skipped, file=sys.stderr) - - def rerun_failed_tests(self): - self.log() + @staticmethod + def list_tests(tests: TestTuple): + for name in tests: + print(name) - if self.ns.python: + def _rerun_failed_tests(self, runtests: RunTests): + # Configure the runner to re-run tests + if self.num_workers == 0: + # Always run tests in fresh processes to have more deterministic + # initial state. Don't re-run tests in parallel but limit to a + # single worker process to have side effects (on the system load + # and timings) between tests. + self.num_workers = 1 + + tests, match_tests_dict = self.results.prepare_rerun() + + # Re-run failed tests + self.log(f"Re-running {len(tests)} failed tests in verbose mode in subprocesses") + runtests = runtests.copy( + tests=tests, + rerun=True, + verbose=True, + forever=False, + fail_fast=False, + match_tests_dict=match_tests_dict, + output_on_failure=False) + self.logger.set_tests(runtests) + self._run_tests_mp(runtests, self.num_workers) + return runtests + + def rerun_failed_tests(self, runtests: RunTests): + if self.python_cmd: # Temp patch for https://github.com/python/cpython/issues/94052 self.log( "Re-running failed tests is not supported with --python " @@ -330,297 +262,117 @@ def rerun_failed_tests(self): ) return - self.ns.verbose = True - self.ns.failfast = False - self.ns.verbose3 = False - - self.first_result = self.get_tests_result() - - self.log("Re-running failed tests in verbose mode") - rerun_list = list(self.need_rerun) - self.need_rerun.clear() - for result in rerun_list: - test_name = result.name - self.rerun.append(test_name) - - errors = result.errors or [] - failures = result.failures or [] - error_names = [ - self.normalize_test_name(test_full_name, is_error=True) - for (test_full_name, *_) in errors] - failure_names = [ - self.normalize_test_name(test_full_name) - for (test_full_name, *_) in failures] - self.ns.verbose = True - orig_match_tests = self.ns.match_tests - if errors or failures: - if self.ns.match_tests is None: - self.ns.match_tests = [] - self.ns.match_tests.extend(error_names) - self.ns.match_tests.extend(failure_names) - matching = "matching: " + ", ".join(self.ns.match_tests) - self.log(f"Re-running {test_name} in verbose mode ({matching})") - else: - self.log(f"Re-running {test_name} in verbose mode") - result = runtest(self.ns, test_name) - self.ns.match_tests = orig_match_tests + self.first_state = self.get_state() + + print() + rerun_runtests = self._rerun_failed_tests(runtests) - self.accumulate_result(result, rerun=True) + if self.results.bad: + print(count(len(self.results.bad), 'test'), "failed again:") + printlist(self.results.bad) - if isinstance(result, Interrupted): - break + self.display_result(rerun_runtests) - if self.bad: - print(count(len(self.bad), 'test'), "failed again:") - printlist(self.bad) - - self.display_result() - - def normalize_test_name(self, test_full_name, *, is_error=False): - short_name = test_full_name.split(" ")[0] - if is_error and short_name in _TEST_LIFECYCLE_HOOKS: - # This means that we have a failure in a life-cycle hook, - # we need to rerun the whole module or class suite. - # Basically the error looks like this: - # ERROR: setUpClass (test.test_reg_ex.RegTest) - # or - # ERROR: setUpModule (test.test_reg_ex) - # So, we need to parse the class / module name. - lpar = test_full_name.index('(') - rpar = test_full_name.index(')') - return test_full_name[lpar + 1: rpar].split('.')[-1] - return short_name - - def display_result(self): + def display_result(self, runtests): # If running the test suite for PGO then no one cares about results. - if self.ns.pgo: + if runtests.pgo: return + state = self.get_state() print() - print("== Tests result: %s ==" % self.get_tests_result()) - - if self.interrupted: - print("Test suite interrupted by signal SIGINT.") - - omitted = set(self.selected) - self.get_executed() - if omitted: - print() - print(count(len(omitted), "test"), "omitted:") - printlist(omitted) - - if self.good and not self.ns.quiet: - print() - if (not self.bad - and not self.skipped - and not self.interrupted - and len(self.good) > 1): - print("All", end=' ') - print(count(len(self.good), "test"), "OK.") - - if self.ns.print_slow: - self.test_times.sort(reverse=True) - print() - print("10 slowest tests:") - for test_time, test in self.test_times[:10]: - print("- %s: %s" % (test, format_duration(test_time))) - - if self.bad: - print() - print(count(len(self.bad), "test"), "failed:") - printlist(self.bad) - - if self.environment_changed: - print() - print("{} altered the execution environment:".format( - count(len(self.environment_changed), "test"))) - printlist(self.environment_changed) - - if self.skipped and not self.ns.quiet: - print() - print(count(len(self.skipped), "test"), "skipped:") - printlist(self.skipped) - - if self.rerun: - print() - print("%s:" % count(len(self.rerun), "re-run test")) - printlist(self.rerun) - - if self.run_no_tests: - print() - print(count(len(self.run_no_tests), "test"), "run no tests:") - printlist(self.run_no_tests) - - def run_tests_sequential(self): - if self.ns.trace: - import trace - self.tracer = trace.Trace(trace=False, count=True) - - save_modules = sys.modules.keys() - - msg = "Run tests sequentially" - if self.ns.timeout: - msg += " (timeout: %s)" % format_duration(self.ns.timeout) + print(f"== Tests result: {state} ==") + + self.results.display_result(runtests.tests, + self.quiet, self.print_slowest) + + def run_test( + self, test_name: TestName, runtests: RunTests, tracer: trace.Trace | None + ) -> TestResult: + if tracer is not None: + # If we're tracing code coverage, then we don't exit with status + # if on a false return value from main. + cmd = ('result = run_single_test(test_name, runtests)') + namespace = dict(locals()) + tracer.runctx(cmd, globals=globals(), locals=namespace) + result = namespace['result'] + # Mypy doesn't know about this attribute yet, + # but it will do soon: https://github.com/python/typeshed/pull/11091 + result.covered_lines = list(tracer.counts) # type: ignore[attr-defined] + else: + result = run_single_test(test_name, runtests) + + self.results.accumulate_result(result, runtests) + + return result + + def run_tests_sequentially(self, runtests) -> None: + if self.coverage: + tracer = trace.Trace(trace=False, count=True) + else: + tracer = None + + save_modules = set(sys.modules) + + jobs = runtests.get_jobs() + if jobs is not None: + tests = count(jobs, 'test') + else: + tests = 'tests' + msg = f"Run {tests} sequentially" + if runtests.timeout: + msg += " (timeout: %s)" % format_duration(runtests.timeout) self.log(msg) previous_test = None - for test_index, test_name in enumerate(self.tests, 1): - start_time = time.monotonic() + tests_iter = runtests.iter_tests() + for test_index, test_name in enumerate(tests_iter, 1): + start_time = time.perf_counter() text = test_name if previous_test: text = '%s -- %s' % (text, previous_test) - self.display_progress(test_index, text) - - if self.tracer: - # If we're tracing code coverage, then we don't exit with status - # if on a false return value from main. - cmd = ('result = runtest(self.ns, test_name); ' - 'self.accumulate_result(result)') - ns = dict(locals()) - self.tracer.runctx(cmd, globals=globals(), locals=ns) - result = ns['result'] - else: - result = runtest(self.ns, test_name) - self.accumulate_result(result) + self.logger.display_progress(test_index, text) + + result = self.run_test(test_name, runtests, tracer) + + # Unload the newly imported test modules (best effort finalization) + new_modules = [module for module in sys.modules + if module not in save_modules and + module.startswith(("test.", "test_"))] + for module in new_modules: + sys.modules.pop(module, None) + # Remove the attribute of the parent module. + parent, _, name = module.rpartition('.') + try: + delattr(sys.modules[parent], name) + except (KeyError, AttributeError): + pass - if isinstance(result, Interrupted): + if result.must_stop(self.fail_fast, self.fail_env_changed): break previous_test = str(result) - test_time = time.monotonic() - start_time + test_time = time.perf_counter() - start_time if test_time >= PROGRESS_MIN_TIME: previous_test = "%s in %s" % (previous_test, format_duration(test_time)) - elif isinstance(result, Passed): + elif result.state == State.PASSED: # be quiet: say nothing if the test passed shortly previous_test = None - # Unload the newly imported modules (best effort finalization) - for module in sys.modules.keys(): - if module not in save_modules and module.startswith("test."): - support.unload(module) - - if self.ns.failfast and is_failed(result, self.ns): - break - if previous_test: print(previous_test) - def _test_forever(self, tests): - while True: - for test_name in tests: - yield test_name - if self.bad: - return - if self.ns.fail_env_changed and self.environment_changed: - return - - def display_header(self): - # Print basic platform information - print("==", platform.python_implementation(), *sys.version.split()) - print("==", platform.platform(aliased=True), - "%s-endian" % sys.byteorder) - print("== Python build:", ' '.join(get_build_info())) - print("== cwd:", os.getcwd()) - cpu_count = os.cpu_count() - if cpu_count: - print("== CPU count:", cpu_count) - print("== encodings: locale=%s, FS=%s" - % (locale.getencoding(), sys.getfilesystemencoding())) - asan = support.check_sanitizer(address=True) - msan = support.check_sanitizer(memory=True) - ubsan = support.check_sanitizer(ub=True) - # This makes it easier to remember what to set in your local - # environment when trying to reproduce a sanitizer failure. - if asan or msan or ubsan: - names = [n for n in (asan and "address", - msan and "memory", - ubsan and "undefined behavior") - if n] - print(f"== sanitizers: {', '.join(names)}") - a_opts = os.environ.get("ASAN_OPTIONS") - if asan and a_opts is not None: - print(f"== ASAN_OPTIONS={a_opts}") - m_opts = os.environ.get("ASAN_OPTIONS") - if msan and m_opts is not None: - print(f"== MSAN_OPTIONS={m_opts}") - ub_opts = os.environ.get("UBSAN_OPTIONS") - if ubsan and ub_opts is not None: - print(f"== UBSAN_OPTIONS={ub_opts}") - - def no_tests_run(self): - return not any((self.good, self.bad, self.skipped, self.interrupted, - self.environment_changed)) - - def get_tests_result(self): - result = [] - if self.bad: - result.append("FAILURE") - elif self.ns.fail_env_changed and self.environment_changed: - result.append("ENV CHANGED") - elif self.no_tests_run(): - result.append("NO TESTS RAN") - - if self.interrupted: - result.append("INTERRUPTED") - - if not result: - result.append("SUCCESS") - - result = ', '.join(result) - if self.first_result: - result = '%s then %s' % (self.first_result, result) - return result + def get_state(self): + state = self.results.get_state(self.fail_env_changed) + if self.first_state: + state = f'{self.first_state} then {state}' + return state - def run_tests(self): - # For a partial run, we do not need to clutter the output. - if (self.ns.header - or not(self.ns.pgo or self.ns.quiet or self.ns.single - or self.tests or self.ns.args)): - self.display_header() - - if self.ns.huntrleaks: - warmup, repetitions, _ = self.ns.huntrleaks - if warmup < 3: - msg = ("WARNING: Running tests with --huntrleaks/-R and less than " - "3 warmup repetitions can give false positives!") - print(msg, file=sys.stdout, flush=True) - - if self.ns.randomize: - print("Using random seed", self.ns.random_seed) - - if self.ns.forever: - self.tests = self._test_forever(list(self.selected)) - self.test_count = '' - self.test_count_width = 3 - else: - self.tests = iter(self.selected) - self.test_count = '/{}'.format(len(self.selected)) - self.test_count_width = len(self.test_count) - 1 - - if self.ns.use_mp: - from test.libregrtest.runtest_mp import run_tests_multiprocess - # If we're on windows and this is the parent runner (not a worker), - # track the load average. - if sys.platform == 'win32' and self.worker_test_name is None: - from test.libregrtest.win_utils import WindowsLoadTracker - - try: - self.win_load_tracker = WindowsLoadTracker() - except PermissionError as error: - # Standard accounts may not have access to the performance - # counters. - print(f'Failed to create WindowsLoadTracker: {error}') - - try: - run_tests_multiprocess(self) - finally: - if self.win_load_tracker is not None: - self.win_load_tracker.close() - self.win_load_tracker = None - else: - self.run_tests_sequential() + def _run_tests_mp(self, runtests: RunTests, num_workers: int) -> None: + from .run_workers import RunWorkers + RunWorkers(num_workers, runtests, self.logger, self.results).run() - def finalize(self): + def finalize_tests(self, coverage: trace.CoverageResults | None) -> None: if self.next_single_filename: if self.next_single_test: with open(self.next_single_filename, 'w') as fp: @@ -628,195 +380,301 @@ def finalize(self): else: os.unlink(self.next_single_filename) - if self.tracer: - r = self.tracer.results() - r.write_results(show_missing=True, summary=True, - coverdir=self.ns.coverdir) - - print() - duration = time.monotonic() - self.start_time - print("Total duration: %s" % format_duration(duration)) - print("Tests result: %s" % self.get_tests_result()) + if coverage is not None: + # uses a new-in-Python 3.13 keyword argument that mypy doesn't know about yet: + coverage.write_results(show_missing=True, summary=True, # type: ignore[call-arg] + coverdir=self.coverage_dir, + ignore_missing_files=True) - if self.ns.runleaks: + if self.want_run_leaks: os.system("leaks %d" % os.getpid()) - def save_xml_result(self): - if not self.ns.xmlpath and not self.testsuite_xml: - return + if self.junit_filename: + self.results.write_junit(self.junit_filename) - import xml.etree.ElementTree as ET - root = ET.Element("testsuites") + def display_summary(self): + duration = time.perf_counter() - self.logger.start_time + filtered = bool(self.match_tests) - # Manually count the totals for the overall summary - totals = {'tests': 0, 'errors': 0, 'failures': 0} - for suite in self.testsuite_xml: - root.append(suite) - for k in totals: - try: - totals[k] += int(suite.get(k, 0)) - except ValueError: - pass + # Total duration + print() + print("Total duration: %s" % format_duration(duration)) - for k, v in totals.items(): - root.set(k, str(v)) - - xmlpath = os.path.join(os_helper.SAVEDCWD, self.ns.xmlpath) - with open(xmlpath, 'wb') as f: - for s in ET.tostringlist(root): - f.write(s) - - def fix_umask(self): - if support.is_emscripten: - # Emscripten has default umask 0o777, which breaks some tests. - # see https://github.com/emscripten-core/emscripten/issues/17269 - old_mask = os.umask(0) - if old_mask == 0o777: - os.umask(0o027) - else: - os.umask(old_mask) - - def set_temp_dir(self): - if self.ns.tempdir: - self.tmp_dir = self.ns.tempdir - - if not self.tmp_dir: - # When tests are run from the Python build directory, it is best practice - # to keep the test files in a subfolder. This eases the cleanup of leftover - # files using the "make distclean" command. - if sysconfig.is_python_build(): - self.tmp_dir = sysconfig.get_config_var('abs_builddir') - if self.tmp_dir is None: - # bpo-30284: On Windows, only srcdir is available. Using - # abs_builddir mostly matters on UNIX when building Python - # out of the source tree, especially when the source tree - # is read only. - self.tmp_dir = sysconfig.get_config_var('srcdir') - self.tmp_dir = os.path.join(self.tmp_dir, 'build') - else: - self.tmp_dir = tempfile.gettempdir() + self.results.display_summary(self.first_runtests, filtered) + + # Result + state = self.get_state() + print(f"Result: {state}") + + def create_run_tests(self, tests: TestTuple): + return RunTests( + tests, + fail_fast=self.fail_fast, + fail_env_changed=self.fail_env_changed, + match_tests=self.match_tests, + match_tests_dict=None, + rerun=False, + forever=self.forever, + pgo=self.pgo, + pgo_extended=self.pgo_extended, + output_on_failure=self.output_on_failure, + timeout=self.timeout, + verbose=self.verbose, + quiet=self.quiet, + hunt_refleak=self.hunt_refleak, + test_dir=self.test_dir, + use_junit=(self.junit_filename is not None), + coverage=self.coverage, + memory_limit=self.memory_limit, + gc_threshold=self.gc_threshold, + use_resources=self.use_resources, + python_cmd=self.python_cmd, + randomize=self.randomize, + random_seed=self.random_seed, + ) + + def _run_tests(self, selected: TestTuple, tests: TestList | None) -> int: + if self.hunt_refleak and self.hunt_refleak.warmups < 3: + msg = ("WARNING: Running tests with --huntrleaks/-R and " + "less than 3 warmup repetitions can give false positives!") + print(msg, file=sys.stdout, flush=True) + + if self.num_workers < 0: + # Use all CPUs + 2 extra worker processes for tests + # that like to sleep + # + # os.process.cpu_count() is new in Python 3.13; + # mypy doesn't know about it yet + self.num_workers = (os.process_cpu_count() or 1) + 2 # type: ignore[attr-defined] - self.tmp_dir = os.path.abspath(self.tmp_dir) + # For a partial run, we do not need to clutter the output. + if (self.want_header + or not(self.pgo or self.quiet or self.single_test_run + or tests or self.cmdline_args)): + display_header(self.use_resources, self.python_cmd) - def create_temp_dir(self): - os.makedirs(self.tmp_dir, exist_ok=True) + print("Using random seed:", self.random_seed) - # Define a writable temp dir that will be used as cwd while running - # the tests. The name of the dir includes the pid to allow parallel - # testing (see the -j option). - # Emscripten and WASI have stubbed getpid(), Emscripten has only - # milisecond clock resolution. Use randint() instead. - if sys.platform in {"emscripten", "wasi"}: - nounce = random.randint(0, 1_000_000) - else: - nounce = os.getpid() - if self.worker_test_name is not None: - test_cwd = 'test_python_worker_{}'.format(nounce) + runtests = self.create_run_tests(selected) + self.first_runtests = runtests + self.logger.set_tests(runtests) + + setup_process() + + if self.hunt_refleak and not self.num_workers: + # gh-109739: WindowsLoadTracker thread interfers with refleak check + use_load_tracker = False else: - test_cwd = 'test_python_{}'.format(nounce) - test_cwd += os_helper.FS_NONASCII - test_cwd = os.path.join(self.tmp_dir, test_cwd) - return test_cwd - - def cleanup(self): - import glob - - path = os.path.join(glob.escape(self.tmp_dir), 'test_python_*') - print("Cleanup %s directory" % self.tmp_dir) - for name in glob.glob(path): - if os.path.isdir(name): - print("Remove directory: %s" % name) - os_helper.rmtree(name) + # WindowsLoadTracker is only needed on Windows + use_load_tracker = MS_WINDOWS + + if use_load_tracker: + self.logger.start_load_tracker() + try: + if self.num_workers: + self._run_tests_mp(runtests, self.num_workers) else: - print("Remove file: %s" % name) - os_helper.unlink(name) + self.run_tests_sequentially(runtests) - def main(self, tests=None, **kwargs): - self.parse_args(kwargs) + coverage = self.results.get_coverage_results() + self.display_result(runtests) - self.set_temp_dir() + if self.want_rerun and self.results.need_rerun(): + self.rerun_failed_tests(runtests) + finally: + if use_load_tracker: + self.logger.stop_load_tracker() - self.fix_umask() + self.display_summary() + self.finalize_tests(coverage) - if self.ns.cleanup: - self.cleanup() - sys.exit(0) + return self.results.get_exitcode(self.fail_env_changed, + self.fail_rerun) - test_cwd = self.create_temp_dir() + def run_tests(self, selected: TestTuple, tests: TestList | None) -> int: + os.makedirs(self.tmp_dir, exist_ok=True) + work_dir = get_work_dir(self.tmp_dir) - try: - # Run the tests in a context manager that temporarily changes the CWD - # to a temporary and writable directory. If it's not possible to - # create or change the CWD, the original CWD will be used. + # Put a timeout on Python exit + with exit_timeout(): + # Run the tests in a context manager that temporarily changes the + # CWD to a temporary and writable directory. If it's not possible + # to create or change the CWD, the original CWD will be used. # The original CWD is available from os_helper.SAVEDCWD. - with os_helper.temp_cwd(test_cwd, quiet=True): - # When using multiprocessing, worker processes will use test_cwd - # as their parent temporary directory. So when the main process - # exit, it removes also subdirectories of worker processes. - self.ns.tempdir = test_cwd - - self._main(tests, kwargs) - except SystemExit as exc: - # bpo-38203: Python can hang at exit in Py_Finalize(), especially - # on threading._shutdown() call: put a timeout - if threading_helper.can_start_thread: - faulthandler.dump_traceback_later(EXIT_TIMEOUT, exit=True) - - sys.exit(exc.code) + with os_helper.temp_cwd(work_dir, quiet=True): + # When using multiprocessing, worker processes will use + # work_dir as their parent temporary directory. So when the + # main process exit, it removes also subdirectories of worker + # processes. + return self._run_tests(selected, tests) + + def _add_cross_compile_opts(self, regrtest_opts): + # WASM/WASI buildbot builders pass multiple PYTHON environment + # variables such as PYTHONPATH and _PYTHON_HOSTRUNNER. + keep_environ = bool(self.python_cmd) + environ = None + + # Are we using cross-compilation? + cross_compile = is_cross_compiled() + + # Get HOSTRUNNER + hostrunner = get_host_runner() + + if cross_compile: + # emulate -E, but keep PYTHONPATH + cross compile env vars, + # so test executable can load correct sysconfigdata file. + keep = { + '_PYTHON_PROJECT_BASE', + '_PYTHON_HOST_PLATFORM', + '_PYTHON_SYSCONFIGDATA_NAME', + 'PYTHONPATH' + } + old_environ = os.environ + new_environ = { + name: value for name, value in os.environ.items() + if not name.startswith(('PYTHON', '_PYTHON')) or name in keep + } + # Only set environ if at least one variable was removed + if new_environ != old_environ: + environ = new_environ + keep_environ = True + + if cross_compile and hostrunner: + if self.num_workers == 0: + # For now use only two cores for cross-compiled builds; + # hostrunner can be expensive. + regrtest_opts.extend(['-j', '2']) + + # If HOSTRUNNER is set and -p/--python option is not given, then + # use hostrunner to execute python binary for tests. + if not self.python_cmd: + buildpython = sysconfig.get_config_var("BUILDPYTHON") + python_cmd = f"{hostrunner} {buildpython}" + regrtest_opts.extend(["--python", python_cmd]) + keep_environ = True + + return (environ, keep_environ) + + def _add_ci_python_opts(self, python_opts, keep_environ): + # --fast-ci and --slow-ci add options to Python: + # "-u -W default -bb -E" + + # Unbuffered stdout and stderr + if not sys.stdout.write_through: + python_opts.append('-u') + + # Add warnings filter 'default' + if 'default' not in sys.warnoptions: + python_opts.extend(('-W', 'default')) + + # Error on bytes/str comparison + if sys.flags.bytes_warning < 2: + python_opts.append('-bb') + + if not keep_environ: + # Ignore PYTHON* environment variables + if not sys.flags.ignore_environment: + python_opts.append('-E') + + def _execute_python(self, cmd, environ): + # Make sure that messages before execv() are logged + sys.stdout.flush() + sys.stderr.flush() + + cmd_text = shlex.join(cmd) + try: + print(f"+ {cmd_text}", flush=True) - def getloadavg(self): - if self.win_load_tracker is not None: - return self.win_load_tracker.getloadavg() + if hasattr(os, 'execv') and not MS_WINDOWS: + os.execv(cmd[0], cmd) + # On success, execv() do no return. + # On error, it raises an OSError. + else: + import subprocess + with subprocess.Popen(cmd, env=environ) as proc: + try: + proc.wait() + except KeyboardInterrupt: + # There is no need to call proc.terminate(): on CTRL+C, + # SIGTERM is also sent to the child process. + try: + proc.wait(timeout=EXIT_TIMEOUT) + except subprocess.TimeoutExpired: + proc.kill() + proc.wait() + sys.exit(EXITCODE_INTERRUPTED) + + sys.exit(proc.returncode) + except Exception as exc: + print_warning(f"Failed to change Python options: {exc!r}\n" + f"Command: {cmd_text}") + # continue executing main() + + def _add_python_opts(self): + python_opts = [] + regrtest_opts = [] + + environ, keep_environ = self._add_cross_compile_opts(regrtest_opts) + if self.ci_mode: + self._add_ci_python_opts(python_opts, keep_environ) + + if (not python_opts) and (not regrtest_opts) and (environ is None): + # Nothing changed: nothing to do + return - if hasattr(os, 'getloadavg'): - return os.getloadavg()[0] + # Create new command line + cmd = list(sys.orig_argv) + if python_opts: + cmd[1:1] = python_opts + if regrtest_opts: + cmd.extend(regrtest_opts) + cmd.append("--dont-add-python-opts") - return None + self._execute_python(cmd, environ) - def _main(self, tests, kwargs): - if self.worker_test_name is not None: - from test.libregrtest.runtest_mp import run_tests_worker - run_tests_worker(self.ns, self.worker_test_name) + def _init(self): + # Set sys.stdout encoder error handler to backslashreplace, + # similar to sys.stderr error handler, to avoid UnicodeEncodeError + # when printing a traceback or any other non-encodable character. + sys.stdout.reconfigure(errors="backslashreplace") - if self.ns.wait: - input("Press any key to continue...") + if self.junit_filename and not os.path.isabs(self.junit_filename): + self.junit_filename = os.path.abspath(self.junit_filename) - support.PGO = self.ns.pgo - support.PGO_EXTENDED = self.ns.pgo_extended + strip_py_suffix(self.cmdline_args) - setup_tests(self.ns) + self.tmp_dir = get_temp_dir(self.tmp_dir) - self.find_tests(tests) + def main(self, tests: TestList | None = None): + if self.want_add_python_opts: + self._add_python_opts() - if self.ns.list_tests: - self.list_tests() - sys.exit(0) + self._init() - if self.ns.list_cases: - self.list_cases() + if self.want_cleanup: + cleanup_temp_dir(self.tmp_dir) sys.exit(0) - self.run_tests() - self.display_result() - - if self.ns.verbose2 and self.bad: - self.rerun_failed_tests() + if self.want_wait: + input("Press any key to continue...") - self.finalize() + setup_test_dir(self.test_dir) + selected, tests = self.find_tests(tests) - self.save_xml_result() + exitcode = 0 + if self.want_list_tests: + self.list_tests(selected) + elif self.want_list_cases: + list_cases(selected, + match_tests=self.match_tests, + test_dir=self.test_dir) + else: + exitcode = self.run_tests(selected, tests) - if self.bad: - sys.exit(EXITCODE_BAD_TEST) - if self.interrupted: - sys.exit(EXITCODE_INTERRUPTED) - if self.ns.fail_env_changed and self.environment_changed: - sys.exit(EXITCODE_ENV_CHANGED) - if self.no_tests_run(): - sys.exit(EXITCODE_NO_TESTS_RAN) - sys.exit(0) + sys.exit(exitcode) -def main(tests=None, **kwargs): +def main(tests=None, _add_python_opts=False, **kwargs): """Run the Python suite.""" - Regrtest().main(tests=tests, **kwargs) + ns = _parse_args(sys.argv[1:], **kwargs) + Regrtest(ns, _add_python_opts=_add_python_opts).main(tests=tests) diff --git a/Lib/test/libregrtest/mypy.ini b/Lib/test/libregrtest/mypy.ini new file mode 100644 index 00000000000000..22c7c7a9acef14 --- /dev/null +++ b/Lib/test/libregrtest/mypy.ini @@ -0,0 +1,33 @@ +# Config file for running mypy on libregrtest. +# Run mypy by invoking `mypy --config-file Lib/test/libregrtest/mypy.ini` +# on the command-line from the repo root + +[mypy] +files = Lib/test/libregrtest +explicit_package_bases = True +python_version = 3.12 +platform = linux +pretty = True + +# Enable most stricter settings +enable_error_code = ignore-without-code +strict = True + +# Various stricter settings that we can't yet enable +# Try to enable these in the following order: +disallow_any_generics = False +disallow_incomplete_defs = False +disallow_untyped_calls = False +disallow_untyped_defs = False +check_untyped_defs = False +warn_return_any = False + +disable_error_code = return + +# Enable --strict-optional for these ASAP: +[mypy-Lib.test.libregrtest.main.*,Lib.test.libregrtest.run_workers.*] +strict_optional = False + +# Various internal modules that typeshed deliberately doesn't have stubs for: +[mypy-_abc.*,_opcode.*,_overlapped.*,_testcapi.*,_testinternalcapi.*,test.*] +ignore_missing_imports = True diff --git a/Lib/test/libregrtest/pgo.py b/Lib/test/libregrtest/pgo.py index 42ce5fba7a97c3..e3a6927be5db1d 100644 --- a/Lib/test/libregrtest/pgo.py +++ b/Lib/test/libregrtest/pgo.py @@ -42,15 +42,15 @@ 'test_set', 'test_sqlite3', 'test_statistics', + 'test_str', 'test_struct', 'test_tabnanny', 'test_time', - 'test_unicode', 'test_xml_etree', 'test_xml_etree_c', ] -def setup_pgo_tests(ns): - if not ns.args and not ns.pgo_extended: +def setup_pgo_tests(cmdline_args, pgo_extended: bool): + if not cmdline_args and not pgo_extended: # run default set of tests for PGO training - ns.args = PGO_TESTS[:] + cmdline_args[:] = PGO_TESTS[:] diff --git a/Lib/test/libregrtest/refleak.py b/Lib/test/libregrtest/refleak.py index cd11d385591f80..5836a8421cb42d 100644 --- a/Lib/test/libregrtest/refleak.py +++ b/Lib/test/libregrtest/refleak.py @@ -1,10 +1,13 @@ -import os import sys import warnings from inspect import isabstract +from typing import Any + from test import support from test.support import os_helper -from test.libregrtest.utils import clear_caches + +from .runtests import HuntRefleak +from .utils import clear_caches try: from _abc import _get_dump @@ -19,7 +22,9 @@ def _get_dump(cls): cls._abc_negative_cache, cls._abc_negative_cache_version) -def dash_R(ns, test_name, test_func): +def runtest_refleak(test_name, test_func, + hunt_refleak: HuntRefleak, + quiet: bool): """Run a test multiple times, looking for reference leaks. Returns: @@ -41,12 +46,14 @@ def dash_R(ns, test_name, test_func): fs = warnings.filters[:] ps = copyreg.dispatch_table.copy() pic = sys.path_importer_cache.copy() + zdc: dict[str, Any] | None try: import zipimport except ImportError: zdc = None # Run unmodified on platforms without zipimport support else: - zdc = zipimport._zip_directory_cache.copy() + # private attribute that mypy doesn't know about: + zdc = zipimport._zip_directory_cache.copy() # type: ignore[attr-defined] abcs = {} for abc in [getattr(collections.abc, a) for a in collections.abc.__all__]: if not isabstract(abc): @@ -62,9 +69,10 @@ def dash_R(ns, test_name, test_func): def get_pooled_int(value): return int_pool.setdefault(value, value) - nwarmup, ntracked, fname = ns.huntrleaks - fname = os.path.join(os_helper.SAVEDCWD, fname) - repcount = nwarmup + ntracked + warmups = hunt_refleak.warmups + runs = hunt_refleak.runs + filename = hunt_refleak.filename + repcount = warmups + runs # Pre-allocate to ensure that the loop doesn't allocate anything new rep_range = list(range(repcount)) @@ -78,16 +86,17 @@ def get_pooled_int(value): # initialize variables to make pyflakes quiet rc_before = alloc_before = fd_before = interned_before = 0 - if not ns.quiet: + if not quiet: print("beginning", repcount, "repetitions", file=sys.stderr) print(("1234567890"*(repcount//10 + 1))[:repcount], file=sys.stderr, flush=True) + results = None dash_R_cleanup(fs, ps, pic, zdc, abcs) support.gc_collect() for i in rep_range: - test_func() + results = test_func() dash_R_cleanup(fs, ps, pic, zdc, abcs) support.gc_collect() @@ -101,7 +110,7 @@ def get_pooled_int(value): rc_after = gettotalrefcount() - interned_after * 2 fd_after = fd_count() - if not ns.quiet: + if not quiet: print('.', end='', file=sys.stderr, flush=True) rc_deltas[i] = get_pooled_int(rc_after - rc_before) @@ -113,7 +122,7 @@ def get_pooled_int(value): fd_before = fd_after interned_before = interned_after - if not ns.quiet: + if not quiet: print(file=sys.stderr) # These checkers return False on success, True on failure @@ -142,16 +151,16 @@ def check_fd_deltas(deltas): (fd_deltas, 'file descriptors', check_fd_deltas) ]: # ignore warmup runs - deltas = deltas[nwarmup:] + deltas = deltas[warmups:] if checker(deltas): msg = '%s leaked %s %s, sum=%s' % ( test_name, deltas, item_name, sum(deltas)) print(msg, file=sys.stderr, flush=True) - with open(fname, "a", encoding="utf-8") as refrep: + with open(filename, "a", encoding="utf-8") as refrep: print(msg, file=refrep) refrep.flush() failed = True - return failed + return (failed, results) def dash_R_cleanup(fs, ps, pic, zdc, abcs): diff --git a/Lib/test/libregrtest/result.py b/Lib/test/libregrtest/result.py new file mode 100644 index 00000000000000..74eae40440435d --- /dev/null +++ b/Lib/test/libregrtest/result.py @@ -0,0 +1,224 @@ +import dataclasses +import json +from typing import Any + +from .utils import ( + StrJSON, TestName, FilterTuple, + format_duration, normalize_test_name, print_warning) + + +@dataclasses.dataclass(slots=True) +class TestStats: + tests_run: int = 0 + failures: int = 0 + skipped: int = 0 + + @staticmethod + def from_unittest(result): + return TestStats(result.testsRun, + len(result.failures), + len(result.skipped)) + + @staticmethod + def from_doctest(results): + return TestStats(results.attempted, + results.failed, + results.skipped) + + def accumulate(self, stats): + self.tests_run += stats.tests_run + self.failures += stats.failures + self.skipped += stats.skipped + + +# Avoid enum.Enum to reduce the number of imports when tests are run +class State: + PASSED = "PASSED" + FAILED = "FAILED" + SKIPPED = "SKIPPED" + UNCAUGHT_EXC = "UNCAUGHT_EXC" + REFLEAK = "REFLEAK" + ENV_CHANGED = "ENV_CHANGED" + RESOURCE_DENIED = "RESOURCE_DENIED" + INTERRUPTED = "INTERRUPTED" + WORKER_FAILED = "WORKER_FAILED" # non-zero worker process exit code + WORKER_BUG = "WORKER_BUG" # exception when running a worker + DID_NOT_RUN = "DID_NOT_RUN" + TIMEOUT = "TIMEOUT" + + @staticmethod + def is_failed(state): + return state in { + State.FAILED, + State.UNCAUGHT_EXC, + State.REFLEAK, + State.WORKER_FAILED, + State.WORKER_BUG, + State.TIMEOUT} + + @staticmethod + def has_meaningful_duration(state): + # Consider that the duration is meaningless for these cases. + # For example, if a whole test file is skipped, its duration + # is unlikely to be the duration of executing its tests, + # but just the duration to execute code which skips the test. + return state not in { + State.SKIPPED, + State.RESOURCE_DENIED, + State.INTERRUPTED, + State.WORKER_FAILED, + State.WORKER_BUG, + State.DID_NOT_RUN} + + @staticmethod + def must_stop(state): + return state in { + State.INTERRUPTED, + State.WORKER_BUG, + } + + +FileName = str +LineNo = int +Location = tuple[FileName, LineNo] + + +@dataclasses.dataclass(slots=True) +class TestResult: + test_name: TestName + state: str | None = None + # Test duration in seconds + duration: float | None = None + xml_data: list[str] | None = None + stats: TestStats | None = None + + # errors and failures copied from support.TestFailedWithDetails + errors: list[tuple[str, str]] | None = None + failures: list[tuple[str, str]] | None = None + + # partial coverage in a worker run; not used by sequential in-process runs + covered_lines: list[Location] | None = None + + def is_failed(self, fail_env_changed: bool) -> bool: + if self.state == State.ENV_CHANGED: + return fail_env_changed + return State.is_failed(self.state) + + def _format_failed(self): + if self.errors and self.failures: + le = len(self.errors) + lf = len(self.failures) + error_s = "error" + ("s" if le > 1 else "") + failure_s = "failure" + ("s" if lf > 1 else "") + return f"{self.test_name} failed ({le} {error_s}, {lf} {failure_s})" + + if self.errors: + le = len(self.errors) + error_s = "error" + ("s" if le > 1 else "") + return f"{self.test_name} failed ({le} {error_s})" + + if self.failures: + lf = len(self.failures) + failure_s = "failure" + ("s" if lf > 1 else "") + return f"{self.test_name} failed ({lf} {failure_s})" + + return f"{self.test_name} failed" + + def __str__(self) -> str: + match self.state: + case State.PASSED: + return f"{self.test_name} passed" + case State.FAILED: + return self._format_failed() + case State.SKIPPED: + return f"{self.test_name} skipped" + case State.UNCAUGHT_EXC: + return f"{self.test_name} failed (uncaught exception)" + case State.REFLEAK: + return f"{self.test_name} failed (reference leak)" + case State.ENV_CHANGED: + return f"{self.test_name} failed (env changed)" + case State.RESOURCE_DENIED: + return f"{self.test_name} skipped (resource denied)" + case State.INTERRUPTED: + return f"{self.test_name} interrupted" + case State.WORKER_FAILED: + return f"{self.test_name} worker non-zero exit code" + case State.WORKER_BUG: + return f"{self.test_name} worker bug" + case State.DID_NOT_RUN: + return f"{self.test_name} ran no tests" + case State.TIMEOUT: + return f"{self.test_name} timed out ({format_duration(self.duration)})" + case _: + raise ValueError("unknown result state: {state!r}") + + def has_meaningful_duration(self): + return State.has_meaningful_duration(self.state) + + def set_env_changed(self): + if self.state is None or self.state == State.PASSED: + self.state = State.ENV_CHANGED + + def must_stop(self, fail_fast: bool, fail_env_changed: bool) -> bool: + if State.must_stop(self.state): + return True + if fail_fast and self.is_failed(fail_env_changed): + return True + return False + + def get_rerun_match_tests(self) -> FilterTuple | None: + match_tests = [] + + errors = self.errors or [] + failures = self.failures or [] + for error_list, is_error in ( + (errors, True), + (failures, False), + ): + for full_name, *_ in error_list: + match_name = normalize_test_name(full_name, is_error=is_error) + if match_name is None: + # 'setUpModule (test.test_sys)': don't filter tests + return None + if not match_name: + error_type = "ERROR" if is_error else "FAIL" + print_warning(f"rerun failed to parse {error_type} test name: " + f"{full_name!r}: don't filter tests") + return None + match_tests.append(match_name) + + if not match_tests: + return None + return tuple(match_tests) + + def write_json_into(self, file) -> None: + json.dump(self, file, cls=_EncodeTestResult) + + @staticmethod + def from_json(worker_json: StrJSON) -> 'TestResult': + return json.loads(worker_json, object_hook=_decode_test_result) + + +class _EncodeTestResult(json.JSONEncoder): + def default(self, o: Any) -> dict[str, Any]: + if isinstance(o, TestResult): + result = dataclasses.asdict(o) + result["__test_result__"] = o.__class__.__name__ + return result + else: + return super().default(o) + + +def _decode_test_result(data: dict[str, Any]) -> TestResult | dict[str, Any]: + if "__test_result__" in data: + data.pop('__test_result__') + if data['stats'] is not None: + data['stats'] = TestStats(**data['stats']) + if data['covered_lines'] is not None: + data['covered_lines'] = [ + tuple(loc) for loc in data['covered_lines'] + ] + return TestResult(**data) + else: + return data diff --git a/Lib/test/libregrtest/results.py b/Lib/test/libregrtest/results.py new file mode 100644 index 00000000000000..a41ea8aba028c3 --- /dev/null +++ b/Lib/test/libregrtest/results.py @@ -0,0 +1,271 @@ +import sys +import trace + +from .runtests import RunTests +from .result import State, TestResult, TestStats, Location +from .utils import ( + StrPath, TestName, TestTuple, TestList, FilterDict, + printlist, count, format_duration) + + +# Python uses exit code 1 when an exception is not caught +# argparse.ArgumentParser.error() uses exit code 2 +EXITCODE_BAD_TEST = 2 +EXITCODE_ENV_CHANGED = 3 +EXITCODE_NO_TESTS_RAN = 4 +EXITCODE_RERUN_FAIL = 5 +EXITCODE_INTERRUPTED = 130 # 128 + signal.SIGINT=2 + + +class TestResults: + def __init__(self): + self.bad: TestList = [] + self.good: TestList = [] + self.rerun_bad: TestList = [] + self.skipped: TestList = [] + self.resource_denied: TestList = [] + self.env_changed: TestList = [] + self.run_no_tests: TestList = [] + self.rerun: TestList = [] + self.rerun_results: list[TestResult] = [] + + self.interrupted: bool = False + self.worker_bug: bool = False + self.test_times: list[tuple[float, TestName]] = [] + self.stats = TestStats() + # used by --junit-xml + self.testsuite_xml: list = [] + # used by -T with -j + self.covered_lines: set[Location] = set() + + def is_all_good(self): + return (not self.bad + and not self.skipped + and not self.interrupted + and not self.worker_bug) + + def get_executed(self): + return (set(self.good) | set(self.bad) | set(self.skipped) + | set(self.resource_denied) | set(self.env_changed) + | set(self.run_no_tests)) + + def no_tests_run(self): + return not any((self.good, self.bad, self.skipped, self.interrupted, + self.env_changed)) + + def get_state(self, fail_env_changed): + state = [] + if self.bad: + state.append("FAILURE") + elif fail_env_changed and self.env_changed: + state.append("ENV CHANGED") + elif self.no_tests_run(): + state.append("NO TESTS RAN") + + if self.interrupted: + state.append("INTERRUPTED") + if self.worker_bug: + state.append("WORKER BUG") + if not state: + state.append("SUCCESS") + + return ', '.join(state) + + def get_exitcode(self, fail_env_changed, fail_rerun): + exitcode = 0 + if self.bad: + exitcode = EXITCODE_BAD_TEST + elif self.interrupted: + exitcode = EXITCODE_INTERRUPTED + elif fail_env_changed and self.env_changed: + exitcode = EXITCODE_ENV_CHANGED + elif self.no_tests_run(): + exitcode = EXITCODE_NO_TESTS_RAN + elif fail_rerun and self.rerun: + exitcode = EXITCODE_RERUN_FAIL + elif self.worker_bug: + exitcode = EXITCODE_BAD_TEST + return exitcode + + def accumulate_result(self, result: TestResult, runtests: RunTests): + test_name = result.test_name + rerun = runtests.rerun + fail_env_changed = runtests.fail_env_changed + + match result.state: + case State.PASSED: + self.good.append(test_name) + case State.ENV_CHANGED: + self.env_changed.append(test_name) + self.rerun_results.append(result) + case State.SKIPPED: + self.skipped.append(test_name) + case State.RESOURCE_DENIED: + self.resource_denied.append(test_name) + case State.INTERRUPTED: + self.interrupted = True + case State.DID_NOT_RUN: + self.run_no_tests.append(test_name) + case _: + if result.is_failed(fail_env_changed): + self.bad.append(test_name) + self.rerun_results.append(result) + else: + raise ValueError(f"invalid test state: {result.state!r}") + + if result.state == State.WORKER_BUG: + self.worker_bug = True + + if result.has_meaningful_duration() and not rerun: + if result.duration is None: + raise ValueError("result.duration is None") + self.test_times.append((result.duration, test_name)) + if result.stats is not None: + self.stats.accumulate(result.stats) + if rerun: + self.rerun.append(test_name) + if result.covered_lines: + # we don't care about trace counts so we don't have to sum them up + self.covered_lines.update(result.covered_lines) + xml_data = result.xml_data + if xml_data: + self.add_junit(xml_data) + + def get_coverage_results(self) -> trace.CoverageResults: + counts = {loc: 1 for loc in self.covered_lines} + return trace.CoverageResults(counts=counts) + + def need_rerun(self): + return bool(self.rerun_results) + + def prepare_rerun(self) -> tuple[TestTuple, FilterDict]: + tests: TestList = [] + match_tests_dict = {} + for result in self.rerun_results: + tests.append(result.test_name) + + match_tests = result.get_rerun_match_tests() + # ignore empty match list + if match_tests: + match_tests_dict[result.test_name] = match_tests + + # Clear previously failed tests + self.rerun_bad.extend(self.bad) + self.bad.clear() + self.env_changed.clear() + self.rerun_results.clear() + + return (tuple(tests), match_tests_dict) + + def add_junit(self, xml_data: list[str]): + import xml.etree.ElementTree as ET + for e in xml_data: + try: + self.testsuite_xml.append(ET.fromstring(e)) + except ET.ParseError: + print(xml_data, file=sys.__stderr__) + raise + + def write_junit(self, filename: StrPath): + if not self.testsuite_xml: + # Don't create empty XML file + return + + import xml.etree.ElementTree as ET + root = ET.Element("testsuites") + + # Manually count the totals for the overall summary + totals = {'tests': 0, 'errors': 0, 'failures': 0} + for suite in self.testsuite_xml: + root.append(suite) + for k in totals: + try: + totals[k] += int(suite.get(k, 0)) + except ValueError: + pass + + for k, v in totals.items(): + root.set(k, str(v)) + + with open(filename, 'wb') as f: + for s in ET.tostringlist(root): + f.write(s) + + def display_result(self, tests: TestTuple, quiet: bool, print_slowest: bool): + if print_slowest: + self.test_times.sort(reverse=True) + print() + print("10 slowest tests:") + for test_time, test in self.test_times[:10]: + print("- %s: %s" % (test, format_duration(test_time))) + + all_tests = [] + omitted = set(tests) - self.get_executed() + + # less important + all_tests.append((omitted, "test", "{} omitted:")) + if not quiet: + all_tests.append((self.skipped, "test", "{} skipped:")) + all_tests.append((self.resource_denied, "test", "{} skipped (resource denied):")) + all_tests.append((self.run_no_tests, "test", "{} run no tests:")) + + # more important + all_tests.append((self.env_changed, "test", "{} altered the execution environment (env changed):")) + all_tests.append((self.rerun, "re-run test", "{}:")) + all_tests.append((self.bad, "test", "{} failed:")) + + for tests_list, count_text, title_format in all_tests: + if tests_list: + print() + count_text = count(len(tests_list), count_text) + print(title_format.format(count_text)) + printlist(tests_list) + + if self.good and not quiet: + print() + text = count(len(self.good), "test") + text = f"{text} OK." + if (self.is_all_good() and len(self.good) > 1): + text = f"All {text}" + print(text) + + if self.interrupted: + print() + print("Test suite interrupted by signal SIGINT.") + + def display_summary(self, first_runtests: RunTests, filtered: bool): + # Total tests + stats = self.stats + text = f'run={stats.tests_run:,}' + if filtered: + text = f"{text} (filtered)" + report = [text] + if stats.failures: + report.append(f'failures={stats.failures:,}') + if stats.skipped: + report.append(f'skipped={stats.skipped:,}') + print(f"Total tests: {' '.join(report)}") + + # Total test files + all_tests = [self.good, self.bad, self.rerun, + self.skipped, + self.env_changed, self.run_no_tests] + run = sum(map(len, all_tests)) + text = f'run={run}' + if not first_runtests.forever: + ntest = len(first_runtests.tests) + text = f"{text}/{ntest}" + if filtered: + text = f"{text} (filtered)" + report = [text] + for name, tests in ( + ('failed', self.bad), + ('env_changed', self.env_changed), + ('skipped', self.skipped), + ('resource_denied', self.resource_denied), + ('rerun', self.rerun), + ('run_no_tests', self.run_no_tests), + ): + if tests: + report.append(f'{name}={len(tests)}') + print(f"Total test files: {' '.join(report)}") diff --git a/Lib/test/libregrtest/run_workers.py b/Lib/test/libregrtest/run_workers.py new file mode 100644 index 00000000000000..18a0342f0611cf --- /dev/null +++ b/Lib/test/libregrtest/run_workers.py @@ -0,0 +1,608 @@ +import contextlib +import dataclasses +import faulthandler +import os.path +import queue +import signal +import subprocess +import sys +import tempfile +import threading +import time +import traceback +from typing import Any, Literal, TextIO + +from test import support +from test.support import os_helper, MS_WINDOWS + +from .logger import Logger +from .result import TestResult, State +from .results import TestResults +from .runtests import RunTests, WorkerRunTests, JsonFile, JsonFileType +from .single import PROGRESS_MIN_TIME +from .utils import ( + StrPath, TestName, + format_duration, print_warning, count, plural, get_signal_name) +from .worker import create_worker_process, USE_PROCESS_GROUP + +if MS_WINDOWS: + import locale + import msvcrt + + + +# Display the running tests if nothing happened last N seconds +PROGRESS_UPDATE = 30.0 # seconds +assert PROGRESS_UPDATE >= PROGRESS_MIN_TIME + +# Kill the main process after 5 minutes. It is supposed to write an update +# every PROGRESS_UPDATE seconds. Tolerate 5 minutes for Python slowest +# buildbot workers. +MAIN_PROCESS_TIMEOUT = 5 * 60.0 +assert MAIN_PROCESS_TIMEOUT >= PROGRESS_UPDATE + +# Time to wait until a worker completes: should be immediate +WAIT_COMPLETED_TIMEOUT = 30.0 # seconds + +# Time to wait a killed process (in seconds) +WAIT_KILLED_TIMEOUT = 60.0 + + +# We do not use a generator so multiple threads can call next(). +class MultiprocessIterator: + + """A thread-safe iterator over tests for multiprocess mode.""" + + def __init__(self, tests_iter): + self.lock = threading.Lock() + self.tests_iter = tests_iter + + def __iter__(self): + return self + + def __next__(self): + with self.lock: + if self.tests_iter is None: + raise StopIteration + return next(self.tests_iter) + + def stop(self): + with self.lock: + self.tests_iter = None + + +@dataclasses.dataclass(slots=True, frozen=True) +class MultiprocessResult: + result: TestResult + # bpo-45410: stderr is written into stdout to keep messages order + worker_stdout: str | None = None + err_msg: str | None = None + + +ExcStr = str +QueueOutput = tuple[Literal[False], MultiprocessResult] | tuple[Literal[True], ExcStr] + + +class ExitThread(Exception): + pass + + +class WorkerError(Exception): + def __init__(self, + test_name: TestName, + err_msg: str | None, + stdout: str | None, + state: str): + result = TestResult(test_name, state=state) + self.mp_result = MultiprocessResult(result, stdout, err_msg) + super().__init__() + + +class WorkerThread(threading.Thread): + def __init__(self, worker_id: int, runner: "RunWorkers") -> None: + super().__init__() + self.worker_id = worker_id + self.runtests = runner.runtests + self.pending = runner.pending + self.output = runner.output + self.timeout = runner.worker_timeout + self.log = runner.log + self.test_name: TestName | None = None + self.start_time: float | None = None + self._popen: subprocess.Popen[str] | None = None + self._killed = False + self._stopped = False + + def __repr__(self) -> str: + info = [f'WorkerThread #{self.worker_id}'] + if self.is_alive(): + info.append("running") + else: + info.append('stopped') + test = self.test_name + if test: + info.append(f'test={test}') + popen = self._popen + if popen is not None: + dt = time.monotonic() - self.start_time + info.extend((f'pid={self._popen.pid}', + f'time={format_duration(dt)}')) + return '<%s>' % ' '.join(info) + + def _kill(self) -> None: + popen = self._popen + if popen is None: + return + + if self._killed: + return + self._killed = True + + if USE_PROCESS_GROUP: + what = f"{self} process group" + else: + what = f"{self} process" + + print(f"Kill {what}", file=sys.stderr, flush=True) + try: + if USE_PROCESS_GROUP: + os.killpg(popen.pid, signal.SIGKILL) + else: + popen.kill() + except ProcessLookupError: + # popen.kill(): the process completed, the WorkerThread thread + # read its exit status, but Popen.send_signal() read the returncode + # just before Popen.wait() set returncode. + pass + except OSError as exc: + print_warning(f"Failed to kill {what}: {exc!r}") + + def stop(self) -> None: + # Method called from a different thread to stop this thread + self._stopped = True + self._kill() + + def _run_process(self, runtests: WorkerRunTests, output_fd: int, + tmp_dir: StrPath | None = None) -> int | None: + popen = create_worker_process(runtests, output_fd, tmp_dir) + self._popen = popen + self._killed = False + + try: + if self._stopped: + # If kill() has been called before self._popen is set, + # self._popen is still running. Call again kill() + # to ensure that the process is killed. + self._kill() + raise ExitThread + + try: + # gh-94026: stdout+stderr are written to tempfile + retcode = popen.wait(timeout=self.timeout) + assert retcode is not None + return retcode + except subprocess.TimeoutExpired: + if self._stopped: + # kill() has been called: communicate() fails on reading + # closed stdout + raise ExitThread + + # On timeout, kill the process + self._kill() + + # None means TIMEOUT for the caller + retcode = None + # bpo-38207: Don't attempt to call communicate() again: on it + # can hang until all child processes using stdout + # pipes completes. + except OSError: + if self._stopped: + # kill() has been called: communicate() fails + # on reading closed stdout + raise ExitThread + raise + except: + self._kill() + raise + finally: + self._wait_completed() + self._popen = None + + def create_stdout(self, stack: contextlib.ExitStack) -> TextIO: + """Create stdout temporay file (file descriptor).""" + + if MS_WINDOWS: + # gh-95027: When stdout is not a TTY, Python uses the ANSI code + # page for the sys.stdout encoding. If the main process runs in a + # terminal, sys.stdout uses WindowsConsoleIO with UTF-8 encoding. + encoding = locale.getencoding() + else: + encoding = sys.stdout.encoding + + # gh-94026: Write stdout+stderr to a tempfile as workaround for + # non-blocking pipes on Emscripten with NodeJS. + # gh-109425: Use "backslashreplace" error handler: log corrupted + # stdout+stderr, instead of failing with a UnicodeDecodeError and not + # logging stdout+stderr at all. + stdout_file = tempfile.TemporaryFile('w+', + encoding=encoding, + errors='backslashreplace') + stack.enter_context(stdout_file) + return stdout_file + + def create_json_file(self, stack: contextlib.ExitStack) -> tuple[JsonFile, TextIO | None]: + """Create JSON file.""" + + json_file_use_stdout = self.runtests.json_file_use_stdout() + if json_file_use_stdout: + json_file = JsonFile(None, JsonFileType.STDOUT) + json_tmpfile = None + else: + json_tmpfile = tempfile.TemporaryFile('w+', encoding='utf8') + stack.enter_context(json_tmpfile) + + json_fd = json_tmpfile.fileno() + if MS_WINDOWS: + # The msvcrt module is only available on Windows; + # we run mypy with `--platform=linux` in CI + json_handle: int = msvcrt.get_osfhandle(json_fd) # type: ignore[attr-defined] + json_file = JsonFile(json_handle, + JsonFileType.WINDOWS_HANDLE) + else: + json_file = JsonFile(json_fd, JsonFileType.UNIX_FD) + return (json_file, json_tmpfile) + + def create_worker_runtests(self, test_name: TestName, json_file: JsonFile) -> WorkerRunTests: + tests = (test_name,) + if self.runtests.rerun: + match_tests = self.runtests.get_match_tests(test_name) + else: + match_tests = None + + kwargs: dict[str, Any] = {} + if match_tests: + kwargs['match_tests'] = [(test, True) for test in match_tests] + if self.runtests.output_on_failure: + kwargs['verbose'] = True + kwargs['output_on_failure'] = False + return self.runtests.create_worker_runtests( + tests=tests, + json_file=json_file, + **kwargs) + + def run_tmp_files(self, worker_runtests: WorkerRunTests, + stdout_fd: int) -> tuple[int | None, list[StrPath]]: + # gh-93353: Check for leaked temporary files in the parent process, + # since the deletion of temporary files can happen late during + # Python finalization: too late for libregrtest. + if not support.is_wasi: + # Don't check for leaked temporary files and directories if Python is + # run on WASI. WASI doesn't pass environment variables like TMPDIR to + # worker processes. + tmp_dir = tempfile.mkdtemp(prefix="test_python_") + tmp_dir = os.path.abspath(tmp_dir) + try: + retcode = self._run_process(worker_runtests, + stdout_fd, tmp_dir) + finally: + tmp_files = os.listdir(tmp_dir) + os_helper.rmtree(tmp_dir) + else: + retcode = self._run_process(worker_runtests, stdout_fd) + tmp_files = [] + + return (retcode, tmp_files) + + def read_stdout(self, stdout_file: TextIO) -> str: + stdout_file.seek(0) + try: + return stdout_file.read().strip() + except Exception as exc: + # gh-101634: Catch UnicodeDecodeError if stdout cannot be + # decoded from encoding + raise WorkerError(self.test_name, + f"Cannot read process stdout: {exc}", + stdout=None, + state=State.WORKER_BUG) + + def read_json(self, json_file: JsonFile, json_tmpfile: TextIO | None, + stdout: str) -> tuple[TestResult, str]: + try: + if json_tmpfile is not None: + json_tmpfile.seek(0) + worker_json = json_tmpfile.read() + elif json_file.file_type == JsonFileType.STDOUT: + stdout, _, worker_json = stdout.rpartition("\n") + stdout = stdout.rstrip() + else: + with json_file.open(encoding='utf8') as json_fp: + worker_json = json_fp.read() + except Exception as exc: + # gh-101634: Catch UnicodeDecodeError if stdout cannot be + # decoded from encoding + err_msg = f"Failed to read worker process JSON: {exc}" + raise WorkerError(self.test_name, err_msg, stdout, + state=State.WORKER_BUG) + + if not worker_json: + raise WorkerError(self.test_name, "empty JSON", stdout, + state=State.WORKER_BUG) + + try: + result = TestResult.from_json(worker_json) + except Exception as exc: + # gh-101634: Catch UnicodeDecodeError if stdout cannot be + # decoded from encoding + err_msg = f"Failed to parse worker process JSON: {exc}" + raise WorkerError(self.test_name, err_msg, stdout, + state=State.WORKER_BUG) + + return (result, stdout) + + def _runtest(self, test_name: TestName) -> MultiprocessResult: + with contextlib.ExitStack() as stack: + stdout_file = self.create_stdout(stack) + json_file, json_tmpfile = self.create_json_file(stack) + worker_runtests = self.create_worker_runtests(test_name, json_file) + + retcode: str | int | None + retcode, tmp_files = self.run_tmp_files(worker_runtests, + stdout_file.fileno()) + + stdout = self.read_stdout(stdout_file) + + if retcode is None: + raise WorkerError(self.test_name, stdout=stdout, + err_msg=None, + state=State.TIMEOUT) + if retcode != 0: + name = get_signal_name(retcode) + if name: + retcode = f"{retcode} ({name})" + raise WorkerError(self.test_name, f"Exit code {retcode}", stdout, + state=State.WORKER_FAILED) + + result, stdout = self.read_json(json_file, json_tmpfile, stdout) + + if tmp_files: + msg = (f'\n\n' + f'Warning -- {test_name} leaked temporary files ' + f'({len(tmp_files)}): {", ".join(sorted(tmp_files))}') + stdout += msg + result.set_env_changed() + + return MultiprocessResult(result, stdout) + + def run(self) -> None: + fail_fast = self.runtests.fail_fast + fail_env_changed = self.runtests.fail_env_changed + while not self._stopped: + try: + try: + test_name = next(self.pending) + except StopIteration: + break + + self.start_time = time.monotonic() + self.test_name = test_name + try: + mp_result = self._runtest(test_name) + except WorkerError as exc: + mp_result = exc.mp_result + finally: + self.test_name = None + mp_result.result.duration = time.monotonic() - self.start_time + self.output.put((False, mp_result)) + + if mp_result.result.must_stop(fail_fast, fail_env_changed): + break + except ExitThread: + break + except BaseException: + self.output.put((True, traceback.format_exc())) + break + + def _wait_completed(self) -> None: + popen = self._popen + + try: + popen.wait(WAIT_COMPLETED_TIMEOUT) + except (subprocess.TimeoutExpired, OSError) as exc: + print_warning(f"Failed to wait for {self} completion " + f"(timeout={format_duration(WAIT_COMPLETED_TIMEOUT)}): " + f"{exc!r}") + + def wait_stopped(self, start_time: float) -> None: + # bpo-38207: RunWorkers.stop_workers() called self.stop() + # which killed the process. Sometimes, killing the process from the + # main thread does not interrupt popen.communicate() in + # WorkerThread thread. This loop with a timeout is a workaround + # for that. + # + # Moreover, if this method fails to join the thread, it is likely + # that Python will hang at exit while calling threading._shutdown() + # which tries again to join the blocked thread. Regrtest.main() + # uses EXIT_TIMEOUT to workaround this second bug. + while True: + # Write a message every second + self.join(1.0) + if not self.is_alive(): + break + dt = time.monotonic() - start_time + self.log(f"Waiting for {self} thread for {format_duration(dt)}") + if dt > WAIT_KILLED_TIMEOUT: + print_warning(f"Failed to join {self} in {format_duration(dt)}") + break + + +def get_running(workers: list[WorkerThread]) -> str | None: + running: list[str] = [] + for worker in workers: + test_name = worker.test_name + if not test_name: + continue + dt = time.monotonic() - worker.start_time + if dt >= PROGRESS_MIN_TIME: + text = f'{test_name} ({format_duration(dt)})' + running.append(text) + if not running: + return None + return f"running ({len(running)}): {', '.join(running)}" + + +class RunWorkers: + def __init__(self, num_workers: int, runtests: RunTests, + logger: Logger, results: TestResults) -> None: + self.num_workers = num_workers + self.runtests = runtests + self.log = logger.log + self.display_progress = logger.display_progress + self.results: TestResults = results + + self.output: queue.Queue[QueueOutput] = queue.Queue() + tests_iter = runtests.iter_tests() + self.pending = MultiprocessIterator(tests_iter) + self.timeout = runtests.timeout + if self.timeout is not None: + # Rely on faulthandler to kill a worker process. This timouet is + # when faulthandler fails to kill a worker process. Give a maximum + # of 5 minutes to faulthandler to kill the worker. + self.worker_timeout: float | None = min(self.timeout * 1.5, self.timeout + 5 * 60) + else: + self.worker_timeout = None + self.workers: list[WorkerThread] | None = None + + jobs = self.runtests.get_jobs() + if jobs is not None: + # Don't spawn more threads than the number of jobs: + # these worker threads would never get anything to do. + self.num_workers = min(self.num_workers, jobs) + + def start_workers(self) -> None: + self.workers = [WorkerThread(index, self) + for index in range(1, self.num_workers + 1)] + jobs = self.runtests.get_jobs() + if jobs is not None: + tests = count(jobs, 'test') + else: + tests = 'tests' + nworkers = len(self.workers) + processes = plural(nworkers, "process", "processes") + msg = (f"Run {tests} in parallel using " + f"{nworkers} worker {processes}") + if self.timeout: + msg += (" (timeout: %s, worker timeout: %s)" + % (format_duration(self.timeout), + format_duration(self.worker_timeout))) + self.log(msg) + for worker in self.workers: + worker.start() + + def stop_workers(self) -> None: + start_time = time.monotonic() + for worker in self.workers: + worker.stop() + for worker in self.workers: + worker.wait_stopped(start_time) + + def _get_result(self) -> QueueOutput | None: + pgo = self.runtests.pgo + use_faulthandler = (self.timeout is not None) + + # bpo-46205: check the status of workers every iteration to avoid + # waiting forever on an empty queue. + while any(worker.is_alive() for worker in self.workers): + if use_faulthandler: + faulthandler.dump_traceback_later(MAIN_PROCESS_TIMEOUT, + exit=True) + + # wait for a thread + try: + return self.output.get(timeout=PROGRESS_UPDATE) + except queue.Empty: + pass + + if not pgo: + # display progress + running = get_running(self.workers) + if running: + self.log(running) + + # all worker threads are done: consume pending results + try: + return self.output.get(timeout=0) + except queue.Empty: + return None + + def display_result(self, mp_result: MultiprocessResult) -> None: + result = mp_result.result + pgo = self.runtests.pgo + + text = str(result) + if mp_result.err_msg: + # WORKER_BUG + text += ' (%s)' % mp_result.err_msg + elif (result.duration >= PROGRESS_MIN_TIME and not pgo): + text += ' (%s)' % format_duration(result.duration) + if not pgo: + running = get_running(self.workers) + if running: + text += f' -- {running}' + self.display_progress(self.test_index, text) + + def _process_result(self, item: QueueOutput) -> TestResult: + """Returns True if test runner must stop.""" + if item[0]: + # Thread got an exception + format_exc = item[1] + print_warning(f"regrtest worker thread failed: {format_exc}") + result = TestResult("", state=State.WORKER_BUG) + self.results.accumulate_result(result, self.runtests) + return result + + self.test_index += 1 + mp_result = item[1] + result = mp_result.result + self.results.accumulate_result(result, self.runtests) + self.display_result(mp_result) + + # Display worker stdout + if not self.runtests.output_on_failure: + show_stdout = True + else: + # --verbose3 ignores stdout on success + show_stdout = (result.state != State.PASSED) + if show_stdout: + stdout = mp_result.worker_stdout + if stdout: + print(stdout, flush=True) + + return result + + def run(self) -> None: + fail_fast = self.runtests.fail_fast + fail_env_changed = self.runtests.fail_env_changed + + self.start_workers() + + self.test_index = 0 + try: + while True: + item = self._get_result() + if item is None: + break + + result = self._process_result(item) + if result.must_stop(fail_fast, fail_env_changed): + break + except KeyboardInterrupt: + print() + self.results.interrupted = True + finally: + if self.timeout is not None: + faulthandler.cancel_dump_traceback_later() + + # Always ensure that all worker processes are no longer + # worker when we exit this function + self.pending.stop() + self.stop_workers() diff --git a/Lib/test/libregrtest/runtest.py b/Lib/test/libregrtest/runtest.py deleted file mode 100644 index 61595277ed6d5a..00000000000000 --- a/Lib/test/libregrtest/runtest.py +++ /dev/null @@ -1,444 +0,0 @@ -import faulthandler -import functools -import gc -import importlib -import io -import os -import sys -import time -import traceback -import unittest - -from test import support -from test.support import os_helper -from test.support import threading_helper -from test.libregrtest.cmdline import Namespace -from test.libregrtest.save_env import saved_test_environment -from test.libregrtest.utils import clear_caches, format_duration, print_warning - - -class TestResult: - def __init__( - self, - name: str, - duration_sec: float = 0.0, - xml_data: list[str] | None = None, - ) -> None: - self.name = name - self.duration_sec = duration_sec - self.xml_data = xml_data - - def __str__(self) -> str: - return f"{self.name} finished" - - -class Passed(TestResult): - def __str__(self) -> str: - return f"{self.name} passed" - - -class Failed(TestResult): - def __init__( - self, - name: str, - duration_sec: float = 0.0, - xml_data: list[str] | None = None, - errors: list[tuple[str, str]] | None = None, - failures: list[tuple[str, str]] | None = None, - ) -> None: - super().__init__(name, duration_sec=duration_sec, xml_data=xml_data) - self.errors = errors - self.failures = failures - - def __str__(self) -> str: - if self.errors and self.failures: - le = len(self.errors) - lf = len(self.failures) - error_s = "error" + ("s" if le > 1 else "") - failure_s = "failure" + ("s" if lf > 1 else "") - return f"{self.name} failed ({le} {error_s}, {lf} {failure_s})" - - if self.errors: - le = len(self.errors) - error_s = "error" + ("s" if le > 1 else "") - return f"{self.name} failed ({le} {error_s})" - - if self.failures: - lf = len(self.failures) - failure_s = "failure" + ("s" if lf > 1 else "") - return f"{self.name} failed ({lf} {failure_s})" - - return f"{self.name} failed" - - -class UncaughtException(Failed): - def __str__(self) -> str: - return f"{self.name} failed (uncaught exception)" - - -class EnvChanged(Failed): - def __str__(self) -> str: - return f"{self.name} failed (env changed)" - - # Convert Passed to EnvChanged - @staticmethod - def from_passed(other): - return EnvChanged(other.name, other.duration_sec, other.xml_data) - - -class RefLeak(Failed): - def __str__(self) -> str: - return f"{self.name} failed (reference leak)" - - -class Skipped(TestResult): - def __str__(self) -> str: - return f"{self.name} skipped" - - -class ResourceDenied(Skipped): - def __str__(self) -> str: - return f"{self.name} skipped (resource denied)" - - -class Interrupted(TestResult): - def __str__(self) -> str: - return f"{self.name} interrupted" - - -class ChildError(Failed): - def __str__(self) -> str: - return f"{self.name} crashed" - - -class DidNotRun(TestResult): - def __str__(self) -> str: - return f"{self.name} ran no tests" - - -class Timeout(Failed): - def __str__(self) -> str: - return f"{self.name} timed out ({format_duration(self.duration_sec)})" - - -# Minimum duration of a test to display its duration or to mention that -# the test is running in background -PROGRESS_MIN_TIME = 30.0 # seconds - -# small set of tests to determine if we have a basically functioning interpreter -# (i.e. if any of these fail, then anything else is likely to follow) -STDTESTS = [ - 'test_grammar', - 'test_opcodes', - 'test_dict', - 'test_builtin', - 'test_exceptions', - 'test_types', - 'test_unittest', - 'test_doctest', - 'test_doctest2', - 'test_support' -] - -# set of tests that we don't want to be executed when using regrtest -NOTTESTS = set() - -#If these test directories are encountered recurse into them and treat each -# test_ .py or dir as a separate test module. This can increase parallelism. -# Beware this can't generally be done for any directory with sub-tests as the -# __init__.py may do things which alter what tests are to be run. - -SPLITTESTDIRS = { - "test_asyncio", -} - -# Storage of uncollectable objects -FOUND_GARBAGE = [] - - -def is_failed(result: TestResult, ns: Namespace) -> bool: - if isinstance(result, EnvChanged): - return ns.fail_env_changed - return isinstance(result, Failed) - - -def findtestdir(path=None): - return path or os.path.dirname(os.path.dirname(__file__)) or os.curdir - - -def findtests(testdir=None, stdtests=STDTESTS, nottests=NOTTESTS, *, split_test_dirs=SPLITTESTDIRS, base_mod=""): - """Return a list of all applicable test modules.""" - testdir = findtestdir(testdir) - names = os.listdir(testdir) - tests = [] - others = set(stdtests) | nottests - for name in names: - mod, ext = os.path.splitext(name) - if mod[:5] == "test_" and mod not in others: - if mod in split_test_dirs: - subdir = os.path.join(testdir, mod) - mod = f"{base_mod or 'test'}.{mod}" - tests.extend(findtests(subdir, [], nottests, split_test_dirs=split_test_dirs, base_mod=mod)) - elif ext in (".py", ""): - tests.append(f"{base_mod}.{mod}" if base_mod else mod) - return stdtests + sorted(tests) - - -def get_abs_module(ns: Namespace, test_name: str) -> str: - if test_name.startswith('test.') or ns.testdir: - return test_name - else: - # Import it from the test package - return 'test.' + test_name - - -def _runtest(ns: Namespace, test_name: str) -> TestResult: - # Handle faulthandler timeout, capture stdout+stderr, XML serialization - # and measure time. - - output_on_failure = ns.verbose3 - - use_timeout = ( - ns.timeout is not None and threading_helper.can_start_thread - ) - if use_timeout: - faulthandler.dump_traceback_later(ns.timeout, exit=True) - - start_time = time.perf_counter() - try: - support.set_match_tests(ns.match_tests, ns.ignore_tests) - support.junit_xml_list = xml_list = [] if ns.xmlpath else None - if ns.failfast: - support.failfast = True - - if output_on_failure: - support.verbose = True - - stream = io.StringIO() - orig_stdout = sys.stdout - orig_stderr = sys.stderr - print_warning = support.print_warning - orig_print_warnings_stderr = print_warning.orig_stderr - - output = None - try: - sys.stdout = stream - sys.stderr = stream - # print_warning() writes into the temporary stream to preserve - # messages order. If support.environment_altered becomes true, - # warnings will be written to sys.stderr below. - print_warning.orig_stderr = stream - - result = _runtest_inner(ns, test_name, - display_failure=False) - if not isinstance(result, Passed): - output = stream.getvalue() - finally: - sys.stdout = orig_stdout - sys.stderr = orig_stderr - print_warning.orig_stderr = orig_print_warnings_stderr - - if output is not None: - sys.stderr.write(output) - sys.stderr.flush() - else: - # Tell tests to be moderately quiet - support.verbose = ns.verbose - - result = _runtest_inner(ns, test_name, - display_failure=not ns.verbose) - - if xml_list: - import xml.etree.ElementTree as ET - result.xml_data = [ - ET.tostring(x).decode('us-ascii') - for x in xml_list - ] - - result.duration_sec = time.perf_counter() - start_time - return result - finally: - if use_timeout: - faulthandler.cancel_dump_traceback_later() - support.junit_xml_list = None - - -def runtest(ns: Namespace, test_name: str) -> TestResult: - """Run a single test. - - ns -- regrtest namespace of options - test_name -- the name of the test - - Returns a TestResult sub-class depending on the kind of result received. - - If ns.xmlpath is not None, xml_data is a list containing each - generated testsuite element. - """ - try: - return _runtest(ns, test_name) - except: - if not ns.pgo: - msg = traceback.format_exc() - print(f"test {test_name} crashed -- {msg}", - file=sys.stderr, flush=True) - return Failed(test_name) - - -def _test_module(the_module): - loader = unittest.TestLoader() - tests = loader.loadTestsFromModule(the_module) - for error in loader.errors: - print(error, file=sys.stderr) - if loader.errors: - raise Exception("errors while loading tests") - support.run_unittest(tests) - - -def save_env(ns: Namespace, test_name: str): - return saved_test_environment(test_name, ns.verbose, ns.quiet, pgo=ns.pgo) - - -def _runtest_inner2(ns: Namespace, test_name: str) -> bool: - # Load the test function, run the test function, handle huntrleaks - # to detect leaks. - - abstest = get_abs_module(ns, test_name) - - # remove the module from sys.module to reload it if it was already imported - try: - del sys.modules[abstest] - except KeyError: - pass - - the_module = importlib.import_module(abstest) - - if ns.huntrleaks: - from test.libregrtest.refleak import dash_R - - # If the test has a test_main, that will run the appropriate - # tests. If not, use normal unittest test loading. - test_runner = getattr(the_module, "test_main", None) - if test_runner is None: - test_runner = functools.partial(_test_module, the_module) - - try: - with save_env(ns, test_name): - if ns.huntrleaks: - # Return True if the test leaked references - refleak = dash_R(ns, test_name, test_runner) - else: - test_runner() - refleak = False - finally: - # First kill any dangling references to open files etc. - # This can also issue some ResourceWarnings which would otherwise get - # triggered during the following test run, and possibly produce - # failures. - support.gc_collect() - - cleanup_test_droppings(test_name, ns.verbose) - - if gc.garbage: - support.environment_altered = True - print_warning(f"{test_name} created {len(gc.garbage)} " - f"uncollectable object(s).") - - # move the uncollectable objects somewhere, - # so we don't see them again - FOUND_GARBAGE.extend(gc.garbage) - gc.garbage.clear() - - support.reap_children() - - return refleak - - -def _runtest_inner( - ns: Namespace, test_name: str, display_failure: bool = True -) -> TestResult: - # Detect environment changes, handle exceptions. - - # Reset the environment_altered flag to detect if a test altered - # the environment - support.environment_altered = False - - if ns.pgo: - display_failure = False - - try: - clear_caches() - support.gc_collect() - - with save_env(ns, test_name): - refleak = _runtest_inner2(ns, test_name) - except support.ResourceDenied as msg: - if not ns.quiet and not ns.pgo: - print(f"{test_name} skipped -- {msg}", flush=True) - return ResourceDenied(test_name) - except unittest.SkipTest as msg: - if not ns.quiet and not ns.pgo: - print(f"{test_name} skipped -- {msg}", flush=True) - return Skipped(test_name) - except support.TestFailedWithDetails as exc: - msg = f"test {test_name} failed" - if display_failure: - msg = f"{msg} -- {exc}" - print(msg, file=sys.stderr, flush=True) - return Failed(test_name, errors=exc.errors, failures=exc.failures) - except support.TestFailed as exc: - msg = f"test {test_name} failed" - if display_failure: - msg = f"{msg} -- {exc}" - print(msg, file=sys.stderr, flush=True) - return Failed(test_name) - except support.TestDidNotRun: - return DidNotRun(test_name) - except KeyboardInterrupt: - print() - return Interrupted(test_name) - except: - if not ns.pgo: - msg = traceback.format_exc() - print(f"test {test_name} crashed -- {msg}", - file=sys.stderr, flush=True) - return UncaughtException(test_name) - - if refleak: - return RefLeak(test_name) - if support.environment_altered: - return EnvChanged(test_name) - return Passed(test_name) - - -def cleanup_test_droppings(test_name: str, verbose: int) -> None: - # Try to clean up junk commonly left behind. While tests shouldn't leave - # any files or directories behind, when a test fails that can be tedious - # for it to arrange. The consequences can be especially nasty on Windows, - # since if a test leaves a file open, it cannot be deleted by name (while - # there's nothing we can do about that here either, we can display the - # name of the offending test, which is a real help). - for name in (os_helper.TESTFN,): - if not os.path.exists(name): - continue - - if os.path.isdir(name): - import shutil - kind, nuker = "directory", shutil.rmtree - elif os.path.isfile(name): - kind, nuker = "file", os.unlink - else: - raise RuntimeError(f"os.path says {name!r} exists but is neither " - f"directory nor file") - - if verbose: - print_warning(f"{test_name} left behind {kind} {name!r}") - support.environment_altered = True - - try: - import stat - # fix possible permissions problems that might prevent cleanup - os.chmod(name, stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO) - nuker(name) - except Exception as exc: - print_warning(f"{test_name} left behind {kind} {name!r} " - f"and it couldn't be removed: {exc}") diff --git a/Lib/test/libregrtest/runtest_mp.py b/Lib/test/libregrtest/runtest_mp.py deleted file mode 100644 index 62e6c6df36518c..00000000000000 --- a/Lib/test/libregrtest/runtest_mp.py +++ /dev/null @@ -1,572 +0,0 @@ -import faulthandler -import json -import os.path -import queue -import signal -import subprocess -import sys -import tempfile -import threading -import time -import traceback -from typing import NamedTuple, NoReturn, Literal, Any, TextIO - -from test import support -from test.support import os_helper - -from test.libregrtest.cmdline import Namespace -from test.libregrtest.main import Regrtest -from test.libregrtest.runtest import ( - runtest, is_failed, TestResult, Interrupted, Timeout, ChildError, - PROGRESS_MIN_TIME, Passed, EnvChanged) -from test.libregrtest.setup import setup_tests -from test.libregrtest.utils import format_duration, print_warning - -if sys.platform == 'win32': - import locale - - -# Display the running tests if nothing happened last N seconds -PROGRESS_UPDATE = 30.0 # seconds -assert PROGRESS_UPDATE >= PROGRESS_MIN_TIME - -# Kill the main process after 5 minutes. It is supposed to write an update -# every PROGRESS_UPDATE seconds. Tolerate 5 minutes for Python slowest -# buildbot workers. -MAIN_PROCESS_TIMEOUT = 5 * 60.0 -assert MAIN_PROCESS_TIMEOUT >= PROGRESS_UPDATE - -# Time to wait until a worker completes: should be immediate -JOIN_TIMEOUT = 30.0 # seconds - -USE_PROCESS_GROUP = (hasattr(os, "setsid") and hasattr(os, "killpg")) - - -def must_stop(result: TestResult, ns: Namespace) -> bool: - if isinstance(result, Interrupted): - return True - if ns.failfast and is_failed(result, ns): - return True - return False - - -def parse_worker_args(worker_args) -> tuple[Namespace, str]: - ns_dict, test_name = json.loads(worker_args) - ns = Namespace(**ns_dict) - return (ns, test_name) - - -def run_test_in_subprocess(testname: str, ns: Namespace, tmp_dir: str, stdout_fh: TextIO) -> subprocess.Popen: - ns_dict = vars(ns) - worker_args = (ns_dict, testname) - worker_args = json.dumps(worker_args) - if ns.python is not None: - executable = ns.python - else: - executable = [sys.executable] - cmd = [*executable, *support.args_from_interpreter_flags(), - '-u', # Unbuffered stdout and stderr - '-m', 'test.regrtest', - '--worker-args', worker_args] - - env = dict(os.environ) - if tmp_dir is not None: - env['TMPDIR'] = tmp_dir - env['TEMP'] = tmp_dir - env['TMP'] = tmp_dir - - # Running the child from the same working directory as regrtest's original - # invocation ensures that TEMPDIR for the child is the same when - # sysconfig.is_python_build() is true. See issue 15300. - kw = dict( - env=env, - stdout=stdout_fh, - # bpo-45410: Write stderr into stdout to keep messages order - stderr=stdout_fh, - text=True, - close_fds=(os.name != 'nt'), - cwd=os_helper.SAVEDCWD, - ) - if USE_PROCESS_GROUP: - kw['start_new_session'] = True - return subprocess.Popen(cmd, **kw) - - -def run_tests_worker(ns: Namespace, test_name: str) -> NoReturn: - setup_tests(ns) - - result = runtest(ns, test_name) - - print() # Force a newline (just in case) - - # Serialize TestResult as dict in JSON - print(json.dumps(result, cls=EncodeTestResult), flush=True) - sys.exit(0) - - -# We do not use a generator so multiple threads can call next(). -class MultiprocessIterator: - - """A thread-safe iterator over tests for multiprocess mode.""" - - def __init__(self, tests_iter): - self.lock = threading.Lock() - self.tests_iter = tests_iter - - def __iter__(self): - return self - - def __next__(self): - with self.lock: - if self.tests_iter is None: - raise StopIteration - return next(self.tests_iter) - - def stop(self): - with self.lock: - self.tests_iter = None - - -class MultiprocessResult(NamedTuple): - result: TestResult - # bpo-45410: stderr is written into stdout to keep messages order - stdout: str - error_msg: str - - -ExcStr = str -QueueOutput = tuple[Literal[False], MultiprocessResult] | tuple[Literal[True], ExcStr] - - -class ExitThread(Exception): - pass - - -class TestWorkerProcess(threading.Thread): - def __init__(self, worker_id: int, runner: "MultiprocessTestRunner") -> None: - super().__init__() - self.worker_id = worker_id - self.pending = runner.pending - self.output = runner.output - self.ns = runner.ns - self.timeout = runner.worker_timeout - self.regrtest = runner.regrtest - self.current_test_name = None - self.start_time = None - self._popen = None - self._killed = False - self._stopped = False - - def __repr__(self) -> str: - info = [f'TestWorkerProcess #{self.worker_id}'] - if self.is_alive(): - info.append("running") - else: - info.append('stopped') - test = self.current_test_name - if test: - info.append(f'test={test}') - popen = self._popen - if popen is not None: - dt = time.monotonic() - self.start_time - info.extend((f'pid={self._popen.pid}', - f'time={format_duration(dt)}')) - return '<%s>' % ' '.join(info) - - def _kill(self) -> None: - popen = self._popen - if popen is None: - return - - if self._killed: - return - self._killed = True - - if USE_PROCESS_GROUP: - what = f"{self} process group" - else: - what = f"{self}" - - print(f"Kill {what}", file=sys.stderr, flush=True) - try: - if USE_PROCESS_GROUP: - os.killpg(popen.pid, signal.SIGKILL) - else: - popen.kill() - except ProcessLookupError: - # popen.kill(): the process completed, the TestWorkerProcess thread - # read its exit status, but Popen.send_signal() read the returncode - # just before Popen.wait() set returncode. - pass - except OSError as exc: - print_warning(f"Failed to kill {what}: {exc!r}") - - def stop(self) -> None: - # Method called from a different thread to stop this thread - self._stopped = True - self._kill() - - def mp_result_error( - self, - test_result: TestResult, - stdout: str = '', - err_msg=None - ) -> MultiprocessResult: - test_result.duration_sec = time.monotonic() - self.start_time - return MultiprocessResult(test_result, stdout, err_msg) - - def _run_process(self, test_name: str, tmp_dir: str, stdout_fh: TextIO) -> int: - self.start_time = time.monotonic() - - self.current_test_name = test_name - try: - popen = run_test_in_subprocess(test_name, self.ns, tmp_dir, stdout_fh) - - self._killed = False - self._popen = popen - except: - self.current_test_name = None - raise - - try: - if self._stopped: - # If kill() has been called before self._popen is set, - # self._popen is still running. Call again kill() - # to ensure that the process is killed. - self._kill() - raise ExitThread - - try: - # gh-94026: stdout+stderr are written to tempfile - retcode = popen.wait(timeout=self.timeout) - assert retcode is not None - return retcode - except subprocess.TimeoutExpired: - if self._stopped: - # kill() has been called: communicate() fails on reading - # closed stdout - raise ExitThread - - # On timeout, kill the process - self._kill() - - # None means TIMEOUT for the caller - retcode = None - # bpo-38207: Don't attempt to call communicate() again: on it - # can hang until all child processes using stdout - # pipes completes. - except OSError: - if self._stopped: - # kill() has been called: communicate() fails - # on reading closed stdout - raise ExitThread - raise - except: - self._kill() - raise - finally: - self._wait_completed() - self._popen = None - self.current_test_name = None - - def _runtest(self, test_name: str) -> MultiprocessResult: - if sys.platform == 'win32': - # gh-95027: When stdout is not a TTY, Python uses the ANSI code - # page for the sys.stdout encoding. If the main process runs in a - # terminal, sys.stdout uses WindowsConsoleIO with UTF-8 encoding. - encoding = locale.getencoding() - else: - encoding = sys.stdout.encoding - - # gh-94026: Write stdout+stderr to a tempfile as workaround for - # non-blocking pipes on Emscripten with NodeJS. - with tempfile.TemporaryFile('w+', encoding=encoding) as stdout_fh: - # gh-93353: Check for leaked temporary files in the parent process, - # since the deletion of temporary files can happen late during - # Python finalization: too late for libregrtest. - if not support.is_wasi: - # Don't check for leaked temporary files and directories if Python is - # run on WASI. WASI don't pass environment variables like TMPDIR to - # worker processes. - tmp_dir = tempfile.mkdtemp(prefix="test_python_") - tmp_dir = os.path.abspath(tmp_dir) - try: - retcode = self._run_process(test_name, tmp_dir, stdout_fh) - finally: - tmp_files = os.listdir(tmp_dir) - os_helper.rmtree(tmp_dir) - else: - retcode = self._run_process(test_name, None, stdout_fh) - tmp_files = () - stdout_fh.seek(0) - - try: - stdout = stdout_fh.read().strip() - except Exception as exc: - # gh-101634: Catch UnicodeDecodeError if stdout cannot be - # decoded from encoding - err_msg = f"Cannot read process stdout: {exc}" - return self.mp_result_error(ChildError(test_name), '', err_msg) - - if retcode is None: - return self.mp_result_error(Timeout(test_name), stdout) - - err_msg = None - if retcode != 0: - err_msg = "Exit code %s" % retcode - else: - stdout, _, result = stdout.rpartition("\n") - stdout = stdout.rstrip() - if not result: - err_msg = "Failed to parse worker stdout" - else: - try: - # deserialize run_tests_worker() output - result = json.loads(result, object_hook=decode_test_result) - except Exception as exc: - err_msg = "Failed to parse worker JSON: %s" % exc - - if err_msg is not None: - return self.mp_result_error(ChildError(test_name), stdout, err_msg) - - if tmp_files: - msg = (f'\n\n' - f'Warning -- {test_name} leaked temporary files ' - f'({len(tmp_files)}): {", ".join(sorted(tmp_files))}') - stdout += msg - if isinstance(result, Passed): - result = EnvChanged.from_passed(result) - - return MultiprocessResult(result, stdout, err_msg) - - def run(self) -> None: - while not self._stopped: - try: - try: - test_name = next(self.pending) - except StopIteration: - break - - mp_result = self._runtest(test_name) - self.output.put((False, mp_result)) - - if must_stop(mp_result.result, self.ns): - break - except ExitThread: - break - except BaseException: - self.output.put((True, traceback.format_exc())) - break - - def _wait_completed(self) -> None: - popen = self._popen - - try: - popen.wait(JOIN_TIMEOUT) - except (subprocess.TimeoutExpired, OSError) as exc: - print_warning(f"Failed to wait for {self} completion " - f"(timeout={format_duration(JOIN_TIMEOUT)}): " - f"{exc!r}") - - def wait_stopped(self, start_time: float) -> None: - # bpo-38207: MultiprocessTestRunner.stop_workers() called self.stop() - # which killed the process. Sometimes, killing the process from the - # main thread does not interrupt popen.communicate() in - # TestWorkerProcess thread. This loop with a timeout is a workaround - # for that. - # - # Moreover, if this method fails to join the thread, it is likely - # that Python will hang at exit while calling threading._shutdown() - # which tries again to join the blocked thread. Regrtest.main() - # uses EXIT_TIMEOUT to workaround this second bug. - while True: - # Write a message every second - self.join(1.0) - if not self.is_alive(): - break - dt = time.monotonic() - start_time - self.regrtest.log(f"Waiting for {self} thread " - f"for {format_duration(dt)}") - if dt > JOIN_TIMEOUT: - print_warning(f"Failed to join {self} in {format_duration(dt)}") - break - - -def get_running(workers: list[TestWorkerProcess]) -> list[TestWorkerProcess]: - running = [] - for worker in workers: - current_test_name = worker.current_test_name - if not current_test_name: - continue - dt = time.monotonic() - worker.start_time - if dt >= PROGRESS_MIN_TIME: - text = '%s (%s)' % (current_test_name, format_duration(dt)) - running.append(text) - return running - - -class MultiprocessTestRunner: - def __init__(self, regrtest: Regrtest) -> None: - self.regrtest = regrtest - self.log = self.regrtest.log - self.ns = regrtest.ns - self.output: queue.Queue[QueueOutput] = queue.Queue() - self.pending = MultiprocessIterator(self.regrtest.tests) - if self.ns.timeout is not None: - # Rely on faulthandler to kill a worker process. This timouet is - # when faulthandler fails to kill a worker process. Give a maximum - # of 5 minutes to faulthandler to kill the worker. - self.worker_timeout = min(self.ns.timeout * 1.5, - self.ns.timeout + 5 * 60) - else: - self.worker_timeout = None - self.workers = None - - def start_workers(self) -> None: - self.workers = [TestWorkerProcess(index, self) - for index in range(1, self.ns.use_mp + 1)] - msg = f"Run tests in parallel using {len(self.workers)} child processes" - if self.ns.timeout: - msg += (" (timeout: %s, worker timeout: %s)" - % (format_duration(self.ns.timeout), - format_duration(self.worker_timeout))) - self.log(msg) - for worker in self.workers: - worker.start() - - def stop_workers(self) -> None: - start_time = time.monotonic() - for worker in self.workers: - worker.stop() - for worker in self.workers: - worker.wait_stopped(start_time) - - def _get_result(self) -> QueueOutput | None: - use_faulthandler = (self.ns.timeout is not None) - timeout = PROGRESS_UPDATE - - # bpo-46205: check the status of workers every iteration to avoid - # waiting forever on an empty queue. - while any(worker.is_alive() for worker in self.workers): - if use_faulthandler: - faulthandler.dump_traceback_later(MAIN_PROCESS_TIMEOUT, - exit=True) - - # wait for a thread - try: - return self.output.get(timeout=timeout) - except queue.Empty: - pass - - # display progress - running = get_running(self.workers) - if running and not self.ns.pgo: - self.log('running: %s' % ', '.join(running)) - - # all worker threads are done: consume pending results - try: - return self.output.get(timeout=0) - except queue.Empty: - return None - - def display_result(self, mp_result: MultiprocessResult) -> None: - result = mp_result.result - - text = str(result) - if mp_result.error_msg is not None: - # CHILD_ERROR - text += ' (%s)' % mp_result.error_msg - elif (result.duration_sec >= PROGRESS_MIN_TIME and not self.ns.pgo): - text += ' (%s)' % format_duration(result.duration_sec) - running = get_running(self.workers) - if running and not self.ns.pgo: - text += ' -- running: %s' % ', '.join(running) - self.regrtest.display_progress(self.test_index, text) - - def _process_result(self, item: QueueOutput) -> bool: - """Returns True if test runner must stop.""" - if item[0]: - # Thread got an exception - format_exc = item[1] - print_warning(f"regrtest worker thread failed: {format_exc}") - result = ChildError("") - self.regrtest.accumulate_result(result) - return True - - self.test_index += 1 - mp_result = item[1] - self.regrtest.accumulate_result(mp_result.result) - self.display_result(mp_result) - - if mp_result.stdout: - print(mp_result.stdout, flush=True) - - if must_stop(mp_result.result, self.ns): - return True - - return False - - def run_tests(self) -> None: - self.start_workers() - - self.test_index = 0 - try: - while True: - item = self._get_result() - if item is None: - break - - stop = self._process_result(item) - if stop: - break - except KeyboardInterrupt: - print() - self.regrtest.interrupted = True - finally: - if self.ns.timeout is not None: - faulthandler.cancel_dump_traceback_later() - - # Always ensure that all worker processes are no longer - # worker when we exit this function - self.pending.stop() - self.stop_workers() - - -def run_tests_multiprocess(regrtest: Regrtest) -> None: - MultiprocessTestRunner(regrtest).run_tests() - - -class EncodeTestResult(json.JSONEncoder): - """Encode a TestResult (sub)class object into a JSON dict.""" - - def default(self, o: Any) -> dict[str, Any]: - if isinstance(o, TestResult): - result = vars(o) - result["__test_result__"] = o.__class__.__name__ - return result - - return super().default(o) - - -def decode_test_result(d: dict[str, Any]) -> TestResult | dict[str, Any]: - """Decode a TestResult (sub)class object from a JSON dict.""" - - if "__test_result__" not in d: - return d - - cls_name = d.pop("__test_result__") - for cls in get_all_test_result_classes(): - if cls.__name__ == cls_name: - return cls(**d) - - -def get_all_test_result_classes() -> set[type[TestResult]]: - prev_count = 0 - classes = {TestResult} - while len(classes) > prev_count: - prev_count = len(classes) - to_add = [] - for cls in classes: - to_add.extend(cls.__subclasses__()) - classes.update(to_add) - return classes diff --git a/Lib/test/libregrtest/runtests.py b/Lib/test/libregrtest/runtests.py new file mode 100644 index 00000000000000..edd72276320e41 --- /dev/null +++ b/Lib/test/libregrtest/runtests.py @@ -0,0 +1,172 @@ +import contextlib +import dataclasses +import json +import os +import subprocess +from typing import Any + +from test import support + +from .utils import ( + StrPath, StrJSON, TestTuple, TestFilter, FilterTuple, FilterDict) + + +class JsonFileType: + UNIX_FD = "UNIX_FD" + WINDOWS_HANDLE = "WINDOWS_HANDLE" + STDOUT = "STDOUT" + + +@dataclasses.dataclass(slots=True, frozen=True) +class JsonFile: + # file type depends on file_type: + # - UNIX_FD: file descriptor (int) + # - WINDOWS_HANDLE: handle (int) + # - STDOUT: use process stdout (None) + file: int | None + file_type: str + + def configure_subprocess(self, popen_kwargs: dict) -> None: + match self.file_type: + case JsonFileType.UNIX_FD: + # Unix file descriptor + popen_kwargs['pass_fds'] = [self.file] + case JsonFileType.WINDOWS_HANDLE: + # Windows handle + # We run mypy with `--platform=linux` so it complains about this: + startupinfo = subprocess.STARTUPINFO() # type: ignore[attr-defined] + startupinfo.lpAttributeList = {"handle_list": [self.file]} + popen_kwargs['startupinfo'] = startupinfo + + @contextlib.contextmanager + def inherit_subprocess(self): + if self.file_type == JsonFileType.WINDOWS_HANDLE: + os.set_handle_inheritable(self.file, True) + try: + yield + finally: + os.set_handle_inheritable(self.file, False) + else: + yield + + def open(self, mode='r', *, encoding): + if self.file_type == JsonFileType.STDOUT: + raise ValueError("for STDOUT file type, just use sys.stdout") + + file = self.file + if self.file_type == JsonFileType.WINDOWS_HANDLE: + import msvcrt + # Create a file descriptor from the handle + file = msvcrt.open_osfhandle(file, os.O_WRONLY) + return open(file, mode, encoding=encoding) + + +@dataclasses.dataclass(slots=True, frozen=True) +class HuntRefleak: + warmups: int + runs: int + filename: StrPath + + +@dataclasses.dataclass(slots=True, frozen=True) +class RunTests: + tests: TestTuple + fail_fast: bool + fail_env_changed: bool + match_tests: TestFilter + match_tests_dict: FilterDict | None + rerun: bool + forever: bool + pgo: bool + pgo_extended: bool + output_on_failure: bool + timeout: float | None + verbose: int + quiet: bool + hunt_refleak: HuntRefleak | None + test_dir: StrPath | None + use_junit: bool + coverage: bool + memory_limit: str | None + gc_threshold: int | None + use_resources: tuple[str, ...] + python_cmd: tuple[str, ...] | None + randomize: bool + random_seed: int | str + + def copy(self, **override) -> 'RunTests': + state = dataclasses.asdict(self) + state.update(override) + return RunTests(**state) + + def create_worker_runtests(self, **override): + state = dataclasses.asdict(self) + state.update(override) + return WorkerRunTests(**state) + + def get_match_tests(self, test_name) -> FilterTuple | None: + if self.match_tests_dict is not None: + return self.match_tests_dict.get(test_name, None) + else: + return None + + def get_jobs(self): + # Number of run_single_test() calls needed to run all tests. + # None means that there is not bound limit (--forever option). + if self.forever: + return None + return len(self.tests) + + def iter_tests(self): + if self.forever: + while True: + yield from self.tests + else: + yield from self.tests + + def json_file_use_stdout(self) -> bool: + # Use STDOUT in two cases: + # + # - If --python command line option is used; + # - On Emscripten and WASI. + # + # On other platforms, UNIX_FD or WINDOWS_HANDLE can be used. + return ( + bool(self.python_cmd) + or support.is_emscripten + or support.is_wasi + ) + + +@dataclasses.dataclass(slots=True, frozen=True) +class WorkerRunTests(RunTests): + json_file: JsonFile + + def as_json(self) -> StrJSON: + return json.dumps(self, cls=_EncodeRunTests) + + @staticmethod + def from_json(worker_json: StrJSON) -> 'WorkerRunTests': + return json.loads(worker_json, object_hook=_decode_runtests) + + +class _EncodeRunTests(json.JSONEncoder): + def default(self, o: Any) -> dict[str, Any]: + if isinstance(o, WorkerRunTests): + result = dataclasses.asdict(o) + result["__runtests__"] = True + return result + else: + return super().default(o) + + +def _decode_runtests(data: dict[str, Any]) -> RunTests | dict[str, Any]: + if "__runtests__" in data: + data.pop('__runtests__') + if data['hunt_refleak']: + data['hunt_refleak'] = HuntRefleak(**data['hunt_refleak']) + if data['json_file']: + data['json_file'] = JsonFile(**data['json_file']) + return WorkerRunTests(**data) + else: + return data diff --git a/Lib/test/libregrtest/save_env.py b/Lib/test/libregrtest/save_env.py index c7801b767c590c..b2cc381344b2ef 100644 --- a/Lib/test/libregrtest/save_env.py +++ b/Lib/test/libregrtest/save_env.py @@ -3,9 +3,11 @@ import os import sys import threading + from test import support from test.support import os_helper -from test.libregrtest.utils import print_warning + +from .utils import print_warning class SkipTestEnvironment(Exception): @@ -23,7 +25,7 @@ class SkipTestEnvironment(Exception): class saved_test_environment: """Save bits of the test environment and restore them at block exit. - with saved_test_environment(testname, verbose, quiet): + with saved_test_environment(test_name, verbose, quiet): #stuff Unless quiet is True, a warning is printed to stderr if any of @@ -34,8 +36,8 @@ class saved_test_environment: items is also printed. """ - def __init__(self, testname, verbose=0, quiet=False, *, pgo=False): - self.testname = testname + def __init__(self, test_name, verbose, quiet, *, pgo): + self.test_name = test_name self.verbose = verbose self.quiet = quiet self.pgo = pgo @@ -323,7 +325,7 @@ def __exit__(self, exc_type, exc_val, exc_tb): restore(original) if not self.quiet and not self.pgo: print_warning( - f"{name} was modified by {self.testname}\n" + f"{name} was modified by {self.test_name}\n" f" Before: {original}\n" f" After: {current} ") return False diff --git a/Lib/test/libregrtest/setup.py b/Lib/test/libregrtest/setup.py index b76bece7ca08b5..9e9741493e9a5b 100644 --- a/Lib/test/libregrtest/setup.py +++ b/Lib/test/libregrtest/setup.py @@ -1,24 +1,33 @@ -import atexit import faulthandler +import gc import os +import random import signal import sys import unittest from test import support from test.support.os_helper import TESTFN_UNDECODABLE, FS_NONASCII -try: - import gc -except ImportError: - gc = None -from test.libregrtest.utils import (setup_unraisable_hook, - setup_threading_excepthook) +from .filter import set_match_tests +from .runtests import RunTests +from .utils import ( + setup_unraisable_hook, setup_threading_excepthook, fix_umask, + adjust_rlimit_nofile) UNICODE_GUARD_ENV = "PYTHONREGRTEST_UNICODE_GUARD" -def setup_tests(ns): +def setup_test_dir(testdir: str | None) -> None: + if testdir: + # Prepend test directory to sys.path, so runtest() will be able + # to locate tests + sys.path.insert(0, os.path.abspath(testdir)) + + +def setup_process(): + fix_umask() + try: stderr_fd = sys.__stderr__.fileno() except (ValueError, AttributeError): @@ -40,14 +49,9 @@ def setup_tests(ns): for signum in signals: faulthandler.register(signum, chain=True, file=stderr_fd) - _adjust_resource_limits() - replace_stdout() - support.record_original_stdout(sys.stdout) + adjust_rlimit_nofile() - if ns.testdir: - # Prepend test directory to sys.path, so runtest() will be able - # to locate tests - sys.path.insert(0, os.path.abspath(ns.testdir)) + support.record_original_stdout(sys.stdout) # Some times __path__ and __file__ are not absolute (e.g. while running from # Lib/) and, if we change the CWD to run the tests in a temporary dir, some @@ -66,19 +70,6 @@ def setup_tests(ns): if getattr(module, '__file__', None): module.__file__ = os.path.abspath(module.__file__) - if ns.huntrleaks: - unittest.BaseTestSuite._cleanup = False - - if ns.memlimit is not None: - support.set_memlimit(ns.memlimit) - - if ns.threshold is not None: - gc.set_threshold(ns.threshold) - - support.suppress_msvcrt_asserts(ns.verbose and ns.verbose >= 2) - - support.use_resources = ns.use_resources - if hasattr(sys, 'addaudithook'): # Add an auditing hook for all tests to ensure PySys_Audit is tested def _test_audit_hook(name, args): @@ -88,21 +79,6 @@ def _test_audit_hook(name, args): setup_unraisable_hook() setup_threading_excepthook() - if ns.timeout is not None: - # For a slow buildbot worker, increase SHORT_TIMEOUT and LONG_TIMEOUT - support.SHORT_TIMEOUT = max(support.SHORT_TIMEOUT, ns.timeout / 40) - support.LONG_TIMEOUT = max(support.LONG_TIMEOUT, ns.timeout / 4) - - # If --timeout is short: reduce timeouts - support.LOOPBACK_TIMEOUT = min(support.LOOPBACK_TIMEOUT, ns.timeout) - support.INTERNET_TIMEOUT = min(support.INTERNET_TIMEOUT, ns.timeout) - support.SHORT_TIMEOUT = min(support.SHORT_TIMEOUT, ns.timeout) - support.LONG_TIMEOUT = min(support.LONG_TIMEOUT, ns.timeout) - - if ns.xmlpath: - from test.support.testresult import RegressionTestResult - RegressionTestResult.USE_XML = True - # Ensure there's a non-ASCII character in env vars at all times to force # tests consider this case. See BPO-44647 for details. if TESTFN_UNDECODABLE and os.supports_bytes_environ: @@ -111,49 +87,47 @@ def _test_audit_hook(name, args): os.environ.setdefault(UNICODE_GUARD_ENV, FS_NONASCII) -def replace_stdout(): - """Set stdout encoder error handler to backslashreplace (as stderr error - handler) to avoid UnicodeEncodeError when printing a traceback""" - stdout = sys.stdout - try: - fd = stdout.fileno() - except ValueError: - # On IDLE, sys.stdout has no file descriptor and is not a TextIOWrapper - # object. Leaving sys.stdout unchanged. - # - # Catch ValueError to catch io.UnsupportedOperation on TextIOBase - # and ValueError on a closed stream. - return +def setup_tests(runtests: RunTests): + support.verbose = runtests.verbose + support.failfast = runtests.fail_fast + support.PGO = runtests.pgo + support.PGO_EXTENDED = runtests.pgo_extended - sys.stdout = open(fd, 'w', - encoding=stdout.encoding, - errors="backslashreplace", - closefd=False, - newline='\n') + set_match_tests(runtests.match_tests) - def restore_stdout(): - sys.stdout.close() - sys.stdout = stdout - atexit.register(restore_stdout) + if runtests.use_junit: + support.junit_xml_list = [] + from .testresult import RegressionTestResult + RegressionTestResult.USE_XML = True + else: + support.junit_xml_list = None + if runtests.memory_limit is not None: + support.set_memlimit(runtests.memory_limit) -def _adjust_resource_limits(): - """Adjust the system resource limits (ulimit) if needed.""" - try: - import resource - from resource import RLIMIT_NOFILE - except ImportError: - return - fd_limit, max_fds = resource.getrlimit(RLIMIT_NOFILE) - # On macOS the default fd limit is sometimes too low (256) for our - # test suite to succeed. Raise it to something more reasonable. - # 1024 is a common Linux default. - desired_fds = 1024 - if fd_limit < desired_fds and fd_limit < max_fds: - new_fd_limit = min(desired_fds, max_fds) - try: - resource.setrlimit(RLIMIT_NOFILE, (new_fd_limit, max_fds)) - print(f"Raised RLIMIT_NOFILE: {fd_limit} -> {new_fd_limit}") - except (ValueError, OSError) as err: - print(f"Unable to raise RLIMIT_NOFILE from {fd_limit} to " - f"{new_fd_limit}: {err}.") + support.suppress_msvcrt_asserts(runtests.verbose >= 2) + + support.use_resources = runtests.use_resources + + timeout = runtests.timeout + if timeout is not None: + # For a slow buildbot worker, increase SHORT_TIMEOUT and LONG_TIMEOUT + support.LOOPBACK_TIMEOUT = max(support.LOOPBACK_TIMEOUT, timeout / 120) + # don't increase INTERNET_TIMEOUT + support.SHORT_TIMEOUT = max(support.SHORT_TIMEOUT, timeout / 40) + support.LONG_TIMEOUT = max(support.LONG_TIMEOUT, timeout / 4) + + # If --timeout is short: reduce timeouts + support.LOOPBACK_TIMEOUT = min(support.LOOPBACK_TIMEOUT, timeout) + support.INTERNET_TIMEOUT = min(support.INTERNET_TIMEOUT, timeout) + support.SHORT_TIMEOUT = min(support.SHORT_TIMEOUT, timeout) + support.LONG_TIMEOUT = min(support.LONG_TIMEOUT, timeout) + + if runtests.hunt_refleak: + # private attribute that mypy doesn't know about: + unittest.BaseTestSuite._cleanup = False # type: ignore[attr-defined] + + if runtests.gc_threshold is not None: + gc.set_threshold(runtests.gc_threshold) + + random.seed(runtests.random_seed) diff --git a/Lib/test/libregrtest/single.py b/Lib/test/libregrtest/single.py new file mode 100644 index 00000000000000..235029d8620ff5 --- /dev/null +++ b/Lib/test/libregrtest/single.py @@ -0,0 +1,318 @@ +import faulthandler +import gc +import importlib +import io +import sys +import time +import traceback +import unittest + +from test import support +from test.support import threading_helper + +from .filter import match_test +from .result import State, TestResult, TestStats +from .runtests import RunTests +from .save_env import saved_test_environment +from .setup import setup_tests +from .testresult import get_test_runner +from .utils import ( + TestName, + clear_caches, remove_testfn, abs_module_name, print_warning) + + +# Minimum duration of a test to display its duration or to mention that +# the test is running in background +PROGRESS_MIN_TIME = 30.0 # seconds + + +def run_unittest(test_mod): + loader = unittest.TestLoader() + tests = loader.loadTestsFromModule(test_mod) + for error in loader.errors: + print(error, file=sys.stderr) + if loader.errors: + raise Exception("errors while loading tests") + _filter_suite(tests, match_test) + return _run_suite(tests) + +def _filter_suite(suite, pred): + """Recursively filter test cases in a suite based on a predicate.""" + newtests = [] + for test in suite._tests: + if isinstance(test, unittest.TestSuite): + _filter_suite(test, pred) + newtests.append(test) + else: + if pred(test): + newtests.append(test) + suite._tests = newtests + +def _run_suite(suite): + """Run tests from a unittest.TestSuite-derived class.""" + runner = get_test_runner(sys.stdout, + verbosity=support.verbose, + capture_output=(support.junit_xml_list is not None)) + + result = runner.run(suite) + + if support.junit_xml_list is not None: + support.junit_xml_list.append(result.get_xml_element()) + + if not result.testsRun and not result.skipped and not result.errors: + raise support.TestDidNotRun + if not result.wasSuccessful(): + stats = TestStats.from_unittest(result) + if len(result.errors) == 1 and not result.failures: + err = result.errors[0][1] + elif len(result.failures) == 1 and not result.errors: + err = result.failures[0][1] + else: + err = "multiple errors occurred" + if not support.verbose: err += "; run in verbose mode for details" + errors = [(str(tc), exc_str) for tc, exc_str in result.errors] + failures = [(str(tc), exc_str) for tc, exc_str in result.failures] + raise support.TestFailedWithDetails(err, errors, failures, stats=stats) + return result + + +def regrtest_runner(result: TestResult, test_func, runtests: RunTests) -> None: + # Run test_func(), collect statistics, and detect reference and memory + # leaks. + if runtests.hunt_refleak: + from .refleak import runtest_refleak + refleak, test_result = runtest_refleak(result.test_name, test_func, + runtests.hunt_refleak, + runtests.quiet) + else: + test_result = test_func() + refleak = False + + if refleak: + result.state = State.REFLEAK + + stats: TestStats | None + + match test_result: + case TestStats(): + stats = test_result + case unittest.TestResult(): + stats = TestStats.from_unittest(test_result) + case None: + print_warning(f"{result.test_name} test runner returned None: {test_func}") + stats = None + case _: + # Don't import doctest at top level since only few tests return + # a doctest.TestResult instance. + import doctest + if isinstance(test_result, doctest.TestResults): + stats = TestStats.from_doctest(test_result) + else: + print_warning(f"Unknown test result type: {type(test_result)}") + stats = None + + result.stats = stats + + +# Storage of uncollectable GC objects (gc.garbage) +GC_GARBAGE = [] + + +def _load_run_test(result: TestResult, runtests: RunTests) -> None: + # Load the test module and run the tests. + test_name = result.test_name + module_name = abs_module_name(test_name, runtests.test_dir) + test_mod = importlib.import_module(module_name) + + if hasattr(test_mod, "test_main"): + # https://github.com/python/cpython/issues/89392 + raise Exception(f"Module {test_name} defines test_main() which " + f"is no longer supported by regrtest") + def test_func(): + return run_unittest(test_mod) + + try: + regrtest_runner(result, test_func, runtests) + finally: + # First kill any dangling references to open files etc. + # This can also issue some ResourceWarnings which would otherwise get + # triggered during the following test run, and possibly produce + # failures. + support.gc_collect() + + remove_testfn(test_name, runtests.verbose) + + if gc.garbage: + support.environment_altered = True + print_warning(f"{test_name} created {len(gc.garbage)} " + f"uncollectable object(s)") + + # move the uncollectable objects somewhere, + # so we don't see them again + GC_GARBAGE.extend(gc.garbage) + gc.garbage.clear() + + support.reap_children() + + +def _runtest_env_changed_exc(result: TestResult, runtests: RunTests, + display_failure: bool = True) -> None: + # Handle exceptions, detect environment changes. + + # Reset the environment_altered flag to detect if a test altered + # the environment + support.environment_altered = False + + pgo = runtests.pgo + if pgo: + display_failure = False + quiet = runtests.quiet + + test_name = result.test_name + try: + clear_caches() + support.gc_collect() + + with saved_test_environment(test_name, + runtests.verbose, quiet, pgo=pgo): + _load_run_test(result, runtests) + except support.ResourceDenied as exc: + if not quiet and not pgo: + print(f"{test_name} skipped -- {exc}", flush=True) + result.state = State.RESOURCE_DENIED + return + except unittest.SkipTest as exc: + if not quiet and not pgo: + print(f"{test_name} skipped -- {exc}", flush=True) + result.state = State.SKIPPED + return + except support.TestFailedWithDetails as exc: + msg = f"test {test_name} failed" + if display_failure: + msg = f"{msg} -- {exc}" + print(msg, file=sys.stderr, flush=True) + result.state = State.FAILED + result.errors = exc.errors + result.failures = exc.failures + result.stats = exc.stats + return + except support.TestFailed as exc: + msg = f"test {test_name} failed" + if display_failure: + msg = f"{msg} -- {exc}" + print(msg, file=sys.stderr, flush=True) + result.state = State.FAILED + result.stats = exc.stats + return + except support.TestDidNotRun: + result.state = State.DID_NOT_RUN + return + except KeyboardInterrupt: + print() + result.state = State.INTERRUPTED + return + except: + if not pgo: + msg = traceback.format_exc() + print(f"test {test_name} crashed -- {msg}", + file=sys.stderr, flush=True) + result.state = State.UNCAUGHT_EXC + return + + if support.environment_altered: + result.set_env_changed() + # Don't override the state if it was already set (REFLEAK or ENV_CHANGED) + if result.state is None: + result.state = State.PASSED + + +def _runtest(result: TestResult, runtests: RunTests) -> None: + # Capture stdout and stderr, set faulthandler timeout, + # and create JUnit XML report. + verbose = runtests.verbose + output_on_failure = runtests.output_on_failure + timeout = runtests.timeout + + if timeout is not None and threading_helper.can_start_thread: + use_timeout = True + faulthandler.dump_traceback_later(timeout, exit=True) + else: + use_timeout = False + + try: + setup_tests(runtests) + + if output_on_failure: + support.verbose = True + + stream = io.StringIO() + orig_stdout = sys.stdout + orig_stderr = sys.stderr + print_warning = support.print_warning + orig_print_warnings_stderr = print_warning.orig_stderr + + output = None + try: + sys.stdout = stream + sys.stderr = stream + # print_warning() writes into the temporary stream to preserve + # messages order. If support.environment_altered becomes true, + # warnings will be written to sys.stderr below. + print_warning.orig_stderr = stream + + _runtest_env_changed_exc(result, runtests, display_failure=False) + # Ignore output if the test passed successfully + if result.state != State.PASSED: + output = stream.getvalue() + finally: + sys.stdout = orig_stdout + sys.stderr = orig_stderr + print_warning.orig_stderr = orig_print_warnings_stderr + + if output is not None: + sys.stderr.write(output) + sys.stderr.flush() + else: + # Tell tests to be moderately quiet + support.verbose = verbose + _runtest_env_changed_exc(result, runtests, + display_failure=not verbose) + + xml_list = support.junit_xml_list + if xml_list: + import xml.etree.ElementTree as ET + result.xml_data = [ET.tostring(x).decode('us-ascii') + for x in xml_list] + finally: + if use_timeout: + faulthandler.cancel_dump_traceback_later() + support.junit_xml_list = None + + +def run_single_test(test_name: TestName, runtests: RunTests) -> TestResult: + """Run a single test. + + test_name -- the name of the test + + Returns a TestResult. + + If runtests.use_junit, xml_data is a list containing each generated + testsuite element. + """ + start_time = time.perf_counter() + result = TestResult(test_name) + pgo = runtests.pgo + try: + _runtest(result, runtests) + except: + if not pgo: + msg = traceback.format_exc() + print(f"test {test_name} crashed -- {msg}", + file=sys.stderr, flush=True) + result.state = State.UNCAUGHT_EXC + + sys.stdout.flush() + sys.stderr.flush() + + result.duration = time.perf_counter() - start_time + return result diff --git a/Lib/test/support/testresult.py b/Lib/test/libregrtest/testresult.py similarity index 98% rename from Lib/test/support/testresult.py rename to Lib/test/libregrtest/testresult.py index 14474be222dc4b..de23fdd59ded95 100644 --- a/Lib/test/support/testresult.py +++ b/Lib/test/libregrtest/testresult.py @@ -8,6 +8,7 @@ import time import traceback import unittest +from test import support class RegressionTestResult(unittest.TextTestResult): USE_XML = False @@ -112,6 +113,8 @@ def addExpectedFailure(self, test, err): def addFailure(self, test, err): self._add_result(test, True, failure=self.__makeErrorDict(*err)) super().addFailure(test, err) + if support.failfast: + self.stop() def addSkip(self, test, reason): self._add_result(test, skipped=reason) diff --git a/Lib/test/libregrtest/utils.py b/Lib/test/libregrtest/utils.py index fd46819fd903fe..b30025d962413c 100644 --- a/Lib/test/libregrtest/utils.py +++ b/Lib/test/libregrtest/utils.py @@ -1,9 +1,60 @@ +import contextlib +import faulthandler +import locale import math import os.path +import platform +import random +import shlex +import signal +import subprocess import sys import sysconfig +import tempfile import textwrap +from collections.abc import Callable, Iterable + from test import support +from test.support import os_helper +from test.support import threading_helper + + +# All temporary files and temporary directories created by libregrtest should +# use TMP_PREFIX so cleanup_temp_dir() can remove them all. +TMP_PREFIX = 'test_python_' +WORK_DIR_PREFIX = TMP_PREFIX +WORKER_WORK_DIR_PREFIX = WORK_DIR_PREFIX + 'worker_' + +# bpo-38203: Maximum delay in seconds to exit Python (call Py_Finalize()). +# Used to protect against threading._shutdown() hang. +# Must be smaller than buildbot "1200 seconds without output" limit. +EXIT_TIMEOUT = 120.0 + + +ALL_RESOURCES = ('audio', 'curses', 'largefile', 'network', + 'decimal', 'cpu', 'subprocess', 'urlfetch', 'gui', 'walltime') + +# Other resources excluded from --use=all: +# +# - extralagefile (ex: test_zipfile64): really too slow to be enabled +# "by default" +# - tzdata: while needed to validate fully test_datetime, it makes +# test_datetime too slow (15-20 min on some buildbots) and so is disabled by +# default (see bpo-30822). +RESOURCE_NAMES = ALL_RESOURCES + ('extralargefile', 'tzdata') + + +# Types for types hints +StrPath = str +TestName = str +StrJSON = str +TestTuple = tuple[TestName, ...] +TestList = list[TestName] +# --match and --ignore options: list of patterns +# ('*' joker character can be used) +TestFilter = list[tuple[TestName, bool]] +FilterTuple = tuple[TestName, ...] +FilterDict = dict[TestName, FilterTuple] def format_duration(seconds): @@ -31,7 +82,7 @@ def format_duration(seconds): return ' '.join(parts) -def removepy(names): +def strip_py_suffix(names: list[str] | None) -> None: if not names: return for idx, name in enumerate(names): @@ -40,11 +91,20 @@ def removepy(names): names[idx] = basename +def plural(n, singular, plural=None): + if n == 1: + return singular + elif plural is not None: + return plural + else: + return singular + 's' + + def count(n, word): if n == 1: - return "%d %s" % (n, word) + return f"{n} {word}" else: - return "%d %ss" % (n, word) + return f"{n} {word}s" def printlist(x, width=70, indent=4, file=None): @@ -228,6 +288,11 @@ def get_build_info(): ldflags_nodist = sysconfig.get_config_var('PY_LDFLAGS_NODIST') or '' build = [] + + # --disable-gil + if sysconfig.get_config_var('Py_GIL_DISABLED'): + build.append("free_threading") + if hasattr(sys, 'gettotalrefcount'): # --with-pydebug build.append('debug') @@ -259,16 +324,8 @@ def get_build_info(): elif '-flto' in ldflags_nodist: optimizations.append('LTO') - # --enable-optimizations - pgo_options = ( - # GCC - '-fprofile-use', - # clang: -fprofile-instr-use=code.profclangd - '-fprofile-instr-use', - # ICC - "-prof-use", - ) - if any(option in cflags_nodist for option in pgo_options): + if support.check_cflags_pgo(): + # PGO (--enable-optimizations) optimizations.append('PGO') if optimizations: build.append('+'.join(optimizations)) @@ -283,6 +340,9 @@ def get_build_info(): # --with-undefined-behavior-sanitizer if support.check_sanitizer(ub=True): sanitizers.append("UBSAN") + # --with-thread-sanitizer + if support.check_sanitizer(thread=True): + sanitizers.append("TSAN") if sanitizers: build.append('+'.join(sanitizers)) @@ -300,3 +360,338 @@ def get_build_info(): build.append("dtrace") return build + + +def get_temp_dir(tmp_dir: StrPath | None = None) -> StrPath: + if tmp_dir: + tmp_dir = os.path.expanduser(tmp_dir) + else: + # When tests are run from the Python build directory, it is best practice + # to keep the test files in a subfolder. This eases the cleanup of leftover + # files using the "make distclean" command. + if sysconfig.is_python_build(): + if not support.is_wasi: + tmp_dir = sysconfig.get_config_var('abs_builddir') + if tmp_dir is None: + tmp_dir = sysconfig.get_config_var('abs_srcdir') + if not tmp_dir: + # gh-74470: On Windows, only srcdir is available. Using + # abs_builddir mostly matters on UNIX when building + # Python out of the source tree, especially when the + # source tree is read only. + tmp_dir = sysconfig.get_config_var('srcdir') + if not tmp_dir: + raise RuntimeError( + "Could not determine the correct value for tmp_dir" + ) + tmp_dir = os.path.join(tmp_dir, 'build') + else: + # WASI platform + tmp_dir = sysconfig.get_config_var('projectbase') + if not tmp_dir: + raise RuntimeError( + "sysconfig.get_config_var('projectbase') " + f"unexpectedly returned {tmp_dir!r} on WASI" + ) + tmp_dir = os.path.join(tmp_dir, 'build') + + # When get_temp_dir() is called in a worker process, + # get_temp_dir() path is different than in the parent process + # which is not a WASI process. So the parent does not create + # the same "tmp_dir" than the test worker process. + os.makedirs(tmp_dir, exist_ok=True) + else: + tmp_dir = tempfile.gettempdir() + + return os.path.abspath(tmp_dir) + + +def fix_umask(): + if support.is_emscripten: + # Emscripten has default umask 0o777, which breaks some tests. + # see https://github.com/emscripten-core/emscripten/issues/17269 + old_mask = os.umask(0) + if old_mask == 0o777: + os.umask(0o027) + else: + os.umask(old_mask) + + +def get_work_dir(parent_dir: StrPath, worker: bool = False) -> StrPath: + # Define a writable temp dir that will be used as cwd while running + # the tests. The name of the dir includes the pid to allow parallel + # testing (see the -j option). + # Emscripten and WASI have stubbed getpid(), Emscripten has only + # milisecond clock resolution. Use randint() instead. + if support.is_emscripten or support.is_wasi: + nounce = random.randint(0, 1_000_000) + else: + nounce = os.getpid() + + if worker: + work_dir = WORK_DIR_PREFIX + str(nounce) + else: + work_dir = WORKER_WORK_DIR_PREFIX + str(nounce) + work_dir += os_helper.FS_NONASCII + work_dir = os.path.join(parent_dir, work_dir) + return work_dir + + +@contextlib.contextmanager +def exit_timeout(): + try: + yield + except SystemExit as exc: + # bpo-38203: Python can hang at exit in Py_Finalize(), especially + # on threading._shutdown() call: put a timeout + if threading_helper.can_start_thread: + faulthandler.dump_traceback_later(EXIT_TIMEOUT, exit=True) + sys.exit(exc.code) + + +def remove_testfn(test_name: TestName, verbose: int) -> None: + # Try to clean up os_helper.TESTFN if left behind. + # + # While tests shouldn't leave any files or directories behind, when a test + # fails that can be tedious for it to arrange. The consequences can be + # especially nasty on Windows, since if a test leaves a file open, it + # cannot be deleted by name (while there's nothing we can do about that + # here either, we can display the name of the offending test, which is a + # real help). + name = os_helper.TESTFN + if not os.path.exists(name): + return + + nuker: Callable[[str], None] + if os.path.isdir(name): + import shutil + kind, nuker = "directory", shutil.rmtree + elif os.path.isfile(name): + kind, nuker = "file", os.unlink + else: + raise RuntimeError(f"os.path says {name!r} exists but is neither " + f"directory nor file") + + if verbose: + print_warning(f"{test_name} left behind {kind} {name!r}") + support.environment_altered = True + + try: + import stat + # fix possible permissions problems that might prevent cleanup + os.chmod(name, stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO) + nuker(name) + except Exception as exc: + print_warning(f"{test_name} left behind {kind} {name!r} " + f"and it couldn't be removed: {exc}") + + +def abs_module_name(test_name: TestName, test_dir: StrPath | None) -> TestName: + if test_name.startswith('test.') or test_dir: + return test_name + else: + # Import it from the test package + return 'test.' + test_name + + +# gh-90681: When rerunning tests, we might need to rerun the whole +# class or module suite if some its life-cycle hooks fail. +# Test level hooks are not affected. +_TEST_LIFECYCLE_HOOKS = frozenset(( + 'setUpClass', 'tearDownClass', + 'setUpModule', 'tearDownModule', +)) + +def normalize_test_name(test_full_name, *, is_error=False): + short_name = test_full_name.split(" ")[0] + if is_error and short_name in _TEST_LIFECYCLE_HOOKS: + if test_full_name.startswith(('setUpModule (', 'tearDownModule (')): + # if setUpModule() or tearDownModule() failed, don't filter + # tests with the test file name, don't use use filters. + return None + + # This means that we have a failure in a life-cycle hook, + # we need to rerun the whole module or class suite. + # Basically the error looks like this: + # ERROR: setUpClass (test.test_reg_ex.RegTest) + # or + # ERROR: setUpModule (test.test_reg_ex) + # So, we need to parse the class / module name. + lpar = test_full_name.index('(') + rpar = test_full_name.index(')') + return test_full_name[lpar + 1: rpar].split('.')[-1] + return short_name + + +def adjust_rlimit_nofile(): + """ + On macOS the default fd limit (RLIMIT_NOFILE) is sometimes too low (256) + for our test suite to succeed. Raise it to something more reasonable. 1024 + is a common Linux default. + """ + try: + import resource + except ImportError: + return + + fd_limit, max_fds = resource.getrlimit(resource.RLIMIT_NOFILE) + + desired_fds = 1024 + + if fd_limit < desired_fds and fd_limit < max_fds: + new_fd_limit = min(desired_fds, max_fds) + try: + resource.setrlimit(resource.RLIMIT_NOFILE, + (new_fd_limit, max_fds)) + print(f"Raised RLIMIT_NOFILE: {fd_limit} -> {new_fd_limit}") + except (ValueError, OSError) as err: + print_warning(f"Unable to raise RLIMIT_NOFILE from {fd_limit} to " + f"{new_fd_limit}: {err}.") + + +def get_host_runner(): + if (hostrunner := os.environ.get("_PYTHON_HOSTRUNNER")) is None: + hostrunner = sysconfig.get_config_var("HOSTRUNNER") + return hostrunner + + +def is_cross_compiled(): + return ('_PYTHON_HOST_PLATFORM' in os.environ) + + +def format_resources(use_resources: Iterable[str]): + use_resources = set(use_resources) + all_resources = set(ALL_RESOURCES) + + # Express resources relative to "all" + relative_all = ['all'] + for name in sorted(all_resources - use_resources): + relative_all.append(f'-{name}') + for name in sorted(use_resources - all_resources): + relative_all.append(f'{name}') + all_text = ','.join(relative_all) + all_text = f"resources: {all_text}" + + # List of enabled resources + text = ','.join(sorted(use_resources)) + text = f"resources ({len(use_resources)}): {text}" + + # Pick the shortest string (prefer relative to all if lengths are equal) + if len(all_text) <= len(text): + return all_text + else: + return text + + +def display_header(use_resources: tuple[str, ...], + python_cmd: tuple[str, ...] | None): + # Print basic platform information + print("==", platform.python_implementation(), *sys.version.split()) + print("==", platform.platform(aliased=True), + "%s-endian" % sys.byteorder) + print("== Python build:", ' '.join(get_build_info())) + print("== cwd:", os.getcwd()) + + cpu_count: object = os.cpu_count() + if cpu_count: + # The function is new in Python 3.13; mypy doesn't know about it yet: + process_cpu_count = os.process_cpu_count() # type: ignore[attr-defined] + if process_cpu_count and process_cpu_count != cpu_count: + cpu_count = f"{process_cpu_count} (process) / {cpu_count} (system)" + print("== CPU count:", cpu_count) + print("== encodings: locale=%s FS=%s" + % (locale.getencoding(), sys.getfilesystemencoding())) + + if use_resources: + text = format_resources(use_resources) + print(f"== {text}") + else: + print("== resources: all test resources are disabled, " + "use -u option to unskip tests") + + cross_compile = is_cross_compiled() + if cross_compile: + print("== cross compiled: Yes") + if python_cmd: + cmd = shlex.join(python_cmd) + print(f"== host python: {cmd}") + + get_cmd = [*python_cmd, '-m', 'platform'] + proc = subprocess.run( + get_cmd, + stdout=subprocess.PIPE, + text=True, + cwd=os_helper.SAVEDCWD) + stdout = proc.stdout.replace('\n', ' ').strip() + if stdout: + print(f"== host platform: {stdout}") + elif proc.returncode: + print(f"== host platform: ") + else: + hostrunner = get_host_runner() + if hostrunner: + print(f"== host runner: {hostrunner}") + + # This makes it easier to remember what to set in your local + # environment when trying to reproduce a sanitizer failure. + asan = support.check_sanitizer(address=True) + msan = support.check_sanitizer(memory=True) + ubsan = support.check_sanitizer(ub=True) + tsan = support.check_sanitizer(thread=True) + sanitizers = [] + if asan: + sanitizers.append("address") + if msan: + sanitizers.append("memory") + if ubsan: + sanitizers.append("undefined behavior") + if tsan: + sanitizers.append("thread") + if sanitizers: + print(f"== sanitizers: {', '.join(sanitizers)}") + for sanitizer, env_var in ( + (asan, "ASAN_OPTIONS"), + (msan, "MSAN_OPTIONS"), + (ubsan, "UBSAN_OPTIONS"), + (tsan, "TSAN_OPTIONS"), + ): + options= os.environ.get(env_var) + if sanitizer and options is not None: + print(f"== {env_var}={options!r}") + + print(flush=True) + + +def cleanup_temp_dir(tmp_dir: StrPath): + import glob + + path = os.path.join(glob.escape(tmp_dir), TMP_PREFIX + '*') + print("Cleanup %s directory" % tmp_dir) + for name in glob.glob(path): + if os.path.isdir(name): + print("Remove directory: %s" % name) + os_helper.rmtree(name) + else: + print("Remove file: %s" % name) + os_helper.unlink(name) + +WINDOWS_STATUS = { + 0xC0000005: "STATUS_ACCESS_VIOLATION", + 0xC00000FD: "STATUS_STACK_OVERFLOW", + 0xC000013A: "STATUS_CONTROL_C_EXIT", +} + +def get_signal_name(exitcode): + if exitcode < 0: + signum = -exitcode + try: + return signal.Signals(signum).name + except ValueError: + pass + + try: + return WINDOWS_STATUS[exitcode] + except KeyError: + pass + + return None diff --git a/Lib/test/libregrtest/worker.py b/Lib/test/libregrtest/worker.py new file mode 100644 index 00000000000000..7a6d33d4499943 --- /dev/null +++ b/Lib/test/libregrtest/worker.py @@ -0,0 +1,130 @@ +import subprocess +import sys +import os +from typing import Any, NoReturn + +from test import support +from test.support import os_helper, Py_DEBUG + +from .setup import setup_process, setup_test_dir +from .runtests import WorkerRunTests, JsonFile, JsonFileType +from .single import run_single_test +from .utils import ( + StrPath, StrJSON, TestFilter, + get_temp_dir, get_work_dir, exit_timeout) + + +USE_PROCESS_GROUP = (hasattr(os, "setsid") and hasattr(os, "killpg")) + + +def create_worker_process(runtests: WorkerRunTests, output_fd: int, + tmp_dir: StrPath | None = None) -> subprocess.Popen: + python_cmd = runtests.python_cmd + worker_json = runtests.as_json() + + python_opts = support.args_from_interpreter_flags() + if python_cmd is not None: + executable = python_cmd + # Remove -E option, since --python=COMMAND can set PYTHON environment + # variables, such as PYTHONPATH, in the worker process. + python_opts = [opt for opt in python_opts if opt != "-E"] + else: + executable = (sys.executable,) + if runtests.coverage: + python_opts.append("-Xpresite=test.cov") + cmd = [*executable, *python_opts, + '-u', # Unbuffered stdout and stderr + '-m', 'test.libregrtest.worker', + worker_json] + + env = dict(os.environ) + if tmp_dir is not None: + env['TMPDIR'] = tmp_dir + env['TEMP'] = tmp_dir + env['TMP'] = tmp_dir + + # Running the child from the same working directory as regrtest's original + # invocation ensures that TEMPDIR for the child is the same when + # sysconfig.is_python_build() is true. See issue 15300. + # + # Emscripten and WASI Python must start in the Python source code directory + # to get 'python.js' or 'python.wasm' file. Then worker_process() changes + # to a temporary directory created to run tests. + work_dir = os_helper.SAVEDCWD + + kwargs: dict[str, Any] = dict( + env=env, + stdout=output_fd, + # bpo-45410: Write stderr into stdout to keep messages order + stderr=output_fd, + text=True, + close_fds=True, + cwd=work_dir, + ) + if USE_PROCESS_GROUP: + kwargs['start_new_session'] = True + + # Pass json_file to the worker process + json_file = runtests.json_file + json_file.configure_subprocess(kwargs) + + with json_file.inherit_subprocess(): + return subprocess.Popen(cmd, **kwargs) + + +def worker_process(worker_json: StrJSON) -> NoReturn: + runtests = WorkerRunTests.from_json(worker_json) + test_name = runtests.tests[0] + match_tests: TestFilter = runtests.match_tests + json_file: JsonFile = runtests.json_file + + setup_test_dir(runtests.test_dir) + setup_process() + + if runtests.rerun: + if match_tests: + matching = "matching: " + ", ".join(pattern for pattern, result in match_tests if result) + print(f"Re-running {test_name} in verbose mode ({matching})", flush=True) + else: + print(f"Re-running {test_name} in verbose mode", flush=True) + + result = run_single_test(test_name, runtests) + if runtests.coverage: + if "test.cov" in sys.modules: # imported by -Xpresite= + result.covered_lines = list(sys.modules["test.cov"].coverage) + elif not Py_DEBUG: + print( + "Gathering coverage in worker processes requires --with-pydebug", + flush=True, + ) + else: + raise LookupError( + "`test.cov` not found in sys.modules but coverage wanted" + ) + + if json_file.file_type == JsonFileType.STDOUT: + print() + result.write_json_into(sys.stdout) + else: + with json_file.open('w', encoding='utf-8') as json_fp: + result.write_json_into(json_fp) + + sys.exit(0) + + +def main(): + if len(sys.argv) != 2: + print("usage: python -m test.libregrtest.worker JSON") + sys.exit(1) + worker_json = sys.argv[1] + + tmp_dir = get_temp_dir() + work_dir = get_work_dir(tmp_dir, worker=True) + + with exit_timeout(): + with os_helper.temp_cwd(work_dir, quiet=True): + worker_process(worker_json) + + +if __name__ == "__main__": + main() diff --git a/Lib/test/list_tests.py b/Lib/test/list_tests.py index b1ef332522d2ce..d9ab21d4941cdb 100644 --- a/Lib/test/list_tests.py +++ b/Lib/test/list_tests.py @@ -6,7 +6,7 @@ from functools import cmp_to_key from test import seq_tests -from test.support import ALWAYS_EQ, NEVER_EQ, C_RECURSION_LIMIT +from test.support import ALWAYS_EQ, NEVER_EQ, Py_C_RECURSION_LIMIT class CommonTest(seq_tests.CommonTest): @@ -61,7 +61,7 @@ def test_repr(self): def test_repr_deep(self): a = self.type2test([]) - for i in range(C_RECURSION_LIMIT + 1): + for i in range(Py_C_RECURSION_LIMIT + 1): a = self.type2test([a]) self.assertRaises(RecursionError, repr, a) diff --git a/Lib/test/lock_tests.py b/Lib/test/lock_tests.py index a4f52cb20ad301..024c6debcd4a54 100644 --- a/Lib/test/lock_tests.py +++ b/Lib/test/lock_tests.py @@ -19,54 +19,74 @@ "(no _at_fork_reinit method)") -def _wait(): - # A crude wait/yield function not relying on synchronization primitives. - time.sleep(0.01) +def wait_threads_blocked(nthread): + # Arbitrary sleep to wait until N threads are blocked, + # like waiting for a lock. + time.sleep(0.010 * nthread) + class Bunch(object): """ A bunch of threads. """ - def __init__(self, f, n, wait_before_exit=False): + def __init__(self, func, nthread, wait_before_exit=False): """ - Construct a bunch of `n` threads running the same function `f`. + Construct a bunch of `nthread` threads running the same function `func`. If `wait_before_exit` is True, the threads won't terminate until do_finish() is called. """ - self.f = f - self.n = n + self.func = func + self.nthread = nthread self.started = [] self.finished = [] + self.exceptions = [] self._can_exit = not wait_before_exit - self.wait_thread = threading_helper.wait_threads_exit() - self.wait_thread.__enter__() + self._wait_thread = None - def task(): - tid = threading.get_ident() - self.started.append(tid) - try: - f() - finally: - self.finished.append(tid) - while not self._can_exit: - _wait() + def task(self): + tid = threading.get_ident() + self.started.append(tid) + try: + self.func() + except BaseException as exc: + self.exceptions.append(exc) + finally: + self.finished.append(tid) + for _ in support.sleeping_retry(support.SHORT_TIMEOUT): + if self._can_exit: + break + + def __enter__(self): + self._wait_thread = threading_helper.wait_threads_exit(support.SHORT_TIMEOUT) + self._wait_thread.__enter__() try: - for i in range(n): - start_new_thread(task, ()) + for _ in range(self.nthread): + start_new_thread(self.task, ()) except: self._can_exit = True raise - def wait_for_started(self): - while len(self.started) < self.n: - _wait() + for _ in support.sleeping_retry(support.SHORT_TIMEOUT): + if len(self.started) >= self.nthread: + break + + return self + + def __exit__(self, exc_type, exc_value, traceback): + for _ in support.sleeping_retry(support.SHORT_TIMEOUT): + if len(self.finished) >= self.nthread: + break + + # Wait until threads completely exit according to _thread._count() + self._wait_thread.__exit__(None, None, None) - def wait_for_finished(self): - while len(self.finished) < self.n: - _wait() - # Wait for threads exit - self.wait_thread.__exit__(None, None, None) + # Break reference cycle + exceptions = self.exceptions + self.exceptions = None + if exceptions: + raise ExceptionGroup(f"{self.func} threads raised exceptions", + exceptions) def do_finish(self): self._can_exit = True @@ -94,6 +114,12 @@ class BaseLockTests(BaseTestCase): Tests for both recursive and non-recursive locks. """ + def wait_phase(self, phase, expected): + for _ in support.sleeping_retry(support.SHORT_TIMEOUT): + if len(phase) >= expected: + break + self.assertEqual(len(phase), expected) + def test_constructor(self): lock = self.locktype() del lock @@ -131,41 +157,57 @@ def test_try_acquire_contended(self): result = [] def f(): result.append(lock.acquire(False)) - Bunch(f, 1).wait_for_finished() + with Bunch(f, 1): + pass self.assertFalse(result[0]) lock.release() def test_acquire_contended(self): lock = self.locktype() lock.acquire() - N = 5 def f(): lock.acquire() lock.release() - b = Bunch(f, N) - b.wait_for_started() - _wait() - self.assertEqual(len(b.finished), 0) - lock.release() - b.wait_for_finished() - self.assertEqual(len(b.finished), N) + N = 5 + with Bunch(f, N) as bunch: + # Threads block on lock.acquire() + wait_threads_blocked(N) + self.assertEqual(len(bunch.finished), 0) + + # Threads unblocked + lock.release() + + self.assertEqual(len(bunch.finished), N) def test_with(self): lock = self.locktype() def f(): lock.acquire() lock.release() - def _with(err=None): + + def with_lock(err=None): with lock: if err is not None: raise err - _with() - # Check the lock is unacquired - Bunch(f, 1).wait_for_finished() - self.assertRaises(TypeError, _with, TypeError) - # Check the lock is unacquired - Bunch(f, 1).wait_for_finished() + + # Acquire the lock, do nothing, with releases the lock + with lock: + pass + + # Check that the lock is unacquired + with Bunch(f, 1): + pass + + # Acquire the lock, raise an exception, with releases the lock + with self.assertRaises(TypeError): + with lock: + raise TypeError + + # Check that the lock is unacquired even if after an exception + # was raised in the previous "with lock:" block + with Bunch(f, 1): + pass def test_thread_leak(self): # The lock shouldn't leak a Thread instance when used from a foreign @@ -174,17 +216,11 @@ def test_thread_leak(self): def f(): lock.acquire() lock.release() - n = len(threading.enumerate()) + # We run many threads in the hope that existing threads ids won't # be recycled. - Bunch(f, 15).wait_for_finished() - if len(threading.enumerate()) != n: - # There is a small window during which a Thread instance's - # target function has finished running, but the Thread is still - # alive and registered. Avoid spurious failures by waiting a - # bit more (seen on a buildbot). - time.sleep(0.4) - self.assertEqual(n, len(threading.enumerate())) + with Bunch(f, 15): + pass def test_timeout(self): lock = self.locktype() @@ -208,7 +244,8 @@ def f(): results.append(lock.acquire(timeout=0.5)) t2 = time.monotonic() results.append(t2 - t1) - Bunch(f, 1).wait_for_finished() + with Bunch(f, 1): + pass self.assertFalse(results[0]) self.assertTimeout(results[1], 0.5) @@ -242,15 +279,13 @@ def f(): phase.append(None) with threading_helper.wait_threads_exit(): + # Thread blocked on lock.acquire() start_new_thread(f, ()) - while len(phase) == 0: - _wait() - _wait() - self.assertEqual(len(phase), 1) + self.wait_phase(phase, 1) + + # Thread unblocked lock.release() - while len(phase) == 1: - _wait() - self.assertEqual(len(phase), 2) + self.wait_phase(phase, 2) def test_different_thread(self): # Lock can be released from a different thread. @@ -258,8 +293,8 @@ def test_different_thread(self): lock.acquire() def f(): lock.release() - b = Bunch(f, 1) - b.wait_for_finished() + with Bunch(f, 1): + pass lock.acquire() lock.release() @@ -330,17 +365,52 @@ def test_release_save_unacquired(self): lock.release() self.assertRaises(RuntimeError, lock._release_save) + def test_recursion_count(self): + lock = self.locktype() + self.assertEqual(0, lock._recursion_count()) + lock.acquire() + self.assertEqual(1, lock._recursion_count()) + lock.acquire() + lock.acquire() + self.assertEqual(3, lock._recursion_count()) + lock.release() + self.assertEqual(2, lock._recursion_count()) + lock.release() + lock.release() + self.assertEqual(0, lock._recursion_count()) + + phase = [] + + def f(): + lock.acquire() + phase.append(None) + + self.wait_phase(phase, 2) + lock.release() + phase.append(None) + + with threading_helper.wait_threads_exit(): + # Thread blocked on lock.acquire() + start_new_thread(f, ()) + self.wait_phase(phase, 1) + self.assertEqual(0, lock._recursion_count()) + + # Thread unblocked + phase.append(None) + self.wait_phase(phase, 3) + self.assertEqual(0, lock._recursion_count()) + def test_different_thread(self): # Cannot release from a different thread lock = self.locktype() def f(): lock.acquire() - b = Bunch(f, 1, True) - try: - self.assertRaises(RuntimeError, lock.release) - finally: - b.do_finish() - b.wait_for_finished() + + with Bunch(f, 1, True) as bunch: + try: + self.assertRaises(RuntimeError, lock.release) + finally: + bunch.do_finish() def test__is_owned(self): lock = self.locktype() @@ -352,7 +422,8 @@ def test__is_owned(self): result = [] def f(): result.append(lock._is_owned()) - Bunch(f, 1).wait_for_finished() + with Bunch(f, 1): + pass self.assertFalse(result[0]) lock.release() self.assertTrue(lock._is_owned()) @@ -385,12 +456,15 @@ def _check_notify(self, evt): def f(): results1.append(evt.wait()) results2.append(evt.wait()) - b = Bunch(f, N) - b.wait_for_started() - _wait() - self.assertEqual(len(results1), 0) - evt.set() - b.wait_for_finished() + + with Bunch(f, N): + # Threads blocked on first evt.wait() + wait_threads_blocked(N) + self.assertEqual(len(results1), 0) + + # Threads unblocked + evt.set() + self.assertEqual(results1, [True] * N) self.assertEqual(results2, [True] * N) @@ -413,35 +487,43 @@ def f(): r = evt.wait(0.5) t2 = time.monotonic() results2.append((r, t2 - t1)) - Bunch(f, N).wait_for_finished() + + with Bunch(f, N): + pass + self.assertEqual(results1, [False] * N) for r, dt in results2: self.assertFalse(r) self.assertTimeout(dt, 0.5) + # The event is set results1 = [] results2 = [] evt.set() - Bunch(f, N).wait_for_finished() + with Bunch(f, N): + pass + self.assertEqual(results1, [True] * N) for r, dt in results2: self.assertTrue(r) def test_set_and_clear(self): - # Issue #13502: check that wait() returns true even when the event is + # gh-57711: check that wait() returns true even when the event is # cleared before the waiting thread is woken up. - evt = self.eventtype() + event = self.eventtype() results = [] - timeout = 0.250 - N = 5 def f(): - results.append(evt.wait(timeout * 4)) - b = Bunch(f, N) - b.wait_for_started() - time.sleep(timeout) - evt.set() - evt.clear() - b.wait_for_finished() + results.append(event.wait(support.LONG_TIMEOUT)) + + N = 5 + with Bunch(f, N): + # Threads blocked on event.wait() + wait_threads_blocked(N) + + # Threads unblocked + event.set() + event.clear() + self.assertEqual(results, [True] * N) @requires_fork @@ -497,15 +579,14 @@ def _check_notify(self, cond): # Note that this test is sensitive to timing. If the worker threads # don't execute in a timely fashion, the main thread may think they # are further along then they are. The main thread therefore issues - # _wait() statements to try to make sure that it doesn't race ahead - # of the workers. + # wait_threads_blocked() statements to try to make sure that it doesn't + # race ahead of the workers. # Secondly, this test assumes that condition variables are not subject # to spurious wakeups. The absence of spurious wakeups is an implementation # detail of Condition Variables in current CPython, but in general, not # a guaranteed property of condition variables as a programming # construct. In particular, it is possible that this can no longer # be conveniently guaranteed should their implementation ever change. - N = 5 ready = [] results1 = [] results2 = [] @@ -514,58 +595,83 @@ def f(): cond.acquire() ready.append(phase_num) result = cond.wait() + cond.release() results1.append((result, phase_num)) + cond.acquire() ready.append(phase_num) + result = cond.wait() cond.release() results2.append((result, phase_num)) - b = Bunch(f, N) - b.wait_for_started() - # first wait, to ensure all workers settle into cond.wait() before - # we continue. See issues #8799 and #30727. - while len(ready) < 5: - _wait() - ready.clear() - self.assertEqual(results1, []) - # Notify 3 threads at first - cond.acquire() - cond.notify(3) - _wait() - phase_num = 1 - cond.release() - while len(results1) < 3: - _wait() - self.assertEqual(results1, [(True, 1)] * 3) - self.assertEqual(results2, []) - # make sure all awaken workers settle into cond.wait() - while len(ready) < 3: - _wait() - # Notify 5 threads: they might be in their first or second wait - cond.acquire() - cond.notify(5) - _wait() - phase_num = 2 - cond.release() - while len(results1) + len(results2) < 8: - _wait() - self.assertEqual(results1, [(True, 1)] * 3 + [(True, 2)] * 2) - self.assertEqual(results2, [(True, 2)] * 3) - # make sure all workers settle into cond.wait() - while len(ready) < 5: - _wait() - # Notify all threads: they are all in their second wait - cond.acquire() - cond.notify_all() - _wait() - phase_num = 3 - cond.release() - while len(results2) < 5: - _wait() - self.assertEqual(results1, [(True, 1)] * 3 + [(True,2)] * 2) - self.assertEqual(results2, [(True, 2)] * 3 + [(True, 3)] * 2) - b.wait_for_finished() + + N = 5 + with Bunch(f, N): + # first wait, to ensure all workers settle into cond.wait() before + # we continue. See issues #8799 and #30727. + for _ in support.sleeping_retry(support.SHORT_TIMEOUT): + if len(ready) >= N: + break + + ready.clear() + self.assertEqual(results1, []) + + # Notify 3 threads at first + count1 = 3 + cond.acquire() + cond.notify(count1) + wait_threads_blocked(count1) + + # Phase 1 + phase_num = 1 + cond.release() + for _ in support.sleeping_retry(support.SHORT_TIMEOUT): + if len(results1) >= count1: + break + + self.assertEqual(results1, [(True, 1)] * count1) + self.assertEqual(results2, []) + + # Wait until awaken workers are blocked on cond.wait() + for _ in support.sleeping_retry(support.SHORT_TIMEOUT): + if len(ready) >= count1 : + break + + # Notify 5 threads: they might be in their first or second wait + cond.acquire() + cond.notify(5) + wait_threads_blocked(N) + + # Phase 2 + phase_num = 2 + cond.release() + for _ in support.sleeping_retry(support.SHORT_TIMEOUT): + if len(results1) + len(results2) >= (N + count1): + break + + count2 = N - count1 + self.assertEqual(results1, [(True, 1)] * count1 + [(True, 2)] * count2) + self.assertEqual(results2, [(True, 2)] * count1) + + # Make sure all workers settle into cond.wait() + for _ in support.sleeping_retry(support.SHORT_TIMEOUT): + if len(ready) >= N: + break + + # Notify all threads: they are all in their second wait + cond.acquire() + cond.notify_all() + wait_threads_blocked(N) + + # Phase 3 + phase_num = 3 + cond.release() + for _ in support.sleeping_retry(support.SHORT_TIMEOUT): + if len(results2) >= N: + break + self.assertEqual(results1, [(True, 1)] * count1 + [(True, 2)] * count2) + self.assertEqual(results2, [(True, 2)] * count1 + [(True, 3)] * count2) def test_notify(self): cond = self.condtype() @@ -575,19 +681,23 @@ def test_notify(self): def test_timeout(self): cond = self.condtype() + timeout = 0.5 results = [] - N = 5 def f(): cond.acquire() t1 = time.monotonic() - result = cond.wait(0.5) + result = cond.wait(timeout) t2 = time.monotonic() cond.release() results.append((t2 - t1, result)) - Bunch(f, N).wait_for_finished() + + N = 5 + with Bunch(f, N): + pass self.assertEqual(len(results), N) + for dt, result in results: - self.assertTimeout(dt, 0.5) + self.assertTimeout(dt, timeout) # Note that conceptually (that"s the condition variable protocol) # a wait() may succeed even if no one notifies us and before any # timeout occurs. Spurious wakeups can occur. @@ -600,17 +710,16 @@ def test_waitfor(self): state = 0 def f(): with cond: - result = cond.wait_for(lambda : state==4) + result = cond.wait_for(lambda: state == 4) self.assertTrue(result) self.assertEqual(state, 4) - b = Bunch(f, 1) - b.wait_for_started() - for i in range(4): - time.sleep(0.01) - with cond: - state += 1 - cond.notify() - b.wait_for_finished() + + with Bunch(f, 1): + for i in range(4): + time.sleep(0.010) + with cond: + state += 1 + cond.notify() def test_waitfor_timeout(self): cond = self.condtype() @@ -624,15 +733,15 @@ def f(): self.assertFalse(result) self.assertTimeout(dt, 0.1) success.append(None) - b = Bunch(f, 1) - b.wait_for_started() - # Only increment 3 times, so state == 4 is never reached. - for i in range(3): - time.sleep(0.01) - with cond: - state += 1 - cond.notify() - b.wait_for_finished() + + with Bunch(f, 1): + # Only increment 3 times, so state == 4 is never reached. + for i in range(3): + time.sleep(0.010) + with cond: + state += 1 + cond.notify() + self.assertEqual(len(success), 1) @@ -661,73 +770,107 @@ def test_acquire_destroy(self): del sem def test_acquire_contended(self): - sem = self.semtype(7) + sem_value = 7 + sem = self.semtype(sem_value) sem.acquire() - N = 10 + sem_results = [] results1 = [] results2 = [] phase_num = 0 - def f(): + + def func(): sem_results.append(sem.acquire()) results1.append(phase_num) + sem_results.append(sem.acquire()) results2.append(phase_num) - b = Bunch(f, 10) - b.wait_for_started() - while len(results1) + len(results2) < 6: - _wait() - self.assertEqual(results1 + results2, [0] * 6) - phase_num = 1 - for i in range(7): - sem.release() - while len(results1) + len(results2) < 13: - _wait() - self.assertEqual(sorted(results1 + results2), [0] * 6 + [1] * 7) - phase_num = 2 - for i in range(6): + + def wait_count(count): + for _ in support.sleeping_retry(support.SHORT_TIMEOUT): + if len(results1) + len(results2) >= count: + break + + N = 10 + with Bunch(func, N): + # Phase 0 + count1 = sem_value - 1 + wait_count(count1) + self.assertEqual(results1 + results2, [0] * count1) + + # Phase 1 + phase_num = 1 + for i in range(sem_value): + sem.release() + count2 = sem_value + wait_count(count1 + count2) + self.assertEqual(sorted(results1 + results2), + [0] * count1 + [1] * count2) + + # Phase 2 + phase_num = 2 + count3 = (sem_value - 1) + for i in range(count3): + sem.release() + wait_count(count1 + count2 + count3) + self.assertEqual(sorted(results1 + results2), + [0] * count1 + [1] * count2 + [2] * count3) + # The semaphore is still locked + self.assertFalse(sem.acquire(False)) + + # Final release, to let the last thread finish + count4 = 1 sem.release() - while len(results1) + len(results2) < 19: - _wait() - self.assertEqual(sorted(results1 + results2), [0] * 6 + [1] * 7 + [2] * 6) - # The semaphore is still locked - self.assertFalse(sem.acquire(False)) - # Final release, to let the last thread finish - sem.release() - b.wait_for_finished() - self.assertEqual(sem_results, [True] * (6 + 7 + 6 + 1)) + + self.assertEqual(sem_results, + [True] * (count1 + count2 + count3 + count4)) def test_multirelease(self): - sem = self.semtype(7) + sem_value = 7 + sem = self.semtype(sem_value) sem.acquire() + results1 = [] results2 = [] phase_num = 0 - def f(): + def func(): sem.acquire() results1.append(phase_num) + sem.acquire() results2.append(phase_num) - b = Bunch(f, 10) - b.wait_for_started() - while len(results1) + len(results2) < 6: - _wait() - self.assertEqual(results1 + results2, [0] * 6) - phase_num = 1 - sem.release(7) - while len(results1) + len(results2) < 13: - _wait() - self.assertEqual(sorted(results1 + results2), [0] * 6 + [1] * 7) - phase_num = 2 - sem.release(6) - while len(results1) + len(results2) < 19: - _wait() - self.assertEqual(sorted(results1 + results2), [0] * 6 + [1] * 7 + [2] * 6) - # The semaphore is still locked - self.assertFalse(sem.acquire(False)) - # Final release, to let the last thread finish - sem.release() - b.wait_for_finished() + + def wait_count(count): + for _ in support.sleeping_retry(support.SHORT_TIMEOUT): + if len(results1) + len(results2) >= count: + break + + with Bunch(func, 10): + # Phase 0 + count1 = sem_value - 1 + wait_count(count1) + self.assertEqual(results1 + results2, [0] * count1) + + # Phase 1 + phase_num = 1 + count2 = sem_value + sem.release(count2) + wait_count(count1 + count2) + self.assertEqual(sorted(results1 + results2), + [0] * count1 + [1] * count2) + + # Phase 2 + phase_num = 2 + count3 = sem_value - 1 + sem.release(count3) + wait_count(count1 + count2 + count3) + self.assertEqual(sorted(results1 + results2), + [0] * count1 + [1] * count2 + [2] * count3) + # The semaphore is still locked + self.assertFalse(sem.acquire(False)) + + # Final release, to let the last thread finish + sem.release() def test_try_acquire(self): sem = self.semtype(2) @@ -744,7 +887,8 @@ def test_try_acquire_contended(self): def f(): results.append(sem.acquire(False)) results.append(sem.acquire(False)) - Bunch(f, 5).wait_for_finished() + with Bunch(f, 5): + pass # There can be a thread switch between acquiring the semaphore and # appending the result, therefore results will not necessarily be # ordered. @@ -770,12 +914,14 @@ def test_default_value(self): def f(): sem.acquire() sem.release() - b = Bunch(f, 1) - b.wait_for_started() - _wait() - self.assertFalse(b.finished) - sem.release() - b.wait_for_finished() + + with Bunch(f, 1) as bunch: + # Thread blocked on sem.acquire() + wait_threads_blocked(1) + self.assertFalse(bunch.finished) + + # Thread unblocked + sem.release() def test_with(self): sem = self.semtype(2) @@ -846,13 +992,13 @@ class BarrierTests(BaseTestCase): def setUp(self): self.barrier = self.barriertype(self.N, timeout=self.defaultTimeout) + def tearDown(self): self.barrier.abort() def run_threads(self, f): - b = Bunch(f, self.N-1) - f() - b.wait_for_finished() + with Bunch(f, self.N): + pass def multipass(self, results, n): m = self.barrier.parties @@ -943,8 +1089,9 @@ def f(): i = self.barrier.wait() if i == self.N//2: # Wait until the other threads are all in the barrier. - while self.barrier.n_waiting < self.N-1: - time.sleep(0.001) + for _ in support.sleeping_retry(support.SHORT_TIMEOUT): + if self.barrier.n_waiting >= (self.N - 1): + break self.barrier.reset() else: try: @@ -1004,25 +1151,27 @@ def f(): i = self.barrier.wait() if i == self.N // 2: # One thread is late! - time.sleep(1.0) + time.sleep(self.defaultTimeout / 2) # Default timeout is 2.0, so this is shorter. self.assertRaises(threading.BrokenBarrierError, - self.barrier.wait, 0.5) + self.barrier.wait, self.defaultTimeout / 4) self.run_threads(f) def test_default_timeout(self): """ Test the barrier's default timeout """ - # create a barrier with a low default timeout - barrier = self.barriertype(self.N, timeout=0.3) + timeout = 0.100 + barrier = self.barriertype(2, timeout=timeout) def f(): - i = barrier.wait() - if i == self.N // 2: - # One thread is later than the default timeout of 0.3s. - time.sleep(1.0) - self.assertRaises(threading.BrokenBarrierError, barrier.wait) - self.run_threads(f) + self.assertRaises(threading.BrokenBarrierError, + barrier.wait) + + start_time = time.monotonic() + with Bunch(f, 1): + pass + dt = time.monotonic() - start_time + self.assertGreaterEqual(dt, timeout) def test_single_thread(self): b = self.barriertype(1) @@ -1030,16 +1179,28 @@ def test_single_thread(self): b.wait() def test_repr(self): - b = self.barriertype(3) - self.assertRegex(repr(b), r"<\w+\.Barrier at .*: waiters=0/3>") + barrier = self.barriertype(3) + timeout = support.LONG_TIMEOUT + self.assertRegex(repr(barrier), r"<\w+\.Barrier at .*: waiters=0/3>") def f(): - b.wait(3) - bunch = Bunch(f, 2) - bunch.wait_for_started() - time.sleep(0.2) - self.assertRegex(repr(b), r"<\w+\.Barrier at .*: waiters=2/3>") - b.wait(3) - bunch.wait_for_finished() - self.assertRegex(repr(b), r"<\w+\.Barrier at .*: waiters=0/3>") - b.abort() - self.assertRegex(repr(b), r"<\w+\.Barrier at .*: broken>") + barrier.wait(timeout) + + N = 2 + with Bunch(f, N): + # Threads blocked on barrier.wait() + for _ in support.sleeping_retry(support.SHORT_TIMEOUT): + if barrier.n_waiting >= N: + break + self.assertRegex(repr(barrier), + r"<\w+\.Barrier at .*: waiters=2/3>") + + # Threads unblocked + barrier.wait(timeout) + + self.assertRegex(repr(barrier), + r"<\w+\.Barrier at .*: waiters=0/3>") + + # Abort the barrier + barrier.abort() + self.assertRegex(repr(barrier), + r"<\w+\.Barrier at .*: broken>") diff --git a/Lib/test/mapping_tests.py b/Lib/test/mapping_tests.py index 5492bbf86d1f87..b4cfce19a7174e 100644 --- a/Lib/test/mapping_tests.py +++ b/Lib/test/mapping_tests.py @@ -1,8 +1,7 @@ # tests common to dict and UserDict import unittest import collections -import sys -from test.support import C_RECURSION_LIMIT +from test.support import Py_C_RECURSION_LIMIT class BasicTestMappingProtocol(unittest.TestCase): @@ -625,7 +624,7 @@ def __repr__(self): def test_repr_deep(self): d = self._empty_mapping() - for i in range(C_RECURSION_LIMIT + 1): + for i in range(Py_C_RECURSION_LIMIT + 1): d0 = d d = self._empty_mapping() d[1] = d0 diff --git a/Lib/test/cmath_testcases.txt b/Lib/test/mathdata/cmath_testcases.txt similarity index 100% rename from Lib/test/cmath_testcases.txt rename to Lib/test/mathdata/cmath_testcases.txt diff --git a/Lib/test/floating_points.txt b/Lib/test/mathdata/floating_points.txt similarity index 100% rename from Lib/test/floating_points.txt rename to Lib/test/mathdata/floating_points.txt diff --git a/Lib/test/formatfloat_testcases.txt b/Lib/test/mathdata/formatfloat_testcases.txt similarity index 100% rename from Lib/test/formatfloat_testcases.txt rename to Lib/test/mathdata/formatfloat_testcases.txt diff --git a/Lib/test/ieee754.txt b/Lib/test/mathdata/ieee754.txt similarity index 100% rename from Lib/test/ieee754.txt rename to Lib/test/mathdata/ieee754.txt diff --git a/Lib/test/math_testcases.txt b/Lib/test/mathdata/math_testcases.txt similarity index 100% rename from Lib/test/math_testcases.txt rename to Lib/test/mathdata/math_testcases.txt diff --git a/Lib/test/pickletester.py b/Lib/test/pickletester.py index 6e87370c2065ba..74b82caf742f20 100644 --- a/Lib/test/pickletester.py +++ b/Lib/test/pickletester.py @@ -1825,6 +1825,14 @@ def test_unicode_high_plane(self): t2 = self.loads(p) self.assert_is_copy(t, t2) + def test_unicode_memoization(self): + # Repeated str is re-used (even when escapes added). + for proto in protocols: + for s in '', 'xyz', 'xyz\n', 'x\\yz', 'x\xa1yz\r': + p = self.dumps((s, s), proto) + s1, s2 = self.loads(p) + self.assertIs(s1, s2) + def test_bytes(self): for proto in protocols: for s in b'', b'xyz', b'xyz'*100: @@ -2408,6 +2416,22 @@ def test_reduce_calls_base(self): y = self.loads(s) self.assertEqual(y._reduce_called, 1) + def test_reduce_ex_None(self): + c = REX_None() + with self.assertRaises(TypeError): + self.dumps(c) + + def test_reduce_None(self): + c = R_None() + with self.assertRaises(TypeError): + self.dumps(c) + + def test_pickle_setstate_None(self): + c = C_None_setstate() + p = self.dumps(c) + with self.assertRaises(TypeError): + self.loads(p) + @no_tracing def test_bad_getattr(self): # Issue #3514: crash when there is an infinite loop in __getattr__ @@ -2576,6 +2600,7 @@ def check_frame_opcodes(self, pickled): self.assertLess(pos - frameless_start, self.FRAME_SIZE_MIN) @support.skip_if_pgo_task + @support.requires_resource('cpu') def test_framing_many_objects(self): obj = list(range(10**5)) for proto in range(4, pickle.HIGHEST_PROTOCOL + 1): @@ -3348,6 +3373,21 @@ def __setstate__(self, state): def __reduce__(self): return type(self), (), self.state +class REX_None: + """ Setting __reduce_ex__ to None should fail """ + __reduce_ex__ = None + +class R_None: + """ Setting __reduce__ to None should fail """ + __reduce__ = None + +class C_None_setstate: + """ Setting __setstate__ to None should fail """ + def __getstate__(self): + return 1 + + __setstate__ = None + # Test classes for newobj @@ -3482,6 +3522,84 @@ def __init__(self): pass self.assertRaises(pickle.PicklingError, BadPickler().dump, 0) self.assertRaises(pickle.UnpicklingError, BadUnpickler().load) + def test_unpickler_bad_file(self): + # bpo-38384: Crash in _pickle if the read attribute raises an error. + def raises_oserror(self, *args, **kwargs): + raise OSError + @property + def bad_property(self): + 1/0 + + # File without read and readline + class F: + pass + self.assertRaises((AttributeError, TypeError), self.Unpickler, F()) + + # File without read + class F: + readline = raises_oserror + self.assertRaises((AttributeError, TypeError), self.Unpickler, F()) + + # File without readline + class F: + read = raises_oserror + self.assertRaises((AttributeError, TypeError), self.Unpickler, F()) + + # File with bad read + class F: + read = bad_property + readline = raises_oserror + self.assertRaises(ZeroDivisionError, self.Unpickler, F()) + + # File with bad readline + class F: + readline = bad_property + read = raises_oserror + self.assertRaises(ZeroDivisionError, self.Unpickler, F()) + + # File with bad readline, no read + class F: + readline = bad_property + self.assertRaises(ZeroDivisionError, self.Unpickler, F()) + + # File with bad read, no readline + class F: + read = bad_property + self.assertRaises((AttributeError, ZeroDivisionError), self.Unpickler, F()) + + # File with bad peek + class F: + peek = bad_property + read = raises_oserror + readline = raises_oserror + try: + self.Unpickler(F()) + except ZeroDivisionError: + pass + + # File with bad readinto + class F: + readinto = bad_property + read = raises_oserror + readline = raises_oserror + try: + self.Unpickler(F()) + except ZeroDivisionError: + pass + + def test_pickler_bad_file(self): + # File without write + class F: + pass + self.assertRaises(TypeError, self.Pickler, F()) + + # File with bad write + class F: + @property + def write(self): + 1/0 + self.assertRaises(ZeroDivisionError, self.Pickler, F()) + def check_dumps_loads_oob_buffers(self, dumps, loads): # No need to do the full gamut of tests here, just enough to # check that dumps() and loads() redirect their arguments @@ -3751,6 +3869,25 @@ def test_unpickling_buffering_readline(self): unpickler = self.unpickler_class(f) self.assertEqual(unpickler.load(), data) + def test_pickle_invalid_reducer_override(self): + # gh-103035 + obj = object() + + f = io.BytesIO() + class MyPickler(self.pickler_class): + pass + pickler = MyPickler(f) + pickler.dump(obj) + + pickler.clear_memo() + pickler.reducer_override = None + with self.assertRaises(TypeError): + pickler.dump(obj) + + pickler.clear_memo() + pickler.reducer_override = 10 + with self.assertRaises(TypeError): + pickler.dump(obj) # Tests for dispatch_table attribute @@ -3913,6 +4050,15 @@ def dumps(obj, protocol=None): self._test_dispatch_table(dumps, dt) + def test_dispatch_table_None_item(self): + # gh-93627 + obj = object() + f = io.BytesIO() + pickler = self.pickler_class(f) + pickler.dispatch_table = {type(obj): None} + with self.assertRaises(TypeError): + pickler.dump(obj) + def _test_dispatch_table(self, dumps, dispatch_table): def custom_load_dump(obj): return pickle.loads(dumps(obj, 0)) diff --git a/Lib/test/pydocfodder.py b/Lib/test/pydocfodder.py index d0750e5a43c0c0..a3ef2231243954 100644 --- a/Lib/test/pydocfodder.py +++ b/Lib/test/pydocfodder.py @@ -2,8 +2,8 @@ import types -class A_new: - "A new-style class." +class A: + "A class." def A_method(self): "Method defined in A." @@ -41,8 +41,8 @@ def _delx(self): A_int_alias = int -class B_new(A_new): - "A new-style class, derived from A_new." +class B(A): + "A class, derived from A." def AB_method(self): "Method defined in A and B." @@ -61,8 +61,8 @@ def BD_method(self): def BCD_method(self): "Method defined in B, C and D." -class C_new(A_new): - "A new-style class, derived from A_new." +class C(A): + "A class, derived from A." def AC_method(self): "Method defined in A and C." @@ -81,8 +81,8 @@ def C_method(self): def CD_method(self): "Method defined in C and D." -class D_new(B_new, C_new): - """A new-style class, derived from B_new and C_new. +class D(B, C): + """A class, derived from B and C. """ def AD_method(self): diff --git a/Lib/test/pythoninfo.py b/Lib/test/pythoninfo.py index e4e098dd84cfb9..6dfb7f37e406a5 100644 --- a/Lib/test/pythoninfo.py +++ b/Lib/test/pythoninfo.py @@ -1,18 +1,13 @@ """ Collect various information about Python to help debugging test failures. """ -from __future__ import print_function import errno import re import sys import traceback -import unittest import warnings -MS_WINDOWS = (sys.platform == 'win32') - - def normalize_text(text): if text is None: return None @@ -112,6 +107,7 @@ def collect_sys(info_add): call_func(info_add, 'sys.androidapilevel', sys, 'getandroidapilevel') call_func(info_add, 'sys.windowsversion', sys, 'getwindowsversion') + call_func(info_add, 'sys.getrecursionlimit', sys, 'getrecursionlimit') encoding = sys.getfilesystemencoding() if hasattr(sys, 'getfilesystemencodeerrors'): @@ -163,6 +159,26 @@ def collect_platform(info_add): if libc_ver: info_add('platform.libc_ver', libc_ver) + try: + os_release = platform.freedesktop_os_release() + except OSError: + pass + else: + for key in ( + 'ID', + 'NAME', + 'PRETTY_NAME' + 'VARIANT', + 'VARIANT_ID', + 'VERSION', + 'VERSION_CODENAME', + 'VERSION_ID', + ): + if key not in os_release: + continue + info_add(f'platform.freedesktop_os_release[{key}]', + os_release[key]) + def collect_locale(info_add): import locale @@ -223,6 +239,7 @@ def format_attr(attr, value): 'getresgid', 'getresuid', 'getuid', + 'process_cpu_count', 'uname', ): call_func(info_add, 'os.%s' % func, os, func) @@ -252,6 +269,7 @@ def format_groups(groups): "ARCHFLAGS", "ARFLAGS", "AUDIODEV", + "BUILDPYTHON", "CC", "CFLAGS", "COLUMNS", @@ -304,15 +322,24 @@ def format_groups(groups): "VIRTUAL_ENV", "WAYLAND_DISPLAY", "WINDIR", + "_PYTHON_HOSTRUNNER", "_PYTHON_HOST_PLATFORM", "_PYTHON_PROJECT_BASE", "_PYTHON_SYSCONFIGDATA_NAME", "__PYVENV_LAUNCHER__", + + # Sanitizer options + "ASAN_OPTIONS", + "LSAN_OPTIONS", + "MSAN_OPTIONS", + "TSAN_OPTIONS", + "UBSAN_OPTIONS", )) for name, value in os.environ.items(): uname = name.upper() if (uname in ENV_VARS - # Copy PYTHON* and LC_* variables + # Copy PYTHON* variables like PYTHONPATH + # Copy LC_* variables like LC_ALL or uname.startswith(("PYTHON", "LC_")) # Visual Studio: VS140COMNTOOLS or (uname.startswith("VS") and uname.endswith("COMNTOOLS"))): @@ -465,13 +492,10 @@ def collect_datetime(info_add): def collect_sysconfig(info_add): - # On Windows, sysconfig is not reliable to get macros used - # to build Python - if MS_WINDOWS: - return - import sysconfig + info_add('sysconfig.is_python_build', sysconfig.is_python_build()) + for name in ( 'ABIFLAGS', 'ANDROID_API_LEVEL', @@ -480,6 +504,7 @@ def collect_sysconfig(info_add): 'CFLAGS', 'CFLAGSFORSHARED', 'CONFIG_ARGS', + 'HOSTRUNNER', 'HOST_GNU_TYPE', 'MACHDEP', 'MULTIARCH', @@ -492,9 +517,13 @@ def collect_sysconfig(info_add): 'PY_STDMODULE_CFLAGS', 'Py_DEBUG', 'Py_ENABLE_SHARED', + 'Py_GIL_DISABLED', 'SHELL', 'SOABI', + 'abs_builddir', + 'abs_srcdir', 'prefix', + 'srcdir', ): value = sysconfig.get_config_var(name) if name == 'ANDROID_API_LEVEL' and not value: @@ -515,6 +544,7 @@ def collect_sysconfig(info_add): 'WITH_DOC_STRINGS', 'WITH_DTRACE', 'WITH_FREELISTS', + 'WITH_MIMALLOC', 'WITH_PYMALLOC', 'WITH_VALGRIND', ): @@ -636,6 +666,22 @@ def collect_decimal(info_add): def collect_testcapi(info_add): + try: + import _testcapi + except ImportError: + return + + for name in ( + 'LONG_MAX', # always 32-bit on Windows, 64-bit on 64-bit Unix + 'PY_SSIZE_T_MAX', + 'Py_C_RECURSION_LIMIT', + 'SIZEOF_TIME_T', # 32-bit or 64-bit depending on the platform + 'SIZEOF_WCHAR_T', # 16-bit or 32-bit depending on the platform + ): + copy_attr(info_add, f'_testcapi.{name}', _testcapi, name) + + +def collect_testinternalcapi(info_add): try: import _testinternalcapi except ImportError: @@ -643,6 +689,12 @@ def collect_testcapi(info_add): call_func(info_add, 'pymem.allocator', _testinternalcapi, 'pymem_getallocatorsname') + for name in ( + 'SIZEOF_PYGC_HEAD', + 'SIZEOF_PYOBJECT', + ): + copy_attr(info_add, f'_testinternalcapi.{name}', _testinternalcapi, name) + def collect_resource(info_add): try: @@ -660,6 +712,7 @@ def collect_resource(info_add): def collect_test_socket(info_add): + import unittest try: from test import test_socket except (ImportError, unittest.SkipTest): @@ -671,26 +724,83 @@ def collect_test_socket(info_add): copy_attributes(info_add, test_socket, 'test_socket.%s', attributes) -def collect_test_support(info_add): +def collect_support(info_add): try: from test import support except ImportError: return - attributes = ('IPV6_ENABLED',) - copy_attributes(info_add, support, 'test_support.%s', attributes) + attributes = ( + 'MS_WINDOWS', + 'has_fork_support', + 'has_socket_support', + 'has_strftime_extensions', + 'has_subprocess_support', + 'is_android', + 'is_emscripten', + 'is_jython', + 'is_wasi', + ) + copy_attributes(info_add, support, 'support.%s', attributes) - call_func(info_add, 'test_support._is_gui_available', support, '_is_gui_available') - call_func(info_add, 'test_support.python_is_optimized', support, 'python_is_optimized') + call_func(info_add, 'support._is_gui_available', support, '_is_gui_available') + call_func(info_add, 'support.python_is_optimized', support, 'python_is_optimized') - info_add('test_support.check_sanitizer(address=True)', + info_add('support.check_sanitizer(address=True)', support.check_sanitizer(address=True)) - info_add('test_support.check_sanitizer(memory=True)', + info_add('support.check_sanitizer(memory=True)', support.check_sanitizer(memory=True)) - info_add('test_support.check_sanitizer(ub=True)', + info_add('support.check_sanitizer(ub=True)', support.check_sanitizer(ub=True)) +def collect_support_os_helper(info_add): + try: + from test.support import os_helper + except ImportError: + return + + for name in ( + 'can_symlink', + 'can_xattr', + 'can_chmod', + 'can_dac_override', + ): + func = getattr(os_helper, name) + info_add(f'support_os_helper.{name}', func()) + + +def collect_support_socket_helper(info_add): + try: + from test.support import socket_helper + except ImportError: + return + + attributes = ( + 'IPV6_ENABLED', + 'has_gethostname', + ) + copy_attributes(info_add, socket_helper, 'support_socket_helper.%s', attributes) + + for name in ( + 'tcp_blackhole', + ): + func = getattr(socket_helper, name) + info_add(f'support_socket_helper.{name}', func()) + + +def collect_support_threading_helper(info_add): + try: + from test.support import threading_helper + except ImportError: + return + + attributes = ( + 'can_start_thread', + ) + copy_attributes(info_add, threading_helper, 'support_threading_helper.%s', attributes) + + def collect_cc(info_add): import subprocess import sysconfig @@ -815,6 +925,8 @@ def collect_windows(info_add): stderr=subprocess.PIPE, text=True) output = proc.communicate()[0] + if proc.returncode == 0xc0000142: + return if proc.returncode: output = "" except OSError: @@ -845,6 +957,21 @@ def collect_fips(info_add): pass +def collect_tempfile(info_add): + import tempfile + + info_add('tempfile.gettempdir', tempfile.gettempdir()) + + +def collect_libregrtest_utils(info_add): + try: + from test.libregrtest import utils + except ImportError: + return + + info_add('libregrtests.build_info', ' '.join(utils.get_build_info())) + + def collect_info(info): error = False info_add = info.add @@ -878,14 +1005,20 @@ def collect_info(info): collect_sys, collect_sysconfig, collect_testcapi, + collect_testinternalcapi, + collect_tempfile, collect_time, collect_tkinter, collect_windows, collect_zlib, + collect_libregrtest_utils, # Collecting from tests should be last as they have side effects. collect_test_socket, - collect_test_support, + collect_support, + collect_support_os_helper, + collect_support_socket_helper, + collect_support_threading_helper, ): try: collect_func(info_add) @@ -911,7 +1044,6 @@ def dump_info(info, file=None): for key, value in infos: value = value.replace("\n", " ") print("%s: %s" % (key, value)) - print() def main(): @@ -920,6 +1052,7 @@ def main(): dump_info(info) if error: + print() print("Collection failed: exit with error", file=sys.stderr) sys.exit(1) diff --git a/Lib/test/regrtest.py b/Lib/test/regrtest.py index 0ffb3ed454eda0..46a74fe276f553 100755 --- a/Lib/test/regrtest.py +++ b/Lib/test/regrtest.py @@ -8,7 +8,7 @@ import os import sys -from test.libregrtest import main +from test.libregrtest.main import main # Alias for backward compatibility (just in case) diff --git a/Lib/test/regrtestdata/import_from_tests/test_regrtest_a.py b/Lib/test/regrtestdata/import_from_tests/test_regrtest_a.py new file mode 100644 index 00000000000000..9c3d0c7cf4bfaa --- /dev/null +++ b/Lib/test/regrtestdata/import_from_tests/test_regrtest_a.py @@ -0,0 +1,11 @@ +import sys +import unittest +import test_regrtest_b.util + +class Test(unittest.TestCase): + def test(self): + test_regrtest_b.util # does not fail + self.assertIn('test_regrtest_a', sys.modules) + self.assertIs(sys.modules['test_regrtest_b'], test_regrtest_b) + self.assertIs(sys.modules['test_regrtest_b.util'], test_regrtest_b.util) + self.assertNotIn('test_regrtest_c', sys.modules) diff --git a/Lib/test/regrtestdata/import_from_tests/test_regrtest_b/__init__.py b/Lib/test/regrtestdata/import_from_tests/test_regrtest_b/__init__.py new file mode 100644 index 00000000000000..3dfba253455ad2 --- /dev/null +++ b/Lib/test/regrtestdata/import_from_tests/test_regrtest_b/__init__.py @@ -0,0 +1,9 @@ +import sys +import unittest + +class Test(unittest.TestCase): + def test(self): + self.assertNotIn('test_regrtest_a', sys.modules) + self.assertIn('test_regrtest_b', sys.modules) + self.assertNotIn('test_regrtest_b.util', sys.modules) + self.assertNotIn('test_regrtest_c', sys.modules) diff --git a/Modules/_testcapi/pytime.c b/Lib/test/regrtestdata/import_from_tests/test_regrtest_b/util.py similarity index 100% rename from Modules/_testcapi/pytime.c rename to Lib/test/regrtestdata/import_from_tests/test_regrtest_b/util.py diff --git a/Lib/test/regrtestdata/import_from_tests/test_regrtest_c.py b/Lib/test/regrtestdata/import_from_tests/test_regrtest_c.py new file mode 100644 index 00000000000000..de80769118d709 --- /dev/null +++ b/Lib/test/regrtestdata/import_from_tests/test_regrtest_c.py @@ -0,0 +1,11 @@ +import sys +import unittest +import test_regrtest_b.util + +class Test(unittest.TestCase): + def test(self): + test_regrtest_b.util # does not fail + self.assertNotIn('test_regrtest_a', sys.modules) + self.assertIs(sys.modules['test_regrtest_b'], test_regrtest_b) + self.assertIs(sys.modules['test_regrtest_b.util'], test_regrtest_b.util) + self.assertIn('test_regrtest_c', sys.modules) diff --git a/Lib/test/setup_testcppext.py b/Lib/test/setup_testcppext.py deleted file mode 100644 index 22fe750085fd70..00000000000000 --- a/Lib/test/setup_testcppext.py +++ /dev/null @@ -1,43 +0,0 @@ -# gh-91321: Build a basic C++ test extension to check that the Python C API is -# compatible with C++ and does not emit C++ compiler warnings. -import os -import sys -from test import support - -from setuptools import setup, Extension - - -MS_WINDOWS = (sys.platform == 'win32') - - -SOURCE = support.findfile('_testcppext.cpp') -if not MS_WINDOWS: - # C++ compiler flags for GCC and clang - CPPFLAGS = [ - # gh-91321: The purpose of _testcppext extension is to check that building - # a C++ extension using the Python C API does not emit C++ compiler - # warnings - '-Werror', - ] -else: - # Don't pass any compiler flag to MSVC - CPPFLAGS = [] - - -def main(): - cppflags = list(CPPFLAGS) - std = os.environ["CPYTHON_TEST_CPP_STD"] - name = os.environ["CPYTHON_TEST_EXT_NAME"] - - cppflags = [*CPPFLAGS, f'-std={std}'] - - cpp_ext = Extension( - name, - sources=[SOURCE], - language='c++', - extra_compile_args=cppflags) - setup(name='internal' + name, version='0.0', ext_modules=[cpp_ext]) - - -if __name__ == "__main__": - main() diff --git a/Lib/test/sgml_input.html b/Lib/test/sgml_input.html deleted file mode 100644 index f4d2e6cc805e6a..00000000000000 --- a/Lib/test/sgml_input.html +++ /dev/null @@ -1,212 +0,0 @@ - - - - - - - - -
- - - - - -
-
- - - - - -
- - -
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - -
  MetalCristalDeuterioEnergía  
160.6363.40639.230-80/3.965
-
-
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Flotas (max. 9)
Num.MisiónCantidadComienzoSalidaObjetivoLlegadaOrden
1 - Espionaje - (F) - 3[2:250:6]Wed Aug 9 18:00:02[2:242:5]Wed Aug 9 18:01:02 -
- - -
-
2 - Espionaje - (V) - 3[2:250:6]Wed Aug 9 17:59:55[2:242:1]Wed Aug 9 18:01:55 -
- - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Nueva misión: elegir naves
NavesDisponibles--
Nave pequeña de carga10máx
Nave grande de carga19máx
Crucero6máx
Reciclador1máx
Sonda de espionaje139máx
Ninguna naveTodas las naves
- -

-
- - diff --git a/Lib/test/signalinterproctester.py b/Lib/test/signalinterproctester.py index cdcd92a8baace6..073c078f45f6d7 100644 --- a/Lib/test/signalinterproctester.py +++ b/Lib/test/signalinterproctester.py @@ -1,3 +1,4 @@ +import gc import os import signal import subprocess @@ -59,6 +60,13 @@ def test_interprocess_signal(self): self.assertEqual(self.got_signals, {'SIGHUP': 1, 'SIGUSR1': 0, 'SIGALRM': 0}) + # gh-110033: Make sure that the subprocess.Popen is deleted before + # the next test which raises an exception. Otherwise, the exception + # may be raised when Popen.__del__() is executed and so be logged + # as "Exception ignored in: ". + child = None + gc.collect() + with self.assertRaises(SIGUSR1Exception): with self.subprocess_send_signal(pid, "SIGUSR1") as child: self.wait_signal(child, 'SIGUSR1') diff --git a/Lib/test/ssl_servers.py b/Lib/test/ssl_servers.py index a4bd7455d47e76..15b071e04dda1f 100644 --- a/Lib/test/ssl_servers.py +++ b/Lib/test/ssl_servers.py @@ -14,7 +14,7 @@ here = os.path.dirname(__file__) HOST = socket_helper.HOST -CERTFILE = os.path.join(here, 'keycert.pem') +CERTFILE = os.path.join(here, 'certdata', 'keycert.pem') # This one's based on HTTPServer, which is based on socketserver diff --git a/Lib/test/string_tests.py b/Lib/test/string_tests.py index 8d210b198d248d..cecf309dca9194 100644 --- a/Lib/test/string_tests.py +++ b/Lib/test/string_tests.py @@ -327,11 +327,12 @@ def reference_find(p, s): for i in range(len(s)): if s.startswith(p, i): return i + if p == '' and s == '': + return 0 return -1 - rr = random.randrange - choices = random.choices - for _ in range(1000): + def check_pattern(rr): + choices = random.choices p0 = ''.join(choices('abcde', k=rr(10))) * rr(10, 20) p = p0[:len(p0) - rr(10)] # pop off some characters left = ''.join(choices('abcdef', k=rr(2000))) @@ -341,6 +342,13 @@ def reference_find(p, s): self.checkequal(reference_find(p, text), text, 'find', p) + rr = random.randrange + for _ in range(1000): + check_pattern(rr) + + # Test that empty string always work: + check_pattern(lambda *args: 0) + def test_find_many_lengths(self): haystack_repeats = [a * 10**e for e in range(6) for a in (1,2,5)] haystacks = [(n, self.fixtype("abcab"*n + "da")) for n in haystack_repeats] diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py index 64c66d8e25d9cd..e5fb725a30b5b8 100644 --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -4,8 +4,8 @@ raise ImportError('support must be imported from the test package') import contextlib +import dataclasses import functools -import getpass import _opcode import os import re @@ -18,13 +18,6 @@ import unittest import warnings -from .testresult import get_test_runner - - -try: - from _testcapi import unicode_legacy_string -except ImportError: - unicode_legacy_string = None __all__ = [ # globals @@ -38,7 +31,6 @@ "is_resource_enabled", "requires", "requires_freebsd_version", "requires_linux_version", "requires_mac_ver", "check_syntax_error", - "run_unittest", "run_doctest", "requires_gzip", "requires_bz2", "requires_lzma", "bigmemtest", "bigaddrspacetest", "cpython_only", "get_attribute", "requires_IEEE_754", "requires_zlib", @@ -50,7 +42,7 @@ "check_disallow_instantiation", "check_sanitizer", "skip_if_sanitizer", "requires_limited_api", "requires_specialization", # sys - "is_jython", "is_android", "is_emscripten", "is_wasi", + "MS_WINDOWS", "is_jython", "is_android", "is_emscripten", "is_wasi", "check_impl_detail", "unix_shell", "setswitchinterval", # os "get_pagesize", @@ -64,8 +56,9 @@ "run_with_tz", "PGO", "missing_compiler_executable", "ALWAYS_EQ", "NEVER_EQ", "LARGEST", "SMALLEST", "LOOPBACK_TIMEOUT", "INTERNET_TIMEOUT", "SHORT_TIMEOUT", "LONG_TIMEOUT", - "Py_DEBUG", "EXCEEDS_RECURSION_LIMIT", "C_RECURSION_LIMIT", + "Py_DEBUG", "EXCEEDS_RECURSION_LIMIT", "Py_C_RECURSION_LIMIT", "skip_on_s390x", + "without_optimizer", ] @@ -78,13 +71,7 @@ # # The timeout should be long enough for connect(), recv() and send() methods # of socket.socket. -LOOPBACK_TIMEOUT = 5.0 -if sys.platform == 'win32' and ' 32 bit (ARM)' in sys.version: - # bpo-37553: test_socket.SendfileUsingSendTest is taking longer than 2 - # seconds on Windows ARM32 buildbot - LOOPBACK_TIMEOUT = 10 -elif sys.platform == 'vxworks': - LOOPBACK_TIMEOUT = 10 +LOOPBACK_TIMEOUT = 10.0 # Timeout in seconds for network requests going to the internet. The timeout is # short enough to prevent a test to wait for too long if the internet request @@ -123,17 +110,20 @@ class Error(Exception): class TestFailed(Error): """Test failed.""" + def __init__(self, msg, *args, stats=None): + self.msg = msg + self.stats = stats + super().__init__(msg, *args) + + def __str__(self): + return self.msg class TestFailedWithDetails(TestFailed): """Test failed.""" - def __init__(self, msg, errors, failures): - self.msg = msg + def __init__(self, msg, errors, failures, stats): self.errors = errors self.failures = failures - super().__init__(msg, errors, failures) - - def __str__(self): - return self.msg + super().__init__(msg, errors, failures, stats=stats) class TestDidNotRun(Error): """Test did not run any subtests.""" @@ -392,6 +382,7 @@ def wrapper(*args, **kw): def skip_if_buildbot(reason=None): """Decorator raising SkipTest if running on a buildbot.""" + import getpass if not reason: reason = 'not suitable for buildbots' try: @@ -401,40 +392,57 @@ def skip_if_buildbot(reason=None): isbuildbot = False return unittest.skipIf(isbuildbot, reason) -def check_sanitizer(*, address=False, memory=False, ub=False): +def check_sanitizer(*, address=False, memory=False, ub=False, thread=False): """Returns True if Python is compiled with sanitizer support""" - if not (address or memory or ub): - raise ValueError('At least one of address, memory, or ub must be True') + if not (address or memory or ub or thread): + raise ValueError('At least one of address, memory, ub or thread must be True') - _cflags = sysconfig.get_config_var('CFLAGS') or '' - _config_args = sysconfig.get_config_var('CONFIG_ARGS') or '' + cflags = sysconfig.get_config_var('CFLAGS') or '' + config_args = sysconfig.get_config_var('CONFIG_ARGS') or '' memory_sanitizer = ( - '-fsanitize=memory' in _cflags or - '--with-memory-sanitizer' in _config_args + '-fsanitize=memory' in cflags or + '--with-memory-sanitizer' in config_args ) address_sanitizer = ( - '-fsanitize=address' in _cflags or - '--with-address-sanitizer' in _config_args + '-fsanitize=address' in cflags or + '--with-address-sanitizer' in config_args ) ub_sanitizer = ( - '-fsanitize=undefined' in _cflags or - '--with-undefined-behavior-sanitizer' in _config_args + '-fsanitize=undefined' in cflags or + '--with-undefined-behavior-sanitizer' in config_args + ) + thread_sanitizer = ( + '-fsanitize=thread' in cflags or + '--with-thread-sanitizer' in config_args ) return ( (memory and memory_sanitizer) or (address and address_sanitizer) or - (ub and ub_sanitizer) + (ub and ub_sanitizer) or + (thread and thread_sanitizer) ) -def skip_if_sanitizer(reason=None, *, address=False, memory=False, ub=False): +def skip_if_sanitizer(reason=None, *, address=False, memory=False, ub=False, thread=False): """Decorator raising SkipTest if running with a sanitizer active.""" if not reason: reason = 'not working with sanitizers active' - skip = check_sanitizer(address=address, memory=memory, ub=ub) + skip = check_sanitizer(address=address, memory=memory, ub=ub, thread=thread) return unittest.skipIf(skip, reason) +# gh-89363: True if fork() can hang if Python is built with Address Sanitizer +# (ASAN): libasan race condition, dead lock in pthread_create(). +HAVE_ASAN_FORK_BUG = check_sanitizer(address=True) + + +def set_sanitizer_env_var(env, option): + for name in ('ASAN_OPTIONS', 'MSAN_OPTIONS', 'UBSAN_OPTIONS', 'TSAN_OPTIONS'): + if name in env: + env[name] += f':{option}' + else: + env[name] = option + def system_must_validate_cert(f): """Skip the test on TLS certificate validation failures.""" @@ -507,8 +515,7 @@ def has_no_debug_ranges(): def requires_debug_ranges(reason='requires co_positions / debug_ranges'): return unittest.skipIf(has_no_debug_ranges(), reason) -requires_legacy_unicode_capi = unittest.skipUnless(unicode_legacy_string, - 'requires legacy Unicode C API') +MS_WINDOWS = (sys.platform == 'win32') # Is not actually used in tests, but is kept for compatibility. is_jython = sys.platform.startswith('java') @@ -776,11 +783,30 @@ def python_is_optimized(): return final_opt not in ('', '-O0', '-Og') -_header = 'nP' +def check_cflags_pgo(): + # Check if Python was built with ./configure --enable-optimizations: + # with Profile Guided Optimization (PGO). + cflags_nodist = sysconfig.get_config_var('PY_CFLAGS_NODIST') or '' + pgo_options = [ + # GCC + '-fprofile-use', + # clang: -fprofile-instr-use=code.profclangd + '-fprofile-instr-use', + # ICC + "-prof-use", + ] + PGO_PROF_USE_FLAG = sysconfig.get_config_var('PGO_PROF_USE_FLAG') + if PGO_PROF_USE_FLAG: + pgo_options.append(PGO_PROF_USE_FLAG) + return any(option in cflags_nodist for option in pgo_options) + + +Py_GIL_DISABLED = bool(sysconfig.get_config_var('Py_GIL_DISABLED')) +if Py_GIL_DISABLED: + _header = 'PHBBInP' +else: + _header = 'nP' _align = '0n' -if hasattr(sys, "getobjects"): - _header = '2P' + _header - _align = '0P' _vheader = _header + 'n' def calcobjsize(fmt): @@ -885,27 +911,31 @@ def inner(*args, **kwds): MAX_Py_ssize_t = sys.maxsize -def set_memlimit(limit): - global max_memuse - global real_max_memuse +def _parse_memlimit(limit: str) -> int: sizes = { 'k': 1024, 'm': _1M, 'g': _1G, 't': 1024*_1G, } - m = re.match(r'(\d+(\.\d+)?) (K|M|G|T)b?$', limit, + m = re.match(r'(\d+(?:\.\d+)?) (K|M|G|T)b?$', limit, re.IGNORECASE | re.VERBOSE) if m is None: - raise ValueError('Invalid memory limit %r' % (limit,)) - memlimit = int(float(m.group(1)) * sizes[m.group(3).lower()]) - real_max_memuse = memlimit - if memlimit > MAX_Py_ssize_t: - memlimit = MAX_Py_ssize_t + raise ValueError(f'Invalid memory limit: {limit!r}') + return int(float(m.group(1)) * sizes[m.group(2).lower()]) + +def set_memlimit(limit: str) -> None: + global max_memuse + global real_max_memuse + memlimit = _parse_memlimit(limit) if memlimit < _2G - 1: - raise ValueError('Memory limit %r too low to be useful' % (limit,)) + raise ValueError('Memory limit {limit!r} too low to be useful') + + real_max_memuse = memlimit + memlimit = min(memlimit, MAX_Py_ssize_t) max_memuse = memlimit + class _MemoryWatchdog: """An object which periodically watches the process' memory consumption and prints it out. @@ -1058,18 +1088,30 @@ def check_impl_detail(**guards): def no_tracing(func): """Decorator to temporarily turn off tracing for the duration of a test.""" - if not hasattr(sys, 'gettrace'): - return func - else: + trace_wrapper = func + if hasattr(sys, 'gettrace'): @functools.wraps(func) - def wrapper(*args, **kwargs): + def trace_wrapper(*args, **kwargs): original_trace = sys.gettrace() try: sys.settrace(None) return func(*args, **kwargs) finally: sys.settrace(original_trace) - return wrapper + + coverage_wrapper = trace_wrapper + if 'test.cov' in sys.modules: # -Xpresite=test.cov used + cov = sys.monitoring.COVERAGE_ID + @functools.wraps(func) + def coverage_wrapper(*args, **kwargs): + original_events = sys.monitoring.get_events(cov) + try: + sys.monitoring.set_events(cov, 0) + return trace_wrapper(*args, **kwargs) + finally: + sys.monitoring.set_events(cov, original_events) + + return coverage_wrapper def refcount_test(test): @@ -1088,158 +1130,12 @@ def requires_limited_api(test): import _testcapi except ImportError: return unittest.skip('needs _testcapi module')(test) - return unittest.skipUnless( - _testcapi.LIMITED_API_AVAILABLE, 'needs Limited API support')(test) + return test def requires_specialization(test): return unittest.skipUnless( _opcode.ENABLE_SPECIALIZATION, "requires specialization")(test) -def _filter_suite(suite, pred): - """Recursively filter test cases in a suite based on a predicate.""" - newtests = [] - for test in suite._tests: - if isinstance(test, unittest.TestSuite): - _filter_suite(test, pred) - newtests.append(test) - else: - if pred(test): - newtests.append(test) - suite._tests = newtests - -def _run_suite(suite): - """Run tests from a unittest.TestSuite-derived class.""" - runner = get_test_runner(sys.stdout, - verbosity=verbose, - capture_output=(junit_xml_list is not None)) - - result = runner.run(suite) - - if junit_xml_list is not None: - junit_xml_list.append(result.get_xml_element()) - - if not result.testsRun and not result.skipped and not result.errors: - raise TestDidNotRun - if not result.wasSuccessful(): - if len(result.errors) == 1 and not result.failures: - err = result.errors[0][1] - elif len(result.failures) == 1 and not result.errors: - err = result.failures[0][1] - else: - err = "multiple errors occurred" - if not verbose: err += "; run in verbose mode for details" - errors = [(str(tc), exc_str) for tc, exc_str in result.errors] - failures = [(str(tc), exc_str) for tc, exc_str in result.failures] - raise TestFailedWithDetails(err, errors, failures) - - -# By default, don't filter tests -_match_test_func = None - -_accept_test_patterns = None -_ignore_test_patterns = None - - -def match_test(test): - # Function used by support.run_unittest() and regrtest --list-cases - if _match_test_func is None: - return True - else: - return _match_test_func(test.id()) - - -def _is_full_match_test(pattern): - # If a pattern contains at least one dot, it's considered - # as a full test identifier. - # Example: 'test.test_os.FileTests.test_access'. - # - # ignore patterns which contain fnmatch patterns: '*', '?', '[...]' - # or '[!...]'. For example, ignore 'test_access*'. - return ('.' in pattern) and (not re.search(r'[?*\[\]]', pattern)) - - -def set_match_tests(accept_patterns=None, ignore_patterns=None): - global _match_test_func, _accept_test_patterns, _ignore_test_patterns - - - if accept_patterns is None: - accept_patterns = () - if ignore_patterns is None: - ignore_patterns = () - - accept_func = ignore_func = None - - if accept_patterns != _accept_test_patterns: - accept_patterns, accept_func = _compile_match_function(accept_patterns) - if ignore_patterns != _ignore_test_patterns: - ignore_patterns, ignore_func = _compile_match_function(ignore_patterns) - - # Create a copy since patterns can be mutable and so modified later - _accept_test_patterns = tuple(accept_patterns) - _ignore_test_patterns = tuple(ignore_patterns) - - if accept_func is not None or ignore_func is not None: - def match_function(test_id): - accept = True - ignore = False - if accept_func: - accept = accept_func(test_id) - if ignore_func: - ignore = ignore_func(test_id) - return accept and not ignore - - _match_test_func = match_function - - -def _compile_match_function(patterns): - if not patterns: - func = None - # set_match_tests(None) behaves as set_match_tests(()) - patterns = () - elif all(map(_is_full_match_test, patterns)): - # Simple case: all patterns are full test identifier. - # The test.bisect_cmd utility only uses such full test identifiers. - func = set(patterns).__contains__ - else: - import fnmatch - regex = '|'.join(map(fnmatch.translate, patterns)) - # The search *is* case sensitive on purpose: - # don't use flags=re.IGNORECASE - regex_match = re.compile(regex).match - - def match_test_regex(test_id): - if regex_match(test_id): - # The regex matches the whole identifier, for example - # 'test.test_os.FileTests.test_access'. - return True - else: - # Try to match parts of the test identifier. - # For example, split 'test.test_os.FileTests.test_access' - # into: 'test', 'test_os', 'FileTests' and 'test_access'. - return any(map(regex_match, test_id.split("."))) - - func = match_test_regex - - return patterns, func - - -def run_unittest(*classes): - """Run tests from unittest.TestCase-derived classes.""" - valid_types = (unittest.TestSuite, unittest.TestCase) - loader = unittest.TestLoader() - suite = unittest.TestSuite() - for cls in classes: - if isinstance(cls, str): - if cls in sys.modules: - suite.addTest(loader.loadTestsFromModule(sys.modules[cls])) - else: - raise ValueError("str arguments must be keys in sys.modules") - elif isinstance(cls, valid_types): - suite.addTest(cls) - else: - suite.addTest(loader.loadTestsFromTestCase(cls)) - _filter_suite(suite, match_test) - _run_suite(suite) #======================================================================= # Check for the presence of docstrings. @@ -1261,33 +1157,6 @@ def _check_docstrings(): "test requires docstrings") -#======================================================================= -# doctest driver. - -def run_doctest(module, verbosity=None, optionflags=0): - """Run doctest on the given module. Return (#failures, #tests). - - If optional argument verbosity is not specified (or is None), pass - support's belief about verbosity on to doctest. Else doctest's - usual behavior is used (it searches sys.argv for -v). - """ - - import doctest - - if verbosity is None: - verbosity = verbose - else: - verbosity = None - - f, t = doctest.testmod(module, verbose=verbosity, optionflags=optionflags) - if f: - raise TestFailed("%d of %d doctests failed" % (f, t)) - if verbose: - print('doctest (%s) ... %d tests with zero failures' % - (module.__name__, t)) - return f, t - - #======================================================================= # Support for saving and restoring the imported modules. @@ -1820,11 +1689,11 @@ def run_in_subinterp_with_config(code, *, own_gil=None, **config): module is enabled. """ _check_tracemalloc() - import _testcapi + import _testinternalcapi if own_gil is not None: assert 'gil' not in config, (own_gil, config) config['gil'] = 2 if own_gil else 1 - return _testcapi.run_in_subinterp_with_config(code, **config) + return _testinternalcapi.run_in_subinterp_with_config(code, **config) def _check_tracemalloc(): @@ -1980,7 +1849,12 @@ def restore(self): def with_pymalloc(): import _testcapi - return _testcapi.WITH_PYMALLOC + return _testcapi.WITH_PYMALLOC and not Py_GIL_DISABLED + + +def with_mimalloc(): + import _testcapi + return _testcapi.WITH_MIMALLOC class _ALWAYS_EQ: @@ -2209,6 +2083,39 @@ def check_disallow_instantiation(testcase, tp, *args, **kwds): msg = f"cannot create '{re.escape(qualname)}' instances" testcase.assertRaisesRegex(TypeError, msg, tp, *args, **kwds) +def get_recursion_depth(): + """Get the recursion depth of the caller function. + + In the __main__ module, at the module level, it should be 1. + """ + try: + import _testinternalcapi + depth = _testinternalcapi.get_recursion_depth() + except (ImportError, RecursionError) as exc: + # sys._getframe() + frame.f_back implementation. + try: + depth = 0 + frame = sys._getframe() + while frame is not None: + depth += 1 + frame = frame.f_back + finally: + # Break any reference cycles. + frame = None + + # Ignore get_recursion_depth() frame. + return max(depth - 1, 1) + +def get_recursion_available(): + """Get the number of available frames before RecursionError. + + It depends on the current recursion depth of the caller function and + sys.getrecursionlimit(). + """ + limit = sys.getrecursionlimit() + depth = get_recursion_depth() + return limit - depth + @contextlib.contextmanager def set_recursion_limit(limit): """Temporarily change the recursion limit.""" @@ -2219,14 +2126,18 @@ def set_recursion_limit(limit): finally: sys.setrecursionlimit(original_limit) -def infinite_recursion(max_depth=75): - """Set a lower limit for tests that interact with infinite recursions - (e.g test_ast.ASTHelpers_Test.test_recursion_direct) since on some - debug windows builds, due to not enough functions being inlined the - stack size might not handle the default recursion limit (1000). See - bpo-11105 for details.""" - return set_recursion_limit(max_depth) - +def infinite_recursion(max_depth=None): + if max_depth is None: + # Pick a number large enough to cause problems + # but not take too long for code that can handle + # very deep recursion. + max_depth = 20_000 + elif max_depth < 3: + raise ValueError("max_depth must be at least 3, got {max_depth}") + depth = get_recursion_depth() + depth = max(depth - 1, 1) # Ignore infinite_recursion() frame. + limit = depth + max_depth + return set_recursion_limit(limit) def ignore_deprecations_from(module: str, *, like: str) -> object: token = object() @@ -2459,12 +2370,66 @@ def adjust_int_max_str_digits(max_digits): finally: sys.set_int_max_str_digits(current) -#For recursion tests, easily exceeds default recursion limit -EXCEEDS_RECURSION_LIMIT = 5000 -# The default C recursion limit (from Include/cpython/pystate.h). -C_RECURSION_LIMIT = 1500 +def _get_c_recursion_limit(): + try: + import _testcapi + return _testcapi.Py_C_RECURSION_LIMIT + except (ImportError, AttributeError): + # Originally taken from Include/cpython/pystate.h . + return 8000 + +# The default C recursion limit. +Py_C_RECURSION_LIMIT = _get_c_recursion_limit() + +#For recursion tests, easily exceeds default recursion limit +EXCEEDS_RECURSION_LIMIT = Py_C_RECURSION_LIMIT * 3 #Windows doesn't have os.uname() but it doesn't support s390x. skip_on_s390x = unittest.skipIf(hasattr(os, 'uname') and os.uname().machine == 's390x', 'skipped on s390x') + +Py_TRACE_REFS = hasattr(sys, 'getobjects') + +# Decorator to disable optimizer while a function run +def without_optimizer(func): + try: + import _testinternalcapi + except ImportError: + return func + @functools.wraps(func) + def wrapper(*args, **kwargs): + save_opt = _testinternalcapi.get_optimizer() + try: + _testinternalcapi.set_optimizer(None) + return func(*args, **kwargs) + finally: + _testinternalcapi.set_optimizer(save_opt) + return wrapper + + +_BASE_COPY_SRC_DIR_IGNORED_NAMES = frozenset({ + # SRC_DIR/.git + '.git', + # ignore all __pycache__/ sub-directories + '__pycache__', +}) + +# Ignore function for shutil.copytree() to copy the Python source code. +def copy_python_src_ignore(path, names): + ignored = _BASE_COPY_SRC_DIR_IGNORED_NAMES + if os.path.basename(path) == 'Doc': + ignored |= { + # SRC_DIR/Doc/build/ + 'build', + # SRC_DIR/Doc/venv/ + 'venv', + } + + # check if we are at the root of the source code + elif 'Modules' in names: + ignored |= { + # SRC_DIR/build/ + 'build', + } + return ignored diff --git a/Lib/test/support/bytecode_helper.py b/Lib/test/support/bytecode_helper.py index 388d1266773c8a..a4845065a5322e 100644 --- a/Lib/test/support/bytecode_helper.py +++ b/Lib/test/support/bytecode_helper.py @@ -7,6 +7,18 @@ _UNSPECIFIED = object() +def instructions_with_positions(instrs, co_positions): + # Return (instr, positions) pairs from the instrs list and co_positions + # iterator. The latter contains items for cache lines and the former + # doesn't, so those need to be skipped. + + co_positions = co_positions or iter(()) + for instr in instrs: + yield instr, next(co_positions, ()) + for _, size, _ in (instr.cache_info or ()): + for i in range(size): + next(co_positions, ()) + class BytecodeTestCase(unittest.TestCase): """Custom assertion methods for inspecting bytecode.""" diff --git a/Lib/test/support/hypothesis_helper.py b/Lib/test/support/hypothesis_helper.py index da16eb50c25958..db93eea5e912e0 100644 --- a/Lib/test/support/hypothesis_helper.py +++ b/Lib/test/support/hypothesis_helper.py @@ -10,7 +10,10 @@ hypothesis.settings.register_profile( "slow-is-ok", deadline=None, - suppress_health_check=[hypothesis.HealthCheck.too_slow], + suppress_health_check=[ + hypothesis.HealthCheck.too_slow, + hypothesis.HealthCheck.differing_executors, + ], ) hypothesis.settings.load_profile("slow-is-ok") diff --git a/Lib/test/support/import_helper.py b/Lib/test/support/import_helper.py index 67f18e530edc4b..3d804f2b590108 100644 --- a/Lib/test/support/import_helper.py +++ b/Lib/test/support/import_helper.py @@ -8,7 +8,7 @@ import unittest import warnings -from .os_helper import unlink +from .os_helper import unlink, temp_dir @contextlib.contextmanager @@ -274,3 +274,26 @@ def mock_register_at_fork(func): # memory. from unittest import mock return mock.patch('os.register_at_fork', create=True)(func) + + +@contextlib.contextmanager +def ready_to_import(name=None, source=""): + from test.support import script_helper + + # 1. Sets up a temporary directory and removes it afterwards + # 2. Creates the module file + # 3. Temporarily clears the module from sys.modules (if any) + # 4. Reverts or removes the module when cleaning up + name = name or "spam" + with temp_dir() as tempdir: + path = script_helper.make_script(tempdir, name, source) + old_module = sys.modules.pop(name, None) + try: + sys.path.insert(0, tempdir) + yield name, path + sys.path.remove(tempdir) + finally: + if old_module is not None: + sys.modules[name] = old_module + else: + sys.modules.pop(name, None) diff --git a/Lib/test/support/interpreters.py b/Lib/test/support/interpreters.py deleted file mode 100644 index 5c484d1170d1d9..00000000000000 --- a/Lib/test/support/interpreters.py +++ /dev/null @@ -1,198 +0,0 @@ -"""Subinterpreters High Level Module.""" - -import time -import _xxsubinterpreters as _interpreters -import _xxinterpchannels as _channels - -# aliases: -from _xxsubinterpreters import is_shareable, RunFailedError -from _xxinterpchannels import ( - ChannelError, ChannelNotFoundError, ChannelEmptyError, -) - - -__all__ = [ - 'Interpreter', 'get_current', 'get_main', 'create', 'list_all', - 'SendChannel', 'RecvChannel', - 'create_channel', 'list_all_channels', 'is_shareable', - 'ChannelError', 'ChannelNotFoundError', - 'ChannelEmptyError', - ] - - -def create(*, isolated=True): - """Return a new (idle) Python interpreter.""" - id = _interpreters.create(isolated=isolated) - return Interpreter(id, isolated=isolated) - - -def list_all(): - """Return all existing interpreters.""" - return [Interpreter(id) for id in _interpreters.list_all()] - - -def get_current(): - """Return the currently running interpreter.""" - id = _interpreters.get_current() - return Interpreter(id) - - -def get_main(): - """Return the main interpreter.""" - id = _interpreters.get_main() - return Interpreter(id) - - -class Interpreter: - """A single Python interpreter.""" - - def __init__(self, id, *, isolated=None): - if not isinstance(id, (int, _interpreters.InterpreterID)): - raise TypeError(f'id must be an int, got {id!r}') - self._id = id - self._isolated = isolated - - def __repr__(self): - data = dict(id=int(self._id), isolated=self._isolated) - kwargs = (f'{k}={v!r}' for k, v in data.items()) - return f'{type(self).__name__}({", ".join(kwargs)})' - - def __hash__(self): - return hash(self._id) - - def __eq__(self, other): - if not isinstance(other, Interpreter): - return NotImplemented - else: - return other._id == self._id - - @property - def id(self): - return self._id - - @property - def isolated(self): - if self._isolated is None: - # XXX The low-level function has not been added yet. - # See bpo-.... - self._isolated = _interpreters.is_isolated(self._id) - return self._isolated - - def is_running(self): - """Return whether or not the identified interpreter is running.""" - return _interpreters.is_running(self._id) - - def close(self): - """Finalize and destroy the interpreter. - - Attempting to destroy the current interpreter results - in a RuntimeError. - """ - return _interpreters.destroy(self._id) - - def run(self, src_str, /, *, channels=None): - """Run the given source code in the interpreter. - - This blocks the current Python thread until done. - """ - _interpreters.run_string(self._id, src_str, channels) - - -def create_channel(): - """Return (recv, send) for a new cross-interpreter channel. - - The channel may be used to pass data safely between interpreters. - """ - cid = _channels.create() - recv, send = RecvChannel(cid), SendChannel(cid) - return recv, send - - -def list_all_channels(): - """Return a list of (recv, send) for all open channels.""" - return [(RecvChannel(cid), SendChannel(cid)) - for cid in _channels.list_all()] - - -class _ChannelEnd: - """The base class for RecvChannel and SendChannel.""" - - def __init__(self, id): - if not isinstance(id, (int, _channels.ChannelID)): - raise TypeError(f'id must be an int, got {id!r}') - self._id = id - - def __repr__(self): - return f'{type(self).__name__}(id={int(self._id)})' - - def __hash__(self): - return hash(self._id) - - def __eq__(self, other): - if isinstance(self, RecvChannel): - if not isinstance(other, RecvChannel): - return NotImplemented - elif not isinstance(other, SendChannel): - return NotImplemented - return other._id == self._id - - @property - def id(self): - return self._id - - -_NOT_SET = object() - - -class RecvChannel(_ChannelEnd): - """The receiving end of a cross-interpreter channel.""" - - def recv(self, *, _sentinel=object(), _delay=10 / 1000): # 10 milliseconds - """Return the next object from the channel. - - This blocks until an object has been sent, if none have been - sent already. - """ - obj = _channels.recv(self._id, _sentinel) - while obj is _sentinel: - time.sleep(_delay) - obj = _channels.recv(self._id, _sentinel) - return obj - - def recv_nowait(self, default=_NOT_SET): - """Return the next object from the channel. - - If none have been sent then return the default if one - is provided or fail with ChannelEmptyError. Otherwise this - is the same as recv(). - """ - if default is _NOT_SET: - return _channels.recv(self._id) - else: - return _channels.recv(self._id, default) - - -class SendChannel(_ChannelEnd): - """The sending end of a cross-interpreter channel.""" - - def send(self, obj): - """Send the object (i.e. its data) to the channel's receiving end. - - This blocks until the object is received. - """ - _channels.send(self._id, obj) - # XXX We are missing a low-level channel_send_wait(). - # See bpo-32604 and gh-19829. - # Until that shows up we fake it: - time.sleep(2) - - def send_nowait(self, obj): - """Send the object to the channel's receiving end. - - If the object is immediately received then return True - (else False). Otherwise this is the same as send(). - """ - # XXX Note that at the moment channel_send() only ever returns - # None. This should be fixed when channel_send_wait() is added. - # See bpo-32604 and gh-19829. - return _channels.send(self._id, obj) diff --git a/Lib/test/support/interpreters/__init__.py b/Lib/test/support/interpreters/__init__.py new file mode 100644 index 00000000000000..15a908e9663593 --- /dev/null +++ b/Lib/test/support/interpreters/__init__.py @@ -0,0 +1,187 @@ +"""Subinterpreters High Level Module.""" + +import threading +import weakref +import _xxsubinterpreters as _interpreters + +# aliases: +from _xxsubinterpreters import ( + InterpreterError, InterpreterNotFoundError, + is_shareable, +) + + +__all__ = [ + 'get_current', 'get_main', 'create', 'list_all', 'is_shareable', + 'Interpreter', + 'InterpreterError', 'InterpreterNotFoundError', 'ExecFailure', + 'create_queue', 'Queue', 'QueueEmpty', 'QueueFull', +] + + +_queuemod = None + +def __getattr__(name): + if name in ('Queue', 'QueueEmpty', 'QueueFull', 'create_queue'): + global create_queue, Queue, QueueEmpty, QueueFull + ns = globals() + from .queues import ( + create as create_queue, + Queue, QueueEmpty, QueueFull, + ) + return ns[name] + else: + raise AttributeError(name) + + +_EXEC_FAILURE_STR = """ +{superstr} + +Uncaught in the interpreter: + +{formatted} +""".strip() + +class ExecFailure(RuntimeError): + + def __init__(self, excinfo): + msg = excinfo.formatted + if not msg: + if excinfo.type and excinfo.msg: + msg = f'{excinfo.type.__name__}: {excinfo.msg}' + else: + msg = excinfo.type.__name__ or excinfo.msg + super().__init__(msg) + self.excinfo = excinfo + + def __str__(self): + try: + formatted = self.excinfo.errdisplay + except Exception: + return super().__str__() + else: + return _EXEC_FAILURE_STR.format( + superstr=super().__str__(), + formatted=formatted, + ) + + +def create(): + """Return a new (idle) Python interpreter.""" + id = _interpreters.create(isolated=True) + return Interpreter(id) + + +def list_all(): + """Return all existing interpreters.""" + return [Interpreter(id) for id in _interpreters.list_all()] + + +def get_current(): + """Return the currently running interpreter.""" + id = _interpreters.get_current() + return Interpreter(id) + + +def get_main(): + """Return the main interpreter.""" + id = _interpreters.get_main() + return Interpreter(id) + + +_known = weakref.WeakValueDictionary() + +class Interpreter: + """A single Python interpreter.""" + + def __new__(cls, id, /): + # There is only one instance for any given ID. + if not isinstance(id, int): + raise TypeError(f'id must be an int, got {id!r}') + id = int(id) + try: + self = _known[id] + assert hasattr(self, '_ownsref') + except KeyError: + # This may raise InterpreterNotFoundError: + _interpreters._incref(id) + try: + self = super().__new__(cls) + self._id = id + self._ownsref = True + except BaseException: + _interpreters._deccref(id) + raise + _known[id] = self + return self + + def __repr__(self): + return f'{type(self).__name__}({self.id})' + + def __hash__(self): + return hash(self._id) + + def __del__(self): + self._decref() + + def _decref(self): + if not self._ownsref: + return + self._ownsref = False + try: + _interpreters._decref(self.id) + except InterpreterNotFoundError: + pass + + @property + def id(self): + return self._id + + def is_running(self): + """Return whether or not the identified interpreter is running.""" + return _interpreters.is_running(self._id) + + def close(self): + """Finalize and destroy the interpreter. + + Attempting to destroy the current interpreter results + in a RuntimeError. + """ + return _interpreters.destroy(self._id) + + def prepare_main(self, ns=None, /, **kwargs): + """Bind the given values into the interpreter's __main__. + + The values must be shareable. + """ + ns = dict(ns, **kwargs) if ns is not None else kwargs + _interpreters.set___main___attrs(self._id, ns) + + def exec_sync(self, code, /): + """Run the given source code in the interpreter. + + This is essentially the same as calling the builtin "exec" + with this interpreter, using the __dict__ of its __main__ + module as both globals and locals. + + There is no return value. + + If the code raises an unhandled exception then an ExecFailure + is raised, which summarizes the unhandled exception. The actual + exception is discarded because objects cannot be shared between + interpreters. + + This blocks the current Python thread until done. During + that time, the previous interpreter is allowed to run + in other threads. + """ + excinfo = _interpreters.exec(self._id, code) + if excinfo is not None: + raise ExecFailure(excinfo) + + def run(self, code, /): + def task(): + self.exec_sync(code) + t = threading.Thread(target=task) + t.start() + return t diff --git a/Lib/test/support/interpreters/channels.py b/Lib/test/support/interpreters/channels.py new file mode 100644 index 00000000000000..75a5a60f54f926 --- /dev/null +++ b/Lib/test/support/interpreters/channels.py @@ -0,0 +1,171 @@ +"""Cross-interpreter Channels High Level Module.""" + +import time +import _xxinterpchannels as _channels + +# aliases: +from _xxinterpchannels import ( + ChannelError, ChannelNotFoundError, ChannelClosedError, + ChannelEmptyError, ChannelNotEmptyError, +) + + +__all__ = [ + 'create', 'list_all', + 'SendChannel', 'RecvChannel', + 'ChannelError', 'ChannelNotFoundError', 'ChannelEmptyError', +] + + +def create(): + """Return (recv, send) for a new cross-interpreter channel. + + The channel may be used to pass data safely between interpreters. + """ + cid = _channels.create() + recv, send = RecvChannel(cid), SendChannel(cid) + return recv, send + + +def list_all(): + """Return a list of (recv, send) for all open channels.""" + return [(RecvChannel(cid), SendChannel(cid)) + for cid in _channels.list_all()] + + +class _ChannelEnd: + """The base class for RecvChannel and SendChannel.""" + + _end = None + + def __init__(self, cid): + if self._end == 'send': + cid = _channels._channel_id(cid, send=True, force=True) + elif self._end == 'recv': + cid = _channels._channel_id(cid, recv=True, force=True) + else: + raise NotImplementedError(self._end) + self._id = cid + + def __repr__(self): + return f'{type(self).__name__}(id={int(self._id)})' + + def __hash__(self): + return hash(self._id) + + def __eq__(self, other): + if isinstance(self, RecvChannel): + if not isinstance(other, RecvChannel): + return NotImplemented + elif not isinstance(other, SendChannel): + return NotImplemented + return other._id == self._id + + @property + def id(self): + return self._id + + @property + def _info(self): + return _channels.get_info(self._id) + + @property + def is_closed(self): + return self._info.closed + + +_NOT_SET = object() + + +class RecvChannel(_ChannelEnd): + """The receiving end of a cross-interpreter channel.""" + + _end = 'recv' + + def recv(self, timeout=None, *, + _sentinel=object(), + _delay=10 / 1000, # 10 milliseconds + ): + """Return the next object from the channel. + + This blocks until an object has been sent, if none have been + sent already. + """ + if timeout is not None: + timeout = int(timeout) + if timeout < 0: + raise ValueError(f'timeout value must be non-negative') + end = time.time() + timeout + obj = _channels.recv(self._id, _sentinel) + while obj is _sentinel: + time.sleep(_delay) + if timeout is not None and time.time() >= end: + raise TimeoutError + obj = _channels.recv(self._id, _sentinel) + return obj + + def recv_nowait(self, default=_NOT_SET): + """Return the next object from the channel. + + If none have been sent then return the default if one + is provided or fail with ChannelEmptyError. Otherwise this + is the same as recv(). + """ + if default is _NOT_SET: + return _channels.recv(self._id) + else: + return _channels.recv(self._id, default) + + def close(self): + _channels.close(self._id, recv=True) + + +class SendChannel(_ChannelEnd): + """The sending end of a cross-interpreter channel.""" + + _end = 'send' + + @property + def is_closed(self): + info = self._info + return info.closed or info.closing + + def send(self, obj, timeout=None): + """Send the object (i.e. its data) to the channel's receiving end. + + This blocks until the object is received. + """ + _channels.send(self._id, obj, timeout=timeout, blocking=True) + + def send_nowait(self, obj): + """Send the object to the channel's receiving end. + + If the object is immediately received then return True + (else False). Otherwise this is the same as send(). + """ + # XXX Note that at the moment channel_send() only ever returns + # None. This should be fixed when channel_send_wait() is added. + # See bpo-32604 and gh-19829. + return _channels.send(self._id, obj, blocking=False) + + def send_buffer(self, obj, timeout=None): + """Send the object's buffer to the channel's receiving end. + + This blocks until the object is received. + """ + _channels.send_buffer(self._id, obj, timeout=timeout, blocking=True) + + def send_buffer_nowait(self, obj): + """Send the object's buffer to the channel's receiving end. + + If the object is immediately received then return True + (else False). Otherwise this is the same as send(). + """ + return _channels.send_buffer(self._id, obj, blocking=False) + + def close(self): + _channels.close(self._id, send=True) + + +# XXX This is causing leaks (gh-110318): +_channels._register_end_types(SendChannel, RecvChannel) diff --git a/Lib/test/support/interpreters/queues.py b/Lib/test/support/interpreters/queues.py new file mode 100644 index 00000000000000..aead0c40ca9667 --- /dev/null +++ b/Lib/test/support/interpreters/queues.py @@ -0,0 +1,172 @@ +"""Cross-interpreter Queues High Level Module.""" + +import queue +import time +import weakref +import _xxinterpqueues as _queues + +# aliases: +from _xxinterpqueues import ( + QueueError, QueueNotFoundError, +) + +__all__ = [ + 'create', 'list_all', + 'Queue', + 'QueueError', 'QueueNotFoundError', 'QueueEmpty', 'QueueFull', +] + + +class QueueEmpty(_queues.QueueEmpty, queue.Empty): + """Raised from get_nowait() when the queue is empty. + + It is also raised from get() if it times out. + """ + + +class QueueFull(_queues.QueueFull, queue.Full): + """Raised from put_nowait() when the queue is full. + + It is also raised from put() if it times out. + """ + + +def create(maxsize=0): + """Return a new cross-interpreter queue. + + The queue may be used to pass data safely between interpreters. + """ + qid = _queues.create(maxsize) + return Queue(qid) + + +def list_all(): + """Return a list of all open queues.""" + return [Queue(qid) + for qid in _queues.list_all()] + + + +_known_queues = weakref.WeakValueDictionary() + +class Queue: + """A cross-interpreter queue.""" + + def __new__(cls, id, /): + # There is only one instance for any given ID. + if isinstance(id, int): + id = int(id) + else: + raise TypeError(f'id must be an int, got {id!r}') + try: + self = _known_queues[id] + except KeyError: + self = super().__new__(cls) + self._id = id + _known_queues[id] = self + _queues.bind(id) + return self + + def __del__(self): + try: + _queues.release(self._id) + except QueueNotFoundError: + pass + try: + del _known_queues[self._id] + except KeyError: + pass + + def __repr__(self): + return f'{type(self).__name__}({self.id})' + + def __hash__(self): + return hash(self._id) + + @property + def id(self): + return self._id + + @property + def maxsize(self): + try: + return self._maxsize + except AttributeError: + self._maxsize = _queues.get_maxsize(self._id) + return self._maxsize + + def empty(self): + return self.qsize() == 0 + + def full(self): + return _queues.is_full(self._id) + + def qsize(self): + return _queues.get_count(self._id) + + def put(self, obj, timeout=None, *, + _delay=10 / 1000, # 10 milliseconds + ): + """Add the object to the queue. + + This blocks while the queue is full. + """ + if timeout is not None: + timeout = int(timeout) + if timeout < 0: + raise ValueError(f'timeout value must be non-negative') + end = time.time() + timeout + while True: + try: + _queues.put(self._id, obj) + except _queues.QueueFull as exc: + if timeout is not None and time.time() >= end: + exc.__class__ = QueueFull + raise # re-raise + time.sleep(_delay) + else: + break + + def put_nowait(self, obj): + try: + return _queues.put(self._id, obj) + except _queues.QueueFull as exc: + exc.__class__ = QueueFull + raise # re-raise + + def get(self, timeout=None, *, + _delay=10 / 1000, # 10 milliseconds + ): + """Return the next object from the queue. + + This blocks while the queue is empty. + """ + if timeout is not None: + timeout = int(timeout) + if timeout < 0: + raise ValueError(f'timeout value must be non-negative') + end = time.time() + timeout + while True: + try: + return _queues.get(self._id) + except _queues.QueueEmpty as exc: + if timeout is not None and time.time() >= end: + exc.__class__ = QueueEmpty + raise # re-raise + time.sleep(_delay) + return obj + + def get_nowait(self): + """Return the next object from the channel. + + If the queue is empty then raise QueueEmpty. Otherwise this + is the same as get(). + """ + try: + return _queues.get(self._id) + except _queues.QueueEmpty as exc: + exc.__class__ = QueueEmpty + raise # re-raise + + +_queues._register_queue_type(Queue) diff --git a/Lib/test/support/os_helper.py b/Lib/test/support/os_helper.py index 821a4b1ffd5077..20f38fd36a8876 100644 --- a/Lib/test/support/os_helper.py +++ b/Lib/test/support/os_helper.py @@ -10,6 +10,8 @@ import unittest import warnings +from test import support + # Filename used for testing TESTFN_ASCII = '@test' @@ -245,15 +247,15 @@ def can_chmod(): global _can_chmod if _can_chmod is not None: return _can_chmod - if not hasattr(os, "chown"): + if not hasattr(os, "chmod"): _can_chmod = False return _can_chmod try: with open(TESTFN, "wb") as f: try: - os.chmod(TESTFN, 0o777) + os.chmod(TESTFN, 0o555) mode1 = os.stat(TESTFN).st_mode - os.chmod(TESTFN, 0o666) + os.chmod(TESTFN, 0o777) mode2 = os.stat(TESTFN).st_mode except OSError as e: can = False @@ -300,6 +302,10 @@ def can_dac_override(): else: _can_dac_override = True finally: + try: + os.chmod(TESTFN, 0o700) + except OSError: + pass unlink(TESTFN) return _can_dac_override @@ -590,10 +596,17 @@ def fd_count(): """Count the number of open file descriptors. """ if sys.platform.startswith(('linux', 'freebsd', 'emscripten')): + fd_path = "/proc/self/fd" + elif sys.platform == "darwin": + fd_path = "/dev/fd" + else: + fd_path = None + + if fd_path is not None: try: - names = os.listdir("/proc/self/fd") + names = os.listdir(fd_path) # Subtract one because listdir() internally opens a file - # descriptor to list the content of the /proc/self/fd/ directory. + # descriptor to list the content of the directory. return len(names) - 1 except FileNotFoundError: pass @@ -720,13 +733,16 @@ def __exit__(self, *ignore_exc): try: - import ctypes - kernel32 = ctypes.WinDLL('kernel32', use_last_error=True) - - ERROR_FILE_NOT_FOUND = 2 - DDD_REMOVE_DEFINITION = 2 - DDD_EXACT_MATCH_ON_REMOVE = 4 - DDD_NO_BROADCAST_SYSTEM = 8 + if support.MS_WINDOWS: + import ctypes + kernel32 = ctypes.WinDLL('kernel32', use_last_error=True) + + ERROR_FILE_NOT_FOUND = 2 + DDD_REMOVE_DEFINITION = 2 + DDD_EXACT_MATCH_ON_REMOVE = 4 + DDD_NO_BROADCAST_SYSTEM = 8 + else: + raise AttributeError except (ImportError, AttributeError): def subst_drive(path): raise unittest.SkipTest('ctypes or kernel32 is not available') diff --git a/Lib/test/support/pty_helper.py b/Lib/test/support/pty_helper.py new file mode 100644 index 00000000000000..11037d22516448 --- /dev/null +++ b/Lib/test/support/pty_helper.py @@ -0,0 +1,60 @@ +""" +Helper to run a script in a pseudo-terminal. +""" +import os +import selectors +import subprocess +import sys +from contextlib import ExitStack +from errno import EIO + +from test.support.import_helper import import_module + +def run_pty(script, input=b"dummy input\r", env=None): + pty = import_module('pty') + output = bytearray() + [master, slave] = pty.openpty() + args = (sys.executable, '-c', script) + proc = subprocess.Popen(args, stdin=slave, stdout=slave, stderr=slave, env=env) + os.close(slave) + with ExitStack() as cleanup: + cleanup.enter_context(proc) + def terminate(proc): + try: + proc.terminate() + except ProcessLookupError: + # Workaround for Open/Net BSD bug (Issue 16762) + pass + cleanup.callback(terminate, proc) + cleanup.callback(os.close, master) + # Avoid using DefaultSelector and PollSelector. Kqueue() does not + # work with pseudo-terminals on OS X < 10.9 (Issue 20365) and Open + # BSD (Issue 20667). Poll() does not work with OS X 10.6 or 10.4 + # either (Issue 20472). Hopefully the file descriptor is low enough + # to use with select(). + sel = cleanup.enter_context(selectors.SelectSelector()) + sel.register(master, selectors.EVENT_READ | selectors.EVENT_WRITE) + os.set_blocking(master, False) + while True: + for [_, events] in sel.select(): + if events & selectors.EVENT_READ: + try: + chunk = os.read(master, 0x10000) + except OSError as err: + # Linux raises EIO when slave is closed (Issue 5380) + if err.errno != EIO: + raise + chunk = b"" + if not chunk: + return output + output.extend(chunk) + if events & selectors.EVENT_WRITE: + try: + input = input[os.write(master, input):] + except OSError as err: + # Apparently EIO means the slave was closed + if err.errno != EIO: + raise + input = b"" # Stop writing + if not input: + sel.modify(master, selectors.EVENT_READ) diff --git a/Lib/test/support/script_helper.py b/Lib/test/support/script_helper.py index c2b43f4060eb55..759020c33aa700 100644 --- a/Lib/test/support/script_helper.py +++ b/Lib/test/support/script_helper.py @@ -8,7 +8,6 @@ import os.path import subprocess import py_compile -import zipfile from importlib.util import source_from_cache from test import support @@ -93,13 +92,28 @@ def fail(self, cmd_line): # Executing the interpreter in a subprocess @support.requires_subprocess() def run_python_until_end(*args, **env_vars): + """Used to implement assert_python_*. + + *args are the command line flags to pass to the python interpreter. + **env_vars keyword arguments are environment variables to set on the process. + + If __run_using_command= is supplied, it must be a list of + command line arguments to prepend to the command line used. + Useful when you want to run another command that should launch the + python interpreter via its own arguments. ["/bin/echo", "--"] for + example could print the unquoted python command line instead of + run it. + """ env_required = interpreter_requires_environment() + run_using_command = env_vars.pop('__run_using_command', None) cwd = env_vars.pop('__cwd', None) if '__isolated' in env_vars: isolated = env_vars.pop('__isolated') else: isolated = not env_vars and not env_required cmd_line = [sys.executable, '-X', 'faulthandler'] + if run_using_command: + cmd_line = run_using_command + cmd_line if isolated: # isolated mode: ignore Python environment variables, ignore user # site-packages, and don't add the current directory to sys.path @@ -226,6 +240,7 @@ def make_script(script_dir, script_basename, source, omit_suffix=False): def make_zip_script(zip_dir, zip_basename, script_name, name_in_zip=None): + import zipfile zip_filename = zip_basename+os.extsep+'zip' zip_name = os.path.join(zip_dir, zip_filename) with zipfile.ZipFile(zip_name, 'w') as zip_file: @@ -252,6 +267,7 @@ def make_pkg(pkg_dir, init_source=''): def make_zip_pkg(zip_dir, zip_basename, pkg_name, script_basename, source, depth=1, compiled=False): + import zipfile unlink = [] init_name = make_script(zip_dir, '__init__', '') unlink.append(init_name) diff --git a/Lib/test/support/socket_helper.py b/Lib/test/support/socket_helper.py index 45f6d65c355dd4..87941ee1791b4e 100644 --- a/Lib/test/support/socket_helper.py +++ b/Lib/test/support/socket_helper.py @@ -3,6 +3,7 @@ import os.path import socket import sys +import subprocess import tempfile import unittest @@ -277,3 +278,62 @@ def create_unix_domain_name(): """ return tempfile.mktemp(prefix="test_python_", suffix='.sock', dir=os.path.curdir) + + +# consider that sysctl values should not change while tests are running +_sysctl_cache = {} + +def _get_sysctl(name): + """Get a sysctl value as an integer.""" + try: + return _sysctl_cache[name] + except KeyError: + pass + + # At least Linux and FreeBSD support the "-n" option + cmd = ['sysctl', '-n', name] + proc = subprocess.run(cmd, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + text=True) + if proc.returncode: + support.print_warning(f'{' '.join(cmd)!r} command failed with ' + f'exit code {proc.returncode}') + # cache the error to only log the warning once + _sysctl_cache[name] = None + return None + output = proc.stdout + + # Parse '0\n' to get '0' + try: + value = int(output.strip()) + except Exception as exc: + support.print_warning(f'Failed to parse {' '.join(cmd)!r} ' + f'command output {output!r}: {exc!r}') + # cache the error to only log the warning once + _sysctl_cache[name] = None + return None + + _sysctl_cache[name] = value + return value + + +def tcp_blackhole(): + if not sys.platform.startswith('freebsd'): + return False + + # gh-109015: test if FreeBSD TCP blackhole is enabled + value = _get_sysctl('net.inet.tcp.blackhole') + if value is None: + # don't skip if we fail to get the sysctl value + return False + return (value != 0) + + +def skip_if_tcp_blackhole(test): + """Decorator skipping test if TCP blackhole is enabled.""" + skip_if = unittest.skipIf( + tcp_blackhole(), + "TCP blackhole is enabled (sysctl net.inet.tcp.blackhole)" + ) + return skip_if(test) diff --git a/Lib/test/support/threading_helper.py b/Lib/test/support/threading_helper.py index 7f16050f32b9d1..afa25a76f63829 100644 --- a/Lib/test/support/threading_helper.py +++ b/Lib/test/support/threading_helper.py @@ -22,34 +22,37 @@ def threading_setup(): - return _thread._count(), threading._dangling.copy() + return _thread._count(), len(threading._dangling) def threading_cleanup(*original_values): - _MAX_COUNT = 100 - - for count in range(_MAX_COUNT): - values = _thread._count(), threading._dangling - if values == original_values: - break - - if not count: - # Display a warning at the first iteration - support.environment_altered = True - dangling_threads = values[1] - support.print_warning(f"threading_cleanup() failed to cleanup " - f"{values[0] - original_values[0]} threads " - f"(count: {values[0]}, " - f"dangling: {len(dangling_threads)})") - for thread in dangling_threads: - support.print_warning(f"Dangling thread: {thread!r}") - - # Don't hold references to threads - dangling_threads = None - values = None - - time.sleep(0.01) - support.gc_collect() + orig_count, orig_ndangling = original_values + + timeout = 1.0 + for _ in support.sleeping_retry(timeout, error=False): + # Copy the thread list to get a consistent output. threading._dangling + # is a WeakSet, its value changes when it's read. + dangling_threads = list(threading._dangling) + count = _thread._count() + + if count <= orig_count: + return + + # Timeout! + support.environment_altered = True + support.print_warning( + f"threading_cleanup() failed to clean up threads " + f"in {timeout:.1f} seconds\n" + f" before: thread count={orig_count}, dangling={orig_ndangling}\n" + f" after: thread count={count}, dangling={len(dangling_threads)}") + for thread in dangling_threads: + support.print_warning(f"Dangling thread: {thread!r}") + + # The warning happens when a test spawns threads and some of these threads + # are still running after the test completes. To fix this warning, join + # threads explicitly to wait until they complete. + # + # To make the warning more likely, reduce the timeout. def reap_threads(func): diff --git a/Lib/test/test___all__.py b/Lib/test/test___all__.py index 2163f1636566b7..c87cde4b3d1fab 100644 --- a/Lib/test/test___all__.py +++ b/Lib/test/test___all__.py @@ -12,10 +12,19 @@ if support.check_sanitizer(address=True, memory=True): - # bpo-46633: test___all__ is skipped because importing some modules - # directly can trigger known problems with ASAN (like tk). - raise unittest.SkipTest("workaround ASAN build issues on loading tests " - "like tk") + SKIP_MODULES = frozenset(( + # gh-90791: Tests involving libX11 can SEGFAULT on ASAN/MSAN builds. + # Skip modules, packages and tests using '_tkinter'. + '_tkinter', + 'tkinter', + 'test_tkinter', + 'test_ttk', + 'test_ttk_textonly', + 'idlelib', + 'test_idle', + )) +else: + SKIP_MODULES = () class NoAll(RuntimeError): @@ -83,15 +92,23 @@ def walk_modules(self, basedir, modpath): for fn in sorted(os.listdir(basedir)): path = os.path.join(basedir, fn) if os.path.isdir(path): + if fn in SKIP_MODULES: + continue pkg_init = os.path.join(path, '__init__.py') if os.path.exists(pkg_init): yield pkg_init, modpath + fn for p, m in self.walk_modules(path, modpath + fn + "."): yield p, m continue - if not fn.endswith('.py') or fn == '__init__.py': + + if fn == '__init__.py': + continue + if not fn.endswith('.py'): + continue + modname = fn.removesuffix('.py') + if modname in SKIP_MODULES: continue - yield path, modpath + fn[:-3] + yield path, modpath + modname def test_all(self): # List of denied modules and packages @@ -119,14 +136,14 @@ def test_all(self): if denied: continue if support.verbose: - print(modname) + print(f"Check {modname}", flush=True) try: # This heuristic speeds up the process by removing, de facto, # most test modules (and avoiding the auto-executing ones). with open(path, "rb") as f: if b"__all__" not in f.read(): raise NoAll(modname) - self.check_all(modname) + self.check_all(modname) except NoAll: ignored.append(modname) except FailedImport: diff --git a/Lib/test/test__opcode.py b/Lib/test/test__opcode.py index c1f612dc4a63cb..10f04b64dda40e 100644 --- a/Lib/test/test__opcode.py +++ b/Lib/test/test__opcode.py @@ -8,6 +8,14 @@ class OpListTests(unittest.TestCase): + def check_bool_function_result(self, func, ops, expected): + for op in ops: + if isinstance(op, str): + op = dis.opmap[op] + with self.subTest(opcode=op, func=func): + self.assertIsInstance(func(op), bool) + self.assertEqual(func(op), expected) + def test_invalid_opcodes(self): invalid = [-100, -1, 255, 512, 513, 1000] self.check_bool_function_result(_opcode.is_valid, invalid, False) @@ -47,7 +55,7 @@ def check_function(self, func, expected): check_function(self, _opcode.has_exc, dis.hasexc) -class OpListTests(unittest.TestCase): +class StackEffectTests(unittest.TestCase): def test_stack_effect(self): self.assertEqual(stack_effect(dis.opmap['POP_TOP']), -1) self.assertEqual(stack_effect(dis.opmap['BUILD_SLICE'], 0), -1) diff --git a/Lib/test/test__xxinterpchannels.py b/Lib/test/test__xxinterpchannels.py index 750cd99b85e7a6..cc2ed7849b0c0f 100644 --- a/Lib/test/test__xxinterpchannels.py +++ b/Lib/test/test__xxinterpchannels.py @@ -21,6 +21,13 @@ ################################## # helpers +def recv_wait(cid): + while True: + try: + return channels.recv(cid) + except channels.ChannelEmptyError: + time.sleep(0.1) + #@contextmanager #def run_threaded(id, source, **shared): # def run(): @@ -72,8 +79,7 @@ def __new__(cls, name=None, id=None): name = 'interp' elif name == 'main': raise ValueError('name mismatch (unexpected "main")') - if not isinstance(id, interpreters.InterpreterID): - id = interpreters.InterpreterID(id) + assert isinstance(id, int), repr(id) elif not name or name == 'main': name = 'main' id = main @@ -189,7 +195,7 @@ def run_action(cid, action, end, state, *, hideclosed=True): def _run_action(cid, action, end, state): if action == 'use': if end == 'send': - channels.send(cid, b'spam') + channels.send(cid, b'spam', blocking=False) return state.incr() elif end == 'recv': if not state.pending: @@ -332,7 +338,7 @@ def test_shareable(self): chan = channels.create() obj = channels.create() - channels.send(chan, obj) + channels.send(chan, obj, blocking=False) got = channels.recv(chan) self.assertEqual(got, obj) @@ -390,7 +396,7 @@ def test_channel_list_interpreters_basic(self): """Test basic listing channel interpreters.""" interp0 = interpreters.get_main() cid = channels.create() - channels.send(cid, "send") + channels.send(cid, "send", blocking=False) # Test for a channel that has one end associated to an interpreter. send_interps = channels.list_interpreters(cid, send=True) recv_interps = channels.list_interpreters(cid, send=False) @@ -416,10 +422,10 @@ def test_channel_list_interpreters_multiple(self): interp3 = interpreters.create() cid = channels.create() - channels.send(cid, "send") + channels.send(cid, "send", blocking=False) _run_output(interp1, dedent(f""" import _xxinterpchannels as _channels - _channels.send({cid}, "send") + _channels.send({cid}, "send", blocking=False) """)) _run_output(interp2, dedent(f""" import _xxinterpchannels as _channels @@ -439,7 +445,7 @@ def test_channel_list_interpreters_destroyed(self): interp0 = interpreters.get_main() interp1 = interpreters.create() cid = channels.create() - channels.send(cid, "send") + channels.send(cid, "send", blocking=False) _run_output(interp1, dedent(f""" import _xxinterpchannels as _channels obj = _channels.recv({cid}) @@ -465,12 +471,12 @@ def test_channel_list_interpreters_released(self): interp1 = interpreters.create() interp2 = interpreters.create() cid = channels.create() - channels.send(cid, "data") + channels.send(cid, "data", blocking=False) _run_output(interp1, dedent(f""" import _xxinterpchannels as _channels obj = _channels.recv({cid}) """)) - channels.send(cid, "data") + channels.send(cid, "data", blocking=False) _run_output(interp2, dedent(f""" import _xxinterpchannels as _channels obj = _channels.recv({cid}) @@ -506,7 +512,7 @@ def test_channel_list_interpreters_closed(self): interp1 = interpreters.create() cid = channels.create() # Put something in the channel so that it's not empty. - channels.send(cid, "send") + channels.send(cid, "send", blocking=False) # Check initial state. send_interps = channels.list_interpreters(cid, send=True) @@ -528,7 +534,7 @@ def test_channel_list_interpreters_closed_send_end(self): interp1 = interpreters.create() cid = channels.create() # Put something in the channel so that it's not empty. - channels.send(cid, "send") + channels.send(cid, "send", blocking=False) # Check initial state. send_interps = channels.list_interpreters(cid, send=True) @@ -557,12 +563,67 @@ def test_channel_list_interpreters_closed_send_end(self): with self.assertRaises(channels.ChannelClosedError): channels.list_interpreters(cid, send=False) - #################### + def test_allowed_types(self): + cid = channels.create() + objects = [ + None, + 'spam', + b'spam', + 42, + ] + for obj in objects: + with self.subTest(obj): + channels.send(cid, obj, blocking=False) + got = channels.recv(cid) + + self.assertEqual(got, obj) + self.assertIs(type(got), type(obj)) + # XXX Check the following? + #self.assertIsNot(got, obj) + # XXX What about between interpreters? + + def test_run_string_arg_unresolved(self): + cid = channels.create() + interp = interpreters.create() + + interpreters.set___main___attrs(interp, dict(cid=cid.send)) + out = _run_output(interp, dedent(""" + import _xxinterpchannels as _channels + print(cid.end) + _channels.send(cid, b'spam', blocking=False) + """)) + obj = channels.recv(cid) + + self.assertEqual(obj, b'spam') + self.assertEqual(out.strip(), 'send') + + # XXX For now there is no high-level channel into which the + # sent channel ID can be converted... + # Note: this test caused crashes on some buildbots (bpo-33615). + @unittest.skip('disabled until high-level channels exist') + def test_run_string_arg_resolved(self): + cid = channels.create() + cid = channels._channel_id(cid, _resolve=True) + interp = interpreters.create() + + out = _run_output(interp, dedent(""" + import _xxinterpchannels as _channels + print(chan.id.end) + _channels.send(chan.id, b'spam', blocking=False) + """), + dict(chan=cid.send)) + obj = channels.recv(cid) + + self.assertEqual(obj, b'spam') + self.assertEqual(out.strip(), 'send') + + #------------------- + # send/recv def test_send_recv_main(self): cid = channels.create() orig = b'spam' - channels.send(cid, orig) + channels.send(cid, orig, blocking=False) obj = channels.recv(cid) self.assertEqual(obj, orig) @@ -574,7 +635,7 @@ def test_send_recv_same_interpreter(self): import _xxinterpchannels as _channels cid = _channels.create() orig = b'spam' - _channels.send(cid, orig) + _channels.send(cid, orig, blocking=False) obj = _channels.recv(cid) assert obj is not orig assert obj == orig @@ -585,7 +646,7 @@ def test_send_recv_different_interpreters(self): id1 = interpreters.create() out = _run_output(id1, dedent(f""" import _xxinterpchannels as _channels - _channels.send({cid}, b'spam') + _channels.send({cid}, b'spam', blocking=False) """)) obj = channels.recv(cid) @@ -595,19 +656,14 @@ def test_send_recv_different_threads(self): cid = channels.create() def f(): - while True: - try: - obj = channels.recv(cid) - break - except channels.ChannelEmptyError: - time.sleep(0.1) + obj = recv_wait(cid) channels.send(cid, obj) t = threading.Thread(target=f) t.start() channels.send(cid, b'spam') + obj = recv_wait(cid) t.join() - obj = channels.recv(cid) self.assertEqual(obj, b'spam') @@ -634,8 +690,8 @@ def f(): t.start() channels.send(cid, b'spam') + obj = recv_wait(cid) t.join() - obj = channels.recv(cid) self.assertEqual(obj, b'eggs') @@ -656,10 +712,10 @@ def test_recv_default(self): default = object() cid = channels.create() obj1 = channels.recv(cid, default) - channels.send(cid, None) - channels.send(cid, 1) - channels.send(cid, b'spam') - channels.send(cid, b'eggs') + channels.send(cid, None, blocking=False) + channels.send(cid, 1, blocking=False) + channels.send(cid, b'spam', blocking=False) + channels.send(cid, b'eggs', blocking=False) obj2 = channels.recv(cid, default) obj3 = channels.recv(cid, default) obj4 = channels.recv(cid) @@ -679,7 +735,7 @@ def test_recv_sending_interp_destroyed(self): interp = interpreters.create() interpreters.run_string(interp, dedent(f""" import _xxinterpchannels as _channels - _channels.send({cid1}, b'spam') + _channels.send({cid1}, b'spam', blocking=False) """)) interpreters.destroy(interp) @@ -692,9 +748,9 @@ def test_recv_sending_interp_destroyed(self): interp = interpreters.create() interpreters.run_string(interp, dedent(f""" import _xxinterpchannels as _channels - _channels.send({cid2}, b'spam') + _channels.send({cid2}, b'spam', blocking=False) """)) - channels.send(cid2, b'eggs') + channels.send(cid2, b'eggs', blocking=False) interpreters.destroy(interp) channels.recv(cid2) @@ -703,65 +759,242 @@ def test_recv_sending_interp_destroyed(self): channels.recv(cid2) del cid2 - def test_allowed_types(self): + #------------------- + # send_buffer + + def test_send_buffer(self): + buf = bytearray(b'spamspamspam') cid = channels.create() - objects = [ - None, - 'spam', - b'spam', - 42, - ] - for obj in objects: - with self.subTest(obj): - channels.send(cid, obj) - got = channels.recv(cid) + channels.send_buffer(cid, buf, blocking=False) + obj = channels.recv(cid) - self.assertEqual(got, obj) - self.assertIs(type(got), type(obj)) - # XXX Check the following? - #self.assertIsNot(got, obj) - # XXX What about between interpreters? + self.assertIsNot(obj, buf) + self.assertIsInstance(obj, memoryview) + self.assertEqual(obj, buf) + + buf[4:8] = b'eggs' + self.assertEqual(obj, buf) + obj[4:8] = b'ham.' + self.assertEqual(obj, buf) + + #------------------- + # send with waiting + + def build_send_waiter(self, obj, *, buffer=False): + # We want a long enough sleep that send() actually has to wait. + + if buffer: + send = channels.send_buffer + else: + send = channels.send - def test_run_string_arg_unresolved(self): cid = channels.create() - interp = interpreters.create() + try: + started = time.monotonic() + send(cid, obj, blocking=False) + stopped = time.monotonic() + channels.recv(cid) + finally: + channels.destroy(cid) + delay = stopped - started # seconds + delay *= 3 - out = _run_output(interp, dedent(""" - import _xxinterpchannels as _channels - print(cid.end) - _channels.send(cid, b'spam') - """), - dict(cid=cid.send)) - obj = channels.recv(cid) + def wait(): + time.sleep(delay) + return wait - self.assertEqual(obj, b'spam') - self.assertEqual(out.strip(), 'send') + def test_send_blocking_waiting(self): + received = None + obj = b'spam' + wait = self.build_send_waiter(obj) + cid = channels.create() + def f(): + nonlocal received + wait() + received = recv_wait(cid) + t = threading.Thread(target=f) + t.start() + channels.send(cid, obj, blocking=True) + t.join() - # XXX For now there is no high-level channel into which the - # sent channel ID can be converted... - # Note: this test caused crashes on some buildbots (bpo-33615). - @unittest.skip('disabled until high-level channels exist') - def test_run_string_arg_resolved(self): + self.assertEqual(received, obj) + + def test_send_buffer_blocking_waiting(self): + received = None + obj = bytearray(b'spam') + wait = self.build_send_waiter(obj, buffer=True) cid = channels.create() - cid = channels._channel_id(cid, _resolve=True) - interp = interpreters.create() + def f(): + nonlocal received + wait() + received = recv_wait(cid) + t = threading.Thread(target=f) + t.start() + channels.send_buffer(cid, obj, blocking=True) + t.join() - out = _run_output(interp, dedent(""" - import _xxinterpchannels as _channels - print(chan.id.end) - _channels.send(chan.id, b'spam') - """), - dict(chan=cid.send)) - obj = channels.recv(cid) + self.assertEqual(received, obj) - self.assertEqual(obj, b'spam') - self.assertEqual(out.strip(), 'send') + def test_send_blocking_no_wait(self): + received = None + obj = b'spam' + cid = channels.create() + def f(): + nonlocal received + received = recv_wait(cid) + t = threading.Thread(target=f) + t.start() + channels.send(cid, obj, blocking=True) + t.join() + + self.assertEqual(received, obj) + + def test_send_buffer_blocking_no_wait(self): + received = None + obj = bytearray(b'spam') + cid = channels.create() + def f(): + nonlocal received + received = recv_wait(cid) + t = threading.Thread(target=f) + t.start() + channels.send_buffer(cid, obj, blocking=True) + t.join() + + self.assertEqual(received, obj) + + def test_send_timeout(self): + obj = b'spam' + + with self.subTest('non-blocking with timeout'): + cid = channels.create() + with self.assertRaises(ValueError): + channels.send(cid, obj, blocking=False, timeout=0.1) + + with self.subTest('timeout hit'): + cid = channels.create() + with self.assertRaises(TimeoutError): + channels.send(cid, obj, blocking=True, timeout=0.1) + with self.assertRaises(channels.ChannelEmptyError): + received = channels.recv(cid) + print(repr(received)) + + with self.subTest('timeout not hit'): + cid = channels.create() + def f(): + recv_wait(cid) + t = threading.Thread(target=f) + t.start() + channels.send(cid, obj, blocking=True, timeout=10) + t.join() + + def test_send_buffer_timeout(self): + try: + self._has_run_once_timeout + except AttributeError: + # At the moment, this test leaks a few references. + # It looks like the leak originates with the addition + # of _channels.send_buffer() (gh-110246), whereas the + # tests were added afterward. We want this test even + # if the refleak isn't fixed yet, so we skip here. + raise unittest.SkipTest('temporarily skipped due to refleaks') + else: + self._has_run_once_timeout = True + + obj = bytearray(b'spam') + + with self.subTest('non-blocking with timeout'): + cid = channels.create() + with self.assertRaises(ValueError): + channels.send_buffer(cid, obj, blocking=False, timeout=0.1) + + with self.subTest('timeout hit'): + cid = channels.create() + with self.assertRaises(TimeoutError): + channels.send_buffer(cid, obj, blocking=True, timeout=0.1) + with self.assertRaises(channels.ChannelEmptyError): + received = channels.recv(cid) + print(repr(received)) + + with self.subTest('timeout not hit'): + cid = channels.create() + def f(): + recv_wait(cid) + t = threading.Thread(target=f) + t.start() + channels.send_buffer(cid, obj, blocking=True, timeout=10) + t.join() + + def test_send_closed_while_waiting(self): + obj = b'spam' + wait = self.build_send_waiter(obj) + + with self.subTest('without timeout'): + cid = channels.create() + def f(): + wait() + channels.close(cid, force=True) + t = threading.Thread(target=f) + t.start() + with self.assertRaises(channels.ChannelClosedError): + channels.send(cid, obj, blocking=True) + t.join() + + with self.subTest('with timeout'): + cid = channels.create() + def f(): + wait() + channels.close(cid, force=True) + t = threading.Thread(target=f) + t.start() + with self.assertRaises(channels.ChannelClosedError): + channels.send(cid, obj, blocking=True, timeout=30) + t.join() + def test_send_buffer_closed_while_waiting(self): + try: + self._has_run_once_closed + except AttributeError: + # At the moment, this test leaks a few references. + # It looks like the leak originates with the addition + # of _channels.send_buffer() (gh-110246), whereas the + # tests were added afterward. We want this test even + # if the refleak isn't fixed yet, so we skip here. + raise unittest.SkipTest('temporarily skipped due to refleaks') + else: + self._has_run_once_closed = True + + obj = bytearray(b'spam') + wait = self.build_send_waiter(obj, buffer=True) + + with self.subTest('without timeout'): + cid = channels.create() + def f(): + wait() + channels.close(cid, force=True) + t = threading.Thread(target=f) + t.start() + with self.assertRaises(channels.ChannelClosedError): + channels.send_buffer(cid, obj, blocking=True) + t.join() + + with self.subTest('with timeout'): + cid = channels.create() + def f(): + wait() + channels.close(cid, force=True) + t = threading.Thread(target=f) + t.start() + with self.assertRaises(channels.ChannelClosedError): + channels.send_buffer(cid, obj, blocking=True, timeout=30) + t.join() + + #------------------- # close def test_close_single_user(self): cid = channels.create() - channels.send(cid, b'spam') + channels.send(cid, b'spam', blocking=False) channels.recv(cid) channels.close(cid) @@ -776,27 +1009,27 @@ def test_close_multiple_users(self): id2 = interpreters.create() interpreters.run_string(id1, dedent(f""" import _xxinterpchannels as _channels - _channels.send({cid}, b'spam') + _channels.send({cid}, b'spam', blocking=False) """)) interpreters.run_string(id2, dedent(f""" import _xxinterpchannels as _channels _channels.recv({cid}) """)) channels.close(cid) - with self.assertRaises(interpreters.RunFailedError) as cm: - interpreters.run_string(id1, dedent(f""" + + excsnap = interpreters.run_string(id1, dedent(f""" _channels.send({cid}, b'spam') """)) - self.assertIn('ChannelClosedError', str(cm.exception)) - with self.assertRaises(interpreters.RunFailedError) as cm: - interpreters.run_string(id2, dedent(f""" + self.assertEqual(excsnap.type.__name__, 'ChannelClosedError') + + excsnap = interpreters.run_string(id2, dedent(f""" _channels.send({cid}, b'spam') """)) - self.assertIn('ChannelClosedError', str(cm.exception)) + self.assertEqual(excsnap.type.__name__, 'ChannelClosedError') def test_close_multiple_times(self): cid = channels.create() - channels.send(cid, b'spam') + channels.send(cid, b'spam', blocking=False) channels.recv(cid) channels.close(cid) @@ -813,7 +1046,7 @@ def test_close_empty(self): for send, recv in tests: with self.subTest((send, recv)): cid = channels.create() - channels.send(cid, b'spam') + channels.send(cid, b'spam', blocking=False) channels.recv(cid) channels.close(cid, send=send, recv=recv) @@ -824,31 +1057,31 @@ def test_close_empty(self): def test_close_defaults_with_unused_items(self): cid = channels.create() - channels.send(cid, b'spam') - channels.send(cid, b'ham') + channels.send(cid, b'spam', blocking=False) + channels.send(cid, b'ham', blocking=False) with self.assertRaises(channels.ChannelNotEmptyError): channels.close(cid) channels.recv(cid) - channels.send(cid, b'eggs') + channels.send(cid, b'eggs', blocking=False) def test_close_recv_with_unused_items_unforced(self): cid = channels.create() - channels.send(cid, b'spam') - channels.send(cid, b'ham') + channels.send(cid, b'spam', blocking=False) + channels.send(cid, b'ham', blocking=False) with self.assertRaises(channels.ChannelNotEmptyError): channels.close(cid, recv=True) channels.recv(cid) - channels.send(cid, b'eggs') + channels.send(cid, b'eggs', blocking=False) channels.recv(cid) channels.recv(cid) channels.close(cid, recv=True) def test_close_send_with_unused_items_unforced(self): cid = channels.create() - channels.send(cid, b'spam') - channels.send(cid, b'ham') + channels.send(cid, b'spam', blocking=False) + channels.send(cid, b'ham', blocking=False) channels.close(cid, send=True) with self.assertRaises(channels.ChannelClosedError): @@ -860,21 +1093,21 @@ def test_close_send_with_unused_items_unforced(self): def test_close_both_with_unused_items_unforced(self): cid = channels.create() - channels.send(cid, b'spam') - channels.send(cid, b'ham') + channels.send(cid, b'spam', blocking=False) + channels.send(cid, b'ham', blocking=False) with self.assertRaises(channels.ChannelNotEmptyError): channels.close(cid, recv=True, send=True) channels.recv(cid) - channels.send(cid, b'eggs') + channels.send(cid, b'eggs', blocking=False) channels.recv(cid) channels.recv(cid) channels.close(cid, recv=True) def test_close_recv_with_unused_items_forced(self): cid = channels.create() - channels.send(cid, b'spam') - channels.send(cid, b'ham') + channels.send(cid, b'spam', blocking=False) + channels.send(cid, b'ham', blocking=False) channels.close(cid, recv=True, force=True) with self.assertRaises(channels.ChannelClosedError): @@ -884,8 +1117,8 @@ def test_close_recv_with_unused_items_forced(self): def test_close_send_with_unused_items_forced(self): cid = channels.create() - channels.send(cid, b'spam') - channels.send(cid, b'ham') + channels.send(cid, b'spam', blocking=False) + channels.send(cid, b'ham', blocking=False) channels.close(cid, send=True, force=True) with self.assertRaises(channels.ChannelClosedError): @@ -895,8 +1128,8 @@ def test_close_send_with_unused_items_forced(self): def test_close_both_with_unused_items_forced(self): cid = channels.create() - channels.send(cid, b'spam') - channels.send(cid, b'ham') + channels.send(cid, b'spam', blocking=False) + channels.send(cid, b'ham', blocking=False) channels.close(cid, send=True, recv=True, force=True) with self.assertRaises(channels.ChannelClosedError): @@ -915,7 +1148,7 @@ def test_close_never_used(self): def test_close_by_unassociated_interp(self): cid = channels.create() - channels.send(cid, b'spam') + channels.send(cid, b'spam', blocking=False) interp = interpreters.create() interpreters.run_string(interp, dedent(f""" import _xxinterpchannels as _channels @@ -928,9 +1161,9 @@ def test_close_by_unassociated_interp(self): def test_close_used_multiple_times_by_single_user(self): cid = channels.create() - channels.send(cid, b'spam') - channels.send(cid, b'spam') - channels.send(cid, b'spam') + channels.send(cid, b'spam', blocking=False) + channels.send(cid, b'spam', blocking=False) + channels.send(cid, b'spam', blocking=False) channels.recv(cid) channels.close(cid, force=True) @@ -1002,7 +1235,7 @@ class ChannelReleaseTests(TestBase): def test_single_user(self): cid = channels.create() - channels.send(cid, b'spam') + channels.send(cid, b'spam', blocking=False) channels.recv(cid) channels.release(cid, send=True, recv=True) @@ -1017,7 +1250,7 @@ def test_multiple_users(self): id2 = interpreters.create() interpreters.run_string(id1, dedent(f""" import _xxinterpchannels as _channels - _channels.send({cid}, b'spam') + _channels.send({cid}, b'spam', blocking=False) """)) out = _run_output(id2, dedent(f""" import _xxinterpchannels as _channels @@ -1033,7 +1266,7 @@ def test_multiple_users(self): def test_no_kwargs(self): cid = channels.create() - channels.send(cid, b'spam') + channels.send(cid, b'spam', blocking=False) channels.recv(cid) channels.release(cid) @@ -1044,7 +1277,7 @@ def test_no_kwargs(self): def test_multiple_times(self): cid = channels.create() - channels.send(cid, b'spam') + channels.send(cid, b'spam', blocking=False) channels.recv(cid) channels.release(cid, send=True, recv=True) @@ -1053,8 +1286,8 @@ def test_multiple_times(self): def test_with_unused_items(self): cid = channels.create() - channels.send(cid, b'spam') - channels.send(cid, b'ham') + channels.send(cid, b'spam', blocking=False) + channels.send(cid, b'ham', blocking=False) channels.release(cid, send=True, recv=True) with self.assertRaises(channels.ChannelClosedError): @@ -1071,7 +1304,7 @@ def test_never_used(self): def test_by_unassociated_interp(self): cid = channels.create() - channels.send(cid, b'spam') + channels.send(cid, b'spam', blocking=False) interp = interpreters.create() interpreters.run_string(interp, dedent(f""" import _xxinterpchannels as _channels @@ -1090,7 +1323,7 @@ def test_close_if_unassociated(self): interp = interpreters.create() interpreters.run_string(interp, dedent(f""" import _xxinterpchannels as _channels - obj = _channels.send({cid}, b'spam') + obj = _channels.send({cid}, b'spam', blocking=False) _channels.release({cid}) """)) @@ -1100,9 +1333,9 @@ def test_close_if_unassociated(self): def test_partially(self): # XXX Is partial close too weird/confusing? cid = channels.create() - channels.send(cid, None) + channels.send(cid, None, blocking=False) channels.recv(cid) - channels.send(cid, b'spam') + channels.send(cid, b'spam', blocking=False) channels.release(cid, send=True) obj = channels.recv(cid) @@ -1110,9 +1343,9 @@ def test_partially(self): def test_used_multiple_times_by_single_user(self): cid = channels.create() - channels.send(cid, b'spam') - channels.send(cid, b'spam') - channels.send(cid, b'spam') + channels.send(cid, b'spam', blocking=False) + channels.send(cid, b'spam', blocking=False) + channels.send(cid, b'spam', blocking=False) channels.recv(cid) channels.release(cid, send=True, recv=True) @@ -1197,7 +1430,7 @@ def _new_channel(self, creator): cid = _xxsubchannels.create() # We purposefully send back an int to avoid tying the # channel to the other interpreter. - _xxsubchannels.send({ch}, int(cid)) + _xxsubchannels.send({ch}, int(cid), blocking=False) del _xxsubinterpreters """) self._cid = channels.recv(ch) @@ -1427,8 +1660,8 @@ def run_action(self, fix, action, *, hideclosed=True): {repr(fix.state)}, hideclosed={hideclosed}, ) - channels.send({_cid}, result.pending.to_bytes(1, 'little')) - channels.send({_cid}, b'X' if result.closed else b'') + channels.send({_cid}, result.pending.to_bytes(1, 'little'), blocking=False) + channels.send({_cid}, b'X' if result.closed else b'', blocking=False) """) result = ChannelState( pending=int.from_bytes(channels.recv(_cid), 'little'), @@ -1475,7 +1708,7 @@ def _assert_closed_in_interp(self, fix, interp=None): """) run_interp(interp.id, """ with helpers.expect_channel_closed(): - channels.send(cid, b'spam') + channels.send(cid, b'spam', blocking=False) """) run_interp(interp.id, """ with helpers.expect_channel_closed(): diff --git a/Lib/test/test__xxsubinterpreters.py b/Lib/test/test__xxsubinterpreters.py index ac2280eb7090e9..a76e4d0ade5b8a 100644 --- a/Lib/test/test__xxsubinterpreters.py +++ b/Lib/test/test__xxsubinterpreters.py @@ -7,13 +7,15 @@ import threading import unittest -import _testcapi +import _testinternalcapi from test import support from test.support import import_helper +from test.support import os_helper from test.support import script_helper interpreters = import_helper.import_module('_xxsubinterpreters') +from _xxsubinterpreters import InterpreterNotFoundError ################################## @@ -31,10 +33,10 @@ def _captured_script(script): return wrapped, open(r, encoding="utf-8") -def _run_output(interp, request, shared=None): +def _run_output(interp, request): script, rpipe = _captured_script(request) with rpipe: - interpreters.run_string(interp, script, shared) + interpreters.run_string(interp, script) return rpipe.read() @@ -102,6 +104,10 @@ def test_default_shareables(self): 'spam', 10, -10, + True, + False, + 100.0, + (1, ('spam', 'eggs')), ] for obj in shareables: with self.subTest(obj): @@ -120,8 +126,6 @@ class SubBytes(bytes): not_shareables = [ # singletons - True, - False, NotImplemented, ..., # builtin types and objects @@ -129,7 +133,6 @@ class SubBytes(bytes): object, object(), Exception(), - 100.0, # user-defined types and objects Cheese, Cheese('Wensleydale'), @@ -146,8 +149,8 @@ class ShareableTypeTests(unittest.TestCase): def _assert_values(self, values): for obj in values: with self.subTest(obj): - xid = _testcapi.get_crossinterp_data(obj) - got = _testcapi.restore_crossinterp_data(xid) + xid = _testinternalcapi.get_crossinterp_data(obj) + got = _testinternalcapi.restore_crossinterp_data(xid) self.assertEqual(got, obj) self.assertIs(type(got), type(obj)) @@ -155,8 +158,8 @@ def _assert_values(self, values): def test_singletons(self): for obj in [None]: with self.subTest(obj): - xid = _testcapi.get_crossinterp_data(obj) - got = _testcapi.restore_crossinterp_data(xid) + xid = _testinternalcapi.get_crossinterp_data(obj) + got = _testinternalcapi.restore_crossinterp_data(xid) # XXX What about between interpreters? self.assertIs(got, obj) @@ -187,7 +190,40 @@ def test_non_shareable_int(self): for i in ints: with self.subTest(i): with self.assertRaises(OverflowError): - _testcapi.get_crossinterp_data(i) + _testinternalcapi.get_crossinterp_data(i) + + def test_bool(self): + self._assert_values([True, False]) + + def test_float(self): + self._assert_values([0.0, 1.1, -1.0, 0.12345678, -0.12345678]) + + def test_tuple(self): + self._assert_values([(), (1,), ("hello", "world", ), (1, True, "hello")]) + # Test nesting + self._assert_values([ + ((1,),), + ((1, 2), (3, 4)), + ((1, 2), (3, 4), (5, 6)), + ]) + + def test_tuples_containing_non_shareable_types(self): + non_shareables = [ + Exception(), + object(), + ] + for s in non_shareables: + value = tuple([0, 1.0, s]) + with self.subTest(repr(value)): + # XXX Assert the NotShareableError when it is exported + with self.assertRaises(ValueError): + _testinternalcapi.get_crossinterp_data(value) + # Check nested as well + value = tuple([0, 1., (s,)]) + with self.subTest("nested " + repr(value)): + # XXX Assert the NotShareableError when it is exported + with self.assertRaises(ValueError): + _testinternalcapi.get_crossinterp_data(value) class ModuleTests(TestBase): @@ -231,7 +267,7 @@ def test_main(self): main = interpreters.get_main() cur = interpreters.get_current() self.assertEqual(cur, main) - self.assertIsInstance(cur, interpreters.InterpreterID) + self.assertIsInstance(cur, int) def test_subinterpreter(self): main = interpreters.get_main() @@ -240,7 +276,7 @@ def test_subinterpreter(self): import _xxsubinterpreters as _interpreters cur = _interpreters.get_current() print(cur) - assert isinstance(cur, _interpreters.InterpreterID) + assert isinstance(cur, int) """)) cur = int(out.strip()) _, expected = interpreters.list_all() @@ -254,7 +290,7 @@ def test_from_main(self): [expected] = interpreters.list_all() main = interpreters.get_main() self.assertEqual(main, expected) - self.assertIsInstance(main, interpreters.InterpreterID) + self.assertIsInstance(main, int) def test_from_subinterpreter(self): [expected] = interpreters.list_all() @@ -263,7 +299,7 @@ def test_from_subinterpreter(self): import _xxsubinterpreters as _interpreters main = _interpreters.get_main() print(main) - assert isinstance(main, _interpreters.InterpreterID) + assert isinstance(main, int) """)) main = int(out.strip()) self.assertEqual(main, expected) @@ -298,11 +334,11 @@ def test_from_subinterpreter(self): def test_already_destroyed(self): interp = interpreters.create() interpreters.destroy(interp) - with self.assertRaises(RuntimeError): + with self.assertRaises(InterpreterNotFoundError): interpreters.is_running(interp) def test_does_not_exist(self): - with self.assertRaises(RuntimeError): + with self.assertRaises(InterpreterNotFoundError): interpreters.is_running(1_000_000) def test_bad_id(self): @@ -310,70 +346,11 @@ def test_bad_id(self): interpreters.is_running(-1) -class InterpreterIDTests(TestBase): - - def test_with_int(self): - id = interpreters.InterpreterID(10, force=True) - - self.assertEqual(int(id), 10) - - def test_coerce_id(self): - class Int(str): - def __index__(self): - return 10 - - id = interpreters.InterpreterID(Int(), force=True) - self.assertEqual(int(id), 10) - - def test_bad_id(self): - self.assertRaises(TypeError, interpreters.InterpreterID, object()) - self.assertRaises(TypeError, interpreters.InterpreterID, 10.0) - self.assertRaises(TypeError, interpreters.InterpreterID, '10') - self.assertRaises(TypeError, interpreters.InterpreterID, b'10') - self.assertRaises(ValueError, interpreters.InterpreterID, -1) - self.assertRaises(OverflowError, interpreters.InterpreterID, 2**64) - - def test_does_not_exist(self): - id = interpreters.create() - with self.assertRaises(RuntimeError): - interpreters.InterpreterID(int(id) + 1) # unforced - - def test_str(self): - id = interpreters.InterpreterID(10, force=True) - self.assertEqual(str(id), '10') - - def test_repr(self): - id = interpreters.InterpreterID(10, force=True) - self.assertEqual(repr(id), 'InterpreterID(10)') - - def test_equality(self): - id1 = interpreters.create() - id2 = interpreters.InterpreterID(int(id1)) - id3 = interpreters.create() - - self.assertTrue(id1 == id1) - self.assertTrue(id1 == id2) - self.assertTrue(id1 == int(id1)) - self.assertTrue(int(id1) == id1) - self.assertTrue(id1 == float(int(id1))) - self.assertTrue(float(int(id1)) == id1) - self.assertFalse(id1 == float(int(id1)) + 0.1) - self.assertFalse(id1 == str(int(id1))) - self.assertFalse(id1 == 2**1000) - self.assertFalse(id1 == float('inf')) - self.assertFalse(id1 == 'spam') - self.assertFalse(id1 == id3) - - self.assertFalse(id1 != id1) - self.assertFalse(id1 != id2) - self.assertTrue(id1 != id3) - - class CreateTests(TestBase): def test_in_main(self): id = interpreters.create() - self.assertIsInstance(id, interpreters.InterpreterID) + self.assertIsInstance(id, int) self.assertIn(id, interpreters.list_all()) @@ -409,7 +386,7 @@ def test_in_subinterpreter(self): import _xxsubinterpreters as _interpreters id = _interpreters.create() print(id) - assert isinstance(id, _interpreters.InterpreterID) + assert isinstance(id, int) """)) id2 = int(out.strip()) @@ -501,11 +478,11 @@ def f(): def test_already_destroyed(self): id = interpreters.create() interpreters.destroy(id) - with self.assertRaises(RuntimeError): + with self.assertRaises(InterpreterNotFoundError): interpreters.destroy(id) def test_does_not_exist(self): - with self.assertRaises(RuntimeError): + with self.assertRaises(InterpreterNotFoundError): interpreters.destroy(1_000_000) def test_bad_id(self): @@ -653,10 +630,10 @@ def test_shareable_types(self): ] for obj in objects: with self.subTest(obj): + interpreters.set___main___attrs(interp, dict(obj=obj)) interpreters.run_string( interp, f'assert(obj == {obj!r})', - shared=dict(obj=obj), ) def test_os_exec(self): @@ -706,7 +683,7 @@ def test_does_not_exist(self): id = 0 while id in interpreters.list_all(): id += 1 - with self.assertRaises(RuntimeError): + with self.assertRaises(InterpreterNotFoundError): interpreters.run_string(id, 'print("spam")') def test_error_id(self): @@ -725,43 +702,6 @@ def test_bytes_for_script(self): with self.assertRaises(TypeError): interpreters.run_string(self.id, b'print("spam")') - @contextlib.contextmanager - def assert_run_failed(self, exctype, msg=None): - with self.assertRaises(interpreters.RunFailedError) as caught: - yield - if msg is None: - self.assertEqual(str(caught.exception).split(':')[0], - exctype.__name__) - else: - self.assertEqual(str(caught.exception), - "{}: {}".format(exctype.__name__, msg)) - - def test_invalid_syntax(self): - with self.assert_run_failed(SyntaxError): - # missing close paren - interpreters.run_string(self.id, 'print("spam"') - - def test_failure(self): - with self.assert_run_failed(Exception, 'spam'): - interpreters.run_string(self.id, 'raise Exception("spam")') - - def test_SystemExit(self): - with self.assert_run_failed(SystemExit, '42'): - interpreters.run_string(self.id, 'raise SystemExit(42)') - - def test_sys_exit(self): - with self.assert_run_failed(SystemExit): - interpreters.run_string(self.id, dedent(""" - import sys - sys.exit() - """)) - - with self.assert_run_failed(SystemExit, '42'): - interpreters.run_string(self.id, dedent(""" - import sys - sys.exit(42) - """)) - def test_with_shared(self): r, w = os.pipe() @@ -781,7 +721,8 @@ def test_with_shared(self): with open({w}, 'wb') as chan: pickle.dump(ns, chan) """) - interpreters.run_string(self.id, script, shared) + interpreters.set___main___attrs(self.id, shared) + interpreters.run_string(self.id, script) with open(r, 'rb') as chan: ns = pickle.load(chan) @@ -802,7 +743,8 @@ def test_shared_overwrites(self): ns2 = dict(vars()) del ns2['__builtins__'] """) - interpreters.run_string(self.id, script, shared) + interpreters.set___main___attrs(self.id, shared) + interpreters.run_string(self.id, script) r, w = os.pipe() script = dedent(f""" @@ -833,7 +775,8 @@ def test_shared_overwrites_default_vars(self): with open({w}, 'wb') as chan: pickle.dump(ns, chan) """) - interpreters.run_string(self.id, script, shared) + interpreters.set___main___attrs(self.id, shared) + interpreters.run_string(self.id, script) with open(r, 'rb') as chan: ns = pickle.load(chan) @@ -925,5 +868,270 @@ def f(): self.assertEqual(retcode, 0) +class RunFailedTests(TestBase): + + def setUp(self): + super().setUp() + self.id = interpreters.create() + + def add_module(self, modname, text): + import tempfile + tempdir = tempfile.mkdtemp() + self.addCleanup(lambda: os_helper.rmtree(tempdir)) + interpreters.run_string(self.id, dedent(f""" + import sys + sys.path.insert(0, {tempdir!r}) + """)) + return script_helper.make_script(tempdir, modname, text) + + def run_script(self, text, *, fails=False): + r, w = os.pipe() + try: + script = dedent(f""" + import os, sys + os.write({w}, b'0') + + # This raises an exception: + {{}} + + # Nothing from here down should ever run. + os.write({w}, b'1') + class NeverError(Exception): pass + raise NeverError # never raised + """).format(dedent(text)) + if fails: + err = interpreters.run_string(self.id, script) + self.assertIsNot(err, None) + return err + else: + err = interpreters.run_string(self.id, script) + self.assertIs(err, None) + return None + except: + raise # re-raise + else: + msg = os.read(r, 100) + self.assertEqual(msg, b'0') + finally: + os.close(r) + os.close(w) + + def _assert_run_failed(self, exctype, msg, script): + if isinstance(exctype, str): + exctype_name = exctype + exctype = None + else: + exctype_name = exctype.__name__ + + # Run the script. + excinfo = self.run_script(script, fails=True) + + # Check the wrapper exception. + self.assertEqual(excinfo.type.__name__, exctype_name) + if msg is None: + self.assertEqual(excinfo.formatted.split(':')[0], + exctype_name) + else: + self.assertEqual(excinfo.formatted, + '{}: {}'.format(exctype_name, msg)) + + return excinfo + + def assert_run_failed(self, exctype, script): + self._assert_run_failed(exctype, None, script) + + def assert_run_failed_msg(self, exctype, msg, script): + self._assert_run_failed(exctype, msg, script) + + def test_exit(self): + with self.subTest('sys.exit(0)'): + # XXX Should an unhandled SystemExit(0) be handled as not-an-error? + self.assert_run_failed(SystemExit, """ + sys.exit(0) + """) + + with self.subTest('sys.exit()'): + self.assert_run_failed(SystemExit, """ + import sys + sys.exit() + """) + + with self.subTest('sys.exit(42)'): + self.assert_run_failed_msg(SystemExit, '42', """ + import sys + sys.exit(42) + """) + + with self.subTest('SystemExit'): + self.assert_run_failed_msg(SystemExit, '42', """ + raise SystemExit(42) + """) + + # XXX Also check os._exit() (via a subprocess)? + + def test_plain_exception(self): + self.assert_run_failed_msg(Exception, 'spam', """ + raise Exception("spam") + """) + + def test_invalid_syntax(self): + script = dedent(""" + x = 1 + 2 + y = 2 + 4 + z = 4 + 8 + + # missing close paren + print("spam" + + if x + y + z < 20: + ... + """) + + with self.subTest('script'): + self.assert_run_failed(SyntaxError, script) + + with self.subTest('module'): + modname = 'spam_spam_spam' + filename = self.add_module(modname, script) + self.assert_run_failed(SyntaxError, f""" + import {modname} + """) + + def test_NameError(self): + self.assert_run_failed(NameError, """ + res = spam + eggs + """) + # XXX check preserved suggestions + + def test_AttributeError(self): + self.assert_run_failed(AttributeError, """ + object().spam + """) + # XXX check preserved suggestions + + def test_ExceptionGroup(self): + self.assert_run_failed(ExceptionGroup, """ + raise ExceptionGroup('exceptions', [ + Exception('spam'), + ImportError('eggs'), + ]) + """) + + def test_user_defined_exception(self): + self.assert_run_failed_msg('MyError', 'spam', """ + class MyError(Exception): + pass + raise MyError('spam') + """) + + +class RunFuncTests(TestBase): + + def setUp(self): + super().setUp() + self.id = interpreters.create() + + def test_success(self): + r, w = os.pipe() + def script(): + global w + import contextlib + with open(w, 'w', encoding="utf-8") as spipe: + with contextlib.redirect_stdout(spipe): + print('it worked!', end='') + interpreters.set___main___attrs(self.id, dict(w=w)) + interpreters.run_func(self.id, script) + + with open(r, encoding="utf-8") as outfile: + out = outfile.read() + + self.assertEqual(out, 'it worked!') + + def test_in_thread(self): + r, w = os.pipe() + def script(): + global w + import contextlib + with open(w, 'w', encoding="utf-8") as spipe: + with contextlib.redirect_stdout(spipe): + print('it worked!', end='') + def f(): + interpreters.set___main___attrs(self.id, dict(w=w)) + interpreters.run_func(self.id, script) + t = threading.Thread(target=f) + t.start() + t.join() + + with open(r, encoding="utf-8") as outfile: + out = outfile.read() + + self.assertEqual(out, 'it worked!') + + def test_code_object(self): + r, w = os.pipe() + + def script(): + global w + import contextlib + with open(w, 'w', encoding="utf-8") as spipe: + with contextlib.redirect_stdout(spipe): + print('it worked!', end='') + code = script.__code__ + interpreters.set___main___attrs(self.id, dict(w=w)) + interpreters.run_func(self.id, code) + + with open(r, encoding="utf-8") as outfile: + out = outfile.read() + + self.assertEqual(out, 'it worked!') + + def test_closure(self): + spam = True + def script(): + assert spam + + with self.assertRaises(ValueError): + interpreters.run_func(self.id, script) + + # XXX This hasn't been fixed yet. + @unittest.expectedFailure + def test_return_value(self): + def script(): + return 'spam' + with self.assertRaises(ValueError): + interpreters.run_func(self.id, script) + + def test_args(self): + with self.subTest('args'): + def script(a, b=0): + assert a == b + with self.assertRaises(ValueError): + interpreters.run_func(self.id, script) + + with self.subTest('*args'): + def script(*args): + assert not args + with self.assertRaises(ValueError): + interpreters.run_func(self.id, script) + + with self.subTest('**kwargs'): + def script(**kwargs): + assert not kwargs + with self.assertRaises(ValueError): + interpreters.run_func(self.id, script) + + with self.subTest('kwonly'): + def script(*, spam=True): + assert spam + with self.assertRaises(ValueError): + interpreters.run_func(self.id, script) + + with self.subTest('posonly'): + def script(spam, /): + assert spam + with self.assertRaises(ValueError): + interpreters.run_func(self.id, script) + + if __name__ == '__main__': unittest.main() diff --git a/Lib/test/test_ast.py b/Lib/test/test_ast.py index 5346b39043f0f5..64fcb02309de77 100644 --- a/Lib/test/test_ast.py +++ b/Lib/test/test_ast.py @@ -12,6 +12,10 @@ import weakref from functools import partial from textwrap import dedent +try: + import _testinternalcapi +except ImportError: + _testinternalcapi = None from test import support from test.support.import_helper import import_fresh_module @@ -100,6 +104,8 @@ def to_tuple(t): # With "with x as y: pass", "with x as y, z as q: pass", + "with (x as y): pass", + "with (x, y): pass", # Raise "raise Exception('string')", # TryExcept @@ -357,6 +363,38 @@ def test_ast_validation(self): tree = ast.parse(snippet) compile(tree, '', 'exec') + def test_optimization_levels__debug__(self): + cases = [(-1, '__debug__'), (0, '__debug__'), (1, False), (2, False)] + for (optval, expected) in cases: + with self.subTest(optval=optval, expected=expected): + res1 = ast.parse("__debug__", optimize=optval) + res2 = ast.parse(ast.parse("__debug__"), optimize=optval) + for res in [res1, res2]: + self.assertIsInstance(res.body[0], ast.Expr) + if isinstance(expected, bool): + self.assertIsInstance(res.body[0].value, ast.Constant) + self.assertEqual(res.body[0].value.value, expected) + else: + self.assertIsInstance(res.body[0].value, ast.Name) + self.assertEqual(res.body[0].value.id, expected) + + def test_optimization_levels_const_folding(self): + folded = ('Expr', (1, 0, 1, 5), ('Constant', (1, 0, 1, 5), 3, None)) + not_folded = ('Expr', (1, 0, 1, 5), + ('BinOp', (1, 0, 1, 5), + ('Constant', (1, 0, 1, 1), 1, None), + ('Add',), + ('Constant', (1, 4, 1, 5), 2, None))) + + cases = [(-1, not_folded), (0, not_folded), (1, folded), (2, folded)] + for (optval, expected) in cases: + with self.subTest(optval=optval): + tree1 = ast.parse("1 + 2", optimize=optval) + tree2 = ast.parse(ast.parse("1 + 2"), optimize=optval) + for tree in [tree1, tree2]: + res = to_tuple(tree.body[0]) + self.assertEqual(res, expected) + def test_invalid_position_information(self): invalid_linenos = [ (10, 1), (-10, -11), (10, -11), (-5, -2), (-5, 1) @@ -1084,12 +1122,14 @@ def next(self): return self enum._test_simple_enum(_Precedence, ast._Precedence) - @unittest.skipIf(support.is_wasi, "exhausts limited stack on WASI") @support.cpython_only def test_ast_recursion_limit(self): fail_depth = support.EXCEEDS_RECURSION_LIMIT crash_depth = 100_000 success_depth = 1200 + if _testinternalcapi is not None: + remaining = _testinternalcapi.get_c_recursion_remaining() + success_depth = min(success_depth, remaining) def check_limit(prefix, repeated): expect_ok = prefix + repeated * success_depth @@ -1999,6 +2039,7 @@ def test_nameconstant(self): 'ast.NameConstant is deprecated and will be removed in Python 3.14; use ast.Constant instead', ]) + @support.requires_resource('cpu') def test_stdlib_validates(self): stdlib = os.path.dirname(ast.__file__) tests = [fn for fn in os.listdir(stdlib) if fn.endswith(".py")] @@ -2982,6 +3023,8 @@ def main(): ('Module', [('If', (1, 0, 6, 6), ('Name', (1, 3, 1, 4), 'a', ('Load',)), [('Pass', (2, 2, 2, 6))], [('If', (3, 0, 6, 6), ('Name', (3, 5, 3, 6), 'b', ('Load',)), [('Pass', (4, 2, 4, 6))], [('Pass', (6, 2, 6, 6))])])], []), ('Module', [('With', (1, 0, 1, 17), [('withitem', ('Name', (1, 5, 1, 6), 'x', ('Load',)), ('Name', (1, 10, 1, 11), 'y', ('Store',)))], [('Pass', (1, 13, 1, 17))], None)], []), ('Module', [('With', (1, 0, 1, 25), [('withitem', ('Name', (1, 5, 1, 6), 'x', ('Load',)), ('Name', (1, 10, 1, 11), 'y', ('Store',))), ('withitem', ('Name', (1, 13, 1, 14), 'z', ('Load',)), ('Name', (1, 18, 1, 19), 'q', ('Store',)))], [('Pass', (1, 21, 1, 25))], None)], []), +('Module', [('With', (1, 0, 1, 19), [('withitem', ('Name', (1, 6, 1, 7), 'x', ('Load',)), ('Name', (1, 11, 1, 12), 'y', ('Store',)))], [('Pass', (1, 15, 1, 19))], None)], []), +('Module', [('With', (1, 0, 1, 17), [('withitem', ('Name', (1, 6, 1, 7), 'x', ('Load',)), None), ('withitem', ('Name', (1, 9, 1, 10), 'y', ('Load',)), None)], [('Pass', (1, 13, 1, 17))], None)], []), ('Module', [('Raise', (1, 0, 1, 25), ('Call', (1, 6, 1, 25), ('Name', (1, 6, 1, 15), 'Exception', ('Load',)), [('Constant', (1, 16, 1, 24), 'string', None)], []), None)], []), ('Module', [('Try', (1, 0, 4, 6), [('Pass', (2, 2, 2, 6))], [('ExceptHandler', (3, 0, 4, 6), ('Name', (3, 7, 3, 16), 'Exception', ('Load',)), None, [('Pass', (4, 2, 4, 6))])], [], [])], []), ('Module', [('Try', (1, 0, 4, 6), [('Pass', (2, 2, 2, 6))], [], [], [('Pass', (4, 2, 4, 6))])], []), diff --git a/Lib/test/test_asyncgen.py b/Lib/test/test_asyncgen.py index 4f00558770dafd..7fa0a85100a581 100644 --- a/Lib/test/test_asyncgen.py +++ b/Lib/test/test_asyncgen.py @@ -1058,8 +1058,7 @@ async def gen(): while True: yield 1 finally: - await asyncio.sleep(0.01) - await asyncio.sleep(0.01) + await asyncio.sleep(0) DONE = 1 async def run(): @@ -1069,7 +1068,10 @@ async def run(): del g gc_collect() # For PyPy or other GCs. - await asyncio.sleep(0.1) + # Starts running the aclose task + await asyncio.sleep(0) + # For asyncio.sleep(0) in finally block + await asyncio.sleep(0) self.loop.run_until_complete(run()) self.assertEqual(DONE, 1) @@ -1699,6 +1701,14 @@ def test_asend(self): async def gen(): yield 1 + # gh-113753: asend objects allocated from a free-list should warn. + # Ensure there is a finalized 'asend' object ready to be reused. + try: + g = gen() + g.asend(None).send(None) + except StopIteration: + pass + msg = f"coroutine method 'asend' of '{gen.__qualname__}' was never awaited" with self.assertWarnsRegex(RuntimeWarning, msg): g = gen() diff --git a/Lib/test/test_asyncio/test_base_events.py b/Lib/test/test_asyncio/test_base_events.py index 3b4026cb73869a..c2080977e9d587 100644 --- a/Lib/test/test_asyncio/test_base_events.py +++ b/Lib/test/test_asyncio/test_base_events.py @@ -273,7 +273,7 @@ def cb(): self.loop.stop() self.loop._process_events = mock.Mock() - delay = 0.1 + delay = 0.100 when = self.loop.time() + delay self.loop.call_at(when, cb) @@ -282,10 +282,7 @@ def cb(): dt = self.loop.time() - t0 # 50 ms: maximum granularity of the event loop - self.assertGreaterEqual(dt, delay - 0.050, dt) - # tolerate a difference of +800 ms because some Python buildbots - # are really slow - self.assertLessEqual(dt, 0.9, dt) + self.assertGreaterEqual(dt, delay - test_utils.CLOCK_RES) with self.assertRaises(TypeError, msg="when cannot be None"): self.loop.call_at(None, cb) @@ -925,6 +922,43 @@ def test_run_forever_pre_stopped(self): self.loop.run_forever() self.loop._selector.select.assert_called_once_with(0) + def test_custom_run_forever_integration(self): + # Test that the run_forever_setup() and run_forever_cleanup() primitives + # can be used to implement a custom run_forever loop. + self.loop._process_events = mock.Mock() + + count = 0 + + def callback(): + nonlocal count + count += 1 + + self.loop.call_soon(callback) + + # Set up the custom event loop + self.loop._run_forever_setup() + + # Confirm the loop has been started + self.assertEqual(asyncio.get_running_loop(), self.loop) + self.assertTrue(self.loop.is_running()) + + # Our custom "event loop" just iterates 10 times before exiting. + for i in range(10): + self.loop._run_once() + + # Clean up the event loop + self.loop._run_forever_cleanup() + + # Confirm the loop has been cleaned up + with self.assertRaises(RuntimeError): + asyncio.get_running_loop() + self.assertFalse(self.loop.is_running()) + + # Confirm the loop actually did run, processing events 10 times, + # and invoking the callback once. + self.assertEqual(self.loop._process_events.call_count, 10) + self.assertEqual(count, 1) + async def leave_unfinalized_asyncgen(self): # Create an async generator, iterate it partially, and leave it # to be garbage collected. diff --git a/Lib/test/test_asyncio/test_eager_task_factory.py b/Lib/test/test_asyncio/test_eager_task_factory.py index fc9ad8eb43bb1b..0f8212dbec47be 100644 --- a/Lib/test/test_asyncio/test_eager_task_factory.py +++ b/Lib/test/test_asyncio/test_eager_task_factory.py @@ -7,7 +7,6 @@ from unittest import mock from asyncio import tasks from test.test_asyncio import utils as test_utils -import test.support from test.support.script_helper import assert_python_ok MOCK_ANY = mock.ANY diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py index b9069056c3a436..b25c0975736e20 100644 --- a/Lib/test/test_asyncio/test_events.py +++ b/Lib/test/test_asyncio/test_events.py @@ -1,6 +1,5 @@ """Tests for events.py.""" -import collections.abc import concurrent.futures import functools import io @@ -31,6 +30,7 @@ from asyncio import coroutines from asyncio import events from asyncio import selector_events +from multiprocessing.util import _cleanup_tests as multiprocessing_cleanup_tests from test.test_asyncio import utils as test_utils from test import support from test.support import socket_helper @@ -293,10 +293,11 @@ async def coro2(): # 15.6 msec, we use fairly long sleep times here (~100 msec). def test_run_until_complete(self): + delay = 0.100 t0 = self.loop.time() - self.loop.run_until_complete(asyncio.sleep(0.1)) - t1 = self.loop.time() - self.assertTrue(0.08 <= t1-t0 <= 0.8, t1-t0) + self.loop.run_until_complete(asyncio.sleep(delay)) + dt = self.loop.time() - t0 + self.assertGreaterEqual(dt, delay - test_utils.CLOCK_RES) def test_run_until_complete_stopped(self): @@ -671,6 +672,7 @@ def test_create_connection_local_addr(self): self.assertEqual(port, expected) tr.close() + @socket_helper.skip_if_tcp_blackhole def test_create_connection_local_addr_skip_different_family(self): # See https://github.com/python/cpython/issues/86508 port1 = socket_helper.find_unused_port() @@ -692,6 +694,7 @@ async def getaddrinfo(host, port, *args, **kwargs): with self.assertRaises(OSError): self.loop.run_until_complete(f) + @socket_helper.skip_if_tcp_blackhole def test_create_connection_local_addr_nomatch_family(self): # See https://github.com/python/cpython/issues/86508 port1 = socket_helper.find_unused_port() @@ -1271,6 +1274,7 @@ def connection_made(self, transport): server.close() + @socket_helper.skip_if_tcp_blackhole def test_server_close(self): f = self.loop.create_server(MyProto, '0.0.0.0', 0) server = self.loop.run_until_complete(f) @@ -1689,12 +1693,9 @@ async def main(): self.loop.stop() return res - start = time.monotonic() t = self.loop.create_task(main()) self.loop.run_forever() - elapsed = time.monotonic() - start - self.assertLess(elapsed, 0.1) self.assertEqual(t.result(), 'cancelled') self.assertRaises(asyncio.CancelledError, f.result) if ov is not None: @@ -1714,7 +1715,6 @@ def _run_once(): self.loop._run_once = _run_once async def wait(): - loop = self.loop await asyncio.sleep(1e-2) await asyncio.sleep(1e-4) await asyncio.sleep(1e-6) @@ -2331,8 +2331,6 @@ def check_source_traceback(h): h = loop.call_later(0, noop) check_source_traceback(h) - @unittest.skipUnless(hasattr(collections.abc, 'Coroutine'), - 'No collections.abc.Coroutine') def test_coroutine_like_object_debug_formatting(self): # Test that asyncio can format coroutines that are instances of # collections.abc.Coroutine, but lack cr_core or gi_code attributes @@ -2762,6 +2760,8 @@ def test_get_event_loop_new_process(self): # multiprocessing.synchronize module cannot be imported. support.skip_if_broken_multiprocessing_synchronize() + self.addCleanup(multiprocessing_cleanup_tests) + async def main(): if multiprocessing.get_start_method() == 'fork': # Avoid 'fork' DeprecationWarning. diff --git a/Lib/test/test_asyncio/test_futures.py b/Lib/test/test_asyncio/test_futures.py index 2184b2091f84ee..d3e8efec1c04c2 100644 --- a/Lib/test/test_asyncio/test_futures.py +++ b/Lib/test/test_asyncio/test_futures.py @@ -270,10 +270,6 @@ def test_exception(self): f = self._new_future(loop=self.loop) self.assertRaises(asyncio.InvalidStateError, f.exception) - # StopIteration cannot be raised into a Future - CPython issue26221 - self.assertRaisesRegex(TypeError, "StopIteration .* cannot be raised", - f.set_exception, StopIteration) - f.set_exception(exc) self.assertFalse(f.cancelled()) self.assertTrue(f.done()) @@ -283,6 +279,25 @@ def test_exception(self): self.assertRaises(asyncio.InvalidStateError, f.set_exception, None) self.assertFalse(f.cancel()) + def test_stop_iteration_exception(self, stop_iteration_class=StopIteration): + exc = stop_iteration_class() + f = self._new_future(loop=self.loop) + f.set_exception(exc) + self.assertFalse(f.cancelled()) + self.assertTrue(f.done()) + self.assertRaises(RuntimeError, f.result) + exc = f.exception() + cause = exc.__cause__ + self.assertIsInstance(exc, RuntimeError) + self.assertRegex(str(exc), 'StopIteration .* cannot be raised') + self.assertIsInstance(cause, stop_iteration_class) + + def test_stop_iteration_subclass_exception(self): + class MyStopIteration(StopIteration): + pass + + self.test_stop_iteration_exception(MyStopIteration) + def test_exception_class(self): f = self._new_future(loop=self.loop) f.set_exception(RuntimeError) diff --git a/Lib/test/test_asyncio/test_locks.py b/Lib/test/test_asyncio/test_locks.py index f6c6a282429a21..9029efd2355b46 100644 --- a/Lib/test/test_asyncio/test_locks.py +++ b/Lib/test/test_asyncio/test_locks.py @@ -758,6 +758,63 @@ async def test_timeout_in_block(self): with self.assertRaises(asyncio.TimeoutError): await asyncio.wait_for(condition.wait(), timeout=0.5) + async def test_cancelled_error_wakeup(self): + # Test that a cancelled error, received when awaiting wakeup, + # will be re-raised un-modified. + wake = False + raised = None + cond = asyncio.Condition() + + async def func(): + nonlocal raised + async with cond: + with self.assertRaises(asyncio.CancelledError) as err: + await cond.wait_for(lambda: wake) + raised = err.exception + raise raised + + task = asyncio.create_task(func()) + await asyncio.sleep(0) + # Task is waiting on the condition, cancel it there. + task.cancel(msg="foo") + with self.assertRaises(asyncio.CancelledError) as err: + await task + self.assertEqual(err.exception.args, ("foo",)) + # We should have got the _same_ exception instance as the one + # originally raised. + self.assertIs(err.exception, raised) + + async def test_cancelled_error_re_aquire(self): + # Test that a cancelled error, received when re-aquiring lock, + # will be re-raised un-modified. + wake = False + raised = None + cond = asyncio.Condition() + + async def func(): + nonlocal raised + async with cond: + with self.assertRaises(asyncio.CancelledError) as err: + await cond.wait_for(lambda: wake) + raised = err.exception + raise raised + + task = asyncio.create_task(func()) + await asyncio.sleep(0) + # Task is waiting on the condition + await cond.acquire() + wake = True + cond.notify() + await asyncio.sleep(0) + # Task is now trying to re-acquire the lock, cancel it there. + task.cancel(msg="foo") + cond.release() + with self.assertRaises(asyncio.CancelledError) as err: + await task + self.assertEqual(err.exception.args, ("foo",)) + # We should have got the _same_ exception instance as the one + # originally raised. + self.assertIs(err.exception, raised) class SemaphoreTests(unittest.IsolatedAsyncioTestCase): @@ -1044,6 +1101,62 @@ async def c3(result): await asyncio.gather(*tasks, return_exceptions=True) self.assertEqual([2, 3], result) + async def test_acquire_fifo_order_4(self): + # Test that a successfule `acquire()` will wake up multiple Tasks + # that were waiting in the Semaphore queue due to FIFO rules. + sem = asyncio.Semaphore(0) + result = [] + count = 0 + + async def c1(result): + # First task immediatlly waits for semaphore. It will be awoken by c2. + self.assertEqual(sem._value, 0) + await sem.acquire() + # We should have woken up all waiting tasks now. + self.assertEqual(sem._value, 0) + # Create a fourth task. It should run after c3, not c2. + nonlocal t4 + t4 = asyncio.create_task(c4(result)) + result.append(1) + return True + + async def c2(result): + # The second task begins by releasing semaphore three times, + # for c1, c2, and c3. + sem.release() + sem.release() + sem.release() + self.assertEqual(sem._value, 2) + # It is locked, because c1 hasn't woken up yet. + self.assertTrue(sem.locked()) + await sem.acquire() + result.append(2) + return True + + async def c3(result): + await sem.acquire() + self.assertTrue(sem.locked()) + result.append(3) + return True + + async def c4(result): + result.append(4) + return True + + t1 = asyncio.create_task(c1(result)) + t2 = asyncio.create_task(c2(result)) + t3 = asyncio.create_task(c3(result)) + t4 = None + + await asyncio.sleep(0) + # Three tasks are in the queue, the first hasn't woken up yet. + self.assertEqual(sem._value, 2) + self.assertEqual(len(sem._waiters), 3) + await asyncio.sleep(0) + + tasks = [t1, t2, t3, t4] + await asyncio.gather(*tasks) + self.assertEqual([1, 2, 3, 4], result) class BarrierTests(unittest.IsolatedAsyncioTestCase): diff --git a/Lib/test/test_asyncio/test_runners.py b/Lib/test/test_asyncio/test_runners.py index b1eb6f492886b3..266f057f0776c3 100644 --- a/Lib/test/test_asyncio/test_runners.py +++ b/Lib/test/test_asyncio/test_runners.py @@ -3,6 +3,7 @@ import contextvars import re import signal +import sys import threading import unittest from test.test_asyncio import utils as test_utils @@ -101,11 +102,14 @@ async def main(expected): loop = asyncio.get_event_loop() self.assertIs(loop.get_debug(), expected) - asyncio.run(main(False)) + asyncio.run(main(False), debug=False) asyncio.run(main(True), debug=True) with mock.patch('asyncio.coroutines._is_debug_mode', lambda: True): asyncio.run(main(True)) asyncio.run(main(False), debug=False) + with mock.patch('asyncio.coroutines._is_debug_mode', lambda: False): + asyncio.run(main(True), debug=True) + asyncio.run(main(False)) def test_asyncio_run_from_running_loop(self): async def main(): @@ -269,6 +273,16 @@ async def main(): asyncio.run(main(), loop_factory=factory) factory.assert_called_once_with() + def test_loop_factory_default_event_loop(self): + async def main(): + if sys.platform == "win32": + self.assertIsInstance(asyncio.get_running_loop(), asyncio.ProactorEventLoop) + else: + self.assertIsInstance(asyncio.get_running_loop(), asyncio.SelectorEventLoop) + + + asyncio.run(main(), loop_factory=asyncio.EventLoop) + class RunnerTests(BaseTest): @@ -481,6 +495,24 @@ async def coro(): self.assertEqual(1, policy.set_event_loop.call_count) runner.close() + def test_no_repr_is_call_on_the_task_result(self): + # See https://github.com/python/cpython/issues/112559. + class MyResult: + def __init__(self): + self.repr_count = 0 + def __repr__(self): + self.repr_count += 1 + return super().__repr__() + + async def coro(): + return MyResult() + + + with asyncio.Runner() as runner: + result = runner.run(coro()) + + self.assertEqual(0, result.repr_count) + if __name__ == '__main__': unittest.main() diff --git a/Lib/test/test_asyncio/test_sendfile.py b/Lib/test/test_asyncio/test_sendfile.py index 0198da21d77028..d33ff197bbfa1d 100644 --- a/Lib/test/test_asyncio/test_sendfile.py +++ b/Lib/test/test_asyncio/test_sendfile.py @@ -470,8 +470,11 @@ def test_sendfile_close_peer_in_the_middle_of_receiving(self): self.assertTrue(1024 <= srv_proto.nbytes < len(self.DATA), srv_proto.nbytes) - self.assertTrue(1024 <= self.file.tell() < len(self.DATA), - self.file.tell()) + if not (sys.platform == 'win32' + and isinstance(self.loop, asyncio.ProactorEventLoop)): + # On Windows, Proactor uses transmitFile, which does not update tell() + self.assertTrue(1024 <= self.file.tell() < len(self.DATA), + self.file.tell()) self.assertTrue(cli_proto.transport.is_closing()) def test_sendfile_fallback_close_peer_in_the_middle_of_receiving(self): diff --git a/Lib/test/test_asyncio/test_server.py b/Lib/test/test_asyncio/test_server.py index 06d8b60f219f1a..918faac909b9bf 100644 --- a/Lib/test/test_asyncio/test_server.py +++ b/Lib/test/test_asyncio/test_server.py @@ -1,4 +1,6 @@ import asyncio +import os +import socket import time import threading import unittest @@ -122,29 +124,133 @@ async def main(srv): class TestServer2(unittest.IsolatedAsyncioTestCase): - async def test_wait_closed(self): + async def test_wait_closed_basic(self): async def serve(*args): pass srv = await asyncio.start_server(serve, socket_helper.HOSTv4, 0) + self.addCleanup(srv.close) - # active count = 0 + # active count = 0, not closed: should block task1 = asyncio.create_task(srv.wait_closed()) await asyncio.sleep(0) - self.assertTrue(task1.done()) + self.assertFalse(task1.done()) - # active count != 0 + # active count != 0, not closed: should block srv._attach() task2 = asyncio.create_task(srv.wait_closed()) await asyncio.sleep(0) + self.assertFalse(task1.done()) self.assertFalse(task2.done()) srv.close() await asyncio.sleep(0) + # active count != 0, closed: should block + task3 = asyncio.create_task(srv.wait_closed()) + await asyncio.sleep(0) + self.assertFalse(task1.done()) self.assertFalse(task2.done()) + self.assertFalse(task3.done()) srv._detach() + # active count == 0, closed: should unblock + await task1 await task2 + await task3 + await srv.wait_closed() # Return immediately + + async def test_wait_closed_race(self): + # Test a regression in 3.12.0, should be fixed in 3.12.1 + async def serve(*args): + pass + + srv = await asyncio.start_server(serve, socket_helper.HOSTv4, 0) + self.addCleanup(srv.close) + + task = asyncio.create_task(srv.wait_closed()) + await asyncio.sleep(0) + self.assertFalse(task.done()) + srv._attach() + loop = asyncio.get_running_loop() + loop.call_soon(srv.close) + loop.call_soon(srv._detach) + await srv.wait_closed() + + + + +# Test the various corner cases of Unix server socket removal +class UnixServerCleanupTests(unittest.IsolatedAsyncioTestCase): + @socket_helper.skip_unless_bind_unix_socket + async def test_unix_server_addr_cleanup(self): + # Default scenario + with test_utils.unix_socket_path() as addr: + async def serve(*args): + pass + + srv = await asyncio.start_unix_server(serve, addr) + + srv.close() + self.assertFalse(os.path.exists(addr)) + + @socket_helper.skip_unless_bind_unix_socket + async def test_unix_server_sock_cleanup(self): + # Using already bound socket + with test_utils.unix_socket_path() as addr: + async def serve(*args): + pass + + with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as sock: + sock.bind(addr) + + srv = await asyncio.start_unix_server(serve, sock=sock) + + srv.close() + self.assertFalse(os.path.exists(addr)) + + @socket_helper.skip_unless_bind_unix_socket + async def test_unix_server_cleanup_gone(self): + # Someone else has already cleaned up the socket + with test_utils.unix_socket_path() as addr: + async def serve(*args): + pass + + with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as sock: + sock.bind(addr) + + srv = await asyncio.start_unix_server(serve, sock=sock) + + os.unlink(addr) + + srv.close() + + @socket_helper.skip_unless_bind_unix_socket + async def test_unix_server_cleanup_replaced(self): + # Someone else has replaced the socket with their own + with test_utils.unix_socket_path() as addr: + async def serve(*args): + pass + + srv = await asyncio.start_unix_server(serve, addr) + + os.unlink(addr) + with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as sock: + sock.bind(addr) + + srv.close() + self.assertTrue(os.path.exists(addr)) + + @socket_helper.skip_unless_bind_unix_socket + async def test_unix_server_cleanup_prevented(self): + # Automatic cleanup explicitly disabled + with test_utils.unix_socket_path() as addr: + async def serve(*args): + pass + + srv = await asyncio.start_unix_server(serve, addr, cleanup_socket=False) + + srv.close() + self.assertTrue(os.path.exists(addr)) @unittest.skipUnless(hasattr(asyncio, 'ProactorEventLoop'), 'Windows only') diff --git a/Lib/test/test_asyncio/test_sock_lowlevel.py b/Lib/test/test_asyncio/test_sock_lowlevel.py index b829fd4cc69fff..075113cbe8e4a6 100644 --- a/Lib/test/test_asyncio/test_sock_lowlevel.py +++ b/Lib/test/test_asyncio/test_sock_lowlevel.py @@ -10,6 +10,10 @@ from test import support from test.support import socket_helper +if socket_helper.tcp_blackhole(): + raise unittest.SkipTest('Not relevant to ProactorEventLoop') + + def tearDownModule(): asyncio.set_event_loop_policy(None) diff --git a/Lib/test/test_asyncio/test_sslproto.py b/Lib/test/test_asyncio/test_sslproto.py index 52a45f1c7c6e96..f5f0afeab51c9e 100644 --- a/Lib/test/test_asyncio/test_sslproto.py +++ b/Lib/test/test_asyncio/test_sslproto.py @@ -5,6 +5,7 @@ import unittest import weakref from test import support +from test.support import socket_helper from unittest import mock try: import ssl @@ -46,6 +47,7 @@ def connection_made(self, ssl_proto, *, do_handshake=None): sslobj = mock.Mock() # emulate reading decompressed data sslobj.read.side_effect = ssl.SSLWantReadError + sslobj.write.side_effect = ssl.SSLWantReadError if do_handshake is not None: sslobj.do_handshake = do_handshake ssl_proto._sslobj = sslobj @@ -119,7 +121,19 @@ def test_close_during_handshake(self): test_utils.run_briefly(self.loop) ssl_proto._app_transport.close() - self.assertTrue(transport.abort.called) + self.assertTrue(transport._force_close.called) + + def test_close_during_ssl_over_ssl(self): + # gh-113214: passing exceptions from the inner wrapped SSL protocol to the + # shim transport provided by the outer SSL protocol should not raise + # attribute errors + outer = self.ssl_protocol(proto=self.ssl_protocol()) + self.connection_made(outer) + # Closing the outer app transport should not raise an exception + messages = [] + self.loop.set_exception_handler(lambda loop, ctx: messages.append(ctx)) + outer._app_transport.close() + self.assertEqual(messages, []) def test_get_extra_info_on_closed_connection(self): waiter = self.loop.create_future() @@ -350,6 +364,7 @@ async def client(addr): support.gc_collect() self.assertIsNone(client_context()) + @socket_helper.skip_if_tcp_blackhole def test_start_tls_client_buf_proto_1(self): HELLO_MSG = b'1' * self.PAYLOAD_SIZE @@ -502,6 +517,7 @@ async def client(addr): asyncio.wait_for(client(srv.addr), timeout=support.SHORT_TIMEOUT)) + @socket_helper.skip_if_tcp_blackhole def test_start_tls_server_1(self): HELLO_MSG = b'1' * self.PAYLOAD_SIZE ANSWER = b'answer' diff --git a/Lib/test/test_asyncio/test_streams.py b/Lib/test/test_asyncio/test_streams.py index 9c92e75886c593..3c8cc5f3649180 100644 --- a/Lib/test/test_asyncio/test_streams.py +++ b/Lib/test/test_asyncio/test_streams.py @@ -37,8 +37,7 @@ def tearDown(self): # just in case if we have transport close callbacks test_utils.run_briefly(self.loop) - self.loop.close() - gc.collect() + # set_event_loop() takes care of closing self.loop in a safe way super().tearDown() def _basetest_open_connection(self, open_connection_fut): @@ -1083,10 +1082,11 @@ async def inner(httpd): self.assertEqual(data, b'HTTP/1.0 200 OK\r\n') data = await rd.read() self.assertTrue(data.endswith(b'\r\n\r\nTest message')) - with self.assertWarns(ResourceWarning): + with self.assertWarns(ResourceWarning) as cm: del wr gc.collect() - + self.assertEqual(len(cm.warnings), 1) + self.assertTrue(str(cm.warnings[0].message).startswith("unclosed None: self.loop.run_until_complete(main()) - def test_subprocess_consistent_callbacks(self): + def test_subprocess_protocol_events(self): + # gh-108973: Test that all subprocess protocol methods are called. + # The protocol methods are not called in a determistic order. + # The order depends on the event loop and the operating system. events = [] + fds = [1, 2] + expected = [ + ('pipe_data_received', 1, b'stdout'), + ('pipe_data_received', 2, b'stderr'), + ('pipe_connection_lost', 1), + ('pipe_connection_lost', 2), + 'process_exited', + ] + per_fd_expected = [ + 'pipe_data_received', + 'pipe_connection_lost', + ] + class MyProtocol(asyncio.SubprocessProtocol): def __init__(self, exit_future: asyncio.Future) -> None: self.exit_future = exit_future def pipe_data_received(self, fd, data) -> None: events.append(('pipe_data_received', fd, data)) + self.exit_maybe() def pipe_connection_lost(self, fd, exc) -> None: - events.append('pipe_connection_lost') + events.append(('pipe_connection_lost', fd)) + self.exit_maybe() def process_exited(self) -> None: events.append('process_exited') - self.exit_future.set_result(True) + self.exit_maybe() + + def exit_maybe(self): + # Only exit when we got all expected events + if len(events) >= len(expected): + self.exit_future.set_result(True) async def main() -> None: loop = asyncio.get_running_loop() @@ -777,15 +831,24 @@ async def main() -> None: sys.executable, '-c', code, stdin=None) await exit_future transport.close() - self.assertEqual(events, [ - ('pipe_data_received', 1, b'stdout'), - ('pipe_data_received', 2, b'stderr'), - 'pipe_connection_lost', - 'pipe_connection_lost', - 'process_exited', - ]) - self.loop.run_until_complete(main()) + return events + + events = self.loop.run_until_complete(main()) + + # First, make sure that we received all events + self.assertSetEqual(set(events), set(expected)) + + # Second, check order of pipe events per file descriptor + per_fd_events = {fd: [] for fd in fds} + for event in events: + if event == 'process_exited': + continue + name, fd = event[:2] + per_fd_events[fd].append(name) + + for fd in fds: + self.assertEqual(per_fd_events[fd], per_fd_expected, (fd, events)) def test_subprocess_communicate_stdout(self): # See https://github.com/python/cpython/issues/100133 diff --git a/Lib/test/test_asyncio/test_taskgroups.py b/Lib/test/test_asyncio/test_taskgroups.py index 6a0231f2859a62..7a18362b54e469 100644 --- a/Lib/test/test_asyncio/test_taskgroups.py +++ b/Lib/test/test_asyncio/test_taskgroups.py @@ -8,6 +8,8 @@ from asyncio import taskgroups import unittest +from test.test_asyncio.utils import await_without_task + # To prevent a warning "test altered the execution environment" def tearDownModule(): @@ -779,6 +781,49 @@ async def main(): await asyncio.create_task(main()) + async def test_taskgroup_already_entered(self): + tg = taskgroups.TaskGroup() + async with tg: + with self.assertRaisesRegex(RuntimeError, "has already been entered"): + async with tg: + pass + + async def test_taskgroup_double_enter(self): + tg = taskgroups.TaskGroup() + async with tg: + pass + with self.assertRaisesRegex(RuntimeError, "has already been entered"): + async with tg: + pass + + async def test_taskgroup_finished(self): + tg = taskgroups.TaskGroup() + async with tg: + pass + coro = asyncio.sleep(0) + with self.assertRaisesRegex(RuntimeError, "is finished"): + tg.create_task(coro) + # We still have to await coro to avoid a warning + await coro + + async def test_taskgroup_not_entered(self): + tg = taskgroups.TaskGroup() + coro = asyncio.sleep(0) + with self.assertRaisesRegex(RuntimeError, "has not been entered"): + tg.create_task(coro) + # We still have to await coro to avoid a warning + await coro + + async def test_taskgroup_without_parent_task(self): + tg = taskgroups.TaskGroup() + with self.assertRaisesRegex(RuntimeError, "parent task"): + await await_without_task(tg.__aenter__()) + coro = asyncio.sleep(0) + with self.assertRaisesRegex(RuntimeError, "has not been entered"): + tg.create_task(coro) + # We still have to await coro to avoid a warning + await coro + if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_asyncio/test_timeouts.py b/Lib/test/test_asyncio/test_timeouts.py index 8b6b9a1fea0be8..1f7f9ee696a525 100644 --- a/Lib/test/test_asyncio/test_timeouts.py +++ b/Lib/test/test_asyncio/test_timeouts.py @@ -5,11 +5,12 @@ import asyncio +from test.test_asyncio.utils import await_without_task + def tearDownModule(): asyncio.set_event_loop_policy(None) - class TimeoutTests(unittest.IsolatedAsyncioTestCase): async def test_timeout_basic(self): @@ -46,7 +47,6 @@ async def test_nested_timeouts(self): self.assertTrue(cm2.expired()) async def test_waiter_cancelled(self): - loop = asyncio.get_running_loop() cancelled = False with self.assertRaises(TimeoutError): async with asyncio.timeout(0.01): @@ -59,39 +59,26 @@ async def test_waiter_cancelled(self): async def test_timeout_not_called(self): loop = asyncio.get_running_loop() - t0 = loop.time() async with asyncio.timeout(10) as cm: await asyncio.sleep(0.01) t1 = loop.time() self.assertFalse(cm.expired()) - # 2 sec for slow CI boxes - self.assertLess(t1-t0, 2) self.assertGreater(cm.when(), t1) async def test_timeout_disabled(self): - loop = asyncio.get_running_loop() - t0 = loop.time() async with asyncio.timeout(None) as cm: await asyncio.sleep(0.01) - t1 = loop.time() self.assertFalse(cm.expired()) self.assertIsNone(cm.when()) - # 2 sec for slow CI boxes - self.assertLess(t1-t0, 2) async def test_timeout_at_disabled(self): - loop = asyncio.get_running_loop() - t0 = loop.time() async with asyncio.timeout_at(None) as cm: await asyncio.sleep(0.01) - t1 = loop.time() self.assertFalse(cm.expired()) self.assertIsNone(cm.when()) - # 2 sec for slow CI boxes - self.assertLess(t1-t0, 2) async def test_timeout_zero(self): loop = asyncio.get_running_loop() @@ -101,8 +88,6 @@ async def test_timeout_zero(self): await asyncio.sleep(10) t1 = loop.time() self.assertTrue(cm.expired()) - # 2 sec for slow CI boxes - self.assertLess(t1-t0, 2) self.assertTrue(t0 <= cm.when() <= t1) async def test_timeout_zero_sleep_zero(self): @@ -113,8 +98,6 @@ async def test_timeout_zero_sleep_zero(self): await asyncio.sleep(0) t1 = loop.time() self.assertTrue(cm.expired()) - # 2 sec for slow CI boxes - self.assertLess(t1-t0, 2) self.assertTrue(t0 <= cm.when() <= t1) async def test_timeout_in_the_past_sleep_zero(self): @@ -125,8 +108,6 @@ async def test_timeout_in_the_past_sleep_zero(self): await asyncio.sleep(0) t1 = loop.time() self.assertTrue(cm.expired()) - # 2 sec for slow CI boxes - self.assertLess(t1-t0, 2) self.assertTrue(t0 >= cm.when() <= t1) async def test_foreign_exception_passed(self): @@ -135,15 +116,68 @@ async def test_foreign_exception_passed(self): raise KeyError self.assertFalse(cm.expired()) + async def test_timeout_exception_context(self): + with self.assertRaises(TimeoutError) as cm: + async with asyncio.timeout(0.01): + try: + 1/0 + finally: + await asyncio.sleep(1) + e = cm.exception + # Expect TimeoutError caused by CancelledError raised during handling + # of ZeroDivisionError. + e2 = e.__cause__ + self.assertIsInstance(e2, asyncio.CancelledError) + self.assertIs(e.__context__, e2) + self.assertIsNone(e2.__cause__) + self.assertIsInstance(e2.__context__, ZeroDivisionError) + async def test_foreign_exception_on_timeout(self): async def crash(): try: await asyncio.sleep(1) finally: 1/0 - with self.assertRaises(ZeroDivisionError): + with self.assertRaises(ZeroDivisionError) as cm: async with asyncio.timeout(0.01): await crash() + e = cm.exception + # Expect ZeroDivisionError raised during handling of TimeoutError + # caused by CancelledError. + self.assertIsNone(e.__cause__) + e2 = e.__context__ + self.assertIsInstance(e2, TimeoutError) + e3 = e2.__cause__ + self.assertIsInstance(e3, asyncio.CancelledError) + self.assertIs(e2.__context__, e3) + + async def test_foreign_exception_on_timeout_2(self): + with self.assertRaises(ZeroDivisionError) as cm: + async with asyncio.timeout(0.01): + try: + try: + raise ValueError + finally: + await asyncio.sleep(1) + finally: + try: + raise KeyError + finally: + 1/0 + e = cm.exception + # Expect ZeroDivisionError raised during handling of KeyError + # raised during handling of TimeoutError caused by CancelledError. + self.assertIsNone(e.__cause__) + e2 = e.__context__ + self.assertIsInstance(e2, KeyError) + self.assertIsNone(e2.__cause__) + e3 = e2.__context__ + self.assertIsInstance(e3, TimeoutError) + e4 = e3.__cause__ + self.assertIsInstance(e4, asyncio.CancelledError) + self.assertIsNone(e4.__cause__) + self.assertIsInstance(e4.__context__, ValueError) + self.assertIs(e3.__context__, e4) async def test_foreign_cancel_doesnt_timeout_if_not_expired(self): with self.assertRaises(asyncio.CancelledError): @@ -238,14 +272,30 @@ async def test_repr_disabled(self): self.assertEqual(repr(cm), r"") async def test_nested_timeout_in_finally(self): - with self.assertRaises(TimeoutError): + with self.assertRaises(TimeoutError) as cm1: async with asyncio.timeout(0.01): try: await asyncio.sleep(1) finally: - with self.assertRaises(TimeoutError): + with self.assertRaises(TimeoutError) as cm2: async with asyncio.timeout(0.01): await asyncio.sleep(10) + e1 = cm1.exception + # Expect TimeoutError caused by CancelledError. + e12 = e1.__cause__ + self.assertIsInstance(e12, asyncio.CancelledError) + self.assertIsNone(e12.__cause__) + self.assertIsNone(e12.__context__) + self.assertIs(e1.__context__, e12) + e2 = cm2.exception + # Expect TimeoutError caused by CancelledError raised during + # handling of other CancelledError (which is the same as in + # the above chain). + e22 = e2.__cause__ + self.assertIsInstance(e22, asyncio.CancelledError) + self.assertIsNone(e22.__cause__) + self.assertIs(e22.__context__, e12) + self.assertIs(e2.__context__, e22) async def test_timeout_after_cancellation(self): try: @@ -254,7 +304,7 @@ async def test_timeout_after_cancellation(self): except asyncio.CancelledError: pass finally: - with self.assertRaises(TimeoutError): + with self.assertRaises(TimeoutError) as cm: async with asyncio.timeout(0.0): await asyncio.sleep(1) # some cleanup @@ -270,12 +320,91 @@ async def test_cancel_in_timeout_after_cancellation(self): asyncio.current_task().cancel() await asyncio.sleep(2) # some cleanup - async def test_timeout_exception_cause (self): - with self.assertRaises(asyncio.TimeoutError) as exc: - async with asyncio.timeout(0): + async def test_timeout_already_entered(self): + async with asyncio.timeout(0.01) as cm: + with self.assertRaisesRegex(RuntimeError, "has already been entered"): + async with cm: + pass + + async def test_timeout_double_enter(self): + async with asyncio.timeout(0.01) as cm: + pass + with self.assertRaisesRegex(RuntimeError, "has already been entered"): + async with cm: + pass + + async def test_timeout_finished(self): + async with asyncio.timeout(0.01) as cm: + pass + with self.assertRaisesRegex(RuntimeError, "finished"): + cm.reschedule(0.02) + + async def test_timeout_expired(self): + with self.assertRaises(TimeoutError): + async with asyncio.timeout(0.01) as cm: + await asyncio.sleep(1) + with self.assertRaisesRegex(RuntimeError, "expired"): + cm.reschedule(0.02) + + async def test_timeout_expiring(self): + async with asyncio.timeout(0.01) as cm: + with self.assertRaises(asyncio.CancelledError): await asyncio.sleep(1) - cause = exc.exception.__cause__ - assert isinstance(cause, asyncio.CancelledError) + with self.assertRaisesRegex(RuntimeError, "expiring"): + cm.reschedule(0.02) + + async def test_timeout_not_entered(self): + cm = asyncio.timeout(0.01) + with self.assertRaisesRegex(RuntimeError, "has not been entered"): + cm.reschedule(0.02) + + async def test_timeout_without_task(self): + cm = asyncio.timeout(0.01) + with self.assertRaisesRegex(RuntimeError, "task"): + await await_without_task(cm.__aenter__()) + with self.assertRaisesRegex(RuntimeError, "has not been entered"): + cm.reschedule(0.02) + + async def test_timeout_taskgroup(self): + async def task(): + try: + await asyncio.sleep(2) # Will be interrupted after 0.01 second + finally: + 1/0 # Crash in cleanup + + with self.assertRaises(ExceptionGroup) as cm: + async with asyncio.timeout(0.01): + async with asyncio.TaskGroup() as tg: + tg.create_task(task()) + try: + raise ValueError + finally: + await asyncio.sleep(1) + eg = cm.exception + # Expect ExceptionGroup raised during handling of TimeoutError caused + # by CancelledError raised during handling of ValueError. + self.assertIsNone(eg.__cause__) + e_1 = eg.__context__ + self.assertIsInstance(e_1, TimeoutError) + e_2 = e_1.__cause__ + self.assertIsInstance(e_2, asyncio.CancelledError) + self.assertIsNone(e_2.__cause__) + self.assertIsInstance(e_2.__context__, ValueError) + self.assertIs(e_1.__context__, e_2) + + self.assertEqual(len(eg.exceptions), 1, eg) + e1 = eg.exceptions[0] + # Expect ZeroDivisionError raised during handling of TimeoutError + # caused by CancelledError (it is a different CancelledError). + self.assertIsInstance(e1, ZeroDivisionError) + self.assertIsNone(e1.__cause__) + e2 = e1.__context__ + self.assertIsInstance(e2, TimeoutError) + e3 = e2.__cause__ + self.assertIsInstance(e3, asyncio.CancelledError) + self.assertIsNone(e3.__context__) + self.assertIsNone(e3.__cause__) + self.assertIs(e2.__context__, e3) if __name__ == '__main__': diff --git a/Lib/test/test_asyncio/test_unix_events.py b/Lib/test/test_asyncio/test_unix_events.py index cdf3eaac68af15..d2c8cba6acfa31 100644 --- a/Lib/test/test_asyncio/test_unix_events.py +++ b/Lib/test/test_asyncio/test_unix_events.py @@ -4,6 +4,7 @@ import errno import io import multiprocessing +from multiprocessing.util import _cleanup_tests as multiprocessing_cleanup_tests import os import pathlib import signal @@ -11,9 +12,12 @@ import stat import sys import threading +import time import unittest from unittest import mock import warnings + +from test import support from test.support import os_helper from test.support import socket_helper from test.support import wait_process @@ -1901,6 +1905,8 @@ async def test_fork_not_share_event_loop(self): @hashlib_helper.requires_hashdigest('md5') def test_fork_signal_handling(self): + self.addCleanup(multiprocessing_cleanup_tests) + # Sending signal to the forked process should not affect the parent # process ctx = multiprocessing.get_context('fork') @@ -1911,8 +1917,14 @@ def test_fork_signal_handling(self): parent_handled = manager.Event() def child_main(): - signal.signal(signal.SIGTERM, lambda *args: child_handled.set()) + def on_sigterm(*args): + child_handled.set() + sys.exit() + + signal.signal(signal.SIGTERM, on_sigterm) child_started.set() + while True: + time.sleep(1) async def main(): loop = asyncio.get_running_loop() @@ -1922,7 +1934,7 @@ async def main(): process.start() child_started.wait() os.kill(process.pid, signal.SIGTERM) - process.join() + process.join(timeout=support.SHORT_TIMEOUT) async def func(): await asyncio.sleep(0.1) @@ -1933,11 +1945,14 @@ async def func(): asyncio.run(main()) + child_handled.wait(timeout=support.SHORT_TIMEOUT) self.assertFalse(parent_handled.is_set()) self.assertTrue(child_handled.is_set()) @hashlib_helper.requires_hashdigest('md5') def test_fork_asyncio_run(self): + self.addCleanup(multiprocessing_cleanup_tests) + ctx = multiprocessing.get_context('fork') manager = ctx.Manager() self.addCleanup(manager.shutdown) @@ -1955,6 +1970,8 @@ async def child_main(): @hashlib_helper.requires_hashdigest('md5') def test_fork_asyncio_subprocess(self): + self.addCleanup(multiprocessing_cleanup_tests) + ctx = multiprocessing.get_context('fork') manager = ctx.Manager() self.addCleanup(manager.shutdown) diff --git a/Lib/test/test_asyncio/test_waitfor.py b/Lib/test/test_asyncio/test_waitfor.py index d5c02ba4a01df9..d52f32534a0cfe 100644 --- a/Lib/test/test_asyncio/test_waitfor.py +++ b/Lib/test/test_asyncio/test_waitfor.py @@ -1,6 +1,7 @@ import asyncio import unittest import time +from test import support def tearDownModule(): @@ -65,17 +66,12 @@ async def test_wait_for_timeout_less_then_0_or_0_future_done(self): fut = loop.create_future() fut.set_result('done') - t0 = loop.time() ret = await asyncio.wait_for(fut, 0) - t1 = loop.time() self.assertEqual(ret, 'done') self.assertTrue(fut.done()) - self.assertLess(t1 - t0, 0.1) async def test_wait_for_timeout_less_then_0_or_0_coroutine_do_not_started(self): - loop = asyncio.get_running_loop() - foo_started = False async def foo(): @@ -83,12 +79,9 @@ async def foo(): foo_started = True with self.assertRaises(asyncio.TimeoutError): - t0 = loop.time() await asyncio.wait_for(foo(), 0) - t1 = loop.time() self.assertEqual(foo_started, False) - self.assertLess(t1 - t0, 0.1) async def test_wait_for_timeout_less_then_0_or_0(self): loop = asyncio.get_running_loop() @@ -112,25 +105,21 @@ async def foo(): await started with self.assertRaises(asyncio.TimeoutError): - t0 = loop.time() await asyncio.wait_for(fut, timeout) - t1 = loop.time() self.assertTrue(fut.done()) # it should have been cancelled due to the timeout self.assertTrue(fut.cancelled()) self.assertEqual(foo_running, False) - self.assertLess(t1 - t0, 0.1) async def test_wait_for(self): - loop = asyncio.get_running_loop() foo_running = None async def foo(): nonlocal foo_running foo_running = True try: - await asyncio.sleep(10) + await asyncio.sleep(support.LONG_TIMEOUT) finally: foo_running = False return 'done' @@ -138,13 +127,10 @@ async def foo(): fut = asyncio.create_task(foo()) with self.assertRaises(asyncio.TimeoutError): - t0 = loop.time() await asyncio.wait_for(fut, 0.1) - t1 = loop.time() self.assertTrue(fut.done()) # it should have been cancelled due to the timeout self.assertTrue(fut.cancelled()) - self.assertLess(t1 - t0, 0.5) self.assertEqual(foo_running, False) async def test_wait_for_blocking(self): diff --git a/Lib/test/test_asyncio/test_windows_events.py b/Lib/test/test_asyncio/test_windows_events.py index a36119a8004f9d..6e6c90a247b291 100644 --- a/Lib/test/test_asyncio/test_windows_events.py +++ b/Lib/test/test_asyncio/test_windows_events.py @@ -163,29 +163,25 @@ def test_wait_for_handle(self): # Wait for unset event with 0.5s timeout; # result should be False at timeout - fut = self.loop._proactor.wait_for_handle(event, 0.5) + timeout = 0.5 + fut = self.loop._proactor.wait_for_handle(event, timeout) start = self.loop.time() done = self.loop.run_until_complete(fut) elapsed = self.loop.time() - start self.assertEqual(done, False) self.assertFalse(fut.result()) - # bpo-31008: Tolerate only 450 ms (at least 500 ms expected), - # because of bad clock resolution on Windows - self.assertTrue(0.45 <= elapsed <= 0.9, elapsed) + self.assertGreaterEqual(elapsed, timeout - test_utils.CLOCK_RES) _overlapped.SetEvent(event) # Wait for set event; # result should be True immediately fut = self.loop._proactor.wait_for_handle(event, 10) - start = self.loop.time() done = self.loop.run_until_complete(fut) - elapsed = self.loop.time() - start self.assertEqual(done, True) self.assertTrue(fut.result()) - self.assertTrue(0 <= elapsed < 0.3, elapsed) # asyncio issue #195: cancelling a done _WaitHandleFuture # must not crash @@ -199,11 +195,8 @@ def test_wait_for_handle_cancel(self): # CancelledError should be raised immediately fut = self.loop._proactor.wait_for_handle(event, 10) fut.cancel() - start = self.loop.time() with self.assertRaises(asyncio.CancelledError): self.loop.run_until_complete(fut) - elapsed = self.loop.time() - start - self.assertTrue(0 <= elapsed < 0.1, elapsed) # asyncio issue #195: cancelling a _WaitHandleFuture twice # must not crash diff --git a/Lib/test/test_asyncio/utils.py b/Lib/test/test_asyncio/utils.py index 6dee5bb33b2560..44943e1fa7bc4e 100644 --- a/Lib/test/test_asyncio/utils.py +++ b/Lib/test/test_asyncio/utils.py @@ -36,21 +36,26 @@ from test.support import threading_helper -def data_file(filename): - if hasattr(support, 'TEST_HOME_DIR'): - fullname = os.path.join(support.TEST_HOME_DIR, filename) - if os.path.isfile(fullname): - return fullname - fullname = os.path.join(os.path.dirname(__file__), '..', filename) +# Use the maximum known clock resolution (gh-75191, gh-110088): Windows +# GetTickCount64() has a resolution of 15.6 ms. Use 50 ms to tolerate rounding +# issues. +CLOCK_RES = 0.050 + + +def data_file(*filename): + fullname = os.path.join(support.TEST_HOME_DIR, *filename) if os.path.isfile(fullname): return fullname - raise FileNotFoundError(filename) + fullname = os.path.join(os.path.dirname(__file__), '..', *filename) + if os.path.isfile(fullname): + return fullname + raise FileNotFoundError(os.path.join(filename)) -ONLYCERT = data_file('ssl_cert.pem') -ONLYKEY = data_file('ssl_key.pem') -SIGNED_CERTFILE = data_file('keycert3.pem') -SIGNING_CA = data_file('pycacert.pem') +ONLYCERT = data_file('certdata', 'ssl_cert.pem') +ONLYKEY = data_file('certdata', 'ssl_key.pem') +SIGNED_CERTFILE = data_file('certdata', 'keycert3.pem') +SIGNING_CA = data_file('certdata', 'pycacert.pem') PEERCERT = { 'OCSP': ('http://testca.pythontest.net/testca/ocsp/',), 'caIssuers': ('http://testca.pythontest.net/testca/pycacert.cer',), @@ -541,6 +546,7 @@ def close_loop(loop): else: loop._default_executor.shutdown(wait=True) loop.close() + policy = support.maybe_get_event_loop_policy() if policy is not None: try: @@ -552,9 +558,13 @@ def close_loop(loop): pass else: if isinstance(watcher, asyncio.ThreadedChildWatcher): - threads = list(watcher._threads.values()) - for thread in threads: - thread.join() + # Wait for subprocess to finish, but not forever + for thread in list(watcher._threads.values()): + thread.join(timeout=support.SHORT_TIMEOUT) + if thread.is_alive(): + raise RuntimeError(f"thread {thread} still alive: " + "subprocess still running") + def set_event_loop(self, loop, *, cleanup=True): if loop is None: @@ -607,3 +617,18 @@ def mock_nonblocking_socket(proto=socket.IPPROTO_TCP, type=socket.SOCK_STREAM, sock.family = family sock.gettimeout.return_value = 0.0 return sock + + +async def await_without_task(coro): + exc = None + def func(): + try: + for _ in coro.__await__(): + pass + except BaseException as err: + nonlocal exc + exc = err + asyncio.get_running_loop().call_soon(func) + await asyncio.sleep(0) + if exc is not None: + raise exc diff --git a/Lib/test/test_audit.py b/Lib/test/test_audit.py index 0b69864751d83d..cd0a4e2264865d 100644 --- a/Lib/test/test_audit.py +++ b/Lib/test/test_audit.py @@ -19,7 +19,7 @@ class AuditTest(unittest.TestCase): maxDiff = None @support.requires_subprocess() - def do_test(self, *args): + def run_test_in_subprocess(self, *args): with subprocess.Popen( [sys.executable, "-X utf8", AUDIT_TESTS_PY, *args], encoding="utf-8", @@ -27,27 +27,26 @@ def do_test(self, *args): stderr=subprocess.PIPE, ) as p: p.wait() - sys.stdout.writelines(p.stdout) - sys.stderr.writelines(p.stderr) - if p.returncode: - self.fail("".join(p.stderr)) + return p, p.stdout.read(), p.stderr.read() - @support.requires_subprocess() - def run_python(self, *args): + def do_test(self, *args): + proc, stdout, stderr = self.run_test_in_subprocess(*args) + + sys.stdout.write(stdout) + sys.stderr.write(stderr) + if proc.returncode: + self.fail(stderr) + + def run_python(self, *args, expect_stderr=False): events = [] - with subprocess.Popen( - [sys.executable, "-X utf8", AUDIT_TESTS_PY, *args], - encoding="utf-8", - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - ) as p: - p.wait() - sys.stderr.writelines(p.stderr) - return ( - p.returncode, - [line.strip().partition(" ") for line in p.stdout], - "".join(p.stderr), - ) + proc, stdout, stderr = self.run_test_in_subprocess(*args) + if not expect_stderr or support.verbose: + sys.stderr.write(stderr) + return ( + proc.returncode, + [line.strip().partition(" ") for line in stdout.splitlines()], + stderr, + ) def test_basic(self): self.do_test("test_basic") @@ -210,6 +209,8 @@ def test_threading(self): expected = [ ("_thread.start_new_thread", "(, (), None)"), ("test.test_func", "()"), + ("_thread.start_joinable_thread", "(,)"), + ("test.test_func", "()"), ] self.assertEqual(actual, expected) @@ -256,6 +257,39 @@ def test_not_in_gc(self): if returncode: self.fail(stderr) + def test_time(self): + returncode, events, stderr = self.run_python("test_time", "print") + if returncode: + self.fail(stderr) + + if support.verbose: + print(*events, sep='\n') + + actual = [(ev[0], ev[2]) for ev in events] + expected = [("time.sleep", "0"), + ("time.sleep", "0.0625"), + ("time.sleep", "-1")] + + self.assertEqual(actual, expected) + + def test_time_fail(self): + returncode, events, stderr = self.run_python("test_time", "fail", + expect_stderr=True) + self.assertNotEqual(returncode, 0) + self.assertIn('hook failed', stderr.splitlines()[-1]) + + def test_sys_monitoring_register_callback(self): + returncode, events, stderr = self.run_python("test_sys_monitoring_register_callback") + if returncode: + self.fail(stderr) + + if support.verbose: + print(*events, sep='\n') + actual = [(ev[0], ev[2]) for ev in events] + expected = [("sys.monitoring.register_callback", "(None,)")] + + self.assertEqual(actual, expected) + if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_base64.py b/Lib/test/test_base64.py index fa03fa1d61ceab..f6171d3ed4efd7 100644 --- a/Lib/test/test_base64.py +++ b/Lib/test/test_base64.py @@ -586,6 +586,7 @@ def test_a85decode(self): eq(base64.a85decode(b'y+', b"www.python.org") @@ -689,6 +690,8 @@ def test_a85decode_errors(self): self.assertRaises(ValueError, base64.a85decode, b's8W', adobe=False) self.assertRaises(ValueError, base64.a85decode, b's8W-', adobe=False) self.assertRaises(ValueError, base64.a85decode, b's8W-"', adobe=False) + self.assertRaises(ValueError, base64.a85decode, b'aaaay', + foldspaces=True) def test_b85decode_errors(self): illegal = list(range(33)) + \ diff --git a/Lib/test/test_binascii.py b/Lib/test/test_binascii.py index a2d7d0293ce1ae..82dea8a6d731ea 100644 --- a/Lib/test/test_binascii.py +++ b/Lib/test/test_binascii.py @@ -5,6 +5,7 @@ import array import re from test.support import bigmemtest, _1G, _4G +from test.support.hypothesis_helper import hypothesis # Note: "*_hex" functions are aliases for "(un)hexlify" @@ -27,6 +28,14 @@ class BinASCIITest(unittest.TestCase): def setUp(self): self.data = self.type2test(self.rawdata) + def assertConversion(self, original, converted, restored, **kwargs): + self.assertIsInstance(original, bytes) + self.assertIsInstance(converted, bytes) + self.assertIsInstance(restored, bytes) + if converted: + self.assertLess(max(converted), 128) + self.assertEqual(original, restored, msg=f'{self.type2test=} {kwargs=}') + def test_exceptions(self): # Check module exceptions self.assertTrue(issubclass(binascii.Error, Exception)) @@ -52,9 +61,7 @@ def test_returned_value(self): self.fail("{}/{} conversion raises {!r}".format(fb, fa, err)) self.assertEqual(res, raw, "{}/{} conversion: " "{!r} != {!r}".format(fb, fa, res, raw)) - self.assertIsInstance(res, bytes) - self.assertIsInstance(a, bytes) - self.assertLess(max(a), 128) + self.assertConversion(raw, a, res) self.assertIsInstance(binascii.crc_hqx(raw, 0), int) self.assertIsInstance(binascii.crc32(raw), int) @@ -222,6 +229,15 @@ def test_uu(self): with self.assertRaises(TypeError): binascii.b2a_uu(b"", True) + @hypothesis.given( + binary=hypothesis.strategies.binary(max_size=45), + backtick=hypothesis.strategies.booleans(), + ) + def test_b2a_roundtrip(self, binary, backtick): + converted = binascii.b2a_uu(self.type2test(binary), backtick=backtick) + restored = binascii.a2b_uu(self.type2test(converted)) + self.assertConversion(binary, converted, restored, backtick=backtick) + def test_crc_hqx(self): crc = binascii.crc_hqx(self.type2test(b"Test the CRC-32 of"), 0) crc = binascii.crc_hqx(self.type2test(b" this string."), crc) @@ -259,6 +275,12 @@ def test_hex(self): self.assertEqual(binascii.hexlify(self.type2test(s)), t) self.assertEqual(binascii.unhexlify(self.type2test(t)), u) + @hypothesis.given(binary=hypothesis.strategies.binary()) + def test_hex_roundtrip(self, binary): + converted = binascii.hexlify(self.type2test(binary)) + restored = binascii.unhexlify(self.type2test(converted)) + self.assertConversion(binary, converted, restored) + def test_hex_separator(self): """Test that hexlify and b2a_hex are binary versions of bytes.hex.""" # Logic of separators is tested in test_bytes.py. This checks that @@ -373,6 +395,21 @@ def test_qp(self): self.assertEqual(b2a_qp(type2test(b'a.\n')), b'a.\n') self.assertEqual(b2a_qp(type2test(b'.a')[:-1]), b'=2E') + @hypothesis.given( + binary=hypothesis.strategies.binary(), + quotetabs=hypothesis.strategies.booleans(), + istext=hypothesis.strategies.booleans(), + header=hypothesis.strategies.booleans(), + ) + def test_b2a_qp_a2b_qp_round_trip(self, binary, quotetabs, istext, header): + converted = binascii.b2a_qp( + self.type2test(binary), + quotetabs=quotetabs, istext=istext, header=header, + ) + restored = binascii.a2b_qp(self.type2test(converted), header=header) + self.assertConversion(binary, converted, restored, + quotetabs=quotetabs, istext=istext, header=header) + def test_empty_string(self): # A test for SF bug #1022953. Make sure SystemError is not raised. empty = self.type2test(b'') @@ -428,6 +465,21 @@ def test_b2a_base64_newline(self): self.assertEqual(binascii.b2a_base64(b, newline=False), b'aGVsbG8=') + @hypothesis.given( + binary=hypothesis.strategies.binary(), + newline=hypothesis.strategies.booleans(), + ) + def test_base64_roundtrip(self, binary, newline): + converted = binascii.b2a_base64(self.type2test(binary), newline=newline) + restored = binascii.a2b_base64(self.type2test(converted)) + self.assertConversion(binary, converted, restored, newline=newline) + + def test_c_contiguity(self): + m = memoryview(bytearray(b'noncontig')) + noncontig_writable = m[::-2] + with self.assertRaises(BufferError): + binascii.b2a_hex(noncontig_writable) + class ArrayBinASCIITest(BinASCIITest): def type2test(self, s): diff --git a/Lib/test/test_buffer.py b/Lib/test/test_buffer.py index b679d2e8a01f92..72a06d6af450e3 100644 --- a/Lib/test/test_buffer.py +++ b/Lib/test/test_buffer.py @@ -1029,6 +1029,7 @@ def match(req, flag): ndim=ndim, shape=shape, strides=strides, lst=lst, sliced=sliced) + @support.requires_resource('cpu') def test_ndarray_getbuf(self): requests = ( # distinct flags @@ -2760,6 +2761,7 @@ def iter_roundtrip(ex, m, items, fmt): m = memoryview(ex) iter_roundtrip(ex, m, items, fmt) + @support.requires_resource('cpu') def test_memoryview_cast_1D_ND(self): # Cast between C-contiguous buffers. At least one buffer must # be 1D, at least one format must be 'c', 'b' or 'B'. diff --git a/Lib/test/test_builtin.py b/Lib/test/test_builtin.py index f5a5c037f1bf1b..fcddd147bac63e 100644 --- a/Lib/test/test_builtin.py +++ b/Lib/test/test_builtin.py @@ -369,16 +369,17 @@ def f(): """doc""" (1, False, 'doc', False, False), (2, False, None, False, False)] for optval, *expected in values: + with self.subTest(optval=optval): # test both direct compilation and compilation via AST - codeobjs = [] - codeobjs.append(compile(codestr, "", "exec", optimize=optval)) - tree = ast.parse(codestr) - codeobjs.append(compile(tree, "", "exec", optimize=optval)) - for code in codeobjs: - ns = {} - exec(code, ns) - rv = ns['f']() - self.assertEqual(rv, tuple(expected)) + codeobjs = [] + codeobjs.append(compile(codestr, "", "exec", optimize=optval)) + tree = ast.parse(codestr) + codeobjs.append(compile(tree, "", "exec", optimize=optval)) + for code in codeobjs: + ns = {} + exec(code, ns) + rv = ns['f']() + self.assertEqual(rv, tuple(expected)) def test_compile_top_level_await_no_coro(self): """Make sure top level non-await codes get the correct coroutine flags""" @@ -517,6 +518,30 @@ def test_compile_async_generator(self): exec(co, glob) self.assertEqual(type(glob['ticker']()), AsyncGeneratorType) + def test_compile_ast(self): + args = ("a*(1+2)", "f.py", "exec") + raw = compile(*args, flags = ast.PyCF_ONLY_AST).body[0] + opt1 = compile(*args, flags = ast.PyCF_OPTIMIZED_AST).body[0] + opt2 = compile(ast.parse(args[0]), *args[1:], flags = ast.PyCF_OPTIMIZED_AST).body[0] + + for tree in (raw, opt1, opt2): + self.assertIsInstance(tree.value, ast.BinOp) + self.assertIsInstance(tree.value.op, ast.Mult) + self.assertIsInstance(tree.value.left, ast.Name) + self.assertEqual(tree.value.left.id, 'a') + + raw_right = raw.value.right # expect BinOp(1, '+', 2) + self.assertIsInstance(raw_right, ast.BinOp) + self.assertIsInstance(raw_right.left, ast.Constant) + self.assertEqual(raw_right.left.value, 1) + self.assertIsInstance(raw_right.right, ast.Constant) + self.assertEqual(raw_right.right.value, 2) + + for opt in [opt1, opt2]: + opt_right = opt.value.right # expect Constant(3) + self.assertIsInstance(opt_right, ast.Constant) + self.assertEqual(opt_right.value, 3) + def test_delattr(self): sys.spam = 1 delattr(sys, 'spam') @@ -602,6 +627,11 @@ def __dir__(self): # test that object has a __dir__() self.assertEqual(sorted([].__dir__()), dir([])) + def test___ne__(self): + self.assertFalse(None.__ne__(None)) + self.assertIs(None.__ne__(0), NotImplemented) + self.assertIs(None.__ne__("abc"), NotImplemented) + def test_divmod(self): self.assertEqual(divmod(12, 7), (1, 5)) self.assertEqual(divmod(-12, 7), (-2, 2)) @@ -807,6 +837,32 @@ class customdict(dict): # this one should not do anything fancy self.assertRaisesRegex(NameError, "name 'superglobal' is not defined", exec, code, {'__builtins__': customdict()}) + def test_eval_builtins_mapping(self): + code = compile("superglobal", "test", "eval") + # works correctly + ns = {'__builtins__': types.MappingProxyType({'superglobal': 1})} + self.assertEqual(eval(code, ns), 1) + # custom builtins mapping is missing key + ns = {'__builtins__': types.MappingProxyType({})} + self.assertRaisesRegex(NameError, "name 'superglobal' is not defined", + eval, code, ns) + + def test_exec_builtins_mapping_import(self): + code = compile("import foo.bar", "test", "exec") + ns = {'__builtins__': types.MappingProxyType({})} + self.assertRaisesRegex(ImportError, "__import__ not found", exec, code, ns) + ns = {'__builtins__': types.MappingProxyType({'__import__': lambda *args: args})} + exec(code, ns) + self.assertEqual(ns['foo'], ('foo.bar', ns, ns, None, 0)) + + def test_eval_builtins_mapping_reduce(self): + # list_iterator.__reduce__() calls _PyEval_GetBuiltin("iter") + code = compile("x.__reduce__()", "test", "eval") + ns = {'__builtins__': types.MappingProxyType({}), 'x': iter([1, 2])} + self.assertRaisesRegex(AttributeError, "iter", eval, code, ns) + ns = {'__builtins__': types.MappingProxyType({'iter': iter}), 'x': iter([1, 2])} + self.assertEqual(eval(code, ns), (iter, ([1, 2],), 0)) + def test_exec_redirected(self): savestdout = sys.stdout sys.stdout = None # Whatever that cannot flush() @@ -927,6 +983,7 @@ def test_filter_pickle(self): f2 = filter(filter_char, "abcdeabcde") self.check_iter_pickle(f1, list(f2), proto) + @support.requires_resource('cpu') def test_filter_dealloc(self): # Tests recursive deallocation of nested filter objects using the # thrashcan mechanism. See gh-102356 for more details. @@ -2013,6 +2070,23 @@ def test_bytearray_extend_error(self): bad_iter = map(int, "X") self.assertRaises(ValueError, array.extend, bad_iter) + def test_bytearray_join_with_misbehaving_iterator(self): + # Issue #112625 + array = bytearray(b',') + def iterator(): + array.clear() + yield b'A' + yield b'B' + self.assertRaises(BufferError, array.join, iterator()) + + def test_bytearray_join_with_custom_iterator(self): + # Issue #112625 + array = bytearray(b',') + def iterator(): + yield b'A' + yield b'B' + self.assertEqual(bytearray(b'A,B'), array.join(iterator())) + def test_construct_singletons(self): for const in None, Ellipsis, NotImplemented: tp = type(const) @@ -2177,8 +2251,6 @@ def _run_child(self, child, terminal_input): if pid == 0: # Child try: - # Make sure we don't get stuck if there's a problem - signal.alarm(2) os.close(r) with open(w, "w") as wpipe: child(wpipe) @@ -2228,7 +2300,10 @@ def _run_child(self, child, terminal_input): return lines - def check_input_tty(self, prompt, terminal_input, stdio_encoding=None): + def check_input_tty(self, prompt, terminal_input, stdio_encoding=None, *, + expected=None, + stdin_errors='surrogateescape', + stdout_errors='replace'): if not sys.stdin.isatty() or not sys.stdout.isatty(): self.skipTest("stdin and stdout must be ttys") def child(wpipe): @@ -2236,22 +2311,26 @@ def child(wpipe): if stdio_encoding: sys.stdin = io.TextIOWrapper(sys.stdin.detach(), encoding=stdio_encoding, - errors='surrogateescape') + errors=stdin_errors) sys.stdout = io.TextIOWrapper(sys.stdout.detach(), encoding=stdio_encoding, - errors='replace') + errors=stdout_errors) print("tty =", sys.stdin.isatty() and sys.stdout.isatty(), file=wpipe) - print(ascii(input(prompt)), file=wpipe) + try: + print(ascii(input(prompt)), file=wpipe) + except BaseException as e: + print(ascii(f'{e.__class__.__name__}: {e!s}'), file=wpipe) lines = self.run_child(child, terminal_input + b"\r\n") # Check we did exercise the GNU readline path self.assertIn(lines[0], {'tty = True', 'tty = False'}) if lines[0] != 'tty = True': self.skipTest("standard IO in should have been a tty") input_result = eval(lines[1]) # ascii() -> eval() roundtrip - if stdio_encoding: - expected = terminal_input.decode(stdio_encoding, 'surrogateescape') - else: - expected = terminal_input.decode(sys.stdin.encoding) # what else? + if expected is None: + if stdio_encoding: + expected = terminal_input.decode(stdio_encoding, 'surrogateescape') + else: + expected = terminal_input.decode(sys.stdin.encoding) # what else? self.assertEqual(input_result, expected) def test_input_tty(self): @@ -2272,13 +2351,32 @@ def skip_if_readline(self): def test_input_tty_non_ascii(self): self.skip_if_readline() # Check stdin/stdout encoding is used when invoking PyOS_Readline() - self.check_input_tty("prompté", b"quux\xe9", "utf-8") + self.check_input_tty("prompté", b"quux\xc3\xa9", "utf-8") def test_input_tty_non_ascii_unicode_errors(self): self.skip_if_readline() # Check stdin/stdout error handler is used when invoking PyOS_Readline() self.check_input_tty("prompté", b"quux\xe9", "ascii") + def test_input_tty_null_in_prompt(self): + self.check_input_tty("prompt\0", b"", + expected='ValueError: input: prompt string cannot contain ' + 'null characters') + + def test_input_tty_nonencodable_prompt(self): + self.skip_if_readline() + self.check_input_tty("prompté", b"quux", "ascii", stdout_errors='strict', + expected="UnicodeEncodeError: 'ascii' codec can't encode " + "character '\\xe9' in position 6: ordinal not in " + "range(128)") + + def test_input_tty_nondecodable_input(self): + self.skip_if_readline() + self.check_input_tty("prompt", b"quux\xe9", "ascii", stdin_errors='strict', + expected="UnicodeDecodeError: 'ascii' codec can't decode " + "byte 0xe9 in position 4: ordinal not in " + "range(128)") + def test_input_no_stdout_fileno(self): # Issue #24402: If stdin is the original terminal but stdout.fileno() # fails, do not use the original stdout file descriptor diff --git a/Lib/test/test_bytes.py b/Lib/test/test_bytes.py index 7c62b722059d12..a3804a945f2e3a 100644 --- a/Lib/test/test_bytes.py +++ b/Lib/test/test_bytes.py @@ -46,6 +46,10 @@ def __index__(self): class BaseBytesTest: + def assertTypedEqual(self, actual, expected): + self.assertIs(type(actual), type(expected)) + self.assertEqual(actual, expected) + def test_basics(self): b = self.type2test() self.assertEqual(type(b), self.type2test) @@ -1023,36 +1027,63 @@ def test_buffer_is_readonly(self): self.assertRaises(TypeError, f.readinto, b"") def test_custom(self): - class A: - def __bytes__(self): - return b'abc' - self.assertEqual(bytes(A()), b'abc') - class A: pass - self.assertRaises(TypeError, bytes, A()) - class A: - def __bytes__(self): - return None - self.assertRaises(TypeError, bytes, A()) - class A: + self.assertEqual(bytes(BytesSubclass(b'abc')), b'abc') + self.assertEqual(BytesSubclass(OtherBytesSubclass(b'abc')), + BytesSubclass(b'abc')) + self.assertEqual(bytes(WithBytes(b'abc')), b'abc') + self.assertEqual(BytesSubclass(WithBytes(b'abc')), BytesSubclass(b'abc')) + + class NoBytes: pass + self.assertRaises(TypeError, bytes, NoBytes()) + self.assertRaises(TypeError, bytes, WithBytes('abc')) + self.assertRaises(TypeError, bytes, WithBytes(None)) + class IndexWithBytes: def __bytes__(self): return b'a' def __index__(self): return 42 - self.assertEqual(bytes(A()), b'a') + self.assertEqual(bytes(IndexWithBytes()), b'a') # Issue #25766 - class A(str): + class StrWithBytes(str): + def __new__(cls, value): + self = str.__new__(cls, '\u20ac') + self.value = value + return self def __bytes__(self): - return b'abc' - self.assertEqual(bytes(A('\u20ac')), b'abc') - self.assertEqual(bytes(A('\u20ac'), 'iso8859-15'), b'\xa4') + return self.value + self.assertEqual(bytes(StrWithBytes(b'abc')), b'abc') + self.assertEqual(bytes(StrWithBytes(b'abc'), 'iso8859-15'), b'\xa4') + self.assertEqual(bytes(StrWithBytes(BytesSubclass(b'abc'))), b'abc') + self.assertEqual(BytesSubclass(StrWithBytes(b'abc')), BytesSubclass(b'abc')) + self.assertEqual(BytesSubclass(StrWithBytes(b'abc'), 'iso8859-15'), + BytesSubclass(b'\xa4')) + self.assertEqual(BytesSubclass(StrWithBytes(BytesSubclass(b'abc'))), + BytesSubclass(b'abc')) + self.assertEqual(BytesSubclass(StrWithBytes(OtherBytesSubclass(b'abc'))), + BytesSubclass(b'abc')) # Issue #24731 - class A: + self.assertTypedEqual(bytes(WithBytes(BytesSubclass(b'abc'))), BytesSubclass(b'abc')) + self.assertTypedEqual(BytesSubclass(WithBytes(BytesSubclass(b'abc'))), + BytesSubclass(b'abc')) + self.assertTypedEqual(BytesSubclass(WithBytes(OtherBytesSubclass(b'abc'))), + BytesSubclass(b'abc')) + + class BytesWithBytes(bytes): + def __new__(cls, value): + self = bytes.__new__(cls, b'\xa4') + self.value = value + return self def __bytes__(self): - return OtherBytesSubclass(b'abc') - self.assertEqual(bytes(A()), b'abc') - self.assertIs(type(bytes(A())), OtherBytesSubclass) - self.assertEqual(BytesSubclass(A()), b'abc') - self.assertIs(type(BytesSubclass(A())), BytesSubclass) + return self.value + self.assertTypedEqual(bytes(BytesWithBytes(b'abc')), b'abc') + self.assertTypedEqual(BytesSubclass(BytesWithBytes(b'abc')), + BytesSubclass(b'abc')) + self.assertTypedEqual(bytes(BytesWithBytes(BytesSubclass(b'abc'))), + BytesSubclass(b'abc')) + self.assertTypedEqual(BytesSubclass(BytesWithBytes(BytesSubclass(b'abc'))), + BytesSubclass(b'abc')) + self.assertTypedEqual(BytesSubclass(BytesWithBytes(OtherBytesSubclass(b'abc'))), + BytesSubclass(b'abc')) # Test PyBytes_FromFormat() def test_from_format(self): @@ -1354,7 +1385,7 @@ def do_tests(setitem): except ValueError: pass try: - setitem(b, 0, None) + setitem(b, 0, object()) self.fail("Didn't raise TypeError") except TypeError: pass @@ -2069,6 +2100,12 @@ class BytesSubclass(bytes): class OtherBytesSubclass(bytes): pass +class WithBytes: + def __init__(self, value): + self.value = value + def __bytes__(self): + return self.value + class ByteArraySubclassTest(SubclassTest, unittest.TestCase): basetype = bytearray type2test = ByteArraySubclass diff --git a/Lib/test/test_bz2.py b/Lib/test/test_bz2.py index e4dd7fc2100b62..1f0b9adc3698b4 100644 --- a/Lib/test/test_bz2.py +++ b/Lib/test/test_bz2.py @@ -721,10 +721,10 @@ def testEOFError(self): @bigmemtest(size=_4G + 100, memuse=3.3) def testDecompress4G(self, size): # "Test BZ2Decompressor.decompress() with >4GiB input" - blocksize = 10 * 1024 * 1024 + blocksize = min(10 * 1024 * 1024, size) block = random.randbytes(blocksize) try: - data = block * (size // blocksize + 1) + data = block * ((size-1) // blocksize + 1) compressed = bz2.compress(data) bz2d = BZ2Decompressor() decompressed = bz2d.decompress(compressed) diff --git a/Lib/test/test_c_locale_coercion.py b/Lib/test/test_c_locale_coercion.py index 71f934756e26a1..7334a325ba22f0 100644 --- a/Lib/test/test_c_locale_coercion.py +++ b/Lib/test/test_c_locale_coercion.py @@ -112,12 +112,16 @@ class EncodingDetails(_EncodingDetails): ]) @classmethod - def get_expected_details(cls, coercion_expected, fs_encoding, stream_encoding, env_vars): + def get_expected_details(cls, coercion_expected, fs_encoding, stream_encoding, stream_errors, env_vars): """Returns expected child process details for a given encoding""" _stream = stream_encoding + ":{}" - # stdin and stdout should use surrogateescape either because the - # coercion triggered, or because the C locale was detected - stream_info = 2*[_stream.format("surrogateescape")] + if stream_errors is None: + # stdin and stdout should use surrogateescape either because the + # coercion triggered, or because the C locale was detected + stream_errors = "surrogateescape" + + stream_info = [_stream.format(stream_errors)] * 2 + # stderr should always use backslashreplace stream_info.append(_stream.format("backslashreplace")) expected_lang = env_vars.get("LANG", "not set") @@ -210,6 +214,7 @@ def _check_child_encoding_details(self, env_vars, expected_fs_encoding, expected_stream_encoding, + expected_stream_errors, expected_warnings, coercion_expected): """Check the C locale handling for the given process environment @@ -225,6 +230,7 @@ def _check_child_encoding_details(self, coercion_expected, expected_fs_encoding, expected_stream_encoding, + expected_stream_errors, env_vars ) self.assertEqual(encoding_details, expected_details) @@ -257,6 +263,7 @@ def test_external_target_locale_configuration(self): "LC_CTYPE": "", "LC_ALL": "", "PYTHONCOERCECLOCALE": "", + "PYTHONIOENCODING": "", } for env_var in ("LANG", "LC_CTYPE"): for locale_to_set in AVAILABLE_TARGETS: @@ -273,10 +280,43 @@ def test_external_target_locale_configuration(self): self._check_child_encoding_details(var_dict, expected_fs_encoding, expected_stream_encoding, + expected_stream_errors=None, expected_warnings=None, coercion_expected=False) + def test_with_ioencoding(self): + # Explicitly setting a target locale should give the same behaviour as + # is seen when implicitly coercing to that target locale + self.maxDiff = None + + expected_fs_encoding = "utf-8" + expected_stream_encoding = "utf-8" + base_var_dict = { + "LANG": "", + "LC_CTYPE": "", + "LC_ALL": "", + "PYTHONCOERCECLOCALE": "", + "PYTHONIOENCODING": "UTF-8", + } + for env_var in ("LANG", "LC_CTYPE"): + for locale_to_set in AVAILABLE_TARGETS: + # XXX (ncoghlan): LANG=UTF-8 doesn't appear to work as + # expected, so skip that combination for now + # See https://bugs.python.org/issue30672 for discussion + if env_var == "LANG" and locale_to_set == "UTF-8": + continue + + with self.subTest(env_var=env_var, + configured_locale=locale_to_set): + var_dict = base_var_dict.copy() + var_dict[env_var] = locale_to_set + self._check_child_encoding_details(var_dict, + expected_fs_encoding, + expected_stream_encoding, + expected_stream_errors="strict", + expected_warnings=None, + coercion_expected=False) @support.cpython_only @unittest.skipUnless(sysconfig.get_config_var("PY_COERCE_C_LOCALE"), @@ -316,6 +356,7 @@ def _check_c_locale_coercion(self, "LC_CTYPE": "", "LC_ALL": "", "PYTHONCOERCECLOCALE": "", + "PYTHONIOENCODING": "", } base_var_dict.update(extra_vars) if coerce_c_locale is not None: @@ -340,6 +381,7 @@ def _check_c_locale_coercion(self, self._check_child_encoding_details(base_var_dict, fs_encoding, stream_encoding, + None, _expected_warnings, _coercion_expected) @@ -348,13 +390,15 @@ def _check_c_locale_coercion(self, for env_var in ("LANG", "LC_CTYPE"): with self.subTest(env_var=env_var, nominal_locale=locale_to_set, - PYTHONCOERCECLOCALE=coerce_c_locale): + PYTHONCOERCECLOCALE=coerce_c_locale, + PYTHONIOENCODING=""): var_dict = base_var_dict.copy() var_dict[env_var] = locale_to_set # Check behaviour on successful coercion self._check_child_encoding_details(var_dict, fs_encoding, stream_encoding, + None, expected_warnings, coercion_expected) diff --git a/Lib/test/test_call.py b/Lib/test/test_call.py index c3c3b1853b5736..b1c78d7136fc9b 100644 --- a/Lib/test/test_call.py +++ b/Lib/test/test_call.py @@ -65,7 +65,8 @@ def test_varargs3(self): self.assertRaisesRegex(TypeError, msg, int.from_bytes, b'a', 'little', False) def test_varargs1min(self): - msg = r"get expected at least 1 argument, got 0" + msg = (r"get\(\) takes at least 1 argument \(0 given\)|" + r"get expected at least 1 argument, got 0") self.assertRaisesRegex(TypeError, msg, {}.get) msg = r"expected 1 argument, got 0" @@ -76,11 +77,13 @@ def test_varargs2min(self): self.assertRaisesRegex(TypeError, msg, getattr) def test_varargs1max(self): - msg = r"input expected at most 1 argument, got 2" + msg = (r"input\(\) takes at most 1 argument \(2 given\)|" + r"input expected at most 1 argument, got 2") self.assertRaisesRegex(TypeError, msg, input, 1, 2) def test_varargs2max(self): - msg = r"get expected at most 2 arguments, got 3" + msg = (r"get\(\) takes at most 2 arguments \(3 given\)|" + r"get expected at most 2 arguments, got 3") self.assertRaisesRegex(TypeError, msg, {}.get, 1, 2, 3) def test_varargs1_kw(self): @@ -96,7 +99,7 @@ def test_varargs3_kw(self): self.assertRaisesRegex(TypeError, msg, bool, x=2) def test_varargs4_kw(self): - msg = r"^list[.]index\(\) takes no keyword arguments$" + msg = r"^(list[.])?index\(\) takes no keyword arguments$" self.assertRaisesRegex(TypeError, msg, [].index, x=2) def test_varargs5_kw(self): @@ -915,6 +918,74 @@ def test_multiple_values(self): with self.check_raises_type_error(msg): A().method_two_args("x", "y", x="oops") +@cpython_only +class TestErrorMessagesSuggestions(unittest.TestCase): + @contextlib.contextmanager + def check_suggestion_includes(self, message): + with self.assertRaises(TypeError) as cm: + yield + self.assertIn(f"Did you mean '{message}'?", str(cm.exception)) + + @contextlib.contextmanager + def check_suggestion_not_pressent(self): + with self.assertRaises(TypeError) as cm: + yield + self.assertNotIn("Did you mean", str(cm.exception)) + + def test_unexpected_keyword_suggestion_valid_positions(self): + def foo(blech=None, /, aaa=None, *args, late1=None): + pass + + cases = [ + ("blach", None), + ("aa", "aaa"), + ("orgs", None), + ("late11", "late1"), + ] + + for keyword, suggestion in cases: + with self.subTest(keyword): + ctx = self.check_suggestion_includes(suggestion) if suggestion else self.check_suggestion_not_pressent() + with ctx: + foo(**{keyword:None}) + + def test_unexpected_keyword_suggestion_kinds(self): + + def substitution(noise=None, more_noise=None, a = None, blech = None): + pass + + def elimination(noise = None, more_noise = None, a = None, blch = None): + pass + + def addition(noise = None, more_noise = None, a = None, bluchin = None): + pass + + def substitution_over_elimination(blach = None, bluc = None): + pass + + def substitution_over_addition(blach = None, bluchi = None): + pass + + def elimination_over_addition(bluc = None, blucha = None): + pass + + def case_change_over_substitution(BLuch=None, Luch = None, fluch = None): + pass + + for func, suggestion in [ + (addition, "bluchin"), + (substitution, "blech"), + (elimination, "blch"), + (addition, "bluchin"), + (substitution_over_elimination, "blach"), + (substitution_over_addition, "blach"), + (elimination_over_addition, "bluc"), + (case_change_over_substitution, "BLuch"), + ]: + with self.subTest(suggestion): + with self.check_suggestion_includes(suggestion): + func(bluch=None) + @cpython_only class TestRecursion(unittest.TestCase): diff --git a/Lib/test/test_capi/test_abstract.py b/Lib/test/test_capi/test_abstract.py new file mode 100644 index 00000000000000..97ed939928c360 --- /dev/null +++ b/Lib/test/test_capi/test_abstract.py @@ -0,0 +1,1005 @@ +import unittest +from collections import OrderedDict +from test import support +from test.support import import_helper + +_testcapi = import_helper.import_module('_testcapi') +from _testcapi import PY_SSIZE_T_MIN, PY_SSIZE_T_MAX + +NULL = None + +class StrSubclass(str): + pass + +class BytesSubclass(bytes): + pass + +class WithStr: + def __init__(self, value): + self.value = value + def __str__(self): + return self.value + +class WithRepr: + def __init__(self, value): + self.value = value + def __repr__(self): + return self.value + +class WithBytes: + def __init__(self, value): + self.value = value + def __bytes__(self): + return self.value + +class TestObject: + @property + def evil(self): + raise RuntimeError('do not get evil') + @evil.setter + def evil(self, value): + raise RuntimeError('do not set evil') + @evil.deleter + def evil(self): + raise RuntimeError('do not del evil') + +class ProxyGetItem: + def __init__(self, obj): + self.obj = obj + def __getitem__(self, key): + return self.obj[key] + +class ProxySetItem: + def __init__(self, obj): + self.obj = obj + def __setitem__(self, key, value): + self.obj[key] = value + +class ProxyDelItem: + def __init__(self, obj): + self.obj = obj + def __delitem__(self, key): + del self.obj[key] + +def gen(): + yield 'a' + yield 'b' + yield 'c' + + +class CAPITest(unittest.TestCase): + def assertTypedEqual(self, actual, expected): + self.assertIs(type(actual), type(expected)) + self.assertEqual(actual, expected) + + def test_object_str(self): + # Test PyObject_Str() + object_str = _testcapi.object_str + self.assertTypedEqual(object_str(''), '') + self.assertTypedEqual(object_str('abc'), 'abc') + self.assertTypedEqual(object_str('\U0001f40d'), '\U0001f40d') + self.assertTypedEqual(object_str(StrSubclass('abc')), 'abc') + self.assertTypedEqual(object_str(WithStr('abc')), 'abc') + self.assertTypedEqual(object_str(WithStr(StrSubclass('abc'))), StrSubclass('abc')) + self.assertTypedEqual(object_str(WithRepr('')), '') + self.assertTypedEqual(object_str(WithRepr(StrSubclass(''))), StrSubclass('')) + self.assertTypedEqual(object_str(NULL), '') + + def test_object_repr(self): + # Test PyObject_Repr() + object_repr = _testcapi.object_repr + self.assertTypedEqual(object_repr(''), "''") + self.assertTypedEqual(object_repr('abc'), "'abc'") + self.assertTypedEqual(object_repr('\U0001f40d'), "'\U0001f40d'") + self.assertTypedEqual(object_repr(StrSubclass('abc')), "'abc'") + self.assertTypedEqual(object_repr(WithRepr('')), '') + self.assertTypedEqual(object_repr(WithRepr(StrSubclass(''))), StrSubclass('')) + self.assertTypedEqual(object_repr(WithRepr('<\U0001f40d>')), '<\U0001f40d>') + self.assertTypedEqual(object_repr(WithRepr(StrSubclass('<\U0001f40d>'))), StrSubclass('<\U0001f40d>')) + self.assertTypedEqual(object_repr(NULL), '') + + def test_object_ascii(self): + # Test PyObject_ASCII() + object_ascii = _testcapi.object_ascii + self.assertTypedEqual(object_ascii(''), "''") + self.assertTypedEqual(object_ascii('abc'), "'abc'") + self.assertTypedEqual(object_ascii('\U0001f40d'), r"'\U0001f40d'") + self.assertTypedEqual(object_ascii(StrSubclass('abc')), "'abc'") + self.assertTypedEqual(object_ascii(WithRepr('')), '') + self.assertTypedEqual(object_ascii(WithRepr(StrSubclass(''))), StrSubclass('')) + self.assertTypedEqual(object_ascii(WithRepr('<\U0001f40d>')), r'<\U0001f40d>') + self.assertTypedEqual(object_ascii(WithRepr(StrSubclass('<\U0001f40d>'))), r'<\U0001f40d>') + self.assertTypedEqual(object_ascii(NULL), '') + + def test_object_bytes(self): + # Test PyObject_Bytes() + object_bytes = _testcapi.object_bytes + self.assertTypedEqual(object_bytes(b''), b'') + self.assertTypedEqual(object_bytes(b'abc'), b'abc') + self.assertTypedEqual(object_bytes(BytesSubclass(b'abc')), b'abc') + self.assertTypedEqual(object_bytes(WithBytes(b'abc')), b'abc') + self.assertTypedEqual(object_bytes(WithBytes(BytesSubclass(b'abc'))), BytesSubclass(b'abc')) + self.assertTypedEqual(object_bytes(bytearray(b'abc')), b'abc') + self.assertTypedEqual(object_bytes(memoryview(b'abc')), b'abc') + self.assertTypedEqual(object_bytes([97, 98, 99]), b'abc') + self.assertTypedEqual(object_bytes((97, 98, 99)), b'abc') + self.assertTypedEqual(object_bytes(iter([97, 98, 99])), b'abc') + self.assertRaises(TypeError, object_bytes, WithBytes(bytearray(b'abc'))) + self.assertRaises(TypeError, object_bytes, WithBytes([97, 98, 99])) + self.assertRaises(TypeError, object_bytes, 3) + self.assertRaises(TypeError, object_bytes, 'abc') + self.assertRaises(TypeError, object_bytes, object()) + self.assertTypedEqual(object_bytes(NULL), b'') + + def test_object_getattr(self): + xgetattr = _testcapi.object_getattr + obj = TestObject() + obj.a = 11 + setattr(obj, '\U0001f40d', 22) + self.assertEqual(xgetattr(obj, 'a'), 11) + self.assertRaises(AttributeError, xgetattr, obj, 'b') + self.assertEqual(xgetattr(obj, '\U0001f40d'), 22) + + self.assertRaises(RuntimeError, xgetattr, obj, 'evil') + self.assertRaises(TypeError, xgetattr, obj, 1) + # CRASHES xgetattr(obj, NULL) + # CRASHES xgetattr(NULL, 'a') + + def test_object_getattrstring(self): + getattrstring = _testcapi.object_getattrstring + obj = TestObject() + obj.a = 11 + setattr(obj, '\U0001f40d', 22) + self.assertEqual(getattrstring(obj, b'a'), 11) + self.assertRaises(AttributeError, getattrstring, obj, b'b') + self.assertEqual(getattrstring(obj, '\U0001f40d'.encode()), 22) + + self.assertRaises(RuntimeError, getattrstring, obj, b'evil') + self.assertRaises(UnicodeDecodeError, getattrstring, obj, b'\xff') + # CRASHES getattrstring(obj, NULL) + # CRASHES getattrstring(NULL, b'a') + + def test_object_getoptionalattr(self): + getoptionalattr = _testcapi.object_getoptionalattr + obj = TestObject() + obj.a = 11 + setattr(obj, '\U0001f40d', 22) + self.assertEqual(getoptionalattr(obj, 'a'), 11) + self.assertIs(getoptionalattr(obj, 'b'), AttributeError) + self.assertEqual(getoptionalattr(obj, '\U0001f40d'), 22) + + self.assertRaises(RuntimeError, getoptionalattr, obj, 'evil') + self.assertRaises(TypeError, getoptionalattr, obj, 1) + # CRASHES getoptionalattr(obj, NULL) + # CRASHES getoptionalattr(NULL, 'a') + + def test_object_getoptionalattrstring(self): + getoptionalattrstring = _testcapi.object_getoptionalattrstring + obj = TestObject() + obj.a = 11 + setattr(obj, '\U0001f40d', 22) + self.assertEqual(getoptionalattrstring(obj, b'a'), 11) + self.assertIs(getoptionalattrstring(obj, b'b'), AttributeError) + self.assertEqual(getoptionalattrstring(obj, '\U0001f40d'.encode()), 22) + + self.assertRaises(RuntimeError, getoptionalattrstring, obj, b'evil') + self.assertRaises(UnicodeDecodeError, getoptionalattrstring, obj, b'\xff') + # CRASHES getoptionalattrstring(obj, NULL) + # CRASHES getoptionalattrstring(NULL, b'a') + + def test_object_hasattr(self): + xhasattr = _testcapi.object_hasattr + obj = TestObject() + obj.a = 1 + setattr(obj, '\U0001f40d', 2) + self.assertTrue(xhasattr(obj, 'a')) + self.assertFalse(xhasattr(obj, 'b')) + self.assertTrue(xhasattr(obj, '\U0001f40d')) + + with support.catch_unraisable_exception() as cm: + self.assertFalse(xhasattr(obj, 'evil')) + self.assertEqual(cm.unraisable.exc_type, RuntimeError) + self.assertEqual(str(cm.unraisable.exc_value), + 'do not get evil') + + with support.catch_unraisable_exception() as cm: + self.assertFalse(xhasattr(obj, 1)) + self.assertEqual(cm.unraisable.exc_type, TypeError) + self.assertEqual(str(cm.unraisable.exc_value), + "attribute name must be string, not 'int'") + + # CRASHES xhasattr(obj, NULL) + # CRASHES xhasattr(NULL, 'a') + + def test_object_hasattrstring(self): + hasattrstring = _testcapi.object_hasattrstring + obj = TestObject() + obj.a = 1 + setattr(obj, '\U0001f40d', 2) + self.assertTrue(hasattrstring(obj, b'a')) + self.assertFalse(hasattrstring(obj, b'b')) + self.assertTrue(hasattrstring(obj, '\U0001f40d'.encode())) + + with support.catch_unraisable_exception() as cm: + self.assertFalse(hasattrstring(obj, b'evil')) + self.assertEqual(cm.unraisable.exc_type, RuntimeError) + self.assertEqual(str(cm.unraisable.exc_value), + 'do not get evil') + + with support.catch_unraisable_exception() as cm: + self.assertFalse(hasattrstring(obj, b'\xff')) + self.assertEqual(cm.unraisable.exc_type, UnicodeDecodeError) + self.assertRegex(str(cm.unraisable.exc_value), + "'utf-8' codec can't decode") + + # CRASHES hasattrstring(obj, NULL) + # CRASHES hasattrstring(NULL, b'a') + + def test_object_hasattrwitherror(self): + xhasattr = _testcapi.object_hasattrwitherror + obj = TestObject() + obj.a = 1 + setattr(obj, '\U0001f40d', 2) + self.assertTrue(xhasattr(obj, 'a')) + self.assertFalse(xhasattr(obj, 'b')) + self.assertTrue(xhasattr(obj, '\U0001f40d')) + + self.assertRaises(RuntimeError, xhasattr, obj, 'evil') + self.assertRaises(TypeError, xhasattr, obj, 1) + # CRASHES xhasattr(obj, NULL) + # CRASHES xhasattr(NULL, 'a') + + def test_object_hasattrstringwitherror(self): + hasattrstring = _testcapi.object_hasattrstringwitherror + obj = TestObject() + obj.a = 1 + setattr(obj, '\U0001f40d', 2) + self.assertTrue(hasattrstring(obj, b'a')) + self.assertFalse(hasattrstring(obj, b'b')) + self.assertTrue(hasattrstring(obj, '\U0001f40d'.encode())) + + self.assertRaises(RuntimeError, hasattrstring, obj, b'evil') + self.assertRaises(UnicodeDecodeError, hasattrstring, obj, b'\xff') + # CRASHES hasattrstring(obj, NULL) + # CRASHES hasattrstring(NULL, b'a') + + def test_object_setattr(self): + xsetattr = _testcapi.object_setattr + obj = TestObject() + xsetattr(obj, 'a', 5) + self.assertEqual(obj.a, 5) + xsetattr(obj, '\U0001f40d', 8) + self.assertEqual(getattr(obj, '\U0001f40d'), 8) + + # PyObject_SetAttr(obj, attr_name, NULL) removes the attribute + xsetattr(obj, 'a', NULL) + self.assertFalse(hasattr(obj, 'a')) + self.assertRaises(AttributeError, xsetattr, obj, 'b', NULL) + self.assertRaises(RuntimeError, xsetattr, obj, 'evil', NULL) + + self.assertRaises(RuntimeError, xsetattr, obj, 'evil', 'good') + self.assertRaises(AttributeError, xsetattr, 42, 'a', 5) + self.assertRaises(TypeError, xsetattr, obj, 1, 5) + # CRASHES xsetattr(obj, NULL, 5) + # CRASHES xsetattr(NULL, 'a', 5) + + def test_object_setattrstring(self): + setattrstring = _testcapi.object_setattrstring + obj = TestObject() + setattrstring(obj, b'a', 5) + self.assertEqual(obj.a, 5) + setattrstring(obj, '\U0001f40d'.encode(), 8) + self.assertEqual(getattr(obj, '\U0001f40d'), 8) + + # PyObject_SetAttrString(obj, attr_name, NULL) removes the attribute + setattrstring(obj, b'a', NULL) + self.assertFalse(hasattr(obj, 'a')) + self.assertRaises(AttributeError, setattrstring, obj, b'b', NULL) + self.assertRaises(RuntimeError, setattrstring, obj, b'evil', NULL) + + self.assertRaises(RuntimeError, setattrstring, obj, b'evil', 'good') + self.assertRaises(AttributeError, setattrstring, 42, b'a', 5) + self.assertRaises(TypeError, setattrstring, obj, 1, 5) + self.assertRaises(UnicodeDecodeError, setattrstring, obj, b'\xff', 5) + # CRASHES setattrstring(obj, NULL, 5) + # CRASHES setattrstring(NULL, b'a', 5) + + def test_object_delattr(self): + xdelattr = _testcapi.object_delattr + obj = TestObject() + obj.a = 1 + setattr(obj, '\U0001f40d', 2) + xdelattr(obj, 'a') + self.assertFalse(hasattr(obj, 'a')) + self.assertRaises(AttributeError, xdelattr, obj, 'b') + xdelattr(obj, '\U0001f40d') + self.assertFalse(hasattr(obj, '\U0001f40d')) + + self.assertRaises(AttributeError, xdelattr, 42, 'numerator') + self.assertRaises(RuntimeError, xdelattr, obj, 'evil') + self.assertRaises(TypeError, xdelattr, obj, 1) + # CRASHES xdelattr(obj, NULL) + # CRASHES xdelattr(NULL, 'a') + + def test_object_delattrstring(self): + delattrstring = _testcapi.object_delattrstring + obj = TestObject() + obj.a = 1 + setattr(obj, '\U0001f40d', 2) + delattrstring(obj, b'a') + self.assertFalse(hasattr(obj, 'a')) + self.assertRaises(AttributeError, delattrstring, obj, b'b') + delattrstring(obj, '\U0001f40d'.encode()) + self.assertFalse(hasattr(obj, '\U0001f40d')) + + self.assertRaises(AttributeError, delattrstring, 42, b'numerator') + self.assertRaises(RuntimeError, delattrstring, obj, b'evil') + self.assertRaises(UnicodeDecodeError, delattrstring, obj, b'\xff') + # CRASHES delattrstring(obj, NULL) + # CRASHES delattrstring(NULL, b'a') + + + def test_mapping_check(self): + check = _testcapi.mapping_check + self.assertTrue(check({1: 2})) + self.assertTrue(check([1, 2])) + self.assertTrue(check((1, 2))) + self.assertTrue(check('abc')) + self.assertTrue(check(b'abc')) + self.assertFalse(check(42)) + self.assertFalse(check(object())) + self.assertFalse(check(NULL)) + + def test_mapping_size(self): + for size in _testcapi.mapping_size, _testcapi.mapping_length: + self.assertEqual(size({1: 2}), 1) + self.assertEqual(size([1, 2]), 2) + self.assertEqual(size((1, 2)), 2) + self.assertEqual(size('abc'), 3) + self.assertEqual(size(b'abc'), 3) + + self.assertRaises(TypeError, size, 42) + self.assertRaises(TypeError, size, object()) + self.assertRaises(SystemError, size, NULL) + + def test_object_getitem(self): + getitem = _testcapi.object_getitem + dct = {'a': 1, '\U0001f40d': 2} + self.assertEqual(getitem(dct, 'a'), 1) + self.assertRaises(KeyError, getitem, dct, 'b') + self.assertEqual(getitem(dct, '\U0001f40d'), 2) + + dct2 = ProxyGetItem(dct) + self.assertEqual(getitem(dct2, 'a'), 1) + self.assertRaises(KeyError, getitem, dct2, 'b') + + self.assertEqual(getitem(['a', 'b', 'c'], 1), 'b') + + self.assertRaises(TypeError, getitem, 42, 'a') + self.assertRaises(TypeError, getitem, {}, []) # unhashable + self.assertRaises(SystemError, getitem, {}, NULL) + self.assertRaises(IndexError, getitem, [], 1) + self.assertRaises(TypeError, getitem, [], 'a') + self.assertRaises(SystemError, getitem, NULL, 'a') + + def test_mapping_getitemstring(self): + getitemstring = _testcapi.mapping_getitemstring + dct = {'a': 1, '\U0001f40d': 2} + self.assertEqual(getitemstring(dct, b'a'), 1) + self.assertRaises(KeyError, getitemstring, dct, b'b') + self.assertEqual(getitemstring(dct, '\U0001f40d'.encode()), 2) + + dct2 = ProxyGetItem(dct) + self.assertEqual(getitemstring(dct2, b'a'), 1) + self.assertRaises(KeyError, getitemstring, dct2, b'b') + + self.assertRaises(TypeError, getitemstring, 42, b'a') + self.assertRaises(UnicodeDecodeError, getitemstring, {}, b'\xff') + self.assertRaises(SystemError, getitemstring, {}, NULL) + self.assertRaises(TypeError, getitemstring, [], b'a') + self.assertRaises(SystemError, getitemstring, NULL, b'a') + + def test_mapping_getoptionalitem(self): + getitem = _testcapi.mapping_getoptionalitem + dct = {'a': 1, '\U0001f40d': 2} + self.assertEqual(getitem(dct, 'a'), 1) + self.assertEqual(getitem(dct, 'b'), KeyError) + self.assertEqual(getitem(dct, '\U0001f40d'), 2) + + dct2 = ProxyGetItem(dct) + self.assertEqual(getitem(dct2, 'a'), 1) + self.assertEqual(getitem(dct2, 'b'), KeyError) + + self.assertEqual(getitem(['a', 'b', 'c'], 1), 'b') + + self.assertRaises(TypeError, getitem, 42, 'a') + self.assertRaises(TypeError, getitem, {}, []) # unhashable + self.assertRaises(IndexError, getitem, [], 1) + self.assertRaises(TypeError, getitem, [], 'a') + # CRASHES getitem({}, NULL) + # CRASHES getitem(NULL, 'a') + + def test_mapping_getoptionalitemstring(self): + getitemstring = _testcapi.mapping_getoptionalitemstring + dct = {'a': 1, '\U0001f40d': 2} + self.assertEqual(getitemstring(dct, b'a'), 1) + self.assertEqual(getitemstring(dct, b'b'), KeyError) + self.assertEqual(getitemstring(dct, '\U0001f40d'.encode()), 2) + + dct2 = ProxyGetItem(dct) + self.assertEqual(getitemstring(dct2, b'a'), 1) + self.assertEqual(getitemstring(dct2, b'b'), KeyError) + + self.assertRaises(TypeError, getitemstring, 42, b'a') + self.assertRaises(UnicodeDecodeError, getitemstring, {}, b'\xff') + self.assertRaises(SystemError, getitemstring, {}, NULL) + self.assertRaises(TypeError, getitemstring, [], b'a') + # CRASHES getitemstring(NULL, b'a') + + def test_mapping_haskey(self): + haskey = _testcapi.mapping_haskey + dct = {'a': 1, '\U0001f40d': 2} + self.assertTrue(haskey(dct, 'a')) + self.assertFalse(haskey(dct, 'b')) + self.assertTrue(haskey(dct, '\U0001f40d')) + + dct2 = ProxyGetItem(dct) + self.assertTrue(haskey(dct2, 'a')) + self.assertFalse(haskey(dct2, 'b')) + + self.assertTrue(haskey(['a', 'b', 'c'], 1)) + + with support.catch_unraisable_exception() as cm: + self.assertFalse(haskey(42, 'a')) + self.assertEqual(cm.unraisable.exc_type, TypeError) + self.assertEqual(str(cm.unraisable.exc_value), + "'int' object is not subscriptable") + + with support.catch_unraisable_exception() as cm: + self.assertFalse(haskey({}, [])) + self.assertEqual(cm.unraisable.exc_type, TypeError) + self.assertEqual(str(cm.unraisable.exc_value), + "unhashable type: 'list'") + + with support.catch_unraisable_exception() as cm: + self.assertFalse(haskey([], 1)) + self.assertEqual(cm.unraisable.exc_type, IndexError) + self.assertEqual(str(cm.unraisable.exc_value), + 'list index out of range') + + with support.catch_unraisable_exception() as cm: + self.assertFalse(haskey([], 'a')) + self.assertEqual(cm.unraisable.exc_type, TypeError) + self.assertEqual(str(cm.unraisable.exc_value), + 'list indices must be integers or slices, not str') + + with support.catch_unraisable_exception() as cm: + self.assertFalse(haskey({}, NULL)) + self.assertEqual(cm.unraisable.exc_type, SystemError) + self.assertEqual(str(cm.unraisable.exc_value), + 'null argument to internal routine') + + with support.catch_unraisable_exception() as cm: + self.assertFalse(haskey(NULL, 'a')) + self.assertEqual(cm.unraisable.exc_type, SystemError) + self.assertEqual(str(cm.unraisable.exc_value), + 'null argument to internal routine') + + def test_mapping_haskeystring(self): + haskeystring = _testcapi.mapping_haskeystring + dct = {'a': 1, '\U0001f40d': 2} + self.assertTrue(haskeystring(dct, b'a')) + self.assertFalse(haskeystring(dct, b'b')) + self.assertTrue(haskeystring(dct, '\U0001f40d'.encode())) + + dct2 = ProxyGetItem(dct) + self.assertTrue(haskeystring(dct2, b'a')) + self.assertFalse(haskeystring(dct2, b'b')) + + with support.catch_unraisable_exception() as cm: + self.assertFalse(haskeystring(42, b'a')) + self.assertEqual(cm.unraisable.exc_type, TypeError) + self.assertEqual(str(cm.unraisable.exc_value), + "'int' object is not subscriptable") + + with support.catch_unraisable_exception() as cm: + self.assertFalse(haskeystring({}, b'\xff')) + self.assertEqual(cm.unraisable.exc_type, UnicodeDecodeError) + self.assertRegex(str(cm.unraisable.exc_value), + "'utf-8' codec can't decode") + + with support.catch_unraisable_exception() as cm: + self.assertFalse(haskeystring({}, NULL)) + self.assertEqual(cm.unraisable.exc_type, SystemError) + self.assertEqual(str(cm.unraisable.exc_value), + "null argument to internal routine") + + with support.catch_unraisable_exception() as cm: + self.assertFalse(haskeystring([], b'a')) + self.assertEqual(cm.unraisable.exc_type, TypeError) + self.assertEqual(str(cm.unraisable.exc_value), + 'list indices must be integers or slices, not str') + + with support.catch_unraisable_exception() as cm: + self.assertFalse(haskeystring(NULL, b'a')) + self.assertEqual(cm.unraisable.exc_type, SystemError) + self.assertEqual(str(cm.unraisable.exc_value), + "null argument to internal routine") + + def test_mapping_haskeywitherror(self): + haskey = _testcapi.mapping_haskeywitherror + dct = {'a': 1, '\U0001f40d': 2} + self.assertTrue(haskey(dct, 'a')) + self.assertFalse(haskey(dct, 'b')) + self.assertTrue(haskey(dct, '\U0001f40d')) + + dct2 = ProxyGetItem(dct) + self.assertTrue(haskey(dct2, 'a')) + self.assertFalse(haskey(dct2, 'b')) + + self.assertTrue(haskey(['a', 'b', 'c'], 1)) + + self.assertRaises(TypeError, haskey, 42, 'a') + self.assertRaises(TypeError, haskey, {}, []) # unhashable + self.assertRaises(IndexError, haskey, [], 1) + self.assertRaises(TypeError, haskey, [], 'a') + + # CRASHES haskey({}, NULL)) + # CRASHES haskey(NULL, 'a')) + + def test_mapping_haskeystringwitherror(self): + haskeystring = _testcapi.mapping_haskeystringwitherror + dct = {'a': 1, '\U0001f40d': 2} + self.assertTrue(haskeystring(dct, b'a')) + self.assertFalse(haskeystring(dct, b'b')) + self.assertTrue(haskeystring(dct, '\U0001f40d'.encode())) + + dct2 = ProxyGetItem(dct) + self.assertTrue(haskeystring(dct2, b'a')) + self.assertFalse(haskeystring(dct2, b'b')) + + self.assertRaises(TypeError, haskeystring, 42, b'a') + self.assertRaises(UnicodeDecodeError, haskeystring, {}, b'\xff') + self.assertRaises(SystemError, haskeystring, {}, NULL) + self.assertRaises(TypeError, haskeystring, [], b'a') + # CRASHES haskeystring(NULL, b'a') + + def test_object_setitem(self): + setitem = _testcapi.object_setitem + dct = {} + setitem(dct, 'a', 5) + self.assertEqual(dct, {'a': 5}) + setitem(dct, '\U0001f40d', 8) + self.assertEqual(dct, {'a': 5, '\U0001f40d': 8}) + + dct = {} + dct2 = ProxySetItem(dct) + setitem(dct2, 'a', 5) + self.assertEqual(dct, {'a': 5}) + + lst = ['a', 'b', 'c'] + setitem(lst, 1, 'x') + self.assertEqual(lst, ['a', 'x', 'c']) + + self.assertRaises(TypeError, setitem, 42, 'a', 5) + self.assertRaises(TypeError, setitem, {}, [], 5) # unhashable + self.assertRaises(SystemError, setitem, {}, NULL, 5) + self.assertRaises(SystemError, setitem, {}, 'a', NULL) + self.assertRaises(IndexError, setitem, [], 1, 5) + self.assertRaises(TypeError, setitem, [], 'a', 5) + self.assertRaises(TypeError, setitem, (), 1, 5) + self.assertRaises(SystemError, setitem, NULL, 'a', 5) + + def test_mapping_setitemstring(self): + setitemstring = _testcapi.mapping_setitemstring + dct = {} + setitemstring(dct, b'a', 5) + self.assertEqual(dct, {'a': 5}) + setitemstring(dct, '\U0001f40d'.encode(), 8) + self.assertEqual(dct, {'a': 5, '\U0001f40d': 8}) + + dct = {} + dct2 = ProxySetItem(dct) + setitemstring(dct2, b'a', 5) + self.assertEqual(dct, {'a': 5}) + + self.assertRaises(TypeError, setitemstring, 42, b'a', 5) + self.assertRaises(UnicodeDecodeError, setitemstring, {}, b'\xff', 5) + self.assertRaises(SystemError, setitemstring, {}, NULL, 5) + self.assertRaises(SystemError, setitemstring, {}, b'a', NULL) + self.assertRaises(TypeError, setitemstring, [], b'a', 5) + self.assertRaises(SystemError, setitemstring, NULL, b'a', 5) + + def test_object_delitem(self): + for delitem in _testcapi.object_delitem, _testcapi.mapping_delitem: + dct = {'a': 1, 'c': 2, '\U0001f40d': 3} + delitem(dct, 'a') + self.assertEqual(dct, {'c': 2, '\U0001f40d': 3}) + self.assertRaises(KeyError, delitem, dct, 'b') + delitem(dct, '\U0001f40d') + self.assertEqual(dct, {'c': 2}) + + dct = {'a': 1, 'c': 2} + dct2 = ProxyDelItem(dct) + delitem(dct2, 'a') + self.assertEqual(dct, {'c': 2}) + self.assertRaises(KeyError, delitem, dct2, 'b') + + lst = ['a', 'b', 'c'] + delitem(lst, 1) + self.assertEqual(lst, ['a', 'c']) + + self.assertRaises(TypeError, delitem, 42, 'a') + self.assertRaises(TypeError, delitem, {}, []) # unhashable + self.assertRaises(SystemError, delitem, {}, NULL) + self.assertRaises(IndexError, delitem, [], 1) + self.assertRaises(TypeError, delitem, [], 'a') + self.assertRaises(SystemError, delitem, NULL, 'a') + + def test_mapping_delitemstring(self): + delitemstring = _testcapi.mapping_delitemstring + dct = {'a': 1, 'c': 2, '\U0001f40d': 3} + delitemstring(dct, b'a') + self.assertEqual(dct, {'c': 2, '\U0001f40d': 3}) + self.assertRaises(KeyError, delitemstring, dct, b'b') + delitemstring(dct, '\U0001f40d'.encode()) + self.assertEqual(dct, {'c': 2}) + + dct = {'a': 1, 'c': 2} + dct2 = ProxyDelItem(dct) + delitemstring(dct2, b'a') + self.assertEqual(dct, {'c': 2}) + self.assertRaises(KeyError, delitemstring, dct2, b'b') + + self.assertRaises(TypeError, delitemstring, 42, b'a') + self.assertRaises(UnicodeDecodeError, delitemstring, {}, b'\xff') + self.assertRaises(SystemError, delitemstring, {}, NULL) + self.assertRaises(TypeError, delitemstring, [], b'a') + self.assertRaises(SystemError, delitemstring, NULL, b'a') + + def test_mapping_keys_valuesitems(self): + class Mapping1(dict): + def keys(self): + return list(super().keys()) + def values(self): + return list(super().values()) + def items(self): + return list(super().items()) + class Mapping2(dict): + def keys(self): + return tuple(super().keys()) + def values(self): + return tuple(super().values()) + def items(self): + return tuple(super().items()) + dict_obj = {'foo': 1, 'bar': 2, 'spam': 3} + + for mapping in [{}, OrderedDict(), Mapping1(), Mapping2(), + dict_obj, OrderedDict(dict_obj), + Mapping1(dict_obj), Mapping2(dict_obj)]: + self.assertListEqual(_testcapi.mapping_keys(mapping), + list(mapping.keys())) + self.assertListEqual(_testcapi.mapping_values(mapping), + list(mapping.values())) + self.assertListEqual(_testcapi.mapping_items(mapping), + list(mapping.items())) + + def test_mapping_keys_valuesitems_bad_arg(self): + self.assertRaises(AttributeError, _testcapi.mapping_keys, object()) + self.assertRaises(AttributeError, _testcapi.mapping_values, object()) + self.assertRaises(AttributeError, _testcapi.mapping_items, object()) + self.assertRaises(AttributeError, _testcapi.mapping_keys, []) + self.assertRaises(AttributeError, _testcapi.mapping_values, []) + self.assertRaises(AttributeError, _testcapi.mapping_items, []) + self.assertRaises(SystemError, _testcapi.mapping_keys, NULL) + self.assertRaises(SystemError, _testcapi.mapping_values, NULL) + self.assertRaises(SystemError, _testcapi.mapping_items, NULL) + + class BadMapping: + def keys(self): + return None + def values(self): + return None + def items(self): + return None + bad_mapping = BadMapping() + self.assertRaises(TypeError, _testcapi.mapping_keys, bad_mapping) + self.assertRaises(TypeError, _testcapi.mapping_values, bad_mapping) + self.assertRaises(TypeError, _testcapi.mapping_items, bad_mapping) + + def test_sequence_check(self): + check = _testcapi.sequence_check + self.assertFalse(check({1: 2})) + self.assertTrue(check([1, 2])) + self.assertTrue(check((1, 2))) + self.assertTrue(check('abc')) + self.assertTrue(check(b'abc')) + self.assertFalse(check(42)) + self.assertFalse(check(object())) + # CRASHES check(NULL) + + def test_sequence_size(self): + for size in _testcapi.sequence_size, _testcapi.sequence_length: + self.assertEqual(size([1, 2]), 2) + self.assertEqual(size((1, 2)), 2) + self.assertEqual(size('abc'), 3) + self.assertEqual(size(b'abc'), 3) + + self.assertRaises(TypeError, size, {}) + self.assertRaises(TypeError, size, 42) + self.assertRaises(TypeError, size, object()) + self.assertRaises(SystemError, size, NULL) + + def test_sequence_getitem(self): + getitem = _testcapi.sequence_getitem + lst = ['a', 'b', 'c'] + self.assertEqual(getitem(lst, 1), 'b') + self.assertEqual(getitem(lst, -1), 'c') + self.assertRaises(IndexError, getitem, lst, 3) + self.assertRaises(IndexError, getitem, lst, PY_SSIZE_T_MAX) + self.assertRaises(IndexError, getitem, lst, PY_SSIZE_T_MIN) + + self.assertRaises(TypeError, getitem, 42, 1) + self.assertRaises(TypeError, getitem, {}, 1) + self.assertRaises(SystemError, getitem, NULL, 1) + + def test_sequence_concat(self): + concat = _testcapi.sequence_concat + self.assertEqual(concat(['a', 'b'], [1, 2]), ['a', 'b', 1, 2]) + self.assertEqual(concat(('a', 'b'), (1, 2)), ('a', 'b', 1, 2)) + + self.assertRaises(TypeError, concat, [], ()) + self.assertRaises(TypeError, concat, (), []) + self.assertRaises(TypeError, concat, [], 42) + self.assertRaises(TypeError, concat, 42, []) + self.assertRaises(TypeError, concat, 42, 43) + self.assertRaises(SystemError, concat, [], NULL) + self.assertRaises(SystemError, concat, NULL, []) + + def test_sequence_repeat(self): + repeat = _testcapi.sequence_repeat + self.assertEqual(repeat(['a', 'b'], 2), ['a', 'b', 'a', 'b']) + self.assertEqual(repeat(('a', 'b'), 2), ('a', 'b', 'a', 'b')) + self.assertEqual(repeat(['a', 'b'], 0), []) + self.assertEqual(repeat(['a', 'b'], -1), []) + self.assertEqual(repeat(['a', 'b'], PY_SSIZE_T_MIN), []) + self.assertEqual(repeat([], PY_SSIZE_T_MAX), []) + self.assertRaises(MemoryError, repeat, ['a', 'b'], PY_SSIZE_T_MAX) + + self.assertRaises(TypeError, repeat, set(), 2) + self.assertRaises(TypeError, repeat, 42, 2) + self.assertRaises(SystemError, repeat, NULL, 2) + + def test_sequence_inplaceconcat(self): + inplaceconcat = _testcapi.sequence_inplaceconcat + lst = ['a', 'b'] + res = inplaceconcat(lst, [1, 2]) + self.assertEqual(res, ['a', 'b', 1, 2]) + self.assertIs(res, lst) + lst = ['a', 'b'] + res = inplaceconcat(lst, (1, 2)) + self.assertEqual(res, ['a', 'b', 1, 2]) + self.assertIs(res, lst) + self.assertEqual(inplaceconcat(('a', 'b'), (1, 2)), ('a', 'b', 1, 2)) + + self.assertRaises(TypeError, inplaceconcat, (), []) + self.assertRaises(TypeError, inplaceconcat, [], 42) + self.assertRaises(TypeError, inplaceconcat, 42, []) + self.assertRaises(TypeError, inplaceconcat, 42, 43) + self.assertRaises(SystemError, inplaceconcat, [], NULL) + self.assertRaises(SystemError, inplaceconcat, NULL, []) + + def test_sequence_inplacerepeat(self): + inplacerepeat = _testcapi.sequence_inplacerepeat + lst = ['a', 'b'] + res = inplacerepeat(lst, 2) + self.assertEqual(res, ['a', 'b', 'a', 'b']) + self.assertIs(res, lst) + self.assertEqual(inplacerepeat(('a', 'b'), 2), ('a', 'b', 'a', 'b')) + self.assertEqual(inplacerepeat(['a', 'b'], 0), []) + self.assertEqual(inplacerepeat(['a', 'b'], -1), []) + self.assertEqual(inplacerepeat(['a', 'b'], PY_SSIZE_T_MIN), []) + self.assertEqual(inplacerepeat([], PY_SSIZE_T_MAX), []) + self.assertRaises(MemoryError, inplacerepeat, ['a', 'b'], PY_SSIZE_T_MAX) + + self.assertRaises(TypeError, inplacerepeat, set(), 2) + self.assertRaises(TypeError, inplacerepeat, 42, 2) + self.assertRaises(SystemError, inplacerepeat, NULL, 2) + + def test_sequence_setitem(self): + setitem = _testcapi.sequence_setitem + lst = ['a', 'b', 'c'] + setitem(lst, 1, 'x') + self.assertEqual(lst, ['a', 'x', 'c']) + setitem(lst, -1, 'y') + self.assertEqual(lst, ['a', 'x', 'y']) + + setitem(lst, 0, NULL) + self.assertEqual(lst, ['x', 'y']) + self.assertRaises(IndexError, setitem, lst, 3, 'x') + self.assertRaises(IndexError, setitem, lst, PY_SSIZE_T_MAX, 'x') + self.assertRaises(IndexError, setitem, lst, PY_SSIZE_T_MIN, 'x') + + self.assertRaises(TypeError, setitem, 42, 1, 'x') + self.assertRaises(TypeError, setitem, {}, 1, 'x') + self.assertRaises(SystemError, setitem, NULL, 1, 'x') + + def test_sequence_delitem(self): + delitem = _testcapi.sequence_delitem + lst = ['a', 'b', 'c'] + delitem(lst, 1) + self.assertEqual(lst, ['a', 'c']) + delitem(lst, -1) + self.assertEqual(lst, ['a']) + self.assertRaises(IndexError, delitem, lst, 3) + self.assertRaises(IndexError, delitem, lst, PY_SSIZE_T_MAX) + self.assertRaises(IndexError, delitem, lst, PY_SSIZE_T_MIN) + + self.assertRaises(TypeError, delitem, 42, 1) + self.assertRaises(TypeError, delitem, {}, 1) + self.assertRaises(SystemError, delitem, NULL, 1) + + def test_sequence_setslice(self): + setslice = _testcapi.sequence_setslice + + # Correct case: + for start in [*range(-6, 7), PY_SSIZE_T_MIN, PY_SSIZE_T_MAX]: + for stop in [*range(-6, 7), PY_SSIZE_T_MIN, PY_SSIZE_T_MAX]: + data = [1, 2, 3, 4, 5] + data_copy = [1, 2, 3, 4, 5] + setslice(data, start, stop, [8, 9]) + data_copy[start:stop] = [8, 9] + self.assertEqual(data, data_copy) + + data = [1, 2, 3, 4, 5] + data_copy = [1, 2, 3, 4, 5] + setslice(data, start, stop, NULL) + del data_copy[start:stop] + self.assertEqual(data, data_copy) + + # Custom class: + class Custom: + def __setitem__(self, index, value): + self.index = index + self.value = value + + c = Custom() + setslice(c, 0, 5, 'abc') + self.assertEqual(c.index, slice(0, 5)) + self.assertEqual(c.value, 'abc') + + # Immutable sequences must raise: + bad_seq1 = (1, 2, 3, 4) + self.assertRaises(TypeError, setslice, bad_seq1, 1, 3, (8, 9)) + self.assertEqual(bad_seq1, (1, 2, 3, 4)) + + bad_seq2 = 'abcd' + self.assertRaises(TypeError, setslice, bad_seq2, 1, 3, 'xy') + self.assertEqual(bad_seq2, 'abcd') + + # Not a sequence: + self.assertRaises(TypeError, setslice, object(), 1, 3, 'xy') + self.assertRaises(SystemError, setslice, NULL, 1, 3, 'xy') + + def test_sequence_delslice(self): + delslice = _testcapi.sequence_delslice + + # Correct case: + for start in [*range(-6, 7), PY_SSIZE_T_MIN, PY_SSIZE_T_MAX]: + for stop in [*range(-6, 7), PY_SSIZE_T_MIN, PY_SSIZE_T_MAX]: + data = [1, 2, 3, 4, 5] + data_copy = [1, 2, 3, 4, 5] + delslice(data, start, stop) + del data_copy[start:stop] + self.assertEqual(data, data_copy) + + # Custom class: + class Custom: + def __delitem__(self, index): + self.index = index + + c = Custom() + delslice(c, 0, 5) + self.assertEqual(c.index, slice(0, 5)) + + # Immutable sequences must raise: + bad_seq1 = (1, 2, 3, 4) + self.assertRaises(TypeError, delslice, bad_seq1, 1, 3) + self.assertEqual(bad_seq1, (1, 2, 3, 4)) + + bad_seq2 = 'abcd' + self.assertRaises(TypeError, delslice, bad_seq2, 1, 3) + self.assertEqual(bad_seq2, 'abcd') + + # Not a sequence: + self.assertRaises(TypeError, delslice, object(), 1, 3) + self.assertRaises(SystemError, delslice, NULL, 1, 3) + + mapping = {1: 'a', 2: 'b', 3: 'c'} + self.assertRaises(KeyError, delslice, mapping, 1, 3) + self.assertEqual(mapping, {1: 'a', 2: 'b', 3: 'c'}) + + def test_sequence_count(self): + count = _testcapi.sequence_count + + lst = ['a', 'b', 'a'] + self.assertEqual(count(lst, 'a'), 2) + self.assertEqual(count(lst, 'c'), 0) + self.assertEqual(count(iter(lst), 'a'), 2) + self.assertEqual(count(iter(lst), 'c'), 0) + self.assertEqual(count({'a': 2}, 'a'), 1) + + self.assertRaises(TypeError, count, 42, 'a') + self.assertRaises(SystemError, count, [], NULL) + self.assertRaises(SystemError, count, [1], NULL) + self.assertRaises(SystemError, count, NULL, 'a') + + def test_sequence_contains(self): + contains = _testcapi.sequence_contains + + lst = ['a', 'b', 'a'] + self.assertEqual(contains(lst, 'a'), 1) + self.assertEqual(contains(lst, 'c'), 0) + self.assertEqual(contains(iter(lst), 'a'), 1) + self.assertEqual(contains(iter(lst), 'c'), 0) + self.assertEqual(contains({'a': 2}, 'a'), 1) + + # XXX Only for empty sequences. Should be SystemError? + self.assertEqual(contains([], NULL), 0) + + self.assertRaises(TypeError, contains, 42, 'a') + self.assertRaises(SystemError, contains, [1], NULL) + # CRASHES contains({}, NULL) + # CRASHES contains(set(), NULL) + # CRASHES contains(NULL, 'a') + + def test_sequence_index(self): + index = _testcapi.sequence_index + + lst = ['a', 'b', 'a'] + self.assertEqual(index(lst, 'a'), 0) + self.assertEqual(index(lst, 'b'), 1) + self.assertRaises(ValueError, index, lst, 'c') + self.assertEqual(index(iter(lst), 'a'), 0) + self.assertEqual(index(iter(lst), 'b'), 1) + self.assertRaises(ValueError, index, iter(lst), 'c') + dct = {'a': 2, 'b': 3} + self.assertEqual(index(dct, 'a'), 0) + self.assertEqual(index(dct, 'b'), 1) + self.assertRaises(ValueError, index, dct, 'c') + + self.assertRaises(TypeError, index, 42, 'a') + self.assertRaises(SystemError, index, [], NULL) + self.assertRaises(SystemError, index, [1], NULL) + self.assertRaises(SystemError, index, NULL, 'a') + + def test_sequence_list(self): + xlist = _testcapi.sequence_list + self.assertEqual(xlist(['a', 'b', 'c']), ['a', 'b', 'c']) + self.assertEqual(xlist(('a', 'b', 'c')), ['a', 'b', 'c']) + self.assertEqual(xlist(iter(['a', 'b', 'c'])), ['a', 'b', 'c']) + self.assertEqual(xlist(gen()), ['a', 'b', 'c']) + + self.assertRaises(TypeError, xlist, 42) + self.assertRaises(SystemError, xlist, NULL) + + def test_sequence_tuple(self): + xtuple = _testcapi.sequence_tuple + self.assertEqual(xtuple(['a', 'b', 'c']), ('a', 'b', 'c')) + self.assertEqual(xtuple(('a', 'b', 'c')), ('a', 'b', 'c')) + self.assertEqual(xtuple(iter(['a', 'b', 'c'])), ('a', 'b', 'c')) + self.assertEqual(xtuple(gen()), ('a', 'b', 'c')) + + self.assertRaises(TypeError, xtuple, 42) + self.assertRaises(SystemError, xtuple, NULL) + + def test_number_check(self): + number_check = _testcapi.number_check + self.assertTrue(number_check(1 + 1j)) + self.assertTrue(number_check(1)) + self.assertTrue(number_check(0.5)) + self.assertFalse(number_check("1 + 1j")) + + +if __name__ == "__main__": + unittest.main() diff --git a/Lib/test/test_capi/test_bytearray.py b/Lib/test/test_capi/test_bytearray.py new file mode 100644 index 00000000000000..833122c4e319d8 --- /dev/null +++ b/Lib/test/test_capi/test_bytearray.py @@ -0,0 +1,164 @@ +import unittest +from test.support import import_helper + +_testcapi = import_helper.import_module('_testcapi') +from _testcapi import PY_SSIZE_T_MIN, PY_SSIZE_T_MAX + +NULL = None + +class ByteArraySubclass(bytearray): + pass + +class BytesLike: + def __init__(self, value): + self.value = value + def __bytes__(self): + return self.value + + +class CAPITest(unittest.TestCase): + def test_check(self): + # Test PyByteArray_Check() + check = _testcapi.bytearray_check + self.assertTrue(check(bytearray(b'abc'))) + self.assertFalse(check(b'abc')) + self.assertTrue(check(ByteArraySubclass(b'abc'))) + self.assertFalse(check(BytesLike(b'abc'))) + self.assertFalse(check(3)) + self.assertFalse(check([])) + self.assertFalse(check(object())) + + # CRASHES check(NULL) + + def test_checkexact(self): + # Test PyByteArray_CheckExact() + check = _testcapi.bytearray_checkexact + self.assertTrue(check(bytearray(b'abc'))) + self.assertFalse(check(b'abc')) + self.assertFalse(check(ByteArraySubclass(b'abc'))) + self.assertFalse(check(BytesLike(b'abc'))) + self.assertFalse(check(3)) + self.assertFalse(check([])) + self.assertFalse(check(object())) + + # CRASHES check(NULL) + + def test_fromstringandsize(self): + # Test PyByteArray_FromStringAndSize() + fromstringandsize = _testcapi.bytearray_fromstringandsize + + self.assertEqual(fromstringandsize(b'abc'), bytearray(b'abc')) + self.assertEqual(fromstringandsize(b'abc', 2), bytearray(b'ab')) + self.assertEqual(fromstringandsize(b'abc\0def'), bytearray(b'abc\0def')) + self.assertEqual(fromstringandsize(b'', 0), bytearray()) + self.assertEqual(fromstringandsize(NULL, 0), bytearray()) + self.assertEqual(len(fromstringandsize(NULL, 3)), 3) + self.assertRaises(MemoryError, fromstringandsize, NULL, PY_SSIZE_T_MAX) + + self.assertRaises(SystemError, fromstringandsize, b'abc', -1) + self.assertRaises(SystemError, fromstringandsize, b'abc', PY_SSIZE_T_MIN) + self.assertRaises(SystemError, fromstringandsize, NULL, -1) + self.assertRaises(SystemError, fromstringandsize, NULL, PY_SSIZE_T_MIN) + + def test_fromobject(self): + # Test PyByteArray_FromObject() + fromobject = _testcapi.bytearray_fromobject + + self.assertEqual(fromobject(b'abc'), bytearray(b'abc')) + self.assertEqual(fromobject(bytearray(b'abc')), bytearray(b'abc')) + self.assertEqual(fromobject(ByteArraySubclass(b'abc')), bytearray(b'abc')) + self.assertEqual(fromobject([97, 98, 99]), bytearray(b'abc')) + self.assertEqual(fromobject(3), bytearray(b'\0\0\0')) + self.assertRaises(TypeError, fromobject, BytesLike(b'abc')) + self.assertRaises(TypeError, fromobject, 'abc') + self.assertRaises(TypeError, fromobject, object()) + + # CRASHES fromobject(NULL) + + def test_size(self): + # Test PyByteArray_Size() + size = _testcapi.bytearray_size + + self.assertEqual(size(bytearray(b'abc')), 3) + self.assertEqual(size(ByteArraySubclass(b'abc')), 3) + + # CRASHES size(b'abc') + # CRASHES size(object()) + # CRASHES size(NULL) + + def test_asstring(self): + """Test PyByteArray_AsString()""" + asstring = _testcapi.bytearray_asstring + + self.assertEqual(asstring(bytearray(b'abc'), 4), b'abc\0') + self.assertEqual(asstring(ByteArraySubclass(b'abc'), 4), b'abc\0') + self.assertEqual(asstring(bytearray(b'abc\0def'), 8), b'abc\0def\0') + + # CRASHES asstring(b'abc', 0) + # CRASHES asstring(object()', 0) + # CRASHES asstring(NULL, 0) + + def test_concat(self): + """Test PyByteArray_Concat()""" + concat = _testcapi.bytearray_concat + + ba = bytearray(b'abc') + self.assertEqual(concat(ba, b'def'), bytearray(b'abcdef')) + self.assertEqual(ba, b'abc') + + self.assertEqual(concat(b'abc', b'def'), bytearray(b'abcdef')) + self.assertEqual(concat(b'a\0b', b'c\0d'), bytearray(b'a\0bc\0d')) + self.assertEqual(concat(bytearray(b'abc'), b'def'), bytearray(b'abcdef')) + self.assertEqual(concat(b'abc', bytearray(b'def')), bytearray(b'abcdef')) + self.assertEqual(concat(bytearray(b'abc'), b''), bytearray(b'abc')) + self.assertEqual(concat(b'', bytearray(b'def')), bytearray(b'def')) + self.assertEqual(concat(memoryview(b'xabcy')[1:4], b'def'), + bytearray(b'abcdef')) + self.assertEqual(concat(b'abc', memoryview(b'xdefy')[1:4]), + bytearray(b'abcdef')) + + self.assertRaises(TypeError, concat, memoryview(b'axbycz')[::2], b'def') + self.assertRaises(TypeError, concat, b'abc', memoryview(b'dxeyfz')[::2]) + self.assertRaises(TypeError, concat, b'abc', 'def') + self.assertRaises(TypeError, concat, 'abc', b'def') + self.assertRaises(TypeError, concat, 'abc', 'def') + self.assertRaises(TypeError, concat, [], b'def') + self.assertRaises(TypeError, concat, b'abc', []) + self.assertRaises(TypeError, concat, [], []) + + # CRASHES concat(NULL, bytearray(b'def')) + # CRASHES concat(bytearray(b'abc'), NULL) + # CRASHES concat(NULL, object()) + # CRASHES concat(object(), NULL) + + def test_resize(self): + """Test PyByteArray_Resize()""" + resize = _testcapi.bytearray_resize + + ba = bytearray(b'abcdef') + self.assertEqual(resize(ba, 3), 0) + self.assertEqual(ba, bytearray(b'abc')) + self.assertEqual(resize(ba, 10), 0) + self.assertEqual(len(ba), 10) + self.assertEqual(ba[:3], bytearray(b'abc')) + self.assertEqual(resize(ba, 2**20), 0) + self.assertEqual(len(ba), 2**20) + self.assertEqual(ba[:3], bytearray(b'abc')) + self.assertEqual(resize(ba, 0), 0) + self.assertEqual(ba, bytearray()) + + ba = ByteArraySubclass(b'abcdef') + self.assertEqual(resize(ba, 3), 0) + self.assertEqual(ba, bytearray(b'abc')) + + self.assertRaises(MemoryError, resize, bytearray(), PY_SSIZE_T_MAX) + self.assertRaises(MemoryError, resize, bytearray(1000), PY_SSIZE_T_MAX) + + # CRASHES resize(bytearray(b'abc'), -1) + # CRASHES resize(b'abc', 0) + # CRASHES resize(object(), 0) + # CRASHES resize(NULL, 0) + + +if __name__ == "__main__": + unittest.main() diff --git a/Lib/test/test_capi/test_bytes.py b/Lib/test/test_capi/test_bytes.py new file mode 100644 index 00000000000000..bb5d724ff187d4 --- /dev/null +++ b/Lib/test/test_capi/test_bytes.py @@ -0,0 +1,222 @@ +import unittest +from test.support import import_helper + +_testcapi = import_helper.import_module('_testcapi') +from _testcapi import PY_SSIZE_T_MIN, PY_SSIZE_T_MAX + +NULL = None + +class BytesSubclass(bytes): + pass + +class BytesLike: + def __init__(self, value): + self.value = value + def __bytes__(self): + return self.value + + +class CAPITest(unittest.TestCase): + def test_check(self): + # Test PyBytes_Check() + check = _testcapi.bytes_check + self.assertTrue(check(b'abc')) + self.assertFalse(check('abc')) + self.assertFalse(check(bytearray(b'abc'))) + self.assertTrue(check(BytesSubclass(b'abc'))) + self.assertFalse(check(BytesLike(b'abc'))) + self.assertFalse(check(3)) + self.assertFalse(check([])) + self.assertFalse(check(object())) + + # CRASHES check(NULL) + + def test_checkexact(self): + # Test PyBytes_CheckExact() + check = _testcapi.bytes_checkexact + self.assertTrue(check(b'abc')) + self.assertFalse(check('abc')) + self.assertFalse(check(bytearray(b'abc'))) + self.assertFalse(check(BytesSubclass(b'abc'))) + self.assertFalse(check(BytesLike(b'abc'))) + self.assertFalse(check(3)) + self.assertFalse(check([])) + self.assertFalse(check(object())) + + # CRASHES check(NULL) + + def test_fromstringandsize(self): + # Test PyBytes_FromStringAndSize() + fromstringandsize = _testcapi.bytes_fromstringandsize + + self.assertEqual(fromstringandsize(b'abc'), b'abc') + self.assertEqual(fromstringandsize(b'abc', 2), b'ab') + self.assertEqual(fromstringandsize(b'abc\0def'), b'abc\0def') + self.assertEqual(fromstringandsize(b'', 0), b'') + self.assertEqual(fromstringandsize(NULL, 0), b'') + self.assertEqual(len(fromstringandsize(NULL, 3)), 3) + self.assertRaises((MemoryError, OverflowError), + fromstringandsize, NULL, PY_SSIZE_T_MAX) + + self.assertRaises(SystemError, fromstringandsize, b'abc', -1) + self.assertRaises(SystemError, fromstringandsize, b'abc', PY_SSIZE_T_MIN) + self.assertRaises(SystemError, fromstringandsize, NULL, -1) + self.assertRaises(SystemError, fromstringandsize, NULL, PY_SSIZE_T_MIN) + + def test_fromstring(self): + # Test PyBytes_FromString() + fromstring = _testcapi.bytes_fromstring + + self.assertEqual(fromstring(b'abc\0def'), b'abc') + self.assertEqual(fromstring(b''), b'') + + # CRASHES fromstring(NULL) + + def test_fromobject(self): + # Test PyBytes_FromObject() + fromobject = _testcapi.bytes_fromobject + + self.assertEqual(fromobject(b'abc'), b'abc') + self.assertEqual(fromobject(bytearray(b'abc')), b'abc') + self.assertEqual(fromobject(BytesSubclass(b'abc')), b'abc') + self.assertEqual(fromobject([97, 98, 99]), b'abc') + self.assertRaises(TypeError, fromobject, 3) + self.assertRaises(TypeError, fromobject, BytesLike(b'abc')) + self.assertRaises(TypeError, fromobject, 'abc') + self.assertRaises(TypeError, fromobject, object()) + self.assertRaises(SystemError, fromobject, NULL) + + def test_size(self): + # Test PyBytes_Size() + size = _testcapi.bytes_size + + self.assertEqual(size(b'abc'), 3) + self.assertEqual(size(BytesSubclass(b'abc')), 3) + self.assertRaises(TypeError, size, bytearray(b'abc')) + self.assertRaises(TypeError, size, 'abc') + self.assertRaises(TypeError, size, object()) + + # CRASHES size(NULL) + + def test_asstring(self): + """Test PyBytes_AsString()""" + asstring = _testcapi.bytes_asstring + + self.assertEqual(asstring(b'abc', 4), b'abc\0') + self.assertEqual(asstring(b'abc\0def', 8), b'abc\0def\0') + self.assertRaises(TypeError, asstring, 'abc', 0) + self.assertRaises(TypeError, asstring, object(), 0) + + # CRASHES asstring(NULL, 0) + + def test_asstringandsize(self): + """Test PyBytes_AsStringAndSize()""" + asstringandsize = _testcapi.bytes_asstringandsize + asstringandsize_null = _testcapi.bytes_asstringandsize_null + + self.assertEqual(asstringandsize(b'abc', 4), (b'abc\0', 3)) + self.assertEqual(asstringandsize(b'abc\0def', 8), (b'abc\0def\0', 7)) + self.assertEqual(asstringandsize_null(b'abc', 4), b'abc\0') + self.assertRaises(ValueError, asstringandsize_null, b'abc\0def', 8) + self.assertRaises(TypeError, asstringandsize, 'abc', 0) + self.assertRaises(TypeError, asstringandsize_null, 'abc', 0) + self.assertRaises(TypeError, asstringandsize, object(), 0) + self.assertRaises(TypeError, asstringandsize_null, object(), 0) + + # CRASHES asstringandsize(NULL, 0) + # CRASHES asstringandsize_null(NULL, 0) + + def test_repr(self): + # Test PyBytes_Repr() + bytes_repr = _testcapi.bytes_repr + + self.assertEqual(bytes_repr(b'''abc''', 0), r"""b'abc'""") + self.assertEqual(bytes_repr(b'''abc''', 1), r"""b'abc'""") + self.assertEqual(bytes_repr(b'''a'b"c"d''', 0), r"""b'a\'b"c"d'""") + self.assertEqual(bytes_repr(b'''a'b"c"d''', 1), r"""b'a\'b"c"d'""") + self.assertEqual(bytes_repr(b'''a'b"c''', 0), r"""b'a\'b"c'""") + self.assertEqual(bytes_repr(b'''a'b"c''', 1), r"""b'a\'b"c'""") + self.assertEqual(bytes_repr(b'''a'b'c"d''', 0), r"""b'a\'b\'c"d'""") + self.assertEqual(bytes_repr(b'''a'b'c"d''', 1), r"""b'a\'b\'c"d'""") + self.assertEqual(bytes_repr(b'''a'b'c'd''', 0), r"""b'a\'b\'c\'d'""") + self.assertEqual(bytes_repr(b'''a'b'c'd''', 1), r'''b"a'b'c'd"''') + + self.assertEqual(bytes_repr(BytesSubclass(b'abc'), 0), r"""b'abc'""") + + # UDEFINED bytes_repr(object(), 0) + # CRASHES bytes_repr(NULL, 0) + + def test_concat(self, concat=None): + """Test PyBytes_Concat()""" + if concat is None: + concat = _testcapi.bytes_concat + + self.assertEqual(concat(b'abc', b'def'), b'abcdef') + self.assertEqual(concat(b'a\0b', b'c\0d'), b'a\0bc\0d') + self.assertEqual(concat(bytearray(b'abc'), b'def'), b'abcdef') + self.assertEqual(concat(b'abc', bytearray(b'def')), b'abcdef') + self.assertEqual(concat(bytearray(b'abc'), b''), b'abc') + self.assertEqual(concat(b'', bytearray(b'def')), b'def') + self.assertEqual(concat(memoryview(b'xabcy')[1:4], b'def'), b'abcdef') + self.assertEqual(concat(b'abc', memoryview(b'xdefy')[1:4]), b'abcdef') + + self.assertEqual(concat(b'abc', b'def', True), b'abcdef') + self.assertEqual(concat(b'abc', bytearray(b'def'), True), b'abcdef') + # Check that it does not change the singleton + self.assertEqual(concat(bytes(), b'def', True), b'def') + self.assertEqual(len(bytes()), 0) + + self.assertRaises(TypeError, concat, memoryview(b'axbycz')[::2], b'def') + self.assertRaises(TypeError, concat, b'abc', memoryview(b'dxeyfz')[::2]) + self.assertRaises(TypeError, concat, b'abc', 'def') + self.assertRaises(TypeError, concat, 'abc', b'def') + self.assertRaises(TypeError, concat, 'abc', 'def') + self.assertRaises(TypeError, concat, [], b'def') + self.assertRaises(TypeError, concat, b'abc', []) + self.assertRaises(TypeError, concat, [], []) + + self.assertEqual(concat(NULL, b'def'), NULL) + self.assertEqual(concat(b'abc', NULL), NULL) + self.assertEqual(concat(NULL, object()), NULL) + self.assertEqual(concat(object(), NULL), NULL) + + def test_concatanddel(self): + """Test PyBytes_ConcatAndDel()""" + self.test_concat(_testcapi.bytes_concatanddel) + + def test_decodeescape(self): + """Test PyBytes_DecodeEscape()""" + decodeescape = _testcapi.bytes_decodeescape + + self.assertEqual(decodeescape(b'abc'), b'abc') + self.assertEqual(decodeescape(br'\t\n\r\x0b\x0c\x00\\\'\"'), + b'''\t\n\r\v\f\0\\'"''') + self.assertEqual(decodeescape(b'\t\n\r\x0b\x0c\x00'), b'\t\n\r\v\f\0') + self.assertEqual(decodeescape(br'\xa1\xa2'), b'\xa1\xa2') + self.assertEqual(decodeescape(br'\2\24\241'), b'\x02\x14\xa1') + self.assertEqual(decodeescape(b'\xa1\xa2'), b'\xa1\xa2') + with self.assertWarns(DeprecationWarning): + self.assertEqual(decodeescape(br'\u4f60'), br'\u4f60') + with self.assertWarns(DeprecationWarning): + self.assertEqual(decodeescape(br'\z'), br'\z') + with self.assertWarns(DeprecationWarning): + self.assertEqual(decodeescape(br'\541'), b'a') + + for b in b'\\', br'\x', br'\xa', br'\xz', br'\xaz': + self.assertRaises(ValueError, decodeescape, b) + self.assertRaises(ValueError, decodeescape, b, 'strict') + self.assertEqual(decodeescape(br'x\xa', 'replace'), b'x?') + self.assertEqual(decodeescape(br'x\xay', 'replace'), b'x?y') + self.assertEqual(decodeescape(br'x\xa\xy', 'replace'), b'x??y') + self.assertEqual(decodeescape(br'x\xa\xy', 'ignore'), b'xy') + self.assertRaises(ValueError, decodeescape, b'\\', 'spam') + self.assertEqual(decodeescape(NULL), b'') + self.assertRaises(OverflowError, decodeescape, b'abc', NULL, PY_SSIZE_T_MAX) + self.assertRaises(OverflowError, decodeescape, NULL, NULL, PY_SSIZE_T_MAX) + + # CRASHES decodeescape(b'abc', NULL, -1) + # CRASHES decodeescape(NULL, NULL, 1) + + +if __name__ == "__main__": + unittest.main() diff --git a/Lib/test/test_capi/test_complex.py b/Lib/test/test_capi/test_complex.py new file mode 100644 index 00000000000000..d6fc1f077c40aa --- /dev/null +++ b/Lib/test/test_capi/test_complex.py @@ -0,0 +1,233 @@ +from math import isnan +import errno +import unittest +import warnings + +from test.test_capi.test_getargs import (BadComplex, BadComplex2, Complex, + FloatSubclass, Float, BadFloat, + BadFloat2, ComplexSubclass) +from test.support import import_helper + + +_testcapi = import_helper.import_module('_testcapi') + +NULL = None +INF = float("inf") +NAN = float("nan") +DBL_MAX = _testcapi.DBL_MAX + + +class BadComplex3: + def __complex__(self): + raise RuntimeError + + +class CAPIComplexTest(unittest.TestCase): + def test_check(self): + # Test PyComplex_Check() + check = _testcapi.complex_check + + self.assertTrue(check(1+2j)) + self.assertTrue(check(ComplexSubclass(1+2j))) + self.assertFalse(check(Complex())) + self.assertFalse(check(3)) + self.assertFalse(check(3.0)) + self.assertFalse(check(object())) + + # CRASHES check(NULL) + + def test_checkexact(self): + # PyComplex_CheckExact() + checkexact = _testcapi.complex_checkexact + + self.assertTrue(checkexact(1+2j)) + self.assertFalse(checkexact(ComplexSubclass(1+2j))) + self.assertFalse(checkexact(Complex())) + self.assertFalse(checkexact(3)) + self.assertFalse(checkexact(3.0)) + self.assertFalse(checkexact(object())) + + # CRASHES checkexact(NULL) + + def test_fromccomplex(self): + # Test PyComplex_FromCComplex() + fromccomplex = _testcapi.complex_fromccomplex + + self.assertEqual(fromccomplex(1+2j), 1.0+2.0j) + + def test_fromdoubles(self): + # Test PyComplex_FromDoubles() + fromdoubles = _testcapi.complex_fromdoubles + + self.assertEqual(fromdoubles(1.0, 2.0), 1.0+2.0j) + + def test_realasdouble(self): + # Test PyComplex_RealAsDouble() + realasdouble = _testcapi.complex_realasdouble + + self.assertEqual(realasdouble(1+2j), 1.0) + self.assertEqual(realasdouble(-1+0j), -1.0) + self.assertEqual(realasdouble(4.25), 4.25) + self.assertEqual(realasdouble(-1.0), -1.0) + self.assertEqual(realasdouble(42), 42.) + self.assertEqual(realasdouble(-1), -1.0) + + # Test subclasses of complex/float + self.assertEqual(realasdouble(ComplexSubclass(1+2j)), 1.0) + self.assertEqual(realasdouble(FloatSubclass(4.25)), 4.25) + + # Test types with __complex__ dunder method + # Function doesn't support classes with __complex__ dunder, see #109598 + self.assertRaises(TypeError, realasdouble, Complex()) + + # Test types with __float__ dunder method + self.assertEqual(realasdouble(Float()), 4.25) + self.assertRaises(TypeError, realasdouble, BadFloat()) + with self.assertWarns(DeprecationWarning): + self.assertEqual(realasdouble(BadFloat2()), 4.25) + + self.assertRaises(TypeError, realasdouble, object()) + + # CRASHES realasdouble(NULL) + + def test_imagasdouble(self): + # Test PyComplex_ImagAsDouble() + imagasdouble = _testcapi.complex_imagasdouble + + self.assertEqual(imagasdouble(1+2j), 2.0) + self.assertEqual(imagasdouble(1-1j), -1.0) + self.assertEqual(imagasdouble(4.25), 0.0) + self.assertEqual(imagasdouble(42), 0.0) + + # Test subclasses of complex/float + self.assertEqual(imagasdouble(ComplexSubclass(1+2j)), 2.0) + self.assertEqual(imagasdouble(FloatSubclass(4.25)), 0.0) + + # Test types with __complex__ dunder method + # Function doesn't support classes with __complex__ dunder, see #109598 + self.assertEqual(imagasdouble(Complex()), 0.0) + + # Function returns 0.0 anyway, see #109598 + self.assertEqual(imagasdouble(object()), 0.0) + + # CRASHES imagasdouble(NULL) + + def test_asccomplex(self): + # Test PyComplex_AsCComplex() + asccomplex = _testcapi.complex_asccomplex + + self.assertEqual(asccomplex(1+2j), 1.0+2.0j) + self.assertEqual(asccomplex(-1+2j), -1.0+2.0j) + self.assertEqual(asccomplex(4.25), 4.25+0.0j) + self.assertEqual(asccomplex(-1.0), -1.0+0.0j) + self.assertEqual(asccomplex(42), 42+0j) + self.assertEqual(asccomplex(-1), -1.0+0.0j) + + # Test subclasses of complex/float + self.assertEqual(asccomplex(ComplexSubclass(1+2j)), 1.0+2.0j) + self.assertEqual(asccomplex(FloatSubclass(4.25)), 4.25+0.0j) + + # Test types with __complex__ dunder method + self.assertEqual(asccomplex(Complex()), 4.25+0.5j) + self.assertRaises(TypeError, asccomplex, BadComplex()) + with self.assertWarns(DeprecationWarning): + self.assertEqual(asccomplex(BadComplex2()), 4.25+0.5j) + with warnings.catch_warnings(): + warnings.simplefilter("error", DeprecationWarning) + self.assertRaises(DeprecationWarning, asccomplex, BadComplex2()) + self.assertRaises(RuntimeError, asccomplex, BadComplex3()) + + # Test types with __float__ dunder method + self.assertEqual(asccomplex(Float()), 4.25+0.0j) + self.assertRaises(TypeError, asccomplex, BadFloat()) + with self.assertWarns(DeprecationWarning): + self.assertEqual(asccomplex(BadFloat2()), 4.25+0.0j) + + self.assertRaises(TypeError, asccomplex, object()) + + # CRASHES asccomplex(NULL) + + def test_py_c_sum(self): + # Test _Py_c_sum() + _py_c_sum = _testcapi._py_c_sum + + self.assertEqual(_py_c_sum(1, 1j), (1+1j, 0)) + + def test_py_c_diff(self): + # Test _Py_c_diff() + _py_c_diff = _testcapi._py_c_diff + + self.assertEqual(_py_c_diff(1, 1j), (1-1j, 0)) + + def test_py_c_neg(self): + # Test _Py_c_neg() + _py_c_neg = _testcapi._py_c_neg + + self.assertEqual(_py_c_neg(1+1j), -1-1j) + + def test_py_c_prod(self): + # Test _Py_c_prod() + _py_c_prod = _testcapi._py_c_prod + + self.assertEqual(_py_c_prod(2, 1j), (2j, 0)) + + def test_py_c_quot(self): + # Test _Py_c_quot() + _py_c_quot = _testcapi._py_c_quot + + self.assertEqual(_py_c_quot(1, 1j), (-1j, 0)) + self.assertEqual(_py_c_quot(1, -1j), (1j, 0)) + self.assertEqual(_py_c_quot(1j, 2), (0.5j, 0)) + self.assertEqual(_py_c_quot(1j, -2), (-0.5j, 0)) + self.assertEqual(_py_c_quot(1, 2j), (-0.5j, 0)) + + z, e = _py_c_quot(NAN, 1j) + self.assertTrue(isnan(z.real)) + self.assertTrue(isnan(z.imag)) + self.assertEqual(e, 0) + + z, e = _py_c_quot(1j, NAN) + self.assertTrue(isnan(z.real)) + self.assertTrue(isnan(z.imag)) + self.assertEqual(e, 0) + + self.assertEqual(_py_c_quot(1, 0j)[1], errno.EDOM) + + def test_py_c_pow(self): + # Test _Py_c_pow() + _py_c_pow = _testcapi._py_c_pow + + self.assertEqual(_py_c_pow(1j, 0j), (1+0j, 0)) + self.assertEqual(_py_c_pow(1, 1j), (1+0j, 0)) + self.assertEqual(_py_c_pow(0j, 1), (0j, 0)) + self.assertAlmostEqual(_py_c_pow(1j, 2)[0], -1.0+0j) + + r, e = _py_c_pow(1+1j, -1) + self.assertAlmostEqual(r, 0.5-0.5j) + self.assertEqual(e, 0) + + self.assertEqual(_py_c_pow(0j, -1)[1], errno.EDOM) + self.assertEqual(_py_c_pow(0j, 1j)[1], errno.EDOM) + self.assertEqual(_py_c_pow(*[DBL_MAX+1j]*2)[0], complex(*[INF]*2)) + + + def test_py_c_abs(self): + # Test _Py_c_abs() + _py_c_abs = _testcapi._py_c_abs + + self.assertEqual(_py_c_abs(-1), (1.0, 0)) + self.assertEqual(_py_c_abs(1j), (1.0, 0)) + + self.assertEqual(_py_c_abs(complex('+inf+1j')), (INF, 0)) + self.assertEqual(_py_c_abs(complex('-inf+1j')), (INF, 0)) + self.assertEqual(_py_c_abs(complex('1.25+infj')), (INF, 0)) + self.assertEqual(_py_c_abs(complex('1.25-infj')), (INF, 0)) + + self.assertTrue(isnan(_py_c_abs(complex('1.25+nanj'))[0])) + self.assertTrue(isnan(_py_c_abs(complex('nan-1j'))[0])) + + self.assertEqual(_py_c_abs(complex(*[DBL_MAX]*2))[1], errno.ERANGE) + + +if __name__ == "__main__": + unittest.main() diff --git a/Lib/test/test_capi/test_dict.py b/Lib/test/test_capi/test_dict.py new file mode 100644 index 00000000000000..57a7238588eae0 --- /dev/null +++ b/Lib/test/test_capi/test_dict.py @@ -0,0 +1,524 @@ +import unittest +from collections import OrderedDict, UserDict +from types import MappingProxyType +from test import support +import _testcapi + + +NULL = None +INVALID_UTF8 = b'\xff' + +class DictSubclass(dict): + def __getitem__(self, key): + raise RuntimeError('do not get evil') + def __setitem__(self, key, value): + raise RuntimeError('do not set evil') + def __delitem__(self, key): + raise RuntimeError('do not del evil') + +def gen(): + yield 'a' + yield 'b' + yield 'c' + + +class CAPITest(unittest.TestCase): + + def test_dict_check(self): + check = _testcapi.dict_check + self.assertTrue(check({1: 2})) + self.assertTrue(check(OrderedDict({1: 2}))) + self.assertFalse(check(UserDict({1: 2}))) + self.assertFalse(check([1, 2])) + self.assertFalse(check(object())) + # CRASHES check(NULL) + + def test_dict_checkexact(self): + check = _testcapi.dict_checkexact + self.assertTrue(check({1: 2})) + self.assertFalse(check(OrderedDict({1: 2}))) + self.assertFalse(check(UserDict({1: 2}))) + self.assertFalse(check([1, 2])) + self.assertFalse(check(object())) + # CRASHES check(NULL) + + def test_dict_new(self): + dict_new = _testcapi.dict_new + dct = dict_new() + self.assertEqual(dct, {}) + self.assertIs(type(dct), dict) + dct2 = dict_new() + self.assertIsNot(dct2, dct) + + def test_dictproxy_new(self): + dictproxy_new = _testcapi.dictproxy_new + for dct in {1: 2}, OrderedDict({1: 2}), UserDict({1: 2}): + proxy = dictproxy_new(dct) + self.assertIs(type(proxy), MappingProxyType) + self.assertEqual(proxy, dct) + with self.assertRaises(TypeError): + proxy[1] = 3 + self.assertEqual(proxy[1], 2) + dct[1] = 4 + self.assertEqual(proxy[1], 4) + + self.assertRaises(TypeError, dictproxy_new, []) + self.assertRaises(TypeError, dictproxy_new, 42) + # CRASHES dictproxy_new(NULL) + + def test_dict_copy(self): + copy = _testcapi.dict_copy + for dct in {1: 2}, OrderedDict({1: 2}): + dct_copy = copy(dct) + self.assertIs(type(dct_copy), dict) + self.assertEqual(dct_copy, dct) + + self.assertRaises(SystemError, copy, UserDict()) + self.assertRaises(SystemError, copy, []) + self.assertRaises(SystemError, copy, 42) + self.assertRaises(SystemError, copy, NULL) + + def test_dict_clear(self): + clear = _testcapi.dict_clear + dct = {1: 2} + clear(dct) + self.assertEqual(dct, {}) + + # NOTE: It is not safe to call it with OrderedDict. + + # Has no effect for non-dicts. + dct = UserDict({1: 2}) + clear(dct) + self.assertEqual(dct, {1: 2}) + lst = [1, 2] + clear(lst) + self.assertEqual(lst, [1, 2]) + clear(object()) + + # CRASHES? clear(NULL) + + def test_dict_size(self): + size = _testcapi.dict_size + self.assertEqual(size({1: 2}), 1) + self.assertEqual(size(OrderedDict({1: 2})), 1) + + self.assertRaises(SystemError, size, UserDict()) + self.assertRaises(SystemError, size, []) + self.assertRaises(SystemError, size, 42) + self.assertRaises(SystemError, size, object()) + self.assertRaises(SystemError, size, NULL) + + def test_dict_getitem(self): + getitem = _testcapi.dict_getitem + dct = {'a': 1, '\U0001f40d': 2} + self.assertEqual(getitem(dct, 'a'), 1) + self.assertIs(getitem(dct, 'b'), KeyError) + self.assertEqual(getitem(dct, '\U0001f40d'), 2) + + dct2 = DictSubclass(dct) + self.assertEqual(getitem(dct2, 'a'), 1) + self.assertIs(getitem(dct2, 'b'), KeyError) + + with support.catch_unraisable_exception() as cm: + self.assertIs(getitem({}, []), KeyError) # unhashable + self.assertEqual(cm.unraisable.exc_type, TypeError) + self.assertEqual(str(cm.unraisable.exc_value), + "unhashable type: 'list'") + + self.assertIs(getitem(42, 'a'), KeyError) + self.assertIs(getitem([1], 0), KeyError) + # CRASHES getitem({}, NULL) + # CRASHES getitem(NULL, 'a') + + def test_dict_getitemstring(self): + getitemstring = _testcapi.dict_getitemstring + dct = {'a': 1, '\U0001f40d': 2} + self.assertEqual(getitemstring(dct, b'a'), 1) + self.assertIs(getitemstring(dct, b'b'), KeyError) + self.assertEqual(getitemstring(dct, '\U0001f40d'.encode()), 2) + + dct2 = DictSubclass(dct) + self.assertEqual(getitemstring(dct2, b'a'), 1) + self.assertIs(getitemstring(dct2, b'b'), KeyError) + + with support.catch_unraisable_exception() as cm: + self.assertIs(getitemstring({}, INVALID_UTF8), KeyError) + self.assertEqual(cm.unraisable.exc_type, UnicodeDecodeError) + self.assertRegex(str(cm.unraisable.exc_value), + "'utf-8' codec can't decode") + + self.assertIs(getitemstring(42, b'a'), KeyError) + self.assertIs(getitemstring([], b'a'), KeyError) + # CRASHES getitemstring({}, NULL) + # CRASHES getitemstring(NULL, b'a') + + def test_dict_getitemref(self): + getitem = _testcapi.dict_getitemref + dct = {'a': 1, '\U0001f40d': 2} + self.assertEqual(getitem(dct, 'a'), 1) + self.assertIs(getitem(dct, 'b'), KeyError) + self.assertEqual(getitem(dct, '\U0001f40d'), 2) + + dct2 = DictSubclass(dct) + self.assertEqual(getitem(dct2, 'a'), 1) + self.assertIs(getitem(dct2, 'b'), KeyError) + + self.assertRaises(SystemError, getitem, 42, 'a') + self.assertRaises(TypeError, getitem, {}, []) # unhashable + self.assertRaises(SystemError, getitem, [], 1) + self.assertRaises(SystemError, getitem, [], 'a') + # CRASHES getitem({}, NULL) + # CRASHES getitem(NULL, 'a') + + def test_dict_getitemstringref(self): + getitemstring = _testcapi.dict_getitemstringref + dct = {'a': 1, '\U0001f40d': 2} + self.assertEqual(getitemstring(dct, b'a'), 1) + self.assertIs(getitemstring(dct, b'b'), KeyError) + self.assertEqual(getitemstring(dct, '\U0001f40d'.encode()), 2) + + dct2 = DictSubclass(dct) + self.assertEqual(getitemstring(dct2, b'a'), 1) + self.assertIs(getitemstring(dct2, b'b'), KeyError) + + self.assertRaises(SystemError, getitemstring, 42, b'a') + self.assertRaises(UnicodeDecodeError, getitemstring, {}, INVALID_UTF8) + self.assertRaises(SystemError, getitemstring, [], b'a') + # CRASHES getitemstring({}, NULL) + # CRASHES getitemstring(NULL, b'a') + + def test_dict_getitemwitherror(self): + getitem = _testcapi.dict_getitemwitherror + dct = {'a': 1, '\U0001f40d': 2} + self.assertEqual(getitem(dct, 'a'), 1) + self.assertIs(getitem(dct, 'b'), KeyError) + self.assertEqual(getitem(dct, '\U0001f40d'), 2) + + dct2 = DictSubclass(dct) + self.assertEqual(getitem(dct2, 'a'), 1) + self.assertIs(getitem(dct2, 'b'), KeyError) + + self.assertRaises(SystemError, getitem, 42, 'a') + self.assertRaises(TypeError, getitem, {}, []) # unhashable + self.assertRaises(SystemError, getitem, [], 1) + self.assertRaises(SystemError, getitem, [], 'a') + # CRASHES getitem({}, NULL) + # CRASHES getitem(NULL, 'a') + + def test_dict_contains(self): + contains = _testcapi.dict_contains + dct = {'a': 1, '\U0001f40d': 2} + self.assertTrue(contains(dct, 'a')) + self.assertFalse(contains(dct, 'b')) + self.assertTrue(contains(dct, '\U0001f40d')) + + dct2 = DictSubclass(dct) + self.assertTrue(contains(dct2, 'a')) + self.assertFalse(contains(dct2, 'b')) + + self.assertRaises(TypeError, contains, {}, []) # unhashable + # CRASHES contains({}, NULL) + # CRASHES contains(UserDict(), 'a') + # CRASHES contains(42, 'a') + # CRASHES contains(NULL, 'a') + + def test_dict_contains_string(self): + contains_string = _testcapi.dict_containsstring + dct = {'a': 1, '\U0001f40d': 2} + self.assertTrue(contains_string(dct, b'a')) + self.assertFalse(contains_string(dct, b'b')) + self.assertTrue(contains_string(dct, '\U0001f40d'.encode())) + self.assertRaises(UnicodeDecodeError, contains_string, dct, INVALID_UTF8) + + dct2 = DictSubclass(dct) + self.assertTrue(contains_string(dct2, b'a')) + self.assertFalse(contains_string(dct2, b'b')) + + # CRASHES contains({}, NULL) + # CRASHES contains(NULL, b'a') + + def test_dict_setitem(self): + setitem = _testcapi.dict_setitem + dct = {} + setitem(dct, 'a', 5) + self.assertEqual(dct, {'a': 5}) + setitem(dct, '\U0001f40d', 8) + self.assertEqual(dct, {'a': 5, '\U0001f40d': 8}) + + dct2 = DictSubclass() + setitem(dct2, 'a', 5) + self.assertEqual(dct2, {'a': 5}) + + self.assertRaises(TypeError, setitem, {}, [], 5) # unhashable + self.assertRaises(SystemError, setitem, UserDict(), 'a', 5) + self.assertRaises(SystemError, setitem, [1], 0, 5) + self.assertRaises(SystemError, setitem, 42, 'a', 5) + # CRASHES setitem({}, NULL, 5) + # CRASHES setitem({}, 'a', NULL) + # CRASHES setitem(NULL, 'a', 5) + + def test_dict_setitemstring(self): + setitemstring = _testcapi.dict_setitemstring + dct = {} + setitemstring(dct, b'a', 5) + self.assertEqual(dct, {'a': 5}) + setitemstring(dct, '\U0001f40d'.encode(), 8) + self.assertEqual(dct, {'a': 5, '\U0001f40d': 8}) + + dct2 = DictSubclass() + setitemstring(dct2, b'a', 5) + self.assertEqual(dct2, {'a': 5}) + + self.assertRaises(UnicodeDecodeError, setitemstring, {}, INVALID_UTF8, 5) + self.assertRaises(SystemError, setitemstring, UserDict(), b'a', 5) + self.assertRaises(SystemError, setitemstring, 42, b'a', 5) + # CRASHES setitemstring({}, NULL, 5) + # CRASHES setitemstring({}, b'a', NULL) + # CRASHES setitemstring(NULL, b'a', 5) + + def test_dict_delitem(self): + delitem = _testcapi.dict_delitem + dct = {'a': 1, 'c': 2, '\U0001f40d': 3} + delitem(dct, 'a') + self.assertEqual(dct, {'c': 2, '\U0001f40d': 3}) + self.assertRaises(KeyError, delitem, dct, 'b') + delitem(dct, '\U0001f40d') + self.assertEqual(dct, {'c': 2}) + + dct2 = DictSubclass({'a': 1, 'c': 2}) + delitem(dct2, 'a') + self.assertEqual(dct2, {'c': 2}) + self.assertRaises(KeyError, delitem, dct2, 'b') + + self.assertRaises(TypeError, delitem, {}, []) # unhashable + self.assertRaises(SystemError, delitem, UserDict({'a': 1}), 'a') + self.assertRaises(SystemError, delitem, [1], 0) + self.assertRaises(SystemError, delitem, 42, 'a') + # CRASHES delitem({}, NULL) + # CRASHES delitem(NULL, 'a') + + def test_dict_delitemstring(self): + delitemstring = _testcapi.dict_delitemstring + dct = {'a': 1, 'c': 2, '\U0001f40d': 3} + delitemstring(dct, b'a') + self.assertEqual(dct, {'c': 2, '\U0001f40d': 3}) + self.assertRaises(KeyError, delitemstring, dct, b'b') + delitemstring(dct, '\U0001f40d'.encode()) + self.assertEqual(dct, {'c': 2}) + + dct2 = DictSubclass({'a': 1, 'c': 2}) + delitemstring(dct2, b'a') + self.assertEqual(dct2, {'c': 2}) + self.assertRaises(KeyError, delitemstring, dct2, b'b') + + self.assertRaises(UnicodeDecodeError, delitemstring, {}, INVALID_UTF8) + self.assertRaises(SystemError, delitemstring, UserDict({'a': 1}), b'a') + self.assertRaises(SystemError, delitemstring, 42, b'a') + # CRASHES delitemstring({}, NULL) + # CRASHES delitemstring(NULL, b'a') + + def test_dict_setdefault(self): + setdefault = _testcapi.dict_setdefault + dct = {} + self.assertEqual(setdefault(dct, 'a', 5), 5) + self.assertEqual(dct, {'a': 5}) + self.assertEqual(setdefault(dct, 'a', 8), 5) + self.assertEqual(dct, {'a': 5}) + + dct2 = DictSubclass() + self.assertEqual(setdefault(dct2, 'a', 5), 5) + self.assertEqual(dct2, {'a': 5}) + self.assertEqual(setdefault(dct2, 'a', 8), 5) + self.assertEqual(dct2, {'a': 5}) + + self.assertRaises(TypeError, setdefault, {}, [], 5) # unhashable + self.assertRaises(SystemError, setdefault, UserDict(), 'a', 5) + self.assertRaises(SystemError, setdefault, [1], 0, 5) + self.assertRaises(SystemError, setdefault, 42, 'a', 5) + # CRASHES setdefault({}, NULL, 5) + # CRASHES setdefault({}, 'a', NULL) + # CRASHES setdefault(NULL, 'a', 5) + + def test_mapping_keys_valuesitems(self): + class BadMapping(dict): + def keys(self): + return None + def values(self): + return None + def items(self): + return None + dict_obj = {'foo': 1, 'bar': 2, 'spam': 3} + for mapping in [dict_obj, DictSubclass(dict_obj), BadMapping(dict_obj)]: + self.assertListEqual(_testcapi.dict_keys(mapping), + list(dict_obj.keys())) + self.assertListEqual(_testcapi.dict_values(mapping), + list(dict_obj.values())) + self.assertListEqual(_testcapi.dict_items(mapping), + list(dict_obj.items())) + + def test_dict_keys_valuesitems_bad_arg(self): + for mapping in UserDict(), [], object(): + self.assertRaises(SystemError, _testcapi.dict_keys, mapping) + self.assertRaises(SystemError, _testcapi.dict_values, mapping) + self.assertRaises(SystemError, _testcapi.dict_items, mapping) + + def test_dict_next(self): + dict_next = _testcapi.dict_next + self.assertIsNone(dict_next({}, 0)) + dct = {'a': 1, 'b': 2, 'c': 3} + pos = 0 + pairs = [] + while True: + res = dict_next(dct, pos) + if res is None: + break + rc, pos, key, value = res + self.assertEqual(rc, 1) + pairs.append((key, value)) + self.assertEqual(pairs, list(dct.items())) + + # CRASHES dict_next(NULL, 0) + + def test_dict_update(self): + update = _testcapi.dict_update + for cls1 in dict, DictSubclass: + for cls2 in dict, DictSubclass, UserDict: + dct = cls1({'a': 1, 'b': 2}) + update(dct, cls2({'b': 3, 'c': 4})) + self.assertEqual(dct, {'a': 1, 'b': 3, 'c': 4}) + + self.assertRaises(AttributeError, update, {}, []) + self.assertRaises(AttributeError, update, {}, 42) + self.assertRaises(SystemError, update, UserDict(), {}) + self.assertRaises(SystemError, update, 42, {}) + self.assertRaises(SystemError, update, {}, NULL) + self.assertRaises(SystemError, update, NULL, {}) + + def test_dict_merge(self): + merge = _testcapi.dict_merge + for cls1 in dict, DictSubclass: + for cls2 in dict, DictSubclass, UserDict: + dct = cls1({'a': 1, 'b': 2}) + merge(dct, cls2({'b': 3, 'c': 4}), 0) + self.assertEqual(dct, {'a': 1, 'b': 2, 'c': 4}) + dct = cls1({'a': 1, 'b': 2}) + merge(dct, cls2({'b': 3, 'c': 4}), 1) + self.assertEqual(dct, {'a': 1, 'b': 3, 'c': 4}) + + self.assertRaises(AttributeError, merge, {}, [], 0) + self.assertRaises(AttributeError, merge, {}, 42, 0) + self.assertRaises(SystemError, merge, UserDict(), {}, 0) + self.assertRaises(SystemError, merge, 42, {}, 0) + self.assertRaises(SystemError, merge, {}, NULL, 0) + self.assertRaises(SystemError, merge, NULL, {}, 0) + + def test_dict_mergefromseq2(self): + mergefromseq2 = _testcapi.dict_mergefromseq2 + for cls1 in dict, DictSubclass: + for cls2 in list, iter: + dct = cls1({'a': 1, 'b': 2}) + mergefromseq2(dct, cls2([('b', 3), ('c', 4)]), 0) + self.assertEqual(dct, {'a': 1, 'b': 2, 'c': 4}) + dct = cls1({'a': 1, 'b': 2}) + mergefromseq2(dct, cls2([('b', 3), ('c', 4)]), 1) + self.assertEqual(dct, {'a': 1, 'b': 3, 'c': 4}) + + self.assertRaises(ValueError, mergefromseq2, {}, [(1,)], 0) + self.assertRaises(ValueError, mergefromseq2, {}, [(1, 2, 3)], 0) + self.assertRaises(TypeError, mergefromseq2, {}, [1], 0) + self.assertRaises(TypeError, mergefromseq2, {}, 42, 0) + # CRASHES mergefromseq2(UserDict(), [], 0) + # CRASHES mergefromseq2(42, [], 0) + # CRASHES mergefromseq2({}, NULL, 0) + # CRASHES mergefromseq2(NULL, {}, 0) + + def test_dict_pop(self): + # Test PyDict_Pop() + dict_pop = _testcapi.dict_pop + dict_pop_null = _testcapi.dict_pop_null + + # key present, get removed value + mydict = {"key": "value", "key2": "value2"} + self.assertEqual(dict_pop(mydict, "key"), (1, "value")) + self.assertEqual(mydict, {"key2": "value2"}) + self.assertEqual(dict_pop(mydict, "key2"), (1, "value2")) + self.assertEqual(mydict, {}) + + # key present, ignore removed value + mydict = {"key": "value", "key2": "value2"} + self.assertEqual(dict_pop_null(mydict, "key"), 1) + self.assertEqual(mydict, {"key2": "value2"}) + self.assertEqual(dict_pop_null(mydict, "key2"), 1) + self.assertEqual(mydict, {}) + + # key missing, expect removed value; empty dict has a fast path + self.assertEqual(dict_pop({}, "key"), (0, NULL)) + self.assertEqual(dict_pop({"a": 1}, "key"), (0, NULL)) + + # key missing, ignored removed value; empty dict has a fast path + self.assertEqual(dict_pop_null({}, "key"), 0) + self.assertEqual(dict_pop_null({"a": 1}, "key"), 0) + + # dict error + not_dict = UserDict({1: 2}) + self.assertRaises(SystemError, dict_pop, not_dict, "key") + self.assertRaises(SystemError, dict_pop_null, not_dict, "key") + + # key error; don't hash key if dict is empty + not_hashable_key = ["list"] + self.assertEqual(dict_pop({}, not_hashable_key), (0, NULL)) + with self.assertRaises(TypeError): + dict_pop({'key': 1}, not_hashable_key) + dict_pop({}, NULL) # key is not checked if dict is empty + + # CRASHES dict_pop(NULL, "key") + # CRASHES dict_pop({"a": 1}, NULL) + + def test_dict_popstring(self): + # Test PyDict_PopString() + dict_popstring = _testcapi.dict_popstring + dict_popstring_null = _testcapi.dict_popstring_null + + # key present, get removed value + mydict = {"key": "value", "key2": "value2"} + self.assertEqual(dict_popstring(mydict, "key"), (1, "value")) + self.assertEqual(mydict, {"key2": "value2"}) + self.assertEqual(dict_popstring(mydict, "key2"), (1, "value2")) + self.assertEqual(mydict, {}) + + # key present, ignore removed value + mydict = {"key": "value", "key2": "value2"} + self.assertEqual(dict_popstring_null(mydict, "key"), 1) + self.assertEqual(mydict, {"key2": "value2"}) + self.assertEqual(dict_popstring_null(mydict, "key2"), 1) + self.assertEqual(mydict, {}) + + # key missing; empty dict has a fast path + self.assertEqual(dict_popstring({}, "key"), (0, NULL)) + self.assertEqual(dict_popstring_null({}, "key"), 0) + self.assertEqual(dict_popstring({"a": 1}, "key"), (0, NULL)) + self.assertEqual(dict_popstring_null({"a": 1}, "key"), 0) + + # non-ASCII key + non_ascii = '\U0001f40d' + dct = {'\U0001f40d': 123} + self.assertEqual(dict_popstring(dct, '\U0001f40d'.encode()), (1, 123)) + dct = {'\U0001f40d': 123} + self.assertEqual(dict_popstring_null(dct, '\U0001f40d'.encode()), 1) + + # dict error + not_dict = UserDict({1: 2}) + self.assertRaises(SystemError, dict_popstring, not_dict, "key") + self.assertRaises(SystemError, dict_popstring_null, not_dict, "key") + + # key error + self.assertRaises(UnicodeDecodeError, dict_popstring, {1: 2}, INVALID_UTF8) + self.assertRaises(UnicodeDecodeError, dict_popstring_null, {1: 2}, INVALID_UTF8) + + # CRASHES dict_popstring(NULL, "key") + # CRASHES dict_popstring({}, NULL) + # CRASHES dict_popstring({"a": 1}, NULL) + + +if __name__ == "__main__": + unittest.main() diff --git a/Lib/test/test_capi/test_exceptions.py b/Lib/test/test_capi/test_exceptions.py index 118b575cba6df7..1d158e3586e98d 100644 --- a/Lib/test/test_capi/test_exceptions.py +++ b/Lib/test/test_capi/test_exceptions.py @@ -1,9 +1,12 @@ +import errno +import os import re import sys import unittest from test import support from test.support import import_helper +from test.support.os_helper import TESTFN, TESTFN_UNDECODABLE from test.support.script_helper import assert_python_failure from test.support.testcase import ExceptionIsLikeMixin @@ -12,6 +15,12 @@ # Skip this test if the _testcapi module isn't available. _testcapi = import_helper.import_module('_testcapi') +NULL = None + +class CustomError(Exception): + pass + + class Test_Exceptions(unittest.TestCase): def test_exception(self): @@ -189,6 +198,180 @@ def __repr__(self): self.assertEqual(exc.__notes__[0], 'Normalization failed: type=Broken args=') + def test_set_string(self): + """Test PyErr_SetString()""" + setstring = _testcapi.err_setstring + with self.assertRaises(ZeroDivisionError) as e: + setstring(ZeroDivisionError, b'error') + self.assertEqual(e.exception.args, ('error',)) + with self.assertRaises(ZeroDivisionError) as e: + setstring(ZeroDivisionError, 'помилка'.encode()) + self.assertEqual(e.exception.args, ('помилка',)) + + with self.assertRaises(UnicodeDecodeError): + setstring(ZeroDivisionError, b'\xff') + self.assertRaises(SystemError, setstring, list, b'error') + # CRASHES setstring(ZeroDivisionError, NULL) + # CRASHES setstring(NULL, b'error') + + def test_format(self): + """Test PyErr_Format()""" + import_helper.import_module('ctypes') + from ctypes import pythonapi, py_object, c_char_p, c_int + name = "PyErr_Format" + PyErr_Format = getattr(pythonapi, name) + PyErr_Format.argtypes = (py_object, c_char_p,) + PyErr_Format.restype = py_object + with self.assertRaises(ZeroDivisionError) as e: + PyErr_Format(ZeroDivisionError, b'%s %d', b'error', c_int(42)) + self.assertEqual(e.exception.args, ('error 42',)) + with self.assertRaises(ZeroDivisionError) as e: + PyErr_Format(ZeroDivisionError, b'%s', 'помилка'.encode()) + self.assertEqual(e.exception.args, ('помилка',)) + + with self.assertRaisesRegex(OverflowError, 'not in range'): + PyErr_Format(ZeroDivisionError, b'%c', c_int(-1)) + with self.assertRaisesRegex(ValueError, 'format string'): + PyErr_Format(ZeroDivisionError, b'\xff') + self.assertRaises(SystemError, PyErr_Format, list, b'error') + # CRASHES PyErr_Format(ZeroDivisionError, NULL) + # CRASHES PyErr_Format(py_object(), b'error') + + def test_setfromerrnowithfilename(self): + """Test PyErr_SetFromErrnoWithFilename()""" + setfromerrnowithfilename = _testcapi.err_setfromerrnowithfilename + ENOENT = errno.ENOENT + with self.assertRaises(FileNotFoundError) as e: + setfromerrnowithfilename(ENOENT, OSError, b'file') + self.assertEqual(e.exception.args, + (ENOENT, 'No such file or directory')) + self.assertEqual(e.exception.errno, ENOENT) + self.assertEqual(e.exception.filename, 'file') + + with self.assertRaises(FileNotFoundError) as e: + setfromerrnowithfilename(ENOENT, OSError, os.fsencode(TESTFN)) + self.assertEqual(e.exception.filename, TESTFN) + + if TESTFN_UNDECODABLE: + with self.assertRaises(FileNotFoundError) as e: + setfromerrnowithfilename(ENOENT, OSError, TESTFN_UNDECODABLE) + self.assertEqual(e.exception.filename, + os.fsdecode(TESTFN_UNDECODABLE)) + + with self.assertRaises(FileNotFoundError) as e: + setfromerrnowithfilename(ENOENT, OSError, NULL) + self.assertIsNone(e.exception.filename) + + with self.assertRaises(OSError) as e: + setfromerrnowithfilename(0, OSError, b'file') + self.assertEqual(e.exception.args, (0, 'Error')) + self.assertEqual(e.exception.errno, 0) + self.assertEqual(e.exception.filename, 'file') + + with self.assertRaises(ZeroDivisionError) as e: + setfromerrnowithfilename(ENOENT, ZeroDivisionError, b'file') + self.assertEqual(e.exception.args, + (ENOENT, 'No such file or directory', 'file')) + # CRASHES setfromerrnowithfilename(ENOENT, NULL, b'error') + + def test_err_writeunraisable(self): + # Test PyErr_WriteUnraisable() + writeunraisable = _testcapi.err_writeunraisable + firstline = self.test_err_writeunraisable.__code__.co_firstlineno + + with support.catch_unraisable_exception() as cm: + writeunraisable(CustomError('oops!'), hex) + self.assertEqual(cm.unraisable.exc_type, CustomError) + self.assertEqual(str(cm.unraisable.exc_value), 'oops!') + self.assertEqual(cm.unraisable.exc_traceback.tb_lineno, + firstline + 6) + self.assertIsNone(cm.unraisable.err_msg) + self.assertEqual(cm.unraisable.object, hex) + + with support.catch_unraisable_exception() as cm: + writeunraisable(CustomError('oops!'), NULL) + self.assertEqual(cm.unraisable.exc_type, CustomError) + self.assertEqual(str(cm.unraisable.exc_value), 'oops!') + self.assertEqual(cm.unraisable.exc_traceback.tb_lineno, + firstline + 15) + self.assertIsNone(cm.unraisable.err_msg) + self.assertIsNone(cm.unraisable.object) + + with (support.swap_attr(sys, 'unraisablehook', None), + support.captured_stderr() as stderr): + writeunraisable(CustomError('oops!'), hex) + lines = stderr.getvalue().splitlines() + self.assertEqual(lines[0], f'Exception ignored in: {hex!r}') + self.assertEqual(lines[1], 'Traceback (most recent call last):') + self.assertEqual(lines[-1], f'{__name__}.CustomError: oops!') + + with (support.swap_attr(sys, 'unraisablehook', None), + support.captured_stderr() as stderr): + writeunraisable(CustomError('oops!'), NULL) + lines = stderr.getvalue().splitlines() + self.assertEqual(lines[0], 'Traceback (most recent call last):') + self.assertEqual(lines[-1], f'{__name__}.CustomError: oops!') + + # CRASHES writeunraisable(NULL, hex) + # CRASHES writeunraisable(NULL, NULL) + + def test_err_formatunraisable(self): + # Test PyErr_FormatUnraisable() + formatunraisable = _testcapi.err_formatunraisable + firstline = self.test_err_formatunraisable.__code__.co_firstlineno + + with support.catch_unraisable_exception() as cm: + formatunraisable(CustomError('oops!'), b'Error in %R', []) + self.assertEqual(cm.unraisable.exc_type, CustomError) + self.assertEqual(str(cm.unraisable.exc_value), 'oops!') + self.assertEqual(cm.unraisable.exc_traceback.tb_lineno, + firstline + 6) + self.assertEqual(cm.unraisable.err_msg, 'Error in []') + self.assertIsNone(cm.unraisable.object) + + with support.catch_unraisable_exception() as cm: + formatunraisable(CustomError('oops!'), b'undecodable \xff') + self.assertEqual(cm.unraisable.exc_type, CustomError) + self.assertEqual(str(cm.unraisable.exc_value), 'oops!') + self.assertEqual(cm.unraisable.exc_traceback.tb_lineno, + firstline + 15) + self.assertIsNone(cm.unraisable.err_msg) + self.assertIsNone(cm.unraisable.object) + + with support.catch_unraisable_exception() as cm: + formatunraisable(CustomError('oops!'), NULL) + self.assertEqual(cm.unraisable.exc_type, CustomError) + self.assertEqual(str(cm.unraisable.exc_value), 'oops!') + self.assertEqual(cm.unraisable.exc_traceback.tb_lineno, + firstline + 24) + self.assertIsNone(cm.unraisable.err_msg) + self.assertIsNone(cm.unraisable.object) + + with (support.swap_attr(sys, 'unraisablehook', None), + support.captured_stderr() as stderr): + formatunraisable(CustomError('oops!'), b'Error in %R', []) + lines = stderr.getvalue().splitlines() + self.assertEqual(lines[0], f'Error in []:') + self.assertEqual(lines[1], 'Traceback (most recent call last):') + self.assertEqual(lines[-1], f'{__name__}.CustomError: oops!') + + with (support.swap_attr(sys, 'unraisablehook', None), + support.captured_stderr() as stderr): + formatunraisable(CustomError('oops!'), b'undecodable \xff') + lines = stderr.getvalue().splitlines() + self.assertEqual(lines[0], 'Traceback (most recent call last):') + self.assertEqual(lines[-1], f'{__name__}.CustomError: oops!') + + with (support.swap_attr(sys, 'unraisablehook', None), + support.captured_stderr() as stderr): + formatunraisable(CustomError('oops!'), NULL) + lines = stderr.getvalue().splitlines() + self.assertEqual(lines[0], 'Traceback (most recent call last):') + self.assertEqual(lines[-1], f'{__name__}.CustomError: oops!') + + # CRASHES formatunraisable(NULL, b'Error in %R', []) + # CRASHES formatunraisable(NULL, NULL) + class Test_PyUnstable_Exc_PrepReraiseStar(ExceptionIsLikeMixin, unittest.TestCase): diff --git a/Lib/test/test_capi/test_float.py b/Lib/test/test_capi/test_float.py new file mode 100644 index 00000000000000..cb94d562645916 --- /dev/null +++ b/Lib/test/test_capi/test_float.py @@ -0,0 +1,182 @@ +import math +import sys +import unittest +import warnings + +from test.test_capi.test_getargs import (Float, FloatSubclass, FloatSubclass2, + BadIndex2, BadFloat2, Index, BadIndex, + BadFloat) +from test.support import import_helper + +_testcapi = import_helper.import_module('_testcapi') + +NULL = None + +# For PyFloat_Pack/Unpack* +BIG_ENDIAN = 0 +LITTLE_ENDIAN = 1 +EPSILON = { + 2: 2.0 ** -11, # binary16 + 4: 2.0 ** -24, # binary32 + 8: 2.0 ** -53, # binary64 +} + +HAVE_IEEE_754 = float.__getformat__("double").startswith("IEEE") +INF = float("inf") +NAN = float("nan") + + +class CAPIFloatTest(unittest.TestCase): + def test_check(self): + # Test PyFloat_Check() + check = _testcapi.float_check + + self.assertTrue(check(4.25)) + self.assertTrue(check(FloatSubclass(4.25))) + self.assertFalse(check(Float())) + self.assertFalse(check(3)) + self.assertFalse(check(object())) + + # CRASHES check(NULL) + + def test_checkexact(self): + # Test PyFloat_CheckExact() + checkexact = _testcapi.float_checkexact + + self.assertTrue(checkexact(4.25)) + self.assertFalse(checkexact(FloatSubclass(4.25))) + self.assertFalse(checkexact(Float())) + self.assertFalse(checkexact(3)) + self.assertFalse(checkexact(object())) + + # CRASHES checkexact(NULL) + + def test_fromstring(self): + # Test PyFloat_FromString() + fromstring = _testcapi.float_fromstring + + self.assertEqual(fromstring("4.25"), 4.25) + self.assertEqual(fromstring(b"4.25"), 4.25) + self.assertRaises(ValueError, fromstring, "4.25\0") + self.assertRaises(ValueError, fromstring, b"4.25\0") + + self.assertEqual(fromstring(bytearray(b"4.25")), 4.25) + + self.assertEqual(fromstring(memoryview(b"4.25")), 4.25) + self.assertEqual(fromstring(memoryview(b"4.255")[:-1]), 4.25) + self.assertRaises(TypeError, fromstring, memoryview(b"4.25")[::2]) + + self.assertRaises(TypeError, fromstring, 4.25) + + # CRASHES fromstring(NULL) + + def test_fromdouble(self): + # Test PyFloat_FromDouble() + fromdouble = _testcapi.float_fromdouble + + self.assertEqual(fromdouble(4.25), 4.25) + + def test_asdouble(self): + # Test PyFloat_AsDouble() + asdouble = _testcapi.float_asdouble + + class BadFloat3: + def __float__(self): + raise RuntimeError + + self.assertEqual(asdouble(4.25), 4.25) + self.assertEqual(asdouble(-1.0), -1.0) + self.assertEqual(asdouble(42), 42.0) + self.assertEqual(asdouble(-1), -1.0) + self.assertEqual(asdouble(2**1000), float(2**1000)) + + self.assertEqual(asdouble(FloatSubclass(4.25)), 4.25) + self.assertEqual(asdouble(FloatSubclass2(4.25)), 4.25) + self.assertEqual(asdouble(Index()), 99.) + + self.assertRaises(TypeError, asdouble, BadIndex()) + self.assertRaises(TypeError, asdouble, BadFloat()) + self.assertRaises(RuntimeError, asdouble, BadFloat3()) + with self.assertWarns(DeprecationWarning): + self.assertEqual(asdouble(BadIndex2()), 1.) + with self.assertWarns(DeprecationWarning): + self.assertEqual(asdouble(BadFloat2()), 4.25) + with warnings.catch_warnings(): + warnings.simplefilter("error", DeprecationWarning) + self.assertRaises(DeprecationWarning, asdouble, BadFloat2()) + self.assertRaises(TypeError, asdouble, object()) + self.assertRaises(TypeError, asdouble, NULL) + + def test_getinfo(self): + # Test PyFloat_GetInfo() + getinfo = _testcapi.float_getinfo + + self.assertEqual(getinfo(), sys.float_info) + + def test_getmax(self): + # Test PyFloat_GetMax() + getmax = _testcapi.float_getmax + + self.assertEqual(getmax(), sys.float_info.max) + + def test_getmin(self): + # Test PyFloat_GetMax() + getmin = _testcapi.float_getmin + + self.assertEqual(getmin(), sys.float_info.min) + + def test_pack(self): + # Test PyFloat_Pack2(), PyFloat_Pack4() and PyFloat_Pack8() + pack = _testcapi.float_pack + + self.assertEqual(pack(2, 1.5, BIG_ENDIAN), b'>\x00') + self.assertEqual(pack(4, 1.5, BIG_ENDIAN), b'?\xc0\x00\x00') + self.assertEqual(pack(8, 1.5, BIG_ENDIAN), + b'?\xf8\x00\x00\x00\x00\x00\x00') + self.assertEqual(pack(2, 1.5, LITTLE_ENDIAN), b'\x00>') + self.assertEqual(pack(4, 1.5, LITTLE_ENDIAN), b'\x00\x00\xc0?') + self.assertEqual(pack(8, 1.5, LITTLE_ENDIAN), + b'\x00\x00\x00\x00\x00\x00\xf8?') + + def test_unpack(self): + # Test PyFloat_Unpack2(), PyFloat_Unpack4() and PyFloat_Unpack8() + unpack = _testcapi.float_unpack + + self.assertEqual(unpack(b'>\x00', BIG_ENDIAN), 1.5) + self.assertEqual(unpack(b'?\xc0\x00\x00', BIG_ENDIAN), 1.5) + self.assertEqual(unpack(b'?\xf8\x00\x00\x00\x00\x00\x00', BIG_ENDIAN), + 1.5) + self.assertEqual(unpack(b'\x00>', LITTLE_ENDIAN), 1.5) + self.assertEqual(unpack(b'\x00\x00\xc0?', LITTLE_ENDIAN), 1.5) + self.assertEqual(unpack(b'\x00\x00\x00\x00\x00\x00\xf8?', LITTLE_ENDIAN), + 1.5) + + def test_pack_unpack_roundtrip(self): + pack = _testcapi.float_pack + unpack = _testcapi.float_unpack + + large = 2.0 ** 100 + values = [1.0, 1.5, large, 1.0/7, math.pi] + if HAVE_IEEE_754: + values.extend((INF, NAN)) + for value in values: + for size in (2, 4, 8,): + if size == 2 and value == large: + # too large for 16-bit float + continue + rel_tol = EPSILON[size] + for endian in (BIG_ENDIAN, LITTLE_ENDIAN): + with self.subTest(value=value, size=size, endian=endian): + data = pack(size, value, endian) + value2 = unpack(data, endian) + if math.isnan(value): + self.assertTrue(math.isnan(value2), (value, value2)) + elif size < 8: + self.assertTrue(math.isclose(value2, value, rel_tol=rel_tol), + (value, value2)) + else: + self.assertEqual(value2, value) + + +if __name__ == "__main__": + unittest.main() diff --git a/Lib/test/test_capi/test_getargs.py b/Lib/test/test_capi/test_getargs.py index 01bc30779add73..9b6aef27625ad0 100644 --- a/Lib/test/test_capi/test_getargs.py +++ b/Lib/test/test_capi/test_getargs.py @@ -55,6 +55,8 @@ LLONG_MIN = -2**63 ULLONG_MAX = 2**64-1 +NULL = None + class Index: def __index__(self): return 99 @@ -151,6 +153,8 @@ class TupleSubclass(tuple): class DictSubclass(dict): pass +NONCONTIG_WRITABLE = memoryview(bytearray(b'noncontig'))[::-2] +NONCONTIG_READONLY = memoryview(b'noncontig')[::-2] class Unsigned_TestCase(unittest.TestCase): def test_b(self): @@ -835,6 +839,8 @@ def test_y_star(self): self.assertEqual(getargs_y_star(bytearray(b'bytearray')), b'bytearray') self.assertEqual(getargs_y_star(memoryview(b'memoryview')), b'memoryview') self.assertRaises(TypeError, getargs_y_star, None) + self.assertRaises(BufferError, getargs_y_star, NONCONTIG_WRITABLE) + self.assertRaises(BufferError, getargs_y_star, NONCONTIG_READONLY) def test_y_hash(self): from _testcapi import getargs_y_hash @@ -844,6 +850,9 @@ def test_y_hash(self): self.assertRaises(TypeError, getargs_y_hash, bytearray(b'bytearray')) self.assertRaises(TypeError, getargs_y_hash, memoryview(b'memoryview')) self.assertRaises(TypeError, getargs_y_hash, None) + # TypeError: must be read-only bytes-like object, not memoryview + self.assertRaises(TypeError, getargs_y_hash, NONCONTIG_WRITABLE) + self.assertRaises(TypeError, getargs_y_hash, NONCONTIG_READONLY) def test_w_star(self): # getargs_w_star() modifies first and last byte @@ -859,6 +868,17 @@ def test_w_star(self): self.assertEqual(getargs_w_star(memoryview(buf)), b'[emoryvie]') self.assertEqual(buf, bytearray(b'[emoryvie]')) self.assertRaises(TypeError, getargs_w_star, None) + self.assertRaises(TypeError, getargs_w_star, NONCONTIG_WRITABLE) + self.assertRaises(TypeError, getargs_w_star, NONCONTIG_READONLY) + + def test_getargs_empty(self): + from _testcapi import getargs_empty + self.assertTrue(getargs_empty()) + self.assertRaises(TypeError, getargs_empty, 1) + self.assertRaises(TypeError, getargs_empty, 1, 2, 3) + self.assertRaises(TypeError, getargs_empty, a=1) + self.assertRaises(TypeError, getargs_empty, a=1, b=2) + self.assertRaises(TypeError, getargs_empty, 'x', 'y', 'z', a=1, b=2) class String_TestCase(unittest.TestCase): @@ -891,6 +911,8 @@ def test_s_star(self): self.assertEqual(getargs_s_star(bytearray(b'bytearray')), b'bytearray') self.assertEqual(getargs_s_star(memoryview(b'memoryview')), b'memoryview') self.assertRaises(TypeError, getargs_s_star, None) + self.assertRaises(BufferError, getargs_s_star, NONCONTIG_WRITABLE) + self.assertRaises(BufferError, getargs_s_star, NONCONTIG_READONLY) def test_s_hash(self): from _testcapi import getargs_s_hash @@ -900,6 +922,9 @@ def test_s_hash(self): self.assertRaises(TypeError, getargs_s_hash, bytearray(b'bytearray')) self.assertRaises(TypeError, getargs_s_hash, memoryview(b'memoryview')) self.assertRaises(TypeError, getargs_s_hash, None) + # TypeError: must be read-only bytes-like object, not memoryview + self.assertRaises(TypeError, getargs_s_hash, NONCONTIG_WRITABLE) + self.assertRaises(TypeError, getargs_s_hash, NONCONTIG_READONLY) def test_z(self): from _testcapi import getargs_z @@ -918,6 +943,8 @@ def test_z_star(self): self.assertEqual(getargs_z_star(bytearray(b'bytearray')), b'bytearray') self.assertEqual(getargs_z_star(memoryview(b'memoryview')), b'memoryview') self.assertIsNone(getargs_z_star(None)) + self.assertRaises(BufferError, getargs_z_star, NONCONTIG_WRITABLE) + self.assertRaises(BufferError, getargs_z_star, NONCONTIG_READONLY) def test_z_hash(self): from _testcapi import getargs_z_hash @@ -927,6 +954,9 @@ def test_z_hash(self): self.assertRaises(TypeError, getargs_z_hash, bytearray(b'bytearray')) self.assertRaises(TypeError, getargs_z_hash, memoryview(b'memoryview')) self.assertIsNone(getargs_z_hash(None)) + # TypeError: must be read-only bytes-like object, not memoryview + self.assertRaises(TypeError, getargs_z_hash, NONCONTIG_WRITABLE) + self.assertRaises(TypeError, getargs_z_hash, NONCONTIG_READONLY) def test_es(self): from _testcapi import getargs_es @@ -1004,70 +1034,6 @@ def test_et_hash(self): buf = bytearray() self.assertRaises(ValueError, getargs_et_hash, 'abc\xe9', 'latin1', buf) - @support.requires_legacy_unicode_capi - def test_u(self): - from _testcapi import getargs_u - with self.assertWarns(DeprecationWarning): - self.assertEqual(getargs_u('abc\xe9'), 'abc\xe9') - with self.assertWarns(DeprecationWarning): - self.assertRaises(ValueError, getargs_u, 'nul:\0') - with self.assertWarns(DeprecationWarning): - self.assertRaises(TypeError, getargs_u, b'bytes') - with self.assertWarns(DeprecationWarning): - self.assertRaises(TypeError, getargs_u, bytearray(b'bytearray')) - with self.assertWarns(DeprecationWarning): - self.assertRaises(TypeError, getargs_u, memoryview(b'memoryview')) - with self.assertWarns(DeprecationWarning): - self.assertRaises(TypeError, getargs_u, None) - - @support.requires_legacy_unicode_capi - def test_u_hash(self): - from _testcapi import getargs_u_hash - with self.assertWarns(DeprecationWarning): - self.assertEqual(getargs_u_hash('abc\xe9'), 'abc\xe9') - with self.assertWarns(DeprecationWarning): - self.assertEqual(getargs_u_hash('nul:\0'), 'nul:\0') - with self.assertWarns(DeprecationWarning): - self.assertRaises(TypeError, getargs_u_hash, b'bytes') - with self.assertWarns(DeprecationWarning): - self.assertRaises(TypeError, getargs_u_hash, bytearray(b'bytearray')) - with self.assertWarns(DeprecationWarning): - self.assertRaises(TypeError, getargs_u_hash, memoryview(b'memoryview')) - with self.assertWarns(DeprecationWarning): - self.assertRaises(TypeError, getargs_u_hash, None) - - @support.requires_legacy_unicode_capi - def test_Z(self): - from _testcapi import getargs_Z - with self.assertWarns(DeprecationWarning): - self.assertEqual(getargs_Z('abc\xe9'), 'abc\xe9') - with self.assertWarns(DeprecationWarning): - self.assertRaises(ValueError, getargs_Z, 'nul:\0') - with self.assertWarns(DeprecationWarning): - self.assertRaises(TypeError, getargs_Z, b'bytes') - with self.assertWarns(DeprecationWarning): - self.assertRaises(TypeError, getargs_Z, bytearray(b'bytearray')) - with self.assertWarns(DeprecationWarning): - self.assertRaises(TypeError, getargs_Z, memoryview(b'memoryview')) - with self.assertWarns(DeprecationWarning): - self.assertIsNone(getargs_Z(None)) - - @support.requires_legacy_unicode_capi - def test_Z_hash(self): - from _testcapi import getargs_Z_hash - with self.assertWarns(DeprecationWarning): - self.assertEqual(getargs_Z_hash('abc\xe9'), 'abc\xe9') - with self.assertWarns(DeprecationWarning): - self.assertEqual(getargs_Z_hash('nul:\0'), 'nul:\0') - with self.assertWarns(DeprecationWarning): - self.assertRaises(TypeError, getargs_Z_hash, b'bytes') - with self.assertWarns(DeprecationWarning): - self.assertRaises(TypeError, getargs_Z_hash, bytearray(b'bytearray')) - with self.assertWarns(DeprecationWarning): - self.assertRaises(TypeError, getargs_Z_hash, memoryview(b'memoryview')) - with self.assertWarns(DeprecationWarning): - self.assertIsNone(getargs_Z_hash(None)) - def test_gh_99240_clear_args(self): from _testcapi import gh_99240_clear_args self.assertRaises(TypeError, gh_99240_clear_args, 'a', '\0b') @@ -1224,6 +1190,27 @@ def test_parse_tuple_and_keywords(self): self.assertRaises(ValueError, _testcapi.parse_tuple_and_keywords, (), {}, '', [42]) + def test_basic(self): + parse = _testcapi.parse_tuple_and_keywords + + self.assertEqual(parse((), {'a': 1}, 'O', ['a']), (1,)) + self.assertEqual(parse((), {}, '|O', ['a']), (NULL,)) + self.assertEqual(parse((1, 2), {}, 'OO', ['a', 'b']), (1, 2)) + self.assertEqual(parse((1,), {'b': 2}, 'OO', ['a', 'b']), (1, 2)) + self.assertEqual(parse((), {'a': 1, 'b': 2}, 'OO', ['a', 'b']), (1, 2)) + self.assertEqual(parse((), {'b': 2}, '|OO', ['a', 'b']), (NULL, 2)) + + with self.assertRaisesRegex(TypeError, + "function missing required argument 'a'"): + parse((), {}, 'O', ['a']) + with self.assertRaisesRegex(TypeError, + "'b' is an invalid keyword argument"): + parse((), {'b': 1}, '|O', ['a']) + with self.assertRaisesRegex(TypeError, + fr"argument for function given by name \('a'\) " + fr"and position \(1\)"): + parse((1,), {'a': 2}, 'O|O', ['a', 'b']) + def test_bad_use(self): # Test handling invalid format and keywords in # PyArg_ParseTupleAndKeywords() @@ -1251,20 +1238,23 @@ def test_bad_use(self): def test_positional_only(self): parse = _testcapi.parse_tuple_and_keywords - parse((1, 2, 3), {}, 'OOO', ['', '', 'a']) - parse((1, 2), {'a': 3}, 'OOO', ['', '', 'a']) + self.assertEqual(parse((1, 2, 3), {}, 'OOO', ['', '', 'a']), (1, 2, 3)) + self.assertEqual(parse((1, 2), {'a': 3}, 'OOO', ['', '', 'a']), (1, 2, 3)) with self.assertRaisesRegex(TypeError, r'function takes at least 2 positional arguments \(1 given\)'): parse((1,), {'a': 3}, 'OOO', ['', '', 'a']) - parse((1,), {}, 'O|OO', ['', '', 'a']) + self.assertEqual(parse((1,), {}, 'O|OO', ['', '', 'a']), + (1, NULL, NULL)) with self.assertRaisesRegex(TypeError, r'function takes at least 1 positional argument \(0 given\)'): parse((), {}, 'O|OO', ['', '', 'a']) - parse((1, 2), {'a': 3}, 'OO$O', ['', '', 'a']) + self.assertEqual(parse((1, 2), {'a': 3}, 'OO$O', ['', '', 'a']), + (1, 2, 3)) with self.assertRaisesRegex(TypeError, r'function takes exactly 2 positional arguments \(1 given\)'): parse((1,), {'a': 3}, 'OO$O', ['', '', 'a']) - parse((1,), {}, 'O|O$O', ['', '', 'a']) + self.assertEqual(parse((1,), {}, 'O|O$O', ['', '', 'a']), + (1, NULL, NULL)) with self.assertRaisesRegex(TypeError, r'function takes at least 1 positional argument \(0 given\)'): parse((), {}, 'O|O$O', ['', '', 'a']) @@ -1273,11 +1263,84 @@ def test_positional_only(self): with self.assertRaisesRegex(SystemError, 'Empty keyword'): parse((1,), {}, 'O|OO', ['', 'a', '']) + def test_nonascii_keywords(self): + parse = _testcapi.parse_tuple_and_keywords + + for name in ('a', 'ä', 'Å·', 'ã··', 'ð€€'): + with self.subTest(name=name): + self.assertEqual(parse((), {name: 1}, 'O', [name]), (1,)) + self.assertEqual(parse((), {}, '|O', [name]), (NULL,)) + with self.assertRaisesRegex(TypeError, + f"function missing required argument '{name}'"): + parse((), {}, 'O', [name]) + with self.assertRaisesRegex(TypeError, + fr"argument for function given by name \('{name}'\) " + fr"and position \(1\)"): + parse((1,), {name: 2}, 'O|O', [name, 'b']) + with self.assertRaisesRegex(TypeError, + f"'{name}' is an invalid keyword argument"): + parse((), {name: 1}, '|O', ['b']) + with self.assertRaisesRegex(TypeError, + "'b' is an invalid keyword argument"): + parse((), {'b': 1}, '|O', [name]) + + invalid = name.encode() + (name.encode()[:-1] or b'\x80') + self.assertEqual(parse((), {}, '|O', [invalid]), (NULL,)) + self.assertEqual(parse((1,), {'b': 2}, 'O|O', [invalid, 'b']), + (1, 2)) + with self.assertRaisesRegex(TypeError, + f"function missing required argument '{name}\ufffd'"): + parse((), {}, 'O', [invalid]) + with self.assertRaisesRegex(UnicodeDecodeError, + f"'utf-8' codec can't decode bytes? "): + parse((), {'b': 1}, '|OO', [invalid, 'b']) + with self.assertRaisesRegex(UnicodeDecodeError, + f"'utf-8' codec can't decode bytes? "): + parse((), {'b': 1}, '|O', [invalid]) + + for name2 in ('b', 'ë', 'ĉ', 'Ɐ', 'ð€'): + with self.subTest(name2=name2): + with self.assertRaisesRegex(TypeError, + f"'{name2}' is an invalid keyword argument"): + parse((), {name2: 1}, '|O', [name]) + + name2 = name.encode().decode('latin1') + if name2 != name: + with self.assertRaisesRegex(TypeError, + f"'{name2}' is an invalid keyword argument"): + parse((), {name2: 1}, '|O', [name]) + name3 = name + '3' + with self.assertRaisesRegex(TypeError, + f"'{name2}' is an invalid keyword argument"): + parse((), {name2: 1, name3: 2}, '|OO', [name, name3]) + + def test_nested_tuple(self): + parse = _testcapi.parse_tuple_and_keywords -class Test_testcapi(unittest.TestCase): - locals().update((name, getattr(_testcapi, name)) - for name in dir(_testcapi) - if name.startswith('test_') and name.endswith('_code')) + self.assertEqual(parse(((1, 2, 3),), {}, '(OOO)', ['a']), (1, 2, 3)) + self.assertEqual(parse((1, (2, 3), 4), {}, 'O(OO)O', ['a', 'b', 'c']), + (1, 2, 3, 4)) + parse(((1, 2, 3),), {}, '(iii)', ['a']) + + with self.assertRaisesRegex(TypeError, + "argument 1 must be sequence of length 2, not 3"): + parse(((1, 2, 3),), {}, '(ii)', ['a']) + with self.assertRaisesRegex(TypeError, + "argument 1 must be sequence of length 2, not 1"): + parse(((1,),), {}, '(ii)', ['a']) + with self.assertRaisesRegex(TypeError, + "argument 1 must be 2-item sequence, not int"): + parse((1,), {}, '(ii)', ['a']) + with self.assertRaisesRegex(TypeError, + "argument 1 must be 2-item sequence, not bytes"): + parse((b'ab',), {}, '(ii)', ['a']) + + for f in 'es', 'et', 'es#', 'et#': + with self.assertRaises(LookupError): # empty encoding "" + parse((('a',),), {}, '(' + f + ')', ['a']) + with self.assertRaisesRegex(TypeError, + "argument 1 must be sequence of length 1, not 0"): + parse(((),), {}, '(' + f + ')', ['a']) if __name__ == "__main__": diff --git a/Lib/test/test_capi/test_hash.py b/Lib/test/test_capi/test_hash.py new file mode 100644 index 00000000000000..8436da7c32df10 --- /dev/null +++ b/Lib/test/test_capi/test_hash.py @@ -0,0 +1,79 @@ +import sys +import unittest +from test.support import import_helper +_testcapi = import_helper.import_module('_testcapi') + + +SIZEOF_VOID_P = _testcapi.SIZEOF_VOID_P +SIZEOF_PY_HASH_T = SIZEOF_VOID_P + + +class CAPITest(unittest.TestCase): + def test_hash_getfuncdef(self): + # Test PyHash_GetFuncDef() + hash_getfuncdef = _testcapi.hash_getfuncdef + func_def = hash_getfuncdef() + + match func_def.name: + case "fnv": + self.assertEqual(func_def.hash_bits, 8 * SIZEOF_PY_HASH_T) + self.assertEqual(func_def.seed_bits, 16 * SIZEOF_PY_HASH_T) + case "siphash13": + self.assertEqual(func_def.hash_bits, 64) + self.assertEqual(func_def.seed_bits, 128) + case "siphash24": + self.assertEqual(func_def.hash_bits, 64) + self.assertEqual(func_def.seed_bits, 128) + case _: + self.fail(f"unknown function name: {func_def.name!r}") + + # compare with sys.hash_info + hash_info = sys.hash_info + self.assertEqual(func_def.name, hash_info.algorithm) + self.assertEqual(func_def.hash_bits, hash_info.hash_bits) + self.assertEqual(func_def.seed_bits, hash_info.seed_bits) + + def test_hash_pointer(self): + # Test Py_HashPointer() + hash_pointer = _testcapi.hash_pointer + + UHASH_T_MASK = ((2 ** (8 * SIZEOF_PY_HASH_T)) - 1) + HASH_T_MAX = (2 ** (8 * SIZEOF_PY_HASH_T - 1) - 1) + + def python_hash_pointer(x): + # Py_HashPointer() rotates the pointer bits by 4 bits to the right + x = (x >> 4) | ((x & 15) << (8 * SIZEOF_VOID_P - 4)) + + # Convert unsigned uintptr_t (Py_uhash_t) to signed Py_hash_t + if HASH_T_MAX < x: + x = (~x) + 1 + x &= UHASH_T_MASK + x = (~x) + 1 + return x + + if SIZEOF_VOID_P == 8: + values = ( + 0xABCDEF1234567890, + 0x1234567890ABCDEF, + 0xFEE4ABEDD1CECA5E, + ) + else: + values = ( + 0x12345678, + 0x1234ABCD, + 0xDEADCAFE, + ) + + for value in values: + expected = python_hash_pointer(value) + with self.subTest(value=value): + self.assertEqual(hash_pointer(value), expected, + f"hash_pointer({value:x}) = " + f"{hash_pointer(value):x} != {expected:x}") + + # Py_HashPointer(NULL) returns 0 + self.assertEqual(hash_pointer(0), 0) + + # Py_HashPointer((void*)(uintptr_t)-1) doesn't return -1 but -2 + VOID_P_MAX = -1 & (2 ** (8 * SIZEOF_VOID_P) - 1) + self.assertEqual(hash_pointer(VOID_P_MAX), -2) diff --git a/Lib/test/test_capi/test_list.py b/Lib/test/test_capi/test_list.py new file mode 100644 index 00000000000000..eb03d51d3def37 --- /dev/null +++ b/Lib/test/test_capi/test_list.py @@ -0,0 +1,344 @@ +import gc +import weakref +import unittest +from test.support import import_helper +from collections import UserList +_testcapi = import_helper.import_module('_testcapi') + +NULL = None +PY_SSIZE_T_MIN = _testcapi.PY_SSIZE_T_MIN +PY_SSIZE_T_MAX = _testcapi.PY_SSIZE_T_MAX + +class ListSubclass(list): + pass + + +class DelAppend: + def __init__(self, lst, item): + self.lst = lst + self.item = item + + def __del__(self): + self.lst.append(self.item) + + +class CAPITest(unittest.TestCase): + def test_check(self): + # Test PyList_Check() + check = _testcapi.list_check + self.assertTrue(check([1, 2])) + self.assertTrue(check([])) + self.assertTrue(check(ListSubclass([1, 2]))) + self.assertFalse(check({1: 2})) + self.assertFalse(check((1, 2))) + self.assertFalse(check(42)) + self.assertFalse(check(object())) + + # CRASHES check(NULL) + + + def test_list_check_exact(self): + # Test PyList_CheckExact() + check = _testcapi.list_check_exact + self.assertTrue(check([1])) + self.assertTrue(check([])) + self.assertFalse(check(ListSubclass([1]))) + self.assertFalse(check(UserList([1, 2]))) + self.assertFalse(check({1: 2})) + self.assertFalse(check(object())) + + # CRASHES check(NULL) + + def test_list_new(self): + # Test PyList_New() + list_new = _testcapi.list_new + lst = list_new(0) + self.assertEqual(lst, []) + self.assertIs(type(lst), list) + lst2 = list_new(0) + self.assertIsNot(lst2, lst) + self.assertRaises(SystemError, list_new, NULL) + self.assertRaises(SystemError, list_new, -1) + + def test_list_size(self): + # Test PyList_Size() + size = _testcapi.list_size + self.assertEqual(size([1, 2]), 2) + self.assertEqual(size(ListSubclass([1, 2])), 2) + self.assertRaises(SystemError, size, UserList()) + self.assertRaises(SystemError, size, {}) + self.assertRaises(SystemError, size, 23) + self.assertRaises(SystemError, size, object()) + # CRASHES size(NULL) + + def test_list_get_size(self): + # Test PyList_GET_SIZE() + size = _testcapi.list_get_size + self.assertEqual(size([1, 2]), 2) + self.assertEqual(size(ListSubclass([1, 2])), 2) + # CRASHES size(object()) + # CRASHES size(23) + # CRASHES size({}) + # CRASHES size(UserList()) + # CRASHES size(NULL) + + + def test_list_getitem(self): + # Test PyList_GetItem() + getitem = _testcapi.list_getitem + lst = [1, 2, 3] + self.assertEqual(getitem(lst, 0), 1) + self.assertEqual(getitem(lst, 2), 3) + self.assertRaises(IndexError, getitem, lst, 3) + self.assertRaises(IndexError, getitem, lst, -1) + self.assertRaises(IndexError, getitem, lst, PY_SSIZE_T_MIN) + self.assertRaises(IndexError, getitem, lst, PY_SSIZE_T_MAX) + self.assertRaises(SystemError, getitem, 42, 1) + self.assertRaises(SystemError, getitem, (1, 2, 3), 1) + self.assertRaises(SystemError, getitem, {1: 2}, 1) + + # CRASHES getitem(NULL, 1) + + def test_list_get_item(self): + # Test PyList_GET_ITEM() + get_item = _testcapi.list_get_item + lst = [1, 2, [1, 2, 3]] + self.assertEqual(get_item(lst, 0), 1) + self.assertEqual(get_item(lst, 2), [1, 2, 3]) + + # CRASHES for out of index: get_item(lst, 3) + # CRASHES for get_item(lst, PY_SSIZE_T_MIN) + # CRASHES for get_item(lst, PY_SSIZE_T_MAX) + # CRASHES get_item(21, 2) + # CRASHES get_item(NULL, 1) + + + def test_list_setitem(self): + # Test PyList_SetItem() + setitem = _testcapi.list_setitem + lst = [1, 2, 3] + setitem(lst, 0, 10) + self.assertEqual(lst, [10, 2, 3]) + setitem(lst, 2, 12) + self.assertEqual(lst, [10, 2, 12]) + self.assertRaises(IndexError, setitem, lst, 3 , 5) + self.assertRaises(IndexError, setitem, lst, -1, 5) + self.assertRaises(IndexError, setitem, lst, PY_SSIZE_T_MIN, 5) + self.assertRaises(IndexError, setitem, lst, PY_SSIZE_T_MAX, 5) + self.assertRaises(SystemError, setitem, (1, 2, 3), 1, 5) + self.assertRaises(SystemError, setitem, {1: 2}, 1, 5) + + # CRASHES setitem(NULL, 'a', 5) + + def test_list_set_item(self): + # Test PyList_SET_ITEM() + set_item = _testcapi.list_set_item + lst = [1, 2, 3] + set_item(lst, 1, 10) + set_item(lst, 2, [1, 2, 3]) + self.assertEqual(lst, [1, 10, [1, 2, 3]]) + + # CRASHES for set_item([1], -1, 5) + # CRASHES for set_item([1], PY_SSIZE_T_MIN, 5) + # CRASHES for set_item([1], PY_SSIZE_T_MAX, 5) + # CRASHES for set_item([], 0, 1) + # CRASHES for set_item(NULL, 0, 1) + + + def test_list_insert(self): + # Test PyList_Insert() + insert = _testcapi.list_insert + lst = [1, 2, 3] + insert(lst, 0, 23) + self.assertEqual(lst, [23, 1, 2, 3]) + insert(lst, -1, 22) + self.assertEqual(lst, [23, 1, 2, 22, 3]) + insert(lst, PY_SSIZE_T_MIN, 1) + self.assertEqual(lst[0], 1) + insert(lst, len(lst), 123) + self.assertEqual(lst[-1], 123) + insert(lst, len(lst)-1, 124) + self.assertEqual(lst[-2], 124) + insert(lst, PY_SSIZE_T_MAX, 223) + self.assertEqual(lst[-1], 223) + + self.assertRaises(SystemError, insert, (1, 2, 3), 1, 5) + self.assertRaises(SystemError, insert, {1: 2}, 1, 5) + + # CRASHES insert(NULL, 1, 5) + + def test_list_append(self): + # Test PyList_Append() + append = _testcapi.list_append + lst = [1, 2, 3] + append(lst, 10) + self.assertEqual(lst, [1, 2, 3, 10]) + append(lst, [4, 5]) + self.assertEqual(lst, [1, 2, 3, 10, [4, 5]]) + self.assertRaises(SystemError, append, lst, NULL) + self.assertRaises(SystemError, append, (), 0) + self.assertRaises(SystemError, append, 42, 0) + # CRASHES append(NULL, 0) + + def test_list_getslice(self): + # Test PyList_GetSlice() + getslice = _testcapi.list_getslice + lst = [1, 2, 3] + + # empty + self.assertEqual(getslice(lst, PY_SSIZE_T_MIN, 0), []) + self.assertEqual(getslice(lst, -1, 0), []) + self.assertEqual(getslice(lst, 3, PY_SSIZE_T_MAX), []) + + # slice + self.assertEqual(getslice(lst, 1, 3), [2, 3]) + + # whole + self.assertEqual(getslice(lst, 0, len(lst)), lst) + self.assertEqual(getslice(lst, 0, 100), lst) + self.assertEqual(getslice(lst, -100, 100), lst) + + self.assertRaises(SystemError, getslice, (1, 2, 3), 0, 0) + self.assertRaises(SystemError, getslice, 'abc', 0, 0) + self.assertRaises(SystemError, getslice, 42, 0, 0) + + # CRASHES getslice(NULL, 0, 0) + + def test_list_setslice(self): + # Test PyList_SetSlice() + list_setslice = _testcapi.list_setslice + def set_slice(lst, low, high, value): + lst = lst.copy() + self.assertEqual(list_setslice(lst, low, high, value), 0) + return lst + + # insert items + self.assertEqual(set_slice([], 0, 0, list("abc")), list("abc")) + self.assertEqual(set_slice([], PY_SSIZE_T_MIN, PY_SSIZE_T_MIN, list("abc")), list("abc")) + self.assertEqual(set_slice([], PY_SSIZE_T_MAX, PY_SSIZE_T_MAX, list("abc")), list("abc")) + lst = list("abc") + self.assertEqual(set_slice(lst, 0, 0, ["X"]), list("Xabc")) + self.assertEqual(set_slice(lst, 1, 1, list("XY")), list("aXYbc")) + self.assertEqual(set_slice(lst, len(lst), len(lst), ["X"]), list("abcX")) + # self.assertEqual(set_slice(lst, PY_SSIZE_T_MAX, PY_SSIZE_T_MAX, ["X"]), list("abcX")) + + # replace items + lst = list("abc") + self.assertEqual(set_slice(lst, -100, 1, list("X")), list("Xbc")) + self.assertEqual(set_slice(lst, 1, 2, list("X")), list("aXc")) + self.assertEqual(set_slice(lst, 1, 3, list("XY")), list("aXY")) + self.assertEqual(set_slice(lst, 0, 3, list("XYZ")), list("XYZ")) + + # delete items + lst = list("abcdef") + self.assertEqual(set_slice(lst, 0, len(lst), []), []) + self.assertEqual(set_slice(lst, -100, 100, []), []) + self.assertEqual(set_slice(lst, 1, 5, []), list("af")) + self.assertEqual(set_slice(lst, 3, len(lst), []), list("abc")) + + # delete items with NULL + lst = list("abcdef") + self.assertEqual(set_slice(lst, 0, len(lst), NULL), []) + self.assertEqual(set_slice(lst, 3, len(lst), NULL), list("abc")) + + self.assertRaises(SystemError, list_setslice, (), 0, 0, []) + self.assertRaises(SystemError, list_setslice, 42, 0, 0, []) + + # Item finalizer modify the list (clear the list) + lst = [] + lst.append(DelAppend(lst, 'zombie')) + self.assertEqual(list_setslice(lst, 0, len(lst), NULL), 0) + self.assertEqual(lst, ['zombie']) + + # Item finalizer modify the list (remove an list item) + lst = [] + lst.append(DelAppend(lst, 'zombie')) + lst.extend("abc") + self.assertEqual(list_setslice(lst, 0, 1, NULL), 0) + self.assertEqual(lst, ['a', 'b', 'c', 'zombie']) + + # CRASHES setslice(NULL, 0, 0, []) + + def test_list_sort(self): + # Test PyList_Sort() + sort = _testcapi.list_sort + lst = [4, 6, 7, 3, 1, 5, 9, 2, 0, 8] + sort(lst) + self.assertEqual(lst, list(range(10))) + + lst2 = ListSubclass([4, 6, 7, 3, 1, 5, 9, 2, 0, 8]) + sort(lst2) + self.assertEqual(lst2, list(range(10))) + + self.assertRaises(SystemError, sort, ()) + self.assertRaises(SystemError, sort, object()) + self.assertRaises(SystemError, sort, NULL) + + + def test_list_reverse(self): + # Test PyList_Reverse() + reverse = _testcapi.list_reverse + def list_reverse(lst): + self.assertEqual(reverse(lst), 0) + return lst + + self.assertEqual(list_reverse([]), []) + self.assertEqual(list_reverse([2, 5, 10]), [10, 5, 2]) + + self.assertRaises(SystemError, reverse, ()) + self.assertRaises(SystemError, reverse, object()) + self.assertRaises(SystemError, reverse, NULL) + + def test_list_astuple(self): + # Test PyList_AsTuple() + astuple = _testcapi.list_astuple + self.assertEqual(astuple([]), ()) + self.assertEqual(astuple([2, 5, 10]), (2, 5, 10)) + + self.assertRaises(SystemError, astuple, ()) + self.assertRaises(SystemError, astuple, object()) + self.assertRaises(SystemError, astuple, NULL) + + def test_list_clear(self): + # Test PyList_Clear() + list_clear = _testcapi.list_clear + + lst = [1, 2, 3] + self.assertEqual(list_clear(lst), 0) + self.assertEqual(lst, []) + + lst = [] + self.assertEqual(list_clear(lst), 0) + self.assertEqual(lst, []) + + self.assertRaises(SystemError, list_clear, ()) + self.assertRaises(SystemError, list_clear, object()) + + # Item finalizer modify the list + lst = [] + lst.append(DelAppend(lst, 'zombie')) + list_clear(lst) + self.assertEqual(lst, ['zombie']) + + # CRASHES list_clear(NULL) + + def test_list_extend(self): + # Test PyList_Extend() + list_extend = _testcapi.list_extend + + for other_type in (list, tuple, str, iter): + lst = list("ab") + arg = other_type("def") + self.assertEqual(list_extend(lst, arg), 0) + self.assertEqual(lst, list("abdef")) + + # PyList_Extend(lst, lst) + lst = list("abc") + self.assertEqual(list_extend(lst, lst), 0) + self.assertEqual(lst, list("abcabc")) + + self.assertRaises(TypeError, list_extend, [], object()) + self.assertRaises(SystemError, list_extend, (), list("abc")) + + # CRASHES list_extend(NULL, []) + # CRASHES list_extend([], NULL) diff --git a/Lib/test/test_capi/test_long.py b/Lib/test/test_capi/test_long.py index 8928fd94a1d6a3..8e3ef25d1ff86f 100644 --- a/Lib/test/test_capi/test_long.py +++ b/Lib/test/test_capi/test_long.py @@ -6,6 +6,25 @@ # Skip this test if the _testcapi module isn't available. _testcapi = import_helper.import_module('_testcapi') +NULL = None + +class IntSubclass(int): + pass + +class Index: + def __init__(self, value): + self.value = value + + def __index__(self): + return self.value + +# use __index__(), not __int__() +class MyIndexAndInt: + def __index__(self): + return 10 + def __int__(self): + return 22 + class LongTests(unittest.TestCase): @@ -34,6 +53,376 @@ def test_compact_known(self): self.assertEqual(_testcapi.call_long_compact_api(sys.maxsize), (False, -1)) + def test_long_check(self): + # Test PyLong_Check() + check = _testcapi.pylong_check + self.assertTrue(check(1)) + self.assertTrue(check(123456789012345678901234567890)) + self.assertTrue(check(-1)) + self.assertTrue(check(True)) + self.assertTrue(check(IntSubclass(1))) + self.assertFalse(check(1.0)) + self.assertFalse(check(object())) + # CRASHES check(NULL) + + def test_long_checkexact(self): + # Test PyLong_CheckExact() + check = _testcapi.pylong_checkexact + self.assertTrue(check(1)) + self.assertTrue(check(123456789012345678901234567890)) + self.assertTrue(check(-1)) + self.assertFalse(check(True)) + self.assertFalse(check(IntSubclass(1))) + self.assertFalse(check(1.0)) + self.assertFalse(check(object())) + # CRASHES check(NULL) + + def test_long_fromdouble(self): + # Test PyLong_FromDouble() + fromdouble = _testcapi.pylong_fromdouble + float_max = sys.float_info.max + for value in (5.0, 5.1, 5.9, -5.1, -5.9, 0.0, -0.0, float_max, -float_max): + with self.subTest(value=value): + self.assertEqual(fromdouble(value), int(value)) + self.assertRaises(OverflowError, fromdouble, float('inf')) + self.assertRaises(OverflowError, fromdouble, float('-inf')) + self.assertRaises(ValueError, fromdouble, float('nan')) + + def test_long_fromvoidptr(self): + # Test PyLong_FromVoidPtr() + fromvoidptr = _testcapi.pylong_fromvoidptr + obj = object() + x = fromvoidptr(obj) + y = fromvoidptr(NULL) + self.assertIsInstance(x, int) + self.assertGreaterEqual(x, 0) + self.assertIsInstance(y, int) + self.assertEqual(y, 0) + self.assertNotEqual(x, y) + + def test_long_fromstring(self): + # Test PyLong_FromString() + fromstring = _testcapi.pylong_fromstring + self.assertEqual(fromstring(b'123', 10), (123, 3)) + self.assertEqual(fromstring(b'cafe', 16), (0xcafe, 4)) + self.assertEqual(fromstring(b'xyz', 36), (44027, 3)) + self.assertEqual(fromstring(b'123', 0), (123, 3)) + self.assertEqual(fromstring(b'0xcafe', 0), (0xcafe, 6)) + self.assertRaises(ValueError, fromstring, b'cafe', 0) + self.assertEqual(fromstring(b'-123', 10), (-123, 4)) + self.assertEqual(fromstring(b' -123 ', 10), (-123, 6)) + self.assertEqual(fromstring(b'1_23', 10), (123, 4)) + self.assertRaises(ValueError, fromstring, b'- 123', 10) + self.assertRaises(ValueError, fromstring, b'', 10) + + self.assertRaises(ValueError, fromstring, b'123', 1) + self.assertRaises(ValueError, fromstring, b'123', -1) + self.assertRaises(ValueError, fromstring, b'123', 37) + + self.assertRaises(ValueError, fromstring, '١٢٣٤٥٦٧٨٩٠'.encode(), 0) + self.assertRaises(ValueError, fromstring, '١٢٣٤٥٦٧٨٩٠'.encode(), 16) + + self.assertEqual(fromstring(b'123\x00', 0), (123, 3)) + self.assertEqual(fromstring(b'123\x00456', 0), (123, 3)) + self.assertEqual(fromstring(b'123\x00', 16), (0x123, 3)) + self.assertEqual(fromstring(b'123\x00456', 16), (0x123, 3)) + + # CRASHES fromstring(NULL, 0) + # CRASHES fromstring(NULL, 16) + + def test_long_fromunicodeobject(self): + # Test PyLong_FromUnicodeObject() + fromunicodeobject = _testcapi.pylong_fromunicodeobject + self.assertEqual(fromunicodeobject('123', 10), 123) + self.assertEqual(fromunicodeobject('cafe', 16), 0xcafe) + self.assertEqual(fromunicodeobject('xyz', 36), 44027) + self.assertEqual(fromunicodeobject('123', 0), 123) + self.assertEqual(fromunicodeobject('0xcafe', 0), 0xcafe) + self.assertRaises(ValueError, fromunicodeobject, 'cafe', 0) + self.assertEqual(fromunicodeobject('-123', 10), -123) + self.assertEqual(fromunicodeobject(' -123 ', 10), -123) + self.assertEqual(fromunicodeobject('1_23', 10), 123) + self.assertRaises(ValueError, fromunicodeobject, '- 123', 10) + self.assertRaises(ValueError, fromunicodeobject, '', 10) + + self.assertRaises(ValueError, fromunicodeobject, '123', 1) + self.assertRaises(ValueError, fromunicodeobject, '123', -1) + self.assertRaises(ValueError, fromunicodeobject, '123', 37) + + self.assertEqual(fromunicodeobject('١٢٣٤٥٦٧٨٩٠', 0), 1234567890) + self.assertEqual(fromunicodeobject('١٢٣٤٥٦٧٨٩٠', 16), 0x1234567890) + + self.assertRaises(ValueError, fromunicodeobject, '123\x00', 0) + self.assertRaises(ValueError, fromunicodeobject, '123\x00456', 0) + self.assertRaises(ValueError, fromunicodeobject, '123\x00', 16) + self.assertRaises(ValueError, fromunicodeobject, '123\x00456', 16) + + # CRASHES fromunicodeobject(NULL, 0) + # CRASHES fromunicodeobject(NULL, 16) + + def test_long_asint(self): + # Test PyLong_AsInt() + PyLong_AsInt = _testcapi.PyLong_AsInt + from _testcapi import INT_MIN, INT_MAX + + # round trip (object -> int -> object) + for value in (INT_MIN, INT_MAX, -1, 0, 1, 123): + with self.subTest(value=value): + self.assertEqual(PyLong_AsInt(value), value) + self.assertEqual(PyLong_AsInt(IntSubclass(42)), 42) + self.assertEqual(PyLong_AsInt(Index(42)), 42) + self.assertEqual(PyLong_AsInt(MyIndexAndInt()), 10) + + # bound checking + self.assertRaises(OverflowError, PyLong_AsInt, INT_MIN - 1) + self.assertRaises(OverflowError, PyLong_AsInt, INT_MAX + 1) + + # invalid type + self.assertRaises(TypeError, PyLong_AsInt, 1.0) + self.assertRaises(TypeError, PyLong_AsInt, b'2') + self.assertRaises(TypeError, PyLong_AsInt, '3') + self.assertRaises(SystemError, PyLong_AsInt, NULL) + + def test_long_aslong(self): + # Test PyLong_AsLong() and PyLong_FromLong() + aslong = _testcapi.pylong_aslong + from _testcapi import LONG_MIN, LONG_MAX + # round trip (object -> long -> object) + for value in (LONG_MIN, LONG_MAX, -1, 0, 1, 1234): + with self.subTest(value=value): + self.assertEqual(aslong(value), value) + + self.assertEqual(aslong(IntSubclass(42)), 42) + self.assertEqual(aslong(Index(42)), 42) + self.assertEqual(aslong(MyIndexAndInt()), 10) + + self.assertRaises(OverflowError, aslong, LONG_MIN - 1) + self.assertRaises(OverflowError, aslong, LONG_MAX + 1) + self.assertRaises(TypeError, aslong, 1.0) + self.assertRaises(TypeError, aslong, b'2') + self.assertRaises(TypeError, aslong, '3') + self.assertRaises(SystemError, aslong, NULL) + + def test_long_aslongandoverflow(self): + # Test PyLong_AsLongAndOverflow() + aslongandoverflow = _testcapi.pylong_aslongandoverflow + from _testcapi import LONG_MIN, LONG_MAX + # round trip (object -> long -> object) + for value in (LONG_MIN, LONG_MAX, -1, 0, 1, 1234): + with self.subTest(value=value): + self.assertEqual(aslongandoverflow(value), (value, 0)) + + self.assertEqual(aslongandoverflow(IntSubclass(42)), (42, 0)) + self.assertEqual(aslongandoverflow(Index(42)), (42, 0)) + self.assertEqual(aslongandoverflow(MyIndexAndInt()), (10, 0)) + + self.assertEqual(aslongandoverflow(LONG_MIN - 1), (-1, -1)) + self.assertEqual(aslongandoverflow(LONG_MAX + 1), (-1, 1)) + # CRASHES aslongandoverflow(1.0) + # CRASHES aslongandoverflow(NULL) + + def test_long_asunsignedlong(self): + # Test PyLong_AsUnsignedLong() and PyLong_FromUnsignedLong() + asunsignedlong = _testcapi.pylong_asunsignedlong + from _testcapi import ULONG_MAX + # round trip (object -> unsigned long -> object) + for value in (ULONG_MAX, 0, 1, 1234): + with self.subTest(value=value): + self.assertEqual(asunsignedlong(value), value) + + self.assertEqual(asunsignedlong(IntSubclass(42)), 42) + self.assertRaises(TypeError, asunsignedlong, Index(42)) + self.assertRaises(TypeError, asunsignedlong, MyIndexAndInt()) + + self.assertRaises(OverflowError, asunsignedlong, -1) + self.assertRaises(OverflowError, asunsignedlong, ULONG_MAX + 1) + self.assertRaises(TypeError, asunsignedlong, 1.0) + self.assertRaises(TypeError, asunsignedlong, b'2') + self.assertRaises(TypeError, asunsignedlong, '3') + self.assertRaises(SystemError, asunsignedlong, NULL) + + def test_long_asunsignedlongmask(self): + # Test PyLong_AsUnsignedLongMask() + asunsignedlongmask = _testcapi.pylong_asunsignedlongmask + from _testcapi import ULONG_MAX + # round trip (object -> unsigned long -> object) + for value in (ULONG_MAX, 0, 1, 1234): + with self.subTest(value=value): + self.assertEqual(asunsignedlongmask(value), value) + + self.assertEqual(asunsignedlongmask(IntSubclass(42)), 42) + self.assertEqual(asunsignedlongmask(Index(42)), 42) + self.assertEqual(asunsignedlongmask(MyIndexAndInt()), 10) + + self.assertEqual(asunsignedlongmask(-1), ULONG_MAX) + self.assertEqual(asunsignedlongmask(ULONG_MAX + 1), 0) + self.assertRaises(TypeError, asunsignedlongmask, 1.0) + self.assertRaises(TypeError, asunsignedlongmask, b'2') + self.assertRaises(TypeError, asunsignedlongmask, '3') + self.assertRaises(SystemError, asunsignedlongmask, NULL) + + def test_long_aslonglong(self): + # Test PyLong_AsLongLong() and PyLong_FromLongLong() + aslonglong = _testcapi.pylong_aslonglong + from _testcapi import LLONG_MIN, LLONG_MAX + # round trip (object -> long long -> object) + for value in (LLONG_MIN, LLONG_MAX, -1, 0, 1, 1234): + with self.subTest(value=value): + self.assertEqual(aslonglong(value), value) + + self.assertEqual(aslonglong(IntSubclass(42)), 42) + self.assertEqual(aslonglong(Index(42)), 42) + self.assertEqual(aslonglong(MyIndexAndInt()), 10) + + self.assertRaises(OverflowError, aslonglong, LLONG_MIN - 1) + self.assertRaises(OverflowError, aslonglong, LLONG_MAX + 1) + self.assertRaises(TypeError, aslonglong, 1.0) + self.assertRaises(TypeError, aslonglong, b'2') + self.assertRaises(TypeError, aslonglong, '3') + self.assertRaises(SystemError, aslonglong, NULL) + + def test_long_aslonglongandoverflow(self): + # Test PyLong_AsLongLongAndOverflow() + aslonglongandoverflow = _testcapi.pylong_aslonglongandoverflow + from _testcapi import LLONG_MIN, LLONG_MAX + # round trip (object -> long long -> object) + for value in (LLONG_MIN, LLONG_MAX, -1, 0, 1, 1234): + with self.subTest(value=value): + self.assertEqual(aslonglongandoverflow(value), (value, 0)) + + self.assertEqual(aslonglongandoverflow(IntSubclass(42)), (42, 0)) + self.assertEqual(aslonglongandoverflow(Index(42)), (42, 0)) + self.assertEqual(aslonglongandoverflow(MyIndexAndInt()), (10, 0)) + + self.assertEqual(aslonglongandoverflow(LLONG_MIN - 1), (-1, -1)) + self.assertEqual(aslonglongandoverflow(LLONG_MAX + 1), (-1, 1)) + # CRASHES aslonglongandoverflow(1.0) + # CRASHES aslonglongandoverflow(NULL) + + def test_long_asunsignedlonglong(self): + # Test PyLong_AsUnsignedLongLong() and PyLong_FromUnsignedLongLong() + asunsignedlonglong = _testcapi.pylong_asunsignedlonglong + from _testcapi import ULLONG_MAX + # round trip (object -> unsigned long long -> object) + for value in (ULLONG_MAX, 0, 1, 1234): + with self.subTest(value=value): + self.assertEqual(asunsignedlonglong(value), value) + + self.assertEqual(asunsignedlonglong(IntSubclass(42)), 42) + self.assertRaises(TypeError, asunsignedlonglong, Index(42)) + self.assertRaises(TypeError, asunsignedlonglong, MyIndexAndInt()) + + self.assertRaises(OverflowError, asunsignedlonglong, -1) + self.assertRaises(OverflowError, asunsignedlonglong, ULLONG_MAX + 1) + self.assertRaises(TypeError, asunsignedlonglong, 1.0) + self.assertRaises(TypeError, asunsignedlonglong, b'2') + self.assertRaises(TypeError, asunsignedlonglong, '3') + self.assertRaises(SystemError, asunsignedlonglong, NULL) + + def test_long_asunsignedlonglongmask(self): + # Test PyLong_AsUnsignedLongLongMask() + asunsignedlonglongmask = _testcapi.pylong_asunsignedlonglongmask + from _testcapi import ULLONG_MAX + # round trip (object -> unsigned long long -> object) + for value in (ULLONG_MAX, 0, 1, 1234): + with self.subTest(value=value): + self.assertEqual(asunsignedlonglongmask(value), value) + + self.assertEqual(asunsignedlonglongmask(IntSubclass(42)), 42) + self.assertEqual(asunsignedlonglongmask(Index(42)), 42) + self.assertEqual(asunsignedlonglongmask(MyIndexAndInt()), 10) + + self.assertEqual(asunsignedlonglongmask(-1), ULLONG_MAX) + self.assertEqual(asunsignedlonglongmask(ULLONG_MAX + 1), 0) + self.assertRaises(TypeError, asunsignedlonglongmask, 1.0) + self.assertRaises(TypeError, asunsignedlonglongmask, b'2') + self.assertRaises(TypeError, asunsignedlonglongmask, '3') + self.assertRaises(SystemError, asunsignedlonglongmask, NULL) + + def test_long_as_ssize_t(self): + # Test PyLong_AsSsize_t() and PyLong_FromSsize_t() + as_ssize_t = _testcapi.pylong_as_ssize_t + from _testcapi import PY_SSIZE_T_MIN, PY_SSIZE_T_MAX + # round trip (object -> Py_ssize_t -> object) + for value in (PY_SSIZE_T_MIN, PY_SSIZE_T_MAX, -1, 0, 1, 1234): + with self.subTest(value=value): + self.assertEqual(as_ssize_t(value), value) + + self.assertEqual(as_ssize_t(IntSubclass(42)), 42) + self.assertRaises(TypeError, as_ssize_t, Index(42)) + self.assertRaises(TypeError, as_ssize_t, MyIndexAndInt()) + + self.assertRaises(OverflowError, as_ssize_t, PY_SSIZE_T_MIN - 1) + self.assertRaises(OverflowError, as_ssize_t, PY_SSIZE_T_MAX + 1) + self.assertRaises(TypeError, as_ssize_t, 1.0) + self.assertRaises(TypeError, as_ssize_t, b'2') + self.assertRaises(TypeError, as_ssize_t, '3') + self.assertRaises(SystemError, as_ssize_t, NULL) + + def test_long_as_size_t(self): + # Test PyLong_AsSize_t() and PyLong_FromSize_t() + as_size_t = _testcapi.pylong_as_size_t + from _testcapi import SIZE_MAX + # round trip (object -> size_t -> object) + for value in (SIZE_MAX, 0, 1, 1234): + with self.subTest(value=value): + self.assertEqual(as_size_t(value), value) + + self.assertEqual(as_size_t(IntSubclass(42)), 42) + self.assertRaises(TypeError, as_size_t, Index(42)) + self.assertRaises(TypeError, as_size_t, MyIndexAndInt()) + + self.assertRaises(OverflowError, as_size_t, -1) + self.assertRaises(OverflowError, as_size_t, SIZE_MAX + 1) + self.assertRaises(TypeError, as_size_t, 1.0) + self.assertRaises(TypeError, as_size_t, b'2') + self.assertRaises(TypeError, as_size_t, '3') + self.assertRaises(SystemError, as_size_t, NULL) + + def test_long_asdouble(self): + # Test PyLong_AsDouble() + asdouble = _testcapi.pylong_asdouble + MAX = int(sys.float_info.max) + for value in (-MAX, MAX, -1, 0, 1, 1234): + with self.subTest(value=value): + self.assertEqual(asdouble(value), float(value)) + self.assertIsInstance(asdouble(value), float) + + self.assertEqual(asdouble(IntSubclass(42)), 42.0) + self.assertRaises(TypeError, asdouble, Index(42)) + self.assertRaises(TypeError, asdouble, MyIndexAndInt()) + + self.assertRaises(OverflowError, asdouble, 2 * MAX) + self.assertRaises(OverflowError, asdouble, -2 * MAX) + self.assertRaises(TypeError, asdouble, 1.0) + self.assertRaises(TypeError, asdouble, b'2') + self.assertRaises(TypeError, asdouble, '3') + self.assertRaises(SystemError, asdouble, NULL) + + def test_long_asvoidptr(self): + # Test PyLong_AsVoidPtr() + fromvoidptr = _testcapi.pylong_fromvoidptr + asvoidptr = _testcapi.pylong_asvoidptr + obj = object() + x = fromvoidptr(obj) + y = fromvoidptr(NULL) + self.assertIs(asvoidptr(x), obj) + self.assertIs(asvoidptr(y), NULL) + self.assertIs(asvoidptr(IntSubclass(x)), obj) + + # negative values + M = (1 << _testcapi.SIZEOF_VOID_P * 8) + if x >= M//2: + self.assertIs(asvoidptr(x - M), obj) + if y >= M//2: + self.assertIs(asvoidptr(y - M), NULL) + + self.assertRaises(TypeError, asvoidptr, Index(x)) + self.assertRaises(TypeError, asvoidptr, object()) + self.assertRaises(OverflowError, asvoidptr, 2**1000) + self.assertRaises(OverflowError, asvoidptr, -2**1000) + # CRASHES asvoidptr(NULL) + if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_capi/test_mem.py b/Lib/test/test_capi/test_mem.py index 527000875b7241..04f17a9ec9e72a 100644 --- a/Lib/test/test_capi/test_mem.py +++ b/Lib/test/test_capi/test_mem.py @@ -112,6 +112,9 @@ def test_pyobject_forbidden_bytes_is_freed(self): def test_pyobject_freed_is_freed(self): self.check_pyobject_is_freed('check_pyobject_freed_is_freed') + # Python built with Py_TRACE_REFS fail with a fatal error in + # _PyRefchain_Trace() on memory allocation error. + @unittest.skipIf(support.Py_TRACE_REFS, 'cannot test Py_TRACE_REFS build') def test_set_nomemory(self): code = """if 1: import _testcapi @@ -149,6 +152,8 @@ class C(): pass self.assertGreaterEqual(count, i*5-2) +# Py_GIL_DISABLED requires mimalloc (not malloc) +@unittest.skipIf(support.Py_GIL_DISABLED, 'need malloc') class PyMemMallocDebugTests(PyMemDebugTests): PYTHONMALLOC = 'malloc_debug' @@ -158,6 +163,11 @@ class PyMemPymallocDebugTests(PyMemDebugTests): PYTHONMALLOC = 'pymalloc_debug' +@unittest.skipUnless(support.with_mimalloc(), 'need mimaloc') +class PyMemMimallocDebugTests(PyMemDebugTests): + PYTHONMALLOC = 'mimalloc_debug' + + @unittest.skipUnless(support.Py_DEBUG, 'need Py_DEBUG') class PyMemDefaultTests(PyMemDebugTests): # test default allocator of Python compiled in debug mode diff --git a/Lib/test/test_capi/test_misc.py b/Lib/test/test_capi/test_misc.py index e7cdd4be002a14..67fbef4f269814 100644 --- a/Lib/test/test_capi/test_misc.py +++ b/Lib/test/test_capi/test_misc.py @@ -2,12 +2,11 @@ # these are all functions _testcapi exports whose name begins with 'test_'. import _thread -from collections import OrderedDict, deque +from collections import deque import contextlib import importlib.machinery import importlib.util import json -import opcode import os import pickle import queue @@ -51,6 +50,8 @@ import _testinternalcapi +NULL = None + def decode_stderr(err): return err.decode('utf-8', 'replace').replace('\r', '') @@ -296,157 +297,132 @@ def test_getitem_with_error(self): # test _Py_CheckFunctionResult() instead. self.assertIn('returned a result with an exception set', err) + def test_buildvalue(self): + # Test Py_BuildValue() with object arguments + buildvalue = _testcapi.py_buildvalue + self.assertEqual(buildvalue(''), None) + self.assertEqual(buildvalue('()'), ()) + self.assertEqual(buildvalue('[]'), []) + self.assertEqual(buildvalue('{}'), {}) + self.assertEqual(buildvalue('()[]{}'), ((), [], {})) + self.assertEqual(buildvalue('O', 1), 1) + self.assertEqual(buildvalue('(O)', 1), (1,)) + self.assertEqual(buildvalue('[O]', 1), [1]) + self.assertRaises(SystemError, buildvalue, '{O}', 1) + self.assertEqual(buildvalue('OO', 1, 2), (1, 2)) + self.assertEqual(buildvalue('(OO)', 1, 2), (1, 2)) + self.assertEqual(buildvalue('[OO]', 1, 2), [1, 2]) + self.assertEqual(buildvalue('{OO}', 1, 2), {1: 2}) + self.assertEqual(buildvalue('{OOOO}', 1, 2, 3, 4), {1: 2, 3: 4}) + self.assertEqual(buildvalue('((O))', 1), ((1,),)) + self.assertEqual(buildvalue('((OO))', 1, 2), ((1, 2),)) + + self.assertEqual(buildvalue(' \t,:'), None) + self.assertEqual(buildvalue('O,', 1), 1) + self.assertEqual(buildvalue(' O ', 1), 1) + self.assertEqual(buildvalue('\tO\t', 1), 1) + self.assertEqual(buildvalue('O,O', 1, 2), (1, 2)) + self.assertEqual(buildvalue('O, O', 1, 2), (1, 2)) + self.assertEqual(buildvalue('O,\tO', 1, 2), (1, 2)) + self.assertEqual(buildvalue('O O', 1, 2), (1, 2)) + self.assertEqual(buildvalue('O\tO', 1, 2), (1, 2)) + self.assertEqual(buildvalue('(O,O)', 1, 2), (1, 2)) + self.assertEqual(buildvalue('(O, O,)', 1, 2), (1, 2)) + self.assertEqual(buildvalue(' ( O O ) ', 1, 2), (1, 2)) + self.assertEqual(buildvalue('\t(\tO\tO\t)\t', 1, 2), (1, 2)) + self.assertEqual(buildvalue('[O,O]', 1, 2), [1, 2]) + self.assertEqual(buildvalue('[O, O,]', 1, 2), [1, 2]) + self.assertEqual(buildvalue(' [ O O ] ', 1, 2), [1, 2]) + self.assertEqual(buildvalue(' [\tO\tO\t] ', 1, 2), [1, 2]) + self.assertEqual(buildvalue('{O:O}', 1, 2), {1: 2}) + self.assertEqual(buildvalue('{O:O,O:O}', 1, 2, 3, 4), {1: 2, 3: 4}) + self.assertEqual(buildvalue('{O: O, O: O,}', 1, 2, 3, 4), {1: 2, 3: 4}) + self.assertEqual(buildvalue(' { O O O O } ', 1, 2, 3, 4), {1: 2, 3: 4}) + self.assertEqual(buildvalue('\t{\tO\tO\tO\tO\t}\t', 1, 2, 3, 4), {1: 2, 3: 4}) + + self.assertRaises(SystemError, buildvalue, 'O', NULL) + self.assertRaises(SystemError, buildvalue, '(O)', NULL) + self.assertRaises(SystemError, buildvalue, '[O]', NULL) + self.assertRaises(SystemError, buildvalue, '{O}', NULL) + self.assertRaises(SystemError, buildvalue, 'OO', 1, NULL) + self.assertRaises(SystemError, buildvalue, 'OO', NULL, 2) + self.assertRaises(SystemError, buildvalue, '(OO)', 1, NULL) + self.assertRaises(SystemError, buildvalue, '(OO)', NULL, 2) + self.assertRaises(SystemError, buildvalue, '[OO]', 1, NULL) + self.assertRaises(SystemError, buildvalue, '[OO]', NULL, 2) + self.assertRaises(SystemError, buildvalue, '{OO}', 1, NULL) + self.assertRaises(SystemError, buildvalue, '{OO}', NULL, 2) + + def test_buildvalue_ints(self): + # Test Py_BuildValue() with integer arguments + buildvalue = _testcapi.py_buildvalue_ints + from _testcapi import SHRT_MIN, SHRT_MAX, USHRT_MAX, INT_MIN, INT_MAX, UINT_MAX + self.assertEqual(buildvalue('i', INT_MAX), INT_MAX) + self.assertEqual(buildvalue('i', INT_MIN), INT_MIN) + self.assertEqual(buildvalue('I', UINT_MAX), UINT_MAX) + + self.assertEqual(buildvalue('h', SHRT_MAX), SHRT_MAX) + self.assertEqual(buildvalue('h', SHRT_MIN), SHRT_MIN) + self.assertEqual(buildvalue('H', USHRT_MAX), USHRT_MAX) + + self.assertEqual(buildvalue('b', 127), 127) + self.assertEqual(buildvalue('b', -128), -128) + self.assertEqual(buildvalue('B', 255), 255) + + self.assertEqual(buildvalue('c', ord('A')), b'A') + self.assertEqual(buildvalue('c', 255), b'\xff') + self.assertEqual(buildvalue('c', 256), b'\x00') + self.assertEqual(buildvalue('c', -1), b'\xff') + + self.assertEqual(buildvalue('C', 255), chr(255)) + self.assertEqual(buildvalue('C', 256), chr(256)) + self.assertEqual(buildvalue('C', sys.maxunicode), chr(sys.maxunicode)) + self.assertRaises(ValueError, buildvalue, 'C', -1) + self.assertRaises(ValueError, buildvalue, 'C', sys.maxunicode+1) + + # gh-84489 + self.assertRaises(ValueError, buildvalue, '(C )i', -1, 2) + self.assertRaises(ValueError, buildvalue, '[C ]i', -1, 2) + self.assertRaises(ValueError, buildvalue, '{Ci }i', -1, 2, 3) + def test_buildvalue_N(self): _testcapi.test_buildvalue_N() - def test_mapping_keys_values_items(self): - class Mapping1(dict): - def keys(self): - return list(super().keys()) - def values(self): - return list(super().values()) - def items(self): - return list(super().items()) - class Mapping2(dict): - def keys(self): - return tuple(super().keys()) - def values(self): - return tuple(super().values()) - def items(self): - return tuple(super().items()) - dict_obj = {'foo': 1, 'bar': 2, 'spam': 3} - - for mapping in [{}, OrderedDict(), Mapping1(), Mapping2(), - dict_obj, OrderedDict(dict_obj), - Mapping1(dict_obj), Mapping2(dict_obj)]: - self.assertListEqual(_testcapi.get_mapping_keys(mapping), - list(mapping.keys())) - self.assertListEqual(_testcapi.get_mapping_values(mapping), - list(mapping.values())) - self.assertListEqual(_testcapi.get_mapping_items(mapping), - list(mapping.items())) - - def test_mapping_keys_values_items_bad_arg(self): - self.assertRaises(AttributeError, _testcapi.get_mapping_keys, None) - self.assertRaises(AttributeError, _testcapi.get_mapping_values, None) - self.assertRaises(AttributeError, _testcapi.get_mapping_items, None) - - class BadMapping: - def keys(self): - return None - def values(self): - return None - def items(self): - return None - bad_mapping = BadMapping() - self.assertRaises(TypeError, _testcapi.get_mapping_keys, bad_mapping) - self.assertRaises(TypeError, _testcapi.get_mapping_values, bad_mapping) - self.assertRaises(TypeError, _testcapi.get_mapping_items, bad_mapping) - - def test_mapping_has_key(self): - dct = {'a': 1} - self.assertTrue(_testcapi.mapping_has_key(dct, 'a')) - self.assertFalse(_testcapi.mapping_has_key(dct, 'b')) - - class SubDict(dict): - pass - - dct2 = SubDict({'a': 1}) - self.assertTrue(_testcapi.mapping_has_key(dct2, 'a')) - self.assertFalse(_testcapi.mapping_has_key(dct2, 'b')) - - def test_sequence_set_slice(self): - # Correct case: - data = [1, 2, 3, 4, 5] - data_copy = data.copy() - - _testcapi.sequence_set_slice(data, 1, 3, [8, 9]) - data_copy[1:3] = [8, 9] - self.assertEqual(data, data_copy) - self.assertEqual(data, [1, 8, 9, 4, 5]) - - # Custom class: - class Custom: - def __setitem__(self, index, value): - self.index = index - self.value = value - - c = Custom() - _testcapi.sequence_set_slice(c, 0, 5, 'abc') - self.assertEqual(c.index, slice(0, 5)) - self.assertEqual(c.value, 'abc') - - # Immutable sequences must raise: - bad_seq1 = (1, 2, 3, 4) - with self.assertRaises(TypeError): - _testcapi.sequence_set_slice(bad_seq1, 1, 3, (8, 9)) - self.assertEqual(bad_seq1, (1, 2, 3, 4)) - - bad_seq2 = 'abcd' - with self.assertRaises(TypeError): - _testcapi.sequence_set_slice(bad_seq2, 1, 3, 'xy') - self.assertEqual(bad_seq2, 'abcd') - - # Not a sequence: - with self.assertRaises(TypeError): - _testcapi.sequence_set_slice(None, 1, 3, 'xy') - - def test_sequence_del_slice(self): - # Correct case: - data = [1, 2, 3, 4, 5] - data_copy = data.copy() - - _testcapi.sequence_del_slice(data, 1, 3) - del data_copy[1:3] - self.assertEqual(data, data_copy) - self.assertEqual(data, [1, 4, 5]) - - # Custom class: - class Custom: - def __delitem__(self, index): - self.index = index - - c = Custom() - _testcapi.sequence_del_slice(c, 0, 5) - self.assertEqual(c.index, slice(0, 5)) - - # Immutable sequences must raise: - bad_seq1 = (1, 2, 3, 4) - with self.assertRaises(TypeError): - _testcapi.sequence_del_slice(bad_seq1, 1, 3) - self.assertEqual(bad_seq1, (1, 2, 3, 4)) - - bad_seq2 = 'abcd' - with self.assertRaises(TypeError): - _testcapi.sequence_del_slice(bad_seq2, 1, 3) - self.assertEqual(bad_seq2, 'abcd') - - # Not a sequence: - with self.assertRaises(TypeError): - _testcapi.sequence_del_slice(None, 1, 3) - - mapping = {1: 'a', 2: 'b', 3: 'c'} - with self.assertRaises(KeyError): - _testcapi.sequence_del_slice(mapping, 1, 3) - self.assertEqual(mapping, {1: 'a', 2: 'b', 3: 'c'}) + def check_negative_refcount(self, code): + # bpo-35059: Check that Py_DECREF() reports the correct filename + # when calling _Py_NegativeRefcount() to abort Python. + code = textwrap.dedent(code) + rc, out, err = assert_python_failure('-c', code) + self.assertRegex(err, + br'_testcapimodule\.c:[0-9]+: ' + br'_Py_NegativeRefcount: Assertion failed: ' + br'object has negative ref count') @unittest.skipUnless(hasattr(_testcapi, 'negative_refcount'), - 'need _testcapi.negative_refcount') + 'need _testcapi.negative_refcount()') def test_negative_refcount(self): - # bpo-35059: Check that Py_DECREF() reports the correct filename - # when calling _Py_NegativeRefcount() to abort Python. - code = textwrap.dedent(""" + code = """ import _testcapi from test import support with support.SuppressCrashReport(): _testcapi.negative_refcount() - """) - rc, out, err = assert_python_failure('-c', code) - self.assertRegex(err, - br'_testcapimodule\.c:[0-9]+: ' - br'_Py_NegativeRefcount: Assertion failed: ' - br'object has negative ref count') + """ + self.check_negative_refcount(code) + + @unittest.skipUnless(hasattr(_testcapi, 'decref_freed_object'), + 'need _testcapi.decref_freed_object()') + @support.skip_if_sanitizer("use after free on purpose", + address=True, memory=True, ub=True) + def test_decref_freed_object(self): + code = """ + import _testcapi + from test import support + + with support.SuppressCrashReport(): + _testcapi.decref_freed_object() + """ + self.check_negative_refcount(code) def test_trashcan_subclass(self): # bpo-35983: Check that the trashcan mechanism for "list" is NOT @@ -493,6 +469,8 @@ def __del__(self): del L self.assertEqual(PyList.num, 0) + @unittest.skipIf(MISSING_C_DOCSTRINGS, + "Signature information for builtins requires docstrings") def test_heap_ctype_doc_and_text_signature(self): self.assertEqual(_testcapi.HeapDocCType.__doc__, "somedoc") self.assertEqual(_testcapi.HeapDocCType.__text_signature__, "(arg1, arg2)") @@ -740,7 +718,7 @@ class Base(metaclass=metaclass): # Class creation from C with warnings_helper.check_warnings( - ('.*custom tp_new.*in Python 3.14.*', DeprecationWarning), + ('.* _testcapi.Subclass .* custom tp_new.*in Python 3.14.*', DeprecationWarning), ): sub = _testcapi.make_type_with_base(Base) self.assertTrue(issubclass(sub, Base)) @@ -1121,6 +1099,21 @@ class Data(_testcapi.ObjExtraData): del d.extra self.assertIsNone(d.extra) + def test_get_type_module_name(self): + from collections import OrderedDict + ht = _testcapi.get_heaptype_for_name() + for cls, expected in { + int: 'builtins', + OrderedDict: 'collections', + ht: '_testcapi', + }.items(): + with self.subTest(repr(cls)): + modname = _testinternalcapi.get_type_module_name(cls) + self.assertEqual(modname, expected) + + ht.__module__ = 'test_module' + modname = _testinternalcapi.get_type_module_name(ht) + self.assertEqual(modname, 'test_module') @requires_limited_api class TestHeapTypeRelative(unittest.TestCase): @@ -1535,6 +1528,7 @@ def test_isolated_subinterpreter(self): maxtext = 250 main_interpid = 0 interpid = _interpreters.create() + self.addCleanup(lambda: _interpreters.destroy(interpid)) _interpreters.run_string(interpid, f"""if True: import json import os @@ -2028,6 +2022,137 @@ def test_module_state_shared_in_global(self): self.assertEqual(main_attr_id, subinterp_attr_id) +@requires_subinterpreters +class InterpreterIDTests(unittest.TestCase): + + InterpreterID = _testcapi.get_interpreterid_type() + + def new_interpreter(self): + def ensure_destroyed(interpid): + try: + _interpreters.destroy(interpid) + except _interpreters.InterpreterNotFoundError: + pass + id = _interpreters.create() + self.addCleanup(lambda: ensure_destroyed(id)) + return id + + def test_with_int(self): + id = self.InterpreterID(10, force=True) + + self.assertEqual(int(id), 10) + + def test_coerce_id(self): + class Int(str): + def __index__(self): + return 10 + + id = self.InterpreterID(Int(), force=True) + self.assertEqual(int(id), 10) + + def test_bad_id(self): + for badid in [ + object(), + 10.0, + '10', + b'10', + ]: + with self.subTest(badid): + with self.assertRaises(TypeError): + self.InterpreterID(badid) + + badid = -1 + with self.subTest(badid): + with self.assertRaises(ValueError): + self.InterpreterID(badid) + + badid = 2**64 + with self.subTest(badid): + with self.assertRaises(OverflowError): + self.InterpreterID(badid) + + def test_exists(self): + id = self.new_interpreter() + with self.assertRaises(_interpreters.InterpreterNotFoundError): + self.InterpreterID(int(id) + 1) # unforced + + def test_does_not_exist(self): + id = self.new_interpreter() + with self.assertRaises(_interpreters.InterpreterNotFoundError): + self.InterpreterID(int(id) + 1) # unforced + + def test_destroyed(self): + id = _interpreters.create() + _interpreters.destroy(id) + with self.assertRaises(_interpreters.InterpreterNotFoundError): + self.InterpreterID(id) # unforced + + def test_str(self): + id = self.InterpreterID(10, force=True) + self.assertEqual(str(id), '10') + + def test_repr(self): + id = self.InterpreterID(10, force=True) + self.assertEqual(repr(id), 'InterpreterID(10)') + + def test_equality(self): + id1 = self.new_interpreter() + id2 = self.InterpreterID(id1) + id3 = self.InterpreterID( + self.new_interpreter()) + + self.assertTrue(id2 == id2) # identity + self.assertTrue(id2 == id1) # int-equivalent + self.assertTrue(id1 == id2) # reversed + self.assertTrue(id2 == int(id2)) + self.assertTrue(id2 == float(int(id2))) + self.assertTrue(float(int(id2)) == id2) + self.assertFalse(id2 == float(int(id2)) + 0.1) + self.assertFalse(id2 == str(int(id2))) + self.assertFalse(id2 == 2**1000) + self.assertFalse(id2 == float('inf')) + self.assertFalse(id2 == 'spam') + self.assertFalse(id2 == id3) + + self.assertFalse(id2 != id2) + self.assertFalse(id2 != id1) + self.assertFalse(id1 != id2) + self.assertTrue(id2 != id3) + + def test_linked_lifecycle(self): + id1 = _interpreters.create() + _testcapi.unlink_interpreter_refcount(id1) + self.assertEqual( + _testinternalcapi.get_interpreter_refcount(id1), + 0) + + id2 = self.InterpreterID(id1) + self.assertEqual( + _testinternalcapi.get_interpreter_refcount(id1), + 1) + + # The interpreter isn't linked to ID objects, so it isn't destroyed. + del id2 + self.assertEqual( + _testinternalcapi.get_interpreter_refcount(id1), + 0) + + _testcapi.link_interpreter_refcount(id1) + self.assertEqual( + _testinternalcapi.get_interpreter_refcount(id1), + 0) + + id3 = self.InterpreterID(id1) + self.assertEqual( + _testinternalcapi.get_interpreter_refcount(id1), + 1) + + # The interpreter is linked now so is destroyed. + del id3 + with self.assertRaises(_interpreters.InterpreterNotFoundError): + _testinternalcapi.get_interpreter_refcount(id1) + + class BuiltinStaticTypesTests(unittest.TestCase): TYPES = [ @@ -2142,7 +2267,7 @@ def test_gilstate_matches_current(self): class Test_testcapi(unittest.TestCase): locals().update((name, getattr(_testcapi, name)) for name in dir(_testcapi) - if name.startswith('test_') and not name.endswith('_code')) + if name.startswith('test_')) # Suppress warning from PyUnicode_FromUnicode(). @warnings_helper.ignore_warnings(category=DeprecationWarning) @@ -2156,7 +2281,15 @@ def test_version_api_data(self): class Test_testinternalcapi(unittest.TestCase): locals().update((name, getattr(_testinternalcapi, name)) for name in dir(_testinternalcapi) - if name.startswith('test_')) + if name.startswith('test_') + and not name.startswith('test_lock_')) + + +@threading_helper.requires_working_threading() +class Test_PyLock(unittest.TestCase): + locals().update((name, getattr(_testinternalcapi, name)) + for name in dir(_testinternalcapi) + if name.startswith('test_lock_')) @unittest.skipIf(_testmultiphase is None, "test requires _testmultiphase module") @@ -2351,361 +2484,60 @@ def func(): self.do_test(func, names) -@contextlib.contextmanager -def temporary_optimizer(opt): - old_opt = _testinternalcapi.get_optimizer() - _testinternalcapi.set_optimizer(opt) - try: - yield - finally: - _testinternalcapi.set_optimizer(old_opt) - +@unittest.skipUnless(support.Py_GIL_DISABLED, 'need Py_GIL_DISABLED') +class TestPyThreadId(unittest.TestCase): + def test_py_thread_id(self): + # gh-112535: Test _Py_ThreadId(): make sure that thread identifiers + # in a few threads are unique + py_thread_id = _testinternalcapi.py_thread_id + short_sleep = 0.010 -@contextlib.contextmanager -def clear_executors(func): - # Clear executors in func before and after running a block - func.__code__ = func.__code__.replace() - try: - yield - finally: - func.__code__ = func.__code__.replace() - - -class TestOptimizerAPI(unittest.TestCase): - - def test_get_set_optimizer(self): - old = _testinternalcapi.get_optimizer() - opt = _testinternalcapi.get_counter_optimizer() - try: - _testinternalcapi.set_optimizer(opt) - self.assertEqual(_testinternalcapi.get_optimizer(), opt) - _testinternalcapi.set_optimizer(None) - self.assertEqual(_testinternalcapi.get_optimizer(), None) - finally: - _testinternalcapi.set_optimizer(old) - - - def test_counter_optimizer(self): - # Generate a new function at each call - ns = {} - exec(textwrap.dedent(""" - def loop(): - for _ in range(1000): - pass - """), ns, ns) - loop = ns['loop'] - - for repeat in range(5): - opt = _testinternalcapi.get_counter_optimizer() - with temporary_optimizer(opt): - self.assertEqual(opt.get_count(), 0) - with clear_executors(loop): - loop() - self.assertEqual(opt.get_count(), 1000) - - def test_long_loop(self): - "Check that we aren't confused by EXTENDED_ARG" - - # Generate a new function at each call - ns = {} - exec(textwrap.dedent(""" - def nop(): - pass - - def long_loop(): - for _ in range(10): - nop(); nop(); nop(); nop(); nop(); nop(); nop(); nop(); - nop(); nop(); nop(); nop(); nop(); nop(); nop(); nop(); - nop(); nop(); nop(); nop(); nop(); nop(); nop(); nop(); - nop(); nop(); nop(); nop(); nop(); nop(); nop(); nop(); - nop(); nop(); nop(); nop(); nop(); nop(); nop(); nop(); - nop(); nop(); nop(); nop(); nop(); nop(); nop(); nop(); - nop(); nop(); nop(); nop(); nop(); nop(); nop(); nop(); - """), ns, ns) - long_loop = ns['long_loop'] - - opt = _testinternalcapi.get_counter_optimizer() - with temporary_optimizer(opt): - self.assertEqual(opt.get_count(), 0) - long_loop() - self.assertEqual(opt.get_count(), 10) - - -def get_first_executor(func): - code = func.__code__ - co_code = code.co_code - JUMP_BACKWARD = opcode.opmap["JUMP_BACKWARD"] - for i in range(0, len(co_code), 2): - if co_code[i] == JUMP_BACKWARD: - try: - return _testinternalcapi.get_executor(code, i) - except ValueError: - pass - return None - - -class TestUops(unittest.TestCase): - - def test_basic_loop(self): - def testfunc(x): - i = 0 - while i < x: - i += 1 - - opt = _testinternalcapi.get_uop_optimizer() - with temporary_optimizer(opt): - testfunc(1000) - - ex = get_first_executor(testfunc) - self.assertIsNotNone(ex) - uops = {opname for opname, _, _ in ex} - self.assertIn("SAVE_IP", uops) - self.assertIn("LOAD_FAST", uops) - - def test_extended_arg(self): - "Check EXTENDED_ARG handling in superblock creation" - ns = {} - exec(textwrap.dedent(""" - def many_vars(): - # 260 vars, so z9 should have index 259 - a0 = a1 = a2 = a3 = a4 = a5 = a6 = a7 = a8 = a9 = 42 - b0 = b1 = b2 = b3 = b4 = b5 = b6 = b7 = b8 = b9 = 42 - c0 = c1 = c2 = c3 = c4 = c5 = c6 = c7 = c8 = c9 = 42 - d0 = d1 = d2 = d3 = d4 = d5 = d6 = d7 = d8 = d9 = 42 - e0 = e1 = e2 = e3 = e4 = e5 = e6 = e7 = e8 = e9 = 42 - f0 = f1 = f2 = f3 = f4 = f5 = f6 = f7 = f8 = f9 = 42 - g0 = g1 = g2 = g3 = g4 = g5 = g6 = g7 = g8 = g9 = 42 - h0 = h1 = h2 = h3 = h4 = h5 = h6 = h7 = h8 = h9 = 42 - i0 = i1 = i2 = i3 = i4 = i5 = i6 = i7 = i8 = i9 = 42 - j0 = j1 = j2 = j3 = j4 = j5 = j6 = j7 = j8 = j9 = 42 - k0 = k1 = k2 = k3 = k4 = k5 = k6 = k7 = k8 = k9 = 42 - l0 = l1 = l2 = l3 = l4 = l5 = l6 = l7 = l8 = l9 = 42 - m0 = m1 = m2 = m3 = m4 = m5 = m6 = m7 = m8 = m9 = 42 - n0 = n1 = n2 = n3 = n4 = n5 = n6 = n7 = n8 = n9 = 42 - o0 = o1 = o2 = o3 = o4 = o5 = o6 = o7 = o8 = o9 = 42 - p0 = p1 = p2 = p3 = p4 = p5 = p6 = p7 = p8 = p9 = 42 - q0 = q1 = q2 = q3 = q4 = q5 = q6 = q7 = q8 = q9 = 42 - r0 = r1 = r2 = r3 = r4 = r5 = r6 = r7 = r8 = r9 = 42 - s0 = s1 = s2 = s3 = s4 = s5 = s6 = s7 = s8 = s9 = 42 - t0 = t1 = t2 = t3 = t4 = t5 = t6 = t7 = t8 = t9 = 42 - u0 = u1 = u2 = u3 = u4 = u5 = u6 = u7 = u8 = u9 = 42 - v0 = v1 = v2 = v3 = v4 = v5 = v6 = v7 = v8 = v9 = 42 - w0 = w1 = w2 = w3 = w4 = w5 = w6 = w7 = w8 = w9 = 42 - x0 = x1 = x2 = x3 = x4 = x5 = x6 = x7 = x8 = x9 = 42 - y0 = y1 = y2 = y3 = y4 = y5 = y6 = y7 = y8 = y9 = 42 - z0 = z1 = z2 = z3 = z4 = z5 = z6 = z7 = z8 = z9 = 42 - while z9 > 0: - z9 = z9 - 1 - """), ns, ns) - many_vars = ns["many_vars"] - - opt = _testinternalcapi.get_uop_optimizer() - with temporary_optimizer(opt): - ex = get_first_executor(many_vars) - self.assertIsNone(ex) - many_vars() - - ex = get_first_executor(many_vars) - self.assertIsNotNone(ex) - self.assertIn(("LOAD_FAST", 259, 0), list(ex)) - - def test_unspecialized_unpack(self): - # An example of an unspecialized opcode - def testfunc(x): - i = 0 - while i < x: - i += 1 - a, b = {1: 2, 3: 3} - assert a == 1 and b == 3 - i = 0 - while i < x: - i += 1 - - opt = _testinternalcapi.get_uop_optimizer() - - with temporary_optimizer(opt): - testfunc(10) - - ex = get_first_executor(testfunc) - self.assertIsNotNone(ex) - uops = {opname for opname, _, _ in ex} - self.assertIn("UNPACK_SEQUENCE", uops) - - def test_pop_jump_if_false(self): - def testfunc(n): - i = 0 - while i < n: - i += 1 - - opt = _testinternalcapi.get_uop_optimizer() - with temporary_optimizer(opt): - testfunc(10) - - ex = get_first_executor(testfunc) - self.assertIsNotNone(ex) - uops = {opname for opname, _, _ in ex} - self.assertIn("_POP_JUMP_IF_FALSE", uops) - - def test_pop_jump_if_none(self): - def testfunc(a): - for x in a: - if x is None: - x = 0 - - opt = _testinternalcapi.get_uop_optimizer() - with temporary_optimizer(opt): - testfunc([1, 2, 3]) - - ex = get_first_executor(testfunc) - self.assertIsNotNone(ex) - uops = {opname for opname, _, _ in ex} - self.assertIn("_POP_JUMP_IF_TRUE", uops) - - def test_pop_jump_if_not_none(self): - def testfunc(a): - for x in a: - if x is not None: - x = 0 - - opt = _testinternalcapi.get_uop_optimizer() - with temporary_optimizer(opt): - testfunc([1, 2, 3]) - - ex = get_first_executor(testfunc) - self.assertIsNotNone(ex) - uops = {opname for opname, _, _ in ex} - self.assertIn("_POP_JUMP_IF_FALSE", uops) - - def test_pop_jump_if_true(self): - def testfunc(n): - i = 0 - while not i >= n: - i += 1 - - opt = _testinternalcapi.get_uop_optimizer() - with temporary_optimizer(opt): - testfunc(10) - - ex = get_first_executor(testfunc) - self.assertIsNotNone(ex) - uops = {opname for opname, _, _ in ex} - self.assertIn("_POP_JUMP_IF_TRUE", uops) - - def test_jump_backward(self): - def testfunc(n): - i = 0 - while i < n: - i += 1 - - opt = _testinternalcapi.get_uop_optimizer() - with temporary_optimizer(opt): - testfunc(10) - - ex = get_first_executor(testfunc) - self.assertIsNotNone(ex) - uops = {opname for opname, _, _ in ex} - self.assertIn("JUMP_TO_TOP", uops) - - def test_jump_forward(self): - def testfunc(n): - a = 0 - while a < n: - if a < 0: - a = -a - else: - a = +a - a += 1 - return a - - opt = _testinternalcapi.get_uop_optimizer() - with temporary_optimizer(opt): - testfunc(10) - - ex = get_first_executor(testfunc) - self.assertIsNotNone(ex) - uops = {opname for opname, _, _ in ex} - # Since there is no JUMP_FORWARD instruction, - # look for indirect evidence: the += operator - self.assertIn("_BINARY_OP_ADD_INT", uops) - - def test_for_iter_range(self): - def testfunc(n): - total = 0 - for i in range(n): - total += i - return total - - opt = _testinternalcapi.get_uop_optimizer() - with temporary_optimizer(opt): - total = testfunc(10) - self.assertEqual(total, 45) - - ex = get_first_executor(testfunc) - self.assertIsNotNone(ex) - # for i, (opname, oparg) in enumerate(ex): - # print(f"{i:4d}: {opname:<20s} {oparg:3d}") - uops = {opname for opname, _, _ in ex} - self.assertIn("_IS_ITER_EXHAUSTED_RANGE", uops) - # Verification that the jump goes past END_FOR - # is done by manual inspection of the output - - def test_for_iter_list(self): - def testfunc(a): - total = 0 - for i in a: - total += i - return total - - opt = _testinternalcapi.get_uop_optimizer() - with temporary_optimizer(opt): - a = list(range(10)) - total = testfunc(a) - self.assertEqual(total, 45) - - ex = get_first_executor(testfunc) - self.assertIsNotNone(ex) - # for i, (opname, oparg) in enumerate(ex): - # print(f"{i:4d}: {opname:<20s} {oparg:3d}") - uops = {opname for opname, _, _ in ex} - self.assertIn("_IS_ITER_EXHAUSTED_LIST", uops) - # Verification that the jump goes past END_FOR - # is done by manual inspection of the output - - def test_for_iter_tuple(self): - def testfunc(a): - total = 0 - for i in a: - total += i - return total - - opt = _testinternalcapi.get_uop_optimizer() - with temporary_optimizer(opt): - a = tuple(range(10)) - total = testfunc(a) - self.assertEqual(total, 45) - - ex = get_first_executor(testfunc) - self.assertIsNotNone(ex) - # for i, (opname, oparg) in enumerate(ex): - # print(f"{i:4d}: {opname:<20s} {oparg:3d}") - uops = {opname for opname, _, _ in ex} - self.assertIn("_IS_ITER_EXHAUSTED_TUPLE", uops) - # Verification that the jump goes past END_FOR - # is done by manual inspection of the output - - def test_list_edge_case(self): - def testfunc(it): - for x in it: - pass + class GetThreadId(threading.Thread): + def __init__(self): + super().__init__() + self.get_lock = threading.Lock() + self.get_lock.acquire() + self.started_lock = threading.Event() + self.py_tid = None + + def run(self): + self.started_lock.set() + self.get_lock.acquire() + self.py_tid = py_thread_id() + time.sleep(short_sleep) + self.py_tid2 = py_thread_id() + + nthread = 5 + threads = [GetThreadId() for _ in range(nthread)] + + # first make run sure that all threads are running + for thread in threads: + thread.start() + for thread in threads: + thread.started_lock.wait() + + # call _Py_ThreadId() in the main thread + py_thread_ids = [py_thread_id()] + + # now call _Py_ThreadId() in each thread + for thread in threads: + thread.get_lock.release() + + # call _Py_ThreadId() in each thread and wait until threads complete + for thread in threads: + thread.join() + py_thread_ids.append(thread.py_tid) + # _PyThread_Id() should not change for a given thread. + # For example, it should remain the same after a short sleep. + self.assertEqual(thread.py_tid2, thread.py_tid) + + # make sure that all _Py_ThreadId() are unique + for tid in py_thread_ids: + self.assertIsInstance(tid, int) + self.assertGreater(tid, 0) + self.assertEqual(len(set(py_thread_ids)), len(py_thread_ids), + py_thread_ids) - opt = _testinternalcapi.get_uop_optimizer() - with temporary_optimizer(opt): - a = [1, 2, 3] - it = iter(a) - testfunc(it) - a.append(4) - with self.assertRaises(StopIteration): - next(it) if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_capi/test_opt.py b/Lib/test/test_capi/test_opt.py new file mode 100644 index 00000000000000..5c8c0596610303 --- /dev/null +++ b/Lib/test/test_capi/test_opt.py @@ -0,0 +1,545 @@ +import contextlib +import opcode +import textwrap +import unittest + +import _testinternalcapi + + +@contextlib.contextmanager +def temporary_optimizer(opt): + old_opt = _testinternalcapi.get_optimizer() + _testinternalcapi.set_optimizer(opt) + try: + yield + finally: + _testinternalcapi.set_optimizer(old_opt) + + +@contextlib.contextmanager +def clear_executors(func): + # Clear executors in func before and after running a block + func.__code__ = func.__code__.replace() + try: + yield + finally: + func.__code__ = func.__code__.replace() + + +class TestOptimizerAPI(unittest.TestCase): + + def test_get_counter_optimizer_dealloc(self): + # See gh-108727 + def f(): + _testinternalcapi.get_counter_optimizer() + + f() + + def test_get_set_optimizer(self): + old = _testinternalcapi.get_optimizer() + opt = _testinternalcapi.get_counter_optimizer() + try: + _testinternalcapi.set_optimizer(opt) + self.assertEqual(_testinternalcapi.get_optimizer(), opt) + _testinternalcapi.set_optimizer(None) + self.assertEqual(_testinternalcapi.get_optimizer(), None) + finally: + _testinternalcapi.set_optimizer(old) + + + def test_counter_optimizer(self): + # Generate a new function at each call + ns = {} + exec(textwrap.dedent(""" + def loop(): + for _ in range(1000): + pass + """), ns, ns) + loop = ns['loop'] + + for repeat in range(5): + opt = _testinternalcapi.get_counter_optimizer() + with temporary_optimizer(opt): + self.assertEqual(opt.get_count(), 0) + with clear_executors(loop): + loop() + self.assertEqual(opt.get_count(), 1000) + + def test_long_loop(self): + "Check that we aren't confused by EXTENDED_ARG" + + # Generate a new function at each call + ns = {} + exec(textwrap.dedent(""" + def nop(): + pass + + def long_loop(): + for _ in range(10): + nop(); nop(); nop(); nop(); nop(); nop(); nop(); nop(); + nop(); nop(); nop(); nop(); nop(); nop(); nop(); nop(); + nop(); nop(); nop(); nop(); nop(); nop(); nop(); nop(); + nop(); nop(); nop(); nop(); nop(); nop(); nop(); nop(); + nop(); nop(); nop(); nop(); nop(); nop(); nop(); nop(); + nop(); nop(); nop(); nop(); nop(); nop(); nop(); nop(); + nop(); nop(); nop(); nop(); nop(); nop(); nop(); nop(); + """), ns, ns) + long_loop = ns['long_loop'] + + opt = _testinternalcapi.get_counter_optimizer() + with temporary_optimizer(opt): + self.assertEqual(opt.get_count(), 0) + long_loop() + self.assertEqual(opt.get_count(), 10) + + def test_code_restore_for_ENTER_EXECUTOR(self): + def testfunc(x): + i = 0 + while i < x: + i += 1 + + opt = _testinternalcapi.get_counter_optimizer() + with temporary_optimizer(opt): + testfunc(1000) + code, replace_code = testfunc.__code__, testfunc.__code__.replace() + self.assertEqual(code, replace_code) + self.assertEqual(hash(code), hash(replace_code)) + + +def get_first_executor(func): + code = func.__code__ + co_code = code.co_code + JUMP_BACKWARD = opcode.opmap["JUMP_BACKWARD"] + for i in range(0, len(co_code), 2): + if co_code[i] == JUMP_BACKWARD: + try: + return _testinternalcapi.get_executor(code, i) + except ValueError: + pass + return None + + +class TestExecutorInvalidation(unittest.TestCase): + + def setUp(self): + self.old = _testinternalcapi.get_optimizer() + self.opt = _testinternalcapi.get_counter_optimizer() + _testinternalcapi.set_optimizer(self.opt) + + def tearDown(self): + _testinternalcapi.set_optimizer(self.old) + + def test_invalidate_object(self): + # Generate a new set of functions at each call + ns = {} + func_src = "\n".join( + f""" + def f{n}(): + for _ in range(1000): + pass + """ for n in range(5) + ) + exec(textwrap.dedent(func_src), ns, ns) + funcs = [ ns[f'f{n}'] for n in range(5)] + objects = [object() for _ in range(5)] + + for f in funcs: + f() + executors = [get_first_executor(f) for f in funcs] + # Set things up so each executor depends on the objects + # with an equal or lower index. + for i, exe in enumerate(executors): + self.assertTrue(exe.is_valid()) + for obj in objects[:i+1]: + _testinternalcapi.add_executor_dependency(exe, obj) + self.assertTrue(exe.is_valid()) + # Assert that the correct executors are invalidated + # and check that nothing crashes when we invalidate + # an executor mutliple times. + for i in (4,3,2,1,0): + _testinternalcapi.invalidate_executors(objects[i]) + for exe in executors[i:]: + self.assertFalse(exe.is_valid()) + for exe in executors[:i]: + self.assertTrue(exe.is_valid()) + + def test_uop_optimizer_invalidation(self): + # Generate a new function at each call + ns = {} + exec(textwrap.dedent(""" + def f(): + for i in range(1000): + pass + """), ns, ns) + f = ns['f'] + opt = _testinternalcapi.get_uop_optimizer() + with temporary_optimizer(opt): + f() + exe = get_first_executor(f) + self.assertIsNotNone(exe) + self.assertTrue(exe.is_valid()) + _testinternalcapi.invalidate_executors(f.__code__) + self.assertFalse(exe.is_valid()) + +class TestUops(unittest.TestCase): + + def test_basic_loop(self): + def testfunc(x): + i = 0 + while i < x: + i += 1 + + opt = _testinternalcapi.get_uop_optimizer() + with temporary_optimizer(opt): + testfunc(1000) + + ex = get_first_executor(testfunc) + self.assertIsNotNone(ex) + uops = {opname for opname, _, _ in ex} + self.assertIn("_SET_IP", uops) + self.assertIn("_LOAD_FAST", uops) + + def test_extended_arg(self): + "Check EXTENDED_ARG handling in superblock creation" + ns = {} + exec(textwrap.dedent(""" + def many_vars(): + # 260 vars, so z9 should have index 259 + a0 = a1 = a2 = a3 = a4 = a5 = a6 = a7 = a8 = a9 = 42 + b0 = b1 = b2 = b3 = b4 = b5 = b6 = b7 = b8 = b9 = 42 + c0 = c1 = c2 = c3 = c4 = c5 = c6 = c7 = c8 = c9 = 42 + d0 = d1 = d2 = d3 = d4 = d5 = d6 = d7 = d8 = d9 = 42 + e0 = e1 = e2 = e3 = e4 = e5 = e6 = e7 = e8 = e9 = 42 + f0 = f1 = f2 = f3 = f4 = f5 = f6 = f7 = f8 = f9 = 42 + g0 = g1 = g2 = g3 = g4 = g5 = g6 = g7 = g8 = g9 = 42 + h0 = h1 = h2 = h3 = h4 = h5 = h6 = h7 = h8 = h9 = 42 + i0 = i1 = i2 = i3 = i4 = i5 = i6 = i7 = i8 = i9 = 42 + j0 = j1 = j2 = j3 = j4 = j5 = j6 = j7 = j8 = j9 = 42 + k0 = k1 = k2 = k3 = k4 = k5 = k6 = k7 = k8 = k9 = 42 + l0 = l1 = l2 = l3 = l4 = l5 = l6 = l7 = l8 = l9 = 42 + m0 = m1 = m2 = m3 = m4 = m5 = m6 = m7 = m8 = m9 = 42 + n0 = n1 = n2 = n3 = n4 = n5 = n6 = n7 = n8 = n9 = 42 + o0 = o1 = o2 = o3 = o4 = o5 = o6 = o7 = o8 = o9 = 42 + p0 = p1 = p2 = p3 = p4 = p5 = p6 = p7 = p8 = p9 = 42 + q0 = q1 = q2 = q3 = q4 = q5 = q6 = q7 = q8 = q9 = 42 + r0 = r1 = r2 = r3 = r4 = r5 = r6 = r7 = r8 = r9 = 42 + s0 = s1 = s2 = s3 = s4 = s5 = s6 = s7 = s8 = s9 = 42 + t0 = t1 = t2 = t3 = t4 = t5 = t6 = t7 = t8 = t9 = 42 + u0 = u1 = u2 = u3 = u4 = u5 = u6 = u7 = u8 = u9 = 42 + v0 = v1 = v2 = v3 = v4 = v5 = v6 = v7 = v8 = v9 = 42 + w0 = w1 = w2 = w3 = w4 = w5 = w6 = w7 = w8 = w9 = 42 + x0 = x1 = x2 = x3 = x4 = x5 = x6 = x7 = x8 = x9 = 42 + y0 = y1 = y2 = y3 = y4 = y5 = y6 = y7 = y8 = y9 = 42 + z0 = z1 = z2 = z3 = z4 = z5 = z6 = z7 = z8 = z9 = 42 + while z9 > 0: + z9 = z9 - 1 + """), ns, ns) + many_vars = ns["many_vars"] + + opt = _testinternalcapi.get_uop_optimizer() + with temporary_optimizer(opt): + ex = get_first_executor(many_vars) + self.assertIsNone(ex) + many_vars() + + ex = get_first_executor(many_vars) + self.assertIsNotNone(ex) + self.assertIn(("_LOAD_FAST", 259, 0), list(ex)) + + def test_unspecialized_unpack(self): + # An example of an unspecialized opcode + def testfunc(x): + i = 0 + while i < x: + i += 1 + a, b = {1: 2, 3: 3} + assert a == 1 and b == 3 + i = 0 + while i < x: + i += 1 + + opt = _testinternalcapi.get_uop_optimizer() + + with temporary_optimizer(opt): + testfunc(20) + + ex = get_first_executor(testfunc) + self.assertIsNotNone(ex) + uops = {opname for opname, _, _ in ex} + self.assertIn("_UNPACK_SEQUENCE", uops) + + def test_pop_jump_if_false(self): + def testfunc(n): + i = 0 + while i < n: + i += 1 + + opt = _testinternalcapi.get_uop_optimizer() + with temporary_optimizer(opt): + testfunc(20) + + ex = get_first_executor(testfunc) + self.assertIsNotNone(ex) + uops = {opname for opname, _, _ in ex} + self.assertIn("_GUARD_IS_TRUE_POP", uops) + + def test_pop_jump_if_none(self): + def testfunc(a): + for x in a: + if x is None: + x = 0 + + opt = _testinternalcapi.get_uop_optimizer() + with temporary_optimizer(opt): + testfunc(range(20)) + + ex = get_first_executor(testfunc) + self.assertIsNotNone(ex) + uops = {opname for opname, _, _ in ex} + self.assertIn("_GUARD_IS_NOT_NONE_POP", uops) + + def test_pop_jump_if_not_none(self): + def testfunc(a): + for x in a: + x = None + if x is not None: + x = 0 + + opt = _testinternalcapi.get_uop_optimizer() + with temporary_optimizer(opt): + testfunc(range(20)) + + ex = get_first_executor(testfunc) + self.assertIsNotNone(ex) + uops = {opname for opname, _, _ in ex} + self.assertIn("_GUARD_IS_NONE_POP", uops) + + def test_pop_jump_if_true(self): + def testfunc(n): + i = 0 + while not i >= n: + i += 1 + + opt = _testinternalcapi.get_uop_optimizer() + with temporary_optimizer(opt): + testfunc(20) + + ex = get_first_executor(testfunc) + self.assertIsNotNone(ex) + uops = {opname for opname, _, _ in ex} + self.assertIn("_GUARD_IS_FALSE_POP", uops) + + def test_jump_backward(self): + def testfunc(n): + i = 0 + while i < n: + i += 1 + + opt = _testinternalcapi.get_uop_optimizer() + with temporary_optimizer(opt): + testfunc(20) + + ex = get_first_executor(testfunc) + self.assertIsNotNone(ex) + uops = {opname for opname, _, _ in ex} + self.assertIn("_JUMP_TO_TOP", uops) + + def test_jump_forward(self): + def testfunc(n): + a = 0 + while a < n: + if a < 0: + a = -a + else: + a = +a + a += 1 + return a + + opt = _testinternalcapi.get_uop_optimizer() + with temporary_optimizer(opt): + testfunc(20) + + ex = get_first_executor(testfunc) + self.assertIsNotNone(ex) + uops = {opname for opname, _, _ in ex} + # Since there is no JUMP_FORWARD instruction, + # look for indirect evidence: the += operator + self.assertIn("_BINARY_OP_ADD_INT", uops) + + def test_for_iter_range(self): + def testfunc(n): + total = 0 + for i in range(n): + total += i + return total + + opt = _testinternalcapi.get_uop_optimizer() + with temporary_optimizer(opt): + total = testfunc(20) + self.assertEqual(total, 190) + + ex = get_first_executor(testfunc) + self.assertIsNotNone(ex) + # for i, (opname, oparg) in enumerate(ex): + # print(f"{i:4d}: {opname:<20s} {oparg:3d}") + uops = {opname for opname, _, _ in ex} + self.assertIn("_GUARD_NOT_EXHAUSTED_RANGE", uops) + # Verification that the jump goes past END_FOR + # is done by manual inspection of the output + + def test_for_iter_list(self): + def testfunc(a): + total = 0 + for i in a: + total += i + return total + + opt = _testinternalcapi.get_uop_optimizer() + with temporary_optimizer(opt): + a = list(range(20)) + total = testfunc(a) + self.assertEqual(total, 190) + + ex = get_first_executor(testfunc) + self.assertIsNotNone(ex) + # for i, (opname, oparg) in enumerate(ex): + # print(f"{i:4d}: {opname:<20s} {oparg:3d}") + uops = {opname for opname, _, _ in ex} + self.assertIn("_GUARD_NOT_EXHAUSTED_LIST", uops) + # Verification that the jump goes past END_FOR + # is done by manual inspection of the output + + def test_for_iter_tuple(self): + def testfunc(a): + total = 0 + for i in a: + total += i + return total + + opt = _testinternalcapi.get_uop_optimizer() + with temporary_optimizer(opt): + a = tuple(range(20)) + total = testfunc(a) + self.assertEqual(total, 190) + + ex = get_first_executor(testfunc) + self.assertIsNotNone(ex) + # for i, (opname, oparg) in enumerate(ex): + # print(f"{i:4d}: {opname:<20s} {oparg:3d}") + uops = {opname for opname, _, _ in ex} + self.assertIn("_GUARD_NOT_EXHAUSTED_TUPLE", uops) + # Verification that the jump goes past END_FOR + # is done by manual inspection of the output + + def test_list_edge_case(self): + def testfunc(it): + for x in it: + pass + + opt = _testinternalcapi.get_uop_optimizer() + with temporary_optimizer(opt): + a = [1, 2, 3] + it = iter(a) + testfunc(it) + a.append(4) + with self.assertRaises(StopIteration): + next(it) + + def test_call_py_exact_args(self): + def testfunc(n): + def dummy(x): + return x+1 + for i in range(n): + dummy(i) + + opt = _testinternalcapi.get_uop_optimizer() + with temporary_optimizer(opt): + testfunc(20) + + ex = get_first_executor(testfunc) + self.assertIsNotNone(ex) + uops = {opname for opname, _, _ in ex} + self.assertIn("_PUSH_FRAME", uops) + self.assertIn("_BINARY_OP_ADD_INT", uops) + + def test_branch_taken(self): + def testfunc(n): + for i in range(n): + if i < 0: + i = 0 + else: + i = 1 + + opt = _testinternalcapi.get_uop_optimizer() + with temporary_optimizer(opt): + testfunc(20) + + ex = get_first_executor(testfunc) + self.assertIsNotNone(ex) + uops = {opname for opname, _, _ in ex} + self.assertIn("_GUARD_IS_FALSE_POP", uops) + + def test_for_iter_tier_two(self): + class MyIter: + def __init__(self, n): + self.n = n + def __iter__(self): + return self + def __next__(self): + self.n -= 1 + if self.n < 0: + raise StopIteration + return self.n + + def testfunc(n, m): + x = 0 + for i in range(m): + for j in MyIter(n): + x += 1000*i + j + return x + + opt = _testinternalcapi.get_uop_optimizer() + with temporary_optimizer(opt): + x = testfunc(10, 10) + + self.assertEqual(x, sum(range(10)) * 10010) + + ex = get_first_executor(testfunc) + self.assertIsNotNone(ex) + uops = {opname for opname, _, _ in ex} + self.assertIn("_FOR_ITER_TIER_TWO", uops) + + def test_confidence_score(self): + def testfunc(n): + bits = 0 + for i in range(n): + if i & 0x01: + bits += 1 + if i & 0x02: + bits += 1 + if i&0x04: + bits += 1 + if i&0x08: + bits += 1 + if i&0x10: + bits += 1 + if i&0x20: + bits += 1 + return bits + + opt = _testinternalcapi.get_uop_optimizer() + with temporary_optimizer(opt): + x = testfunc(20) + + self.assertEqual(x, 40) + ex = get_first_executor(testfunc) + self.assertIsNotNone(ex) + ops = [opname for opname, _, _ in ex] + count = ops.count("_GUARD_IS_TRUE_POP") + # Because Each 'if' halves the score, the second branch is + # too much already. + self.assertEqual(count, 1) + + +if __name__ == "__main__": + unittest.main() diff --git a/Lib/test/test_capi/test_pyatomic.py b/Lib/test/test_capi/test_pyatomic.py new file mode 100644 index 00000000000000..846d6d50c25969 --- /dev/null +++ b/Lib/test/test_capi/test_pyatomic.py @@ -0,0 +1,15 @@ +import unittest +from test.support import import_helper + +# Skip this test if the _testcapi module isn't available. +_testcapi = import_helper.import_module('_testcapi') + +class PyAtomicTests(unittest.TestCase): + pass + +for name in sorted(dir(_testcapi)): + if name.startswith('test_atomic'): + setattr(PyAtomicTests, name, getattr(_testcapi, name)) + +if __name__ == "__main__": + unittest.main() diff --git a/Lib/test/test_capi/test_set.py b/Lib/test/test_capi/test_set.py new file mode 100644 index 00000000000000..5235f81543e0b6 --- /dev/null +++ b/Lib/test/test_capi/test_set.py @@ -0,0 +1,265 @@ +import unittest + +from test.support import import_helper + +# Skip this test if the _testcapi or _testinternalcapi modules aren't available. +_testcapi = import_helper.import_module('_testcapi') +_testinternalcapi = import_helper.import_module('_testinternalcapi') + +class set_subclass(set): + pass + +class frozenset_subclass(frozenset): + pass + + +class BaseSetTests: + def assertImmutable(self, action, *args): + self.assertRaises(SystemError, action, frozenset(), *args) + self.assertRaises(SystemError, action, frozenset({1}), *args) + self.assertRaises(SystemError, action, frozenset_subclass(), *args) + self.assertRaises(SystemError, action, frozenset_subclass({1}), *args) + + +class TestSetCAPI(BaseSetTests, unittest.TestCase): + def test_set_check(self): + check = _testcapi.set_check + self.assertTrue(check(set())) + self.assertTrue(check({1, 2})) + self.assertFalse(check(frozenset())) + self.assertTrue(check(set_subclass())) + self.assertFalse(check(frozenset_subclass())) + self.assertFalse(check(object())) + # CRASHES: check(NULL) + + def test_set_check_exact(self): + check = _testcapi.set_checkexact + self.assertTrue(check(set())) + self.assertTrue(check({1, 2})) + self.assertFalse(check(frozenset())) + self.assertFalse(check(set_subclass())) + self.assertFalse(check(frozenset_subclass())) + self.assertFalse(check(object())) + # CRASHES: check(NULL) + + def test_frozenset_check(self): + check = _testcapi.frozenset_check + self.assertFalse(check(set())) + self.assertTrue(check(frozenset())) + self.assertTrue(check(frozenset({1, 2}))) + self.assertFalse(check(set_subclass())) + self.assertTrue(check(frozenset_subclass())) + self.assertFalse(check(object())) + # CRASHES: check(NULL) + + def test_frozenset_check_exact(self): + check = _testcapi.frozenset_checkexact + self.assertFalse(check(set())) + self.assertTrue(check(frozenset())) + self.assertTrue(check(frozenset({1, 2}))) + self.assertFalse(check(set_subclass())) + self.assertFalse(check(frozenset_subclass())) + self.assertFalse(check(object())) + # CRASHES: check(NULL) + + def test_anyset_check(self): + check = _testcapi.anyset_check + self.assertTrue(check(set())) + self.assertTrue(check({1, 2})) + self.assertTrue(check(frozenset())) + self.assertTrue(check(frozenset({1, 2}))) + self.assertTrue(check(set_subclass())) + self.assertTrue(check(frozenset_subclass())) + self.assertFalse(check(object())) + # CRASHES: check(NULL) + + def test_anyset_check_exact(self): + check = _testcapi.anyset_checkexact + self.assertTrue(check(set())) + self.assertTrue(check({1, 2})) + self.assertTrue(check(frozenset())) + self.assertTrue(check(frozenset({1, 2}))) + self.assertFalse(check(set_subclass())) + self.assertFalse(check(frozenset_subclass())) + self.assertFalse(check(object())) + # CRASHES: check(NULL) + + def test_set_new(self): + set_new = _testcapi.set_new + self.assertEqual(set_new().__class__, set) + self.assertEqual(set_new(), set()) + self.assertEqual(set_new((1, 1, 2)), {1, 2}) + self.assertEqual(set_new([1, 1, 2]), {1, 2}) + with self.assertRaisesRegex(TypeError, 'object is not iterable'): + set_new(object()) + with self.assertRaisesRegex(TypeError, 'object is not iterable'): + set_new(1) + with self.assertRaisesRegex(TypeError, "unhashable type: 'dict'"): + set_new((1, {})) + + def test_frozenset_new(self): + frozenset_new = _testcapi.frozenset_new + self.assertEqual(frozenset_new().__class__, frozenset) + self.assertEqual(frozenset_new(), frozenset()) + self.assertEqual(frozenset_new((1, 1, 2)), frozenset({1, 2})) + self.assertEqual(frozenset_new([1, 1, 2]), frozenset({1, 2})) + with self.assertRaisesRegex(TypeError, 'object is not iterable'): + frozenset_new(object()) + with self.assertRaisesRegex(TypeError, 'object is not iterable'): + frozenset_new(1) + with self.assertRaisesRegex(TypeError, "unhashable type: 'dict'"): + frozenset_new((1, {})) + + def test_set_size(self): + get_size = _testcapi.set_size + self.assertEqual(get_size(set()), 0) + self.assertEqual(get_size(frozenset()), 0) + self.assertEqual(get_size({1, 1, 2}), 2) + self.assertEqual(get_size(frozenset({1, 1, 2})), 2) + self.assertEqual(get_size(set_subclass((1, 2, 3))), 3) + self.assertEqual(get_size(frozenset_subclass((1, 2, 3))), 3) + with self.assertRaises(SystemError): + get_size(object()) + # CRASHES: get_size(NULL) + + def test_set_get_size(self): + get_size = _testcapi.set_get_size + self.assertEqual(get_size(set()), 0) + self.assertEqual(get_size(frozenset()), 0) + self.assertEqual(get_size({1, 1, 2}), 2) + self.assertEqual(get_size(frozenset({1, 1, 2})), 2) + self.assertEqual(get_size(set_subclass((1, 2, 3))), 3) + self.assertEqual(get_size(frozenset_subclass((1, 2, 3))), 3) + # CRASHES: get_size(NULL) + # CRASHES: get_size(object()) + + def test_set_contains(self): + contains = _testcapi.set_contains + for cls in (set, frozenset, set_subclass, frozenset_subclass): + with self.subTest(cls=cls): + instance = cls((1, 2)) + self.assertTrue(contains(instance, 1)) + self.assertFalse(contains(instance, 'missing')) + with self.assertRaisesRegex(TypeError, "unhashable type: 'list'"): + contains(instance, []) + # CRASHES: contains(instance, NULL) + # CRASHES: contains(NULL, object()) + # CRASHES: contains(NULL, NULL) + + def test_add(self): + add = _testcapi.set_add + for cls in (set, set_subclass): + with self.subTest(cls=cls): + instance = cls((1, 2)) + self.assertEqual(add(instance, 1), 0) + self.assertEqual(instance, {1, 2}) + self.assertEqual(add(instance, 3), 0) + self.assertEqual(instance, {1, 2, 3}) + with self.assertRaisesRegex(TypeError, "unhashable type: 'list'"): + add(instance, []) + with self.assertRaises(SystemError): + add(object(), 1) + self.assertImmutable(add, 1) + # CRASHES: add(NULL, object()) + # CRASHES: add(instance, NULL) + # CRASHES: add(NULL, NULL) + + def test_discard(self): + discard = _testcapi.set_discard + for cls in (set, set_subclass): + with self.subTest(cls=cls): + instance = cls((1, 2)) + self.assertEqual(discard(instance, 3), 0) + self.assertEqual(instance, {1, 2}) + self.assertEqual(discard(instance, 1), 1) + self.assertEqual(instance, {2}) + self.assertEqual(discard(instance, 2), 1) + self.assertEqual(instance, set()) + self.assertEqual(discard(instance, 2), 0) + self.assertEqual(instance, set()) + with self.assertRaisesRegex(TypeError, "unhashable type: 'list'"): + discard(instance, []) + with self.assertRaises(SystemError): + discard(object(), 1) + self.assertImmutable(discard, 1) + # CRASHES: discard(NULL, object()) + # CRASHES: discard(instance, NULL) + # CRASHES: discard(NULL, NULL) + + def test_pop(self): + pop = _testcapi.set_pop + orig = (1, 2) + for cls in (set, set_subclass): + with self.subTest(cls=cls): + instance = cls(orig) + self.assertIn(pop(instance), orig) + self.assertEqual(len(instance), 1) + self.assertIn(pop(instance), orig) + self.assertEqual(len(instance), 0) + with self.assertRaises(KeyError): + pop(instance) + with self.assertRaises(SystemError): + pop(object()) + self.assertImmutable(pop) + # CRASHES: pop(NULL) + + def test_clear(self): + clear = _testcapi.set_clear + for cls in (set, set_subclass): + with self.subTest(cls=cls): + instance = cls((1, 2)) + self.assertEqual(clear(instance), 0) + self.assertEqual(instance, set()) + self.assertEqual(clear(instance), 0) + self.assertEqual(instance, set()) + with self.assertRaises(SystemError): + clear(object()) + self.assertImmutable(clear) + # CRASHES: clear(NULL) + + +class TestInternalCAPI(BaseSetTests, unittest.TestCase): + def test_set_update(self): + update = _testinternalcapi.set_update + for cls in (set, set_subclass): + for it in ('ab', ('a', 'b'), ['a', 'b'], + set('ab'), set_subclass('ab'), + frozenset('ab'), frozenset_subclass('ab')): + with self.subTest(cls=cls, it=it): + instance = cls() + self.assertEqual(update(instance, it), 0) + self.assertEqual(instance, {'a', 'b'}) + instance = cls(it) + self.assertEqual(update(instance, it), 0) + self.assertEqual(instance, {'a', 'b'}) + with self.assertRaisesRegex(TypeError, 'object is not iterable'): + update(cls(), 1) + with self.assertRaisesRegex(TypeError, "unhashable type: 'dict'"): + update(cls(), [{}]) + with self.assertRaises(SystemError): + update(object(), 'ab') + self.assertImmutable(update, 'ab') + # CRASHES: update(NULL, object()) + # CRASHES: update(instance, NULL) + # CRASHES: update(NULL, NULL) + + def test_set_next_entry(self): + set_next = _testinternalcapi.set_next_entry + for cls in (set, set_subclass, frozenset, frozenset_subclass): + with self.subTest(cls=cls): + instance = cls('abc') + pos = 0 + items = [] + while True: + res = set_next(instance, pos) + if res is None: + break + rc, pos, hash_, item = res + items.append(item) + self.assertEqual(rc, 1) + self.assertIn(item, instance) + self.assertEqual(hash(item), hash_) + self.assertEqual(items, list(instance)) + with self.assertRaises(SystemError): + set_next(object(), 0) + # CRASHES: set_next(NULL, 0) diff --git a/Lib/test/test_capi/test_sys.py b/Lib/test/test_capi/test_sys.py new file mode 100644 index 00000000000000..08bf0370fc59b5 --- /dev/null +++ b/Lib/test/test_capi/test_sys.py @@ -0,0 +1,154 @@ +import unittest +import contextlib +import sys +from test import support +from test.support import import_helper + +try: + import _testcapi +except ImportError: + _testcapi = None + +NULL = None + +class CAPITest(unittest.TestCase): + # TODO: Test the following functions: + # + # PySys_Audit() + # PySys_AuditTuple() + + maxDiff = None + + @support.cpython_only + @unittest.skipIf(_testcapi is None, 'need _testcapi module') + def test_sys_getobject(self): + # Test PySys_GetObject() + getobject = _testcapi.sys_getobject + + self.assertIs(getobject(b'stdout'), sys.stdout) + with support.swap_attr(sys, '\U0001f40d', 42): + self.assertEqual(getobject('\U0001f40d'.encode()), 42) + + self.assertIs(getobject(b'nonexisting'), AttributeError) + with support.catch_unraisable_exception() as cm: + self.assertIs(getobject(b'\xff'), AttributeError) + self.assertEqual(cm.unraisable.exc_type, UnicodeDecodeError) + self.assertRegex(str(cm.unraisable.exc_value), + "'utf-8' codec can't decode") + # CRASHES getobject(NULL) + + @support.cpython_only + @unittest.skipIf(_testcapi is None, 'need _testcapi module') + def test_sys_setobject(self): + # Test PySys_SetObject() + setobject = _testcapi.sys_setobject + + value = ['value'] + value2 = ['value2'] + try: + self.assertEqual(setobject(b'newattr', value), 0) + self.assertIs(sys.newattr, value) + self.assertEqual(setobject(b'newattr', value2), 0) + self.assertIs(sys.newattr, value2) + self.assertEqual(setobject(b'newattr', NULL), 0) + self.assertFalse(hasattr(sys, 'newattr')) + self.assertEqual(setobject(b'newattr', NULL), 0) + finally: + with contextlib.suppress(AttributeError): + del sys.newattr + try: + self.assertEqual(setobject('\U0001f40d'.encode(), value), 0) + self.assertIs(getattr(sys, '\U0001f40d'), value) + self.assertEqual(setobject('\U0001f40d'.encode(), NULL), 0) + self.assertFalse(hasattr(sys, '\U0001f40d')) + finally: + with contextlib.suppress(AttributeError): + delattr(sys, '\U0001f40d') + + with self.assertRaises(UnicodeDecodeError): + setobject(b'\xff', value) + # CRASHES setobject(NULL, value) + + @support.cpython_only + @unittest.skipIf(_testcapi is None, 'need _testcapi module') + def test_sys_getxoptions(self): + # Test PySys_GetXOptions() + getxoptions = _testcapi.sys_getxoptions + + self.assertIs(getxoptions(), sys._xoptions) + + xoptions = sys._xoptions + try: + sys._xoptions = 'non-dict' + self.assertEqual(getxoptions(), {}) + self.assertIs(getxoptions(), sys._xoptions) + + del sys._xoptions + self.assertEqual(getxoptions(), {}) + self.assertIs(getxoptions(), sys._xoptions) + finally: + sys._xoptions = xoptions + self.assertIs(getxoptions(), sys._xoptions) + + def _test_sys_formatstream(self, funname, streamname): + import_helper.import_module('ctypes') + from ctypes import pythonapi, c_char_p, py_object + func = getattr(pythonapi, funname) + func.argtypes = (c_char_p,) + + # Supports plain C types. + with support.captured_output(streamname) as stream: + func(b'Hello, %s!', c_char_p(b'world')) + self.assertEqual(stream.getvalue(), 'Hello, world!') + + # Supports Python objects. + with support.captured_output(streamname) as stream: + func(b'Hello, %R!', py_object('world')) + self.assertEqual(stream.getvalue(), "Hello, 'world'!") + + # The total length is not limited. + with support.captured_output(streamname) as stream: + func(b'Hello, %s!', c_char_p(b'world'*200)) + self.assertEqual(stream.getvalue(), 'Hello, ' + 'world'*200 + '!') + + def test_sys_formatstdout(self): + # Test PySys_FormatStdout() + self._test_sys_formatstream('PySys_FormatStdout', 'stdout') + + def test_sys_formatstderr(self): + # Test PySys_FormatStderr() + self._test_sys_formatstream('PySys_FormatStderr', 'stderr') + + def _test_sys_writestream(self, funname, streamname): + import_helper.import_module('ctypes') + from ctypes import pythonapi, c_char_p + func = getattr(pythonapi, funname) + func.argtypes = (c_char_p,) + + # Supports plain C types. + with support.captured_output(streamname) as stream: + func(b'Hello, %s!', c_char_p(b'world')) + self.assertEqual(stream.getvalue(), 'Hello, world!') + + # There is a limit on the total length. + with support.captured_output(streamname) as stream: + func(b'Hello, %s!', c_char_p(b'world'*100)) + self.assertEqual(stream.getvalue(), 'Hello, ' + 'world'*100 + '!') + with support.captured_output(streamname) as stream: + func(b'Hello, %s!', c_char_p(b'world'*200)) + out = stream.getvalue() + self.assertEqual(out[:20], 'Hello, worldworldwor') + self.assertEqual(out[-13:], '... truncated') + self.assertGreater(len(out), 1000) + + def test_sys_writestdout(self): + # Test PySys_WriteStdout() + self._test_sys_writestream('PySys_WriteStdout', 'stdout') + + def test_sys_writestderr(self): + # Test PySys_WriteStderr() + self._test_sys_writestream('PySys_WriteStderr', 'stderr') + + +if __name__ == "__main__": + unittest.main() diff --git a/Lib/test/test_capi/test_unicode.py b/Lib/test/test_capi/test_unicode.py index 622ee8993907fa..bb6161abf4da81 100644 --- a/Lib/test/test_capi/test_unicode.py +++ b/Lib/test/test_capi/test_unicode.py @@ -5,6 +5,7 @@ try: import _testcapi + from _testcapi import PY_SSIZE_T_MIN, PY_SSIZE_T_MAX except ImportError: _testcapi = None try: @@ -30,9 +31,17 @@ def test_new(self): for maxchar in 0, 0x61, 0xa1, 0x4f60, 0x1f600, 0x10ffff: self.assertEqual(new(0, maxchar), '') self.assertEqual(new(5, maxchar), chr(maxchar)*5) + self.assertRaises(MemoryError, new, PY_SSIZE_T_MAX, maxchar) self.assertEqual(new(0, 0x110000), '') + self.assertRaises(MemoryError, new, PY_SSIZE_T_MAX//2, 0x4f60) + self.assertRaises(MemoryError, new, PY_SSIZE_T_MAX//2+1, 0x4f60) + self.assertRaises(MemoryError, new, PY_SSIZE_T_MAX//2, 0x1f600) + self.assertRaises(MemoryError, new, PY_SSIZE_T_MAX//2+1, 0x1f600) + self.assertRaises(MemoryError, new, PY_SSIZE_T_MAX//4, 0x1f600) + self.assertRaises(MemoryError, new, PY_SSIZE_T_MAX//4+1, 0x1f600) self.assertRaises(SystemError, new, 5, 0x110000) self.assertRaises(SystemError, new, -1, 0) + self.assertRaises(SystemError, new, PY_SSIZE_T_MIN, 0) @support.cpython_only @unittest.skipIf(_testcapi is None, 'need _testcapi module') @@ -53,8 +62,8 @@ def test_fill(self): for to in strings[:idx]: self.assertRaises(ValueError, fill, to, 0, 0, fill_char) for to in strings[idx:]: - for start in range(7): - for length in range(-1, 7 - start): + for start in [*range(7), PY_SSIZE_T_MAX]: + for length in [*range(-1, 7 - start), PY_SSIZE_T_MIN, PY_SSIZE_T_MAX]: filled = max(min(length, 5 - start), 0) if filled == 5 and to != strings[idx]: # narrow -> wide @@ -66,6 +75,7 @@ def test_fill(self): s = strings[0] self.assertRaises(IndexError, fill, s, -1, 0, 0x78) + self.assertRaises(IndexError, fill, s, PY_SSIZE_T_MIN, 0, 0x78) self.assertRaises(ValueError, fill, s, 0, 0, 0x110000) self.assertRaises(SystemError, fill, b'abc', 0, 0, 0x78) self.assertRaises(SystemError, fill, [], 0, 0, 0x78) @@ -76,7 +86,7 @@ def test_fill(self): @support.cpython_only @unittest.skipIf(_testcapi is None, 'need _testcapi module') def test_writechar(self): - """Test PyUnicode_ReadChar()""" + """Test PyUnicode_WriteChar()""" from _testcapi import unicode_writechar as writechar strings = [ @@ -96,10 +106,12 @@ def test_writechar(self): self.assertRaises(IndexError, writechar, 'abc', 3, 0x78) self.assertRaises(IndexError, writechar, 'abc', -1, 0x78) + self.assertRaises(IndexError, writechar, 'abc', PY_SSIZE_T_MAX, 0x78) + self.assertRaises(IndexError, writechar, 'abc', PY_SSIZE_T_MIN, 0x78) self.assertRaises(TypeError, writechar, b'abc', 0, 0x78) self.assertRaises(TypeError, writechar, [], 0, 0x78) # CRASHES writechar(NULL, 0, 0x78) - # TODO: Test PyUnicode_CopyCharacters() with non-modifiable and legacy + # TODO: Test PyUnicode_WriteChar() with non-modifiable and legacy # unicode. @support.cpython_only @@ -117,7 +129,11 @@ def test_resize(self): self.assertEqual(resize(s, 3), (s, 0)) self.assertEqual(resize(s, 2), (s[:2], 0)) self.assertEqual(resize(s, 4), (s + '\0', 0)) + self.assertEqual(resize(s, 10), (s + '\0'*7, 0)) self.assertEqual(resize(s, 0), ('', 0)) + self.assertRaises(MemoryError, resize, s, PY_SSIZE_T_MAX) + self.assertRaises(SystemError, resize, s, -1) + self.assertRaises(SystemError, resize, s, PY_SSIZE_T_MIN) self.assertRaises(SystemError, resize, b'abc', 0) self.assertRaises(SystemError, resize, [], 0) self.assertRaises(SystemError, resize, NULL, 0) @@ -196,8 +212,13 @@ def test_fromstringandsize(self): self.assertEqual(fromstringandsize(b'', 0), '') self.assertEqual(fromstringandsize(NULL, 0), '') + self.assertRaises(MemoryError, fromstringandsize, b'abc', PY_SSIZE_T_MAX) self.assertRaises(SystemError, fromstringandsize, b'abc', -1) - # TODO: Test PyUnicode_FromStringAndSize(NULL, size) for size != 0 + self.assertRaises(SystemError, fromstringandsize, b'abc', PY_SSIZE_T_MIN) + self.assertRaises(SystemError, fromstringandsize, NULL, -1) + self.assertRaises(SystemError, fromstringandsize, NULL, PY_SSIZE_T_MIN) + self.assertRaises(SystemError, fromstringandsize, NULL, 3) + self.assertRaises(SystemError, fromstringandsize, NULL, PY_SSIZE_T_MAX) @support.cpython_only @unittest.skipIf(_testcapi is None, 'need _testcapi module') @@ -245,7 +266,9 @@ def test_fromkindanddata(self): for kind in -1, 0, 3, 5, 8: self.assertRaises(SystemError, fromkindanddata, kind, b'') self.assertRaises(ValueError, fromkindanddata, 1, b'abc', -1) + self.assertRaises(ValueError, fromkindanddata, 1, b'abc', PY_SSIZE_T_MIN) self.assertRaises(ValueError, fromkindanddata, 1, NULL, -1) + self.assertRaises(ValueError, fromkindanddata, 1, NULL, PY_SSIZE_T_MIN) # CRASHES fromkindanddata(1, NULL, 1) # CRASHES fromkindanddata(4, b'\xff\xff\xff\xff') @@ -261,12 +284,14 @@ def test_substring(self): 'ab\xa1\xa2\u4f60\u597d\U0001f600\U0001f601' ] for s in strings: - for start in range(0, len(s) + 2): - for end in range(max(start-1, 0), len(s) + 2): + for start in [*range(0, len(s) + 2), PY_SSIZE_T_MAX]: + for end in [*range(max(start-1, 0), len(s) + 2), PY_SSIZE_T_MAX]: self.assertEqual(substring(s, start, end), s[start:end]) self.assertRaises(IndexError, substring, 'abc', -1, 0) + self.assertRaises(IndexError, substring, 'abc', PY_SSIZE_T_MIN, 0) self.assertRaises(IndexError, substring, 'abc', 0, -1) + self.assertRaises(IndexError, substring, 'abc', 0, PY_SSIZE_T_MIN) # CRASHES substring(b'abc', 0, 0) # CRASHES substring([], 0, 0) # CRASHES substring(NULL, 0, 0) @@ -296,7 +321,9 @@ def test_readchar(self): for i, c in enumerate(s): self.assertEqual(readchar(s, i), ord(c)) self.assertRaises(IndexError, readchar, s, len(s)) + self.assertRaises(IndexError, readchar, s, PY_SSIZE_T_MAX) self.assertRaises(IndexError, readchar, s, -1) + self.assertRaises(IndexError, readchar, s, PY_SSIZE_T_MIN) self.assertRaises(TypeError, readchar, b'abc', 0) self.assertRaises(TypeError, readchar, [], 0) @@ -731,10 +758,15 @@ def test_fromwidechar(self): if SIZEOF_WCHAR_T == 2: self.assertEqual(fromwidechar('a\U0001f600'.encode(encoding), 2), 'a\ud83d') + self.assertRaises(MemoryError, fromwidechar, b'', PY_SSIZE_T_MAX) self.assertRaises(SystemError, fromwidechar, b'\0'*SIZEOF_WCHAR_T, -2) + self.assertRaises(SystemError, fromwidechar, b'\0'*SIZEOF_WCHAR_T, PY_SSIZE_T_MIN) self.assertEqual(fromwidechar(NULL, 0), '') self.assertRaises(SystemError, fromwidechar, NULL, 1) + self.assertRaises(SystemError, fromwidechar, NULL, PY_SSIZE_T_MAX) self.assertRaises(SystemError, fromwidechar, NULL, -1) + self.assertRaises(SystemError, fromwidechar, NULL, -2) + self.assertRaises(SystemError, fromwidechar, NULL, PY_SSIZE_T_MIN) @support.cpython_only @unittest.skipIf(_testcapi is None, 'need _testcapi module') @@ -906,7 +938,11 @@ def test_asutf8andsize(self): self.assertRaises(UnicodeEncodeError, unicode_asutf8andsize, '\ud8ff', 0) self.assertRaises(TypeError, unicode_asutf8andsize, b'abc', 0) self.assertRaises(TypeError, unicode_asutf8andsize, [], 0) + self.assertRaises(UnicodeEncodeError, unicode_asutf8andsize_null, '\ud8ff', 0) + self.assertRaises(TypeError, unicode_asutf8andsize_null, b'abc', 0) + self.assertRaises(TypeError, unicode_asutf8andsize_null, [], 0) # CRASHES unicode_asutf8andsize(NULL, 0) + # CRASHES unicode_asutf8andsize_null(NULL, 0) @support.cpython_only @unittest.skipIf(_testcapi is None, 'need _testcapi module') @@ -965,6 +1001,11 @@ def test_split(self): self.assertEqual(split('a|b|c|d', '|'), ['a', 'b', 'c', 'd']) self.assertEqual(split('a|b|c|d', '|', 2), ['a', 'b', 'c|d']) + self.assertEqual(split('a|b|c|d', '|', PY_SSIZE_T_MAX), + ['a', 'b', 'c', 'd']) + self.assertEqual(split('a|b|c|d', '|', -1), ['a', 'b', 'c', 'd']) + self.assertEqual(split('a|b|c|d', '|', PY_SSIZE_T_MIN), + ['a', 'b', 'c', 'd']) self.assertEqual(split('a|b|c|d', '\u20ac'), ['a|b|c|d']) self.assertEqual(split('a||b|c||d', '||'), ['a', 'b|c', 'd']) self.assertEqual(split('а|б|в|г', '|'), ['а', 'б', 'в', 'г']) @@ -988,6 +1029,11 @@ def test_rsplit(self): self.assertEqual(rsplit('a|b|c|d', '|'), ['a', 'b', 'c', 'd']) self.assertEqual(rsplit('a|b|c|d', '|', 2), ['a|b', 'c', 'd']) + self.assertEqual(rsplit('a|b|c|d', '|', PY_SSIZE_T_MAX), + ['a', 'b', 'c', 'd']) + self.assertEqual(rsplit('a|b|c|d', '|', -1), ['a', 'b', 'c', 'd']) + self.assertEqual(rsplit('a|b|c|d', '|', PY_SSIZE_T_MIN), + ['a', 'b', 'c', 'd']) self.assertEqual(rsplit('a|b|c|d', '\u20ac'), ['a|b|c|d']) self.assertEqual(rsplit('a||b|c||d', '||'), ['a', 'b|c', 'd']) self.assertEqual(rsplit('а|б|в|г', '|'), ['а', 'б', 'в', 'г']) @@ -1120,11 +1166,14 @@ def test_count(self): self.assertEqual(unicode_count(str, '', 0, len(str)), len(str)+1) # start < end self.assertEqual(unicode_count(str, '!', 1, len(str)+1), 1) + self.assertEqual(unicode_count(str, '!', 1, PY_SSIZE_T_MAX), 1) # start >= end self.assertEqual(unicode_count(str, '!', 0, 0), 0) self.assertEqual(unicode_count(str, '!', len(str), 0), 0) # negative self.assertEqual(unicode_count(str, '!', -len(str), -1), 1) + self.assertEqual(unicode_count(str, '!', -len(str)-1, -1), 1) + self.assertEqual(unicode_count(str, '!', PY_SSIZE_T_MIN, -1), 1) # bad arguments self.assertRaises(TypeError, unicode_count, str, b'!', 0, len(str)) self.assertRaises(TypeError, unicode_count, b"!>_= end self.assertEqual(find(str, '!', 0, 0, 1), -1) + self.assertEqual(find(str, '!', 0, 0, -1), -1) self.assertEqual(find(str, '!', len(str), 0, 1), -1) + self.assertEqual(find(str, '!', len(str), 0, -1), -1) # negative self.assertEqual(find(str, '!', -len(str), -1, 1), 0) self.assertEqual(find(str, '!', -len(str), -1, -1), 0) + self.assertEqual(find(str, '!', PY_SSIZE_T_MIN, -1, 1), 0) + self.assertEqual(find(str, '!', PY_SSIZE_T_MIN, -1, -1), 0) + self.assertEqual(find(str, '!', PY_SSIZE_T_MIN, PY_SSIZE_T_MAX, 1), 0) + self.assertEqual(find(str, '!', PY_SSIZE_T_MIN, PY_SSIZE_T_MAX, -1), 4) # bad arguments self.assertRaises(TypeError, find, str, b'!', 0, len(str), 1) self.assertRaises(TypeError, find, b"!>_= end self.assertEqual(unicode_findchar(str, ord('!'), 0, 0, 1), -1) + self.assertEqual(unicode_findchar(str, ord('!'), 0, 0, -1), -1) self.assertEqual(unicode_findchar(str, ord('!'), len(str), 0, 1), -1) + self.assertEqual(unicode_findchar(str, ord('!'), len(str), 0, -1), -1) # negative self.assertEqual(unicode_findchar(str, ord('!'), -len(str), -1, 1), 0) self.assertEqual(unicode_findchar(str, ord('!'), -len(str), -1, -1), 0) + self.assertEqual(unicode_findchar(str, ord('!'), PY_SSIZE_T_MIN, -1, 1), 0) + self.assertEqual(unicode_findchar(str, ord('!'), PY_SSIZE_T_MIN, -1, -1), 0) + self.assertEqual(unicode_findchar(str, ord('!'), PY_SSIZE_T_MIN, PY_SSIZE_T_MAX, 1), 0) + self.assertEqual(unicode_findchar(str, ord('!'), PY_SSIZE_T_MIN, PY_SSIZE_T_MAX, -1), 4) # bad arguments # CRASHES unicode_findchar(b"!>_" + return cm.exception class ClinicWholeFileTest(TestCase): @@ -124,7 +60,7 @@ def expect_failure(self, raw, errmsg, *, filename=None, lineno=None): filename=filename, lineno=lineno) def setUp(self): - self.clinic = clinic.Clinic(clinic.CLanguage(None), filename="test.c") + self.clinic = _make_clinic(filename="test.c") def test_eol(self): # regression test: @@ -189,7 +125,7 @@ def test_parse_with_body_prefix(self): clang.body_prefix = "//" clang.start_line = "//[{dsl_name} start]" clang.stop_line = "//[{dsl_name} stop]" - cl = clinic.Clinic(clang, filename="test.c") + cl = clinic.Clinic(clang, filename="test.c", limited_capi=False) raw = dedent(""" //[clinic start] //module test @@ -291,6 +227,15 @@ def test_directive_output_print(self): last_line.startswith("/*[clinic end generated code: output=") ) + def test_directive_wrong_arg_number(self): + raw = dedent(""" + /*[clinic input] + preserve foo bar baz eggs spam ham mushrooms + [clinic start generated code]*/ + """) + err = "takes 1 positional argument but 8 were given" + self.expect_failure(raw, err) + def test_unknown_destination_command(self): raw = """ /*[clinic input] @@ -319,70 +264,6 @@ def converter_init(self): ) self.expect_failure(raw, err) - @staticmethod - @contextlib.contextmanager - def _clinic_version(new_version): - """Helper for test_version_*() tests""" - _saved = clinic.version - clinic.version = new_version - try: - yield - finally: - clinic.version = _saved - - def test_version_directive(self): - dataset = ( - # (clinic version, required version) - ('3', '2'), # required version < clinic version - ('3.1', '3.0'), # required version < clinic version - ('1.2b0', '1.2a7'), # required version < clinic version - ('5', '5'), # required version == clinic version - ('6.1', '6.1'), # required version == clinic version - ('1.2b3', '1.2b3'), # required version == clinic version - ) - for clinic_version, required_version in dataset: - with self.subTest(clinic_version=clinic_version, - required_version=required_version): - with self._clinic_version(clinic_version): - block = dedent(f""" - /*[clinic input] - version {required_version} - [clinic start generated code]*/ - """) - self.clinic.parse(block) - - def test_version_directive_insufficient_version(self): - with self._clinic_version('4'): - err = ( - "Insufficient Clinic version!\n" - " Version: 4\n" - " Required: 5" - ) - block = """ - /*[clinic input] - version 5 - [clinic start generated code]*/ - """ - self.expect_failure(block, err) - - def test_version_directive_illegal_char(self): - err = "Illegal character 'v' in version string 'v5'" - block = """ - /*[clinic input] - version v5 - [clinic start generated code]*/ - """ - self.expect_failure(block, err) - - def test_version_directive_unsupported_string(self): - err = "Unsupported version string: '.-'" - block = """ - /*[clinic input] - version .- - [clinic start generated code]*/ - """ - self.expect_failure(block, err) - def test_clone_mismatch(self): err = "'kind' of function and cloned function don't match!" block = """ @@ -414,6 +295,20 @@ def __init__(self): """ self.expect_failure(block, err, lineno=8) + def test_multiple_star_in_args(self): + err = "'my_test_func' uses '*' more than once." + block = """ + /*[clinic input] + my_test_func + + pos_arg: object + *args: object + * + kw_arg: object + [clinic start generated code]*/ + """ + self.expect_failure(block, err, lineno=6) + def test_module_already_got_one(self): err = "Already defined module 'm'!" block = """ @@ -626,7 +521,6 @@ def test_directive_preserve_input(self): self.expect_failure(block, err, lineno=6) def test_directive_preserve_output(self): - err = "'preserve' only works for blocks that don't produce any output!" block = dedent(""" /*[clinic input] output everything buffer @@ -668,6 +562,104 @@ def test_directive_output_invalid_command(self): """ self.expect_failure(block, err, lineno=2) + def test_validate_cloned_init(self): + block = """ + /*[clinic input] + class C "void *" "" + C.meth + a: int + [clinic start generated code]*/ + /*[clinic input] + @classmethod + C.__init__ = C.meth + [clinic start generated code]*/ + """ + err = "'__init__' must be a normal method; got 'FunctionKind.CLASS_METHOD'!" + self.expect_failure(block, err, lineno=8) + + def test_validate_cloned_new(self): + block = """ + /*[clinic input] + class C "void *" "" + C.meth + a: int + [clinic start generated code]*/ + /*[clinic input] + C.__new__ = C.meth + [clinic start generated code]*/ + """ + err = "'__new__' must be a class method" + self.expect_failure(block, err, lineno=7) + + def test_no_c_basename_cloned(self): + block = """ + /*[clinic input] + foo2 + [clinic start generated code]*/ + /*[clinic input] + foo as = foo2 + [clinic start generated code]*/ + """ + err = "No C basename provided after 'as' keyword" + self.expect_failure(block, err, lineno=5) + + def test_cloned_with_custom_c_basename(self): + raw = dedent(""" + /*[clinic input] + # Make sure we don't create spurious clinic/ directories. + output everything suppress + foo2 + [clinic start generated code]*/ + + /*[clinic input] + foo as foo1 = foo2 + [clinic start generated code]*/ + """) + self.clinic.parse(raw) + funcs = self.clinic.functions + self.assertEqual(len(funcs), 2) + self.assertEqual(funcs[1].name, "foo") + self.assertEqual(funcs[1].c_basename, "foo1") + + def test_cloned_with_illegal_c_basename(self): + block = """ + /*[clinic input] + class C "void *" "" + foo1 + [clinic start generated code]*/ + + /*[clinic input] + foo2 as .illegal. = foo1 + [clinic start generated code]*/ + """ + err = "Illegal C basename: '.illegal.'" + self.expect_failure(block, err, lineno=7) + + +class ParseFileUnitTest(TestCase): + def expect_parsing_failure( + self, *, filename, expected_error, verify=True, output=None + ): + errmsg = re.escape(dedent(expected_error).strip()) + with self.assertRaisesRegex(clinic.ClinicError, errmsg): + clinic.parse_file(filename, limited_capi=False) + + def test_parse_file_no_extension(self) -> None: + self.expect_parsing_failure( + filename="foo", + expected_error="Can't extract file type for file 'foo'" + ) + + def test_parse_file_strange_extension(self) -> None: + filenames_to_errors = { + "foo.rs": "Can't identify file type for file 'foo.rs'", + "foo.hs": "Can't identify file type for file 'foo.hs'", + "foo.js": "Can't identify file type for file 'foo.js'", + } + for filename, errmsg in filenames_to_errors.items(): + with self.subTest(filename=filename): + self.expect_parsing_failure(filename=filename, expected_error=errmsg) + class ClinicGroupPermuterTest(TestCase): def _test(self, l, m, r, output): @@ -790,8 +782,9 @@ def _test(self, input, output): blocks = list(clinic.BlockParser(input, language)) writer = clinic.BlockPrinter(language) + c = _make_clinic() for block in blocks: - writer.print_block(block) + writer.print_block(block, limited_capi=c.limited_capi, header_includes=c.includes) output = writer.f.getvalue() assert output == input, "output != input!\n\noutput " + repr(output) + "\n\n input " + repr(input) @@ -817,7 +810,7 @@ def test_round_trip_2(self): def _test_clinic(self, input, output): language = clinic.CLanguage(None) - c = clinic.Clinic(language, filename="file") + c = clinic.Clinic(language, filename="file", limited_capi=False) c.parsers['inert'] = InertParser(c) c.parsers['copy'] = CopyParser(c) computed = c.parse(input) @@ -848,7 +841,7 @@ def test_clinic_1(self): class ClinicParserTest(TestCase): def parse(self, text): - c = FakeClinic() + c = _make_clinic() parser = DSLParser(c) block = clinic.Block(text) parser.parse(block) @@ -862,17 +855,18 @@ def parse_function(self, text, signatures_in_block=2, function_index=1): assert isinstance(s[function_index], clinic.Function) return s[function_index] - def expect_failure(self, block, err, *, filename=None, lineno=None): - _expect_failure(self, self.parse_function, block, err, - filename=filename, lineno=lineno) + def expect_failure(self, block, err, *, + filename=None, lineno=None, strip=True): + return _expect_failure(self, self.parse_function, block, err, + filename=filename, lineno=lineno, strip=strip) def checkDocstring(self, fn, expected): self.assertTrue(hasattr(fn, "docstring")) - self.assertEqual(fn.docstring.strip(), - dedent(expected).strip()) + self.assertEqual(dedent(expected).strip(), + fn.docstring.strip()) def test_trivial(self): - parser = DSLParser(FakeClinic()) + parser = DSLParser(_make_clinic()) block = clinic.Block(""" module os os.access @@ -946,6 +940,41 @@ def test_param_default_expr_named_constant(self): """ self.expect_failure(block, err, lineno=2) + def test_param_with_bizarre_default_fails_correctly(self): + template = """ + module os + os.access + follow_symlinks: int = {default} + """ + err = "Unsupported expression as default value" + for bad_default_value in ( + "{1, 2, 3}", + "3 if bool() else 4", + "[x for x in range(42)]" + ): + with self.subTest(bad_default=bad_default_value): + block = template.format(default=bad_default_value) + self.expect_failure(block, err, lineno=2) + + def test_unspecified_not_allowed_as_default_value(self): + block = """ + module os + os.access + follow_symlinks: int(c_default='MAXSIZE') = unspecified + """ + err = "'unspecified' is not a legal default value!" + exc = self.expect_failure(block, err, lineno=2) + self.assertNotIn('Malformed expression given as default value', str(exc)) + + def test_malformed_expression_as_default_value(self): + block = """ + module os + os.access + follow_symlinks: int(c_default='MAXSIZE') = 1/0 + """ + err = "Malformed expression given as default value" + self.expect_failure(block, err, lineno=2) + def test_param_default_expr_binop(self): err = ( "When you specify an expression ('a + b') as your default value, " @@ -964,7 +993,6 @@ def test_param_no_docstring(self): follow_symlinks: bool = True something_else: str = '' """) - p = function.parameters['follow_symlinks'] self.assertEqual(3, len(function.parameters)) conv = function.parameters['something_else'].converter self.assertIsInstance(conv, clinic.str_converter) @@ -998,8 +1026,12 @@ def test_function_docstring(self): path: str Path to be examined + Ensure that multiple lines are indented correctly. Perform a stat system call on the given path. + + Ensure that multiple lines are indented correctly. + Ensure that multiple lines are indented correctly. """) self.checkDocstring(function, """ stat($module, /, path) @@ -1009,6 +1041,10 @@ def test_function_docstring(self): path Path to be examined + Ensure that multiple lines are indented correctly. + + Ensure that multiple lines are indented correctly. + Ensure that multiple lines are indented correctly. """) def test_docstring_trailing_whitespace(self): @@ -1110,6 +1146,28 @@ def test_c_name(self): """) self.assertEqual("os_stat_fn", function.c_basename) + def test_base_invalid_syntax(self): + block = """ + module os + os.stat + invalid syntax: int = 42 + """ + err = dedent(r""" + Function 'stat' has an invalid parameter declaration: + \s+'invalid syntax: int = 42' + """).strip() + with self.assertRaisesRegex(clinic.ClinicError, err): + self.parse_function(block) + + def test_param_default_invalid_syntax(self): + block = """ + module os + os.stat + x: int = invalid syntax + """ + err = r"Syntax error: 'x = invalid syntax\n'" + self.expect_failure(block, err, lineno=2) + def test_cloning_nonexistent_function_correctly_fails(self): block = """ cloned = fooooooooooooooooo @@ -1119,7 +1177,7 @@ def test_cloning_nonexistent_function_correctly_fails(self): with support.captured_stderr() as stderr: self.expect_failure(block, err, lineno=0) expected_debug_print = dedent("""\ - cls=None, module=, existing='fooooooooooooooooo' + cls=None, module=, existing='fooooooooooooooooo' (cls or module).functions=[] """) stderr = stderr.getvalue() @@ -1417,6 +1475,27 @@ def test_disallowed_grouping__no_matching_bracket(self): err = "Function 'empty_group' has a ']' without a matching '['" self.expect_failure(block, err) + def test_disallowed_grouping__must_be_position_only(self): + dataset = (""" + with_kwds + [ + * + a: object + ] + """, """ + with_kwds + [ + a: object + ] + """) + err = ( + "You cannot use optional groups ('[' and ']') unless all " + "parameters are positional-only ('/')" + ) + for block in dataset: + with self.subTest(block=block): + self.expect_failure(block, err) + def test_no_parameters(self): function = self.parse_function(""" module foo @@ -1461,6 +1540,11 @@ def test_illegal_c_basename(self): err = "Illegal C basename: '935'" self.expect_failure(block, err) + def test_no_c_basename(self): + block = "foo as " + err = "No C basename provided after 'as' keyword" + self.expect_failure(block, err, strip=False) + def test_single_star(self): block = """ module foo @@ -1478,11 +1562,205 @@ def test_parameters_required_after_star(self): "module foo\nfoo.bar\n this: int\n *", "module foo\nfoo.bar\n this: int\n *\nDocstring.", ) - err = "Function 'bar' specifies '*' without any parameters afterwards." + err = "Function 'bar' specifies '*' without following parameters." for block in dataset: with self.subTest(block=block): self.expect_failure(block, err) + def test_fulldisplayname_class(self): + dataset = ( + ("T", """ + class T "void *" "" + T.__init__ + """), + ("m.T", """ + module m + class m.T "void *" "" + @classmethod + m.T.__new__ + """), + ("m.T.C", """ + module m + class m.T "void *" "" + class m.T.C "void *" "" + m.T.C.__init__ + """), + ) + for name, code in dataset: + with self.subTest(name=name, code=code): + block = self.parse(code) + func = block.signatures[-1] + self.assertEqual(func.fulldisplayname, name) + + def test_fulldisplayname_meth(self): + dataset = ( + ("func", "func"), + ("m.func", """ + module m + m.func + """), + ("T.meth", """ + class T "void *" "" + T.meth + """), + ("m.T.meth", """ + module m + class m.T "void *" "" + m.T.meth + """), + ("m.T.C.meth", """ + module m + class m.T "void *" "" + class m.T.C "void *" "" + m.T.C.meth + """), + ) + for name, code in dataset: + with self.subTest(name=name, code=code): + block = self.parse(code) + func = block.signatures[-1] + self.assertEqual(func.fulldisplayname, name) + + def test_depr_star_invalid_format_1(self): + block = """ + module foo + foo.bar + this: int + * [from 3] + Docstring. + """ + err = ( + "Function 'bar': expected format '[from major.minor]' " + "where 'major' and 'minor' are integers; got '3'" + ) + self.expect_failure(block, err, lineno=3) + + def test_depr_star_invalid_format_2(self): + block = """ + module foo + foo.bar + this: int + * [from a.b] + Docstring. + """ + err = ( + "Function 'bar': expected format '[from major.minor]' " + "where 'major' and 'minor' are integers; got 'a.b'" + ) + self.expect_failure(block, err, lineno=3) + + def test_depr_star_invalid_format_3(self): + block = """ + module foo + foo.bar + this: int + * [from 1.2.3] + Docstring. + """ + err = ( + "Function 'bar': expected format '[from major.minor]' " + "where 'major' and 'minor' are integers; got '1.2.3'" + ) + self.expect_failure(block, err, lineno=3) + + def test_parameters_required_after_depr_star(self): + block = """ + module foo + foo.bar + this: int + * [from 3.14] + Docstring. + """ + err = ( + "Function 'bar' specifies '* [from ...]' without " + "following parameters." + ) + self.expect_failure(block, err, lineno=4) + + def test_parameters_required_after_depr_star2(self): + block = """ + module foo + foo.bar + a: int + * [from 3.14] + * + b: int + Docstring. + """ + err = ( + "Function 'bar' specifies '* [from ...]' without " + "following parameters." + ) + self.expect_failure(block, err, lineno=4) + + def test_depr_star_must_come_before_star(self): + block = """ + module foo + foo.bar + this: int + * + * [from 3.14] + Docstring. + """ + err = "Function 'bar': '* [from ...]' must precede '*'" + self.expect_failure(block, err, lineno=4) + + def test_depr_star_duplicate(self): + block = """ + module foo + foo.bar + a: int + * [from 3.14] + b: int + * [from 3.14] + c: int + Docstring. + """ + err = "Function 'bar' uses '* [from 3.14]' more than once." + self.expect_failure(block, err, lineno=5) + + def test_depr_star_duplicate2(self): + block = """ + module foo + foo.bar + a: int + * [from 3.14] + b: int + * [from 3.15] + c: int + Docstring. + """ + err = "Function 'bar': '* [from 3.15]' must precede '* [from 3.14]'" + self.expect_failure(block, err, lineno=5) + + def test_depr_slash_duplicate(self): + block = """ + module foo + foo.bar + a: int + / [from 3.14] + b: int + / [from 3.14] + c: int + Docstring. + """ + err = "Function 'bar' uses '/ [from 3.14]' more than once." + self.expect_failure(block, err, lineno=5) + + def test_depr_slash_duplicate2(self): + block = """ + module foo + foo.bar + a: int + / [from 3.15] + b: int + / [from 3.14] + c: int + Docstring. + """ + err = "Function 'bar': '/ [from 3.14]' must precede '/ [from 3.15]'" + self.expect_failure(block, err, lineno=5) + def test_single_slash(self): block = """ module foo @@ -1496,6 +1774,34 @@ def test_single_slash(self): ) self.expect_failure(block, err) + def test_parameters_required_before_depr_slash(self): + block = """ + module foo + foo.bar + / [from 3.14] + Docstring. + """ + err = ( + "Function 'bar' specifies '/ [from ...]' without " + "preceding parameters." + ) + self.expect_failure(block, err, lineno=2) + + def test_parameters_required_before_depr_slash2(self): + block = """ + module foo + foo.bar + a: int + / + / [from 3.14] + Docstring. + """ + err = ( + "Function 'bar' specifies '/ [from ...]' without " + "preceding parameters." + ) + self.expect_failure(block, err, lineno=4) + def test_double_slash(self): block = """ module foo @@ -1518,12 +1824,61 @@ def test_mix_star_and_slash(self): z: int / """ - err = ( - "Function 'bar' mixes keyword-only and positional-only parameters, " - "which is unsupported." - ) + err = "Function 'bar': '/' must precede '*'" self.expect_failure(block, err) + def test_depr_star_must_come_after_slash(self): + block = """ + module foo + foo.bar + a: int + * [from 3.14] + / + b: int + Docstring. + """ + err = "Function 'bar': '/' must precede '* [from ...]'" + self.expect_failure(block, err, lineno=4) + + def test_depr_star_must_come_after_depr_slash(self): + block = """ + module foo + foo.bar + a: int + * [from 3.14] + / [from 3.14] + b: int + Docstring. + """ + err = "Function 'bar': '/ [from ...]' must precede '* [from ...]'" + self.expect_failure(block, err, lineno=4) + + def test_star_must_come_after_depr_slash(self): + block = """ + module foo + foo.bar + a: int + * + / [from 3.14] + b: int + Docstring. + """ + err = "Function 'bar': '/ [from ...]' must precede '*'" + self.expect_failure(block, err, lineno=4) + + def test_depr_slash_must_come_after_slash(self): + block = """ + module foo + foo.bar + a: int + / [from 3.14] + / + b: int + Docstring. + """ + err = "Function 'bar': '/' must precede '/ [from ...]'" + self.expect_failure(block, err, lineno=4) + def test_parameters_not_permitted_after_slash_for_now(self): block = """ module foo @@ -1646,8 +2001,7 @@ def test_indent_stack_illegal_outdent(self): self.expect_failure(block, err) def test_directive(self): - c = FakeClinic() - parser = DSLParser(c) + parser = DSLParser(_make_clinic()) parser.flag = False parser.directives['setflag'] = lambda : setattr(parser, 'flag', True) block = clinic.Block("setflag") @@ -1753,7 +2107,7 @@ class Foo "" "" self.parse_function(block) def test_new_must_be_a_class_method(self): - err = "__new__ must be a class method!" + err = "'__new__' must be a class method!" block = """ module foo class Foo "" "" @@ -1762,14 +2116,100 @@ class Foo "" "" self.expect_failure(block, err, lineno=2) def test_init_must_be_a_normal_method(self): - err = "__init__ must be a normal method, not a class or static method!" + err_template = "'__init__' must be a normal method; got 'FunctionKind.{}'!" + annotations = { + "@classmethod": "CLASS_METHOD", + "@staticmethod": "STATIC_METHOD", + "@getter": "GETTER", + } + for annotation, invalid_kind in annotations.items(): + with self.subTest(annotation=annotation, invalid_kind=invalid_kind): + block = f""" + module foo + class Foo "" "" + {annotation} + Foo.__init__ + """ + expected_error = err_template.format(invalid_kind) + self.expect_failure(block, expected_error, lineno=3) + + def test_invalid_getset(self): + annotations = ["@getter", "@setter"] + for annotation in annotations: + with self.subTest(annotation=annotation): + block = f""" + module foo + class Foo "" "" + {annotation} + Foo.property -> int + """ + expected_error = f"{annotation} method cannot define a return type" + self.expect_failure(block, expected_error, lineno=3) + + block = f""" + module foo + class Foo "" "" + {annotation} + Foo.property + obj: int + / + """ + expected_error = f"{annotation} method cannot define parameters" + self.expect_failure(block, expected_error) + + def test_setter_docstring(self): block = """ module foo class Foo "" "" - @classmethod - Foo.__init__ + @setter + Foo.property + + foo + + bar + [clinic start generated code]*/ """ - self.expect_failure(block, err, lineno=3) + expected_error = "docstrings are only supported for @getter, not @setter" + self.expect_failure(block, expected_error) + + def test_duplicate_getset(self): + annotations = ["@getter", "@setter"] + for annotation in annotations: + with self.subTest(annotation=annotation): + block = f""" + module foo + class Foo "" "" + {annotation} + {annotation} + Foo.property -> int + """ + expected_error = f"Cannot apply {annotation} twice to the same function!" + self.expect_failure(block, expected_error, lineno=3) + + def test_getter_and_setter_disallowed_on_same_function(self): + dup_annotations = [("@getter", "@setter"), ("@setter", "@getter")] + for dup in dup_annotations: + with self.subTest(dup=dup): + block = f""" + module foo + class Foo "" "" + {dup[0]} + {dup[1]} + Foo.property -> int + """ + expected_error = "Cannot apply both @getter and @setter to the same function!" + self.expect_failure(block, expected_error, lineno=3) + + def test_getset_no_class(self): + for annotation in "@getter", "@setter": + with self.subTest(annotation=annotation): + block = f""" + module m + {annotation} + m.func + """ + expected_error = "@getter and @setter must be methods" + self.expect_failure(block, expected_error, lineno=2) def test_duplicate_coexist(self): err = "Called @coexist twice" @@ -1825,10 +2265,6 @@ def test_scaffolding(self): self.assertEqual(repr(clinic.NULL), '') # test that fail fails - expected = ( - 'Error in file "clown.txt" on line 69:\n' - 'The igloos are melting!\n' - ) with support.captured_stdout() as stdout: errmsg = 'The igloos are melting' with self.assertRaisesRegex(clinic.ClinicError, errmsg) as cm: @@ -1836,6 +2272,7 @@ def test_scaffolding(self): exc = cm.exception self.assertEqual(exc.filename, 'clown.txt') self.assertEqual(exc.lineno, 69) + self.assertEqual(stdout.getvalue(), "") def test_non_ascii_character_in_docstring(self): block = """ @@ -1868,7 +2305,7 @@ def test_illegal_c_identifier(self): self.expect_failure(block, err, lineno=2) def test_cannot_convert_special_method(self): - err = "__len__ is a special method and cannot be converted" + err = "'__len__' is a special method and cannot be converted" block = """ class T "" "" T.__len__ @@ -1909,10 +2346,10 @@ def test_invalid_legacy_converter(self): self.expect_failure(block, err, lineno=1) def test_parent_class_or_module_does_not_exist(self): - err = "Parent class or module 'z' does not exist" + err = "Parent class or module 'baz' does not exist" block = """ module m - z.func + baz.func """ self.expect_failure(block, err, lineno=1) @@ -1997,7 +2434,7 @@ def expect_failure(self, *args): def test_external(self): CLINIC_TEST = 'clinic.test.c' source = support.findfile(CLINIC_TEST) - with open(source, 'r', encoding='utf-8') as f: + with open(source, encoding='utf-8') as f: orig_contents = f.read() # Run clinic CLI and verify that it does not complain. @@ -2005,7 +2442,7 @@ def test_external(self): out = self.expect_success("-f", "-o", TESTFN, source) self.assertEqual(out, "") - with open(TESTFN, 'r', encoding='utf-8') as f: + with open(TESTFN, encoding='utf-8') as f: new_contents = f.read() self.assertEqual(new_contents, orig_contents) @@ -2063,11 +2500,12 @@ def test_cli_force(self): # Verify by checking the checksum. checksum = ( "/*[clinic end generated code: " - "output=2124c291eb067d76 input=9543a8d2da235301]*/\n" + "output=c16447c01510dfb3 input=9543a8d2da235301]*/\n" ) - with open(fn, 'r', encoding='utf-8') as f: + with open(fn, encoding='utf-8') as f: generated = f.read() - self.assertTrue(generated.endswith(checksum)) + self.assertTrue(generated.endswith(checksum), + (generated, checksum)) def test_cli_make(self): c_code = dedent(""" @@ -2112,6 +2550,35 @@ def create_files(files, srcdir, code): path = os.path.join(ext_path, filename) self.assertNotIn(path, out) + def test_cli_make_exclude(self): + code = dedent(""" + /*[clinic input] + [clinic start generated code]*/ + """) + with os_helper.temp_dir(quiet=False) as tmp_dir: + # add some folders, some C files and a Python file + for fn in "file1.c", "file2.c", "file3.c", "file4.c": + path = os.path.join(tmp_dir, fn) + with open(path, "w", encoding="utf-8") as f: + f.write(code) + + # Run clinic in verbose mode with --make on tmpdir. + # Exclude file2.c and file3.c. + out = self.expect_success( + "-v", "--make", "--srcdir", tmp_dir, + "--exclude", os.path.join(tmp_dir, "file2.c"), + # The added ./ should be normalised away. + "--exclude", os.path.join(tmp_dir, "./file3.c"), + # Relative paths should also work. + "--exclude", "file4.c" + ) + + # expect verbose mode to only mention the C files in tmp_dir + self.assertIn("file1.c", out) + self.assertNotIn("file2.c", out) + self.assertNotIn("file3.c", out) + self.assertNotIn("file4.c", out) + def test_cli_verbose(self): with os_helper.temp_dir() as tmp_dir: fn = os.path.join(tmp_dir, "test.c") @@ -2242,12 +2709,6 @@ def test_file_dest(self): 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_VAR(func__doc__); PyDoc_STRVAR(func__doc__, @@ -2260,7 +2721,7 @@ def test_file_dest(self): static PyObject * func(PyObject *module, PyObject *a) - /*[clinic end generated code: output=56c09670e89a0d9a input=a9049054013a1b77]*/ + /*[clinic end generated code: output=3dde2d13002165b9 input=a9049054013a1b77]*/ """) with os_helper.temp_dir() as tmp_dir: in_fn = os.path.join(tmp_dir, "test.c") @@ -2275,7 +2736,7 @@ def test_file_dest(self): "not overwriting!") self.assertIn(expected_err, err) # Run clinic again, this time with the -f option. - out = self.expect_success("-f", in_fn) + _ = self.expect_success("-f", in_fn) # Read back the generated output. with open(in_fn, encoding="utf-8") as f: data = f.read() @@ -2295,6 +2756,39 @@ class ClinicFunctionalTest(unittest.TestCase): locals().update((name, getattr(ac_tester, name)) for name in dir(ac_tester) if name.startswith('test_')) + def check_depr(self, regex, fn, /, *args, **kwds): + with self.assertWarnsRegex(DeprecationWarning, regex) as cm: + # Record the line number, so we're sure we've got the correct stack + # level on the deprecation warning. + _, lineno = fn(*args, **kwds), sys._getframe().f_lineno + self.assertEqual(cm.filename, __file__) + self.assertEqual(cm.lineno, lineno) + + def check_depr_star(self, pnames, fn, /, *args, name=None, **kwds): + if name is None: + name = fn.__qualname__ + if isinstance(fn, type): + name = f'{fn.__module__}.{name}' + regex = ( + fr"Passing( more than)?( [0-9]+)? positional argument(s)? to " + fr"{re.escape(name)}\(\) is deprecated. Parameters? {pnames} will " + fr"become( a)? keyword-only parameters? in Python 3\.14" + ) + self.check_depr(regex, fn, *args, **kwds) + + def check_depr_kwd(self, pnames, fn, *args, name=None, **kwds): + if name is None: + name = fn.__qualname__ + if isinstance(fn, type): + name = f'{fn.__module__}.{name}' + pl = 's' if ' ' in pnames else '' + regex = ( + fr"Passing keyword argument{pl} {pnames} to " + fr"{re.escape(name)}\(\) is deprecated. Parameter{pl} {pnames} " + fr"will become positional-only in Python 3\.14." + ) + self.check_depr(regex, fn, *args, **kwds) + def test_objects_converter(self): with self.assertRaises(TypeError): ac_tester.objects_converter() @@ -2696,6 +3190,10 @@ def test_posonly_vararg(self): self.assertEqual(ac_tester.posonly_vararg(1, 2), (1, 2, ())) self.assertEqual(ac_tester.posonly_vararg(1, b=2), (1, 2, ())) self.assertEqual(ac_tester.posonly_vararg(1, 2, 3, 4), (1, 2, (3, 4))) + with self.assertRaises(TypeError): + ac_tester.posonly_vararg(b=4) + with self.assertRaises(TypeError): + ac_tester.posonly_vararg(1, 2, 3, b=4) def test_vararg_and_posonly(self): with self.assertRaises(TypeError): @@ -2746,6 +3244,37 @@ def test_gh_99240_double_free(self): with self.assertRaisesRegex(TypeError, err): ac_tester.gh_99240_double_free('a', '\0b') + def test_null_or_tuple_for_varargs(self): + # All of these should not crash: + valid_args_for_test = [ + (('a',), {}, + ('a', (), False)), + (('a', 1, 2, 3), {'covariant': True}, + ('a', (1, 2, 3), True)), + ((), {'name': 'a'}, + ('a', (), False)), + ((), {'name': 'a', 'covariant': True}, + ('a', (), True)), + ((), {'covariant': True, 'name': 'a'}, + ('a', (), True)), + ] + for args, kwargs, expected in valid_args_for_test: + with self.subTest(args=args, kwargs=kwargs): + self.assertEqual( + ac_tester.null_or_tuple_for_varargs(*args, **kwargs), + expected, + ) + + def test_null_or_tuple_for_varargs_error(self): + with self.assertRaises(TypeError): + ac_tester.null_or_tuple_for_varargs(covariant=True) + with self.assertRaises(TypeError): + ac_tester.null_or_tuple_for_varargs(1, name='a') + with self.assertRaises(TypeError): + ac_tester.null_or_tuple_for_varargs(1, 2, 3, name='a', covariant=True) + with self.assertRaises(TypeError): + ac_tester.null_or_tuple_for_varargs(1, 2, 3, covariant=True, name='a') + def test_cloned_func_exception_message(self): incorrect_arg = -1 # f1() and f2() accept a single str with self.assertRaisesRegex(TypeError, "clone_f1"): @@ -2759,6 +3288,323 @@ def test_cloned_func_with_converter_exception_message(self): func = getattr(ac_tester, name) self.assertEqual(func(), name) + def test_depr_star_new(self): + cls = ac_tester.DeprStarNew + cls() + cls(a=None) + self.check_depr_star("'a'", cls, None) + + def test_depr_star_new_cloned(self): + fn = ac_tester.DeprStarNew().cloned + fn() + fn(a=None) + self.check_depr_star("'a'", fn, None, name='_testclinic.DeprStarNew.cloned') + + def test_depr_star_init(self): + cls = ac_tester.DeprStarInit + cls() + cls(a=None) + self.check_depr_star("'a'", cls, None) + + def test_depr_star_init_cloned(self): + fn = ac_tester.DeprStarInit().cloned + fn() + fn(a=None) + self.check_depr_star("'a'", fn, None, name='_testclinic.DeprStarInit.cloned') + + def test_depr_star_init_noinline(self): + cls = ac_tester.DeprStarInitNoInline + self.assertRaises(TypeError, cls, "a") + cls(a="a", b="b") + cls(a="a", b="b", c="c") + cls("a", b="b") + cls("a", b="b", c="c") + check = partial(self.check_depr_star, "'b' and 'c'", cls) + check("a", "b") + check("a", "b", "c") + check("a", "b", c="c") + self.assertRaises(TypeError, cls, "a", "b", "c", "d") + + def test_depr_kwd_new(self): + cls = ac_tester.DeprKwdNew + cls() + cls(None) + self.check_depr_kwd("'a'", cls, a=None) + + def test_depr_kwd_init(self): + cls = ac_tester.DeprKwdInit + cls() + cls(None) + self.check_depr_kwd("'a'", cls, a=None) + + def test_depr_kwd_init_noinline(self): + cls = ac_tester.DeprKwdInitNoInline + cls = ac_tester.depr_star_noinline + self.assertRaises(TypeError, cls, "a") + cls(a="a", b="b") + cls(a="a", b="b", c="c") + cls("a", b="b") + cls("a", b="b", c="c") + check = partial(self.check_depr_star, "'b' and 'c'", cls) + check("a", "b") + check("a", "b", "c") + check("a", "b", c="c") + self.assertRaises(TypeError, cls, "a", "b", "c", "d") + + def test_depr_star_pos0_len1(self): + fn = ac_tester.depr_star_pos0_len1 + fn(a=None) + self.check_depr_star("'a'", fn, "a") + + def test_depr_star_pos0_len2(self): + fn = ac_tester.depr_star_pos0_len2 + fn(a=0, b=0) + check = partial(self.check_depr_star, "'a' and 'b'", fn) + check("a", b=0) + check("a", "b") + + def test_depr_star_pos0_len3_with_kwd(self): + fn = ac_tester.depr_star_pos0_len3_with_kwd + fn(a=0, b=0, c=0, d=0) + check = partial(self.check_depr_star, "'a', 'b' and 'c'", fn) + check("a", b=0, c=0, d=0) + check("a", "b", c=0, d=0) + check("a", "b", "c", d=0) + + def test_depr_star_pos1_len1_opt(self): + fn = ac_tester.depr_star_pos1_len1_opt + fn(a=0, b=0) + fn("a", b=0) + fn(a=0) # b is optional + check = partial(self.check_depr_star, "'b'", fn) + check("a", "b") + + def test_depr_star_pos1_len1(self): + fn = ac_tester.depr_star_pos1_len1 + fn(a=0, b=0) + fn("a", b=0) + check = partial(self.check_depr_star, "'b'", fn) + check("a", "b") + + def test_depr_star_pos1_len2_with_kwd(self): + fn = ac_tester.depr_star_pos1_len2_with_kwd + fn(a=0, b=0, c=0, d=0), + fn("a", b=0, c=0, d=0), + check = partial(self.check_depr_star, "'b' and 'c'", fn) + check("a", "b", c=0, d=0), + check("a", "b", "c", d=0), + + def test_depr_star_pos2_len1(self): + fn = ac_tester.depr_star_pos2_len1 + fn(a=0, b=0, c=0) + fn("a", b=0, c=0) + fn("a", "b", c=0) + check = partial(self.check_depr_star, "'c'", fn) + check("a", "b", "c") + + def test_depr_star_pos2_len2(self): + fn = ac_tester.depr_star_pos2_len2 + fn(a=0, b=0, c=0, d=0) + fn("a", b=0, c=0, d=0) + fn("a", "b", c=0, d=0) + check = partial(self.check_depr_star, "'c' and 'd'", fn) + check("a", "b", "c", d=0) + check("a", "b", "c", "d") + + def test_depr_star_pos2_len2_with_kwd(self): + fn = ac_tester.depr_star_pos2_len2_with_kwd + fn(a=0, b=0, c=0, d=0, e=0) + fn("a", b=0, c=0, d=0, e=0) + fn("a", "b", c=0, d=0, e=0) + check = partial(self.check_depr_star, "'c' and 'd'", fn) + check("a", "b", "c", d=0, e=0) + check("a", "b", "c", "d", e=0) + + def test_depr_star_noinline(self): + fn = ac_tester.depr_star_noinline + self.assertRaises(TypeError, fn, "a") + fn(a="a", b="b") + fn(a="a", b="b", c="c") + fn("a", b="b") + fn("a", b="b", c="c") + check = partial(self.check_depr_star, "'b' and 'c'", fn) + check("a", "b") + check("a", "b", "c") + check("a", "b", c="c") + self.assertRaises(TypeError, fn, "a", "b", "c", "d") + + def test_depr_star_multi(self): + fn = ac_tester.depr_star_multi + self.assertRaises(TypeError, fn, "a") + fn("a", b="b", c="c", d="d", e="e", f="f", g="g", h="h") + errmsg = ( + "Passing more than 1 positional argument to depr_star_multi() is deprecated. " + "Parameter 'b' will become a keyword-only parameter in Python 3.16. " + "Parameters 'c' and 'd' will become keyword-only parameters in Python 3.15. " + "Parameters 'e', 'f' and 'g' will become keyword-only parameters in Python 3.14.") + check = partial(self.check_depr, re.escape(errmsg), fn) + check("a", "b", c="c", d="d", e="e", f="f", g="g", h="h") + check("a", "b", "c", d="d", e="e", f="f", g="g", h="h") + check("a", "b", "c", "d", e="e", f="f", g="g", h="h") + check("a", "b", "c", "d", "e", f="f", g="g", h="h") + check("a", "b", "c", "d", "e", "f", g="g", h="h") + check("a", "b", "c", "d", "e", "f", "g", h="h") + self.assertRaises(TypeError, fn, "a", "b", "c", "d", "e", "f", "g", "h") + + def test_depr_kwd_required_1(self): + fn = ac_tester.depr_kwd_required_1 + fn("a", "b") + self.assertRaises(TypeError, fn, "a") + self.assertRaises(TypeError, fn, "a", "b", "c") + check = partial(self.check_depr_kwd, "'b'", fn) + check("a", b="b") + self.assertRaises(TypeError, fn, a="a", b="b") + + def test_depr_kwd_required_2(self): + fn = ac_tester.depr_kwd_required_2 + fn("a", "b", "c") + self.assertRaises(TypeError, fn, "a", "b") + self.assertRaises(TypeError, fn, "a", "b", "c", "d") + check = partial(self.check_depr_kwd, "'b' and 'c'", fn) + check("a", "b", c="c") + check("a", b="b", c="c") + self.assertRaises(TypeError, fn, a="a", b="b", c="c") + + def test_depr_kwd_optional_1(self): + fn = ac_tester.depr_kwd_optional_1 + fn("a") + fn("a", "b") + self.assertRaises(TypeError, fn) + self.assertRaises(TypeError, fn, "a", "b", "c") + check = partial(self.check_depr_kwd, "'b'", fn) + check("a", b="b") + self.assertRaises(TypeError, fn, a="a", b="b") + + def test_depr_kwd_optional_2(self): + fn = ac_tester.depr_kwd_optional_2 + fn("a") + fn("a", "b") + fn("a", "b", "c") + self.assertRaises(TypeError, fn) + self.assertRaises(TypeError, fn, "a", "b", "c", "d") + check = partial(self.check_depr_kwd, "'b' and 'c'", fn) + check("a", b="b") + check("a", c="c") + check("a", b="b", c="c") + check("a", c="c", b="b") + check("a", "b", c="c") + self.assertRaises(TypeError, fn, a="a", b="b", c="c") + + def test_depr_kwd_optional_3(self): + fn = ac_tester.depr_kwd_optional_3 + fn() + fn("a") + fn("a", "b") + fn("a", "b", "c") + self.assertRaises(TypeError, fn, "a", "b", "c", "d") + check = partial(self.check_depr_kwd, "'a', 'b' and 'c'", fn) + check("a", "b", c="c") + check("a", b="b") + check(a="a") + + def test_depr_kwd_required_optional(self): + fn = ac_tester.depr_kwd_required_optional + fn("a", "b") + fn("a", "b", "c") + self.assertRaises(TypeError, fn) + self.assertRaises(TypeError, fn, "a") + self.assertRaises(TypeError, fn, "a", "b", "c", "d") + check = partial(self.check_depr_kwd, "'b' and 'c'", fn) + check("a", b="b") + check("a", b="b", c="c") + check("a", c="c", b="b") + check("a", "b", c="c") + self.assertRaises(TypeError, fn, "a", c="c") + self.assertRaises(TypeError, fn, a="a", b="b", c="c") + + def test_depr_kwd_noinline(self): + fn = ac_tester.depr_kwd_noinline + fn("a", "b") + fn("a", "b", "c") + self.assertRaises(TypeError, fn, "a") + check = partial(self.check_depr_kwd, "'b' and 'c'", fn) + check("a", b="b") + check("a", b="b", c="c") + check("a", c="c", b="b") + check("a", "b", c="c") + self.assertRaises(TypeError, fn, "a", c="c") + self.assertRaises(TypeError, fn, a="a", b="b", c="c") + + def test_depr_kwd_multi(self): + fn = ac_tester.depr_kwd_multi + fn("a", "b", "c", "d", "e", "f", "g", h="h") + errmsg = ( + "Passing keyword arguments 'b', 'c', 'd', 'e', 'f' and 'g' to depr_kwd_multi() is deprecated. " + "Parameter 'b' will become positional-only in Python 3.14. " + "Parameters 'c' and 'd' will become positional-only in Python 3.15. " + "Parameters 'e', 'f' and 'g' will become positional-only in Python 3.16.") + check = partial(self.check_depr, re.escape(errmsg), fn) + check("a", "b", "c", "d", "e", "f", g="g", h="h") + check("a", "b", "c", "d", "e", f="f", g="g", h="h") + check("a", "b", "c", "d", e="e", f="f", g="g", h="h") + check("a", "b", "c", d="d", e="e", f="f", g="g", h="h") + check("a", "b", c="c", d="d", e="e", f="f", g="g", h="h") + check("a", b="b", c="c", d="d", e="e", f="f", g="g", h="h") + self.assertRaises(TypeError, fn, a="a", b="b", c="c", d="d", e="e", f="f", g="g", h="h") + + def test_depr_multi(self): + fn = ac_tester.depr_multi + self.assertRaises(TypeError, fn, "a", "b", "c", "d", "e", "f", "g") + errmsg = ( + "Passing more than 4 positional arguments to depr_multi() is deprecated. " + "Parameter 'e' will become a keyword-only parameter in Python 3.15. " + "Parameter 'f' will become a keyword-only parameter in Python 3.14.") + check = partial(self.check_depr, re.escape(errmsg), fn) + check("a", "b", "c", "d", "e", "f", g="g") + check("a", "b", "c", "d", "e", f="f", g="g") + fn("a", "b", "c", "d", e="e", f="f", g="g") + fn("a", "b", "c", d="d", e="e", f="f", g="g") + errmsg = ( + "Passing keyword arguments 'b' and 'c' to depr_multi() is deprecated. " + "Parameter 'b' will become positional-only in Python 3.14. " + "Parameter 'c' will become positional-only in Python 3.15.") + check = partial(self.check_depr, re.escape(errmsg), fn) + check("a", "b", c="c", d="d", e="e", f="f", g="g") + check("a", b="b", c="c", d="d", e="e", f="f", g="g") + self.assertRaises(TypeError, fn, a="a", b="b", c="c", d="d", e="e", f="f", g="g") + + +try: + import _testclinic_limited +except ImportError: + _testclinic_limited = None + +@unittest.skipIf(_testclinic_limited is None, "_testclinic_limited is missing") +class LimitedCAPIFunctionalTest(unittest.TestCase): + locals().update((name, getattr(_testclinic_limited, name)) + for name in dir(_testclinic_limited) if name.startswith('test_')) + + def test_my_int_func(self): + with self.assertRaises(TypeError): + _testclinic_limited.my_int_func() + self.assertEqual(_testclinic_limited.my_int_func(3), 3) + with self.assertRaises(TypeError): + _testclinic_limited.my_int_func(1.0) + with self.assertRaises(TypeError): + _testclinic_limited.my_int_func("xyz") + + def test_my_int_sum(self): + with self.assertRaises(TypeError): + _testclinic_limited.my_int_sum() + with self.assertRaises(TypeError): + _testclinic_limited.my_int_sum(1) + self.assertEqual(_testclinic_limited.my_int_sum(1, 2), 3) + with self.assertRaises(TypeError): + _testclinic_limited.my_int_sum(1.0, 2) + with self.assertRaises(TypeError): + _testclinic_limited.my_int_sum(1, "str") + + class PermutationTests(unittest.TestCase): """Test permutation support functions.""" @@ -2884,7 +3730,7 @@ def test_strip_leading_and_trailing_blank_lines(self): ) for lines, expected in dataset: with self.subTest(lines=lines, expected=expected): - out = clinic.strip_leading_and_trailing_blank_lines(lines) + out = libclinic.normalize_snippet(lines) self.assertEqual(out, expected) def test_normalize_snippet(self): @@ -2913,63 +3759,33 @@ def test_normalize_snippet(self): expected_outputs = {0: zero_indent, 4: four_indent, 8: eight_indent} for indent, expected in expected_outputs.items(): with self.subTest(indent=indent): - actual = clinic.normalize_snippet(snippet, indent=indent) + actual = libclinic.normalize_snippet(snippet, indent=indent) self.assertEqual(actual, expected) - def test_accumulator(self): - acc = clinic.text_accumulator() - self.assertEqual(acc.output(), "") - acc.append("a") - self.assertEqual(acc.output(), "a") - self.assertEqual(acc.output(), "") - acc.append("b") - self.assertEqual(acc.output(), "b") - self.assertEqual(acc.output(), "") - acc.append("c") - acc.append("d") - self.assertEqual(acc.output(), "cd") - self.assertEqual(acc.output(), "") - - def test_quoted_for_c_string(self): + def test_escaped_docstring(self): dataset = ( # input, expected - (r"abc", r"abc"), - (r"\abc", r"\\abc"), - (r"\a\bc", r"\\a\\bc"), - (r"\a\\bc", r"\\a\\\\bc"), - (r'"abc"', r'\"abc\"'), - (r"'a'", r"\'a\'"), + (r"abc", r'"abc"'), + (r"\abc", r'"\\abc"'), + (r"\a\bc", r'"\\a\\bc"'), + (r"\a\\bc", r'"\\a\\\\bc"'), + (r'"abc"', r'"\"abc\""'), + (r"'a'", r'"\'a\'"'), ) for line, expected in dataset: with self.subTest(line=line, expected=expected): - out = clinic.quoted_for_c_string(line) + out = libclinic.docstring_for_c_string(line) self.assertEqual(out, expected) - def test_rstrip_lines(self): - lines = ( - "a \n" - "b\n" - " c\n" - " d \n" - ) - expected = ( - "a\n" - "b\n" - " c\n" - " d\n" - ) - out = clinic.rstrip_lines(lines) - self.assertEqual(out, expected) - def test_format_escape(self): line = "{}, {a}" expected = "{{}}, {{a}}" - out = clinic.format_escape(line) + out = libclinic.format_escape(line) self.assertEqual(out, expected) def test_indent_all_lines(self): # Blank lines are expected to be unchanged. - self.assertEqual(clinic.indent_all_lines("", prefix="bar"), "") + self.assertEqual(libclinic.indent_all_lines("", prefix="bar"), "") lines = ( "one\n" @@ -2979,7 +3795,7 @@ def test_indent_all_lines(self): "barone\n" "bartwo" ) - out = clinic.indent_all_lines(lines, prefix="bar") + out = libclinic.indent_all_lines(lines, prefix="bar") self.assertEqual(out, expected) # If last line is empty, expect it to be unchanged. @@ -2995,12 +3811,12 @@ def test_indent_all_lines(self): "bartwo\n" "" ) - out = clinic.indent_all_lines(lines, prefix="bar") + out = libclinic.indent_all_lines(lines, prefix="bar") self.assertEqual(out, expected) def test_suffix_all_lines(self): # Blank lines are expected to be unchanged. - self.assertEqual(clinic.suffix_all_lines("", suffix="foo"), "") + self.assertEqual(libclinic.suffix_all_lines("", suffix="foo"), "") lines = ( "one\n" @@ -3010,7 +3826,7 @@ def test_suffix_all_lines(self): "onefoo\n" "twofoo" ) - out = clinic.suffix_all_lines(lines, suffix="foo") + out = libclinic.suffix_all_lines(lines, suffix="foo") self.assertEqual(out, expected) # If last line is empty, expect it to be unchanged. @@ -3026,7 +3842,7 @@ def test_suffix_all_lines(self): "twofoo\n" "" ) - out = clinic.suffix_all_lines(lines, suffix="foo") + out = libclinic.suffix_all_lines(lines, suffix="foo") self.assertEqual(out, expected) @@ -3053,22 +3869,24 @@ def test_Block_repr(self): self.assertEqual(repr(block3), expected_repr_3) def test_Destination_repr(self): + c = _make_clinic() + destination = clinic.Destination( - "foo", type="file", clinic=FakeClinic(), args=("eggs",) + "foo", type="file", clinic=c, args=("eggs",) ) self.assertEqual( repr(destination), "" ) - destination2 = clinic.Destination("bar", type="buffer", clinic=FakeClinic()) + destination2 = clinic.Destination("bar", type="buffer", clinic=c) self.assertEqual(repr(destination2), "") def test_Module_repr(self): - module = clinic.Module("foo", FakeClinic()) + module = clinic.Module("foo", _make_clinic()) self.assertRegex(repr(module), r"") def test_Class_repr(self): - cls = clinic.Class("foo", FakeClinic(), None, 'some_typedef', 'some_type_object') + cls = clinic.Class("foo", _make_clinic(), None, 'some_typedef', 'some_type_object') self.assertRegex(repr(cls), r"") def test_FunctionKind_repr(self): @@ -3082,7 +3900,7 @@ def test_FunctionKind_repr(self): def test_Function_and_Parameter_reprs(self): function = clinic.Function( name='foo', - module=FakeClinic(), + module=_make_clinic(), cls=None, c_basename=None, full_name='foofoo', @@ -3102,7 +3920,7 @@ def test_Function_and_Parameter_reprs(self): self.assertEqual(repr(parameter), "") def test_Monitor_repr(self): - monitor = clinic.cpp.Monitor() + monitor = libclinic.cpp.Monitor("test.c") self.assertRegex(repr(monitor), r"") monitor.line_number = 42 diff --git a/Lib/test/test_cmd.py b/Lib/test/test_cmd.py index 319801c71f776b..46ec82b704963d 100644 --- a/Lib/test/test_cmd.py +++ b/Lib/test/test_cmd.py @@ -9,7 +9,10 @@ import doctest import unittest import io +import textwrap from test import support +from test.support.import_helper import import_module +from test.support.pty_helper import run_pty class samplecmdclass(cmd.Cmd): """ @@ -244,23 +247,55 @@ def test_input_reset_at_EOF(self): "(Cmd) *** Unknown syntax: EOF\n")) +class CmdPrintExceptionClass(cmd.Cmd): + """ + GH-80731 + cmd.Cmd should print the correct exception in default() + >>> mycmd = CmdPrintExceptionClass() + >>> try: + ... raise ValueError("test") + ... except ValueError: + ... mycmd.onecmd("not important") + (, ValueError('test')) + """ + + def default(self, line): + print(sys.exc_info()[:2]) + + +@support.requires_subprocess() +class CmdTestReadline(unittest.TestCase): + def setUpClass(): + # Ensure that the readline module is loaded + # If this fails, the test is skipped because SkipTest will be raised + readline = import_module('readline') + + def test_basic_completion(self): + script = textwrap.dedent(""" + import cmd + class simplecmd(cmd.Cmd): + def do_tab_completion_test(self, args): + print('tab completion success') + return True + + simplecmd().cmdloop() + """) + + # 't' and complete 'ab_completion_test' to 'tab_completion_test' + input = b"t\t\n" + + output = run_pty(script, input) + + self.assertIn(b'ab_completion_test', output) + self.assertIn(b'tab completion success', output) + def load_tests(loader, tests, pattern): tests.addTest(doctest.DocTestSuite()) return tests -def test_coverage(coverdir): - trace = support.import_module('trace') - tracer=trace.Trace(ignoredirs=[sys.base_prefix, sys.base_exec_prefix,], - trace=0, count=1) - tracer.run('import importlib; importlib.reload(cmd); test_main()') - r=tracer.results() - print("Writing coverage results...") - r.write_results(show_missing=True, summary=True, coverdir=coverdir) if __name__ == "__main__": - if "-c" in sys.argv: - test_coverage('/tmp/cmd.cover') - elif "-i" in sys.argv: + if "-i" in sys.argv: samplecmdclass().cmdloop() else: unittest.main() diff --git a/Lib/test/test_cmd_line.py b/Lib/test/test_cmd_line.py index e88b7c8572d9e8..1fe3b2fe53c0b6 100644 --- a/Lib/test/test_cmd_line.py +++ b/Lib/test/test_cmd_line.py @@ -153,6 +153,17 @@ def test_xoption_frozen_modules(self): res = assert_python_ok(*cmd) self.assertRegex(res.out.decode('utf-8'), expected) + def test_env_var_frozen_modules(self): + tests = { + ('on', 'FrozenImporter'), + ('off', 'SourceFileLoader'), + } + for raw, expected in tests: + cmd = ['-c', 'import os; print(os.__spec__.loader, end="")'] + with self.subTest(raw): + res = assert_python_ok(*cmd, PYTHON_FROZEN_MODULES=raw) + self.assertRegex(res.out.decode('utf-8'), expected) + def test_run_module(self): # Test expected operation of the '-m' switch # Switch needs an argument @@ -468,8 +479,9 @@ def test_stdout_flush_at_shutdown(self): rc, out, err = assert_python_failure('-c', code) self.assertEqual(b'', out) self.assertEqual(120, rc) - self.assertRegex(err.decode('ascii', 'ignore'), - 'Exception ignored in.*\nOSError: .*') + self.assertIn(b'Exception ignored on flushing sys.stdout:\n' + b'OSError: '.replace(b'\n', os.linesep.encode()), + err) def test_closed_stdout(self): # Issue #13444: if stdout has been explicitly closed, we should @@ -726,6 +738,8 @@ def test_xdev(self): out = self.run_xdev("-c", code, check_exitcode=False) if support.with_pymalloc(): alloc_name = "pymalloc_debug" + elif support.Py_GIL_DISABLED: + alloc_name = "mimalloc_debug" else: alloc_name = "malloc_debug" self.assertEqual(out, alloc_name) @@ -799,10 +813,16 @@ def check_pythonmalloc(self, env_var, name): self.assertEqual(proc.stdout.rstrip(), name) self.assertEqual(proc.returncode, 0) + @support.cpython_only def test_pythonmalloc(self): # Test the PYTHONMALLOC environment variable + malloc = not support.Py_GIL_DISABLED pymalloc = support.with_pymalloc() - if pymalloc: + mimalloc = support.with_mimalloc() + if support.Py_GIL_DISABLED: + default_name = 'mimalloc_debug' if support.Py_DEBUG else 'mimalloc' + default_name_debug = 'mimalloc_debug' + elif pymalloc: default_name = 'pymalloc_debug' if support.Py_DEBUG else 'pymalloc' default_name_debug = 'pymalloc_debug' else: @@ -812,14 +832,22 @@ def test_pythonmalloc(self): tests = [ (None, default_name), ('debug', default_name_debug), - ('malloc', 'malloc'), - ('malloc_debug', 'malloc_debug'), ] + if malloc: + tests.extend([ + ('malloc', 'malloc'), + ('malloc_debug', 'malloc_debug'), + ]) if pymalloc: tests.extend(( ('pymalloc', 'pymalloc'), ('pymalloc_debug', 'pymalloc_debug'), )) + if mimalloc: + tests.extend(( + ('mimalloc', 'mimalloc'), + ('mimalloc_debug', 'mimalloc_debug'), + )) for env_var, name in tests: with self.subTest(env_var=env_var, name=name): @@ -877,11 +905,8 @@ def test_int_max_str_digits(self): 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) + res2int = self.res2int current_max = sys.get_int_max_str_digits() self.assertEqual(res2int(res), (current_max, current_max)) res = assert_python_ok('-X', 'int_max_str_digits=0', '-c', code) @@ -901,6 +926,26 @@ def res2int(res): ) self.assertEqual(res2int(res), (6000, 6000)) + def test_cpu_count(self): + code = "import os; print(os.cpu_count(), os.process_cpu_count())" + res = assert_python_ok('-X', 'cpu_count=4321', '-c', code) + self.assertEqual(self.res2int(res), (4321, 4321)) + res = assert_python_ok('-c', code, PYTHON_CPU_COUNT='1234') + self.assertEqual(self.res2int(res), (1234, 1234)) + + def test_cpu_count_default(self): + code = "import os; print(os.cpu_count(), os.process_cpu_count())" + res = assert_python_ok('-X', 'cpu_count=default', '-c', code) + self.assertEqual(self.res2int(res), (os.cpu_count(), os.process_cpu_count())) + res = assert_python_ok('-X', 'cpu_count=default', '-c', code, PYTHON_CPU_COUNT='1234') + self.assertEqual(self.res2int(res), (os.cpu_count(), os.process_cpu_count())) + es = assert_python_ok('-c', code, PYTHON_CPU_COUNT='default') + self.assertEqual(self.res2int(res), (os.cpu_count(), os.process_cpu_count())) + + def res2int(self, res): + out = res.out.strip().decode("utf-8") + return tuple(int(i) for i in out.split()) + @unittest.skipIf(interpreter_requires_environment(), 'Cannot run -I tests when PYTHON env vars are required.') diff --git a/Lib/test/test_cmd_line_script.py b/Lib/test/test_cmd_line_script.py index 1b588826010717..48754d5a63da3b 100644 --- a/Lib/test/test_cmd_line_script.py +++ b/Lib/test/test_cmd_line_script.py @@ -203,6 +203,8 @@ def check_repl_stderr_flush(self, separate_stderr=False): stderr = p.stderr if separate_stderr else p.stdout self.assertIn(b'Traceback ', stderr.readline()) self.assertIn(b'File ""', stderr.readline()) + self.assertIn(b'1/0', stderr.readline()) + self.assertIn(b' ~^~', stderr.readline()) self.assertIn(b'ZeroDivisionError', stderr.readline()) def test_repl_stdout_flush(self): @@ -682,6 +684,27 @@ def test_syntaxerror_null_bytes_in_multiline_string(self): ] ) + def test_source_lines_are_shown_when_running_source(self): + _, _, stderr = assert_python_failure("-c", "1/0") + expected_lines = [ + b'Traceback (most recent call last):', + b' File "", line 1, in ', + b' 1/0', + b' ~^~', + b'ZeroDivisionError: division by zero'] + self.assertEqual(stderr.splitlines(), expected_lines) + + def test_syntaxerror_does_not_crash(self): + script = "nonlocal x\n" + with os_helper.temp_dir() as script_dir: + script_name = _make_test_script(script_dir, 'script', script) + exitcode, stdout, stderr = assert_python_failure(script_name) + text = io.TextIOWrapper(io.BytesIO(stderr), 'ascii').read() + # It used to crash in https://github.com/python/cpython/issues/111132 + self.assertTrue(text.endswith( + 'SyntaxError: nonlocal declaration not allowed at module level\n', + ), text) + def test_consistent_sys_path_for_direct_execution(self): # This test case ensures that the following all give the same # sys.path configuration: diff --git a/Lib/test/test_code.py b/Lib/test/test_code.py index ca06a39f5df142..d8fb826edeb681 100644 --- a/Lib/test/test_code.py +++ b/Lib/test/test_code.py @@ -125,6 +125,7 @@ """ +import copy import inspect import sys import threading @@ -143,6 +144,8 @@ gc_collect) from test.support.script_helper import assert_python_ok from test.support import threading_helper +from test.support.bytecode_helper import (BytecodeTestCase, + instructions_with_positions) from opcode import opmap, opname COPY_FREE_VARS = opmap['COPY_FREE_VARS'] @@ -264,7 +267,7 @@ def func2(): ("co_posonlyargcount", 0), ("co_kwonlyargcount", 0), ("co_nlocals", 1), - ("co_stacksize", 0), + ("co_stacksize", 1), ("co_flags", code.co_flags | inspect.CO_COROUTINE), ("co_firstlineno", 100), ("co_code", code2.co_code), @@ -280,11 +283,17 @@ def func2(): with self.subTest(attr=attr, value=value): new_code = code.replace(**{attr: value}) self.assertEqual(getattr(new_code, attr), value) + new_code = copy.replace(code, **{attr: value}) + self.assertEqual(getattr(new_code, attr), value) new_code = code.replace(co_varnames=code2.co_varnames, co_nlocals=code2.co_nlocals) self.assertEqual(new_code.co_varnames, code2.co_varnames) self.assertEqual(new_code.co_nlocals, code2.co_nlocals) + new_code = copy.replace(code, co_varnames=code2.co_varnames, + co_nlocals=code2.co_nlocals) + self.assertEqual(new_code.co_varnames, code2.co_varnames) + self.assertEqual(new_code.co_nlocals, code2.co_nlocals) def test_nlocals_mismatch(self): def func(): @@ -377,10 +386,8 @@ def test_co_positions_artificial_instructions(self): code = traceback.tb_frame.f_code artificial_instructions = [] - for instr, positions in zip( - dis.get_instructions(code, show_caches=True), - code.co_positions(), - strict=True + for instr, positions in instructions_with_positions( + dis.get_instructions(code), code.co_positions() ): # If any of the positions is None, then all have to # be None as well for the case above. There are still @@ -498,6 +505,25 @@ def test_code_hash_uses_bytecode(self): self.assertNotEqual(c, c1) self.assertNotEqual(hash(c), hash(c1)) + @cpython_only + def test_code_equal_with_instrumentation(self): + """ GH-109052 + + Make sure the instrumentation doesn't affect the code equality + The validity of this test relies on the fact that "x is x" and + "x in x" have only one different instruction and the instructions + have the same argument. + + """ + code1 = compile("x is x", "example.py", "eval") + code2 = compile("x in x", "example.py", "eval") + sys._getframe().f_trace_opcodes = True + sys.settrace(lambda *args: None) + exec(code1, {'x': []}) + exec(code2, {'x': []}) + self.assertNotEqual(code1, code2) + sys.settrace(None) + def isinterned(s): return s is sys.intern(('_' + s + '_')[1:-1]) diff --git a/Lib/test/test_code_module.py b/Lib/test/test_code_module.py index 226bc3a853b7b9..747c0f9683c19c 100644 --- a/Lib/test/test_code_module.py +++ b/Lib/test/test_code_module.py @@ -10,11 +10,7 @@ code = import_helper.import_module('code') -class TestInteractiveConsole(unittest.TestCase): - - def setUp(self): - self.console = code.InteractiveConsole() - self.mock_sys() +class MockSys: def mock_sys(self): "Mock system environment for InteractiveConsole" @@ -32,6 +28,13 @@ def mock_sys(self): del self.sysmod.ps1 del self.sysmod.ps2 + +class TestInteractiveConsole(unittest.TestCase, MockSys): + + def setUp(self): + self.console = code.InteractiveConsole() + self.mock_sys() + def test_ps1(self): self.infunc.side_effect = EOFError('Finished') self.console.interact() @@ -151,5 +154,21 @@ def test_context_tb(self): self.assertIn(expected, output) +class TestInteractiveConsoleLocalExit(unittest.TestCase, MockSys): + + def setUp(self): + self.console = code.InteractiveConsole(local_exit=True) + self.mock_sys() + + def test_exit(self): + # default exit message + self.infunc.side_effect = ["exit()"] + self.console.interact(banner='') + self.assertEqual(len(self.stderr.method_calls), 2) + err_msg = self.stderr.method_calls[1] + expected = 'now exiting InteractiveConsole...\n' + self.assertEqual(err_msg, ['write', (expected,), {}]) + + if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_codecencodings_iso2022.py b/Lib/test/test_codecencodings_iso2022.py index 00ea1c39dd6fb6..027dbecc6134df 100644 --- a/Lib/test/test_codecencodings_iso2022.py +++ b/Lib/test/test_codecencodings_iso2022.py @@ -24,6 +24,52 @@ class Test_ISO2022_JP2(multibytecodec_support.TestBase, unittest.TestCase): (b'ab\x1BNdef', 'replace', 'abdef'), ) +class Test_ISO2022_JP3(multibytecodec_support.TestBase, unittest.TestCase): + encoding = 'iso2022_jp_3' + tstring = multibytecodec_support.load_teststring('iso2022_jp') + codectests = COMMON_CODEC_TESTS + ( + (b'ab\x1BNdef', 'replace', 'ab\x1BNdef'), + (b'\x1B$(O\x2E\x23\x1B(B', 'strict', '\u3402' ), + (b'\x1B$(O\x2E\x22\x1B(B', 'strict', '\U0002000B' ), + (b'\x1B$(O\x24\x77\x1B(B', 'strict', '\u304B\u309A'), + (b'\x1B$(P\x21\x22\x1B(B', 'strict', '\u4E02' ), + (b'\x1B$(P\x7E\x76\x1B(B', 'strict', '\U0002A6B2' ), + ('\u3402', 'strict', b'\x1B$(O\x2E\x23\x1B(B'), + ('\U0002000B', 'strict', b'\x1B$(O\x2E\x22\x1B(B'), + ('\u304B\u309A', 'strict', b'\x1B$(O\x24\x77\x1B(B'), + ('\u4E02', 'strict', b'\x1B$(P\x21\x22\x1B(B'), + ('\U0002A6B2', 'strict', b'\x1B$(P\x7E\x76\x1B(B'), + (b'ab\x1B$(O\x2E\x21\x1B(Bdef', 'replace', 'ab\uFFFDdef'), + ('ab\u4FF1def', 'replace', b'ab?def'), + ) + xmlcharnametest = ( + '\xAB\u211C\xBB = \u2329\u1234\u232A', + b'\x1B$(O\x29\x28\x1B(Bℜ\x1B$(O\x29\x32\x1B(B = ⟨ሴ⟩' + ) + +class Test_ISO2022_JP2004(multibytecodec_support.TestBase, unittest.TestCase): + encoding = 'iso2022_jp_2004' + tstring = multibytecodec_support.load_teststring('iso2022_jp') + codectests = COMMON_CODEC_TESTS + ( + (b'ab\x1BNdef', 'replace', 'ab\x1BNdef'), + (b'\x1B$(Q\x2E\x23\x1B(B', 'strict', '\u3402' ), + (b'\x1B$(Q\x2E\x22\x1B(B', 'strict', '\U0002000B' ), + (b'\x1B$(Q\x24\x77\x1B(B', 'strict', '\u304B\u309A'), + (b'\x1B$(P\x21\x22\x1B(B', 'strict', '\u4E02' ), + (b'\x1B$(P\x7E\x76\x1B(B', 'strict', '\U0002A6B2' ), + ('\u3402', 'strict', b'\x1B$(Q\x2E\x23\x1B(B'), + ('\U0002000B', 'strict', b'\x1B$(Q\x2E\x22\x1B(B'), + ('\u304B\u309A', 'strict', b'\x1B$(Q\x24\x77\x1B(B'), + ('\u4E02', 'strict', b'\x1B$(P\x21\x22\x1B(B'), + ('\U0002A6B2', 'strict', b'\x1B$(P\x7E\x76\x1B(B'), + (b'ab\x1B$(Q\x2E\x21\x1B(Bdef', 'replace', 'ab\u4FF1def'), + ('ab\u4FF1def', 'replace', b'ab\x1B$(Q\x2E\x21\x1B(Bdef'), + ) + xmlcharnametest = ( + '\xAB\u211C\xBB = \u2329\u1234\u232A', + b'\x1B$(Q\x29\x28\x1B(Bℜ\x1B$(Q\x29\x32\x1B(B = ⟨ሴ⟩' + ) + class Test_ISO2022_KR(multibytecodec_support.TestBase, unittest.TestCase): encoding = 'iso2022_kr' tstring = multibytecodec_support.load_teststring('iso2022_kr') diff --git a/Lib/test/test_codecs.py b/Lib/test/test_codecs.py index 91d7eaf997ae20..ff511a625a0194 100644 --- a/Lib/test/test_codecs.py +++ b/Lib/test/test_codecs.py @@ -1,7 +1,9 @@ import codecs import contextlib +import copy import io import locale +import pickle import sys import unittest import encodings @@ -1760,6 +1762,76 @@ def test_file_closes_if_lookup_error_raised(self): file().close.assert_called() + def test_copy(self): + orig = codecs.lookup('utf-8') + dup = copy.copy(orig) + self.assertIsNot(dup, orig) + self.assertEqual(dup, orig) + self.assertTrue(orig._is_text_encoding) + self.assertEqual(dup.encode, orig.encode) + self.assertEqual(dup.name, orig.name) + self.assertEqual(dup.incrementalencoder, orig.incrementalencoder) + + # Test a CodecInfo with _is_text_encoding equal to false. + orig = codecs.lookup("base64") + dup = copy.copy(orig) + self.assertIsNot(dup, orig) + self.assertEqual(dup, orig) + self.assertFalse(orig._is_text_encoding) + self.assertEqual(dup.encode, orig.encode) + self.assertEqual(dup.name, orig.name) + self.assertEqual(dup.incrementalencoder, orig.incrementalencoder) + + def test_deepcopy(self): + orig = codecs.lookup('utf-8') + dup = copy.deepcopy(orig) + self.assertIsNot(dup, orig) + self.assertEqual(dup, orig) + self.assertTrue(orig._is_text_encoding) + self.assertEqual(dup.encode, orig.encode) + self.assertEqual(dup.name, orig.name) + self.assertEqual(dup.incrementalencoder, orig.incrementalencoder) + + # Test a CodecInfo with _is_text_encoding equal to false. + orig = codecs.lookup("base64") + dup = copy.deepcopy(orig) + self.assertIsNot(dup, orig) + self.assertEqual(dup, orig) + self.assertFalse(orig._is_text_encoding) + self.assertEqual(dup.encode, orig.encode) + self.assertEqual(dup.name, orig.name) + self.assertEqual(dup.incrementalencoder, orig.incrementalencoder) + + def test_pickle(self): + codec_info = codecs.lookup('utf-8') + for proto in range(pickle.HIGHEST_PROTOCOL + 1): + with self.subTest(protocol=proto): + pickled_codec_info = pickle.dumps(codec_info) + unpickled_codec_info = pickle.loads(pickled_codec_info) + self.assertIsNot(codec_info, unpickled_codec_info) + self.assertEqual(codec_info, unpickled_codec_info) + self.assertEqual(codec_info.name, unpickled_codec_info.name) + self.assertEqual( + codec_info.incrementalencoder, + unpickled_codec_info.incrementalencoder + ) + self.assertTrue(unpickled_codec_info._is_text_encoding) + + # Test a CodecInfo with _is_text_encoding equal to false. + codec_info = codecs.lookup('base64') + for proto in range(pickle.HIGHEST_PROTOCOL + 1): + with self.subTest(protocol=proto): + pickled_codec_info = pickle.dumps(codec_info) + unpickled_codec_info = pickle.loads(pickled_codec_info) + self.assertIsNot(codec_info, unpickled_codec_info) + self.assertEqual(codec_info, unpickled_codec_info) + self.assertEqual(codec_info.name, unpickled_codec_info.name) + self.assertEqual( + codec_info.incrementalencoder, + unpickled_codec_info.incrementalencoder + ) + self.assertFalse(unpickled_codec_info._is_text_encoding) + class StreamReaderTest(unittest.TestCase): @@ -1771,6 +1843,61 @@ def test_readlines(self): f = self.reader(self.stream) self.assertEqual(f.readlines(), ['\ud55c\n', '\uae00']) + def test_copy(self): + f = self.reader(Queue(b'\xed\x95\x9c\n\xea\xb8\x80')) + with self.assertRaisesRegex(TypeError, 'StreamReader'): + copy.copy(f) + with self.assertRaisesRegex(TypeError, 'StreamReader'): + copy.deepcopy(f) + + def test_pickle(self): + for proto in range(pickle.HIGHEST_PROTOCOL + 1): + with self.subTest(protocol=proto): + f = self.reader(Queue(b'\xed\x95\x9c\n\xea\xb8\x80')) + with self.assertRaisesRegex(TypeError, 'StreamReader'): + pickle.dumps(f, proto) + + +class StreamWriterTest(unittest.TestCase): + + def setUp(self): + self.writer = codecs.getwriter('utf-8') + + def test_copy(self): + f = self.writer(Queue(b'')) + with self.assertRaisesRegex(TypeError, 'StreamWriter'): + copy.copy(f) + with self.assertRaisesRegex(TypeError, 'StreamWriter'): + copy.deepcopy(f) + + def test_pickle(self): + for proto in range(pickle.HIGHEST_PROTOCOL + 1): + with self.subTest(protocol=proto): + f = self.writer(Queue(b'')) + with self.assertRaisesRegex(TypeError, 'StreamWriter'): + pickle.dumps(f, proto) + + +class StreamReaderWriterTest(unittest.TestCase): + + def setUp(self): + self.reader = codecs.getreader('latin1') + self.writer = codecs.getwriter('utf-8') + + def test_copy(self): + f = codecs.StreamReaderWriter(Queue(b''), self.reader, self.writer) + with self.assertRaisesRegex(TypeError, 'StreamReaderWriter'): + copy.copy(f) + with self.assertRaisesRegex(TypeError, 'StreamReaderWriter'): + copy.deepcopy(f) + + def test_pickle(self): + for proto in range(pickle.HIGHEST_PROTOCOL + 1): + with self.subTest(protocol=proto): + f = codecs.StreamReaderWriter(Queue(b''), self.reader, self.writer) + with self.assertRaisesRegex(TypeError, 'StreamReaderWriter'): + pickle.dumps(f, proto) + class EncodedFileTest(unittest.TestCase): @@ -3346,6 +3473,28 @@ def test_seeking_write(self): self.assertEqual(sr.readline(), b'abc\n') self.assertEqual(sr.readline(), b'789\n') + def test_copy(self): + bio = io.BytesIO() + codec = codecs.lookup('ascii') + sr = codecs.StreamRecoder(bio, codec.encode, codec.decode, + encodings.ascii.StreamReader, encodings.ascii.StreamWriter) + + with self.assertRaisesRegex(TypeError, 'StreamRecoder'): + copy.copy(sr) + with self.assertRaisesRegex(TypeError, 'StreamRecoder'): + copy.deepcopy(sr) + + def test_pickle(self): + q = Queue(b'') + codec = codecs.lookup('ascii') + sr = codecs.StreamRecoder(q, codec.encode, codec.decode, + encodings.ascii.StreamReader, encodings.ascii.StreamWriter) + + for proto in range(pickle.HIGHEST_PROTOCOL + 1): + with self.subTest(protocol=proto): + with self.assertRaisesRegex(TypeError, 'StreamRecoder'): + pickle.dumps(sr, proto) + @unittest.skipIf(_testinternalcapi is None, 'need _testinternalcapi module') class LocaleCodecTest(unittest.TestCase): @@ -3488,9 +3637,10 @@ class Rot13UtilTest(unittest.TestCase): $ echo "Hello World" | python -m encodings.rot_13 """ def test_rot13_func(self): + from encodings.rot_13 import rot13 infile = io.StringIO('Gb or, be abg gb or, gung vf gur dhrfgvba') outfile = io.StringIO() - encodings.rot_13.rot13(infile, outfile) + rot13(infile, outfile) outfile.seek(0) plain_text = outfile.read() self.assertEqual( diff --git a/Lib/test/test_codeop.py b/Lib/test/test_codeop.py index e3c382266fa058..787bd1b6a79e20 100644 --- a/Lib/test/test_codeop.py +++ b/Lib/test/test_codeop.py @@ -5,6 +5,7 @@ import unittest import warnings from test.support import warnings_helper +from textwrap import dedent from codeop import compile_command, PyCF_DONT_IMPLY_DEDENT @@ -222,6 +223,9 @@ def test_incomplete(self): ai("(x for x in") ai("(x for x in (") + ai('a = f"""') + ai('a = \\') + def test_invalid(self): ai = self.assertInvalid ai("a b") @@ -308,6 +312,19 @@ def test_invalid_warning(self): self.assertRegex(str(w[0].message), 'invalid escape sequence') self.assertEqual(w[0].filename, '') + def assertSyntaxErrorMatches(self, code, message): + with self.subTest(code): + with self.assertRaisesRegex(SyntaxError, message): + compile_command(code, symbol='exec') + + def test_syntax_errors(self): + self.assertSyntaxErrorMatches( + dedent("""\ + def foo(x,x): + pass + """), "duplicate argument 'x' in function definition") + + if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_collections.py b/Lib/test/test_collections.py index bb8b352518ef3e..7e6f811e17cfa2 100644 --- a/Lib/test/test_collections.py +++ b/Lib/test/test_collections.py @@ -488,12 +488,8 @@ def test_instance(self): self.assertEqual(p._replace(x=1), (1, 22)) # test _replace method self.assertEqual(p._asdict(), dict(x=11, y=22)) # test _asdict method - try: + with self.assertRaises(TypeError): p._replace(x=1, error=2) - except ValueError: - pass - else: - self._fail('Did not detect an incorrect fieldname') # verify that field string can have commas Point = namedtuple('Point', 'x, y') diff --git a/Lib/test/test_compile.py b/Lib/test/test_compile.py index 770184c5ef9a91..45fd30987760cb 100644 --- a/Lib/test/test_compile.py +++ b/Lib/test/test_compile.py @@ -11,7 +11,8 @@ import warnings from test import support from test.support import (script_helper, requires_debug_ranges, - requires_specialization, C_RECURSION_LIMIT) + requires_specialization, Py_C_RECURSION_LIMIT) +from test.support.bytecode_helper import instructions_with_positions from test.support.os_helper import FakePath class TestSpecifics(unittest.TestCase): @@ -111,7 +112,7 @@ def __getitem__(self, key): @unittest.skipIf(support.is_wasi, "exhausts limited stack on WASI") def test_extended_arg(self): - repeat = int(C_RECURSION_LIMIT * 0.9) + repeat = int(Py_C_RECURSION_LIMIT * 0.9) longexpr = 'x = x or ' + '-x' * repeat g = {} code = textwrap.dedent(''' @@ -443,6 +444,51 @@ def f(): self.assertIn("_A__mangled_mod", A.f.__code__.co_varnames) self.assertIn("__package__", A.f.__code__.co_varnames) + def test_condition_expression_with_dead_blocks_compiles(self): + # See gh-113054 + compile('if (5 if 5 else T): 0', '', 'exec') + + def test_condition_expression_with_redundant_comparisons_compiles(self): + # See gh-113054 + with self.assertWarns(SyntaxWarning): + compile('if 9<9<9and 9or 9:9', '', 'exec') + + def test_dead_code_with_except_handler_compiles(self): + compile(textwrap.dedent(""" + if None: + with CM: + x = 1 + else: + x = 2 + """), '', 'exec') + + def test_compile_invalid_namedexpr(self): + # gh-109351 + m = ast.Module( + body=[ + ast.Expr( + value=ast.ListComp( + elt=ast.NamedExpr( + target=ast.Constant(value=1), + value=ast.Constant(value=3), + ), + generators=[ + ast.comprehension( + target=ast.Name(id="x", ctx=ast.Store()), + iter=ast.Name(id="y", ctx=ast.Load()), + ifs=[], + is_async=0, + ) + ], + ) + ) + ], + type_ignores=[], + ) + + with self.assertRaisesRegex(TypeError, "NamedExpr target must be a Name"): + compile(ast.fix_missing_locations(m), "", "exec") + def test_compile_ast(self): fname = __file__ if fname.lower().endswith('pyc'): @@ -478,6 +524,26 @@ def test_compile_ast(self): ast.body = [_ast.BoolOp()] self.assertRaises(TypeError, compile, ast, '', 'exec') + def test_compile_invalid_typealias(self): + # gh-109341 + m = ast.Module( + body=[ + ast.TypeAlias( + name=ast.Subscript( + value=ast.Name(id="foo", ctx=ast.Load()), + slice=ast.Constant(value="x"), + ctx=ast.Store(), + ), + type_params=[], + value=ast.Name(id="Callable", ctx=ast.Load()), + ) + ], + type_ignores=[], + ) + + with self.assertRaisesRegex(TypeError, "TypeAlias with non-Name name"): + compile(ast.fix_missing_locations(m), "", "exec") + def test_dict_evaluation_order(self): i = 0 @@ -557,12 +623,12 @@ def test_yet_more_evil_still_undecodable(self): @support.cpython_only @unittest.skipIf(support.is_wasi, "exhausts limited stack on WASI") def test_compiler_recursion_limit(self): - # Expected limit is C_RECURSION_LIMIT * 2 + # Expected limit is Py_C_RECURSION_LIMIT * 2 # Duplicating the limit here is a little ugly. # Perhaps it should be exposed somewhere... - fail_depth = C_RECURSION_LIMIT * 2 + 1 - crash_depth = C_RECURSION_LIMIT * 100 - success_depth = int(C_RECURSION_LIMIT * 1.8) + fail_depth = Py_C_RECURSION_LIMIT * 2 + 1 + crash_depth = Py_C_RECURSION_LIMIT * 100 + success_depth = int(Py_C_RECURSION_LIMIT * 1.8) def check_limit(prefix, repeated, mode="single"): expect_ok = prefix + repeated * success_depth @@ -784,6 +850,7 @@ def test_path_like_objects(self): # An implicit test for PyUnicode_FSDecoder(). compile("42", FakePath("test_compile_pathlike"), "single") + @support.requires_resource('cpu') def test_stack_overflow(self): # bpo-31113: Stack overflow when compile a long sequence of # complex statements. @@ -1031,6 +1098,20 @@ async def test(aseq): code_lines = self.get_code_lines(test.__code__) self.assertEqual(expected_lines, code_lines) + def test_lineno_of_backward_jump(self): + # Issue gh-107901 + def f(): + for i in x: + if y: + pass + + linenos = list(inst.positions.lineno + for inst in dis.get_instructions(f.__code__) + if inst.opname == 'JUMP_BACKWARD') + + self.assertTrue(len(linenos) > 0) + self.assertTrue(all(l is not None for l in linenos)) + def test_big_dict_literal(self): # The compiler has a flushing point in "compiler_dict" that calls compiles # a portion of the dictionary literal when the loop that iterates over the items @@ -1190,6 +1271,53 @@ def f(): return a, b self.assertEqual(f(), (54, 96)) + def test_duplicated_small_exit_block(self): + # See gh-109627 + def f(): + while element and something: + try: + return something + except: + pass + + def test_cold_block_moved_to_end(self): + # See gh-109719 + def f(): + while name: + try: + break + except: + pass + else: + 1 if 1 else 1 + + def test_remove_empty_basic_block_with_jump_target_label(self): + # See gh-109823 + def f(x): + while x: + 0 if 1 else 0 + + def test_remove_redundant_nop_edge_case(self): + # See gh-109889 + def f(): + a if (1 if b else c) else d + + def test_global_declaration_in_except_used_in_else(self): + # See gh-111123 + code = textwrap.dedent("""\ + def f(): + try: + pass + %s Exception: + global a + else: + print(a) + """) + + g, l = {'a': 5}, {} + for kw in ("except", "except*"): + exec(code % kw, g, l); + @requires_debug_ranges() class TestSourcePositions(unittest.TestCase): @@ -1237,8 +1365,8 @@ def generic_visit(self, node): def assertOpcodeSourcePositionIs(self, code, opcode, line, end_line, column, end_column, occurrence=1): - for instr, position in zip( - dis.Bytecode(code, show_caches=True), code.co_positions(), strict=True + for instr, position in instructions_with_positions( + dis.Bytecode(code), code.co_positions() ): if instr.opname == opcode: occurrence -= 1 @@ -1315,18 +1443,18 @@ def test_multiline_assert(self): snippet = textwrap.dedent("""\ assert (a > 0 and bb > 0 and - ccc == 4), "error msg" + ccc == 1000000), "error msg" """) compiled_code, _ = self.check_positions_against_ast(snippet) self.assertOpcodeSourcePositionIs(compiled_code, 'LOAD_ASSERTION_ERROR', - line=1, end_line=3, column=0, end_column=30, occurrence=1) + line=1, end_line=3, column=0, end_column=36, occurrence=1) # The "error msg": self.assertOpcodeSourcePositionIs(compiled_code, 'LOAD_CONST', - line=3, end_line=3, column=19, end_column=30, occurrence=4) + line=3, end_line=3, column=25, end_column=36, occurrence=4) self.assertOpcodeSourcePositionIs(compiled_code, 'CALL', - line=1, end_line=3, column=0, end_column=30, occurrence=1) + line=1, end_line=3, column=0, end_column=36, occurrence=1) self.assertOpcodeSourcePositionIs(compiled_code, 'RAISE_VARARGS', - line=1, end_line=3, column=0, end_column=30, occurrence=1) + line=1, end_line=3, column=8, end_column=22, occurrence=1) def test_multiline_generator_expression(self): snippet = textwrap.dedent("""\ @@ -1736,6 +1864,13 @@ def test_column_offset_deduplication(self): list(code.co_consts[1].co_positions()), ) + def test_load_super_attr(self): + source = "class C:\n def __init__(self):\n super().__init__()" + code = compile(source, "", "exec").co_consts[0].co_consts[1] + self.assertOpcodeSourcePositionIs( + code, "LOAD_GLOBAL", line=3, end_line=3, column=4, end_column=9 + ) + class TestExpressionStackSize(unittest.TestCase): # These tests check that the computed stack size for a code object diff --git a/Lib/test/test_compileall.py b/Lib/test/test_compileall.py index 05154c8f1c6057..83a9532aecfac8 100644 --- a/Lib/test/test_compileall.py +++ b/Lib/test/test_compileall.py @@ -18,6 +18,7 @@ try: # compileall relies on ProcessPoolExecutor if ProcessPoolExecutor exists # and it can function. + from multiprocessing.util import _cleanup_tests as multiprocessing_cleanup_tests from concurrent.futures import ProcessPoolExecutor from concurrent.futures.process import _check_system_limits _check_system_limits() @@ -54,6 +55,8 @@ class CompileallTestsBase: def setUp(self): self.directory = tempfile.mkdtemp() + self.addCleanup(shutil.rmtree, self.directory) + self.source_path = os.path.join(self.directory, '_test.py') self.bc_path = importlib.util.cache_from_source(self.source_path) with open(self.source_path, 'w', encoding="utf-8") as file: @@ -66,9 +69,6 @@ def setUp(self): self.source_path3 = os.path.join(self.subdirectory, '_test3.py') shutil.copyfile(self.source_path, self.source_path3) - def tearDown(self): - shutil.rmtree(self.directory) - def add_bad_source_file(self): self.bad_source_path = os.path.join(self.directory, '_test_bad.py') with open(self.bad_source_path, 'w', encoding="utf-8") as file: @@ -307,9 +307,13 @@ def _test_ddir_only(self, *, ddir, parallel=True): script_helper.make_script(path, "__init__", "") mods.append(script_helper.make_script(path, "mod", "def fn(): 1/0\nfn()\n")) + + if parallel: + self.addCleanup(multiprocessing_cleanup_tests) compileall.compile_dir( self.directory, quiet=True, ddir=ddir, workers=2 if parallel else 1) + self.assertTrue(mods) for mod in mods: self.assertTrue(mod.startswith(self.directory), mod) @@ -358,6 +362,29 @@ def test_strip_only(self): str(err, encoding=sys.getdefaultencoding()) ) + def test_strip_only_invalid(self): + fullpath = ["test", "build", "real", "path"] + path = os.path.join(self.directory, *fullpath) + os.makedirs(path) + script = script_helper.make_script(path, "test", "1 / 0") + bc = importlib.util.cache_from_source(script) + stripdir = os.path.join(self.directory, *(fullpath[:2] + ['fake'])) + compileall.compile_dir(path, quiet=True, stripdir=stripdir) + rc, out, err = script_helper.assert_python_failure(bc) + expected_not_in = os.path.join(self.directory, *fullpath[2:]) + self.assertIn( + path, + str(err, encoding=sys.getdefaultencoding()) + ) + self.assertNotIn( + expected_not_in, + str(err, encoding=sys.getdefaultencoding()) + ) + self.assertNotIn( + stripdir, + str(err, encoding=sys.getdefaultencoding()) + ) + def test_prepend_only(self): fullpath = ["test", "build", "real", "path"] path = os.path.join(self.directory, *fullpath) @@ -551,6 +578,7 @@ def test_no_args_compiles_path(self): self.assertNotCompiled(self.barfn) @without_source_date_epoch # timestamp invalidation test + @support.requires_resource('cpu') def test_no_args_respects_force_flag(self): bazfn = script_helper.make_script(self.directory, 'baz', '') with self.temporary_pycache_prefix() as env: @@ -568,6 +596,7 @@ def test_no_args_respects_force_flag(self): mtime2 = os.stat(pycpath).st_mtime self.assertNotEqual(mtime, mtime2) + @support.requires_resource('cpu') def test_no_args_respects_quiet_flag(self): script_helper.make_script(self.directory, 'baz', '') with self.temporary_pycache_prefix() as env: diff --git a/Lib/test/test_compiler_assemble.py b/Lib/test/test_compiler_assemble.py index 6df72cbc54666b..5696433e529d0a 100644 --- a/Lib/test/test_compiler_assemble.py +++ b/Lib/test/test_compiler_assemble.py @@ -94,12 +94,12 @@ def inner(): instructions = [ ('RESUME', 0,), - ('PUSH_NULL', 0, 1), ('LOAD_CLOSURE', 0, 1), ('BUILD_TUPLE', 1, 1), ('LOAD_CONST', 1, 1), ('MAKE_FUNCTION', 0, 2), ('SET_FUNCTION_ATTRIBUTE', 8, 2), + ('PUSH_NULL', 0, 1), ('CALL', 0, 2), # (lambda: x)() ('LOAD_CONST', 2, 2), # 2 ('BINARY_OP', 6, 2), # % diff --git a/Lib/test/test_compiler_codegen.py b/Lib/test/test_compiler_codegen.py index d99bb8c6cd472d..b5d1e2f9e4752c 100644 --- a/Lib/test/test_compiler_codegen.py +++ b/Lib/test/test_compiler_codegen.py @@ -21,7 +21,7 @@ def test_if_expression(self): ('TO_BOOL', 0, 1), ('POP_JUMP_IF_FALSE', false_lbl := self.Label(), 1), ('LOAD_CONST', 1, 1), - ('JUMP', exit_lbl := self.Label()), + ('JUMP_NO_INTERRUPT', exit_lbl := self.Label()), false_lbl, ('LOAD_CONST', 2, 1), exit_lbl, @@ -41,8 +41,8 @@ def test_for_loop(self): loop_lbl := self.Label(), ('FOR_ITER', exit_lbl := self.Label(), 1), ('STORE_NAME', 1, 1), - ('PUSH_NULL', None, 2), ('LOAD_NAME', 2, 2), + ('PUSH_NULL', None, 2), ('LOAD_NAME', 1, 2), ('CALL', 1, 2), ('POP_TOP', None), diff --git a/Lib/test/test_complex.py b/Lib/test/test_complex.py index 9180cca62b28b8..b057121f285dc7 100644 --- a/Lib/test/test_complex.py +++ b/Lib/test/test_complex.py @@ -109,6 +109,8 @@ def test_truediv(self): complex(random(), random())) self.assertAlmostEqual(complex.__truediv__(2+0j, 1+1j), 1-1j) + self.assertRaises(TypeError, operator.truediv, 1j, None) + self.assertRaises(TypeError, operator.truediv, None, 1j) for denom_real, denom_imag in [(0, NAN), (NAN, 0), (NAN, NAN)]: z = complex(0, 0) / complex(denom_real, denom_imag) @@ -140,6 +142,7 @@ def test_floordiv_zero_division(self): def test_richcompare(self): self.assertIs(complex.__eq__(1+1j, 1<<10000), False) self.assertIs(complex.__lt__(1+1j, None), NotImplemented) + self.assertIs(complex.__eq__(1+1j, None), NotImplemented) self.assertIs(complex.__eq__(1+1j, 1+1j), True) self.assertIs(complex.__eq__(1+1j, 2+2j), False) self.assertIs(complex.__ne__(1+1j, 1+1j), False) @@ -162,6 +165,7 @@ def test_richcompare(self): self.assertIs(operator.eq(1+1j, 2+2j), False) self.assertIs(operator.ne(1+1j, 1+1j), False) self.assertIs(operator.ne(1+1j, 2+2j), True) + self.assertIs(operator.eq(1+1j, 2.0), False) def test_richcompare_boundaries(self): def check(n, deltas, is_equal, imag = 0.0): @@ -180,6 +184,27 @@ def check(n, deltas, is_equal, imag = 0.0): check(2 ** pow, range(1, 101), lambda delta: False, float(i)) check(2 ** 53, range(-100, 0), lambda delta: True) + def test_add(self): + self.assertEqual(1j + int(+1), complex(+1, 1)) + self.assertEqual(1j + int(-1), complex(-1, 1)) + self.assertRaises(OverflowError, operator.add, 1j, 10**1000) + self.assertRaises(TypeError, operator.add, 1j, None) + self.assertRaises(TypeError, operator.add, None, 1j) + + def test_sub(self): + self.assertEqual(1j - int(+1), complex(-1, 1)) + self.assertEqual(1j - int(-1), complex(1, 1)) + self.assertRaises(OverflowError, operator.sub, 1j, 10**1000) + self.assertRaises(TypeError, operator.sub, 1j, None) + self.assertRaises(TypeError, operator.sub, None, 1j) + + def test_mul(self): + self.assertEqual(1j * int(20), complex(0, 20)) + self.assertEqual(1j * int(-1), complex(0, -1)) + self.assertRaises(OverflowError, operator.mul, 1j, 10**1000) + self.assertRaises(TypeError, operator.mul, 1j, None) + self.assertRaises(TypeError, operator.mul, None, 1j) + def test_mod(self): # % is no longer supported on complex numbers with self.assertRaises(TypeError): @@ -212,11 +237,18 @@ def test_divmod_zero_division(self): def test_pow(self): self.assertAlmostEqual(pow(1+1j, 0+0j), 1.0) self.assertAlmostEqual(pow(0+0j, 2+0j), 0.0) + self.assertEqual(pow(0+0j, 2000+0j), 0.0) + self.assertEqual(pow(0, 0+0j), 1.0) + self.assertEqual(pow(-1, 0+0j), 1.0) self.assertRaises(ZeroDivisionError, pow, 0+0j, 1j) + self.assertRaises(ZeroDivisionError, pow, 0+0j, -1000) self.assertAlmostEqual(pow(1j, -1), 1/1j) self.assertAlmostEqual(pow(1j, 200), 1) self.assertRaises(ValueError, pow, 1+1j, 1+1j, 1+1j) self.assertRaises(OverflowError, pow, 1e200+1j, 1e200+1j) + self.assertRaises(TypeError, pow, 1j, None) + self.assertRaises(TypeError, pow, None, 1j) + self.assertAlmostEqual(pow(1j, 0.5), 0.7071067811865476+0.7071067811865475j) a = 3.33+4.43j self.assertEqual(a ** 0j, 1) @@ -301,6 +333,7 @@ def test_boolcontext(self): for i in range(100): self.assertTrue(complex(random() + 1e-6, random() + 1e-6)) self.assertTrue(not complex(0.0, 0.0)) + self.assertTrue(1j) def test_conjugate(self): self.assertClose(complex(5.3, 9.8).conjugate(), 5.3-9.8j) @@ -314,6 +347,8 @@ def __complex__(self): return self.value self.assertRaises(TypeError, complex, {}) self.assertRaises(TypeError, complex, NS(1.5)) self.assertRaises(TypeError, complex, NS(1)) + self.assertRaises(TypeError, complex, object()) + self.assertRaises(TypeError, complex, NS(4.25+0.5j), object()) self.assertAlmostEqual(complex("1+10j"), 1+10j) self.assertAlmostEqual(complex(10), 10+0j) @@ -359,6 +394,8 @@ def __complex__(self): return self.value self.assertAlmostEqual(complex('1e-500'), 0.0 + 0.0j) self.assertAlmostEqual(complex('-1e-500j'), 0.0 - 0.0j) self.assertAlmostEqual(complex('-1e-500+1e-500j'), -0.0 + 0.0j) + self.assertEqual(complex('1-1j'), 1.0 - 1j) + self.assertEqual(complex('1J'), 1j) class complex2(complex): pass self.assertAlmostEqual(complex(complex2(1+1j)), 1+1j) @@ -553,6 +590,8 @@ def test_hash(self): x /= 3.0 # now check against floating point self.assertEqual(hash(x), hash(complex(x, 0.))) + self.assertNotEqual(hash(2000005 - 1j), -1) + def test_abs(self): nums = [complex(x/3., y/7.) for x in range(-9,9) for y in range(-9,9)] for num in nums: @@ -602,6 +641,14 @@ def test(v, expected, test_fn=self.assertEqual): test(complex(-0., 0.), "(-0+0j)") test(complex(-0., -0.), "(-0-0j)") + def test_pos(self): + class ComplexSubclass(complex): + pass + + self.assertEqual(+(1+6j), 1+6j) + self.assertEqual(+ComplexSubclass(1, 6), 1+6j) + self.assertIs(type(+ComplexSubclass(1, 6)), complex) + def test_neg(self): self.assertEqual(-(1+6j), -1-6j) diff --git a/Lib/test/test_concurrent_futures.py b/Lib/test/test_concurrent_futures.py deleted file mode 100644 index 39dbe234e765e8..00000000000000 --- a/Lib/test/test_concurrent_futures.py +++ /dev/null @@ -1,1677 +0,0 @@ -from test import support -from test.support import import_helper -from test.support import threading_helper - -# Skip tests if _multiprocessing wasn't built. -import_helper.import_module('_multiprocessing') - -from test.support import hashlib_helper -from test.support.script_helper import assert_python_ok - -import contextlib -import itertools -import logging -from logging.handlers import QueueHandler -import os -import queue -import signal -import sys -import threading -import time -import unittest -import weakref -from pickle import PicklingError - -from concurrent import futures -from concurrent.futures._base import ( - PENDING, RUNNING, CANCELLED, CANCELLED_AND_NOTIFIED, FINISHED, Future, - BrokenExecutor) -from concurrent.futures.process import BrokenProcessPool, _check_system_limits - -import multiprocessing.process -import multiprocessing.util -import multiprocessing as mp - - -if support.check_sanitizer(address=True, memory=True): - # bpo-46633: Skip the test because it is too slow when Python is built - # with ASAN/MSAN: between 5 and 20 minutes on GitHub Actions. - raise unittest.SkipTest("test too slow on ASAN/MSAN build") - - -def create_future(state=PENDING, exception=None, result=None): - f = Future() - f._state = state - f._exception = exception - f._result = result - return f - - -PENDING_FUTURE = create_future(state=PENDING) -RUNNING_FUTURE = create_future(state=RUNNING) -CANCELLED_FUTURE = create_future(state=CANCELLED) -CANCELLED_AND_NOTIFIED_FUTURE = create_future(state=CANCELLED_AND_NOTIFIED) -EXCEPTION_FUTURE = create_future(state=FINISHED, exception=OSError()) -SUCCESSFUL_FUTURE = create_future(state=FINISHED, result=42) - -INITIALIZER_STATUS = 'uninitialized' - -def mul(x, y): - return x * y - -def capture(*args, **kwargs): - return args, kwargs - -def sleep_and_raise(t): - time.sleep(t) - raise Exception('this is an exception') - -def sleep_and_print(t, msg): - time.sleep(t) - print(msg) - sys.stdout.flush() - -def init(x): - global INITIALIZER_STATUS - INITIALIZER_STATUS = x - -def get_init_status(): - return INITIALIZER_STATUS - -def init_fail(log_queue=None): - if log_queue is not None: - logger = logging.getLogger('concurrent.futures') - logger.addHandler(QueueHandler(log_queue)) - logger.setLevel('CRITICAL') - logger.propagate = False - time.sleep(0.1) # let some futures be scheduled - raise ValueError('error in initializer') - - -class MyObject(object): - def my_method(self): - pass - - -class EventfulGCObj(): - def __init__(self, mgr): - self.event = mgr.Event() - - def __del__(self): - self.event.set() - - -def make_dummy_object(_): - return MyObject() - - -class BaseTestCase(unittest.TestCase): - def setUp(self): - self._thread_key = threading_helper.threading_setup() - - def tearDown(self): - support.reap_children() - threading_helper.threading_cleanup(*self._thread_key) - - -class ExecutorMixin: - worker_count = 5 - executor_kwargs = {} - - def setUp(self): - super().setUp() - - self.t1 = time.monotonic() - if hasattr(self, "ctx"): - self.executor = self.executor_type( - max_workers=self.worker_count, - mp_context=self.get_context(), - **self.executor_kwargs) - else: - self.executor = self.executor_type( - max_workers=self.worker_count, - **self.executor_kwargs) - - def tearDown(self): - self.executor.shutdown(wait=True) - self.executor = None - - dt = time.monotonic() - self.t1 - if support.verbose: - print("%.2fs" % dt, end=' ') - self.assertLess(dt, 300, "synchronization issue: test lasted too long") - - super().tearDown() - - def get_context(self): - return mp.get_context(self.ctx) - - -class ThreadPoolMixin(ExecutorMixin): - executor_type = futures.ThreadPoolExecutor - - -class ProcessPoolForkMixin(ExecutorMixin): - executor_type = futures.ProcessPoolExecutor - ctx = "fork" - - def get_context(self): - try: - _check_system_limits() - except NotImplementedError: - self.skipTest("ProcessPoolExecutor unavailable on this system") - if sys.platform == "win32": - self.skipTest("require unix system") - return super().get_context() - - -class ProcessPoolSpawnMixin(ExecutorMixin): - executor_type = futures.ProcessPoolExecutor - ctx = "spawn" - - def get_context(self): - try: - _check_system_limits() - except NotImplementedError: - self.skipTest("ProcessPoolExecutor unavailable on this system") - return super().get_context() - - -class ProcessPoolForkserverMixin(ExecutorMixin): - executor_type = futures.ProcessPoolExecutor - ctx = "forkserver" - - def get_context(self): - try: - _check_system_limits() - except NotImplementedError: - self.skipTest("ProcessPoolExecutor unavailable on this system") - if sys.platform == "win32": - self.skipTest("require unix system") - return super().get_context() - - -def create_executor_tests(mixin, bases=(BaseTestCase,), - executor_mixins=(ThreadPoolMixin, - ProcessPoolForkMixin, - ProcessPoolForkserverMixin, - ProcessPoolSpawnMixin)): - def strip_mixin(name): - if name.endswith(('Mixin', 'Tests')): - return name[:-5] - elif name.endswith('Test'): - return name[:-4] - else: - return name - - for exe in executor_mixins: - name = ("%s%sTest" - % (strip_mixin(exe.__name__), strip_mixin(mixin.__name__))) - cls = type(name, (mixin,) + (exe,) + bases, {}) - globals()[name] = cls - - -class InitializerMixin(ExecutorMixin): - worker_count = 2 - - def setUp(self): - global INITIALIZER_STATUS - INITIALIZER_STATUS = 'uninitialized' - self.executor_kwargs = dict(initializer=init, - initargs=('initialized',)) - super().setUp() - - def test_initializer(self): - futures = [self.executor.submit(get_init_status) - for _ in range(self.worker_count)] - - for f in futures: - self.assertEqual(f.result(), 'initialized') - - -class FailingInitializerMixin(ExecutorMixin): - worker_count = 2 - - def setUp(self): - if hasattr(self, "ctx"): - # Pass a queue to redirect the child's logging output - self.mp_context = self.get_context() - self.log_queue = self.mp_context.Queue() - self.executor_kwargs = dict(initializer=init_fail, - initargs=(self.log_queue,)) - else: - # In a thread pool, the child shares our logging setup - # (see _assert_logged()) - self.mp_context = None - self.log_queue = None - self.executor_kwargs = dict(initializer=init_fail) - super().setUp() - - def test_initializer(self): - with self._assert_logged('ValueError: error in initializer'): - try: - future = self.executor.submit(get_init_status) - except BrokenExecutor: - # Perhaps the executor is already broken - pass - else: - with self.assertRaises(BrokenExecutor): - future.result() - - # At some point, the executor should break - for _ in support.sleeping_retry(support.SHORT_TIMEOUT, - "executor not broken"): - if self.executor._broken: - break - - # ... and from this point submit() is guaranteed to fail - with self.assertRaises(BrokenExecutor): - self.executor.submit(get_init_status) - - @contextlib.contextmanager - def _assert_logged(self, msg): - if self.log_queue is not None: - yield - output = [] - try: - while True: - output.append(self.log_queue.get_nowait().getMessage()) - except queue.Empty: - pass - else: - with self.assertLogs('concurrent.futures', 'CRITICAL') as cm: - yield - output = cm.output - self.assertTrue(any(msg in line for line in output), - output) - - -create_executor_tests(InitializerMixin) -create_executor_tests(FailingInitializerMixin) - - -class ExecutorShutdownTest: - def test_run_after_shutdown(self): - self.executor.shutdown() - self.assertRaises(RuntimeError, - self.executor.submit, - pow, 2, 5) - - def test_interpreter_shutdown(self): - # Test the atexit hook for shutdown of worker threads and processes - rc, out, err = assert_python_ok('-c', """if 1: - from concurrent.futures import {executor_type} - from time import sleep - from test.test_concurrent_futures import sleep_and_print - if __name__ == "__main__": - context = '{context}' - if context == "": - t = {executor_type}(5) - else: - from multiprocessing import get_context - context = get_context(context) - t = {executor_type}(5, mp_context=context) - t.submit(sleep_and_print, 1.0, "apple") - """.format(executor_type=self.executor_type.__name__, - context=getattr(self, "ctx", ""))) - # Errors in atexit hooks don't change the process exit code, check - # stderr manually. - self.assertFalse(err) - self.assertEqual(out.strip(), b"apple") - - def test_submit_after_interpreter_shutdown(self): - # Test the atexit hook for shutdown of worker threads and processes - rc, out, err = assert_python_ok('-c', """if 1: - import atexit - @atexit.register - def run_last(): - try: - t.submit(id, None) - except RuntimeError: - print("runtime-error") - raise - from concurrent.futures import {executor_type} - if __name__ == "__main__": - context = '{context}' - if not context: - t = {executor_type}(5) - else: - from multiprocessing import get_context - context = get_context(context) - t = {executor_type}(5, mp_context=context) - t.submit(id, 42).result() - """.format(executor_type=self.executor_type.__name__, - context=getattr(self, "ctx", ""))) - # Errors in atexit hooks don't change the process exit code, check - # stderr manually. - self.assertIn("RuntimeError: cannot schedule new futures", err.decode()) - self.assertEqual(out.strip(), b"runtime-error") - - def test_hang_issue12364(self): - fs = [self.executor.submit(time.sleep, 0.1) for _ in range(50)] - self.executor.shutdown() - for f in fs: - f.result() - - def test_cancel_futures(self): - assert self.worker_count <= 5, "test needs few workers" - fs = [self.executor.submit(time.sleep, .1) for _ in range(50)] - self.executor.shutdown(cancel_futures=True) - # We can't guarantee the exact number of cancellations, but we can - # guarantee that *some* were cancelled. With few workers, many of - # the submitted futures should have been cancelled. - cancelled = [fut for fut in fs if fut.cancelled()] - self.assertGreater(len(cancelled), 20) - - # Ensure the other futures were able to finish. - # Use "not fut.cancelled()" instead of "fut.done()" to include futures - # that may have been left in a pending state. - others = [fut for fut in fs if not fut.cancelled()] - for fut in others: - self.assertTrue(fut.done(), msg=f"{fut._state=}") - self.assertIsNone(fut.exception()) - - # Similar to the number of cancelled futures, we can't guarantee the - # exact number that completed. But, we can guarantee that at least - # one finished. - self.assertGreater(len(others), 0) - - def test_hang_gh83386(self): - """shutdown(wait=False) doesn't hang at exit with running futures. - - See https://github.com/python/cpython/issues/83386. - """ - if self.executor_type == futures.ProcessPoolExecutor: - raise unittest.SkipTest( - "Hangs, see https://github.com/python/cpython/issues/83386") - - rc, out, err = assert_python_ok('-c', """if True: - from concurrent.futures import {executor_type} - from test.test_concurrent_futures import sleep_and_print - if __name__ == "__main__": - if {context!r}: multiprocessing.set_start_method({context!r}) - t = {executor_type}(max_workers=3) - t.submit(sleep_and_print, 1.0, "apple") - t.shutdown(wait=False) - """.format(executor_type=self.executor_type.__name__, - context=getattr(self, 'ctx', None))) - self.assertFalse(err) - self.assertEqual(out.strip(), b"apple") - - def test_hang_gh94440(self): - """shutdown(wait=True) doesn't hang when a future was submitted and - quickly canceled right before shutdown. - - See https://github.com/python/cpython/issues/94440. - """ - if not hasattr(signal, 'alarm'): - raise unittest.SkipTest( - "Tested platform does not support the alarm signal") - - def timeout(_signum, _frame): - raise RuntimeError("timed out waiting for shutdown") - - kwargs = {} - if getattr(self, 'ctx', None): - kwargs['mp_context'] = self.get_context() - executor = self.executor_type(max_workers=1, **kwargs) - executor.submit(int).result() - old_handler = signal.signal(signal.SIGALRM, timeout) - try: - signal.alarm(5) - executor.submit(int).cancel() - executor.shutdown(wait=True) - finally: - signal.alarm(0) - signal.signal(signal.SIGALRM, old_handler) - - -class ThreadPoolShutdownTest(ThreadPoolMixin, ExecutorShutdownTest, BaseTestCase): - def test_threads_terminate(self): - def acquire_lock(lock): - lock.acquire() - - sem = threading.Semaphore(0) - for i in range(3): - self.executor.submit(acquire_lock, sem) - self.assertEqual(len(self.executor._threads), 3) - for i in range(3): - sem.release() - self.executor.shutdown() - for t in self.executor._threads: - t.join() - - def test_context_manager_shutdown(self): - with futures.ThreadPoolExecutor(max_workers=5) as e: - executor = e - self.assertEqual(list(e.map(abs, range(-5, 5))), - [5, 4, 3, 2, 1, 0, 1, 2, 3, 4]) - - for t in executor._threads: - t.join() - - def test_del_shutdown(self): - executor = futures.ThreadPoolExecutor(max_workers=5) - res = executor.map(abs, range(-5, 5)) - threads = executor._threads - del executor - - for t in threads: - t.join() - - # Make sure the results were all computed before the - # executor got shutdown. - assert all([r == abs(v) for r, v in zip(res, range(-5, 5))]) - - def test_shutdown_no_wait(self): - # Ensure that the executor cleans up the threads when calling - # shutdown with wait=False - executor = futures.ThreadPoolExecutor(max_workers=5) - res = executor.map(abs, range(-5, 5)) - threads = executor._threads - executor.shutdown(wait=False) - for t in threads: - t.join() - - # Make sure the results were all computed before the - # executor got shutdown. - assert all([r == abs(v) for r, v in zip(res, range(-5, 5))]) - - - def test_thread_names_assigned(self): - executor = futures.ThreadPoolExecutor( - max_workers=5, thread_name_prefix='SpecialPool') - executor.map(abs, range(-5, 5)) - threads = executor._threads - del executor - support.gc_collect() # For PyPy or other GCs. - - for t in threads: - self.assertRegex(t.name, r'^SpecialPool_[0-4]$') - t.join() - - def test_thread_names_default(self): - executor = futures.ThreadPoolExecutor(max_workers=5) - executor.map(abs, range(-5, 5)) - threads = executor._threads - del executor - support.gc_collect() # For PyPy or other GCs. - - for t in threads: - # Ensure that our default name is reasonably sane and unique when - # no thread_name_prefix was supplied. - self.assertRegex(t.name, r'ThreadPoolExecutor-\d+_[0-4]$') - t.join() - - def test_cancel_futures_wait_false(self): - # Can only be reliably tested for TPE, since PPE often hangs with - # `wait=False` (even without *cancel_futures*). - rc, out, err = assert_python_ok('-c', """if True: - from concurrent.futures import ThreadPoolExecutor - from test.test_concurrent_futures import sleep_and_print - if __name__ == "__main__": - t = ThreadPoolExecutor() - t.submit(sleep_and_print, .1, "apple") - t.shutdown(wait=False, cancel_futures=True) - """) - # Errors in atexit hooks don't change the process exit code, check - # stderr manually. - self.assertFalse(err) - self.assertEqual(out.strip(), b"apple") - - -class ProcessPoolShutdownTest(ExecutorShutdownTest): - def test_processes_terminate(self): - def acquire_lock(lock): - lock.acquire() - - mp_context = self.get_context() - if mp_context.get_start_method(allow_none=False) == "fork": - # fork pre-spawns, not on demand. - expected_num_processes = self.worker_count - else: - expected_num_processes = 3 - - sem = mp_context.Semaphore(0) - for _ in range(3): - self.executor.submit(acquire_lock, sem) - self.assertEqual(len(self.executor._processes), expected_num_processes) - for _ in range(3): - sem.release() - processes = self.executor._processes - self.executor.shutdown() - - for p in processes.values(): - p.join() - - def test_context_manager_shutdown(self): - with futures.ProcessPoolExecutor( - max_workers=5, mp_context=self.get_context()) as e: - processes = e._processes - self.assertEqual(list(e.map(abs, range(-5, 5))), - [5, 4, 3, 2, 1, 0, 1, 2, 3, 4]) - - for p in processes.values(): - p.join() - - def test_del_shutdown(self): - executor = futures.ProcessPoolExecutor( - max_workers=5, mp_context=self.get_context()) - res = executor.map(abs, range(-5, 5)) - executor_manager_thread = executor._executor_manager_thread - processes = executor._processes - call_queue = executor._call_queue - executor_manager_thread = executor._executor_manager_thread - del executor - support.gc_collect() # For PyPy or other GCs. - - # Make sure that all the executor resources were properly cleaned by - # the shutdown process - executor_manager_thread.join() - for p in processes.values(): - p.join() - call_queue.join_thread() - - # Make sure the results were all computed before the - # executor got shutdown. - assert all([r == abs(v) for r, v in zip(res, range(-5, 5))]) - - def test_shutdown_no_wait(self): - # Ensure that the executor cleans up the processes when calling - # shutdown with wait=False - executor = futures.ProcessPoolExecutor( - max_workers=5, mp_context=self.get_context()) - res = executor.map(abs, range(-5, 5)) - processes = executor._processes - call_queue = executor._call_queue - executor_manager_thread = executor._executor_manager_thread - executor.shutdown(wait=False) - - # Make sure that all the executor resources were properly cleaned by - # the shutdown process - executor_manager_thread.join() - for p in processes.values(): - p.join() - call_queue.join_thread() - - # Make sure the results were all computed before the executor got - # shutdown. - assert all([r == abs(v) for r, v in zip(res, range(-5, 5))]) - - -create_executor_tests(ProcessPoolShutdownTest, - executor_mixins=(ProcessPoolForkMixin, - ProcessPoolForkserverMixin, - ProcessPoolSpawnMixin)) - - -class WaitTests: - def test_20369(self): - # See https://bugs.python.org/issue20369 - future = self.executor.submit(time.sleep, 1.5) - done, not_done = futures.wait([future, future], - return_when=futures.ALL_COMPLETED) - self.assertEqual({future}, done) - self.assertEqual(set(), not_done) - - - def test_first_completed(self): - future1 = self.executor.submit(mul, 21, 2) - future2 = self.executor.submit(time.sleep, 1.5) - - done, not_done = futures.wait( - [CANCELLED_FUTURE, future1, future2], - return_when=futures.FIRST_COMPLETED) - - self.assertEqual(set([future1]), done) - self.assertEqual(set([CANCELLED_FUTURE, future2]), not_done) - - def test_first_completed_some_already_completed(self): - future1 = self.executor.submit(time.sleep, 1.5) - - finished, pending = futures.wait( - [CANCELLED_AND_NOTIFIED_FUTURE, SUCCESSFUL_FUTURE, future1], - return_when=futures.FIRST_COMPLETED) - - self.assertEqual( - set([CANCELLED_AND_NOTIFIED_FUTURE, SUCCESSFUL_FUTURE]), - finished) - self.assertEqual(set([future1]), pending) - - def test_first_exception(self): - future1 = self.executor.submit(mul, 2, 21) - future2 = self.executor.submit(sleep_and_raise, 1.5) - future3 = self.executor.submit(time.sleep, 3) - - finished, pending = futures.wait( - [future1, future2, future3], - return_when=futures.FIRST_EXCEPTION) - - self.assertEqual(set([future1, future2]), finished) - self.assertEqual(set([future3]), pending) - - def test_first_exception_some_already_complete(self): - future1 = self.executor.submit(divmod, 21, 0) - future2 = self.executor.submit(time.sleep, 1.5) - - finished, pending = futures.wait( - [SUCCESSFUL_FUTURE, - CANCELLED_FUTURE, - CANCELLED_AND_NOTIFIED_FUTURE, - future1, future2], - return_when=futures.FIRST_EXCEPTION) - - self.assertEqual(set([SUCCESSFUL_FUTURE, - CANCELLED_AND_NOTIFIED_FUTURE, - future1]), finished) - self.assertEqual(set([CANCELLED_FUTURE, future2]), pending) - - def test_first_exception_one_already_failed(self): - future1 = self.executor.submit(time.sleep, 2) - - finished, pending = futures.wait( - [EXCEPTION_FUTURE, future1], - return_when=futures.FIRST_EXCEPTION) - - self.assertEqual(set([EXCEPTION_FUTURE]), finished) - self.assertEqual(set([future1]), pending) - - def test_all_completed(self): - future1 = self.executor.submit(divmod, 2, 0) - future2 = self.executor.submit(mul, 2, 21) - - finished, pending = futures.wait( - [SUCCESSFUL_FUTURE, - CANCELLED_AND_NOTIFIED_FUTURE, - EXCEPTION_FUTURE, - future1, - future2], - return_when=futures.ALL_COMPLETED) - - self.assertEqual(set([SUCCESSFUL_FUTURE, - CANCELLED_AND_NOTIFIED_FUTURE, - EXCEPTION_FUTURE, - future1, - future2]), finished) - self.assertEqual(set(), pending) - - def test_timeout(self): - future1 = self.executor.submit(mul, 6, 7) - future2 = self.executor.submit(time.sleep, 6) - - finished, pending = futures.wait( - [CANCELLED_AND_NOTIFIED_FUTURE, - EXCEPTION_FUTURE, - SUCCESSFUL_FUTURE, - future1, future2], - timeout=5, - return_when=futures.ALL_COMPLETED) - - self.assertEqual(set([CANCELLED_AND_NOTIFIED_FUTURE, - EXCEPTION_FUTURE, - SUCCESSFUL_FUTURE, - future1]), finished) - self.assertEqual(set([future2]), pending) - - -class ThreadPoolWaitTests(ThreadPoolMixin, WaitTests, BaseTestCase): - - def test_pending_calls_race(self): - # Issue #14406: multi-threaded race condition when waiting on all - # futures. - event = threading.Event() - def future_func(): - event.wait() - oldswitchinterval = sys.getswitchinterval() - sys.setswitchinterval(1e-6) - try: - fs = {self.executor.submit(future_func) for i in range(100)} - event.set() - futures.wait(fs, return_when=futures.ALL_COMPLETED) - finally: - sys.setswitchinterval(oldswitchinterval) - - -create_executor_tests(WaitTests, - executor_mixins=(ProcessPoolForkMixin, - ProcessPoolForkserverMixin, - ProcessPoolSpawnMixin)) - - -class AsCompletedTests: - def test_no_timeout(self): - future1 = self.executor.submit(mul, 2, 21) - future2 = self.executor.submit(mul, 7, 6) - - completed = set(futures.as_completed( - [CANCELLED_AND_NOTIFIED_FUTURE, - EXCEPTION_FUTURE, - SUCCESSFUL_FUTURE, - future1, future2])) - self.assertEqual(set( - [CANCELLED_AND_NOTIFIED_FUTURE, - EXCEPTION_FUTURE, - SUCCESSFUL_FUTURE, - future1, future2]), - completed) - - def test_future_times_out(self): - """Test ``futures.as_completed`` timing out before - completing it's final future.""" - already_completed = {CANCELLED_AND_NOTIFIED_FUTURE, - EXCEPTION_FUTURE, - SUCCESSFUL_FUTURE} - - for timeout in (0, 0.01): - with self.subTest(timeout): - - future = self.executor.submit(time.sleep, 0.1) - completed_futures = set() - try: - for f in futures.as_completed( - already_completed | {future}, - timeout - ): - completed_futures.add(f) - except futures.TimeoutError: - pass - - # Check that ``future`` wasn't completed. - self.assertEqual(completed_futures, already_completed) - - def test_duplicate_futures(self): - # Issue 20367. Duplicate futures should not raise exceptions or give - # duplicate responses. - # Issue #31641: accept arbitrary iterables. - future1 = self.executor.submit(time.sleep, 2) - completed = [ - f for f in futures.as_completed(itertools.repeat(future1, 3)) - ] - self.assertEqual(len(completed), 1) - - def test_free_reference_yielded_future(self): - # Issue #14406: Generator should not keep references - # to finished futures. - futures_list = [Future() for _ in range(8)] - futures_list.append(create_future(state=CANCELLED_AND_NOTIFIED)) - futures_list.append(create_future(state=FINISHED, result=42)) - - with self.assertRaises(futures.TimeoutError): - for future in futures.as_completed(futures_list, timeout=0): - futures_list.remove(future) - wr = weakref.ref(future) - del future - support.gc_collect() # For PyPy or other GCs. - self.assertIsNone(wr()) - - futures_list[0].set_result("test") - for future in futures.as_completed(futures_list): - futures_list.remove(future) - wr = weakref.ref(future) - del future - support.gc_collect() # For PyPy or other GCs. - self.assertIsNone(wr()) - if futures_list: - futures_list[0].set_result("test") - - def test_correct_timeout_exception_msg(self): - futures_list = [CANCELLED_AND_NOTIFIED_FUTURE, PENDING_FUTURE, - RUNNING_FUTURE, SUCCESSFUL_FUTURE] - - with self.assertRaises(futures.TimeoutError) as cm: - list(futures.as_completed(futures_list, timeout=0)) - - self.assertEqual(str(cm.exception), '2 (of 4) futures unfinished') - - -create_executor_tests(AsCompletedTests) - - -class ExecutorTest: - # Executor.shutdown() and context manager usage is tested by - # ExecutorShutdownTest. - def test_submit(self): - future = self.executor.submit(pow, 2, 8) - self.assertEqual(256, future.result()) - - def test_submit_keyword(self): - future = self.executor.submit(mul, 2, y=8) - self.assertEqual(16, future.result()) - future = self.executor.submit(capture, 1, self=2, fn=3) - self.assertEqual(future.result(), ((1,), {'self': 2, 'fn': 3})) - with self.assertRaises(TypeError): - self.executor.submit(fn=capture, arg=1) - with self.assertRaises(TypeError): - self.executor.submit(arg=1) - - def test_map(self): - self.assertEqual( - list(self.executor.map(pow, range(10), range(10))), - list(map(pow, range(10), range(10)))) - - self.assertEqual( - list(self.executor.map(pow, range(10), range(10), chunksize=3)), - list(map(pow, range(10), range(10)))) - - def test_map_exception(self): - i = self.executor.map(divmod, [1, 1, 1, 1], [2, 3, 0, 5]) - self.assertEqual(i.__next__(), (0, 1)) - self.assertEqual(i.__next__(), (0, 1)) - self.assertRaises(ZeroDivisionError, i.__next__) - - def test_map_timeout(self): - results = [] - try: - for i in self.executor.map(time.sleep, - [0, 0, 6], - timeout=5): - results.append(i) - except futures.TimeoutError: - pass - else: - self.fail('expected TimeoutError') - - self.assertEqual([None, None], results) - - def test_shutdown_race_issue12456(self): - # Issue #12456: race condition at shutdown where trying to post a - # sentinel in the call queue blocks (the queue is full while processes - # have exited). - self.executor.map(str, [2] * (self.worker_count + 1)) - self.executor.shutdown() - - @support.cpython_only - def test_no_stale_references(self): - # Issue #16284: check that the executors don't unnecessarily hang onto - # references. - my_object = MyObject() - my_object_collected = threading.Event() - my_object_callback = weakref.ref( - my_object, lambda obj: my_object_collected.set()) - # Deliberately discarding the future. - self.executor.submit(my_object.my_method) - del my_object - - collected = my_object_collected.wait(timeout=support.SHORT_TIMEOUT) - self.assertTrue(collected, - "Stale reference not collected within timeout.") - - def test_max_workers_negative(self): - for number in (0, -1): - with self.assertRaisesRegex(ValueError, - "max_workers must be greater " - "than 0"): - self.executor_type(max_workers=number) - - def test_free_reference(self): - # Issue #14406: Result iterator should not keep an internal - # reference to result objects. - for obj in self.executor.map(make_dummy_object, range(10)): - wr = weakref.ref(obj) - del obj - support.gc_collect() # For PyPy or other GCs. - self.assertIsNone(wr()) - - -class ThreadPoolExecutorTest(ThreadPoolMixin, ExecutorTest, BaseTestCase): - def test_map_submits_without_iteration(self): - """Tests verifying issue 11777.""" - finished = [] - def record_finished(n): - finished.append(n) - - self.executor.map(record_finished, range(10)) - self.executor.shutdown(wait=True) - self.assertCountEqual(finished, range(10)) - - def test_default_workers(self): - executor = self.executor_type() - expected = min(32, (os.cpu_count() or 1) + 4) - self.assertEqual(executor._max_workers, expected) - - def test_saturation(self): - executor = self.executor_type(4) - def acquire_lock(lock): - lock.acquire() - - sem = threading.Semaphore(0) - for i in range(15 * executor._max_workers): - executor.submit(acquire_lock, sem) - self.assertEqual(len(executor._threads), executor._max_workers) - for i in range(15 * executor._max_workers): - sem.release() - executor.shutdown(wait=True) - - def test_idle_thread_reuse(self): - executor = self.executor_type() - executor.submit(mul, 21, 2).result() - executor.submit(mul, 6, 7).result() - executor.submit(mul, 3, 14).result() - self.assertEqual(len(executor._threads), 1) - executor.shutdown(wait=True) - - @unittest.skipUnless(hasattr(os, 'register_at_fork'), 'need os.register_at_fork') - def test_hang_global_shutdown_lock(self): - # bpo-45021: _global_shutdown_lock should be reinitialized in the child - # process, otherwise it will never exit - def submit(pool): - pool.submit(submit, pool) - - with futures.ThreadPoolExecutor(1) as pool: - pool.submit(submit, pool) - - for _ in range(50): - with futures.ProcessPoolExecutor(1, mp_context=mp.get_context('fork')) as workers: - workers.submit(tuple) - - def test_executor_map_current_future_cancel(self): - stop_event = threading.Event() - log = [] - - def log_n_wait(ident): - log.append(f"{ident=} started") - try: - stop_event.wait() - finally: - log.append(f"{ident=} stopped") - - with self.executor_type(max_workers=1) as pool: - # submit work to saturate the pool - fut = pool.submit(log_n_wait, ident="first") - try: - with contextlib.closing( - pool.map(log_n_wait, ["second", "third"], timeout=0) - ) as gen: - with self.assertRaises(TimeoutError): - next(gen) - finally: - stop_event.set() - fut.result() - # ident='second' is cancelled as a result of raising a TimeoutError - # ident='third' is cancelled because it remained in the collection of futures - self.assertListEqual(log, ["ident='first' started", "ident='first' stopped"]) - - -class ProcessPoolExecutorTest(ExecutorTest): - - @unittest.skipUnless(sys.platform=='win32', 'Windows-only process limit') - def test_max_workers_too_large(self): - with self.assertRaisesRegex(ValueError, - "max_workers must be <= 61"): - futures.ProcessPoolExecutor(max_workers=62) - - def test_killed_child(self): - # When a child process is abruptly terminated, the whole pool gets - # "broken". - futures = [self.executor.submit(time.sleep, 3)] - # Get one of the processes, and terminate (kill) it - p = next(iter(self.executor._processes.values())) - p.terminate() - for fut in futures: - self.assertRaises(BrokenProcessPool, fut.result) - # Submitting other jobs fails as well. - self.assertRaises(BrokenProcessPool, self.executor.submit, pow, 2, 8) - - def test_map_chunksize(self): - def bad_map(): - list(self.executor.map(pow, range(40), range(40), chunksize=-1)) - - ref = list(map(pow, range(40), range(40))) - self.assertEqual( - list(self.executor.map(pow, range(40), range(40), chunksize=6)), - ref) - self.assertEqual( - list(self.executor.map(pow, range(40), range(40), chunksize=50)), - ref) - self.assertEqual( - list(self.executor.map(pow, range(40), range(40), chunksize=40)), - ref) - self.assertRaises(ValueError, bad_map) - - @classmethod - def _test_traceback(cls): - raise RuntimeError(123) # some comment - - def test_traceback(self): - # We want ensure that the traceback from the child process is - # contained in the traceback raised in the main process. - future = self.executor.submit(self._test_traceback) - with self.assertRaises(Exception) as cm: - future.result() - - exc = cm.exception - self.assertIs(type(exc), RuntimeError) - self.assertEqual(exc.args, (123,)) - cause = exc.__cause__ - self.assertIs(type(cause), futures.process._RemoteTraceback) - self.assertIn('raise RuntimeError(123) # some comment', cause.tb) - - with support.captured_stderr() as f1: - try: - raise exc - except RuntimeError: - sys.excepthook(*sys.exc_info()) - self.assertIn('raise RuntimeError(123) # some comment', - f1.getvalue()) - - @hashlib_helper.requires_hashdigest('md5') - def test_ressources_gced_in_workers(self): - # Ensure that argument for a job are correctly gc-ed after the job - # is finished - mgr = self.get_context().Manager() - obj = EventfulGCObj(mgr) - future = self.executor.submit(id, obj) - future.result() - - self.assertTrue(obj.event.wait(timeout=1)) - - # explicitly destroy the object to ensure that EventfulGCObj.__del__() - # is called while manager is still running. - obj = None - support.gc_collect() - - mgr.shutdown() - mgr.join() - - def test_saturation(self): - executor = self.executor - mp_context = self.get_context() - sem = mp_context.Semaphore(0) - job_count = 15 * executor._max_workers - for _ in range(job_count): - executor.submit(sem.acquire) - self.assertEqual(len(executor._processes), executor._max_workers) - for _ in range(job_count): - sem.release() - - def test_idle_process_reuse_one(self): - executor = self.executor - assert executor._max_workers >= 4 - if self.get_context().get_start_method(allow_none=False) == "fork": - raise unittest.SkipTest("Incompatible with the fork start method.") - executor.submit(mul, 21, 2).result() - executor.submit(mul, 6, 7).result() - executor.submit(mul, 3, 14).result() - self.assertEqual(len(executor._processes), 1) - - def test_idle_process_reuse_multiple(self): - executor = self.executor - assert executor._max_workers <= 5 - if self.get_context().get_start_method(allow_none=False) == "fork": - raise unittest.SkipTest("Incompatible with the fork start method.") - executor.submit(mul, 12, 7).result() - executor.submit(mul, 33, 25) - executor.submit(mul, 25, 26).result() - executor.submit(mul, 18, 29) - executor.submit(mul, 1, 2).result() - executor.submit(mul, 0, 9) - self.assertLessEqual(len(executor._processes), 3) - executor.shutdown() - - def test_max_tasks_per_child(self): - context = self.get_context() - if context.get_start_method(allow_none=False) == "fork": - with self.assertRaises(ValueError): - self.executor_type(1, mp_context=context, max_tasks_per_child=3) - return - # not using self.executor as we need to control construction. - # arguably this could go in another class w/o that mixin. - executor = self.executor_type( - 1, mp_context=context, max_tasks_per_child=3) - f1 = executor.submit(os.getpid) - original_pid = f1.result() - # The worker pid remains the same as the worker could be reused - f2 = executor.submit(os.getpid) - self.assertEqual(f2.result(), original_pid) - self.assertEqual(len(executor._processes), 1) - f3 = executor.submit(os.getpid) - self.assertEqual(f3.result(), original_pid) - - # A new worker is spawned, with a statistically different pid, - # while the previous was reaped. - f4 = executor.submit(os.getpid) - new_pid = f4.result() - self.assertNotEqual(original_pid, new_pid) - self.assertEqual(len(executor._processes), 1) - - executor.shutdown() - - def test_max_tasks_per_child_defaults_to_spawn_context(self): - # not using self.executor as we need to control construction. - # arguably this could go in another class w/o that mixin. - executor = self.executor_type(1, max_tasks_per_child=3) - self.assertEqual(executor._mp_context.get_start_method(), "spawn") - - def test_max_tasks_early_shutdown(self): - context = self.get_context() - if context.get_start_method(allow_none=False) == "fork": - raise unittest.SkipTest("Incompatible with the fork start method.") - # not using self.executor as we need to control construction. - # arguably this could go in another class w/o that mixin. - executor = self.executor_type( - 3, mp_context=context, max_tasks_per_child=1) - futures = [] - for i in range(6): - futures.append(executor.submit(mul, i, i)) - executor.shutdown() - for i, future in enumerate(futures): - self.assertEqual(future.result(), mul(i, i)) - - -create_executor_tests(ProcessPoolExecutorTest, - executor_mixins=(ProcessPoolForkMixin, - ProcessPoolForkserverMixin, - ProcessPoolSpawnMixin)) - -def _crash(delay=None): - """Induces a segfault.""" - if delay: - time.sleep(delay) - import faulthandler - faulthandler.disable() - faulthandler._sigsegv() - - -def _crash_with_data(data): - """Induces a segfault with dummy data in input.""" - _crash() - - -def _exit(): - """Induces a sys exit with exitcode 1.""" - sys.exit(1) - - -def _raise_error(Err): - """Function that raises an Exception in process.""" - raise Err() - - -def _raise_error_ignore_stderr(Err): - """Function that raises an Exception in process and ignores stderr.""" - import io - sys.stderr = io.StringIO() - raise Err() - - -def _return_instance(cls): - """Function that returns a instance of cls.""" - return cls() - - -class CrashAtPickle(object): - """Bad object that triggers a segfault at pickling time.""" - def __reduce__(self): - _crash() - - -class CrashAtUnpickle(object): - """Bad object that triggers a segfault at unpickling time.""" - def __reduce__(self): - return _crash, () - - -class ExitAtPickle(object): - """Bad object that triggers a process exit at pickling time.""" - def __reduce__(self): - _exit() - - -class ExitAtUnpickle(object): - """Bad object that triggers a process exit at unpickling time.""" - def __reduce__(self): - return _exit, () - - -class ErrorAtPickle(object): - """Bad object that triggers an error at pickling time.""" - def __reduce__(self): - from pickle import PicklingError - raise PicklingError("Error in pickle") - - -class ErrorAtUnpickle(object): - """Bad object that triggers an error at unpickling time.""" - def __reduce__(self): - from pickle import UnpicklingError - return _raise_error_ignore_stderr, (UnpicklingError, ) - - -class ExecutorDeadlockTest: - TIMEOUT = support.SHORT_TIMEOUT - - def _fail_on_deadlock(self, executor): - # If we did not recover before TIMEOUT seconds, consider that the - # executor is in a deadlock state and forcefully clean all its - # composants. - import faulthandler - from tempfile import TemporaryFile - with TemporaryFile(mode="w+") as f: - faulthandler.dump_traceback(file=f) - f.seek(0) - tb = f.read() - for p in executor._processes.values(): - p.terminate() - # This should be safe to call executor.shutdown here as all possible - # deadlocks should have been broken. - executor.shutdown(wait=True) - print(f"\nTraceback:\n {tb}", file=sys.__stderr__) - self.fail(f"Executor deadlock:\n\n{tb}") - - - def _check_crash(self, error, func, *args, ignore_stderr=False): - # test for deadlock caused by crashes in a pool - self.executor.shutdown(wait=True) - - executor = self.executor_type( - max_workers=2, mp_context=self.get_context()) - res = executor.submit(func, *args) - - if ignore_stderr: - cm = support.captured_stderr() - else: - cm = contextlib.nullcontext() - - try: - with self.assertRaises(error): - with cm: - res.result(timeout=self.TIMEOUT) - except futures.TimeoutError: - # If we did not recover before TIMEOUT seconds, - # consider that the executor is in a deadlock state - self._fail_on_deadlock(executor) - executor.shutdown(wait=True) - - def test_error_at_task_pickle(self): - # Check problem occurring while pickling a task in - # the task_handler thread - self._check_crash(PicklingError, id, ErrorAtPickle()) - - def test_exit_at_task_unpickle(self): - # Check problem occurring while unpickling a task on workers - self._check_crash(BrokenProcessPool, id, ExitAtUnpickle()) - - def test_error_at_task_unpickle(self): - # Check problem occurring while unpickling a task on workers - self._check_crash(BrokenProcessPool, id, ErrorAtUnpickle()) - - def test_crash_at_task_unpickle(self): - # Check problem occurring while unpickling a task on workers - self._check_crash(BrokenProcessPool, id, CrashAtUnpickle()) - - def test_crash_during_func_exec_on_worker(self): - # Check problem occurring during func execution on workers - self._check_crash(BrokenProcessPool, _crash) - - def test_exit_during_func_exec_on_worker(self): - # Check problem occurring during func execution on workers - self._check_crash(SystemExit, _exit) - - def test_error_during_func_exec_on_worker(self): - # Check problem occurring during func execution on workers - self._check_crash(RuntimeError, _raise_error, RuntimeError) - - def test_crash_during_result_pickle_on_worker(self): - # Check problem occurring while pickling a task result - # on workers - self._check_crash(BrokenProcessPool, _return_instance, CrashAtPickle) - - def test_exit_during_result_pickle_on_worker(self): - # Check problem occurring while pickling a task result - # on workers - self._check_crash(SystemExit, _return_instance, ExitAtPickle) - - def test_error_during_result_pickle_on_worker(self): - # Check problem occurring while pickling a task result - # on workers - self._check_crash(PicklingError, _return_instance, ErrorAtPickle) - - def test_error_during_result_unpickle_in_result_handler(self): - # Check problem occurring while unpickling a task in - # the result_handler thread - self._check_crash(BrokenProcessPool, - _return_instance, ErrorAtUnpickle, - ignore_stderr=True) - - def test_exit_during_result_unpickle_in_result_handler(self): - # Check problem occurring while unpickling a task in - # the result_handler thread - self._check_crash(BrokenProcessPool, _return_instance, ExitAtUnpickle) - - def test_shutdown_deadlock(self): - # Test that the pool calling shutdown do not cause deadlock - # if a worker fails after the shutdown call. - self.executor.shutdown(wait=True) - with self.executor_type(max_workers=2, - mp_context=self.get_context()) as executor: - self.executor = executor # Allow clean up in fail_on_deadlock - f = executor.submit(_crash, delay=.1) - executor.shutdown(wait=True) - with self.assertRaises(BrokenProcessPool): - f.result() - - def test_shutdown_deadlock_pickle(self): - # Test that the pool calling shutdown with wait=False does not cause - # a deadlock if a task fails at pickle after the shutdown call. - # Reported in bpo-39104. - self.executor.shutdown(wait=True) - with self.executor_type(max_workers=2, - mp_context=self.get_context()) as executor: - self.executor = executor # Allow clean up in fail_on_deadlock - - # Start the executor and get the executor_manager_thread to collect - # the threads and avoid dangling thread that should be cleaned up - # asynchronously. - executor.submit(id, 42).result() - executor_manager = executor._executor_manager_thread - - # Submit a task that fails at pickle and shutdown the executor - # without waiting - f = executor.submit(id, ErrorAtPickle()) - executor.shutdown(wait=False) - with self.assertRaises(PicklingError): - f.result() - - # Make sure the executor is eventually shutdown and do not leave - # dangling threads - executor_manager.join() - - def test_crash_big_data(self): - # Test that there is a clean exception instad of a deadlock when a - # child process crashes while some data is being written into the - # queue. - # https://github.com/python/cpython/issues/94777 - self.executor.shutdown(wait=True) - data = "a" * support.PIPE_MAX_SIZE - with self.executor_type(max_workers=2, - mp_context=self.get_context()) as executor: - self.executor = executor # Allow clean up in fail_on_deadlock - with self.assertRaises(BrokenProcessPool): - list(executor.map(_crash_with_data, [data] * 10)) - - -create_executor_tests(ExecutorDeadlockTest, - executor_mixins=(ProcessPoolForkMixin, - ProcessPoolForkserverMixin, - ProcessPoolSpawnMixin)) - - -class FutureTests(BaseTestCase): - def test_done_callback_with_result(self): - callback_result = None - def fn(callback_future): - nonlocal callback_result - callback_result = callback_future.result() - - f = Future() - f.add_done_callback(fn) - f.set_result(5) - self.assertEqual(5, callback_result) - - def test_done_callback_with_exception(self): - callback_exception = None - def fn(callback_future): - nonlocal callback_exception - callback_exception = callback_future.exception() - - f = Future() - f.add_done_callback(fn) - f.set_exception(Exception('test')) - self.assertEqual(('test',), callback_exception.args) - - def test_done_callback_with_cancel(self): - was_cancelled = None - def fn(callback_future): - nonlocal was_cancelled - was_cancelled = callback_future.cancelled() - - f = Future() - f.add_done_callback(fn) - self.assertTrue(f.cancel()) - self.assertTrue(was_cancelled) - - def test_done_callback_raises(self): - with support.captured_stderr() as stderr: - raising_was_called = False - fn_was_called = False - - def raising_fn(callback_future): - nonlocal raising_was_called - raising_was_called = True - raise Exception('doh!') - - def fn(callback_future): - nonlocal fn_was_called - fn_was_called = True - - f = Future() - f.add_done_callback(raising_fn) - f.add_done_callback(fn) - f.set_result(5) - self.assertTrue(raising_was_called) - self.assertTrue(fn_was_called) - self.assertIn('Exception: doh!', stderr.getvalue()) - - def test_done_callback_already_successful(self): - callback_result = None - def fn(callback_future): - nonlocal callback_result - callback_result = callback_future.result() - - f = Future() - f.set_result(5) - f.add_done_callback(fn) - self.assertEqual(5, callback_result) - - def test_done_callback_already_failed(self): - callback_exception = None - def fn(callback_future): - nonlocal callback_exception - callback_exception = callback_future.exception() - - f = Future() - f.set_exception(Exception('test')) - f.add_done_callback(fn) - self.assertEqual(('test',), callback_exception.args) - - def test_done_callback_already_cancelled(self): - was_cancelled = None - def fn(callback_future): - nonlocal was_cancelled - was_cancelled = callback_future.cancelled() - - f = Future() - self.assertTrue(f.cancel()) - f.add_done_callback(fn) - self.assertTrue(was_cancelled) - - def test_done_callback_raises_already_succeeded(self): - with support.captured_stderr() as stderr: - def raising_fn(callback_future): - raise Exception('doh!') - - f = Future() - - # Set the result first to simulate a future that runs instantly, - # effectively allowing the callback to be run immediately. - f.set_result(5) - f.add_done_callback(raising_fn) - - self.assertIn('exception calling callback for', stderr.getvalue()) - self.assertIn('doh!', stderr.getvalue()) - - - def test_repr(self): - self.assertRegex(repr(PENDING_FUTURE), - '') - self.assertRegex(repr(RUNNING_FUTURE), - '') - self.assertRegex(repr(CANCELLED_FUTURE), - '') - self.assertRegex(repr(CANCELLED_AND_NOTIFIED_FUTURE), - '') - self.assertRegex( - repr(EXCEPTION_FUTURE), - '') - self.assertRegex( - repr(SUCCESSFUL_FUTURE), - '') - - - def test_cancel(self): - f1 = create_future(state=PENDING) - f2 = create_future(state=RUNNING) - f3 = create_future(state=CANCELLED) - f4 = create_future(state=CANCELLED_AND_NOTIFIED) - f5 = create_future(state=FINISHED, exception=OSError()) - f6 = create_future(state=FINISHED, result=5) - - self.assertTrue(f1.cancel()) - self.assertEqual(f1._state, CANCELLED) - - self.assertFalse(f2.cancel()) - self.assertEqual(f2._state, RUNNING) - - self.assertTrue(f3.cancel()) - self.assertEqual(f3._state, CANCELLED) - - self.assertTrue(f4.cancel()) - self.assertEqual(f4._state, CANCELLED_AND_NOTIFIED) - - self.assertFalse(f5.cancel()) - self.assertEqual(f5._state, FINISHED) - - self.assertFalse(f6.cancel()) - self.assertEqual(f6._state, FINISHED) - - def test_cancelled(self): - self.assertFalse(PENDING_FUTURE.cancelled()) - self.assertFalse(RUNNING_FUTURE.cancelled()) - self.assertTrue(CANCELLED_FUTURE.cancelled()) - self.assertTrue(CANCELLED_AND_NOTIFIED_FUTURE.cancelled()) - self.assertFalse(EXCEPTION_FUTURE.cancelled()) - self.assertFalse(SUCCESSFUL_FUTURE.cancelled()) - - def test_done(self): - self.assertFalse(PENDING_FUTURE.done()) - self.assertFalse(RUNNING_FUTURE.done()) - self.assertTrue(CANCELLED_FUTURE.done()) - self.assertTrue(CANCELLED_AND_NOTIFIED_FUTURE.done()) - self.assertTrue(EXCEPTION_FUTURE.done()) - self.assertTrue(SUCCESSFUL_FUTURE.done()) - - def test_running(self): - self.assertFalse(PENDING_FUTURE.running()) - self.assertTrue(RUNNING_FUTURE.running()) - self.assertFalse(CANCELLED_FUTURE.running()) - self.assertFalse(CANCELLED_AND_NOTIFIED_FUTURE.running()) - self.assertFalse(EXCEPTION_FUTURE.running()) - self.assertFalse(SUCCESSFUL_FUTURE.running()) - - def test_result_with_timeout(self): - self.assertRaises(futures.TimeoutError, - PENDING_FUTURE.result, timeout=0) - self.assertRaises(futures.TimeoutError, - RUNNING_FUTURE.result, timeout=0) - self.assertRaises(futures.CancelledError, - CANCELLED_FUTURE.result, timeout=0) - self.assertRaises(futures.CancelledError, - CANCELLED_AND_NOTIFIED_FUTURE.result, timeout=0) - self.assertRaises(OSError, EXCEPTION_FUTURE.result, timeout=0) - self.assertEqual(SUCCESSFUL_FUTURE.result(timeout=0), 42) - - def test_result_with_success(self): - # TODO(brian@sweetapp.com): This test is timing dependent. - def notification(): - # Wait until the main thread is waiting for the result. - time.sleep(1) - f1.set_result(42) - - f1 = create_future(state=PENDING) - t = threading.Thread(target=notification) - t.start() - - self.assertEqual(f1.result(timeout=5), 42) - t.join() - - def test_result_with_cancel(self): - # TODO(brian@sweetapp.com): This test is timing dependent. - def notification(): - # Wait until the main thread is waiting for the result. - time.sleep(1) - f1.cancel() - - f1 = create_future(state=PENDING) - t = threading.Thread(target=notification) - t.start() - - self.assertRaises(futures.CancelledError, - f1.result, timeout=support.SHORT_TIMEOUT) - t.join() - - def test_exception_with_timeout(self): - self.assertRaises(futures.TimeoutError, - PENDING_FUTURE.exception, timeout=0) - self.assertRaises(futures.TimeoutError, - RUNNING_FUTURE.exception, timeout=0) - self.assertRaises(futures.CancelledError, - CANCELLED_FUTURE.exception, timeout=0) - self.assertRaises(futures.CancelledError, - CANCELLED_AND_NOTIFIED_FUTURE.exception, timeout=0) - self.assertTrue(isinstance(EXCEPTION_FUTURE.exception(timeout=0), - OSError)) - self.assertEqual(SUCCESSFUL_FUTURE.exception(timeout=0), None) - - def test_exception_with_success(self): - def notification(): - # Wait until the main thread is waiting for the exception. - time.sleep(1) - with f1._condition: - f1._state = FINISHED - f1._exception = OSError() - f1._condition.notify_all() - - f1 = create_future(state=PENDING) - t = threading.Thread(target=notification) - t.start() - - self.assertTrue(isinstance(f1.exception(timeout=support.SHORT_TIMEOUT), OSError)) - t.join() - - def test_multiple_set_result(self): - f = create_future(state=PENDING) - f.set_result(1) - - with self.assertRaisesRegex( - futures.InvalidStateError, - 'FINISHED: ' - ): - f.set_result(2) - - self.assertTrue(f.done()) - self.assertEqual(f.result(), 1) - - def test_multiple_set_exception(self): - f = create_future(state=PENDING) - e = ValueError() - f.set_exception(e) - - with self.assertRaisesRegex( - futures.InvalidStateError, - 'FINISHED: ' - ): - f.set_exception(Exception()) - - self.assertEqual(f.exception(), e) - - -def setUpModule(): - unittest.addModuleCleanup(multiprocessing.util._cleanup_tests) - thread_info = threading_helper.threading_setup() - unittest.addModuleCleanup(threading_helper.threading_cleanup, *thread_info) - - -if __name__ == "__main__": - unittest.main() diff --git a/Lib/test/test_concurrent_futures/__init__.py b/Lib/test/test_concurrent_futures/__init__.py new file mode 100644 index 00000000000000..430fa93aa456a2 --- /dev/null +++ b/Lib/test/test_concurrent_futures/__init__.py @@ -0,0 +1,16 @@ +import os.path +import unittest +from test import support +from test.support import import_helper + +# Skip tests if _multiprocessing wasn't built. +import_helper.import_module('_multiprocessing') + +if support.check_sanitizer(address=True, memory=True): + # gh-90791: Skip the test because it is too slow when Python is built + # with ASAN/MSAN: between 5 and 20 minutes on GitHub Actions. + raise unittest.SkipTest("test too slow on ASAN/MSAN build") + + +def load_tests(*args): + return support.load_package_tests(os.path.dirname(__file__), *args) diff --git a/Lib/test/test_concurrent_futures/executor.py b/Lib/test/test_concurrent_futures/executor.py new file mode 100644 index 00000000000000..1e7d4344740943 --- /dev/null +++ b/Lib/test/test_concurrent_futures/executor.py @@ -0,0 +1,108 @@ +import threading +import time +import weakref +from concurrent import futures +from test import support + + +def mul(x, y): + return x * y + +def capture(*args, **kwargs): + return args, kwargs + + +class MyObject(object): + def my_method(self): + pass + + +def make_dummy_object(_): + return MyObject() + + +class ExecutorTest: + # Executor.shutdown() and context manager usage is tested by + # ExecutorShutdownTest. + def test_submit(self): + future = self.executor.submit(pow, 2, 8) + self.assertEqual(256, future.result()) + + def test_submit_keyword(self): + future = self.executor.submit(mul, 2, y=8) + self.assertEqual(16, future.result()) + future = self.executor.submit(capture, 1, self=2, fn=3) + self.assertEqual(future.result(), ((1,), {'self': 2, 'fn': 3})) + with self.assertRaises(TypeError): + self.executor.submit(fn=capture, arg=1) + with self.assertRaises(TypeError): + self.executor.submit(arg=1) + + def test_map(self): + self.assertEqual( + list(self.executor.map(pow, range(10), range(10))), + list(map(pow, range(10), range(10)))) + + self.assertEqual( + list(self.executor.map(pow, range(10), range(10), chunksize=3)), + list(map(pow, range(10), range(10)))) + + def test_map_exception(self): + i = self.executor.map(divmod, [1, 1, 1, 1], [2, 3, 0, 5]) + self.assertEqual(i.__next__(), (0, 1)) + self.assertEqual(i.__next__(), (0, 1)) + self.assertRaises(ZeroDivisionError, i.__next__) + + @support.requires_resource('walltime') + def test_map_timeout(self): + results = [] + try: + for i in self.executor.map(time.sleep, + [0, 0, 6], + timeout=5): + results.append(i) + except futures.TimeoutError: + pass + else: + self.fail('expected TimeoutError') + + self.assertEqual([None, None], results) + + def test_shutdown_race_issue12456(self): + # Issue #12456: race condition at shutdown where trying to post a + # sentinel in the call queue blocks (the queue is full while processes + # have exited). + self.executor.map(str, [2] * (self.worker_count + 1)) + self.executor.shutdown() + + @support.cpython_only + def test_no_stale_references(self): + # Issue #16284: check that the executors don't unnecessarily hang onto + # references. + my_object = MyObject() + my_object_collected = threading.Event() + my_object_callback = weakref.ref( + my_object, lambda obj: my_object_collected.set()) + # Deliberately discarding the future. + self.executor.submit(my_object.my_method) + del my_object + + collected = my_object_collected.wait(timeout=support.SHORT_TIMEOUT) + self.assertTrue(collected, + "Stale reference not collected within timeout.") + + def test_max_workers_negative(self): + for number in (0, -1): + with self.assertRaisesRegex(ValueError, + "max_workers must be greater " + "than 0"): + self.executor_type(max_workers=number) + + def test_free_reference(self): + # Issue #14406: Result iterator should not keep an internal + # reference to result objects. + for obj in self.executor.map(make_dummy_object, range(10)): + wr = weakref.ref(obj) + del obj + support.gc_collect() # For PyPy or other GCs. + self.assertIsNone(wr()) diff --git a/Lib/test/test_concurrent_futures/test_as_completed.py b/Lib/test/test_concurrent_futures/test_as_completed.py new file mode 100644 index 00000000000000..c90b0021d85fc7 --- /dev/null +++ b/Lib/test/test_concurrent_futures/test_as_completed.py @@ -0,0 +1,118 @@ +import itertools +import time +import unittest +import weakref +from concurrent import futures +from concurrent.futures._base import ( + CANCELLED_AND_NOTIFIED, FINISHED, Future) + +from test import support + +from .util import ( + PENDING_FUTURE, RUNNING_FUTURE, + CANCELLED_AND_NOTIFIED_FUTURE, EXCEPTION_FUTURE, SUCCESSFUL_FUTURE, + create_future, create_executor_tests, setup_module) + + +def mul(x, y): + return x * y + + +class AsCompletedTests: + def test_no_timeout(self): + future1 = self.executor.submit(mul, 2, 21) + future2 = self.executor.submit(mul, 7, 6) + + completed = set(futures.as_completed( + [CANCELLED_AND_NOTIFIED_FUTURE, + EXCEPTION_FUTURE, + SUCCESSFUL_FUTURE, + future1, future2])) + self.assertEqual(set( + [CANCELLED_AND_NOTIFIED_FUTURE, + EXCEPTION_FUTURE, + SUCCESSFUL_FUTURE, + future1, future2]), + completed) + + def test_future_times_out(self): + """Test ``futures.as_completed`` timing out before + completing it's final future.""" + already_completed = {CANCELLED_AND_NOTIFIED_FUTURE, + EXCEPTION_FUTURE, + SUCCESSFUL_FUTURE} + + # Windows clock resolution is around 15.6 ms + short_timeout = 0.100 + for timeout in (0, short_timeout): + with self.subTest(timeout): + + completed_futures = set() + future = self.executor.submit(time.sleep, short_timeout * 10) + + try: + for f in futures.as_completed( + already_completed | {future}, + timeout + ): + completed_futures.add(f) + except futures.TimeoutError: + pass + + # Check that ``future`` wasn't completed. + self.assertEqual(completed_futures, already_completed) + + def test_duplicate_futures(self): + # Issue 20367. Duplicate futures should not raise exceptions or give + # duplicate responses. + # Issue #31641: accept arbitrary iterables. + future1 = self.executor.submit(time.sleep, 2) + completed = [ + f for f in futures.as_completed(itertools.repeat(future1, 3)) + ] + self.assertEqual(len(completed), 1) + + def test_free_reference_yielded_future(self): + # Issue #14406: Generator should not keep references + # to finished futures. + futures_list = [Future() for _ in range(8)] + futures_list.append(create_future(state=CANCELLED_AND_NOTIFIED)) + futures_list.append(create_future(state=FINISHED, result=42)) + + with self.assertRaises(futures.TimeoutError): + for future in futures.as_completed(futures_list, timeout=0): + futures_list.remove(future) + wr = weakref.ref(future) + del future + support.gc_collect() # For PyPy or other GCs. + self.assertIsNone(wr()) + + futures_list[0].set_result("test") + for future in futures.as_completed(futures_list): + futures_list.remove(future) + wr = weakref.ref(future) + del future + support.gc_collect() # For PyPy or other GCs. + self.assertIsNone(wr()) + if futures_list: + futures_list[0].set_result("test") + + def test_correct_timeout_exception_msg(self): + futures_list = [CANCELLED_AND_NOTIFIED_FUTURE, PENDING_FUTURE, + RUNNING_FUTURE, SUCCESSFUL_FUTURE] + + with self.assertRaises(futures.TimeoutError) as cm: + list(futures.as_completed(futures_list, timeout=0)) + + self.assertEqual(str(cm.exception), '2 (of 4) futures unfinished') + + +create_executor_tests(globals(), AsCompletedTests) + + +def setUpModule(): + setup_module() + + +if __name__ == "__main__": + unittest.main() diff --git a/Lib/test/test_concurrent_futures/test_deadlock.py b/Lib/test/test_concurrent_futures/test_deadlock.py new file mode 100644 index 00000000000000..3c30c4558c0b3e --- /dev/null +++ b/Lib/test/test_concurrent_futures/test_deadlock.py @@ -0,0 +1,332 @@ +import contextlib +import queue +import signal +import sys +import time +import unittest +import unittest.mock +from pickle import PicklingError +from concurrent import futures +from concurrent.futures.process import BrokenProcessPool, _ThreadWakeup + +from test import support + +from .util import ( + create_executor_tests, setup_module, + ProcessPoolForkMixin, ProcessPoolForkserverMixin, ProcessPoolSpawnMixin) + + +def _crash(delay=None): + """Induces a segfault.""" + if delay: + time.sleep(delay) + import faulthandler + faulthandler.disable() + faulthandler._sigsegv() + + +def _crash_with_data(data): + """Induces a segfault with dummy data in input.""" + _crash() + + +def _exit(): + """Induces a sys exit with exitcode 1.""" + sys.exit(1) + + +def _raise_error(Err): + """Function that raises an Exception in process.""" + raise Err() + + +def _raise_error_ignore_stderr(Err): + """Function that raises an Exception in process and ignores stderr.""" + import io + sys.stderr = io.StringIO() + raise Err() + + +def _return_instance(cls): + """Function that returns a instance of cls.""" + return cls() + + +class CrashAtPickle(object): + """Bad object that triggers a segfault at pickling time.""" + def __reduce__(self): + _crash() + + +class CrashAtUnpickle(object): + """Bad object that triggers a segfault at unpickling time.""" + def __reduce__(self): + return _crash, () + + +class ExitAtPickle(object): + """Bad object that triggers a process exit at pickling time.""" + def __reduce__(self): + _exit() + + +class ExitAtUnpickle(object): + """Bad object that triggers a process exit at unpickling time.""" + def __reduce__(self): + return _exit, () + + +class ErrorAtPickle(object): + """Bad object that triggers an error at pickling time.""" + def __reduce__(self): + from pickle import PicklingError + raise PicklingError("Error in pickle") + + +class ErrorAtUnpickle(object): + """Bad object that triggers an error at unpickling time.""" + def __reduce__(self): + from pickle import UnpicklingError + return _raise_error_ignore_stderr, (UnpicklingError, ) + + +class ExecutorDeadlockTest: + TIMEOUT = support.LONG_TIMEOUT + + def _fail_on_deadlock(self, executor): + # If we did not recover before TIMEOUT seconds, consider that the + # executor is in a deadlock state and forcefully clean all its + # composants. + import faulthandler + from tempfile import TemporaryFile + with TemporaryFile(mode="w+") as f: + faulthandler.dump_traceback(file=f) + f.seek(0) + tb = f.read() + for p in executor._processes.values(): + p.terminate() + # This should be safe to call executor.shutdown here as all possible + # deadlocks should have been broken. + executor.shutdown(wait=True) + print(f"\nTraceback:\n {tb}", file=sys.__stderr__) + self.fail(f"Executor deadlock:\n\n{tb}") + + + def _check_crash(self, error, func, *args, ignore_stderr=False): + # test for deadlock caused by crashes in a pool + self.executor.shutdown(wait=True) + + executor = self.executor_type( + max_workers=2, mp_context=self.get_context()) + res = executor.submit(func, *args) + + if ignore_stderr: + cm = support.captured_stderr() + else: + cm = contextlib.nullcontext() + + try: + with self.assertRaises(error): + with cm: + res.result(timeout=self.TIMEOUT) + except futures.TimeoutError: + # If we did not recover before TIMEOUT seconds, + # consider that the executor is in a deadlock state + self._fail_on_deadlock(executor) + executor.shutdown(wait=True) + + def test_error_at_task_pickle(self): + # Check problem occurring while pickling a task in + # the task_handler thread + self._check_crash(PicklingError, id, ErrorAtPickle()) + + def test_exit_at_task_unpickle(self): + # Check problem occurring while unpickling a task on workers + self._check_crash(BrokenProcessPool, id, ExitAtUnpickle()) + + def test_error_at_task_unpickle(self): + # gh-109832: Restore stderr overriden by _raise_error_ignore_stderr() + self.addCleanup(setattr, sys, 'stderr', sys.stderr) + + # Check problem occurring while unpickling a task on workers + self._check_crash(BrokenProcessPool, id, ErrorAtUnpickle()) + + def test_crash_at_task_unpickle(self): + # Check problem occurring while unpickling a task on workers + self._check_crash(BrokenProcessPool, id, CrashAtUnpickle()) + + def test_crash_during_func_exec_on_worker(self): + # Check problem occurring during func execution on workers + self._check_crash(BrokenProcessPool, _crash) + + def test_exit_during_func_exec_on_worker(self): + # Check problem occurring during func execution on workers + self._check_crash(SystemExit, _exit) + + def test_error_during_func_exec_on_worker(self): + # Check problem occurring during func execution on workers + self._check_crash(RuntimeError, _raise_error, RuntimeError) + + def test_crash_during_result_pickle_on_worker(self): + # Check problem occurring while pickling a task result + # on workers + self._check_crash(BrokenProcessPool, _return_instance, CrashAtPickle) + + def test_exit_during_result_pickle_on_worker(self): + # Check problem occurring while pickling a task result + # on workers + self._check_crash(SystemExit, _return_instance, ExitAtPickle) + + def test_error_during_result_pickle_on_worker(self): + # Check problem occurring while pickling a task result + # on workers + self._check_crash(PicklingError, _return_instance, ErrorAtPickle) + + def test_error_during_result_unpickle_in_result_handler(self): + # gh-109832: Restore stderr overriden by _raise_error_ignore_stderr() + self.addCleanup(setattr, sys, 'stderr', sys.stderr) + + # Check problem occurring while unpickling a task in + # the result_handler thread + self._check_crash(BrokenProcessPool, + _return_instance, ErrorAtUnpickle, + ignore_stderr=True) + + def test_exit_during_result_unpickle_in_result_handler(self): + # Check problem occurring while unpickling a task in + # the result_handler thread + self._check_crash(BrokenProcessPool, _return_instance, ExitAtUnpickle) + + def test_shutdown_deadlock(self): + # Test that the pool calling shutdown do not cause deadlock + # if a worker fails after the shutdown call. + self.executor.shutdown(wait=True) + with self.executor_type(max_workers=2, + mp_context=self.get_context()) as executor: + self.executor = executor # Allow clean up in fail_on_deadlock + f = executor.submit(_crash, delay=.1) + executor.shutdown(wait=True) + with self.assertRaises(BrokenProcessPool): + f.result() + + def test_shutdown_deadlock_pickle(self): + # Test that the pool calling shutdown with wait=False does not cause + # a deadlock if a task fails at pickle after the shutdown call. + # Reported in bpo-39104. + self.executor.shutdown(wait=True) + with self.executor_type(max_workers=2, + mp_context=self.get_context()) as executor: + self.executor = executor # Allow clean up in fail_on_deadlock + + # Start the executor and get the executor_manager_thread to collect + # the threads and avoid dangling thread that should be cleaned up + # asynchronously. + executor.submit(id, 42).result() + executor_manager = executor._executor_manager_thread + + # Submit a task that fails at pickle and shutdown the executor + # without waiting + f = executor.submit(id, ErrorAtPickle()) + executor.shutdown(wait=False) + with self.assertRaises(PicklingError): + f.result() + + # Make sure the executor is eventually shutdown and do not leave + # dangling threads + executor_manager.join() + + def test_crash_big_data(self): + # Test that there is a clean exception instad of a deadlock when a + # child process crashes while some data is being written into the + # queue. + # https://github.com/python/cpython/issues/94777 + self.executor.shutdown(wait=True) + data = "a" * support.PIPE_MAX_SIZE + with self.executor_type(max_workers=2, + mp_context=self.get_context()) as executor: + self.executor = executor # Allow clean up in fail_on_deadlock + with self.assertRaises(BrokenProcessPool): + list(executor.map(_crash_with_data, [data] * 10)) + + executor.shutdown(wait=True) + + def test_gh105829_should_not_deadlock_if_wakeup_pipe_full(self): + # Issue #105829: The _ExecutorManagerThread wakeup pipe could + # fill up and block. See: https://github.com/python/cpython/issues/105829 + + # Lots of cargo culting while writing this test, apologies if + # something is really stupid... + + self.executor.shutdown(wait=True) + + if not hasattr(signal, 'alarm'): + raise unittest.SkipTest( + "Tested platform does not support the alarm signal") + + def timeout(_signum, _frame): + import faulthandler + faulthandler.dump_traceback() + + raise RuntimeError("timed out while submitting jobs?") + + thread_run = futures.process._ExecutorManagerThread.run + def mock_run(self): + # Delay thread startup so the wakeup pipe can fill up and block + time.sleep(3) + thread_run(self) + + class MockWakeup(_ThreadWakeup): + """Mock wakeup object to force the wakeup to block""" + def __init__(self): + super().__init__() + self._dummy_queue = queue.Queue(maxsize=1) + + def wakeup(self): + self._dummy_queue.put(None, block=True) + super().wakeup() + + def clear(self): + super().clear() + try: + while True: + self._dummy_queue.get_nowait() + except queue.Empty: + pass + + with (unittest.mock.patch.object(futures.process._ExecutorManagerThread, + 'run', mock_run), + unittest.mock.patch('concurrent.futures.process._ThreadWakeup', + MockWakeup)): + with self.executor_type(max_workers=2, + mp_context=self.get_context()) as executor: + self.executor = executor # Allow clean up in fail_on_deadlock + + job_num = 100 + job_data = range(job_num) + + # Need to use sigalarm for timeout detection because + # Executor.submit is not guarded by any timeout (both + # self._work_ids.put(self._queue_count) and + # self._executor_manager_thread_wakeup.wakeup() might + # timeout, maybe more?). In this specific case it was + # the wakeup call that deadlocked on a blocking pipe. + old_handler = signal.signal(signal.SIGALRM, timeout) + try: + signal.alarm(int(self.TIMEOUT)) + self.assertEqual(job_num, len(list(executor.map(int, job_data)))) + finally: + signal.alarm(0) + signal.signal(signal.SIGALRM, old_handler) + + +create_executor_tests(globals(), ExecutorDeadlockTest, + executor_mixins=(ProcessPoolForkMixin, + ProcessPoolForkserverMixin, + ProcessPoolSpawnMixin)) + +def setUpModule(): + setup_module() + + +if __name__ == "__main__": + unittest.main() diff --git a/Lib/test/test_concurrent_futures/test_future.py b/Lib/test/test_concurrent_futures/test_future.py new file mode 100644 index 00000000000000..4066ea1ee4b367 --- /dev/null +++ b/Lib/test/test_concurrent_futures/test_future.py @@ -0,0 +1,291 @@ +import threading +import time +import unittest +from concurrent import futures +from concurrent.futures._base import ( + PENDING, RUNNING, CANCELLED, CANCELLED_AND_NOTIFIED, FINISHED, Future) + +from test import support + +from .util import ( + PENDING_FUTURE, RUNNING_FUTURE, CANCELLED_FUTURE, + CANCELLED_AND_NOTIFIED_FUTURE, EXCEPTION_FUTURE, SUCCESSFUL_FUTURE, + BaseTestCase, create_future, setup_module) + + +class FutureTests(BaseTestCase): + def test_done_callback_with_result(self): + callback_result = None + def fn(callback_future): + nonlocal callback_result + callback_result = callback_future.result() + + f = Future() + f.add_done_callback(fn) + f.set_result(5) + self.assertEqual(5, callback_result) + + def test_done_callback_with_exception(self): + callback_exception = None + def fn(callback_future): + nonlocal callback_exception + callback_exception = callback_future.exception() + + f = Future() + f.add_done_callback(fn) + f.set_exception(Exception('test')) + self.assertEqual(('test',), callback_exception.args) + + def test_done_callback_with_cancel(self): + was_cancelled = None + def fn(callback_future): + nonlocal was_cancelled + was_cancelled = callback_future.cancelled() + + f = Future() + f.add_done_callback(fn) + self.assertTrue(f.cancel()) + self.assertTrue(was_cancelled) + + def test_done_callback_raises(self): + with support.captured_stderr() as stderr: + raising_was_called = False + fn_was_called = False + + def raising_fn(callback_future): + nonlocal raising_was_called + raising_was_called = True + raise Exception('doh!') + + def fn(callback_future): + nonlocal fn_was_called + fn_was_called = True + + f = Future() + f.add_done_callback(raising_fn) + f.add_done_callback(fn) + f.set_result(5) + self.assertTrue(raising_was_called) + self.assertTrue(fn_was_called) + self.assertIn('Exception: doh!', stderr.getvalue()) + + def test_done_callback_already_successful(self): + callback_result = None + def fn(callback_future): + nonlocal callback_result + callback_result = callback_future.result() + + f = Future() + f.set_result(5) + f.add_done_callback(fn) + self.assertEqual(5, callback_result) + + def test_done_callback_already_failed(self): + callback_exception = None + def fn(callback_future): + nonlocal callback_exception + callback_exception = callback_future.exception() + + f = Future() + f.set_exception(Exception('test')) + f.add_done_callback(fn) + self.assertEqual(('test',), callback_exception.args) + + def test_done_callback_already_cancelled(self): + was_cancelled = None + def fn(callback_future): + nonlocal was_cancelled + was_cancelled = callback_future.cancelled() + + f = Future() + self.assertTrue(f.cancel()) + f.add_done_callback(fn) + self.assertTrue(was_cancelled) + + def test_done_callback_raises_already_succeeded(self): + with support.captured_stderr() as stderr: + def raising_fn(callback_future): + raise Exception('doh!') + + f = Future() + + # Set the result first to simulate a future that runs instantly, + # effectively allowing the callback to be run immediately. + f.set_result(5) + f.add_done_callback(raising_fn) + + self.assertIn('exception calling callback for', stderr.getvalue()) + self.assertIn('doh!', stderr.getvalue()) + + + def test_repr(self): + self.assertRegex(repr(PENDING_FUTURE), + '') + self.assertRegex(repr(RUNNING_FUTURE), + '') + self.assertRegex(repr(CANCELLED_FUTURE), + '') + self.assertRegex(repr(CANCELLED_AND_NOTIFIED_FUTURE), + '') + self.assertRegex( + repr(EXCEPTION_FUTURE), + '') + self.assertRegex( + repr(SUCCESSFUL_FUTURE), + '') + + def test_cancel(self): + f1 = create_future(state=PENDING) + f2 = create_future(state=RUNNING) + f3 = create_future(state=CANCELLED) + f4 = create_future(state=CANCELLED_AND_NOTIFIED) + f5 = create_future(state=FINISHED, exception=OSError()) + f6 = create_future(state=FINISHED, result=5) + + self.assertTrue(f1.cancel()) + self.assertEqual(f1._state, CANCELLED) + + self.assertFalse(f2.cancel()) + self.assertEqual(f2._state, RUNNING) + + self.assertTrue(f3.cancel()) + self.assertEqual(f3._state, CANCELLED) + + self.assertTrue(f4.cancel()) + self.assertEqual(f4._state, CANCELLED_AND_NOTIFIED) + + self.assertFalse(f5.cancel()) + self.assertEqual(f5._state, FINISHED) + + self.assertFalse(f6.cancel()) + self.assertEqual(f6._state, FINISHED) + + def test_cancelled(self): + self.assertFalse(PENDING_FUTURE.cancelled()) + self.assertFalse(RUNNING_FUTURE.cancelled()) + self.assertTrue(CANCELLED_FUTURE.cancelled()) + self.assertTrue(CANCELLED_AND_NOTIFIED_FUTURE.cancelled()) + self.assertFalse(EXCEPTION_FUTURE.cancelled()) + self.assertFalse(SUCCESSFUL_FUTURE.cancelled()) + + def test_done(self): + self.assertFalse(PENDING_FUTURE.done()) + self.assertFalse(RUNNING_FUTURE.done()) + self.assertTrue(CANCELLED_FUTURE.done()) + self.assertTrue(CANCELLED_AND_NOTIFIED_FUTURE.done()) + self.assertTrue(EXCEPTION_FUTURE.done()) + self.assertTrue(SUCCESSFUL_FUTURE.done()) + + def test_running(self): + self.assertFalse(PENDING_FUTURE.running()) + self.assertTrue(RUNNING_FUTURE.running()) + self.assertFalse(CANCELLED_FUTURE.running()) + self.assertFalse(CANCELLED_AND_NOTIFIED_FUTURE.running()) + self.assertFalse(EXCEPTION_FUTURE.running()) + self.assertFalse(SUCCESSFUL_FUTURE.running()) + + def test_result_with_timeout(self): + self.assertRaises(futures.TimeoutError, + PENDING_FUTURE.result, timeout=0) + self.assertRaises(futures.TimeoutError, + RUNNING_FUTURE.result, timeout=0) + self.assertRaises(futures.CancelledError, + CANCELLED_FUTURE.result, timeout=0) + self.assertRaises(futures.CancelledError, + CANCELLED_AND_NOTIFIED_FUTURE.result, timeout=0) + self.assertRaises(OSError, EXCEPTION_FUTURE.result, timeout=0) + self.assertEqual(SUCCESSFUL_FUTURE.result(timeout=0), 42) + + def test_result_with_success(self): + # TODO(brian@sweetapp.com): This test is timing dependent. + def notification(): + # Wait until the main thread is waiting for the result. + time.sleep(1) + f1.set_result(42) + + f1 = create_future(state=PENDING) + t = threading.Thread(target=notification) + t.start() + + self.assertEqual(f1.result(timeout=5), 42) + t.join() + + def test_result_with_cancel(self): + # TODO(brian@sweetapp.com): This test is timing dependent. + def notification(): + # Wait until the main thread is waiting for the result. + time.sleep(1) + f1.cancel() + + f1 = create_future(state=PENDING) + t = threading.Thread(target=notification) + t.start() + + self.assertRaises(futures.CancelledError, + f1.result, timeout=support.SHORT_TIMEOUT) + t.join() + + def test_exception_with_timeout(self): + self.assertRaises(futures.TimeoutError, + PENDING_FUTURE.exception, timeout=0) + self.assertRaises(futures.TimeoutError, + RUNNING_FUTURE.exception, timeout=0) + self.assertRaises(futures.CancelledError, + CANCELLED_FUTURE.exception, timeout=0) + self.assertRaises(futures.CancelledError, + CANCELLED_AND_NOTIFIED_FUTURE.exception, timeout=0) + self.assertTrue(isinstance(EXCEPTION_FUTURE.exception(timeout=0), + OSError)) + self.assertEqual(SUCCESSFUL_FUTURE.exception(timeout=0), None) + + def test_exception_with_success(self): + def notification(): + # Wait until the main thread is waiting for the exception. + time.sleep(1) + with f1._condition: + f1._state = FINISHED + f1._exception = OSError() + f1._condition.notify_all() + + f1 = create_future(state=PENDING) + t = threading.Thread(target=notification) + t.start() + + self.assertTrue(isinstance(f1.exception(timeout=support.SHORT_TIMEOUT), OSError)) + t.join() + + def test_multiple_set_result(self): + f = create_future(state=PENDING) + f.set_result(1) + + with self.assertRaisesRegex( + futures.InvalidStateError, + 'FINISHED: ' + ): + f.set_result(2) + + self.assertTrue(f.done()) + self.assertEqual(f.result(), 1) + + def test_multiple_set_exception(self): + f = create_future(state=PENDING) + e = ValueError() + f.set_exception(e) + + with self.assertRaisesRegex( + futures.InvalidStateError, + 'FINISHED: ' + ): + f.set_exception(Exception()) + + self.assertEqual(f.exception(), e) + + +def setUpModule(): + setup_module() + + +if __name__ == "__main__": + unittest.main() diff --git a/Lib/test/test_concurrent_futures/test_init.py b/Lib/test/test_concurrent_futures/test_init.py new file mode 100644 index 00000000000000..ce01e0ff0f287a --- /dev/null +++ b/Lib/test/test_concurrent_futures/test_init.py @@ -0,0 +1,117 @@ +import contextlib +import logging +import queue +import time +import unittest +from concurrent.futures._base import BrokenExecutor +from logging.handlers import QueueHandler + +from test import support + +from .util import ExecutorMixin, create_executor_tests, setup_module + + +INITIALIZER_STATUS = 'uninitialized' + +def init(x): + global INITIALIZER_STATUS + INITIALIZER_STATUS = x + +def get_init_status(): + return INITIALIZER_STATUS + +def init_fail(log_queue=None): + if log_queue is not None: + logger = logging.getLogger('concurrent.futures') + logger.addHandler(QueueHandler(log_queue)) + logger.setLevel('CRITICAL') + logger.propagate = False + time.sleep(0.1) # let some futures be scheduled + raise ValueError('error in initializer') + + +class InitializerMixin(ExecutorMixin): + worker_count = 2 + + def setUp(self): + global INITIALIZER_STATUS + INITIALIZER_STATUS = 'uninitialized' + self.executor_kwargs = dict(initializer=init, + initargs=('initialized',)) + super().setUp() + + def test_initializer(self): + futures = [self.executor.submit(get_init_status) + for _ in range(self.worker_count)] + + for f in futures: + self.assertEqual(f.result(), 'initialized') + + +class FailingInitializerMixin(ExecutorMixin): + worker_count = 2 + + def setUp(self): + if hasattr(self, "ctx"): + # Pass a queue to redirect the child's logging output + self.mp_context = self.get_context() + self.log_queue = self.mp_context.Queue() + self.executor_kwargs = dict(initializer=init_fail, + initargs=(self.log_queue,)) + else: + # In a thread pool, the child shares our logging setup + # (see _assert_logged()) + self.mp_context = None + self.log_queue = None + self.executor_kwargs = dict(initializer=init_fail) + super().setUp() + + def test_initializer(self): + with self._assert_logged('ValueError: error in initializer'): + try: + future = self.executor.submit(get_init_status) + except BrokenExecutor: + # Perhaps the executor is already broken + pass + else: + with self.assertRaises(BrokenExecutor): + future.result() + + # At some point, the executor should break + for _ in support.sleeping_retry(support.SHORT_TIMEOUT, + "executor not broken"): + if self.executor._broken: + break + + # ... and from this point submit() is guaranteed to fail + with self.assertRaises(BrokenExecutor): + self.executor.submit(get_init_status) + + @contextlib.contextmanager + def _assert_logged(self, msg): + if self.log_queue is not None: + yield + output = [] + try: + while True: + output.append(self.log_queue.get_nowait().getMessage()) + except queue.Empty: + pass + else: + with self.assertLogs('concurrent.futures', 'CRITICAL') as cm: + yield + output = cm.output + self.assertTrue(any(msg in line for line in output), + output) + + +create_executor_tests(globals(), InitializerMixin) +create_executor_tests(globals(), FailingInitializerMixin) + + +def setUpModule(): + setup_module() + + +if __name__ == "__main__": + unittest.main() diff --git a/Lib/test/test_concurrent_futures/test_process_pool.py b/Lib/test/test_concurrent_futures/test_process_pool.py new file mode 100644 index 00000000000000..3e61b0c9387c6f --- /dev/null +++ b/Lib/test/test_concurrent_futures/test_process_pool.py @@ -0,0 +1,231 @@ +import os +import sys +import threading +import time +import unittest +from concurrent import futures +from concurrent.futures.process import BrokenProcessPool + +from test import support +from test.support import hashlib_helper + +from .executor import ExecutorTest, mul +from .util import ( + ProcessPoolForkMixin, ProcessPoolForkserverMixin, ProcessPoolSpawnMixin, + create_executor_tests, setup_module) + + +class EventfulGCObj(): + def __init__(self, mgr): + self.event = mgr.Event() + + def __del__(self): + self.event.set() + + +class ProcessPoolExecutorTest(ExecutorTest): + + @unittest.skipUnless(sys.platform=='win32', 'Windows-only process limit') + def test_max_workers_too_large(self): + with self.assertRaisesRegex(ValueError, + "max_workers must be <= 61"): + futures.ProcessPoolExecutor(max_workers=62) + + def test_killed_child(self): + # When a child process is abruptly terminated, the whole pool gets + # "broken". + futures = [self.executor.submit(time.sleep, 3)] + # Get one of the processes, and terminate (kill) it + p = next(iter(self.executor._processes.values())) + p.terminate() + for fut in futures: + self.assertRaises(BrokenProcessPool, fut.result) + # Submitting other jobs fails as well. + self.assertRaises(BrokenProcessPool, self.executor.submit, pow, 2, 8) + + def test_map_chunksize(self): + def bad_map(): + list(self.executor.map(pow, range(40), range(40), chunksize=-1)) + + ref = list(map(pow, range(40), range(40))) + self.assertEqual( + list(self.executor.map(pow, range(40), range(40), chunksize=6)), + ref) + self.assertEqual( + list(self.executor.map(pow, range(40), range(40), chunksize=50)), + ref) + self.assertEqual( + list(self.executor.map(pow, range(40), range(40), chunksize=40)), + ref) + self.assertRaises(ValueError, bad_map) + + @classmethod + def _test_traceback(cls): + raise RuntimeError(123) # some comment + + def test_traceback(self): + # We want ensure that the traceback from the child process is + # contained in the traceback raised in the main process. + future = self.executor.submit(self._test_traceback) + with self.assertRaises(Exception) as cm: + future.result() + + exc = cm.exception + self.assertIs(type(exc), RuntimeError) + self.assertEqual(exc.args, (123,)) + cause = exc.__cause__ + self.assertIs(type(cause), futures.process._RemoteTraceback) + self.assertIn('raise RuntimeError(123) # some comment', cause.tb) + + with support.captured_stderr() as f1: + try: + raise exc + except RuntimeError: + sys.excepthook(*sys.exc_info()) + self.assertIn('raise RuntimeError(123) # some comment', + f1.getvalue()) + + @hashlib_helper.requires_hashdigest('md5') + def test_ressources_gced_in_workers(self): + # Ensure that argument for a job are correctly gc-ed after the job + # is finished + mgr = self.get_context().Manager() + obj = EventfulGCObj(mgr) + future = self.executor.submit(id, obj) + future.result() + + self.assertTrue(obj.event.wait(timeout=1)) + + # explicitly destroy the object to ensure that EventfulGCObj.__del__() + # is called while manager is still running. + obj = None + support.gc_collect() + + mgr.shutdown() + mgr.join() + + def test_saturation(self): + executor = self.executor + mp_context = self.get_context() + sem = mp_context.Semaphore(0) + job_count = 15 * executor._max_workers + for _ in range(job_count): + executor.submit(sem.acquire) + self.assertEqual(len(executor._processes), executor._max_workers) + for _ in range(job_count): + sem.release() + + def test_idle_process_reuse_one(self): + executor = self.executor + assert executor._max_workers >= 4 + if self.get_context().get_start_method(allow_none=False) == "fork": + raise unittest.SkipTest("Incompatible with the fork start method.") + executor.submit(mul, 21, 2).result() + executor.submit(mul, 6, 7).result() + executor.submit(mul, 3, 14).result() + self.assertEqual(len(executor._processes), 1) + + def test_idle_process_reuse_multiple(self): + executor = self.executor + assert executor._max_workers <= 5 + if self.get_context().get_start_method(allow_none=False) == "fork": + raise unittest.SkipTest("Incompatible with the fork start method.") + executor.submit(mul, 12, 7).result() + executor.submit(mul, 33, 25) + executor.submit(mul, 25, 26).result() + executor.submit(mul, 18, 29) + executor.submit(mul, 1, 2).result() + executor.submit(mul, 0, 9) + self.assertLessEqual(len(executor._processes), 3) + executor.shutdown() + + def test_max_tasks_per_child(self): + context = self.get_context() + if context.get_start_method(allow_none=False) == "fork": + with self.assertRaises(ValueError): + self.executor_type(1, mp_context=context, max_tasks_per_child=3) + return + # not using self.executor as we need to control construction. + # arguably this could go in another class w/o that mixin. + executor = self.executor_type( + 1, mp_context=context, max_tasks_per_child=3) + f1 = executor.submit(os.getpid) + original_pid = f1.result() + # The worker pid remains the same as the worker could be reused + f2 = executor.submit(os.getpid) + self.assertEqual(f2.result(), original_pid) + self.assertEqual(len(executor._processes), 1) + f3 = executor.submit(os.getpid) + self.assertEqual(f3.result(), original_pid) + + # A new worker is spawned, with a statistically different pid, + # while the previous was reaped. + f4 = executor.submit(os.getpid) + new_pid = f4.result() + self.assertNotEqual(original_pid, new_pid) + self.assertEqual(len(executor._processes), 1) + + executor.shutdown() + + def test_max_tasks_per_child_defaults_to_spawn_context(self): + # not using self.executor as we need to control construction. + # arguably this could go in another class w/o that mixin. + executor = self.executor_type(1, max_tasks_per_child=3) + self.assertEqual(executor._mp_context.get_start_method(), "spawn") + + def test_max_tasks_early_shutdown(self): + context = self.get_context() + if context.get_start_method(allow_none=False) == "fork": + raise unittest.SkipTest("Incompatible with the fork start method.") + # not using self.executor as we need to control construction. + # arguably this could go in another class w/o that mixin. + executor = self.executor_type( + 3, mp_context=context, max_tasks_per_child=1) + futures = [] + for i in range(6): + futures.append(executor.submit(mul, i, i)) + executor.shutdown() + for i, future in enumerate(futures): + self.assertEqual(future.result(), mul(i, i)) + + def test_python_finalization_error(self): + # gh-109047: Catch RuntimeError on thread creation + # during Python finalization. + + context = self.get_context() + + # gh-109047: Mock the threading.start_joinable_thread() function to inject + # RuntimeError: simulate the error raised during Python finalization. + # Block the second creation: create _ExecutorManagerThread, but block + # QueueFeederThread. + orig_start_new_thread = threading._start_joinable_thread + nthread = 0 + def mock_start_new_thread(func, *args): + nonlocal nthread + if nthread >= 1: + raise RuntimeError("can't create new thread at " + "interpreter shutdown") + nthread += 1 + return orig_start_new_thread(func, *args) + + with support.swap_attr(threading, '_start_joinable_thread', + mock_start_new_thread): + executor = self.executor_type(max_workers=2, mp_context=context) + with executor: + with self.assertRaises(BrokenProcessPool): + list(executor.map(mul, [(2, 3)] * 10)) + executor.shutdown() + + +create_executor_tests(globals(), ProcessPoolExecutorTest, + executor_mixins=(ProcessPoolForkMixin, + ProcessPoolForkserverMixin, + ProcessPoolSpawnMixin)) + + +def setUpModule(): + setup_module() + + +if __name__ == "__main__": + unittest.main() diff --git a/Lib/test/test_concurrent_futures/test_shutdown.py b/Lib/test/test_concurrent_futures/test_shutdown.py new file mode 100644 index 00000000000000..45dab7a75fdd50 --- /dev/null +++ b/Lib/test/test_concurrent_futures/test_shutdown.py @@ -0,0 +1,343 @@ +import signal +import sys +import threading +import time +import unittest +from concurrent import futures + +from test import support +from test.support.script_helper import assert_python_ok + +from .util import ( + BaseTestCase, ThreadPoolMixin, ProcessPoolForkMixin, + ProcessPoolForkserverMixin, ProcessPoolSpawnMixin, + create_executor_tests, setup_module) + + +def sleep_and_print(t, msg): + time.sleep(t) + print(msg) + sys.stdout.flush() + + +class ExecutorShutdownTest: + def test_run_after_shutdown(self): + self.executor.shutdown() + self.assertRaises(RuntimeError, + self.executor.submit, + pow, 2, 5) + + def test_interpreter_shutdown(self): + # Test the atexit hook for shutdown of worker threads and processes + rc, out, err = assert_python_ok('-c', """if 1: + from concurrent.futures import {executor_type} + from time import sleep + from test.test_concurrent_futures.test_shutdown import sleep_and_print + if __name__ == "__main__": + context = '{context}' + if context == "": + t = {executor_type}(5) + else: + from multiprocessing import get_context + context = get_context(context) + t = {executor_type}(5, mp_context=context) + t.submit(sleep_and_print, 1.0, "apple") + """.format(executor_type=self.executor_type.__name__, + context=getattr(self, "ctx", ""))) + # Errors in atexit hooks don't change the process exit code, check + # stderr manually. + self.assertFalse(err) + self.assertEqual(out.strip(), b"apple") + + def test_submit_after_interpreter_shutdown(self): + # Test the atexit hook for shutdown of worker threads and processes + rc, out, err = assert_python_ok('-c', """if 1: + import atexit + @atexit.register + def run_last(): + try: + t.submit(id, None) + except RuntimeError: + print("runtime-error") + raise + from concurrent.futures import {executor_type} + if __name__ == "__main__": + context = '{context}' + if not context: + t = {executor_type}(5) + else: + from multiprocessing import get_context + context = get_context(context) + t = {executor_type}(5, mp_context=context) + t.submit(id, 42).result() + """.format(executor_type=self.executor_type.__name__, + context=getattr(self, "ctx", ""))) + # Errors in atexit hooks don't change the process exit code, check + # stderr manually. + self.assertIn("RuntimeError: cannot schedule new futures", err.decode()) + self.assertEqual(out.strip(), b"runtime-error") + + def test_hang_issue12364(self): + fs = [self.executor.submit(time.sleep, 0.1) for _ in range(50)] + self.executor.shutdown() + for f in fs: + f.result() + + def test_cancel_futures(self): + assert self.worker_count <= 5, "test needs few workers" + fs = [self.executor.submit(time.sleep, .1) for _ in range(50)] + self.executor.shutdown(cancel_futures=True) + # We can't guarantee the exact number of cancellations, but we can + # guarantee that *some* were cancelled. With few workers, many of + # the submitted futures should have been cancelled. + cancelled = [fut for fut in fs if fut.cancelled()] + self.assertGreater(len(cancelled), 20) + + # Ensure the other futures were able to finish. + # Use "not fut.cancelled()" instead of "fut.done()" to include futures + # that may have been left in a pending state. + others = [fut for fut in fs if not fut.cancelled()] + for fut in others: + self.assertTrue(fut.done(), msg=f"{fut._state=}") + self.assertIsNone(fut.exception()) + + # Similar to the number of cancelled futures, we can't guarantee the + # exact number that completed. But, we can guarantee that at least + # one finished. + self.assertGreater(len(others), 0) + + def test_hang_gh83386(self): + """shutdown(wait=False) doesn't hang at exit with running futures. + + See https://github.com/python/cpython/issues/83386. + """ + if self.executor_type == futures.ProcessPoolExecutor: + raise unittest.SkipTest( + "Hangs, see https://github.com/python/cpython/issues/83386") + + rc, out, err = assert_python_ok('-c', """if True: + from concurrent.futures import {executor_type} + from test.test_concurrent_futures.test_shutdown import sleep_and_print + if __name__ == "__main__": + if {context!r}: multiprocessing.set_start_method({context!r}) + t = {executor_type}(max_workers=3) + t.submit(sleep_and_print, 1.0, "apple") + t.shutdown(wait=False) + """.format(executor_type=self.executor_type.__name__, + context=getattr(self, 'ctx', None))) + self.assertFalse(err) + self.assertEqual(out.strip(), b"apple") + + def test_hang_gh94440(self): + """shutdown(wait=True) doesn't hang when a future was submitted and + quickly canceled right before shutdown. + + See https://github.com/python/cpython/issues/94440. + """ + if not hasattr(signal, 'alarm'): + raise unittest.SkipTest( + "Tested platform does not support the alarm signal") + + def timeout(_signum, _frame): + raise RuntimeError("timed out waiting for shutdown") + + kwargs = {} + if getattr(self, 'ctx', None): + kwargs['mp_context'] = self.get_context() + executor = self.executor_type(max_workers=1, **kwargs) + executor.submit(int).result() + old_handler = signal.signal(signal.SIGALRM, timeout) + try: + signal.alarm(5) + executor.submit(int).cancel() + executor.shutdown(wait=True) + finally: + signal.alarm(0) + signal.signal(signal.SIGALRM, old_handler) + + +class ThreadPoolShutdownTest(ThreadPoolMixin, ExecutorShutdownTest, BaseTestCase): + def test_threads_terminate(self): + def acquire_lock(lock): + lock.acquire() + + sem = threading.Semaphore(0) + for i in range(3): + self.executor.submit(acquire_lock, sem) + self.assertEqual(len(self.executor._threads), 3) + for i in range(3): + sem.release() + self.executor.shutdown() + for t in self.executor._threads: + t.join() + + def test_context_manager_shutdown(self): + with futures.ThreadPoolExecutor(max_workers=5) as e: + executor = e + self.assertEqual(list(e.map(abs, range(-5, 5))), + [5, 4, 3, 2, 1, 0, 1, 2, 3, 4]) + + for t in executor._threads: + t.join() + + def test_del_shutdown(self): + executor = futures.ThreadPoolExecutor(max_workers=5) + res = executor.map(abs, range(-5, 5)) + threads = executor._threads + del executor + + for t in threads: + t.join() + + # Make sure the results were all computed before the + # executor got shutdown. + assert all([r == abs(v) for r, v in zip(res, range(-5, 5))]) + + def test_shutdown_no_wait(self): + # Ensure that the executor cleans up the threads when calling + # shutdown with wait=False + executor = futures.ThreadPoolExecutor(max_workers=5) + res = executor.map(abs, range(-5, 5)) + threads = executor._threads + executor.shutdown(wait=False) + for t in threads: + t.join() + + # Make sure the results were all computed before the + # executor got shutdown. + assert all([r == abs(v) for r, v in zip(res, range(-5, 5))]) + + + def test_thread_names_assigned(self): + executor = futures.ThreadPoolExecutor( + max_workers=5, thread_name_prefix='SpecialPool') + executor.map(abs, range(-5, 5)) + threads = executor._threads + del executor + support.gc_collect() # For PyPy or other GCs. + + for t in threads: + self.assertRegex(t.name, r'^SpecialPool_[0-4]$') + t.join() + + def test_thread_names_default(self): + executor = futures.ThreadPoolExecutor(max_workers=5) + executor.map(abs, range(-5, 5)) + threads = executor._threads + del executor + support.gc_collect() # For PyPy or other GCs. + + for t in threads: + # Ensure that our default name is reasonably sane and unique when + # no thread_name_prefix was supplied. + self.assertRegex(t.name, r'ThreadPoolExecutor-\d+_[0-4]$') + t.join() + + def test_cancel_futures_wait_false(self): + # Can only be reliably tested for TPE, since PPE often hangs with + # `wait=False` (even without *cancel_futures*). + rc, out, err = assert_python_ok('-c', """if True: + from concurrent.futures import ThreadPoolExecutor + from test.test_concurrent_futures.test_shutdown import sleep_and_print + if __name__ == "__main__": + t = ThreadPoolExecutor() + t.submit(sleep_and_print, .1, "apple") + t.shutdown(wait=False, cancel_futures=True) + """) + # Errors in atexit hooks don't change the process exit code, check + # stderr manually. + self.assertFalse(err) + self.assertEqual(out.strip(), b"apple") + + +class ProcessPoolShutdownTest(ExecutorShutdownTest): + def test_processes_terminate(self): + def acquire_lock(lock): + lock.acquire() + + mp_context = self.get_context() + if mp_context.get_start_method(allow_none=False) == "fork": + # fork pre-spawns, not on demand. + expected_num_processes = self.worker_count + else: + expected_num_processes = 3 + + sem = mp_context.Semaphore(0) + for _ in range(3): + self.executor.submit(acquire_lock, sem) + self.assertEqual(len(self.executor._processes), expected_num_processes) + for _ in range(3): + sem.release() + processes = self.executor._processes + self.executor.shutdown() + + for p in processes.values(): + p.join() + + def test_context_manager_shutdown(self): + with futures.ProcessPoolExecutor( + max_workers=5, mp_context=self.get_context()) as e: + processes = e._processes + self.assertEqual(list(e.map(abs, range(-5, 5))), + [5, 4, 3, 2, 1, 0, 1, 2, 3, 4]) + + for p in processes.values(): + p.join() + + def test_del_shutdown(self): + executor = futures.ProcessPoolExecutor( + max_workers=5, mp_context=self.get_context()) + res = executor.map(abs, range(-5, 5)) + executor_manager_thread = executor._executor_manager_thread + processes = executor._processes + call_queue = executor._call_queue + executor_manager_thread = executor._executor_manager_thread + del executor + support.gc_collect() # For PyPy or other GCs. + + # Make sure that all the executor resources were properly cleaned by + # the shutdown process + executor_manager_thread.join() + for p in processes.values(): + p.join() + call_queue.join_thread() + + # Make sure the results were all computed before the + # executor got shutdown. + assert all([r == abs(v) for r, v in zip(res, range(-5, 5))]) + + def test_shutdown_no_wait(self): + # Ensure that the executor cleans up the processes when calling + # shutdown with wait=False + executor = futures.ProcessPoolExecutor( + max_workers=5, mp_context=self.get_context()) + res = executor.map(abs, range(-5, 5)) + processes = executor._processes + call_queue = executor._call_queue + executor_manager_thread = executor._executor_manager_thread + executor.shutdown(wait=False) + + # Make sure that all the executor resources were properly cleaned by + # the shutdown process + executor_manager_thread.join() + for p in processes.values(): + p.join() + call_queue.join_thread() + + # Make sure the results were all computed before the executor got + # shutdown. + assert all([r == abs(v) for r, v in zip(res, range(-5, 5))]) + + +create_executor_tests(globals(), ProcessPoolShutdownTest, + executor_mixins=(ProcessPoolForkMixin, + ProcessPoolForkserverMixin, + ProcessPoolSpawnMixin)) + + +def setUpModule(): + setup_module() + + +if __name__ == "__main__": + unittest.main() diff --git a/Lib/test/test_concurrent_futures/test_thread_pool.py b/Lib/test/test_concurrent_futures/test_thread_pool.py new file mode 100644 index 00000000000000..5926a632aa4bec --- /dev/null +++ b/Lib/test/test_concurrent_futures/test_thread_pool.py @@ -0,0 +1,100 @@ +import contextlib +import multiprocessing as mp +import multiprocessing.process +import multiprocessing.util +import os +import threading +import unittest +from concurrent import futures +from test import support + +from .executor import ExecutorTest, mul +from .util import BaseTestCase, ThreadPoolMixin, setup_module + + +class ThreadPoolExecutorTest(ThreadPoolMixin, ExecutorTest, BaseTestCase): + def test_map_submits_without_iteration(self): + """Tests verifying issue 11777.""" + finished = [] + def record_finished(n): + finished.append(n) + + self.executor.map(record_finished, range(10)) + self.executor.shutdown(wait=True) + self.assertCountEqual(finished, range(10)) + + def test_default_workers(self): + executor = self.executor_type() + expected = min(32, (os.process_cpu_count() or 1) + 4) + self.assertEqual(executor._max_workers, expected) + + def test_saturation(self): + executor = self.executor_type(4) + def acquire_lock(lock): + lock.acquire() + + sem = threading.Semaphore(0) + for i in range(15 * executor._max_workers): + executor.submit(acquire_lock, sem) + self.assertEqual(len(executor._threads), executor._max_workers) + for i in range(15 * executor._max_workers): + sem.release() + executor.shutdown(wait=True) + + def test_idle_thread_reuse(self): + executor = self.executor_type() + executor.submit(mul, 21, 2).result() + executor.submit(mul, 6, 7).result() + executor.submit(mul, 3, 14).result() + self.assertEqual(len(executor._threads), 1) + executor.shutdown(wait=True) + + @unittest.skipUnless(hasattr(os, 'register_at_fork'), 'need os.register_at_fork') + @support.requires_resource('cpu') + def test_hang_global_shutdown_lock(self): + # bpo-45021: _global_shutdown_lock should be reinitialized in the child + # process, otherwise it will never exit + def submit(pool): + pool.submit(submit, pool) + + with futures.ThreadPoolExecutor(1) as pool: + pool.submit(submit, pool) + + for _ in range(50): + with futures.ProcessPoolExecutor(1, mp_context=mp.get_context('fork')) as workers: + workers.submit(tuple) + + def test_executor_map_current_future_cancel(self): + stop_event = threading.Event() + log = [] + + def log_n_wait(ident): + log.append(f"{ident=} started") + try: + stop_event.wait() + finally: + log.append(f"{ident=} stopped") + + with self.executor_type(max_workers=1) as pool: + # submit work to saturate the pool + fut = pool.submit(log_n_wait, ident="first") + try: + with contextlib.closing( + pool.map(log_n_wait, ["second", "third"], timeout=0) + ) as gen: + with self.assertRaises(TimeoutError): + next(gen) + finally: + stop_event.set() + fut.result() + # ident='second' is cancelled as a result of raising a TimeoutError + # ident='third' is cancelled because it remained in the collection of futures + self.assertListEqual(log, ["ident='first' started", "ident='first' stopped"]) + + +def setUpModule(): + setup_module() + + +if __name__ == "__main__": + unittest.main() diff --git a/Lib/test/test_concurrent_futures/test_wait.py b/Lib/test/test_concurrent_futures/test_wait.py new file mode 100644 index 00000000000000..ff486202092c81 --- /dev/null +++ b/Lib/test/test_concurrent_futures/test_wait.py @@ -0,0 +1,165 @@ +import sys +import threading +import time +import unittest +from concurrent import futures +from test import support + +from .util import ( + CANCELLED_FUTURE, CANCELLED_AND_NOTIFIED_FUTURE, EXCEPTION_FUTURE, + SUCCESSFUL_FUTURE, + create_executor_tests, setup_module, + BaseTestCase, ThreadPoolMixin, + ProcessPoolForkMixin, ProcessPoolForkserverMixin, ProcessPoolSpawnMixin) + + +def mul(x, y): + return x * y + +def sleep_and_raise(t): + time.sleep(t) + raise Exception('this is an exception') + + +class WaitTests: + def test_20369(self): + # See https://bugs.python.org/issue20369 + future = self.executor.submit(time.sleep, 1.5) + done, not_done = futures.wait([future, future], + return_when=futures.ALL_COMPLETED) + self.assertEqual({future}, done) + self.assertEqual(set(), not_done) + + + def test_first_completed(self): + future1 = self.executor.submit(mul, 21, 2) + future2 = self.executor.submit(time.sleep, 1.5) + + done, not_done = futures.wait( + [CANCELLED_FUTURE, future1, future2], + return_when=futures.FIRST_COMPLETED) + + self.assertEqual(set([future1]), done) + self.assertEqual(set([CANCELLED_FUTURE, future2]), not_done) + + def test_first_completed_some_already_completed(self): + future1 = self.executor.submit(time.sleep, 1.5) + + finished, pending = futures.wait( + [CANCELLED_AND_NOTIFIED_FUTURE, SUCCESSFUL_FUTURE, future1], + return_when=futures.FIRST_COMPLETED) + + self.assertEqual( + set([CANCELLED_AND_NOTIFIED_FUTURE, SUCCESSFUL_FUTURE]), + finished) + self.assertEqual(set([future1]), pending) + + @support.requires_resource('walltime') + def test_first_exception(self): + future1 = self.executor.submit(mul, 2, 21) + future2 = self.executor.submit(sleep_and_raise, 1.5) + future3 = self.executor.submit(time.sleep, 3) + + finished, pending = futures.wait( + [future1, future2, future3], + return_when=futures.FIRST_EXCEPTION) + + self.assertEqual(set([future1, future2]), finished) + self.assertEqual(set([future3]), pending) + + def test_first_exception_some_already_complete(self): + future1 = self.executor.submit(divmod, 21, 0) + future2 = self.executor.submit(time.sleep, 1.5) + + finished, pending = futures.wait( + [SUCCESSFUL_FUTURE, + CANCELLED_FUTURE, + CANCELLED_AND_NOTIFIED_FUTURE, + future1, future2], + return_when=futures.FIRST_EXCEPTION) + + self.assertEqual(set([SUCCESSFUL_FUTURE, + CANCELLED_AND_NOTIFIED_FUTURE, + future1]), finished) + self.assertEqual(set([CANCELLED_FUTURE, future2]), pending) + + def test_first_exception_one_already_failed(self): + future1 = self.executor.submit(time.sleep, 2) + + finished, pending = futures.wait( + [EXCEPTION_FUTURE, future1], + return_when=futures.FIRST_EXCEPTION) + + self.assertEqual(set([EXCEPTION_FUTURE]), finished) + self.assertEqual(set([future1]), pending) + + def test_all_completed(self): + future1 = self.executor.submit(divmod, 2, 0) + future2 = self.executor.submit(mul, 2, 21) + + finished, pending = futures.wait( + [SUCCESSFUL_FUTURE, + CANCELLED_AND_NOTIFIED_FUTURE, + EXCEPTION_FUTURE, + future1, + future2], + return_when=futures.ALL_COMPLETED) + + self.assertEqual(set([SUCCESSFUL_FUTURE, + CANCELLED_AND_NOTIFIED_FUTURE, + EXCEPTION_FUTURE, + future1, + future2]), finished) + self.assertEqual(set(), pending) + + def test_timeout(self): + short_timeout = 0.050 + long_timeout = short_timeout * 10 + + future = self.executor.submit(time.sleep, long_timeout) + + finished, pending = futures.wait( + [CANCELLED_AND_NOTIFIED_FUTURE, + EXCEPTION_FUTURE, + SUCCESSFUL_FUTURE, + future], + timeout=short_timeout, + return_when=futures.ALL_COMPLETED) + + self.assertEqual(set([CANCELLED_AND_NOTIFIED_FUTURE, + EXCEPTION_FUTURE, + SUCCESSFUL_FUTURE]), + finished) + self.assertEqual(set([future]), pending) + + +class ThreadPoolWaitTests(ThreadPoolMixin, WaitTests, BaseTestCase): + + def test_pending_calls_race(self): + # Issue #14406: multi-threaded race condition when waiting on all + # futures. + event = threading.Event() + def future_func(): + event.wait() + oldswitchinterval = sys.getswitchinterval() + sys.setswitchinterval(1e-6) + try: + fs = {self.executor.submit(future_func) for i in range(100)} + event.set() + futures.wait(fs, return_when=futures.ALL_COMPLETED) + finally: + sys.setswitchinterval(oldswitchinterval) + + +create_executor_tests(globals(), WaitTests, + executor_mixins=(ProcessPoolForkMixin, + ProcessPoolForkserverMixin, + ProcessPoolSpawnMixin)) + + +def setUpModule(): + setup_module() + + +if __name__ == "__main__": + unittest.main() diff --git a/Lib/test/test_concurrent_futures/util.py b/Lib/test/test_concurrent_futures/util.py new file mode 100644 index 00000000000000..dc48bec796b87f --- /dev/null +++ b/Lib/test/test_concurrent_futures/util.py @@ -0,0 +1,141 @@ +import multiprocessing +import sys +import time +import unittest +from concurrent import futures +from concurrent.futures._base import ( + PENDING, RUNNING, CANCELLED, CANCELLED_AND_NOTIFIED, FINISHED, Future, + ) +from concurrent.futures.process import _check_system_limits + +from test import support +from test.support import threading_helper + + +def create_future(state=PENDING, exception=None, result=None): + f = Future() + f._state = state + f._exception = exception + f._result = result + return f + + +PENDING_FUTURE = create_future(state=PENDING) +RUNNING_FUTURE = create_future(state=RUNNING) +CANCELLED_FUTURE = create_future(state=CANCELLED) +CANCELLED_AND_NOTIFIED_FUTURE = create_future(state=CANCELLED_AND_NOTIFIED) +EXCEPTION_FUTURE = create_future(state=FINISHED, exception=OSError()) +SUCCESSFUL_FUTURE = create_future(state=FINISHED, result=42) + + +class BaseTestCase(unittest.TestCase): + def setUp(self): + self._thread_key = threading_helper.threading_setup() + + def tearDown(self): + support.reap_children() + threading_helper.threading_cleanup(*self._thread_key) + + +class ExecutorMixin: + worker_count = 5 + executor_kwargs = {} + + def setUp(self): + super().setUp() + + self.t1 = time.monotonic() + if hasattr(self, "ctx"): + self.executor = self.executor_type( + max_workers=self.worker_count, + mp_context=self.get_context(), + **self.executor_kwargs) + else: + self.executor = self.executor_type( + max_workers=self.worker_count, + **self.executor_kwargs) + + def tearDown(self): + self.executor.shutdown(wait=True) + self.executor = None + + dt = time.monotonic() - self.t1 + if support.verbose: + print("%.2fs" % dt, end=' ') + self.assertLess(dt, 300, "synchronization issue: test lasted too long") + + super().tearDown() + + def get_context(self): + return multiprocessing.get_context(self.ctx) + + +class ThreadPoolMixin(ExecutorMixin): + executor_type = futures.ThreadPoolExecutor + + +class ProcessPoolForkMixin(ExecutorMixin): + executor_type = futures.ProcessPoolExecutor + ctx = "fork" + + def get_context(self): + try: + _check_system_limits() + except NotImplementedError: + self.skipTest("ProcessPoolExecutor unavailable on this system") + if sys.platform == "win32": + self.skipTest("require unix system") + return super().get_context() + + +class ProcessPoolSpawnMixin(ExecutorMixin): + executor_type = futures.ProcessPoolExecutor + ctx = "spawn" + + def get_context(self): + try: + _check_system_limits() + except NotImplementedError: + self.skipTest("ProcessPoolExecutor unavailable on this system") + return super().get_context() + + +class ProcessPoolForkserverMixin(ExecutorMixin): + executor_type = futures.ProcessPoolExecutor + ctx = "forkserver" + + def get_context(self): + try: + _check_system_limits() + except NotImplementedError: + self.skipTest("ProcessPoolExecutor unavailable on this system") + if sys.platform == "win32": + self.skipTest("require unix system") + return super().get_context() + + +def create_executor_tests(remote_globals, mixin, bases=(BaseTestCase,), + executor_mixins=(ThreadPoolMixin, + ProcessPoolForkMixin, + ProcessPoolForkserverMixin, + ProcessPoolSpawnMixin)): + def strip_mixin(name): + if name.endswith(('Mixin', 'Tests')): + return name[:-5] + elif name.endswith('Test'): + return name[:-4] + else: + return name + + module = remote_globals['__name__'] + for exe in executor_mixins: + name = ("%s%sTest" + % (strip_mixin(exe.__name__), strip_mixin(mixin.__name__))) + cls = type(name, (mixin,) + (exe,) + bases, {'__module__': module}) + remote_globals[name] = cls + + +def setup_module(): + unittest.addModuleCleanup(multiprocessing.util._cleanup_tests) + thread_info = threading_helper.threading_setup() + unittest.addModuleCleanup(threading_helper.threading_cleanup, *thread_info) diff --git a/Lib/test/test_configparser.py b/Lib/test/test_configparser.py index 53163d7528b64a..2d7dfbde7082ee 100644 --- a/Lib/test/test_configparser.py +++ b/Lib/test/test_configparser.py @@ -543,7 +543,7 @@ def test_parse_errors(self): "[Foo]\n wrong-indent\n") self.assertEqual(e.args, ('',)) # read_file on a real file - tricky = support.findfile("cfgparser.3") + tricky = support.findfile("cfgparser.3", subdir="configdata") if self.delimiters[0] == '=': error = configparser.ParsingError expected = (tricky,) @@ -717,7 +717,7 @@ class mystr(str): def test_read_returns_file_list(self): if self.delimiters[0] != '=': self.skipTest('incompatible format') - file1 = support.findfile("cfgparser.1") + file1 = support.findfile("cfgparser.1", subdir="configdata") # check when we pass a mix of readable and non-readable files: cf = self.newconfig() parsed_files = cf.read([file1, "nonexistent-file"], encoding="utf-8") @@ -750,7 +750,7 @@ def test_read_returns_file_list(self): def test_read_returns_file_list_with_bytestring_path(self): if self.delimiters[0] != '=': self.skipTest('incompatible format') - file1_bytestring = support.findfile("cfgparser.1").encode() + file1_bytestring = support.findfile("cfgparser.1", subdir="configdata").encode() # check when passing an existing bytestring path cf = self.newconfig() parsed_files = cf.read(file1_bytestring, encoding="utf-8") @@ -1126,7 +1126,7 @@ class RawConfigParserTestSambaConf(CfgParserTestCaseClass, unittest.TestCase): empty_lines_in_values = False def test_reading(self): - smbconf = support.findfile("cfgparser.2") + smbconf = support.findfile("cfgparser.2", subdir="configdata") # check when we pass a mix of readable and non-readable files: cf = self.newconfig() parsed_files = cf.read([smbconf, "nonexistent-file"], encoding='utf-8') @@ -1321,7 +1321,7 @@ class ConfigParserTestCaseTrickyFile(CfgParserTestCaseClass, unittest.TestCase): allow_no_value = True def test_cfgparser_dot_3(self): - tricky = support.findfile("cfgparser.3") + tricky = support.findfile("cfgparser.3", subdir="configdata") cf = self.newconfig() self.assertEqual(len(cf.read(tricky, encoding='utf-8')), 1) self.assertEqual(cf.sections(), ['strange', @@ -1353,7 +1353,7 @@ def test_cfgparser_dot_3(self): self.assertEqual(cf.get('more interpolation', 'lets'), 'go shopping') def test_unicode_failure(self): - tricky = support.findfile("cfgparser.3") + tricky = support.findfile("cfgparser.3", subdir="configdata") cf = self.newconfig() with self.assertRaises(UnicodeDecodeError): cf.read(tricky, encoding='ascii') @@ -1454,7 +1454,7 @@ def fromstring(self, string, defaults=None): class FakeFile: def __init__(self): - file_path = support.findfile("cfgparser.1") + file_path = support.findfile("cfgparser.1", subdir="configdata") with open(file_path, encoding="utf-8") as f: self.lines = f.readlines() self.lines.reverse() @@ -1475,7 +1475,7 @@ def readline_generator(f): class ReadFileTestCase(unittest.TestCase): def test_file(self): - file_paths = [support.findfile("cfgparser.1")] + file_paths = [support.findfile("cfgparser.1", subdir="configdata")] try: file_paths.append(file_paths[0].encode('utf8')) except UnicodeEncodeError: diff --git a/Lib/test/test_context.py b/Lib/test/test_context.py index b1aece4f5c9c49..255be306156c0b 100644 --- a/Lib/test/test_context.py +++ b/Lib/test/test_context.py @@ -6,10 +6,11 @@ import time import unittest import weakref +from test import support from test.support import threading_helper try: - from _testcapi import hamt + from _testinternalcapi import hamt except ImportError: hamt = None @@ -431,7 +432,7 @@ class EqError(Exception): pass -@unittest.skipIf(hamt is None, '_testcapi lacks "hamt()" function') +@unittest.skipIf(hamt is None, '_testinternalcapi.hamt() not available') class HamtTest(unittest.TestCase): def test_hashkey_helper_1(self): @@ -570,6 +571,7 @@ def test_hamt_collision_3(self): self.assertEqual({k.name for k in h.keys()}, {'C', 'D', 'E'}) + @support.requires_resource('cpu') def test_hamt_stress(self): COLLECTION_SIZE = 7000 TEST_ITERS_EVERY = 647 diff --git a/Lib/test/test_contextlib.py b/Lib/test/test_contextlib.py index dbc7dfcc24bf07..36c3abca80f894 100644 --- a/Lib/test/test_contextlib.py +++ b/Lib/test/test_contextlib.py @@ -167,9 +167,46 @@ def whoo(): yield ctx = whoo() ctx.__enter__() - self.assertRaises( - RuntimeError, ctx.__exit__, TypeError, TypeError("foo"), None - ) + with self.assertRaises(RuntimeError): + ctx.__exit__(TypeError, TypeError("foo"), None) + if support.check_impl_detail(cpython=True): + # The "gen" attribute is an implementation detail. + self.assertFalse(ctx.gen.gi_suspended) + + def test_contextmanager_trap_no_yield(self): + @contextmanager + def whoo(): + if False: + yield + ctx = whoo() + with self.assertRaises(RuntimeError): + ctx.__enter__() + + def test_contextmanager_trap_second_yield(self): + @contextmanager + def whoo(): + yield + yield + ctx = whoo() + ctx.__enter__() + with self.assertRaises(RuntimeError): + ctx.__exit__(None, None, None) + if support.check_impl_detail(cpython=True): + # The "gen" attribute is an implementation detail. + self.assertFalse(ctx.gen.gi_suspended) + + def test_contextmanager_non_normalised(self): + @contextmanager + def whoo(): + try: + yield + except RuntimeError: + raise SyntaxError + + ctx = whoo() + ctx.__enter__() + with self.assertRaises(SyntaxError): + ctx.__exit__(RuntimeError, None, None) def test_contextmanager_except(self): state = [] @@ -250,6 +287,25 @@ def test_issue29692(): self.assertEqual(ex.args[0], 'issue29692:Unchained') self.assertIsNone(ex.__cause__) + def test_contextmanager_wrap_runtimeerror(self): + @contextmanager + def woohoo(): + try: + yield + except Exception as exc: + raise RuntimeError(f'caught {exc}') from exc + + with self.assertRaises(RuntimeError): + with woohoo(): + 1 / 0 + + # If the context manager wrapped StopIteration in a RuntimeError, + # we also unwrap it, because we can't tell whether the wrapping was + # done by the generator machinery or by the generator itself. + with self.assertRaises(StopIteration): + with woohoo(): + raise StopIteration + def _create_contextmanager_attribs(self): def attribs(**kw): def decorate(func): @@ -261,6 +317,7 @@ def decorate(func): @attribs(foo='bar') def baz(spam): """Whee!""" + yield return baz def test_contextmanager_attribs(self): @@ -317,8 +374,11 @@ def woohoo(a, *, b): def test_recursive(self): depth = 0 + ncols = 0 @contextmanager def woohoo(): + nonlocal ncols + ncols += 1 nonlocal depth before = depth depth += 1 @@ -332,6 +392,7 @@ def recursive(): recursive() recursive() + self.assertEqual(ncols, 10) self.assertEqual(depth, 0) @@ -1236,6 +1297,24 @@ def test_exception_groups(self): [KeyError("ke1"), KeyError("ke2")], ), ) + # Check handling of BaseExceptionGroup, using GeneratorExit so that + # we don't accidentally discard a ctrl-c with KeyboardInterrupt. + with suppress(GeneratorExit): + raise BaseExceptionGroup("message", [GeneratorExit()]) + # If we raise a BaseException group, we can still suppress parts + with self.assertRaises(BaseExceptionGroup) as eg1: + with suppress(KeyError): + raise BaseExceptionGroup("message", [GeneratorExit("g"), KeyError("k")]) + self.assertExceptionIsLike( + eg1.exception, BaseExceptionGroup("message", [GeneratorExit("g")]), + ) + # If we suppress all the leaf BaseExceptions, we get a non-base ExceptionGroup + with self.assertRaises(ExceptionGroup) as eg1: + with suppress(GeneratorExit): + raise BaseExceptionGroup("message", [GeneratorExit("g"), KeyError("k")]) + self.assertExceptionIsLike( + eg1.exception, ExceptionGroup("message", [KeyError("k")]), + ) class TestChdir(unittest.TestCase): @@ -1257,7 +1336,7 @@ def test_simple(self): def test_reentrant(self): old_cwd = os.getcwd() target1 = self.make_relative_path('data') - target2 = self.make_relative_path('ziptestdata') + target2 = self.make_relative_path('archivetestdata') self.assertNotIn(old_cwd, (target1, target2)) chdir1, chdir2 = chdir(target1), chdir(target2) diff --git a/Lib/test/test_contextlib_async.py b/Lib/test/test_contextlib_async.py index fa89c23f8edd91..ca7315783b9674 100644 --- a/Lib/test/test_contextlib_async.py +++ b/Lib/test/test_contextlib_async.py @@ -2,7 +2,6 @@ from contextlib import ( asynccontextmanager, AbstractAsyncContextManager, AsyncExitStack, nullcontext, aclosing, contextmanager) -import functools from test import support import unittest import traceback @@ -11,21 +10,12 @@ support.requires_working_socket(module=True) -def _async_test(func): - """Decorator to turn an async function into a test case.""" - @functools.wraps(func) - def wrapper(*args, **kwargs): - coro = func(*args, **kwargs) - asyncio.run(coro) - return wrapper - def tearDownModule(): asyncio.set_event_loop_policy(None) -class TestAbstractAsyncContextManager(unittest.TestCase): +class TestAbstractAsyncContextManager(unittest.IsolatedAsyncioTestCase): - @_async_test async def test_enter(self): class DefaultEnter(AbstractAsyncContextManager): async def __aexit__(self, *args): @@ -37,7 +27,6 @@ async def __aexit__(self, *args): async with manager as context: self.assertIs(manager, context) - @_async_test async def test_slots(self): class DefaultAsyncContextManager(AbstractAsyncContextManager): __slots__ = () @@ -49,7 +38,6 @@ async def __aexit__(self, *args): manager = DefaultAsyncContextManager() manager.var = 42 - @_async_test async def test_async_gen_propagates_generator_exit(self): # A regression test for https://bugs.python.org/issue33786. @@ -61,15 +49,11 @@ async def gen(): async with ctx(): yield 11 - ret = [] - exc = ValueError(22) - with self.assertRaises(ValueError): - async with ctx(): - async for val in gen(): - ret.append(val) - raise exc - - self.assertEqual(ret, [11]) + g = gen() + async for val in g: + self.assertEqual(val, 11) + break + await g.aclose() def test_exit_is_abstract(self): class MissingAexit(AbstractAsyncContextManager): @@ -104,9 +88,8 @@ class NoneAexit(ManagerFromScratch): self.assertFalse(issubclass(NoneAexit, AbstractAsyncContextManager)) -class AsyncContextManagerTestCase(unittest.TestCase): +class AsyncContextManagerTestCase(unittest.IsolatedAsyncioTestCase): - @_async_test async def test_contextmanager_plain(self): state = [] @asynccontextmanager @@ -120,7 +103,6 @@ async def woohoo(): state.append(x) self.assertEqual(state, [1, 42, 999]) - @_async_test async def test_contextmanager_finally(self): state = [] @asynccontextmanager @@ -138,7 +120,6 @@ async def woohoo(): raise ZeroDivisionError() self.assertEqual(state, [1, 42, 999]) - @_async_test async def test_contextmanager_traceback(self): @asynccontextmanager async def f(): @@ -194,7 +175,6 @@ class StopAsyncIterationSubclass(StopAsyncIteration): self.assertEqual(frames[0].name, 'test_contextmanager_traceback') self.assertEqual(frames[0].line, 'raise stop_exc') - @_async_test async def test_contextmanager_no_reraise(self): @asynccontextmanager async def whee(): @@ -204,7 +184,6 @@ async def whee(): # Calling __aexit__ should not result in an exception self.assertFalse(await ctx.__aexit__(TypeError, TypeError("foo"), None)) - @_async_test async def test_contextmanager_trap_yield_after_throw(self): @asynccontextmanager async def whoo(): @@ -216,8 +195,10 @@ async def whoo(): await ctx.__aenter__() with self.assertRaises(RuntimeError): await ctx.__aexit__(TypeError, TypeError('foo'), None) + if support.check_impl_detail(cpython=True): + # The "gen" attribute is an implementation detail. + self.assertFalse(ctx.gen.ag_suspended) - @_async_test async def test_contextmanager_trap_no_yield(self): @asynccontextmanager async def whoo(): @@ -227,7 +208,6 @@ async def whoo(): with self.assertRaises(RuntimeError): await ctx.__aenter__() - @_async_test async def test_contextmanager_trap_second_yield(self): @asynccontextmanager async def whoo(): @@ -237,8 +217,10 @@ async def whoo(): await ctx.__aenter__() with self.assertRaises(RuntimeError): await ctx.__aexit__(None, None, None) + if support.check_impl_detail(cpython=True): + # The "gen" attribute is an implementation detail. + self.assertFalse(ctx.gen.ag_suspended) - @_async_test async def test_contextmanager_non_normalised(self): @asynccontextmanager async def whoo(): @@ -252,7 +234,6 @@ async def whoo(): with self.assertRaises(SyntaxError): await ctx.__aexit__(RuntimeError, None, None) - @_async_test async def test_contextmanager_except(self): state = [] @asynccontextmanager @@ -270,7 +251,6 @@ async def woohoo(): raise ZeroDivisionError(999) self.assertEqual(state, [1, 42, 999]) - @_async_test async def test_contextmanager_except_stopiter(self): @asynccontextmanager async def woohoo(): @@ -297,7 +277,6 @@ class StopAsyncIterationSubclass(StopAsyncIteration): else: self.fail(f'{stop_exc} was suppressed') - @_async_test async def test_contextmanager_wrap_runtimeerror(self): @asynccontextmanager async def woohoo(): @@ -342,14 +321,12 @@ def test_contextmanager_doc_attrib(self): self.assertEqual(baz.__doc__, "Whee!") @support.requires_docstrings - @_async_test async def test_instance_docstring_given_cm_docstring(self): baz = self._create_contextmanager_attribs()(None) self.assertEqual(baz.__doc__, "Whee!") async with baz: pass # suppress warning - @_async_test async def test_keywords(self): # Ensure no keyword arguments are inhibited @asynccontextmanager @@ -358,7 +335,6 @@ async def woohoo(self, func, args, kwds): async with woohoo(self=11, func=22, args=33, kwds=44) as target: self.assertEqual(target, (11, 22, 33, 44)) - @_async_test async def test_recursive(self): depth = 0 ncols = 0 @@ -385,7 +361,6 @@ async def recursive(): self.assertEqual(ncols, 10) self.assertEqual(depth, 0) - @_async_test async def test_decorator(self): entered = False @@ -404,7 +379,6 @@ async def test(): await test() self.assertFalse(entered) - @_async_test async def test_decorator_with_exception(self): entered = False @@ -427,7 +401,6 @@ async def test(): await test() self.assertFalse(entered) - @_async_test async def test_decorating_method(self): @asynccontextmanager @@ -462,7 +435,7 @@ async def method(self, a, b, c=None): self.assertEqual(test.b, 2) -class AclosingTestCase(unittest.TestCase): +class AclosingTestCase(unittest.IsolatedAsyncioTestCase): @support.requires_docstrings def test_instance_docs(self): @@ -470,7 +443,6 @@ def test_instance_docs(self): obj = aclosing(None) self.assertEqual(obj.__doc__, cm_docstring) - @_async_test async def test_aclosing(self): state = [] class C: @@ -482,7 +454,6 @@ async def aclose(self): self.assertEqual(x, y) self.assertEqual(state, [1]) - @_async_test async def test_aclosing_error(self): state = [] class C: @@ -496,7 +467,6 @@ async def aclose(self): 1 / 0 self.assertEqual(state, [1]) - @_async_test async def test_aclosing_bpo41229(self): state = [] @@ -522,7 +492,7 @@ async def agenfunc(): self.assertEqual(state, [1]) -class TestAsyncExitStack(TestBaseExitStack, unittest.TestCase): +class TestAsyncExitStack(TestBaseExitStack, unittest.IsolatedAsyncioTestCase): class SyncAsyncExitStack(AsyncExitStack): @staticmethod def run_coroutine(coro): @@ -561,13 +531,6 @@ def __exit__(self, *exc_details): ('__aexit__', 'cb_suppress = cb(*exc_details)'), ] - def setUp(self): - self.loop = asyncio.new_event_loop() - asyncio.set_event_loop(self.loop) - self.addCleanup(self.loop.close) - self.addCleanup(asyncio.set_event_loop_policy, None) - - @_async_test async def test_async_callback(self): expected = [ ((), {}), @@ -610,7 +573,6 @@ async def _exit(*args, **kwds): stack.push_async_callback(callback=_exit, arg=3) self.assertEqual(result, []) - @_async_test async def test_async_push(self): exc_raised = ZeroDivisionError async def _expect_exc(exc_type, exc, exc_tb): @@ -646,7 +608,6 @@ async def __aexit__(self, *exc_details): self.assertIs(stack._exit_callbacks[-1][1], _expect_exc) 1/0 - @_async_test async def test_enter_async_context(self): class TestCM(object): async def __aenter__(self): @@ -668,7 +629,6 @@ async def _exit(): self.assertEqual(result, [1, 2, 3, 4]) - @_async_test async def test_enter_async_context_errors(self): class LacksEnterAndExit: pass @@ -688,7 +648,6 @@ async def __aenter__(self): await stack.enter_async_context(LacksExit()) self.assertFalse(stack._exit_callbacks) - @_async_test async def test_async_exit_exception_chaining(self): # Ensure exception chaining matches the reference behaviour async def raise_exc(exc): @@ -720,7 +679,6 @@ async def suppress_exc(*exc_details): self.assertIsInstance(inner_exc, ValueError) self.assertIsInstance(inner_exc.__context__, ZeroDivisionError) - @_async_test async def test_async_exit_exception_explicit_none_context(self): # Ensure AsyncExitStack chaining matches actual nested `with` statements # regarding explicit __context__ = None. @@ -755,7 +713,6 @@ async def my_cm_with_exit_stack(): else: self.fail("Expected IndexError, but no exception was raised") - @_async_test async def test_instance_bypass_async(self): class Example(object): pass cm = Example() @@ -768,8 +725,7 @@ class Example(object): pass self.assertIs(stack._exit_callbacks[-1][1], cm) -class TestAsyncNullcontext(unittest.TestCase): - @_async_test +class TestAsyncNullcontext(unittest.IsolatedAsyncioTestCase): async def test_async_nullcontext(self): class C: pass diff --git a/Lib/test/test_copy.py b/Lib/test/test_copy.py index 826e46824e004c..89102373759ca0 100644 --- a/Lib/test/test_copy.py +++ b/Lib/test/test_copy.py @@ -4,7 +4,7 @@ import copyreg import weakref import abc -from operator import le, lt, ge, gt, eq, ne +from operator import le, lt, ge, gt, eq, ne, attrgetter import unittest from test import support @@ -899,7 +899,81 @@ def m(self): g.b() +class TestReplace(unittest.TestCase): + + def test_unsupported(self): + self.assertRaises(TypeError, copy.replace, 1) + self.assertRaises(TypeError, copy.replace, []) + self.assertRaises(TypeError, copy.replace, {}) + def f(): pass + self.assertRaises(TypeError, copy.replace, f) + class A: pass + self.assertRaises(TypeError, copy.replace, A) + self.assertRaises(TypeError, copy.replace, A()) + + def test_replace_method(self): + class A: + def __new__(cls, x, y=0): + self = object.__new__(cls) + self.x = x + self.y = y + return self + + def __init__(self, *args, **kwargs): + self.z = self.x + self.y + + def __replace__(self, **changes): + x = changes.get('x', self.x) + y = changes.get('y', self.y) + return type(self)(x, y) + + attrs = attrgetter('x', 'y', 'z') + a = A(11, 22) + self.assertEqual(attrs(copy.replace(a)), (11, 22, 33)) + self.assertEqual(attrs(copy.replace(a, x=1)), (1, 22, 23)) + self.assertEqual(attrs(copy.replace(a, y=2)), (11, 2, 13)) + self.assertEqual(attrs(copy.replace(a, x=1, y=2)), (1, 2, 3)) + + def test_namedtuple(self): + from collections import namedtuple + from typing import NamedTuple + PointFromCall = namedtuple('Point', 'x y', defaults=(0,)) + class PointFromInheritance(PointFromCall): + pass + class PointFromClass(NamedTuple): + x: int + y: int = 0 + for Point in (PointFromCall, PointFromInheritance, PointFromClass): + with self.subTest(Point=Point): + p = Point(11, 22) + self.assertIsInstance(p, Point) + self.assertEqual(copy.replace(p), (11, 22)) + self.assertIsInstance(copy.replace(p), Point) + self.assertEqual(copy.replace(p, x=1), (1, 22)) + self.assertEqual(copy.replace(p, y=2), (11, 2)) + self.assertEqual(copy.replace(p, x=1, y=2), (1, 2)) + with self.assertRaisesRegex(TypeError, 'unexpected field name'): + copy.replace(p, x=1, error=2) + + def test_dataclass(self): + from dataclasses import dataclass + @dataclass + class C: + x: int + y: int = 0 + + attrs = attrgetter('x', 'y') + c = C(11, 22) + self.assertEqual(attrs(copy.replace(c)), (11, 22)) + self.assertEqual(attrs(copy.replace(c, x=1)), (1, 22)) + self.assertEqual(attrs(copy.replace(c, y=2)), (11, 2)) + self.assertEqual(attrs(copy.replace(c, x=1, y=2)), (1, 2)) + with self.assertRaisesRegex(TypeError, 'unexpected keyword argument'): + copy.replace(c, x=1, error=2) + + def global_foo(x, y): return x+y + if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_coroutines.py b/Lib/test/test_coroutines.py index 47145782c0f04f..d848bfbd46c83b 100644 --- a/Lib/test/test_coroutines.py +++ b/Lib/test/test_coroutines.py @@ -953,11 +953,12 @@ async def b(): def test_corotype_1(self): ct = types.CoroutineType - self.assertIn('into coroutine', ct.send.__doc__) - self.assertIn('inside coroutine', ct.close.__doc__) - self.assertIn('in coroutine', ct.throw.__doc__) - self.assertIn('of the coroutine', ct.__dict__['__name__'].__doc__) - self.assertIn('of the coroutine', ct.__dict__['__qualname__'].__doc__) + if not support.MISSING_C_DOCSTRINGS: + self.assertIn('into coroutine', ct.send.__doc__) + self.assertIn('inside coroutine', ct.close.__doc__) + self.assertIn('in coroutine', ct.throw.__doc__) + self.assertIn('of the coroutine', ct.__dict__['__name__'].__doc__) + self.assertIn('of the coroutine', ct.__dict__['__qualname__'].__doc__) self.assertEqual(ct.__name__, 'coroutine') async def f(): pass @@ -2216,6 +2217,14 @@ async def f(): gen.cr_frame.clear() gen.close() + def test_cr_frame_after_close(self): + async def f(): + pass + gen = f() + self.assertIsNotNone(gen.cr_frame) + gen.close() + self.assertIsNone(gen.cr_frame) + def test_stack_in_coroutine_throw(self): # Regression test for https://github.com/python/cpython/issues/93592 async def a(): diff --git a/Lib/test/test_cppext.py b/Lib/test/test_cppext.py deleted file mode 100644 index 7a143f44640137..00000000000000 --- a/Lib/test/test_cppext.py +++ /dev/null @@ -1,88 +0,0 @@ -# gh-91321: Build a basic C++ test extension to check that the Python C API is -# compatible with C++ and does not emit C++ compiler warnings. -import os.path -import shutil -import sys -import unittest -import subprocess -import sysconfig -from test import support - - -MS_WINDOWS = (sys.platform == 'win32') - - -SETUP_TESTCPPEXT = support.findfile('setup_testcppext.py') - - -@support.requires_subprocess() -class TestCPPExt(unittest.TestCase): - def test_build_cpp11(self): - self.check_build(False, '_testcpp11ext') - - def test_build_cpp03(self): - self.check_build(True, '_testcpp03ext') - - # With MSVC, the linker fails with: cannot open file 'python311.lib' - # https://github.com/python/cpython/pull/32175#issuecomment-1111175897 - @unittest.skipIf(MS_WINDOWS, 'test fails on Windows') - # Building and running an extension in clang sanitizing mode is not - # straightforward - @unittest.skipIf( - '-fsanitize' in (sysconfig.get_config_var('PY_CFLAGS') or ''), - 'test does not work with analyzing builds') - # the test uses venv+pip: skip if it's not available - @support.requires_venv_with_pip() - def check_build(self, std_cpp03, extension_name): - venv_dir = 'env' - with support.setup_venv_with_pip_setuptools_wheel(venv_dir) as python_exe: - self._check_build(std_cpp03, extension_name, python_exe) - - def _check_build(self, std_cpp03, extension_name, python_exe): - pkg_dir = 'pkg' - os.mkdir(pkg_dir) - shutil.copy(SETUP_TESTCPPEXT, os.path.join(pkg_dir, "setup.py")) - - def run_cmd(operation, cmd): - env = os.environ.copy() - env['CPYTHON_TEST_CPP_STD'] = 'c++03' if std_cpp03 else 'c++11' - env['CPYTHON_TEST_EXT_NAME'] = extension_name - if support.verbose: - print('Run:', ' '.join(cmd)) - subprocess.run(cmd, check=True, env=env) - else: - proc = subprocess.run(cmd, - env=env, - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, - text=True) - if proc.returncode: - print(proc.stdout, end='') - self.fail( - f"{operation} failed with exit code {proc.returncode}") - - # Build and install the C++ extension - cmd = [python_exe, '-X', 'dev', - '-m', 'pip', 'install', '--no-build-isolation', - os.path.abspath(pkg_dir)] - run_cmd('Install', cmd) - - # Do a reference run. Until we test that running python - # doesn't leak references (gh-94755), run it so one can manually check - # -X showrefcount results against this baseline. - cmd = [python_exe, - '-X', 'dev', - '-X', 'showrefcount', - '-c', 'pass'] - run_cmd('Reference run', cmd) - - # Import the C++ extension - cmd = [python_exe, - '-X', 'dev', - '-X', 'showrefcount', - '-c', f"import {extension_name}"] - run_cmd('Import', cmd) - - -if __name__ == "__main__": - unittest.main() diff --git a/Lib/test/test_cppext/__init__.py b/Lib/test/test_cppext/__init__.py new file mode 100644 index 00000000000000..c6039bd17b0662 --- /dev/null +++ b/Lib/test/test_cppext/__init__.py @@ -0,0 +1,92 @@ +# gh-91321: Build a basic C++ test extension to check that the Python C API is +# compatible with C++ and does not emit C++ compiler warnings. +import os.path +import shutil +import unittest +import subprocess +import sysconfig +from test import support + + +SOURCE = os.path.join(os.path.dirname(__file__), 'extension.cpp') +SETUP = os.path.join(os.path.dirname(__file__), 'setup.py') + + +# gh-110119: pip does not currently support 't' in the ABI flag use by +# --disable-gil builds. Once it does, we can remove this skip. +@unittest.skipIf(support.Py_GIL_DISABLED, + 'test does not work with --disable-gil') +@support.requires_subprocess() +class TestCPPExt(unittest.TestCase): + @support.requires_resource('cpu') + def test_build_cpp11(self): + self.check_build(False, '_testcpp11ext') + + @support.requires_resource('cpu') + def test_build_cpp03(self): + self.check_build(True, '_testcpp03ext') + + # With MSVC, the linker fails with: cannot open file 'python311.lib' + # https://github.com/python/cpython/pull/32175#issuecomment-1111175897 + @unittest.skipIf(support.MS_WINDOWS, 'test fails on Windows') + # Building and running an extension in clang sanitizing mode is not + # straightforward + @unittest.skipIf( + '-fsanitize' in (sysconfig.get_config_var('PY_CFLAGS') or ''), + 'test does not work with analyzing builds') + # the test uses venv+pip: skip if it's not available + @support.requires_venv_with_pip() + def check_build(self, std_cpp03, extension_name): + venv_dir = 'env' + with support.setup_venv_with_pip_setuptools_wheel(venv_dir) as python_exe: + self._check_build(std_cpp03, extension_name, python_exe) + + def _check_build(self, std_cpp03, extension_name, python_exe): + pkg_dir = 'pkg' + os.mkdir(pkg_dir) + shutil.copy(SETUP, os.path.join(pkg_dir, os.path.basename(SETUP))) + shutil.copy(SOURCE, os.path.join(pkg_dir, os.path.basename(SOURCE))) + + def run_cmd(operation, cmd): + env = os.environ.copy() + env['CPYTHON_TEST_CPP_STD'] = 'c++03' if std_cpp03 else 'c++11' + env['CPYTHON_TEST_EXT_NAME'] = extension_name + if support.verbose: + print('Run:', ' '.join(cmd)) + subprocess.run(cmd, check=True, env=env) + else: + proc = subprocess.run(cmd, + env=env, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + text=True) + if proc.returncode: + print(proc.stdout, end='') + self.fail( + f"{operation} failed with exit code {proc.returncode}") + + # Build and install the C++ extension + cmd = [python_exe, '-X', 'dev', + '-m', 'pip', 'install', '--no-build-isolation', + os.path.abspath(pkg_dir)] + run_cmd('Install', cmd) + + # Do a reference run. Until we test that running python + # doesn't leak references (gh-94755), run it so one can manually check + # -X showrefcount results against this baseline. + cmd = [python_exe, + '-X', 'dev', + '-X', 'showrefcount', + '-c', 'pass'] + run_cmd('Reference run', cmd) + + # Import the C++ extension + cmd = [python_exe, + '-X', 'dev', + '-X', 'showrefcount', + '-c', f"import {extension_name}"] + run_cmd('Import', cmd) + + +if __name__ == "__main__": + unittest.main() diff --git a/Lib/test/test_cppext/extension.cpp b/Lib/test/test_cppext/extension.cpp new file mode 100644 index 00000000000000..90669b10cb2c6d --- /dev/null +++ b/Lib/test/test_cppext/extension.cpp @@ -0,0 +1,260 @@ +// gh-91321: Very basic C++ test extension to check that the Python C API is +// compatible with C++ and does not emit C++ compiler warnings. +// +// The code is only built, not executed. + +// Always enable assertions +#undef NDEBUG + +#include "Python.h" + +#if __cplusplus >= 201103 +# define NAME _testcpp11ext +#else +# define NAME _testcpp03ext +#endif + +#define _STR(NAME) #NAME +#define STR(NAME) _STR(NAME) + +PyDoc_STRVAR(_testcppext_add_doc, +"add(x, y)\n" +"\n" +"Return the sum of two integers: x + y."); + +static PyObject * +_testcppext_add(PyObject *Py_UNUSED(module), PyObject *args) +{ + long i, j; + if (!PyArg_ParseTuple(args, "ll:foo", &i, &j)) { + return _Py_NULL; + } + long res = i + j; + return PyLong_FromLong(res); +} + + +// Class to test operator casting an object to PyObject* +class StrongRef +{ +public: + StrongRef(PyObject *obj) : m_obj(obj) { + Py_INCREF(this->m_obj); + } + + ~StrongRef() { + Py_DECREF(this->m_obj); + } + + // Cast to PyObject*: get a borrowed reference + inline operator PyObject*() const { return this->m_obj; } + +private: + PyObject *m_obj; // Strong reference +}; + + +static PyObject * +test_api_casts(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args)) +{ + PyObject *obj = Py_BuildValue("(ii)", 1, 2); + if (obj == _Py_NULL) { + return _Py_NULL; + } + Py_ssize_t refcnt = Py_REFCNT(obj); + assert(refcnt >= 1); + + // gh-92138: For backward compatibility, functions of Python C API accepts + // "const PyObject*". Check that using it does not emit C++ compiler + // warnings. + const PyObject *const_obj = obj; + Py_INCREF(const_obj); + Py_DECREF(const_obj); + PyTypeObject *type = Py_TYPE(const_obj); + assert(Py_REFCNT(const_obj) == refcnt); + assert(type == &PyTuple_Type); + assert(PyTuple_GET_SIZE(const_obj) == 2); + PyObject *one = PyTuple_GET_ITEM(const_obj, 0); + assert(PyLong_AsLong(one) == 1); + + // gh-92898: StrongRef doesn't inherit from PyObject but has an operator to + // cast to PyObject*. + StrongRef strong_ref(obj); + assert(Py_TYPE(strong_ref) == &PyTuple_Type); + assert(Py_REFCNT(strong_ref) == (refcnt + 1)); + Py_INCREF(strong_ref); + Py_DECREF(strong_ref); + + // gh-93442: Pass 0 as NULL for PyObject* + Py_XINCREF(0); + Py_XDECREF(0); +#if __cplusplus >= 201103 + // Test nullptr passed as PyObject* + Py_XINCREF(nullptr); + Py_XDECREF(nullptr); +#endif + + Py_DECREF(obj); + Py_RETURN_NONE; +} + + +static PyObject * +test_unicode(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args)) +{ + PyObject *str = PyUnicode_FromString("abc"); + if (str == _Py_NULL) { + return _Py_NULL; + } + + assert(PyUnicode_Check(str)); + assert(PyUnicode_GET_LENGTH(str) == 3); + + // gh-92800: test PyUnicode_READ() + const void* data = PyUnicode_DATA(str); + assert(data != _Py_NULL); + int kind = PyUnicode_KIND(str); + assert(kind == PyUnicode_1BYTE_KIND); + assert(PyUnicode_READ(kind, data, 0) == 'a'); + + // gh-92800: test PyUnicode_READ() casts + const void* const_data = PyUnicode_DATA(str); + unsigned int ukind = static_cast(kind); + assert(PyUnicode_READ(ukind, const_data, 2) == 'c'); + + assert(PyUnicode_READ_CHAR(str, 1) == 'b'); + + Py_DECREF(str); + Py_RETURN_NONE; +} + +/* Test a `new`-allocated object with a virtual method. + * (https://github.com/python/cpython/issues/94731) */ + +class VirtualPyObject : public PyObject { +public: + VirtualPyObject(); + virtual ~VirtualPyObject() { + delete [] internal_data; + --instance_count; + } + virtual void set_internal_data() { + internal_data[0] = 1; + } + static void dealloc(PyObject* o) { + delete static_cast(o); + } + + // Number of "living" instances + static int instance_count; +private: + // buffer that can get corrupted + int* internal_data; +}; + +int VirtualPyObject::instance_count = 0; + +PyType_Slot VirtualPyObject_Slots[] = { + {Py_tp_free, (void*)VirtualPyObject::dealloc}, + {0, _Py_NULL}, +}; + +PyType_Spec VirtualPyObject_Spec = { + /* .name */ STR(NAME) ".VirtualPyObject", + /* .basicsize */ sizeof(VirtualPyObject), + /* .itemsize */ 0, + /* .flags */ Py_TPFLAGS_DEFAULT, + /* .slots */ VirtualPyObject_Slots, +}; + +VirtualPyObject::VirtualPyObject() { + // Create a temporary type (just so we don't need to store it) + PyObject *type = PyType_FromSpec(&VirtualPyObject_Spec); + // no good way to signal failure from a C++ constructor, so use assert + // for error handling + assert(type); + assert(PyObject_Init(this, (PyTypeObject *)type)); + Py_DECREF(type); + internal_data = new int[50]; + ++instance_count; +} + +static PyObject * +test_virtual_object(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args)) +{ + VirtualPyObject* obj = new VirtualPyObject(); + obj->set_internal_data(); + Py_DECREF(obj); + if (VirtualPyObject::instance_count != 0) { + return PyErr_Format( + PyExc_AssertionError, + "instance_count should be 0, got %d", + VirtualPyObject::instance_count); + } + Py_RETURN_NONE; +} + +static PyMethodDef _testcppext_methods[] = { + {"add", _testcppext_add, METH_VARARGS, _testcppext_add_doc}, + {"test_api_casts", test_api_casts, METH_NOARGS, _Py_NULL}, + {"test_unicode", test_unicode, METH_NOARGS, _Py_NULL}, + {"test_virtual_object", test_virtual_object, METH_NOARGS, _Py_NULL}, + // Note: _testcppext_exec currently runs all test functions directly. + // When adding a new one, add a call there. + + {_Py_NULL, _Py_NULL, 0, _Py_NULL} /* sentinel */ +}; + + +static int +_testcppext_exec(PyObject *module) +{ + if (PyModule_AddIntMacro(module, __cplusplus) < 0) { + return -1; + } + + PyObject *result; + + result = PyObject_CallMethod(module, "test_api_casts", ""); + if (!result) return -1; + Py_DECREF(result); + + result = PyObject_CallMethod(module, "test_unicode", ""); + if (!result) return -1; + Py_DECREF(result); + + result = PyObject_CallMethod(module, "test_virtual_object", ""); + if (!result) return -1; + Py_DECREF(result); + + return 0; +} + +static PyModuleDef_Slot _testcppext_slots[] = { + {Py_mod_exec, reinterpret_cast(_testcppext_exec)}, + {0, _Py_NULL} +}; + + +PyDoc_STRVAR(_testcppext_doc, "C++ test extension."); + +static struct PyModuleDef _testcppext_module = { + PyModuleDef_HEAD_INIT, // m_base + STR(NAME), // m_name + _testcppext_doc, // m_doc + 0, // m_size + _testcppext_methods, // m_methods + _testcppext_slots, // m_slots + _Py_NULL, // m_traverse + _Py_NULL, // m_clear + _Py_NULL, // m_free +}; + +#define _FUNC_NAME(NAME) PyInit_ ## NAME +#define FUNC_NAME(NAME) _FUNC_NAME(NAME) + +PyMODINIT_FUNC +FUNC_NAME(NAME)(void) +{ + return PyModuleDef_Init(&_testcppext_module); +} diff --git a/Lib/test/test_cppext/setup.py b/Lib/test/test_cppext/setup.py new file mode 100644 index 00000000000000..c7ba1efb4dd05a --- /dev/null +++ b/Lib/test/test_cppext/setup.py @@ -0,0 +1,53 @@ +# gh-91321: Build a basic C++ test extension to check that the Python C API is +# compatible with C++ and does not emit C++ compiler warnings. +import os +import shlex +import sys +import sysconfig +from test import support + +from setuptools import setup, Extension + + +SOURCE = 'extension.cpp' +if not support.MS_WINDOWS: + # C++ compiler flags for GCC and clang + CPPFLAGS = [ + # gh-91321: The purpose of _testcppext extension is to check that building + # a C++ extension using the Python C API does not emit C++ compiler + # warnings + '-Werror', + ] +else: + # Don't pass any compiler flag to MSVC + CPPFLAGS = [] + + +def main(): + cppflags = list(CPPFLAGS) + std = os.environ["CPYTHON_TEST_CPP_STD"] + name = os.environ["CPYTHON_TEST_EXT_NAME"] + + cppflags = [*CPPFLAGS, f'-std={std}'] + + # gh-105776: When "gcc -std=11" is used as the C++ compiler, -std=c11 + # option emits a C++ compiler warning. Remove "-std11" option from the + # CC command. + cmd = (sysconfig.get_config_var('CC') or '') + if cmd is not None: + cmd = shlex.split(cmd) + cmd = [arg for arg in cmd if not arg.startswith('-std=')] + cmd = shlex.join(cmd) + # CC env var overrides sysconfig CC variable in setuptools + os.environ['CC'] = cmd + + cpp_ext = Extension( + name, + sources=[SOURCE], + language='c++', + extra_compile_args=cppflags) + setup(name='internal' + name, version='0.0', ext_modules=[cpp_ext]) + + +if __name__ == "__main__": + main() diff --git a/Lib/test/test_cprofile.py b/Lib/test/test_cprofile.py index 3056fe84dac5dd..27e8a767903777 100644 --- a/Lib/test/test_cprofile.py +++ b/Lib/test/test_cprofile.py @@ -83,8 +83,8 @@ def test_throw(self): for func, (cc, nc, _, _, _) in pr.stats.items(): if func[2] == "": - self.assertEqual(cc, 2) - self.assertEqual(nc, 2) + self.assertEqual(cc, 1) + self.assertEqual(nc, 1) class TestCommandLine(unittest.TestCase): diff --git a/Lib/test/test_crashers.py b/Lib/test/test_crashers.py deleted file mode 100644 index 31b712028f8a12..00000000000000 --- a/Lib/test/test_crashers.py +++ /dev/null @@ -1,37 +0,0 @@ -# Tests that the crashers in the Lib/test/crashers directory actually -# do crash the interpreter as expected -# -# If a crasher is fixed, it should be moved elsewhere in the test suite to -# ensure it continues to work correctly. - -import unittest -import glob -import os.path -import test.support -from test.support.script_helper import assert_python_failure - -CRASHER_DIR = os.path.join(os.path.dirname(__file__), "crashers") -CRASHER_FILES = os.path.join(glob.escape(CRASHER_DIR), "*.py") - -infinite_loops = ["infinite_loop_re.py", "nasty_eq_vs_dict.py"] - -class CrasherTest(unittest.TestCase): - - @unittest.skip("these tests are too fragile") - @test.support.cpython_only - def test_crashers_crash(self): - for fname in glob.glob(CRASHER_FILES): - if os.path.basename(fname) in infinite_loops: - continue - # Some "crashers" only trigger an exception rather than a - # segfault. Consider that an acceptable outcome. - if test.support.verbose: - print("Checking crasher:", fname) - assert_python_failure(fname) - - -def tearDownModule(): - test.support.reap_children() - -if __name__ == "__main__": - unittest.main() diff --git a/Lib/test/test_csv.py b/Lib/test/test_csv.py index 6a4180e6d1b0a1..282cff4344b77f 100644 --- a/Lib/test/test_csv.py +++ b/Lib/test/test_csv.py @@ -10,7 +10,7 @@ import gc import pickle from test import support -from test.support import warnings_helper, import_helper, check_disallow_instantiation +from test.support import import_helper, check_disallow_instantiation from itertools import permutations from textwrap import dedent from collections import OrderedDict @@ -281,18 +281,6 @@ def test_writerows_errors(self): self.assertRaises(TypeError, writer.writerows, None) self.assertRaises(OSError, writer.writerows, BadIterable()) - @support.cpython_only - @support.requires_legacy_unicode_capi - @warnings_helper.ignore_warnings(category=DeprecationWarning) - def test_writerows_legacy_strings(self): - import _testcapi - c = _testcapi.unicode_legacy_string('a') - with TemporaryFile("w+", encoding="utf-8", newline='') as fileobj: - writer = csv.writer(fileobj) - writer.writerows([[c]]) - fileobj.seek(0) - self.assertEqual(fileobj.read(), "a\r\n") - def _read_test(self, input, expect, **kwargs): reader = csv.reader(input, **kwargs) result = list(reader) @@ -309,13 +297,18 @@ def test_read_oddinputs(self): [b'abc'], None) def test_read_eol(self): - self._read_test(['a,b'], [['a','b']]) - self._read_test(['a,b\n'], [['a','b']]) - self._read_test(['a,b\r\n'], [['a','b']]) - self._read_test(['a,b\r'], [['a','b']]) - self.assertRaises(csv.Error, self._read_test, ['a,b\rc,d'], []) - self.assertRaises(csv.Error, self._read_test, ['a,b\nc,d'], []) - self.assertRaises(csv.Error, self._read_test, ['a,b\r\nc,d'], []) + self._read_test(['a,b', 'c,d'], [['a','b'], ['c','d']]) + self._read_test(['a,b\n', 'c,d\n'], [['a','b'], ['c','d']]) + self._read_test(['a,b\r\n', 'c,d\r\n'], [['a','b'], ['c','d']]) + self._read_test(['a,b\r', 'c,d\r'], [['a','b'], ['c','d']]) + + errmsg = "with newline=''" + with self.assertRaisesRegex(csv.Error, errmsg): + next(csv.reader(['a,b\rc,d'])) + with self.assertRaisesRegex(csv.Error, errmsg): + next(csv.reader(['a,b\nc,d'])) + with self.assertRaisesRegex(csv.Error, errmsg): + next(csv.reader(['a,b\r\nc,d'])) def test_read_eof(self): self._read_test(['a,"'], [['a', '']]) diff --git a/Lib/test/test_ctypes/_support.py b/Lib/test/test_ctypes/_support.py new file mode 100644 index 00000000000000..e4c2b33825ae8f --- /dev/null +++ b/Lib/test/test_ctypes/_support.py @@ -0,0 +1,24 @@ +# Some classes and types are not export to _ctypes module directly. + +import ctypes +from _ctypes import Structure, Union, _Pointer, Array, _SimpleCData, CFuncPtr + + +_CData = Structure.__base__ +assert _CData.__name__ == "_CData" + +class _X(Structure): + _fields_ = [("x", ctypes.c_int)] +CField = type(_X.x) + +# metaclasses +PyCStructType = type(Structure) +UnionType = type(Union) +PyCPointerType = type(_Pointer) +PyCArrayType = type(Array) +PyCSimpleType = type(_SimpleCData) +PyCFuncPtrType = type(CFuncPtr) + +# type flags +Py_TPFLAGS_DISALLOW_INSTANTIATION = 1 << 7 +Py_TPFLAGS_IMMUTABLETYPE = 1 << 8 diff --git a/Lib/test/test_ctypes/test_arrays.py b/Lib/test/test_ctypes/test_arrays.py index f7a4b5df514e5b..774316e227ff73 100644 --- a/Lib/test/test_ctypes/test_arrays.py +++ b/Lib/test/test_ctypes/test_arrays.py @@ -7,6 +7,8 @@ c_char, c_wchar, c_byte, c_ubyte, c_short, c_ushort, c_int, c_uint, c_long, c_ulonglong, c_float, c_double, c_longdouble) from test.support import bigmemtest, _2G +from ._support import (_CData, PyCArrayType, Py_TPFLAGS_DISALLOW_INSTANTIATION, + Py_TPFLAGS_IMMUTABLETYPE) formats = "bBhHiIlLqQfd" @@ -23,6 +25,18 @@ def ARRAY(*args): class ArrayTestCase(unittest.TestCase): + def test_inheritance_hierarchy(self): + self.assertEqual(Array.mro(), [Array, _CData, object]) + + self.assertEqual(PyCArrayType.__name__, "PyCArrayType") + self.assertEqual(type(PyCArrayType), type) + + def test_type_flags(self): + for cls in Array, PyCArrayType: + with self.subTest(cls=cls): + self.assertTrue(cls.__flags__ & Py_TPFLAGS_IMMUTABLETYPE) + self.assertFalse(cls.__flags__ & Py_TPFLAGS_DISALLOW_INSTANTIATION) + def test_simple(self): # create classes holding simple numeric types, and check # various properties. @@ -189,10 +203,10 @@ def test_bad_subclass(self): class T(Array): pass with self.assertRaises(AttributeError): - class T(Array): + class T2(Array): _type_ = c_int with self.assertRaises(AttributeError): - class T(Array): + class T3(Array): _length_ = 13 def test_bad_length(self): @@ -201,15 +215,15 @@ class T(Array): _type_ = c_int _length_ = - sys.maxsize * 2 with self.assertRaises(ValueError): - class T(Array): + class T2(Array): _type_ = c_int _length_ = -1 with self.assertRaises(TypeError): - class T(Array): + class T3(Array): _type_ = c_int _length_ = 1.87 with self.assertRaises(OverflowError): - class T(Array): + class T4(Array): _type_ = c_int _length_ = sys.maxsize * 2 diff --git a/Lib/test/test_ctypes/test_callbacks.py b/Lib/test/test_ctypes/test_callbacks.py index 6fe3e119672409..19f4158c0ac846 100644 --- a/Lib/test/test_ctypes/test_callbacks.py +++ b/Lib/test/test_ctypes/test_callbacks.py @@ -322,9 +322,9 @@ def func(): self.assertIsInstance(cm.unraisable.exc_value, TypeError) self.assertEqual(cm.unraisable.err_msg, - "Exception ignored on converting result " - "of ctypes callback function") - self.assertIs(cm.unraisable.object, func) + f"Exception ignored on converting result " + f"of ctypes callback function {func!r}") + self.assertIsNone(cm.unraisable.object) if __name__ == '__main__': diff --git a/Lib/test/test_ctypes/test_funcptr.py b/Lib/test/test_ctypes/test_funcptr.py index 2ad40647e0cfbb..0eed39484fb39e 100644 --- a/Lib/test/test_ctypes/test_funcptr.py +++ b/Lib/test/test_ctypes/test_funcptr.py @@ -3,6 +3,8 @@ import unittest from ctypes import (CDLL, Structure, CFUNCTYPE, sizeof, _CFuncPtr, c_void_p, c_char_p, c_char, c_int, c_uint, c_long) +from ._support import (_CData, PyCFuncPtrType, Py_TPFLAGS_DISALLOW_INSTANTIATION, + Py_TPFLAGS_IMMUTABLETYPE) try: @@ -15,6 +17,18 @@ class CFuncPtrTestCase(unittest.TestCase): + def test_inheritance_hierarchy(self): + self.assertEqual(_CFuncPtr.mro(), [_CFuncPtr, _CData, object]) + + self.assertEqual(PyCFuncPtrType.__name__, "PyCFuncPtrType") + self.assertEqual(type(PyCFuncPtrType), type) + + def test_type_flags(self): + for cls in _CFuncPtr, PyCFuncPtrType: + with self.subTest(cls=cls): + self.assertTrue(_CFuncPtr.__flags__ & Py_TPFLAGS_IMMUTABLETYPE) + self.assertFalse(_CFuncPtr.__flags__ & Py_TPFLAGS_DISALLOW_INSTANTIATION) + def test_basic(self): X = WINFUNCTYPE(c_int, c_int, c_int) diff --git a/Lib/test/test_ctypes/test_functions.py b/Lib/test/test_ctypes/test_functions.py index 08eecbc9ea4442..04e8582ff1e427 100644 --- a/Lib/test/test_ctypes/test_functions.py +++ b/Lib/test/test_ctypes/test_functions.py @@ -46,15 +46,15 @@ class X(object, Array): _type_ = "i" with self.assertRaises(TypeError): - class X(object, _Pointer): + class X2(object, _Pointer): pass with self.assertRaises(TypeError): - class X(object, _SimpleCData): + class X3(object, _SimpleCData): _type_ = "i" with self.assertRaises(TypeError): - class X(object, Structure): + class X4(object, Structure): _fields_ = [] def test_c_char_parm(self): diff --git a/Lib/test/test_ctypes/test_keeprefs.py b/Lib/test/test_ctypes/test_keeprefs.py index c6fe1de62eae7c..23b03b64b4a716 100644 --- a/Lib/test/test_ctypes/test_keeprefs.py +++ b/Lib/test/test_ctypes/test_keeprefs.py @@ -98,33 +98,6 @@ def test_p_cint(self): x = pointer(i) self.assertEqual(x._objects, {'1': i}) - def test_pp_ownership(self): - d = c_int(123) - n = c_int(456) - - p = pointer(d) - pp = pointer(p) - - self.assertIs(pp._objects['1'], p) - self.assertIs(pp._objects['0']['1'], d) - - pp.contents.contents = n - - self.assertIs(pp._objects['1'], p) - self.assertIs(pp._objects['0']['1'], n) - - self.assertIs(p._objects['1'], n) - self.assertEqual(len(p._objects), 1) - - del d - del p - - self.assertIs(pp._objects['0']['1'], n) - self.assertEqual(len(pp._objects), 2) - - del n - - self.assertEqual(len(pp._objects), 2) class PointerToStructure(unittest.TestCase): def test(self): diff --git a/Lib/test/test_ctypes/test_objects.py b/Lib/test/test_ctypes/test_objects.py index 23c92b01a11107..fb01421b955951 100644 --- a/Lib/test/test_ctypes/test_objects.py +++ b/Lib/test/test_ctypes/test_objects.py @@ -55,14 +55,12 @@ import doctest import unittest -import test.test_ctypes.test_objects -class TestCase(unittest.TestCase): - def test(self): - failures, tests = doctest.testmod(test.test_ctypes.test_objects) - self.assertFalse(failures, 'doctests failed, see output above') +def load_tests(loader, tests, pattern): + tests.addTest(doctest.DocTestSuite()) + return tests if __name__ == '__main__': - doctest.testmod(test.test_ctypes.test_objects) + unittest.main() diff --git a/Lib/test/test_ctypes/test_pointers.py b/Lib/test/test_ctypes/test_pointers.py index 8410174358c19d..8cf2114c282cab 100644 --- a/Lib/test/test_ctypes/test_pointers.py +++ b/Lib/test/test_ctypes/test_pointers.py @@ -10,6 +10,8 @@ c_byte, c_ubyte, c_short, c_ushort, c_int, c_uint, c_long, c_ulong, c_longlong, c_ulonglong, c_float, c_double) +from ._support import (_CData, PyCPointerType, Py_TPFLAGS_DISALLOW_INSTANTIATION, + Py_TPFLAGS_IMMUTABLETYPE) ctype_types = [c_byte, c_ubyte, c_short, c_ushort, c_int, c_uint, @@ -19,6 +21,18 @@ class PointersTestCase(unittest.TestCase): + def test_inheritance_hierarchy(self): + self.assertEqual(_Pointer.mro(), [_Pointer, _CData, object]) + + self.assertEqual(PyCPointerType.__name__, "PyCPointerType") + self.assertEqual(type(PyCPointerType), type) + + def test_type_flags(self): + for cls in _Pointer, PyCPointerType: + with self.subTest(cls=cls): + self.assertTrue(_Pointer.__flags__ & Py_TPFLAGS_IMMUTABLETYPE) + self.assertFalse(_Pointer.__flags__ & Py_TPFLAGS_DISALLOW_INSTANTIATION) + def test_pointer_crash(self): class A(POINTER(c_ulong)): diff --git a/Lib/test/test_ctypes/test_random_things.py b/Lib/test/test_ctypes/test_random_things.py index 65eb53f86475d3..630f6ed9489eba 100644 --- a/Lib/test/test_ctypes/test_random_things.py +++ b/Lib/test/test_ctypes/test_random_things.py @@ -51,9 +51,9 @@ def expect_unraisable(self, exc_type, exc_msg=None): if exc_msg is not None: self.assertEqual(str(cm.unraisable.exc_value), exc_msg) self.assertEqual(cm.unraisable.err_msg, - "Exception ignored on calling ctypes " - "callback function") - self.assertIs(cm.unraisable.object, callback_func) + f"Exception ignored on calling ctypes " + f"callback function {callback_func!r}") + self.assertIsNone(cm.unraisable.object) def test_ValueError(self): cb = CFUNCTYPE(c_int, c_int)(callback_func) diff --git a/Lib/test/test_ctypes/test_simplesubclasses.py b/Lib/test/test_ctypes/test_simplesubclasses.py index 6072b62de5d53a..c96798e67f23f7 100644 --- a/Lib/test/test_ctypes/test_simplesubclasses.py +++ b/Lib/test/test_ctypes/test_simplesubclasses.py @@ -1,5 +1,7 @@ import unittest -from ctypes import Structure, CFUNCTYPE, c_int +from ctypes import Structure, CFUNCTYPE, c_int, _SimpleCData +from ._support import (_CData, PyCSimpleType, Py_TPFLAGS_DISALLOW_INSTANTIATION, + Py_TPFLAGS_IMMUTABLETYPE) class MyInt(c_int): @@ -10,6 +12,19 @@ def __eq__(self, other): class Test(unittest.TestCase): + def test_inheritance_hierarchy(self): + self.assertEqual(_SimpleCData.mro(), [_SimpleCData, _CData, object]) + + self.assertEqual(PyCSimpleType.__name__, "PyCSimpleType") + self.assertEqual(type(PyCSimpleType), type) + + self.assertEqual(c_int.mro(), [c_int, _SimpleCData, _CData, object]) + + def test_type_flags(self): + for cls in _SimpleCData, PyCSimpleType: + with self.subTest(cls=cls): + self.assertTrue(_SimpleCData.__flags__ & Py_TPFLAGS_IMMUTABLETYPE) + self.assertFalse(_SimpleCData.__flags__ & Py_TPFLAGS_DISALLOW_INSTANTIATION) def test_compare(self): self.assertEqual(MyInt(3), MyInt(3)) diff --git a/Lib/test/test_ctypes/test_struct_fields.py b/Lib/test/test_ctypes/test_struct_fields.py index f60dfe5b42ef65..f474a02fa8db06 100644 --- a/Lib/test/test_ctypes/test_struct_fields.py +++ b/Lib/test/test_ctypes/test_struct_fields.py @@ -1,5 +1,7 @@ import unittest from ctypes import Structure, Union, sizeof, c_char, c_int +from ._support import (CField, Py_TPFLAGS_DISALLOW_INSTANTIATION, + Py_TPFLAGS_IMMUTABLETYPE) class StructFieldsTestCase(unittest.TestCase): @@ -12,7 +14,6 @@ class StructFieldsTestCase(unittest.TestCase): # 4. The type is subclassed # # When they are finalized, assigning _fields_ is no longer allowed. - def test_1_A(self): class X(Structure): pass @@ -56,11 +57,15 @@ class X(Structure): self.assertEqual(bytes(x), b'a\x00###') def test_6(self): - class X(Structure): - _fields_ = [("x", c_int)] - CField = type(X.x) self.assertRaises(TypeError, CField) + def test_cfield_type_flags(self): + self.assertTrue(CField.__flags__ & Py_TPFLAGS_DISALLOW_INSTANTIATION) + self.assertTrue(CField.__flags__ & Py_TPFLAGS_IMMUTABLETYPE) + + def test_cfield_inheritance_hierarchy(self): + self.assertEqual(CField.mro(), [CField, object]) + def test_gh99275(self): class BrokenStructure(Structure): def __init_subclass__(cls, **kwargs): diff --git a/Lib/test/test_ctypes/test_structures.py b/Lib/test/test_ctypes/test_structures.py index f05ee5e491a41e..98bc4bdcac9306 100644 --- a/Lib/test/test_ctypes/test_structures.py +++ b/Lib/test/test_ctypes/test_structures.py @@ -1,14 +1,19 @@ import _ctypes_test +from platform import architecture as _architecture import struct import sys import unittest -from ctypes import (CDLL, Structure, Union, POINTER, sizeof, byref, alignment, +from ctypes import (CDLL, Array, Structure, Union, POINTER, sizeof, byref, alignment, c_void_p, c_char, c_wchar, c_byte, c_ubyte, c_uint8, c_uint16, c_uint32, c_short, c_ushort, c_int, c_uint, c_long, c_ulong, c_longlong, c_ulonglong, c_float, c_double) +from ctypes.util import find_library from struct import calcsize +from collections import namedtuple from test import support +from ._support import (_CData, PyCStructType, Py_TPFLAGS_DISALLOW_INSTANTIATION, + Py_TPFLAGS_IMMUTABLETYPE) class SubclassesTest(unittest.TestCase): @@ -67,6 +72,19 @@ class StructureTestCase(unittest.TestCase): "d": c_double, } + def test_inheritance_hierarchy(self): + self.assertEqual(Structure.mro(), [Structure, _CData, object]) + + self.assertEqual(PyCStructType.__name__, "PyCStructType") + self.assertEqual(type(PyCStructType), type) + + + def test_type_flags(self): + for cls in Structure, PyCStructType: + with self.subTest(cls=cls): + self.assertTrue(Structure.__flags__ & Py_TPFLAGS_IMMUTABLETYPE) + self.assertFalse(Structure.__flags__ & Py_TPFLAGS_DISALLOW_INSTANTIATION) + def test_simple_structs(self): for code, tp in self.formats.items(): class X(Structure): @@ -470,37 +488,116 @@ class X(Structure): self.assertEqual(s.first, got.first) self.assertEqual(s.second, got.second) + def _test_issue18060(self, Vector): + # The call to atan2() should succeed if the + # class fields were correctly cloned in the + # subclasses. Otherwise, it will segfault. + if sys.platform == 'win32': + libm = CDLL(find_library('msvcrt.dll')) + else: + libm = CDLL(find_library('m')) + + libm.atan2.argtypes = [Vector] + libm.atan2.restype = c_double + + arg = Vector(y=0.0, x=-1.0) + self.assertAlmostEqual(libm.atan2(arg), 3.141592653589793) + + @unittest.skipIf(_architecture() == ('64bit', 'WindowsPE'), "can't test Windows x64 build") + @unittest.skipUnless(sys.byteorder == 'little', "can't test on this platform") + def test_issue18060_a(self): + # This test case calls + # PyCStructUnionType_update_stgdict() for each + # _fields_ assignment, and PyCStgDict_clone() + # for the Mid and Vector class definitions. + class Base(Structure): + _fields_ = [('y', c_double), + ('x', c_double)] + class Mid(Base): + pass + Mid._fields_ = [] + class Vector(Mid): pass + self._test_issue18060(Vector) + + @unittest.skipIf(_architecture() == ('64bit', 'WindowsPE'), "can't test Windows x64 build") + @unittest.skipUnless(sys.byteorder == 'little', "can't test on this platform") + def test_issue18060_b(self): + # This test case calls + # PyCStructUnionType_update_stgdict() for each + # _fields_ assignment. + class Base(Structure): + _fields_ = [('y', c_double), + ('x', c_double)] + class Mid(Base): + _fields_ = [] + class Vector(Mid): + _fields_ = [] + self._test_issue18060(Vector) + + @unittest.skipIf(_architecture() == ('64bit', 'WindowsPE'), "can't test Windows x64 build") + @unittest.skipUnless(sys.byteorder == 'little', "can't test on this platform") + def test_issue18060_c(self): + # This test case calls + # PyCStructUnionType_update_stgdict() for each + # _fields_ assignment. + class Base(Structure): + _fields_ = [('y', c_double)] + class Mid(Base): + _fields_ = [] + class Vector(Mid): + _fields_ = [('x', c_double)] + self._test_issue18060(Vector) + def test_array_in_struct(self): # See bpo-22273 + # Load the shared library + dll = CDLL(_ctypes_test.__file__) + # These should mirror the structures in Modules/_ctypes/_ctypes_test.c class Test2(Structure): _fields_ = [ ('data', c_ubyte * 16), ] - class Test3(Structure): + class Test3AParent(Structure): + _fields_ = [ + ('data', c_float * 2), + ] + + class Test3A(Test3AParent): + _fields_ = [ + ('more_data', c_float * 2), + ] + + class Test3B(Structure): _fields_ = [ ('data', c_double * 2), ] - class Test3A(Structure): + class Test3C(Structure): _fields_ = [ - ('data', c_float * 2), + ("data", c_double * 4) ] - class Test3B(Test3A): + class Test3D(Structure): _fields_ = [ - ('more_data', c_float * 2), + ("data", c_double * 8) + ] + + class Test3E(Structure): + _fields_ = [ + ("data", c_double * 9) ] + + # Tests for struct Test2 s = Test2() expected = 0 for i in range(16): s.data[i] = i expected += i - dll = CDLL(_ctypes_test.__file__) - func = dll._testfunc_array_in_struct1 + func = dll._testfunc_array_in_struct2 func.restype = c_int func.argtypes = (Test2,) result = func(s) @@ -509,29 +606,16 @@ class Test3B(Test3A): for i in range(16): self.assertEqual(s.data[i], i) - s = Test3() - s.data[0] = 3.14159 - s.data[1] = 2.71828 - expected = 3.14159 + 2.71828 - func = dll._testfunc_array_in_struct2 - func.restype = c_double - func.argtypes = (Test3,) - result = func(s) - self.assertEqual(result, expected) - # check the passed-in struct hasn't changed - self.assertEqual(s.data[0], 3.14159) - self.assertEqual(s.data[1], 2.71828) - - s = Test3B() + # Tests for struct Test3A + s = Test3A() s.data[0] = 3.14159 s.data[1] = 2.71828 s.more_data[0] = -3.0 s.more_data[1] = -2.0 - - expected = 3.14159 + 2.71828 - 5.0 - func = dll._testfunc_array_in_struct2a + expected = 3.14159 + 2.71828 - 3.0 - 2.0 + func = dll._testfunc_array_in_struct3A func.restype = c_double - func.argtypes = (Test3B,) + func.argtypes = (Test3A,) result = func(s) self.assertAlmostEqual(result, expected, places=6) # check the passed-in struct hasn't changed @@ -540,6 +624,61 @@ class Test3B(Test3A): self.assertAlmostEqual(s.more_data[0], -3.0, places=6) self.assertAlmostEqual(s.more_data[1], -2.0, places=6) + # Test3B, Test3C, Test3D, Test3E have the same logic with different + # sizes hence putting them in a loop. + StructCtype = namedtuple( + "StructCtype", + ["cls", "cfunc1", "cfunc2", "items"] + ) + structs_to_test = [ + StructCtype( + Test3B, + dll._testfunc_array_in_struct3B, + dll._testfunc_array_in_struct3B_set_defaults, + 2), + StructCtype( + Test3C, + dll._testfunc_array_in_struct3C, + dll._testfunc_array_in_struct3C_set_defaults, + 4), + StructCtype( + Test3D, + dll._testfunc_array_in_struct3D, + dll._testfunc_array_in_struct3D_set_defaults, + 8), + StructCtype( + Test3E, + dll._testfunc_array_in_struct3E, + dll._testfunc_array_in_struct3E_set_defaults, + 9), + ] + + for sut in structs_to_test: + s = sut.cls() + + # Test for cfunc1 + expected = 0 + for i in range(sut.items): + float_i = float(i) + s.data[i] = float_i + expected += float_i + func = sut.cfunc1 + func.restype = c_double + func.argtypes = (sut.cls,) + result = func(s) + self.assertEqual(result, expected) + # check the passed-in struct hasn't changed + for i in range(sut.items): + self.assertEqual(s.data[i], float(i)) + + # Test for cfunc2 + func = sut.cfunc2 + func.restype = sut.cls + result = func() + # check if the default values have been set correctly + for i in range(sut.items): + self.assertEqual(result.data[i], float(i+1)) + def test_38368(self): class U(Union): _fields_ = [ diff --git a/Lib/test/test_ctypes/test_unions.py b/Lib/test/test_ctypes/test_unions.py new file mode 100644 index 00000000000000..cf5344bdf19165 --- /dev/null +++ b/Lib/test/test_ctypes/test_unions.py @@ -0,0 +1,18 @@ +import unittest +from ctypes import Union +from ._support import (_CData, UnionType, Py_TPFLAGS_DISALLOW_INSTANTIATION, + Py_TPFLAGS_IMMUTABLETYPE) + + +class ArrayTestCase(unittest.TestCase): + def test_inheritance_hierarchy(self): + self.assertEqual(Union.mro(), [Union, _CData, object]) + + self.assertEqual(UnionType.__name__, "UnionType") + self.assertEqual(type(UnionType), type) + + def test_type_flags(self): + for cls in Union, UnionType: + with self.subTest(cls=Union): + self.assertTrue(Union.__flags__ & Py_TPFLAGS_IMMUTABLETYPE) + self.assertFalse(Union.__flags__ & Py_TPFLAGS_DISALLOW_INSTANTIATION) diff --git a/Lib/test/test_ctypes/test_values.py b/Lib/test/test_ctypes/test_values.py index 9f8b69409cb880..d0b4803dff8529 100644 --- a/Lib/test/test_ctypes/test_values.py +++ b/Lib/test/test_ctypes/test_values.py @@ -58,7 +58,6 @@ class struct_frozen(Structure): ("code", POINTER(c_ubyte)), ("size", c_int), ("is_package", c_int), - ("get_code", POINTER(c_ubyte)), # Function ptr ] FrozenTable = POINTER(struct_frozen) diff --git a/Lib/test/test_ctypes/test_win32.py b/Lib/test/test_ctypes/test_win32.py index 01e624f76f0685..4aaecd8d38f98f 100644 --- a/Lib/test/test_ctypes/test_win32.py +++ b/Lib/test/test_ctypes/test_win32.py @@ -9,6 +9,7 @@ _pointer_type_cache, c_void_p, c_char, c_int, c_long) from test import support +from ._support import Py_TPFLAGS_DISALLOW_INSTANTIATION, Py_TPFLAGS_IMMUTABLETYPE @unittest.skipUnless(sys.platform == "win32", 'Windows-specific test') @@ -73,6 +74,11 @@ def test_COMError(self): self.assertEqual(ex.text, "text") self.assertEqual(ex.details, ("details",)) + self.assertEqual(COMError.mro(), + [COMError, Exception, BaseException, object]) + self.assertFalse(COMError.__flags__ & Py_TPFLAGS_DISALLOW_INSTANTIATION) + self.assertTrue(COMError.__flags__ & Py_TPFLAGS_IMMUTABLETYPE) + @unittest.skipUnless(sys.platform == "win32", 'Windows-specific test') class TestWinError(unittest.TestCase): diff --git a/Lib/test/test_curses.py b/Lib/test/test_curses.py index 31bc108e7712ea..83d10dd8579074 100644 --- a/Lib/test/test_curses.py +++ b/Lib/test/test_curses.py @@ -8,7 +8,7 @@ from unittest.mock import MagicMock from test.support import (requires, verbose, SaveSignals, cpython_only, - check_disallow_instantiation) + check_disallow_instantiation, MISSING_C_DOCSTRINGS) from test.support.import_helper import import_module # Optionally test curses module. This currently requires that the @@ -1142,6 +1142,8 @@ def test_encoding(self): with self.assertRaises(TypeError): del stdscr.encoding + @unittest.skipIf(MISSING_C_DOCSTRINGS, + "Signature information for builtins requires docstrings") def test_issue21088(self): stdscr = self.stdscr # diff --git a/Lib/test/test_dataclasses.py b/Lib/test/test_dataclasses.py deleted file mode 100644 index 6669f1c57e2e78..00000000000000 --- a/Lib/test/test_dataclasses.py +++ /dev/null @@ -1,4547 +0,0 @@ -# Deliberately use "from dataclasses import *". Every name in __all__ -# is tested, so they all must be present. This is a way to catch -# missing ones. - -from dataclasses import * - -import abc -import io -import pickle -import inspect -import builtins -import types -import weakref -import traceback -import unittest -from unittest.mock import Mock -from typing import ClassVar, Any, List, Union, Tuple, Dict, Generic, TypeVar, Optional, Protocol, DefaultDict -from typing import get_type_hints -from collections import deque, OrderedDict, namedtuple, defaultdict -from functools import total_ordering - -import typing # Needed for the string "typing.ClassVar[int]" to work as an annotation. -import dataclasses # Needed for the string "dataclasses.InitVar[int]" to work as an annotation. - -# Just any custom exception we can catch. -class CustomError(Exception): pass - -class TestCase(unittest.TestCase): - def test_no_fields(self): - @dataclass - class C: - pass - - o = C() - self.assertEqual(len(fields(C)), 0) - - def test_no_fields_but_member_variable(self): - @dataclass - class C: - i = 0 - - o = C() - self.assertEqual(len(fields(C)), 0) - - def test_one_field_no_default(self): - @dataclass - class C: - x: int - - o = C(42) - self.assertEqual(o.x, 42) - - def test_field_default_default_factory_error(self): - msg = "cannot specify both default and default_factory" - with self.assertRaisesRegex(ValueError, msg): - @dataclass - class C: - x: int = field(default=1, default_factory=int) - - def test_field_repr(self): - int_field = field(default=1, init=True, repr=False) - int_field.name = "id" - repr_output = repr(int_field) - expected_output = "Field(name='id',type=None," \ - f"default=1,default_factory={MISSING!r}," \ - "init=True,repr=False,hash=None," \ - "compare=True,metadata=mappingproxy({})," \ - f"kw_only={MISSING!r}," \ - "_field_type=None)" - - self.assertEqual(repr_output, expected_output) - - def test_field_recursive_repr(self): - rec_field = field() - rec_field.type = rec_field - rec_field.name = "id" - repr_output = repr(rec_field) - - self.assertIn(",type=...,", repr_output) - - def test_recursive_annotation(self): - class C: - pass - - @dataclass - class D: - C: C = field() - - self.assertIn(",type=...,", repr(D.__dataclass_fields__["C"])) - - def test_dataclass_params_repr(self): - # Even though this is testing an internal implementation detail, - # it's testing a feature we want to make sure is correctly implemented - # for the sake of dataclasses itself - @dataclass(slots=True, frozen=True) - class Some: pass - - repr_output = repr(Some.__dataclass_params__) - expected_output = "_DataclassParams(init=True,repr=True," \ - "eq=True,order=False,unsafe_hash=False,frozen=True," \ - "match_args=True,kw_only=False," \ - "slots=True,weakref_slot=False)" - self.assertEqual(repr_output, expected_output) - - def test_dataclass_params_signature(self): - # Even though this is testing an internal implementation detail, - # it's testing a feature we want to make sure is correctly implemented - # for the sake of dataclasses itself - @dataclass - class Some: pass - - for param in inspect.signature(dataclass).parameters: - if param == 'cls': - continue - self.assertTrue(hasattr(Some.__dataclass_params__, param), msg=param) - - def test_named_init_params(self): - @dataclass - class C: - x: int - - o = C(x=32) - self.assertEqual(o.x, 32) - - def test_two_fields_one_default(self): - @dataclass - class C: - x: int - y: int = 0 - - o = C(3) - self.assertEqual((o.x, o.y), (3, 0)) - - # Non-defaults following defaults. - with self.assertRaisesRegex(TypeError, - "non-default argument 'y' follows " - "default argument"): - @dataclass - class C: - x: int = 0 - y: int - - # A derived class adds a non-default field after a default one. - with self.assertRaisesRegex(TypeError, - "non-default argument 'y' follows " - "default argument"): - @dataclass - class B: - x: int = 0 - - @dataclass - class C(B): - y: int - - # Override a base class field and add a default to - # a field which didn't use to have a default. - with self.assertRaisesRegex(TypeError, - "non-default argument 'y' follows " - "default argument"): - @dataclass - class B: - x: int - y: int - - @dataclass - class C(B): - x: int = 0 - - def test_overwrite_hash(self): - # Test that declaring this class isn't an error. It should - # use the user-provided __hash__. - @dataclass(frozen=True) - class C: - x: int - def __hash__(self): - return 301 - self.assertEqual(hash(C(100)), 301) - - # Test that declaring this class isn't an error. It should - # use the generated __hash__. - @dataclass(frozen=True) - class C: - x: int - def __eq__(self, other): - return False - self.assertEqual(hash(C(100)), hash((100,))) - - # But this one should generate an exception, because with - # unsafe_hash=True, it's an error to have a __hash__ defined. - with self.assertRaisesRegex(TypeError, - 'Cannot overwrite attribute __hash__'): - @dataclass(unsafe_hash=True) - class C: - def __hash__(self): - pass - - # Creating this class should not generate an exception, - # because even though __hash__ exists before @dataclass is - # called, (due to __eq__ being defined), since it's None - # that's okay. - @dataclass(unsafe_hash=True) - class C: - x: int - def __eq__(self): - pass - # The generated hash function works as we'd expect. - self.assertEqual(hash(C(10)), hash((10,))) - - # Creating this class should generate an exception, because - # __hash__ exists and is not None, which it would be if it - # had been auto-generated due to __eq__ being defined. - with self.assertRaisesRegex(TypeError, - 'Cannot overwrite attribute __hash__'): - @dataclass(unsafe_hash=True) - class C: - x: int - def __eq__(self): - pass - def __hash__(self): - pass - - def test_overwrite_fields_in_derived_class(self): - # Note that x from C1 replaces x in Base, but the order remains - # the same as defined in Base. - @dataclass - class Base: - x: Any = 15.0 - y: int = 0 - - @dataclass - class C1(Base): - z: int = 10 - x: int = 15 - - o = Base() - self.assertEqual(repr(o), 'TestCase.test_overwrite_fields_in_derived_class..Base(x=15.0, y=0)') - - o = C1() - self.assertEqual(repr(o), 'TestCase.test_overwrite_fields_in_derived_class..C1(x=15, y=0, z=10)') - - o = C1(x=5) - self.assertEqual(repr(o), 'TestCase.test_overwrite_fields_in_derived_class..C1(x=5, y=0, z=10)') - - def test_field_named_self(self): - @dataclass - class C: - self: str - c=C('foo') - self.assertEqual(c.self, 'foo') - - # Make sure the first parameter is not named 'self'. - sig = inspect.signature(C.__init__) - first = next(iter(sig.parameters)) - self.assertNotEqual('self', first) - - # But we do use 'self' if no field named self. - @dataclass - class C: - selfx: str - - # Make sure the first parameter is named 'self'. - sig = inspect.signature(C.__init__) - first = next(iter(sig.parameters)) - self.assertEqual('self', first) - - def test_field_named_object(self): - @dataclass - class C: - object: str - c = C('foo') - self.assertEqual(c.object, 'foo') - - def test_field_named_object_frozen(self): - @dataclass(frozen=True) - class C: - object: str - c = C('foo') - self.assertEqual(c.object, 'foo') - - def test_field_named_BUILTINS_frozen(self): - # gh-96151 - @dataclass(frozen=True) - class C: - BUILTINS: int - c = C(5) - self.assertEqual(c.BUILTINS, 5) - - def test_field_with_special_single_underscore_names(self): - # gh-98886 - - @dataclass - class X: - x: int = field(default_factory=lambda: 111) - _dflt_x: int = field(default_factory=lambda: 222) - - X() - - @dataclass - class Y: - y: int = field(default_factory=lambda: 111) - _HAS_DEFAULT_FACTORY: int = 222 - - assert Y(y=222).y == 222 - - def test_field_named_like_builtin(self): - # Attribute names can shadow built-in names - # since code generation is used. - # Ensure that this is not happening. - exclusions = {'None', 'True', 'False'} - builtins_names = sorted( - b for b in builtins.__dict__.keys() - if not b.startswith('__') and b not in exclusions - ) - attributes = [(name, str) for name in builtins_names] - C = make_dataclass('C', attributes) - - c = C(*[name for name in builtins_names]) - - for name in builtins_names: - self.assertEqual(getattr(c, name), name) - - def test_field_named_like_builtin_frozen(self): - # Attribute names can shadow built-in names - # since code generation is used. - # Ensure that this is not happening - # for frozen data classes. - exclusions = {'None', 'True', 'False'} - builtins_names = sorted( - b for b in builtins.__dict__.keys() - if not b.startswith('__') and b not in exclusions - ) - attributes = [(name, str) for name in builtins_names] - C = make_dataclass('C', attributes, frozen=True) - - c = C(*[name for name in builtins_names]) - - for name in builtins_names: - self.assertEqual(getattr(c, name), name) - - def test_0_field_compare(self): - # Ensure that order=False is the default. - @dataclass - class C0: - pass - - @dataclass(order=False) - class C1: - pass - - for cls in [C0, C1]: - with self.subTest(cls=cls): - self.assertEqual(cls(), cls()) - for idx, fn in enumerate([lambda a, b: a < b, - lambda a, b: a <= b, - lambda a, b: a > b, - lambda a, b: a >= b]): - with self.subTest(idx=idx): - with self.assertRaisesRegex(TypeError, - f"not supported between instances of '{cls.__name__}' and '{cls.__name__}'"): - fn(cls(), cls()) - - @dataclass(order=True) - class C: - pass - self.assertLessEqual(C(), C()) - self.assertGreaterEqual(C(), C()) - - def test_1_field_compare(self): - # Ensure that order=False is the default. - @dataclass - class C0: - x: int - - @dataclass(order=False) - class C1: - x: int - - for cls in [C0, C1]: - with self.subTest(cls=cls): - self.assertEqual(cls(1), cls(1)) - self.assertNotEqual(cls(0), cls(1)) - for idx, fn in enumerate([lambda a, b: a < b, - lambda a, b: a <= b, - lambda a, b: a > b, - lambda a, b: a >= b]): - with self.subTest(idx=idx): - with self.assertRaisesRegex(TypeError, - f"not supported between instances of '{cls.__name__}' and '{cls.__name__}'"): - fn(cls(0), cls(0)) - - @dataclass(order=True) - class C: - x: int - self.assertLess(C(0), C(1)) - self.assertLessEqual(C(0), C(1)) - self.assertLessEqual(C(1), C(1)) - self.assertGreater(C(1), C(0)) - self.assertGreaterEqual(C(1), C(0)) - self.assertGreaterEqual(C(1), C(1)) - - def test_simple_compare(self): - # Ensure that order=False is the default. - @dataclass - class C0: - x: int - y: int - - @dataclass(order=False) - class C1: - x: int - y: int - - for cls in [C0, C1]: - with self.subTest(cls=cls): - self.assertEqual(cls(0, 0), cls(0, 0)) - self.assertEqual(cls(1, 2), cls(1, 2)) - self.assertNotEqual(cls(1, 0), cls(0, 0)) - self.assertNotEqual(cls(1, 0), cls(1, 1)) - for idx, fn in enumerate([lambda a, b: a < b, - lambda a, b: a <= b, - lambda a, b: a > b, - lambda a, b: a >= b]): - with self.subTest(idx=idx): - with self.assertRaisesRegex(TypeError, - f"not supported between instances of '{cls.__name__}' and '{cls.__name__}'"): - fn(cls(0, 0), cls(0, 0)) - - @dataclass(order=True) - class C: - x: int - y: int - - for idx, fn in enumerate([lambda a, b: a == b, - lambda a, b: a <= b, - lambda a, b: a >= b]): - with self.subTest(idx=idx): - self.assertTrue(fn(C(0, 0), C(0, 0))) - - for idx, fn in enumerate([lambda a, b: a < b, - lambda a, b: a <= b, - lambda a, b: a != b]): - with self.subTest(idx=idx): - self.assertTrue(fn(C(0, 0), C(0, 1))) - self.assertTrue(fn(C(0, 1), C(1, 0))) - self.assertTrue(fn(C(1, 0), C(1, 1))) - - for idx, fn in enumerate([lambda a, b: a > b, - lambda a, b: a >= b, - lambda a, b: a != b]): - with self.subTest(idx=idx): - self.assertTrue(fn(C(0, 1), C(0, 0))) - self.assertTrue(fn(C(1, 0), C(0, 1))) - self.assertTrue(fn(C(1, 1), C(1, 0))) - - def test_compare_subclasses(self): - # Comparisons fail for subclasses, even if no fields - # are added. - @dataclass - class B: - i: int - - @dataclass - class C(B): - pass - - for idx, (fn, expected) in enumerate([(lambda a, b: a == b, False), - (lambda a, b: a != b, True)]): - with self.subTest(idx=idx): - self.assertEqual(fn(B(0), C(0)), expected) - - for idx, fn in enumerate([lambda a, b: a < b, - lambda a, b: a <= b, - lambda a, b: a > b, - lambda a, b: a >= b]): - with self.subTest(idx=idx): - with self.assertRaisesRegex(TypeError, - "not supported between instances of 'B' and 'C'"): - fn(B(0), C(0)) - - def test_eq_order(self): - # Test combining eq and order. - for (eq, order, result ) in [ - (False, False, 'neither'), - (False, True, 'exception'), - (True, False, 'eq_only'), - (True, True, 'both'), - ]: - with self.subTest(eq=eq, order=order): - if result == 'exception': - with self.assertRaisesRegex(ValueError, 'eq must be true if order is true'): - @dataclass(eq=eq, order=order) - class C: - pass - else: - @dataclass(eq=eq, order=order) - class C: - pass - - if result == 'neither': - self.assertNotIn('__eq__', C.__dict__) - self.assertNotIn('__lt__', C.__dict__) - self.assertNotIn('__le__', C.__dict__) - self.assertNotIn('__gt__', C.__dict__) - self.assertNotIn('__ge__', C.__dict__) - elif result == 'both': - self.assertIn('__eq__', C.__dict__) - self.assertIn('__lt__', C.__dict__) - self.assertIn('__le__', C.__dict__) - self.assertIn('__gt__', C.__dict__) - self.assertIn('__ge__', C.__dict__) - elif result == 'eq_only': - self.assertIn('__eq__', C.__dict__) - self.assertNotIn('__lt__', C.__dict__) - self.assertNotIn('__le__', C.__dict__) - self.assertNotIn('__gt__', C.__dict__) - self.assertNotIn('__ge__', C.__dict__) - else: - assert False, f'unknown result {result!r}' - - def test_field_no_default(self): - @dataclass - class C: - x: int = field() - - self.assertEqual(C(5).x, 5) - - with self.assertRaisesRegex(TypeError, - r"__init__\(\) missing 1 required " - "positional argument: 'x'"): - C() - - def test_field_default(self): - default = object() - @dataclass - class C: - x: object = field(default=default) - - self.assertIs(C.x, default) - c = C(10) - self.assertEqual(c.x, 10) - - # If we delete the instance attribute, we should then see the - # class attribute. - del c.x - self.assertIs(c.x, default) - - self.assertIs(C().x, default) - - def test_not_in_repr(self): - @dataclass - class C: - x: int = field(repr=False) - with self.assertRaises(TypeError): - C() - c = C(10) - self.assertEqual(repr(c), 'TestCase.test_not_in_repr..C()') - - @dataclass - class C: - x: int = field(repr=False) - y: int - c = C(10, 20) - self.assertEqual(repr(c), 'TestCase.test_not_in_repr..C(y=20)') - - def test_not_in_compare(self): - @dataclass - class C: - x: int = 0 - y: int = field(compare=False, default=4) - - self.assertEqual(C(), C(0, 20)) - self.assertEqual(C(1, 10), C(1, 20)) - self.assertNotEqual(C(3), C(4, 10)) - self.assertNotEqual(C(3, 10), C(4, 10)) - - def test_no_unhashable_default(self): - # See bpo-44674. - class Unhashable: - __hash__ = None - - unhashable_re = 'mutable default .* for field a is not allowed' - with self.assertRaisesRegex(ValueError, unhashable_re): - @dataclass - class A: - a: dict = {} - - with self.assertRaisesRegex(ValueError, unhashable_re): - @dataclass - class A: - a: Any = Unhashable() - - # Make sure that the machinery looking for hashability is using the - # class's __hash__, not the instance's __hash__. - with self.assertRaisesRegex(ValueError, unhashable_re): - unhashable = Unhashable() - # This shouldn't make the variable hashable. - unhashable.__hash__ = lambda: 0 - @dataclass - class A: - a: Any = unhashable - - def test_hash_field_rules(self): - # Test all 6 cases of: - # hash=True/False/None - # compare=True/False - for (hash_, compare, result ) in [ - (True, False, 'field' ), - (True, True, 'field' ), - (False, False, 'absent'), - (False, True, 'absent'), - (None, False, 'absent'), - (None, True, 'field' ), - ]: - with self.subTest(hash=hash_, compare=compare): - @dataclass(unsafe_hash=True) - class C: - x: int = field(compare=compare, hash=hash_, default=5) - - if result == 'field': - # __hash__ contains the field. - self.assertEqual(hash(C(5)), hash((5,))) - elif result == 'absent': - # The field is not present in the hash. - self.assertEqual(hash(C(5)), hash(())) - else: - assert False, f'unknown result {result!r}' - - def test_init_false_no_default(self): - # If init=False and no default value, then the field won't be - # present in the instance. - @dataclass - class C: - x: int = field(init=False) - - self.assertNotIn('x', C().__dict__) - - @dataclass - class C: - x: int - y: int = 0 - z: int = field(init=False) - t: int = 10 - - self.assertNotIn('z', C(0).__dict__) - self.assertEqual(vars(C(5)), {'t': 10, 'x': 5, 'y': 0}) - - def test_class_marker(self): - @dataclass - class C: - x: int - y: str = field(init=False, default=None) - z: str = field(repr=False) - - the_fields = fields(C) - # the_fields is a tuple of 3 items, each value - # is in __annotations__. - self.assertIsInstance(the_fields, tuple) - for f in the_fields: - self.assertIs(type(f), Field) - self.assertIn(f.name, C.__annotations__) - - self.assertEqual(len(the_fields), 3) - - self.assertEqual(the_fields[0].name, 'x') - self.assertEqual(the_fields[0].type, int) - self.assertFalse(hasattr(C, 'x')) - self.assertTrue (the_fields[0].init) - self.assertTrue (the_fields[0].repr) - self.assertEqual(the_fields[1].name, 'y') - self.assertEqual(the_fields[1].type, str) - self.assertIsNone(getattr(C, 'y')) - self.assertFalse(the_fields[1].init) - self.assertTrue (the_fields[1].repr) - self.assertEqual(the_fields[2].name, 'z') - self.assertEqual(the_fields[2].type, str) - self.assertFalse(hasattr(C, 'z')) - self.assertTrue (the_fields[2].init) - self.assertFalse(the_fields[2].repr) - - def test_field_order(self): - @dataclass - class B: - a: str = 'B:a' - b: str = 'B:b' - c: str = 'B:c' - - @dataclass - class C(B): - b: str = 'C:b' - - self.assertEqual([(f.name, f.default) for f in fields(C)], - [('a', 'B:a'), - ('b', 'C:b'), - ('c', 'B:c')]) - - @dataclass - class D(B): - c: str = 'D:c' - - self.assertEqual([(f.name, f.default) for f in fields(D)], - [('a', 'B:a'), - ('b', 'B:b'), - ('c', 'D:c')]) - - @dataclass - class E(D): - a: str = 'E:a' - d: str = 'E:d' - - self.assertEqual([(f.name, f.default) for f in fields(E)], - [('a', 'E:a'), - ('b', 'B:b'), - ('c', 'D:c'), - ('d', 'E:d')]) - - def test_class_attrs(self): - # We only have a class attribute if a default value is - # specified, either directly or via a field with a default. - default = object() - @dataclass - class C: - x: int - y: int = field(repr=False) - z: object = default - t: int = field(default=100) - - self.assertFalse(hasattr(C, 'x')) - self.assertFalse(hasattr(C, 'y')) - self.assertIs (C.z, default) - self.assertEqual(C.t, 100) - - def test_disallowed_mutable_defaults(self): - # For the known types, don't allow mutable default values. - for typ, empty, non_empty in [(list, [], [1]), - (dict, {}, {0:1}), - (set, set(), set([1])), - ]: - with self.subTest(typ=typ): - # Can't use a zero-length value. - with self.assertRaisesRegex(ValueError, - f'mutable default {typ} for field ' - 'x is not allowed'): - @dataclass - class Point: - x: typ = empty - - - # Nor a non-zero-length value - with self.assertRaisesRegex(ValueError, - f'mutable default {typ} for field ' - 'y is not allowed'): - @dataclass - class Point: - y: typ = non_empty - - # Check subtypes also fail. - class Subclass(typ): pass - - with self.assertRaisesRegex(ValueError, - "mutable default .*Subclass'>" - " for field z is not allowed" - ): - @dataclass - class Point: - z: typ = Subclass() - - # Because this is a ClassVar, it can be mutable. - @dataclass - class C: - z: ClassVar[typ] = typ() - - # Because this is a ClassVar, it can be mutable. - @dataclass - class C: - x: ClassVar[typ] = Subclass() - - def test_deliberately_mutable_defaults(self): - # If a mutable default isn't in the known list of - # (list, dict, set), then it's okay. - class Mutable: - def __init__(self): - self.l = [] - - @dataclass - class C: - x: Mutable - - # These 2 instances will share this value of x. - lst = Mutable() - o1 = C(lst) - o2 = C(lst) - self.assertEqual(o1, o2) - o1.x.l.extend([1, 2]) - self.assertEqual(o1, o2) - self.assertEqual(o1.x.l, [1, 2]) - self.assertIs(o1.x, o2.x) - - def test_no_options(self): - # Call with dataclass(). - @dataclass() - class C: - x: int - - self.assertEqual(C(42).x, 42) - - def test_not_tuple(self): - # Make sure we can't be compared to a tuple. - @dataclass - class Point: - x: int - y: int - self.assertNotEqual(Point(1, 2), (1, 2)) - - # And that we can't compare to another unrelated dataclass. - @dataclass - class C: - x: int - y: int - self.assertNotEqual(Point(1, 3), C(1, 3)) - - def test_not_other_dataclass(self): - # Test that some of the problems with namedtuple don't happen - # here. - @dataclass - class Point3D: - x: int - y: int - z: int - - @dataclass - class Date: - year: int - month: int - day: int - - self.assertNotEqual(Point3D(2017, 6, 3), Date(2017, 6, 3)) - self.assertNotEqual(Point3D(1, 2, 3), (1, 2, 3)) - - # Make sure we can't unpack. - with self.assertRaisesRegex(TypeError, 'unpack'): - x, y, z = Point3D(4, 5, 6) - - # Make sure another class with the same field names isn't - # equal. - @dataclass - class Point3Dv1: - x: int = 0 - y: int = 0 - z: int = 0 - self.assertNotEqual(Point3D(0, 0, 0), Point3Dv1()) - - def test_function_annotations(self): - # Some dummy class and instance to use as a default. - class F: - pass - f = F() - - def validate_class(cls): - # First, check __annotations__, even though they're not - # function annotations. - self.assertEqual(cls.__annotations__['i'], int) - self.assertEqual(cls.__annotations__['j'], str) - self.assertEqual(cls.__annotations__['k'], F) - self.assertEqual(cls.__annotations__['l'], float) - self.assertEqual(cls.__annotations__['z'], complex) - - # Verify __init__. - - signature = inspect.signature(cls.__init__) - # Check the return type, should be None. - self.assertIs(signature.return_annotation, None) - - # Check each parameter. - params = iter(signature.parameters.values()) - param = next(params) - # This is testing an internal name, and probably shouldn't be tested. - self.assertEqual(param.name, 'self') - param = next(params) - self.assertEqual(param.name, 'i') - self.assertIs (param.annotation, int) - self.assertEqual(param.default, inspect.Parameter.empty) - self.assertEqual(param.kind, inspect.Parameter.POSITIONAL_OR_KEYWORD) - param = next(params) - self.assertEqual(param.name, 'j') - self.assertIs (param.annotation, str) - self.assertEqual(param.default, inspect.Parameter.empty) - self.assertEqual(param.kind, inspect.Parameter.POSITIONAL_OR_KEYWORD) - param = next(params) - self.assertEqual(param.name, 'k') - self.assertIs (param.annotation, F) - # Don't test for the default, since it's set to MISSING. - self.assertEqual(param.kind, inspect.Parameter.POSITIONAL_OR_KEYWORD) - param = next(params) - self.assertEqual(param.name, 'l') - self.assertIs (param.annotation, float) - # Don't test for the default, since it's set to MISSING. - self.assertEqual(param.kind, inspect.Parameter.POSITIONAL_OR_KEYWORD) - self.assertRaises(StopIteration, next, params) - - - @dataclass - class C: - i: int - j: str - k: F = f - l: float=field(default=None) - z: complex=field(default=3+4j, init=False) - - validate_class(C) - - # Now repeat with __hash__. - @dataclass(frozen=True, unsafe_hash=True) - class C: - i: int - j: str - k: F = f - l: float=field(default=None) - z: complex=field(default=3+4j, init=False) - - validate_class(C) - - def test_missing_default(self): - # Test that MISSING works the same as a default not being - # specified. - @dataclass - class C: - x: int=field(default=MISSING) - with self.assertRaisesRegex(TypeError, - r'__init__\(\) missing 1 required ' - 'positional argument'): - C() - self.assertNotIn('x', C.__dict__) - - @dataclass - class D: - x: int - with self.assertRaisesRegex(TypeError, - r'__init__\(\) missing 1 required ' - 'positional argument'): - D() - self.assertNotIn('x', D.__dict__) - - def test_missing_default_factory(self): - # Test that MISSING works the same as a default factory not - # being specified (which is really the same as a default not - # being specified, too). - @dataclass - class C: - x: int=field(default_factory=MISSING) - with self.assertRaisesRegex(TypeError, - r'__init__\(\) missing 1 required ' - 'positional argument'): - C() - self.assertNotIn('x', C.__dict__) - - @dataclass - class D: - x: int=field(default=MISSING, default_factory=MISSING) - with self.assertRaisesRegex(TypeError, - r'__init__\(\) missing 1 required ' - 'positional argument'): - D() - self.assertNotIn('x', D.__dict__) - - def test_missing_repr(self): - self.assertIn('MISSING_TYPE object', repr(MISSING)) - - def test_dont_include_other_annotations(self): - @dataclass - class C: - i: int - def foo(self) -> int: - return 4 - @property - def bar(self) -> int: - return 5 - self.assertEqual(list(C.__annotations__), ['i']) - self.assertEqual(C(10).foo(), 4) - self.assertEqual(C(10).bar, 5) - self.assertEqual(C(10).i, 10) - - def test_post_init(self): - # Just make sure it gets called - @dataclass - class C: - def __post_init__(self): - raise CustomError() - with self.assertRaises(CustomError): - C() - - @dataclass - class C: - i: int = 10 - def __post_init__(self): - if self.i == 10: - raise CustomError() - with self.assertRaises(CustomError): - C() - # post-init gets called, but doesn't raise. This is just - # checking that self is used correctly. - C(5) - - # If there's not an __init__, then post-init won't get called. - @dataclass(init=False) - class C: - def __post_init__(self): - raise CustomError() - # Creating the class won't raise - C() - - @dataclass - class C: - x: int = 0 - def __post_init__(self): - self.x *= 2 - self.assertEqual(C().x, 0) - self.assertEqual(C(2).x, 4) - - # Make sure that if we're frozen, post-init can't set - # attributes. - @dataclass(frozen=True) - class C: - x: int = 0 - def __post_init__(self): - self.x *= 2 - with self.assertRaises(FrozenInstanceError): - C() - - def test_post_init_super(self): - # Make sure super() post-init isn't called by default. - class B: - def __post_init__(self): - raise CustomError() - - @dataclass - class C(B): - def __post_init__(self): - self.x = 5 - - self.assertEqual(C().x, 5) - - # Now call super(), and it will raise. - @dataclass - class C(B): - def __post_init__(self): - super().__post_init__() - - with self.assertRaises(CustomError): - C() - - # Make sure post-init is called, even if not defined in our - # class. - @dataclass - class C(B): - pass - - with self.assertRaises(CustomError): - C() - - def test_post_init_staticmethod(self): - flag = False - @dataclass - class C: - x: int - y: int - @staticmethod - def __post_init__(): - nonlocal flag - flag = True - - self.assertFalse(flag) - c = C(3, 4) - self.assertEqual((c.x, c.y), (3, 4)) - self.assertTrue(flag) - - def test_post_init_classmethod(self): - @dataclass - class C: - flag = False - x: int - y: int - @classmethod - def __post_init__(cls): - cls.flag = True - - self.assertFalse(C.flag) - c = C(3, 4) - self.assertEqual((c.x, c.y), (3, 4)) - self.assertTrue(C.flag) - - def test_post_init_not_auto_added(self): - # See bpo-46757, which had proposed always adding __post_init__. As - # Raymond Hettinger pointed out, that would be a breaking change. So, - # add a test to make sure that the current behavior doesn't change. - - @dataclass - class A0: - pass - - @dataclass - class B0: - b_called: bool = False - def __post_init__(self): - self.b_called = True - - @dataclass - class C0(A0, B0): - c_called: bool = False - def __post_init__(self): - super().__post_init__() - self.c_called = True - - # Since A0 has no __post_init__, and one wasn't automatically added - # (because that's the rule: it's never added by @dataclass, it's only - # the class author that can add it), then B0.__post_init__ is called. - # Verify that. - c = C0() - self.assertTrue(c.b_called) - self.assertTrue(c.c_called) - - ###################################### - # Now, the same thing, except A1 defines __post_init__. - @dataclass - class A1: - def __post_init__(self): - pass - - @dataclass - class B1: - b_called: bool = False - def __post_init__(self): - self.b_called = True - - @dataclass - class C1(A1, B1): - c_called: bool = False - def __post_init__(self): - super().__post_init__() - self.c_called = True - - # This time, B1.__post_init__ isn't being called. This mimics what - # would happen if A1.__post_init__ had been automatically added, - # instead of manually added as we see here. This test isn't really - # needed, but I'm including it just to demonstrate the changed - # behavior when A1 does define __post_init__. - c = C1() - self.assertFalse(c.b_called) - self.assertTrue(c.c_called) - - def test_class_var(self): - # Make sure ClassVars are ignored in __init__, __repr__, etc. - @dataclass - class C: - x: int - y: int = 10 - z: ClassVar[int] = 1000 - w: ClassVar[int] = 2000 - t: ClassVar[int] = 3000 - s: ClassVar = 4000 - - c = C(5) - self.assertEqual(repr(c), 'TestCase.test_class_var..C(x=5, y=10)') - self.assertEqual(len(fields(C)), 2) # We have 2 fields. - self.assertEqual(len(C.__annotations__), 6) # And 4 ClassVars. - self.assertEqual(c.z, 1000) - self.assertEqual(c.w, 2000) - self.assertEqual(c.t, 3000) - self.assertEqual(c.s, 4000) - C.z += 1 - self.assertEqual(c.z, 1001) - c = C(20) - self.assertEqual((c.x, c.y), (20, 10)) - self.assertEqual(c.z, 1001) - self.assertEqual(c.w, 2000) - self.assertEqual(c.t, 3000) - self.assertEqual(c.s, 4000) - - def test_class_var_no_default(self): - # If a ClassVar has no default value, it should not be set on the class. - @dataclass - class C: - x: ClassVar[int] - - self.assertNotIn('x', C.__dict__) - - def test_class_var_default_factory(self): - # It makes no sense for a ClassVar to have a default factory. When - # would it be called? Call it yourself, since it's class-wide. - with self.assertRaisesRegex(TypeError, - 'cannot have a default factory'): - @dataclass - class C: - x: ClassVar[int] = field(default_factory=int) - - self.assertNotIn('x', C.__dict__) - - def test_class_var_with_default(self): - # If a ClassVar has a default value, it should be set on the class. - @dataclass - class C: - x: ClassVar[int] = 10 - self.assertEqual(C.x, 10) - - @dataclass - class C: - x: ClassVar[int] = field(default=10) - self.assertEqual(C.x, 10) - - def test_class_var_frozen(self): - # Make sure ClassVars work even if we're frozen. - @dataclass(frozen=True) - class C: - x: int - y: int = 10 - z: ClassVar[int] = 1000 - w: ClassVar[int] = 2000 - t: ClassVar[int] = 3000 - - c = C(5) - self.assertEqual(repr(C(5)), 'TestCase.test_class_var_frozen..C(x=5, y=10)') - self.assertEqual(len(fields(C)), 2) # We have 2 fields - self.assertEqual(len(C.__annotations__), 5) # And 3 ClassVars - self.assertEqual(c.z, 1000) - self.assertEqual(c.w, 2000) - self.assertEqual(c.t, 3000) - # We can still modify the ClassVar, it's only instances that are - # frozen. - C.z += 1 - self.assertEqual(c.z, 1001) - c = C(20) - self.assertEqual((c.x, c.y), (20, 10)) - self.assertEqual(c.z, 1001) - self.assertEqual(c.w, 2000) - self.assertEqual(c.t, 3000) - - def test_init_var_no_default(self): - # If an InitVar has no default value, it should not be set on the class. - @dataclass - class C: - x: InitVar[int] - - self.assertNotIn('x', C.__dict__) - - def test_init_var_default_factory(self): - # It makes no sense for an InitVar to have a default factory. When - # would it be called? Call it yourself, since it's class-wide. - with self.assertRaisesRegex(TypeError, - 'cannot have a default factory'): - @dataclass - class C: - x: InitVar[int] = field(default_factory=int) - - self.assertNotIn('x', C.__dict__) - - def test_init_var_with_default(self): - # If an InitVar has a default value, it should be set on the class. - @dataclass - class C: - x: InitVar[int] = 10 - self.assertEqual(C.x, 10) - - @dataclass - class C: - x: InitVar[int] = field(default=10) - self.assertEqual(C.x, 10) - - def test_init_var(self): - @dataclass - class C: - x: int = None - init_param: InitVar[int] = None - - def __post_init__(self, init_param): - if self.x is None: - self.x = init_param*2 - - c = C(init_param=10) - self.assertEqual(c.x, 20) - - def test_init_var_preserve_type(self): - self.assertEqual(InitVar[int].type, int) - - # Make sure the repr is correct. - self.assertEqual(repr(InitVar[int]), 'dataclasses.InitVar[int]') - self.assertEqual(repr(InitVar[List[int]]), - 'dataclasses.InitVar[typing.List[int]]') - self.assertEqual(repr(InitVar[list[int]]), - 'dataclasses.InitVar[list[int]]') - self.assertEqual(repr(InitVar[int|str]), - 'dataclasses.InitVar[int | str]') - - def test_init_var_inheritance(self): - # Note that this deliberately tests that a dataclass need not - # have a __post_init__ function if it has an InitVar field. - # It could just be used in a derived class, as shown here. - @dataclass - class Base: - x: int - init_base: InitVar[int] - - # We can instantiate by passing the InitVar, even though - # it's not used. - b = Base(0, 10) - self.assertEqual(vars(b), {'x': 0}) - - @dataclass - class C(Base): - y: int - init_derived: InitVar[int] - - def __post_init__(self, init_base, init_derived): - self.x = self.x + init_base - self.y = self.y + init_derived - - c = C(10, 11, 50, 51) - self.assertEqual(vars(c), {'x': 21, 'y': 101}) - - def test_default_factory(self): - # Test a factory that returns a new list. - @dataclass - class C: - x: int - y: list = field(default_factory=list) - - c0 = C(3) - c1 = C(3) - self.assertEqual(c0.x, 3) - self.assertEqual(c0.y, []) - self.assertEqual(c0, c1) - self.assertIsNot(c0.y, c1.y) - self.assertEqual(astuple(C(5, [1])), (5, [1])) - - # Test a factory that returns a shared list. - l = [] - @dataclass - class C: - x: int - y: list = field(default_factory=lambda: l) - - c0 = C(3) - c1 = C(3) - self.assertEqual(c0.x, 3) - self.assertEqual(c0.y, []) - self.assertEqual(c0, c1) - self.assertIs(c0.y, c1.y) - self.assertEqual(astuple(C(5, [1])), (5, [1])) - - # Test various other field flags. - # repr - @dataclass - class C: - x: list = field(default_factory=list, repr=False) - self.assertEqual(repr(C()), 'TestCase.test_default_factory..C()') - self.assertEqual(C().x, []) - - # hash - @dataclass(unsafe_hash=True) - class C: - x: list = field(default_factory=list, hash=False) - self.assertEqual(astuple(C()), ([],)) - self.assertEqual(hash(C()), hash(())) - - # init (see also test_default_factory_with_no_init) - @dataclass - class C: - x: list = field(default_factory=list, init=False) - self.assertEqual(astuple(C()), ([],)) - - # compare - @dataclass - class C: - x: list = field(default_factory=list, compare=False) - self.assertEqual(C(), C([1])) - - def test_default_factory_with_no_init(self): - # We need a factory with a side effect. - factory = Mock() - - @dataclass - class C: - x: list = field(default_factory=factory, init=False) - - # Make sure the default factory is called for each new instance. - C().x - self.assertEqual(factory.call_count, 1) - C().x - self.assertEqual(factory.call_count, 2) - - def test_default_factory_not_called_if_value_given(self): - # We need a factory that we can test if it's been called. - factory = Mock() - - @dataclass - class C: - x: int = field(default_factory=factory) - - # Make sure that if a field has a default factory function, - # it's not called if a value is specified. - C().x - self.assertEqual(factory.call_count, 1) - self.assertEqual(C(10).x, 10) - self.assertEqual(factory.call_count, 1) - C().x - self.assertEqual(factory.call_count, 2) - - def test_default_factory_derived(self): - # See bpo-32896. - @dataclass - class Foo: - x: dict = field(default_factory=dict) - - @dataclass - class Bar(Foo): - y: int = 1 - - self.assertEqual(Foo().x, {}) - self.assertEqual(Bar().x, {}) - self.assertEqual(Bar().y, 1) - - @dataclass - class Baz(Foo): - pass - self.assertEqual(Baz().x, {}) - - def test_intermediate_non_dataclass(self): - # Test that an intermediate class that defines - # annotations does not define fields. - - @dataclass - class A: - x: int - - class B(A): - y: int - - @dataclass - class C(B): - z: int - - c = C(1, 3) - self.assertEqual((c.x, c.z), (1, 3)) - - # .y was not initialized. - with self.assertRaisesRegex(AttributeError, - 'object has no attribute'): - c.y - - # And if we again derive a non-dataclass, no fields are added. - class D(C): - t: int - d = D(4, 5) - self.assertEqual((d.x, d.z), (4, 5)) - - def test_classvar_default_factory(self): - # It's an error for a ClassVar to have a factory function. - with self.assertRaisesRegex(TypeError, - 'cannot have a default factory'): - @dataclass - class C: - x: ClassVar[int] = field(default_factory=int) - - def test_is_dataclass(self): - class NotDataClass: - pass - - self.assertFalse(is_dataclass(0)) - self.assertFalse(is_dataclass(int)) - self.assertFalse(is_dataclass(NotDataClass)) - self.assertFalse(is_dataclass(NotDataClass())) - - @dataclass - class C: - x: int - - @dataclass - class D: - d: C - e: int - - c = C(10) - d = D(c, 4) - - self.assertTrue(is_dataclass(C)) - self.assertTrue(is_dataclass(c)) - self.assertFalse(is_dataclass(c.x)) - self.assertTrue(is_dataclass(d.d)) - self.assertFalse(is_dataclass(d.e)) - - def test_is_dataclass_when_getattr_always_returns(self): - # See bpo-37868. - class A: - def __getattr__(self, key): - return 0 - self.assertFalse(is_dataclass(A)) - a = A() - - # Also test for an instance attribute. - class B: - pass - b = B() - b.__dataclass_fields__ = [] - - for obj in a, b: - with self.subTest(obj=obj): - self.assertFalse(is_dataclass(obj)) - - # Indirect tests for _is_dataclass_instance(). - with self.assertRaisesRegex(TypeError, 'should be called on dataclass instances'): - asdict(obj) - with self.assertRaisesRegex(TypeError, 'should be called on dataclass instances'): - astuple(obj) - with self.assertRaisesRegex(TypeError, 'should be called on dataclass instances'): - replace(obj, x=0) - - def test_is_dataclass_genericalias(self): - @dataclass - class A(types.GenericAlias): - origin: type - args: type - self.assertTrue(is_dataclass(A)) - a = A(list, int) - self.assertTrue(is_dataclass(type(a))) - self.assertTrue(is_dataclass(a)) - - - def test_helper_fields_with_class_instance(self): - # Check that we can call fields() on either a class or instance, - # and get back the same thing. - @dataclass - class C: - x: int - y: float - - self.assertEqual(fields(C), fields(C(0, 0.0))) - - def test_helper_fields_exception(self): - # Check that TypeError is raised if not passed a dataclass or - # instance. - with self.assertRaisesRegex(TypeError, 'dataclass type or instance'): - fields(0) - - class C: pass - with self.assertRaisesRegex(TypeError, 'dataclass type or instance'): - fields(C) - with self.assertRaisesRegex(TypeError, 'dataclass type or instance'): - fields(C()) - - def test_clean_traceback_from_fields_exception(self): - stdout = io.StringIO() - try: - fields(object) - except TypeError as exc: - traceback.print_exception(exc, file=stdout) - printed_traceback = stdout.getvalue() - self.assertNotIn("AttributeError", printed_traceback) - self.assertNotIn("__dataclass_fields__", printed_traceback) - - def test_helper_asdict(self): - # Basic tests for asdict(), it should return a new dictionary. - @dataclass - class C: - x: int - y: int - c = C(1, 2) - - self.assertEqual(asdict(c), {'x': 1, 'y': 2}) - self.assertEqual(asdict(c), asdict(c)) - self.assertIsNot(asdict(c), asdict(c)) - c.x = 42 - self.assertEqual(asdict(c), {'x': 42, 'y': 2}) - self.assertIs(type(asdict(c)), dict) - - def test_helper_asdict_raises_on_classes(self): - # asdict() should raise on a class object. - @dataclass - class C: - x: int - y: int - with self.assertRaisesRegex(TypeError, 'dataclass instance'): - asdict(C) - with self.assertRaisesRegex(TypeError, 'dataclass instance'): - asdict(int) - - def test_helper_asdict_copy_values(self): - @dataclass - class C: - x: int - y: List[int] = field(default_factory=list) - initial = [] - c = C(1, initial) - d = asdict(c) - self.assertEqual(d['y'], initial) - self.assertIsNot(d['y'], initial) - c = C(1) - d = asdict(c) - d['y'].append(1) - self.assertEqual(c.y, []) - - def test_helper_asdict_nested(self): - @dataclass - class UserId: - token: int - group: int - @dataclass - class User: - name: str - id: UserId - u = User('Joe', UserId(123, 1)) - d = asdict(u) - self.assertEqual(d, {'name': 'Joe', 'id': {'token': 123, 'group': 1}}) - self.assertIsNot(asdict(u), asdict(u)) - u.id.group = 2 - self.assertEqual(asdict(u), {'name': 'Joe', - 'id': {'token': 123, 'group': 2}}) - - def test_helper_asdict_builtin_containers(self): - @dataclass - class User: - name: str - id: int - @dataclass - class GroupList: - id: int - users: List[User] - @dataclass - class GroupTuple: - id: int - users: Tuple[User, ...] - @dataclass - class GroupDict: - id: int - users: Dict[str, User] - a = User('Alice', 1) - b = User('Bob', 2) - gl = GroupList(0, [a, b]) - gt = GroupTuple(0, (a, b)) - gd = GroupDict(0, {'first': a, 'second': b}) - self.assertEqual(asdict(gl), {'id': 0, 'users': [{'name': 'Alice', 'id': 1}, - {'name': 'Bob', 'id': 2}]}) - self.assertEqual(asdict(gt), {'id': 0, 'users': ({'name': 'Alice', 'id': 1}, - {'name': 'Bob', 'id': 2})}) - self.assertEqual(asdict(gd), {'id': 0, 'users': {'first': {'name': 'Alice', 'id': 1}, - 'second': {'name': 'Bob', 'id': 2}}}) - - def test_helper_asdict_builtin_object_containers(self): - @dataclass - class Child: - d: object - - @dataclass - class Parent: - child: Child - - self.assertEqual(asdict(Parent(Child([1]))), {'child': {'d': [1]}}) - self.assertEqual(asdict(Parent(Child({1: 2}))), {'child': {'d': {1: 2}}}) - - def test_helper_asdict_factory(self): - @dataclass - class C: - x: int - y: int - c = C(1, 2) - d = asdict(c, dict_factory=OrderedDict) - self.assertEqual(d, OrderedDict([('x', 1), ('y', 2)])) - self.assertIsNot(d, asdict(c, dict_factory=OrderedDict)) - c.x = 42 - d = asdict(c, dict_factory=OrderedDict) - self.assertEqual(d, OrderedDict([('x', 42), ('y', 2)])) - self.assertIs(type(d), OrderedDict) - - def test_helper_asdict_namedtuple(self): - T = namedtuple('T', 'a b c') - @dataclass - class C: - x: str - y: T - c = C('outer', T(1, C('inner', T(11, 12, 13)), 2)) - - d = asdict(c) - self.assertEqual(d, {'x': 'outer', - 'y': T(1, - {'x': 'inner', - 'y': T(11, 12, 13)}, - 2), - } - ) - - # Now with a dict_factory. OrderedDict is convenient, but - # since it compares to dicts, we also need to have separate - # assertIs tests. - d = asdict(c, dict_factory=OrderedDict) - self.assertEqual(d, {'x': 'outer', - 'y': T(1, - {'x': 'inner', - 'y': T(11, 12, 13)}, - 2), - } - ) - - # Make sure that the returned dicts are actually OrderedDicts. - self.assertIs(type(d), OrderedDict) - self.assertIs(type(d['y'][1]), OrderedDict) - - def test_helper_asdict_namedtuple_key(self): - # Ensure that a field that contains a dict which has a - # namedtuple as a key works with asdict(). - - @dataclass - class C: - f: dict - T = namedtuple('T', 'a') - - c = C({T('an a'): 0}) - - self.assertEqual(asdict(c), {'f': {T(a='an a'): 0}}) - - def test_helper_asdict_namedtuple_derived(self): - class T(namedtuple('Tbase', 'a')): - def my_a(self): - return self.a - - @dataclass - class C: - f: T - - t = T(6) - c = C(t) - - d = asdict(c) - self.assertEqual(d, {'f': T(a=6)}) - # Make sure that t has been copied, not used directly. - self.assertIsNot(d['f'], t) - self.assertEqual(d['f'].my_a(), 6) - - def test_helper_asdict_defaultdict(self): - # Ensure asdict() does not throw exceptions when a - # defaultdict is a member of a dataclass - @dataclass - class C: - mp: DefaultDict[str, List] - - dd = defaultdict(list) - dd["x"].append(12) - c = C(mp=dd) - d = asdict(c) - - self.assertEqual(d, {"mp": {"x": [12]}}) - self.assertTrue(d["mp"] is not c.mp) # make sure defaultdict is copied - - def test_helper_astuple(self): - # Basic tests for astuple(), it should return a new tuple. - @dataclass - class C: - x: int - y: int = 0 - c = C(1) - - self.assertEqual(astuple(c), (1, 0)) - self.assertEqual(astuple(c), astuple(c)) - self.assertIsNot(astuple(c), astuple(c)) - c.y = 42 - self.assertEqual(astuple(c), (1, 42)) - self.assertIs(type(astuple(c)), tuple) - - def test_helper_astuple_raises_on_classes(self): - # astuple() should raise on a class object. - @dataclass - class C: - x: int - y: int - with self.assertRaisesRegex(TypeError, 'dataclass instance'): - astuple(C) - with self.assertRaisesRegex(TypeError, 'dataclass instance'): - astuple(int) - - def test_helper_astuple_copy_values(self): - @dataclass - class C: - x: int - y: List[int] = field(default_factory=list) - initial = [] - c = C(1, initial) - t = astuple(c) - self.assertEqual(t[1], initial) - self.assertIsNot(t[1], initial) - c = C(1) - t = astuple(c) - t[1].append(1) - self.assertEqual(c.y, []) - - def test_helper_astuple_nested(self): - @dataclass - class UserId: - token: int - group: int - @dataclass - class User: - name: str - id: UserId - u = User('Joe', UserId(123, 1)) - t = astuple(u) - self.assertEqual(t, ('Joe', (123, 1))) - self.assertIsNot(astuple(u), astuple(u)) - u.id.group = 2 - self.assertEqual(astuple(u), ('Joe', (123, 2))) - - def test_helper_astuple_builtin_containers(self): - @dataclass - class User: - name: str - id: int - @dataclass - class GroupList: - id: int - users: List[User] - @dataclass - class GroupTuple: - id: int - users: Tuple[User, ...] - @dataclass - class GroupDict: - id: int - users: Dict[str, User] - a = User('Alice', 1) - b = User('Bob', 2) - gl = GroupList(0, [a, b]) - gt = GroupTuple(0, (a, b)) - gd = GroupDict(0, {'first': a, 'second': b}) - self.assertEqual(astuple(gl), (0, [('Alice', 1), ('Bob', 2)])) - self.assertEqual(astuple(gt), (0, (('Alice', 1), ('Bob', 2)))) - self.assertEqual(astuple(gd), (0, {'first': ('Alice', 1), 'second': ('Bob', 2)})) - - def test_helper_astuple_builtin_object_containers(self): - @dataclass - class Child: - d: object - - @dataclass - class Parent: - child: Child - - self.assertEqual(astuple(Parent(Child([1]))), (([1],),)) - self.assertEqual(astuple(Parent(Child({1: 2}))), (({1: 2},),)) - - def test_helper_astuple_factory(self): - @dataclass - class C: - x: int - y: int - NT = namedtuple('NT', 'x y') - def nt(lst): - return NT(*lst) - c = C(1, 2) - t = astuple(c, tuple_factory=nt) - self.assertEqual(t, NT(1, 2)) - self.assertIsNot(t, astuple(c, tuple_factory=nt)) - c.x = 42 - t = astuple(c, tuple_factory=nt) - self.assertEqual(t, NT(42, 2)) - self.assertIs(type(t), NT) - - def test_helper_astuple_namedtuple(self): - T = namedtuple('T', 'a b c') - @dataclass - class C: - x: str - y: T - c = C('outer', T(1, C('inner', T(11, 12, 13)), 2)) - - t = astuple(c) - self.assertEqual(t, ('outer', T(1, ('inner', (11, 12, 13)), 2))) - - # Now, using a tuple_factory. list is convenient here. - t = astuple(c, tuple_factory=list) - self.assertEqual(t, ['outer', T(1, ['inner', T(11, 12, 13)], 2)]) - - def test_helper_astuple_defaultdict(self): - # Ensure astuple() does not throw exceptions when a - # defaultdict is a member of a dataclass - @dataclass - class C: - mp: DefaultDict[str, List] - - dd = defaultdict(list) - dd["x"].append(12) - c = C(mp=dd) - t = astuple(c) - - self.assertEqual(t, ({"x": [12]},)) - self.assertTrue(t[0] is not dd) # make sure defaultdict is copied - - def test_dynamic_class_creation(self): - cls_dict = {'__annotations__': {'x': int, 'y': int}, - } - - # Create the class. - cls = type('C', (), cls_dict) - - # Make it a dataclass. - cls1 = dataclass(cls) - - self.assertEqual(cls1, cls) - self.assertEqual(asdict(cls(1, 2)), {'x': 1, 'y': 2}) - - def test_dynamic_class_creation_using_field(self): - cls_dict = {'__annotations__': {'x': int, 'y': int}, - 'y': field(default=5), - } - - # Create the class. - cls = type('C', (), cls_dict) - - # Make it a dataclass. - cls1 = dataclass(cls) - - self.assertEqual(cls1, cls) - self.assertEqual(asdict(cls1(1)), {'x': 1, 'y': 5}) - - def test_init_in_order(self): - @dataclass - class C: - a: int - b: int = field() - c: list = field(default_factory=list, init=False) - d: list = field(default_factory=list) - e: int = field(default=4, init=False) - f: int = 4 - - calls = [] - def setattr(self, name, value): - calls.append((name, value)) - - C.__setattr__ = setattr - c = C(0, 1) - self.assertEqual(('a', 0), calls[0]) - self.assertEqual(('b', 1), calls[1]) - self.assertEqual(('c', []), calls[2]) - self.assertEqual(('d', []), calls[3]) - self.assertNotIn(('e', 4), calls) - self.assertEqual(('f', 4), calls[4]) - - def test_items_in_dicts(self): - @dataclass - class C: - a: int - b: list = field(default_factory=list, init=False) - c: list = field(default_factory=list) - d: int = field(default=4, init=False) - e: int = 0 - - c = C(0) - # Class dict - self.assertNotIn('a', C.__dict__) - self.assertNotIn('b', C.__dict__) - self.assertNotIn('c', C.__dict__) - self.assertIn('d', C.__dict__) - self.assertEqual(C.d, 4) - self.assertIn('e', C.__dict__) - self.assertEqual(C.e, 0) - # Instance dict - self.assertIn('a', c.__dict__) - self.assertEqual(c.a, 0) - self.assertIn('b', c.__dict__) - self.assertEqual(c.b, []) - self.assertIn('c', c.__dict__) - self.assertEqual(c.c, []) - self.assertNotIn('d', c.__dict__) - self.assertIn('e', c.__dict__) - self.assertEqual(c.e, 0) - - def test_alternate_classmethod_constructor(self): - # Since __post_init__ can't take params, use a classmethod - # alternate constructor. This is mostly an example to show - # how to use this technique. - @dataclass - class C: - x: int - @classmethod - def from_file(cls, filename): - # In a real example, create a new instance - # and populate 'x' from contents of a file. - value_in_file = 20 - return cls(value_in_file) - - self.assertEqual(C.from_file('filename').x, 20) - - def test_field_metadata_default(self): - # Make sure the default metadata is read-only and of - # zero length. - @dataclass - class C: - i: int - - self.assertFalse(fields(C)[0].metadata) - self.assertEqual(len(fields(C)[0].metadata), 0) - with self.assertRaisesRegex(TypeError, - 'does not support item assignment'): - fields(C)[0].metadata['test'] = 3 - - def test_field_metadata_mapping(self): - # Make sure only a mapping can be passed as metadata - # zero length. - with self.assertRaises(TypeError): - @dataclass - class C: - i: int = field(metadata=0) - - # Make sure an empty dict works. - d = {} - @dataclass - class C: - i: int = field(metadata=d) - self.assertFalse(fields(C)[0].metadata) - self.assertEqual(len(fields(C)[0].metadata), 0) - # Update should work (see bpo-35960). - d['foo'] = 1 - self.assertEqual(len(fields(C)[0].metadata), 1) - self.assertEqual(fields(C)[0].metadata['foo'], 1) - with self.assertRaisesRegex(TypeError, - 'does not support item assignment'): - fields(C)[0].metadata['test'] = 3 - - # Make sure a non-empty dict works. - d = {'test': 10, 'bar': '42', 3: 'three'} - @dataclass - class C: - i: int = field(metadata=d) - self.assertEqual(len(fields(C)[0].metadata), 3) - self.assertEqual(fields(C)[0].metadata['test'], 10) - self.assertEqual(fields(C)[0].metadata['bar'], '42') - self.assertEqual(fields(C)[0].metadata[3], 'three') - # Update should work. - d['foo'] = 1 - self.assertEqual(len(fields(C)[0].metadata), 4) - self.assertEqual(fields(C)[0].metadata['foo'], 1) - with self.assertRaises(KeyError): - # Non-existent key. - fields(C)[0].metadata['baz'] - with self.assertRaisesRegex(TypeError, - 'does not support item assignment'): - fields(C)[0].metadata['test'] = 3 - - def test_field_metadata_custom_mapping(self): - # Try a custom mapping. - class SimpleNameSpace: - def __init__(self, **kw): - self.__dict__.update(kw) - - def __getitem__(self, item): - if item == 'xyzzy': - return 'plugh' - return getattr(self, item) - - def __len__(self): - return self.__dict__.__len__() - - @dataclass - class C: - i: int = field(metadata=SimpleNameSpace(a=10)) - - self.assertEqual(len(fields(C)[0].metadata), 1) - self.assertEqual(fields(C)[0].metadata['a'], 10) - with self.assertRaises(AttributeError): - fields(C)[0].metadata['b'] - # Make sure we're still talking to our custom mapping. - self.assertEqual(fields(C)[0].metadata['xyzzy'], 'plugh') - - def test_generic_dataclasses(self): - T = TypeVar('T') - - @dataclass - class LabeledBox(Generic[T]): - content: T - label: str = '' - - box = LabeledBox(42) - self.assertEqual(box.content, 42) - self.assertEqual(box.label, '') - - # Subscripting the resulting class should work, etc. - Alias = List[LabeledBox[int]] - - def test_generic_extending(self): - S = TypeVar('S') - T = TypeVar('T') - - @dataclass - class Base(Generic[T, S]): - x: T - y: S - - @dataclass - class DataDerived(Base[int, T]): - new_field: str - Alias = DataDerived[str] - c = Alias(0, 'test1', 'test2') - self.assertEqual(astuple(c), (0, 'test1', 'test2')) - - class NonDataDerived(Base[int, T]): - def new_method(self): - return self.y - Alias = NonDataDerived[float] - c = Alias(10, 1.0) - self.assertEqual(c.new_method(), 1.0) - - def test_generic_dynamic(self): - T = TypeVar('T') - - @dataclass - class Parent(Generic[T]): - x: T - Child = make_dataclass('Child', [('y', T), ('z', Optional[T], None)], - bases=(Parent[int], Generic[T]), namespace={'other': 42}) - self.assertIs(Child[int](1, 2).z, None) - self.assertEqual(Child[int](1, 2, 3).z, 3) - self.assertEqual(Child[int](1, 2, 3).other, 42) - # Check that type aliases work correctly. - Alias = Child[T] - self.assertEqual(Alias[int](1, 2).x, 1) - # Check MRO resolution. - self.assertEqual(Child.__mro__, (Child, Parent, Generic, object)) - - def test_dataclasses_pickleable(self): - global P, Q, R - @dataclass - class P: - x: int - y: int = 0 - @dataclass - class Q: - x: int - y: int = field(default=0, init=False) - @dataclass - class R: - x: int - y: List[int] = field(default_factory=list) - q = Q(1) - q.y = 2 - samples = [P(1), P(1, 2), Q(1), q, R(1), R(1, [2, 3, 4])] - for sample in samples: - for proto in range(pickle.HIGHEST_PROTOCOL + 1): - with self.subTest(sample=sample, proto=proto): - new_sample = pickle.loads(pickle.dumps(sample, proto)) - self.assertEqual(sample.x, new_sample.x) - self.assertEqual(sample.y, new_sample.y) - self.assertIsNot(sample, new_sample) - new_sample.x = 42 - another_new_sample = pickle.loads(pickle.dumps(new_sample, proto)) - self.assertEqual(new_sample.x, another_new_sample.x) - self.assertEqual(sample.y, another_new_sample.y) - - def test_dataclasses_qualnames(self): - @dataclass(order=True, unsafe_hash=True, frozen=True) - class A: - x: int - y: int - - self.assertEqual(A.__init__.__name__, "__init__") - for function in ( - '__eq__', - '__lt__', - '__le__', - '__gt__', - '__ge__', - '__hash__', - '__init__', - '__repr__', - '__setattr__', - '__delattr__', - ): - self.assertEqual(getattr(A, function).__qualname__, f"TestCase.test_dataclasses_qualnames..A.{function}") - - with self.assertRaisesRegex(TypeError, r"A\.__init__\(\) missing"): - A() - - -class TestFieldNoAnnotation(unittest.TestCase): - def test_field_without_annotation(self): - with self.assertRaisesRegex(TypeError, - "'f' is a field but has no type annotation"): - @dataclass - class C: - f = field() - - def test_field_without_annotation_but_annotation_in_base(self): - @dataclass - class B: - f: int - - with self.assertRaisesRegex(TypeError, - "'f' is a field but has no type annotation"): - # This is still an error: make sure we don't pick up the - # type annotation in the base class. - @dataclass - class C(B): - f = field() - - def test_field_without_annotation_but_annotation_in_base_not_dataclass(self): - # Same test, but with the base class not a dataclass. - class B: - f: int - - with self.assertRaisesRegex(TypeError, - "'f' is a field but has no type annotation"): - # This is still an error: make sure we don't pick up the - # type annotation in the base class. - @dataclass - class C(B): - f = field() - - -class TestDocString(unittest.TestCase): - def assertDocStrEqual(self, a, b): - # Because 3.6 and 3.7 differ in how inspect.signature work - # (see bpo #32108), for the time being just compare them with - # whitespace stripped. - self.assertEqual(a.replace(' ', ''), b.replace(' ', '')) - - def test_existing_docstring_not_overridden(self): - @dataclass - class C: - """Lorem ipsum""" - x: int - - self.assertEqual(C.__doc__, "Lorem ipsum") - - def test_docstring_no_fields(self): - @dataclass - class C: - pass - - self.assertDocStrEqual(C.__doc__, "C()") - - def test_docstring_one_field(self): - @dataclass - class C: - x: int - - self.assertDocStrEqual(C.__doc__, "C(x:int)") - - def test_docstring_two_fields(self): - @dataclass - class C: - x: int - y: int - - self.assertDocStrEqual(C.__doc__, "C(x:int, y:int)") - - def test_docstring_three_fields(self): - @dataclass - class C: - x: int - y: int - z: str - - self.assertDocStrEqual(C.__doc__, "C(x:int, y:int, z:str)") - - def test_docstring_one_field_with_default(self): - @dataclass - class C: - x: int = 3 - - self.assertDocStrEqual(C.__doc__, "C(x:int=3)") - - def test_docstring_one_field_with_default_none(self): - @dataclass - class C: - x: Union[int, type(None)] = None - - self.assertDocStrEqual(C.__doc__, "C(x:Optional[int]=None)") - - def test_docstring_list_field(self): - @dataclass - class C: - x: List[int] - - self.assertDocStrEqual(C.__doc__, "C(x:List[int])") - - def test_docstring_list_field_with_default_factory(self): - @dataclass - class C: - x: List[int] = field(default_factory=list) - - self.assertDocStrEqual(C.__doc__, "C(x:List[int]=)") - - def test_docstring_deque_field(self): - @dataclass - class C: - x: deque - - self.assertDocStrEqual(C.__doc__, "C(x:collections.deque)") - - def test_docstring_deque_field_with_default_factory(self): - @dataclass - class C: - x: deque = field(default_factory=deque) - - self.assertDocStrEqual(C.__doc__, "C(x:collections.deque=)") - - def test_docstring_with_no_signature(self): - # See https://github.com/python/cpython/issues/103449 - class Meta(type): - __call__ = dict - class Base(metaclass=Meta): - pass - - @dataclass - class C(Base): - pass - - self.assertDocStrEqual(C.__doc__, "C") - - -class TestInit(unittest.TestCase): - def test_base_has_init(self): - class B: - def __init__(self): - self.z = 100 - - # Make sure that declaring this class doesn't raise an error. - # The issue is that we can't override __init__ in our class, - # but it should be okay to add __init__ to us if our base has - # an __init__. - @dataclass - class C(B): - x: int = 0 - c = C(10) - self.assertEqual(c.x, 10) - self.assertNotIn('z', vars(c)) - - # Make sure that if we don't add an init, the base __init__ - # gets called. - @dataclass(init=False) - class C(B): - x: int = 10 - c = C() - self.assertEqual(c.x, 10) - self.assertEqual(c.z, 100) - - def test_no_init(self): - @dataclass(init=False) - class C: - i: int = 0 - self.assertEqual(C().i, 0) - - @dataclass(init=False) - class C: - i: int = 2 - def __init__(self): - self.i = 3 - self.assertEqual(C().i, 3) - - def test_overwriting_init(self): - # If the class has __init__, use it no matter the value of - # init=. - - @dataclass - class C: - x: int - def __init__(self, x): - self.x = 2 * x - self.assertEqual(C(3).x, 6) - - @dataclass(init=True) - class C: - x: int - def __init__(self, x): - self.x = 2 * x - self.assertEqual(C(4).x, 8) - - @dataclass(init=False) - class C: - x: int - def __init__(self, x): - self.x = 2 * x - self.assertEqual(C(5).x, 10) - - def test_inherit_from_protocol(self): - # Dataclasses inheriting from protocol should preserve their own `__init__`. - # See bpo-45081. - - class P(Protocol): - a: int - - @dataclass - class C(P): - a: int - - self.assertEqual(C(5).a, 5) - - @dataclass - class D(P): - def __init__(self, a): - self.a = a * 2 - - self.assertEqual(D(5).a, 10) - - -class TestRepr(unittest.TestCase): - def test_repr(self): - @dataclass - class B: - x: int - - @dataclass - class C(B): - y: int = 10 - - o = C(4) - self.assertEqual(repr(o), 'TestRepr.test_repr..C(x=4, y=10)') - - @dataclass - class D(C): - x: int = 20 - self.assertEqual(repr(D()), 'TestRepr.test_repr..D(x=20, y=10)') - - @dataclass - class C: - @dataclass - class D: - i: int - @dataclass - class E: - pass - self.assertEqual(repr(C.D(0)), 'TestRepr.test_repr..C.D(i=0)') - self.assertEqual(repr(C.E()), 'TestRepr.test_repr..C.E()') - - def test_no_repr(self): - # Test a class with no __repr__ and repr=False. - @dataclass(repr=False) - class C: - x: int - self.assertIn(f'{__name__}.TestRepr.test_no_repr..C object at', - repr(C(3))) - - # Test a class with a __repr__ and repr=False. - @dataclass(repr=False) - class C: - x: int - def __repr__(self): - return 'C-class' - self.assertEqual(repr(C(3)), 'C-class') - - def test_overwriting_repr(self): - # If the class has __repr__, use it no matter the value of - # repr=. - - @dataclass - class C: - x: int - def __repr__(self): - return 'x' - self.assertEqual(repr(C(0)), 'x') - - @dataclass(repr=True) - class C: - x: int - def __repr__(self): - return 'x' - self.assertEqual(repr(C(0)), 'x') - - @dataclass(repr=False) - class C: - x: int - def __repr__(self): - return 'x' - self.assertEqual(repr(C(0)), 'x') - - -class TestEq(unittest.TestCase): - def test_no_eq(self): - # Test a class with no __eq__ and eq=False. - @dataclass(eq=False) - class C: - x: int - self.assertNotEqual(C(0), C(0)) - c = C(3) - self.assertEqual(c, c) - - # Test a class with an __eq__ and eq=False. - @dataclass(eq=False) - class C: - x: int - def __eq__(self, other): - return other == 10 - self.assertEqual(C(3), 10) - - def test_overwriting_eq(self): - # If the class has __eq__, use it no matter the value of - # eq=. - - @dataclass - class C: - x: int - def __eq__(self, other): - return other == 3 - self.assertEqual(C(1), 3) - self.assertNotEqual(C(1), 1) - - @dataclass(eq=True) - class C: - x: int - def __eq__(self, other): - return other == 4 - self.assertEqual(C(1), 4) - self.assertNotEqual(C(1), 1) - - @dataclass(eq=False) - class C: - x: int - def __eq__(self, other): - return other == 5 - self.assertEqual(C(1), 5) - self.assertNotEqual(C(1), 1) - - -class TestOrdering(unittest.TestCase): - def test_functools_total_ordering(self): - # Test that functools.total_ordering works with this class. - @total_ordering - @dataclass - class C: - x: int - def __lt__(self, other): - # Perform the test "backward", just to make - # sure this is being called. - return self.x >= other - - self.assertLess(C(0), -1) - self.assertLessEqual(C(0), -1) - self.assertGreater(C(0), 1) - self.assertGreaterEqual(C(0), 1) - - def test_no_order(self): - # Test that no ordering functions are added by default. - @dataclass(order=False) - class C: - x: int - # Make sure no order methods are added. - self.assertNotIn('__le__', C.__dict__) - self.assertNotIn('__lt__', C.__dict__) - self.assertNotIn('__ge__', C.__dict__) - self.assertNotIn('__gt__', C.__dict__) - - # Test that __lt__ is still called - @dataclass(order=False) - class C: - x: int - def __lt__(self, other): - return False - # Make sure other methods aren't added. - self.assertNotIn('__le__', C.__dict__) - self.assertNotIn('__ge__', C.__dict__) - self.assertNotIn('__gt__', C.__dict__) - - def test_overwriting_order(self): - with self.assertRaisesRegex(TypeError, - 'Cannot overwrite attribute __lt__' - '.*using functools.total_ordering'): - @dataclass(order=True) - class C: - x: int - def __lt__(self): - pass - - with self.assertRaisesRegex(TypeError, - 'Cannot overwrite attribute __le__' - '.*using functools.total_ordering'): - @dataclass(order=True) - class C: - x: int - def __le__(self): - pass - - with self.assertRaisesRegex(TypeError, - 'Cannot overwrite attribute __gt__' - '.*using functools.total_ordering'): - @dataclass(order=True) - class C: - x: int - def __gt__(self): - pass - - with self.assertRaisesRegex(TypeError, - 'Cannot overwrite attribute __ge__' - '.*using functools.total_ordering'): - @dataclass(order=True) - class C: - x: int - def __ge__(self): - pass - -class TestHash(unittest.TestCase): - def test_unsafe_hash(self): - @dataclass(unsafe_hash=True) - class C: - x: int - y: str - self.assertEqual(hash(C(1, 'foo')), hash((1, 'foo'))) - - def test_hash_rules(self): - def non_bool(value): - # Map to something else that's True, but not a bool. - if value is None: - return None - if value: - return (3,) - return 0 - - def test(case, unsafe_hash, eq, frozen, with_hash, result): - with self.subTest(case=case, unsafe_hash=unsafe_hash, eq=eq, - frozen=frozen): - if result != 'exception': - if with_hash: - @dataclass(unsafe_hash=unsafe_hash, eq=eq, frozen=frozen) - class C: - def __hash__(self): - return 0 - else: - @dataclass(unsafe_hash=unsafe_hash, eq=eq, frozen=frozen) - class C: - pass - - # See if the result matches what's expected. - if result == 'fn': - # __hash__ contains the function we generated. - self.assertIn('__hash__', C.__dict__) - self.assertIsNotNone(C.__dict__['__hash__']) - - elif result == '': - # __hash__ is not present in our class. - if not with_hash: - self.assertNotIn('__hash__', C.__dict__) - - elif result == 'none': - # __hash__ is set to None. - self.assertIn('__hash__', C.__dict__) - self.assertIsNone(C.__dict__['__hash__']) - - elif result == 'exception': - # Creating the class should cause an exception. - # This only happens with with_hash==True. - assert(with_hash) - with self.assertRaisesRegex(TypeError, 'Cannot overwrite attribute __hash__'): - @dataclass(unsafe_hash=unsafe_hash, eq=eq, frozen=frozen) - class C: - def __hash__(self): - return 0 - - else: - assert False, f'unknown result {result!r}' - - # There are 8 cases of: - # unsafe_hash=True/False - # eq=True/False - # frozen=True/False - # And for each of these, a different result if - # __hash__ is defined or not. - for case, (unsafe_hash, eq, frozen, res_no_defined_hash, res_defined_hash) in enumerate([ - (False, False, False, '', ''), - (False, False, True, '', ''), - (False, True, False, 'none', ''), - (False, True, True, 'fn', ''), - (True, False, False, 'fn', 'exception'), - (True, False, True, 'fn', 'exception'), - (True, True, False, 'fn', 'exception'), - (True, True, True, 'fn', 'exception'), - ], 1): - test(case, unsafe_hash, eq, frozen, False, res_no_defined_hash) - test(case, unsafe_hash, eq, frozen, True, res_defined_hash) - - # Test non-bool truth values, too. This is just to - # make sure the data-driven table in the decorator - # handles non-bool values. - test(case, non_bool(unsafe_hash), non_bool(eq), non_bool(frozen), False, res_no_defined_hash) - test(case, non_bool(unsafe_hash), non_bool(eq), non_bool(frozen), True, res_defined_hash) - - - def test_eq_only(self): - # If a class defines __eq__, __hash__ is automatically added - # and set to None. This is normal Python behavior, not - # related to dataclasses. Make sure we don't interfere with - # that (see bpo=32546). - - @dataclass - class C: - i: int - def __eq__(self, other): - return self.i == other.i - self.assertEqual(C(1), C(1)) - self.assertNotEqual(C(1), C(4)) - - # And make sure things work in this case if we specify - # unsafe_hash=True. - @dataclass(unsafe_hash=True) - class C: - i: int - def __eq__(self, other): - return self.i == other.i - self.assertEqual(C(1), C(1.0)) - self.assertEqual(hash(C(1)), hash(C(1.0))) - - # And check that the classes __eq__ is being used, despite - # specifying eq=True. - @dataclass(unsafe_hash=True, eq=True) - class C: - i: int - def __eq__(self, other): - return self.i == 3 and self.i == other.i - self.assertEqual(C(3), C(3)) - self.assertNotEqual(C(1), C(1)) - self.assertEqual(hash(C(1)), hash(C(1.0))) - - def test_0_field_hash(self): - @dataclass(frozen=True) - class C: - pass - self.assertEqual(hash(C()), hash(())) - - @dataclass(unsafe_hash=True) - class C: - pass - self.assertEqual(hash(C()), hash(())) - - def test_1_field_hash(self): - @dataclass(frozen=True) - class C: - x: int - self.assertEqual(hash(C(4)), hash((4,))) - self.assertEqual(hash(C(42)), hash((42,))) - - @dataclass(unsafe_hash=True) - class C: - x: int - self.assertEqual(hash(C(4)), hash((4,))) - self.assertEqual(hash(C(42)), hash((42,))) - - def test_hash_no_args(self): - # Test dataclasses with no hash= argument. This exists to - # make sure that if the @dataclass parameter name is changed - # or the non-default hashing behavior changes, the default - # hashability keeps working the same way. - - class Base: - def __hash__(self): - return 301 - - # If frozen or eq is None, then use the default value (do not - # specify any value in the decorator). - for frozen, eq, base, expected in [ - (None, None, object, 'unhashable'), - (None, None, Base, 'unhashable'), - (None, False, object, 'object'), - (None, False, Base, 'base'), - (None, True, object, 'unhashable'), - (None, True, Base, 'unhashable'), - (False, None, object, 'unhashable'), - (False, None, Base, 'unhashable'), - (False, False, object, 'object'), - (False, False, Base, 'base'), - (False, True, object, 'unhashable'), - (False, True, Base, 'unhashable'), - (True, None, object, 'tuple'), - (True, None, Base, 'tuple'), - (True, False, object, 'object'), - (True, False, Base, 'base'), - (True, True, object, 'tuple'), - (True, True, Base, 'tuple'), - ]: - - with self.subTest(frozen=frozen, eq=eq, base=base, expected=expected): - # First, create the class. - if frozen is None and eq is None: - @dataclass - class C(base): - i: int - elif frozen is None: - @dataclass(eq=eq) - class C(base): - i: int - elif eq is None: - @dataclass(frozen=frozen) - class C(base): - i: int - else: - @dataclass(frozen=frozen, eq=eq) - class C(base): - i: int - - # Now, make sure it hashes as expected. - if expected == 'unhashable': - c = C(10) - with self.assertRaisesRegex(TypeError, 'unhashable type'): - hash(c) - - elif expected == 'base': - self.assertEqual(hash(C(10)), 301) - - elif expected == 'object': - # I'm not sure what test to use here. object's - # hash isn't based on id(), so calling hash() - # won't tell us much. So, just check the - # function used is object's. - self.assertIs(C.__hash__, object.__hash__) - - elif expected == 'tuple': - self.assertEqual(hash(C(42)), hash((42,))) - - else: - assert False, f'unknown value for expected={expected!r}' - - -class TestFrozen(unittest.TestCase): - def test_frozen(self): - @dataclass(frozen=True) - class C: - i: int - - c = C(10) - self.assertEqual(c.i, 10) - with self.assertRaises(FrozenInstanceError): - c.i = 5 - self.assertEqual(c.i, 10) - - def test_frozen_empty(self): - @dataclass(frozen=True) - class C: - pass - - c = C() - self.assertFalse(hasattr(c, 'i')) - with self.assertRaises(FrozenInstanceError): - c.i = 5 - self.assertFalse(hasattr(c, 'i')) - with self.assertRaises(FrozenInstanceError): - del c.i - - def test_inherit(self): - @dataclass(frozen=True) - class C: - i: int - - @dataclass(frozen=True) - class D(C): - j: int - - d = D(0, 10) - with self.assertRaises(FrozenInstanceError): - d.i = 5 - with self.assertRaises(FrozenInstanceError): - d.j = 6 - self.assertEqual(d.i, 0) - self.assertEqual(d.j, 10) - - def test_inherit_nonfrozen_from_empty_frozen(self): - @dataclass(frozen=True) - class C: - pass - - with self.assertRaisesRegex(TypeError, - 'cannot inherit non-frozen dataclass from a frozen one'): - @dataclass - class D(C): - j: int - - def test_inherit_nonfrozen_from_empty(self): - @dataclass - class C: - pass - - @dataclass - class D(C): - j: int - - d = D(3) - self.assertEqual(d.j, 3) - self.assertIsInstance(d, C) - - # Test both ways: with an intermediate normal (non-dataclass) - # class and without an intermediate class. - def test_inherit_nonfrozen_from_frozen(self): - for intermediate_class in [True, False]: - with self.subTest(intermediate_class=intermediate_class): - @dataclass(frozen=True) - class C: - i: int - - if intermediate_class: - class I(C): pass - else: - I = C - - with self.assertRaisesRegex(TypeError, - 'cannot inherit non-frozen dataclass from a frozen one'): - @dataclass - class D(I): - pass - - def test_inherit_frozen_from_nonfrozen(self): - for intermediate_class in [True, False]: - with self.subTest(intermediate_class=intermediate_class): - @dataclass - class C: - i: int - - if intermediate_class: - class I(C): pass - else: - I = C - - with self.assertRaisesRegex(TypeError, - 'cannot inherit frozen dataclass from a non-frozen one'): - @dataclass(frozen=True) - class D(I): - pass - - def test_inherit_from_normal_class(self): - for intermediate_class in [True, False]: - with self.subTest(intermediate_class=intermediate_class): - class C: - pass - - if intermediate_class: - class I(C): pass - else: - I = C - - @dataclass(frozen=True) - class D(I): - i: int - - d = D(10) - with self.assertRaises(FrozenInstanceError): - d.i = 5 - - def test_non_frozen_normal_derived(self): - # See bpo-32953. - - @dataclass(frozen=True) - class D: - x: int - y: int = 10 - - class S(D): - pass - - s = S(3) - self.assertEqual(s.x, 3) - self.assertEqual(s.y, 10) - s.cached = True - - # But can't change the frozen attributes. - with self.assertRaises(FrozenInstanceError): - s.x = 5 - with self.assertRaises(FrozenInstanceError): - s.y = 5 - self.assertEqual(s.x, 3) - self.assertEqual(s.y, 10) - self.assertEqual(s.cached, True) - - with self.assertRaises(FrozenInstanceError): - del s.x - self.assertEqual(s.x, 3) - with self.assertRaises(FrozenInstanceError): - del s.y - self.assertEqual(s.y, 10) - del s.cached - self.assertFalse(hasattr(s, 'cached')) - with self.assertRaises(AttributeError) as cm: - del s.cached - self.assertNotIsInstance(cm.exception, FrozenInstanceError) - - def test_non_frozen_normal_derived_from_empty_frozen(self): - @dataclass(frozen=True) - class D: - pass - - class S(D): - pass - - s = S() - self.assertFalse(hasattr(s, 'x')) - s.x = 5 - self.assertEqual(s.x, 5) - - del s.x - self.assertFalse(hasattr(s, 'x')) - with self.assertRaises(AttributeError) as cm: - del s.x - self.assertNotIsInstance(cm.exception, FrozenInstanceError) - - def test_overwriting_frozen(self): - # frozen uses __setattr__ and __delattr__. - with self.assertRaisesRegex(TypeError, - 'Cannot overwrite attribute __setattr__'): - @dataclass(frozen=True) - class C: - x: int - def __setattr__(self): - pass - - with self.assertRaisesRegex(TypeError, - 'Cannot overwrite attribute __delattr__'): - @dataclass(frozen=True) - class C: - x: int - def __delattr__(self): - pass - - @dataclass(frozen=False) - class C: - x: int - def __setattr__(self, name, value): - self.__dict__['x'] = value * 2 - self.assertEqual(C(10).x, 20) - - def test_frozen_hash(self): - @dataclass(frozen=True) - class C: - x: Any - - # If x is immutable, we can compute the hash. No exception is - # raised. - hash(C(3)) - - # If x is mutable, computing the hash is an error. - with self.assertRaisesRegex(TypeError, 'unhashable type'): - hash(C({})) - - -class TestSlots(unittest.TestCase): - def test_simple(self): - @dataclass - class C: - __slots__ = ('x',) - x: Any - - # There was a bug where a variable in a slot was assumed to - # also have a default value (of type - # types.MemberDescriptorType). - with self.assertRaisesRegex(TypeError, - r"__init__\(\) missing 1 required positional argument: 'x'"): - C() - - # We can create an instance, and assign to x. - c = C(10) - self.assertEqual(c.x, 10) - c.x = 5 - self.assertEqual(c.x, 5) - - # We can't assign to anything else. - with self.assertRaisesRegex(AttributeError, "'C' object has no attribute 'y'"): - c.y = 5 - - def test_derived_added_field(self): - # See bpo-33100. - @dataclass - class Base: - __slots__ = ('x',) - x: Any - - @dataclass - class Derived(Base): - x: int - y: int - - d = Derived(1, 2) - self.assertEqual((d.x, d.y), (1, 2)) - - # We can add a new field to the derived instance. - d.z = 10 - - def test_generated_slots(self): - @dataclass(slots=True) - class C: - x: int - y: int - - c = C(1, 2) - self.assertEqual((c.x, c.y), (1, 2)) - - c.x = 3 - c.y = 4 - self.assertEqual((c.x, c.y), (3, 4)) - - with self.assertRaisesRegex(AttributeError, "'C' object has no attribute 'z'"): - c.z = 5 - - def test_add_slots_when_slots_exists(self): - with self.assertRaisesRegex(TypeError, '^C already specifies __slots__$'): - @dataclass(slots=True) - class C: - __slots__ = ('x',) - x: int - - def test_generated_slots_value(self): - - class Root: - __slots__ = {'x'} - - class Root2(Root): - __slots__ = {'k': '...', 'j': ''} - - class Root3(Root2): - __slots__ = ['h'] - - class Root4(Root3): - __slots__ = 'aa' - - @dataclass(slots=True) - class Base(Root4): - y: int - j: str - h: str - - self.assertEqual(Base.__slots__, ('y', )) - - @dataclass(slots=True) - class Derived(Base): - aa: float - x: str - z: int - k: str - h: str - - self.assertEqual(Derived.__slots__, ('z', )) - - @dataclass - class AnotherDerived(Base): - z: int - - self.assertNotIn('__slots__', AnotherDerived.__dict__) - - def test_cant_inherit_from_iterator_slots(self): - - class Root: - __slots__ = iter(['a']) - - class Root2(Root): - __slots__ = ('b', ) - - with self.assertRaisesRegex( - TypeError, - "^Slots of 'Root' cannot be determined" - ): - @dataclass(slots=True) - class C(Root2): - x: int - - def test_returns_new_class(self): - class A: - x: int - - B = dataclass(A, slots=True) - self.assertIsNot(A, B) - - self.assertFalse(hasattr(A, "__slots__")) - self.assertTrue(hasattr(B, "__slots__")) - - # Can't be local to test_frozen_pickle. - @dataclass(frozen=True, slots=True) - class FrozenSlotsClass: - foo: str - bar: int - - @dataclass(frozen=True) - class FrozenWithoutSlotsClass: - foo: str - bar: int - - def test_frozen_pickle(self): - # bpo-43999 - - self.assertEqual(self.FrozenSlotsClass.__slots__, ("foo", "bar")) - for proto in range(pickle.HIGHEST_PROTOCOL + 1): - with self.subTest(proto=proto): - obj = self.FrozenSlotsClass("a", 1) - p = pickle.loads(pickle.dumps(obj, protocol=proto)) - self.assertIsNot(obj, p) - self.assertEqual(obj, p) - - obj = self.FrozenWithoutSlotsClass("a", 1) - p = pickle.loads(pickle.dumps(obj, protocol=proto)) - self.assertIsNot(obj, p) - self.assertEqual(obj, p) - - @dataclass(frozen=True, slots=True) - class FrozenSlotsGetStateClass: - foo: str - bar: int - - getstate_called: bool = field(default=False, compare=False) - - def __getstate__(self): - object.__setattr__(self, 'getstate_called', True) - return [self.foo, self.bar] - - @dataclass(frozen=True, slots=True) - class FrozenSlotsSetStateClass: - foo: str - bar: int - - setstate_called: bool = field(default=False, compare=False) - - def __setstate__(self, state): - object.__setattr__(self, 'setstate_called', True) - object.__setattr__(self, 'foo', state[0]) - object.__setattr__(self, 'bar', state[1]) - - @dataclass(frozen=True, slots=True) - class FrozenSlotsAllStateClass: - foo: str - bar: int - - getstate_called: bool = field(default=False, compare=False) - setstate_called: bool = field(default=False, compare=False) - - def __getstate__(self): - object.__setattr__(self, 'getstate_called', True) - return [self.foo, self.bar] - - def __setstate__(self, state): - object.__setattr__(self, 'setstate_called', True) - object.__setattr__(self, 'foo', state[0]) - object.__setattr__(self, 'bar', state[1]) - - def test_frozen_slots_pickle_custom_state(self): - for proto in range(pickle.HIGHEST_PROTOCOL + 1): - with self.subTest(proto=proto): - obj = self.FrozenSlotsGetStateClass('a', 1) - dumped = pickle.dumps(obj, protocol=proto) - - self.assertTrue(obj.getstate_called) - self.assertEqual(obj, pickle.loads(dumped)) - - for proto in range(pickle.HIGHEST_PROTOCOL + 1): - with self.subTest(proto=proto): - obj = self.FrozenSlotsSetStateClass('a', 1) - obj2 = pickle.loads(pickle.dumps(obj, protocol=proto)) - - self.assertTrue(obj2.setstate_called) - self.assertEqual(obj, obj2) - - for proto in range(pickle.HIGHEST_PROTOCOL + 1): - with self.subTest(proto=proto): - obj = self.FrozenSlotsAllStateClass('a', 1) - dumped = pickle.dumps(obj, protocol=proto) - - self.assertTrue(obj.getstate_called) - - obj2 = pickle.loads(dumped) - self.assertTrue(obj2.setstate_called) - self.assertEqual(obj, obj2) - - def test_slots_with_default_no_init(self): - # Originally reported in bpo-44649. - @dataclass(slots=True) - class A: - a: str - b: str = field(default='b', init=False) - - obj = A("a") - self.assertEqual(obj.a, 'a') - self.assertEqual(obj.b, 'b') - - def test_slots_with_default_factory_no_init(self): - # Originally reported in bpo-44649. - @dataclass(slots=True) - class A: - a: str - b: str = field(default_factory=lambda:'b', init=False) - - obj = A("a") - self.assertEqual(obj.a, 'a') - self.assertEqual(obj.b, 'b') - - def test_slots_no_weakref(self): - @dataclass(slots=True) - class A: - # No weakref. - pass - - self.assertNotIn("__weakref__", A.__slots__) - a = A() - with self.assertRaisesRegex(TypeError, - "cannot create weak reference"): - weakref.ref(a) - with self.assertRaises(AttributeError): - a.__weakref__ - - def test_slots_weakref(self): - @dataclass(slots=True, weakref_slot=True) - class A: - a: int - - self.assertIn("__weakref__", A.__slots__) - a = A(1) - a_ref = weakref.ref(a) - - self.assertIs(a.__weakref__, a_ref) - - def test_slots_weakref_base_str(self): - class Base: - __slots__ = '__weakref__' - - @dataclass(slots=True) - class A(Base): - a: int - - # __weakref__ is in the base class, not A. But an A is still weakref-able. - self.assertIn("__weakref__", Base.__slots__) - self.assertNotIn("__weakref__", A.__slots__) - a = A(1) - weakref.ref(a) - - def test_slots_weakref_base_tuple(self): - # Same as test_slots_weakref_base, but use a tuple instead of a string - # in the base class. - class Base: - __slots__ = ('__weakref__',) - - @dataclass(slots=True) - class A(Base): - a: int - - # __weakref__ is in the base class, not A. But an A is still - # weakref-able. - self.assertIn("__weakref__", Base.__slots__) - self.assertNotIn("__weakref__", A.__slots__) - a = A(1) - weakref.ref(a) - - def test_weakref_slot_without_slot(self): - with self.assertRaisesRegex(TypeError, - "weakref_slot is True but slots is False"): - @dataclass(weakref_slot=True) - class A: - a: int - - def test_weakref_slot_make_dataclass(self): - A = make_dataclass('A', [('a', int),], slots=True, weakref_slot=True) - self.assertIn("__weakref__", A.__slots__) - a = A(1) - weakref.ref(a) - - # And make sure if raises if slots=True is not given. - with self.assertRaisesRegex(TypeError, - "weakref_slot is True but slots is False"): - B = make_dataclass('B', [('a', int),], weakref_slot=True) - - def test_weakref_slot_subclass_weakref_slot(self): - @dataclass(slots=True, weakref_slot=True) - class Base: - field: int - - # A *can* also specify weakref_slot=True if it wants to (gh-93521) - @dataclass(slots=True, weakref_slot=True) - class A(Base): - ... - - # __weakref__ is in the base class, not A. But an instance of A - # is still weakref-able. - self.assertIn("__weakref__", Base.__slots__) - self.assertNotIn("__weakref__", A.__slots__) - a = A(1) - a_ref = weakref.ref(a) - self.assertIs(a.__weakref__, a_ref) - - def test_weakref_slot_subclass_no_weakref_slot(self): - @dataclass(slots=True, weakref_slot=True) - class Base: - field: int - - @dataclass(slots=True) - class A(Base): - ... - - # __weakref__ is in the base class, not A. Even though A doesn't - # specify weakref_slot, it should still be weakref-able. - self.assertIn("__weakref__", Base.__slots__) - self.assertNotIn("__weakref__", A.__slots__) - a = A(1) - a_ref = weakref.ref(a) - self.assertIs(a.__weakref__, a_ref) - - def test_weakref_slot_normal_base_weakref_slot(self): - class Base: - __slots__ = ('__weakref__',) - - @dataclass(slots=True, weakref_slot=True) - class A(Base): - field: int - - # __weakref__ is in the base class, not A. But an instance of - # A is still weakref-able. - self.assertIn("__weakref__", Base.__slots__) - self.assertNotIn("__weakref__", A.__slots__) - a = A(1) - a_ref = weakref.ref(a) - self.assertIs(a.__weakref__, a_ref) - - -class TestDescriptors(unittest.TestCase): - def test_set_name(self): - # See bpo-33141. - - # Create a descriptor. - class D: - def __set_name__(self, owner, name): - self.name = name + 'x' - def __get__(self, instance, owner): - if instance is not None: - return 1 - return self - - # This is the case of just normal descriptor behavior, no - # dataclass code is involved in initializing the descriptor. - @dataclass - class C: - c: int=D() - self.assertEqual(C.c.name, 'cx') - - # Now test with a default value and init=False, which is the - # only time this is really meaningful. If not using - # init=False, then the descriptor will be overwritten, anyway. - @dataclass - class C: - c: int=field(default=D(), init=False) - self.assertEqual(C.c.name, 'cx') - self.assertEqual(C().c, 1) - - def test_non_descriptor(self): - # PEP 487 says __set_name__ should work on non-descriptors. - # Create a descriptor. - - class D: - def __set_name__(self, owner, name): - self.name = name + 'x' - - @dataclass - class C: - c: int=field(default=D(), init=False) - self.assertEqual(C.c.name, 'cx') - - def test_lookup_on_instance(self): - # See bpo-33175. - class D: - pass - - d = D() - # Create an attribute on the instance, not type. - d.__set_name__ = Mock() - - # Make sure d.__set_name__ is not called. - @dataclass - class C: - i: int=field(default=d, init=False) - - self.assertEqual(d.__set_name__.call_count, 0) - - def test_lookup_on_class(self): - # See bpo-33175. - class D: - pass - D.__set_name__ = Mock() - - # Make sure D.__set_name__ is called. - @dataclass - class C: - i: int=field(default=D(), init=False) - - self.assertEqual(D.__set_name__.call_count, 1) - - def test_init_calls_set(self): - class D: - pass - - D.__set__ = Mock() - - @dataclass - class C: - i: D = D() - - # Make sure D.__set__ is called. - D.__set__.reset_mock() - c = C(5) - self.assertEqual(D.__set__.call_count, 1) - - def test_getting_field_calls_get(self): - class D: - pass - - D.__set__ = Mock() - D.__get__ = Mock() - - @dataclass - class C: - i: D = D() - - c = C(5) - - # Make sure D.__get__ is called. - D.__get__.reset_mock() - value = c.i - self.assertEqual(D.__get__.call_count, 1) - - def test_setting_field_calls_set(self): - class D: - pass - - D.__set__ = Mock() - - @dataclass - class C: - i: D = D() - - c = C(5) - - # Make sure D.__set__ is called. - D.__set__.reset_mock() - c.i = 10 - self.assertEqual(D.__set__.call_count, 1) - - def test_setting_uninitialized_descriptor_field(self): - class D: - pass - - D.__set__ = Mock() - - @dataclass - class C: - i: D - - # D.__set__ is not called because there's no D instance to call it on - D.__set__.reset_mock() - c = C(5) - self.assertEqual(D.__set__.call_count, 0) - - # D.__set__ still isn't called after setting i to an instance of D - # because descriptors don't behave like that when stored as instance vars - c.i = D() - c.i = 5 - self.assertEqual(D.__set__.call_count, 0) - - def test_default_value(self): - class D: - def __get__(self, instance: Any, owner: object) -> int: - if instance is None: - return 100 - - return instance._x - - def __set__(self, instance: Any, value: int) -> None: - instance._x = value - - @dataclass - class C: - i: D = D() - - c = C() - self.assertEqual(c.i, 100) - - c = C(5) - self.assertEqual(c.i, 5) - - def test_no_default_value(self): - class D: - def __get__(self, instance: Any, owner: object) -> int: - if instance is None: - raise AttributeError() - - return instance._x - - def __set__(self, instance: Any, value: int) -> None: - instance._x = value - - @dataclass - class C: - i: D = D() - - with self.assertRaisesRegex(TypeError, 'missing 1 required positional argument'): - c = C() - -class TestStringAnnotations(unittest.TestCase): - def test_classvar(self): - # Some expressions recognized as ClassVar really aren't. But - # if you're using string annotations, it's not an exact - # science. - # These tests assume that both "import typing" and "from - # typing import *" have been run in this file. - for typestr in ('ClassVar[int]', - 'ClassVar [int]', - ' ClassVar [int]', - 'ClassVar', - ' ClassVar ', - 'typing.ClassVar[int]', - 'typing.ClassVar[str]', - ' typing.ClassVar[str]', - 'typing .ClassVar[str]', - 'typing. ClassVar[str]', - 'typing.ClassVar [str]', - 'typing.ClassVar [ str]', - - # Not syntactically valid, but these will - # be treated as ClassVars. - 'typing.ClassVar.[int]', - 'typing.ClassVar+', - ): - with self.subTest(typestr=typestr): - @dataclass - class C: - x: typestr - - # x is a ClassVar, so C() takes no args. - C() - - # And it won't appear in the class's dict because it doesn't - # have a default. - self.assertNotIn('x', C.__dict__) - - def test_isnt_classvar(self): - for typestr in ('CV', - 't.ClassVar', - 't.ClassVar[int]', - 'typing..ClassVar[int]', - 'Classvar', - 'Classvar[int]', - 'typing.ClassVarx[int]', - 'typong.ClassVar[int]', - 'dataclasses.ClassVar[int]', - 'typingxClassVar[str]', - ): - with self.subTest(typestr=typestr): - @dataclass - class C: - x: typestr - - # x is not a ClassVar, so C() takes one arg. - self.assertEqual(C(10).x, 10) - - def test_initvar(self): - # These tests assume that both "import dataclasses" and "from - # dataclasses import *" have been run in this file. - for typestr in ('InitVar[int]', - 'InitVar [int]' - ' InitVar [int]', - 'InitVar', - ' InitVar ', - 'dataclasses.InitVar[int]', - 'dataclasses.InitVar[str]', - ' dataclasses.InitVar[str]', - 'dataclasses .InitVar[str]', - 'dataclasses. InitVar[str]', - 'dataclasses.InitVar [str]', - 'dataclasses.InitVar [ str]', - - # Not syntactically valid, but these will - # be treated as InitVars. - 'dataclasses.InitVar.[int]', - 'dataclasses.InitVar+', - ): - with self.subTest(typestr=typestr): - @dataclass - class C: - x: typestr - - # x is an InitVar, so doesn't create a member. - with self.assertRaisesRegex(AttributeError, - "object has no attribute 'x'"): - C(1).x - - def test_isnt_initvar(self): - for typestr in ('IV', - 'dc.InitVar', - 'xdataclasses.xInitVar', - 'typing.xInitVar[int]', - ): - with self.subTest(typestr=typestr): - @dataclass - class C: - x: typestr - - # x is not an InitVar, so there will be a member x. - self.assertEqual(C(10).x, 10) - - def test_classvar_module_level_import(self): - from test import dataclass_module_1 - from test import dataclass_module_1_str - from test import dataclass_module_2 - from test import dataclass_module_2_str - - for m in (dataclass_module_1, dataclass_module_1_str, - dataclass_module_2, dataclass_module_2_str, - ): - with self.subTest(m=m): - # There's a difference in how the ClassVars are - # interpreted when using string annotations or - # not. See the imported modules for details. - if m.USING_STRINGS: - c = m.CV(10) - else: - c = m.CV() - self.assertEqual(c.cv0, 20) - - - # There's a difference in how the InitVars are - # interpreted when using string annotations or - # not. See the imported modules for details. - c = m.IV(0, 1, 2, 3, 4) - - for field_name in ('iv0', 'iv1', 'iv2', 'iv3'): - with self.subTest(field_name=field_name): - with self.assertRaisesRegex(AttributeError, f"object has no attribute '{field_name}'"): - # Since field_name is an InitVar, it's - # not an instance field. - getattr(c, field_name) - - if m.USING_STRINGS: - # iv4 is interpreted as a normal field. - self.assertIn('not_iv4', c.__dict__) - self.assertEqual(c.not_iv4, 4) - else: - # iv4 is interpreted as an InitVar, so it - # won't exist on the instance. - self.assertNotIn('not_iv4', c.__dict__) - - def test_text_annotations(self): - from test import dataclass_textanno - - self.assertEqual( - get_type_hints(dataclass_textanno.Bar), - {'foo': dataclass_textanno.Foo}) - self.assertEqual( - get_type_hints(dataclass_textanno.Bar.__init__), - {'foo': dataclass_textanno.Foo, - 'return': type(None)}) - - -ByMakeDataClass = make_dataclass('ByMakeDataClass', [('x', int)]) -ManualModuleMakeDataClass = make_dataclass('ManualModuleMakeDataClass', - [('x', int)], - module=__name__) -WrongNameMakeDataclass = make_dataclass('Wrong', [('x', int)]) -WrongModuleMakeDataclass = make_dataclass('WrongModuleMakeDataclass', - [('x', int)], - module='custom') - -class TestMakeDataclass(unittest.TestCase): - def test_simple(self): - C = make_dataclass('C', - [('x', int), - ('y', int, field(default=5))], - namespace={'add_one': lambda self: self.x + 1}) - c = C(10) - self.assertEqual((c.x, c.y), (10, 5)) - self.assertEqual(c.add_one(), 11) - - - def test_no_mutate_namespace(self): - # Make sure a provided namespace isn't mutated. - ns = {} - C = make_dataclass('C', - [('x', int), - ('y', int, field(default=5))], - namespace=ns) - self.assertEqual(ns, {}) - - def test_base(self): - class Base1: - pass - class Base2: - pass - C = make_dataclass('C', - [('x', int)], - bases=(Base1, Base2)) - c = C(2) - self.assertIsInstance(c, C) - self.assertIsInstance(c, Base1) - self.assertIsInstance(c, Base2) - - def test_base_dataclass(self): - @dataclass - class Base1: - x: int - class Base2: - pass - C = make_dataclass('C', - [('y', int)], - bases=(Base1, Base2)) - with self.assertRaisesRegex(TypeError, 'required positional'): - c = C(2) - c = C(1, 2) - self.assertIsInstance(c, C) - self.assertIsInstance(c, Base1) - self.assertIsInstance(c, Base2) - - self.assertEqual((c.x, c.y), (1, 2)) - - def test_init_var(self): - def post_init(self, y): - self.x *= y - - C = make_dataclass('C', - [('x', int), - ('y', InitVar[int]), - ], - namespace={'__post_init__': post_init}, - ) - c = C(2, 3) - self.assertEqual(vars(c), {'x': 6}) - self.assertEqual(len(fields(c)), 1) - - def test_class_var(self): - C = make_dataclass('C', - [('x', int), - ('y', ClassVar[int], 10), - ('z', ClassVar[int], field(default=20)), - ]) - c = C(1) - self.assertEqual(vars(c), {'x': 1}) - self.assertEqual(len(fields(c)), 1) - self.assertEqual(C.y, 10) - self.assertEqual(C.z, 20) - - def test_other_params(self): - C = make_dataclass('C', - [('x', int), - ('y', ClassVar[int], 10), - ('z', ClassVar[int], field(default=20)), - ], - init=False) - # Make sure we have a repr, but no init. - self.assertNotIn('__init__', vars(C)) - self.assertIn('__repr__', vars(C)) - - # Make sure random other params don't work. - with self.assertRaisesRegex(TypeError, 'unexpected keyword argument'): - C = make_dataclass('C', - [], - xxinit=False) - - def test_no_types(self): - C = make_dataclass('Point', ['x', 'y', 'z']) - c = C(1, 2, 3) - self.assertEqual(vars(c), {'x': 1, 'y': 2, 'z': 3}) - self.assertEqual(C.__annotations__, {'x': 'typing.Any', - 'y': 'typing.Any', - 'z': 'typing.Any'}) - - C = make_dataclass('Point', ['x', ('y', int), 'z']) - c = C(1, 2, 3) - self.assertEqual(vars(c), {'x': 1, 'y': 2, 'z': 3}) - self.assertEqual(C.__annotations__, {'x': 'typing.Any', - 'y': int, - 'z': 'typing.Any'}) - - def test_module_attr(self): - self.assertEqual(ByMakeDataClass.__module__, __name__) - self.assertEqual(ByMakeDataClass(1).__module__, __name__) - self.assertEqual(WrongModuleMakeDataclass.__module__, "custom") - Nested = make_dataclass('Nested', []) - self.assertEqual(Nested.__module__, __name__) - self.assertEqual(Nested().__module__, __name__) - - def test_pickle_support(self): - for klass in [ByMakeDataClass, ManualModuleMakeDataClass]: - for proto in range(pickle.HIGHEST_PROTOCOL + 1): - with self.subTest(proto=proto): - self.assertEqual( - pickle.loads(pickle.dumps(klass, proto)), - klass, - ) - self.assertEqual( - pickle.loads(pickle.dumps(klass(1), proto)), - klass(1), - ) - - def test_cannot_be_pickled(self): - for klass in [WrongNameMakeDataclass, WrongModuleMakeDataclass]: - for proto in range(pickle.HIGHEST_PROTOCOL + 1): - with self.subTest(proto=proto): - with self.assertRaises(pickle.PickleError): - pickle.dumps(klass, proto) - with self.assertRaises(pickle.PickleError): - pickle.dumps(klass(1), proto) - - def test_invalid_type_specification(self): - for bad_field in [(), - (1, 2, 3, 4), - ]: - with self.subTest(bad_field=bad_field): - with self.assertRaisesRegex(TypeError, r'Invalid field: '): - make_dataclass('C', ['a', bad_field]) - - # And test for things with no len(). - for bad_field in [float, - lambda x:x, - ]: - with self.subTest(bad_field=bad_field): - with self.assertRaisesRegex(TypeError, r'has no len\(\)'): - make_dataclass('C', ['a', bad_field]) - - def test_duplicate_field_names(self): - for field in ['a', 'ab']: - with self.subTest(field=field): - with self.assertRaisesRegex(TypeError, 'Field name duplicated'): - make_dataclass('C', [field, 'a', field]) - - def test_keyword_field_names(self): - for field in ['for', 'async', 'await', 'as']: - with self.subTest(field=field): - with self.assertRaisesRegex(TypeError, 'must not be keywords'): - make_dataclass('C', ['a', field]) - with self.assertRaisesRegex(TypeError, 'must not be keywords'): - make_dataclass('C', [field]) - with self.assertRaisesRegex(TypeError, 'must not be keywords'): - make_dataclass('C', [field, 'a']) - - def test_non_identifier_field_names(self): - for field in ['()', 'x,y', '*', '2@3', '', 'little johnny tables']: - with self.subTest(field=field): - with self.assertRaisesRegex(TypeError, 'must be valid identifiers'): - make_dataclass('C', ['a', field]) - with self.assertRaisesRegex(TypeError, 'must be valid identifiers'): - make_dataclass('C', [field]) - with self.assertRaisesRegex(TypeError, 'must be valid identifiers'): - make_dataclass('C', [field, 'a']) - - def test_underscore_field_names(self): - # Unlike namedtuple, it's okay if dataclass field names have - # an underscore. - make_dataclass('C', ['_', '_a', 'a_a', 'a_']) - - def test_funny_class_names_names(self): - # No reason to prevent weird class names, since - # types.new_class allows them. - for classname in ['()', 'x,y', '*', '2@3', '']: - with self.subTest(classname=classname): - C = make_dataclass(classname, ['a', 'b']) - self.assertEqual(C.__name__, classname) - -class TestReplace(unittest.TestCase): - def test(self): - @dataclass(frozen=True) - class C: - x: int - y: int - - c = C(1, 2) - c1 = replace(c, x=3) - self.assertEqual(c1.x, 3) - self.assertEqual(c1.y, 2) - - def test_frozen(self): - @dataclass(frozen=True) - class C: - x: int - y: int - z: int = field(init=False, default=10) - t: int = field(init=False, default=100) - - c = C(1, 2) - c1 = replace(c, x=3) - self.assertEqual((c.x, c.y, c.z, c.t), (1, 2, 10, 100)) - self.assertEqual((c1.x, c1.y, c1.z, c1.t), (3, 2, 10, 100)) - - - with self.assertRaisesRegex(ValueError, 'init=False'): - replace(c, x=3, z=20, t=50) - with self.assertRaisesRegex(ValueError, 'init=False'): - replace(c, z=20) - replace(c, x=3, z=20, t=50) - - # Make sure the result is still frozen. - with self.assertRaisesRegex(FrozenInstanceError, "cannot assign to field 'x'"): - c1.x = 3 - - # Make sure we can't replace an attribute that doesn't exist, - # if we're also replacing one that does exist. Test this - # here, because setting attributes on frozen instances is - # handled slightly differently from non-frozen ones. - with self.assertRaisesRegex(TypeError, r"__init__\(\) got an unexpected " - "keyword argument 'a'"): - c1 = replace(c, x=20, a=5) - - def test_invalid_field_name(self): - @dataclass(frozen=True) - class C: - x: int - y: int - - c = C(1, 2) - with self.assertRaisesRegex(TypeError, r"__init__\(\) got an unexpected " - "keyword argument 'z'"): - c1 = replace(c, z=3) - - def test_invalid_object(self): - @dataclass(frozen=True) - class C: - x: int - y: int - - with self.assertRaisesRegex(TypeError, 'dataclass instance'): - replace(C, x=3) - - with self.assertRaisesRegex(TypeError, 'dataclass instance'): - replace(0, x=3) - - def test_no_init(self): - @dataclass - class C: - x: int - y: int = field(init=False, default=10) - - c = C(1) - c.y = 20 - - # Make sure y gets the default value. - c1 = replace(c, x=5) - self.assertEqual((c1.x, c1.y), (5, 10)) - - # Trying to replace y is an error. - with self.assertRaisesRegex(ValueError, 'init=False'): - replace(c, x=2, y=30) - - with self.assertRaisesRegex(ValueError, 'init=False'): - replace(c, y=30) - - def test_classvar(self): - @dataclass - class C: - x: int - y: ClassVar[int] = 1000 - - c = C(1) - d = C(2) - - self.assertIs(c.y, d.y) - self.assertEqual(c.y, 1000) - - # Trying to replace y is an error: can't replace ClassVars. - with self.assertRaisesRegex(TypeError, r"__init__\(\) got an " - "unexpected keyword argument 'y'"): - replace(c, y=30) - - replace(c, x=5) - - def test_initvar_is_specified(self): - @dataclass - class C: - x: int - y: InitVar[int] - - def __post_init__(self, y): - self.x *= y - - c = C(1, 10) - self.assertEqual(c.x, 10) - with self.assertRaisesRegex(ValueError, r"InitVar 'y' must be " - "specified with replace()"): - replace(c, x=3) - c = replace(c, x=3, y=5) - self.assertEqual(c.x, 15) - - def test_initvar_with_default_value(self): - @dataclass - class C: - x: int - y: InitVar[int] = None - z: InitVar[int] = 42 - - def __post_init__(self, y, z): - if y is not None: - self.x += y - if z is not None: - self.x += z - - c = C(x=1, y=10, z=1) - self.assertEqual(replace(c), C(x=12)) - self.assertEqual(replace(c, y=4), C(x=12, y=4, z=42)) - self.assertEqual(replace(c, y=4, z=1), C(x=12, y=4, z=1)) - - def test_recursive_repr(self): - @dataclass - class C: - f: "C" - - c = C(None) - c.f = c - self.assertEqual(repr(c), "TestReplace.test_recursive_repr..C(f=...)") - - def test_recursive_repr_two_attrs(self): - @dataclass - class C: - f: "C" - g: "C" - - c = C(None, None) - c.f = c - c.g = c - self.assertEqual(repr(c), "TestReplace.test_recursive_repr_two_attrs" - "..C(f=..., g=...)") - - def test_recursive_repr_indirection(self): - @dataclass - class C: - f: "D" - - @dataclass - class D: - f: "C" - - c = C(None) - d = D(None) - c.f = d - d.f = c - self.assertEqual(repr(c), "TestReplace.test_recursive_repr_indirection" - "..C(f=TestReplace.test_recursive_repr_indirection" - "..D(f=...))") - - def test_recursive_repr_indirection_two(self): - @dataclass - class C: - f: "D" - - @dataclass - class D: - f: "E" - - @dataclass - class E: - f: "C" - - c = C(None) - d = D(None) - e = E(None) - c.f = d - d.f = e - e.f = c - self.assertEqual(repr(c), "TestReplace.test_recursive_repr_indirection_two" - "..C(f=TestReplace.test_recursive_repr_indirection_two" - "..D(f=TestReplace.test_recursive_repr_indirection_two" - "..E(f=...)))") - - def test_recursive_repr_misc_attrs(self): - @dataclass - class C: - f: "C" - g: int - - c = C(None, 1) - c.f = c - self.assertEqual(repr(c), "TestReplace.test_recursive_repr_misc_attrs" - "..C(f=..., g=1)") - - ## def test_initvar(self): - ## @dataclass - ## class C: - ## x: int - ## y: InitVar[int] - - ## c = C(1, 10) - ## d = C(2, 20) - - ## # In our case, replacing an InitVar is a no-op - ## self.assertEqual(c, replace(c, y=5)) - - ## replace(c, x=5) - -class TestAbstract(unittest.TestCase): - def test_abc_implementation(self): - class Ordered(abc.ABC): - @abc.abstractmethod - def __lt__(self, other): - pass - - @abc.abstractmethod - def __le__(self, other): - pass - - @dataclass(order=True) - class Date(Ordered): - year: int - month: 'Month' - day: 'int' - - self.assertFalse(inspect.isabstract(Date)) - self.assertGreater(Date(2020,12,25), Date(2020,8,31)) - - def test_maintain_abc(self): - class A(abc.ABC): - @abc.abstractmethod - def foo(self): - pass - - @dataclass - class Date(A): - year: int - month: 'Month' - day: 'int' - - self.assertTrue(inspect.isabstract(Date)) - msg = "class Date without an implementation for abstract method 'foo'" - self.assertRaisesRegex(TypeError, msg, Date) - - -class TestMatchArgs(unittest.TestCase): - def test_match_args(self): - @dataclass - class C: - a: int - self.assertEqual(C(42).__match_args__, ('a',)) - - def test_explicit_match_args(self): - ma = () - @dataclass - class C: - a: int - __match_args__ = ma - self.assertIs(C(42).__match_args__, ma) - - def test_bpo_43764(self): - @dataclass(repr=False, eq=False, init=False) - class X: - a: int - b: int - c: int - self.assertEqual(X.__match_args__, ("a", "b", "c")) - - def test_match_args_argument(self): - @dataclass(match_args=False) - class X: - a: int - self.assertNotIn('__match_args__', X.__dict__) - - @dataclass(match_args=False) - class Y: - a: int - __match_args__ = ('b',) - self.assertEqual(Y.__match_args__, ('b',)) - - @dataclass(match_args=False) - class Z(Y): - z: int - self.assertEqual(Z.__match_args__, ('b',)) - - # Ensure parent dataclass __match_args__ is seen, if child class - # specifies match_args=False. - @dataclass - class A: - a: int - z: int - @dataclass(match_args=False) - class B(A): - b: int - self.assertEqual(B.__match_args__, ('a', 'z')) - - def test_make_dataclasses(self): - C = make_dataclass('C', [('x', int), ('y', int)]) - self.assertEqual(C.__match_args__, ('x', 'y')) - - C = make_dataclass('C', [('x', int), ('y', int)], match_args=True) - self.assertEqual(C.__match_args__, ('x', 'y')) - - C = make_dataclass('C', [('x', int), ('y', int)], match_args=False) - self.assertNotIn('__match__args__', C.__dict__) - - C = make_dataclass('C', [('x', int), ('y', int)], namespace={'__match_args__': ('z',)}) - self.assertEqual(C.__match_args__, ('z',)) - - -class TestKeywordArgs(unittest.TestCase): - def test_no_classvar_kwarg(self): - msg = 'field a is a ClassVar but specifies kw_only' - with self.assertRaisesRegex(TypeError, msg): - @dataclass - class A: - a: ClassVar[int] = field(kw_only=True) - - with self.assertRaisesRegex(TypeError, msg): - @dataclass - class A: - a: ClassVar[int] = field(kw_only=False) - - with self.assertRaisesRegex(TypeError, msg): - @dataclass(kw_only=True) - class A: - a: ClassVar[int] = field(kw_only=False) - - def test_field_marked_as_kwonly(self): - ####################### - # Using dataclass(kw_only=True) - @dataclass(kw_only=True) - class A: - a: int - self.assertTrue(fields(A)[0].kw_only) - - @dataclass(kw_only=True) - class A: - a: int = field(kw_only=True) - self.assertTrue(fields(A)[0].kw_only) - - @dataclass(kw_only=True) - class A: - a: int = field(kw_only=False) - self.assertFalse(fields(A)[0].kw_only) - - ####################### - # Using dataclass(kw_only=False) - @dataclass(kw_only=False) - class A: - a: int - self.assertFalse(fields(A)[0].kw_only) - - @dataclass(kw_only=False) - class A: - a: int = field(kw_only=True) - self.assertTrue(fields(A)[0].kw_only) - - @dataclass(kw_only=False) - class A: - a: int = field(kw_only=False) - self.assertFalse(fields(A)[0].kw_only) - - ####################### - # Not specifying dataclass(kw_only) - @dataclass - class A: - a: int - self.assertFalse(fields(A)[0].kw_only) - - @dataclass - class A: - a: int = field(kw_only=True) - self.assertTrue(fields(A)[0].kw_only) - - @dataclass - class A: - a: int = field(kw_only=False) - self.assertFalse(fields(A)[0].kw_only) - - def test_match_args(self): - # kw fields don't show up in __match_args__. - @dataclass(kw_only=True) - class C: - a: int - self.assertEqual(C(a=42).__match_args__, ()) - - @dataclass - class C: - a: int - b: int = field(kw_only=True) - self.assertEqual(C(42, b=10).__match_args__, ('a',)) - - def test_KW_ONLY(self): - @dataclass - class A: - a: int - _: KW_ONLY - b: int - c: int - A(3, c=5, b=4) - msg = "takes 2 positional arguments but 4 were given" - with self.assertRaisesRegex(TypeError, msg): - A(3, 4, 5) - - - @dataclass(kw_only=True) - class B: - a: int - _: KW_ONLY - b: int - c: int - B(a=3, b=4, c=5) - msg = "takes 1 positional argument but 4 were given" - with self.assertRaisesRegex(TypeError, msg): - B(3, 4, 5) - - # Explicitly make a field that follows KW_ONLY be non-keyword-only. - @dataclass - class C: - a: int - _: KW_ONLY - b: int - c: int = field(kw_only=False) - c = C(1, 2, b=3) - self.assertEqual(c.a, 1) - self.assertEqual(c.b, 3) - self.assertEqual(c.c, 2) - c = C(1, b=3, c=2) - self.assertEqual(c.a, 1) - self.assertEqual(c.b, 3) - self.assertEqual(c.c, 2) - c = C(1, b=3, c=2) - self.assertEqual(c.a, 1) - self.assertEqual(c.b, 3) - self.assertEqual(c.c, 2) - c = C(c=2, b=3, a=1) - self.assertEqual(c.a, 1) - self.assertEqual(c.b, 3) - self.assertEqual(c.c, 2) - - def test_KW_ONLY_as_string(self): - @dataclass - class A: - a: int - _: 'dataclasses.KW_ONLY' - b: int - c: int - A(3, c=5, b=4) - msg = "takes 2 positional arguments but 4 were given" - with self.assertRaisesRegex(TypeError, msg): - A(3, 4, 5) - - def test_KW_ONLY_twice(self): - msg = "'Y' is KW_ONLY, but KW_ONLY has already been specified" - - with self.assertRaisesRegex(TypeError, msg): - @dataclass - class A: - a: int - X: KW_ONLY - Y: KW_ONLY - b: int - c: int - - with self.assertRaisesRegex(TypeError, msg): - @dataclass - class A: - a: int - X: KW_ONLY - b: int - Y: KW_ONLY - c: int - - with self.assertRaisesRegex(TypeError, msg): - @dataclass - class A: - a: int - X: KW_ONLY - b: int - c: int - Y: KW_ONLY - - # But this usage is okay, since it's not using KW_ONLY. - @dataclass - class A: - a: int - _: KW_ONLY - b: int - c: int = field(kw_only=True) - - # And if inheriting, it's okay. - @dataclass - class A: - a: int - _: KW_ONLY - b: int - c: int - @dataclass - class B(A): - _: KW_ONLY - d: int - - # Make sure the error is raised in a derived class. - with self.assertRaisesRegex(TypeError, msg): - @dataclass - class A: - a: int - _: KW_ONLY - b: int - c: int - @dataclass - class B(A): - X: KW_ONLY - d: int - Y: KW_ONLY - - - def test_post_init(self): - @dataclass - class A: - a: int - _: KW_ONLY - b: InitVar[int] - c: int - d: InitVar[int] - def __post_init__(self, b, d): - raise CustomError(f'{b=} {d=}') - with self.assertRaisesRegex(CustomError, 'b=3 d=4'): - A(1, c=2, b=3, d=4) - - @dataclass - class B: - a: int - _: KW_ONLY - b: InitVar[int] - c: int - d: InitVar[int] - def __post_init__(self, b, d): - self.a = b - self.c = d - b = B(1, c=2, b=3, d=4) - self.assertEqual(asdict(b), {'a': 3, 'c': 4}) - - def test_defaults(self): - # For kwargs, make sure we can have defaults after non-defaults. - @dataclass - class A: - a: int = 0 - _: KW_ONLY - b: int - c: int = 1 - d: int - - a = A(d=4, b=3) - self.assertEqual(a.a, 0) - self.assertEqual(a.b, 3) - self.assertEqual(a.c, 1) - self.assertEqual(a.d, 4) - - # Make sure we still check for non-kwarg non-defaults not following - # defaults. - err_regex = "non-default argument 'z' follows default argument" - with self.assertRaisesRegex(TypeError, err_regex): - @dataclass - class A: - a: int = 0 - z: int - _: KW_ONLY - b: int - c: int = 1 - d: int - - def test_make_dataclass(self): - A = make_dataclass("A", ['a'], kw_only=True) - self.assertTrue(fields(A)[0].kw_only) - - B = make_dataclass("B", - ['a', ('b', int, field(kw_only=False))], - kw_only=True) - self.assertTrue(fields(B)[0].kw_only) - self.assertFalse(fields(B)[1].kw_only) - - -if __name__ == '__main__': - unittest.main() diff --git a/Lib/test/test_dataclasses/__init__.py b/Lib/test/test_dataclasses/__init__.py new file mode 100644 index 00000000000000..272d427875ae40 --- /dev/null +++ b/Lib/test/test_dataclasses/__init__.py @@ -0,0 +1,4642 @@ +# Deliberately use "from dataclasses import *". Every name in __all__ +# is tested, so they all must be present. This is a way to catch +# missing ones. + +from dataclasses import * + +import abc +import io +import pickle +import inspect +import builtins +import types +import weakref +import traceback +import unittest +from unittest.mock import Mock +from typing import ClassVar, Any, List, Union, Tuple, Dict, Generic, TypeVar, Optional, Protocol, DefaultDict +from typing import get_type_hints +from collections import deque, OrderedDict, namedtuple, defaultdict +from functools import total_ordering + +import typing # Needed for the string "typing.ClassVar[int]" to work as an annotation. +import dataclasses # Needed for the string "dataclasses.InitVar[int]" to work as an annotation. + +# Just any custom exception we can catch. +class CustomError(Exception): pass + +class TestCase(unittest.TestCase): + def test_no_fields(self): + @dataclass + class C: + pass + + o = C() + self.assertEqual(len(fields(C)), 0) + + def test_no_fields_but_member_variable(self): + @dataclass + class C: + i = 0 + + o = C() + self.assertEqual(len(fields(C)), 0) + + def test_one_field_no_default(self): + @dataclass + class C: + x: int + + o = C(42) + self.assertEqual(o.x, 42) + + def test_field_default_default_factory_error(self): + msg = "cannot specify both default and default_factory" + with self.assertRaisesRegex(ValueError, msg): + @dataclass + class C: + x: int = field(default=1, default_factory=int) + + def test_field_repr(self): + int_field = field(default=1, init=True, repr=False) + int_field.name = "id" + repr_output = repr(int_field) + expected_output = "Field(name='id',type=None," \ + f"default=1,default_factory={MISSING!r}," \ + "init=True,repr=False,hash=None," \ + "compare=True,metadata=mappingproxy({})," \ + f"kw_only={MISSING!r}," \ + "_field_type=None)" + + self.assertEqual(repr_output, expected_output) + + def test_field_recursive_repr(self): + rec_field = field() + rec_field.type = rec_field + rec_field.name = "id" + repr_output = repr(rec_field) + + self.assertIn(",type=...,", repr_output) + + def test_recursive_annotation(self): + class C: + pass + + @dataclass + class D: + C: C = field() + + self.assertIn(",type=...,", repr(D.__dataclass_fields__["C"])) + + def test_dataclass_params_repr(self): + # Even though this is testing an internal implementation detail, + # it's testing a feature we want to make sure is correctly implemented + # for the sake of dataclasses itself + @dataclass(slots=True, frozen=True) + class Some: pass + + repr_output = repr(Some.__dataclass_params__) + expected_output = "_DataclassParams(init=True,repr=True," \ + "eq=True,order=False,unsafe_hash=False,frozen=True," \ + "match_args=True,kw_only=False," \ + "slots=True,weakref_slot=False)" + self.assertEqual(repr_output, expected_output) + + def test_dataclass_params_signature(self): + # Even though this is testing an internal implementation detail, + # it's testing a feature we want to make sure is correctly implemented + # for the sake of dataclasses itself + @dataclass + class Some: pass + + for param in inspect.signature(dataclass).parameters: + if param == 'cls': + continue + self.assertTrue(hasattr(Some.__dataclass_params__, param), msg=param) + + def test_named_init_params(self): + @dataclass + class C: + x: int + + o = C(x=32) + self.assertEqual(o.x, 32) + + def test_two_fields_one_default(self): + @dataclass + class C: + x: int + y: int = 0 + + o = C(3) + self.assertEqual((o.x, o.y), (3, 0)) + + # Non-defaults following defaults. + with self.assertRaisesRegex(TypeError, + "non-default argument 'y' follows " + "default argument 'x'"): + @dataclass + class C: + x: int = 0 + y: int + + # A derived class adds a non-default field after a default one. + with self.assertRaisesRegex(TypeError, + "non-default argument 'y' follows " + "default argument 'x'"): + @dataclass + class B: + x: int = 0 + + @dataclass + class C(B): + y: int + + # Override a base class field and add a default to + # a field which didn't use to have a default. + with self.assertRaisesRegex(TypeError, + "non-default argument 'y' follows " + "default argument 'x'"): + @dataclass + class B: + x: int + y: int + + @dataclass + class C(B): + x: int = 0 + + def test_overwrite_hash(self): + # Test that declaring this class isn't an error. It should + # use the user-provided __hash__. + @dataclass(frozen=True) + class C: + x: int + def __hash__(self): + return 301 + self.assertEqual(hash(C(100)), 301) + + # Test that declaring this class isn't an error. It should + # use the generated __hash__. + @dataclass(frozen=True) + class C: + x: int + def __eq__(self, other): + return False + self.assertEqual(hash(C(100)), hash((100,))) + + # But this one should generate an exception, because with + # unsafe_hash=True, it's an error to have a __hash__ defined. + with self.assertRaisesRegex(TypeError, + 'Cannot overwrite attribute __hash__'): + @dataclass(unsafe_hash=True) + class C: + def __hash__(self): + pass + + # Creating this class should not generate an exception, + # because even though __hash__ exists before @dataclass is + # called, (due to __eq__ being defined), since it's None + # that's okay. + @dataclass(unsafe_hash=True) + class C: + x: int + def __eq__(self): + pass + # The generated hash function works as we'd expect. + self.assertEqual(hash(C(10)), hash((10,))) + + # Creating this class should generate an exception, because + # __hash__ exists and is not None, which it would be if it + # had been auto-generated due to __eq__ being defined. + with self.assertRaisesRegex(TypeError, + 'Cannot overwrite attribute __hash__'): + @dataclass(unsafe_hash=True) + class C: + x: int + def __eq__(self): + pass + def __hash__(self): + pass + + def test_overwrite_fields_in_derived_class(self): + # Note that x from C1 replaces x in Base, but the order remains + # the same as defined in Base. + @dataclass + class Base: + x: Any = 15.0 + y: int = 0 + + @dataclass + class C1(Base): + z: int = 10 + x: int = 15 + + o = Base() + self.assertEqual(repr(o), 'TestCase.test_overwrite_fields_in_derived_class..Base(x=15.0, y=0)') + + o = C1() + self.assertEqual(repr(o), 'TestCase.test_overwrite_fields_in_derived_class..C1(x=15, y=0, z=10)') + + o = C1(x=5) + self.assertEqual(repr(o), 'TestCase.test_overwrite_fields_in_derived_class..C1(x=5, y=0, z=10)') + + def test_field_named_self(self): + @dataclass + class C: + self: str + c=C('foo') + self.assertEqual(c.self, 'foo') + + # Make sure the first parameter is not named 'self'. + sig = inspect.signature(C.__init__) + first = next(iter(sig.parameters)) + self.assertNotEqual('self', first) + + # But we do use 'self' if no field named self. + @dataclass + class C: + selfx: str + + # Make sure the first parameter is named 'self'. + sig = inspect.signature(C.__init__) + first = next(iter(sig.parameters)) + self.assertEqual('self', first) + + def test_field_named_object(self): + @dataclass + class C: + object: str + c = C('foo') + self.assertEqual(c.object, 'foo') + + def test_field_named_object_frozen(self): + @dataclass(frozen=True) + class C: + object: str + c = C('foo') + self.assertEqual(c.object, 'foo') + + def test_field_named_BUILTINS_frozen(self): + # gh-96151 + @dataclass(frozen=True) + class C: + BUILTINS: int + c = C(5) + self.assertEqual(c.BUILTINS, 5) + + def test_field_with_special_single_underscore_names(self): + # gh-98886 + + @dataclass + class X: + x: int = field(default_factory=lambda: 111) + _dflt_x: int = field(default_factory=lambda: 222) + + X() + + @dataclass + class Y: + y: int = field(default_factory=lambda: 111) + _HAS_DEFAULT_FACTORY: int = 222 + + assert Y(y=222).y == 222 + + def test_field_named_like_builtin(self): + # Attribute names can shadow built-in names + # since code generation is used. + # Ensure that this is not happening. + exclusions = {'None', 'True', 'False'} + builtins_names = sorted( + b for b in builtins.__dict__.keys() + if not b.startswith('__') and b not in exclusions + ) + attributes = [(name, str) for name in builtins_names] + C = make_dataclass('C', attributes) + + c = C(*[name for name in builtins_names]) + + for name in builtins_names: + self.assertEqual(getattr(c, name), name) + + def test_field_named_like_builtin_frozen(self): + # Attribute names can shadow built-in names + # since code generation is used. + # Ensure that this is not happening + # for frozen data classes. + exclusions = {'None', 'True', 'False'} + builtins_names = sorted( + b for b in builtins.__dict__.keys() + if not b.startswith('__') and b not in exclusions + ) + attributes = [(name, str) for name in builtins_names] + C = make_dataclass('C', attributes, frozen=True) + + c = C(*[name for name in builtins_names]) + + for name in builtins_names: + self.assertEqual(getattr(c, name), name) + + def test_0_field_compare(self): + # Ensure that order=False is the default. + @dataclass + class C0: + pass + + @dataclass(order=False) + class C1: + pass + + for cls in [C0, C1]: + with self.subTest(cls=cls): + self.assertEqual(cls(), cls()) + for idx, fn in enumerate([lambda a, b: a < b, + lambda a, b: a <= b, + lambda a, b: a > b, + lambda a, b: a >= b]): + with self.subTest(idx=idx): + with self.assertRaisesRegex(TypeError, + f"not supported between instances of '{cls.__name__}' and '{cls.__name__}'"): + fn(cls(), cls()) + + @dataclass(order=True) + class C: + pass + self.assertLessEqual(C(), C()) + self.assertGreaterEqual(C(), C()) + + def test_1_field_compare(self): + # Ensure that order=False is the default. + @dataclass + class C0: + x: int + + @dataclass(order=False) + class C1: + x: int + + for cls in [C0, C1]: + with self.subTest(cls=cls): + self.assertEqual(cls(1), cls(1)) + self.assertNotEqual(cls(0), cls(1)) + for idx, fn in enumerate([lambda a, b: a < b, + lambda a, b: a <= b, + lambda a, b: a > b, + lambda a, b: a >= b]): + with self.subTest(idx=idx): + with self.assertRaisesRegex(TypeError, + f"not supported between instances of '{cls.__name__}' and '{cls.__name__}'"): + fn(cls(0), cls(0)) + + @dataclass(order=True) + class C: + x: int + self.assertLess(C(0), C(1)) + self.assertLessEqual(C(0), C(1)) + self.assertLessEqual(C(1), C(1)) + self.assertGreater(C(1), C(0)) + self.assertGreaterEqual(C(1), C(0)) + self.assertGreaterEqual(C(1), C(1)) + + def test_simple_compare(self): + # Ensure that order=False is the default. + @dataclass + class C0: + x: int + y: int + + @dataclass(order=False) + class C1: + x: int + y: int + + for cls in [C0, C1]: + with self.subTest(cls=cls): + self.assertEqual(cls(0, 0), cls(0, 0)) + self.assertEqual(cls(1, 2), cls(1, 2)) + self.assertNotEqual(cls(1, 0), cls(0, 0)) + self.assertNotEqual(cls(1, 0), cls(1, 1)) + for idx, fn in enumerate([lambda a, b: a < b, + lambda a, b: a <= b, + lambda a, b: a > b, + lambda a, b: a >= b]): + with self.subTest(idx=idx): + with self.assertRaisesRegex(TypeError, + f"not supported between instances of '{cls.__name__}' and '{cls.__name__}'"): + fn(cls(0, 0), cls(0, 0)) + + @dataclass(order=True) + class C: + x: int + y: int + + for idx, fn in enumerate([lambda a, b: a == b, + lambda a, b: a <= b, + lambda a, b: a >= b]): + with self.subTest(idx=idx): + self.assertTrue(fn(C(0, 0), C(0, 0))) + + for idx, fn in enumerate([lambda a, b: a < b, + lambda a, b: a <= b, + lambda a, b: a != b]): + with self.subTest(idx=idx): + self.assertTrue(fn(C(0, 0), C(0, 1))) + self.assertTrue(fn(C(0, 1), C(1, 0))) + self.assertTrue(fn(C(1, 0), C(1, 1))) + + for idx, fn in enumerate([lambda a, b: a > b, + lambda a, b: a >= b, + lambda a, b: a != b]): + with self.subTest(idx=idx): + self.assertTrue(fn(C(0, 1), C(0, 0))) + self.assertTrue(fn(C(1, 0), C(0, 1))) + self.assertTrue(fn(C(1, 1), C(1, 0))) + + def test_compare_subclasses(self): + # Comparisons fail for subclasses, even if no fields + # are added. + @dataclass + class B: + i: int + + @dataclass + class C(B): + pass + + for idx, (fn, expected) in enumerate([(lambda a, b: a == b, False), + (lambda a, b: a != b, True)]): + with self.subTest(idx=idx): + self.assertEqual(fn(B(0), C(0)), expected) + + for idx, fn in enumerate([lambda a, b: a < b, + lambda a, b: a <= b, + lambda a, b: a > b, + lambda a, b: a >= b]): + with self.subTest(idx=idx): + with self.assertRaisesRegex(TypeError, + "not supported between instances of 'B' and 'C'"): + fn(B(0), C(0)) + + def test_eq_order(self): + # Test combining eq and order. + for (eq, order, result ) in [ + (False, False, 'neither'), + (False, True, 'exception'), + (True, False, 'eq_only'), + (True, True, 'both'), + ]: + with self.subTest(eq=eq, order=order): + if result == 'exception': + with self.assertRaisesRegex(ValueError, 'eq must be true if order is true'): + @dataclass(eq=eq, order=order) + class C: + pass + else: + @dataclass(eq=eq, order=order) + class C: + pass + + if result == 'neither': + self.assertNotIn('__eq__', C.__dict__) + self.assertNotIn('__lt__', C.__dict__) + self.assertNotIn('__le__', C.__dict__) + self.assertNotIn('__gt__', C.__dict__) + self.assertNotIn('__ge__', C.__dict__) + elif result == 'both': + self.assertIn('__eq__', C.__dict__) + self.assertIn('__lt__', C.__dict__) + self.assertIn('__le__', C.__dict__) + self.assertIn('__gt__', C.__dict__) + self.assertIn('__ge__', C.__dict__) + elif result == 'eq_only': + self.assertIn('__eq__', C.__dict__) + self.assertNotIn('__lt__', C.__dict__) + self.assertNotIn('__le__', C.__dict__) + self.assertNotIn('__gt__', C.__dict__) + self.assertNotIn('__ge__', C.__dict__) + else: + assert False, f'unknown result {result!r}' + + def test_field_no_default(self): + @dataclass + class C: + x: int = field() + + self.assertEqual(C(5).x, 5) + + with self.assertRaisesRegex(TypeError, + r"__init__\(\) missing 1 required " + "positional argument: 'x'"): + C() + + def test_field_default(self): + default = object() + @dataclass + class C: + x: object = field(default=default) + + self.assertIs(C.x, default) + c = C(10) + self.assertEqual(c.x, 10) + + # If we delete the instance attribute, we should then see the + # class attribute. + del c.x + self.assertIs(c.x, default) + + self.assertIs(C().x, default) + + def test_not_in_repr(self): + @dataclass + class C: + x: int = field(repr=False) + with self.assertRaises(TypeError): + C() + c = C(10) + self.assertEqual(repr(c), 'TestCase.test_not_in_repr..C()') + + @dataclass + class C: + x: int = field(repr=False) + y: int + c = C(10, 20) + self.assertEqual(repr(c), 'TestCase.test_not_in_repr..C(y=20)') + + def test_not_in_compare(self): + @dataclass + class C: + x: int = 0 + y: int = field(compare=False, default=4) + + self.assertEqual(C(), C(0, 20)) + self.assertEqual(C(1, 10), C(1, 20)) + self.assertNotEqual(C(3), C(4, 10)) + self.assertNotEqual(C(3, 10), C(4, 10)) + + def test_no_unhashable_default(self): + # See bpo-44674. + class Unhashable: + __hash__ = None + + unhashable_re = 'mutable default .* for field a is not allowed' + with self.assertRaisesRegex(ValueError, unhashable_re): + @dataclass + class A: + a: dict = {} + + with self.assertRaisesRegex(ValueError, unhashable_re): + @dataclass + class A: + a: Any = Unhashable() + + # Make sure that the machinery looking for hashability is using the + # class's __hash__, not the instance's __hash__. + with self.assertRaisesRegex(ValueError, unhashable_re): + unhashable = Unhashable() + # This shouldn't make the variable hashable. + unhashable.__hash__ = lambda: 0 + @dataclass + class A: + a: Any = unhashable + + def test_hash_field_rules(self): + # Test all 6 cases of: + # hash=True/False/None + # compare=True/False + for (hash_, compare, result ) in [ + (True, False, 'field' ), + (True, True, 'field' ), + (False, False, 'absent'), + (False, True, 'absent'), + (None, False, 'absent'), + (None, True, 'field' ), + ]: + with self.subTest(hash=hash_, compare=compare): + @dataclass(unsafe_hash=True) + class C: + x: int = field(compare=compare, hash=hash_, default=5) + + if result == 'field': + # __hash__ contains the field. + self.assertEqual(hash(C(5)), hash((5,))) + elif result == 'absent': + # The field is not present in the hash. + self.assertEqual(hash(C(5)), hash(())) + else: + assert False, f'unknown result {result!r}' + + def test_init_false_no_default(self): + # If init=False and no default value, then the field won't be + # present in the instance. + @dataclass + class C: + x: int = field(init=False) + + self.assertNotIn('x', C().__dict__) + + @dataclass + class C: + x: int + y: int = 0 + z: int = field(init=False) + t: int = 10 + + self.assertNotIn('z', C(0).__dict__) + self.assertEqual(vars(C(5)), {'t': 10, 'x': 5, 'y': 0}) + + def test_class_marker(self): + @dataclass + class C: + x: int + y: str = field(init=False, default=None) + z: str = field(repr=False) + + the_fields = fields(C) + # the_fields is a tuple of 3 items, each value + # is in __annotations__. + self.assertIsInstance(the_fields, tuple) + for f in the_fields: + self.assertIs(type(f), Field) + self.assertIn(f.name, C.__annotations__) + + self.assertEqual(len(the_fields), 3) + + self.assertEqual(the_fields[0].name, 'x') + self.assertEqual(the_fields[0].type, int) + self.assertFalse(hasattr(C, 'x')) + self.assertTrue (the_fields[0].init) + self.assertTrue (the_fields[0].repr) + self.assertEqual(the_fields[1].name, 'y') + self.assertEqual(the_fields[1].type, str) + self.assertIsNone(getattr(C, 'y')) + self.assertFalse(the_fields[1].init) + self.assertTrue (the_fields[1].repr) + self.assertEqual(the_fields[2].name, 'z') + self.assertEqual(the_fields[2].type, str) + self.assertFalse(hasattr(C, 'z')) + self.assertTrue (the_fields[2].init) + self.assertFalse(the_fields[2].repr) + + def test_field_order(self): + @dataclass + class B: + a: str = 'B:a' + b: str = 'B:b' + c: str = 'B:c' + + @dataclass + class C(B): + b: str = 'C:b' + + self.assertEqual([(f.name, f.default) for f in fields(C)], + [('a', 'B:a'), + ('b', 'C:b'), + ('c', 'B:c')]) + + @dataclass + class D(B): + c: str = 'D:c' + + self.assertEqual([(f.name, f.default) for f in fields(D)], + [('a', 'B:a'), + ('b', 'B:b'), + ('c', 'D:c')]) + + @dataclass + class E(D): + a: str = 'E:a' + d: str = 'E:d' + + self.assertEqual([(f.name, f.default) for f in fields(E)], + [('a', 'E:a'), + ('b', 'B:b'), + ('c', 'D:c'), + ('d', 'E:d')]) + + def test_class_attrs(self): + # We only have a class attribute if a default value is + # specified, either directly or via a field with a default. + default = object() + @dataclass + class C: + x: int + y: int = field(repr=False) + z: object = default + t: int = field(default=100) + + self.assertFalse(hasattr(C, 'x')) + self.assertFalse(hasattr(C, 'y')) + self.assertIs (C.z, default) + self.assertEqual(C.t, 100) + + def test_disallowed_mutable_defaults(self): + # For the known types, don't allow mutable default values. + for typ, empty, non_empty in [(list, [], [1]), + (dict, {}, {0:1}), + (set, set(), set([1])), + ]: + with self.subTest(typ=typ): + # Can't use a zero-length value. + with self.assertRaisesRegex(ValueError, + f'mutable default {typ} for field ' + 'x is not allowed'): + @dataclass + class Point: + x: typ = empty + + + # Nor a non-zero-length value + with self.assertRaisesRegex(ValueError, + f'mutable default {typ} for field ' + 'y is not allowed'): + @dataclass + class Point: + y: typ = non_empty + + # Check subtypes also fail. + class Subclass(typ): pass + + with self.assertRaisesRegex(ValueError, + "mutable default .*Subclass'>" + " for field z is not allowed" + ): + @dataclass + class Point: + z: typ = Subclass() + + # Because this is a ClassVar, it can be mutable. + @dataclass + class C: + z: ClassVar[typ] = typ() + + # Because this is a ClassVar, it can be mutable. + @dataclass + class C: + x: ClassVar[typ] = Subclass() + + def test_deliberately_mutable_defaults(self): + # If a mutable default isn't in the known list of + # (list, dict, set), then it's okay. + class Mutable: + def __init__(self): + self.l = [] + + @dataclass + class C: + x: Mutable + + # These 2 instances will share this value of x. + lst = Mutable() + o1 = C(lst) + o2 = C(lst) + self.assertEqual(o1, o2) + o1.x.l.extend([1, 2]) + self.assertEqual(o1, o2) + self.assertEqual(o1.x.l, [1, 2]) + self.assertIs(o1.x, o2.x) + + def test_no_options(self): + # Call with dataclass(). + @dataclass() + class C: + x: int + + self.assertEqual(C(42).x, 42) + + def test_not_tuple(self): + # Make sure we can't be compared to a tuple. + @dataclass + class Point: + x: int + y: int + self.assertNotEqual(Point(1, 2), (1, 2)) + + # And that we can't compare to another unrelated dataclass. + @dataclass + class C: + x: int + y: int + self.assertNotEqual(Point(1, 3), C(1, 3)) + + def test_not_other_dataclass(self): + # Test that some of the problems with namedtuple don't happen + # here. + @dataclass + class Point3D: + x: int + y: int + z: int + + @dataclass + class Date: + year: int + month: int + day: int + + self.assertNotEqual(Point3D(2017, 6, 3), Date(2017, 6, 3)) + self.assertNotEqual(Point3D(1, 2, 3), (1, 2, 3)) + + # Make sure we can't unpack. + with self.assertRaisesRegex(TypeError, 'unpack'): + x, y, z = Point3D(4, 5, 6) + + # Make sure another class with the same field names isn't + # equal. + @dataclass + class Point3Dv1: + x: int = 0 + y: int = 0 + z: int = 0 + self.assertNotEqual(Point3D(0, 0, 0), Point3Dv1()) + + def test_function_annotations(self): + # Some dummy class and instance to use as a default. + class F: + pass + f = F() + + def validate_class(cls): + # First, check __annotations__, even though they're not + # function annotations. + self.assertEqual(cls.__annotations__['i'], int) + self.assertEqual(cls.__annotations__['j'], str) + self.assertEqual(cls.__annotations__['k'], F) + self.assertEqual(cls.__annotations__['l'], float) + self.assertEqual(cls.__annotations__['z'], complex) + + # Verify __init__. + + signature = inspect.signature(cls.__init__) + # Check the return type, should be None. + self.assertIs(signature.return_annotation, None) + + # Check each parameter. + params = iter(signature.parameters.values()) + param = next(params) + # This is testing an internal name, and probably shouldn't be tested. + self.assertEqual(param.name, 'self') + param = next(params) + self.assertEqual(param.name, 'i') + self.assertIs (param.annotation, int) + self.assertEqual(param.default, inspect.Parameter.empty) + self.assertEqual(param.kind, inspect.Parameter.POSITIONAL_OR_KEYWORD) + param = next(params) + self.assertEqual(param.name, 'j') + self.assertIs (param.annotation, str) + self.assertEqual(param.default, inspect.Parameter.empty) + self.assertEqual(param.kind, inspect.Parameter.POSITIONAL_OR_KEYWORD) + param = next(params) + self.assertEqual(param.name, 'k') + self.assertIs (param.annotation, F) + # Don't test for the default, since it's set to MISSING. + self.assertEqual(param.kind, inspect.Parameter.POSITIONAL_OR_KEYWORD) + param = next(params) + self.assertEqual(param.name, 'l') + self.assertIs (param.annotation, float) + # Don't test for the default, since it's set to MISSING. + self.assertEqual(param.kind, inspect.Parameter.POSITIONAL_OR_KEYWORD) + self.assertRaises(StopIteration, next, params) + + + @dataclass + class C: + i: int + j: str + k: F = f + l: float=field(default=None) + z: complex=field(default=3+4j, init=False) + + validate_class(C) + + # Now repeat with __hash__. + @dataclass(frozen=True, unsafe_hash=True) + class C: + i: int + j: str + k: F = f + l: float=field(default=None) + z: complex=field(default=3+4j, init=False) + + validate_class(C) + + def test_missing_default(self): + # Test that MISSING works the same as a default not being + # specified. + @dataclass + class C: + x: int=field(default=MISSING) + with self.assertRaisesRegex(TypeError, + r'__init__\(\) missing 1 required ' + 'positional argument'): + C() + self.assertNotIn('x', C.__dict__) + + @dataclass + class D: + x: int + with self.assertRaisesRegex(TypeError, + r'__init__\(\) missing 1 required ' + 'positional argument'): + D() + self.assertNotIn('x', D.__dict__) + + def test_missing_default_factory(self): + # Test that MISSING works the same as a default factory not + # being specified (which is really the same as a default not + # being specified, too). + @dataclass + class C: + x: int=field(default_factory=MISSING) + with self.assertRaisesRegex(TypeError, + r'__init__\(\) missing 1 required ' + 'positional argument'): + C() + self.assertNotIn('x', C.__dict__) + + @dataclass + class D: + x: int=field(default=MISSING, default_factory=MISSING) + with self.assertRaisesRegex(TypeError, + r'__init__\(\) missing 1 required ' + 'positional argument'): + D() + self.assertNotIn('x', D.__dict__) + + def test_missing_repr(self): + self.assertIn('MISSING_TYPE object', repr(MISSING)) + + def test_dont_include_other_annotations(self): + @dataclass + class C: + i: int + def foo(self) -> int: + return 4 + @property + def bar(self) -> int: + return 5 + self.assertEqual(list(C.__annotations__), ['i']) + self.assertEqual(C(10).foo(), 4) + self.assertEqual(C(10).bar, 5) + self.assertEqual(C(10).i, 10) + + def test_post_init(self): + # Just make sure it gets called + @dataclass + class C: + def __post_init__(self): + raise CustomError() + with self.assertRaises(CustomError): + C() + + @dataclass + class C: + i: int = 10 + def __post_init__(self): + if self.i == 10: + raise CustomError() + with self.assertRaises(CustomError): + C() + # post-init gets called, but doesn't raise. This is just + # checking that self is used correctly. + C(5) + + # If there's not an __init__, then post-init won't get called. + @dataclass(init=False) + class C: + def __post_init__(self): + raise CustomError() + # Creating the class won't raise + C() + + @dataclass + class C: + x: int = 0 + def __post_init__(self): + self.x *= 2 + self.assertEqual(C().x, 0) + self.assertEqual(C(2).x, 4) + + # Make sure that if we're frozen, post-init can't set + # attributes. + @dataclass(frozen=True) + class C: + x: int = 0 + def __post_init__(self): + self.x *= 2 + with self.assertRaises(FrozenInstanceError): + C() + + def test_post_init_super(self): + # Make sure super() post-init isn't called by default. + class B: + def __post_init__(self): + raise CustomError() + + @dataclass + class C(B): + def __post_init__(self): + self.x = 5 + + self.assertEqual(C().x, 5) + + # Now call super(), and it will raise. + @dataclass + class C(B): + def __post_init__(self): + super().__post_init__() + + with self.assertRaises(CustomError): + C() + + # Make sure post-init is called, even if not defined in our + # class. + @dataclass + class C(B): + pass + + with self.assertRaises(CustomError): + C() + + def test_post_init_staticmethod(self): + flag = False + @dataclass + class C: + x: int + y: int + @staticmethod + def __post_init__(): + nonlocal flag + flag = True + + self.assertFalse(flag) + c = C(3, 4) + self.assertEqual((c.x, c.y), (3, 4)) + self.assertTrue(flag) + + def test_post_init_classmethod(self): + @dataclass + class C: + flag = False + x: int + y: int + @classmethod + def __post_init__(cls): + cls.flag = True + + self.assertFalse(C.flag) + c = C(3, 4) + self.assertEqual((c.x, c.y), (3, 4)) + self.assertTrue(C.flag) + + def test_post_init_not_auto_added(self): + # See bpo-46757, which had proposed always adding __post_init__. As + # Raymond Hettinger pointed out, that would be a breaking change. So, + # add a test to make sure that the current behavior doesn't change. + + @dataclass + class A0: + pass + + @dataclass + class B0: + b_called: bool = False + def __post_init__(self): + self.b_called = True + + @dataclass + class C0(A0, B0): + c_called: bool = False + def __post_init__(self): + super().__post_init__() + self.c_called = True + + # Since A0 has no __post_init__, and one wasn't automatically added + # (because that's the rule: it's never added by @dataclass, it's only + # the class author that can add it), then B0.__post_init__ is called. + # Verify that. + c = C0() + self.assertTrue(c.b_called) + self.assertTrue(c.c_called) + + ###################################### + # Now, the same thing, except A1 defines __post_init__. + @dataclass + class A1: + def __post_init__(self): + pass + + @dataclass + class B1: + b_called: bool = False + def __post_init__(self): + self.b_called = True + + @dataclass + class C1(A1, B1): + c_called: bool = False + def __post_init__(self): + super().__post_init__() + self.c_called = True + + # This time, B1.__post_init__ isn't being called. This mimics what + # would happen if A1.__post_init__ had been automatically added, + # instead of manually added as we see here. This test isn't really + # needed, but I'm including it just to demonstrate the changed + # behavior when A1 does define __post_init__. + c = C1() + self.assertFalse(c.b_called) + self.assertTrue(c.c_called) + + def test_class_var(self): + # Make sure ClassVars are ignored in __init__, __repr__, etc. + @dataclass + class C: + x: int + y: int = 10 + z: ClassVar[int] = 1000 + w: ClassVar[int] = 2000 + t: ClassVar[int] = 3000 + s: ClassVar = 4000 + + c = C(5) + self.assertEqual(repr(c), 'TestCase.test_class_var..C(x=5, y=10)') + self.assertEqual(len(fields(C)), 2) # We have 2 fields. + self.assertEqual(len(C.__annotations__), 6) # And 4 ClassVars. + self.assertEqual(c.z, 1000) + self.assertEqual(c.w, 2000) + self.assertEqual(c.t, 3000) + self.assertEqual(c.s, 4000) + C.z += 1 + self.assertEqual(c.z, 1001) + c = C(20) + self.assertEqual((c.x, c.y), (20, 10)) + self.assertEqual(c.z, 1001) + self.assertEqual(c.w, 2000) + self.assertEqual(c.t, 3000) + self.assertEqual(c.s, 4000) + + def test_class_var_no_default(self): + # If a ClassVar has no default value, it should not be set on the class. + @dataclass + class C: + x: ClassVar[int] + + self.assertNotIn('x', C.__dict__) + + def test_class_var_default_factory(self): + # It makes no sense for a ClassVar to have a default factory. When + # would it be called? Call it yourself, since it's class-wide. + with self.assertRaisesRegex(TypeError, + 'cannot have a default factory'): + @dataclass + class C: + x: ClassVar[int] = field(default_factory=int) + + self.assertNotIn('x', C.__dict__) + + def test_class_var_with_default(self): + # If a ClassVar has a default value, it should be set on the class. + @dataclass + class C: + x: ClassVar[int] = 10 + self.assertEqual(C.x, 10) + + @dataclass + class C: + x: ClassVar[int] = field(default=10) + self.assertEqual(C.x, 10) + + def test_class_var_frozen(self): + # Make sure ClassVars work even if we're frozen. + @dataclass(frozen=True) + class C: + x: int + y: int = 10 + z: ClassVar[int] = 1000 + w: ClassVar[int] = 2000 + t: ClassVar[int] = 3000 + + c = C(5) + self.assertEqual(repr(C(5)), 'TestCase.test_class_var_frozen..C(x=5, y=10)') + self.assertEqual(len(fields(C)), 2) # We have 2 fields + self.assertEqual(len(C.__annotations__), 5) # And 3 ClassVars + self.assertEqual(c.z, 1000) + self.assertEqual(c.w, 2000) + self.assertEqual(c.t, 3000) + # We can still modify the ClassVar, it's only instances that are + # frozen. + C.z += 1 + self.assertEqual(c.z, 1001) + c = C(20) + self.assertEqual((c.x, c.y), (20, 10)) + self.assertEqual(c.z, 1001) + self.assertEqual(c.w, 2000) + self.assertEqual(c.t, 3000) + + def test_init_var_no_default(self): + # If an InitVar has no default value, it should not be set on the class. + @dataclass + class C: + x: InitVar[int] + + self.assertNotIn('x', C.__dict__) + + def test_init_var_default_factory(self): + # It makes no sense for an InitVar to have a default factory. When + # would it be called? Call it yourself, since it's class-wide. + with self.assertRaisesRegex(TypeError, + 'cannot have a default factory'): + @dataclass + class C: + x: InitVar[int] = field(default_factory=int) + + self.assertNotIn('x', C.__dict__) + + def test_init_var_with_default(self): + # If an InitVar has a default value, it should be set on the class. + @dataclass + class C: + x: InitVar[int] = 10 + self.assertEqual(C.x, 10) + + @dataclass + class C: + x: InitVar[int] = field(default=10) + self.assertEqual(C.x, 10) + + def test_init_var(self): + @dataclass + class C: + x: int = None + init_param: InitVar[int] = None + + def __post_init__(self, init_param): + if self.x is None: + self.x = init_param*2 + + c = C(init_param=10) + self.assertEqual(c.x, 20) + + def test_init_var_preserve_type(self): + self.assertEqual(InitVar[int].type, int) + + # Make sure the repr is correct. + self.assertEqual(repr(InitVar[int]), 'dataclasses.InitVar[int]') + self.assertEqual(repr(InitVar[List[int]]), + 'dataclasses.InitVar[typing.List[int]]') + self.assertEqual(repr(InitVar[list[int]]), + 'dataclasses.InitVar[list[int]]') + self.assertEqual(repr(InitVar[int|str]), + 'dataclasses.InitVar[int | str]') + + def test_init_var_inheritance(self): + # Note that this deliberately tests that a dataclass need not + # have a __post_init__ function if it has an InitVar field. + # It could just be used in a derived class, as shown here. + @dataclass + class Base: + x: int + init_base: InitVar[int] + + # We can instantiate by passing the InitVar, even though + # it's not used. + b = Base(0, 10) + self.assertEqual(vars(b), {'x': 0}) + + @dataclass + class C(Base): + y: int + init_derived: InitVar[int] + + def __post_init__(self, init_base, init_derived): + self.x = self.x + init_base + self.y = self.y + init_derived + + c = C(10, 11, 50, 51) + self.assertEqual(vars(c), {'x': 21, 'y': 101}) + + def test_default_factory(self): + # Test a factory that returns a new list. + @dataclass + class C: + x: int + y: list = field(default_factory=list) + + c0 = C(3) + c1 = C(3) + self.assertEqual(c0.x, 3) + self.assertEqual(c0.y, []) + self.assertEqual(c0, c1) + self.assertIsNot(c0.y, c1.y) + self.assertEqual(astuple(C(5, [1])), (5, [1])) + + # Test a factory that returns a shared list. + l = [] + @dataclass + class C: + x: int + y: list = field(default_factory=lambda: l) + + c0 = C(3) + c1 = C(3) + self.assertEqual(c0.x, 3) + self.assertEqual(c0.y, []) + self.assertEqual(c0, c1) + self.assertIs(c0.y, c1.y) + self.assertEqual(astuple(C(5, [1])), (5, [1])) + + # Test various other field flags. + # repr + @dataclass + class C: + x: list = field(default_factory=list, repr=False) + self.assertEqual(repr(C()), 'TestCase.test_default_factory..C()') + self.assertEqual(C().x, []) + + # hash + @dataclass(unsafe_hash=True) + class C: + x: list = field(default_factory=list, hash=False) + self.assertEqual(astuple(C()), ([],)) + self.assertEqual(hash(C()), hash(())) + + # init (see also test_default_factory_with_no_init) + @dataclass + class C: + x: list = field(default_factory=list, init=False) + self.assertEqual(astuple(C()), ([],)) + + # compare + @dataclass + class C: + x: list = field(default_factory=list, compare=False) + self.assertEqual(C(), C([1])) + + def test_default_factory_with_no_init(self): + # We need a factory with a side effect. + factory = Mock() + + @dataclass + class C: + x: list = field(default_factory=factory, init=False) + + # Make sure the default factory is called for each new instance. + C().x + self.assertEqual(factory.call_count, 1) + C().x + self.assertEqual(factory.call_count, 2) + + def test_default_factory_not_called_if_value_given(self): + # We need a factory that we can test if it's been called. + factory = Mock() + + @dataclass + class C: + x: int = field(default_factory=factory) + + # Make sure that if a field has a default factory function, + # it's not called if a value is specified. + C().x + self.assertEqual(factory.call_count, 1) + self.assertEqual(C(10).x, 10) + self.assertEqual(factory.call_count, 1) + C().x + self.assertEqual(factory.call_count, 2) + + def test_default_factory_derived(self): + # See bpo-32896. + @dataclass + class Foo: + x: dict = field(default_factory=dict) + + @dataclass + class Bar(Foo): + y: int = 1 + + self.assertEqual(Foo().x, {}) + self.assertEqual(Bar().x, {}) + self.assertEqual(Bar().y, 1) + + @dataclass + class Baz(Foo): + pass + self.assertEqual(Baz().x, {}) + + def test_intermediate_non_dataclass(self): + # Test that an intermediate class that defines + # annotations does not define fields. + + @dataclass + class A: + x: int + + class B(A): + y: int + + @dataclass + class C(B): + z: int + + c = C(1, 3) + self.assertEqual((c.x, c.z), (1, 3)) + + # .y was not initialized. + with self.assertRaisesRegex(AttributeError, + 'object has no attribute'): + c.y + + # And if we again derive a non-dataclass, no fields are added. + class D(C): + t: int + d = D(4, 5) + self.assertEqual((d.x, d.z), (4, 5)) + + def test_classvar_default_factory(self): + # It's an error for a ClassVar to have a factory function. + with self.assertRaisesRegex(TypeError, + 'cannot have a default factory'): + @dataclass + class C: + x: ClassVar[int] = field(default_factory=int) + + def test_is_dataclass(self): + class NotDataClass: + pass + + self.assertFalse(is_dataclass(0)) + self.assertFalse(is_dataclass(int)) + self.assertFalse(is_dataclass(NotDataClass)) + self.assertFalse(is_dataclass(NotDataClass())) + + @dataclass + class C: + x: int + + @dataclass + class D: + d: C + e: int + + c = C(10) + d = D(c, 4) + + self.assertTrue(is_dataclass(C)) + self.assertTrue(is_dataclass(c)) + self.assertFalse(is_dataclass(c.x)) + self.assertTrue(is_dataclass(d.d)) + self.assertFalse(is_dataclass(d.e)) + + def test_is_dataclass_when_getattr_always_returns(self): + # See bpo-37868. + class A: + def __getattr__(self, key): + return 0 + self.assertFalse(is_dataclass(A)) + a = A() + + # Also test for an instance attribute. + class B: + pass + b = B() + b.__dataclass_fields__ = [] + + for obj in a, b: + with self.subTest(obj=obj): + self.assertFalse(is_dataclass(obj)) + + # Indirect tests for _is_dataclass_instance(). + with self.assertRaisesRegex(TypeError, 'should be called on dataclass instances'): + asdict(obj) + with self.assertRaisesRegex(TypeError, 'should be called on dataclass instances'): + astuple(obj) + with self.assertRaisesRegex(TypeError, 'should be called on dataclass instances'): + replace(obj, x=0) + + def test_is_dataclass_genericalias(self): + @dataclass + class A(types.GenericAlias): + origin: type + args: type + self.assertTrue(is_dataclass(A)) + a = A(list, int) + self.assertTrue(is_dataclass(type(a))) + self.assertTrue(is_dataclass(a)) + + + def test_helper_fields_with_class_instance(self): + # Check that we can call fields() on either a class or instance, + # and get back the same thing. + @dataclass + class C: + x: int + y: float + + self.assertEqual(fields(C), fields(C(0, 0.0))) + + def test_helper_fields_exception(self): + # Check that TypeError is raised if not passed a dataclass or + # instance. + with self.assertRaisesRegex(TypeError, 'dataclass type or instance'): + fields(0) + + class C: pass + with self.assertRaisesRegex(TypeError, 'dataclass type or instance'): + fields(C) + with self.assertRaisesRegex(TypeError, 'dataclass type or instance'): + fields(C()) + + def test_clean_traceback_from_fields_exception(self): + stdout = io.StringIO() + try: + fields(object) + except TypeError as exc: + traceback.print_exception(exc, file=stdout) + printed_traceback = stdout.getvalue() + self.assertNotIn("AttributeError", printed_traceback) + self.assertNotIn("__dataclass_fields__", printed_traceback) + + def test_helper_asdict(self): + # Basic tests for asdict(), it should return a new dictionary. + @dataclass + class C: + x: int + y: int + c = C(1, 2) + + self.assertEqual(asdict(c), {'x': 1, 'y': 2}) + self.assertEqual(asdict(c), asdict(c)) + self.assertIsNot(asdict(c), asdict(c)) + c.x = 42 + self.assertEqual(asdict(c), {'x': 42, 'y': 2}) + self.assertIs(type(asdict(c)), dict) + + def test_helper_asdict_raises_on_classes(self): + # asdict() should raise on a class object. + @dataclass + class C: + x: int + y: int + with self.assertRaisesRegex(TypeError, 'dataclass instance'): + asdict(C) + with self.assertRaisesRegex(TypeError, 'dataclass instance'): + asdict(int) + + def test_helper_asdict_copy_values(self): + @dataclass + class C: + x: int + y: List[int] = field(default_factory=list) + initial = [] + c = C(1, initial) + d = asdict(c) + self.assertEqual(d['y'], initial) + self.assertIsNot(d['y'], initial) + c = C(1) + d = asdict(c) + d['y'].append(1) + self.assertEqual(c.y, []) + + def test_helper_asdict_nested(self): + @dataclass + class UserId: + token: int + group: int + @dataclass + class User: + name: str + id: UserId + u = User('Joe', UserId(123, 1)) + d = asdict(u) + self.assertEqual(d, {'name': 'Joe', 'id': {'token': 123, 'group': 1}}) + self.assertIsNot(asdict(u), asdict(u)) + u.id.group = 2 + self.assertEqual(asdict(u), {'name': 'Joe', + 'id': {'token': 123, 'group': 2}}) + + def test_helper_asdict_builtin_containers(self): + @dataclass + class User: + name: str + id: int + @dataclass + class GroupList: + id: int + users: List[User] + @dataclass + class GroupTuple: + id: int + users: Tuple[User, ...] + @dataclass + class GroupDict: + id: int + users: Dict[str, User] + a = User('Alice', 1) + b = User('Bob', 2) + gl = GroupList(0, [a, b]) + gt = GroupTuple(0, (a, b)) + gd = GroupDict(0, {'first': a, 'second': b}) + self.assertEqual(asdict(gl), {'id': 0, 'users': [{'name': 'Alice', 'id': 1}, + {'name': 'Bob', 'id': 2}]}) + self.assertEqual(asdict(gt), {'id': 0, 'users': ({'name': 'Alice', 'id': 1}, + {'name': 'Bob', 'id': 2})}) + self.assertEqual(asdict(gd), {'id': 0, 'users': {'first': {'name': 'Alice', 'id': 1}, + 'second': {'name': 'Bob', 'id': 2}}}) + + def test_helper_asdict_builtin_object_containers(self): + @dataclass + class Child: + d: object + + @dataclass + class Parent: + child: Child + + self.assertEqual(asdict(Parent(Child([1]))), {'child': {'d': [1]}}) + self.assertEqual(asdict(Parent(Child({1: 2}))), {'child': {'d': {1: 2}}}) + + def test_helper_asdict_factory(self): + @dataclass + class C: + x: int + y: int + c = C(1, 2) + d = asdict(c, dict_factory=OrderedDict) + self.assertEqual(d, OrderedDict([('x', 1), ('y', 2)])) + self.assertIsNot(d, asdict(c, dict_factory=OrderedDict)) + c.x = 42 + d = asdict(c, dict_factory=OrderedDict) + self.assertEqual(d, OrderedDict([('x', 42), ('y', 2)])) + self.assertIs(type(d), OrderedDict) + + def test_helper_asdict_namedtuple(self): + T = namedtuple('T', 'a b c') + @dataclass + class C: + x: str + y: T + c = C('outer', T(1, C('inner', T(11, 12, 13)), 2)) + + d = asdict(c) + self.assertEqual(d, {'x': 'outer', + 'y': T(1, + {'x': 'inner', + 'y': T(11, 12, 13)}, + 2), + } + ) + + # Now with a dict_factory. OrderedDict is convenient, but + # since it compares to dicts, we also need to have separate + # assertIs tests. + d = asdict(c, dict_factory=OrderedDict) + self.assertEqual(d, {'x': 'outer', + 'y': T(1, + {'x': 'inner', + 'y': T(11, 12, 13)}, + 2), + } + ) + + # Make sure that the returned dicts are actually OrderedDicts. + self.assertIs(type(d), OrderedDict) + self.assertIs(type(d['y'][1]), OrderedDict) + + def test_helper_asdict_namedtuple_key(self): + # Ensure that a field that contains a dict which has a + # namedtuple as a key works with asdict(). + + @dataclass + class C: + f: dict + T = namedtuple('T', 'a') + + c = C({T('an a'): 0}) + + self.assertEqual(asdict(c), {'f': {T(a='an a'): 0}}) + + def test_helper_asdict_namedtuple_derived(self): + class T(namedtuple('Tbase', 'a')): + def my_a(self): + return self.a + + @dataclass + class C: + f: T + + t = T(6) + c = C(t) + + d = asdict(c) + self.assertEqual(d, {'f': T(a=6)}) + # Make sure that t has been copied, not used directly. + self.assertIsNot(d['f'], t) + self.assertEqual(d['f'].my_a(), 6) + + def test_helper_asdict_defaultdict(self): + # Ensure asdict() does not throw exceptions when a + # defaultdict is a member of a dataclass + @dataclass + class C: + mp: DefaultDict[str, List] + + dd = defaultdict(list) + dd["x"].append(12) + c = C(mp=dd) + d = asdict(c) + + self.assertEqual(d, {"mp": {"x": [12]}}) + self.assertTrue(d["mp"] is not c.mp) # make sure defaultdict is copied + + def test_helper_astuple(self): + # Basic tests for astuple(), it should return a new tuple. + @dataclass + class C: + x: int + y: int = 0 + c = C(1) + + self.assertEqual(astuple(c), (1, 0)) + self.assertEqual(astuple(c), astuple(c)) + self.assertIsNot(astuple(c), astuple(c)) + c.y = 42 + self.assertEqual(astuple(c), (1, 42)) + self.assertIs(type(astuple(c)), tuple) + + def test_helper_astuple_raises_on_classes(self): + # astuple() should raise on a class object. + @dataclass + class C: + x: int + y: int + with self.assertRaisesRegex(TypeError, 'dataclass instance'): + astuple(C) + with self.assertRaisesRegex(TypeError, 'dataclass instance'): + astuple(int) + + def test_helper_astuple_copy_values(self): + @dataclass + class C: + x: int + y: List[int] = field(default_factory=list) + initial = [] + c = C(1, initial) + t = astuple(c) + self.assertEqual(t[1], initial) + self.assertIsNot(t[1], initial) + c = C(1) + t = astuple(c) + t[1].append(1) + self.assertEqual(c.y, []) + + def test_helper_astuple_nested(self): + @dataclass + class UserId: + token: int + group: int + @dataclass + class User: + name: str + id: UserId + u = User('Joe', UserId(123, 1)) + t = astuple(u) + self.assertEqual(t, ('Joe', (123, 1))) + self.assertIsNot(astuple(u), astuple(u)) + u.id.group = 2 + self.assertEqual(astuple(u), ('Joe', (123, 2))) + + def test_helper_astuple_builtin_containers(self): + @dataclass + class User: + name: str + id: int + @dataclass + class GroupList: + id: int + users: List[User] + @dataclass + class GroupTuple: + id: int + users: Tuple[User, ...] + @dataclass + class GroupDict: + id: int + users: Dict[str, User] + a = User('Alice', 1) + b = User('Bob', 2) + gl = GroupList(0, [a, b]) + gt = GroupTuple(0, (a, b)) + gd = GroupDict(0, {'first': a, 'second': b}) + self.assertEqual(astuple(gl), (0, [('Alice', 1), ('Bob', 2)])) + self.assertEqual(astuple(gt), (0, (('Alice', 1), ('Bob', 2)))) + self.assertEqual(astuple(gd), (0, {'first': ('Alice', 1), 'second': ('Bob', 2)})) + + def test_helper_astuple_builtin_object_containers(self): + @dataclass + class Child: + d: object + + @dataclass + class Parent: + child: Child + + self.assertEqual(astuple(Parent(Child([1]))), (([1],),)) + self.assertEqual(astuple(Parent(Child({1: 2}))), (({1: 2},),)) + + def test_helper_astuple_factory(self): + @dataclass + class C: + x: int + y: int + NT = namedtuple('NT', 'x y') + def nt(lst): + return NT(*lst) + c = C(1, 2) + t = astuple(c, tuple_factory=nt) + self.assertEqual(t, NT(1, 2)) + self.assertIsNot(t, astuple(c, tuple_factory=nt)) + c.x = 42 + t = astuple(c, tuple_factory=nt) + self.assertEqual(t, NT(42, 2)) + self.assertIs(type(t), NT) + + def test_helper_astuple_namedtuple(self): + T = namedtuple('T', 'a b c') + @dataclass + class C: + x: str + y: T + c = C('outer', T(1, C('inner', T(11, 12, 13)), 2)) + + t = astuple(c) + self.assertEqual(t, ('outer', T(1, ('inner', (11, 12, 13)), 2))) + + # Now, using a tuple_factory. list is convenient here. + t = astuple(c, tuple_factory=list) + self.assertEqual(t, ['outer', T(1, ['inner', T(11, 12, 13)], 2)]) + + def test_helper_astuple_defaultdict(self): + # Ensure astuple() does not throw exceptions when a + # defaultdict is a member of a dataclass + @dataclass + class C: + mp: DefaultDict[str, List] + + dd = defaultdict(list) + dd["x"].append(12) + c = C(mp=dd) + t = astuple(c) + + self.assertEqual(t, ({"x": [12]},)) + self.assertTrue(t[0] is not dd) # make sure defaultdict is copied + + def test_dynamic_class_creation(self): + cls_dict = {'__annotations__': {'x': int, 'y': int}, + } + + # Create the class. + cls = type('C', (), cls_dict) + + # Make it a dataclass. + cls1 = dataclass(cls) + + self.assertEqual(cls1, cls) + self.assertEqual(asdict(cls(1, 2)), {'x': 1, 'y': 2}) + + def test_dynamic_class_creation_using_field(self): + cls_dict = {'__annotations__': {'x': int, 'y': int}, + 'y': field(default=5), + } + + # Create the class. + cls = type('C', (), cls_dict) + + # Make it a dataclass. + cls1 = dataclass(cls) + + self.assertEqual(cls1, cls) + self.assertEqual(asdict(cls1(1)), {'x': 1, 'y': 5}) + + def test_init_in_order(self): + @dataclass + class C: + a: int + b: int = field() + c: list = field(default_factory=list, init=False) + d: list = field(default_factory=list) + e: int = field(default=4, init=False) + f: int = 4 + + calls = [] + def setattr(self, name, value): + calls.append((name, value)) + + C.__setattr__ = setattr + c = C(0, 1) + self.assertEqual(('a', 0), calls[0]) + self.assertEqual(('b', 1), calls[1]) + self.assertEqual(('c', []), calls[2]) + self.assertEqual(('d', []), calls[3]) + self.assertNotIn(('e', 4), calls) + self.assertEqual(('f', 4), calls[4]) + + def test_items_in_dicts(self): + @dataclass + class C: + a: int + b: list = field(default_factory=list, init=False) + c: list = field(default_factory=list) + d: int = field(default=4, init=False) + e: int = 0 + + c = C(0) + # Class dict + self.assertNotIn('a', C.__dict__) + self.assertNotIn('b', C.__dict__) + self.assertNotIn('c', C.__dict__) + self.assertIn('d', C.__dict__) + self.assertEqual(C.d, 4) + self.assertIn('e', C.__dict__) + self.assertEqual(C.e, 0) + # Instance dict + self.assertIn('a', c.__dict__) + self.assertEqual(c.a, 0) + self.assertIn('b', c.__dict__) + self.assertEqual(c.b, []) + self.assertIn('c', c.__dict__) + self.assertEqual(c.c, []) + self.assertNotIn('d', c.__dict__) + self.assertIn('e', c.__dict__) + self.assertEqual(c.e, 0) + + def test_alternate_classmethod_constructor(self): + # Since __post_init__ can't take params, use a classmethod + # alternate constructor. This is mostly an example to show + # how to use this technique. + @dataclass + class C: + x: int + @classmethod + def from_file(cls, filename): + # In a real example, create a new instance + # and populate 'x' from contents of a file. + value_in_file = 20 + return cls(value_in_file) + + self.assertEqual(C.from_file('filename').x, 20) + + def test_field_metadata_default(self): + # Make sure the default metadata is read-only and of + # zero length. + @dataclass + class C: + i: int + + self.assertFalse(fields(C)[0].metadata) + self.assertEqual(len(fields(C)[0].metadata), 0) + with self.assertRaisesRegex(TypeError, + 'does not support item assignment'): + fields(C)[0].metadata['test'] = 3 + + def test_field_metadata_mapping(self): + # Make sure only a mapping can be passed as metadata + # zero length. + with self.assertRaises(TypeError): + @dataclass + class C: + i: int = field(metadata=0) + + # Make sure an empty dict works. + d = {} + @dataclass + class C: + i: int = field(metadata=d) + self.assertFalse(fields(C)[0].metadata) + self.assertEqual(len(fields(C)[0].metadata), 0) + # Update should work (see bpo-35960). + d['foo'] = 1 + self.assertEqual(len(fields(C)[0].metadata), 1) + self.assertEqual(fields(C)[0].metadata['foo'], 1) + with self.assertRaisesRegex(TypeError, + 'does not support item assignment'): + fields(C)[0].metadata['test'] = 3 + + # Make sure a non-empty dict works. + d = {'test': 10, 'bar': '42', 3: 'three'} + @dataclass + class C: + i: int = field(metadata=d) + self.assertEqual(len(fields(C)[0].metadata), 3) + self.assertEqual(fields(C)[0].metadata['test'], 10) + self.assertEqual(fields(C)[0].metadata['bar'], '42') + self.assertEqual(fields(C)[0].metadata[3], 'three') + # Update should work. + d['foo'] = 1 + self.assertEqual(len(fields(C)[0].metadata), 4) + self.assertEqual(fields(C)[0].metadata['foo'], 1) + with self.assertRaises(KeyError): + # Non-existent key. + fields(C)[0].metadata['baz'] + with self.assertRaisesRegex(TypeError, + 'does not support item assignment'): + fields(C)[0].metadata['test'] = 3 + + def test_field_metadata_custom_mapping(self): + # Try a custom mapping. + class SimpleNameSpace: + def __init__(self, **kw): + self.__dict__.update(kw) + + def __getitem__(self, item): + if item == 'xyzzy': + return 'plugh' + return getattr(self, item) + + def __len__(self): + return self.__dict__.__len__() + + @dataclass + class C: + i: int = field(metadata=SimpleNameSpace(a=10)) + + self.assertEqual(len(fields(C)[0].metadata), 1) + self.assertEqual(fields(C)[0].metadata['a'], 10) + with self.assertRaises(AttributeError): + fields(C)[0].metadata['b'] + # Make sure we're still talking to our custom mapping. + self.assertEqual(fields(C)[0].metadata['xyzzy'], 'plugh') + + def test_generic_dataclasses(self): + T = TypeVar('T') + + @dataclass + class LabeledBox(Generic[T]): + content: T + label: str = '' + + box = LabeledBox(42) + self.assertEqual(box.content, 42) + self.assertEqual(box.label, '') + + # Subscripting the resulting class should work, etc. + Alias = List[LabeledBox[int]] + + def test_generic_extending(self): + S = TypeVar('S') + T = TypeVar('T') + + @dataclass + class Base(Generic[T, S]): + x: T + y: S + + @dataclass + class DataDerived(Base[int, T]): + new_field: str + Alias = DataDerived[str] + c = Alias(0, 'test1', 'test2') + self.assertEqual(astuple(c), (0, 'test1', 'test2')) + + class NonDataDerived(Base[int, T]): + def new_method(self): + return self.y + Alias = NonDataDerived[float] + c = Alias(10, 1.0) + self.assertEqual(c.new_method(), 1.0) + + def test_generic_dynamic(self): + T = TypeVar('T') + + @dataclass + class Parent(Generic[T]): + x: T + Child = make_dataclass('Child', [('y', T), ('z', Optional[T], None)], + bases=(Parent[int], Generic[T]), namespace={'other': 42}) + self.assertIs(Child[int](1, 2).z, None) + self.assertEqual(Child[int](1, 2, 3).z, 3) + self.assertEqual(Child[int](1, 2, 3).other, 42) + # Check that type aliases work correctly. + Alias = Child[T] + self.assertEqual(Alias[int](1, 2).x, 1) + # Check MRO resolution. + self.assertEqual(Child.__mro__, (Child, Parent, Generic, object)) + + def test_dataclasses_pickleable(self): + global P, Q, R + @dataclass + class P: + x: int + y: int = 0 + @dataclass + class Q: + x: int + y: int = field(default=0, init=False) + @dataclass + class R: + x: int + y: List[int] = field(default_factory=list) + q = Q(1) + q.y = 2 + samples = [P(1), P(1, 2), Q(1), q, R(1), R(1, [2, 3, 4])] + for sample in samples: + for proto in range(pickle.HIGHEST_PROTOCOL + 1): + with self.subTest(sample=sample, proto=proto): + new_sample = pickle.loads(pickle.dumps(sample, proto)) + self.assertEqual(sample.x, new_sample.x) + self.assertEqual(sample.y, new_sample.y) + self.assertIsNot(sample, new_sample) + new_sample.x = 42 + another_new_sample = pickle.loads(pickle.dumps(new_sample, proto)) + self.assertEqual(new_sample.x, another_new_sample.x) + self.assertEqual(sample.y, another_new_sample.y) + + def test_dataclasses_qualnames(self): + @dataclass(order=True, unsafe_hash=True, frozen=True) + class A: + x: int + y: int + + self.assertEqual(A.__init__.__name__, "__init__") + for function in ( + '__eq__', + '__lt__', + '__le__', + '__gt__', + '__ge__', + '__hash__', + '__init__', + '__repr__', + '__setattr__', + '__delattr__', + ): + self.assertEqual(getattr(A, function).__qualname__, f"TestCase.test_dataclasses_qualnames..A.{function}") + + with self.assertRaisesRegex(TypeError, r"A\.__init__\(\) missing"): + A() + + +class TestFieldNoAnnotation(unittest.TestCase): + def test_field_without_annotation(self): + with self.assertRaisesRegex(TypeError, + "'f' is a field but has no type annotation"): + @dataclass + class C: + f = field() + + def test_field_without_annotation_but_annotation_in_base(self): + @dataclass + class B: + f: int + + with self.assertRaisesRegex(TypeError, + "'f' is a field but has no type annotation"): + # This is still an error: make sure we don't pick up the + # type annotation in the base class. + @dataclass + class C(B): + f = field() + + def test_field_without_annotation_but_annotation_in_base_not_dataclass(self): + # Same test, but with the base class not a dataclass. + class B: + f: int + + with self.assertRaisesRegex(TypeError, + "'f' is a field but has no type annotation"): + # This is still an error: make sure we don't pick up the + # type annotation in the base class. + @dataclass + class C(B): + f = field() + + +class TestDocString(unittest.TestCase): + def assertDocStrEqual(self, a, b): + # Because 3.6 and 3.7 differ in how inspect.signature work + # (see bpo #32108), for the time being just compare them with + # whitespace stripped. + self.assertEqual(a.replace(' ', ''), b.replace(' ', '')) + + def test_existing_docstring_not_overridden(self): + @dataclass + class C: + """Lorem ipsum""" + x: int + + self.assertEqual(C.__doc__, "Lorem ipsum") + + def test_docstring_no_fields(self): + @dataclass + class C: + pass + + self.assertDocStrEqual(C.__doc__, "C()") + + def test_docstring_one_field(self): + @dataclass + class C: + x: int + + self.assertDocStrEqual(C.__doc__, "C(x:int)") + + def test_docstring_two_fields(self): + @dataclass + class C: + x: int + y: int + + self.assertDocStrEqual(C.__doc__, "C(x:int, y:int)") + + def test_docstring_three_fields(self): + @dataclass + class C: + x: int + y: int + z: str + + self.assertDocStrEqual(C.__doc__, "C(x:int, y:int, z:str)") + + def test_docstring_one_field_with_default(self): + @dataclass + class C: + x: int = 3 + + self.assertDocStrEqual(C.__doc__, "C(x:int=3)") + + def test_docstring_one_field_with_default_none(self): + @dataclass + class C: + x: Union[int, type(None)] = None + + self.assertDocStrEqual(C.__doc__, "C(x:Optional[int]=None)") + + def test_docstring_list_field(self): + @dataclass + class C: + x: List[int] + + self.assertDocStrEqual(C.__doc__, "C(x:List[int])") + + def test_docstring_list_field_with_default_factory(self): + @dataclass + class C: + x: List[int] = field(default_factory=list) + + self.assertDocStrEqual(C.__doc__, "C(x:List[int]=)") + + def test_docstring_deque_field(self): + @dataclass + class C: + x: deque + + self.assertDocStrEqual(C.__doc__, "C(x:collections.deque)") + + def test_docstring_deque_field_with_default_factory(self): + @dataclass + class C: + x: deque = field(default_factory=deque) + + self.assertDocStrEqual(C.__doc__, "C(x:collections.deque=)") + + def test_docstring_with_no_signature(self): + # See https://github.com/python/cpython/issues/103449 + class Meta(type): + __call__ = dict + class Base(metaclass=Meta): + pass + + @dataclass + class C(Base): + pass + + self.assertDocStrEqual(C.__doc__, "C") + + +class TestInit(unittest.TestCase): + def test_base_has_init(self): + class B: + def __init__(self): + self.z = 100 + + # Make sure that declaring this class doesn't raise an error. + # The issue is that we can't override __init__ in our class, + # but it should be okay to add __init__ to us if our base has + # an __init__. + @dataclass + class C(B): + x: int = 0 + c = C(10) + self.assertEqual(c.x, 10) + self.assertNotIn('z', vars(c)) + + # Make sure that if we don't add an init, the base __init__ + # gets called. + @dataclass(init=False) + class C(B): + x: int = 10 + c = C() + self.assertEqual(c.x, 10) + self.assertEqual(c.z, 100) + + def test_no_init(self): + @dataclass(init=False) + class C: + i: int = 0 + self.assertEqual(C().i, 0) + + @dataclass(init=False) + class C: + i: int = 2 + def __init__(self): + self.i = 3 + self.assertEqual(C().i, 3) + + def test_overwriting_init(self): + # If the class has __init__, use it no matter the value of + # init=. + + @dataclass + class C: + x: int + def __init__(self, x): + self.x = 2 * x + self.assertEqual(C(3).x, 6) + + @dataclass(init=True) + class C: + x: int + def __init__(self, x): + self.x = 2 * x + self.assertEqual(C(4).x, 8) + + @dataclass(init=False) + class C: + x: int + def __init__(self, x): + self.x = 2 * x + self.assertEqual(C(5).x, 10) + + def test_inherit_from_protocol(self): + # Dataclasses inheriting from protocol should preserve their own `__init__`. + # See bpo-45081. + + class P(Protocol): + a: int + + @dataclass + class C(P): + a: int + + self.assertEqual(C(5).a, 5) + + @dataclass + class D(P): + def __init__(self, a): + self.a = a * 2 + + self.assertEqual(D(5).a, 10) + + +class TestRepr(unittest.TestCase): + def test_repr(self): + @dataclass + class B: + x: int + + @dataclass + class C(B): + y: int = 10 + + o = C(4) + self.assertEqual(repr(o), 'TestRepr.test_repr..C(x=4, y=10)') + + @dataclass + class D(C): + x: int = 20 + self.assertEqual(repr(D()), 'TestRepr.test_repr..D(x=20, y=10)') + + @dataclass + class C: + @dataclass + class D: + i: int + @dataclass + class E: + pass + self.assertEqual(repr(C.D(0)), 'TestRepr.test_repr..C.D(i=0)') + self.assertEqual(repr(C.E()), 'TestRepr.test_repr..C.E()') + + def test_no_repr(self): + # Test a class with no __repr__ and repr=False. + @dataclass(repr=False) + class C: + x: int + self.assertIn(f'{__name__}.TestRepr.test_no_repr..C object at', + repr(C(3))) + + # Test a class with a __repr__ and repr=False. + @dataclass(repr=False) + class C: + x: int + def __repr__(self): + return 'C-class' + self.assertEqual(repr(C(3)), 'C-class') + + def test_overwriting_repr(self): + # If the class has __repr__, use it no matter the value of + # repr=. + + @dataclass + class C: + x: int + def __repr__(self): + return 'x' + self.assertEqual(repr(C(0)), 'x') + + @dataclass(repr=True) + class C: + x: int + def __repr__(self): + return 'x' + self.assertEqual(repr(C(0)), 'x') + + @dataclass(repr=False) + class C: + x: int + def __repr__(self): + return 'x' + self.assertEqual(repr(C(0)), 'x') + + +class TestEq(unittest.TestCase): + def test_no_eq(self): + # Test a class with no __eq__ and eq=False. + @dataclass(eq=False) + class C: + x: int + self.assertNotEqual(C(0), C(0)) + c = C(3) + self.assertEqual(c, c) + + # Test a class with an __eq__ and eq=False. + @dataclass(eq=False) + class C: + x: int + def __eq__(self, other): + return other == 10 + self.assertEqual(C(3), 10) + + def test_overwriting_eq(self): + # If the class has __eq__, use it no matter the value of + # eq=. + + @dataclass + class C: + x: int + def __eq__(self, other): + return other == 3 + self.assertEqual(C(1), 3) + self.assertNotEqual(C(1), 1) + + @dataclass(eq=True) + class C: + x: int + def __eq__(self, other): + return other == 4 + self.assertEqual(C(1), 4) + self.assertNotEqual(C(1), 1) + + @dataclass(eq=False) + class C: + x: int + def __eq__(self, other): + return other == 5 + self.assertEqual(C(1), 5) + self.assertNotEqual(C(1), 1) + + +class TestOrdering(unittest.TestCase): + def test_functools_total_ordering(self): + # Test that functools.total_ordering works with this class. + @total_ordering + @dataclass + class C: + x: int + def __lt__(self, other): + # Perform the test "backward", just to make + # sure this is being called. + return self.x >= other + + self.assertLess(C(0), -1) + self.assertLessEqual(C(0), -1) + self.assertGreater(C(0), 1) + self.assertGreaterEqual(C(0), 1) + + def test_no_order(self): + # Test that no ordering functions are added by default. + @dataclass(order=False) + class C: + x: int + # Make sure no order methods are added. + self.assertNotIn('__le__', C.__dict__) + self.assertNotIn('__lt__', C.__dict__) + self.assertNotIn('__ge__', C.__dict__) + self.assertNotIn('__gt__', C.__dict__) + + # Test that __lt__ is still called + @dataclass(order=False) + class C: + x: int + def __lt__(self, other): + return False + # Make sure other methods aren't added. + self.assertNotIn('__le__', C.__dict__) + self.assertNotIn('__ge__', C.__dict__) + self.assertNotIn('__gt__', C.__dict__) + + def test_overwriting_order(self): + with self.assertRaisesRegex(TypeError, + 'Cannot overwrite attribute __lt__' + '.*using functools.total_ordering'): + @dataclass(order=True) + class C: + x: int + def __lt__(self): + pass + + with self.assertRaisesRegex(TypeError, + 'Cannot overwrite attribute __le__' + '.*using functools.total_ordering'): + @dataclass(order=True) + class C: + x: int + def __le__(self): + pass + + with self.assertRaisesRegex(TypeError, + 'Cannot overwrite attribute __gt__' + '.*using functools.total_ordering'): + @dataclass(order=True) + class C: + x: int + def __gt__(self): + pass + + with self.assertRaisesRegex(TypeError, + 'Cannot overwrite attribute __ge__' + '.*using functools.total_ordering'): + @dataclass(order=True) + class C: + x: int + def __ge__(self): + pass + +class TestHash(unittest.TestCase): + def test_unsafe_hash(self): + @dataclass(unsafe_hash=True) + class C: + x: int + y: str + self.assertEqual(hash(C(1, 'foo')), hash((1, 'foo'))) + + def test_hash_rules(self): + def non_bool(value): + # Map to something else that's True, but not a bool. + if value is None: + return None + if value: + return (3,) + return 0 + + def test(case, unsafe_hash, eq, frozen, with_hash, result): + with self.subTest(case=case, unsafe_hash=unsafe_hash, eq=eq, + frozen=frozen): + if result != 'exception': + if with_hash: + @dataclass(unsafe_hash=unsafe_hash, eq=eq, frozen=frozen) + class C: + def __hash__(self): + return 0 + else: + @dataclass(unsafe_hash=unsafe_hash, eq=eq, frozen=frozen) + class C: + pass + + # See if the result matches what's expected. + if result == 'fn': + # __hash__ contains the function we generated. + self.assertIn('__hash__', C.__dict__) + self.assertIsNotNone(C.__dict__['__hash__']) + + elif result == '': + # __hash__ is not present in our class. + if not with_hash: + self.assertNotIn('__hash__', C.__dict__) + + elif result == 'none': + # __hash__ is set to None. + self.assertIn('__hash__', C.__dict__) + self.assertIsNone(C.__dict__['__hash__']) + + elif result == 'exception': + # Creating the class should cause an exception. + # This only happens with with_hash==True. + assert(with_hash) + with self.assertRaisesRegex(TypeError, 'Cannot overwrite attribute __hash__'): + @dataclass(unsafe_hash=unsafe_hash, eq=eq, frozen=frozen) + class C: + def __hash__(self): + return 0 + + else: + assert False, f'unknown result {result!r}' + + # There are 8 cases of: + # unsafe_hash=True/False + # eq=True/False + # frozen=True/False + # And for each of these, a different result if + # __hash__ is defined or not. + for case, (unsafe_hash, eq, frozen, res_no_defined_hash, res_defined_hash) in enumerate([ + (False, False, False, '', ''), + (False, False, True, '', ''), + (False, True, False, 'none', ''), + (False, True, True, 'fn', ''), + (True, False, False, 'fn', 'exception'), + (True, False, True, 'fn', 'exception'), + (True, True, False, 'fn', 'exception'), + (True, True, True, 'fn', 'exception'), + ], 1): + test(case, unsafe_hash, eq, frozen, False, res_no_defined_hash) + test(case, unsafe_hash, eq, frozen, True, res_defined_hash) + + # Test non-bool truth values, too. This is just to + # make sure the data-driven table in the decorator + # handles non-bool values. + test(case, non_bool(unsafe_hash), non_bool(eq), non_bool(frozen), False, res_no_defined_hash) + test(case, non_bool(unsafe_hash), non_bool(eq), non_bool(frozen), True, res_defined_hash) + + + def test_eq_only(self): + # If a class defines __eq__, __hash__ is automatically added + # and set to None. This is normal Python behavior, not + # related to dataclasses. Make sure we don't interfere with + # that (see bpo=32546). + + @dataclass + class C: + i: int + def __eq__(self, other): + return self.i == other.i + self.assertEqual(C(1), C(1)) + self.assertNotEqual(C(1), C(4)) + + # And make sure things work in this case if we specify + # unsafe_hash=True. + @dataclass(unsafe_hash=True) + class C: + i: int + def __eq__(self, other): + return self.i == other.i + self.assertEqual(C(1), C(1.0)) + self.assertEqual(hash(C(1)), hash(C(1.0))) + + # And check that the classes __eq__ is being used, despite + # specifying eq=True. + @dataclass(unsafe_hash=True, eq=True) + class C: + i: int + def __eq__(self, other): + return self.i == 3 and self.i == other.i + self.assertEqual(C(3), C(3)) + self.assertNotEqual(C(1), C(1)) + self.assertEqual(hash(C(1)), hash(C(1.0))) + + def test_0_field_hash(self): + @dataclass(frozen=True) + class C: + pass + self.assertEqual(hash(C()), hash(())) + + @dataclass(unsafe_hash=True) + class C: + pass + self.assertEqual(hash(C()), hash(())) + + def test_1_field_hash(self): + @dataclass(frozen=True) + class C: + x: int + self.assertEqual(hash(C(4)), hash((4,))) + self.assertEqual(hash(C(42)), hash((42,))) + + @dataclass(unsafe_hash=True) + class C: + x: int + self.assertEqual(hash(C(4)), hash((4,))) + self.assertEqual(hash(C(42)), hash((42,))) + + def test_hash_no_args(self): + # Test dataclasses with no hash= argument. This exists to + # make sure that if the @dataclass parameter name is changed + # or the non-default hashing behavior changes, the default + # hashability keeps working the same way. + + class Base: + def __hash__(self): + return 301 + + # If frozen or eq is None, then use the default value (do not + # specify any value in the decorator). + for frozen, eq, base, expected in [ + (None, None, object, 'unhashable'), + (None, None, Base, 'unhashable'), + (None, False, object, 'object'), + (None, False, Base, 'base'), + (None, True, object, 'unhashable'), + (None, True, Base, 'unhashable'), + (False, None, object, 'unhashable'), + (False, None, Base, 'unhashable'), + (False, False, object, 'object'), + (False, False, Base, 'base'), + (False, True, object, 'unhashable'), + (False, True, Base, 'unhashable'), + (True, None, object, 'tuple'), + (True, None, Base, 'tuple'), + (True, False, object, 'object'), + (True, False, Base, 'base'), + (True, True, object, 'tuple'), + (True, True, Base, 'tuple'), + ]: + + with self.subTest(frozen=frozen, eq=eq, base=base, expected=expected): + # First, create the class. + if frozen is None and eq is None: + @dataclass + class C(base): + i: int + elif frozen is None: + @dataclass(eq=eq) + class C(base): + i: int + elif eq is None: + @dataclass(frozen=frozen) + class C(base): + i: int + else: + @dataclass(frozen=frozen, eq=eq) + class C(base): + i: int + + # Now, make sure it hashes as expected. + if expected == 'unhashable': + c = C(10) + with self.assertRaisesRegex(TypeError, 'unhashable type'): + hash(c) + + elif expected == 'base': + self.assertEqual(hash(C(10)), 301) + + elif expected == 'object': + # I'm not sure what test to use here. object's + # hash isn't based on id(), so calling hash() + # won't tell us much. So, just check the + # function used is object's. + self.assertIs(C.__hash__, object.__hash__) + + elif expected == 'tuple': + self.assertEqual(hash(C(42)), hash((42,))) + + else: + assert False, f'unknown value for expected={expected!r}' + + +class TestFrozen(unittest.TestCase): + def test_frozen(self): + @dataclass(frozen=True) + class C: + i: int + + c = C(10) + self.assertEqual(c.i, 10) + with self.assertRaises(FrozenInstanceError): + c.i = 5 + self.assertEqual(c.i, 10) + + def test_frozen_empty(self): + @dataclass(frozen=True) + class C: + pass + + c = C() + self.assertFalse(hasattr(c, 'i')) + with self.assertRaises(FrozenInstanceError): + c.i = 5 + self.assertFalse(hasattr(c, 'i')) + with self.assertRaises(FrozenInstanceError): + del c.i + + def test_inherit(self): + @dataclass(frozen=True) + class C: + i: int + + @dataclass(frozen=True) + class D(C): + j: int + + d = D(0, 10) + with self.assertRaises(FrozenInstanceError): + d.i = 5 + with self.assertRaises(FrozenInstanceError): + d.j = 6 + self.assertEqual(d.i, 0) + self.assertEqual(d.j, 10) + + def test_inherit_nonfrozen_from_empty_frozen(self): + @dataclass(frozen=True) + class C: + pass + + with self.assertRaisesRegex(TypeError, + 'cannot inherit non-frozen dataclass from a frozen one'): + @dataclass + class D(C): + j: int + + def test_inherit_frozen_mutliple_inheritance(self): + @dataclass + class NotFrozen: + pass + + @dataclass(frozen=True) + class Frozen: + pass + + class NotDataclass: + pass + + for bases in ( + (NotFrozen, Frozen), + (Frozen, NotFrozen), + (Frozen, NotDataclass), + (NotDataclass, Frozen), + ): + with self.subTest(bases=bases): + with self.assertRaisesRegex( + TypeError, + 'cannot inherit non-frozen dataclass from a frozen one', + ): + @dataclass + class NotFrozenChild(*bases): + pass + + for bases in ( + (NotFrozen, Frozen), + (Frozen, NotFrozen), + (NotFrozen, NotDataclass), + (NotDataclass, NotFrozen), + ): + with self.subTest(bases=bases): + with self.assertRaisesRegex( + TypeError, + 'cannot inherit frozen dataclass from a non-frozen one', + ): + @dataclass(frozen=True) + class FrozenChild(*bases): + pass + + def test_inherit_frozen_mutliple_inheritance_regular_mixins(self): + @dataclass(frozen=True) + class Frozen: + pass + + class NotDataclass: + pass + + class C1(Frozen, NotDataclass): + pass + self.assertEqual(C1.__mro__, (C1, Frozen, NotDataclass, object)) + + class C2(NotDataclass, Frozen): + pass + self.assertEqual(C2.__mro__, (C2, NotDataclass, Frozen, object)) + + @dataclass(frozen=True) + class C3(Frozen, NotDataclass): + pass + self.assertEqual(C3.__mro__, (C3, Frozen, NotDataclass, object)) + + @dataclass(frozen=True) + class C4(NotDataclass, Frozen): + pass + self.assertEqual(C4.__mro__, (C4, NotDataclass, Frozen, object)) + + def test_multiple_frozen_dataclasses_inheritance(self): + @dataclass(frozen=True) + class FrozenA: + pass + + @dataclass(frozen=True) + class FrozenB: + pass + + class C1(FrozenA, FrozenB): + pass + self.assertEqual(C1.__mro__, (C1, FrozenA, FrozenB, object)) + + class C2(FrozenB, FrozenA): + pass + self.assertEqual(C2.__mro__, (C2, FrozenB, FrozenA, object)) + + @dataclass(frozen=True) + class C3(FrozenA, FrozenB): + pass + self.assertEqual(C3.__mro__, (C3, FrozenA, FrozenB, object)) + + @dataclass(frozen=True) + class C4(FrozenB, FrozenA): + pass + self.assertEqual(C4.__mro__, (C4, FrozenB, FrozenA, object)) + + def test_inherit_nonfrozen_from_empty(self): + @dataclass + class C: + pass + + @dataclass + class D(C): + j: int + + d = D(3) + self.assertEqual(d.j, 3) + self.assertIsInstance(d, C) + + # Test both ways: with an intermediate normal (non-dataclass) + # class and without an intermediate class. + def test_inherit_nonfrozen_from_frozen(self): + for intermediate_class in [True, False]: + with self.subTest(intermediate_class=intermediate_class): + @dataclass(frozen=True) + class C: + i: int + + if intermediate_class: + class I(C): pass + else: + I = C + + with self.assertRaisesRegex(TypeError, + 'cannot inherit non-frozen dataclass from a frozen one'): + @dataclass + class D(I): + pass + + def test_inherit_frozen_from_nonfrozen(self): + for intermediate_class in [True, False]: + with self.subTest(intermediate_class=intermediate_class): + @dataclass + class C: + i: int + + if intermediate_class: + class I(C): pass + else: + I = C + + with self.assertRaisesRegex(TypeError, + 'cannot inherit frozen dataclass from a non-frozen one'): + @dataclass(frozen=True) + class D(I): + pass + + def test_inherit_from_normal_class(self): + for intermediate_class in [True, False]: + with self.subTest(intermediate_class=intermediate_class): + class C: + pass + + if intermediate_class: + class I(C): pass + else: + I = C + + @dataclass(frozen=True) + class D(I): + i: int + + d = D(10) + with self.assertRaises(FrozenInstanceError): + d.i = 5 + + def test_non_frozen_normal_derived(self): + # See bpo-32953. + + @dataclass(frozen=True) + class D: + x: int + y: int = 10 + + class S(D): + pass + + s = S(3) + self.assertEqual(s.x, 3) + self.assertEqual(s.y, 10) + s.cached = True + + # But can't change the frozen attributes. + with self.assertRaises(FrozenInstanceError): + s.x = 5 + with self.assertRaises(FrozenInstanceError): + s.y = 5 + self.assertEqual(s.x, 3) + self.assertEqual(s.y, 10) + self.assertEqual(s.cached, True) + + with self.assertRaises(FrozenInstanceError): + del s.x + self.assertEqual(s.x, 3) + with self.assertRaises(FrozenInstanceError): + del s.y + self.assertEqual(s.y, 10) + del s.cached + self.assertFalse(hasattr(s, 'cached')) + with self.assertRaises(AttributeError) as cm: + del s.cached + self.assertNotIsInstance(cm.exception, FrozenInstanceError) + + def test_non_frozen_normal_derived_from_empty_frozen(self): + @dataclass(frozen=True) + class D: + pass + + class S(D): + pass + + s = S() + self.assertFalse(hasattr(s, 'x')) + s.x = 5 + self.assertEqual(s.x, 5) + + del s.x + self.assertFalse(hasattr(s, 'x')) + with self.assertRaises(AttributeError) as cm: + del s.x + self.assertNotIsInstance(cm.exception, FrozenInstanceError) + + def test_overwriting_frozen(self): + # frozen uses __setattr__ and __delattr__. + with self.assertRaisesRegex(TypeError, + 'Cannot overwrite attribute __setattr__'): + @dataclass(frozen=True) + class C: + x: int + def __setattr__(self): + pass + + with self.assertRaisesRegex(TypeError, + 'Cannot overwrite attribute __delattr__'): + @dataclass(frozen=True) + class C: + x: int + def __delattr__(self): + pass + + @dataclass(frozen=False) + class C: + x: int + def __setattr__(self, name, value): + self.__dict__['x'] = value * 2 + self.assertEqual(C(10).x, 20) + + def test_frozen_hash(self): + @dataclass(frozen=True) + class C: + x: Any + + # If x is immutable, we can compute the hash. No exception is + # raised. + hash(C(3)) + + # If x is mutable, computing the hash is an error. + with self.assertRaisesRegex(TypeError, 'unhashable type'): + hash(C({})) + + +class TestSlots(unittest.TestCase): + def test_simple(self): + @dataclass + class C: + __slots__ = ('x',) + x: Any + + # There was a bug where a variable in a slot was assumed to + # also have a default value (of type + # types.MemberDescriptorType). + with self.assertRaisesRegex(TypeError, + r"__init__\(\) missing 1 required positional argument: 'x'"): + C() + + # We can create an instance, and assign to x. + c = C(10) + self.assertEqual(c.x, 10) + c.x = 5 + self.assertEqual(c.x, 5) + + # We can't assign to anything else. + with self.assertRaisesRegex(AttributeError, "'C' object has no attribute 'y'"): + c.y = 5 + + def test_derived_added_field(self): + # See bpo-33100. + @dataclass + class Base: + __slots__ = ('x',) + x: Any + + @dataclass + class Derived(Base): + x: int + y: int + + d = Derived(1, 2) + self.assertEqual((d.x, d.y), (1, 2)) + + # We can add a new field to the derived instance. + d.z = 10 + + def test_generated_slots(self): + @dataclass(slots=True) + class C: + x: int + y: int + + c = C(1, 2) + self.assertEqual((c.x, c.y), (1, 2)) + + c.x = 3 + c.y = 4 + self.assertEqual((c.x, c.y), (3, 4)) + + with self.assertRaisesRegex(AttributeError, "'C' object has no attribute 'z'"): + c.z = 5 + + def test_add_slots_when_slots_exists(self): + with self.assertRaisesRegex(TypeError, '^C already specifies __slots__$'): + @dataclass(slots=True) + class C: + __slots__ = ('x',) + x: int + + def test_generated_slots_value(self): + + class Root: + __slots__ = {'x'} + + class Root2(Root): + __slots__ = {'k': '...', 'j': ''} + + class Root3(Root2): + __slots__ = ['h'] + + class Root4(Root3): + __slots__ = 'aa' + + @dataclass(slots=True) + class Base(Root4): + y: int + j: str + h: str + + self.assertEqual(Base.__slots__, ('y', )) + + @dataclass(slots=True) + class Derived(Base): + aa: float + x: str + z: int + k: str + h: str + + self.assertEqual(Derived.__slots__, ('z', )) + + @dataclass + class AnotherDerived(Base): + z: int + + self.assertNotIn('__slots__', AnotherDerived.__dict__) + + def test_cant_inherit_from_iterator_slots(self): + + class Root: + __slots__ = iter(['a']) + + class Root2(Root): + __slots__ = ('b', ) + + with self.assertRaisesRegex( + TypeError, + "^Slots of 'Root' cannot be determined" + ): + @dataclass(slots=True) + class C(Root2): + x: int + + def test_returns_new_class(self): + class A: + x: int + + B = dataclass(A, slots=True) + self.assertIsNot(A, B) + + self.assertFalse(hasattr(A, "__slots__")) + self.assertTrue(hasattr(B, "__slots__")) + + # Can't be local to test_frozen_pickle. + @dataclass(frozen=True, slots=True) + class FrozenSlotsClass: + foo: str + bar: int + + @dataclass(frozen=True) + class FrozenWithoutSlotsClass: + foo: str + bar: int + + def test_frozen_pickle(self): + # bpo-43999 + + self.assertEqual(self.FrozenSlotsClass.__slots__, ("foo", "bar")) + for proto in range(pickle.HIGHEST_PROTOCOL + 1): + with self.subTest(proto=proto): + obj = self.FrozenSlotsClass("a", 1) + p = pickle.loads(pickle.dumps(obj, protocol=proto)) + self.assertIsNot(obj, p) + self.assertEqual(obj, p) + + obj = self.FrozenWithoutSlotsClass("a", 1) + p = pickle.loads(pickle.dumps(obj, protocol=proto)) + self.assertIsNot(obj, p) + self.assertEqual(obj, p) + + @dataclass(frozen=True, slots=True) + class FrozenSlotsGetStateClass: + foo: str + bar: int + + getstate_called: bool = field(default=False, compare=False) + + def __getstate__(self): + object.__setattr__(self, 'getstate_called', True) + return [self.foo, self.bar] + + @dataclass(frozen=True, slots=True) + class FrozenSlotsSetStateClass: + foo: str + bar: int + + setstate_called: bool = field(default=False, compare=False) + + def __setstate__(self, state): + object.__setattr__(self, 'setstate_called', True) + object.__setattr__(self, 'foo', state[0]) + object.__setattr__(self, 'bar', state[1]) + + @dataclass(frozen=True, slots=True) + class FrozenSlotsAllStateClass: + foo: str + bar: int + + getstate_called: bool = field(default=False, compare=False) + setstate_called: bool = field(default=False, compare=False) + + def __getstate__(self): + object.__setattr__(self, 'getstate_called', True) + return [self.foo, self.bar] + + def __setstate__(self, state): + object.__setattr__(self, 'setstate_called', True) + object.__setattr__(self, 'foo', state[0]) + object.__setattr__(self, 'bar', state[1]) + + def test_frozen_slots_pickle_custom_state(self): + for proto in range(pickle.HIGHEST_PROTOCOL + 1): + with self.subTest(proto=proto): + obj = self.FrozenSlotsGetStateClass('a', 1) + dumped = pickle.dumps(obj, protocol=proto) + + self.assertTrue(obj.getstate_called) + self.assertEqual(obj, pickle.loads(dumped)) + + for proto in range(pickle.HIGHEST_PROTOCOL + 1): + with self.subTest(proto=proto): + obj = self.FrozenSlotsSetStateClass('a', 1) + obj2 = pickle.loads(pickle.dumps(obj, protocol=proto)) + + self.assertTrue(obj2.setstate_called) + self.assertEqual(obj, obj2) + + for proto in range(pickle.HIGHEST_PROTOCOL + 1): + with self.subTest(proto=proto): + obj = self.FrozenSlotsAllStateClass('a', 1) + dumped = pickle.dumps(obj, protocol=proto) + + self.assertTrue(obj.getstate_called) + + obj2 = pickle.loads(dumped) + self.assertTrue(obj2.setstate_called) + self.assertEqual(obj, obj2) + + def test_slots_with_default_no_init(self): + # Originally reported in bpo-44649. + @dataclass(slots=True) + class A: + a: str + b: str = field(default='b', init=False) + + obj = A("a") + self.assertEqual(obj.a, 'a') + self.assertEqual(obj.b, 'b') + + def test_slots_with_default_factory_no_init(self): + # Originally reported in bpo-44649. + @dataclass(slots=True) + class A: + a: str + b: str = field(default_factory=lambda:'b', init=False) + + obj = A("a") + self.assertEqual(obj.a, 'a') + self.assertEqual(obj.b, 'b') + + def test_slots_no_weakref(self): + @dataclass(slots=True) + class A: + # No weakref. + pass + + self.assertNotIn("__weakref__", A.__slots__) + a = A() + with self.assertRaisesRegex(TypeError, + "cannot create weak reference"): + weakref.ref(a) + with self.assertRaises(AttributeError): + a.__weakref__ + + def test_slots_weakref(self): + @dataclass(slots=True, weakref_slot=True) + class A: + a: int + + self.assertIn("__weakref__", A.__slots__) + a = A(1) + a_ref = weakref.ref(a) + + self.assertIs(a.__weakref__, a_ref) + + def test_slots_weakref_base_str(self): + class Base: + __slots__ = '__weakref__' + + @dataclass(slots=True) + class A(Base): + a: int + + # __weakref__ is in the base class, not A. But an A is still weakref-able. + self.assertIn("__weakref__", Base.__slots__) + self.assertNotIn("__weakref__", A.__slots__) + a = A(1) + weakref.ref(a) + + def test_slots_weakref_base_tuple(self): + # Same as test_slots_weakref_base, but use a tuple instead of a string + # in the base class. + class Base: + __slots__ = ('__weakref__',) + + @dataclass(slots=True) + class A(Base): + a: int + + # __weakref__ is in the base class, not A. But an A is still + # weakref-able. + self.assertIn("__weakref__", Base.__slots__) + self.assertNotIn("__weakref__", A.__slots__) + a = A(1) + weakref.ref(a) + + def test_weakref_slot_without_slot(self): + with self.assertRaisesRegex(TypeError, + "weakref_slot is True but slots is False"): + @dataclass(weakref_slot=True) + class A: + a: int + + def test_weakref_slot_make_dataclass(self): + A = make_dataclass('A', [('a', int),], slots=True, weakref_slot=True) + self.assertIn("__weakref__", A.__slots__) + a = A(1) + weakref.ref(a) + + # And make sure if raises if slots=True is not given. + with self.assertRaisesRegex(TypeError, + "weakref_slot is True but slots is False"): + B = make_dataclass('B', [('a', int),], weakref_slot=True) + + def test_weakref_slot_subclass_weakref_slot(self): + @dataclass(slots=True, weakref_slot=True) + class Base: + field: int + + # A *can* also specify weakref_slot=True if it wants to (gh-93521) + @dataclass(slots=True, weakref_slot=True) + class A(Base): + ... + + # __weakref__ is in the base class, not A. But an instance of A + # is still weakref-able. + self.assertIn("__weakref__", Base.__slots__) + self.assertNotIn("__weakref__", A.__slots__) + a = A(1) + a_ref = weakref.ref(a) + self.assertIs(a.__weakref__, a_ref) + + def test_weakref_slot_subclass_no_weakref_slot(self): + @dataclass(slots=True, weakref_slot=True) + class Base: + field: int + + @dataclass(slots=True) + class A(Base): + ... + + # __weakref__ is in the base class, not A. Even though A doesn't + # specify weakref_slot, it should still be weakref-able. + self.assertIn("__weakref__", Base.__slots__) + self.assertNotIn("__weakref__", A.__slots__) + a = A(1) + a_ref = weakref.ref(a) + self.assertIs(a.__weakref__, a_ref) + + def test_weakref_slot_normal_base_weakref_slot(self): + class Base: + __slots__ = ('__weakref__',) + + @dataclass(slots=True, weakref_slot=True) + class A(Base): + field: int + + # __weakref__ is in the base class, not A. But an instance of + # A is still weakref-able. + self.assertIn("__weakref__", Base.__slots__) + self.assertNotIn("__weakref__", A.__slots__) + a = A(1) + a_ref = weakref.ref(a) + self.assertIs(a.__weakref__, a_ref) + + +class TestDescriptors(unittest.TestCase): + def test_set_name(self): + # See bpo-33141. + + # Create a descriptor. + class D: + def __set_name__(self, owner, name): + self.name = name + 'x' + def __get__(self, instance, owner): + if instance is not None: + return 1 + return self + + # This is the case of just normal descriptor behavior, no + # dataclass code is involved in initializing the descriptor. + @dataclass + class C: + c: int=D() + self.assertEqual(C.c.name, 'cx') + + # Now test with a default value and init=False, which is the + # only time this is really meaningful. If not using + # init=False, then the descriptor will be overwritten, anyway. + @dataclass + class C: + c: int=field(default=D(), init=False) + self.assertEqual(C.c.name, 'cx') + self.assertEqual(C().c, 1) + + def test_non_descriptor(self): + # PEP 487 says __set_name__ should work on non-descriptors. + # Create a descriptor. + + class D: + def __set_name__(self, owner, name): + self.name = name + 'x' + + @dataclass + class C: + c: int=field(default=D(), init=False) + self.assertEqual(C.c.name, 'cx') + + def test_lookup_on_instance(self): + # See bpo-33175. + class D: + pass + + d = D() + # Create an attribute on the instance, not type. + d.__set_name__ = Mock() + + # Make sure d.__set_name__ is not called. + @dataclass + class C: + i: int=field(default=d, init=False) + + self.assertEqual(d.__set_name__.call_count, 0) + + def test_lookup_on_class(self): + # See bpo-33175. + class D: + pass + D.__set_name__ = Mock() + + # Make sure D.__set_name__ is called. + @dataclass + class C: + i: int=field(default=D(), init=False) + + self.assertEqual(D.__set_name__.call_count, 1) + + def test_init_calls_set(self): + class D: + pass + + D.__set__ = Mock() + + @dataclass + class C: + i: D = D() + + # Make sure D.__set__ is called. + D.__set__.reset_mock() + c = C(5) + self.assertEqual(D.__set__.call_count, 1) + + def test_getting_field_calls_get(self): + class D: + pass + + D.__set__ = Mock() + D.__get__ = Mock() + + @dataclass + class C: + i: D = D() + + c = C(5) + + # Make sure D.__get__ is called. + D.__get__.reset_mock() + value = c.i + self.assertEqual(D.__get__.call_count, 1) + + def test_setting_field_calls_set(self): + class D: + pass + + D.__set__ = Mock() + + @dataclass + class C: + i: D = D() + + c = C(5) + + # Make sure D.__set__ is called. + D.__set__.reset_mock() + c.i = 10 + self.assertEqual(D.__set__.call_count, 1) + + def test_setting_uninitialized_descriptor_field(self): + class D: + pass + + D.__set__ = Mock() + + @dataclass + class C: + i: D + + # D.__set__ is not called because there's no D instance to call it on + D.__set__.reset_mock() + c = C(5) + self.assertEqual(D.__set__.call_count, 0) + + # D.__set__ still isn't called after setting i to an instance of D + # because descriptors don't behave like that when stored as instance vars + c.i = D() + c.i = 5 + self.assertEqual(D.__set__.call_count, 0) + + def test_default_value(self): + class D: + def __get__(self, instance: Any, owner: object) -> int: + if instance is None: + return 100 + + return instance._x + + def __set__(self, instance: Any, value: int) -> None: + instance._x = value + + @dataclass + class C: + i: D = D() + + c = C() + self.assertEqual(c.i, 100) + + c = C(5) + self.assertEqual(c.i, 5) + + def test_no_default_value(self): + class D: + def __get__(self, instance: Any, owner: object) -> int: + if instance is None: + raise AttributeError() + + return instance._x + + def __set__(self, instance: Any, value: int) -> None: + instance._x = value + + @dataclass + class C: + i: D = D() + + with self.assertRaisesRegex(TypeError, 'missing 1 required positional argument'): + c = C() + +class TestStringAnnotations(unittest.TestCase): + def test_classvar(self): + # Some expressions recognized as ClassVar really aren't. But + # if you're using string annotations, it's not an exact + # science. + # These tests assume that both "import typing" and "from + # typing import *" have been run in this file. + for typestr in ('ClassVar[int]', + 'ClassVar [int]', + ' ClassVar [int]', + 'ClassVar', + ' ClassVar ', + 'typing.ClassVar[int]', + 'typing.ClassVar[str]', + ' typing.ClassVar[str]', + 'typing .ClassVar[str]', + 'typing. ClassVar[str]', + 'typing.ClassVar [str]', + 'typing.ClassVar [ str]', + + # Not syntactically valid, but these will + # be treated as ClassVars. + 'typing.ClassVar.[int]', + 'typing.ClassVar+', + ): + with self.subTest(typestr=typestr): + @dataclass + class C: + x: typestr + + # x is a ClassVar, so C() takes no args. + C() + + # And it won't appear in the class's dict because it doesn't + # have a default. + self.assertNotIn('x', C.__dict__) + + def test_isnt_classvar(self): + for typestr in ('CV', + 't.ClassVar', + 't.ClassVar[int]', + 'typing..ClassVar[int]', + 'Classvar', + 'Classvar[int]', + 'typing.ClassVarx[int]', + 'typong.ClassVar[int]', + 'dataclasses.ClassVar[int]', + 'typingxClassVar[str]', + ): + with self.subTest(typestr=typestr): + @dataclass + class C: + x: typestr + + # x is not a ClassVar, so C() takes one arg. + self.assertEqual(C(10).x, 10) + + def test_initvar(self): + # These tests assume that both "import dataclasses" and "from + # dataclasses import *" have been run in this file. + for typestr in ('InitVar[int]', + 'InitVar [int]' + ' InitVar [int]', + 'InitVar', + ' InitVar ', + 'dataclasses.InitVar[int]', + 'dataclasses.InitVar[str]', + ' dataclasses.InitVar[str]', + 'dataclasses .InitVar[str]', + 'dataclasses. InitVar[str]', + 'dataclasses.InitVar [str]', + 'dataclasses.InitVar [ str]', + + # Not syntactically valid, but these will + # be treated as InitVars. + 'dataclasses.InitVar.[int]', + 'dataclasses.InitVar+', + ): + with self.subTest(typestr=typestr): + @dataclass + class C: + x: typestr + + # x is an InitVar, so doesn't create a member. + with self.assertRaisesRegex(AttributeError, + "object has no attribute 'x'"): + C(1).x + + def test_isnt_initvar(self): + for typestr in ('IV', + 'dc.InitVar', + 'xdataclasses.xInitVar', + 'typing.xInitVar[int]', + ): + with self.subTest(typestr=typestr): + @dataclass + class C: + x: typestr + + # x is not an InitVar, so there will be a member x. + self.assertEqual(C(10).x, 10) + + def test_classvar_module_level_import(self): + from test.test_dataclasses import dataclass_module_1 + from test.test_dataclasses import dataclass_module_1_str + from test.test_dataclasses import dataclass_module_2 + from test.test_dataclasses import dataclass_module_2_str + + for m in (dataclass_module_1, dataclass_module_1_str, + dataclass_module_2, dataclass_module_2_str, + ): + with self.subTest(m=m): + # There's a difference in how the ClassVars are + # interpreted when using string annotations or + # not. See the imported modules for details. + if m.USING_STRINGS: + c = m.CV(10) + else: + c = m.CV() + self.assertEqual(c.cv0, 20) + + + # There's a difference in how the InitVars are + # interpreted when using string annotations or + # not. See the imported modules for details. + c = m.IV(0, 1, 2, 3, 4) + + for field_name in ('iv0', 'iv1', 'iv2', 'iv3'): + with self.subTest(field_name=field_name): + with self.assertRaisesRegex(AttributeError, f"object has no attribute '{field_name}'"): + # Since field_name is an InitVar, it's + # not an instance field. + getattr(c, field_name) + + if m.USING_STRINGS: + # iv4 is interpreted as a normal field. + self.assertIn('not_iv4', c.__dict__) + self.assertEqual(c.not_iv4, 4) + else: + # iv4 is interpreted as an InitVar, so it + # won't exist on the instance. + self.assertNotIn('not_iv4', c.__dict__) + + def test_text_annotations(self): + from test.test_dataclasses import dataclass_textanno + + self.assertEqual( + get_type_hints(dataclass_textanno.Bar), + {'foo': dataclass_textanno.Foo}) + self.assertEqual( + get_type_hints(dataclass_textanno.Bar.__init__), + {'foo': dataclass_textanno.Foo, + 'return': type(None)}) + + +ByMakeDataClass = make_dataclass('ByMakeDataClass', [('x', int)]) +ManualModuleMakeDataClass = make_dataclass('ManualModuleMakeDataClass', + [('x', int)], + module=__name__) +WrongNameMakeDataclass = make_dataclass('Wrong', [('x', int)]) +WrongModuleMakeDataclass = make_dataclass('WrongModuleMakeDataclass', + [('x', int)], + module='custom') + +class TestMakeDataclass(unittest.TestCase): + def test_simple(self): + C = make_dataclass('C', + [('x', int), + ('y', int, field(default=5))], + namespace={'add_one': lambda self: self.x + 1}) + c = C(10) + self.assertEqual((c.x, c.y), (10, 5)) + self.assertEqual(c.add_one(), 11) + + + def test_no_mutate_namespace(self): + # Make sure a provided namespace isn't mutated. + ns = {} + C = make_dataclass('C', + [('x', int), + ('y', int, field(default=5))], + namespace=ns) + self.assertEqual(ns, {}) + + def test_base(self): + class Base1: + pass + class Base2: + pass + C = make_dataclass('C', + [('x', int)], + bases=(Base1, Base2)) + c = C(2) + self.assertIsInstance(c, C) + self.assertIsInstance(c, Base1) + self.assertIsInstance(c, Base2) + + def test_base_dataclass(self): + @dataclass + class Base1: + x: int + class Base2: + pass + C = make_dataclass('C', + [('y', int)], + bases=(Base1, Base2)) + with self.assertRaisesRegex(TypeError, 'required positional'): + c = C(2) + c = C(1, 2) + self.assertIsInstance(c, C) + self.assertIsInstance(c, Base1) + self.assertIsInstance(c, Base2) + + self.assertEqual((c.x, c.y), (1, 2)) + + def test_init_var(self): + def post_init(self, y): + self.x *= y + + C = make_dataclass('C', + [('x', int), + ('y', InitVar[int]), + ], + namespace={'__post_init__': post_init}, + ) + c = C(2, 3) + self.assertEqual(vars(c), {'x': 6}) + self.assertEqual(len(fields(c)), 1) + + def test_class_var(self): + C = make_dataclass('C', + [('x', int), + ('y', ClassVar[int], 10), + ('z', ClassVar[int], field(default=20)), + ]) + c = C(1) + self.assertEqual(vars(c), {'x': 1}) + self.assertEqual(len(fields(c)), 1) + self.assertEqual(C.y, 10) + self.assertEqual(C.z, 20) + + def test_other_params(self): + C = make_dataclass('C', + [('x', int), + ('y', ClassVar[int], 10), + ('z', ClassVar[int], field(default=20)), + ], + init=False) + # Make sure we have a repr, but no init. + self.assertNotIn('__init__', vars(C)) + self.assertIn('__repr__', vars(C)) + + # Make sure random other params don't work. + with self.assertRaisesRegex(TypeError, 'unexpected keyword argument'): + C = make_dataclass('C', + [], + xxinit=False) + + def test_no_types(self): + C = make_dataclass('Point', ['x', 'y', 'z']) + c = C(1, 2, 3) + self.assertEqual(vars(c), {'x': 1, 'y': 2, 'z': 3}) + self.assertEqual(C.__annotations__, {'x': 'typing.Any', + 'y': 'typing.Any', + 'z': 'typing.Any'}) + + C = make_dataclass('Point', ['x', ('y', int), 'z']) + c = C(1, 2, 3) + self.assertEqual(vars(c), {'x': 1, 'y': 2, 'z': 3}) + self.assertEqual(C.__annotations__, {'x': 'typing.Any', + 'y': int, + 'z': 'typing.Any'}) + + def test_module_attr(self): + self.assertEqual(ByMakeDataClass.__module__, __name__) + self.assertEqual(ByMakeDataClass(1).__module__, __name__) + self.assertEqual(WrongModuleMakeDataclass.__module__, "custom") + Nested = make_dataclass('Nested', []) + self.assertEqual(Nested.__module__, __name__) + self.assertEqual(Nested().__module__, __name__) + + def test_pickle_support(self): + for klass in [ByMakeDataClass, ManualModuleMakeDataClass]: + for proto in range(pickle.HIGHEST_PROTOCOL + 1): + with self.subTest(proto=proto): + self.assertEqual( + pickle.loads(pickle.dumps(klass, proto)), + klass, + ) + self.assertEqual( + pickle.loads(pickle.dumps(klass(1), proto)), + klass(1), + ) + + def test_cannot_be_pickled(self): + for klass in [WrongNameMakeDataclass, WrongModuleMakeDataclass]: + for proto in range(pickle.HIGHEST_PROTOCOL + 1): + with self.subTest(proto=proto): + with self.assertRaises(pickle.PickleError): + pickle.dumps(klass, proto) + with self.assertRaises(pickle.PickleError): + pickle.dumps(klass(1), proto) + + def test_invalid_type_specification(self): + for bad_field in [(), + (1, 2, 3, 4), + ]: + with self.subTest(bad_field=bad_field): + with self.assertRaisesRegex(TypeError, r'Invalid field: '): + make_dataclass('C', ['a', bad_field]) + + # And test for things with no len(). + for bad_field in [float, + lambda x:x, + ]: + with self.subTest(bad_field=bad_field): + with self.assertRaisesRegex(TypeError, r'has no len\(\)'): + make_dataclass('C', ['a', bad_field]) + + def test_duplicate_field_names(self): + for field in ['a', 'ab']: + with self.subTest(field=field): + with self.assertRaisesRegex(TypeError, 'Field name duplicated'): + make_dataclass('C', [field, 'a', field]) + + def test_keyword_field_names(self): + for field in ['for', 'async', 'await', 'as']: + with self.subTest(field=field): + with self.assertRaisesRegex(TypeError, 'must not be keywords'): + make_dataclass('C', ['a', field]) + with self.assertRaisesRegex(TypeError, 'must not be keywords'): + make_dataclass('C', [field]) + with self.assertRaisesRegex(TypeError, 'must not be keywords'): + make_dataclass('C', [field, 'a']) + + def test_non_identifier_field_names(self): + for field in ['()', 'x,y', '*', '2@3', '', 'little johnny tables']: + with self.subTest(field=field): + with self.assertRaisesRegex(TypeError, 'must be valid identifiers'): + make_dataclass('C', ['a', field]) + with self.assertRaisesRegex(TypeError, 'must be valid identifiers'): + make_dataclass('C', [field]) + with self.assertRaisesRegex(TypeError, 'must be valid identifiers'): + make_dataclass('C', [field, 'a']) + + def test_underscore_field_names(self): + # Unlike namedtuple, it's okay if dataclass field names have + # an underscore. + make_dataclass('C', ['_', '_a', 'a_a', 'a_']) + + def test_funny_class_names_names(self): + # No reason to prevent weird class names, since + # types.new_class allows them. + for classname in ['()', 'x,y', '*', '2@3', '']: + with self.subTest(classname=classname): + C = make_dataclass(classname, ['a', 'b']) + self.assertEqual(C.__name__, classname) + +class TestReplace(unittest.TestCase): + def test(self): + @dataclass(frozen=True) + class C: + x: int + y: int + + c = C(1, 2) + c1 = replace(c, x=3) + self.assertEqual(c1.x, 3) + self.assertEqual(c1.y, 2) + + def test_frozen(self): + @dataclass(frozen=True) + class C: + x: int + y: int + z: int = field(init=False, default=10) + t: int = field(init=False, default=100) + + c = C(1, 2) + c1 = replace(c, x=3) + self.assertEqual((c.x, c.y, c.z, c.t), (1, 2, 10, 100)) + self.assertEqual((c1.x, c1.y, c1.z, c1.t), (3, 2, 10, 100)) + + + with self.assertRaisesRegex(TypeError, 'init=False'): + replace(c, x=3, z=20, t=50) + with self.assertRaisesRegex(TypeError, 'init=False'): + replace(c, z=20) + replace(c, x=3, z=20, t=50) + + # Make sure the result is still frozen. + with self.assertRaisesRegex(FrozenInstanceError, "cannot assign to field 'x'"): + c1.x = 3 + + # Make sure we can't replace an attribute that doesn't exist, + # if we're also replacing one that does exist. Test this + # here, because setting attributes on frozen instances is + # handled slightly differently from non-frozen ones. + with self.assertRaisesRegex(TypeError, r"__init__\(\) got an unexpected " + "keyword argument 'a'"): + c1 = replace(c, x=20, a=5) + + def test_invalid_field_name(self): + @dataclass(frozen=True) + class C: + x: int + y: int + + c = C(1, 2) + with self.assertRaisesRegex(TypeError, r"__init__\(\) got an unexpected " + "keyword argument 'z'"): + c1 = replace(c, z=3) + + def test_invalid_object(self): + @dataclass(frozen=True) + class C: + x: int + y: int + + with self.assertRaisesRegex(TypeError, 'dataclass instance'): + replace(C, x=3) + + with self.assertRaisesRegex(TypeError, 'dataclass instance'): + replace(0, x=3) + + def test_no_init(self): + @dataclass + class C: + x: int + y: int = field(init=False, default=10) + + c = C(1) + c.y = 20 + + # Make sure y gets the default value. + c1 = replace(c, x=5) + self.assertEqual((c1.x, c1.y), (5, 10)) + + # Trying to replace y is an error. + with self.assertRaisesRegex(TypeError, 'init=False'): + replace(c, x=2, y=30) + + with self.assertRaisesRegex(TypeError, 'init=False'): + replace(c, y=30) + + def test_classvar(self): + @dataclass + class C: + x: int + y: ClassVar[int] = 1000 + + c = C(1) + d = C(2) + + self.assertIs(c.y, d.y) + self.assertEqual(c.y, 1000) + + # Trying to replace y is an error: can't replace ClassVars. + with self.assertRaisesRegex(TypeError, r"__init__\(\) got an " + "unexpected keyword argument 'y'"): + replace(c, y=30) + + replace(c, x=5) + + def test_initvar_is_specified(self): + @dataclass + class C: + x: int + y: InitVar[int] + + def __post_init__(self, y): + self.x *= y + + c = C(1, 10) + self.assertEqual(c.x, 10) + with self.assertRaisesRegex(TypeError, r"InitVar 'y' must be " + r"specified with replace\(\)"): + replace(c, x=3) + c = replace(c, x=3, y=5) + self.assertEqual(c.x, 15) + + def test_initvar_with_default_value(self): + @dataclass + class C: + x: int + y: InitVar[int] = None + z: InitVar[int] = 42 + + def __post_init__(self, y, z): + if y is not None: + self.x += y + if z is not None: + self.x += z + + c = C(x=1, y=10, z=1) + self.assertEqual(replace(c), C(x=12)) + self.assertEqual(replace(c, y=4), C(x=12, y=4, z=42)) + self.assertEqual(replace(c, y=4, z=1), C(x=12, y=4, z=1)) + + def test_recursive_repr(self): + @dataclass + class C: + f: "C" + + c = C(None) + c.f = c + self.assertEqual(repr(c), "TestReplace.test_recursive_repr..C(f=...)") + + def test_recursive_repr_two_attrs(self): + @dataclass + class C: + f: "C" + g: "C" + + c = C(None, None) + c.f = c + c.g = c + self.assertEqual(repr(c), "TestReplace.test_recursive_repr_two_attrs" + "..C(f=..., g=...)") + + def test_recursive_repr_indirection(self): + @dataclass + class C: + f: "D" + + @dataclass + class D: + f: "C" + + c = C(None) + d = D(None) + c.f = d + d.f = c + self.assertEqual(repr(c), "TestReplace.test_recursive_repr_indirection" + "..C(f=TestReplace.test_recursive_repr_indirection" + "..D(f=...))") + + def test_recursive_repr_indirection_two(self): + @dataclass + class C: + f: "D" + + @dataclass + class D: + f: "E" + + @dataclass + class E: + f: "C" + + c = C(None) + d = D(None) + e = E(None) + c.f = d + d.f = e + e.f = c + self.assertEqual(repr(c), "TestReplace.test_recursive_repr_indirection_two" + "..C(f=TestReplace.test_recursive_repr_indirection_two" + "..D(f=TestReplace.test_recursive_repr_indirection_two" + "..E(f=...)))") + + def test_recursive_repr_misc_attrs(self): + @dataclass + class C: + f: "C" + g: int + + c = C(None, 1) + c.f = c + self.assertEqual(repr(c), "TestReplace.test_recursive_repr_misc_attrs" + "..C(f=..., g=1)") + + ## def test_initvar(self): + ## @dataclass + ## class C: + ## x: int + ## y: InitVar[int] + + ## c = C(1, 10) + ## d = C(2, 20) + + ## # In our case, replacing an InitVar is a no-op + ## self.assertEqual(c, replace(c, y=5)) + + ## replace(c, x=5) + +class TestAbstract(unittest.TestCase): + def test_abc_implementation(self): + class Ordered(abc.ABC): + @abc.abstractmethod + def __lt__(self, other): + pass + + @abc.abstractmethod + def __le__(self, other): + pass + + @dataclass(order=True) + class Date(Ordered): + year: int + month: 'Month' + day: 'int' + + self.assertFalse(inspect.isabstract(Date)) + self.assertGreater(Date(2020,12,25), Date(2020,8,31)) + + def test_maintain_abc(self): + class A(abc.ABC): + @abc.abstractmethod + def foo(self): + pass + + @dataclass + class Date(A): + year: int + month: 'Month' + day: 'int' + + self.assertTrue(inspect.isabstract(Date)) + msg = "class Date without an implementation for abstract method 'foo'" + self.assertRaisesRegex(TypeError, msg, Date) + + +class TestMatchArgs(unittest.TestCase): + def test_match_args(self): + @dataclass + class C: + a: int + self.assertEqual(C(42).__match_args__, ('a',)) + + def test_explicit_match_args(self): + ma = () + @dataclass + class C: + a: int + __match_args__ = ma + self.assertIs(C(42).__match_args__, ma) + + def test_bpo_43764(self): + @dataclass(repr=False, eq=False, init=False) + class X: + a: int + b: int + c: int + self.assertEqual(X.__match_args__, ("a", "b", "c")) + + def test_match_args_argument(self): + @dataclass(match_args=False) + class X: + a: int + self.assertNotIn('__match_args__', X.__dict__) + + @dataclass(match_args=False) + class Y: + a: int + __match_args__ = ('b',) + self.assertEqual(Y.__match_args__, ('b',)) + + @dataclass(match_args=False) + class Z(Y): + z: int + self.assertEqual(Z.__match_args__, ('b',)) + + # Ensure parent dataclass __match_args__ is seen, if child class + # specifies match_args=False. + @dataclass + class A: + a: int + z: int + @dataclass(match_args=False) + class B(A): + b: int + self.assertEqual(B.__match_args__, ('a', 'z')) + + def test_make_dataclasses(self): + C = make_dataclass('C', [('x', int), ('y', int)]) + self.assertEqual(C.__match_args__, ('x', 'y')) + + C = make_dataclass('C', [('x', int), ('y', int)], match_args=True) + self.assertEqual(C.__match_args__, ('x', 'y')) + + C = make_dataclass('C', [('x', int), ('y', int)], match_args=False) + self.assertNotIn('__match__args__', C.__dict__) + + C = make_dataclass('C', [('x', int), ('y', int)], namespace={'__match_args__': ('z',)}) + self.assertEqual(C.__match_args__, ('z',)) + + +class TestKeywordArgs(unittest.TestCase): + def test_no_classvar_kwarg(self): + msg = 'field a is a ClassVar but specifies kw_only' + with self.assertRaisesRegex(TypeError, msg): + @dataclass + class A: + a: ClassVar[int] = field(kw_only=True) + + with self.assertRaisesRegex(TypeError, msg): + @dataclass + class A: + a: ClassVar[int] = field(kw_only=False) + + with self.assertRaisesRegex(TypeError, msg): + @dataclass(kw_only=True) + class A: + a: ClassVar[int] = field(kw_only=False) + + def test_field_marked_as_kwonly(self): + ####################### + # Using dataclass(kw_only=True) + @dataclass(kw_only=True) + class A: + a: int + self.assertTrue(fields(A)[0].kw_only) + + @dataclass(kw_only=True) + class A: + a: int = field(kw_only=True) + self.assertTrue(fields(A)[0].kw_only) + + @dataclass(kw_only=True) + class A: + a: int = field(kw_only=False) + self.assertFalse(fields(A)[0].kw_only) + + ####################### + # Using dataclass(kw_only=False) + @dataclass(kw_only=False) + class A: + a: int + self.assertFalse(fields(A)[0].kw_only) + + @dataclass(kw_only=False) + class A: + a: int = field(kw_only=True) + self.assertTrue(fields(A)[0].kw_only) + + @dataclass(kw_only=False) + class A: + a: int = field(kw_only=False) + self.assertFalse(fields(A)[0].kw_only) + + ####################### + # Not specifying dataclass(kw_only) + @dataclass + class A: + a: int + self.assertFalse(fields(A)[0].kw_only) + + @dataclass + class A: + a: int = field(kw_only=True) + self.assertTrue(fields(A)[0].kw_only) + + @dataclass + class A: + a: int = field(kw_only=False) + self.assertFalse(fields(A)[0].kw_only) + + def test_match_args(self): + # kw fields don't show up in __match_args__. + @dataclass(kw_only=True) + class C: + a: int + self.assertEqual(C(a=42).__match_args__, ()) + + @dataclass + class C: + a: int + b: int = field(kw_only=True) + self.assertEqual(C(42, b=10).__match_args__, ('a',)) + + def test_KW_ONLY(self): + @dataclass + class A: + a: int + _: KW_ONLY + b: int + c: int + A(3, c=5, b=4) + msg = "takes 2 positional arguments but 4 were given" + with self.assertRaisesRegex(TypeError, msg): + A(3, 4, 5) + + + @dataclass(kw_only=True) + class B: + a: int + _: KW_ONLY + b: int + c: int + B(a=3, b=4, c=5) + msg = "takes 1 positional argument but 4 were given" + with self.assertRaisesRegex(TypeError, msg): + B(3, 4, 5) + + # Explicitly make a field that follows KW_ONLY be non-keyword-only. + @dataclass + class C: + a: int + _: KW_ONLY + b: int + c: int = field(kw_only=False) + c = C(1, 2, b=3) + self.assertEqual(c.a, 1) + self.assertEqual(c.b, 3) + self.assertEqual(c.c, 2) + c = C(1, b=3, c=2) + self.assertEqual(c.a, 1) + self.assertEqual(c.b, 3) + self.assertEqual(c.c, 2) + c = C(1, b=3, c=2) + self.assertEqual(c.a, 1) + self.assertEqual(c.b, 3) + self.assertEqual(c.c, 2) + c = C(c=2, b=3, a=1) + self.assertEqual(c.a, 1) + self.assertEqual(c.b, 3) + self.assertEqual(c.c, 2) + + def test_KW_ONLY_as_string(self): + @dataclass + class A: + a: int + _: 'dataclasses.KW_ONLY' + b: int + c: int + A(3, c=5, b=4) + msg = "takes 2 positional arguments but 4 were given" + with self.assertRaisesRegex(TypeError, msg): + A(3, 4, 5) + + def test_KW_ONLY_twice(self): + msg = "'Y' is KW_ONLY, but KW_ONLY has already been specified" + + with self.assertRaisesRegex(TypeError, msg): + @dataclass + class A: + a: int + X: KW_ONLY + Y: KW_ONLY + b: int + c: int + + with self.assertRaisesRegex(TypeError, msg): + @dataclass + class A: + a: int + X: KW_ONLY + b: int + Y: KW_ONLY + c: int + + with self.assertRaisesRegex(TypeError, msg): + @dataclass + class A: + a: int + X: KW_ONLY + b: int + c: int + Y: KW_ONLY + + # But this usage is okay, since it's not using KW_ONLY. + @dataclass + class A: + a: int + _: KW_ONLY + b: int + c: int = field(kw_only=True) + + # And if inheriting, it's okay. + @dataclass + class A: + a: int + _: KW_ONLY + b: int + c: int + @dataclass + class B(A): + _: KW_ONLY + d: int + + # Make sure the error is raised in a derived class. + with self.assertRaisesRegex(TypeError, msg): + @dataclass + class A: + a: int + _: KW_ONLY + b: int + c: int + @dataclass + class B(A): + X: KW_ONLY + d: int + Y: KW_ONLY + + + def test_post_init(self): + @dataclass + class A: + a: int + _: KW_ONLY + b: InitVar[int] + c: int + d: InitVar[int] + def __post_init__(self, b, d): + raise CustomError(f'{b=} {d=}') + with self.assertRaisesRegex(CustomError, 'b=3 d=4'): + A(1, c=2, b=3, d=4) + + @dataclass + class B: + a: int + _: KW_ONLY + b: InitVar[int] + c: int + d: InitVar[int] + def __post_init__(self, b, d): + self.a = b + self.c = d + b = B(1, c=2, b=3, d=4) + self.assertEqual(asdict(b), {'a': 3, 'c': 4}) + + def test_defaults(self): + # For kwargs, make sure we can have defaults after non-defaults. + @dataclass + class A: + a: int = 0 + _: KW_ONLY + b: int + c: int = 1 + d: int + + a = A(d=4, b=3) + self.assertEqual(a.a, 0) + self.assertEqual(a.b, 3) + self.assertEqual(a.c, 1) + self.assertEqual(a.d, 4) + + # Make sure we still check for non-kwarg non-defaults not following + # defaults. + err_regex = "non-default argument 'z' follows default argument 'a'" + with self.assertRaisesRegex(TypeError, err_regex): + @dataclass + class A: + a: int = 0 + z: int + _: KW_ONLY + b: int + c: int = 1 + d: int + + def test_make_dataclass(self): + A = make_dataclass("A", ['a'], kw_only=True) + self.assertTrue(fields(A)[0].kw_only) + + B = make_dataclass("B", + ['a', ('b', int, field(kw_only=False))], + kw_only=True) + self.assertTrue(fields(B)[0].kw_only) + self.assertFalse(fields(B)[1].kw_only) + + +if __name__ == '__main__': + unittest.main() diff --git a/Lib/test/dataclass_module_1.py b/Lib/test/test_dataclasses/dataclass_module_1.py similarity index 100% rename from Lib/test/dataclass_module_1.py rename to Lib/test/test_dataclasses/dataclass_module_1.py diff --git a/Lib/test/dataclass_module_1_str.py b/Lib/test/test_dataclasses/dataclass_module_1_str.py similarity index 100% rename from Lib/test/dataclass_module_1_str.py rename to Lib/test/test_dataclasses/dataclass_module_1_str.py diff --git a/Lib/test/dataclass_module_2.py b/Lib/test/test_dataclasses/dataclass_module_2.py similarity index 100% rename from Lib/test/dataclass_module_2.py rename to Lib/test/test_dataclasses/dataclass_module_2.py diff --git a/Lib/test/dataclass_module_2_str.py b/Lib/test/test_dataclasses/dataclass_module_2_str.py similarity index 100% rename from Lib/test/dataclass_module_2_str.py rename to Lib/test/test_dataclasses/dataclass_module_2_str.py diff --git a/Lib/test/dataclass_textanno.py b/Lib/test/test_dataclasses/dataclass_textanno.py similarity index 100% rename from Lib/test/dataclass_textanno.py rename to Lib/test/test_dataclasses/dataclass_textanno.py diff --git a/Lib/test/test_decimal.py b/Lib/test/test_decimal.py index fc66a309788ac1..7a5fe62b467372 100644 --- a/Lib/test/test_decimal.py +++ b/Lib/test/test_decimal.py @@ -34,14 +34,13 @@ import locale from test.support import (is_resource_enabled, requires_IEEE_754, requires_docstrings, - requires_legacy_unicode_capi, check_sanitizer, + check_sanitizer, check_disallow_instantiation) from test.support import (TestFailed, run_with_locale, cpython_only, darwin_malloc_err_warning, is_emscripten) from test.support.import_helper import import_fresh_module from test.support import threading_helper -from test.support import warnings_helper import random import inspect import threading @@ -587,18 +586,6 @@ def test_explicit_from_string(self): # underscores don't prevent errors self.assertRaises(InvalidOperation, Decimal, "1_2_\u00003") - @cpython_only - @requires_legacy_unicode_capi - @warnings_helper.ignore_warnings(category=DeprecationWarning) - def test_from_legacy_strings(self): - import _testcapi - Decimal = self.decimal.Decimal - context = self.decimal.Context() - - s = _testcapi.unicode_legacy_string('9.999999') - self.assertEqual(str(Decimal(s)), '9.999999') - self.assertEqual(str(context.create_decimal(s)), '9.999999') - def test_explicit_from_tuples(self): Decimal = self.decimal.Decimal @@ -1235,6 +1222,23 @@ def get_fmt(x, override=None, fmt='n'): self.assertEqual(get_fmt(Decimal('-1.5'), dotsep_wide, '020n'), '-0\u00b4000\u00b4000\u00b4000\u00b4001\u00bf5') + def test_deprecated_N_format(self): + Decimal = self.decimal.Decimal + h = Decimal('6.62607015e-34') + if self.decimal == C: + with self.assertWarns(DeprecationWarning) as cm: + r = format(h, 'N') + self.assertEqual(cm.filename, __file__) + self.assertEqual(r, format(h, 'n').upper()) + with self.assertWarns(DeprecationWarning) as cm: + r = format(h, '010.3N') + self.assertEqual(cm.filename, __file__) + self.assertEqual(r, format(h, '010.3n').upper()) + else: + self.assertRaises(ValueError, format, h, 'N') + self.assertRaises(ValueError, format, h, '010.3N') + + @run_with_locale('LC_ALL', 'ps_AF') def test_wide_char_separator_decimal_point(self): # locale with wide char separator and decimal point @@ -2919,23 +2923,6 @@ def test_none_args(self): assert_signals(self, c, 'traps', [InvalidOperation, DivisionByZero, Overflow]) - @cpython_only - @requires_legacy_unicode_capi - @warnings_helper.ignore_warnings(category=DeprecationWarning) - def test_from_legacy_strings(self): - import _testcapi - c = self.decimal.Context() - - for rnd in RoundingModes: - c.rounding = _testcapi.unicode_legacy_string(rnd) - self.assertEqual(c.rounding, rnd) - - s = _testcapi.unicode_legacy_string('') - self.assertRaises(TypeError, setattr, c, 'rounding', s) - - s = _testcapi.unicode_legacy_string('ROUND_\x00UP') - self.assertRaises(TypeError, setattr, c, 'rounding', s) - def test_pickle(self): for proto in range(pickle.HIGHEST_PROTOCOL + 1): diff --git a/Lib/test/test_decorators.py b/Lib/test/test_decorators.py index 4b492178c1581f..3a4fc959f6f8a7 100644 --- a/Lib/test/test_decorators.py +++ b/Lib/test/test_decorators.py @@ -291,44 +291,6 @@ def bar(): return 42 self.assertEqual(bar(), 42) self.assertEqual(actions, expected_actions) - def test_wrapped_descriptor_inside_classmethod(self): - class BoundWrapper: - def __init__(self, wrapped): - self.__wrapped__ = wrapped - - def __call__(self, *args, **kwargs): - return self.__wrapped__(*args, **kwargs) - - class Wrapper: - def __init__(self, wrapped): - self.__wrapped__ = wrapped - - def __get__(self, instance, owner): - bound_function = self.__wrapped__.__get__(instance, owner) - return BoundWrapper(bound_function) - - def decorator(wrapped): - return Wrapper(wrapped) - - class Class: - @decorator - @classmethod - def inner(cls): - # This should already work. - return 'spam' - - @classmethod - @decorator - def outer(cls): - # Raised TypeError with a message saying that the 'Wrapper' - # object is not callable. - return 'eggs' - - self.assertEqual(Class.inner(), 'spam') - self.assertEqual(Class.outer(), 'eggs') - self.assertEqual(Class().inner(), 'spam') - self.assertEqual(Class().outer(), 'eggs') - def test_bound_function_inside_classmethod(self): class A: def foo(self, cls): @@ -339,91 +301,6 @@ class B: self.assertEqual(B.bar(), 'spam') - def test_wrapped_classmethod_inside_classmethod(self): - class MyClassMethod1: - def __init__(self, func): - self.func = func - - def __call__(self, cls): - if hasattr(self.func, '__get__'): - return self.func.__get__(cls, cls)() - return self.func(cls) - - def __get__(self, instance, owner=None): - if owner is None: - owner = type(instance) - return MethodType(self, owner) - - class MyClassMethod2: - def __init__(self, func): - if isinstance(func, classmethod): - func = func.__func__ - self.func = func - - def __call__(self, cls): - return self.func(cls) - - def __get__(self, instance, owner=None): - if owner is None: - owner = type(instance) - return MethodType(self, owner) - - for myclassmethod in [MyClassMethod1, MyClassMethod2]: - class A: - @myclassmethod - def f1(cls): - return cls - - @classmethod - @myclassmethod - def f2(cls): - return cls - - @myclassmethod - @classmethod - def f3(cls): - return cls - - @classmethod - @classmethod - def f4(cls): - return cls - - @myclassmethod - @MyClassMethod1 - def f5(cls): - return cls - - @myclassmethod - @MyClassMethod2 - def f6(cls): - return cls - - self.assertIs(A.f1(), A) - self.assertIs(A.f2(), A) - self.assertIs(A.f3(), A) - self.assertIs(A.f4(), A) - self.assertIs(A.f5(), A) - self.assertIs(A.f6(), A) - a = A() - self.assertIs(a.f1(), A) - self.assertIs(a.f2(), A) - self.assertIs(a.f3(), A) - self.assertIs(a.f4(), A) - self.assertIs(a.f5(), A) - self.assertIs(a.f6(), A) - - def f(cls): - return cls - - self.assertIs(myclassmethod(f).__get__(a)(), A) - self.assertIs(myclassmethod(f).__get__(a, A)(), A) - self.assertIs(myclassmethod(f).__get__(A, A)(), A) - self.assertIs(myclassmethod(f).__get__(A)(), type(A)) - self.assertIs(classmethod(f).__get__(a)(), A) - self.assertIs(classmethod(f).__get__(a, A)(), A) - self.assertIs(classmethod(f).__get__(A, A)(), A) - self.assertIs(classmethod(f).__get__(A)(), type(A)) class TestClassDecorators(unittest.TestCase): diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py index ad3eefba365856..fd0af9b30a0a71 100644 --- a/Lib/test/test_descr.py +++ b/Lib/test/test_descr.py @@ -989,8 +989,8 @@ class EditableScrollablePane(ScrollablePane,EditablePane): pass def test_mro_disagreement(self): # Testing error messages for MRO disagreement... - mro_err_msg = """Cannot create a consistent method resolution -order (MRO) for bases """ + mro_err_msg = ("Cannot create a consistent method resolution " + "order (MRO) for bases ") def raises(exc, expected, callable, *args): try: @@ -1989,7 +1989,7 @@ def __getattr__(self, attr): ns = {} exec(code, ns) number_attrs = ns["number_attrs"] - # Warm up the the function for quickening (PEP 659) + # Warm up the function for quickening (PEP 659) for _ in range(30): self.assertEqual(number_attrs(Numbers()), list(range(280))) @@ -4457,6 +4457,7 @@ class Oops(object): o.whatever = Provoker(o) del o + @support.requires_resource('cpu') def test_wrapper_segfault(self): # SF 927248: deeply nested wrappers could cause stack overflow f = lambda:None @@ -4756,24 +4757,24 @@ class Thing: thing = Thing() for i in range(20): with self.assertRaises(TypeError): - # PRECALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS + # CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS list.sort(thing) for i in range(20): with self.assertRaises(TypeError): - # PRECALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS + # CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS str.split(thing) for i in range(20): with self.assertRaises(TypeError): - # PRECALL_NO_KW_METHOD_DESCRIPTOR_NOARGS + # CALL_METHOD_DESCRIPTOR_NOARGS str.upper(thing) for i in range(20): with self.assertRaises(TypeError): - # PRECALL_NO_KW_METHOD_DESCRIPTOR_FAST + # CALL_METHOD_DESCRIPTOR_FAST str.strip(thing) from collections import deque for i in range(20): with self.assertRaises(TypeError): - # PRECALL_NO_KW_METHOD_DESCRIPTOR_O + # CALL_METHOD_DESCRIPTOR_O deque.append(thing, thing) def test_repr_as_str(self): @@ -5003,6 +5004,21 @@ class Child(Parent): gc.collect() self.assertEqual(Parent.__subclasses__(), []) + def test_instance_method_get_behavior(self): + # test case for gh-113157 + + class A: + def meth(self): + return self + + class B: + pass + + a = A() + b = B() + b.meth = a.meth.__get__(b, B) + self.assertEqual(b.meth(), a) + def test_attr_raise_through_property(self): # test case for gh-103272 class A: diff --git a/Lib/test/test_dict.py b/Lib/test/test_dict.py index fbc6ce8282de3c..620d0ca4f4c2da 100644 --- a/Lib/test/test_dict.py +++ b/Lib/test/test_dict.py @@ -8,7 +8,7 @@ import unittest import weakref from test import support -from test.support import import_helper, C_RECURSION_LIMIT +from test.support import import_helper, Py_C_RECURSION_LIMIT class DictTest(unittest.TestCase): @@ -596,7 +596,7 @@ def __repr__(self): def test_repr_deep(self): d = {} - for i in range(C_RECURSION_LIMIT + 1): + for i in range(Py_C_RECURSION_LIMIT + 1): d = {1: d} self.assertRaises(RecursionError, repr, d) @@ -1582,8 +1582,8 @@ class CAPITest(unittest.TestCase): # Test _PyDict_GetItem_KnownHash() @support.cpython_only def test_getitem_knownhash(self): - _testcapi = import_helper.import_module('_testcapi') - dict_getitem_knownhash = _testcapi.dict_getitem_knownhash + _testinternalcapi = import_helper.import_module('_testinternalcapi') + dict_getitem_knownhash = _testinternalcapi.dict_getitem_knownhash d = {'x': 1, 'y': 2, 'z': 3} self.assertEqual(dict_getitem_knownhash(d, 'x', hash('x')), 1) diff --git a/Lib/test/test_dictviews.py b/Lib/test/test_dictviews.py index 2bd9d6eef8cfc6..cad568b6ac4c2d 100644 --- a/Lib/test/test_dictviews.py +++ b/Lib/test/test_dictviews.py @@ -1,9 +1,8 @@ import collections.abc import copy import pickle -import sys import unittest -from test.support import C_RECURSION_LIMIT +from test.support import Py_C_RECURSION_LIMIT class DictSetTest(unittest.TestCase): @@ -280,7 +279,7 @@ def test_recursive_repr(self): def test_deeply_nested_repr(self): d = {} - for i in range(C_RECURSION_LIMIT//2 + 100): + for i in range(Py_C_RECURSION_LIMIT//2 + 100): d = {42: d.values()} self.assertRaises(RecursionError, repr, d) diff --git a/Lib/test/test_dis.py b/Lib/test/test_dis.py index 642b26163ab248..097f05afdf1517 100644 --- a/Lib/test/test_dis.py +++ b/Lib/test/test_dis.py @@ -2,6 +2,7 @@ import contextlib import dis +import functools import io import re import sys @@ -13,6 +14,7 @@ import opcode +CACHE = dis.opmap["CACHE"] def get_tb(): def _error(): @@ -42,45 +44,45 @@ def cm(cls, x): cls.x = x == 1 dis_c_instance_method = """\ -%3d RESUME 0 - -%3d LOAD_FAST 1 (x) - LOAD_CONST 1 (1) - COMPARE_OP 72 (==) - LOAD_FAST 0 (self) - STORE_ATTR 0 (x) - RETURN_CONST 0 (None) +%3d RESUME 0 + +%3d LOAD_FAST 1 (x) + LOAD_CONST 1 (1) + COMPARE_OP 72 (==) + LOAD_FAST 0 (self) + STORE_ATTR 0 (x) + RETURN_CONST 0 (None) """ % (_C.__init__.__code__.co_firstlineno, _C.__init__.__code__.co_firstlineno + 1,) dis_c_instance_method_bytes = """\ - RESUME 0 - LOAD_FAST 1 - LOAD_CONST 1 - COMPARE_OP 72 (==) - LOAD_FAST 0 - STORE_ATTR 0 - RETURN_CONST 0 + RESUME 0 + LOAD_FAST 1 + LOAD_CONST 1 + COMPARE_OP 72 (==) + LOAD_FAST 0 + STORE_ATTR 0 + RETURN_CONST 0 """ dis_c_class_method = """\ -%3d RESUME 0 - -%3d LOAD_FAST 1 (x) - LOAD_CONST 1 (1) - COMPARE_OP 72 (==) - LOAD_FAST 0 (cls) - STORE_ATTR 0 (x) - RETURN_CONST 0 (None) +%3d RESUME 0 + +%3d LOAD_FAST 1 (x) + LOAD_CONST 1 (1) + COMPARE_OP 72 (==) + LOAD_FAST 0 (cls) + STORE_ATTR 0 (x) + RETURN_CONST 0 (None) """ % (_C.cm.__code__.co_firstlineno, _C.cm.__code__.co_firstlineno + 2,) dis_c_static_method = """\ -%3d RESUME 0 +%3d RESUME 0 -%3d LOAD_FAST 0 (x) - LOAD_CONST 1 (1) - COMPARE_OP 72 (==) - STORE_FAST 0 (x) - RETURN_CONST 0 (None) +%3d LOAD_FAST 0 (x) + LOAD_CONST 1 (1) + COMPARE_OP 72 (==) + STORE_FAST 0 (x) + RETURN_CONST 0 (None) """ % (_C.sm.__code__.co_firstlineno, _C.sm.__code__.co_firstlineno + 2,) # Class disassembling info has an extra newline at end. @@ -100,51 +102,63 @@ def _f(a): return 1 dis_f = """\ -%3d RESUME 0 +%3d RESUME 0 -%3d LOAD_GLOBAL 1 (NULL + print) - LOAD_FAST 0 (a) - CALL 1 - POP_TOP +%3d LOAD_GLOBAL 1 (print + NULL) + LOAD_FAST 0 (a) + CALL 1 + POP_TOP -%3d RETURN_CONST 1 (1) +%3d RETURN_CONST 1 (1) +""" % (_f.__code__.co_firstlineno, + _f.__code__.co_firstlineno + 1, + _f.__code__.co_firstlineno + 2) + +dis_f_with_offsets = """\ +%3d 0 RESUME 0 + +%3d 2 LOAD_GLOBAL 1 (print + NULL) + 12 LOAD_FAST 0 (a) + 14 CALL 1 + 22 POP_TOP + +%3d 24 RETURN_CONST 1 (1) """ % (_f.__code__.co_firstlineno, _f.__code__.co_firstlineno + 1, _f.__code__.co_firstlineno + 2) dis_f_co_code = """\ - RESUME 0 - LOAD_GLOBAL 1 - LOAD_FAST 0 - CALL 1 - POP_TOP - RETURN_CONST 1 + RESUME 0 + LOAD_GLOBAL 1 + LOAD_FAST 0 + CALL 1 + POP_TOP + RETURN_CONST 1 """ - def bug708901(): for res in range(1, 10): pass dis_bug708901 = """\ -%3d RESUME 0 +%3d RESUME 0 -%3d LOAD_GLOBAL 1 (NULL + range) - LOAD_CONST 1 (1) +%3d LOAD_GLOBAL 1 (range + NULL) + LOAD_CONST 1 (1) -%3d LOAD_CONST 2 (10) +%3d LOAD_CONST 2 (10) -%3d CALL 2 - GET_ITER - >> FOR_ITER 3 (to 36) - STORE_FAST 0 (res) +%3d CALL 2 + GET_ITER + L1: FOR_ITER 3 (to L2) + STORE_FAST 0 (res) -%3d JUMP_BACKWARD 5 (to 26) +%3d JUMP_BACKWARD 5 (to L1) -%3d >> END_FOR - RETURN_CONST 0 (None) +%3d L2: END_FOR + RETURN_CONST 0 (None) """ % (bug708901.__code__.co_firstlineno, bug708901.__code__.co_firstlineno + 1, bug708901.__code__.co_firstlineno + 2, @@ -159,20 +173,20 @@ def bug1333982(x=[]): pass dis_bug1333982 = """\ -%3d RESUME 0 +%3d RESUME 0 -%3d LOAD_ASSERTION_ERROR - LOAD_CONST 1 ( at 0x..., file "%s", line %d>) - MAKE_FUNCTION - LOAD_FAST 0 (x) - GET_ITER - CALL 0 +%3d LOAD_ASSERTION_ERROR + LOAD_CONST 1 ( at 0x..., file "%s", line %d>) + MAKE_FUNCTION + LOAD_FAST 0 (x) + GET_ITER + CALL 0 -%3d LOAD_CONST 2 (1) +%3d LOAD_CONST 2 (1) -%3d BINARY_OP 0 (+) - CALL 0 - RAISE_VARARGS 1 +%3d BINARY_OP 0 (+) + CALL 0 + RAISE_VARARGS 1 """ % (bug1333982.__code__.co_firstlineno, bug1333982.__code__.co_firstlineno + 1, __file__, @@ -190,25 +204,25 @@ def bug42562(): dis_bug42562 = """\ - RESUME 0 - RETURN_CONST 0 (None) + RESUME 0 + RETURN_CONST 0 (None) """ # Extended arg followed by NOP code_bug_45757 = bytes([ - 0x90, 0x01, # EXTENDED_ARG 0x01 - 0x09, 0xFF, # NOP 0xFF - 0x90, 0x01, # EXTENDED_ARG 0x01 - 0x64, 0x29, # LOAD_CONST 0x29 - 0x53, 0x00, # RETURN_VALUE 0x00 + opcode.opmap['EXTENDED_ARG'], 0x01, # EXTENDED_ARG 0x01 + opcode.opmap['NOP'], 0xFF, # NOP 0xFF + opcode.opmap['EXTENDED_ARG'], 0x01, # EXTENDED_ARG 0x01 + opcode.opmap['LOAD_CONST'], 0x29, # LOAD_CONST 0x29 + opcode.opmap['RETURN_VALUE'], 0x00, # RETURN_VALUE 0x00 ]) dis_bug_45757 = """\ - EXTENDED_ARG 1 - NOP - EXTENDED_ARG 1 - LOAD_CONST 297 - RETURN_VALUE + EXTENDED_ARG 1 + NOP + EXTENDED_ARG 1 + LOAD_CONST 297 + RETURN_VALUE """ # [255, 255, 255, 252] is -4 in a 4 byte signed integer @@ -221,10 +235,10 @@ def bug42562(): dis_bug46724 = """\ - >> EXTENDED_ARG 255 - EXTENDED_ARG 65535 - EXTENDED_ARG 16777215 - JUMP_FORWARD -4 (to 0) + L1: EXTENDED_ARG 255 + EXTENDED_ARG 65535 + EXTENDED_ARG 16777215 + JUMP_FORWARD -4 (to L1) """ def func_w_kwargs(a, b, **c): @@ -234,96 +248,96 @@ def wrap_func_w_kwargs(): func_w_kwargs(1, 2, c=5) dis_kw_names = """\ -%3d RESUME 0 - -%3d LOAD_GLOBAL 1 (NULL + func_w_kwargs) - LOAD_CONST 1 (1) - LOAD_CONST 2 (2) - LOAD_CONST 3 (5) - KW_NAMES 4 (('c',)) - CALL 3 - POP_TOP - RETURN_CONST 0 (None) +%3d RESUME 0 + +%3d LOAD_GLOBAL 1 (func_w_kwargs + NULL) + LOAD_CONST 1 (1) + LOAD_CONST 2 (2) + LOAD_CONST 3 (5) + LOAD_CONST 4 (('c',)) + CALL_KW 3 + POP_TOP + RETURN_CONST 0 (None) """ % (wrap_func_w_kwargs.__code__.co_firstlineno, wrap_func_w_kwargs.__code__.co_firstlineno + 1) dis_intrinsic_1_2 = """\ - 0 RESUME 0 - - 1 LOAD_CONST 0 (0) - LOAD_CONST 1 (('*',)) - IMPORT_NAME 0 (math) - CALL_INTRINSIC_1 2 (INTRINSIC_IMPORT_STAR) - POP_TOP - RETURN_CONST 2 (None) + 0 RESUME 0 + + 1 LOAD_CONST 0 (0) + LOAD_CONST 1 (('*',)) + IMPORT_NAME 0 (math) + CALL_INTRINSIC_1 2 (INTRINSIC_IMPORT_STAR) + POP_TOP + RETURN_CONST 2 (None) """ dis_intrinsic_1_5 = """\ - 0 RESUME 0 + 0 RESUME 0 - 1 LOAD_NAME 0 (a) - CALL_INTRINSIC_1 5 (INTRINSIC_UNARY_POSITIVE) - RETURN_VALUE + 1 LOAD_NAME 0 (a) + CALL_INTRINSIC_1 5 (INTRINSIC_UNARY_POSITIVE) + RETURN_VALUE """ dis_intrinsic_1_6 = """\ - 0 RESUME 0 + 0 RESUME 0 - 1 BUILD_LIST 0 - LOAD_NAME 0 (a) - LIST_EXTEND 1 - CALL_INTRINSIC_1 6 (INTRINSIC_LIST_TO_TUPLE) - RETURN_VALUE + 1 BUILD_LIST 0 + LOAD_NAME 0 (a) + LIST_EXTEND 1 + CALL_INTRINSIC_1 6 (INTRINSIC_LIST_TO_TUPLE) + RETURN_VALUE """ _BIG_LINENO_FORMAT = """\ - 1 RESUME 0 + 1 RESUME 0 -%3d LOAD_GLOBAL 0 (spam) - POP_TOP - RETURN_CONST 0 (None) +%3d LOAD_GLOBAL 0 (spam) + POP_TOP + RETURN_CONST 0 (None) """ _BIG_LINENO_FORMAT2 = """\ - 1 RESUME 0 + 1 RESUME 0 -%4d LOAD_GLOBAL 0 (spam) - POP_TOP - RETURN_CONST 0 (None) +%4d LOAD_GLOBAL 0 (spam) + POP_TOP + RETURN_CONST 0 (None) """ dis_module_expected_results = """\ Disassembly of f: - 4 RESUME 0 - RETURN_CONST 0 (None) + 4 RESUME 0 + RETURN_CONST 0 (None) Disassembly of g: - 5 RESUME 0 - RETURN_CONST 0 (None) + 5 RESUME 0 + RETURN_CONST 0 (None) """ expr_str = "x + 1" dis_expr_str = """\ - 0 RESUME 0 + 0 RESUME 0 - 1 LOAD_NAME 0 (x) - LOAD_CONST 0 (1) - BINARY_OP 0 (+) - RETURN_VALUE + 1 LOAD_NAME 0 (x) + LOAD_CONST 0 (1) + BINARY_OP 0 (+) + RETURN_VALUE """ simple_stmt_str = "x = x + 1" dis_simple_stmt_str = """\ - 0 RESUME 0 + 0 RESUME 0 - 1 LOAD_NAME 0 (x) - LOAD_CONST 0 (1) - BINARY_OP 0 (+) - STORE_NAME 0 (x) - RETURN_CONST 1 (None) + 1 LOAD_NAME 0 (x) + LOAD_CONST 0 (1) + BINARY_OP 0 (+) + STORE_NAME 0 (x) + RETURN_CONST 1 (None) """ annot_stmt_str = """\ @@ -335,34 +349,34 @@ def wrap_func_w_kwargs(): # leading newline is for a reason (tests lineno) dis_annot_stmt_str = """\ - 0 RESUME 0 - - 2 SETUP_ANNOTATIONS - LOAD_CONST 0 (1) - STORE_NAME 0 (x) - LOAD_NAME 1 (int) - LOAD_NAME 2 (__annotations__) - LOAD_CONST 1 ('x') - STORE_SUBSCR - - 3 PUSH_NULL - LOAD_NAME 3 (fun) - LOAD_CONST 0 (1) - CALL 1 - LOAD_NAME 2 (__annotations__) - LOAD_CONST 2 ('y') - STORE_SUBSCR - - 4 LOAD_CONST 0 (1) - LOAD_NAME 4 (lst) - PUSH_NULL - LOAD_NAME 3 (fun) - LOAD_CONST 3 (0) - CALL 1 - STORE_SUBSCR - LOAD_NAME 1 (int) - POP_TOP - RETURN_CONST 4 (None) + 0 RESUME 0 + + 2 SETUP_ANNOTATIONS + LOAD_CONST 0 (1) + STORE_NAME 0 (x) + LOAD_NAME 1 (int) + LOAD_NAME 2 (__annotations__) + LOAD_CONST 1 ('x') + STORE_SUBSCR + + 3 LOAD_NAME 3 (fun) + PUSH_NULL + LOAD_CONST 0 (1) + CALL 1 + LOAD_NAME 2 (__annotations__) + LOAD_CONST 2 ('y') + STORE_SUBSCR + + 4 LOAD_CONST 0 (1) + LOAD_NAME 4 (lst) + LOAD_NAME 3 (fun) + PUSH_NULL + LOAD_CONST 3 (0) + CALL 1 + STORE_SUBSCR + LOAD_NAME 1 (int) + POP_TOP + RETURN_CONST 4 (None) """ compound_stmt_str = """\ @@ -372,61 +386,67 @@ def wrap_func_w_kwargs(): # Trailing newline has been deliberately omitted dis_compound_stmt_str = """\ - 0 RESUME 0 + 0 RESUME 0 - 1 LOAD_CONST 0 (0) - STORE_NAME 0 (x) + 1 LOAD_CONST 0 (0) + STORE_NAME 0 (x) - 2 NOP + 2 NOP - 3 >> LOAD_NAME 0 (x) - LOAD_CONST 1 (1) - BINARY_OP 13 (+=) - STORE_NAME 0 (x) + 3 L1: LOAD_NAME 0 (x) + LOAD_CONST 1 (1) + BINARY_OP 13 (+=) + STORE_NAME 0 (x) - 2 JUMP_BACKWARD 7 (to 8) + 2 JUMP_BACKWARD 7 (to L1) """ dis_traceback = """\ -%3d RESUME 0 - -%3d NOP - -%3d LOAD_CONST 1 (1) - LOAD_CONST 2 (0) - --> BINARY_OP 11 (/) - POP_TOP - -%3d LOAD_FAST_CHECK 1 (tb) - RETURN_VALUE - >> PUSH_EXC_INFO - -%3d LOAD_GLOBAL 0 (Exception) - CHECK_EXC_MATCH - POP_JUMP_IF_FALSE 23 (to 80) - STORE_FAST 0 (e) - -%3d LOAD_FAST 0 (e) - LOAD_ATTR 2 (__traceback__) - STORE_FAST 1 (tb) - POP_EXCEPT - LOAD_CONST 0 (None) - STORE_FAST 0 (e) - DELETE_FAST 0 (e) - -%3d LOAD_FAST 1 (tb) - RETURN_VALUE - >> LOAD_CONST 0 (None) - STORE_FAST 0 (e) - DELETE_FAST 0 (e) - RERAISE 1 - -%3d >> RERAISE 0 - >> COPY 3 - POP_EXCEPT - RERAISE 1 +%4d RESUME 0 + +%4d NOP + +%4d L1: LOAD_CONST 1 (1) + LOAD_CONST 2 (0) + --> BINARY_OP 11 (/) + POP_TOP + +%4d L2: LOAD_FAST_CHECK 1 (tb) + RETURN_VALUE + + -- L3: PUSH_EXC_INFO + +%4d LOAD_GLOBAL 0 (Exception) + CHECK_EXC_MATCH + POP_JUMP_IF_FALSE 23 (to L7) + STORE_FAST 0 (e) + +%4d L4: LOAD_FAST 0 (e) + LOAD_ATTR 2 (__traceback__) + STORE_FAST 1 (tb) + L5: POP_EXCEPT + LOAD_CONST 0 (None) + STORE_FAST 0 (e) + DELETE_FAST 0 (e) + +%4d LOAD_FAST 1 (tb) + RETURN_VALUE + + -- L6: LOAD_CONST 0 (None) + STORE_FAST 0 (e) + DELETE_FAST 0 (e) + RERAISE 1 + +%4d L7: RERAISE 0 + + -- L8: COPY 3 + POP_EXCEPT + RERAISE 1 ExceptionTable: -4 rows + L1 to L2 -> L3 [0] + L3 to L4 -> L8 [1] lasti + L4 to L5 -> L6 [1] lasti + L6 to L8 -> L8 [1] lasti """ % (TRACEBACK_CODE.co_firstlineno, TRACEBACK_CODE.co_firstlineno + 1, TRACEBACK_CODE.co_firstlineno + 2, @@ -440,25 +460,25 @@ def _fstring(a, b, c, d): return f'{a} {b:4} {c!r} {d!r:4}' dis_fstring = """\ -%3d RESUME 0 - -%3d LOAD_FAST 0 (a) - FORMAT_SIMPLE - LOAD_CONST 1 (' ') - LOAD_FAST 1 (b) - LOAD_CONST 2 ('4') - FORMAT_WITH_SPEC - LOAD_CONST 1 (' ') - LOAD_FAST 2 (c) - CONVERT_VALUE 2 (repr) - FORMAT_SIMPLE - LOAD_CONST 1 (' ') - LOAD_FAST 3 (d) - CONVERT_VALUE 2 (repr) - LOAD_CONST 2 ('4') - FORMAT_WITH_SPEC - BUILD_STRING 7 - RETURN_VALUE +%3d RESUME 0 + +%3d LOAD_FAST 0 (a) + FORMAT_SIMPLE + LOAD_CONST 1 (' ') + LOAD_FAST 1 (b) + LOAD_CONST 2 ('4') + FORMAT_WITH_SPEC + LOAD_CONST 1 (' ') + LOAD_FAST 2 (c) + CONVERT_VALUE 2 (repr) + FORMAT_SIMPLE + LOAD_CONST 1 (' ') + LOAD_FAST 3 (d) + CONVERT_VALUE 2 (repr) + LOAD_CONST 2 ('4') + FORMAT_WITH_SPEC + BUILD_STRING 7 + RETURN_VALUE """ % (_fstring.__code__.co_firstlineno, _fstring.__code__.co_firstlineno + 1) def _with(c): @@ -467,43 +487,45 @@ def _with(c): y = 2 dis_with = """\ -%3d RESUME 0 - -%3d LOAD_FAST 0 (c) - BEFORE_WITH - POP_TOP - -%3d LOAD_CONST 1 (1) - STORE_FAST 1 (x) - -%3d LOAD_CONST 0 (None) - LOAD_CONST 0 (None) - LOAD_CONST 0 (None) - CALL 2 - POP_TOP - -%3d LOAD_CONST 2 (2) - STORE_FAST 2 (y) - RETURN_CONST 0 (None) - -%3d >> PUSH_EXC_INFO - WITH_EXCEPT_START - TO_BOOL - POP_JUMP_IF_TRUE 1 (to 50) - RERAISE 2 - >> POP_TOP - POP_EXCEPT - POP_TOP - POP_TOP - -%3d LOAD_CONST 2 (2) - STORE_FAST 2 (y) - RETURN_CONST 0 (None) - >> COPY 3 - POP_EXCEPT - RERAISE 1 +%4d RESUME 0 + +%4d LOAD_FAST 0 (c) + BEFORE_WITH + L1: POP_TOP + +%4d LOAD_CONST 1 (1) + STORE_FAST 1 (x) + +%4d L2: LOAD_CONST 0 (None) + LOAD_CONST 0 (None) + LOAD_CONST 0 (None) + CALL 2 + POP_TOP + +%4d LOAD_CONST 2 (2) + STORE_FAST 2 (y) + RETURN_CONST 0 (None) + +%4d L3: PUSH_EXC_INFO + WITH_EXCEPT_START + TO_BOOL + POP_JUMP_IF_TRUE 1 (to L4) + RERAISE 2 + L4: POP_TOP + L5: POP_EXCEPT + POP_TOP + POP_TOP + +%4d LOAD_CONST 2 (2) + STORE_FAST 2 (y) + RETURN_CONST 0 (None) + + -- L6: COPY 3 + POP_EXCEPT + RERAISE 1 ExceptionTable: -2 rows + L1 to L2 -> L3 [1] lasti + L3 to L5 -> L6 [3] lasti """ % (_with.__code__.co_firstlineno, _with.__code__.co_firstlineno + 1, _with.__code__.co_firstlineno + 2, @@ -519,79 +541,97 @@ async def _asyncwith(c): y = 2 dis_asyncwith = """\ -%3d RETURN_GENERATOR - POP_TOP - RESUME 0 - -%3d LOAD_FAST 0 (c) - BEFORE_ASYNC_WITH - GET_AWAITABLE 1 - LOAD_CONST 0 (None) - >> SEND 3 (to 24) - YIELD_VALUE 2 - RESUME 3 - JUMP_BACKWARD_NO_INTERRUPT 5 (to 14) - >> END_SEND - POP_TOP - -%3d LOAD_CONST 1 (1) - STORE_FAST 1 (x) - -%3d LOAD_CONST 0 (None) - LOAD_CONST 0 (None) - LOAD_CONST 0 (None) - CALL 2 - GET_AWAITABLE 2 - LOAD_CONST 0 (None) - >> SEND 3 (to 60) - YIELD_VALUE 2 - RESUME 3 - JUMP_BACKWARD_NO_INTERRUPT 5 (to 50) - >> END_SEND - POP_TOP - -%3d LOAD_CONST 2 (2) - STORE_FAST 2 (y) - RETURN_CONST 0 (None) - -%3d >> CLEANUP_THROW - JUMP_BACKWARD 26 (to 24) - >> CLEANUP_THROW - JUMP_BACKWARD 11 (to 60) - >> PUSH_EXC_INFO - WITH_EXCEPT_START - GET_AWAITABLE 2 - LOAD_CONST 0 (None) - >> SEND 4 (to 102) - YIELD_VALUE 3 - RESUME 3 - JUMP_BACKWARD_NO_INTERRUPT 5 (to 90) - >> CLEANUP_THROW - >> END_SEND - TO_BOOL - POP_JUMP_IF_TRUE 1 (to 116) - RERAISE 2 - >> POP_TOP - POP_EXCEPT - POP_TOP - POP_TOP - -%3d LOAD_CONST 2 (2) - STORE_FAST 2 (y) - RETURN_CONST 0 (None) - >> COPY 3 - POP_EXCEPT - RERAISE 1 - >> CALL_INTRINSIC_1 3 (INTRINSIC_STOPITERATION_ERROR) - RERAISE 1 +%4d RETURN_GENERATOR + POP_TOP + L1: RESUME 0 + +%4d LOAD_FAST 0 (c) + BEFORE_ASYNC_WITH + GET_AWAITABLE 1 + LOAD_CONST 0 (None) + L2: SEND 3 (to L5) + L3: YIELD_VALUE 1 + L4: RESUME 3 + JUMP_BACKWARD_NO_INTERRUPT 5 (to L2) + L5: END_SEND + L6: POP_TOP + +%4d LOAD_CONST 1 (1) + STORE_FAST 1 (x) + +%4d L7: LOAD_CONST 0 (None) + LOAD_CONST 0 (None) + LOAD_CONST 0 (None) + CALL 2 + GET_AWAITABLE 2 + LOAD_CONST 0 (None) + L8: SEND 3 (to L11) + L9: YIELD_VALUE 1 + L10: RESUME 3 + JUMP_BACKWARD_NO_INTERRUPT 5 (to L8) + L11: END_SEND + POP_TOP + +%4d LOAD_CONST 2 (2) + STORE_FAST 2 (y) + RETURN_CONST 0 (None) + +%4d L12: CLEANUP_THROW + + -- L13: JUMP_BACKWARD_NO_INTERRUPT 25 (to L5) + +%4d L14: CLEANUP_THROW + + -- L15: JUMP_BACKWARD_NO_INTERRUPT 9 (to L11) + +%4d L16: PUSH_EXC_INFO + WITH_EXCEPT_START + GET_AWAITABLE 2 + LOAD_CONST 0 (None) + L17: SEND 4 (to L21) + L18: YIELD_VALUE 1 + L19: RESUME 3 + JUMP_BACKWARD_NO_INTERRUPT 5 (to L17) + L20: CLEANUP_THROW + L21: END_SEND + TO_BOOL + POP_JUMP_IF_TRUE 1 (to L22) + RERAISE 2 + L22: POP_TOP + L23: POP_EXCEPT + POP_TOP + POP_TOP + +%4d LOAD_CONST 2 (2) + STORE_FAST 2 (y) + RETURN_CONST 0 (None) + + -- L24: COPY 3 + POP_EXCEPT + RERAISE 1 + L25: CALL_INTRINSIC_1 3 (INTRINSIC_STOPITERATION_ERROR) + RERAISE 1 ExceptionTable: -12 rows + L1 to L3 -> L25 [0] lasti + L3 to L4 -> L12 [3] + L4 to L6 -> L25 [0] lasti + L6 to L7 -> L16 [1] lasti + L7 to L9 -> L25 [0] lasti + L9 to L10 -> L14 [2] + L10 to L13 -> L25 [0] lasti + L14 to L15 -> L25 [0] lasti + L16 to L18 -> L24 [3] lasti + L18 to L19 -> L20 [6] + L19 to L23 -> L24 [3] lasti + L23 to L25 -> L25 [0] lasti """ % (_asyncwith.__code__.co_firstlineno, _asyncwith.__code__.co_firstlineno + 1, _asyncwith.__code__.co_firstlineno + 2, _asyncwith.__code__.co_firstlineno + 1, _asyncwith.__code__.co_firstlineno + 3, _asyncwith.__code__.co_firstlineno + 1, + _asyncwith.__code__.co_firstlineno + 1, + _asyncwith.__code__.co_firstlineno + 1, _asyncwith.__code__.co_firstlineno + 3, ) @@ -609,61 +649,70 @@ def _tryfinallyconst(b): b() dis_tryfinally = """\ -%3d RESUME 0 - -%3d NOP - -%3d LOAD_FAST 0 (a) - -%3d PUSH_NULL - LOAD_FAST 1 (b) - CALL 0 - POP_TOP - RETURN_VALUE - >> PUSH_EXC_INFO - PUSH_NULL - LOAD_FAST 1 (b) - CALL 0 - POP_TOP - RERAISE 0 - >> COPY 3 - POP_EXCEPT - RERAISE 1 +%4d RESUME 0 + +%4d NOP + +%4d L1: LOAD_FAST 0 (a) + +%4d L2: LOAD_FAST 1 (b) + PUSH_NULL + CALL 0 + POP_TOP + RETURN_VALUE + + -- L3: PUSH_EXC_INFO + +%4d LOAD_FAST 1 (b) + PUSH_NULL + CALL 0 + POP_TOP + RERAISE 0 + + -- L4: COPY 3 + POP_EXCEPT + RERAISE 1 ExceptionTable: -2 rows + L1 to L2 -> L3 [0] + L3 to L4 -> L4 [1] lasti """ % (_tryfinally.__code__.co_firstlineno, _tryfinally.__code__.co_firstlineno + 1, _tryfinally.__code__.co_firstlineno + 2, _tryfinally.__code__.co_firstlineno + 4, + _tryfinally.__code__.co_firstlineno + 4, ) dis_tryfinallyconst = """\ -%3d RESUME 0 - -%3d NOP - -%3d NOP - -%3d PUSH_NULL - LOAD_FAST 0 (b) - CALL 0 - POP_TOP - RETURN_CONST 1 (1) - PUSH_EXC_INFO - PUSH_NULL - LOAD_FAST 0 (b) - CALL 0 - POP_TOP - RERAISE 0 - >> COPY 3 - POP_EXCEPT - RERAISE 1 +%4d RESUME 0 + +%4d NOP + +%4d NOP + +%4d LOAD_FAST 0 (b) + PUSH_NULL + CALL 0 + POP_TOP + RETURN_CONST 1 (1) + + -- L1: PUSH_EXC_INFO + +%4d LOAD_FAST 0 (b) + PUSH_NULL + CALL 0 + POP_TOP + RERAISE 0 + + -- L2: COPY 3 + POP_EXCEPT + RERAISE 1 ExceptionTable: -1 row + L1 to L2 -> L2 [1] lasti """ % (_tryfinallyconst.__code__.co_firstlineno, _tryfinallyconst.__code__.co_firstlineno + 1, _tryfinallyconst.__code__.co_firstlineno + 2, _tryfinallyconst.__code__.co_firstlineno + 4, + _tryfinallyconst.__code__.co_firstlineno + 4, ) def _g(x): @@ -683,19 +732,19 @@ def foo(x): return foo dis_nested_0 = """\ - MAKE_CELL 0 (y) + -- MAKE_CELL 0 (y) -%3d RESUME 0 +%4d RESUME 0 -%3d LOAD_FAST 0 (y) - BUILD_TUPLE 1 - LOAD_CONST 1 () - MAKE_FUNCTION - SET_FUNCTION_ATTRIBUTE 8 (closure) - STORE_FAST 1 (foo) +%4d LOAD_FAST 0 (y) + BUILD_TUPLE 1 + LOAD_CONST 1 () + MAKE_FUNCTION + SET_FUNCTION_ATTRIBUTE 8 (closure) + STORE_FAST 1 (foo) -%3d LOAD_FAST 1 (foo) - RETURN_VALUE +%4d LOAD_FAST 1 (foo) + RETURN_VALUE """ % (_h.__code__.co_firstlineno, _h.__code__.co_firstlineno + 1, __file__, @@ -705,22 +754,22 @@ def foo(x): dis_nested_1 = """%s Disassembly of : - COPY_FREE_VARS 1 - MAKE_CELL 0 (x) - -%3d RESUME 0 - -%3d LOAD_GLOBAL 1 (NULL + list) - LOAD_FAST 0 (x) - BUILD_TUPLE 1 - LOAD_CONST 1 ( at 0x..., file "%s", line %d>) - MAKE_FUNCTION - SET_FUNCTION_ATTRIBUTE 8 (closure) - LOAD_DEREF 1 (y) - GET_ITER - CALL 0 - CALL 1 - RETURN_VALUE + -- COPY_FREE_VARS 1 + MAKE_CELL 0 (x) + +%4d RESUME 0 + +%4d LOAD_GLOBAL 1 (list + NULL) + LOAD_FAST 0 (x) + BUILD_TUPLE 1 + LOAD_CONST 1 ( at 0x..., file "%s", line %d>) + MAKE_FUNCTION + SET_FUNCTION_ATTRIBUTE 8 (closure) + LOAD_DEREF 1 (y) + GET_ITER + CALL 0 + CALL 1 + RETURN_VALUE """ % (dis_nested_0, __file__, _h.__code__.co_firstlineno + 1, @@ -732,27 +781,28 @@ def foo(x): dis_nested_2 = """%s Disassembly of at 0x..., file "%s", line %d>: - COPY_FREE_VARS 1 - -%3d RETURN_GENERATOR - POP_TOP - RESUME 0 - LOAD_FAST 0 (.0) - >> FOR_ITER 10 (to 34) - STORE_FAST 1 (z) - LOAD_DEREF 2 (x) - LOAD_FAST 1 (z) - BINARY_OP 0 (+) - YIELD_VALUE 1 - RESUME 1 - POP_TOP - JUMP_BACKWARD 12 (to 10) - >> END_FOR - RETURN_CONST 0 (None) - >> CALL_INTRINSIC_1 3 (INTRINSIC_STOPITERATION_ERROR) - RERAISE 1 + -- COPY_FREE_VARS 1 + +%4d RETURN_GENERATOR + POP_TOP + L1: RESUME 0 + LOAD_FAST 0 (.0) + L2: FOR_ITER 10 (to L3) + STORE_FAST 1 (z) + LOAD_DEREF 2 (x) + LOAD_FAST 1 (z) + BINARY_OP 0 (+) + YIELD_VALUE 0 + RESUME 5 + POP_TOP + JUMP_BACKWARD 12 (to L2) + L3: END_FOR + RETURN_CONST 0 (None) + + -- L4: CALL_INTRINSIC_1 3 (INTRINSIC_STOPITERATION_ERROR) + RERAISE 1 ExceptionTable: -1 row + L1 to L4 -> L4 [0] lasti """ % (dis_nested_1, __file__, _h.__code__.co_firstlineno + 3, @@ -764,14 +814,14 @@ def load_test(x, y=0): return a, b dis_load_test_quickened_code = """\ -%3d 0 RESUME 0 +%3d RESUME_CHECK 0 -%3d 2 LOAD_FAST_LOAD_FAST 1 (x, y) - 4 STORE_FAST_STORE_FAST 50 (b, a) +%3d LOAD_FAST_LOAD_FAST 1 (x, y) + STORE_FAST_STORE_FAST 50 (b, a) -%3d 6 LOAD_FAST_LOAD_FAST 35 (a, b) - 8 BUILD_TUPLE 2 - 10 RETURN_VALUE +%3d LOAD_FAST_LOAD_FAST 35 (a, b) + BUILD_TUPLE 2 + RETURN_VALUE """ % (load_test.__code__.co_firstlineno, load_test.__code__.co_firstlineno + 1, load_test.__code__.co_firstlineno + 2) @@ -781,25 +831,25 @@ def loop_test(): load_test(i) dis_loop_test_quickened_code = """\ -%3d RESUME 0 - -%3d BUILD_LIST 0 - LOAD_CONST 1 ((1, 2, 3)) - LIST_EXTEND 1 - LOAD_CONST 2 (3) - BINARY_OP 5 (*) - GET_ITER - >> FOR_ITER_LIST 14 (to 48) - STORE_FAST 0 (i) - -%3d LOAD_GLOBAL_MODULE 1 (NULL + load_test) - LOAD_FAST 0 (i) - CALL_PY_WITH_DEFAULTS 1 - POP_TOP - JUMP_BACKWARD 16 (to 16) - -%3d >> END_FOR - RETURN_CONST 0 (None) +%3d RESUME_CHECK 0 + +%3d BUILD_LIST 0 + LOAD_CONST 1 ((1, 2, 3)) + LIST_EXTEND 1 + LOAD_CONST 2 (3) + BINARY_OP 5 (*) + GET_ITER + L1: FOR_ITER_LIST 14 (to L2) + STORE_FAST 0 (i) + +%3d LOAD_GLOBAL_MODULE 1 (load_test + NULL) + LOAD_FAST 0 (i) + CALL_PY_WITH_DEFAULTS 1 + POP_TOP + JUMP_BACKWARD 16 (to L1) + +%3d L2: END_FOR + RETURN_CONST 0 (None) """ % (loop_test.__code__.co_firstlineno, loop_test.__code__.co_firstlineno + 1, loop_test.__code__.co_firstlineno + 2, @@ -809,14 +859,14 @@ def extended_arg_quick(): *_, _ = ... dis_extended_arg_quick_code = """\ -%3d 0 RESUME 0 - -%3d 2 LOAD_CONST 1 (Ellipsis) - 4 EXTENDED_ARG 1 - 6 UNPACK_EX 256 - 8 POP_TOP - 10 STORE_FAST 0 (_) - 12 RETURN_CONST 0 (None) +%3d RESUME 0 + +%3d LOAD_CONST 1 (Ellipsis) + EXTENDED_ARG 1 + UNPACK_EX 256 + POP_TOP + STORE_FAST 0 (_) + RETURN_CONST 0 (None) """% (extended_arg_quick.__code__.co_firstlineno, extended_arg_quick.__code__.co_firstlineno + 1,) @@ -828,74 +878,19 @@ class DisTestBase(unittest.TestCase): def strip_addresses(self, text): return re.sub(r'\b0x[0-9A-Fa-f]+\b', '0x...', text) - def find_offset_column(self, lines): - for line in lines: - if line and not line.startswith("Disassembly"): - break - else: - return 0, 0 - offset = 5 - while (line[offset] == " "): - offset += 1 - if (line[offset] == ">"): - offset += 2 - while (line[offset] == " "): - offset += 1 - end = offset - while line[end] in "0123456789": - end += 1 - return end-5, end - - def assert_offsets_increasing(self, text, delta): - expected_offset = 0 - lines = text.splitlines() - start, end = self.find_offset_column(lines) - for line in lines: - if not line: - continue - if line.startswith("Disassembly"): - expected_offset = 0 - continue - if line.startswith("Exception"): - break - offset = int(line[start:end]) - self.assertGreaterEqual(offset, expected_offset, line) - expected_offset = offset + delta - def assert_exception_table_increasing(self, lines): prev_start, prev_end = -1, -1 count = 0 for line in lines: - m = re.match(r' (\d+) to (\d+) -> \d+ \[\d+\]', line) + m = re.match(r' L(\d+) to L(\d+) -> L\d+ \[\d+\]', line) start, end = [int(g) for g in m.groups()] self.assertGreaterEqual(end, start) - self.assertGreater(start, prev_end) + self.assertGreaterEqual(start, prev_end) prev_start, prev_end = start, end count += 1 return count - def strip_offsets(self, text): - lines = text.splitlines(True) - start, end = self.find_offset_column(lines) - res = [] - lines = iter(lines) - for line in lines: - if line.startswith("Exception"): - res.append(line) - break - if not line or line.startswith("Disassembly"): - res.append(line) - else: - res.append(line[:start] + line[end:]) - num_rows = self.assert_exception_table_increasing(lines) - if num_rows: - res.append(f"{num_rows} row{'s' if num_rows > 1 else ''}\n") - return "".join(res) - - def do_disassembly_compare(self, got, expected, with_offsets=False): - if not with_offsets: - self.assert_offsets_increasing(got, 2) - got = self.strip_offsets(got) + def do_disassembly_compare(self, got, expected): if got != expected: got = self.strip_addresses(got) self.assertEqual(got, expected) @@ -918,20 +913,19 @@ def get_disassembly(self, func, lasti=-1, wrapper=True, **kwargs): def get_disassemble_as_string(self, func, lasti=-1): return self.get_disassembly(func, lasti, False) - def do_disassembly_test(self, func, expected, with_offsets=False): + def do_disassembly_test(self, func, expected, **kwargs): self.maxDiff = None - got = self.get_disassembly(func, depth=0) - self.do_disassembly_compare(got, expected, with_offsets) + got = self.get_disassembly(func, depth=0, **kwargs) + self.do_disassembly_compare(got, expected) # Add checks for dis.disco if hasattr(func, '__code__'): got_disco = io.StringIO() with contextlib.redirect_stdout(got_disco): - dis.disco(func.__code__) - self.do_disassembly_compare(got_disco.getvalue(), expected, - with_offsets) + dis.disco(func.__code__, **kwargs) + self.do_disassembly_compare(got_disco.getvalue(), expected) def test_opmap(self): - self.assertEqual(dis.opmap["NOP"], 9) + self.assertEqual(dis.opmap["CACHE"], 0) self.assertIn(dis.opmap["LOAD_CONST"], dis.hasconst) self.assertIn(dis.opmap["STORE_NAME"], dis.hasname) @@ -940,7 +934,6 @@ def test_opname(self): def test_boundaries(self): self.assertEqual(dis.opmap["EXTENDED_ARG"], dis.EXTENDED_ARG) - self.assertEqual(dis.opmap["STORE_NAME"], dis.HAVE_ARGUMENT) def test_widths(self): long_opcodes = set(['JUMP_BACKWARD_NO_INTERRUPT', @@ -957,6 +950,9 @@ def test_widths(self): def test_dis(self): self.do_disassembly_test(_f, dis_f) + def test_dis_with_offsets(self): + self.do_disassembly_test(_f, dis_f_with_offsets, show_offsets=True) + def test_bug_708901(self): self.do_disassembly_test(bug708901, dis_bug708901) @@ -980,7 +976,7 @@ def test_bug_46724(self): self.do_disassembly_test(bug46724, dis_bug46724) def test_kw_names(self): - # Test that value is displayed for KW_NAMES + # Test that value is displayed for keyword argument names: self.do_disassembly_test(wrap_func_w_kwargs, dis_kw_names) def test_intrinsic_1(self): @@ -1017,41 +1013,6 @@ def func(count): from test import dis_module self.do_disassembly_test(dis_module, dis_module_expected_results) - def test_big_offsets(self): - self.maxDiff = None - def func(count): - namespace = {} - func = "def foo(x):\n " + ";".join(["x = x + 1"] * count) + "\n return x" - exec(func, namespace) - return namespace['foo'] - - def expected(count, w): - s = ['''\ - 1 %*d RESUME 0 - - 2 %*d LOAD_FAST 0 (x) - %*d LOAD_CONST 1 (1) - %*d BINARY_OP 0 (+) -''' % (w, 0, w, 2, w, 4, w, 6)] - s += ['''\ - %*d STORE_FAST_LOAD_FAST 0 (x, x) - %*d LOAD_CONST 1 (1) - %*d BINARY_OP 0 (+) -''' % (w, 8*i + 10, w, 8*i + 12, w, 8*i + 14) - for i in range(count-1)] - s += ['''\ - %*d STORE_FAST 0 (x) - - 3 %*d LOAD_FAST 0 (x) - %*d RETURN_VALUE -''' % (w, 8*count + 2, w, 8*count + 4, w, 8*count + 6)] - return ''.join(s) - - for i in range(1, 5): - self.do_disassembly_test(func(i), expected(i, 4), True) - self.do_disassembly_test(func(1200), expected(1200, 4), True) - self.do_disassembly_test(func(1300), expected(1300, 5), True) - def test_disassemble_str(self): self.do_disassembly_test(expr_str, dis_expr_str) self.do_disassembly_test(simple_stmt_str, dis_simple_stmt_str) @@ -1132,7 +1093,7 @@ def test_dis_traceback(self): sys.last_exc = e tb_dis = self.get_disassemble_as_string(tb.tb_frame.f_code, tb.tb_lasti) - self.do_disassembly_test(None, tb_dis, True) + self.do_disassembly_test(None, tb_dis) def test_dis_object(self): self.assertRaises(TypeError, dis.dis, object()) @@ -1141,7 +1102,6 @@ def test_disassemble_recursive(self): def check(expected, **kwargs): dis = self.get_disassembly(_h, **kwargs) dis = self.strip_addresses(dis) - dis = self.strip_offsets(dis) self.assertEqual(dis, expected) check(dis_nested_0, depth=0) @@ -1168,73 +1128,73 @@ def code_quicken(f, times=ADAPTIVE_WARMUP_DELAY): def test_super_instructions(self): self.code_quicken(lambda: load_test(0, 0)) got = self.get_disassembly(load_test, adaptive=True) - self.do_disassembly_compare(got, dis_load_test_quickened_code, True) + self.do_disassembly_compare(got, dis_load_test_quickened_code) @cpython_only @requires_specialization def test_binary_specialize(self): binary_op_quicken = """\ - 0 0 RESUME 0 + 0 RESUME_CHECK 0 - 1 2 LOAD_NAME 0 (a) - 4 LOAD_NAME 1 (b) - 6 %s - 10 RETURN_VALUE + 1 LOAD_NAME 0 (a) + LOAD_NAME 1 (b) + %s + RETURN_VALUE """ co_int = compile('a + b', "", "eval") self.code_quicken(lambda: exec(co_int, {}, {'a': 1, 'b': 2})) got = self.get_disassembly(co_int, adaptive=True) - self.do_disassembly_compare(got, binary_op_quicken % "BINARY_OP_ADD_INT 0 (+)", True) + self.do_disassembly_compare(got, binary_op_quicken % "BINARY_OP_ADD_INT 0 (+)") co_unicode = compile('a + b', "", "eval") self.code_quicken(lambda: exec(co_unicode, {}, {'a': 'a', 'b': 'b'})) got = self.get_disassembly(co_unicode, adaptive=True) - self.do_disassembly_compare(got, binary_op_quicken % "BINARY_OP_ADD_UNICODE 0 (+)", True) + self.do_disassembly_compare(got, binary_op_quicken % "BINARY_OP_ADD_UNICODE 0 (+)") binary_subscr_quicken = """\ - 0 0 RESUME 0 + 0 RESUME_CHECK 0 - 1 2 LOAD_NAME 0 (a) - 4 LOAD_CONST 0 (0) - 6 %s - 10 RETURN_VALUE + 1 LOAD_NAME 0 (a) + LOAD_CONST 0 (0) + %s + RETURN_VALUE """ co_list = compile('a[0]', "", "eval") self.code_quicken(lambda: exec(co_list, {}, {'a': [0]})) got = self.get_disassembly(co_list, adaptive=True) - self.do_disassembly_compare(got, binary_subscr_quicken % "BINARY_SUBSCR_LIST_INT", True) + self.do_disassembly_compare(got, binary_subscr_quicken % "BINARY_SUBSCR_LIST_INT") co_dict = compile('a[0]', "", "eval") self.code_quicken(lambda: exec(co_dict, {}, {'a': {0: '1'}})) got = self.get_disassembly(co_dict, adaptive=True) - self.do_disassembly_compare(got, binary_subscr_quicken % "BINARY_SUBSCR_DICT", True) + self.do_disassembly_compare(got, binary_subscr_quicken % "BINARY_SUBSCR_DICT") @cpython_only @requires_specialization def test_load_attr_specialize(self): load_attr_quicken = """\ - 0 0 RESUME 0 + 0 RESUME_CHECK 0 - 1 2 LOAD_CONST 0 ('a') - 4 LOAD_ATTR_SLOT 0 (__class__) - 24 RETURN_VALUE + 1 LOAD_CONST 0 ('a') + LOAD_ATTR_SLOT 0 (__class__) + RETURN_VALUE """ co = compile("'a'.__class__", "", "eval") self.code_quicken(lambda: exec(co, {}, {})) got = self.get_disassembly(co, adaptive=True) - self.do_disassembly_compare(got, load_attr_quicken, True) + self.do_disassembly_compare(got, load_attr_quicken) @cpython_only @requires_specialization def test_call_specialize(self): call_quicken = """\ - 0 RESUME 0 + 0 RESUME_CHECK 0 - 1 PUSH_NULL - LOAD_NAME 0 (str) - LOAD_CONST 0 (1) - CALL_NO_KW_STR_1 1 - RETURN_VALUE + 1 LOAD_NAME 0 (str) + PUSH_NULL + LOAD_CONST 0 (1) + CALL_STR_1 1 + RETURN_VALUE """ co = compile("str(1)", "", "eval") self.code_quicken(lambda: exec(co, {}, {})) @@ -1250,13 +1210,19 @@ def test_loop_quicken(self): got = self.get_disassembly(loop_test, adaptive=True) expected = dis_loop_test_quickened_code if _testinternalcapi.get_optimizer(): - expected = expected.replace("JUMP_BACKWARD ", "ENTER_EXECUTOR") + # We *may* see ENTER_EXECUTOR in the disassembly. This is a + # temporary hack to keep the test working until dis is able to + # handle the instruction correctly (GH-112383): + got = got.replace( + "ENTER_EXECUTOR 16", + "JUMP_BACKWARD 16 (to L1)", + ) self.do_disassembly_compare(got, expected) @cpython_only def test_extended_arg_quick(self): got = self.get_disassembly(extended_arg_quick) - self.do_disassembly_compare(got, dis_extended_arg_quick_code, True) + self.do_disassembly_compare(got, dis_extended_arg_quick_code) def get_cached_values(self, quickened, adaptive): def f(): @@ -1268,9 +1234,9 @@ def f(): else: # "copy" the code to un-quicken it: f.__code__ = f.__code__.replace() - for instruction in dis.get_instructions( + for instruction in _unroll_caches_as_Instructions(dis.get_instructions( f, show_caches=True, adaptive=adaptive - ): + ), show_caches=True): if instruction.opname == "CACHE": yield instruction.argrepr @@ -1303,19 +1269,22 @@ def f(): # However, this might change in the future. So we explicitly try to find # a CACHE entry in the instructions. If we can't do that, fail the test - for inst in dis.get_instructions(f, show_caches=True): + for inst in _unroll_caches_as_Instructions( + dis.get_instructions(f, show_caches=True), show_caches=True): if inst.opname == "CACHE": op_offset = inst.offset - 2 cache_offset = inst.offset break + else: + opname = inst.opname else: self.fail("Can't find a CACHE entry in the function provided to do the test") assem_op = self.get_disassembly(f.__code__, lasti=op_offset, wrapper=False) assem_cache = self.get_disassembly(f.__code__, lasti=cache_offset, wrapper=False) - # Make sure --> exists and points to the correct offset - self.assertRegex(assem_op, fr"-->\s+{op_offset}") + # Make sure --> exists and points to the correct op + self.assertRegex(assem_op, fr"--> {opname}") # Make sure when lasti points to cache, it shows the same disassembly self.assertEqual(assem_op, assem_cache) @@ -1612,210 +1581,210 @@ def _prepare_test_cases(): result = result.replace(repr(code_object_inner), "code_object_inner") print(result) -# _prepare_test_cases() +# from test.test_dis import _prepare_test_cases; _prepare_test_cases() Instruction = dis.Instruction expected_opinfo_outer = [ - Instruction(opname='MAKE_CELL', opcode=135, arg=0, argval='a', argrepr='a', offset=0, start_offset=0, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='MAKE_CELL', opcode=135, arg=1, argval='b', argrepr='b', offset=2, start_offset=2, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='RESUME', opcode=151, arg=0, argval=0, argrepr='', offset=4, start_offset=4, starts_line=1, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=5, argval=(3, 4), argrepr='(3, 4)', offset=6, start_offset=6, starts_line=2, is_jump_target=False, positions=None), - Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='a', argrepr='a', offset=8, start_offset=8, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_FAST', opcode=124, arg=1, argval='b', argrepr='b', offset=10, start_offset=10, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='BUILD_TUPLE', opcode=102, arg=2, argval=2, argrepr='', offset=12, start_offset=12, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=1, argval=code_object_f, argrepr=repr(code_object_f), offset=14, start_offset=14, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='MAKE_FUNCTION', opcode=24, arg=None, argval=None, argrepr='', offset=16, start_offset=16, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='SET_FUNCTION_ATTRIBUTE', opcode=177, arg=8, argval=8, argrepr='closure', offset=18, start_offset=18, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='SET_FUNCTION_ATTRIBUTE', opcode=177, arg=1, argval=1, argrepr='defaults', offset=20, start_offset=20, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='STORE_FAST', opcode=125, arg=2, argval='f', argrepr='f', offset=22, start_offset=22, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='NULL + print', offset=24, start_offset=24, starts_line=7, is_jump_target=False, positions=None), - Instruction(opname='LOAD_DEREF', opcode=137, arg=0, argval='a', argrepr='a', offset=34, start_offset=34, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_DEREF', opcode=137, arg=1, argval='b', argrepr='b', offset=36, start_offset=36, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=2, argval='', argrepr="''", offset=38, start_offset=38, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=3, argval=1, argrepr='1', offset=40, start_offset=40, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='BUILD_LIST', opcode=103, arg=0, argval=0, argrepr='', offset=42, start_offset=42, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='BUILD_MAP', opcode=105, arg=0, argval=0, argrepr='', offset=44, start_offset=44, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=4, argval='Hello world!', argrepr="'Hello world!'", offset=46, start_offset=46, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL', opcode=171, arg=7, argval=7, argrepr='', offset=48, start_offset=48, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=56, start_offset=56, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_FAST', opcode=124, arg=2, argval='f', argrepr='f', offset=58, start_offset=58, starts_line=8, is_jump_target=False, positions=None), - Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=60, start_offset=60, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='MAKE_CELL', opcode=94, arg=0, argval='a', argrepr='a', offset=0, start_offset=0, starts_line=True, line_number=None, label=None, positions=None), + Instruction(opname='MAKE_CELL', opcode=94, arg=1, argval='b', argrepr='b', offset=2, start_offset=2, starts_line=False, line_number=None, label=None, positions=None), + Instruction(opname='RESUME', opcode=149, arg=0, argval=0, argrepr='', offset=4, start_offset=4, starts_line=True, line_number=1, label=None, positions=None), + Instruction(opname='LOAD_CONST', opcode=83, arg=5, argval=(3, 4), argrepr='(3, 4)', offset=6, start_offset=6, starts_line=True, line_number=2, label=None, positions=None), + Instruction(opname='LOAD_FAST', opcode=85, arg=0, argval='a', argrepr='a', offset=8, start_offset=8, starts_line=False, line_number=2, label=None, positions=None), + Instruction(opname='LOAD_FAST', opcode=85, arg=1, argval='b', argrepr='b', offset=10, start_offset=10, starts_line=False, line_number=2, label=None, positions=None), + Instruction(opname='BUILD_TUPLE', opcode=52, arg=2, argval=2, argrepr='', offset=12, start_offset=12, starts_line=False, line_number=2, label=None, positions=None), + Instruction(opname='LOAD_CONST', opcode=83, arg=1, argval=code_object_f, argrepr=repr(code_object_f), offset=14, start_offset=14, starts_line=False, line_number=2, label=None, positions=None), + Instruction(opname='MAKE_FUNCTION', opcode=26, arg=None, argval=None, argrepr='', offset=16, start_offset=16, starts_line=False, line_number=2, label=None, positions=None), + Instruction(opname='SET_FUNCTION_ATTRIBUTE', opcode=106, arg=8, argval=8, argrepr='closure', offset=18, start_offset=18, starts_line=False, line_number=2, label=None, positions=None), + Instruction(opname='SET_FUNCTION_ATTRIBUTE', opcode=106, arg=1, argval=1, argrepr='defaults', offset=20, start_offset=20, starts_line=False, line_number=2, label=None, positions=None), + Instruction(opname='STORE_FAST', opcode=110, arg=2, argval='f', argrepr='f', offset=22, start_offset=22, starts_line=False, line_number=2, label=None, positions=None), + Instruction(opname='LOAD_GLOBAL', opcode=91, arg=1, argval='print', argrepr='print + NULL', offset=24, start_offset=24, starts_line=True, line_number=7, label=None, positions=None), + Instruction(opname='LOAD_DEREF', opcode=84, arg=0, argval='a', argrepr='a', offset=34, start_offset=34, starts_line=False, line_number=7, label=None, positions=None), + Instruction(opname='LOAD_DEREF', opcode=84, arg=1, argval='b', argrepr='b', offset=36, start_offset=36, starts_line=False, line_number=7, label=None, positions=None), + Instruction(opname='LOAD_CONST', opcode=83, arg=2, argval='', argrepr="''", offset=38, start_offset=38, starts_line=False, line_number=7, label=None, positions=None), + Instruction(opname='LOAD_CONST', opcode=83, arg=3, argval=1, argrepr='1', offset=40, start_offset=40, starts_line=False, line_number=7, label=None, positions=None), + Instruction(opname='BUILD_LIST', opcode=47, arg=0, argval=0, argrepr='', offset=42, start_offset=42, starts_line=False, line_number=7, label=None, positions=None), + Instruction(opname='BUILD_MAP', opcode=48, arg=0, argval=0, argrepr='', offset=44, start_offset=44, starts_line=False, line_number=7, label=None, positions=None), + Instruction(opname='LOAD_CONST', opcode=83, arg=4, argval='Hello world!', argrepr="'Hello world!'", offset=46, start_offset=46, starts_line=False, line_number=7, label=None, positions=None), + Instruction(opname='CALL', opcode=53, arg=7, argval=7, argrepr='', offset=48, start_offset=48, starts_line=False, line_number=7, label=None, positions=None), + Instruction(opname='POP_TOP', opcode=32, arg=None, argval=None, argrepr='', offset=56, start_offset=56, starts_line=False, line_number=7, label=None, positions=None), + Instruction(opname='LOAD_FAST', opcode=85, arg=2, argval='f', argrepr='f', offset=58, start_offset=58, starts_line=True, line_number=8, label=None, positions=None), + Instruction(opname='RETURN_VALUE', opcode=36, arg=None, argval=None, argrepr='', offset=60, start_offset=60, starts_line=False, line_number=8, label=None, positions=None), ] expected_opinfo_f = [ - Instruction(opname='COPY_FREE_VARS', opcode=149, arg=2, argval=2, argrepr='', offset=0, start_offset=0, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='MAKE_CELL', opcode=135, arg=0, argval='c', argrepr='c', offset=2, start_offset=2, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='MAKE_CELL', opcode=135, arg=1, argval='d', argrepr='d', offset=4, start_offset=4, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='RESUME', opcode=151, arg=0, argval=0, argrepr='', offset=6, start_offset=6, starts_line=2, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=2, argval=(5, 6), argrepr='(5, 6)', offset=8, start_offset=8, starts_line=3, is_jump_target=False, positions=None), - Instruction(opname='LOAD_FAST', opcode=124, arg=3, argval='a', argrepr='a', offset=10, start_offset=10, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_FAST', opcode=124, arg=4, argval='b', argrepr='b', offset=12, start_offset=12, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='c', argrepr='c', offset=14, start_offset=14, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_FAST', opcode=124, arg=1, argval='d', argrepr='d', offset=16, start_offset=16, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='BUILD_TUPLE', opcode=102, arg=4, argval=4, argrepr='', offset=18, start_offset=18, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=1, argval=code_object_inner, argrepr=repr(code_object_inner), offset=20, start_offset=20, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='MAKE_FUNCTION', opcode=24, arg=None, argval=None, argrepr='', offset=22, start_offset=22, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='SET_FUNCTION_ATTRIBUTE', opcode=177, arg=8, argval=8, argrepr='closure', offset=24, start_offset=24, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='SET_FUNCTION_ATTRIBUTE', opcode=177, arg=1, argval=1, argrepr='defaults', offset=26, start_offset=26, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='STORE_FAST', opcode=125, arg=2, argval='inner', argrepr='inner', offset=28, start_offset=28, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='NULL + print', offset=30, start_offset=30, starts_line=5, is_jump_target=False, positions=None), - Instruction(opname='LOAD_DEREF', opcode=137, arg=3, argval='a', argrepr='a', offset=40, start_offset=40, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_DEREF', opcode=137, arg=4, argval='b', argrepr='b', offset=42, start_offset=42, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_DEREF', opcode=137, arg=0, argval='c', argrepr='c', offset=44, start_offset=44, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_DEREF', opcode=137, arg=1, argval='d', argrepr='d', offset=46, start_offset=46, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL', opcode=171, arg=4, argval=4, argrepr='', offset=48, start_offset=48, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=56, start_offset=56, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_FAST', opcode=124, arg=2, argval='inner', argrepr='inner', offset=58, start_offset=58, starts_line=6, is_jump_target=False, positions=None), - Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=60, start_offset=60, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='COPY_FREE_VARS', opcode=62, arg=2, argval=2, argrepr='', offset=0, start_offset=0, starts_line=True, line_number=None, label=None, positions=None), + Instruction(opname='MAKE_CELL', opcode=94, arg=0, argval='c', argrepr='c', offset=2, start_offset=2, starts_line=False, line_number=None, label=None, positions=None), + Instruction(opname='MAKE_CELL', opcode=94, arg=1, argval='d', argrepr='d', offset=4, start_offset=4, starts_line=False, line_number=None, label=None, positions=None), + Instruction(opname='RESUME', opcode=149, arg=0, argval=0, argrepr='', offset=6, start_offset=6, starts_line=True, line_number=2, label=None, positions=None), + Instruction(opname='LOAD_CONST', opcode=83, arg=2, argval=(5, 6), argrepr='(5, 6)', offset=8, start_offset=8, starts_line=True, line_number=3, label=None, positions=None), + Instruction(opname='LOAD_FAST', opcode=85, arg=3, argval='a', argrepr='a', offset=10, start_offset=10, starts_line=False, line_number=3, label=None, positions=None), + Instruction(opname='LOAD_FAST', opcode=85, arg=4, argval='b', argrepr='b', offset=12, start_offset=12, starts_line=False, line_number=3, label=None, positions=None), + Instruction(opname='LOAD_FAST', opcode=85, arg=0, argval='c', argrepr='c', offset=14, start_offset=14, starts_line=False, line_number=3, label=None, positions=None), + Instruction(opname='LOAD_FAST', opcode=85, arg=1, argval='d', argrepr='d', offset=16, start_offset=16, starts_line=False, line_number=3, label=None, positions=None), + Instruction(opname='BUILD_TUPLE', opcode=52, arg=4, argval=4, argrepr='', offset=18, start_offset=18, starts_line=False, line_number=3, label=None, positions=None), + Instruction(opname='LOAD_CONST', opcode=83, arg=1, argval=code_object_inner, argrepr=repr(code_object_inner), offset=20, start_offset=20, starts_line=False, line_number=3, label=None, positions=None), + Instruction(opname='MAKE_FUNCTION', opcode=26, arg=None, argval=None, argrepr='', offset=22, start_offset=22, starts_line=False, line_number=3, label=None, positions=None), + Instruction(opname='SET_FUNCTION_ATTRIBUTE', opcode=106, arg=8, argval=8, argrepr='closure', offset=24, start_offset=24, starts_line=False, line_number=3, label=None, positions=None), + Instruction(opname='SET_FUNCTION_ATTRIBUTE', opcode=106, arg=1, argval=1, argrepr='defaults', offset=26, start_offset=26, starts_line=False, line_number=3, label=None, positions=None), + Instruction(opname='STORE_FAST', opcode=110, arg=2, argval='inner', argrepr='inner', offset=28, start_offset=28, starts_line=False, line_number=3, label=None, positions=None), + Instruction(opname='LOAD_GLOBAL', opcode=91, arg=1, argval='print', argrepr='print + NULL', offset=30, start_offset=30, starts_line=True, line_number=5, label=None, positions=None), + Instruction(opname='LOAD_DEREF', opcode=84, arg=3, argval='a', argrepr='a', offset=40, start_offset=40, starts_line=False, line_number=5, label=None, positions=None), + Instruction(opname='LOAD_DEREF', opcode=84, arg=4, argval='b', argrepr='b', offset=42, start_offset=42, starts_line=False, line_number=5, label=None, positions=None), + Instruction(opname='LOAD_DEREF', opcode=84, arg=0, argval='c', argrepr='c', offset=44, start_offset=44, starts_line=False, line_number=5, label=None, positions=None), + Instruction(opname='LOAD_DEREF', opcode=84, arg=1, argval='d', argrepr='d', offset=46, start_offset=46, starts_line=False, line_number=5, label=None, positions=None), + Instruction(opname='CALL', opcode=53, arg=4, argval=4, argrepr='', offset=48, start_offset=48, starts_line=False, line_number=5, label=None, positions=None), + Instruction(opname='POP_TOP', opcode=32, arg=None, argval=None, argrepr='', offset=56, start_offset=56, starts_line=False, line_number=5, label=None, positions=None), + Instruction(opname='LOAD_FAST', opcode=85, arg=2, argval='inner', argrepr='inner', offset=58, start_offset=58, starts_line=True, line_number=6, label=None, positions=None), + Instruction(opname='RETURN_VALUE', opcode=36, arg=None, argval=None, argrepr='', offset=60, start_offset=60, starts_line=False, line_number=6, label=None, positions=None), ] expected_opinfo_inner = [ - Instruction(opname='COPY_FREE_VARS', opcode=149, arg=4, argval=4, argrepr='', offset=0, start_offset=0, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='RESUME', opcode=151, arg=0, argval=0, argrepr='', offset=2, start_offset=2, starts_line=3, is_jump_target=False, positions=None), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='NULL + print', offset=4, start_offset=4, starts_line=4, is_jump_target=False, positions=None), - Instruction(opname='LOAD_DEREF', opcode=137, arg=2, argval='a', argrepr='a', offset=14, start_offset=14, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_DEREF', opcode=137, arg=3, argval='b', argrepr='b', offset=16, start_offset=16, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_DEREF', opcode=137, arg=4, argval='c', argrepr='c', offset=18, start_offset=18, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_DEREF', opcode=137, arg=5, argval='d', argrepr='d', offset=20, start_offset=20, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_FAST_LOAD_FAST', opcode=168, arg=1, argval=('e', 'f'), argrepr='e, f', offset=22, start_offset=22, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL', opcode=171, arg=6, argval=6, argrepr='', offset=24, start_offset=24, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=32, start_offset=32, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='RETURN_CONST', opcode=121, arg=0, argval=None, argrepr='None', offset=34, start_offset=34, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='COPY_FREE_VARS', opcode=62, arg=4, argval=4, argrepr='', offset=0, start_offset=0, starts_line=True, line_number=None, label=None, positions=None), + Instruction(opname='RESUME', opcode=149, arg=0, argval=0, argrepr='', offset=2, start_offset=2, starts_line=True, line_number=3, label=None, positions=None), + Instruction(opname='LOAD_GLOBAL', opcode=91, arg=1, argval='print', argrepr='print + NULL', offset=4, start_offset=4, starts_line=True, line_number=4, label=None, positions=None), + Instruction(opname='LOAD_DEREF', opcode=84, arg=2, argval='a', argrepr='a', offset=14, start_offset=14, starts_line=False, line_number=4, label=None, positions=None), + Instruction(opname='LOAD_DEREF', opcode=84, arg=3, argval='b', argrepr='b', offset=16, start_offset=16, starts_line=False, line_number=4, label=None, positions=None), + Instruction(opname='LOAD_DEREF', opcode=84, arg=4, argval='c', argrepr='c', offset=18, start_offset=18, starts_line=False, line_number=4, label=None, positions=None), + Instruction(opname='LOAD_DEREF', opcode=84, arg=5, argval='d', argrepr='d', offset=20, start_offset=20, starts_line=False, line_number=4, label=None, positions=None), + Instruction(opname='LOAD_FAST_LOAD_FAST', opcode=88, arg=1, argval=('e', 'f'), argrepr='e, f', offset=22, start_offset=22, starts_line=False, line_number=4, label=None, positions=None), + Instruction(opname='CALL', opcode=53, arg=6, argval=6, argrepr='', offset=24, start_offset=24, starts_line=False, line_number=4, label=None, positions=None), + Instruction(opname='POP_TOP', opcode=32, arg=None, argval=None, argrepr='', offset=32, start_offset=32, starts_line=False, line_number=4, label=None, positions=None), + Instruction(opname='RETURN_CONST', opcode=103, arg=0, argval=None, argrepr='None', offset=34, start_offset=34, starts_line=False, line_number=4, label=None, positions=None), ] expected_opinfo_jumpy = [ - Instruction(opname='RESUME', opcode=151, arg=0, argval=0, argrepr='', offset=0, start_offset=0, starts_line=1, is_jump_target=False, positions=None), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='range', argrepr='NULL + range', offset=2, start_offset=2, starts_line=3, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=1, argval=10, argrepr='10', offset=12, start_offset=12, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=14, start_offset=14, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='GET_ITER', opcode=68, arg=None, argval=None, argrepr='', offset=22, start_offset=22, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='FOR_ITER', opcode=93, arg=28, argval=84, argrepr='to 84', offset=24, start_offset=24, starts_line=None, is_jump_target=True, positions=None), - Instruction(opname='STORE_FAST', opcode=125, arg=0, argval='i', argrepr='i', offset=28, start_offset=28, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=30, start_offset=30, starts_line=4, is_jump_target=False, positions=None), - Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=40, start_offset=40, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=42, start_offset=42, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=50, start_offset=50, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=52, start_offset=52, starts_line=5, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=2, argval=4, argrepr='4', offset=54, start_offset=54, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='COMPARE_OP', opcode=107, arg=18, argval='<', argrepr='bool(<)', offset=56, start_offset=56, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=2, argval=66, argrepr='to 66', offset=60, start_offset=60, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='JUMP_BACKWARD', opcode=140, arg=21, argval=24, argrepr='to 24', offset=62, start_offset=62, starts_line=6, is_jump_target=False, positions=None), - Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=66, start_offset=66, starts_line=7, is_jump_target=True, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=3, argval=6, argrepr='6', offset=68, start_offset=68, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='COMPARE_OP', opcode=107, arg=148, argval='>', argrepr='bool(>)', offset=70, start_offset=70, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_JUMP_IF_TRUE', opcode=115, arg=2, argval=80, argrepr='to 80', offset=74, start_offset=74, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='JUMP_BACKWARD', opcode=140, arg=28, argval=24, argrepr='to 24', offset=76, start_offset=76, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=80, start_offset=80, starts_line=8, is_jump_target=True, positions=None), - Instruction(opname='JUMP_FORWARD', opcode=110, arg=12, argval=108, argrepr='to 108', offset=82, start_offset=82, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='END_FOR', opcode=4, arg=None, argval=None, argrepr='', offset=84, start_offset=84, starts_line=3, is_jump_target=True, positions=None), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=86, start_offset=86, starts_line=10, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=4, argval='I can haz else clause?', argrepr="'I can haz else clause?'", offset=96, start_offset=96, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=98, start_offset=98, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=106, start_offset=106, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_FAST_CHECK', opcode=127, arg=0, argval='i', argrepr='i', offset=108, start_offset=108, starts_line=11, is_jump_target=True, positions=None), - Instruction(opname='TO_BOOL', opcode=6, arg=None, argval=None, argrepr='', offset=110, start_offset=110, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=37, argval=194, argrepr='to 194', offset=118, start_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, start_offset=120, starts_line=12, is_jump_target=True, positions=None), - Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=130, start_offset=130, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=132, start_offset=132, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=140, start_offset=140, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=142, start_offset=142, starts_line=13, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=5, argval=1, argrepr='1', offset=144, start_offset=144, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='BINARY_OP', opcode=122, arg=23, argval=23, argrepr='-=', offset=146, start_offset=146, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='STORE_FAST', opcode=125, arg=0, argval='i', argrepr='i', offset=150, start_offset=150, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=152, start_offset=152, starts_line=14, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=3, argval=6, argrepr='6', offset=154, start_offset=154, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='COMPARE_OP', opcode=107, arg=148, argval='>', argrepr='bool(>)', offset=156, start_offset=156, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=2, argval=166, argrepr='to 166', offset=160, start_offset=160, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='JUMP_BACKWARD', opcode=140, arg=29, argval=108, argrepr='to 108', offset=162, start_offset=162, starts_line=15, is_jump_target=False, positions=None), - Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=166, start_offset=166, starts_line=16, is_jump_target=True, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=2, argval=4, argrepr='4', offset=168, start_offset=168, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='COMPARE_OP', opcode=107, arg=18, argval='<', argrepr='bool(<)', offset=170, start_offset=170, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=1, argval=178, argrepr='to 178', offset=174, start_offset=174, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='JUMP_FORWARD', opcode=110, arg=19, argval=216, argrepr='to 216', offset=176, start_offset=176, starts_line=17, is_jump_target=False, positions=None), - Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=178, start_offset=178, starts_line=11, is_jump_target=True, positions=None), - Instruction(opname='TO_BOOL', opcode=6, arg=None, argval=None, argrepr='', offset=180, start_offset=180, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=2, argval=194, argrepr='to 194', offset=188, start_offset=188, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='JUMP_BACKWARD', opcode=140, arg=37, argval=120, argrepr='to 120', offset=190, start_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=194, start_offset=194, 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, start_offset=204, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=206, start_offset=206, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=214, start_offset=214, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='NOP', opcode=9, arg=None, argval=None, argrepr='', offset=216, start_offset=216, starts_line=20, is_jump_target=True, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=5, argval=1, argrepr='1', offset=218, start_offset=218, starts_line=21, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=7, argval=0, argrepr='0', offset=220, start_offset=220, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='BINARY_OP', opcode=122, arg=11, argval=11, argrepr='/', offset=222, start_offset=222, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=226, start_offset=226, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=228, start_offset=228, starts_line=25, is_jump_target=False, positions=None), - Instruction(opname='BEFORE_WITH', opcode=53, arg=None, argval=None, argrepr='', offset=230, start_offset=230, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='STORE_FAST', opcode=125, arg=1, argval='dodgy', argrepr='dodgy', offset=232, start_offset=232, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=234, start_offset=234, 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, start_offset=244, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=246, start_offset=246, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=254, start_offset=254, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=256, start_offset=256, starts_line=25, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=258, start_offset=258, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=260, start_offset=260, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL', opcode=171, arg=2, argval=2, argrepr='', offset=262, start_offset=262, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=270, start_offset=270, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=272, start_offset=272, 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=282, start_offset=282, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=284, start_offset=284, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=292, start_offset=292, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='RETURN_CONST', opcode=121, arg=0, argval=None, argrepr='None', offset=294, start_offset=294, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=296, start_offset=296, starts_line=25, is_jump_target=False, positions=None), - Instruction(opname='WITH_EXCEPT_START', opcode=49, arg=None, argval=None, argrepr='', offset=298, start_offset=298, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='TO_BOOL', opcode=6, arg=None, argval=None, argrepr='', offset=300, start_offset=300, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_JUMP_IF_TRUE', opcode=115, arg=1, argval=312, argrepr='to 312', offset=308, start_offset=308, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='RERAISE', opcode=119, arg=2, argval=2, argrepr='', offset=310, start_offset=310, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=312, start_offset=312, starts_line=None, is_jump_target=True, positions=None), - Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=314, start_offset=314, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=316, start_offset=316, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=318, start_offset=318, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='JUMP_BACKWARD', opcode=140, arg=26, argval=272, argrepr='to 272', offset=320, start_offset=320, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='COPY', opcode=120, arg=3, argval=3, argrepr='', offset=324, start_offset=324, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=326, start_offset=326, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='RERAISE', opcode=119, arg=1, argval=1, argrepr='', offset=328, start_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, start_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, start_offset=332, starts_line=22, is_jump_target=False, positions=None), - Instruction(opname='CHECK_EXC_MATCH', opcode=36, arg=None, argval=None, argrepr='', offset=342, start_offset=342, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=15, argval=376, argrepr='to 376', offset=344, start_offset=344, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=346, start_offset=346, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=348, start_offset=348, 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=358, start_offset=358, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=360, start_offset=360, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=368, start_offset=368, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=370, start_offset=370, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='JUMP_BACKWARD', opcode=140, arg=52, argval=272, argrepr='to 272', offset=372, start_offset=372, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='RERAISE', opcode=119, arg=0, argval=0, argrepr='', offset=376, start_offset=376, starts_line=22, is_jump_target=True, positions=None), - Instruction(opname='COPY', opcode=120, arg=3, argval=3, argrepr='', offset=378, start_offset=378, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=380, start_offset=380, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='RERAISE', opcode=119, arg=1, argval=1, argrepr='', offset=382, start_offset=382, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=384, start_offset=384, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=386, start_offset=386, 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=396, start_offset=396, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=398, start_offset=398, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=406, start_offset=406, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='RERAISE', opcode=119, arg=0, argval=0, argrepr='', offset=408, start_offset=408, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='COPY', opcode=120, arg=3, argval=3, argrepr='', offset=410, start_offset=410, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=412, start_offset=412, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='RERAISE', opcode=119, arg=1, argval=1, argrepr='', offset=414, start_offset=414, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='RESUME', opcode=149, arg=0, argval=0, argrepr='', offset=0, start_offset=0, starts_line=True, line_number=1, label=None, positions=None), + Instruction(opname='LOAD_GLOBAL', opcode=91, arg=1, argval='range', argrepr='range + NULL', offset=2, start_offset=2, starts_line=True, line_number=3, label=None, positions=None), + Instruction(opname='LOAD_CONST', opcode=83, arg=1, argval=10, argrepr='10', offset=12, start_offset=12, starts_line=False, line_number=3, label=None, positions=None), + Instruction(opname='CALL', opcode=53, arg=1, argval=1, argrepr='', offset=14, start_offset=14, starts_line=False, line_number=3, label=None, positions=None), + Instruction(opname='GET_ITER', opcode=19, arg=None, argval=None, argrepr='', offset=22, start_offset=22, starts_line=False, line_number=3, label=None, positions=None), + Instruction(opname='FOR_ITER', opcode=72, arg=30, argval=88, argrepr='to L4', offset=24, start_offset=24, starts_line=False, line_number=3, label=1, positions=None), + Instruction(opname='STORE_FAST', opcode=110, arg=0, argval='i', argrepr='i', offset=28, start_offset=28, starts_line=False, line_number=3, label=None, positions=None), + Instruction(opname='LOAD_GLOBAL', opcode=91, arg=3, argval='print', argrepr='print + NULL', offset=30, start_offset=30, starts_line=True, line_number=4, label=None, positions=None), + Instruction(opname='LOAD_FAST', opcode=85, arg=0, argval='i', argrepr='i', offset=40, start_offset=40, starts_line=False, line_number=4, label=None, positions=None), + Instruction(opname='CALL', opcode=53, arg=1, argval=1, argrepr='', offset=42, start_offset=42, starts_line=False, line_number=4, label=None, positions=None), + Instruction(opname='POP_TOP', opcode=32, arg=None, argval=None, argrepr='', offset=50, start_offset=50, starts_line=False, line_number=4, label=None, positions=None), + Instruction(opname='LOAD_FAST', opcode=85, arg=0, argval='i', argrepr='i', offset=52, start_offset=52, starts_line=True, line_number=5, label=None, positions=None), + Instruction(opname='LOAD_CONST', opcode=83, arg=2, argval=4, argrepr='4', offset=54, start_offset=54, starts_line=False, line_number=5, label=None, positions=None), + Instruction(opname='COMPARE_OP', opcode=58, arg=18, argval='<', argrepr='bool(<)', offset=56, start_offset=56, starts_line=False, line_number=5, label=None, positions=None), + Instruction(opname='POP_JUMP_IF_FALSE', opcode=97, arg=2, argval=68, argrepr='to L2', offset=60, start_offset=60, starts_line=False, line_number=5, label=None, positions=None), + Instruction(opname='JUMP_BACKWARD', opcode=77, arg=22, argval=24, argrepr='to L1', offset=64, start_offset=64, starts_line=True, line_number=6, label=None, positions=None), + Instruction(opname='LOAD_FAST', opcode=85, arg=0, argval='i', argrepr='i', offset=68, start_offset=68, starts_line=True, line_number=7, label=2, positions=None), + Instruction(opname='LOAD_CONST', opcode=83, arg=3, argval=6, argrepr='6', offset=70, start_offset=70, starts_line=False, line_number=7, label=None, positions=None), + Instruction(opname='COMPARE_OP', opcode=58, arg=148, argval='>', argrepr='bool(>)', offset=72, start_offset=72, starts_line=False, line_number=7, label=None, positions=None), + Instruction(opname='POP_JUMP_IF_TRUE', opcode=100, arg=2, argval=84, argrepr='to L3', offset=76, start_offset=76, starts_line=False, line_number=7, label=None, positions=None), + Instruction(opname='JUMP_BACKWARD', opcode=77, arg=30, argval=24, argrepr='to L1', offset=80, start_offset=80, starts_line=False, line_number=7, label=None, positions=None), + Instruction(opname='POP_TOP', opcode=32, arg=None, argval=None, argrepr='', offset=84, start_offset=84, starts_line=True, line_number=8, label=3, positions=None), + Instruction(opname='JUMP_FORWARD', opcode=79, arg=12, argval=112, argrepr='to L5', offset=86, start_offset=86, starts_line=False, line_number=8, label=None, positions=None), + Instruction(opname='END_FOR', opcode=11, arg=None, argval=None, argrepr='', offset=88, start_offset=88, starts_line=True, line_number=3, label=4, positions=None), + Instruction(opname='LOAD_GLOBAL', opcode=91, arg=3, argval='print', argrepr='print + NULL', offset=90, start_offset=90, starts_line=True, line_number=10, label=None, positions=None), + Instruction(opname='LOAD_CONST', opcode=83, arg=4, argval='I can haz else clause?', argrepr="'I can haz else clause?'", offset=100, start_offset=100, starts_line=False, line_number=10, label=None, positions=None), + Instruction(opname='CALL', opcode=53, arg=1, argval=1, argrepr='', offset=102, start_offset=102, starts_line=False, line_number=10, label=None, positions=None), + Instruction(opname='POP_TOP', opcode=32, arg=None, argval=None, argrepr='', offset=110, start_offset=110, starts_line=False, line_number=10, label=None, positions=None), + Instruction(opname='LOAD_FAST_CHECK', opcode=87, arg=0, argval='i', argrepr='i', offset=112, start_offset=112, starts_line=True, line_number=11, label=5, positions=None), + Instruction(opname='TO_BOOL', opcode=40, arg=None, argval=None, argrepr='', offset=114, start_offset=114, starts_line=False, line_number=11, label=None, positions=None), + Instruction(opname='POP_JUMP_IF_FALSE', opcode=97, arg=40, argval=206, argrepr='to L9', offset=122, start_offset=122, starts_line=False, line_number=11, label=None, positions=None), + Instruction(opname='LOAD_GLOBAL', opcode=91, arg=3, argval='print', argrepr='print + NULL', offset=126, start_offset=126, starts_line=True, line_number=12, label=6, positions=None), + Instruction(opname='LOAD_FAST', opcode=85, arg=0, argval='i', argrepr='i', offset=136, start_offset=136, starts_line=False, line_number=12, label=None, positions=None), + Instruction(opname='CALL', opcode=53, arg=1, argval=1, argrepr='', offset=138, start_offset=138, starts_line=False, line_number=12, label=None, positions=None), + Instruction(opname='POP_TOP', opcode=32, arg=None, argval=None, argrepr='', offset=146, start_offset=146, starts_line=False, line_number=12, label=None, positions=None), + Instruction(opname='LOAD_FAST', opcode=85, arg=0, argval='i', argrepr='i', offset=148, start_offset=148, starts_line=True, line_number=13, label=None, positions=None), + Instruction(opname='LOAD_CONST', opcode=83, arg=5, argval=1, argrepr='1', offset=150, start_offset=150, starts_line=False, line_number=13, label=None, positions=None), + Instruction(opname='BINARY_OP', opcode=45, arg=23, argval=23, argrepr='-=', offset=152, start_offset=152, starts_line=False, line_number=13, label=None, positions=None), + Instruction(opname='STORE_FAST', opcode=110, arg=0, argval='i', argrepr='i', offset=156, start_offset=156, starts_line=False, line_number=13, label=None, positions=None), + Instruction(opname='LOAD_FAST', opcode=85, arg=0, argval='i', argrepr='i', offset=158, start_offset=158, starts_line=True, line_number=14, label=None, positions=None), + Instruction(opname='LOAD_CONST', opcode=83, arg=3, argval=6, argrepr='6', offset=160, start_offset=160, starts_line=False, line_number=14, label=None, positions=None), + Instruction(opname='COMPARE_OP', opcode=58, arg=148, argval='>', argrepr='bool(>)', offset=162, start_offset=162, starts_line=False, line_number=14, label=None, positions=None), + Instruction(opname='POP_JUMP_IF_FALSE', opcode=97, arg=2, argval=174, argrepr='to L7', offset=166, start_offset=166, starts_line=False, line_number=14, label=None, positions=None), + Instruction(opname='JUMP_BACKWARD', opcode=77, arg=31, argval=112, argrepr='to L5', offset=170, start_offset=170, starts_line=True, line_number=15, label=None, positions=None), + Instruction(opname='LOAD_FAST', opcode=85, arg=0, argval='i', argrepr='i', offset=174, start_offset=174, starts_line=True, line_number=16, label=7, positions=None), + Instruction(opname='LOAD_CONST', opcode=83, arg=2, argval=4, argrepr='4', offset=176, start_offset=176, starts_line=False, line_number=16, label=None, positions=None), + Instruction(opname='COMPARE_OP', opcode=58, arg=18, argval='<', argrepr='bool(<)', offset=178, start_offset=178, starts_line=False, line_number=16, label=None, positions=None), + Instruction(opname='POP_JUMP_IF_FALSE', opcode=97, arg=1, argval=188, argrepr='to L8', offset=182, start_offset=182, starts_line=False, line_number=16, label=None, positions=None), + Instruction(opname='JUMP_FORWARD', opcode=79, arg=20, argval=228, argrepr='to L10', offset=186, start_offset=186, starts_line=True, line_number=17, label=None, positions=None), + Instruction(opname='LOAD_FAST', opcode=85, arg=0, argval='i', argrepr='i', offset=188, start_offset=188, starts_line=True, line_number=11, label=8, positions=None), + Instruction(opname='TO_BOOL', opcode=40, arg=None, argval=None, argrepr='', offset=190, start_offset=190, starts_line=False, line_number=11, label=None, positions=None), + Instruction(opname='POP_JUMP_IF_FALSE', opcode=97, arg=2, argval=206, argrepr='to L9', offset=198, start_offset=198, starts_line=False, line_number=11, label=None, positions=None), + Instruction(opname='JUMP_BACKWARD', opcode=77, arg=40, argval=126, argrepr='to L6', offset=202, start_offset=202, starts_line=False, line_number=11, label=None, positions=None), + Instruction(opname='LOAD_GLOBAL', opcode=91, arg=3, argval='print', argrepr='print + NULL', offset=206, start_offset=206, starts_line=True, line_number=19, label=9, positions=None), + Instruction(opname='LOAD_CONST', opcode=83, arg=6, argval='Who let lolcatz into this test suite?', argrepr="'Who let lolcatz into this test suite?'", offset=216, start_offset=216, starts_line=False, line_number=19, label=None, positions=None), + Instruction(opname='CALL', opcode=53, arg=1, argval=1, argrepr='', offset=218, start_offset=218, starts_line=False, line_number=19, label=None, positions=None), + Instruction(opname='POP_TOP', opcode=32, arg=None, argval=None, argrepr='', offset=226, start_offset=226, starts_line=False, line_number=19, label=None, positions=None), + Instruction(opname='NOP', opcode=30, arg=None, argval=None, argrepr='', offset=228, start_offset=228, starts_line=True, line_number=20, label=10, positions=None), + Instruction(opname='LOAD_CONST', opcode=83, arg=5, argval=1, argrepr='1', offset=230, start_offset=230, starts_line=True, line_number=21, label=None, positions=None), + Instruction(opname='LOAD_CONST', opcode=83, arg=7, argval=0, argrepr='0', offset=232, start_offset=232, starts_line=False, line_number=21, label=None, positions=None), + Instruction(opname='BINARY_OP', opcode=45, arg=11, argval=11, argrepr='/', offset=234, start_offset=234, starts_line=False, line_number=21, label=None, positions=None), + Instruction(opname='POP_TOP', opcode=32, arg=None, argval=None, argrepr='', offset=238, start_offset=238, starts_line=False, line_number=21, label=None, positions=None), + Instruction(opname='LOAD_FAST', opcode=85, arg=0, argval='i', argrepr='i', offset=240, start_offset=240, starts_line=True, line_number=25, label=None, positions=None), + Instruction(opname='BEFORE_WITH', opcode=2, arg=None, argval=None, argrepr='', offset=242, start_offset=242, starts_line=False, line_number=25, label=None, positions=None), + Instruction(opname='STORE_FAST', opcode=110, arg=1, argval='dodgy', argrepr='dodgy', offset=244, start_offset=244, starts_line=False, line_number=25, label=None, positions=None), + Instruction(opname='LOAD_GLOBAL', opcode=91, arg=3, argval='print', argrepr='print + NULL', offset=246, start_offset=246, starts_line=True, line_number=26, label=None, positions=None), + Instruction(opname='LOAD_CONST', opcode=83, arg=8, argval='Never reach this', argrepr="'Never reach this'", offset=256, start_offset=256, starts_line=False, line_number=26, label=None, positions=None), + Instruction(opname='CALL', opcode=53, arg=1, argval=1, argrepr='', offset=258, start_offset=258, starts_line=False, line_number=26, label=None, positions=None), + Instruction(opname='POP_TOP', opcode=32, arg=None, argval=None, argrepr='', offset=266, start_offset=266, starts_line=False, line_number=26, label=None, positions=None), + Instruction(opname='LOAD_CONST', opcode=83, arg=0, argval=None, argrepr='None', offset=268, start_offset=268, starts_line=True, line_number=25, label=None, positions=None), + Instruction(opname='LOAD_CONST', opcode=83, arg=0, argval=None, argrepr='None', offset=270, start_offset=270, starts_line=False, line_number=25, label=None, positions=None), + Instruction(opname='LOAD_CONST', opcode=83, arg=0, argval=None, argrepr='None', offset=272, start_offset=272, starts_line=False, line_number=25, label=None, positions=None), + Instruction(opname='CALL', opcode=53, arg=2, argval=2, argrepr='', offset=274, start_offset=274, starts_line=False, line_number=25, label=None, positions=None), + Instruction(opname='POP_TOP', opcode=32, arg=None, argval=None, argrepr='', offset=282, start_offset=282, starts_line=False, line_number=25, label=None, positions=None), + Instruction(opname='LOAD_GLOBAL', opcode=91, arg=3, argval='print', argrepr='print + NULL', offset=284, start_offset=284, starts_line=True, line_number=28, label=11, positions=None), + Instruction(opname='LOAD_CONST', opcode=83, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=294, start_offset=294, starts_line=False, line_number=28, label=None, positions=None), + Instruction(opname='CALL', opcode=53, arg=1, argval=1, argrepr='', offset=296, start_offset=296, starts_line=False, line_number=28, label=None, positions=None), + Instruction(opname='POP_TOP', opcode=32, arg=None, argval=None, argrepr='', offset=304, start_offset=304, starts_line=False, line_number=28, label=None, positions=None), + Instruction(opname='RETURN_CONST', opcode=103, arg=0, argval=None, argrepr='None', offset=306, start_offset=306, starts_line=False, line_number=28, label=None, positions=None), + Instruction(opname='PUSH_EXC_INFO', opcode=33, arg=None, argval=None, argrepr='', offset=308, start_offset=308, starts_line=True, line_number=25, label=None, positions=None), + Instruction(opname='WITH_EXCEPT_START', opcode=44, arg=None, argval=None, argrepr='', offset=310, start_offset=310, starts_line=False, line_number=25, label=None, positions=None), + Instruction(opname='TO_BOOL', opcode=40, arg=None, argval=None, argrepr='', offset=312, start_offset=312, starts_line=False, line_number=25, label=None, positions=None), + Instruction(opname='POP_JUMP_IF_TRUE', opcode=100, arg=1, argval=326, argrepr='to L12', offset=320, start_offset=320, starts_line=False, line_number=25, label=None, positions=None), + Instruction(opname='RERAISE', opcode=102, arg=2, argval=2, argrepr='', offset=324, start_offset=324, starts_line=False, line_number=25, label=None, positions=None), + Instruction(opname='POP_TOP', opcode=32, arg=None, argval=None, argrepr='', offset=326, start_offset=326, starts_line=False, line_number=25, label=12, positions=None), + Instruction(opname='POP_EXCEPT', opcode=31, arg=None, argval=None, argrepr='', offset=328, start_offset=328, starts_line=False, line_number=25, label=None, positions=None), + Instruction(opname='POP_TOP', opcode=32, arg=None, argval=None, argrepr='', offset=330, start_offset=330, starts_line=False, line_number=25, label=None, positions=None), + Instruction(opname='POP_TOP', opcode=32, arg=None, argval=None, argrepr='', offset=332, start_offset=332, starts_line=False, line_number=25, label=None, positions=None), + Instruction(opname='JUMP_BACKWARD_NO_INTERRUPT', opcode=78, arg=26, argval=284, argrepr='to L11', offset=334, start_offset=334, starts_line=False, line_number=25, label=None, positions=None), + Instruction(opname='COPY', opcode=61, arg=3, argval=3, argrepr='', offset=336, start_offset=336, starts_line=True, line_number=None, label=None, positions=None), + Instruction(opname='POP_EXCEPT', opcode=31, arg=None, argval=None, argrepr='', offset=338, start_offset=338, starts_line=False, line_number=None, label=None, positions=None), + Instruction(opname='RERAISE', opcode=102, arg=1, argval=1, argrepr='', offset=340, start_offset=340, starts_line=False, line_number=None, label=None, positions=None), + Instruction(opname='PUSH_EXC_INFO', opcode=33, arg=None, argval=None, argrepr='', offset=342, start_offset=342, starts_line=False, line_number=None, label=None, positions=None), + Instruction(opname='LOAD_GLOBAL', opcode=91, arg=4, argval='ZeroDivisionError', argrepr='ZeroDivisionError', offset=344, start_offset=344, starts_line=True, line_number=22, label=None, positions=None), + Instruction(opname='CHECK_EXC_MATCH', opcode=7, arg=None, argval=None, argrepr='', offset=354, start_offset=354, starts_line=False, line_number=22, label=None, positions=None), + Instruction(opname='POP_JUMP_IF_FALSE', opcode=97, arg=14, argval=388, argrepr='to L13', offset=356, start_offset=356, starts_line=False, line_number=22, label=None, positions=None), + Instruction(opname='POP_TOP', opcode=32, arg=None, argval=None, argrepr='', offset=360, start_offset=360, starts_line=False, line_number=22, label=None, positions=None), + Instruction(opname='LOAD_GLOBAL', opcode=91, arg=3, argval='print', argrepr='print + NULL', offset=362, start_offset=362, starts_line=True, line_number=23, label=None, positions=None), + Instruction(opname='LOAD_CONST', opcode=83, arg=9, argval='Here we go, here we go, here we go...', argrepr="'Here we go, here we go, here we go...'", offset=372, start_offset=372, starts_line=False, line_number=23, label=None, positions=None), + Instruction(opname='CALL', opcode=53, arg=1, argval=1, argrepr='', offset=374, start_offset=374, starts_line=False, line_number=23, label=None, positions=None), + Instruction(opname='POP_TOP', opcode=32, arg=None, argval=None, argrepr='', offset=382, start_offset=382, starts_line=False, line_number=23, label=None, positions=None), + Instruction(opname='POP_EXCEPT', opcode=31, arg=None, argval=None, argrepr='', offset=384, start_offset=384, starts_line=False, line_number=23, label=None, positions=None), + Instruction(opname='JUMP_BACKWARD_NO_INTERRUPT', opcode=78, arg=52, argval=284, argrepr='to L11', offset=386, start_offset=386, starts_line=False, line_number=23, label=None, positions=None), + Instruction(opname='RERAISE', opcode=102, arg=0, argval=0, argrepr='', offset=388, start_offset=388, starts_line=True, line_number=22, label=13, positions=None), + Instruction(opname='COPY', opcode=61, arg=3, argval=3, argrepr='', offset=390, start_offset=390, starts_line=True, line_number=None, label=None, positions=None), + Instruction(opname='POP_EXCEPT', opcode=31, arg=None, argval=None, argrepr='', offset=392, start_offset=392, starts_line=False, line_number=None, label=None, positions=None), + Instruction(opname='RERAISE', opcode=102, arg=1, argval=1, argrepr='', offset=394, start_offset=394, starts_line=False, line_number=None, label=None, positions=None), + Instruction(opname='PUSH_EXC_INFO', opcode=33, arg=None, argval=None, argrepr='', offset=396, start_offset=396, starts_line=False, line_number=None, label=None, positions=None), + Instruction(opname='LOAD_GLOBAL', opcode=91, arg=3, argval='print', argrepr='print + NULL', offset=398, start_offset=398, starts_line=True, line_number=28, label=None, positions=None), + Instruction(opname='LOAD_CONST', opcode=83, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=408, start_offset=408, starts_line=False, line_number=28, label=None, positions=None), + Instruction(opname='CALL', opcode=53, arg=1, argval=1, argrepr='', offset=410, start_offset=410, starts_line=False, line_number=28, label=None, positions=None), + Instruction(opname='POP_TOP', opcode=32, arg=None, argval=None, argrepr='', offset=418, start_offset=418, starts_line=False, line_number=28, label=None, positions=None), + Instruction(opname='RERAISE', opcode=102, arg=0, argval=0, argrepr='', offset=420, start_offset=420, starts_line=False, line_number=28, label=None, positions=None), + Instruction(opname='COPY', opcode=61, arg=3, argval=3, argrepr='', offset=422, start_offset=422, starts_line=True, line_number=None, label=None, positions=None), + Instruction(opname='POP_EXCEPT', opcode=31, arg=None, argval=None, argrepr='', offset=424, start_offset=424, starts_line=False, line_number=None, label=None, positions=None), + Instruction(opname='RERAISE', opcode=102, arg=1, argval=1, argrepr='', offset=426, start_offset=426, starts_line=False, line_number=None, label=None, positions=None), ] # One last piece of inspect fodder to check the default line number handling def simple(): pass expected_opinfo_simple = [ - Instruction(opname='RESUME', opcode=151, arg=0, argval=0, argrepr='', offset=0, start_offset=0, starts_line=simple.__code__.co_firstlineno, is_jump_target=False, positions=None), - Instruction(opname='RETURN_CONST', opcode=121, arg=0, argval=None, argrepr='None', offset=2, start_offset=2, starts_line=None, is_jump_target=False), + Instruction(opname='RESUME', opcode=149, arg=0, argval=0, argrepr='', offset=0, start_offset=0, starts_line=True, line_number=simple.__code__.co_firstlineno, label=None, positions=None), + Instruction(opname='RETURN_CONST', opcode=103, arg=0, argval=None, argrepr='None', offset=2, start_offset=2, starts_line=False, line_number=simple.__code__.co_firstlineno, label=None), ] class InstructionTestCase(BytecodeTestCase): def assertInstructionsEqual(self, instrs_1, instrs_2, /): - instrs_1 = [instr_1._replace(positions=None) for instr_1 in instrs_1] - instrs_2 = [instr_2._replace(positions=None) for instr_2 in instrs_2] + instrs_1 = [instr_1._replace(positions=None, cache_info=None) for instr_1 in instrs_1] + instrs_2 = [instr_2._replace(positions=None, cache_info=None) for instr_2 in instrs_2] self.assertEqual(instrs_1, instrs_2) class InstructionTests(InstructionTestCase): @@ -1824,6 +1793,12 @@ def __init__(self, *args): super().__init__(*args) self.maxDiff = None + def test_instruction_str(self): + # smoke test for __str__ + instrs = dis.get_instructions(simple) + for instr in instrs: + str(instr) + def test_default_first_line(self): actual = dis.get_instructions(simple) self.assertInstructionsEqual(list(actual), expected_opinfo_simple) @@ -1917,24 +1892,41 @@ def roots(a, b, c): if show_caches or op != cache_opcode ] dis_positions = [ - instruction.positions - for instruction in dis.get_instructions( - code, adaptive=adaptive, show_caches=show_caches + None if instruction.positions is None else ( + instruction.positions.lineno, + instruction.positions.end_lineno, + instruction.positions.col_offset, + instruction.positions.end_col_offset, ) + for instruction in _unroll_caches_as_Instructions(dis.get_instructions( + code, adaptive=adaptive, show_caches=show_caches + ), show_caches=show_caches) ] self.assertEqual(co_positions, dis_positions) def test_oparg_alias(self): instruction = Instruction(opname="NOP", opcode=dis.opmap["NOP"], arg=None, argval=None, - argrepr='', offset=10, start_offset=10, starts_line=1, is_jump_target=False, + argrepr='', offset=10, start_offset=10, starts_line=True, line_number=1, label=None, positions=None) self.assertEqual(instruction.arg, instruction.oparg) + def test_show_caches_with_label(self): + def f(x, y, z): + if x: + res = y + else: + res = z + return res + + output = io.StringIO() + dis.dis(f.__code__, file=output, show_caches=True) + self.assertIn("L1:", output.getvalue()) + def test_baseopname_and_baseopcode(self): # Standard instructions for name, code in dis.opmap.items(): instruction = Instruction(opname=name, opcode=code, arg=None, argval=None, argrepr='', offset=0, - start_offset=0, starts_line=1, is_jump_target=False, positions=None) + start_offset=0, starts_line=True, line_number=1, label=None, positions=None) baseopname = instruction.baseopname baseopcode = instruction.baseopcode self.assertIsNotNone(baseopname) @@ -1943,9 +1935,9 @@ def test_baseopname_and_baseopcode(self): self.assertEqual(code, baseopcode) # Specialized instructions - for name in opcode._specialized_instructions: + for name in opcode._specialized_opmap: instruction = Instruction(opname=name, opcode=dis._all_opmap[name], arg=None, argval=None, argrepr='', - offset=0, start_offset=0, starts_line=1, is_jump_target=False, positions=None) + offset=0, start_offset=0, starts_line=True, line_number=1, label=None, positions=None) baseopname = instruction.baseopname baseopcode = instruction.baseopcode self.assertIn(name, opcode._specializations[baseopname]) @@ -1954,41 +1946,69 @@ def test_baseopname_and_baseopcode(self): def test_jump_target(self): # Non-jump instructions should return None instruction = Instruction(opname="NOP", opcode=dis.opmap["NOP"], arg=None, argval=None, - argrepr='', offset=10, start_offset=10, starts_line=1, is_jump_target=False, + argrepr='', offset=10, start_offset=10, starts_line=True, line_number=1, label=None, positions=None) self.assertIsNone(instruction.jump_target) delta = 100 instruction = Instruction(opname="JUMP_FORWARD", opcode=dis.opmap["JUMP_FORWARD"], arg=delta, argval=delta, - argrepr='', offset=10, start_offset=10, starts_line=1, is_jump_target=False, + argrepr='', offset=10, start_offset=10, starts_line=True, line_number=1, label=None, positions=None) self.assertEqual(10 + 2 + 100*2, instruction.jump_target) # Test negative deltas instruction = Instruction(opname="JUMP_BACKWARD", opcode=dis.opmap["JUMP_BACKWARD"], arg=delta, argval=delta, - argrepr='', offset=200, start_offset=200, starts_line=1, is_jump_target=False, + argrepr='', offset=200, start_offset=200, starts_line=True, line_number=1, label=None, positions=None) self.assertEqual(200 + 2 - 100*2 + 2*1, instruction.jump_target) # Make sure cache entries are handled instruction = Instruction(opname="SEND", opcode=dis.opmap["SEND"], arg=delta, argval=delta, - argrepr='', offset=10, start_offset=10, starts_line=1, is_jump_target=False, + argrepr='', offset=10, start_offset=10, starts_line=True, line_number=1, label=None, positions=None) self.assertEqual(10 + 2 + 1*2 + 100*2, instruction.jump_target) + def test_argval_argrepr(self): + def f(opcode, oparg, offset, *init_args): + arg_resolver = dis.ArgResolver(*init_args) + return arg_resolver.get_argval_argrepr(opcode, oparg, offset) + + offset = 42 + co_consts = (0, 1, 2, 3) + names = {1: 'a', 2: 'b'} + varname_from_oparg = lambda i : names[i] + labels_map = {24: 1} + args = (offset, co_consts, names, varname_from_oparg, labels_map) + self.assertEqual(f(opcode.opmap["POP_TOP"], None, *args), (None, '')) + self.assertEqual(f(opcode.opmap["LOAD_CONST"], 1, *args), (1, '1')) + self.assertEqual(f(opcode.opmap["LOAD_GLOBAL"], 2, *args), ('a', 'a')) + self.assertEqual(f(opcode.opmap["JUMP_BACKWARD"], 11, *args), (24, 'to L1')) + self.assertEqual(f(opcode.opmap["COMPARE_OP"], 3, *args), ('<', '<')) + self.assertEqual(f(opcode.opmap["SET_FUNCTION_ATTRIBUTE"], 2, *args), (2, 'kwdefaults')) + self.assertEqual(f(opcode.opmap["BINARY_OP"], 3, *args), (3, '<<')) + self.assertEqual(f(opcode.opmap["CALL_INTRINSIC_1"], 2, *args), (2, 'INTRINSIC_IMPORT_STAR')) + + def get_instructions(self, code): + return dis._get_instructions_bytes(code) + def test_start_offset(self): # When no extended args are present, # start_offset should be equal to offset + instructions = list(dis.Bytecode(_f)) for instruction in instructions: self.assertEqual(instruction.offset, instruction.start_offset) + def last_item(iterable): + return functools.reduce(lambda a, b : b, iterable) + code = bytes([ opcode.opmap["LOAD_FAST"], 0x00, opcode.opmap["EXTENDED_ARG"], 0x01, opcode.opmap["POP_JUMP_IF_TRUE"], 0xFF, ]) - jump = list(dis._get_instructions_bytes(code))[-1] + labels_map = dis._make_labels_map(code) + jump = last_item(self.get_instructions(code)) self.assertEqual(4, jump.offset) self.assertEqual(2, jump.start_offset) @@ -1998,8 +2018,9 @@ def test_start_offset(self): opcode.opmap["EXTENDED_ARG"], 0x01, opcode.opmap["EXTENDED_ARG"], 0x01, opcode.opmap["POP_JUMP_IF_TRUE"], 0xFF, + opcode.opmap["CACHE"], 0x00, ]) - jump = list(dis._get_instructions_bytes(code))[-1] + jump = last_item(self.get_instructions(code)) self.assertEqual(8, jump.offset) self.assertEqual(2, jump.start_offset) @@ -2007,18 +2028,20 @@ def test_start_offset(self): opcode.opmap["LOAD_FAST"], 0x00, opcode.opmap["EXTENDED_ARG"], 0x01, opcode.opmap["POP_JUMP_IF_TRUE"], 0xFF, + opcode.opmap["CACHE"], 0x00, opcode.opmap["EXTENDED_ARG"], 0x01, opcode.opmap["EXTENDED_ARG"], 0x01, opcode.opmap["EXTENDED_ARG"], 0x01, opcode.opmap["POP_JUMP_IF_TRUE"], 0xFF, + opcode.opmap["CACHE"], 0x00, ]) - instructions = list(dis._get_instructions_bytes(code)) + instructions = list(self.get_instructions(code)) # 1st jump self.assertEqual(4, instructions[2].offset) self.assertEqual(2, instructions[2].start_offset) # 2nd jump - self.assertEqual(12, instructions[6].offset) - self.assertEqual(6, instructions[6].start_offset) + self.assertEqual(14, instructions[6].offset) + self.assertEqual(8, instructions[6].start_offset) def test_cache_offset_and_end_offset(self): code = bytes([ @@ -2033,7 +2056,7 @@ def test_cache_offset_and_end_offset(self): opcode.opmap["CACHE"], 0x00, opcode.opmap["CACHE"], 0x00 ]) - instructions = list(dis._get_instructions_bytes(code)) + instructions = list(self.get_instructions(code)) self.assertEqual(2, instructions[0].cache_offset) self.assertEqual(10, instructions[0].end_offset) self.assertEqual(12, instructions[1].cache_offset) @@ -2104,7 +2127,7 @@ def test_from_traceback_dis(self): self.maxDiff = None tb = get_tb() b = dis.Bytecode.from_traceback(tb) - self.assertEqual(self.strip_offsets(b.dis()), dis_traceback) + self.assertEqual(b.dis(), dis_traceback) @requires_debug_ranges() def test_bytecode_co_positions(self): @@ -2226,6 +2249,31 @@ def get_disassembly(self, tb): dis.distb(tb, file=output) return output.getvalue() +def _unroll_caches_as_Instructions(instrs, show_caches=False): + # Cache entries are no longer reported by dis as fake instructions, + # but some tests assume that do. We should rewrite the tests to assume + # the new API, but it will be clearer to keep the tests working as + # before and do that in a separate PR. + + for instr in instrs: + yield instr + if not show_caches: + continue + + offset = instr.offset + for name, size, data in (instr.cache_info or ()): + for i in range(size): + offset += 2 + # Only show the fancy argrepr for a CACHE instruction when it's + # the first entry for a particular cache value: + if i == 0: + argrepr = f"{name}: {int.from_bytes(data, sys.byteorder)}" + else: + argrepr = "" + + yield Instruction("CACHE", CACHE, 0, None, argrepr, offset, offset, + False, None, None, instr.positions) + if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_doctest.py b/Lib/test/test_doctest.py index bea52c6de7ec6d..46a51007f9644d 100644 --- a/Lib/test/test_doctest.py +++ b/Lib/test/test_doctest.py @@ -102,14 +102,13 @@ def a_classmethod(cls, v): a_class_attribute = 42 - @classmethod - @property - def a_classmethod_property(cls): + @functools.cached_property + def a_cached_property(self): """ - >>> print(SampleClass.a_classmethod_property) - 42 + >>> print(SampleClass(29).get()) + 29 """ - return cls.a_class_attribute + return "hello" class NestedClass: """ @@ -414,6 +413,23 @@ def test_DocTest(): r""" False >>> test != other_test True + >>> test < other_test + False + >>> other_test < test + True + +Test comparison with lineno None on one side + + >>> no_lineno = parser.get_doctest(docstring, globs, 'some_test', + ... 'some_test', None) + >>> test.lineno is None + False + >>> no_lineno.lineno is None + True + >>> test < no_lineno + False + >>> no_lineno < test + True Compare `DocTestCase`: @@ -515,8 +531,8 @@ def basics(): r""" 3 SampleClass.NestedClass 1 SampleClass.NestedClass.__init__ 1 SampleClass.__init__ + 1 SampleClass.a_cached_property 2 SampleClass.a_classmethod - 1 SampleClass.a_classmethod_property 1 SampleClass.a_property 1 SampleClass.a_staticmethod 1 SampleClass.double @@ -571,8 +587,8 @@ def basics(): r""" 3 some_module.SampleClass.NestedClass 1 some_module.SampleClass.NestedClass.__init__ 1 some_module.SampleClass.__init__ + 1 some_module.SampleClass.a_cached_property 2 some_module.SampleClass.a_classmethod - 1 some_module.SampleClass.a_classmethod_property 1 some_module.SampleClass.a_property 1 some_module.SampleClass.a_staticmethod 1 some_module.SampleClass.double @@ -613,8 +629,8 @@ def basics(): r""" 3 SampleClass.NestedClass 1 SampleClass.NestedClass.__init__ 1 SampleClass.__init__ + 1 SampleClass.a_cached_property 2 SampleClass.a_classmethod - 1 SampleClass.a_classmethod_property 1 SampleClass.a_property 1 SampleClass.a_staticmethod 1 SampleClass.double @@ -634,8 +650,8 @@ def basics(): r""" 0 SampleClass.NestedClass.get 0 SampleClass.NestedClass.square 1 SampleClass.__init__ + 1 SampleClass.a_cached_property 2 SampleClass.a_classmethod - 1 SampleClass.a_classmethod_property 1 SampleClass.a_property 1 SampleClass.a_staticmethod 1 SampleClass.double @@ -654,9 +670,11 @@ def basics(): r""" 30 test.doctest_lineno.ClassWithDoctest None test.doctest_lineno.ClassWithoutDocstring None test.doctest_lineno.MethodWrapper + 53 test.doctest_lineno.MethodWrapper.classmethod_with_doctest 39 test.doctest_lineno.MethodWrapper.method_with_docstring 45 test.doctest_lineno.MethodWrapper.method_with_doctest None test.doctest_lineno.MethodWrapper.method_without_docstring + 61 test.doctest_lineno.MethodWrapper.property_with_doctest 4 test.doctest_lineno.func_with_docstring 12 test.doctest_lineno.func_with_doctest None test.doctest_lineno.func_without_docstring @@ -736,19 +754,49 @@ def non_Python_modules(): r""" """ +class TestDocTest(unittest.TestCase): + + def test_run(self): + test = ''' + >>> 1 + 1 + 11 + >>> 2 + 3 # doctest: +SKIP + "23" + >>> 5 + 7 + 57 + ''' + + def myfunc(): + pass + myfunc.__doc__ = test + + # test DocTestFinder.run() + test = doctest.DocTestFinder().find(myfunc)[0] + with support.captured_stdout(): + with support.captured_stderr(): + results = doctest.DocTestRunner(verbose=False).run(test) + + # test TestResults + self.assertIsInstance(results, doctest.TestResults) + self.assertEqual(results.failed, 2) + self.assertEqual(results.attempted, 3) + self.assertEqual(results.skipped, 1) + self.assertEqual(tuple(results), (2, 3)) + x, y = results + self.assertEqual((x, y), (2, 3)) + + class TestDocTestFinder(unittest.TestCase): def test_issue35753(self): # This import of `call` should trigger issue35753 when - # `support.run_doctest` is called due to unwrap failing, + # DocTestFinder.find() is called due to inspect.unwrap() failing, # however with a patched doctest this should succeed. from unittest.mock import call dummy_module = types.ModuleType("dummy") dummy_module.__dict__['inject_call'] = call - try: - support.run_doctest(dummy_module, verbosity=True) - except ValueError as e: - raise support.TestFailed("Doctest unwrap failed") from e + finder = doctest.DocTestFinder() + self.assertEqual(finder.find(dummy_module), []) def test_empty_namespace_package(self): pkg_name = 'doctest_empty_pkg' @@ -2876,6 +2924,9 @@ def test_unicode(): """ Traceback (most recent call last): File ... exec(compile(example.source, filename, "single", + ~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + compileflags, True), test.globs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "", line 1, in raise Exception('clé') Exception: clé @@ -3170,25 +3221,173 @@ def test_run_doctestsuite_multiple_times(): """ +def test_exception_with_note(note): + """ + >>> test_exception_with_note('Note') + Traceback (most recent call last): + ... + ValueError: Text + Note + + >>> test_exception_with_note('Note') # doctest: +IGNORE_EXCEPTION_DETAIL + Traceback (most recent call last): + ... + ValueError: Text + Note + + >>> test_exception_with_note('''Note + ... multiline + ... example''') + Traceback (most recent call last): + ValueError: Text + Note + multiline + example + + Different note will fail the test: + + >>> def f(x): + ... r''' + ... >>> exc = ValueError('message') + ... >>> exc.add_note('note') + ... >>> raise exc + ... Traceback (most recent call last): + ... ValueError: message + ... wrong note + ... ''' + >>> test = doctest.DocTestFinder().find(f)[0] + >>> doctest.DocTestRunner(verbose=False).run(test) + ... # doctest: +ELLIPSIS + ********************************************************************** + File "...", line 5, in f + Failed example: + raise exc + Expected: + Traceback (most recent call last): + ValueError: message + wrong note + Got: + Traceback (most recent call last): + ... + ValueError: message + note + TestResults(failed=1, attempted=...) + """ + exc = ValueError('Text') + exc.add_note(note) + raise exc + + +def test_exception_with_multiple_notes(): + """ + >>> test_exception_with_multiple_notes() + Traceback (most recent call last): + ... + ValueError: Text + One + Two + """ + exc = ValueError('Text') + exc.add_note('One') + exc.add_note('Two') + raise exc + + +def test_syntax_error_with_note(cls, multiline=False): + """ + >>> test_syntax_error_with_note(SyntaxError) + Traceback (most recent call last): + ... + SyntaxError: error + Note + + >>> test_syntax_error_with_note(SyntaxError) + Traceback (most recent call last): + SyntaxError: error + Note + + >>> test_syntax_error_with_note(SyntaxError) + Traceback (most recent call last): + ... + File "x.py", line 23 + bad syntax + SyntaxError: error + Note + + >>> test_syntax_error_with_note(IndentationError) + Traceback (most recent call last): + ... + IndentationError: error + Note + + >>> test_syntax_error_with_note(TabError, multiline=True) + Traceback (most recent call last): + ... + TabError: error + Note + Line + """ + exc = cls("error", ("x.py", 23, None, "bad syntax")) + exc.add_note('Note\nLine' if multiline else 'Note') + raise exc + + +def test_syntax_error_subclass_from_stdlib(): + """ + `ParseError` is a subclass of `SyntaxError`, but it is not a builtin: + + >>> test_syntax_error_subclass_from_stdlib() + Traceback (most recent call last): + ... + xml.etree.ElementTree.ParseError: error + error + Note + Line + """ + from xml.etree.ElementTree import ParseError + exc = ParseError("error\nerror") + exc.add_note('Note\nLine') + raise exc + + +def test_syntax_error_with_incorrect_expected_note(): + """ + >>> def f(x): + ... r''' + ... >>> exc = SyntaxError("error", ("x.py", 23, None, "bad syntax")) + ... >>> exc.add_note('note1') + ... >>> exc.add_note('note2') + ... >>> raise exc + ... Traceback (most recent call last): + ... SyntaxError: error + ... wrong note + ... ''' + >>> test = doctest.DocTestFinder().find(f)[0] + >>> doctest.DocTestRunner(verbose=False).run(test) + ... # doctest: +ELLIPSIS + ********************************************************************** + File "...", line 6, in f + Failed example: + raise exc + Expected: + Traceback (most recent call last): + SyntaxError: error + wrong note + Got: + Traceback (most recent call last): + ... + SyntaxError: error + note1 + note2 + TestResults(failed=1, attempted=...) + """ + + def load_tests(loader, tests, pattern): tests.addTest(doctest.DocTestSuite(doctest)) tests.addTest(doctest.DocTestSuite()) return tests -def test_coverage(coverdir): - trace = import_helper.import_module('trace') - tracer = trace.Trace(ignoredirs=[sys.base_prefix, sys.base_exec_prefix,], - trace=0, count=1) - tracer.run('test_main()') - r = tracer.results() - print('Writing coverage results...') - r.write_results(show_missing=True, summary=True, - coverdir=coverdir) - - if __name__ == '__main__': - if '-c' in sys.argv: - test_coverage('/tmp/doctest.cover') - else: - unittest.main() + unittest.main(module='test.test_doctest') diff --git a/Lib/test/test_dynamic.py b/Lib/test/test_dynamic.py index 7e12d428e0fde2..0aa3be6a1bde6a 100644 --- a/Lib/test/test_dynamic.py +++ b/Lib/test/test_dynamic.py @@ -145,7 +145,7 @@ def __missing__(self, key): code = "lambda: " + "+".join(f"_number_{i}" for i in range(variables)) sum_func = eval(code, MyGlobals()) expected = sum(range(variables)) - # Warm up the the function for quickening (PEP 659) + # Warm up the function for quickening (PEP 659) for _ in range(30): self.assertEqual(sum_func(), expected) diff --git a/Lib/test/test_eintr.py b/Lib/test/test_eintr.py index 528147802ba47e..49b15f1a2dba92 100644 --- a/Lib/test/test_eintr.py +++ b/Lib/test/test_eintr.py @@ -9,6 +9,7 @@ class EINTRTests(unittest.TestCase): @unittest.skipUnless(hasattr(signal, "setitimer"), "requires setitimer()") + @support.requires_resource('walltime') def test_all(self): # Run the tester in a sub-process, to make sure there is only one # thread (for reliable signal delivery). diff --git a/Lib/test/test_email/test__header_value_parser.py b/Lib/test/test_email/test__header_value_parser.py index 854f2ff009c618..bdb0e55f21069f 100644 --- a/Lib/test/test_email/test__header_value_parser.py +++ b/Lib/test/test_email/test__header_value_parser.py @@ -2915,6 +2915,45 @@ def test_ews_combined_before_wrap(self): "mich. And that's\n" " all I'm sayin.\n") + def test_unicode_after_unknown_not_combined(self): + self._test(parser.get_unstructured("=?unknown-8bit?q?=A4?=\xa4"), + "=?unknown-8bit?q?=A4?==?utf-8?q?=C2=A4?=\n") + prefix = "0123456789 "*5 + self._test(parser.get_unstructured(prefix + "=?unknown-8bit?q?=A4?=\xa4"), + prefix + "=?unknown-8bit?q?=A4?=\n =?utf-8?q?=C2=A4?=\n") + + def test_ascii_after_unknown_not_combined(self): + self._test(parser.get_unstructured("=?unknown-8bit?q?=A4?=abc"), + "=?unknown-8bit?q?=A4?=abc\n") + prefix = "0123456789 "*5 + self._test(parser.get_unstructured(prefix + "=?unknown-8bit?q?=A4?=abc"), + prefix + "=?unknown-8bit?q?=A4?=\n =?utf-8?q?abc?=\n") + + def test_unknown_after_unicode_not_combined(self): + self._test(parser.get_unstructured("\xa4" + "=?unknown-8bit?q?=A4?="), + "=?utf-8?q?=C2=A4?==?unknown-8bit?q?=A4?=\n") + prefix = "0123456789 "*5 + self._test(parser.get_unstructured(prefix + "\xa4=?unknown-8bit?q?=A4?="), + prefix + "=?utf-8?q?=C2=A4?=\n =?unknown-8bit?q?=A4?=\n") + + def test_unknown_after_ascii_not_combined(self): + self._test(parser.get_unstructured("abc" + "=?unknown-8bit?q?=A4?="), + "abc=?unknown-8bit?q?=A4?=\n") + prefix = "0123456789 "*5 + self._test(parser.get_unstructured(prefix + "abcd=?unknown-8bit?q?=A4?="), + prefix + "abcd\n =?unknown-8bit?q?=A4?=\n") + + def test_unknown_after_unknown(self): + self._test(parser.get_unstructured("=?unknown-8bit?q?=C2?=" + "=?unknown-8bit?q?=A4?="), + "=?unknown-8bit?q?=C2=A4?=\n") + prefix = "0123456789 "*5 + self._test(parser.get_unstructured(prefix + "=?unknown-8bit?q?=C2?=" + "=?unknown-8bit?q?=A4?="), + prefix + "=?unknown-8bit?q?=C2?=\n =?unknown-8bit?q?=A4?=\n") + # XXX Need test of an encoded word so long that it needs to be wrapped def test_simple_address(self): diff --git a/Lib/test/test_email/test_email.py b/Lib/test/test_email/test_email.py index cdb6ef1275e520..39d4ace8d4a1d8 100644 --- a/Lib/test/test_email/test_email.py +++ b/Lib/test/test_email/test_email.py @@ -16,6 +16,7 @@ import email import email.policy +import email.utils from email.charset import Charset from email.generator import Generator, DecodedGenerator, BytesGenerator @@ -38,6 +39,7 @@ from email import quoprimime from email import utils +from test import support from test.support import threading_helper from test.support.os_helper import unlink from test.test_email import openfile, TestEmailBase @@ -2235,7 +2237,7 @@ def test_multipart_valid_cte_no_defect(self): "\nContent-Transfer-Encoding: {}".format(cte))) self.assertEqual(len(msg.defects), 0) - # test_headerregistry.TestContentTyopeHeader invalid_1 and invalid_2. + # test_headerregistry.TestContentTypeHeader invalid_1 and invalid_2. def test_invalid_content_type(self): eq = self.assertEqual neq = self.ndiffAssertEqual @@ -3336,15 +3338,137 @@ def test_getaddresses_comma_in_name(self): ], ) + def test_parsing_errors(self): + """Test for parsing errors from CVE-2023-27043 and CVE-2019-16056""" + alice = 'alice@example.org' + bob = 'bob@example.com' + empty = ('', '') + + # Test utils.getaddresses() and utils.parseaddr() on malformed email + # addresses: default behavior (strict=True) rejects malformed address, + # and strict=False which tolerates malformed address. + for invalid_separator, expected_non_strict in ( + ('(', [(f'<{bob}>', alice)]), + (')', [('', alice), empty, ('', bob)]), + ('<', [('', alice), empty, ('', bob), empty]), + ('>', [('', alice), empty, ('', bob)]), + ('[', [('', f'{alice}[<{bob}>]')]), + (']', [('', alice), empty, ('', bob)]), + ('@', [empty, empty, ('', bob)]), + (';', [('', alice), empty, ('', bob)]), + (':', [('', alice), ('', bob)]), + ('.', [('', alice + '.'), ('', bob)]), + ('"', [('', alice), ('', f'<{bob}>')]), + ): + address = f'{alice}{invalid_separator}<{bob}>' + with self.subTest(address=address): + self.assertEqual(utils.getaddresses([address]), + [empty]) + self.assertEqual(utils.getaddresses([address], strict=False), + expected_non_strict) + + self.assertEqual(utils.parseaddr([address]), + empty) + self.assertEqual(utils.parseaddr([address], strict=False), + ('', address)) + + # Comma (',') is treated differently depending on strict parameter. + # Comma without quotes. + address = f'{alice},<{bob}>' + self.assertEqual(utils.getaddresses([address]), + [('', alice), ('', bob)]) + self.assertEqual(utils.getaddresses([address], strict=False), + [('', alice), ('', bob)]) + self.assertEqual(utils.parseaddr([address]), + empty) + self.assertEqual(utils.parseaddr([address], strict=False), + ('', address)) + + # Real name between quotes containing comma. + address = '"Alice, alice@example.org" ' + expected_strict = ('Alice, alice@example.org', 'bob@example.com') + self.assertEqual(utils.getaddresses([address]), [expected_strict]) + self.assertEqual(utils.getaddresses([address], strict=False), [expected_strict]) + self.assertEqual(utils.parseaddr([address]), expected_strict) + self.assertEqual(utils.parseaddr([address], strict=False), + ('', address)) + + # Valid parenthesis in comments. + address = 'alice@example.org (Alice)' + expected_strict = ('Alice', 'alice@example.org') + self.assertEqual(utils.getaddresses([address]), [expected_strict]) + self.assertEqual(utils.getaddresses([address], strict=False), [expected_strict]) + self.assertEqual(utils.parseaddr([address]), expected_strict) + self.assertEqual(utils.parseaddr([address], strict=False), + ('', address)) + + # Invalid parenthesis in comments. + address = 'alice@example.org )Alice(' + self.assertEqual(utils.getaddresses([address]), [empty]) + self.assertEqual(utils.getaddresses([address], strict=False), + [('', 'alice@example.org'), ('', ''), ('', 'Alice')]) + self.assertEqual(utils.parseaddr([address]), empty) + self.assertEqual(utils.parseaddr([address], strict=False), + ('', address)) + + # Two addresses with quotes separated by comma. + address = '"Jane Doe" , "John Doe" ' + self.assertEqual(utils.getaddresses([address]), + [('Jane Doe', 'jane@example.net'), + ('John Doe', 'john@example.net')]) + self.assertEqual(utils.getaddresses([address], strict=False), + [('Jane Doe', 'jane@example.net'), + ('John Doe', 'john@example.net')]) + self.assertEqual(utils.parseaddr([address]), empty) + self.assertEqual(utils.parseaddr([address], strict=False), + ('', address)) + + # Test email.utils.supports_strict_parsing attribute + self.assertEqual(email.utils.supports_strict_parsing, True) + def test_getaddresses_nasty(self): - eq = self.assertEqual - eq(utils.getaddresses(['foo: ;']), [('', '')]) - eq(utils.getaddresses( - ['[]*-- =~$']), - [('', ''), ('', ''), ('', '*--')]) - eq(utils.getaddresses( - ['foo: ;', '"Jason R. Mastaler" ']), - [('', ''), ('Jason R. Mastaler', 'jason@dom.ain')]) + for addresses, expected in ( + (['"Sürname, Firstname" '], + [('Sürname, Firstname', 'to@example.com')]), + + (['foo: ;'], + [('', '')]), + + (['foo: ;', '"Jason R. Mastaler" '], + [('', ''), ('Jason R. Mastaler', 'jason@dom.ain')]), + + ([r'Pete(A nice \) chap) '], + [('Pete (A nice ) chap his account his host)', 'pete@silly.test')]), + + (['(Empty list)(start)Undisclosed recipients :(nobody(I know))'], + [('', '')]), + + (['Mary <@machine.tld:mary@example.net>, , jdoe@test . example'], + [('Mary', 'mary@example.net'), ('', ''), ('', 'jdoe@test.example')]), + + (['John Doe '], + [('John Doe (comment)', 'jdoe@machine.example')]), + + (['"Mary Smith: Personal Account" '], + [('Mary Smith: Personal Account', 'smith@home.example')]), + + (['Undisclosed recipients:;'], + [('', '')]), + + ([r', "Giant; \"Big\" Box" '], + [('', 'boss@nil.test'), ('Giant; "Big" Box', 'bob@example.net')]), + ): + with self.subTest(addresses=addresses): + self.assertEqual(utils.getaddresses(addresses), + expected) + self.assertEqual(utils.getaddresses(addresses, strict=False), + expected) + + addresses = ['[]*-- =~$'] + self.assertEqual(utils.getaddresses(addresses), + [('', '')]) + self.assertEqual(utils.getaddresses(addresses, strict=False), + [('', ''), ('', ''), ('', '*--')]) def test_getaddresses_embedded_comment(self): """Test proper handling of a nested comment""" @@ -3358,6 +3482,7 @@ def test_getaddresses_header_obj(self): self.assertEqual(addrs[0][1], 'aperson@dom.ain') @threading_helper.requires_working_threading() + @support.requires_resource('cpu') def test_make_msgid_collisions(self): # Test make_msgid uniqueness, even with multiple threads class MsgidsThread(Thread): @@ -3534,6 +3659,54 @@ def test_mime_classes_policy_argument(self): m = cls(*constructor, policy=email.policy.default) self.assertIs(m.policy, email.policy.default) + def test_iter_escaped_chars(self): + self.assertEqual(list(utils._iter_escaped_chars(r'a\\b\"c\\"d')), + [(0, 'a'), + (2, '\\\\'), + (3, 'b'), + (5, '\\"'), + (6, 'c'), + (8, '\\\\'), + (9, '"'), + (10, 'd')]) + self.assertEqual(list(utils._iter_escaped_chars('a\\')), + [(0, 'a'), (1, '\\')]) + + def test_strip_quoted_realnames(self): + def check(addr, expected): + self.assertEqual(utils._strip_quoted_realnames(addr), expected) + + check('"Jane Doe" , "John Doe" ', + ' , ') + check(r'"Jane \"Doe\"." ', + ' ') + + # special cases + check(r'before"name"after', 'beforeafter') + check(r'before"name"', 'before') + check(r'b"name"', 'b') # single char + check(r'"name"after', 'after') + check(r'"name"a', 'a') # single char + check(r'"name"', '') + + # no change + for addr in ( + 'Jane Doe , John Doe ', + 'lone " quote', + ): + self.assertEqual(utils._strip_quoted_realnames(addr), addr) + + + def test_check_parenthesis(self): + addr = 'alice@example.net' + self.assertTrue(utils._check_parenthesis(f'{addr} (Alice)')) + self.assertFalse(utils._check_parenthesis(f'{addr} )Alice(')) + self.assertFalse(utils._check_parenthesis(f'{addr} (Alice))')) + self.assertFalse(utils._check_parenthesis(f'{addr} ((Alice)')) + + # Ignore real name between quotes + self.assertTrue(utils._check_parenthesis(f'")Alice((" {addr}')) + # Test the iterator/generators class TestIterators(TestEmailBase): diff --git a/Lib/test/test_email/test_message.py b/Lib/test/test_email/test_message.py index d3f396f02e7a72..034f7626c1fc7c 100644 --- a/Lib/test/test_email/test_message.py +++ b/Lib/test/test_email/test_message.py @@ -748,6 +748,35 @@ def test_iter_attachments_mutation(self): self.assertEqual(len(list(m.iter_attachments())), 2) self.assertEqual(m.get_payload(), orig) + get_payload_surrogate_params = { + + 'good_surrogateescape': ( + "String that can be encod\udcc3\udcabd with surrogateescape", + b'String that can be encod\xc3\xabd with surrogateescape' + ), + + 'string_with_utf8': ( + "String with utf-8 charactër", + b'String with utf-8 charact\xebr' + ), + + 'surrogate_and_utf8': ( + "String that cannot be ëncod\udcc3\udcabd with surrogateescape", + b'String that cannot be \xebncod\\udcc3\\udcabd with surrogateescape' + ), + + 'out_of_range_surrogate': ( + "String with \udfff cannot be encoded with surrogateescape", + b'String with \\udfff cannot be encoded with surrogateescape' + ), + } + + def get_payload_surrogate_as_gh_94606(self, msg, expected): + """test for GH issue 94606""" + m = self._str_msg(msg) + payload = m.get_payload(decode=True) + self.assertEqual(expected, payload) + class TestEmailMessage(TestEmailMessageBase, TestEmailBase): message = EmailMessage diff --git a/Lib/test/test_email/test_utils.py b/Lib/test/test_email/test_utils.py index 25fa48c5ee217b..0f1c3a84e61abd 100644 --- a/Lib/test/test_email/test_utils.py +++ b/Lib/test/test_email/test_utils.py @@ -5,6 +5,7 @@ import unittest import sys import os.path +import zoneinfo class DateTimeTests(unittest.TestCase): @@ -142,16 +143,12 @@ def test_localtime_epoch_notz_daylight_false(self): t2 = utils.localtime(t0.replace(tzinfo=None)) self.assertEqual(t1, t2) - # XXX: Need a more robust test for Olson's tzdata - @unittest.skipIf(sys.platform.startswith('win'), - "Windows does not use Olson's TZ database") - @unittest.skipUnless(os.path.exists('/usr/share/zoneinfo') or - os.path.exists('/usr/lib/zoneinfo'), - "Can't find the Olson's TZ database") - @test.support.run_with_tz('Europe/Kiev') + @test.support.run_with_tz('Europe/Kyiv') def test_variable_tzname(self): t0 = datetime.datetime(1984, 1, 1, tzinfo=datetime.timezone.utc) t1 = utils.localtime(t0) + if t1.tzname() == 'Europe': + self.skipTest("Can't find a Kyiv timezone database") self.assertEqual(t1.tzname(), 'MSK') t0 = datetime.datetime(1994, 1, 1, tzinfo=datetime.timezone.utc) t1 = utils.localtime(t0) diff --git a/Lib/test/test_embed.py b/Lib/test/test_embed.py index 582392ecddcb91..6c60854bbd76cc 100644 --- a/Lib/test/test_embed.py +++ b/Lib/test/test_embed.py @@ -1,8 +1,6 @@ # Run the tests in Programs/_testembed.c (tests for the CPython embedding APIs) from test import support -from test.support import import_helper -from test.support import os_helper -from test.support import requires_specialization +from test.support import import_helper, os_helper, MS_WINDOWS import unittest from collections import namedtuple @@ -21,11 +19,17 @@ if not support.has_subprocess_support: raise unittest.SkipTest("test module requires subprocess") -MS_WINDOWS = (os.name == 'nt') MACOS = (sys.platform == 'darwin') PYMEM_ALLOCATOR_NOT_SET = 0 PYMEM_ALLOCATOR_DEBUG = 2 PYMEM_ALLOCATOR_MALLOC = 3 +PYMEM_ALLOCATOR_MIMALLOC = 7 +if support.Py_GIL_DISABLED: + ALLOCATOR_FOR_CONFIG = PYMEM_ALLOCATOR_MIMALLOC +else: + ALLOCATOR_FOR_CONFIG = PYMEM_ALLOCATOR_MALLOC + +Py_STATS = hasattr(sys, '_stats_on') # _PyCoreConfig_InitCompatConfig() API_COMPAT = 1 @@ -347,7 +351,7 @@ def test_simple_initialization_api(self): out, err = self.run_embedded_interpreter("test_repeated_simple_init") self.assertEqual(out, 'Finalized\n' * INIT_LOOPS) - @requires_specialization + @support.requires_specialization def test_specialized_static_code_gets_unspecialized_at_Py_FINALIZE(self): # https://github.com/python/cpython/issues/92031 @@ -361,7 +365,7 @@ def is_specialized(f): for instruction in dis.get_instructions(f, adaptive=True): opname = instruction.opname if ( - opname in opcode._specialized_instructions + opname in opcode._specialized_opmap # Exclude superinstructions: and "__" not in opname ): @@ -447,6 +451,7 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase): 'use_hash_seed': 0, 'hash_seed': 0, 'int_max_str_digits': sys.int_info.default_max_str_digits, + 'cpu_count': -1, 'faulthandler': 0, 'tracemalloc': 0, 'perf_profiling': 0, @@ -454,6 +459,7 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase): 'code_debug_ranges': 1, 'show_ref_count': 0, 'dump_refs': 0, + 'dump_refs_file': None, 'malloc_stats': 0, 'filesystem_encoding': GET_DEFAULT_CONFIG, @@ -503,6 +509,7 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase): 'run_command': None, 'run_module': None, 'run_filename': None, + 'sys_path_0': None, '_install_importlib': 1, 'check_hash_pycs_mode': 'default', @@ -512,6 +519,10 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase): 'safe_path': 0, '_is_python_build': IGNORE_CONFIG, } + if Py_STATS: + CONFIG_COMPAT['_pystats'] = 0 + if support.Py_DEBUG: + CONFIG_COMPAT['run_presite'] = None if MS_WINDOWS: CONFIG_COMPAT.update({ 'legacy_windows_stdio': 0, @@ -836,7 +847,7 @@ def test_init_global_config(self): def test_init_from_config(self): preconfig = { - 'allocator': PYMEM_ALLOCATOR_MALLOC, + 'allocator': ALLOCATOR_FOR_CONFIG, 'utf8_mode': 1, } config = { @@ -891,16 +902,19 @@ def test_init_from_config(self): 'module_search_paths': self.IGNORE_CONFIG, 'safe_path': 1, 'int_max_str_digits': 31337, + 'cpu_count': 4321, 'check_hash_pycs_mode': 'always', 'pathconfig_warnings': 0, } + if Py_STATS: + config['_pystats'] = 1 self.check_all_configs("test_init_from_config", config, preconfig, api=API_COMPAT) def test_init_compat_env(self): preconfig = { - 'allocator': PYMEM_ALLOCATOR_MALLOC, + 'allocator': ALLOCATOR_FOR_CONFIG, } config = { 'use_hash_seed': 1, @@ -927,12 +941,14 @@ def test_init_compat_env(self): 'safe_path': 1, 'int_max_str_digits': 4567, } + if Py_STATS: + config['_pystats'] = 1 self.check_all_configs("test_init_compat_env", config, preconfig, api=API_COMPAT) def test_init_python_env(self): preconfig = { - 'allocator': PYMEM_ALLOCATOR_MALLOC, + 'allocator': ALLOCATOR_FOR_CONFIG, 'utf8_mode': 1, } config = { @@ -960,6 +976,8 @@ def test_init_python_env(self): 'safe_path': 1, 'int_max_str_digits': 4567, } + if Py_STATS: + config['_pystats'] = 1 self.check_all_configs("test_init_python_env", config, preconfig, api=API_PYTHON) @@ -972,7 +990,7 @@ def test_init_env_dev_mode(self): api=API_COMPAT) def test_init_env_dev_mode_alloc(self): - preconfig = dict(allocator=PYMEM_ALLOCATOR_MALLOC) + preconfig = dict(allocator=ALLOCATOR_FOR_CONFIG) config = dict(dev_mode=1, faulthandler=1, warnoptions=['default']) @@ -1122,6 +1140,7 @@ def test_init_run_main(self): 'program_name': './python3', 'run_command': code + '\n', 'parse_argv': 2, + 'sys_path_0': '', } self.check_all_configs("test_init_run_main", config, api=API_PYTHON) @@ -1137,6 +1156,7 @@ def test_init_main(self): 'run_command': code + '\n', 'parse_argv': 2, '_init_main': 0, + 'sys_path_0': '', } self.check_all_configs("test_init_main", config, api=API_PYTHON, @@ -1703,6 +1723,9 @@ def test_open_code_hook(self): def test_audit(self): self.run_embedded_interpreter("test_audit") + def test_audit_tuple(self): + self.run_embedded_interpreter("test_audit_tuple") + def test_audit_subinterpreter(self): self.run_embedded_interpreter("test_audit_subinterpreter") @@ -1803,6 +1826,22 @@ def test_no_memleak(self): self.assertEqual(refs, 0, out) self.assertEqual(blocks, 0, out) + @unittest.skipUnless(support.Py_DEBUG, + '-X presite requires a Python debug build') + def test_presite(self): + cmd = [sys.executable, "-I", "-X", "presite=test.reperf", "-c", "print('cmd')"] + proc = subprocess.run( + cmd, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + text=True, + ) + self.assertEqual(proc.returncode, 0) + out = proc.stdout.strip() + self.assertIn("10 times sub", out) + self.assertIn("CPU seconds", out) + self.assertIn("cmd", out) + class StdPrinterTests(EmbeddingTestsMixin, unittest.TestCase): # Test PyStdPrinter_Type which is used by _PySys_SetPreliminaryStderr(): diff --git a/Lib/test/test_enum.py b/Lib/test/test_enum.py index a286411f7bcf57..f99d4ca204b5a7 100644 --- a/Lib/test/test_enum.py +++ b/Lib/test/test_enum.py @@ -18,7 +18,7 @@ from io import StringIO from pickle import dumps, loads, PicklingError, HIGHEST_PROTOCOL from test import support -from test.support import ALWAYS_EQ +from test.support import ALWAYS_EQ, REPO_ROOT from test.support import threading_helper from datetime import timedelta @@ -26,18 +26,42 @@ def load_tests(loader, tests, ignore): tests.addTests(doctest.DocTestSuite(enum)) - if os.path.exists('Doc/library/enum.rst'): + + lib_tests = os.path.join(REPO_ROOT, 'Doc/library/enum.rst') + if os.path.exists(lib_tests): tests.addTests(doctest.DocFileSuite( - '../../Doc/library/enum.rst', + lib_tests, + module_relative=False, optionflags=doctest.ELLIPSIS|doctest.NORMALIZE_WHITESPACE, )) - if os.path.exists('Doc/howto/enum.rst'): + howto_tests = os.path.join(REPO_ROOT, 'Doc/howto/enum.rst') + if os.path.exists(howto_tests): tests.addTests(doctest.DocFileSuite( - '../../Doc/howto/enum.rst', + howto_tests, + module_relative=False, optionflags=doctest.ELLIPSIS|doctest.NORMALIZE_WHITESPACE, )) return tests +def reraise_if_not_enum(*enum_types_or_exceptions): + from functools import wraps + + def decorator(func): + @wraps(func) + def inner(*args, **kwargs): + excs = [ + e + for e in enum_types_or_exceptions + if isinstance(e, Exception) + ] + if len(excs) == 1: + raise excs[0] + elif excs: + raise ExceptionGroup('Enum Exceptions', excs) + return func(*args, **kwargs) + return inner + return decorator + MODULE = __name__ SHORT_MODULE = MODULE.split('.')[-1] @@ -75,30 +99,42 @@ class FlagStooges(Flag): except Exception as exc: FlagStooges = exc -class FlagStoogesWithZero(Flag): - NOFLAG = 0 - LARRY = 1 - CURLY = 2 - MOE = 4 - BIG = 389 - -class IntFlagStooges(IntFlag): - LARRY = 1 - CURLY = 2 - MOE = 4 - BIG = 389 - -class IntFlagStoogesWithZero(IntFlag): - NOFLAG = 0 - LARRY = 1 - CURLY = 2 - MOE = 4 - BIG = 389 +try: + class FlagStoogesWithZero(Flag): + NOFLAG = 0 + LARRY = 1 + CURLY = 2 + MOE = 4 + BIG = 389 +except Exception as exc: + FlagStoogesWithZero = exc + +try: + class IntFlagStooges(IntFlag): + LARRY = 1 + CURLY = 2 + MOE = 4 + BIG = 389 +except Exception as exc: + IntFlagStooges = exc + +try: + class IntFlagStoogesWithZero(IntFlag): + NOFLAG = 0 + LARRY = 1 + CURLY = 2 + MOE = 4 + BIG = 389 +except Exception as exc: + IntFlagStoogesWithZero = exc # for pickle test and subclass tests -class Name(StrEnum): - BDFL = 'Guido van Rossum' - FLUFL = 'Barry Warsaw' +try: + class Name(StrEnum): + BDFL = 'Guido van Rossum' + FLUFL = 'Barry Warsaw' +except Exception as exc: + Name = exc try: Question = Enum('Question', 'who what when where why', module=__name__) @@ -140,7 +176,7 @@ class TestHelpers(unittest.TestCase): sunder_names = '_bad_', '_good_', '_what_ho_' dunder_names = '__mal__', '__bien__', '__que_que__' - private_names = '_MyEnum__private', '_MyEnum__still_private' + private_names = '_MyEnum__private', '_MyEnum__still_private', '_MyEnum___triple_private' private_and_sunder_names = '_MyEnum__private_', '_MyEnum__also_private_' random_names = 'okay', '_semi_private', '_weird__', '_MyEnum__' @@ -204,26 +240,35 @@ def __get__(self, instance, ownerclass): # for global repr tests -@enum.global_enum -class HeadlightsK(IntFlag, boundary=enum.KEEP): - OFF_K = 0 - LOW_BEAM_K = auto() - HIGH_BEAM_K = auto() - FOG_K = auto() +try: + @enum.global_enum + class HeadlightsK(IntFlag, boundary=enum.KEEP): + OFF_K = 0 + LOW_BEAM_K = auto() + HIGH_BEAM_K = auto() + FOG_K = auto() +except Exception as exc: + HeadlightsK = exc -@enum.global_enum -class HeadlightsC(IntFlag, boundary=enum.CONFORM): - OFF_C = 0 - LOW_BEAM_C = auto() - HIGH_BEAM_C = auto() - FOG_C = auto() +try: + @enum.global_enum + class HeadlightsC(IntFlag, boundary=enum.CONFORM): + OFF_C = 0 + LOW_BEAM_C = auto() + HIGH_BEAM_C = auto() + FOG_C = auto() +except Exception as exc: + HeadlightsC = exc -@enum.global_enum -class NoName(Flag): - ONE = 1 - TWO = 2 +try: + @enum.global_enum + class NoName(Flag): + ONE = 1 + TWO = 2 +except Exception as exc: + NoName = exc # tests @@ -236,11 +281,83 @@ class _EnumTests: values = None def setUp(self): - class BaseEnum(self.enum_type): + if self.__class__.__name__[-5:] == 'Class': + class BaseEnum(self.enum_type): + @enum.property + def first(self): + return '%s is first!' % self.name + class MainEnum(BaseEnum): + first = auto() + second = auto() + third = auto() + if issubclass(self.enum_type, Flag): + dupe = 3 + else: + dupe = third + self.MainEnum = MainEnum + # + class NewStrEnum(self.enum_type): + def __str__(self): + return self.name.upper() + first = auto() + self.NewStrEnum = NewStrEnum + # + class NewFormatEnum(self.enum_type): + def __format__(self, spec): + return self.name.upper() + first = auto() + self.NewFormatEnum = NewFormatEnum + # + class NewStrFormatEnum(self.enum_type): + def __str__(self): + return self.name.title() + def __format__(self, spec): + return ''.join(reversed(self.name)) + first = auto() + self.NewStrFormatEnum = NewStrFormatEnum + # + class NewBaseEnum(self.enum_type): + def __str__(self): + return self.name.title() + def __format__(self, spec): + return ''.join(reversed(self.name)) + self.NewBaseEnum = NewBaseEnum + class NewSubEnum(NewBaseEnum): + first = auto() + self.NewSubEnum = NewSubEnum + # + class LazyGNV(self.enum_type): + def _generate_next_value_(name, start, last, values): + pass + self.LazyGNV = LazyGNV + # + class BusyGNV(self.enum_type): + @staticmethod + def _generate_next_value_(name, start, last, values): + pass + self.BusyGNV = BusyGNV + # + self.is_flag = False + self.names = ['first', 'second', 'third'] + if issubclass(MainEnum, StrEnum): + self.values = self.names + elif MainEnum._member_type_ is str: + self.values = ['1', '2', '3'] + elif issubclass(self.enum_type, Flag): + self.values = [1, 2, 4] + self.is_flag = True + self.dupe2 = MainEnum(5) + else: + self.values = self.values or [1, 2, 3] + # + if not getattr(self, 'source_values', False): + self.source_values = self.values + elif self.__class__.__name__[-8:] == 'Function': @enum.property def first(self): return '%s is first!' % self.name - class MainEnum(BaseEnum): + BaseEnum = self.enum_type('BaseEnum', {'first':first}) + # first = auto() second = auto() third = auto() @@ -248,63 +365,58 @@ class MainEnum(BaseEnum): dupe = 3 else: dupe = third - self.MainEnum = MainEnum - # - class NewStrEnum(self.enum_type): + self.MainEnum = MainEnum = BaseEnum('MainEnum', dict(first=first, second=second, third=third, dupe=dupe)) + # def __str__(self): return self.name.upper() first = auto() - self.NewStrEnum = NewStrEnum - # - class NewFormatEnum(self.enum_type): + self.NewStrEnum = self.enum_type('NewStrEnum', (('first',first),('__str__',__str__))) + # def __format__(self, spec): return self.name.upper() first = auto() - self.NewFormatEnum = NewFormatEnum - # - class NewStrFormatEnum(self.enum_type): + self.NewFormatEnum = self.enum_type('NewFormatEnum', [('first',first),('__format__',__format__)]) + # def __str__(self): return self.name.title() def __format__(self, spec): return ''.join(reversed(self.name)) first = auto() - self.NewStrFormatEnum = NewStrFormatEnum - # - class NewBaseEnum(self.enum_type): + self.NewStrFormatEnum = self.enum_type('NewStrFormatEnum', dict(first=first, __format__=__format__, __str__=__str__)) + # def __str__(self): return self.name.title() def __format__(self, spec): return ''.join(reversed(self.name)) - class NewSubEnum(NewBaseEnum): - first = auto() - self.NewSubEnum = NewSubEnum - # - class LazyGNV(self.enum_type): + self.NewBaseEnum = self.enum_type('NewBaseEnum', dict(__format__=__format__, __str__=__str__)) + self.NewSubEnum = self.NewBaseEnum('NewSubEnum', 'first') + # def _generate_next_value_(name, start, last, values): pass - self.LazyGNV = LazyGNV - # - class BusyGNV(self.enum_type): + self.LazyGNV = self.enum_type('LazyGNV', {'_generate_next_value_':_generate_next_value_}) + # @staticmethod def _generate_next_value_(name, start, last, values): pass - self.BusyGNV = BusyGNV - # - self.is_flag = False - self.names = ['first', 'second', 'third'] - if issubclass(MainEnum, StrEnum): - self.values = self.names - elif MainEnum._member_type_ is str: - self.values = ['1', '2', '3'] - elif issubclass(self.enum_type, Flag): - self.values = [1, 2, 4] - self.is_flag = True - self.dupe2 = MainEnum(5) + self.BusyGNV = self.enum_type('BusyGNV', {'_generate_next_value_':_generate_next_value_}) + # + self.is_flag = False + self.names = ['first', 'second', 'third'] + if issubclass(MainEnum, StrEnum): + self.values = self.names + elif MainEnum._member_type_ is str: + self.values = ['1', '2', '3'] + elif issubclass(self.enum_type, Flag): + self.values = [1, 2, 4] + self.is_flag = True + self.dupe2 = MainEnum(5) + else: + self.values = self.values or [1, 2, 3] + # + if not getattr(self, 'source_values', False): + self.source_values = self.values else: - self.values = self.values or [1, 2, 3] - # - if not getattr(self, 'source_values', False): - self.source_values = self.values + raise ValueError('unknown enum style: %r' % self.__class__.__name__) def assertFormatIsValue(self, spec, member): self.assertEqual(spec.format(member), spec.format(member.value)) @@ -332,6 +444,17 @@ def spam(cls): with self.assertRaises(AttributeError): del Season.SPRING.name + def test_bad_new_super(self): + with self.assertRaisesRegex( + TypeError, + 'has no members defined', + ): + class BadSuper(self.enum_type): + def __new__(cls, value): + obj = super().__new__(cls, value) + return obj + failed = 1 + def test_basics(self): TE = self.MainEnum if self.is_flag: @@ -387,10 +510,11 @@ def test_contains_tf(self): MainEnum = self.MainEnum self.assertIn(MainEnum.first, MainEnum) self.assertTrue(self.values[0] in MainEnum) - if type(self) is not TestStrEnum: + if type(self) not in (TestStrEnumClass, TestStrEnumFunction): self.assertFalse('first' in MainEnum) val = MainEnum.dupe self.assertIn(val, MainEnum) + self.assertNotIn(float('nan'), MainEnum) # class OtherEnum(Enum): one = auto() @@ -482,6 +606,10 @@ class SubEnum(SuperEnum): self.assertTrue('description' not in dir(SubEnum)) self.assertTrue('description' in dir(SubEnum.sample), dir(SubEnum.sample)) + def test_empty_enum_has_no_values(self): + with self.assertRaisesRegex(TypeError, "<.... 'NewBaseEnum'> has no members"): + self.NewBaseEnum(7) + def test_enum_in_enum_out(self): Main = self.MainEnum self.assertIs(Main(Main.first), Main.first) @@ -909,15 +1037,23 @@ class OpenXYZ(self.enum_type): self.assertTrue(~OpenXYZ(0), (X|Y|Z)) -class TestPlainEnum(_EnumTests, _PlainOutputTests, unittest.TestCase): +class TestPlainEnumClass(_EnumTests, _PlainOutputTests, unittest.TestCase): enum_type = Enum -class TestPlainFlag(_EnumTests, _PlainOutputTests, _FlagTests, unittest.TestCase): +class TestPlainEnumFunction(_EnumTests, _PlainOutputTests, unittest.TestCase): + enum_type = Enum + + +class TestPlainFlagClass(_EnumTests, _PlainOutputTests, _FlagTests, unittest.TestCase): enum_type = Flag -class TestIntEnum(_EnumTests, _MinimalOutputTests, unittest.TestCase): +class TestPlainFlagFunction(_EnumTests, _PlainOutputTests, _FlagTests, unittest.TestCase): + enum_type = Flag + + +class TestIntEnumClass(_EnumTests, _MinimalOutputTests, unittest.TestCase): enum_type = IntEnum # def test_shadowed_attr(self): @@ -929,7 +1065,17 @@ class Number(IntEnum): self.assertIs(Number.numerator.divisor, Number.divisor) -class TestStrEnum(_EnumTests, _MinimalOutputTests, unittest.TestCase): +class TestIntEnumFunction(_EnumTests, _MinimalOutputTests, unittest.TestCase): + enum_type = IntEnum + # + def test_shadowed_attr(self): + Number = IntEnum('Number', ('divisor', 'numerator')) + # + self.assertEqual(Number.divisor.numerator, 1) + self.assertIs(Number.numerator.divisor, Number.divisor) + + +class TestStrEnumClass(_EnumTests, _MinimalOutputTests, unittest.TestCase): enum_type = StrEnum # def test_shadowed_attr(self): @@ -942,64 +1088,141 @@ class Book(StrEnum): self.assertIs(Book.title.author, Book.author) -class TestIntFlag(_EnumTests, _MinimalOutputTests, _FlagTests, unittest.TestCase): +class TestStrEnumFunction(_EnumTests, _MinimalOutputTests, unittest.TestCase): + enum_type = StrEnum + # + def test_shadowed_attr(self): + Book = StrEnum('Book', ('author', 'title')) + # + self.assertEqual(Book.author.title(), 'Author') + self.assertEqual(Book.title.title(), 'Title') + self.assertIs(Book.title.author, Book.author) + + +class TestIntFlagClass(_EnumTests, _MinimalOutputTests, _FlagTests, unittest.TestCase): enum_type = IntFlag -class TestMixedInt(_EnumTests, _MixedOutputTests, unittest.TestCase): +class TestIntFlagFunction(_EnumTests, _MinimalOutputTests, _FlagTests, unittest.TestCase): + enum_type = IntFlag + + +class TestMixedIntClass(_EnumTests, _MixedOutputTests, unittest.TestCase): class enum_type(int, Enum): pass -class TestMixedStr(_EnumTests, _MixedOutputTests, unittest.TestCase): +class TestMixedIntFunction(_EnumTests, _MixedOutputTests, unittest.TestCase): + enum_type = Enum('enum_type', type=int) + + +class TestMixedStrClass(_EnumTests, _MixedOutputTests, unittest.TestCase): class enum_type(str, Enum): pass -class TestMixedIntFlag(_EnumTests, _MixedOutputTests, _FlagTests, unittest.TestCase): +class TestMixedStrFunction(_EnumTests, _MixedOutputTests, unittest.TestCase): + enum_type = Enum('enum_type', type=str) + + +class TestMixedIntFlagClass(_EnumTests, _MixedOutputTests, _FlagTests, unittest.TestCase): class enum_type(int, Flag): pass -class TestMixedDate(_EnumTests, _MixedOutputTests, unittest.TestCase): +class TestMixedIntFlagFunction(_EnumTests, _MixedOutputTests, _FlagTests, unittest.TestCase): + enum_type = Flag('enum_type', type=int) + +class TestMixedDateClass(_EnumTests, _MixedOutputTests, unittest.TestCase): + # values = [date(2021, 12, 25), date(2020, 3, 15), date(2019, 11, 27)] source_values = [(2021, 12, 25), (2020, 3, 15), (2019, 11, 27)] - + # class enum_type(date, Enum): + @staticmethod def _generate_next_value_(name, start, count, last_values): values = [(2021, 12, 25), (2020, 3, 15), (2019, 11, 27)] return values[count] -class TestMinimalDate(_EnumTests, _MinimalOutputTests, unittest.TestCase): +class TestMixedDateFunction(_EnumTests, _MixedOutputTests, unittest.TestCase): + # + values = [date(2021, 12, 25), date(2020, 3, 15), date(2019, 11, 27)] + source_values = [(2021, 12, 25), (2020, 3, 15), (2019, 11, 27)] + # + # staticmethod decorator will be added by EnumType if not present + def _generate_next_value_(name, start, count, last_values): + values = [(2021, 12, 25), (2020, 3, 15), (2019, 11, 27)] + return values[count] + # + enum_type = Enum('enum_type', {'_generate_next_value_':_generate_next_value_}, type=date) + +class TestMinimalDateClass(_EnumTests, _MinimalOutputTests, unittest.TestCase): + # values = [date(2023, 12, 1), date(2016, 2, 29), date(2009, 1, 1)] source_values = [(2023, 12, 1), (2016, 2, 29), (2009, 1, 1)] - + # class enum_type(date, ReprEnum): + # staticmethod decorator will be added by EnumType if absent def _generate_next_value_(name, start, count, last_values): values = [(2023, 12, 1), (2016, 2, 29), (2009, 1, 1)] return values[count] -class TestMixedFloat(_EnumTests, _MixedOutputTests, unittest.TestCase): +class TestMinimalDateFunction(_EnumTests, _MinimalOutputTests, unittest.TestCase): + # + values = [date(2023, 12, 1), date(2016, 2, 29), date(2009, 1, 1)] + source_values = [(2023, 12, 1), (2016, 2, 29), (2009, 1, 1)] + # + @staticmethod + def _generate_next_value_(name, start, count, last_values): + values = [(2023, 12, 1), (2016, 2, 29), (2009, 1, 1)] + return values[count] + # + enum_type = ReprEnum('enum_type', {'_generate_next_value_':_generate_next_value_}, type=date) - values = [1.1, 2.2, 3.3] +class TestMixedFloatClass(_EnumTests, _MixedOutputTests, unittest.TestCase): + # + values = [1.1, 2.2, 3.3] + # class enum_type(float, Enum): def _generate_next_value_(name, start, count, last_values): values = [1.1, 2.2, 3.3] return values[count] -class TestMinimalFloat(_EnumTests, _MinimalOutputTests, unittest.TestCase): +class TestMixedFloatFunction(_EnumTests, _MixedOutputTests, unittest.TestCase): + # + values = [1.1, 2.2, 3.3] + # + def _generate_next_value_(name, start, count, last_values): + values = [1.1, 2.2, 3.3] + return values[count] + # + enum_type = Enum('enum_type', {'_generate_next_value_':_generate_next_value_}, type=float) - values = [4.4, 5.5, 6.6] +class TestMinimalFloatClass(_EnumTests, _MinimalOutputTests, unittest.TestCase): + # + values = [4.4, 5.5, 6.6] + # class enum_type(float, ReprEnum): def _generate_next_value_(name, start, count, last_values): values = [4.4, 5.5, 6.6] return values[count] +class TestMinimalFloatFunction(_EnumTests, _MinimalOutputTests, unittest.TestCase): + # + values = [4.4, 5.5, 6.6] + # + def _generate_next_value_(name, start, count, last_values): + values = [4.4, 5.5, 6.6] + return values[count] + # + enum_type = ReprEnum('enum_type', {'_generate_next_value_':_generate_next_value_}, type=float) + + class TestSpecial(unittest.TestCase): """ various operations that are not attributable to every possible enum @@ -1124,9 +1347,8 @@ def red(self): green = 2 blue = 3 + @reraise_if_not_enum(Theory) def test_enum_function_with_qualname(self): - if isinstance(Theory, Exception): - raise Theory self.assertEqual(Theory.__qualname__, 'spanish_inquisition') def test_enum_of_types(self): @@ -1355,6 +1577,7 @@ class MyUnBrokenEnum(UnBrokenInt, Enum): test_pickle_dump_load(self.assertIs, MyUnBrokenEnum.I) test_pickle_dump_load(self.assertIs, MyUnBrokenEnum) + @reraise_if_not_enum(FloatStooges) def test_floatenum_fromhex(self): h = float.hex(FloatStooges.MOE.value) self.assertIs(FloatStooges.fromhex(h), FloatStooges.MOE) @@ -1475,6 +1698,7 @@ class ThreePart(Enum): self.assertIs(ThreePart((3, 3.0, 'three')), ThreePart.THREE) self.assertIs(ThreePart(3, 3.0, 'three'), ThreePart.THREE) + @reraise_if_not_enum(IntStooges) def test_intenum_from_bytes(self): self.assertIs(IntStooges.from_bytes(b'\x00\x03', 'big'), IntStooges.MOE) with self.assertRaises(ValueError): @@ -1503,33 +1727,28 @@ def repr(self): class Huh(MyStr, MyInt, Enum): One = 1 + @reraise_if_not_enum(Stooges) def test_pickle_enum(self): - if isinstance(Stooges, Exception): - raise Stooges test_pickle_dump_load(self.assertIs, Stooges.CURLY) test_pickle_dump_load(self.assertIs, Stooges) + @reraise_if_not_enum(IntStooges) def test_pickle_int(self): - if isinstance(IntStooges, Exception): - raise IntStooges test_pickle_dump_load(self.assertIs, IntStooges.CURLY) test_pickle_dump_load(self.assertIs, IntStooges) + @reraise_if_not_enum(FloatStooges) def test_pickle_float(self): - if isinstance(FloatStooges, Exception): - raise FloatStooges test_pickle_dump_load(self.assertIs, FloatStooges.CURLY) test_pickle_dump_load(self.assertIs, FloatStooges) + @reraise_if_not_enum(Answer) def test_pickle_enum_function(self): - if isinstance(Answer, Exception): - raise Answer test_pickle_dump_load(self.assertIs, Answer.him) test_pickle_dump_load(self.assertIs, Answer) + @reraise_if_not_enum(Question) def test_pickle_enum_function_with_module(self): - if isinstance(Question, Exception): - raise Question test_pickle_dump_load(self.assertIs, Question.who) test_pickle_dump_load(self.assertIs, Question) @@ -1592,9 +1811,8 @@ class Season(Enum): [Season.SUMMER, Season.WINTER, Season.AUTUMN, Season.SPRING], ) + @reraise_if_not_enum(Name) def test_subclassing(self): - if isinstance(Name, Exception): - raise Name self.assertEqual(Name.BDFL, 'Guido van Rossum') self.assertTrue(Name.BDFL, Name('Guido van Rossum')) self.assertIs(Name.BDFL, getattr(Name, 'BDFL')) @@ -2764,11 +2982,13 @@ class SecondFailedStrEnum(CustomStrEnum): class ThirdFailedStrEnum(CustomStrEnum): one = '1' two = 2 # this will become '2' - with self.assertRaisesRegex(TypeError, '.encoding. must be str, not '): + with self.assertRaisesRegex(TypeError, + r"argument (2|'encoding') must be str, not "): class ThirdFailedStrEnum(CustomStrEnum): one = '1' two = b'2', sys.getdefaultencoding - with self.assertRaisesRegex(TypeError, '.errors. must be str, not '): + with self.assertRaisesRegex(TypeError, + r"argument (3|'errors') must be str, not "): class ThirdFailedStrEnum(CustomStrEnum): one = '1' two = b'2', 'ascii', 9 @@ -3049,6 +3269,65 @@ def __new__(cls, value): member._value_ = Base(value) return member + def test_extra_member_creation(self): + class IDEnumMeta(EnumMeta): + def __new__(metacls, cls, bases, classdict, **kwds): + # add new entries to classdict + for name in classdict.member_names: + classdict[f'{name}_DESC'] = f'-{classdict[name]}' + return super().__new__(metacls, cls, bases, classdict, **kwds) + class IDEnum(StrEnum, metaclass=IDEnumMeta): + pass + class MyEnum(IDEnum): + ID = 'id' + NAME = 'name' + self.assertEqual(list(MyEnum), [MyEnum.ID, MyEnum.NAME, MyEnum.ID_DESC, MyEnum.NAME_DESC]) + + def test_add_alias(self): + class mixin: + @property + def ORG(self): + return 'huh' + class Color(mixin, Enum): + RED = 1 + GREEN = 2 + BLUE = 3 + Color.RED._add_alias_('ROJO') + self.assertIs(Color.RED, Color['ROJO']) + self.assertIs(Color.RED, Color.ROJO) + Color.BLUE._add_alias_('ORG') + self.assertIs(Color.BLUE, Color['ORG']) + self.assertIs(Color.BLUE, Color.ORG) + self.assertEqual(Color.RED.ORG, 'huh') + self.assertEqual(Color.GREEN.ORG, 'huh') + self.assertEqual(Color.BLUE.ORG, 'huh') + self.assertEqual(Color.ORG.ORG, 'huh') + + def test_add_value_alias_after_creation(self): + class Color(Enum): + RED = 1 + GREEN = 2 + BLUE = 3 + Color.RED._add_value_alias_(5) + self.assertIs(Color.RED, Color(5)) + + def test_add_value_alias_during_creation(self): + class Types(Enum): + Unknown = 0, + Source = 1, 'src' + NetList = 2, 'nl' + def __new__(cls, int_value, *value_aliases): + member = object.__new__(cls) + member._value_ = int_value + for alias in value_aliases: + member._add_value_alias_(alias) + return member + self.assertIs(Types(0), Types.Unknown) + self.assertIs(Types(1), Types.Source) + self.assertIs(Types('src'), Types.Source) + self.assertIs(Types(2), Types.NetList) + self.assertIs(Types('nl'), Types.NetList) + class TestOrder(unittest.TestCase): "test usage of the `_order_` attribute" @@ -3330,9 +3609,13 @@ def test_programatic_function_from_dict(self): self.assertIn(e, Perm) self.assertIs(type(e), Perm) + @reraise_if_not_enum( + FlagStooges, + FlagStoogesWithZero, + IntFlagStooges, + IntFlagStoogesWithZero, + ) def test_pickle(self): - if isinstance(FlagStooges, Exception): - raise FlagStooges test_pickle_dump_load(self.assertIs, FlagStooges.CURLY) test_pickle_dump_load(self.assertEqual, FlagStooges.CURLY|FlagStooges.MOE) @@ -3637,6 +3920,7 @@ def test_type(self): self.assertTrue(isinstance(Open.WO | Open.RW, Open)) self.assertEqual(Open.WO | Open.RW, 3) + @reraise_if_not_enum(HeadlightsK) def test_global_repr_keep(self): self.assertEqual( repr(HeadlightsK(0)), @@ -3651,6 +3935,7 @@ def test_global_repr_keep(self): '%(m)s.HeadlightsK(8)' % {'m': SHORT_MODULE}, ) + @reraise_if_not_enum(HeadlightsC) def test_global_repr_conform1(self): self.assertEqual( repr(HeadlightsC(0)), @@ -3665,6 +3950,7 @@ def test_global_repr_conform1(self): '%(m)s.OFF_C' % {'m': SHORT_MODULE}, ) + @reraise_if_not_enum(NoName) def test_global_enum_str(self): self.assertEqual(str(NoName.ONE & NoName.TWO), 'NoName(0)') self.assertEqual(str(NoName(0)), 'NoName(0)') @@ -4470,8 +4756,6 @@ def _generate_next_value_(name, start, count, last): self.assertEqual(Huh.TWO.value, (2, 2)) self.assertEqual(Huh.THREE.value, (3, 3, 3)) -class TestEnumTypeSubclassing(unittest.TestCase): - pass expected_help_output_with_docs = """\ Help on class Color in module %s: @@ -4717,12 +5001,14 @@ class CheckedColor(Enum): @bltns.property def zeroth(self): return 'zeroed %s' % self.name - self.assertTrue(_test_simple_enum(CheckedColor, SimpleColor) is None) + _test_simple_enum(CheckedColor, SimpleColor) SimpleColor.MAGENTA._value_ = 9 self.assertRaisesRegex( TypeError, "enum mismatch", _test_simple_enum, CheckedColor, SimpleColor, ) + # + # class CheckedMissing(IntFlag, boundary=KEEP): SIXTY_FOUR = 64 ONE_TWENTY_EIGHT = 128 @@ -4739,8 +5025,28 @@ class Missing: ALL = 2048 + 128 + 64 + 12 M = Missing self.assertEqual(list(CheckedMissing), [M.SIXTY_FOUR, M.ONE_TWENTY_EIGHT, M.TWENTY_FORTY_EIGHT]) - # _test_simple_enum(CheckedMissing, Missing) + # + # + class CheckedUnhashable(Enum): + ONE = dict() + TWO = set() + name = 'python' + self.assertIn(dict(), CheckedUnhashable) + self.assertIn('python', CheckedUnhashable) + self.assertEqual(CheckedUnhashable.name.value, 'python') + self.assertEqual(CheckedUnhashable.name.name, 'name') + # + @_simple_enum() + class Unhashable: + ONE = dict() + TWO = set() + name = 'python' + self.assertIn(dict(), Unhashable) + self.assertIn('python', Unhashable) + self.assertEqual(Unhashable.name.value, 'python') + self.assertEqual(Unhashable.name.name, 'name') + _test_simple_enum(Unhashable, Unhashable) class MiscTestCase(unittest.TestCase): @@ -4947,7 +5253,7 @@ def member_dir(member): allowed.add(name) else: allowed.discard(name) - else: + elif name not in member._member_map_: allowed.add(name) return sorted(allowed) diff --git a/Lib/test/test_exception_group.py b/Lib/test/test_exception_group.py index a02d54da35e948..20122679223843 100644 --- a/Lib/test/test_exception_group.py +++ b/Lib/test/test_exception_group.py @@ -1,7 +1,7 @@ import collections.abc import types import unittest -from test.support import C_RECURSION_LIMIT +from test.support import Py_C_RECURSION_LIMIT class TestExceptionGroupTypeHierarchy(unittest.TestCase): def test_exception_group_types(self): @@ -460,7 +460,7 @@ def test_basics_split_by_predicate__match(self): class DeepRecursionInSplitAndSubgroup(unittest.TestCase): def make_deep_eg(self): e = TypeError(1) - for i in range(C_RECURSION_LIMIT + 1): + for i in range(Py_C_RECURSION_LIMIT + 1): e = ExceptionGroup('eg', [e]) return e diff --git a/Lib/test/test_exceptions.py b/Lib/test/test_exceptions.py index f3554f1c4bb3f3..c57488e44aecc6 100644 --- a/Lib/test/test_exceptions.py +++ b/Lib/test/test_exceptions.py @@ -18,6 +18,12 @@ from test.support.warnings_helper import check_warnings from test import support +try: + from _testcapi import INT_MAX +except ImportError: + INT_MAX = 2**31 - 1 + + class NaiveException(Exception): def __init__(self, x): @@ -253,7 +259,7 @@ def testSyntaxErrorOffset(self): check('try:\n pass\nexcept*:\n pass', 3, 8) check('try:\n pass\nexcept*:\n pass\nexcept* ValueError:\n pass', 3, 8) - # Errors thrown by tokenizer.c + # Errors thrown by the tokenizer check('(0x+1)', 1, 3) check('x = 0xI', 1, 6) check('0010 + 2', 1, 1) @@ -318,6 +324,14 @@ def baz(): check('(yield i) = 2', 1, 2) check('def f(*):\n pass', 1, 7) + @unittest.skipIf(INT_MAX >= sys.maxsize, "Downcasting to int is safe for col_offset") + @support.requires_resource('cpu') + @support.bigmemtest(INT_MAX, memuse=2, dry_run=False) + def testMemoryErrorBigSource(self, size): + src = b"if True:\n%*s" % (size, b"pass") + with self.assertRaisesRegex(OverflowError, "Parser column offset overflow"): + compile(src, '', 'exec') + @cpython_only def testSettingException(self): # test that setting an exception at the C level works even if the @@ -1350,6 +1364,7 @@ def g(): @cpython_only + @support.requires_resource('cpu') def test_trashcan_recursion(self): # See bpo-33930 @@ -1484,6 +1499,9 @@ def recurse_in_body_and_except(): @cpython_only + # Python built with Py_TRACE_REFS fail with a fatal error in + # _PyRefchain_Trace() on memory allocation error. + @unittest.skipIf(support.Py_TRACE_REFS, 'cannot test Py_TRACE_REFS build') def test_recursion_normalizing_with_no_memory(self): # Issue #30697. Test that in the abort that occurs when there is no # memory left and the size of the Python frames stack is greater than @@ -1652,6 +1670,9 @@ def test_unhandled(self): self.assertTrue(report.endswith("\n")) @cpython_only + # Python built with Py_TRACE_REFS fail with a fatal error in + # _PyRefchain_Trace() on memory allocation error. + @unittest.skipIf(support.Py_TRACE_REFS, 'cannot test Py_TRACE_REFS build') def test_memory_error_in_PyErr_PrintEx(self): code = """if 1: import _testcapi @@ -1770,6 +1791,20 @@ class TestException(MemoryError): gc_collect() + def test_memory_error_in_subinterp(self): + # gh-109894: subinterpreters shouldn't count on last resort memory error + # when MemoryError is raised through PyErr_NoMemory() call, + # and should preallocate memory errors as does the main interpreter. + # interp.static_objects.last_resort_memory_error.args + # should be initialized to empty tuple to avoid crash on attempt to print it. + code = f"""if 1: + import _testcapi + _testcapi.run_in_subinterp(\"[0]*{sys.maxsize}\") + exit(0) + """ + rc, _, err = script_helper.assert_python_ok("-c", code) + self.assertIn(b'MemoryError', err) + class NameErrorTests(unittest.TestCase): def test_name_error_has_name(self): @@ -1809,6 +1844,13 @@ def f(): self.assertIn("nonsense", err.getvalue()) self.assertIn("ZeroDivisionError", err.getvalue()) + def test_gh_111654(self): + def f(): + class TestClass: + TestClass + + self.assertRaises(NameError, f) + # Note: name suggestion tests live in `test_traceback`. @@ -1931,6 +1973,124 @@ def test_copy_pickle(self): self.assertEqual(exc.name, orig.name) self.assertEqual(exc.path, orig.path) + +class AssertionErrorTests(unittest.TestCase): + def tearDown(self): + unlink(TESTFN) + + def write_source(self, source): + with open(TESTFN, 'w') as testfile: + testfile.write(dedent(source)) + _rc, _out, err = script_helper.assert_python_failure('-Wd', '-X', 'utf8', TESTFN) + return err.decode('utf-8').splitlines() + + def test_assertion_error_location(self): + cases = [ + ('assert None', + [ + ' assert None', + ' ^^^^', + 'AssertionError', + ], + ), + ('assert 0', + [ + ' assert 0', + ' ^', + 'AssertionError', + ], + ), + ('assert 1 > 2', + [ + ' assert 1 > 2', + ' ^^^^^', + 'AssertionError', + ], + ), + ('assert 1 > 2 and 3 > 2', + [ + ' assert 1 > 2 and 3 > 2', + ' ^^^^^^^^^^^^^^^', + 'AssertionError', + ], + ), + ('assert 1 > 2, "message"', + [ + ' assert 1 > 2, "message"', + ' ^^^^^', + 'AssertionError: message', + ], + ), + + # Multiline: + (""" + assert ( + 1 > 2) + """, + [ + ' 1 > 2)', + ' ^^^^^', + 'AssertionError', + ], + ), + (""" + assert ( + 1 > 2), "Message" + """, + [ + ' 1 > 2), "Message"', + ' ^^^^^', + 'AssertionError: Message', + ], + ), + (""" + assert ( + 1 > 2), \\ + "Message" + """, + [ + ' 1 > 2), \\', + ' ^^^^^', + 'AssertionError: Message', + ], + ), + ] + for source, expected in cases: + with self.subTest(source): + result = self.write_source(source) + self.assertEqual(result[-3:], expected) + + def test_multiline_not_highlighted(self): + cases = [ + (""" + assert ( + 1 > 2 + ) + """, + [ + ' 1 > 2', + 'AssertionError', + ], + ), + (""" + assert ( + 1 < 2 and + 3 > 4 + ) + """, + [ + ' 1 < 2 and', + ' 3 > 4', + 'AssertionError', + ], + ), + ] + for source, expected in cases: + with self.subTest(source): + result = self.write_source(source) + self.assertEqual(result[-len(expected):], expected) + + class SyntaxErrorTests(unittest.TestCase): def test_range_of_offsets(self): cases = [ diff --git a/Lib/test/test_faulthandler.py b/Lib/test/test_faulthandler.py index 2e97de592712c0..d0473500a17735 100644 --- a/Lib/test/test_faulthandler.py +++ b/Lib/test/test_faulthandler.py @@ -7,9 +7,7 @@ import subprocess import sys from test import support -from test.support import os_helper -from test.support import script_helper, is_android -from test.support import skip_if_sanitizer +from test.support import os_helper, script_helper, is_android, MS_WINDOWS import tempfile import unittest from textwrap import dedent @@ -23,7 +21,6 @@ raise unittest.SkipTest("test module requires subprocess") TIMEOUT = 0.5 -MS_WINDOWS = (os.name == 'nt') def expected_traceback(lineno1, lineno2, header, min_count=1): @@ -36,7 +33,7 @@ def expected_traceback(lineno1, lineno2, header, min_count=1): return '^' + regex + '$' def skip_segfault_on_android(test): - # Issue #32138: Raising SIGSEGV on Android may not cause a crash. + # gh-76319: Raising SIGSEGV on Android may not cause a crash. return unittest.skipIf(is_android, 'raising SIGSEGV on Android is unreliable')(test) @@ -64,8 +61,16 @@ def get_output(self, code, filename=None, fd=None): pass_fds = [] if fd is not None: pass_fds.append(fd) + env = dict(os.environ) + + # Sanitizers must not handle SIGSEGV (ex: for test_enable_fd()) + option = 'handle_segv=0' + support.set_sanitizer_env_var(env, option) + with support.SuppressCrashReport(): - process = script_helper.spawn_python('-c', code, pass_fds=pass_fds) + process = script_helper.spawn_python('-c', code, + pass_fds=pass_fds, + env=env) with process: output, stderr = process.communicate() exitcode = process.wait() @@ -304,8 +309,6 @@ def test_gil_released(self): 3, 'Segmentation fault') - @skip_if_sanitizer(memory=True, ub=True, reason="sanitizer " - "builds change crashing process output.") @skip_segfault_on_android def test_enable_file(self): with temporary_filename() as filename: @@ -321,8 +324,6 @@ def test_enable_file(self): @unittest.skipIf(sys.platform == "win32", "subprocess doesn't support pass_fds on Windows") - @skip_if_sanitizer(memory=True, ub=True, reason="sanitizer " - "builds change crashing process output.") @skip_segfault_on_android def test_enable_fd(self): with tempfile.TemporaryFile('wb+') as fp: @@ -676,6 +677,7 @@ def test_dump_traceback_later_fd(self): with tempfile.TemporaryFile('wb+') as fp: self.check_dump_traceback_later(fd=fp.fileno()) + @support.requires_resource('walltime') def test_dump_traceback_later_twice(self): self.check_dump_traceback_later(loops=2) diff --git a/Lib/test/test_fcntl.py b/Lib/test/test_fcntl.py index 5da75615b41d79..203dd6fe57dcd9 100644 --- a/Lib/test/test_fcntl.py +++ b/Lib/test/test_fcntl.py @@ -16,37 +16,6 @@ -def get_lockdata(): - try: - os.O_LARGEFILE - except AttributeError: - start_len = "ll" - else: - start_len = "qq" - - if (sys.platform.startswith(('netbsd', 'freebsd', 'openbsd')) - or sys.platform == 'darwin'): - if struct.calcsize('l') == 8: - off_t = 'l' - pid_t = 'i' - else: - off_t = 'lxxxx' - pid_t = 'l' - lockdata = struct.pack(off_t + off_t + pid_t + 'hh', 0, 0, 0, - fcntl.F_WRLCK, 0) - elif sys.platform.startswith('gnukfreebsd'): - lockdata = struct.pack('qqihhi', 0, 0, 0, fcntl.F_WRLCK, 0, 0) - elif sys.platform in ['hp-uxB', 'unixware7']: - lockdata = struct.pack('hhlllii', fcntl.F_WRLCK, 0, 0, 0, 0, 0, 0) - else: - lockdata = struct.pack('hh'+start_len+'hh', fcntl.F_WRLCK, 0, 0, 0, 0, 0) - if lockdata: - if verbose: - print('struct.pack: ', repr(lockdata)) - return lockdata - -lockdata = get_lockdata() - class BadFile: def __init__(self, fn): self.fn = fn @@ -78,12 +47,43 @@ def tearDown(self): self.f.close() unlink(TESTFN) + @staticmethod + def get_lockdata(): + try: + os.O_LARGEFILE + except AttributeError: + start_len = "ll" + else: + start_len = "qq" + + if (sys.platform.startswith(('netbsd', 'freebsd', 'openbsd')) + or sys.platform == 'darwin'): + if struct.calcsize('l') == 8: + off_t = 'l' + pid_t = 'i' + else: + off_t = 'lxxxx' + pid_t = 'l' + lockdata = struct.pack(off_t + off_t + pid_t + 'hh', 0, 0, 0, + fcntl.F_WRLCK, 0) + elif sys.platform.startswith('gnukfreebsd'): + lockdata = struct.pack('qqihhi', 0, 0, 0, fcntl.F_WRLCK, 0, 0) + elif sys.platform in ['hp-uxB', 'unixware7']: + lockdata = struct.pack('hhlllii', fcntl.F_WRLCK, 0, 0, 0, 0, 0, 0) + else: + lockdata = struct.pack('hh'+start_len+'hh', fcntl.F_WRLCK, 0, 0, 0, 0, 0) + if lockdata: + if verbose: + print('struct.pack: ', repr(lockdata)) + return lockdata + def test_fcntl_fileno(self): # the example from the library docs self.f = open(TESTFN, 'wb') rv = fcntl.fcntl(self.f.fileno(), fcntl.F_SETFL, os.O_NONBLOCK) if verbose: print('Status from fcntl with O_NONBLOCK: ', rv) + lockdata = self.get_lockdata() rv = fcntl.fcntl(self.f.fileno(), fcntl.F_SETLKW, lockdata) if verbose: print('String from fcntl with F_SETLKW: ', repr(rv)) @@ -95,6 +95,7 @@ def test_fcntl_file_descriptor(self): rv = fcntl.fcntl(self.f, fcntl.F_SETFL, os.O_NONBLOCK) if verbose: print('Status from fcntl with O_NONBLOCK: ', rv) + lockdata = self.get_lockdata() rv = fcntl.fcntl(self.f, fcntl.F_SETLKW, lockdata) if verbose: print('String from fcntl with F_SETLKW: ', repr(rv)) diff --git a/Lib/test/test_fileio.py b/Lib/test/test_fileio.py index ebfcffd1829174..06d9b454add34c 100644 --- a/Lib/test/test_fileio.py +++ b/Lib/test/test_fileio.py @@ -10,7 +10,8 @@ from functools import wraps from test.support import ( - cpython_only, swap_attr, gc_collect, is_emscripten, is_wasi + cpython_only, swap_attr, gc_collect, is_emscripten, is_wasi, + infinite_recursion, ) from test.support.os_helper import ( TESTFN, TESTFN_ASCII, TESTFN_UNICODE, make_bad_fd, @@ -173,6 +174,16 @@ def testRepr(self): self.assertEqual(repr(self.f), "<%s.FileIO [closed]>" % (self.modulename,)) + def test_subclass_repr(self): + class TestSubclass(self.FileIO): + pass + + f = TestSubclass(TESTFN) + with f: + self.assertIn(TestSubclass.__name__, repr(f)) + + self.assertIn(TestSubclass.__name__, repr(f)) + def testReprNoCloseFD(self): fd = os.open(TESTFN, os.O_RDONLY) try: @@ -183,6 +194,7 @@ def testReprNoCloseFD(self): finally: os.close(fd) + @infinite_recursion(25) def testRecursiveRepr(self): # Issue #25455 with swap_attr(self.f, 'name', self.f): diff --git a/Lib/test/test_float.py b/Lib/test/test_float.py index c4ee1e08251d63..5bd640617d6874 100644 --- a/Lib/test/test_float.py +++ b/Lib/test/test_float.py @@ -18,14 +18,13 @@ except ImportError: _testcapi = None -HAVE_IEEE_754 = float.__getformat__("double").startswith("IEEE") INF = float("inf") NAN = float("nan") #locate file with float format test values test_dir = os.path.dirname(__file__) or os.curdir -format_testfile = os.path.join(test_dir, 'formatfloat_testcases.txt') +format_testfile = os.path.join(test_dir, 'mathdata', 'formatfloat_testcases.txt') class FloatSubclass(float): pass @@ -733,8 +732,13 @@ def test_format_testfile(self): lhs, rhs = map(str.strip, line.split('->')) fmt, arg = lhs.split() - self.assertEqual(fmt % float(arg), rhs) - self.assertEqual(fmt % -float(arg), '-' + rhs) + f = float(arg) + self.assertEqual(fmt % f, rhs) + self.assertEqual(fmt % -f, '-' + rhs) + if fmt != '%r': + fmt2 = fmt[1:] + self.assertEqual(format(f, fmt2), rhs) + self.assertEqual(format(-f, fmt2), '-' + rhs) def test_issue5864(self): self.assertEqual(format(123.456, '.4'), '123.5') @@ -763,6 +767,7 @@ def test_issue35560(self): class ReprTestCase(unittest.TestCase): def test_repr(self): with open(os.path.join(os.path.split(__file__)[0], + 'mathdata', 'floating_points.txt'), encoding="utf-8") as floats_file: for line in floats_file: line = line.strip() @@ -1499,69 +1504,5 @@ def __init__(self, value): self.assertEqual(getattr(f, 'foo', 'none'), 'bar') -# Test PyFloat_Pack2(), PyFloat_Pack4() and PyFloat_Pack8() -# Test PyFloat_Unpack2(), PyFloat_Unpack4() and PyFloat_Unpack8() -BIG_ENDIAN = 0 -LITTLE_ENDIAN = 1 -EPSILON = { - 2: 2.0 ** -11, # binary16 - 4: 2.0 ** -24, # binary32 - 8: 2.0 ** -53, # binary64 -} - -@unittest.skipIf(_testcapi is None, 'needs _testcapi') -class PackTests(unittest.TestCase): - def test_pack(self): - self.assertEqual(_testcapi.float_pack(2, 1.5, BIG_ENDIAN), - b'>\x00') - self.assertEqual(_testcapi.float_pack(4, 1.5, BIG_ENDIAN), - b'?\xc0\x00\x00') - self.assertEqual(_testcapi.float_pack(8, 1.5, BIG_ENDIAN), - b'?\xf8\x00\x00\x00\x00\x00\x00') - self.assertEqual(_testcapi.float_pack(2, 1.5, LITTLE_ENDIAN), - b'\x00>') - self.assertEqual(_testcapi.float_pack(4, 1.5, LITTLE_ENDIAN), - b'\x00\x00\xc0?') - self.assertEqual(_testcapi.float_pack(8, 1.5, LITTLE_ENDIAN), - b'\x00\x00\x00\x00\x00\x00\xf8?') - - def test_unpack(self): - self.assertEqual(_testcapi.float_unpack(b'>\x00', BIG_ENDIAN), - 1.5) - self.assertEqual(_testcapi.float_unpack(b'?\xc0\x00\x00', BIG_ENDIAN), - 1.5) - self.assertEqual(_testcapi.float_unpack(b'?\xf8\x00\x00\x00\x00\x00\x00', BIG_ENDIAN), - 1.5) - self.assertEqual(_testcapi.float_unpack(b'\x00>', LITTLE_ENDIAN), - 1.5) - self.assertEqual(_testcapi.float_unpack(b'\x00\x00\xc0?', LITTLE_ENDIAN), - 1.5) - self.assertEqual(_testcapi.float_unpack(b'\x00\x00\x00\x00\x00\x00\xf8?', LITTLE_ENDIAN), - 1.5) - - def test_roundtrip(self): - large = 2.0 ** 100 - values = [1.0, 1.5, large, 1.0/7, math.pi] - if HAVE_IEEE_754: - values.extend((INF, NAN)) - for value in values: - for size in (2, 4, 8,): - if size == 2 and value == large: - # too large for 16-bit float - continue - rel_tol = EPSILON[size] - for endian in (BIG_ENDIAN, LITTLE_ENDIAN): - with self.subTest(value=value, size=size, endian=endian): - data = _testcapi.float_pack(size, value, endian) - value2 = _testcapi.float_unpack(data, endian) - if isnan(value): - self.assertTrue(isnan(value2), (value, value2)) - elif size < 8: - self.assertTrue(math.isclose(value2, value, rel_tol=rel_tol), - (value, value2)) - else: - self.assertEqual(value2, value) - - if __name__ == '__main__': unittest.main() diff --git a/Lib/test/test_fractions.py b/Lib/test/test_fractions.py index e112f49d2e7944..84779526ce0eb0 100644 --- a/Lib/test/test_fractions.py +++ b/Lib/test/test_fractions.py @@ -7,6 +7,7 @@ import operator import fractions import functools +import os import sys import typing import unittest @@ -15,6 +16,9 @@ from pickle import dumps, loads F = fractions.Fraction +#locate file with float format test values +test_dir = os.path.dirname(__file__) or os.curdir +format_testfile = os.path.join(test_dir, 'mathdata', 'formatfloat_testcases.txt') class DummyFloat(object): """Dummy float class for testing comparisons with Fractions""" @@ -845,12 +849,50 @@ def denominator(self): self.assertEqual(type(f.denominator), myint) def test_format_no_presentation_type(self): - # Triples (fraction, specification, expected_result) + # Triples (fraction, specification, expected_result). testcases = [ - (F(1, 3), '', '1/3'), - (F(-1, 3), '', '-1/3'), - (F(3), '', '3'), - (F(-3), '', '-3'), + # Explicit sign handling + (F(2, 3), '+', '+2/3'), + (F(-2, 3), '+', '-2/3'), + (F(3), '+', '+3'), + (F(-3), '+', '-3'), + (F(2, 3), ' ', ' 2/3'), + (F(-2, 3), ' ', '-2/3'), + (F(3), ' ', ' 3'), + (F(-3), ' ', '-3'), + (F(2, 3), '-', '2/3'), + (F(-2, 3), '-', '-2/3'), + (F(3), '-', '3'), + (F(-3), '-', '-3'), + # Padding + (F(0), '5', ' 0'), + (F(2, 3), '5', ' 2/3'), + (F(-2, 3), '5', ' -2/3'), + (F(2, 3), '0', '2/3'), + (F(2, 3), '1', '2/3'), + (F(2, 3), '2', '2/3'), + # Alignment + (F(2, 3), '<5', '2/3 '), + (F(2, 3), '>5', ' 2/3'), + (F(2, 3), '^5', ' 2/3 '), + (F(2, 3), '=5', ' 2/3'), + (F(-2, 3), '<5', '-2/3 '), + (F(-2, 3), '>5', ' -2/3'), + (F(-2, 3), '^5', '-2/3 '), + (F(-2, 3), '=5', '- 2/3'), + # Fill + (F(2, 3), 'X>5', 'XX2/3'), + (F(-2, 3), '.<5', '-2/3.'), + (F(-2, 3), '\n^6', '\n-2/3\n'), + # Thousands separators + (F(1234, 5679), ',', '1,234/5,679'), + (F(-1234, 5679), '_', '-1_234/5_679'), + (F(1234567), '_', '1_234_567'), + (F(-1234567), ',', '-1,234,567'), + # Alternate form forces a slash in the output + (F(123), '#', '123/1'), + (F(-123), '#', '-123/1'), + (F(0), '#', '0/1'), ] for fraction, spec, expected in testcases: with self.subTest(fraction=fraction, spec=spec): @@ -1214,12 +1256,40 @@ def test_invalid_formats(self): '.%', # Z instead of z for negative zero suppression 'Z.2f' + # z flag not supported for general formatting + 'z', + # zero padding not supported for general formatting + '05', ] for spec in invalid_specs: with self.subTest(spec=spec): with self.assertRaises(ValueError): format(fraction, spec) + @requires_IEEE_754 + def test_float_format_testfile(self): + with open(format_testfile, encoding="utf-8") as testfile: + for line in testfile: + if line.startswith('--'): + continue + line = line.strip() + if not line: + continue + + lhs, rhs = map(str.strip, line.split('->')) + fmt, arg = lhs.split() + if fmt == '%r': + continue + fmt2 = fmt[1:] + with self.subTest(fmt=fmt, arg=arg): + f = F(float(arg)) + self.assertEqual(format(f, fmt2), rhs) + if f: # skip negative zero + self.assertEqual(format(-f, fmt2), '-' + rhs) + f = F(arg) + self.assertEqual(float(format(f, fmt2)), float(rhs)) + self.assertEqual(float(format(-f, fmt2)), float('-' + rhs)) + if __name__ == '__main__': unittest.main() diff --git a/Lib/test/test_frame.py b/Lib/test/test_frame.py index 6bb0144e9b1ed7..7f17666a8d9697 100644 --- a/Lib/test/test_frame.py +++ b/Lib/test/test_frame.py @@ -80,9 +80,11 @@ def g(): gen = g() next(gen) self.assertFalse(endly) - # Clearing the frame closes the generator - gen.gi_frame.clear() - self.assertTrue(endly) + + # Cannot clear a suspended frame + with self.assertRaisesRegex(RuntimeError, r'suspended frame'): + gen.gi_frame.clear() + self.assertFalse(endly) def test_clear_executing(self): # Attempting to clear an executing frame is forbidden. @@ -114,9 +116,10 @@ def g(): gen = g() f = next(gen) self.assertFalse(endly) - # Clearing the frame closes the generator - f.clear() - self.assertTrue(endly) + # Cannot clear a suspended frame + with self.assertRaisesRegex(RuntimeError, 'suspended frame'): + f.clear() + self.assertFalse(endly) def test_lineno_with_tracing(self): def record_line(): @@ -322,7 +325,7 @@ def f(): sneaky_frame_object = None gc.enable() next(g) - # g.gi_frame should be the the frame object from the callback (the + # g.gi_frame should be the frame object from the callback (the # one that was *requested* second, but *created* first): self.assertIs(g.gi_frame, sneaky_frame_object) finally: diff --git a/Lib/test/test_fstring.py b/Lib/test/test_fstring.py index cb14bba2602def..27c7f70cef32e3 100644 --- a/Lib/test/test_fstring.py +++ b/Lib/test/test_fstring.py @@ -8,6 +8,7 @@ # Unicode identifiers in tests is allowed by PEP 3131. import ast +import dis import os import re import types @@ -514,6 +515,54 @@ def test_ast_fstring_empty_format_spec(self): self.assertEqual(type(format_spec), ast.JoinedStr) self.assertEqual(len(format_spec.values), 0) + def test_ast_fstring_format_spec(self): + expr = "f'{1:{name}}'" + + mod = ast.parse(expr) + self.assertEqual(type(mod), ast.Module) + self.assertEqual(len(mod.body), 1) + + fstring = mod.body[0].value + self.assertEqual(type(fstring), ast.JoinedStr) + self.assertEqual(len(fstring.values), 1) + + fv = fstring.values[0] + self.assertEqual(type(fv), ast.FormattedValue) + + format_spec = fv.format_spec + self.assertEqual(type(format_spec), ast.JoinedStr) + self.assertEqual(len(format_spec.values), 1) + + format_spec_value = format_spec.values[0] + self.assertEqual(type(format_spec_value), ast.FormattedValue) + self.assertEqual(format_spec_value.value.id, 'name') + + expr = "f'{1:{name1}{name2}}'" + + mod = ast.parse(expr) + self.assertEqual(type(mod), ast.Module) + self.assertEqual(len(mod.body), 1) + + fstring = mod.body[0].value + self.assertEqual(type(fstring), ast.JoinedStr) + self.assertEqual(len(fstring.values), 1) + + fv = fstring.values[0] + self.assertEqual(type(fv), ast.FormattedValue) + + format_spec = fv.format_spec + self.assertEqual(type(format_spec), ast.JoinedStr) + self.assertEqual(len(format_spec.values), 2) + + format_spec_value = format_spec.values[0] + self.assertEqual(type(format_spec_value), ast.FormattedValue) + self.assertEqual(format_spec_value.value.id, 'name1') + + format_spec_value = format_spec.values[1] + self.assertEqual(type(format_spec_value), ast.FormattedValue) + self.assertEqual(format_spec_value.value.id, 'name2') + + def test_docstring(self): def f(): f'''Not a docstring''' @@ -1027,6 +1076,10 @@ def test_lambda(self): "f'{lambda x:}'", "f'{lambda :}'", ]) + # Ensure the detection of invalid lambdas doesn't trigger detection + # for valid lambdas in the second error pass + with self.assertRaisesRegex(SyntaxError, "invalid syntax"): + compile("lambda name_3=f'{name_4}': {name_3}\n1 $ 1", "", "exec") # but don't emit the paren warning in general cases with self.assertRaisesRegex(SyntaxError, "f-string: expecting a valid expression after '{'"): @@ -1575,6 +1628,9 @@ def __repr__(self): self.assertEqual(f'X{x = }Y', 'Xx = '+repr(x)+'Y') self.assertEqual(f"sadsd {1 + 1 = :{1 + 1:1d}f}", "sadsd 1 + 1 = 2.000000") + self.assertEqual(f"{1+2 = # my comment + }", '1+2 = \n 3') + # These next lines contains tabs. Backslash escapes don't # work in f-strings. # patchcheck doesn't like these tabs. So the only way to test @@ -1673,5 +1729,24 @@ def test_debug_in_file(self): self.assertEqual(stdout.decode('utf-8').strip().replace('\r\n', '\n').replace('\r', '\n'), "3\n=3") + def test_syntax_warning_infinite_recursion_in_file(self): + with temp_cwd(): + script = 'script.py' + with open(script, 'w') as f: + f.write(r"print(f'\{1}')") + + _, stdout, stderr = assert_python_ok(script) + self.assertIn(rb'\1', stdout) + self.assertEqual(len(stderr.strip().splitlines()), 2) + + def test_fstring_without_formatting_bytecode(self): + # f-string without any formatting should emit the same bytecode + # as a normal string. See gh-99606. + def get_code(s): + return [(i.opname, i.oparg) for i in dis.get_instructions(s)] + + for s in ["", "some string"]: + self.assertEqual(get_code(f"'{s}'"), get_code(f"f'{s}'")) + if __name__ == '__main__': unittest.main() diff --git a/Lib/test/test_ftplib.py b/Lib/test/test_ftplib.py index 544228e3bab47b..2f191ea7a44c16 100644 --- a/Lib/test/test_ftplib.py +++ b/Lib/test/test_ftplib.py @@ -32,7 +32,7 @@ DEFAULT_ENCODING = 'utf-8' # the dummy data returned by server over the data channel when # RETR, LIST, NLST, MLSD commands are issued -RETR_DATA = 'abcde12345\r\n' * 1000 + 'non-ascii char \xAE\r\n' +RETR_DATA = 'abcde\xB9\xB2\xB3\xA4\xA6\r\n' * 1000 LIST_DATA = 'foo\r\nbar\r\n non-ascii char \xAE\r\n' NLST_DATA = 'foo\r\nbar\r\n non-ascii char \xAE\r\n' MLSD_DATA = ("type=cdir;perm=el;unique==keVO1+ZF4; test\r\n" @@ -67,11 +67,11 @@ class DummyDTPHandler(asynchat.async_chat): def __init__(self, conn, baseclass): asynchat.async_chat.__init__(self, conn) self.baseclass = baseclass - self.baseclass.last_received_data = '' + self.baseclass.last_received_data = bytearray() self.encoding = baseclass.encoding def handle_read(self): - new_data = self.recv(1024).decode(self.encoding, 'replace') + new_data = self.recv(1024) self.baseclass.last_received_data += new_data def handle_close(self): @@ -107,7 +107,7 @@ def __init__(self, conn, encoding=DEFAULT_ENCODING): self.in_buffer = [] self.dtp = None self.last_received_cmd = None - self.last_received_data = '' + self.last_received_data = bytearray() self.next_response = '' self.next_data = None self.rest = None @@ -325,8 +325,8 @@ def handle_error(self): if ssl is not None: - CERTFILE = os.path.join(os.path.dirname(__file__), "keycert3.pem") - CAFILE = os.path.join(os.path.dirname(__file__), "pycacert.pem") + CERTFILE = os.path.join(os.path.dirname(__file__), "certdata", "keycert3.pem") + CAFILE = os.path.join(os.path.dirname(__file__), "certdata", "pycacert.pem") class SSLConnection(asyncore.dispatcher): """An asyncore.dispatcher subclass supporting TLS/SSL.""" @@ -590,19 +590,17 @@ def test_abort(self): self.client.abort() def test_retrbinary(self): - def callback(data): - received.append(data.decode(self.client.encoding)) received = [] - self.client.retrbinary('retr', callback) - self.check_data(''.join(received), RETR_DATA) + self.client.retrbinary('retr', received.append) + self.check_data(b''.join(received), + RETR_DATA.encode(self.client.encoding)) def test_retrbinary_rest(self): - def callback(data): - received.append(data.decode(self.client.encoding)) for rest in (0, 10, 20): received = [] - self.client.retrbinary('retr', callback, rest=rest) - self.check_data(''.join(received), RETR_DATA[rest:]) + self.client.retrbinary('retr', received.append, rest=rest) + self.check_data(b''.join(received), + RETR_DATA[rest:].encode(self.client.encoding)) def test_retrlines(self): received = [] @@ -612,7 +610,8 @@ def test_retrlines(self): def test_storbinary(self): f = io.BytesIO(RETR_DATA.encode(self.client.encoding)) self.client.storbinary('stor', f) - self.check_data(self.server.handler_instance.last_received_data, RETR_DATA) + self.check_data(self.server.handler_instance.last_received_data, + RETR_DATA.encode(self.server.encoding)) # test new callback arg flag = [] f.seek(0) @@ -631,7 +630,8 @@ def test_storlines(self): data = RETR_DATA.replace('\r\n', '\n').encode(self.client.encoding) f = io.BytesIO(data) self.client.storlines('stor', f) - self.check_data(self.server.handler_instance.last_received_data, RETR_DATA) + self.check_data(self.server.handler_instance.last_received_data, + RETR_DATA.encode(self.server.encoding)) # test new callback arg flag = [] f.seek(0) @@ -649,7 +649,7 @@ def test_nlst(self): def test_dir(self): l = [] - self.client.dir(lambda x: l.append(x)) + self.client.dir(l.append) self.assertEqual(''.join(l), LIST_DATA.replace('\r\n', '')) def test_mlsd(self): @@ -889,12 +889,10 @@ def test_makepasv(self): def test_transfer(self): def retr(): - def callback(data): - received.append(data.decode(self.client.encoding)) received = [] - self.client.retrbinary('retr', callback) - self.assertEqual(len(''.join(received)), len(RETR_DATA)) - self.assertEqual(''.join(received), RETR_DATA) + self.client.retrbinary('retr', received.append) + self.assertEqual(b''.join(received), + RETR_DATA.encode(self.client.encoding)) self.client.set_pasv(True) retr() self.client.set_pasv(False) diff --git a/Lib/test/test_funcattrs.py b/Lib/test/test_funcattrs.py index e08d72877d8aef..b3fc5ad42e7fde 100644 --- a/Lib/test/test_funcattrs.py +++ b/Lib/test/test_funcattrs.py @@ -2,6 +2,7 @@ import types import typing import unittest +import warnings def global_function(): @@ -70,6 +71,27 @@ def test(): pass test.__code__ = self.b.__code__ self.assertEqual(test(), 3) # self.b always returns 3, arbitrarily + def test_invalid___code___assignment(self): + def A(): pass + def B(): yield + async def C(): yield + async def D(x): await x + + for src in [A, B, C, D]: + for dst in [A, B, C, D]: + if src == dst: + continue + + assert src.__code__.co_flags != dst.__code__.co_flags + prev = dst.__code__ + try: + with self.assertWarnsRegex(DeprecationWarning, 'code object of non-matching type'): + dst.__code__ = src.__code__ + finally: + with warnings.catch_warnings(): + warnings.filterwarnings('ignore', '', DeprecationWarning) + dst.__code__ = prev + def test___globals__(self): self.assertIs(self.b.__globals__, globals()) self.cannot_set_attr(self.b, '__globals__', 2, @@ -194,16 +216,19 @@ def test___qualname__(self): def test___type_params__(self): def generic[T](): pass def not_generic(): pass + lambda_ = lambda: ... T, = generic.__type_params__ self.assertIsInstance(T, typing.TypeVar) self.assertEqual(generic.__type_params__, (T,)) - self.assertEqual(not_generic.__type_params__, ()) - with self.assertRaises(TypeError): - del not_generic.__type_params__ - with self.assertRaises(TypeError): - not_generic.__type_params__ = 42 - not_generic.__type_params__ = (T,) - self.assertEqual(not_generic.__type_params__, (T,)) + for func in (not_generic, lambda_): + with self.subTest(func=func): + self.assertEqual(func.__type_params__, ()) + with self.assertRaises(TypeError): + del func.__type_params__ + with self.assertRaises(TypeError): + func.__type_params__ = 42 + func.__type_params__ = (T,) + self.assertEqual(func.__type_params__, (T,)) def test___code__(self): num_one, num_two = 7, 8 diff --git a/Lib/test/test_functools.py b/Lib/test/test_functools.py index c4eca0f5b79511..0ef45d3c670e85 100644 --- a/Lib/test/test_functools.py +++ b/Lib/test/test_functools.py @@ -26,10 +26,16 @@ py_functools = import_helper.import_fresh_module('functools', blocked=['_functools']) -c_functools = import_helper.import_fresh_module('functools') +c_functools = import_helper.import_fresh_module('functools', + fresh=['_functools']) decimal = import_helper.import_fresh_module('decimal', fresh=['_decimal']) +_partial_types = [py_functools.partial] +if c_functools: + _partial_types.append(c_functools.partial) + + @contextlib.contextmanager def replaced_module(name, replacement): original_module = sys.modules[name] @@ -201,7 +207,7 @@ def test_repr(self): kwargs = {'a': object(), 'b': object()} kwargs_reprs = ['a={a!r}, b={b!r}'.format_map(kwargs), 'b={b!r}, a={a!r}'.format_map(kwargs)] - if self.partial in (c_functools.partial, py_functools.partial): + if self.partial in _partial_types: name = 'functools.partial' else: name = self.partial.__name__ @@ -223,7 +229,7 @@ def test_repr(self): for kwargs_repr in kwargs_reprs]) def test_recursive_repr(self): - if self.partial in (c_functools.partial, py_functools.partial): + if self.partial in _partial_types: name = 'functools.partial' else: name = self.partial.__name__ @@ -250,7 +256,7 @@ def test_recursive_repr(self): f.__setstate__((capture, (), {}, {})) def test_pickle(self): - with self.AllowPickle(): + with replaced_module('functools', self.module): f = self.partial(signature, ['asdf'], bar=[True]) f.attr = [] for proto in range(pickle.HIGHEST_PROTOCOL + 1): @@ -333,7 +339,7 @@ def test_setstate_subclasses(self): self.assertIs(type(r[0]), tuple) def test_recursive_pickle(self): - with self.AllowPickle(): + with replaced_module('functools', self.module): f = self.partial(capture) f.__setstate__((f, (), {}, {})) try: @@ -387,14 +393,9 @@ def __getitem__(self, key): @unittest.skipUnless(c_functools, 'requires the C _functools module') class TestPartialC(TestPartial, unittest.TestCase): if c_functools: + module = c_functools partial = c_functools.partial - class AllowPickle: - def __enter__(self): - return self - def __exit__(self, type, value, tb): - return False - def test_attributes_unwritable(self): # attributes should not be writable p = self.partial(capture, 1, 2, a=10, b=20) @@ -437,15 +438,9 @@ def __str__(self): class TestPartialPy(TestPartial, unittest.TestCase): + module = py_functools partial = py_functools.partial - class AllowPickle: - def __init__(self): - self._cm = replaced_module("functools", py_functools) - def __enter__(self): - return self._cm.__enter__() - def __exit__(self, type, value, tb): - return self._cm.__exit__(type, value, tb) if c_functools: class CPartialSubclass(c_functools.partial): @@ -944,6 +939,8 @@ def mycmp(x, y): self.assertRaises(TypeError, hash, k) self.assertNotIsInstance(k, collections.abc.Hashable) + @unittest.skipIf(support.MISSING_C_DOCSTRINGS, + "Signature information for builtins requires docstrings") def test_cmp_to_signature(self): self.assertEqual(str(Signature.from_callable(self.cmp_to_key)), '(mycmp)') @@ -1867,14 +1864,29 @@ def orig(): ... self.assertEqual(str(Signature.from_callable(lru.cache_info)), '()') self.assertEqual(str(Signature.from_callable(lru.cache_clear)), '()') + @support.skip_on_s390x + @unittest.skipIf(support.is_wasi, "WASI has limited C stack") + def test_lru_recursion(self): + + @self.module.lru_cache + def fib(n): + if n <= 1: + return n + return fib(n-1) + fib(n-2) + + if not support.Py_DEBUG: + with support.infinite_recursion(): + fib(2500) + @py_functools.lru_cache() def py_cached_func(x, y): return 3 * x + y -@c_functools.lru_cache() -def c_cached_func(x, y): - return 3 * x + y +if c_functools: + @c_functools.lru_cache() + def c_cached_func(x, y): + return 3 * x + y class TestLRUPy(TestLRU, unittest.TestCase): @@ -1891,18 +1903,20 @@ def cached_staticmeth(x, y): return 3 * x + y +@unittest.skipUnless(c_functools, 'requires the C _functools module') class TestLRUC(TestLRU, unittest.TestCase): - module = c_functools - cached_func = c_cached_func, + if c_functools: + module = c_functools + cached_func = c_cached_func, - @module.lru_cache() - def cached_meth(self, x, y): - return 3 * x + y + @module.lru_cache() + def cached_meth(self, x, y): + return 3 * x + y - @staticmethod - @module.lru_cache() - def cached_staticmeth(x, y): - return 3 * x + y + @staticmethod + @module.lru_cache() + def cached_staticmeth(x, y): + return 3 * x + y class TestSingleDispatch(unittest.TestCase): @@ -2474,6 +2488,74 @@ def _(arg): self.assertTrue(A.t('')) self.assertEqual(A.t(0.0), 0.0) + def test_slotted_class(self): + class Slot: + __slots__ = ('a', 'b') + @functools.singledispatchmethod + def go(self, item, arg): + pass + + @go.register + def _(self, item: int, arg): + return item + arg + + s = Slot() + self.assertEqual(s.go(1, 1), 2) + + def test_classmethod_slotted_class(self): + class Slot: + __slots__ = ('a', 'b') + @functools.singledispatchmethod + @classmethod + def go(cls, item, arg): + pass + + @go.register + @classmethod + def _(cls, item: int, arg): + return item + arg + + s = Slot() + self.assertEqual(s.go(1, 1), 2) + self.assertEqual(Slot.go(1, 1), 2) + + def test_staticmethod_slotted_class(self): + class A: + __slots__ = ['a'] + @functools.singledispatchmethod + @staticmethod + def t(arg): + return arg + @t.register(int) + @staticmethod + def _(arg): + return isinstance(arg, int) + @t.register(str) + @staticmethod + def _(arg): + return isinstance(arg, str) + a = A() + + self.assertTrue(A.t(0)) + self.assertTrue(A.t('')) + self.assertEqual(A.t(0.0), 0.0) + self.assertTrue(a.t(0)) + self.assertTrue(a.t('')) + self.assertEqual(a.t(0.0), 0.0) + + def test_assignment_behavior(self): + # see gh-106448 + class A: + @functools.singledispatchmethod + def t(arg): + return arg + + a = A() + a.t.foo = 'bar' + a2 = A() + with self.assertRaises(AttributeError): + a2.t.foo + def test_classmethod_register(self): class A: def __init__(self, arg): @@ -3037,6 +3119,9 @@ def test_access_from_class(self): def test_doc(self): self.assertEqual(CachedCostItem.cost.__doc__, "The cost of the item.") + def test_module(self): + self.assertEqual(CachedCostItem.cost.__module__, CachedCostItem.__module__) + def test_subclass_with___set__(self): """Caching still works for a subclass defining __set__.""" class readonly_cached_property(py_functools.cached_property): diff --git a/Lib/test/test_future.py b/Lib/test/test_future.py deleted file mode 100644 index 4730bfafbd9cfe..00000000000000 --- a/Lib/test/test_future.py +++ /dev/null @@ -1,450 +0,0 @@ -# Test various flavors of legal and illegal future statements - -import __future__ -import ast -import unittest -from test.support import import_helper -from test.support.script_helper import spawn_python, kill_python -from textwrap import dedent -import os -import re -import sys - -rx = re.compile(r'\((\S+).py, line (\d+)') - -def get_error_location(msg): - mo = rx.search(str(msg)) - return mo.group(1, 2) - -class FutureTest(unittest.TestCase): - - def check_syntax_error(self, err, basename, lineno, offset=1): - self.assertIn('%s.py, line %d' % (basename, lineno), str(err)) - self.assertEqual(os.path.basename(err.filename), basename + '.py') - self.assertEqual(err.lineno, lineno) - self.assertEqual(err.offset, offset) - - def test_future1(self): - with import_helper.CleanImport('future_test1'): - from test import future_test1 - self.assertEqual(future_test1.result, 6) - - def test_future2(self): - with import_helper.CleanImport('future_test2'): - from test import future_test2 - self.assertEqual(future_test2.result, 6) - - def test_future3(self): - with import_helper.CleanImport('test_future3'): - from test import test_future3 - - def test_badfuture3(self): - with self.assertRaises(SyntaxError) as cm: - from test import badsyntax_future3 - self.check_syntax_error(cm.exception, "badsyntax_future3", 3) - - def test_badfuture4(self): - with self.assertRaises(SyntaxError) as cm: - from test import badsyntax_future4 - self.check_syntax_error(cm.exception, "badsyntax_future4", 3) - - def test_badfuture5(self): - with self.assertRaises(SyntaxError) as cm: - from test import badsyntax_future5 - self.check_syntax_error(cm.exception, "badsyntax_future5", 4) - - def test_badfuture6(self): - with self.assertRaises(SyntaxError) as cm: - from test import badsyntax_future6 - self.check_syntax_error(cm.exception, "badsyntax_future6", 3) - - def test_badfuture7(self): - with self.assertRaises(SyntaxError) as cm: - from test import badsyntax_future7 - self.check_syntax_error(cm.exception, "badsyntax_future7", 3, 54) - - def test_badfuture8(self): - with self.assertRaises(SyntaxError) as cm: - from test import badsyntax_future8 - self.check_syntax_error(cm.exception, "badsyntax_future8", 3) - - def test_badfuture9(self): - with self.assertRaises(SyntaxError) as cm: - from test import badsyntax_future9 - self.check_syntax_error(cm.exception, "badsyntax_future9", 3) - - def test_badfuture10(self): - with self.assertRaises(SyntaxError) as cm: - from test import badsyntax_future10 - self.check_syntax_error(cm.exception, "badsyntax_future10", 3) - - def test_ensure_flags_dont_clash(self): - # bpo-39562: test that future flags and compiler flags doesn't clash - - # obtain future flags (CO_FUTURE_***) from the __future__ module - flags = { - f"CO_FUTURE_{future.upper()}": getattr(__future__, future).compiler_flag - for future in __future__.all_feature_names - } - # obtain some of the exported compiler flags (PyCF_***) from the ast module - flags |= { - flag: getattr(ast, flag) - for flag in dir(ast) if flag.startswith("PyCF_") - } - self.assertCountEqual(set(flags.values()), flags.values()) - - def test_parserhack(self): - # test that the parser.c::future_hack function works as expected - # Note: although this test must pass, it's not testing the original - # bug as of 2.6 since the with statement is not optional and - # the parser hack disabled. If a new keyword is introduced in - # 2.6, change this to refer to the new future import. - try: - exec("from __future__ import print_function; print 0") - except SyntaxError: - pass - else: - self.fail("syntax error didn't occur") - - try: - exec("from __future__ import (print_function); print 0") - except SyntaxError: - pass - else: - self.fail("syntax error didn't occur") - - def test_multiple_features(self): - with import_helper.CleanImport("test.test_future5"): - from test import test_future5 - - def test_unicode_literals_exec(self): - scope = {} - exec("from __future__ import unicode_literals; x = ''", {}, scope) - self.assertIsInstance(scope["x"], str) - - def test_syntactical_future_repl(self): - p = spawn_python('-i') - p.stdin.write(b"from __future__ import barry_as_FLUFL\n") - p.stdin.write(b"2 <> 3\n") - out = kill_python(p) - self.assertNotIn(b'SyntaxError: invalid syntax', out) - -class AnnotationsFutureTestCase(unittest.TestCase): - template = dedent( - """ - from __future__ import annotations - def f() -> {ann}: - ... - def g(arg: {ann}) -> None: - ... - async def f2() -> {ann}: - ... - async def g2(arg: {ann}) -> None: - ... - class H: - var: {ann} - object.attr: {ann} - var: {ann} - var2: {ann} = None - object.attr: {ann} - """ - ) - - def getActual(self, annotation): - scope = {} - exec(self.template.format(ann=annotation), {}, scope) - func_ret_ann = scope['f'].__annotations__['return'] - func_arg_ann = scope['g'].__annotations__['arg'] - async_func_ret_ann = scope['f2'].__annotations__['return'] - async_func_arg_ann = scope['g2'].__annotations__['arg'] - var_ann1 = scope['__annotations__']['var'] - var_ann2 = scope['__annotations__']['var2'] - self.assertEqual(func_ret_ann, func_arg_ann) - self.assertEqual(func_ret_ann, async_func_ret_ann) - self.assertEqual(func_ret_ann, async_func_arg_ann) - self.assertEqual(func_ret_ann, var_ann1) - self.assertEqual(func_ret_ann, var_ann2) - return func_ret_ann - - def assertAnnotationEqual( - self, annotation, expected=None, drop_parens=False, is_tuple=False, - ): - actual = self.getActual(annotation) - if expected is None: - expected = annotation if not is_tuple else annotation[1:-1] - if drop_parens: - self.assertNotEqual(actual, expected) - actual = actual.replace("(", "").replace(")", "") - - self.assertEqual(actual, expected) - - def _exec_future(self, code): - scope = {} - exec( - "from __future__ import annotations\n" - + code, scope - ) - return scope - - def test_annotations(self): - eq = self.assertAnnotationEqual - eq('...') - eq("'some_string'") - eq("u'some_string'") - eq("b'\\xa3'") - eq('Name') - eq('None') - eq('True') - eq('False') - eq('1') - eq('1.0') - eq('1j') - eq('True or False') - eq('True or False or None') - eq('True and False') - eq('True and False and None') - eq('Name1 and Name2 or Name3') - eq('Name1 and (Name2 or Name3)') - eq('Name1 or Name2 and Name3') - eq('(Name1 or Name2) and Name3') - eq('Name1 and Name2 or Name3 and Name4') - eq('Name1 or Name2 and Name3 or Name4') - eq('a + b + (c + d)') - eq('a * b * (c * d)') - eq('(a ** b) ** c ** d') - eq('v1 << 2') - eq('1 >> v2') - eq('1 % finished') - eq('1 + v2 - v3 * 4 ^ 5 ** v6 / 7 // 8') - eq('not great') - eq('not not great') - eq('~great') - eq('+value') - eq('++value') - eq('-1') - eq('~int and not v1 ^ 123 + v2 | True') - eq('a + (not b)') - eq('lambda: None') - eq('lambda arg: None') - eq('lambda a=True: a') - eq('lambda a, b, c=True: a') - eq("lambda a, b, c=True, *, d=1 << v2, e='str': a") - eq("lambda a, b, c=True, *vararg, d, e='str', **kwargs: a + b") - eq("lambda a, /, b, c=True, *vararg, d, e='str', **kwargs: a + b") - eq('lambda x, /: x') - eq('lambda x=1, /: x') - eq('lambda x, /, y: x + y') - eq('lambda x=1, /, y=2: x + y') - eq('lambda x, /, y=1: x + y') - eq('lambda x, /, y=1, *, z=3: x + y + z') - eq('lambda x=1, /, y=2, *, z=3: x + y + z') - eq('lambda x=1, /, y=2, *, z: x + y + z') - eq('lambda x=1, y=2, z=3, /, w=4, *, l, l2: x + y + z + w + l + l2') - eq('lambda x=1, y=2, z=3, /, w=4, *, l, l2, **kwargs: x + y + z + w + l + l2') - eq('lambda x, /, y=1, *, z: x + y + z') - eq('lambda x: lambda y: x + y') - eq('1 if True else 2') - eq('str or None if int or True else str or bytes or None') - eq('str or None if (1 if True else 2) else str or bytes or None') - eq("0 if not x else 1 if x > 0 else -1") - eq("(1 if x > 0 else -1) if x else 0") - eq("{'2.7': dead, '3.7': long_live or die_hard}") - eq("{'2.7': dead, '3.7': long_live or die_hard, **{'3.6': verygood}}") - eq("{**a, **b, **c}") - eq("{'2.7', '3.6', '3.7', '3.8', '3.9', '4.0' if gilectomy else '3.10'}") - eq("{*a, *b, *c}") - eq("({'a': 'b'}, True or False, +value, 'string', b'bytes') or None") - eq("()") - eq("(a,)") - eq("(a, b)") - eq("(a, b, c)") - eq("(*a, *b, *c)") - eq("[]") - eq("[1, 2, 3, 4, 5, 6, 7, 8, 9, 10 or A, 11 or B, 12 or C]") - eq("[*a, *b, *c]") - eq("{i for i in (1, 2, 3)}") - eq("{i ** 2 for i in (1, 2, 3)}") - eq("{i ** 2 for i, _ in ((1, 'a'), (2, 'b'), (3, 'c'))}") - eq("{i ** 2 + j for i in (1, 2, 3) for j in (1, 2, 3)}") - eq("[i for i in (1, 2, 3)]") - eq("[i ** 2 for i in (1, 2, 3)]") - eq("[i ** 2 for i, _ in ((1, 'a'), (2, 'b'), (3, 'c'))]") - eq("[i ** 2 + j for i in (1, 2, 3) for j in (1, 2, 3)]") - eq("(i for i in (1, 2, 3))") - eq("(i ** 2 for i in (1, 2, 3))") - eq("(i ** 2 for i, _ in ((1, 'a'), (2, 'b'), (3, 'c')))") - eq("(i ** 2 + j for i in (1, 2, 3) for j in (1, 2, 3))") - eq("{i: 0 for i in (1, 2, 3)}") - eq("{i: j for i, j in ((1, 'a'), (2, 'b'), (3, 'c'))}") - eq("[(x, y) for x, y in (a, b)]") - eq("[(x,) for x, in (a,)]") - eq("Python3 > Python2 > COBOL") - eq("Life is Life") - eq("call()") - eq("call(arg)") - eq("call(kwarg='hey')") - eq("call(arg, kwarg='hey')") - eq("call(arg, *args, another, kwarg='hey')") - eq("call(arg, another, kwarg='hey', **kwargs, kwarg2='ho')") - eq("lukasz.langa.pl") - eq("call.me(maybe)") - eq("1 .real") - eq("1.0.real") - eq("....__class__") - eq("list[str]") - eq("dict[str, int]") - eq("set[str,]") - eq("tuple[()]") - eq("tuple[str, ...]") - eq("tuple[str, *types]") - eq("tuple[str, int, (str, int)]") - eq("tuple[*int, str, str, (str, int)]") - eq("tuple[str, int, float, dict[str, int]]") - eq("slice[0]") - eq("slice[0:1]") - eq("slice[0:1:2]") - eq("slice[:]") - eq("slice[:-1]") - eq("slice[1:]") - eq("slice[::-1]") - eq("slice[:,]") - eq("slice[1:2,]") - eq("slice[1:2:3,]") - eq("slice[1:2, 1]") - eq("slice[1:2, 2, 3]") - eq("slice[()]") - # Note that `slice[*Ts]`, `slice[*Ts,]`, and `slice[(*Ts,)]` all have - # the same AST, but only `slice[*Ts,]` passes this test, because that's - # what the unparser produces. - eq("slice[*Ts,]") - eq("slice[1, *Ts]") - eq("slice[*Ts, 2]") - eq("slice[1, *Ts, 2]") - eq("slice[*Ts, *Ts]") - eq("slice[1, *Ts, *Ts]") - eq("slice[*Ts, 1, *Ts]") - eq("slice[*Ts, *Ts, 1]") - eq("slice[1, *Ts, *Ts, 2]") - eq("slice[1:2, *Ts]") - eq("slice[*Ts, 1:2]") - eq("slice[1:2, *Ts, 3:4]") - eq("slice[a, b:c, d:e:f]") - eq("slice[(x for x in a)]") - eq('str or None if sys.version_info[0] > (3,) else str or bytes or None') - eq("f'f-string without formatted values is just a string'") - eq("f'{{NOT a formatted value}}'") - eq("f'some f-string with {a} {few():.2f} {formatted.values!r}'") - eq('''f"{f'{nested} inner'} outer"''') - eq("f'space between opening braces: { {a for a in (1, 2, 3)}}'") - eq("f'{(lambda x: x)}'") - eq("f'{(None if a else lambda x: x)}'") - eq("f'{x}'") - eq("f'{x!r}'") - eq("f'{x!a}'") - eq('[x for x in (a if b else c)]') - eq('[x for x in a if (b if c else d)]') - eq('f(x for x in a)') - eq('f(1, (x for x in a))') - eq('f((x for x in a), 2)') - eq('(((a)))', 'a') - eq('(((a, b)))', '(a, b)') - eq("1 + 2 + 3") - - def test_fstring_debug_annotations(self): - # f-strings with '=' don't round trip very well, so set the expected - # result explicitly. - self.assertAnnotationEqual("f'{x=!r}'", expected="f'x={x!r}'") - self.assertAnnotationEqual("f'{x=:}'", expected="f'x={x:}'") - self.assertAnnotationEqual("f'{x=:.2f}'", expected="f'x={x:.2f}'") - self.assertAnnotationEqual("f'{x=!r}'", expected="f'x={x!r}'") - self.assertAnnotationEqual("f'{x=!a}'", expected="f'x={x!a}'") - self.assertAnnotationEqual("f'{x=!s:*^20}'", expected="f'x={x!s:*^20}'") - - def test_infinity_numbers(self): - inf = "1e" + repr(sys.float_info.max_10_exp + 1) - infj = f"{inf}j" - self.assertAnnotationEqual("1e1000", expected=inf) - self.assertAnnotationEqual("1e1000j", expected=infj) - self.assertAnnotationEqual("-1e1000", expected=f"-{inf}") - self.assertAnnotationEqual("3+1e1000j", expected=f"3 + {infj}") - self.assertAnnotationEqual("(1e1000, 1e1000j)", expected=f"({inf}, {infj})") - self.assertAnnotationEqual("'inf'") - self.assertAnnotationEqual("('inf', 1e1000, 'infxxx', 1e1000j)", expected=f"('inf', {inf}, 'infxxx', {infj})") - self.assertAnnotationEqual("(1e1000, (1e1000j,))", expected=f"({inf}, ({infj},))") - - def test_annotation_with_complex_target(self): - with self.assertRaises(SyntaxError): - exec( - "from __future__ import annotations\n" - "object.__debug__: int" - ) - - def test_annotations_symbol_table_pass(self): - namespace = self._exec_future(dedent(""" - from __future__ import annotations - - def foo(): - outer = 1 - def bar(): - inner: outer = 1 - return bar - """)) - - foo = namespace.pop("foo") - self.assertIsNone(foo().__closure__) - self.assertEqual(foo.__code__.co_cellvars, ()) - self.assertEqual(foo().__code__.co_freevars, ()) - - def test_annotations_forbidden(self): - with self.assertRaises(SyntaxError): - self._exec_future("test: (yield)") - - with self.assertRaises(SyntaxError): - self._exec_future("test.test: (yield a + b)") - - with self.assertRaises(SyntaxError): - self._exec_future("test[something]: (yield from x)") - - with self.assertRaises(SyntaxError): - self._exec_future("def func(test: (yield from outside_of_generator)): pass") - - with self.assertRaises(SyntaxError): - self._exec_future("def test() -> (await y): pass") - - with self.assertRaises(SyntaxError): - self._exec_future("async def test() -> something((a := b)): pass") - - with self.assertRaises(SyntaxError): - self._exec_future("test: await some.complicated[0].call(with_args=True or 1 is not 1)") - - with self.assertRaises(SyntaxError): - self._exec_future("test: f'{(x := 10):=10}'") - - with self.assertRaises(SyntaxError): - self._exec_future(dedent("""\ - def foo(): - def bar(arg: (yield)): pass - """)) - - def test_get_type_hints_on_func_with_variadic_arg(self): - # `typing.get_type_hints` might break on a function with a variadic - # annotation (e.g. `f(*args: *Ts)`) if `from __future__ import - # annotations`, because it could try to evaluate `*Ts` as an expression, - # which on its own isn't value syntax. - namespace = self._exec_future(dedent("""\ - class StarredC: pass - class C: - def __iter__(self): - yield StarredC() - c = C() - def f(*args: *c): pass - import typing - hints = typing.get_type_hints(f) - """)) - - hints = namespace.pop('hints') - self.assertIsInstance(hints['args'], namespace['StarredC']) - - -if __name__ == "__main__": - unittest.main() diff --git a/Lib/test/test_future_stmt/__init__.py b/Lib/test/test_future_stmt/__init__.py new file mode 100644 index 00000000000000..f2a39a3fe29c7f --- /dev/null +++ b/Lib/test/test_future_stmt/__init__.py @@ -0,0 +1,6 @@ +import os +from test import support + + +def load_tests(*args): + return support.load_package_tests(os.path.dirname(__file__), *args) diff --git a/Lib/test/badsyntax_future10.py b/Lib/test/test_future_stmt/badsyntax_future.py similarity index 100% rename from Lib/test/badsyntax_future10.py rename to Lib/test/test_future_stmt/badsyntax_future.py diff --git a/Lib/test/future_test1.py b/Lib/test/test_future_stmt/import_nested_scope_twice.py similarity index 100% rename from Lib/test/future_test1.py rename to Lib/test/test_future_stmt/import_nested_scope_twice.py diff --git a/Lib/test/future_test2.py b/Lib/test/test_future_stmt/nested_scope.py similarity index 100% rename from Lib/test/future_test2.py rename to Lib/test/test_future_stmt/nested_scope.py diff --git a/Lib/test/test_future_stmt/test_future.py b/Lib/test/test_future_stmt/test_future.py new file mode 100644 index 00000000000000..2c8ceb664cb362 --- /dev/null +++ b/Lib/test/test_future_stmt/test_future.py @@ -0,0 +1,524 @@ +# Test various flavors of legal and illegal future statements + +import __future__ +import ast +import unittest +from test.support import import_helper +from test.support.script_helper import spawn_python, kill_python +from textwrap import dedent +import os +import re +import sys + +TOP_LEVEL_MSG = 'from __future__ imports must occur at the beginning of the file' + +rx = re.compile(r'\((\S+).py, line (\d+)') + +def get_error_location(msg): + mo = rx.search(str(msg)) + return mo.group(1, 2) + +class FutureTest(unittest.TestCase): + + def check_syntax_error(self, err, basename, + *, + lineno, + message=TOP_LEVEL_MSG, offset=1): + if basename != '': + basename += '.py' + + self.assertEqual(f'{message} ({basename}, line {lineno})', str(err)) + self.assertEqual(os.path.basename(err.filename), basename) + self.assertEqual(err.lineno, lineno) + self.assertEqual(err.offset, offset) + + def assertSyntaxError(self, code, + *, + lineno=1, + message=TOP_LEVEL_MSG, offset=1, + parametrize_docstring=True): + code = dedent(code.lstrip('\n')) + for add_docstring in ([False, True] if parametrize_docstring else [False]): + with self.subTest(code=code, add_docstring=add_docstring): + if add_docstring: + code = '"""Docstring"""\n' + code + lineno += 1 + with self.assertRaises(SyntaxError) as cm: + exec(code) + self.check_syntax_error(cm.exception, "", + lineno=lineno, + message=message, + offset=offset) + + def test_import_nested_scope_twice(self): + # Import the name nested_scopes twice to trigger SF bug #407394 + with import_helper.CleanImport( + 'test.test_future_stmt.import_nested_scope_twice', + ): + from test.test_future_stmt import import_nested_scope_twice + self.assertEqual(import_nested_scope_twice.result, 6) + + def test_nested_scope(self): + with import_helper.CleanImport('test.test_future_stmt.nested_scope'): + from test.test_future_stmt import nested_scope + self.assertEqual(nested_scope.result, 6) + + def test_future_single_import(self): + with import_helper.CleanImport( + 'test.test_future_stmt.test_future_single_import', + ): + from test.test_future_stmt import test_future_single_import + + def test_future_multiple_imports(self): + with import_helper.CleanImport( + 'test.test_future_stmt.test_future_multiple_imports', + ): + from test.test_future_stmt import test_future_multiple_imports + + def test_future_multiple_features(self): + with import_helper.CleanImport( + "test.test_future_stmt.test_future_multiple_features", + ): + from test.test_future_stmt import test_future_multiple_features + + def test_unknown_future_flag(self): + code = """ + from __future__ import nested_scopes + from __future__ import rested_snopes # typo error here: nested => rested + """ + self.assertSyntaxError( + code, lineno=2, + message='future feature rested_snopes is not defined', + ) + + def test_future_import_not_on_top(self): + code = """ + import some_module + from __future__ import annotations + """ + self.assertSyntaxError(code, lineno=2) + + code = """ + import __future__ + from __future__ import annotations + """ + self.assertSyntaxError(code, lineno=2) + + code = """ + from __future__ import absolute_import + "spam, bar, blah" + from __future__ import print_function + """ + self.assertSyntaxError(code, lineno=3) + + def test_future_import_with_extra_string(self): + code = """ + '''Docstring''' + "this isn't a doc string" + from __future__ import nested_scopes + """ + self.assertSyntaxError(code, lineno=3, parametrize_docstring=False) + + def test_multiple_import_statements_on_same_line(self): + # With `\`: + code = """ + from __future__ import nested_scopes; import string; from __future__ import \ + nested_scopes + """ + self.assertSyntaxError(code, offset=54) + + # Without `\`: + code = """ + from __future__ import nested_scopes; import string; from __future__ import nested_scopes + """ + self.assertSyntaxError(code, offset=54) + + def test_future_import_star(self): + code = """ + from __future__ import * + """ + self.assertSyntaxError(code, message='future feature * is not defined') + + def test_future_import_braces(self): + code = """ + from __future__ import braces + """ + # Congrats, you found an easter egg! + self.assertSyntaxError(code, message='not a chance') + + code = """ + from __future__ import nested_scopes, braces + """ + self.assertSyntaxError(code, message='not a chance') + + def test_module_with_future_import_not_on_top(self): + with self.assertRaises(SyntaxError) as cm: + from test.test_future_stmt import badsyntax_future + self.check_syntax_error(cm.exception, "badsyntax_future", lineno=3) + + def test_ensure_flags_dont_clash(self): + # bpo-39562: test that future flags and compiler flags doesn't clash + + # obtain future flags (CO_FUTURE_***) from the __future__ module + flags = { + f"CO_FUTURE_{future.upper()}": getattr(__future__, future).compiler_flag + for future in __future__.all_feature_names + } + # obtain some of the exported compiler flags (PyCF_***) from the ast module + flags |= { + flag: getattr(ast, flag) + for flag in dir(ast) if flag.startswith("PyCF_") + } + self.assertCountEqual(set(flags.values()), flags.values()) + + def test_parserhack(self): + # test that the parser.c::future_hack function works as expected + # Note: although this test must pass, it's not testing the original + # bug as of 2.6 since the with statement is not optional and + # the parser hack disabled. If a new keyword is introduced in + # 2.6, change this to refer to the new future import. + try: + exec("from __future__ import print_function; print 0") + except SyntaxError: + pass + else: + self.fail("syntax error didn't occur") + + try: + exec("from __future__ import (print_function); print 0") + except SyntaxError: + pass + else: + self.fail("syntax error didn't occur") + + def test_unicode_literals_exec(self): + scope = {} + exec("from __future__ import unicode_literals; x = ''", {}, scope) + self.assertIsInstance(scope["x"], str) + + def test_syntactical_future_repl(self): + p = spawn_python('-i') + p.stdin.write(b"from __future__ import barry_as_FLUFL\n") + p.stdin.write(b"2 <> 3\n") + out = kill_python(p) + self.assertNotIn(b'SyntaxError: invalid syntax', out) + +class AnnotationsFutureTestCase(unittest.TestCase): + template = dedent( + """ + from __future__ import annotations + def f() -> {ann}: + ... + def g(arg: {ann}) -> None: + ... + async def f2() -> {ann}: + ... + async def g2(arg: {ann}) -> None: + ... + class H: + var: {ann} + object.attr: {ann} + var: {ann} + var2: {ann} = None + object.attr: {ann} + """ + ) + + def getActual(self, annotation): + scope = {} + exec(self.template.format(ann=annotation), {}, scope) + func_ret_ann = scope['f'].__annotations__['return'] + func_arg_ann = scope['g'].__annotations__['arg'] + async_func_ret_ann = scope['f2'].__annotations__['return'] + async_func_arg_ann = scope['g2'].__annotations__['arg'] + var_ann1 = scope['__annotations__']['var'] + var_ann2 = scope['__annotations__']['var2'] + self.assertEqual(func_ret_ann, func_arg_ann) + self.assertEqual(func_ret_ann, async_func_ret_ann) + self.assertEqual(func_ret_ann, async_func_arg_ann) + self.assertEqual(func_ret_ann, var_ann1) + self.assertEqual(func_ret_ann, var_ann2) + return func_ret_ann + + def assertAnnotationEqual( + self, annotation, expected=None, drop_parens=False, is_tuple=False, + ): + actual = self.getActual(annotation) + if expected is None: + expected = annotation if not is_tuple else annotation[1:-1] + if drop_parens: + self.assertNotEqual(actual, expected) + actual = actual.replace("(", "").replace(")", "") + + self.assertEqual(actual, expected) + + def _exec_future(self, code): + scope = {} + exec( + "from __future__ import annotations\n" + + code, scope + ) + return scope + + def test_annotations(self): + eq = self.assertAnnotationEqual + eq('...') + eq("'some_string'") + eq("u'some_string'") + eq("b'\\xa3'") + eq('Name') + eq('None') + eq('True') + eq('False') + eq('1') + eq('1.0') + eq('1j') + eq('True or False') + eq('True or False or None') + eq('True and False') + eq('True and False and None') + eq('Name1 and Name2 or Name3') + eq('Name1 and (Name2 or Name3)') + eq('Name1 or Name2 and Name3') + eq('(Name1 or Name2) and Name3') + eq('Name1 and Name2 or Name3 and Name4') + eq('Name1 or Name2 and Name3 or Name4') + eq('a + b + (c + d)') + eq('a * b * (c * d)') + eq('(a ** b) ** c ** d') + eq('v1 << 2') + eq('1 >> v2') + eq('1 % finished') + eq('1 + v2 - v3 * 4 ^ 5 ** v6 / 7 // 8') + eq('not great') + eq('not not great') + eq('~great') + eq('+value') + eq('++value') + eq('-1') + eq('~int and not v1 ^ 123 + v2 | True') + eq('a + (not b)') + eq('lambda: None') + eq('lambda arg: None') + eq('lambda a=True: a') + eq('lambda a, b, c=True: a') + eq("lambda a, b, c=True, *, d=1 << v2, e='str': a") + eq("lambda a, b, c=True, *vararg, d, e='str', **kwargs: a + b") + eq("lambda a, /, b, c=True, *vararg, d, e='str', **kwargs: a + b") + eq('lambda x, /: x') + eq('lambda x=1, /: x') + eq('lambda x, /, y: x + y') + eq('lambda x=1, /, y=2: x + y') + eq('lambda x, /, y=1: x + y') + eq('lambda x, /, y=1, *, z=3: x + y + z') + eq('lambda x=1, /, y=2, *, z=3: x + y + z') + eq('lambda x=1, /, y=2, *, z: x + y + z') + eq('lambda x=1, y=2, z=3, /, w=4, *, l, l2: x + y + z + w + l + l2') + eq('lambda x=1, y=2, z=3, /, w=4, *, l, l2, **kwargs: x + y + z + w + l + l2') + eq('lambda x, /, y=1, *, z: x + y + z') + eq('lambda x: lambda y: x + y') + eq('1 if True else 2') + eq('str or None if int or True else str or bytes or None') + eq('str or None if (1 if True else 2) else str or bytes or None') + eq("0 if not x else 1 if x > 0 else -1") + eq("(1 if x > 0 else -1) if x else 0") + eq("{'2.7': dead, '3.7': long_live or die_hard}") + eq("{'2.7': dead, '3.7': long_live or die_hard, **{'3.6': verygood}}") + eq("{**a, **b, **c}") + eq("{'2.7', '3.6', '3.7', '3.8', '3.9', '4.0' if gilectomy else '3.10'}") + eq("{*a, *b, *c}") + eq("({'a': 'b'}, True or False, +value, 'string', b'bytes') or None") + eq("()") + eq("(a,)") + eq("(a, b)") + eq("(a, b, c)") + eq("(*a, *b, *c)") + eq("[]") + eq("[1, 2, 3, 4, 5, 6, 7, 8, 9, 10 or A, 11 or B, 12 or C]") + eq("[*a, *b, *c]") + eq("{i for i in (1, 2, 3)}") + eq("{i ** 2 for i in (1, 2, 3)}") + eq("{i ** 2 for i, _ in ((1, 'a'), (2, 'b'), (3, 'c'))}") + eq("{i ** 2 + j for i in (1, 2, 3) for j in (1, 2, 3)}") + eq("[i for i in (1, 2, 3)]") + eq("[i ** 2 for i in (1, 2, 3)]") + eq("[i ** 2 for i, _ in ((1, 'a'), (2, 'b'), (3, 'c'))]") + eq("[i ** 2 + j for i in (1, 2, 3) for j in (1, 2, 3)]") + eq("(i for i in (1, 2, 3))") + eq("(i ** 2 for i in (1, 2, 3))") + eq("(i ** 2 for i, _ in ((1, 'a'), (2, 'b'), (3, 'c')))") + eq("(i ** 2 + j for i in (1, 2, 3) for j in (1, 2, 3))") + eq("{i: 0 for i in (1, 2, 3)}") + eq("{i: j for i, j in ((1, 'a'), (2, 'b'), (3, 'c'))}") + eq("[(x, y) for x, y in (a, b)]") + eq("[(x,) for x, in (a,)]") + eq("Python3 > Python2 > COBOL") + eq("Life is Life") + eq("call()") + eq("call(arg)") + eq("call(kwarg='hey')") + eq("call(arg, kwarg='hey')") + eq("call(arg, *args, another, kwarg='hey')") + eq("call(arg, another, kwarg='hey', **kwargs, kwarg2='ho')") + eq("lukasz.langa.pl") + eq("call.me(maybe)") + eq("1 .real") + eq("1.0.real") + eq("....__class__") + eq("list[str]") + eq("dict[str, int]") + eq("set[str,]") + eq("tuple[()]") + eq("tuple[str, ...]") + eq("tuple[str, *types]") + eq("tuple[str, int, (str, int)]") + eq("tuple[*int, str, str, (str, int)]") + eq("tuple[str, int, float, dict[str, int]]") + eq("slice[0]") + eq("slice[0:1]") + eq("slice[0:1:2]") + eq("slice[:]") + eq("slice[:-1]") + eq("slice[1:]") + eq("slice[::-1]") + eq("slice[:,]") + eq("slice[1:2,]") + eq("slice[1:2:3,]") + eq("slice[1:2, 1]") + eq("slice[1:2, 2, 3]") + eq("slice[()]") + # Note that `slice[*Ts]`, `slice[*Ts,]`, and `slice[(*Ts,)]` all have + # the same AST, but only `slice[*Ts,]` passes this test, because that's + # what the unparser produces. + eq("slice[*Ts,]") + eq("slice[1, *Ts]") + eq("slice[*Ts, 2]") + eq("slice[1, *Ts, 2]") + eq("slice[*Ts, *Ts]") + eq("slice[1, *Ts, *Ts]") + eq("slice[*Ts, 1, *Ts]") + eq("slice[*Ts, *Ts, 1]") + eq("slice[1, *Ts, *Ts, 2]") + eq("slice[1:2, *Ts]") + eq("slice[*Ts, 1:2]") + eq("slice[1:2, *Ts, 3:4]") + eq("slice[a, b:c, d:e:f]") + eq("slice[(x for x in a)]") + eq('str or None if sys.version_info[0] > (3,) else str or bytes or None') + eq("f'f-string without formatted values is just a string'") + eq("f'{{NOT a formatted value}}'") + eq("f'some f-string with {a} {few():.2f} {formatted.values!r}'") + eq('''f"{f'{nested} inner'} outer"''') + eq("f'space between opening braces: { {a for a in (1, 2, 3)}}'") + eq("f'{(lambda x: x)}'") + eq("f'{(None if a else lambda x: x)}'") + eq("f'{x}'") + eq("f'{x!r}'") + eq("f'{x!a}'") + eq('[x for x in (a if b else c)]') + eq('[x for x in a if (b if c else d)]') + eq('f(x for x in a)') + eq('f(1, (x for x in a))') + eq('f((x for x in a), 2)') + eq('(((a)))', 'a') + eq('(((a, b)))', '(a, b)') + eq("1 + 2 + 3") + + def test_fstring_debug_annotations(self): + # f-strings with '=' don't round trip very well, so set the expected + # result explicitly. + self.assertAnnotationEqual("f'{x=!r}'", expected="f'x={x!r}'") + self.assertAnnotationEqual("f'{x=:}'", expected="f'x={x:}'") + self.assertAnnotationEqual("f'{x=:.2f}'", expected="f'x={x:.2f}'") + self.assertAnnotationEqual("f'{x=!r}'", expected="f'x={x!r}'") + self.assertAnnotationEqual("f'{x=!a}'", expected="f'x={x!a}'") + self.assertAnnotationEqual("f'{x=!s:*^20}'", expected="f'x={x!s:*^20}'") + + def test_infinity_numbers(self): + inf = "1e" + repr(sys.float_info.max_10_exp + 1) + infj = f"{inf}j" + self.assertAnnotationEqual("1e1000", expected=inf) + self.assertAnnotationEqual("1e1000j", expected=infj) + self.assertAnnotationEqual("-1e1000", expected=f"-{inf}") + self.assertAnnotationEqual("3+1e1000j", expected=f"3 + {infj}") + self.assertAnnotationEqual("(1e1000, 1e1000j)", expected=f"({inf}, {infj})") + self.assertAnnotationEqual("'inf'") + self.assertAnnotationEqual("('inf', 1e1000, 'infxxx', 1e1000j)", expected=f"('inf', {inf}, 'infxxx', {infj})") + self.assertAnnotationEqual("(1e1000, (1e1000j,))", expected=f"({inf}, ({infj},))") + + def test_annotation_with_complex_target(self): + with self.assertRaises(SyntaxError): + exec( + "from __future__ import annotations\n" + "object.__debug__: int" + ) + + def test_annotations_symbol_table_pass(self): + namespace = self._exec_future(dedent(""" + from __future__ import annotations + + def foo(): + outer = 1 + def bar(): + inner: outer = 1 + return bar + """)) + + foo = namespace.pop("foo") + self.assertIsNone(foo().__closure__) + self.assertEqual(foo.__code__.co_cellvars, ()) + self.assertEqual(foo().__code__.co_freevars, ()) + + def test_annotations_forbidden(self): + with self.assertRaises(SyntaxError): + self._exec_future("test: (yield)") + + with self.assertRaises(SyntaxError): + self._exec_future("test.test: (yield a + b)") + + with self.assertRaises(SyntaxError): + self._exec_future("test[something]: (yield from x)") + + with self.assertRaises(SyntaxError): + self._exec_future("def func(test: (yield from outside_of_generator)): pass") + + with self.assertRaises(SyntaxError): + self._exec_future("def test() -> (await y): pass") + + with self.assertRaises(SyntaxError): + self._exec_future("async def test() -> something((a := b)): pass") + + with self.assertRaises(SyntaxError): + self._exec_future("test: await some.complicated[0].call(with_args=True or 1 is not 1)") + + with self.assertRaises(SyntaxError): + self._exec_future("test: f'{(x := 10):=10}'") + + with self.assertRaises(SyntaxError): + self._exec_future(dedent("""\ + def foo(): + def bar(arg: (yield)): pass + """)) + + def test_get_type_hints_on_func_with_variadic_arg(self): + # `typing.get_type_hints` might break on a function with a variadic + # annotation (e.g. `f(*args: *Ts)`) if `from __future__ import + # annotations`, because it could try to evaluate `*Ts` as an expression, + # which on its own isn't value syntax. + namespace = self._exec_future(dedent("""\ + class StarredC: pass + class C: + def __iter__(self): + yield StarredC() + c = C() + def f(*args: *c): pass + import typing + hints = typing.get_type_hints(f) + """)) + + hints = namespace.pop('hints') + self.assertIsInstance(hints['args'], namespace['StarredC']) + + +if __name__ == "__main__": + unittest.main() diff --git a/Lib/test/test___future__.py b/Lib/test/test_future_stmt/test_future_flags.py similarity index 100% rename from Lib/test/test___future__.py rename to Lib/test/test_future_stmt/test_future_flags.py diff --git a/Lib/test/test_future5.py b/Lib/test/test_future_stmt/test_future_multiple_features.py similarity index 100% rename from Lib/test/test_future5.py rename to Lib/test/test_future_stmt/test_future_multiple_features.py diff --git a/Lib/test/test_future4.py b/Lib/test/test_future_stmt/test_future_multiple_imports.py similarity index 100% rename from Lib/test/test_future4.py rename to Lib/test/test_future_stmt/test_future_multiple_imports.py diff --git a/Lib/test/test_future3.py b/Lib/test/test_future_stmt/test_future_single_import.py similarity index 100% rename from Lib/test/test_future3.py rename to Lib/test/test_future_stmt/test_future_single_import.py diff --git a/Lib/test/test_gc.py b/Lib/test/test_gc.py index db7cb9ace6e5f3..1d71dd9e262a6a 100644 --- a/Lib/test/test_gc.py +++ b/Lib/test/test_gc.py @@ -1225,7 +1225,7 @@ def test_refcount_errors(self): p.stderr.close() # Verify that stderr has a useful error message: self.assertRegex(stderr, - br'gcmodule\.c:[0-9]+: gc_decref: Assertion "gc_get_refs\(g\) > 0" failed.') + br'gc\.c:[0-9]+: gc_decref: Assertion "gc_get_refs\(g\) > 0" failed.') self.assertRegex(stderr, br'refcount is too small') # "address : 0x7fb5062efc18" diff --git a/Lib/test/test_gdb.py b/Lib/test/test_gdb.py deleted file mode 100644 index 85009089f21d2f..00000000000000 --- a/Lib/test/test_gdb.py +++ /dev/null @@ -1,1052 +0,0 @@ -# Verify that gdb can pretty-print the various PyObject* types -# -# The code for testing gdb was adapted from similar work in Unladen Swallow's -# Lib/test/test_jit_gdb.py - -import os -import platform -import re -import subprocess -import sys -import sysconfig -import textwrap -import unittest - -from test import support -from test.support import findfile, python_is_optimized - -def get_gdb_version(): - try: - cmd = ["gdb", "-nx", "--version"] - proc = subprocess.Popen(cmd, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - universal_newlines=True) - with proc: - version, stderr = proc.communicate() - - if proc.returncode: - raise Exception(f"Command {' '.join(cmd)!r} failed " - f"with exit code {proc.returncode}: " - f"stdout={version!r} stderr={stderr!r}") - except OSError: - # This is what "no gdb" looks like. There may, however, be other - # errors that manifest this way too. - raise unittest.SkipTest("Couldn't find gdb on the path") - - # Regex to parse: - # 'GNU gdb (GDB; SUSE Linux Enterprise 12) 7.7\n' -> 7.7 - # 'GNU gdb (GDB) Fedora 7.9.1-17.fc22\n' -> 7.9 - # 'GNU gdb 6.1.1 [FreeBSD]\n' -> 6.1 - # 'GNU gdb (GDB) Fedora (7.5.1-37.fc18)\n' -> 7.5 - # 'HP gdb 6.7 for HP Itanium (32 or 64 bit) and target HP-UX 11iv2 and 11iv3.\n' -> 6.7 - match = re.search(r"^(?:GNU|HP) gdb.*?\b(\d+)\.(\d+)", version) - if match is None: - raise Exception("unable to parse GDB version: %r" % version) - return (version, int(match.group(1)), int(match.group(2))) - -gdb_version, gdb_major_version, gdb_minor_version = get_gdb_version() -if gdb_major_version < 7: - raise unittest.SkipTest("gdb versions before 7.0 didn't support python " - "embedding. Saw %s.%s:\n%s" - % (gdb_major_version, gdb_minor_version, - gdb_version)) - -if not sysconfig.is_python_build(): - raise unittest.SkipTest("test_gdb only works on source builds at the moment.") - -if 'Clang' in platform.python_compiler() and sys.platform == 'darwin': - raise unittest.SkipTest("test_gdb doesn't work correctly when python is" - " built with LLVM clang") - -if ((sysconfig.get_config_var('PGO_PROF_USE_FLAG') or 'xxx') in - (sysconfig.get_config_var('PY_CORE_CFLAGS') or '')): - raise unittest.SkipTest("test_gdb is not reliable on PGO builds") - -# Location of custom hooks file in a repository checkout. -checkout_hook_path = os.path.join(os.path.dirname(sys.executable), - 'python-gdb.py') - -PYTHONHASHSEED = '123' - - -def cet_protection(): - cflags = sysconfig.get_config_var('CFLAGS') - if not cflags: - return False - flags = cflags.split() - # True if "-mcet -fcf-protection" options are found, but false - # if "-fcf-protection=none" or "-fcf-protection=return" is found. - return (('-mcet' in flags) - and any((flag.startswith('-fcf-protection') - and not flag.endswith(("=none", "=return"))) - for flag in flags)) - -# Control-flow enforcement technology -CET_PROTECTION = cet_protection() - - -def run_gdb(*args, **env_vars): - """Runs gdb in --batch mode with the additional arguments given by *args. - - Returns its (stdout, stderr) decoded from utf-8 using the replace handler. - """ - if env_vars: - env = os.environ.copy() - env.update(env_vars) - else: - env = None - # -nx: Do not execute commands from any .gdbinit initialization files - # (issue #22188) - base_cmd = ('gdb', '--batch', '-nx') - if (gdb_major_version, gdb_minor_version) >= (7, 4): - base_cmd += ('-iex', 'add-auto-load-safe-path ' + checkout_hook_path) - proc = subprocess.Popen(base_cmd + args, - # Redirect stdin to prevent GDB from messing with - # the terminal settings - stdin=subprocess.PIPE, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - env=env) - with proc: - out, err = proc.communicate() - return out.decode('utf-8', 'replace'), err.decode('utf-8', 'replace') - -# Verify that "gdb" was built with the embedded python support enabled: -gdbpy_version, _ = run_gdb("--eval-command=python import sys; print(sys.version_info)") -if not gdbpy_version: - raise unittest.SkipTest("gdb not built with embedded python support") - -if "major=2" in gdbpy_version: - raise unittest.SkipTest("gdb built with Python 2") - -# Verify that "gdb" can load our custom hooks, as OS security settings may -# disallow this without a customized .gdbinit. -_, gdbpy_errors = run_gdb('--args', sys.executable) -if "auto-loading has been declined" in gdbpy_errors: - msg = "gdb security settings prevent use of custom hooks: " - raise unittest.SkipTest(msg + gdbpy_errors.rstrip()) - -def gdb_has_frame_select(): - # Does this build of gdb have gdb.Frame.select ? - stdout, _ = run_gdb("--eval-command=python print(dir(gdb.Frame))") - m = re.match(r'.*\[(.*)\].*', stdout) - if not m: - raise unittest.SkipTest("Unable to parse output from gdb.Frame.select test") - gdb_frame_dir = m.group(1).split(', ') - return "'select'" in gdb_frame_dir - -HAS_PYUP_PYDOWN = gdb_has_frame_select() - -BREAKPOINT_FN='builtin_id' - -@unittest.skipIf(support.PGO, "not useful for PGO") -class DebuggerTests(unittest.TestCase): - - """Test that the debugger can debug Python.""" - - def get_stack_trace(self, source=None, script=None, - breakpoint=BREAKPOINT_FN, - cmds_after_breakpoint=None, - import_site=False, - ignore_stderr=False): - ''' - Run 'python -c SOURCE' under gdb with a breakpoint. - - Support injecting commands after the breakpoint is reached - - Returns the stdout from gdb - - cmds_after_breakpoint: if provided, a list of strings: gdb commands - ''' - # We use "set breakpoint pending yes" to avoid blocking with a: - # Function "foo" not defined. - # Make breakpoint pending on future shared library load? (y or [n]) - # error, which typically happens python is dynamically linked (the - # breakpoints of interest are to be found in the shared library) - # When this happens, we still get: - # Function "textiowrapper_write" not defined. - # emitted to stderr each time, alas. - - # Initially I had "--eval-command=continue" here, but removed it to - # avoid repeated print breakpoints when traversing hierarchical data - # structures - - # Generate a list of commands in gdb's language: - commands = ['set breakpoint pending yes', - 'break %s' % breakpoint, - - # The tests assume that the first frame of printed - # backtrace will not contain program counter, - # that is however not guaranteed by gdb - # therefore we need to use 'set print address off' to - # make sure the counter is not there. For example: - # #0 in PyObject_Print ... - # is assumed, but sometimes this can be e.g. - # #0 0x00003fffb7dd1798 in PyObject_Print ... - 'set print address off', - - 'run'] - - # GDB as of 7.4 onwards can distinguish between the - # value of a variable at entry vs current value: - # http://sourceware.org/gdb/onlinedocs/gdb/Variables.html - # which leads to the selftests failing with errors like this: - # AssertionError: 'v@entry=()' != '()' - # Disable this: - if (gdb_major_version, gdb_minor_version) >= (7, 4): - commands += ['set print entry-values no'] - - if cmds_after_breakpoint: - if CET_PROTECTION: - # bpo-32962: When Python is compiled with -mcet - # -fcf-protection, function arguments are unusable before - # running the first instruction of the function entry point. - # The 'next' command makes the required first step. - commands += ['next'] - commands += cmds_after_breakpoint - else: - commands += ['backtrace'] - - # print commands - - # Use "commands" to generate the arguments with which to invoke "gdb": - args = ['--eval-command=%s' % cmd for cmd in commands] - args += ["--args", - sys.executable] - args.extend(subprocess._args_from_interpreter_flags()) - - if not import_site: - # -S suppresses the default 'import site' - args += ["-S"] - - if source: - args += ["-c", source] - elif script: - args += [script] - - # Use "args" to invoke gdb, capturing stdout, stderr: - out, err = run_gdb(*args, PYTHONHASHSEED=PYTHONHASHSEED) - - if not ignore_stderr: - for line in err.splitlines(): - print(line, file=sys.stderr) - - # bpo-34007: Sometimes some versions of the shared libraries that - # are part of the traceback are compiled in optimised mode and the - # Program Counter (PC) is not present, not allowing gdb to walk the - # frames back. When this happens, the Python bindings of gdb raise - # an exception, making the test impossible to succeed. - if "PC not saved" in err: - raise unittest.SkipTest("gdb cannot walk the frame object" - " because the Program Counter is" - " not present") - - # bpo-40019: Skip the test if gdb failed to read debug information - # because the Python binary is optimized. - for pattern in ( - '(frame information optimized out)', - 'Unable to read information on python frame', - ): - if pattern in out: - raise unittest.SkipTest(f"{pattern!r} found in gdb output") - - return out - - def get_gdb_repr(self, source, - cmds_after_breakpoint=None, - import_site=False): - # Given an input python source representation of data, - # run "python -c'id(DATA)'" under gdb with a breakpoint on - # builtin_id and scrape out gdb's representation of the "op" - # parameter, and verify that the gdb displays the same string - # - # Verify that the gdb displays the expected string - # - # For a nested structure, the first time we hit the breakpoint will - # give us the top-level structure - - # NOTE: avoid decoding too much of the traceback as some - # undecodable characters may lurk there in optimized mode - # (issue #19743). - cmds_after_breakpoint = cmds_after_breakpoint or ["backtrace 1"] - gdb_output = self.get_stack_trace(source, breakpoint=BREAKPOINT_FN, - cmds_after_breakpoint=cmds_after_breakpoint, - import_site=import_site) - # gdb can insert additional '\n' and space characters in various places - # in its output, depending on the width of the terminal it's connected - # to (using its "wrap_here" function) - m = re.search( - # Match '#0 builtin_id(self=..., v=...)' - r'#0\s+builtin_id\s+\(self\=.*,\s+v=\s*(.*?)?\)' - # Match ' at Python/bltinmodule.c'. - # bpo-38239: builtin_id() is defined in Python/bltinmodule.c, - # but accept any "Directory\file.c" to support Link Time - # Optimization (LTO). - r'\s+at\s+\S*[A-Za-z]+/[A-Za-z0-9_-]+\.c', - gdb_output, re.DOTALL) - if not m: - self.fail('Unexpected gdb output: %r\n%s' % (gdb_output, gdb_output)) - return m.group(1), gdb_output - - def assertEndsWith(self, actual, exp_end): - '''Ensure that the given "actual" string ends with "exp_end"''' - self.assertTrue(actual.endswith(exp_end), - msg='%r did not end with %r' % (actual, exp_end)) - - def assertMultilineMatches(self, actual, pattern): - m = re.match(pattern, actual, re.DOTALL) - if not m: - self.fail(msg='%r did not match %r' % (actual, pattern)) - - def get_sample_script(self): - return findfile('gdb_sample.py') - -class PrettyPrintTests(DebuggerTests): - def test_getting_backtrace(self): - gdb_output = self.get_stack_trace('id(42)') - self.assertTrue(BREAKPOINT_FN in gdb_output) - - def assertGdbRepr(self, val, exp_repr=None): - # Ensure that gdb's rendering of the value in a debugged process - # matches repr(value) in this process: - gdb_repr, gdb_output = self.get_gdb_repr('id(' + ascii(val) + ')') - if not exp_repr: - exp_repr = repr(val) - self.assertEqual(gdb_repr, exp_repr, - ('%r did not equal expected %r; full output was:\n%s' - % (gdb_repr, exp_repr, gdb_output))) - - def test_int(self): - 'Verify the pretty-printing of various int values' - self.assertGdbRepr(42) - self.assertGdbRepr(0) - self.assertGdbRepr(-7) - self.assertGdbRepr(1000000000000) - self.assertGdbRepr(-1000000000000000) - - def test_singletons(self): - 'Verify the pretty-printing of True, False and None' - self.assertGdbRepr(True) - self.assertGdbRepr(False) - self.assertGdbRepr(None) - - def test_dicts(self): - 'Verify the pretty-printing of dictionaries' - self.assertGdbRepr({}) - self.assertGdbRepr({'foo': 'bar'}, "{'foo': 'bar'}") - # Python preserves insertion order since 3.6 - self.assertGdbRepr({'foo': 'bar', 'douglas': 42}, "{'foo': 'bar', 'douglas': 42}") - - def test_lists(self): - 'Verify the pretty-printing of lists' - self.assertGdbRepr([]) - self.assertGdbRepr(list(range(5))) - - def test_bytes(self): - 'Verify the pretty-printing of bytes' - self.assertGdbRepr(b'') - self.assertGdbRepr(b'And now for something hopefully the same') - self.assertGdbRepr(b'string with embedded NUL here \0 and then some more text') - self.assertGdbRepr(b'this is a tab:\t' - b' this is a slash-N:\n' - b' this is a slash-R:\r' - ) - - self.assertGdbRepr(b'this is byte 255:\xff and byte 128:\x80') - - self.assertGdbRepr(bytes([b for b in range(255)])) - - def test_strings(self): - 'Verify the pretty-printing of unicode strings' - # We cannot simply call locale.getpreferredencoding() here, - # as GDB might have been linked against a different version - # of Python with a different encoding and coercion policy - # with respect to PEP 538 and PEP 540. - out, err = run_gdb( - '--eval-command', - 'python import locale; print(locale.getpreferredencoding())') - - encoding = out.rstrip() - if err or not encoding: - raise RuntimeError( - f'unable to determine the preferred encoding ' - f'of embedded Python in GDB: {err}') - - def check_repr(text): - try: - text.encode(encoding) - except UnicodeEncodeError: - self.assertGdbRepr(text, ascii(text)) - else: - self.assertGdbRepr(text) - - self.assertGdbRepr('') - self.assertGdbRepr('And now for something hopefully the same') - self.assertGdbRepr('string with embedded NUL here \0 and then some more text') - - # Test printing a single character: - # U+2620 SKULL AND CROSSBONES - check_repr('\u2620') - - # Test printing a Japanese unicode string - # (I believe this reads "mojibake", using 3 characters from the CJK - # Unified Ideographs area, followed by U+3051 HIRAGANA LETTER KE) - check_repr('\u6587\u5b57\u5316\u3051') - - # Test a character outside the BMP: - # U+1D121 MUSICAL SYMBOL C CLEF - # This is: - # UTF-8: 0xF0 0x9D 0x84 0xA1 - # UTF-16: 0xD834 0xDD21 - check_repr(chr(0x1D121)) - - def test_tuples(self): - 'Verify the pretty-printing of tuples' - self.assertGdbRepr(tuple(), '()') - self.assertGdbRepr((1,), '(1,)') - self.assertGdbRepr(('foo', 'bar', 'baz')) - - def test_sets(self): - 'Verify the pretty-printing of sets' - if (gdb_major_version, gdb_minor_version) < (7, 3): - self.skipTest("pretty-printing of sets needs gdb 7.3 or later") - self.assertGdbRepr(set(), "set()") - self.assertGdbRepr(set(['a']), "{'a'}") - # PYTHONHASHSEED is need to get the exact frozenset item order - if not sys.flags.ignore_environment: - self.assertGdbRepr(set(['a', 'b']), "{'a', 'b'}") - self.assertGdbRepr(set([4, 5, 6]), "{4, 5, 6}") - - # Ensure that we handle sets containing the "dummy" key value, - # which happens on deletion: - gdb_repr, gdb_output = self.get_gdb_repr('''s = set(['a','b']) -s.remove('a') -id(s)''') - self.assertEqual(gdb_repr, "{'b'}") - - def test_frozensets(self): - 'Verify the pretty-printing of frozensets' - if (gdb_major_version, gdb_minor_version) < (7, 3): - self.skipTest("pretty-printing of frozensets needs gdb 7.3 or later") - self.assertGdbRepr(frozenset(), "frozenset()") - self.assertGdbRepr(frozenset(['a']), "frozenset({'a'})") - # PYTHONHASHSEED is need to get the exact frozenset item order - if not sys.flags.ignore_environment: - self.assertGdbRepr(frozenset(['a', 'b']), "frozenset({'a', 'b'})") - self.assertGdbRepr(frozenset([4, 5, 6]), "frozenset({4, 5, 6})") - - def test_exceptions(self): - # Test a RuntimeError - gdb_repr, gdb_output = self.get_gdb_repr(''' -try: - raise RuntimeError("I am an error") -except RuntimeError as e: - id(e) -''') - self.assertEqual(gdb_repr, - "RuntimeError('I am an error',)") - - - # Test division by zero: - gdb_repr, gdb_output = self.get_gdb_repr(''' -try: - a = 1 / 0 -except ZeroDivisionError as e: - id(e) -''') - self.assertEqual(gdb_repr, - "ZeroDivisionError('division by zero',)") - - def test_modern_class(self): - 'Verify the pretty-printing of new-style class instances' - gdb_repr, gdb_output = self.get_gdb_repr(''' -class Foo: - pass -foo = Foo() -foo.an_int = 42 -id(foo)''') - m = re.match(r'', gdb_repr) - self.assertTrue(m, - msg='Unexpected new-style class rendering %r' % gdb_repr) - - def test_subclassing_list(self): - 'Verify the pretty-printing of an instance of a list subclass' - gdb_repr, gdb_output = self.get_gdb_repr(''' -class Foo(list): - pass -foo = Foo() -foo += [1, 2, 3] -foo.an_int = 42 -id(foo)''') - m = re.match(r'', gdb_repr) - - self.assertTrue(m, - msg='Unexpected new-style class rendering %r' % gdb_repr) - - def test_subclassing_tuple(self): - 'Verify the pretty-printing of an instance of a tuple subclass' - # This should exercise the negative tp_dictoffset code in the - # new-style class support - gdb_repr, gdb_output = self.get_gdb_repr(''' -class Foo(tuple): - pass -foo = Foo((1, 2, 3)) -foo.an_int = 42 -id(foo)''') - m = re.match(r'', gdb_repr) - - self.assertTrue(m, - msg='Unexpected new-style class rendering %r' % gdb_repr) - - def assertSane(self, source, corruption, exprepr=None): - '''Run Python under gdb, corrupting variables in the inferior process - immediately before taking a backtrace. - - Verify that the variable's representation is the expected failsafe - representation''' - if corruption: - cmds_after_breakpoint=[corruption, 'backtrace'] - else: - cmds_after_breakpoint=['backtrace'] - - gdb_repr, gdb_output = \ - self.get_gdb_repr(source, - cmds_after_breakpoint=cmds_after_breakpoint) - if exprepr: - if gdb_repr == exprepr: - # gdb managed to print the value in spite of the corruption; - # this is good (see http://bugs.python.org/issue8330) - return - - # Match anything for the type name; 0xDEADBEEF could point to - # something arbitrary (see http://bugs.python.org/issue8330) - pattern = '<.* at remote 0x-?[0-9a-f]+>' - - m = re.match(pattern, gdb_repr) - if not m: - self.fail('Unexpected gdb representation: %r\n%s' % \ - (gdb_repr, gdb_output)) - - def test_NULL_ptr(self): - 'Ensure that a NULL PyObject* is handled gracefully' - gdb_repr, gdb_output = ( - self.get_gdb_repr('id(42)', - cmds_after_breakpoint=['set variable v=0', - 'backtrace']) - ) - - self.assertEqual(gdb_repr, '0x0') - - def test_NULL_ob_type(self): - 'Ensure that a PyObject* with NULL ob_type is handled gracefully' - self.assertSane('id(42)', - 'set v->ob_type=0') - - def test_corrupt_ob_type(self): - 'Ensure that a PyObject* with a corrupt ob_type is handled gracefully' - self.assertSane('id(42)', - 'set v->ob_type=0xDEADBEEF', - exprepr='42') - - def test_corrupt_tp_flags(self): - 'Ensure that a PyObject* with a type with corrupt tp_flags is handled' - self.assertSane('id(42)', - 'set v->ob_type->tp_flags=0x0', - exprepr='42') - - def test_corrupt_tp_name(self): - 'Ensure that a PyObject* with a type with corrupt tp_name is handled' - self.assertSane('id(42)', - 'set v->ob_type->tp_name=0xDEADBEEF', - exprepr='42') - - def test_builtins_help(self): - 'Ensure that the new-style class _Helper in site.py can be handled' - - if sys.flags.no_site: - self.skipTest("need site module, but -S option was used") - - # (this was the issue causing tracebacks in - # http://bugs.python.org/issue8032#msg100537 ) - gdb_repr, gdb_output = self.get_gdb_repr('id(__builtins__.help)', import_site=True) - - m = re.match(r'<_Helper\(\) at remote 0x-?[0-9a-f]+>', gdb_repr) - self.assertTrue(m, - msg='Unexpected rendering %r' % gdb_repr) - - def test_selfreferential_list(self): - '''Ensure that a reference loop involving a list doesn't lead proxyval - into an infinite loop:''' - gdb_repr, gdb_output = \ - self.get_gdb_repr("a = [3, 4, 5] ; a.append(a) ; id(a)") - self.assertEqual(gdb_repr, '[3, 4, 5, [...]]') - - gdb_repr, gdb_output = \ - self.get_gdb_repr("a = [3, 4, 5] ; b = [a] ; a.append(b) ; id(a)") - self.assertEqual(gdb_repr, '[3, 4, 5, [[...]]]') - - def test_selfreferential_dict(self): - '''Ensure that a reference loop involving a dict doesn't lead proxyval - into an infinite loop:''' - gdb_repr, gdb_output = \ - self.get_gdb_repr("a = {} ; b = {'bar':a} ; a['foo'] = b ; id(a)") - - self.assertEqual(gdb_repr, "{'foo': {'bar': {...}}}") - - def test_selfreferential_old_style_instance(self): - gdb_repr, gdb_output = \ - self.get_gdb_repr(''' -class Foo: - pass -foo = Foo() -foo.an_attr = foo -id(foo)''') - self.assertTrue(re.match(r'\) at remote 0x-?[0-9a-f]+>', - gdb_repr), - 'Unexpected gdb representation: %r\n%s' % \ - (gdb_repr, gdb_output)) - - def test_selfreferential_new_style_instance(self): - gdb_repr, gdb_output = \ - self.get_gdb_repr(''' -class Foo(object): - pass -foo = Foo() -foo.an_attr = foo -id(foo)''') - self.assertTrue(re.match(r'\) at remote 0x-?[0-9a-f]+>', - gdb_repr), - 'Unexpected gdb representation: %r\n%s' % \ - (gdb_repr, gdb_output)) - - gdb_repr, gdb_output = \ - self.get_gdb_repr(''' -class Foo(object): - pass -a = Foo() -b = Foo() -a.an_attr = b -b.an_attr = a -id(a)''') - self.assertTrue(re.match(r'\) at remote 0x-?[0-9a-f]+>\) at remote 0x-?[0-9a-f]+>', - gdb_repr), - 'Unexpected gdb representation: %r\n%s' % \ - (gdb_repr, gdb_output)) - - def test_truncation(self): - 'Verify that very long output is truncated' - gdb_repr, gdb_output = self.get_gdb_repr('id(list(range(1000)))') - self.assertEqual(gdb_repr, - "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, " - "14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, " - "27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, " - "40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, " - "53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, " - "66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, " - "79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, " - "92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, " - "104, 105, 106, 107, 108, 109, 110, 111, 112, 113, " - "114, 115, 116, 117, 118, 119, 120, 121, 122, 123, " - "124, 125, 126, 127, 128, 129, 130, 131, 132, 133, " - "134, 135, 136, 137, 138, 139, 140, 141, 142, 143, " - "144, 145, 146, 147, 148, 149, 150, 151, 152, 153, " - "154, 155, 156, 157, 158, 159, 160, 161, 162, 163, " - "164, 165, 166, 167, 168, 169, 170, 171, 172, 173, " - "174, 175, 176, 177, 178, 179, 180, 181, 182, 183, " - "184, 185, 186, 187, 188, 189, 190, 191, 192, 193, " - "194, 195, 196, 197, 198, 199, 200, 201, 202, 203, " - "204, 205, 206, 207, 208, 209, 210, 211, 212, 213, " - "214, 215, 216, 217, 218, 219, 220, 221, 222, 223, " - "224, 225, 226...(truncated)") - self.assertEqual(len(gdb_repr), - 1024 + len('...(truncated)')) - - def test_builtin_method(self): - gdb_repr, gdb_output = self.get_gdb_repr('import sys; id(sys.stdout.readlines)') - self.assertTrue(re.match(r'', - gdb_repr), - 'Unexpected gdb representation: %r\n%s' % \ - (gdb_repr, gdb_output)) - - def test_frames(self): - gdb_output = self.get_stack_trace(''' -import sys -def foo(a, b, c): - return sys._getframe(0) - -f = foo(3, 4, 5) -id(f)''', - breakpoint='builtin_id', - cmds_after_breakpoint=['print (PyFrameObject*)v'] - ) - self.assertTrue(re.match(r'.*\s+\$1 =\s+Frame 0x-?[0-9a-f]+, for file , line 4, in foo \(a=3.*', - gdb_output, - re.DOTALL), - 'Unexpected gdb representation: %r\n%s' % (gdb_output, gdb_output)) - -@unittest.skipIf(python_is_optimized(), - "Python was compiled with optimizations") -class PyListTests(DebuggerTests): - def assertListing(self, expected, actual): - self.assertEndsWith(actual, expected) - - def test_basic_command(self): - 'Verify that the "py-list" command works' - bt = self.get_stack_trace(script=self.get_sample_script(), - cmds_after_breakpoint=['py-list']) - - self.assertListing(' 5 \n' - ' 6 def bar(a, b, c):\n' - ' 7 baz(a, b, c)\n' - ' 8 \n' - ' 9 def baz(*args):\n' - ' >10 id(42)\n' - ' 11 \n' - ' 12 foo(1, 2, 3)\n', - bt) - - def test_one_abs_arg(self): - 'Verify the "py-list" command with one absolute argument' - bt = self.get_stack_trace(script=self.get_sample_script(), - cmds_after_breakpoint=['py-list 9']) - - self.assertListing(' 9 def baz(*args):\n' - ' >10 id(42)\n' - ' 11 \n' - ' 12 foo(1, 2, 3)\n', - bt) - - def test_two_abs_args(self): - 'Verify the "py-list" command with two absolute arguments' - bt = self.get_stack_trace(script=self.get_sample_script(), - cmds_after_breakpoint=['py-list 1,3']) - - self.assertListing(' 1 # Sample script for use by test_gdb.py\n' - ' 2 \n' - ' 3 def foo(a, b, c):\n', - bt) - -SAMPLE_WITH_C_CALL = """ - -from _testcapi import pyobject_vectorcall - -def foo(a, b, c): - bar(a, b, c) - -def bar(a, b, c): - pyobject_vectorcall(baz, (a, b, c), None) - -def baz(*args): - id(42) - -foo(1, 2, 3) - -""" - - -class StackNavigationTests(DebuggerTests): - @unittest.skipUnless(HAS_PYUP_PYDOWN, "test requires py-up/py-down commands") - @unittest.skipIf(python_is_optimized(), - "Python was compiled with optimizations") - def test_pyup_command(self): - 'Verify that the "py-up" command works' - bt = self.get_stack_trace(source=SAMPLE_WITH_C_CALL, - cmds_after_breakpoint=['py-up', 'py-up']) - self.assertMultilineMatches(bt, - r'''^.* -#[0-9]+ Frame 0x-?[0-9a-f]+, for file , line 12, in baz \(args=\(1, 2, 3\)\) -#[0-9]+ -$''') - - @unittest.skipUnless(HAS_PYUP_PYDOWN, "test requires py-up/py-down commands") - def test_down_at_bottom(self): - 'Verify handling of "py-down" at the bottom of the stack' - bt = self.get_stack_trace(script=self.get_sample_script(), - cmds_after_breakpoint=['py-down']) - self.assertEndsWith(bt, - 'Unable to find a newer python frame\n') - - @unittest.skipUnless(HAS_PYUP_PYDOWN, "test requires py-up/py-down commands") - def test_up_at_top(self): - 'Verify handling of "py-up" at the top of the stack' - bt = self.get_stack_trace(script=self.get_sample_script(), - cmds_after_breakpoint=['py-up'] * 5) - self.assertEndsWith(bt, - 'Unable to find an older python frame\n') - - @unittest.skipUnless(HAS_PYUP_PYDOWN, "test requires py-up/py-down commands") - @unittest.skipIf(python_is_optimized(), - "Python was compiled with optimizations") - def test_up_then_down(self): - 'Verify "py-up" followed by "py-down"' - bt = self.get_stack_trace(source=SAMPLE_WITH_C_CALL, - cmds_after_breakpoint=['py-up', 'py-up', 'py-down']) - self.assertMultilineMatches(bt, - r'''^.* -#[0-9]+ Frame 0x-?[0-9a-f]+, for file , line 12, in baz \(args=\(1, 2, 3\)\) -#[0-9]+ -#[0-9]+ Frame 0x-?[0-9a-f]+, for file , line 12, in baz \(args=\(1, 2, 3\)\) -$''') - -class PyBtTests(DebuggerTests): - @unittest.skipIf(python_is_optimized(), - "Python was compiled with optimizations") - def test_bt(self): - 'Verify that the "py-bt" command works' - bt = self.get_stack_trace(script=self.get_sample_script(), - cmds_after_breakpoint=['py-bt']) - self.assertMultilineMatches(bt, - r'''^.* -Traceback \(most recent call first\): - - File ".*gdb_sample.py", line 10, in baz - id\(42\) - File ".*gdb_sample.py", line 7, in bar - baz\(a, b, c\) - File ".*gdb_sample.py", line 4, in foo - bar\(a=a, b=b, c=c\) - File ".*gdb_sample.py", line 12, in - foo\(1, 2, 3\) -''') - - @unittest.skipIf(python_is_optimized(), - "Python was compiled with optimizations") - def test_bt_full(self): - 'Verify that the "py-bt-full" command works' - bt = self.get_stack_trace(script=self.get_sample_script(), - cmds_after_breakpoint=['py-bt-full']) - self.assertMultilineMatches(bt, - r'''^.* -#[0-9]+ Frame 0x-?[0-9a-f]+, for file .*gdb_sample.py, line 7, in bar \(a=1, b=2, c=3\) - baz\(a, b, c\) -#[0-9]+ Frame 0x-?[0-9a-f]+, for file .*gdb_sample.py, line 4, in foo \(a=1, b=2, c=3\) - bar\(a=a, b=b, c=c\) -#[0-9]+ Frame 0x-?[0-9a-f]+, for file .*gdb_sample.py, line 12, in \(\) - foo\(1, 2, 3\) -''') - - @unittest.skipIf(python_is_optimized(), - "Python was compiled with optimizations") - def test_threads(self): - 'Verify that "py-bt" indicates threads that are waiting for the GIL' - cmd = ''' -from threading import Thread - -class TestThread(Thread): - # These threads would run forever, but we'll interrupt things with the - # debugger - def run(self): - i = 0 - while 1: - i += 1 - -t = {} -for i in range(4): - t[i] = TestThread() - t[i].start() - -# Trigger a breakpoint on the main thread -id(42) - -''' - # Verify with "py-bt": - gdb_output = self.get_stack_trace(cmd, - cmds_after_breakpoint=['thread apply all py-bt']) - self.assertIn('Waiting for the GIL', gdb_output) - - # Verify with "py-bt-full": - gdb_output = self.get_stack_trace(cmd, - cmds_after_breakpoint=['thread apply all py-bt-full']) - self.assertIn('Waiting for the GIL', gdb_output) - - @unittest.skipIf(python_is_optimized(), - "Python was compiled with optimizations") - # Some older versions of gdb will fail with - # "Cannot find new threads: generic error" - # unless we add LD_PRELOAD=PATH-TO-libpthread.so.1 as a workaround - def test_gc(self): - 'Verify that "py-bt" indicates if a thread is garbage-collecting' - cmd = ('from gc import collect\n' - 'id(42)\n' - 'def foo():\n' - ' collect()\n' - 'def bar():\n' - ' foo()\n' - 'bar()\n') - # Verify with "py-bt": - gdb_output = self.get_stack_trace(cmd, - cmds_after_breakpoint=['break update_refs', 'continue', 'py-bt'], - ) - self.assertIn('Garbage-collecting', gdb_output) - - # Verify with "py-bt-full": - gdb_output = self.get_stack_trace(cmd, - cmds_after_breakpoint=['break update_refs', 'continue', 'py-bt-full'], - ) - self.assertIn('Garbage-collecting', gdb_output) - - - @unittest.skipIf(python_is_optimized(), - "Python was compiled with optimizations") - # Some older versions of gdb will fail with - # "Cannot find new threads: generic error" - # unless we add LD_PRELOAD=PATH-TO-libpthread.so.1 as a workaround - # - # gdb will also generate many erroneous errors such as: - # Function "meth_varargs" not defined. - # This is because we are calling functions from an "external" module - # (_testcapimodule) rather than compiled-in functions. It seems difficult - # to suppress these. See also the comment in DebuggerTests.get_stack_trace - def test_pycfunction(self): - 'Verify that "py-bt" displays invocations of PyCFunction instances' - # bpo-46600: If the compiler inlines _null_to_none() in meth_varargs() - # (ex: clang -Og), _null_to_none() is the frame #1. Otherwise, - # meth_varargs() is the frame #1. - expected_frame = r'#(1|2)' - # Various optimizations multiply the code paths by which these are - # called, so test a variety of calling conventions. - for func_name, args in ( - ('meth_varargs', ''), - ('meth_varargs_keywords', ''), - ('meth_o', '[]'), - ('meth_noargs', ''), - ('meth_fastcall', ''), - ('meth_fastcall_keywords', ''), - ): - for obj in ( - '_testcapi', - '_testcapi.MethClass', - '_testcapi.MethClass()', - '_testcapi.MethStatic()', - - # XXX: bound methods don't yet give nice tracebacks - # '_testcapi.MethInstance()', - ): - with self.subTest(f'{obj}.{func_name}'): - cmd = textwrap.dedent(f''' - import _testcapi - def foo(): - {obj}.{func_name}({args}) - def bar(): - foo() - bar() - ''') - # Verify with "py-bt": - gdb_output = self.get_stack_trace( - cmd, - breakpoint=func_name, - cmds_after_breakpoint=['bt', 'py-bt'], - # bpo-45207: Ignore 'Function "meth_varargs" not - # defined.' message in stderr. - ignore_stderr=True, - ) - self.assertIn(f'\n.*") - -class PyLocalsTests(DebuggerTests): - @unittest.skipIf(python_is_optimized(), - "Python was compiled with optimizations") - def test_basic_command(self): - bt = self.get_stack_trace(script=self.get_sample_script(), - cmds_after_breakpoint=['py-up', 'py-locals']) - self.assertMultilineMatches(bt, - r".*\nargs = \(1, 2, 3\)\n.*") - - @unittest.skipUnless(HAS_PYUP_PYDOWN, "test requires py-up/py-down commands") - @unittest.skipIf(python_is_optimized(), - "Python was compiled with optimizations") - def test_locals_after_up(self): - bt = self.get_stack_trace(script=self.get_sample_script(), - cmds_after_breakpoint=['py-up', 'py-up', 'py-locals']) - self.assertMultilineMatches(bt, - r'''^.* -Locals for foo -a = 1 -b = 2 -c = 3 -Locals for -.*$''') - - -def setUpModule(): - if support.verbose: - print("GDB version %s.%s:" % (gdb_major_version, gdb_minor_version)) - for line in gdb_version.splitlines(): - print(" " * 4 + line) - - -if __name__ == "__main__": - unittest.main() diff --git a/Lib/test/test_gdb/__init__.py b/Lib/test/test_gdb/__init__.py new file mode 100644 index 00000000000000..99557739af6748 --- /dev/null +++ b/Lib/test/test_gdb/__init__.py @@ -0,0 +1,29 @@ +# Verify that gdb can pretty-print the various PyObject* types +# +# The code for testing gdb was adapted from similar work in Unladen Swallow's +# Lib/test/test_jit_gdb.py + +import os +import sysconfig +import unittest +from test import support + + +if support.MS_WINDOWS: + # On Windows, Python is usually built by MSVC. Passing /p:DebugSymbols=true + # option to MSBuild produces PDB debug symbols, but gdb doesn't support PDB + # debug symbol files. + raise unittest.SkipTest("test_gdb doesn't work on Windows") + +if support.PGO: + raise unittest.SkipTest("test_gdb is not useful for PGO") + +if not sysconfig.is_python_build(): + raise unittest.SkipTest("test_gdb only works on source builds at the moment.") + +if support.check_cflags_pgo(): + raise unittest.SkipTest("test_gdb is not reliable on PGO builds") + + +def load_tests(*args): + return support.load_package_tests(os.path.dirname(__file__), *args) diff --git a/Lib/test/gdb_sample.py b/Lib/test/test_gdb/gdb_sample.py similarity index 75% rename from Lib/test/gdb_sample.py rename to Lib/test/test_gdb/gdb_sample.py index 4188f50136fb97..a7f23db73ea6e6 100644 --- a/Lib/test/gdb_sample.py +++ b/Lib/test/test_gdb/gdb_sample.py @@ -1,4 +1,4 @@ -# Sample script for use by test_gdb.py +# Sample script for use by test_gdb def foo(a, b, c): bar(a=a, b=b, c=c) diff --git a/Lib/test/test_gdb/test_backtrace.py b/Lib/test/test_gdb/test_backtrace.py new file mode 100644 index 00000000000000..c41e7cb7c210de --- /dev/null +++ b/Lib/test/test_gdb/test_backtrace.py @@ -0,0 +1,134 @@ +import textwrap +import unittest +from test import support +from test.support import python_is_optimized + +from .util import setup_module, DebuggerTests, CET_PROTECTION, SAMPLE_SCRIPT + + +def setUpModule(): + setup_module() + + +class PyBtTests(DebuggerTests): + @unittest.skipIf(python_is_optimized(), + "Python was compiled with optimizations") + def test_bt(self): + 'Verify that the "py-bt" command works' + bt = self.get_stack_trace(script=SAMPLE_SCRIPT, + cmds_after_breakpoint=['py-bt']) + self.assertMultilineMatches(bt, + r'''^.* +Traceback \(most recent call first\): + + File ".*gdb_sample.py", line 10, in baz + id\(42\) + File ".*gdb_sample.py", line 7, in bar + baz\(a, b, c\) + File ".*gdb_sample.py", line 4, in foo + bar\(a=a, b=b, c=c\) + File ".*gdb_sample.py", line 12, in + foo\(1, 2, 3\) +''') + + @unittest.skipIf(python_is_optimized(), + "Python was compiled with optimizations") + def test_bt_full(self): + 'Verify that the "py-bt-full" command works' + bt = self.get_stack_trace(script=SAMPLE_SCRIPT, + cmds_after_breakpoint=['py-bt-full']) + self.assertMultilineMatches(bt, + r'''^.* +#[0-9]+ Frame 0x-?[0-9a-f]+, for file .*gdb_sample.py, line 7, in bar \(a=1, b=2, c=3\) + baz\(a, b, c\) +#[0-9]+ Frame 0x-?[0-9a-f]+, for file .*gdb_sample.py, line 4, in foo \(a=1, b=2, c=3\) + bar\(a=a, b=b, c=c\) +#[0-9]+ Frame 0x-?[0-9a-f]+, for file .*gdb_sample.py, line 12, in \(\) + foo\(1, 2, 3\) +''') + + @unittest.skipIf(python_is_optimized(), + "Python was compiled with optimizations") + @support.requires_resource('cpu') + def test_threads(self): + 'Verify that "py-bt" indicates threads that are waiting for the GIL' + cmd = ''' +from threading import Thread + +class TestThread(Thread): + # These threads would run forever, but we'll interrupt things with the + # debugger + def run(self): + i = 0 + while 1: + i += 1 + +t = {} +for i in range(4): + t[i] = TestThread() + t[i].start() + +# Trigger a breakpoint on the main thread +id(42) + +''' + # Verify with "py-bt": + gdb_output = self.get_stack_trace(cmd, + cmds_after_breakpoint=['thread apply all py-bt']) + self.assertIn('Waiting for the GIL', gdb_output) + + # Verify with "py-bt-full": + gdb_output = self.get_stack_trace(cmd, + cmds_after_breakpoint=['thread apply all py-bt-full']) + self.assertIn('Waiting for the GIL', gdb_output) + + @unittest.skipIf(python_is_optimized(), + "Python was compiled with optimizations") + # Some older versions of gdb will fail with + # "Cannot find new threads: generic error" + # unless we add LD_PRELOAD=PATH-TO-libpthread.so.1 as a workaround + def test_gc(self): + 'Verify that "py-bt" indicates if a thread is garbage-collecting' + cmd = ('from gc import collect\n' + 'id(42)\n' + 'def foo():\n' + ' collect()\n' + 'def bar():\n' + ' foo()\n' + 'bar()\n') + # Verify with "py-bt": + gdb_output = self.get_stack_trace(cmd, + cmds_after_breakpoint=['break update_refs', 'continue', 'py-bt'], + ) + self.assertIn('Garbage-collecting', gdb_output) + + # Verify with "py-bt-full": + gdb_output = self.get_stack_trace(cmd, + cmds_after_breakpoint=['break update_refs', 'continue', 'py-bt-full'], + ) + self.assertIn('Garbage-collecting', gdb_output) + + @unittest.skipIf(python_is_optimized(), + "Python was compiled with optimizations") + def test_wrapper_call(self): + cmd = textwrap.dedent(''' + class MyList(list): + def __init__(self): + super(*[]).__init__() # wrapper_call() + + id("first break point") + l = MyList() + ''') + cmds_after_breakpoint = ['break wrapper_call', 'continue'] + if CET_PROTECTION: + # bpo-32962: same case as in get_stack_trace(): + # we need an additional 'next' command in order to read + # arguments of the innermost function of the call stack. + cmds_after_breakpoint.append('next') + cmds_after_breakpoint.append('py-bt') + + # Verify with "py-bt": + gdb_output = self.get_stack_trace(cmd, + cmds_after_breakpoint=cmds_after_breakpoint) + self.assertRegex(gdb_output, + r"10 id(42)\n' + ' 11 \n' + ' 12 foo(1, 2, 3)\n', + bt) + + def test_one_abs_arg(self): + 'Verify the "py-list" command with one absolute argument' + bt = self.get_stack_trace(script=SAMPLE_SCRIPT, + cmds_after_breakpoint=['py-list 9']) + + self.assertListing(' 9 def baz(*args):\n' + ' >10 id(42)\n' + ' 11 \n' + ' 12 foo(1, 2, 3)\n', + bt) + + def test_two_abs_args(self): + 'Verify the "py-list" command with two absolute arguments' + bt = self.get_stack_trace(script=SAMPLE_SCRIPT, + cmds_after_breakpoint=['py-list 1,3']) + + self.assertListing(' 1 # Sample script for use by test_gdb\n' + ' 2 \n' + ' 3 def foo(a, b, c):\n', + bt) + +SAMPLE_WITH_C_CALL = """ + +from _testcapi import pyobject_vectorcall + +def foo(a, b, c): + bar(a, b, c) + +def bar(a, b, c): + pyobject_vectorcall(baz, (a, b, c), None) + +def baz(*args): + id(42) + +foo(1, 2, 3) + +""" + + +class StackNavigationTests(DebuggerTests): + @unittest.skipUnless(HAS_PYUP_PYDOWN, "test requires py-up/py-down commands") + @unittest.skipIf(python_is_optimized(), + "Python was compiled with optimizations") + def test_pyup_command(self): + 'Verify that the "py-up" command works' + bt = self.get_stack_trace(source=SAMPLE_WITH_C_CALL, + cmds_after_breakpoint=['py-up', 'py-up']) + self.assertMultilineMatches(bt, + r'''^.* +#[0-9]+ Frame 0x-?[0-9a-f]+, for file , line 12, in baz \(args=\(1, 2, 3\)\) +#[0-9]+ +$''') + + @unittest.skipUnless(HAS_PYUP_PYDOWN, "test requires py-up/py-down commands") + def test_down_at_bottom(self): + 'Verify handling of "py-down" at the bottom of the stack' + bt = self.get_stack_trace(script=SAMPLE_SCRIPT, + cmds_after_breakpoint=['py-down']) + self.assertEndsWith(bt, + 'Unable to find a newer python frame\n') + + @unittest.skipUnless(HAS_PYUP_PYDOWN, "test requires py-up/py-down commands") + def test_up_at_top(self): + 'Verify handling of "py-up" at the top of the stack' + bt = self.get_stack_trace(script=SAMPLE_SCRIPT, + cmds_after_breakpoint=['py-up'] * 5) + self.assertEndsWith(bt, + 'Unable to find an older python frame\n') + + @unittest.skipUnless(HAS_PYUP_PYDOWN, "test requires py-up/py-down commands") + @unittest.skipIf(python_is_optimized(), + "Python was compiled with optimizations") + def test_up_then_down(self): + 'Verify "py-up" followed by "py-down"' + bt = self.get_stack_trace(source=SAMPLE_WITH_C_CALL, + cmds_after_breakpoint=['py-up', 'py-up', 'py-down']) + self.assertMultilineMatches(bt, + r'''^.* +#[0-9]+ Frame 0x-?[0-9a-f]+, for file , line 12, in baz \(args=\(1, 2, 3\)\) +#[0-9]+ +#[0-9]+ Frame 0x-?[0-9a-f]+, for file , line 12, in baz \(args=\(1, 2, 3\)\) +$''') + +class PyPrintTests(DebuggerTests): + @unittest.skipIf(python_is_optimized(), + "Python was compiled with optimizations") + def test_basic_command(self): + 'Verify that the "py-print" command works' + bt = self.get_stack_trace(source=SAMPLE_WITH_C_CALL, + cmds_after_breakpoint=['py-up', 'py-print args']) + self.assertMultilineMatches(bt, + r".*\nlocal 'args' = \(1, 2, 3\)\n.*") + + @unittest.skipIf(python_is_optimized(), + "Python was compiled with optimizations") + @unittest.skipUnless(HAS_PYUP_PYDOWN, "test requires py-up/py-down commands") + def test_print_after_up(self): + bt = self.get_stack_trace(source=SAMPLE_WITH_C_CALL, + cmds_after_breakpoint=['py-up', 'py-up', 'py-print c', 'py-print b', 'py-print a']) + self.assertMultilineMatches(bt, + r".*\nlocal 'c' = 3\nlocal 'b' = 2\nlocal 'a' = 1\n.*") + + @unittest.skipIf(python_is_optimized(), + "Python was compiled with optimizations") + def test_printing_global(self): + bt = self.get_stack_trace(script=SAMPLE_SCRIPT, + cmds_after_breakpoint=['py-up', 'py-print __name__']) + self.assertMultilineMatches(bt, + r".*\nglobal '__name__' = '__main__'\n.*") + + @unittest.skipIf(python_is_optimized(), + "Python was compiled with optimizations") + def test_printing_builtin(self): + bt = self.get_stack_trace(script=SAMPLE_SCRIPT, + cmds_after_breakpoint=['py-up', 'py-print len']) + self.assertMultilineMatches(bt, + r".*\nbuiltin 'len' = \n.*") + +class PyLocalsTests(DebuggerTests): + @unittest.skipIf(python_is_optimized(), + "Python was compiled with optimizations") + def test_basic_command(self): + bt = self.get_stack_trace(script=SAMPLE_SCRIPT, + cmds_after_breakpoint=['py-up', 'py-locals']) + self.assertMultilineMatches(bt, + r".*\nargs = \(1, 2, 3\)\n.*") + + @unittest.skipUnless(HAS_PYUP_PYDOWN, "test requires py-up/py-down commands") + @unittest.skipIf(python_is_optimized(), + "Python was compiled with optimizations") + def test_locals_after_up(self): + bt = self.get_stack_trace(script=SAMPLE_SCRIPT, + cmds_after_breakpoint=['py-up', 'py-up', 'py-locals']) + self.assertMultilineMatches(bt, + r'''^.* +Locals for foo +a = 1 +b = 2 +c = 3 +Locals for +.*$''') diff --git a/Lib/test/test_gdb/test_pretty_print.py b/Lib/test/test_gdb/test_pretty_print.py new file mode 100644 index 00000000000000..dfc77d65ab16a4 --- /dev/null +++ b/Lib/test/test_gdb/test_pretty_print.py @@ -0,0 +1,438 @@ +import re +import sys +from test import support + +from .util import ( + BREAKPOINT_FN, GDB_VERSION, + run_gdb, setup_module, DebuggerTests) + + +def setUpModule(): + setup_module() + + +class PrettyPrintTests(DebuggerTests): + def get_gdb_repr(self, source, + cmds_after_breakpoint=None, + import_site=False): + # Given an input python source representation of data, + # run "python -c'id(DATA)'" under gdb with a breakpoint on + # builtin_id and scrape out gdb's representation of the "op" + # parameter, and verify that the gdb displays the same string + # + # Verify that the gdb displays the expected string + # + # For a nested structure, the first time we hit the breakpoint will + # give us the top-level structure + + # NOTE: avoid decoding too much of the traceback as some + # undecodable characters may lurk there in optimized mode + # (issue #19743). + cmds_after_breakpoint = cmds_after_breakpoint or ["backtrace 1"] + gdb_output = self.get_stack_trace(source, breakpoint=BREAKPOINT_FN, + cmds_after_breakpoint=cmds_after_breakpoint, + import_site=import_site) + # gdb can insert additional '\n' and space characters in various places + # in its output, depending on the width of the terminal it's connected + # to (using its "wrap_here" function) + m = re.search( + # Match '#0 builtin_id(self=..., v=...)' + r'#0\s+builtin_id\s+\(self\=.*,\s+v=\s*(.*?)?\)' + # Match ' at Python/bltinmodule.c'. + # bpo-38239: builtin_id() is defined in Python/bltinmodule.c, + # but accept any "Directory\file.c" to support Link Time + # Optimization (LTO). + r'\s+at\s+\S*[A-Za-z]+/[A-Za-z0-9_-]+\.c', + gdb_output, re.DOTALL) + if not m: + self.fail('Unexpected gdb output: %r\n%s' % (gdb_output, gdb_output)) + return m.group(1), gdb_output + + def test_getting_backtrace(self): + gdb_output = self.get_stack_trace('id(42)') + self.assertTrue(BREAKPOINT_FN in gdb_output) + + def assertGdbRepr(self, val, exp_repr=None): + # Ensure that gdb's rendering of the value in a debugged process + # matches repr(value) in this process: + gdb_repr, gdb_output = self.get_gdb_repr('id(' + ascii(val) + ')') + if not exp_repr: + exp_repr = repr(val) + self.assertEqual(gdb_repr, exp_repr, + ('%r did not equal expected %r; full output was:\n%s' + % (gdb_repr, exp_repr, gdb_output))) + + @support.requires_resource('cpu') + def test_int(self): + 'Verify the pretty-printing of various int values' + self.assertGdbRepr(42) + self.assertGdbRepr(0) + self.assertGdbRepr(-7) + self.assertGdbRepr(1000000000000) + self.assertGdbRepr(-1000000000000000) + + def test_singletons(self): + 'Verify the pretty-printing of True, False and None' + self.assertGdbRepr(True) + self.assertGdbRepr(False) + self.assertGdbRepr(None) + + def test_dicts(self): + 'Verify the pretty-printing of dictionaries' + self.assertGdbRepr({}) + self.assertGdbRepr({'foo': 'bar'}, "{'foo': 'bar'}") + # Python preserves insertion order since 3.6 + self.assertGdbRepr({'foo': 'bar', 'douglas': 42}, "{'foo': 'bar', 'douglas': 42}") + + def test_lists(self): + 'Verify the pretty-printing of lists' + self.assertGdbRepr([]) + self.assertGdbRepr(list(range(5))) + + @support.requires_resource('cpu') + def test_bytes(self): + 'Verify the pretty-printing of bytes' + self.assertGdbRepr(b'') + self.assertGdbRepr(b'And now for something hopefully the same') + self.assertGdbRepr(b'string with embedded NUL here \0 and then some more text') + self.assertGdbRepr(b'this is a tab:\t' + b' this is a slash-N:\n' + b' this is a slash-R:\r' + ) + + self.assertGdbRepr(b'this is byte 255:\xff and byte 128:\x80') + + self.assertGdbRepr(bytes([b for b in range(255)])) + + @support.requires_resource('cpu') + def test_strings(self): + 'Verify the pretty-printing of unicode strings' + # We cannot simply call locale.getpreferredencoding() here, + # as GDB might have been linked against a different version + # of Python with a different encoding and coercion policy + # with respect to PEP 538 and PEP 540. + stdout, stderr = run_gdb( + '--eval-command', + 'python import locale; print(locale.getpreferredencoding())') + + encoding = stdout + if stderr or not encoding: + raise RuntimeError( + f'unable to determine the Python locale preferred encoding ' + f'of embedded Python in GDB\n' + f'stdout={stdout!r}\n' + f'stderr={stderr!r}') + + def check_repr(text): + try: + text.encode(encoding) + except UnicodeEncodeError: + self.assertGdbRepr(text, ascii(text)) + else: + self.assertGdbRepr(text) + + self.assertGdbRepr('') + self.assertGdbRepr('And now for something hopefully the same') + self.assertGdbRepr('string with embedded NUL here \0 and then some more text') + + # Test printing a single character: + # U+2620 SKULL AND CROSSBONES + check_repr('\u2620') + + # Test printing a Japanese unicode string + # (I believe this reads "mojibake", using 3 characters from the CJK + # Unified Ideographs area, followed by U+3051 HIRAGANA LETTER KE) + check_repr('\u6587\u5b57\u5316\u3051') + + # Test a character outside the BMP: + # U+1D121 MUSICAL SYMBOL C CLEF + # This is: + # UTF-8: 0xF0 0x9D 0x84 0xA1 + # UTF-16: 0xD834 0xDD21 + check_repr(chr(0x1D121)) + + def test_tuples(self): + 'Verify the pretty-printing of tuples' + self.assertGdbRepr(tuple(), '()') + self.assertGdbRepr((1,), '(1,)') + self.assertGdbRepr(('foo', 'bar', 'baz')) + + @support.requires_resource('cpu') + def test_sets(self): + 'Verify the pretty-printing of sets' + if GDB_VERSION < (7, 3): + self.skipTest("pretty-printing of sets needs gdb 7.3 or later") + self.assertGdbRepr(set(), "set()") + self.assertGdbRepr(set(['a']), "{'a'}") + # PYTHONHASHSEED is need to get the exact frozenset item order + if not sys.flags.ignore_environment: + self.assertGdbRepr(set(['a', 'b']), "{'a', 'b'}") + self.assertGdbRepr(set([4, 5, 6]), "{4, 5, 6}") + + # Ensure that we handle sets containing the "dummy" key value, + # which happens on deletion: + gdb_repr, gdb_output = self.get_gdb_repr('''s = set(['a','b']) +s.remove('a') +id(s)''') + self.assertEqual(gdb_repr, "{'b'}") + + @support.requires_resource('cpu') + def test_frozensets(self): + 'Verify the pretty-printing of frozensets' + if GDB_VERSION < (7, 3): + self.skipTest("pretty-printing of frozensets needs gdb 7.3 or later") + self.assertGdbRepr(frozenset(), "frozenset()") + self.assertGdbRepr(frozenset(['a']), "frozenset({'a'})") + # PYTHONHASHSEED is need to get the exact frozenset item order + if not sys.flags.ignore_environment: + self.assertGdbRepr(frozenset(['a', 'b']), "frozenset({'a', 'b'})") + self.assertGdbRepr(frozenset([4, 5, 6]), "frozenset({4, 5, 6})") + + def test_exceptions(self): + # Test a RuntimeError + gdb_repr, gdb_output = self.get_gdb_repr(''' +try: + raise RuntimeError("I am an error") +except RuntimeError as e: + id(e) +''') + self.assertEqual(gdb_repr, + "RuntimeError('I am an error',)") + + + # Test division by zero: + gdb_repr, gdb_output = self.get_gdb_repr(''' +try: + a = 1 / 0 +except ZeroDivisionError as e: + id(e) +''') + self.assertEqual(gdb_repr, + "ZeroDivisionError('division by zero',)") + + def test_modern_class(self): + 'Verify the pretty-printing of new-style class instances' + gdb_repr, gdb_output = self.get_gdb_repr(''' +class Foo: + pass +foo = Foo() +foo.an_int = 42 +id(foo)''') + m = re.match(r'', gdb_repr) + self.assertTrue(m, + msg='Unexpected new-style class rendering %r' % gdb_repr) + + def test_subclassing_list(self): + 'Verify the pretty-printing of an instance of a list subclass' + gdb_repr, gdb_output = self.get_gdb_repr(''' +class Foo(list): + pass +foo = Foo() +foo += [1, 2, 3] +foo.an_int = 42 +id(foo)''') + m = re.match(r'', gdb_repr) + + self.assertTrue(m, + msg='Unexpected new-style class rendering %r' % gdb_repr) + + def test_subclassing_tuple(self): + 'Verify the pretty-printing of an instance of a tuple subclass' + # This should exercise the negative tp_dictoffset code in the + # new-style class support + gdb_repr, gdb_output = self.get_gdb_repr(''' +class Foo(tuple): + pass +foo = Foo((1, 2, 3)) +foo.an_int = 42 +id(foo)''') + m = re.match(r'', gdb_repr) + + self.assertTrue(m, + msg='Unexpected new-style class rendering %r' % gdb_repr) + + def assertSane(self, source, corruption, exprepr=None): + '''Run Python under gdb, corrupting variables in the inferior process + immediately before taking a backtrace. + + Verify that the variable's representation is the expected failsafe + representation''' + if corruption: + cmds_after_breakpoint=[corruption, 'backtrace'] + else: + cmds_after_breakpoint=['backtrace'] + + gdb_repr, gdb_output = \ + self.get_gdb_repr(source, + cmds_after_breakpoint=cmds_after_breakpoint) + if exprepr: + if gdb_repr == exprepr: + # gdb managed to print the value in spite of the corruption; + # this is good (see http://bugs.python.org/issue8330) + return + + # Match anything for the type name; 0xDEADBEEF could point to + # something arbitrary (see http://bugs.python.org/issue8330) + pattern = '<.* at remote 0x-?[0-9a-f]+>' + + m = re.match(pattern, gdb_repr) + if not m: + self.fail('Unexpected gdb representation: %r\n%s' % \ + (gdb_repr, gdb_output)) + + def test_NULL_ptr(self): + 'Ensure that a NULL PyObject* is handled gracefully' + gdb_repr, gdb_output = ( + self.get_gdb_repr('id(42)', + cmds_after_breakpoint=['set variable v=0', + 'backtrace']) + ) + + self.assertEqual(gdb_repr, '0x0') + + def test_NULL_ob_type(self): + 'Ensure that a PyObject* with NULL ob_type is handled gracefully' + self.assertSane('id(42)', + 'set v->ob_type=0') + + def test_corrupt_ob_type(self): + 'Ensure that a PyObject* with a corrupt ob_type is handled gracefully' + self.assertSane('id(42)', + 'set v->ob_type=0xDEADBEEF', + exprepr='42') + + def test_corrupt_tp_flags(self): + 'Ensure that a PyObject* with a type with corrupt tp_flags is handled' + self.assertSane('id(42)', + 'set v->ob_type->tp_flags=0x0', + exprepr='42') + + def test_corrupt_tp_name(self): + 'Ensure that a PyObject* with a type with corrupt tp_name is handled' + self.assertSane('id(42)', + 'set v->ob_type->tp_name=0xDEADBEEF', + exprepr='42') + + def test_builtins_help(self): + 'Ensure that the new-style class _Helper in site.py can be handled' + + if sys.flags.no_site: + self.skipTest("need site module, but -S option was used") + + # (this was the issue causing tracebacks in + # http://bugs.python.org/issue8032#msg100537 ) + gdb_repr, gdb_output = self.get_gdb_repr('id(__builtins__.help)', import_site=True) + + m = re.match(r'<_Helper\(\) at remote 0x-?[0-9a-f]+>', gdb_repr) + self.assertTrue(m, + msg='Unexpected rendering %r' % gdb_repr) + + def test_selfreferential_list(self): + '''Ensure that a reference loop involving a list doesn't lead proxyval + into an infinite loop:''' + gdb_repr, gdb_output = \ + self.get_gdb_repr("a = [3, 4, 5] ; a.append(a) ; id(a)") + self.assertEqual(gdb_repr, '[3, 4, 5, [...]]') + + gdb_repr, gdb_output = \ + self.get_gdb_repr("a = [3, 4, 5] ; b = [a] ; a.append(b) ; id(a)") + self.assertEqual(gdb_repr, '[3, 4, 5, [[...]]]') + + def test_selfreferential_dict(self): + '''Ensure that a reference loop involving a dict doesn't lead proxyval + into an infinite loop:''' + gdb_repr, gdb_output = \ + self.get_gdb_repr("a = {} ; b = {'bar':a} ; a['foo'] = b ; id(a)") + + self.assertEqual(gdb_repr, "{'foo': {'bar': {...}}}") + + def test_selfreferential_old_style_instance(self): + gdb_repr, gdb_output = \ + self.get_gdb_repr(''' +class Foo: + pass +foo = Foo() +foo.an_attr = foo +id(foo)''') + self.assertTrue(re.match(r'\) at remote 0x-?[0-9a-f]+>', + gdb_repr), + 'Unexpected gdb representation: %r\n%s' % \ + (gdb_repr, gdb_output)) + + def test_selfreferential_new_style_instance(self): + gdb_repr, gdb_output = \ + self.get_gdb_repr(''' +class Foo(object): + pass +foo = Foo() +foo.an_attr = foo +id(foo)''') + self.assertTrue(re.match(r'\) at remote 0x-?[0-9a-f]+>', + gdb_repr), + 'Unexpected gdb representation: %r\n%s' % \ + (gdb_repr, gdb_output)) + + gdb_repr, gdb_output = \ + self.get_gdb_repr(''' +class Foo(object): + pass +a = Foo() +b = Foo() +a.an_attr = b +b.an_attr = a +id(a)''') + self.assertTrue(re.match(r'\) at remote 0x-?[0-9a-f]+>\) at remote 0x-?[0-9a-f]+>', + gdb_repr), + 'Unexpected gdb representation: %r\n%s' % \ + (gdb_repr, gdb_output)) + + def test_truncation(self): + 'Verify that very long output is truncated' + gdb_repr, gdb_output = self.get_gdb_repr('id(list(range(1000)))') + self.assertEqual(gdb_repr, + "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, " + "14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, " + "27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, " + "40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, " + "53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, " + "66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, " + "79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, " + "92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, " + "104, 105, 106, 107, 108, 109, 110, 111, 112, 113, " + "114, 115, 116, 117, 118, 119, 120, 121, 122, 123, " + "124, 125, 126, 127, 128, 129, 130, 131, 132, 133, " + "134, 135, 136, 137, 138, 139, 140, 141, 142, 143, " + "144, 145, 146, 147, 148, 149, 150, 151, 152, 153, " + "154, 155, 156, 157, 158, 159, 160, 161, 162, 163, " + "164, 165, 166, 167, 168, 169, 170, 171, 172, 173, " + "174, 175, 176, 177, 178, 179, 180, 181, 182, 183, " + "184, 185, 186, 187, 188, 189, 190, 191, 192, 193, " + "194, 195, 196, 197, 198, 199, 200, 201, 202, 203, " + "204, 205, 206, 207, 208, 209, 210, 211, 212, 213, " + "214, 215, 216, 217, 218, 219, 220, 221, 222, 223, " + "224, 225, 226...(truncated)") + self.assertEqual(len(gdb_repr), + 1024 + len('...(truncated)')) + + def test_builtin_method(self): + gdb_repr, gdb_output = self.get_gdb_repr('import sys; id(sys.stdout.readlines)') + self.assertTrue(re.match(r'', + gdb_repr), + 'Unexpected gdb representation: %r\n%s' % \ + (gdb_repr, gdb_output)) + + def test_frames(self): + gdb_output = self.get_stack_trace(''' +import sys +def foo(a, b, c): + return sys._getframe(0) + +f = foo(3, 4, 5) +id(f)''', + breakpoint='builtin_id', + cmds_after_breakpoint=['print (PyFrameObject*)v'] + ) + self.assertTrue(re.match(r'.*\s+\$1 =\s+Frame 0x-?[0-9a-f]+, for file , line 4, in foo \(a=3.*', + gdb_output, + re.DOTALL), + 'Unexpected gdb representation: %r\n%s' % (gdb_output, gdb_output)) diff --git a/Lib/test/test_gdb/util.py b/Lib/test/test_gdb/util.py new file mode 100644 index 00000000000000..8fe9cfc543395e --- /dev/null +++ b/Lib/test/test_gdb/util.py @@ -0,0 +1,291 @@ +import os +import re +import shlex +import shutil +import subprocess +import sys +import sysconfig +import unittest +from test import support + + +GDB_PROGRAM = shutil.which('gdb') or 'gdb' + +# Location of custom hooks file in a repository checkout. +CHECKOUT_HOOK_PATH = os.path.join(os.path.dirname(sys.executable), + 'python-gdb.py') + +SAMPLE_SCRIPT = os.path.join(os.path.dirname(__file__), 'gdb_sample.py') +BREAKPOINT_FN = 'builtin_id' + +PYTHONHASHSEED = '123' + + +def clean_environment(): + # Remove PYTHON* environment variables such as PYTHONHOME + return {name: value for name, value in os.environ.items() + if not name.startswith('PYTHON')} + + +# Temporary value until it's initialized by get_gdb_version() below +GDB_VERSION = (0, 0) + +def run_gdb(*args, exitcode=0, check=True, **env_vars): + """Runs gdb in --batch mode with the additional arguments given by *args. + + Returns its (stdout, stderr) decoded from utf-8 using the replace handler. + """ + env = clean_environment() + if env_vars: + env.update(env_vars) + + cmd = [GDB_PROGRAM, + # Batch mode: Exit after processing all the command files + # specified with -x/--command + '--batch', + # -nx: Do not execute commands from any .gdbinit initialization + # files (gh-66384) + '-nx'] + if GDB_VERSION >= (7, 4): + cmd.extend(('--init-eval-command', + f'add-auto-load-safe-path {CHECKOUT_HOOK_PATH}')) + cmd.extend(args) + + proc = subprocess.run( + cmd, + # Redirect stdin to prevent gdb from messing with the terminal settings + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + encoding="utf8", errors="backslashreplace", + env=env) + + stdout = proc.stdout + stderr = proc.stderr + if check and proc.returncode != exitcode: + cmd_text = shlex.join(cmd) + raise Exception(f"{cmd_text} failed with exit code {proc.returncode}, " + f"expected exit code {exitcode}:\n" + f"stdout={stdout!r}\n" + f"stderr={stderr!r}") + + return (stdout, stderr) + + +def get_gdb_version(): + try: + stdout, stderr = run_gdb('--version') + except OSError as exc: + # This is what "no gdb" looks like. There may, however, be other + # errors that manifest this way too. + raise unittest.SkipTest(f"Couldn't find gdb program on the path: {exc}") + + # Regex to parse: + # 'GNU gdb (GDB; SUSE Linux Enterprise 12) 7.7\n' -> 7.7 + # 'GNU gdb (GDB) Fedora 7.9.1-17.fc22\n' -> 7.9 + # 'GNU gdb 6.1.1 [FreeBSD]\n' -> 6.1 + # 'GNU gdb (GDB) Fedora (7.5.1-37.fc18)\n' -> 7.5 + # 'HP gdb 6.7 for HP Itanium (32 or 64 bit) and target HP-UX 11iv2 and 11iv3.\n' -> 6.7 + match = re.search(r"^(?:GNU|HP) gdb.*?\b(\d+)\.(\d+)", stdout) + if match is None: + raise Exception("unable to parse gdb version: %r" % stdout) + version_text = stdout + major = int(match.group(1)) + minor = int(match.group(2)) + version = (major, minor) + return (version_text, version) + +GDB_VERSION_TEXT, GDB_VERSION = get_gdb_version() +if GDB_VERSION < (7, 0): + raise unittest.SkipTest( + f"gdb versions before 7.0 didn't support python embedding. " + f"Saw gdb version {GDB_VERSION[0]}.{GDB_VERSION[1]}:\n" + f"{GDB_VERSION_TEXT}") + + +def check_usable_gdb(): + # Verify that "gdb" was built with the embedded Python support enabled and + # verify that "gdb" can load our custom hooks, as OS security settings may + # disallow this without a customized .gdbinit. + stdout, stderr = run_gdb( + '--eval-command=python import sys; print(sys.version_info)', + '--args', sys.executable, + check=False) + + if "auto-loading has been declined" in stderr: + raise unittest.SkipTest( + f"gdb security settings prevent use of custom hooks; " + f"stderr: {stderr!r}") + + if not stdout: + raise unittest.SkipTest( + f"gdb not built with embedded python support; " + f"stderr: {stderr!r}") + + if "major=2" in stdout: + raise unittest.SkipTest("gdb built with Python 2") + +check_usable_gdb() + + +# Control-flow enforcement technology +def cet_protection(): + cflags = sysconfig.get_config_var('CFLAGS') + if not cflags: + return False + flags = cflags.split() + # True if "-mcet -fcf-protection" options are found, but false + # if "-fcf-protection=none" or "-fcf-protection=return" is found. + return (('-mcet' in flags) + and any((flag.startswith('-fcf-protection') + and not flag.endswith(("=none", "=return"))) + for flag in flags)) +CET_PROTECTION = cet_protection() + + +def setup_module(): + if support.verbose: + print(f"gdb version {GDB_VERSION[0]}.{GDB_VERSION[1]}:") + for line in GDB_VERSION_TEXT.splitlines(): + print(" " * 4 + line) + print(f" path: {GDB_PROGRAM}") + print() + + +class DebuggerTests(unittest.TestCase): + + """Test that the debugger can debug Python.""" + + def get_stack_trace(self, source=None, script=None, + breakpoint=BREAKPOINT_FN, + cmds_after_breakpoint=None, + import_site=False, + ignore_stderr=False): + ''' + Run 'python -c SOURCE' under gdb with a breakpoint. + + Support injecting commands after the breakpoint is reached + + Returns the stdout from gdb + + cmds_after_breakpoint: if provided, a list of strings: gdb commands + ''' + # We use "set breakpoint pending yes" to avoid blocking with a: + # Function "foo" not defined. + # Make breakpoint pending on future shared library load? (y or [n]) + # error, which typically happens python is dynamically linked (the + # breakpoints of interest are to be found in the shared library) + # When this happens, we still get: + # Function "textiowrapper_write" not defined. + # emitted to stderr each time, alas. + + # Initially I had "--eval-command=continue" here, but removed it to + # avoid repeated print breakpoints when traversing hierarchical data + # structures + + # Generate a list of commands in gdb's language: + commands = [ + 'set breakpoint pending yes', + 'break %s' % breakpoint, + + # The tests assume that the first frame of printed + # backtrace will not contain program counter, + # that is however not guaranteed by gdb + # therefore we need to use 'set print address off' to + # make sure the counter is not there. For example: + # #0 in PyObject_Print ... + # is assumed, but sometimes this can be e.g. + # #0 0x00003fffb7dd1798 in PyObject_Print ... + 'set print address off', + + 'run', + ] + + # GDB as of 7.4 onwards can distinguish between the + # value of a variable at entry vs current value: + # http://sourceware.org/gdb/onlinedocs/gdb/Variables.html + # which leads to the selftests failing with errors like this: + # AssertionError: 'v@entry=()' != '()' + # Disable this: + if GDB_VERSION >= (7, 4): + commands += ['set print entry-values no'] + + if cmds_after_breakpoint: + if CET_PROTECTION: + # bpo-32962: When Python is compiled with -mcet + # -fcf-protection, function arguments are unusable before + # running the first instruction of the function entry point. + # The 'next' command makes the required first step. + commands += ['next'] + commands += cmds_after_breakpoint + else: + commands += ['backtrace'] + + # print commands + + # Use "commands" to generate the arguments with which to invoke "gdb": + args = ['--eval-command=%s' % cmd for cmd in commands] + args += ["--args", + sys.executable] + args.extend(subprocess._args_from_interpreter_flags()) + + if not import_site: + # -S suppresses the default 'import site' + args += ["-S"] + + if source: + args += ["-c", source] + elif script: + args += [script] + + # Use "args" to invoke gdb, capturing stdout, stderr: + out, err = run_gdb(*args, PYTHONHASHSEED=PYTHONHASHSEED) + + if not ignore_stderr: + for line in err.splitlines(): + print(line, file=sys.stderr) + + # bpo-34007: Sometimes some versions of the shared libraries that + # are part of the traceback are compiled in optimised mode and the + # Program Counter (PC) is not present, not allowing gdb to walk the + # frames back. When this happens, the Python bindings of gdb raise + # an exception, making the test impossible to succeed. + if "PC not saved" in err: + raise unittest.SkipTest("gdb cannot walk the frame object" + " because the Program Counter is" + " not present") + + # bpo-40019: Skip the test if gdb failed to read debug information + # because the Python binary is optimized. + for pattern in ( + '(frame information optimized out)', + 'Unable to read information on python frame', + + # gh-91960: On Python built with "clang -Og", gdb gets + # "frame=" for _PyEval_EvalFrameDefault() parameter + '(unable to read python frame information)', + + # gh-104736: On Python built with "clang -Og" on ppc64le, + # "py-bt" displays a truncated or not traceback, but "where" + # logs this error message: + 'Backtrace stopped: frame did not save the PC', + + # gh-104736: When "bt" command displays something like: + # "#1 0x0000000000000000 in ?? ()", the traceback is likely + # truncated or wrong. + ' ?? ()', + ): + if pattern in out: + raise unittest.SkipTest(f"{pattern!r} found in gdb output") + + return out + + def assertEndsWith(self, actual, exp_end): + '''Ensure that the given "actual" string ends with "exp_end"''' + self.assertTrue(actual.endswith(exp_end), + msg='%r did not end with %r' % (actual, exp_end)) + + def assertMultilineMatches(self, actual, pattern): + m = re.match(pattern, actual, re.DOTALL) + if not m: + self.fail(msg='%r did not match %r' % (actual, pattern)) diff --git a/Lib/test/test_generated_cases.py b/Lib/test/test_generated_cases.py index 54378fced54699..3b2f579be684b7 100644 --- a/Lib/test/test_generated_cases.py +++ b/Lib/test/test_generated_cases.py @@ -1,50 +1,64 @@ +import contextlib +import os +import sys import tempfile import unittest -import os +from test import support from test import test_tools + +def skip_if_different_mount_drives(): + if sys.platform != 'win32': + return + ROOT = os.path.dirname(os.path.dirname(__file__)) + root_drive = os.path.splitroot(ROOT)[0] + cwd_drive = os.path.splitroot(os.getcwd())[0] + if root_drive != cwd_drive: + # May raise ValueError if ROOT and the current working + # different have different mount drives (on Windows). + raise unittest.SkipTest( + f"the current working directory and the Python source code " + f"directory have different mount drives " + f"({cwd_drive} and {root_drive})" + ) +skip_if_different_mount_drives() + + test_tools.skip_if_missing('cases_generator') with test_tools.imports_under_tool('cases_generator'): - import generate_cases - import analysis - import formatting - from parsing import StackEffect + from analyzer import StackItem + import parser + from stack import Stack + import tier1_generator +def handle_stderr(): + if support.verbose > 1: + return contextlib.nullcontext() + else: + return support.captured_stderr() + class TestEffects(unittest.TestCase): def test_effect_sizes(self): - input_effects = [ - x := StackEffect("x", "", "", ""), - y := StackEffect("y", "", "", "oparg"), - z := StackEffect("z", "", "", "oparg*2"), - ] - output_effects = [ - StackEffect("a", "", "", ""), - StackEffect("b", "", "", "oparg*4"), - StackEffect("c", "", "", ""), + stack = Stack() + inputs = [ + x:= StackItem("x", None, "", "1"), + y:= StackItem("y", None, "", "oparg"), + z:= StackItem("z", None, "", "oparg*2"), ] - other_effects = [ - StackEffect("p", "", "", "oparg<<1"), - StackEffect("q", "", "", ""), - StackEffect("r", "", "", ""), + outputs = [ + StackItem("x", None, "", "1"), + StackItem("b", None, "", "oparg*4"), + StackItem("c", None, "", "1"), ] - self.assertEqual(formatting.effect_size(x), (1, "")) - self.assertEqual(formatting.effect_size(y), (0, "oparg")) - self.assertEqual(formatting.effect_size(z), (0, "oparg*2")) - - self.assertEqual( - formatting.list_effect_size(input_effects), - (1, "oparg + oparg*2"), - ) - self.assertEqual( - formatting.list_effect_size(output_effects), - (2, "oparg*4"), - ) - self.assertEqual( - formatting.list_effect_size(other_effects), - (2, "(oparg<<1)"), - ) + stack.pop(z) + stack.pop(y) + stack.pop(x) + for out in outputs: + stack.push(out) + self.assertEqual(stack.base_offset.to_c(), "-1 - oparg*2 - oparg") + self.assertEqual(stack.top_offset.to_c(), "1 - oparg*2 - oparg + oparg*4") class TestGeneratedCases(unittest.TestCase): @@ -75,31 +89,33 @@ def tearDown(self) -> None: def run_cases_test(self, input: str, expected: str): with open(self.temp_input_filename, "w+") as temp_input: - temp_input.write(analysis.BEGIN_MARKER) + temp_input.write(parser.BEGIN_MARKER) temp_input.write(input) - temp_input.write(analysis.END_MARKER) + temp_input.write(parser.END_MARKER) temp_input.flush() - a = generate_cases.Generator([self.temp_input_filename]) - a.parse() - a.analyze() - if a.errors: - raise RuntimeError(f"Found {a.errors} errors") - a.write_instructions(self.temp_output_filename, False) + with handle_stderr(): + tier1_generator.generate_tier1_from_files( + [self.temp_input_filename], + self.temp_output_filename, + False + ) with open(self.temp_output_filename) as temp_output: lines = temp_output.readlines() - while lines and lines[0].startswith("// "): + while lines and lines[0].startswith(("// ", "#", " #", "\n")): lines.pop(0) + while lines and lines[-1].startswith(("#", "\n")): + lines.pop(-1) actual = "".join(lines) - # if actual.rstrip() != expected.rstrip(): + # if actual.strip() != expected.strip(): # print("Actual:") # print(actual) # print("Expected:") # print(expected) # print("End") - self.assertEqual(actual.rstrip(), expected.rstrip()) + self.assertEqual(actual.strip(), expected.strip()) def test_inst_no_args(self): input = """ @@ -109,6 +125,9 @@ def test_inst_no_args(self): """ output = """ TARGET(OP) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(OP); spam(); DISPATCH(); } @@ -123,10 +142,13 @@ def test_inst_one_pop(self): """ output = """ TARGET(OP) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(OP); PyObject *value; value = stack_pointer[-1]; spam(); - STACK_SHRINK(1); + stack_pointer += -1; DISPATCH(); } """ @@ -140,10 +162,13 @@ def test_inst_one_push(self): """ output = """ TARGET(OP) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(OP); PyObject *res; spam(); - STACK_GROW(1); - stack_pointer[-1] = res; + stack_pointer[0] = res; + stack_pointer += 1; DISPATCH(); } """ @@ -157,6 +182,9 @@ def test_inst_one_push_one_pop(self): """ output = """ TARGET(OP) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(OP); PyObject *value; PyObject *res; value = stack_pointer[-1]; @@ -175,14 +203,17 @@ def test_binary_op(self): """ output = """ TARGET(OP) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(OP); PyObject *right; PyObject *left; PyObject *res; right = stack_pointer[-1]; left = stack_pointer[-2]; spam(); - STACK_SHRINK(1); - stack_pointer[-1] = res; + stack_pointer[-2] = res; + stack_pointer += -1; DISPATCH(); } """ @@ -196,6 +227,9 @@ def test_overlap(self): """ output = """ TARGET(OP) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(OP); PyObject *right; PyObject *left; PyObject *result; @@ -210,20 +244,32 @@ def test_overlap(self): def test_predictions_and_eval_breaker(self): input = """ - inst(OP1, (--)) { + inst(OP1, (arg -- rest)) { } inst(OP3, (arg -- res)) { - DEOPT_IF(xxx, OP1); + DEOPT_IF(xxx); CHECK_EVAL_BREAKER(); } + family(OP1, INLINE_CACHE_ENTRIES_OP1) = { OP3 }; """ output = """ TARGET(OP1) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(OP1); PREDICTED(OP1); + PyObject *arg; + PyObject *rest; + arg = stack_pointer[-1]; + stack_pointer[-1] = rest; DISPATCH(); } TARGET(OP3) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(OP3); + static_assert(INLINE_CACHE_ENTRIES_OP1 == 0, "incorrect cache size"); PyObject *arg; PyObject *res; arg = stack_pointer[-1]; @@ -243,6 +289,9 @@ def test_error_if_plain(self): """ output = """ TARGET(OP) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(OP); if (cond) goto label; DISPATCH(); } @@ -257,7 +306,11 @@ def test_error_if_plain_with_comment(self): """ output = """ TARGET(OP) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(OP); if (cond) goto label; + // Comment is ok DISPATCH(); } """ @@ -271,14 +324,17 @@ def test_error_if_pop(self): """ output = """ TARGET(OP) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(OP); PyObject *right; PyObject *left; PyObject *res; right = stack_pointer[-1]; left = stack_pointer[-2]; if (cond) goto pop_2_label; - STACK_SHRINK(1); - stack_pointer[-1] = res; + stack_pointer[-2] = res; + stack_pointer += -1; DISPATCH(); } """ @@ -291,12 +347,14 @@ def test_cache_effect(self): """ output = """ TARGET(OP) { + _Py_CODEUNIT *this_instr = frame->instr_ptr = next_instr; + next_instr += 4; + INSTRUCTION_STATS(OP); PyObject *value; value = stack_pointer[-1]; - uint16_t counter = read_u16(&next_instr[0].cache); - uint32_t extra = read_u32(&next_instr[1].cache); - STACK_SHRINK(1); - next_instr += 3; + uint16_t counter = read_u16(&this_instr[1].cache); + uint32_t extra = read_u32(&this_instr[2].cache); + stack_pointer += -1; DISPATCH(); } """ @@ -310,6 +368,9 @@ def test_suppress_dispatch(self): """ output = """ TARGET(OP) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(OP); goto somewhere; } """ @@ -330,54 +391,121 @@ def test_macro_instruction(self): family(OP, INLINE_CACHE_ENTRIES_OP) = { OP3 }; """ output = """ - TARGET(OP1) { - PyObject *right; - PyObject *left; - right = stack_pointer[-1]; - left = stack_pointer[-2]; - uint16_t counter = read_u16(&next_instr[0].cache); - op1(left, right); - next_instr += 1; - DISPATCH(); - } - TARGET(OP) { - static_assert(INLINE_CACHE_ENTRIES_OP == 5, "incorrect cache size"); + frame->instr_ptr = next_instr; + next_instr += 6; + INSTRUCTION_STATS(OP); + PREDICTED(OP); + _Py_CODEUNIT *this_instr = next_instr - 6; PyObject *right; PyObject *left; PyObject *arg2; PyObject *res; - // OP1 + // _OP1 right = stack_pointer[-1]; left = stack_pointer[-2]; { - uint16_t counter = read_u16(&next_instr[0].cache); + uint16_t counter = read_u16(&this_instr[1].cache); op1(left, right); } + /* Skip 2 cache entries */ // OP2 arg2 = stack_pointer[-3]; { - uint32_t extra = read_u32(&next_instr[3].cache); + uint32_t extra = read_u32(&this_instr[4].cache); res = op2(arg2, left, right); } - STACK_SHRINK(2); - stack_pointer[-1] = res; - next_instr += 5; + stack_pointer[-3] = res; + stack_pointer += -2; + DISPATCH(); + } + + TARGET(OP1) { + _Py_CODEUNIT *this_instr = frame->instr_ptr = next_instr; + next_instr += 2; + INSTRUCTION_STATS(OP1); + PyObject *right; + PyObject *left; + right = stack_pointer[-1]; + left = stack_pointer[-2]; + uint16_t counter = read_u16(&this_instr[1].cache); + op1(left, right); DISPATCH(); } TARGET(OP3) { + frame->instr_ptr = next_instr; + next_instr += 6; + INSTRUCTION_STATS(OP3); + static_assert(INLINE_CACHE_ENTRIES_OP == 5, "incorrect cache size"); PyObject *right; PyObject *left; PyObject *arg2; PyObject *res; + /* Skip 5 cache entries */ right = stack_pointer[-1]; left = stack_pointer[-2]; arg2 = stack_pointer[-3]; res = op3(arg2, left, right); - STACK_SHRINK(2); - stack_pointer[-1] = res; - next_instr += 5; + stack_pointer[-3] = res; + stack_pointer += -2; + DISPATCH(); + } + """ + self.run_cases_test(input, output) + + def test_unused_caches(self): + input = """ + inst(OP, (unused/1, unused/2 --)) { + body(); + } + """ + output = """ + TARGET(OP) { + frame->instr_ptr = next_instr; + next_instr += 4; + INSTRUCTION_STATS(OP); + /* Skip 1 cache entry */ + /* Skip 2 cache entries */ + body(); + DISPATCH(); + } + """ + self.run_cases_test(input, output) + + def test_pseudo_instruction_no_flags(self): + input = """ + pseudo(OP) = { + OP1, + }; + + inst(OP1, (--)) { + } + """ + output = """ + TARGET(OP1) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(OP1); + DISPATCH(); + } + """ + self.run_cases_test(input, output) + + def test_pseudo_instruction_with_flags(self): + input = """ + pseudo(OP, (HAS_ARG, HAS_JUMP)) = { + OP1, + }; + + inst(OP1, (--)) { + } + """ + output = """ + TARGET(OP1) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(OP1); DISPATCH(); } """ @@ -391,15 +519,17 @@ def test_array_input(self): """ output = """ TARGET(OP) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(OP); PyObject *above; PyObject **values; PyObject *below; above = stack_pointer[-1]; - values = stack_pointer - 1 - oparg*2; + values = &stack_pointer[-1 - oparg*2]; below = stack_pointer[-2 - oparg*2]; spam(); - STACK_SHRINK(oparg*2); - STACK_SHRINK(2); + stack_pointer += -2 - oparg*2; DISPATCH(); } """ @@ -413,14 +543,17 @@ def test_array_output(self): """ output = """ TARGET(OP) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(OP); PyObject *below; PyObject **values; PyObject *above; - values = stack_pointer - 1; + values = &stack_pointer[-1]; spam(values, oparg); - STACK_GROW(oparg*3); - stack_pointer[-2 - oparg*3] = below; - stack_pointer[-1] = above; + stack_pointer[-2] = below; + stack_pointer[-1 + oparg*3] = above; + stack_pointer += oparg*3; DISPATCH(); } """ @@ -434,12 +567,15 @@ def test_array_input_output(self): """ output = """ TARGET(OP) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(OP); PyObject **values; PyObject *above; - values = stack_pointer - oparg; + values = &stack_pointer[-oparg]; spam(values, oparg); - STACK_GROW(1); - stack_pointer[-1] = above; + stack_pointer[0] = above; + stack_pointer += 1; DISPATCH(); } """ @@ -453,13 +589,15 @@ def test_array_error_if(self): """ output = """ TARGET(OP) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(OP); PyObject **values; PyObject *extra; - values = stack_pointer - oparg; + values = &stack_pointer[-oparg]; extra = stack_pointer[-1 - oparg]; - if (oparg == 0) { STACK_SHRINK(oparg); goto pop_1_somewhere; } - STACK_SHRINK(oparg); - STACK_SHRINK(1); + if (oparg == 0) { stack_pointer += -1 - oparg; goto somewhere; } + stack_pointer += -1 - oparg; DISPATCH(); } """ @@ -473,6 +611,9 @@ def test_cond_effect(self): """ output = """ TARGET(OP) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(OP); PyObject *cc; PyObject *input = NULL; PyObject *aa; @@ -480,14 +621,13 @@ def test_cond_effect(self): PyObject *output = NULL; PyObject *zz; cc = stack_pointer[-1]; - if ((oparg & 1) == 1) { input = stack_pointer[-1 - ((oparg & 1) == 1 ? 1 : 0)]; } - aa = stack_pointer[-2 - ((oparg & 1) == 1 ? 1 : 0)]; + if ((oparg & 1) == 1) { input = stack_pointer[-1 - (((oparg & 1) == 1) ? 1 : 0)]; } + aa = stack_pointer[-2 - (((oparg & 1) == 1) ? 1 : 0)]; output = spam(oparg, input); - STACK_SHRINK((((oparg & 1) == 1) ? 1 : 0)); - STACK_GROW(((oparg & 2) ? 1 : 0)); - stack_pointer[-2 - (oparg & 2 ? 1 : 0)] = xx; - if (oparg & 2) { stack_pointer[-1 - (oparg & 2 ? 1 : 0)] = output; } - stack_pointer[-1] = zz; + stack_pointer[-2 - (((oparg & 1) == 1) ? 1 : 0)] = xx; + if (oparg & 2) stack_pointer[-1 - (((oparg & 1) == 1) ? 1 : 0)] = output; + stack_pointer[-1 - (((oparg & 1) == 1) ? 1 : 0) + ((oparg & 2) ? 1 : 0)] = zz; + stack_pointer += -(((oparg & 1) == 1) ? 1 : 0) + ((oparg & 2) ? 1 : 0); DISPATCH(); } """ @@ -505,6 +645,9 @@ def test_macro_cond_effect(self): """ output = """ TARGET(M) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(M); PyObject *right; PyObject *middle; PyObject *left; @@ -522,16 +665,132 @@ def test_macro_cond_effect(self): { # Body of B } - STACK_SHRINK(1); - STACK_GROW((oparg ? 1 : 0)); - stack_pointer[-2 - (oparg ? 1 : 0)] = deep; - if (oparg) { stack_pointer[-1 - (oparg ? 1 : 0)] = extra; } - stack_pointer[-1] = res; + stack_pointer[-3] = deep; + if (oparg) stack_pointer[-2] = extra; + stack_pointer[-2 + ((oparg) ? 1 : 0)] = res; + stack_pointer += -1 + ((oparg) ? 1 : 0); DISPATCH(); } """ self.run_cases_test(input, output) + def test_macro_push_push(self): + input = """ + op(A, (-- val1)) { + val1 = spam(); + } + op(B, (-- val2)) { + val2 = spam(); + } + macro(M) = A + B; + """ + output = """ + TARGET(M) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(M); + PyObject *val1; + PyObject *val2; + // A + { + val1 = spam(); + } + // B + { + val2 = spam(); + } + stack_pointer[0] = val1; + stack_pointer[1] = val2; + stack_pointer += 2; + DISPATCH(); + } + """ + self.run_cases_test(input, output) + + def test_override_inst(self): + input = """ + inst(OP, (--)) { + spam(); + } + override inst(OP, (--)) { + ham(); + } + """ + output = """ + TARGET(OP) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(OP); + ham(); + DISPATCH(); + } + """ + self.run_cases_test(input, output) + + def test_override_op(self): + input = """ + op(OP, (--)) { + spam(); + } + macro(M) = OP; + override op(OP, (--)) { + ham(); + } + """ + output = """ + TARGET(M) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(M); + ham(); + DISPATCH(); + } + """ + self.run_cases_test(input, output) + + def test_annotated_inst(self): + input = """ + guard inst(OP, (--)) { + ham(); + } + """ + output = """ + TARGET(OP) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(OP); + ham(); + DISPATCH(); + } + """ + self.run_cases_test(input, output) + + def test_annotated_op(self): + input = """ + guard op(OP, (--)) { + spam(); + } + macro(M) = OP; + """ + output = """ + TARGET(M) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(M); + spam(); + DISPATCH(); + } + """ + self.run_cases_test(input, output) + + input = """ + guard register specializing op(OP, (--)) { + spam(); + } + macro(M) = OP; + """ + self.run_cases_test(input, output) + if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_generators.py b/Lib/test/test_generators.py index a8a344ab8de48d..d48f0d47ba1962 100644 --- a/Lib/test/test_generators.py +++ b/Lib/test/test_generators.py @@ -2258,6 +2258,7 @@ def printsolution(self, x): caught ValueError (xyz) >>> import warnings +>>> old_filters = warnings.filters.copy() >>> warnings.filterwarnings("ignore", category=DeprecationWarning) # Filter DeprecationWarning: regarding the (type, val, tb) signature of throw(). @@ -2331,8 +2332,7 @@ def printsolution(self, x): ... ValueError: 7 ->>> warnings.filters.pop(0) -('ignore', None, , None, 0) +>>> warnings.filters[:] = old_filters # Re-enable DeprecationWarning: the (type, val, tb) exception representation is deprecated, # and may be removed in a future version of Python. diff --git a/Lib/test/test_genericalias.py b/Lib/test/test_genericalias.py index bf600a0f4d1834..04cb810d9babbf 100644 --- a/Lib/test/test_genericalias.py +++ b/Lib/test/test_genericalias.py @@ -28,7 +28,7 @@ from itertools import chain from http.cookies import Morsel try: - from multiprocessing.managers import ValueProxy + from multiprocessing.managers import ValueProxy, DictProxy, ListProxy from multiprocessing.pool import ApplyResult from multiprocessing.queues import SimpleQueue as MPSimpleQueue from multiprocessing.queues import Queue as MPQueue @@ -36,6 +36,8 @@ except ImportError: # _multiprocessing module is optional ValueProxy = None + DictProxy = None + ListProxy = None ApplyResult = None MPSimpleQueue = None MPQueue = None @@ -134,7 +136,7 @@ class BaseTest(unittest.TestCase): if ctypes is not None: generic_types.extend((ctypes.Array, ctypes.LibraryLoader)) if ValueProxy is not None: - generic_types.extend((ValueProxy, ApplyResult, + generic_types.extend((ValueProxy, DictProxy, ListProxy, ApplyResult, MPSimpleQueue, MPQueue, MPJoinableQueue)) def test_subscriptable(self): diff --git a/Lib/test/test_genericclass.py b/Lib/test/test_genericclass.py index d8bb37f69e18a1..aece757fc1933e 100644 --- a/Lib/test/test_genericclass.py +++ b/Lib/test/test_genericclass.py @@ -98,7 +98,7 @@ def __mro_entries__(self): return () d = C_too_few() with self.assertRaises(TypeError): - class D(d): ... + class E(d): ... def test_mro_entry_errors_2(self): class C_not_callable: @@ -111,7 +111,7 @@ def __mro_entries__(self): return object c = C_not_tuple() with self.assertRaises(TypeError): - class D(c): ... + class E(c): ... def test_mro_entry_metaclass(self): meta_args = [] diff --git a/Lib/test/test_genericpath.py b/Lib/test/test_genericpath.py index 489044f8090d3b..4f311c2d498e9f 100644 --- a/Lib/test/test_genericpath.py +++ b/Lib/test/test_genericpath.py @@ -460,6 +460,10 @@ def test_normpath_issue5827(self): for path in ('', '.', '/', '\\', '///foo/.//bar//'): self.assertIsInstance(self.pathmodule.normpath(path), str) + def test_normpath_issue106242(self): + for path in ('\x00', 'foo\x00bar', '\x00\x00', '\x00foo', 'foo\x00'): + self.assertEqual(self.pathmodule.normpath(path), path) + def test_abspath_issue3426(self): # Check that abspath returns unicode when the arg is unicode # with both ASCII and non-ASCII cwds. diff --git a/Lib/test/test_getopt.py b/Lib/test/test_getopt.py index c96a33b77fe272..c8b3442de4aa77 100644 --- a/Lib/test/test_getopt.py +++ b/Lib/test/test_getopt.py @@ -1,8 +1,8 @@ # test_getopt.py # David Goodger 2000-08-19 -from test.support import verbose, run_doctest from test.support.os_helper import EnvironmentVarGuard +import doctest import unittest import getopt @@ -134,48 +134,49 @@ def test_gnu_getopt(self): self.assertEqual(opts, [('-a', '')]) self.assertEqual(args, ['arg1', '-b', '1', '--alpha', '--beta=2']) - def test_libref_examples(self): - s = """ - Examples from the Library Reference: Doc/lib/libgetopt.tex + def test_issue4629(self): + longopts, shortopts = getopt.getopt(['--help='], '', ['help=']) + self.assertEqual(longopts, [('--help', '')]) + longopts, shortopts = getopt.getopt(['--help=x'], '', ['help=']) + self.assertEqual(longopts, [('--help', 'x')]) + self.assertRaises(getopt.GetoptError, getopt.getopt, ['--help='], '', ['help']) - An example using only Unix style options: +def test_libref_examples(): + """ + Examples from the Library Reference: Doc/lib/libgetopt.tex + An example using only Unix style options: - >>> import getopt - >>> args = '-a -b -cfoo -d bar a1 a2'.split() - >>> args - ['-a', '-b', '-cfoo', '-d', 'bar', 'a1', 'a2'] - >>> optlist, args = getopt.getopt(args, 'abc:d:') - >>> optlist - [('-a', ''), ('-b', ''), ('-c', 'foo'), ('-d', 'bar')] - >>> args - ['a1', 'a2'] - Using long option names is equally easy: + >>> import getopt + >>> args = '-a -b -cfoo -d bar a1 a2'.split() + >>> args + ['-a', '-b', '-cfoo', '-d', 'bar', 'a1', 'a2'] + >>> optlist, args = getopt.getopt(args, 'abc:d:') + >>> optlist + [('-a', ''), ('-b', ''), ('-c', 'foo'), ('-d', 'bar')] + >>> args + ['a1', 'a2'] + Using long option names is equally easy: - >>> s = '--condition=foo --testing --output-file abc.def -x a1 a2' - >>> args = s.split() - >>> args - ['--condition=foo', '--testing', '--output-file', 'abc.def', '-x', 'a1', 'a2'] - >>> optlist, args = getopt.getopt(args, 'x', [ - ... 'condition=', 'output-file=', 'testing']) - >>> optlist - [('--condition', 'foo'), ('--testing', ''), ('--output-file', 'abc.def'), ('-x', '')] - >>> args - ['a1', 'a2'] - """ - import types - m = types.ModuleType("libreftest", s) - run_doctest(m, verbose) + >>> s = '--condition=foo --testing --output-file abc.def -x a1 a2' + >>> args = s.split() + >>> args + ['--condition=foo', '--testing', '--output-file', 'abc.def', '-x', 'a1', 'a2'] + >>> optlist, args = getopt.getopt(args, 'x', [ + ... 'condition=', 'output-file=', 'testing']) + >>> optlist + [('--condition', 'foo'), ('--testing', ''), ('--output-file', 'abc.def'), ('-x', '')] + >>> args + ['a1', 'a2'] + """ + +def load_tests(loader, tests, pattern): + tests.addTest(doctest.DocTestSuite()) + return tests - def test_issue4629(self): - longopts, shortopts = getopt.getopt(['--help='], '', ['help=']) - self.assertEqual(longopts, [('--help', '')]) - longopts, shortopts = getopt.getopt(['--help=x'], '', ['help=']) - self.assertEqual(longopts, [('--help', 'x')]) - self.assertRaises(getopt.GetoptError, getopt.getopt, ['--help='], '', ['help']) if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_getpass.py b/Lib/test/test_getpass.py index 98ecec94336e32..80dda2caaa3331 100644 --- a/Lib/test/test_getpass.py +++ b/Lib/test/test_getpass.py @@ -26,7 +26,7 @@ def test_username_priorities_of_env_values(self, environ): environ.get.return_value = None try: getpass.getuser() - except ImportError: # in case there's no pwd module + except OSError: # in case there's no pwd module pass except KeyError: # current user has no pwd entry @@ -47,7 +47,7 @@ def test_username_falls_back_to_pwd(self, environ): getpass.getuser()) getpw.assert_called_once_with(42) else: - self.assertRaises(ImportError, getpass.getuser) + self.assertRaises(OSError, getpass.getuser) class GetpassRawinputTest(unittest.TestCase): diff --git a/Lib/test/test_getpath.py b/Lib/test/test_getpath.py index b9cbe1d92c436f..2f7aa69efc184a 100644 --- a/Lib/test/test_getpath.py +++ b/Lib/test/test_getpath.py @@ -818,6 +818,20 @@ def test_symlink_buildpath_macos(self): actual = getpath(ns, expected) self.assertEqual(expected, actual) + def test_explicitly_set_stdlib_dir(self): + """Test the explicitly set stdlib_dir in the config is respected.""" + ns = MockPosixNamespace( + PREFIX="/usr", + argv0="python", + ENV_PATH="/usr/bin", + ) + ns["config"]["stdlib_dir"] = "/custom_stdlib_dir" + expected = dict( + stdlib_dir="/custom_stdlib_dir", + ) + actual = getpath(ns, expected) + self.assertEqual(expected, actual) + # ****************************************************************************** diff --git a/Lib/test/test_gettext.py b/Lib/test/test_gettext.py index 8430fc234d00ee..b2fe3e28c3bec7 100644 --- a/Lib/test/test_gettext.py +++ b/Lib/test/test_gettext.py @@ -2,6 +2,7 @@ import base64 import gettext import unittest +from functools import partial from test import support from test.support import os_helper @@ -115,9 +116,16 @@ MMOFILE = os.path.join(LOCALEDIR, 'metadata.mo') +def reset_gettext(): + gettext._localedirs.clear() + gettext._current_domain = 'messages' + gettext._translations.clear() + + class GettextBaseTest(unittest.TestCase): - def setUp(self): - self.addCleanup(os_helper.rmtree, os.path.split(LOCALEDIR)[0]) + @classmethod + def setUpClass(cls): + cls.addClassCleanup(os_helper.rmtree, os.path.split(LOCALEDIR)[0]) if not os.path.isdir(LOCALEDIR): os.makedirs(LOCALEDIR) with open(MOFILE, 'wb') as fp: @@ -130,9 +138,12 @@ def setUp(self): fp.write(base64.decodebytes(UMO_DATA)) with open(MMOFILE, 'wb') as fp: fp.write(base64.decodebytes(MMO_DATA)) + + def setUp(self): self.env = self.enterContext(os_helper.EnvironmentVarGuard()) self.env['LANGUAGE'] = 'xx' - gettext._translations.clear() + reset_gettext() + self.addCleanup(reset_gettext) GNU_MO_DATA_ISSUE_17898 = b'''\ @@ -309,55 +320,139 @@ def test_multiline_strings(self): trggrkg zrffntr pngnybt yvoenel.''') -class PluralFormsTestCase(GettextBaseTest): +class PluralFormsTests: + + def _test_plural_forms(self, ngettext, gettext, + singular, plural, tsingular, tplural, + numbers_only=True): + x = ngettext(singular, plural, 1) + self.assertEqual(x, tsingular) + x = ngettext(singular, plural, 2) + self.assertEqual(x, tplural) + x = gettext(singular) + self.assertEqual(x, tsingular) + + lineno = self._test_plural_forms.__code__.co_firstlineno + 12 + with self.assertWarns(DeprecationWarning) as cm: + x = ngettext(singular, plural, 1.0) + self.assertEqual(cm.filename, __file__) + self.assertEqual(cm.lineno, lineno) + self.assertEqual(x, tsingular) + with self.assertWarns(DeprecationWarning) as cm: + x = ngettext(singular, plural, 1.1) + self.assertEqual(cm.filename, __file__) + self.assertEqual(cm.lineno, lineno + 5) + self.assertEqual(x, tplural) + + if numbers_only: + with self.assertRaises(TypeError): + ngettext(singular, plural, None) + else: + with self.assertWarns(DeprecationWarning) as cm: + x = ngettext(singular, plural, None) + self.assertEqual(x, tplural) + + def test_plural_forms(self): + self._test_plural_forms( + self.ngettext, self.gettext, + 'There is %s file', 'There are %s files', + 'Hay %s fichero', 'Hay %s ficheros') + self._test_plural_forms( + self.ngettext, self.gettext, + '%d file deleted', '%d files deleted', + '%d file deleted', '%d files deleted') + + def test_plural_context_forms(self): + ngettext = partial(self.npgettext, 'With context') + gettext = partial(self.pgettext, 'With context') + self._test_plural_forms( + ngettext, gettext, + 'There is %s file', 'There are %s files', + 'Hay %s fichero (context)', 'Hay %s ficheros (context)') + self._test_plural_forms( + ngettext, gettext, + '%d file deleted', '%d files deleted', + '%d file deleted', '%d files deleted') + + def test_plural_wrong_context_forms(self): + self._test_plural_forms( + partial(self.npgettext, 'Unknown context'), + partial(self.pgettext, 'Unknown context'), + 'There is %s file', 'There are %s files', + 'There is %s file', 'There are %s files') + + +class GNUTranslationsPluralFormsTestCase(PluralFormsTests, GettextBaseTest): def setUp(self): GettextBaseTest.setUp(self) - self.mofile = MOFILE + # Set up the bindings + gettext.bindtextdomain('gettext', os.curdir) + gettext.textdomain('gettext') - def test_plural_forms1(self): - eq = self.assertEqual - x = gettext.ngettext('There is %s file', 'There are %s files', 1) - eq(x, 'Hay %s fichero') - x = gettext.ngettext('There is %s file', 'There are %s files', 2) - eq(x, 'Hay %s ficheros') - x = gettext.gettext('There is %s file') - eq(x, 'Hay %s fichero') - - def test_plural_context_forms1(self): - eq = self.assertEqual - x = gettext.npgettext('With context', - 'There is %s file', 'There are %s files', 1) - eq(x, 'Hay %s fichero (context)') - x = gettext.npgettext('With context', - 'There is %s file', 'There are %s files', 2) - eq(x, 'Hay %s ficheros (context)') - x = gettext.pgettext('With context', 'There is %s file') - eq(x, 'Hay %s fichero (context)') - - def test_plural_forms2(self): - eq = self.assertEqual - with open(self.mofile, 'rb') as fp: - t = gettext.GNUTranslations(fp) - x = t.ngettext('There is %s file', 'There are %s files', 1) - eq(x, 'Hay %s fichero') - x = t.ngettext('There is %s file', 'There are %s files', 2) - eq(x, 'Hay %s ficheros') - x = t.gettext('There is %s file') - eq(x, 'Hay %s fichero') - - def test_plural_context_forms2(self): - eq = self.assertEqual - with open(self.mofile, 'rb') as fp: + self.gettext = gettext.gettext + self.ngettext = gettext.ngettext + self.pgettext = gettext.pgettext + self.npgettext = gettext.npgettext + + +class GNUTranslationsWithDomainPluralFormsTestCase(PluralFormsTests, GettextBaseTest): + def setUp(self): + GettextBaseTest.setUp(self) + # Set up the bindings + gettext.bindtextdomain('gettext', os.curdir) + + self.gettext = partial(gettext.dgettext, 'gettext') + self.ngettext = partial(gettext.dngettext, 'gettext') + self.pgettext = partial(gettext.dpgettext, 'gettext') + self.npgettext = partial(gettext.dnpgettext, 'gettext') + + def test_plural_forms_wrong_domain(self): + self._test_plural_forms( + partial(gettext.dngettext, 'unknown'), + partial(gettext.dgettext, 'unknown'), + 'There is %s file', 'There are %s files', + 'There is %s file', 'There are %s files', + numbers_only=False) + + def test_plural_context_forms_wrong_domain(self): + self._test_plural_forms( + partial(gettext.dnpgettext, 'unknown', 'With context'), + partial(gettext.dpgettext, 'unknown', 'With context'), + 'There is %s file', 'There are %s files', + 'There is %s file', 'There are %s files', + numbers_only=False) + + +class GNUTranslationsClassPluralFormsTestCase(PluralFormsTests, GettextBaseTest): + def setUp(self): + GettextBaseTest.setUp(self) + with open(MOFILE, 'rb') as fp: t = gettext.GNUTranslations(fp) - x = t.npgettext('With context', - 'There is %s file', 'There are %s files', 1) - eq(x, 'Hay %s fichero (context)') - x = t.npgettext('With context', - 'There is %s file', 'There are %s files', 2) - eq(x, 'Hay %s ficheros (context)') - x = gettext.pgettext('With context', 'There is %s file') - eq(x, 'Hay %s fichero (context)') + self.gettext = t.gettext + self.ngettext = t.ngettext + self.pgettext = t.pgettext + self.npgettext = t.npgettext + + def test_plural_forms_null_translations(self): + t = gettext.NullTranslations() + self._test_plural_forms( + t.ngettext, t.gettext, + 'There is %s file', 'There are %s files', + 'There is %s file', 'There are %s files', + numbers_only=False) + + def test_plural_context_forms_null_translations(self): + t = gettext.NullTranslations() + self._test_plural_forms( + partial(t.npgettext, 'With context'), + partial(t.pgettext, 'With context'), + 'There is %s file', 'There are %s files', + 'There is %s file', 'There are %s files', + numbers_only=False) + + +class PluralFormsInternalTestCase: # Examples from http://www.gnu.org/software/gettext/manual/gettext.html def test_ja(self): diff --git a/Lib/test/test_glob.py b/Lib/test/test_glob.py index f4b5821f408cb4..aa5fac8eca1354 100644 --- a/Lib/test/test_glob.py +++ b/Lib/test/test_glob.py @@ -1,5 +1,6 @@ import glob import os +import re import shutil import sys import unittest @@ -349,6 +350,96 @@ def test_glob_many_open_files(self): for it in iters: self.assertEqual(next(it), p) + def test_translate_matching(self): + match = re.compile(glob.translate('*')).match + self.assertIsNotNone(match('foo')) + self.assertIsNotNone(match('foo.bar')) + self.assertIsNone(match('.foo')) + match = re.compile(glob.translate('.*')).match + self.assertIsNotNone(match('.foo')) + match = re.compile(glob.translate('**', recursive=True)).match + self.assertIsNotNone(match('foo')) + self.assertIsNone(match('.foo')) + self.assertIsNotNone(match(os.path.join('foo', 'bar'))) + self.assertIsNone(match(os.path.join('foo', '.bar'))) + self.assertIsNone(match(os.path.join('.foo', 'bar'))) + self.assertIsNone(match(os.path.join('.foo', '.bar'))) + match = re.compile(glob.translate('**/*', recursive=True)).match + self.assertIsNotNone(match(os.path.join('foo', 'bar'))) + self.assertIsNone(match(os.path.join('foo', '.bar'))) + self.assertIsNone(match(os.path.join('.foo', 'bar'))) + self.assertIsNone(match(os.path.join('.foo', '.bar'))) + match = re.compile(glob.translate('*/**', recursive=True)).match + self.assertIsNotNone(match(os.path.join('foo', 'bar'))) + self.assertIsNone(match(os.path.join('foo', '.bar'))) + self.assertIsNone(match(os.path.join('.foo', 'bar'))) + self.assertIsNone(match(os.path.join('.foo', '.bar'))) + match = re.compile(glob.translate('**/.bar', recursive=True)).match + self.assertIsNotNone(match(os.path.join('foo', '.bar'))) + self.assertIsNone(match(os.path.join('.foo', '.bar'))) + match = re.compile(glob.translate('**/*.*', recursive=True)).match + self.assertIsNone(match(os.path.join('foo', 'bar'))) + self.assertIsNone(match(os.path.join('foo', '.bar'))) + self.assertIsNotNone(match(os.path.join('foo', 'bar.txt'))) + self.assertIsNone(match(os.path.join('foo', '.bar.txt'))) + + def test_translate(self): + def fn(pat): + return glob.translate(pat, seps='/') + self.assertEqual(fn('foo'), r'(?s:foo)\Z') + self.assertEqual(fn('foo/bar'), r'(?s:foo/bar)\Z') + self.assertEqual(fn('*'), r'(?s:[^/.][^/]*)\Z') + self.assertEqual(fn('?'), r'(?s:(?!\.)[^/])\Z') + self.assertEqual(fn('a*'), r'(?s:a[^/]*)\Z') + self.assertEqual(fn('*a'), r'(?s:(?!\.)[^/]*a)\Z') + self.assertEqual(fn('.*'), r'(?s:\.[^/]*)\Z') + self.assertEqual(fn('?aa'), r'(?s:(?!\.)[^/]aa)\Z') + self.assertEqual(fn('aa?'), r'(?s:aa[^/])\Z') + self.assertEqual(fn('aa[ab]'), r'(?s:aa[ab])\Z') + self.assertEqual(fn('**'), r'(?s:(?!\.)[^/]*)\Z') + self.assertEqual(fn('***'), r'(?s:(?!\.)[^/]*)\Z') + self.assertEqual(fn('a**'), r'(?s:a[^/]*)\Z') + self.assertEqual(fn('**b'), r'(?s:(?!\.)[^/]*b)\Z') + self.assertEqual(fn('/**/*/*.*/**'), + r'(?s:/(?!\.)[^/]*/[^/.][^/]*/(?!\.)[^/]*\.[^/]*/(?!\.)[^/]*)\Z') + + def test_translate_include_hidden(self): + def fn(pat): + return glob.translate(pat, include_hidden=True, seps='/') + self.assertEqual(fn('foo'), r'(?s:foo)\Z') + self.assertEqual(fn('foo/bar'), r'(?s:foo/bar)\Z') + self.assertEqual(fn('*'), r'(?s:[^/]+)\Z') + self.assertEqual(fn('?'), r'(?s:[^/])\Z') + self.assertEqual(fn('a*'), r'(?s:a[^/]*)\Z') + self.assertEqual(fn('*a'), r'(?s:[^/]*a)\Z') + self.assertEqual(fn('.*'), r'(?s:\.[^/]*)\Z') + self.assertEqual(fn('?aa'), r'(?s:[^/]aa)\Z') + self.assertEqual(fn('aa?'), r'(?s:aa[^/])\Z') + self.assertEqual(fn('aa[ab]'), r'(?s:aa[ab])\Z') + self.assertEqual(fn('**'), r'(?s:[^/]*)\Z') + self.assertEqual(fn('***'), r'(?s:[^/]*)\Z') + self.assertEqual(fn('a**'), r'(?s:a[^/]*)\Z') + self.assertEqual(fn('**b'), r'(?s:[^/]*b)\Z') + self.assertEqual(fn('/**/*/*.*/**'), r'(?s:/[^/]*/[^/]+/[^/]*\.[^/]*/[^/]*)\Z') + + def test_translate_recursive(self): + def fn(pat): + return glob.translate(pat, recursive=True, include_hidden=True, seps='/') + self.assertEqual(fn('*'), r'(?s:[^/]+)\Z') + self.assertEqual(fn('?'), r'(?s:[^/])\Z') + self.assertEqual(fn('**'), r'(?s:.*)\Z') + self.assertEqual(fn('**/**'), r'(?s:.*)\Z') + self.assertRaises(ValueError, fn, '***') + self.assertRaises(ValueError, fn, 'a**') + self.assertRaises(ValueError, fn, '**b') + self.assertEqual(fn('/**/*/*.*/**'), r'(?s:/(?:.+/)?[^/]+/[^/]*\.[^/]*/.*)\Z') + + def test_translate_seps(self): + def fn(pat): + return glob.translate(pat, recursive=True, include_hidden=True, seps=['/', '\\']) + self.assertEqual(fn('foo/bar\\baz'), r'(?s:foo[/\\]bar[/\\]baz)\Z') + self.assertEqual(fn('**/*'), r'(?s:(?:.+[/\\])?[^/\\]+)\Z') + @skip_unless_symlink class SymlinkLoopGlobTests(unittest.TestCase): diff --git a/Lib/test/test_grammar.py b/Lib/test/test_grammar.py index ee105a3de17f8a..8501006b799262 100644 --- a/Lib/test/test_grammar.py +++ b/Lib/test/test_grammar.py @@ -12,9 +12,9 @@ # different import patterns to check that __annotations__ does not interfere # with import machinery -import test.ann_module as ann_module +import test.typinganndata.ann_module as ann_module import typing -from test import ann_module2 +from test.typinganndata import ann_module2 import test # These are shared with test_tokenize and other test modules. @@ -236,6 +236,10 @@ def check(test, error=False): check(f"[{num}for x in ()]") check(f"{num}spam", error=True) + # gh-88943: Invalid non-ASCII character following a numerical literal. + with self.assertRaisesRegex(SyntaxError, r"invalid character 'â„' \(U\+2044\)"): + compile(f"{num}â„7", "", "eval") + with self.assertWarnsRegex(SyntaxWarning, r'invalid \w+ literal'): compile(f"{num}is x", "", "eval") with warnings.catch_warnings(): @@ -350,6 +354,11 @@ def test_var_annot_syntax_errors(self): check_syntax_error(self, "x: int: str") check_syntax_error(self, "def f():\n" " nonlocal x: int\n") + check_syntax_error(self, "def f():\n" + " global x: int\n") + check_syntax_error(self, "x: int = y = 1") + check_syntax_error(self, "z = w: int = 1") + check_syntax_error(self, "x: int = y: int = 1") # AST pass check_syntax_error(self, "[x, 0]: int\n") check_syntax_error(self, "f(): int\n") @@ -363,6 +372,12 @@ def test_var_annot_syntax_errors(self): check_syntax_error(self, "def f():\n" " global x\n" " x: int\n") + check_syntax_error(self, "def f():\n" + " x: int\n" + " nonlocal x\n") + check_syntax_error(self, "def f():\n" + " nonlocal x\n" + " x: int\n") def test_var_annot_basic_semantics(self): # execution order @@ -452,7 +467,7 @@ def test_var_annot_module_semantics(self): def test_var_annot_in_module(self): # check that functions fail the same way when executed # outside of module where they were defined - ann_module3 = import_helper.import_fresh_module("test.ann_module3") + ann_module3 = import_helper.import_fresh_module("test.typinganndata.ann_module3") with self.assertRaises(NameError): ann_module3.f_bad_ann() with self.assertRaises(NameError): diff --git a/Lib/test/test_gzip.py b/Lib/test/test_gzip.py index b06b3b09411d62..128f933787a3f6 100644 --- a/Lib/test/test_gzip.py +++ b/Lib/test/test_gzip.py @@ -665,6 +665,18 @@ def flush(self, mode=-1): ] self.assertEqual(fc.modes, expected_modes) + def test_write_seek_write(self): + # Make sure that offset is up-to-date before seeking + # See issue GH-108111 + b = io.BytesIO() + message = b"important message here." + with gzip.GzipFile(fileobj=b, mode='w') as f: + f.write(message) + f.seek(len(message)) + f.write(message) + data = b.getvalue() + self.assertEqual(gzip.decompress(data), message * 2) + class TestOpen(BaseTest): def test_binary_modes(self): diff --git a/Lib/test/test_httplib.py b/Lib/test/test_httplib.py index fe8105ee2bb3fa..089bf5be40a0e2 100644 --- a/Lib/test/test_httplib.py +++ b/Lib/test/test_httplib.py @@ -21,11 +21,13 @@ here = os.path.dirname(__file__) # Self-signed cert file for 'localhost' -CERT_localhost = os.path.join(here, 'keycert.pem') +CERT_localhost = os.path.join(here, 'certdata', 'keycert.pem') # Self-signed cert file for 'fakehostname' -CERT_fakehostname = os.path.join(here, 'keycert2.pem') +CERT_fakehostname = os.path.join(here, 'certdata', 'keycert2.pem') # Self-signed cert file for self-signed.pythontest.net -CERT_selfsigned_pythontestdotnet = os.path.join(here, 'selfsigned_pythontestdotnet.pem') +CERT_selfsigned_pythontestdotnet = os.path.join( + here, 'certdata', 'selfsigned_pythontestdotnet.pem', +) # constants for testing chunked encoding chunked_start = ( @@ -281,6 +283,22 @@ def test_ipv6host_header(self): conn.request('GET', '/foo') self.assertTrue(sock.data.startswith(expected)) + expected = b'GET /foo HTTP/1.1\r\nHost: [fe80::]\r\n' \ + b'Accept-Encoding: identity\r\n\r\n' + conn = client.HTTPConnection('[fe80::%2]') + sock = FakeSocket('') + conn.sock = sock + conn.request('GET', '/foo') + self.assertTrue(sock.data.startswith(expected)) + + expected = b'GET /foo HTTP/1.1\r\nHost: [fe80::]:81\r\n' \ + b'Accept-Encoding: identity\r\n\r\n' + conn = client.HTTPConnection('[fe80::%2]:81') + sock = FakeSocket('') + conn.sock = sock + conn.request('GET', '/foo') + self.assertTrue(sock.data.startswith(expected)) + def test_malformed_headers_coped_with(self): # Issue 19996 body = "HTTP/1.1 200 OK\r\nFirst: val\r\n: nval\r\nSecond: val\r\n\r\n" @@ -1528,11 +1546,14 @@ def test_readline(self): resp = self.resp self._verify_readline(self.resp.readline, self.lines_expected) - def _verify_readline(self, readline, expected): + def test_readline_without_limit(self): + self._verify_readline(self.resp.readline, self.lines_expected, limit=-1) + + def _verify_readline(self, readline, expected, limit=5): all = [] while True: # short readlines - line = readline(5) + line = readline(limit) if line and line != b"foo": if len(line) < 5: self.assertTrue(line.endswith(b"\n")) @@ -1540,6 +1561,7 @@ def _verify_readline(self, readline, expected): if not line: break self.assertEqual(b"".join(all), expected) + self.assertTrue(self.resp.isclosed()) def test_read1(self): resp = self.resp @@ -1559,6 +1581,7 @@ def test_read1_unbounded(self): break all.append(data) self.assertEqual(b"".join(all), self.lines_expected) + self.assertTrue(resp.isclosed()) def test_read1_bounded(self): resp = self.resp @@ -1570,15 +1593,22 @@ def test_read1_bounded(self): self.assertLessEqual(len(data), 10) all.append(data) self.assertEqual(b"".join(all), self.lines_expected) + self.assertTrue(resp.isclosed()) def test_read1_0(self): self.assertEqual(self.resp.read1(0), b"") + self.assertFalse(self.resp.isclosed()) def test_peek_0(self): p = self.resp.peek(0) self.assertLessEqual(0, len(p)) +class ExtendedReadTestContentLengthKnown(ExtendedReadTest): + _header, _body = ExtendedReadTest.lines.split('\r\n\r\n', 1) + lines = _header + f'\r\nContent-Length: {len(_body)}\r\n\r\n' + _body + + class ExtendedReadTestChunked(ExtendedReadTest): """ Test peek(), read1(), readline() in chunked mode @@ -1954,6 +1984,7 @@ def test_networked_good_cert(self): h.close() self.assertIn('nginx', server_string) + @support.requires_resource('walltime') def test_networked_bad_cert(self): # We feed a "CA" cert that is unrelated to the server's cert import ssl diff --git a/Lib/test/test_httpservers.py b/Lib/test/test_httpservers.py index cfd8a101dcc1c1..9fa6ecf9c08e27 100644 --- a/Lib/test/test_httpservers.py +++ b/Lib/test/test_httpservers.py @@ -699,11 +699,20 @@ def test_html_escape_filename(self): "This test can't be run reliably as root (issue #13308).") class CGIHTTPServerTestCase(BaseTestCase): class request_handler(NoLogRequestHandler, CGIHTTPRequestHandler): - pass + _test_case_self = None # populated by each setUp() method call. + + def __init__(self, *args, **kwargs): + with self._test_case_self.assertWarnsRegex( + DeprecationWarning, + r'http\.server\.CGIHTTPRequestHandler'): + # This context also happens to catch and silence the + # threading DeprecationWarning from os.fork(). + super().__init__(*args, **kwargs) linesep = os.linesep.encode('ascii') def setUp(self): + self.request_handler._test_case_self = self # practical, but yuck. BaseTestCase.setUp(self) self.cwd = os.getcwd() self.parent_dir = tempfile.mkdtemp() @@ -780,6 +789,7 @@ def setUp(self): os.chdir(self.parent_dir) def tearDown(self): + self.request_handler._test_case_self = None try: os.chdir(self.cwd) if self._pythonexe_symlink: diff --git a/Lib/test/test_idle.py b/Lib/test/test_idle.py index ebb1e8eb823b51..3d8b7ecc0ecb6d 100644 --- a/Lib/test/test_idle.py +++ b/Lib/test/test_idle.py @@ -3,6 +3,7 @@ from test.support import check_sanitizer if check_sanitizer(address=True, memory=True): + # See gh-90791 for details raise unittest.SkipTest("Tests involving libX11 can SEGFAULT on ASAN/MSAN builds") # Skip test_idle if _tkinter, tkinter, or idlelib are missing. diff --git a/Lib/test/test_imaplib.py b/Lib/test/test_imaplib.py index 2b2f1f76d26db3..b97474acca370f 100644 --- a/Lib/test/test_imaplib.py +++ b/Lib/test/test_imaplib.py @@ -10,7 +10,7 @@ import threading import socket -from test.support import verbose, run_with_tz, run_with_locale, cpython_only +from test.support import verbose, run_with_tz, run_with_locale, cpython_only, requires_resource from test.support import hashlib_helper from test.support import threading_helper import unittest @@ -23,8 +23,8 @@ support.requires_working_socket(module=True) -CERTFILE = os.path.join(os.path.dirname(__file__) or os.curdir, "keycert3.pem") -CAFILE = os.path.join(os.path.dirname(__file__) or os.curdir, "pycacert.pem") +CERTFILE = os.path.join(os.path.dirname(__file__) or os.curdir, "certdata", "keycert3.pem") +CAFILE = os.path.join(os.path.dirname(__file__) or os.curdir, "certdata", "pycacert.pem") class TestImaplib(unittest.TestCase): @@ -74,6 +74,7 @@ def test_that_Time2Internaldate_returns_a_result(self): for t in self.timevalues(): imaplib.Time2Internaldate(t) + @socket_helper.skip_if_tcp_blackhole def test_imap4_host_default_value(self): # Check whether the IMAP4_PORT is truly unavailable. with socket.socket() as s: @@ -456,6 +457,7 @@ def test_simple_with_statement(self): with self.imap_class(*server.server_address): pass + @requires_resource('walltime') def test_imaplib_timeout_test(self): _, server = self._setup(SimpleIMAPHandler) addr = server.server_address[1] @@ -549,6 +551,7 @@ class NewIMAPSSLTests(NewIMAPTestsMixin, unittest.TestCase): imap_class = IMAP4_SSL server_class = SecureTCPServer + @requires_resource('walltime') def test_ssl_raises(self): ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) self.assertEqual(ssl_context.verify_mode, ssl.CERT_REQUIRED) @@ -563,6 +566,7 @@ def test_ssl_raises(self): ssl_context=ssl_context) client.shutdown() + @requires_resource('walltime') def test_ssl_verified(self): ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) ssl_context.load_verify_locations(CAFILE) diff --git a/Lib/test/test_import/__init__.py b/Lib/test/test_import/__init__.py index 163ed824ff1fb0..7b0126226c4aba 100644 --- a/Lib/test/test_import/__init__.py +++ b/Lib/test/test_import/__init__.py @@ -1,5 +1,4 @@ import builtins -import contextlib import errno import glob import json @@ -22,17 +21,17 @@ import types import unittest from unittest import mock -import _testinternalcapi import _imp from test.support import os_helper from test.support import ( STDLIB_DIR, swap_attr, swap_item, cpython_only, is_emscripten, - is_wasi, run_in_subinterp, run_in_subinterp_with_config) + is_wasi, run_in_subinterp, run_in_subinterp_with_config, Py_TRACE_REFS) from test.support.import_helper import ( - forget, make_legacy_pyc, unlink, unload, DirsOnSysPath, CleanImport) + forget, make_legacy_pyc, unlink, unload, ready_to_import, + DirsOnSysPath, CleanImport) from test.support.os_helper import ( - TESTFN, rmtree, temp_umask, TESTFN_UNENCODABLE, temp_dir) + TESTFN, rmtree, temp_umask, TESTFN_UNENCODABLE) from test.support import script_helper from test.support import threading_helper from test.test_importlib.util import uncache @@ -49,6 +48,10 @@ import _xxsubinterpreters as _interpreters except ModuleNotFoundError: _interpreters = None +try: + import _testinternalcapi +except ImportError: + _testinternalcapi = None skip_if_dont_write_bytecode = unittest.skipIf( @@ -125,27 +128,6 @@ def wrapper(self): return deco -@contextlib.contextmanager -def _ready_to_import(name=None, source=""): - # sets up a temporary directory and removes it - # creates the module file - # temporarily clears the module from sys.modules (if any) - # reverts or removes the module when cleaning up - name = name or "spam" - with temp_dir() as tempdir: - path = script_helper.make_script(tempdir, name, source) - old_module = sys.modules.pop(name, None) - try: - sys.path.insert(0, tempdir) - yield name, path - sys.path.remove(tempdir) - finally: - if old_module is not None: - sys.modules[name] = old_module - elif name in sys.modules: - del sys.modules[name] - - if _testsinglephase is not None: def restore__testsinglephase(*, _orig=_testsinglephase): # We started with the module imported and want to restore @@ -401,7 +383,7 @@ def test_from_import_missing_attr_path_is_canonical(self): def test_from_import_star_invalid_type(self): import re - with _ready_to_import() as (name, path): + with ready_to_import() as (name, path): with open(path, 'w', encoding='utf-8') as f: f.write("__all__ = [b'invalid_type']") globals = {} @@ -410,7 +392,7 @@ def test_from_import_star_invalid_type(self): ): exec(f"from {name} import *", globals) self.assertNotIn(b"invalid_type", globals) - with _ready_to_import() as (name, path): + with ready_to_import() as (name, path): with open(path, 'w', encoding='utf-8') as f: f.write("globals()[b'invalid_type'] = object()") globals = {} @@ -427,9 +409,12 @@ def test_case_sensitivity(self): import RAnDoM def test_double_const(self): - # Another brief digression to test the accuracy of manifest float - # constants. - from test import double_const # don't blink -- that *was* the test + # Importing double_const checks that float constants + # serialiazed by marshal as PYC files don't lose precision + # (SF bug 422177). + from test.test_import.data import double_const + unload('test.test_import.data.double_const') + from test.test_import.data import double_const def test_import(self): def test_with_extension(ext): @@ -818,7 +803,7 @@ class FilePermissionTests(unittest.TestCase): ) def test_creation_mode(self): mask = 0o022 - with temp_umask(mask), _ready_to_import() as (name, path): + with temp_umask(mask), ready_to_import() as (name, path): cached_path = importlib.util.cache_from_source(path) module = __import__(name) if not os.path.exists(cached_path): @@ -837,7 +822,7 @@ def test_creation_mode(self): def test_cached_mode_issue_2051(self): # permissions of .pyc should match those of .py, regardless of mask mode = 0o600 - with temp_umask(0o022), _ready_to_import() as (name, path): + with temp_umask(0o022), ready_to_import() as (name, path): cached_path = importlib.util.cache_from_source(path) os.chmod(path, mode) __import__(name) @@ -853,7 +838,7 @@ def test_cached_mode_issue_2051(self): @os_helper.skip_unless_working_chmod def test_cached_readonly(self): mode = 0o400 - with temp_umask(0o022), _ready_to_import() as (name, path): + with temp_umask(0o022), ready_to_import() as (name, path): cached_path = importlib.util.cache_from_source(path) os.chmod(path, mode) __import__(name) @@ -868,7 +853,7 @@ def test_cached_readonly(self): def test_pyc_always_writable(self): # Initially read-only .pyc files on Windows used to cause problems # with later updates, see issue #6074 for details - with _ready_to_import() as (name, path): + with ready_to_import() as (name, path): # Write a Python file, make it read-only and import it with open(path, 'w', encoding='utf-8') as f: f.write("x = 'original'\n") @@ -1647,6 +1632,14 @@ def test_circular_from_import(self): str(cm.exception), ) + def test_circular_import(self): + with self.assertRaisesRegex( + AttributeError, + r"partially initialized module 'test.test_import.data.circular_imports.import_cycle' " + r"from '.*' has no attribute 'some_attribute' \(most likely due to a circular import\)" + ): + import test.test_import.data.circular_imports.import_cycle + def test_absolute_circular_submodule(self): with self.assertRaises(AttributeError) as cm: import test.test_import.data.circular_imports.subpkg2.parent @@ -1805,12 +1798,12 @@ def check_compatible_fresh(self, name, *, strict=False, isolated=False): check_multi_interp_extensions=strict, ) _, out, err = script_helper.assert_python_ok('-c', textwrap.dedent(f''' - import _testcapi, sys + import _testinternalcapi, sys assert ( {name!r} in sys.builtin_module_names or {name!r} not in sys.modules ), repr({name!r}) - ret = _testcapi.run_in_subinterp_with_config( + ret = _testinternalcapi.run_in_subinterp_with_config( {self.import_script(name, "sys.stdout.fileno()")!r}, **{kwargs}, ) @@ -1829,9 +1822,9 @@ def check_incompatible_fresh(self, name, *, isolated=False): check_multi_interp_extensions=True, ) _, out, err = script_helper.assert_python_ok('-c', textwrap.dedent(f''' - import _testcapi, sys + import _testinternalcapi, sys assert {name!r} not in sys.modules, {name!r} - ret = _testcapi.run_in_subinterp_with_config( + ret = _testinternalcapi.run_in_subinterp_with_config( {self.import_script(name, "sys.stdout.fileno()")!r}, **{kwargs}, ) @@ -1986,10 +1979,13 @@ def test_disallowed_reimport(self): print(_testsinglephase) ''') interpid = _interpreters.create() - with self.assertRaises(_interpreters.RunFailedError): - _interpreters.run_string(interpid, script) - with self.assertRaises(_interpreters.RunFailedError): - _interpreters.run_string(interpid, script) + self.addCleanup(lambda: _interpreters.destroy(interpid)) + + excsnap = _interpreters.run_string(interpid, script) + self.assertIsNot(excsnap, None) + + excsnap = _interpreters.run_string(interpid, script) + self.assertIsNot(excsnap, None) class TestSinglePhaseSnapshot(ModuleSnapshot): @@ -2118,12 +2114,18 @@ def re_load(self, name, mod): def add_subinterpreter(self): interpid = _interpreters.create(isolated=False) - _interpreters.run_string(interpid, textwrap.dedent(''' + def ensure_destroyed(): + try: + _interpreters.destroy(interpid) + except _interpreters.InterpreterNotFoundError: + pass + self.addCleanup(ensure_destroyed) + _interpreters.exec(interpid, textwrap.dedent(''' import sys import _testinternalcapi ''')) def clean_up(): - _interpreters.run_string(interpid, textwrap.dedent(f''' + _interpreters.exec(interpid, textwrap.dedent(f''' name = {self.NAME!r} if name in sys.modules: sys.modules.pop(name)._clear_globals() @@ -2555,6 +2557,12 @@ def test_basic_multiple_interpreters_main_no_reset(self): def test_basic_multiple_interpreters_deleted_no_reset(self): # without resetting; already loaded in a deleted interpreter + if Py_TRACE_REFS: + # It's a Py_TRACE_REFS build. + # This test breaks interpreter isolation a little, + # which causes problems on Py_TRACE_REF builds. + raise unittest.SkipTest('crashes on Py_TRACE_REFS builds') + # At this point: # * alive in 0 interpreters # * module def may or may not be loaded already diff --git a/Lib/test/test_import/data/circular_imports/import_cycle.py b/Lib/test/test_import/data/circular_imports/import_cycle.py new file mode 100644 index 00000000000000..cd9507b5f69e25 --- /dev/null +++ b/Lib/test/test_import/data/circular_imports/import_cycle.py @@ -0,0 +1,3 @@ +import test.test_import.data.circular_imports.import_cycle as m + +m.some_attribute diff --git a/Lib/test/double_const.py b/Lib/test/test_import/data/double_const.py similarity index 100% rename from Lib/test/double_const.py rename to Lib/test/test_import/data/double_const.py diff --git a/Lib/test/test_importlib/_path.py b/Lib/test/test_importlib/_path.py index 71a704389b986e..25c799fa44cd55 100644 --- a/Lib/test/test_importlib/_path.py +++ b/Lib/test/test_importlib/_path.py @@ -1,17 +1,18 @@ -# from jaraco.path 3.5 +# from jaraco.path 3.7 import functools import pathlib -from typing import Dict, Union +from typing import Dict, Protocol, Union +from typing import runtime_checkable -try: - from typing import Protocol, runtime_checkable -except ImportError: # pragma: no cover - # Python 3.7 - from typing_extensions import Protocol, runtime_checkable # type: ignore + +class Symlink(str): + """ + A string indicating the target of a symlink. + """ -FilesSpec = Dict[str, Union[str, bytes, 'FilesSpec']] # type: ignore +FilesSpec = Dict[str, Union[str, bytes, Symlink, 'FilesSpec']] # type: ignore @runtime_checkable @@ -28,6 +29,9 @@ def write_text(self, content, **kwargs): def write_bytes(self, content): ... # pragma: no cover + def symlink_to(self, target): + ... # pragma: no cover + def _ensure_tree_maker(obj: Union[str, TreeMaker]) -> TreeMaker: return obj if isinstance(obj, TreeMaker) else pathlib.Path(obj) # type: ignore @@ -51,12 +55,16 @@ def build( ... "__init__.py": "", ... }, ... "baz.py": "# Some code", - ... } + ... "bar.py": Symlink("baz.py"), + ... }, + ... "bing": Symlink("foo"), ... } >>> target = getfixture('tmp_path') >>> build(spec, target) >>> target.joinpath('foo/baz.py').read_text(encoding='utf-8') '# Some code' + >>> target.joinpath('bing/bar.py').read_text(encoding='utf-8') + '# Some code' """ for name, contents in spec.items(): create(contents, _ensure_tree_maker(prefix) / name) @@ -79,8 +87,8 @@ def _(content: str, path): @create.register -def _(content: str, path): - path.write_text(content, encoding='utf-8') +def _(content: Symlink, path): + path.symlink_to(content) class Recording: @@ -107,3 +115,6 @@ def write_text(self, content, **kwargs): def mkdir(self, **kwargs): return + + def symlink_to(self, target): + pass diff --git a/Lib/test/test_importlib/extension/test_loader.py b/Lib/test/test_importlib/extension/test_loader.py index 64c8a5485106e3..84a0680e4ec653 100644 --- a/Lib/test/test_importlib/extension/test_loader.py +++ b/Lib/test/test_importlib/extension/test_loader.py @@ -9,6 +9,7 @@ import warnings import importlib.util import importlib +from test.support import MISSING_C_DOCSTRINGS class LoaderTests: @@ -373,7 +374,8 @@ def test_nonascii(self): with self.subTest(name): module = self.load_module_by_name(name) self.assertEqual(module.__name__, name) - self.assertEqual(module.__doc__, "Module named in %s" % lang) + if not MISSING_C_DOCSTRINGS: + self.assertEqual(module.__doc__, "Module named in %s" % lang) (Frozen_MultiPhaseExtensionModuleTests, diff --git a/Lib/test/test_importlib/fixtures.py b/Lib/test/test_importlib/fixtures.py index 73e5da2ba92279..8c973356b5660d 100644 --- a/Lib/test/test_importlib/fixtures.py +++ b/Lib/test/test_importlib/fixtures.py @@ -1,6 +1,7 @@ import os import sys import copy +import json import shutil import pathlib import tempfile @@ -86,7 +87,15 @@ def setUp(self): self.fixtures.enter_context(self.add_sys_path(self.site_dir)) -class DistInfoPkg(OnSysPath, SiteDir): +class SiteBuilder(SiteDir): + def setUp(self): + super().setUp() + for cls in self.__class__.mro(): + with contextlib.suppress(AttributeError): + build_files(cls.files, prefix=self.site_dir) + + +class DistInfoPkg(OnSysPath, SiteBuilder): files: FilesSpec = { "distinfo_pkg-1.0.0.dist-info": { "METADATA": """ @@ -113,10 +122,6 @@ def main(): """, } - def setUp(self): - super().setUp() - build_files(DistInfoPkg.files, self.site_dir) - def make_uppercase(self): """ Rewrite metadata with everything uppercase. @@ -128,7 +133,28 @@ def make_uppercase(self): build_files(files, self.site_dir) -class DistInfoPkgWithDot(OnSysPath, SiteDir): +class DistInfoPkgEditable(DistInfoPkg): + """ + Package with a PEP 660 direct_url.json. + """ + + some_hash = '524127ce937f7cb65665130c695abd18ca386f60bb29687efb976faa1596fdcc' + files: FilesSpec = { + 'distinfo_pkg-1.0.0.dist-info': { + 'direct_url.json': json.dumps( + { + "archive_info": { + "hash": f"sha256={some_hash}", + "hashes": {"sha256": f"{some_hash}"}, + }, + "url": "file:///path/to/distinfo_pkg-1.0.0.editable-py3-none-any.whl", + } + ) + }, + } + + +class DistInfoPkgWithDot(OnSysPath, SiteBuilder): files: FilesSpec = { "pkg_dot-1.0.0.dist-info": { "METADATA": """ @@ -138,12 +164,8 @@ class DistInfoPkgWithDot(OnSysPath, SiteDir): }, } - def setUp(self): - super().setUp() - build_files(DistInfoPkgWithDot.files, self.site_dir) - -class DistInfoPkgWithDotLegacy(OnSysPath, SiteDir): +class DistInfoPkgWithDotLegacy(OnSysPath, SiteBuilder): files: FilesSpec = { "pkg.dot-1.0.0.dist-info": { "METADATA": """ @@ -159,18 +181,12 @@ class DistInfoPkgWithDotLegacy(OnSysPath, SiteDir): }, } - def setUp(self): - super().setUp() - build_files(DistInfoPkgWithDotLegacy.files, self.site_dir) - -class DistInfoPkgOffPath(SiteDir): - def setUp(self): - super().setUp() - build_files(DistInfoPkg.files, self.site_dir) +class DistInfoPkgOffPath(SiteBuilder): + files = DistInfoPkg.files -class EggInfoPkg(OnSysPath, SiteDir): +class EggInfoPkg(OnSysPath, SiteBuilder): files: FilesSpec = { "egginfo_pkg.egg-info": { "PKG-INFO": """ @@ -205,12 +221,8 @@ def main(): """, } - def setUp(self): - super().setUp() - build_files(EggInfoPkg.files, prefix=self.site_dir) - -class EggInfoPkgPipInstalledNoToplevel(OnSysPath, SiteDir): +class EggInfoPkgPipInstalledNoToplevel(OnSysPath, SiteBuilder): files: FilesSpec = { "egg_with_module_pkg.egg-info": { "PKG-INFO": "Name: egg_with_module-pkg", @@ -240,12 +252,8 @@ def main(): """, } - def setUp(self): - super().setUp() - build_files(EggInfoPkgPipInstalledNoToplevel.files, prefix=self.site_dir) - -class EggInfoPkgPipInstalledNoModules(OnSysPath, SiteDir): +class EggInfoPkgPipInstalledNoModules(OnSysPath, SiteBuilder): files: FilesSpec = { "egg_with_no_modules_pkg.egg-info": { "PKG-INFO": "Name: egg_with_no_modules-pkg", @@ -270,12 +278,8 @@ class EggInfoPkgPipInstalledNoModules(OnSysPath, SiteDir): }, } - def setUp(self): - super().setUp() - build_files(EggInfoPkgPipInstalledNoModules.files, prefix=self.site_dir) - -class EggInfoPkgSourcesFallback(OnSysPath, SiteDir): +class EggInfoPkgSourcesFallback(OnSysPath, SiteBuilder): files: FilesSpec = { "sources_fallback_pkg.egg-info": { "PKG-INFO": "Name: sources_fallback-pkg", @@ -296,12 +300,8 @@ def main(): """, } - def setUp(self): - super().setUp() - build_files(EggInfoPkgSourcesFallback.files, prefix=self.site_dir) - -class EggInfoFile(OnSysPath, SiteDir): +class EggInfoFile(OnSysPath, SiteBuilder): files: FilesSpec = { "egginfo_file.egg-info": """ Metadata-Version: 1.0 @@ -317,10 +317,6 @@ class EggInfoFile(OnSysPath, SiteDir): """, } - def setUp(self): - super().setUp() - build_files(EggInfoFile.files, prefix=self.site_dir) - # dedent all text strings before writing orig = _path.create.registry[str] diff --git a/Lib/test/test_importlib/import_/test_packages.py b/Lib/test/test_importlib/import_/test_packages.py index eb0831f7d6d54b..0c29d6083265fa 100644 --- a/Lib/test/test_importlib/import_/test_packages.py +++ b/Lib/test/test_importlib/import_/test_packages.py @@ -1,7 +1,6 @@ from test.test_importlib import util import sys import unittest -from test import support from test.support import import_helper diff --git a/Lib/test/test_importlib/test_locks.py b/Lib/test/test_importlib/test_locks.py index ba9cf51c261d52..befac5d62b0abf 100644 --- a/Lib/test/test_importlib/test_locks.py +++ b/Lib/test/test_importlib/test_locks.py @@ -29,6 +29,8 @@ class ModuleLockAsRLockTests: test_timeout = None # _release_save() unsupported test_release_save_unacquired = None + # _recursion_count() unsupported + test_recursion_count = None # lock status in repr unsupported test_repr = None test_locked_repr = None @@ -91,7 +93,8 @@ def f(): b.release() if ra: a.release() - lock_tests.Bunch(f, NTHREADS).wait_for_finished() + with lock_tests.Bunch(f, NTHREADS): + pass self.assertEqual(len(results), NTHREADS) return results diff --git a/Lib/test/test_importlib/test_main.py b/Lib/test/test_importlib/test_main.py index 3b49227255eb58..1d3817151edf64 100644 --- a/Lib/test/test_importlib/test_main.py +++ b/Lib/test/test_importlib/test_main.py @@ -12,6 +12,7 @@ from . import fixtures from ._context import suppress +from ._path import Symlink from importlib.metadata import ( Distribution, EntryPoint, @@ -68,7 +69,7 @@ def test_abc_enforced(self): dict(name=''), ) def test_invalid_inputs_to_from_name(self, name): - with self.assertRaises(ValueError): + with self.assertRaises(Exception): Distribution.from_name(name) @@ -207,6 +208,20 @@ def test_invalid_usage(self): with self.assertRaises(ValueError): list(distributions(context='something', name='else')) + def test_interleaved_discovery(self): + """ + Ensure interleaved searches are safe. + + When the search is cached, it is possible for searches to be + interleaved, so make sure those use-cases are safe. + + Ref #293 + """ + dists = distributions() + next(dists) + version('egginfo-pkg') + next(dists) + class DirectoryTest(fixtures.OnSysPath, fixtures.SiteDir, unittest.TestCase): def test_egg_info(self): @@ -388,6 +403,27 @@ def test_packages_distributions_all_module_types(self): assert not any(name.endswith('.dist-info') for name in distributions) + def test_packages_distributions_symlinked_top_level(self) -> None: + """ + Distribution is resolvable from a simple top-level symlink in RECORD. + See #452. + """ + + files: fixtures.FilesSpec = { + "symlinked_pkg-1.0.0.dist-info": { + "METADATA": """ + Name: symlinked-pkg + Version: 1.0.0 + """, + "RECORD": "symlinked,,\n", + }, + ".symlink.target": {}, + "symlinked": Symlink(".symlink.target"), + } + + fixtures.build_files(files, self.site_dir) + assert packages_distributions()['symlinked'] == ['symlinked-pkg'] + class PackagesDistributionsEggTest( fixtures.EggInfoPkg, @@ -424,3 +460,10 @@ def import_names_from_package(package_name): # sources_fallback-pkg has one import ('sources_fallback') inferred from # SOURCES.txt (top_level.txt and installed-files.txt is missing) assert import_names_from_package('sources_fallback-pkg') == {'sources_fallback'} + + +class EditableDistributionTest(fixtures.DistInfoPkgEditable, unittest.TestCase): + def test_origin(self): + dist = Distribution.from_name('distinfo-pkg') + assert dist.origin.url.endswith('.whl') + assert dist.origin.archive_info.hashes.sha256 diff --git a/Lib/test/test_importlib/test_namespace_pkgs.py b/Lib/test/test_importlib/test_namespace_pkgs.py index 9b3bef02c66820..072e198795d394 100644 --- a/Lib/test/test_importlib/test_namespace_pkgs.py +++ b/Lib/test/test_importlib/test_namespace_pkgs.py @@ -80,7 +80,7 @@ def test_cant_import_other(self): def test_simple_repr(self): import foo.one - assert repr(foo).startswith(" 42: pass self.assertEqual(str(inspect.signature(foo)), '(a: int = 1, *, b, c=None, **kwargs) -> 42') + self.assertEqual(str(inspect.signature(foo)), + inspect.signature(foo).format()) def foo(a:int=1, *args, b, c=None, **kwargs) -> 42: pass self.assertEqual(str(inspect.signature(foo)), '(a: int = 1, *args, b, c=None, **kwargs) -> 42') + self.assertEqual(str(inspect.signature(foo)), + inspect.signature(foo).format()) def foo(): pass self.assertEqual(str(inspect.signature(foo)), '()') + self.assertEqual(str(inspect.signature(foo)), + inspect.signature(foo).format()) def foo(a: list[str]) -> tuple[str, float]: pass self.assertEqual(str(inspect.signature(foo)), '(a: list[str]) -> tuple[str, float]') + self.assertEqual(str(inspect.signature(foo)), + inspect.signature(foo).format()) from typing import Tuple def foo(a: list[str]) -> Tuple[str, float]: pass self.assertEqual(str(inspect.signature(foo)), '(a: list[str]) -> Tuple[str, float]') + self.assertEqual(str(inspect.signature(foo)), + inspect.signature(foo).format()) def test_signature_str_positional_only(self): P = inspect.Parameter @@ -3723,19 +3836,107 @@ def test(a_po, /, *, b, **kwargs): self.assertEqual(str(inspect.signature(test)), '(a_po, /, *, b, **kwargs)') + self.assertEqual(str(inspect.signature(test)), + inspect.signature(test).format()) + + test = S(parameters=[P('foo', P.POSITIONAL_ONLY)]) + self.assertEqual(str(test), '(foo, /)') + self.assertEqual(str(test), test.format()) + + test = S(parameters=[P('foo', P.POSITIONAL_ONLY), + P('bar', P.VAR_KEYWORD)]) + self.assertEqual(str(test), '(foo, /, **bar)') + self.assertEqual(str(test), test.format()) + + test = S(parameters=[P('foo', P.POSITIONAL_ONLY), + P('bar', P.VAR_POSITIONAL)]) + self.assertEqual(str(test), '(foo, /, *bar)') + self.assertEqual(str(test), test.format()) + + def test_signature_format(self): + from typing import Annotated, Literal + + def func(x: Annotated[int, 'meta'], y: Literal['a', 'b'], z: 'LiteralString'): + pass + + expected_singleline = "(x: Annotated[int, 'meta'], y: Literal['a', 'b'], z: 'LiteralString')" + expected_multiline = """( + x: Annotated[int, 'meta'], + y: Literal['a', 'b'], + z: 'LiteralString' +)""" + self.assertEqual( + inspect.signature(func).format(), + expected_singleline, + ) + self.assertEqual( + inspect.signature(func).format(max_width=None), + expected_singleline, + ) + self.assertEqual( + inspect.signature(func).format(max_width=len(expected_singleline)), + expected_singleline, + ) + self.assertEqual( + inspect.signature(func).format(max_width=len(expected_singleline) - 1), + expected_multiline, + ) + self.assertEqual( + inspect.signature(func).format(max_width=0), + expected_multiline, + ) + self.assertEqual( + inspect.signature(func).format(max_width=-1), + expected_multiline, + ) - self.assertEqual(str(S(parameters=[P('foo', P.POSITIONAL_ONLY)])), - '(foo, /)') + def test_signature_format_all_arg_types(self): + from typing import Annotated, Literal + + def func( + x: Annotated[int, 'meta'], + /, + y: Literal['a', 'b'], + *, + z: 'LiteralString', + **kwargs: object, + ) -> None: + pass - self.assertEqual(str(S(parameters=[ - P('foo', P.POSITIONAL_ONLY), - P('bar', P.VAR_KEYWORD)])), - '(foo, /, **bar)') + expected_multiline = """( + x: Annotated[int, 'meta'], + /, + y: Literal['a', 'b'], + *, + z: 'LiteralString', + **kwargs: object +) -> None""" + self.assertEqual( + inspect.signature(func).format(max_width=-1), + expected_multiline, + ) - self.assertEqual(str(S(parameters=[ - P('foo', P.POSITIONAL_ONLY), - P('bar', P.VAR_POSITIONAL)])), - '(foo, /, *bar)') + def test_signature_replace_parameters(self): + def test(a, b) -> 42: + pass + + sig = inspect.signature(test) + parameters = sig.parameters + sig = sig.replace(parameters=list(parameters.values())[1:]) + self.assertEqual(list(sig.parameters), ['b']) + self.assertEqual(sig.parameters['b'], parameters['b']) + self.assertEqual(sig.return_annotation, 42) + sig = sig.replace(parameters=()) + self.assertEqual(dict(sig.parameters), {}) + + sig = inspect.signature(test) + parameters = sig.parameters + sig = copy.replace(sig, parameters=list(parameters.values())[1:]) + self.assertEqual(list(sig.parameters), ['b']) + self.assertEqual(sig.parameters['b'], parameters['b']) + self.assertEqual(sig.return_annotation, 42) + sig = copy.replace(sig, parameters=()) + self.assertEqual(dict(sig.parameters), {}) def test_signature_replace_anno(self): def test() -> 42: @@ -3750,6 +3951,15 @@ def test() -> 42: self.assertEqual(sig.return_annotation, 42) self.assertEqual(sig, inspect.signature(test)) + sig = inspect.signature(test) + sig = copy.replace(sig, return_annotation=None) + self.assertIs(sig.return_annotation, None) + sig = copy.replace(sig, return_annotation=sig.empty) + self.assertIs(sig.return_annotation, sig.empty) + sig = copy.replace(sig, return_annotation=42) + self.assertEqual(sig.return_annotation, 42) + self.assertEqual(sig, inspect.signature(test)) + def test_signature_replaced(self): def test(): pass @@ -3780,6 +3990,8 @@ def foo(a, *, b:1): pass foo_sig = MySignature.from_callable(foo) self.assertIsInstance(foo_sig, MySignature) + @unittest.skipIf(MISSING_C_DOCSTRINGS, + "Signature information for builtins requires docstrings") def test_signature_from_callable_class(self): # A regression test for a class inheriting its signature from `object`. class MySignature(inspect.Signature): pass @@ -3870,7 +4082,8 @@ def test_signature_eval_str(self): par('c', PORK, annotation="'MyClass'"), ))) - self.assertEqual(signature_func(isa.UnannotatedClass), sig()) + if not MISSING_C_DOCSTRINGS: + self.assertEqual(signature_func(isa.UnannotatedClass), sig()) self.assertEqual(signature_func(isa.unannotated_function), sig( parameters=( @@ -4094,41 +4307,66 @@ def test_signature_parameter_replace(self): p = inspect.Parameter('foo', default=42, kind=inspect.Parameter.KEYWORD_ONLY) - self.assertIsNot(p, p.replace()) - self.assertEqual(p, p.replace()) + self.assertIsNot(p.replace(), p) + self.assertEqual(p.replace(), p) + self.assertIsNot(copy.replace(p), p) + self.assertEqual(copy.replace(p), p) p2 = p.replace(annotation=1) self.assertEqual(p2.annotation, 1) p2 = p2.replace(annotation=p2.empty) - self.assertEqual(p, p2) + self.assertEqual(p2, p) + p3 = copy.replace(p, annotation=1) + self.assertEqual(p3.annotation, 1) + p3 = copy.replace(p3, annotation=p3.empty) + self.assertEqual(p3, p) p2 = p2.replace(name='bar') self.assertEqual(p2.name, 'bar') self.assertNotEqual(p2, p) + p3 = copy.replace(p3, name='bar') + self.assertEqual(p3.name, 'bar') + self.assertNotEqual(p3, p) with self.assertRaisesRegex(ValueError, 'name is a required attribute'): p2 = p2.replace(name=p2.empty) + with self.assertRaisesRegex(ValueError, + 'name is a required attribute'): + p3 = copy.replace(p3, name=p3.empty) p2 = p2.replace(name='foo', default=None) self.assertIs(p2.default, None) self.assertNotEqual(p2, p) + p3 = copy.replace(p3, name='foo', default=None) + self.assertIs(p3.default, None) + self.assertNotEqual(p3, p) p2 = p2.replace(name='foo', default=p2.empty) self.assertIs(p2.default, p2.empty) - + p3 = copy.replace(p3, name='foo', default=p3.empty) + self.assertIs(p3.default, p3.empty) p2 = p2.replace(default=42, kind=p2.POSITIONAL_OR_KEYWORD) self.assertEqual(p2.kind, p2.POSITIONAL_OR_KEYWORD) self.assertNotEqual(p2, p) + p3 = copy.replace(p3, default=42, kind=p3.POSITIONAL_OR_KEYWORD) + self.assertEqual(p3.kind, p3.POSITIONAL_OR_KEYWORD) + self.assertNotEqual(p3, p) with self.assertRaisesRegex(ValueError, "value " "is not a valid Parameter.kind"): p2 = p2.replace(kind=p2.empty) + with self.assertRaisesRegex(ValueError, + "value " + "is not a valid Parameter.kind"): + p3 = copy.replace(p3, kind=p3.empty) p2 = p2.replace(kind=p2.KEYWORD_ONLY) self.assertEqual(p2, p) + p3 = copy.replace(p3, kind=p3.KEYWORD_ONLY) + self.assertEqual(p3, p) def test_signature_parameter_positional_only(self): with self.assertRaisesRegex(TypeError, 'name must be a str'): @@ -4582,19 +4820,15 @@ def test_builtins_have_signatures(self): # These have unrepresentable parameter default values of NULL needs_null = {"anext"} no_signature |= needs_null - # These need PEP 457 groups or a signature change to accept None - needs_semantic_update = {"round"} - no_signature |= needs_semantic_update # These need *args support in Argument Clinic - needs_varargs = {"breakpoint", "min", "max", "print", - "__build_class__"} + needs_varargs = {"min", "max", "__build_class__"} no_signature |= needs_varargs - # These simply weren't covered in the initial AC conversion - # for builtin callables - not_converted_yet = {"open", "__import__"} - no_signature |= not_converted_yet # These builtin types are expected to provide introspection info - types_with_signatures = set() + types_with_signatures = { + 'bool', 'classmethod', 'complex', 'enumerate', 'filter', 'float', + 'frozenset', 'list', 'map', 'memoryview', 'object', 'property', + 'reversed', 'set', 'staticmethod', 'tuple', 'zip' + } # Check the signatures we expect to be there ns = vars(builtins) for name, obj in sorted(ns.items()): @@ -4607,15 +4841,19 @@ def test_builtins_have_signatures(self): if (name in no_signature): # Not yet converted continue + if name in {'classmethod', 'staticmethod'}: + # Bug gh-112006: inspect.unwrap() does not work with types + # with the __wrapped__ data descriptor. + continue with self.subTest(builtin=name): self.assertIsNotNone(inspect.signature(obj)) # Check callables that haven't been converted don't claim a signature # This ensures this test will start failing as more signatures are # added, so the affected items can be moved into the scope of the # regression test above - for name in no_signature: + for name in no_signature - needs_null: with self.subTest(builtin=name): - self.assertIsNone(obj.__text_signature__) + self.assertIsNone(ns[name].__text_signature__) def test_python_function_override_signature(self): def func(*args, **kwargs): @@ -4649,7 +4887,7 @@ def func(*args, **kwargs): def test_base_class_have_text_signature(self): # see issue 43118 - from test.ann_module7 import BufferedReader + from test.typinganndata.ann_module7 import BufferedReader class MyBufferedReader(BufferedReader): """buffer reader class.""" @@ -4804,7 +5042,7 @@ def assertInspectEqual(self, path, source): def test_getsource_reload(self): # see issue 1218234 - with _ready_to_import('reload_bug', self.src_before) as (name, path): + with ready_to_import('reload_bug', self.src_before) as (name, path): module = importlib.import_module(name) self.assertInspectEqual(path, module) with open(path, 'w', encoding='utf-8') as src: @@ -4812,5 +5050,66 @@ def test_getsource_reload(self): self.assertInspectEqual(path, module) +class TestRepl(unittest.TestCase): + + def spawn_repl(self, *args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, **kw): + """Run the Python REPL with the given arguments. + + kw is extra keyword args to pass to subprocess.Popen. Returns a Popen + object. + """ + + # To run the REPL without using a terminal, spawn python with the command + # line option '-i' and the process name set to ''. + # The directory of argv[0] must match the directory of the Python + # executable for the Popen() call to python to succeed as the directory + # path may be used by Py_GetPath() to build the default module search + # path. + stdin_fname = os.path.join(os.path.dirname(sys.executable), "") + cmd_line = [stdin_fname, '-E', '-i'] + cmd_line.extend(args) + + # Set TERM=vt100, for the rationale see the comments in spawn_python() of + # test.support.script_helper. + env = kw.setdefault('env', dict(os.environ)) + env['TERM'] = 'vt100' + return subprocess.Popen(cmd_line, + executable=sys.executable, + text=True, + stdin=subprocess.PIPE, + stdout=stdout, stderr=stderr, + **kw) + + def run_on_interactive_mode(self, source): + """Spawn a new Python interpreter, pass the given + input source code from the stdin and return the + result back. If the interpreter exits non-zero, it + raises a ValueError.""" + + process = self.spawn_repl() + process.stdin.write(source) + output = kill_python(process) + + if process.returncode != 0: + raise ValueError("Process didn't exit properly.") + return output + + @unittest.skipIf(not has_subprocess_support, "test requires subprocess") + def test_getsource(self): + output = self.run_on_interactive_mode(textwrap.dedent("""\ + def f(): + print(0) + return 1 + 2 + + import inspect + print(f"The source is: <<<{inspect.getsource(f)}>>>") + """)) + + expected = "The source is: <<>>" + self.assertIn(expected, output) + + + + if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_interpreters.py b/Lib/test/test_interpreters.py deleted file mode 100644 index 662eafa3b7a104..00000000000000 --- a/Lib/test/test_interpreters.py +++ /dev/null @@ -1,771 +0,0 @@ -import contextlib -import os -import threading -from textwrap import dedent -import unittest -import time - -from test import support -from test.support import import_helper -from test.support import threading_helper -_interpreters = import_helper.import_module('_xxsubinterpreters') -_channels = import_helper.import_module('_xxinterpchannels') -from test.support import interpreters - - -def _captured_script(script): - r, w = os.pipe() - indented = script.replace('\n', '\n ') - wrapped = dedent(f""" - import contextlib - with open({w}, 'w', encoding='utf-8') as spipe: - with contextlib.redirect_stdout(spipe): - {indented} - """) - return wrapped, open(r, encoding='utf-8') - - -def clean_up_interpreters(): - for interp in interpreters.list_all(): - if interp.id == 0: # main - continue - try: - interp.close() - except RuntimeError: - pass # already destroyed - - -def _run_output(interp, request, channels=None): - script, rpipe = _captured_script(request) - with rpipe: - interp.run(script, channels=channels) - return rpipe.read() - - -@contextlib.contextmanager -def _running(interp): - r, w = os.pipe() - def run(): - interp.run(dedent(f""" - # wait for "signal" - with open({r}) as rpipe: - rpipe.read() - """)) - - t = threading.Thread(target=run) - t.start() - - yield - - with open(w, 'w') as spipe: - spipe.write('done') - t.join() - - -class TestBase(unittest.TestCase): - - def tearDown(self): - clean_up_interpreters() - - -class CreateTests(TestBase): - - def test_in_main(self): - interp = interpreters.create() - self.assertIsInstance(interp, interpreters.Interpreter) - self.assertIn(interp, interpreters.list_all()) - - def test_in_thread(self): - lock = threading.Lock() - interp = None - def f(): - nonlocal interp - interp = interpreters.create() - lock.acquire() - lock.release() - t = threading.Thread(target=f) - with lock: - t.start() - t.join() - self.assertIn(interp, interpreters.list_all()) - - def test_in_subinterpreter(self): - main, = interpreters.list_all() - interp = interpreters.create() - out = _run_output(interp, dedent(""" - from test.support import interpreters - interp = interpreters.create() - print(interp.id) - """)) - interp2 = interpreters.Interpreter(int(out)) - self.assertEqual(interpreters.list_all(), [main, interp, interp2]) - - def test_after_destroy_all(self): - before = set(interpreters.list_all()) - # Create 3 subinterpreters. - interp_lst = [] - for _ in range(3): - interps = interpreters.create() - interp_lst.append(interps) - # Now destroy them. - for interp in interp_lst: - interp.close() - # Finally, create another. - interp = interpreters.create() - self.assertEqual(set(interpreters.list_all()), before | {interp}) - - def test_after_destroy_some(self): - before = set(interpreters.list_all()) - # Create 3 subinterpreters. - interp1 = interpreters.create() - interp2 = interpreters.create() - interp3 = interpreters.create() - # Now destroy 2 of them. - interp1.close() - interp2.close() - # Finally, create another. - interp = interpreters.create() - self.assertEqual(set(interpreters.list_all()), before | {interp3, interp}) - - -class GetCurrentTests(TestBase): - - def test_main(self): - main = interpreters.get_main() - current = interpreters.get_current() - self.assertEqual(current, main) - - def test_subinterpreter(self): - main = _interpreters.get_main() - interp = interpreters.create() - out = _run_output(interp, dedent(""" - from test.support import interpreters - cur = interpreters.get_current() - print(cur.id) - """)) - current = interpreters.Interpreter(int(out)) - self.assertNotEqual(current, main) - - -class ListAllTests(TestBase): - - def test_initial(self): - interps = interpreters.list_all() - self.assertEqual(1, len(interps)) - - def test_after_creating(self): - main = interpreters.get_current() - first = interpreters.create() - second = interpreters.create() - - ids = [] - for interp in interpreters.list_all(): - ids.append(interp.id) - - self.assertEqual(ids, [main.id, first.id, second.id]) - - def test_after_destroying(self): - main = interpreters.get_current() - first = interpreters.create() - second = interpreters.create() - first.close() - - ids = [] - for interp in interpreters.list_all(): - ids.append(interp.id) - - self.assertEqual(ids, [main.id, second.id]) - - -class TestInterpreterAttrs(TestBase): - - def test_id_type(self): - main = interpreters.get_main() - current = interpreters.get_current() - interp = interpreters.create() - self.assertIsInstance(main.id, _interpreters.InterpreterID) - self.assertIsInstance(current.id, _interpreters.InterpreterID) - self.assertIsInstance(interp.id, _interpreters.InterpreterID) - - def test_main_id(self): - main = interpreters.get_main() - self.assertEqual(main.id, 0) - - def test_custom_id(self): - interp = interpreters.Interpreter(1) - self.assertEqual(interp.id, 1) - - with self.assertRaises(TypeError): - interpreters.Interpreter('1') - - def test_id_readonly(self): - interp = interpreters.Interpreter(1) - with self.assertRaises(AttributeError): - interp.id = 2 - - @unittest.skip('not ready yet (see bpo-32604)') - def test_main_isolated(self): - main = interpreters.get_main() - self.assertFalse(main.isolated) - - @unittest.skip('not ready yet (see bpo-32604)') - def test_subinterpreter_isolated_default(self): - interp = interpreters.create() - self.assertFalse(interp.isolated) - - def test_subinterpreter_isolated_explicit(self): - interp1 = interpreters.create(isolated=True) - interp2 = interpreters.create(isolated=False) - self.assertTrue(interp1.isolated) - self.assertFalse(interp2.isolated) - - @unittest.skip('not ready yet (see bpo-32604)') - def test_custom_isolated_default(self): - interp = interpreters.Interpreter(1) - self.assertFalse(interp.isolated) - - def test_custom_isolated_explicit(self): - interp1 = interpreters.Interpreter(1, isolated=True) - interp2 = interpreters.Interpreter(1, isolated=False) - self.assertTrue(interp1.isolated) - self.assertFalse(interp2.isolated) - - def test_isolated_readonly(self): - interp = interpreters.Interpreter(1) - with self.assertRaises(AttributeError): - interp.isolated = True - - def test_equality(self): - interp1 = interpreters.create() - interp2 = interpreters.create() - self.assertEqual(interp1, interp1) - self.assertNotEqual(interp1, interp2) - - -class TestInterpreterIsRunning(TestBase): - - def test_main(self): - main = interpreters.get_main() - self.assertTrue(main.is_running()) - - @unittest.skip('Fails on FreeBSD') - def test_subinterpreter(self): - interp = interpreters.create() - self.assertFalse(interp.is_running()) - - with _running(interp): - self.assertTrue(interp.is_running()) - self.assertFalse(interp.is_running()) - - def test_from_subinterpreter(self): - interp = interpreters.create() - out = _run_output(interp, dedent(f""" - import _xxsubinterpreters as _interpreters - if _interpreters.is_running({interp.id}): - print(True) - else: - print(False) - """)) - self.assertEqual(out.strip(), 'True') - - def test_already_destroyed(self): - interp = interpreters.create() - interp.close() - with self.assertRaises(RuntimeError): - interp.is_running() - - def test_does_not_exist(self): - interp = interpreters.Interpreter(1_000_000) - with self.assertRaises(RuntimeError): - interp.is_running() - - def test_bad_id(self): - interp = interpreters.Interpreter(-1) - with self.assertRaises(ValueError): - interp.is_running() - - -class TestInterpreterClose(TestBase): - - def test_basic(self): - main = interpreters.get_main() - interp1 = interpreters.create() - interp2 = interpreters.create() - interp3 = interpreters.create() - self.assertEqual(set(interpreters.list_all()), - {main, interp1, interp2, interp3}) - interp2.close() - self.assertEqual(set(interpreters.list_all()), - {main, interp1, interp3}) - - def test_all(self): - before = set(interpreters.list_all()) - interps = set() - for _ in range(3): - interp = interpreters.create() - interps.add(interp) - self.assertEqual(set(interpreters.list_all()), before | interps) - for interp in interps: - interp.close() - self.assertEqual(set(interpreters.list_all()), before) - - def test_main(self): - main, = interpreters.list_all() - with self.assertRaises(RuntimeError): - main.close() - - def f(): - with self.assertRaises(RuntimeError): - main.close() - - t = threading.Thread(target=f) - t.start() - t.join() - - def test_already_destroyed(self): - interp = interpreters.create() - interp.close() - with self.assertRaises(RuntimeError): - interp.close() - - def test_does_not_exist(self): - interp = interpreters.Interpreter(1_000_000) - with self.assertRaises(RuntimeError): - interp.close() - - def test_bad_id(self): - interp = interpreters.Interpreter(-1) - with self.assertRaises(ValueError): - interp.close() - - def test_from_current(self): - main, = interpreters.list_all() - interp = interpreters.create() - out = _run_output(interp, dedent(f""" - from test.support import interpreters - interp = interpreters.Interpreter({int(interp.id)}) - try: - interp.close() - except RuntimeError: - print('failed') - """)) - self.assertEqual(out.strip(), 'failed') - self.assertEqual(set(interpreters.list_all()), {main, interp}) - - def test_from_sibling(self): - main, = interpreters.list_all() - interp1 = interpreters.create() - interp2 = interpreters.create() - self.assertEqual(set(interpreters.list_all()), - {main, interp1, interp2}) - interp1.run(dedent(f""" - from test.support import interpreters - interp2 = interpreters.Interpreter(int({interp2.id})) - interp2.close() - interp3 = interpreters.create() - interp3.close() - """)) - self.assertEqual(set(interpreters.list_all()), {main, interp1}) - - def test_from_other_thread(self): - interp = interpreters.create() - def f(): - interp.close() - - t = threading.Thread(target=f) - t.start() - t.join() - - @unittest.skip('Fails on FreeBSD') - def test_still_running(self): - main, = interpreters.list_all() - interp = interpreters.create() - with _running(interp): - with self.assertRaises(RuntimeError): - interp.close() - self.assertTrue(interp.is_running()) - - -class TestInterpreterRun(TestBase): - - def test_success(self): - interp = interpreters.create() - script, file = _captured_script('print("it worked!", end="")') - with file: - interp.run(script) - out = file.read() - - self.assertEqual(out, 'it worked!') - - def test_in_thread(self): - interp = interpreters.create() - script, file = _captured_script('print("it worked!", end="")') - with file: - def f(): - interp.run(script) - - t = threading.Thread(target=f) - t.start() - t.join() - out = file.read() - - self.assertEqual(out, 'it worked!') - - @support.requires_fork() - def test_fork(self): - interp = interpreters.create() - import tempfile - with tempfile.NamedTemporaryFile('w+', encoding='utf-8') as file: - file.write('') - file.flush() - - expected = 'spam spam spam spam spam' - script = dedent(f""" - import os - try: - os.fork() - except RuntimeError: - with open('{file.name}', 'w', encoding='utf-8') as out: - out.write('{expected}') - """) - interp.run(script) - - file.seek(0) - content = file.read() - self.assertEqual(content, expected) - - @unittest.skip('Fails on FreeBSD') - def test_already_running(self): - interp = interpreters.create() - with _running(interp): - with self.assertRaises(RuntimeError): - interp.run('print("spam")') - - def test_does_not_exist(self): - interp = interpreters.Interpreter(1_000_000) - with self.assertRaises(RuntimeError): - interp.run('print("spam")') - - def test_bad_id(self): - interp = interpreters.Interpreter(-1) - with self.assertRaises(ValueError): - interp.run('print("spam")') - - def test_bad_script(self): - interp = interpreters.create() - with self.assertRaises(TypeError): - interp.run(10) - - def test_bytes_for_script(self): - interp = interpreters.create() - with self.assertRaises(TypeError): - interp.run(b'print("spam")') - - # test_xxsubinterpreters covers the remaining Interpreter.run() behavior. - - -@unittest.skip('these are crashing, likely just due just to _xxsubinterpreters (see gh-105699)') -class StressTests(TestBase): - - # In these tests we generally want a lot of interpreters, - # but not so many that any test takes too long. - - def test_create_many_sequential(self): - alive = [] - for _ in range(100): - interp = interpreters.create() - alive.append(interp) - - def test_create_many_threaded(self): - alive = [] - def task(): - interp = interpreters.create() - alive.append(interp) - threads = (threading.Thread(target=task) for _ in range(200)) - with threading_helper.start_threads(threads): - pass - - -class TestIsShareable(TestBase): - - def test_default_shareables(self): - shareables = [ - # singletons - None, - # builtin objects - b'spam', - 'spam', - 10, - -10, - ] - for obj in shareables: - with self.subTest(obj): - shareable = interpreters.is_shareable(obj) - self.assertTrue(shareable) - - def test_not_shareable(self): - class Cheese: - def __init__(self, name): - self.name = name - def __str__(self): - return self.name - - class SubBytes(bytes): - """A subclass of a shareable type.""" - - not_shareables = [ - # singletons - True, - False, - NotImplemented, - ..., - # builtin types and objects - type, - object, - object(), - Exception(), - 100.0, - # user-defined types and objects - Cheese, - Cheese('Wensleydale'), - SubBytes(b'spam'), - ] - for obj in not_shareables: - with self.subTest(repr(obj)): - self.assertFalse( - interpreters.is_shareable(obj)) - - -class TestChannels(TestBase): - - def test_create(self): - r, s = interpreters.create_channel() - self.assertIsInstance(r, interpreters.RecvChannel) - self.assertIsInstance(s, interpreters.SendChannel) - - def test_list_all(self): - self.assertEqual(interpreters.list_all_channels(), []) - created = set() - for _ in range(3): - ch = interpreters.create_channel() - created.add(ch) - after = set(interpreters.list_all_channels()) - self.assertEqual(after, created) - - -class TestRecvChannelAttrs(TestBase): - - def test_id_type(self): - rch, _ = interpreters.create_channel() - self.assertIsInstance(rch.id, _channels.ChannelID) - - def test_custom_id(self): - rch = interpreters.RecvChannel(1) - self.assertEqual(rch.id, 1) - - with self.assertRaises(TypeError): - interpreters.RecvChannel('1') - - def test_id_readonly(self): - rch = interpreters.RecvChannel(1) - with self.assertRaises(AttributeError): - rch.id = 2 - - def test_equality(self): - ch1, _ = interpreters.create_channel() - ch2, _ = interpreters.create_channel() - self.assertEqual(ch1, ch1) - self.assertNotEqual(ch1, ch2) - - -class TestSendChannelAttrs(TestBase): - - def test_id_type(self): - _, sch = interpreters.create_channel() - self.assertIsInstance(sch.id, _channels.ChannelID) - - def test_custom_id(self): - sch = interpreters.SendChannel(1) - self.assertEqual(sch.id, 1) - - with self.assertRaises(TypeError): - interpreters.SendChannel('1') - - def test_id_readonly(self): - sch = interpreters.SendChannel(1) - with self.assertRaises(AttributeError): - sch.id = 2 - - def test_equality(self): - _, ch1 = interpreters.create_channel() - _, ch2 = interpreters.create_channel() - self.assertEqual(ch1, ch1) - self.assertNotEqual(ch1, ch2) - - -class TestSendRecv(TestBase): - - def test_send_recv_main(self): - r, s = interpreters.create_channel() - orig = b'spam' - s.send_nowait(orig) - obj = r.recv() - - self.assertEqual(obj, orig) - self.assertIsNot(obj, orig) - - def test_send_recv_same_interpreter(self): - interp = interpreters.create() - interp.run(dedent(""" - from test.support import interpreters - r, s = interpreters.create_channel() - orig = b'spam' - s.send_nowait(orig) - obj = r.recv() - assert obj == orig, 'expected: obj == orig' - assert obj is not orig, 'expected: obj is not orig' - """)) - - @unittest.skip('broken (see BPO-...)') - def test_send_recv_different_interpreters(self): - r1, s1 = interpreters.create_channel() - r2, s2 = interpreters.create_channel() - orig1 = b'spam' - s1.send_nowait(orig1) - out = _run_output( - interpreters.create(), - dedent(f""" - obj1 = r.recv() - assert obj1 == b'spam', 'expected: obj1 == orig1' - # When going to another interpreter we get a copy. - assert id(obj1) != {id(orig1)}, 'expected: obj1 is not orig1' - orig2 = b'eggs' - print(id(orig2)) - s.send_nowait(orig2) - """), - channels=dict(r=r1, s=s2), - ) - obj2 = r2.recv() - - self.assertEqual(obj2, b'eggs') - self.assertNotEqual(id(obj2), int(out)) - - def test_send_recv_different_threads(self): - r, s = interpreters.create_channel() - - def f(): - while True: - try: - obj = r.recv() - break - except interpreters.ChannelEmptyError: - time.sleep(0.1) - s.send(obj) - t = threading.Thread(target=f) - t.start() - - orig = b'spam' - s.send(orig) - t.join() - obj = r.recv() - - self.assertEqual(obj, orig) - self.assertIsNot(obj, orig) - - def test_send_recv_nowait_main(self): - r, s = interpreters.create_channel() - orig = b'spam' - s.send_nowait(orig) - obj = r.recv_nowait() - - self.assertEqual(obj, orig) - self.assertIsNot(obj, orig) - - def test_send_recv_nowait_main_with_default(self): - r, _ = interpreters.create_channel() - obj = r.recv_nowait(None) - - self.assertIsNone(obj) - - def test_send_recv_nowait_same_interpreter(self): - interp = interpreters.create() - interp.run(dedent(""" - from test.support import interpreters - r, s = interpreters.create_channel() - orig = b'spam' - s.send_nowait(orig) - obj = r.recv_nowait() - assert obj == orig, 'expected: obj == orig' - # When going back to the same interpreter we get the same object. - assert obj is not orig, 'expected: obj is not orig' - """)) - - @unittest.skip('broken (see BPO-...)') - def test_send_recv_nowait_different_interpreters(self): - r1, s1 = interpreters.create_channel() - r2, s2 = interpreters.create_channel() - orig1 = b'spam' - s1.send_nowait(orig1) - out = _run_output( - interpreters.create(), - dedent(f""" - obj1 = r.recv_nowait() - assert obj1 == b'spam', 'expected: obj1 == orig1' - # When going to another interpreter we get a copy. - assert id(obj1) != {id(orig1)}, 'expected: obj1 is not orig1' - orig2 = b'eggs' - print(id(orig2)) - s.send_nowait(orig2) - """), - channels=dict(r=r1, s=s2), - ) - obj2 = r2.recv_nowait() - - self.assertEqual(obj2, b'eggs') - self.assertNotEqual(id(obj2), int(out)) - - def test_recv_channel_does_not_exist(self): - ch = interpreters.RecvChannel(1_000_000) - with self.assertRaises(interpreters.ChannelNotFoundError): - ch.recv() - - def test_send_channel_does_not_exist(self): - ch = interpreters.SendChannel(1_000_000) - with self.assertRaises(interpreters.ChannelNotFoundError): - ch.send(b'spam') - - def test_recv_nowait_channel_does_not_exist(self): - ch = interpreters.RecvChannel(1_000_000) - with self.assertRaises(interpreters.ChannelNotFoundError): - ch.recv_nowait() - - def test_send_nowait_channel_does_not_exist(self): - ch = interpreters.SendChannel(1_000_000) - with self.assertRaises(interpreters.ChannelNotFoundError): - ch.send_nowait(b'spam') - - def test_recv_nowait_empty(self): - ch, _ = interpreters.create_channel() - with self.assertRaises(interpreters.ChannelEmptyError): - ch.recv_nowait() - - def test_recv_nowait_default(self): - default = object() - rch, sch = interpreters.create_channel() - obj1 = rch.recv_nowait(default) - sch.send_nowait(None) - sch.send_nowait(1) - sch.send_nowait(b'spam') - sch.send_nowait(b'eggs') - obj2 = rch.recv_nowait(default) - obj3 = rch.recv_nowait(default) - obj4 = rch.recv_nowait() - obj5 = rch.recv_nowait(default) - obj6 = rch.recv_nowait(default) - - self.assertIs(obj1, default) - self.assertIs(obj2, None) - self.assertEqual(obj3, 1) - self.assertEqual(obj4, b'spam') - self.assertEqual(obj5, b'eggs') - self.assertIs(obj6, default) diff --git a/Lib/test/test_interpreters/__init__.py b/Lib/test/test_interpreters/__init__.py new file mode 100644 index 00000000000000..4b16ecc31156a5 --- /dev/null +++ b/Lib/test/test_interpreters/__init__.py @@ -0,0 +1,5 @@ +import os +from test.support import load_package_tests + +def load_tests(*args): + return load_package_tests(os.path.dirname(__file__), *args) diff --git a/Lib/test/test_interpreters/__main__.py b/Lib/test/test_interpreters/__main__.py new file mode 100644 index 00000000000000..40a23a297ec2b4 --- /dev/null +++ b/Lib/test/test_interpreters/__main__.py @@ -0,0 +1,4 @@ +from . import load_tests +import unittest + +unittest.main() diff --git a/Lib/test/test_interpreters/test_api.py b/Lib/test/test_interpreters/test_api.py new file mode 100644 index 00000000000000..aefd326977095f --- /dev/null +++ b/Lib/test/test_interpreters/test_api.py @@ -0,0 +1,747 @@ +import os +import threading +from textwrap import dedent +import unittest + +from test import support +from test.support import import_helper +# Raise SkipTest if subinterpreters not supported. +import_helper.import_module('_xxsubinterpreters') +from test.support import interpreters +from test.support.interpreters import InterpreterNotFoundError +from .utils import _captured_script, _run_output, _running, TestBase + + +class ModuleTests(TestBase): + + def test_queue_aliases(self): + first = [ + interpreters.create_queue, + interpreters.Queue, + interpreters.QueueEmpty, + interpreters.QueueFull, + ] + second = [ + interpreters.create_queue, + interpreters.Queue, + interpreters.QueueEmpty, + interpreters.QueueFull, + ] + self.assertEqual(second, first) + + +class CreateTests(TestBase): + + def test_in_main(self): + interp = interpreters.create() + self.assertIsInstance(interp, interpreters.Interpreter) + self.assertIn(interp, interpreters.list_all()) + + def test_in_thread(self): + lock = threading.Lock() + interp = None + def f(): + nonlocal interp + interp = interpreters.create() + lock.acquire() + lock.release() + t = threading.Thread(target=f) + with lock: + t.start() + t.join() + self.assertIn(interp, interpreters.list_all()) + + def test_in_subinterpreter(self): + main, = interpreters.list_all() + interp = interpreters.create() + out = _run_output(interp, dedent(""" + from test.support import interpreters + interp = interpreters.create() + print(interp.id) + """)) + interp2 = interpreters.Interpreter(int(out)) + self.assertEqual(interpreters.list_all(), [main, interp, interp2]) + + def test_after_destroy_all(self): + before = set(interpreters.list_all()) + # Create 3 subinterpreters. + interp_lst = [] + for _ in range(3): + interps = interpreters.create() + interp_lst.append(interps) + # Now destroy them. + for interp in interp_lst: + interp.close() + # Finally, create another. + interp = interpreters.create() + self.assertEqual(set(interpreters.list_all()), before | {interp}) + + def test_after_destroy_some(self): + before = set(interpreters.list_all()) + # Create 3 subinterpreters. + interp1 = interpreters.create() + interp2 = interpreters.create() + interp3 = interpreters.create() + # Now destroy 2 of them. + interp1.close() + interp2.close() + # Finally, create another. + interp = interpreters.create() + self.assertEqual(set(interpreters.list_all()), before | {interp3, interp}) + + +class GetMainTests(TestBase): + + def test_id(self): + main = interpreters.get_main() + self.assertEqual(main.id, 0) + + def test_current(self): + main = interpreters.get_main() + current = interpreters.get_current() + self.assertIs(main, current) + + def test_idempotent(self): + main1 = interpreters.get_main() + main2 = interpreters.get_main() + self.assertIs(main1, main2) + + +class GetCurrentTests(TestBase): + + def test_main(self): + main = interpreters.get_main() + current = interpreters.get_current() + self.assertEqual(current, main) + + def test_subinterpreter(self): + main = interpreters.get_main() + interp = interpreters.create() + out = _run_output(interp, dedent(""" + from test.support import interpreters + cur = interpreters.get_current() + print(cur.id) + """)) + current = interpreters.Interpreter(int(out)) + self.assertEqual(current, interp) + self.assertNotEqual(current, main) + + def test_idempotent(self): + with self.subTest('main'): + cur1 = interpreters.get_current() + cur2 = interpreters.get_current() + self.assertIs(cur1, cur2) + + with self.subTest('subinterpreter'): + interp = interpreters.create() + out = _run_output(interp, dedent(""" + from test.support import interpreters + cur = interpreters.get_current() + print(id(cur)) + cur = interpreters.get_current() + print(id(cur)) + """)) + objid1, objid2 = (int(v) for v in out.splitlines()) + self.assertEqual(objid1, objid2) + + with self.subTest('per-interpreter'): + interp = interpreters.create() + out = _run_output(interp, dedent(""" + from test.support import interpreters + cur = interpreters.get_current() + print(id(cur)) + """)) + id1 = int(out) + id2 = id(interp) + self.assertNotEqual(id1, id2) + + +class ListAllTests(TestBase): + + def test_initial(self): + interps = interpreters.list_all() + self.assertEqual(1, len(interps)) + + def test_after_creating(self): + main = interpreters.get_current() + first = interpreters.create() + second = interpreters.create() + + ids = [] + for interp in interpreters.list_all(): + ids.append(interp.id) + + self.assertEqual(ids, [main.id, first.id, second.id]) + + def test_after_destroying(self): + main = interpreters.get_current() + first = interpreters.create() + second = interpreters.create() + first.close() + + ids = [] + for interp in interpreters.list_all(): + ids.append(interp.id) + + self.assertEqual(ids, [main.id, second.id]) + + def test_idempotent(self): + main = interpreters.get_current() + first = interpreters.create() + second = interpreters.create() + expected = [main, first, second] + + actual = interpreters.list_all() + + self.assertEqual(actual, expected) + for interp1, interp2 in zip(actual, expected): + self.assertIs(interp1, interp2) + + +class InterpreterObjectTests(TestBase): + + def test_init_int(self): + interpid = interpreters.get_current().id + interp = interpreters.Interpreter(interpid) + self.assertEqual(interp.id, interpid) + + def test_init_interpreter_id(self): + interpid = interpreters.get_current()._id + interp = interpreters.Interpreter(interpid) + self.assertEqual(interp._id, interpid) + + def test_init_unsupported(self): + actualid = interpreters.get_current().id + for interpid in [ + str(actualid), + float(actualid), + object(), + None, + '', + ]: + with self.subTest(repr(interpid)): + with self.assertRaises(TypeError): + interpreters.Interpreter(interpid) + + def test_idempotent(self): + main = interpreters.get_main() + interp = interpreters.Interpreter(main.id) + self.assertIs(interp, main) + + def test_init_does_not_exist(self): + with self.assertRaises(InterpreterNotFoundError): + interpreters.Interpreter(1_000_000) + + def test_init_bad_id(self): + with self.assertRaises(ValueError): + interpreters.Interpreter(-1) + + def test_id_type(self): + main = interpreters.get_main() + current = interpreters.get_current() + interp = interpreters.create() + self.assertIsInstance(main.id, int) + self.assertIsInstance(current.id, int) + self.assertIsInstance(interp.id, int) + + def test_id_readonly(self): + interp = interpreters.create() + with self.assertRaises(AttributeError): + interp.id = 1_000_000 + + def test_hashable(self): + interp = interpreters.create() + expected = hash(interp.id) + actual = hash(interp) + self.assertEqual(actual, expected) + + def test_equality(self): + interp1 = interpreters.create() + interp2 = interpreters.create() + self.assertEqual(interp1, interp1) + self.assertNotEqual(interp1, interp2) + + +class TestInterpreterIsRunning(TestBase): + + def test_main(self): + main = interpreters.get_main() + self.assertTrue(main.is_running()) + + @unittest.skip('Fails on FreeBSD') + def test_subinterpreter(self): + interp = interpreters.create() + self.assertFalse(interp.is_running()) + + with _running(interp): + self.assertTrue(interp.is_running()) + self.assertFalse(interp.is_running()) + + def test_finished(self): + r, w = self.pipe() + interp = interpreters.create() + interp.exec_sync(f"""if True: + import os + os.write({w}, b'x') + """) + self.assertFalse(interp.is_running()) + self.assertEqual(os.read(r, 1), b'x') + + def test_from_subinterpreter(self): + interp = interpreters.create() + out = _run_output(interp, dedent(f""" + import _xxsubinterpreters as _interpreters + if _interpreters.is_running({interp.id}): + print(True) + else: + print(False) + """)) + self.assertEqual(out.strip(), 'True') + + def test_already_destroyed(self): + interp = interpreters.create() + interp.close() + with self.assertRaises(InterpreterNotFoundError): + interp.is_running() + + def test_with_only_background_threads(self): + r_interp, w_interp = self.pipe() + r_thread, w_thread = self.pipe() + + DONE = b'D' + FINISHED = b'F' + + interp = interpreters.create() + interp.exec_sync(f"""if True: + import os + import threading + + def task(): + v = os.read({r_thread}, 1) + assert v == {DONE!r} + os.write({w_interp}, {FINISHED!r}) + t = threading.Thread(target=task) + t.start() + """) + self.assertFalse(interp.is_running()) + + os.write(w_thread, DONE) + interp.exec_sync('t.join()') + self.assertEqual(os.read(r_interp, 1), FINISHED) + + +class TestInterpreterClose(TestBase): + + def test_basic(self): + main = interpreters.get_main() + interp1 = interpreters.create() + interp2 = interpreters.create() + interp3 = interpreters.create() + self.assertEqual(set(interpreters.list_all()), + {main, interp1, interp2, interp3}) + interp2.close() + self.assertEqual(set(interpreters.list_all()), + {main, interp1, interp3}) + + def test_all(self): + before = set(interpreters.list_all()) + interps = set() + for _ in range(3): + interp = interpreters.create() + interps.add(interp) + self.assertEqual(set(interpreters.list_all()), before | interps) + for interp in interps: + interp.close() + self.assertEqual(set(interpreters.list_all()), before) + + def test_main(self): + main, = interpreters.list_all() + with self.assertRaises(RuntimeError): + main.close() + + def f(): + with self.assertRaises(RuntimeError): + main.close() + + t = threading.Thread(target=f) + t.start() + t.join() + + def test_already_destroyed(self): + interp = interpreters.create() + interp.close() + with self.assertRaises(InterpreterNotFoundError): + interp.close() + + def test_from_current(self): + main, = interpreters.list_all() + interp = interpreters.create() + out = _run_output(interp, dedent(f""" + from test.support import interpreters + interp = interpreters.Interpreter({interp.id}) + try: + interp.close() + except RuntimeError: + print('failed') + """)) + self.assertEqual(out.strip(), 'failed') + self.assertEqual(set(interpreters.list_all()), {main, interp}) + + def test_from_sibling(self): + main, = interpreters.list_all() + interp1 = interpreters.create() + interp2 = interpreters.create() + self.assertEqual(set(interpreters.list_all()), + {main, interp1, interp2}) + interp1.exec_sync(dedent(f""" + from test.support import interpreters + interp2 = interpreters.Interpreter({interp2.id}) + interp2.close() + interp3 = interpreters.create() + interp3.close() + """)) + self.assertEqual(set(interpreters.list_all()), {main, interp1}) + + def test_from_other_thread(self): + interp = interpreters.create() + def f(): + interp.close() + + t = threading.Thread(target=f) + t.start() + t.join() + + @unittest.skip('Fails on FreeBSD') + def test_still_running(self): + main, = interpreters.list_all() + interp = interpreters.create() + with _running(interp): + with self.assertRaises(RuntimeError): + interp.close() + self.assertTrue(interp.is_running()) + + def test_subthreads_still_running(self): + r_interp, w_interp = self.pipe() + r_thread, w_thread = self.pipe() + + FINISHED = b'F' + + interp = interpreters.create() + interp.exec_sync(f"""if True: + import os + import threading + import time + + done = False + + def notify_fini(): + global done + done = True + t.join() + threading._register_atexit(notify_fini) + + def task(): + while not done: + time.sleep(0.1) + os.write({w_interp}, {FINISHED!r}) + t = threading.Thread(target=task) + t.start() + """) + interp.close() + + self.assertEqual(os.read(r_interp, 1), FINISHED) + + +class TestInterpreterPrepareMain(TestBase): + + def test_empty(self): + interp = interpreters.create() + with self.assertRaises(ValueError): + interp.prepare_main() + + def test_dict(self): + values = {'spam': 42, 'eggs': 'ham'} + interp = interpreters.create() + interp.prepare_main(values) + out = _run_output(interp, dedent(""" + print(spam, eggs) + """)) + self.assertEqual(out.strip(), '42 ham') + + def test_tuple(self): + values = {'spam': 42, 'eggs': 'ham'} + values = tuple(values.items()) + interp = interpreters.create() + interp.prepare_main(values) + out = _run_output(interp, dedent(""" + print(spam, eggs) + """)) + self.assertEqual(out.strip(), '42 ham') + + def test_kwargs(self): + values = {'spam': 42, 'eggs': 'ham'} + interp = interpreters.create() + interp.prepare_main(**values) + out = _run_output(interp, dedent(""" + print(spam, eggs) + """)) + self.assertEqual(out.strip(), '42 ham') + + def test_dict_and_kwargs(self): + values = {'spam': 42, 'eggs': 'ham'} + interp = interpreters.create() + interp.prepare_main(values, foo='bar') + out = _run_output(interp, dedent(""" + print(spam, eggs, foo) + """)) + self.assertEqual(out.strip(), '42 ham bar') + + def test_not_shareable(self): + interp = interpreters.create() + # XXX TypeError? + with self.assertRaises(ValueError): + interp.prepare_main(spam={'spam': 'eggs', 'foo': 'bar'}) + + # Make sure neither was actually bound. + with self.assertRaises(interpreters.ExecFailure): + interp.exec_sync('print(foo)') + with self.assertRaises(interpreters.ExecFailure): + interp.exec_sync('print(spam)') + + +class TestInterpreterExecSync(TestBase): + + def test_success(self): + interp = interpreters.create() + script, file = _captured_script('print("it worked!", end="")') + with file: + interp.exec_sync(script) + out = file.read() + + self.assertEqual(out, 'it worked!') + + def test_failure(self): + interp = interpreters.create() + with self.assertRaises(interpreters.ExecFailure): + interp.exec_sync('raise Exception') + + def test_display_preserved_exception(self): + tempdir = self.temp_dir() + modfile = self.make_module('spam', tempdir, text=""" + def ham(): + raise RuntimeError('uh-oh!') + + def eggs(): + ham() + """) + scriptfile = self.make_script('script.py', tempdir, text=""" + from test.support import interpreters + + def script(): + import spam + spam.eggs() + + interp = interpreters.create() + interp.exec_sync(script) + """) + + stdout, stderr = self.assert_python_failure(scriptfile) + self.maxDiff = None + interpmod_line, = (l for l in stderr.splitlines() if ' exec_sync' in l) + # File "{interpreters.__file__}", line 179, in exec_sync + self.assertEqual(stderr, dedent(f"""\ + Traceback (most recent call last): + File "{scriptfile}", line 9, in + interp.exec_sync(script) + ~~~~~~~~~~~~~~~~^^^^^^^^ + {interpmod_line.strip()} + raise ExecFailure(excinfo) + test.support.interpreters.ExecFailure: RuntimeError: uh-oh! + + Uncaught in the interpreter: + + Traceback (most recent call last): + File "{scriptfile}", line 6, in script + spam.eggs() + ~~~~~~~~~^^ + File "{modfile}", line 6, in eggs + ham() + ~~~^^ + File "{modfile}", line 3, in ham + raise RuntimeError('uh-oh!') + RuntimeError: uh-oh! + """)) + self.assertEqual(stdout, '') + + def test_in_thread(self): + interp = interpreters.create() + script, file = _captured_script('print("it worked!", end="")') + with file: + def f(): + interp.exec_sync(script) + + t = threading.Thread(target=f) + t.start() + t.join() + out = file.read() + + self.assertEqual(out, 'it worked!') + + @support.requires_fork() + def test_fork(self): + interp = interpreters.create() + import tempfile + with tempfile.NamedTemporaryFile('w+', encoding='utf-8') as file: + file.write('') + file.flush() + + expected = 'spam spam spam spam spam' + script = dedent(f""" + import os + try: + os.fork() + except RuntimeError: + with open('{file.name}', 'w', encoding='utf-8') as out: + out.write('{expected}') + """) + interp.exec_sync(script) + + file.seek(0) + content = file.read() + self.assertEqual(content, expected) + + @unittest.skip('Fails on FreeBSD') + def test_already_running(self): + interp = interpreters.create() + with _running(interp): + with self.assertRaises(RuntimeError): + interp.exec_sync('print("spam")') + + def test_bad_script(self): + interp = interpreters.create() + with self.assertRaises(TypeError): + interp.exec_sync(10) + + def test_bytes_for_script(self): + interp = interpreters.create() + with self.assertRaises(TypeError): + interp.exec_sync(b'print("spam")') + + def test_with_background_threads_still_running(self): + r_interp, w_interp = self.pipe() + r_thread, w_thread = self.pipe() + + RAN = b'R' + DONE = b'D' + FINISHED = b'F' + + interp = interpreters.create() + interp.exec_sync(f"""if True: + import os + import threading + + def task(): + v = os.read({r_thread}, 1) + assert v == {DONE!r} + os.write({w_interp}, {FINISHED!r}) + t = threading.Thread(target=task) + t.start() + os.write({w_interp}, {RAN!r}) + """) + interp.exec_sync(f"""if True: + os.write({w_interp}, {RAN!r}) + """) + + os.write(w_thread, DONE) + interp.exec_sync('t.join()') + self.assertEqual(os.read(r_interp, 1), RAN) + self.assertEqual(os.read(r_interp, 1), RAN) + self.assertEqual(os.read(r_interp, 1), FINISHED) + + # test_xxsubinterpreters covers the remaining + # Interpreter.exec_sync() behavior. + + +class TestInterpreterRun(TestBase): + + def test_success(self): + interp = interpreters.create() + script, file = _captured_script('print("it worked!", end="")') + with file: + t = interp.run(script) + t.join() + out = file.read() + + self.assertEqual(out, 'it worked!') + + def test_failure(self): + caught = False + def excepthook(args): + nonlocal caught + caught = True + threading.excepthook = excepthook + try: + interp = interpreters.create() + t = interp.run('raise Exception') + t.join() + + self.assertTrue(caught) + except BaseException: + threading.excepthook = threading.__excepthook__ + + +class TestIsShareable(TestBase): + + def test_default_shareables(self): + shareables = [ + # singletons + None, + # builtin objects + b'spam', + 'spam', + 10, + -10, + True, + False, + 100.0, + (), + (1, ('spam', 'eggs'), True), + ] + for obj in shareables: + with self.subTest(obj): + shareable = interpreters.is_shareable(obj) + self.assertTrue(shareable) + + def test_not_shareable(self): + class Cheese: + def __init__(self, name): + self.name = name + def __str__(self): + return self.name + + class SubBytes(bytes): + """A subclass of a shareable type.""" + + not_shareables = [ + # singletons + NotImplemented, + ..., + # builtin types and objects + type, + object, + object(), + Exception(), + # user-defined types and objects + Cheese, + Cheese('Wensleydale'), + SubBytes(b'spam'), + ] + for obj in not_shareables: + with self.subTest(repr(obj)): + self.assertFalse( + interpreters.is_shareable(obj)) + + +if __name__ == '__main__': + # Test needs to be a package, so we can do relative imports. + unittest.main() diff --git a/Lib/test/test_interpreters/test_channels.py b/Lib/test/test_interpreters/test_channels.py new file mode 100644 index 00000000000000..3c3e18832d4168 --- /dev/null +++ b/Lib/test/test_interpreters/test_channels.py @@ -0,0 +1,328 @@ +import threading +from textwrap import dedent +import unittest +import time + +from test.support import import_helper +# Raise SkipTest if subinterpreters not supported. +_channels = import_helper.import_module('_xxinterpchannels') +from test.support import interpreters +from test.support.interpreters import channels +from .utils import _run_output, TestBase + + +class TestChannels(TestBase): + + def test_create(self): + r, s = channels.create() + self.assertIsInstance(r, channels.RecvChannel) + self.assertIsInstance(s, channels.SendChannel) + + def test_list_all(self): + self.assertEqual(channels.list_all(), []) + created = set() + for _ in range(3): + ch = channels.create() + created.add(ch) + after = set(channels.list_all()) + self.assertEqual(after, created) + + def test_shareable(self): + rch, sch = channels.create() + + self.assertTrue( + interpreters.is_shareable(rch)) + self.assertTrue( + interpreters.is_shareable(sch)) + + sch.send_nowait(rch) + sch.send_nowait(sch) + rch2 = rch.recv() + sch2 = rch.recv() + + self.assertEqual(rch2, rch) + self.assertEqual(sch2, sch) + + def test_is_closed(self): + rch, sch = channels.create() + rbefore = rch.is_closed + sbefore = sch.is_closed + rch.close() + rafter = rch.is_closed + safter = sch.is_closed + + self.assertFalse(rbefore) + self.assertFalse(sbefore) + self.assertTrue(rafter) + self.assertTrue(safter) + + +class TestRecvChannelAttrs(TestBase): + + def test_id_type(self): + rch, _ = channels.create() + self.assertIsInstance(rch.id, _channels.ChannelID) + + def test_custom_id(self): + rch = channels.RecvChannel(1) + self.assertEqual(rch.id, 1) + + with self.assertRaises(TypeError): + channels.RecvChannel('1') + + def test_id_readonly(self): + rch = channels.RecvChannel(1) + with self.assertRaises(AttributeError): + rch.id = 2 + + def test_equality(self): + ch1, _ = channels.create() + ch2, _ = channels.create() + self.assertEqual(ch1, ch1) + self.assertNotEqual(ch1, ch2) + + +class TestSendChannelAttrs(TestBase): + + def test_id_type(self): + _, sch = channels.create() + self.assertIsInstance(sch.id, _channels.ChannelID) + + def test_custom_id(self): + sch = channels.SendChannel(1) + self.assertEqual(sch.id, 1) + + with self.assertRaises(TypeError): + channels.SendChannel('1') + + def test_id_readonly(self): + sch = channels.SendChannel(1) + with self.assertRaises(AttributeError): + sch.id = 2 + + def test_equality(self): + _, ch1 = channels.create() + _, ch2 = channels.create() + self.assertEqual(ch1, ch1) + self.assertNotEqual(ch1, ch2) + + +class TestSendRecv(TestBase): + + def test_send_recv_main(self): + r, s = channels.create() + orig = b'spam' + s.send_nowait(orig) + obj = r.recv() + + self.assertEqual(obj, orig) + self.assertIsNot(obj, orig) + + def test_send_recv_same_interpreter(self): + interp = interpreters.create() + interp.exec_sync(dedent(""" + from test.support.interpreters import channels + r, s = channels.create() + orig = b'spam' + s.send_nowait(orig) + obj = r.recv() + assert obj == orig, 'expected: obj == orig' + assert obj is not orig, 'expected: obj is not orig' + """)) + + @unittest.skip('broken (see BPO-...)') + def test_send_recv_different_interpreters(self): + r1, s1 = channels.create() + r2, s2 = channels.create() + orig1 = b'spam' + s1.send_nowait(orig1) + out = _run_output( + interpreters.create(), + dedent(f""" + obj1 = r.recv() + assert obj1 == b'spam', 'expected: obj1 == orig1' + # When going to another interpreter we get a copy. + assert id(obj1) != {id(orig1)}, 'expected: obj1 is not orig1' + orig2 = b'eggs' + print(id(orig2)) + s.send_nowait(orig2) + """), + channels=dict(r=r1, s=s2), + ) + obj2 = r2.recv() + + self.assertEqual(obj2, b'eggs') + self.assertNotEqual(id(obj2), int(out)) + + def test_send_recv_different_threads(self): + r, s = channels.create() + + def f(): + while True: + try: + obj = r.recv() + break + except channels.ChannelEmptyError: + time.sleep(0.1) + s.send(obj) + t = threading.Thread(target=f) + t.start() + + orig = b'spam' + s.send(orig) + obj = r.recv() + t.join() + + self.assertEqual(obj, orig) + self.assertIsNot(obj, orig) + + def test_send_recv_nowait_main(self): + r, s = channels.create() + orig = b'spam' + s.send_nowait(orig) + obj = r.recv_nowait() + + self.assertEqual(obj, orig) + self.assertIsNot(obj, orig) + + def test_send_recv_nowait_main_with_default(self): + r, _ = channels.create() + obj = r.recv_nowait(None) + + self.assertIsNone(obj) + + def test_send_recv_nowait_same_interpreter(self): + interp = interpreters.create() + interp.exec_sync(dedent(""" + from test.support.interpreters import channels + r, s = channels.create() + orig = b'spam' + s.send_nowait(orig) + obj = r.recv_nowait() + assert obj == orig, 'expected: obj == orig' + # When going back to the same interpreter we get the same object. + assert obj is not orig, 'expected: obj is not orig' + """)) + + @unittest.skip('broken (see BPO-...)') + def test_send_recv_nowait_different_interpreters(self): + r1, s1 = channels.create() + r2, s2 = channels.create() + orig1 = b'spam' + s1.send_nowait(orig1) + out = _run_output( + interpreters.create(), + dedent(f""" + obj1 = r.recv_nowait() + assert obj1 == b'spam', 'expected: obj1 == orig1' + # When going to another interpreter we get a copy. + assert id(obj1) != {id(orig1)}, 'expected: obj1 is not orig1' + orig2 = b'eggs' + print(id(orig2)) + s.send_nowait(orig2) + """), + channels=dict(r=r1, s=s2), + ) + obj2 = r2.recv_nowait() + + self.assertEqual(obj2, b'eggs') + self.assertNotEqual(id(obj2), int(out)) + + def test_recv_timeout(self): + r, _ = channels.create() + with self.assertRaises(TimeoutError): + r.recv(timeout=1) + + def test_recv_channel_does_not_exist(self): + ch = channels.RecvChannel(1_000_000) + with self.assertRaises(channels.ChannelNotFoundError): + ch.recv() + + def test_send_channel_does_not_exist(self): + ch = channels.SendChannel(1_000_000) + with self.assertRaises(channels.ChannelNotFoundError): + ch.send(b'spam') + + def test_recv_nowait_channel_does_not_exist(self): + ch = channels.RecvChannel(1_000_000) + with self.assertRaises(channels.ChannelNotFoundError): + ch.recv_nowait() + + def test_send_nowait_channel_does_not_exist(self): + ch = channels.SendChannel(1_000_000) + with self.assertRaises(channels.ChannelNotFoundError): + ch.send_nowait(b'spam') + + def test_recv_nowait_empty(self): + ch, _ = channels.create() + with self.assertRaises(channels.ChannelEmptyError): + ch.recv_nowait() + + def test_recv_nowait_default(self): + default = object() + rch, sch = channels.create() + obj1 = rch.recv_nowait(default) + sch.send_nowait(None) + sch.send_nowait(1) + sch.send_nowait(b'spam') + sch.send_nowait(b'eggs') + obj2 = rch.recv_nowait(default) + obj3 = rch.recv_nowait(default) + obj4 = rch.recv_nowait() + obj5 = rch.recv_nowait(default) + obj6 = rch.recv_nowait(default) + + self.assertIs(obj1, default) + self.assertIs(obj2, None) + self.assertEqual(obj3, 1) + self.assertEqual(obj4, b'spam') + self.assertEqual(obj5, b'eggs') + self.assertIs(obj6, default) + + def test_send_buffer(self): + buf = bytearray(b'spamspamspam') + obj = None + rch, sch = channels.create() + + def f(): + nonlocal obj + while True: + try: + obj = rch.recv() + break + except channels.ChannelEmptyError: + time.sleep(0.1) + t = threading.Thread(target=f) + t.start() + + sch.send_buffer(buf) + t.join() + + self.assertIsNot(obj, buf) + self.assertIsInstance(obj, memoryview) + self.assertEqual(obj, buf) + + buf[4:8] = b'eggs' + self.assertEqual(obj, buf) + obj[4:8] = b'ham.' + self.assertEqual(obj, buf) + + def test_send_buffer_nowait(self): + buf = bytearray(b'spamspamspam') + rch, sch = channels.create() + sch.send_buffer_nowait(buf) + obj = rch.recv() + + self.assertIsNot(obj, buf) + self.assertIsInstance(obj, memoryview) + self.assertEqual(obj, buf) + + buf[4:8] = b'eggs' + self.assertEqual(obj, buf) + obj[4:8] = b'ham.' + self.assertEqual(obj, buf) + + +if __name__ == '__main__': + # Test needs to be a package, so we can do relative imports. + unittest.main() diff --git a/Lib/test/test_interpreters/test_lifecycle.py b/Lib/test/test_interpreters/test_lifecycle.py new file mode 100644 index 00000000000000..c2917d839904f9 --- /dev/null +++ b/Lib/test/test_interpreters/test_lifecycle.py @@ -0,0 +1,189 @@ +import contextlib +import json +import os +import os.path +import sys +from textwrap import dedent +import unittest + +from test import support +from test.support import import_helper +from test.support import os_helper +# Raise SkipTest if subinterpreters not supported. +import_helper.import_module('_xxsubinterpreters') +from .utils import TestBase + + +class StartupTests(TestBase): + + # We want to ensure the initial state of subinterpreters + # matches expectations. + + _subtest_count = 0 + + @contextlib.contextmanager + def subTest(self, *args): + with super().subTest(*args) as ctx: + self._subtest_count += 1 + try: + yield ctx + finally: + if self._debugged_in_subtest: + if self._subtest_count == 1: + # The first subtest adds a leading newline, so we + # compensate here by not printing a trailing newline. + print('### end subtest debug ###', end='') + else: + print('### end subtest debug ###') + self._debugged_in_subtest = False + + def debug(self, msg, *, header=None): + if header: + self._debug(f'--- {header} ---') + if msg: + if msg.endswith(os.linesep): + self._debug(msg[:-len(os.linesep)]) + else: + self._debug(msg) + self._debug('') + self._debug('------') + else: + self._debug(msg) + + _debugged = False + _debugged_in_subtest = False + def _debug(self, msg): + if not self._debugged: + print() + self._debugged = True + if self._subtest is not None: + if True: + if not self._debugged_in_subtest: + self._debugged_in_subtest = True + print('### start subtest debug ###') + print(msg) + else: + print(msg) + + def create_temp_dir(self): + import tempfile + tmp = tempfile.mkdtemp(prefix='test_interpreters_') + tmp = os.path.realpath(tmp) + self.addCleanup(os_helper.rmtree, tmp) + return tmp + + def write_script(self, *path, text): + filename = os.path.join(*path) + dirname = os.path.dirname(filename) + if dirname: + os.makedirs(dirname, exist_ok=True) + with open(filename, 'w', encoding='utf-8') as outfile: + outfile.write(dedent(text)) + return filename + + @support.requires_subprocess() + def run_python(self, argv, *, cwd=None): + # This method is inspired by + # EmbeddingTestsMixin.run_embedded_interpreter() in test_embed.py. + import shlex + import subprocess + if isinstance(argv, str): + argv = shlex.split(argv) + argv = [sys.executable, *argv] + try: + proc = subprocess.run( + argv, + cwd=cwd, + capture_output=True, + text=True, + ) + except Exception as exc: + self.debug(f'# cmd: {shlex.join(argv)}') + if isinstance(exc, FileNotFoundError) and not exc.filename: + if os.path.exists(argv[0]): + exists = 'exists' + else: + exists = 'does not exist' + self.debug(f'{argv[0]} {exists}') + raise # re-raise + assert proc.stderr == '' or proc.returncode != 0, proc.stderr + if proc.returncode != 0 and support.verbose: + self.debug(f'# python3 {shlex.join(argv[1:])} failed:') + self.debug(proc.stdout, header='stdout') + self.debug(proc.stderr, header='stderr') + self.assertEqual(proc.returncode, 0) + self.assertEqual(proc.stderr, '') + return proc.stdout + + def test_sys_path_0(self): + # The main interpreter's sys.path[0] should be used by subinterpreters. + script = ''' + import sys + from test.support import interpreters + + orig = sys.path[0] + + interp = interpreters.create() + interp.exec_sync(f"""if True: + import json + import sys + print(json.dumps({{ + 'main': {orig!r}, + 'sub': sys.path[0], + }}, indent=4), flush=True) + """) + ''' + # / + # pkg/ + # __init__.py + # __main__.py + # script.py + # script.py + cwd = self.create_temp_dir() + self.write_script(cwd, 'pkg', '__init__.py', text='') + self.write_script(cwd, 'pkg', '__main__.py', text=script) + self.write_script(cwd, 'pkg', 'script.py', text=script) + self.write_script(cwd, 'script.py', text=script) + + cases = [ + ('script.py', cwd), + ('-m script', cwd), + ('-m pkg', cwd), + ('-m pkg.script', cwd), + ('-c "import script"', ''), + ] + for argv, expected in cases: + with self.subTest(f'python3 {argv}'): + out = self.run_python(argv, cwd=cwd) + data = json.loads(out) + sp0_main, sp0_sub = data['main'], data['sub'] + self.assertEqual(sp0_sub, sp0_main) + self.assertEqual(sp0_sub, expected) + # XXX Also check them all with the -P cmdline flag? + + +class FinalizationTests(TestBase): + + def test_gh_109793(self): + # Make sure finalization finishes and the correct error code + # is reported, even when subinterpreters get cleaned up at the end. + import subprocess + argv = [sys.executable, '-c', '''if True: + from test.support import interpreters + interp = interpreters.create() + raise Exception + '''] + proc = subprocess.run(argv, capture_output=True, text=True) + self.assertIn('Traceback', proc.stderr) + if proc.returncode == 0 and support.verbose: + print() + print("--- cmd unexpected succeeded ---") + print(f"stdout:\n{proc.stdout}") + print(f"stderr:\n{proc.stderr}") + print("------") + self.assertEqual(proc.returncode, 1) + + +if __name__ == '__main__': + # Test needs to be a package, so we can do relative imports. + unittest.main() diff --git a/Lib/test/test_interpreters/test_queues.py b/Lib/test/test_interpreters/test_queues.py new file mode 100644 index 00000000000000..2a8ca99c1f6e3f --- /dev/null +++ b/Lib/test/test_interpreters/test_queues.py @@ -0,0 +1,299 @@ +import threading +from textwrap import dedent +import unittest +import time + +from test.support import import_helper +# Raise SkipTest if subinterpreters not supported. +_queues = import_helper.import_module('_xxinterpqueues') +from test.support import interpreters +from test.support.interpreters import queues +from .utils import _run_output, TestBase + + +class TestBase(TestBase): + def tearDown(self): + for qid in _queues.list_all(): + try: + _queues.destroy(qid) + except Exception: + pass + + +class QueueTests(TestBase): + + def test_create(self): + with self.subTest('vanilla'): + queue = queues.create() + self.assertEqual(queue.maxsize, 0) + + with self.subTest('small maxsize'): + queue = queues.create(3) + self.assertEqual(queue.maxsize, 3) + + with self.subTest('big maxsize'): + queue = queues.create(100) + self.assertEqual(queue.maxsize, 100) + + with self.subTest('no maxsize'): + queue = queues.create(0) + self.assertEqual(queue.maxsize, 0) + + with self.subTest('negative maxsize'): + queue = queues.create(-10) + self.assertEqual(queue.maxsize, -10) + + with self.subTest('bad maxsize'): + with self.assertRaises(TypeError): + queues.create('1') + + def test_shareable(self): + queue1 = queues.create() + + interp = interpreters.create() + interp.exec_sync(dedent(f""" + from test.support.interpreters import queues + queue1 = queues.Queue({queue1.id}) + """)); + + with self.subTest('same interpreter'): + queue2 = queues.create() + queue1.put(queue2) + queue3 = queue1.get() + self.assertIs(queue3, queue2) + + with self.subTest('from current interpreter'): + queue4 = queues.create() + queue1.put(queue4) + out = _run_output(interp, dedent(""" + queue4 = queue1.get() + print(queue4.id) + """)) + qid = int(out) + self.assertEqual(qid, queue4.id) + + with self.subTest('from subinterpreter'): + out = _run_output(interp, dedent(""" + queue5 = queues.create() + queue1.put(queue5) + print(queue5.id) + """)) + qid = int(out) + queue5 = queue1.get() + self.assertEqual(queue5.id, qid) + + def test_id_type(self): + queue = queues.create() + self.assertIsInstance(queue.id, int) + + def test_custom_id(self): + with self.assertRaises(queues.QueueNotFoundError): + queues.Queue(1_000_000) + + def test_id_readonly(self): + queue = queues.create() + with self.assertRaises(AttributeError): + queue.id = 1_000_000 + + def test_maxsize_readonly(self): + queue = queues.create(10) + with self.assertRaises(AttributeError): + queue.maxsize = 1_000_000 + + def test_hashable(self): + queue = queues.create() + expected = hash(queue.id) + actual = hash(queue) + self.assertEqual(actual, expected) + + def test_equality(self): + queue1 = queues.create() + queue2 = queues.create() + self.assertEqual(queue1, queue1) + self.assertNotEqual(queue1, queue2) + + +class TestQueueOps(TestBase): + + def test_empty(self): + queue = queues.create() + before = queue.empty() + queue.put(None) + during = queue.empty() + queue.get() + after = queue.empty() + + self.assertIs(before, True) + self.assertIs(during, False) + self.assertIs(after, True) + + def test_full(self): + expected = [False, False, False, True, False, False, False] + actual = [] + queue = queues.create(3) + for _ in range(3): + actual.append(queue.full()) + queue.put(None) + actual.append(queue.full()) + for _ in range(3): + queue.get() + actual.append(queue.full()) + + self.assertEqual(actual, expected) + + def test_qsize(self): + expected = [0, 1, 2, 3, 2, 3, 2, 1, 0, 1, 0] + actual = [] + queue = queues.create() + for _ in range(3): + actual.append(queue.qsize()) + queue.put(None) + actual.append(queue.qsize()) + queue.get() + actual.append(queue.qsize()) + queue.put(None) + actual.append(queue.qsize()) + for _ in range(3): + queue.get() + actual.append(queue.qsize()) + queue.put(None) + actual.append(queue.qsize()) + queue.get() + actual.append(queue.qsize()) + + self.assertEqual(actual, expected) + + def test_put_get_main(self): + expected = list(range(20)) + queue = queues.create() + for i in range(20): + queue.put(i) + actual = [queue.get() for _ in range(20)] + + self.assertEqual(actual, expected) + + def test_put_timeout(self): + queue = queues.create(2) + queue.put(None) + queue.put(None) + with self.assertRaises(queues.QueueFull): + queue.put(None, timeout=0.1) + queue.get() + queue.put(None) + + def test_put_nowait(self): + queue = queues.create(2) + queue.put_nowait(None) + queue.put_nowait(None) + with self.assertRaises(queues.QueueFull): + queue.put_nowait(None) + queue.get() + queue.put_nowait(None) + + def test_get_timeout(self): + queue = queues.create() + with self.assertRaises(queues.QueueEmpty): + queue.get(timeout=0.1) + + def test_get_nowait(self): + queue = queues.create() + with self.assertRaises(queues.QueueEmpty): + queue.get_nowait() + + def test_put_get_same_interpreter(self): + interp = interpreters.create() + interp.exec_sync(dedent(""" + from test.support.interpreters import queues + queue = queues.create() + orig = b'spam' + queue.put(orig) + obj = queue.get() + assert obj == orig, 'expected: obj == orig' + assert obj is not orig, 'expected: obj is not orig' + """)) + + def test_put_get_different_interpreters(self): + interp = interpreters.create() + queue1 = queues.create() + queue2 = queues.create() + self.assertEqual(len(queues.list_all()), 2) + + obj1 = b'spam' + queue1.put(obj1) + + out = _run_output( + interp, + dedent(f""" + from test.support.interpreters import queues + queue1 = queues.Queue({queue1.id}) + queue2 = queues.Queue({queue2.id}) + assert queue1.qsize() == 1, 'expected: queue1.qsize() == 1' + obj = queue1.get() + assert queue1.qsize() == 0, 'expected: queue1.qsize() == 0' + assert obj == b'spam', 'expected: obj == obj1' + # When going to another interpreter we get a copy. + assert id(obj) != {id(obj1)}, 'expected: obj is not obj1' + obj2 = b'eggs' + print(id(obj2)) + assert queue2.qsize() == 0, 'expected: queue2.qsize() == 0' + queue2.put(obj2) + assert queue2.qsize() == 1, 'expected: queue2.qsize() == 1' + """)) + self.assertEqual(len(queues.list_all()), 2) + self.assertEqual(queue1.qsize(), 0) + self.assertEqual(queue2.qsize(), 1) + + obj2 = queue2.get() + self.assertEqual(obj2, b'eggs') + self.assertNotEqual(id(obj2), int(out)) + + def test_put_cleared_with_subinterpreter(self): + interp = interpreters.create() + queue = queues.create() + + out = _run_output( + interp, + dedent(f""" + from test.support.interpreters import queues + queue = queues.Queue({queue.id}) + obj1 = b'spam' + obj2 = b'eggs' + queue.put(obj1) + queue.put(obj2) + """)) + self.assertEqual(queue.qsize(), 2) + + obj1 = queue.get() + self.assertEqual(obj1, b'spam') + self.assertEqual(queue.qsize(), 1) + + del interp + self.assertEqual(queue.qsize(), 0) + + def test_put_get_different_threads(self): + queue1 = queues.create() + queue2 = queues.create() + + def f(): + while True: + try: + obj = queue1.get(timeout=0.1) + break + except queues.QueueEmpty: + continue + queue2.put(obj) + t = threading.Thread(target=f) + t.start() + + orig = b'spam' + queue1.put(orig) + obj = queue2.get() + t.join() + + self.assertEqual(obj, orig) + self.assertIsNot(obj, orig) + + +if __name__ == '__main__': + # Test needs to be a package, so we can do relative imports. + unittest.main() diff --git a/Lib/test/test_interpreters/test_stress.py b/Lib/test/test_interpreters/test_stress.py new file mode 100644 index 00000000000000..3cc570b3bf7128 --- /dev/null +++ b/Lib/test/test_interpreters/test_stress.py @@ -0,0 +1,38 @@ +import threading +import unittest + +from test import support +from test.support import import_helper +from test.support import threading_helper +# Raise SkipTest if subinterpreters not supported. +import_helper.import_module('_xxsubinterpreters') +from test.support import interpreters +from .utils import TestBase + + +class StressTests(TestBase): + + # In these tests we generally want a lot of interpreters, + # but not so many that any test takes too long. + + @support.requires_resource('cpu') + def test_create_many_sequential(self): + alive = [] + for _ in range(100): + interp = interpreters.create() + alive.append(interp) + + @support.requires_resource('cpu') + def test_create_many_threaded(self): + alive = [] + def task(): + interp = interpreters.create() + alive.append(interp) + threads = (threading.Thread(target=task) for _ in range(200)) + with threading_helper.start_threads(threads): + pass + + +if __name__ == '__main__': + # Test needs to be a package, so we can do relative imports. + unittest.main() diff --git a/Lib/test/test_interpreters/utils.py b/Lib/test/test_interpreters/utils.py new file mode 100644 index 00000000000000..3a37ed09dd8943 --- /dev/null +++ b/Lib/test/test_interpreters/utils.py @@ -0,0 +1,147 @@ +import contextlib +import os +import os.path +import subprocess +import sys +import tempfile +import threading +from textwrap import dedent +import unittest + +from test import support +from test.support import os_helper + +from test.support import interpreters + + +def _captured_script(script): + r, w = os.pipe() + indented = script.replace('\n', '\n ') + wrapped = dedent(f""" + import contextlib + with open({w}, 'w', encoding='utf-8') as spipe: + with contextlib.redirect_stdout(spipe): + {indented} + """) + return wrapped, open(r, encoding='utf-8') + + +def clean_up_interpreters(): + for interp in interpreters.list_all(): + if interp.id == 0: # main + continue + try: + interp.close() + except RuntimeError: + pass # already destroyed + + +def _run_output(interp, request, init=None): + script, rpipe = _captured_script(request) + with rpipe: + if init: + interp.prepare_main(init) + interp.exec_sync(script) + return rpipe.read() + + +@contextlib.contextmanager +def _running(interp): + r, w = os.pipe() + def run(): + interp.exec_sync(dedent(f""" + # wait for "signal" + with open({r}) as rpipe: + rpipe.read() + """)) + + t = threading.Thread(target=run) + t.start() + + yield + + with open(w, 'w') as spipe: + spipe.write('done') + t.join() + + +class TestBase(unittest.TestCase): + + def pipe(self): + def ensure_closed(fd): + try: + os.close(fd) + except OSError: + pass + r, w = os.pipe() + self.addCleanup(lambda: ensure_closed(r)) + self.addCleanup(lambda: ensure_closed(w)) + return r, w + + def temp_dir(self): + tempdir = tempfile.mkdtemp() + tempdir = os.path.realpath(tempdir) + self.addCleanup(lambda: os_helper.rmtree(tempdir)) + return tempdir + + def make_script(self, filename, dirname=None, text=None): + if text: + text = dedent(text) + if dirname is None: + dirname = self.temp_dir() + filename = os.path.join(dirname, filename) + + os.makedirs(os.path.dirname(filename), exist_ok=True) + with open(filename, 'w', encoding='utf-8') as outfile: + outfile.write(text or '') + return filename + + def make_module(self, name, pathentry=None, text=None): + if text: + text = dedent(text) + if pathentry is None: + pathentry = self.temp_dir() + else: + os.makedirs(pathentry, exist_ok=True) + *subnames, basename = name.split('.') + + dirname = pathentry + for subname in subnames: + dirname = os.path.join(dirname, subname) + if os.path.isdir(dirname): + pass + elif os.path.exists(dirname): + raise Exception(dirname) + else: + os.mkdir(dirname) + initfile = os.path.join(dirname, '__init__.py') + if not os.path.exists(initfile): + with open(initfile, 'w'): + pass + filename = os.path.join(dirname, basename + '.py') + + with open(filename, 'w', encoding='utf-8') as outfile: + outfile.write(text or '') + return filename + + @support.requires_subprocess() + def run_python(self, *argv): + proc = subprocess.run( + [sys.executable, *argv], + capture_output=True, + text=True, + ) + return proc.returncode, proc.stdout, proc.stderr + + def assert_python_ok(self, *argv): + exitcode, stdout, stderr = self.run_python(*argv) + self.assertNotEqual(exitcode, 1) + return stdout, stderr + + def assert_python_failure(self, *argv): + exitcode, stdout, stderr = self.run_python(*argv) + self.assertNotEqual(exitcode, 0) + return stdout, stderr + + def tearDown(self): + clean_up_interpreters() diff --git a/Lib/test/test_io.py b/Lib/test/test_io.py index 26ae40d93c84eb..936edea3cad70c 100644 --- a/Lib/test/test_io.py +++ b/Lib/test/test_io.py @@ -77,6 +77,10 @@ def _default_chunk_size(): ) +class BadIndex: + def __index__(self): + 1/0 + class MockRawIOWithoutRead: """A RawIO implementation without read(), so as to exercise the default RawIO.read() which calls readinto().""" @@ -1230,11 +1234,9 @@ def test_recursive_repr(self): # Issue #25455 raw = self.MockRawIO() b = self.tp(raw) - with support.swap_attr(raw, 'name', b): - try: + with support.swap_attr(raw, 'name', b), support.infinite_recursion(25): + with self.assertRaises(RuntimeError): repr(b) # Should not crash - except RuntimeError: - pass def test_flush_error_on_close(self): # Test that buffered file is closed despite failed flush @@ -1541,8 +1543,8 @@ def test_read_all(self): self.assertEqual(b"abcdefg", bufio.read()) - @support.requires_resource('cpu') @threading_helper.requires_working_threading() + @support.requires_resource('cpu') def test_threads(self): try: # Write out many bytes with exactly the same number of 0's, @@ -1652,7 +1654,8 @@ def test_truncate_on_read_only(self): class CBufferedReaderTest(BufferedReaderTest, SizeofTest): tp = io.BufferedReader - @skip_if_sanitizer(memory=True, address=True, reason= "sanitizer defaults to crashing " + @skip_if_sanitizer(memory=True, address=True, thread=True, + reason="sanitizer defaults to crashing " "instead of returning NULL for malloc failure.") def test_constructor(self): BufferedReaderTest.test_constructor(self) @@ -1930,8 +1933,8 @@ def test_truncate_after_write(self): f.truncate() self.assertEqual(f.tell(), buffer_size + 2) - @support.requires_resource('cpu') @threading_helper.requires_working_threading() + @support.requires_resource('cpu') def test_threads(self): try: # Write out many bytes from many threads and test they were @@ -2019,7 +2022,8 @@ def test_slow_close_from_thread(self): class CBufferedWriterTest(BufferedWriterTest, SizeofTest): tp = io.BufferedWriter - @skip_if_sanitizer(memory=True, address=True, reason= "sanitizer defaults to crashing " + @skip_if_sanitizer(memory=True, address=True, thread=True, + reason="sanitizer defaults to crashing " "instead of returning NULL for malloc failure.") def test_constructor(self): BufferedWriterTest.test_constructor(self) @@ -2518,7 +2522,8 @@ def test_interleaved_readline_write(self): class CBufferedRandomTest(BufferedRandomTest, SizeofTest): tp = io.BufferedRandom - @skip_if_sanitizer(memory=True, address=True, reason= "sanitizer defaults to crashing " + @skip_if_sanitizer(memory=True, address=True, thread=True, + reason="sanitizer defaults to crashing " "instead of returning NULL for malloc failure.") def test_constructor(self): BufferedRandomTest.test_constructor(self) @@ -2709,8 +2714,29 @@ def test_constructor(self): self.assertEqual(t.encoding, "utf-8") self.assertEqual(t.line_buffering, True) self.assertEqual("\xe9\n", t.readline()) - self.assertRaises(TypeError, t.__init__, b, encoding="utf-8", newline=42) - self.assertRaises(ValueError, t.__init__, b, encoding="utf-8", newline='xyzzy') + invalid_type = TypeError if self.is_C else ValueError + with self.assertRaises(invalid_type): + t.__init__(b, encoding=42) + with self.assertRaises(UnicodeEncodeError): + t.__init__(b, encoding='\udcfe') + with self.assertRaises(ValueError): + t.__init__(b, encoding='utf-8\0') + with self.assertRaises(invalid_type): + t.__init__(b, encoding="utf-8", errors=42) + if support.Py_DEBUG or sys.flags.dev_mode or self.is_C: + with self.assertRaises(UnicodeEncodeError): + t.__init__(b, encoding="utf-8", errors='\udcfe') + if support.Py_DEBUG or sys.flags.dev_mode or self.is_C: + with self.assertRaises(ValueError): + t.__init__(b, encoding="utf-8", errors='replace\0') + with self.assertRaises(TypeError): + t.__init__(b, encoding="utf-8", newline=42) + with self.assertRaises(ValueError): + t.__init__(b, encoding="utf-8", newline='\udcfe') + with self.assertRaises(ValueError): + t.__init__(b, encoding="utf-8", newline='\n\0') + with self.assertRaises(ValueError): + t.__init__(b, encoding="utf-8", newline='xyzzy') def test_uninitialized(self): t = self.TextIOWrapper.__new__(self.TextIOWrapper) @@ -2776,11 +2802,16 @@ def test_recursive_repr(self): # Issue #25455 raw = self.BytesIO() t = self.TextIOWrapper(raw, encoding="utf-8") - with support.swap_attr(raw, 'name', t): - try: + with support.swap_attr(raw, 'name', t), support.infinite_recursion(25): + with self.assertRaises(RuntimeError): repr(t) # Should not crash - except RuntimeError: - pass + + def test_subclass_repr(self): + class TestSubclass(self.TextIOWrapper): + pass + + f = TestSubclass(self.StringIO()) + self.assertIn(TestSubclass.__name__, repr(f)) def test_line_buffering(self): r = self.BytesIO() @@ -3756,6 +3787,59 @@ def test_reconfigure_defaults(self): self.assertEqual(txt.detach().getvalue(), b'LF\nCRLF\r\n') + def test_reconfigure_errors(self): + txt = self.TextIOWrapper(self.BytesIO(), 'ascii', 'replace', '\r') + with self.assertRaises(TypeError): # there was a crash + txt.reconfigure(encoding=42) + if self.is_C: + with self.assertRaises(UnicodeEncodeError): + txt.reconfigure(encoding='\udcfe') + with self.assertRaises(LookupError): + txt.reconfigure(encoding='locale\0') + # TODO: txt.reconfigure(encoding='utf-8\0') + # TODO: txt.reconfigure(encoding='nonexisting') + with self.assertRaises(TypeError): + txt.reconfigure(errors=42) + if self.is_C: + with self.assertRaises(UnicodeEncodeError): + txt.reconfigure(errors='\udcfe') + # TODO: txt.reconfigure(errors='ignore\0') + # TODO: txt.reconfigure(errors='nonexisting') + with self.assertRaises(TypeError): + txt.reconfigure(newline=42) + with self.assertRaises(ValueError): + txt.reconfigure(newline='\udcfe') + with self.assertRaises(ValueError): + txt.reconfigure(newline='xyz') + if not self.is_C: + # TODO: Should fail in C too. + with self.assertRaises(ValueError): + txt.reconfigure(newline='\n\0') + if self.is_C: + # TODO: Use __bool__(), not __index__(). + with self.assertRaises(ZeroDivisionError): + txt.reconfigure(line_buffering=BadIndex()) + with self.assertRaises(OverflowError): + txt.reconfigure(line_buffering=2**1000) + with self.assertRaises(ZeroDivisionError): + txt.reconfigure(write_through=BadIndex()) + with self.assertRaises(OverflowError): + txt.reconfigure(write_through=2**1000) + with self.assertRaises(ZeroDivisionError): # there was a crash + txt.reconfigure(line_buffering=BadIndex(), + write_through=BadIndex()) + self.assertEqual(txt.encoding, 'ascii') + self.assertEqual(txt.errors, 'replace') + self.assertIs(txt.line_buffering, False) + self.assertIs(txt.write_through, False) + + txt.reconfigure(encoding='latin1', errors='ignore', newline='\r\n', + line_buffering=True, write_through=True) + self.assertEqual(txt.encoding, 'latin1') + self.assertEqual(txt.errors, 'ignore') + self.assertIs(txt.line_buffering, True) + self.assertIs(txt.write_through, True) + def test_reconfigure_newline(self): raw = self.BytesIO(b'CR\rEOF') txt = self.TextIOWrapper(raw, 'ascii', newline='\n') @@ -3803,6 +3887,14 @@ def test_issue25862(self): t.write('x') t.tell() + def test_issue35928(self): + p = self.BufferedRWPair(self.BytesIO(b'foo\nbar\n'), self.BytesIO()) + f = self.TextIOWrapper(p) + res = f.readline() + self.assertEqual(res, 'foo\n') + f.write(res) + self.assertEqual(res + f.readline(), 'foo\nbar\n') + class MemviewBytesIO(io.BytesIO): '''A BytesIO object whose read method returns memoryviews @@ -4042,19 +4134,18 @@ class PyIncrementalNewlineDecoderTest(IncrementalNewlineDecoderTest): class MiscIOTest(unittest.TestCase): + # for test__all__, actual values are set in subclasses + name_of_module = None + extra_exported = () + not_exported = () + def tearDown(self): os_helper.unlink(os_helper.TESTFN) def test___all__(self): - for name in self.io.__all__: - obj = getattr(self.io, name, None) - self.assertIsNotNone(obj, name) - if name in ("open", "open_code"): - continue - elif "error" in name.lower() or name == "UnsupportedOperation": - self.assertTrue(issubclass(obj, Exception), name) - elif not name.startswith("SEEK_"): - self.assertTrue(issubclass(obj, self.IOBase)) + support.check__all__(self, self.io, self.name_of_module, + extra=self.extra_exported, + not_exported=self.not_exported) def test_attributes(self): f = self.open(os_helper.TESTFN, "wb", buffering=0) @@ -4396,11 +4487,11 @@ def test_check_encoding_warning(self): ''') proc = assert_python_ok('-X', 'warn_default_encoding', '-c', code) warnings = proc.err.splitlines() - self.assertEqual(len(warnings), 2) + self.assertEqual(len(warnings), 4) self.assertTrue( warnings[0].startswith(b":5: EncodingWarning: ")) self.assertTrue( - warnings[1].startswith(b":8: EncodingWarning: ")) + warnings[2].startswith(b":8: EncodingWarning: ")) def test_text_encoding(self): # PEP 597, bpo-47000. io.text_encoding() returns "locale" or "utf-8" @@ -4416,6 +4507,8 @@ def test_text_encoding(self): class CMiscIOTest(MiscIOTest): io = io + name_of_module = "io", "_io" + extra_exported = "BlockingIOError", def test_readinto_buffer_overflow(self): # Issue #18025 @@ -4468,16 +4561,21 @@ def run(): self.assertFalse(err.strip('.!')) @threading_helper.requires_working_threading() + @support.requires_resource('walltime') def test_daemon_threads_shutdown_stdout_deadlock(self): self.check_daemon_threads_shutdown_deadlock('stdout') @threading_helper.requires_working_threading() + @support.requires_resource('walltime') def test_daemon_threads_shutdown_stderr_deadlock(self): self.check_daemon_threads_shutdown_deadlock('stderr') class PyMiscIOTest(MiscIOTest): io = pyio + name_of_module = "_pyio", "io" + extra_exported = "BlockingIOError", "open_code", + not_exported = "valid_seek_flags", @unittest.skipIf(os.name == 'nt', 'POSIX signals required for this test.') @@ -4645,11 +4743,13 @@ def alarm_handler(sig, frame): os.close(r) @requires_alarm + @support.requires_resource('walltime') def test_interrupted_read_retry_buffered(self): self.check_interrupted_read_retry(lambda x: x.decode('latin1'), mode="rb") @requires_alarm + @support.requires_resource('walltime') def test_interrupted_read_retry_text(self): self.check_interrupted_read_retry(lambda x: x, mode="r", encoding="latin1") @@ -4723,10 +4823,12 @@ def alarm2(sig, frame): raise @requires_alarm + @support.requires_resource('walltime') def test_interrupted_write_retry_buffered(self): self.check_interrupted_write_retry(b"x", mode="wb") @requires_alarm + @support.requires_resource('walltime') def test_interrupted_write_retry_text(self): self.check_interrupted_write_retry("x", mode="w", encoding="latin1") @@ -4761,7 +4863,7 @@ def load_tests(loader, tests, pattern): mocks = (MockRawIO, MisbehavedRawIO, MockFileIO, CloseFailureIO, MockNonBlockWriterIO, MockUnseekableIO, MockRawIOWithoutRead, SlowFlushRawIO) - all_members = io.__all__ + ["IncrementalNewlineDecoder"] + all_members = io.__all__ c_io_ns = {name : getattr(io, name) for name in all_members} py_io_ns = {name : getattr(pyio, name) for name in all_members} globs = globals() @@ -4771,9 +4873,11 @@ def load_tests(loader, tests, pattern): if test.__name__.startswith("C"): for name, obj in c_io_ns.items(): setattr(test, name, obj) + test.is_C = True elif test.__name__.startswith("Py"): for name, obj in py_io_ns.items(): setattr(test, name, obj) + test.is_C = False suite = loader.suiteClass() for test in tests: diff --git a/Lib/test/test_ipaddress.py b/Lib/test/test_ipaddress.py index 6f204948c9fc48..b4952acc2b61b1 100644 --- a/Lib/test/test_ipaddress.py +++ b/Lib/test/test_ipaddress.py @@ -4,6 +4,7 @@ """Unittest for ipaddress module.""" +import copy import unittest import re import contextlib @@ -302,6 +303,14 @@ def test_pickle(self): def test_weakref(self): weakref.ref(self.factory('192.0.2.1')) + def test_ipv6_mapped(self): + self.assertEqual(ipaddress.IPv4Address('192.168.1.1').ipv6_mapped, + ipaddress.IPv6Address('::ffff:192.168.1.1')) + self.assertEqual(ipaddress.IPv4Address('192.168.1.1').ipv6_mapped, + ipaddress.IPv6Address('::ffff:c0a8:101')) + self.assertEqual(ipaddress.IPv4Address('192.168.1.1').ipv6_mapped.ipv4_mapped, + ipaddress.IPv4Address('192.168.1.1')) + class AddressTestCase_v6(BaseTestCase, CommonTestMixin_v6): factory = ipaddress.IPv6Address @@ -542,11 +551,17 @@ def assertBadPart(addr, part): def test_pickle(self): self.pickle_test('2001:db8::') + self.pickle_test('2001:db8::%scope') def test_weakref(self): weakref.ref(self.factory('2001:db8::')) weakref.ref(self.factory('2001:db8::%scope')) + def test_copy(self): + addr = self.factory('2001:db8::%scope') + self.assertEqual(addr, copy.copy(addr)) + self.assertEqual(addr, copy.deepcopy(addr)) + class NetmaskTestMixin_v4(CommonTestMixin_v4): """Input validation on interfaces and networks is very similar""" diff --git a/Lib/test/test_itertools.py b/Lib/test/test_itertools.py index 4d6ea780e15373..9af0730ea98004 100644 --- a/Lib/test/test_itertools.py +++ b/Lib/test/test_itertools.py @@ -187,7 +187,11 @@ def test_batched(self): [('A', 'B'), ('C', 'D'), ('E', 'F'), ('G',)]) self.assertEqual(list(batched('ABCDEFG', 1)), [('A',), ('B',), ('C',), ('D',), ('E',), ('F',), ('G',)]) + self.assertEqual(list(batched('ABCDEF', 2, strict=True)), + [('A', 'B'), ('C', 'D'), ('E', 'F')]) + with self.assertRaises(ValueError): # Incomplete batch when strict + list(batched('ABCDEFG', 3, strict=True)) with self.assertRaises(TypeError): # Too few arguments list(batched('ABCDEFG')) with self.assertRaises(TypeError): @@ -1152,6 +1156,78 @@ def test_pairwise(self): with self.assertRaises(TypeError): pairwise(None) # non-iterable argument + def test_pairwise_reenter(self): + def check(reenter_at, expected): + class I: + count = 0 + def __iter__(self): + return self + def __next__(self): + self.count +=1 + if self.count in reenter_at: + return next(it) + return [self.count] # new object + + it = pairwise(I()) + for item in expected: + self.assertEqual(next(it), item) + + check({1}, [ + (([2], [3]), [4]), + ([4], [5]), + ]) + check({2}, [ + ([1], ([1], [3])), + (([1], [3]), [4]), + ([4], [5]), + ]) + check({3}, [ + ([1], [2]), + ([2], ([2], [4])), + (([2], [4]), [5]), + ([5], [6]), + ]) + check({1, 2}, [ + ((([3], [4]), [5]), [6]), + ([6], [7]), + ]) + check({1, 3}, [ + (([2], ([2], [4])), [5]), + ([5], [6]), + ]) + check({1, 4}, [ + (([2], [3]), (([2], [3]), [5])), + ((([2], [3]), [5]), [6]), + ([6], [7]), + ]) + check({2, 3}, [ + ([1], ([1], ([1], [4]))), + (([1], ([1], [4])), [5]), + ([5], [6]), + ]) + + def test_pairwise_reenter2(self): + def check(maxcount, expected): + class I: + count = 0 + def __iter__(self): + return self + def __next__(self): + if self.count >= maxcount: + raise StopIteration + self.count +=1 + if self.count == 1: + return next(it, None) + return [self.count] # new object + + it = pairwise(I()) + self.assertEqual(list(it), expected) + + check(1, []) + check(2, []) + check(3, []) + check(4, [(([2], [3]), [4])]) + def test_product(self): for args, result in [ ([], [()]), # zero iterables @@ -2401,6 +2477,7 @@ def gen2(x): self.assertEqual(hist, [0,1]) @support.skip_if_pgo_task + @support.requires_resource('cpu') def test_long_chain_of_empty_iterables(self): # Make sure itertools.chain doesn't run into recursion limits when # dealing with long chains of empty iterables. Even with a high diff --git a/Lib/test/test_json/test_fail.py b/Lib/test/test_json/test_fail.py index efc982e8b0eb04..d6bce605e21463 100644 --- a/Lib/test/test_json/test_fail.py +++ b/Lib/test/test_json/test_fail.py @@ -143,11 +143,11 @@ def test_unexpected_data(self): ('{"spam":[}', 'Expecting value', 9), ('[42:', "Expecting ',' delimiter", 3), ('[42 "spam"', "Expecting ',' delimiter", 4), - ('[42,]', 'Expecting value', 4), + ('[42,]', "Illegal trailing comma before end of array", 3), ('{"spam":[42}', "Expecting ',' delimiter", 11), ('["]', 'Unterminated string starting at', 1), ('["spam":', "Expecting ',' delimiter", 7), - ('["spam",]', 'Expecting value', 8), + ('["spam",]', "Illegal trailing comma before end of array", 7), ('{:', 'Expecting property name enclosed in double quotes', 1), ('{,', 'Expecting property name enclosed in double quotes', 1), ('{42', 'Expecting property name enclosed in double quotes', 1), @@ -159,7 +159,9 @@ def test_unexpected_data(self): ('[{"spam":]', 'Expecting value', 9), ('{"spam":42 "ham"', "Expecting ',' delimiter", 11), ('[{"spam":42]', "Expecting ',' delimiter", 11), - ('{"spam":42,}', 'Expecting property name enclosed in double quotes', 11), + ('{"spam":42,}', "Illegal trailing comma before end of object", 10), + ('{"spam":42 , }', "Illegal trailing comma before end of object", 11), + ('[123 , ]', "Illegal trailing comma before end of array", 6), ] for data, msg, idx in test_cases: with self.assertRaises(self.JSONDecodeError) as cm: diff --git a/Lib/test/test_json/test_recursion.py b/Lib/test/test_json/test_recursion.py index 9919d7fbe54ef7..164ff2013eb552 100644 --- a/Lib/test/test_json/test_recursion.py +++ b/Lib/test/test_json/test_recursion.py @@ -85,10 +85,10 @@ def test_highly_nested_objects_encoding(self): for x in range(100000): l, d = [l], {'k':d} with self.assertRaises(RecursionError): - with support.infinite_recursion(): + with support.infinite_recursion(5000): self.dumps(l) with self.assertRaises(RecursionError): - with support.infinite_recursion(): + with support.infinite_recursion(5000): self.dumps(d) def test_endless_recursion(self): @@ -99,7 +99,7 @@ def default(self, o): return [o] with self.assertRaises(RecursionError): - with support.infinite_recursion(): + with support.infinite_recursion(1000): EndlessJSONEncoder(check_circular=False).encode(5j) diff --git a/Lib/test/test_keywordonlyarg.py b/Lib/test/test_keywordonlyarg.py index df82f677a00a48..918f953cae5702 100644 --- a/Lib/test/test_keywordonlyarg.py +++ b/Lib/test/test_keywordonlyarg.py @@ -170,7 +170,7 @@ def f(v=a, x=b, *, y=c, z=d): pass self.assertEqual(str(err.exception), "name 'b' is not defined") with self.assertRaises(NameError) as err: - f = lambda v=a, x=b, *, y=c, z=d: None + g = lambda v=a, x=b, *, y=c, z=d: None self.assertEqual(str(err.exception), "name 'b' is not defined") diff --git a/Lib/test/test_kqueue.py b/Lib/test/test_kqueue.py index 998fd9d46496bb..e94edcbc107ba9 100644 --- a/Lib/test/test_kqueue.py +++ b/Lib/test/test_kqueue.py @@ -5,6 +5,7 @@ import os import select import socket +from test import support import time import unittest @@ -256,6 +257,23 @@ def test_fd_non_inheritable(self): self.addCleanup(kqueue.close) self.assertEqual(os.get_inheritable(kqueue.fileno()), False) + @support.requires_fork() + def test_fork(self): + # gh-110395: kqueue objects must be closed after fork + kqueue = select.kqueue() + if (pid := os.fork()) == 0: + try: + self.assertTrue(kqueue.closed) + with self.assertRaisesRegex(ValueError, "closed kqueue"): + kqueue.fileno() + except: + os._exit(1) + finally: + os._exit(0) + else: + support.wait_process(pid, exitcode=0) + self.assertFalse(kqueue.closed) # child done, we're still open. + if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_largefile.py b/Lib/test/test_largefile.py index 3c11c59baef6e5..3b0930fe69e30e 100644 --- a/Lib/test/test_largefile.py +++ b/Lib/test/test_largefile.py @@ -8,7 +8,7 @@ import socket import shutil import threading -from test.support import requires, bigmemtest +from test.support import requires, bigmemtest, requires_resource from test.support import SHORT_TIMEOUT from test.support import socket_helper from test.support.os_helper import TESTFN, unlink @@ -173,6 +173,7 @@ class TestCopyfile(LargeFileTest, unittest.TestCase): # Exact required disk space would be (size * 2), but let's give it a # bit more tolerance. @skip_no_disk_space(TESTFN, size * 2.5) + @requires_resource('cpu') def test_it(self): # Internally shutil.copyfile() can use "fast copy" methods like # os.sendfile(). @@ -222,6 +223,7 @@ def run(sock): # Exact required disk space would be (size * 2), but let's give it a # bit more tolerance. @skip_no_disk_space(TESTFN, size * 2.5) + @requires_resource('cpu') def test_it(self): port = socket_helper.find_unused_port() with socket.create_server(("", port)) as sock: diff --git a/Lib/test/test_launcher.py b/Lib/test/test_launcher.py index 362b507d158288..bcd4ed63bf25a0 100644 --- a/Lib/test/test_launcher.py +++ b/Lib/test/test_launcher.py @@ -717,3 +717,25 @@ def test_literal_shebang_invalid_template(self): f"{expect} arg1 {script}", data["stdout"].strip(), ) + + def test_shebang_command_in_venv(self): + stem = "python-that-is-not-on-path" + + # First ensure that our test name doesn't exist, and the launcher does + # not match any installed env + with self.script(f'#! /usr/bin/env {stem} arg1') as script: + data = self.run_py([script], expect_returncode=103) + + with self.fake_venv() as (venv_exe, env): + # Put a real Python (ourselves) on PATH as a distraction. + # The active VIRTUAL_ENV should be preferred when the name isn't an + # exact match. + env["PATH"] = f"{Path(sys.executable).parent};{os.environ['PATH']}" + + with self.script(f'#! /usr/bin/env {stem} arg1') as script: + data = self.run_py([script], env=env) + self.assertEqual(data["stdout"].strip(), f"{venv_exe} arg1 {script}") + + with self.script(f'#! /usr/bin/env {Path(sys.executable).stem} arg1') as script: + data = self.run_py([script], env=env) + self.assertEqual(data["stdout"].strip(), f"{sys.executable} arg1 {script}") diff --git a/Lib/test/test_listcomps.py b/Lib/test/test_listcomps.py index 9f28ced32bd26c..f95a78aff0c711 100644 --- a/Lib/test/test_listcomps.py +++ b/Lib/test/test_listcomps.py @@ -1,5 +1,6 @@ import doctest import textwrap +import types import unittest @@ -92,7 +93,8 @@ class ListComprehensionTest(unittest.TestCase): - def _check_in_scopes(self, code, outputs=None, ns=None, scopes=None, raises=()): + def _check_in_scopes(self, code, outputs=None, ns=None, scopes=None, raises=(), + exec_func=exec): code = textwrap.dedent(code) scopes = scopes or ["module", "class", "function"] for scope in scopes: @@ -119,13 +121,13 @@ def get_output(moddict, name): return moddict[name] newns = ns.copy() if ns else {} try: - exec(newcode, newns) + exec_func(newcode, newns) except raises as e: # We care about e.g. NameError vs UnboundLocalError self.assertIs(type(e), raises) else: for k, v in (outputs or {}).items(): - self.assertEqual(get_output(newns, k), v) + self.assertEqual(get_output(newns, k), v, k) def test_lambdas_with_iteration_var_as_default(self): code = """ @@ -561,6 +563,97 @@ def test_iter_var_available_in_locals(self): } ) + def test_comp_in_try_except(self): + template = """ + value = ["ab"] + result = snapshot = None + try: + result = [{func}(value) for value in value] + except: + snapshot = value + raise + """ + # No exception. + code = template.format(func='len') + self._check_in_scopes(code, {"value": ["ab"], "result": [2], "snapshot": None}) + # Handles exception. + code = template.format(func='int') + self._check_in_scopes(code, {"value": ["ab"], "result": None, "snapshot": ["ab"]}, + raises=ValueError) + + def test_comp_in_try_finally(self): + template = """ + value = ["ab"] + result = snapshot = None + try: + result = [{func}(value) for value in value] + finally: + snapshot = value + """ + # No exception. + code = template.format(func='len') + self._check_in_scopes(code, {"value": ["ab"], "result": [2], "snapshot": ["ab"]}) + # Handles exception. + code = template.format(func='int') + self._check_in_scopes(code, {"value": ["ab"], "result": None, "snapshot": ["ab"]}, + raises=ValueError) + + def test_exception_in_post_comp_call(self): + code = """ + value = [1, None] + try: + [v for v in value].sort() + except: + pass + """ + self._check_in_scopes(code, {"value": [1, None]}) + + def test_frame_locals(self): + code = """ + val = [sys._getframe().f_locals for a in [0]][0]["a"] + """ + import sys + self._check_in_scopes(code, {"val": 0}, ns={"sys": sys}) + + def _recursive_replace(self, maybe_code): + if not isinstance(maybe_code, types.CodeType): + return maybe_code + return maybe_code.replace(co_consts=tuple( + self._recursive_replace(c) for c in maybe_code.co_consts + )) + + def _replacing_exec(self, code_string, ns): + co = compile(code_string, "", "exec") + co = self._recursive_replace(co) + exec(co, ns) + + def test_code_replace(self): + code = """ + x = 3 + [x for x in (1, 2)] + dir() + y = [x] + """ + self._check_in_scopes(code, {"y": [3], "x": 3}) + self._check_in_scopes(code, {"y": [3], "x": 3}, exec_func=self._replacing_exec) + + def test_code_replace_extended_arg(self): + num_names = 300 + assignments = "; ".join(f"x{i} = {i}" for i in range(num_names)) + name_list = ", ".join(f"x{i}" for i in range(num_names)) + expected = { + "y": list(range(num_names)), + **{f"x{i}": i for i in range(num_names)} + } + code = f""" + {assignments} + [({name_list}) for {name_list} in (range(300),)] + dir() + y = [{name_list}] + """ + self._check_in_scopes(code, expected) + self._check_in_scopes(code, expected, exec_func=self._replacing_exec) + __test__ = {'doctests' : doctests} diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py index def976fbe96ba3..0be26981184213 100644 --- a/Lib/test/test_logging.py +++ b/Lib/test/test_logging.py @@ -43,6 +43,7 @@ import tempfile from test.support.script_helper import assert_python_ok, assert_python_failure from test import support +from test.support import import_helper from test.support import os_helper from test.support import socket_helper from test.support import threading_helper @@ -76,6 +77,13 @@ pass +# gh-89363: Skip fork() test if Python is built with Address Sanitizer (ASAN) +# to work around a libasan race condition, dead lock in pthread_create(). +skip_if_asan_fork = unittest.skipIf( + support.HAVE_ASAN_FORK_BUG, + "libasan has a pthread_create() dead lock related to thread+fork") + + class BaseTest(unittest.TestCase): """Base class for logging tests.""" @@ -90,8 +98,7 @@ def setUp(self): self._threading_key = threading_helper.threading_setup() logger_dict = logging.getLogger().manager.loggerDict - logging._acquireLock() - try: + with logging._lock: self.saved_handlers = logging._handlers.copy() self.saved_handler_list = logging._handlerList[:] self.saved_loggers = saved_loggers = logger_dict.copy() @@ -101,8 +108,6 @@ def setUp(self): for name in saved_loggers: logger_states[name] = getattr(saved_loggers[name], 'disabled', None) - finally: - logging._releaseLock() # Set two unused loggers self.logger1 = logging.getLogger("\xab\xd7\xbb") @@ -136,8 +141,7 @@ def tearDown(self): self.root_logger.removeHandler(h) h.close() self.root_logger.setLevel(self.original_logging_level) - logging._acquireLock() - try: + with logging._lock: logging._levelToName.clear() logging._levelToName.update(self.saved_level_to_name) logging._nameToLevel.clear() @@ -154,8 +158,6 @@ def tearDown(self): for name in self.logger_states: if logger_states[name] is not None: self.saved_loggers[name].disabled = logger_states[name] - finally: - logging._releaseLock() self.doCleanups() threading_helper.threading_cleanup(*self._threading_key) @@ -680,6 +682,7 @@ def test_path_objects(self): support.is_emscripten, "Emscripten cannot fstat unlinked files." ) @threading_helper.requires_working_threading() + @support.requires_resource('walltime') def test_race(self): # Issue #14632 refers. def remove_loop(fname, tries): @@ -729,6 +732,7 @@ def remove_loop(fname, tries): # register_at_fork mechanism is also present and used. @support.requires_fork() @threading_helper.requires_working_threading() + @skip_if_asan_fork def test_post_fork_child_no_deadlock(self): """Ensure child logging locks are not held; bpo-6721 & bpo-36533.""" class _OurHandler(logging.Handler): @@ -738,11 +742,8 @@ def __init__(self): stream=open('/dev/null', 'wt', encoding='utf-8')) def emit(self, record): - self.sub_handler.acquire() - try: + with self.sub_handler.lock: self.sub_handler.emit(record) - finally: - self.sub_handler.release() self.assertEqual(len(logging._handlers), 0) refed_h = _OurHandler() @@ -758,29 +759,22 @@ def emit(self, record): fork_happened__release_locks_and_end_thread = threading.Event() def lock_holder_thread_fn(): - logging._acquireLock() - try: - refed_h.acquire() - try: - # Tell the main thread to do the fork. - locks_held__ready_to_fork.set() - - # If the deadlock bug exists, the fork will happen - # without dealing with the locks we hold, deadlocking - # the child. - - # Wait for a successful fork or an unreasonable amount of - # time before releasing our locks. To avoid a timing based - # test we'd need communication from os.fork() as to when it - # has actually happened. Given this is a regression test - # for a fixed issue, potentially less reliably detecting - # regression via timing is acceptable for simplicity. - # The test will always take at least this long. :( - fork_happened__release_locks_and_end_thread.wait(0.5) - finally: - refed_h.release() - finally: - logging._releaseLock() + with logging._lock, refed_h.lock: + # Tell the main thread to do the fork. + locks_held__ready_to_fork.set() + + # If the deadlock bug exists, the fork will happen + # without dealing with the locks we hold, deadlocking + # the child. + + # Wait for a successful fork or an unreasonable amount of + # time before releasing our locks. To avoid a timing based + # test we'd need communication from os.fork() as to when it + # has actually happened. Given this is a regression test + # for a fixed issue, potentially less reliably detecting + # regression via timing is acceptable for simplicity. + # The test will always take at least this long. :( + fork_happened__release_locks_and_end_thread.wait(0.5) lock_holder_thread = threading.Thread( target=lock_holder_thread_fn, @@ -2169,7 +2163,7 @@ def test_output(self): sslctx = None else: here = os.path.dirname(__file__) - localhost_cert = os.path.join(here, "keycert.pem") + localhost_cert = os.path.join(here, "certdata", "keycert.pem") sslctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) sslctx.load_cert_chain(localhost_cert) @@ -3005,6 +2999,39 @@ class ConfigDictTest(BaseTest): }, } + class CustomFormatter(logging.Formatter): + custom_property = "." + + def format(self, record): + return super().format(record) + + config17 = { + 'version': 1, + 'formatters': { + "custom": { + "()": CustomFormatter, + "style": "{", + "datefmt": "%Y-%m-%d %H:%M:%S", + "format": "{message}", # <-- to force an exception when configuring + ".": { + "custom_property": "value" + } + } + }, + 'handlers' : { + 'hand1' : { + 'class' : 'logging.StreamHandler', + 'formatter' : 'custom', + 'level' : 'NOTSET', + 'stream' : 'ext://sys.stdout', + }, + }, + 'root' : { + 'level' : 'WARNING', + 'handlers' : ['hand1'], + }, + } + bad_format = { "version": 1, "formatters": { @@ -3486,7 +3513,10 @@ def test_config16_ok(self): {'msg': 'Hello'})) self.assertEqual(result, 'Hello ++ defaultvalue') - + def test_config17_ok(self): + self.apply_config(self.config17) + h = logging._handlers['hand1'] + self.assertEqual(h.formatter.custom_property, 'value') def setup_via_listener(self, text, verify=None): text = text.encode("utf-8") @@ -3662,7 +3692,28 @@ def test_baseconfig(self): d = { 'atuple': (1, 2, 3), 'alist': ['a', 'b', 'c'], - 'adict': {'d': 'e', 'f': 3 }, + 'adict': { + 'd': 'e', 'f': 3 , + 'alpha numeric 1 with spaces' : 5, + 'aplha numeric 1 %( - © ©ß¯' : 9, + 'alpha numeric ] 1 with spaces' : 15, + 'aplha ]] numeric 1 %( - © ©ß¯]' : 19, + ' aplha [ numeric 1 %( - © ©ß¯] ' : 11, + ' aplha ' : 32, + '' : 10, + 'nest4' : { + 'd': 'e', 'f': 3 , + 'alpha numeric 1 with spaces' : 5, + 'aplha numeric 1 %( - © ©ß¯' : 9, + '' : 10, + 'somelist' : ('g', ('h', 'i'), 'j'), + 'somedict' : { + 'a' : 1, + 'a with 1 and space' : 3, + 'a with ( and space' : 4, + } + } + }, 'nest1': ('g', ('h', 'i'), 'j'), 'nest2': ['k', ['l', 'm'], 'n'], 'nest3': ['o', 'cfg://alist', 'p'], @@ -3674,11 +3725,36 @@ def test_baseconfig(self): self.assertEqual(bc.convert('cfg://nest2[1][1]'), 'm') self.assertEqual(bc.convert('cfg://adict.d'), 'e') self.assertEqual(bc.convert('cfg://adict[f]'), 3) + self.assertEqual(bc.convert('cfg://adict[alpha numeric 1 with spaces]'), 5) + self.assertEqual(bc.convert('cfg://adict[aplha numeric 1 %( - © ©ß¯]'), 9) + self.assertEqual(bc.convert('cfg://adict[]'), 10) + self.assertEqual(bc.convert('cfg://adict.nest4.d'), 'e') + self.assertEqual(bc.convert('cfg://adict.nest4[d]'), 'e') + self.assertEqual(bc.convert('cfg://adict[nest4].d'), 'e') + self.assertEqual(bc.convert('cfg://adict[nest4][f]'), 3) + self.assertEqual(bc.convert('cfg://adict[nest4][alpha numeric 1 with spaces]'), 5) + self.assertEqual(bc.convert('cfg://adict[nest4][aplha numeric 1 %( - © ©ß¯]'), 9) + self.assertEqual(bc.convert('cfg://adict[nest4][]'), 10) + self.assertEqual(bc.convert('cfg://adict[nest4][somelist][0]'), 'g') + self.assertEqual(bc.convert('cfg://adict[nest4][somelist][1][0]'), 'h') + self.assertEqual(bc.convert('cfg://adict[nest4][somelist][1][1]'), 'i') + self.assertEqual(bc.convert('cfg://adict[nest4][somelist][2]'), 'j') + self.assertEqual(bc.convert('cfg://adict[nest4].somedict.a'), 1) + self.assertEqual(bc.convert('cfg://adict[nest4].somedict[a]'), 1) + self.assertEqual(bc.convert('cfg://adict[nest4].somedict[a with 1 and space]'), 3) + self.assertEqual(bc.convert('cfg://adict[nest4].somedict[a with ( and space]'), 4) + self.assertEqual(bc.convert('cfg://adict.nest4.somelist[1][1]'), 'i') + self.assertEqual(bc.convert('cfg://adict.nest4.somelist[2]'), 'j') + self.assertEqual(bc.convert('cfg://adict.nest4.somedict.a'), 1) + self.assertEqual(bc.convert('cfg://adict.nest4.somedict[a]'), 1) v = bc.convert('cfg://nest3') self.assertEqual(v.pop(1), ['a', 'b', 'c']) self.assertRaises(KeyError, bc.convert, 'cfg://nosuch') self.assertRaises(ValueError, bc.convert, 'cfg://!') self.assertRaises(KeyError, bc.convert, 'cfg://adict[2]') + self.assertRaises(KeyError, bc.convert, 'cfg://adict[alpha numeric ] 1 with spaces]') + self.assertRaises(ValueError, bc.convert, 'cfg://adict[ aplha ]] numeric 1 %( - © ©ß¯] ]') + self.assertRaises(ValueError, bc.convert, 'cfg://adict[ aplha [ numeric 1 %( - © ©ß¯] ]') def test_namedtuple(self): # see bpo-39142 @@ -3847,6 +3923,26 @@ def test_90195(self): # Logger should be enabled, since explicitly mentioned self.assertFalse(logger.disabled) + def test_111615(self): + # See gh-111615 + import_helper.import_module('_multiprocessing') # see gh-113692 + mp = import_helper.import_module('multiprocessing') + + config = { + 'version': 1, + 'handlers': { + 'sink': { + 'class': 'logging.handlers.QueueHandler', + 'queue': mp.get_context('spawn').Queue(), + }, + }, + 'root': { + 'handlers': ['sink'], + 'level': 'DEBUG', + }, + } + logging.config.dictConfig(config) + class ManagerTest(BaseTest): def test_manager_loggerclass(self): logged = [] @@ -5433,6 +5529,46 @@ def process(self, msg, kwargs): self.assertIs(adapter.manager, orig_manager) self.assertIs(self.logger.manager, orig_manager) + def test_extra_in_records(self): + self.adapter = logging.LoggerAdapter(logger=self.logger, + extra={'foo': '1'}) + + self.adapter.critical('foo should be here') + self.assertEqual(len(self.recording.records), 1) + record = self.recording.records[0] + self.assertTrue(hasattr(record, 'foo')) + self.assertEqual(record.foo, '1') + + def test_extra_not_merged_by_default(self): + self.adapter.critical('foo should NOT be here', extra={'foo': 'nope'}) + self.assertEqual(len(self.recording.records), 1) + record = self.recording.records[0] + self.assertFalse(hasattr(record, 'foo')) + + def test_extra_merged(self): + self.adapter = logging.LoggerAdapter(logger=self.logger, + extra={'foo': '1'}, + merge_extra=True) + + self.adapter.critical('foo and bar should be here', extra={'bar': '2'}) + self.assertEqual(len(self.recording.records), 1) + record = self.recording.records[0] + self.assertTrue(hasattr(record, 'foo')) + self.assertTrue(hasattr(record, 'bar')) + self.assertEqual(record.foo, '1') + self.assertEqual(record.bar, '2') + + def test_extra_merged_log_call_has_precedence(self): + self.adapter = logging.LoggerAdapter(logger=self.logger, + extra={'foo': '1'}, + merge_extra=True) + + self.adapter.critical('foo shall be min', extra={'foo': '2'}) + self.assertEqual(len(self.recording.records), 1) + record = self.recording.records[0] + self.assertTrue(hasattr(record, 'foo')) + self.assertEqual(record.foo, '2') + class LoggerTest(BaseTest, AssertErrorMessage): diff --git a/Lib/test/test_lzma.py b/Lib/test/test_lzma.py index ac53bdda2f1747..13b200912f6abd 100644 --- a/Lib/test/test_lzma.py +++ b/Lib/test/test_lzma.py @@ -352,10 +352,10 @@ def test_compressor_bigmem(self, size): @bigmemtest(size=_4G + 100, memuse=3) def test_decompressor_bigmem(self, size): lzd = LZMADecompressor() - blocksize = 10 * 1024 * 1024 + blocksize = min(10 * 1024 * 1024, size) block = random.randbytes(blocksize) try: - input = block * (size // blocksize + 1) + input = block * ((size-1) // blocksize + 1) cdata = lzma.compress(input) ddata = lzd.decompress(cdata) self.assertEqual(ddata, input) diff --git a/Lib/test/test_mailbox.py b/Lib/test/test_mailbox.py index 4977a9369ddf88..d84faad0eb3406 100644 --- a/Lib/test/test_mailbox.py +++ b/Lib/test/test_mailbox.py @@ -681,6 +681,20 @@ def test_initialize_existing(self): self._box = mailbox.Maildir(self._path) self._check_basics() + def test_filename_leading_dot(self): + self.tearDown() + for subdir in '', 'tmp', 'new', 'cur': + os.mkdir(os.path.normpath(os.path.join(self._path, subdir))) + for subdir in 'tmp', 'new', 'cur': + fname = os.path.join(self._path, subdir, '.foo' + subdir) + with open(fname, 'wb') as f: + f.write(b"@") + self._box = mailbox.Maildir(self._path) + self.assertNotIn('.footmp', self._box) + self.assertNotIn('.foonew', self._box) + self.assertNotIn('.foocur', self._box) + self.assertEqual(list(self._box.iterkeys()), []) + def _check_basics(self, factory=None): # (Used by test_open_new() and test_open_existing().) self.assertEqual(self._box._path, os.path.abspath(self._path)) @@ -847,6 +861,92 @@ def test_lock_unlock(self): self._box.lock() self._box.unlock() + def test_get_info(self): + # Test getting message info from Maildir, not the message. + msg = mailbox.MaildirMessage(self._template % 0) + key = self._box.add(msg) + self.assertEqual(self._box.get_info(key), '') + msg.set_info('OurTestInfo') + self._box[key] = msg + self.assertEqual(self._box.get_info(key), 'OurTestInfo') + + def test_set_info(self): + # Test setting message info from Maildir, not the message. + # This should immediately rename the message file. + msg = mailbox.MaildirMessage(self._template % 0) + key = self._box.add(msg) + def check_info(oldinfo, newinfo): + oldfilename = os.path.join(self._box._path, self._box._lookup(key)) + newsubpath = self._box._lookup(key).split(self._box.colon)[0] + if newinfo: + newsubpath += self._box.colon + newinfo + newfilename = os.path.join(self._box._path, newsubpath) + # assert initial conditions + self.assertEqual(self._box.get_info(key), oldinfo) + if not oldinfo: + self.assertNotIn(self._box._lookup(key), self._box.colon) + self.assertTrue(os.path.exists(oldfilename)) + if oldinfo != newinfo: + self.assertFalse(os.path.exists(newfilename)) + # do the rename + self._box.set_info(key, newinfo) + # assert post conditions + if not newinfo: + self.assertNotIn(self._box._lookup(key), self._box.colon) + if oldinfo != newinfo: + self.assertFalse(os.path.exists(oldfilename)) + self.assertTrue(os.path.exists(newfilename)) + self.assertEqual(self._box.get_info(key), newinfo) + # none -> has info + check_info('', 'info1') + # has info -> same info + check_info('info1', 'info1') + # has info -> different info + check_info('info1', 'info2') + # has info -> none + check_info('info2', '') + # none -> none + check_info('', '') + + def test_get_flags(self): + # Test getting message flags from Maildir, not the message. + msg = mailbox.MaildirMessage(self._template % 0) + key = self._box.add(msg) + self.assertEqual(self._box.get_flags(key), '') + msg.set_flags('T') + self._box[key] = msg + self.assertEqual(self._box.get_flags(key), 'T') + + def test_set_flags(self): + msg = mailbox.MaildirMessage(self._template % 0) + key = self._box.add(msg) + self.assertEqual(self._box.get_flags(key), '') + self._box.set_flags(key, 'S') + self.assertEqual(self._box.get_flags(key), 'S') + + def test_add_flag(self): + msg = mailbox.MaildirMessage(self._template % 0) + key = self._box.add(msg) + self.assertEqual(self._box.get_flags(key), '') + self._box.add_flag(key, 'B') + self.assertEqual(self._box.get_flags(key), 'B') + self._box.add_flag(key, 'B') + self.assertEqual(self._box.get_flags(key), 'B') + self._box.add_flag(key, 'AC') + self.assertEqual(self._box.get_flags(key), 'ABC') + + def test_remove_flag(self): + msg = mailbox.MaildirMessage(self._template % 0) + key = self._box.add(msg) + self._box.set_flags(key, 'abc') + self.assertEqual(self._box.get_flags(key), 'abc') + self._box.remove_flag(key, 'b') + self.assertEqual(self._box.get_flags(key), 'ac') + self._box.remove_flag(key, 'b') + self.assertEqual(self._box.get_flags(key), 'ac') + self._box.remove_flag(key, 'ac') + self.assertEqual(self._box.get_flags(key), '') + def test_folder (self): # Test for bug #1569790: verify that folders returned by .get_folder() # use the same factory function. @@ -1247,6 +1347,28 @@ def test_sequences(self): self._box.remove(key1) self.assertEqual(self._box.get_sequences(), {'flagged':[key0]}) + self._box.set_sequences({'foo':[key0]}) + self.assertEqual(self._box.get_sequences(), {'foo':[key0]}) + + def test_no_dot_mh_sequences_file(self): + path = os.path.join(self._path, 'foo.bar') + os.mkdir(path) + box = self._factory(path) + self.assertEqual(os.listdir(path), []) + self.assertEqual(box.get_sequences(), {}) + self.assertEqual(os.listdir(path), []) + box.set_sequences({}) + self.assertEqual(os.listdir(path), ['.mh_sequences']) + + def test_lock_unlock_no_dot_mh_sequences_file(self): + path = os.path.join(self._path, 'foo.bar') + os.mkdir(path) + box = self._factory(path) + self.assertEqual(os.listdir(path), []) + box.lock() + box.unlock() + self.assertEqual(os.listdir(path), ['.mh_sequences']) + def test_issue2625(self): msg0 = mailbox.MHMessage(self._template % 0) msg0.add_sequence('foo') diff --git a/Lib/test/test_math.py b/Lib/test/test_math.py index 2bda61012164d1..ad382fc2b59891 100644 --- a/Lib/test/test_math.py +++ b/Lib/test/test_math.py @@ -33,8 +33,8 @@ else: file = __file__ test_dir = os.path.dirname(file) or os.curdir -math_testcases = os.path.join(test_dir, 'math_testcases.txt') -test_file = os.path.join(test_dir, 'cmath_testcases.txt') +math_testcases = os.path.join(test_dir, 'mathdata', 'math_testcases.txt') +test_file = os.path.join(test_dir, 'mathdata', 'cmath_testcases.txt') def to_ulps(x): @@ -235,6 +235,10 @@ def __init__(self, value): def __index__(self): return self.value +class BadDescr: + def __get__(self, obj, objtype=None): + raise ValueError + class MathTests(unittest.TestCase): def ftest(self, name, got, expected, ulp_tol=5, abs_tol=0.0): @@ -324,6 +328,7 @@ def testAtan2(self): self.ftest('atan2(0, 1)', math.atan2(0, 1), 0) self.ftest('atan2(1, 1)', math.atan2(1, 1), math.pi/4) self.ftest('atan2(1, 0)', math.atan2(1, 0), math.pi/2) + self.ftest('atan2(1, -1)', math.atan2(1, -1), 3*math.pi/4) # math.atan2(0, x) self.ftest('atan2(0., -inf)', math.atan2(0., NINF), math.pi) @@ -417,16 +422,22 @@ def __ceil__(self): return 42 class TestNoCeil: pass + class TestBadCeil: + __ceil__ = BadDescr() self.assertEqual(math.ceil(TestCeil()), 42) self.assertEqual(math.ceil(FloatCeil()), 42) self.assertEqual(math.ceil(FloatLike(42.5)), 43) self.assertRaises(TypeError, math.ceil, TestNoCeil()) + self.assertRaises(ValueError, math.ceil, TestBadCeil()) t = TestNoCeil() t.__ceil__ = lambda *args: args self.assertRaises(TypeError, math.ceil, t) self.assertRaises(TypeError, math.ceil, t, 0) + self.assertEqual(math.ceil(FloatLike(+1.0)), +1.0) + self.assertEqual(math.ceil(FloatLike(-1.0)), -1.0) + @requires_IEEE_754 def testCopysign(self): self.assertEqual(math.copysign(1, 42), 1.0) @@ -567,16 +578,22 @@ def __floor__(self): return 42 class TestNoFloor: pass + class TestBadFloor: + __floor__ = BadDescr() self.assertEqual(math.floor(TestFloor()), 42) self.assertEqual(math.floor(FloatFloor()), 42) self.assertEqual(math.floor(FloatLike(41.9)), 41) self.assertRaises(TypeError, math.floor, TestNoFloor()) + self.assertRaises(ValueError, math.floor, TestBadFloor()) t = TestNoFloor() t.__floor__ = lambda *args: args self.assertRaises(TypeError, math.floor, t) self.assertRaises(TypeError, math.floor, t, 0) + self.assertEqual(math.floor(FloatLike(+1.0)), +1.0) + self.assertEqual(math.floor(FloatLike(-1.0)), -1.0) + def testFmod(self): self.assertRaises(TypeError, math.fmod) self.ftest('fmod(10, 1)', math.fmod(10, 1), 0.0) @@ -598,6 +615,7 @@ def testFmod(self): self.assertEqual(math.fmod(-3.0, NINF), -3.0) self.assertEqual(math.fmod(0.0, 3.0), 0.0) self.assertEqual(math.fmod(0.0, NINF), 0.0) + self.assertRaises(ValueError, math.fmod, INF, INF) def testFrexp(self): self.assertRaises(TypeError, math.frexp) @@ -667,6 +685,7 @@ def msum(iterable): ([], 0.0), ([0.0], 0.0), ([1e100, 1.0, -1e100, 1e-100, 1e50, -1.0, -1e50], 1e-100), + ([1e100, 1.0, -1e100, 1e-100, 1e50, -1, -1e50], 1e-100), ([2.0**53, -0.5, -2.0**-54], 2.0**53-1.0), ([2.0**53, 1.0, 2.0**-100], 2.0**53+2.0), ([2.0**53+10.0, 1.0, 2.0**-100], 2.0**53+12.0), @@ -714,6 +733,22 @@ def msum(iterable): s = msum(vals) self.assertEqual(msum(vals), math.fsum(vals)) + self.assertEqual(math.fsum([1.0, math.inf]), math.inf) + self.assertTrue(math.isnan(math.fsum([math.nan, 1.0]))) + self.assertEqual(math.fsum([1e100, FloatLike(1.0), -1e100, 1e-100, + 1e50, FloatLike(-1.0), -1e50]), 1e-100) + self.assertRaises(OverflowError, math.fsum, [1e+308, 1e+308]) + self.assertRaises(ValueError, math.fsum, [math.inf, -math.inf]) + self.assertRaises(TypeError, math.fsum, ['spam']) + self.assertRaises(TypeError, math.fsum, 1) + self.assertRaises(OverflowError, math.fsum, [10**1000]) + + def bad_iter(): + yield 1.0 + raise ZeroDivisionError + + self.assertRaises(ZeroDivisionError, math.fsum, bad_iter()) + def testGcd(self): gcd = math.gcd self.assertEqual(gcd(0, 0), 0) @@ -774,6 +809,8 @@ def testHypot(self): # Test allowable types (those with __float__) self.assertEqual(hypot(12.0, 5.0), 13.0) self.assertEqual(hypot(12, 5), 13) + self.assertEqual(hypot(1, -1), math.sqrt(2)) + self.assertEqual(hypot(1, FloatLike(-1.)), math.sqrt(2)) self.assertEqual(hypot(Decimal(12), Decimal(5)), 13) self.assertEqual(hypot(Fraction(12, 32), Fraction(5, 32)), Fraction(13, 32)) self.assertEqual(hypot(bool(1), bool(0), bool(1), bool(1)), math.sqrt(3)) @@ -831,6 +868,8 @@ def testHypot(self): scale = FLOAT_MIN / 2.0 ** exp self.assertEqual(math.hypot(4*scale, 3*scale), 5*scale) + self.assertRaises(TypeError, math.hypot, *([1.0]*18), 'spam') + @requires_IEEE_754 @unittest.skipIf(HAVE_DOUBLE_ROUNDING, "hypot() loses accuracy on machines with double rounding") @@ -923,6 +962,10 @@ def testDist(self): # Test allowable types (those with __float__) self.assertEqual(dist((14.0, 1.0), (2.0, -4.0)), 13.0) self.assertEqual(dist((14, 1), (2, -4)), 13) + self.assertEqual(dist((FloatLike(14.), 1), (2, -4)), 13) + self.assertEqual(dist((11, 1), (FloatLike(-1.), -4)), 13) + self.assertEqual(dist((14, FloatLike(-1.)), (2, -6)), 13) + self.assertEqual(dist((14, -1), (2, -6)), 13) self.assertEqual(dist((D(14), D(1)), (D(2), D(-4))), D(13)) self.assertEqual(dist((F(14, 32), F(1, 32)), (F(2, 32), F(-4, 32))), F(13, 32)) @@ -966,6 +1009,8 @@ class T(tuple): dist((1, 2, 3, 4), (5, 6, 7)) with self.assertRaises(ValueError): # Check dimension agree dist((1, 2, 3), (4, 5, 6, 7)) + with self.assertRaises(TypeError): + dist((1,)*17 + ("spam",), (1,)*18) with self.assertRaises(TypeError): # Rejects invalid types dist("abc", "xyz") int_too_big_for_float = 10 ** (sys.float_info.max_10_exp + 5) @@ -973,6 +1018,16 @@ class T(tuple): dist((1, int_too_big_for_float), (2, 3)) with self.assertRaises((ValueError, OverflowError)): dist((2, 3), (1, int_too_big_for_float)) + with self.assertRaises(TypeError): + dist((1,), 2) + with self.assertRaises(TypeError): + dist([1], 2) + + class BadFloat: + __float__ = BadDescr() + + with self.assertRaises(ValueError): + dist([1], [BadFloat()]) # Verify that the one dimensional case is equivalent to abs() for i in range(20): @@ -1111,6 +1166,7 @@ def test_lcm(self): def testLdexp(self): self.assertRaises(TypeError, math.ldexp) + self.assertRaises(TypeError, math.ldexp, 2.0, 1.1) self.ftest('ldexp(0,1)', math.ldexp(0,1), 0) self.ftest('ldexp(1,1)', math.ldexp(1,1), 2) self.ftest('ldexp(1,-1)', math.ldexp(1,-1), 0.5) @@ -1143,6 +1199,7 @@ def testLdexp(self): def testLog(self): self.assertRaises(TypeError, math.log) + self.assertRaises(TypeError, math.log, 1, 2, 3) self.ftest('log(1/e)', math.log(1/math.e), -1) self.ftest('log(1)', math.log(1), 0) self.ftest('log(e)', math.log(math.e), 1) @@ -1153,6 +1210,7 @@ def testLog(self): 2302.5850929940457) self.assertRaises(ValueError, math.log, -1.5) self.assertRaises(ValueError, math.log, -10**1000) + self.assertRaises(ValueError, math.log, 10, -10) self.assertRaises(ValueError, math.log, NINF) self.assertEqual(math.log(INF), INF) self.assertTrue(math.isnan(math.log(NAN))) @@ -1212,6 +1270,8 @@ def testSumProd(self): self.assertEqual(sumprod(iter([10, 20, 30]), (1, 2, 3)), 140) self.assertEqual(sumprod([1.5, 2.5], [3.5, 4.5]), 16.5) self.assertEqual(sumprod([], []), 0) + self.assertEqual(sumprod([-1], [1.]), -1) + self.assertEqual(sumprod([1.], [-1]), -1) # Type preservation and coercion for v in [ @@ -1237,11 +1297,20 @@ def testSumProd(self): self.assertRaises(TypeError, sumprod, [], [], []) # Three args self.assertRaises(TypeError, sumprod, None, [10]) # Non-iterable self.assertRaises(TypeError, sumprod, [10], None) # Non-iterable + self.assertRaises(TypeError, sumprod, ['x'], [1.0]) # Uneven lengths self.assertRaises(ValueError, sumprod, [10, 20], [30]) self.assertRaises(ValueError, sumprod, [10], [20, 30]) + # Overflows + self.assertEqual(sumprod([10**20], [1]), 10**20) + self.assertEqual(sumprod([1], [10**20]), 10**20) + self.assertEqual(sumprod([10**10], [10**10]), 10**20) + self.assertEqual(sumprod([10**7]*10**5, [10**7]*10**5), 10**19) + self.assertRaises(OverflowError, sumprod, [10**1000], [1.0]) + self.assertRaises(OverflowError, sumprod, [1.0], [10**1000]) + # Error in iterator def raise_after(n): for i in range(n): @@ -1252,6 +1321,11 @@ def raise_after(n): with self.assertRaises(RuntimeError): sumprod(raise_after(5), range(10)) + from test.test_iter import BasicIterClass + + self.assertEqual(sumprod(BasicIterClass(1), [1]), 0) + self.assertEqual(sumprod([1], BasicIterClass(1)), 0) + # Error in multiplication class BadMultiply: def __mul__(self, other): @@ -1292,6 +1366,7 @@ def test_sumprod_accuracy(self): sumprod = math.sumprod self.assertEqual(sumprod([0.1] * 10, [1]*10), 1.0) self.assertEqual(sumprod([0.1] * 20, [True, False] * 10), 1.0) + self.assertEqual(sumprod([True, False] * 10, [0.1] * 20), 1.0) self.assertEqual(sumprod([1.0, 10E100, 1.0, -10E100], [1.0]*4), 2.0) @support.requires_resource('cpu') @@ -1490,6 +1565,7 @@ def testPow(self): self.assertTrue(math.isnan(math.pow(2, NAN))) self.assertTrue(math.isnan(math.pow(0, NAN))) self.assertEqual(math.pow(1, NAN), 1) + self.assertRaises(OverflowError, math.pow, 1e+100, 1e+100) # pow(0., x) self.assertEqual(math.pow(0., INF), 0.) @@ -1846,6 +1922,8 @@ def __trunc__(self): return 23 class TestNoTrunc: pass + class TestBadTrunc: + __trunc__ = BadDescr() self.assertEqual(math.trunc(TestTrunc()), 23) self.assertEqual(math.trunc(FloatTrunc()), 23) @@ -1854,6 +1932,7 @@ class TestNoTrunc: self.assertRaises(TypeError, math.trunc, 1, 2) self.assertRaises(TypeError, math.trunc, FloatLike(23.5)) self.assertRaises(TypeError, math.trunc, TestNoTrunc()) + self.assertRaises(ValueError, math.trunc, TestBadTrunc()) def testIsfinite(self): self.assertTrue(math.isfinite(0.0)) @@ -2054,6 +2133,8 @@ def test_mtestfile(self): '\n '.join(failures)) def test_prod(self): + from fractions import Fraction as F + prod = math.prod self.assertEqual(prod([]), 1) self.assertEqual(prod([], start=5), 5) @@ -2065,6 +2146,14 @@ def test_prod(self): self.assertEqual(prod([1.0, 2.0, 3.0, 4.0, 5.0]), 120.0) self.assertEqual(prod([1, 2, 3, 4.0, 5.0]), 120.0) self.assertEqual(prod([1.0, 2.0, 3.0, 4, 5]), 120.0) + self.assertEqual(prod([1., F(3, 2)]), 1.5) + + # Error in multiplication + class BadMultiply: + def __rmul__(self, other): + raise RuntimeError + with self.assertRaises(RuntimeError): + prod([10., BadMultiply()]) # Test overflow in fast-path for integers self.assertEqual(prod([1, 1, 2**32, 1, 1]), 2**32) @@ -2378,6 +2467,14 @@ def __float__(self): # argument to a float. self.assertFalse(getattr(y, "converted", False)) + def test_input_exceptions(self): + self.assertRaises(TypeError, math.exp, "spam") + self.assertRaises(TypeError, math.erf, "spam") + self.assertRaises(TypeError, math.atan2, "spam", 1.0) + self.assertRaises(TypeError, math.atan2, 1.0, "spam") + self.assertRaises(TypeError, math.atan2, 1.0) + self.assertRaises(TypeError, math.atan2, 1.0, 2.0, 3.0) + # Custom assertions. def assertIsNaN(self, value): @@ -2518,7 +2615,7 @@ def test_fractions(self): def load_tests(loader, tests, pattern): from doctest import DocFileSuite - tests.addTest(DocFileSuite("ieee754.txt")) + tests.addTest(DocFileSuite(os.path.join("mathdata", "ieee754.txt"))) return tests if __name__ == '__main__': diff --git a/Lib/test/test_memoryio.py b/Lib/test/test_memoryio.py index cd2faba1791c77..8192502a40791b 100644 --- a/Lib/test/test_memoryio.py +++ b/Lib/test/test_memoryio.py @@ -6,10 +6,12 @@ import unittest from test import support +import gc import io import _pyio as pyio import pickle import sys +import weakref class IntLike: def __init__(self, num): @@ -463,6 +465,39 @@ def test_getbuffer(self): memio.close() self.assertRaises(ValueError, memio.getbuffer) + def test_getbuffer_empty(self): + memio = self.ioclass() + buf = memio.getbuffer() + self.assertEqual(bytes(buf), b"") + # Trying to change the size of the BytesIO while a buffer is exported + # raises a BufferError. + self.assertRaises(BufferError, memio.write, b'x') + buf2 = memio.getbuffer() + self.assertRaises(BufferError, memio.write, b'x') + buf.release() + self.assertRaises(BufferError, memio.write, b'x') + buf2.release() + memio.write(b'x') + + def test_getbuffer_gc_collect(self): + memio = self.ioclass(b"1234567890") + buf = memio.getbuffer() + memiowr = weakref.ref(memio) + bufwr = weakref.ref(buf) + # Create a reference loop. + a = [buf] + a.append(a) + # The Python implementation emits an unraisable exception. + with support.catch_unraisable_exception(): + del memio + del buf + del a + # The C implementation emits an unraisable exception. + with support.catch_unraisable_exception(): + gc.collect() + self.assertIsNone(memiowr()) + self.assertIsNone(bufwr()) + def test_read1(self): buf = self.buftype("1234567890") self.assertEqual(self.ioclass(buf).read1(), buf) diff --git a/Lib/test/test_minidom.py b/Lib/test/test_minidom.py index 699265ccadc7f9..3ecd1af31eea77 100644 --- a/Lib/test/test_minidom.py +++ b/Lib/test/test_minidom.py @@ -505,6 +505,46 @@ def testWriteXML(self): dom.unlink() self.confirm(str == domstr) + def test_toxml_quote_text(self): + dom = Document() + elem = dom.appendChild(dom.createElement('elem')) + elem.appendChild(dom.createTextNode('&<>"')) + cr = elem.appendChild(dom.createElement('cr')) + cr.appendChild(dom.createTextNode('\r')) + crlf = elem.appendChild(dom.createElement('crlf')) + crlf.appendChild(dom.createTextNode('\r\n')) + lflf = elem.appendChild(dom.createElement('lflf')) + lflf.appendChild(dom.createTextNode('\n\n')) + ws = elem.appendChild(dom.createElement('ws')) + ws.appendChild(dom.createTextNode('\t\n\r ')) + domstr = dom.toxml() + dom.unlink() + self.assertEqual(domstr, '' + '&<>"' + '\r' + '\r\n' + '\n\n' + '\t\n\r ') + + def test_toxml_quote_attrib(self): + dom = Document() + elem = dom.appendChild(dom.createElement('elem')) + elem.setAttribute("a", '&<>"') + elem.setAttribute("cr", "\r") + elem.setAttribute("lf", "\n") + elem.setAttribute("crlf", "\r\n") + elem.setAttribute("lflf", "\n\n") + elem.setAttribute("ws", "\t\n\r ") + domstr = dom.toxml() + dom.unlink() + self.assertEqual(domstr, '' + '') + def testAltNewline(self): str = '\n\n' dom = parseString(str) diff --git a/Lib/test/test_mmap.py b/Lib/test/test_mmap.py index bab868600895c1..f1e4b1efe2d0aa 100644 --- a/Lib/test/test_mmap.py +++ b/Lib/test/test_mmap.py @@ -93,11 +93,12 @@ def test_basic(self): self.assertEqual(end, PAGESIZE + 6) # test seeking around (try to overflow the seek implementation) - m.seek(0,0) + self.assertTrue(m.seekable()) + self.assertEqual(m.seek(0, 0), 0) self.assertEqual(m.tell(), 0) - m.seek(42,1) + self.assertEqual(m.seek(42, 1), 42) self.assertEqual(m.tell(), 42) - m.seek(0,2) + self.assertEqual(m.seek(0, 2), len(m)) self.assertEqual(m.tell(), len(m)) # Try to seek to negative position... @@ -162,7 +163,7 @@ def test_access_parameter(self): # Ensuring that readonly mmap can't be write() to try: - m.seek(0,0) + m.seek(0, 0) m.write(b'abc') except TypeError: pass @@ -171,7 +172,7 @@ def test_access_parameter(self): # Ensuring that readonly mmap can't be write_byte() to try: - m.seek(0,0) + m.seek(0, 0) m.write_byte(b'd') except TypeError: pass @@ -255,10 +256,15 @@ def test_access_parameter(self): # Try writing with PROT_EXEC and without PROT_WRITE prot = mmap.PROT_READ | getattr(mmap, 'PROT_EXEC', 0) with open(TESTFN, "r+b") as f: - m = mmap.mmap(f.fileno(), mapsize, prot=prot) - self.assertRaises(TypeError, m.write, b"abcdef") - self.assertRaises(TypeError, m.write_byte, 0) - m.close() + try: + m = mmap.mmap(f.fileno(), mapsize, prot=prot) + except PermissionError: + # on macOS 14, PROT_READ | PROT_EXEC is not allowed + pass + else: + self.assertRaises(TypeError, m.write, b"abcdef") + self.assertRaises(TypeError, m.write_byte, 0) + m.close() def test_bad_file_desc(self): # Try opening a bad file descriptor... @@ -666,14 +672,16 @@ def test_tagname(self): m2.close() m1.close() + with self.assertRaisesRegex(TypeError, 'tagname'): + mmap.mmap(-1, 8, tagname=1) + @cpython_only @unittest.skipUnless(os.name == 'nt', 'requires Windows') def test_sizeof(self): m1 = mmap.mmap(-1, 100) tagname = random_tagname() m2 = mmap.mmap(-1, 100, tagname=tagname) - self.assertEqual(sys.getsizeof(m2), - sys.getsizeof(m1) + len(tagname) + 1) + self.assertGreater(sys.getsizeof(m2), sys.getsizeof(m1)) @unittest.skipUnless(os.name == 'nt', 'requires Windows') def test_crasher_on_windows(self): diff --git a/Lib/test/test_module.py b/Lib/test/test_module.py deleted file mode 100644 index c7eb92290e1b6d..00000000000000 --- a/Lib/test/test_module.py +++ /dev/null @@ -1,368 +0,0 @@ -# Test the module type -import unittest -import weakref -from test.support import gc_collect -from test.support import import_helper -from test.support.script_helper import assert_python_ok - -import sys -ModuleType = type(sys) - - -class FullLoader: - pass - - -class BareLoader: - pass - - -class ModuleTests(unittest.TestCase): - def test_uninitialized(self): - # An uninitialized module has no __dict__ or __name__, - # and __doc__ is None - foo = ModuleType.__new__(ModuleType) - self.assertTrue(isinstance(foo.__dict__, dict)) - self.assertEqual(dir(foo), []) - try: - s = foo.__name__ - self.fail("__name__ = %s" % repr(s)) - except AttributeError: - pass - self.assertEqual(foo.__doc__, ModuleType.__doc__) - - def test_uninitialized_missing_getattr(self): - # Issue 8297 - # test the text in the AttributeError of an uninitialized module - foo = ModuleType.__new__(ModuleType) - self.assertRaisesRegex( - AttributeError, "module has no attribute 'not_here'", - getattr, foo, "not_here") - - def test_missing_getattr(self): - # Issue 8297 - # test the text in the AttributeError - foo = ModuleType("foo") - self.assertRaisesRegex( - AttributeError, "module 'foo' has no attribute 'not_here'", - getattr, foo, "not_here") - - def test_no_docstring(self): - # Regularly initialized module, no docstring - foo = ModuleType("foo") - self.assertEqual(foo.__name__, "foo") - self.assertEqual(foo.__doc__, None) - self.assertIs(foo.__loader__, None) - self.assertIs(foo.__package__, None) - self.assertIs(foo.__spec__, None) - self.assertEqual(foo.__dict__, {"__name__": "foo", "__doc__": None, - "__loader__": None, "__package__": None, - "__spec__": None}) - - def test_ascii_docstring(self): - # ASCII docstring - foo = ModuleType("foo", "foodoc") - self.assertEqual(foo.__name__, "foo") - self.assertEqual(foo.__doc__, "foodoc") - self.assertEqual(foo.__dict__, - {"__name__": "foo", "__doc__": "foodoc", - "__loader__": None, "__package__": None, - "__spec__": None}) - - def test_unicode_docstring(self): - # Unicode docstring - foo = ModuleType("foo", "foodoc\u1234") - self.assertEqual(foo.__name__, "foo") - self.assertEqual(foo.__doc__, "foodoc\u1234") - self.assertEqual(foo.__dict__, - {"__name__": "foo", "__doc__": "foodoc\u1234", - "__loader__": None, "__package__": None, - "__spec__": None}) - - def test_reinit(self): - # Reinitialization should not replace the __dict__ - foo = ModuleType("foo", "foodoc\u1234") - foo.bar = 42 - d = foo.__dict__ - foo.__init__("foo", "foodoc") - self.assertEqual(foo.__name__, "foo") - self.assertEqual(foo.__doc__, "foodoc") - self.assertEqual(foo.bar, 42) - self.assertEqual(foo.__dict__, - {"__name__": "foo", "__doc__": "foodoc", "bar": 42, - "__loader__": None, "__package__": None, "__spec__": None}) - self.assertTrue(foo.__dict__ is d) - - def test_dont_clear_dict(self): - # See issue 7140. - def f(): - foo = ModuleType("foo") - foo.bar = 4 - return foo - gc_collect() - self.assertEqual(f().__dict__["bar"], 4) - - def test_clear_dict_in_ref_cycle(self): - destroyed = [] - m = ModuleType("foo") - m.destroyed = destroyed - s = """class A: - def __init__(self, l): - self.l = l - def __del__(self): - self.l.append(1) -a = A(destroyed)""" - exec(s, m.__dict__) - del m - gc_collect() - self.assertEqual(destroyed, [1]) - - def test_weakref(self): - m = ModuleType("foo") - wr = weakref.ref(m) - self.assertIs(wr(), m) - del m - gc_collect() - self.assertIs(wr(), None) - - def test_module_getattr(self): - import test.good_getattr as gga - from test.good_getattr import test - self.assertEqual(test, "There is test") - self.assertEqual(gga.x, 1) - self.assertEqual(gga.y, 2) - with self.assertRaisesRegex(AttributeError, - "Deprecated, use whatever instead"): - gga.yolo - self.assertEqual(gga.whatever, "There is whatever") - del sys.modules['test.good_getattr'] - - def test_module_getattr_errors(self): - import test.bad_getattr as bga - from test import bad_getattr2 - self.assertEqual(bga.x, 1) - self.assertEqual(bad_getattr2.x, 1) - with self.assertRaises(TypeError): - bga.nope - with self.assertRaises(TypeError): - bad_getattr2.nope - del sys.modules['test.bad_getattr'] - if 'test.bad_getattr2' in sys.modules: - del sys.modules['test.bad_getattr2'] - - def test_module_dir(self): - import test.good_getattr as gga - self.assertEqual(dir(gga), ['a', 'b', 'c']) - del sys.modules['test.good_getattr'] - - def test_module_dir_errors(self): - import test.bad_getattr as bga - from test import bad_getattr2 - with self.assertRaises(TypeError): - dir(bga) - with self.assertRaises(TypeError): - dir(bad_getattr2) - del sys.modules['test.bad_getattr'] - if 'test.bad_getattr2' in sys.modules: - del sys.modules['test.bad_getattr2'] - - def test_module_getattr_tricky(self): - from test import bad_getattr3 - # these lookups should not crash - with self.assertRaises(AttributeError): - bad_getattr3.one - with self.assertRaises(AttributeError): - bad_getattr3.delgetattr - if 'test.bad_getattr3' in sys.modules: - del sys.modules['test.bad_getattr3'] - - def test_module_repr_minimal(self): - # reprs when modules have no __file__, __name__, or __loader__ - m = ModuleType('foo') - del m.__name__ - self.assertEqual(repr(m), "") - - def test_module_repr_with_name(self): - m = ModuleType('foo') - self.assertEqual(repr(m), "") - - def test_module_repr_with_name_and_filename(self): - m = ModuleType('foo') - m.__file__ = '/tmp/foo.py' - self.assertEqual(repr(m), "") - - def test_module_repr_with_filename_only(self): - m = ModuleType('foo') - del m.__name__ - m.__file__ = '/tmp/foo.py' - self.assertEqual(repr(m), "") - - def test_module_repr_with_loader_as_None(self): - m = ModuleType('foo') - assert m.__loader__ is None - self.assertEqual(repr(m), "") - - def test_module_repr_with_bare_loader_but_no_name(self): - m = ModuleType('foo') - del m.__name__ - # Yes, a class not an instance. - m.__loader__ = BareLoader - loader_repr = repr(BareLoader) - self.assertEqual( - repr(m), "".format(loader_repr)) - - def test_module_repr_with_full_loader_but_no_name(self): - # m.__loader__.module_repr() will fail because the module has no - # m.__name__. This exception will get suppressed and instead the - # loader's repr will be used. - m = ModuleType('foo') - del m.__name__ - # Yes, a class not an instance. - m.__loader__ = FullLoader - loader_repr = repr(FullLoader) - self.assertEqual( - repr(m), "".format(loader_repr)) - - def test_module_repr_with_bare_loader(self): - m = ModuleType('foo') - # Yes, a class not an instance. - m.__loader__ = BareLoader - module_repr = repr(BareLoader) - self.assertEqual( - repr(m), "".format(module_repr)) - - def test_module_repr_with_full_loader(self): - m = ModuleType('foo') - # Yes, a class not an instance. - m.__loader__ = FullLoader - self.assertEqual( - repr(m), f")>") - - def test_module_repr_with_bare_loader_and_filename(self): - m = ModuleType('foo') - # Yes, a class not an instance. - m.__loader__ = BareLoader - m.__file__ = '/tmp/foo.py' - self.assertEqual(repr(m), "") - - def test_module_repr_with_full_loader_and_filename(self): - m = ModuleType('foo') - # Yes, a class not an instance. - m.__loader__ = FullLoader - m.__file__ = '/tmp/foo.py' - self.assertEqual(repr(m), "") - - def test_module_repr_builtin(self): - self.assertEqual(repr(sys), "") - - def test_module_repr_source(self): - r = repr(unittest) - starts_with = "") + + def test_module_repr_with_name(self): + m = ModuleType('foo') + self.assertEqual(repr(m), "") + + def test_module_repr_with_name_and_filename(self): + m = ModuleType('foo') + m.__file__ = '/tmp/foo.py' + self.assertEqual(repr(m), "") + + def test_module_repr_with_filename_only(self): + m = ModuleType('foo') + del m.__name__ + m.__file__ = '/tmp/foo.py' + self.assertEqual(repr(m), "") + + def test_module_repr_with_loader_as_None(self): + m = ModuleType('foo') + assert m.__loader__ is None + self.assertEqual(repr(m), "") + + def test_module_repr_with_bare_loader_but_no_name(self): + m = ModuleType('foo') + del m.__name__ + # Yes, a class not an instance. + m.__loader__ = BareLoader + loader_repr = repr(BareLoader) + self.assertEqual( + repr(m), "".format(loader_repr)) + + def test_module_repr_with_full_loader_but_no_name(self): + # m.__loader__.module_repr() will fail because the module has no + # m.__name__. This exception will get suppressed and instead the + # loader's repr will be used. + m = ModuleType('foo') + del m.__name__ + # Yes, a class not an instance. + m.__loader__ = FullLoader + loader_repr = repr(FullLoader) + self.assertEqual( + repr(m), "".format(loader_repr)) + + def test_module_repr_with_bare_loader(self): + m = ModuleType('foo') + # Yes, a class not an instance. + m.__loader__ = BareLoader + module_repr = repr(BareLoader) + self.assertEqual( + repr(m), "".format(module_repr)) + + def test_module_repr_with_full_loader(self): + m = ModuleType('foo') + # Yes, a class not an instance. + m.__loader__ = FullLoader + self.assertEqual( + repr(m), f")>") + + def test_module_repr_with_bare_loader_and_filename(self): + m = ModuleType('foo') + # Yes, a class not an instance. + m.__loader__ = BareLoader + m.__file__ = '/tmp/foo.py' + self.assertEqual(repr(m), "") + + def test_module_repr_with_full_loader_and_filename(self): + m = ModuleType('foo') + # Yes, a class not an instance. + m.__loader__ = FullLoader + m.__file__ = '/tmp/foo.py' + self.assertEqual(repr(m), "") + + def test_module_repr_builtin(self): + self.assertEqual(repr(sys), "") + + def test_module_repr_source(self): + r = repr(unittest) + starts_with = "") + + def test_module_repr_with_namespace_package_and_custom_loader(self): + m = ModuleType('foo') + loader = BareLoader() + spec = importlib.machinery.ModuleSpec('foo', loader) + m.__loader__ = loader + m.__spec__ = spec + expected_repr_pattern = r"\)>" + self.assertRegex(repr(m), expected_repr_pattern) + self.assertNotIn('from', repr(m)) + + def test_module_repr_with_fake_namespace_package(self): + m = ModuleType('foo') + loader = BareLoader() + loader._path = ['spam'] + spec = importlib.machinery.ModuleSpec('foo', loader) + m.__loader__ = loader + m.__spec__ = spec + expected_repr_pattern = r"\)>" + self.assertRegex(repr(m), expected_repr_pattern) + self.assertNotIn('from', repr(m)) + + def test_module_finalization_at_shutdown(self): + # Module globals and builtins should still be available during shutdown + rc, out, err = assert_python_ok("-c", "from test.test_module import final_a") + self.assertFalse(err) + lines = out.splitlines() + self.assertEqual(set(lines), { + b"x = a", + b"x = b", + b"final_a.x = a", + b"final_b.x = b", + b"len = len", + b"shutil.rmtree = rmtree"}) + + def test_descriptor_errors_propagate(self): + class Descr: + def __get__(self, o, t): + raise RuntimeError + class M(ModuleType): + melon = Descr() + self.assertRaises(RuntimeError, getattr, M("mymod"), "melon") + + def test_lazy_create_annotations(self): + # module objects lazy create their __annotations__ dict on demand. + # the annotations dict is stored in module.__dict__. + # a freshly created module shouldn't have an annotations dict yet. + foo = ModuleType("foo") + for i in range(4): + self.assertFalse("__annotations__" in foo.__dict__) + d = foo.__annotations__ + self.assertTrue("__annotations__" in foo.__dict__) + self.assertEqual(foo.__annotations__, d) + self.assertEqual(foo.__dict__['__annotations__'], d) + if i % 2: + del foo.__annotations__ + else: + del foo.__dict__['__annotations__'] + + def test_setting_annotations(self): + foo = ModuleType("foo") + for i in range(4): + self.assertFalse("__annotations__" in foo.__dict__) + d = {'a': int} + foo.__annotations__ = d + self.assertTrue("__annotations__" in foo.__dict__) + self.assertEqual(foo.__annotations__, d) + self.assertEqual(foo.__dict__['__annotations__'], d) + if i % 2: + del foo.__annotations__ + else: + del foo.__dict__['__annotations__'] + + def test_annotations_getset_raises(self): + # double delete + foo = ModuleType("foo") + foo.__annotations__ = {} + del foo.__annotations__ + with self.assertRaises(AttributeError): + del foo.__annotations__ + + def test_annotations_are_created_correctly(self): + ann_module4 = import_helper.import_fresh_module( + 'test.typinganndata.ann_module4', + ) + self.assertTrue("__annotations__" in ann_module4.__dict__) + del ann_module4.__annotations__ + self.assertFalse("__annotations__" in ann_module4.__dict__) + + + def test_repeated_attribute_pops(self): + # Repeated accesses to module attribute will be specialized + # Check that popping the attribute doesn't break it + m = ModuleType("test") + d = m.__dict__ + count = 0 + for _ in range(100): + m.attr = 1 + count += m.attr # Might be specialized + d.pop("attr") + self.assertEqual(count, 100) + + # frozen and namespace module reprs are tested in importlib. + + def test_subclass_with_slots(self): + # In 3.11alpha this crashed, as the slots weren't NULLed. + + class ModuleWithSlots(ModuleType): + __slots__ = ("a", "b") + + def __init__(self, name): + super().__init__(name) + + m = ModuleWithSlots("name") + with self.assertRaises(AttributeError): + m.a + with self.assertRaises(AttributeError): + m.b + m.a, m.b = 1, 2 + self.assertEqual(m.a, 1) + self.assertEqual(m.b, 2) + + + +if __name__ == '__main__': + unittest.main() diff --git a/Lib/test/bad_getattr.py b/Lib/test/test_module/bad_getattr.py similarity index 100% rename from Lib/test/bad_getattr.py rename to Lib/test/test_module/bad_getattr.py diff --git a/Lib/test/bad_getattr2.py b/Lib/test/test_module/bad_getattr2.py similarity index 100% rename from Lib/test/bad_getattr2.py rename to Lib/test/test_module/bad_getattr2.py diff --git a/Lib/test/bad_getattr3.py b/Lib/test/test_module/bad_getattr3.py similarity index 100% rename from Lib/test/bad_getattr3.py rename to Lib/test/test_module/bad_getattr3.py diff --git a/Lib/test/final_a.py b/Lib/test/test_module/final_a.py similarity index 79% rename from Lib/test/final_a.py rename to Lib/test/test_module/final_a.py index 390ee8895a8a9e..a983f3111248e0 100644 --- a/Lib/test/final_a.py +++ b/Lib/test/test_module/final_a.py @@ -3,7 +3,7 @@ """ import shutil -import test.final_b +import test.test_module.final_b x = 'a' @@ -11,7 +11,7 @@ class C: def __del__(self): # Inspect module globals and builtins print("x =", x) - print("final_b.x =", test.final_b.x) + print("final_b.x =", test.test_module.final_b.x) print("shutil.rmtree =", getattr(shutil.rmtree, '__name__', None)) print("len =", getattr(len, '__name__', None)) diff --git a/Lib/test/final_b.py b/Lib/test/test_module/final_b.py similarity index 79% rename from Lib/test/final_b.py rename to Lib/test/test_module/final_b.py index 7228d82b880156..f3e8d5594904f2 100644 --- a/Lib/test/final_b.py +++ b/Lib/test/test_module/final_b.py @@ -3,7 +3,7 @@ """ import shutil -import test.final_a +import test.test_module.final_a x = 'b' @@ -11,7 +11,7 @@ class C: def __del__(self): # Inspect module globals and builtins print("x =", x) - print("final_a.x =", test.final_a.x) + print("final_a.x =", test.test_module.final_a.x) print("shutil.rmtree =", getattr(shutil.rmtree, '__name__', None)) print("len =", getattr(len, '__name__', None)) diff --git a/Lib/test/good_getattr.py b/Lib/test/test_module/good_getattr.py similarity index 100% rename from Lib/test/good_getattr.py rename to Lib/test/test_module/good_getattr.py diff --git a/Lib/test/test_monitoring.py b/Lib/test/test_monitoring.py index b36382c8d0982d..a64d1ed79decd8 100644 --- a/Lib/test/test_monitoring.py +++ b/Lib/test/test_monitoring.py @@ -501,6 +501,22 @@ def test_two_with_disable(self): self.assertEqual(sys.monitoring._all_events(), {}) sys.monitoring.restart_events() + def test_with_instruction_event(self): + """Test that the second tool can set events with instruction events set by the first tool.""" + def f(): + pass + code = f.__code__ + + try: + self.assertEqual(sys.monitoring._all_events(), {}) + sys.monitoring.set_local_events(TEST_TOOL, code, E.INSTRUCTION | E.LINE) + sys.monitoring.set_local_events(TEST_TOOL2, code, E.LINE) + finally: + sys.monitoring.set_events(TEST_TOOL, 0) + sys.monitoring.set_events(TEST_TOOL2, 0) + self.assertEqual(sys.monitoring._all_events(), {}) + + class LineMonitoringTest(MonitoringTestBase, unittest.TestCase): def test_lines_single(self): @@ -734,7 +750,7 @@ class UnwindRecorder(ExceptionRecorder): event_type = E.PY_UNWIND def __call__(self, code, offset, exc): - self.events.append(("unwind", type(exc))) + self.events.append(("unwind", type(exc), code.co_name)) class ExceptionHandledRecorder(ExceptionRecorder): @@ -743,8 +759,34 @@ class ExceptionHandledRecorder(ExceptionRecorder): def __call__(self, code, offset, exc): self.events.append(("handled", type(exc))) -class ExceptionMonitoringTest(CheckEvents): +class ThrowRecorder(ExceptionRecorder): + + event_type = E.PY_THROW + + def __call__(self, code, offset, exc): + self.events.append(("throw", type(exc))) + +class CallRecorder: + + event_type = E.CALL + + def __init__(self, events): + self.events = events + + def __call__(self, code, offset, func, arg): + self.events.append(("call", func.__name__, arg)) + +class ReturnRecorder: + + event_type = E.PY_RETURN + + def __init__(self, events): + self.events = events + + def __call__(self, code, offset, val): + self.events.append(("return", code.co_name, val)) +class ExceptionMonitoringTest(CheckEvents): exception_recorders = ( ExceptionRecorder, @@ -888,26 +930,73 @@ async def async_loop(): func, recorders = self.exception_recorders) -class LineRecorder: + def test_throw(self): - event_type = E.LINE + def gen(): + yield 1 + yield 2 + def func(): + try: + g = gen() + next(g) + g.throw(IndexError) + except IndexError: + pass - def __init__(self, events): - self.events = events + self.check_balanced( + func, + recorders = self.exception_recorders) - def __call__(self, code, line): - self.events.append(("line", code.co_name, line - code.co_firstlineno)) + events = self.get_events( + func, + TEST_TOOL, + self.exception_recorders + (ThrowRecorder,) + ) + self.assertEqual(events[0], ("throw", IndexError)) -class CallRecorder: + def test_no_unwind_for_shim_frame(self): + + class B: + def __init__(self): + raise ValueError() + + def f(): + try: + return B() + except ValueError: + pass + + for _ in range(100): + f() + recorders = ( + ReturnRecorder, + UnwindRecorder + ) + events = self.get_events(f, TEST_TOOL, recorders) + adaptive_insts = dis.get_instructions(f, adaptive=True) + self.assertIn( + "CALL_ALLOC_AND_ENTER_INIT", + [i.opname for i in adaptive_insts] + ) + #There should be only one unwind event + expected = [ + ('unwind', ValueError, '__init__'), + ('return', 'f', None), + ] + + self.assertEqual(events, expected) + +class LineRecorder: + + event_type = E.LINE - event_type = E.CALL def __init__(self, events): self.events = events - def __call__(self, code, offset, func, arg): - self.events.append(("call", func.__name__, arg)) + def __call__(self, code, line): + self.events.append(("line", code.co_name, line - code.co_firstlineno)) class CEventRecorder: @@ -1120,7 +1209,24 @@ def func1(): ('instruction', 'func1', 14), ('line', 'get_events', 11)]) -class TestInstallIncrementallly(MonitoringTestBase, unittest.TestCase): + def test_turn_off_only_instruction(self): + """ + LINE events should be recorded after INSTRUCTION event is turned off + """ + events = [] + def line(*args): + events.append("line") + sys.monitoring.set_events(TEST_TOOL, 0) + sys.monitoring.register_callback(TEST_TOOL, E.LINE, line) + sys.monitoring.register_callback(TEST_TOOL, E.INSTRUCTION, lambda *args: None) + sys.monitoring.set_events(TEST_TOOL, E.LINE | E.INSTRUCTION) + sys.monitoring.set_events(TEST_TOOL, E.LINE) + events = [] + a = 0 + sys.monitoring.set_events(TEST_TOOL, 0) + self.assertGreater(len(events), 0) + +class TestInstallIncrementally(MonitoringTestBase, unittest.TestCase): def check_events(self, func, must_include, tool=TEST_TOOL, recorders=(ExceptionRecorder,)): try: @@ -1149,19 +1255,19 @@ def func1(): MUST_INCLUDE_LI = [ ('instruction', 'func1', 2), - ('line', 'func1', 1), + ('line', 'func1', 2), ('instruction', 'func1', 4), ('instruction', 'func1', 6)] def test_line_then_instruction(self): recorders = [ LineRecorder, InstructionRecorder ] self.check_events(self.func1, - recorders = recorders, must_include = self.EXPECTED_LI) + recorders = recorders, must_include = self.MUST_INCLUDE_LI) def test_instruction_then_line(self): - recorders = [ InstructionRecorder, LineRecorderLowNoise ] + recorders = [ InstructionRecorder, LineRecorder ] self.check_events(self.func1, - recorders = recorders, must_include = self.EXPECTED_LI) + recorders = recorders, must_include = self.MUST_INCLUDE_LI) @staticmethod def func2(): @@ -1176,19 +1282,21 @@ def func2(): - def test_line_then_instruction(self): + def test_call_then_instruction(self): recorders = [ CallRecorder, InstructionRecorder ] self.check_events(self.func2, recorders = recorders, must_include = self.MUST_INCLUDE_CI) - def test_instruction_then_line(self): + def test_instruction_then_call(self): recorders = [ InstructionRecorder, CallRecorder ] self.check_events(self.func2, recorders = recorders, must_include = self.MUST_INCLUDE_CI) +LOCAL_RECORDERS = CallRecorder, LineRecorder, CReturnRecorder, CRaiseRecorder + class TestLocalEvents(MonitoringTestBase, unittest.TestCase): - def check_events(self, func, expected, tool=TEST_TOOL, recorders=(ExceptionRecorder,)): + def check_events(self, func, expected, tool=TEST_TOOL, recorders=()): try: self.assertEqual(sys.monitoring._all_events(), {}) event_list = [] @@ -1216,7 +1324,7 @@ def func1(): line2 = 2 line3 = 3 - self.check_events(func1, recorders = MANY_RECORDERS, expected = [ + self.check_events(func1, recorders = LOCAL_RECORDERS, expected = [ ('line', 'func1', 1), ('line', 'func1', 2), ('line', 'func1', 3)]) @@ -1228,7 +1336,7 @@ def func2(): [].append(2) line3 = 3 - self.check_events(func2, recorders = MANY_RECORDERS, expected = [ + self.check_events(func2, recorders = LOCAL_RECORDERS, expected = [ ('line', 'func2', 1), ('line', 'func2', 2), ('call', 'append', [2]), @@ -1245,15 +1353,17 @@ def func3(): line = 5 line = 6 - self.check_events(func3, recorders = MANY_RECORDERS, expected = [ + self.check_events(func3, recorders = LOCAL_RECORDERS, expected = [ ('line', 'func3', 1), ('line', 'func3', 2), ('line', 'func3', 3), - ('raise', KeyError), ('line', 'func3', 4), ('line', 'func3', 5), ('line', 'func3', 6)]) + def test_set_non_local_event(self): + with self.assertRaises(ValueError): + sys.monitoring.set_local_events(TEST_TOOL, just_call.__code__, E.RAISE) def line_from_offset(code, offset): for start, end, line in code.co_lines(): @@ -1282,15 +1392,6 @@ class BranchRecorder(JumpRecorder): event_type = E.BRANCH name = "branch" -class ReturnRecorder: - - event_type = E.PY_RETURN - - def __init__(self, events): - self.events = events - - def __call__(self, code, offset, val): - self.events.append(("return", val)) JUMP_AND_BRANCH_RECORDERS = JumpRecorder, BranchRecorder @@ -1309,6 +1410,7 @@ def func(): x = 4 else: x = 6 + 7 self.check_events(func, recorders = JUMP_AND_BRANCH_RECORDERS, expected = [ ('branch', 'func', 2, 2), @@ -1317,7 +1419,7 @@ def func(): ('branch', 'func', 2, 2), ('branch', 'func', 3, 4), ('jump', 'func', 4, 2), - ('branch', 'func', 2, 2)]) + ('branch', 'func', 2, 7)]) self.check_events(func, recorders = JUMP_BRANCH_AND_LINE_RECORDERS, expected = [ ('line', 'get_events', 10), @@ -1335,7 +1437,8 @@ def func(): ('line', 'func', 4), ('jump', 'func', 4, 2), ('line', 'func', 2), - ('branch', 'func', 2, 2), + ('branch', 'func', 2, 7), + ('line', 'func', 7), ('line', 'get_events', 11)]) def test_except_star(self): @@ -1364,8 +1467,8 @@ def func(): ('line', 'func', 5), ('line', 'meth', 1), ('jump', 'func', 5, 5), - ('jump', 'func', 5, '[offset=112]'), - ('branch', 'func', '[offset=118]', '[offset=120]'), + ('jump', 'func', 5, '[offset=114]'), + ('branch', 'func', '[offset=120]', '[offset=124]'), ('line', 'get_events', 11)]) self.check_events(func, recorders = FLOW_AND_LINE_RECORDERS, expected = [ @@ -1378,11 +1481,11 @@ def func(): ('branch', 'func', 4, 4), ('line', 'func', 5), ('line', 'meth', 1), - ('return', None), + ('return', 'meth', None), ('jump', 'func', 5, 5), - ('jump', 'func', 5, '[offset=112]'), - ('branch', 'func', '[offset=118]', '[offset=120]'), - ('return', None), + ('jump', 'func', 5, '[offset=114]'), + ('branch', 'func', '[offset=120]', '[offset=124]'), + ('return', 'func', None), ('line', 'get_events', 11)]) class TestLoadSuperAttr(CheckEvents): @@ -1666,3 +1769,81 @@ def run(): self.assertEqual(caught, "inner") finally: sys.monitoring.set_events(TEST_TOOL, 0) + + def test_108390(self): + + class Foo: + def __init__(self, set_event): + if set_event: + sys.monitoring.set_events(TEST_TOOL, E.PY_RESUME) + + def make_foo_optimized_then_set_event(): + for i in range(100): + Foo(i == 99) + + try: + make_foo_optimized_then_set_event() + finally: + sys.monitoring.set_events(TEST_TOOL, 0) + + def test_gh108976(self): + sys.monitoring.use_tool_id(0, "test") + self.addCleanup(sys.monitoring.free_tool_id, 0) + sys.monitoring.set_events(0, 0) + sys.monitoring.register_callback(0, E.LINE, lambda *args: sys.monitoring.set_events(0, 0)) + sys.monitoring.register_callback(0, E.INSTRUCTION, lambda *args: 0) + sys.monitoring.set_events(0, E.LINE | E.INSTRUCTION) + sys.monitoring.set_events(0, 0) + + +class TestOptimizer(MonitoringTestBase, unittest.TestCase): + + def setUp(self): + import _testinternalcapi + self.old_opt = _testinternalcapi.get_optimizer() + opt = _testinternalcapi.get_counter_optimizer() + _testinternalcapi.set_optimizer(opt) + super(TestOptimizer, self).setUp() + + def tearDown(self): + import _testinternalcapi + super(TestOptimizer, self).tearDown() + _testinternalcapi.set_optimizer(self.old_opt) + + def test_for_loop(self): + def test_func(x): + i = 0 + while i < x: + i += 1 + + code = test_func.__code__ + sys.monitoring.set_local_events(TEST_TOOL, code, E.PY_START) + self.assertEqual(sys.monitoring.get_local_events(TEST_TOOL, code), E.PY_START) + test_func(1000) + sys.monitoring.set_local_events(TEST_TOOL, code, 0) + self.assertEqual(sys.monitoring.get_local_events(TEST_TOOL, code), 0) + +class TestTier2Optimizer(CheckEvents): + + def test_monitoring_already_opimized_loop(self): + def test_func(recorder): + set_events = sys.monitoring.set_events + line = E.LINE + i = 0 + for i in range(551): + # Turn on events without branching once i reaches 500. + set_events(TEST_TOOL, line * int(i >= 500)) + pass + pass + pass + + self.assertEqual(sys.monitoring._all_events(), {}) + events = [] + recorder = LineRecorder(events) + sys.monitoring.register_callback(TEST_TOOL, E.LINE, recorder) + try: + test_func(recorder) + finally: + sys.monitoring.register_callback(TEST_TOOL, E.LINE, None) + sys.monitoring.set_events(TEST_TOOL, 0) + self.assertGreater(len(events), 250) diff --git a/Lib/test/test_msvcrt.py b/Lib/test/test_msvcrt.py new file mode 100644 index 00000000000000..600c4446fd5cd4 --- /dev/null +++ b/Lib/test/test_msvcrt.py @@ -0,0 +1,120 @@ +import os +import subprocess +import sys +import unittest +from textwrap import dedent + +from test.support import os_helper, requires_resource +from test.support.os_helper import TESTFN, TESTFN_ASCII + +if sys.platform != "win32": + raise unittest.SkipTest("windows related tests") + +import _winapi +import msvcrt + + +class TestFileOperations(unittest.TestCase): + def test_locking(self): + with open(TESTFN, "w") as f: + self.addCleanup(os_helper.unlink, TESTFN) + + msvcrt.locking(f.fileno(), msvcrt.LK_LOCK, 1) + self.assertRaises(OSError, msvcrt.locking, f.fileno(), msvcrt.LK_NBLCK, 1) + + def test_unlockfile(self): + with open(TESTFN, "w") as f: + self.addCleanup(os_helper.unlink, TESTFN) + + msvcrt.locking(f.fileno(), msvcrt.LK_LOCK, 1) + msvcrt.locking(f.fileno(), msvcrt.LK_UNLCK, 1) + msvcrt.locking(f.fileno(), msvcrt.LK_LOCK, 1) + + def test_setmode(self): + with open(TESTFN, "w") as f: + self.addCleanup(os_helper.unlink, TESTFN) + + msvcrt.setmode(f.fileno(), os.O_BINARY) + msvcrt.setmode(f.fileno(), os.O_TEXT) + + def test_open_osfhandle(self): + h = _winapi.CreateFile(TESTFN_ASCII, _winapi.GENERIC_WRITE, 0, 0, 1, 128, 0) + self.addCleanup(os_helper.unlink, TESTFN_ASCII) + + try: + fd = msvcrt.open_osfhandle(h, os.O_RDONLY) + h = None + os.close(fd) + finally: + if h: + _winapi.CloseHandle(h) + + def test_get_osfhandle(self): + with open(TESTFN, "w") as f: + self.addCleanup(os_helper.unlink, TESTFN) + + msvcrt.get_osfhandle(f.fileno()) + + +c = '\u5b57' # unicode CJK char (meaning 'character') for 'wide-char' tests +c_encoded = b'\x57\x5b' # utf-16-le (which windows internally used) encoded char for this CJK char + + +class TestConsoleIO(unittest.TestCase): + # CREATE_NEW_CONSOLE creates a "popup" window. + @requires_resource('gui') + def run_in_separated_process(self, code): + # Run test in a seprated process to avoid stdin conflicts. + # See: gh-110147 + cmd = [sys.executable, '-c', code] + subprocess.run(cmd, check=True, capture_output=True, + creationflags=subprocess.CREATE_NEW_CONSOLE) + + def test_kbhit(self): + code = dedent(''' + import msvcrt + assert msvcrt.kbhit() == 0 + ''') + self.run_in_separated_process(code) + + def test_getch(self): + msvcrt.ungetch(b'c') + self.assertEqual(msvcrt.getch(), b'c') + + def check_getwch(self, funcname): + code = dedent(f''' + import msvcrt + from _testconsole import write_input + with open("CONIN$", "rb", buffering=0) as stdin: + write_input(stdin, {ascii(c_encoded)}) + assert msvcrt.{funcname}() == "{c}" + ''') + self.run_in_separated_process(code) + + def test_getwch(self): + self.check_getwch('getwch') + + def test_getche(self): + msvcrt.ungetch(b'c') + self.assertEqual(msvcrt.getche(), b'c') + + def test_getwche(self): + self.check_getwch('getwche') + + def test_putch(self): + msvcrt.putch(b'c') + + def test_putwch(self): + msvcrt.putwch(c) + + +class TestOther(unittest.TestCase): + def test_heap_min(self): + try: + msvcrt.heapmin() + except OSError: + pass + + +if __name__ == "__main__": + unittest.main() diff --git a/Lib/test/test_multibytecodec.py b/Lib/test/test_multibytecodec.py index cf8bb5e3a0520d..6451df14696933 100644 --- a/Lib/test/test_multibytecodec.py +++ b/Lib/test/test_multibytecodec.py @@ -363,6 +363,7 @@ def test_iso2022_jp_g0(self): e = '\u3406'.encode(encoding) self.assertFalse(any(x > 0x80 for x in e)) + @support.requires_resource('cpu') def test_bug1572832(self): for x in range(0x10000, 0x110000): # Any ISO 2022 codec will cause the segfault diff --git a/Lib/test/test_multiprocessing_fork.py b/Lib/test/test_multiprocessing_fork.py deleted file mode 100644 index 5000edb7c5c299..00000000000000 --- a/Lib/test/test_multiprocessing_fork.py +++ /dev/null @@ -1,19 +0,0 @@ -import unittest -import test._test_multiprocessing - -import sys -from test import support - -if support.PGO: - raise unittest.SkipTest("test is not helpful for PGO") - -if sys.platform == "win32": - raise unittest.SkipTest("fork is not available on Windows") - -if sys.platform == 'darwin': - raise unittest.SkipTest("test may crash on macOS (bpo-33725)") - -test._test_multiprocessing.install_tests_in_module_dict(globals(), 'fork') - -if __name__ == '__main__': - unittest.main() diff --git a/Lib/test/test_multiprocessing_fork/__init__.py b/Lib/test/test_multiprocessing_fork/__init__.py new file mode 100644 index 00000000000000..aa1fff50b28f5f --- /dev/null +++ b/Lib/test/test_multiprocessing_fork/__init__.py @@ -0,0 +1,16 @@ +import os.path +import sys +import unittest +from test import support + +if support.PGO: + raise unittest.SkipTest("test is not helpful for PGO") + +if sys.platform == "win32": + raise unittest.SkipTest("fork is not available on Windows") + +if sys.platform == 'darwin': + raise unittest.SkipTest("test may crash on macOS (bpo-33725)") + +def load_tests(*args): + return support.load_package_tests(os.path.dirname(__file__), *args) diff --git a/Lib/test/test_multiprocessing_fork/test_manager.py b/Lib/test/test_multiprocessing_fork/test_manager.py new file mode 100644 index 00000000000000..9efbb83bbb73bf --- /dev/null +++ b/Lib/test/test_multiprocessing_fork/test_manager.py @@ -0,0 +1,7 @@ +import unittest +from test._test_multiprocessing import install_tests_in_module_dict + +install_tests_in_module_dict(globals(), 'fork', only_type="manager") + +if __name__ == '__main__': + unittest.main() diff --git a/Lib/test/test_multiprocessing_fork/test_misc.py b/Lib/test/test_multiprocessing_fork/test_misc.py new file mode 100644 index 00000000000000..891a494020c3a1 --- /dev/null +++ b/Lib/test/test_multiprocessing_fork/test_misc.py @@ -0,0 +1,7 @@ +import unittest +from test._test_multiprocessing import install_tests_in_module_dict + +install_tests_in_module_dict(globals(), 'fork', exclude_types=True) + +if __name__ == '__main__': + unittest.main() diff --git a/Lib/test/test_multiprocessing_fork/test_processes.py b/Lib/test/test_multiprocessing_fork/test_processes.py new file mode 100644 index 00000000000000..e64e9afc0100e8 --- /dev/null +++ b/Lib/test/test_multiprocessing_fork/test_processes.py @@ -0,0 +1,7 @@ +import unittest +from test._test_multiprocessing import install_tests_in_module_dict + +install_tests_in_module_dict(globals(), 'fork', only_type="processes") + +if __name__ == '__main__': + unittest.main() diff --git a/Lib/test/test_multiprocessing_fork/test_threads.py b/Lib/test/test_multiprocessing_fork/test_threads.py new file mode 100644 index 00000000000000..1670e34cb17f25 --- /dev/null +++ b/Lib/test/test_multiprocessing_fork/test_threads.py @@ -0,0 +1,7 @@ +import unittest +from test._test_multiprocessing import install_tests_in_module_dict + +install_tests_in_module_dict(globals(), 'fork', only_type="threads") + +if __name__ == '__main__': + unittest.main() diff --git a/Lib/test/test_multiprocessing_forkserver.py b/Lib/test/test_multiprocessing_forkserver.py deleted file mode 100644 index 6ad5faf9e8a329..00000000000000 --- a/Lib/test/test_multiprocessing_forkserver.py +++ /dev/null @@ -1,16 +0,0 @@ -import unittest -import test._test_multiprocessing - -import sys -from test import support - -if support.PGO: - raise unittest.SkipTest("test is not helpful for PGO") - -if sys.platform == "win32": - raise unittest.SkipTest("forkserver is not available on Windows") - -test._test_multiprocessing.install_tests_in_module_dict(globals(), 'forkserver') - -if __name__ == '__main__': - unittest.main() diff --git a/Lib/test/test_multiprocessing_forkserver/__init__.py b/Lib/test/test_multiprocessing_forkserver/__init__.py new file mode 100644 index 00000000000000..d91715a344dfa7 --- /dev/null +++ b/Lib/test/test_multiprocessing_forkserver/__init__.py @@ -0,0 +1,13 @@ +import os.path +import sys +import unittest +from test import support + +if support.PGO: + raise unittest.SkipTest("test is not helpful for PGO") + +if sys.platform == "win32": + raise unittest.SkipTest("forkserver is not available on Windows") + +def load_tests(*args): + return support.load_package_tests(os.path.dirname(__file__), *args) diff --git a/Lib/test/test_multiprocessing_forkserver/test_manager.py b/Lib/test/test_multiprocessing_forkserver/test_manager.py new file mode 100644 index 00000000000000..14f8f10dfb4e2f --- /dev/null +++ b/Lib/test/test_multiprocessing_forkserver/test_manager.py @@ -0,0 +1,7 @@ +import unittest +from test._test_multiprocessing import install_tests_in_module_dict + +install_tests_in_module_dict(globals(), 'forkserver', only_type="manager") + +if __name__ == '__main__': + unittest.main() diff --git a/Lib/test/test_multiprocessing_forkserver/test_misc.py b/Lib/test/test_multiprocessing_forkserver/test_misc.py new file mode 100644 index 00000000000000..9cae1b50f71e00 --- /dev/null +++ b/Lib/test/test_multiprocessing_forkserver/test_misc.py @@ -0,0 +1,7 @@ +import unittest +from test._test_multiprocessing import install_tests_in_module_dict + +install_tests_in_module_dict(globals(), 'forkserver', exclude_types=True) + +if __name__ == '__main__': + unittest.main() diff --git a/Lib/test/test_multiprocessing_forkserver/test_processes.py b/Lib/test/test_multiprocessing_forkserver/test_processes.py new file mode 100644 index 00000000000000..360967cf1ae152 --- /dev/null +++ b/Lib/test/test_multiprocessing_forkserver/test_processes.py @@ -0,0 +1,7 @@ +import unittest +from test._test_multiprocessing import install_tests_in_module_dict + +install_tests_in_module_dict(globals(), 'forkserver', only_type="processes") + +if __name__ == '__main__': + unittest.main() diff --git a/Lib/test/test_multiprocessing_forkserver/test_threads.py b/Lib/test/test_multiprocessing_forkserver/test_threads.py new file mode 100644 index 00000000000000..719c752aa05350 --- /dev/null +++ b/Lib/test/test_multiprocessing_forkserver/test_threads.py @@ -0,0 +1,7 @@ +import unittest +from test._test_multiprocessing import install_tests_in_module_dict + +install_tests_in_module_dict(globals(), 'forkserver', only_type="threads") + +if __name__ == '__main__': + unittest.main() diff --git a/Lib/test/test_multiprocessing_spawn.py b/Lib/test/test_multiprocessing_spawn.py deleted file mode 100644 index 6558952308f25c..00000000000000 --- a/Lib/test/test_multiprocessing_spawn.py +++ /dev/null @@ -1,12 +0,0 @@ -import unittest -import test._test_multiprocessing - -from test import support - -if support.PGO: - raise unittest.SkipTest("test is not helpful for PGO") - -test._test_multiprocessing.install_tests_in_module_dict(globals(), 'spawn') - -if __name__ == '__main__': - unittest.main() diff --git a/Lib/test/test_multiprocessing_spawn/__init__.py b/Lib/test/test_multiprocessing_spawn/__init__.py new file mode 100644 index 00000000000000..3fd0f9b390612a --- /dev/null +++ b/Lib/test/test_multiprocessing_spawn/__init__.py @@ -0,0 +1,9 @@ +import os.path +import unittest +from test import support + +if support.PGO: + raise unittest.SkipTest("test is not helpful for PGO") + +def load_tests(*args): + return support.load_package_tests(os.path.dirname(__file__), *args) diff --git a/Lib/test/test_multiprocessing_spawn/test_manager.py b/Lib/test/test_multiprocessing_spawn/test_manager.py new file mode 100644 index 00000000000000..b40bea0bf61581 --- /dev/null +++ b/Lib/test/test_multiprocessing_spawn/test_manager.py @@ -0,0 +1,7 @@ +import unittest +from test._test_multiprocessing import install_tests_in_module_dict + +install_tests_in_module_dict(globals(), 'spawn', only_type="manager") + +if __name__ == '__main__': + unittest.main() diff --git a/Lib/test/test_multiprocessing_spawn/test_misc.py b/Lib/test/test_multiprocessing_spawn/test_misc.py new file mode 100644 index 00000000000000..32f37c5cc81ee1 --- /dev/null +++ b/Lib/test/test_multiprocessing_spawn/test_misc.py @@ -0,0 +1,7 @@ +import unittest +from test._test_multiprocessing import install_tests_in_module_dict + +install_tests_in_module_dict(globals(), 'spawn', exclude_types=True) + +if __name__ == '__main__': + unittest.main() diff --git a/Lib/test/test_multiprocessing_spawn/test_processes.py b/Lib/test/test_multiprocessing_spawn/test_processes.py new file mode 100644 index 00000000000000..af764b0d8483ab --- /dev/null +++ b/Lib/test/test_multiprocessing_spawn/test_processes.py @@ -0,0 +1,7 @@ +import unittest +from test._test_multiprocessing import install_tests_in_module_dict + +install_tests_in_module_dict(globals(), 'spawn', only_type="processes") + +if __name__ == '__main__': + unittest.main() diff --git a/Lib/test/test_multiprocessing_spawn/test_threads.py b/Lib/test/test_multiprocessing_spawn/test_threads.py new file mode 100644 index 00000000000000..c1257749b9c419 --- /dev/null +++ b/Lib/test/test_multiprocessing_spawn/test_threads.py @@ -0,0 +1,7 @@ +import unittest +from test._test_multiprocessing import install_tests_in_module_dict + +install_tests_in_module_dict(globals(), 'spawn', only_type="threads") + +if __name__ == '__main__': + unittest.main() diff --git a/Lib/test/test_netrc.py b/Lib/test/test_netrc.py index 573d636de956d1..81e11a293cc4c8 100644 --- a/Lib/test/test_netrc.py +++ b/Lib/test/test_netrc.py @@ -1,5 +1,5 @@ import netrc, os, unittest, sys, textwrap -from test.support import os_helper, run_unittest +from test.support import os_helper try: import pwd @@ -308,8 +308,6 @@ def test_security(self): self.assertEqual(nrc.hosts['foo.domain.com'], ('anonymous', '', 'pass')) -def test_main(): - run_unittest(NetrcTestCase) if __name__ == "__main__": - test_main() + unittest.main() diff --git a/Lib/test/test_ntpath.py b/Lib/test/test_ntpath.py index 538d758624c9d6..bf990ed36fbcae 100644 --- a/Lib/test/test_ntpath.py +++ b/Lib/test/test_ntpath.py @@ -2,6 +2,7 @@ import ntpath import os import string +import subprocess import sys import unittest import warnings @@ -255,6 +256,7 @@ def test_join(self): tester('ntpath.join("a", "b", "c")', 'a\\b\\c') tester('ntpath.join("a\\", "b", "c")', 'a\\b\\c') tester('ntpath.join("a", "b\\", "c")', 'a\\b\\c') + tester('ntpath.join("a", "b", "c\\")', 'a\\b\\c\\') tester('ntpath.join("a", "b", "\\c")', '\\c') tester('ntpath.join("d:\\", "\\pleep")', 'd:\\pleep') tester('ntpath.join("d:\\", "a", "b")', 'd:\\a\\b') @@ -312,6 +314,16 @@ def test_join(self): tester("ntpath.join('\\\\computer\\', 'share')", '\\\\computer\\share') tester("ntpath.join('\\\\computer\\share\\', 'a')", '\\\\computer\\share\\a') tester("ntpath.join('\\\\computer\\share\\a\\', 'b')", '\\\\computer\\share\\a\\b') + # Second part is anchored, so that the first part is ignored. + tester("ntpath.join('a', 'Z:b', 'c')", 'Z:b\\c') + tester("ntpath.join('a', 'Z:\\b', 'c')", 'Z:\\b\\c') + tester("ntpath.join('a', '\\\\b\\c', 'd')", '\\\\b\\c\\d') + # Second part has a root but not drive. + tester("ntpath.join('a', '\\b', 'c')", '\\b\\c') + tester("ntpath.join('Z:/a', '/b', 'c')", 'Z:\\b\\c') + tester("ntpath.join('//?/Z:/a', '/b', 'c')", '\\\\?\\Z:\\b\\c') + tester("ntpath.join('D:a', './c:b')", 'D:a\\.\\c:b') + tester("ntpath.join('D:/a', './c:b')", 'D:\\a\\.\\c:b') def test_normpath(self): tester("ntpath.normpath('A//////././//.//B')", r'A\B') @@ -394,6 +406,10 @@ def test_realpath_basic(self): d = drives.pop().encode() self.assertEqual(ntpath.realpath(d), d) + # gh-106242: Embedded nulls and non-strict fallback to abspath + self.assertEqual(ABSTFN + "\0spam", + ntpath.realpath(os_helper.TESTFN + "\0spam", strict=False)) + @os_helper.skip_unless_symlink @unittest.skipUnless(HAVE_GETFINALPATHNAME, 'need _getfinalpathname') def test_realpath_strict(self): @@ -404,6 +420,8 @@ def test_realpath_strict(self): self.addCleanup(os_helper.unlink, ABSTFN) self.assertRaises(FileNotFoundError, ntpath.realpath, ABSTFN, strict=True) self.assertRaises(FileNotFoundError, ntpath.realpath, ABSTFN + "2", strict=True) + # gh-106242: Embedded nulls should raise OSError (not ValueError) + self.assertRaises(OSError, ntpath.realpath, ABSTFN + "\0spam", strict=True) @os_helper.skip_unless_symlink @unittest.skipUnless(HAVE_GETFINALPATHNAME, 'need _getfinalpathname') @@ -631,6 +649,48 @@ def test_realpath_cwd(self): with os_helper.change_cwd(test_dir_short): self.assertPathEqual(test_file_long, ntpath.realpath("file.txt")) + @unittest.skipUnless(HAVE_GETFINALPATHNAME, 'need _getfinalpathname') + def test_realpath_permission(self): + # Test whether python can resolve the real filename of a + # shortened file name even if it does not have permission to access it. + ABSTFN = ntpath.realpath(os_helper.TESTFN) + + os_helper.unlink(ABSTFN) + os_helper.rmtree(ABSTFN) + os.mkdir(ABSTFN) + self.addCleanup(os_helper.rmtree, ABSTFN) + + test_file = ntpath.join(ABSTFN, "LongFileName123.txt") + test_file_short = ntpath.join(ABSTFN, "LONGFI~1.TXT") + + with open(test_file, "wb") as f: + f.write(b"content") + # Automatic generation of short names may be disabled on + # NTFS volumes for the sake of performance. + # They're not supported at all on ReFS and exFAT. + subprocess.run( + # Try to set the short name manually. + ['fsutil.exe', 'file', 'setShortName', test_file, 'LONGFI~1.TXT'], + creationflags=subprocess.DETACHED_PROCESS + ) + + try: + self.assertPathEqual(test_file, ntpath.realpath(test_file_short)) + except AssertionError: + raise unittest.SkipTest('the filesystem seems to lack support for short filenames') + + # Deny the right to [S]YNCHRONIZE on the file to + # force nt._getfinalpathname to fail with ERROR_ACCESS_DENIED. + p = subprocess.run( + ['icacls.exe', test_file, '/deny', '*S-1-5-32-545:(S)'], + creationflags=subprocess.DETACHED_PROCESS + ) + + if p.returncode: + raise unittest.SkipTest('failed to deny access to the test file') + + self.assertPathEqual(test_file, ntpath.realpath(test_file_short)) + def test_expandvars(self): with os_helper.EnvironmentVarGuard() as env: env.clear() @@ -1036,6 +1096,7 @@ def test_path_normcase(self): self._check_function(self.path.normcase) if sys.platform == 'win32': self.assertEqual(ntpath.normcase('\u03a9\u2126'), 'ωΩ') + self.assertEqual(ntpath.normcase('abc\x00def'), 'abc\x00def') def test_path_isabs(self): self._check_function(self.path.isabs) diff --git a/Lib/test/test_opcache.py b/Lib/test/test_opcache.py index 564dc4745ae64e..2b2783d57be8f4 100644 --- a/Lib/test/test_opcache.py +++ b/Lib/test/test_opcache.py @@ -1,8 +1,28 @@ +import copy +import pickle import dis import threading import types import unittest -from test.support import threading_helper +from test.support import threading_helper, check_impl_detail + +# Skip this module on other interpreters, it is cpython specific: +if check_impl_detail(cpython=False): + raise unittest.SkipTest('implementation detail specific to cpython') + +import _testinternalcapi + + +def disabling_optimizer(func): + def wrapper(*args, **kwargs): + old_opt = _testinternalcapi.get_optimizer() + _testinternalcapi.set_optimizer(None) + try: + return func(*args, **kwargs) + finally: + _testinternalcapi.set_optimizer(old_opt) + + return wrapper class TestLoadSuperAttrCache(unittest.TestCase): @@ -499,6 +519,7 @@ def assert_specialized(self, f, opname): opnames = {instruction.opname for instruction in instructions} self.assertIn(opname, opnames) + @disabling_optimizer def assert_races_do_not_crash( self, opname, get_items, read, write, *, check_items=False ): @@ -865,8 +886,10 @@ class C: items = [] for _ in range(self.ITEMS): item = C() - item.__dict__ item.a = None + # Resize into a combined unicode dict: + for i in range(29): + setattr(item, f"_{i}", None) items.append(item) return items @@ -932,7 +955,9 @@ class C: items = [] for _ in range(self.ITEMS): item = C() - item.__dict__ + # Resize into a combined unicode dict: + for i in range(29): + setattr(item, f"_{i}", None) items.append(item) return items @@ -993,6 +1018,124 @@ def write(items): opname = "UNPACK_SEQUENCE_LIST" self.assert_races_do_not_crash(opname, get_items, read, write) +class C: + pass + +class TestInstanceDict(unittest.TestCase): + + def setUp(self): + c = C() + c.a, c.b, c.c = 0,0,0 + + def test_values_on_instance(self): + c = C() + c.a = 1 + C().b = 2 + c.c = 3 + self.assertEqual( + _testinternalcapi.get_object_dict_values(c), + (1, '', 3) + ) + + def test_dict_materialization(self): + c = C() + c.a = 1 + c.b = 2 + c.__dict__ + self.assertIs( + _testinternalcapi.get_object_dict_values(c), + None + ) + + def test_dict_dematerialization(self): + c = C() + c.a = 1 + c.b = 2 + c.__dict__ + self.assertIs( + _testinternalcapi.get_object_dict_values(c), + None + ) + for _ in range(100): + c.a + self.assertEqual( + _testinternalcapi.get_object_dict_values(c), + (1, 2, '') + ) + + def test_dict_dematerialization_multiple_refs(self): + c = C() + c.a = 1 + c.b = 2 + d = c.__dict__ + for _ in range(100): + c.a + self.assertIs( + _testinternalcapi.get_object_dict_values(c), + None + ) + self.assertIs(c.__dict__, d) + + def test_dict_dematerialization_copy(self): + c = C() + c.a = 1 + c.b = 2 + c2 = copy.copy(c) + for _ in range(100): + c.a + c2.a + self.assertEqual( + _testinternalcapi.get_object_dict_values(c), + (1, 2, '') + ) + self.assertEqual( + _testinternalcapi.get_object_dict_values(c2), + (1, 2, '') + ) + c3 = copy.deepcopy(c) + for _ in range(100): + c.a + c3.a + self.assertEqual( + _testinternalcapi.get_object_dict_values(c), + (1, 2, '') + ) + #NOTE -- c3.__dict__ does not de-materialize + + def test_dict_dematerialization_pickle(self): + c = C() + c.a = 1 + c.b = 2 + c2 = pickle.loads(pickle.dumps(c)) + for _ in range(100): + c.a + c2.a + self.assertEqual( + _testinternalcapi.get_object_dict_values(c), + (1, 2, '') + ) + self.assertEqual( + _testinternalcapi.get_object_dict_values(c2), + (1, 2, '') + ) + + def test_dict_dematerialization_subclass(self): + class D(dict): pass + c = C() + c.a = 1 + c.b = 2 + c.__dict__ = D(c.__dict__) + for _ in range(100): + c.a + self.assertIs( + _testinternalcapi.get_object_dict_values(c), + None + ) + self.assertEqual( + c.__dict__, + {'a':1, 'b':2} + ) + if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_opcodes.py b/Lib/test/test_opcodes.py index e880c3f1ac875e..72488b2bb6b4ff 100644 --- a/Lib/test/test_opcodes.py +++ b/Lib/test/test_opcodes.py @@ -1,7 +1,8 @@ # Python test set -- part 2, opcodes import unittest -from test import ann_module, support +from test import support +from test.typinganndata import ann_module class OpcodeTest(unittest.TestCase): diff --git a/Lib/test/test_ordered_dict.py b/Lib/test/test_ordered_dict.py index decbcc2419c9fc..4571b23dfe7c1a 100644 --- a/Lib/test/test_ordered_dict.py +++ b/Lib/test/test_ordered_dict.py @@ -122,6 +122,17 @@ def items(self): self.OrderedDict(Spam()) self.assertEqual(calls, ['keys']) + def test_overridden_init(self): + # Sync-up pure Python OD class with C class where + # a consistent internal state is created in __new__ + # rather than __init__. + OrderedDict = self.OrderedDict + class ODNI(OrderedDict): + def __init__(*args, **kwargs): + pass + od = ODNI() + od['a'] = 1 # This used to fail because __init__ was bypassed + def test_fromkeys(self): OrderedDict = self.OrderedDict od = OrderedDict.fromkeys('abc') diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py index 99e9ed213e5615..bff6e604cccdd6 100644 --- a/Lib/test/test_os.py +++ b/Lib/test/test_os.py @@ -14,6 +14,7 @@ import os import pickle import select +import selectors import shutil import signal import socket @@ -737,7 +738,7 @@ def test_access_denied(self): # denied. See issue 28075. # os.environ['TEMP'] should be located on a volume that # supports file ACLs. - fname = os.path.join(os.environ['TEMP'], self.fname) + fname = os.path.join(os.environ['TEMP'], self.fname + "_access") self.addCleanup(os_helper.unlink, fname) create_file(fname, b'ABC') # Deny the right to [S]YNCHRONIZE on the file to @@ -913,6 +914,13 @@ def set_time(filename): os.utime(self.fname, None) self._test_utime_current(set_time) + def test_utime_nonexistent(self): + now = time.time() + filename = 'nonexistent' + with self.assertRaises(FileNotFoundError) as cm: + os.utime(filename, (now, now)) + self.assertEqual(cm.exception.filename, filename) + def get_file_system(self, path): if sys.platform == 'win32': root = os.path.splitdrive(os.path.abspath(path))[0] + '\\' @@ -1142,9 +1150,12 @@ def test_putenv_unsetenv(self): def test_putenv_unsetenv_error(self): # Empty variable name is invalid. # "=" and null character are not allowed in a variable name. - for name in ('', '=name', 'na=me', 'name=', 'name\0', 'na\0me'): + for name in ('', '=name', 'na=me', 'name='): self.assertRaises((OSError, ValueError), os.putenv, name, "value") self.assertRaises((OSError, ValueError), os.unsetenv, name) + for name in ('name\0', 'na\0me'): + self.assertRaises(ValueError, os.putenv, name, "value") + self.assertRaises(ValueError, os.unsetenv, name) if sys.platform == "win32": # On Windows, an environment variable string ("name=value" string) @@ -1732,7 +1743,7 @@ def tearDown(self): os.removedirs(path) -@os_helper.skip_unless_working_chmod +@unittest.skipUnless(hasattr(os, "chown"), "requires os.chown()") class ChownFileTests(unittest.TestCase): @classmethod @@ -2559,30 +2570,34 @@ def _kill_with_event(self, event, name): tagname = "test_os_%s" % uuid.uuid1() m = mmap.mmap(-1, 1, tagname) m[0] = 0 + # Run a script which has console control handling enabled. - proc = subprocess.Popen([sys.executable, - os.path.join(os.path.dirname(__file__), - "win_console_handler.py"), tagname], - creationflags=subprocess.CREATE_NEW_PROCESS_GROUP) - # Let the interpreter startup before we send signals. See #3137. - count, max = 0, 100 - while count < max and proc.poll() is None: - if m[0] == 1: - break - time.sleep(0.1) - count += 1 - else: - # Forcefully kill the process if we weren't able to signal it. - os.kill(proc.pid, signal.SIGINT) - self.fail("Subprocess didn't finish initialization") - os.kill(proc.pid, event) - # proc.send_signal(event) could also be done here. - # Allow time for the signal to be passed and the process to exit. - time.sleep(0.5) - if not proc.poll(): - # Forcefully kill the process if we weren't able to signal it. - os.kill(proc.pid, signal.SIGINT) - self.fail("subprocess did not stop on {}".format(name)) + script = os.path.join(os.path.dirname(__file__), + "win_console_handler.py") + cmd = [sys.executable, script, tagname] + proc = subprocess.Popen(cmd, + creationflags=subprocess.CREATE_NEW_PROCESS_GROUP) + + with proc: + # Let the interpreter startup before we send signals. See #3137. + for _ in support.sleeping_retry(support.SHORT_TIMEOUT): + if proc.poll() is None: + break + else: + # Forcefully kill the process if we weren't able to signal it. + proc.kill() + self.fail("Subprocess didn't finish initialization") + + os.kill(proc.pid, event) + + try: + # proc.send_signal(event) could also be done here. + # Allow time for the signal to be passed and the process to exit. + proc.wait(timeout=support.SHORT_TIMEOUT) + except subprocess.TimeoutExpired: + # Forcefully kill the process if we weren't able to signal it. + proc.kill() + self.fail("subprocess did not stop on {}".format(name)) @unittest.skip("subprocesses aren't inheriting Ctrl+C property") @support.requires_subprocess() @@ -3915,6 +3930,328 @@ def test_eventfd_select(self): self.assertEqual((rfd, wfd, xfd), ([fd], [], [])) os.eventfd_read(fd) +@unittest.skipUnless(hasattr(os, 'timerfd_create'), 'requires os.timerfd_create') +@support.requires_linux_version(2, 6, 30) +class TimerfdTests(unittest.TestCase): + # Tolerate a difference of 1 ms + CLOCK_RES_NS = 1_000_000 + CLOCK_RES = CLOCK_RES_NS * 1e-9 + + def timerfd_create(self, *args, **kwargs): + fd = os.timerfd_create(*args, **kwargs) + self.assertGreaterEqual(fd, 0) + self.assertFalse(os.get_inheritable(fd)) + self.addCleanup(os.close, fd) + return fd + + def read_count_signaled(self, fd): + # read 8 bytes + data = os.read(fd, 8) + return int.from_bytes(data, byteorder=sys.byteorder) + + def test_timerfd_initval(self): + fd = self.timerfd_create(time.CLOCK_REALTIME) + + initial_expiration = 0.25 + interval = 0.125 + + # 1st call + next_expiration, interval2 = os.timerfd_settime(fd, initial=initial_expiration, interval=interval) + self.assertAlmostEqual(interval2, 0.0, places=3) + self.assertAlmostEqual(next_expiration, 0.0, places=3) + + # 2nd call + next_expiration, interval2 = os.timerfd_settime(fd, initial=initial_expiration, interval=interval) + self.assertAlmostEqual(interval2, interval, places=3) + self.assertAlmostEqual(next_expiration, initial_expiration, places=3) + + # timerfd_gettime + next_expiration, interval2 = os.timerfd_gettime(fd) + self.assertAlmostEqual(interval2, interval, places=3) + self.assertAlmostEqual(next_expiration, initial_expiration, places=3) + + def test_timerfd_non_blocking(self): + fd = self.timerfd_create(time.CLOCK_REALTIME, flags=os.TFD_NONBLOCK) + + # 0.1 second later + initial_expiration = 0.1 + os.timerfd_settime(fd, initial=initial_expiration, interval=0) + + # read() raises OSError with errno is EAGAIN for non-blocking timer. + with self.assertRaises(OSError) as ctx: + self.read_count_signaled(fd) + self.assertEqual(ctx.exception.errno, errno.EAGAIN) + + # Wait more than 0.1 seconds + time.sleep(initial_expiration + 0.1) + + # confirm if timerfd is readable and read() returns 1 as bytes. + self.assertEqual(self.read_count_signaled(fd), 1) + + def test_timerfd_negative(self): + one_sec_in_nsec = 10**9 + fd = self.timerfd_create(time.CLOCK_REALTIME) + + test_flags = [0, os.TFD_TIMER_ABSTIME] + if hasattr(os, 'TFD_TIMER_CANCEL_ON_SET'): + test_flags.append(os.TFD_TIMER_ABSTIME | os.TFD_TIMER_CANCEL_ON_SET) + + # Any of 'initial' and 'interval' is negative value. + for initial, interval in ( (-1, 0), (1, -1), (-1, -1), (-0.1, 0), (1, -0.1), (-0.1, -0.1)): + for flags in test_flags: + with self.subTest(flags=flags, initial=initial, interval=interval): + with self.assertRaises(OSError) as context: + os.timerfd_settime(fd, flags=flags, initial=initial, interval=interval) + self.assertEqual(context.exception.errno, errno.EINVAL) + + with self.assertRaises(OSError) as context: + initial_ns = int( one_sec_in_nsec * initial ) + interval_ns = int( one_sec_in_nsec * interval ) + os.timerfd_settime_ns(fd, flags=flags, initial=initial_ns, interval=interval_ns) + self.assertEqual(context.exception.errno, errno.EINVAL) + + def test_timerfd_interval(self): + fd = self.timerfd_create(time.CLOCK_REALTIME) + + # 1 second + initial_expiration = 1 + # 0.5 second + interval = 0.5 + + os.timerfd_settime(fd, initial=initial_expiration, interval=interval) + + # timerfd_gettime + next_expiration, interval2 = os.timerfd_gettime(fd) + self.assertAlmostEqual(interval2, interval, places=3) + self.assertAlmostEqual(next_expiration, initial_expiration, places=3) + + count = 3 + t = time.perf_counter() + for _ in range(count): + self.assertEqual(self.read_count_signaled(fd), 1) + t = time.perf_counter() - t + + total_time = initial_expiration + interval * (count - 1) + self.assertGreater(t, total_time - self.CLOCK_RES) + + # wait 3.5 time of interval + time.sleep( (count+0.5) * interval) + self.assertEqual(self.read_count_signaled(fd), count) + + def test_timerfd_TFD_TIMER_ABSTIME(self): + fd = self.timerfd_create(time.CLOCK_REALTIME) + + now = time.clock_gettime(time.CLOCK_REALTIME) + + # 1 second later from now. + offset = 1 + initial_expiration = now + offset + # not interval timer + interval = 0 + + os.timerfd_settime(fd, flags=os.TFD_TIMER_ABSTIME, initial=initial_expiration, interval=interval) + + # timerfd_gettime + # Note: timerfd_gettime returns relative values even if TFD_TIMER_ABSTIME is specified. + next_expiration, interval2 = os.timerfd_gettime(fd) + self.assertAlmostEqual(interval2, interval, places=3) + self.assertAlmostEqual(next_expiration, offset, places=3) + + t = time.perf_counter() + count_signaled = self.read_count_signaled(fd) + t = time.perf_counter() - t + self.assertEqual(count_signaled, 1) + + self.assertGreater(t, offset - self.CLOCK_RES) + + def test_timerfd_select(self): + fd = self.timerfd_create(time.CLOCK_REALTIME, flags=os.TFD_NONBLOCK) + + rfd, wfd, xfd = select.select([fd], [fd], [fd], 0) + self.assertEqual((rfd, wfd, xfd), ([], [], [])) + + # 0.25 second + initial_expiration = 0.25 + # every 0.125 second + interval = 0.125 + + os.timerfd_settime(fd, initial=initial_expiration, interval=interval) + + count = 3 + t = time.perf_counter() + for _ in range(count): + rfd, wfd, xfd = select.select([fd], [fd], [fd], initial_expiration + interval) + self.assertEqual((rfd, wfd, xfd), ([fd], [], [])) + self.assertEqual(self.read_count_signaled(fd), 1) + t = time.perf_counter() - t + + total_time = initial_expiration + interval * (count - 1) + self.assertGreater(t, total_time - self.CLOCK_RES) + + def check_timerfd_poll(self, nanoseconds): + fd = self.timerfd_create(time.CLOCK_REALTIME, flags=os.TFD_NONBLOCK) + + selector = selectors.DefaultSelector() + selector.register(fd, selectors.EVENT_READ) + self.addCleanup(selector.close) + + sec_to_nsec = 10 ** 9 + # 0.25 second + initial_expiration_ns = sec_to_nsec // 4 + # every 0.125 second + interval_ns = sec_to_nsec // 8 + + if nanoseconds: + os.timerfd_settime_ns(fd, + initial=initial_expiration_ns, + interval=interval_ns) + else: + os.timerfd_settime(fd, + initial=initial_expiration_ns / sec_to_nsec, + interval=interval_ns / sec_to_nsec) + + count = 3 + if nanoseconds: + t = time.perf_counter_ns() + else: + t = time.perf_counter() + for i in range(count): + timeout_margin_ns = interval_ns + if i == 0: + timeout_ns = initial_expiration_ns + interval_ns + timeout_margin_ns + else: + timeout_ns = interval_ns + timeout_margin_ns + + ready = selector.select(timeout_ns / sec_to_nsec) + self.assertEqual(len(ready), 1, ready) + event = ready[0][1] + self.assertEqual(event, selectors.EVENT_READ) + + self.assertEqual(self.read_count_signaled(fd), 1) + + total_time = initial_expiration_ns + interval_ns * (count - 1) + if nanoseconds: + dt = time.perf_counter_ns() - t + self.assertGreater(dt, total_time - self.CLOCK_RES_NS) + else: + dt = time.perf_counter() - t + self.assertGreater(dt, total_time / sec_to_nsec - self.CLOCK_RES) + selector.unregister(fd) + + def test_timerfd_poll(self): + self.check_timerfd_poll(False) + + def test_timerfd_ns_poll(self): + self.check_timerfd_poll(True) + + def test_timerfd_ns_initval(self): + one_sec_in_nsec = 10**9 + limit_error = one_sec_in_nsec // 10**3 + fd = self.timerfd_create(time.CLOCK_REALTIME) + + # 1st call + initial_expiration_ns = 0 + interval_ns = one_sec_in_nsec // 1000 + next_expiration_ns, interval_ns2 = os.timerfd_settime_ns(fd, initial=initial_expiration_ns, interval=interval_ns) + self.assertEqual(interval_ns2, 0) + self.assertEqual(next_expiration_ns, 0) + + # 2nd call + next_expiration_ns, interval_ns2 = os.timerfd_settime_ns(fd, initial=initial_expiration_ns, interval=interval_ns) + self.assertEqual(interval_ns2, interval_ns) + self.assertEqual(next_expiration_ns, initial_expiration_ns) + + # timerfd_gettime + next_expiration_ns, interval_ns2 = os.timerfd_gettime_ns(fd) + self.assertEqual(interval_ns2, interval_ns) + self.assertLessEqual(next_expiration_ns, initial_expiration_ns) + + self.assertAlmostEqual(next_expiration_ns, initial_expiration_ns, delta=limit_error) + + def test_timerfd_ns_interval(self): + one_sec_in_nsec = 10**9 + limit_error = one_sec_in_nsec // 10**3 + fd = self.timerfd_create(time.CLOCK_REALTIME) + + # 1 second + initial_expiration_ns = one_sec_in_nsec + # every 0.5 second + interval_ns = one_sec_in_nsec // 2 + + os.timerfd_settime_ns(fd, initial=initial_expiration_ns, interval=interval_ns) + + # timerfd_gettime + next_expiration_ns, interval_ns2 = os.timerfd_gettime_ns(fd) + self.assertEqual(interval_ns2, interval_ns) + self.assertLessEqual(next_expiration_ns, initial_expiration_ns) + + count = 3 + t = time.perf_counter_ns() + for _ in range(count): + self.assertEqual(self.read_count_signaled(fd), 1) + t = time.perf_counter_ns() - t + + total_time_ns = initial_expiration_ns + interval_ns * (count - 1) + self.assertGreater(t, total_time_ns - self.CLOCK_RES_NS) + + # wait 3.5 time of interval + time.sleep( (count+0.5) * interval_ns / one_sec_in_nsec) + self.assertEqual(self.read_count_signaled(fd), count) + + + def test_timerfd_ns_TFD_TIMER_ABSTIME(self): + one_sec_in_nsec = 10**9 + limit_error = one_sec_in_nsec // 10**3 + fd = self.timerfd_create(time.CLOCK_REALTIME) + + now_ns = time.clock_gettime_ns(time.CLOCK_REALTIME) + + # 1 second later from now. + offset_ns = one_sec_in_nsec + initial_expiration_ns = now_ns + offset_ns + # not interval timer + interval_ns = 0 + + os.timerfd_settime_ns(fd, flags=os.TFD_TIMER_ABSTIME, initial=initial_expiration_ns, interval=interval_ns) + + # timerfd_gettime + # Note: timerfd_gettime returns relative values even if TFD_TIMER_ABSTIME is specified. + next_expiration_ns, interval_ns2 = os.timerfd_gettime_ns(fd) + self.assertLess(abs(interval_ns2 - interval_ns), limit_error) + self.assertLess(abs(next_expiration_ns - offset_ns), limit_error) + + t = time.perf_counter_ns() + count_signaled = self.read_count_signaled(fd) + t = time.perf_counter_ns() - t + self.assertEqual(count_signaled, 1) + + self.assertGreater(t, offset_ns - self.CLOCK_RES_NS) + + def test_timerfd_ns_select(self): + one_sec_in_nsec = 10**9 + + fd = self.timerfd_create(time.CLOCK_REALTIME, flags=os.TFD_NONBLOCK) + + rfd, wfd, xfd = select.select([fd], [fd], [fd], 0) + self.assertEqual((rfd, wfd, xfd), ([], [], [])) + + # 0.25 second + initial_expiration_ns = one_sec_in_nsec // 4 + # every 0.125 second + interval_ns = one_sec_in_nsec // 8 + + os.timerfd_settime_ns(fd, initial=initial_expiration_ns, interval=interval_ns) + + count = 3 + t = time.perf_counter_ns() + for _ in range(count): + rfd, wfd, xfd = select.select([fd], [fd], [fd], (initial_expiration_ns + interval_ns) / 1e9 ) + self.assertEqual((rfd, wfd, xfd), ([fd], [], [])) + self.assertEqual(self.read_count_signaled(fd), 1) + t = time.perf_counter_ns() - t + + total_time_ns = initial_expiration_ns + interval_ns * (count - 1) + self.assertGreater(t, total_time_ns - self.CLOCK_RES_NS) class OSErrorTests(unittest.TestCase): def setUp(self): @@ -3989,14 +4326,42 @@ def test_oserror_filename(self): self.fail(f"No exception thrown by {func}") class CPUCountTests(unittest.TestCase): + def check_cpu_count(self, cpus): + if cpus is None: + self.skipTest("Could not determine the number of CPUs") + + self.assertIsInstance(cpus, int) + self.assertGreater(cpus, 0) + def test_cpu_count(self): cpus = os.cpu_count() - if cpus is not None: - self.assertIsInstance(cpus, int) - self.assertGreater(cpus, 0) - else: + self.check_cpu_count(cpus) + + def test_process_cpu_count(self): + cpus = os.process_cpu_count() + self.assertLessEqual(cpus, os.cpu_count()) + self.check_cpu_count(cpus) + + @unittest.skipUnless(hasattr(os, 'sched_setaffinity'), + "don't have sched affinity support") + def test_process_cpu_count_affinity(self): + affinity1 = os.process_cpu_count() + if affinity1 is None: self.skipTest("Could not determine the number of CPUs") + # Disable one CPU + mask = os.sched_getaffinity(0) + if len(mask) <= 1: + self.skipTest(f"sched_getaffinity() returns less than " + f"2 CPUs: {sorted(mask)}") + self.addCleanup(os.sched_setaffinity, 0, list(mask)) + mask.pop() + os.sched_setaffinity(0, mask) + + # test process_cpu_count() + affinity2 = os.process_cpu_count() + self.assertEqual(affinity2, affinity1 - 1) + # FD inheritance check is only useful for systems with process support. @support.requires_subprocess() @@ -4120,6 +4485,61 @@ def test_openpty(self): self.assertEqual(os.get_inheritable(master_fd), False) self.assertEqual(os.get_inheritable(slave_fd), False) + @unittest.skipUnless(hasattr(os, 'spawnl'), "need os.openpty()") + def test_pipe_spawnl(self): + # gh-77046: On Windows, os.pipe() file descriptors must be created with + # _O_NOINHERIT to make them non-inheritable. UCRT has no public API to + # get (_osfile(fd) & _O_NOINHERIT), so use a functional test. + # + # Make sure that fd is not inherited by a child process created by + # os.spawnl(): get_osfhandle() and dup() must fail with EBADF. + + fd, fd2 = os.pipe() + self.addCleanup(os.close, fd) + self.addCleanup(os.close, fd2) + + code = textwrap.dedent(f""" + import errno + import os + import test.support + try: + import msvcrt + except ImportError: + msvcrt = None + + fd = {fd} + + with test.support.SuppressCrashReport(): + if msvcrt is not None: + try: + handle = msvcrt.get_osfhandle(fd) + except OSError as exc: + if exc.errno != errno.EBADF: + raise + # get_osfhandle(fd) failed with EBADF as expected + else: + raise Exception("get_osfhandle() must fail") + + try: + fd3 = os.dup(fd) + except OSError as exc: + if exc.errno != errno.EBADF: + raise + # os.dup(fd) failed with EBADF as expected + else: + os.close(fd3) + raise Exception("dup must fail") + """) + + filename = os_helper.TESTFN + self.addCleanup(os_helper.unlink, os_helper.TESTFN) + with open(filename, "w") as fp: + print(code, file=fp, end="") + + cmd = [sys.executable, filename] + exitcode = os.spawnl(os.P_WAIT, cmd[0], *cmd) + self.assertEqual(exitcode, 0) + class PathTConverterTests(unittest.TestCase): # tuples of (function name, allows fd arguments, additional arguments to @@ -4715,7 +5135,10 @@ def test_fork(self): support.wait_process(pid, exitcode=0) """ assert_python_ok("-c", code) - assert_python_ok("-c", code, PYTHONMALLOC="malloc_debug") + if support.Py_GIL_DISABLED: + assert_python_ok("-c", code, PYTHONMALLOC="mimalloc_debug") + else: + assert_python_ok("-c", code, PYTHONMALLOC="malloc_debug") @unittest.skipUnless(sys.platform in ("linux", "darwin"), "Only Linux and macOS detect this today.") diff --git a/Lib/test/test_pathlib.py b/Lib/test/test_pathlib.py deleted file mode 100644 index 74deec84336f72..00000000000000 --- a/Lib/test/test_pathlib.py +++ /dev/null @@ -1,3521 +0,0 @@ -import collections.abc -import io -import os -import sys -import errno -import pathlib -import pickle -import posixpath -import socket -import stat -import tempfile -import unittest -from unittest import mock - -from test.support import import_helper -from test.support import set_recursion_limit -from test.support import is_emscripten, is_wasi -from test.support import os_helper -from test.support.os_helper import TESTFN, FakePath - -try: - import grp, pwd -except ImportError: - grp = pwd = None - - -class UnsupportedOperationTest(unittest.TestCase): - def test_is_notimplemented(self): - self.assertTrue(issubclass(pathlib.UnsupportedOperation, NotImplementedError)) - self.assertTrue(isinstance(pathlib.UnsupportedOperation(), NotImplementedError)) - - -# Make sure any symbolic links in the base test path are resolved. -BASE = os.path.realpath(TESTFN) -join = lambda *x: os.path.join(BASE, *x) -rel_join = lambda *x: os.path.join(TESTFN, *x) - -only_nt = unittest.skipIf(os.name != 'nt', - 'test requires a Windows-compatible system') -only_posix = unittest.skipIf(os.name == 'nt', - 'test requires a POSIX-compatible system') - - -# -# Tests for the pure classes. -# - -class PurePathTest(unittest.TestCase): - cls = pathlib.PurePath - - # Keys are canonical paths, values are list of tuples of arguments - # supposed to produce equal paths. - equivalences = { - 'a/b': [ - ('a', 'b'), ('a/', 'b'), ('a', 'b/'), ('a/', 'b/'), - ('a/b/',), ('a//b',), ('a//b//',), - # Empty components get removed. - ('', 'a', 'b'), ('a', '', 'b'), ('a', 'b', ''), - ], - '/b/c/d': [ - ('a', '/b/c', 'd'), ('/a', '/b/c', 'd'), - # Empty components get removed. - ('/', 'b', '', 'c/d'), ('/', '', 'b/c/d'), ('', '/b/c/d'), - ], - } - - def setUp(self): - p = self.cls('a') - self.pathmod = p.pathmod - self.sep = self.pathmod.sep - self.altsep = self.pathmod.altsep - - def test_constructor_common(self): - P = self.cls - p = P('a') - self.assertIsInstance(p, P) - P('a', 'b', 'c') - P('/a', 'b', 'c') - P('a/b/c') - P('/a/b/c') - P(FakePath("a/b/c")) - self.assertEqual(P(P('a')), P('a')) - self.assertEqual(P(P('a'), 'b'), P('a/b')) - self.assertEqual(P(P('a'), P('b')), P('a/b')) - self.assertEqual(P(P('a'), P('b'), P('c')), P(FakePath("a/b/c"))) - self.assertEqual(P(P('./a:b')), P('./a:b')) - - def test_concrete_class(self): - if self.cls is pathlib.PurePath: - expected = pathlib.PureWindowsPath if os.name == 'nt' else pathlib.PurePosixPath - else: - expected = self.cls - p = self.cls('a') - self.assertIs(type(p), expected) - - def test_different_pathmods_unequal(self): - p = self.cls('a') - if p.pathmod is posixpath: - q = pathlib.PureWindowsPath('a') - else: - q = pathlib.PurePosixPath('a') - self.assertNotEqual(p, q) - - def test_different_pathmods_unordered(self): - p = self.cls('a') - if p.pathmod is posixpath: - q = pathlib.PureWindowsPath('a') - else: - q = pathlib.PurePosixPath('a') - with self.assertRaises(TypeError): - p < q - with self.assertRaises(TypeError): - p <= q - with self.assertRaises(TypeError): - p > q - with self.assertRaises(TypeError): - p >= q - - def test_bytes(self): - P = self.cls - message = (r"argument should be a str or an os\.PathLike object " - r"where __fspath__ returns a str, not 'bytes'") - with self.assertRaisesRegex(TypeError, message): - P(b'a') - with self.assertRaisesRegex(TypeError, message): - P(b'a', 'b') - with self.assertRaisesRegex(TypeError, message): - P('a', b'b') - with self.assertRaises(TypeError): - P('a').joinpath(b'b') - with self.assertRaises(TypeError): - P('a') / b'b' - with self.assertRaises(TypeError): - b'a' / P('b') - with self.assertRaises(TypeError): - P('a').match(b'b') - with self.assertRaises(TypeError): - P('a').relative_to(b'b') - with self.assertRaises(TypeError): - P('a').with_name(b'b') - with self.assertRaises(TypeError): - P('a').with_stem(b'b') - with self.assertRaises(TypeError): - P('a').with_suffix(b'b') - - def _check_str_subclass(self, *args): - # Issue #21127: it should be possible to construct a PurePath object - # from a str subclass instance, and it then gets converted to - # a pure str object. - class StrSubclass(str): - pass - P = self.cls - p = P(*(StrSubclass(x) for x in args)) - self.assertEqual(p, P(*args)) - for part in p.parts: - self.assertIs(type(part), str) - - def test_str_subclass_common(self): - self._check_str_subclass('') - self._check_str_subclass('.') - self._check_str_subclass('a') - self._check_str_subclass('a/b.txt') - self._check_str_subclass('/a/b.txt') - - def test_with_segments_common(self): - class P(self.cls): - def __init__(self, *pathsegments, session_id): - super().__init__(*pathsegments) - self.session_id = session_id - - def with_segments(self, *pathsegments): - return type(self)(*pathsegments, session_id=self.session_id) - p = P('foo', 'bar', session_id=42) - self.assertEqual(42, (p / 'foo').session_id) - self.assertEqual(42, ('foo' / p).session_id) - self.assertEqual(42, p.joinpath('foo').session_id) - self.assertEqual(42, p.with_name('foo').session_id) - self.assertEqual(42, p.with_stem('foo').session_id) - self.assertEqual(42, p.with_suffix('.foo').session_id) - self.assertEqual(42, p.with_segments('foo').session_id) - self.assertEqual(42, p.relative_to('foo').session_id) - self.assertEqual(42, p.parent.session_id) - for parent in p.parents: - self.assertEqual(42, parent.session_id) - - def _get_drive_root_parts(self, parts): - path = self.cls(*parts) - return path.drive, path.root, path.parts - - def _check_drive_root_parts(self, arg, *expected): - sep = self.pathmod.sep - actual = self._get_drive_root_parts([x.replace('/', sep) for x in arg]) - self.assertEqual(actual, expected) - if altsep := self.pathmod.altsep: - actual = self._get_drive_root_parts([x.replace('/', altsep) for x in arg]) - self.assertEqual(actual, expected) - - def test_drive_root_parts_common(self): - check = self._check_drive_root_parts - sep = self.pathmod.sep - # Unanchored parts. - check((), '', '', ()) - check(('a',), '', '', ('a',)) - check(('a/',), '', '', ('a',)) - check(('a', 'b'), '', '', ('a', 'b')) - # Expansion. - check(('a/b',), '', '', ('a', 'b')) - check(('a/b/',), '', '', ('a', 'b')) - check(('a', 'b/c', 'd'), '', '', ('a', 'b', 'c', 'd')) - # Collapsing and stripping excess slashes. - check(('a', 'b//c', 'd'), '', '', ('a', 'b', 'c', 'd')) - check(('a', 'b/c/', 'd'), '', '', ('a', 'b', 'c', 'd')) - # Eliminating standalone dots. - check(('.',), '', '', ()) - check(('.', '.', 'b'), '', '', ('b',)) - check(('a', '.', 'b'), '', '', ('a', 'b')) - check(('a', '.', '.'), '', '', ('a',)) - # The first part is anchored. - check(('/a/b',), '', sep, (sep, 'a', 'b')) - check(('/a', 'b'), '', sep, (sep, 'a', 'b')) - check(('/a/', 'b'), '', sep, (sep, 'a', 'b')) - # Ignoring parts before an anchored part. - check(('a', '/b', 'c'), '', sep, (sep, 'b', 'c')) - check(('a', '/b', '/c'), '', sep, (sep, 'c')) - - def test_join_common(self): - P = self.cls - p = P('a/b') - pp = p.joinpath('c') - self.assertEqual(pp, P('a/b/c')) - self.assertIs(type(pp), type(p)) - pp = p.joinpath('c', 'd') - self.assertEqual(pp, P('a/b/c/d')) - pp = p.joinpath(P('c')) - self.assertEqual(pp, P('a/b/c')) - pp = p.joinpath('/c') - self.assertEqual(pp, P('/c')) - - def test_div_common(self): - # Basically the same as joinpath(). - P = self.cls - p = P('a/b') - pp = p / 'c' - self.assertEqual(pp, P('a/b/c')) - self.assertIs(type(pp), type(p)) - pp = p / 'c/d' - self.assertEqual(pp, P('a/b/c/d')) - pp = p / 'c' / 'd' - self.assertEqual(pp, P('a/b/c/d')) - pp = 'c' / p / 'd' - self.assertEqual(pp, P('c/a/b/d')) - pp = p / P('c') - self.assertEqual(pp, P('a/b/c')) - pp = p/ '/c' - self.assertEqual(pp, P('/c')) - - def _check_str(self, expected, args): - p = self.cls(*args) - self.assertEqual(str(p), expected.replace('/', self.sep)) - - def test_str_common(self): - # Canonicalized paths roundtrip. - for pathstr in ('a', 'a/b', 'a/b/c', '/', '/a/b', '/a/b/c'): - self._check_str(pathstr, (pathstr,)) - # Special case for the empty path. - self._check_str('.', ('',)) - # Other tests for str() are in test_equivalences(). - - def test_as_posix_common(self): - P = self.cls - for pathstr in ('a', 'a/b', 'a/b/c', '/', '/a/b', '/a/b/c'): - self.assertEqual(P(pathstr).as_posix(), pathstr) - # Other tests for as_posix() are in test_equivalences(). - - def test_as_bytes_common(self): - sep = os.fsencode(self.sep) - P = self.cls - self.assertEqual(bytes(P('a/b')), b'a' + sep + b'b') - - def test_as_uri_common(self): - P = self.cls - with self.assertRaises(ValueError): - P('a').as_uri() - with self.assertRaises(ValueError): - P().as_uri() - - def test_repr_common(self): - for pathstr in ('a', 'a/b', 'a/b/c', '/', '/a/b', '/a/b/c'): - with self.subTest(pathstr=pathstr): - p = self.cls(pathstr) - clsname = p.__class__.__name__ - r = repr(p) - # The repr() is in the form ClassName("forward-slashes path"). - self.assertTrue(r.startswith(clsname + '('), r) - self.assertTrue(r.endswith(')'), r) - inner = r[len(clsname) + 1 : -1] - self.assertEqual(eval(inner), p.as_posix()) - - def test_repr_roundtrips(self): - for pathstr in ('a', 'a/b', 'a/b/c', '/', '/a/b', '/a/b/c'): - with self.subTest(pathstr=pathstr): - p = self.cls(pathstr) - r = repr(p) - # The repr() roundtrips. - q = eval(r, pathlib.__dict__) - self.assertIs(q.__class__, p.__class__) - self.assertEqual(q, p) - self.assertEqual(repr(q), r) - - def test_eq_common(self): - P = self.cls - self.assertEqual(P('a/b'), P('a/b')) - self.assertEqual(P('a/b'), P('a', 'b')) - self.assertNotEqual(P('a/b'), P('a')) - self.assertNotEqual(P('a/b'), P('/a/b')) - self.assertNotEqual(P('a/b'), P()) - self.assertNotEqual(P('/a/b'), P('/')) - self.assertNotEqual(P(), P('/')) - self.assertNotEqual(P(), "") - self.assertNotEqual(P(), {}) - self.assertNotEqual(P(), int) - - def test_match_common(self): - P = self.cls - self.assertRaises(ValueError, P('a').match, '') - self.assertRaises(ValueError, P('a').match, '.') - # Simple relative pattern. - self.assertTrue(P('b.py').match('b.py')) - self.assertTrue(P('a/b.py').match('b.py')) - self.assertTrue(P('/a/b.py').match('b.py')) - self.assertFalse(P('a.py').match('b.py')) - self.assertFalse(P('b/py').match('b.py')) - self.assertFalse(P('/a.py').match('b.py')) - self.assertFalse(P('b.py/c').match('b.py')) - # Wildcard relative pattern. - self.assertTrue(P('b.py').match('*.py')) - self.assertTrue(P('a/b.py').match('*.py')) - self.assertTrue(P('/a/b.py').match('*.py')) - self.assertFalse(P('b.pyc').match('*.py')) - self.assertFalse(P('b./py').match('*.py')) - self.assertFalse(P('b.py/c').match('*.py')) - # Multi-part relative pattern. - self.assertTrue(P('ab/c.py').match('a*/*.py')) - self.assertTrue(P('/d/ab/c.py').match('a*/*.py')) - self.assertFalse(P('a.py').match('a*/*.py')) - self.assertFalse(P('/dab/c.py').match('a*/*.py')) - self.assertFalse(P('ab/c.py/d').match('a*/*.py')) - # Absolute pattern. - self.assertTrue(P('/b.py').match('/*.py')) - self.assertFalse(P('b.py').match('/*.py')) - self.assertFalse(P('a/b.py').match('/*.py')) - self.assertFalse(P('/a/b.py').match('/*.py')) - # Multi-part absolute pattern. - self.assertTrue(P('/a/b.py').match('/a/*.py')) - self.assertFalse(P('/ab.py').match('/a/*.py')) - self.assertFalse(P('/a/b/c.py').match('/a/*.py')) - # Multi-part glob-style pattern. - self.assertTrue(P('a').match('**')) - self.assertTrue(P('c.py').match('**')) - self.assertTrue(P('a/b/c.py').match('**')) - self.assertTrue(P('/a/b/c.py').match('**')) - self.assertTrue(P('/a/b/c.py').match('/**')) - self.assertTrue(P('/a/b/c.py').match('**/')) - self.assertTrue(P('/a/b/c.py').match('/a/**')) - self.assertTrue(P('/a/b/c.py').match('**/*.py')) - self.assertTrue(P('/a/b/c.py').match('/**/*.py')) - self.assertTrue(P('/a/b/c.py').match('/a/**/*.py')) - self.assertTrue(P('/a/b/c.py').match('/a/b/**/*.py')) - self.assertTrue(P('/a/b/c.py').match('/**/**/**/**/*.py')) - self.assertFalse(P('c.py').match('**/a.py')) - self.assertFalse(P('c.py').match('c/**')) - self.assertFalse(P('a/b/c.py').match('**/a')) - self.assertFalse(P('a/b/c.py').match('**/a/b')) - self.assertFalse(P('a/b/c.py').match('**/a/b/c')) - self.assertFalse(P('a/b/c.py').match('**/a/b/c.')) - self.assertFalse(P('a/b/c.py').match('**/a/b/c./**')) - self.assertFalse(P('a/b/c.py').match('**/a/b/c./**')) - self.assertFalse(P('a/b/c.py').match('/a/b/c.py/**')) - self.assertFalse(P('a/b/c.py').match('/**/a/b/c.py')) - self.assertRaises(ValueError, P('a').match, '**a/b/c') - self.assertRaises(ValueError, P('a').match, 'a/b/c**') - # Case-sensitive flag - self.assertFalse(P('A.py').match('a.PY', case_sensitive=True)) - self.assertTrue(P('A.py').match('a.PY', case_sensitive=False)) - self.assertFalse(P('c:/a/B.Py').match('C:/A/*.pY', case_sensitive=True)) - self.assertTrue(P('/a/b/c.py').match('/A/*/*.Py', case_sensitive=False)) - # Matching against empty path - self.assertFalse(P().match('*')) - self.assertTrue(P().match('**')) - self.assertFalse(P().match('**/*')) - - def test_ordering_common(self): - # Ordering is tuple-alike. - def assertLess(a, b): - self.assertLess(a, b) - self.assertGreater(b, a) - P = self.cls - a = P('a') - b = P('a/b') - c = P('abc') - d = P('b') - assertLess(a, b) - assertLess(a, c) - assertLess(a, d) - assertLess(b, c) - assertLess(c, d) - P = self.cls - a = P('/a') - b = P('/a/b') - c = P('/abc') - d = P('/b') - assertLess(a, b) - assertLess(a, c) - assertLess(a, d) - assertLess(b, c) - assertLess(c, d) - with self.assertRaises(TypeError): - P() < {} - - def test_parts_common(self): - # `parts` returns a tuple. - sep = self.sep - P = self.cls - p = P('a/b') - parts = p.parts - self.assertEqual(parts, ('a', 'b')) - # When the path is absolute, the anchor is a separate part. - p = P('/a/b') - parts = p.parts - self.assertEqual(parts, (sep, 'a', 'b')) - - def test_fspath_common(self): - P = self.cls - p = P('a/b') - self._check_str(p.__fspath__(), ('a/b',)) - self._check_str(os.fspath(p), ('a/b',)) - - def test_equivalences(self): - for k, tuples in self.equivalences.items(): - canon = k.replace('/', self.sep) - posix = k.replace(self.sep, '/') - if canon != posix: - tuples = tuples + [ - tuple(part.replace('/', self.sep) for part in t) - for t in tuples - ] - tuples.append((posix, )) - pcanon = self.cls(canon) - for t in tuples: - p = self.cls(*t) - self.assertEqual(p, pcanon, "failed with args {}".format(t)) - self.assertEqual(hash(p), hash(pcanon)) - self.assertEqual(str(p), canon) - self.assertEqual(p.as_posix(), posix) - - def test_parent_common(self): - # Relative - P = self.cls - p = P('a/b/c') - self.assertEqual(p.parent, P('a/b')) - self.assertEqual(p.parent.parent, P('a')) - self.assertEqual(p.parent.parent.parent, P()) - self.assertEqual(p.parent.parent.parent.parent, P()) - # Anchored - p = P('/a/b/c') - self.assertEqual(p.parent, P('/a/b')) - self.assertEqual(p.parent.parent, P('/a')) - self.assertEqual(p.parent.parent.parent, P('/')) - self.assertEqual(p.parent.parent.parent.parent, P('/')) - - def test_parents_common(self): - # Relative - P = self.cls - p = P('a/b/c') - par = p.parents - self.assertEqual(len(par), 3) - self.assertEqual(par[0], P('a/b')) - self.assertEqual(par[1], P('a')) - self.assertEqual(par[2], P('.')) - self.assertEqual(par[-1], P('.')) - self.assertEqual(par[-2], P('a')) - self.assertEqual(par[-3], P('a/b')) - self.assertEqual(par[0:1], (P('a/b'),)) - self.assertEqual(par[:2], (P('a/b'), P('a'))) - self.assertEqual(par[:-1], (P('a/b'), P('a'))) - self.assertEqual(par[1:], (P('a'), P('.'))) - self.assertEqual(par[::2], (P('a/b'), P('.'))) - self.assertEqual(par[::-1], (P('.'), P('a'), P('a/b'))) - self.assertEqual(list(par), [P('a/b'), P('a'), P('.')]) - with self.assertRaises(IndexError): - par[-4] - with self.assertRaises(IndexError): - par[3] - with self.assertRaises(TypeError): - par[0] = p - # Anchored - p = P('/a/b/c') - par = p.parents - self.assertEqual(len(par), 3) - self.assertEqual(par[0], P('/a/b')) - self.assertEqual(par[1], P('/a')) - self.assertEqual(par[2], P('/')) - self.assertEqual(par[-1], P('/')) - self.assertEqual(par[-2], P('/a')) - self.assertEqual(par[-3], P('/a/b')) - self.assertEqual(par[0:1], (P('/a/b'),)) - self.assertEqual(par[:2], (P('/a/b'), P('/a'))) - self.assertEqual(par[:-1], (P('/a/b'), P('/a'))) - self.assertEqual(par[1:], (P('/a'), P('/'))) - self.assertEqual(par[::2], (P('/a/b'), P('/'))) - self.assertEqual(par[::-1], (P('/'), P('/a'), P('/a/b'))) - self.assertEqual(list(par), [P('/a/b'), P('/a'), P('/')]) - with self.assertRaises(IndexError): - par[-4] - with self.assertRaises(IndexError): - par[3] - - def test_drive_common(self): - P = self.cls - self.assertEqual(P('a/b').drive, '') - self.assertEqual(P('/a/b').drive, '') - self.assertEqual(P('').drive, '') - - def test_root_common(self): - P = self.cls - sep = self.sep - self.assertEqual(P('').root, '') - self.assertEqual(P('a/b').root, '') - self.assertEqual(P('/').root, sep) - self.assertEqual(P('/a/b').root, sep) - - def test_anchor_common(self): - P = self.cls - sep = self.sep - self.assertEqual(P('').anchor, '') - self.assertEqual(P('a/b').anchor, '') - self.assertEqual(P('/').anchor, sep) - self.assertEqual(P('/a/b').anchor, sep) - - def test_name_common(self): - P = self.cls - self.assertEqual(P('').name, '') - self.assertEqual(P('.').name, '') - self.assertEqual(P('/').name, '') - self.assertEqual(P('a/b').name, 'b') - self.assertEqual(P('/a/b').name, 'b') - self.assertEqual(P('/a/b/.').name, 'b') - self.assertEqual(P('a/b.py').name, 'b.py') - self.assertEqual(P('/a/b.py').name, 'b.py') - - def test_suffix_common(self): - P = self.cls - self.assertEqual(P('').suffix, '') - self.assertEqual(P('.').suffix, '') - self.assertEqual(P('..').suffix, '') - self.assertEqual(P('/').suffix, '') - self.assertEqual(P('a/b').suffix, '') - self.assertEqual(P('/a/b').suffix, '') - self.assertEqual(P('/a/b/.').suffix, '') - self.assertEqual(P('a/b.py').suffix, '.py') - self.assertEqual(P('/a/b.py').suffix, '.py') - self.assertEqual(P('a/.hgrc').suffix, '') - self.assertEqual(P('/a/.hgrc').suffix, '') - self.assertEqual(P('a/.hg.rc').suffix, '.rc') - self.assertEqual(P('/a/.hg.rc').suffix, '.rc') - self.assertEqual(P('a/b.tar.gz').suffix, '.gz') - self.assertEqual(P('/a/b.tar.gz').suffix, '.gz') - self.assertEqual(P('a/Some name. Ending with a dot.').suffix, '') - self.assertEqual(P('/a/Some name. Ending with a dot.').suffix, '') - - def test_suffixes_common(self): - P = self.cls - self.assertEqual(P('').suffixes, []) - self.assertEqual(P('.').suffixes, []) - self.assertEqual(P('/').suffixes, []) - self.assertEqual(P('a/b').suffixes, []) - self.assertEqual(P('/a/b').suffixes, []) - self.assertEqual(P('/a/b/.').suffixes, []) - self.assertEqual(P('a/b.py').suffixes, ['.py']) - self.assertEqual(P('/a/b.py').suffixes, ['.py']) - self.assertEqual(P('a/.hgrc').suffixes, []) - self.assertEqual(P('/a/.hgrc').suffixes, []) - self.assertEqual(P('a/.hg.rc').suffixes, ['.rc']) - self.assertEqual(P('/a/.hg.rc').suffixes, ['.rc']) - self.assertEqual(P('a/b.tar.gz').suffixes, ['.tar', '.gz']) - self.assertEqual(P('/a/b.tar.gz').suffixes, ['.tar', '.gz']) - self.assertEqual(P('a/Some name. Ending with a dot.').suffixes, []) - self.assertEqual(P('/a/Some name. Ending with a dot.').suffixes, []) - - def test_stem_common(self): - P = self.cls - self.assertEqual(P('').stem, '') - self.assertEqual(P('.').stem, '') - self.assertEqual(P('..').stem, '..') - self.assertEqual(P('/').stem, '') - self.assertEqual(P('a/b').stem, 'b') - self.assertEqual(P('a/b.py').stem, 'b') - self.assertEqual(P('a/.hgrc').stem, '.hgrc') - self.assertEqual(P('a/.hg.rc').stem, '.hg') - self.assertEqual(P('a/b.tar.gz').stem, 'b.tar') - self.assertEqual(P('a/Some name. Ending with a dot.').stem, - 'Some name. Ending with a dot.') - - def test_with_name_common(self): - P = self.cls - self.assertEqual(P('a/b').with_name('d.xml'), P('a/d.xml')) - self.assertEqual(P('/a/b').with_name('d.xml'), P('/a/d.xml')) - self.assertEqual(P('a/b.py').with_name('d.xml'), P('a/d.xml')) - self.assertEqual(P('/a/b.py').with_name('d.xml'), P('/a/d.xml')) - self.assertEqual(P('a/Dot ending.').with_name('d.xml'), P('a/d.xml')) - self.assertEqual(P('/a/Dot ending.').with_name('d.xml'), P('/a/d.xml')) - self.assertRaises(ValueError, P('').with_name, 'd.xml') - self.assertRaises(ValueError, P('.').with_name, 'd.xml') - self.assertRaises(ValueError, P('/').with_name, 'd.xml') - self.assertRaises(ValueError, P('a/b').with_name, '') - self.assertRaises(ValueError, P('a/b').with_name, '/c') - self.assertRaises(ValueError, P('a/b').with_name, 'c/') - self.assertRaises(ValueError, P('a/b').with_name, 'c/d') - - def test_with_stem_common(self): - P = self.cls - self.assertEqual(P('a/b').with_stem('d'), P('a/d')) - self.assertEqual(P('/a/b').with_stem('d'), P('/a/d')) - self.assertEqual(P('a/b.py').with_stem('d'), P('a/d.py')) - self.assertEqual(P('/a/b.py').with_stem('d'), P('/a/d.py')) - self.assertEqual(P('/a/b.tar.gz').with_stem('d'), P('/a/d.gz')) - self.assertEqual(P('a/Dot ending.').with_stem('d'), P('a/d')) - self.assertEqual(P('/a/Dot ending.').with_stem('d'), P('/a/d')) - self.assertRaises(ValueError, P('').with_stem, 'd') - self.assertRaises(ValueError, P('.').with_stem, 'd') - self.assertRaises(ValueError, P('/').with_stem, 'd') - self.assertRaises(ValueError, P('a/b').with_stem, '') - self.assertRaises(ValueError, P('a/b').with_stem, '/c') - self.assertRaises(ValueError, P('a/b').with_stem, 'c/') - self.assertRaises(ValueError, P('a/b').with_stem, 'c/d') - - def test_with_suffix_common(self): - P = self.cls - self.assertEqual(P('a/b').with_suffix('.gz'), P('a/b.gz')) - self.assertEqual(P('/a/b').with_suffix('.gz'), P('/a/b.gz')) - self.assertEqual(P('a/b.py').with_suffix('.gz'), P('a/b.gz')) - self.assertEqual(P('/a/b.py').with_suffix('.gz'), P('/a/b.gz')) - # Stripping suffix. - self.assertEqual(P('a/b.py').with_suffix(''), P('a/b')) - self.assertEqual(P('/a/b').with_suffix(''), P('/a/b')) - # Path doesn't have a "filename" component. - self.assertRaises(ValueError, P('').with_suffix, '.gz') - self.assertRaises(ValueError, P('.').with_suffix, '.gz') - self.assertRaises(ValueError, P('/').with_suffix, '.gz') - # Invalid suffix. - self.assertRaises(ValueError, P('a/b').with_suffix, 'gz') - self.assertRaises(ValueError, P('a/b').with_suffix, '/') - self.assertRaises(ValueError, P('a/b').with_suffix, '.') - self.assertRaises(ValueError, P('a/b').with_suffix, '/.gz') - self.assertRaises(ValueError, P('a/b').with_suffix, 'c/d') - self.assertRaises(ValueError, P('a/b').with_suffix, '.c/.d') - self.assertRaises(ValueError, P('a/b').with_suffix, './.d') - self.assertRaises(ValueError, P('a/b').with_suffix, '.d/.') - self.assertRaises(ValueError, P('a/b').with_suffix, - (self.pathmod.sep, 'd')) - - def test_relative_to_common(self): - P = self.cls - p = P('a/b') - self.assertRaises(TypeError, p.relative_to) - self.assertRaises(TypeError, p.relative_to, b'a') - self.assertEqual(p.relative_to(P()), P('a/b')) - self.assertEqual(p.relative_to(''), P('a/b')) - self.assertEqual(p.relative_to(P('a')), P('b')) - self.assertEqual(p.relative_to('a'), P('b')) - self.assertEqual(p.relative_to('a/'), P('b')) - self.assertEqual(p.relative_to(P('a/b')), P()) - self.assertEqual(p.relative_to('a/b'), P()) - self.assertEqual(p.relative_to(P(), walk_up=True), P('a/b')) - self.assertEqual(p.relative_to('', walk_up=True), P('a/b')) - self.assertEqual(p.relative_to(P('a'), walk_up=True), P('b')) - self.assertEqual(p.relative_to('a', walk_up=True), P('b')) - self.assertEqual(p.relative_to('a/', walk_up=True), P('b')) - self.assertEqual(p.relative_to(P('a/b'), walk_up=True), P()) - self.assertEqual(p.relative_to('a/b', walk_up=True), P()) - self.assertEqual(p.relative_to(P('a/c'), walk_up=True), P('../b')) - self.assertEqual(p.relative_to('a/c', walk_up=True), P('../b')) - self.assertEqual(p.relative_to(P('a/b/c'), walk_up=True), P('..')) - self.assertEqual(p.relative_to('a/b/c', walk_up=True), P('..')) - self.assertEqual(p.relative_to(P('c'), walk_up=True), P('../a/b')) - self.assertEqual(p.relative_to('c', walk_up=True), P('../a/b')) - # With several args. - with self.assertWarns(DeprecationWarning): - p.relative_to('a', 'b') - p.relative_to('a', 'b', walk_up=True) - # Unrelated paths. - self.assertRaises(ValueError, p.relative_to, P('c')) - self.assertRaises(ValueError, p.relative_to, P('a/b/c')) - self.assertRaises(ValueError, p.relative_to, P('a/c')) - self.assertRaises(ValueError, p.relative_to, P('/a')) - self.assertRaises(ValueError, p.relative_to, P("../a")) - self.assertRaises(ValueError, p.relative_to, P("a/..")) - self.assertRaises(ValueError, p.relative_to, P("/a/..")) - self.assertRaises(ValueError, p.relative_to, P('/'), walk_up=True) - self.assertRaises(ValueError, p.relative_to, P('/a'), walk_up=True) - self.assertRaises(ValueError, p.relative_to, P("../a"), walk_up=True) - self.assertRaises(ValueError, p.relative_to, P("a/.."), walk_up=True) - self.assertRaises(ValueError, p.relative_to, P("/a/.."), walk_up=True) - p = P('/a/b') - self.assertEqual(p.relative_to(P('/')), P('a/b')) - self.assertEqual(p.relative_to('/'), P('a/b')) - self.assertEqual(p.relative_to(P('/a')), P('b')) - self.assertEqual(p.relative_to('/a'), P('b')) - self.assertEqual(p.relative_to('/a/'), P('b')) - self.assertEqual(p.relative_to(P('/a/b')), P()) - self.assertEqual(p.relative_to('/a/b'), P()) - self.assertEqual(p.relative_to(P('/'), walk_up=True), P('a/b')) - self.assertEqual(p.relative_to('/', walk_up=True), P('a/b')) - self.assertEqual(p.relative_to(P('/a'), walk_up=True), P('b')) - self.assertEqual(p.relative_to('/a', walk_up=True), P('b')) - self.assertEqual(p.relative_to('/a/', walk_up=True), P('b')) - self.assertEqual(p.relative_to(P('/a/b'), walk_up=True), P()) - self.assertEqual(p.relative_to('/a/b', walk_up=True), P()) - self.assertEqual(p.relative_to(P('/a/c'), walk_up=True), P('../b')) - self.assertEqual(p.relative_to('/a/c', walk_up=True), P('../b')) - self.assertEqual(p.relative_to(P('/a/b/c'), walk_up=True), P('..')) - self.assertEqual(p.relative_to('/a/b/c', walk_up=True), P('..')) - self.assertEqual(p.relative_to(P('/c'), walk_up=True), P('../a/b')) - self.assertEqual(p.relative_to('/c', walk_up=True), P('../a/b')) - # Unrelated paths. - self.assertRaises(ValueError, p.relative_to, P('/c')) - self.assertRaises(ValueError, p.relative_to, P('/a/b/c')) - self.assertRaises(ValueError, p.relative_to, P('/a/c')) - self.assertRaises(ValueError, p.relative_to, P()) - self.assertRaises(ValueError, p.relative_to, '') - self.assertRaises(ValueError, p.relative_to, P('a')) - self.assertRaises(ValueError, p.relative_to, P("../a")) - self.assertRaises(ValueError, p.relative_to, P("a/..")) - self.assertRaises(ValueError, p.relative_to, P("/a/..")) - self.assertRaises(ValueError, p.relative_to, P(''), walk_up=True) - self.assertRaises(ValueError, p.relative_to, P('a'), walk_up=True) - self.assertRaises(ValueError, p.relative_to, P("../a"), walk_up=True) - self.assertRaises(ValueError, p.relative_to, P("a/.."), walk_up=True) - self.assertRaises(ValueError, p.relative_to, P("/a/.."), walk_up=True) - - def test_is_relative_to_common(self): - P = self.cls - p = P('a/b') - self.assertRaises(TypeError, p.is_relative_to) - self.assertRaises(TypeError, p.is_relative_to, b'a') - self.assertTrue(p.is_relative_to(P())) - self.assertTrue(p.is_relative_to('')) - self.assertTrue(p.is_relative_to(P('a'))) - self.assertTrue(p.is_relative_to('a/')) - self.assertTrue(p.is_relative_to(P('a/b'))) - self.assertTrue(p.is_relative_to('a/b')) - # With several args. - with self.assertWarns(DeprecationWarning): - p.is_relative_to('a', 'b') - # Unrelated paths. - self.assertFalse(p.is_relative_to(P('c'))) - self.assertFalse(p.is_relative_to(P('a/b/c'))) - self.assertFalse(p.is_relative_to(P('a/c'))) - self.assertFalse(p.is_relative_to(P('/a'))) - p = P('/a/b') - self.assertTrue(p.is_relative_to(P('/'))) - self.assertTrue(p.is_relative_to('/')) - self.assertTrue(p.is_relative_to(P('/a'))) - self.assertTrue(p.is_relative_to('/a')) - self.assertTrue(p.is_relative_to('/a/')) - self.assertTrue(p.is_relative_to(P('/a/b'))) - self.assertTrue(p.is_relative_to('/a/b')) - # Unrelated paths. - self.assertFalse(p.is_relative_to(P('/c'))) - self.assertFalse(p.is_relative_to(P('/a/b/c'))) - self.assertFalse(p.is_relative_to(P('/a/c'))) - self.assertFalse(p.is_relative_to(P())) - self.assertFalse(p.is_relative_to('')) - self.assertFalse(p.is_relative_to(P('a'))) - - def test_pickling_common(self): - P = self.cls - p = P('/a/b') - for proto in range(0, pickle.HIGHEST_PROTOCOL + 1): - dumped = pickle.dumps(p, proto) - pp = pickle.loads(dumped) - self.assertIs(pp.__class__, p.__class__) - self.assertEqual(pp, p) - self.assertEqual(hash(pp), hash(p)) - self.assertEqual(str(pp), str(p)) - - -class PurePosixPathTest(PurePathTest): - cls = pathlib.PurePosixPath - - def test_drive_root_parts(self): - check = self._check_drive_root_parts - # Collapsing of excess leading slashes, except for the double-slash - # special case. - check(('//a', 'b'), '', '//', ('//', 'a', 'b')) - check(('///a', 'b'), '', '/', ('/', 'a', 'b')) - check(('////a', 'b'), '', '/', ('/', 'a', 'b')) - # Paths which look like NT paths aren't treated specially. - check(('c:a',), '', '', ('c:a',)) - check(('c:\\a',), '', '', ('c:\\a',)) - check(('\\a',), '', '', ('\\a',)) - - def test_root(self): - P = self.cls - self.assertEqual(P('/a/b').root, '/') - self.assertEqual(P('///a/b').root, '/') - # POSIX special case for two leading slashes. - self.assertEqual(P('//a/b').root, '//') - - def test_eq(self): - P = self.cls - self.assertNotEqual(P('a/b'), P('A/b')) - self.assertEqual(P('/a'), P('///a')) - self.assertNotEqual(P('/a'), P('//a')) - - def test_as_uri(self): - P = self.cls - self.assertEqual(P('/').as_uri(), 'file:///') - self.assertEqual(P('/a/b.c').as_uri(), 'file:///a/b.c') - self.assertEqual(P('/a/b%#c').as_uri(), 'file:///a/b%25%23c') - - def test_as_uri_non_ascii(self): - from urllib.parse import quote_from_bytes - P = self.cls - try: - os.fsencode('\xe9') - except UnicodeEncodeError: - self.skipTest("\\xe9 cannot be encoded to the filesystem encoding") - self.assertEqual(P('/a/b\xe9').as_uri(), - 'file:///a/b' + quote_from_bytes(os.fsencode('\xe9'))) - - def test_match(self): - P = self.cls - self.assertFalse(P('A.py').match('a.PY')) - - def test_is_absolute(self): - P = self.cls - self.assertFalse(P().is_absolute()) - self.assertFalse(P('a').is_absolute()) - self.assertFalse(P('a/b/').is_absolute()) - self.assertTrue(P('/').is_absolute()) - self.assertTrue(P('/a').is_absolute()) - self.assertTrue(P('/a/b/').is_absolute()) - self.assertTrue(P('//a').is_absolute()) - self.assertTrue(P('//a/b').is_absolute()) - - def test_is_reserved(self): - P = self.cls - self.assertIs(False, P('').is_reserved()) - self.assertIs(False, P('/').is_reserved()) - self.assertIs(False, P('/foo/bar').is_reserved()) - self.assertIs(False, P('/dev/con/PRN/NUL').is_reserved()) - - def test_join(self): - P = self.cls - p = P('//a') - pp = p.joinpath('b') - self.assertEqual(pp, P('//a/b')) - pp = P('/a').joinpath('//c') - self.assertEqual(pp, P('//c')) - pp = P('//a').joinpath('/c') - self.assertEqual(pp, P('/c')) - - def test_div(self): - # Basically the same as joinpath(). - P = self.cls - p = P('//a') - pp = p / 'b' - self.assertEqual(pp, P('//a/b')) - pp = P('/a') / '//c' - self.assertEqual(pp, P('//c')) - pp = P('//a') / '/c' - self.assertEqual(pp, P('/c')) - - def test_parse_windows_path(self): - P = self.cls - p = P('c:', 'a', 'b') - pp = P(pathlib.PureWindowsPath('c:\\a\\b')) - self.assertEqual(p, pp) - - -class PureWindowsPathTest(PurePathTest): - cls = pathlib.PureWindowsPath - - equivalences = PurePathTest.equivalences.copy() - equivalences.update({ - './a:b': [ ('./a:b',) ], - 'c:a': [ ('c:', 'a'), ('c:', 'a/'), ('.', 'c:', 'a') ], - 'c:/a': [ - ('c:/', 'a'), ('c:', '/', 'a'), ('c:', '/a'), - ('/z', 'c:/', 'a'), ('//x/y', 'c:/', 'a'), - ], - '//a/b/': [ ('//a/b',) ], - '//a/b/c': [ - ('//a/b', 'c'), ('//a/b/', 'c'), - ], - }) - - def test_drive_root_parts(self): - check = self._check_drive_root_parts - # First part is anchored. - check(('c:',), 'c:', '', ('c:',)) - check(('c:/',), 'c:', '\\', ('c:\\',)) - check(('/',), '', '\\', ('\\',)) - check(('c:a',), 'c:', '', ('c:', 'a')) - check(('c:/a',), 'c:', '\\', ('c:\\', 'a')) - check(('/a',), '', '\\', ('\\', 'a')) - # UNC paths. - check(('//',), '\\\\', '', ('\\\\',)) - check(('//a',), '\\\\a', '', ('\\\\a',)) - check(('//a/',), '\\\\a\\', '', ('\\\\a\\',)) - check(('//a/b',), '\\\\a\\b', '\\', ('\\\\a\\b\\',)) - check(('//a/b/',), '\\\\a\\b', '\\', ('\\\\a\\b\\',)) - check(('//a/b/c',), '\\\\a\\b', '\\', ('\\\\a\\b\\', 'c')) - # Second part is anchored, so that the first part is ignored. - check(('a', 'Z:b', 'c'), 'Z:', '', ('Z:', 'b', 'c')) - check(('a', 'Z:/b', 'c'), 'Z:', '\\', ('Z:\\', 'b', 'c')) - # UNC paths. - check(('a', '//b/c', 'd'), '\\\\b\\c', '\\', ('\\\\b\\c\\', 'd')) - # Collapsing and stripping excess slashes. - check(('a', 'Z://b//c/', 'd/'), 'Z:', '\\', ('Z:\\', 'b', 'c', 'd')) - # UNC paths. - check(('a', '//b/c//', 'd'), '\\\\b\\c', '\\', ('\\\\b\\c\\', 'd')) - # Extended paths. - check(('//./c:',), '\\\\.\\c:', '', ('\\\\.\\c:',)) - check(('//?/c:/',), '\\\\?\\c:', '\\', ('\\\\?\\c:\\',)) - check(('//?/c:/a',), '\\\\?\\c:', '\\', ('\\\\?\\c:\\', 'a')) - check(('//?/c:/a', '/b'), '\\\\?\\c:', '\\', ('\\\\?\\c:\\', 'b')) - # Extended UNC paths (format is "\\?\UNC\server\share"). - check(('//?',), '\\\\?', '', ('\\\\?',)) - check(('//?/',), '\\\\?\\', '', ('\\\\?\\',)) - check(('//?/UNC',), '\\\\?\\UNC', '', ('\\\\?\\UNC',)) - check(('//?/UNC/',), '\\\\?\\UNC\\', '', ('\\\\?\\UNC\\',)) - check(('//?/UNC/b',), '\\\\?\\UNC\\b', '', ('\\\\?\\UNC\\b',)) - check(('//?/UNC/b/',), '\\\\?\\UNC\\b\\', '', ('\\\\?\\UNC\\b\\',)) - check(('//?/UNC/b/c',), '\\\\?\\UNC\\b\\c', '\\', ('\\\\?\\UNC\\b\\c\\',)) - check(('//?/UNC/b/c/',), '\\\\?\\UNC\\b\\c', '\\', ('\\\\?\\UNC\\b\\c\\',)) - check(('//?/UNC/b/c/d',), '\\\\?\\UNC\\b\\c', '\\', ('\\\\?\\UNC\\b\\c\\', 'd')) - # UNC device paths - check(('//./BootPartition/',), '\\\\.\\BootPartition', '\\', ('\\\\.\\BootPartition\\',)) - check(('//?/BootPartition/',), '\\\\?\\BootPartition', '\\', ('\\\\?\\BootPartition\\',)) - check(('//./PhysicalDrive0',), '\\\\.\\PhysicalDrive0', '', ('\\\\.\\PhysicalDrive0',)) - check(('//?/Volume{}/',), '\\\\?\\Volume{}', '\\', ('\\\\?\\Volume{}\\',)) - check(('//./nul',), '\\\\.\\nul', '', ('\\\\.\\nul',)) - # Second part has a root but not drive. - check(('a', '/b', 'c'), '', '\\', ('\\', 'b', 'c')) - check(('Z:/a', '/b', 'c'), 'Z:', '\\', ('Z:\\', 'b', 'c')) - check(('//?/Z:/a', '/b', 'c'), '\\\\?\\Z:', '\\', ('\\\\?\\Z:\\', 'b', 'c')) - # Joining with the same drive => the first path is appended to if - # the second path is relative. - check(('c:/a/b', 'c:x/y'), 'c:', '\\', ('c:\\', 'a', 'b', 'x', 'y')) - check(('c:/a/b', 'c:/x/y'), 'c:', '\\', ('c:\\', 'x', 'y')) - # Paths to files with NTFS alternate data streams - check(('./c:s',), '', '', ('c:s',)) - check(('cc:s',), '', '', ('cc:s',)) - check(('C:c:s',), 'C:', '', ('C:', 'c:s')) - check(('C:/c:s',), 'C:', '\\', ('C:\\', 'c:s')) - check(('D:a', './c:b'), 'D:', '', ('D:', 'a', 'c:b')) - check(('D:/a', './c:b'), 'D:', '\\', ('D:\\', 'a', 'c:b')) - - def test_str(self): - p = self.cls('a/b/c') - self.assertEqual(str(p), 'a\\b\\c') - p = self.cls('c:/a/b/c') - self.assertEqual(str(p), 'c:\\a\\b\\c') - p = self.cls('//a/b') - self.assertEqual(str(p), '\\\\a\\b\\') - p = self.cls('//a/b/c') - self.assertEqual(str(p), '\\\\a\\b\\c') - p = self.cls('//a/b/c/d') - self.assertEqual(str(p), '\\\\a\\b\\c\\d') - - def test_str_subclass(self): - self._check_str_subclass('.\\a:b') - self._check_str_subclass('c:') - self._check_str_subclass('c:a') - self._check_str_subclass('c:a\\b.txt') - self._check_str_subclass('c:\\') - self._check_str_subclass('c:\\a') - self._check_str_subclass('c:\\a\\b.txt') - self._check_str_subclass('\\\\some\\share') - self._check_str_subclass('\\\\some\\share\\a') - self._check_str_subclass('\\\\some\\share\\a\\b.txt') - - def test_eq(self): - P = self.cls - self.assertEqual(P('c:a/b'), P('c:a/b')) - self.assertEqual(P('c:a/b'), P('c:', 'a', 'b')) - self.assertNotEqual(P('c:a/b'), P('d:a/b')) - self.assertNotEqual(P('c:a/b'), P('c:/a/b')) - self.assertNotEqual(P('/a/b'), P('c:/a/b')) - # Case-insensitivity. - self.assertEqual(P('a/B'), P('A/b')) - self.assertEqual(P('C:a/B'), P('c:A/b')) - self.assertEqual(P('//Some/SHARE/a/B'), P('//somE/share/A/b')) - self.assertEqual(P('\u0130'), P('i\u0307')) - - def test_as_uri(self): - P = self.cls - with self.assertRaises(ValueError): - P('/a/b').as_uri() - with self.assertRaises(ValueError): - P('c:a/b').as_uri() - self.assertEqual(P('c:/').as_uri(), 'file:///c:/') - self.assertEqual(P('c:/a/b.c').as_uri(), 'file:///c:/a/b.c') - self.assertEqual(P('c:/a/b%#c').as_uri(), 'file:///c:/a/b%25%23c') - self.assertEqual(P('c:/a/b\xe9').as_uri(), 'file:///c:/a/b%C3%A9') - self.assertEqual(P('//some/share/').as_uri(), 'file://some/share/') - self.assertEqual(P('//some/share/a/b.c').as_uri(), - 'file://some/share/a/b.c') - self.assertEqual(P('//some/share/a/b%#c\xe9').as_uri(), - 'file://some/share/a/b%25%23c%C3%A9') - - def test_match(self): - P = self.cls - # Absolute patterns. - self.assertTrue(P('c:/b.py').match('*:/*.py')) - self.assertTrue(P('c:/b.py').match('c:/*.py')) - self.assertFalse(P('d:/b.py').match('c:/*.py')) # wrong drive - self.assertFalse(P('b.py').match('/*.py')) - self.assertFalse(P('b.py').match('c:*.py')) - self.assertFalse(P('b.py').match('c:/*.py')) - self.assertFalse(P('c:b.py').match('/*.py')) - self.assertFalse(P('c:b.py').match('c:/*.py')) - self.assertFalse(P('/b.py').match('c:*.py')) - self.assertFalse(P('/b.py').match('c:/*.py')) - # UNC patterns. - self.assertTrue(P('//some/share/a.py').match('//*/*/*.py')) - self.assertTrue(P('//some/share/a.py').match('//some/share/*.py')) - self.assertFalse(P('//other/share/a.py').match('//some/share/*.py')) - self.assertFalse(P('//some/share/a/b.py').match('//some/share/*.py')) - # Case-insensitivity. - self.assertTrue(P('B.py').match('b.PY')) - self.assertTrue(P('c:/a/B.Py').match('C:/A/*.pY')) - self.assertTrue(P('//Some/Share/B.Py').match('//somE/sharE/*.pY')) - # Path anchor doesn't match pattern anchor - self.assertFalse(P('c:/b.py').match('/*.py')) # 'c:/' vs '/' - self.assertFalse(P('c:/b.py').match('c:*.py')) # 'c:/' vs 'c:' - self.assertFalse(P('//some/share/a.py').match('/*.py')) # '//some/share/' vs '/' - - def test_ordering_common(self): - # Case-insensitivity. - def assertOrderedEqual(a, b): - self.assertLessEqual(a, b) - self.assertGreaterEqual(b, a) - P = self.cls - p = P('c:A/b') - q = P('C:a/B') - assertOrderedEqual(p, q) - self.assertFalse(p < q) - self.assertFalse(p > q) - p = P('//some/Share/A/b') - q = P('//Some/SHARE/a/B') - assertOrderedEqual(p, q) - self.assertFalse(p < q) - self.assertFalse(p > q) - - def test_parts(self): - P = self.cls - p = P('c:a/b') - parts = p.parts - self.assertEqual(parts, ('c:', 'a', 'b')) - p = P('c:/a/b') - parts = p.parts - self.assertEqual(parts, ('c:\\', 'a', 'b')) - p = P('//a/b/c/d') - parts = p.parts - self.assertEqual(parts, ('\\\\a\\b\\', 'c', 'd')) - - def test_parent(self): - # Anchored - P = self.cls - p = P('z:a/b/c') - self.assertEqual(p.parent, P('z:a/b')) - self.assertEqual(p.parent.parent, P('z:a')) - self.assertEqual(p.parent.parent.parent, P('z:')) - self.assertEqual(p.parent.parent.parent.parent, P('z:')) - p = P('z:/a/b/c') - self.assertEqual(p.parent, P('z:/a/b')) - self.assertEqual(p.parent.parent, P('z:/a')) - self.assertEqual(p.parent.parent.parent, P('z:/')) - self.assertEqual(p.parent.parent.parent.parent, P('z:/')) - p = P('//a/b/c/d') - self.assertEqual(p.parent, P('//a/b/c')) - self.assertEqual(p.parent.parent, P('//a/b')) - self.assertEqual(p.parent.parent.parent, P('//a/b')) - - def test_parents(self): - # Anchored - P = self.cls - p = P('z:a/b/') - par = p.parents - self.assertEqual(len(par), 2) - self.assertEqual(par[0], P('z:a')) - self.assertEqual(par[1], P('z:')) - self.assertEqual(par[0:1], (P('z:a'),)) - self.assertEqual(par[:-1], (P('z:a'),)) - self.assertEqual(par[:2], (P('z:a'), P('z:'))) - self.assertEqual(par[1:], (P('z:'),)) - self.assertEqual(par[::2], (P('z:a'),)) - self.assertEqual(par[::-1], (P('z:'), P('z:a'))) - self.assertEqual(list(par), [P('z:a'), P('z:')]) - with self.assertRaises(IndexError): - par[2] - p = P('z:/a/b/') - par = p.parents - self.assertEqual(len(par), 2) - self.assertEqual(par[0], P('z:/a')) - self.assertEqual(par[1], P('z:/')) - self.assertEqual(par[0:1], (P('z:/a'),)) - self.assertEqual(par[0:-1], (P('z:/a'),)) - self.assertEqual(par[:2], (P('z:/a'), P('z:/'))) - self.assertEqual(par[1:], (P('z:/'),)) - self.assertEqual(par[::2], (P('z:/a'),)) - self.assertEqual(par[::-1], (P('z:/'), P('z:/a'),)) - self.assertEqual(list(par), [P('z:/a'), P('z:/')]) - with self.assertRaises(IndexError): - par[2] - p = P('//a/b/c/d') - par = p.parents - self.assertEqual(len(par), 2) - self.assertEqual(par[0], P('//a/b/c')) - self.assertEqual(par[1], P('//a/b')) - self.assertEqual(par[0:1], (P('//a/b/c'),)) - self.assertEqual(par[0:-1], (P('//a/b/c'),)) - self.assertEqual(par[:2], (P('//a/b/c'), P('//a/b'))) - self.assertEqual(par[1:], (P('//a/b'),)) - self.assertEqual(par[::2], (P('//a/b/c'),)) - self.assertEqual(par[::-1], (P('//a/b'), P('//a/b/c'))) - self.assertEqual(list(par), [P('//a/b/c'), P('//a/b')]) - with self.assertRaises(IndexError): - par[2] - - def test_drive(self): - P = self.cls - self.assertEqual(P('c:').drive, 'c:') - self.assertEqual(P('c:a/b').drive, 'c:') - self.assertEqual(P('c:/').drive, 'c:') - self.assertEqual(P('c:/a/b/').drive, 'c:') - self.assertEqual(P('//a/b').drive, '\\\\a\\b') - self.assertEqual(P('//a/b/').drive, '\\\\a\\b') - self.assertEqual(P('//a/b/c/d').drive, '\\\\a\\b') - self.assertEqual(P('./c:a').drive, '') - - def test_root(self): - P = self.cls - self.assertEqual(P('c:').root, '') - self.assertEqual(P('c:a/b').root, '') - self.assertEqual(P('c:/').root, '\\') - self.assertEqual(P('c:/a/b/').root, '\\') - self.assertEqual(P('//a/b').root, '\\') - self.assertEqual(P('//a/b/').root, '\\') - self.assertEqual(P('//a/b/c/d').root, '\\') - - def test_anchor(self): - P = self.cls - self.assertEqual(P('c:').anchor, 'c:') - self.assertEqual(P('c:a/b').anchor, 'c:') - self.assertEqual(P('c:/').anchor, 'c:\\') - self.assertEqual(P('c:/a/b/').anchor, 'c:\\') - self.assertEqual(P('//a/b').anchor, '\\\\a\\b\\') - self.assertEqual(P('//a/b/').anchor, '\\\\a\\b\\') - self.assertEqual(P('//a/b/c/d').anchor, '\\\\a\\b\\') - - def test_name(self): - P = self.cls - self.assertEqual(P('c:').name, '') - self.assertEqual(P('c:/').name, '') - self.assertEqual(P('c:a/b').name, 'b') - self.assertEqual(P('c:/a/b').name, 'b') - self.assertEqual(P('c:a/b.py').name, 'b.py') - self.assertEqual(P('c:/a/b.py').name, 'b.py') - self.assertEqual(P('//My.py/Share.php').name, '') - self.assertEqual(P('//My.py/Share.php/a/b').name, 'b') - - def test_suffix(self): - P = self.cls - self.assertEqual(P('c:').suffix, '') - self.assertEqual(P('c:/').suffix, '') - self.assertEqual(P('c:a/b').suffix, '') - self.assertEqual(P('c:/a/b').suffix, '') - self.assertEqual(P('c:a/b.py').suffix, '.py') - self.assertEqual(P('c:/a/b.py').suffix, '.py') - self.assertEqual(P('c:a/.hgrc').suffix, '') - self.assertEqual(P('c:/a/.hgrc').suffix, '') - self.assertEqual(P('c:a/.hg.rc').suffix, '.rc') - self.assertEqual(P('c:/a/.hg.rc').suffix, '.rc') - self.assertEqual(P('c:a/b.tar.gz').suffix, '.gz') - self.assertEqual(P('c:/a/b.tar.gz').suffix, '.gz') - self.assertEqual(P('c:a/Some name. Ending with a dot.').suffix, '') - self.assertEqual(P('c:/a/Some name. Ending with a dot.').suffix, '') - self.assertEqual(P('//My.py/Share.php').suffix, '') - self.assertEqual(P('//My.py/Share.php/a/b').suffix, '') - - def test_suffixes(self): - P = self.cls - self.assertEqual(P('c:').suffixes, []) - self.assertEqual(P('c:/').suffixes, []) - self.assertEqual(P('c:a/b').suffixes, []) - self.assertEqual(P('c:/a/b').suffixes, []) - self.assertEqual(P('c:a/b.py').suffixes, ['.py']) - self.assertEqual(P('c:/a/b.py').suffixes, ['.py']) - self.assertEqual(P('c:a/.hgrc').suffixes, []) - self.assertEqual(P('c:/a/.hgrc').suffixes, []) - self.assertEqual(P('c:a/.hg.rc').suffixes, ['.rc']) - self.assertEqual(P('c:/a/.hg.rc').suffixes, ['.rc']) - self.assertEqual(P('c:a/b.tar.gz').suffixes, ['.tar', '.gz']) - self.assertEqual(P('c:/a/b.tar.gz').suffixes, ['.tar', '.gz']) - self.assertEqual(P('//My.py/Share.php').suffixes, []) - self.assertEqual(P('//My.py/Share.php/a/b').suffixes, []) - self.assertEqual(P('c:a/Some name. Ending with a dot.').suffixes, []) - self.assertEqual(P('c:/a/Some name. Ending with a dot.').suffixes, []) - - def test_stem(self): - P = self.cls - self.assertEqual(P('c:').stem, '') - self.assertEqual(P('c:.').stem, '') - self.assertEqual(P('c:..').stem, '..') - self.assertEqual(P('c:/').stem, '') - self.assertEqual(P('c:a/b').stem, 'b') - self.assertEqual(P('c:a/b.py').stem, 'b') - self.assertEqual(P('c:a/.hgrc').stem, '.hgrc') - self.assertEqual(P('c:a/.hg.rc').stem, '.hg') - self.assertEqual(P('c:a/b.tar.gz').stem, 'b.tar') - self.assertEqual(P('c:a/Some name. Ending with a dot.').stem, - 'Some name. Ending with a dot.') - - def test_with_name(self): - P = self.cls - self.assertEqual(P('c:a/b').with_name('d.xml'), P('c:a/d.xml')) - self.assertEqual(P('c:/a/b').with_name('d.xml'), P('c:/a/d.xml')) - self.assertEqual(P('c:a/Dot ending.').with_name('d.xml'), P('c:a/d.xml')) - self.assertEqual(P('c:/a/Dot ending.').with_name('d.xml'), P('c:/a/d.xml')) - self.assertRaises(ValueError, P('c:').with_name, 'd.xml') - self.assertRaises(ValueError, P('c:/').with_name, 'd.xml') - self.assertRaises(ValueError, P('//My/Share').with_name, 'd.xml') - self.assertRaises(ValueError, P('c:a/b').with_name, 'd:') - self.assertRaises(ValueError, P('c:a/b').with_name, 'd:e') - self.assertRaises(ValueError, P('c:a/b').with_name, 'd:/e') - self.assertRaises(ValueError, P('c:a/b').with_name, '//My/Share') - - def test_with_stem(self): - P = self.cls - self.assertEqual(P('c:a/b').with_stem('d'), P('c:a/d')) - self.assertEqual(P('c:/a/b').with_stem('d'), P('c:/a/d')) - self.assertEqual(P('c:a/Dot ending.').with_stem('d'), P('c:a/d')) - self.assertEqual(P('c:/a/Dot ending.').with_stem('d'), P('c:/a/d')) - self.assertRaises(ValueError, P('c:').with_stem, 'd') - self.assertRaises(ValueError, P('c:/').with_stem, 'd') - self.assertRaises(ValueError, P('//My/Share').with_stem, 'd') - self.assertRaises(ValueError, P('c:a/b').with_stem, 'd:') - self.assertRaises(ValueError, P('c:a/b').with_stem, 'd:e') - self.assertRaises(ValueError, P('c:a/b').with_stem, 'd:/e') - self.assertRaises(ValueError, P('c:a/b').with_stem, '//My/Share') - - def test_with_suffix(self): - P = self.cls - self.assertEqual(P('c:a/b').with_suffix('.gz'), P('c:a/b.gz')) - self.assertEqual(P('c:/a/b').with_suffix('.gz'), P('c:/a/b.gz')) - self.assertEqual(P('c:a/b.py').with_suffix('.gz'), P('c:a/b.gz')) - self.assertEqual(P('c:/a/b.py').with_suffix('.gz'), P('c:/a/b.gz')) - # Path doesn't have a "filename" component. - self.assertRaises(ValueError, P('').with_suffix, '.gz') - self.assertRaises(ValueError, P('.').with_suffix, '.gz') - self.assertRaises(ValueError, P('/').with_suffix, '.gz') - self.assertRaises(ValueError, P('//My/Share').with_suffix, '.gz') - # Invalid suffix. - self.assertRaises(ValueError, P('c:a/b').with_suffix, 'gz') - self.assertRaises(ValueError, P('c:a/b').with_suffix, '/') - self.assertRaises(ValueError, P('c:a/b').with_suffix, '\\') - self.assertRaises(ValueError, P('c:a/b').with_suffix, 'c:') - self.assertRaises(ValueError, P('c:a/b').with_suffix, '/.gz') - self.assertRaises(ValueError, P('c:a/b').with_suffix, '\\.gz') - self.assertRaises(ValueError, P('c:a/b').with_suffix, 'c:.gz') - self.assertRaises(ValueError, P('c:a/b').with_suffix, 'c/d') - self.assertRaises(ValueError, P('c:a/b').with_suffix, 'c\\d') - self.assertRaises(ValueError, P('c:a/b').with_suffix, '.c/d') - self.assertRaises(ValueError, P('c:a/b').with_suffix, '.c\\d') - - def test_relative_to(self): - P = self.cls - p = P('C:Foo/Bar') - self.assertEqual(p.relative_to(P('c:')), P('Foo/Bar')) - self.assertEqual(p.relative_to('c:'), P('Foo/Bar')) - self.assertEqual(p.relative_to(P('c:foO')), P('Bar')) - self.assertEqual(p.relative_to('c:foO'), P('Bar')) - self.assertEqual(p.relative_to('c:foO/'), P('Bar')) - self.assertEqual(p.relative_to(P('c:foO/baR')), P()) - self.assertEqual(p.relative_to('c:foO/baR'), P()) - self.assertEqual(p.relative_to(P('c:'), walk_up=True), P('Foo/Bar')) - self.assertEqual(p.relative_to('c:', walk_up=True), P('Foo/Bar')) - self.assertEqual(p.relative_to(P('c:foO'), walk_up=True), P('Bar')) - self.assertEqual(p.relative_to('c:foO', walk_up=True), P('Bar')) - self.assertEqual(p.relative_to('c:foO/', walk_up=True), P('Bar')) - self.assertEqual(p.relative_to(P('c:foO/baR'), walk_up=True), P()) - self.assertEqual(p.relative_to('c:foO/baR', walk_up=True), P()) - self.assertEqual(p.relative_to(P('C:Foo/Bar/Baz'), walk_up=True), P('..')) - self.assertEqual(p.relative_to(P('C:Foo/Baz'), walk_up=True), P('../Bar')) - self.assertEqual(p.relative_to(P('C:Baz/Bar'), walk_up=True), P('../../Foo/Bar')) - # Unrelated paths. - self.assertRaises(ValueError, p.relative_to, P()) - self.assertRaises(ValueError, p.relative_to, '') - self.assertRaises(ValueError, p.relative_to, P('d:')) - self.assertRaises(ValueError, p.relative_to, P('/')) - self.assertRaises(ValueError, p.relative_to, P('Foo')) - self.assertRaises(ValueError, p.relative_to, P('/Foo')) - self.assertRaises(ValueError, p.relative_to, P('C:/Foo')) - self.assertRaises(ValueError, p.relative_to, P('C:Foo/Bar/Baz')) - self.assertRaises(ValueError, p.relative_to, P('C:Foo/Baz')) - self.assertRaises(ValueError, p.relative_to, P(), walk_up=True) - self.assertRaises(ValueError, p.relative_to, '', walk_up=True) - self.assertRaises(ValueError, p.relative_to, P('d:'), walk_up=True) - self.assertRaises(ValueError, p.relative_to, P('/'), walk_up=True) - self.assertRaises(ValueError, p.relative_to, P('Foo'), walk_up=True) - self.assertRaises(ValueError, p.relative_to, P('/Foo'), walk_up=True) - self.assertRaises(ValueError, p.relative_to, P('C:/Foo'), walk_up=True) - p = P('C:/Foo/Bar') - self.assertEqual(p.relative_to(P('c:/')), P('Foo/Bar')) - self.assertEqual(p.relative_to('c:/'), P('Foo/Bar')) - self.assertEqual(p.relative_to(P('c:/foO')), P('Bar')) - self.assertEqual(p.relative_to('c:/foO'), P('Bar')) - self.assertEqual(p.relative_to('c:/foO/'), P('Bar')) - self.assertEqual(p.relative_to(P('c:/foO/baR')), P()) - self.assertEqual(p.relative_to('c:/foO/baR'), P()) - self.assertEqual(p.relative_to(P('c:/'), walk_up=True), P('Foo/Bar')) - self.assertEqual(p.relative_to('c:/', walk_up=True), P('Foo/Bar')) - self.assertEqual(p.relative_to(P('c:/foO'), walk_up=True), P('Bar')) - self.assertEqual(p.relative_to('c:/foO', walk_up=True), P('Bar')) - self.assertEqual(p.relative_to('c:/foO/', walk_up=True), P('Bar')) - self.assertEqual(p.relative_to(P('c:/foO/baR'), walk_up=True), P()) - self.assertEqual(p.relative_to('c:/foO/baR', walk_up=True), P()) - self.assertEqual(p.relative_to('C:/Baz', walk_up=True), P('../Foo/Bar')) - self.assertEqual(p.relative_to('C:/Foo/Bar/Baz', walk_up=True), P('..')) - self.assertEqual(p.relative_to('C:/Foo/Baz', walk_up=True), P('../Bar')) - # Unrelated paths. - self.assertRaises(ValueError, p.relative_to, 'c:') - self.assertRaises(ValueError, p.relative_to, P('c:')) - self.assertRaises(ValueError, p.relative_to, P('C:/Baz')) - self.assertRaises(ValueError, p.relative_to, P('C:/Foo/Bar/Baz')) - self.assertRaises(ValueError, p.relative_to, P('C:/Foo/Baz')) - self.assertRaises(ValueError, p.relative_to, P('C:Foo')) - self.assertRaises(ValueError, p.relative_to, P('d:')) - self.assertRaises(ValueError, p.relative_to, P('d:/')) - self.assertRaises(ValueError, p.relative_to, P('/')) - self.assertRaises(ValueError, p.relative_to, P('/Foo')) - self.assertRaises(ValueError, p.relative_to, P('//C/Foo')) - self.assertRaises(ValueError, p.relative_to, 'c:', walk_up=True) - self.assertRaises(ValueError, p.relative_to, P('c:'), walk_up=True) - self.assertRaises(ValueError, p.relative_to, P('C:Foo'), walk_up=True) - self.assertRaises(ValueError, p.relative_to, P('d:'), walk_up=True) - self.assertRaises(ValueError, p.relative_to, P('d:/'), walk_up=True) - self.assertRaises(ValueError, p.relative_to, P('/'), walk_up=True) - self.assertRaises(ValueError, p.relative_to, P('/Foo'), walk_up=True) - self.assertRaises(ValueError, p.relative_to, P('//C/Foo'), walk_up=True) - # UNC paths. - p = P('//Server/Share/Foo/Bar') - self.assertEqual(p.relative_to(P('//sErver/sHare')), P('Foo/Bar')) - self.assertEqual(p.relative_to('//sErver/sHare'), P('Foo/Bar')) - self.assertEqual(p.relative_to('//sErver/sHare/'), P('Foo/Bar')) - self.assertEqual(p.relative_to(P('//sErver/sHare/Foo')), P('Bar')) - self.assertEqual(p.relative_to('//sErver/sHare/Foo'), P('Bar')) - self.assertEqual(p.relative_to('//sErver/sHare/Foo/'), P('Bar')) - self.assertEqual(p.relative_to(P('//sErver/sHare/Foo/Bar')), P()) - self.assertEqual(p.relative_to('//sErver/sHare/Foo/Bar'), P()) - self.assertEqual(p.relative_to(P('//sErver/sHare'), walk_up=True), P('Foo/Bar')) - self.assertEqual(p.relative_to('//sErver/sHare', walk_up=True), P('Foo/Bar')) - self.assertEqual(p.relative_to('//sErver/sHare/', walk_up=True), P('Foo/Bar')) - self.assertEqual(p.relative_to(P('//sErver/sHare/Foo'), walk_up=True), P('Bar')) - self.assertEqual(p.relative_to('//sErver/sHare/Foo', walk_up=True), P('Bar')) - self.assertEqual(p.relative_to('//sErver/sHare/Foo/', walk_up=True), P('Bar')) - self.assertEqual(p.relative_to(P('//sErver/sHare/Foo/Bar'), walk_up=True), P()) - self.assertEqual(p.relative_to('//sErver/sHare/Foo/Bar', walk_up=True), P()) - self.assertEqual(p.relative_to(P('//sErver/sHare/bar'), walk_up=True), P('../Foo/Bar')) - self.assertEqual(p.relative_to('//sErver/sHare/bar', walk_up=True), P('../Foo/Bar')) - # Unrelated paths. - self.assertRaises(ValueError, p.relative_to, P('/Server/Share/Foo')) - self.assertRaises(ValueError, p.relative_to, P('c:/Server/Share/Foo')) - self.assertRaises(ValueError, p.relative_to, P('//z/Share/Foo')) - self.assertRaises(ValueError, p.relative_to, P('//Server/z/Foo')) - self.assertRaises(ValueError, p.relative_to, P('/Server/Share/Foo'), walk_up=True) - self.assertRaises(ValueError, p.relative_to, P('c:/Server/Share/Foo'), walk_up=True) - self.assertRaises(ValueError, p.relative_to, P('//z/Share/Foo'), walk_up=True) - self.assertRaises(ValueError, p.relative_to, P('//Server/z/Foo'), walk_up=True) - - def test_is_relative_to(self): - P = self.cls - p = P('C:Foo/Bar') - self.assertTrue(p.is_relative_to(P('c:'))) - self.assertTrue(p.is_relative_to('c:')) - self.assertTrue(p.is_relative_to(P('c:foO'))) - self.assertTrue(p.is_relative_to('c:foO')) - self.assertTrue(p.is_relative_to('c:foO/')) - self.assertTrue(p.is_relative_to(P('c:foO/baR'))) - self.assertTrue(p.is_relative_to('c:foO/baR')) - # Unrelated paths. - self.assertFalse(p.is_relative_to(P())) - self.assertFalse(p.is_relative_to('')) - self.assertFalse(p.is_relative_to(P('d:'))) - self.assertFalse(p.is_relative_to(P('/'))) - self.assertFalse(p.is_relative_to(P('Foo'))) - self.assertFalse(p.is_relative_to(P('/Foo'))) - self.assertFalse(p.is_relative_to(P('C:/Foo'))) - self.assertFalse(p.is_relative_to(P('C:Foo/Bar/Baz'))) - self.assertFalse(p.is_relative_to(P('C:Foo/Baz'))) - p = P('C:/Foo/Bar') - self.assertTrue(p.is_relative_to(P('c:/'))) - self.assertTrue(p.is_relative_to(P('c:/foO'))) - self.assertTrue(p.is_relative_to('c:/foO/')) - self.assertTrue(p.is_relative_to(P('c:/foO/baR'))) - self.assertTrue(p.is_relative_to('c:/foO/baR')) - # Unrelated paths. - self.assertFalse(p.is_relative_to('c:')) - self.assertFalse(p.is_relative_to(P('C:/Baz'))) - self.assertFalse(p.is_relative_to(P('C:/Foo/Bar/Baz'))) - self.assertFalse(p.is_relative_to(P('C:/Foo/Baz'))) - self.assertFalse(p.is_relative_to(P('C:Foo'))) - self.assertFalse(p.is_relative_to(P('d:'))) - self.assertFalse(p.is_relative_to(P('d:/'))) - self.assertFalse(p.is_relative_to(P('/'))) - self.assertFalse(p.is_relative_to(P('/Foo'))) - self.assertFalse(p.is_relative_to(P('//C/Foo'))) - # UNC paths. - p = P('//Server/Share/Foo/Bar') - self.assertTrue(p.is_relative_to(P('//sErver/sHare'))) - self.assertTrue(p.is_relative_to('//sErver/sHare')) - self.assertTrue(p.is_relative_to('//sErver/sHare/')) - self.assertTrue(p.is_relative_to(P('//sErver/sHare/Foo'))) - self.assertTrue(p.is_relative_to('//sErver/sHare/Foo')) - self.assertTrue(p.is_relative_to('//sErver/sHare/Foo/')) - self.assertTrue(p.is_relative_to(P('//sErver/sHare/Foo/Bar'))) - self.assertTrue(p.is_relative_to('//sErver/sHare/Foo/Bar')) - # Unrelated paths. - self.assertFalse(p.is_relative_to(P('/Server/Share/Foo'))) - self.assertFalse(p.is_relative_to(P('c:/Server/Share/Foo'))) - self.assertFalse(p.is_relative_to(P('//z/Share/Foo'))) - self.assertFalse(p.is_relative_to(P('//Server/z/Foo'))) - - def test_is_absolute(self): - P = self.cls - # Under NT, only paths with both a drive and a root are absolute. - self.assertFalse(P().is_absolute()) - self.assertFalse(P('a').is_absolute()) - self.assertFalse(P('a/b/').is_absolute()) - self.assertFalse(P('/').is_absolute()) - self.assertFalse(P('/a').is_absolute()) - self.assertFalse(P('/a/b/').is_absolute()) - self.assertFalse(P('c:').is_absolute()) - self.assertFalse(P('c:a').is_absolute()) - self.assertFalse(P('c:a/b/').is_absolute()) - self.assertTrue(P('c:/').is_absolute()) - self.assertTrue(P('c:/a').is_absolute()) - self.assertTrue(P('c:/a/b/').is_absolute()) - # UNC paths are absolute by definition. - self.assertTrue(P('//a/b').is_absolute()) - self.assertTrue(P('//a/b/').is_absolute()) - self.assertTrue(P('//a/b/c').is_absolute()) - self.assertTrue(P('//a/b/c/d').is_absolute()) - - def test_join(self): - P = self.cls - p = P('C:/a/b') - pp = p.joinpath('x/y') - self.assertEqual(pp, P('C:/a/b/x/y')) - pp = p.joinpath('/x/y') - self.assertEqual(pp, P('C:/x/y')) - # Joining with a different drive => the first path is ignored, even - # if the second path is relative. - pp = p.joinpath('D:x/y') - self.assertEqual(pp, P('D:x/y')) - pp = p.joinpath('D:/x/y') - self.assertEqual(pp, P('D:/x/y')) - pp = p.joinpath('//host/share/x/y') - self.assertEqual(pp, P('//host/share/x/y')) - # Joining with the same drive => the first path is appended to if - # the second path is relative. - pp = p.joinpath('c:x/y') - self.assertEqual(pp, P('C:/a/b/x/y')) - pp = p.joinpath('c:/x/y') - self.assertEqual(pp, P('C:/x/y')) - # Joining with files with NTFS data streams => the filename should - # not be parsed as a drive letter - pp = p.joinpath(P('./d:s')) - self.assertEqual(pp, P('C:/a/b/d:s')) - pp = p.joinpath(P('./dd:s')) - self.assertEqual(pp, P('C:/a/b/dd:s')) - pp = p.joinpath(P('E:d:s')) - self.assertEqual(pp, P('E:d:s')) - # Joining onto a UNC path with no root - pp = P('//').joinpath('server') - self.assertEqual(pp, P('//server')) - pp = P('//server').joinpath('share') - self.assertEqual(pp, P('//server/share')) - pp = P('//./BootPartition').joinpath('Windows') - self.assertEqual(pp, P('//./BootPartition/Windows')) - - def test_div(self): - # Basically the same as joinpath(). - P = self.cls - p = P('C:/a/b') - self.assertEqual(p / 'x/y', P('C:/a/b/x/y')) - self.assertEqual(p / 'x' / 'y', P('C:/a/b/x/y')) - self.assertEqual(p / '/x/y', P('C:/x/y')) - self.assertEqual(p / '/x' / 'y', P('C:/x/y')) - # Joining with a different drive => the first path is ignored, even - # if the second path is relative. - self.assertEqual(p / 'D:x/y', P('D:x/y')) - self.assertEqual(p / 'D:' / 'x/y', P('D:x/y')) - self.assertEqual(p / 'D:/x/y', P('D:/x/y')) - self.assertEqual(p / 'D:' / '/x/y', P('D:/x/y')) - self.assertEqual(p / '//host/share/x/y', P('//host/share/x/y')) - # Joining with the same drive => the first path is appended to if - # the second path is relative. - self.assertEqual(p / 'c:x/y', P('C:/a/b/x/y')) - self.assertEqual(p / 'c:/x/y', P('C:/x/y')) - # Joining with files with NTFS data streams => the filename should - # not be parsed as a drive letter - self.assertEqual(p / P('./d:s'), P('C:/a/b/d:s')) - self.assertEqual(p / P('./dd:s'), P('C:/a/b/dd:s')) - self.assertEqual(p / P('E:d:s'), P('E:d:s')) - - def test_is_reserved(self): - P = self.cls - self.assertIs(False, P('').is_reserved()) - self.assertIs(False, P('/').is_reserved()) - self.assertIs(False, P('/foo/bar').is_reserved()) - # UNC paths are never reserved. - self.assertIs(False, P('//my/share/nul/con/aux').is_reserved()) - # Case-insensitive DOS-device names are reserved. - self.assertIs(True, P('nul').is_reserved()) - self.assertIs(True, P('aux').is_reserved()) - self.assertIs(True, P('prn').is_reserved()) - self.assertIs(True, P('con').is_reserved()) - self.assertIs(True, P('conin$').is_reserved()) - self.assertIs(True, P('conout$').is_reserved()) - # COM/LPT + 1-9 or + superscript 1-3 are reserved. - self.assertIs(True, P('COM1').is_reserved()) - self.assertIs(True, P('LPT9').is_reserved()) - self.assertIs(True, P('com\xb9').is_reserved()) - self.assertIs(True, P('com\xb2').is_reserved()) - self.assertIs(True, P('lpt\xb3').is_reserved()) - # DOS-device name mataching ignores characters after a dot or - # a colon and also ignores trailing spaces. - self.assertIs(True, P('NUL.txt').is_reserved()) - self.assertIs(True, P('PRN ').is_reserved()) - self.assertIs(True, P('AUX .txt').is_reserved()) - self.assertIs(True, P('COM1:bar').is_reserved()) - self.assertIs(True, P('LPT9 :bar').is_reserved()) - # DOS-device names are only matched at the beginning - # of a path component. - self.assertIs(False, P('bar.com9').is_reserved()) - self.assertIs(False, P('bar.lpt9').is_reserved()) - # Only the last path component matters. - self.assertIs(True, P('c:/baz/con/NUL').is_reserved()) - self.assertIs(False, P('c:/NUL/con/baz').is_reserved()) - - -class PurePathSubclassTest(PurePathTest): - class cls(pathlib.PurePath): - pass - - # repr() roundtripping is not supported in custom subclass. - test_repr_roundtrips = None - - -@only_posix -class PosixPathAsPureTest(PurePosixPathTest): - cls = pathlib.PosixPath - -@only_nt -class WindowsPathAsPureTest(PureWindowsPathTest): - cls = pathlib.WindowsPath - - def test_owner(self): - P = self.cls - with self.assertRaises(pathlib.UnsupportedOperation): - P('c:/').owner() - - def test_group(self): - P = self.cls - with self.assertRaises(pathlib.UnsupportedOperation): - P('c:/').group() - - -# -# Tests for the concrete classes. -# - -class PathTest(unittest.TestCase): - """Tests for the FS-accessing functionalities of the Path classes.""" - - cls = pathlib.Path - can_symlink = os_helper.can_symlink() - - # (BASE) - # | - # |-- brokenLink -> non-existing - # |-- dirA - # | `-- linkC -> ../dirB - # |-- dirB - # | |-- fileB - # | `-- linkD -> ../dirB - # |-- dirC - # | |-- dirD - # | | `-- fileD - # | `-- fileC - # | `-- novel.txt - # |-- dirE # No permissions - # |-- fileA - # |-- linkA -> fileA - # |-- linkB -> dirB - # `-- brokenLinkLoop -> brokenLinkLoop - # - - def setUp(self): - def cleanup(): - os.chmod(join('dirE'), 0o777) - os_helper.rmtree(BASE) - self.addCleanup(cleanup) - os.mkdir(BASE) - os.mkdir(join('dirA')) - os.mkdir(join('dirB')) - os.mkdir(join('dirC')) - os.mkdir(join('dirC', 'dirD')) - os.mkdir(join('dirE')) - with open(join('fileA'), 'wb') as f: - f.write(b"this is file A\n") - with open(join('dirB', 'fileB'), 'wb') as f: - f.write(b"this is file B\n") - with open(join('dirC', 'fileC'), 'wb') as f: - f.write(b"this is file C\n") - with open(join('dirC', 'novel.txt'), 'wb') as f: - f.write(b"this is a novel\n") - with open(join('dirC', 'dirD', 'fileD'), 'wb') as f: - f.write(b"this is file D\n") - os.chmod(join('dirE'), 0) - if self.can_symlink: - # Relative symlinks. - os.symlink('fileA', join('linkA')) - os.symlink('non-existing', join('brokenLink')) - os.symlink('dirB', join('linkB'), target_is_directory=True) - os.symlink(os.path.join('..', 'dirB'), join('dirA', 'linkC'), target_is_directory=True) - # This one goes upwards, creating a loop. - os.symlink(os.path.join('..', 'dirB'), join('dirB', 'linkD'), target_is_directory=True) - # Broken symlink (pointing to itself). - os.symlink('brokenLinkLoop', join('brokenLinkLoop')) - - def assertFileNotFound(self, func, *args, **kwargs): - with self.assertRaises(FileNotFoundError) as cm: - func(*args, **kwargs) - self.assertEqual(cm.exception.errno, errno.ENOENT) - - def assertEqualNormCase(self, path_a, path_b): - self.assertEqual(os.path.normcase(path_a), os.path.normcase(path_b)) - - def test_samefile(self): - fileA_path = os.path.join(BASE, 'fileA') - fileB_path = os.path.join(BASE, 'dirB', 'fileB') - p = self.cls(fileA_path) - pp = self.cls(fileA_path) - q = self.cls(fileB_path) - self.assertTrue(p.samefile(fileA_path)) - self.assertTrue(p.samefile(pp)) - self.assertFalse(p.samefile(fileB_path)) - self.assertFalse(p.samefile(q)) - # Test the non-existent file case - non_existent = os.path.join(BASE, 'foo') - r = self.cls(non_existent) - self.assertRaises(FileNotFoundError, p.samefile, r) - self.assertRaises(FileNotFoundError, p.samefile, non_existent) - self.assertRaises(FileNotFoundError, r.samefile, p) - self.assertRaises(FileNotFoundError, r.samefile, non_existent) - self.assertRaises(FileNotFoundError, r.samefile, r) - self.assertRaises(FileNotFoundError, r.samefile, non_existent) - - def test_empty_path(self): - # The empty path points to '.' - p = self.cls('') - self.assertEqual(str(p), '.') - - def test_exists(self): - P = self.cls - p = P(BASE) - self.assertIs(True, p.exists()) - self.assertIs(True, (p / 'dirA').exists()) - self.assertIs(True, (p / 'fileA').exists()) - self.assertIs(False, (p / 'fileA' / 'bah').exists()) - if self.can_symlink: - self.assertIs(True, (p / 'linkA').exists()) - self.assertIs(True, (p / 'linkB').exists()) - self.assertIs(True, (p / 'linkB' / 'fileB').exists()) - self.assertIs(False, (p / 'linkA' / 'bah').exists()) - self.assertIs(False, (p / 'brokenLink').exists()) - self.assertIs(True, (p / 'brokenLink').exists(follow_symlinks=False)) - self.assertIs(False, (p / 'foo').exists()) - self.assertIs(False, P('/xyzzy').exists()) - self.assertIs(False, P(BASE + '\udfff').exists()) - self.assertIs(False, P(BASE + '\x00').exists()) - - def test_open_common(self): - p = self.cls(BASE) - with (p / 'fileA').open('r') as f: - self.assertIsInstance(f, io.TextIOBase) - self.assertEqual(f.read(), "this is file A\n") - with (p / 'fileA').open('rb') as f: - self.assertIsInstance(f, io.BufferedIOBase) - self.assertEqual(f.read().strip(), b"this is file A") - - def test_read_write_bytes(self): - p = self.cls(BASE) - (p / 'fileA').write_bytes(b'abcdefg') - self.assertEqual((p / 'fileA').read_bytes(), b'abcdefg') - # Check that trying to write str does not truncate the file. - self.assertRaises(TypeError, (p / 'fileA').write_bytes, 'somestr') - self.assertEqual((p / 'fileA').read_bytes(), b'abcdefg') - - def test_read_write_text(self): - p = self.cls(BASE) - (p / 'fileA').write_text('äbcdefg', encoding='latin-1') - self.assertEqual((p / 'fileA').read_text( - encoding='utf-8', errors='ignore'), 'bcdefg') - # Check that trying to write bytes does not truncate the file. - self.assertRaises(TypeError, (p / 'fileA').write_text, b'somebytes') - self.assertEqual((p / 'fileA').read_text(encoding='latin-1'), 'äbcdefg') - - def test_write_text_with_newlines(self): - p = self.cls(BASE) - # Check that `\n` character change nothing - (p / 'fileA').write_text('abcde\r\nfghlk\n\rmnopq', newline='\n') - self.assertEqual((p / 'fileA').read_bytes(), - b'abcde\r\nfghlk\n\rmnopq') - # Check that `\r` character replaces `\n` - (p / 'fileA').write_text('abcde\r\nfghlk\n\rmnopq', newline='\r') - self.assertEqual((p / 'fileA').read_bytes(), - b'abcde\r\rfghlk\r\rmnopq') - # Check that `\r\n` character replaces `\n` - (p / 'fileA').write_text('abcde\r\nfghlk\n\rmnopq', newline='\r\n') - self.assertEqual((p / 'fileA').read_bytes(), - b'abcde\r\r\nfghlk\r\n\rmnopq') - # Check that no argument passed will change `\n` to `os.linesep` - os_linesep_byte = bytes(os.linesep, encoding='ascii') - (p / 'fileA').write_text('abcde\nfghlk\n\rmnopq') - self.assertEqual((p / 'fileA').read_bytes(), - b'abcde' + os_linesep_byte + b'fghlk' + os_linesep_byte + b'\rmnopq') - - def test_iterdir(self): - P = self.cls - p = P(BASE) - it = p.iterdir() - paths = set(it) - expected = ['dirA', 'dirB', 'dirC', 'dirE', 'fileA'] - if self.can_symlink: - expected += ['linkA', 'linkB', 'brokenLink', 'brokenLinkLoop'] - self.assertEqual(paths, { P(BASE, q) for q in expected }) - - def test_iterdir_symlink(self): - if not self.can_symlink: - self.skipTest("symlinks required") - # __iter__ on a symlink to a directory. - P = self.cls - p = P(BASE, 'linkB') - paths = set(p.iterdir()) - expected = { P(BASE, 'linkB', q) for q in ['fileB', 'linkD'] } - self.assertEqual(paths, expected) - - def test_iterdir_nodir(self): - # __iter__ on something that is not a directory. - p = self.cls(BASE, 'fileA') - with self.assertRaises(OSError) as cm: - next(p.iterdir()) - # ENOENT or EINVAL under Windows, ENOTDIR otherwise - # (see issue #12802). - self.assertIn(cm.exception.errno, (errno.ENOTDIR, - errno.ENOENT, errno.EINVAL)) - - def test_glob_common(self): - def _check(glob, expected): - self.assertEqual(set(glob), { P(BASE, q) for q in expected }) - P = self.cls - p = P(BASE) - it = p.glob("fileA") - self.assertIsInstance(it, collections.abc.Iterator) - _check(it, ["fileA"]) - _check(p.glob("fileB"), []) - _check(p.glob("dir*/file*"), ["dirB/fileB", "dirC/fileC"]) - if not self.can_symlink: - _check(p.glob("*A"), ['dirA', 'fileA']) - else: - _check(p.glob("*A"), ['dirA', 'fileA', 'linkA']) - if not self.can_symlink: - _check(p.glob("*B/*"), ['dirB/fileB']) - else: - _check(p.glob("*B/*"), ['dirB/fileB', 'dirB/linkD', - 'linkB/fileB', 'linkB/linkD']) - if not self.can_symlink: - _check(p.glob("*/fileB"), ['dirB/fileB']) - else: - _check(p.glob("*/fileB"), ['dirB/fileB', 'linkB/fileB']) - if self.can_symlink: - _check(p.glob("brokenLink"), ['brokenLink']) - - if not self.can_symlink: - _check(p.glob("*/"), ["dirA", "dirB", "dirC", "dirE"]) - else: - _check(p.glob("*/"), ["dirA", "dirB", "dirC", "dirE", "linkB"]) - - def test_glob_empty_pattern(self): - p = self.cls() - with self.assertRaisesRegex(ValueError, 'Unacceptable pattern'): - list(p.glob('')) - - def test_glob_case_sensitive(self): - P = self.cls - def _check(path, pattern, case_sensitive, expected): - actual = {str(q) for q in path.glob(pattern, case_sensitive=case_sensitive)} - expected = {str(P(BASE, q)) for q in expected} - self.assertEqual(actual, expected) - path = P(BASE) - _check(path, "DIRB/FILE*", True, []) - _check(path, "DIRB/FILE*", False, ["dirB/fileB"]) - _check(path, "dirb/file*", True, []) - _check(path, "dirb/file*", False, ["dirB/fileB"]) - - def test_glob_follow_symlinks_common(self): - if not self.can_symlink: - self.skipTest("symlinks required") - def _check(path, glob, expected): - actual = {path for path in path.glob(glob, follow_symlinks=True) - if "linkD" not in path.parent.parts} # exclude symlink loop. - self.assertEqual(actual, { P(BASE, q) for q in expected }) - P = self.cls - p = P(BASE) - _check(p, "fileB", []) - _check(p, "dir*/file*", ["dirB/fileB", "dirC/fileC"]) - _check(p, "*A", ["dirA", "fileA", "linkA"]) - _check(p, "*B/*", ["dirB/fileB", "dirB/linkD", "linkB/fileB", "linkB/linkD"]) - _check(p, "*/fileB", ["dirB/fileB", "linkB/fileB"]) - _check(p, "*/", ["dirA", "dirB", "dirC", "dirE", "linkB"]) - _check(p, "dir*/*/..", ["dirC/dirD/..", "dirA/linkC/.."]) - _check(p, "dir*/**/", ["dirA", "dirA/linkC", "dirA/linkC/linkD", "dirB", "dirB/linkD", - "dirC", "dirC/dirD", "dirE"]) - _check(p, "dir*/**/..", ["dirA/..", "dirA/linkC/..", "dirB/..", - "dirC/..", "dirC/dirD/..", "dirE/.."]) - _check(p, "dir*/*/**/", ["dirA/linkC", "dirA/linkC/linkD", "dirB/linkD", "dirC/dirD"]) - _check(p, "dir*/*/**/..", ["dirA/linkC/..", "dirC/dirD/.."]) - _check(p, "dir*/**/fileC", ["dirC/fileC"]) - _check(p, "dir*/*/../dirD/**/", ["dirC/dirD/../dirD"]) - _check(p, "*/dirD/**/", ["dirC/dirD"]) - - def test_glob_no_follow_symlinks_common(self): - if not self.can_symlink: - self.skipTest("symlinks required") - def _check(path, glob, expected): - actual = {path for path in path.glob(glob, follow_symlinks=False)} - self.assertEqual(actual, { P(BASE, q) for q in expected }) - P = self.cls - p = P(BASE) - _check(p, "fileB", []) - _check(p, "dir*/file*", ["dirB/fileB", "dirC/fileC"]) - _check(p, "*A", ["dirA", "fileA", "linkA"]) - _check(p, "*B/*", ["dirB/fileB", "dirB/linkD"]) - _check(p, "*/fileB", ["dirB/fileB"]) - _check(p, "*/", ["dirA", "dirB", "dirC", "dirE"]) - _check(p, "dir*/*/..", ["dirC/dirD/.."]) - _check(p, "dir*/**/", ["dirA", "dirB", "dirC", "dirC/dirD", "dirE"]) - _check(p, "dir*/**/..", ["dirA/..", "dirB/..", "dirC/..", "dirC/dirD/..", "dirE/.."]) - _check(p, "dir*/*/**/", ["dirC/dirD"]) - _check(p, "dir*/*/**/..", ["dirC/dirD/.."]) - _check(p, "dir*/**/fileC", ["dirC/fileC"]) - _check(p, "dir*/*/../dirD/**/", ["dirC/dirD/../dirD"]) - _check(p, "*/dirD/**/", ["dirC/dirD"]) - - def test_rglob_common(self): - def _check(glob, expected): - self.assertEqual(sorted(glob), sorted(P(BASE, q) for q in expected)) - P = self.cls - p = P(BASE) - it = p.rglob("fileA") - self.assertIsInstance(it, collections.abc.Iterator) - _check(it, ["fileA"]) - _check(p.rglob("fileB"), ["dirB/fileB"]) - _check(p.rglob("**/fileB"), ["dirB/fileB"]) - _check(p.rglob("*/fileA"), []) - if not self.can_symlink: - _check(p.rglob("*/fileB"), ["dirB/fileB"]) - else: - _check(p.rglob("*/fileB"), ["dirB/fileB", "dirB/linkD/fileB", - "linkB/fileB", "dirA/linkC/fileB"]) - _check(p.rglob("file*"), ["fileA", "dirB/fileB", - "dirC/fileC", "dirC/dirD/fileD"]) - if not self.can_symlink: - _check(p.rglob("*/"), [ - "dirA", "dirB", "dirC", "dirC/dirD", "dirE", - ]) - else: - _check(p.rglob("*/"), [ - "dirA", "dirA/linkC", "dirB", "dirB/linkD", "dirC", - "dirC/dirD", "dirE", "linkB", - ]) - _check(p.rglob(""), ["", "dirA", "dirB", "dirC", "dirE", "dirC/dirD"]) - - p = P(BASE, "dirC") - _check(p.rglob("*"), ["dirC/fileC", "dirC/novel.txt", - "dirC/dirD", "dirC/dirD/fileD"]) - _check(p.rglob("file*"), ["dirC/fileC", "dirC/dirD/fileD"]) - _check(p.rglob("**/file*"), ["dirC/fileC", "dirC/dirD/fileD"]) - _check(p.rglob("dir*/**/"), ["dirC/dirD"]) - _check(p.rglob("*/*"), ["dirC/dirD/fileD"]) - _check(p.rglob("*/"), ["dirC/dirD"]) - _check(p.rglob(""), ["dirC", "dirC/dirD"]) - _check(p.rglob("**/"), ["dirC", "dirC/dirD"]) - # gh-91616, a re module regression - _check(p.rglob("*.txt"), ["dirC/novel.txt"]) - _check(p.rglob("*.*"), ["dirC/novel.txt"]) - - def test_rglob_follow_symlinks_common(self): - if not self.can_symlink: - self.skipTest("symlinks required") - def _check(path, glob, expected): - actual = {path for path in path.rglob(glob, follow_symlinks=True) - if 'linkD' not in path.parent.parts} # exclude symlink loop. - self.assertEqual(actual, { P(BASE, q) for q in expected }) - P = self.cls - p = P(BASE) - _check(p, "fileB", ["dirB/fileB", "dirA/linkC/fileB", "linkB/fileB"]) - _check(p, "*/fileA", []) - _check(p, "*/fileB", ["dirB/fileB", "dirA/linkC/fileB", "linkB/fileB"]) - _check(p, "file*", ["fileA", "dirA/linkC/fileB", "dirB/fileB", - "dirC/fileC", "dirC/dirD/fileD", "linkB/fileB"]) - _check(p, "*/", ["dirA", "dirA/linkC", "dirA/linkC/linkD", "dirB", "dirB/linkD", - "dirC", "dirC/dirD", "dirE", "linkB", "linkB/linkD"]) - _check(p, "", ["", "dirA", "dirA/linkC", "dirA/linkC/linkD", "dirB", "dirB/linkD", - "dirC", "dirE", "dirC/dirD", "linkB", "linkB/linkD"]) - - p = P(BASE, "dirC") - _check(p, "*", ["dirC/fileC", "dirC/novel.txt", - "dirC/dirD", "dirC/dirD/fileD"]) - _check(p, "file*", ["dirC/fileC", "dirC/dirD/fileD"]) - _check(p, "*/*", ["dirC/dirD/fileD"]) - _check(p, "*/", ["dirC/dirD"]) - _check(p, "", ["dirC", "dirC/dirD"]) - # gh-91616, a re module regression - _check(p, "*.txt", ["dirC/novel.txt"]) - _check(p, "*.*", ["dirC/novel.txt"]) - - def test_rglob_no_follow_symlinks_common(self): - if not self.can_symlink: - self.skipTest("symlinks required") - def _check(path, glob, expected): - actual = {path for path in path.rglob(glob, follow_symlinks=False)} - self.assertEqual(actual, { P(BASE, q) for q in expected }) - P = self.cls - p = P(BASE) - _check(p, "fileB", ["dirB/fileB"]) - _check(p, "*/fileA", []) - _check(p, "*/fileB", ["dirB/fileB"]) - _check(p, "file*", ["fileA", "dirB/fileB", "dirC/fileC", "dirC/dirD/fileD", ]) - _check(p, "*/", ["dirA", "dirB", "dirC", "dirC/dirD", "dirE"]) - _check(p, "", ["", "dirA", "dirB", "dirC", "dirE", "dirC/dirD"]) - - p = P(BASE, "dirC") - _check(p, "*", ["dirC/fileC", "dirC/novel.txt", - "dirC/dirD", "dirC/dirD/fileD"]) - _check(p, "file*", ["dirC/fileC", "dirC/dirD/fileD"]) - _check(p, "*/*", ["dirC/dirD/fileD"]) - _check(p, "*/", ["dirC/dirD"]) - _check(p, "", ["dirC", "dirC/dirD"]) - # gh-91616, a re module regression - _check(p, "*.txt", ["dirC/novel.txt"]) - _check(p, "*.*", ["dirC/novel.txt"]) - - def test_rglob_symlink_loop(self): - # Don't get fooled by symlink loops (Issue #26012). - if not self.can_symlink: - self.skipTest("symlinks required") - P = self.cls - p = P(BASE) - given = set(p.rglob('*')) - expect = {'brokenLink', - 'dirA', 'dirA/linkC', - 'dirB', 'dirB/fileB', 'dirB/linkD', - 'dirC', 'dirC/dirD', 'dirC/dirD/fileD', - 'dirC/fileC', 'dirC/novel.txt', - 'dirE', - 'fileA', - 'linkA', - 'linkB', - 'brokenLinkLoop', - } - self.assertEqual(given, {p / x for x in expect}) - - def test_glob_many_open_files(self): - depth = 30 - P = self.cls - base = P(BASE) / 'deep' - p = P(base, *(['d']*depth)) - p.mkdir(parents=True) - pattern = '/'.join(['*'] * depth) - iters = [base.glob(pattern) for j in range(100)] - for it in iters: - self.assertEqual(next(it), p) - iters = [base.rglob('d') for j in range(100)] - p = base - for i in range(depth): - p = p / 'd' - for it in iters: - self.assertEqual(next(it), p) - - def test_glob_dotdot(self): - # ".." is not special in globs. - P = self.cls - p = P(BASE) - self.assertEqual(set(p.glob("..")), { P(BASE, "..") }) - self.assertEqual(set(p.glob("../..")), { P(BASE, "..", "..") }) - self.assertEqual(set(p.glob("dirA/..")), { P(BASE, "dirA", "..") }) - self.assertEqual(set(p.glob("dirA/../file*")), { P(BASE, "dirA/../fileA") }) - self.assertEqual(set(p.glob("dirA/../file*/..")), set()) - self.assertEqual(set(p.glob("../xyzzy")), set()) - self.assertEqual(set(p.glob("xyzzy/..")), set()) - self.assertEqual(set(p.glob("/".join([".."] * 50))), { P(BASE, *[".."] * 50)}) - - def test_glob_permissions(self): - # See bpo-38894 - if not self.can_symlink: - self.skipTest("symlinks required") - P = self.cls - base = P(BASE) / 'permissions' - base.mkdir() - - for i in range(100): - link = base / f"link{i}" - if i % 2: - link.symlink_to(P(BASE, "dirE", "nonexistent")) - else: - link.symlink_to(P(BASE, "dirC")) - - self.assertEqual(len(set(base.glob("*"))), 100) - self.assertEqual(len(set(base.glob("*/"))), 50) - self.assertEqual(len(set(base.glob("*/fileC"))), 50) - self.assertEqual(len(set(base.glob("*/file*"))), 50) - - def test_glob_long_symlink(self): - # See gh-87695 - if not self.can_symlink: - self.skipTest("symlinks required") - base = self.cls(BASE) / 'long_symlink' - base.mkdir() - bad_link = base / 'bad_link' - bad_link.symlink_to("bad" * 200) - self.assertEqual(sorted(base.glob('**/*')), [bad_link]) - - def test_glob_above_recursion_limit(self): - recursion_limit = 50 - # directory_depth > recursion_limit - directory_depth = recursion_limit + 10 - base = self.cls(BASE, 'deep') - path = self.cls(base, *(['d'] * directory_depth)) - path.mkdir(parents=True) - - with set_recursion_limit(recursion_limit): - list(base.glob('**/')) - - def test_glob_recursive_no_trailing_slash(self): - P = self.cls - p = P(BASE) - with self.assertWarns(FutureWarning): - p.glob('**') - with self.assertWarns(FutureWarning): - p.glob('*/**') - with self.assertWarns(FutureWarning): - p.rglob('**') - with self.assertWarns(FutureWarning): - p.rglob('*/**') - - - def test_readlink(self): - if not self.can_symlink: - self.skipTest("symlinks required") - P = self.cls(BASE) - self.assertEqual((P / 'linkA').readlink(), self.cls('fileA')) - self.assertEqual((P / 'brokenLink').readlink(), - self.cls('non-existing')) - self.assertEqual((P / 'linkB').readlink(), self.cls('dirB')) - with self.assertRaises(OSError): - (P / 'fileA').readlink() - - @unittest.skipIf(hasattr(os, "readlink"), "os.readlink() is present") - def test_readlink_unsupported(self): - P = self.cls(BASE) - p = P / 'fileA' - with self.assertRaises(pathlib.UnsupportedOperation): - q.readlink(p) - - def _check_resolve(self, p, expected, strict=True): - q = p.resolve(strict) - self.assertEqual(q, expected) - - # This can be used to check both relative and absolute resolutions. - _check_resolve_relative = _check_resolve_absolute = _check_resolve - - def test_resolve_common(self): - if not self.can_symlink: - self.skipTest("symlinks required") - P = self.cls - p = P(BASE, 'foo') - with self.assertRaises(OSError) as cm: - p.resolve(strict=True) - self.assertEqual(cm.exception.errno, errno.ENOENT) - # Non-strict - self.assertEqualNormCase(str(p.resolve(strict=False)), - os.path.join(BASE, 'foo')) - p = P(BASE, 'foo', 'in', 'spam') - self.assertEqualNormCase(str(p.resolve(strict=False)), - os.path.join(BASE, 'foo', 'in', 'spam')) - p = P(BASE, '..', 'foo', 'in', 'spam') - self.assertEqualNormCase(str(p.resolve(strict=False)), - os.path.abspath(os.path.join('foo', 'in', 'spam'))) - # These are all relative symlinks. - p = P(BASE, 'dirB', 'fileB') - self._check_resolve_relative(p, p) - p = P(BASE, 'linkA') - self._check_resolve_relative(p, P(BASE, 'fileA')) - p = P(BASE, 'dirA', 'linkC', 'fileB') - self._check_resolve_relative(p, P(BASE, 'dirB', 'fileB')) - p = P(BASE, 'dirB', 'linkD', 'fileB') - self._check_resolve_relative(p, P(BASE, 'dirB', 'fileB')) - # Non-strict - p = P(BASE, 'dirA', 'linkC', 'fileB', 'foo', 'in', 'spam') - self._check_resolve_relative(p, P(BASE, 'dirB', 'fileB', 'foo', 'in', - 'spam'), False) - p = P(BASE, 'dirA', 'linkC', '..', 'foo', 'in', 'spam') - if os.name == 'nt': - # In Windows, if linkY points to dirB, 'dirA\linkY\..' - # resolves to 'dirA' without resolving linkY first. - self._check_resolve_relative(p, P(BASE, 'dirA', 'foo', 'in', - 'spam'), False) - else: - # In Posix, if linkY points to dirB, 'dirA/linkY/..' - # resolves to 'dirB/..' first before resolving to parent of dirB. - self._check_resolve_relative(p, P(BASE, 'foo', 'in', 'spam'), False) - # Now create absolute symlinks. - d = os_helper._longpath(tempfile.mkdtemp(suffix='-dirD', - dir=os.getcwd())) - self.addCleanup(os_helper.rmtree, d) - P(BASE, 'dirA', 'linkX').symlink_to(d) - P(BASE, str(d), 'linkY').symlink_to(join('dirB')) - p = P(BASE, 'dirA', 'linkX', 'linkY', 'fileB') - self._check_resolve_absolute(p, P(BASE, 'dirB', 'fileB')) - # Non-strict - p = P(BASE, 'dirA', 'linkX', 'linkY', 'foo', 'in', 'spam') - self._check_resolve_relative(p, P(BASE, 'dirB', 'foo', 'in', 'spam'), - False) - p = P(BASE, 'dirA', 'linkX', 'linkY', '..', 'foo', 'in', 'spam') - if os.name == 'nt': - # In Windows, if linkY points to dirB, 'dirA\linkY\..' - # resolves to 'dirA' without resolving linkY first. - self._check_resolve_relative(p, P(d, 'foo', 'in', 'spam'), False) - else: - # In Posix, if linkY points to dirB, 'dirA/linkY/..' - # resolves to 'dirB/..' first before resolving to parent of dirB. - self._check_resolve_relative(p, P(BASE, 'foo', 'in', 'spam'), False) - - def test_resolve_dot(self): - # See http://web.archive.org/web/20200623062557/https://bitbucket.org/pitrou/pathlib/issues/9/ - if not self.can_symlink: - self.skipTest("symlinks required") - p = self.cls(BASE) - p.joinpath('0').symlink_to('.', target_is_directory=True) - p.joinpath('1').symlink_to(os.path.join('0', '0'), target_is_directory=True) - p.joinpath('2').symlink_to(os.path.join('1', '1'), target_is_directory=True) - q = p / '2' - self.assertEqual(q.resolve(strict=True), p) - r = q / '3' / '4' - self.assertRaises(FileNotFoundError, r.resolve, strict=True) - # Non-strict - self.assertEqual(r.resolve(strict=False), p / '3' / '4') - - def test_stat(self): - statA = self.cls(BASE).joinpath('fileA').stat() - statB = self.cls(BASE).joinpath('dirB', 'fileB').stat() - statC = self.cls(BASE).joinpath('dirC').stat() - # st_mode: files are the same, directory differs. - self.assertIsInstance(statA.st_mode, int) - self.assertEqual(statA.st_mode, statB.st_mode) - self.assertNotEqual(statA.st_mode, statC.st_mode) - self.assertNotEqual(statB.st_mode, statC.st_mode) - # st_ino: all different, - self.assertIsInstance(statA.st_ino, int) - self.assertNotEqual(statA.st_ino, statB.st_ino) - self.assertNotEqual(statA.st_ino, statC.st_ino) - self.assertNotEqual(statB.st_ino, statC.st_ino) - # st_dev: all the same. - self.assertIsInstance(statA.st_dev, int) - self.assertEqual(statA.st_dev, statB.st_dev) - self.assertEqual(statA.st_dev, statC.st_dev) - # other attributes not used by pathlib. - - def test_stat_no_follow_symlinks(self): - if not self.can_symlink: - self.skipTest("symlinks required") - p = self.cls(BASE) / 'linkA' - st = p.stat() - self.assertNotEqual(st, p.stat(follow_symlinks=False)) - - def test_stat_no_follow_symlinks_nosymlink(self): - p = self.cls(BASE) / 'fileA' - st = p.stat() - self.assertEqual(st, p.stat(follow_symlinks=False)) - - def test_lstat(self): - if not self.can_symlink: - self.skipTest("symlinks required") - p = self.cls(BASE)/ 'linkA' - st = p.stat() - self.assertNotEqual(st, p.lstat()) - - def test_lstat_nosymlink(self): - p = self.cls(BASE) / 'fileA' - st = p.stat() - self.assertEqual(st, p.lstat()) - - def test_is_dir(self): - P = self.cls(BASE) - self.assertTrue((P / 'dirA').is_dir()) - self.assertFalse((P / 'fileA').is_dir()) - self.assertFalse((P / 'non-existing').is_dir()) - self.assertFalse((P / 'fileA' / 'bah').is_dir()) - if self.can_symlink: - self.assertFalse((P / 'linkA').is_dir()) - self.assertTrue((P / 'linkB').is_dir()) - self.assertFalse((P/ 'brokenLink').is_dir()) - self.assertFalse((P / 'dirA\udfff').is_dir()) - self.assertFalse((P / 'dirA\x00').is_dir()) - - def test_is_dir_no_follow_symlinks(self): - P = self.cls(BASE) - self.assertTrue((P / 'dirA').is_dir(follow_symlinks=False)) - self.assertFalse((P / 'fileA').is_dir(follow_symlinks=False)) - self.assertFalse((P / 'non-existing').is_dir(follow_symlinks=False)) - self.assertFalse((P / 'fileA' / 'bah').is_dir(follow_symlinks=False)) - if self.can_symlink: - self.assertFalse((P / 'linkA').is_dir(follow_symlinks=False)) - self.assertFalse((P / 'linkB').is_dir(follow_symlinks=False)) - self.assertFalse((P/ 'brokenLink').is_dir(follow_symlinks=False)) - self.assertFalse((P / 'dirA\udfff').is_dir(follow_symlinks=False)) - self.assertFalse((P / 'dirA\x00').is_dir(follow_symlinks=False)) - - def test_is_file(self): - P = self.cls(BASE) - self.assertTrue((P / 'fileA').is_file()) - self.assertFalse((P / 'dirA').is_file()) - self.assertFalse((P / 'non-existing').is_file()) - self.assertFalse((P / 'fileA' / 'bah').is_file()) - if self.can_symlink: - self.assertTrue((P / 'linkA').is_file()) - self.assertFalse((P / 'linkB').is_file()) - self.assertFalse((P/ 'brokenLink').is_file()) - self.assertFalse((P / 'fileA\udfff').is_file()) - self.assertFalse((P / 'fileA\x00').is_file()) - - def test_is_file_no_follow_symlinks(self): - P = self.cls(BASE) - self.assertTrue((P / 'fileA').is_file(follow_symlinks=False)) - self.assertFalse((P / 'dirA').is_file(follow_symlinks=False)) - self.assertFalse((P / 'non-existing').is_file(follow_symlinks=False)) - self.assertFalse((P / 'fileA' / 'bah').is_file(follow_symlinks=False)) - if self.can_symlink: - self.assertFalse((P / 'linkA').is_file(follow_symlinks=False)) - self.assertFalse((P / 'linkB').is_file(follow_symlinks=False)) - self.assertFalse((P/ 'brokenLink').is_file(follow_symlinks=False)) - self.assertFalse((P / 'fileA\udfff').is_file(follow_symlinks=False)) - self.assertFalse((P / 'fileA\x00').is_file(follow_symlinks=False)) - - def test_is_mount(self): - P = self.cls(BASE) - self.assertFalse((P / 'fileA').is_mount()) - self.assertFalse((P / 'dirA').is_mount()) - self.assertFalse((P / 'non-existing').is_mount()) - self.assertFalse((P / 'fileA' / 'bah').is_mount()) - if self.can_symlink: - self.assertFalse((P / 'linkA').is_mount()) - - def test_is_symlink(self): - P = self.cls(BASE) - self.assertFalse((P / 'fileA').is_symlink()) - self.assertFalse((P / 'dirA').is_symlink()) - self.assertFalse((P / 'non-existing').is_symlink()) - self.assertFalse((P / 'fileA' / 'bah').is_symlink()) - if self.can_symlink: - self.assertTrue((P / 'linkA').is_symlink()) - self.assertTrue((P / 'linkB').is_symlink()) - self.assertTrue((P/ 'brokenLink').is_symlink()) - self.assertIs((P / 'fileA\udfff').is_file(), False) - self.assertIs((P / 'fileA\x00').is_file(), False) - if self.can_symlink: - self.assertIs((P / 'linkA\udfff').is_file(), False) - self.assertIs((P / 'linkA\x00').is_file(), False) - - def test_is_junction_false(self): - P = self.cls(BASE) - self.assertFalse((P / 'fileA').is_junction()) - self.assertFalse((P / 'dirA').is_junction()) - self.assertFalse((P / 'non-existing').is_junction()) - self.assertFalse((P / 'fileA' / 'bah').is_junction()) - self.assertFalse((P / 'fileA\udfff').is_junction()) - self.assertFalse((P / 'fileA\x00').is_junction()) - - def test_is_fifo_false(self): - P = self.cls(BASE) - self.assertFalse((P / 'fileA').is_fifo()) - self.assertFalse((P / 'dirA').is_fifo()) - self.assertFalse((P / 'non-existing').is_fifo()) - self.assertFalse((P / 'fileA' / 'bah').is_fifo()) - self.assertIs((P / 'fileA\udfff').is_fifo(), False) - self.assertIs((P / 'fileA\x00').is_fifo(), False) - - def test_is_socket_false(self): - P = self.cls(BASE) - self.assertFalse((P / 'fileA').is_socket()) - self.assertFalse((P / 'dirA').is_socket()) - self.assertFalse((P / 'non-existing').is_socket()) - self.assertFalse((P / 'fileA' / 'bah').is_socket()) - self.assertIs((P / 'fileA\udfff').is_socket(), False) - self.assertIs((P / 'fileA\x00').is_socket(), False) - - def test_is_block_device_false(self): - P = self.cls(BASE) - self.assertFalse((P / 'fileA').is_block_device()) - self.assertFalse((P / 'dirA').is_block_device()) - self.assertFalse((P / 'non-existing').is_block_device()) - self.assertFalse((P / 'fileA' / 'bah').is_block_device()) - self.assertIs((P / 'fileA\udfff').is_block_device(), False) - self.assertIs((P / 'fileA\x00').is_block_device(), False) - - def test_is_char_device_false(self): - P = self.cls(BASE) - self.assertFalse((P / 'fileA').is_char_device()) - self.assertFalse((P / 'dirA').is_char_device()) - self.assertFalse((P / 'non-existing').is_char_device()) - self.assertFalse((P / 'fileA' / 'bah').is_char_device()) - self.assertIs((P / 'fileA\udfff').is_char_device(), False) - self.assertIs((P / 'fileA\x00').is_char_device(), False) - - def test_pickling_common(self): - p = self.cls(BASE, 'fileA') - for proto in range(0, pickle.HIGHEST_PROTOCOL + 1): - dumped = pickle.dumps(p, proto) - pp = pickle.loads(dumped) - self.assertEqual(pp.stat(), p.stat()) - - def test_parts_interning(self): - P = self.cls - p = P('/usr/bin/foo') - q = P('/usr/local/bin') - # 'usr' - self.assertIs(p.parts[1], q.parts[1]) - # 'bin' - self.assertIs(p.parts[2], q.parts[3]) - - def _check_complex_symlinks(self, link0_target): - if not self.can_symlink: - self.skipTest("symlinks required") - - # Test solving a non-looping chain of symlinks (issue #19887). - P = self.cls(BASE) - P.joinpath('link1').symlink_to(os.path.join('link0', 'link0'), target_is_directory=True) - P.joinpath('link2').symlink_to(os.path.join('link1', 'link1'), target_is_directory=True) - P.joinpath('link3').symlink_to(os.path.join('link2', 'link2'), target_is_directory=True) - P.joinpath('link0').symlink_to(link0_target, target_is_directory=True) - - # Resolve absolute paths. - p = (P / 'link0').resolve() - self.assertEqual(p, P) - self.assertEqualNormCase(str(p), BASE) - p = (P / 'link1').resolve() - self.assertEqual(p, P) - self.assertEqualNormCase(str(p), BASE) - p = (P / 'link2').resolve() - self.assertEqual(p, P) - self.assertEqualNormCase(str(p), BASE) - p = (P / 'link3').resolve() - self.assertEqual(p, P) - self.assertEqualNormCase(str(p), BASE) - - # Resolve relative paths. - old_path = os.getcwd() - os.chdir(BASE) - try: - p = self.cls('link0').resolve() - self.assertEqual(p, P) - self.assertEqualNormCase(str(p), BASE) - p = self.cls('link1').resolve() - self.assertEqual(p, P) - self.assertEqualNormCase(str(p), BASE) - p = self.cls('link2').resolve() - self.assertEqual(p, P) - self.assertEqualNormCase(str(p), BASE) - p = self.cls('link3').resolve() - self.assertEqual(p, P) - self.assertEqualNormCase(str(p), BASE) - finally: - os.chdir(old_path) - - def test_complex_symlinks_absolute(self): - self._check_complex_symlinks(BASE) - - def test_complex_symlinks_relative(self): - self._check_complex_symlinks('.') - - def test_complex_symlinks_relative_dot_dot(self): - self._check_complex_symlinks(os.path.join('dirA', '..')) - - def test_concrete_class(self): - if self.cls is pathlib.Path: - expected = pathlib.WindowsPath if os.name == 'nt' else pathlib.PosixPath - else: - expected = self.cls - p = self.cls('a') - self.assertIs(type(p), expected) - - def test_unsupported_pathmod(self): - if self.cls.pathmod is os.path: - self.skipTest("path flavour is supported") - else: - self.assertRaises(pathlib.UnsupportedOperation, self.cls) - - def _test_cwd(self, p): - q = self.cls(os.getcwd()) - self.assertEqual(p, q) - self.assertEqualNormCase(str(p), str(q)) - self.assertIs(type(p), type(q)) - self.assertTrue(p.is_absolute()) - - def test_cwd(self): - p = self.cls.cwd() - self._test_cwd(p) - - def test_absolute_common(self): - P = self.cls - - with mock.patch("os.getcwd") as getcwd: - getcwd.return_value = BASE - - # Simple relative paths. - self.assertEqual(str(P().absolute()), BASE) - self.assertEqual(str(P('.').absolute()), BASE) - self.assertEqual(str(P('a').absolute()), os.path.join(BASE, 'a')) - self.assertEqual(str(P('a', 'b', 'c').absolute()), os.path.join(BASE, 'a', 'b', 'c')) - - # Symlinks should not be resolved. - self.assertEqual(str(P('linkB', 'fileB').absolute()), os.path.join(BASE, 'linkB', 'fileB')) - self.assertEqual(str(P('brokenLink').absolute()), os.path.join(BASE, 'brokenLink')) - self.assertEqual(str(P('brokenLinkLoop').absolute()), os.path.join(BASE, 'brokenLinkLoop')) - - # '..' entries should be preserved and not normalised. - self.assertEqual(str(P('..').absolute()), os.path.join(BASE, '..')) - self.assertEqual(str(P('a', '..').absolute()), os.path.join(BASE, 'a', '..')) - self.assertEqual(str(P('..', 'b').absolute()), os.path.join(BASE, '..', 'b')) - - def _test_home(self, p): - q = self.cls(os.path.expanduser('~')) - self.assertEqual(p, q) - self.assertEqualNormCase(str(p), str(q)) - self.assertIs(type(p), type(q)) - self.assertTrue(p.is_absolute()) - - @unittest.skipIf( - pwd is None, reason="Test requires pwd module to get homedir." - ) - def test_home(self): - with os_helper.EnvironmentVarGuard() as env: - self._test_home(self.cls.home()) - - env.clear() - env['USERPROFILE'] = os.path.join(BASE, 'userprofile') - self._test_home(self.cls.home()) - - # bpo-38883: ignore `HOME` when set on windows - env['HOME'] = os.path.join(BASE, 'home') - self._test_home(self.cls.home()) - - @unittest.skipIf(is_wasi, "WASI has no user accounts.") - def test_expanduser_common(self): - P = self.cls - p = P('~') - self.assertEqual(p.expanduser(), P(os.path.expanduser('~'))) - p = P('foo') - self.assertEqual(p.expanduser(), p) - p = P('/~') - self.assertEqual(p.expanduser(), p) - p = P('../~') - self.assertEqual(p.expanduser(), p) - p = P(P('').absolute().anchor) / '~' - self.assertEqual(p.expanduser(), p) - p = P('~/a:b') - self.assertEqual(p.expanduser(), P(os.path.expanduser('~'), './a:b')) - - def test_with_segments(self): - class P(self.cls): - def __init__(self, *pathsegments, session_id): - super().__init__(*pathsegments) - self.session_id = session_id - - def with_segments(self, *pathsegments): - return type(self)(*pathsegments, session_id=self.session_id) - p = P(BASE, session_id=42) - self.assertEqual(42, p.absolute().session_id) - self.assertEqual(42, p.resolve().session_id) - if not is_wasi: # WASI has no user accounts. - self.assertEqual(42, p.with_segments('~').expanduser().session_id) - self.assertEqual(42, (p / 'fileA').rename(p / 'fileB').session_id) - self.assertEqual(42, (p / 'fileB').replace(p / 'fileA').session_id) - if self.can_symlink: - self.assertEqual(42, (p / 'linkA').readlink().session_id) - for path in p.iterdir(): - self.assertEqual(42, path.session_id) - for path in p.glob('*'): - self.assertEqual(42, path.session_id) - for path in p.rglob('*'): - self.assertEqual(42, path.session_id) - for dirpath, dirnames, filenames in p.walk(): - self.assertEqual(42, dirpath.session_id) - - def test_open_unbuffered(self): - p = self.cls(BASE) - with (p / 'fileA').open('rb', buffering=0) as f: - self.assertIsInstance(f, io.RawIOBase) - self.assertEqual(f.read().strip(), b"this is file A") - - def test_resolve_nonexist_relative_issue38671(self): - p = self.cls('non', 'exist') - - old_cwd = os.getcwd() - os.chdir(BASE) - try: - self.assertEqual(p.resolve(), self.cls(BASE, p)) - finally: - os.chdir(old_cwd) - - @os_helper.skip_unless_working_chmod - def test_chmod(self): - p = self.cls(BASE) / 'fileA' - mode = p.stat().st_mode - # Clear writable bit. - new_mode = mode & ~0o222 - p.chmod(new_mode) - self.assertEqual(p.stat().st_mode, new_mode) - # Set writable bit. - new_mode = mode | 0o222 - p.chmod(new_mode) - self.assertEqual(p.stat().st_mode, new_mode) - - # On Windows, os.chmod does not follow symlinks (issue #15411) - @only_posix - @os_helper.skip_unless_working_chmod - def test_chmod_follow_symlinks_true(self): - p = self.cls(BASE) / 'linkA' - q = p.resolve() - mode = q.stat().st_mode - # Clear writable bit. - new_mode = mode & ~0o222 - p.chmod(new_mode, follow_symlinks=True) - self.assertEqual(q.stat().st_mode, new_mode) - # Set writable bit - new_mode = mode | 0o222 - p.chmod(new_mode, follow_symlinks=True) - self.assertEqual(q.stat().st_mode, new_mode) - - # XXX also need a test for lchmod. - - @unittest.skipUnless(pwd, "the pwd module is needed for this test") - def test_owner(self): - p = self.cls(BASE) / 'fileA' - uid = p.stat().st_uid - try: - name = pwd.getpwuid(uid).pw_name - except KeyError: - self.skipTest( - "user %d doesn't have an entry in the system database" % uid) - self.assertEqual(name, p.owner()) - - @unittest.skipUnless(grp, "the grp module is needed for this test") - def test_group(self): - p = self.cls(BASE) / 'fileA' - gid = p.stat().st_gid - try: - name = grp.getgrgid(gid).gr_name - except KeyError: - self.skipTest( - "group %d doesn't have an entry in the system database" % gid) - self.assertEqual(name, p.group()) - - def test_unlink(self): - p = self.cls(BASE) / 'fileA' - p.unlink() - self.assertFileNotFound(p.stat) - self.assertFileNotFound(p.unlink) - - def test_unlink_missing_ok(self): - p = self.cls(BASE) / 'fileAAA' - self.assertFileNotFound(p.unlink) - p.unlink(missing_ok=True) - - def test_rmdir(self): - p = self.cls(BASE) / 'dirA' - for q in p.iterdir(): - q.unlink() - p.rmdir() - self.assertFileNotFound(p.stat) - self.assertFileNotFound(p.unlink) - - @unittest.skipUnless(hasattr(os, "link"), "os.link() is not present") - def test_hardlink_to(self): - P = self.cls(BASE) - target = P / 'fileA' - size = target.stat().st_size - # linking to another path. - link = P / 'dirA' / 'fileAA' - link.hardlink_to(target) - self.assertEqual(link.stat().st_size, size) - self.assertTrue(os.path.samefile(target, link)) - self.assertTrue(target.exists()) - # Linking to a str of a relative path. - link2 = P / 'dirA' / 'fileAAA' - target2 = rel_join('fileA') - link2.hardlink_to(target2) - self.assertEqual(os.stat(target2).st_size, size) - self.assertTrue(link2.exists()) - - @unittest.skipIf(hasattr(os, "link"), "os.link() is present") - def test_hardlink_to_unsupported(self): - P = self.cls(BASE) - p = P / 'fileA' - # linking to another path. - q = P / 'dirA' / 'fileAA' - with self.assertRaises(pathlib.UnsupportedOperation): - q.hardlink_to(p) - - def test_rename(self): - P = self.cls(BASE) - p = P / 'fileA' - size = p.stat().st_size - # Renaming to another path. - q = P / 'dirA' / 'fileAA' - renamed_p = p.rename(q) - self.assertEqual(renamed_p, q) - self.assertEqual(q.stat().st_size, size) - self.assertFileNotFound(p.stat) - # Renaming to a str of a relative path. - r = rel_join('fileAAA') - renamed_q = q.rename(r) - self.assertEqual(renamed_q, self.cls(r)) - self.assertEqual(os.stat(r).st_size, size) - self.assertFileNotFound(q.stat) - - def test_replace(self): - P = self.cls(BASE) - p = P / 'fileA' - size = p.stat().st_size - # Replacing a non-existing path. - q = P / 'dirA' / 'fileAA' - replaced_p = p.replace(q) - self.assertEqual(replaced_p, q) - self.assertEqual(q.stat().st_size, size) - self.assertFileNotFound(p.stat) - # Replacing another (existing) path. - r = rel_join('dirB', 'fileB') - replaced_q = q.replace(r) - self.assertEqual(replaced_q, self.cls(r)) - self.assertEqual(os.stat(r).st_size, size) - self.assertFileNotFound(q.stat) - - def test_touch_common(self): - P = self.cls(BASE) - p = P / 'newfileA' - self.assertFalse(p.exists()) - p.touch() - self.assertTrue(p.exists()) - st = p.stat() - old_mtime = st.st_mtime - old_mtime_ns = st.st_mtime_ns - # Rewind the mtime sufficiently far in the past to work around - # filesystem-specific timestamp granularity. - os.utime(str(p), (old_mtime - 10, old_mtime - 10)) - # The file mtime should be refreshed by calling touch() again. - p.touch() - st = p.stat() - self.assertGreaterEqual(st.st_mtime_ns, old_mtime_ns) - self.assertGreaterEqual(st.st_mtime, old_mtime) - # Now with exist_ok=False. - p = P / 'newfileB' - self.assertFalse(p.exists()) - p.touch(mode=0o700, exist_ok=False) - self.assertTrue(p.exists()) - self.assertRaises(OSError, p.touch, exist_ok=False) - - def test_touch_nochange(self): - P = self.cls(BASE) - p = P / 'fileA' - p.touch() - with p.open('rb') as f: - self.assertEqual(f.read().strip(), b"this is file A") - - def test_mkdir(self): - P = self.cls(BASE) - p = P / 'newdirA' - self.assertFalse(p.exists()) - p.mkdir() - self.assertTrue(p.exists()) - self.assertTrue(p.is_dir()) - with self.assertRaises(OSError) as cm: - p.mkdir() - self.assertEqual(cm.exception.errno, errno.EEXIST) - - def test_mkdir_parents(self): - # Creating a chain of directories. - p = self.cls(BASE, 'newdirB', 'newdirC') - self.assertFalse(p.exists()) - with self.assertRaises(OSError) as cm: - p.mkdir() - self.assertEqual(cm.exception.errno, errno.ENOENT) - p.mkdir(parents=True) - self.assertTrue(p.exists()) - self.assertTrue(p.is_dir()) - with self.assertRaises(OSError) as cm: - p.mkdir(parents=True) - self.assertEqual(cm.exception.errno, errno.EEXIST) - # Test `mode` arg. - mode = stat.S_IMODE(p.stat().st_mode) # Default mode. - p = self.cls(BASE, 'newdirD', 'newdirE') - p.mkdir(0o555, parents=True) - self.assertTrue(p.exists()) - self.assertTrue(p.is_dir()) - if os.name != 'nt': - # The directory's permissions follow the mode argument. - self.assertEqual(stat.S_IMODE(p.stat().st_mode), 0o7555 & mode) - # The parent's permissions follow the default process settings. - self.assertEqual(stat.S_IMODE(p.parent.stat().st_mode), mode) - - def test_mkdir_exist_ok(self): - p = self.cls(BASE, 'dirB') - st_ctime_first = p.stat().st_ctime - self.assertTrue(p.exists()) - self.assertTrue(p.is_dir()) - with self.assertRaises(FileExistsError) as cm: - p.mkdir() - self.assertEqual(cm.exception.errno, errno.EEXIST) - p.mkdir(exist_ok=True) - self.assertTrue(p.exists()) - self.assertEqual(p.stat().st_ctime, st_ctime_first) - - def test_mkdir_exist_ok_with_parent(self): - p = self.cls(BASE, 'dirC') - self.assertTrue(p.exists()) - with self.assertRaises(FileExistsError) as cm: - p.mkdir() - self.assertEqual(cm.exception.errno, errno.EEXIST) - p = p / 'newdirC' - p.mkdir(parents=True) - st_ctime_first = p.stat().st_ctime - self.assertTrue(p.exists()) - with self.assertRaises(FileExistsError) as cm: - p.mkdir(parents=True) - self.assertEqual(cm.exception.errno, errno.EEXIST) - p.mkdir(parents=True, exist_ok=True) - self.assertTrue(p.exists()) - self.assertEqual(p.stat().st_ctime, st_ctime_first) - - @unittest.skipIf(is_emscripten, "FS root cannot be modified on Emscripten.") - def test_mkdir_exist_ok_root(self): - # Issue #25803: A drive root could raise PermissionError on Windows. - self.cls('/').resolve().mkdir(exist_ok=True) - self.cls('/').resolve().mkdir(parents=True, exist_ok=True) - - @only_nt # XXX: not sure how to test this on POSIX. - def test_mkdir_with_unknown_drive(self): - for d in 'ZYXWVUTSRQPONMLKJIHGFEDCBA': - p = self.cls(d + ':\\') - if not p.is_dir(): - break - else: - self.skipTest("cannot find a drive that doesn't exist") - with self.assertRaises(OSError): - (p / 'child' / 'path').mkdir(parents=True) - - def test_mkdir_with_child_file(self): - p = self.cls(BASE, 'dirB', 'fileB') - self.assertTrue(p.exists()) - # An exception is raised when the last path component is an existing - # regular file, regardless of whether exist_ok is true or not. - with self.assertRaises(FileExistsError) as cm: - p.mkdir(parents=True) - self.assertEqual(cm.exception.errno, errno.EEXIST) - with self.assertRaises(FileExistsError) as cm: - p.mkdir(parents=True, exist_ok=True) - self.assertEqual(cm.exception.errno, errno.EEXIST) - - def test_mkdir_no_parents_file(self): - p = self.cls(BASE, 'fileA') - self.assertTrue(p.exists()) - # An exception is raised when the last path component is an existing - # regular file, regardless of whether exist_ok is true or not. - with self.assertRaises(FileExistsError) as cm: - p.mkdir() - self.assertEqual(cm.exception.errno, errno.EEXIST) - with self.assertRaises(FileExistsError) as cm: - p.mkdir(exist_ok=True) - self.assertEqual(cm.exception.errno, errno.EEXIST) - - def test_mkdir_concurrent_parent_creation(self): - for pattern_num in range(32): - p = self.cls(BASE, 'dirCPC%d' % pattern_num) - self.assertFalse(p.exists()) - - real_mkdir = os.mkdir - def my_mkdir(path, mode=0o777): - path = str(path) - # Emulate another process that would create the directory - # just before we try to create it ourselves. We do it - # in all possible pattern combinations, assuming that this - # function is called at most 5 times (dirCPC/dir1/dir2, - # dirCPC/dir1, dirCPC, dirCPC/dir1, dirCPC/dir1/dir2). - if pattern.pop(): - real_mkdir(path, mode) # From another process. - concurrently_created.add(path) - real_mkdir(path, mode) # Our real call. - - pattern = [bool(pattern_num & (1 << n)) for n in range(5)] - concurrently_created = set() - p12 = p / 'dir1' / 'dir2' - try: - with mock.patch("os.mkdir", my_mkdir): - p12.mkdir(parents=True, exist_ok=False) - except FileExistsError: - self.assertIn(str(p12), concurrently_created) - else: - self.assertNotIn(str(p12), concurrently_created) - self.assertTrue(p.exists()) - - def test_symlink_to(self): - if not self.can_symlink: - self.skipTest("symlinks required") - P = self.cls(BASE) - target = P / 'fileA' - # Symlinking a path target. - link = P / 'dirA' / 'linkAA' - link.symlink_to(target) - self.assertEqual(link.stat(), target.stat()) - self.assertNotEqual(link.lstat(), target.stat()) - # Symlinking a str target. - link = P / 'dirA' / 'linkAAA' - link.symlink_to(str(target)) - self.assertEqual(link.stat(), target.stat()) - self.assertNotEqual(link.lstat(), target.stat()) - self.assertFalse(link.is_dir()) - # Symlinking to a directory. - target = P / 'dirB' - link = P / 'dirA' / 'linkAAAA' - link.symlink_to(target, target_is_directory=True) - self.assertEqual(link.stat(), target.stat()) - self.assertNotEqual(link.lstat(), target.stat()) - self.assertTrue(link.is_dir()) - self.assertTrue(list(link.iterdir())) - - @unittest.skipIf(hasattr(os, "symlink"), "os.symlink() is present") - def test_symlink_to_unsupported(self): - P = self.cls(BASE) - p = P / 'fileA' - # linking to another path. - q = P / 'dirA' / 'fileAA' - with self.assertRaises(pathlib.UnsupportedOperation): - q.symlink_to(p) - - def test_is_junction(self): - P = self.cls(BASE) - - with mock.patch.object(P.pathmod, 'isjunction'): - self.assertEqual(P.is_junction(), P.pathmod.isjunction.return_value) - P.pathmod.isjunction.assert_called_once_with(P) - - @unittest.skipUnless(hasattr(os, "mkfifo"), "os.mkfifo() required") - @unittest.skipIf(sys.platform == "vxworks", - "fifo requires special path on VxWorks") - def test_is_fifo_true(self): - P = self.cls(BASE, 'myfifo') - try: - os.mkfifo(str(P)) - except PermissionError as e: - self.skipTest('os.mkfifo(): %s' % e) - self.assertTrue(P.is_fifo()) - self.assertFalse(P.is_socket()) - self.assertFalse(P.is_file()) - self.assertIs(self.cls(BASE, 'myfifo\udfff').is_fifo(), False) - self.assertIs(self.cls(BASE, 'myfifo\x00').is_fifo(), False) - - @unittest.skipUnless(hasattr(socket, "AF_UNIX"), "Unix sockets required") - @unittest.skipIf( - is_emscripten, "Unix sockets are not implemented on Emscripten." - ) - @unittest.skipIf( - is_wasi, "Cannot create socket on WASI." - ) - def test_is_socket_true(self): - P = self.cls(BASE, 'mysock') - sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) - self.addCleanup(sock.close) - try: - sock.bind(str(P)) - except OSError as e: - if (isinstance(e, PermissionError) or - "AF_UNIX path too long" in str(e)): - self.skipTest("cannot bind Unix socket: " + str(e)) - self.assertTrue(P.is_socket()) - self.assertFalse(P.is_fifo()) - self.assertFalse(P.is_file()) - self.assertIs(self.cls(BASE, 'mysock\udfff').is_socket(), False) - self.assertIs(self.cls(BASE, 'mysock\x00').is_socket(), False) - - def test_is_char_device_true(self): - # Under Unix, /dev/null should generally be a char device. - P = self.cls('/dev/null') - if not P.exists(): - self.skipTest("/dev/null required") - self.assertTrue(P.is_char_device()) - self.assertFalse(P.is_block_device()) - self.assertFalse(P.is_file()) - self.assertIs(self.cls('/dev/null\udfff').is_char_device(), False) - self.assertIs(self.cls('/dev/null\x00').is_char_device(), False) - - def test_is_mount_root(self): - if os.name == 'nt': - R = self.cls('c:\\') - else: - R = self.cls('/') - self.assertTrue(R.is_mount()) - self.assertFalse((R / '\udfff').is_mount()) - - def test_passing_kwargs_deprecated(self): - with self.assertWarns(DeprecationWarning): - self.cls(foo="bar") - - -class WalkTests(unittest.TestCase): - - def setUp(self): - self.addCleanup(os_helper.rmtree, os_helper.TESTFN) - - # Build: - # TESTFN/ - # TEST1/ a file kid and two directory kids - # tmp1 - # SUB1/ a file kid and a directory kid - # tmp2 - # SUB11/ no kids - # SUB2/ a file kid and a dirsymlink kid - # tmp3 - # SUB21/ not readable - # tmp5 - # link/ a symlink to TEST2 - # broken_link - # broken_link2 - # broken_link3 - # TEST2/ - # tmp4 a lone file - self.walk_path = pathlib.Path(os_helper.TESTFN, "TEST1") - self.sub1_path = self.walk_path / "SUB1" - self.sub11_path = self.sub1_path / "SUB11" - self.sub2_path = self.walk_path / "SUB2" - sub21_path= self.sub2_path / "SUB21" - tmp1_path = self.walk_path / "tmp1" - tmp2_path = self.sub1_path / "tmp2" - tmp3_path = self.sub2_path / "tmp3" - tmp5_path = sub21_path / "tmp3" - self.link_path = self.sub2_path / "link" - t2_path = pathlib.Path(os_helper.TESTFN, "TEST2") - tmp4_path = pathlib.Path(os_helper.TESTFN, "TEST2", "tmp4") - broken_link_path = self.sub2_path / "broken_link" - broken_link2_path = self.sub2_path / "broken_link2" - broken_link3_path = self.sub2_path / "broken_link3" - - os.makedirs(self.sub11_path) - os.makedirs(self.sub2_path) - os.makedirs(sub21_path) - os.makedirs(t2_path) - - for path in tmp1_path, tmp2_path, tmp3_path, tmp4_path, tmp5_path: - with open(path, "x", encoding='utf-8') as f: - f.write(f"I'm {path} and proud of it. Blame test_pathlib.\n") - - if os_helper.can_symlink(): - os.symlink(os.path.abspath(t2_path), self.link_path) - os.symlink('broken', broken_link_path, True) - os.symlink(pathlib.Path('tmp3', 'broken'), broken_link2_path, True) - os.symlink(pathlib.Path('SUB21', 'tmp5'), broken_link3_path, True) - self.sub2_tree = (self.sub2_path, ["SUB21"], - ["broken_link", "broken_link2", "broken_link3", - "link", "tmp3"]) - else: - self.sub2_tree = (self.sub2_path, ["SUB21"], ["tmp3"]) - - if not is_emscripten: - # Emscripten fails with inaccessible directories. - os.chmod(sub21_path, 0) - try: - os.listdir(sub21_path) - except PermissionError: - self.addCleanup(os.chmod, sub21_path, stat.S_IRWXU) - else: - os.chmod(sub21_path, stat.S_IRWXU) - os.unlink(tmp5_path) - os.rmdir(sub21_path) - del self.sub2_tree[1][:1] - - def test_walk_topdown(self): - walker = self.walk_path.walk() - entry = next(walker) - entry[1].sort() # Ensure we visit SUB1 before SUB2 - self.assertEqual(entry, (self.walk_path, ["SUB1", "SUB2"], ["tmp1"])) - entry = next(walker) - self.assertEqual(entry, (self.sub1_path, ["SUB11"], ["tmp2"])) - entry = next(walker) - self.assertEqual(entry, (self.sub11_path, [], [])) - entry = next(walker) - entry[1].sort() - entry[2].sort() - self.assertEqual(entry, self.sub2_tree) - with self.assertRaises(StopIteration): - next(walker) - - def test_walk_prune(self, walk_path=None): - if walk_path is None: - walk_path = self.walk_path - # Prune the search. - all = [] - for root, dirs, files in walk_path.walk(): - all.append((root, dirs, files)) - if 'SUB1' in dirs: - # Note that this also mutates the dirs we appended to all! - dirs.remove('SUB1') - - self.assertEqual(len(all), 2) - self.assertEqual(all[0], (self.walk_path, ["SUB2"], ["tmp1"])) - - all[1][-1].sort() - all[1][1].sort() - self.assertEqual(all[1], self.sub2_tree) - - def test_file_like_path(self): - self.test_walk_prune(FakePath(self.walk_path).__fspath__()) - - def test_walk_bottom_up(self): - seen_testfn = seen_sub1 = seen_sub11 = seen_sub2 = False - for path, dirnames, filenames in self.walk_path.walk(top_down=False): - if path == self.walk_path: - self.assertFalse(seen_testfn) - self.assertTrue(seen_sub1) - self.assertTrue(seen_sub2) - self.assertEqual(sorted(dirnames), ["SUB1", "SUB2"]) - self.assertEqual(filenames, ["tmp1"]) - seen_testfn = True - elif path == self.sub1_path: - self.assertFalse(seen_testfn) - self.assertFalse(seen_sub1) - self.assertTrue(seen_sub11) - self.assertEqual(dirnames, ["SUB11"]) - self.assertEqual(filenames, ["tmp2"]) - seen_sub1 = True - elif path == self.sub11_path: - self.assertFalse(seen_sub1) - self.assertFalse(seen_sub11) - self.assertEqual(dirnames, []) - self.assertEqual(filenames, []) - seen_sub11 = True - elif path == self.sub2_path: - self.assertFalse(seen_testfn) - self.assertFalse(seen_sub2) - self.assertEqual(sorted(dirnames), sorted(self.sub2_tree[1])) - self.assertEqual(sorted(filenames), sorted(self.sub2_tree[2])) - seen_sub2 = True - else: - raise AssertionError(f"Unexpected path: {path}") - self.assertTrue(seen_testfn) - - @os_helper.skip_unless_symlink - def test_walk_follow_symlinks(self): - walk_it = self.walk_path.walk(follow_symlinks=True) - for root, dirs, files in walk_it: - if root == self.link_path: - self.assertEqual(dirs, []) - self.assertEqual(files, ["tmp4"]) - break - else: - self.fail("Didn't follow symlink with follow_symlinks=True") - - @os_helper.skip_unless_symlink - def test_walk_symlink_location(self): - # Tests whether symlinks end up in filenames or dirnames depending - # on the `follow_symlinks` argument. - walk_it = self.walk_path.walk(follow_symlinks=False) - for root, dirs, files in walk_it: - if root == self.sub2_path: - self.assertIn("link", files) - break - else: - self.fail("symlink not found") - - walk_it = self.walk_path.walk(follow_symlinks=True) - for root, dirs, files in walk_it: - if root == self.sub2_path: - self.assertIn("link", dirs) - break - - def test_walk_bad_dir(self): - errors = [] - walk_it = self.walk_path.walk(on_error=errors.append) - root, dirs, files = next(walk_it) - self.assertEqual(errors, []) - dir1 = 'SUB1' - path1 = root / dir1 - path1new = (root / dir1).with_suffix(".new") - path1.rename(path1new) - try: - roots = [r for r, _, _ in walk_it] - self.assertTrue(errors) - self.assertNotIn(path1, roots) - self.assertNotIn(path1new, roots) - for dir2 in dirs: - if dir2 != dir1: - self.assertIn(root / dir2, roots) - finally: - path1new.rename(path1) - - def test_walk_many_open_files(self): - depth = 30 - base = pathlib.Path(os_helper.TESTFN, 'deep') - path = pathlib.Path(base, *(['d']*depth)) - path.mkdir(parents=True) - - iters = [base.walk(top_down=False) for _ in range(100)] - for i in range(depth + 1): - expected = (path, ['d'] if i else [], []) - for it in iters: - self.assertEqual(next(it), expected) - path = path.parent - - iters = [base.walk(top_down=True) for _ in range(100)] - path = base - for i in range(depth + 1): - expected = (path, ['d'] if i < depth else [], []) - for it in iters: - self.assertEqual(next(it), expected) - path = path / 'd' - - def test_walk_above_recursion_limit(self): - recursion_limit = 40 - # directory_depth > recursion_limit - directory_depth = recursion_limit + 10 - base = pathlib.Path(os_helper.TESTFN, 'deep') - path = pathlib.Path(base, *(['d'] * directory_depth)) - path.mkdir(parents=True) - - with set_recursion_limit(recursion_limit): - list(base.walk()) - list(base.walk(top_down=False)) - - -@only_posix -class PosixPathTest(PathTest): - cls = pathlib.PosixPath - - def test_absolute(self): - P = self.cls - self.assertEqual(str(P('/').absolute()), '/') - self.assertEqual(str(P('/a').absolute()), '/a') - self.assertEqual(str(P('/a/b').absolute()), '/a/b') - - # '//'-prefixed absolute path (supported by POSIX). - self.assertEqual(str(P('//').absolute()), '//') - self.assertEqual(str(P('//a').absolute()), '//a') - self.assertEqual(str(P('//a/b').absolute()), '//a/b') - - def _check_symlink_loop(self, *args, strict=True): - path = self.cls(*args) - with self.assertRaises(RuntimeError): - print(path.resolve(strict)) - - @unittest.skipIf( - is_emscripten or is_wasi, - "umask is not implemented on Emscripten/WASI." - ) - def test_open_mode(self): - old_mask = os.umask(0) - self.addCleanup(os.umask, old_mask) - p = self.cls(BASE) - with (p / 'new_file').open('wb'): - pass - st = os.stat(join('new_file')) - self.assertEqual(stat.S_IMODE(st.st_mode), 0o666) - os.umask(0o022) - with (p / 'other_new_file').open('wb'): - pass - st = os.stat(join('other_new_file')) - self.assertEqual(stat.S_IMODE(st.st_mode), 0o644) - - def test_resolve_root(self): - current_directory = os.getcwd() - try: - os.chdir('/') - p = self.cls('spam') - self.assertEqual(str(p.resolve()), '/spam') - finally: - os.chdir(current_directory) - - @unittest.skipIf( - is_emscripten or is_wasi, - "umask is not implemented on Emscripten/WASI." - ) - def test_touch_mode(self): - old_mask = os.umask(0) - self.addCleanup(os.umask, old_mask) - p = self.cls(BASE) - (p / 'new_file').touch() - st = os.stat(join('new_file')) - self.assertEqual(stat.S_IMODE(st.st_mode), 0o666) - os.umask(0o022) - (p / 'other_new_file').touch() - st = os.stat(join('other_new_file')) - self.assertEqual(stat.S_IMODE(st.st_mode), 0o644) - (p / 'masked_new_file').touch(mode=0o750) - st = os.stat(join('masked_new_file')) - self.assertEqual(stat.S_IMODE(st.st_mode), 0o750) - - def test_resolve_loop(self): - if not self.can_symlink: - self.skipTest("symlinks required") - # Loops with relative symlinks. - os.symlink('linkX/inside', join('linkX')) - self._check_symlink_loop(BASE, 'linkX') - os.symlink('linkY', join('linkY')) - self._check_symlink_loop(BASE, 'linkY') - os.symlink('linkZ/../linkZ', join('linkZ')) - self._check_symlink_loop(BASE, 'linkZ') - # Non-strict - self._check_symlink_loop(BASE, 'linkZ', 'foo', strict=False) - # Loops with absolute symlinks. - os.symlink(join('linkU/inside'), join('linkU')) - self._check_symlink_loop(BASE, 'linkU') - os.symlink(join('linkV'), join('linkV')) - self._check_symlink_loop(BASE, 'linkV') - os.symlink(join('linkW/../linkW'), join('linkW')) - self._check_symlink_loop(BASE, 'linkW') - # Non-strict - self._check_symlink_loop(BASE, 'linkW', 'foo', strict=False) - - def test_glob(self): - P = self.cls - p = P(BASE) - given = set(p.glob("FILEa")) - expect = set() if not os_helper.fs_is_case_insensitive(BASE) else given - self.assertEqual(given, expect) - self.assertEqual(set(p.glob("FILEa*")), set()) - - def test_rglob(self): - P = self.cls - p = P(BASE, "dirC") - given = set(p.rglob("FILEd")) - expect = set() if not os_helper.fs_is_case_insensitive(BASE) else given - self.assertEqual(given, expect) - self.assertEqual(set(p.rglob("FILEd*")), set()) - - @unittest.skipUnless(hasattr(pwd, 'getpwall'), - 'pwd module does not expose getpwall()') - @unittest.skipIf(sys.platform == "vxworks", - "no home directory on VxWorks") - def test_expanduser(self): - P = self.cls - import_helper.import_module('pwd') - import pwd - pwdent = pwd.getpwuid(os.getuid()) - username = pwdent.pw_name - userhome = pwdent.pw_dir.rstrip('/') or '/' - # Find arbitrary different user (if exists). - for pwdent in pwd.getpwall(): - othername = pwdent.pw_name - otherhome = pwdent.pw_dir.rstrip('/') - if othername != username and otherhome: - break - else: - othername = username - otherhome = userhome - - fakename = 'fakeuser' - # This user can theoretically exist on a test runner. Create unique name: - try: - while pwd.getpwnam(fakename): - fakename += '1' - except KeyError: - pass # Non-existent name found - - p1 = P('~/Documents') - p2 = P(f'~{username}/Documents') - p3 = P(f'~{othername}/Documents') - p4 = P(f'../~{username}/Documents') - p5 = P(f'/~{username}/Documents') - p6 = P('') - p7 = P(f'~{fakename}/Documents') - - with os_helper.EnvironmentVarGuard() as env: - env.pop('HOME', None) - - self.assertEqual(p1.expanduser(), P(userhome) / 'Documents') - self.assertEqual(p2.expanduser(), P(userhome) / 'Documents') - self.assertEqual(p3.expanduser(), P(otherhome) / 'Documents') - self.assertEqual(p4.expanduser(), p4) - self.assertEqual(p5.expanduser(), p5) - self.assertEqual(p6.expanduser(), p6) - self.assertRaises(RuntimeError, p7.expanduser) - - env['HOME'] = '/tmp' - self.assertEqual(p1.expanduser(), P('/tmp/Documents')) - self.assertEqual(p2.expanduser(), P(userhome) / 'Documents') - self.assertEqual(p3.expanduser(), P(otherhome) / 'Documents') - self.assertEqual(p4.expanduser(), p4) - self.assertEqual(p5.expanduser(), p5) - self.assertEqual(p6.expanduser(), p6) - self.assertRaises(RuntimeError, p7.expanduser) - - @unittest.skipIf(sys.platform != "darwin", - "Bad file descriptor in /dev/fd affects only macOS") - def test_handling_bad_descriptor(self): - try: - file_descriptors = list(pathlib.Path('/dev/fd').rglob("*"))[3:] - if not file_descriptors: - self.skipTest("no file descriptors - issue was not reproduced") - # Checking all file descriptors because there is no guarantee - # which one will fail. - for f in file_descriptors: - f.exists() - f.is_dir() - f.is_file() - f.is_symlink() - f.is_block_device() - f.is_char_device() - f.is_fifo() - f.is_socket() - except OSError as e: - if e.errno == errno.EBADF: - self.fail("Bad file descriptor not handled.") - raise - - -@only_nt -class WindowsPathTest(PathTest): - cls = pathlib.WindowsPath - - def test_absolute(self): - P = self.cls - - # Simple absolute paths. - self.assertEqual(str(P('c:\\').absolute()), 'c:\\') - self.assertEqual(str(P('c:\\a').absolute()), 'c:\\a') - self.assertEqual(str(P('c:\\a\\b').absolute()), 'c:\\a\\b') - - # UNC absolute paths. - share = '\\\\server\\share\\' - self.assertEqual(str(P(share).absolute()), share) - self.assertEqual(str(P(share + 'a').absolute()), share + 'a') - self.assertEqual(str(P(share + 'a\\b').absolute()), share + 'a\\b') - - # UNC relative paths. - with mock.patch("os.getcwd") as getcwd: - getcwd.return_value = share - - self.assertEqual(str(P().absolute()), share) - self.assertEqual(str(P('.').absolute()), share) - self.assertEqual(str(P('a').absolute()), os.path.join(share, 'a')) - self.assertEqual(str(P('a', 'b', 'c').absolute()), - os.path.join(share, 'a', 'b', 'c')) - - drive = os.path.splitdrive(BASE)[0] - with os_helper.change_cwd(BASE): - # Relative path with root - self.assertEqual(str(P('\\').absolute()), drive + '\\') - self.assertEqual(str(P('\\foo').absolute()), drive + '\\foo') - - # Relative path on current drive - self.assertEqual(str(P(drive).absolute()), BASE) - self.assertEqual(str(P(drive + 'foo').absolute()), os.path.join(BASE, 'foo')) - - with os_helper.subst_drive(BASE) as other_drive: - # Set the working directory on the substitute drive - saved_cwd = os.getcwd() - other_cwd = f'{other_drive}\\dirA' - os.chdir(other_cwd) - os.chdir(saved_cwd) - - # Relative path on another drive - self.assertEqual(str(P(other_drive).absolute()), other_cwd) - self.assertEqual(str(P(other_drive + 'foo').absolute()), other_cwd + '\\foo') - - def test_glob(self): - P = self.cls - p = P(BASE) - self.assertEqual(set(p.glob("FILEa")), { P(BASE, "fileA") }) - self.assertEqual(set(p.glob("*a\\")), { P(BASE, "dirA") }) - self.assertEqual(set(p.glob("F*a")), { P(BASE, "fileA") }) - self.assertEqual(set(map(str, p.glob("FILEa"))), {f"{p}\\fileA"}) - self.assertEqual(set(map(str, p.glob("F*a"))), {f"{p}\\fileA"}) - - def test_rglob(self): - P = self.cls - p = P(BASE, "dirC") - self.assertEqual(set(p.rglob("FILEd")), { P(BASE, "dirC/dirD/fileD") }) - self.assertEqual(set(p.rglob("*\\")), { P(BASE, "dirC/dirD") }) - self.assertEqual(set(map(str, p.rglob("FILEd"))), {f"{p}\\dirD\\fileD"}) - - def test_expanduser(self): - P = self.cls - with os_helper.EnvironmentVarGuard() as env: - env.pop('HOME', None) - env.pop('USERPROFILE', None) - env.pop('HOMEPATH', None) - env.pop('HOMEDRIVE', None) - env['USERNAME'] = 'alice' - - # test that the path returns unchanged - p1 = P('~/My Documents') - p2 = P('~alice/My Documents') - p3 = P('~bob/My Documents') - p4 = P('/~/My Documents') - p5 = P('d:~/My Documents') - p6 = P('') - self.assertRaises(RuntimeError, p1.expanduser) - self.assertRaises(RuntimeError, p2.expanduser) - self.assertRaises(RuntimeError, p3.expanduser) - self.assertEqual(p4.expanduser(), p4) - self.assertEqual(p5.expanduser(), p5) - self.assertEqual(p6.expanduser(), p6) - - def check(): - env.pop('USERNAME', None) - self.assertEqual(p1.expanduser(), - P('C:/Users/alice/My Documents')) - self.assertRaises(RuntimeError, p2.expanduser) - env['USERNAME'] = 'alice' - self.assertEqual(p2.expanduser(), - P('C:/Users/alice/My Documents')) - self.assertEqual(p3.expanduser(), - P('C:/Users/bob/My Documents')) - self.assertEqual(p4.expanduser(), p4) - self.assertEqual(p5.expanduser(), p5) - self.assertEqual(p6.expanduser(), p6) - - env['HOMEPATH'] = 'C:\\Users\\alice' - check() - - env['HOMEDRIVE'] = 'C:\\' - env['HOMEPATH'] = 'Users\\alice' - check() - - env.pop('HOMEDRIVE', None) - env.pop('HOMEPATH', None) - env['USERPROFILE'] = 'C:\\Users\\alice' - check() - - # bpo-38883: ignore `HOME` when set on windows - env['HOME'] = 'C:\\Users\\eve' - check() - - - -class PathSubclassTest(PathTest): - class cls(pathlib.Path): - pass - - # repr() roundtripping is not supported in custom subclass. - test_repr_roundtrips = None - - -class CompatiblePathTest(unittest.TestCase): - """ - Test that a type can be made compatible with PurePath - derivatives by implementing division operator overloads. - """ - - class CompatPath: - """ - Minimum viable class to test PurePath compatibility. - Simply uses the division operator to join a given - string and the string value of another object with - a forward slash. - """ - def __init__(self, string): - self.string = string - - def __truediv__(self, other): - return type(self)(f"{self.string}/{other}") - - def __rtruediv__(self, other): - return type(self)(f"{other}/{self.string}") - - def test_truediv(self): - result = pathlib.PurePath("test") / self.CompatPath("right") - self.assertIsInstance(result, self.CompatPath) - self.assertEqual(result.string, "test/right") - - with self.assertRaises(TypeError): - # Verify improper operations still raise a TypeError - pathlib.PurePath("test") / 10 - - def test_rtruediv(self): - result = self.CompatPath("left") / pathlib.PurePath("test") - self.assertIsInstance(result, self.CompatPath) - self.assertEqual(result.string, "left/test") - - with self.assertRaises(TypeError): - # Verify improper operations still raise a TypeError - 10 / pathlib.PurePath("test") - - -if __name__ == "__main__": - unittest.main() diff --git a/Lib/test/test_pathlib/__init__.py b/Lib/test/test_pathlib/__init__.py new file mode 100644 index 00000000000000..4b16ecc31156a5 --- /dev/null +++ b/Lib/test/test_pathlib/__init__.py @@ -0,0 +1,5 @@ +import os +from test.support import load_package_tests + +def load_tests(*args): + return load_package_tests(os.path.dirname(__file__), *args) diff --git a/Lib/test/test_pathlib/test_pathlib.py b/Lib/test/test_pathlib/test_pathlib.py new file mode 100644 index 00000000000000..04e6280509ecfc --- /dev/null +++ b/Lib/test/test_pathlib/test_pathlib.py @@ -0,0 +1,2240 @@ +import io +import os +import sys +import errno +import ntpath +import pathlib +import pickle +import posixpath +import socket +import stat +import tempfile +import unittest +from unittest import mock +from urllib.request import pathname2url + +from test.support import import_helper +from test.support import is_emscripten, is_wasi +from test.support import set_recursion_limit +from test.support import os_helper +from test.support.os_helper import TESTFN, FakePath +from test.test_pathlib import test_pathlib_abc + +try: + import grp, pwd +except ImportError: + grp = pwd = None + + +only_nt = unittest.skipIf(os.name != 'nt', + 'test requires a Windows-compatible system') +only_posix = unittest.skipIf(os.name == 'nt', + 'test requires a POSIX-compatible system') + +root_in_posix = False +if hasattr(os, 'geteuid'): + root_in_posix = (os.geteuid() == 0) + +# +# Tests for the pure classes. +# + +class PurePathTest(test_pathlib_abc.DummyPurePathTest): + cls = pathlib.PurePath + + # Make sure any symbolic links in the base test path are resolved. + base = os.path.realpath(TESTFN) + + # Keys are canonical paths, values are list of tuples of arguments + # supposed to produce equal paths. + equivalences = { + 'a/b': [ + ('a', 'b'), ('a/', 'b'), ('a', 'b/'), ('a/', 'b/'), + ('a/b/',), ('a//b',), ('a//b//',), + # Empty components get removed. + ('', 'a', 'b'), ('a', '', 'b'), ('a', 'b', ''), + ], + '/b/c/d': [ + ('a', '/b/c', 'd'), ('/a', '/b/c', 'd'), + # Empty components get removed. + ('/', 'b', '', 'c/d'), ('/', '', 'b/c/d'), ('', '/b/c/d'), + ], + } + + def test_concrete_class(self): + if self.cls is pathlib.PurePath: + expected = pathlib.PureWindowsPath if os.name == 'nt' else pathlib.PurePosixPath + else: + expected = self.cls + p = self.cls('a') + self.assertIs(type(p), expected) + + def test_concrete_pathmod(self): + if self.cls is pathlib.PurePosixPath: + expected = posixpath + elif self.cls is pathlib.PureWindowsPath: + expected = ntpath + else: + expected = os.path + p = self.cls('a') + self.assertIs(p.pathmod, expected) + + def test_different_pathmods_unequal(self): + p = self.cls('a') + if p.pathmod is posixpath: + q = pathlib.PureWindowsPath('a') + else: + q = pathlib.PurePosixPath('a') + self.assertNotEqual(p, q) + + def test_different_pathmods_unordered(self): + p = self.cls('a') + if p.pathmod is posixpath: + q = pathlib.PureWindowsPath('a') + else: + q = pathlib.PurePosixPath('a') + with self.assertRaises(TypeError): + p < q + with self.assertRaises(TypeError): + p <= q + with self.assertRaises(TypeError): + p > q + with self.assertRaises(TypeError): + p >= q + + def test_constructor_nested(self): + P = self.cls + P(FakePath("a/b/c")) + self.assertEqual(P(P('a')), P('a')) + self.assertEqual(P(P('a'), 'b'), P('a/b')) + self.assertEqual(P(P('a'), P('b')), P('a/b')) + self.assertEqual(P(P('a'), P('b'), P('c')), P(FakePath("a/b/c"))) + self.assertEqual(P(P('./a:b')), P('./a:b')) + + def _check_parse_path(self, raw_path, *expected): + sep = self.pathmod.sep + actual = self.cls._parse_path(raw_path.replace('/', sep)) + self.assertEqual(actual, expected) + if altsep := self.pathmod.altsep: + actual = self.cls._parse_path(raw_path.replace('/', altsep)) + self.assertEqual(actual, expected) + + def test_parse_path_common(self): + check = self._check_parse_path + sep = self.pathmod.sep + check('', '', '', []) + check('a', '', '', ['a']) + check('a/', '', '', ['a']) + check('a/b', '', '', ['a', 'b']) + check('a/b/', '', '', ['a', 'b']) + check('a/b/c/d', '', '', ['a', 'b', 'c', 'd']) + check('a/b//c/d', '', '', ['a', 'b', 'c', 'd']) + check('a/b/c/d', '', '', ['a', 'b', 'c', 'd']) + check('.', '', '', []) + check('././b', '', '', ['b']) + check('a/./b', '', '', ['a', 'b']) + check('a/./.', '', '', ['a']) + check('/a/b', '', sep, ['a', 'b']) + + def test_empty_path(self): + # The empty path points to '.' + p = self.cls('') + self.assertEqual(str(p), '.') + # Special case for the empty path. + self._check_str('.', ('',)) + + def test_parts_interning(self): + P = self.cls + p = P('/usr/bin/foo') + q = P('/usr/local/bin') + # 'usr' + self.assertIs(p.parts[1], q.parts[1]) + # 'bin' + self.assertIs(p.parts[2], q.parts[3]) + + def test_join_nested(self): + P = self.cls + p = P('a/b').joinpath(P('c')) + self.assertEqual(p, P('a/b/c')) + + def test_div_nested(self): + P = self.cls + p = P('a/b') / P('c') + self.assertEqual(p, P('a/b/c')) + + def test_pickling_common(self): + P = self.cls + for pathstr in ('a', 'a/', 'a/b', 'a/b/c', '/', '/a/b', '/a/b/c', 'a/b/c/'): + with self.subTest(pathstr=pathstr): + p = P(pathstr) + for proto in range(0, pickle.HIGHEST_PROTOCOL + 1): + dumped = pickle.dumps(p, proto) + pp = pickle.loads(dumped) + self.assertIs(pp.__class__, p.__class__) + self.assertEqual(pp, p) + self.assertEqual(hash(pp), hash(p)) + self.assertEqual(str(pp), str(p)) + + def test_repr_common(self): + for pathstr in ('a', 'a/b', 'a/b/c', '/', '/a/b', '/a/b/c'): + with self.subTest(pathstr=pathstr): + p = self.cls(pathstr) + clsname = p.__class__.__name__ + r = repr(p) + # The repr() is in the form ClassName("forward-slashes path"). + self.assertTrue(r.startswith(clsname + '('), r) + self.assertTrue(r.endswith(')'), r) + inner = r[len(clsname) + 1 : -1] + self.assertEqual(eval(inner), p.as_posix()) + + def test_fspath_common(self): + P = self.cls + p = P('a/b') + self._check_str(p.__fspath__(), ('a/b',)) + self._check_str(os.fspath(p), ('a/b',)) + + def test_bytes(self): + P = self.cls + message = (r"argument should be a str or an os\.PathLike object " + r"where __fspath__ returns a str, not 'bytes'") + with self.assertRaisesRegex(TypeError, message): + P(b'a') + with self.assertRaisesRegex(TypeError, message): + P(b'a', 'b') + with self.assertRaisesRegex(TypeError, message): + P('a', b'b') + with self.assertRaises(TypeError): + P('a').joinpath(b'b') + with self.assertRaises(TypeError): + P('a') / b'b' + with self.assertRaises(TypeError): + b'a' / P('b') + with self.assertRaises(TypeError): + P('a').match(b'b') + with self.assertRaises(TypeError): + P('a').relative_to(b'b') + with self.assertRaises(TypeError): + P('a').with_name(b'b') + with self.assertRaises(TypeError): + P('a').with_stem(b'b') + with self.assertRaises(TypeError): + P('a').with_suffix(b'b') + + def test_as_bytes_common(self): + sep = os.fsencode(self.sep) + P = self.cls + self.assertEqual(bytes(P('a/b')), b'a' + sep + b'b') + + def test_eq_common(self): + P = self.cls + self.assertEqual(P('a/b'), P('a/b')) + self.assertEqual(P('a/b'), P('a', 'b')) + self.assertNotEqual(P('a/b'), P('a')) + self.assertNotEqual(P('a/b'), P('/a/b')) + self.assertNotEqual(P('a/b'), P()) + self.assertNotEqual(P('/a/b'), P('/')) + self.assertNotEqual(P(), P('/')) + self.assertNotEqual(P(), "") + self.assertNotEqual(P(), {}) + self.assertNotEqual(P(), int) + + def test_equivalences(self): + for k, tuples in self.equivalences.items(): + canon = k.replace('/', self.sep) + posix = k.replace(self.sep, '/') + if canon != posix: + tuples = tuples + [ + tuple(part.replace('/', self.sep) for part in t) + for t in tuples + ] + tuples.append((posix, )) + pcanon = self.cls(canon) + for t in tuples: + p = self.cls(*t) + self.assertEqual(p, pcanon, "failed with args {}".format(t)) + self.assertEqual(hash(p), hash(pcanon)) + self.assertEqual(str(p), canon) + self.assertEqual(p.as_posix(), posix) + + def test_ordering_common(self): + # Ordering is tuple-alike. + def assertLess(a, b): + self.assertLess(a, b) + self.assertGreater(b, a) + P = self.cls + a = P('a') + b = P('a/b') + c = P('abc') + d = P('b') + assertLess(a, b) + assertLess(a, c) + assertLess(a, d) + assertLess(b, c) + assertLess(c, d) + P = self.cls + a = P('/a') + b = P('/a/b') + c = P('/abc') + d = P('/b') + assertLess(a, b) + assertLess(a, c) + assertLess(a, d) + assertLess(b, c) + assertLess(c, d) + with self.assertRaises(TypeError): + P() < {} + + def test_as_uri_common(self): + P = self.cls + with self.assertRaises(ValueError): + P('a').as_uri() + with self.assertRaises(ValueError): + P().as_uri() + + def test_repr_roundtrips(self): + for pathstr in ('a', 'a/b', 'a/b/c', '/', '/a/b', '/a/b/c'): + with self.subTest(pathstr=pathstr): + p = self.cls(pathstr) + r = repr(p) + # The repr() roundtrips. + q = eval(r, pathlib.__dict__) + self.assertIs(q.__class__, p.__class__) + self.assertEqual(q, p) + self.assertEqual(repr(q), r) + + def test_name_empty(self): + P = self.cls + self.assertEqual(P('').name, '') + self.assertEqual(P('.').name, '') + self.assertEqual(P('/a/b/.').name, 'b') + + def test_stem_empty(self): + P = self.cls + self.assertEqual(P('').stem, '') + self.assertEqual(P('.').stem, '') + + def test_with_name_empty(self): + P = self.cls + self.assertRaises(ValueError, P('').with_name, 'd.xml') + self.assertRaises(ValueError, P('.').with_name, 'd.xml') + self.assertRaises(ValueError, P('/').with_name, 'd.xml') + self.assertRaises(ValueError, P('a/b').with_name, '') + self.assertRaises(ValueError, P('a/b').with_name, '.') + + def test_with_stem_empty(self): + P = self.cls + self.assertRaises(ValueError, P('').with_stem, 'd') + self.assertRaises(ValueError, P('.').with_stem, 'd') + self.assertRaises(ValueError, P('/').with_stem, 'd') + self.assertRaises(ValueError, P('a/b').with_stem, '') + self.assertRaises(ValueError, P('a/b').with_stem, '.') + + def test_with_suffix_empty(self): + # Path doesn't have a "filename" component. + P = self.cls + self.assertRaises(ValueError, P('').with_suffix, '.gz') + self.assertRaises(ValueError, P('.').with_suffix, '.gz') + self.assertRaises(ValueError, P('/').with_suffix, '.gz') + + def test_relative_to_several_args(self): + P = self.cls + p = P('a/b') + with self.assertWarns(DeprecationWarning): + p.relative_to('a', 'b') + p.relative_to('a', 'b', walk_up=True) + + def test_is_relative_to_several_args(self): + P = self.cls + p = P('a/b') + with self.assertWarns(DeprecationWarning): + p.is_relative_to('a', 'b') + + def test_match_empty(self): + P = self.cls + self.assertRaises(ValueError, P('a').match, '') + self.assertRaises(ValueError, P('a').match, '.') + + +class PurePosixPathTest(PurePathTest): + cls = pathlib.PurePosixPath + + def test_parse_path(self): + check = self._check_parse_path + # Collapsing of excess leading slashes, except for the double-slash + # special case. + check('//a/b', '', '//', ['a', 'b']) + check('///a/b', '', '/', ['a', 'b']) + check('////a/b', '', '/', ['a', 'b']) + # Paths which look like NT paths aren't treated specially. + check('c:a', '', '', ['c:a',]) + check('c:\\a', '', '', ['c:\\a',]) + check('\\a', '', '', ['\\a',]) + + def test_root(self): + P = self.cls + self.assertEqual(P('/a/b').root, '/') + self.assertEqual(P('///a/b').root, '/') + # POSIX special case for two leading slashes. + self.assertEqual(P('//a/b').root, '//') + + def test_eq(self): + P = self.cls + self.assertNotEqual(P('a/b'), P('A/b')) + self.assertEqual(P('/a'), P('///a')) + self.assertNotEqual(P('/a'), P('//a')) + + def test_as_uri(self): + P = self.cls + self.assertEqual(P('/').as_uri(), 'file:///') + self.assertEqual(P('/a/b.c').as_uri(), 'file:///a/b.c') + self.assertEqual(P('/a/b%#c').as_uri(), 'file:///a/b%25%23c') + + def test_as_uri_non_ascii(self): + from urllib.parse import quote_from_bytes + P = self.cls + try: + os.fsencode('\xe9') + except UnicodeEncodeError: + self.skipTest("\\xe9 cannot be encoded to the filesystem encoding") + self.assertEqual(P('/a/b\xe9').as_uri(), + 'file:///a/b' + quote_from_bytes(os.fsencode('\xe9'))) + + def test_match(self): + P = self.cls + self.assertFalse(P('A.py').match('a.PY')) + + def test_is_absolute(self): + P = self.cls + self.assertFalse(P().is_absolute()) + self.assertFalse(P('a').is_absolute()) + self.assertFalse(P('a/b/').is_absolute()) + self.assertTrue(P('/').is_absolute()) + self.assertTrue(P('/a').is_absolute()) + self.assertTrue(P('/a/b/').is_absolute()) + self.assertTrue(P('//a').is_absolute()) + self.assertTrue(P('//a/b').is_absolute()) + + def test_is_reserved(self): + P = self.cls + self.assertIs(False, P('').is_reserved()) + self.assertIs(False, P('/').is_reserved()) + self.assertIs(False, P('/foo/bar').is_reserved()) + self.assertIs(False, P('/dev/con/PRN/NUL').is_reserved()) + + def test_join(self): + P = self.cls + p = P('//a') + pp = p.joinpath('b') + self.assertEqual(pp, P('//a/b')) + pp = P('/a').joinpath('//c') + self.assertEqual(pp, P('//c')) + pp = P('//a').joinpath('/c') + self.assertEqual(pp, P('/c')) + + def test_div(self): + # Basically the same as joinpath(). + P = self.cls + p = P('//a') + pp = p / 'b' + self.assertEqual(pp, P('//a/b')) + pp = P('/a') / '//c' + self.assertEqual(pp, P('//c')) + pp = P('//a') / '/c' + self.assertEqual(pp, P('/c')) + + def test_parse_windows_path(self): + P = self.cls + p = P('c:', 'a', 'b') + pp = P(pathlib.PureWindowsPath('c:\\a\\b')) + self.assertEqual(p, pp) + + +class PureWindowsPathTest(PurePathTest): + cls = pathlib.PureWindowsPath + + equivalences = PurePathTest.equivalences.copy() + equivalences.update({ + './a:b': [ ('./a:b',) ], + 'c:a': [ ('c:', 'a'), ('c:', 'a/'), ('.', 'c:', 'a') ], + 'c:/a': [ + ('c:/', 'a'), ('c:', '/', 'a'), ('c:', '/a'), + ('/z', 'c:/', 'a'), ('//x/y', 'c:/', 'a'), + ], + '//a/b/': [ ('//a/b',) ], + '//a/b/c': [ + ('//a/b', 'c'), ('//a/b/', 'c'), + ], + }) + + def test_parse_path(self): + check = self._check_parse_path + # First part is anchored. + check('c:', 'c:', '', []) + check('c:/', 'c:', '\\', []) + check('/', '', '\\', []) + check('c:a', 'c:', '', ['a']) + check('c:/a', 'c:', '\\', ['a']) + check('/a', '', '\\', ['a']) + # UNC paths. + check('//', '\\\\', '', []) + check('//a', '\\\\a', '', []) + check('//a/', '\\\\a\\', '', []) + check('//a/b', '\\\\a\\b', '\\', []) + check('//a/b/', '\\\\a\\b', '\\', []) + check('//a/b/c', '\\\\a\\b', '\\', ['c']) + # Collapsing and stripping excess slashes. + check('Z://b//c/d/', 'Z:', '\\', ['b', 'c', 'd']) + # UNC paths. + check('//b/c//d', '\\\\b\\c', '\\', ['d']) + # Extended paths. + check('//./c:', '\\\\.\\c:', '', []) + check('//?/c:/', '\\\\?\\c:', '\\', []) + check('//?/c:/a', '\\\\?\\c:', '\\', ['a']) + # Extended UNC paths (format is "\\?\UNC\server\share"). + check('//?', '\\\\?', '', []) + check('//?/', '\\\\?\\', '', []) + check('//?/UNC', '\\\\?\\UNC', '', []) + check('//?/UNC/', '\\\\?\\UNC\\', '', []) + check('//?/UNC/b', '\\\\?\\UNC\\b', '', []) + check('//?/UNC/b/', '\\\\?\\UNC\\b\\', '', []) + check('//?/UNC/b/c', '\\\\?\\UNC\\b\\c', '\\', []) + check('//?/UNC/b/c/', '\\\\?\\UNC\\b\\c', '\\', []) + check('//?/UNC/b/c/d', '\\\\?\\UNC\\b\\c', '\\', ['d']) + # UNC device paths + check('//./BootPartition/', '\\\\.\\BootPartition', '\\', []) + check('//?/BootPartition/', '\\\\?\\BootPartition', '\\', []) + check('//./PhysicalDrive0', '\\\\.\\PhysicalDrive0', '', []) + check('//?/Volume{}/', '\\\\?\\Volume{}', '\\', []) + check('//./nul', '\\\\.\\nul', '', []) + # Paths to files with NTFS alternate data streams + check('./c:s', '', '', ['c:s']) + check('cc:s', '', '', ['cc:s']) + check('C:c:s', 'C:', '', ['c:s']) + check('C:/c:s', 'C:', '\\', ['c:s']) + check('D:a/c:b', 'D:', '', ['a', 'c:b']) + check('D:/a/c:b', 'D:', '\\', ['a', 'c:b']) + + def test_str(self): + p = self.cls('a/b/c') + self.assertEqual(str(p), 'a\\b\\c') + p = self.cls('c:/a/b/c') + self.assertEqual(str(p), 'c:\\a\\b\\c') + p = self.cls('//a/b') + self.assertEqual(str(p), '\\\\a\\b\\') + p = self.cls('//a/b/c') + self.assertEqual(str(p), '\\\\a\\b\\c') + p = self.cls('//a/b/c/d') + self.assertEqual(str(p), '\\\\a\\b\\c\\d') + + def test_str_subclass(self): + self._check_str_subclass('.\\a:b') + self._check_str_subclass('c:') + self._check_str_subclass('c:a') + self._check_str_subclass('c:a\\b.txt') + self._check_str_subclass('c:\\') + self._check_str_subclass('c:\\a') + self._check_str_subclass('c:\\a\\b.txt') + self._check_str_subclass('\\\\some\\share') + self._check_str_subclass('\\\\some\\share\\a') + self._check_str_subclass('\\\\some\\share\\a\\b.txt') + + def test_eq(self): + P = self.cls + self.assertEqual(P('c:a/b'), P('c:a/b')) + self.assertEqual(P('c:a/b'), P('c:', 'a', 'b')) + self.assertNotEqual(P('c:a/b'), P('d:a/b')) + self.assertNotEqual(P('c:a/b'), P('c:/a/b')) + self.assertNotEqual(P('/a/b'), P('c:/a/b')) + # Case-insensitivity. + self.assertEqual(P('a/B'), P('A/b')) + self.assertEqual(P('C:a/B'), P('c:A/b')) + self.assertEqual(P('//Some/SHARE/a/B'), P('//somE/share/A/b')) + self.assertEqual(P('\u0130'), P('i\u0307')) + + def test_as_uri(self): + P = self.cls + with self.assertRaises(ValueError): + P('/a/b').as_uri() + with self.assertRaises(ValueError): + P('c:a/b').as_uri() + self.assertEqual(P('c:/').as_uri(), 'file:///c:/') + self.assertEqual(P('c:/a/b.c').as_uri(), 'file:///c:/a/b.c') + self.assertEqual(P('c:/a/b%#c').as_uri(), 'file:///c:/a/b%25%23c') + self.assertEqual(P('c:/a/b\xe9').as_uri(), 'file:///c:/a/b%C3%A9') + self.assertEqual(P('//some/share/').as_uri(), 'file://some/share/') + self.assertEqual(P('//some/share/a/b.c').as_uri(), + 'file://some/share/a/b.c') + self.assertEqual(P('//some/share/a/b%#c\xe9').as_uri(), + 'file://some/share/a/b%25%23c%C3%A9') + + def test_match(self): + P = self.cls + # Absolute patterns. + self.assertTrue(P('c:/b.py').match('*:/*.py')) + self.assertTrue(P('c:/b.py').match('c:/*.py')) + self.assertFalse(P('d:/b.py').match('c:/*.py')) # wrong drive + self.assertFalse(P('b.py').match('/*.py')) + self.assertFalse(P('b.py').match('c:*.py')) + self.assertFalse(P('b.py').match('c:/*.py')) + self.assertFalse(P('c:b.py').match('/*.py')) + self.assertFalse(P('c:b.py').match('c:/*.py')) + self.assertFalse(P('/b.py').match('c:*.py')) + self.assertFalse(P('/b.py').match('c:/*.py')) + # UNC patterns. + self.assertTrue(P('//some/share/a.py').match('//*/*/*.py')) + self.assertTrue(P('//some/share/a.py').match('//some/share/*.py')) + self.assertFalse(P('//other/share/a.py').match('//some/share/*.py')) + self.assertFalse(P('//some/share/a/b.py').match('//some/share/*.py')) + # Case-insensitivity. + self.assertTrue(P('B.py').match('b.PY')) + self.assertTrue(P('c:/a/B.Py').match('C:/A/*.pY')) + self.assertTrue(P('//Some/Share/B.Py').match('//somE/sharE/*.pY')) + # Path anchor doesn't match pattern anchor + self.assertFalse(P('c:/b.py').match('/*.py')) # 'c:/' vs '/' + self.assertFalse(P('c:/b.py').match('c:*.py')) # 'c:/' vs 'c:' + self.assertFalse(P('//some/share/a.py').match('/*.py')) # '//some/share/' vs '/' + + def test_ordering_common(self): + # Case-insensitivity. + def assertOrderedEqual(a, b): + self.assertLessEqual(a, b) + self.assertGreaterEqual(b, a) + P = self.cls + p = P('c:A/b') + q = P('C:a/B') + assertOrderedEqual(p, q) + self.assertFalse(p < q) + self.assertFalse(p > q) + p = P('//some/Share/A/b') + q = P('//Some/SHARE/a/B') + assertOrderedEqual(p, q) + self.assertFalse(p < q) + self.assertFalse(p > q) + + def test_parts(self): + P = self.cls + p = P('c:a/b') + parts = p.parts + self.assertEqual(parts, ('c:', 'a', 'b')) + p = P('c:/a/b') + parts = p.parts + self.assertEqual(parts, ('c:\\', 'a', 'b')) + p = P('//a/b/c/d') + parts = p.parts + self.assertEqual(parts, ('\\\\a\\b\\', 'c', 'd')) + + def test_parent(self): + # Anchored + P = self.cls + p = P('z:a/b/c') + self.assertEqual(p.parent, P('z:a/b')) + self.assertEqual(p.parent.parent, P('z:a')) + self.assertEqual(p.parent.parent.parent, P('z:')) + self.assertEqual(p.parent.parent.parent.parent, P('z:')) + p = P('z:/a/b/c') + self.assertEqual(p.parent, P('z:/a/b')) + self.assertEqual(p.parent.parent, P('z:/a')) + self.assertEqual(p.parent.parent.parent, P('z:/')) + self.assertEqual(p.parent.parent.parent.parent, P('z:/')) + p = P('//a/b/c/d') + self.assertEqual(p.parent, P('//a/b/c')) + self.assertEqual(p.parent.parent, P('//a/b')) + self.assertEqual(p.parent.parent.parent, P('//a/b')) + + def test_parents(self): + # Anchored + P = self.cls + p = P('z:a/b/') + par = p.parents + self.assertEqual(len(par), 2) + self.assertEqual(par[0], P('z:a')) + self.assertEqual(par[1], P('z:')) + self.assertEqual(par[0:1], (P('z:a'),)) + self.assertEqual(par[:-1], (P('z:a'),)) + self.assertEqual(par[:2], (P('z:a'), P('z:'))) + self.assertEqual(par[1:], (P('z:'),)) + self.assertEqual(par[::2], (P('z:a'),)) + self.assertEqual(par[::-1], (P('z:'), P('z:a'))) + self.assertEqual(list(par), [P('z:a'), P('z:')]) + with self.assertRaises(IndexError): + par[2] + p = P('z:/a/b/') + par = p.parents + self.assertEqual(len(par), 2) + self.assertEqual(par[0], P('z:/a')) + self.assertEqual(par[1], P('z:/')) + self.assertEqual(par[0:1], (P('z:/a'),)) + self.assertEqual(par[0:-1], (P('z:/a'),)) + self.assertEqual(par[:2], (P('z:/a'), P('z:/'))) + self.assertEqual(par[1:], (P('z:/'),)) + self.assertEqual(par[::2], (P('z:/a'),)) + self.assertEqual(par[::-1], (P('z:/'), P('z:/a'),)) + self.assertEqual(list(par), [P('z:/a'), P('z:/')]) + with self.assertRaises(IndexError): + par[2] + p = P('//a/b/c/d') + par = p.parents + self.assertEqual(len(par), 2) + self.assertEqual(par[0], P('//a/b/c')) + self.assertEqual(par[1], P('//a/b')) + self.assertEqual(par[0:1], (P('//a/b/c'),)) + self.assertEqual(par[0:-1], (P('//a/b/c'),)) + self.assertEqual(par[:2], (P('//a/b/c'), P('//a/b'))) + self.assertEqual(par[1:], (P('//a/b'),)) + self.assertEqual(par[::2], (P('//a/b/c'),)) + self.assertEqual(par[::-1], (P('//a/b'), P('//a/b/c'))) + self.assertEqual(list(par), [P('//a/b/c'), P('//a/b')]) + with self.assertRaises(IndexError): + par[2] + + def test_drive(self): + P = self.cls + self.assertEqual(P('c:').drive, 'c:') + self.assertEqual(P('c:a/b').drive, 'c:') + self.assertEqual(P('c:/').drive, 'c:') + self.assertEqual(P('c:/a/b/').drive, 'c:') + self.assertEqual(P('//a/b').drive, '\\\\a\\b') + self.assertEqual(P('//a/b/').drive, '\\\\a\\b') + self.assertEqual(P('//a/b/c/d').drive, '\\\\a\\b') + self.assertEqual(P('./c:a').drive, '') + + def test_root(self): + P = self.cls + self.assertEqual(P('c:').root, '') + self.assertEqual(P('c:a/b').root, '') + self.assertEqual(P('c:/').root, '\\') + self.assertEqual(P('c:/a/b/').root, '\\') + self.assertEqual(P('//a/b').root, '\\') + self.assertEqual(P('//a/b/').root, '\\') + self.assertEqual(P('//a/b/c/d').root, '\\') + + def test_anchor(self): + P = self.cls + self.assertEqual(P('c:').anchor, 'c:') + self.assertEqual(P('c:a/b').anchor, 'c:') + self.assertEqual(P('c:/').anchor, 'c:\\') + self.assertEqual(P('c:/a/b/').anchor, 'c:\\') + self.assertEqual(P('//a/b').anchor, '\\\\a\\b\\') + self.assertEqual(P('//a/b/').anchor, '\\\\a\\b\\') + self.assertEqual(P('//a/b/c/d').anchor, '\\\\a\\b\\') + + def test_name(self): + P = self.cls + self.assertEqual(P('c:').name, '') + self.assertEqual(P('c:/').name, '') + self.assertEqual(P('c:a/b').name, 'b') + self.assertEqual(P('c:/a/b').name, 'b') + self.assertEqual(P('c:a/b.py').name, 'b.py') + self.assertEqual(P('c:/a/b.py').name, 'b.py') + self.assertEqual(P('//My.py/Share.php').name, '') + self.assertEqual(P('//My.py/Share.php/a/b').name, 'b') + + def test_suffix(self): + P = self.cls + self.assertEqual(P('c:').suffix, '') + self.assertEqual(P('c:/').suffix, '') + self.assertEqual(P('c:a/b').suffix, '') + self.assertEqual(P('c:/a/b').suffix, '') + self.assertEqual(P('c:a/b.py').suffix, '.py') + self.assertEqual(P('c:/a/b.py').suffix, '.py') + self.assertEqual(P('c:a/.hgrc').suffix, '') + self.assertEqual(P('c:/a/.hgrc').suffix, '') + self.assertEqual(P('c:a/.hg.rc').suffix, '.rc') + self.assertEqual(P('c:/a/.hg.rc').suffix, '.rc') + self.assertEqual(P('c:a/b.tar.gz').suffix, '.gz') + self.assertEqual(P('c:/a/b.tar.gz').suffix, '.gz') + self.assertEqual(P('c:a/Some name. Ending with a dot.').suffix, '') + self.assertEqual(P('c:/a/Some name. Ending with a dot.').suffix, '') + self.assertEqual(P('//My.py/Share.php').suffix, '') + self.assertEqual(P('//My.py/Share.php/a/b').suffix, '') + + def test_suffixes(self): + P = self.cls + self.assertEqual(P('c:').suffixes, []) + self.assertEqual(P('c:/').suffixes, []) + self.assertEqual(P('c:a/b').suffixes, []) + self.assertEqual(P('c:/a/b').suffixes, []) + self.assertEqual(P('c:a/b.py').suffixes, ['.py']) + self.assertEqual(P('c:/a/b.py').suffixes, ['.py']) + self.assertEqual(P('c:a/.hgrc').suffixes, []) + self.assertEqual(P('c:/a/.hgrc').suffixes, []) + self.assertEqual(P('c:a/.hg.rc').suffixes, ['.rc']) + self.assertEqual(P('c:/a/.hg.rc').suffixes, ['.rc']) + self.assertEqual(P('c:a/b.tar.gz').suffixes, ['.tar', '.gz']) + self.assertEqual(P('c:/a/b.tar.gz').suffixes, ['.tar', '.gz']) + self.assertEqual(P('//My.py/Share.php').suffixes, []) + self.assertEqual(P('//My.py/Share.php/a/b').suffixes, []) + self.assertEqual(P('c:a/Some name. Ending with a dot.').suffixes, []) + self.assertEqual(P('c:/a/Some name. Ending with a dot.').suffixes, []) + + def test_stem(self): + P = self.cls + self.assertEqual(P('c:').stem, '') + self.assertEqual(P('c:.').stem, '') + self.assertEqual(P('c:..').stem, '..') + self.assertEqual(P('c:/').stem, '') + self.assertEqual(P('c:a/b').stem, 'b') + self.assertEqual(P('c:a/b.py').stem, 'b') + self.assertEqual(P('c:a/.hgrc').stem, '.hgrc') + self.assertEqual(P('c:a/.hg.rc').stem, '.hg') + self.assertEqual(P('c:a/b.tar.gz').stem, 'b.tar') + self.assertEqual(P('c:a/Some name. Ending with a dot.').stem, + 'Some name. Ending with a dot.') + + def test_with_name(self): + P = self.cls + self.assertEqual(P('c:a/b').with_name('d.xml'), P('c:a/d.xml')) + self.assertEqual(P('c:/a/b').with_name('d.xml'), P('c:/a/d.xml')) + self.assertEqual(P('c:a/Dot ending.').with_name('d.xml'), P('c:a/d.xml')) + self.assertEqual(P('c:/a/Dot ending.').with_name('d.xml'), P('c:/a/d.xml')) + self.assertRaises(ValueError, P('c:').with_name, 'd.xml') + self.assertRaises(ValueError, P('c:/').with_name, 'd.xml') + self.assertRaises(ValueError, P('//My/Share').with_name, 'd.xml') + self.assertEqual(str(P('a').with_name('d:')), '.\\d:') + self.assertEqual(str(P('a').with_name('d:e')), '.\\d:e') + self.assertEqual(P('c:a/b').with_name('d:'), P('c:a/d:')) + self.assertEqual(P('c:a/b').with_name('d:e'), P('c:a/d:e')) + self.assertRaises(ValueError, P('c:a/b').with_name, 'd:/e') + self.assertRaises(ValueError, P('c:a/b').with_name, '//My/Share') + + def test_with_stem(self): + P = self.cls + self.assertEqual(P('c:a/b').with_stem('d'), P('c:a/d')) + self.assertEqual(P('c:/a/b').with_stem('d'), P('c:/a/d')) + self.assertEqual(P('c:a/Dot ending.').with_stem('d'), P('c:a/d')) + self.assertEqual(P('c:/a/Dot ending.').with_stem('d'), P('c:/a/d')) + self.assertRaises(ValueError, P('c:').with_stem, 'd') + self.assertRaises(ValueError, P('c:/').with_stem, 'd') + self.assertRaises(ValueError, P('//My/Share').with_stem, 'd') + self.assertEqual(str(P('a').with_stem('d:')), '.\\d:') + self.assertEqual(str(P('a').with_stem('d:e')), '.\\d:e') + self.assertEqual(P('c:a/b').with_stem('d:'), P('c:a/d:')) + self.assertEqual(P('c:a/b').with_stem('d:e'), P('c:a/d:e')) + self.assertRaises(ValueError, P('c:a/b').with_stem, 'd:/e') + self.assertRaises(ValueError, P('c:a/b').with_stem, '//My/Share') + + def test_with_suffix(self): + P = self.cls + self.assertEqual(P('c:a/b').with_suffix('.gz'), P('c:a/b.gz')) + self.assertEqual(P('c:/a/b').with_suffix('.gz'), P('c:/a/b.gz')) + self.assertEqual(P('c:a/b.py').with_suffix('.gz'), P('c:a/b.gz')) + self.assertEqual(P('c:/a/b.py').with_suffix('.gz'), P('c:/a/b.gz')) + # Path doesn't have a "filename" component. + self.assertRaises(ValueError, P('').with_suffix, '.gz') + self.assertRaises(ValueError, P('.').with_suffix, '.gz') + self.assertRaises(ValueError, P('/').with_suffix, '.gz') + self.assertRaises(ValueError, P('//My/Share').with_suffix, '.gz') + # Invalid suffix. + self.assertRaises(ValueError, P('c:a/b').with_suffix, 'gz') + self.assertRaises(ValueError, P('c:a/b').with_suffix, '/') + self.assertRaises(ValueError, P('c:a/b').with_suffix, '\\') + self.assertRaises(ValueError, P('c:a/b').with_suffix, 'c:') + self.assertRaises(ValueError, P('c:a/b').with_suffix, '/.gz') + self.assertRaises(ValueError, P('c:a/b').with_suffix, '\\.gz') + self.assertRaises(ValueError, P('c:a/b').with_suffix, 'c:.gz') + self.assertRaises(ValueError, P('c:a/b').with_suffix, 'c/d') + self.assertRaises(ValueError, P('c:a/b').with_suffix, 'c\\d') + self.assertRaises(ValueError, P('c:a/b').with_suffix, '.c/d') + self.assertRaises(ValueError, P('c:a/b').with_suffix, '.c\\d') + + def test_relative_to(self): + P = self.cls + p = P('C:Foo/Bar') + self.assertEqual(p.relative_to(P('c:')), P('Foo/Bar')) + self.assertEqual(p.relative_to('c:'), P('Foo/Bar')) + self.assertEqual(p.relative_to(P('c:foO')), P('Bar')) + self.assertEqual(p.relative_to('c:foO'), P('Bar')) + self.assertEqual(p.relative_to('c:foO/'), P('Bar')) + self.assertEqual(p.relative_to(P('c:foO/baR')), P()) + self.assertEqual(p.relative_to('c:foO/baR'), P()) + self.assertEqual(p.relative_to(P('c:'), walk_up=True), P('Foo/Bar')) + self.assertEqual(p.relative_to('c:', walk_up=True), P('Foo/Bar')) + self.assertEqual(p.relative_to(P('c:foO'), walk_up=True), P('Bar')) + self.assertEqual(p.relative_to('c:foO', walk_up=True), P('Bar')) + self.assertEqual(p.relative_to('c:foO/', walk_up=True), P('Bar')) + self.assertEqual(p.relative_to(P('c:foO/baR'), walk_up=True), P()) + self.assertEqual(p.relative_to('c:foO/baR', walk_up=True), P()) + self.assertEqual(p.relative_to(P('C:Foo/Bar/Baz'), walk_up=True), P('..')) + self.assertEqual(p.relative_to(P('C:Foo/Baz'), walk_up=True), P('../Bar')) + self.assertEqual(p.relative_to(P('C:Baz/Bar'), walk_up=True), P('../../Foo/Bar')) + # Unrelated paths. + self.assertRaises(ValueError, p.relative_to, P()) + self.assertRaises(ValueError, p.relative_to, '') + self.assertRaises(ValueError, p.relative_to, P('d:')) + self.assertRaises(ValueError, p.relative_to, P('/')) + self.assertRaises(ValueError, p.relative_to, P('Foo')) + self.assertRaises(ValueError, p.relative_to, P('/Foo')) + self.assertRaises(ValueError, p.relative_to, P('C:/Foo')) + self.assertRaises(ValueError, p.relative_to, P('C:Foo/Bar/Baz')) + self.assertRaises(ValueError, p.relative_to, P('C:Foo/Baz')) + self.assertRaises(ValueError, p.relative_to, P(), walk_up=True) + self.assertRaises(ValueError, p.relative_to, '', walk_up=True) + self.assertRaises(ValueError, p.relative_to, P('d:'), walk_up=True) + self.assertRaises(ValueError, p.relative_to, P('/'), walk_up=True) + self.assertRaises(ValueError, p.relative_to, P('Foo'), walk_up=True) + self.assertRaises(ValueError, p.relative_to, P('/Foo'), walk_up=True) + self.assertRaises(ValueError, p.relative_to, P('C:/Foo'), walk_up=True) + p = P('C:/Foo/Bar') + self.assertEqual(p.relative_to(P('c:/')), P('Foo/Bar')) + self.assertEqual(p.relative_to('c:/'), P('Foo/Bar')) + self.assertEqual(p.relative_to(P('c:/foO')), P('Bar')) + self.assertEqual(p.relative_to('c:/foO'), P('Bar')) + self.assertEqual(p.relative_to('c:/foO/'), P('Bar')) + self.assertEqual(p.relative_to(P('c:/foO/baR')), P()) + self.assertEqual(p.relative_to('c:/foO/baR'), P()) + self.assertEqual(p.relative_to(P('c:/'), walk_up=True), P('Foo/Bar')) + self.assertEqual(p.relative_to('c:/', walk_up=True), P('Foo/Bar')) + self.assertEqual(p.relative_to(P('c:/foO'), walk_up=True), P('Bar')) + self.assertEqual(p.relative_to('c:/foO', walk_up=True), P('Bar')) + self.assertEqual(p.relative_to('c:/foO/', walk_up=True), P('Bar')) + self.assertEqual(p.relative_to(P('c:/foO/baR'), walk_up=True), P()) + self.assertEqual(p.relative_to('c:/foO/baR', walk_up=True), P()) + self.assertEqual(p.relative_to('C:/Baz', walk_up=True), P('../Foo/Bar')) + self.assertEqual(p.relative_to('C:/Foo/Bar/Baz', walk_up=True), P('..')) + self.assertEqual(p.relative_to('C:/Foo/Baz', walk_up=True), P('../Bar')) + # Unrelated paths. + self.assertRaises(ValueError, p.relative_to, 'c:') + self.assertRaises(ValueError, p.relative_to, P('c:')) + self.assertRaises(ValueError, p.relative_to, P('C:/Baz')) + self.assertRaises(ValueError, p.relative_to, P('C:/Foo/Bar/Baz')) + self.assertRaises(ValueError, p.relative_to, P('C:/Foo/Baz')) + self.assertRaises(ValueError, p.relative_to, P('C:Foo')) + self.assertRaises(ValueError, p.relative_to, P('d:')) + self.assertRaises(ValueError, p.relative_to, P('d:/')) + self.assertRaises(ValueError, p.relative_to, P('/')) + self.assertRaises(ValueError, p.relative_to, P('/Foo')) + self.assertRaises(ValueError, p.relative_to, P('//C/Foo')) + self.assertRaises(ValueError, p.relative_to, 'c:', walk_up=True) + self.assertRaises(ValueError, p.relative_to, P('c:'), walk_up=True) + self.assertRaises(ValueError, p.relative_to, P('C:Foo'), walk_up=True) + self.assertRaises(ValueError, p.relative_to, P('d:'), walk_up=True) + self.assertRaises(ValueError, p.relative_to, P('d:/'), walk_up=True) + self.assertRaises(ValueError, p.relative_to, P('/'), walk_up=True) + self.assertRaises(ValueError, p.relative_to, P('/Foo'), walk_up=True) + self.assertRaises(ValueError, p.relative_to, P('//C/Foo'), walk_up=True) + # UNC paths. + p = P('//Server/Share/Foo/Bar') + self.assertEqual(p.relative_to(P('//sErver/sHare')), P('Foo/Bar')) + self.assertEqual(p.relative_to('//sErver/sHare'), P('Foo/Bar')) + self.assertEqual(p.relative_to('//sErver/sHare/'), P('Foo/Bar')) + self.assertEqual(p.relative_to(P('//sErver/sHare/Foo')), P('Bar')) + self.assertEqual(p.relative_to('//sErver/sHare/Foo'), P('Bar')) + self.assertEqual(p.relative_to('//sErver/sHare/Foo/'), P('Bar')) + self.assertEqual(p.relative_to(P('//sErver/sHare/Foo/Bar')), P()) + self.assertEqual(p.relative_to('//sErver/sHare/Foo/Bar'), P()) + self.assertEqual(p.relative_to(P('//sErver/sHare'), walk_up=True), P('Foo/Bar')) + self.assertEqual(p.relative_to('//sErver/sHare', walk_up=True), P('Foo/Bar')) + self.assertEqual(p.relative_to('//sErver/sHare/', walk_up=True), P('Foo/Bar')) + self.assertEqual(p.relative_to(P('//sErver/sHare/Foo'), walk_up=True), P('Bar')) + self.assertEqual(p.relative_to('//sErver/sHare/Foo', walk_up=True), P('Bar')) + self.assertEqual(p.relative_to('//sErver/sHare/Foo/', walk_up=True), P('Bar')) + self.assertEqual(p.relative_to(P('//sErver/sHare/Foo/Bar'), walk_up=True), P()) + self.assertEqual(p.relative_to('//sErver/sHare/Foo/Bar', walk_up=True), P()) + self.assertEqual(p.relative_to(P('//sErver/sHare/bar'), walk_up=True), P('../Foo/Bar')) + self.assertEqual(p.relative_to('//sErver/sHare/bar', walk_up=True), P('../Foo/Bar')) + # Unrelated paths. + self.assertRaises(ValueError, p.relative_to, P('/Server/Share/Foo')) + self.assertRaises(ValueError, p.relative_to, P('c:/Server/Share/Foo')) + self.assertRaises(ValueError, p.relative_to, P('//z/Share/Foo')) + self.assertRaises(ValueError, p.relative_to, P('//Server/z/Foo')) + self.assertRaises(ValueError, p.relative_to, P('/Server/Share/Foo'), walk_up=True) + self.assertRaises(ValueError, p.relative_to, P('c:/Server/Share/Foo'), walk_up=True) + self.assertRaises(ValueError, p.relative_to, P('//z/Share/Foo'), walk_up=True) + self.assertRaises(ValueError, p.relative_to, P('//Server/z/Foo'), walk_up=True) + + def test_is_relative_to(self): + P = self.cls + p = P('C:Foo/Bar') + self.assertTrue(p.is_relative_to(P('c:'))) + self.assertTrue(p.is_relative_to('c:')) + self.assertTrue(p.is_relative_to(P('c:foO'))) + self.assertTrue(p.is_relative_to('c:foO')) + self.assertTrue(p.is_relative_to('c:foO/')) + self.assertTrue(p.is_relative_to(P('c:foO/baR'))) + self.assertTrue(p.is_relative_to('c:foO/baR')) + # Unrelated paths. + self.assertFalse(p.is_relative_to(P())) + self.assertFalse(p.is_relative_to('')) + self.assertFalse(p.is_relative_to(P('d:'))) + self.assertFalse(p.is_relative_to(P('/'))) + self.assertFalse(p.is_relative_to(P('Foo'))) + self.assertFalse(p.is_relative_to(P('/Foo'))) + self.assertFalse(p.is_relative_to(P('C:/Foo'))) + self.assertFalse(p.is_relative_to(P('C:Foo/Bar/Baz'))) + self.assertFalse(p.is_relative_to(P('C:Foo/Baz'))) + p = P('C:/Foo/Bar') + self.assertTrue(p.is_relative_to(P('c:/'))) + self.assertTrue(p.is_relative_to(P('c:/foO'))) + self.assertTrue(p.is_relative_to('c:/foO/')) + self.assertTrue(p.is_relative_to(P('c:/foO/baR'))) + self.assertTrue(p.is_relative_to('c:/foO/baR')) + # Unrelated paths. + self.assertFalse(p.is_relative_to('c:')) + self.assertFalse(p.is_relative_to(P('C:/Baz'))) + self.assertFalse(p.is_relative_to(P('C:/Foo/Bar/Baz'))) + self.assertFalse(p.is_relative_to(P('C:/Foo/Baz'))) + self.assertFalse(p.is_relative_to(P('C:Foo'))) + self.assertFalse(p.is_relative_to(P('d:'))) + self.assertFalse(p.is_relative_to(P('d:/'))) + self.assertFalse(p.is_relative_to(P('/'))) + self.assertFalse(p.is_relative_to(P('/Foo'))) + self.assertFalse(p.is_relative_to(P('//C/Foo'))) + # UNC paths. + p = P('//Server/Share/Foo/Bar') + self.assertTrue(p.is_relative_to(P('//sErver/sHare'))) + self.assertTrue(p.is_relative_to('//sErver/sHare')) + self.assertTrue(p.is_relative_to('//sErver/sHare/')) + self.assertTrue(p.is_relative_to(P('//sErver/sHare/Foo'))) + self.assertTrue(p.is_relative_to('//sErver/sHare/Foo')) + self.assertTrue(p.is_relative_to('//sErver/sHare/Foo/')) + self.assertTrue(p.is_relative_to(P('//sErver/sHare/Foo/Bar'))) + self.assertTrue(p.is_relative_to('//sErver/sHare/Foo/Bar')) + # Unrelated paths. + self.assertFalse(p.is_relative_to(P('/Server/Share/Foo'))) + self.assertFalse(p.is_relative_to(P('c:/Server/Share/Foo'))) + self.assertFalse(p.is_relative_to(P('//z/Share/Foo'))) + self.assertFalse(p.is_relative_to(P('//Server/z/Foo'))) + + def test_is_absolute(self): + P = self.cls + # Under NT, only paths with both a drive and a root are absolute. + self.assertFalse(P().is_absolute()) + self.assertFalse(P('a').is_absolute()) + self.assertFalse(P('a/b/').is_absolute()) + self.assertFalse(P('/').is_absolute()) + self.assertFalse(P('/a').is_absolute()) + self.assertFalse(P('/a/b/').is_absolute()) + self.assertFalse(P('c:').is_absolute()) + self.assertFalse(P('c:a').is_absolute()) + self.assertFalse(P('c:a/b/').is_absolute()) + self.assertTrue(P('c:/').is_absolute()) + self.assertTrue(P('c:/a').is_absolute()) + self.assertTrue(P('c:/a/b/').is_absolute()) + # UNC paths are absolute by definition. + self.assertTrue(P('//a/b').is_absolute()) + self.assertTrue(P('//a/b/').is_absolute()) + self.assertTrue(P('//a/b/c').is_absolute()) + self.assertTrue(P('//a/b/c/d').is_absolute()) + + def test_join(self): + P = self.cls + p = P('C:/a/b') + pp = p.joinpath('x/y') + self.assertEqual(pp, P('C:/a/b/x/y')) + pp = p.joinpath('/x/y') + self.assertEqual(pp, P('C:/x/y')) + # Joining with a different drive => the first path is ignored, even + # if the second path is relative. + pp = p.joinpath('D:x/y') + self.assertEqual(pp, P('D:x/y')) + pp = p.joinpath('D:/x/y') + self.assertEqual(pp, P('D:/x/y')) + pp = p.joinpath('//host/share/x/y') + self.assertEqual(pp, P('//host/share/x/y')) + # Joining with the same drive => the first path is appended to if + # the second path is relative. + pp = p.joinpath('c:x/y') + self.assertEqual(pp, P('C:/a/b/x/y')) + pp = p.joinpath('c:/x/y') + self.assertEqual(pp, P('C:/x/y')) + # Joining with files with NTFS data streams => the filename should + # not be parsed as a drive letter + pp = p.joinpath(P('./d:s')) + self.assertEqual(pp, P('C:/a/b/d:s')) + pp = p.joinpath(P('./dd:s')) + self.assertEqual(pp, P('C:/a/b/dd:s')) + pp = p.joinpath(P('E:d:s')) + self.assertEqual(pp, P('E:d:s')) + # Joining onto a UNC path with no root + pp = P('//').joinpath('server') + self.assertEqual(pp, P('//server')) + pp = P('//server').joinpath('share') + self.assertEqual(pp, P('//server/share')) + pp = P('//./BootPartition').joinpath('Windows') + self.assertEqual(pp, P('//./BootPartition/Windows')) + + def test_div(self): + # Basically the same as joinpath(). + P = self.cls + p = P('C:/a/b') + self.assertEqual(p / 'x/y', P('C:/a/b/x/y')) + self.assertEqual(p / 'x' / 'y', P('C:/a/b/x/y')) + self.assertEqual(p / '/x/y', P('C:/x/y')) + self.assertEqual(p / '/x' / 'y', P('C:/x/y')) + # Joining with a different drive => the first path is ignored, even + # if the second path is relative. + self.assertEqual(p / 'D:x/y', P('D:x/y')) + self.assertEqual(p / 'D:' / 'x/y', P('D:x/y')) + self.assertEqual(p / 'D:/x/y', P('D:/x/y')) + self.assertEqual(p / 'D:' / '/x/y', P('D:/x/y')) + self.assertEqual(p / '//host/share/x/y', P('//host/share/x/y')) + # Joining with the same drive => the first path is appended to if + # the second path is relative. + self.assertEqual(p / 'c:x/y', P('C:/a/b/x/y')) + self.assertEqual(p / 'c:/x/y', P('C:/x/y')) + # Joining with files with NTFS data streams => the filename should + # not be parsed as a drive letter + self.assertEqual(p / P('./d:s'), P('C:/a/b/d:s')) + self.assertEqual(p / P('./dd:s'), P('C:/a/b/dd:s')) + self.assertEqual(p / P('E:d:s'), P('E:d:s')) + + def test_is_reserved(self): + P = self.cls + self.assertIs(False, P('').is_reserved()) + self.assertIs(False, P('/').is_reserved()) + self.assertIs(False, P('/foo/bar').is_reserved()) + # UNC paths are never reserved. + self.assertIs(False, P('//my/share/nul/con/aux').is_reserved()) + # Case-insensitive DOS-device names are reserved. + self.assertIs(True, P('nul').is_reserved()) + self.assertIs(True, P('aux').is_reserved()) + self.assertIs(True, P('prn').is_reserved()) + self.assertIs(True, P('con').is_reserved()) + self.assertIs(True, P('conin$').is_reserved()) + self.assertIs(True, P('conout$').is_reserved()) + # COM/LPT + 1-9 or + superscript 1-3 are reserved. + self.assertIs(True, P('COM1').is_reserved()) + self.assertIs(True, P('LPT9').is_reserved()) + self.assertIs(True, P('com\xb9').is_reserved()) + self.assertIs(True, P('com\xb2').is_reserved()) + self.assertIs(True, P('lpt\xb3').is_reserved()) + # DOS-device name mataching ignores characters after a dot or + # a colon and also ignores trailing spaces. + self.assertIs(True, P('NUL.txt').is_reserved()) + self.assertIs(True, P('PRN ').is_reserved()) + self.assertIs(True, P('AUX .txt').is_reserved()) + self.assertIs(True, P('COM1:bar').is_reserved()) + self.assertIs(True, P('LPT9 :bar').is_reserved()) + # DOS-device names are only matched at the beginning + # of a path component. + self.assertIs(False, P('bar.com9').is_reserved()) + self.assertIs(False, P('bar.lpt9').is_reserved()) + # Only the last path component matters. + self.assertIs(True, P('c:/baz/con/NUL').is_reserved()) + self.assertIs(False, P('c:/NUL/con/baz').is_reserved()) + + +class PurePathSubclassTest(PurePathTest): + class cls(pathlib.PurePath): + pass + + # repr() roundtripping is not supported in custom subclass. + test_repr_roundtrips = None + + +# +# Tests for the concrete classes. +# + +class PathTest(test_pathlib_abc.DummyPathTest, PurePathTest): + """Tests for the FS-accessing functionalities of the Path classes.""" + cls = pathlib.Path + can_symlink = os_helper.can_symlink() + + def setUp(self): + super().setUp() + os.chmod(self.pathmod.join(self.base, 'dirE'), 0) + + def tearDown(self): + os.chmod(self.pathmod.join(self.base, 'dirE'), 0o777) + os_helper.rmtree(self.base) + + def tempdir(self): + d = os_helper._longpath(tempfile.mkdtemp(suffix='-dirD', + dir=os.getcwd())) + self.addCleanup(os_helper.rmtree, d) + return d + + def test_matches_pathbase_api(self): + our_names = {name for name in dir(self.cls) if name[0] != '_'} + path_names = {name for name in dir(pathlib._abc.PathBase) if name[0] != '_'} + self.assertEqual(our_names, path_names) + for attr_name in our_names: + if attr_name == 'pathmod': + # On Windows, Path.pathmod is ntpath, but PathBase.pathmod is + # posixpath, and so their docstrings differ. + continue + our_attr = getattr(self.cls, attr_name) + path_attr = getattr(pathlib._abc.PathBase, attr_name) + self.assertEqual(our_attr.__doc__, path_attr.__doc__) + + def test_concrete_class(self): + if self.cls is pathlib.Path: + expected = pathlib.WindowsPath if os.name == 'nt' else pathlib.PosixPath + else: + expected = self.cls + p = self.cls('a') + self.assertIs(type(p), expected) + + def test_unsupported_pathmod(self): + if self.cls.pathmod is os.path: + self.skipTest("path flavour is supported") + else: + self.assertRaises(pathlib.UnsupportedOperation, self.cls) + + def _test_cwd(self, p): + q = self.cls(os.getcwd()) + self.assertEqual(p, q) + self.assertEqualNormCase(str(p), str(q)) + self.assertIs(type(p), type(q)) + self.assertTrue(p.is_absolute()) + + def test_cwd(self): + p = self.cls.cwd() + self._test_cwd(p) + + def test_absolute_common(self): + P = self.cls + + with mock.patch("os.getcwd") as getcwd: + getcwd.return_value = self.base + + # Simple relative paths. + self.assertEqual(str(P().absolute()), self.base) + self.assertEqual(str(P('.').absolute()), self.base) + self.assertEqual(str(P('a').absolute()), os.path.join(self.base, 'a')) + self.assertEqual(str(P('a', 'b', 'c').absolute()), os.path.join(self.base, 'a', 'b', 'c')) + + # Symlinks should not be resolved. + self.assertEqual(str(P('linkB', 'fileB').absolute()), os.path.join(self.base, 'linkB', 'fileB')) + self.assertEqual(str(P('brokenLink').absolute()), os.path.join(self.base, 'brokenLink')) + self.assertEqual(str(P('brokenLinkLoop').absolute()), os.path.join(self.base, 'brokenLinkLoop')) + + # '..' entries should be preserved and not normalised. + self.assertEqual(str(P('..').absolute()), os.path.join(self.base, '..')) + self.assertEqual(str(P('a', '..').absolute()), os.path.join(self.base, 'a', '..')) + self.assertEqual(str(P('..', 'b').absolute()), os.path.join(self.base, '..', 'b')) + + def _test_home(self, p): + q = self.cls(os.path.expanduser('~')) + self.assertEqual(p, q) + self.assertEqualNormCase(str(p), str(q)) + self.assertIs(type(p), type(q)) + self.assertTrue(p.is_absolute()) + + @unittest.skipIf( + pwd is None, reason="Test requires pwd module to get homedir." + ) + def test_home(self): + with os_helper.EnvironmentVarGuard() as env: + self._test_home(self.cls.home()) + + env.clear() + env['USERPROFILE'] = os.path.join(self.base, 'userprofile') + self._test_home(self.cls.home()) + + # bpo-38883: ignore `HOME` when set on windows + env['HOME'] = os.path.join(self.base, 'home') + self._test_home(self.cls.home()) + + @unittest.skipIf(is_wasi, "WASI has no user accounts.") + def test_expanduser_common(self): + P = self.cls + p = P('~') + self.assertEqual(p.expanduser(), P(os.path.expanduser('~'))) + p = P('foo') + self.assertEqual(p.expanduser(), p) + p = P('/~') + self.assertEqual(p.expanduser(), p) + p = P('../~') + self.assertEqual(p.expanduser(), p) + p = P(P('').absolute().anchor) / '~' + self.assertEqual(p.expanduser(), p) + p = P('~/a:b') + self.assertEqual(p.expanduser(), P(os.path.expanduser('~'), './a:b')) + + def test_with_segments(self): + class P(self.cls): + def __init__(self, *pathsegments, session_id): + super().__init__(*pathsegments) + self.session_id = session_id + + def with_segments(self, *pathsegments): + return type(self)(*pathsegments, session_id=self.session_id) + p = P(self.base, session_id=42) + self.assertEqual(42, p.absolute().session_id) + self.assertEqual(42, p.resolve().session_id) + if not is_wasi: # WASI has no user accounts. + self.assertEqual(42, p.with_segments('~').expanduser().session_id) + self.assertEqual(42, (p / 'fileA').rename(p / 'fileB').session_id) + self.assertEqual(42, (p / 'fileB').replace(p / 'fileA').session_id) + if self.can_symlink: + self.assertEqual(42, (p / 'linkA').readlink().session_id) + for path in p.iterdir(): + self.assertEqual(42, path.session_id) + for path in p.glob('*'): + self.assertEqual(42, path.session_id) + for path in p.rglob('*'): + self.assertEqual(42, path.session_id) + for dirpath, dirnames, filenames in p.walk(): + self.assertEqual(42, dirpath.session_id) + + def test_open_unbuffered(self): + p = self.cls(self.base) + with (p / 'fileA').open('rb', buffering=0) as f: + self.assertIsInstance(f, io.RawIOBase) + self.assertEqual(f.read().strip(), b"this is file A") + + def test_resolve_nonexist_relative_issue38671(self): + p = self.cls('non', 'exist') + + old_cwd = os.getcwd() + os.chdir(self.base) + try: + self.assertEqual(p.resolve(), self.cls(self.base, p)) + finally: + os.chdir(old_cwd) + + @os_helper.skip_unless_working_chmod + def test_chmod(self): + p = self.cls(self.base) / 'fileA' + mode = p.stat().st_mode + # Clear writable bit. + new_mode = mode & ~0o222 + p.chmod(new_mode) + self.assertEqual(p.stat().st_mode, new_mode) + # Set writable bit. + new_mode = mode | 0o222 + p.chmod(new_mode) + self.assertEqual(p.stat().st_mode, new_mode) + + # On Windows, os.chmod does not follow symlinks (issue #15411) + @only_posix + @os_helper.skip_unless_working_chmod + def test_chmod_follow_symlinks_true(self): + p = self.cls(self.base) / 'linkA' + q = p.resolve() + mode = q.stat().st_mode + # Clear writable bit. + new_mode = mode & ~0o222 + p.chmod(new_mode, follow_symlinks=True) + self.assertEqual(q.stat().st_mode, new_mode) + # Set writable bit + new_mode = mode | 0o222 + p.chmod(new_mode, follow_symlinks=True) + self.assertEqual(q.stat().st_mode, new_mode) + + # XXX also need a test for lchmod. + + def _get_pw_name_or_skip_test(self, uid): + try: + return pwd.getpwuid(uid).pw_name + except KeyError: + self.skipTest( + "user %d doesn't have an entry in the system database" % uid) + + @unittest.skipUnless(pwd, "the pwd module is needed for this test") + def test_owner(self): + p = self.cls(self.base) / 'fileA' + expected_uid = p.stat().st_uid + expected_name = self._get_pw_name_or_skip_test(expected_uid) + + self.assertEqual(expected_name, p.owner()) + + @unittest.skipUnless(pwd, "the pwd module is needed for this test") + @unittest.skipUnless(root_in_posix, "test needs root privilege") + def test_owner_no_follow_symlinks(self): + all_users = [u.pw_uid for u in pwd.getpwall()] + if len(all_users) < 2: + self.skipTest("test needs more than one user") + + target = self.cls(self.base) / 'fileA' + link = self.cls(self.base) / 'linkA' + + uid_1, uid_2 = all_users[:2] + os.chown(target, uid_1, -1) + os.chown(link, uid_2, -1, follow_symlinks=False) + + expected_uid = link.stat(follow_symlinks=False).st_uid + expected_name = self._get_pw_name_or_skip_test(expected_uid) + + self.assertEqual(expected_uid, uid_2) + self.assertEqual(expected_name, link.owner(follow_symlinks=False)) + + def _get_gr_name_or_skip_test(self, gid): + try: + return grp.getgrgid(gid).gr_name + except KeyError: + self.skipTest( + "group %d doesn't have an entry in the system database" % gid) + + @unittest.skipUnless(grp, "the grp module is needed for this test") + def test_group(self): + p = self.cls(self.base) / 'fileA' + expected_gid = p.stat().st_gid + expected_name = self._get_gr_name_or_skip_test(expected_gid) + + self.assertEqual(expected_name, p.group()) + + @unittest.skipUnless(grp, "the grp module is needed for this test") + @unittest.skipUnless(root_in_posix, "test needs root privilege") + def test_group_no_follow_symlinks(self): + all_groups = [g.gr_gid for g in grp.getgrall()] + if len(all_groups) < 2: + self.skipTest("test needs more than one group") + + target = self.cls(self.base) / 'fileA' + link = self.cls(self.base) / 'linkA' + + gid_1, gid_2 = all_groups[:2] + os.chown(target, -1, gid_1) + os.chown(link, -1, gid_2, follow_symlinks=False) + + expected_gid = link.stat(follow_symlinks=False).st_gid + expected_name = self._get_pw_name_or_skip_test(expected_gid) + + self.assertEqual(expected_gid, gid_2) + self.assertEqual(expected_name, link.group(follow_symlinks=False)) + + def test_unlink(self): + p = self.cls(self.base) / 'fileA' + p.unlink() + self.assertFileNotFound(p.stat) + self.assertFileNotFound(p.unlink) + + def test_unlink_missing_ok(self): + p = self.cls(self.base) / 'fileAAA' + self.assertFileNotFound(p.unlink) + p.unlink(missing_ok=True) + + def test_rmdir(self): + p = self.cls(self.base) / 'dirA' + for q in p.iterdir(): + q.unlink() + p.rmdir() + self.assertFileNotFound(p.stat) + self.assertFileNotFound(p.unlink) + + @unittest.skipUnless(hasattr(os, "link"), "os.link() is not present") + def test_hardlink_to(self): + P = self.cls(self.base) + target = P / 'fileA' + size = target.stat().st_size + # linking to another path. + link = P / 'dirA' / 'fileAA' + link.hardlink_to(target) + self.assertEqual(link.stat().st_size, size) + self.assertTrue(os.path.samefile(target, link)) + self.assertTrue(target.exists()) + # Linking to a str of a relative path. + link2 = P / 'dirA' / 'fileAAA' + target2 = self.pathmod.join(TESTFN, 'fileA') + link2.hardlink_to(target2) + self.assertEqual(os.stat(target2).st_size, size) + self.assertTrue(link2.exists()) + + @unittest.skipIf(hasattr(os, "link"), "os.link() is present") + def test_hardlink_to_unsupported(self): + P = self.cls(self.base) + p = P / 'fileA' + # linking to another path. + q = P / 'dirA' / 'fileAA' + with self.assertRaises(pathlib.UnsupportedOperation): + q.hardlink_to(p) + + def test_rename(self): + P = self.cls(self.base) + p = P / 'fileA' + size = p.stat().st_size + # Renaming to another path. + q = P / 'dirA' / 'fileAA' + renamed_p = p.rename(q) + self.assertEqual(renamed_p, q) + self.assertEqual(q.stat().st_size, size) + self.assertFileNotFound(p.stat) + # Renaming to a str of a relative path. + r = self.pathmod.join(TESTFN, 'fileAAA') + renamed_q = q.rename(r) + self.assertEqual(renamed_q, self.cls(r)) + self.assertEqual(os.stat(r).st_size, size) + self.assertFileNotFound(q.stat) + + def test_replace(self): + P = self.cls(self.base) + p = P / 'fileA' + size = p.stat().st_size + # Replacing a non-existing path. + q = P / 'dirA' / 'fileAA' + replaced_p = p.replace(q) + self.assertEqual(replaced_p, q) + self.assertEqual(q.stat().st_size, size) + self.assertFileNotFound(p.stat) + # Replacing another (existing) path. + r = self.pathmod.join(TESTFN, 'dirB', 'fileB') + replaced_q = q.replace(r) + self.assertEqual(replaced_q, self.cls(r)) + self.assertEqual(os.stat(r).st_size, size) + self.assertFileNotFound(q.stat) + + def test_touch_common(self): + P = self.cls(self.base) + p = P / 'newfileA' + self.assertFalse(p.exists()) + p.touch() + self.assertTrue(p.exists()) + st = p.stat() + old_mtime = st.st_mtime + old_mtime_ns = st.st_mtime_ns + # Rewind the mtime sufficiently far in the past to work around + # filesystem-specific timestamp granularity. + os.utime(str(p), (old_mtime - 10, old_mtime - 10)) + # The file mtime should be refreshed by calling touch() again. + p.touch() + st = p.stat() + self.assertGreaterEqual(st.st_mtime_ns, old_mtime_ns) + self.assertGreaterEqual(st.st_mtime, old_mtime) + # Now with exist_ok=False. + p = P / 'newfileB' + self.assertFalse(p.exists()) + p.touch(mode=0o700, exist_ok=False) + self.assertTrue(p.exists()) + self.assertRaises(OSError, p.touch, exist_ok=False) + + def test_touch_nochange(self): + P = self.cls(self.base) + p = P / 'fileA' + p.touch() + with p.open('rb') as f: + self.assertEqual(f.read().strip(), b"this is file A") + + def test_mkdir(self): + P = self.cls(self.base) + p = P / 'newdirA' + self.assertFalse(p.exists()) + p.mkdir() + self.assertTrue(p.exists()) + self.assertTrue(p.is_dir()) + with self.assertRaises(OSError) as cm: + p.mkdir() + self.assertEqual(cm.exception.errno, errno.EEXIST) + + def test_mkdir_parents(self): + # Creating a chain of directories. + p = self.cls(self.base, 'newdirB', 'newdirC') + self.assertFalse(p.exists()) + with self.assertRaises(OSError) as cm: + p.mkdir() + self.assertEqual(cm.exception.errno, errno.ENOENT) + p.mkdir(parents=True) + self.assertTrue(p.exists()) + self.assertTrue(p.is_dir()) + with self.assertRaises(OSError) as cm: + p.mkdir(parents=True) + self.assertEqual(cm.exception.errno, errno.EEXIST) + # Test `mode` arg. + mode = stat.S_IMODE(p.stat().st_mode) # Default mode. + p = self.cls(self.base, 'newdirD', 'newdirE') + p.mkdir(0o555, parents=True) + self.assertTrue(p.exists()) + self.assertTrue(p.is_dir()) + if os.name != 'nt': + # The directory's permissions follow the mode argument. + self.assertEqual(stat.S_IMODE(p.stat().st_mode), 0o7555 & mode) + # The parent's permissions follow the default process settings. + self.assertEqual(stat.S_IMODE(p.parent.stat().st_mode), mode) + + def test_mkdir_exist_ok(self): + p = self.cls(self.base, 'dirB') + st_ctime_first = p.stat().st_ctime + self.assertTrue(p.exists()) + self.assertTrue(p.is_dir()) + with self.assertRaises(FileExistsError) as cm: + p.mkdir() + self.assertEqual(cm.exception.errno, errno.EEXIST) + p.mkdir(exist_ok=True) + self.assertTrue(p.exists()) + self.assertEqual(p.stat().st_ctime, st_ctime_first) + + def test_mkdir_exist_ok_with_parent(self): + p = self.cls(self.base, 'dirC') + self.assertTrue(p.exists()) + with self.assertRaises(FileExistsError) as cm: + p.mkdir() + self.assertEqual(cm.exception.errno, errno.EEXIST) + p = p / 'newdirC' + p.mkdir(parents=True) + st_ctime_first = p.stat().st_ctime + self.assertTrue(p.exists()) + with self.assertRaises(FileExistsError) as cm: + p.mkdir(parents=True) + self.assertEqual(cm.exception.errno, errno.EEXIST) + p.mkdir(parents=True, exist_ok=True) + self.assertTrue(p.exists()) + self.assertEqual(p.stat().st_ctime, st_ctime_first) + + @unittest.skipIf(is_emscripten, "FS root cannot be modified on Emscripten.") + def test_mkdir_exist_ok_root(self): + # Issue #25803: A drive root could raise PermissionError on Windows. + self.cls('/').resolve().mkdir(exist_ok=True) + self.cls('/').resolve().mkdir(parents=True, exist_ok=True) + + @only_nt # XXX: not sure how to test this on POSIX. + def test_mkdir_with_unknown_drive(self): + for d in 'ZYXWVUTSRQPONMLKJIHGFEDCBA': + p = self.cls(d + ':\\') + if not p.is_dir(): + break + else: + self.skipTest("cannot find a drive that doesn't exist") + with self.assertRaises(OSError): + (p / 'child' / 'path').mkdir(parents=True) + + def test_mkdir_with_child_file(self): + p = self.cls(self.base, 'dirB', 'fileB') + self.assertTrue(p.exists()) + # An exception is raised when the last path component is an existing + # regular file, regardless of whether exist_ok is true or not. + with self.assertRaises(FileExistsError) as cm: + p.mkdir(parents=True) + self.assertEqual(cm.exception.errno, errno.EEXIST) + with self.assertRaises(FileExistsError) as cm: + p.mkdir(parents=True, exist_ok=True) + self.assertEqual(cm.exception.errno, errno.EEXIST) + + def test_mkdir_no_parents_file(self): + p = self.cls(self.base, 'fileA') + self.assertTrue(p.exists()) + # An exception is raised when the last path component is an existing + # regular file, regardless of whether exist_ok is true or not. + with self.assertRaises(FileExistsError) as cm: + p.mkdir() + self.assertEqual(cm.exception.errno, errno.EEXIST) + with self.assertRaises(FileExistsError) as cm: + p.mkdir(exist_ok=True) + self.assertEqual(cm.exception.errno, errno.EEXIST) + + def test_mkdir_concurrent_parent_creation(self): + for pattern_num in range(32): + p = self.cls(self.base, 'dirCPC%d' % pattern_num) + self.assertFalse(p.exists()) + + real_mkdir = os.mkdir + def my_mkdir(path, mode=0o777): + path = str(path) + # Emulate another process that would create the directory + # just before we try to create it ourselves. We do it + # in all possible pattern combinations, assuming that this + # function is called at most 5 times (dirCPC/dir1/dir2, + # dirCPC/dir1, dirCPC, dirCPC/dir1, dirCPC/dir1/dir2). + if pattern.pop(): + real_mkdir(path, mode) # From another process. + concurrently_created.add(path) + real_mkdir(path, mode) # Our real call. + + pattern = [bool(pattern_num & (1 << n)) for n in range(5)] + concurrently_created = set() + p12 = p / 'dir1' / 'dir2' + try: + with mock.patch("os.mkdir", my_mkdir): + p12.mkdir(parents=True, exist_ok=False) + except FileExistsError: + self.assertIn(str(p12), concurrently_created) + else: + self.assertNotIn(str(p12), concurrently_created) + self.assertTrue(p.exists()) + + def test_symlink_to(self): + if not self.can_symlink: + self.skipTest("symlinks required") + P = self.cls(self.base) + target = P / 'fileA' + # Symlinking a path target. + link = P / 'dirA' / 'linkAA' + link.symlink_to(target) + self.assertEqual(link.stat(), target.stat()) + self.assertNotEqual(link.lstat(), target.stat()) + # Symlinking a str target. + link = P / 'dirA' / 'linkAAA' + link.symlink_to(str(target)) + self.assertEqual(link.stat(), target.stat()) + self.assertNotEqual(link.lstat(), target.stat()) + self.assertFalse(link.is_dir()) + # Symlinking to a directory. + target = P / 'dirB' + link = P / 'dirA' / 'linkAAAA' + link.symlink_to(target, target_is_directory=True) + self.assertEqual(link.stat(), target.stat()) + self.assertNotEqual(link.lstat(), target.stat()) + self.assertTrue(link.is_dir()) + self.assertTrue(list(link.iterdir())) + + @unittest.skipIf(hasattr(os, "symlink"), "os.symlink() is present") + def test_symlink_to_unsupported(self): + P = self.cls(self.base) + p = P / 'fileA' + # linking to another path. + q = P / 'dirA' / 'fileAA' + with self.assertRaises(pathlib.UnsupportedOperation): + q.symlink_to(p) + + def test_is_junction(self): + P = self.cls(self.base) + + with mock.patch.object(P.pathmod, 'isjunction'): + self.assertEqual(P.is_junction(), P.pathmod.isjunction.return_value) + P.pathmod.isjunction.assert_called_once_with(P) + + @unittest.skipUnless(hasattr(os, "mkfifo"), "os.mkfifo() required") + @unittest.skipIf(sys.platform == "vxworks", + "fifo requires special path on VxWorks") + def test_is_fifo_true(self): + P = self.cls(self.base, 'myfifo') + try: + os.mkfifo(str(P)) + except PermissionError as e: + self.skipTest('os.mkfifo(): %s' % e) + self.assertTrue(P.is_fifo()) + self.assertFalse(P.is_socket()) + self.assertFalse(P.is_file()) + self.assertIs(self.cls(self.base, 'myfifo\udfff').is_fifo(), False) + self.assertIs(self.cls(self.base, 'myfifo\x00').is_fifo(), False) + + @unittest.skipUnless(hasattr(socket, "AF_UNIX"), "Unix sockets required") + @unittest.skipIf( + is_emscripten, "Unix sockets are not implemented on Emscripten." + ) + @unittest.skipIf( + is_wasi, "Cannot create socket on WASI." + ) + def test_is_socket_true(self): + P = self.cls(self.base, 'mysock') + sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) + self.addCleanup(sock.close) + try: + sock.bind(str(P)) + except OSError as e: + if (isinstance(e, PermissionError) or + "AF_UNIX path too long" in str(e)): + self.skipTest("cannot bind Unix socket: " + str(e)) + self.assertTrue(P.is_socket()) + self.assertFalse(P.is_fifo()) + self.assertFalse(P.is_file()) + self.assertIs(self.cls(self.base, 'mysock\udfff').is_socket(), False) + self.assertIs(self.cls(self.base, 'mysock\x00').is_socket(), False) + + def test_is_char_device_true(self): + # Under Unix, /dev/null should generally be a char device. + P = self.cls('/dev/null') + if not P.exists(): + self.skipTest("/dev/null required") + self.assertTrue(P.is_char_device()) + self.assertFalse(P.is_block_device()) + self.assertFalse(P.is_file()) + self.assertIs(self.cls('/dev/null\udfff').is_char_device(), False) + self.assertIs(self.cls('/dev/null\x00').is_char_device(), False) + + def test_is_mount_root(self): + if os.name == 'nt': + R = self.cls('c:\\') + else: + R = self.cls('/') + self.assertTrue(R.is_mount()) + self.assertFalse((R / '\udfff').is_mount()) + + def test_passing_kwargs_deprecated(self): + with self.assertWarns(DeprecationWarning): + self.cls(foo="bar") + + def setUpWalk(self): + super().setUpWalk() + sub21_path= self.sub2_path / "SUB21" + tmp5_path = sub21_path / "tmp3" + broken_link3_path = self.sub2_path / "broken_link3" + + os.makedirs(sub21_path) + tmp5_path.write_text("I am tmp5, blame test_pathlib.") + if self.can_symlink: + os.symlink(tmp5_path, broken_link3_path) + self.sub2_tree[2].append('broken_link3') + self.sub2_tree[2].sort() + if not is_emscripten: + # Emscripten fails with inaccessible directories. + os.chmod(sub21_path, 0) + try: + os.listdir(sub21_path) + except PermissionError: + self.sub2_tree[1].append('SUB21') + else: + os.chmod(sub21_path, stat.S_IRWXU) + os.unlink(tmp5_path) + os.rmdir(sub21_path) + + def test_walk_bad_dir(self): + self.setUpWalk() + errors = [] + walk_it = self.walk_path.walk(on_error=errors.append) + root, dirs, files = next(walk_it) + self.assertEqual(errors, []) + dir1 = 'SUB1' + path1 = root / dir1 + path1new = (root / dir1).with_suffix(".new") + path1.rename(path1new) + try: + roots = [r for r, _, _ in walk_it] + self.assertTrue(errors) + self.assertNotIn(path1, roots) + self.assertNotIn(path1new, roots) + for dir2 in dirs: + if dir2 != dir1: + self.assertIn(root / dir2, roots) + finally: + path1new.rename(path1) + + def test_walk_many_open_files(self): + depth = 30 + base = self.cls(self.base, 'deep') + path = self.cls(base, *(['d']*depth)) + path.mkdir(parents=True) + + iters = [base.walk(top_down=False) for _ in range(100)] + for i in range(depth + 1): + expected = (path, ['d'] if i else [], []) + for it in iters: + self.assertEqual(next(it), expected) + path = path.parent + + iters = [base.walk(top_down=True) for _ in range(100)] + path = base + for i in range(depth + 1): + expected = (path, ['d'] if i < depth else [], []) + for it in iters: + self.assertEqual(next(it), expected) + path = path / 'd' + + def test_walk_above_recursion_limit(self): + recursion_limit = 40 + # directory_depth > recursion_limit + directory_depth = recursion_limit + 10 + base = self.cls(self.base, 'deep') + path = base.joinpath(*(['d'] * directory_depth)) + path.mkdir(parents=True) + + with set_recursion_limit(recursion_limit): + list(base.walk()) + list(base.walk(top_down=False)) + + def test_glob_many_open_files(self): + depth = 30 + P = self.cls + p = base = P(self.base) / 'deep' + p.mkdir() + for _ in range(depth): + p /= 'd' + p.mkdir() + pattern = '/'.join(['*'] * depth) + iters = [base.glob(pattern) for j in range(100)] + for it in iters: + self.assertEqual(next(it), p) + iters = [base.rglob('d') for j in range(100)] + p = base + for i in range(depth): + p = p / 'd' + for it in iters: + self.assertEqual(next(it), p) + + def test_glob_above_recursion_limit(self): + recursion_limit = 50 + # directory_depth > recursion_limit + directory_depth = recursion_limit + 10 + base = self.cls(self.base, 'deep') + path = base.joinpath(*(['d'] * directory_depth)) + path.mkdir(parents=True) + + with set_recursion_limit(recursion_limit): + list(base.glob('**/')) + + def test_glob_recursive_no_trailing_slash(self): + P = self.cls + p = P(self.base) + with self.assertWarns(FutureWarning): + p.glob('**') + with self.assertWarns(FutureWarning): + p.glob('*/**') + with self.assertWarns(FutureWarning): + p.rglob('**') + with self.assertWarns(FutureWarning): + p.rglob('*/**') + + +@only_posix +class PosixPathTest(PathTest, PurePosixPathTest): + cls = pathlib.PosixPath + + def test_absolute(self): + P = self.cls + self.assertEqual(str(P('/').absolute()), '/') + self.assertEqual(str(P('/a').absolute()), '/a') + self.assertEqual(str(P('/a/b').absolute()), '/a/b') + + # '//'-prefixed absolute path (supported by POSIX). + self.assertEqual(str(P('//').absolute()), '//') + self.assertEqual(str(P('//a').absolute()), '//a') + self.assertEqual(str(P('//a/b').absolute()), '//a/b') + + @unittest.skipIf( + is_emscripten or is_wasi, + "umask is not implemented on Emscripten/WASI." + ) + def test_open_mode(self): + old_mask = os.umask(0) + self.addCleanup(os.umask, old_mask) + p = self.cls(self.base) + with (p / 'new_file').open('wb'): + pass + st = os.stat(self.pathmod.join(self.base, 'new_file')) + self.assertEqual(stat.S_IMODE(st.st_mode), 0o666) + os.umask(0o022) + with (p / 'other_new_file').open('wb'): + pass + st = os.stat(self.pathmod.join(self.base, 'other_new_file')) + self.assertEqual(stat.S_IMODE(st.st_mode), 0o644) + + def test_resolve_root(self): + current_directory = os.getcwd() + try: + os.chdir('/') + p = self.cls('spam') + self.assertEqual(str(p.resolve()), '/spam') + finally: + os.chdir(current_directory) + + @unittest.skipIf( + is_emscripten or is_wasi, + "umask is not implemented on Emscripten/WASI." + ) + def test_touch_mode(self): + old_mask = os.umask(0) + self.addCleanup(os.umask, old_mask) + p = self.cls(self.base) + (p / 'new_file').touch() + st = os.stat(self.pathmod.join(self.base, 'new_file')) + self.assertEqual(stat.S_IMODE(st.st_mode), 0o666) + os.umask(0o022) + (p / 'other_new_file').touch() + st = os.stat(self.pathmod.join(self.base, 'other_new_file')) + self.assertEqual(stat.S_IMODE(st.st_mode), 0o644) + (p / 'masked_new_file').touch(mode=0o750) + st = os.stat(self.pathmod.join(self.base, 'masked_new_file')) + self.assertEqual(stat.S_IMODE(st.st_mode), 0o750) + + def test_glob(self): + P = self.cls + p = P(self.base) + given = set(p.glob("FILEa")) + expect = set() if not os_helper.fs_is_case_insensitive(self.base) else given + self.assertEqual(given, expect) + self.assertEqual(set(p.glob("FILEa*")), set()) + + def test_rglob(self): + P = self.cls + p = P(self.base, "dirC") + given = set(p.rglob("FILEd")) + expect = set() if not os_helper.fs_is_case_insensitive(self.base) else given + self.assertEqual(given, expect) + self.assertEqual(set(p.rglob("FILEd*")), set()) + + @unittest.skipUnless(hasattr(pwd, 'getpwall'), + 'pwd module does not expose getpwall()') + @unittest.skipIf(sys.platform == "vxworks", + "no home directory on VxWorks") + def test_expanduser(self): + P = self.cls + import_helper.import_module('pwd') + import pwd + pwdent = pwd.getpwuid(os.getuid()) + username = pwdent.pw_name + userhome = pwdent.pw_dir.rstrip('/') or '/' + # Find arbitrary different user (if exists). + for pwdent in pwd.getpwall(): + othername = pwdent.pw_name + otherhome = pwdent.pw_dir.rstrip('/') + if othername != username and otherhome: + break + else: + othername = username + otherhome = userhome + + fakename = 'fakeuser' + # This user can theoretically exist on a test runner. Create unique name: + try: + while pwd.getpwnam(fakename): + fakename += '1' + except KeyError: + pass # Non-existent name found + + p1 = P('~/Documents') + p2 = P(f'~{username}/Documents') + p3 = P(f'~{othername}/Documents') + p4 = P(f'../~{username}/Documents') + p5 = P(f'/~{username}/Documents') + p6 = P('') + p7 = P(f'~{fakename}/Documents') + + with os_helper.EnvironmentVarGuard() as env: + env.pop('HOME', None) + + self.assertEqual(p1.expanduser(), P(userhome) / 'Documents') + self.assertEqual(p2.expanduser(), P(userhome) / 'Documents') + self.assertEqual(p3.expanduser(), P(otherhome) / 'Documents') + self.assertEqual(p4.expanduser(), p4) + self.assertEqual(p5.expanduser(), p5) + self.assertEqual(p6.expanduser(), p6) + self.assertRaises(RuntimeError, p7.expanduser) + + env['HOME'] = '/tmp' + self.assertEqual(p1.expanduser(), P('/tmp/Documents')) + self.assertEqual(p2.expanduser(), P(userhome) / 'Documents') + self.assertEqual(p3.expanduser(), P(otherhome) / 'Documents') + self.assertEqual(p4.expanduser(), p4) + self.assertEqual(p5.expanduser(), p5) + self.assertEqual(p6.expanduser(), p6) + self.assertRaises(RuntimeError, p7.expanduser) + + @unittest.skipIf(sys.platform != "darwin", + "Bad file descriptor in /dev/fd affects only macOS") + def test_handling_bad_descriptor(self): + try: + file_descriptors = list(pathlib.Path('/dev/fd').rglob("*"))[3:] + if not file_descriptors: + self.skipTest("no file descriptors - issue was not reproduced") + # Checking all file descriptors because there is no guarantee + # which one will fail. + for f in file_descriptors: + f.exists() + f.is_dir() + f.is_file() + f.is_symlink() + f.is_block_device() + f.is_char_device() + f.is_fifo() + f.is_socket() + except OSError as e: + if e.errno == errno.EBADF: + self.fail("Bad file descriptor not handled.") + raise + + def test_from_uri(self): + P = self.cls + self.assertEqual(P.from_uri('file:/foo/bar'), P('/foo/bar')) + self.assertEqual(P.from_uri('file://foo/bar'), P('//foo/bar')) + self.assertEqual(P.from_uri('file:///foo/bar'), P('/foo/bar')) + self.assertEqual(P.from_uri('file:////foo/bar'), P('//foo/bar')) + self.assertEqual(P.from_uri('file://localhost/foo/bar'), P('/foo/bar')) + self.assertRaises(ValueError, P.from_uri, 'foo/bar') + self.assertRaises(ValueError, P.from_uri, '/foo/bar') + self.assertRaises(ValueError, P.from_uri, '//foo/bar') + self.assertRaises(ValueError, P.from_uri, 'file:foo/bar') + self.assertRaises(ValueError, P.from_uri, 'http://foo/bar') + + def test_from_uri_pathname2url(self): + P = self.cls + self.assertEqual(P.from_uri('file:' + pathname2url('/foo/bar')), P('/foo/bar')) + self.assertEqual(P.from_uri('file:' + pathname2url('//foo/bar')), P('//foo/bar')) + + +@only_nt +class WindowsPathTest(PathTest, PureWindowsPathTest): + cls = pathlib.WindowsPath + + def test_absolute(self): + P = self.cls + + # Simple absolute paths. + self.assertEqual(str(P('c:\\').absolute()), 'c:\\') + self.assertEqual(str(P('c:\\a').absolute()), 'c:\\a') + self.assertEqual(str(P('c:\\a\\b').absolute()), 'c:\\a\\b') + + # UNC absolute paths. + share = '\\\\server\\share\\' + self.assertEqual(str(P(share).absolute()), share) + self.assertEqual(str(P(share + 'a').absolute()), share + 'a') + self.assertEqual(str(P(share + 'a\\b').absolute()), share + 'a\\b') + + # UNC relative paths. + with mock.patch("os.getcwd") as getcwd: + getcwd.return_value = share + + self.assertEqual(str(P().absolute()), share) + self.assertEqual(str(P('.').absolute()), share) + self.assertEqual(str(P('a').absolute()), os.path.join(share, 'a')) + self.assertEqual(str(P('a', 'b', 'c').absolute()), + os.path.join(share, 'a', 'b', 'c')) + + drive = os.path.splitdrive(self.base)[0] + with os_helper.change_cwd(self.base): + # Relative path with root + self.assertEqual(str(P('\\').absolute()), drive + '\\') + self.assertEqual(str(P('\\foo').absolute()), drive + '\\foo') + + # Relative path on current drive + self.assertEqual(str(P(drive).absolute()), self.base) + self.assertEqual(str(P(drive + 'foo').absolute()), os.path.join(self.base, 'foo')) + + with os_helper.subst_drive(self.base) as other_drive: + # Set the working directory on the substitute drive + saved_cwd = os.getcwd() + other_cwd = f'{other_drive}\\dirA' + os.chdir(other_cwd) + os.chdir(saved_cwd) + + # Relative path on another drive + self.assertEqual(str(P(other_drive).absolute()), other_cwd) + self.assertEqual(str(P(other_drive + 'foo').absolute()), other_cwd + '\\foo') + + def test_glob(self): + P = self.cls + p = P(self.base) + self.assertEqual(set(p.glob("FILEa")), { P(self.base, "fileA") }) + self.assertEqual(set(p.glob("*a\\")), { P(self.base, "dirA/") }) + self.assertEqual(set(p.glob("F*a")), { P(self.base, "fileA") }) + self.assertEqual(set(map(str, p.glob("FILEa"))), {f"{p}\\fileA"}) + self.assertEqual(set(map(str, p.glob("F*a"))), {f"{p}\\fileA"}) + + def test_rglob(self): + P = self.cls + p = P(self.base, "dirC") + self.assertEqual(set(p.rglob("FILEd")), { P(self.base, "dirC/dirD/fileD") }) + self.assertEqual(set(p.rglob("*\\")), { P(self.base, "dirC/dirD/") }) + self.assertEqual(set(map(str, p.rglob("FILEd"))), {f"{p}\\dirD\\fileD"}) + + def test_expanduser(self): + P = self.cls + with os_helper.EnvironmentVarGuard() as env: + env.pop('HOME', None) + env.pop('USERPROFILE', None) + env.pop('HOMEPATH', None) + env.pop('HOMEDRIVE', None) + env['USERNAME'] = 'alice' + + # test that the path returns unchanged + p1 = P('~/My Documents') + p2 = P('~alice/My Documents') + p3 = P('~bob/My Documents') + p4 = P('/~/My Documents') + p5 = P('d:~/My Documents') + p6 = P('') + self.assertRaises(RuntimeError, p1.expanduser) + self.assertRaises(RuntimeError, p2.expanduser) + self.assertRaises(RuntimeError, p3.expanduser) + self.assertEqual(p4.expanduser(), p4) + self.assertEqual(p5.expanduser(), p5) + self.assertEqual(p6.expanduser(), p6) + + def check(): + env.pop('USERNAME', None) + self.assertEqual(p1.expanduser(), + P('C:/Users/alice/My Documents')) + self.assertRaises(RuntimeError, p2.expanduser) + env['USERNAME'] = 'alice' + self.assertEqual(p2.expanduser(), + P('C:/Users/alice/My Documents')) + self.assertEqual(p3.expanduser(), + P('C:/Users/bob/My Documents')) + self.assertEqual(p4.expanduser(), p4) + self.assertEqual(p5.expanduser(), p5) + self.assertEqual(p6.expanduser(), p6) + + env['HOMEPATH'] = 'C:\\Users\\alice' + check() + + env['HOMEDRIVE'] = 'C:\\' + env['HOMEPATH'] = 'Users\\alice' + check() + + env.pop('HOMEDRIVE', None) + env.pop('HOMEPATH', None) + env['USERPROFILE'] = 'C:\\Users\\alice' + check() + + # bpo-38883: ignore `HOME` when set on windows + env['HOME'] = 'C:\\Users\\eve' + check() + + def test_from_uri(self): + P = self.cls + # DOS drive paths + self.assertEqual(P.from_uri('file:c:/path/to/file'), P('c:/path/to/file')) + self.assertEqual(P.from_uri('file:c|/path/to/file'), P('c:/path/to/file')) + self.assertEqual(P.from_uri('file:/c|/path/to/file'), P('c:/path/to/file')) + self.assertEqual(P.from_uri('file:///c|/path/to/file'), P('c:/path/to/file')) + # UNC paths + self.assertEqual(P.from_uri('file://server/path/to/file'), P('//server/path/to/file')) + self.assertEqual(P.from_uri('file:////server/path/to/file'), P('//server/path/to/file')) + self.assertEqual(P.from_uri('file://///server/path/to/file'), P('//server/path/to/file')) + # Localhost paths + self.assertEqual(P.from_uri('file://localhost/c:/path/to/file'), P('c:/path/to/file')) + self.assertEqual(P.from_uri('file://localhost/c|/path/to/file'), P('c:/path/to/file')) + # Invalid paths + self.assertRaises(ValueError, P.from_uri, 'foo/bar') + self.assertRaises(ValueError, P.from_uri, 'c:/foo/bar') + self.assertRaises(ValueError, P.from_uri, '//foo/bar') + self.assertRaises(ValueError, P.from_uri, 'file:foo/bar') + self.assertRaises(ValueError, P.from_uri, 'http://foo/bar') + + def test_from_uri_pathname2url(self): + P = self.cls + self.assertEqual(P.from_uri('file:' + pathname2url(r'c:\path\to\file')), P('c:/path/to/file')) + self.assertEqual(P.from_uri('file:' + pathname2url(r'\\server\path\to\file')), P('//server/path/to/file')) + + def test_owner(self): + P = self.cls + with self.assertRaises(pathlib.UnsupportedOperation): + P('c:/').owner() + + def test_group(self): + P = self.cls + with self.assertRaises(pathlib.UnsupportedOperation): + P('c:/').group() + + +class PathSubclassTest(PathTest): + class cls(pathlib.Path): + pass + + # repr() roundtripping is not supported in custom subclass. + test_repr_roundtrips = None + + +class CompatiblePathTest(unittest.TestCase): + """ + Test that a type can be made compatible with PurePath + derivatives by implementing division operator overloads. + """ + + class CompatPath: + """ + Minimum viable class to test PurePath compatibility. + Simply uses the division operator to join a given + string and the string value of another object with + a forward slash. + """ + def __init__(self, string): + self.string = string + + def __truediv__(self, other): + return type(self)(f"{self.string}/{other}") + + def __rtruediv__(self, other): + return type(self)(f"{other}/{self.string}") + + def test_truediv(self): + result = pathlib.PurePath("test") / self.CompatPath("right") + self.assertIsInstance(result, self.CompatPath) + self.assertEqual(result.string, "test/right") + + with self.assertRaises(TypeError): + # Verify improper operations still raise a TypeError + pathlib.PurePath("test") / 10 + + def test_rtruediv(self): + result = self.CompatPath("left") / pathlib.PurePath("test") + self.assertIsInstance(result, self.CompatPath) + self.assertEqual(result.string, "left/test") + + with self.assertRaises(TypeError): + # Verify improper operations still raise a TypeError + 10 / pathlib.PurePath("test") + + +if __name__ == "__main__": + unittest.main() diff --git a/Lib/test/test_pathlib/test_pathlib_abc.py b/Lib/test/test_pathlib/test_pathlib_abc.py new file mode 100644 index 00000000000000..14df1e69db1f96 --- /dev/null +++ b/Lib/test/test_pathlib/test_pathlib_abc.py @@ -0,0 +1,1761 @@ +import collections +import io +import os +import errno +import stat +import unittest + +from pathlib._abc import UnsupportedOperation, PurePathBase, PathBase +import posixpath + +from test.support.os_helper import TESTFN + + +class UnsupportedOperationTest(unittest.TestCase): + def test_is_notimplemented(self): + self.assertTrue(issubclass(UnsupportedOperation, NotImplementedError)) + self.assertTrue(isinstance(UnsupportedOperation(), NotImplementedError)) + + +# +# Tests for the pure classes. +# + + +class PurePathBaseTest(unittest.TestCase): + cls = PurePathBase + + def test_magic_methods(self): + P = self.cls + self.assertFalse(hasattr(P, '__fspath__')) + self.assertFalse(hasattr(P, '__bytes__')) + self.assertIs(P.__reduce__, object.__reduce__) + self.assertIs(P.__repr__, object.__repr__) + self.assertIs(P.__hash__, object.__hash__) + self.assertIs(P.__eq__, object.__eq__) + self.assertIs(P.__lt__, object.__lt__) + self.assertIs(P.__le__, object.__le__) + self.assertIs(P.__gt__, object.__gt__) + self.assertIs(P.__ge__, object.__ge__) + + def test_pathmod(self): + self.assertIs(self.cls.pathmod, posixpath) + + +class DummyPurePath(PurePathBase): + __slots__ = () + + def __eq__(self, other): + if not isinstance(other, DummyPurePath): + return NotImplemented + return str(self) == str(other) + + def __hash__(self): + return hash(str(self)) + + def __repr__(self): + return "{}({!r})".format(self.__class__.__name__, self.as_posix()) + + +class DummyPurePathTest(unittest.TestCase): + cls = DummyPurePath + + # Use a base path that's unrelated to any real filesystem path. + base = f'/this/path/kills/fascists/{TESTFN}' + + def setUp(self): + p = self.cls('a') + self.pathmod = p.pathmod + self.sep = self.pathmod.sep + self.altsep = self.pathmod.altsep + + def test_constructor_common(self): + P = self.cls + p = P('a') + self.assertIsInstance(p, P) + P('a', 'b', 'c') + P('/a', 'b', 'c') + P('a/b/c') + P('/a/b/c') + + def _check_str_subclass(self, *args): + # Issue #21127: it should be possible to construct a PurePath object + # from a str subclass instance, and it then gets converted to + # a pure str object. + class StrSubclass(str): + pass + P = self.cls + p = P(*(StrSubclass(x) for x in args)) + self.assertEqual(p, P(*args)) + for part in p.parts: + self.assertIs(type(part), str) + + def test_str_subclass_common(self): + self._check_str_subclass('') + self._check_str_subclass('.') + self._check_str_subclass('a') + self._check_str_subclass('a/b.txt') + self._check_str_subclass('/a/b.txt') + + def test_with_segments_common(self): + class P(self.cls): + def __init__(self, *pathsegments, session_id): + super().__init__(*pathsegments) + self.session_id = session_id + + def with_segments(self, *pathsegments): + return type(self)(*pathsegments, session_id=self.session_id) + p = P('foo', 'bar', session_id=42) + self.assertEqual(42, (p / 'foo').session_id) + self.assertEqual(42, ('foo' / p).session_id) + self.assertEqual(42, p.joinpath('foo').session_id) + self.assertEqual(42, p.with_name('foo').session_id) + self.assertEqual(42, p.with_stem('foo').session_id) + self.assertEqual(42, p.with_suffix('.foo').session_id) + self.assertEqual(42, p.with_segments('foo').session_id) + self.assertEqual(42, p.relative_to('foo').session_id) + self.assertEqual(42, p.parent.session_id) + for parent in p.parents: + self.assertEqual(42, parent.session_id) + + def test_join_common(self): + P = self.cls + p = P('a/b') + pp = p.joinpath('c') + self.assertEqual(pp, P('a/b/c')) + self.assertIs(type(pp), type(p)) + pp = p.joinpath('c', 'd') + self.assertEqual(pp, P('a/b/c/d')) + pp = p.joinpath('/c') + self.assertEqual(pp, P('/c')) + + def test_div_common(self): + # Basically the same as joinpath(). + P = self.cls + p = P('a/b') + pp = p / 'c' + self.assertEqual(pp, P('a/b/c')) + self.assertIs(type(pp), type(p)) + pp = p / 'c/d' + self.assertEqual(pp, P('a/b/c/d')) + pp = p / 'c' / 'd' + self.assertEqual(pp, P('a/b/c/d')) + pp = 'c' / p / 'd' + self.assertEqual(pp, P('c/a/b/d')) + pp = p/ '/c' + self.assertEqual(pp, P('/c')) + + def _check_str(self, expected, args): + p = self.cls(*args) + self.assertEqual(str(p), expected.replace('/', self.sep)) + + def test_str_common(self): + # Canonicalized paths roundtrip. + for pathstr in ('a', 'a/b', 'a/b/c', '/', '/a/b', '/a/b/c'): + self._check_str(pathstr, (pathstr,)) + # Other tests for str() are in test_equivalences(). + + def test_as_posix_common(self): + P = self.cls + for pathstr in ('a', 'a/b', 'a/b/c', '/', '/a/b', '/a/b/c'): + self.assertEqual(P(pathstr).as_posix(), pathstr) + # Other tests for as_posix() are in test_equivalences(). + + def test_match_empty(self): + P = self.cls + self.assertRaises(ValueError, P('a').match, '') + + def test_match_common(self): + P = self.cls + # Simple relative pattern. + self.assertTrue(P('b.py').match('b.py')) + self.assertTrue(P('a/b.py').match('b.py')) + self.assertTrue(P('/a/b.py').match('b.py')) + self.assertFalse(P('a.py').match('b.py')) + self.assertFalse(P('b/py').match('b.py')) + self.assertFalse(P('/a.py').match('b.py')) + self.assertFalse(P('b.py/c').match('b.py')) + # Wildcard relative pattern. + self.assertTrue(P('b.py').match('*.py')) + self.assertTrue(P('a/b.py').match('*.py')) + self.assertTrue(P('/a/b.py').match('*.py')) + self.assertFalse(P('b.pyc').match('*.py')) + self.assertFalse(P('b./py').match('*.py')) + self.assertFalse(P('b.py/c').match('*.py')) + # Multi-part relative pattern. + self.assertTrue(P('ab/c.py').match('a*/*.py')) + self.assertTrue(P('/d/ab/c.py').match('a*/*.py')) + self.assertFalse(P('a.py').match('a*/*.py')) + self.assertFalse(P('/dab/c.py').match('a*/*.py')) + self.assertFalse(P('ab/c.py/d').match('a*/*.py')) + # Absolute pattern. + self.assertTrue(P('/b.py').match('/*.py')) + self.assertFalse(P('b.py').match('/*.py')) + self.assertFalse(P('a/b.py').match('/*.py')) + self.assertFalse(P('/a/b.py').match('/*.py')) + # Multi-part absolute pattern. + self.assertTrue(P('/a/b.py').match('/a/*.py')) + self.assertFalse(P('/ab.py').match('/a/*.py')) + self.assertFalse(P('/a/b/c.py').match('/a/*.py')) + # Multi-part glob-style pattern. + self.assertTrue(P('a').match('**')) + self.assertTrue(P('c.py').match('**')) + self.assertTrue(P('a/b/c.py').match('**')) + self.assertTrue(P('/a/b/c.py').match('**')) + self.assertTrue(P('/a/b/c.py').match('/**')) + self.assertTrue(P('/a/b/c.py').match('/a/**')) + self.assertTrue(P('/a/b/c.py').match('**/*.py')) + self.assertTrue(P('/a/b/c.py').match('/**/*.py')) + self.assertTrue(P('/a/b/c.py').match('/a/**/*.py')) + self.assertTrue(P('/a/b/c.py').match('/a/b/**/*.py')) + self.assertTrue(P('/a/b/c.py').match('/**/**/**/**/*.py')) + self.assertFalse(P('c.py').match('**/a.py')) + self.assertFalse(P('c.py').match('c/**')) + self.assertFalse(P('a/b/c.py').match('**/a')) + self.assertFalse(P('a/b/c.py').match('**/a/b')) + self.assertFalse(P('a/b/c.py').match('**/a/b/c')) + self.assertFalse(P('a/b/c.py').match('**/a/b/c.')) + self.assertFalse(P('a/b/c.py').match('**/a/b/c./**')) + self.assertFalse(P('a/b/c.py').match('**/a/b/c./**')) + self.assertFalse(P('a/b/c.py').match('/a/b/c.py/**')) + self.assertFalse(P('a/b/c.py').match('/**/a/b/c.py')) + self.assertRaises(ValueError, P('a').match, '**a/b/c') + self.assertRaises(ValueError, P('a').match, 'a/b/c**') + # Case-sensitive flag + self.assertFalse(P('A.py').match('a.PY', case_sensitive=True)) + self.assertTrue(P('A.py').match('a.PY', case_sensitive=False)) + self.assertFalse(P('c:/a/B.Py').match('C:/A/*.pY', case_sensitive=True)) + self.assertTrue(P('/a/b/c.py').match('/A/*/*.Py', case_sensitive=False)) + # Matching against empty path + self.assertFalse(P('').match('*')) + self.assertTrue(P('').match('**')) + self.assertFalse(P('').match('**/*')) + + def test_parts_common(self): + # `parts` returns a tuple. + sep = self.sep + P = self.cls + p = P('a/b') + parts = p.parts + self.assertEqual(parts, ('a', 'b')) + # When the path is absolute, the anchor is a separate part. + p = P('/a/b') + parts = p.parts + self.assertEqual(parts, (sep, 'a', 'b')) + + def test_parent_common(self): + # Relative + P = self.cls + p = P('a/b/c') + self.assertEqual(p.parent, P('a/b')) + self.assertEqual(p.parent.parent, P('a')) + self.assertEqual(p.parent.parent.parent, P('')) + self.assertEqual(p.parent.parent.parent.parent, P('')) + # Anchored + p = P('/a/b/c') + self.assertEqual(p.parent, P('/a/b')) + self.assertEqual(p.parent.parent, P('/a')) + self.assertEqual(p.parent.parent.parent, P('/')) + self.assertEqual(p.parent.parent.parent.parent, P('/')) + + def test_parents_common(self): + # Relative + P = self.cls + p = P('a/b/c') + par = p.parents + self.assertEqual(len(par), 3) + self.assertEqual(par[0], P('a/b')) + self.assertEqual(par[1], P('a')) + self.assertEqual(par[2], P('')) + self.assertEqual(par[-1], P('')) + self.assertEqual(par[-2], P('a')) + self.assertEqual(par[-3], P('a/b')) + self.assertEqual(par[0:1], (P('a/b'),)) + self.assertEqual(par[:2], (P('a/b'), P('a'))) + self.assertEqual(par[:-1], (P('a/b'), P('a'))) + self.assertEqual(par[1:], (P('a'), P(''))) + self.assertEqual(par[::2], (P('a/b'), P(''))) + self.assertEqual(par[::-1], (P(''), P('a'), P('a/b'))) + self.assertEqual(list(par), [P('a/b'), P('a'), P('')]) + with self.assertRaises(IndexError): + par[-4] + with self.assertRaises(IndexError): + par[3] + with self.assertRaises(TypeError): + par[0] = p + # Anchored + p = P('/a/b/c') + par = p.parents + self.assertEqual(len(par), 3) + self.assertEqual(par[0], P('/a/b')) + self.assertEqual(par[1], P('/a')) + self.assertEqual(par[2], P('/')) + self.assertEqual(par[-1], P('/')) + self.assertEqual(par[-2], P('/a')) + self.assertEqual(par[-3], P('/a/b')) + self.assertEqual(par[0:1], (P('/a/b'),)) + self.assertEqual(par[:2], (P('/a/b'), P('/a'))) + self.assertEqual(par[:-1], (P('/a/b'), P('/a'))) + self.assertEqual(par[1:], (P('/a'), P('/'))) + self.assertEqual(par[::2], (P('/a/b'), P('/'))) + self.assertEqual(par[::-1], (P('/'), P('/a'), P('/a/b'))) + self.assertEqual(list(par), [P('/a/b'), P('/a'), P('/')]) + with self.assertRaises(IndexError): + par[-4] + with self.assertRaises(IndexError): + par[3] + + def test_drive_common(self): + P = self.cls + self.assertEqual(P('a/b').drive, '') + self.assertEqual(P('/a/b').drive, '') + self.assertEqual(P('').drive, '') + + def test_root_common(self): + P = self.cls + sep = self.sep + self.assertEqual(P('').root, '') + self.assertEqual(P('a/b').root, '') + self.assertEqual(P('/').root, sep) + self.assertEqual(P('/a/b').root, sep) + + def test_anchor_common(self): + P = self.cls + sep = self.sep + self.assertEqual(P('').anchor, '') + self.assertEqual(P('a/b').anchor, '') + self.assertEqual(P('/').anchor, sep) + self.assertEqual(P('/a/b').anchor, sep) + + def test_name_empty(self): + P = self.cls + self.assertEqual(P('').name, '') + self.assertEqual(P('.').name, '.') + self.assertEqual(P('/a/b/.').name, '.') + + def test_name_common(self): + P = self.cls + self.assertEqual(P('/').name, '') + self.assertEqual(P('a/b').name, 'b') + self.assertEqual(P('/a/b').name, 'b') + self.assertEqual(P('a/b.py').name, 'b.py') + self.assertEqual(P('/a/b.py').name, 'b.py') + + def test_suffix_common(self): + P = self.cls + self.assertEqual(P('').suffix, '') + self.assertEqual(P('.').suffix, '') + self.assertEqual(P('..').suffix, '') + self.assertEqual(P('/').suffix, '') + self.assertEqual(P('a/b').suffix, '') + self.assertEqual(P('/a/b').suffix, '') + self.assertEqual(P('/a/b/.').suffix, '') + self.assertEqual(P('a/b.py').suffix, '.py') + self.assertEqual(P('/a/b.py').suffix, '.py') + self.assertEqual(P('a/.hgrc').suffix, '') + self.assertEqual(P('/a/.hgrc').suffix, '') + self.assertEqual(P('a/.hg.rc').suffix, '.rc') + self.assertEqual(P('/a/.hg.rc').suffix, '.rc') + self.assertEqual(P('a/b.tar.gz').suffix, '.gz') + self.assertEqual(P('/a/b.tar.gz').suffix, '.gz') + self.assertEqual(P('a/Some name. Ending with a dot.').suffix, '') + self.assertEqual(P('/a/Some name. Ending with a dot.').suffix, '') + + def test_suffixes_common(self): + P = self.cls + self.assertEqual(P('').suffixes, []) + self.assertEqual(P('.').suffixes, []) + self.assertEqual(P('/').suffixes, []) + self.assertEqual(P('a/b').suffixes, []) + self.assertEqual(P('/a/b').suffixes, []) + self.assertEqual(P('/a/b/.').suffixes, []) + self.assertEqual(P('a/b.py').suffixes, ['.py']) + self.assertEqual(P('/a/b.py').suffixes, ['.py']) + self.assertEqual(P('a/.hgrc').suffixes, []) + self.assertEqual(P('/a/.hgrc').suffixes, []) + self.assertEqual(P('a/.hg.rc').suffixes, ['.rc']) + self.assertEqual(P('/a/.hg.rc').suffixes, ['.rc']) + self.assertEqual(P('a/b.tar.gz').suffixes, ['.tar', '.gz']) + self.assertEqual(P('/a/b.tar.gz').suffixes, ['.tar', '.gz']) + self.assertEqual(P('a/Some name. Ending with a dot.').suffixes, []) + self.assertEqual(P('/a/Some name. Ending with a dot.').suffixes, []) + + def test_stem_empty(self): + P = self.cls + self.assertEqual(P('').stem, '') + self.assertEqual(P('.').stem, '.') + + def test_stem_common(self): + P = self.cls + self.assertEqual(P('..').stem, '..') + self.assertEqual(P('/').stem, '') + self.assertEqual(P('a/b').stem, 'b') + self.assertEqual(P('a/b.py').stem, 'b') + self.assertEqual(P('a/.hgrc').stem, '.hgrc') + self.assertEqual(P('a/.hg.rc').stem, '.hg') + self.assertEqual(P('a/b.tar.gz').stem, 'b.tar') + self.assertEqual(P('a/Some name. Ending with a dot.').stem, + 'Some name. Ending with a dot.') + + def test_with_name_common(self): + P = self.cls + self.assertEqual(P('a/b').with_name('d.xml'), P('a/d.xml')) + self.assertEqual(P('/a/b').with_name('d.xml'), P('/a/d.xml')) + self.assertEqual(P('a/b.py').with_name('d.xml'), P('a/d.xml')) + self.assertEqual(P('/a/b.py').with_name('d.xml'), P('/a/d.xml')) + self.assertEqual(P('a/Dot ending.').with_name('d.xml'), P('a/d.xml')) + self.assertEqual(P('/a/Dot ending.').with_name('d.xml'), P('/a/d.xml')) + + def test_with_name_empty(self): + P = self.cls + self.assertEqual(P('').with_name('d.xml'), P('d.xml')) + self.assertEqual(P('.').with_name('d.xml'), P('d.xml')) + self.assertEqual(P('/').with_name('d.xml'), P('/d.xml')) + self.assertEqual(P('a/b').with_name(''), P('a/')) + self.assertEqual(P('a/b').with_name('.'), P('a/.')) + + def test_with_name_seps(self): + P = self.cls + self.assertRaises(ValueError, P('a/b').with_name, '/c') + self.assertRaises(ValueError, P('a/b').with_name, 'c/') + self.assertRaises(ValueError, P('a/b').with_name, 'c/d') + + def test_with_stem_common(self): + P = self.cls + self.assertEqual(P('a/b').with_stem('d'), P('a/d')) + self.assertEqual(P('/a/b').with_stem('d'), P('/a/d')) + self.assertEqual(P('a/b.py').with_stem('d'), P('a/d.py')) + self.assertEqual(P('/a/b.py').with_stem('d'), P('/a/d.py')) + self.assertEqual(P('/a/b.tar.gz').with_stem('d'), P('/a/d.gz')) + self.assertEqual(P('a/Dot ending.').with_stem('d'), P('a/d')) + self.assertEqual(P('/a/Dot ending.').with_stem('d'), P('/a/d')) + + def test_with_stem_empty(self): + P = self.cls + self.assertEqual(P('').with_stem('d'), P('d')) + self.assertEqual(P('.').with_stem('d'), P('d')) + self.assertEqual(P('/').with_stem('d'), P('/d')) + self.assertEqual(P('a/b').with_stem(''), P('a/')) + self.assertEqual(P('a/b').with_stem('.'), P('a/.')) + + def test_with_stem_seps(self): + P = self.cls + self.assertRaises(ValueError, P('a/b').with_stem, '/c') + self.assertRaises(ValueError, P('a/b').with_stem, 'c/') + self.assertRaises(ValueError, P('a/b').with_stem, 'c/d') + + def test_with_suffix_common(self): + P = self.cls + self.assertEqual(P('a/b').with_suffix('.gz'), P('a/b.gz')) + self.assertEqual(P('/a/b').with_suffix('.gz'), P('/a/b.gz')) + self.assertEqual(P('a/b.py').with_suffix('.gz'), P('a/b.gz')) + self.assertEqual(P('/a/b.py').with_suffix('.gz'), P('/a/b.gz')) + # Stripping suffix. + self.assertEqual(P('a/b.py').with_suffix(''), P('a/b')) + self.assertEqual(P('/a/b').with_suffix(''), P('/a/b')) + + def test_with_suffix_empty(self): + P = self.cls + # Path doesn't have a "filename" component. + self.assertEqual(P('').with_suffix('.gz'), P('.gz')) + self.assertEqual(P('.').with_suffix('.gz'), P('..gz')) + self.assertEqual(P('/').with_suffix('.gz'), P('/.gz')) + + def test_with_suffix_seps(self): + P = self.cls + # Invalid suffix. + self.assertRaises(ValueError, P('a/b').with_suffix, 'gz') + self.assertRaises(ValueError, P('a/b').with_suffix, '/') + self.assertRaises(ValueError, P('a/b').with_suffix, '.') + self.assertRaises(ValueError, P('a/b').with_suffix, '/.gz') + self.assertRaises(ValueError, P('a/b').with_suffix, 'c/d') + self.assertRaises(ValueError, P('a/b').with_suffix, '.c/.d') + self.assertRaises(ValueError, P('a/b').with_suffix, './.d') + self.assertRaises(ValueError, P('a/b').with_suffix, '.d/.') + + def test_relative_to_common(self): + P = self.cls + p = P('a/b') + self.assertRaises(TypeError, p.relative_to) + self.assertRaises(TypeError, p.relative_to, b'a') + self.assertEqual(p.relative_to(P('')), P('a/b')) + self.assertEqual(p.relative_to(''), P('a/b')) + self.assertEqual(p.relative_to(P('a')), P('b')) + self.assertEqual(p.relative_to('a'), P('b')) + self.assertEqual(p.relative_to('a/'), P('b')) + self.assertEqual(p.relative_to(P('a/b')), P('')) + self.assertEqual(p.relative_to('a/b'), P('')) + self.assertEqual(p.relative_to(P(''), walk_up=True), P('a/b')) + self.assertEqual(p.relative_to('', walk_up=True), P('a/b')) + self.assertEqual(p.relative_to(P('a'), walk_up=True), P('b')) + self.assertEqual(p.relative_to('a', walk_up=True), P('b')) + self.assertEqual(p.relative_to('a/', walk_up=True), P('b')) + self.assertEqual(p.relative_to(P('a/b'), walk_up=True), P('')) + self.assertEqual(p.relative_to('a/b', walk_up=True), P('')) + self.assertEqual(p.relative_to(P('a/c'), walk_up=True), P('../b')) + self.assertEqual(p.relative_to('a/c', walk_up=True), P('../b')) + self.assertEqual(p.relative_to(P('a/b/c'), walk_up=True), P('..')) + self.assertEqual(p.relative_to('a/b/c', walk_up=True), P('..')) + self.assertEqual(p.relative_to(P('c'), walk_up=True), P('../a/b')) + self.assertEqual(p.relative_to('c', walk_up=True), P('../a/b')) + # Unrelated paths. + self.assertRaises(ValueError, p.relative_to, P('c')) + self.assertRaises(ValueError, p.relative_to, P('a/b/c')) + self.assertRaises(ValueError, p.relative_to, P('a/c')) + self.assertRaises(ValueError, p.relative_to, P('/a')) + self.assertRaises(ValueError, p.relative_to, P("../a")) + self.assertRaises(ValueError, p.relative_to, P("a/..")) + self.assertRaises(ValueError, p.relative_to, P("/a/..")) + self.assertRaises(ValueError, p.relative_to, P('/'), walk_up=True) + self.assertRaises(ValueError, p.relative_to, P('/a'), walk_up=True) + self.assertRaises(ValueError, p.relative_to, P("../a"), walk_up=True) + self.assertRaises(ValueError, p.relative_to, P("a/.."), walk_up=True) + self.assertRaises(ValueError, p.relative_to, P("/a/.."), walk_up=True) + p = P('/a/b') + self.assertEqual(p.relative_to(P('/')), P('a/b')) + self.assertEqual(p.relative_to('/'), P('a/b')) + self.assertEqual(p.relative_to(P('/a')), P('b')) + self.assertEqual(p.relative_to('/a'), P('b')) + self.assertEqual(p.relative_to('/a/'), P('b')) + self.assertEqual(p.relative_to(P('/a/b')), P('')) + self.assertEqual(p.relative_to('/a/b'), P('')) + self.assertEqual(p.relative_to(P('/'), walk_up=True), P('a/b')) + self.assertEqual(p.relative_to('/', walk_up=True), P('a/b')) + self.assertEqual(p.relative_to(P('/a'), walk_up=True), P('b')) + self.assertEqual(p.relative_to('/a', walk_up=True), P('b')) + self.assertEqual(p.relative_to('/a/', walk_up=True), P('b')) + self.assertEqual(p.relative_to(P('/a/b'), walk_up=True), P('')) + self.assertEqual(p.relative_to('/a/b', walk_up=True), P('')) + self.assertEqual(p.relative_to(P('/a/c'), walk_up=True), P('../b')) + self.assertEqual(p.relative_to('/a/c', walk_up=True), P('../b')) + self.assertEqual(p.relative_to(P('/a/b/c'), walk_up=True), P('..')) + self.assertEqual(p.relative_to('/a/b/c', walk_up=True), P('..')) + self.assertEqual(p.relative_to(P('/c'), walk_up=True), P('../a/b')) + self.assertEqual(p.relative_to('/c', walk_up=True), P('../a/b')) + # Unrelated paths. + self.assertRaises(ValueError, p.relative_to, P('/c')) + self.assertRaises(ValueError, p.relative_to, P('/a/b/c')) + self.assertRaises(ValueError, p.relative_to, P('/a/c')) + self.assertRaises(ValueError, p.relative_to, P('')) + self.assertRaises(ValueError, p.relative_to, '') + self.assertRaises(ValueError, p.relative_to, P('a')) + self.assertRaises(ValueError, p.relative_to, P("../a")) + self.assertRaises(ValueError, p.relative_to, P("a/..")) + self.assertRaises(ValueError, p.relative_to, P("/a/..")) + self.assertRaises(ValueError, p.relative_to, P(''), walk_up=True) + self.assertRaises(ValueError, p.relative_to, P('a'), walk_up=True) + self.assertRaises(ValueError, p.relative_to, P("../a"), walk_up=True) + self.assertRaises(ValueError, p.relative_to, P("a/.."), walk_up=True) + self.assertRaises(ValueError, p.relative_to, P("/a/.."), walk_up=True) + + def test_is_relative_to_common(self): + P = self.cls + p = P('a/b') + self.assertRaises(TypeError, p.is_relative_to) + self.assertRaises(TypeError, p.is_relative_to, b'a') + self.assertTrue(p.is_relative_to(P(''))) + self.assertTrue(p.is_relative_to('')) + self.assertTrue(p.is_relative_to(P('a'))) + self.assertTrue(p.is_relative_to('a/')) + self.assertTrue(p.is_relative_to(P('a/b'))) + self.assertTrue(p.is_relative_to('a/b')) + # Unrelated paths. + self.assertFalse(p.is_relative_to(P('c'))) + self.assertFalse(p.is_relative_to(P('a/b/c'))) + self.assertFalse(p.is_relative_to(P('a/c'))) + self.assertFalse(p.is_relative_to(P('/a'))) + p = P('/a/b') + self.assertTrue(p.is_relative_to(P('/'))) + self.assertTrue(p.is_relative_to('/')) + self.assertTrue(p.is_relative_to(P('/a'))) + self.assertTrue(p.is_relative_to('/a')) + self.assertTrue(p.is_relative_to('/a/')) + self.assertTrue(p.is_relative_to(P('/a/b'))) + self.assertTrue(p.is_relative_to('/a/b')) + # Unrelated paths. + self.assertFalse(p.is_relative_to(P('/c'))) + self.assertFalse(p.is_relative_to(P('/a/b/c'))) + self.assertFalse(p.is_relative_to(P('/a/c'))) + self.assertFalse(p.is_relative_to(P(''))) + self.assertFalse(p.is_relative_to('')) + self.assertFalse(p.is_relative_to(P('a'))) + + +# +# Tests for the virtual classes. +# + +class PathBaseTest(PurePathBaseTest): + cls = PathBase + + def test_unsupported_operation(self): + P = self.cls + p = self.cls('') + e = UnsupportedOperation + self.assertRaises(e, p.stat) + self.assertRaises(e, p.lstat) + self.assertRaises(e, p.exists) + self.assertRaises(e, p.samefile, 'foo') + self.assertRaises(e, p.is_dir) + self.assertRaises(e, p.is_file) + self.assertRaises(e, p.is_mount) + self.assertRaises(e, p.is_symlink) + self.assertRaises(e, p.is_block_device) + self.assertRaises(e, p.is_char_device) + self.assertRaises(e, p.is_fifo) + self.assertRaises(e, p.is_socket) + self.assertRaises(e, p.open) + self.assertRaises(e, p.read_bytes) + self.assertRaises(e, p.read_text) + self.assertRaises(e, p.write_bytes, b'foo') + self.assertRaises(e, p.write_text, 'foo') + self.assertRaises(e, p.iterdir) + self.assertRaises(e, p.glob, '*') + self.assertRaises(e, p.rglob, '*') + self.assertRaises(e, lambda: list(p.walk())) + self.assertRaises(e, p.absolute) + self.assertRaises(e, P.cwd) + self.assertRaises(e, p.expanduser) + self.assertRaises(e, p.home) + self.assertRaises(e, p.readlink) + self.assertRaises(e, p.symlink_to, 'foo') + self.assertRaises(e, p.hardlink_to, 'foo') + self.assertRaises(e, p.mkdir) + self.assertRaises(e, p.touch) + self.assertRaises(e, p.rename, 'foo') + self.assertRaises(e, p.replace, 'foo') + self.assertRaises(e, p.chmod, 0o755) + self.assertRaises(e, p.lchmod, 0o755) + self.assertRaises(e, p.unlink) + self.assertRaises(e, p.rmdir) + self.assertRaises(e, p.owner) + self.assertRaises(e, p.group) + self.assertRaises(e, p.as_uri) + + def test_as_uri_common(self): + e = UnsupportedOperation + self.assertRaises(e, self.cls('').as_uri) + + def test_fspath_common(self): + self.assertRaises(TypeError, os.fspath, self.cls('')) + + def test_as_bytes_common(self): + self.assertRaises(TypeError, bytes, self.cls('')) + + +class DummyPathIO(io.BytesIO): + """ + Used by DummyPath to implement `open('w')` + """ + + def __init__(self, files, path): + super().__init__() + self.files = files + self.path = path + + def close(self): + self.files[self.path] = self.getvalue() + super().close() + + +DummyPathStatResult = collections.namedtuple( + 'DummyPathStatResult', + 'st_mode st_ino st_dev st_nlink st_uid st_gid st_size st_atime st_mtime st_ctime') + + +class DummyPath(PathBase): + """ + Simple implementation of PathBase that keeps files and directories in + memory. + """ + __slots__ = () + + _files = {} + _directories = {} + _symlinks = {} + + def __eq__(self, other): + if not isinstance(other, DummyPath): + return NotImplemented + return str(self) == str(other) + + def __hash__(self): + return hash(str(self)) + + def __repr__(self): + return "{}({!r})".format(self.__class__.__name__, self.as_posix()) + + def stat(self, *, follow_symlinks=True): + if follow_symlinks: + path = str(self.resolve()) + else: + path = str(self.parent.resolve() / self.name) + if path in self._files: + st_mode = stat.S_IFREG + elif path in self._directories: + st_mode = stat.S_IFDIR + elif path in self._symlinks: + st_mode = stat.S_IFLNK + else: + raise FileNotFoundError(errno.ENOENT, "Not found", str(self)) + return DummyPathStatResult(st_mode, hash(str(self)), 0, 0, 0, 0, 0, 0, 0, 0) + + def open(self, mode='r', buffering=-1, encoding=None, + errors=None, newline=None): + if buffering != -1: + raise NotImplementedError + path_obj = self.resolve() + path = str(path_obj) + name = path_obj.name + parent = str(path_obj.parent) + if path in self._directories: + raise IsADirectoryError(errno.EISDIR, "Is a directory", path) + + text = 'b' not in mode + mode = ''.join(c for c in mode if c not in 'btU') + if mode == 'r': + if path not in self._files: + raise FileNotFoundError(errno.ENOENT, "File not found", path) + stream = io.BytesIO(self._files[path]) + elif mode == 'w': + if parent not in self._directories: + raise FileNotFoundError(errno.ENOENT, "File not found", parent) + stream = DummyPathIO(self._files, path) + self._files[path] = b'' + self._directories[parent].add(name) + else: + raise NotImplementedError + if text: + stream = io.TextIOWrapper(stream, encoding=encoding, errors=errors, newline=newline) + return stream + + def iterdir(self): + path = str(self.resolve()) + if path in self._files: + raise NotADirectoryError(errno.ENOTDIR, "Not a directory", path) + elif path in self._directories: + return (self / name for name in self._directories[path]) + else: + raise FileNotFoundError(errno.ENOENT, "File not found", path) + + def mkdir(self, mode=0o777, parents=False, exist_ok=False): + path = str(self.resolve()) + if path in self._directories: + if exist_ok: + return + else: + raise FileExistsError(errno.EEXIST, "File exists", path) + try: + if self.name: + self._directories[str(self.parent)].add(self.name) + self._directories[path] = set() + except KeyError: + if not parents: + raise FileNotFoundError(errno.ENOENT, "File not found", str(self.parent)) from None + self.parent.mkdir(parents=True, exist_ok=True) + self.mkdir(mode, parents=False, exist_ok=exist_ok) + + +class DummyPathTest(DummyPurePathTest): + """Tests for PathBase methods that use stat(), open() and iterdir().""" + + cls = DummyPath + can_symlink = False + + # (self.base) + # | + # |-- brokenLink -> non-existing + # |-- dirA + # | `-- linkC -> ../dirB + # |-- dirB + # | |-- fileB + # | `-- linkD -> ../dirB + # |-- dirC + # | |-- dirD + # | | `-- fileD + # | `-- fileC + # | `-- novel.txt + # |-- dirE # No permissions + # |-- fileA + # |-- linkA -> fileA + # |-- linkB -> dirB + # `-- brokenLinkLoop -> brokenLinkLoop + # + + def setUp(self): + super().setUp() + pathmod = self.cls.pathmod + p = self.cls(self.base) + p.mkdir(parents=True) + p.joinpath('dirA').mkdir() + p.joinpath('dirB').mkdir() + p.joinpath('dirC').mkdir() + p.joinpath('dirC', 'dirD').mkdir() + p.joinpath('dirE').mkdir() + with p.joinpath('fileA').open('wb') as f: + f.write(b"this is file A\n") + with p.joinpath('dirB', 'fileB').open('wb') as f: + f.write(b"this is file B\n") + with p.joinpath('dirC', 'fileC').open('wb') as f: + f.write(b"this is file C\n") + with p.joinpath('dirC', 'novel.txt').open('wb') as f: + f.write(b"this is a novel\n") + with p.joinpath('dirC', 'dirD', 'fileD').open('wb') as f: + f.write(b"this is file D\n") + if self.can_symlink: + p.joinpath('linkA').symlink_to('fileA') + p.joinpath('brokenLink').symlink_to('non-existing') + p.joinpath('linkB').symlink_to('dirB') + p.joinpath('dirA', 'linkC').symlink_to(pathmod.join('..', 'dirB')) + p.joinpath('dirB', 'linkD').symlink_to(pathmod.join('..', 'dirB')) + p.joinpath('brokenLinkLoop').symlink_to('brokenLinkLoop') + + def tearDown(self): + cls = self.cls + cls._files.clear() + cls._directories.clear() + cls._symlinks.clear() + + def tempdir(self): + path = self.cls(self.base).with_name('tmp-dirD') + path.mkdir() + return path + + def assertFileNotFound(self, func, *args, **kwargs): + with self.assertRaises(FileNotFoundError) as cm: + func(*args, **kwargs) + self.assertEqual(cm.exception.errno, errno.ENOENT) + + def assertEqualNormCase(self, path_a, path_b): + normcase = self.pathmod.normcase + self.assertEqual(normcase(path_a), normcase(path_b)) + + def test_samefile(self): + pathmod = self.pathmod + fileA_path = pathmod.join(self.base, 'fileA') + fileB_path = pathmod.join(self.base, 'dirB', 'fileB') + p = self.cls(fileA_path) + pp = self.cls(fileA_path) + q = self.cls(fileB_path) + self.assertTrue(p.samefile(fileA_path)) + self.assertTrue(p.samefile(pp)) + self.assertFalse(p.samefile(fileB_path)) + self.assertFalse(p.samefile(q)) + # Test the non-existent file case + non_existent = pathmod.join(self.base, 'foo') + r = self.cls(non_existent) + self.assertRaises(FileNotFoundError, p.samefile, r) + self.assertRaises(FileNotFoundError, p.samefile, non_existent) + self.assertRaises(FileNotFoundError, r.samefile, p) + self.assertRaises(FileNotFoundError, r.samefile, non_existent) + self.assertRaises(FileNotFoundError, r.samefile, r) + self.assertRaises(FileNotFoundError, r.samefile, non_existent) + + def test_exists(self): + P = self.cls + p = P(self.base) + self.assertIs(True, p.exists()) + self.assertIs(True, (p / 'dirA').exists()) + self.assertIs(True, (p / 'fileA').exists()) + self.assertIs(False, (p / 'fileA' / 'bah').exists()) + if self.can_symlink: + self.assertIs(True, (p / 'linkA').exists()) + self.assertIs(True, (p / 'linkB').exists()) + self.assertIs(True, (p / 'linkB' / 'fileB').exists()) + self.assertIs(False, (p / 'linkA' / 'bah').exists()) + self.assertIs(False, (p / 'brokenLink').exists()) + self.assertIs(True, (p / 'brokenLink').exists(follow_symlinks=False)) + self.assertIs(False, (p / 'foo').exists()) + self.assertIs(False, P('/xyzzy').exists()) + self.assertIs(False, P(self.base + '\udfff').exists()) + self.assertIs(False, P(self.base + '\x00').exists()) + + def test_open_common(self): + p = self.cls(self.base) + with (p / 'fileA').open('r') as f: + self.assertIsInstance(f, io.TextIOBase) + self.assertEqual(f.read(), "this is file A\n") + with (p / 'fileA').open('rb') as f: + self.assertIsInstance(f, io.BufferedIOBase) + self.assertEqual(f.read().strip(), b"this is file A") + + def test_read_write_bytes(self): + p = self.cls(self.base) + (p / 'fileA').write_bytes(b'abcdefg') + self.assertEqual((p / 'fileA').read_bytes(), b'abcdefg') + # Check that trying to write str does not truncate the file. + self.assertRaises(TypeError, (p / 'fileA').write_bytes, 'somestr') + self.assertEqual((p / 'fileA').read_bytes(), b'abcdefg') + + def test_read_write_text(self): + p = self.cls(self.base) + (p / 'fileA').write_text('äbcdefg', encoding='latin-1') + self.assertEqual((p / 'fileA').read_text( + encoding='utf-8', errors='ignore'), 'bcdefg') + # Check that trying to write bytes does not truncate the file. + self.assertRaises(TypeError, (p / 'fileA').write_text, b'somebytes') + self.assertEqual((p / 'fileA').read_text(encoding='latin-1'), 'äbcdefg') + + def test_read_text_with_newlines(self): + p = self.cls(self.base) + # Check that `\n` character change nothing + (p / 'fileA').write_bytes(b'abcde\r\nfghlk\n\rmnopq') + self.assertEqual((p / 'fileA').read_text(newline='\n'), + 'abcde\r\nfghlk\n\rmnopq') + # Check that `\r` character replaces `\n` + (p / 'fileA').write_bytes(b'abcde\r\nfghlk\n\rmnopq') + self.assertEqual((p / 'fileA').read_text(newline='\r'), + 'abcde\r\nfghlk\n\rmnopq') + # Check that `\r\n` character replaces `\n` + (p / 'fileA').write_bytes(b'abcde\r\nfghlk\n\rmnopq') + self.assertEqual((p / 'fileA').read_text(newline='\r\n'), + 'abcde\r\nfghlk\n\rmnopq') + + def test_write_text_with_newlines(self): + p = self.cls(self.base) + # Check that `\n` character change nothing + (p / 'fileA').write_text('abcde\r\nfghlk\n\rmnopq', newline='\n') + self.assertEqual((p / 'fileA').read_bytes(), + b'abcde\r\nfghlk\n\rmnopq') + # Check that `\r` character replaces `\n` + (p / 'fileA').write_text('abcde\r\nfghlk\n\rmnopq', newline='\r') + self.assertEqual((p / 'fileA').read_bytes(), + b'abcde\r\rfghlk\r\rmnopq') + # Check that `\r\n` character replaces `\n` + (p / 'fileA').write_text('abcde\r\nfghlk\n\rmnopq', newline='\r\n') + self.assertEqual((p / 'fileA').read_bytes(), + b'abcde\r\r\nfghlk\r\n\rmnopq') + # Check that no argument passed will change `\n` to `os.linesep` + os_linesep_byte = bytes(os.linesep, encoding='ascii') + (p / 'fileA').write_text('abcde\nfghlk\n\rmnopq') + self.assertEqual((p / 'fileA').read_bytes(), + b'abcde' + os_linesep_byte + b'fghlk' + os_linesep_byte + b'\rmnopq') + + def test_iterdir(self): + P = self.cls + p = P(self.base) + it = p.iterdir() + paths = set(it) + expected = ['dirA', 'dirB', 'dirC', 'dirE', 'fileA'] + if self.can_symlink: + expected += ['linkA', 'linkB', 'brokenLink', 'brokenLinkLoop'] + self.assertEqual(paths, { P(self.base, q) for q in expected }) + + def test_iterdir_symlink(self): + if not self.can_symlink: + self.skipTest("symlinks required") + # __iter__ on a symlink to a directory. + P = self.cls + p = P(self.base, 'linkB') + paths = set(p.iterdir()) + expected = { P(self.base, 'linkB', q) for q in ['fileB', 'linkD'] } + self.assertEqual(paths, expected) + + def test_iterdir_nodir(self): + # __iter__ on something that is not a directory. + p = self.cls(self.base, 'fileA') + with self.assertRaises(OSError) as cm: + p.iterdir() + # ENOENT or EINVAL under Windows, ENOTDIR otherwise + # (see issue #12802). + self.assertIn(cm.exception.errno, (errno.ENOTDIR, + errno.ENOENT, errno.EINVAL)) + + def test_glob_common(self): + def _check(glob, expected): + self.assertEqual(set(glob), { P(self.base, q) for q in expected }) + P = self.cls + p = P(self.base) + it = p.glob("fileA") + self.assertIsInstance(it, collections.abc.Iterator) + _check(it, ["fileA"]) + _check(p.glob("fileB"), []) + _check(p.glob("dir*/file*"), ["dirB/fileB", "dirC/fileC"]) + if not self.can_symlink: + _check(p.glob("*A"), ['dirA', 'fileA']) + else: + _check(p.glob("*A"), ['dirA', 'fileA', 'linkA']) + if not self.can_symlink: + _check(p.glob("*B/*"), ['dirB/fileB']) + else: + _check(p.glob("*B/*"), ['dirB/fileB', 'dirB/linkD', + 'linkB/fileB', 'linkB/linkD']) + if not self.can_symlink: + _check(p.glob("*/fileB"), ['dirB/fileB']) + else: + _check(p.glob("*/fileB"), ['dirB/fileB', 'linkB/fileB']) + if self.can_symlink: + _check(p.glob("brokenLink"), ['brokenLink']) + + if not self.can_symlink: + _check(p.glob("*/"), ["dirA/", "dirB/", "dirC/", "dirE/"]) + else: + _check(p.glob("*/"), ["dirA/", "dirB/", "dirC/", "dirE/", "linkB/"]) + + def test_glob_empty_pattern(self): + p = self.cls('') + with self.assertRaisesRegex(ValueError, 'Unacceptable pattern'): + list(p.glob('')) + + def test_glob_case_sensitive(self): + P = self.cls + def _check(path, pattern, case_sensitive, expected): + actual = {str(q) for q in path.glob(pattern, case_sensitive=case_sensitive)} + expected = {str(P(self.base, q)) for q in expected} + self.assertEqual(actual, expected) + path = P(self.base) + _check(path, "DIRB/FILE*", True, []) + _check(path, "DIRB/FILE*", False, ["dirB/fileB"]) + _check(path, "dirb/file*", True, []) + _check(path, "dirb/file*", False, ["dirB/fileB"]) + + def test_glob_follow_symlinks_common(self): + if not self.can_symlink: + self.skipTest("symlinks required") + def _check(path, glob, expected): + actual = {path for path in path.glob(glob, follow_symlinks=True) + if path.parts.count("linkD") <= 1} # exclude symlink loop. + self.assertEqual(actual, { P(self.base, q) for q in expected }) + P = self.cls + p = P(self.base) + _check(p, "fileB", []) + _check(p, "dir*/file*", ["dirB/fileB", "dirC/fileC"]) + _check(p, "*A", ["dirA", "fileA", "linkA"]) + _check(p, "*B/*", ["dirB/fileB", "dirB/linkD", "linkB/fileB", "linkB/linkD"]) + _check(p, "*/fileB", ["dirB/fileB", "linkB/fileB"]) + _check(p, "*/", ["dirA/", "dirB/", "dirC/", "dirE/", "linkB/"]) + _check(p, "dir*/*/..", ["dirC/dirD/..", "dirA/linkC/..", "dirB/linkD/.."]) + _check(p, "dir*/**/", ["dirA/", "dirA/linkC/", "dirA/linkC/linkD/", "dirB/", "dirB/linkD/", + "dirC/", "dirC/dirD/", "dirE/"]) + _check(p, "dir*/**/..", ["dirA/..", "dirA/linkC/..", "dirB/..", + "dirB/linkD/..", "dirA/linkC/linkD/..", + "dirC/..", "dirC/dirD/..", "dirE/.."]) + _check(p, "dir*/*/**/", ["dirA/linkC/", "dirA/linkC/linkD/", "dirB/linkD/", "dirC/dirD/"]) + _check(p, "dir*/*/**/..", ["dirA/linkC/..", "dirA/linkC/linkD/..", + "dirB/linkD/..", "dirC/dirD/.."]) + _check(p, "dir*/**/fileC", ["dirC/fileC"]) + _check(p, "dir*/*/../dirD/**/", ["dirC/dirD/../dirD/"]) + _check(p, "*/dirD/**/", ["dirC/dirD/"]) + + def test_glob_no_follow_symlinks_common(self): + if not self.can_symlink: + self.skipTest("symlinks required") + def _check(path, glob, expected): + actual = {path for path in path.glob(glob, follow_symlinks=False)} + self.assertEqual(actual, { P(self.base, q) for q in expected }) + P = self.cls + p = P(self.base) + _check(p, "fileB", []) + _check(p, "dir*/file*", ["dirB/fileB", "dirC/fileC"]) + _check(p, "*A", ["dirA", "fileA", "linkA"]) + _check(p, "*B/*", ["dirB/fileB", "dirB/linkD"]) + _check(p, "*/fileB", ["dirB/fileB"]) + _check(p, "*/", ["dirA/", "dirB/", "dirC/", "dirE/"]) + _check(p, "dir*/*/..", ["dirC/dirD/.."]) + _check(p, "dir*/**/", ["dirA/", "dirB/", "dirC/", "dirC/dirD/", "dirE/"]) + _check(p, "dir*/**/..", ["dirA/..", "dirB/..", "dirC/..", "dirC/dirD/..", "dirE/.."]) + _check(p, "dir*/*/**/", ["dirC/dirD/"]) + _check(p, "dir*/*/**/..", ["dirC/dirD/.."]) + _check(p, "dir*/**/fileC", ["dirC/fileC"]) + _check(p, "dir*/*/../dirD/**/", ["dirC/dirD/../dirD/"]) + _check(p, "*/dirD/**/", ["dirC/dirD/"]) + + def test_rglob_common(self): + def _check(glob, expected): + self.assertEqual(set(glob), {P(self.base, q) for q in expected}) + P = self.cls + p = P(self.base) + it = p.rglob("fileA") + self.assertIsInstance(it, collections.abc.Iterator) + _check(it, ["fileA"]) + _check(p.rglob("fileB"), ["dirB/fileB"]) + _check(p.rglob("**/fileB"), ["dirB/fileB"]) + _check(p.rglob("*/fileA"), []) + if not self.can_symlink: + _check(p.rglob("*/fileB"), ["dirB/fileB"]) + else: + _check(p.rglob("*/fileB"), ["dirB/fileB", "dirB/linkD/fileB", + "linkB/fileB", "dirA/linkC/fileB"]) + _check(p.rglob("file*"), ["fileA", "dirB/fileB", + "dirC/fileC", "dirC/dirD/fileD"]) + if not self.can_symlink: + _check(p.rglob("*/"), [ + "dirA/", "dirB/", "dirC/", "dirC/dirD/", "dirE/", + ]) + else: + _check(p.rglob("*/"), [ + "dirA/", "dirA/linkC/", "dirB/", "dirB/linkD/", "dirC/", + "dirC/dirD/", "dirE/", "linkB/", + ]) + _check(p.rglob(""), ["", "dirA/", "dirB/", "dirC/", "dirE/", "dirC/dirD/"]) + + p = P(self.base, "dirC") + _check(p.rglob("*"), ["dirC/fileC", "dirC/novel.txt", + "dirC/dirD", "dirC/dirD/fileD"]) + _check(p.rglob("file*"), ["dirC/fileC", "dirC/dirD/fileD"]) + _check(p.rglob("**/file*"), ["dirC/fileC", "dirC/dirD/fileD"]) + _check(p.rglob("dir*/**/"), ["dirC/dirD/"]) + _check(p.rglob("*/*"), ["dirC/dirD/fileD"]) + _check(p.rglob("*/"), ["dirC/dirD/"]) + _check(p.rglob(""), ["dirC/", "dirC/dirD/"]) + _check(p.rglob("**/"), ["dirC/", "dirC/dirD/"]) + # gh-91616, a re module regression + _check(p.rglob("*.txt"), ["dirC/novel.txt"]) + _check(p.rglob("*.*"), ["dirC/novel.txt"]) + + def test_rglob_follow_symlinks_common(self): + if not self.can_symlink: + self.skipTest("symlinks required") + def _check(path, glob, expected): + actual = {path for path in path.rglob(glob, follow_symlinks=True) + if path.parts.count("linkD") <= 1} # exclude symlink loop. + self.assertEqual(actual, { P(self.base, q) for q in expected }) + P = self.cls + p = P(self.base) + _check(p, "fileB", ["dirB/fileB", "dirA/linkC/fileB", "linkB/fileB", + "dirA/linkC/linkD/fileB", "dirB/linkD/fileB", "linkB/linkD/fileB"]) + _check(p, "*/fileA", []) + _check(p, "*/fileB", ["dirB/fileB", "dirA/linkC/fileB", "linkB/fileB", + "dirA/linkC/linkD/fileB", "dirB/linkD/fileB", "linkB/linkD/fileB"]) + _check(p, "file*", ["fileA", "dirA/linkC/fileB", "dirB/fileB", + "dirA/linkC/linkD/fileB", "dirB/linkD/fileB", "linkB/linkD/fileB", + "dirC/fileC", "dirC/dirD/fileD", "linkB/fileB"]) + _check(p, "*/", ["dirA/", "dirA/linkC/", "dirA/linkC/linkD/", "dirB/", "dirB/linkD/", + "dirC/", "dirC/dirD/", "dirE/", "linkB/", "linkB/linkD/"]) + _check(p, "", ["", "dirA/", "dirA/linkC/", "dirA/linkC/linkD/", "dirB/", "dirB/linkD/", + "dirC/", "dirE/", "dirC/dirD/", "linkB/", "linkB/linkD/"]) + + p = P(self.base, "dirC") + _check(p, "*", ["dirC/fileC", "dirC/novel.txt", + "dirC/dirD", "dirC/dirD/fileD"]) + _check(p, "file*", ["dirC/fileC", "dirC/dirD/fileD"]) + _check(p, "*/*", ["dirC/dirD/fileD"]) + _check(p, "*/", ["dirC/dirD/"]) + _check(p, "", ["dirC/", "dirC/dirD/"]) + # gh-91616, a re module regression + _check(p, "*.txt", ["dirC/novel.txt"]) + _check(p, "*.*", ["dirC/novel.txt"]) + + def test_rglob_no_follow_symlinks_common(self): + if not self.can_symlink: + self.skipTest("symlinks required") + def _check(path, glob, expected): + actual = {path for path in path.rglob(glob, follow_symlinks=False)} + self.assertEqual(actual, { P(self.base, q) for q in expected }) + P = self.cls + p = P(self.base) + _check(p, "fileB", ["dirB/fileB"]) + _check(p, "*/fileA", []) + _check(p, "*/fileB", ["dirB/fileB"]) + _check(p, "file*", ["fileA", "dirB/fileB", "dirC/fileC", "dirC/dirD/fileD", ]) + _check(p, "*/", ["dirA/", "dirB/", "dirC/", "dirC/dirD/", "dirE/"]) + _check(p, "", ["", "dirA/", "dirB/", "dirC/", "dirE/", "dirC/dirD/"]) + + p = P(self.base, "dirC") + _check(p, "*", ["dirC/fileC", "dirC/novel.txt", + "dirC/dirD", "dirC/dirD/fileD"]) + _check(p, "file*", ["dirC/fileC", "dirC/dirD/fileD"]) + _check(p, "*/*", ["dirC/dirD/fileD"]) + _check(p, "*/", ["dirC/dirD/"]) + _check(p, "", ["dirC/", "dirC/dirD/"]) + # gh-91616, a re module regression + _check(p, "*.txt", ["dirC/novel.txt"]) + _check(p, "*.*", ["dirC/novel.txt"]) + + def test_rglob_symlink_loop(self): + # Don't get fooled by symlink loops (Issue #26012). + if not self.can_symlink: + self.skipTest("symlinks required") + P = self.cls + p = P(self.base) + given = set(p.rglob('*')) + expect = {'brokenLink', + 'dirA', 'dirA/linkC', + 'dirB', 'dirB/fileB', 'dirB/linkD', + 'dirC', 'dirC/dirD', 'dirC/dirD/fileD', + 'dirC/fileC', 'dirC/novel.txt', + 'dirE', + 'fileA', + 'linkA', + 'linkB', + 'brokenLinkLoop', + } + self.assertEqual(given, {p / x for x in expect}) + + def test_glob_dotdot(self): + # ".." is not special in globs. + P = self.cls + p = P(self.base) + self.assertEqual(set(p.glob("..")), { P(self.base, "..") }) + self.assertEqual(set(p.glob("../..")), { P(self.base, "..", "..") }) + self.assertEqual(set(p.glob("dirA/..")), { P(self.base, "dirA", "..") }) + self.assertEqual(set(p.glob("dirA/../file*")), { P(self.base, "dirA/../fileA") }) + self.assertEqual(set(p.glob("dirA/../file*/..")), set()) + self.assertEqual(set(p.glob("../xyzzy")), set()) + self.assertEqual(set(p.glob("xyzzy/..")), set()) + self.assertEqual(set(p.glob("/".join([".."] * 50))), { P(self.base, *[".."] * 50)}) + + def test_glob_permissions(self): + # See bpo-38894 + if not self.can_symlink: + self.skipTest("symlinks required") + P = self.cls + base = P(self.base) / 'permissions' + base.mkdir() + + for i in range(100): + link = base / f"link{i}" + if i % 2: + link.symlink_to(P(self.base, "dirE", "nonexistent")) + else: + link.symlink_to(P(self.base, "dirC")) + + self.assertEqual(len(set(base.glob("*"))), 100) + self.assertEqual(len(set(base.glob("*/"))), 50) + self.assertEqual(len(set(base.glob("*/fileC"))), 50) + self.assertEqual(len(set(base.glob("*/file*"))), 50) + + def test_glob_long_symlink(self): + # See gh-87695 + if not self.can_symlink: + self.skipTest("symlinks required") + base = self.cls(self.base) / 'long_symlink' + base.mkdir() + bad_link = base / 'bad_link' + bad_link.symlink_to("bad" * 200) + self.assertEqual(sorted(base.glob('**/*')), [bad_link]) + + def test_readlink(self): + if not self.can_symlink: + self.skipTest("symlinks required") + P = self.cls(self.base) + self.assertEqual((P / 'linkA').readlink(), self.cls('fileA')) + self.assertEqual((P / 'brokenLink').readlink(), + self.cls('non-existing')) + self.assertEqual((P / 'linkB').readlink(), self.cls('dirB')) + self.assertEqual((P / 'linkB' / 'linkD').readlink(), self.cls('../dirB')) + with self.assertRaises(OSError): + (P / 'fileA').readlink() + + @unittest.skipIf(hasattr(os, "readlink"), "os.readlink() is present") + def test_readlink_unsupported(self): + P = self.cls(self.base) + p = P / 'fileA' + with self.assertRaises(UnsupportedOperation): + q.readlink(p) + + def _check_resolve(self, p, expected, strict=True): + q = p.resolve(strict) + self.assertEqual(q, expected) + + # This can be used to check both relative and absolute resolutions. + _check_resolve_relative = _check_resolve_absolute = _check_resolve + + def test_resolve_common(self): + if not self.can_symlink: + self.skipTest("symlinks required") + P = self.cls + p = P(self.base, 'foo') + with self.assertRaises(OSError) as cm: + p.resolve(strict=True) + self.assertEqual(cm.exception.errno, errno.ENOENT) + # Non-strict + pathmod = self.pathmod + self.assertEqualNormCase(str(p.resolve(strict=False)), + pathmod.join(self.base, 'foo')) + p = P(self.base, 'foo', 'in', 'spam') + self.assertEqualNormCase(str(p.resolve(strict=False)), + pathmod.join(self.base, 'foo', 'in', 'spam')) + p = P(self.base, '..', 'foo', 'in', 'spam') + self.assertEqualNormCase(str(p.resolve(strict=False)), + pathmod.join(pathmod.dirname(self.base), 'foo', 'in', 'spam')) + # These are all relative symlinks. + p = P(self.base, 'dirB', 'fileB') + self._check_resolve_relative(p, p) + p = P(self.base, 'linkA') + self._check_resolve_relative(p, P(self.base, 'fileA')) + p = P(self.base, 'dirA', 'linkC', 'fileB') + self._check_resolve_relative(p, P(self.base, 'dirB', 'fileB')) + p = P(self.base, 'dirB', 'linkD', 'fileB') + self._check_resolve_relative(p, P(self.base, 'dirB', 'fileB')) + # Non-strict + p = P(self.base, 'dirA', 'linkC', 'fileB', 'foo', 'in', 'spam') + self._check_resolve_relative(p, P(self.base, 'dirB', 'fileB', 'foo', 'in', + 'spam'), False) + p = P(self.base, 'dirA', 'linkC', '..', 'foo', 'in', 'spam') + if self.cls.pathmod is not posixpath: + # In Windows, if linkY points to dirB, 'dirA\linkY\..' + # resolves to 'dirA' without resolving linkY first. + self._check_resolve_relative(p, P(self.base, 'dirA', 'foo', 'in', + 'spam'), False) + else: + # In Posix, if linkY points to dirB, 'dirA/linkY/..' + # resolves to 'dirB/..' first before resolving to parent of dirB. + self._check_resolve_relative(p, P(self.base, 'foo', 'in', 'spam'), False) + # Now create absolute symlinks. + d = self.tempdir() + P(self.base, 'dirA', 'linkX').symlink_to(d) + P(self.base, str(d), 'linkY').symlink_to(self.pathmod.join(self.base, 'dirB')) + p = P(self.base, 'dirA', 'linkX', 'linkY', 'fileB') + self._check_resolve_absolute(p, P(self.base, 'dirB', 'fileB')) + # Non-strict + p = P(self.base, 'dirA', 'linkX', 'linkY', 'foo', 'in', 'spam') + self._check_resolve_relative(p, P(self.base, 'dirB', 'foo', 'in', 'spam'), + False) + p = P(self.base, 'dirA', 'linkX', 'linkY', '..', 'foo', 'in', 'spam') + if self.cls.pathmod is not posixpath: + # In Windows, if linkY points to dirB, 'dirA\linkY\..' + # resolves to 'dirA' without resolving linkY first. + self._check_resolve_relative(p, P(d, 'foo', 'in', 'spam'), False) + else: + # In Posix, if linkY points to dirB, 'dirA/linkY/..' + # resolves to 'dirB/..' first before resolving to parent of dirB. + self._check_resolve_relative(p, P(self.base, 'foo', 'in', 'spam'), False) + + def test_resolve_dot(self): + # See http://web.archive.org/web/20200623062557/https://bitbucket.org/pitrou/pathlib/issues/9/ + if not self.can_symlink: + self.skipTest("symlinks required") + pathmod = self.pathmod + p = self.cls(self.base) + p.joinpath('0').symlink_to('.', target_is_directory=True) + p.joinpath('1').symlink_to(pathmod.join('0', '0'), target_is_directory=True) + p.joinpath('2').symlink_to(pathmod.join('1', '1'), target_is_directory=True) + q = p / '2' + self.assertEqual(q.resolve(strict=True), p) + r = q / '3' / '4' + self.assertRaises(FileNotFoundError, r.resolve, strict=True) + # Non-strict + self.assertEqual(r.resolve(strict=False), p / '3' / '4') + + def _check_symlink_loop(self, *args): + path = self.cls(*args) + with self.assertRaises(OSError) as cm: + path.resolve(strict=True) + self.assertEqual(cm.exception.errno, errno.ELOOP) + + def test_resolve_loop(self): + if not self.can_symlink: + self.skipTest("symlinks required") + if self.cls.pathmod is not posixpath: + self.skipTest("symlink loops work differently with concrete Windows paths") + # Loops with relative symlinks. + self.cls(self.base, 'linkX').symlink_to('linkX/inside') + self._check_symlink_loop(self.base, 'linkX') + self.cls(self.base, 'linkY').symlink_to('linkY') + self._check_symlink_loop(self.base, 'linkY') + self.cls(self.base, 'linkZ').symlink_to('linkZ/../linkZ') + self._check_symlink_loop(self.base, 'linkZ') + # Non-strict + p = self.cls(self.base, 'linkZ', 'foo') + self.assertEqual(p.resolve(strict=False), p) + # Loops with absolute symlinks. + self.cls(self.base, 'linkU').symlink_to(self.pathmod.join(self.base, 'linkU/inside')) + self._check_symlink_loop(self.base, 'linkU') + self.cls(self.base, 'linkV').symlink_to(self.pathmod.join(self.base, 'linkV')) + self._check_symlink_loop(self.base, 'linkV') + self.cls(self.base, 'linkW').symlink_to(self.pathmod.join(self.base, 'linkW/../linkW')) + self._check_symlink_loop(self.base, 'linkW') + # Non-strict + q = self.cls(self.base, 'linkW', 'foo') + self.assertEqual(q.resolve(strict=False), q) + + def test_stat(self): + statA = self.cls(self.base).joinpath('fileA').stat() + statB = self.cls(self.base).joinpath('dirB', 'fileB').stat() + statC = self.cls(self.base).joinpath('dirC').stat() + # st_mode: files are the same, directory differs. + self.assertIsInstance(statA.st_mode, int) + self.assertEqual(statA.st_mode, statB.st_mode) + self.assertNotEqual(statA.st_mode, statC.st_mode) + self.assertNotEqual(statB.st_mode, statC.st_mode) + # st_ino: all different, + self.assertIsInstance(statA.st_ino, int) + self.assertNotEqual(statA.st_ino, statB.st_ino) + self.assertNotEqual(statA.st_ino, statC.st_ino) + self.assertNotEqual(statB.st_ino, statC.st_ino) + # st_dev: all the same. + self.assertIsInstance(statA.st_dev, int) + self.assertEqual(statA.st_dev, statB.st_dev) + self.assertEqual(statA.st_dev, statC.st_dev) + # other attributes not used by pathlib. + + def test_stat_no_follow_symlinks(self): + if not self.can_symlink: + self.skipTest("symlinks required") + p = self.cls(self.base) / 'linkA' + st = p.stat() + self.assertNotEqual(st, p.stat(follow_symlinks=False)) + + def test_stat_no_follow_symlinks_nosymlink(self): + p = self.cls(self.base) / 'fileA' + st = p.stat() + self.assertEqual(st, p.stat(follow_symlinks=False)) + + def test_lstat(self): + if not self.can_symlink: + self.skipTest("symlinks required") + p = self.cls(self.base)/ 'linkA' + st = p.stat() + self.assertNotEqual(st, p.lstat()) + + def test_lstat_nosymlink(self): + p = self.cls(self.base) / 'fileA' + st = p.stat() + self.assertEqual(st, p.lstat()) + + def test_is_dir(self): + P = self.cls(self.base) + self.assertTrue((P / 'dirA').is_dir()) + self.assertFalse((P / 'fileA').is_dir()) + self.assertFalse((P / 'non-existing').is_dir()) + self.assertFalse((P / 'fileA' / 'bah').is_dir()) + if self.can_symlink: + self.assertFalse((P / 'linkA').is_dir()) + self.assertTrue((P / 'linkB').is_dir()) + self.assertFalse((P/ 'brokenLink').is_dir()) + self.assertFalse((P / 'dirA\udfff').is_dir()) + self.assertFalse((P / 'dirA\x00').is_dir()) + + def test_is_dir_no_follow_symlinks(self): + P = self.cls(self.base) + self.assertTrue((P / 'dirA').is_dir(follow_symlinks=False)) + self.assertFalse((P / 'fileA').is_dir(follow_symlinks=False)) + self.assertFalse((P / 'non-existing').is_dir(follow_symlinks=False)) + self.assertFalse((P / 'fileA' / 'bah').is_dir(follow_symlinks=False)) + if self.can_symlink: + self.assertFalse((P / 'linkA').is_dir(follow_symlinks=False)) + self.assertFalse((P / 'linkB').is_dir(follow_symlinks=False)) + self.assertFalse((P/ 'brokenLink').is_dir(follow_symlinks=False)) + self.assertFalse((P / 'dirA\udfff').is_dir(follow_symlinks=False)) + self.assertFalse((P / 'dirA\x00').is_dir(follow_symlinks=False)) + + def test_is_file(self): + P = self.cls(self.base) + self.assertTrue((P / 'fileA').is_file()) + self.assertFalse((P / 'dirA').is_file()) + self.assertFalse((P / 'non-existing').is_file()) + self.assertFalse((P / 'fileA' / 'bah').is_file()) + if self.can_symlink: + self.assertTrue((P / 'linkA').is_file()) + self.assertFalse((P / 'linkB').is_file()) + self.assertFalse((P/ 'brokenLink').is_file()) + self.assertFalse((P / 'fileA\udfff').is_file()) + self.assertFalse((P / 'fileA\x00').is_file()) + + def test_is_file_no_follow_symlinks(self): + P = self.cls(self.base) + self.assertTrue((P / 'fileA').is_file(follow_symlinks=False)) + self.assertFalse((P / 'dirA').is_file(follow_symlinks=False)) + self.assertFalse((P / 'non-existing').is_file(follow_symlinks=False)) + self.assertFalse((P / 'fileA' / 'bah').is_file(follow_symlinks=False)) + if self.can_symlink: + self.assertFalse((P / 'linkA').is_file(follow_symlinks=False)) + self.assertFalse((P / 'linkB').is_file(follow_symlinks=False)) + self.assertFalse((P/ 'brokenLink').is_file(follow_symlinks=False)) + self.assertFalse((P / 'fileA\udfff').is_file(follow_symlinks=False)) + self.assertFalse((P / 'fileA\x00').is_file(follow_symlinks=False)) + + def test_is_mount(self): + P = self.cls(self.base) + self.assertFalse((P / 'fileA').is_mount()) + self.assertFalse((P / 'dirA').is_mount()) + self.assertFalse((P / 'non-existing').is_mount()) + self.assertFalse((P / 'fileA' / 'bah').is_mount()) + if self.can_symlink: + self.assertFalse((P / 'linkA').is_mount()) + + def test_is_symlink(self): + P = self.cls(self.base) + self.assertFalse((P / 'fileA').is_symlink()) + self.assertFalse((P / 'dirA').is_symlink()) + self.assertFalse((P / 'non-existing').is_symlink()) + self.assertFalse((P / 'fileA' / 'bah').is_symlink()) + if self.can_symlink: + self.assertTrue((P / 'linkA').is_symlink()) + self.assertTrue((P / 'linkB').is_symlink()) + self.assertTrue((P/ 'brokenLink').is_symlink()) + self.assertIs((P / 'fileA\udfff').is_file(), False) + self.assertIs((P / 'fileA\x00').is_file(), False) + if self.can_symlink: + self.assertIs((P / 'linkA\udfff').is_file(), False) + self.assertIs((P / 'linkA\x00').is_file(), False) + + def test_is_junction_false(self): + P = self.cls(self.base) + self.assertFalse((P / 'fileA').is_junction()) + self.assertFalse((P / 'dirA').is_junction()) + self.assertFalse((P / 'non-existing').is_junction()) + self.assertFalse((P / 'fileA' / 'bah').is_junction()) + self.assertFalse((P / 'fileA\udfff').is_junction()) + self.assertFalse((P / 'fileA\x00').is_junction()) + + def test_is_fifo_false(self): + P = self.cls(self.base) + self.assertFalse((P / 'fileA').is_fifo()) + self.assertFalse((P / 'dirA').is_fifo()) + self.assertFalse((P / 'non-existing').is_fifo()) + self.assertFalse((P / 'fileA' / 'bah').is_fifo()) + self.assertIs((P / 'fileA\udfff').is_fifo(), False) + self.assertIs((P / 'fileA\x00').is_fifo(), False) + + def test_is_socket_false(self): + P = self.cls(self.base) + self.assertFalse((P / 'fileA').is_socket()) + self.assertFalse((P / 'dirA').is_socket()) + self.assertFalse((P / 'non-existing').is_socket()) + self.assertFalse((P / 'fileA' / 'bah').is_socket()) + self.assertIs((P / 'fileA\udfff').is_socket(), False) + self.assertIs((P / 'fileA\x00').is_socket(), False) + + def test_is_block_device_false(self): + P = self.cls(self.base) + self.assertFalse((P / 'fileA').is_block_device()) + self.assertFalse((P / 'dirA').is_block_device()) + self.assertFalse((P / 'non-existing').is_block_device()) + self.assertFalse((P / 'fileA' / 'bah').is_block_device()) + self.assertIs((P / 'fileA\udfff').is_block_device(), False) + self.assertIs((P / 'fileA\x00').is_block_device(), False) + + def test_is_char_device_false(self): + P = self.cls(self.base) + self.assertFalse((P / 'fileA').is_char_device()) + self.assertFalse((P / 'dirA').is_char_device()) + self.assertFalse((P / 'non-existing').is_char_device()) + self.assertFalse((P / 'fileA' / 'bah').is_char_device()) + self.assertIs((P / 'fileA\udfff').is_char_device(), False) + self.assertIs((P / 'fileA\x00').is_char_device(), False) + + def _check_complex_symlinks(self, link0_target): + if not self.can_symlink: + self.skipTest("symlinks required") + + # Test solving a non-looping chain of symlinks (issue #19887). + pathmod = self.pathmod + P = self.cls(self.base) + P.joinpath('link1').symlink_to(pathmod.join('link0', 'link0'), target_is_directory=True) + P.joinpath('link2').symlink_to(pathmod.join('link1', 'link1'), target_is_directory=True) + P.joinpath('link3').symlink_to(pathmod.join('link2', 'link2'), target_is_directory=True) + P.joinpath('link0').symlink_to(link0_target, target_is_directory=True) + + # Resolve absolute paths. + p = (P / 'link0').resolve() + self.assertEqual(p, P) + self.assertEqualNormCase(str(p), self.base) + p = (P / 'link1').resolve() + self.assertEqual(p, P) + self.assertEqualNormCase(str(p), self.base) + p = (P / 'link2').resolve() + self.assertEqual(p, P) + self.assertEqualNormCase(str(p), self.base) + p = (P / 'link3').resolve() + self.assertEqual(p, P) + self.assertEqualNormCase(str(p), self.base) + + # Resolve relative paths. + try: + self.cls('').absolute() + except UnsupportedOperation: + return + old_path = os.getcwd() + os.chdir(self.base) + try: + p = self.cls('link0').resolve() + self.assertEqual(p, P) + self.assertEqualNormCase(str(p), self.base) + p = self.cls('link1').resolve() + self.assertEqual(p, P) + self.assertEqualNormCase(str(p), self.base) + p = self.cls('link2').resolve() + self.assertEqual(p, P) + self.assertEqualNormCase(str(p), self.base) + p = self.cls('link3').resolve() + self.assertEqual(p, P) + self.assertEqualNormCase(str(p), self.base) + finally: + os.chdir(old_path) + + def test_complex_symlinks_absolute(self): + self._check_complex_symlinks(self.base) + + def test_complex_symlinks_relative(self): + self._check_complex_symlinks('.') + + def test_complex_symlinks_relative_dot_dot(self): + self._check_complex_symlinks(self.pathmod.join('dirA', '..')) + + def setUpWalk(self): + # Build: + # TESTFN/ + # TEST1/ a file kid and two directory kids + # tmp1 + # SUB1/ a file kid and a directory kid + # tmp2 + # SUB11/ no kids + # SUB2/ a file kid and a dirsymlink kid + # tmp3 + # link/ a symlink to TEST2 + # broken_link + # broken_link2 + # TEST2/ + # tmp4 a lone file + self.walk_path = self.cls(self.base, "TEST1") + self.sub1_path = self.walk_path / "SUB1" + self.sub11_path = self.sub1_path / "SUB11" + self.sub2_path = self.walk_path / "SUB2" + tmp1_path = self.walk_path / "tmp1" + tmp2_path = self.sub1_path / "tmp2" + tmp3_path = self.sub2_path / "tmp3" + self.link_path = self.sub2_path / "link" + t2_path = self.cls(self.base, "TEST2") + tmp4_path = self.cls(self.base, "TEST2", "tmp4") + broken_link_path = self.sub2_path / "broken_link" + broken_link2_path = self.sub2_path / "broken_link2" + + self.sub11_path.mkdir(parents=True) + self.sub2_path.mkdir(parents=True) + t2_path.mkdir(parents=True) + + for path in tmp1_path, tmp2_path, tmp3_path, tmp4_path: + with path.open("w", encoding='utf-8') as f: + f.write(f"I'm {path} and proud of it. Blame test_pathlib.\n") + + if self.can_symlink: + self.link_path.symlink_to(t2_path) + broken_link_path.symlink_to('broken') + broken_link2_path.symlink_to(self.cls('tmp3', 'broken')) + self.sub2_tree = (self.sub2_path, [], ["broken_link", "broken_link2", "link", "tmp3"]) + else: + self.sub2_tree = (self.sub2_path, [], ["tmp3"]) + + def test_walk_topdown(self): + self.setUpWalk() + walker = self.walk_path.walk() + entry = next(walker) + entry[1].sort() # Ensure we visit SUB1 before SUB2 + self.assertEqual(entry, (self.walk_path, ["SUB1", "SUB2"], ["tmp1"])) + entry = next(walker) + self.assertEqual(entry, (self.sub1_path, ["SUB11"], ["tmp2"])) + entry = next(walker) + self.assertEqual(entry, (self.sub11_path, [], [])) + entry = next(walker) + entry[1].sort() + entry[2].sort() + self.assertEqual(entry, self.sub2_tree) + with self.assertRaises(StopIteration): + next(walker) + + def test_walk_prune(self): + self.setUpWalk() + # Prune the search. + all = [] + for root, dirs, files in self.walk_path.walk(): + all.append((root, dirs, files)) + if 'SUB1' in dirs: + # Note that this also mutates the dirs we appended to all! + dirs.remove('SUB1') + + self.assertEqual(len(all), 2) + self.assertEqual(all[0], (self.walk_path, ["SUB2"], ["tmp1"])) + + all[1][-1].sort() + all[1][1].sort() + self.assertEqual(all[1], self.sub2_tree) + + def test_walk_bottom_up(self): + self.setUpWalk() + seen_testfn = seen_sub1 = seen_sub11 = seen_sub2 = False + for path, dirnames, filenames in self.walk_path.walk(top_down=False): + if path == self.walk_path: + self.assertFalse(seen_testfn) + self.assertTrue(seen_sub1) + self.assertTrue(seen_sub2) + self.assertEqual(sorted(dirnames), ["SUB1", "SUB2"]) + self.assertEqual(filenames, ["tmp1"]) + seen_testfn = True + elif path == self.sub1_path: + self.assertFalse(seen_testfn) + self.assertFalse(seen_sub1) + self.assertTrue(seen_sub11) + self.assertEqual(dirnames, ["SUB11"]) + self.assertEqual(filenames, ["tmp2"]) + seen_sub1 = True + elif path == self.sub11_path: + self.assertFalse(seen_sub1) + self.assertFalse(seen_sub11) + self.assertEqual(dirnames, []) + self.assertEqual(filenames, []) + seen_sub11 = True + elif path == self.sub2_path: + self.assertFalse(seen_testfn) + self.assertFalse(seen_sub2) + self.assertEqual(sorted(dirnames), sorted(self.sub2_tree[1])) + self.assertEqual(sorted(filenames), sorted(self.sub2_tree[2])) + seen_sub2 = True + else: + raise AssertionError(f"Unexpected path: {path}") + self.assertTrue(seen_testfn) + + def test_walk_follow_symlinks(self): + if not self.can_symlink: + self.skipTest("symlinks required") + self.setUpWalk() + walk_it = self.walk_path.walk(follow_symlinks=True) + for root, dirs, files in walk_it: + if root == self.link_path: + self.assertEqual(dirs, []) + self.assertEqual(files, ["tmp4"]) + break + else: + self.fail("Didn't follow symlink with follow_symlinks=True") + + def test_walk_symlink_location(self): + if not self.can_symlink: + self.skipTest("symlinks required") + self.setUpWalk() + # Tests whether symlinks end up in filenames or dirnames depending + # on the `follow_symlinks` argument. + walk_it = self.walk_path.walk(follow_symlinks=False) + for root, dirs, files in walk_it: + if root == self.sub2_path: + self.assertIn("link", files) + break + else: + self.fail("symlink not found") + + walk_it = self.walk_path.walk(follow_symlinks=True) + for root, dirs, files in walk_it: + if root == self.sub2_path: + self.assertIn("link", dirs) + break + else: + self.fail("symlink not found") + + +class DummyPathWithSymlinks(DummyPath): + __slots__ = () + + # Reduce symlink traversal limit to make tests run faster. + _max_symlinks = 20 + + def readlink(self): + path = str(self.parent.resolve() / self.name) + if path in self._symlinks: + return self.with_segments(self._symlinks[path]) + elif path in self._files or path in self._directories: + raise OSError(errno.EINVAL, "Not a symlink", path) + else: + raise FileNotFoundError(errno.ENOENT, "File not found", path) + + def symlink_to(self, target, target_is_directory=False): + self._directories[str(self.parent)].add(self.name) + self._symlinks[str(self)] = str(target) + + +class DummyPathWithSymlinksTest(DummyPathTest): + cls = DummyPathWithSymlinks + can_symlink = True + + +if __name__ == "__main__": + unittest.main() diff --git a/Lib/test/test_patma.py b/Lib/test/test_patma.py index dedbc828784184..298e78ccee3875 100644 --- a/Lib/test/test_patma.py +++ b/Lib/test/test_patma.py @@ -2760,6 +2760,132 @@ def test_patma_255(self): self.assertEqual(y, 1) self.assertIs(z, x) + def test_patma_runtime_checkable_protocol(self): + # Runtime-checkable protocol + from typing import Protocol, runtime_checkable + + @runtime_checkable + class P(Protocol): + x: int + y: int + + class A: + def __init__(self, x: int, y: int): + self.x = x + self.y = y + + class B(A): ... + + for cls in (A, B): + with self.subTest(cls=cls.__name__): + inst = cls(1, 2) + w = 0 + match inst: + case P() as p: + self.assertIsInstance(p, cls) + self.assertEqual(p.x, 1) + self.assertEqual(p.y, 2) + w = 1 + self.assertEqual(w, 1) + + q = 0 + match inst: + case P(x=x, y=y): + self.assertEqual(x, 1) + self.assertEqual(y, 2) + q = 1 + self.assertEqual(q, 1) + + + def test_patma_generic_protocol(self): + # Runtime-checkable generic protocol + from typing import Generic, TypeVar, Protocol, runtime_checkable + + T = TypeVar('T') # not using PEP695 to be able to backport changes + + @runtime_checkable + class P(Protocol[T]): + a: T + b: T + + class A: + def __init__(self, x: int, y: int): + self.x = x + self.y = y + + class G(Generic[T]): + def __init__(self, x: T, y: T): + self.x = x + self.y = y + + for cls in (A, G): + with self.subTest(cls=cls.__name__): + inst = cls(1, 2) + w = 0 + match inst: + case P(): + w = 1 + self.assertEqual(w, 0) + + def test_patma_protocol_with_match_args(self): + # Runtime-checkable protocol with `__match_args__` + from typing import Protocol, runtime_checkable + + # Used to fail before + # https://github.com/python/cpython/issues/110682 + @runtime_checkable + class P(Protocol): + __match_args__ = ('x', 'y') + x: int + y: int + + class A: + def __init__(self, x: int, y: int): + self.x = x + self.y = y + + class B(A): ... + + for cls in (A, B): + with self.subTest(cls=cls.__name__): + inst = cls(1, 2) + w = 0 + match inst: + case P() as p: + self.assertIsInstance(p, cls) + self.assertEqual(p.x, 1) + self.assertEqual(p.y, 2) + w = 1 + self.assertEqual(w, 1) + + q = 0 + match inst: + case P(x=x, y=y): + self.assertEqual(x, 1) + self.assertEqual(y, 2) + q = 1 + self.assertEqual(q, 1) + + j = 0 + match inst: + case P(x=1, y=2): + j = 1 + self.assertEqual(j, 1) + + g = 0 + match inst: + case P(x, y): + self.assertEqual(x, 1) + self.assertEqual(y, 2) + g = 1 + self.assertEqual(g, 1) + + h = 0 + match inst: + case P(1, 2): + h = 1 + self.assertEqual(h, 1) + class TestSyntaxErrors(unittest.TestCase): @@ -3198,6 +3324,35 @@ def test_class_pattern_not_type(self): w = 0 self.assertIsNone(w) + def test_regular_protocol(self): + from typing import Protocol + class P(Protocol): ... + msg = ( + 'Instance and class checks can only be used ' + 'with @runtime_checkable protocols' + ) + w = None + with self.assertRaisesRegex(TypeError, msg): + match 1: + case P(): + w = 0 + self.assertIsNone(w) + + def test_positional_patterns_with_regular_protocol(self): + from typing import Protocol + class P(Protocol): + x: int # no `__match_args__` + y: int + class A: + x = 1 + y = 2 + w = None + with self.assertRaises(TypeError): + match A(): + case P(x, y): + w = 0 + self.assertIsNone(w) + class TestValueErrors(unittest.TestCase): diff --git a/Lib/test/test_pdb.py b/Lib/test/test_pdb.py index a66953557e52dc..d53fe3c611bc35 100644 --- a/Lib/test/test_pdb.py +++ b/Lib/test/test_pdb.py @@ -15,6 +15,8 @@ from io import StringIO from test import support from test.support import os_helper +from test.support.import_helper import import_module +from test.support.pty_helper import run_pty # This little helper class is essential for testing pdb under doctest. from test.test_doctest import _FakeInput from unittest.mock import patch @@ -664,18 +666,32 @@ def test_pdb_alias_command(): ... o.method() >>> with PdbTestInput([ # doctest: +ELLIPSIS + ... 'alias pi', ... 'alias pi for k in %1.__dict__.keys(): print(f"%1.{k} = {%1.__dict__[k]}")', ... 'alias ps pi self', + ... 'alias ps', ... 'pi o', ... 's', ... 'ps', + ... 'alias myp p %2', + ... 'alias myp', + ... 'alias myp p %1', + ... 'myp', + ... 'myp 1', + ... 'myp 1 2', + ... 'alias repeat_second_arg p "%* %2"', + ... 'repeat_second_arg 1 2 3', ... 'continue', ... ]): ... test_function() > (4)test_function() -> o.method() + (Pdb) alias pi + *** Unknown alias 'pi' (Pdb) alias pi for k in %1.__dict__.keys(): print(f"%1.{k} = {%1.__dict__[k]}") (Pdb) alias ps pi self + (Pdb) alias ps + ps = pi self (Pdb) pi o o.attr1 = 10 o.attr2 = str @@ -686,6 +702,20 @@ def test_pdb_alias_command(): (Pdb) ps self.attr1 = 10 self.attr2 = str + (Pdb) alias myp p %2 + *** Replaceable parameters must be consecutive + (Pdb) alias myp + *** Unknown alias 'myp' + (Pdb) alias myp p %1 + (Pdb) myp + *** Not enough arguments for alias 'myp' + (Pdb) myp 1 + 1 + (Pdb) myp 1 2 + *** Too many arguments for alias 'myp' + (Pdb) alias repeat_second_arg p "%* %2" + (Pdb) repeat_second_arg 1 2 3 + '1 2 3 2' (Pdb) continue """ @@ -748,6 +778,59 @@ def test_pdb_where_command(): (Pdb) continue """ +def test_pdb_interact_command(): + """Test interact command + + >>> g = 0 + >>> dict_g = {} + + >>> def test_function(): + ... x = 1 + ... lst_local = [] + ... import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace() + + >>> with PdbTestInput([ # doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE + ... 'interact', + ... 'x', + ... 'g', + ... 'x = 2', + ... 'g = 3', + ... 'dict_g["a"] = True', + ... 'lst_local.append(x)', + ... 'exit()', + ... 'p x', + ... 'p g', + ... 'p dict_g', + ... 'p lst_local', + ... 'continue', + ... ]): + ... test_function() + --Return-- + > (4)test_function()->None + -> import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace() + (Pdb) interact + *pdb interact start* + ... x + 1 + ... g + 0 + ... x = 2 + ... g = 3 + ... dict_g["a"] = True + ... lst_local.append(x) + ... exit() + *exit from pdb interact command* + (Pdb) p x + 1 + (Pdb) p g + 0 + (Pdb) p dict_g + {'a': True} + (Pdb) p lst_local + [2] + (Pdb) continue + """ + def test_convenience_variables(): """Test convenience variables @@ -826,6 +909,414 @@ def test_convenience_variables(): (Pdb) continue """ + +def test_post_mortem_chained(): + """Test post mortem traceback debugging of chained exception + + >>> def test_function_2(): + ... try: + ... 1/0 + ... finally: + ... print('Exception!') + + >>> def test_function_reraise(): + ... try: + ... test_function_2() + ... except ZeroDivisionError as e: + ... raise ZeroDivisionError('reraised') from e + + >>> def test_function(): + ... import pdb; + ... instance = pdb.Pdb(nosigint=True, readrc=False) + ... try: + ... test_function_reraise() + ... except Exception as e: + ... pdb._post_mortem(e, instance) + + >>> with PdbTestInput([ # doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE + ... 'exceptions', + ... 'exceptions 0', + ... '$_exception', + ... 'up', + ... 'down', + ... 'exceptions 1', + ... '$_exception', + ... 'up', + ... 'down', + ... 'exceptions -1', + ... 'exceptions 3', + ... 'up', + ... 'exit', + ... ]): + ... try: + ... test_function() + ... except ZeroDivisionError: + ... print('Correctly reraised.') + Exception! + > (5)test_function_reraise() + -> raise ZeroDivisionError('reraised') from e + (Pdb) exceptions + 0 ZeroDivisionError('division by zero') + > 1 ZeroDivisionError('reraised') + (Pdb) exceptions 0 + > (3)test_function_2() + -> 1/0 + (Pdb) $_exception + ZeroDivisionError('division by zero') + (Pdb) up + > (3)test_function_reraise() + -> test_function_2() + (Pdb) down + > (3)test_function_2() + -> 1/0 + (Pdb) exceptions 1 + > (5)test_function_reraise() + -> raise ZeroDivisionError('reraised') from e + (Pdb) $_exception + ZeroDivisionError('reraised') + (Pdb) up + > (5)test_function() + -> test_function_reraise() + (Pdb) down + > (5)test_function_reraise() + -> raise ZeroDivisionError('reraised') from e + (Pdb) exceptions -1 + *** No exception with that number + (Pdb) exceptions 3 + *** No exception with that number + (Pdb) up + > (5)test_function() + -> test_function_reraise() + (Pdb) exit + """ + + +def test_post_mortem_cause_no_context(): + """Test post mortem traceback debugging of chained exception + + >>> def make_exc_with_stack(type_, *content, from_=None): + ... try: + ... raise type_(*content) from from_ + ... except Exception as out: + ... return out + ... + + >>> def main(): + ... try: + ... raise ValueError('Context Not Shown') + ... except Exception as e1: + ... raise ValueError("With Cause") from make_exc_with_stack(TypeError,'The Cause') + + >>> def test_function(): + ... import pdb; + ... instance = pdb.Pdb(nosigint=True, readrc=False) + ... try: + ... main() + ... except Exception as e: + ... pdb._post_mortem(e, instance) + + >>> with PdbTestInput([ # doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE + ... 'exceptions', + ... 'exceptions 0', + ... 'exceptions 1', + ... 'up', + ... 'down', + ... 'exit', + ... ]): + ... try: + ... test_function() + ... except ValueError: + ... print('Ok.') + > (5)main() + -> raise ValueError("With Cause") from make_exc_with_stack(TypeError,'The Cause') + (Pdb) exceptions + 0 TypeError('The Cause') + > 1 ValueError('With Cause') + (Pdb) exceptions 0 + > (3)make_exc_with_stack() + -> raise type_(*content) from from_ + (Pdb) exceptions 1 + > (5)main() + -> raise ValueError("With Cause") from make_exc_with_stack(TypeError,'The Cause') + (Pdb) up + > (5)test_function() + -> main() + (Pdb) down + > (5)main() + -> raise ValueError("With Cause") from make_exc_with_stack(TypeError,'The Cause') + (Pdb) exit""" + + +def test_post_mortem_context_of_the_cause(): + """Test post mortem traceback debugging of chained exception + + + >>> def main(): + ... try: + ... raise TypeError('Context of the cause') + ... except Exception as e1: + ... try: + ... raise ValueError('Root Cause') + ... except Exception as e2: + ... ex = e2 + ... raise ValueError("With Cause, and cause has context") from ex + + >>> def test_function(): + ... import pdb; + ... instance = pdb.Pdb(nosigint=True, readrc=False) + ... try: + ... main() + ... except Exception as e: + ... pdb._post_mortem(e, instance) + + >>> with PdbTestInput([ # doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE + ... 'exceptions', + ... 'exceptions 2', + ... 'up', + ... 'down', + ... 'exceptions 3', + ... 'up', + ... 'down', + ... 'exceptions 4', + ... 'up', + ... 'down', + ... 'exit', + ... ]): + ... try: + ... test_function() + ... except ValueError: + ... print('Correctly reraised.') + > (9)main() + -> raise ValueError("With Cause, and cause has context") from ex + (Pdb) exceptions + 0 TypeError('Context of the cause') + 1 ValueError('Root Cause') + > 2 ValueError('With Cause, and cause has context') + (Pdb) exceptions 2 + > (9)main() + -> raise ValueError("With Cause, and cause has context") from ex + (Pdb) up + > (5)test_function() + -> main() + (Pdb) down + > (9)main() + -> raise ValueError("With Cause, and cause has context") from ex + (Pdb) exceptions 3 + *** No exception with that number + (Pdb) up + > (5)test_function() + -> main() + (Pdb) down + > (9)main() + -> raise ValueError("With Cause, and cause has context") from ex + (Pdb) exceptions 4 + *** No exception with that number + (Pdb) up + > (5)test_function() + -> main() + (Pdb) down + > (9)main() + -> raise ValueError("With Cause, and cause has context") from ex + (Pdb) exit + """ + + +def test_post_mortem_from_none(): + """Test post mortem traceback debugging of chained exception + + In particular that cause from None (which sets __supress_context__ to True) + does not show context. + + + >>> def main(): + ... try: + ... raise TypeError('Context of the cause') + ... except Exception as e1: + ... raise ValueError("With Cause, and cause has context") from None + + >>> def test_function(): + ... import pdb; + ... instance = pdb.Pdb(nosigint=True, readrc=False) + ... try: + ... main() + ... except Exception as e: + ... pdb._post_mortem(e, instance) + + >>> with PdbTestInput([ # doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE + ... 'exceptions', + ... 'exit', + ... ]): + ... try: + ... test_function() + ... except ValueError: + ... print('Correctly reraised.') + > (5)main() + -> raise ValueError("With Cause, and cause has context") from None + (Pdb) exceptions + > 0 ValueError('With Cause, and cause has context') + (Pdb) exit + """ + + +def test_post_mortem_from_no_stack(): + """Test post mortem traceback debugging of chained exception + + especially when one exception has no stack. + + >>> def main(): + ... raise Exception() from Exception() + + + >>> def test_function(): + ... import pdb; + ... instance = pdb.Pdb(nosigint=True, readrc=False) + ... try: + ... main() + ... except Exception as e: + ... pdb._post_mortem(e, instance) + + >>> with PdbTestInput( # doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE + ... ["exceptions", + ... "exceptions 0", + ... "exit"], + ... ): + ... try: + ... test_function() + ... except ValueError: + ... print('Correctly reraised.') + > (2)main() + -> raise Exception() from Exception() + (Pdb) exceptions + - Exception() + > 1 Exception() + (Pdb) exceptions 0 + *** This exception does not have a traceback, cannot jump to it + (Pdb) exit + """ + + +def test_post_mortem_single_no_stack(): + """Test post mortem called when origin exception has no stack + + + >>> def test_function(): + ... import pdb; + ... instance = pdb.Pdb(nosigint=True, readrc=False) + ... import sys + ... sys.last_exc = Exception() + ... pdb._post_mortem(sys.last_exc, instance) + + >>> with PdbTestInput( # doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE + ... [] + ... ): + ... try: + ... test_function() + ... except ValueError as e: + ... print(e) + A valid traceback must be passed if no exception is being handled + """ + +def test_post_mortem_complex(): + """Test post mortem traceback debugging of chained exception + + Test with simple and complex cycles, exception groups,... + + >>> def make_ex_with_stack(type_, *content, from_=None): + ... try: + ... raise type_(*content) from from_ + ... except Exception as out: + ... return out + ... + + >>> def cycle(): + ... try: + ... raise ValueError("Cycle Leaf") + ... except Exception as e: + ... raise e from e + ... + + >>> def tri_cycle(): + ... a = make_ex_with_stack(ValueError, "Cycle1") + ... b = make_ex_with_stack(ValueError, "Cycle2") + ... c = make_ex_with_stack(ValueError, "Cycle3") + ... + ... a.__cause__ = b + ... b.__cause__ = c + ... + ... raise c from a + ... + + >>> def cause(): + ... try: + ... raise ValueError("Cause Leaf") + ... except Exception as e: + ... raise e + ... + + >>> def context(n=10): + ... try: + ... raise ValueError(f"Context Leaf {n}") + ... except Exception as e: + ... if n == 0: + ... raise ValueError(f"With Context {n}") from e + ... else: + ... context(n - 1) + ... + + >>> def main(): + ... try: + ... cycle() + ... except Exception as e1: + ... try: + ... tri_cycle() + ... except Exception as e2: + ... ex = e2 + ... raise ValueError("With Context and With Cause") from ex + + + >>> def test_function(): + ... import pdb; + ... instance = pdb.Pdb(nosigint=True, readrc=False) + ... try: + ... main() + ... except Exception as e: + ... pdb._post_mortem(e, instance) + + >>> with PdbTestInput( # doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE + ... ["exceptions", + ... "exceptions 0", + ... "exceptions 1", + ... "exceptions 2", + ... "exceptions 3", + ... "exit"], + ... ): + ... try: + ... test_function() + ... except ValueError: + ... print('Correctly reraised.') + > (9)main() + -> raise ValueError("With Context and With Cause") from ex + (Pdb) exceptions + 0 ValueError('Cycle2') + 1 ValueError('Cycle1') + 2 ValueError('Cycle3') + > 3 ValueError('With Context and With Cause') + (Pdb) exceptions 0 + > (3)make_ex_with_stack() + -> raise type_(*content) from from_ + (Pdb) exceptions 1 + > (3)make_ex_with_stack() + -> raise type_(*content) from from_ + (Pdb) exceptions 2 + > (3)make_ex_with_stack() + -> raise type_(*content) from from_ + (Pdb) exceptions 3 + > (9)main() + -> raise ValueError("With Context and With Cause") from ex + (Pdb) exit + """ + + def test_post_mortem(): """Test post mortem traceback debugging. @@ -1102,7 +1593,7 @@ def test_next_until_return_at_return_event(): > (3)test_function() -> test_function_2() (Pdb) break test_function_2 - Breakpoint 1 at :1 + Breakpoint 1 at :2 (Pdb) continue > (2)test_function_2() -> x = 1 @@ -1524,7 +2015,7 @@ def test_pdb_next_command_in_generator_for_loop(): > (3)test_function() -> for i in test_gen(): (Pdb) break test_gen - Breakpoint 1 at :1 + Breakpoint 1 at :2 (Pdb) continue > (2)test_gen() -> yield 0 @@ -1614,6 +2105,46 @@ def test_pdb_multiline_statement(): (Pdb) c """ +def test_pdb_show_attribute_and_item(): + """Test for multiline statement + + >>> def test_function(): + ... n = lambda x: x + ... c = {"a": 1} + ... import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace() + ... pass + + >>> with PdbTestInput([ # doctest: +NORMALIZE_WHITESPACE + ... 'c["a"]', + ... 'c.get("a")', + ... 'n(1)', + ... 'j=1', + ... 'j+1', + ... 'r"a"', + ... 'next(iter([1]))', + ... 'list((0, 1))', + ... 'c' + ... ]): + ... test_function() + > (5)test_function() + -> pass + (Pdb) c["a"] + 1 + (Pdb) c.get("a") + 1 + (Pdb) n(1) + 1 + (Pdb) j=1 + (Pdb) j+1 + 2 + (Pdb) r"a" + 'a' + (Pdb) next(iter([1])) + 1 + (Pdb) list((0, 1)) + [0, 1] + (Pdb) c + """ def test_pdb_issue_20766(): """Test for reference leaks when the SIGINT handler is set. @@ -1855,6 +2386,49 @@ def test_pdb_issue_gh_101517(): (Pdb) continue """ +def test_pdb_issue_gh_108976(): + """See GH-108976 + Make sure setting f_trace_opcodes = True won't crash pdb + >>> def test_function(): + ... import sys + ... sys._getframe().f_trace_opcodes = True + ... import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace() + ... a = 1 + >>> with PdbTestInput([ # doctest: +NORMALIZE_WHITESPACE + ... 'continue' + ... ]): + ... test_function() + bdb.Bdb.dispatch: unknown debugging event: 'opcode' + > (5)test_function() + -> a = 1 + (Pdb) continue + """ + + +def test_pdb_issue_gh_80731(): + """See GH-80731 + + pdb should correctly print exception info if in an except block. + + >>> with PdbTestInput([ # doctest: +ELLIPSIS + ... 'import sys', + ... 'sys.exc_info()', + ... 'continue' + ... ]): + ... try: + ... raise ValueError('Correct') + ... except ValueError: + ... import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace() + ... pass + > (10)() + -> pass + (Pdb) import sys + (Pdb) sys.exc_info() + (, ValueError('Correct'), ) + (Pdb) continue + """ + + def test_pdb_ambiguous_statements(): """See GH-104301 @@ -1878,6 +2452,119 @@ def test_pdb_ambiguous_statements(): (Pdb) continue """ +def test_pdb_f_trace_lines(): + """GH-80675 + + pdb should work even if f_trace_lines is set to False on some frames. + + >>> reset_Breakpoint() + + >>> def test_function(): + ... import sys + ... frame = sys._getframe() + ... frame.f_trace_lines = False + ... import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace() + ... if frame.f_trace_lines != False: + ... print("f_trace_lines is not reset after continue!") + + >>> with PdbTestInput([ # doctest: +NORMALIZE_WHITESPACE + ... 'continue' + ... ]): + ... test_function() + > (6)test_function() + -> if frame.f_trace_lines != False: + (Pdb) continue + """ + +def test_pdb_function_break(): + """Testing the line number of break on function + + >>> def foo(): pass + + >>> def bar(): + ... + ... pass + + >>> def boo(): + ... # comments + ... global x + ... x = 1 + + >>> def gen(): + ... yield 42 + + >>> def test_function(): + ... import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace() + ... pass + + >>> with PdbTestInput([ # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE + ... 'break foo', + ... 'break bar', + ... 'break boo', + ... 'break gen', + ... 'continue' + ... ]): + ... test_function() + > (3)test_function() + -> pass + (Pdb) break foo + Breakpoint ... at :1 + (Pdb) break bar + Breakpoint ... at :3 + (Pdb) break boo + Breakpoint ... at :4 + (Pdb) break gen + Breakpoint ... at :2 + (Pdb) continue + """ + +def test_pdb_issue_gh_65052(): + """See GH-65052 + + args, retval and display should not crash if the object is not displayable + >>> class A: + ... def __new__(cls): + ... import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace() + ... return object.__new__(cls) + ... def __init__(self): + ... import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace() + ... self.a = 1 + ... def __repr__(self): + ... return self.a + + >>> def test_function(): + ... A() + >>> with PdbTestInput([ # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE + ... 's', + ... 'retval', + ... 'continue', + ... 'args', + ... 'display self', + ... 'display', + ... 'continue', + ... ]): + ... test_function() + > (4)__new__() + -> return object.__new__(cls) + (Pdb) s + --Return-- + > (4)__new__()-> + -> return object.__new__(cls) + (Pdb) retval + *** repr(retval) failed: AttributeError: 'A' object has no attribute 'a' *** + (Pdb) continue + > (7)__init__() + -> self.a = 1 + (Pdb) args + self = *** repr(self) failed: AttributeError: 'A' object has no attribute 'a' *** + (Pdb) display self + display self: *** repr(self) failed: AttributeError: 'A' object has no attribute 'a' *** + (Pdb) display + Currently displaying: + self: *** repr(self) failed: AttributeError: 'A' object has no attribute 'a' *** + (Pdb) continue + """ + @support.requires_subprocess() class PdbTestCase(unittest.TestCase): @@ -1886,15 +2573,21 @@ def tearDown(self): @unittest.skipIf(sys.flags.safe_path, 'PYTHONSAFEPATH changes default sys.path') - def _run_pdb(self, pdb_args, commands, expected_returncode=0): + def _run_pdb(self, pdb_args, commands, + expected_returncode=0, + extra_env=None): self.addCleanup(os_helper.rmtree, '__pycache__') cmd = [sys.executable, '-m', 'pdb'] + pdb_args + if extra_env is not None: + env = os.environ | extra_env + else: + env = os.environ with subprocess.Popen( cmd, stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.STDOUT, - env = {**os.environ, 'PYTHONIOENCODING': 'utf-8'} + env = {**env, 'PYTHONIOENCODING': 'utf-8'} ) as proc: stdout, stderr = proc.communicate(str.encode(commands)) stdout = stdout and bytes.decode(stdout) @@ -1906,13 +2599,15 @@ def _run_pdb(self, pdb_args, commands, expected_returncode=0): ) return stdout, stderr - def run_pdb_script(self, script, commands, expected_returncode=0): + def run_pdb_script(self, script, commands, + expected_returncode=0, + extra_env=None): """Run 'script' lines with pdb and the pdb 'commands'.""" filename = 'main.py' with open(filename, 'w') as f: f.write(textwrap.dedent(script)) self.addCleanup(os_helper.unlink, filename) - return self._run_pdb([filename], commands, expected_returncode) + return self._run_pdb([filename], commands, expected_returncode, extra_env) def run_pdb_module(self, script, commands): """Runs the script code as part of a module""" @@ -2119,13 +2814,28 @@ def test_issue16180(self): commands = '' expected = "SyntaxError:" stdout, stderr = self.run_pdb_script( - script, commands, expected_returncode=1 + script, commands ) self.assertIn(expected, stdout, '\n\nExpected:\n{}\nGot:\n{}\n' 'Fail to handle a syntax error in the debuggee.' .format(expected, stdout)) + def test_issue84583(self): + # A syntax error from ast.literal_eval should not make pdb exit. + script = "import ast; ast.literal_eval('')\n" + commands = """ + continue + where + quit + """ + stdout, stderr = self.run_pdb_script(script, commands) + # The code should appear 3 times in the stdout: + # 1. when pdb starts + # 2. when the exception is raised, in trackback + # 3. in where command + self.assertEqual(stdout.count("ast.literal_eval('')"), 3) + def test_issue26053(self): # run command of pdb prompt echoes the correct args script = "print('hello')" @@ -2286,8 +2996,7 @@ def test_module_without_a_main(self): stdout, stderr = self._run_pdb( ['-m', module_name], "", expected_returncode=1 ) - self.assertIn("ImportError: No module named t_main.__main__", - stdout.splitlines()) + self.assertIn("ImportError: No module named t_main.__main__;", stdout) def test_package_without_a_main(self): pkg_name = 't_pkg' @@ -2305,6 +3014,22 @@ def test_package_without_a_main(self): "'t_pkg.t_main' is a package and cannot be directly executed", stdout) + def test_nonexistent_module(self): + assert not os.path.exists(os_helper.TESTFN) + stdout, stderr = self._run_pdb(["-m", os_helper.TESTFN], "", expected_returncode=1) + self.assertIn(f"ImportError: No module named {os_helper.TESTFN}", stdout) + + def test_dir_as_script(self): + with os_helper.temp_dir() as temp_dir: + stdout, stderr = self._run_pdb([temp_dir], "", expected_returncode=1) + self.assertIn(f"Error: {temp_dir} is a directory", stdout) + + def test_invalid_cmd_line_options(self): + stdout, stderr = self._run_pdb(["-c"], "", expected_returncode=2) + self.assertIn(f"pdb: error: argument -c/--command: expected one argument", stdout.split('\n')[1]) + stdout, stderr = self._run_pdb(["--spam", "-m", "pdb"], "", expected_returncode=2) + self.assertIn(f"pdb: error: unrecognized arguments: --spam", stdout.split('\n')[1]) + def test_blocks_at_first_code_line(self): script = """ #This is a comment, on line 2 @@ -2467,6 +3192,23 @@ def test_issue42384_symlink(self): self.assertEqual(stdout.split('\n')[2].rstrip('\r'), expected) + def test_safe_path(self): + """ With safe_path set, pdb should not mangle sys.path[0]""" + + script = textwrap.dedent(""" + import sys + import random + print('sys.path[0] is', sys.path[0]) + """) + commands = 'c\n' + + + with os_helper.temp_cwd() as cwd: + stdout, _ = self.run_pdb_script(script, commands, extra_env={'PYTHONSAFEPATH': '1'}) + + unexpected = f'sys.path[0] is {os.path.realpath(cwd)}' + self.assertNotIn(unexpected, stdout) + def test_issue42383(self): with os_helper.temp_cwd() as cwd: with open('foo.py', 'w') as f: @@ -2598,6 +3340,55 @@ def test_checkline_is_not_executable(self): self.assertFalse(db.checkline(os_helper.TESTFN, lineno)) +@support.requires_subprocess() +class PdbTestReadline(unittest.TestCase): + def setUpClass(): + # Ensure that the readline module is loaded + # If this fails, the test is skipped because SkipTest will be raised + readline = import_module('readline') + if readline.backend == "editline": + raise unittest.SkipTest("libedit readline is not supported for pdb") + + def test_basic_completion(self): + script = textwrap.dedent(""" + import pdb; pdb.Pdb().set_trace() + # Concatenate strings so that the output doesn't appear in the source + print('hello' + '!') + """) + + # List everything starting with 'co', there should be multiple matches + # then add ntin and complete 'contin' to 'continue' + input = b"co\t\tntin\t\n" + + output = run_pty(script, input) + + self.assertIn(b'commands', output) + self.assertIn(b'condition', output) + self.assertIn(b'continue', output) + self.assertIn(b'hello!', output) + + def test_expression_completion(self): + script = textwrap.dedent(""" + value = "speci" + import pdb; pdb.Pdb().set_trace() + """) + + # Complete: value + 'al' + input = b"val\t + 'al'\n" + # Complete: p value + 'es' + input += b"p val\t + 'es'\n" + # Complete: $_frame + input += b"$_fra\t\n" + # Continue + input += b"c\n" + + output = run_pty(script, input) + + self.assertIn(b'special', output) + self.assertIn(b'species', output) + self.assertIn(b'$_frame', output) + + def load_tests(loader, tests, pattern): from test import test_pdb tests.addTest(doctest.DocTestSuite(test_pdb)) diff --git a/Lib/test/test_peepholer.py b/Lib/test/test_peepholer.py index fba41f0b119796..76a6f25c34bbd3 100644 --- a/Lib/test/test_peepholer.py +++ b/Lib/test/test_peepholer.py @@ -4,6 +4,7 @@ import textwrap import unittest +from test import support from test.support.bytecode_helper import BytecodeTestCase, CfgOptimizationTestCase @@ -522,6 +523,7 @@ def genexpr(): return (y for x in a for y in [f(x)]) self.assertEqual(count_instr_recursively(genexpr, 'FOR_ITER'), 1) + @support.requires_resource('cpu') def test_format_combinations(self): flags = '-+ #0' testcases = [ @@ -1129,6 +1131,46 @@ def test_no_dead_store_elimination_in_different_lineno(self): ] self.cfg_optimization_test(insts, expected_insts, consts=list(range(3)), nlocals=1) + def test_unconditional_jump_threading(self): + + def get_insts(lno1, lno2, op1, op2): + return [ + lbl2 := self.Label(), + ('LOAD_NAME', 0, 10), + (op1, lbl1 := self.Label(), lno1), + ('LOAD_NAME', 1, 20), + lbl1, + (op2, lbl2, lno2), + ] + + + for op1 in ('JUMP', 'JUMP_NO_INTERRUPT'): + for op2 in ('JUMP', 'JUMP_NO_INTERRUPT'): + # different lines + lno1, lno2 = (4, 5) + with self.subTest(lno = (lno1, lno2), ops = (op1, op2)): + insts = get_insts(lno1, lno2, op1, op2) + expected_insts = [ + ('LOAD_NAME', 0, 10), + ('NOP', 0, 4), + (op2, 0, 5), + ] + self.cfg_optimization_test(insts, expected_insts, consts=list(range(5))) + + # Threading + for lno1, lno2 in [(-1, -1), (-1, 5), (6, -1), (7, 7)]: + with self.subTest(lno = (lno1, lno2), ops = (op1, op2)): + insts = get_insts(lno1, lno2, op1, op2) + lno = lno1 if lno1 != -1 else lno2 + if lno == -1: + lno = 10 # Propagated from the line before + + op = 'JUMP' if 'JUMP' in (op1, op2) else 'JUMP_NO_INTERRUPT' + expected_insts = [ + ('LOAD_NAME', 0, 10), + (op, 0, lno), + ] + self.cfg_optimization_test(insts, expected_insts, consts=list(range(5))) if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_peg_generator/__init__.py b/Lib/test/test_peg_generator/__init__.py index 77f72fcc7c6e3b..b32db4426f251d 100644 --- a/Lib/test/test_peg_generator/__init__.py +++ b/Lib/test/test_peg_generator/__init__.py @@ -1,13 +1,10 @@ import os.path -import unittest from test import support from test.support import load_package_tests -if support.check_sanitizer(address=True, memory=True): - # bpo-46633: Skip the test because it is too slow when Python is built - # with ASAN/MSAN: between 5 and 20 minutes on GitHub Actions. - raise unittest.SkipTest("test too slow on ASAN/MSAN build") +# Creating a virtual environment and building C extensions is slow +support.requires('cpu') # Load all tests in package diff --git a/Lib/test/test_peg_generator/test_pegen.py b/Lib/test/test_peg_generator/test_pegen.py index 3af2c0cf47d20a..86db767b99a228 100644 --- a/Lib/test/test_peg_generator/test_pegen.py +++ b/Lib/test/test_peg_generator/test_pegen.py @@ -42,6 +42,15 @@ def test_parse_grammar(self) -> None: ) self.assertEqual(repr(rules["term"]), expected_repr) + def test_repeated_rules(self) -> None: + grammar_source = """ + start: the_rule NEWLINE + the_rule: 'b' NEWLINE + the_rule: 'a' NEWLINE + """ + with self.assertRaisesRegex(GrammarError, "Repeated rule 'the_rule'"): + parse_string(grammar_source, GrammarParser) + def test_long_rule_str(self) -> None: grammar_source = """ start: zero | one | one zero | one one | one zero zero | one zero one | one one zero | one one one diff --git a/Lib/test/test_pep646_syntax.py b/Lib/test/test_pep646_syntax.py index 3ffa82dc55fa23..aac089b190bc11 100644 --- a/Lib/test/test_pep646_syntax.py +++ b/Lib/test/test_pep646_syntax.py @@ -1,3 +1,6 @@ +import doctest +import unittest + doctests = """ Setup @@ -317,10 +320,10 @@ __test__ = {'doctests' : doctests} -def test_main(verbose=False): - from test import support - from test import test_pep646_syntax - support.run_doctest(test_pep646_syntax, verbose) +def load_tests(loader, tests, pattern): + tests.addTest(doctest.DocTestSuite()) + return tests + if __name__ == "__main__": - test_main(verbose=True) + unittest.main() diff --git a/Lib/test/test_perf_profiler.py b/Lib/test/test_perf_profiler.py index 5418f9f35485f8..040be63da11447 100644 --- a/Lib/test/test_perf_profiler.py +++ b/Lib/test/test_perf_profiler.py @@ -17,6 +17,11 @@ if not support.has_subprocess_support: raise unittest.SkipTest("test module requires subprocess") +if support.check_sanitizer(address=True, memory=True, ub=True): + # gh-109580: Skip the test because it does crash randomly if Python is + # built with ASAN. + raise unittest.SkipTest("test crash randomly on ASAN/MSAN/UBSAN build") + def supports_trampoline_profiling(): perf_trampoline = sysconfig.get_config_var("PY_HAVE_PERF_TRAMPOLINE") @@ -287,7 +292,6 @@ def run_perf(cwd, *args, **env_vars): @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() @@ -349,6 +353,82 @@ def baz(n): self.assertNotIn(f"py::bar:{script}", stdout) self.assertNotIn(f"py::baz:{script}", stdout) + def test_pre_fork_compile(self): + code = """if 1: + import sys + import os + import sysconfig + from _testinternalcapi import ( + compile_perf_trampoline_entry, + perf_trampoline_set_persist_after_fork, + ) + + def foo_fork(): + pass + + def bar_fork(): + foo_fork() + + def foo(): + pass + + def bar(): + foo() + + def compile_trampolines_for_all_functions(): + perf_trampoline_set_persist_after_fork(1) + for _, obj in globals().items(): + if callable(obj) and hasattr(obj, '__code__'): + compile_perf_trampoline_entry(obj.__code__) + + if __name__ == "__main__": + compile_trampolines_for_all_functions() + pid = os.fork() + if pid == 0: + print(os.getpid()) + bar_fork() + else: + bar() + """ + + with temp_dir() as script_dir: + script = make_script(script_dir, "perftest", code) + with subprocess.Popen( + [sys.executable, "-Xperf", script], + universal_newlines=True, + stderr=subprocess.PIPE, + stdout=subprocess.PIPE, + ) as process: + stdout, stderr = process.communicate() + + self.assertEqual(process.returncode, 0) + self.assertNotIn("Error:", 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::foo_fork:{script}", perf_file_contents) + self.assertIn(f"py::bar_fork:{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) + + # Pre-compiled perf-map entries of a forked process must be + # identical in both the parent and child perf-map files. + perf_file_lines = perf_file_contents.split("\n") + for line in perf_file_lines: + if ( + f"py::foo_fork:{script}" in line + or f"py::bar_fork:{script}" in line + ): + self.assertIn(line, child_perf_file_contents) + if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_pickle.py b/Lib/test/test_pickle.py index 1a55da39bdc58d..f6405d6dd44ef6 100644 --- a/Lib/test/test_pickle.py +++ b/Lib/test/test_pickle.py @@ -122,6 +122,7 @@ class PyIdPersPicklerTests(AbstractIdentityPersistentPicklerTests, pickler = pickle._Pickler unpickler = pickle._Unpickler + persistent_load_error = pickle.UnpicklingError @support.cpython_only def test_pickler_reference_cycle(self): @@ -176,7 +177,6 @@ class DispatchTable: support.gc_collect() self.assertIsNone(table_ref()) - @support.cpython_only def test_unpickler_reference_cycle(self): def check(Unpickler): @@ -206,6 +206,28 @@ def persistent_load(pid): return pid check(PersUnpickler) + def test_pickler_super(self): + class PersPickler(self.pickler): + def persistent_id(subself, obj): + self.assertIsNone(super().persistent_id(obj)) + return obj + + for proto in range(pickle.HIGHEST_PROTOCOL + 1): + f = io.BytesIO() + pickler = PersPickler(f, proto) + pickler.dump('abc') + self.assertEqual(self.loads(f.getvalue()), 'abc') + + def test_unpickler_super(self): + class PersUnpickler(self.unpickler): + def persistent_load(subself, pid): + with self.assertRaises(self.persistent_load_error): + super().persistent_load(pid) + return pid + + for proto in range(pickle.HIGHEST_PROTOCOL + 1): + unpickler = PersUnpickler(io.BytesIO(self.dumps('abc', proto))) + self.assertEqual(unpickler.load(), 'abc') class PyPicklerUnpicklerObjectTests(AbstractPicklerUnpicklerObjectTests, unittest.TestCase): @@ -256,6 +278,7 @@ class CPersPicklerTests(PyPersPicklerTests): class CIdPersPicklerTests(PyIdPersPicklerTests): pickler = _pickle.Pickler unpickler = _pickle.Unpickler + persistent_load_error = _pickle.UnpicklingError class CDumpPickle_LoadPickle(PyPicklerTests): pickler = _pickle.Pickler @@ -326,7 +349,7 @@ class SizeofTests(unittest.TestCase): check_sizeof = support.check_sizeof def test_pickler(self): - basesize = support.calcobjsize('7P2n3i2n3i2P') + basesize = support.calcobjsize('6P2n3i2n3i2P') p = _pickle.Pickler(io.BytesIO()) self.assertEqual(object.__sizeof__(p), basesize) MT_size = struct.calcsize('3nP0n') @@ -343,7 +366,7 @@ def test_pickler(self): 0) # Write buffer is cleared after every dump(). def test_unpickler(self): - basesize = support.calcobjsize('2P2n2P 2P2n2i5P 2P3n8P2n2i') + basesize = support.calcobjsize('2P2nP 2P2n2i5P 2P3n8P2n2i') unpickler = _pickle.Unpickler P = struct.calcsize('P') # Size of memo table entry. n = struct.calcsize('n') # Size of mark table entry. diff --git a/Lib/test/test_plistlib.py b/Lib/test/test_plistlib.py index b08ababa341cfe..f47982907def21 100644 --- a/Lib/test/test_plistlib.py +++ b/Lib/test/test_plistlib.py @@ -13,6 +13,8 @@ import subprocess import binascii import collections +import time +import zoneinfo from test import support from test.support import os_helper from io import BytesIO @@ -508,6 +510,19 @@ def test_bytes(self): data2 = plistlib.dumps(pl2) self.assertEqual(data, data2) + def test_loads_str_with_xml_fmt(self): + pl = self._create() + b = plistlib.dumps(pl) + s = b.decode() + self.assertIsInstance(s, str) + pl2 = plistlib.loads(s) + self.assertEqual(pl, pl2) + + def test_loads_str_with_binary_fmt(self): + msg = "value must be bytes-like object when fmt is FMT_BINARY" + with self.assertRaisesRegex(TypeError, msg): + plistlib.loads('test', fmt=plistlib.FMT_BINARY) + def test_indentation_array(self): data = [[[[[[[[{'test': b'aaaaaa'}]]]]]]]] self.assertEqual(plistlib.loads(plistlib.dumps(data)), data) @@ -838,6 +853,54 @@ def test_xml_plist_with_entity_decl(self): "XML entity declarations are not supported"): plistlib.loads(XML_PLIST_WITH_ENTITY, fmt=plistlib.FMT_XML) + def test_load_aware_datetime(self): + dt = plistlib.loads(b"2023-12-10T08:03:30Z", + aware_datetime=True) + self.assertEqual(dt.tzinfo, datetime.UTC) + + @unittest.skipUnless("America/Los_Angeles" in zoneinfo.available_timezones(), + "Can't find timezone datebase") + def test_dump_aware_datetime(self): + dt = datetime.datetime(2345, 6, 7, 8, 9, 10, + tzinfo=zoneinfo.ZoneInfo("America/Los_Angeles")) + for fmt in ALL_FORMATS: + s = plistlib.dumps(dt, fmt=fmt, aware_datetime=True) + loaded_dt = plistlib.loads(s, fmt=fmt, aware_datetime=True) + self.assertEqual(loaded_dt.tzinfo, datetime.UTC) + self.assertEqual(loaded_dt, dt) + + def test_dump_utc_aware_datetime(self): + dt = datetime.datetime(2345, 6, 7, 8, 9, 10, tzinfo=datetime.UTC) + for fmt in ALL_FORMATS: + s = plistlib.dumps(dt, fmt=fmt, aware_datetime=True) + loaded_dt = plistlib.loads(s, fmt=fmt, aware_datetime=True) + self.assertEqual(loaded_dt.tzinfo, datetime.UTC) + self.assertEqual(loaded_dt, dt) + + @unittest.skipUnless("America/Los_Angeles" in zoneinfo.available_timezones(), + "Can't find timezone datebase") + def test_dump_aware_datetime_without_aware_datetime_option(self): + dt = datetime.datetime(2345, 6, 7, 8, + tzinfo=zoneinfo.ZoneInfo("America/Los_Angeles")) + s = plistlib.dumps(dt, fmt=plistlib.FMT_XML, aware_datetime=False) + self.assertIn(b"2345-06-07T08:00:00Z", s) + + def test_dump_utc_aware_datetime_without_aware_datetime_option(self): + dt = datetime.datetime(2345, 6, 7, 8, tzinfo=datetime.UTC) + s = plistlib.dumps(dt, fmt=plistlib.FMT_XML, aware_datetime=False) + self.assertIn(b"2345-06-07T08:00:00Z", s) + + def test_dump_naive_datetime_with_aware_datetime_option(self): + # Save a naive datetime with aware_datetime set to true. This will lead + # to having different time as compared to the current machine's + # timezone, which is UTC. + dt = datetime.datetime(2003, 6, 7, 8, tzinfo=None) + for fmt in ALL_FORMATS: + s = plistlib.dumps(dt, fmt=fmt, aware_datetime=True) + parsed = plistlib.loads(s, aware_datetime=False) + expected = dt.astimezone(datetime.UTC).replace(tzinfo=None) + self.assertEqual(parsed, expected) + class TestBinaryPlistlib(unittest.TestCase): @@ -962,6 +1025,28 @@ def test_invalid_binary(self): with self.assertRaises(plistlib.InvalidFileException): plistlib.loads(b'bplist00' + data, fmt=plistlib.FMT_BINARY) + def test_load_aware_datetime(self): + data = (b'bplist003B\x04>\xd0d\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00' + b'\x01\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00' + b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x11') + self.assertEqual(plistlib.loads(data, aware_datetime=True), + datetime.datetime(2345, 6, 7, 8, tzinfo=datetime.UTC)) + + @unittest.skipUnless("America/Los_Angeles" in zoneinfo.available_timezones(), + "Can't find timezone datebase") + def test_dump_aware_datetime_without_aware_datetime_option(self): + dt = datetime.datetime(2345, 6, 7, 8, + tzinfo=zoneinfo.ZoneInfo("America/Los_Angeles")) + msg = "can't subtract offset-naive and offset-aware datetimes" + with self.assertRaisesRegex(TypeError, msg): + plistlib.dumps(dt, fmt=plistlib.FMT_BINARY, aware_datetime=False) + + def test_dump_utc_aware_datetime_without_aware_datetime_option(self): + dt = datetime.datetime(2345, 6, 7, 8, tzinfo=datetime.UTC) + msg = "can't subtract offset-naive and offset-aware datetimes" + with self.assertRaisesRegex(TypeError, msg): + plistlib.dumps(dt, fmt=plistlib.FMT_BINARY, aware_datetime=False) + class TestKeyedArchive(unittest.TestCase): def test_keyed_archive_data(self): @@ -1072,5 +1157,6 @@ def test_octal_and_hex(self): self.assertEqual(p.get("HexType"), 16777228) self.assertEqual(p.get("IntType"), 83) + if __name__ == '__main__': unittest.main() diff --git a/Lib/test/test_poll.py b/Lib/test/test_poll.py index 02165a0244ddf4..1847ae95db9292 100644 --- a/Lib/test/test_poll.py +++ b/Lib/test/test_poll.py @@ -8,7 +8,7 @@ import time import unittest from test.support import ( - cpython_only, requires_subprocess, requires_working_socket + cpython_only, requires_subprocess, requires_working_socket, requires_resource ) from test.support import threading_helper from test.support.os_helper import TESTFN @@ -124,6 +124,7 @@ def fileno(self): # select(), modified to use poll() instead. @requires_subprocess() + @requires_resource('walltime') def test_poll2(self): cmd = 'for i in 0 1 2 3 4 5 6 7 8 9; do echo testing...; sleep 1; done' proc = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, diff --git a/Lib/test/test_poplib.py b/Lib/test/test_poplib.py index fa41ba0b6e4637..869f9431b928bb 100644 --- a/Lib/test/test_poplib.py +++ b/Lib/test/test_poplib.py @@ -29,8 +29,8 @@ import ssl SUPPORTS_SSL = True - CERTFILE = os.path.join(os.path.dirname(__file__) or os.curdir, "keycert3.pem") - CAFILE = os.path.join(os.path.dirname(__file__) or os.curdir, "pycacert.pem") + CERTFILE = os.path.join(os.path.dirname(__file__) or os.curdir, "certdata", "keycert3.pem") + CAFILE = os.path.join(os.path.dirname(__file__) or os.curdir, "certdata", "pycacert.pem") requires_ssl = skipUnless(SUPPORTS_SSL, 'SSL not supported') diff --git a/Lib/test/test_posix.py b/Lib/test/test_posix.py index 444f8abe4607b7..9c382ace806e0f 100644 --- a/Lib/test/test_posix.py +++ b/Lib/test/test_posix.py @@ -6,9 +6,6 @@ from test.support import warnings_helper from test.support.script_helper import assert_python_ok -# Skip these tests if there is no posix module. -posix = import_helper.import_module('posix') - import errno import sys import signal @@ -22,6 +19,11 @@ import textwrap from contextlib import contextmanager +try: + import posix +except ImportError: + import nt as posix + try: import pwd except ImportError: @@ -789,7 +791,7 @@ def check_stat(uid, gid): self.assertRaises(TypeError, chown_func, first_param, uid, t(gid)) check_stat(uid, gid) - @os_helper.skip_unless_working_chmod + @unittest.skipUnless(hasattr(os, "chown"), "requires os.chown()") @unittest.skipIf(support.is_emscripten, "getgid() is a stub") def test_chown(self): # raise an OSError if the file does not exist @@ -933,6 +935,131 @@ def test_utime(self): posix.utime(os_helper.TESTFN, (int(now), int(now))) posix.utime(os_helper.TESTFN, (now, now)) + def check_chmod(self, chmod_func, target, **kwargs): + closefd = not isinstance(target, int) + mode = os.stat(target).st_mode + try: + new_mode = mode & ~(stat.S_IWOTH | stat.S_IWGRP | stat.S_IWUSR) + chmod_func(target, new_mode, **kwargs) + self.assertEqual(os.stat(target).st_mode, new_mode) + if stat.S_ISREG(mode): + try: + with open(target, 'wb+', closefd=closefd): + pass + except PermissionError: + pass + new_mode = mode | (stat.S_IWOTH | stat.S_IWGRP | stat.S_IWUSR) + chmod_func(target, new_mode, **kwargs) + self.assertEqual(os.stat(target).st_mode, new_mode) + if stat.S_ISREG(mode): + with open(target, 'wb+', closefd=closefd): + pass + finally: + chmod_func(target, mode) + + @os_helper.skip_unless_working_chmod + def test_chmod_file(self): + self.check_chmod(posix.chmod, os_helper.TESTFN) + + def tempdir(self): + target = os_helper.TESTFN + 'd' + posix.mkdir(target) + self.addCleanup(posix.rmdir, target) + return target + + @os_helper.skip_unless_working_chmod + def test_chmod_dir(self): + target = self.tempdir() + self.check_chmod(posix.chmod, target) + + @os_helper.skip_unless_working_chmod + def test_fchmod_file(self): + with open(os_helper.TESTFN, 'wb+') as f: + self.check_chmod(posix.fchmod, f.fileno()) + self.check_chmod(posix.chmod, f.fileno()) + + @unittest.skipUnless(hasattr(posix, 'lchmod'), 'test needs os.lchmod()') + def test_lchmod_file(self): + self.check_chmod(posix.lchmod, os_helper.TESTFN) + self.check_chmod(posix.chmod, os_helper.TESTFN, follow_symlinks=False) + + @unittest.skipUnless(hasattr(posix, 'lchmod'), 'test needs os.lchmod()') + def test_lchmod_dir(self): + target = self.tempdir() + self.check_chmod(posix.lchmod, target) + self.check_chmod(posix.chmod, target, follow_symlinks=False) + + def check_chmod_link(self, chmod_func, target, link, **kwargs): + target_mode = os.stat(target).st_mode + link_mode = os.lstat(link).st_mode + try: + new_mode = target_mode & ~(stat.S_IWOTH | stat.S_IWGRP | stat.S_IWUSR) + chmod_func(link, new_mode, **kwargs) + self.assertEqual(os.stat(target).st_mode, new_mode) + self.assertEqual(os.lstat(link).st_mode, link_mode) + new_mode = target_mode | (stat.S_IWOTH | stat.S_IWGRP | stat.S_IWUSR) + chmod_func(link, new_mode, **kwargs) + self.assertEqual(os.stat(target).st_mode, new_mode) + self.assertEqual(os.lstat(link).st_mode, link_mode) + finally: + posix.chmod(target, target_mode) + + def check_lchmod_link(self, chmod_func, target, link, **kwargs): + target_mode = os.stat(target).st_mode + link_mode = os.lstat(link).st_mode + new_mode = link_mode & ~(stat.S_IWOTH | stat.S_IWGRP | stat.S_IWUSR) + chmod_func(link, new_mode, **kwargs) + self.assertEqual(os.stat(target).st_mode, target_mode) + self.assertEqual(os.lstat(link).st_mode, new_mode) + new_mode = link_mode | (stat.S_IWOTH | stat.S_IWGRP | stat.S_IWUSR) + chmod_func(link, new_mode, **kwargs) + self.assertEqual(os.stat(target).st_mode, target_mode) + self.assertEqual(os.lstat(link).st_mode, new_mode) + + @os_helper.skip_unless_symlink + def test_chmod_file_symlink(self): + target = os_helper.TESTFN + link = os_helper.TESTFN + '-link' + os.symlink(target, link) + self.addCleanup(posix.unlink, link) + if os.name == 'nt': + self.check_lchmod_link(posix.chmod, target, link) + else: + self.check_chmod_link(posix.chmod, target, link) + self.check_chmod_link(posix.chmod, target, link, follow_symlinks=True) + + @os_helper.skip_unless_symlink + def test_chmod_dir_symlink(self): + target = self.tempdir() + link = os_helper.TESTFN + '-link' + os.symlink(target, link, target_is_directory=True) + self.addCleanup(posix.unlink, link) + if os.name == 'nt': + self.check_lchmod_link(posix.chmod, target, link) + else: + self.check_chmod_link(posix.chmod, target, link) + self.check_chmod_link(posix.chmod, target, link, follow_symlinks=True) + + @unittest.skipUnless(hasattr(posix, 'lchmod'), 'test needs os.lchmod()') + @os_helper.skip_unless_symlink + def test_lchmod_file_symlink(self): + target = os_helper.TESTFN + link = os_helper.TESTFN + '-link' + os.symlink(target, link) + self.addCleanup(posix.unlink, link) + self.check_lchmod_link(posix.chmod, target, link, follow_symlinks=False) + self.check_lchmod_link(posix.lchmod, target, link) + + @unittest.skipUnless(hasattr(posix, 'lchmod'), 'test needs os.lchmod()') + @os_helper.skip_unless_symlink + def test_lchmod_dir_symlink(self): + target = self.tempdir() + link = os_helper.TESTFN + '-link' + os.symlink(target, link) + self.addCleanup(posix.unlink, link) + self.check_lchmod_link(posix.chmod, target, link, follow_symlinks=False) + self.check_lchmod_link(posix.lchmod, target, link) + def _test_chflags_regular_file(self, chflags_func, target_file, **kwargs): st = os.stat(target_file) self.assertTrue(hasattr(st, 'st_flags')) @@ -1012,16 +1139,17 @@ def test_environ(self): def test_putenv(self): with self.assertRaises(ValueError): os.putenv('FRUIT\0VEGETABLE', 'cabbage') - with self.assertRaises(ValueError): - os.putenv(b'FRUIT\0VEGETABLE', b'cabbage') with self.assertRaises(ValueError): os.putenv('FRUIT', 'orange\0VEGETABLE=cabbage') - with self.assertRaises(ValueError): - os.putenv(b'FRUIT', b'orange\0VEGETABLE=cabbage') with self.assertRaises(ValueError): os.putenv('FRUIT=ORANGE', 'lemon') - with self.assertRaises(ValueError): - os.putenv(b'FRUIT=ORANGE', b'lemon') + if os.name == 'posix': + with self.assertRaises(ValueError): + os.putenv(b'FRUIT\0VEGETABLE', b'cabbage') + with self.assertRaises(ValueError): + os.putenv(b'FRUIT', b'orange\0VEGETABLE=cabbage') + with self.assertRaises(ValueError): + os.putenv(b'FRUIT=ORANGE', b'lemon') @unittest.skipUnless(hasattr(posix, 'getcwd'), 'test needs posix.getcwd()') def test_getcwd_long_pathnames(self): @@ -1205,6 +1333,7 @@ def test_sched_getaffinity(self): @requires_sched_affinity def test_sched_setaffinity(self): mask = posix.sched_getaffinity(0) + self.addCleanup(posix.sched_setaffinity, 0, list(mask)) if len(mask) > 1: # Empty masks are forbidden mask.pop() @@ -1219,6 +1348,7 @@ def test_sched_setaffinity(self): self.assertRaises(OSError, posix.sched_setaffinity, -1, mask) @unittest.skipIf(support.is_wasi, "No dynamic linking on WASI") + @unittest.skipUnless(os.name == 'posix', "POSIX-only test") def test_rtld_constants(self): # check presence of major RTLD_* constants posix.RTLD_LAZY diff --git a/Lib/test/test_posixpath.py b/Lib/test/test_posixpath.py index 9be4640f970aef..86ce1b1d41ba61 100644 --- a/Lib/test/test_posixpath.py +++ b/Lib/test/test_posixpath.py @@ -47,18 +47,26 @@ def tearDown(self): safe_rmdir(os_helper.TESTFN + suffix) def test_join(self): - self.assertEqual(posixpath.join("/foo", "bar", "/bar", "baz"), - "/bar/baz") - self.assertEqual(posixpath.join("/foo", "bar", "baz"), "/foo/bar/baz") - self.assertEqual(posixpath.join("/foo/", "bar/", "baz/"), - "/foo/bar/baz/") - - self.assertEqual(posixpath.join(b"/foo", b"bar", b"/bar", b"baz"), - b"/bar/baz") - self.assertEqual(posixpath.join(b"/foo", b"bar", b"baz"), - b"/foo/bar/baz") - self.assertEqual(posixpath.join(b"/foo/", b"bar/", b"baz/"), - b"/foo/bar/baz/") + fn = posixpath.join + self.assertEqual(fn("/foo", "bar", "/bar", "baz"), "/bar/baz") + self.assertEqual(fn("/foo", "bar", "baz"), "/foo/bar/baz") + self.assertEqual(fn("/foo/", "bar/", "baz/"), "/foo/bar/baz/") + + self.assertEqual(fn(b"/foo", b"bar", b"/bar", b"baz"), b"/bar/baz") + self.assertEqual(fn(b"/foo", b"bar", b"baz"), b"/foo/bar/baz") + self.assertEqual(fn(b"/foo/", b"bar/", b"baz/"), b"/foo/bar/baz/") + + self.assertEqual(fn("a", "b"), "a/b") + self.assertEqual(fn("a", "b/"), "a/b/") + self.assertEqual(fn("a/", "b"), "a/b") + self.assertEqual(fn("a/", "b/"), "a/b/") + self.assertEqual(fn("a", "b/c", "d"), "a/b/c/d") + self.assertEqual(fn("a", "b//c", "d"), "a/b//c/d") + self.assertEqual(fn("a", "b/c/", "d"), "a/b/c/d") + self.assertEqual(fn("/a", "b"), "/a/b") + self.assertEqual(fn("/a/", "b"), "/a/b") + self.assertEqual(fn("a", "/b", "c"), "/b/c") + self.assertEqual(fn("a", "/b", "/c"), "/c") def test_split(self): self.assertEqual(posixpath.split("/foo/bar"), ("/foo", "bar")) diff --git a/Lib/test/test_pprint.py b/Lib/test/test_pprint.py index 6ea7e7db2ce113..4e6fed1ab969ac 100644 --- a/Lib/test/test_pprint.py +++ b/Lib/test/test_pprint.py @@ -7,8 +7,8 @@ import itertools import pprint import random +import re import test.support -import test.test_set import types import unittest @@ -535,7 +535,10 @@ def test_dataclass_with_repr(self): def test_dataclass_no_repr(self): dc = dataclass3() formatted = pprint.pformat(dc, width=10) - self.assertRegex(formatted, r"") + self.assertRegex( + formatted, + fr"<{re.escape(__name__)}.dataclass3 object at \w+>", + ) def test_recursive_dataclass(self): dc = dataclass4(None) @@ -619,9 +622,6 @@ def test_set_reprs(self): self.assertEqual(pprint.pformat(frozenset3(range(7)), width=20), 'frozenset3({0, 1, 2, 3, 4, 5, 6})') - @unittest.expectedFailure - #See http://bugs.python.org/issue13907 - @test.support.cpython_only def test_set_of_sets_reprs(self): # This test creates a complex arrangement of frozensets and # compares the pretty-printed repr against a string hard-coded in @@ -632,204 +632,106 @@ def test_set_of_sets_reprs(self): # partial ordering (subset relationships), the output of the # list.sort() method is undefined for lists of sets." # - # In a nutshell, the test assumes frozenset({0}) will always - # sort before frozenset({1}), but: - # # >>> frozenset({0}) < frozenset({1}) # False # >>> frozenset({1}) < frozenset({0}) # False # - # Consequently, this test is fragile and - # implementation-dependent. Small changes to Python's sort - # algorithm cause the test to fail when it should pass. - # XXX Or changes to the dictionary implementation... - - cube_repr_tgt = """\ -{frozenset(): frozenset({frozenset({2}), frozenset({0}), frozenset({1})}), - frozenset({0}): frozenset({frozenset(), - frozenset({0, 2}), - frozenset({0, 1})}), - frozenset({1}): frozenset({frozenset(), - frozenset({1, 2}), - frozenset({0, 1})}), - frozenset({2}): frozenset({frozenset(), - frozenset({1, 2}), - frozenset({0, 2})}), - frozenset({1, 2}): frozenset({frozenset({2}), - frozenset({1}), - frozenset({0, 1, 2})}), - frozenset({0, 2}): frozenset({frozenset({2}), - frozenset({0}), - frozenset({0, 1, 2})}), - frozenset({0, 1}): frozenset({frozenset({0}), - frozenset({1}), - frozenset({0, 1, 2})}), - frozenset({0, 1, 2}): frozenset({frozenset({1, 2}), - frozenset({0, 2}), - frozenset({0, 1})})}""" - cube = test.test_set.cube(3) - self.assertEqual(pprint.pformat(cube), cube_repr_tgt) - cubo_repr_tgt = """\ -{frozenset({frozenset({0, 2}), frozenset({0})}): frozenset({frozenset({frozenset({0, - 2}), - frozenset({0, - 1, - 2})}), - frozenset({frozenset({0}), - frozenset({0, - 1})}), - frozenset({frozenset(), - frozenset({0})}), - frozenset({frozenset({2}), - frozenset({0, - 2})})}), - frozenset({frozenset({0, 1}), frozenset({1})}): frozenset({frozenset({frozenset({0, - 1}), - frozenset({0, - 1, - 2})}), - frozenset({frozenset({0}), - frozenset({0, - 1})}), - frozenset({frozenset({1}), - frozenset({1, - 2})}), - frozenset({frozenset(), - frozenset({1})})}), - frozenset({frozenset({1, 2}), frozenset({1})}): frozenset({frozenset({frozenset({1, - 2}), - frozenset({0, - 1, - 2})}), - frozenset({frozenset({2}), - frozenset({1, - 2})}), - frozenset({frozenset(), - frozenset({1})}), - frozenset({frozenset({1}), - frozenset({0, - 1})})}), - frozenset({frozenset({1, 2}), frozenset({2})}): frozenset({frozenset({frozenset({1, - 2}), - frozenset({0, - 1, - 2})}), - frozenset({frozenset({1}), - frozenset({1, - 2})}), - frozenset({frozenset({2}), - frozenset({0, - 2})}), - frozenset({frozenset(), - frozenset({2})})}), - frozenset({frozenset(), frozenset({0})}): frozenset({frozenset({frozenset({0}), - frozenset({0, - 1})}), - frozenset({frozenset({0}), - frozenset({0, - 2})}), - frozenset({frozenset(), - frozenset({1})}), - frozenset({frozenset(), - frozenset({2})})}), - frozenset({frozenset(), frozenset({1})}): frozenset({frozenset({frozenset(), - frozenset({0})}), - frozenset({frozenset({1}), - frozenset({1, - 2})}), - frozenset({frozenset(), - frozenset({2})}), - frozenset({frozenset({1}), - frozenset({0, - 1})})}), - frozenset({frozenset({2}), frozenset()}): frozenset({frozenset({frozenset({2}), - frozenset({1, - 2})}), - frozenset({frozenset(), - frozenset({0})}), - frozenset({frozenset(), - frozenset({1})}), - frozenset({frozenset({2}), - frozenset({0, - 2})})}), - frozenset({frozenset({0, 1, 2}), frozenset({0, 1})}): frozenset({frozenset({frozenset({1, - 2}), - frozenset({0, - 1, - 2})}), - frozenset({frozenset({0, - 2}), - frozenset({0, - 1, - 2})}), - frozenset({frozenset({0}), - frozenset({0, - 1})}), - frozenset({frozenset({1}), - frozenset({0, - 1})})}), - frozenset({frozenset({0}), frozenset({0, 1})}): frozenset({frozenset({frozenset(), - frozenset({0})}), - frozenset({frozenset({0, - 1}), - frozenset({0, - 1, - 2})}), - frozenset({frozenset({0}), - frozenset({0, - 2})}), - frozenset({frozenset({1}), - frozenset({0, - 1})})}), - frozenset({frozenset({2}), frozenset({0, 2})}): frozenset({frozenset({frozenset({0, - 2}), - frozenset({0, - 1, - 2})}), - frozenset({frozenset({2}), - frozenset({1, - 2})}), - frozenset({frozenset({0}), - frozenset({0, - 2})}), - frozenset({frozenset(), - frozenset({2})})}), - frozenset({frozenset({0, 1, 2}), frozenset({0, 2})}): frozenset({frozenset({frozenset({1, - 2}), - frozenset({0, - 1, - 2})}), - frozenset({frozenset({0, - 1}), - frozenset({0, - 1, - 2})}), - frozenset({frozenset({0}), - frozenset({0, - 2})}), - frozenset({frozenset({2}), - frozenset({0, - 2})})}), - frozenset({frozenset({1, 2}), frozenset({0, 1, 2})}): frozenset({frozenset({frozenset({0, - 2}), - frozenset({0, - 1, - 2})}), - frozenset({frozenset({0, - 1}), - frozenset({0, - 1, - 2})}), - frozenset({frozenset({2}), - frozenset({1, - 2})}), - frozenset({frozenset({1}), - frozenset({1, - 2})})})}""" - - cubo = test.test_set.linegraph(cube) - self.assertEqual(pprint.pformat(cubo), cubo_repr_tgt) + # In this test we list all possible invariants of the result + # for unordered frozensets. + # + # This test has a long history, see: + # - https://github.com/python/cpython/commit/969fe57baa0eb80332990f9cda936a33e13fabef + # - https://github.com/python/cpython/issues/58115 + # - https://github.com/python/cpython/issues/111147 + + import textwrap + + # Single-line, always ordered: + fs0 = frozenset() + fs1 = frozenset(('abc', 'xyz')) + data = frozenset((fs0, fs1)) + self.assertEqual(pprint.pformat(data), + 'frozenset({%r, %r})' % (fs0, fs1)) + self.assertEqual(pprint.pformat(data), repr(data)) + + fs2 = frozenset(('one', 'two')) + data = {fs2: frozenset((fs0, fs1))} + self.assertEqual(pprint.pformat(data), + "{%r: frozenset({%r, %r})}" % (fs2, fs0, fs1)) + self.assertEqual(pprint.pformat(data), repr(data)) + + # Single-line, unordered: + fs1 = frozenset(("xyz", "qwerty")) + fs2 = frozenset(("abcd", "spam")) + fs = frozenset((fs1, fs2)) + self.assertEqual(pprint.pformat(fs), repr(fs)) + + # Multiline, unordered: + def check(res, invariants): + self.assertIn(res, [textwrap.dedent(i).strip() for i in invariants]) + + # Inner-most frozensets are singleline, result is multiline, unordered: + fs1 = frozenset(('regular string', 'other string')) + fs2 = frozenset(('third string', 'one more string')) + check( + pprint.pformat(frozenset((fs1, fs2))), + [ + """ + frozenset({%r, + %r}) + """ % (fs1, fs2), + """ + frozenset({%r, + %r}) + """ % (fs2, fs1), + ], + ) + + # Everything is multiline, unordered: + check( + pprint.pformat( + frozenset(( + frozenset(( + "xyz very-very long string", + "qwerty is also absurdly long", + )), + frozenset(( + "abcd is even longer that before", + "spam is not so long", + )), + )), + ), + [ + """ + frozenset({frozenset({'abcd is even longer that before', + 'spam is not so long'}), + frozenset({'qwerty is also absurdly long', + 'xyz very-very long string'})}) + """, + + """ + frozenset({frozenset({'abcd is even longer that before', + 'spam is not so long'}), + frozenset({'xyz very-very long string', + 'qwerty is also absurdly long'})}) + """, + + """ + frozenset({frozenset({'qwerty is also absurdly long', + 'xyz very-very long string'}), + frozenset({'abcd is even longer that before', + 'spam is not so long'})}) + """, + + """ + frozenset({frozenset({'qwerty is also absurdly long', + 'xyz very-very long string'}), + frozenset({'spam is not so long', + 'abcd is even longer that before'})}) + """, + ], + ) def test_depth(self): nested_tuple = (1, (2, (3, (4, (5, 6))))) diff --git a/Lib/test/test_property.py b/Lib/test/test_property.py index 45aa9e51c06de0..c12c908d2ee32d 100644 --- a/Lib/test/test_property.py +++ b/Lib/test/test_property.py @@ -183,27 +183,6 @@ def test_refleaks_in___init__(self): fake_prop.__init__('fget', 'fset', 'fdel', 'doc') self.assertAlmostEqual(gettotalrefcount() - refs_before, 0, delta=10) - @unittest.skipIf(sys.flags.optimize >= 2, - "Docstrings are omitted with -O2 and above") - def test_class_property(self): - class A: - @classmethod - @property - def __doc__(cls): - return 'A doc for %r' % cls.__name__ - self.assertEqual(A.__doc__, "A doc for 'A'") - - @unittest.skipIf(sys.flags.optimize >= 2, - "Docstrings are omitted with -O2 and above") - def test_class_property_override(self): - class A: - """First""" - @classmethod - @property - def __doc__(cls): - return 'Second' - self.assertEqual(A.__doc__, 'Second') - def test_property_set_name_incorrect_args(self): p = property() diff --git a/Lib/test/test_pstats.py b/Lib/test/test_pstats.py index acc2fa5385d923..d5a5a9738c2498 100644 --- a/Lib/test/test_pstats.py +++ b/Lib/test/test_pstats.py @@ -5,7 +5,9 @@ from pstats import SortKey from enum import StrEnum, _test_simple_enum +import os import pstats +import tempfile import cProfile class AddCallersTestCase(unittest.TestCase): @@ -36,6 +38,33 @@ def test_add(self): stats = pstats.Stats(stream=stream) stats.add(self.stats, self.stats) + def test_dump_and_load_works_correctly(self): + temp_storage_new = tempfile.NamedTemporaryFile(delete=False) + try: + self.stats.dump_stats(filename=temp_storage_new.name) + tmp_stats = pstats.Stats(temp_storage_new.name) + self.assertEqual(self.stats.stats, tmp_stats.stats) + finally: + temp_storage_new.close() + os.remove(temp_storage_new.name) + + def test_load_equivalent_to_init(self): + stats = pstats.Stats() + self.temp_storage = tempfile.NamedTemporaryFile(delete=False) + try: + cProfile.run('import os', filename=self.temp_storage.name) + stats.load_stats(self.temp_storage.name) + created = pstats.Stats(self.temp_storage.name) + self.assertEqual(stats.stats, created.stats) + finally: + self.temp_storage.close() + os.remove(self.temp_storage.name) + + def test_loading_wrong_types(self): + stats = pstats.Stats() + with self.assertRaises(TypeError): + stats.load_stats(42) + def test_sort_stats_int(self): valid_args = {-1: 'stdname', 0: 'calls', diff --git a/Lib/test/test_pty.py b/Lib/test/test_pty.py index c9c2b42861c6f4..f31a68c5d84e03 100644 --- a/Lib/test/test_pty.py +++ b/Lib/test/test_pty.py @@ -76,21 +76,22 @@ def expectedFailureIfStdinIsTTY(fun): pass return fun + +def write_all(fd, data): + written = os.write(fd, data) + if written != len(data): + # gh-73256, gh-110673: It should never happen, but check just in case + raise Exception(f"short write: os.write({fd}, {len(data)} bytes) " + f"wrote {written} bytes") + + # Marginal testing of pty suite. Cannot do extensive 'do or fail' testing # because pty code is not too portable. class PtyTest(unittest.TestCase): def setUp(self): - old_alarm = signal.signal(signal.SIGALRM, self.handle_sig) - self.addCleanup(signal.signal, signal.SIGALRM, old_alarm) - old_sighup = signal.signal(signal.SIGHUP, self.handle_sighup) self.addCleanup(signal.signal, signal.SIGHUP, old_sighup) - # isatty() and close() can hang on some platforms. Set an alarm - # before running the test to make sure we don't hang forever. - self.addCleanup(signal.alarm, 0) - signal.alarm(10) - # Save original stdin window size. self.stdin_dim = None if _HAVE_WINSZ: @@ -101,9 +102,6 @@ def setUp(self): except tty.error: pass - def handle_sig(self, sig, frame): - self.fail("isatty hung") - @staticmethod def handle_sighup(signum, frame): pass @@ -181,14 +179,14 @@ def test_openpty(self): os.set_blocking(master_fd, blocking) debug("Writing to slave_fd") - os.write(slave_fd, TEST_STRING_1) + write_all(slave_fd, TEST_STRING_1) s1 = _readline(master_fd) self.assertEqual(b'I wish to buy a fish license.\n', normalize_output(s1)) debug("Writing chunked output") - os.write(slave_fd, TEST_STRING_2[:5]) - os.write(slave_fd, TEST_STRING_2[5:]) + write_all(slave_fd, TEST_STRING_2[:5]) + write_all(slave_fd, TEST_STRING_2[5:]) s2 = _readline(master_fd) self.assertEqual(b'For my pet fish, Eric.\n', normalize_output(s2)) @@ -371,8 +369,8 @@ def test__copy_to_each(self): masters = [s.fileno() for s in socketpair] # Feed data. Smaller than PIPEBUF. These writes will not block. - os.write(masters[1], b'from master') - os.write(write_to_stdin_fd, b'from stdin') + write_all(masters[1], b'from master') + write_all(write_to_stdin_fd, b'from stdin') # Expect three select calls, the last one will cause IndexError pty.select = self._mock_select diff --git a/Lib/test/test_py_compile.py b/Lib/test/test_py_compile.py index 5e0a44ad9691ec..c4e6551f605782 100644 --- a/Lib/test/test_py_compile.py +++ b/Lib/test/test_py_compile.py @@ -132,7 +132,9 @@ def test_exceptions_propagate(self): os.chmod(self.directory, mode.st_mode) def test_bad_coding(self): - bad_coding = os.path.join(os.path.dirname(__file__), 'bad_coding2.py') + bad_coding = os.path.join(os.path.dirname(__file__), + 'tokenizedata', + 'bad_coding2.py') with support.captured_stderr(): self.assertIsNone(py_compile.compile(bad_coding, doraise=False)) self.assertFalse(os.path.exists( @@ -195,7 +197,9 @@ def test_invalidation_mode(self): self.assertEqual(flags, 0b1) def test_quiet(self): - bad_coding = os.path.join(os.path.dirname(__file__), 'bad_coding2.py') + bad_coding = os.path.join(os.path.dirname(__file__), + 'tokenizedata', + 'bad_coding2.py') with support.captured_stderr() as stderr: self.assertIsNone(py_compile.compile(bad_coding, doraise=False, quiet=2)) self.assertIsNone(py_compile.compile(bad_coding, doraise=True, quiet=2)) @@ -260,14 +264,18 @@ def test_with_files(self): self.assertTrue(os.path.exists(self.cache_path)) def test_bad_syntax(self): - bad_syntax = os.path.join(os.path.dirname(__file__), 'badsyntax_3131.py') + bad_syntax = os.path.join(os.path.dirname(__file__), + 'tokenizedata', + 'badsyntax_3131.py') rc, stdout, stderr = self.pycompilecmd_failure(bad_syntax) self.assertEqual(rc, 1) self.assertEqual(stdout, b'') self.assertIn(b'SyntaxError', stderr) def test_bad_syntax_with_quiet(self): - bad_syntax = os.path.join(os.path.dirname(__file__), 'badsyntax_3131.py') + bad_syntax = os.path.join(os.path.dirname(__file__), + 'tokenizedata', + 'badsyntax_3131.py') rc, stdout, stderr = self.pycompilecmd_failure('-q', bad_syntax) self.assertEqual(rc, 1) self.assertEqual(stdout, b'') diff --git a/Lib/test/test_pydoc.py b/Lib/test/test_pydoc.py index ddb5187f90da9b..99b19d01783a10 100644 --- a/Lib/test/test_pydoc.py +++ b/Lib/test/test_pydoc.py @@ -1,3 +1,4 @@ +import datetime import os import sys import contextlib @@ -12,6 +13,7 @@ import stat import tempfile import test.support +import time import types import typing import unittest @@ -22,6 +24,7 @@ from io import StringIO from collections import namedtuple from urllib.request import urlopen, urlcleanup +from test import support from test.support import import_helper from test.support import os_helper from test.support.script_helper import (assert_python_ok, @@ -29,7 +32,7 @@ from test.support import threading_helper from test.support import (reap_children, captured_output, captured_stdout, captured_stderr, is_emscripten, is_wasi, - requires_docstrings) + requires_docstrings, MISSING_C_DOCSTRINGS) from test.support.os_helper import (TESTFN, rmtree, unlink) from test import pydoc_mod @@ -40,8 +43,8 @@ class nonascii: if test.support.HAVE_DOCSTRINGS: expected_data_docstrings = ( - 'dictionary for instance variables (if defined)', - 'list of weak references to the object (if defined)', + 'dictionary for instance variables', + 'list of weak references to the object', ) * 2 else: expected_data_docstrings = ('', '', '', '') @@ -105,10 +108,10 @@ class C(builtins.object) | Data descriptors defined here: | | __dict__ - | dictionary for instance variables (if defined) + | dictionary for instance variables | | __weakref__ - | list of weak references to the object (if defined) + | list of weak references to the object FUNCTIONS doc_func() @@ -166,16 +169,16 @@ class A(builtins.object) Data descriptors defined here: __dict__ - dictionary for instance variables (if defined) + dictionary for instance variables __weakref__ - list of weak references to the object (if defined) + list of weak references to the object class B(builtins.object) Data descriptors defined here: __dict__ - dictionary for instance variables (if defined) + dictionary for instance variables __weakref__ - list of weak references to the object (if defined) + list of weak references to the object Data and other attributes defined here: NO_MEANING = 'eggs' __annotations__ = {'NO_MEANING': } @@ -192,9 +195,9 @@ class C(builtins.object) __class_getitem__(item) from builtins.type Data descriptors defined here: __dict__ - dictionary for instance variables (if defined) + dictionary for instance variables __weakref__ - list of weak references to the object (if defined) + list of weak references to the object Functions doc_func() @@ -742,14 +745,18 @@ def test_splitdoc_with_description(self): def test_is_package_when_not_package(self): with os_helper.temp_cwd() as test_dir: - self.assertFalse(pydoc.ispackage(test_dir)) + with self.assertWarns(DeprecationWarning) as cm: + self.assertFalse(pydoc.ispackage(test_dir)) + self.assertEqual(cm.filename, __file__) def test_is_package_when_is_package(self): with os_helper.temp_cwd() as test_dir: init_path = os.path.join(test_dir, '__init__.py') open(init_path, 'w').close() - self.assertTrue(pydoc.ispackage(test_dir)) + with self.assertWarns(DeprecationWarning) as cm: + self.assertTrue(pydoc.ispackage(test_dir)) os.remove(init_path) + self.assertEqual(cm.filename, __file__) def test_allmethods(self): # issue 17476: allmethods was no longer returning unbound methods. @@ -826,10 +833,10 @@ class B(A) | Data descriptors inherited from A: | | __dict__ - | dictionary for instance variables (if defined) + | dictionary for instance variables | | __weakref__ - | list of weak references to the object (if defined) + | list of weak references to the object ''' % __name__) doc = pydoc.render_doc(B, renderer=pydoc.HTMLDoc()) @@ -858,15 +865,105 @@ class B(A) Data descriptors inherited from A: __dict__ - dictionary for instance variables (if defined) + dictionary for instance variables __weakref__ - list of weak references to the object (if defined) + list of weak references to the object """ as_text = html2text(doc) expected_lines = [line.strip() for line in expected_text.split("\n") if line] for expected_line in expected_lines: self.assertIn(expected_line, as_text) + def test_long_signatures(self): + from collections.abc import Callable + from typing import Literal, Annotated + + class A: + def __init__(self, + arg1: Callable[[int, int, int], str], + arg2: Literal['some value', 'other value'], + arg3: Annotated[int, 'some docs about this type'], + ) -> None: + ... + + doc = pydoc.render_doc(A) + # clean up the extra text formatting that pydoc performs + doc = re.sub('\b.', '', doc) + self.assertEqual(doc, '''Python Library Documentation: class A in module %s + +class A(builtins.object) + | A( + | arg1: collections.abc.Callable[[int, int, int], str], + | arg2: Literal['some value', 'other value'], + | arg3: Annotated[int, 'some docs about this type'] + | ) -> None + | + | Methods defined here: + | + | __init__( + | self, + | arg1: collections.abc.Callable[[int, int, int], str], + | arg2: Literal['some value', 'other value'], + | arg3: Annotated[int, 'some docs about this type'] + | ) -> None + | + | ---------------------------------------------------------------------- + | Data descriptors defined here: + | + | __dict__%s + | + | __weakref__%s +''' % (__name__, + '' if MISSING_C_DOCSTRINGS else '\n | dictionary for instance variables', + '' if MISSING_C_DOCSTRINGS else '\n | list of weak references to the object', + )) + + def func( + arg1: Callable[[Annotated[int, 'Some doc']], str], + arg2: Literal[1, 2, 3, 4, 5, 6, 7, 8], + ) -> Annotated[int, 'Some other']: + ... + + doc = pydoc.render_doc(func) + # clean up the extra text formatting that pydoc performs + doc = re.sub('\b.', '', doc) + self.assertEqual(doc, '''Python Library Documentation: function func in module %s + +func( + arg1: collections.abc.Callable[[typing.Annotated[int, 'Some doc']], str], + arg2: Literal[1, 2, 3, 4, 5, 6, 7, 8] +) -> Annotated[int, 'Some other'] +''' % __name__) + + def function_with_really_long_name_so_annotations_can_be_rather_small( + arg1: int, + arg2: str, + ): + ... + + doc = pydoc.render_doc(function_with_really_long_name_so_annotations_can_be_rather_small) + # clean up the extra text formatting that pydoc performs + doc = re.sub('\b.', '', doc) + self.assertEqual(doc, '''Python Library Documentation: function function_with_really_long_name_so_annotations_can_be_rather_small in module %s + +function_with_really_long_name_so_annotations_can_be_rather_small( + arg1: int, + arg2: str +) +''' % __name__) + + does_not_have_name = lambda \ + very_long_parameter_name_that_should_not_fit_into_a_single_line, \ + second_very_long_parameter_name: ... + + doc = pydoc.render_doc(does_not_have_name) + # clean up the extra text formatting that pydoc performs + doc = re.sub('\b.', '', doc) + self.assertEqual(doc, '''Python Library Documentation: function in module %s + + lambda very_long_parameter_name_that_should_not_fit_into_a_single_line, second_very_long_parameter_name +''' % __name__) + def test__future__imports(self): # __future__ features are excluded from module help, # except when it's the __future__ module itself @@ -1062,13 +1159,15 @@ def test_generic_alias(self): doc = pydoc.render_doc(typing.List[int], renderer=pydoc.plaintext) self.assertIn('_GenericAlias in module typing', doc) self.assertIn('List = class list(object)', doc) - self.assertIn(list.__doc__.strip().splitlines()[0], doc) + if not MISSING_C_DOCSTRINGS: + self.assertIn(list.__doc__.strip().splitlines()[0], doc) self.assertEqual(pydoc.describe(list[int]), 'GenericAlias') doc = pydoc.render_doc(list[int], renderer=pydoc.plaintext) self.assertIn('GenericAlias in module builtins', doc) self.assertIn('\nclass list(object)', doc) - self.assertIn(list.__doc__.strip().splitlines()[0], doc) + if not MISSING_C_DOCSTRINGS: + self.assertIn(list.__doc__.strip().splitlines()[0], doc) def test_union_type(self): self.assertEqual(pydoc.describe(typing.Union[int, str]), '_UnionGenericAlias') @@ -1082,7 +1181,8 @@ def test_union_type(self): doc = pydoc.render_doc(int | str, renderer=pydoc.plaintext) self.assertIn('UnionType in module types object', doc) self.assertIn('\nclass UnionType(builtins.object)', doc) - self.assertIn(types.UnionType.__doc__.strip().splitlines()[0], doc) + if not MISSING_C_DOCSTRINGS: + self.assertIn(types.UnionType.__doc__.strip().splitlines()[0], doc) def test_special_form(self): self.assertEqual(pydoc.describe(typing.NoReturn), '_SpecialForm') @@ -1180,6 +1280,154 @@ def test_module_level_callable(self): self.assertEqual(self._get_summary_line(os.stat), "stat(path, *, dir_fd=None, follow_symlinks=True)") + def test_module_level_callable_noargs(self): + self.assertEqual(self._get_summary_line(time.time), + "time()") + + def test_module_level_callable_o(self): + try: + import _stat + except ImportError: + # stat.S_IMODE() and _stat.S_IMODE() have a different signature + self.skipTest('_stat extension is missing') + + self.assertEqual(self._get_summary_line(_stat.S_IMODE), + "S_IMODE(object, /)") + + def test_unbound_builtin_method_noargs(self): + self.assertEqual(self._get_summary_line(str.lower), + "lower(self, /)") + + def test_bound_builtin_method_noargs(self): + self.assertEqual(self._get_summary_line(''.lower), + "lower() method of builtins.str instance") + + def test_unbound_builtin_method_o(self): + self.assertEqual(self._get_summary_line(set.add), + "add(self, object, /)") + + def test_bound_builtin_method_o(self): + self.assertEqual(self._get_summary_line(set().add), + "add(object, /) method of builtins.set instance") + + def test_unbound_builtin_method_coexist_o(self): + self.assertEqual(self._get_summary_line(set.__contains__), + "__contains__(self, object, /)") + + def test_bound_builtin_method_coexist_o(self): + self.assertEqual(self._get_summary_line(set().__contains__), + "__contains__(object, /) method of builtins.set instance") + + def test_unbound_builtin_classmethod_noargs(self): + self.assertEqual(self._get_summary_line(datetime.datetime.__dict__['utcnow']), + "utcnow(type, /)") + + def test_bound_builtin_classmethod_noargs(self): + self.assertEqual(self._get_summary_line(datetime.datetime.utcnow), + "utcnow() method of builtins.type instance") + + def test_unbound_builtin_classmethod_o(self): + self.assertEqual(self._get_summary_line(dict.__dict__['__class_getitem__']), + "__class_getitem__(type, object, /)") + + def test_bound_builtin_classmethod_o(self): + self.assertEqual(self._get_summary_line(dict.__class_getitem__), + "__class_getitem__(object, /) method of builtins.type instance") + + @support.cpython_only + @requires_docstrings + def test_module_level_callable_unrepresentable_default(self): + import _testcapi + builtin = _testcapi.func_with_unrepresentable_signature + self.assertEqual(self._get_summary_line(builtin), + "func_with_unrepresentable_signature(a, b=)") + + @support.cpython_only + @requires_docstrings + def test_builtin_staticmethod_unrepresentable_default(self): + self.assertEqual(self._get_summary_line(str.maketrans), + "maketrans(x, y=, z=, /)") + import _testcapi + cls = _testcapi.DocStringUnrepresentableSignatureTest + self.assertEqual(self._get_summary_line(cls.staticmeth), + "staticmeth(a, b=)") + + @support.cpython_only + @requires_docstrings + def test_unbound_builtin_method_unrepresentable_default(self): + self.assertEqual(self._get_summary_line(dict.pop), + "pop(self, key, default=, /)") + import _testcapi + cls = _testcapi.DocStringUnrepresentableSignatureTest + self.assertEqual(self._get_summary_line(cls.meth), + "meth(self, /, a, b=)") + + @support.cpython_only + @requires_docstrings + def test_bound_builtin_method_unrepresentable_default(self): + self.assertEqual(self._get_summary_line({}.pop), + "pop(key, default=, /) " + "method of builtins.dict instance") + import _testcapi + obj = _testcapi.DocStringUnrepresentableSignatureTest() + self.assertEqual(self._get_summary_line(obj.meth), + "meth(a, b=) " + "method of _testcapi.DocStringUnrepresentableSignatureTest instance") + + @support.cpython_only + @requires_docstrings + def test_unbound_builtin_classmethod_unrepresentable_default(self): + import _testcapi + cls = _testcapi.DocStringUnrepresentableSignatureTest + descr = cls.__dict__['classmeth'] + self.assertEqual(self._get_summary_line(descr), + "classmeth(type, /, a, b=)") + + @support.cpython_only + @requires_docstrings + def test_bound_builtin_classmethod_unrepresentable_default(self): + import _testcapi + cls = _testcapi.DocStringUnrepresentableSignatureTest + self.assertEqual(self._get_summary_line(cls.classmeth), + "classmeth(a, b=) method of builtins.type instance") + + def test_overridden_text_signature(self): + class C: + def meth(*args, **kwargs): + pass + @classmethod + def cmeth(*args, **kwargs): + pass + @staticmethod + def smeth(*args, **kwargs): + pass + for text_signature, unbound, bound in [ + ("($slf)", "(slf, /)", "()"), + ("($slf, /)", "(slf, /)", "()"), + ("($slf, /, arg)", "(slf, /, arg)", "(arg)"), + ("($slf, /, arg=)", "(slf, /, arg=)", "(arg=)"), + ("($slf, arg, /)", "(slf, arg, /)", "(arg, /)"), + ("($slf, arg=, /)", "(slf, arg=, /)", "(arg=, /)"), + ("(/, slf, arg)", "(/, slf, arg)", "(/, slf, arg)"), + ("(/, slf, arg=)", "(/, slf, arg=)", "(/, slf, arg=)"), + ("(slf, /, arg)", "(slf, /, arg)", "(arg)"), + ("(slf, /, arg=)", "(slf, /, arg=)", "(arg=)"), + ("(slf, arg, /)", "(slf, arg, /)", "(arg, /)"), + ("(slf, arg=, /)", "(slf, arg=, /)", "(arg=, /)"), + ]: + with self.subTest(text_signature): + C.meth.__text_signature__ = text_signature + self.assertEqual(self._get_summary_line(C.meth), + "meth" + unbound) + self.assertEqual(self._get_summary_line(C().meth), + "meth" + bound + " method of test.test_pydoc.C instance") + C.cmeth.__func__.__text_signature__ = text_signature + self.assertEqual(self._get_summary_line(C.cmeth), + "cmeth" + bound + " method of builtins.type instance") + C.smeth.__text_signature__ = text_signature + self.assertEqual(self._get_summary_line(C.smeth), + "smeth" + unbound) + @requires_docstrings def test_staticmethod(self): class X: diff --git a/Lib/test/test_pyexpat.py b/Lib/test/test_pyexpat.py index 863c1194672c1c..d941a1a8f9ebc6 100644 --- a/Lib/test/test_pyexpat.py +++ b/Lib/test/test_pyexpat.py @@ -1,18 +1,19 @@ # XXX TypeErrors on calling handlers, or on bad return values from a # handler, are obscure and unhelpful. -from io import BytesIO import os -import platform import sys import sysconfig import unittest import traceback +from io import BytesIO +from test import support +from test.support import os_helper from xml.parsers import expat from xml.parsers.expat import errors -from test.support import sortdict, is_emscripten, is_wasi +from test.support import sortdict class SetAttributeTest(unittest.TestCase): @@ -281,12 +282,10 @@ def test_legal(self): expat.ParserCreate(namespace_separator=' ') def test_illegal(self): - try: + with self.assertRaisesRegex(TypeError, + r"ParserCreate\(\) argument (2|'namespace_separator') " + r"must be str or None, not int"): expat.ParserCreate(namespace_separator=42) - self.fail() - except TypeError as e: - self.assertEqual(str(e), - "ParserCreate() argument 'namespace_separator' must be str or None, not int") try: expat.ParserCreate(namespace_separator='too long') @@ -441,37 +440,59 @@ def test7(self): # Test handling of exception from callback: class HandlerExceptionTest(unittest.TestCase): def StartElementHandler(self, name, attrs): - raise RuntimeError(name) + raise RuntimeError(f'StartElementHandler: <{name}>') def check_traceback_entry(self, entry, filename, funcname): - self.assertEqual(os.path.basename(entry[0]), filename) - self.assertEqual(entry[2], funcname) + self.assertEqual(os.path.basename(entry.filename), filename) + self.assertEqual(entry.name, funcname) + @support.cpython_only def test_exception(self): + # gh-66652: test _PyTraceback_Add() used by pyexpat.c to inject frames + + # Change the current directory to the Python source code directory + # if it is available. + src_dir = sysconfig.get_config_var('abs_builddir') + if src_dir: + have_source = os.path.isdir(src_dir) + else: + have_source = False + if have_source: + with os_helper.change_cwd(src_dir): + self._test_exception(have_source) + else: + self._test_exception(have_source) + + def _test_exception(self, have_source): + # Use path relative to the current directory which should be the Python + # source code directory (if it is available). + PYEXPAT_C = os.path.join('Modules', 'pyexpat.c') + parser = expat.ParserCreate() parser.StartElementHandler = self.StartElementHandler try: parser.Parse(b"", True) - self.fail() - except RuntimeError as e: - self.assertEqual(e.args[0], 'a', - "Expected RuntimeError for element 'a', but" + \ - " found %r" % e.args[0]) - # Check that the traceback contains the relevant line in pyexpat.c - entries = traceback.extract_tb(e.__traceback__) - self.assertEqual(len(entries), 3) - self.check_traceback_entry(entries[0], - "test_pyexpat.py", "test_exception") - self.check_traceback_entry(entries[1], - "pyexpat.c", "StartElement") - self.check_traceback_entry(entries[2], - "test_pyexpat.py", "StartElementHandler") - if (sysconfig.is_python_build() - and not (sys.platform == 'win32' and platform.machine() == 'ARM') - and not is_emscripten - and not is_wasi - ): - self.assertIn('call_with_frame("StartElement"', entries[1][3]) + + self.fail("the parser did not raise RuntimeError") + except RuntimeError as exc: + self.assertEqual(exc.args[0], 'StartElementHandler: ', exc) + entries = traceback.extract_tb(exc.__traceback__) + + self.assertEqual(len(entries), 3, entries) + self.check_traceback_entry(entries[0], + "test_pyexpat.py", "_test_exception") + self.check_traceback_entry(entries[1], + os.path.basename(PYEXPAT_C), + "StartElement") + self.check_traceback_entry(entries[2], + "test_pyexpat.py", "StartElementHandler") + + # Check that the traceback contains the relevant line in + # Modules/pyexpat.c. Skip the test if Modules/pyexpat.c is not + # available. + if have_source and os.path.exists(PYEXPAT_C): + self.assertIn('call_with_frame("StartElement"', + entries[1].line) # Test Current* members: @@ -523,7 +544,7 @@ def handler(text): parser = expat.ParserCreate() parser.CharacterDataHandler = handler - self.assertRaises(Exception, parser.Parse, xml.encode('iso8859')) + self.assertRaises(SpecificException, parser.Parse, xml.encode('iso8859')) class ChardataBufferTest(unittest.TestCase): """ diff --git a/Lib/test/test_raise.py b/Lib/test/test_raise.py index 5936d7535edd5f..6d26a61bee4292 100644 --- a/Lib/test/test_raise.py +++ b/Lib/test/test_raise.py @@ -185,6 +185,20 @@ def test_class_cause(self): else: self.fail("No exception raised") + def test_class_cause_nonexception_result(self): + class ConstructsNone(BaseException): + @classmethod + def __new__(*args, **kwargs): + return None + try: + raise IndexError from ConstructsNone + except TypeError as e: + self.assertIn("should have returned an instance of BaseException", str(e)) + except IndexError: + self.fail("Wrong kind of exception raised") + else: + self.fail("No exception raised") + def test_instance_cause(self): cause = KeyError() try: diff --git a/Lib/test/test_random.py b/Lib/test/test_random.py index 50bea7be6d54c7..b1e4ef4197d130 100644 --- a/Lib/test/test_random.py +++ b/Lib/test/test_random.py @@ -1081,6 +1081,7 @@ def test_binomialvariate(self): B(n=1, p=-0.5) # Negative p with self.assertRaises(ValueError): B(n=1, p=1.5) # p > 1.0 + self.assertEqual(B(0, 0.5), 0) # n == 0 self.assertEqual(B(10, 0.0), 0) # p == 0.0 self.assertEqual(B(10, 1.0), 10) # p == 1.0 self.assertTrue(B(1, 0.3) in {0, 1}) # n == 1 fast path @@ -1088,6 +1089,9 @@ def test_binomialvariate(self): self.assertTrue(B(1, 0.0) in {0}) # n == 1 fast path self.assertTrue(B(1, 1.0) in {1}) # n == 1 fast path + # BG method very small p + self.assertEqual(B(5, 1e-18), 0) + # BG method p <= 0.5 and n*p=1.25 self.assertTrue(B(5, 0.25) in set(range(6))) diff --git a/Lib/test/test_re.py b/Lib/test/test_re.py index a6f5af17d7d51b..993a7d6e264a1f 100644 --- a/Lib/test/test_re.py +++ b/Lib/test/test_re.py @@ -47,7 +47,7 @@ def recurse(actual, expect): recurse(actual, expect) def checkPatternError(self, pattern, errmsg, pos=None): - with self.assertRaises(re.error) as cm: + with self.assertRaises(re.PatternError) as cm: re.compile(pattern) with self.subTest(pattern=pattern): err = cm.exception @@ -56,7 +56,7 @@ def checkPatternError(self, pattern, errmsg, pos=None): self.assertEqual(err.pos, pos) def checkTemplateError(self, pattern, repl, string, errmsg, pos=None): - with self.assertRaises(re.error) as cm: + with self.assertRaises(re.PatternError) as cm: re.sub(pattern, repl, string) with self.subTest(pattern=pattern, repl=repl): err = cm.exception @@ -64,6 +64,9 @@ def checkTemplateError(self, pattern, repl, string, errmsg, pos=None): if pos is not None: self.assertEqual(err.pos, pos) + def test_error_is_PatternError_alias(self): + assert re.error is re.PatternError + def test_keep_buffer(self): # See bug 14212 b = bytearray(b'x') @@ -127,8 +130,10 @@ def test_basic_re_sub(self): self.assertEqual(re.sub("(?i)b+", "x", "bbbb BBBB"), 'x x') self.assertEqual(re.sub(r'\d+', self.bump_num, '08.2 -2 23x99y'), '9.3 -3 24x100y') - self.assertEqual(re.sub(r'\d+', self.bump_num, '08.2 -2 23x99y', 3), - '9.3 -3 23x99y') + with self.assertWarns(DeprecationWarning) as w: + self.assertEqual(re.sub(r'\d+', self.bump_num, '08.2 -2 23x99y', 3), + '9.3 -3 23x99y') + self.assertEqual(w.filename, __file__) self.assertEqual(re.sub(r'\d+', self.bump_num, '08.2 -2 23x99y', count=3), '9.3 -3 23x99y') @@ -152,7 +157,7 @@ def test_basic_re_sub(self): (chr(9)+chr(10)+chr(11)+chr(13)+chr(12)+chr(7)+chr(8))) for c in 'cdehijklmopqsuwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ': with self.subTest(c): - with self.assertRaises(re.error): + with self.assertRaises(re.PatternError): self.assertEqual(re.sub('a', '\\' + c, 'a'), '\\' + c) self.assertEqual(re.sub(r'^\s*', 'X', 'test'), 'Xtest') @@ -235,9 +240,42 @@ def test_sub_template_numeric_escape(self): def test_qualified_re_sub(self): self.assertEqual(re.sub('a', 'b', 'aaaaa'), 'bbbbb') - self.assertEqual(re.sub('a', 'b', 'aaaaa', 1), 'baaaa') + with self.assertWarns(DeprecationWarning) as w: + self.assertEqual(re.sub('a', 'b', 'aaaaa', 1), 'baaaa') + self.assertEqual(w.filename, __file__) self.assertEqual(re.sub('a', 'b', 'aaaaa', count=1), 'baaaa') + with self.assertRaisesRegex(TypeError, + r"sub\(\) got multiple values for argument 'count'"): + re.sub('a', 'b', 'aaaaa', 1, count=1) + with self.assertRaisesRegex(TypeError, + r"sub\(\) got multiple values for argument 'flags'"): + re.sub('a', 'b', 'aaaaa', 1, 0, flags=0) + with self.assertRaisesRegex(TypeError, + r"sub\(\) takes from 3 to 5 positional arguments but 6 " + r"were given"): + re.sub('a', 'b', 'aaaaa', 1, 0, 0) + + def test_misuse_flags(self): + with self.assertWarns(DeprecationWarning) as w: + result = re.sub('a', 'b', 'aaaaa', re.I) + self.assertEqual(result, re.sub('a', 'b', 'aaaaa', count=int(re.I))) + self.assertEqual(str(w.warning), + "'count' is passed as positional argument") + self.assertEqual(w.filename, __file__) + with self.assertWarns(DeprecationWarning) as w: + result = re.subn("b*", "x", "xyz", re.I) + self.assertEqual(result, re.subn("b*", "x", "xyz", count=int(re.I))) + self.assertEqual(str(w.warning), + "'count' is passed as positional argument") + self.assertEqual(w.filename, __file__) + with self.assertWarns(DeprecationWarning) as w: + result = re.split(":", ":a:b::c", re.I) + self.assertEqual(result, re.split(":", ":a:b::c", maxsplit=int(re.I))) + self.assertEqual(str(w.warning), + "'maxsplit' is passed as positional argument") + self.assertEqual(w.filename, __file__) + def test_bug_114660(self): self.assertEqual(re.sub(r'(\S)\s+(\S)', r'\1 \2', 'hello there'), 'hello there') @@ -344,9 +382,22 @@ def test_re_subn(self): self.assertEqual(re.subn("b+", "x", "bbbb BBBB"), ('x BBBB', 1)) self.assertEqual(re.subn("b+", "x", "xyz"), ('xyz', 0)) self.assertEqual(re.subn("b*", "x", "xyz"), ('xxxyxzx', 4)) - self.assertEqual(re.subn("b*", "x", "xyz", 2), ('xxxyz', 2)) + with self.assertWarns(DeprecationWarning) as w: + self.assertEqual(re.subn("b*", "x", "xyz", 2), ('xxxyz', 2)) + self.assertEqual(w.filename, __file__) self.assertEqual(re.subn("b*", "x", "xyz", count=2), ('xxxyz', 2)) + with self.assertRaisesRegex(TypeError, + r"subn\(\) got multiple values for argument 'count'"): + re.subn('a', 'b', 'aaaaa', 1, count=1) + with self.assertRaisesRegex(TypeError, + r"subn\(\) got multiple values for argument 'flags'"): + re.subn('a', 'b', 'aaaaa', 1, 0, flags=0) + with self.assertRaisesRegex(TypeError, + r"subn\(\) takes from 3 to 5 positional arguments but 6 " + r"were given"): + re.subn('a', 'b', 'aaaaa', 1, 0, 0) + def test_re_split(self): for string in ":a:b::c", S(":a:b::c"): self.assertTypedEqual(re.split(":", string), @@ -401,7 +452,9 @@ def test_re_split(self): self.assertTypedEqual(re.split(sep, ':a:b::c'), expected) def test_qualified_re_split(self): - self.assertEqual(re.split(":", ":a:b::c", 2), ['', 'a', 'b::c']) + with self.assertWarns(DeprecationWarning) as w: + self.assertEqual(re.split(":", ":a:b::c", 2), ['', 'a', 'b::c']) + self.assertEqual(w.filename, __file__) self.assertEqual(re.split(":", ":a:b::c", maxsplit=2), ['', 'a', 'b::c']) self.assertEqual(re.split(':', 'a:b:c:d', maxsplit=2), ['a', 'b', 'c:d']) self.assertEqual(re.split("(:)", ":a:b::c", maxsplit=2), @@ -411,6 +464,17 @@ def test_qualified_re_split(self): self.assertEqual(re.split("(:*)", ":a:b::c", maxsplit=2), ['', ':', '', '', 'a:b::c']) + with self.assertRaisesRegex(TypeError, + r"split\(\) got multiple values for argument 'maxsplit'"): + re.split(":", ":a:b::c", 2, maxsplit=2) + with self.assertRaisesRegex(TypeError, + r"split\(\) got multiple values for argument 'flags'"): + re.split(":", ":a:b::c", 2, 0, flags=0) + with self.assertRaisesRegex(TypeError, + r"split\(\) takes from 2 to 4 positional arguments but 5 " + r"were given"): + re.split(":", ":a:b::c", 2, 0, 0) + def test_re_findall(self): self.assertEqual(re.findall(":+", "abc"), []) for string in "a:b::c:::d", S("a:b::c:::d"): @@ -775,10 +839,10 @@ def test_other_escapes(self): re.purge() # for warnings for c in 'ceghijklmopqyzCEFGHIJKLMNOPQRTVXY': with self.subTest(c): - self.assertRaises(re.error, re.compile, '\\%c' % c) + self.assertRaises(re.PatternError, re.compile, '\\%c' % c) for c in 'ceghijklmopqyzABCEFGHIJKLMNOPQRTVXYZ': with self.subTest(c): - self.assertRaises(re.error, re.compile, '[\\%c]' % c) + self.assertRaises(re.PatternError, re.compile, '[\\%c]' % c) def test_named_unicode_escapes(self): # test individual Unicode named escapes @@ -909,14 +973,14 @@ def test_lookbehind(self): self.assertIsNone(re.match(r'(?:(a)|(x))b(?<=(?(1)c|x))c', 'abc')) self.assertTrue(re.match(r'(?:(a)|(x))b(?<=(?(1)b|x))c', 'abc')) # Group used before defined. - self.assertRaises(re.error, re.compile, r'(a)b(?<=(?(2)b|x))(c)') + self.assertRaises(re.PatternError, re.compile, r'(a)b(?<=(?(2)b|x))(c)') self.assertIsNone(re.match(r'(a)b(?<=(?(1)c|x))(c)', 'abc')) self.assertTrue(re.match(r'(a)b(?<=(?(1)b|x))(c)', 'abc')) # Group defined in the same lookbehind pattern - self.assertRaises(re.error, re.compile, r'(a)b(?<=(.)\2)(c)') - self.assertRaises(re.error, re.compile, r'(a)b(?<=(?P.)(?P=a))(c)') - self.assertRaises(re.error, re.compile, r'(a)b(?<=(a)(?(2)b|x))(c)') - self.assertRaises(re.error, re.compile, r'(a)b(?<=(.)(?<=\2))(c)') + self.assertRaises(re.PatternError, re.compile, r'(a)b(?<=(.)\2)(c)') + self.assertRaises(re.PatternError, re.compile, r'(a)b(?<=(?P.)(?P=a))(c)') + self.assertRaises(re.PatternError, re.compile, r'(a)b(?<=(a)(?(2)b|x))(c)') + self.assertRaises(re.PatternError, re.compile, r'(a)b(?<=(.)(?<=\2))(c)') def test_ignore_case(self): self.assertEqual(re.match("abc", "ABC", re.I).group(0), "ABC") @@ -1257,8 +1321,8 @@ def test_sre_byte_literals(self): self.assertTrue(re.match((r"\x%02x" % i).encode(), bytes([i]))) self.assertTrue(re.match((r"\x%02x0" % i).encode(), bytes([i])+b"0")) self.assertTrue(re.match((r"\x%02xz" % i).encode(), bytes([i])+b"z")) - self.assertRaises(re.error, re.compile, br"\u1234") - self.assertRaises(re.error, re.compile, br"\U00012345") + self.assertRaises(re.PatternError, re.compile, br"\u1234") + self.assertRaises(re.PatternError, re.compile, br"\U00012345") self.assertTrue(re.match(br"\0", b"\000")) self.assertTrue(re.match(br"\08", b"\0008")) self.assertTrue(re.match(br"\01", b"\001")) @@ -1280,8 +1344,8 @@ def test_sre_byte_class_literals(self): self.assertTrue(re.match((r"[\x%02x]" % i).encode(), bytes([i]))) self.assertTrue(re.match((r"[\x%02x0]" % i).encode(), bytes([i]))) self.assertTrue(re.match((r"[\x%02xz]" % i).encode(), bytes([i]))) - self.assertRaises(re.error, re.compile, br"[\u1234]") - self.assertRaises(re.error, re.compile, br"[\U00012345]") + self.assertRaises(re.PatternError, re.compile, br"[\u1234]") + self.assertRaises(re.PatternError, re.compile, br"[\U00012345]") self.checkPatternError(br"[\567]", r'octal escape value \567 outside of ' r'range 0-0o377', 1) @@ -1614,11 +1678,11 @@ def test_ascii_and_unicode_flag(self): self.assertIsNone(pat.match(b'\xe0')) # Incompatibilities self.assertRaises(ValueError, re.compile, br'\w', re.UNICODE) - self.assertRaises(re.error, re.compile, br'(?u)\w') + self.assertRaises(re.PatternError, re.compile, br'(?u)\w') self.assertRaises(ValueError, re.compile, r'\w', re.UNICODE | re.ASCII) self.assertRaises(ValueError, re.compile, r'(?u)\w', re.ASCII) self.assertRaises(ValueError, re.compile, r'(?a)\w', re.UNICODE) - self.assertRaises(re.error, re.compile, r'(?au)\w') + self.assertRaises(re.PatternError, re.compile, r'(?au)\w') def test_locale_flag(self): enc = locale.getpreferredencoding() @@ -1659,11 +1723,11 @@ def test_locale_flag(self): self.assertIsNone(pat.match(bletter)) # Incompatibilities self.assertRaises(ValueError, re.compile, '', re.LOCALE) - self.assertRaises(re.error, re.compile, '(?L)') + self.assertRaises(re.PatternError, re.compile, '(?L)') self.assertRaises(ValueError, re.compile, b'', re.LOCALE | re.ASCII) self.assertRaises(ValueError, re.compile, b'(?L)', re.ASCII) self.assertRaises(ValueError, re.compile, b'(?a)', re.LOCALE) - self.assertRaises(re.error, re.compile, b'(?aL)') + self.assertRaises(re.PatternError, re.compile, b'(?aL)') def test_scoped_flags(self): self.assertTrue(re.match(r'(?i:a)b', 'Ab')) @@ -1800,6 +1864,29 @@ def test_repeat_minmax_overflow(self): self.assertRaises(OverflowError, re.compile, r".{%d,}?" % 2**128) self.assertRaises(OverflowError, re.compile, r".{%d,%d}" % (2**129, 2**128)) + def test_look_behind_overflow(self): + string = "x" * 2_500_000 + p1 = r"(?<=((.{%d}){%d}){%d})" + p2 = r"(?)', @@ -1976,7 +2063,7 @@ def test_locale_compiled(self): self.assertIsNone(p4.match(b'\xc5\xc5')) def test_error(self): - with self.assertRaises(re.error) as cm: + with self.assertRaises(re.PatternError) as cm: re.compile('(\u20ac))') err = cm.exception self.assertIsInstance(err.pattern, str) @@ -1988,14 +2075,14 @@ def test_error(self): self.assertIn(' at position 3', str(err)) self.assertNotIn(' at position 3', err.msg) # Bytes pattern - with self.assertRaises(re.error) as cm: + with self.assertRaises(re.PatternError) as cm: re.compile(b'(\xa4))') err = cm.exception self.assertIsInstance(err.pattern, bytes) self.assertEqual(err.pattern, b'(\xa4))') self.assertEqual(err.pos, 3) # Multiline pattern - with self.assertRaises(re.error) as cm: + with self.assertRaises(re.PatternError) as cm: re.compile(""" ( abc @@ -2342,6 +2429,26 @@ def test_bug_gh91616(self): self.assertTrue(re.fullmatch(r'(?s:(?>.*?\.).*)\Z', "a.txt")) # reproducer self.assertTrue(re.fullmatch(r'(?s:(?=(?P.*?\.))(?P=g0).*)\Z', "a.txt")) + def test_bug_gh100061(self): + # gh-100061 + self.assertEqual(re.match('(?>(?:.(?!D))+)', 'ABCDE').span(), (0, 2)) + self.assertEqual(re.match('(?:.(?!D))++', 'ABCDE').span(), (0, 2)) + self.assertEqual(re.match('(?>(?:.(?!D))*)', 'ABCDE').span(), (0, 2)) + self.assertEqual(re.match('(?:.(?!D))*+', 'ABCDE').span(), (0, 2)) + self.assertEqual(re.match('(?>(?:.(?!D))?)', 'CDE').span(), (0, 0)) + self.assertEqual(re.match('(?:.(?!D))?+', 'CDE').span(), (0, 0)) + self.assertEqual(re.match('(?>(?:.(?!D)){1,3})', 'ABCDE').span(), (0, 2)) + self.assertEqual(re.match('(?:.(?!D)){1,3}+', 'ABCDE').span(), (0, 2)) + # gh-106052 + self.assertEqual(re.match("(?>(?:ab?c)+)", "aca").span(), (0, 2)) + self.assertEqual(re.match("(?:ab?c)++", "aca").span(), (0, 2)) + self.assertEqual(re.match("(?>(?:ab?c)*)", "aca").span(), (0, 2)) + self.assertEqual(re.match("(?:ab?c)*+", "aca").span(), (0, 2)) + self.assertEqual(re.match("(?>(?:ab?c)?)", "a").span(), (0, 0)) + self.assertEqual(re.match("(?:ab?c)?+", "a").span(), (0, 0)) + self.assertEqual(re.match("(?>(?:ab?c){1,3})", "aca").span(), (0, 2)) + self.assertEqual(re.match("(?:ab?c){1,3}+", "aca").span(), (0, 2)) + @unittest.skipIf(multiprocessing is None, 'test requires multiprocessing') def test_regression_gh94675(self): pattern = re.compile(r'(?<=[({}])(((//[^\n]*)?[\n])([\000-\040])*)*' @@ -2362,6 +2469,9 @@ def test_regression_gh94675(self): p.terminate() p.join() + def test_fail(self): + self.assertEqual(re.search(r'12(?!)|3', '123')[0], '3') + def get_debug_out(pat): with captured_stdout() as out: @@ -2651,6 +2761,9 @@ def test_dealloc(self): _sre.compile("abc", 0, [long_overflow], 0, {}, ()) with self.assertRaises(TypeError): _sre.compile({}, 0, [], 0, [], []) + # gh-110590: `TypeError` was overwritten with `OverflowError`: + with self.assertRaises(TypeError): + _sre.compile('', 0, ['abc'], 0, {}, ()) @cpython_only def test_repeat_minmax_overflow_maxrepeat(self): @@ -2710,7 +2823,7 @@ def test_re_tests(self): with self.subTest(pattern=pattern, string=s): if outcome == SYNTAX_ERROR: # Expected a syntax error - with self.assertRaises(re.error): + with self.assertRaises(re.PatternError): re.compile(pattern) continue diff --git a/Lib/test/test_readline.py b/Lib/test/test_readline.py index 59dbef90380053..5e0e6f8dfac651 100644 --- a/Lib/test/test_readline.py +++ b/Lib/test/test_readline.py @@ -1,18 +1,16 @@ """ Very minimal unittests for parts of the readline module. """ -from contextlib import ExitStack -from errno import EIO import locale import os -import selectors -import subprocess import sys import tempfile +import textwrap import unittest from test.support import verbose from test.support.import_helper import import_module from test.support.os_helper import unlink, temp_dir, TESTFN +from test.support.pty_helper import run_pty from test.support.script_helper import assert_python_ok # Skip tests if there is no readline module @@ -21,7 +19,7 @@ if hasattr(readline, "_READLINE_LIBRARY_VERSION"): is_editline = ("EditLine wrapper" in readline._READLINE_LIBRARY_VERSION) else: - is_editline = (readline.__doc__ and "libedit" in readline.__doc__) + is_editline = readline.backend == "editline" def setUpModule(): @@ -147,6 +145,9 @@ def test_init(self): TERM='xterm-256color') self.assertEqual(stdout, b'') + def test_backend(self): + self.assertIn(readline.backend, ("readline", "editline")) + auto_history_script = """\ import readline readline.set_auto_history({}) @@ -166,6 +167,25 @@ def test_auto_history_disabled(self): # end, so don't expect it in the output. self.assertIn(b"History length: 0", output) + def test_set_complete_delims(self): + script = textwrap.dedent(""" + import readline + def complete(text, state): + if state == 0 and text == "$": + return "$complete" + return None + if readline.backend == "editline": + readline.parse_and_bind(r'bind "\\t" rl_complete') + else: + readline.parse_and_bind(r'"\\t": complete') + readline.set_completer_delims(" \\t\\n") + readline.set_completer(complete) + print(input()) + """) + + output = run_pty(script, input=b"$\t\n") + self.assertIn(b"$complete", output) + def test_nonascii(self): loc = locale.setlocale(locale.LC_CTYPE, None) if loc in ('C', 'POSIX'): @@ -181,7 +201,7 @@ def test_nonascii(self): script = r"""import readline -is_editline = readline.__doc__ and "libedit" in readline.__doc__ +is_editline = readline.backend == "editline" inserted = "[\xEFnserted]" macro = "|t\xEB[after]" set_pre_input_hook = getattr(readline, "set_pre_input_hook", None) @@ -304,55 +324,5 @@ def test_history_size(self): self.assertEqual(lines[-1].strip(), b"last input") -def run_pty(script, input=b"dummy input\r", env=None): - pty = import_module('pty') - output = bytearray() - [master, slave] = pty.openpty() - args = (sys.executable, '-c', script) - proc = subprocess.Popen(args, stdin=slave, stdout=slave, stderr=slave, env=env) - os.close(slave) - with ExitStack() as cleanup: - cleanup.enter_context(proc) - def terminate(proc): - try: - proc.terminate() - except ProcessLookupError: - # Workaround for Open/Net BSD bug (Issue 16762) - pass - cleanup.callback(terminate, proc) - cleanup.callback(os.close, master) - # Avoid using DefaultSelector and PollSelector. Kqueue() does not - # work with pseudo-terminals on OS X < 10.9 (Issue 20365) and Open - # BSD (Issue 20667). Poll() does not work with OS X 10.6 or 10.4 - # either (Issue 20472). Hopefully the file descriptor is low enough - # to use with select(). - sel = cleanup.enter_context(selectors.SelectSelector()) - sel.register(master, selectors.EVENT_READ | selectors.EVENT_WRITE) - os.set_blocking(master, False) - while True: - for [_, events] in sel.select(): - if events & selectors.EVENT_READ: - try: - chunk = os.read(master, 0x10000) - except OSError as err: - # Linux raises EIO when slave is closed (Issue 5380) - if err.errno != EIO: - raise - chunk = b"" - if not chunk: - return output - output.extend(chunk) - if events & selectors.EVENT_WRITE: - try: - input = input[os.write(master, input):] - except OSError as err: - # Apparently EIO means the slave was closed - if err.errno != EIO: - raise - input = b"" # Stop writing - if not input: - sel.modify(master, selectors.EVENT_READ) - - if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_regrtest.py b/Lib/test/test_regrtest.py index 806b932a164df8..e828941f6c779d 100644 --- a/Lib/test/test_regrtest.py +++ b/Lib/test/test_regrtest.py @@ -5,22 +5,31 @@ """ import contextlib +import dataclasses import glob import io import locale import os.path import platform +import random import re +import shlex +import signal import subprocess import sys import sysconfig import tempfile import textwrap import unittest -from test import libregrtest from test import support -from test.support import os_helper -from test.libregrtest import utils, setup +from test.support import os_helper, without_optimizer +from test.libregrtest import cmdline +from test.libregrtest import main +from test.libregrtest import setup +from test.libregrtest import utils +from test.libregrtest.filter import set_match_tests, match_test +from test.libregrtest.result import TestStats +from test.libregrtest.utils import normalize_test_name if not support.has_subprocess_support: raise unittest.SkipTest("test module requires subprocess") @@ -32,6 +41,7 @@ EXITCODE_BAD_TEST = 2 EXITCODE_ENV_CHANGED = 3 EXITCODE_NO_TESTS_RAN = 4 +EXITCODE_RERUN_FAIL = 5 EXITCODE_INTERRUPTED = 130 TEST_INTERRUPTED = textwrap.dedent(""" @@ -49,9 +59,13 @@ class ParseArgsTestCase(unittest.TestCase): Test regrtest's argument parsing, function _parse_args(). """ + @staticmethod + def parse_args(args): + return cmdline._parse_args(args) + def checkError(self, args, msg): with support.captured_stderr() as err, self.assertRaises(SystemExit): - libregrtest._parse_args(args) + self.parse_args(args) self.assertIn(msg, err.getvalue()) def test_help(self): @@ -59,83 +73,101 @@ def test_help(self): with self.subTest(opt=opt): with support.captured_stdout() as out, \ self.assertRaises(SystemExit): - libregrtest._parse_args([opt]) + self.parse_args([opt]) self.assertIn('Run Python regression tests.', out.getvalue()) def test_timeout(self): - ns = libregrtest._parse_args(['--timeout', '4.2']) + ns = self.parse_args(['--timeout', '4.2']) self.assertEqual(ns.timeout, 4.2) + + # negative, zero and empty string are treated as "no timeout" + for value in ('-1', '0', ''): + with self.subTest(value=value): + ns = self.parse_args([f'--timeout={value}']) + self.assertEqual(ns.timeout, None) + self.checkError(['--timeout'], 'expected one argument') - self.checkError(['--timeout', 'foo'], 'invalid float value') + self.checkError(['--timeout', 'foo'], 'invalid timeout value:') def test_wait(self): - ns = libregrtest._parse_args(['--wait']) + ns = self.parse_args(['--wait']) self.assertTrue(ns.wait) - def test_worker_args(self): - ns = libregrtest._parse_args(['--worker-args', '[[], {}]']) - self.assertEqual(ns.worker_args, '[[], {}]') - self.checkError(['--worker-args'], 'expected one argument') - def test_start(self): for opt in '-S', '--start': with self.subTest(opt=opt): - ns = libregrtest._parse_args([opt, 'foo']) + ns = self.parse_args([opt, 'foo']) self.assertEqual(ns.start, 'foo') self.checkError([opt], 'expected one argument') def test_verbose(self): - ns = libregrtest._parse_args(['-v']) + ns = self.parse_args(['-v']) self.assertEqual(ns.verbose, 1) - ns = libregrtest._parse_args(['-vvv']) + ns = self.parse_args(['-vvv']) self.assertEqual(ns.verbose, 3) - ns = libregrtest._parse_args(['--verbose']) + ns = self.parse_args(['--verbose']) self.assertEqual(ns.verbose, 1) - ns = libregrtest._parse_args(['--verbose'] * 3) + ns = self.parse_args(['--verbose'] * 3) self.assertEqual(ns.verbose, 3) - ns = libregrtest._parse_args([]) + ns = self.parse_args([]) self.assertEqual(ns.verbose, 0) - def test_verbose2(self): - for opt in '-w', '--verbose2': + def test_rerun(self): + for opt in '-w', '--rerun', '--verbose2': with self.subTest(opt=opt): - ns = libregrtest._parse_args([opt]) - self.assertTrue(ns.verbose2) + ns = self.parse_args([opt]) + self.assertTrue(ns.rerun) def test_verbose3(self): for opt in '-W', '--verbose3': with self.subTest(opt=opt): - ns = libregrtest._parse_args([opt]) + ns = self.parse_args([opt]) self.assertTrue(ns.verbose3) def test_quiet(self): for opt in '-q', '--quiet': with self.subTest(opt=opt): - ns = libregrtest._parse_args([opt]) + ns = self.parse_args([opt]) self.assertTrue(ns.quiet) self.assertEqual(ns.verbose, 0) def test_slowest(self): for opt in '-o', '--slowest': with self.subTest(opt=opt): - ns = libregrtest._parse_args([opt]) + ns = self.parse_args([opt]) self.assertTrue(ns.print_slow) def test_header(self): - ns = libregrtest._parse_args(['--header']) + ns = self.parse_args(['--header']) self.assertTrue(ns.header) - ns = libregrtest._parse_args(['--verbose']) + ns = self.parse_args(['--verbose']) self.assertTrue(ns.header) def test_randomize(self): - for opt in '-r', '--randomize': + for opt in ('-r', '--randomize'): with self.subTest(opt=opt): - ns = libregrtest._parse_args([opt]) + ns = self.parse_args([opt]) self.assertTrue(ns.randomize) + with os_helper.EnvironmentVarGuard() as env: + # with SOURCE_DATE_EPOCH + env['SOURCE_DATE_EPOCH'] = '1697839080' + ns = self.parse_args(['--randomize']) + regrtest = main.Regrtest(ns) + self.assertFalse(regrtest.randomize) + self.assertIsInstance(regrtest.random_seed, str) + self.assertEqual(regrtest.random_seed, '1697839080') + + # without SOURCE_DATE_EPOCH + del env['SOURCE_DATE_EPOCH'] + ns = self.parse_args(['--randomize']) + regrtest = main.Regrtest(ns) + self.assertTrue(regrtest.randomize) + self.assertIsInstance(regrtest.random_seed, int) + def test_randseed(self): - ns = libregrtest._parse_args(['--randseed', '12345']) + ns = self.parse_args(['--randseed', '12345']) self.assertEqual(ns.random_seed, 12345) self.assertTrue(ns.randomize) self.checkError(['--randseed'], 'expected one argument') @@ -144,7 +176,7 @@ def test_randseed(self): def test_fromfile(self): for opt in '-f', '--fromfile': with self.subTest(opt=opt): - ns = libregrtest._parse_args([opt, 'foo']) + ns = self.parse_args([opt, 'foo']) self.assertEqual(ns.fromfile, 'foo') self.checkError([opt], 'expected one argument') self.checkError([opt, 'foo', '-s'], "don't go together") @@ -152,44 +184,37 @@ def test_fromfile(self): def test_exclude(self): for opt in '-x', '--exclude': with self.subTest(opt=opt): - ns = libregrtest._parse_args([opt]) + ns = self.parse_args([opt]) self.assertTrue(ns.exclude) def test_single(self): for opt in '-s', '--single': with self.subTest(opt=opt): - ns = libregrtest._parse_args([opt]) + ns = self.parse_args([opt]) self.assertTrue(ns.single) self.checkError([opt, '-f', 'foo'], "don't go together") - def test_ignore(self): - for opt in '-i', '--ignore': + def test_match(self): + for opt in '-m', '--match': with self.subTest(opt=opt): - ns = libregrtest._parse_args([opt, 'pattern']) - self.assertEqual(ns.ignore_tests, ['pattern']) + ns = self.parse_args([opt, 'pattern']) + self.assertEqual(ns.match_tests, [('pattern', True)]) self.checkError([opt], 'expected one argument') - self.addCleanup(os_helper.unlink, os_helper.TESTFN) - with open(os_helper.TESTFN, "w") as fp: - print('matchfile1', file=fp) - print('matchfile2', file=fp) - - filename = os.path.abspath(os_helper.TESTFN) - ns = libregrtest._parse_args(['-m', 'match', - '--ignorefile', filename]) - self.assertEqual(ns.ignore_tests, - ['matchfile1', 'matchfile2']) - - def test_match(self): - for opt in '-m', '--match': + for opt in '-i', '--ignore': with self.subTest(opt=opt): - ns = libregrtest._parse_args([opt, 'pattern']) - self.assertEqual(ns.match_tests, ['pattern']) + ns = self.parse_args([opt, 'pattern']) + self.assertEqual(ns.match_tests, [('pattern', False)]) self.checkError([opt], 'expected one argument') - ns = libregrtest._parse_args(['-m', 'pattern1', - '-m', 'pattern2']) - self.assertEqual(ns.match_tests, ['pattern1', 'pattern2']) + ns = self.parse_args(['-m', 'pattern1', '-m', 'pattern2']) + self.assertEqual(ns.match_tests, [('pattern1', True), ('pattern2', True)]) + + ns = self.parse_args(['-m', 'pattern1', '-i', 'pattern2']) + self.assertEqual(ns.match_tests, [('pattern1', True), ('pattern2', False)]) + + ns = self.parse_args(['-i', 'pattern1', '-m', 'pattern2']) + self.assertEqual(ns.match_tests, [('pattern1', False), ('pattern2', True)]) self.addCleanup(os_helper.unlink, os_helper.TESTFN) with open(os_helper.TESTFN, "w") as fp: @@ -197,73 +222,76 @@ def test_match(self): print('matchfile2', file=fp) filename = os.path.abspath(os_helper.TESTFN) - ns = libregrtest._parse_args(['-m', 'match', - '--matchfile', filename]) + ns = self.parse_args(['-m', 'match', '--matchfile', filename]) self.assertEqual(ns.match_tests, - ['match', 'matchfile1', 'matchfile2']) + [('match', True), ('matchfile1', True), ('matchfile2', True)]) + + ns = self.parse_args(['-i', 'match', '--ignorefile', filename]) + self.assertEqual(ns.match_tests, + [('match', False), ('matchfile1', False), ('matchfile2', False)]) def test_failfast(self): for opt in '-G', '--failfast': with self.subTest(opt=opt): - ns = libregrtest._parse_args([opt, '-v']) + ns = self.parse_args([opt, '-v']) self.assertTrue(ns.failfast) - ns = libregrtest._parse_args([opt, '-W']) + ns = self.parse_args([opt, '-W']) self.assertTrue(ns.failfast) self.checkError([opt], '-G/--failfast needs either -v or -W') def test_use(self): for opt in '-u', '--use': with self.subTest(opt=opt): - ns = libregrtest._parse_args([opt, 'gui,network']) + ns = self.parse_args([opt, 'gui,network']) self.assertEqual(ns.use_resources, ['gui', 'network']) - ns = libregrtest._parse_args([opt, 'gui,none,network']) + ns = self.parse_args([opt, 'gui,none,network']) self.assertEqual(ns.use_resources, ['network']) - expected = list(libregrtest.ALL_RESOURCES) + expected = list(cmdline.ALL_RESOURCES) expected.remove('gui') - ns = libregrtest._parse_args([opt, 'all,-gui']) + ns = self.parse_args([opt, 'all,-gui']) self.assertEqual(ns.use_resources, expected) self.checkError([opt], 'expected one argument') self.checkError([opt, 'foo'], 'invalid resource') # all + a resource not part of "all" - ns = libregrtest._parse_args([opt, 'all,tzdata']) + ns = self.parse_args([opt, 'all,tzdata']) self.assertEqual(ns.use_resources, - list(libregrtest.ALL_RESOURCES) + ['tzdata']) + list(cmdline.ALL_RESOURCES) + ['tzdata']) # test another resource which is not part of "all" - ns = libregrtest._parse_args([opt, 'extralargefile']) + ns = self.parse_args([opt, 'extralargefile']) self.assertEqual(ns.use_resources, ['extralargefile']) def test_memlimit(self): for opt in '-M', '--memlimit': with self.subTest(opt=opt): - ns = libregrtest._parse_args([opt, '4G']) + ns = self.parse_args([opt, '4G']) self.assertEqual(ns.memlimit, '4G') self.checkError([opt], 'expected one argument') def test_testdir(self): - ns = libregrtest._parse_args(['--testdir', 'foo']) + ns = self.parse_args(['--testdir', 'foo']) self.assertEqual(ns.testdir, os.path.join(os_helper.SAVEDCWD, 'foo')) self.checkError(['--testdir'], 'expected one argument') def test_runleaks(self): for opt in '-L', '--runleaks': with self.subTest(opt=opt): - ns = libregrtest._parse_args([opt]) + ns = self.parse_args([opt]) self.assertTrue(ns.runleaks) def test_huntrleaks(self): for opt in '-R', '--huntrleaks': with self.subTest(opt=opt): - ns = libregrtest._parse_args([opt, ':']) + ns = self.parse_args([opt, ':']) self.assertEqual(ns.huntrleaks, (5, 4, 'reflog.txt')) - ns = libregrtest._parse_args([opt, '6:']) + ns = self.parse_args([opt, '6:']) self.assertEqual(ns.huntrleaks, (6, 4, 'reflog.txt')) - ns = libregrtest._parse_args([opt, ':3']) + ns = self.parse_args([opt, ':3']) self.assertEqual(ns.huntrleaks, (5, 3, 'reflog.txt')) - ns = libregrtest._parse_args([opt, '6:3:leaks.log']) + ns = self.parse_args([opt, '6:3:leaks.log']) self.assertEqual(ns.huntrleaks, (6, 3, 'leaks.log')) self.checkError([opt], 'expected one argument') self.checkError([opt, '6'], @@ -274,23 +302,33 @@ def test_huntrleaks(self): def test_multiprocess(self): for opt in '-j', '--multiprocess': with self.subTest(opt=opt): - ns = libregrtest._parse_args([opt, '2']) + ns = self.parse_args([opt, '2']) self.assertEqual(ns.use_mp, 2) self.checkError([opt], 'expected one argument') self.checkError([opt, 'foo'], 'invalid int value') - self.checkError([opt, '2', '-T'], "don't go together") - self.checkError([opt, '0', '-T'], "don't go together") - def test_coverage(self): + def test_coverage_sequential(self): + for opt in '-T', '--coverage': + with self.subTest(opt=opt): + with support.captured_stderr() as stderr: + ns = self.parse_args([opt]) + self.assertTrue(ns.trace) + self.assertIn( + "collecting coverage without -j is imprecise", + stderr.getvalue(), + ) + + @unittest.skipUnless(support.Py_DEBUG, 'need a debug build') + def test_coverage_mp(self): for opt in '-T', '--coverage': with self.subTest(opt=opt): - ns = libregrtest._parse_args([opt]) + ns = self.parse_args([opt, '-j1']) self.assertTrue(ns.trace) def test_coverdir(self): for opt in '-D', '--coverdir': with self.subTest(opt=opt): - ns = libregrtest._parse_args([opt, 'foo']) + ns = self.parse_args([opt, 'foo']) self.assertEqual(ns.coverdir, os.path.join(os_helper.SAVEDCWD, 'foo')) self.checkError([opt], 'expected one argument') @@ -298,13 +336,13 @@ def test_coverdir(self): def test_nocoverdir(self): for opt in '-N', '--nocoverdir': with self.subTest(opt=opt): - ns = libregrtest._parse_args([opt]) + ns = self.parse_args([opt]) self.assertIsNone(ns.coverdir) def test_threshold(self): for opt in '-t', '--threshold': with self.subTest(opt=opt): - ns = libregrtest._parse_args([opt, '1000']) + ns = self.parse_args([opt, '1000']) self.assertEqual(ns.threshold, 1000) self.checkError([opt], 'expected one argument') self.checkError([opt, 'foo'], 'invalid int value') @@ -313,7 +351,7 @@ def test_nowindows(self): for opt in '-n', '--nowindows': with self.subTest(opt=opt): with contextlib.redirect_stderr(io.StringIO()) as stderr: - ns = libregrtest._parse_args([opt]) + ns = self.parse_args([opt]) self.assertTrue(ns.nowindows) err = stderr.getvalue() self.assertIn('the --nowindows (-n) option is deprecated', err) @@ -321,39 +359,39 @@ def test_nowindows(self): def test_forever(self): for opt in '-F', '--forever': with self.subTest(opt=opt): - ns = libregrtest._parse_args([opt]) + ns = self.parse_args([opt]) self.assertTrue(ns.forever) def test_unrecognized_argument(self): self.checkError(['--xxx'], 'usage:') def test_long_option__partial(self): - ns = libregrtest._parse_args(['--qui']) + ns = self.parse_args(['--qui']) self.assertTrue(ns.quiet) self.assertEqual(ns.verbose, 0) def test_two_options(self): - ns = libregrtest._parse_args(['--quiet', '--exclude']) + ns = self.parse_args(['--quiet', '--exclude']) self.assertTrue(ns.quiet) self.assertEqual(ns.verbose, 0) self.assertTrue(ns.exclude) def test_option_with_empty_string_value(self): - ns = libregrtest._parse_args(['--start', '']) + ns = self.parse_args(['--start', '']) self.assertEqual(ns.start, '') def test_arg(self): - ns = libregrtest._parse_args(['foo']) + ns = self.parse_args(['foo']) self.assertEqual(ns.args, ['foo']) def test_option_and_arg(self): - ns = libregrtest._parse_args(['--quiet', 'foo']) + ns = self.parse_args(['--quiet', 'foo']) self.assertTrue(ns.quiet) self.assertEqual(ns.verbose, 0) self.assertEqual(ns.args, ['foo']) def test_arg_option_arg(self): - ns = libregrtest._parse_args(['test_unaryop', '-v', 'test_binop']) + ns = self.parse_args(['test_unaryop', '-v', 'test_binop']) self.assertEqual(ns.verbose, 1) self.assertEqual(ns.args, ['test_unaryop', 'test_binop']) @@ -361,6 +399,69 @@ def test_unknown_option(self): self.checkError(['--unknown-option'], 'unrecognized arguments: --unknown-option') + def check_ci_mode(self, args, use_resources, rerun=True): + ns = cmdline._parse_args(args) + + # Check Regrtest attributes which are more reliable than Namespace + # which has an unclear API + with os_helper.EnvironmentVarGuard() as env: + # Ignore SOURCE_DATE_EPOCH env var if it's set + if 'SOURCE_DATE_EPOCH' in env: + del env['SOURCE_DATE_EPOCH'] + + regrtest = main.Regrtest(ns) + + self.assertEqual(regrtest.num_workers, -1) + self.assertEqual(regrtest.want_rerun, rerun) + self.assertTrue(regrtest.randomize) + self.assertIsInstance(regrtest.random_seed, int) + self.assertTrue(regrtest.fail_env_changed) + self.assertTrue(regrtest.print_slowest) + self.assertTrue(regrtest.output_on_failure) + self.assertEqual(sorted(regrtest.use_resources), sorted(use_resources)) + return regrtest + + def test_fast_ci(self): + args = ['--fast-ci'] + use_resources = sorted(cmdline.ALL_RESOURCES) + use_resources.remove('cpu') + regrtest = self.check_ci_mode(args, use_resources) + self.assertEqual(regrtest.timeout, 10 * 60) + + def test_fast_ci_python_cmd(self): + args = ['--fast-ci', '--python', 'python -X dev'] + use_resources = sorted(cmdline.ALL_RESOURCES) + use_resources.remove('cpu') + regrtest = self.check_ci_mode(args, use_resources, rerun=False) + self.assertEqual(regrtest.timeout, 10 * 60) + self.assertEqual(regrtest.python_cmd, ('python', '-X', 'dev')) + + def test_fast_ci_resource(self): + # it should be possible to override resources individually + args = ['--fast-ci', '-u-network'] + use_resources = sorted(cmdline.ALL_RESOURCES) + use_resources.remove('cpu') + use_resources.remove('network') + self.check_ci_mode(args, use_resources) + + def test_slow_ci(self): + args = ['--slow-ci'] + use_resources = sorted(cmdline.ALL_RESOURCES) + regrtest = self.check_ci_mode(args, use_resources) + self.assertEqual(regrtest.timeout, 20 * 60) + + def test_dont_add_python_opts(self): + args = ['--dont-add-python-opts'] + ns = cmdline._parse_args(args) + self.assertFalse(ns._add_python_opts) + + +@dataclasses.dataclass(slots=True) +class Rerun: + name: str + match: str | None + success: bool + class BaseTestCase(unittest.TestCase): TEST_UNIQUE_ID = 1 @@ -409,8 +510,12 @@ def regex_search(self, regex, output): self.fail("%r not found in %r" % (regex, output)) return match - def check_line(self, output, regex): - regex = re.compile(r'^' + regex, re.MULTILINE) + def check_line(self, output, pattern, full=False, regex=True): + if not regex: + pattern = re.escape(pattern) + if full: + pattern += '\n' + regex = re.compile(r'^' + pattern, re.MULTILINE) self.assertRegex(output, regex) def parse_executed_tests(self, output): @@ -419,29 +524,47 @@ def parse_executed_tests(self, output): parser = re.finditer(regex, output, re.MULTILINE) return list(match.group(1) for match in parser) - def check_executed_tests(self, output, tests, skipped=(), failed=(), + def check_executed_tests(self, output, tests, *, stats, + skipped=(), failed=(), env_changed=(), omitted=(), - rerun={}, no_test_ran=(), - randomize=False, interrupted=False, - fail_env_changed=False): + rerun=None, run_no_tests=(), + resource_denied=(), + randomize=False, parallel=False, interrupted=False, + fail_env_changed=False, + forever=False, filtered=False): if isinstance(tests, str): tests = [tests] if isinstance(skipped, str): skipped = [skipped] + if isinstance(resource_denied, str): + resource_denied = [resource_denied] if isinstance(failed, str): failed = [failed] if isinstance(env_changed, str): env_changed = [env_changed] if isinstance(omitted, str): omitted = [omitted] - if isinstance(no_test_ran, str): - no_test_ran = [no_test_ran] + if isinstance(run_no_tests, str): + run_no_tests = [run_no_tests] + if isinstance(stats, int): + stats = TestStats(stats) + if parallel: + randomize = True + + rerun_failed = [] + if rerun is not None and not env_changed: + failed = [rerun.name] + if not rerun.success: + rerun_failed.append(rerun.name) executed = self.parse_executed_tests(output) + total_tests = list(tests) + if rerun is not None: + total_tests.append(rerun.name) if randomize: - self.assertEqual(set(executed), set(tests), output) + self.assertEqual(set(executed), set(total_tests), output) else: - self.assertEqual(executed, tests, output) + self.assertEqual(executed, total_tests, output) def plural(count): return 's' if count != 1 else '' @@ -457,12 +580,17 @@ def list_regex(line_format, tests): regex = list_regex('%s test%s skipped', skipped) self.check_line(output, regex) + if resource_denied: + regex = list_regex(r'%s test%s skipped \(resource denied\)', resource_denied) + self.check_line(output, regex) + if failed: regex = list_regex('%s test%s failed', failed) self.check_line(output, regex) if env_changed: - regex = list_regex('%s test%s altered the execution environment', + regex = list_regex(r'%s test%s altered the execution environment ' + r'\(env changed\)', env_changed) self.check_line(output, regex) @@ -470,73 +598,120 @@ def list_regex(line_format, tests): regex = list_regex('%s test%s omitted', omitted) self.check_line(output, regex) - if rerun: - regex = list_regex('%s re-run test%s', rerun.keys()) + if rerun is not None: + regex = list_regex('%s re-run test%s', [rerun.name]) self.check_line(output, regex) - regex = LOG_PREFIX + r"Re-running failed tests in verbose mode" + regex = LOG_PREFIX + r"Re-running 1 failed tests in verbose mode" + self.check_line(output, regex) + regex = fr"Re-running {rerun.name} in verbose mode" + if rerun.match: + regex = fr"{regex} \(matching: {rerun.match}\)" self.check_line(output, regex) - for name, match in rerun.items(): - regex = LOG_PREFIX + f"Re-running {name} in verbose mode \\(matching: {match}\\)" - self.check_line(output, regex) - if no_test_ran: - regex = list_regex('%s test%s run no tests', no_test_ran) + if run_no_tests: + regex = list_regex('%s test%s run no tests', run_no_tests) self.check_line(output, regex) - good = (len(tests) - len(skipped) - len(failed) - - len(omitted) - len(env_changed) - len(no_test_ran)) + good = (len(tests) - len(skipped) - len(resource_denied) - len(failed) + - len(omitted) - len(env_changed) - len(run_no_tests)) if good: - regex = r'%s test%s OK\.$' % (good, plural(good)) - if not skipped and not failed and good > 1: + regex = r'%s test%s OK\.' % (good, plural(good)) + if not skipped and not failed and (rerun is None or rerun.success) and good > 1: regex = 'All %s' % regex - self.check_line(output, regex) + self.check_line(output, regex, full=True) if interrupted: self.check_line(output, 'Test suite interrupted by signal SIGINT.') - result = [] + # Total tests + text = f'run={stats.tests_run:,}' + if filtered: + text = fr'{text} \(filtered\)' + parts = [text] + if stats.failures: + parts.append(f'failures={stats.failures:,}') + if stats.skipped: + parts.append(f'skipped={stats.skipped:,}') + line = fr'Total tests: {" ".join(parts)}' + self.check_line(output, line, full=True) + + # Total test files + run = len(total_tests) - len(resource_denied) + if rerun is not None: + total_failed = len(rerun_failed) + total_rerun = 1 + else: + total_failed = len(failed) + total_rerun = 0 + if interrupted: + run = 0 + text = f'run={run}' + if not forever: + text = f'{text}/{len(tests)}' + if filtered: + text = fr'{text} \(filtered\)' + report = [text] + for name, ntest in ( + ('failed', total_failed), + ('env_changed', len(env_changed)), + ('skipped', len(skipped)), + ('resource_denied', len(resource_denied)), + ('rerun', total_rerun), + ('run_no_tests', len(run_no_tests)), + ): + if ntest: + report.append(f'{name}={ntest}') + line = fr'Total test files: {" ".join(report)}' + self.check_line(output, line, full=True) + + # Result + state = [] if failed: - result.append('FAILURE') + state.append('FAILURE') elif fail_env_changed and env_changed: - result.append('ENV CHANGED') + state.append('ENV CHANGED') if interrupted: - result.append('INTERRUPTED') - if not any((good, result, failed, interrupted, skipped, + state.append('INTERRUPTED') + if not any((good, failed, interrupted, skipped, env_changed, fail_env_changed)): - result.append("NO TESTS RAN") - elif not result: - result.append('SUCCESS') - result = ', '.join(result) - if rerun: - self.check_line(output, 'Tests result: FAILURE') - result = 'FAILURE then %s' % result - - self.check_line(output, 'Tests result: %s' % result) - - def parse_random_seed(self, output): - match = self.regex_search(r'Using random seed ([0-9]+)', output) - randseed = int(match.group(1)) - self.assertTrue(0 <= randseed <= 10000000, randseed) - return randseed + state.append("NO TESTS RAN") + elif not state: + state.append('SUCCESS') + state = ', '.join(state) + if rerun is not None: + new_state = 'SUCCESS' if rerun.success else 'FAILURE' + state = f'{state} then {new_state}' + self.check_line(output, f'Result: {state}', full=True) + + def parse_random_seed(self, output: str) -> str: + match = self.regex_search(r'Using random seed: (.*)', output) + return match.group(1) def run_command(self, args, input=None, exitcode=0, **kw): if not input: input = '' if 'stderr' not in kw: kw['stderr'] = subprocess.STDOUT + + env = kw.pop('env', None) + if env is None: + env = dict(os.environ) + env.pop('SOURCE_DATE_EPOCH', None) + proc = subprocess.run(args, - universal_newlines=True, + text=True, input=input, stdout=subprocess.PIPE, + env=env, **kw) if proc.returncode != exitcode: - msg = ("Command %s failed with exit code %s\n" + msg = ("Command %s failed with exit code %s, but exit code %s expected!\n" "\n" "stdout:\n" "---\n" "%s\n" "---\n" - % (str(args), proc.returncode, proc.stdout)) + % (str(args), proc.returncode, exitcode, proc.stdout)) if proc.stderr: msg += ("\n" "stderr:\n" @@ -548,7 +723,11 @@ def run_command(self, args, input=None, exitcode=0, **kw): return proc def run_python(self, args, **kw): - args = [sys.executable, '-X', 'faulthandler', '-I', *args] + extraargs = [] + if 'uops' in sys._xoptions: + # Pass -X uops along + extraargs.extend(['-X', 'uops']) + args = [sys.executable, *extraargs, '-X', 'faulthandler', '-I', *args] proc = self.run_command(args, **kw) return proc.stdout @@ -599,11 +778,14 @@ def setUp(self): self.regrtest_args.append('-n') def check_output(self, output): - self.parse_random_seed(output) - self.check_executed_tests(output, self.tests, randomize=True) + randseed = self.parse_random_seed(output) + self.assertTrue(randseed.isdigit(), randseed) - def run_tests(self, args): - output = self.run_python(args) + self.check_executed_tests(output, self.tests, + randomize=True, stats=len(self.tests)) + + def run_tests(self, args, env=None): + output = self.run_python(args, env=env) self.check_output(output) def test_script_regrtest(self): @@ -644,14 +826,6 @@ def test_script_autotest(self): args = [*self.python_args, script, *self.regrtest_args, *self.tests] self.run_tests(args) - @unittest.skipUnless(sysconfig.is_python_build(), - 'run_tests.py script is not installed') - def test_tools_script_run_tests(self): - # Tools/scripts/run_tests.py - script = os.path.join(ROOT_DIR, 'Tools', 'scripts', 'run_tests.py') - args = [script, *self.regrtest_args, *self.tests] - self.run_tests(args) - def run_batch(self, *args): proc = self.run_command(args) self.check_output(proc.stdout) @@ -700,6 +874,40 @@ def run_tests(self, *testargs, **kw): cmdargs = ['-m', 'test', '--testdir=%s' % self.tmptestdir, *testargs] return self.run_python(cmdargs, **kw) + def test_success(self): + code = textwrap.dedent(""" + import unittest + + class PassingTests(unittest.TestCase): + def test_test1(self): + pass + + def test_test2(self): + pass + + def test_test3(self): + pass + """) + tests = [self.create_test(f'ok{i}', code=code) for i in range(1, 6)] + + output = self.run_tests(*tests) + self.check_executed_tests(output, tests, + stats=3 * len(tests)) + + def test_skip(self): + code = textwrap.dedent(""" + import unittest + raise unittest.SkipTest("nope") + """) + test_ok = self.create_test('ok') + test_skip = self.create_test('skip', code=code) + tests = [test_ok, test_skip] + + output = self.run_tests(*tests) + self.check_executed_tests(output, tests, + skipped=[test_skip], + stats=1) + def test_failing_test(self): # test a failing test code = textwrap.dedent(""" @@ -714,7 +922,8 @@ def test_failing(self): tests = [test_ok, test_failing] output = self.run_tests(*tests, exitcode=EXITCODE_BAD_TEST) - self.check_executed_tests(output, tests, failed=test_failing) + self.check_executed_tests(output, tests, failed=test_failing, + stats=TestStats(2, 1)) def test_resources(self): # test -u command line option @@ -733,17 +942,19 @@ def test_pass(self): # -u all: 2 resources enabled output = self.run_tests('-u', 'all', *test_names) - self.check_executed_tests(output, test_names) + self.check_executed_tests(output, test_names, stats=2) # -u audio: 1 resource enabled output = self.run_tests('-uaudio', *test_names) self.check_executed_tests(output, test_names, - skipped=tests['network']) + resource_denied=tests['network'], + stats=1) # no option: 0 resources enabled - output = self.run_tests(*test_names) + output = self.run_tests(*test_names, exitcode=EXITCODE_NO_TESTS_RAN) self.check_executed_tests(output, test_names, - skipped=test_names) + resource_denied=test_names, + stats=0) def test_random(self): # test -r and --randseed command line option @@ -760,7 +971,7 @@ def test_random(self): test_random = int(match.group(1)) # try to reproduce with the random seed - output = self.run_tests('-r', '--randseed=%s' % randseed, test, + output = self.run_tests('-r', f'--randseed={randseed}', test, exitcode=EXITCODE_NO_TESTS_RAN) randseed2 = self.parse_random_seed(output) self.assertEqual(randseed2, randseed) @@ -769,6 +980,35 @@ def test_random(self): test_random2 = int(match.group(1)) self.assertEqual(test_random2, test_random) + # check that random.seed is used by default + output = self.run_tests(test, exitcode=EXITCODE_NO_TESTS_RAN) + randseed = self.parse_random_seed(output) + self.assertTrue(randseed.isdigit(), randseed) + + # check SOURCE_DATE_EPOCH (integer) + timestamp = '1697839080' + env = dict(os.environ, SOURCE_DATE_EPOCH=timestamp) + output = self.run_tests('-r', test, exitcode=EXITCODE_NO_TESTS_RAN, + env=env) + randseed = self.parse_random_seed(output) + self.assertEqual(randseed, timestamp) + self.check_line(output, 'TESTRANDOM: 520') + + # check SOURCE_DATE_EPOCH (string) + env = dict(os.environ, SOURCE_DATE_EPOCH='XYZ') + output = self.run_tests('-r', test, exitcode=EXITCODE_NO_TESTS_RAN, + env=env) + randseed = self.parse_random_seed(output) + self.assertEqual(randseed, 'XYZ') + self.check_line(output, 'TESTRANDOM: 22') + + # check SOURCE_DATE_EPOCH (empty string): ignore the env var + env = dict(os.environ, SOURCE_DATE_EPOCH='') + output = self.run_tests('-r', test, exitcode=EXITCODE_NO_TESTS_RAN, + env=env) + randseed = self.parse_random_seed(output) + self.assertTrue(randseed.isdigit(), randseed) + def test_fromfile(self): # test --fromfile tests = [self.create_test() for index in range(5)] @@ -791,7 +1031,8 @@ def test_fromfile(self): previous = name output = self.run_tests('--fromfile', filename) - self.check_executed_tests(output, tests) + stats = len(tests) + self.check_executed_tests(output, tests, stats=stats) # test format '[2/7] test_opcodes' with open(filename, "w") as fp: @@ -799,7 +1040,7 @@ def test_fromfile(self): print("[%s/%s] %s" % (index, len(tests), name), file=fp) output = self.run_tests('--fromfile', filename) - self.check_executed_tests(output, tests) + self.check_executed_tests(output, tests, stats=stats) # test format 'test_opcodes' with open(filename, "w") as fp: @@ -807,7 +1048,7 @@ def test_fromfile(self): print(name, file=fp) output = self.run_tests('--fromfile', filename) - self.check_executed_tests(output, tests) + self.check_executed_tests(output, tests, stats=stats) # test format 'Lib/test/test_opcodes.py' with open(filename, "w") as fp: @@ -815,20 +1056,20 @@ def test_fromfile(self): print('Lib/test/%s.py' % name, file=fp) output = self.run_tests('--fromfile', filename) - self.check_executed_tests(output, tests) + self.check_executed_tests(output, tests, stats=stats) def test_interrupted(self): code = TEST_INTERRUPTED test = self.create_test('sigint', code=code) output = self.run_tests(test, exitcode=EXITCODE_INTERRUPTED) self.check_executed_tests(output, test, omitted=test, - interrupted=True) + interrupted=True, stats=0) def test_slowest(self): # test --slowest tests = [self.create_test() for index in range(3)] output = self.run_tests("--slowest", *tests) - self.check_executed_tests(output, tests) + self.check_executed_tests(output, tests, stats=len(tests)) regex = ('10 slowest tests:\n' '(?:- %s: .*\n){%s}' % (self.TESTNAME_REGEX, len(tests))) @@ -847,7 +1088,8 @@ def test_slowest_interrupted(self): args = ("--slowest", test) output = self.run_tests(*args, exitcode=EXITCODE_INTERRUPTED) self.check_executed_tests(output, test, - omitted=test, interrupted=True) + omitted=test, interrupted=True, + stats=0) regex = ('10 slowest tests:\n') self.check_line(output, regex) @@ -856,7 +1098,7 @@ def test_coverage(self): # test --coverage test = self.create_test('coverage') output = self.run_tests("--coverage", test) - self.check_executed_tests(output, [test]) + self.check_executed_tests(output, [test], stats=1) regex = (r'lines +cov% +module +\(path\)\n' r'(?: *[0-9]+ *[0-9]{1,2}% *[^ ]+ +\([^)]+\)+)+') self.check_line(output, regex) @@ -885,18 +1127,36 @@ def test_run(self): builtins.__dict__['RUN'] = 1 """) test = self.create_test('forever', code=code) - output = self.run_tests('--forever', test, exitcode=EXITCODE_BAD_TEST) - self.check_executed_tests(output, [test]*3, failed=test) - def check_leak(self, code, what): + # --forever + output = self.run_tests('--forever', test, exitcode=EXITCODE_BAD_TEST) + self.check_executed_tests(output, [test]*3, failed=test, + stats=TestStats(3, 1), + forever=True) + + # --forever --rerun + output = self.run_tests('--forever', '--rerun', test, exitcode=0) + self.check_executed_tests(output, [test]*3, + rerun=Rerun(test, + match='test_run', + success=True), + stats=TestStats(4, 1), + forever=True) + + @without_optimizer + def check_leak(self, code, what, *, run_workers=False): test = self.create_test('huntrleaks', code=code) filename = 'reflog.txt' self.addCleanup(os_helper.unlink, filename) - output = self.run_tests('--huntrleaks', '3:3:', test, + cmd = ['--huntrleaks', '3:3:'] + if run_workers: + cmd.append('-j1') + cmd.append(test) + output = self.run_tests(*cmd, exitcode=EXITCODE_BAD_TEST, stderr=subprocess.STDOUT) - self.check_executed_tests(output, [test], failed=test) + self.check_executed_tests(output, [test], failed=test, stats=1) line = 'beginning 6 repetitions\n123456\n......\n' self.check_line(output, re.escape(line)) @@ -909,7 +1169,7 @@ def check_leak(self, code, what): self.assertIn(line2, reflog) @unittest.skipUnless(support.Py_DEBUG, 'need a debug build') - def test_huntrleaks(self): + def check_huntrleaks(self, *, run_workers: bool): # test --huntrleaks code = textwrap.dedent(""" import unittest @@ -920,7 +1180,13 @@ class RefLeakTest(unittest.TestCase): def test_leak(self): GLOBAL_LIST.append(object()) """) - self.check_leak(code, 'references') + self.check_leak(code, 'references', run_workers=run_workers) + + def test_huntrleaks(self): + self.check_huntrleaks(run_workers=False) + + def test_huntrleaks_mp(self): + self.check_huntrleaks(run_workers=True) @unittest.skipUnless(support.Py_DEBUG, 'need a debug build') def test_huntrleaks_fd_leak(self): @@ -978,7 +1244,7 @@ def test_crashed(self): tests = [crash_test] output = self.run_tests("-j2", *tests, exitcode=EXITCODE_BAD_TEST) self.check_executed_tests(output, tests, failed=crash_test, - randomize=True) + parallel=True, stats=0) def parse_methods(self, output): regex = re.compile("^(test[^ ]+).*ok$", flags=re.MULTILINE) @@ -998,8 +1264,6 @@ def test_method3(self): def test_method4(self): pass """) - all_methods = ['test_method1', 'test_method2', - 'test_method3', 'test_method4'] testname = self.create_test(code=code) # only run a subset @@ -1073,13 +1337,23 @@ def test_env_changed(self): # don't fail by default output = self.run_tests(testname) - self.check_executed_tests(output, [testname], env_changed=testname) + self.check_executed_tests(output, [testname], + env_changed=testname, stats=1) # fail with --fail-env-changed output = self.run_tests("--fail-env-changed", testname, exitcode=EXITCODE_ENV_CHANGED) self.check_executed_tests(output, [testname], env_changed=testname, - fail_env_changed=True) + fail_env_changed=True, stats=1) + + # rerun + output = self.run_tests("--rerun", testname) + self.check_executed_tests(output, [testname], + env_changed=testname, + rerun=Rerun(testname, + match=None, + success=True), + stats=2) def test_rerun_fail(self): # FAILURE then FAILURE @@ -1096,30 +1370,55 @@ def test_fail_always(self): """) testname = self.create_test(code=code) - output = self.run_tests("-w", testname, exitcode=EXITCODE_BAD_TEST) + output = self.run_tests("--rerun", testname, exitcode=EXITCODE_BAD_TEST) self.check_executed_tests(output, [testname], - failed=testname, rerun={testname: "test_fail_always"}) + rerun=Rerun(testname, + "test_fail_always", + success=False), + stats=TestStats(3, 2)) def test_rerun_success(self): # FAILURE then SUCCESS - code = textwrap.dedent(""" - import builtins + marker_filename = os.path.abspath("regrtest_marker_filename") + self.addCleanup(os_helper.unlink, marker_filename) + self.assertFalse(os.path.exists(marker_filename)) + + code = textwrap.dedent(f""" + import os.path import unittest + marker_filename = {marker_filename!r} + class Tests(unittest.TestCase): def test_succeed(self): return def test_fail_once(self): - if not hasattr(builtins, '_test_failed'): - builtins._test_failed = True + if not os.path.exists(marker_filename): + open(marker_filename, "w").close() self.fail("bug") """) testname = self.create_test(code=code) - output = self.run_tests("-w", testname, exitcode=0) + # FAILURE then SUCCESS => exit code 0 + output = self.run_tests("--rerun", testname, exitcode=0) self.check_executed_tests(output, [testname], - rerun={testname: "test_fail_once"}) + rerun=Rerun(testname, + match="test_fail_once", + success=True), + stats=TestStats(3, 1)) + os_helper.unlink(marker_filename) + + # with --fail-rerun, exit code EXITCODE_RERUN_FAIL + # on "FAILURE then SUCCESS" state. + output = self.run_tests("--rerun", "--fail-rerun", testname, + exitcode=EXITCODE_RERUN_FAIL) + self.check_executed_tests(output, [testname], + rerun=Rerun(testname, + match="test_fail_once", + success=True), + stats=TestStats(3, 1)) + os_helper.unlink(marker_filename) def test_rerun_setup_class_hook_failure(self): # FAILURE then FAILURE @@ -1136,10 +1435,13 @@ def test_success(self): """) testname = self.create_test(code=code) - output = self.run_tests("-w", testname, exitcode=EXITCODE_BAD_TEST) + output = self.run_tests("--rerun", testname, exitcode=EXITCODE_BAD_TEST) self.check_executed_tests(output, testname, failed=[testname], - rerun={testname: "ExampleTests"}) + rerun=Rerun(testname, + match="ExampleTests", + success=False), + stats=0) def test_rerun_teardown_class_hook_failure(self): # FAILURE then FAILURE @@ -1156,10 +1458,13 @@ def test_success(self): """) testname = self.create_test(code=code) - output = self.run_tests("-w", testname, exitcode=EXITCODE_BAD_TEST) + output = self.run_tests("--rerun", testname, exitcode=EXITCODE_BAD_TEST) self.check_executed_tests(output, testname, failed=[testname], - rerun={testname: "ExampleTests"}) + rerun=Rerun(testname, + match="ExampleTests", + success=False), + stats=2) def test_rerun_setup_module_hook_failure(self): # FAILURE then FAILURE @@ -1175,10 +1480,13 @@ def test_success(self): """) testname = self.create_test(code=code) - output = self.run_tests("-w", testname, exitcode=EXITCODE_BAD_TEST) + output = self.run_tests("--rerun", testname, exitcode=EXITCODE_BAD_TEST) self.check_executed_tests(output, testname, failed=[testname], - rerun={testname: testname}) + rerun=Rerun(testname, + match=None, + success=False), + stats=0) def test_rerun_teardown_module_hook_failure(self): # FAILURE then FAILURE @@ -1194,10 +1502,13 @@ def test_success(self): """) testname = self.create_test(code=code) - output = self.run_tests("-w", testname, exitcode=EXITCODE_BAD_TEST) - self.check_executed_tests(output, testname, + output = self.run_tests("--rerun", testname, exitcode=EXITCODE_BAD_TEST) + self.check_executed_tests(output, [testname], failed=[testname], - rerun={testname: testname}) + rerun=Rerun(testname, + match=None, + success=False), + stats=2) def test_rerun_setup_hook_failure(self): # FAILURE then FAILURE @@ -1213,10 +1524,13 @@ def test_success(self): """) testname = self.create_test(code=code) - output = self.run_tests("-w", testname, exitcode=EXITCODE_BAD_TEST) + output = self.run_tests("--rerun", testname, exitcode=EXITCODE_BAD_TEST) self.check_executed_tests(output, testname, failed=[testname], - rerun={testname: "test_success"}) + rerun=Rerun(testname, + match="test_success", + success=False), + stats=2) def test_rerun_teardown_hook_failure(self): # FAILURE then FAILURE @@ -1232,10 +1546,13 @@ def test_success(self): """) testname = self.create_test(code=code) - output = self.run_tests("-w", testname, exitcode=EXITCODE_BAD_TEST) + output = self.run_tests("--rerun", testname, exitcode=EXITCODE_BAD_TEST) self.check_executed_tests(output, testname, failed=[testname], - rerun={testname: "test_success"}) + rerun=Rerun(testname, + match="test_success", + success=False), + stats=2) def test_rerun_async_setup_hook_failure(self): # FAILURE then FAILURE @@ -1251,10 +1568,12 @@ async def test_success(self): """) testname = self.create_test(code=code) - output = self.run_tests("-w", testname, exitcode=EXITCODE_BAD_TEST) + output = self.run_tests("--rerun", testname, exitcode=EXITCODE_BAD_TEST) self.check_executed_tests(output, testname, - failed=[testname], - rerun={testname: "test_success"}) + rerun=Rerun(testname, + match="test_success", + success=False), + stats=2) def test_rerun_async_teardown_hook_failure(self): # FAILURE then FAILURE @@ -1270,10 +1589,13 @@ async def test_success(self): """) testname = self.create_test(code=code) - output = self.run_tests("-w", testname, exitcode=EXITCODE_BAD_TEST) + output = self.run_tests("--rerun", testname, exitcode=EXITCODE_BAD_TEST) self.check_executed_tests(output, testname, failed=[testname], - rerun={testname: "test_success"}) + rerun=Rerun(testname, + match="test_success", + success=False), + stats=2) def test_no_tests_ran(self): code = textwrap.dedent(""" @@ -1287,7 +1609,9 @@ def test_bug(self): output = self.run_tests(testname, "-m", "nosuchtest", exitcode=EXITCODE_NO_TESTS_RAN) - self.check_executed_tests(output, [testname], no_test_ran=testname) + self.check_executed_tests(output, [testname], + run_no_tests=testname, + stats=0, filtered=True) def test_no_tests_ran_skip(self): code = textwrap.dedent(""" @@ -1300,7 +1624,8 @@ def test_skipped(self): testname = self.create_test(code=code) output = self.run_tests(testname) - self.check_executed_tests(output, [testname]) + self.check_executed_tests(output, [testname], + stats=TestStats(1, skipped=1)) def test_no_tests_ran_multiple_tests_nonexistent(self): code = textwrap.dedent(""" @@ -1316,7 +1641,8 @@ def test_bug(self): output = self.run_tests(testname, testname2, "-m", "nosuchtest", exitcode=EXITCODE_NO_TESTS_RAN) self.check_executed_tests(output, [testname, testname2], - no_test_ran=[testname, testname2]) + run_no_tests=[testname, testname2], + stats=0, filtered=True) def test_no_test_ran_some_test_exist_some_not(self): code = textwrap.dedent(""" @@ -1339,7 +1665,8 @@ def test_other_bug(self): output = self.run_tests(testname, testname2, "-m", "nosuchtest", "-m", "test_other_bug", exitcode=0) self.check_executed_tests(output, [testname, testname2], - no_test_ran=[testname]) + run_no_tests=[testname], + stats=1, filtered=True) @support.cpython_only def test_uncollectable(self): @@ -1366,7 +1693,8 @@ def test_garbage(self): exitcode=EXITCODE_ENV_CHANGED) self.check_executed_tests(output, [testname], env_changed=[testname], - fail_env_changed=True) + fail_env_changed=True, + stats=1) def test_multiprocessing_timeout(self): code = textwrap.dedent(r""" @@ -1392,7 +1720,7 @@ def test_sleep(self): output = self.run_tests("-j2", "--timeout=1.0", testname, exitcode=EXITCODE_BAD_TEST) self.check_executed_tests(output, [testname], - failed=testname) + failed=testname, stats=0) self.assertRegex(output, re.compile('%s timed out' % testname, re.MULTILINE)) @@ -1426,7 +1754,8 @@ def test_unraisable_exc(self): exitcode=EXITCODE_ENV_CHANGED) self.check_executed_tests(output, [testname], env_changed=[testname], - fail_env_changed=True) + fail_env_changed=True, + stats=1) self.assertIn("Warning -- Unraisable exception", output) self.assertIn("Exception: weakref callback bug", output) @@ -1458,7 +1787,8 @@ def test_threading_excepthook(self): exitcode=EXITCODE_ENV_CHANGED) self.check_executed_tests(output, [testname], env_changed=[testname], - fail_env_changed=True) + fail_env_changed=True, + stats=1) self.assertIn("Warning -- Uncaught thread exception", output) self.assertIn("Exception: bug in thread", output) @@ -1499,7 +1829,8 @@ def test_print_warning(self): output = self.run_tests(*cmd, exitcode=EXITCODE_ENV_CHANGED) self.check_executed_tests(output, [testname], env_changed=[testname], - fail_env_changed=True) + fail_env_changed=True, + stats=1) self.assertRegex(output, regex) def test_unicode_guard_env(self): @@ -1546,15 +1877,15 @@ def test_leak_tmp_file(self): self.check_executed_tests(output, testnames, env_changed=testnames, fail_env_changed=True, - randomize=True) + parallel=True, + stats=len(testnames)) for testname in testnames: self.assertIn(f"Warning -- {testname} leaked temporary " f"files (1): mytmpfile", output) - def test_mp_decode_error(self): - # gh-101634: If a worker stdout cannot be decoded, report a failed test - # and a non-zero exit code. + def test_worker_decode_error(self): + # gh-109425: Use "backslashreplace" error handler to decode stdout. if sys.platform == 'win32': encoding = locale.getencoding() else: @@ -1562,30 +1893,284 @@ def test_mp_decode_error(self): if encoding is None: encoding = sys.__stdout__.encoding if encoding is None: - self.skipTest(f"cannot get regrtest worker encoding") - - nonascii = b"byte:\xa0\xa9\xff\n" + self.skipTest("cannot get regrtest worker encoding") + + nonascii = bytes(ch for ch in range(128, 256)) + corrupted_output = b"nonascii:%s\n" % (nonascii,) + # gh-108989: On Windows, assertion errors are written in UTF-16: when + # decoded each letter is follow by a NUL character. + assertion_failed = 'Assertion failed: tstate_is_alive(tstate)\n' + corrupted_output += assertion_failed.encode('utf-16-le') try: - nonascii.decode(encoding) + corrupted_output.decode(encoding) except UnicodeDecodeError: pass else: - self.skipTest(f"{encoding} can decode non-ASCII bytes {nonascii!a}") + self.skipTest(f"{encoding} can decode non-ASCII bytes") + + expected_line = corrupted_output.decode(encoding, 'backslashreplace') code = textwrap.dedent(fr""" import sys + import unittest + + class Tests(unittest.TestCase): + def test_pass(self): + pass + # bytes which cannot be decoded from UTF-8 - nonascii = {nonascii!a} - sys.stdout.buffer.write(nonascii) + corrupted_output = {corrupted_output!a} + sys.stdout.buffer.write(corrupted_output) sys.stdout.buffer.flush() """) testname = self.create_test(code=code) + output = self.run_tests("--fail-env-changed", "-v", "-j1", testname) + self.check_executed_tests(output, [testname], + parallel=True, + stats=1) + self.check_line(output, expected_line, regex=False) + + def test_doctest(self): + code = textwrap.dedent(r''' + import doctest + import sys + from test import support + + def my_function(): + """ + Pass: + + >>> 1 + 1 + 2 + + Failure: + + >>> 2 + 3 + 23 + >>> 1 + 1 + 11 + + Skipped test (ignored): + + >>> id(1.0) # doctest: +SKIP + 7948648 + """ + + def load_tests(loader, tests, pattern): + tests.addTest(doctest.DocTestSuite()) + return tests + ''') + testname = self.create_test(code=code) + output = self.run_tests("--fail-env-changed", "-v", "-j1", testname, exitcode=EXITCODE_BAD_TEST) self.check_executed_tests(output, [testname], failed=[testname], - randomize=True) + parallel=True, + stats=TestStats(1, 1, 0)) + + def _check_random_seed(self, run_workers: bool): + # gh-109276: When -r/--randomize is used, random.seed() is called + # with the same random seed before running each test file. + code = textwrap.dedent(r''' + import random + import unittest + + class RandomSeedTest(unittest.TestCase): + def test_randint(self): + numbers = [random.randint(0, 1000) for _ in range(10)] + print(f"Random numbers: {numbers}") + ''') + tests = [self.create_test(name=f'test_random{i}', code=code) + for i in range(1, 3+1)] + + random_seed = 856_656_202 + cmd = ["--randomize", f"--randseed={random_seed}"] + if run_workers: + # run as many worker processes than the number of tests + cmd.append(f'-j{len(tests)}') + cmd.extend(tests) + output = self.run_tests(*cmd) + + random.seed(random_seed) + # Make the assumption that nothing consume entropy between libregrest + # setup_tests() which calls random.seed() and RandomSeedTest calling + # random.randint(). + numbers = [random.randint(0, 1000) for _ in range(10)] + expected = f"Random numbers: {numbers}" + + regex = r'^Random numbers: .*$' + matches = re.findall(regex, output, flags=re.MULTILINE) + self.assertEqual(matches, [expected] * len(tests)) + + def test_random_seed(self): + self._check_random_seed(run_workers=False) + + def test_random_seed_workers(self): + self._check_random_seed(run_workers=True) + + def test_python_command(self): + code = textwrap.dedent(r""" + import sys + import unittest + + class WorkerTests(unittest.TestCase): + def test_dev_mode(self): + self.assertTrue(sys.flags.dev_mode) + """) + tests = [self.create_test(code=code) for _ in range(3)] + + # Custom Python command: "python -X dev" + python_cmd = [sys.executable, '-X', 'dev'] + # test.libregrtest.cmdline uses shlex.split() to parse the Python + # command line string + python_cmd = shlex.join(python_cmd) + + output = self.run_tests("--python", python_cmd, "-j0", *tests) + self.check_executed_tests(output, tests, + stats=len(tests), parallel=True) + + def test_unload_tests(self): + # Test that unloading test modules does not break tests + # that import from other tests. + # The test execution order matters for this test. + # Both test_regrtest_a and test_regrtest_c which are executed before + # and after test_regrtest_b import a submodule from the test_regrtest_b + # package and use it in testing. test_regrtest_b itself does not import + # that submodule. + # Previously test_regrtest_c failed because test_regrtest_b.util in + # sys.modules was left after test_regrtest_a (making the import + # statement no-op), but new test_regrtest_b without the util attribute + # was imported for test_regrtest_b. + testdir = os.path.join(os.path.dirname(__file__), + 'regrtestdata', 'import_from_tests') + tests = [f'test_regrtest_{name}' for name in ('a', 'b', 'c')] + args = ['-Wd', '-E', '-bb', '-m', 'test', '--testdir=%s' % testdir, *tests] + output = self.run_python(args) + self.check_executed_tests(output, tests, stats=3) + + def check_add_python_opts(self, option): + # --fast-ci and --slow-ci add "-u -W default -bb -E" options to Python + code = textwrap.dedent(r""" + import sys + import unittest + from test import support + try: + from _testinternalcapi import get_config + except ImportError: + get_config = None + + # WASI/WASM buildbots don't use -E option + use_environment = (support.is_emscripten or support.is_wasi) + + class WorkerTests(unittest.TestCase): + @unittest.skipUnless(get_config is None, 'need get_config()') + def test_config(self): + config = get_config()['config'] + # -u option + self.assertEqual(config['buffered_stdio'], 0) + # -W default option + self.assertTrue(config['warnoptions'], ['default']) + # -bb option + self.assertTrue(config['bytes_warning'], 2) + # -E option + self.assertTrue(config['use_environment'], use_environment) + + def test_python_opts(self): + # -u option + self.assertTrue(sys.__stdout__.write_through) + self.assertTrue(sys.__stderr__.write_through) + + # -W default option + self.assertTrue(sys.warnoptions, ['default']) + + # -bb option + self.assertEqual(sys.flags.bytes_warning, 2) + + # -E option + self.assertEqual(not sys.flags.ignore_environment, + use_environment) + """) + testname = self.create_test(code=code) + + # Use directly subprocess to control the exact command line + cmd = [sys.executable, + "-m", "test", option, + f'--testdir={self.tmptestdir}', + testname] + proc = subprocess.run(cmd, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + text=True) + self.assertEqual(proc.returncode, 0, proc) + + def test_add_python_opts(self): + for opt in ("--fast-ci", "--slow-ci"): + with self.subTest(opt=opt): + self.check_add_python_opts(opt) + + # gh-76319: Raising SIGSEGV on Android may not cause a crash. + @unittest.skipIf(support.is_android, + 'raising SIGSEGV on Android is unreliable') + def test_worker_output_on_failure(self): + try: + from faulthandler import _sigsegv + except ImportError: + self.skipTest("need faulthandler._sigsegv") + + code = textwrap.dedent(r""" + import faulthandler + import unittest + from test import support + + class CrashTests(unittest.TestCase): + def test_crash(self): + print("just before crash!", flush=True) + + with support.SuppressCrashReport(): + faulthandler._sigsegv(True) + """) + testname = self.create_test(code=code) + + # Sanitizers must not handle SIGSEGV (ex: for test_enable_fd()) + env = dict(os.environ) + option = 'handle_segv=0' + support.set_sanitizer_env_var(env, option) + + output = self.run_tests("-j1", testname, + exitcode=EXITCODE_BAD_TEST, + env=env) + self.check_executed_tests(output, testname, + failed=[testname], + stats=0, parallel=True) + if not support.MS_WINDOWS: + exitcode = -int(signal.SIGSEGV) + self.assertIn(f"Exit code {exitcode} (SIGSEGV)", output) + self.check_line(output, "just before crash!", full=True, regex=False) + + def test_verbose3(self): + code = textwrap.dedent(r""" + import unittest + from test import support + + class VerboseTests(unittest.TestCase): + def test_pass(self): + print("SPAM SPAM SPAM") + """) + testname = self.create_test(code=code) + + # Run sequentially + output = self.run_tests("--verbose3", testname) + self.check_executed_tests(output, testname, stats=1) + self.assertNotIn('SPAM SPAM SPAM', output) + + # -R option needs a debug build + if support.Py_DEBUG: + # Check for reference leaks, run in parallel + output = self.run_tests("-R", "3:3", "-j1", "--verbose3", testname) + self.check_executed_tests(output, testname, stats=1, parallel=True) + self.assertNotIn('SPAM SPAM SPAM', output) class TestUtils(unittest.TestCase): @@ -1611,6 +2196,160 @@ def test_format_duration(self): self.assertEqual(utils.format_duration(3 * 3600 + 1), '3 hour 1 sec') + def test_normalize_test_name(self): + normalize = normalize_test_name + self.assertEqual(normalize('test_access (test.test_os.FileTests.test_access)'), + 'test_access') + self.assertEqual(normalize('setUpClass (test.test_os.ChownFileTests)', is_error=True), + 'ChownFileTests') + self.assertEqual(normalize('test_success (test.test_bug.ExampleTests.test_success)', is_error=True), + 'test_success') + self.assertIsNone(normalize('setUpModule (test.test_x)', is_error=True)) + self.assertIsNone(normalize('tearDownModule (test.test_module)', is_error=True)) + + def test_get_signal_name(self): + for exitcode, expected in ( + (-int(signal.SIGINT), 'SIGINT'), + (-int(signal.SIGSEGV), 'SIGSEGV'), + (3221225477, "STATUS_ACCESS_VIOLATION"), + (0xC00000FD, "STATUS_STACK_OVERFLOW"), + ): + self.assertEqual(utils.get_signal_name(exitcode), expected, exitcode) + + def test_format_resources(self): + format_resources = utils.format_resources + ALL_RESOURCES = utils.ALL_RESOURCES + self.assertEqual( + format_resources(("network",)), + 'resources (1): network') + self.assertEqual( + format_resources(("audio", "decimal", "network")), + 'resources (3): audio,decimal,network') + self.assertEqual( + format_resources(ALL_RESOURCES), + 'resources: all') + self.assertEqual( + format_resources(tuple(name for name in ALL_RESOURCES + if name != "cpu")), + 'resources: all,-cpu') + self.assertEqual( + format_resources((*ALL_RESOURCES, "tzdata")), + 'resources: all,tzdata') + + def test_match_test(self): + class Test: + def __init__(self, test_id): + self.test_id = test_id + + def id(self): + return self.test_id + + test_access = Test('test.test_os.FileTests.test_access') + test_chdir = Test('test.test_os.Win32ErrorTests.test_chdir') + test_copy = Test('test.test_shutil.TestCopy.test_copy') + + # Test acceptance + with support.swap_attr(support, '_test_matchers', ()): + # match all + set_match_tests([]) + self.assertTrue(match_test(test_access)) + self.assertTrue(match_test(test_chdir)) + + # match all using None + set_match_tests(None) + self.assertTrue(match_test(test_access)) + self.assertTrue(match_test(test_chdir)) + + # match the full test identifier + set_match_tests([(test_access.id(), True)]) + self.assertTrue(match_test(test_access)) + self.assertFalse(match_test(test_chdir)) + + # match the module name + set_match_tests([('test_os', True)]) + self.assertTrue(match_test(test_access)) + self.assertTrue(match_test(test_chdir)) + self.assertFalse(match_test(test_copy)) + + # Test '*' pattern + set_match_tests([('test_*', True)]) + self.assertTrue(match_test(test_access)) + self.assertTrue(match_test(test_chdir)) + + # Test case sensitivity + set_match_tests([('filetests', True)]) + self.assertFalse(match_test(test_access)) + set_match_tests([('FileTests', True)]) + self.assertTrue(match_test(test_access)) + + # Test pattern containing '.' and a '*' metacharacter + set_match_tests([('*test_os.*.test_*', True)]) + self.assertTrue(match_test(test_access)) + self.assertTrue(match_test(test_chdir)) + self.assertFalse(match_test(test_copy)) + + # Multiple patterns + set_match_tests([(test_access.id(), True), (test_chdir.id(), True)]) + self.assertTrue(match_test(test_access)) + self.assertTrue(match_test(test_chdir)) + self.assertFalse(match_test(test_copy)) + + set_match_tests([('test_access', True), ('DONTMATCH', True)]) + self.assertTrue(match_test(test_access)) + self.assertFalse(match_test(test_chdir)) + + # Test rejection + with support.swap_attr(support, '_test_matchers', ()): + # match the full test identifier + set_match_tests([(test_access.id(), False)]) + self.assertFalse(match_test(test_access)) + self.assertTrue(match_test(test_chdir)) + + # match the module name + set_match_tests([('test_os', False)]) + self.assertFalse(match_test(test_access)) + self.assertFalse(match_test(test_chdir)) + self.assertTrue(match_test(test_copy)) + + # Test '*' pattern + set_match_tests([('test_*', False)]) + self.assertFalse(match_test(test_access)) + self.assertFalse(match_test(test_chdir)) + + # Test case sensitivity + set_match_tests([('filetests', False)]) + self.assertTrue(match_test(test_access)) + set_match_tests([('FileTests', False)]) + self.assertFalse(match_test(test_access)) + + # Test pattern containing '.' and a '*' metacharacter + set_match_tests([('*test_os.*.test_*', False)]) + self.assertFalse(match_test(test_access)) + self.assertFalse(match_test(test_chdir)) + self.assertTrue(match_test(test_copy)) + + # Multiple patterns + set_match_tests([(test_access.id(), False), (test_chdir.id(), False)]) + self.assertFalse(match_test(test_access)) + self.assertFalse(match_test(test_chdir)) + self.assertTrue(match_test(test_copy)) + + set_match_tests([('test_access', False), ('DONTMATCH', False)]) + self.assertFalse(match_test(test_access)) + self.assertTrue(match_test(test_chdir)) + + # Test mixed filters + with support.swap_attr(support, '_test_matchers', ()): + set_match_tests([('*test_os', False), ('test_access', True)]) + self.assertTrue(match_test(test_access)) + self.assertFalse(match_test(test_chdir)) + self.assertTrue(match_test(test_copy)) + + set_match_tests([('*test_os', True), ('test_access', False)]) + self.assertFalse(match_test(test_access)) + self.assertTrue(match_test(test_chdir)) + self.assertFalse(match_test(test_copy)) + if __name__ == '__main__': unittest.main() diff --git a/Lib/test/test_repl.py b/Lib/test/test_repl.py index ddb4aa68048df1..a28d1595f44533 100644 --- a/Lib/test/test_repl.py +++ b/Lib/test/test_repl.py @@ -5,6 +5,7 @@ import unittest import subprocess from textwrap import dedent +from test import support from test.support import cpython_only, has_subprocess_support, SuppressCrashReport from test.support.script_helper import kill_python @@ -59,6 +60,9 @@ def run_on_interactive_mode(source): class TestInteractiveInterpreter(unittest.TestCase): @cpython_only + # Python built with Py_TRACE_REFS fail with a fatal error in + # _PyRefchain_Trace() on memory allocation error. + @unittest.skipIf(support.Py_TRACE_REFS, 'cannot test Py_TRACE_REFS build') def test_no_memory(self): # Issue #30696: Fix the interactive interpreter looping endlessly when # no memory. Check also that the fix does not break the interactive @@ -127,6 +131,69 @@ def test_close_stdin(self): self.assertEqual(process.returncode, 0) self.assertIn('before close', output) + def test_interactive_traceback_reporting(self): + user_input = "1 / 0 / 3 / 4" + p = spawn_repl() + p.stdin.write(user_input) + output = kill_python(p) + self.assertEqual(p.returncode, 0) + + traceback_lines = output.splitlines()[-6:-1] + expected_lines = [ + "Traceback (most recent call last):", + " File \"\", line 1, in ", + " 1 / 0 / 3 / 4", + " ~~^~~", + "ZeroDivisionError: division by zero", + ] + self.assertEqual(traceback_lines, expected_lines) + + def test_interactive_traceback_reporting_multiple_input(self): + user_input1 = dedent(""" + def foo(x): + 1 / x + + """) + p = spawn_repl() + p.stdin.write(user_input1) + user_input2 = "foo(0)" + p.stdin.write(user_input2) + output = kill_python(p) + self.assertEqual(p.returncode, 0) + + traceback_lines = output.splitlines()[-8:-1] + expected_lines = [ + ' File "", line 1, in ', + ' foo(0)', + ' ~~~^^^', + ' File "", line 2, in foo', + ' 1 / x', + ' ~~^~~', + 'ZeroDivisionError: division by zero' + ] + self.assertEqual(traceback_lines, expected_lines) + + def test_interactive_source_is_in_linecache(self): + user_input = dedent(""" + def foo(x): + return x + 1 + + def bar(x): + return foo(x) + 2 + """) + p = spawn_repl() + p.stdin.write(user_input) + user_input2 = dedent(""" + import linecache + print(linecache.cache['-1']) + """) + p.stdin.write(user_input2) + output = kill_python(p) + self.assertEqual(p.returncode, 0) + expected = "(30, None, [\'def foo(x):\\n\', \' return x + 1\\n\', \'\\n\'], \'\')" + self.assertIn(expected, output, expected) + + class TestInteractiveModeSyntaxErrors(unittest.TestCase): diff --git a/Lib/test/test_reprlib.py b/Lib/test/test_reprlib.py index e7216d427200c1..3e93b561c143d8 100644 --- a/Lib/test/test_reprlib.py +++ b/Lib/test/test_reprlib.py @@ -765,5 +765,25 @@ def test_assigned_attributes(self): for name in assigned: self.assertIs(getattr(wrapper, name), getattr(wrapped, name)) + def test__wrapped__(self): + class X: + def __repr__(self): + return 'X()' + f = __repr__ # save reference to check it later + __repr__ = recursive_repr()(__repr__) + + self.assertIs(X.f, X.__repr__.__wrapped__) + + def test__type_params__(self): + class My: + @recursive_repr() + def __repr__[T: str](self, default: T = '') -> str: + return default + + type_params = My().__repr__.__type_params__ + self.assertEqual(len(type_params), 1) + self.assertEqual(type_params[0].__name__, 'T') + self.assertEqual(type_params[0].__bound__, str) + if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_richcmp.py b/Lib/test/test_richcmp.py index 58729a9fea62fa..6fb31c80d7e670 100644 --- a/Lib/test/test_richcmp.py +++ b/Lib/test/test_richcmp.py @@ -221,6 +221,7 @@ def do(bad): self.assertRaises(Exc, func, Bad()) @support.no_tracing + @support.infinite_recursion() def test_recursion(self): # Check that comparison for recursive objects fails gracefully from collections import UserList diff --git a/Lib/test/test_rlcompleter.py b/Lib/test/test_rlcompleter.py index 6b5fc9a0247f4b..273ce2cf5c7dd2 100644 --- a/Lib/test/test_rlcompleter.py +++ b/Lib/test/test_rlcompleter.py @@ -2,6 +2,7 @@ from unittest.mock import patch import builtins import rlcompleter +from test.support import MISSING_C_DOCSTRINGS class CompleteMe: """ Trivial class used in testing rlcompleter.Completer. """ @@ -40,12 +41,12 @@ def test_global_matches(self): # test with a customized namespace self.assertEqual(self.completer.global_matches('CompleteM'), - ['CompleteMe()']) + ['CompleteMe(' if MISSING_C_DOCSTRINGS else 'CompleteMe()']) self.assertEqual(self.completer.global_matches('eg'), ['egg(']) # XXX: see issue5256 self.assertEqual(self.completer.global_matches('CompleteM'), - ['CompleteMe()']) + ['CompleteMe(' if MISSING_C_DOCSTRINGS else 'CompleteMe()']) def test_attr_matches(self): # test with builtins namespace @@ -53,7 +54,10 @@ def test_attr_matches(self): ['str.{}('.format(x) for x in dir(str) if x.startswith('s')]) self.assertEqual(self.stdcompleter.attr_matches('tuple.foospamegg'), []) - expected = sorted({'None.%s%s' % (x, '(' if x != '__doc__' else '') + expected = sorted({'None.%s%s' % (x, + '()' if x == '__init_subclass__' + else '' if x == '__doc__' + else '(') for x in dir(None)}) self.assertEqual(self.stdcompleter.attr_matches('None.'), expected) self.assertEqual(self.stdcompleter.attr_matches('None._'), expected) diff --git a/Lib/test/test_runpy.py b/Lib/test/test_runpy.py index 6aaa288c14e1d7..628c8cae38a751 100644 --- a/Lib/test/test_runpy.py +++ b/Lib/test/test_runpy.py @@ -12,7 +12,7 @@ import textwrap import unittest import warnings -from test.support import no_tracing, verbose, requires_subprocess +from test.support import no_tracing, verbose, requires_subprocess, requires_resource from test.support.import_helper import forget, make_legacy_pyc, unload from test.support.os_helper import create_empty_file, temp_dir from test.support.script_helper import make_script, make_zip_script @@ -733,6 +733,7 @@ def test_zipfile_error(self): self._check_import_error(zip_name, msg) @no_tracing + @requires_resource('cpu') def test_main_recursion_error(self): with temp_dir() as script_dir, temp_dir() as dummy_dir: mod_name = '__main__' diff --git a/Lib/test/test_selectors.py b/Lib/test/test_selectors.py index 4545cbadb796fd..677349c2bfca93 100644 --- a/Lib/test/test_selectors.py +++ b/Lib/test/test_selectors.py @@ -285,6 +285,35 @@ def test_select(self): self.assertEqual([(wr_key, selectors.EVENT_WRITE)], result) + def test_select_read_write(self): + # gh-110038: when a file descriptor is registered for both read and + # write, the two events must be seen on a single call to select(). + s = self.SELECTOR() + self.addCleanup(s.close) + + sock1, sock2 = self.make_socketpair() + sock2.send(b"foo") + my_key = s.register(sock1, selectors.EVENT_READ | selectors.EVENT_WRITE) + + seen_read, seen_write = False, False + result = s.select() + # We get the read and write either in the same result entry or in two + # distinct entries with the same key. + self.assertLessEqual(len(result), 2) + for key, events in result: + self.assertTrue(isinstance(key, selectors.SelectorKey)) + self.assertEqual(key, my_key) + self.assertFalse(events & ~(selectors.EVENT_READ | + selectors.EVENT_WRITE)) + if events & selectors.EVENT_READ: + self.assertFalse(seen_read) + seen_read = True + if events & selectors.EVENT_WRITE: + self.assertFalse(seen_write) + seen_write = True + self.assertTrue(seen_read) + self.assertTrue(seen_write) + def test_context_manager(self): s = self.SELECTOR() self.addCleanup(s.close) @@ -455,6 +484,7 @@ class ScalableSelectorMixIn: # see issue #18963 for why it's skipped on older OS X versions @support.requires_mac_ver(10, 5) @unittest.skipUnless(resource, "Test needs resource module") + @support.requires_resource('cpu') def test_above_fd_setsize(self): # A scalable implementation should have no problem with more than # FD_SETSIZE file descriptors. Since we don't know the value, we just diff --git a/Lib/test/test_set.py b/Lib/test/test_set.py index 2dd65240f5faec..d9102eb98a54a6 100644 --- a/Lib/test/test_set.py +++ b/Lib/test/test_set.py @@ -635,10 +635,6 @@ def __le__(self, some_set): myset >= myobj self.assertTrue(myobj.le_called) - @unittest.skipUnless(hasattr(set, "test_c_api"), - 'C API test only available in a debug build') - def test_c_api(self): - self.assertEqual(set().test_c_api(), True) class SetSubclass(set): pass diff --git a/Lib/test/test_shutil.py b/Lib/test/test_shutil.py index 93f20a6ff41332..8edd75e9907ec0 100644 --- a/Lib/test/test_shutil.py +++ b/Lib/test/test_shutil.py @@ -208,8 +208,7 @@ def test_rmtree_fails_on_symlink_onerror(self): errors = [] def onerror(*args): errors.append(args) - with self.assertWarns(DeprecationWarning): - shutil.rmtree(link, onerror=onerror) + shutil.rmtree(link, onerror=onerror) self.assertEqual(len(errors), 1) self.assertIs(errors[0][0], os.path.islink) self.assertEqual(errors[0][1], link) @@ -270,8 +269,7 @@ def test_rmtree_fails_on_junctions_onerror(self): errors = [] def onerror(*args): errors.append(args) - with self.assertWarns(DeprecationWarning): - shutil.rmtree(link, onerror=onerror) + shutil.rmtree(link, onerror=onerror) self.assertEqual(len(errors), 1) self.assertIs(errors[0][0], os.path.islink) self.assertEqual(errors[0][1], link) @@ -319,7 +317,7 @@ def test_rmtree_works_on_junctions(self): self.assertTrue(os.path.exists(dir3)) self.assertTrue(os.path.exists(file1)) - def test_rmtree_errors_onerror(self): + def test_rmtree_errors(self): # filename is guaranteed not to exist filename = tempfile.mktemp(dir=self.mkdtemp()) self.assertRaises(FileNotFoundError, shutil.rmtree, filename) @@ -328,8 +326,8 @@ def test_rmtree_errors_onerror(self): # existing file tmpdir = self.mkdtemp() - write_file((tmpdir, "tstfile"), "") filename = os.path.join(tmpdir, "tstfile") + write_file(filename, "") with self.assertRaises(NotADirectoryError) as cm: shutil.rmtree(filename) self.assertEqual(cm.exception.filename, filename) @@ -337,11 +335,23 @@ def test_rmtree_errors_onerror(self): # test that ignore_errors option is honored shutil.rmtree(filename, ignore_errors=True) self.assertTrue(os.path.exists(filename)) + + self.assertRaises(TypeError, shutil.rmtree, None) + self.assertRaises(TypeError, shutil.rmtree, None, ignore_errors=True) + exc = TypeError if shutil.rmtree.avoids_symlink_attacks else NotImplementedError + with self.assertRaises(exc): + shutil.rmtree(filename, dir_fd='invalid') + with self.assertRaises(exc): + shutil.rmtree(filename, dir_fd='invalid', ignore_errors=True) + + def test_rmtree_errors_onerror(self): + tmpdir = self.mkdtemp() + filename = os.path.join(tmpdir, "tstfile") + write_file(filename, "") errors = [] def onerror(*args): errors.append(args) - with self.assertWarns(DeprecationWarning): - shutil.rmtree(filename, onerror=onerror) + shutil.rmtree(filename, onerror=onerror) self.assertEqual(len(errors), 2) self.assertIs(errors[0][0], os.scandir) self.assertEqual(errors[0][1], filename) @@ -353,23 +363,9 @@ def onerror(*args): self.assertEqual(errors[1][2][1].filename, filename) def test_rmtree_errors_onexc(self): - # filename is guaranteed not to exist - filename = tempfile.mktemp(dir=self.mkdtemp()) - self.assertRaises(FileNotFoundError, shutil.rmtree, filename) - # test that ignore_errors option is honored - shutil.rmtree(filename, ignore_errors=True) - - # existing file tmpdir = self.mkdtemp() - write_file((tmpdir, "tstfile"), "") filename = os.path.join(tmpdir, "tstfile") - with self.assertRaises(NotADirectoryError) as cm: - shutil.rmtree(filename) - self.assertEqual(cm.exception.filename, filename) - self.assertTrue(os.path.exists(filename)) - # test that ignore_errors option is honored - shutil.rmtree(filename, ignore_errors=True) - self.assertTrue(os.path.exists(filename)) + write_file(filename, "") errors = [] def onexc(*args): errors.append(args) @@ -410,8 +406,7 @@ def test_on_error(self): self.addCleanup(os.chmod, self.child_file_path, old_child_file_mode) self.addCleanup(os.chmod, self.child_dir_path, old_child_dir_mode) - with self.assertWarns(DeprecationWarning): - shutil.rmtree(TESTFN, onerror=self.check_args_to_onerror) + shutil.rmtree(TESTFN, onerror=self.check_args_to_onerror) # Test whether onerror has actually been called. self.assertEqual(self.errorState, 3, "Expected call to onerror function did not happen.") @@ -537,8 +532,7 @@ def onexc(*args): self.addCleanup(os.chmod, self.child_file_path, old_child_file_mode) self.addCleanup(os.chmod, self.child_dir_path, old_child_dir_mode) - with self.assertWarns(DeprecationWarning): - shutil.rmtree(TESTFN, onerror=onerror, onexc=onexc) + shutil.rmtree(TESTFN, onerror=onerror, onexc=onexc) self.assertTrue(onexc_called) self.assertFalse(onerror_called) @@ -582,6 +576,41 @@ def _raiser(*args, **kwargs): self.assertFalse(shutil._use_fd_functions) self.assertFalse(shutil.rmtree.avoids_symlink_attacks) + @unittest.skipUnless(shutil._use_fd_functions, "requires safe rmtree") + def test_rmtree_fails_on_close(self): + # Test that the error handler is called for failed os.close() and that + # os.close() is only called once for a file descriptor. + tmp = self.mkdtemp() + dir1 = os.path.join(tmp, 'dir1') + os.mkdir(dir1) + dir2 = os.path.join(dir1, 'dir2') + os.mkdir(dir2) + def close(fd): + orig_close(fd) + nonlocal close_count + close_count += 1 + raise OSError + + close_count = 0 + with support.swap_attr(os, 'close', close) as orig_close: + with self.assertRaises(OSError): + shutil.rmtree(dir1) + self.assertTrue(os.path.isdir(dir2)) + self.assertEqual(close_count, 2) + + close_count = 0 + errors = [] + def onexc(*args): + errors.append(args) + with support.swap_attr(os, 'close', close) as orig_close: + shutil.rmtree(dir1, onexc=onexc) + self.assertEqual(len(errors), 2) + self.assertIs(errors[0][0], close) + self.assertEqual(errors[0][1], dir2) + self.assertIs(errors[1][0], close) + self.assertEqual(errors[1][1], dir1) + self.assertEqual(close_count, 2) + @unittest.skipUnless(shutil._use_fd_functions, "dir_fd is not supported") def test_rmtree_with_dir_fd(self): tmp_dir = self.mkdtemp() @@ -638,6 +667,63 @@ def test_rmtree_on_junction(self): finally: shutil.rmtree(TESTFN, ignore_errors=True) + @unittest.skipIf(sys.platform[:6] == 'cygwin', + "This test can't be run on Cygwin (issue #1071513).") + @os_helper.skip_if_dac_override + @os_helper.skip_unless_working_chmod + def test_rmtree_deleted_race_condition(self): + # bpo-37260 + # + # Test that a file or a directory deleted after it is enumerated + # by scandir() but before unlink() or rmdr() is called doesn't + # generate any errors. + def _onexc(fn, path, exc): + assert fn in (os.rmdir, os.unlink) + if not isinstance(exc, PermissionError): + raise + # Make the parent and the children writeable. + for p, mode in zip(paths, old_modes): + os.chmod(p, mode) + # Remove other dirs except one. + keep = next(p for p in dirs if p != path) + for p in dirs: + if p != keep: + os.rmdir(p) + # Remove other files except one. + keep = next(p for p in files if p != path) + for p in files: + if p != keep: + os.unlink(p) + + os.mkdir(TESTFN) + paths = [TESTFN] + [os.path.join(TESTFN, f'child{i}') + for i in range(6)] + dirs = paths[1::2] + files = paths[2::2] + for path in dirs: + os.mkdir(path) + for path in files: + write_file(path, '') + + old_modes = [os.stat(path).st_mode for path in paths] + + # Make the parent and the children non-writeable. + new_mode = stat.S_IREAD|stat.S_IEXEC + for path in reversed(paths): + os.chmod(path, new_mode) + + try: + shutil.rmtree(TESTFN, onexc=_onexc) + except: + # Test failed, so cleanup artifacts. + for path, mode in zip(paths, old_modes): + try: + os.chmod(path, mode) + except OSError: + pass + shutil.rmtree(TESTFN) + raise + class TestCopyTree(BaseTest, unittest.TestCase): @@ -1015,19 +1101,18 @@ def test_copymode_follow_symlinks(self): shutil.copymode(src, dst) self.assertEqual(os.stat(src).st_mode, os.stat(dst).st_mode) # On Windows, os.chmod does not follow symlinks (issue #15411) - if os.name != 'nt': - # follow src link - os.chmod(dst, stat.S_IRWXO) - shutil.copymode(src_link, dst) - self.assertEqual(os.stat(src).st_mode, os.stat(dst).st_mode) - # follow dst link - os.chmod(dst, stat.S_IRWXO) - shutil.copymode(src, dst_link) - self.assertEqual(os.stat(src).st_mode, os.stat(dst).st_mode) - # follow both links - os.chmod(dst, stat.S_IRWXO) - shutil.copymode(src_link, dst_link) - self.assertEqual(os.stat(src).st_mode, os.stat(dst).st_mode) + # follow src link + os.chmod(dst, stat.S_IRWXO) + shutil.copymode(src_link, dst) + self.assertEqual(os.stat(src).st_mode, os.stat(dst).st_mode) + # follow dst link + os.chmod(dst, stat.S_IRWXO) + shutil.copymode(src, dst_link) + self.assertEqual(os.stat(src).st_mode, os.stat(dst).st_mode) + # follow both links + os.chmod(dst, stat.S_IRWXO) + shutil.copymode(src_link, dst_link) + self.assertEqual(os.stat(src).st_mode, os.stat(dst).st_mode) @unittest.skipUnless(hasattr(os, 'lchmod'), 'requires os.lchmod') @os_helper.skip_unless_symlink @@ -1046,10 +1131,11 @@ def test_copymode_symlink_to_symlink(self): os.lchmod(src_link, stat.S_IRWXO|stat.S_IRWXG) # link to link os.lchmod(dst_link, stat.S_IRWXO) + old_mode = os.stat(dst).st_mode shutil.copymode(src_link, dst_link, follow_symlinks=False) self.assertEqual(os.lstat(src_link).st_mode, os.lstat(dst_link).st_mode) - self.assertNotEqual(os.stat(src).st_mode, os.stat(dst).st_mode) + self.assertEqual(os.stat(dst).st_mode, old_mode) # src link - use chmod os.lchmod(dst_link, stat.S_IRWXO) shutil.copymode(src_link, dst, follow_symlinks=False) @@ -1584,6 +1670,17 @@ def test_tarfile_vs_tar(self): # now create another tarball using `tar` tarball2 = os.path.join(root_dir, 'archive2.tar') tar_cmd = ['tar', '-cf', 'archive2.tar', base_dir] + if sys.platform == 'darwin': + # macOS tar can include extended attributes, + # ACLs and other mac specific metadata into the + # archive (an recentish version of the OS). + # + # This feature can be disabled with the + # '--no-mac-metadata' option on macOS 11 or + # later. + import platform + if int(platform.mac_ver()[0].split('.')[0]) >= 11: + tar_cmd.insert(1, '--no-mac-metadata') subprocess.check_call(tar_cmd, cwd=root_dir, stdout=subprocess.DEVNULL) @@ -1839,6 +1936,49 @@ def test_register_archive_format(self): formats = [name for name, params in get_archive_formats()] self.assertNotIn('xxx', formats) + def test_make_tarfile_rootdir_nodir(self): + # GH-99203 + self.addCleanup(os_helper.unlink, f'{TESTFN}.tar') + for dry_run in (False, True): + with self.subTest(dry_run=dry_run): + tmp_dir = self.mkdtemp() + nonexisting_file = os.path.join(tmp_dir, 'nonexisting') + with self.assertRaises(FileNotFoundError) as cm: + make_archive(TESTFN, 'tar', nonexisting_file, dry_run=dry_run) + self.assertEqual(cm.exception.errno, errno.ENOENT) + self.assertEqual(cm.exception.filename, nonexisting_file) + self.assertFalse(os.path.exists(f'{TESTFN}.tar')) + + tmp_fd, tmp_file = tempfile.mkstemp(dir=tmp_dir) + os.close(tmp_fd) + with self.assertRaises(NotADirectoryError) as cm: + make_archive(TESTFN, 'tar', tmp_file, dry_run=dry_run) + self.assertEqual(cm.exception.errno, errno.ENOTDIR) + self.assertEqual(cm.exception.filename, tmp_file) + self.assertFalse(os.path.exists(f'{TESTFN}.tar')) + + @support.requires_zlib() + def test_make_zipfile_rootdir_nodir(self): + # GH-99203 + self.addCleanup(os_helper.unlink, f'{TESTFN}.zip') + for dry_run in (False, True): + with self.subTest(dry_run=dry_run): + tmp_dir = self.mkdtemp() + nonexisting_file = os.path.join(tmp_dir, 'nonexisting') + with self.assertRaises(FileNotFoundError) as cm: + make_archive(TESTFN, 'zip', nonexisting_file, dry_run=dry_run) + self.assertEqual(cm.exception.errno, errno.ENOENT) + self.assertEqual(cm.exception.filename, nonexisting_file) + self.assertFalse(os.path.exists(f'{TESTFN}.zip')) + + tmp_fd, tmp_file = tempfile.mkstemp(dir=tmp_dir) + os.close(tmp_fd) + with self.assertRaises(NotADirectoryError) as cm: + make_archive(TESTFN, 'zip', tmp_file, dry_run=dry_run) + self.assertEqual(cm.exception.errno, errno.ENOTDIR) + self.assertEqual(cm.exception.filename, tmp_file) + self.assertFalse(os.path.exists(f'{TESTFN}.zip')) + ### shutil.unpack_archive def check_unpack_archive(self, format, **kwargs): @@ -2024,6 +2164,14 @@ def setUp(self): self.curdir = os.curdir self.ext = ".EXE" + def to_text_type(self, s): + ''' + In this class we're testing with str, so convert s to a str + ''' + if isinstance(s, bytes): + return s.decode() + return s + def test_basic(self): # Given an EXE in a directory, it should be returned. rv = shutil.which(self.file, path=self.dir) @@ -2211,9 +2359,9 @@ def test_empty_path_no_PATH(self): @unittest.skipUnless(sys.platform == "win32", 'test specific to Windows') def test_pathext(self): - ext = ".xyz" + ext = self.to_text_type(".xyz") temp_filexyz = tempfile.NamedTemporaryFile(dir=self.temp_dir, - prefix="Tmp2", suffix=ext) + prefix=self.to_text_type("Tmp2"), suffix=ext) os.chmod(temp_filexyz.name, stat.S_IXUSR) self.addCleanup(temp_filexyz.close) @@ -2222,16 +2370,16 @@ def test_pathext(self): program = os.path.splitext(program)[0] with os_helper.EnvironmentVarGuard() as env: - env['PATHEXT'] = ext + env['PATHEXT'] = ext if isinstance(ext, str) else ext.decode() rv = shutil.which(program, path=self.temp_dir) self.assertEqual(rv, temp_filexyz.name) # Issue 40592: See https://bugs.python.org/issue40592 @unittest.skipUnless(sys.platform == "win32", 'test specific to Windows') def test_pathext_with_empty_str(self): - ext = ".xyz" + ext = self.to_text_type(".xyz") temp_filexyz = tempfile.NamedTemporaryFile(dir=self.temp_dir, - prefix="Tmp2", suffix=ext) + prefix=self.to_text_type("Tmp2"), suffix=ext) self.addCleanup(temp_filexyz.close) # strip path and extension @@ -2239,7 +2387,7 @@ def test_pathext_with_empty_str(self): program = os.path.splitext(program)[0] with os_helper.EnvironmentVarGuard() as env: - env['PATHEXT'] = f"{ext};" # note the ; + env['PATHEXT'] = f"{ext if isinstance(ext, str) else ext.decode()};" # note the ; rv = shutil.which(program, path=self.temp_dir) self.assertEqual(rv, temp_filexyz.name) @@ -2247,13 +2395,14 @@ def test_pathext_with_empty_str(self): @unittest.skipUnless(sys.platform == "win32", 'test specific to Windows') def test_pathext_applied_on_files_in_path(self): with os_helper.EnvironmentVarGuard() as env: - env["PATH"] = self.temp_dir + env["PATH"] = self.temp_dir if isinstance(self.temp_dir, str) else self.temp_dir.decode() env["PATHEXT"] = ".test" - test_path = pathlib.Path(self.temp_dir) / "test_program.test" - test_path.touch(mode=0o755) + test_path = os.path.join(self.temp_dir, self.to_text_type("test_program.test")) + open(test_path, 'w').close() + os.chmod(test_path, 0o755) - self.assertEqual(shutil.which("test_program"), str(test_path)) + self.assertEqual(shutil.which(self.to_text_type("test_program")), test_path) # See GH-75586 @unittest.skipUnless(sys.platform == "win32", 'test specific to Windows') @@ -2269,6 +2418,50 @@ def test_win_path_needs_curdir(self): self.assertFalse(shutil._win_path_needs_curdir('dontcare', os.X_OK)) need_curdir_mock.assert_called_once_with('dontcare') + # See GH-109590 + @unittest.skipUnless(sys.platform == "win32", 'test specific to Windows') + def test_pathext_preferred_for_execute(self): + with os_helper.EnvironmentVarGuard() as env: + env["PATH"] = self.temp_dir if isinstance(self.temp_dir, str) else self.temp_dir.decode() + env["PATHEXT"] = ".test" + + exe = os.path.join(self.temp_dir, self.to_text_type("test.exe")) + open(exe, 'w').close() + os.chmod(exe, 0o755) + + # default behavior allows a direct match if nothing in PATHEXT matches + self.assertEqual(shutil.which(self.to_text_type("test.exe")), exe) + + dot_test = os.path.join(self.temp_dir, self.to_text_type("test.exe.test")) + open(dot_test, 'w').close() + os.chmod(dot_test, 0o755) + + # now we have a PATHEXT match, so it take precedence + self.assertEqual(shutil.which(self.to_text_type("test.exe")), dot_test) + + # but if we don't use os.X_OK we don't change the order based off PATHEXT + # and therefore get the direct match. + self.assertEqual(shutil.which(self.to_text_type("test.exe"), mode=os.F_OK), exe) + + # See GH-109590 + @unittest.skipUnless(sys.platform == "win32", 'test specific to Windows') + def test_pathext_given_extension_preferred(self): + with os_helper.EnvironmentVarGuard() as env: + env["PATH"] = self.temp_dir if isinstance(self.temp_dir, str) else self.temp_dir.decode() + env["PATHEXT"] = ".exe2;.exe" + + exe = os.path.join(self.temp_dir, self.to_text_type("test.exe")) + open(exe, 'w').close() + os.chmod(exe, 0o755) + + exe2 = os.path.join(self.temp_dir, self.to_text_type("test.exe2")) + open(exe2, 'w').close() + os.chmod(exe2, 0o755) + + # even though .exe2 is preferred in PATHEXT, we matched directly to test.exe + self.assertEqual(shutil.which(self.to_text_type("test.exe")), exe) + self.assertEqual(shutil.which(self.to_text_type("test")), exe2) + class TestWhichBytes(TestWhich): def setUp(self): @@ -2276,9 +2469,18 @@ def setUp(self): self.dir = os.fsencode(self.dir) self.file = os.fsencode(self.file) self.temp_file.name = os.fsencode(self.temp_file.name) + self.temp_dir = os.fsencode(self.temp_dir) self.curdir = os.fsencode(self.curdir) self.ext = os.fsencode(self.ext) + def to_text_type(self, s): + ''' + In this class we're testing with bytes, so convert s to a bytes + ''' + if isinstance(s, str): + return s.encode() + return s + class TestMove(BaseTest, unittest.TestCase): @@ -2486,6 +2688,35 @@ def test_move_dir_caseinsensitive(self): finally: os.rmdir(dst_dir) + # bpo-26791: Check that a symlink to a directory can + # be moved into that directory. + @mock_rename + def _test_move_symlink_to_dir_into_dir(self, dst): + src = os.path.join(self.src_dir, 'linktodir') + dst_link = os.path.join(self.dst_dir, 'linktodir') + os.symlink(self.dst_dir, src, target_is_directory=True) + shutil.move(src, dst) + self.assertTrue(os.path.islink(dst_link)) + self.assertTrue(os.path.samefile(self.dst_dir, dst_link)) + self.assertFalse(os.path.exists(src)) + + # Repeat the move operation with the destination + # symlink already in place (should raise shutil.Error). + os.symlink(self.dst_dir, src, target_is_directory=True) + with self.assertRaises(shutil.Error): + shutil.move(src, dst) + self.assertTrue(os.path.samefile(self.dst_dir, dst_link)) + self.assertTrue(os.path.exists(src)) + + @os_helper.skip_unless_symlink + def test_move_symlink_to_dir_into_dir(self): + self._test_move_symlink_to_dir_into_dir(self.dst_dir) + + @os_helper.skip_unless_symlink + def test_move_symlink_to_dir_into_symlink_to_dir(self): + dst = os.path.join(self.src_dir, 'otherlinktodir') + os.symlink(self.dst_dir, dst, target_is_directory=True) + self._test_move_symlink_to_dir_into_dir(dst) @os_helper.skip_unless_dac_override @unittest.skipUnless(hasattr(os, 'lchflags') diff --git a/Lib/test/test_signal.py b/Lib/test/test_signal.py index 25afd6aabe0751..637a0ca3b36972 100644 --- a/Lib/test/test_signal.py +++ b/Lib/test/test_signal.py @@ -1,5 +1,6 @@ import enum import errno +import functools import inspect import os import random @@ -76,6 +77,9 @@ class PosixTests(unittest.TestCase): def trivial_signal_handler(self, *args): pass + def create_handler_with_partial(self, argument): + return functools.partial(self.trivial_signal_handler, argument) + def test_out_of_range_signal_number_raises_error(self): self.assertRaises(ValueError, signal.getsignal, 4242) @@ -96,6 +100,28 @@ def test_getsignal(self): signal.signal(signal.SIGHUP, hup) self.assertEqual(signal.getsignal(signal.SIGHUP), hup) + def test_no_repr_is_called_on_signal_handler(self): + # See https://github.com/python/cpython/issues/112559. + + class MyArgument: + def __init__(self): + self.repr_count = 0 + + def __repr__(self): + self.repr_count += 1 + return super().__repr__() + + argument = MyArgument() + self.assertEqual(0, argument.repr_count) + + handler = self.create_handler_with_partial(argument) + hup = signal.signal(signal.SIGHUP, handler) + self.assertIsInstance(hup, signal.Handlers) + self.assertEqual(signal.getsignal(signal.SIGHUP), handler) + signal.signal(signal.SIGHUP, hup) + self.assertEqual(signal.getsignal(signal.SIGHUP), hup) + self.assertEqual(0, argument.repr_count) + def test_strsignal(self): self.assertIn("Interrupt", signal.strsignal(signal.SIGINT)) self.assertIn("Terminated", signal.strsignal(signal.SIGTERM)) @@ -745,6 +771,7 @@ def test_siginterrupt_on(self): interrupted = self.readpipe_interrupted(True) self.assertTrue(interrupted) + @support.requires_resource('walltime') def test_siginterrupt_off(self): # If a signal handler is installed and siginterrupt is called with # a false value for the second argument, when that signal arrives, it @@ -1317,6 +1344,7 @@ def handler(signum, frame): # Python handler self.assertEqual(len(sigs), N, "Some signals were lost") + @unittest.skipIf(sys.platform == "darwin", "crashes due to system bug (FB13453490)") @unittest.skipUnless(hasattr(signal, "SIGUSR1"), "test needs SIGUSR1") @threading_helper.requires_working_threading() @@ -1338,7 +1366,7 @@ def set_interrupts(): num_sent_signals += 1 def cycle_handlers(): - while num_sent_signals < 100: + while num_sent_signals < 100 or num_received_signals < 1: for i in range(20000): # Cycle between a Python-defined and a non-Python handler for handler in [custom_handler, signal.SIG_IGN]: @@ -1371,7 +1399,7 @@ def cycle_handlers(): if not ignored: # Sanity check that some signals were received, but not all self.assertGreater(num_received_signals, 0) - self.assertLess(num_received_signals, num_sent_signals) + self.assertLessEqual(num_received_signals, num_sent_signals) finally: do_stop = True t.join() diff --git a/Lib/test/test_site.py b/Lib/test/test_site.py index 9e701fd847acdf..e26b48ee9483d5 100644 --- a/Lib/test/test_site.py +++ b/Lib/test/test_site.py @@ -7,6 +7,7 @@ import unittest import test.support from test import support +from test.support.script_helper import assert_python_ok from test.support import os_helper from test.support import socket_helper from test.support import captured_stderr @@ -338,6 +339,19 @@ def test_no_home_directory(self): mock_addsitedir.assert_not_called() self.assertFalse(known_paths) + def test_gethistoryfile(self): + filename = 'file' + rc, out, err = assert_python_ok('-c', + f'import site; assert site.gethistoryfile() == "{filename}"', + PYTHON_HISTORY=filename) + self.assertEqual(rc, 0) + + # Check that PYTHON_HISTORY is ignored in isolated mode. + rc, out, err = assert_python_ok('-I', '-c', + f'import site; assert site.gethistoryfile() != "{filename}"', + PYTHON_HISTORY=filename) + self.assertEqual(rc, 0) + def test_trace(self): message = "bla-bla-bla" for verbose, out in (True, message + "\n"), (False, ""): @@ -465,10 +479,48 @@ def test_sitecustomize_executed(self): else: self.fail("sitecustomize not imported automatically") - @test.support.requires_resource('network') - @test.support.system_must_validate_cert + @support.requires_subprocess() + def test_customization_modules_on_startup(self): + mod_names = [ + 'sitecustomize' + ] + + if site.ENABLE_USER_SITE: + mod_names.append('usercustomize') + + temp_dir = tempfile.mkdtemp() + self.addCleanup(os_helper.rmtree, temp_dir) + + with EnvironmentVarGuard() as environ: + environ['PYTHONPATH'] = temp_dir + + for module_name in mod_names: + os_helper.rmtree(temp_dir) + os.mkdir(temp_dir) + + customize_path = os.path.join(temp_dir, f'{module_name}.py') + eyecatcher = f'EXECUTED_{module_name}' + + with open(customize_path, 'w') as f: + f.write(f'print("{eyecatcher}")') + + output = subprocess.check_output([sys.executable, '-c', '""']) + self.assertIn(eyecatcher, output.decode('utf-8')) + + # -S blocks any site-packages + output = subprocess.check_output([sys.executable, '-S', '-c', '""']) + self.assertNotIn(eyecatcher, output.decode('utf-8')) + + # -s blocks user site-packages + if 'usercustomize' == module_name: + output = subprocess.check_output([sys.executable, '-s', '-c', '""']) + self.assertNotIn(eyecatcher, output.decode('utf-8')) + + @unittest.skipUnless(hasattr(urllib.request, "HTTPSHandler"), 'need SSL support to download license') + @test.support.requires_resource('network') + @test.support.system_must_validate_cert def test_license_exists_at_url(self): # This test is a bit fragile since it depends on the format of the # string displayed by license in the absence of a LICENSE file. @@ -576,7 +628,7 @@ def _create_underpth_exe(self, lines, exe_pth=True): _pth_file = os.path.splitext(exe_file)[0] + '._pth' else: _pth_file = os.path.splitext(dll_file)[0] + '._pth' - with open(_pth_file, 'w') as f: + with open(_pth_file, 'w', encoding='utf8') as f: for line in lines: print(line, file=f) return exe_file @@ -603,17 +655,31 @@ def _calc_sys_path_for_underpth_nosite(self, sys_prefix, lines): sys_path.append(abs_path) return sys_path + def _get_pth_lines(self, libpath: str, *, import_site: bool): + pth_lines = ['fake-path-name'] + # include 200 lines of `libpath` in _pth lines (or fewer + # if the `libpath` is long enough to get close to 32KB + # see https://github.com/python/cpython/issues/113628) + encoded_libpath_length = len(libpath.encode("utf-8")) + repetitions = min(200, 30000 // encoded_libpath_length) + if repetitions <= 2: + self.skipTest( + f"Python stdlib path is too long ({encoded_libpath_length:,} bytes)") + pth_lines.extend(libpath for _ in range(repetitions)) + pth_lines.extend(['', '# comment']) + if import_site: + pth_lines.append('import site') + return pth_lines + @support.requires_subprocess() def test_underpth_basic(self): - libpath = test.support.STDLIB_DIR - exe_prefix = os.path.dirname(sys.executable) pth_lines = ['#.', '# ..', *sys.path, '.', '..'] exe_file = self._create_underpth_exe(pth_lines) sys_path = self._calc_sys_path_for_underpth_nosite( os.path.dirname(exe_file), pth_lines) - output = subprocess.check_output([exe_file, '-c', + output = subprocess.check_output([exe_file, '-X', 'utf8', '-c', 'import sys; print("\\n".join(sys.path) if sys.flags.no_site else "")' ], encoding='utf-8', errors='surrogateescape') actual_sys_path = output.rstrip().split('\n') @@ -628,12 +694,7 @@ def test_underpth_basic(self): def test_underpth_nosite_file(self): libpath = test.support.STDLIB_DIR exe_prefix = os.path.dirname(sys.executable) - pth_lines = [ - 'fake-path-name', - *[libpath for _ in range(200)], - '', - '# comment', - ] + pth_lines = self._get_pth_lines(libpath, import_site=False) exe_file = self._create_underpth_exe(pth_lines) sys_path = self._calc_sys_path_for_underpth_nosite( os.path.dirname(exe_file), @@ -657,13 +718,8 @@ def test_underpth_nosite_file(self): def test_underpth_file(self): libpath = test.support.STDLIB_DIR exe_prefix = os.path.dirname(sys.executable) - exe_file = self._create_underpth_exe([ - 'fake-path-name', - *[libpath for _ in range(200)], - '', - '# comment', - 'import site' - ]) + exe_file = self._create_underpth_exe( + self._get_pth_lines(libpath, import_site=True)) sys_prefix = os.path.dirname(exe_file) env = os.environ.copy() env['PYTHONPATH'] = 'from-env' @@ -682,13 +738,8 @@ def test_underpth_file(self): def test_underpth_dll_file(self): libpath = test.support.STDLIB_DIR exe_prefix = os.path.dirname(sys.executable) - exe_file = self._create_underpth_exe([ - 'fake-path-name', - *[libpath for _ in range(200)], - '', - '# comment', - 'import site' - ], exe_pth=False) + exe_file = self._create_underpth_exe( + self._get_pth_lines(libpath, import_site=True), exe_pth=False) sys_prefix = os.path.dirname(exe_file) env = os.environ.copy() env['PYTHONPATH'] = 'from-env' diff --git a/Lib/test/test_smtpnet.py b/Lib/test/test_smtpnet.py index 72f51cd8d81f59..2e0dc1aa276f35 100644 --- a/Lib/test/test_smtpnet.py +++ b/Lib/test/test_smtpnet.py @@ -61,6 +61,7 @@ def test_connect_default_port(self): server.ehlo() server.quit() + @support.requires_resource('walltime') def test_connect_using_sslcontext(self): context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) context.check_hostname = False diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py index 0eaf64257c3b81..4eb5af99d6674c 100644 --- a/Lib/test/test_socket.py +++ b/Lib/test/test_socket.py @@ -215,24 +215,6 @@ def setUp(self): self.serv = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDPLITE) self.port = socket_helper.bind_port(self.serv) -class ThreadSafeCleanupTestCase: - """Subclass of unittest.TestCase with thread-safe cleanup methods. - - This subclass protects the addCleanup() and doCleanups() methods - with a recursive lock. - """ - - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - self._cleanup_lock = threading.RLock() - - def addCleanup(self, *args, **kwargs): - with self._cleanup_lock: - return super().addCleanup(*args, **kwargs) - - def doCleanups(self, *args, **kwargs): - with self._cleanup_lock: - return super().doCleanups(*args, **kwargs) class SocketCANTest(unittest.TestCase): @@ -626,8 +608,7 @@ def setUp(self): self.serv.listen() -class ThreadedSocketTestMixin(ThreadSafeCleanupTestCase, SocketTestBase, - ThreadableTest): +class ThreadedSocketTestMixin(SocketTestBase, ThreadableTest): """Mixin to add client socket and allow client/server tests. Client socket is self.cli and its address is self.cli_addr. See @@ -1101,7 +1082,20 @@ def testInterfaceNameIndex(self): 'socket.if_indextoname() not available.') def testInvalidInterfaceIndexToName(self): self.assertRaises(OSError, socket.if_indextoname, 0) + self.assertRaises(OverflowError, socket.if_indextoname, -1) + self.assertRaises(OverflowError, socket.if_indextoname, 2**1000) self.assertRaises(TypeError, socket.if_indextoname, '_DEADBEEF') + if hasattr(socket, 'if_nameindex'): + indices = dict(socket.if_nameindex()) + for index in indices: + index2 = index + 2**32 + if index2 not in indices: + with self.assertRaises((OverflowError, OSError)): + socket.if_indextoname(index2) + for index in 2**32-1, 2**64-1: + if index not in indices: + with self.assertRaises((OverflowError, OSError)): + socket.if_indextoname(index) @unittest.skipUnless(hasattr(socket, 'if_nametoindex'), 'socket.if_nametoindex() not available.') @@ -2813,7 +2807,7 @@ def _testRecvFromNegative(self): # here assumes that datagram delivery on the local machine will be # reliable. -class SendrecvmsgBase(ThreadSafeCleanupTestCase): +class SendrecvmsgBase: # Base class for sendmsg()/recvmsg() tests. # Time in seconds to wait before considering a test failed, or @@ -4679,7 +4673,6 @@ def testInterruptedRecvmsgIntoTimeout(self): @unittest.skipUnless(hasattr(signal, "alarm") or hasattr(signal, "setitimer"), "Don't have signal.alarm or signal.setitimer") class InterruptedSendTimeoutTest(InterruptedTimeoutBase, - ThreadSafeCleanupTestCase, SocketListeningTestMixin, TCPTestBase): # Test interrupting the interruptible send*() methods with signals # when a timeout is set. @@ -5288,6 +5281,7 @@ def mocked_socket_module(self): finally: socket.socket = old_socket + @socket_helper.skip_if_tcp_blackhole def test_connect(self): port = socket_helper.find_unused_port() cli = socket.socket(socket.AF_INET, socket.SOCK_STREAM) @@ -5296,6 +5290,7 @@ def test_connect(self): cli.connect((HOST, port)) self.assertEqual(cm.exception.errno, errno.ECONNREFUSED) + @socket_helper.skip_if_tcp_blackhole def test_create_connection(self): # Issue #9792: errors raised by create_connection() should have # a proper errno attribute. @@ -5354,6 +5349,7 @@ def test_create_connection_timeout(self): class NetworkConnectionAttributesTest(SocketTCPTest, ThreadableTest): + cli = None def __init__(self, methodName='runTest'): SocketTCPTest.__init__(self, methodName=methodName) @@ -5363,7 +5359,8 @@ def clientSetUp(self): self.source_port = socket_helper.find_unused_port() def clientTearDown(self): - self.cli.close() + if self.cli is not None: + self.cli.close() self.cli = None ThreadableTest.clientTearDown(self) @@ -6472,12 +6469,16 @@ def test_sha256(self): self.assertEqual(op.recv(512), expected) def test_hmac_sha1(self): - expected = bytes.fromhex("effcdf6ae5eb2fa2d27416d5f184df9c259a7c79") + # gh-109396: In FIPS mode, Linux 6.5 requires a key + # of at least 112 bits. Use a key of 152 bits. + key = b"Python loves AF_ALG" + data = b"what do ya want for nothing?" + expected = bytes.fromhex("193dbb43c6297b47ea6277ec0ce67119a3f3aa66") with self.create_alg('hash', 'hmac(sha1)') as algo: - algo.setsockopt(socket.SOL_ALG, socket.ALG_SET_KEY, b"Jefe") + algo.setsockopt(socket.SOL_ALG, socket.ALG_SET_KEY, key) op, _ = algo.accept() with op: - op.sendall(b"what do ya want for nothing?") + op.sendall(data) self.assertEqual(op.recv(512), expected) # Although it should work with 3.19 and newer the test blocks on diff --git a/Lib/test/test_socketserver.py b/Lib/test/test_socketserver.py index c81d559cde315d..0f62f9eb200e42 100644 --- a/Lib/test/test_socketserver.py +++ b/Lib/test/test_socketserver.py @@ -32,11 +32,6 @@ HAVE_FORKING = test.support.has_fork_support requires_forking = unittest.skipUnless(HAVE_FORKING, 'requires forking') -def signal_alarm(n): - """Call signal.alarm when it exists (i.e. not on Windows).""" - if hasattr(signal, 'alarm'): - signal.alarm(n) - # Remember real select() to avoid interferences with mocking _real_select = select.select @@ -68,12 +63,10 @@ class SocketServerTest(unittest.TestCase): """Test all socket servers.""" def setUp(self): - signal_alarm(60) # Kill deadlocks after 60 seconds. self.port_seed = 0 self.test_files = [] def tearDown(self): - signal_alarm(0) # Didn't deadlock. reap_children() for fn in self.test_files: diff --git a/Lib/test/test_source_encoding.py b/Lib/test/test_source_encoding.py index b05173ad00d442..61b00778f8361c 100644 --- a/Lib/test/test_source_encoding.py +++ b/Lib/test/test_source_encoding.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- import unittest -from test.support import script_helper, captured_stdout, requires_subprocess +from test.support import script_helper, captured_stdout, requires_subprocess, requires_resource from test.support.os_helper import TESTFN, unlink, rmtree from test.support.import_helper import unload import importlib @@ -68,6 +68,7 @@ def test_issue7820(self): def test_20731(self): sub = subprocess.Popen([sys.executable, os.path.join(os.path.dirname(__file__), + 'tokenizedata', 'coding20731.py')], stderr=subprocess.PIPE) err = sub.communicate()[1] @@ -100,10 +101,10 @@ def test_bad_coding2(self): self.verify_bad_module(module_name) def verify_bad_module(self, module_name): - self.assertRaises(SyntaxError, __import__, 'test.' + module_name) + self.assertRaises(SyntaxError, __import__, 'test.tokenizedata.' + module_name) path = os.path.dirname(__file__) - filename = os.path.join(path, module_name + '.py') + filename = os.path.join(path, 'tokenizedata', module_name + '.py') with open(filename, "rb") as fp: bytes = fp.read() self.assertRaises(SyntaxError, compile, bytes, filename, 'exec') @@ -250,10 +251,11 @@ def test_crcrcrlf2(self): class UTF8ValidatorTest(unittest.TestCase): @unittest.skipIf(not sys.platform.startswith("linux"), "Too slow to run on non-Linux platforms") + @requires_resource('cpu') def test_invalid_utf8(self): # This is a port of test_utf8_decode_invalid_sequences in # test_unicode.py to exercise the separate utf8 validator in - # Parser/tokenizer.c used when reading source files. + # Parser/tokenizer/helpers.c used when reading source files. # That file is written using low-level C file I/O, so the only way to # test it is to write actual files to disk. diff --git a/Lib/test/test_sqlite3/test_backup.py b/Lib/test/test_sqlite3/test_backup.py index 87ab29c54d65e2..c7400d8b2165e6 100644 --- a/Lib/test/test_sqlite3/test_backup.py +++ b/Lib/test/test_sqlite3/test_backup.py @@ -1,6 +1,8 @@ import sqlite3 as sqlite import unittest +from .util import memory_database + class BackupTests(unittest.TestCase): def setUp(self): @@ -32,32 +34,32 @@ def test_bad_target_same_connection(self): self.cx.backup(self.cx) def test_bad_target_closed_connection(self): - bck = sqlite.connect(':memory:') - bck.close() - with self.assertRaises(sqlite.ProgrammingError): - self.cx.backup(bck) + with memory_database() as bck: + bck.close() + with self.assertRaises(sqlite.ProgrammingError): + self.cx.backup(bck) def test_bad_source_closed_connection(self): - bck = sqlite.connect(':memory:') - source = sqlite.connect(":memory:") - source.close() - with self.assertRaises(sqlite.ProgrammingError): - source.backup(bck) + with memory_database() as bck: + source = sqlite.connect(":memory:") + source.close() + with self.assertRaises(sqlite.ProgrammingError): + source.backup(bck) def test_bad_target_in_transaction(self): - bck = sqlite.connect(':memory:') - bck.execute('CREATE TABLE bar (key INTEGER)') - bck.executemany('INSERT INTO bar (key) VALUES (?)', [(3,), (4,)]) - with self.assertRaises(sqlite.OperationalError) as cm: - self.cx.backup(bck) + with memory_database() as bck: + bck.execute('CREATE TABLE bar (key INTEGER)') + bck.executemany('INSERT INTO bar (key) VALUES (?)', [(3,), (4,)]) + with self.assertRaises(sqlite.OperationalError) as cm: + self.cx.backup(bck) def test_keyword_only_args(self): with self.assertRaises(TypeError): - with sqlite.connect(':memory:') as bck: + with memory_database() as bck: self.cx.backup(bck, 1) def test_simple(self): - with sqlite.connect(':memory:') as bck: + with memory_database() as bck: self.cx.backup(bck) self.verify_backup(bck) @@ -67,7 +69,7 @@ def test_progress(self): def progress(status, remaining, total): journal.append(status) - with sqlite.connect(':memory:') as bck: + with memory_database() as bck: self.cx.backup(bck, pages=1, progress=progress) self.verify_backup(bck) @@ -81,7 +83,7 @@ def test_progress_all_pages_at_once_1(self): def progress(status, remaining, total): journal.append(remaining) - with sqlite.connect(':memory:') as bck: + with memory_database() as bck: self.cx.backup(bck, progress=progress) self.verify_backup(bck) @@ -94,7 +96,7 @@ def test_progress_all_pages_at_once_2(self): def progress(status, remaining, total): journal.append(remaining) - with sqlite.connect(':memory:') as bck: + with memory_database() as bck: self.cx.backup(bck, pages=-1, progress=progress) self.verify_backup(bck) @@ -103,7 +105,7 @@ def progress(status, remaining, total): def test_non_callable_progress(self): with self.assertRaises(TypeError) as cm: - with sqlite.connect(':memory:') as bck: + with memory_database() as bck: self.cx.backup(bck, pages=1, progress='bar') self.assertEqual(str(cm.exception), 'progress argument must be a callable') @@ -116,7 +118,7 @@ def progress(status, remaining, total): self.cx.commit() journal.append(remaining) - with sqlite.connect(':memory:') as bck: + with memory_database() as bck: self.cx.backup(bck, pages=1, progress=progress) self.verify_backup(bck) @@ -135,17 +137,17 @@ def progress(status, remaining, total): raise SystemError('nearly out of space') with self.assertRaises(SystemError) as err: - with sqlite.connect(':memory:') as bck: + with memory_database() as bck: self.cx.backup(bck, progress=progress) self.assertEqual(str(err.exception), 'nearly out of space') def test_database_source_name(self): - with sqlite.connect(':memory:') as bck: + with memory_database() as bck: self.cx.backup(bck, name='main') - with sqlite.connect(':memory:') as bck: + with memory_database() as bck: self.cx.backup(bck, name='temp') with self.assertRaises(sqlite.OperationalError) as cm: - with sqlite.connect(':memory:') as bck: + with memory_database() as bck: self.cx.backup(bck, name='non-existing') self.assertIn("unknown database", str(cm.exception)) @@ -153,7 +155,7 @@ def test_database_source_name(self): self.cx.execute('CREATE TABLE attached_db.foo (key INTEGER)') self.cx.executemany('INSERT INTO attached_db.foo (key) VALUES (?)', [(3,), (4,)]) self.cx.commit() - with sqlite.connect(':memory:') as bck: + with memory_database() as bck: self.cx.backup(bck, name='attached_db') self.verify_backup(bck) diff --git a/Lib/test/test_sqlite3/test_cli.py b/Lib/test/test_sqlite3/test_cli.py index d374f8ee4fc8d3..303f9e03b5383f 100644 --- a/Lib/test/test_sqlite3/test_cli.py +++ b/Lib/test/test_sqlite3/test_cli.py @@ -1,42 +1,35 @@ """sqlite3 CLI tests.""" - -import sqlite3 as sqlite -import subprocess -import sys +import sqlite3 import unittest -from test.support import SHORT_TIMEOUT, requires_subprocess +from sqlite3.__main__ import main as cli from test.support.os_helper import TESTFN, unlink +from test.support import captured_stdout, captured_stderr, captured_stdin -@requires_subprocess() class CommandLineInterface(unittest.TestCase): def _do_test(self, *args, expect_success=True): - with subprocess.Popen( - [sys.executable, "-Xutf8", "-m", "sqlite3", *args], - encoding="utf-8", - bufsize=0, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - ) as proc: - proc.wait() - if expect_success == bool(proc.returncode): - self.fail("".join(proc.stderr)) - stdout = proc.stdout.read() - stderr = proc.stderr.read() - if expect_success: - self.assertEqual(stderr, "") - else: - self.assertEqual(stdout, "") - return stdout, stderr + with ( + captured_stdout() as out, + captured_stderr() as err, + self.assertRaises(SystemExit) as cm + ): + cli(args) + return out.getvalue(), err.getvalue(), cm.exception.code def expect_success(self, *args): - out, _ = self._do_test(*args) + out, err, code = self._do_test(*args) + self.assertEqual(code, 0, + "\n".join([f"Unexpected failure: {args=}", out, err])) + self.assertEqual(err, "") return out def expect_failure(self, *args): - _, err = self._do_test(*args, expect_success=False) + out, err, code = self._do_test(*args, expect_success=False) + self.assertNotEqual(code, 0, + "\n".join([f"Unexpected failure: {args=}", out, err])) + self.assertEqual(out, "") return err def test_cli_help(self): @@ -45,7 +38,7 @@ def test_cli_help(self): def test_cli_version(self): out = self.expect_success("-v") - self.assertIn(sqlite.sqlite_version, out) + self.assertIn(sqlite3.sqlite_version, out) def test_cli_execute_sql(self): out = self.expect_success(":memory:", "select 1") @@ -68,87 +61,94 @@ def test_cli_on_disk_db(self): self.assertIn("(0,)", out) -@requires_subprocess() class InteractiveSession(unittest.TestCase): - TIMEOUT = SHORT_TIMEOUT / 10. MEMORY_DB_MSG = "Connected to a transient in-memory database" PS1 = "sqlite> " PS2 = "... " - def start_cli(self, *args): - return subprocess.Popen( - [sys.executable, "-Xutf8", "-m", "sqlite3", *args], - encoding="utf-8", - bufsize=0, - stdin=subprocess.PIPE, - # Note: the banner is printed to stderr, the prompt to stdout. - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - ) - - def expect_success(self, proc): - proc.wait() - if proc.returncode: - self.fail("".join(proc.stderr)) + def run_cli(self, *args, commands=()): + with ( + captured_stdin() as stdin, + captured_stdout() as stdout, + captured_stderr() as stderr, + self.assertRaises(SystemExit) as cm + ): + for cmd in commands: + stdin.write(cmd + "\n") + stdin.seek(0) + cli(args) + + out = stdout.getvalue() + err = stderr.getvalue() + self.assertEqual(cm.exception.code, 0, + f"Unexpected failure: {args=}\n{out}\n{err}") + return out, err def test_interact(self): - with self.start_cli() as proc: - out, err = proc.communicate(timeout=self.TIMEOUT) - self.assertIn(self.MEMORY_DB_MSG, err) - self.assertIn(self.PS1, out) - self.expect_success(proc) + out, err = self.run_cli() + self.assertIn(self.MEMORY_DB_MSG, err) + self.assertIn(self.MEMORY_DB_MSG, err) + self.assertTrue(out.endswith(self.PS1)) + self.assertEqual(out.count(self.PS1), 1) + self.assertEqual(out.count(self.PS2), 0) def test_interact_quit(self): - with self.start_cli() as proc: - out, err = proc.communicate(input=".quit", timeout=self.TIMEOUT) - self.assertIn(self.MEMORY_DB_MSG, err) - self.assertIn(self.PS1, out) - self.expect_success(proc) + out, err = self.run_cli(commands=(".quit",)) + self.assertIn(self.MEMORY_DB_MSG, err) + self.assertTrue(out.endswith(self.PS1)) + self.assertEqual(out.count(self.PS1), 1) + self.assertEqual(out.count(self.PS2), 0) def test_interact_version(self): - with self.start_cli() as proc: - out, err = proc.communicate(input=".version", timeout=self.TIMEOUT) - self.assertIn(self.MEMORY_DB_MSG, err) - self.assertIn(sqlite.sqlite_version, out) - self.expect_success(proc) + out, err = self.run_cli(commands=(".version",)) + self.assertIn(self.MEMORY_DB_MSG, err) + self.assertIn(sqlite3.sqlite_version + "\n", out) + self.assertTrue(out.endswith(self.PS1)) + self.assertEqual(out.count(self.PS1), 2) + self.assertEqual(out.count(self.PS2), 0) + self.assertIn(sqlite3.sqlite_version, out) def test_interact_valid_sql(self): - with self.start_cli() as proc: - out, err = proc.communicate(input="select 1;", - timeout=self.TIMEOUT) - self.assertIn(self.MEMORY_DB_MSG, err) - self.assertIn("(1,)", out) - self.expect_success(proc) + out, err = self.run_cli(commands=("SELECT 1;",)) + self.assertIn(self.MEMORY_DB_MSG, err) + self.assertIn("(1,)\n", out) + self.assertTrue(out.endswith(self.PS1)) + self.assertEqual(out.count(self.PS1), 2) + self.assertEqual(out.count(self.PS2), 0) + + def test_interact_incomplete_multiline_sql(self): + out, err = self.run_cli(commands=("SELECT 1",)) + self.assertIn(self.MEMORY_DB_MSG, err) + self.assertTrue(out.endswith(self.PS2)) + self.assertEqual(out.count(self.PS1), 1) + self.assertEqual(out.count(self.PS2), 1) def test_interact_valid_multiline_sql(self): - with self.start_cli() as proc: - out, err = proc.communicate(input="select 1\n;", - timeout=self.TIMEOUT) - self.assertIn(self.MEMORY_DB_MSG, err) - self.assertIn(self.PS2, out) - self.assertIn("(1,)", out) - self.expect_success(proc) + out, err = self.run_cli(commands=("SELECT 1\n;",)) + self.assertIn(self.MEMORY_DB_MSG, err) + self.assertIn(self.PS2, out) + self.assertIn("(1,)\n", out) + self.assertTrue(out.endswith(self.PS1)) + self.assertEqual(out.count(self.PS1), 2) + self.assertEqual(out.count(self.PS2), 1) def test_interact_invalid_sql(self): - with self.start_cli() as proc: - out, err = proc.communicate(input="sel;", timeout=self.TIMEOUT) - self.assertIn(self.MEMORY_DB_MSG, err) - self.assertIn("OperationalError (SQLITE_ERROR)", err) - self.expect_success(proc) + out, err = self.run_cli(commands=("sel;",)) + self.assertIn(self.MEMORY_DB_MSG, err) + self.assertIn("OperationalError (SQLITE_ERROR)", err) + self.assertTrue(out.endswith(self.PS1)) + self.assertEqual(out.count(self.PS1), 2) + self.assertEqual(out.count(self.PS2), 0) def test_interact_on_disk_file(self): self.addCleanup(unlink, TESTFN) - with self.start_cli(TESTFN) as proc: - out, err = proc.communicate(input="create table t(t);", - timeout=self.TIMEOUT) - self.assertIn(TESTFN, err) - self.assertIn(self.PS1, out) - self.expect_success(proc) - with self.start_cli(TESTFN, "select count(t) from t") as proc: - out = proc.stdout.read() - err = proc.stderr.read() - self.assertIn("(0,)", out) - self.expect_success(proc) + + out, err = self.run_cli(TESTFN, commands=("CREATE TABLE t(t);",)) + self.assertIn(TESTFN, err) + self.assertTrue(out.endswith(self.PS1)) + + out, _ = self.run_cli(TESTFN, commands=("SELECT count(t) FROM t;",)) + self.assertIn("(0,)\n", out) if __name__ == "__main__": diff --git a/Lib/test/test_sqlite3/test_dbapi.py b/Lib/test/test_sqlite3/test_dbapi.py index 3f9bd0248a8b96..f3efe0f52f4fd7 100644 --- a/Lib/test/test_sqlite3/test_dbapi.py +++ b/Lib/test/test_sqlite3/test_dbapi.py @@ -33,26 +33,14 @@ SHORT_TIMEOUT, check_disallow_instantiation, requires_subprocess, is_emscripten, is_wasi ) +from test.support import gc_collect from test.support import threading_helper from _testcapi import INT_MAX, ULLONG_MAX from os import SEEK_SET, SEEK_CUR, SEEK_END from test.support.os_helper import TESTFN, TESTFN_UNDECODABLE, unlink, temp_dir, FakePath - -# Helper for temporary memory databases -def memory_database(*args, **kwargs): - cx = sqlite.connect(":memory:", *args, **kwargs) - return contextlib.closing(cx) - - -# Temporarily limit a database connection parameter -@contextlib.contextmanager -def cx_limit(cx, category=sqlite.SQLITE_LIMIT_SQL_LENGTH, limit=128): - try: - _prev = cx.setlimit(category, limit) - yield limit - finally: - cx.setlimit(category, _prev) +from .util import memory_database, cx_limit +from .util import MemoryDatabaseMixin class ModuleTests(unittest.TestCase): @@ -326,9 +314,9 @@ def test_extended_error_code_on_exception(self): self.assertEqual(exc.sqlite_errorname, "SQLITE_CONSTRAINT_CHECK") def test_disallow_instantiation(self): - cx = sqlite.connect(":memory:") - check_disallow_instantiation(self, type(cx("select 1"))) - check_disallow_instantiation(self, sqlite.Blob) + with memory_database() as cx: + check_disallow_instantiation(self, type(cx("select 1"))) + check_disallow_instantiation(self, sqlite.Blob) def test_complete_statement(self): self.assertFalse(sqlite.complete_statement("select t")) @@ -342,6 +330,7 @@ def setUp(self): cu = self.cx.cursor() cu.execute("create table test(id integer primary key, name text)") cu.execute("insert into test(name) values (?)", ("foo",)) + cu.close() def tearDown(self): self.cx.close() @@ -412,21 +401,22 @@ def test_exceptions(self): def test_in_transaction(self): # Can't use db from setUp because we want to test initial state. - cx = sqlite.connect(":memory:") - cu = cx.cursor() - self.assertEqual(cx.in_transaction, False) - cu.execute("create table transactiontest(id integer primary key, name text)") - self.assertEqual(cx.in_transaction, False) - cu.execute("insert into transactiontest(name) values (?)", ("foo",)) - self.assertEqual(cx.in_transaction, True) - cu.execute("select name from transactiontest where name=?", ["foo"]) - row = cu.fetchone() - self.assertEqual(cx.in_transaction, True) - cx.commit() - self.assertEqual(cx.in_transaction, False) - cu.execute("select name from transactiontest where name=?", ["foo"]) - row = cu.fetchone() - self.assertEqual(cx.in_transaction, False) + with memory_database() as cx: + cu = cx.cursor() + self.assertEqual(cx.in_transaction, False) + cu.execute("create table transactiontest(id integer primary key, name text)") + self.assertEqual(cx.in_transaction, False) + cu.execute("insert into transactiontest(name) values (?)", ("foo",)) + self.assertEqual(cx.in_transaction, True) + cu.execute("select name from transactiontest where name=?", ["foo"]) + row = cu.fetchone() + self.assertEqual(cx.in_transaction, True) + cx.commit() + self.assertEqual(cx.in_transaction, False) + cu.execute("select name from transactiontest where name=?", ["foo"]) + row = cu.fetchone() + self.assertEqual(cx.in_transaction, False) + cu.close() def test_in_transaction_ro(self): with self.assertRaises(AttributeError): @@ -450,10 +440,9 @@ def test_connection_exceptions(self): self.assertIs(getattr(sqlite, exc), getattr(self.cx, exc)) def test_interrupt_on_closed_db(self): - cx = sqlite.connect(":memory:") - cx.close() + self.cx.close() with self.assertRaises(sqlite.ProgrammingError): - cx.interrupt() + self.cx.interrupt() def test_interrupt(self): self.assertIsNone(self.cx.interrupt()) @@ -521,29 +510,29 @@ def test_connection_init_good_isolation_levels(self): self.assertEqual(cx.isolation_level, level) def test_connection_reinit(self): - db = ":memory:" - cx = sqlite.connect(db) - cx.text_factory = bytes - cx.row_factory = sqlite.Row - cu = cx.cursor() - cu.execute("create table foo (bar)") - cu.executemany("insert into foo (bar) values (?)", - ((str(v),) for v in range(4))) - cu.execute("select bar from foo") - - rows = [r for r in cu.fetchmany(2)] - self.assertTrue(all(isinstance(r, sqlite.Row) for r in rows)) - self.assertEqual([r[0] for r in rows], [b"0", b"1"]) - - cx.__init__(db) - cx.execute("create table foo (bar)") - cx.executemany("insert into foo (bar) values (?)", - ((v,) for v in ("a", "b", "c", "d"))) - - # This uses the old database, old row factory, but new text factory - rows = [r for r in cu.fetchall()] - self.assertTrue(all(isinstance(r, sqlite.Row) for r in rows)) - self.assertEqual([r[0] for r in rows], ["2", "3"]) + with memory_database() as cx: + cx.text_factory = bytes + cx.row_factory = sqlite.Row + cu = cx.cursor() + cu.execute("create table foo (bar)") + cu.executemany("insert into foo (bar) values (?)", + ((str(v),) for v in range(4))) + cu.execute("select bar from foo") + + rows = [r for r in cu.fetchmany(2)] + self.assertTrue(all(isinstance(r, sqlite.Row) for r in rows)) + self.assertEqual([r[0] for r in rows], [b"0", b"1"]) + + cx.__init__(":memory:") + cx.execute("create table foo (bar)") + cx.executemany("insert into foo (bar) values (?)", + ((v,) for v in ("a", "b", "c", "d"))) + + # This uses the old database, old row factory, but new text factory + rows = [r for r in cu.fetchall()] + self.assertTrue(all(isinstance(r, sqlite.Row) for r in rows)) + self.assertEqual([r[0] for r in rows], ["2", "3"]) + cu.close() def test_connection_bad_reinit(self): cx = sqlite.connect(":memory:") @@ -582,6 +571,25 @@ def test_connection_config(self): with self.assertRaisesRegex(sqlite.IntegrityError, "constraint"): cx.execute("insert into u values(0)") + def test_connect_positional_arguments(self): + regex = ( + r"Passing more than 1 positional argument to sqlite3.connect\(\)" + " is deprecated. Parameters 'timeout', 'detect_types', " + "'isolation_level', 'check_same_thread', 'factory', " + "'cached_statements' and 'uri' will become keyword-only " + "parameters in Python 3.15." + ) + with self.assertWarnsRegex(DeprecationWarning, regex) as cm: + cx = sqlite.connect(":memory:", 1.0) + cx.close() + self.assertEqual(cm.filename, __file__) + + def test_connection_resource_warning(self): + with self.assertWarns(ResourceWarning): + cx = sqlite.connect(":memory:") + del cx + gc_collect() + class UninitialisedConnectionTests(unittest.TestCase): def setUp(self): @@ -1558,12 +1566,12 @@ def run(con, err): except sqlite.Error: err.append("multi-threading not allowed") - con = sqlite.connect(":memory:", check_same_thread=False) - err = [] - t = threading.Thread(target=run, kwargs={"con": con, "err": err}) - t.start() - t.join() - self.assertEqual(len(err), 0, "\n".join(err)) + with memory_database(check_same_thread=False) as con: + err = [] + t = threading.Thread(target=run, kwargs={"con": con, "err": err}) + t.start() + t.join() + self.assertEqual(len(err), 0, "\n".join(err)) class ConstructorTests(unittest.TestCase): @@ -1589,9 +1597,16 @@ def test_binary(self): b = sqlite.Binary(b"\0'") class ExtensionTests(unittest.TestCase): + def setUp(self): + self.con = sqlite.connect(":memory:") + self.cur = self.con.cursor() + + def tearDown(self): + self.cur.close() + self.con.close() + def test_script_string_sql(self): - con = sqlite.connect(":memory:") - cur = con.cursor() + cur = self.cur cur.executescript(""" -- bla bla /* a stupid comment */ @@ -1603,40 +1618,40 @@ def test_script_string_sql(self): self.assertEqual(res, 5) def test_script_syntax_error(self): - con = sqlite.connect(":memory:") - cur = con.cursor() with self.assertRaises(sqlite.OperationalError): - cur.executescript("create table test(x); asdf; create table test2(x)") + self.cur.executescript(""" + CREATE TABLE test(x); + asdf; + CREATE TABLE test2(x) + """) def test_script_error_normal(self): - con = sqlite.connect(":memory:") - cur = con.cursor() with self.assertRaises(sqlite.OperationalError): - cur.executescript("create table test(sadfsadfdsa); select foo from hurz;") + self.cur.executescript(""" + CREATE TABLE test(sadfsadfdsa); + SELECT foo FROM hurz; + """) def test_cursor_executescript_as_bytes(self): - con = sqlite.connect(":memory:") - cur = con.cursor() with self.assertRaises(TypeError): - cur.executescript(b"create table test(foo); insert into test(foo) values (5);") + self.cur.executescript(b""" + CREATE TABLE test(foo); + INSERT INTO test(foo) VALUES (5); + """) def test_cursor_executescript_with_null_characters(self): - con = sqlite.connect(":memory:") - cur = con.cursor() with self.assertRaises(ValueError): - cur.executescript(""" - create table a(i);\0 - insert into a(i) values (5); - """) + self.cur.executescript(""" + CREATE TABLE a(i);\0 + INSERT INTO a(i) VALUES (5); + """) def test_cursor_executescript_with_surrogates(self): - con = sqlite.connect(":memory:") - cur = con.cursor() with self.assertRaises(UnicodeEncodeError): - cur.executescript(""" - create table a(s); - insert into a(s) values ('\ud8ff'); - """) + self.cur.executescript(""" + CREATE TABLE a(s); + INSERT INTO a(s) VALUES ('\ud8ff'); + """) def test_cursor_executescript_too_large_script(self): msg = "query string is too large" @@ -1646,19 +1661,18 @@ def test_cursor_executescript_too_large_script(self): cx.executescript("select 'too large'".ljust(lim+1)) def test_cursor_executescript_tx_control(self): - con = sqlite.connect(":memory:") + con = self.con con.execute("begin") self.assertTrue(con.in_transaction) con.executescript("select 1") self.assertFalse(con.in_transaction) def test_connection_execute(self): - con = sqlite.connect(":memory:") - result = con.execute("select 5").fetchone()[0] + result = self.con.execute("select 5").fetchone()[0] self.assertEqual(result, 5, "Basic test of Connection.execute") def test_connection_executemany(self): - con = sqlite.connect(":memory:") + con = self.con con.execute("create table test(foo)") con.executemany("insert into test(foo) values (?)", [(3,), (4,)]) result = con.execute("select foo from test order by foo").fetchall() @@ -1666,47 +1680,44 @@ def test_connection_executemany(self): self.assertEqual(result[1][0], 4, "Basic test of Connection.executemany") def test_connection_executescript(self): - con = sqlite.connect(":memory:") - con.executescript("create table test(foo); insert into test(foo) values (5);") + con = self.con + con.executescript(""" + CREATE TABLE test(foo); + INSERT INTO test(foo) VALUES (5); + """) result = con.execute("select foo from test").fetchone()[0] self.assertEqual(result, 5, "Basic test of Connection.executescript") + class ClosedConTests(unittest.TestCase): + def check(self, fn, *args, **kwds): + regex = "Cannot operate on a closed database." + with self.assertRaisesRegex(sqlite.ProgrammingError, regex): + fn(*args, **kwds) + + def setUp(self): + self.con = sqlite.connect(":memory:") + self.cur = self.con.cursor() + self.con.close() + def test_closed_con_cursor(self): - con = sqlite.connect(":memory:") - con.close() - with self.assertRaises(sqlite.ProgrammingError): - cur = con.cursor() + self.check(self.con.cursor) def test_closed_con_commit(self): - con = sqlite.connect(":memory:") - con.close() - with self.assertRaises(sqlite.ProgrammingError): - con.commit() + self.check(self.con.commit) def test_closed_con_rollback(self): - con = sqlite.connect(":memory:") - con.close() - with self.assertRaises(sqlite.ProgrammingError): - con.rollback() + self.check(self.con.rollback) def test_closed_cur_execute(self): - con = sqlite.connect(":memory:") - cur = con.cursor() - con.close() - with self.assertRaises(sqlite.ProgrammingError): - cur.execute("select 4") + self.check(self.cur.execute, "select 4") def test_closed_create_function(self): - con = sqlite.connect(":memory:") - con.close() - def f(x): return 17 - with self.assertRaises(sqlite.ProgrammingError): - con.create_function("foo", 1, f) + def f(x): + return 17 + self.check(self.con.create_function, "foo", 1, f) def test_closed_create_aggregate(self): - con = sqlite.connect(":memory:") - con.close() class Agg: def __init__(self): pass @@ -1714,34 +1725,25 @@ def step(self, x): pass def finalize(self): return 17 - with self.assertRaises(sqlite.ProgrammingError): - con.create_aggregate("foo", 1, Agg) + self.check(self.con.create_aggregate, "foo", 1, Agg) def test_closed_set_authorizer(self): - con = sqlite.connect(":memory:") - con.close() def authorizer(*args): return sqlite.DENY - with self.assertRaises(sqlite.ProgrammingError): - con.set_authorizer(authorizer) + self.check(self.con.set_authorizer, authorizer) def test_closed_set_progress_callback(self): - con = sqlite.connect(":memory:") - con.close() - def progress(): pass - with self.assertRaises(sqlite.ProgrammingError): - con.set_progress_handler(progress, 100) + def progress(): + pass + self.check(self.con.set_progress_handler, progress, 100) def test_closed_call(self): - con = sqlite.connect(":memory:") - con.close() - with self.assertRaises(sqlite.ProgrammingError): - con() + self.check(self.con) + -class ClosedCurTests(unittest.TestCase): +class ClosedCurTests(MemoryDatabaseMixin, unittest.TestCase): def test_closed(self): - con = sqlite.connect(":memory:") - cur = con.cursor() + cur = self.cx.cursor() cur.close() for method_name in ("execute", "executemany", "executescript", "fetchall", "fetchmany", "fetchone"): @@ -1852,7 +1854,7 @@ def test_on_conflict_replace(self): @requires_subprocess() class MultiprocessTests(unittest.TestCase): - CONNECTION_TIMEOUT = SHORT_TIMEOUT / 1000. # Defaults to 30 ms + CONNECTION_TIMEOUT = 0 # Disable the busy timeout. def tearDown(self): unlink(TESTFN) diff --git a/Lib/test/test_sqlite3/test_dump.py b/Lib/test/test_sqlite3/test_dump.py index d0c24b9c60e613..14a18c1ad37102 100644 --- a/Lib/test/test_sqlite3/test_dump.py +++ b/Lib/test/test_sqlite3/test_dump.py @@ -1,17 +1,12 @@ # Author: Paul Kippes import unittest -import sqlite3 as sqlite -from .test_dbapi import memory_database +from .util import memory_database +from .util import MemoryDatabaseMixin -class DumpTests(unittest.TestCase): - def setUp(self): - self.cx = sqlite.connect(":memory:") - self.cu = self.cx.cursor() - def tearDown(self): - self.cx.close() +class DumpTests(MemoryDatabaseMixin, unittest.TestCase): def test_table_dump(self): expected_sqls = [ @@ -117,6 +112,26 @@ def __getitem__(self, index): got = list(self.cx.iterdump()) self.assertEqual(expected, got) + def test_dump_virtual_tables(self): + # gh-64662 + expected = [ + "BEGIN TRANSACTION;", + "PRAGMA writable_schema=ON;", + ("INSERT INTO sqlite_master(type,name,tbl_name,rootpage,sql)" + "VALUES('table','test','test',0,'CREATE VIRTUAL TABLE test USING fts4(example)');"), + "CREATE TABLE 'test_content'(docid INTEGER PRIMARY KEY, 'c0example');", + "CREATE TABLE 'test_docsize'(docid INTEGER PRIMARY KEY, size BLOB);", + ("CREATE TABLE 'test_segdir'(level INTEGER,idx INTEGER,start_block INTEGER," + "leaves_end_block INTEGER,end_block INTEGER,root BLOB,PRIMARY KEY(level, idx));"), + "CREATE TABLE 'test_segments'(blockid INTEGER PRIMARY KEY, block BLOB);", + "CREATE TABLE 'test_stat'(id INTEGER PRIMARY KEY, value BLOB);", + "PRAGMA writable_schema=OFF;", + "COMMIT;" + ] + self.cu.execute("CREATE VIRTUAL TABLE test USING fts4(example)") + actual = list(self.cx.iterdump()) + self.assertEqual(expected, actual) + if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_sqlite3/test_factory.py b/Lib/test/test_sqlite3/test_factory.py index 7c36135ecadccd..48d35b54a2e239 100644 --- a/Lib/test/test_sqlite3/test_factory.py +++ b/Lib/test/test_sqlite3/test_factory.py @@ -24,6 +24,9 @@ import sqlite3 as sqlite from collections.abc import Sequence +from .util import memory_database +from .util import MemoryDatabaseMixin + def dict_factory(cursor, row): d = {} @@ -45,10 +48,12 @@ class OkFactory(sqlite.Connection): def __init__(self, *args, **kwargs): sqlite.Connection.__init__(self, *args, **kwargs) - for factory in DefectFactory, OkFactory: - with self.subTest(factory=factory): - con = sqlite.connect(":memory:", factory=factory) - self.assertIsInstance(con, factory) + with memory_database(factory=OkFactory) as con: + self.assertIsInstance(con, OkFactory) + regex = "Base Connection.__init__ not called." + with self.assertRaisesRegex(sqlite.ProgrammingError, regex): + with memory_database(factory=DefectFactory) as con: + self.assertIsInstance(con, DefectFactory) def test_connection_factory_relayed_call(self): # gh-95132: keyword args must not be passed as positional args @@ -57,26 +62,30 @@ def __init__(self, *args, **kwargs): kwargs["isolation_level"] = None super(Factory, self).__init__(*args, **kwargs) - con = sqlite.connect(":memory:", factory=Factory) - self.assertIsNone(con.isolation_level) - self.assertIsInstance(con, Factory) + with memory_database(factory=Factory) as con: + self.assertIsNone(con.isolation_level) + self.assertIsInstance(con, Factory) def test_connection_factory_as_positional_arg(self): class Factory(sqlite.Connection): def __init__(self, *args, **kwargs): super(Factory, self).__init__(*args, **kwargs) - con = sqlite.connect(":memory:", 5.0, 0, None, True, Factory) - self.assertIsNone(con.isolation_level) - self.assertIsInstance(con, Factory) + regex = ( + r"Passing more than 1 positional argument to _sqlite3.Connection\(\) " + r"is deprecated. Parameters 'timeout', 'detect_types', " + r"'isolation_level', 'check_same_thread', 'factory', " + r"'cached_statements' and 'uri' will become keyword-only " + r"parameters in Python 3.15." + ) + with self.assertWarnsRegex(DeprecationWarning, regex) as cm: + with memory_database(5.0, 0, None, True, Factory) as con: + self.assertIsNone(con.isolation_level) + self.assertIsInstance(con, Factory) + self.assertEqual(cm.filename, __file__) -class CursorFactoryTests(unittest.TestCase): - def setUp(self): - self.con = sqlite.connect(":memory:") - - def tearDown(self): - self.con.close() +class CursorFactoryTests(MemoryDatabaseMixin, unittest.TestCase): def test_is_instance(self): cur = self.con.cursor() @@ -94,9 +103,8 @@ def test_invalid_factory(self): # invalid callable returning non-cursor self.assertRaises(TypeError, self.con.cursor, lambda con: None) -class RowFactoryTestsBackwardsCompat(unittest.TestCase): - def setUp(self): - self.con = sqlite.connect(":memory:") + +class RowFactoryTestsBackwardsCompat(MemoryDatabaseMixin, unittest.TestCase): def test_is_produced_by_factory(self): cur = self.con.cursor(factory=MyCursor) @@ -105,12 +113,12 @@ def test_is_produced_by_factory(self): self.assertIsInstance(row, dict) cur.close() - def tearDown(self): - self.con.close() -class RowFactoryTests(unittest.TestCase): +class RowFactoryTests(MemoryDatabaseMixin, unittest.TestCase): + def setUp(self): - self.con = sqlite.connect(":memory:") + super().setUp() + self.con.row_factory = sqlite.Row def test_custom_factory(self): self.con.row_factory = lambda cur, row: list(row) @@ -118,7 +126,6 @@ def test_custom_factory(self): self.assertIsInstance(row, list) def test_sqlite_row_index(self): - self.con.row_factory = sqlite.Row row = self.con.execute("select 1 as a_1, 2 as b").fetchone() self.assertIsInstance(row, sqlite.Row) @@ -149,7 +156,6 @@ def test_sqlite_row_index(self): row[complex()] # index must be int or string def test_sqlite_row_index_unicode(self): - self.con.row_factory = sqlite.Row row = self.con.execute("select 1 as \xff").fetchone() self.assertEqual(row["\xff"], 1) with self.assertRaises(IndexError): @@ -159,7 +165,6 @@ def test_sqlite_row_index_unicode(self): def test_sqlite_row_slice(self): # A sqlite.Row can be sliced like a list. - self.con.row_factory = sqlite.Row row = self.con.execute("select 1, 2, 3, 4").fetchone() self.assertEqual(row[0:0], ()) self.assertEqual(row[0:1], (1,)) @@ -176,8 +181,7 @@ def test_sqlite_row_slice(self): self.assertEqual(row[3:0:-2], (4, 2)) def test_sqlite_row_iter(self): - """Checks if the row object is iterable""" - self.con.row_factory = sqlite.Row + # Checks if the row object is iterable. row = self.con.execute("select 1 as a, 2 as b").fetchone() # Is iterable in correct order and produces valid results: @@ -189,23 +193,20 @@ def test_sqlite_row_iter(self): self.assertEqual(items, [1, 2]) def test_sqlite_row_as_tuple(self): - """Checks if the row object can be converted to a tuple""" - self.con.row_factory = sqlite.Row + # Checks if the row object can be converted to a tuple. row = self.con.execute("select 1 as a, 2 as b").fetchone() t = tuple(row) self.assertEqual(t, (row['a'], row['b'])) def test_sqlite_row_as_dict(self): - """Checks if the row object can be correctly converted to a dictionary""" - self.con.row_factory = sqlite.Row + # Checks if the row object can be correctly converted to a dictionary. row = self.con.execute("select 1 as a, 2 as b").fetchone() d = dict(row) self.assertEqual(d["a"], row["a"]) self.assertEqual(d["b"], row["b"]) def test_sqlite_row_hash_cmp(self): - """Checks if the row object compares and hashes correctly""" - self.con.row_factory = sqlite.Row + # Checks if the row object compares and hashes correctly. row_1 = self.con.execute("select 1 as a, 2 as b").fetchone() row_2 = self.con.execute("select 1 as a, 2 as b").fetchone() row_3 = self.con.execute("select 1 as a, 3 as b").fetchone() @@ -238,30 +239,29 @@ def test_sqlite_row_hash_cmp(self): self.assertEqual(hash(row_1), hash(row_2)) def test_sqlite_row_as_sequence(self): - """ Checks if the row object can act like a sequence """ - self.con.row_factory = sqlite.Row + # Checks if the row object can act like a sequence. row = self.con.execute("select 1 as a, 2 as b").fetchone() as_tuple = tuple(row) self.assertEqual(list(reversed(row)), list(reversed(as_tuple))) self.assertIsInstance(row, Sequence) + def test_sqlite_row_keys(self): + # Checks if the row object can return a list of columns as strings. + row = self.con.execute("select 1 as a, 2 as b").fetchone() + self.assertEqual(row.keys(), ['a', 'b']) + def test_fake_cursor_class(self): # Issue #24257: Incorrect use of PyObject_IsInstance() caused # segmentation fault. # Issue #27861: Also applies for cursor factory. class FakeCursor(str): __class__ = sqlite.Cursor - self.con.row_factory = sqlite.Row self.assertRaises(TypeError, self.con.cursor, FakeCursor) self.assertRaises(TypeError, sqlite.Row, FakeCursor(), ()) - def tearDown(self): - self.con.close() -class TextFactoryTests(unittest.TestCase): - def setUp(self): - self.con = sqlite.connect(":memory:") +class TextFactoryTests(MemoryDatabaseMixin, unittest.TestCase): def test_unicode(self): austria = "Österreich" @@ -282,15 +282,17 @@ def test_custom(self): self.assertEqual(type(row[0]), str, "type of row[0] must be unicode") self.assertTrue(row[0].endswith("reich"), "column must contain original data") - def tearDown(self): - self.con.close() class TextFactoryTestsWithEmbeddedZeroBytes(unittest.TestCase): + def setUp(self): self.con = sqlite.connect(":memory:") self.con.execute("create table test (value text)") self.con.execute("insert into test (value) values (?)", ("a\x00b",)) + def tearDown(self): + self.con.close() + def test_string(self): # text_factory defaults to str row = self.con.execute("select value from test").fetchone() @@ -316,9 +318,6 @@ def test_custom(self): self.assertIs(type(row[0]), bytes) self.assertEqual(row[0], b"a\x00b") - def tearDown(self): - self.con.close() - if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_sqlite3/test_hooks.py b/Lib/test/test_sqlite3/test_hooks.py index 89230c08cc9143..49e72f8fcfbcbd 100644 --- a/Lib/test/test_sqlite3/test_hooks.py +++ b/Lib/test/test_sqlite3/test_hooks.py @@ -26,34 +26,31 @@ from test.support.os_helper import TESTFN, unlink -from test.test_sqlite3.test_dbapi import memory_database, cx_limit -from test.test_sqlite3.test_userfunctions import with_tracebacks +from .util import memory_database, cx_limit, with_tracebacks +from .util import MemoryDatabaseMixin -class CollationTests(unittest.TestCase): +class CollationTests(MemoryDatabaseMixin, unittest.TestCase): + def test_create_collation_not_string(self): - con = sqlite.connect(":memory:") with self.assertRaises(TypeError): - con.create_collation(None, lambda x, y: (x > y) - (x < y)) + self.con.create_collation(None, lambda x, y: (x > y) - (x < y)) def test_create_collation_not_callable(self): - con = sqlite.connect(":memory:") with self.assertRaises(TypeError) as cm: - con.create_collation("X", 42) + self.con.create_collation("X", 42) self.assertEqual(str(cm.exception), 'parameter must be callable') def test_create_collation_not_ascii(self): - con = sqlite.connect(":memory:") - con.create_collation("collä", lambda x, y: (x > y) - (x < y)) + self.con.create_collation("collä", lambda x, y: (x > y) - (x < y)) def test_create_collation_bad_upper(self): class BadUpperStr(str): def upper(self): return None - con = sqlite.connect(":memory:") mycoll = lambda x, y: -((x > y) - (x < y)) - con.create_collation(BadUpperStr("mycoll"), mycoll) - result = con.execute(""" + self.con.create_collation(BadUpperStr("mycoll"), mycoll) + result = self.con.execute(""" select x from ( select 'a' as x union @@ -68,8 +65,7 @@ def mycoll(x, y): # reverse order return -((x > y) - (x < y)) - con = sqlite.connect(":memory:") - con.create_collation("mycoll", mycoll) + self.con.create_collation("mycoll", mycoll) sql = """ select x from ( select 'a' as x @@ -79,21 +75,20 @@ def mycoll(x, y): select 'c' as x ) order by x collate mycoll """ - result = con.execute(sql).fetchall() + result = self.con.execute(sql).fetchall() self.assertEqual(result, [('c',), ('b',), ('a',)], msg='the expected order was not returned') - con.create_collation("mycoll", None) + self.con.create_collation("mycoll", None) with self.assertRaises(sqlite.OperationalError) as cm: - result = con.execute(sql).fetchall() + result = self.con.execute(sql).fetchall() self.assertEqual(str(cm.exception), 'no such collation sequence: mycoll') def test_collation_returns_large_integer(self): def mycoll(x, y): # reverse order return -((x > y) - (x < y)) * 2**32 - con = sqlite.connect(":memory:") - con.create_collation("mycoll", mycoll) + self.con.create_collation("mycoll", mycoll) sql = """ select x from ( select 'a' as x @@ -103,7 +98,7 @@ def mycoll(x, y): select 'c' as x ) order by x collate mycoll """ - result = con.execute(sql).fetchall() + result = self.con.execute(sql).fetchall() self.assertEqual(result, [('c',), ('b',), ('a',)], msg="the expected order was not returned") @@ -112,7 +107,7 @@ def test_collation_register_twice(self): Register two different collation functions under the same name. Verify that the last one is actually used. """ - con = sqlite.connect(":memory:") + con = self.con con.create_collation("mycoll", lambda x, y: (x > y) - (x < y)) con.create_collation("mycoll", lambda x, y: -((x > y) - (x < y))) result = con.execute(""" @@ -126,25 +121,26 @@ def test_deregister_collation(self): Register a collation, then deregister it. Make sure an error is raised if we try to use it. """ - con = sqlite.connect(":memory:") + con = self.con con.create_collation("mycoll", lambda x, y: (x > y) - (x < y)) con.create_collation("mycoll", None) with self.assertRaises(sqlite.OperationalError) as cm: con.execute("select 'a' as x union select 'b' as x order by x collate mycoll") self.assertEqual(str(cm.exception), 'no such collation sequence: mycoll') -class ProgressTests(unittest.TestCase): + +class ProgressTests(MemoryDatabaseMixin, unittest.TestCase): + def test_progress_handler_used(self): """ Test that the progress handler is invoked once it is set. """ - con = sqlite.connect(":memory:") progress_calls = [] def progress(): progress_calls.append(None) return 0 - con.set_progress_handler(progress, 1) - con.execute(""" + self.con.set_progress_handler(progress, 1) + self.con.execute(""" create table foo(a, b) """) self.assertTrue(progress_calls) @@ -153,7 +149,7 @@ def test_opcode_count(self): """ Test that the opcode argument is respected. """ - con = sqlite.connect(":memory:") + con = self.con progress_calls = [] def progress(): progress_calls.append(None) @@ -176,11 +172,10 @@ def test_cancel_operation(self): """ Test that returning a non-zero value stops the operation in progress. """ - con = sqlite.connect(":memory:") def progress(): return 1 - con.set_progress_handler(progress, 1) - curs = con.cursor() + self.con.set_progress_handler(progress, 1) + curs = self.con.cursor() self.assertRaises( sqlite.OperationalError, curs.execute, @@ -190,7 +185,7 @@ def test_clear_handler(self): """ Test that setting the progress handler to None clears the previously set handler. """ - con = sqlite.connect(":memory:") + con = self.con action = 0 def progress(): nonlocal action @@ -203,31 +198,42 @@ def progress(): @with_tracebacks(ZeroDivisionError, name="bad_progress") def test_error_in_progress_handler(self): - con = sqlite.connect(":memory:") def bad_progress(): 1 / 0 - con.set_progress_handler(bad_progress, 1) + self.con.set_progress_handler(bad_progress, 1) with self.assertRaises(sqlite.OperationalError): - con.execute(""" + self.con.execute(""" create table foo(a, b) """) @with_tracebacks(ZeroDivisionError, name="bad_progress") def test_error_in_progress_handler_result(self): - con = sqlite.connect(":memory:") class BadBool: def __bool__(self): 1 / 0 def bad_progress(): return BadBool() - con.set_progress_handler(bad_progress, 1) + self.con.set_progress_handler(bad_progress, 1) with self.assertRaises(sqlite.OperationalError): - con.execute(""" + self.con.execute(""" create table foo(a, b) """) + def test_progress_handler_keyword_args(self): + regex = ( + r"Passing keyword argument 'progress_handler' to " + r"_sqlite3.Connection.set_progress_handler\(\) is deprecated. " + r"Parameter 'progress_handler' will become positional-only in " + r"Python 3.15." + ) + + with self.assertWarnsRegex(DeprecationWarning, regex) as cm: + self.con.set_progress_handler(progress_handler=lambda: None, n=1) + self.assertEqual(cm.filename, __file__) + + +class TraceCallbackTests(MemoryDatabaseMixin, unittest.TestCase): -class TraceCallbackTests(unittest.TestCase): @contextlib.contextmanager def check_stmt_trace(self, cx, expected): try: @@ -242,12 +248,11 @@ def test_trace_callback_used(self): """ Test that the trace callback is invoked once it is set. """ - con = sqlite.connect(":memory:") traced_statements = [] def trace(statement): traced_statements.append(statement) - con.set_trace_callback(trace) - con.execute("create table foo(a, b)") + self.con.set_trace_callback(trace) + self.con.execute("create table foo(a, b)") self.assertTrue(traced_statements) self.assertTrue(any("create table foo" in stmt for stmt in traced_statements)) @@ -255,7 +260,7 @@ def test_clear_trace_callback(self): """ Test that setting the trace callback to None clears the previously set callback. """ - con = sqlite.connect(":memory:") + con = self.con traced_statements = [] def trace(statement): traced_statements.append(statement) @@ -269,7 +274,7 @@ def test_unicode_content(self): Test that the statement can contain unicode literals. """ unicode_value = '\xf6\xe4\xfc\xd6\xc4\xdc\xdf\u20ac' - con = sqlite.connect(":memory:") + con = self.con traced_statements = [] def trace(statement): traced_statements.append(statement) @@ -347,6 +352,18 @@ def test_trace_bad_handler(self): cx.set_trace_callback(lambda stmt: 5/0) cx.execute("select 1") + def test_trace_keyword_args(self): + regex = ( + r"Passing keyword argument 'trace_callback' to " + r"_sqlite3.Connection.set_trace_callback\(\) is deprecated. " + r"Parameter 'trace_callback' will become positional-only in " + r"Python 3.15." + ) + + with self.assertWarnsRegex(DeprecationWarning, regex) as cm: + self.con.set_trace_callback(trace_callback=lambda: None) + self.assertEqual(cm.filename, __file__) + if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_sqlite3/test_regression.py b/Lib/test/test_sqlite3/test_regression.py index 7e8221e7227e6e..db4e13222da9da 100644 --- a/Lib/test/test_sqlite3/test_regression.py +++ b/Lib/test/test_sqlite3/test_regression.py @@ -28,15 +28,12 @@ from test import support from unittest.mock import patch -from test.test_sqlite3.test_dbapi import memory_database, cx_limit +from .util import memory_database, cx_limit +from .util import MemoryDatabaseMixin -class RegressionTests(unittest.TestCase): - def setUp(self): - self.con = sqlite.connect(":memory:") - def tearDown(self): - self.con.close() +class RegressionTests(MemoryDatabaseMixin, unittest.TestCase): def test_pragma_user_version(self): # This used to crash pysqlite because this pragma command returns NULL for the column name @@ -45,28 +42,24 @@ def test_pragma_user_version(self): def test_pragma_schema_version(self): # This still crashed pysqlite <= 2.2.1 - con = sqlite.connect(":memory:", detect_types=sqlite.PARSE_COLNAMES) - try: + with memory_database(detect_types=sqlite.PARSE_COLNAMES) as con: cur = self.con.cursor() cur.execute("pragma schema_version") - finally: - cur.close() - con.close() def test_statement_reset(self): # pysqlite 2.1.0 to 2.2.0 have the problem that not all statements are # reset before a rollback, but only those that are still in the # statement cache. The others are not accessible from the connection object. - con = sqlite.connect(":memory:", cached_statements=5) - cursors = [con.cursor() for x in range(5)] - cursors[0].execute("create table test(x)") - for i in range(10): - cursors[0].executemany("insert into test(x) values (?)", [(x,) for x in range(10)]) + with memory_database(cached_statements=5) as con: + cursors = [con.cursor() for x in range(5)] + cursors[0].execute("create table test(x)") + for i in range(10): + cursors[0].executemany("insert into test(x) values (?)", [(x,) for x in range(10)]) - for i in range(5): - cursors[i].execute(" " * i + "select x from test") + for i in range(5): + cursors[i].execute(" " * i + "select x from test") - con.rollback() + con.rollback() def test_column_name_with_spaces(self): cur = self.con.cursor() @@ -81,17 +74,15 @@ def test_statement_finalization_on_close_db(self): # cache when closing the database. statements that were still # referenced in cursors weren't closed and could provoke " # "OperationalError: Unable to close due to unfinalised statements". - con = sqlite.connect(":memory:") cursors = [] # default statement cache size is 100 for i in range(105): - cur = con.cursor() + cur = self.con.cursor() cursors.append(cur) cur.execute("select 1 x union select " + str(i)) - con.close() def test_on_conflict_rollback(self): - con = sqlite.connect(":memory:") + con = self.con con.execute("create table foo(x, unique(x) on conflict rollback)") con.execute("insert into foo(x) values (1)") try: @@ -126,16 +117,16 @@ def test_type_map_usage(self): a statement. This test exhibits the problem. """ SELECT = "select * from foo" - con = sqlite.connect(":memory:",detect_types=sqlite.PARSE_DECLTYPES) - cur = con.cursor() - cur.execute("create table foo(bar timestamp)") - with self.assertWarnsRegex(DeprecationWarning, "adapter"): - cur.execute("insert into foo(bar) values (?)", (datetime.datetime.now(),)) - cur.execute(SELECT) - cur.execute("drop table foo") - cur.execute("create table foo(bar integer)") - cur.execute("insert into foo(bar) values (5)") - cur.execute(SELECT) + with memory_database(detect_types=sqlite.PARSE_DECLTYPES) as con: + cur = con.cursor() + cur.execute("create table foo(bar timestamp)") + with self.assertWarnsRegex(DeprecationWarning, "adapter"): + cur.execute("insert into foo(bar) values (?)", (datetime.datetime.now(),)) + cur.execute(SELECT) + cur.execute("drop table foo") + cur.execute("create table foo(bar integer)") + cur.execute("insert into foo(bar) values (5)") + cur.execute(SELECT) def test_bind_mutating_list(self): # Issue41662: Crash when mutate a list of parameters during iteration. @@ -144,11 +135,11 @@ def __conform__(self, protocol): parameters.clear() return "..." parameters = [X(), 0] - con = sqlite.connect(":memory:",detect_types=sqlite.PARSE_DECLTYPES) - con.execute("create table foo(bar X, baz integer)") - # Should not crash - with self.assertRaises(IndexError): - con.execute("insert into foo(bar, baz) values (?, ?)", parameters) + with memory_database(detect_types=sqlite.PARSE_DECLTYPES) as con: + con.execute("create table foo(bar X, baz integer)") + # Should not crash + with self.assertRaises(IndexError): + con.execute("insert into foo(bar, baz) values (?, ?)", parameters) def test_error_msg_decode_error(self): # When porting the module to Python 3.0, the error message about @@ -173,7 +164,7 @@ def upper(self): def __del__(self): con.isolation_level = "" - con = sqlite.connect(":memory:") + con = self.con con.isolation_level = None for level in "", "DEFERRED", "IMMEDIATE", "EXCLUSIVE": with self.subTest(level=level): @@ -204,8 +195,7 @@ class Cursor(sqlite.Cursor): def __init__(self, con): pass - con = sqlite.connect(":memory:") - cur = Cursor(con) + cur = Cursor(self.con) with self.assertRaises(sqlite.ProgrammingError): cur.execute("select 4+5").fetchall() with self.assertRaisesRegex(sqlite.ProgrammingError, @@ -238,7 +228,9 @@ def test_auto_commit(self): 2.5.3 introduced a regression so that these could no longer be created. """ - con = sqlite.connect(":memory:", isolation_level=None) + with memory_database(isolation_level=None) as con: + self.assertIsNone(con.isolation_level) + self.assertFalse(con.in_transaction) def test_pragma_autocommit(self): """ @@ -273,9 +265,7 @@ def test_recursive_cursor_use(self): Recursively using a cursor, such as when reusing it from a generator led to segfaults. Now we catch recursive cursor usage and raise a ProgrammingError. """ - con = sqlite.connect(":memory:") - - cur = con.cursor() + cur = self.con.cursor() cur.execute("create table a (bar)") cur.execute("create table b (baz)") @@ -295,29 +285,30 @@ def test_convert_timestamp_microsecond_padding(self): since the microsecond string "456" actually represents "456000". """ - con = sqlite.connect(":memory:", detect_types=sqlite.PARSE_DECLTYPES) - cur = con.cursor() - cur.execute("CREATE TABLE t (x TIMESTAMP)") + with memory_database(detect_types=sqlite.PARSE_DECLTYPES) as con: + cur = con.cursor() + cur.execute("CREATE TABLE t (x TIMESTAMP)") - # Microseconds should be 456000 - cur.execute("INSERT INTO t (x) VALUES ('2012-04-04 15:06:00.456')") + # Microseconds should be 456000 + cur.execute("INSERT INTO t (x) VALUES ('2012-04-04 15:06:00.456')") - # Microseconds should be truncated to 123456 - cur.execute("INSERT INTO t (x) VALUES ('2012-04-04 15:06:00.123456789')") + # Microseconds should be truncated to 123456 + cur.execute("INSERT INTO t (x) VALUES ('2012-04-04 15:06:00.123456789')") - cur.execute("SELECT * FROM t") - with self.assertWarnsRegex(DeprecationWarning, "converter"): - values = [x[0] for x in cur.fetchall()] + cur.execute("SELECT * FROM t") + with self.assertWarnsRegex(DeprecationWarning, "converter"): + values = [x[0] for x in cur.fetchall()] - self.assertEqual(values, [ - datetime.datetime(2012, 4, 4, 15, 6, 0, 456000), - datetime.datetime(2012, 4, 4, 15, 6, 0, 123456), - ]) + self.assertEqual(values, [ + datetime.datetime(2012, 4, 4, 15, 6, 0, 456000), + datetime.datetime(2012, 4, 4, 15, 6, 0, 123456), + ]) def test_invalid_isolation_level_type(self): # isolation level is a string, not an integer - self.assertRaises(TypeError, - sqlite.connect, ":memory:", isolation_level=123) + regex = "isolation_level must be str or None" + with self.assertRaisesRegex(TypeError, regex): + memory_database(isolation_level=123).__enter__() def test_null_character(self): @@ -333,7 +324,7 @@ def test_null_character(self): cur.execute, query) def test_surrogates(self): - con = sqlite.connect(":memory:") + con = self.con self.assertRaises(UnicodeEncodeError, con, "select '\ud8ff'") self.assertRaises(UnicodeEncodeError, con, "select '\udcff'") cur = con.cursor() @@ -359,7 +350,7 @@ def test_commit_cursor_reset(self): to return rows multiple times when fetched from cursors after commit. See issues 10513 and 23129 for details. """ - con = sqlite.connect(":memory:") + con = self.con con.executescript(""" create table t(c); create table t2(c); @@ -391,10 +382,9 @@ def test_bpo31770(self): """ def callback(*args): pass - con = sqlite.connect(":memory:") - cur = sqlite.Cursor(con) + cur = sqlite.Cursor(self.con) ref = weakref.ref(cur, callback) - cur.__init__(con) + cur.__init__(self.con) del cur # The interpreter shouldn't crash when ref is collected. del ref @@ -425,6 +415,7 @@ def test_return_empty_bytestring(self): def test_table_lock_cursor_replace_stmt(self): with memory_database() as con: + con = self.con cur = con.cursor() cur.execute("create table t(t)") cur.executemany("insert into t values(?)", diff --git a/Lib/test/test_sqlite3/test_transactions.py b/Lib/test/test_sqlite3/test_transactions.py index 5d211dd47b0b6b..a3de7a7a82ec1c 100644 --- a/Lib/test/test_sqlite3/test_transactions.py +++ b/Lib/test/test_sqlite3/test_transactions.py @@ -24,22 +24,21 @@ import sqlite3 as sqlite from contextlib import contextmanager -from test.support import LOOPBACK_TIMEOUT from test.support.os_helper import TESTFN, unlink from test.support.script_helper import assert_python_ok -from test.test_sqlite3.test_dbapi import memory_database - - -TIMEOUT = LOOPBACK_TIMEOUT / 10 +from .util import memory_database +from .util import MemoryDatabaseMixin class TransactionTests(unittest.TestCase): def setUp(self): - self.con1 = sqlite.connect(TESTFN, timeout=TIMEOUT) + # We can disable the busy handlers, since we control + # the order of SQLite C API operations. + self.con1 = sqlite.connect(TESTFN, timeout=0) self.cur1 = self.con1.cursor() - self.con2 = sqlite.connect(TESTFN, timeout=TIMEOUT) + self.con2 = sqlite.connect(TESTFN, timeout=0) self.cur2 = self.con2.cursor() def tearDown(self): @@ -119,10 +118,8 @@ def test_raise_timeout(self): self.cur2.execute("insert into test(i) values (5)") def test_locking(self): - """ - This tests the improved concurrency with pysqlite 2.3.4. You needed - to roll back con2 before you could commit con1. - """ + # This tests the improved concurrency with pysqlite 2.3.4. You needed + # to roll back con2 before you could commit con1. self.cur1.execute("create table test(i)") self.cur1.execute("insert into test(i) values (5)") with self.assertRaises(sqlite.OperationalError): @@ -132,14 +129,14 @@ def test_locking(self): def test_rollback_cursor_consistency(self): """Check that cursors behave correctly after rollback.""" - con = sqlite.connect(":memory:") - cur = con.cursor() - cur.execute("create table test(x)") - cur.execute("insert into test(x) values (5)") - cur.execute("select 1 union select 2 union select 3") + with memory_database() as con: + cur = con.cursor() + cur.execute("create table test(x)") + cur.execute("insert into test(x) values (5)") + cur.execute("select 1 union select 2 union select 3") - con.rollback() - self.assertEqual(cur.fetchall(), [(1,), (2,), (3,)]) + con.rollback() + self.assertEqual(cur.fetchall(), [(1,), (2,), (3,)]) def test_multiple_cursors_and_iternext(self): # gh-94028: statements are cleared and reset in cursor iternext. @@ -218,10 +215,7 @@ def test_no_duplicate_rows_after_rollback_new_query(self): -class SpecialCommandTests(unittest.TestCase): - def setUp(self): - self.con = sqlite.connect(":memory:") - self.cur = self.con.cursor() +class SpecialCommandTests(MemoryDatabaseMixin, unittest.TestCase): def test_drop_table(self): self.cur.execute("create table test(i)") @@ -233,14 +227,8 @@ def test_pragma(self): self.cur.execute("insert into test(i) values (5)") self.cur.execute("pragma count_changes=1") - def tearDown(self): - self.cur.close() - self.con.close() - -class TransactionalDDL(unittest.TestCase): - def setUp(self): - self.con = sqlite.connect(":memory:") +class TransactionalDDL(MemoryDatabaseMixin, unittest.TestCase): def test_ddl_does_not_autostart_transaction(self): # For backwards compatibility reasons, DDL statements should not @@ -268,9 +256,6 @@ def test_transactional_ddl(self): with self.assertRaises(sqlite.OperationalError): self.con.execute("select * from test") - def tearDown(self): - self.con.close() - class IsolationLevelFromInit(unittest.TestCase): CREATE = "create table t(t)" diff --git a/Lib/test/test_sqlite3/test_userfunctions.py b/Lib/test/test_sqlite3/test_userfunctions.py index 05c2fb3aa6f8f2..c6c3db159add64 100644 --- a/Lib/test/test_sqlite3/test_userfunctions.py +++ b/Lib/test/test_sqlite3/test_userfunctions.py @@ -21,54 +21,15 @@ # misrepresented as being the original software. # 3. This notice may not be removed or altered from any source distribution. -import contextlib -import functools -import io -import re import sys import unittest import sqlite3 as sqlite from unittest.mock import Mock, patch -from test.support import bigmemtest, catch_unraisable_exception, gc_collect - -from test.test_sqlite3.test_dbapi import cx_limit - - -def with_tracebacks(exc, regex="", name=""): - """Convenience decorator for testing callback tracebacks.""" - def decorator(func): - _regex = re.compile(regex) if regex else None - @functools.wraps(func) - def wrapper(self, *args, **kwargs): - with catch_unraisable_exception() as cm: - # First, run the test with traceback enabled. - with check_tracebacks(self, cm, exc, _regex, name): - func(self, *args, **kwargs) - - # Then run the test with traceback disabled. - func(self, *args, **kwargs) - return wrapper - return decorator - - -@contextlib.contextmanager -def check_tracebacks(self, cm, exc, regex, obj_name): - """Convenience context manager for testing callback tracebacks.""" - sqlite.enable_callback_tracebacks(True) - try: - buf = io.StringIO() - with contextlib.redirect_stderr(buf): - yield - - self.assertEqual(cm.unraisable.exc_type, exc) - if regex: - msg = str(cm.unraisable.exc_value) - self.assertIsNotNone(regex.search(msg)) - if obj_name: - self.assertEqual(cm.unraisable.object.__name__, obj_name) - finally: - sqlite.enable_callback_tracebacks(False) +from test.support import bigmemtest, gc_collect + +from .util import cx_limit, memory_database +from .util import with_tracebacks def func_returntext(): @@ -405,19 +366,19 @@ def test_func_deterministic_keyword_only(self): def test_function_destructor_via_gc(self): # See bpo-44304: The destructor of the user function can # crash if is called without the GIL from the gc functions - dest = sqlite.connect(':memory:') def md5sum(t): return - dest.create_function("md5", 1, md5sum) - x = dest("create table lang (name, first_appeared)") - del md5sum, dest + with memory_database() as dest: + dest.create_function("md5", 1, md5sum) + x = dest("create table lang (name, first_appeared)") + del md5sum, dest - y = [x] - y.append(y) + y = [x] + y.append(y) - del x,y - gc_collect() + del x,y + gc_collect() @with_tracebacks(OverflowError) def test_func_return_too_large_int(self): @@ -460,6 +421,29 @@ def test_func_return_illegal_value(self): self.assertRaisesRegex(sqlite.OperationalError, msg, self.con.execute, "select badreturn()") + def test_func_keyword_args(self): + regex = ( + r"Passing keyword arguments 'name', 'narg' and 'func' to " + r"_sqlite3.Connection.create_function\(\) is deprecated. " + r"Parameters 'name', 'narg' and 'func' will become " + r"positional-only in Python 3.15." + ) + + def noop(): + return None + + with self.assertWarnsRegex(DeprecationWarning, regex) as cm: + self.con.create_function("noop", 0, func=noop) + self.assertEqual(cm.filename, __file__) + + with self.assertWarnsRegex(DeprecationWarning, regex) as cm: + self.con.create_function("noop", narg=0, func=noop) + self.assertEqual(cm.filename, __file__) + + with self.assertWarnsRegex(DeprecationWarning, regex) as cm: + self.con.create_function(name="noop", narg=0, func=noop) + self.assertEqual(cm.filename, __file__) + class WindowSumInt: def __init__(self): @@ -514,6 +498,10 @@ def setUp(self): """ self.con.create_window_function("sumint", 1, WindowSumInt) + def tearDown(self): + self.cur.close() + self.con.close() + def test_win_sum_int(self): self.cur.execute(self.query % "sumint") self.assertEqual(self.cur.fetchall(), self.expected) @@ -634,6 +622,7 @@ def setUp(self): """) cur.execute("insert into test(t, i, f, n, b) values (?, ?, ?, ?, ?)", ("foo", 5, 3.14, None, memoryview(b"blob"),)) + cur.close() self.con.create_aggregate("nostep", 1, AggrNoStep) self.con.create_aggregate("nofinalize", 1, AggrNoFinalize) @@ -646,9 +635,7 @@ def setUp(self): self.con.create_aggregate("aggtxt", 1, AggrText) def tearDown(self): - #self.cur.close() - #self.con.close() - pass + self.con.close() def test_aggr_error_on_create(self): with self.assertRaises(sqlite.OperationalError): @@ -750,6 +737,27 @@ def test_aggr_text(self): val = cur.fetchone()[0] self.assertEqual(val, txt) + def test_agg_keyword_args(self): + regex = ( + r"Passing keyword arguments 'name', 'n_arg' and 'aggregate_class' to " + r"_sqlite3.Connection.create_aggregate\(\) is deprecated. " + r"Parameters 'name', 'n_arg' and 'aggregate_class' will become " + r"positional-only in Python 3.15." + ) + + with self.assertWarnsRegex(DeprecationWarning, regex) as cm: + self.con.create_aggregate("test", 1, aggregate_class=AggrText) + self.assertEqual(cm.filename, __file__) + + with self.assertWarnsRegex(DeprecationWarning, regex) as cm: + self.con.create_aggregate("test", n_arg=1, aggregate_class=AggrText) + self.assertEqual(cm.filename, __file__) + + with self.assertWarnsRegex(DeprecationWarning, regex) as cm: + self.con.create_aggregate(name="test", n_arg=0, + aggregate_class=AggrText) + self.assertEqual(cm.filename, __file__) + class AuthorizerTests(unittest.TestCase): @staticmethod @@ -775,7 +783,7 @@ def setUp(self): self.con.set_authorizer(self.authorizer_cb) def tearDown(self): - pass + self.con.close() def test_table_access(self): with self.assertRaises(sqlite.DatabaseError) as cm: @@ -792,6 +800,18 @@ def test_clear_authorizer(self): self.con.execute("select * from t2") self.con.execute("select c2 from t1") + def test_authorizer_keyword_args(self): + regex = ( + r"Passing keyword argument 'authorizer_callback' to " + r"_sqlite3.Connection.set_authorizer\(\) is deprecated. " + r"Parameter 'authorizer_callback' will become positional-only in " + r"Python 3.15." + ) + + with self.assertWarnsRegex(DeprecationWarning, regex) as cm: + self.con.set_authorizer(authorizer_callback=lambda: None) + self.assertEqual(cm.filename, __file__) + class AuthorizerRaiseExceptionTests(AuthorizerTests): @staticmethod diff --git a/Lib/test/test_sqlite3/util.py b/Lib/test/test_sqlite3/util.py new file mode 100644 index 00000000000000..5599823838beea --- /dev/null +++ b/Lib/test/test_sqlite3/util.py @@ -0,0 +1,77 @@ +import contextlib +import functools +import io +import re +import sqlite3 +import test.support + + +# Helper for temporary memory databases +def memory_database(*args, **kwargs): + cx = sqlite3.connect(":memory:", *args, **kwargs) + return contextlib.closing(cx) + + +# Temporarily limit a database connection parameter +@contextlib.contextmanager +def cx_limit(cx, category=sqlite3.SQLITE_LIMIT_SQL_LENGTH, limit=128): + try: + _prev = cx.setlimit(category, limit) + yield limit + finally: + cx.setlimit(category, _prev) + + +def with_tracebacks(exc, regex="", name=""): + """Convenience decorator for testing callback tracebacks.""" + def decorator(func): + _regex = re.compile(regex) if regex else None + @functools.wraps(func) + def wrapper(self, *args, **kwargs): + with test.support.catch_unraisable_exception() as cm: + # First, run the test with traceback enabled. + with check_tracebacks(self, cm, exc, _regex, name): + func(self, *args, **kwargs) + + # Then run the test with traceback disabled. + func(self, *args, **kwargs) + return wrapper + return decorator + + +@contextlib.contextmanager +def check_tracebacks(self, cm, exc, regex, obj_name): + """Convenience context manager for testing callback tracebacks.""" + sqlite3.enable_callback_tracebacks(True) + try: + buf = io.StringIO() + with contextlib.redirect_stderr(buf): + yield + + self.assertEqual(cm.unraisable.exc_type, exc) + if regex: + msg = str(cm.unraisable.exc_value) + self.assertIsNotNone(regex.search(msg)) + if obj_name: + self.assertEqual(cm.unraisable.object.__name__, obj_name) + finally: + sqlite3.enable_callback_tracebacks(False) + + +class MemoryDatabaseMixin: + + def setUp(self): + self.con = sqlite3.connect(":memory:") + self.cur = self.con.cursor() + + def tearDown(self): + self.cur.close() + self.con.close() + + @property + def cx(self): + return self.con + + @property + def cu(self): + return self.cur diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py index 6117ca3fdba1b7..3fdfa2960503b8 100644 --- a/Lib/test/test_ssl.py +++ b/Lib/test/test_ssl.py @@ -10,11 +10,15 @@ from test.support import threading_helper from test.support import warnings_helper from test.support import asyncore +import array +import re import socket import select +import struct import time import enum import gc +import http.client import os import errno import pprint @@ -57,10 +61,10 @@ PROTOCOL_TO_TLS_VERSION[proto] = ver def data_file(*name): - return os.path.join(os.path.dirname(__file__), *name) + return os.path.join(os.path.dirname(__file__), "certdata", *name) # The custom key and certificate files used in test_ssl are generated -# using Lib/test/make_ssl_certs.py. +# using Lib/test/certdata/make_ssl_certs.py. # Other certificates are simply fetched from the internet servers they # are meant to authenticate. @@ -638,7 +642,7 @@ def test_openssl111_deprecations(self): def bad_cert_test(self, certfile): """Check that trying to use the given client certificate fails""" certfile = os.path.join(os.path.dirname(__file__) or os.curdir, - certfile) + "certdata", certfile) sock = socket.socket() self.addCleanup(sock.close) with self.assertRaises(ssl.SSLError): @@ -1736,6 +1740,10 @@ def test_buffer_types(self): self.assertEqual(bio.read(), b'bar') bio.write(memoryview(b'baz')) self.assertEqual(bio.read(), b'baz') + m = memoryview(bytearray(b'noncontig')) + noncontig_writable = m[::-2] + with self.assertRaises(BufferError): + bio.write(memoryview(noncontig_writable)) def test_error_types(self): bio = ssl.MemoryBIO() @@ -2179,6 +2187,7 @@ def test_timeout_connect_ex(self): self.assertIn(rc, (errno.EAGAIN, errno.EWOULDBLOCK)) @unittest.skipUnless(socket_helper.IPV6_ENABLED, 'Needs IPv6') + @support.requires_resource('walltime') def test_get_server_certificate_ipv6(self): with socket_helper.transient_internet('ipv6.google.com'): _test_get_server_certificate(self, 'ipv6.google.com', 443) @@ -2737,6 +2746,7 @@ def try_protocol_combo(server_protocol, client_protocol, expect_success, class ThreadedTests(unittest.TestCase): + @support.requires_resource('walltime') def test_echo(self): """Basic test of an SSL client connecting to a server""" if support.verbose: @@ -3304,12 +3314,12 @@ def test_socketserver(self): # try to connect if support.verbose: sys.stdout.write('\n') - with open(CERTFILE, 'rb') as f: + # Get this test file itself: + with open(__file__, 'rb') as f: d1 = f.read() d2 = '' # now fetch the same data from the HTTPS server - url = 'https://localhost:%d/%s' % ( - server.port, os.path.split(CERTFILE)[1]) + url = f'https://localhost:{server.port}/test_ssl.py' context = ssl.create_default_context(cafile=SIGNING_CA) f = urllib.request.urlopen(url, context=context) try: @@ -3508,6 +3518,27 @@ def test_recv_zero(self): self.assertEqual(s.recv(0), b"") self.assertEqual(s.recv_into(bytearray()), 0) + def test_recv_into_buffer_protocol_len(self): + server = ThreadedEchoServer(CERTFILE) + self.enterContext(server) + s = socket.create_connection((HOST, server.port)) + self.addCleanup(s.close) + s = test_wrap_socket(s, suppress_ragged_eofs=False) + self.addCleanup(s.close) + + s.send(b"data") + buf = array.array('I', [0, 0]) + self.assertEqual(s.recv_into(buf), 4) + self.assertEqual(bytes(buf)[:4], b"data") + + class B(bytearray): + def __len__(self): + 1/0 + s.send(b"data") + buf = B(6) + self.assertEqual(s.recv_into(buf), 4) + self.assertEqual(bytes(buf), b"data\0\0") + def test_nonblocking_send(self): server = ThreadedEchoServer(CERTFILE, certreqs=ssl.CERT_NONE, @@ -4227,6 +4258,107 @@ def test_session_handling(self): self.assertEqual(str(e.exception), 'Session refers to a different SSLContext.') + @requires_tls_version('TLSv1_2') + @unittest.skipUnless(ssl.HAS_PSK, 'TLS-PSK disabled on this OpenSSL build') + def test_psk(self): + psk = bytes.fromhex('deadbeef') + + client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) + client_context.check_hostname = False + client_context.verify_mode = ssl.CERT_NONE + client_context.maximum_version = ssl.TLSVersion.TLSv1_2 + client_context.set_ciphers('PSK') + client_context.set_psk_client_callback(lambda hint: (None, psk)) + + server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) + server_context.maximum_version = ssl.TLSVersion.TLSv1_2 + server_context.set_ciphers('PSK') + server_context.set_psk_server_callback(lambda identity: psk) + + # correct PSK should connect + server = ThreadedEchoServer(context=server_context) + with server: + with client_context.wrap_socket(socket.socket()) as s: + s.connect((HOST, server.port)) + + # incorrect PSK should fail + incorrect_psk = bytes.fromhex('cafebabe') + client_context.set_psk_client_callback(lambda hint: (None, incorrect_psk)) + server = ThreadedEchoServer(context=server_context) + with server: + with client_context.wrap_socket(socket.socket()) as s: + with self.assertRaises(ssl.SSLError): + s.connect((HOST, server.port)) + + # identity_hint and client_identity should be sent to the other side + identity_hint = 'identity-hint' + client_identity = 'client-identity' + + def client_callback(hint): + self.assertEqual(hint, identity_hint) + return client_identity, psk + + def server_callback(identity): + self.assertEqual(identity, client_identity) + return psk + + client_context.set_psk_client_callback(client_callback) + server_context.set_psk_server_callback(server_callback, identity_hint) + server = ThreadedEchoServer(context=server_context) + with server: + with client_context.wrap_socket(socket.socket()) as s: + s.connect((HOST, server.port)) + + # adding client callback to server or vice versa raises an exception + with self.assertRaisesRegex(ssl.SSLError, 'Cannot add PSK server callback'): + client_context.set_psk_server_callback(server_callback, identity_hint) + with self.assertRaisesRegex(ssl.SSLError, 'Cannot add PSK client callback'): + server_context.set_psk_client_callback(client_callback) + + # test with UTF-8 identities + identity_hint = '身份暗示' # Translation: "Identity hint" + client_identity = '客户身份' # Translation: "Customer identity" + + client_context.set_psk_client_callback(client_callback) + server_context.set_psk_server_callback(server_callback, identity_hint) + server = ThreadedEchoServer(context=server_context) + with server: + with client_context.wrap_socket(socket.socket()) as s: + s.connect((HOST, server.port)) + + @requires_tls_version('TLSv1_3') + @unittest.skipUnless(ssl.HAS_PSK, 'TLS-PSK disabled on this OpenSSL build') + def test_psk_tls1_3(self): + psk = bytes.fromhex('deadbeef') + identity_hint = 'identity-hint' + client_identity = 'client-identity' + + def client_callback(hint): + # identity_hint is not sent to the client in TLS 1.3 + self.assertIsNone(hint) + return client_identity, psk + + def server_callback(identity): + self.assertEqual(identity, client_identity) + return psk + + client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) + client_context.check_hostname = False + client_context.verify_mode = ssl.CERT_NONE + client_context.minimum_version = ssl.TLSVersion.TLSv1_3 + client_context.set_ciphers('PSK') + client_context.set_psk_client_callback(client_callback) + + server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) + server_context.minimum_version = ssl.TLSVersion.TLSv1_3 + server_context.set_ciphers('PSK') + server_context.set_psk_server_callback(server_callback, identity_hint) + + server = ThreadedEchoServer(context=server_context) + with server: + with client_context.wrap_socket(socket.socket()) as s: + s.connect((HOST, server.port)) + @unittest.skipUnless(has_tls_version('TLSv1_3'), "Test needs TLS 1.3") class TestPostHandshakeAuth(unittest.TestCase): @@ -4659,6 +4791,254 @@ def sni_cb(sock, servername, ctx): s.connect((HOST, server.port)) +def set_socket_so_linger_on_with_zero_timeout(sock): + sock.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER, struct.pack('ii', 1, 0)) + + +class TestPreHandshakeClose(unittest.TestCase): + """Verify behavior of close sockets with received data before to the handshake. + """ + + class SingleConnectionTestServerThread(threading.Thread): + + def __init__(self, *, name, call_after_accept, timeout=None): + self.call_after_accept = call_after_accept + self.received_data = b'' # set by .run() + self.wrap_error = None # set by .run() + self.listener = None # set by .start() + self.port = None # set by .start() + if timeout is None: + self.timeout = support.SHORT_TIMEOUT + else: + self.timeout = timeout + super().__init__(name=name) + + def __enter__(self): + self.start() + return self + + def __exit__(self, *args): + try: + if self.listener: + self.listener.close() + except OSError: + pass + self.join() + self.wrap_error = None # avoid dangling references + + def start(self): + self.ssl_ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH) + self.ssl_ctx.verify_mode = ssl.CERT_REQUIRED + self.ssl_ctx.load_verify_locations(cafile=ONLYCERT) + self.ssl_ctx.load_cert_chain(certfile=ONLYCERT, keyfile=ONLYKEY) + self.listener = socket.socket() + self.port = socket_helper.bind_port(self.listener) + self.listener.settimeout(self.timeout) + self.listener.listen(1) + super().start() + + def run(self): + try: + conn, address = self.listener.accept() + except TimeoutError: + # on timeout, just close the listener + return + finally: + self.listener.close() + + with conn: + if self.call_after_accept(conn): + return + try: + tls_socket = self.ssl_ctx.wrap_socket(conn, server_side=True) + except OSError as err: # ssl.SSLError inherits from OSError + self.wrap_error = err + else: + try: + self.received_data = tls_socket.recv(400) + except OSError: + pass # closed, protocol error, etc. + + def non_linux_skip_if_other_okay_error(self, err): + if sys.platform == "linux": + return # Expect the full test setup to always work on Linux. + if (isinstance(err, ConnectionResetError) or + (isinstance(err, OSError) and err.errno == errno.EINVAL) or + re.search('wrong.version.number', getattr(err, "reason", ""), re.I)): + # On Windows the TCP RST leads to a ConnectionResetError + # (ECONNRESET) which Linux doesn't appear to surface to userspace. + # If wrap_socket() winds up on the "if connected:" path and doing + # the actual wrapping... we get an SSLError from OpenSSL. Typically + # WRONG_VERSION_NUMBER. While appropriate, neither is the scenario + # we're specifically trying to test. The way this test is written + # is known to work on Linux. We'll skip it anywhere else that it + # does not present as doing so. + try: + self.skipTest(f"Could not recreate conditions on {sys.platform}:" + f" {err=}") + finally: + # gh-108342: Explicitly break the reference cycle + err = None + + # If maintaining this conditional winds up being a problem. + # just turn this into an unconditional skip anything but Linux. + # The important thing is that our CI has the logic covered. + + def test_preauth_data_to_tls_server(self): + server_accept_called = threading.Event() + ready_for_server_wrap_socket = threading.Event() + + def call_after_accept(unused): + server_accept_called.set() + if not ready_for_server_wrap_socket.wait(support.SHORT_TIMEOUT): + raise RuntimeError("wrap_socket event never set, test may fail.") + return False # Tell the server thread to continue. + + server = self.SingleConnectionTestServerThread( + call_after_accept=call_after_accept, + name="preauth_data_to_tls_server") + self.enterContext(server) # starts it & unittest.TestCase stops it. + + with socket.socket() as client: + client.connect(server.listener.getsockname()) + # This forces an immediate connection close via RST on .close(). + set_socket_so_linger_on_with_zero_timeout(client) + client.setblocking(False) + + server_accept_called.wait() + client.send(b"DELETE /data HTTP/1.0\r\n\r\n") + client.close() # RST + + ready_for_server_wrap_socket.set() + server.join() + + wrap_error = server.wrap_error + server.wrap_error = None + try: + self.assertEqual(b"", server.received_data) + self.assertIsInstance(wrap_error, OSError) # All platforms. + self.non_linux_skip_if_other_okay_error(wrap_error) + self.assertIsInstance(wrap_error, ssl.SSLError) + self.assertIn("before TLS handshake with data", wrap_error.args[1]) + self.assertIn("before TLS handshake with data", wrap_error.reason) + self.assertNotEqual(0, wrap_error.args[0]) + self.assertIsNone(wrap_error.library, msg="attr must exist") + finally: + # gh-108342: Explicitly break the reference cycle + wrap_error = None + server = None + + def test_preauth_data_to_tls_client(self): + server_can_continue_with_wrap_socket = threading.Event() + client_can_continue_with_wrap_socket = threading.Event() + + def call_after_accept(conn_to_client): + if not server_can_continue_with_wrap_socket.wait(support.SHORT_TIMEOUT): + print("ERROR: test client took too long") + + # This forces an immediate connection close via RST on .close(). + set_socket_so_linger_on_with_zero_timeout(conn_to_client) + conn_to_client.send( + b"HTTP/1.0 307 Temporary Redirect\r\n" + b"Location: https://example.com/someone-elses-server\r\n" + b"\r\n") + conn_to_client.close() # RST + client_can_continue_with_wrap_socket.set() + return True # Tell the server to stop. + + server = self.SingleConnectionTestServerThread( + call_after_accept=call_after_accept, + name="preauth_data_to_tls_client") + self.enterContext(server) # starts it & unittest.TestCase stops it. + # Redundant; call_after_accept sets SO_LINGER on the accepted conn. + set_socket_so_linger_on_with_zero_timeout(server.listener) + + with socket.socket() as client: + client.connect(server.listener.getsockname()) + server_can_continue_with_wrap_socket.set() + + if not client_can_continue_with_wrap_socket.wait(support.SHORT_TIMEOUT): + self.fail("test server took too long") + ssl_ctx = ssl.create_default_context() + try: + tls_client = ssl_ctx.wrap_socket( + client, server_hostname="localhost") + except OSError as err: # SSLError inherits from OSError + wrap_error = err + received_data = b"" + else: + wrap_error = None + received_data = tls_client.recv(400) + tls_client.close() + + server.join() + try: + self.assertEqual(b"", received_data) + self.assertIsInstance(wrap_error, OSError) # All platforms. + self.non_linux_skip_if_other_okay_error(wrap_error) + self.assertIsInstance(wrap_error, ssl.SSLError) + self.assertIn("before TLS handshake with data", wrap_error.args[1]) + self.assertIn("before TLS handshake with data", wrap_error.reason) + self.assertNotEqual(0, wrap_error.args[0]) + self.assertIsNone(wrap_error.library, msg="attr must exist") + finally: + # gh-108342: Explicitly break the reference cycle + wrap_error = None + server = None + + def test_https_client_non_tls_response_ignored(self): + server_responding = threading.Event() + + class SynchronizedHTTPSConnection(http.client.HTTPSConnection): + def connect(self): + # Call clear text HTTP connect(), not the encrypted HTTPS (TLS) + # connect(): wrap_socket() is called manually below. + http.client.HTTPConnection.connect(self) + + # Wait for our fault injection server to have done its thing. + if not server_responding.wait(support.SHORT_TIMEOUT) and support.verbose: + sys.stdout.write("server_responding event never set.") + self.sock = self._context.wrap_socket( + self.sock, server_hostname=self.host) + + def call_after_accept(conn_to_client): + # This forces an immediate connection close via RST on .close(). + set_socket_so_linger_on_with_zero_timeout(conn_to_client) + conn_to_client.send( + b"HTTP/1.0 402 Payment Required\r\n" + b"\r\n") + conn_to_client.close() # RST + server_responding.set() + return True # Tell the server to stop. + + timeout = 2.0 + server = self.SingleConnectionTestServerThread( + call_after_accept=call_after_accept, + name="non_tls_http_RST_responder", + timeout=timeout) + self.enterContext(server) # starts it & unittest.TestCase stops it. + # Redundant; call_after_accept sets SO_LINGER on the accepted conn. + set_socket_so_linger_on_with_zero_timeout(server.listener) + + connection = SynchronizedHTTPSConnection( + server.listener.getsockname()[0], + port=server.port, + context=ssl.create_default_context(), + timeout=timeout, + ) + + # There are lots of reasons this raises as desired, long before this + # test was added. Sending the request requires a successful TLS wrapped + # socket; that fails if the connection is broken. It may seem pointless + # to test this. It serves as an illustration of something that we never + # want to happen... properly not happening. + with self.assertRaises(OSError): + connection.request("HEAD", "/test", headers={"Host": "localhost"}) + response = connection.getresponse() + + server.join() + + class TestEnumerations(unittest.TestCase): def test_tlsversion(self): diff --git a/Lib/test/test_stable_abi_ctypes.py b/Lib/test/test_stable_abi_ctypes.py index 566d36a3f5ba11..4976ac3642bbe4 100644 --- a/Lib/test/test_stable_abi_ctypes.py +++ b/Lib/test/test_stable_abi_ctypes.py @@ -375,6 +375,7 @@ def test_windows_feature_macros(self): "PyList_Type", "PyLongRangeIter_Type", "PyLong_AsDouble", + "PyLong_AsInt", "PyLong_AsLong", "PyLong_AsLongAndOverflow", "PyLong_AsLongLong", @@ -404,6 +405,8 @@ def test_windows_feature_macros(self): "PyMapping_GetOptionalItemString", "PyMapping_HasKey", "PyMapping_HasKeyString", + "PyMapping_HasKeyStringWithError", + "PyMapping_HasKeyWithError", "PyMapping_Items", "PyMapping_Keys", "PyMapping_Length", @@ -415,6 +418,10 @@ def test_windows_feature_macros(self): "PyMem_Calloc", "PyMem_Free", "PyMem_Malloc", + "PyMem_RawCalloc", + "PyMem_RawFree", + "PyMem_RawMalloc", + "PyMem_RawRealloc", "PyMem_Realloc", "PyMemberDescr_Type", "PyMember_GetOne", @@ -541,6 +548,8 @@ def test_windows_feature_macros(self): "PyObject_GetTypeData", "PyObject_HasAttr", "PyObject_HasAttrString", + "PyObject_HasAttrStringWithError", + "PyObject_HasAttrWithError", "PyObject_Hash", "PyObject_HashNotImplemented", "PyObject_Init", @@ -617,6 +626,8 @@ def test_windows_feature_macros(self): "PySys_AddWarnOption", "PySys_AddWarnOptionUnicode", "PySys_AddXOption", + "PySys_Audit", + "PySys_AuditTuple", "PySys_FormatStderr", "PySys_FormatStdout", "PySys_GetObject", @@ -765,6 +776,8 @@ def test_windows_feature_macros(self): "PyUnicode_DecodeUnicodeEscape", "PyUnicode_EncodeFSDefault", "PyUnicode_EncodeLocale", + "PyUnicode_EqualToUTF8", + "PyUnicode_EqualToUTF8AndSize", "PyUnicode_FSConverter", "PyUnicode_FSDecoder", "PyUnicode_Find", @@ -846,6 +859,7 @@ def test_windows_feature_macros(self): "Py_InitializeEx", "Py_Is", "Py_IsFalse", + "Py_IsFinalizing", "Py_IsInitialized", "Py_IsNone", "Py_IsTrue", @@ -892,6 +906,7 @@ def test_windows_feature_macros(self): "_Py_IncRef", "_Py_NoneStruct", "_Py_NotImplementedStruct", + "_Py_SetRefcnt", "_Py_SwappedOp", "_Py_TrueStruct", "_Py_VaBuildValue_SizeT", diff --git a/Lib/test/test_stat.py b/Lib/test/test_stat.py index 4ba37aed2dc9db..a0d0f61e5a192c 100644 --- a/Lib/test/test_stat.py +++ b/Lib/test/test_stat.py @@ -122,8 +122,11 @@ def test_mode(self): st_mode, modestr = self.get_mode() self.assertEqual(modestr, '-rwx------') self.assertS_IS("REG", st_mode) - self.assertEqual(self.statmod.S_IMODE(st_mode), + imode = self.statmod.S_IMODE(st_mode) + self.assertEqual(imode, self.statmod.S_IRWXU) + self.assertEqual(self.statmod.filemode(imode), + '?rwx------') os.chmod(TESTFN, 0o070) st_mode, modestr = self.get_mode() @@ -145,12 +148,19 @@ def test_mode(self): self.assertEqual(modestr, '-r--r--r--') self.assertEqual(self.statmod.S_IMODE(st_mode), 0o444) else: + os.chmod(TESTFN, 0o500) + st_mode, modestr = self.get_mode() + self.assertEqual(modestr[:3], '-r-') + self.assertS_IS("REG", st_mode) + self.assertEqual(self.statmod.S_IMODE(st_mode), 0o444) + os.chmod(TESTFN, 0o700) st_mode, modestr = self.get_mode() self.assertEqual(modestr[:3], '-rw') self.assertS_IS("REG", st_mode) self.assertEqual(self.statmod.S_IFMT(st_mode), self.statmod.S_IFREG) + self.assertEqual(self.statmod.S_IMODE(st_mode), 0o666) @os_helper.skip_unless_working_chmod def test_directory(self): @@ -238,6 +248,7 @@ def test_file_attribute_constants(self): self.assertEqual(value, modvalue, key) +@unittest.skipIf(c_stat is None, 'need _stat extension') class TestFilemodeCStat(TestFilemode, unittest.TestCase): statmod = c_stat diff --git a/Lib/test/test_statistics.py b/Lib/test/test_statistics.py index f0fa6454b1f91a..bf2c254c9ee7d9 100644 --- a/Lib/test/test_statistics.py +++ b/Lib/test/test_statistics.py @@ -28,6 +28,12 @@ # === Helper functions and class === +# Test copied from Lib/test/test_math.py +# detect evidence of double-rounding: fsum is not always correctly +# rounded on machines that suffer from double rounding. +x, y = 1e16, 2.9999 # use temporary values to defeat peephole optimizer +HAVE_DOUBLE_ROUNDING = (x + y == 1e16 + 4) + def sign(x): """Return -1.0 for negatives, including -0.0, otherwise +1.0.""" return math.copysign(1, x) @@ -692,14 +698,6 @@ def test_check_all(self): 'missing name "%s" in __all__' % name) -class DocTests(unittest.TestCase): - @unittest.skipIf(sys.flags.optimize >= 2, - "Docstrings are omitted with -OO and above") - def test_doc_tests(self): - failed, tried = doctest.testmod(statistics, optionflags=doctest.ELLIPSIS) - self.assertGreater(tried, 0) - self.assertEqual(failed, 0) - class StatisticsErrorTest(unittest.TestCase): def test_has_exception(self): errmsg = ( @@ -2139,6 +2137,7 @@ def test_integer_sqrt_of_frac_rto(self): self.assertTrue(m * (r - 1)**2 < n < m * (r + 1)**2) @requires_IEEE_754 + @support.requires_resource('cpu') def test_float_sqrt_of_frac(self): def is_root_correctly_rounded(x: Fraction, root: float) -> bool: @@ -2303,10 +2302,12 @@ def test_error_cases(self): StatisticsError = statistics.StatisticsError with self.assertRaises(StatisticsError): geometric_mean([]) # empty input - with self.assertRaises(StatisticsError): - geometric_mean([3.5, 0.0, 5.25]) # zero input with self.assertRaises(StatisticsError): geometric_mean([3.5, -4.0, 5.25]) # negative input + with self.assertRaises(StatisticsError): + geometric_mean([0.0, -4.0, 5.25]) # negative input with zero + with self.assertRaises(StatisticsError): + geometric_mean([3.5, -math.inf, 5.25]) # negative infinity with self.assertRaises(StatisticsError): geometric_mean(iter([])) # empty iterator with self.assertRaises(TypeError): @@ -2329,6 +2330,12 @@ def test_special_values(self): with self.assertRaises(ValueError): geometric_mean([Inf, -Inf]) + # Cases with zero + self.assertEqual(geometric_mean([3, 0.0, 5]), 0.0) # Any zero gives a zero + self.assertEqual(geometric_mean([3, -0.0, 5]), 0.0) # Negative zero allowed + self.assertTrue(math.isnan(geometric_mean([0, NaN]))) # NaN beats zero + self.assertTrue(math.isnan(geometric_mean([0, Inf]))) # Because 0.0 * Inf -> NaN + def test_mixed_int_and_float(self): # Regression test for b.p.o. issue #28327 geometric_mean = statistics.geometric_mean @@ -2455,6 +2462,11 @@ def f(x): data = random.choices(range(100), k=k) q1, q2, q3 = quantiles(data, method='inclusive') self.assertEqual(q2, statistics.median(data)) + # Base case with a single data point: When estimating quantiles from + # a sample, we want to be able to add one sample point at a time, + # getting increasingly better estimates. + self.assertEqual(quantiles([10], n=4), [10.0, 10.0, 10.0]) + self.assertEqual(quantiles([10], n=4, method='exclusive'), [10.0, 10.0, 10.0]) def test_equal_inputs(self): quantiles = statistics.quantiles @@ -2505,7 +2517,7 @@ def test_error_cases(self): with self.assertRaises(ValueError): quantiles([10, 20, 30], method='X') # method is unknown with self.assertRaises(StatisticsError): - quantiles([10], n=4) # not enough data points + quantiles([], n=4) # not enough data points with self.assertRaises(TypeError): quantiles([10, None, 30], n=4) # data is non-numeric @@ -2564,6 +2576,79 @@ def test_different_scales(self): self.assertAlmostEqual(statistics.correlation(x, y), 1) self.assertAlmostEqual(statistics.covariance(x, y), 0.1) + def test_sqrtprod_helper_function_fundamentals(self): + # Verify that results are close to sqrt(x * y) + for i in range(100): + x = random.expovariate() + y = random.expovariate() + expected = math.sqrt(x * y) + actual = statistics._sqrtprod(x, y) + with self.subTest(x=x, y=y, expected=expected, actual=actual): + self.assertAlmostEqual(expected, actual) + + x, y, target = 0.8035720646477457, 0.7957468097636939, 0.7996498651651661 + self.assertEqual(statistics._sqrtprod(x, y), target) + self.assertNotEqual(math.sqrt(x * y), target) + + # Test that range extremes avoid underflow and overflow + smallest = sys.float_info.min * sys.float_info.epsilon + self.assertEqual(statistics._sqrtprod(smallest, smallest), smallest) + biggest = sys.float_info.max + self.assertEqual(statistics._sqrtprod(biggest, biggest), biggest) + + # Check special values and the sign of the result + special_values = [0.0, -0.0, 1.0, -1.0, 4.0, -4.0, + math.nan, -math.nan, math.inf, -math.inf] + for x, y in itertools.product(special_values, repeat=2): + try: + expected = math.sqrt(x * y) + except ValueError: + expected = 'ValueError' + try: + actual = statistics._sqrtprod(x, y) + except ValueError: + actual = 'ValueError' + with self.subTest(x=x, y=y, expected=expected, actual=actual): + if isinstance(expected, str) and expected == 'ValueError': + self.assertEqual(actual, 'ValueError') + continue + self.assertIsInstance(actual, float) + if math.isnan(expected): + self.assertTrue(math.isnan(actual)) + continue + self.assertEqual(actual, expected) + self.assertEqual(sign(actual), sign(expected)) + + @requires_IEEE_754 + @unittest.skipIf(HAVE_DOUBLE_ROUNDING, + "accuracy not guaranteed on machines with double rounding") + @support.cpython_only # Allow for a weaker sumprod() implmentation + def test_sqrtprod_helper_function_improved_accuracy(self): + # Test a known example where accuracy is improved + x, y, target = 0.8035720646477457, 0.7957468097636939, 0.7996498651651661 + self.assertEqual(statistics._sqrtprod(x, y), target) + self.assertNotEqual(math.sqrt(x * y), target) + + def reference_value(x: float, y: float) -> float: + x = decimal.Decimal(x) + y = decimal.Decimal(y) + with decimal.localcontext() as ctx: + ctx.prec = 200 + return float((x * y).sqrt()) + + # Verify that the new function with improved accuracy + # agrees with a reference value more often than old version. + new_agreements = 0 + old_agreements = 0 + for i in range(10_000): + x = random.expovariate() + y = random.expovariate() + new = statistics._sqrtprod(x, y) + old = math.sqrt(x * y) + ref = reference_value(x, y) + new_agreements += (new == ref) + old_agreements += (old == ref) + self.assertGreater(new_agreements, old_agreements) def test_correlation_spearman(self): # https://statistics.laerd.com/statistical-guides/spearmans-rank-order-correlation-statistical-guide-2.php @@ -2770,6 +2855,7 @@ def test_cdf(self): self.assertTrue(math.isnan(X.cdf(float('NaN')))) @support.skip_if_pgo_task + @support.requires_resource('cpu') def test_inv_cdf(self): NormalDist = self.module.NormalDist @@ -3064,6 +3150,7 @@ def tearDown(self): def load_tests(loader, tests, ignore): """Used for doctest/unittest integration.""" tests.addTests(doctest.DocTestSuite()) + tests.addTests(doctest.DocTestSuite(statistics)) return tests diff --git a/Lib/test/test_str.py b/Lib/test/test_str.py index a6bcc2455de15e..b4927113db44e3 100644 --- a/Lib/test/test_str.py +++ b/Lib/test/test_str.py @@ -55,6 +55,21 @@ def duplicate_string(text): class StrSubclass(str): pass +class OtherStrSubclass(str): + pass + +class WithStr: + def __init__(self, value): + self.value = value + def __str__(self): + return self.value + +class WithRepr: + def __init__(self, value): + self.value = value + def __repr__(self): + return self.value + class StrTest(string_tests.StringLikeTest, string_tests.MixinStrUnicodeTest, unittest.TestCase): @@ -83,6 +98,10 @@ def __repr__(self): self.assertEqual(realresult, result) self.assertTrue(object is not realresult) + def assertTypedEqual(self, actual, expected): + self.assertIs(type(actual), type(expected)) + self.assertEqual(actual, expected) + def test_literals(self): self.assertEqual('\xff', '\u00ff') self.assertEqual('\uffff', '\U0000ffff') @@ -127,10 +146,13 @@ def test_ascii(self): self.assertEqual(ascii("\U00010000" * 39 + "\uffff" * 4096), ascii("\U00010000" * 39 + "\uffff" * 4096)) - class WrongRepr: - def __repr__(self): - return b'byte-repr' - self.assertRaises(TypeError, ascii, WrongRepr()) + self.assertTypedEqual(ascii('\U0001f40d'), r"'\U0001f40d'") + self.assertTypedEqual(ascii(StrSubclass('abc')), "'abc'") + self.assertTypedEqual(ascii(WithRepr('')), '') + self.assertTypedEqual(ascii(WithRepr(StrSubclass(''))), StrSubclass('')) + self.assertTypedEqual(ascii(WithRepr('<\U0001f40d>')), r'<\U0001f40d>') + self.assertTypedEqual(ascii(WithRepr(StrSubclass('<\U0001f40d>'))), r'<\U0001f40d>') + self.assertRaises(TypeError, ascii, WithRepr(b'byte-repr')) def test_repr(self): # Test basic sanity of repr() @@ -168,10 +190,13 @@ def test_repr(self): self.assertEqual(repr("\U00010000" * 39 + "\uffff" * 4096), repr("\U00010000" * 39 + "\uffff" * 4096)) - class WrongRepr: - def __repr__(self): - return b'byte-repr' - self.assertRaises(TypeError, repr, WrongRepr()) + self.assertTypedEqual(repr('\U0001f40d'), "'\U0001f40d'") + self.assertTypedEqual(repr(StrSubclass('abc')), "'abc'") + self.assertTypedEqual(repr(WithRepr('')), '') + self.assertTypedEqual(repr(WithRepr(StrSubclass(''))), StrSubclass('')) + self.assertTypedEqual(repr(WithRepr('<\U0001f40d>')), '<\U0001f40d>') + self.assertTypedEqual(repr(WithRepr(StrSubclass('<\U0001f40d>'))), StrSubclass('<\U0001f40d>')) + self.assertRaises(TypeError, repr, WithRepr(b'byte-repr')) def test_iterators(self): # Make sure unicode objects have an __iter__ method @@ -812,16 +837,6 @@ def test_isidentifier(self): self.assertFalse("©".isidentifier()) self.assertFalse("0".isidentifier()) - @support.cpython_only - @support.requires_legacy_unicode_capi - @unittest.skipIf(_testcapi is None, 'need _testcapi module') - def test_isidentifier_legacy(self): - u = 'ð–€ð–“ð–Žð–ˆð–”ð–‰ð–Š' - self.assertTrue(u.isidentifier()) - with warnings_helper.check_warnings(): - warnings.simplefilter('ignore', DeprecationWarning) - self.assertTrue(_testcapi.unicode_legacy_string(u).isidentifier()) - def test_isprintable(self): self.assertTrue("".isprintable()) self.assertTrue(" ".isprintable()) @@ -2377,28 +2392,37 @@ def test_ucs4(self): def test_conversion(self): # Make sure __str__() works properly - class ObjectToStr: - def __str__(self): - return "foo" - - class StrSubclassToStr(str): - def __str__(self): - return "foo" - - class StrSubclassToStrSubclass(str): - def __new__(cls, content=""): - return str.__new__(cls, 2*content) - def __str__(self): + class StrWithStr(str): + def __new__(cls, value): + self = str.__new__(cls, "") + self.value = value return self + def __str__(self): + return self.value - self.assertEqual(str(ObjectToStr()), "foo") - self.assertEqual(str(StrSubclassToStr("bar")), "foo") - s = str(StrSubclassToStrSubclass("foo")) - self.assertEqual(s, "foofoo") - self.assertIs(type(s), StrSubclassToStrSubclass) - s = StrSubclass(StrSubclassToStrSubclass("foo")) - self.assertEqual(s, "foofoo") - self.assertIs(type(s), StrSubclass) + self.assertTypedEqual(str(WithStr('abc')), 'abc') + self.assertTypedEqual(str(WithStr(StrSubclass('abc'))), StrSubclass('abc')) + self.assertTypedEqual(StrSubclass(WithStr('abc')), StrSubclass('abc')) + self.assertTypedEqual(StrSubclass(WithStr(StrSubclass('abc'))), + StrSubclass('abc')) + self.assertTypedEqual(StrSubclass(WithStr(OtherStrSubclass('abc'))), + StrSubclass('abc')) + + self.assertTypedEqual(str(StrWithStr('abc')), 'abc') + self.assertTypedEqual(str(StrWithStr(StrSubclass('abc'))), StrSubclass('abc')) + self.assertTypedEqual(StrSubclass(StrWithStr('abc')), StrSubclass('abc')) + self.assertTypedEqual(StrSubclass(StrWithStr(StrSubclass('abc'))), + StrSubclass('abc')) + self.assertTypedEqual(StrSubclass(StrWithStr(OtherStrSubclass('abc'))), + StrSubclass('abc')) + + self.assertTypedEqual(str(WithRepr('')), '') + self.assertTypedEqual(str(WithRepr(StrSubclass(''))), StrSubclass('')) + self.assertTypedEqual(StrSubclass(WithRepr('')), StrSubclass('')) + self.assertTypedEqual(StrSubclass(WithRepr(StrSubclass(''))), + StrSubclass('')) + self.assertTypedEqual(StrSubclass(WithRepr(OtherStrSubclass(''))), + StrSubclass('')) def test_unicode_repr(self): class s1: @@ -2489,26 +2513,6 @@ def test_getnewargs(self): self.assertEqual(args[0], text) self.assertEqual(len(args), 1) - @support.cpython_only - @support.requires_legacy_unicode_capi - @unittest.skipIf(_testcapi is None, 'need _testcapi module') - def test_resize(self): - for length in range(1, 100, 7): - # generate a fresh string (refcount=1) - text = 'a' * length + 'b' - - # fill wstr internal field - with self.assertWarns(DeprecationWarning): - abc = _testcapi.getargs_u(text) - self.assertEqual(abc, text) - - # resize text: wstr field must be cleared and then recomputed - text += 'c' - with self.assertWarns(DeprecationWarning): - abcdef = _testcapi.getargs_u(text) - self.assertNotEqual(abc, abcdef) - self.assertEqual(abcdef, text) - def test_compare(self): # Issue #17615 N = 10 diff --git a/Lib/test/test_string_literals.py b/Lib/test/test_string_literals.py index 9b663c00223d1b..371e8193b3544d 100644 --- a/Lib/test/test_string_literals.py +++ b/Lib/test/test_string_literals.py @@ -131,6 +131,18 @@ def test_eval_str_invalid_escape(self): self.assertEqual(exc.lineno, 1) self.assertEqual(exc.offset, 1) + # Check that the warning is raised ony once if there are syntax errors + + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter('always', category=SyntaxWarning) + with self.assertRaises(SyntaxError) as cm: + eval("'\\e' $") + exc = cm.exception + self.assertEqual(len(w), 1) + self.assertEqual(w[0].category, SyntaxWarning) + self.assertRegex(str(w[0].message), 'invalid escape sequence') + self.assertEqual(w[0].filename, '') + def test_eval_str_invalid_octal_escape(self): for i in range(0o400, 0o1000): with self.assertWarns(SyntaxWarning): diff --git a/Lib/test/test_strptime.py b/Lib/test/test_strptime.py index 810c5a36e02f41..05c8afc907ad3c 100644 --- a/Lib/test/test_strptime.py +++ b/Lib/test/test_strptime.py @@ -224,35 +224,55 @@ def test_ValueError(self): else: self.fail("'%s' did not raise ValueError" % bad_format) + msg_week_no_year_or_weekday = r"ISO week directive '%V' must be used with " \ + r"the ISO year directive '%G' and a weekday directive " \ + r"\('%A', '%a', '%w', or '%u'\)." + msg_week_not_compatible = r"ISO week directive '%V' is incompatible with " \ + r"the year directive '%Y'. Use the ISO year '%G' instead." + msg_julian_not_compatible = r"Day of the year directive '%j' is not " \ + r"compatible with ISO year directive '%G'. Use '%Y' instead." + msg_year_no_week_or_weekday = r"ISO year directive '%G' must be used with " \ + r"the ISO week directive '%V' and a weekday directive " \ + r"\('%A', '%a', '%w', or '%u'\)." + + locale_time = _strptime.LocaleTime() + # Ambiguous or incomplete cases using ISO year/week/weekday directives - # 1. ISO week (%V) is specified, but the year is specified with %Y - # instead of %G - with self.assertRaises(ValueError): - _strptime._strptime("1999 50", "%Y %V") - # 2. ISO year (%G) and ISO week (%V) are specified, but weekday is not - with self.assertRaises(ValueError): - _strptime._strptime("1999 51", "%G %V") - # 3. ISO year (%G) and weekday are specified, but ISO week (%V) is not - for w in ('A', 'a', 'w', 'u'): - with self.assertRaises(ValueError): - _strptime._strptime("1999 51","%G %{}".format(w)) - # 4. ISO year is specified alone (e.g. time.strptime('2015', '%G')) - with self.assertRaises(ValueError): - _strptime._strptime("2015", "%G") - # 5. Julian/ordinal day (%j) is specified with %G, but not %Y - with self.assertRaises(ValueError): - _strptime._strptime("1999 256", "%G %j") - # 6. Invalid ISO weeks - invalid_iso_weeks = [ - "2019-00-1", - "2019-54-1", - "2021-53-1", + subtests = [ + # 1. ISO week (%V) is specified, but the year is specified with %Y + # instead of %G + ("1999 50", "%Y %V", msg_week_no_year_or_weekday), + ("1999 50 5", "%Y %V %u", msg_week_not_compatible), + # 2. ISO year (%G) and ISO week (%V) are specified, but weekday is not + ("1999 51", "%G %V", msg_year_no_week_or_weekday), + # 3. ISO year (%G) and weekday are specified, but ISO week (%V) is not + ("1999 {}".format(locale_time.f_weekday[5]), "%G %A", + msg_year_no_week_or_weekday), + ("1999 {}".format(locale_time.a_weekday[5]), "%G %a", + msg_year_no_week_or_weekday), + ("1999 5", "%G %w", msg_year_no_week_or_weekday), + ("1999 5", "%G %u", msg_year_no_week_or_weekday), + # 4. ISO year is specified alone (e.g. time.strptime('2015', '%G')) + ("2015", "%G", msg_year_no_week_or_weekday), + # 5. Julian/ordinal day (%j) is specified with %G, but not %Y + ("1999 256", "%G %j", msg_julian_not_compatible), + ("1999 50 5 256", "%G %V %u %j", msg_julian_not_compatible), + # ISO week specified alone + ("50", "%V", msg_week_no_year_or_weekday), + # ISO year is unspecified, falling back to year + ("50 5", "%V %u", msg_week_no_year_or_weekday), + # 6. Invalid ISO weeks + ("2019-00-1", "%G-%V-%u", + "time data '2019-00-1' does not match format '%G-%V-%u'"), + ("2019-54-1", "%G-%V-%u", + "time data '2019-54-1' does not match format '%G-%V-%u'"), + ("2021-53-1", "%G-%V-%u", "Invalid week: 53"), ] - for invalid_iso_dtstr in invalid_iso_weeks: - with self.subTest(invalid_iso_dtstr): - with self.assertRaises(ValueError): - _strptime._strptime(invalid_iso_dtstr, "%G-%V-%u") + for (data_string, format, message) in subtests: + with self.subTest(data_string=data_string, format=format): + with self.assertRaisesRegex(ValueError, message): + _strptime._strptime(data_string, format) def test_strptime_exception_context(self): # check that this doesn't chain exceptions needlessly (see #17572) diff --git a/Lib/test/test_struct.py b/Lib/test/test_struct.py index 6b1f22f66fd157..15f6ee06ffe19b 100644 --- a/Lib/test/test_struct.py +++ b/Lib/test/test_struct.py @@ -700,20 +700,6 @@ def test__struct_types_immutable(self): with self.assertRaises(TypeError): cls.x = 1 - @support.cpython_only - def test__struct_Struct__new__initialized(self): - # See https://github.com/python/cpython/issues/78724 - - s = struct.Struct.__new__(struct.Struct, "b") - s.unpack_from(b"abcd") - - @support.cpython_only - def test__struct_Struct_subclassing(self): - class Bob(struct.Struct): - pass - - s = Bob("b") - s.unpack_from(b"abcd") def test_issue35714(self): # Embedded null characters should not be allowed in format strings. @@ -774,6 +760,19 @@ def test_error_propagation(fmt_str): test_error_propagation('N') test_error_propagation('n') + def test_struct_subclass_instantiation(self): + # Regression test for https://github.com/python/cpython/issues/112358 + class MyStruct(struct.Struct): + def __init__(self): + super().__init__('>h') + + my_struct = MyStruct() + self.assertEqual(my_struct.pack(12345), b'\x30\x39') + + def test_repr(self): + s = struct.Struct('=i2H') + self.assertEqual(repr(s), f'Struct({s.format!r})') + class UnpackIteratorTest(unittest.TestCase): """ Tests for iterative unpacking (struct.Struct.iter_unpack). diff --git a/Lib/test/test_structseq.py b/Lib/test/test_structseq.py index a9fe193028ebe4..6aec63e2603412 100644 --- a/Lib/test/test_structseq.py +++ b/Lib/test/test_structseq.py @@ -1,4 +1,7 @@ +import copy import os +import pickle +import re import time import unittest @@ -89,10 +92,69 @@ def test_constructor(self): self.assertRaises(TypeError, t, "123") self.assertRaises(TypeError, t, "123", dict={}) self.assertRaises(TypeError, t, "123456789", dict=None) + self.assertRaises(TypeError, t, seq="123456789", dict={}) + + self.assertEqual(t("123456789"), tuple("123456789")) + self.assertEqual(t("123456789", {}), tuple("123456789")) + self.assertEqual(t("123456789", dict={}), tuple("123456789")) + self.assertEqual(t(sequence="123456789", dict={}), tuple("123456789")) + + self.assertEqual(t("1234567890"), tuple("123456789")) + self.assertEqual(t("1234567890").tm_zone, "0") + self.assertEqual(t("123456789", {"tm_zone": "some zone"}), tuple("123456789")) + self.assertEqual(t("123456789", {"tm_zone": "some zone"}).tm_zone, "some zone") s = "123456789" self.assertEqual("".join(t(s)), s) + def test_constructor_with_duplicate_fields(self): + t = time.struct_time + + error_message = re.escape("got duplicate or unexpected field name(s)") + with self.assertRaisesRegex(TypeError, error_message): + t("1234567890", dict={"tm_zone": "some zone"}) + with self.assertRaisesRegex(TypeError, error_message): + t("1234567890", dict={"tm_zone": "some zone", "tm_mon": 1}) + with self.assertRaisesRegex(TypeError, error_message): + t("1234567890", dict={"error": 0, "tm_zone": "some zone"}) + with self.assertRaisesRegex(TypeError, error_message): + t("1234567890", dict={"error": 0, "tm_zone": "some zone", "tm_mon": 1}) + + def test_constructor_with_duplicate_unnamed_fields(self): + assert os.stat_result.n_unnamed_fields > 0 + n_visible_fields = os.stat_result.n_sequence_fields + + r = os.stat_result(range(n_visible_fields), {'st_atime': -1.0}) + self.assertEqual(r.st_atime, -1.0) + self.assertEqual(r, tuple(range(n_visible_fields))) + + r = os.stat_result((*range(n_visible_fields), -1.0)) + self.assertEqual(r.st_atime, -1.0) + self.assertEqual(r, tuple(range(n_visible_fields))) + + with self.assertRaisesRegex(TypeError, + re.escape("got duplicate or unexpected field name(s)")): + os.stat_result((*range(n_visible_fields), -1.0), {'st_atime': -1.0}) + + def test_constructor_with_unknown_fields(self): + t = time.struct_time + + error_message = re.escape("got duplicate or unexpected field name(s)") + with self.assertRaisesRegex(TypeError, error_message): + t("123456789", dict={"tm_year": 0}) + with self.assertRaisesRegex(TypeError, error_message): + t("123456789", dict={"tm_year": 0, "tm_mon": 1}) + with self.assertRaisesRegex(TypeError, error_message): + t("123456789", dict={"tm_zone": "some zone", "tm_mon": 1}) + with self.assertRaisesRegex(TypeError, error_message): + t("123456789", dict={"tm_zone": "some zone", "error": 0}) + with self.assertRaisesRegex(TypeError, error_message): + t("123456789", dict={"error": 0, "tm_zone": "some zone", "tm_mon": 1}) + with self.assertRaisesRegex(TypeError, error_message): + t("123456789", dict={"error": 0}) + with self.assertRaisesRegex(TypeError, error_message): + t("123456789", dict={"tm_zone": "some zone", "error": 0}) + def test_eviltuple(self): class Exc(Exception): pass @@ -106,9 +168,78 @@ def __len__(self): self.assertRaises(Exc, time.struct_time, C()) - def test_reduce(self): + def test_pickling(self): t = time.gmtime() - x = t.__reduce__() + for proto in range(pickle.HIGHEST_PROTOCOL + 1): + p = pickle.dumps(t, proto) + t2 = pickle.loads(p) + self.assertEqual(t2.__class__, t.__class__) + self.assertEqual(t2, t) + self.assertEqual(t2.tm_year, t.tm_year) + self.assertEqual(t2.tm_zone, t.tm_zone) + + def test_pickling_with_unnamed_fields(self): + assert os.stat_result.n_unnamed_fields > 0 + + r = os.stat_result(range(os.stat_result.n_sequence_fields), + {'st_atime': 1.0, 'st_atime_ns': 2.0}) + for proto in range(pickle.HIGHEST_PROTOCOL + 1): + p = pickle.dumps(r, proto) + r2 = pickle.loads(p) + self.assertEqual(r2.__class__, r.__class__) + self.assertEqual(r2, r) + self.assertEqual(r2.st_mode, r.st_mode) + self.assertEqual(r2.st_atime, r.st_atime) + self.assertEqual(r2.st_atime_ns, r.st_atime_ns) + + def test_copying(self): + n_fields = time.struct_time.n_fields + t = time.struct_time([[i] for i in range(n_fields)]) + + t2 = copy.copy(t) + self.assertEqual(t2.__class__, t.__class__) + self.assertEqual(t2, t) + self.assertEqual(t2.tm_year, t.tm_year) + self.assertEqual(t2.tm_zone, t.tm_zone) + self.assertIs(t2[0], t[0]) + self.assertIs(t2.tm_year, t.tm_year) + + t3 = copy.deepcopy(t) + self.assertEqual(t3.__class__, t.__class__) + self.assertEqual(t3, t) + self.assertEqual(t3.tm_year, t.tm_year) + self.assertEqual(t3.tm_zone, t.tm_zone) + self.assertIsNot(t3[0], t[0]) + self.assertIsNot(t3.tm_year, t.tm_year) + + def test_copying_with_unnamed_fields(self): + assert os.stat_result.n_unnamed_fields > 0 + + n_sequence_fields = os.stat_result.n_sequence_fields + r = os.stat_result([[i] for i in range(n_sequence_fields)], + {'st_atime': [1.0], 'st_atime_ns': [2.0]}) + + r2 = copy.copy(r) + self.assertEqual(r2.__class__, r.__class__) + self.assertEqual(r2, r) + self.assertEqual(r2.st_mode, r.st_mode) + self.assertEqual(r2.st_atime, r.st_atime) + self.assertEqual(r2.st_atime_ns, r.st_atime_ns) + self.assertIs(r2[0], r[0]) + self.assertIs(r2.st_mode, r.st_mode) + self.assertIs(r2.st_atime, r.st_atime) + self.assertIs(r2.st_atime_ns, r.st_atime_ns) + + r3 = copy.deepcopy(r) + self.assertEqual(r3.__class__, r.__class__) + self.assertEqual(r3, r) + self.assertEqual(r3.st_mode, r.st_mode) + self.assertEqual(r3.st_atime, r.st_atime) + self.assertEqual(r3.st_atime_ns, r.st_atime_ns) + self.assertIsNot(r3[0], r[0]) + self.assertIsNot(r3.st_mode, r.st_mode) + self.assertIsNot(r3.st_atime, r.st_atime) + self.assertIsNot(r3.st_atime_ns, r.st_atime_ns) def test_extended_getslice(self): # Test extended slicing by comparing with list slicing. @@ -133,6 +264,84 @@ def test_match_args_with_unnamed_fields(self): self.assertEqual(os.stat_result.n_unnamed_fields, 3) self.assertEqual(os.stat_result.__match_args__, expected_args) + def test_copy_replace_all_fields_visible(self): + assert os.times_result.n_unnamed_fields == 0 + assert os.times_result.n_sequence_fields == os.times_result.n_fields + + t = os.times() + + # visible fields + self.assertEqual(copy.replace(t), t) + self.assertIsInstance(copy.replace(t), os.times_result) + self.assertEqual(copy.replace(t, user=1.5), (1.5, *t[1:])) + self.assertEqual(copy.replace(t, system=2.5), (t[0], 2.5, *t[2:])) + self.assertEqual(copy.replace(t, user=1.5, system=2.5), (1.5, 2.5, *t[2:])) + + # unknown fields + with self.assertRaisesRegex(TypeError, 'unexpected field name'): + copy.replace(t, error=-1) + with self.assertRaisesRegex(TypeError, 'unexpected field name'): + copy.replace(t, user=1, error=-1) + + def test_copy_replace_with_invisible_fields(self): + assert time.struct_time.n_unnamed_fields == 0 + assert time.struct_time.n_sequence_fields < time.struct_time.n_fields + + t = time.gmtime(0) + + # visible fields + t2 = copy.replace(t) + self.assertEqual(t2, (1970, 1, 1, 0, 0, 0, 3, 1, 0)) + self.assertIsInstance(t2, time.struct_time) + t3 = copy.replace(t, tm_year=2000) + self.assertEqual(t3, (2000, 1, 1, 0, 0, 0, 3, 1, 0)) + self.assertEqual(t3.tm_year, 2000) + t4 = copy.replace(t, tm_mon=2) + self.assertEqual(t4, (1970, 2, 1, 0, 0, 0, 3, 1, 0)) + self.assertEqual(t4.tm_mon, 2) + t5 = copy.replace(t, tm_year=2000, tm_mon=2) + self.assertEqual(t5, (2000, 2, 1, 0, 0, 0, 3, 1, 0)) + self.assertEqual(t5.tm_year, 2000) + self.assertEqual(t5.tm_mon, 2) + + # named invisible fields + self.assertTrue(hasattr(t, 'tm_zone'), f"{t} has no attribute 'tm_zone'") + with self.assertRaisesRegex(AttributeError, 'readonly attribute'): + t.tm_zone = 'some other zone' + self.assertEqual(t2.tm_zone, t.tm_zone) + self.assertEqual(t3.tm_zone, t.tm_zone) + self.assertEqual(t4.tm_zone, t.tm_zone) + t6 = copy.replace(t, tm_zone='some other zone') + self.assertEqual(t, t6) + self.assertEqual(t6.tm_zone, 'some other zone') + t7 = copy.replace(t, tm_year=2000, tm_zone='some other zone') + self.assertEqual(t7, (2000, 1, 1, 0, 0, 0, 3, 1, 0)) + self.assertEqual(t7.tm_year, 2000) + self.assertEqual(t7.tm_zone, 'some other zone') + + # unknown fields + with self.assertRaisesRegex(TypeError, 'unexpected field name'): + copy.replace(t, error=2) + with self.assertRaisesRegex(TypeError, 'unexpected field name'): + copy.replace(t, tm_year=2000, error=2) + with self.assertRaisesRegex(TypeError, 'unexpected field name'): + copy.replace(t, tm_zone='some other zone', error=2) + + def test_copy_replace_with_unnamed_fields(self): + assert os.stat_result.n_unnamed_fields > 0 + + r = os.stat_result(range(os.stat_result.n_sequence_fields)) + + error_message = re.escape('__replace__() is not supported') + with self.assertRaisesRegex(TypeError, error_message): + copy.replace(r) + with self.assertRaisesRegex(TypeError, error_message): + copy.replace(r, st_mode=1) + with self.assertRaisesRegex(TypeError, error_message): + copy.replace(r, error=2) + with self.assertRaisesRegex(TypeError, error_message): + copy.replace(r, st_mode=1, error=2) + if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_subclassinit.py b/Lib/test/test_subclassinit.py index 310473a4a2fe58..0d32aa509bd25c 100644 --- a/Lib/test/test_subclassinit.py +++ b/Lib/test/test_subclassinit.py @@ -230,7 +230,7 @@ def __init__(self, name, bases, namespace, otherarg): super().__init__(name, bases, namespace) with self.assertRaises(TypeError): - class MyClass(metaclass=MyMeta, otherarg=1): + class MyClass2(metaclass=MyMeta, otherarg=1): pass class MyMeta(type): @@ -241,10 +241,10 @@ def __init__(self, name, bases, namespace, otherarg): super().__init__(name, bases, namespace) self.otherarg = otherarg - class MyClass(metaclass=MyMeta, otherarg=1): + class MyClass3(metaclass=MyMeta, otherarg=1): pass - self.assertEqual(MyClass.otherarg, 1) + self.assertEqual(MyClass3.otherarg, 1) def test_errors_changed_pep487(self): # These tests failed before Python 3.6, PEP 487 @@ -263,10 +263,10 @@ def __new__(cls, name, bases, namespace, otherarg): self.otherarg = otherarg return self - class MyClass(metaclass=MyMeta, otherarg=1): + class MyClass2(metaclass=MyMeta, otherarg=1): pass - self.assertEqual(MyClass.otherarg, 1) + self.assertEqual(MyClass2.otherarg, 1) def test_type(self): t = type('NewClass', (object,), {}) diff --git a/Lib/test/test_subprocess.py b/Lib/test/test_subprocess.py index 817eab0c8a7e19..944a7de4210bc9 100644 --- a/Lib/test/test_subprocess.py +++ b/Lib/test/test_subprocess.py @@ -269,6 +269,7 @@ def test_check_output_stdin_with_input_arg(self): self.assertIn('stdin', c.exception.args[0]) self.assertIn('input', c.exception.args[0]) + @support.requires_resource('walltime') def test_check_output_timeout(self): # check_output() function with timeout arg with self.assertRaises(subprocess.TimeoutExpired) as c: @@ -748,31 +749,36 @@ def test_pipesizes(self): @unittest.skipUnless(fcntl and hasattr(fcntl, 'F_GETPIPE_SZ'), 'fcntl.F_GETPIPE_SZ required for test.') def test_pipesize_default(self): - p = subprocess.Popen( + proc = subprocess.Popen( [sys.executable, "-c", 'import sys; sys.stdin.read(); sys.stdout.write("out"); ' 'sys.stderr.write("error!")'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, pipesize=-1) - try: - fp_r, fp_w = os.pipe() + + with proc: try: - default_pipesize = fcntl.fcntl(fp_w, fcntl.F_GETPIPE_SZ) - for fifo in [p.stdin, p.stdout, p.stderr]: - self.assertEqual( - fcntl.fcntl(fifo.fileno(), fcntl.F_GETPIPE_SZ), - default_pipesize) + fp_r, fp_w = os.pipe() + try: + default_read_pipesize = fcntl.fcntl(fp_r, fcntl.F_GETPIPE_SZ) + default_write_pipesize = fcntl.fcntl(fp_w, fcntl.F_GETPIPE_SZ) + finally: + os.close(fp_r) + os.close(fp_w) + + self.assertEqual( + fcntl.fcntl(proc.stdin.fileno(), fcntl.F_GETPIPE_SZ), + default_read_pipesize) + self.assertEqual( + fcntl.fcntl(proc.stdout.fileno(), fcntl.F_GETPIPE_SZ), + default_write_pipesize) + self.assertEqual( + fcntl.fcntl(proc.stderr.fileno(), fcntl.F_GETPIPE_SZ), + default_write_pipesize) + # On other platforms we cannot test the pipe size (yet). But above + # code using pipesize=-1 should not crash. finally: - os.close(fp_r) - os.close(fp_w) - # On other platforms we cannot test the pipe size (yet). But above - # code using pipesize=-1 should not crash. - p.stdin.close() - p.stdout.close() - p.stderr.close() - finally: - p.kill() - p.wait() + proc.kill() def test_env(self): newenv = os.environ.copy() @@ -785,6 +791,19 @@ def test_env(self): stdout, stderr = p.communicate() self.assertEqual(stdout, b"orange") + @unittest.skipUnless(sys.platform == "win32", "Windows only issue") + def test_win32_duplicate_envs(self): + newenv = os.environ.copy() + newenv["fRUit"] = "cherry" + newenv["fruit"] = "lemon" + newenv["FRUIT"] = "orange" + newenv["frUit"] = "banana" + with subprocess.Popen(["CMD", "/c", "SET", "fruit"], + stdout=subprocess.PIPE, + env=newenv) as p: + stdout, _ = p.communicate() + self.assertEqual(stdout.strip(), b"frUit=banana") + # Windows requires at least the SYSTEMROOT environment variable to start # Python @unittest.skipIf(sys.platform == 'win32', @@ -816,6 +835,26 @@ def is_env_var_to_ignore(n): if not is_env_var_to_ignore(k)] self.assertEqual(child_env_names, []) + @unittest.skipIf(sysconfig.get_config_var('Py_ENABLE_SHARED') == 1, + 'The Python shared library cannot be loaded ' + 'without some system environments.') + @unittest.skipIf(check_sanitizer(address=True), + 'AddressSanitizer adds to the environment.') + def test_one_environment_variable(self): + newenv = {'fruit': 'orange'} + cmd = [sys.executable, '-c', + 'import sys,os;' + 'sys.stdout.write("fruit="+os.getenv("fruit"))'] + if sys.platform == "win32": + cmd = ["CMD", "/c", "SET", "fruit"] + with subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=newenv) as p: + stdout, stderr = p.communicate() + if p.returncode and support.verbose: + print("STDOUT:", stdout.decode("ascii", "replace")) + print("STDERR:", stderr.decode("ascii", "replace")) + self.assertEqual(p.returncode, 0) + self.assertEqual(stdout.strip(), b"fruit=orange") + def test_invalid_cmd(self): # null character in the command name cmd = sys.executable + '\0' @@ -856,6 +895,19 @@ def test_invalid_env(self): stdout, stderr = p.communicate() self.assertEqual(stdout, b"orange=lemon") + @unittest.skipUnless(sys.platform == "win32", "Windows only issue") + def test_win32_invalid_env(self): + # '=' in the environment variable name + newenv = os.environ.copy() + newenv["FRUIT=VEGETABLE"] = "cabbage" + with self.assertRaises(ValueError): + subprocess.Popen(ZERO_RETURN_CMD, env=newenv) + + newenv = os.environ.copy() + newenv["==FRUIT"] = "cabbage" + with self.assertRaises(ValueError): + subprocess.Popen(ZERO_RETURN_CMD, env=newenv) + def test_communicate_stdin(self): p = subprocess.Popen([sys.executable, "-c", 'import sys;' @@ -1292,6 +1344,7 @@ def test_bufsize_equal_one_binary_mode(self): with self.assertWarnsRegex(RuntimeWarning, 'line buffering'): self._test_bufsize_equal_one(line, b'', universal_newlines=False) + @support.requires_resource('cpu') def test_leaking_fds_on_error(self): # see bug #5179: Popen leaks file descriptors to PIPEs if # the child fails to execute; this will eventually exhaust @@ -1554,21 +1607,6 @@ def test_class_getitems(self): self.assertIsInstance(subprocess.Popen[bytes], types.GenericAlias) self.assertIsInstance(subprocess.CompletedProcess[str], types.GenericAlias) - @unittest.skipIf(not sysconfig.get_config_var("HAVE_VFORK"), - "vfork() not enabled by configure.") - @mock.patch("subprocess._fork_exec") - def test__use_vfork(self, mock_fork_exec): - self.assertTrue(subprocess._USE_VFORK) # The default value regardless. - mock_fork_exec.side_effect = RuntimeError("just testing args") - with self.assertRaises(RuntimeError): - subprocess.run([sys.executable, "-c", "pass"]) - mock_fork_exec.assert_called_once() - self.assertTrue(mock_fork_exec.call_args.args[-1]) - with mock.patch.object(subprocess, '_USE_VFORK', False): - with self.assertRaises(RuntimeError): - subprocess.run([sys.executable, "-c", "pass"]) - self.assertFalse(mock_fork_exec.call_args_list[-1].args[-1]) - class RunFuncTestCase(BaseTestCase): def run_python(self, code, **kwargs): @@ -1642,6 +1680,7 @@ def test_check_output_stdin_with_input_arg(self): self.assertIn('stdin', c.exception.args[0]) self.assertIn('input', c.exception.args[0]) + @support.requires_resource('walltime') def test_check_output_timeout(self): with self.assertRaises(subprocess.TimeoutExpired) as c: cp = self.run_python(( @@ -1761,9 +1800,9 @@ def test_encoding_warning(self): cp = subprocess.run([sys.executable, "-Xwarn_default_encoding", "-c", code], capture_output=True) lines = cp.stderr.splitlines() - self.assertEqual(len(lines), 2, lines) + self.assertEqual(len(lines), 4, lines) self.assertTrue(lines[0].startswith(b":2: EncodingWarning: ")) - self.assertTrue(lines[1].startswith(b":3: EncodingWarning: ")) + self.assertTrue(lines[2].startswith(b":3: EncodingWarning: ")) def _get_test_grp_name(): @@ -2058,8 +2097,14 @@ def test_group_error(self): def test_extra_groups(self): gid = os.getegid() group_list = [65534 if gid != 65534 else 65533] + self._test_extra_groups_impl(gid=gid, group_list=group_list) + + @unittest.skipUnless(hasattr(os, 'setgroups'), 'no setgroups() on platform') + def test_extra_groups_empty_list(self): + self._test_extra_groups_impl(gid=os.getegid(), group_list=[]) + + def _test_extra_groups_impl(self, *, gid, group_list): name_group = _get_test_grp_name() - perm_error = False if grp is not None: group_list.append(name_group) @@ -2069,11 +2114,8 @@ def test_extra_groups(self): [sys.executable, "-c", "import os, sys, json; json.dump(os.getgroups(), sys.stdout)"], extra_groups=group_list) - except OSError as ex: - if ex.errno != errno.EPERM: - raise - perm_error = True - + except PermissionError: + self.skipTest("setgroup() EPERM; this test may require root.") else: parent_groups = os.getgroups() child_groups = json.loads(output) @@ -2084,12 +2126,15 @@ def test_extra_groups(self): else: desired_gids = group_list - if perm_error: - self.assertEqual(set(child_groups), set(parent_groups)) - else: - self.assertEqual(set(desired_gids), set(child_groups)) + self.assertEqual(set(desired_gids), set(child_groups)) - # make sure we bomb on negative values + if grp is None: + with self.assertRaises(ValueError): + subprocess.check_call(ZERO_RETURN_CMD, + extra_groups=[name_group]) + + # No skip necessary, this test won't make it to a setgroup() call. + def test_extra_groups_invalid_gid_t_values(self): with self.assertRaises(ValueError): subprocess.check_call(ZERO_RETURN_CMD, extra_groups=[-1]) @@ -2098,16 +2143,6 @@ def test_extra_groups(self): cwd=os.curdir, env=os.environ, extra_groups=[2**64]) - if grp is None: - with self.assertRaises(ValueError): - subprocess.check_call(ZERO_RETURN_CMD, - extra_groups=[name_group]) - - @unittest.skipIf(hasattr(os, 'setgroups'), 'setgroups() available on platform') - def test_extra_groups_error(self): - with self.assertRaises(ValueError): - subprocess.check_call(ZERO_RETURN_CMD, extra_groups=[]) - @unittest.skipIf(mswindows or not hasattr(os, 'umask'), 'POSIX umask() is not available.') def test_umask(self): @@ -3356,6 +3391,94 @@ def exit_handler(): self.assertEqual(out, b'') self.assertIn(b"preexec_fn not supported at interpreter shutdown", err) + @unittest.skipIf(not sysconfig.get_config_var("HAVE_VFORK"), + "vfork() not enabled by configure.") + @mock.patch("subprocess._fork_exec") + @mock.patch("subprocess._USE_POSIX_SPAWN", new=False) + def test__use_vfork(self, mock_fork_exec): + self.assertTrue(subprocess._USE_VFORK) # The default value regardless. + mock_fork_exec.side_effect = RuntimeError("just testing args") + with self.assertRaises(RuntimeError): + subprocess.run([sys.executable, "-c", "pass"]) + mock_fork_exec.assert_called_once() + # NOTE: These assertions are *ugly* as they require the last arg + # to remain the have_vfork boolean. We really need to refactor away + # from the giant "wall of args" internal C extension API. + self.assertTrue(mock_fork_exec.call_args.args[-1]) + with mock.patch.object(subprocess, '_USE_VFORK', False): + with self.assertRaises(RuntimeError): + subprocess.run([sys.executable, "-c", "pass"]) + self.assertFalse(mock_fork_exec.call_args_list[-1].args[-1]) + + @unittest.skipIf(not sysconfig.get_config_var("HAVE_VFORK"), + "vfork() not enabled by configure.") + @unittest.skipIf(sys.platform != "linux", "Linux only, requires strace.") + @mock.patch("subprocess._USE_POSIX_SPAWN", new=False) + def test_vfork_used_when_expected(self): + # This is a performance regression test to ensure we default to using + # vfork() when possible. + # Technically this test could pass when posix_spawn is used as well + # because libc tends to implement that internally using vfork. But + # that'd just be testing a libc+kernel implementation detail. + strace_binary = "/usr/bin/strace" + # The only system calls we are interested in. + strace_filter = "--trace=clone,clone2,clone3,fork,vfork,exit,exit_group" + true_binary = "/bin/true" + strace_command = [strace_binary, strace_filter] + + try: + does_strace_work_process = subprocess.run( + strace_command + [true_binary], + stderr=subprocess.PIPE, + stdout=subprocess.DEVNULL, + ) + rc = does_strace_work_process.returncode + stderr = does_strace_work_process.stderr + except OSError: + rc = -1 + stderr = "" + if rc or (b"+++ exited with 0 +++" not in stderr): + self.skipTest("strace not found or not working as expected.") + + with self.subTest(name="default_is_vfork"): + vfork_result = assert_python_ok( + "-c", + textwrap.dedent(f"""\ + import subprocess + subprocess.check_call([{true_binary!r}])"""), + __run_using_command=strace_command, + ) + # Match both vfork() and clone(..., flags=...|CLONE_VFORK|...) + self.assertRegex(vfork_result.err, br"(?i)vfork") + # Do NOT check that fork() or other clones did not happen. + # If the OS denys the vfork it'll fallback to plain fork(). + + # Test that each individual thing that would disable the use of vfork + # actually disables it. + for sub_name, preamble, sp_kwarg, expect_permission_error in ( + ("!use_vfork", "subprocess._USE_VFORK = False", "", False), + ("preexec", "", "preexec_fn=lambda: None", False), + ("setgid", "", f"group={os.getgid()}", True), + ("setuid", "", f"user={os.getuid()}", True), + ("setgroups", "", "extra_groups=[]", True), + ): + with self.subTest(name=sub_name): + non_vfork_result = assert_python_ok( + "-c", + textwrap.dedent(f"""\ + import subprocess + {preamble} + try: + subprocess.check_call( + [{true_binary!r}], **dict({sp_kwarg})) + except PermissionError: + if not {expect_permission_error}: + raise"""), + __run_using_command=strace_command, + ) + # Ensure neither vfork() or clone(..., flags=...|CLONE_VFORK|...). + self.assertNotRegex(non_vfork_result.err, br"(?i)vfork") + @unittest.skipUnless(mswindows, "Windows specific tests") class Win32ProcessTestCase(BaseTestCase): diff --git a/Lib/test/test_super.py b/Lib/test/test_super.py index 43162c540b55ae..f8e968b9b56f82 100644 --- a/Lib/test/test_super.py +++ b/Lib/test/test_super.py @@ -396,6 +396,33 @@ def method(self): with self.assertRaisesRegex(TypeError, "argument 1 must be a type"): C().method() + def test_supercheck_fail(self): + class C: + def method(self, type_, obj): + return super(type_, obj).method() + + c = C() + err_msg = ( + r"super\(type, obj\): obj \({} {}\) is not " + r"an instance or subtype of type \({}\)." + ) + + cases = ( + (int, c, int.__name__, C.__name__, "instance of"), + # obj is instance of type + (C, list(), C.__name__, list.__name__, "instance of"), + # obj is type itself + (C, list, C.__name__, list.__name__, "type"), + ) + + for case in cases: + with self.subTest(case=case): + type_, obj, type_str, obj_str, instance_or_type = case + regex = err_msg.format(instance_or_type, obj_str, type_str) + + with self.assertRaisesRegex(TypeError, regex): + c.method(type_, obj) + def test_super___class__(self): class C: def method(self): diff --git a/Lib/test/test_support.py b/Lib/test/test_support.py index cd1679dd23281c..d160cbf0645b47 100644 --- a/Lib/test/test_support.py +++ b/Lib/test/test_support.py @@ -7,6 +7,7 @@ import stat import subprocess import sys +import sysconfig import tempfile import textwrap import unittest @@ -497,6 +498,7 @@ def check_options(self, args, func, expected=None): self.assertEqual(proc.stdout.rstrip(), repr(expected)) self.assertEqual(proc.returncode, 0) + @support.requires_resource('cpu') def test_args_from_interpreter_flags(self): # Test test.support.args_from_interpreter_flags() for opts in ( @@ -545,111 +547,6 @@ def test_optim_args_from_interpreter_flags(self): with self.subTest(opts=opts): self.check_options(opts, 'optim_args_from_interpreter_flags') - def test_match_test(self): - class Test: - def __init__(self, test_id): - self.test_id = test_id - - def id(self): - return self.test_id - - test_access = Test('test.test_os.FileTests.test_access') - test_chdir = Test('test.test_os.Win32ErrorTests.test_chdir') - - # Test acceptance - with support.swap_attr(support, '_match_test_func', None): - # match all - support.set_match_tests([]) - self.assertTrue(support.match_test(test_access)) - self.assertTrue(support.match_test(test_chdir)) - - # match all using None - support.set_match_tests(None, None) - self.assertTrue(support.match_test(test_access)) - self.assertTrue(support.match_test(test_chdir)) - - # match the full test identifier - support.set_match_tests([test_access.id()], None) - self.assertTrue(support.match_test(test_access)) - self.assertFalse(support.match_test(test_chdir)) - - # match the module name - support.set_match_tests(['test_os'], None) - self.assertTrue(support.match_test(test_access)) - self.assertTrue(support.match_test(test_chdir)) - - # Test '*' pattern - support.set_match_tests(['test_*'], None) - self.assertTrue(support.match_test(test_access)) - self.assertTrue(support.match_test(test_chdir)) - - # Test case sensitivity - support.set_match_tests(['filetests'], None) - self.assertFalse(support.match_test(test_access)) - support.set_match_tests(['FileTests'], None) - self.assertTrue(support.match_test(test_access)) - - # Test pattern containing '.' and a '*' metacharacter - support.set_match_tests(['*test_os.*.test_*'], None) - self.assertTrue(support.match_test(test_access)) - self.assertTrue(support.match_test(test_chdir)) - - # Multiple patterns - support.set_match_tests([test_access.id(), test_chdir.id()], None) - self.assertTrue(support.match_test(test_access)) - self.assertTrue(support.match_test(test_chdir)) - - support.set_match_tests(['test_access', 'DONTMATCH'], None) - self.assertTrue(support.match_test(test_access)) - self.assertFalse(support.match_test(test_chdir)) - - # Test rejection - with support.swap_attr(support, '_match_test_func', None): - # match all - support.set_match_tests(ignore_patterns=[]) - self.assertTrue(support.match_test(test_access)) - self.assertTrue(support.match_test(test_chdir)) - - # match all using None - support.set_match_tests(None, None) - self.assertTrue(support.match_test(test_access)) - self.assertTrue(support.match_test(test_chdir)) - - # match the full test identifier - support.set_match_tests(None, [test_access.id()]) - self.assertFalse(support.match_test(test_access)) - self.assertTrue(support.match_test(test_chdir)) - - # match the module name - support.set_match_tests(None, ['test_os']) - self.assertFalse(support.match_test(test_access)) - self.assertFalse(support.match_test(test_chdir)) - - # Test '*' pattern - support.set_match_tests(None, ['test_*']) - self.assertFalse(support.match_test(test_access)) - self.assertFalse(support.match_test(test_chdir)) - - # Test case sensitivity - support.set_match_tests(None, ['filetests']) - self.assertTrue(support.match_test(test_access)) - support.set_match_tests(None, ['FileTests']) - self.assertFalse(support.match_test(test_access)) - - # Test pattern containing '.' and a '*' metacharacter - support.set_match_tests(None, ['*test_os.*.test_*']) - self.assertFalse(support.match_test(test_access)) - self.assertFalse(support.match_test(test_chdir)) - - # Multiple patterns - support.set_match_tests(None, [test_access.id(), test_chdir.id()]) - self.assertFalse(support.match_test(test_access)) - self.assertFalse(support.match_test(test_chdir)) - - support.set_match_tests(None, ['test_access', 'DONTMATCH']) - self.assertFalse(support.match_test(test_access)) - self.assertTrue(support.match_test(test_chdir)) - @unittest.skipIf(support.is_emscripten, "Unstable in Emscripten") @unittest.skipIf(support.is_wasi, "Unavailable on WASI") def test_fd_count(self): @@ -684,6 +581,157 @@ def test_has_strftime_extensions(self): else: self.assertTrue(support.has_strftime_extensions) + def test_get_recursion_depth(self): + # test support.get_recursion_depth() + code = textwrap.dedent(""" + from test import support + import sys + + def check(cond): + if not cond: + raise AssertionError("test failed") + + # depth 1 + check(support.get_recursion_depth() == 1) + + # depth 2 + def test_func(): + check(support.get_recursion_depth() == 2) + test_func() + + def test_recursive(depth, limit): + if depth >= limit: + # cannot call get_recursion_depth() at this depth, + # it can raise RecursionError + return + get_depth = support.get_recursion_depth() + print(f"test_recursive: {depth}/{limit}: " + f"get_recursion_depth() says {get_depth}") + check(get_depth == depth) + test_recursive(depth + 1, limit) + + # depth up to 25 + with support.infinite_recursion(max_depth=25): + limit = sys.getrecursionlimit() + print(f"test with sys.getrecursionlimit()={limit}") + test_recursive(2, limit) + + # depth up to 500 + with support.infinite_recursion(max_depth=500): + limit = sys.getrecursionlimit() + print(f"test with sys.getrecursionlimit()={limit}") + test_recursive(2, limit) + """) + script_helper.assert_python_ok("-c", code) + + def test_recursion(self): + # Test infinite_recursion() and get_recursion_available() functions. + def recursive_function(depth): + if depth: + recursive_function(depth - 1) + + for max_depth in (5, 25, 250, 2500): + with support.infinite_recursion(max_depth): + available = support.get_recursion_available() + + # Recursion up to 'available' additional frames should be OK. + recursive_function(available) + + # Recursion up to 'available+1' additional frames must raise + # RecursionError. Avoid self.assertRaises(RecursionError) which + # can consume more than 3 frames and so raises RecursionError. + try: + recursive_function(available + 1) + except RecursionError: + pass + else: + self.fail("RecursionError was not raised") + + # Test the bare minimumum: max_depth=3 + with support.infinite_recursion(3): + try: + recursive_function(3) + except RecursionError: + pass + else: + self.fail("RecursionError was not raised") + + def test_parse_memlimit(self): + parse = support._parse_memlimit + KiB = 1024 + MiB = KiB * 1024 + GiB = MiB * 1024 + TiB = GiB * 1024 + self.assertEqual(parse('0k'), 0) + self.assertEqual(parse('3k'), 3 * KiB) + self.assertEqual(parse('2.4m'), int(2.4 * MiB)) + self.assertEqual(parse('4g'), int(4 * GiB)) + self.assertEqual(parse('1t'), TiB) + + for limit in ('', '3', '3.5.10k', '10x'): + with self.subTest(limit=limit): + with self.assertRaises(ValueError): + parse(limit) + + def test_set_memlimit(self): + _4GiB = 4 * 1024 ** 3 + TiB = 1024 ** 4 + old_max_memuse = support.max_memuse + old_real_max_memuse = support.real_max_memuse + try: + if sys.maxsize > 2**32: + support.set_memlimit('4g') + self.assertEqual(support.max_memuse, _4GiB) + self.assertEqual(support.real_max_memuse, _4GiB) + + big = 2**100 // TiB + support.set_memlimit(f'{big}t') + self.assertEqual(support.max_memuse, sys.maxsize) + self.assertEqual(support.real_max_memuse, big * TiB) + else: + support.set_memlimit('4g') + self.assertEqual(support.max_memuse, sys.maxsize) + self.assertEqual(support.real_max_memuse, _4GiB) + finally: + support.max_memuse = old_max_memuse + support.real_max_memuse = old_real_max_memuse + + def test_copy_python_src_ignore(self): + # Get source directory + src_dir = sysconfig.get_config_var('abs_srcdir') + if not src_dir: + src_dir = sysconfig.get_config_var('srcdir') + src_dir = os.path.abspath(src_dir) + + # Check that the source code is available + if not os.path.exists(src_dir): + self.skipTest(f"cannot access Python source code directory:" + f" {src_dir!r}") + # Check that the landmark copy_python_src_ignore() expects is available + # (Previously we looked for 'Lib\os.py', which is always present on Windows.) + landmark = os.path.join(src_dir, 'Modules') + if not os.path.exists(landmark): + self.skipTest(f"cannot access Python source code directory:" + f" {landmark!r} landmark is missing") + + # Test support.copy_python_src_ignore() + + # Source code directory + ignored = {'.git', '__pycache__'} + names = os.listdir(src_dir) + self.assertEqual(support.copy_python_src_ignore(src_dir, names), + ignored | {'build'}) + + # Doc/ directory + path = os.path.join(src_dir, 'Doc') + self.assertEqual(support.copy_python_src_ignore(path, os.listdir(path)), + ignored | {'build', 'venv'}) + + # Another directory + path = os.path.join(src_dir, 'Objects') + self.assertEqual(support.copy_python_src_ignore(path, os.listdir(path)), + ignored) + # XXX -follows a list of untested API # make_legacy_pyc # is_resource_enabled @@ -695,12 +743,10 @@ def test_has_strftime_extensions(self): # EnvironmentVarGuard # transient_internet # run_with_locale - # set_memlimit # bigmemtest # precisionbigmemtest # bigaddrspacetest # requires_resource - # run_doctest # threading_cleanup # reap_threads # can_symlink diff --git a/Lib/test/test_symtable.py b/Lib/test/test_symtable.py index 25714aecda3a15..92b78a8086a83d 100644 --- a/Lib/test/test_symtable.py +++ b/Lib/test/test_symtable.py @@ -4,6 +4,8 @@ import symtable import unittest +from test import support +from test.support import os_helper TEST_CODE = """ @@ -40,6 +42,15 @@ def foo(): def namespace_test(): pass def namespace_test(): pass + +type Alias = int +type GenericAlias[T] = list[T] + +def generic_spam[T](a): + pass + +class GenericMine[T: int]: + pass """ @@ -59,6 +70,14 @@ class SymtableTest(unittest.TestCase): internal = find_block(spam, "internal") other_internal = find_block(spam, "other_internal") foo = find_block(top, "foo") + Alias = find_block(top, "Alias") + GenericAlias = find_block(top, "GenericAlias") + GenericAlias_inner = find_block(GenericAlias, "GenericAlias") + generic_spam = find_block(top, "generic_spam") + generic_spam_inner = find_block(generic_spam, "generic_spam") + GenericMine = find_block(top, "GenericMine") + GenericMine_inner = find_block(GenericMine, "GenericMine") + T = find_block(GenericMine, "T") def test_type(self): self.assertEqual(self.top.get_type(), "module") @@ -66,6 +85,15 @@ def test_type(self): self.assertEqual(self.a_method.get_type(), "function") self.assertEqual(self.spam.get_type(), "function") self.assertEqual(self.internal.get_type(), "function") + self.assertEqual(self.foo.get_type(), "function") + self.assertEqual(self.Alias.get_type(), "type alias") + self.assertEqual(self.GenericAlias.get_type(), "type parameter") + self.assertEqual(self.GenericAlias_inner.get_type(), "type alias") + self.assertEqual(self.generic_spam.get_type(), "type parameter") + self.assertEqual(self.generic_spam_inner.get_type(), "function") + self.assertEqual(self.GenericMine.get_type(), "type parameter") + self.assertEqual(self.GenericMine_inner.get_type(), "class") + self.assertEqual(self.T.get_type(), "TypeVar bound") def test_id(self): self.assertGreater(self.top.get_id(), 0) @@ -73,6 +101,11 @@ def test_id(self): self.assertGreater(self.a_method.get_id(), 0) self.assertGreater(self.spam.get_id(), 0) self.assertGreater(self.internal.get_id(), 0) + self.assertGreater(self.foo.get_id(), 0) + self.assertGreater(self.Alias.get_id(), 0) + self.assertGreater(self.GenericAlias.get_id(), 0) + self.assertGreater(self.generic_spam.get_id(), 0) + self.assertGreater(self.GenericMine.get_id(), 0) def test_optimized(self): self.assertFalse(self.top.is_optimized()) @@ -251,6 +284,61 @@ def test_symtable_repr(self): self.assertEqual(str(self.top), "") self.assertEqual(str(self.spam), "") + def test_symbol_repr(self): + self.assertEqual(repr(self.spam.lookup("glob")), + "") + self.assertEqual(repr(self.spam.lookup("bar")), + "") + self.assertEqual(repr(self.spam.lookup("a")), + "") + self.assertEqual(repr(self.spam.lookup("internal")), + "") + self.assertEqual(repr(self.spam.lookup("other_internal")), + "") + self.assertEqual(repr(self.internal.lookup("x")), + "") + self.assertEqual(repr(self.other_internal.lookup("some_var")), + "") + + def test_symtable_entry_repr(self): + expected = f"" + self.assertEqual(repr(self.top._table), expected) + + +class CommandLineTest(unittest.TestCase): + maxDiff = None + + def test_file(self): + filename = os_helper.TESTFN + self.addCleanup(os_helper.unlink, filename) + with open(filename, 'w') as f: + f.write(TEST_CODE) + with support.captured_stdout() as stdout: + symtable.main([filename]) + out = stdout.getvalue() + self.assertIn('\n\n', out) + self.assertNotIn('\n\n\n', out) + lines = out.splitlines() + self.assertIn(f"symbol table for module from file {filename!r}:", lines) + self.assertIn(" local symbol 'glob': def_local", lines) + self.assertIn(" global_implicit symbol 'glob': use", lines) + self.assertIn(" local symbol 'spam': def_local", lines) + self.assertIn(" symbol table for function 'spam':", lines) + + def test_stdin(self): + with support.captured_stdin() as stdin: + stdin.write(TEST_CODE) + stdin.seek(0) + with support.captured_stdout() as stdout: + symtable.main([]) + out = stdout.getvalue() + stdin.seek(0) + with support.captured_stdout() as stdout: + symtable.main(['-']) + self.assertEqual(stdout.getvalue(), out) + lines = out.splitlines() + self.assertIn("symbol table for module from file '':", lines) + if __name__ == '__main__': unittest.main() diff --git a/Lib/test/test_syntax.py b/Lib/test/test_syntax.py index f3d6cd7bad0eec..ee9b873d9023f0 100644 --- a/Lib/test/test_syntax.py +++ b/Lib/test/test_syntax.py @@ -259,6 +259,36 @@ Traceback (most recent call last): SyntaxError: invalid syntax +Comprehensions without 'in' keyword: + +>>> [x for x if range(1)] +Traceback (most recent call last): +SyntaxError: 'in' expected after for-loop variables + +>>> tuple(x for x if range(1)) +Traceback (most recent call last): +SyntaxError: 'in' expected after for-loop variables + +>>> [x for x() in a] +Traceback (most recent call last): +SyntaxError: cannot assign to function call + +>>> [x for a, b, (c + 1, d()) in y] +Traceback (most recent call last): +SyntaxError: cannot assign to expression + +>>> [x for a, b, (c + 1, d()) if y] +Traceback (most recent call last): +SyntaxError: 'in' expected after for-loop variables + +>>> [x for x+1 in y] +Traceback (most recent call last): +SyntaxError: cannot assign to expression + +>>> [x for x+1, x() in y] +Traceback (most recent call last): +SyntaxError: cannot assign to expression + Comprehensions creating tuples without parentheses should produce a specialized error message: @@ -1004,11 +1034,26 @@ Traceback (most recent call last): SyntaxError: expected ':' + >>> def f[T]() + ... pass + Traceback (most recent call last): + SyntaxError: expected ':' + >>> class A ... pass Traceback (most recent call last): SyntaxError: expected ':' + >>> class A[T] + ... pass + Traceback (most recent call last): + SyntaxError: expected ':' + + >>> class A[T]() + ... pass + Traceback (most recent call last): + SyntaxError: expected ':' + >>> class R&D: ... pass Traceback (most recent call last): @@ -1446,11 +1491,21 @@ Traceback (most recent call last): IndentationError: expected an indented block after function definition on line 1 + >>> def foo[T](x, /, y, *, z=2): + ... pass + Traceback (most recent call last): + IndentationError: expected an indented block after function definition on line 1 + >>> class Blech(A): ... pass Traceback (most recent call last): IndentationError: expected an indented block after class definition on line 1 + >>> class Blech[T](A): + ... pass + Traceback (most recent call last): + IndentationError: expected an indented block after class definition on line 1 + >>> match something: ... pass Traceback (most recent call last): @@ -1727,6 +1782,28 @@ Traceback (most recent call last): SyntaxError: positional patterns follow keyword patterns +Non-matching 'elif'/'else' statements: + + >>> if a == b: + ... ... + ... elif a == c: + Traceback (most recent call last): + SyntaxError: 'elif' must match an if-statement here + + >>> if x == y: + ... ... + ... else: + Traceback (most recent call last): + SyntaxError: 'else' must match a valid statement here + + >>> elif m == n: + Traceback (most recent call last): + SyntaxError: 'elif' must match an if-statement here + + >>> else: + Traceback (most recent call last): + SyntaxError: 'else' must match a valid statement here + Uses of the star operator which should fail: A[:*b] @@ -1955,10 +2032,22 @@ def f(x: *b) ... SyntaxError: yield expression cannot be used within the definition of a generic + >>> f(**x, *y) + Traceback (most recent call last): + SyntaxError: iterable argument unpacking follows keyword argument unpacking + + >>> f(**x, *) + Traceback (most recent call last): + SyntaxError: iterable argument unpacking follows keyword argument unpacking + + >>> f(x, *:) + Traceback (most recent call last): + SyntaxError: invalid syntax """ import re import doctest +import textwrap import unittest from test import support @@ -1970,8 +2059,8 @@ def _check_error(self, code, errtext, lineno=None, offset=None, end_lineno=None, end_offset=None): """Check that compiling code raises SyntaxError with errtext. - errtest is a regular expression that must be present in the - test of the exception raised. If subclass is specified it + errtext is a regular expression that must be present in the + test of the exception raised. If subclass is specified, it is the expected subclass of SyntaxError (e.g. IndentationError). """ try: @@ -1995,6 +2084,22 @@ def _check_error(self, code, errtext, else: self.fail("compile() did not raise SyntaxError") + def _check_noerror(self, code, + errtext="compile() raised unexpected SyntaxError", + filename="", mode="exec", subclass=None): + """Check that compiling code does not raise a SyntaxError. + + errtext is the message passed to self.fail if there is + a SyntaxError. If the subclass parameter is specified, + it is the subclass of SyntaxError (e.g. IndentationError) + that the raised error is checked against. + """ + try: + compile(code, filename, mode) + except SyntaxError as err: + if (not subclass) or isinstance(err, subclass): + self.fail(errtext) + def test_expression_with_assignment(self): self._check_error( "print(end1 + end2 = ' ')", @@ -2205,6 +2310,31 @@ def test_nested_named_except_blocks(self): code += f"{' '*4*12}pass" self._check_error(code, "too many statically nested blocks") + @support.cpython_only + def test_with_statement_many_context_managers(self): + # See gh-113297 + + def get_code(n): + code = textwrap.dedent(""" + def bug(): + with ( + a + """) + for i in range(n): + code += f" as a{i}, a\n" + code += "): yield a" + return code + + CO_MAXBLOCKS = 20 # static nesting limit of the compiler + + for n in range(CO_MAXBLOCKS): + with self.subTest(f"within range: {n=}"): + compile(get_code(n), "", "exec") + + for n in range(CO_MAXBLOCKS, CO_MAXBLOCKS + 5): + with self.subTest(f"out of range: {n=}"): + self._check_error(get_code(n), "too many statically nested blocks") + def test_barry_as_flufl_with_syntax_errors(self): # The "barry_as_flufl" rule can produce some "bugs-at-a-distance" if # is reading the wrong token in the presence of syntax errors later @@ -2260,15 +2390,28 @@ def test_error_parenthesis(self): """ self._check_error(code, "parenthesis '\\)' does not match opening parenthesis '\\['") + self._check_error("match y:\n case e(e=v,v,", " was never closed") + + # Examples with dencodings + s = b'# coding=latin\n(aaaaaaaaaaaaaaaaa\naaaaaaaaaaa\xb5' + self._check_error(s, r"'\(' was never closed") + def test_error_string_literal(self): - self._check_error("'blech", "unterminated string literal") - self._check_error('"blech', "unterminated string literal") + self._check_error("'blech", r"unterminated string literal \(.*\)$") + self._check_error('"blech', r"unterminated string literal \(.*\)$") + self._check_error( + r'"blech\"', r"unterminated string literal \(.*\); perhaps you escaped the end quote" + ) + self._check_error( + r'r"blech\"', r"unterminated string literal \(.*\); perhaps you escaped the end quote" + ) self._check_error("'''blech", "unterminated triple-quoted string literal") self._check_error('"""blech', "unterminated triple-quoted string literal") def test_invisible_characters(self): self._check_error('print\x17("Hello")', "invalid non-printable character") + self._check_error(b"with(0,,):\n\x01", "invalid non-printable character") def test_match_call_does_not_raise_syntax_error(self): code = """ @@ -2330,12 +2473,31 @@ def test_syntax_error_on_deeply_nested_blocks(self): """ self._check_error(source, "too many statically nested blocks") + def test_syntax_error_non_matching_elif_else_statements(self): + # Check bpo-45759: 'elif' statements that doesn't match an + # if-statement or 'else' statements that doesn't match any + # valid else-able statement (e.g. 'while') + self._check_error( + "elif m == n:\n ...", + "'elif' must match an if-statement here") + self._check_error( + "else:\n ...", + "'else' must match a valid statement here") + self._check_noerror("if a == b:\n ...\nelif a == c:\n ...") + self._check_noerror("if x == y:\n ...\nelse:\n ...") + self._check_error( + "else = 123", + "invalid syntax") + self._check_error( + "elif 55 = 123", + "cannot assign to literal here") + @support.cpython_only def test_error_on_parser_stack_overflow(self): source = "-" * 100000 + "4" for mode in ["exec", "eval", "single"]: with self.subTest(mode=mode): - with self.assertRaises(MemoryError): + with self.assertRaisesRegex(MemoryError, r"too complex"): compile(source, "", mode) @support.cpython_only diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py index 9dce15ed1529e7..6c87dfabad9f0f 100644 --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -1,9 +1,11 @@ import builtins import codecs +import _datetime import gc import locale import operator import os +import random import struct import subprocess import sys @@ -29,10 +31,6 @@ def requires_subinterpreters(meth): 'subinterpreters required')(meth) -# count the number of test runs, used to create unique -# strings to intern in test_intern() -INTERN_NUMRUNS = 0 - DICT_KEY_STRUCT_FORMAT = 'n2BI2n' class DisplayHookTest(unittest.TestCase): @@ -177,7 +175,8 @@ def test_excepthook_bytes_filename(self): def test_excepthook(self): with test.support.captured_output("stderr") as stderr: - sys.excepthook(1, '1', 1) + with test.support.catch_unraisable_exception(): + sys.excepthook(1, '1', 1) self.assertTrue("TypeError: print_exception(): Exception expected for " \ "value, str found" in stderr.getvalue()) @@ -279,20 +278,29 @@ def test_switchinterval(self): finally: sys.setswitchinterval(orig) - def test_recursionlimit(self): + def test_getrecursionlimit(self): + limit = sys.getrecursionlimit() + self.assertIsInstance(limit, int) + self.assertGreater(limit, 1) + self.assertRaises(TypeError, sys.getrecursionlimit, 42) - oldlimit = sys.getrecursionlimit() - self.assertRaises(TypeError, sys.setrecursionlimit) - self.assertRaises(ValueError, sys.setrecursionlimit, -42) - sys.setrecursionlimit(10000) - self.assertEqual(sys.getrecursionlimit(), 10000) - sys.setrecursionlimit(oldlimit) + + def test_setrecursionlimit(self): + old_limit = sys.getrecursionlimit() + try: + sys.setrecursionlimit(10_005) + self.assertEqual(sys.getrecursionlimit(), 10_005) + + self.assertRaises(TypeError, sys.setrecursionlimit) + self.assertRaises(ValueError, sys.setrecursionlimit, -42) + finally: + sys.setrecursionlimit(old_limit) def test_recursionlimit_recovery(self): if hasattr(sys, 'gettrace') and sys.gettrace(): self.skipTest('fatal error if run with a trace function') - oldlimit = sys.getrecursionlimit() + old_limit = sys.getrecursionlimit() def f(): f() try: @@ -311,35 +319,31 @@ def f(): with self.assertRaises(RecursionError): f() finally: - sys.setrecursionlimit(oldlimit) + sys.setrecursionlimit(old_limit) @test.support.cpython_only - def test_setrecursionlimit_recursion_depth(self): + def test_setrecursionlimit_to_depth(self): # Issue #25274: Setting a low recursion limit must be blocked if the # current recursion depth is already higher than limit. - from _testinternalcapi import get_recursion_depth - - def set_recursion_limit_at_depth(depth, limit): - recursion_depth = get_recursion_depth() - if recursion_depth >= depth: - with self.assertRaises(RecursionError) as cm: - sys.setrecursionlimit(limit) - self.assertRegex(str(cm.exception), - "cannot set the recursion limit to [0-9]+ " - "at the recursion depth [0-9]+: " - "the limit is too low") - else: - set_recursion_limit_at_depth(depth, limit) - - oldlimit = sys.getrecursionlimit() + old_limit = sys.getrecursionlimit() try: - sys.setrecursionlimit(1000) - - for limit in (10, 25, 50, 75, 100, 150, 200): - set_recursion_limit_at_depth(limit, limit) + depth = support.get_recursion_depth() + with self.subTest(limit=sys.getrecursionlimit(), depth=depth): + # depth + 1 is OK + sys.setrecursionlimit(depth + 1) + + # reset the limit to be able to call self.assertRaises() + # context manager + sys.setrecursionlimit(old_limit) + with self.assertRaises(RecursionError) as cm: + sys.setrecursionlimit(depth) + self.assertRegex(str(cm.exception), + "cannot set the recursion limit to [0-9]+ " + "at the recursion depth [0-9]+: " + "the limit is too low") finally: - sys.setrecursionlimit(oldlimit) + sys.setrecursionlimit(old_limit) def test_getwindowsversion(self): # Raise SkipTest if sys doesn't have getwindowsversion attribute @@ -507,7 +511,7 @@ def test_current_exceptions(self): # Spawn a thread that blocks at a known place. Then the main # thread does sys._current_frames(), and verifies that the frames # returned make sense. - entered_g = threading.Event() + g_raised = threading.Event() leave_g = threading.Event() thread_info = [] # the thread's id @@ -516,22 +520,19 @@ def f123(): def g456(): thread_info.append(threading.get_ident()) - entered_g.set() while True: try: raise ValueError("oops") except ValueError: + g_raised.set() if leave_g.wait(timeout=support.LONG_TIMEOUT): break t = threading.Thread(target=f123) t.start() - entered_g.wait() + g_raised.wait(timeout=support.LONG_TIMEOUT) try: - # At this point, t has finished its entered_g.set(), although it's - # impossible to guess whether it's still on that line or has moved on - # to its leave_g.wait(). self.assertEqual(len(thread_info), 1) thread_id = thread_info[0] @@ -690,13 +691,23 @@ def test_43581(self): self.assertEqual(sys.__stdout__.encoding, sys.__stderr__.encoding) def test_intern(self): - global INTERN_NUMRUNS - INTERN_NUMRUNS += 1 + has_is_interned = (test.support.check_impl_detail(cpython=True) + or hasattr(sys, '_is_interned')) self.assertRaises(TypeError, sys.intern) - s = "never interned before" + str(INTERN_NUMRUNS) + self.assertRaises(TypeError, sys.intern, b'abc') + if has_is_interned: + self.assertRaises(TypeError, sys._is_interned) + self.assertRaises(TypeError, sys._is_interned, b'abc') + s = "never interned before" + str(random.randrange(0, 10**9)) self.assertTrue(sys.intern(s) is s) + if has_is_interned: + self.assertIs(sys._is_interned(s), True) s2 = s.swapcase().swapcase() + if has_is_interned: + self.assertIs(sys._is_interned(s2), False) self.assertTrue(sys.intern(s2) is s) + if has_is_interned: + self.assertIs(sys._is_interned(s2), False) # Subclasses of string can't be interned, because they # provide too much opportunity for insane things to happen. @@ -708,17 +719,17 @@ def __hash__(self): return 123 self.assertRaises(TypeError, sys.intern, S("abc")) + if has_is_interned: + self.assertIs(sys._is_interned(S("abc")), False) @requires_subinterpreters def test_subinterp_intern_dynamically_allocated(self): - global INTERN_NUMRUNS - INTERN_NUMRUNS += 1 - s = "never interned before" + str(INTERN_NUMRUNS) + s = "never interned before" + str(random.randrange(0, 10**9)) t = sys.intern(s) self.assertIs(t, s) interp = interpreters.create() - interp.run(textwrap.dedent(f''' + interp.exec_sync(textwrap.dedent(f''' import sys t = sys.intern({s!r}) assert id(t) != {id(s)}, (id(t), {id(s)}) @@ -732,9 +743,8 @@ def test_subinterp_intern_statically_allocated(self): s = '__init__' t = sys.intern(s) - print('------------------------') interp = interpreters.create() - interp.run(textwrap.dedent(f''' + interp.exec_sync(textwrap.dedent(f''' import sys t = sys.intern({s!r}) assert id(t) == {id(t)}, (id(t), {id(t)}) @@ -1118,14 +1128,20 @@ def check(tracebacklimit, expected): traceback = [ b'Traceback (most recent call last):', b' File "", line 8, in ', + b' f2()', + b' ~~^^', b' File "", line 6, in f2', + b' f1()', + b' ~~^^', b' File "", line 4, in f1', + b' 1 / 0', + b' ~~^~~', b'ZeroDivisionError: division by zero' ] check(10, traceback) check(3, traceback) - check(2, traceback[:1] + traceback[2:]) - check(1, traceback[:1] + traceback[3:]) + check(2, traceback[:1] + traceback[4:]) + check(1, traceback[:1] + traceback[7:]) check(0, [traceback[-1]]) check(-1, [traceback[-1]]) check(1<<1000, traceback) @@ -1175,41 +1191,76 @@ def test_stdlib_dir(self): self.assertEqual(os.path.normpath(sys._stdlib_dir), os.path.normpath(expected)) + @unittest.skipUnless(hasattr(sys, 'getobjects'), 'need sys.getobjects()') + def test_getobjects(self): + # sys.getobjects(0) + all_objects = sys.getobjects(0) + self.assertIsInstance(all_objects, list) + self.assertGreater(len(all_objects), 0) + + # sys.getobjects(0, MyType) + class MyType: + pass + size = 100 + my_objects = [MyType() for _ in range(size)] + get_objects = sys.getobjects(0, MyType) + self.assertEqual(len(get_objects), size) + for obj in get_objects: + self.assertIsInstance(obj, MyType) + + # sys.getobjects(3, MyType) + get_objects = sys.getobjects(3, MyType) + self.assertEqual(len(get_objects), 3) + + @unittest.skipUnless(hasattr(sys, '_stats_on'), 'need Py_STATS build') + def test_pystats(self): + # Call the functions, just check that they don't crash + # Cannot save/restore state. + sys._stats_on() + sys._stats_off() + sys._stats_clear() + sys._stats_dump() + + @test.support.cpython_only + @unittest.skipUnless(hasattr(sys, 'abiflags'), 'need sys.abiflags') + def test_disable_gil_abi(self): + self.assertEqual('t' in sys.abiflags, support.Py_GIL_DISABLED) + @test.support.cpython_only class UnraisableHookTest(unittest.TestCase): - def write_unraisable_exc(self, exc, err_msg, obj): - import _testcapi - import types - err_msg2 = f"Exception ignored {err_msg}" - try: - _testcapi.write_unraisable_exc(exc, err_msg, obj) - return types.SimpleNamespace(exc_type=type(exc), - exc_value=exc, - exc_traceback=exc.__traceback__, - err_msg=err_msg2, - object=obj) - finally: - # Explicitly break any reference cycle - exc = None - def test_original_unraisablehook(self): - for err_msg in (None, "original hook"): - with self.subTest(err_msg=err_msg): - obj = "an object" - - with test.support.captured_output("stderr") as stderr: - with test.support.swap_attr(sys, 'unraisablehook', - sys.__unraisablehook__): - self.write_unraisable_exc(ValueError(42), err_msg, obj) - - err = stderr.getvalue() - if err_msg is not None: - self.assertIn(f'Exception ignored {err_msg}: {obj!r}\n', err) - else: - self.assertIn(f'Exception ignored in: {obj!r}\n', err) - self.assertIn('Traceback (most recent call last):\n', err) - self.assertIn('ValueError: 42\n', err) + _testcapi = import_helper.import_module('_testcapi') + from _testcapi import err_writeunraisable, err_formatunraisable + obj = hex + + with support.swap_attr(sys, 'unraisablehook', + sys.__unraisablehook__): + with support.captured_stderr() as stderr: + err_writeunraisable(ValueError(42), obj) + lines = stderr.getvalue().splitlines() + self.assertEqual(lines[0], f'Exception ignored in: {obj!r}') + self.assertEqual(lines[1], 'Traceback (most recent call last):') + self.assertEqual(lines[-1], 'ValueError: 42') + + with support.captured_stderr() as stderr: + err_writeunraisable(ValueError(42), None) + lines = stderr.getvalue().splitlines() + self.assertEqual(lines[0], 'Traceback (most recent call last):') + self.assertEqual(lines[-1], 'ValueError: 42') + + with support.captured_stderr() as stderr: + err_formatunraisable(ValueError(42), 'Error in %R', obj) + lines = stderr.getvalue().splitlines() + self.assertEqual(lines[0], f'Error in {obj!r}:') + self.assertEqual(lines[1], 'Traceback (most recent call last):') + self.assertEqual(lines[-1], 'ValueError: 42') + + with support.captured_stderr() as stderr: + err_formatunraisable(ValueError(42), None) + lines = stderr.getvalue().splitlines() + self.assertEqual(lines[0], 'Traceback (most recent call last):') + self.assertEqual(lines[-1], 'ValueError: 42') def test_original_unraisablehook_err(self): # bpo-22836: PyErr_WriteUnraisable() should give sensible reports @@ -1256,6 +1307,8 @@ def test_original_unraisablehook_exception_qualname(self): # Check that the exception is printed with its qualified name # rather than just classname, and the module names appears # unless it is one of the hard-coded exclusions. + _testcapi = import_helper.import_module('_testcapi') + from _testcapi import err_writeunraisable class A: class B: class X(Exception): @@ -1267,9 +1320,7 @@ class X(Exception): with test.support.captured_stderr() as stderr, test.support.swap_attr( sys, 'unraisablehook', sys.__unraisablehook__ ): - expected = self.write_unraisable_exc( - A.B.X(), "msg", "obj" - ) + err_writeunraisable(A.B.X(), "obj") report = stderr.getvalue() self.assertIn(A.B.X.__qualname__, report) if moduleName in ['builtins', '__main__']: @@ -1285,34 +1336,45 @@ def test_original_unraisablehook_wrong_type(self): sys.unraisablehook(exc) def test_custom_unraisablehook(self): + _testcapi = import_helper.import_module('_testcapi') + from _testcapi import err_writeunraisable, err_formatunraisable hook_args = None def hook_func(args): nonlocal hook_args hook_args = args - obj = object() + obj = hex try: with test.support.swap_attr(sys, 'unraisablehook', hook_func): - expected = self.write_unraisable_exc(ValueError(42), - "custom hook", obj) - for attr in "exc_type exc_value exc_traceback err_msg object".split(): - self.assertEqual(getattr(hook_args, attr), - getattr(expected, attr), - (hook_args, expected)) + exc = ValueError(42) + err_writeunraisable(exc, obj) + self.assertIs(hook_args.exc_type, type(exc)) + self.assertIs(hook_args.exc_value, exc) + self.assertIs(hook_args.exc_traceback, exc.__traceback__) + self.assertIsNone(hook_args.err_msg) + self.assertEqual(hook_args.object, obj) + + err_formatunraisable(exc, "custom hook %R", obj) + self.assertIs(hook_args.exc_type, type(exc)) + self.assertIs(hook_args.exc_value, exc) + self.assertIs(hook_args.exc_traceback, exc.__traceback__) + self.assertEqual(hook_args.err_msg, f'custom hook {obj!r}') + self.assertIsNone(hook_args.object) finally: # expected and hook_args contain an exception: break reference cycle expected = None hook_args = None def test_custom_unraisablehook_fail(self): + _testcapi = import_helper.import_module('_testcapi') + from _testcapi import err_writeunraisable def hook_func(*args): raise Exception("hook_func failed") with test.support.captured_output("stderr") as stderr: with test.support.swap_attr(sys, 'unraisablehook', hook_func): - self.write_unraisable_exc(ValueError(42), - "custom hook fail", None) + err_writeunraisable(ValueError(42), "custom hook fail") err = stderr.getvalue() self.assertIn(f'Exception ignored in sys.unraisablehook: ' @@ -1547,7 +1609,7 @@ def delx(self): del self.__x x = property(getx, setx, delx, "") check(x, size('5Pi')) # PyCapsule - # XXX + check(_datetime.datetime_CAPI, size('6P')) # rangeiterator check(iter(range(1)), size('3l')) check(iter(range(2**65)), size('3P')) diff --git a/Lib/test/test_sys_setprofile.py b/Lib/test/test_sys_setprofile.py index 49e076c77d167a..32e03d7cd25dbe 100644 --- a/Lib/test/test_sys_setprofile.py +++ b/Lib/test/test_sys_setprofile.py @@ -30,9 +30,9 @@ def callback(self, frame, event, arg): if (event == "call" or event == "return" or event == "exception"): - self.add_event(event, frame) + self.add_event(event, frame, arg) - def add_event(self, event, frame=None): + def add_event(self, event, frame=None, arg=None): """Add an event to the log.""" if frame is None: frame = sys._getframe(1) @@ -43,7 +43,7 @@ def add_event(self, event, frame=None): frameno = len(self.frames) self.frames.append(frame) - self.events.append((frameno, event, ident(frame))) + self.events.append((frameno, event, ident(frame), arg)) def get_events(self): """Remove calls to add_event().""" @@ -89,11 +89,16 @@ def trace_pass(self, frame): class TestCaseBase(unittest.TestCase): - def check_events(self, callable, expected): + def check_events(self, callable, expected, check_args=False): events = capture_events(callable, self.new_watcher()) - if events != expected: - self.fail("Expected events:\n%s\nReceived events:\n%s" - % (pprint.pformat(expected), pprint.pformat(events))) + if check_args: + if events != expected: + self.fail("Expected events:\n%s\nReceived events:\n%s" + % (pprint.pformat(expected), pprint.pformat(events))) + else: + if [(frameno, event, ident) for frameno, event, ident, arg in events] != expected: + self.fail("Expected events:\n%s\nReceived events:\n%s" + % (pprint.pformat(expected), pprint.pformat(events))) class ProfileHookTestCase(TestCaseBase): @@ -255,6 +260,21 @@ def g(p): (1, 'return', g_ident), ]) + def test_unfinished_generator(self): + def f(): + for i in range(2): + yield i + def g(p): + next(f()) + + f_ident = ident(f) + g_ident = ident(g) + self.check_events(g, [(1, 'call', g_ident, None), + (2, 'call', f_ident, None), + (2, 'return', f_ident, 0), + (1, 'return', g_ident, None), + ], check_args=True) + def test_stop_iteration(self): def f(): for i in range(2): @@ -439,7 +459,6 @@ def __del__(self): sys.setprofile(foo) self.assertEqual(sys.getprofile(), bar) - def test_same_object(self): def foo(*args): ... @@ -448,6 +467,18 @@ def foo(*args): del foo sys.setprofile(sys.getprofile()) + def test_profile_after_trace_opcodes(self): + def f(): + ... + + sys._getframe().f_trace_opcodes = True + prev_trace = sys.gettrace() + sys.settrace(lambda *args: None) + f() + sys.settrace(prev_trace) + sys.setprofile(lambda *args: None) + f() + if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_sys_settrace.py b/Lib/test/test_sys_settrace.py index 4462b5c712d662..fc5ca72236b1fb 100644 --- a/Lib/test/test_sys_settrace.py +++ b/Lib/test/test_sys_settrace.py @@ -8,6 +8,16 @@ from functools import wraps import asyncio from test.support import import_helper +import contextlib +import os +import tempfile +import textwrap +import subprocess +import warnings +try: + import _testinternalcapi +except ImportError: + _testinternalcapi = None support.requires_working_socket(module=True) @@ -40,6 +50,20 @@ async def asynciter(iterable): for x in iterable: yield x +def clean_asynciter(test): + @wraps(test) + async def wrapper(*args, **kwargs): + cleanups = [] + def wrapped_asynciter(iterable): + it = asynciter(iterable) + cleanups.append(it.aclose) + return it + try: + return await test(*args, **kwargs, asynciter=wrapped_asynciter) + finally: + while cleanups: + await cleanups.pop()() + return wrapper # A very basic example. If this fails, we're in deep trouble. def basic(): @@ -302,6 +326,13 @@ def generator_example(): [(5, 'line'), (5, 'return')]) +def lineno_matches_lasti(frame): + last_line = None + for start, end, line in frame.f_code.co_lines(): + if start <= frame.f_lasti < end: + last_line = line + return last_line == frame.f_lineno + class Tracer: def __init__(self, trace_line_events=None, trace_opcode_events=None): self.trace_line_events = trace_line_events @@ -315,6 +346,7 @@ def _reconfigure_frame(self, frame): frame.f_trace_opcodes = self.trace_opcode_events def trace(self, frame, event, arg): + assert lineno_matches_lasti(frame) self._reconfigure_frame(frame) self.events.append((frame.f_lineno, event)) return self.trace @@ -906,6 +938,35 @@ def func(): (6, 'line'), (6, 'return')]) + def test_finally_with_conditional(self): + + # See gh-105658 + condition = True + def func(): + try: + try: + raise Exception + finally: + if condition: + result = 1 + result = 2 + except: + result = 3 + return result + + self.run_and_compare(func, + [(0, 'call'), + (1, 'line'), + (2, 'line'), + (3, 'line'), + (3, 'exception'), + (5, 'line'), + (6, 'line'), + (8, 'line'), + (9, 'line'), + (10, 'line'), + (10, 'return')]) + def test_break_to_continue1(self): def func(): @@ -1653,7 +1714,6 @@ def error_once(frame, event, arg): except Exception as ex: count = 0 tb = ex.__traceback__ - print(tb) while tb: if tb.tb_frame.f_code.co_name == "test_settrace_error": count += 1 @@ -1750,6 +1810,39 @@ def compare_events(self, line_offset, events, expected_events): def make_tracer(): return Tracer(trace_opcode_events=True) + def test_trace_opcodes_after_settrace(self): + """Make sure setting f_trace_opcodes after starting trace works even + if it's the first time f_trace_opcodes is being set. GH-103615""" + + code = textwrap.dedent(""" + import sys + + def opcode_trace_func(frame, event, arg): + if event == "opcode": + print("opcode trace triggered") + return opcode_trace_func + + sys.settrace(opcode_trace_func) + sys._getframe().f_trace = opcode_trace_func + sys._getframe().f_trace_opcodes = True + a = 1 + """) + + # We can't use context manager because Windows can't execute a file while + # it's being written + tmp = tempfile.NamedTemporaryFile(delete=False, suffix='.py') + tmp.write(code.encode('utf-8')) + tmp.close() + try: + p = subprocess.Popen([sys.executable, tmp.name], stdout=subprocess.PIPE, stderr=subprocess.PIPE) + p.wait() + out = p.stdout.read() + finally: + os.remove(tmp.name) + p.stdout.close() + p.stderr.close() + self.assertIn(b"opcode trace triggered", out) + class RaisingTraceFuncTestCase(unittest.TestCase): def setUp(self): @@ -1876,6 +1969,7 @@ def __init__(self, function, jumpFrom, jumpTo, event='line', def trace(self, frame, event, arg): if self.done: return + assert lineno_matches_lasti(frame) # frame.f_code.co_firstlineno is the first line of the decorator when # 'function' is decorated and the decorator may be written using # multiple physical lines when it is too long. Use the first line @@ -1922,6 +2016,8 @@ def no_jump_without_trace_function(): class JumpTestCase(unittest.TestCase): + unbound_locals = r"assigning None to [0-9]+ unbound local" + def setUp(self): self.addCleanup(sys.settrace, sys.gettrace()) sys.settrace(None) @@ -1933,33 +2029,50 @@ def compare_jump_output(self, expected, received): "Received: " + repr(received)) def run_test(self, func, jumpFrom, jumpTo, expected, error=None, - event='line', decorated=False): - tracer = JumpTracer(func, jumpFrom, jumpTo, event, decorated) + event='line', decorated=False, warning=None): + wrapped = func + while hasattr(wrapped, '__wrapped__'): + wrapped = wrapped.__wrapped__ + + tracer = JumpTracer(wrapped, jumpFrom, jumpTo, event, decorated) sys.settrace(tracer.trace) output = [] - if error is None: + + with contextlib.ExitStack() as stack: + if error is not None: + stack.enter_context(self.assertRaisesRegex(*error)) + if warning is not None: + stack.enter_context(self.assertWarnsRegex(*warning)) + else: + stack.enter_context(warnings.catch_warnings()) + warnings.simplefilter('error') func(output) - else: - with self.assertRaisesRegex(*error): - func(output) + sys.settrace(None) self.compare_jump_output(expected, output) def run_async_test(self, func, jumpFrom, jumpTo, expected, error=None, - event='line', decorated=False): - tracer = JumpTracer(func, jumpFrom, jumpTo, event, decorated) + event='line', decorated=False, warning=None): + wrapped = func + while hasattr(wrapped, '__wrapped__'): + wrapped = wrapped.__wrapped__ + + tracer = JumpTracer(wrapped, jumpFrom, jumpTo, event, decorated) sys.settrace(tracer.trace) output = [] - if error is None: + + with contextlib.ExitStack() as stack: + if error is not None: + stack.enter_context(self.assertRaisesRegex(*error)) + if warning is not None: + stack.enter_context(self.assertWarnsRegex(*warning)) asyncio.run(func(output)) - else: - with self.assertRaisesRegex(*error): - asyncio.run(func(output)) + sys.settrace(None) asyncio.set_event_loop_policy(None) self.compare_jump_output(expected, output) - def jump_test(jumpFrom, jumpTo, expected, error=None, event='line'): + def jump_test(jumpFrom, jumpTo, expected, error=None, event='line', warning=None): """Decorator that creates a test that makes a jump from one place to another in the following code. """ @@ -1967,11 +2080,11 @@ def decorator(func): @wraps(func) def test(self): self.run_test(func, jumpFrom, jumpTo, expected, - error=error, event=event, decorated=True) + error=error, event=event, decorated=True, warning=warning) return test return decorator - def async_jump_test(jumpFrom, jumpTo, expected, error=None, event='line'): + def async_jump_test(jumpFrom, jumpTo, expected, error=None, event='line', warning=None): """Decorator that creates a test that makes a jump from one place to another in the following asynchronous code. """ @@ -1979,7 +2092,7 @@ def decorator(func): @wraps(func) def test(self): self.run_async_test(func, jumpFrom, jumpTo, expected, - error=error, event=event, decorated=True) + error=error, event=event, decorated=True, warning=warning) return test return decorator @@ -1996,7 +2109,41 @@ def test_jump_simple_backwards(output): output.append(1) output.append(2) - @jump_test(3, 5, [2, 5]) + @jump_test(1, 4, [5], warning=(RuntimeWarning, unbound_locals)) + def test_jump_is_none_forwards(output): + x = None + if x is None: + output.append(3) + else: + output.append(5) + + @jump_test(6, 5, [3, 5, 6]) + def test_jump_is_none_backwards(output): + x = None + if x is None: + output.append(3) + else: + output.append(5) + output.append(6) + + @jump_test(2, 4, [5]) + def test_jump_is_not_none_forwards(output): + x = None + if x is not None: + output.append(3) + else: + output.append(5) + + @jump_test(6, 5, [5, 5, 6]) + def test_jump_is_not_none_backwards(output): + x = None + if x is not None: + output.append(3) + else: + output.append(5) + output.append(6) + + @jump_test(3, 5, [2, 5], warning=(RuntimeWarning, unbound_locals)) def test_jump_out_of_block_forwards(output): for i in 1, 2: output.append(2) @@ -2015,7 +2162,8 @@ def test_jump_out_of_block_backwards(output): output.append(7) @async_jump_test(4, 5, [3, 5]) - async def test_jump_out_of_async_for_block_forwards(output): + @clean_asynciter + async def test_jump_out_of_async_for_block_forwards(output, asynciter): for i in [1]: async for i in asynciter([1, 2]): output.append(3) @@ -2023,7 +2171,8 @@ async def test_jump_out_of_async_for_block_forwards(output): output.append(5) @async_jump_test(5, 2, [2, 4, 2, 4, 5, 6]) - async def test_jump_out_of_async_for_block_backwards(output): + @clean_asynciter + async def test_jump_out_of_async_for_block_backwards(output, asynciter): for i in [1]: output.append(2) async for i in asynciter([1]): @@ -2082,7 +2231,7 @@ def test_jump_in_nested_finally_3(output): output.append(11) output.append(12) - @jump_test(5, 11, [2, 4], (ValueError, 'exception')) + @jump_test(5, 11, [2, 4], (ValueError, 'comes after the current code block')) def test_no_jump_over_return_try_finally_in_finally_block(output): try: output.append(2) @@ -2210,7 +2359,7 @@ def test_jump_within_except_block(output): output.append(6) output.append(7) - @jump_test(6, 1, [1, 5, 1, 5]) + @jump_test(6, 1, [1, 5, 1, 5], warning=(RuntimeWarning, unbound_locals)) def test_jump_over_try_except(output): output.append(1) try: @@ -2306,7 +2455,7 @@ def test_jump_out_of_complex_nested_blocks(output): output.append(11) output.append(12) - @jump_test(3, 5, [1, 2, 5]) + @jump_test(3, 5, [1, 2, 5], warning=(RuntimeWarning, unbound_locals)) def test_jump_out_of_with_assignment(output): output.append(1) with tracecontext(output, 2) \ @@ -2314,7 +2463,7 @@ def test_jump_out_of_with_assignment(output): output.append(4) output.append(5) - @async_jump_test(3, 5, [1, 2, 5]) + @async_jump_test(3, 5, [1, 2, 5], warning=(RuntimeWarning, unbound_locals)) async def test_jump_out_of_async_with_assignment(output): output.append(1) async with asynctracecontext(output, 2) \ @@ -2350,7 +2499,7 @@ def test_jump_over_break_in_try_finally_block(output): break output.append(13) - @jump_test(1, 7, [7, 8]) + @jump_test(1, 7, [7, 8], warning=(RuntimeWarning, unbound_locals)) def test_jump_over_for_block_before_else(output): output.append(1) if not output: # always false @@ -2361,7 +2510,7 @@ def test_jump_over_for_block_before_else(output): output.append(7) output.append(8) - @async_jump_test(1, 7, [7, 8]) + @async_jump_test(1, 7, [7, 8], warning=(RuntimeWarning, unbound_locals)) async def test_jump_over_async_for_block_before_else(output): output.append(1) if not output: # always false @@ -2436,6 +2585,7 @@ def test_no_jump_backwards_into_for_block(output): output.append(2) output.append(3) + @async_jump_test(3, 2, [2, 2], (ValueError, "can't jump into the body of a for loop")) async def test_no_jump_backwards_into_async_for_block(output): async for i in asynciter([1, 2]): @@ -2501,7 +2651,7 @@ def test_jump_backwards_into_try_except_block(output): output.append(6) # 'except' with a variable creates an implicit finally block - @jump_test(5, 7, [4, 7, 8]) + @jump_test(5, 7, [4, 7, 8], warning=(RuntimeWarning, unbound_locals)) def test_jump_between_except_blocks_2(output): try: 1/0 @@ -2664,7 +2814,7 @@ def test_large_function(self): output.append(x) # line 1007 return""" % ('\n' * 1000,), d) f = d['f'] - self.run_test(f, 2, 1007, [0]) + self.run_test(f, 2, 1007, [0], warning=(RuntimeWarning, self.unbound_locals)) def test_jump_to_firstlineno(self): # This tests that PDB can jump back to the first line in a @@ -2714,7 +2864,7 @@ def gen(): next(gen()) output.append(5) - @jump_test(2, 3, [1, 3]) + @jump_test(2, 3, [1, 3], warning=(RuntimeWarning, unbound_locals)) def test_jump_forward_over_listcomp(output): output.append(1) x = [i for i in range(10)] @@ -2722,13 +2872,13 @@ def test_jump_forward_over_listcomp(output): # checking for segfaults. # See https://github.com/python/cpython/issues/92311 - @jump_test(3, 1, []) + @jump_test(3, 1, [], warning=(RuntimeWarning, unbound_locals)) def test_jump_backward_over_listcomp(output): a = 1 x = [i for i in range(10)] c = 3 - @jump_test(8, 2, [2, 7, 2]) + @jump_test(8, 2, [2, 7, 2], warning=(RuntimeWarning, unbound_locals)) def test_jump_backward_over_listcomp_v2(output): flag = False output.append(2) @@ -2739,19 +2889,19 @@ def test_jump_backward_over_listcomp_v2(output): output.append(7) output.append(8) - @async_jump_test(2, 3, [1, 3]) + @async_jump_test(2, 3, [1, 3], warning=(RuntimeWarning, unbound_locals)) async def test_jump_forward_over_async_listcomp(output): output.append(1) x = [i async for i in asynciter(range(10))] output.append(3) - @async_jump_test(3, 1, []) + @async_jump_test(3, 1, [], warning=(RuntimeWarning, unbound_locals)) async def test_jump_backward_over_async_listcomp(output): a = 1 x = [i async for i in asynciter(range(10))] c = 3 - @async_jump_test(8, 2, [2, 7, 2]) + @async_jump_test(8, 2, [2, 7, 2], warning=(RuntimeWarning, unbound_locals)) async def test_jump_backward_over_async_listcomp_v2(output): flag = False output.append(2) @@ -2820,13 +2970,13 @@ def test_jump_with_null_on_stack_load_attr(output): ) output.append(15) - @jump_test(2, 3, [1, 3]) + @jump_test(2, 3, [1, 3], warning=(RuntimeWarning, unbound_locals)) def test_jump_extended_args_unpack_ex_simple(output): output.append(1) _, *_, _ = output.append(2) or "Spam" output.append(3) - @jump_test(3, 4, [1, 4, 4, 5]) + @jump_test(3, 4, [1, 4, 4, 5], warning=(RuntimeWarning, unbound_locals)) def test_jump_extended_args_unpack_ex_tricky(output): output.append(1) ( @@ -2834,6 +2984,7 @@ def test_jump_extended_args_unpack_ex_tricky(output): ) = output.append(4) or "Spam" output.append(5) + @support.requires_resource('cpu') def test_jump_extended_args_for_iter(self): # In addition to failing when extended arg handling is broken, this can # also hang for a *very* long time: @@ -2847,9 +2998,9 @@ def test_jump_extended_args_for_iter(self): namespace = {} exec("\n".join(source), namespace) f = namespace["f"] - self.run_test(f, 2, 100_000, [1, 100_000]) + self.run_test(f, 2, 100_000, [1, 100_000], warning=(RuntimeWarning, self.unbound_locals)) - @jump_test(2, 3, [1, 3]) + @jump_test(2, 3, [1, 3], warning=(RuntimeWarning, unbound_locals)) def test_jump_or_pop(output): output.append(1) _ = output.append(2) and "Spam" @@ -2886,16 +3037,21 @@ def test_trace_unpack_long_sequence(self): self.assertEqual(counts, {'call': 1, 'line': 301, 'return': 1}) def test_trace_lots_of_globals(self): + count = 1000 + if _testinternalcapi is not None: + remaining = _testinternalcapi.get_c_recursion_remaining() + count = min(count, remaining) + code = """if 1: def f(): return ( {} ) - """.format("\n+\n".join(f"var{i}\n" for i in range(1000))) - ns = {f"var{i}": i for i in range(1000)} + """.format("\n+\n".join(f"var{i}\n" for i in range(count))) + ns = {f"var{i}": i for i in range(count)} exec(code, ns) counts = self.count_traces(ns["f"]) - self.assertEqual(counts, {'call': 1, 'line': 2000, 'return': 1}) + self.assertEqual(counts, {'call': 1, 'line': count * 2, 'return': 1}) class TestEdgeCases(unittest.TestCase): diff --git a/Lib/test/test_sysconfig.py b/Lib/test/test_sysconfig.py index b6dbf3d52cb4c3..be609a0abd29c8 100644 --- a/Lib/test/test_sysconfig.py +++ b/Lib/test/test_sysconfig.py @@ -16,8 +16,11 @@ from sysconfig import (get_paths, get_platform, get_config_vars, get_path, get_path_names, _INSTALL_SCHEMES, get_default_scheme, get_scheme_names, get_config_var, - _expand_vars, _get_preferred_schemes, _main) + _expand_vars, _get_preferred_schemes) +from sysconfig.__main__ import _main, _parse_makefile +import _imp import _osx_support +import _sysconfig HAS_USER_BASE = sysconfig._HAS_USER_BASE @@ -40,6 +43,7 @@ def setUp(self): self.name = os.name self.platform = sys.platform self.version = sys.version + self._framework = sys._framework self.sep = os.sep self.join = os.path.join self.isabs = os.path.isabs @@ -63,6 +67,7 @@ def tearDown(self): os.name = self.name sys.platform = self.platform sys.version = self.version + sys._framework = self._framework os.sep = self.sep os.path.join = self.join os.path.isabs = self.isabs @@ -136,7 +141,7 @@ def test_get_preferred_schemes(self): # Mac, framework build. os.name = 'posix' sys.platform = 'darwin' - sys._framework = True + sys._framework = "MyPython" self.assertIsInstance(schemes, dict) self.assertEqual(set(schemes), expected_schemes) @@ -394,6 +399,27 @@ def test_ldshared_value(self): self.assertIn(ldflags, ldshared) + @unittest.skipIf(not _imp.extension_suffixes(), "stub loader has no suffixes") + def test_soabi(self): + soabi = sysconfig.get_config_var('SOABI') + self.assertIn(soabi, _imp.extension_suffixes()[0]) + + def test_library(self): + library = sysconfig.get_config_var('LIBRARY') + ldlibrary = sysconfig.get_config_var('LDLIBRARY') + major, minor = sys.version_info[:2] + if sys.platform == 'win32': + self.assertTrue(library.startswith(f'python{major}{minor}')) + self.assertTrue(library.endswith('.dll')) + self.assertEqual(library, ldlibrary) + else: + self.assertTrue(library.startswith(f'libpython{major}.{minor}')) + self.assertTrue(library.endswith('.a')) + if sys.platform == 'darwin' and sys._framework: + self.skipTest('gh-110824: skip LDLIBRARY test for framework build') + else: + self.assertTrue(ldlibrary.startswith(f'libpython{major}.{minor}')) + @unittest.skipUnless(sys.platform == "darwin", "test only relevant on MacOSX") @requires_subprocess() def test_platform_in_subprocess(self): @@ -451,11 +477,15 @@ def test_srcdir(self): # should be a full source checkout. Python_h = os.path.join(srcdir, 'Include', 'Python.h') self.assertTrue(os.path.exists(Python_h), Python_h) - # /PC/pyconfig.h always exists even if unused on POSIX. - pyconfig_h = os.path.join(srcdir, 'PC', 'pyconfig.h') + # /PC/pyconfig.h.in always exists even if unused + pyconfig_h = os.path.join(srcdir, 'PC', 'pyconfig.h.in') self.assertTrue(os.path.exists(pyconfig_h), pyconfig_h) pyconfig_h_in = os.path.join(srcdir, 'pyconfig.h.in') self.assertTrue(os.path.exists(pyconfig_h_in), pyconfig_h_in) + if os.name == 'nt': + # /pyconfig.h exists on Windows in a build tree + pyconfig_h = os.path.join(sys.executable, '..', 'pyconfig.h') + self.assertTrue(os.path.exists(pyconfig_h), pyconfig_h) elif os.name == 'posix': makefile_dir = os.path.dirname(sysconfig.get_makefile_filename()) # Issue #19340: srcdir has been realpath'ed already @@ -472,10 +502,8 @@ def test_srcdir_independent_of_cwd(self): @unittest.skipIf(sysconfig.get_config_var('EXT_SUFFIX') is None, 'EXT_SUFFIX required for this test') + @unittest.skipIf(not _imp.extension_suffixes(), "stub loader has no suffixes") def test_EXT_SUFFIX_in_vars(self): - import _imp - if not _imp.extension_suffixes(): - self.skipTest("stub loader has no suffixes") vars = sysconfig.get_config_vars() self.assertEqual(vars['EXT_SUFFIX'], _imp.extension_suffixes()[0]) @@ -521,7 +549,7 @@ def test_parse_makefile(self): print("var5=dollar$$5", file=makefile) print("var6=${var3}/lib/python3.5/config-$(VAR2)$(var5)" "-x86_64-linux-gnu", file=makefile) - vars = sysconfig._parse_makefile(TESTFN) + vars = _parse_makefile(TESTFN) self.assertEqual(vars, { 'var1': 'ab42', 'VAR2': 'b42', diff --git a/Lib/test/test_tarfile.py b/Lib/test/test_tarfile.py index 2eda7fc4ceac71..da5009126b3815 100644 --- a/Lib/test/test_tarfile.py +++ b/Lib/test/test_tarfile.py @@ -1,3 +1,4 @@ +import errno import sys import os import io @@ -42,7 +43,7 @@ def sha256sum(data): TEMPDIR = os.path.abspath(os_helper.TESTFN) + "-tardir" tarextdir = TEMPDIR + '-extract-test' -tarname = support.findfile("testtar.tar") +tarname = support.findfile("testtar.tar", subdir="archivetestdata") gzipname = os.path.join(TEMPDIR, "testtar.tar.gz") bz2name = os.path.join(TEMPDIR, "testtar.tar.bz2") xzname = os.path.join(TEMPDIR, "testtar.tar.xz") @@ -322,11 +323,23 @@ def test_list_verbose(self): # accessories if verbose flag is being used # ... # ?rw-r--r-- tarfile/tarfile 7011 2003-01-06 07:19:43 ustar/conttype - # ?rw-r--r-- tarfile/tarfile 7011 2003-01-06 07:19:43 ustar/regtype + # -rw-r--r-- tarfile/tarfile 7011 2003-01-06 07:19:43 ustar/regtype + # drwxr-xr-x tarfile/tarfile 0 2003-01-05 15:19:43 ustar/dirtype/ # ... - self.assertRegex(out, (br'\?rw-r--r-- tarfile/tarfile\s+7011 ' - br'\d{4}-\d\d-\d\d\s+\d\d:\d\d:\d\d ' - br'ustar/\w+type ?\r?\n') * 2) + # + # Array of values to modify the regex below: + # ((file_type, file_permissions, file_length), ...) + type_perm_lengths = ( + (br'\?', b'rw-r--r--', b'7011'), (b'-', b'rw-r--r--', b'7011'), + (b'd', b'rwxr-xr-x', b'0'), (b'd', b'rwxr-xr-x', b'255'), + (br'\?', b'rw-r--r--', b'0'), (b'l', b'rwxrwxrwx', b'0'), + (b'b', b'rw-rw----', b'3,0'), (b'c', b'rw-rw-rw-', b'1,3'), + (b'p', b'rw-r--r--', b'0')) + self.assertRegex(out, b''.join( + [(tp + (br'%s tarfile/tarfile\s+%s ' % (perm, ln) + + br'\d{4}-\d\d-\d\d\s+\d\d:\d\d:\d\d ' + br'ustar/\w+type[/>\sa-z-]*\n')) for tp, perm, ln + in type_perm_lengths])) # Make sure it prints the source of link with verbose flag self.assertIn(b'ustar/symtype -> regtype', out) self.assertIn(b'./ustar/linktest2/symtype -> ../linktest1/regtype', out) @@ -490,7 +503,7 @@ def test_length_zero_header(self): # bpo-39017 (CVE-2019-20907): reading a zero-length header should fail # with an exception with self.assertRaisesRegex(tarfile.ReadError, "file could not be opened successfully"): - with tarfile.open(support.findfile('recursion.tar')) as tar: + with tarfile.open(support.findfile('recursion.tar', subdir='archivetestdata')): pass def test_extractfile_name(self): @@ -938,6 +951,23 @@ class LzmaDetectReadTest(LzmaTest, DetectReadTest): pass +class GzipBrokenHeaderCorrectException(GzipTest, unittest.TestCase): + """ + See: https://github.com/python/cpython/issues/107396 + """ + def runTest(self): + f = io.BytesIO( + b'\x1f\x8b' # header + b'\x08' # compression method + b'\x04' # flags + b'\0\0\0\0\0\0' # timestamp, compression data, OS ID + b'\0\x01' # size + b'\0\0\0\0\0' # corrupt data (zeros) + ) + with self.assertRaises(tarfile.ReadError): + tarfile.open(fileobj=f, mode='r|gz') + + class MemberReadTest(ReadTest, unittest.TestCase): def _test_member(self, tarinfo, chksum=None, **kwargs): @@ -2547,7 +2577,7 @@ def test__all__(self): support.check__all__(self, tarfile, not_exported=not_exported) def test_useful_error_message_when_modules_missing(self): - fname = os.path.join(os.path.dirname(__file__), 'testtar.tar.xz') + fname = os.path.join(os.path.dirname(__file__), 'archivetestdata', 'testtar.tar.xz') with self.assertRaises(tarfile.ReadError) as excinfo: error = tarfile.CompressionError('lzma module is not available'), with unittest.mock.patch.object(tarfile.TarFile, 'xzopen', side_effect=error): @@ -2570,16 +2600,17 @@ def tarfilecmd_failure(self, *args): return script_helper.assert_python_failure('-m', 'tarfile', *args) def make_simple_tarfile(self, tar_name): - files = [support.findfile('tokenize_tests.txt'), + files = [support.findfile('tokenize_tests.txt', + subdir='tokenizedata'), support.findfile('tokenize_tests-no-coding-cookie-' - 'and-utf8-bom-sig-only.txt')] + 'and-utf8-bom-sig-only.txt', + subdir='tokenizedata')] self.addCleanup(os_helper.unlink, tar_name) with tarfile.open(tar_name, 'w') as tf: for tardata in files: tf.add(tardata, arcname=os.path.basename(tardata)) def make_evil_tarfile(self, tar_name): - files = [support.findfile('tokenize_tests.txt')] self.addCleanup(os_helper.unlink, tar_name) with tarfile.open(tar_name, 'w') as tf: benign = tarfile.TarInfo('benign') @@ -2611,7 +2642,7 @@ def test_test_command_verbose(self): self.assertIn(b'is a tar archive.\n', out) def test_test_command_invalid_file(self): - zipname = support.findfile('zipdir.zip') + zipname = support.findfile('zipdir.zip', subdir='archivetestdata') rc, out, err = self.tarfilecmd_failure('-t', zipname) self.assertIn(b' is not a tar archive.', err) self.assertEqual(out, b'') @@ -2653,16 +2684,18 @@ def test_list_command_verbose(self): self.assertEqual(out, expected) def test_list_command_invalid_file(self): - zipname = support.findfile('zipdir.zip') + zipname = support.findfile('zipdir.zip', subdir='archivetestdata') rc, out, err = self.tarfilecmd_failure('-l', zipname) self.assertIn(b' is not a tar archive.', err) self.assertEqual(out, b'') self.assertEqual(rc, 1) def test_create_command(self): - files = [support.findfile('tokenize_tests.txt'), + files = [support.findfile('tokenize_tests.txt', + subdir='tokenizedata'), support.findfile('tokenize_tests-no-coding-cookie-' - 'and-utf8-bom-sig-only.txt')] + 'and-utf8-bom-sig-only.txt', + subdir='tokenizedata')] for opt in '-c', '--create': try: out = self.tarfilecmd(opt, tmpname, *files) @@ -2673,9 +2706,11 @@ def test_create_command(self): os_helper.unlink(tmpname) def test_create_command_verbose(self): - files = [support.findfile('tokenize_tests.txt'), + files = [support.findfile('tokenize_tests.txt', + subdir='tokenizedata'), support.findfile('tokenize_tests-no-coding-cookie-' - 'and-utf8-bom-sig-only.txt')] + 'and-utf8-bom-sig-only.txt', + subdir='tokenizedata')] for opt in '-v', '--verbose': try: out = self.tarfilecmd(opt, '-c', tmpname, *files, @@ -2687,7 +2722,7 @@ def test_create_command_verbose(self): os_helper.unlink(tmpname) def test_create_command_dotless_filename(self): - files = [support.findfile('tokenize_tests.txt')] + files = [support.findfile('tokenize_tests.txt', subdir='tokenizedata')] try: out = self.tarfilecmd('-c', dotlessname, *files) self.assertEqual(out, b'') @@ -2698,7 +2733,7 @@ def test_create_command_dotless_filename(self): def test_create_command_dot_started_filename(self): tar_name = os.path.join(TEMPDIR, ".testtar") - files = [support.findfile('tokenize_tests.txt')] + files = [support.findfile('tokenize_tests.txt', subdir='tokenizedata')] try: out = self.tarfilecmd('-c', tar_name, *files) self.assertEqual(out, b'') @@ -2708,9 +2743,11 @@ def test_create_command_dot_started_filename(self): os_helper.unlink(tar_name) def test_create_command_compressed(self): - files = [support.findfile('tokenize_tests.txt'), + files = [support.findfile('tokenize_tests.txt', + subdir='tokenizedata'), support.findfile('tokenize_tests-no-coding-cookie-' - 'and-utf8-bom-sig-only.txt')] + 'and-utf8-bom-sig-only.txt', + subdir='tokenizedata')] for filetype in (GzipTest, Bz2Test, LzmaTest): if not filetype.open: continue @@ -2772,7 +2809,7 @@ def test_extract_command_different_directory(self): os_helper.rmtree(tarextdir) def test_extract_command_invalid_file(self): - zipname = support.findfile('zipdir.zip') + zipname = support.findfile('zipdir.zip', subdir='archivetestdata') with os_helper.temp_cwd(tarextdir): rc, out, err = self.tarfilecmd_failure('-e', zipname) self.assertIn(b' is not a tar archive.', err) @@ -3337,10 +3374,12 @@ def __exit__(self, *exc): self.bio = None def add(self, name, *, type=None, symlink_to=None, hardlink_to=None, - mode=None, **kwargs): + mode=None, size=None, **kwargs): """Add a member to the test archive. Call within `with`.""" name = str(name) tarinfo = tarfile.TarInfo(name).replace(**kwargs) + if size is not None: + tarinfo.size = size if mode: tarinfo.mode = _filemode_to_int(mode) if symlink_to is not None: @@ -3416,7 +3455,8 @@ def check_context(self, tar, filter): raise self.raised_exception self.assertEqual(self.expected_paths, set()) - def expect_file(self, name, type=None, symlink_to=None, mode=None): + def expect_file(self, name, type=None, symlink_to=None, mode=None, + size=None): """Check a single file. See check_context.""" if self.raised_exception: raise self.raised_exception @@ -3424,7 +3464,7 @@ def expect_file(self, name, type=None, symlink_to=None, mode=None): path = pathlib.Path(os.path.normpath(self.destdir / name)) self.assertIn(path, self.expected_paths) self.expected_paths.remove(path) - if mode is not None and os_helper.can_chmod(): + if mode is not None and os_helper.can_chmod() and os.name != 'nt': got = stat.filemode(stat.S_IMODE(path.stat().st_mode)) self.assertEqual(got, mode) if type is None and isinstance(name, str) and name.endswith('/'): @@ -3445,6 +3485,8 @@ def expect_file(self, name, type=None, symlink_to=None, mode=None): self.assertTrue(path.is_fifo()) else: raise NotImplementedError(type) + if size is not None: + self.assertEqual(path.stat().st_size, size) for parent in path.parents: self.expected_paths.discard(parent) @@ -3491,8 +3533,15 @@ def test_parent_symlink(self): # Test interplaying symlinks # Inspired by 'dirsymlink2a' in jwilk/traversal-archives with ArchiveMaker() as arc: + + # `current` links to `.` which is both: + # - the destination directory + # - `current` itself arc.add('current', symlink_to='.') + + # effectively points to ./../ arc.add('parent', symlink_to='current/..') + arc.add('parent/evil') if os_helper.can_symlink(): @@ -3534,9 +3583,46 @@ def test_parent_symlink(self): def test_parent_symlink2(self): # Test interplaying symlinks # Inspired by 'dirsymlink2b' in jwilk/traversal-archives + + # Posix and Windows have different pathname resolution: + # either symlink or a '..' component resolve first. + # Let's see which we are on. + if os_helper.can_symlink(): + testpath = os.path.join(TEMPDIR, 'resolution_test') + os.mkdir(testpath) + + # testpath/current links to `.` which is all of: + # - `testpath` + # - `testpath/current` + # - `testpath/current/current` + # - etc. + os.symlink('.', os.path.join(testpath, 'current')) + + # we'll test where `testpath/current/../file` ends up + with open(os.path.join(testpath, 'current', '..', 'file'), 'w'): + pass + + if os.path.exists(os.path.join(testpath, 'file')): + # Windows collapses 'current\..' to '.' first, leaving + # 'testpath\file' + dotdot_resolves_early = True + elif os.path.exists(os.path.join(testpath, '..', 'file')): + # Posix resolves 'current' to '.' first, leaving + # 'testpath/../file' + dotdot_resolves_early = False + else: + raise AssertionError('Could not determine link resolution') + with ArchiveMaker() as arc: + + # `current` links to `.` which is both the destination directory + # and `current` itself arc.add('current', symlink_to='.') + + # `current/parent` is also available as `./parent`, + # and effectively points to `./../` arc.add('current/parent', symlink_to='..') + arc.add('parent/evil') with self.check_context(arc.open(), 'fully_trusted'): @@ -3550,6 +3636,7 @@ def test_parent_symlink2(self): with self.check_context(arc.open(), 'tar'): if os_helper.can_symlink(): + # Fail when extracting a file outside destination self.expect_exception( tarfile.OutsideDestinationError, "'parent/evil' would be extracted to " @@ -3560,10 +3647,24 @@ def test_parent_symlink2(self): self.expect_file('parent/evil') with self.check_context(arc.open(), 'data'): - self.expect_exception( - tarfile.LinkOutsideDestinationError, - """'current/parent' would link to ['"].*['"], """ - + "which is outside the destination") + if os_helper.can_symlink(): + if dotdot_resolves_early: + # Fail when extracting a file outside destination + self.expect_exception( + tarfile.OutsideDestinationError, + "'parent/evil' would be extracted to " + + """['"].*evil['"], which is outside """ + + "the destination") + else: + # Fail as soon as we have a symlink outside the destination + self.expect_exception( + tarfile.LinkOutsideDestinationError, + "'current/parent' would link to " + + """['"].*outerdir['"], which is outside """ + + "the destination") + else: + self.expect_file('current/') + self.expect_file('parent/evil') @symlink_test def test_absolute_symlink(self): @@ -3593,12 +3694,30 @@ def test_absolute_symlink(self): with self.check_context(arc.open(), 'data'): self.expect_exception( tarfile.AbsoluteLinkError, - "'parent' is a symlink to an absolute path") + "'parent' is a link to an absolute path") + + def test_absolute_hardlink(self): + # Test hardlink to an absolute path + # Inspired by 'dirsymlink' in https://github.com/jwilk/traversal-archives + with ArchiveMaker() as arc: + arc.add('parent', hardlink_to=self.outerdir / 'foo') + + with self.check_context(arc.open(), 'fully_trusted'): + self.expect_exception(KeyError, ".*foo. not found") + + with self.check_context(arc.open(), 'tar'): + self.expect_exception(KeyError, ".*foo. not found") + + with self.check_context(arc.open(), 'data'): + self.expect_exception( + tarfile.AbsoluteLinkError, + "'parent' is a link to an absolute path") @symlink_test def test_sly_relative0(self): # Inspired by 'relative0' in jwilk/traversal-archives with ArchiveMaker() as arc: + # points to `../../tmp/moo` arc.add('../moo', symlink_to='..//tmp/moo') try: @@ -3649,6 +3768,56 @@ def test_sly_relative2(self): + """['"].*moo['"], which is outside the """ + "destination") + @symlink_test + def test_deep_symlink(self): + # Test that symlinks and hardlinks inside a directory + # point to the correct file (`target` of size 3). + # If links aren't supported we get a copy of the file. + with ArchiveMaker() as arc: + arc.add('targetdir/target', size=3) + # a hardlink's linkname is relative to the archive + arc.add('linkdir/hardlink', hardlink_to=os.path.join( + 'targetdir', 'target')) + # a symlink's linkname is relative to the link's directory + arc.add('linkdir/symlink', symlink_to=os.path.join( + '..', 'targetdir', 'target')) + + for filter in 'tar', 'data', 'fully_trusted': + with self.check_context(arc.open(), filter): + self.expect_file('targetdir/target', size=3) + self.expect_file('linkdir/hardlink', size=3) + if os_helper.can_symlink(): + self.expect_file('linkdir/symlink', size=3, + symlink_to='../targetdir/target') + else: + self.expect_file('linkdir/symlink', size=3) + + @symlink_test + def test_chains(self): + # Test chaining of symlinks/hardlinks. + # Symlinks are created before the files they point to. + with ArchiveMaker() as arc: + arc.add('linkdir/symlink', symlink_to='hardlink') + arc.add('symlink2', symlink_to=os.path.join( + 'linkdir', 'hardlink2')) + arc.add('targetdir/target', size=3) + arc.add('linkdir/hardlink', hardlink_to='targetdir/target') + arc.add('linkdir/hardlink2', hardlink_to='linkdir/symlink') + + for filter in 'tar', 'data', 'fully_trusted': + with self.check_context(arc.open(), filter): + self.expect_file('targetdir/target', size=3) + self.expect_file('linkdir/hardlink', size=3) + self.expect_file('linkdir/hardlink2', size=3) + if os_helper.can_symlink(): + self.expect_file('linkdir/symlink', size=3, + symlink_to='hardlink') + self.expect_file('symlink2', size=3, + symlink_to='linkdir/hardlink2') + else: + self.expect_file('linkdir/symlink', size=3) + self.expect_file('symlink2', size=3) + def test_modes(self): # Test how file modes are extracted # (Note that the modes are ignored on platforms without working chmod) @@ -3659,34 +3828,55 @@ def test_modes(self): arc.add('read_group_only', mode='?---r-----') arc.add('no_bits', mode='?---------') arc.add('dir/', mode='?---rwsrwt') + arc.add('dir_all_bits/', mode='?rwsrwsrwt') - # On some systems, setting the sticky bit is a no-op. - # Check if that's the case. + # On some systems, setting the uid, gid, and/or sticky bit is a no-ops. + # Check which bits we can set, so we can compare tarfile machinery to + # a simple chmod. tmp_filename = os.path.join(TEMPDIR, "tmp.file") with open(tmp_filename, 'w'): pass - os.chmod(tmp_filename, os.stat(tmp_filename).st_mode | stat.S_ISVTX) - have_sticky_files = (os.stat(tmp_filename).st_mode & stat.S_ISVTX) - os.unlink(tmp_filename) + try: + new_mode = (os.stat(tmp_filename).st_mode + | stat.S_ISVTX | stat.S_ISGID | stat.S_ISUID) + try: + os.chmod(tmp_filename, new_mode) + except OSError as exc: + if exc.errno == getattr(errno, "EFTYPE", 0): + # gh-108948: On FreeBSD, regular users cannot set + # the sticky bit. + self.skipTest("chmod() failed with EFTYPE: " + "regular users cannot set sticky bit") + else: + raise + + got_mode = os.stat(tmp_filename).st_mode + _t_file = 't' if (got_mode & stat.S_ISVTX) else 'x' + _suid_file = 's' if (got_mode & stat.S_ISUID) else 'x' + _sgid_file = 's' if (got_mode & stat.S_ISGID) else 'x' + finally: + os.unlink(tmp_filename) os.mkdir(tmp_filename) - os.chmod(tmp_filename, os.stat(tmp_filename).st_mode | stat.S_ISVTX) - have_sticky_dirs = (os.stat(tmp_filename).st_mode & stat.S_ISVTX) + new_mode = (os.stat(tmp_filename).st_mode + | stat.S_ISVTX | stat.S_ISGID | stat.S_ISUID) + os.chmod(tmp_filename, new_mode) + got_mode = os.stat(tmp_filename).st_mode + _t_dir = 't' if (got_mode & stat.S_ISVTX) else 'x' + _suid_dir = 's' if (got_mode & stat.S_ISUID) else 'x' + _sgid_dir = 's' if (got_mode & stat.S_ISGID) else 'x' os.rmdir(tmp_filename) with self.check_context(arc.open(), 'fully_trusted'): - if have_sticky_files: - self.expect_file('all_bits', mode='?rwsrwsrwt') - else: - self.expect_file('all_bits', mode='?rwsrwsrwx') + self.expect_file('all_bits', + mode=f'?rw{_suid_file}rw{_sgid_file}rw{_t_file}') self.expect_file('perm_bits', mode='?rwxrwxrwx') self.expect_file('exec_group_other', mode='?rw-rwxrwx') self.expect_file('read_group_only', mode='?---r-----') self.expect_file('no_bits', mode='?---------') - if have_sticky_dirs: - self.expect_file('dir/', mode='?---rwsrwt') - else: - self.expect_file('dir/', mode='?---rwsrwx') + self.expect_file('dir/', mode=f'?---rw{_sgid_dir}rw{_t_dir}') + self.expect_file('dir_all_bits/', + mode=f'?rw{_suid_dir}rw{_sgid_dir}rw{_t_dir}') with self.check_context(arc.open(), 'tar'): self.expect_file('all_bits', mode='?rwxr-xr-x') @@ -3695,6 +3885,7 @@ def test_modes(self): self.expect_file('read_group_only', mode='?---r-----') self.expect_file('no_bits', mode='?---------') self.expect_file('dir/', mode='?---r-xr-x') + self.expect_file('dir_all_bits/', mode='?rwxr-xr-x') with self.check_context(arc.open(), 'data'): normal_dir_mode = stat.filemode(stat.S_IMODE( @@ -3705,6 +3896,7 @@ def test_modes(self): self.expect_file('read_group_only', mode='?rw-r-----') self.expect_file('no_bits', mode='?rw-------') self.expect_file('dir/', mode=normal_dir_mode) + self.expect_file('dir_all_bits/', mode=normal_dir_mode) def test_pipe(self): # Test handling of a special file diff --git a/Lib/test/test_tcl.py b/Lib/test/test_tcl.py index d07b83acb1b505..ebdb58f91d3d8a 100644 --- a/Lib/test/test_tcl.py +++ b/Lib/test/test_tcl.py @@ -20,14 +20,6 @@ tcl_version = tuple(map(int, _tkinter.TCL_VERSION.split('.'))) -_tk_patchlevel = None -def get_tk_patchlevel(): - global _tk_patchlevel - if _tk_patchlevel is None: - tcl = Tcl() - _tk_patchlevel = tcl.info_patchlevel() - return _tk_patchlevel - class TkinterTest(unittest.TestCase): @@ -571,7 +563,6 @@ def test_splitlist(self): (1, '2', (3.4,)) if self.wantobjects else ('1', '2', '3.4')), ] - tk_patchlevel = get_tk_patchlevel() if not self.wantobjects: expected = ('12', '\u20ac', '\xe2\x82\xac', '3.4') else: @@ -580,8 +571,8 @@ def test_splitlist(self): (call('dict', 'create', 12, '\u20ac', b'\xe2\x82\xac', (3.4,)), expected), ] - dbg_info = ('want objects? %s, Tcl version: %s, Tk patchlevel: %s' - % (self.wantobjects, tcl_version, tk_patchlevel)) + dbg_info = ('want objects? %s, Tcl version: %s, Tcl patchlevel: %s' + % (self.wantobjects, tcl_version, self.interp.info_patchlevel())) for arg, res in testcases: self.assertEqual(splitlist(arg), res, 'arg=%a, %s' % (arg, dbg_info)) diff --git a/Lib/test/test_tempfile.py b/Lib/test/test_tempfile.py index db08fb1c7f2a42..b64b6a4f2baeb5 100644 --- a/Lib/test/test_tempfile.py +++ b/Lib/test/test_tempfile.py @@ -1641,6 +1641,28 @@ def test_explicit_cleanup_ignore_errors(self): temp_path.exists(), f"TemporaryDirectory {temp_path!s} exists after cleanup") + @unittest.skipUnless(os.name == "nt", "Only on Windows.") + def test_explicit_cleanup_correct_error(self): + with tempfile.TemporaryDirectory() as working_dir: + temp_dir = self.do_create(dir=working_dir) + with open(os.path.join(temp_dir.name, "example.txt"), 'wb'): + # Previously raised NotADirectoryError on some OSes + # (e.g. Windows). See bpo-43153. + with self.assertRaises(PermissionError): + temp_dir.cleanup() + + @unittest.skipUnless(os.name == "nt", "Only on Windows.") + def test_cleanup_with_used_directory(self): + with tempfile.TemporaryDirectory() as working_dir: + temp_dir = self.do_create(dir=working_dir) + subdir = os.path.join(temp_dir.name, "subdir") + os.mkdir(subdir) + with os_helper.change_cwd(subdir): + # Previously raised RecursionError on some OSes + # (e.g. Windows). See bpo-35144. + with self.assertRaises(PermissionError): + temp_dir.cleanup() + @os_helper.skip_unless_symlink def test_cleanup_with_symlink_to_a_directory(self): # cleanup() should not follow symlinks to directories (issue #12464) @@ -1662,6 +1684,103 @@ def test_cleanup_with_symlink_to_a_directory(self): "were deleted") d2.cleanup() + @os_helper.skip_unless_symlink + def test_cleanup_with_symlink_modes(self): + # cleanup() should not follow symlinks when fixing mode bits (#91133) + with self.do_create(recurse=0) as d2: + file1 = os.path.join(d2, 'file1') + open(file1, 'wb').close() + dir1 = os.path.join(d2, 'dir1') + os.mkdir(dir1) + for mode in range(8): + mode <<= 6 + with self.subTest(mode=format(mode, '03o')): + def test(target, target_is_directory): + d1 = self.do_create(recurse=0) + symlink = os.path.join(d1.name, 'symlink') + os.symlink(target, symlink, + target_is_directory=target_is_directory) + try: + os.chmod(symlink, mode, follow_symlinks=False) + except NotImplementedError: + pass + try: + os.chmod(symlink, mode) + except FileNotFoundError: + pass + os.chmod(d1.name, mode) + d1.cleanup() + self.assertFalse(os.path.exists(d1.name)) + + with self.subTest('nonexisting file'): + test('nonexisting', target_is_directory=False) + with self.subTest('nonexisting dir'): + test('nonexisting', target_is_directory=True) + + with self.subTest('existing file'): + os.chmod(file1, mode) + old_mode = os.stat(file1).st_mode + test(file1, target_is_directory=False) + new_mode = os.stat(file1).st_mode + self.assertEqual(new_mode, old_mode, + '%03o != %03o' % (new_mode, old_mode)) + + with self.subTest('existing dir'): + os.chmod(dir1, mode) + old_mode = os.stat(dir1).st_mode + test(dir1, target_is_directory=True) + new_mode = os.stat(dir1).st_mode + self.assertEqual(new_mode, old_mode, + '%03o != %03o' % (new_mode, old_mode)) + + @unittest.skipUnless(hasattr(os, 'chflags'), 'requires os.chflags') + @os_helper.skip_unless_symlink + def test_cleanup_with_symlink_flags(self): + # cleanup() should not follow symlinks when fixing flags (#91133) + flags = stat.UF_IMMUTABLE | stat.UF_NOUNLINK + self.check_flags(flags) + + with self.do_create(recurse=0) as d2: + file1 = os.path.join(d2, 'file1') + open(file1, 'wb').close() + dir1 = os.path.join(d2, 'dir1') + os.mkdir(dir1) + def test(target, target_is_directory): + d1 = self.do_create(recurse=0) + symlink = os.path.join(d1.name, 'symlink') + os.symlink(target, symlink, + target_is_directory=target_is_directory) + try: + os.chflags(symlink, flags, follow_symlinks=False) + except NotImplementedError: + pass + try: + os.chflags(symlink, flags) + except FileNotFoundError: + pass + os.chflags(d1.name, flags) + d1.cleanup() + self.assertFalse(os.path.exists(d1.name)) + + with self.subTest('nonexisting file'): + test('nonexisting', target_is_directory=False) + with self.subTest('nonexisting dir'): + test('nonexisting', target_is_directory=True) + + with self.subTest('existing file'): + os.chflags(file1, flags) + old_flags = os.stat(file1).st_flags + test(file1, target_is_directory=False) + new_flags = os.stat(file1).st_flags + self.assertEqual(new_flags, old_flags) + + with self.subTest('existing dir'): + os.chflags(dir1, flags) + old_flags = os.stat(dir1).st_flags + test(dir1, target_is_directory=True) + new_flags = os.stat(dir1).st_flags + self.assertEqual(new_flags, old_flags) + @support.cpython_only def test_del_on_collection(self): # A TemporaryDirectory is deleted when garbage collected @@ -1834,9 +1953,27 @@ def test_modes(self): d.cleanup() self.assertFalse(os.path.exists(d.name)) - @unittest.skipUnless(hasattr(os, 'chflags'), 'requires os.lchflags') + def check_flags(self, flags): + # skip the test if these flags are not supported (ex: FreeBSD 13) + filename = os_helper.TESTFN + try: + open(filename, "w").close() + try: + os.chflags(filename, flags) + except OSError as exc: + # "OSError: [Errno 45] Operation not supported" + self.skipTest(f"chflags() doesn't support flags " + f"{flags:#b}: {exc}") + else: + os.chflags(filename, 0) + finally: + os_helper.unlink(filename) + + @unittest.skipUnless(hasattr(os, 'chflags'), 'requires os.chflags') def test_flags(self): flags = stat.UF_IMMUTABLE | stat.UF_NOUNLINK + self.check_flags(flags) + d = self.do_create(recurse=3, dirs=2, files=2) with d: # Change files and directories flags recursively. diff --git a/Lib/test/test_termios.py b/Lib/test/test_termios.py new file mode 100644 index 00000000000000..58698ffac2d981 --- /dev/null +++ b/Lib/test/test_termios.py @@ -0,0 +1,220 @@ +import errno +import os +import sys +import tempfile +import unittest +from test.support.import_helper import import_module + +termios = import_module('termios') + + +@unittest.skipUnless(hasattr(os, 'openpty'), "need os.openpty()") +class TestFunctions(unittest.TestCase): + + def setUp(self): + master_fd, self.fd = os.openpty() + self.addCleanup(os.close, master_fd) + self.stream = self.enterContext(open(self.fd, 'wb', buffering=0)) + tmp = self.enterContext(tempfile.TemporaryFile(mode='wb', buffering=0)) + self.bad_fd = tmp.fileno() + + def assertRaisesTermiosError(self, errno, callable, *args): + with self.assertRaises(termios.error) as cm: + callable(*args) + self.assertEqual(cm.exception.args[0], errno) + + def test_tcgetattr(self): + attrs = termios.tcgetattr(self.fd) + self.assertIsInstance(attrs, list) + self.assertEqual(len(attrs), 7) + for i in range(6): + self.assertIsInstance(attrs[i], int) + iflag, oflag, cflag, lflag, ispeed, ospeed, cc = attrs + self.assertIsInstance(cc, list) + self.assertEqual(len(cc), termios.NCCS) + for i, x in enumerate(cc): + if ((lflag & termios.ICANON) == 0 and + (i == termios.VMIN or i == termios.VTIME)): + self.assertIsInstance(x, int) + else: + self.assertIsInstance(x, bytes) + self.assertEqual(len(x), 1) + self.assertEqual(termios.tcgetattr(self.stream), attrs) + + def test_tcgetattr_errors(self): + self.assertRaisesTermiosError(errno.ENOTTY, termios.tcgetattr, self.bad_fd) + self.assertRaises(ValueError, termios.tcgetattr, -1) + self.assertRaises(OverflowError, termios.tcgetattr, 2**1000) + self.assertRaises(TypeError, termios.tcgetattr, object()) + self.assertRaises(TypeError, termios.tcgetattr) + + def test_tcsetattr(self): + attrs = termios.tcgetattr(self.fd) + termios.tcsetattr(self.fd, termios.TCSANOW, attrs) + termios.tcsetattr(self.fd, termios.TCSADRAIN, attrs) + termios.tcsetattr(self.fd, termios.TCSAFLUSH, attrs) + termios.tcsetattr(self.stream, termios.TCSANOW, attrs) + + def test_tcsetattr_errors(self): + attrs = termios.tcgetattr(self.fd) + self.assertRaises(TypeError, termios.tcsetattr, self.fd, termios.TCSANOW, tuple(attrs)) + self.assertRaises(TypeError, termios.tcsetattr, self.fd, termios.TCSANOW, attrs[:-1]) + self.assertRaises(TypeError, termios.tcsetattr, self.fd, termios.TCSANOW, attrs + [0]) + for i in range(6): + attrs2 = attrs[:] + attrs2[i] = 2**1000 + self.assertRaises(OverflowError, termios.tcsetattr, self.fd, termios.TCSANOW, attrs2) + attrs2[i] = object() + self.assertRaises(TypeError, termios.tcsetattr, self.fd, termios.TCSANOW, attrs2) + self.assertRaises(TypeError, termios.tcsetattr, self.fd, termios.TCSANOW, attrs[:-1] + [attrs[-1][:-1]]) + self.assertRaises(TypeError, termios.tcsetattr, self.fd, termios.TCSANOW, attrs[:-1] + [attrs[-1] + [b'\0']]) + for i in range(len(attrs[-1])): + attrs2 = attrs[:] + attrs2[-1] = attrs2[-1][:] + attrs2[-1][i] = 2**1000 + self.assertRaises(OverflowError, termios.tcsetattr, self.fd, termios.TCSANOW, attrs2) + attrs2[-1][i] = object() + self.assertRaises(TypeError, termios.tcsetattr, self.fd, termios.TCSANOW, attrs2) + attrs2[-1][i] = b'' + self.assertRaises(TypeError, termios.tcsetattr, self.fd, termios.TCSANOW, attrs2) + attrs2[-1][i] = b'\0\0' + self.assertRaises(TypeError, termios.tcsetattr, self.fd, termios.TCSANOW, attrs2) + self.assertRaises(TypeError, termios.tcsetattr, self.fd, termios.TCSANOW, object()) + self.assertRaises(TypeError, termios.tcsetattr, self.fd, termios.TCSANOW) + self.assertRaisesTermiosError(errno.EINVAL, termios.tcsetattr, self.fd, -1, attrs) + self.assertRaises(OverflowError, termios.tcsetattr, self.fd, 2**1000, attrs) + self.assertRaises(TypeError, termios.tcsetattr, self.fd, object(), attrs) + self.assertRaisesTermiosError(errno.ENOTTY, termios.tcsetattr, self.bad_fd, termios.TCSANOW, attrs) + self.assertRaises(ValueError, termios.tcsetattr, -1, termios.TCSANOW, attrs) + self.assertRaises(OverflowError, termios.tcsetattr, 2**1000, termios.TCSANOW, attrs) + self.assertRaises(TypeError, termios.tcsetattr, object(), termios.TCSANOW, attrs) + self.assertRaises(TypeError, termios.tcsetattr, self.fd, termios.TCSANOW) + + def test_tcsendbreak(self): + try: + termios.tcsendbreak(self.fd, 1) + except termios.error as exc: + if exc.args[0] == errno.ENOTTY and sys.platform.startswith('freebsd'): + self.skipTest('termios.tcsendbreak() is not supported ' + 'with pseudo-terminals (?) on this platform') + raise + termios.tcsendbreak(self.stream, 1) + + def test_tcsendbreak_errors(self): + self.assertRaises(OverflowError, termios.tcsendbreak, self.fd, 2**1000) + self.assertRaises(TypeError, termios.tcsendbreak, self.fd, 0.0) + self.assertRaises(TypeError, termios.tcsendbreak, self.fd, object()) + self.assertRaisesTermiosError(errno.ENOTTY, termios.tcsendbreak, self.bad_fd, 0) + self.assertRaises(ValueError, termios.tcsendbreak, -1, 0) + self.assertRaises(OverflowError, termios.tcsendbreak, 2**1000, 0) + self.assertRaises(TypeError, termios.tcsendbreak, object(), 0) + self.assertRaises(TypeError, termios.tcsendbreak, self.fd) + + def test_tcdrain(self): + termios.tcdrain(self.fd) + termios.tcdrain(self.stream) + + def test_tcdrain_errors(self): + self.assertRaisesTermiosError(errno.ENOTTY, termios.tcdrain, self.bad_fd) + self.assertRaises(ValueError, termios.tcdrain, -1) + self.assertRaises(OverflowError, termios.tcdrain, 2**1000) + self.assertRaises(TypeError, termios.tcdrain, object()) + self.assertRaises(TypeError, termios.tcdrain) + + def test_tcflush(self): + termios.tcflush(self.fd, termios.TCIFLUSH) + termios.tcflush(self.fd, termios.TCOFLUSH) + termios.tcflush(self.fd, termios.TCIOFLUSH) + + def test_tcflush_errors(self): + self.assertRaisesTermiosError(errno.EINVAL, termios.tcflush, self.fd, -1) + self.assertRaises(OverflowError, termios.tcflush, self.fd, 2**1000) + self.assertRaises(TypeError, termios.tcflush, self.fd, object()) + self.assertRaisesTermiosError(errno.ENOTTY, termios.tcflush, self.bad_fd, termios.TCIFLUSH) + self.assertRaises(ValueError, termios.tcflush, -1, termios.TCIFLUSH) + self.assertRaises(OverflowError, termios.tcflush, 2**1000, termios.TCIFLUSH) + self.assertRaises(TypeError, termios.tcflush, object(), termios.TCIFLUSH) + self.assertRaises(TypeError, termios.tcflush, self.fd) + + def test_tcflow(self): + termios.tcflow(self.fd, termios.TCOOFF) + termios.tcflow(self.fd, termios.TCOON) + termios.tcflow(self.fd, termios.TCIOFF) + termios.tcflow(self.fd, termios.TCION) + + def test_tcflow_errors(self): + self.assertRaisesTermiosError(errno.EINVAL, termios.tcflow, self.fd, -1) + self.assertRaises(OverflowError, termios.tcflow, self.fd, 2**1000) + self.assertRaises(TypeError, termios.tcflow, self.fd, object()) + self.assertRaisesTermiosError(errno.ENOTTY, termios.tcflow, self.bad_fd, termios.TCOON) + self.assertRaises(ValueError, termios.tcflow, -1, termios.TCOON) + self.assertRaises(OverflowError, termios.tcflow, 2**1000, termios.TCOON) + self.assertRaises(TypeError, termios.tcflow, object(), termios.TCOON) + self.assertRaises(TypeError, termios.tcflow, self.fd) + + def test_tcgetwinsize(self): + size = termios.tcgetwinsize(self.fd) + self.assertIsInstance(size, tuple) + self.assertEqual(len(size), 2) + self.assertIsInstance(size[0], int) + self.assertIsInstance(size[1], int) + self.assertEqual(termios.tcgetwinsize(self.stream), size) + + def test_tcgetwinsize_errors(self): + self.assertRaisesTermiosError(errno.ENOTTY, termios.tcgetwinsize, self.bad_fd) + self.assertRaises(ValueError, termios.tcgetwinsize, -1) + self.assertRaises(OverflowError, termios.tcgetwinsize, 2**1000) + self.assertRaises(TypeError, termios.tcgetwinsize, object()) + self.assertRaises(TypeError, termios.tcgetwinsize) + + def test_tcsetwinsize(self): + size = termios.tcgetwinsize(self.fd) + termios.tcsetwinsize(self.fd, size) + termios.tcsetwinsize(self.fd, list(size)) + termios.tcsetwinsize(self.stream, size) + + def test_tcsetwinsize_errors(self): + size = termios.tcgetwinsize(self.fd) + self.assertRaises(TypeError, termios.tcsetwinsize, self.fd, size[:-1]) + self.assertRaises(TypeError, termios.tcsetwinsize, self.fd, size + (0,)) + self.assertRaises(TypeError, termios.tcsetwinsize, self.fd, object()) + self.assertRaises(OverflowError, termios.tcsetwinsize, self.fd, (size[0], 2**1000)) + self.assertRaises(TypeError, termios.tcsetwinsize, self.fd, (size[0], float(size[1]))) + self.assertRaises(TypeError, termios.tcsetwinsize, self.fd, (size[0], object())) + self.assertRaises(OverflowError, termios.tcsetwinsize, self.fd, (2**1000, size[1])) + self.assertRaises(TypeError, termios.tcsetwinsize, self.fd, (float(size[0]), size[1])) + self.assertRaises(TypeError, termios.tcsetwinsize, self.fd, (object(), size[1])) + self.assertRaisesTermiosError(errno.ENOTTY, termios.tcsetwinsize, self.bad_fd, size) + self.assertRaises(ValueError, termios.tcsetwinsize, -1, size) + self.assertRaises(OverflowError, termios.tcsetwinsize, 2**1000, size) + self.assertRaises(TypeError, termios.tcsetwinsize, object(), size) + self.assertRaises(TypeError, termios.tcsetwinsize, self.fd) + + +class TestModule(unittest.TestCase): + def test_constants(self): + self.assertIsInstance(termios.B0, int) + self.assertIsInstance(termios.B38400, int) + self.assertIsInstance(termios.TCSANOW, int) + self.assertIsInstance(termios.TCSADRAIN, int) + self.assertIsInstance(termios.TCSAFLUSH, int) + self.assertIsInstance(termios.TCIFLUSH, int) + self.assertIsInstance(termios.TCOFLUSH, int) + self.assertIsInstance(termios.TCIOFLUSH, int) + self.assertIsInstance(termios.TCOOFF, int) + self.assertIsInstance(termios.TCOON, int) + self.assertIsInstance(termios.TCIOFF, int) + self.assertIsInstance(termios.TCION, int) + self.assertIsInstance(termios.VTIME, int) + self.assertIsInstance(termios.VMIN, int) + self.assertIsInstance(termios.NCCS, int) + self.assertLess(termios.VTIME, termios.NCCS) + self.assertLess(termios.VMIN, termios.NCCS) + + def test_exception(self): + self.assertTrue(issubclass(termios.error, Exception)) + self.assertFalse(issubclass(termios.error, OSError)) + + +if __name__ == '__main__': + unittest.main() diff --git a/Lib/test/test_thread.py b/Lib/test/test_thread.py index 8656fbdd83e9c7..931cb4b797e0b2 100644 --- a/Lib/test/test_thread.py +++ b/Lib/test/test_thread.py @@ -155,11 +155,137 @@ def task(): started.acquire() self.assertEqual(str(cm.unraisable.exc_value), "task failed") - self.assertIs(cm.unraisable.object, task) + self.assertIsNone(cm.unraisable.object) self.assertEqual(cm.unraisable.err_msg, - "Exception ignored in thread started by") + f"Exception ignored in thread started by {task!r}") self.assertIsNotNone(cm.unraisable.exc_traceback) + def test_join_thread(self): + finished = [] + + def task(): + time.sleep(0.05) + finished.append(thread.get_ident()) + + with threading_helper.wait_threads_exit(): + handle = thread.start_joinable_thread(task) + handle.join() + self.assertEqual(len(finished), 1) + self.assertEqual(handle.ident, finished[0]) + + def test_join_thread_already_exited(self): + def task(): + pass + + with threading_helper.wait_threads_exit(): + handle = thread.start_joinable_thread(task) + time.sleep(0.05) + handle.join() + + def test_join_several_times(self): + def task(): + pass + + with threading_helper.wait_threads_exit(): + handle = thread.start_joinable_thread(task) + handle.join() + with self.assertRaisesRegex(ValueError, "not joinable"): + handle.join() + + def test_joinable_not_joined(self): + handle_destroyed = thread.allocate_lock() + handle_destroyed.acquire() + + def task(): + handle_destroyed.acquire() + + with threading_helper.wait_threads_exit(): + handle = thread.start_joinable_thread(task) + del handle + handle_destroyed.release() + + def test_join_from_self(self): + errors = [] + handles = [] + start_joinable_thread_returned = thread.allocate_lock() + start_joinable_thread_returned.acquire() + task_tried_to_join = thread.allocate_lock() + task_tried_to_join.acquire() + + def task(): + start_joinable_thread_returned.acquire() + try: + handles[0].join() + except Exception as e: + errors.append(e) + finally: + task_tried_to_join.release() + + with threading_helper.wait_threads_exit(): + handle = thread.start_joinable_thread(task) + handles.append(handle) + start_joinable_thread_returned.release() + # Can still join after joining failed in other thread + task_tried_to_join.acquire() + handle.join() + + assert len(errors) == 1 + with self.assertRaisesRegex(RuntimeError, "Cannot join current thread"): + raise errors[0] + + def test_detach_from_self(self): + errors = [] + handles = [] + start_joinable_thread_returned = thread.allocate_lock() + start_joinable_thread_returned.acquire() + thread_detached = thread.allocate_lock() + thread_detached.acquire() + + def task(): + start_joinable_thread_returned.acquire() + try: + handles[0].detach() + except Exception as e: + errors.append(e) + finally: + thread_detached.release() + + with threading_helper.wait_threads_exit(): + handle = thread.start_joinable_thread(task) + handles.append(handle) + start_joinable_thread_returned.release() + thread_detached.acquire() + with self.assertRaisesRegex(ValueError, "not joinable"): + handle.join() + + assert len(errors) == 0 + + def test_detach_then_join(self): + lock = thread.allocate_lock() + lock.acquire() + + def task(): + lock.acquire() + + with threading_helper.wait_threads_exit(): + handle = thread.start_joinable_thread(task) + # detach() returns even though the thread is blocked on lock + handle.detach() + # join() then cannot be called anymore + with self.assertRaisesRegex(ValueError, "not joinable"): + handle.join() + lock.release() + + def test_join_then_detach(self): + def task(): + pass + + with threading_helper.wait_threads_exit(): + handle = thread.start_joinable_thread(task) + handle.join() + with self.assertRaisesRegex(ValueError, "not joinable"): + handle.detach() + class Barrier: def __init__(self, num_threads): diff --git a/Lib/test/test_threading.py b/Lib/test/test_threading.py index 4a91eef31c4b8b..3060af44fd7e3d 100644 --- a/Lib/test/test_threading.py +++ b/Lib/test/test_threading.py @@ -26,6 +26,11 @@ from test import lock_tests from test import support +try: + from test.support import interpreters +except ImportError: + interpreters = None + threading_helper.requires_working_threading(module=True) # Between fork() and exec(), only async-safe functions are allowed (issues @@ -35,6 +40,22 @@ platforms_to_skip = ('netbsd5', 'hp-ux11') +def skip_unless_reliable_fork(test): + if not support.has_fork_support: + return unittest.skip("requires working os.fork()")(test) + if sys.platform in platforms_to_skip: + return unittest.skip("due to known OS bug related to thread+fork")(test) + if support.HAVE_ASAN_FORK_BUG: + return unittest.skip("libasan has a pthread_create() dead lock related to thread+fork")(test) + return test + + +def requires_subinterpreters(meth): + """Decorator to skip a test if subinterpreters are not supported.""" + return unittest.skipIf(interpreters is None, + 'subinterpreters required')(meth) + + def restore_default_excepthook(testcase): testcase.addCleanup(setattr, threading, 'excepthook', threading.excepthook) threading.excepthook = threading.__excepthook__ @@ -355,8 +376,8 @@ def test_limbo_cleanup(self): # Issue 7481: Failure to start thread should cleanup the limbo map. def fail_new_thread(*args): raise threading.ThreadError() - _start_new_thread = threading._start_new_thread - threading._start_new_thread = fail_new_thread + _start_joinable_thread = threading._start_joinable_thread + threading._start_joinable_thread = fail_new_thread try: t = threading.Thread(target=lambda: None) self.assertRaises(threading.ThreadError, t.start) @@ -364,7 +385,7 @@ def fail_new_thread(*args): t in threading._limbo, "Failed to cleanup _limbo map on failure of Thread.start().") finally: - threading._start_new_thread = _start_new_thread + threading._start_joinable_thread = _start_joinable_thread def test_finalize_running_thread(self): # Issue 1402: the PyGILState_Ensure / _Release functions may be called @@ -461,6 +482,47 @@ def test_enumerate_after_join(self): finally: sys.setswitchinterval(old_interval) + def test_join_from_multiple_threads(self): + # Thread.join() should be thread-safe + errors = [] + + def worker(): + time.sleep(0.005) + + def joiner(thread): + try: + thread.join() + except Exception as e: + errors.append(e) + + for N in range(2, 20): + threads = [threading.Thread(target=worker)] + for i in range(N): + threads.append(threading.Thread(target=joiner, + args=(threads[0],))) + for t in threads: + t.start() + time.sleep(0.01) + for t in threads: + t.join() + if errors: + raise errors[0] + + def test_join_with_timeout(self): + lock = _thread.allocate_lock() + lock.acquire() + + def worker(): + lock.acquire() + + thread = threading.Thread(target=worker) + thread.start() + thread.join(timeout=0.01) + assert thread.is_alive() + lock.release() + thread.join() + assert not thread.is_alive() + def test_no_refcycle_through_target(self): class RunSelfFunction(object): def __init__(self, should_raise): @@ -539,7 +601,7 @@ def test_daemon_param(self): t = threading.Thread(daemon=True) self.assertTrue(t.daemon) - @support.requires_fork() + @skip_unless_reliable_fork def test_dummy_thread_after_fork(self): # Issue #14308: a dummy thread in the active list doesn't mess up # the after-fork mechanism. @@ -571,7 +633,7 @@ def background_thread(evt): self.assertEqual(out, b'') self.assertEqual(err, b'') - @support.requires_fork() + @skip_unless_reliable_fork def test_is_alive_after_fork(self): # Try hard to trigger #18418: is_alive() could sometimes be True on # threads that vanished after a fork. @@ -607,7 +669,7 @@ def f(): th.start() th.join() - @support.requires_fork() + @skip_unless_reliable_fork @unittest.skipUnless(hasattr(os, 'waitpid'), "test needs os.waitpid()") def test_main_thread_after_fork(self): code = """if 1: @@ -628,8 +690,7 @@ def test_main_thread_after_fork(self): self.assertEqual(err, b"") self.assertEqual(data, "MainThread\nTrue\nTrue\n") - @unittest.skipIf(sys.platform in platforms_to_skip, "due to known OS bug") - @support.requires_fork() + @skip_unless_reliable_fork @unittest.skipUnless(hasattr(os, 'waitpid'), "test needs os.waitpid()") def test_main_thread_after_fork_from_nonmain_thread(self): code = """if 1: @@ -1076,8 +1137,7 @@ def test_1_join_on_shutdown(self): """ self._run_and_join(script) - @support.requires_fork() - @unittest.skipIf(sys.platform in platforms_to_skip, "due to known OS bug") + @skip_unless_reliable_fork def test_2_join_in_forked_process(self): # Like the test above, but from a forked interpreter script = """if 1: @@ -1097,8 +1157,7 @@ def test_2_join_in_forked_process(self): """ self._run_and_join(script) - @support.requires_fork() - @unittest.skipIf(sys.platform in platforms_to_skip, "due to known OS bug") + @skip_unless_reliable_fork def test_3_join_in_forked_from_thread(self): # Like the test above, but fork() was called from a worker thread # In the forked process, the main Thread object must be marked as stopped. @@ -1168,8 +1227,7 @@ def main(): rc, out, err = assert_python_ok('-c', script) self.assertFalse(err) - @support.requires_fork() - @unittest.skipIf(sys.platform in platforms_to_skip, "due to known OS bug") + @skip_unless_reliable_fork def test_reinit_tls_after_fork(self): # Issue #13817: fork() would deadlock in a multithreaded program with # the ad-hoc TLS implementation. @@ -1195,7 +1253,7 @@ def do_fork_and_wait(): for t in threads: t.join() - @support.requires_fork() + @skip_unless_reliable_fork def test_clear_threads_states_after_fork(self): # Issue #17094: check that threads states are cleared after fork() @@ -1298,6 +1356,44 @@ def f(): # The thread was joined properly. self.assertEqual(os.read(r, 1), b"x") + @requires_subinterpreters + def test_threads_join_with_no_main(self): + r_interp, w_interp = self.pipe() + + INTERP = b'I' + FINI = b'F' + DONE = b'D' + + interp = interpreters.create() + interp.exec_sync(f"""if True: + import os + import threading + import time + + done = False + + def notify_fini(): + global done + done = True + os.write({w_interp}, {FINI!r}) + t.join() + threading._register_atexit(notify_fini) + + def task(): + while not done: + time.sleep(0.1) + os.write({w_interp}, {DONE!r}) + t = threading.Thread(target=task) + t.start() + + os.write({w_interp}, {INTERP!r}) + """) + interp.close() + + self.assertEqual(os.read(r_interp, 1), INTERP) + self.assertEqual(os.read(r_interp, 1), FINI) + self.assertEqual(os.read(r_interp, 1), DONE) + @cpython_only def test_daemon_threads_fatal_error(self): subinterp_code = f"""if 1: @@ -1748,6 +1844,30 @@ class PyRLockTests(lock_tests.RLockTests): class CRLockTests(lock_tests.RLockTests): locktype = staticmethod(threading._CRLock) + def test_signature(self): # gh-102029 + with warnings.catch_warnings(record=True) as warnings_log: + threading.RLock() + self.assertEqual(warnings_log, []) + + arg_types = [ + ((1,), {}), + ((), {'a': 1}), + ((1, 2), {'a': 1}), + ] + for args, kwargs in arg_types: + with self.subTest(args=args, kwargs=kwargs): + with self.assertWarns(DeprecationWarning): + threading.RLock(*args, **kwargs) + + # Subtypes with custom `__init__` are allowed (but, not recommended): + class CustomRLock(self.locktype): + def __init__(self, a, *, b) -> None: + super().__init__() + + with warnings.catch_warnings(record=True) as warnings_log: + CustomRLock(1, b=2) + self.assertEqual(warnings_log, []) + class EventTests(lock_tests.EventTests): eventtype = staticmethod(threading.Event) @@ -1755,6 +1875,9 @@ class ConditionAsRLockTests(lock_tests.RLockTests): # Condition uses an RLock by default and exports its API. locktype = staticmethod(threading.Condition) + def test_recursion_count(self): + self.skipTest("Condition does not expose _recursion_count()") + class ConditionTests(lock_tests.ConditionTests): condtype = staticmethod(threading.Condition) diff --git a/Lib/test/test_timeout.py b/Lib/test/test_timeout.py index 30e843a423a777..35ff56f1a5ee09 100644 --- a/Lib/test/test_timeout.py +++ b/Lib/test/test_timeout.py @@ -148,13 +148,12 @@ def setUp(self): def tearDown(self): self.sock.close() - @unittest.skipIf(True, 'need to replace these hosts; see bpo-35518') def testConnectTimeout(self): # Testing connect timeout is tricky: we need to have IP connectivity # to a host that silently drops our packets. We can't simulate this # from Python because it's a function of the underlying TCP/IP stack. - # So, the following Snakebite host has been defined: - blackhole = resolve_address('blackhole.snakebite.net', 56666) + # So, the following port on the pythontest.net host has been defined: + blackhole = resolve_address('pythontest.net', 56666) # Blackhole has been configured to silently drop any incoming packets. # No RSTs (for TCP) or ICMP UNREACH (for UDP/ICMP) will be sent back @@ -166,7 +165,7 @@ def testConnectTimeout(self): # to firewalling or general network configuration. In order to improve # our confidence in testing the blackhole, a corresponding 'whitehole' # has also been set up using one port higher: - whitehole = resolve_address('whitehole.snakebite.net', 56667) + whitehole = resolve_address('pythontest.net', 56667) # This address has been configured to immediately drop any incoming # packets as well, but it does it respectfully with regards to the @@ -180,20 +179,15 @@ def testConnectTimeout(self): # timeframe). # For the records, the whitehole/blackhole configuration has been set - # up using the 'pf' firewall (available on BSDs), using the following: + # up using the 'iptables' firewall, using the following rules: # - # ext_if="bge0" - # - # blackhole_ip="35.8.247.6" - # whitehole_ip="35.8.247.6" - # blackhole_port="56666" - # whitehole_port="56667" - # - # block return in log quick on $ext_if proto { tcp udp } \ - # from any to $whitehole_ip port $whitehole_port - # block drop in log quick on $ext_if proto { tcp udp } \ - # from any to $blackhole_ip port $blackhole_port + # -A INPUT -p tcp --destination-port 56666 -j DROP + # -A INPUT -p udp --destination-port 56666 -j DROP + # -A INPUT -p tcp --destination-port 56667 -j REJECT + # -A INPUT -p udp --destination-port 56667 -j REJECT # + # See https://github.com/python/psf-salt/blob/main/pillar/base/firewall/snakebite.sls + # for the current configuration. skip = True sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) diff --git a/Lib/test/test_tkinter/__init__.py b/Lib/test/test_tkinter/__init__.py index b1181bc04b7953..aa196c12c804ac 100644 --- a/Lib/test/test_tkinter/__init__.py +++ b/Lib/test/test_tkinter/__init__.py @@ -10,6 +10,7 @@ if check_sanitizer(address=True, memory=True): + # See gh-90791 for details raise unittest.SkipTest("Tests involving libX11 can SEGFAULT on ASAN/MSAN builds") # Skip test if _tkinter wasn't built. diff --git a/Lib/test/test_tkinter/support.py b/Lib/test/test_tkinter/support.py index 9154ebac5c48f8..a37705f0ae6feb 100644 --- a/Lib/test/test_tkinter/support.py +++ b/Lib/test/test_tkinter/support.py @@ -1,6 +1,5 @@ import functools import tkinter -import unittest class AbstractTkTest: @@ -79,28 +78,28 @@ def simulate_mouse_click(widget, x, y): import _tkinter tcl_version = tuple(map(int, _tkinter.TCL_VERSION.split('.'))) +tk_version = tuple(map(int, _tkinter.TK_VERSION.split('.'))) -def requires_tcl(*version): - if len(version) <= 2: - return unittest.skipUnless(tcl_version >= version, - 'requires Tcl version >= ' + '.'.join(map(str, version))) +def requires_tk(*version): + if len(version) <= 2 and tk_version >= version: + return lambda test: test def deco(test): @functools.wraps(test) def newtest(self): - if get_tk_patchlevel() < version: - self.skipTest('requires Tcl version >= ' + + root = getattr(self, 'root', None) + if get_tk_patchlevel(root) < version: + self.skipTest('requires Tk version >= ' + '.'.join(map(str, version))) test(self) return newtest return deco _tk_patchlevel = None -def get_tk_patchlevel(): +def get_tk_patchlevel(root): global _tk_patchlevel if _tk_patchlevel is None: - tcl = tkinter.Tcl() - _tk_patchlevel = tcl.info_patchlevel() + _tk_patchlevel = tkinter._parse_version(root.tk.globalgetvar('tk_patchLevel')) return _tk_patchlevel units = { diff --git a/Lib/test/test_tkinter/test_images.py b/Lib/test/test_tkinter/test_images.py index c07de867ce04b7..ef1c99f57c6f47 100644 --- a/Lib/test/test_tkinter/test_images.py +++ b/Lib/test/test_tkinter/test_images.py @@ -2,7 +2,7 @@ import tkinter from test import support from test.support import os_helper -from test.test_tkinter.support import AbstractTkTest, AbstractDefaultRootTest, requires_tcl +from test.test_tkinter.support import AbstractTkTest, AbstractDefaultRootTest, requires_tk support.requires('gui') @@ -144,6 +144,14 @@ def test_configure_foreground(self): self.assertEqual(image['foreground'], '-foreground {} {} #000000 yellow') + def test_bug_100814(self): + # gh-100814: Passing a callable option value causes AttributeError. + with self.assertRaises(tkinter.TclError): + tkinter.BitmapImage('::img::test', master=self.root, spam=print) + image = tkinter.BitmapImage('::img::test', master=self.root) + with self.assertRaises(tkinter.TclError): + image.configure(spam=print) + class PhotoImageTest(AbstractTkTest, unittest.TestCase): @@ -213,11 +221,11 @@ def test_create_from_gif_file(self): def test_create_from_gif_data(self): self.check_create_from_data('gif') - @requires_tcl(8, 6) + @requires_tk(8, 6) def test_create_from_png_file(self): self.check_create_from_file('png') - @requires_tcl(8, 6) + @requires_tk(8, 6) def test_create_from_png_data(self): self.check_create_from_data('png') @@ -274,6 +282,14 @@ def test_configure_palette(self): image.configure(palette='3/4/2') self.assertEqual(image['palette'], '3/4/2') + def test_bug_100814(self): + # gh-100814: Passing a callable option value causes AttributeError. + with self.assertRaises(tkinter.TclError): + tkinter.PhotoImage('::img::test', master=self.root, spam=print) + image = tkinter.PhotoImage('::img::test', master=self.root) + with self.assertRaises(tkinter.TclError): + image.configure(spam=print) + def test_blank(self): image = self.create() image.blank() @@ -341,13 +357,18 @@ def test_get(self): self.assertRaises(tkinter.TclError, image.get, 15, 16) def test_write(self): + filename = os_helper.TESTFN + import locale + if locale.getlocale()[0] is None: + # Tcl uses Latin1 in the C locale + filename = os_helper.TESTFN_ASCII image = self.create() - self.addCleanup(os_helper.unlink, os_helper.TESTFN) + self.addCleanup(os_helper.unlink, filename) - image.write(os_helper.TESTFN) + image.write(filename) image2 = tkinter.PhotoImage('::img::test2', master=self.root, format='ppm', - file=os_helper.TESTFN) + file=filename) self.assertEqual(str(image2), '::img::test2') self.assertEqual(image2.type(), 'photo') self.assertEqual(image2.width(), 16) @@ -355,10 +376,10 @@ def test_write(self): self.assertEqual(image2.get(0, 0), image.get(0, 0)) self.assertEqual(image2.get(15, 8), image.get(15, 8)) - image.write(os_helper.TESTFN, format='gif', from_coords=(4, 6, 6, 9)) + image.write(filename, format='gif', from_coords=(4, 6, 6, 9)) image3 = tkinter.PhotoImage('::img::test3', master=self.root, format='gif', - file=os_helper.TESTFN) + file=filename) self.assertEqual(str(image3), '::img::test3') self.assertEqual(image3.type(), 'photo') self.assertEqual(image3.width(), 2) diff --git a/Lib/test/test_tkinter/test_misc.py b/Lib/test/test_tkinter/test_misc.py index d1aca58d15fbd8..dc8a810235fc9b 100644 --- a/Lib/test/test_tkinter/test_misc.py +++ b/Lib/test/test_tkinter/test_misc.py @@ -1,9 +1,10 @@ import functools import unittest import tkinter +from tkinter import TclError import enum from test import support -from test.test_tkinter.support import AbstractTkTest, AbstractDefaultRootTest +from test.test_tkinter.support import AbstractTkTest, AbstractDefaultRootTest, requires_tk support.requires('gui') @@ -36,6 +37,59 @@ def test_generated_names(self): for name in str(b).split('.'): self.assertFalse(name.isidentifier(), msg=repr(name)) + @requires_tk(8, 6, 6) + def test_tk_busy(self): + root = self.root + f = tkinter.Frame(root, name='myframe') + f2 = tkinter.Frame(root) + f.pack() + f2.pack() + b = tkinter.Button(f) + b.pack() + f.tk_busy_hold() + with self.assertRaisesRegex(TclError, 'unknown option "-spam"'): + f.tk_busy_configure(spam='eggs') + with self.assertRaisesRegex(TclError, 'unknown option "-spam"'): + f.tk_busy_cget('spam') + with self.assertRaisesRegex(TclError, 'unknown option "-spam"'): + f.tk_busy_configure('spam') + self.assertIsInstance(f.tk_busy_configure(), dict) + + self.assertTrue(f.tk_busy_status()) + self.assertFalse(root.tk_busy_status()) + self.assertFalse(f2.tk_busy_status()) + self.assertFalse(b.tk_busy_status()) + self.assertIn(f, f.tk_busy_current()) + self.assertIn(f, f.tk_busy_current('*.m?f*me')) + self.assertNotIn(f, f.tk_busy_current('*spam')) + + f.tk_busy_forget() + self.assertFalse(f.tk_busy_status()) + self.assertFalse(f.tk_busy_current()) + with self.assertRaisesRegex(TclError, "can't find busy window"): + f.tk_busy_configure() + with self.assertRaisesRegex(TclError, "can't find busy window"): + f.tk_busy_forget() + + @requires_tk(8, 6, 6) + def test_tk_busy_with_cursor(self): + root = self.root + if root._windowingsystem == 'aqua': + self.skipTest('the cursor option is not supported on OSX/Aqua') + f = tkinter.Frame(root, name='myframe') + f.pack() + f.tk_busy_hold(cursor='gumby') + + self.assertEqual(f.tk_busy_cget('cursor'), 'gumby') + f.tk_busy_configure(cursor='heart') + self.assertEqual(f.tk_busy_cget('cursor'), 'heart') + self.assertEqual(f.tk_busy_configure()['cursor'][4], 'heart') + self.assertEqual(f.tk_busy_configure('cursor')[4], 'heart') + + f.tk_busy_forget() + with self.assertRaisesRegex(TclError, "can't find busy window"): + f.tk_busy_cget('cursor') + def test_tk_setPalette(self): root = self.root root.tk_setPalette('black') @@ -227,6 +281,18 @@ def assertApprox(col1, col2): with self.assertRaises(tkinter.TclError): rgb((111, 78, 55)) + def test_winfo_pathname(self): + t = tkinter.Toplevel(self.root) + w = tkinter.Button(t) + wid = w.winfo_id() + self.assertIsInstance(wid, int) + self.assertEqual(self.root.winfo_pathname(hex(wid)), str(w)) + self.assertEqual(self.root.winfo_pathname(hex(wid), displayof=None), str(w)) + self.assertEqual(self.root.winfo_pathname(hex(wid), displayof=t), str(w)) + self.assertEqual(self.root.winfo_pathname(wid), str(w)) + self.assertEqual(self.root.winfo_pathname(wid, displayof=None), str(w)) + self.assertEqual(self.root.winfo_pathname(wid, displayof=t), str(w)) + def test_event_repr_defaults(self): e = tkinter.Event() e.serial = 12345 @@ -371,6 +437,329 @@ def test_info_patchlevel(self): self.assertTrue(str(vi).startswith(f'{vi.major}.{vi.minor}')) +class BindTest(AbstractTkTest, unittest.TestCase): + + def setUp(self): + super().setUp() + root = self.root + self.frame = tkinter.Frame(self.root, class_='Test', + width=150, height=100) + self.frame.pack() + + def assertCommandExist(self, funcid): + self.assertEqual(_info_commands(self.root, funcid), (funcid,)) + + def assertCommandNotExist(self, funcid): + self.assertEqual(_info_commands(self.root, funcid), ()) + + def test_bind(self): + event = '' + f = self.frame + self.assertEqual(f.bind(), ()) + self.assertEqual(f.bind(event), '') + def test1(e): pass + def test2(e): pass + + funcid = f.bind(event, test1) + self.assertEqual(f.bind(), (event,)) + script = f.bind(event) + self.assertIn(funcid, script) + self.assertCommandExist(funcid) + + funcid2 = f.bind(event, test2, add=True) + script = f.bind(event) + self.assertIn(funcid, script) + self.assertIn(funcid2, script) + self.assertCommandExist(funcid) + self.assertCommandExist(funcid2) + + def test_unbind(self): + event = '' + f = self.frame + self.assertEqual(f.bind(), ()) + self.assertEqual(f.bind(event), '') + def test1(e): pass + def test2(e): pass + + funcid = f.bind(event, test1) + funcid2 = f.bind(event, test2, add=True) + + self.assertRaises(TypeError, f.unbind) + f.unbind(event) + self.assertEqual(f.bind(event), '') + self.assertEqual(f.bind(), ()) + + def test_unbind2(self): + f = self.frame + f.wait_visibility() + f.focus_force() + f.update_idletasks() + event = '' + self.assertEqual(f.bind(), ()) + self.assertEqual(f.bind(event), '') + def test1(e): events.append('a') + def test2(e): events.append('b') + def test3(e): events.append('c') + + funcid = f.bind(event, test1) + funcid2 = f.bind(event, test2, add=True) + funcid3 = f.bind(event, test3, add=True) + events = [] + f.event_generate(event) + self.assertEqual(events, ['a', 'b', 'c']) + + f.unbind(event, funcid2) + script = f.bind(event) + self.assertNotIn(funcid2, script) + self.assertIn(funcid, script) + self.assertIn(funcid3, script) + self.assertEqual(f.bind(), (event,)) + self.assertCommandNotExist(funcid2) + self.assertCommandExist(funcid) + self.assertCommandExist(funcid3) + events = [] + f.event_generate(event) + self.assertEqual(events, ['a', 'c']) + + f.unbind(event, funcid) + f.unbind(event, funcid3) + self.assertEqual(f.bind(event), '') + self.assertEqual(f.bind(), ()) + self.assertCommandNotExist(funcid) + self.assertCommandNotExist(funcid2) + self.assertCommandNotExist(funcid3) + events = [] + f.event_generate(event) + self.assertEqual(events, []) + + # non-idempotent + self.assertRaises(tkinter.TclError, f.unbind, event, funcid2) + + def test_bind_rebind(self): + event = '' + f = self.frame + self.assertEqual(f.bind(), ()) + self.assertEqual(f.bind(event), '') + def test1(e): pass + def test2(e): pass + def test3(e): pass + + funcid = f.bind(event, test1) + funcid2 = f.bind(event, test2, add=True) + script = f.bind(event) + self.assertIn(funcid2, script) + self.assertIn(funcid, script) + self.assertCommandExist(funcid) + self.assertCommandExist(funcid2) + + funcid3 = f.bind(event, test3) + script = f.bind(event) + self.assertNotIn(funcid, script) + self.assertNotIn(funcid2, script) + self.assertIn(funcid3, script) + self.assertCommandExist(funcid3) + + def test_bind_class(self): + event = '' + bind_class = self.root.bind_class + unbind_class = self.root.unbind_class + self.assertRaises(TypeError, bind_class) + self.assertEqual(bind_class('Test'), ()) + self.assertEqual(bind_class('Test', event), '') + self.addCleanup(unbind_class, 'Test', event) + def test1(e): pass + def test2(e): pass + + funcid = bind_class('Test', event, test1) + self.assertEqual(bind_class('Test'), (event,)) + script = bind_class('Test', event) + self.assertIn(funcid, script) + self.assertCommandExist(funcid) + + funcid2 = bind_class('Test', event, test2, add=True) + script = bind_class('Test', event) + self.assertIn(funcid, script) + self.assertIn(funcid2, script) + self.assertCommandExist(funcid) + self.assertCommandExist(funcid2) + + def test_unbind_class(self): + event = '' + bind_class = self.root.bind_class + unbind_class = self.root.unbind_class + self.assertEqual(bind_class('Test'), ()) + self.assertEqual(bind_class('Test', event), '') + self.addCleanup(unbind_class, 'Test', event) + def test1(e): pass + def test2(e): pass + + funcid = bind_class('Test', event, test1) + funcid2 = bind_class('Test', event, test2, add=True) + + self.assertRaises(TypeError, unbind_class) + self.assertRaises(TypeError, unbind_class, 'Test') + unbind_class('Test', event) + self.assertEqual(bind_class('Test', event), '') + self.assertEqual(bind_class('Test'), ()) + self.assertCommandExist(funcid) + self.assertCommandExist(funcid2) + + unbind_class('Test', event) # idempotent + + def test_bind_class_rebind(self): + event = '' + bind_class = self.root.bind_class + unbind_class = self.root.unbind_class + self.assertEqual(bind_class('Test'), ()) + self.assertEqual(bind_class('Test', event), '') + self.addCleanup(unbind_class, 'Test', event) + def test1(e): pass + def test2(e): pass + def test3(e): pass + + funcid = bind_class('Test', event, test1) + funcid2 = bind_class('Test', event, test2, add=True) + script = bind_class('Test', event) + self.assertIn(funcid2, script) + self.assertIn(funcid, script) + self.assertCommandExist(funcid) + self.assertCommandExist(funcid2) + + funcid3 = bind_class('Test', event, test3) + script = bind_class('Test', event) + self.assertNotIn(funcid, script) + self.assertNotIn(funcid2, script) + self.assertIn(funcid3, script) + self.assertCommandExist(funcid) + self.assertCommandExist(funcid2) + self.assertCommandExist(funcid3) + + def test_bind_all(self): + event = '' + bind_all = self.root.bind_all + unbind_all = self.root.unbind_all + self.assertNotIn(event, bind_all()) + self.assertEqual(bind_all(event), '') + self.addCleanup(unbind_all, event) + def test1(e): pass + def test2(e): pass + + funcid = bind_all(event, test1) + self.assertIn(event, bind_all()) + script = bind_all(event) + self.assertIn(funcid, script) + self.assertCommandExist(funcid) + + funcid2 = bind_all(event, test2, add=True) + script = bind_all(event) + self.assertIn(funcid, script) + self.assertIn(funcid2, script) + self.assertCommandExist(funcid) + self.assertCommandExist(funcid2) + + def test_unbind_all(self): + event = '' + bind_all = self.root.bind_all + unbind_all = self.root.unbind_all + self.assertNotIn(event, bind_all()) + self.assertEqual(bind_all(event), '') + self.addCleanup(unbind_all, event) + def test1(e): pass + def test2(e): pass + + funcid = bind_all(event, test1) + funcid2 = bind_all(event, test2, add=True) + + unbind_all(event) + self.assertEqual(bind_all(event), '') + self.assertNotIn(event, bind_all()) + self.assertCommandExist(funcid) + self.assertCommandExist(funcid2) + + unbind_all(event) # idempotent + + def test_bind_all_rebind(self): + event = '' + bind_all = self.root.bind_all + unbind_all = self.root.unbind_all + self.assertNotIn(event, bind_all()) + self.assertEqual(bind_all(event), '') + self.addCleanup(unbind_all, event) + def test1(e): pass + def test2(e): pass + def test3(e): pass + + funcid = bind_all(event, test1) + funcid2 = bind_all(event, test2, add=True) + script = bind_all(event) + self.assertIn(funcid2, script) + self.assertIn(funcid, script) + self.assertCommandExist(funcid) + self.assertCommandExist(funcid2) + + funcid3 = bind_all(event, test3) + script = bind_all(event) + self.assertNotIn(funcid, script) + self.assertNotIn(funcid2, script) + self.assertIn(funcid3, script) + self.assertCommandExist(funcid) + self.assertCommandExist(funcid2) + self.assertCommandExist(funcid3) + + def test_bindtags(self): + f = self.frame + self.assertEqual(self.root.bindtags(), ('.', 'Tk', 'all')) + self.assertEqual(f.bindtags(), (str(f), 'Test', '.', 'all')) + f.bindtags(('a', 'b c')) + self.assertEqual(f.bindtags(), ('a', 'b c')) + + def test_bind_events(self): + event = '' + root = self.root + t = tkinter.Toplevel(root) + f = tkinter.Frame(t, class_='Test', width=150, height=100) + f.pack() + root.wait_visibility() # needed on Windows + root.update_idletasks() + self.addCleanup(root.unbind_class, 'Test', event) + self.addCleanup(root.unbind_class, 'Toplevel', event) + self.addCleanup(root.unbind_class, 'tag', event) + self.addCleanup(root.unbind_class, 'tag2', event) + self.addCleanup(root.unbind_all, event) + def test(what): + return lambda e: events.append((what, e.widget)) + + root.bind_all(event, test('all')) + root.bind_class('Test', event, test('frame class')) + root.bind_class('Toplevel', event, test('toplevel class')) + root.bind_class('tag', event, test('tag')) + root.bind_class('tag2', event, test('tag2')) + f.bind(event, test('frame')) + t.bind(event, test('toplevel')) + + events = [] + f.event_generate(event) + self.assertEqual(events, [ + ('frame', f), + ('frame class', f), + ('toplevel', f), + ('all', f), + ]) + + events = [] + t.event_generate(event) + self.assertEqual(events, [ + ('toplevel', t), + ('toplevel class', t), + ('all', t), + ]) + + f.bindtags(('tag', 'tag3')) + events = [] + f.event_generate(event) + self.assertEqual(events, [('tag', f)]) + + class DefaultRootTest(AbstractDefaultRootTest, unittest.TestCase): def test_default_root(self): @@ -426,5 +815,9 @@ def test_mainloop(self): self.assertRaises(RuntimeError, tkinter.mainloop) +def _info_commands(widget, pattern=None): + return widget.tk.splitlist(widget.tk.call('info', 'commands', pattern)) + + if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_tkinter/test_text.py b/Lib/test/test_tkinter/test_text.py index 328e4256ce0711..f809c4510e3a1f 100644 --- a/Lib/test/test_tkinter/test_text.py +++ b/Lib/test/test_tkinter/test_text.py @@ -10,6 +10,7 @@ class TextTest(AbstractTkTest, unittest.TestCase): def setUp(self): super().setUp() self.text = tkinter.Text(self.root) + self.text.pack() def test_debug(self): text = self.text @@ -41,8 +42,6 @@ def test_search(self): self.assertEqual(text.search('test', '1.0', 'end'), '1.3') def test_count(self): - # XXX Some assertions do not check against the intended result, - # but instead check the current result to prevent regression. text = self.text text.insert('1.0', 'Lorem ipsum dolor sit amet,\n' @@ -53,44 +52,27 @@ def test_count(self): options = ('chars', 'indices', 'lines', 'displaychars', 'displayindices', 'displaylines', 'xpixels', 'ypixels') - if self.wantobjects: - self.assertEqual(len(text.count('1.0', 'end', *options)), 8) - else: - text.count('1.0', 'end', *options) - self.assertEqual(text.count('1.0', 'end', 'chars', 'lines'), (124, 4) - if self.wantobjects else '124 4') - self.assertEqual(text.count('1.3', '4.5', 'chars', 'lines'), (92, 3) - if self.wantobjects else '92 3') - self.assertEqual(text.count('4.5', '1.3', 'chars', 'lines'), (-92, -3) - if self.wantobjects else '-92 -3') - self.assertEqual(text.count('1.3', '1.3', 'chars', 'lines'), (0, 0) - if self.wantobjects else '0 0') - self.assertEqual(text.count('1.0', 'end', 'lines'), (4,) - if self.wantobjects else ('4',)) - self.assertEqual(text.count('end', '1.0', 'lines'), (-4,) - if self.wantobjects else ('-4',)) - self.assertEqual(text.count('1.3', '1.5', 'lines'), None - if self.wantobjects else ('0',)) - self.assertEqual(text.count('1.3', '1.3', 'lines'), None - if self.wantobjects else ('0',)) - self.assertEqual(text.count('1.0', 'end'), (124,) # 'indices' by default - if self.wantobjects else ('124',)) + self.assertEqual(len(text.count('1.0', 'end', *options)), 8) + self.assertEqual(text.count('1.0', 'end', 'chars', 'lines'), (124, 4)) + self.assertEqual(text.count('1.3', '4.5', 'chars', 'lines'), (92, 3)) + self.assertEqual(text.count('4.5', '1.3', 'chars', 'lines'), (-92, -3)) + self.assertEqual(text.count('1.3', '1.3', 'chars', 'lines'), (0, 0)) + self.assertEqual(text.count('1.0', 'end', 'lines'), 4) + self.assertEqual(text.count('end', '1.0', 'lines'), -4) + self.assertEqual(text.count('1.3', '1.5', 'lines'), 0) + self.assertEqual(text.count('1.3', '1.3', 'lines'), 0) + self.assertEqual(text.count('1.0', 'end'), 124) # 'indices' by default + self.assertEqual(text.count('1.0', 'end', 'indices'), 124) self.assertRaises(tkinter.TclError, text.count, '1.0', 'end', 'spam') self.assertRaises(tkinter.TclError, text.count, '1.0', 'end', '-lines') - self.assertIsInstance(text.count('1.3', '1.5', 'ypixels'), tuple) - self.assertIsInstance(text.count('1.3', '1.5', 'update', 'ypixels'), int - if self.wantobjects else str) - self.assertEqual(text.count('1.3', '1.3', 'update', 'ypixels'), None - if self.wantobjects else '0') - self.assertEqual(text.count('1.3', '1.5', 'update', 'indices'), 2 - if self.wantobjects else '2') - self.assertEqual(text.count('1.3', '1.3', 'update', 'indices'), None - if self.wantobjects else '0') - self.assertEqual(text.count('1.3', '1.5', 'update'), (2,) - if self.wantobjects else ('2',)) - self.assertEqual(text.count('1.3', '1.3', 'update'), None - if self.wantobjects else ('0',)) + self.assertIsInstance(text.count('1.3', '1.5', 'ypixels'), int) + self.assertIsInstance(text.count('1.3', '1.5', 'update', 'ypixels'), int) + self.assertEqual(text.count('1.3', '1.3', 'update', 'ypixels'), 0) + self.assertEqual(text.count('1.3', '1.5', 'update', 'indices'), 2) + self.assertEqual(text.count('1.3', '1.3', 'update', 'indices'), 0) + self.assertEqual(text.count('1.3', '1.5', 'update'), 2) + self.assertEqual(text.count('1.3', '1.3', 'update'), 0) if __name__ == "__main__": diff --git a/Lib/test/test_tkinter/test_widgets.py b/Lib/test/test_tkinter/test_widgets.py index 34e67c0cbc44a3..d3f942db7baf9a 100644 --- a/Lib/test/test_tkinter/test_widgets.py +++ b/Lib/test/test_tkinter/test_widgets.py @@ -4,7 +4,7 @@ import os from test.support import requires -from test.test_tkinter.support import (requires_tcl, +from test.test_tkinter.support import (requires_tk, get_tk_patchlevel, widget_eq, AbstractDefaultRootTest) from test.test_tkinter.widget_tests import ( @@ -613,7 +613,7 @@ def test_configure_inactiveselectbackground(self): widget = self.create() self.checkColorParam(widget, 'inactiveselectbackground') - @requires_tcl(8, 6) + @requires_tk(8, 6) def test_configure_insertunfocussed(self): widget = self.create() self.checkEnumParam(widget, 'insertunfocussed', @@ -924,7 +924,7 @@ def test_coords(self): for i in range(4): self.assertIsInstance(coords[i], float) - @requires_tcl(8, 6) + @requires_tk(8, 6) def test_moveto(self): widget = self.create() i1 = widget.create_rectangle(1, 1, 20, 20, tags='group') @@ -969,7 +969,7 @@ def test_configure_activestyle(self): self.checkEnumParam(widget, 'activestyle', 'dotbox', 'none', 'underline') - test_configure_justify = requires_tcl(8, 6, 5)(StandardOptionsTests.test_configure_justify) + test_configure_justify = requires_tk(8, 6, 5)(StandardOptionsTests.test_configure_justify) def test_configure_listvariable(self): widget = self.create() @@ -1108,7 +1108,7 @@ def test_configure_digits(self): def test_configure_from(self): widget = self.create() - conv = float if get_tk_patchlevel() >= (8, 6, 10) else float_round + conv = float if get_tk_patchlevel(self.root) >= (8, 6, 10) else float_round self.checkFloatParam(widget, 'from', 100, 14.9, 15.1, conv=conv) def test_configure_label(self): @@ -1235,19 +1235,19 @@ def test_configure_opaqueresize(self): widget = self.create() self.checkBooleanParam(widget, 'opaqueresize') - @requires_tcl(8, 6, 5) + @requires_tk(8, 6, 5) def test_configure_proxybackground(self): widget = self.create() self.checkColorParam(widget, 'proxybackground') - @requires_tcl(8, 6, 5) + @requires_tk(8, 6, 5) def test_configure_proxyborderwidth(self): widget = self.create() self.checkPixelsParam(widget, 'proxyborderwidth', 0, 1.3, 2.9, 6, -2, '10p', conv=False) - @requires_tcl(8, 6, 5) + @requires_tk(8, 6, 5) def test_configure_proxyrelief(self): widget = self.create() self.checkReliefParam(widget, 'proxyrelief') diff --git a/Lib/test/test_tkinter/widget_tests.py b/Lib/test/test_tkinter/widget_tests.py index f60087a6e9f385..31f82f459beefd 100644 --- a/Lib/test/test_tkinter/widget_tests.py +++ b/Lib/test/test_tkinter/widget_tests.py @@ -1,7 +1,7 @@ # Common tests for test_tkinter/test_widgets.py and test_ttk/test_widgets.py import tkinter -from test.test_tkinter.support import (AbstractTkTest, tcl_version, +from test.test_tkinter.support import (AbstractTkTest, tk_version, pixels_conv, tcl_obj_eq) import test.support @@ -22,7 +22,7 @@ def scaling(self): return self._scaling def _str(self, value): - if not self._stringify and self.wantobjects and tcl_version >= (8, 6): + if not self._stringify and self.wantobjects and tk_version >= (8, 6): return value if isinstance(value, tuple): return ' '.join(map(self._str, value)) @@ -156,7 +156,7 @@ def checkReliefParam(self, widget, name): 'flat', 'groove', 'raised', 'ridge', 'solid', 'sunken') errmsg='bad relief "spam": must be '\ 'flat, groove, raised, ridge, solid, or sunken' - if tcl_version < (8, 6): + if tk_version < (8, 6): errmsg = None self.checkInvalidParam(widget, name, 'spam', errmsg=errmsg) diff --git a/Lib/test/test_tokenize.py b/Lib/test/test_tokenize.py index 7863e27fccd972..21e8637a7ca905 100644 --- a/Lib/test/test_tokenize.py +++ b/Lib/test/test_tokenize.py @@ -566,6 +566,65 @@ def test_string(self): OP '=' (3, 0) (3, 1) OP '}' (3, 1) (3, 2) FSTRING_END "'''" (3, 2) (3, 5) + """) + self.check_tokenize("""\ +f'''__{ + x:a +}__'''""", """\ + FSTRING_START "f'''" (1, 0) (1, 4) + FSTRING_MIDDLE '__' (1, 4) (1, 6) + OP '{' (1, 6) (1, 7) + NL '\\n' (1, 7) (1, 8) + NAME 'x' (2, 4) (2, 5) + OP ':' (2, 5) (2, 6) + FSTRING_MIDDLE 'a\\n' (2, 6) (3, 0) + OP '}' (3, 0) (3, 1) + FSTRING_MIDDLE '__' (3, 1) (3, 3) + FSTRING_END "'''" (3, 3) (3, 6) + """) + self.check_tokenize("""\ +f'''__{ + x:a + b + c + d +}__'''""", """\ + FSTRING_START "f'''" (1, 0) (1, 4) + FSTRING_MIDDLE '__' (1, 4) (1, 6) + OP '{' (1, 6) (1, 7) + NL '\\n' (1, 7) (1, 8) + NAME 'x' (2, 4) (2, 5) + OP ':' (2, 5) (2, 6) + FSTRING_MIDDLE 'a\\n b\\n c\\n d\\n' (2, 6) (6, 0) + OP '}' (6, 0) (6, 1) + FSTRING_MIDDLE '__' (6, 1) (6, 3) + FSTRING_END "'''" (6, 3) (6, 6) + """) + self.check_tokenize("""\ +f'__{ + x:d +}__'""", """\ + FSTRING_START "f'" (1, 0) (1, 2) + FSTRING_MIDDLE '__' (1, 2) (1, 4) + OP '{' (1, 4) (1, 5) + NL '\\n' (1, 5) (1, 6) + NAME 'x' (2, 4) (2, 5) + OP ':' (2, 5) (2, 6) + FSTRING_MIDDLE 'd' (2, 6) (2, 7) + NL '\\n' (2, 7) (2, 8) + OP '}' (3, 0) (3, 1) + FSTRING_MIDDLE '__' (3, 1) (3, 3) + FSTRING_END "'" (3, 3) (3, 4) + """) + + self.check_tokenize("""\ + '''Autorzy, którzy tÄ… jednostkÄ™ majÄ… wpisani jako AKTUALNA -- czyli + aktualni pracownicy, obecni pracownicy''' +""", """\ + INDENT ' ' (1, 0) (1, 4) + STRING "'''Autorzy, którzy tÄ… jednostkÄ™ majÄ… wpisani jako AKTUALNA -- czyli\\n aktualni pracownicy, obecni pracownicy'''" (1, 4) (2, 45) + NEWLINE '\\n' (2, 45) (2, 46) + DEDENT '' (3, 0) (3, 0) """) def test_function(self): @@ -1200,7 +1259,7 @@ class TestTokenizerAdheresToPep0263(TestCase): """ def _testFile(self, filename): - path = os.path.join(os.path.dirname(__file__), filename) + path = os.path.join(os.path.dirname(__file__), 'tokenizedata', filename) with open(path, 'rb') as f: TestRoundtrip.check_roundtrip(self, f) @@ -1386,7 +1445,7 @@ def test_cookie_second_line_empty_first_line(self): self.assertEqual(consumed_lines, expected) def test_latin1_normalization(self): - # See get_normal_name() in tokenizer.c. + # See get_normal_name() in Parser/tokenizer/helpers.c. encodings = ("latin-1", "iso-8859-1", "iso-latin-1", "latin-1-unix", "iso-8859-1-unix", "iso-latin-1-mac") for encoding in encodings: @@ -1411,7 +1470,7 @@ def test_syntaxerror_latin1(self): def test_utf8_normalization(self): - # See get_normal_name() in tokenizer.c. + # See get_normal_name() in Parser/tokenizer/helpers.c. encodings = ("utf-8", "utf-8-mac", "utf-8-unix") for encoding in encodings: for rep in ("-", "_"): @@ -1794,7 +1853,7 @@ def test_roundtrip(self): self.check_roundtrip("if x == 1 : \n" " print(x)\n") - fn = support.findfile("tokenize_tests.txt") + fn = support.findfile("tokenize_tests.txt", subdir="tokenizedata") with open(fn, 'rb') as f: self.check_roundtrip(f) self.check_roundtrip("if x == 1:\n" @@ -1849,23 +1908,12 @@ def test_random_files(self): # pass the '-ucpu' option to process the full directory. import glob, random - fn = support.findfile("tokenize_tests.txt") - tempdir = os.path.dirname(fn) or os.curdir + tempdir = os.path.dirname(__file__) or os.curdir testfiles = glob.glob(os.path.join(glob.escape(tempdir), "test*.py")) - # Tokenize is broken on test_pep3131.py because regular expressions are - # broken on the obscure unicode identifiers in it. *sigh* - # With roundtrip extended to test the 5-tuple mode of untokenize, - # 7 more testfiles fail. Remove them also until the failure is diagnosed. - - testfiles.remove(os.path.join(tempdir, "test_unicode_identifiers.py")) - - # TODO: Remove this once we can unparse PEP 701 syntax + # TODO: Remove this once we can untokenize PEP 701 syntax testfiles.remove(os.path.join(tempdir, "test_fstring.py")) - for f in ('buffer', 'builtin', 'fileio', 'inspect', 'os', 'platform', 'sys'): - testfiles.remove(os.path.join(tempdir, "test_%s.py") % f) - if not support.is_resource_enabled("cpu"): testfiles = random.sample(testfiles, 10) @@ -2278,6 +2326,54 @@ def test_string(self): FSTRING_START \'f"\' (1, 0) (1, 2) FSTRING_MIDDLE 'hola\\\\\\\\\\\\r\\\\ndfgf' (1, 2) (1, 16) FSTRING_END \'"\' (1, 16) (1, 17) + """) + + self.check_tokenize("""\ +f'''__{ + x:a +}__'''""", """\ + FSTRING_START "f'''" (1, 0) (1, 4) + FSTRING_MIDDLE '__' (1, 4) (1, 6) + LBRACE '{' (1, 6) (1, 7) + NAME 'x' (2, 4) (2, 5) + COLON ':' (2, 5) (2, 6) + FSTRING_MIDDLE 'a\\n' (2, 6) (3, 0) + RBRACE '}' (3, 0) (3, 1) + FSTRING_MIDDLE '__' (3, 1) (3, 3) + FSTRING_END "'''" (3, 3) (3, 6) + """) + + self.check_tokenize("""\ +f'''__{ + x:a + b + c + d +}__'''""", """\ + FSTRING_START "f'''" (1, 0) (1, 4) + FSTRING_MIDDLE '__' (1, 4) (1, 6) + LBRACE '{' (1, 6) (1, 7) + NAME 'x' (2, 4) (2, 5) + COLON ':' (2, 5) (2, 6) + FSTRING_MIDDLE 'a\\n b\\n c\\n d\\n' (2, 6) (6, 0) + RBRACE '}' (6, 0) (6, 1) + FSTRING_MIDDLE '__' (6, 1) (6, 3) + FSTRING_END "'''" (6, 3) (6, 6) + """) + + self.check_tokenize("""\ +f'__{ + x:d +}__'""", """\ + FSTRING_START "f'" (1, 0) (1, 2) + FSTRING_MIDDLE '__' (1, 2) (1, 4) + LBRACE '{' (1, 4) (1, 5) + NAME 'x' (2, 4) (2, 5) + COLON ':' (2, 5) (2, 6) + FSTRING_MIDDLE 'd' (2, 6) (2, 7) + RBRACE '}' (3, 0) (3, 1) + FSTRING_MIDDLE '__' (3, 1) (3, 3) + FSTRING_END "'" (3, 3) (3, 4) """) def test_function(self): diff --git a/Lib/test/test_tomllib/test_misc.py b/Lib/test/test_tomllib/test_misc.py index a477a219fd9ebd..9e677a337a2835 100644 --- a/Lib/test/test_tomllib/test_misc.py +++ b/Lib/test/test_tomllib/test_misc.py @@ -9,6 +9,7 @@ import sys import tempfile import unittest +from test import support from . import tomllib @@ -92,13 +93,23 @@ def test_deepcopy(self): self.assertEqual(obj_copy, expected_obj) def test_inline_array_recursion_limit(self): - # 465 with default recursion limit - nest_count = int(sys.getrecursionlimit() * 0.465) - recursive_array_toml = "arr = " + nest_count * "[" + nest_count * "]" - tomllib.loads(recursive_array_toml) + with support.infinite_recursion(max_depth=100): + available = support.get_recursion_available() + nest_count = (available // 2) - 2 + # Add details if the test fails + with self.subTest(limit=sys.getrecursionlimit(), + available=available, + nest_count=nest_count): + recursive_array_toml = "arr = " + nest_count * "[" + nest_count * "]" + tomllib.loads(recursive_array_toml) def test_inline_table_recursion_limit(self): - # 310 with default recursion limit - nest_count = int(sys.getrecursionlimit() * 0.31) - recursive_table_toml = nest_count * "key = {" + nest_count * "}" - tomllib.loads(recursive_table_toml) + with support.infinite_recursion(max_depth=100): + available = support.get_recursion_available() + nest_count = (available // 3) - 1 + # Add details if the test fails + with self.subTest(limit=sys.getrecursionlimit(), + available=available, + nest_count=nest_count): + recursive_table_toml = nest_count * "key = {" + nest_count * "}" + tomllib.loads(recursive_table_toml) diff --git a/Lib/test/test_tools/__init__.py b/Lib/test/test_tools/__init__.py index 2102b9fceff568..c4395c7c0ad0c9 100644 --- a/Lib/test/test_tools/__init__.py +++ b/Lib/test/test_tools/__init__.py @@ -7,12 +7,6 @@ from test.support import import_helper -if support.check_sanitizer(address=True, memory=True): - # bpo-46633: Skip the test because it is too slow when Python is built - # with ASAN/MSAN: between 5 and 20 minutes on GitHub Actions. - raise unittest.SkipTest("test too slow on ASAN/MSAN build") - - if not support.has_subprocess_support: raise unittest.SkipTest("test module requires subprocess") diff --git a/Lib/test/test_tools/test_freeze.py b/Lib/test/test_tools/test_freeze.py index 2ba36ca208f967..0e7ed67de71067 100644 --- a/Lib/test/test_tools/test_freeze.py +++ b/Lib/test/test_tools/test_freeze.py @@ -14,9 +14,16 @@ @support.requires_zlib() @unittest.skipIf(sys.platform.startswith('win'), 'not supported on Windows') +@unittest.skipIf(sys.platform == 'darwin' and sys._framework, + 'not supported for frameworks builds on macOS') @support.skip_if_buildbot('not all buildbots have enough space') +# gh-103053: Skip test if Python is built with Profile Guided Optimization +# (PGO), since the test is just too slow in this case. +@unittest.skipIf(support.check_cflags_pgo(), + 'test is too slow with PGO') class TestFreeze(unittest.TestCase): + @support.requires_resource('cpu') # Building Python is slow def test_freeze_simple_script(self): script = textwrap.dedent(""" import sys diff --git a/Lib/test/test_tools/test_makeunicodedata.py b/Lib/test/test_tools/test_makeunicodedata.py new file mode 100644 index 00000000000000..f31375117e2e92 --- /dev/null +++ b/Lib/test/test_tools/test_makeunicodedata.py @@ -0,0 +1,122 @@ +import unittest +from test.test_tools import skip_if_missing, imports_under_tool +from test import support +from test.support.hypothesis_helper import hypothesis + +st = hypothesis.strategies +given = hypothesis.given +example = hypothesis.example + + +skip_if_missing("unicode") +with imports_under_tool("unicode"): + from dawg import Dawg, build_compression_dawg, lookup, inverse_lookup + + +@st.composite +def char_name_db(draw, min_length=1, max_length=30): + m = draw(st.integers(min_value=min_length, max_value=max_length)) + names = draw( + st.sets(st.text("abcd", min_size=1, max_size=10), min_size=m, max_size=m) + ) + characters = draw(st.sets(st.characters(), min_size=m, max_size=m)) + return list(zip(names, characters)) + + +class TestDawg(unittest.TestCase): + """Tests for the directed acyclic word graph data structure that is used + to store the unicode character names in unicodedata. Tests ported from PyPy + """ + + def test_dawg_direct_simple(self): + dawg = Dawg() + dawg.insert("a", -4) + dawg.insert("c", -2) + dawg.insert("cat", -1) + dawg.insert("catarr", 0) + dawg.insert("catnip", 1) + dawg.insert("zcatnip", 5) + packed, data, inverse = dawg.finish() + + self.assertEqual(lookup(packed, data, b"a"), -4) + self.assertEqual(lookup(packed, data, b"c"), -2) + self.assertEqual(lookup(packed, data, b"cat"), -1) + self.assertEqual(lookup(packed, data, b"catarr"), 0) + self.assertEqual(lookup(packed, data, b"catnip"), 1) + self.assertEqual(lookup(packed, data, b"zcatnip"), 5) + self.assertRaises(KeyError, lookup, packed, data, b"b") + self.assertRaises(KeyError, lookup, packed, data, b"catni") + self.assertRaises(KeyError, lookup, packed, data, b"catnipp") + + self.assertEqual(inverse_lookup(packed, inverse, -4), b"a") + self.assertEqual(inverse_lookup(packed, inverse, -2), b"c") + self.assertEqual(inverse_lookup(packed, inverse, -1), b"cat") + self.assertEqual(inverse_lookup(packed, inverse, 0), b"catarr") + self.assertEqual(inverse_lookup(packed, inverse, 1), b"catnip") + self.assertEqual(inverse_lookup(packed, inverse, 5), b"zcatnip") + self.assertRaises(KeyError, inverse_lookup, packed, inverse, 12) + + def test_forbid_empty_dawg(self): + dawg = Dawg() + self.assertRaises(ValueError, dawg.finish) + + @given(char_name_db()) + @example([("abc", "a"), ("abd", "b")]) + @example( + [ + ("bab", "1"), + ("a", ":"), + ("ad", "@"), + ("b", "<"), + ("aacc", "?"), + ("dab", "D"), + ("aa", "0"), + ("ab", "F"), + ("aaa", "7"), + ("cbd", "="), + ("abad", ";"), + ("ac", "B"), + ("abb", "4"), + ("bb", "2"), + ("aab", "9"), + ("caaaaba", "E"), + ("ca", ">"), + ("bbaaa", "5"), + ("d", "3"), + ("baac", "8"), + ("c", "6"), + ("ba", "A"), + ] + ) + @example( + [ + ("bcdac", "9"), + ("acc", "g"), + ("d", "d"), + ("daabdda", "0"), + ("aba", ";"), + ("c", "6"), + ("aa", "7"), + ("abbd", "c"), + ("badbd", "?"), + ("bbd", "f"), + ("cc", "@"), + ("bb", "8"), + ("daca", ">"), + ("ba", ":"), + ("baac", "3"), + ("dbdddac", "a"), + ("a", "2"), + ("cabd", "b"), + ("b", "="), + ("abd", "4"), + ("adcbd", "5"), + ("abc", "e"), + ("ab", "1"), + ] + ) + def test_dawg(self, data): + # suppress debug prints + with support.captured_stdout() as output: + # it's enough to build it, building will also check the result + build_compression_dawg(data) diff --git a/Lib/test/test_tools/test_reindent.py b/Lib/test/test_tools/test_reindent.py index 3b0c793a38e4da..64e31c2b7703c0 100644 --- a/Lib/test/test_tools/test_reindent.py +++ b/Lib/test/test_tools/test_reindent.py @@ -25,7 +25,7 @@ def test_help(self): self.assertGreater(err, b'') def test_reindent_file_with_bad_encoding(self): - bad_coding_path = findfile('bad_coding.py') + bad_coding_path = findfile('bad_coding.py', subdir='tokenizedata') rc, out, err = assert_python_ok(self.script, '-r', bad_coding_path) self.assertEqual(out, b'') self.assertNotEqual(err, b'') diff --git a/Lib/test/test_trace.py b/Lib/test/test_trace.py index 73339ebdb7c4e9..c1e289bcaff9e5 100644 --- a/Lib/test/test_trace.py +++ b/Lib/test/test_trace.py @@ -1,7 +1,7 @@ import os from pickle import dump import sys -from test.support import captured_stdout +from test.support import captured_stdout, requires_resource from test.support.os_helper import (TESTFN, rmtree, unlink) from test.support.script_helper import assert_python_ok, assert_python_failure import textwrap @@ -360,13 +360,19 @@ def tearDown(self): rmtree(TESTFN) unlink(TESTFN) - def _coverage(self, tracer, - cmd='import test.support, test.test_pprint;' - 'test.support.run_unittest(test.test_pprint.QueryTestCase)'): + DEFAULT_SCRIPT = '''if True: + import unittest + from test.test_pprint import QueryTestCase + loader = unittest.TestLoader() + tests = loader.loadTestsFromTestCase(QueryTestCase) + tests(unittest.TestResult()) + ''' + def _coverage(self, tracer, cmd=DEFAULT_SCRIPT): tracer.run(cmd) r = tracer.results() r.write_results(show_missing=True, summary=True, coverdir=TESTFN) + @requires_resource('cpu') def test_coverage(self): tracer = trace.Trace(trace=0, count=1) with captured_stdout() as stdout: diff --git a/Lib/test/test_traceback.py b/Lib/test/test_traceback.py index 7c6fdbf762921f..a6708119b81191 100644 --- a/Lib/test/test_traceback.py +++ b/Lib/test/test_traceback.py @@ -8,6 +8,7 @@ import inspect import builtins import unittest +import unittest.mock import re import tempfile import random @@ -24,6 +25,7 @@ import json import textwrap import traceback +import contextlib from functools import partial from pathlib import Path @@ -41,6 +43,14 @@ class TracebackCases(unittest.TestCase): # For now, a very minimal set of tests. I want to be sure that # formatting of SyntaxErrors works based on changes for 2.1. + def setUp(self): + super().setUp() + self.colorize = traceback._COLORIZE + traceback._COLORIZE = False + + def tearDown(self): + super().tearDown() + traceback._COLORIZE = self.colorize def get_exception_format(self, func, exc): try: @@ -215,6 +225,155 @@ def __str__(self): str_name = '.'.join([X.__module__, X.__qualname__]) self.assertEqual(err[0], "%s: %s\n" % (str_name, str_value)) + def test_format_exception_group_without_show_group(self): + eg = ExceptionGroup('A', [ValueError('B')]) + err = traceback.format_exception_only(eg) + self.assertEqual(err, ['ExceptionGroup: A (1 sub-exception)\n']) + + def test_format_exception_group(self): + eg = ExceptionGroup('A', [ValueError('B')]) + err = traceback.format_exception_only(eg, show_group=True) + self.assertEqual(err, [ + 'ExceptionGroup: A (1 sub-exception)\n', + ' ValueError: B\n', + ]) + + def test_format_base_exception_group(self): + eg = BaseExceptionGroup('A', [BaseException('B')]) + err = traceback.format_exception_only(eg, show_group=True) + self.assertEqual(err, [ + 'BaseExceptionGroup: A (1 sub-exception)\n', + ' BaseException: B\n', + ]) + + def test_format_exception_group_with_note(self): + exc = ValueError('B') + exc.add_note('Note') + eg = ExceptionGroup('A', [exc]) + err = traceback.format_exception_only(eg, show_group=True) + self.assertEqual(err, [ + 'ExceptionGroup: A (1 sub-exception)\n', + ' ValueError: B\n', + ' Note\n', + ]) + + def test_format_exception_group_explicit_class(self): + eg = ExceptionGroup('A', [ValueError('B')]) + err = traceback.format_exception_only(ExceptionGroup, eg, show_group=True) + self.assertEqual(err, [ + 'ExceptionGroup: A (1 sub-exception)\n', + ' ValueError: B\n', + ]) + + def test_format_exception_group_multiple_exceptions(self): + eg = ExceptionGroup('A', [ValueError('B'), TypeError('C')]) + err = traceback.format_exception_only(eg, show_group=True) + self.assertEqual(err, [ + 'ExceptionGroup: A (2 sub-exceptions)\n', + ' ValueError: B\n', + ' TypeError: C\n', + ]) + + def test_format_exception_group_multiline_messages(self): + eg = ExceptionGroup('A\n1', [ValueError('B\n2')]) + err = traceback.format_exception_only(eg, show_group=True) + self.assertEqual(err, [ + 'ExceptionGroup: A\n1 (1 sub-exception)\n', + ' ValueError: B\n', + ' 2\n', + ]) + + def test_format_exception_group_multiline2_messages(self): + exc = ValueError('B\n\n2\n') + exc.add_note('\nC\n\n3') + eg = ExceptionGroup('A\n\n1\n', [exc, IndexError('D')]) + err = traceback.format_exception_only(eg, show_group=True) + self.assertEqual(err, [ + 'ExceptionGroup: A\n\n1\n (2 sub-exceptions)\n', + ' ValueError: B\n', + ' \n', + ' 2\n', + ' \n', + ' \n', # first char of `note` + ' C\n', + ' \n', + ' 3\n', # note ends + ' IndexError: D\n', + ]) + + def test_format_exception_group_syntax_error(self): + exc = SyntaxError("error", ("x.py", 23, None, "bad syntax")) + eg = ExceptionGroup('A\n1', [exc]) + err = traceback.format_exception_only(eg, show_group=True) + self.assertEqual(err, [ + 'ExceptionGroup: A\n1 (1 sub-exception)\n', + ' File "x.py", line 23\n', + ' bad syntax\n', + ' SyntaxError: error\n', + ]) + + def test_format_exception_group_nested_with_notes(self): + exc = IndexError('D') + exc.add_note('Note\nmultiline') + eg = ExceptionGroup('A', [ + ValueError('B'), + ExceptionGroup('C', [exc, LookupError('E')]), + TypeError('F'), + ]) + err = traceback.format_exception_only(eg, show_group=True) + self.assertEqual(err, [ + 'ExceptionGroup: A (3 sub-exceptions)\n', + ' ValueError: B\n', + ' ExceptionGroup: C (2 sub-exceptions)\n', + ' IndexError: D\n', + ' Note\n', + ' multiline\n', + ' LookupError: E\n', + ' TypeError: F\n', + ]) + + def test_format_exception_group_with_tracebacks(self): + def f(): + try: + 1 / 0 + except ZeroDivisionError as e: + return e + + def g(): + try: + raise TypeError('g') + except TypeError as e: + return e + + eg = ExceptionGroup('A', [ + f(), + ExceptionGroup('B', [g()]), + ]) + err = traceback.format_exception_only(eg, show_group=True) + self.assertEqual(err, [ + 'ExceptionGroup: A (2 sub-exceptions)\n', + ' ZeroDivisionError: division by zero\n', + ' ExceptionGroup: B (1 sub-exception)\n', + ' TypeError: g\n', + ]) + + def test_format_exception_group_with_cause(self): + def f(): + try: + try: + 1 / 0 + except ZeroDivisionError: + raise ValueError(0) + except Exception as e: + return e + + eg = ExceptionGroup('A', [f()]) + err = traceback.format_exception_only(eg, show_group=True) + self.assertEqual(err, [ + 'ExceptionGroup: A (1 sub-exception)\n', + ' ValueError: 0\n', + ]) + @requires_subprocess() def test_encoded_file(self): # Test that tracebacks are correctly printed for encoded source files: @@ -313,6 +472,8 @@ def __del__(self): rc, stdout, stderr = assert_python_ok('-c', code) expected = [b'Traceback (most recent call last):', b' File "", line 8, in __init__', + b' x = 1 / 0', + b' ^^^^^', b'ZeroDivisionError: division by zero'] self.assertEqual(stderr.splitlines(), expected) @@ -370,7 +531,7 @@ def test_signatures(self): self.assertEqual( str(inspect.signature(traceback.print_exception)), ('(exc, /, value=, tb=, ' - 'limit=None, file=None, chain=True)')) + 'limit=None, file=None, chain=True, **kwargs)')) self.assertEqual( str(inspect.signature(traceback.format_exception)), @@ -379,7 +540,7 @@ def test_signatures(self): self.assertEqual( str(inspect.signature(traceback.format_exception_only)), - '(exc, /, value=)') + '(exc, /, value=, *, show_group=False)') class PurePythonExceptionFormattingMixin: @@ -427,6 +588,7 @@ def f(): 'Traceback (most recent call last):\n' f' File "{__file__}", line {self.callable_line}, in get_exception\n' ' callable()\n' + ' ~~~~~~~~^^\n' f' File "{__file__}", line {lineno_f+1}, in f\n' ' if True: raise ValueError("basic caret tests")\n' ' ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n' @@ -445,6 +607,7 @@ def f_with_unicode(): 'Traceback (most recent call last):\n' f' File "{__file__}", line {self.callable_line}, in get_exception\n' ' callable()\n' + ' ~~~~~~~~^^\n' f' File "{__file__}", line {lineno_f+1}, in f_with_unicode\n' ' if True: raise ValueError("Ĥellö Wörld")\n' ' ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n' @@ -462,6 +625,7 @@ def foo(a: THIS_DOES_NOT_EXIST ) -> int: 'Traceback (most recent call last):\n' f' File "{__file__}", line {self.callable_line}, in get_exception\n' ' callable()\n' + ' ~~~~~~~~^^\n' f' File "{__file__}", line {lineno_f+1}, in f_with_type\n' ' def foo(a: THIS_DOES_NOT_EXIST ) -> int:\n' ' ^^^^^^^^^^^^^^^^^^^\n' @@ -482,9 +646,14 @@ def f_with_multiline(): 'Traceback (most recent call last):\n' f' File "{__file__}", line {self.callable_line}, in get_exception\n' ' callable()\n' + ' ~~~~~~~~^^\n' f' File "{__file__}", line {lineno_f+1}, in f_with_multiline\n' ' if True: raise ValueError(\n' - ' ^^^^^^^^^^^^^^^^^' + ' ^^^^^^^^^^^^^^^^^\n' + ' "error over multiple lines"\n' + ' ^^^^^^^^^^^^^^^^^^^^^^^^^^^\n' + ' )\n' + ' ^' ) result_lines = self.get_exception(f_with_multiline) self.assertEqual(result_lines, expected_f.splitlines()) @@ -513,9 +682,10 @@ def f_with_multiline(): 'Traceback (most recent call last):\n' f' File "{__file__}", line {self.callable_line}, in get_exception\n' ' callable()\n' + ' ~~~~~~~~^^\n' f' File "{__file__}", line {lineno_f+2}, in f_with_multiline\n' ' return compile(code, "?", "exec")\n' - ' ^^^^^^^^^^^^^^^^^^^^^^^^^^\n' + ' ~~~~~~~^^^^^^^^^^^^^^^^^^^\n' ' File "?", line 7\n' ' foo(a, z\n' ' ^' @@ -538,9 +708,12 @@ def f_with_multiline(): 'Traceback (most recent call last):\n' f' File "{__file__}", line {self.callable_line}, in get_exception\n' ' callable()\n' + ' ~~~~~~~~^^\n' f' File "{__file__}", line {lineno_f+2}, in f_with_multiline\n' ' 2 + 1 /\n' - ' ^^^' + ' ~~^\n' + ' 0\n' + ' ~' ) result_lines = self.get_exception(f_with_multiline) self.assertEqual(result_lines, expected_f.splitlines()) @@ -555,6 +728,7 @@ def f_with_binary_operator(): 'Traceback (most recent call last):\n' f' File "{__file__}", line {self.callable_line}, in get_exception\n' ' callable()\n' + ' ~~~~~~~~^^\n' f' File "{__file__}", line {lineno_f+2}, in f_with_binary_operator\n' ' return 10 + divisor / 0 + 30\n' ' ~~~~~~~~^~~\n' @@ -572,6 +746,7 @@ def f_with_binary_operator(): 'Traceback (most recent call last):\n' f' File "{__file__}", line {self.callable_line}, in get_exception\n' ' callable()\n' + ' ~~~~~~~~^^\n' f' File "{__file__}", line {lineno_f+2}, in f_with_binary_operator\n' ' return 10 + áóí / 0 + 30\n' ' ~~~~^~~\n' @@ -589,6 +764,7 @@ def f_with_binary_operator(): 'Traceback (most recent call last):\n' f' File "{__file__}", line {self.callable_line}, in get_exception\n' ' callable()\n' + ' ~~~~~~~~^^\n' f' File "{__file__}", line {lineno_f+2}, in f_with_binary_operator\n' ' return 10 + divisor // 0 + 30\n' ' ~~~~~~~~^^~~\n' @@ -596,6 +772,110 @@ def f_with_binary_operator(): result_lines = self.get_exception(f_with_binary_operator) self.assertEqual(result_lines, expected_error.splitlines()) + def test_caret_for_binary_operators_with_spaces_and_parenthesis(self): + def f_with_binary_operator(): + a = 1 + b = "" + return ( a ) +b + + lineno_f = f_with_binary_operator.__code__.co_firstlineno + expected_error = ( + 'Traceback (most recent call last):\n' + f' File "{__file__}", line {self.callable_line}, in get_exception\n' + ' callable()\n' + ' ~~~~~~~~^^\n' + f' File "{__file__}", line {lineno_f+3}, in f_with_binary_operator\n' + ' return ( a ) +b\n' + ' ~~~~~~~~~~^~\n' + ) + result_lines = self.get_exception(f_with_binary_operator) + self.assertEqual(result_lines, expected_error.splitlines()) + + def test_caret_for_binary_operators_multiline(self): + def f_with_binary_operator(): + b = 1 + c = "" + a = b \ + +\ + c # test + return a + + lineno_f = f_with_binary_operator.__code__.co_firstlineno + expected_error = ( + 'Traceback (most recent call last):\n' + f' File "{__file__}", line {self.callable_line}, in get_exception\n' + ' callable()\n' + ' ~~~~~~~~^^\n' + f' File "{__file__}", line {lineno_f+3}, in f_with_binary_operator\n' + ' a = b \\\n' + ' ~~~~~~\n' + ' +\\\n' + ' ^~\n' + ' c # test\n' + ' ~\n' + ) + result_lines = self.get_exception(f_with_binary_operator) + self.assertEqual(result_lines, expected_error.splitlines()) + + def test_caret_for_binary_operators_multiline_two_char(self): + def f_with_binary_operator(): + b = 1 + c = "" + a = ( + (b # test + + ) \ + # + + << (c # test + \ + ) # test + ) + return a + + lineno_f = f_with_binary_operator.__code__.co_firstlineno + expected_error = ( + 'Traceback (most recent call last):\n' + f' File "{__file__}", line {self.callable_line}, in get_exception\n' + ' callable()\n' + ' ~~~~~~~~^^\n' + f' File "{__file__}", line {lineno_f+4}, in f_with_binary_operator\n' + ' (b # test +\n' + ' ~~~~~~~~~~~~\n' + ' ) \\\n' + ' ~~~~\n' + ' # +\n' + ' ~~~\n' + ' << (c # test\n' + ' ^^~~~~~~~~~~~\n' + ' \\\n' + ' ~\n' + ' ) # test\n' + ' ~\n' + ) + result_lines = self.get_exception(f_with_binary_operator) + self.assertEqual(result_lines, expected_error.splitlines()) + + def test_caret_for_binary_operators_multiline_with_unicode(self): + def f_with_binary_operator(): + b = 1 + a = ("ááá" + + "áá") + b + return a + + lineno_f = f_with_binary_operator.__code__.co_firstlineno + expected_error = ( + 'Traceback (most recent call last):\n' + f' File "{__file__}", line {self.callable_line}, in get_exception\n' + ' callable()\n' + ' ~~~~~~~~^^\n' + f' File "{__file__}", line {lineno_f+2}, in f_with_binary_operator\n' + ' a = ("ááá" +\n' + ' ~~~~~~~~\n' + ' "áá") + b\n' + ' ~~~~~~^~~\n' + ) + result_lines = self.get_exception(f_with_binary_operator) + self.assertEqual(result_lines, expected_error.splitlines()) + def test_caret_for_subscript(self): def f_with_subscript(): some_dict = {'x': {'y': None}} @@ -606,6 +886,7 @@ def f_with_subscript(): 'Traceback (most recent call last):\n' f' File "{__file__}", line {self.callable_line}, in get_exception\n' ' callable()\n' + ' ~~~~~~~~^^\n' f' File "{__file__}", line {lineno_f+2}, in f_with_subscript\n' " return some_dict['x']['y']['z']\n" ' ~~~~~~~~~~~~~~~~~~~^^^^^\n' @@ -623,6 +904,7 @@ def f_with_subscript(): 'Traceback (most recent call last):\n' f' File "{__file__}", line {self.callable_line}, in get_exception\n' ' callable()\n' + ' ~~~~~~~~^^\n' f' File "{__file__}", line {lineno_f+2}, in f_with_subscript\n' " return some_dict['ó']['á']['í']['beta']\n" ' ~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^\n' @@ -630,6 +912,245 @@ def f_with_subscript(): result_lines = self.get_exception(f_with_subscript) self.assertEqual(result_lines, expected_error.splitlines()) + def test_caret_for_subscript_with_spaces_and_parenthesis(self): + def f_with_binary_operator(): + a = [] + b = c = 1 + return b [ a ] + c + + lineno_f = f_with_binary_operator.__code__.co_firstlineno + expected_error = ( + 'Traceback (most recent call last):\n' + f' File "{__file__}", line {self.callable_line}, in get_exception\n' + ' callable()\n' + ' ~~~~~~~~^^\n' + f' File "{__file__}", line {lineno_f+3}, in f_with_binary_operator\n' + ' return b [ a ] + c\n' + ' ~~~~~~^^^^^^^^^\n' + ) + result_lines = self.get_exception(f_with_binary_operator) + self.assertEqual(result_lines, expected_error.splitlines()) + + def test_caret_for_subscript_multiline(self): + def f_with_subscript(): + bbbbb = {} + ccc = 1 + ddd = 2 + b = bbbbb \ + [ ccc # test + + + ddd \ + + ] # test + return b + + lineno_f = f_with_subscript.__code__.co_firstlineno + expected_error = ( + 'Traceback (most recent call last):\n' + f' File "{__file__}", line {self.callable_line}, in get_exception\n' + ' callable()\n' + ' ~~~~~~~~^^\n' + f' File "{__file__}", line {lineno_f+4}, in f_with_subscript\n' + ' b = bbbbb \\\n' + ' ~~~~~~~\n' + ' [ ccc # test\n' + ' ^^^^^^^^^^^^^\n' + ' \n' + ' \n' + ' + ddd \\\n' + ' ^^^^^^^^\n' + ' \n' + ' \n' + ' ] # test\n' + ' ^\n' + ) + result_lines = self.get_exception(f_with_subscript) + self.assertEqual(result_lines, expected_error.splitlines()) + + def test_caret_for_call(self): + def f_with_call(): + def f1(a): + def f2(b): + raise RuntimeError("fail") + return f2 + return f1("x")("y") + + lineno_f = f_with_call.__code__.co_firstlineno + expected_error = ( + 'Traceback (most recent call last):\n' + f' File "{__file__}", line {self.callable_line}, in get_exception\n' + ' callable()\n' + ' ~~~~~~~~^^\n' + f' File "{__file__}", line {lineno_f+5}, in f_with_call\n' + ' return f1("x")("y")\n' + ' ~~~~~~~^^^^^\n' + f' File "{__file__}", line {lineno_f+3}, in f2\n' + ' raise RuntimeError("fail")\n' + ) + result_lines = self.get_exception(f_with_call) + self.assertEqual(result_lines, expected_error.splitlines()) + + def test_caret_for_call_unicode(self): + def f_with_call(): + def f1(a): + def f2(b): + raise RuntimeError("fail") + return f2 + return f1("ó")("á") + + lineno_f = f_with_call.__code__.co_firstlineno + expected_error = ( + 'Traceback (most recent call last):\n' + f' File "{__file__}", line {self.callable_line}, in get_exception\n' + ' callable()\n' + ' ~~~~~~~~^^\n' + f' File "{__file__}", line {lineno_f+5}, in f_with_call\n' + ' return f1("ó")("á")\n' + ' ~~~~~~~^^^^^\n' + f' File "{__file__}", line {lineno_f+3}, in f2\n' + ' raise RuntimeError("fail")\n' + ) + result_lines = self.get_exception(f_with_call) + self.assertEqual(result_lines, expected_error.splitlines()) + + def test_caret_for_call_with_spaces_and_parenthesis(self): + def f_with_binary_operator(): + def f(a): + raise RuntimeError("fail") + return f ( "x" ) + 2 + + lineno_f = f_with_binary_operator.__code__.co_firstlineno + expected_error = ( + 'Traceback (most recent call last):\n' + f' File "{__file__}", line {self.callable_line}, in get_exception\n' + ' callable()\n' + ' ~~~~~~~~^^\n' + f' File "{__file__}", line {lineno_f+3}, in f_with_binary_operator\n' + ' return f ( "x" ) + 2\n' + ' ~~~~~~^^^^^^^^^^^\n' + f' File "{__file__}", line {lineno_f+2}, in f\n' + ' raise RuntimeError("fail")\n' + ) + result_lines = self.get_exception(f_with_binary_operator) + self.assertEqual(result_lines, expected_error.splitlines()) + + def test_caret_for_call_multiline(self): + def f_with_call(): + class C: + def y(self, a): + def f(b): + raise RuntimeError("fail") + return f + def g(x): + return C() + a = (g(1).y)( + 2 + )(3)(4) + return a + + lineno_f = f_with_call.__code__.co_firstlineno + expected_error = ( + 'Traceback (most recent call last):\n' + f' File "{__file__}", line {self.callable_line}, in get_exception\n' + ' callable()\n' + ' ~~~~~~~~^^\n' + f' File "{__file__}", line {lineno_f+8}, in f_with_call\n' + ' a = (g(1).y)(\n' + ' ~~~~~~~~~\n' + ' 2\n' + ' ~\n' + ' )(3)(4)\n' + ' ~^^^\n' + f' File "{__file__}", line {lineno_f+4}, in f\n' + ' raise RuntimeError("fail")\n' + ) + result_lines = self.get_exception(f_with_call) + self.assertEqual(result_lines, expected_error.splitlines()) + + def test_many_lines(self): + def f(): + x = 1 + if True: x += ( + "a" + + "a" + ) # test + + lineno_f = f.__code__.co_firstlineno + expected_error = ( + 'Traceback (most recent call last):\n' + f' File "{__file__}", line {self.callable_line}, in get_exception\n' + ' callable()\n' + ' ~~~~~~~~^^\n' + f' File "{__file__}", line {lineno_f+2}, in f\n' + ' if True: x += (\n' + ' ^^^^^^\n' + ' ...<2 lines>...\n' + ' ) # test\n' + ' ^\n' + ) + result_lines = self.get_exception(f) + self.assertEqual(result_lines, expected_error.splitlines()) + + def test_many_lines_no_caret(self): + def f(): + x = 1 + x += ( + "a" + + "a" + ) + + lineno_f = f.__code__.co_firstlineno + expected_error = ( + 'Traceback (most recent call last):\n' + f' File "{__file__}", line {self.callable_line}, in get_exception\n' + ' callable()\n' + ' ~~~~~~~~^^\n' + f' File "{__file__}", line {lineno_f+2}, in f\n' + ' x += (\n' + ' ...<2 lines>...\n' + ' )\n' + ) + result_lines = self.get_exception(f) + self.assertEqual(result_lines, expected_error.splitlines()) + + def test_many_lines_binary_op(self): + def f_with_binary_operator(): + b = 1 + c = "a" + a = ( + b + + b + ) + ( + c + + c + + c + ) + return a + + lineno_f = f_with_binary_operator.__code__.co_firstlineno + expected_error = ( + 'Traceback (most recent call last):\n' + f' File "{__file__}", line {self.callable_line}, in get_exception\n' + ' callable()\n' + ' ~~~~~~~~^^\n' + f' File "{__file__}", line {lineno_f+3}, in f_with_binary_operator\n' + ' a = (\n' + ' ~\n' + ' b +\n' + ' ~~~\n' + ' b\n' + ' ~\n' + ' ) + (\n' + ' ~~^~~\n' + ' c +\n' + ' ~~~\n' + ' ...<2 lines>...\n' + ' )\n' + ' ~\n' + ) + result_lines = self.get_exception(f_with_binary_operator) + self.assertEqual(result_lines, expected_error.splitlines()) + def test_traceback_specialization_with_syntax_error(self): bytecode = compile("1 / 0 / 1 / 2\n", TESTFN, "exec") @@ -646,6 +1167,7 @@ def test_traceback_specialization_with_syntax_error(self): 'Traceback (most recent call last):\n' f' File "{__file__}", line {self.callable_line}, in get_exception\n' ' callable()\n' + ' ~~~~~~~~^^\n' f' File "{TESTFN}", line {lineno_f}, in \n' " 1 $ 0 / 1 / 2\n" ' ^^^^^\n' @@ -668,6 +1190,7 @@ def test_traceback_very_long_line(self): 'Traceback (most recent call last):\n' f' File "{__file__}", line {self.callable_line}, in get_exception\n' ' callable()\n' + ' ~~~~~~~~^^\n' f' File "{TESTFN}", line {lineno_f}, in \n' f' {source}\n' f' {" "*len("if True: ") + "^"*256}\n' @@ -685,6 +1208,7 @@ def f_with_subscript(): 'Traceback (most recent call last):\n' f' File "{__file__}", line {self.callable_line}, in get_exception\n' ' callable()\n' + ' ~~~~~~~~^^\n' f' File "{__file__}", line {lineno_f+2}, in f_with_subscript\n' " some_dict['x']['y']['z']\n" ' ~~~~~~~~~~~~~~~~~~~^^^^^\n' @@ -704,6 +1228,7 @@ def exc(): f' + Exception Group Traceback (most recent call last):\n' f' | File "{__file__}", line {self.callable_line}, in get_exception\n' f' | callable()\n' + f' | ~~~~~~~~^^\n' f' | File "{__file__}", line {exc.__code__.co_firstlineno + 1}, in exc\n' f' | if True: raise ExceptionGroup("eg", [ValueError(1), TypeError(2)])\n' f' | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n' @@ -769,6 +1294,7 @@ def g(): pass 'Traceback (most recent call last):\n' f' File "{__file__}", line {self.callable_line}, in get_exception\n' ' callable()\n' + ' ~~~~~~~~^^\n' f' File "{__file__}", line {lineno_applydescs + 1}, in applydecs\n' ' @dec_error\n' ' ^^^^^^^^^\n' @@ -787,6 +1313,7 @@ class A: pass 'Traceback (most recent call last):\n' f' File "{__file__}", line {self.callable_line}, in get_exception\n' ' callable()\n' + ' ~~~~~~~~^^\n' f' File "{__file__}", line {lineno_applydescs_class + 1}, in applydecs_class\n' ' @dec_error\n' ' ^^^^^^^^^\n' @@ -805,6 +1332,7 @@ def f(): "Traceback (most recent call last):", f" File \"{__file__}\", line {self.callable_line}, in get_exception", " callable()", + " ~~~~~~~~^^", f" File \"{__file__}\", line {f.__code__.co_firstlineno + 2}, in f", " .method", " ^^^^^^", @@ -821,6 +1349,7 @@ def f(): "Traceback (most recent call last):", f" File \"{__file__}\", line {self.callable_line}, in get_exception", " callable()", + " ~~~~~~~~^^", f" File \"{__file__}\", line {f.__code__.co_firstlineno + 2}, in f", " method", ] @@ -836,6 +1365,7 @@ def f(): "Traceback (most recent call last):", f" File \"{__file__}\", line {self.callable_line}, in get_exception", " callable()", + " ~~~~~~~~^^", f" File \"{__file__}\", line {f.__code__.co_firstlineno + 2}, in f", " . method", " ^^^^^^", @@ -851,6 +1381,7 @@ def f(): "Traceback (most recent call last):", f" File \"{__file__}\", line {self.callable_line}, in get_exception", " callable()", + " ~~~~~~~~^^", f" File \"{__file__}\", line {f.__code__.co_firstlineno + 1}, in f", " width", ] @@ -867,6 +1398,7 @@ def f(): "Traceback (most recent call last):", f" File \"{__file__}\", line {self.callable_line}, in get_exception", " callable()", + " ~~~~~~~~^^", f" File \"{__file__}\", line {f.__code__.co_firstlineno + 2}, in f", " raise ValueError(width)", ] @@ -885,12 +1417,85 @@ def f(): "Traceback (most recent call last):", f" File \"{__file__}\", line {self.callable_line}, in get_exception", " callable()", + " ~~~~~~~~^^", f" File \"{__file__}\", line {f.__code__.co_firstlineno + 4}, in f", - " print(1, ï½—ï½—ï½—(", - " ^^^^", + f" print(1, ï½—ï½—ï½—(", + f" ~~~~~~^", + f" th))", + f" ^^^^^", + ] + self.assertEqual(actual, expected) + + def test_byte_offset_with_wide_characters_term_highlight(self): + def f(): + 说明说明 = 1 + şçöğıĤellö = 0 # not wide but still non-ascii + return 说明说明 / şçöğıĤellö + + actual = self.get_exception(f) + expected = [ + f"Traceback (most recent call last):", + f" File \"{__file__}\", line {self.callable_line}, in get_exception", + f" callable()", + f" ~~~~~~~~^^", + f" File \"{__file__}\", line {f.__code__.co_firstlineno + 3}, in f", + f" return 说明说明 / şçöğıĤellö", + f" ~~~~~~~~~^~~~~~~~~~~~", + ] + self.assertEqual(actual, expected) + + def test_byte_offset_with_emojis_term_highlight(self): + def f(): + return "✨ðŸ" + func_说明说明("📗🚛", + "📗🚛") + "ðŸ" + + actual = self.get_exception(f) + expected = [ + f"Traceback (most recent call last):", + f" File \"{__file__}\", line {self.callable_line}, in get_exception", + f" callable()", + f" ~~~~~~~~^^", + f" File \"{__file__}\", line {f.__code__.co_firstlineno + 1}, in f", + f' return "✨ðŸ" + func_说明说明("📗🚛",', + f" ^^^^^^^^^^^^^", ] self.assertEqual(actual, expected) + def test_byte_offset_wide_chars_subscript(self): + def f(): + my_dct = { + "✨🚛✨": { + "说明": { + "ðŸðŸðŸ": None + } + } + } + return my_dct["✨🚛✨"]["说明"]["ðŸ"]["说明"]["ðŸðŸ"] + + actual = self.get_exception(f) + expected = [ + f"Traceback (most recent call last):", + f" File \"{__file__}\", line {self.callable_line}, in get_exception", + f" callable()", + f" ~~~~~~~~^^", + f" File \"{__file__}\", line {f.__code__.co_firstlineno + 8}, in f", + f' return my_dct["✨🚛✨"]["说明"]["ðŸ"]["说明"]["ðŸðŸ"]', + f" ~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^", + ] + self.assertEqual(actual, expected) + + def test_memory_error(self): + def f(): + raise MemoryError() + + actual = self.get_exception(f) + expected = ['Traceback (most recent call last):', + f' File "{__file__}", line {self.callable_line}, in get_exception', + ' callable()', + ' ~~~~~~~~^^', + f' File "{__file__}", line {f.__code__.co_firstlineno + 1}, in f', + ' raise MemoryError()'] + self.assertEqual(actual, expected) @requires_debug_ranges() @@ -927,11 +1532,21 @@ class CPythonTracebackLegacyErrorCaretTests( Same set of tests as above but with Python's legacy internal traceback printing. """ -class TracebackFormatTests(unittest.TestCase): + +class TracebackFormatMixin: + DEBUG_RANGES = True def some_exception(self): raise KeyError('blah') + def _filter_debug_ranges(self, expected): + return [line for line in expected if not set(line.strip()) <= set("^~")] + + def _maybe_filter_debug_ranges(self, expected): + if not self.DEBUG_RANGES: + return self._filter_debug_ranges(expected) + return expected + @cpython_only def check_traceback_format(self, cleanup_func=None): from _testcapi import traceback_print @@ -944,6 +1559,11 @@ def check_traceback_format(self, cleanup_func=None): cleanup_func(tb.tb_next) traceback_fmt = 'Traceback (most recent call last):\n' + \ ''.join(traceback.format_tb(tb)) + # clear caret lines from traceback_fmt since internal API does + # not emit them + traceback_fmt = "\n".join( + self._filter_debug_ranges(traceback_fmt.splitlines()) + ) + "\n" file_ = StringIO() traceback_print(tb, file_) python_fmt = file_.getvalue() @@ -1036,12 +1656,16 @@ def f(): 'Traceback (most recent call last):\n' f' File "{__file__}", line {lineno_f+5}, in _check_recursive_traceback_display\n' ' f()\n' + ' ~^^\n' f' File "{__file__}", line {lineno_f+1}, in f\n' ' f()\n' + ' ~^^\n' f' File "{__file__}", line {lineno_f+1}, in f\n' ' f()\n' + ' ~^^\n' f' File "{__file__}", line {lineno_f+1}, in f\n' ' f()\n' + ' ~^^\n' # XXX: The following line changes depending on whether the tests # are run through the interactive interpreter or with -m # It also varies depending on the platform (stack size) @@ -1050,7 +1674,7 @@ def f(): 'RecursionError: maximum recursion depth exceeded\n' ) - expected = result_f.splitlines() + expected = self._maybe_filter_debug_ranges(result_f.splitlines()) actual = stderr_f.getvalue().splitlines() # Check the output text matches expectations @@ -1082,13 +1706,13 @@ def g(count=10): result_g = ( f' File "{__file__}", line {lineno_g+2}, in g\n' ' return g(count-1)\n' - ' ^^^^^^^^^^\n' + ' ~^^^^^^^^^\n' f' File "{__file__}", line {lineno_g+2}, in g\n' ' return g(count-1)\n' - ' ^^^^^^^^^^\n' + ' ~^^^^^^^^^\n' f' File "{__file__}", line {lineno_g+2}, in g\n' ' return g(count-1)\n' - ' ^^^^^^^^^^\n' + ' ~^^^^^^^^^\n' ' [Previous line repeated 7 more times]\n' f' File "{__file__}", line {lineno_g+3}, in g\n' ' raise ValueError\n' @@ -1098,8 +1722,9 @@ def g(count=10): 'Traceback (most recent call last):\n' f' File "{__file__}", line {lineno_g+7}, in _check_recursive_traceback_display\n' ' g()\n' + ' ~^^\n' ) - expected = (tb_line + result_g).splitlines() + expected = self._maybe_filter_debug_ranges((tb_line + result_g).splitlines()) actual = stderr_g.getvalue().splitlines() self.assertEqual(actual, expected) @@ -1122,20 +1747,22 @@ def h(count=10): 'Traceback (most recent call last):\n' f' File "{__file__}", line {lineno_h+7}, in _check_recursive_traceback_display\n' ' h()\n' + ' ~^^\n' f' File "{__file__}", line {lineno_h+2}, in h\n' ' return h(count-1)\n' - ' ^^^^^^^^^^\n' + ' ~^^^^^^^^^\n' f' File "{__file__}", line {lineno_h+2}, in h\n' ' return h(count-1)\n' - ' ^^^^^^^^^^\n' + ' ~^^^^^^^^^\n' f' File "{__file__}", line {lineno_h+2}, in h\n' ' return h(count-1)\n' - ' ^^^^^^^^^^\n' + ' ~^^^^^^^^^\n' ' [Previous line repeated 7 more times]\n' f' File "{__file__}", line {lineno_h+3}, in h\n' ' g()\n' + ' ~^^\n' ) - expected = (result_h + result_g).splitlines() + expected = self._maybe_filter_debug_ranges((result_h + result_g).splitlines()) actual = stderr_h.getvalue().splitlines() self.assertEqual(actual, expected) @@ -1150,23 +1777,24 @@ def h(count=10): result_g = ( f' File "{__file__}", line {lineno_g+2}, in g\n' ' return g(count-1)\n' - ' ^^^^^^^^^^\n' + ' ~^^^^^^^^^\n' f' File "{__file__}", line {lineno_g+2}, in g\n' ' return g(count-1)\n' - ' ^^^^^^^^^^\n' + ' ~^^^^^^^^^\n' f' File "{__file__}", line {lineno_g+2}, in g\n' ' return g(count-1)\n' - ' ^^^^^^^^^^\n' + ' ~^^^^^^^^^\n' f' File "{__file__}", line {lineno_g+3}, in g\n' ' raise ValueError\n' 'ValueError\n' ) tb_line = ( 'Traceback (most recent call last):\n' - f' File "{__file__}", line {lineno_g+77}, in _check_recursive_traceback_display\n' + f' File "{__file__}", line {lineno_g+80}, in _check_recursive_traceback_display\n' ' g(traceback._RECURSIVE_CUTOFF)\n' + ' ~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n' ) - expected = (tb_line + result_g).splitlines() + expected = self._maybe_filter_debug_ranges((tb_line + result_g).splitlines()) actual = stderr_g.getvalue().splitlines() self.assertEqual(actual, expected) @@ -1181,13 +1809,13 @@ def h(count=10): result_g = ( f' File "{__file__}", line {lineno_g+2}, in g\n' ' return g(count-1)\n' - ' ^^^^^^^^^^\n' + ' ~^^^^^^^^^\n' f' File "{__file__}", line {lineno_g+2}, in g\n' ' return g(count-1)\n' - ' ^^^^^^^^^^\n' + ' ~^^^^^^^^^\n' f' File "{__file__}", line {lineno_g+2}, in g\n' ' return g(count-1)\n' - ' ^^^^^^^^^^\n' + ' ~^^^^^^^^^\n' ' [Previous line repeated 1 more time]\n' f' File "{__file__}", line {lineno_g+3}, in g\n' ' raise ValueError\n' @@ -1195,24 +1823,23 @@ def h(count=10): ) tb_line = ( 'Traceback (most recent call last):\n' - f' File "{__file__}", line {lineno_g+108}, in _check_recursive_traceback_display\n' + f' File "{__file__}", line {lineno_g+112}, in _check_recursive_traceback_display\n' ' g(traceback._RECURSIVE_CUTOFF + 1)\n' + ' ~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n' ) - expected = (tb_line + result_g).splitlines() + expected = self._maybe_filter_debug_ranges((tb_line + result_g).splitlines()) actual = stderr_g.getvalue().splitlines() self.assertEqual(actual, expected) @requires_debug_ranges() - def test_recursive_traceback_python(self): - self._check_recursive_traceback_display(traceback.print_exc) - - @cpython_only - @requires_debug_ranges() - def test_recursive_traceback_cpython_internal(self): - from _testcapi import exception_print - def render_exc(): - exception_print(sys.exception()) - self._check_recursive_traceback_display(render_exc) + def test_recursive_traceback(self): + if self.DEBUG_RANGES: + self._check_recursive_traceback_display(traceback.print_exc) + else: + from _testcapi import exception_print + def render_exc(): + exception_print(sys.exception()) + self._check_recursive_traceback_display(render_exc) def test_format_stack(self): def fmt(): @@ -1285,7 +1912,8 @@ def test_exception_group_deep_recursion_traceback(self): def test_print_exception_bad_type_capi(self): from _testcapi import exception_print with captured_output("stderr") as stderr: - exception_print(42) + with support.catch_unraisable_exception(): + exception_print(42) self.assertEqual( stderr.getvalue(), ('TypeError: print_exception(): ' @@ -1309,6 +1937,24 @@ def test_print_exception_bad_type_python(self): boundaries = re.compile( '(%s|%s)' % (re.escape(cause_message), re.escape(context_message))) +class TestTracebackFormat(unittest.TestCase, TracebackFormatMixin): + pass + +@cpython_only +class TestFallbackTracebackFormat(unittest.TestCase, TracebackFormatMixin): + DEBUG_RANGES = False + def setUp(self) -> None: + self.original_unraisable_hook = sys.unraisablehook + sys.unraisablehook = lambda *args: None + self.original_hook = traceback._print_exception_bltin + traceback._print_exception_bltin = lambda *args: 1/0 + return super().setUp() + + def tearDown(self) -> None: + traceback._print_exception_bltin = self.original_hook + sys.unraisablehook = self.original_unraisable_hook + return super().tearDown() + class BaseExceptionReportingTests: def get_exception(self, exception_or_callable): @@ -1563,27 +2209,28 @@ def __repr__(self): err_msg = "b'please do not show me as numbers'" self.assertEqual(self.get_report(e), vanilla + err_msg + '\n') - def test_exception_with_note_with_multiple_notes(self): - e = ValueError(42) - vanilla = self.get_report(e) + def test_exception_with_multiple_notes(self): + for e in [ValueError(42), SyntaxError('bad syntax')]: + with self.subTest(e=e): + vanilla = self.get_report(e) - e.add_note('Note 1') - e.add_note('Note 2') - e.add_note('Note 3') + e.add_note('Note 1') + e.add_note('Note 2') + e.add_note('Note 3') - self.assertEqual( - self.get_report(e), - vanilla + 'Note 1\n' + 'Note 2\n' + 'Note 3\n') + self.assertEqual( + self.get_report(e), + vanilla + 'Note 1\n' + 'Note 2\n' + 'Note 3\n') - del e.__notes__ - e.add_note('Note 4') - del e.__notes__ - e.add_note('Note 5') - e.add_note('Note 6') + del e.__notes__ + e.add_note('Note 4') + del e.__notes__ + e.add_note('Note 5') + e.add_note('Note 6') - self.assertEqual( - self.get_report(e), - vanilla + 'Note 5\n' + 'Note 6\n') + self.assertEqual( + self.get_report(e), + vanilla + 'Note 5\n' + 'Note 6\n') def test_exception_qualname(self): class A: @@ -1661,6 +2308,7 @@ def exc(): f' + Exception Group Traceback (most recent call last):\n' f' | File "{__file__}", line {self.callable_line}, in get_exception\n' f' | exception_or_callable()\n' + f' | ~~~~~~~~~~~~~~~~~~~~~^^\n' f' | File "{__file__}", line {exc.__code__.co_firstlineno + 1}, in exc\n' f' | raise ExceptionGroup("eg", [ValueError(1), TypeError(2)])\n' f' | ExceptionGroup: eg (2 sub-exceptions)\n' @@ -1696,6 +2344,7 @@ def exc(): f' + Exception Group Traceback (most recent call last):\n' f' | File "{__file__}", line {self.callable_line}, in get_exception\n' f' | exception_or_callable()\n' + f' | ~~~~~~~~~~~~~~~~~~~~~^^\n' f' | File "{__file__}", line {exc.__code__.co_firstlineno + 5}, in exc\n' f' | raise EG("eg2", [ValueError(3), TypeError(4)]) from e\n' f' | ExceptionGroup: eg2 (2 sub-exceptions)\n' @@ -1747,6 +2396,7 @@ def exc(): f'Traceback (most recent call last):\n' f' File "{__file__}", line {self.callable_line}, in get_exception\n' f' exception_or_callable()\n' + f' ~~~~~~~~~~~~~~~~~~~~~^^\n' f' File "{__file__}", line {exc.__code__.co_firstlineno + 8}, in exc\n' f' raise ImportError(5)\n' f'ImportError: 5\n') @@ -1793,6 +2443,7 @@ def exc(): f' + Exception Group Traceback (most recent call last):\n' f' | File "{__file__}", line {self.callable_line}, in get_exception\n' f' | exception_or_callable()\n' + f' | ~~~~~~~~~~~~~~~~~~~~~^^\n' f' | File "{__file__}", line {exc.__code__.co_firstlineno + 11}, in exc\n' f' | raise EG("top", [VE(5)])\n' f' | ExceptionGroup: top (1 sub-exception)\n' @@ -1952,6 +2603,7 @@ def exc(): expected = (f' + Exception Group Traceback (most recent call last):\n' f' | File "{__file__}", line {self.callable_line}, in get_exception\n' f' | exception_or_callable()\n' + f' | ~~~~~~~~~~~~~~~~~~~~~^^\n' f' | File "{__file__}", line {exc.__code__.co_firstlineno + 9}, in exc\n' f' | raise ExceptionGroup("nested", excs)\n' f' | ExceptionGroup: nested (2 sub-exceptions)\n' @@ -2003,6 +2655,7 @@ def exc(): expected = (f' + Exception Group Traceback (most recent call last):\n' f' | File "{__file__}", line {self.callable_line}, in get_exception\n' f' | exception_or_callable()\n' + f' | ~~~~~~~~~~~~~~~~~~~~~^^\n' f' | File "{__file__}", line {exc.__code__.co_firstlineno + 10}, in exc\n' f' | raise ExceptionGroup("nested", excs)\n' f' | ExceptionGroup: nested (2 sub-exceptions)\n' @@ -2271,7 +2924,7 @@ def test_basics(self): def test_lazy_lines(self): linecache.clearcache() f = traceback.FrameSummary("f", 1, "dummy", lookup_line=False) - self.assertEqual(None, f._line) + self.assertEqual(None, f._lines) linecache.lazycache("f", globals()) self.assertEqual( '"""Test cases for traceback module"""', @@ -2388,7 +3041,7 @@ def some_inner(k, v): def test_custom_format_frame(self): class CustomStackSummary(traceback.StackSummary): - def format_frame_summary(self, frame_summary): + def format_frame_summary(self, frame_summary, colorize=False): return f'{frame_summary.filename}:{frame_summary.lineno}' def some_inner(): @@ -2413,7 +3066,7 @@ def g(): tb = g() class Skip_G(traceback.StackSummary): - def format_frame_summary(self, frame_summary): + def format_frame_summary(self, frame_summary, colorize=False): if frame_summary.name == 'g': return None return super().format_frame_summary(frame_summary) @@ -2433,10 +3086,9 @@ def __repr__(self) -> str: raise Exception("Unrepresentable") class TestTracebackException(unittest.TestCase): - - def test_smoke(self): + def do_test_smoke(self, exc, expected_type_str): try: - 1/0 + raise exc except Exception as e: exc_obj = e exc = traceback.TracebackException.from_exception(e) @@ -2446,9 +3098,23 @@ def test_smoke(self): self.assertEqual(None, exc.__context__) self.assertEqual(False, exc.__suppress_context__) self.assertEqual(expected_stack, exc.stack) - self.assertEqual(type(exc_obj), exc.exc_type) + with self.assertWarns(DeprecationWarning): + self.assertEqual(type(exc_obj), exc.exc_type) + self.assertEqual(expected_type_str, exc.exc_type_str) self.assertEqual(str(exc_obj), str(exc)) + def test_smoke_builtin(self): + self.do_test_smoke(ValueError(42), 'ValueError') + + def test_smoke_user_exception(self): + class MyException(Exception): + pass + + self.do_test_smoke( + MyException('bad things happened'), + ('test.test_traceback.TestTracebackException.' + 'test_smoke_user_exception..MyException')) + def test_from_exception(self): # Check all the parameters are accepted. def foo(): @@ -2469,7 +3135,9 @@ def foo(): self.assertEqual(None, exc.__context__) self.assertEqual(False, exc.__suppress_context__) self.assertEqual(expected_stack, exc.stack) - self.assertEqual(type(exc_obj), exc.exc_type) + with self.assertWarns(DeprecationWarning): + self.assertEqual(type(exc_obj), exc.exc_type) + self.assertEqual(type(exc_obj).__name__, exc.exc_type_str) self.assertEqual(str(exc_obj), str(exc)) def test_cause(self): @@ -2491,7 +3159,9 @@ def test_cause(self): self.assertEqual(exc_context, exc.__context__) self.assertEqual(True, exc.__suppress_context__) self.assertEqual(expected_stack, exc.stack) - self.assertEqual(type(exc_obj), exc.exc_type) + with self.assertWarns(DeprecationWarning): + self.assertEqual(type(exc_obj), exc.exc_type) + self.assertEqual(type(exc_obj).__name__, exc.exc_type_str) self.assertEqual(str(exc_obj), str(exc)) def test_context(self): @@ -2511,7 +3181,9 @@ def test_context(self): self.assertEqual(exc_context, exc.__context__) self.assertEqual(False, exc.__suppress_context__) self.assertEqual(expected_stack, exc.stack) - self.assertEqual(type(exc_obj), exc.exc_type) + with self.assertWarns(DeprecationWarning): + self.assertEqual(type(exc_obj), exc.exc_type) + self.assertEqual(type(exc_obj).__name__, exc.exc_type_str) self.assertEqual(str(exc_obj), str(exc)) def test_long_context_chain(self): @@ -2556,7 +3228,9 @@ def test_compact_with_cause(self): self.assertEqual(None, exc.__context__) self.assertEqual(True, exc.__suppress_context__) self.assertEqual(expected_stack, exc.stack) - self.assertEqual(type(exc_obj), exc.exc_type) + with self.assertWarns(DeprecationWarning): + self.assertEqual(type(exc_obj), exc.exc_type) + self.assertEqual(type(exc_obj).__name__, exc.exc_type_str) self.assertEqual(str(exc_obj), str(exc)) def test_compact_no_cause(self): @@ -2576,9 +3250,22 @@ def test_compact_no_cause(self): self.assertEqual(exc_context, exc.__context__) self.assertEqual(False, exc.__suppress_context__) self.assertEqual(expected_stack, exc.stack) - self.assertEqual(type(exc_obj), exc.exc_type) + with self.assertWarns(DeprecationWarning): + self.assertEqual(type(exc_obj), exc.exc_type) + self.assertEqual(type(exc_obj).__name__, exc.exc_type_str) self.assertEqual(str(exc_obj), str(exc)) + def test_no_save_exc_type(self): + try: + 1/0 + except Exception as e: + exc = e + + te = traceback.TracebackException.from_exception( + exc, save_exc_type=False) + with self.assertWarns(DeprecationWarning): + self.assertIsNone(te.exc_type) + def test_no_refs_to_exception_and_traceback_objects(self): try: 1/0 @@ -2827,6 +3514,7 @@ def test_exception_group_format(self): f' | Traceback (most recent call last):', f' | File "{__file__}", line {lno_g+9}, in _get_exception_group', f' | f()', + f' | ~^^', f' | File "{__file__}", line {lno_f+1}, in f', f' | 1/0', f' | ~^~', @@ -2835,6 +3523,7 @@ def test_exception_group_format(self): f' | Traceback (most recent call last):', f' | File "{__file__}", line {lno_g+13}, in _get_exception_group', f' | g(42)', + f' | ~^^^^', f' | File "{__file__}", line {lno_g+1}, in g', f' | raise ValueError(v)', f' | ValueError: 42', @@ -2843,6 +3532,7 @@ def test_exception_group_format(self): f' | Traceback (most recent call last):', f' | File "{__file__}", line {lno_g+20}, in _get_exception_group', f' | g(24)', + f' | ~^^^^', f' | File "{__file__}", line {lno_g+1}, in g', f' | raise ValueError(v)', f' | ValueError: 24', @@ -3539,6 +4229,7 @@ def CHECK(a, b, expected): CHECK("AttributeError", "AttributeErrorTests", 10) CHECK("ABA", "AAB", 4) + @support.requires_resource('cpu') def test_levenshtein_distance_short_circuit(self): if not LEVENSHTEIN_DATA_FILE.is_file(): self.fail( @@ -3563,6 +4254,115 @@ def test_levenshtein_distance_short_circuit(self): res3 = traceback._levenshtein_distance(a, b, threshold) self.assertGreater(res3, threshold, msg=(a, b, threshold)) +class TestColorizedTraceback(unittest.TestCase): + def test_colorized_traceback(self): + def foo(*args): + x = {'a':{'b': None}} + y = x['a']['b']['c'] + + def baz(*args): + return foo(1,2,3,4) + + def bar(): + return baz(1, + 2,3 + ,4) + try: + bar() + except Exception as e: + exc = traceback.TracebackException.from_exception( + e, capture_locals=True + ) + lines = "".join(exc.format(colorize=True)) + red = traceback._ANSIColors.RED + boldr = traceback._ANSIColors.BOLD_RED + reset = traceback._ANSIColors.RESET + self.assertIn("y = " + red + "x['a']['b']" + reset + boldr + "['c']" + reset, lines) + self.assertIn("return " + red + "foo" + reset + boldr + "(1,2,3,4)" + reset, lines) + self.assertIn("return " + red + "baz" + reset + boldr + "(1," + reset, lines) + self.assertIn(boldr + "2,3" + reset, lines) + self.assertIn(boldr + ",4)" + reset, lines) + self.assertIn(red + "bar" + reset + boldr + "()" + reset, lines) + + def test_colorized_syntax_error(self): + try: + compile("a $ b", "", "exec") + except SyntaxError as e: + exc = traceback.TracebackException.from_exception( + e, capture_locals=True + ) + actual = "".join(exc.format(colorize=True)) + red = traceback._ANSIColors.RED + magenta = traceback._ANSIColors.MAGENTA + boldm = traceback._ANSIColors.BOLD_MAGENTA + boldr = traceback._ANSIColors.BOLD_RED + reset = traceback._ANSIColors.RESET + expected = "".join([ + f' File {magenta}""{reset}, line {magenta}1{reset}\n', + f' a {boldr}${reset} b\n', + f' {boldr}^{reset}\n', + f'{boldm}SyntaxError{reset}: {magenta}invalid syntax{reset}\n'] + ) + self.assertIn(expected, actual) + + def test_colorized_traceback_is_the_default(self): + def foo(): + 1/0 + + from _testcapi import exception_print + try: + foo() + self.fail("No exception thrown.") + except Exception as e: + with captured_output("stderr") as tbstderr: + with unittest.mock.patch('traceback._can_colorize', return_value=True): + exception_print(e) + actual = tbstderr.getvalue().splitlines() + + red = traceback._ANSIColors.RED + boldr = traceback._ANSIColors.BOLD_RED + magenta = traceback._ANSIColors.MAGENTA + boldm = traceback._ANSIColors.BOLD_MAGENTA + reset = traceback._ANSIColors.RESET + lno_foo = foo.__code__.co_firstlineno + expected = ['Traceback (most recent call last):', + f' File {magenta}"{__file__}"{reset}, ' + f'line {magenta}{lno_foo+5}{reset}, in {magenta}test_colorized_traceback_is_the_default{reset}', + f' {red}foo{reset+boldr}(){reset}', + f' {red}~~~{reset+boldr}^^{reset}', + f' File {magenta}"{__file__}"{reset}, ' + f'line {magenta}{lno_foo+1}{reset}, in {magenta}foo{reset}', + f' {red}1{reset+boldr}/{reset+red}0{reset}', + f' {red}~{reset+boldr}^{reset+red}~{reset}', + f'{boldm}ZeroDivisionError{reset}: {magenta}division by zero{reset}'] + self.assertEqual(actual, expected) + + def test_colorized_detection_checks_for_environment_variables(self): + if sys.platform == "win32": + virtual_patching = unittest.mock.patch("nt._supports_virtual_terminal", return_value=True) + else: + virtual_patching = contextlib.nullcontext() + with virtual_patching: + with unittest.mock.patch("os.isatty") as isatty_mock: + isatty_mock.return_value = True + with unittest.mock.patch("os.environ", {'TERM': 'dumb'}): + self.assertEqual(traceback._can_colorize(), False) + with unittest.mock.patch("os.environ", {'PYTHON_COLORS': '1'}): + self.assertEqual(traceback._can_colorize(), True) + with unittest.mock.patch("os.environ", {'PYTHON_COLORS': '0'}): + self.assertEqual(traceback._can_colorize(), False) + with unittest.mock.patch("os.environ", {'NO_COLOR': '1'}): + self.assertEqual(traceback._can_colorize(), False) + with unittest.mock.patch("os.environ", {'NO_COLOR': '1', "PYTHON_COLORS": '1'}): + self.assertEqual(traceback._can_colorize(), True) + with unittest.mock.patch("os.environ", {'FORCE_COLOR': '1'}): + self.assertEqual(traceback._can_colorize(), True) + with unittest.mock.patch("os.environ", {'FORCE_COLOR': '1', 'NO_COLOR': '1'}): + self.assertEqual(traceback._can_colorize(), False) + with unittest.mock.patch("os.environ", {'FORCE_COLOR': '1', "PYTHON_COLORS": '0'}): + self.assertEqual(traceback._can_colorize(), False) + isatty_mock.return_value = False + self.assertEqual(traceback._can_colorize(), False) if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_tracemalloc.py b/Lib/test/test_tracemalloc.py index 4af4ca3b977236..bea124521032d1 100644 --- a/Lib/test/test_tracemalloc.py +++ b/Lib/test/test_tracemalloc.py @@ -173,9 +173,11 @@ def test_set_traceback_limit(self): self.assertEqual(len(traceback), 1) self.assertEqual(traceback, obj_traceback) - def find_trace(self, traces, traceback): + def find_trace(self, traces, traceback, size): + # filter also by size to ignore the memory allocated by + # _PyRefchain_Trace() if Python is built with Py_TRACE_REFS. for trace in traces: - if trace[2] == traceback._frames: + if trace[2] == traceback._frames and trace[1] == size: return trace self.fail("trace not found") @@ -186,11 +188,10 @@ def test_get_traces(self): obj, obj_traceback = allocate_bytes(obj_size) traces = tracemalloc._get_traces() - trace = self.find_trace(traces, obj_traceback) + trace = self.find_trace(traces, obj_traceback, obj_size) self.assertIsInstance(trace, tuple) domain, size, traceback, length = trace - self.assertEqual(size, obj_size) self.assertEqual(traceback, obj_traceback._frames) tracemalloc.stop() @@ -208,17 +209,18 @@ def allocate_bytes4(size): # Ensure that two identical tracebacks are not duplicated tracemalloc.stop() tracemalloc.start(4) - obj_size = 123 - obj1, obj1_traceback = allocate_bytes4(obj_size) - obj2, obj2_traceback = allocate_bytes4(obj_size) + obj1_size = 123 + obj2_size = 125 + obj1, obj1_traceback = allocate_bytes4(obj1_size) + obj2, obj2_traceback = allocate_bytes4(obj2_size) traces = tracemalloc._get_traces() obj1_traceback._frames = tuple(reversed(obj1_traceback._frames)) obj2_traceback._frames = tuple(reversed(obj2_traceback._frames)) - trace1 = self.find_trace(traces, obj1_traceback) - trace2 = self.find_trace(traces, obj2_traceback) + trace1 = self.find_trace(traces, obj1_traceback, obj1_size) + trace2 = self.find_trace(traces, obj2_traceback, obj2_size) domain1, size1, traceback1, length1 = trace1 domain2, size2, traceback2, length2 = trace2 self.assertIs(traceback2, traceback1) diff --git a/Lib/test/test_ttk/test_style.py b/Lib/test/test_ttk/test_style.py index 0ec95cf6b5ffc9..9a04a95dc40d65 100644 --- a/Lib/test/test_ttk/test_style.py +++ b/Lib/test/test_ttk/test_style.py @@ -2,6 +2,7 @@ import sys import tkinter from tkinter import ttk +from tkinter import TclError from test import support from test.support import requires from test.test_tkinter.support import AbstractTkTest, get_tk_patchlevel @@ -122,7 +123,6 @@ def test_theme_use(self): self.style.theme_use(curr_theme) - def test_configure_custom_copy(self): style = self.style @@ -170,12 +170,276 @@ def test_map_custom_copy(self): newname = f'C.{name}' self.assertEqual(style.map(newname), {}) style.map(newname, **default) - if theme == 'alt' and name == '.' and get_tk_patchlevel() < (8, 6, 1): + if theme == 'alt' and name == '.' and get_tk_patchlevel(self.root) < (8, 6, 1): default['embossed'] = [('disabled', '1')] self.assertEqual(style.map(newname), default) for key, value in default.items(): self.assertEqual(style.map(newname, key), value) + def test_element_options(self): + style = self.style + element_names = style.element_names() + self.assertNotIsInstance(element_names, str) + for name in element_names: + self.assertIsInstance(name, str) + element_options = style.element_options(name) + self.assertNotIsInstance(element_options, str) + for optname in element_options: + self.assertIsInstance(optname, str) + + def test_element_create_errors(self): + style = self.style + with self.assertRaises(TypeError): + style.element_create('plain.newelem') + with self.assertRaisesRegex(TclError, 'No such element type spam'): + style.element_create('plain.newelem', 'spam') + + def test_element_create_from(self): + style = self.style + style.element_create('plain.background', 'from', 'default') + self.assertIn('plain.background', style.element_names()) + style.element_create('plain.arrow', 'from', 'default', 'rightarrow') + self.assertIn('plain.arrow', style.element_names()) + + def test_element_create_from_errors(self): + style = self.style + with self.assertRaises(IndexError): + style.element_create('plain.newelem', 'from') + with self.assertRaisesRegex(TclError, 'theme "spam" doesn\'t exist'): + style.element_create('plain.newelem', 'from', 'spam') + + def test_element_create_image(self): + style = self.style + image = tkinter.PhotoImage(master=self.root, width=12, height=10) + style.element_create('block', 'image', image) + self.assertIn('block', style.element_names()) + + style.layout('TestLabel1', [('block', {'sticky': 'news'})]) + a = ttk.Label(self.root, style='TestLabel1') + a.pack(expand=True, fill='both') + self.assertEqual(a.winfo_reqwidth(), 12) + self.assertEqual(a.winfo_reqheight(), 10) + + imgfile = support.findfile('python.xbm', subdir='tkinterdata') + img1 = tkinter.BitmapImage(master=self.root, file=imgfile, + foreground='yellow', background='blue') + img2 = tkinter.BitmapImage(master=self.root, file=imgfile, + foreground='blue', background='yellow') + img3 = tkinter.BitmapImage(master=self.root, file=imgfile, + foreground='white', background='black') + style.element_create('Button.button', 'image', + img1, ('pressed', img2), ('active', img3), + border=(2, 4), sticky='we') + self.assertIn('Button.button', style.element_names()) + + style.layout('Button', [('Button.button', {'sticky': 'news'})]) + b = ttk.Button(self.root, style='Button') + b.pack(expand=True, fill='both') + self.assertEqual(b.winfo_reqwidth(), 16) + self.assertEqual(b.winfo_reqheight(), 16) + + def test_element_create_image_errors(self): + style = self.style + image = tkinter.PhotoImage(master=self.root, width=10, height=10) + with self.assertRaises(IndexError): + style.element_create('block2', 'image') + with self.assertRaises(TypeError): + style.element_create('block2', 'image', image, 1) + with self.assertRaises(ValueError): + style.element_create('block2', 'image', image, ()) + with self.assertRaisesRegex(TclError, 'Invalid state name'): + style.element_create('block2', 'image', image, ('spam', image)) + with self.assertRaisesRegex(TclError, 'Invalid state name'): + style.element_create('block2', 'image', image, (1, image)) + with self.assertRaises(TypeError): + style.element_create('block2', 'image', image, ('pressed', 1, image)) + with self.assertRaises(TypeError): + style.element_create('block2', 'image', image, (1, 'selected', image)) + with self.assertRaisesRegex(TclError, 'bad option'): + style.element_create('block2', 'image', image, spam=1) + + def test_element_create_vsapi_1(self): + style = self.style + if 'xpnative' not in style.theme_names(): + self.skipTest("requires 'xpnative' theme") + style.element_create('smallclose', 'vsapi', 'WINDOW', 19, [ + ('disabled', 4), + ('pressed', 3), + ('active', 2), + ('', 1)]) + style.layout('CloseButton', + [('CloseButton.smallclose', {'sticky': 'news'})]) + b = ttk.Button(self.root, style='CloseButton') + b.pack(expand=True, fill='both') + self.assertEqual(b.winfo_reqwidth(), 13) + self.assertEqual(b.winfo_reqheight(), 13) + + def test_element_create_vsapi_2(self): + style = self.style + if 'xpnative' not in style.theme_names(): + self.skipTest("requires 'xpnative' theme") + style.element_create('pin', 'vsapi', 'EXPLORERBAR', 3, [ + ('pressed', '!selected', 3), + ('active', '!selected', 2), + ('pressed', 'selected', 6), + ('active', 'selected', 5), + ('selected', 4), + ('', 1)]) + style.layout('Explorer.Pin', + [('Explorer.Pin.pin', {'sticky': 'news'})]) + pin = ttk.Checkbutton(self.root, style='Explorer.Pin') + pin.pack(expand=True, fill='both') + self.assertEqual(pin.winfo_reqwidth(), 16) + self.assertEqual(pin.winfo_reqheight(), 16) + + def test_element_create_vsapi_3(self): + style = self.style + if 'xpnative' not in style.theme_names(): + self.skipTest("requires 'xpnative' theme") + style.element_create('headerclose', 'vsapi', 'EXPLORERBAR', 2, [ + ('pressed', 3), + ('active', 2), + ('', 1)]) + style.layout('Explorer.CloseButton', + [('Explorer.CloseButton.headerclose', {'sticky': 'news'})]) + b = ttk.Button(self.root, style='Explorer.CloseButton') + b.pack(expand=True, fill='both') + self.assertEqual(b.winfo_reqwidth(), 16) + self.assertEqual(b.winfo_reqheight(), 16) + + def test_theme_create(self): + style = self.style + curr_theme = style.theme_use() + curr_layout = style.layout('TLabel') + style.theme_create('testtheme1') + self.assertIn('testtheme1', style.theme_names()) + + style.theme_create('testtheme2', settings={ + 'elem' : {'element create': ['from', 'default'],}, + 'TLabel' : { + 'configure': {'padding': 10}, + 'layout': [('elem', {'sticky': 'we'})], + }, + }) + self.assertIn('testtheme2', style.theme_names()) + + style.theme_create('testtheme3', 'testtheme2') + self.assertIn('testtheme3', style.theme_names()) + + style.theme_use('testtheme1') + self.assertEqual(style.element_names(), ()) + self.assertEqual(style.layout('TLabel'), curr_layout) + + style.theme_use('testtheme2') + self.assertEqual(style.element_names(), ('elem',)) + self.assertEqual(style.lookup('TLabel', 'padding'), '10') + self.assertEqual(style.layout('TLabel'), [('elem', {'sticky': 'we'})]) + + style.theme_use('testtheme3') + self.assertEqual(style.element_names(), ()) + self.assertEqual(style.lookup('TLabel', 'padding'), '') + self.assertEqual(style.layout('TLabel'), [('elem', {'sticky': 'we'})]) + + style.theme_use(curr_theme) + + def test_theme_create_image(self): + style = self.style + curr_theme = style.theme_use() + image = tkinter.PhotoImage(master=self.root, width=10, height=10) + new_theme = 'testtheme4' + style.theme_create(new_theme, settings={ + 'block' : { + 'element create': ['image', image, {'width': 120, 'height': 100}], + }, + 'TestWidget.block2' : { + 'element create': ['image', image], + }, + 'TestWidget' : { + 'configure': { + 'anchor': 'left', + 'padding': (3, 0, 0, 2), + 'foreground': 'yellow', + }, + 'map': { + 'foreground': [ + ('pressed', 'red'), + ('active', 'disabled', 'blue'), + ], + }, + 'layout': [ + ('TestWidget.block', {'sticky': 'we', 'side': 'left'}), + ('TestWidget.border', { + 'sticky': 'nsw', + 'border': 1, + 'children': [ + ('TestWidget.block2', {'sticky': 'nswe'}) + ] + }) + ], + }, + }) + + style.theme_use(new_theme) + self.assertIn('block', style.element_names()) + self.assertEqual(style.lookup('TestWidget', 'anchor'), 'left') + self.assertEqual(style.lookup('TestWidget', 'padding'), '3 0 0 2') + self.assertEqual(style.lookup('TestWidget', 'foreground'), 'yellow') + self.assertEqual(style.lookup('TestWidget', 'foreground', + ['active']), 'yellow') + self.assertEqual(style.lookup('TestWidget', 'foreground', + ['active', 'pressed']), 'red') + self.assertEqual(style.lookup('TestWidget', 'foreground', + ['active', 'disabled']), 'blue') + self.assertEqual(style.layout('TestWidget'), + [ + ('TestWidget.block', {'side': 'left', 'sticky': 'we'}), + ('TestWidget.border', { + 'sticky': 'nsw', + 'border': '1', + 'children': [('TestWidget.block2', {'sticky': 'nswe'})] + }) + ]) + + b = ttk.Label(self.root, style='TestWidget') + b.pack(expand=True, fill='both') + self.assertEqual(b.winfo_reqwidth(), 134) + self.assertEqual(b.winfo_reqheight(), 100) + + style.theme_use(curr_theme) + + def test_theme_create_vsapi(self): + style = self.style + if 'xpnative' not in style.theme_names(): + self.skipTest("requires 'xpnative' theme") + curr_theme = style.theme_use() + new_theme = 'testtheme5' + style.theme_create(new_theme, settings={ + 'pin' : { + 'element create': ['vsapi', 'EXPLORERBAR', 3, [ + ('pressed', '!selected', 3), + ('active', '!selected', 2), + ('pressed', 'selected', 6), + ('active', 'selected', 5), + ('selected', 4), + ('', 1)]], + }, + 'Explorer.Pin' : { + 'layout': [('Explorer.Pin.pin', {'sticky': 'news'})], + }, + }) + + style.theme_use(new_theme) + self.assertIn('pin', style.element_names()) + self.assertEqual(style.layout('Explorer.Pin'), + [('Explorer.Pin.pin', {'sticky': 'nswe'})]) + + pin = ttk.Checkbutton(self.root, style='Explorer.Pin') + pin.pack(expand=True, fill='both') + self.assertEqual(pin.winfo_reqwidth(), 16) + self.assertEqual(pin.winfo_reqheight(), 16) + + style.theme_use(curr_theme) + if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_ttk/test_widgets.py b/Lib/test/test_ttk/test_widgets.py index 79d65b496abdc6..fd1a748a498ac5 100644 --- a/Lib/test/test_ttk/test_widgets.py +++ b/Lib/test/test_ttk/test_widgets.py @@ -5,7 +5,7 @@ import sys from test.test_ttk_textonly import MockTclObj -from test.test_tkinter.support import (AbstractTkTest, tcl_version, get_tk_patchlevel, +from test.test_tkinter.support import (AbstractTkTest, tk_version, get_tk_patchlevel, simulate_mouse_click, AbstractDefaultRootTest) from test.test_tkinter.widget_tests import (add_standard_options, AbstractWidgetTest, StandardOptionsTests, IntegerSizeTests, PixelSizeTests) @@ -19,7 +19,7 @@ def test_configure_class(self): widget = self.create() self.assertEqual(widget['class'], '') errmsg='attempt to change read-only option' - if get_tk_patchlevel() < (8, 6, 0, 'beta', 3): + if get_tk_patchlevel(self.root) < (8, 6, 0, 'beta', 3): errmsg='Attempt to change read-only option' self.checkInvalidParam(widget, 'class', 'Foo', errmsg=errmsg) widget2 = self.create(class_='Foo') @@ -560,7 +560,7 @@ def test_configure_orient(self): widget = self.create() self.assertEqual(str(widget['orient']), 'vertical') errmsg='attempt to change read-only option' - if get_tk_patchlevel() < (8, 6, 0, 'beta', 3): + if get_tk_patchlevel(self.root) < (8, 6, 0, 'beta', 3): errmsg='Attempt to change read-only option' self.checkInvalidParam(widget, 'orient', 'horizontal', errmsg=errmsg) @@ -1526,7 +1526,7 @@ def test_heading(self): def test_heading_callback(self): def simulate_heading_click(x, y): - if tcl_version >= (8, 6): + if tk_version >= (8, 6): self.assertEqual(self.tv.identify_column(x), '#0') self.assertEqual(self.tv.identify_region(x, y), 'heading') simulate_mouse_click(self.tv, x, y) diff --git a/Lib/test/test_ttk_textonly.py b/Lib/test/test_ttk_textonly.py index 96dc179a69ecac..e6525c4d6c6982 100644 --- a/Lib/test/test_ttk_textonly.py +++ b/Lib/test/test_ttk_textonly.py @@ -179,7 +179,7 @@ def test_format_elemcreate(self): # don't format returned values as a tcl script # minimum acceptable for image type self.assertEqual(ttk._format_elemcreate('image', False, 'test'), - ("test ", ())) + ("test", ())) # specifying a state spec self.assertEqual(ttk._format_elemcreate('image', False, 'test', ('', 'a')), ("test {} a", ())) @@ -203,17 +203,19 @@ def test_format_elemcreate(self): # don't format returned values as a tcl script # minimum acceptable for vsapi self.assertEqual(ttk._format_elemcreate('vsapi', False, 'a', 'b'), - ("a b ", ())) + ('a', 'b', ('', 1), ())) # now with a state spec with multiple states self.assertEqual(ttk._format_elemcreate('vsapi', False, 'a', 'b', - ('a', 'b', 'c')), ("a b {a b} c", ())) + [('a', 'b', 'c')]), ('a', 'b', ('a b', 'c'), ())) # state spec and option self.assertEqual(ttk._format_elemcreate('vsapi', False, 'a', 'b', - ('a', 'b'), opt='x'), ("a b a b", ("-opt", "x"))) + [('a', 'b')], opt='x'), ('a', 'b', ('a', 'b'), ("-opt", "x"))) # format returned values as a tcl script # state spec with a multivalue and an option self.assertEqual(ttk._format_elemcreate('vsapi', True, 'a', 'b', - ('a', 'b', [1, 2]), opt='x'), ("{a b {a b} {1 2}}", "-opt x")) + opt='x'), ("a b {{} 1}", "-opt x")) + self.assertEqual(ttk._format_elemcreate('vsapi', True, 'a', 'b', + [('a', 'b', [1, 2])], opt='x'), ("a b {{a b} {1 2}}", "-opt x")) # Testing type = from # from type expects at least a type name @@ -222,9 +224,9 @@ def test_format_elemcreate(self): self.assertEqual(ttk._format_elemcreate('from', False, 'a'), ('a', ())) self.assertEqual(ttk._format_elemcreate('from', False, 'a', 'b'), - ('a', ('b', ))) + ('a', ('b',))) self.assertEqual(ttk._format_elemcreate('from', True, 'a', 'b'), - ('{a}', 'b')) + ('a', 'b')) def test_format_layoutlist(self): @@ -326,6 +328,22 @@ def test_script_from_settings(self): "ttk::style element create thing image {name {state1 state2} val} " "-opt {3 2m}") + vsapi = {'pin': {'element create': + ['vsapi', 'EXPLORERBAR', 3, [ + ('pressed', '!selected', 3), + ('active', '!selected', 2), + ('pressed', 'selected', 6), + ('active', 'selected', 5), + ('selected', 4), + ('', 1)]]}} + self.assertEqual(ttk._script_from_settings(vsapi), + "ttk::style element create pin vsapi EXPLORERBAR 3 {" + "{pressed !selected} 3 " + "{active !selected} 2 " + "{pressed selected} 6 " + "{active selected} 5 " + "selected 4 " + "{} 1} ") def test_tclobj_to_py(self): self.assertEqual( diff --git a/Lib/test/test_tty.py b/Lib/test/test_tty.py new file mode 100644 index 00000000000000..af20864aac361e --- /dev/null +++ b/Lib/test/test_tty.py @@ -0,0 +1,84 @@ +import os +import unittest +from test.support.import_helper import import_module + +termios = import_module('termios') +tty = import_module('tty') + + +@unittest.skipUnless(hasattr(os, 'openpty'), "need os.openpty()") +class TestTty(unittest.TestCase): + + def setUp(self): + master_fd, self.fd = os.openpty() + self.addCleanup(os.close, master_fd) + self.stream = self.enterContext(open(self.fd, 'wb', buffering=0)) + self.fd = self.stream.fileno() + self.mode = termios.tcgetattr(self.fd) + self.addCleanup(termios.tcsetattr, self.fd, termios.TCSANOW, self.mode) + self.addCleanup(termios.tcsetattr, self.fd, termios.TCSAFLUSH, self.mode) + + def check_cbreak(self, mode): + self.assertEqual(mode[0] & termios.ICRNL, 0) + self.assertEqual(mode[3] & termios.ECHO, 0) + self.assertEqual(mode[3] & termios.ICANON, 0) + self.assertEqual(mode[6][termios.VMIN], 1) + self.assertEqual(mode[6][termios.VTIME], 0) + + def check_raw(self, mode): + self.check_cbreak(mode) + self.assertEqual(mode[0] & termios.ISTRIP, 0) + self.assertEqual(mode[0] & termios.ICRNL, 0) + self.assertEqual(mode[1] & termios.OPOST, 0) + self.assertEqual(mode[2] & termios.PARENB, termios.CS8 & termios.PARENB) + self.assertEqual(mode[2] & termios.CSIZE, termios.CS8 & termios.CSIZE) + self.assertEqual(mode[2] & termios.CS8, termios.CS8) + self.assertEqual(mode[3] & termios.ECHO, 0) + self.assertEqual(mode[3] & termios.ICANON, 0) + self.assertEqual(mode[3] & termios.ISIG, 0) + self.assertEqual(mode[6][termios.VMIN], 1) + self.assertEqual(mode[6][termios.VTIME], 0) + + def test_cfmakeraw(self): + mode = termios.tcgetattr(self.fd) + self.assertEqual(mode, self.mode) + tty.cfmakeraw(mode) + self.check_raw(mode) + self.assertEqual(mode[4], self.mode[4]) + self.assertEqual(mode[5], self.mode[5]) + + def test_cfmakecbreak(self): + mode = termios.tcgetattr(self.fd) + self.assertEqual(mode, self.mode) + tty.cfmakecbreak(mode) + self.check_cbreak(mode) + self.assertEqual(mode[1], self.mode[1]) + self.assertEqual(mode[2], self.mode[2]) + self.assertEqual(mode[4], self.mode[4]) + self.assertEqual(mode[5], self.mode[5]) + + def test_setraw(self): + mode0 = termios.tcgetattr(self.fd) + mode1 = tty.setraw(self.fd) + self.assertEqual(mode1, mode0) + mode2 = termios.tcgetattr(self.fd) + self.check_raw(mode2) + mode3 = tty.setraw(self.fd, termios.TCSANOW) + self.assertEqual(mode3, mode2) + tty.setraw(self.stream) + tty.setraw(fd=self.fd, when=termios.TCSANOW) + + def test_setcbreak(self): + mode0 = termios.tcgetattr(self.fd) + mode1 = tty.setcbreak(self.fd) + self.assertEqual(mode1, mode0) + mode2 = termios.tcgetattr(self.fd) + self.check_cbreak(mode2) + mode3 = tty.setcbreak(self.fd, termios.TCSANOW) + self.assertEqual(mode3, mode2) + tty.setcbreak(self.stream) + tty.setcbreak(fd=self.fd, when=termios.TCSANOW) + + +if __name__ == '__main__': + unittest.main() diff --git a/Lib/test/test_turtle.py b/Lib/test/test_turtle.py index 3f9f129a3dd200..14121a590a5026 100644 --- a/Lib/test/test_turtle.py +++ b/Lib/test/test_turtle.py @@ -461,5 +461,25 @@ def test_teleport(self): self.assertTrue(tpen.isdown()) +class TestModuleLevel(unittest.TestCase): + def test_all_signatures(self): + import inspect + + known_signatures = { + 'teleport': + '(x=None, y=None, *, fill_gap: bool = False) -> None', + 'undo': '()', + 'goto': '(x, y=None)', + 'bgcolor': '(*args)', + 'pen': '(pen=None, **pendict)', + } + + for name in known_signatures: + with self.subTest(name=name): + obj = getattr(turtle, name) + sig = inspect.signature(obj) + self.assertEqual(str(sig), known_signatures[name]) + + if __name__ == '__main__': unittest.main() diff --git a/Lib/test/test_type_aliases.py b/Lib/test/test_type_aliases.py index 0ce97f57de6860..9c325bc595f585 100644 --- a/Lib/test/test_type_aliases.py +++ b/Lib/test/test_type_aliases.py @@ -2,7 +2,7 @@ import types import unittest from test.support import check_syntax_error, run_code -from test import mod_generics_cache +from test.typinganndata import mod_generics_cache from typing import Callable, TypeAliasType, TypeVar, get_args @@ -168,6 +168,24 @@ def test_recursive_repr(self): self.assertEqual(repr(GenericRecursive[GenericRecursive[int]]), "GenericRecursive[GenericRecursive[int]]") + def test_raising(self): + type MissingName = list[_My_X] + with self.assertRaisesRegex( + NameError, + "cannot access free variable '_My_X' where it is not associated with a value", + ): + MissingName.__value__ + _My_X = int + self.assertEqual(MissingName.__value__, list[int]) + del _My_X + # Cache should still work: + self.assertEqual(MissingName.__value__, list[int]) + + # Explicit exception: + type ExprException = 1 / 0 + with self.assertRaises(ZeroDivisionError): + ExprException.__value__ + class TypeAliasConstructorTest(unittest.TestCase): def test_basic(self): diff --git a/Lib/test/test_type_cache.py b/Lib/test/test_type_cache.py index 24f83cd3e172c7..95b55009c7187d 100644 --- a/Lib/test/test_type_cache.py +++ b/Lib/test/test_type_cache.py @@ -1,5 +1,6 @@ """ Tests for the internal type cache in CPython. """ import unittest +import dis from test import support from test.support import import_helper try: @@ -8,8 +9,11 @@ _clear_type_cache = None # Skip this test if the _testcapi module isn't available. -type_get_version = import_helper.import_module('_testcapi').type_get_version -type_assign_version = import_helper.import_module('_testcapi').type_assign_version +_testcapi = import_helper.import_module("_testcapi") +type_get_version = _testcapi.type_get_version +type_assign_specific_version_unsafe = _testcapi.type_assign_specific_version_unsafe +type_assign_version = _testcapi.type_assign_version +type_modified = _testcapi.type_modified @support.cpython_only @@ -56,6 +60,183 @@ class C: self.assertNotEqual(type_get_version(C), 0) self.assertNotEqual(type_get_version(C), c_ver) + def test_type_assign_specific_version(self): + """meta-test for type_assign_specific_version_unsafe""" + class C: + pass + + type_assign_version(C) + orig_version = type_get_version(C) + self.assertNotEqual(orig_version, 0) + + type_modified(C) + type_assign_specific_version_unsafe(C, orig_version + 5) + type_assign_version(C) # this should do nothing + + new_version = type_get_version(C) + self.assertEqual(new_version, orig_version + 5) + + _clear_type_cache() + + +@support.cpython_only +class TypeCacheWithSpecializationTests(unittest.TestCase): + def tearDown(self): + _clear_type_cache() + + def _assign_and_check_valid_version(self, user_type): + type_modified(user_type) + type_assign_version(user_type) + self.assertNotEqual(type_get_version(user_type), 0) + + def _assign_and_check_version_0(self, user_type): + type_modified(user_type) + type_assign_specific_version_unsafe(user_type, 0) + self.assertEqual(type_get_version(user_type), 0) + + def _all_opnames(self, func): + return set(instr.opname for instr in dis.Bytecode(func, adaptive=True)) + + def _check_specialization(self, func, arg, opname, *, should_specialize): + self.assertIn(opname, self._all_opnames(func)) + + for _ in range(100): + func(arg) + + if should_specialize: + self.assertNotIn(opname, self._all_opnames(func)) + else: + self.assertIn(opname, self._all_opnames(func)) + + def test_class_load_attr_specialization_user_type(self): + class A: + def foo(self): + pass + + self._assign_and_check_valid_version(A) + + def load_foo_1(type_): + type_.foo + + self._check_specialization(load_foo_1, A, "LOAD_ATTR", should_specialize=True) + del load_foo_1 + + self._assign_and_check_version_0(A) + + def load_foo_2(type_): + return type_.foo + + self._check_specialization(load_foo_2, A, "LOAD_ATTR", should_specialize=False) + + def test_class_load_attr_specialization_static_type(self): + self._assign_and_check_valid_version(str) + self._assign_and_check_valid_version(bytes) + + def get_capitalize_1(type_): + return type_.capitalize + + self._check_specialization(get_capitalize_1, str, "LOAD_ATTR", should_specialize=True) + self.assertEqual(get_capitalize_1(str)('hello'), 'Hello') + self.assertEqual(get_capitalize_1(bytes)(b'hello'), b'Hello') + del get_capitalize_1 + + # Permanently overflow the static type version counter, and force str and bytes + # to have tp_version_tag == 0 + for _ in range(2**16): + type_modified(str) + type_assign_version(str) + type_modified(bytes) + type_assign_version(bytes) + + self.assertEqual(type_get_version(str), 0) + self.assertEqual(type_get_version(bytes), 0) + + def get_capitalize_2(type_): + return type_.capitalize + + self._check_specialization(get_capitalize_2, str, "LOAD_ATTR", should_specialize=False) + self.assertEqual(get_capitalize_2(str)('hello'), 'Hello') + self.assertEqual(get_capitalize_2(bytes)(b'hello'), b'Hello') + + def test_property_load_attr_specialization_user_type(self): + class G: + @property + def x(self): + return 9 + + self._assign_and_check_valid_version(G) + + def load_x_1(instance): + instance.x + + self._check_specialization(load_x_1, G(), "LOAD_ATTR", should_specialize=True) + del load_x_1 + + self._assign_and_check_version_0(G) + + def load_x_2(instance): + instance.x + + self._check_specialization(load_x_2, G(), "LOAD_ATTR", should_specialize=False) + + def test_store_attr_specialization_user_type(self): + class B: + __slots__ = ("bar",) + + self._assign_and_check_valid_version(B) + + def store_bar_1(type_): + type_.bar = 10 + + self._check_specialization(store_bar_1, B(), "STORE_ATTR", should_specialize=True) + del store_bar_1 + + self._assign_and_check_version_0(B) + + def store_bar_2(type_): + type_.bar = 10 + + self._check_specialization(store_bar_2, B(), "STORE_ATTR", should_specialize=False) + + def test_class_call_specialization_user_type(self): + class F: + def __init__(self): + pass + + self._assign_and_check_valid_version(F) + + def call_class_1(type_): + type_() + + self._check_specialization(call_class_1, F, "CALL", should_specialize=True) + del call_class_1 + + self._assign_and_check_version_0(F) + + def call_class_2(type_): + type_() + + self._check_specialization(call_class_2, F, "CALL", should_specialize=False) + + def test_to_bool_specialization_user_type(self): + class H: + pass + + self._assign_and_check_valid_version(H) + + def to_bool_1(instance): + not instance + + self._check_specialization(to_bool_1, H(), "TO_BOOL", should_specialize=True) + del to_bool_1 + + self._assign_and_check_version_0(H) + + def to_bool_2(instance): + not instance + + self._check_specialization(to_bool_2, H(), "TO_BOOL", should_specialize=False) + if __name__ == "__main__": - support.run_unittest(TypeCacheTests) + unittest.main() diff --git a/Lib/test/test_type_comments.py b/Lib/test/test_type_comments.py index 9a11fab237235e..5a911da56f8f8a 100644 --- a/Lib/test/test_type_comments.py +++ b/Lib/test/test_type_comments.py @@ -66,6 +66,14 @@ def foo(): pass """ +parenthesized_withstmt = """\ +with (a as b): # type: int + pass + +with (a, b): # type: int + pass +""" + vardecl = """\ a = 0 # type: int """ @@ -300,6 +308,14 @@ def test_withstmt(self): tree = self.classic_parse(withstmt) self.assertEqual(tree.body[0].type_comment, None) + def test_parenthesized_withstmt(self): + for tree in self.parse_all(parenthesized_withstmt, minver=9): + self.assertEqual(tree.body[0].type_comment, "int") + self.assertEqual(tree.body[1].type_comment, "int") + tree = self.classic_parse(parenthesized_withstmt) + self.assertEqual(tree.body[0].type_comment, None) + self.assertEqual(tree.body[1].type_comment, None) + def test_vardecl(self): for tree in self.parse_all(vardecl): self.assertEqual(tree.body[0].type_comment, "int") diff --git a/Lib/test/test_type_params.py b/Lib/test/test_type_params.py index bced641a9661fd..25ee188731f31f 100644 --- a/Lib/test/test_type_params.py +++ b/Lib/test/test_type_params.py @@ -148,6 +148,10 @@ def test_disallowed_expressions(self): check_syntax_error(self, "def f[T: [(x := 3) for _ in range(2)]](): pass") check_syntax_error(self, "type T = [(x := 3) for _ in range(2)]") + def test_incorrect_mro_explicit_object(self): + with self.assertRaisesRegex(TypeError, r"\(MRO\) for bases object, Generic"): + class My[X](object): ... + class TypeParamsNonlocalTest(unittest.TestCase): def test_nonlocal_disallowed_01(self): @@ -408,6 +412,99 @@ def test_comprehension_02(self): func, = T.__bound__ self.assertEqual(func(), 1) + def test_gen_exp_in_nested_class(self): + code = """ + from test.test_type_params import make_base + + class C[T]: + T = "class" + class Inner(make_base(T for _ in (1,)), make_base(T)): + pass + """ + C = run_code(code)["C"] + T, = C.__type_params__ + base1, base2 = C.Inner.__bases__ + self.assertEqual(list(base1.__arg__), [T]) + self.assertEqual(base2.__arg__, "class") + + def test_gen_exp_in_nested_generic_class(self): + code = """ + from test.test_type_params import make_base + + class C[T]: + T = "class" + class Inner[U](make_base(T for _ in (1,)), make_base(T)): + pass + """ + with self.assertRaisesRegex(SyntaxError, + "Cannot use comprehension in annotation scope within class scope"): + run_code(code) + + def test_listcomp_in_nested_class(self): + code = """ + from test.test_type_params import make_base + + class C[T]: + T = "class" + class Inner(make_base([T for _ in (1,)]), make_base(T)): + pass + """ + C = run_code(code)["C"] + T, = C.__type_params__ + base1, base2 = C.Inner.__bases__ + self.assertEqual(base1.__arg__, [T]) + self.assertEqual(base2.__arg__, "class") + + def test_listcomp_in_nested_generic_class(self): + code = """ + from test.test_type_params import make_base + + class C[T]: + T = "class" + class Inner[U](make_base([T for _ in (1,)]), make_base(T)): + pass + """ + with self.assertRaisesRegex(SyntaxError, + "Cannot use comprehension in annotation scope within class scope"): + run_code(code) + + def test_gen_exp_in_generic_method(self): + code = """ + class C[T]: + T = "class" + def meth[U](x: (T for _ in (1,)), y: T): + pass + """ + with self.assertRaisesRegex(SyntaxError, + "Cannot use comprehension in annotation scope within class scope"): + run_code(code) + + def test_nested_scope_in_generic_alias(self): + code = """ + class C[T]: + T = "class" + {} + """ + error_cases = [ + "type Alias1[T] = lambda: T", + "type Alias2 = lambda: T", + "type Alias3[T] = (T for _ in (1,))", + "type Alias4 = (T for _ in (1,))", + "type Alias5[T] = [T for _ in (1,)]", + "type Alias6 = [T for _ in (1,)]", + ] + for case in error_cases: + with self.subTest(case=case): + with self.assertRaisesRegex(SyntaxError, + r"Cannot use [a-z]+ in annotation scope within class scope"): + run_code(code.format(case)) + + +def make_base(arg): + class Base: + __arg__ = arg + return Base + def global_generic_func[T](): pass @@ -597,6 +694,19 @@ class Cls: cls = ns["outer"]() self.assertEqual(cls.Alias.__value__, "class") + def test_nested_free(self): + ns = run_code(""" + def f(): + T = str + class C: + T = int + class D[U](T): + x = T + return C + """) + C = ns["f"]() + self.assertIn(int, C.D.__bases__) + self.assertIs(C.D.x, str) class TypeParamsManglingTest(unittest.TestCase): def test_mangling(self): @@ -952,3 +1062,43 @@ class NewStyle[T]: for case in cases: with self.subTest(case=case): weakref.ref(case) + + +class TypeParamsRuntimeTest(unittest.TestCase): + def test_name_error(self): + # gh-109118: This crashed the interpreter due to a refcounting bug + code = """ + class name_2[name_5]: + class name_4[name_5](name_0): + pass + """ + with self.assertRaises(NameError): + run_code(code) + + # Crashed with a slightly different stack trace + code = """ + class name_2[name_5]: + class name_4[name_5: name_5](name_0): + pass + """ + with self.assertRaises(NameError): + run_code(code) + + def test_broken_class_namespace(self): + code = """ + class WeirdMapping(dict): + def __missing__(self, key): + if key == "T": + raise RuntimeError + raise KeyError(key) + + class Meta(type): + def __prepare__(name, bases): + return WeirdMapping() + + class MyClass[V](metaclass=Meta): + class Inner[U](T): + pass + """ + with self.assertRaises(RuntimeError): + run_code(code) diff --git a/Lib/test/test_types.py b/Lib/test/test_types.py index f2efee90dc0240..1acb2a4d81adf3 100644 --- a/Lib/test/test_types.py +++ b/Lib/test/test_types.py @@ -1,9 +1,10 @@ # Python test set -- part 6, built-in types -from test.support import run_with_locale, cpython_only +from test.support import run_with_locale, cpython_only, MISSING_C_DOCSTRINGS import collections.abc from collections import namedtuple import copy +import _datetime import gc import inspect import pickle @@ -597,6 +598,8 @@ def test_slot_wrapper_types(self): self.assertIsInstance(object.__lt__, types.WrapperDescriptorType) self.assertIsInstance(int.__lt__, types.WrapperDescriptorType) + @unittest.skipIf(MISSING_C_DOCSTRINGS, + "Signature information for builtins requires docstrings") def test_dunder_get_signature(self): sig = inspect.signature(object.__init__.__get__) self.assertEqual(list(sig.parameters), ["instance", "owner"]) @@ -636,6 +639,9 @@ def test_traceback_and_frame_types(self): self.assertIsInstance(exc.__traceback__, types.TracebackType) self.assertIsInstance(exc.__traceback__.tb_frame, types.FrameType) + def test_capsule_type(self): + self.assertIsInstance(_datetime.datetime_CAPI, types.CapsuleType) + class UnionTests(unittest.TestCase): @@ -1900,6 +1906,33 @@ def test_pickle(self): self.assertEqual(ns, ns_roundtrip, pname) + def test_replace(self): + ns = types.SimpleNamespace(x=11, y=22) + + ns2 = copy.replace(ns) + self.assertEqual(ns2, ns) + self.assertIsNot(ns2, ns) + self.assertIs(type(ns2), types.SimpleNamespace) + self.assertEqual(vars(ns2), {'x': 11, 'y': 22}) + ns2.x = 3 + self.assertEqual(ns.x, 11) + ns.x = 4 + self.assertEqual(ns2.x, 3) + + self.assertEqual(vars(copy.replace(ns, x=1)), {'x': 1, 'y': 22}) + self.assertEqual(vars(copy.replace(ns, y=2)), {'x': 4, 'y': 2}) + self.assertEqual(vars(copy.replace(ns, x=1, y=2)), {'x': 1, 'y': 2}) + + def test_replace_subclass(self): + class Spam(types.SimpleNamespace): + pass + + spam = Spam(ham=8, eggs=9) + spam2 = copy.replace(spam, ham=5) + + self.assertIs(type(spam2), Spam) + self.assertEqual(vars(spam2), {'ham': 5, 'eggs': 9}) + def test_fake_namespace_compare(self): # Issue #24257: Incorrect use of PyObject_IsInstance() caused # SystemError. @@ -2230,5 +2263,38 @@ def coro(): 'close', 'throw'})) +class FunctionTests(unittest.TestCase): + def test_function_type_defaults(self): + def ex(a, /, b, *, c): + return a + b + c + + func = types.FunctionType( + ex.__code__, {}, "func", (1, 2), None, {'c': 3}, + ) + + self.assertEqual(func(), 6) + self.assertEqual(func.__defaults__, (1, 2)) + self.assertEqual(func.__kwdefaults__, {'c': 3}) + + func = types.FunctionType( + ex.__code__, {}, "func", None, None, None, + ) + self.assertEqual(func.__defaults__, None) + self.assertEqual(func.__kwdefaults__, None) + + def test_function_type_wrong_defaults(self): + def ex(a, /, b, *, c): + return a + b + c + + with self.assertRaisesRegex(TypeError, 'arg 4'): + types.FunctionType( + ex.__code__, {}, "func", 1, None, {'c': 3}, + ) + with self.assertRaisesRegex(TypeError, 'arg 6'): + types.FunctionType( + ex.__code__, {}, "func", None, None, 3, + ) + + if __name__ == '__main__': unittest.main() diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py index 0450a87577ecea..8edab0cd6e34db 100644 --- a/Lib/test/test_typing.py +++ b/Lib/test/test_typing.py @@ -9,8 +9,7 @@ import pickle import re import sys -import warnings -from unittest import TestCase, main, skipUnless, skip +from unittest import TestCase, main, skip from unittest.mock import patch from copy import copy, deepcopy @@ -45,9 +44,8 @@ import weakref import types -from test.support import import_helper, captured_stderr, cpython_only -from test import mod_generics_cache -from test import _typed_dict_helper +from test.support import captured_stderr, cpython_only, infinite_recursion +from test.typinganndata import mod_generics_cache, _typed_dict_helper CANNOT_SUBCLASS_TYPE = 'Cannot subclass special typing classes' @@ -185,7 +183,7 @@ def test_cannot_subclass(self): class A(self.bottom_type): pass with self.assertRaisesRegex(TypeError, CANNOT_SUBCLASS_TYPE): - class A(type(self.bottom_type)): + class B(type(self.bottom_type)): pass def test_cannot_instantiate(self): @@ -282,7 +280,7 @@ class C(type(Self)): pass with self.assertRaisesRegex(TypeError, r'Cannot subclass typing\.Self'): - class C(Self): + class D(Self): pass def test_cannot_init(self): @@ -339,7 +337,7 @@ class C(type(LiteralString)): pass with self.assertRaisesRegex(TypeError, r'Cannot subclass typing\.LiteralString'): - class C(LiteralString): + class D(LiteralString): pass def test_cannot_init(self): @@ -483,7 +481,7 @@ class V(TypeVar): pass T = TypeVar("T") with self.assertRaisesRegex(TypeError, CANNOT_SUBCLASS_INSTANCE % 'TypeVar'): - class V(T): pass + class W(T): pass def test_cannot_instantiate_vars(self): with self.assertRaises(TypeError): @@ -544,6 +542,22 @@ def test_bad_var_substitution(self): with self.assertRaises(TypeError): list[T][arg] + def test_many_weakrefs(self): + # gh-108295: this used to segfault + for cls in (ParamSpec, TypeVarTuple, TypeVar): + with self.subTest(cls=cls): + vals = weakref.WeakValueDictionary() + + for x in range(10): + vals[x] = cls(str(x)) + del vals + + def test_constructor(self): + T = TypeVar(name="T") + self.assertEqual(T.__name__, "T") + self.assertEqual(T.__constraints__, ()) + self.assertIs(T.__bound__, None) + def template_replace(templates: list[str], replacements: dict[str, list[str]]) -> list[tuple[str]]: """Renders templates with possible combinations of replacements. @@ -1234,20 +1248,20 @@ class C(TypeVarTuple): pass Ts = TypeVarTuple('Ts') with self.assertRaisesRegex(TypeError, CANNOT_SUBCLASS_INSTANCE % 'TypeVarTuple'): - class C(Ts): pass + class D(Ts): pass with self.assertRaisesRegex(TypeError, CANNOT_SUBCLASS_TYPE): - class C(type(Unpack)): pass + class E(type(Unpack)): pass with self.assertRaisesRegex(TypeError, CANNOT_SUBCLASS_TYPE): - class C(type(*Ts)): pass + class F(type(*Ts)): pass with self.assertRaisesRegex(TypeError, CANNOT_SUBCLASS_TYPE): - class C(type(Unpack[Ts])): pass + class G(type(Unpack[Ts])): pass with self.assertRaisesRegex(TypeError, r'Cannot subclass typing\.Unpack'): - class C(Unpack): pass + class H(Unpack): pass with self.assertRaisesRegex(TypeError, r'Cannot subclass typing.Unpack\[Ts\]'): - class C(*Ts): pass + class I(*Ts): pass with self.assertRaisesRegex(TypeError, r'Cannot subclass typing.Unpack\[Ts\]'): - class C(Unpack[Ts]): pass + class J(Unpack[Ts]): pass def test_variadic_class_args_are_correct(self): T = TypeVar('T') @@ -1421,12 +1435,12 @@ def test_variadic_class_with_duplicate_typevartuples_fails(self): with self.assertRaises(TypeError): class C(Generic[*Ts1, *Ts1]): pass with self.assertRaises(TypeError): - class C(Generic[Unpack[Ts1], Unpack[Ts1]]): pass + class D(Generic[Unpack[Ts1], Unpack[Ts1]]): pass with self.assertRaises(TypeError): - class C(Generic[*Ts1, *Ts2, *Ts1]): pass + class E(Generic[*Ts1, *Ts2, *Ts1]): pass with self.assertRaises(TypeError): - class C(Generic[Unpack[Ts1], Unpack[Ts2], Unpack[Ts1]]): pass + class F(Generic[Unpack[Ts1], Unpack[Ts2], Unpack[Ts1]]): pass def test_type_concatenation_in_variadic_class_argument_list_succeeds(self): Ts = TypeVarTuple('Ts') @@ -1794,11 +1808,11 @@ def test_cannot_subclass(self): class C(Union): pass with self.assertRaisesRegex(TypeError, CANNOT_SUBCLASS_TYPE): - class C(type(Union)): + class D(type(Union)): pass with self.assertRaisesRegex(TypeError, r'Cannot subclass typing\.Union\[int, str\]'): - class C(Union[int, str]): + class E(Union[int, str]): pass def test_cannot_instantiate(self): @@ -1995,13 +2009,13 @@ def test_callable_instance_type_error(self): def f(): pass with self.assertRaises(TypeError): - self.assertIsInstance(f, Callable[[], None]) + isinstance(f, Callable[[], None]) with self.assertRaises(TypeError): - self.assertIsInstance(f, Callable[[], Any]) + isinstance(f, Callable[[], Any]) with self.assertRaises(TypeError): - self.assertNotIsInstance(None, Callable[[], None]) + isinstance(None, Callable[[], None]) with self.assertRaises(TypeError): - self.assertNotIsInstance(None, Callable[[], Any]) + isinstance(None, Callable[[], Any]) def test_repr(self): Callable = self.Callable @@ -2547,10 +2561,10 @@ class BP(Protocol): pass class P(C, Protocol): pass with self.assertRaises(TypeError): - class P(Protocol, C): + class Q(Protocol, C): pass with self.assertRaises(TypeError): - class P(BP, C, Protocol): + class R(BP, C, Protocol): pass class D(BP, C): pass @@ -2826,7 +2840,7 @@ class NotAProtocolButAnImplicitSubclass3: meth: Callable[[], None] meth2: Callable[[int, str], bool] def meth(self): pass - def meth(self, x, y): return True + def meth2(self, x, y): return True self.assertNotIsSubclass(AnnotatedButNotAProtocol, CallableMembersProto) self.assertIsSubclass(NotAProtocolButAnImplicitSubclass, CallableMembersProto) @@ -3434,8 +3448,8 @@ def meth(self): pass self.assertNotIn("__protocol_attrs__", vars(NonP)) self.assertNotIn("__protocol_attrs__", vars(NonPR)) - self.assertNotIn("__callable_proto_members_only__", vars(NonP)) - self.assertNotIn("__callable_proto_members_only__", vars(NonPR)) + self.assertNotIn("__non_callable_proto_members__", vars(NonP)) + self.assertNotIn("__non_callable_proto_members__", vars(NonPR)) self.assertEqual(get_protocol_members(P), {"x"}) self.assertEqual(get_protocol_members(PR), {"meth"}) @@ -3519,13 +3533,26 @@ def __subclasshook__(cls, other): def test_issubclass_fails_correctly(self): @runtime_checkable - class P(Protocol): + class NonCallableMembers(Protocol): x = 1 + class NotRuntimeCheckable(Protocol): + def callable_member(self) -> int: ... + + @runtime_checkable + class RuntimeCheckable(Protocol): + def callable_member(self) -> int: ... + class C: pass - with self.assertRaisesRegex(TypeError, r"issubclass\(\) arg 1 must be a class"): - issubclass(C(), P) + # These three all exercise different code paths, + # but should result in the same error message: + for protocol in NonCallableMembers, NotRuntimeCheckable, RuntimeCheckable: + with self.subTest(proto_name=protocol.__name__): + with self.assertRaisesRegex( + TypeError, r"issubclass\(\) arg 1 must be a class" + ): + issubclass(C(), protocol) def test_defining_generic_protocols(self): T = TypeVar('T') @@ -3648,11 +3675,11 @@ def test_protocols_bad_subscripts(self): with self.assertRaises(TypeError): class P(Protocol[T, T]): pass with self.assertRaises(TypeError): - class P(Protocol[int]): pass + class Q(Protocol[int]): pass with self.assertRaises(TypeError): - class P(Protocol[T], Protocol[S]): pass + class R(Protocol[T], Protocol[S]): pass with self.assertRaises(TypeError): - class P(typing.Mapping[T, S], Protocol[T]): pass + class S(typing.Mapping[T, S], Protocol[T]): pass def test_generic_protocols_repr(self): T = TypeVar('T') @@ -3791,6 +3818,39 @@ class E: self.assertIsInstance(E(), D) + def test_runtime_checkable_with_match_args(self): + @runtime_checkable + class P_regular(Protocol): + x: int + y: int + + @runtime_checkable + class P_match(Protocol): + __match_args__ = ('x', 'y') + x: int + y: int + + class Regular: + def __init__(self, x: int, y: int): + self.x = x + self.y = y + + class WithMatch: + __match_args__ = ('x', 'y', 'z') + def __init__(self, x: int, y: int, z: int): + self.x = x + self.y = y + self.z = z + + class Nope: ... + + self.assertIsInstance(Regular(1, 2), P_regular) + self.assertIsInstance(Regular(1, 2), P_match) + self.assertIsInstance(WithMatch(1, 2, 3), P_regular) + self.assertIsInstance(WithMatch(1, 2, 3), P_match) + self.assertNotIsInstance(Nope(), P_regular) + self.assertNotIsInstance(Nope(), P_match) + def test_supports_int(self): self.assertIsSubclass(int, typing.SupportsInt) self.assertNotIsSubclass(str, typing.SupportsInt) @@ -4044,6 +4104,56 @@ def method(self) -> None: ... self.assertIsInstance(Foo(), ProtocolWithMixedMembers) self.assertNotIsInstance(42, ProtocolWithMixedMembers) + def test_protocol_issubclass_error_message(self): + @runtime_checkable + class Vec2D(Protocol): + x: float + y: float + + def square_norm(self) -> float: + return self.x ** 2 + self.y ** 2 + + self.assertEqual(Vec2D.__protocol_attrs__, {'x', 'y', 'square_norm'}) + expected_error_message = ( + "Protocols with non-method members don't support issubclass()." + " Non-method members: 'x', 'y'." + ) + with self.assertRaisesRegex(TypeError, re.escape(expected_error_message)): + issubclass(int, Vec2D) + + def test_nonruntime_protocol_interaction_with_evil_classproperty(self): + class classproperty: + def __get__(self, instance, type): + raise RuntimeError("NO") + + class Commentable(Protocol): + evil = classproperty() + + # recognised as a protocol attr, + # but not actually accessed by the protocol metaclass + # (which would raise RuntimeError) for non-runtime protocols. + # See gh-113320 + self.assertEqual(get_protocol_members(Commentable), {"evil"}) + + def test_runtime_protocol_interaction_with_evil_classproperty(self): + class CustomError(Exception): pass + + class classproperty: + def __get__(self, instance, type): + raise CustomError + + with self.assertRaises(TypeError) as cm: + @runtime_checkable + class Commentable(Protocol): + evil = classproperty() + + exc = cm.exception + self.assertEqual( + exc.args[0], + "Failed to determine whether protocol member 'evil' is a method member" + ) + self.assertIs(type(exc.__cause__), CustomError) + class GenericTests(BaseTestCase): @@ -4084,12 +4194,28 @@ class NewGeneric(Generic): ... with self.assertRaises(TypeError): class MyGeneric(Generic[T], Generic[S]): ... with self.assertRaises(TypeError): - class MyGeneric(List[T], Generic[S]): ... + class MyGeneric2(List[T], Generic[S]): ... with self.assertRaises(TypeError): Generic[()] - class C(Generic[T]): pass + class D(Generic[T]): pass with self.assertRaises(TypeError): - C[()] + D[()] + + def test_generic_subclass_checks(self): + for typ in [list[int], List[int], + tuple[int, str], Tuple[int, str], + typing.Callable[..., None], + collections.abc.Callable[..., None]]: + with self.subTest(typ=typ): + self.assertRaises(TypeError, issubclass, typ, object) + self.assertRaises(TypeError, issubclass, typ, type) + self.assertRaises(TypeError, issubclass, typ, typ) + self.assertRaises(TypeError, issubclass, object, typ) + + # isinstance is fine: + self.assertTrue(isinstance(typ, object)) + # but, not when the right arg is also a generic: + self.assertRaises(TypeError, isinstance, typ, typ) def test_init(self): T = TypeVar('T') @@ -4810,7 +4936,7 @@ class Test(Generic[T], Final): class Subclass(Test): pass with self.assertRaises(FinalException): - class Subclass(Test[int]): + class Subclass2(Test[int]): pass def test_nested(self): @@ -5048,15 +5174,15 @@ def test_cannot_subclass(self): class C(type(ClassVar)): pass with self.assertRaisesRegex(TypeError, CANNOT_SUBCLASS_TYPE): - class C(type(ClassVar[int])): + class D(type(ClassVar[int])): pass with self.assertRaisesRegex(TypeError, r'Cannot subclass typing\.ClassVar'): - class C(ClassVar): + class E(ClassVar): pass with self.assertRaisesRegex(TypeError, r'Cannot subclass typing\.ClassVar\[int\]'): - class C(ClassVar[int]): + class F(ClassVar[int]): pass def test_cannot_init(self): @@ -5098,15 +5224,15 @@ def test_cannot_subclass(self): class C(type(Final)): pass with self.assertRaisesRegex(TypeError, CANNOT_SUBCLASS_TYPE): - class C(type(Final[int])): + class D(type(Final[int])): pass with self.assertRaisesRegex(TypeError, r'Cannot subclass typing\.Final'): - class C(Final): + class E(Final): pass with self.assertRaisesRegex(TypeError, r'Cannot subclass typing\.Final\[int\]'): - class C(Final[int]): + class F(Final[int]): pass def test_cannot_init(self): @@ -5361,7 +5487,7 @@ def test_errors(self): # We need this to make sure that `@no_type_check` respects `__module__` attr: -from test import ann_module8 +from test.typinganndata import ann_module8 @no_type_check class NoTypeCheck_Outer: @@ -5558,10 +5684,11 @@ def fun(x: a): pass def cmp(o1, o2): return o1 == o2 - r1 = namespace1() - r2 = namespace2() - self.assertIsNot(r1, r2) - self.assertRaises(RecursionError, cmp, r1, r2) + with infinite_recursion(): + r1 = namespace1() + r2 = namespace2() + self.assertIsNot(r1, r2) + self.assertRaises(RecursionError, cmp, r1, r2) def test_union_forward_recursion(self): ValueList = List['Value'] @@ -5952,7 +6079,9 @@ def test_overload_registry_repeated(self): # Definitions needed for features introduced in Python 3.6 -from test import ann_module, ann_module2, ann_module3, ann_module5, ann_module6 +from test.typinganndata import ( + ann_module, ann_module2, ann_module3, ann_module5, ann_module6, +) T_a = TypeVar('T_a') @@ -7237,15 +7366,15 @@ class A: class X(NamedTuple, A): x: int with self.assertRaises(TypeError): - class X(NamedTuple, tuple): + class Y(NamedTuple, tuple): x: int with self.assertRaises(TypeError): - class X(NamedTuple, NamedTuple): + class Z(NamedTuple, NamedTuple): x: int - class A(NamedTuple): + class B(NamedTuple): x: int with self.assertRaises(TypeError): - class X(NamedTuple, A): + class C(NamedTuple, B): y: str def test_generic(self): @@ -7453,6 +7582,83 @@ class GenericNamedTuple(NamedTuple, Generic[T]): self.assertEqual(CallNamedTuple.__orig_bases__, (NamedTuple,)) + def test_setname_called_on_values_in_class_dictionary(self): + class Vanilla: + def __set_name__(self, owner, name): + self.name = name + + class Foo(NamedTuple): + attr = Vanilla() + + foo = Foo() + self.assertEqual(len(foo), 0) + self.assertNotIn('attr', Foo._fields) + self.assertIsInstance(foo.attr, Vanilla) + self.assertEqual(foo.attr.name, "attr") + + class Bar(NamedTuple): + attr: Vanilla = Vanilla() + + bar = Bar() + self.assertEqual(len(bar), 1) + self.assertIn('attr', Bar._fields) + self.assertIsInstance(bar.attr, Vanilla) + self.assertEqual(bar.attr.name, "attr") + + def test_setname_raises_the_same_as_on_other_classes(self): + class CustomException(BaseException): pass + + class Annoying: + def __set_name__(self, owner, name): + raise CustomException + + annoying = Annoying() + + with self.assertRaises(CustomException) as cm: + class NormalClass: + attr = annoying + normal_exception = cm.exception + + with self.assertRaises(CustomException) as cm: + class NamedTupleClass(NamedTuple): + attr = annoying + namedtuple_exception = cm.exception + + self.assertIs(type(namedtuple_exception), CustomException) + self.assertIs(type(namedtuple_exception), type(normal_exception)) + + self.assertEqual(len(namedtuple_exception.__notes__), 1) + self.assertEqual( + len(namedtuple_exception.__notes__), len(normal_exception.__notes__) + ) + + expected_note = ( + "Error calling __set_name__ on 'Annoying' instance " + "'attr' in 'NamedTupleClass'" + ) + self.assertEqual(namedtuple_exception.__notes__[0], expected_note) + self.assertEqual( + namedtuple_exception.__notes__[0], + normal_exception.__notes__[0].replace("NormalClass", "NamedTupleClass") + ) + + def test_strange_errors_when_accessing_set_name_itself(self): + class CustomException(Exception): pass + + class Meta(type): + def __getattribute__(self, attr): + if attr == "__set_name__": + raise CustomException + return object.__getattribute__(self, attr) + + class VeryAnnoying(metaclass=Meta): pass + + very_annoying = VeryAnnoying() + + with self.assertRaises(CustomException): + class Foo(NamedTuple): + attr = very_annoying + class TypedDictTests(BaseTestCase): def test_basics_functional_syntax(self): @@ -7558,6 +7764,17 @@ def test_total(self): self.assertEqual(Options.__required_keys__, frozenset()) self.assertEqual(Options.__optional_keys__, {'log_level', 'log_path'}) + def test_total_inherits_non_total(self): + class TD1(TypedDict, total=False): + a: int + + self.assertIs(TD1.__total__, False) + + class TD2(TD1): + b: str + + self.assertIs(TD2.__total__, True) + def test_optional_keys(self): class Point2Dor3D(Point2D, total=False): z: int @@ -7599,6 +7816,46 @@ class Cat(Animal): 'voice': str, }) + def test_keys_inheritance_with_same_name(self): + class NotTotal(TypedDict, total=False): + a: int + + class Total(NotTotal): + a: int + + self.assertEqual(NotTotal.__required_keys__, frozenset()) + self.assertEqual(NotTotal.__optional_keys__, frozenset(['a'])) + self.assertEqual(Total.__required_keys__, frozenset(['a'])) + self.assertEqual(Total.__optional_keys__, frozenset()) + + class Base(TypedDict): + a: NotRequired[int] + b: Required[int] + + class Child(Base): + a: Required[int] + b: NotRequired[int] + + self.assertEqual(Base.__required_keys__, frozenset(['b'])) + self.assertEqual(Base.__optional_keys__, frozenset(['a'])) + self.assertEqual(Child.__required_keys__, frozenset(['a'])) + self.assertEqual(Child.__optional_keys__, frozenset(['b'])) + + def test_multiple_inheritance_with_same_key(self): + class Base1(TypedDict): + a: NotRequired[int] + + class Base2(TypedDict): + a: Required[str] + + class Child(Base1, Base2): + pass + + # Last base wins + self.assertEqual(Child.__annotations__, {'a': Required[str]}) + self.assertEqual(Child.__required_keys__, frozenset(['a'])) + self.assertEqual(Child.__optional_keys__, frozenset()) + def test_required_notrequired_keys(self): self.assertEqual(NontotalMovie.__required_keys__, frozenset({"title"})) @@ -7998,15 +8255,15 @@ def test_cannot_subclass(self): class C(type(Required)): pass with self.assertRaisesRegex(TypeError, CANNOT_SUBCLASS_TYPE): - class C(type(Required[int])): + class D(type(Required[int])): pass with self.assertRaisesRegex(TypeError, r'Cannot subclass typing\.Required'): - class C(Required): + class E(Required): pass with self.assertRaisesRegex(TypeError, r'Cannot subclass typing\.Required\[int\]'): - class C(Required[int]): + class F(Required[int]): pass def test_cannot_init(self): @@ -8046,15 +8303,15 @@ def test_cannot_subclass(self): class C(type(NotRequired)): pass with self.assertRaisesRegex(TypeError, CANNOT_SUBCLASS_TYPE): - class C(type(NotRequired[int])): + class D(type(NotRequired[int])): pass with self.assertRaisesRegex(TypeError, r'Cannot subclass typing\.NotRequired'): - class C(NotRequired): + class E(NotRequired): pass with self.assertRaisesRegex(TypeError, r'Cannot subclass typing\.NotRequired\[int\]'): - class C(NotRequired[int]): + class F(NotRequired[int]): pass def test_cannot_init(self): @@ -8153,7 +8410,7 @@ class A(typing.Match): TypeError, r"type 're\.Pattern' is not an acceptable base type", ): - class A(typing.Pattern): + class B(typing.Pattern): pass @@ -8161,8 +8418,7 @@ class AnnotatedTests(BaseTestCase): def test_new(self): with self.assertRaisesRegex( - TypeError, - 'Type Annotated cannot be instantiated', + TypeError, 'Cannot instantiate typing.Annotated', ): Annotated() @@ -8466,6 +8722,40 @@ class X(Annotated[int, (1, 10)]): ... self.assertEqual(X.__mro__, (X, int, object), "Annotated should be transparent.") + def test_annotated_cached_with_types(self): + class A(str): ... + class B(str): ... + + field_a1 = Annotated[str, A("X")] + field_a2 = Annotated[str, B("X")] + a1_metadata = field_a1.__metadata__[0] + a2_metadata = field_a2.__metadata__[0] + + self.assertIs(type(a1_metadata), A) + self.assertEqual(a1_metadata, A("X")) + self.assertIs(type(a2_metadata), B) + self.assertEqual(a2_metadata, B("X")) + self.assertIsNot(type(a1_metadata), type(a2_metadata)) + + field_b1 = Annotated[str, A("Y")] + field_b2 = Annotated[str, B("Y")] + b1_metadata = field_b1.__metadata__[0] + b2_metadata = field_b2.__metadata__[0] + + self.assertIs(type(b1_metadata), A) + self.assertEqual(b1_metadata, A("Y")) + self.assertIs(type(b2_metadata), B) + self.assertEqual(b2_metadata, B("Y")) + self.assertIsNot(type(b1_metadata), type(b2_metadata)) + + field_c1 = Annotated[int, 1] + field_c2 = Annotated[int, 1.0] + field_c3 = Annotated[int, True] + + self.assertIs(type(field_c1.__metadata__[0]), int) + self.assertIs(type(field_c2.__metadata__[0]), float) + self.assertIs(type(field_c3.__metadata__[0]), bool) + class TypeAliasTests(BaseTestCase): def test_canonical_usage_with_variable_annotation(self): @@ -8501,7 +8791,7 @@ class C(TypeAlias): pass with self.assertRaises(TypeError): - class C(type(TypeAlias)): + class D(type(TypeAlias)): pass def test_repr(self): @@ -8891,19 +9181,19 @@ def test_cannot_subclass(self): with self.assertRaisesRegex(TypeError, NOT_A_BASE_TYPE % 'ParamSpec'): class C(ParamSpec): pass with self.assertRaisesRegex(TypeError, NOT_A_BASE_TYPE % 'ParamSpecArgs'): - class C(ParamSpecArgs): pass + class D(ParamSpecArgs): pass with self.assertRaisesRegex(TypeError, NOT_A_BASE_TYPE % 'ParamSpecKwargs'): - class C(ParamSpecKwargs): pass + class E(ParamSpecKwargs): pass P = ParamSpec('P') with self.assertRaisesRegex(TypeError, CANNOT_SUBCLASS_INSTANCE % 'ParamSpec'): - class C(P): pass + class F(P): pass with self.assertRaisesRegex(TypeError, CANNOT_SUBCLASS_INSTANCE % 'ParamSpecArgs'): - class C(P.args): pass + class G(P.args): pass with self.assertRaisesRegex(TypeError, CANNOT_SUBCLASS_INSTANCE % 'ParamSpecKwargs'): - class C(P.kwargs): pass + class H(P.kwargs): pass class ConcatenateTests(BaseTestCase): @@ -8984,15 +9274,15 @@ def test_cannot_subclass(self): class C(type(TypeGuard)): pass with self.assertRaisesRegex(TypeError, CANNOT_SUBCLASS_TYPE): - class C(type(TypeGuard[int])): + class D(type(TypeGuard[int])): pass with self.assertRaisesRegex(TypeError, r'Cannot subclass typing\.TypeGuard'): - class C(TypeGuard): + class E(TypeGuard): pass with self.assertRaisesRegex(TypeError, r'Cannot subclass typing\.TypeGuard\[int\]'): - class C(TypeGuard[int]): + class F(TypeGuard[int]): pass def test_cannot_init(self): @@ -9335,6 +9625,10 @@ def test_all(self): self.assertIn('SupportsComplex', a) def test_all_exported_names(self): + # ensure all dynamically created objects are actualised + for name in typing.__all__: + getattr(typing, name) + actual_all = set(typing.__all__) computed_all = { k for k, v in vars(typing).items() @@ -9384,5 +9678,11 @@ def test_is_not_instance_of_iterable(self): self.assertNotIsInstance(type_to_test, collections.abc.Iterable) +def load_tests(loader, tests, pattern): + import doctest + tests.addTests(doctest.DocTestSuite(typing)) + return tests + + if __name__ == '__main__': main() diff --git a/Lib/test/test_unicode_identifiers.py b/Lib/test/test_unicode_identifiers.py index 5b9ced5d1cb837..63c6c055824b20 100644 --- a/Lib/test/test_unicode_identifiers.py +++ b/Lib/test/test_unicode_identifiers.py @@ -19,7 +19,7 @@ def test_non_bmp_normalized(self): def test_invalid(self): try: - from test import badsyntax_3131 + from test.tokenizedata import badsyntax_3131 except SyntaxError as err: self.assertEqual(str(err), "invalid character '€' (U+20AC) (badsyntax_3131.py, line 2)") diff --git a/Lib/test/test_unicodedata.py b/Lib/test/test_unicodedata.py index 3dc0790ca15b41..d3bf4ea7c7d437 100644 --- a/Lib/test/test_unicodedata.py +++ b/Lib/test/test_unicodedata.py @@ -18,7 +18,7 @@ class UnicodeMethodsTest(unittest.TestCase): # update this, if the database changes - expectedchecksum = 'e708c31c0d51f758adf475cb7201cf80917362be' + expectedchecksum = '63aa77dcb36b0e1df082ee2a6071caeda7f0955e' @requires_resource('cpu') def test_method_checksum(self): @@ -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 = '26ff0d31c14194b4606a5b3a81ac36df3a14e331' + expectedchecksum = '232affd2a50ec4bd69d2482aa0291385cbdefaba' @requires_resource('cpu') def test_function_checksum(self): @@ -104,6 +104,26 @@ def test_name_inverse_lookup(self): if looked_name := self.db.name(char, None): self.assertEqual(self.db.lookup(looked_name), char) + def test_no_names_in_pua(self): + puas = [*range(0xe000, 0xf8ff), + *range(0xf0000, 0xfffff), + *range(0x100000, 0x10ffff)] + for i in puas: + char = chr(i) + self.assertRaises(ValueError, self.db.name, char) + + def test_lookup_nonexistant(self): + # just make sure that lookup can fail + for nonexistant in [ + "LATIN SMLL LETR A", + "OPEN HANDS SIGHS", + "DREGS", + "HANDBUG", + "MODIFIER LETTER CYRILLIC SMALL QUESTION MARK", + "???", + ]: + self.assertRaises(KeyError, self.db.lookup, nonexistant) + def test_digit(self): self.assertEqual(self.db.digit('A', None), None) self.assertEqual(self.db.digit('9'), 9) @@ -313,6 +333,7 @@ def test_ucd_510(self): self.assertTrue("\u1d79".upper()=='\ua77d') self.assertTrue(".".upper()=='.') + @requires_resource('cpu') def test_bug_5828(self): self.assertEqual("\u1d79".lower(), "\u1d79") # Only U+0000 should have U+0000 as its upper/lower/titlecase variant @@ -353,6 +374,7 @@ def unistr(data): return "".join([chr(x) for x in data]) @requires_resource('network') + @requires_resource('cpu') def test_normalization(self): TESTDATAFILE = "NormalizationTest.txt" TESTDATAURL = f"http://www.pythontest.net/unicode/{unicodedata.unidata_version}/{TESTDATAFILE}" diff --git a/Lib/test/test_unittest/test_async_case.py b/Lib/test/test_unittest/test_async_case.py index a465103b59b6ec..ba1ab838cd4a22 100644 --- a/Lib/test/test_unittest/test_async_case.py +++ b/Lib/test/test_unittest/test_async_case.py @@ -484,5 +484,19 @@ async def test_demo1(self): result = test.run() self.assertTrue(result.wasSuccessful()) + def test_loop_factory(self): + asyncio.set_event_loop_policy(None) + + class TestCase1(unittest.IsolatedAsyncioTestCase): + loop_factory = asyncio.EventLoop + + async def test_demo1(self): + pass + + test = TestCase1('test_demo1') + result = test.run() + self.assertTrue(result.wasSuccessful()) + self.assertIsNone(support.maybe_get_event_loop_policy()) + if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_unittest/test_discovery.py b/Lib/test/test_unittest/test_discovery.py index 946fa1258ea25e..dcb72d73efceab 100644 --- a/Lib/test/test_unittest/test_discovery.py +++ b/Lib/test/test_unittest/test_discovery.py @@ -6,7 +6,6 @@ import pickle from test import support from test.support import import_helper -import test.test_importlib.util import unittest import unittest.mock @@ -572,7 +571,7 @@ def _get_module_from_name(name): result = unittest.TestResult() suite.run(result) self.assertEqual(len(result.skipped), 1) - self.assertEqual(result.testsRun, 1) + self.assertEqual(result.testsRun, 0) self.assertEqual(import_calls, ['my_package']) # Check picklability @@ -826,6 +825,8 @@ def restore(): 'as dotted module names') def test_discovery_failed_discovery(self): + from test.test_importlib import util + loader = unittest.TestLoader() package = types.ModuleType('package') @@ -837,7 +838,7 @@ def _import(packagename, *args, **kwargs): # Since loader.discover() can modify sys.path, restore it when done. with import_helper.DirsOnSysPath(): # Make sure to remove 'package' from sys.modules when done. - with test.test_importlib.util.uncache('package'): + with util.uncache('package'): with self.assertRaises(TypeError) as cm: loader.discover('package') self.assertEqual(str(cm.exception), diff --git a/Lib/test/test_unittest/test_loader.py b/Lib/test/test_unittest/test_loader.py index f32450c9223d8b..83dd25ca54623f 100644 --- a/Lib/test/test_unittest/test_loader.py +++ b/Lib/test/test_unittest/test_loader.py @@ -82,6 +82,22 @@ def runTest(self): self.assertIsInstance(suite, loader.suiteClass) self.assertEqual(list(suite), [Foo('runTest')]) + # "Do not load any tests from `TestCase` class itself." + def test_loadTestsFromTestCase__from_TestCase(self): + loader = unittest.TestLoader() + + suite = loader.loadTestsFromTestCase(unittest.TestCase) + self.assertIsInstance(suite, loader.suiteClass) + self.assertEqual(list(suite), []) + + # "Do not load any tests from `FunctionTestCase` class." + def test_loadTestsFromTestCase__from_FunctionTestCase(self): + loader = unittest.TestLoader() + + suite = loader.loadTestsFromTestCase(unittest.FunctionTestCase) + self.assertIsInstance(suite, loader.suiteClass) + self.assertEqual(list(suite), []) + ################################################################ ### /Tests for TestLoader.loadTestsFromTestCase @@ -103,6 +119,19 @@ def test(self): expected = [loader.suiteClass([MyTestCase('test')])] self.assertEqual(list(suite), expected) + # "This test ensures that internal `TestCase` subclasses are not loaded" + def test_loadTestsFromModule__TestCase_subclass_internals(self): + # See https://github.com/python/cpython/issues/84867 + m = types.ModuleType('m') + # Simulate imported names: + m.TestCase = unittest.TestCase + m.FunctionTestCase = unittest.FunctionTestCase + + loader = unittest.TestLoader() + suite = loader.loadTestsFromModule(m) + self.assertIsInstance(suite, loader.suiteClass) + self.assertEqual(list(suite), []) + # "This method searches `module` for classes derived from TestCase" # # What happens if no tests are found (no TestCase instances)? diff --git a/Lib/test/test_unittest/test_program.py b/Lib/test/test_unittest/test_program.py index f6d52f93e4a25f..d8f5d3692a5088 100644 --- a/Lib/test/test_unittest/test_program.py +++ b/Lib/test/test_unittest/test_program.py @@ -167,6 +167,18 @@ def test_ExitAsDefault(self): 'expected failures=1, unexpected successes=1)\n') self.assertTrue(out.endswith(expected)) + def test_ExitSkippedSuite(self): + stream = BufferedWriter() + with self.assertRaises(SystemExit) as cm: + unittest.main( + argv=["foobar", "-k", "testSkipped"], + testRunner=unittest.TextTestRunner(stream=stream), + testLoader=self.TestLoader(self.FooBar)) + self.assertEqual(cm.exception.code, 0) + out = stream.getvalue() + expected = '\n\nOK (skipped=1)\n' + self.assertTrue(out.endswith(expected)) + def test_ExitEmptySuite(self): stream = BufferedWriter() with self.assertRaises(SystemExit) as cm: diff --git a/Lib/test/test_unittest/test_runner.py b/Lib/test/test_unittest/test_runner.py index f3b2c0cffd4513..1b9cef43e3f9c5 100644 --- a/Lib/test/test_unittest/test_runner.py +++ b/Lib/test/test_unittest/test_runner.py @@ -24,6 +24,13 @@ def getRunner(): stream=io.StringIO()) +class CustomError(Exception): + pass + +# For test output compat: +CustomErrorRepr = f"{__name__ + '.' if __name__ != '__main__' else ''}CustomError" + + def runTests(*cases): suite = unittest.TestSuite() for case in cases: @@ -46,7 +53,7 @@ def cleanup(ordering, blowUp=False): ordering.append('cleanup_good') else: ordering.append('cleanup_exc') - raise Exception('CleanUpExc') + raise CustomError('CleanUpExc') class TestCM: @@ -108,8 +115,8 @@ def testNothing(self): result = unittest.TestResult() outcome = test._outcome = _Outcome(result=result) - CleanUpExc = Exception('foo') - exc2 = Exception('bar') + CleanUpExc = CustomError('foo') + exc2 = CustomError('bar') def cleanup1(): raise CleanUpExc @@ -125,10 +132,10 @@ def cleanup2(): (_, msg2), (_, msg1) = result.errors self.assertIn('in cleanup1', msg1) self.assertIn('raise CleanUpExc', msg1) - self.assertIn('Exception: foo', msg1) + self.assertIn(f'{CustomErrorRepr}: foo', msg1) self.assertIn('in cleanup2', msg2) self.assertIn('raise exc2', msg2) - self.assertIn('Exception: bar', msg2) + self.assertIn(f'{CustomErrorRepr}: bar', msg2) def testCleanupInRun(self): blowUp = False @@ -139,7 +146,7 @@ def setUp(self): ordering.append('setUp') test.addCleanup(cleanup2) if blowUp: - raise Exception('foo') + raise CustomError('foo') def testNothing(self): ordering.append('test') @@ -280,7 +287,7 @@ def setUpClass(cls): ordering.append('setUpClass') cls.addClassCleanup(cleanup, ordering) if blowUp: - raise Exception() + raise CustomError() def testNothing(self): ordering.append('test') @classmethod @@ -306,7 +313,7 @@ def setUpClass(cls): ordering.append('setUpClass') cls.addClassCleanup(cleanup, ordering) if blowUp: - raise Exception() + raise CustomError() def testNothing(self): ordering.append('test') @classmethod @@ -346,7 +353,7 @@ def tearDownClass(cls): ordering = [] blowUp = True suite = unittest.defaultTestLoader.loadTestsFromTestCase(TestableTest) - with self.assertRaises(Exception) as cm: + with self.assertRaises(CustomError) as cm: suite.debug() self.assertEqual(str(cm.exception), 'CleanUpExc') self.assertEqual(ordering, @@ -366,10 +373,10 @@ def testNothing(self): @classmethod def tearDownClass(cls): ordering.append('tearDownClass') - raise Exception('TearDownClassExc') + raise CustomError('TearDownClassExc') suite = unittest.defaultTestLoader.loadTestsFromTestCase(TestableTest) - with self.assertRaises(Exception) as cm: + with self.assertRaises(CustomError) as cm: suite.debug() self.assertEqual(str(cm.exception), 'TearDownClassExc') self.assertEqual(ordering, ['setUpClass', 'test', 'tearDownClass']) @@ -379,7 +386,7 @@ def tearDownClass(cls): ordering = [] blowUp = True suite = unittest.defaultTestLoader.loadTestsFromTestCase(TestableTest) - with self.assertRaises(Exception) as cm: + with self.assertRaises(CustomError) as cm: suite.debug() self.assertEqual(str(cm.exception), 'TearDownClassExc') self.assertEqual(ordering, ['setUpClass', 'test', 'tearDownClass']) @@ -392,16 +399,22 @@ def testNothing(self): pass def cleanup1(): - raise Exception('cleanup1') + raise CustomError('cleanup1') def cleanup2(): - raise Exception('cleanup2') + raise CustomError('cleanup2') TestableTest.addClassCleanup(cleanup1) TestableTest.addClassCleanup(cleanup2) - with self.assertRaises(Exception) as e: - TestableTest.doClassCleanups() - self.assertEqual(e, 'cleanup1') + TestableTest.doClassCleanups() + + self.assertEqual(len(TestableTest.tearDown_exceptions), 2) + + e1, e2 = TestableTest.tearDown_exceptions + self.assertIsInstance(e1[1], CustomError) + self.assertEqual(str(e1[1]), 'cleanup2') + self.assertIsInstance(e2[1], CustomError) + self.assertEqual(str(e2[1]), 'cleanup1') def test_with_errors_addCleanUp(self): ordering = [] @@ -421,7 +434,7 @@ def tearDownClass(cls): result = runTests(TestableTest) self.assertEqual(result.errors[0][1].splitlines()[-1], - 'Exception: CleanUpExc') + f'{CustomErrorRepr}: CleanUpExc') self.assertEqual(ordering, ['setUpClass', 'setUp', 'cleanup_exc', 'tearDownClass', 'cleanup_good']) @@ -444,7 +457,7 @@ def tearDownClass(cls): result = runTests(TestableTest) self.assertEqual(result.errors[0][1].splitlines()[-1], - 'Exception: CleanUpExc') + f'{CustomErrorRepr}: CleanUpExc') self.assertEqual(ordering, ['setUpClass', 'setUp', 'test', 'cleanup_good', 'tearDownClass', 'cleanup_exc']) @@ -460,11 +473,11 @@ def setUpClass(cls): ordering.append('setUpClass') cls.addClassCleanup(cleanup, ordering, blowUp=True) if class_blow_up: - raise Exception('ClassExc') + raise CustomError('ClassExc') def setUp(self): ordering.append('setUp') if method_blow_up: - raise Exception('MethodExc') + raise CustomError('MethodExc') def testNothing(self): ordering.append('test') @classmethod @@ -473,7 +486,7 @@ def tearDownClass(cls): result = runTests(TestableTest) self.assertEqual(result.errors[0][1].splitlines()[-1], - 'Exception: CleanUpExc') + f'{CustomErrorRepr}: CleanUpExc') self.assertEqual(ordering, ['setUpClass', 'setUp', 'test', 'tearDownClass', 'cleanup_exc']) @@ -483,9 +496,9 @@ def tearDownClass(cls): method_blow_up = False result = runTests(TestableTest) self.assertEqual(result.errors[0][1].splitlines()[-1], - 'Exception: ClassExc') + f'{CustomErrorRepr}: ClassExc') self.assertEqual(result.errors[1][1].splitlines()[-1], - 'Exception: CleanUpExc') + f'{CustomErrorRepr}: CleanUpExc') self.assertEqual(ordering, ['setUpClass', 'cleanup_exc']) @@ -494,9 +507,9 @@ def tearDownClass(cls): method_blow_up = True result = runTests(TestableTest) self.assertEqual(result.errors[0][1].splitlines()[-1], - 'Exception: MethodExc') + f'{CustomErrorRepr}: MethodExc') self.assertEqual(result.errors[1][1].splitlines()[-1], - 'Exception: CleanUpExc') + f'{CustomErrorRepr}: CleanUpExc') self.assertEqual(ordering, ['setUpClass', 'setUp', 'tearDownClass', 'cleanup_exc']) @@ -513,11 +526,11 @@ def testNothing(self): @classmethod def tearDownClass(cls): ordering.append('tearDownClass') - raise Exception('TearDownExc') + raise CustomError('TearDownExc') result = runTests(TestableTest) self.assertEqual(result.errors[0][1].splitlines()[-1], - 'Exception: TearDownExc') + f'{CustomErrorRepr}: TearDownExc') self.assertEqual(ordering, ['setUpClass', 'test', 'tearDownClass', 'cleanup_good']) @@ -620,7 +633,7 @@ def module_cleanup_good(*args, **kwargs): module_cleanups.append((3, args, kwargs)) def module_cleanup_bad(*args, **kwargs): - raise Exception('CleanUpExc') + raise CustomError('CleanUpExc') class Module(object): unittest.addModuleCleanup(module_cleanup_good, 1, 2, 3, @@ -630,7 +643,7 @@ class Module(object): [(module_cleanup_good, (1, 2, 3), dict(four='hello', five='goodbye')), (module_cleanup_bad, (), {})]) - with self.assertRaises(Exception) as e: + with self.assertRaises(CustomError) as e: unittest.case.doModuleCleanups() self.assertEqual(str(e.exception), 'CleanUpExc') self.assertEqual(unittest.case._module_cleanups, []) @@ -659,7 +672,7 @@ def setUpModule(): ordering.append('setUpModule') unittest.addModuleCleanup(cleanup, ordering) if blowUp: - raise Exception('setUpModule Exc') + raise CustomError('setUpModule Exc') @staticmethod def tearDownModule(): ordering.append('tearDownModule') @@ -679,7 +692,7 @@ def tearDownClass(cls): result = runTests(TestableTest) self.assertEqual(ordering, ['setUpModule', 'cleanup_good']) self.assertEqual(result.errors[0][1].splitlines()[-1], - 'Exception: setUpModule Exc') + f'{CustomErrorRepr}: setUpModule Exc') ordering = [] blowUp = False @@ -699,7 +712,7 @@ def setUpModule(): ordering.append('setUpModule') unittest.addModuleCleanup(cleanup, ordering) if blowUp: - raise Exception() + raise CustomError() @staticmethod def tearDownModule(): ordering.append('tearDownModule') @@ -710,7 +723,7 @@ def setUpModule(): ordering.append('setUpModule2') unittest.addModuleCleanup(cleanup, ordering) if blowUp2: - raise Exception() + raise CustomError() @staticmethod def tearDownModule(): ordering.append('tearDownModule2') @@ -799,7 +812,7 @@ def setUpModule(): @staticmethod def tearDownModule(): ordering.append('tearDownModule') - raise Exception('CleanUpExc') + raise CustomError('CleanUpExc') class TestableTest(unittest.TestCase): @classmethod @@ -815,7 +828,7 @@ def tearDownClass(cls): sys.modules['Module'] = Module result = runTests(TestableTest) self.assertEqual(result.errors[0][1].splitlines()[-1], - 'Exception: CleanUpExc') + f'{CustomErrorRepr}: CleanUpExc') self.assertEqual(ordering, ['setUpModule', 'setUpClass', 'test', 'tearDownClass', 'tearDownModule', 'cleanup_good']) @@ -855,7 +868,7 @@ def tearDownClass(cls): ordering = [] blowUp = True suite = unittest.defaultTestLoader.loadTestsFromTestCase(TestableTest) - with self.assertRaises(Exception) as cm: + with self.assertRaises(CustomError) as cm: suite.debug() self.assertEqual(str(cm.exception), 'CleanUpExc') self.assertEqual(ordering, ['setUpModule', 'setUpClass', 'test', @@ -873,7 +886,7 @@ def setUpModule(): @staticmethod def tearDownModule(): ordering.append('tearDownModule') - raise Exception('TearDownModuleExc') + raise CustomError('TearDownModuleExc') class TestableTest(unittest.TestCase): @classmethod @@ -888,7 +901,7 @@ def tearDownClass(cls): TestableTest.__module__ = 'Module' sys.modules['Module'] = Module suite = unittest.defaultTestLoader.loadTestsFromTestCase(TestableTest) - with self.assertRaises(Exception) as cm: + with self.assertRaises(CustomError) as cm: suite.debug() self.assertEqual(str(cm.exception), 'TearDownModuleExc') self.assertEqual(ordering, ['setUpModule', 'setUpClass', 'test', @@ -899,7 +912,7 @@ def tearDownClass(cls): ordering = [] blowUp = True suite = unittest.defaultTestLoader.loadTestsFromTestCase(TestableTest) - with self.assertRaises(Exception) as cm: + with self.assertRaises(CustomError) as cm: suite.debug() self.assertEqual(str(cm.exception), 'TearDownModuleExc') self.assertEqual(ordering, ['setUpModule', 'setUpClass', 'test', @@ -978,7 +991,7 @@ def tearDownClass(cls): result = runTests(TestableTest) self.assertEqual(result.errors[0][1].splitlines()[-1], - 'Exception: CleanUpExc') + f'{CustomErrorRepr}: CleanUpExc') self.assertEqual(ordering, ['setUpModule', 'setUpClass', 'test', 'tearDownClass', 'cleanup_exc', 'tearDownModule', 'cleanup_good']) @@ -1008,7 +1021,7 @@ def tearDown(self): result = runTests(TestableTest) self.assertEqual(result.errors[0][1].splitlines()[-1], - 'Exception: CleanUpExc') + f'{CustomErrorRepr}: CleanUpExc') self.assertEqual(ordering, ['setUpModule', 'setUp', 'test', 'tearDown', 'cleanup_exc', 'tearDownModule', 'cleanup_good']) @@ -1024,7 +1037,7 @@ def setUpModule(): ordering.append('setUpModule') unittest.addModuleCleanup(cleanup, ordering, blowUp=True) if module_blow_up: - raise Exception('ModuleExc') + raise CustomError('ModuleExc') @staticmethod def tearDownModule(): ordering.append('tearDownModule') @@ -1034,11 +1047,11 @@ class TestableTest(unittest.TestCase): def setUpClass(cls): ordering.append('setUpClass') if class_blow_up: - raise Exception('ClassExc') + raise CustomError('ClassExc') def setUp(self): ordering.append('setUp') if method_blow_up: - raise Exception('MethodExc') + raise CustomError('MethodExc') def testNothing(self): ordering.append('test') @classmethod @@ -1050,7 +1063,7 @@ def tearDownClass(cls): result = runTests(TestableTest) self.assertEqual(result.errors[0][1].splitlines()[-1], - 'Exception: CleanUpExc') + f'{CustomErrorRepr}: CleanUpExc') self.assertEqual(ordering, ['setUpModule', 'setUpClass', 'setUp', 'test', 'tearDownClass', 'tearDownModule', @@ -1062,9 +1075,9 @@ def tearDownClass(cls): method_blow_up = False result = runTests(TestableTest) self.assertEqual(result.errors[0][1].splitlines()[-1], - 'Exception: ModuleExc') + f'{CustomErrorRepr}: ModuleExc') self.assertEqual(result.errors[1][1].splitlines()[-1], - 'Exception: CleanUpExc') + f'{CustomErrorRepr}: CleanUpExc') self.assertEqual(ordering, ['setUpModule', 'cleanup_exc']) ordering = [] @@ -1073,9 +1086,9 @@ def tearDownClass(cls): method_blow_up = False result = runTests(TestableTest) self.assertEqual(result.errors[0][1].splitlines()[-1], - 'Exception: ClassExc') + f'{CustomErrorRepr}: ClassExc') self.assertEqual(result.errors[1][1].splitlines()[-1], - 'Exception: CleanUpExc') + f'{CustomErrorRepr}: CleanUpExc') self.assertEqual(ordering, ['setUpModule', 'setUpClass', 'tearDownModule', 'cleanup_exc']) @@ -1085,9 +1098,9 @@ def tearDownClass(cls): method_blow_up = True result = runTests(TestableTest) self.assertEqual(result.errors[0][1].splitlines()[-1], - 'Exception: MethodExc') + f'{CustomErrorRepr}: MethodExc') self.assertEqual(result.errors[1][1].splitlines()[-1], - 'Exception: CleanUpExc') + f'{CustomErrorRepr}: CleanUpExc') self.assertEqual(ordering, ['setUpModule', 'setUpClass', 'setUp', 'tearDownClass', 'tearDownModule', 'cleanup_exc']) diff --git a/Lib/test/test_unittest/test_skipping.py b/Lib/test/test_unittest/test_skipping.py index f146dcac18ecc0..1a6af06d32b433 100644 --- a/Lib/test/test_unittest/test_skipping.py +++ b/Lib/test/test_unittest/test_skipping.py @@ -103,16 +103,16 @@ def test_dont_skip(self): pass result = LoggingResult(events) self.assertIs(suite.run(result), result) self.assertEqual(len(result.skipped), 1) - expected = ['startTest', 'addSkip', 'stopTest', - 'startTest', 'addSuccess', 'stopTest'] + expected = ['addSkip', 'stopTest', 'startTest', + 'addSuccess', 'stopTest'] self.assertEqual(events, expected) - self.assertEqual(result.testsRun, 2) + self.assertEqual(result.testsRun, 1) self.assertEqual(result.skipped, [(test_do_skip, "testing")]) self.assertTrue(result.wasSuccessful()) events = [] result = test_do_skip.run() - self.assertEqual(events, ['startTestRun', 'startTest', 'addSkip', + self.assertEqual(events, ['startTestRun', 'addSkip', 'stopTest', 'stopTestRun']) self.assertEqual(result.skipped, [(test_do_skip, "testing")]) @@ -135,13 +135,13 @@ def test_1(self): test = Foo("test_1") suite = unittest.TestSuite([test]) self.assertIs(suite.run(result), result) - self.assertEqual(events, ['startTest', 'addSkip', 'stopTest']) + self.assertEqual(events, ['addSkip', 'stopTest']) self.assertEqual(result.skipped, [(test, "testing")]) self.assertEqual(record, []) events = [] result = test.run() - self.assertEqual(events, ['startTestRun', 'startTest', 'addSkip', + self.assertEqual(events, ['startTestRun', 'addSkip', 'stopTest', 'stopTestRun']) self.assertEqual(result.skipped, [(test, "testing")]) self.assertEqual(record, []) diff --git a/Lib/test/test_unittest/testmock/testmock.py b/Lib/test/test_unittest/testmock/testmock.py index bb09913d70b7ca..1725406bcfb9e4 100644 --- a/Lib/test/test_unittest/testmock/testmock.py +++ b/Lib/test/test_unittest/testmock/testmock.py @@ -1058,7 +1058,7 @@ def test_assert_called_with_failure_message(self): actual = 'not called.' expected = "mock(1, '2', 3, bar='foo')" - message = 'expected call not found.\nExpected: %s\nActual: %s' + message = 'expected call not found.\nExpected: %s\n Actual: %s' self.assertRaisesWithMsg( AssertionError, message % (expected, actual), mock.assert_called_with, 1, '2', 3, bar='foo' @@ -1073,7 +1073,7 @@ def test_assert_called_with_failure_message(self): for meth in asserters: actual = "foo(1, '2', 3, foo='foo')" expected = "foo(1, '2', 3, bar='foo')" - message = 'expected call not found.\nExpected: %s\nActual: %s' + message = 'expected call not found.\nExpected: %s\n Actual: %s' self.assertRaisesWithMsg( AssertionError, message % (expected, actual), meth, 1, '2', 3, bar='foo' @@ -1083,7 +1083,7 @@ def test_assert_called_with_failure_message(self): for meth in asserters: actual = "foo(1, '2', 3, foo='foo')" expected = "foo(bar='foo')" - message = 'expected call not found.\nExpected: %s\nActual: %s' + message = 'expected call not found.\nExpected: %s\n Actual: %s' self.assertRaisesWithMsg( AssertionError, message % (expected, actual), meth, bar='foo' @@ -1093,7 +1093,7 @@ def test_assert_called_with_failure_message(self): for meth in asserters: actual = "foo(1, '2', 3, foo='foo')" expected = "foo(1, 2, 3)" - message = 'expected call not found.\nExpected: %s\nActual: %s' + message = 'expected call not found.\nExpected: %s\n Actual: %s' self.assertRaisesWithMsg( AssertionError, message % (expected, actual), meth, 1, 2, 3 @@ -1103,7 +1103,7 @@ def test_assert_called_with_failure_message(self): for meth in asserters: actual = "foo(1, '2', 3, foo='foo')" expected = "foo()" - message = 'expected call not found.\nExpected: %s\nActual: %s' + message = 'expected call not found.\nExpected: %s\n Actual: %s' self.assertRaisesWithMsg( AssertionError, message % (expected, actual), meth ) @@ -1547,25 +1547,33 @@ def f(x=None): pass mock = Mock(spec=f) mock(1) - with self.assertRaisesRegex( - AssertionError, - '^{}$'.format( - re.escape('Calls not found.\n' - 'Expected: [call()]\n' - 'Actual: [call(1)]'))) as cm: + with self.assertRaises(AssertionError) as cm: mock.assert_has_calls([call()]) + self.assertEqual(str(cm.exception), + 'Calls not found.\n' + 'Expected: [call()]\n' + ' Actual: [call(1)]' + ) self.assertIsNone(cm.exception.__cause__) + uncalled_mock = Mock() + with self.assertRaises(AssertionError) as cm: + uncalled_mock.assert_has_calls([call()]) + self.assertEqual(str(cm.exception), + 'Calls not found.\n' + 'Expected: [call()]\n' + ' Actual: []' + ) + self.assertIsNone(cm.exception.__cause__) - with self.assertRaisesRegex( - AssertionError, - '^{}$'.format( - re.escape( - 'Error processing expected calls.\n' - "Errors: [None, TypeError('too many positional arguments')]\n" - "Expected: [call(), call(1, 2)]\n" - 'Actual: [call(1)]'))) as cm: + with self.assertRaises(AssertionError) as cm: mock.assert_has_calls([call(), call(1, 2)]) + self.assertEqual(str(cm.exception), + 'Error processing expected calls.\n' + "Errors: [None, TypeError('too many positional arguments')]\n" + 'Expected: [call(), call(1, 2)]\n' + ' Actual: [call(1)]' + ) self.assertIsInstance(cm.exception.__cause__, TypeError) def test_assert_any_call(self): @@ -2270,7 +2278,7 @@ def test_misspelled_arguments(self): class Foo(): one = 'one' # patch, patch.object and create_autospec need to check for misspelled - # arguments explicitly and throw a RuntimError if found. + # arguments explicitly and throw a RuntimeError if found. with self.assertRaises(RuntimeError): with patch(f'{__name__}.Something.meth', autospect=True): pass with self.assertRaises(RuntimeError): diff --git a/Lib/test/test_unittest/testmock/testthreadingmock.py b/Lib/test/test_unittest/testmock/testthreadingmock.py index 94e71921d9bc03..a02b532ed447cd 100644 --- a/Lib/test/test_unittest/testmock/testthreadingmock.py +++ b/Lib/test/test_unittest/testmock/testthreadingmock.py @@ -3,7 +3,7 @@ import concurrent.futures from test.support import threading_helper -from unittest.mock import patch, ThreadingMock, call +from unittest.mock import patch, ThreadingMock threading_helper.requires_working_threading(module=True) diff --git a/Lib/test/test_unpack.py b/Lib/test/test_unpack.py index f5ca1d455b5c6f..515ec128a08a9c 100644 --- a/Lib/test/test_unpack.py +++ b/Lib/test/test_unpack.py @@ -162,7 +162,7 @@ def test_extended_oparg_not_ignored(self): ns = {} exec(code, ns) unpack_400 = ns["unpack_400"] - # Warm up the the function for quickening (PEP 659) + # Warm up the function for quickening (PEP 659) for _ in range(30): y = unpack_400(range(400)) self.assertEqual(y, 399) diff --git a/Lib/test/test_unparse.py b/Lib/test/test_unparse.py index b3efb61e83049e..6f698a8d891815 100644 --- a/Lib/test/test_unparse.py +++ b/Lib/test/test_unparse.py @@ -197,6 +197,10 @@ def test_fstrings_complicated(self): self.check_ast_roundtrip('''f"a\\r\\nb"''') self.check_ast_roundtrip('''f"\\u2028{'x'}"''') + def test_fstrings_pep701(self): + self.check_ast_roundtrip('f" something { my_dict["key"] } something else "') + self.check_ast_roundtrip('f"{f"{f"{f"{f"{f"{1+1}"}"}"}"}"}"') + def test_strings(self): self.check_ast_roundtrip("u'foo'") self.check_ast_roundtrip("r'foo'") @@ -378,8 +382,15 @@ def test_invalid_fstring_value(self): ) ) - def test_invalid_fstring_backslash(self): - self.check_invalid(ast.FormattedValue(value=ast.Constant(value="\\\\"))) + def test_fstring_backslash(self): + # valid since Python 3.12 + self.assertEqual(ast.unparse( + ast.FormattedValue( + value=ast.Constant(value="\\\\"), + conversion=-1, + format_spec=None, + ) + ), "{'\\\\\\\\'}") def test_invalid_yield_from(self): self.check_invalid(ast.YieldFrom(value=None)) @@ -502,11 +513,11 @@ def test_class_bases_and_keywords(self): self.check_src_roundtrip("class X(*args, **kwargs):\n pass") def test_fstrings(self): - self.check_src_roundtrip('''f\'\'\'-{f"""*{f"+{f'.{x}.'}+"}*"""}-\'\'\'''') - self.check_src_roundtrip('''f"\\u2028{'x'}"''') + self.check_src_roundtrip("f'-{f'*{f'+{f'.{x}.'}+'}*'}-'") + self.check_src_roundtrip("f'\\u2028{'x'}'") self.check_src_roundtrip(r"f'{x}\n'") - self.check_src_roundtrip('''f''\'{"""\n"""}\\n''\'''') - self.check_src_roundtrip('''f''\'{f"""{x}\n"""}\\n''\'''') + self.check_src_roundtrip("f'{'\\n'}\\n'") + self.check_src_roundtrip("f'{f'{x}\\n'}\\n'") def test_docstrings(self): docstrings = ( @@ -624,6 +635,20 @@ def test_star_expr_assign_target_multiple(self): self.check_src_roundtrip("[a, b] = [c, d] = [e, f] = g") self.check_src_roundtrip("a, b = [c, d] = e, f = g") + def test_multiquote_joined_string(self): + self.check_ast_roundtrip("f\"'''{1}\\\"\\\"\\\"\" ") + self.check_ast_roundtrip("""f"'''{1}""\\"" """) + self.check_ast_roundtrip("""f'""\"{1}''' """) + self.check_ast_roundtrip("""f'""\"{1}""\\"' """) + + self.check_ast_roundtrip("""f"'''{"\\n"}""\\"" """) + self.check_ast_roundtrip("""f'""\"{"\\n"}''' """) + self.check_ast_roundtrip("""f'""\"{"\\n"}""\\"' """) + + self.check_ast_roundtrip("""f'''""\"''\\'{"\\n"}''' """) + self.check_ast_roundtrip("""f'''""\"''\\'{"\\n\\"'"}''' """) + self.check_ast_roundtrip("""f'''""\"''\\'{""\"\\n\\"'''""\" '''\\n'''}''' """) + class ManualASTCreationTestCase(unittest.TestCase): """Test that AST nodes created without a type_params field unparse correctly.""" @@ -705,7 +730,8 @@ class DirectoryTestCase(ASTTestCase): test_directories = (lib_dir, lib_dir / "test") run_always_files = {"test_grammar.py", "test_syntax.py", "test_compile.py", "test_ast.py", "test_asdl_parser.py", "test_fstring.py", - "test_patma.py", "test_type_alias.py", "test_type_params.py"} + "test_patma.py", "test_type_alias.py", "test_type_params.py", + "test_tokenize.py"} _files_to_test = None diff --git a/Lib/test/test_urllib2_localnet.py b/Lib/test/test_urllib2_localnet.py index 0dcdbac76b50f2..50c491a3cfd3d0 100644 --- a/Lib/test/test_urllib2_localnet.py +++ b/Lib/test/test_urllib2_localnet.py @@ -21,9 +21,9 @@ here = os.path.dirname(__file__) # Self-signed cert file for 'localhost' -CERT_localhost = os.path.join(here, 'keycert.pem') +CERT_localhost = os.path.join(here, 'certdata', 'keycert.pem') # Self-signed cert file for 'fakehostname' -CERT_fakehostname = os.path.join(here, 'keycert2.pem') +CERT_fakehostname = os.path.join(here, 'certdata', 'keycert2.pem') # Loopback http server infrastructure diff --git a/Lib/test/test_urllib2net.py b/Lib/test/test_urllib2net.py index d8d882b2d33589..f0874d8d3ce463 100644 --- a/Lib/test/test_urllib2net.py +++ b/Lib/test/test_urllib2net.py @@ -133,6 +133,7 @@ def setUp(self): # XXX The rest of these tests aren't very good -- they don't check much. # They do sometimes catch some major disasters, though. + @support.requires_resource('walltime') def test_ftp(self): # Testing the same URL twice exercises the caching in CacheFTPHandler urls = [ @@ -196,6 +197,7 @@ def test_urlwithfrag(self): self.assertEqual(res.geturl(), "http://www.pythontest.net/index.html#frag") + @support.requires_resource('walltime') def test_redirect_url_withfrag(self): redirect_url_with_frag = "http://www.pythontest.net/redir/with_frag/" with socket_helper.transient_internet(redirect_url_with_frag): @@ -334,6 +336,7 @@ def test_http_timeout(self): FTP_HOST = 'ftp://www.pythontest.net/' + @support.requires_resource('walltime') def test_ftp_basic(self): self.assertIsNone(socket.getdefaulttimeout()) with socket_helper.transient_internet(self.FTP_HOST, timeout=None): @@ -352,6 +355,7 @@ def test_ftp_default_timeout(self): socket.setdefaulttimeout(None) self.assertEqual(u.fp.fp.raw._sock.gettimeout(), 60) + @support.requires_resource('walltime') def test_ftp_no_timeout(self): self.assertIsNone(socket.getdefaulttimeout()) with socket_helper.transient_internet(self.FTP_HOST): @@ -363,6 +367,7 @@ def test_ftp_no_timeout(self): socket.setdefaulttimeout(None) self.assertIsNone(u.fp.fp.raw._sock.gettimeout()) + @support.requires_resource('walltime') def test_ftp_timeout(self): with socket_helper.transient_internet(self.FTP_HOST): u = _urlopen_with_retry(self.FTP_HOST, timeout=60) diff --git a/Lib/test/test_urllibnet.py b/Lib/test/test_urllibnet.py index 773101ce41f602..49a3b5afdebb2f 100644 --- a/Lib/test/test_urllibnet.py +++ b/Lib/test/test_urllibnet.py @@ -109,6 +109,7 @@ def test_getcode(self): open_url.close() self.assertEqual(code, 404) + @support.requires_resource('walltime') def test_bad_address(self): # Make sure proper exception is raised when connecting to a bogus # address. @@ -191,6 +192,7 @@ def test_header(self): logo = "http://www.pythontest.net/" + @support.requires_resource('walltime') def test_data_header(self): with self.urlretrieve(self.logo) as (file_location, fileheaders): datevalue = fileheaders.get('Date') diff --git a/Lib/test/test_userdict.py b/Lib/test/test_userdict.py index 483910aaa4620e..9a03f2d04ce970 100644 --- a/Lib/test/test_userdict.py +++ b/Lib/test/test_userdict.py @@ -1,6 +1,6 @@ # Check every path through every method of UserDict -from test import mapping_tests +from test import mapping_tests, support import unittest import collections @@ -213,6 +213,11 @@ class G(collections.UserDict): else: self.fail("g[42] didn't raise KeyError") + # Decorate existing test with recursion limit, because + # the test is for C structure, but `UserDict` is a Python structure. + test_repr_deep = support.infinite_recursion()( + mapping_tests.TestHashMappingProtocol.test_repr_deep, + ) if __name__ == "__main__": diff --git a/Lib/test/test_userlist.py b/Lib/test/test_userlist.py index 1ed67dac805967..76d253753528b0 100644 --- a/Lib/test/test_userlist.py +++ b/Lib/test/test_userlist.py @@ -3,6 +3,8 @@ from collections import UserList from test import list_tests import unittest +from test import support + class UserListTest(list_tests.CommonTest): type2test = UserList @@ -65,5 +67,11 @@ def test_userlist_copy(self): self.assertEqual(u, v) self.assertEqual(type(u), type(v)) + # Decorate existing test with recursion limit, because + # the test is for C structure, but `UserList` is a Python structure. + test_repr_deep = support.infinite_recursion()( + list_tests.CommonTest.test_repr_deep, + ) + if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_utf8_mode.py b/Lib/test/test_utf8_mode.py index ec29ba6d51b127..f66881044e16df 100644 --- a/Lib/test/test_utf8_mode.py +++ b/Lib/test/test_utf8_mode.py @@ -9,10 +9,9 @@ import unittest from test import support from test.support.script_helper import assert_python_ok, assert_python_failure -from test.support import os_helper +from test.support import os_helper, MS_WINDOWS -MS_WINDOWS = (sys.platform == 'win32') POSIX_LOCALES = ('C', 'POSIX') VXWORKS = (sys.platform == "vxworks") diff --git a/Lib/test/test_utf8source.py b/Lib/test/test_utf8source.py index 97dced8a622889..c42b6aaaab579d 100644 --- a/Lib/test/test_utf8source.py +++ b/Lib/test/test_utf8source.py @@ -1,5 +1,3 @@ -# This file is marked as binary in the CVS, to prevent MacCVS from recoding it. - import unittest class PEP3120Test(unittest.TestCase): @@ -16,7 +14,7 @@ def test_pep3120(self): def test_badsyntax(self): try: - import test.badsyntax_pep3120 + import test.tokenizedata.badsyntax_pep3120 except SyntaxError as msg: msg = str(msg).lower() self.assertTrue('utf-8' in msg) diff --git a/Lib/test/test_venv.py b/Lib/test/test_venv.py index 3d19b2b2e905f3..8ecb23ff384362 100644 --- a/Lib/test/test_venv.py +++ b/Lib/test/test_venv.py @@ -20,7 +20,8 @@ from test.support import (captured_stdout, captured_stderr, skip_if_broken_multiprocessing_synchronize, verbose, requires_subprocess, is_emscripten, is_wasi, - requires_venv_with_pip, TEST_HOME_DIR) + requires_venv_with_pip, TEST_HOME_DIR, + requires_resource, copy_python_src_ignore) from test.support.os_helper import (can_symlink, EnvironmentVarGuard, rmtree) import unittest import venv @@ -46,13 +47,18 @@ def check_output(cmd, encoding=None): p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, - encoding=encoding) + env={**os.environ, "PYTHONHOME": ""}) out, err = p.communicate() if p.returncode: if verbose and err: - print(err.decode('utf-8', 'backslashreplace')) + print(err.decode(encoding or 'utf-8', 'backslashreplace')) raise subprocess.CalledProcessError( p.returncode, cmd, out, err) + if encoding: + return ( + out.decode(encoding, 'backslashreplace'), + err.decode(encoding, 'backslashreplace'), + ) return out, err class BaseTest(unittest.TestCase): @@ -81,6 +87,13 @@ def setUp(self): def tearDown(self): rmtree(self.env_dir) + def envpy(self, *, real_env_dir=False): + if real_env_dir: + env_dir = os.path.realpath(self.env_dir) + else: + env_dir = self.env_dir + return os.path.join(env_dir, self.bindir, self.exe) + def run_with_capture(self, func, *args, **kwargs): with captured_stdout() as output: with captured_stderr() as error: @@ -137,7 +150,8 @@ def _check_output_of_default_create(self): self.assertIn('executable = %s' % os.path.realpath(sys.executable), data) copies = '' if os.name=='nt' else ' --copies' - cmd = f'command = {sys.executable} -m venv{copies} --without-pip {self.env_dir}' + cmd = (f'command = {sys.executable} -m venv{copies} --without-pip ' + f'--without-scm-ignore-files {self.env_dir}') self.assertIn(cmd, data) fn = self.get_env_file(self.bindir, self.exe) if not os.path.exists(fn): # diagnostics for Windows buildbot failures @@ -147,35 +161,37 @@ def _check_output_of_default_create(self): self.assertTrue(os.path.exists(fn), 'File %r should exist.' % fn) def test_config_file_command_key(self): - attrs = [ - (None, None), - ('symlinks', '--copies'), - ('with_pip', '--without-pip'), - ('system_site_packages', '--system-site-packages'), - ('clear', '--clear'), - ('upgrade', '--upgrade'), - ('upgrade_deps', '--upgrade-deps'), - ('prompt', '--prompt'), + options = [ + (None, None, None), # Default case. + ('--copies', 'symlinks', False), + ('--without-pip', 'with_pip', False), + ('--system-site-packages', 'system_site_packages', True), + ('--clear', 'clear', True), + ('--upgrade', 'upgrade', True), + ('--upgrade-deps', 'upgrade_deps', True), + ('--prompt', 'prompt', True), + ('--without-scm-ignore-files', 'scm_ignore_files', frozenset()), ] - for attr, opt in attrs: - rmtree(self.env_dir) - if not attr: - b = venv.EnvBuilder() - else: - b = venv.EnvBuilder( - **{attr: False if attr in ('with_pip', 'symlinks') else True}) - b.upgrade_dependencies = Mock() # avoid pip command to upgrade deps - b._setup_pip = Mock() # avoid pip setup - self.run_with_capture(b.create, self.env_dir) - data = self.get_text_file_contents('pyvenv.cfg') - if not attr: - for opt in ('--system-site-packages', '--clear', '--upgrade', - '--upgrade-deps', '--prompt'): - self.assertNotRegex(data, rf'command = .* {opt}') - elif os.name=='nt' and attr=='symlinks': - pass - else: - self.assertRegex(data, rf'command = .* {opt}') + for opt, attr, value in options: + with self.subTest(opt=opt, attr=attr, value=value): + rmtree(self.env_dir) + if not attr: + kwargs = {} + else: + kwargs = {attr: value} + b = venv.EnvBuilder(**kwargs) + b.upgrade_dependencies = Mock() # avoid pip command to upgrade deps + b._setup_pip = Mock() # avoid pip setup + self.run_with_capture(b.create, self.env_dir) + data = self.get_text_file_contents('pyvenv.cfg') + if not attr or opt.endswith('git'): + for opt in ('--system-site-packages', '--clear', '--upgrade', + '--upgrade-deps', '--prompt'): + self.assertNotRegex(data, rf'command = .* {opt}') + elif os.name=='nt' and attr=='symlinks': + pass + else: + self.assertRegex(data, rf'command = .* {opt}') def test_prompt(self): env_name = os.path.split(self.env_dir)[1] @@ -208,8 +224,7 @@ def test_prompt(self): def test_upgrade_dependencies(self): builder = venv.EnvBuilder() bin_path = 'Scripts' if sys.platform == 'win32' else 'bin' - python_exe_realpath = os.path.realpath(sys._base_executable) - python_exe = os.path.split(python_exe_realpath)[1] + python_exe = os.path.split(sys.executable)[1] with tempfile.TemporaryDirectory() as fake_env_dir: expect_exe = os.path.normcase( os.path.join(fake_env_dir, bin_path, python_exe) @@ -243,8 +258,7 @@ def test_prefixes(self): # check a venv's prefixes rmtree(self.env_dir) self.run_with_capture(venv.create, self.env_dir) - envpy = os.path.join(self.env_dir, self.bindir, self.exe) - cmd = [envpy, '-c', None] + cmd = [self.envpy(), '-c', None] for prefix, expected in ( ('prefix', self.env_dir), ('exec_prefix', self.env_dir), @@ -261,8 +275,7 @@ def test_sysconfig(self): """ rmtree(self.env_dir) self.run_with_capture(venv.create, self.env_dir, symlinks=False) - envpy = os.path.join(self.env_dir, self.bindir, self.exe) - cmd = [envpy, '-c', None] + cmd = [self.envpy(), '-c', None] for call, expected in ( # installation scheme ('get_preferred_scheme("prefix")', 'venv'), @@ -273,8 +286,18 @@ def test_sysconfig(self): ('get_config_h_filename()', sysconfig.get_config_h_filename())): with self.subTest(call): cmd[2] = 'import sysconfig; print(sysconfig.%s)' % call - out, err = check_output(cmd) - self.assertEqual(out.strip(), expected.encode(), err) + out, err = check_output(cmd, encoding='utf-8') + self.assertEqual(out.strip(), expected, err) + for attr, expected in ( + ('executable', self.envpy()), + # Usually compare to sys.executable, but if we're running in our own + # venv then we really need to compare to our base executable + ('_base_executable', sys._base_executable), + ): + with self.subTest(attr): + cmd[2] = f'import sys; print(sys.{attr})' + out, err = check_output(cmd, encoding='utf-8') + self.assertEqual(out.strip(), expected, err) @requireVenvCreate @unittest.skipUnless(can_symlink(), 'Needs symlinks') @@ -284,8 +307,7 @@ def test_sysconfig_symlinks(self): """ rmtree(self.env_dir) self.run_with_capture(venv.create, self.env_dir, symlinks=True) - envpy = os.path.join(self.env_dir, self.bindir, self.exe) - cmd = [envpy, '-c', None] + cmd = [self.envpy(), '-c', None] for call, expected in ( # installation scheme ('get_preferred_scheme("prefix")', 'venv'), @@ -296,8 +318,18 @@ def test_sysconfig_symlinks(self): ('get_config_h_filename()', sysconfig.get_config_h_filename())): with self.subTest(call): cmd[2] = 'import sysconfig; print(sysconfig.%s)' % call - out, err = check_output(cmd) - self.assertEqual(out.strip(), expected.encode(), err) + out, err = check_output(cmd, encoding='utf-8') + self.assertEqual(out.strip(), expected, err) + for attr, expected in ( + ('executable', self.envpy()), + # Usually compare to sys.executable, but if we're running in our own + # venv then we really need to compare to our base executable + ('_base_executable', sys._base_executable), + ): + with self.subTest(attr): + cmd[2] = f'import sys; print(sys.{attr})' + out, err = check_output(cmd, encoding='utf-8') + self.assertEqual(out.strip(), expected, err) if sys.platform == 'win32': ENV_SUBDIRS = ( @@ -424,8 +456,7 @@ def test_executable(self): """ rmtree(self.env_dir) self.run_with_capture(venv.create, self.env_dir) - envpy = os.path.join(os.path.realpath(self.env_dir), - self.bindir, self.exe) + envpy = self.envpy(real_env_dir=True) out, err = check_output([envpy, '-c', 'import sys; print(sys.executable)']) self.assertEqual(out.strip(), envpy.encode()) @@ -438,8 +469,7 @@ def test_executable_symlinks(self): rmtree(self.env_dir) builder = venv.EnvBuilder(clear=True, symlinks=True) builder.create(self.env_dir) - envpy = os.path.join(os.path.realpath(self.env_dir), - self.bindir, self.exe) + envpy = self.envpy(real_env_dir=True) out, err = check_output([envpy, '-c', 'import sys; print(sys.executable)']) self.assertEqual(out.strip(), envpy.encode()) @@ -454,7 +484,6 @@ def test_unicode_in_batch_file(self): builder = venv.EnvBuilder(clear=True) builder.create(env_dir) activate = os.path.join(env_dir, self.bindir, 'activate.bat') - envpy = os.path.join(env_dir, self.bindir, self.exe) out, err = check_output( [activate, '&', self.exe, '-c', 'print(0)'], encoding='oem', @@ -473,9 +502,7 @@ def test_multiprocessing(self): rmtree(self.env_dir) self.run_with_capture(venv.create, self.env_dir) - envpy = os.path.join(os.path.realpath(self.env_dir), - self.bindir, self.exe) - out, err = check_output([envpy, '-c', + out, err = check_output([self.envpy(real_env_dir=True), '-c', 'from multiprocessing import Pool; ' 'pool = Pool(1); ' 'print(pool.apply_async("Python".lower).get(3)); ' @@ -491,10 +518,8 @@ def test_multiprocessing_recursion(self): rmtree(self.env_dir) self.run_with_capture(venv.create, self.env_dir) - envpy = os.path.join(os.path.realpath(self.env_dir), - self.bindir, self.exe) script = os.path.join(TEST_HOME_DIR, '_test_venv_multiprocessing.py') - subprocess.check_call([envpy, script]) + subprocess.check_call([self.envpy(real_env_dir=True), script]) @unittest.skipIf(os.name == 'nt', 'not relevant on Windows') def test_deactivate_with_strict_bash_opts(self): @@ -521,9 +546,7 @@ def test_macos_env(self): builder = venv.EnvBuilder() builder.create(self.env_dir) - envpy = os.path.join(os.path.realpath(self.env_dir), - self.bindir, self.exe) - out, err = check_output([envpy, '-c', + out, err = check_output([self.envpy(real_env_dir=True), '-c', 'import os; print("__PYVENV_LAUNCHER__" in os.environ)']) self.assertEqual(out.strip(), 'False'.encode()) @@ -552,8 +575,7 @@ def test_zippath_from_non_installed_posix(self): self.addCleanup(rmtree, non_installed_dir) bindir = os.path.join(non_installed_dir, self.bindir) os.mkdir(bindir) - python_exe_realpath = os.path.realpath(sys._base_executable) - shutil.copy2(python_exe_realpath, bindir) + shutil.copy2(sys.executable, bindir) libdir = os.path.join(non_installed_dir, platlibdir, self.lib[1]) os.makedirs(libdir) landmark = os.path.join(libdir, "os.py") @@ -562,6 +584,7 @@ def test_zippath_from_non_installed_posix(self): platlibdir, stdlib_zip) additional_pythonpath_for_non_installed = [] + # Copy stdlib files to the non-installed python so venv can # correctly calculate the prefix. for eachpath in sys.path: @@ -571,14 +594,19 @@ def test_zippath_from_non_installed_posix(self): eachpath, os.path.join(non_installed_dir, platlibdir)) elif os.path.isfile(os.path.join(eachpath, "os.py")): - for name in os.listdir(eachpath): + names = os.listdir(eachpath) + ignored_names = copy_python_src_ignore(eachpath, names) + for name in names: + if name in ignored_names: + continue if name == "site-packages": continue fn = os.path.join(eachpath, name) if os.path.isfile(fn): shutil.copy(fn, libdir) elif os.path.isdir(fn): - shutil.copytree(fn, os.path.join(libdir, name)) + shutil.copytree(fn, os.path.join(libdir, name), + ignore=copy_python_src_ignore) else: additional_pythonpath_for_non_installed.append( eachpath) @@ -586,6 +614,7 @@ def test_zippath_from_non_installed_posix(self): "-m", "venv", "--without-pip", + "--without-scm-ignore-files", self.env_dir] # Our fake non-installed python is not fully functional because # it cannot find the extensions. Set PYTHONPATH so it can run the @@ -597,7 +626,7 @@ def test_zippath_from_non_installed_posix(self): # libpython.so ld_library_path = sysconfig.get_config_var("LIBDIR") if not ld_library_path or sysconfig.is_python_build(): - ld_library_path = os.path.abspath(os.path.dirname(python_exe_realpath)) + ld_library_path = os.path.abspath(os.path.dirname(sys.executable)) if sys.platform == 'darwin': ld_library_path_env = "DYLD_LIBRARY_PATH" else: @@ -610,13 +639,13 @@ def test_zippath_from_non_installed_posix(self): # prevent https://github.com/python/cpython/issues/104839 child_env["ASAN_OPTIONS"] = asan_options subprocess.check_call(cmd, env=child_env) - envpy = os.path.join(self.env_dir, self.bindir, self.exe) # Now check the venv created from the non-installed python has # correct zip path in pythonpath. - cmd = [envpy, '-S', '-c', 'import sys; print(sys.path)'] + cmd = [self.envpy(), '-S', '-c', 'import sys; print(sys.path)'] out, err = check_output(cmd) self.assertTrue(zip_landmark.encode() in out) + @requireVenvCreate def test_activate_shell_script_has_no_dos_newlines(self): """ Test that the `activate` shell script contains no CR LF. @@ -633,13 +662,80 @@ def test_activate_shell_script_has_no_dos_newlines(self): error_message = f"CR LF found in line {i}" self.assertFalse(line.endswith(b'\r\n'), error_message) + @requireVenvCreate + def test_scm_ignore_files_git(self): + """ + Test that a .gitignore file is created when "git" is specified. + The file should contain a `*\n` line. + """ + self.run_with_capture(venv.create, self.env_dir, + scm_ignore_files={'git'}) + file_lines = self.get_text_file_contents('.gitignore').splitlines() + self.assertIn('*', file_lines) + + @requireVenvCreate + def test_create_scm_ignore_files_multiple(self): + """ + Test that ``scm_ignore_files`` can work with multiple SCMs. + """ + bzrignore_name = ".bzrignore" + contents = "# For Bazaar.\n*\n" + + class BzrEnvBuilder(venv.EnvBuilder): + def create_bzr_ignore_file(self, context): + gitignore_path = os.path.join(context.env_dir, bzrignore_name) + with open(gitignore_path, 'w', encoding='utf-8') as file: + file.write(contents) + + builder = BzrEnvBuilder(scm_ignore_files={'git', 'bzr'}) + self.run_with_capture(builder.create, self.env_dir) + + gitignore_lines = self.get_text_file_contents('.gitignore').splitlines() + self.assertIn('*', gitignore_lines) + + bzrignore = self.get_text_file_contents(bzrignore_name) + self.assertEqual(bzrignore, contents) + + @requireVenvCreate + def test_create_scm_ignore_files_empty(self): + """ + Test that no default ignore files are created when ``scm_ignore_files`` + is empty. + """ + # scm_ignore_files is set to frozenset() by default. + self.run_with_capture(venv.create, self.env_dir) + with self.assertRaises(FileNotFoundError): + self.get_text_file_contents('.gitignore') + + self.assertIn("--without-scm-ignore-files", + self.get_text_file_contents('pyvenv.cfg')) + + @requireVenvCreate + def test_cli_with_scm_ignore_files(self): + """ + Test that default SCM ignore files are created by default via the CLI. + """ + self.run_with_capture(venv.main, ['--without-pip', self.env_dir]) + + gitignore_lines = self.get_text_file_contents('.gitignore').splitlines() + self.assertIn('*', gitignore_lines) + + @requireVenvCreate + def test_cli_without_scm_ignore_files(self): + """ + Test that ``--without-scm-ignore-files`` doesn't create SCM ignore files. + """ + args = ['--without-pip', '--without-scm-ignore-files', self.env_dir] + self.run_with_capture(venv.main, args) + + with self.assertRaises(FileNotFoundError): + self.get_text_file_contents('.gitignore') + @requireVenvCreate class EnsurePipTest(BaseTest): """Test venv module installation of pip.""" def assert_pip_not_installed(self): - envpy = os.path.join(os.path.realpath(self.env_dir), - self.bindir, self.exe) - out, err = check_output([envpy, '-c', + out, err = check_output([self.envpy(real_env_dir=True), '-c', 'try:\n import pip\nexcept ImportError:\n print("OK")']) # We force everything to text, so unittest gives the detailed diff # if we get unexpected results @@ -706,9 +802,9 @@ def do_test_with_pip(self, system_site_packages): system_site_packages=system_site_packages, with_pip=True) # Ensure pip is available in the virtual environment - envpy = os.path.join(os.path.realpath(self.env_dir), self.bindir, self.exe) # Ignore DeprecationWarning since pip code is not part of Python - out, err = check_output([envpy, '-W', 'ignore::DeprecationWarning', + out, err = check_output([self.envpy(real_env_dir=True), + '-W', 'ignore::DeprecationWarning', '-W', 'ignore::ImportWarning', '-I', '-m', 'pip', '--version']) # We force everything to text, so unittest gives the detailed diff @@ -729,7 +825,7 @@ def do_test_with_pip(self, system_site_packages): # It seems ensurepip._uninstall calls subprocesses which do not # inherit the interpreter settings. envvars["PYTHONWARNINGS"] = "ignore" - out, err = check_output([envpy, + out, err = check_output([self.envpy(real_env_dir=True), '-W', 'ignore::DeprecationWarning', '-W', 'ignore::ImportWarning', '-I', '-m', 'ensurepip._uninstall']) @@ -777,6 +873,7 @@ def nicer_error(self): ) @requires_venv_with_pip() + @requires_resource('cpu') def test_with_pip(self): self.do_test_with_pip(False) self.do_test_with_pip(True) diff --git a/Lib/test/test_warnings/__init__.py b/Lib/test/test_warnings/__init__.py index 83237f5fe0d1b3..50b0f3fff04c57 100644 --- a/Lib/test/test_warnings/__init__.py +++ b/Lib/test/test_warnings/__init__.py @@ -5,6 +5,8 @@ import re import sys import textwrap +import types +from typing import overload, get_overloads import unittest from test import support from test.support import import_helper @@ -16,6 +18,7 @@ from test.test_warnings.data import stacklevel as warning_tests import warnings as original_warnings +from warnings import deprecated py_warnings = import_helper.import_fresh_module('warnings', @@ -90,7 +93,7 @@ def test_module_all_attribute(self): self.assertTrue(hasattr(self.module, '__all__')) target_api = ["warn", "warn_explicit", "showwarning", "formatwarning", "filterwarnings", "simplefilter", - "resetwarnings", "catch_warnings"] + "resetwarnings", "catch_warnings", "deprecated"] self.assertSetEqual(set(self.module.__all__), set(target_api)) @@ -372,6 +375,28 @@ def test_append_duplicate(self): "appended duplicate changed order of filters" ) + def test_argument_validation(self): + with self.assertRaises(ValueError): + self.module.filterwarnings(action='foo') + with self.assertRaises(TypeError): + self.module.filterwarnings('ignore', message=0) + with self.assertRaises(TypeError): + self.module.filterwarnings('ignore', category=0) + with self.assertRaises(TypeError): + self.module.filterwarnings('ignore', category=int) + with self.assertRaises(TypeError): + self.module.filterwarnings('ignore', module=0) + with self.assertRaises(TypeError): + self.module.filterwarnings('ignore', lineno=int) + with self.assertRaises(ValueError): + self.module.filterwarnings('ignore', lineno=-1) + with self.assertRaises(ValueError): + self.module.simplefilter(action='foo') + with self.assertRaises(TypeError): + self.module.simplefilter('ignore', lineno=int) + with self.assertRaises(ValueError): + self.module.simplefilter('ignore', lineno=-1) + def test_catchwarnings_with_simplefilter_ignore(self): with original_warnings.catch_warnings(module=self.module): self.module.resetwarnings() @@ -1233,6 +1258,10 @@ def test_conflicting_envvar_and_command_line(self): self.assertEqual(stderr.splitlines(), [b"Traceback (most recent call last):", b" File \"\", line 1, in ", + b' import sys, warnings; sys.stdout.write(str(sys.warnoptions)); warnings.w' + b"arn('Message', DeprecationWarning)", + b' ~~~~~~~~~~' + b'~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^', b"DeprecationWarning: Message"]) def test_default_filter_configuration(self): @@ -1373,6 +1402,283 @@ def test_late_resource_warning(self): self.assertTrue(err.startswith(expected), ascii(err)) +class DeprecatedTests(unittest.TestCase): + def test_dunder_deprecated(self): + @deprecated("A will go away soon") + class A: + pass + + self.assertEqual(A.__deprecated__, "A will go away soon") + self.assertIsInstance(A, type) + + @deprecated("b will go away soon") + def b(): + pass + + self.assertEqual(b.__deprecated__, "b will go away soon") + self.assertIsInstance(b, types.FunctionType) + + @overload + @deprecated("no more ints") + def h(x: int) -> int: ... + @overload + def h(x: str) -> str: ... + def h(x): + return x + + overloads = get_overloads(h) + self.assertEqual(len(overloads), 2) + self.assertEqual(overloads[0].__deprecated__, "no more ints") + + def test_class(self): + @deprecated("A will go away soon") + class A: + pass + + with self.assertWarnsRegex(DeprecationWarning, "A will go away soon"): + A() + with self.assertWarnsRegex(DeprecationWarning, "A will go away soon"): + with self.assertRaises(TypeError): + A(42) + + def test_class_with_init(self): + @deprecated("HasInit will go away soon") + class HasInit: + def __init__(self, x): + self.x = x + + with self.assertWarnsRegex(DeprecationWarning, "HasInit will go away soon"): + instance = HasInit(42) + self.assertEqual(instance.x, 42) + + def test_class_with_new(self): + has_new_called = False + + @deprecated("HasNew will go away soon") + class HasNew: + def __new__(cls, x): + nonlocal has_new_called + has_new_called = True + return super().__new__(cls) + + def __init__(self, x) -> None: + self.x = x + + with self.assertWarnsRegex(DeprecationWarning, "HasNew will go away soon"): + instance = HasNew(42) + self.assertEqual(instance.x, 42) + self.assertTrue(has_new_called) + + def test_class_with_inherited_new(self): + new_base_called = False + + class NewBase: + def __new__(cls, x): + nonlocal new_base_called + new_base_called = True + return super().__new__(cls) + + def __init__(self, x) -> None: + self.x = x + + @deprecated("HasInheritedNew will go away soon") + class HasInheritedNew(NewBase): + pass + + with self.assertWarnsRegex(DeprecationWarning, "HasInheritedNew will go away soon"): + instance = HasInheritedNew(42) + self.assertEqual(instance.x, 42) + self.assertTrue(new_base_called) + + def test_class_with_new_but_no_init(self): + new_called = False + + @deprecated("HasNewNoInit will go away soon") + class HasNewNoInit: + def __new__(cls, x): + nonlocal new_called + new_called = True + obj = super().__new__(cls) + obj.x = x + return obj + + with self.assertWarnsRegex(DeprecationWarning, "HasNewNoInit will go away soon"): + instance = HasNewNoInit(42) + self.assertEqual(instance.x, 42) + self.assertTrue(new_called) + + def test_mixin_class(self): + @deprecated("Mixin will go away soon") + class Mixin: + pass + + class Base: + def __init__(self, a) -> None: + self.a = a + + with self.assertWarnsRegex(DeprecationWarning, "Mixin will go away soon"): + class Child(Base, Mixin): + pass + + instance = Child(42) + self.assertEqual(instance.a, 42) + + def test_existing_init_subclass(self): + @deprecated("C will go away soon") + class C: + def __init_subclass__(cls) -> None: + cls.inited = True + + with self.assertWarnsRegex(DeprecationWarning, "C will go away soon"): + C() + + with self.assertWarnsRegex(DeprecationWarning, "C will go away soon"): + class D(C): + pass + + self.assertTrue(D.inited) + self.assertIsInstance(D(), D) # no deprecation + + def test_existing_init_subclass_in_base(self): + class Base: + def __init_subclass__(cls, x) -> None: + cls.inited = x + + @deprecated("C will go away soon") + class C(Base, x=42): + pass + + self.assertEqual(C.inited, 42) + + with self.assertWarnsRegex(DeprecationWarning, "C will go away soon"): + C() + + with self.assertWarnsRegex(DeprecationWarning, "C will go away soon"): + class D(C, x=3): + pass + + self.assertEqual(D.inited, 3) + + def test_init_subclass_has_correct_cls(self): + init_subclass_saw = None + + @deprecated("Base will go away soon") + class Base: + def __init_subclass__(cls) -> None: + nonlocal init_subclass_saw + init_subclass_saw = cls + + self.assertIsNone(init_subclass_saw) + + with self.assertWarnsRegex(DeprecationWarning, "Base will go away soon"): + class C(Base): + pass + + self.assertIs(init_subclass_saw, C) + + def test_init_subclass_with_explicit_classmethod(self): + init_subclass_saw = None + + @deprecated("Base will go away soon") + class Base: + @classmethod + def __init_subclass__(cls) -> None: + nonlocal init_subclass_saw + init_subclass_saw = cls + + self.assertIsNone(init_subclass_saw) + + with self.assertWarnsRegex(DeprecationWarning, "Base will go away soon"): + class C(Base): + pass + + self.assertIs(init_subclass_saw, C) + + def test_function(self): + @deprecated("b will go away soon") + def b(): + pass + + with self.assertWarnsRegex(DeprecationWarning, "b will go away soon"): + b() + + def test_method(self): + class Capybara: + @deprecated("x will go away soon") + def x(self): + pass + + instance = Capybara() + with self.assertWarnsRegex(DeprecationWarning, "x will go away soon"): + instance.x() + + def test_property(self): + class Capybara: + @property + @deprecated("x will go away soon") + def x(self): + pass + + @property + def no_more_setting(self): + return 42 + + @no_more_setting.setter + @deprecated("no more setting") + def no_more_setting(self, value): + pass + + instance = Capybara() + with self.assertWarnsRegex(DeprecationWarning, "x will go away soon"): + instance.x + + with py_warnings.catch_warnings(): + py_warnings.simplefilter("error") + self.assertEqual(instance.no_more_setting, 42) + + with self.assertWarnsRegex(DeprecationWarning, "no more setting"): + instance.no_more_setting = 42 + + def test_category(self): + @deprecated("c will go away soon", category=RuntimeWarning) + def c(): + pass + + with self.assertWarnsRegex(RuntimeWarning, "c will go away soon"): + c() + + def test_turn_off_warnings(self): + @deprecated("d will go away soon", category=None) + def d(): + pass + + with py_warnings.catch_warnings(): + py_warnings.simplefilter("error") + d() + + def test_only_strings_allowed(self): + with self.assertRaisesRegex( + TypeError, + "Expected an object of type str for 'message', not 'type'" + ): + @deprecated + class Foo: ... + + with self.assertRaisesRegex( + TypeError, + "Expected an object of type str for 'message', not 'function'" + ): + @deprecated + def foo(): ... + + def test_no_retained_references_to_wrapper_instance(self): + @deprecated('depr') + def d(): pass + + self.assertFalse(any( + isinstance(cell.cell_contents, deprecated) for cell in d.__closure__ + )) + def setUpModule(): py_warnings.onceregistry.clear() c_warnings.onceregistry.clear() diff --git a/Lib/test/test_weakref.py b/Lib/test/test_weakref.py index 1bc1d05f7daba9..4cdd66d3769e0c 100644 --- a/Lib/test/test_weakref.py +++ b/Lib/test/test_weakref.py @@ -1933,6 +1933,7 @@ def test_threaded_weak_key_dict_copy(self): self.check_threaded_weak_dict_copy(weakref.WeakKeyDictionary, False) @threading_helper.requires_working_threading() + @support.requires_resource('cpu') def test_threaded_weak_key_dict_deepcopy(self): # Issue #35615: Weakref keys or values getting GC'ed during dict # copying should not result in a crash. @@ -1945,6 +1946,7 @@ def test_threaded_weak_value_dict_copy(self): self.check_threaded_weak_dict_copy(weakref.WeakValueDictionary, False) @threading_helper.requires_working_threading() + @support.requires_resource('cpu') def test_threaded_weak_value_dict_deepcopy(self): # Issue #35615: Weakref keys or values getting GC'ed during dict # copying should not result in a crash. diff --git a/Lib/test/test_weakset.py b/Lib/test/test_weakset.py index d6c88596cff71f..76e8e5c8ab7d3c 100644 --- a/Lib/test/test_weakset.py +++ b/Lib/test/test_weakset.py @@ -44,7 +44,7 @@ def setUp(self): def test_methods(self): weaksetmethods = dir(WeakSet) for method in dir(set): - if method == 'test_c_api' or method.startswith('_'): + if method.startswith('_'): continue self.assertIn(method, weaksetmethods, "WeakSet missing method " + method) diff --git a/Lib/test/test_webbrowser.py b/Lib/test/test_webbrowser.py index 2d695bc883131f..ca481c57c3d972 100644 --- a/Lib/test/test_webbrowser.py +++ b/Lib/test/test_webbrowser.py @@ -272,6 +272,17 @@ def test_register_preferred(self): self._check_registration(preferred=True) + @unittest.skipUnless(sys.platform == "darwin", "macOS specific test") + def test_no_xdg_settings_on_macOS(self): + # On macOS webbrowser should not use xdg-settings to + # look for X11 based browsers (for those users with + # XQuartz installed) + with mock.patch("subprocess.check_output") as ck_o: + webbrowser.register_standard_browsers() + + ck_o.assert_not_called() + + class ImportTest(unittest.TestCase): def test_register(self): webbrowser = import_helper.import_fresh_module('webbrowser') diff --git a/Lib/test/test_winconsoleio.py b/Lib/test/test_winconsoleio.py index 70a85552cc03b0..72ff9606908ed5 100644 --- a/Lib/test/test_winconsoleio.py +++ b/Lib/test/test_winconsoleio.py @@ -98,6 +98,16 @@ def test_open_name(self): self.assertIsInstance(f, ConIO) f.close() + def test_subclass_repr(self): + class TestSubclass(ConIO): + pass + + f = TestSubclass("CON") + with f: + self.assertIn(TestSubclass.__name__, repr(f)) + + self.assertIn(TestSubclass.__name__, repr(f)) + @unittest.skipIf(sys.getwindowsversion()[:2] <= (6, 1), "test does not work on Windows 7 and earlier") def test_conin_conout_names(self): diff --git a/Lib/test/test_wmi.py b/Lib/test/test_wmi.py index 3445702846d8a0..bf8c52e646dc18 100644 --- a/Lib/test/test_wmi.py +++ b/Lib/test/test_wmi.py @@ -1,17 +1,29 @@ # Test the internal _wmi module on Windows # This is used by the platform module, and potentially others +import time import unittest -from test.support import import_helper, requires_resource +from test.support import import_helper, requires_resource, LOOPBACK_TIMEOUT # Do this first so test will be skipped if module doesn't exist _wmi = import_helper.import_module('_wmi', required_on=['win']) +def wmi_exec_query(query): + # gh-112278: WMI maybe slow response when first call. + try: + return _wmi.exec_query(query) + except WindowsError as e: + if e.winerror != 258: + raise + time.sleep(LOOPBACK_TIMEOUT) + return _wmi.exec_query(query) + + class WmiTests(unittest.TestCase): def test_wmi_query_os_version(self): - r = _wmi.exec_query("SELECT Version FROM Win32_OperatingSystem").split("\0") + 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]) @@ -28,7 +40,7 @@ def test_wmi_query_repeated(self): def test_wmi_query_error(self): # Invalid queries fail with OSError try: - _wmi.exec_query("SELECT InvalidColumnName FROM InvalidTableName") + 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 @@ -42,7 +54,7 @@ def test_wmi_query_repeated_error(self): 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") + wmi_exec_query("not select, just in case someone tries something") @requires_resource('cpu') def test_wmi_query_overflow(self): @@ -50,11 +62,11 @@ def test_wmi_query_overflow(self): # Test multiple times to ensure consistency for _ in range(2): with self.assertRaises(OSError): - _wmi.exec_query("SELECT * FROM CIM_DataFile") + 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") + 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")) @@ -69,6 +81,6 @@ def test_wmi_query_threads(self): from concurrent.futures import ThreadPoolExecutor query = "SELECT ProcessId FROM Win32_Process WHERE ProcessId < 1000" with ThreadPoolExecutor(4) as pool: - task = [pool.submit(_wmi.exec_query, query) for _ in range(32)] + task = [pool.submit(wmi_exec_query, query) for _ in range(32)] for t in task: self.assertRegex(t.result(), "ProcessId=") diff --git a/Lib/test/test_xml_etree.py b/Lib/test/test_xml_etree.py index b9352cb865d027..80ee064896f59a 100644 --- a/Lib/test/test_xml_etree.py +++ b/Lib/test/test_xml_etree.py @@ -365,6 +365,7 @@ def test_path_cache(self): from xml.etree import ElementPath elem = ET.XML(SAMPLE_XML) + ElementPath._cache.clear() for i in range(10): ET.ElementTree(elem).find('./'+str(i)) cache_len_10 = len(ElementPath._cache) for i in range(10): ET.ElementTree(elem).find('./'+str(i)) @@ -2534,6 +2535,7 @@ def __eq__(self, o): e.extend([ET.Element('bar')]) self.assertRaises(ValueError, e.remove, X('baz')) + @support.infinite_recursion() def test_recursive_repr(self): # Issue #25455 e = ET.Element('foo') @@ -3926,8 +3928,9 @@ def test_issue14818(self): # -------------------------------------------------------------------- class NoAcceleratorTest(unittest.TestCase): - def setUp(self): - if not pyET: + @classmethod + def setUpClass(cls): + if ET is not pyET: raise unittest.SkipTest('only for the Python version') # Test that the C accelerator was not imported for pyET @@ -4192,8 +4195,7 @@ def get_option(config, option_name, default=None): # -------------------------------------------------------------------- - -def test_main(module=None): +def setUpModule(module=None): # When invoked without a module, runs the Python ET tests by loading pyET. # Otherwise, uses the given module as the ET. global pyET @@ -4205,63 +4207,30 @@ def test_main(module=None): global ET ET = module - test_classes = [ - ModuleTest, - ElementSlicingTest, - BasicElementTest, - BadElementTest, - BadElementPathTest, - ElementTreeTest, - IOTest, - ParseErrorTest, - XIncludeTest, - ElementTreeTypeTest, - ElementFindTest, - ElementIterTest, - TreeBuilderTest, - XMLParserTest, - XMLPullParserTest, - BugsTest, - KeywordArgsTest, - BoolTest, - C14NTest, - ] - - # These tests will only run for the pure-Python version that doesn't import - # _elementtree. We can't use skipUnless here, because pyET is filled in only - # after the module is loaded. - if pyET is not ET: - test_classes.extend([ - NoAcceleratorTest, - ]) + # don't interfere with subsequent tests + def cleanup(): + global ET, pyET + ET = pyET = None + unittest.addModuleCleanup(cleanup) # Provide default namespace mapping and path cache. from xml.etree import ElementPath nsmap = ET.register_namespace._namespace_map # Copy the default namespace mapping nsmap_copy = nsmap.copy() + unittest.addModuleCleanup(nsmap.update, nsmap_copy) + unittest.addModuleCleanup(nsmap.clear) + # Copy the path cache (should be empty) path_cache = ElementPath._cache + unittest.addModuleCleanup(setattr, ElementPath, "_cache", path_cache) ElementPath._cache = path_cache.copy() + # Align the Comment/PI factories. if hasattr(ET, '_set_factories'): old_factories = ET._set_factories(ET.Comment, ET.PI) - else: - old_factories = None - - try: - support.run_unittest(*test_classes) - finally: - from xml.etree import ElementPath - # Restore mapping and path cache - nsmap.clear() - nsmap.update(nsmap_copy) - ElementPath._cache = path_cache - if old_factories is not None: - ET._set_factories(*old_factories) - # don't interfere with subsequent tests - ET = pyET = None + unittest.addModuleCleanup(ET._set_factories, *old_factories) if __name__ == '__main__': - test_main() + unittest.main() diff --git a/Lib/test/test_xml_etree_c.py b/Lib/test/test_xml_etree_c.py index fd27b575ec8dc9..3a0fc572f457ff 100644 --- a/Lib/test/test_xml_etree_c.py +++ b/Lib/test/test_xml_etree_c.py @@ -254,20 +254,25 @@ def test_element_with_children(self): self.check_sizeof(e, self.elementsize + self.extra + struct.calcsize('8P')) -def test_main(): - from test import test_xml_etree - - # Run the tests specific to the C implementation - support.run_unittest( - MiscTests, - TestAliasWorking, - TestAcceleratorImported, - SizeofTest, - ) - # Run the same test suite as the Python module - test_xml_etree.test_main(module=cET) +def install_tests(): + # Test classes should have __module__ referring to this module. + from test import test_xml_etree + for name, base in vars(test_xml_etree).items(): + if isinstance(base, type) and issubclass(base, unittest.TestCase): + class Temp(base): + pass + Temp.__name__ = Temp.__qualname__ = name + Temp.__module__ = __name__ + assert name not in globals() + globals()[name] = Temp + +install_tests() + +def setUpModule(): + from test import test_xml_etree + test_xml_etree.setUpModule(module=cET) if __name__ == '__main__': - test_main() + unittest.main() diff --git a/Lib/test/test_xmlrpc.py b/Lib/test/test_xmlrpc.py index edc741dbc60088..6c4b8384a3202e 100644 --- a/Lib/test/test_xmlrpc.py +++ b/Lib/test/test_xmlrpc.py @@ -1037,38 +1037,47 @@ def test_path2(self): self.assertEqual(p.add(6,8), 6+8) self.assertRaises(xmlrpclib.Fault, p.pow, 6, 8) + @support.requires_resource('walltime') def test_path3(self): p = xmlrpclib.ServerProxy(URL+"/is/broken") self.assertRaises(xmlrpclib.Fault, p.add, 6, 8) + @support.requires_resource('walltime') def test_invalid_path(self): p = xmlrpclib.ServerProxy(URL+"/invalid") self.assertRaises(xmlrpclib.Fault, p.add, 6, 8) + @support.requires_resource('walltime') def test_path_query_fragment(self): p = xmlrpclib.ServerProxy(URL+"/foo?k=v#frag") self.assertEqual(p.test(), "/foo?k=v#frag") + @support.requires_resource('walltime') def test_path_fragment(self): p = xmlrpclib.ServerProxy(URL+"/foo#frag") self.assertEqual(p.test(), "/foo#frag") + @support.requires_resource('walltime') def test_path_query(self): p = xmlrpclib.ServerProxy(URL+"/foo?k=v") self.assertEqual(p.test(), "/foo?k=v") + @support.requires_resource('walltime') def test_empty_path(self): p = xmlrpclib.ServerProxy(URL) self.assertEqual(p.test(), "/RPC2") + @support.requires_resource('walltime') def test_root_path(self): p = xmlrpclib.ServerProxy(URL + "/") self.assertEqual(p.test(), "/") + @support.requires_resource('walltime') def test_empty_path_query(self): p = xmlrpclib.ServerProxy(URL + "?k=v") self.assertEqual(p.test(), "?k=v") + @support.requires_resource('walltime') def test_empty_path_fragment(self): p = xmlrpclib.ServerProxy(URL + "#frag") self.assertEqual(p.test(), "#frag") diff --git a/Lib/test/test_zipfile/_path/test_path.py b/Lib/test/test_zipfile/_path/test_path.py index c66cb3cba69ebd..171ab6fdb5fc28 100644 --- a/Lib/test/test_zipfile/_path/test_path.py +++ b/Lib/test/test_zipfile/_path/test_path.py @@ -577,3 +577,15 @@ def test_getinfo_missing(self, alpharep): zipfile.Path(alpharep) with self.assertRaises(KeyError): alpharep.getinfo('does-not-exist') + + def test_root_folder_in_zipfile(self): + """ + gh-112795: Some tools or self constructed codes will add '/' folder to + the zip file, this is a strange behavior, but we should support it. + """ + in_memory_file = io.BytesIO() + zf = zipfile.ZipFile(in_memory_file, "w") + zf.mkdir('/') + zf.writestr('./a.txt', 'aaa') + tmpdir = pathlib.Path(self.fixtures.enter_context(temp_dir())) + zf.extractall(tmpdir) diff --git a/Lib/test/test_zipfile/test_core.py b/Lib/test/test_zipfile/test_core.py index 9960259c4cde0c..f7b6db465b4bc7 100644 --- a/Lib/test/test_zipfile/test_core.py +++ b/Lib/test/test_zipfile/test_core.py @@ -1754,7 +1754,7 @@ def test_unsupported_version(self): @requires_zlib() def test_read_unicode_filenames(self): # bug #10801 - fname = findfile('zip_cp437_header.zip') + fname = findfile('zip_cp437_header.zip', subdir='archivetestdata') with zipfile.ZipFile(fname) as zipfp: for name in zipfp.namelist(): zipfp.open(name).close() @@ -1769,13 +1769,9 @@ def test_write_unicode_filenames(self): self.assertEqual(zf.filelist[0].filename, "foo.txt") self.assertEqual(zf.filelist[1].filename, "\xf6.txt") - @requires_zlib() - def test_read_zipfile_containing_unicode_path_extra_field(self): + def create_zipfile_with_extra_data(self, filename, extra_data_name): with zipfile.ZipFile(TESTFN, mode='w') as zf: - # create a file with a non-ASCII name - filename = 'ì´ë¦„.txt' - filename_encoded = filename.encode('utf-8') - + filename_encoded = filename.encode("utf-8") # create a ZipInfo object with Unicode path extra field zip_info = zipfile.ZipInfo(filename) @@ -1785,7 +1781,7 @@ def test_read_zipfile_containing_unicode_path_extra_field(self): import zlib filename_crc = struct.pack('= (1, 2, 5, 3): + if ZLIB_RUNTIME_VERSION_TUPLE >= (1, 2, 5, 3): sync_opt.append('Z_BLOCK') sync_opt = [getattr(zlib, opt) for opt in sync_opt @@ -513,18 +526,7 @@ def test_odd_flush(self): # Try 17K of data # generate random data stream - try: - # In 2.3 and later, WichmannHill is the RNG of the bug report - gen = random.WichmannHill() - except AttributeError: - try: - # 2.2 called it Random - gen = random.Random() - except AttributeError: - # others might simply have a single RNG - gen = random - gen.seed(1) - data = gen.randbytes(17 * 1024) + data = random.randbytes(17 * 1024) # compress, sync-flush, and decompress first = co.compress(data) @@ -805,16 +807,7 @@ def test_large_unconsumed_tail(self, size): def test_wbits(self): # wbits=0 only supported since zlib v1.2.3.5 - # Register "1.2.3" as "1.2.3.0" - # or "1.2.0-linux","1.2.0.f","1.2.0.f-linux" - v = zlib.ZLIB_RUNTIME_VERSION.split('-', 1)[0].split('.') - if len(v) < 4: - v.append('0') - elif not v[-1].isnumeric(): - v[-1] = '0' - - v = tuple(map(int, v)) - supports_wbits_0 = v >= (1, 2, 3, 5) + supports_wbits_0 = ZLIB_RUNTIME_VERSION_TUPLE >= (1, 2, 3, 5) co = zlib.compressobj(level=1, wbits=15) zlib15 = co.compress(HAMLET_SCENE) + co.flush() @@ -989,10 +982,10 @@ def testEOFError(self): @bigmemtest(size=_4G + 100, memuse=3.3) def testDecompress4G(self, size): # "Test zlib._ZlibDecompressor.decompress() with >4GiB input" - blocksize = 10 * 1024 * 1024 + blocksize = min(10 * 1024 * 1024, size) block = random.randbytes(blocksize) try: - data = block * (size // blocksize + 1) + data = block * ((size-1) // blocksize + 1) compressed = zlib.compress(data) zlibd = zlib._ZlibDecompressor() decompressed = zlibd.decompress(compressed) diff --git a/Lib/test/test_zoneinfo/__init__.py b/Lib/test/test_zoneinfo/__init__.py index c3ea567103275d..4b16ecc31156a5 100644 --- a/Lib/test/test_zoneinfo/__init__.py +++ b/Lib/test/test_zoneinfo/__init__.py @@ -1,2 +1,5 @@ -from .test_zoneinfo import * -from .test_zoneinfo_property import * +import os +from test.support import load_package_tests + +def load_tests(*args): + return load_package_tests(os.path.dirname(__file__), *args) diff --git a/Lib/test/test_zoneinfo/test_zoneinfo.py b/Lib/test/test_zoneinfo/test_zoneinfo.py index ae921f7432c466..7b6b69d0109d88 100644 --- a/Lib/test/test_zoneinfo/test_zoneinfo.py +++ b/Lib/test/test_zoneinfo/test_zoneinfo.py @@ -17,6 +17,7 @@ from datetime import date, datetime, time, timedelta, timezone from functools import cached_property +from test.support import MISSING_C_DOCSTRINGS from test.test_zoneinfo import _support as test_support from test.test_zoneinfo._support import OS_ENV_LOCK, TZPATH_TEST_LOCK, ZoneInfoTestBase from test.support.import_helper import import_module @@ -404,6 +405,8 @@ def test_time_fixed_offset(self): class CZoneInfoTest(ZoneInfoTest): module = c_zoneinfo + @unittest.skipIf(MISSING_C_DOCSTRINGS, + "Signature information for builtins requires docstrings") def test_signatures(self): """Ensure that C module has valid method signatures.""" import inspect @@ -1001,6 +1004,80 @@ def test_tzstr_from_utc(self): self.assertEqual(dt_act, dt_utc) + def test_extreme_tzstr(self): + tzstrs = [ + # Extreme offset hour + "AAA24", + "AAA+24", + "AAA-24", + "AAA24BBB,J60/2,J300/2", + "AAA+24BBB,J60/2,J300/2", + "AAA-24BBB,J60/2,J300/2", + "AAA4BBB24,J60/2,J300/2", + "AAA4BBB+24,J60/2,J300/2", + "AAA4BBB-24,J60/2,J300/2", + # Extreme offset minutes + "AAA4:00BBB,J60/2,J300/2", + "AAA4:59BBB,J60/2,J300/2", + "AAA4BBB5:00,J60/2,J300/2", + "AAA4BBB5:59,J60/2,J300/2", + # Extreme offset seconds + "AAA4:00:00BBB,J60/2,J300/2", + "AAA4:00:59BBB,J60/2,J300/2", + "AAA4BBB5:00:00,J60/2,J300/2", + "AAA4BBB5:00:59,J60/2,J300/2", + # Extreme total offset + "AAA24:59:59BBB5,J60/2,J300/2", + "AAA-24:59:59BBB5,J60/2,J300/2", + "AAA4BBB24:59:59,J60/2,J300/2", + "AAA4BBB-24:59:59,J60/2,J300/2", + # Extreme months + "AAA4BBB,M12.1.1/2,M1.1.1/2", + "AAA4BBB,M1.1.1/2,M12.1.1/2", + # Extreme weeks + "AAA4BBB,M1.5.1/2,M1.1.1/2", + "AAA4BBB,M1.1.1/2,M1.5.1/2", + # Extreme weekday + "AAA4BBB,M1.1.6/2,M2.1.1/2", + "AAA4BBB,M1.1.1/2,M2.1.6/2", + # Extreme numeric offset + "AAA4BBB,0/2,20/2", + "AAA4BBB,0/2,0/14", + "AAA4BBB,20/2,365/2", + "AAA4BBB,365/2,365/14", + # Extreme julian offset + "AAA4BBB,J1/2,J20/2", + "AAA4BBB,J1/2,J1/14", + "AAA4BBB,J20/2,J365/2", + "AAA4BBB,J365/2,J365/14", + # Extreme transition hour + "AAA4BBB,J60/167,J300/2", + "AAA4BBB,J60/+167,J300/2", + "AAA4BBB,J60/-167,J300/2", + "AAA4BBB,J60/2,J300/167", + "AAA4BBB,J60/2,J300/+167", + "AAA4BBB,J60/2,J300/-167", + # Extreme transition minutes + "AAA4BBB,J60/2:00,J300/2", + "AAA4BBB,J60/2:59,J300/2", + "AAA4BBB,J60/2,J300/2:00", + "AAA4BBB,J60/2,J300/2:59", + # Extreme transition seconds + "AAA4BBB,J60/2:00:00,J300/2", + "AAA4BBB,J60/2:00:59,J300/2", + "AAA4BBB,J60/2,J300/2:00:00", + "AAA4BBB,J60/2,J300/2:00:59", + # Extreme total transition time + "AAA4BBB,J60/167:59:59,J300/2", + "AAA4BBB,J60/-167:59:59,J300/2", + "AAA4BBB,J60/2,J300/167:59:59", + "AAA4BBB,J60/2,J300/-167:59:59", + ] + + for tzstr in tzstrs: + with self.subTest(tzstr=tzstr): + self.zone_from_tzstr(tzstr) + def test_invalid_tzstr(self): invalid_tzstrs = [ "PST8PDT", # DST but no transition specified @@ -1008,16 +1085,33 @@ def test_invalid_tzstr(self): "GMT,M3.2.0/2,M11.1.0/3", # Transition rule but no DST "GMT0+11,M3.2.0/2,M11.1.0/3", # Unquoted alphanumeric in DST "PST8PDT,M3.2.0/2", # Only one transition rule - # Invalid offsets - "STD+25", - "STD-25", - "STD+374", - "STD+374DST,M3.2.0/2,M11.1.0/3", - "STD+23DST+25,M3.2.0/2,M11.1.0/3", - "STD-23DST-25,M3.2.0/2,M11.1.0/3", + # Invalid offset hours + "AAA168", + "AAA+168", + "AAA-168", + "AAA168BBB,J60/2,J300/2", + "AAA+168BBB,J60/2,J300/2", + "AAA-168BBB,J60/2,J300/2", + "AAA4BBB168,J60/2,J300/2", + "AAA4BBB+168,J60/2,J300/2", + "AAA4BBB-168,J60/2,J300/2", + # Invalid offset minutes + "AAA4:0BBB,J60/2,J300/2", + "AAA4:100BBB,J60/2,J300/2", + "AAA4BBB5:0,J60/2,J300/2", + "AAA4BBB5:100,J60/2,J300/2", + # Invalid offset seconds + "AAA4:00:0BBB,J60/2,J300/2", + "AAA4:00:100BBB,J60/2,J300/2", + "AAA4BBB5:00:0,J60/2,J300/2", + "AAA4BBB5:00:100,J60/2,J300/2", # Completely invalid dates "AAA4BBB,M1443339,M11.1.0/3", "AAA4BBB,M3.2.0/2,0349309483959c", + "AAA4BBB,,J300/2", + "AAA4BBB,z,J300/2", + "AAA4BBB,J60/2,", + "AAA4BBB,J60/2,z", # Invalid months "AAA4BBB,M13.1.1/2,M1.1.1/2", "AAA4BBB,M1.1.1/2,M13.1.1/2", @@ -1037,6 +1131,26 @@ def test_invalid_tzstr(self): # Invalid julian offset "AAA4BBB,J0/2,J20/2", "AAA4BBB,J20/2,J366/2", + # Invalid transition time + "AAA4BBB,J60/2/3,J300/2", + "AAA4BBB,J60/2,J300/2/3", + # Invalid transition hour + "AAA4BBB,J60/168,J300/2", + "AAA4BBB,J60/+168,J300/2", + "AAA4BBB,J60/-168,J300/2", + "AAA4BBB,J60/2,J300/168", + "AAA4BBB,J60/2,J300/+168", + "AAA4BBB,J60/2,J300/-168", + # Invalid transition minutes + "AAA4BBB,J60/2:0,J300/2", + "AAA4BBB,J60/2:100,J300/2", + "AAA4BBB,J60/2,J300/2:0", + "AAA4BBB,J60/2,J300/2:100", + # Invalid transition seconds + "AAA4BBB,J60/2:00:0,J300/2", + "AAA4BBB,J60/2:00:100,J300/2", + "AAA4BBB,J60/2,J300/2:00:0", + "AAA4BBB,J60/2,J300/2:00:100", ] for invalid_tzstr in invalid_tzstrs: diff --git a/Lib/test/tokenizedata/__init__.py b/Lib/test/tokenizedata/__init__.py new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/Lib/test/bad_coding.py b/Lib/test/tokenizedata/bad_coding.py similarity index 100% rename from Lib/test/bad_coding.py rename to Lib/test/tokenizedata/bad_coding.py diff --git a/Lib/test/bad_coding2.py b/Lib/test/tokenizedata/bad_coding2.py similarity index 100% rename from Lib/test/bad_coding2.py rename to Lib/test/tokenizedata/bad_coding2.py diff --git a/Lib/test/badsyntax_3131.py b/Lib/test/tokenizedata/badsyntax_3131.py similarity index 100% rename from Lib/test/badsyntax_3131.py rename to Lib/test/tokenizedata/badsyntax_3131.py diff --git a/Lib/test/badsyntax_pep3120.py b/Lib/test/tokenizedata/badsyntax_pep3120.py similarity index 100% rename from Lib/test/badsyntax_pep3120.py rename to Lib/test/tokenizedata/badsyntax_pep3120.py diff --git a/Lib/test/coding20731.py b/Lib/test/tokenizedata/coding20731.py similarity index 100% rename from Lib/test/coding20731.py rename to Lib/test/tokenizedata/coding20731.py diff --git a/Lib/test/tokenize_tests-latin1-coding-cookie-and-utf8-bom-sig.txt b/Lib/test/tokenizedata/tokenize_tests-latin1-coding-cookie-and-utf8-bom-sig.txt similarity index 100% rename from Lib/test/tokenize_tests-latin1-coding-cookie-and-utf8-bom-sig.txt rename to Lib/test/tokenizedata/tokenize_tests-latin1-coding-cookie-and-utf8-bom-sig.txt diff --git a/Lib/test/tokenize_tests-no-coding-cookie-and-utf8-bom-sig-only.txt b/Lib/test/tokenizedata/tokenize_tests-no-coding-cookie-and-utf8-bom-sig-only.txt similarity index 100% rename from Lib/test/tokenize_tests-no-coding-cookie-and-utf8-bom-sig-only.txt rename to Lib/test/tokenizedata/tokenize_tests-no-coding-cookie-and-utf8-bom-sig-only.txt diff --git a/Lib/test/tokenize_tests-utf8-coding-cookie-and-no-utf8-bom-sig.txt b/Lib/test/tokenizedata/tokenize_tests-utf8-coding-cookie-and-no-utf8-bom-sig.txt similarity index 100% rename from Lib/test/tokenize_tests-utf8-coding-cookie-and-no-utf8-bom-sig.txt rename to Lib/test/tokenizedata/tokenize_tests-utf8-coding-cookie-and-no-utf8-bom-sig.txt diff --git a/Lib/test/tokenize_tests-utf8-coding-cookie-and-utf8-bom-sig.txt b/Lib/test/tokenizedata/tokenize_tests-utf8-coding-cookie-and-utf8-bom-sig.txt similarity index 100% rename from Lib/test/tokenize_tests-utf8-coding-cookie-and-utf8-bom-sig.txt rename to Lib/test/tokenizedata/tokenize_tests-utf8-coding-cookie-and-utf8-bom-sig.txt diff --git a/Lib/test/tokenize_tests.txt b/Lib/test/tokenizedata/tokenize_tests.txt similarity index 100% rename from Lib/test/tokenize_tests.txt rename to Lib/test/tokenizedata/tokenize_tests.txt diff --git a/Lib/test/_typed_dict_helper.py b/Lib/test/typinganndata/_typed_dict_helper.py similarity index 100% rename from Lib/test/_typed_dict_helper.py rename to Lib/test/typinganndata/_typed_dict_helper.py diff --git a/Lib/test/ann_module.py b/Lib/test/typinganndata/ann_module.py similarity index 100% rename from Lib/test/ann_module.py rename to Lib/test/typinganndata/ann_module.py diff --git a/Lib/test/ann_module2.py b/Lib/test/typinganndata/ann_module2.py similarity index 100% rename from Lib/test/ann_module2.py rename to Lib/test/typinganndata/ann_module2.py diff --git a/Lib/test/ann_module3.py b/Lib/test/typinganndata/ann_module3.py similarity index 100% rename from Lib/test/ann_module3.py rename to Lib/test/typinganndata/ann_module3.py diff --git a/Lib/test/ann_module4.py b/Lib/test/typinganndata/ann_module4.py similarity index 100% rename from Lib/test/ann_module4.py rename to Lib/test/typinganndata/ann_module4.py diff --git a/Lib/test/ann_module5.py b/Lib/test/typinganndata/ann_module5.py similarity index 100% rename from Lib/test/ann_module5.py rename to Lib/test/typinganndata/ann_module5.py diff --git a/Lib/test/ann_module6.py b/Lib/test/typinganndata/ann_module6.py similarity index 100% rename from Lib/test/ann_module6.py rename to Lib/test/typinganndata/ann_module6.py diff --git a/Lib/test/ann_module7.py b/Lib/test/typinganndata/ann_module7.py similarity index 100% rename from Lib/test/ann_module7.py rename to Lib/test/typinganndata/ann_module7.py diff --git a/Lib/test/ann_module8.py b/Lib/test/typinganndata/ann_module8.py similarity index 100% rename from Lib/test/ann_module8.py rename to Lib/test/typinganndata/ann_module8.py diff --git a/Lib/test/mod_generics_cache.py b/Lib/test/typinganndata/mod_generics_cache.py similarity index 100% rename from Lib/test/mod_generics_cache.py rename to Lib/test/typinganndata/mod_generics_cache.py diff --git a/Lib/test/ziptestdata/README.md b/Lib/test/ziptestdata/README.md deleted file mode 100644 index 6b9147db76e178..00000000000000 --- a/Lib/test/ziptestdata/README.md +++ /dev/null @@ -1,35 +0,0 @@ -# Test data for `test_zipfile` - -The test executables in this directory are created manually from header.sh and -the `testdata_module_inside_zip.py` file. You must have infozip's zip utility -installed (`apt install zip` on Debian). - -## Purpose - -These are used to test executable files with an appended zipfile, in a scenario -where the executable is _not_ a Python interpreter itself so our automatic -zipimport machinery (that'd look for `__main__.py`) is not being used. - -## Updating the test executables - -If you update header.sh or the testdata_module_inside_zip.py file, rerun the -commands below. These are expected to be rarely changed, if ever. - -### Standard old format (2.0) zip file - -``` -zip -0 zip2.zip testdata_module_inside_zip.py -cat header.sh zip2.zip >exe_with_zip -rm zip2.zip -``` - -### Modern format (4.5) zip64 file - -Redirecting from stdin forces infozip's zip tool to create a zip64. - -``` -zip -0 zip64.zip -cat header.sh zip64.zip >exe_with_z64 -rm zip64.zip -``` - diff --git a/Lib/threading.py b/Lib/threading.py index e036cb891e196d..85aff58968082d 100644 --- a/Lib/threading.py +++ b/Lib/threading.py @@ -4,6 +4,8 @@ import sys as _sys import _thread import functools +import warnings +import _weakref from time import monotonic as _time from _weakrefset import WeakSet @@ -32,11 +34,12 @@ 'setprofile_all_threads','settrace_all_threads'] # Rename some stuff so "from threading import *" is safe -_start_new_thread = _thread.start_new_thread +_start_joinable_thread = _thread.start_joinable_thread _daemon_threads_allowed = _thread.daemon_threads_allowed _allocate_lock = _thread.allocate_lock _set_sentinel = _thread._set_sentinel get_ident = _thread.get_ident +_is_main_interpreter = _thread._is_main_interpreter try: get_native_id = _thread.get_native_id _HAVE_THREAD_NATIVE_ID = True @@ -116,6 +119,12 @@ def RLock(*args, **kwargs): acquired it. """ + if args or kwargs: + warnings.warn( + 'Passing arguments to RLock is deprecated and will be removed in 3.15', + DeprecationWarning, + stacklevel=2, + ) if _CRLock is None: return _PyRLock(*args, **kwargs) return _CRLock(*args, **kwargs) @@ -238,6 +247,13 @@ def _release_save(self): def _is_owned(self): return self._owner == get_ident() + # Internal method used for reentrancy checks + + def _recursion_count(self): + if self._owner != get_ident(): + return 0 + return self._count + _PyRLock = _RLock @@ -574,7 +590,7 @@ def __repr__(self): return f"<{cls.__module__}.{cls.__qualname__} at {id(self):#x}: {status}>" def _at_fork_reinit(self): - # Private method called by Thread._reset_internal_locks() + # Private method called by Thread._after_fork() self._cond._at_fork_reinit() def is_set(self): @@ -909,6 +925,8 @@ class is implemented. if _HAVE_THREAD_NATIVE_ID: self._native_id = None self._tstate_lock = None + self._join_lock = None + self._handle = None self._started = Event() self._is_stopped = False self._initialized = True @@ -918,22 +936,32 @@ class is implemented. # For debugging and _after_fork() _dangling.add(self) - def _reset_internal_locks(self, is_alive): - # private! Called by _after_fork() to reset our internal locks as - # they may be in an invalid state leading to a deadlock or crash. + def _after_fork(self, new_ident=None): + # Private! Called by threading._after_fork(). self._started._at_fork_reinit() - if is_alive: + if new_ident is not None: + # This thread is alive. + self._ident = new_ident + if self._handle is not None: + self._handle.after_fork_alive() + assert self._handle.ident == new_ident # bpo-42350: If the fork happens when the thread is already stopped # (ex: after threading._shutdown() has been called), _tstate_lock # is None. Do nothing in this case. if self._tstate_lock is not None: self._tstate_lock._at_fork_reinit() self._tstate_lock.acquire() + if self._join_lock is not None: + self._join_lock._at_fork_reinit() else: - # The thread isn't alive after fork: it doesn't have a tstate + # This thread isn't alive after fork: it doesn't have a tstate # anymore. self._is_stopped = True self._tstate_lock = None + self._join_lock = None + if self._handle is not None: + self._handle.after_fork_dead() + self._handle = None def __repr__(self): assert self._initialized, "Thread.__init__() was not called" @@ -965,15 +993,18 @@ def start(self): if self._started.is_set(): raise RuntimeError("threads can only be started once") + self._join_lock = _allocate_lock() + with _active_limbo_lock: _limbo[self] = self try: - _start_new_thread(self._bootstrap, ()) + # Start joinable thread + self._handle = _start_joinable_thread(self._bootstrap) except Exception: with _active_limbo_lock: del _limbo[self] raise - self._started.wait() + self._started.wait() # Will set ident and native_id def run(self): """Method representing the thread's activity. @@ -1129,6 +1160,22 @@ def join(self, timeout=None): # historically .join(timeout=x) for x<0 has acted as if timeout=0 self._wait_for_tstate_lock(timeout=max(timeout, 0)) + if self._is_stopped: + self._join_os_thread() + + def _join_os_thread(self): + join_lock = self._join_lock + if join_lock is None: + return + with join_lock: + # Calling join() multiple times would raise an exception + # in one of the callers. + if self._handle is not None: + self._handle.join() + self._handle = None + # No need to keep this around + self._join_lock = None + def _wait_for_tstate_lock(self, block=True, timeout=-1): # Issue #18808: wait for the thread state to be gone. # At the end of the thread's life, after all knowledge of the thread @@ -1208,7 +1255,10 @@ def is_alive(self): if self._is_stopped or not self._started.is_set(): return False self._wait_for_tstate_lock(False) - return not self._is_stopped + if not self._is_stopped: + return True + self._join_os_thread() + return False @property def daemon(self): @@ -1560,7 +1610,7 @@ def _shutdown(): # the main thread's tstate_lock - that won't happen until the interpreter # is nearly dead. So we release it here. Note that just calling _stop() # isn't enough: other threads may already be waiting on _tstate_lock. - if _main_thread._is_stopped: + if _main_thread._is_stopped and _is_main_interpreter(): # _shutdown() was already called return @@ -1578,8 +1628,11 @@ def _shutdown(): # The main thread isn't finished yet, so its thread state lock can't # have been released. assert tlock is not None - assert tlock.locked() - tlock.release() + if tlock.locked(): + # It should have been released already by + # _PyInterpreterState_SetNotRunningMain(), but there may be + # embedders that aren't calling that yet. + tlock.release() _main_thread._stop() else: # bpo-1596321: _shutdown() must be called in the main thread. @@ -1613,6 +1666,7 @@ def main_thread(): In normal conditions, the main thread is the thread from which the Python interpreter was started. """ + # XXX Figure this out for subinterpreters. (See gh-75698.) return _main_thread # get thread-local implementation, either from the thread @@ -1660,15 +1714,13 @@ def _after_fork(): # Any lock/condition variable may be currently locked or in an # invalid state, so we reinitialize them. if thread is current: - # There is only one active thread. We reset the ident to - # its new value since it can have changed. - thread._reset_internal_locks(True) + # This is the one and only active thread. ident = get_ident() - thread._ident = ident + thread._after_fork(new_ident=ident) new_active[ident] = thread else: # All the others are already stopped. - thread._reset_internal_locks(False) + thread._after_fork() thread._stop() _limbo.clear() diff --git a/Lib/timeit.py b/Lib/timeit.py index 0cf8db67723a49..02cfafaf36e5d1 100755 --- a/Lib/timeit.py +++ b/Lib/timeit.py @@ -50,9 +50,9 @@ """ import gc +import itertools import sys import time -import itertools __all__ = ["Timer", "timeit", "repeat", "default_timer"] @@ -77,9 +77,11 @@ def inner(_it, _timer{init}): return _t1 - _t0 """ + def reindent(src, indent): """Helper to reindent a multi-line statement.""" - return src.replace("\n", "\n" + " "*indent) + return src.replace("\n", "\n" + " " * indent) + class Timer: """Class for timing execution speed of small code snippets. @@ -166,7 +168,7 @@ def timeit(self, number=default_number): To be precise, this executes the setup statement once, and then returns the time it takes to execute the main statement - a number of times, as a float measured in seconds. The + a number of times, as float seconds if using the default timer. The argument is the number of times through the loop, defaulting to one million. The main statement, the setup statement and the timer function to be used are passed to the constructor. @@ -228,16 +230,19 @@ def autorange(self, callback=None): return (number, time_taken) i *= 10 + def timeit(stmt="pass", setup="pass", timer=default_timer, number=default_number, globals=None): """Convenience function to create Timer object and call timeit method.""" return Timer(stmt, setup, timer, globals).timeit(number) + def repeat(stmt="pass", setup="pass", timer=default_timer, repeat=default_repeat, number=default_number, globals=None): """Convenience function to create Timer object and call repeat method.""" return Timer(stmt, setup, timer, globals).repeat(repeat, number) + def main(args=None, *, _wrap_timer=None): """Main program, used when run as a script. @@ -269,7 +274,7 @@ def main(args=None, *, _wrap_timer=None): timer = default_timer stmt = "\n".join(args) or "pass" - number = 0 # auto-determine + number = 0 # auto-determine setup = [] repeat = default_repeat verbose = 0 @@ -286,7 +291,7 @@ def main(args=None, *, _wrap_timer=None): time_unit = a else: print("Unrecognized unit. Please select nsec, usec, msec, or sec.", - file=sys.stderr) + file=sys.stderr) return 2 if o in ("-r", "--repeat"): repeat = int(a) @@ -320,7 +325,7 @@ def callback(number, time_taken): msg = "{num} loop{s} -> {secs:.{prec}g} secs" plural = (number != 1) print(msg.format(num=number, s='s' if plural else '', - secs=time_taken, prec=precision)) + secs=time_taken, prec=precision)) try: number, _ = t.autorange(callback) except: @@ -371,5 +376,6 @@ def format_time(dt): UserWarning, '', 0) return None + if __name__ == "__main__": sys.exit(main()) diff --git a/Lib/tkinter/__init__.py b/Lib/tkinter/__init__.py index c675c511e04533..2590acdc87e695 100644 --- a/Lib/tkinter/__init__.py +++ b/Lib/tkinter/__init__.py @@ -901,6 +901,85 @@ def bell(self, displayof=0): """Ring a display's bell.""" self.tk.call(('bell',) + self._displayof(displayof)) + def tk_busy_cget(self, option): + """Return the value of busy configuration option. + + The widget must have been previously made busy by + tk_busy_hold(). Option may have any of the values accepted by + tk_busy_hold(). + """ + return self.tk.call('tk', 'busy', 'cget', self._w, '-'+option) + busy_cget = tk_busy_cget + + def tk_busy_configure(self, cnf=None, **kw): + """Query or modify the busy configuration options. + + The widget must have been previously made busy by + tk_busy_hold(). Options may have any of the values accepted by + tk_busy_hold(). + + Please note that the option database is referenced by the widget + name or class. For example, if a Frame widget with name "frame" + is to be made busy, the busy cursor can be specified for it by + either call: + + w.option_add('*frame.busyCursor', 'gumby') + w.option_add('*Frame.BusyCursor', 'gumby') + """ + if kw: + cnf = _cnfmerge((cnf, kw)) + elif cnf: + cnf = _cnfmerge(cnf) + if cnf is None: + return self._getconfigure( + 'tk', 'busy', 'configure', self._w) + if isinstance(cnf, str): + return self._getconfigure1( + 'tk', 'busy', 'configure', self._w, '-'+cnf) + self.tk.call('tk', 'busy', 'configure', self._w, *self._options(cnf)) + busy_config = busy_configure = tk_busy_config = tk_busy_configure + + def tk_busy_current(self, pattern=None): + """Return a list of widgets that are currently busy. + + If a pattern is given, only busy widgets whose path names match + a pattern are returned. + """ + return [self._nametowidget(x) for x in + self.tk.splitlist(self.tk.call( + 'tk', 'busy', 'current', pattern))] + busy_current = tk_busy_current + + def tk_busy_forget(self): + """Make this widget no longer busy. + + User events will again be received by the widget. + """ + self.tk.call('tk', 'busy', 'forget', self._w) + busy_forget = tk_busy_forget + + def tk_busy_hold(self, **kw): + """Make this widget appear busy. + + The specified widget and its descendants will be blocked from + user interactions. Normally update() should be called + immediately afterward to insure that the hold operation is in + effect before the application starts its processing. + + The only supported configuration option is: + + cursor: the cursor to be displayed when the widget is made + busy. + """ + self.tk.call('tk', 'busy', 'hold', self._w, *self._options(kw)) + busy = busy_hold = tk_busy = tk_busy_hold + + def tk_busy_status(self): + """Return True if the widget is busy, False otherwise.""" + return self.tk.getboolean(self.tk.call( + 'tk', 'busy', 'status', self._w)) + busy_status = tk_busy_status + # Clipboard handling: def clipboard_get(self, **kw): """Retrieve data from the clipboard on window's display. @@ -1181,6 +1260,8 @@ def winfo_parent(self): def winfo_pathname(self, id, displayof=0): """Return the pathname of the widget given by ID.""" + if isinstance(id, int): + id = hex(id) args = ('winfo', 'pathname') \ + self._displayof(displayof) + (id,) return self.tk.call(args) @@ -1448,10 +1529,24 @@ def bind(self, sequence=None, func=None, add=None): return self._bind(('bind', self._w), sequence, func, add) def unbind(self, sequence, funcid=None): - """Unbind for this widget for event SEQUENCE the - function identified with FUNCID.""" - self.tk.call('bind', self._w, sequence, '') - if funcid: + """Unbind for this widget the event SEQUENCE. + + If FUNCID is given, only unbind the function identified with FUNCID + and also delete the corresponding Tcl command. + + Otherwise destroy the current binding for SEQUENCE, leaving SEQUENCE + unbound. + """ + if funcid is None: + self.tk.call('bind', self._w, sequence, '') + else: + lines = self.tk.call('bind', self._w, sequence).split('\n') + prefix = f'if {{"[{funcid} ' + keep = '\n'.join(line for line in lines + if not line.startswith(prefix)) + if not keep.strip(): + keep = '' + self.tk.call('bind', self._w, sequence, keep) self.deletecommand(funcid) def bind_all(self, sequence=None, func=None, add=None): @@ -1459,7 +1554,7 @@ def bind_all(self, sequence=None, func=None, add=None): An additional boolean parameter ADD specifies whether FUNC will be called additionally to the other bound function or whether it will replace the previous function. See bind for the return value.""" - return self._bind(('bind', 'all'), sequence, func, add, 0) + return self._root()._bind(('bind', 'all'), sequence, func, add, True) def unbind_all(self, sequence): """Unbind for all widgets for event SEQUENCE all functions.""" @@ -1473,7 +1568,7 @@ def bind_class(self, className, sequence=None, func=None, add=None): whether it will replace the previous function. See bind for the return value.""" - return self._bind(('bind', className), sequence, func, add, 0) + return self._root()._bind(('bind', className), sequence, func, add, True) def unbind_class(self, className, sequence): """Unbind for all widgets with bindtag CLASSNAME for event SEQUENCE @@ -3636,25 +3731,28 @@ def compare(self, index1, op, index2): return self.tk.getboolean(self.tk.call( self._w, 'compare', index1, op, index2)) - def count(self, index1, index2, *args): # new in Tk 8.5 + def count(self, index1, index2, *options): # new in Tk 8.5 """Counts the number of relevant things between the two indices. - If index1 is after index2, the result will be a negative number + + If INDEX1 is after INDEX2, the result will be a negative number (and this holds for each of the possible options). - The actual items which are counted depends on the options given by - args. The result is a list of integers, one for the result of each - counting option given. Valid counting options are "chars", + The actual items which are counted depends on the options given. + The result is a tuple of integers, one for the result of each + counting option given, if more than one option is specified, + otherwise it is an integer. Valid counting options are "chars", "displaychars", "displayindices", "displaylines", "indices", - "lines", "xpixels" and "ypixels". There is an additional possible + "lines", "xpixels" and "ypixels". The default value, if no + option is specified, is "indices". There is an additional possible option "update", which if given then all subsequent options ensure that any possible out of date information is recalculated.""" - args = ['-%s' % arg for arg in args] - args += [index1, index2] - res = self.tk.call(self._w, 'count', *args) or None - if res is not None and len(args) <= 3: - return (res, ) - else: - return res + options = ['-%s' % arg for arg in options] + res = self.tk.call(self._w, 'count', *options, index1, index2) + if not isinstance(res, int): + res = self._getints(res) + if len(res) == 1: + res, = res + return res def debug(self, boolean=None): """Turn on the internal consistency checks of the B-Tree inside the text @@ -4069,8 +4167,6 @@ def __init__(self, imgtype, name=None, cnf={}, master=None, **kw): elif kw: cnf = kw options = () for k, v in cnf.items(): - if callable(v): - v = self._register(v) options = options + ('-'+k, v) self.tk.call(('image', 'create', imgtype, name,) + options) self.name = name @@ -4097,8 +4193,6 @@ def configure(self, **kw): for k, v in _cnfmerge(kw).items(): if v is not None: if k[-1] == '_': k = k[:-1] - if callable(v): - v = self._register(v) res = res + ('-'+k, v) self.tk.call((self.name, 'config') + res) diff --git a/Lib/tkinter/ttk.py b/Lib/tkinter/ttk.py index efeabb7a92c627..5ca938a670831a 100644 --- a/Lib/tkinter/ttk.py +++ b/Lib/tkinter/ttk.py @@ -95,40 +95,47 @@ def _format_mapdict(mapdict, script=False): def _format_elemcreate(etype, script=False, *args, **kw): """Formats args and kw according to the given element factory etype.""" - spec = None + specs = () opts = () - if etype in ("image", "vsapi"): - if etype == "image": # define an element based on an image - # first arg should be the default image name - iname = args[0] - # next args, if any, are statespec/value pairs which is almost - # a mapdict, but we just need the value - imagespec = _join(_mapdict_values(args[1:])) - spec = "%s %s" % (iname, imagespec) - + if etype == "image": # define an element based on an image + # first arg should be the default image name + iname = args[0] + # next args, if any, are statespec/value pairs which is almost + # a mapdict, but we just need the value + imagespec = (iname, *_mapdict_values(args[1:])) + if script: + specs = (imagespec,) else: - # define an element whose visual appearance is drawn using the - # Microsoft Visual Styles API which is responsible for the - # themed styles on Windows XP and Vista. - # Availability: Tk 8.6, Windows XP and Vista. - class_name, part_id = args[:2] - statemap = _join(_mapdict_values(args[2:])) - spec = "%s %s %s" % (class_name, part_id, statemap) + specs = (_join(imagespec),) + opts = _format_optdict(kw, script) + if etype == "vsapi": + # define an element whose visual appearance is drawn using the + # Microsoft Visual Styles API which is responsible for the + # themed styles on Windows XP and Vista. + # Availability: Tk 8.6, Windows XP and Vista. + if len(args) < 3: + class_name, part_id = args + statemap = (((), 1),) + else: + class_name, part_id, statemap = args + specs = (class_name, part_id, tuple(_mapdict_values(statemap))) opts = _format_optdict(kw, script) elif etype == "from": # clone an element # it expects a themename and optionally an element to clone from, # otherwise it will clone {} (empty element) - spec = args[0] # theme name + specs = (args[0],) # theme name if len(args) > 1: # elementfrom specified opts = (_format_optvalue(args[1], script),) if script: - spec = '{%s}' % spec + specs = _join(specs) opts = ' '.join(opts) + return specs, opts + else: + return *specs, opts - return spec, opts def _format_layoutlist(layout, indent=0, indent_size=2): """Formats a layout list so we can pass the result to ttk::style @@ -214,10 +221,10 @@ def _script_from_settings(settings): elemargs = eopts[1:argc] elemkw = eopts[argc] if argc < len(eopts) and eopts[argc] else {} - spec, opts = _format_elemcreate(etype, True, *elemargs, **elemkw) + specs, eopts = _format_elemcreate(etype, True, *elemargs, **elemkw) script.append("ttk::style element create %s %s %s %s" % ( - name, etype, spec, opts)) + name, etype, specs, eopts)) return '\n'.join(script) @@ -434,9 +441,9 @@ def layout(self, style, layoutspec=None): def element_create(self, elementname, etype, *args, **kw): """Create a new element in the current theme of given etype.""" - spec, opts = _format_elemcreate(etype, False, *args, **kw) + *specs, opts = _format_elemcreate(etype, False, *args, **kw) self.tk.call(self._name, "element", "create", elementname, etype, - spec, *opts) + *specs, *opts) def element_names(self): diff --git a/Lib/tokenize.py b/Lib/tokenize.py index c21876fb403d8f..0ab1893d42f72f 100644 --- a/Lib/tokenize.py +++ b/Lib/tokenize.py @@ -298,7 +298,7 @@ def untokenize(iterable): def _get_normal_name(orig_enc): - """Imitates get_normal_name in tokenizer.c.""" + """Imitates get_normal_name in Parser/tokenizer/helpers.c.""" # Only care about the first 12 characters. enc = orig_enc[:12].lower().replace("_", "-") if enc == "utf-8" or enc.startswith("utf-8-"): diff --git a/Lib/trace.py b/Lib/trace.py index fb9a423ea09fce..7cb6f897634b14 100755 --- a/Lib/trace.py +++ b/Lib/trace.py @@ -202,7 +202,8 @@ def update(self, other): for key in other_callers: callers[key] = 1 - def write_results(self, show_missing=True, summary=False, coverdir=None): + def write_results(self, show_missing=True, summary=False, coverdir=None, *, + ignore_missing_files=False): """ Write the coverage results. @@ -211,6 +212,9 @@ def write_results(self, show_missing=True, summary=False, coverdir=None): :param coverdir: If None, the results of each module are placed in its directory, otherwise it is included in the directory specified. + :param ignore_missing_files: If True, counts for files that no longer + exist are silently ignored. Otherwise, a missing file + will raise a FileNotFoundError. """ if self.calledfuncs: print() @@ -253,6 +257,9 @@ def write_results(self, show_missing=True, summary=False, coverdir=None): if filename.endswith(".pyc"): filename = filename[:-1] + if ignore_missing_files and not os.path.isfile(filename): + continue + if coverdir is None: dir = os.path.dirname(os.path.abspath(filename)) modulename = _modname(filename) @@ -278,7 +285,6 @@ def write_results(self, show_missing=True, summary=False, coverdir=None): percent = int(100 * n_hits / n_lines) sums[modulename] = n_lines, percent, modulename, filename - if summary and sums: print("lines cov% module (path)") for m in sorted(sums): diff --git a/Lib/traceback.py b/Lib/traceback.py index 354754b9560a19..30b42a4f693d95 100644 --- a/Lib/traceback.py +++ b/Lib/traceback.py @@ -1,10 +1,13 @@ """Extract, format and print information about Python stack traces.""" +import os +import io import collections.abc import itertools import linecache import sys import textwrap +import warnings from contextlib import suppress __all__ = ['extract_stack', 'extract_tb', 'format_exception', @@ -18,6 +21,8 @@ # Formatting and printing lists of traceback lines. # +_COLORIZE = True + def print_list(extracted_list, file=None): """Print the list of tuples as returned by extract_tb() or extract_stack() as a formatted stack trace to the given file.""" @@ -109,7 +114,7 @@ def _parse_value_tb(exc, value, tb): def print_exception(exc, /, value=_sentinel, tb=_sentinel, limit=None, \ - file=None, chain=True): + file=None, chain=True, **kwargs): """Print exception up to 'limit' stack trace entries from 'tb' to 'file'. This differs from print_tb() in the following ways: (1) if @@ -120,9 +125,44 @@ def print_exception(exc, /, value=_sentinel, tb=_sentinel, limit=None, \ occurred with a caret on the next line indicating the approximate position of the error. """ + colorize = kwargs.get("colorize", False) value, tb = _parse_value_tb(exc, value, tb) te = TracebackException(type(value), value, tb, limit=limit, compact=True) - te.print(file=file, chain=chain) + te.print(file=file, chain=chain, colorize=colorize) + + +BUILTIN_EXCEPTION_LIMIT = object() + +def _can_colorize(): + if sys.platform == "win32": + try: + import nt + if not nt._supports_virtual_terminal(): + return False + except (ImportError, AttributeError): + return False + + if os.environ.get("PYTHON_COLORS") == "0": + return False + if os.environ.get("PYTHON_COLORS") == "1": + return True + if "NO_COLOR" in os.environ: + return False + if not _COLORIZE: + return False + if "FORCE_COLOR" in os.environ: + return True + if os.environ.get("TERM") == "dumb": + return False + try: + return os.isatty(sys.stderr.fileno()) + except io.UnsupportedOperation: + return sys.stderr.isatty() + +def _print_exception_bltin(exc, /): + file = sys.stderr if sys.stderr is not None else sys.__stderr__ + colorize = _can_colorize() + return print_exception(exc, limit=BUILTIN_EXCEPTION_LIMIT, file=file, colorize=colorize) def format_exception(exc, /, value=_sentinel, tb=_sentinel, limit=None, \ @@ -140,34 +180,42 @@ def format_exception(exc, /, value=_sentinel, tb=_sentinel, limit=None, \ return list(te.format(chain=chain)) -def format_exception_only(exc, /, value=_sentinel): +def format_exception_only(exc, /, value=_sentinel, *, show_group=False): """Format the exception part of a traceback. The return value is a list of strings, each ending in a newline. - Normally, the list contains a single string; however, for - SyntaxError exceptions, it contains several lines that (when - printed) display detailed information about where the syntax - error occurred. - - The message indicating which exception occurred is always the last - string in the list. + The list contains the exception's message, which is + normally a single string; however, for :exc:`SyntaxError` exceptions, it + contains several lines that (when printed) display detailed information + about where the syntax error occurred. Following the message, the list + contains the exception's ``__notes__``. + When *show_group* is ``True``, and the exception is an instance of + :exc:`BaseExceptionGroup`, the nested exceptions are included as + well, recursively, with indentation relative to their nesting depth. """ if value is _sentinel: value = exc te = TracebackException(type(value), value, None, compact=True) - return list(te.format_exception_only()) + return list(te.format_exception_only(show_group=show_group)) # -- not official API but folk probably use these two functions. -def _format_final_exc_line(etype, value): +def _format_final_exc_line(etype, value, *, insert_final_newline=True, colorize=False): valuestr = _safe_string(value, 'exception') - if value is None or not valuestr: - line = "%s\n" % etype + end_char = "\n" if insert_final_newline else "" + if colorize: + if value is None or not valuestr: + line = f"{_ANSIColors.BOLD_MAGENTA}{etype}{_ANSIColors.RESET}{end_char}" + else: + line = f"{_ANSIColors.BOLD_MAGENTA}{etype}{_ANSIColors.RESET}: {_ANSIColors.MAGENTA}{valuestr}{_ANSIColors.RESET}{end_char}" else: - line = "%s: %s\n" % (etype, valuestr) + if value is None or not valuestr: + line = f"{etype}{end_char}" + else: + line = f"{etype}: {valuestr}{end_char}" return line def _safe_string(value, what, func=str): @@ -263,7 +311,7 @@ class FrameSummary: """ __slots__ = ('filename', 'lineno', 'end_lineno', 'colno', 'end_colno', - 'name', '_line', 'locals') + 'name', '_lines', '_lines_dedented', 'locals') def __init__(self, filename, lineno, name, *, lookup_line=True, locals=None, line=None, @@ -279,15 +327,16 @@ def __init__(self, filename, lineno, name, *, lookup_line=True, """ self.filename = filename self.lineno = lineno + self.end_lineno = lineno if end_lineno is None else end_lineno + self.colno = colno + self.end_colno = end_colno self.name = name - self._line = line + self._lines = line + self._lines_dedented = None if lookup_line: self.line self.locals = {k: _safe_string(v, 'local', func=repr) for k, v in locals.items()} if locals else None - self.end_lineno = end_lineno - self.colno = colno - self.end_colno = end_colno def __eq__(self, other): if isinstance(other, FrameSummary): @@ -312,19 +361,39 @@ def __repr__(self): def __len__(self): return 4 + def _set_lines(self): + if ( + self._lines is None + and self.lineno is not None + and self.end_lineno is not None + ): + lines = [] + for lineno in range(self.lineno, self.end_lineno + 1): + # treat errors (empty string) and empty lines (newline) as the same + lines.append(linecache.getline(self.filename, lineno).rstrip()) + self._lines = "\n".join(lines) + "\n" + @property - def _original_line(self): + def _original_lines(self): # Returns the line as-is from the source, without modifying whitespace. - self.line - return self._line + self._set_lines() + return self._lines + + @property + def _dedented_lines(self): + # Returns _original_lines, but dedented + self._set_lines() + if self._lines_dedented is None and self._lines is not None: + self._lines_dedented = textwrap.dedent(self._lines) + return self._lines_dedented @property def line(self): - if self._line is None: - if self.lineno is None: - return None - self._line = linecache.getline(self.filename, self.lineno) - return self._line.strip() + self._set_lines() + if self._lines is None: + return None + # return only the first line, stripped + return self._lines.partition("\n")[0].strip() def walk_stack(f): @@ -374,6 +443,14 @@ def _get_code_position(code, instruction_index): _RECURSIVE_CUTOFF = 3 # Also hardcoded in traceback.c. +class _ANSIColors: + RED = '\x1b[31m' + BOLD_RED = '\x1b[1;31m' + MAGENTA = '\x1b[35m' + BOLD_MAGENTA = '\x1b[1;35m' + GREY = '\x1b[90m' + RESET = '\x1b[0m' + class StackSummary(list): """A list of FrameSummary objects, representing a stack of frames.""" @@ -406,12 +483,16 @@ def _extract_from_extended_frame_gen(klass, frame_gen, *, limit=None, # (frame, (lineno, end_lineno, colno, end_colno)) in the stack. # Only lineno is required, the remaining fields can be None if the # information is not available. - if limit is None: + builtin_limit = limit is BUILTIN_EXCEPTION_LIMIT + if limit is None or builtin_limit: limit = getattr(sys, 'tracebacklimit', None) if limit is not None and limit < 0: limit = 0 if limit is not None: - if limit >= 0: + if builtin_limit: + frame_gen = tuple(frame_gen) + frame_gen = frame_gen[len(frame_gen) - limit:] + elif limit >= 0: frame_gen = itertools.islice(frame_gen, limit) else: frame_gen = collections.deque(frame_gen, maxlen=-limit) @@ -422,7 +503,6 @@ def _extract_from_extended_frame_gen(klass, frame_gen, *, limit=None, co = f.f_code filename = co.co_filename name = co.co_name - fnames.add(filename) linecache.lazycache(filename, f.f_globals) # Must defer line lookups until we have called checkcache. @@ -435,6 +515,7 @@ def _extract_from_extended_frame_gen(klass, frame_gen, *, limit=None, end_lineno=end_lineno, colno=colno, end_colno=end_colno)) for filename in fnames: linecache.checkcache(filename) + # If immediate lookup was desired, trigger lookups now. if lookup_lines: for f in result: @@ -460,62 +541,193 @@ def from_list(klass, a_list): result.append(FrameSummary(filename, lineno, name, line=line)) return result - def format_frame_summary(self, frame_summary): + def format_frame_summary(self, frame_summary, **kwargs): """Format the lines for a single FrameSummary. Returns a string representing one frame involved in the stack. This gets called for every frame to be printed in the stack summary. """ + colorize = kwargs.get("colorize", False) row = [] - row.append(' File "{}", line {}, in {}\n'.format( - frame_summary.filename, frame_summary.lineno, frame_summary.name)) - if frame_summary.line: - stripped_line = frame_summary.line.strip() - row.append(' {}\n'.format(stripped_line)) - - orig_line_len = len(frame_summary._original_line) - frame_line_len = len(frame_summary.line.lstrip()) - stripped_characters = orig_line_len - frame_line_len + filename = frame_summary.filename + if frame_summary.filename.startswith("-"): + filename = "" + if colorize: + row.append(' File {}"{}"{}, line {}{}{}, in {}{}{}\n'.format( + _ANSIColors.MAGENTA, + filename, + _ANSIColors.RESET, + _ANSIColors.MAGENTA, + frame_summary.lineno, + _ANSIColors.RESET, + _ANSIColors.MAGENTA, + frame_summary.name, + _ANSIColors.RESET, + ) + ) + else: + row.append(' File "{}", line {}, in {}\n'.format( + filename, frame_summary.lineno, frame_summary.name)) + if frame_summary._dedented_lines and frame_summary._dedented_lines.strip(): if ( - frame_summary.colno is not None - and frame_summary.end_colno is not None + frame_summary.colno is None or + frame_summary.end_colno is None ): - start_offset = _byte_offset_to_character_offset( - frame_summary._original_line, frame_summary.colno) + 1 - end_offset = _byte_offset_to_character_offset( - frame_summary._original_line, frame_summary.end_colno) + 1 - + # only output first line if column information is missing + row.append(textwrap.indent(frame_summary.line, ' ') + "\n") + else: + # get first and last line + all_lines_original = frame_summary._original_lines.splitlines() + first_line = all_lines_original[0] + # assume all_lines_original has enough lines (since we constructed it) + last_line = all_lines_original[frame_summary.end_lineno - frame_summary.lineno] + + # character index of the start/end of the instruction + start_offset = _byte_offset_to_character_offset(first_line, frame_summary.colno) + end_offset = _byte_offset_to_character_offset(last_line, frame_summary.end_colno) + + all_lines = frame_summary._dedented_lines.splitlines()[ + :frame_summary.end_lineno - frame_summary.lineno + 1 + ] + + # adjust start/end offset based on dedent + dedent_characters = len(first_line) - len(all_lines[0]) + start_offset = max(0, start_offset - dedent_characters) + end_offset = max(0, end_offset - dedent_characters) + + # When showing this on a terminal, some of the non-ASCII characters + # might be rendered as double-width characters, so we need to take + # that into account when calculating the length of the line. + dp_start_offset = _display_width(all_lines[0], offset=start_offset) + dp_end_offset = _display_width(all_lines[-1], offset=end_offset) + + # get exact code segment corresponding to the instruction + segment = "\n".join(all_lines) + segment = segment[start_offset:len(segment) - (len(all_lines[-1]) - end_offset)] + + # attempt to parse for anchors anchors = None - if frame_summary.lineno == frame_summary.end_lineno: - with suppress(Exception): - anchors = _extract_caret_anchors_from_line_segment( - frame_summary._original_line[start_offset - 1:end_offset - 1] - ) - else: - end_offset = stripped_characters + len(stripped_line) - - # show indicators if primary char doesn't span the frame line - if end_offset - start_offset < len(stripped_line) or ( - anchors and anchors.right_start_offset - anchors.left_end_offset > 0): - row.append(' ') - row.append(' ' * (start_offset - stripped_characters)) - - if anchors: - row.append(anchors.primary_char * (anchors.left_end_offset)) - row.append(anchors.secondary_char * (anchors.right_start_offset - anchors.left_end_offset)) - row.append(anchors.primary_char * (end_offset - start_offset - anchors.right_start_offset)) - else: - row.append('^' * (end_offset - start_offset)) + with suppress(Exception): + anchors = _extract_caret_anchors_from_line_segment(segment) + + # only use carets if there are anchors or the carets do not span all lines + show_carets = False + if anchors or all_lines[0][:start_offset].lstrip() or all_lines[-1][end_offset:].rstrip(): + show_carets = True + + result = [] + + # only display first line, last line, and lines around anchor start/end + significant_lines = {0, len(all_lines) - 1} + + anchors_left_end_offset = 0 + anchors_right_start_offset = 0 + primary_char = "^" + secondary_char = "^" + if anchors: + anchors_left_end_offset = anchors.left_end_offset + anchors_right_start_offset = anchors.right_start_offset + # computed anchor positions do not take start_offset into account, + # so account for it here + if anchors.left_end_lineno == 0: + anchors_left_end_offset += start_offset + if anchors.right_start_lineno == 0: + anchors_right_start_offset += start_offset + + # account for display width + anchors_left_end_offset = _display_width( + all_lines[anchors.left_end_lineno], offset=anchors_left_end_offset + ) + anchors_right_start_offset = _display_width( + all_lines[anchors.right_start_lineno], offset=anchors_right_start_offset + ) - row.append('\n') + primary_char = anchors.primary_char + secondary_char = anchors.secondary_char + significant_lines.update( + range(anchors.left_end_lineno - 1, anchors.left_end_lineno + 2) + ) + significant_lines.update( + range(anchors.right_start_lineno - 1, anchors.right_start_lineno + 2) + ) + # remove bad line numbers + significant_lines.discard(-1) + significant_lines.discard(len(all_lines)) + + def output_line(lineno): + """output all_lines[lineno] along with carets""" + result.append(all_lines[lineno] + "\n") + if not show_carets: + return + num_spaces = len(all_lines[lineno]) - len(all_lines[lineno].lstrip()) + carets = [] + num_carets = dp_end_offset if lineno == len(all_lines) - 1 else _display_width(all_lines[lineno]) + # compute caret character for each position + for col in range(num_carets): + if col < num_spaces or (lineno == 0 and col < dp_start_offset): + # before first non-ws char of the line, or before start of instruction + carets.append(' ') + elif anchors and ( + lineno > anchors.left_end_lineno or + (lineno == anchors.left_end_lineno and col >= anchors_left_end_offset) + ) and ( + lineno < anchors.right_start_lineno or + (lineno == anchors.right_start_lineno and col < anchors_right_start_offset) + ): + # within anchors + carets.append(secondary_char) + else: + carets.append(primary_char) + if colorize: + # Replace the previous line with a red version of it only in the parts covered + # by the carets. + line = result[-1] + colorized_line_parts = [] + colorized_carets_parts = [] + + for color, group in itertools.groupby(itertools.zip_longest(line, carets, fillvalue=""), key=lambda x: x[1]): + caret_group = list(group) + if color == "^": + colorized_line_parts.append(_ANSIColors.BOLD_RED + "".join(char for char, _ in caret_group) + _ANSIColors.RESET) + colorized_carets_parts.append(_ANSIColors.BOLD_RED + "".join(caret for _, caret in caret_group) + _ANSIColors.RESET) + elif color == "~": + colorized_line_parts.append(_ANSIColors.RED + "".join(char for char, _ in caret_group) + _ANSIColors.RESET) + colorized_carets_parts.append(_ANSIColors.RED + "".join(caret for _, caret in caret_group) + _ANSIColors.RESET) + else: + colorized_line_parts.append("".join(char for char, _ in caret_group)) + colorized_carets_parts.append("".join(caret for _, caret in caret_group)) + + colorized_line = "".join(colorized_line_parts) + colorized_carets = "".join(colorized_carets_parts) + result[-1] = colorized_line + result.append(colorized_carets + "\n") + else: + result.append("".join(carets) + "\n") + + # display significant lines + sig_lines_list = sorted(significant_lines) + for i, lineno in enumerate(sig_lines_list): + if i: + linediff = lineno - sig_lines_list[i - 1] + if linediff == 2: + # 1 line in between - just output it + output_line(lineno - 1) + elif linediff > 2: + # > 1 line in between - abbreviate + result.append(f"...<{linediff - 1} lines>...\n") + output_line(lineno) + + row.append( + textwrap.indent(textwrap.dedent("".join(result)), ' ', lambda line: True) + ) if frame_summary.locals: for name, value in sorted(frame_summary.locals.items()): row.append(' {name} = {value}\n'.format(name=name, value=value)) return ''.join(row) - def format(self): + def format(self, **kwargs): """Format the stack ready for printing. Returns a list of strings ready for printing. Each string in the @@ -527,13 +739,14 @@ def format(self): repetitions are shown, followed by a summary line stating the exact number of further repetitions. """ + colorize = kwargs.get("colorize", False) result = [] last_file = None last_line = None last_name = None count = 0 for frame_summary in self: - formatted_frame = self.format_frame_summary(frame_summary) + formatted_frame = self.format_frame_summary(frame_summary, colorize=colorize) if formatted_frame is None: continue if (last_file is None or last_file != frame_summary.filename or @@ -571,7 +784,9 @@ def _byte_offset_to_character_offset(str, offset): _Anchors = collections.namedtuple( "_Anchors", [ + "left_end_lineno", "left_end_offset", + "right_start_lineno", "right_start_offset", "primary_char", "secondary_char", @@ -580,42 +795,173 @@ def _byte_offset_to_character_offset(str, offset): ) def _extract_caret_anchors_from_line_segment(segment): + """ + Given source code `segment` corresponding to a FrameSummary, determine: + - for binary ops, the location of the binary op + - for indexing and function calls, the location of the brackets. + `segment` is expected to be a valid Python expression. + """ import ast try: - tree = ast.parse(segment) + # Without parentheses, `segment` is parsed as a statement. + # Binary ops, subscripts, and calls are expressions, so + # we can wrap them with parentheses to parse them as + # (possibly multi-line) expressions. + # e.g. if we try to highlight the addition in + # x = ( + # a + + # b + # ) + # then we would ast.parse + # a + + # b + # which is not a valid statement because of the newline. + # Adding brackets makes it a valid expression. + # ( + # a + + # b + # ) + # Line locations will be different than the original, + # which is taken into account later on. + tree = ast.parse(f"(\n{segment}\n)") except SyntaxError: return None if len(tree.body) != 1: return None - normalize = lambda offset: _byte_offset_to_character_offset(segment, offset) + lines = segment.splitlines() + + def normalize(lineno, offset): + """Get character index given byte offset""" + return _byte_offset_to_character_offset(lines[lineno], offset) + + def next_valid_char(lineno, col): + """Gets the next valid character index in `lines`, if + the current location is not valid. Handles empty lines. + """ + while lineno < len(lines) and col >= len(lines[lineno]): + col = 0 + lineno += 1 + assert lineno < len(lines) and col < len(lines[lineno]) + return lineno, col + + def increment(lineno, col): + """Get the next valid character index in `lines`.""" + col += 1 + lineno, col = next_valid_char(lineno, col) + return lineno, col + + def nextline(lineno, col): + """Get the next valid character at least on the next line""" + col = 0 + lineno += 1 + lineno, col = next_valid_char(lineno, col) + return lineno, col + + def increment_until(lineno, col, stop): + """Get the next valid non-"\\#" character that satisfies the `stop` predicate""" + while True: + ch = lines[lineno][col] + if ch in "\\#": + lineno, col = nextline(lineno, col) + elif not stop(ch): + lineno, col = increment(lineno, col) + else: + break + return lineno, col + + def setup_positions(expr, force_valid=True): + """Get the lineno/col position of the end of `expr`. If `force_valid` is True, + forces the position to be a valid character (e.g. if the position is beyond the + end of the line, move to the next line) + """ + # -2 since end_lineno is 1-indexed and because we added an extra + # bracket + newline to `segment` when calling ast.parse + lineno = expr.end_lineno - 2 + col = normalize(lineno, expr.end_col_offset) + return next_valid_char(lineno, col) if force_valid else (lineno, col) + statement = tree.body[0] match statement: case ast.Expr(expr): match expr: case ast.BinOp(): - operator_start = normalize(expr.left.end_col_offset) - operator_end = normalize(expr.right.col_offset) - operator_str = segment[operator_start:operator_end] - operator_offset = len(operator_str) - len(operator_str.lstrip()) + # ast gives these locations for BinOp subexpressions + # ( left_expr ) + ( right_expr ) + # left^^^^^ right^^^^^ + lineno, col = setup_positions(expr.left) - left_anchor = expr.left.end_col_offset + operator_offset - right_anchor = left_anchor + 1 + # First operator character is the first non-space/')' character + lineno, col = increment_until(lineno, col, lambda x: not x.isspace() and x != ')') + + # binary op is 1 or 2 characters long, on the same line, + # before the right subexpression + right_col = col + 1 if ( - operator_offset + 1 < len(operator_str) - and not operator_str[operator_offset + 1].isspace() + right_col < len(lines[lineno]) + and ( + # operator char should not be in the right subexpression + expr.right.lineno - 2 > lineno or + right_col < normalize(expr.right.lineno - 2, expr.right.col_offset) + ) + and not (ch := lines[lineno][right_col]).isspace() + and ch not in "\\#" ): - right_anchor += 1 - return _Anchors(normalize(left_anchor), normalize(right_anchor)) + right_col += 1 + + # right_col can be invalid since it is exclusive + return _Anchors(lineno, col, lineno, right_col) case ast.Subscript(): - subscript_start = normalize(expr.value.end_col_offset) - subscript_end = normalize(expr.slice.end_col_offset + 1) - return _Anchors(subscript_start, subscript_end) + # ast gives these locations for value and slice subexpressions + # ( value_expr ) [ slice_expr ] + # value^^^^^ slice^^^^^ + # subscript^^^^^^^^^^^^^^^^^^^^ + + # find left bracket + left_lineno, left_col = setup_positions(expr.value) + left_lineno, left_col = increment_until(left_lineno, left_col, lambda x: x == '[') + # find right bracket (final character of expression) + right_lineno, right_col = setup_positions(expr, force_valid=False) + return _Anchors(left_lineno, left_col, right_lineno, right_col) + case ast.Call(): + # ast gives these locations for function call expressions + # ( func_expr ) (args, kwargs) + # func^^^^^ + # call^^^^^^^^^^^^^^^^^^^^^^^^ + + # find left bracket + left_lineno, left_col = setup_positions(expr.func) + left_lineno, left_col = increment_until(left_lineno, left_col, lambda x: x == '(') + # find right bracket (final character of expression) + right_lineno, right_col = setup_positions(expr, force_valid=False) + return _Anchors(left_lineno, left_col, right_lineno, right_col) return None +_WIDE_CHAR_SPECIFIERS = "WF" + +def _display_width(line, offset=None): + """Calculate the extra amount of width space the given source + code segment might take if it were to be displayed on a fixed + width output device. Supports wide unicode characters and emojis.""" + + if offset is None: + offset = len(line) + + # Fast track for ASCII-only strings + if line.isascii(): + return offset + + import unicodedata + + return sum( + 2 if unicodedata.east_asian_width(char) in _WIDE_CHAR_SPECIFIERS else 1 + for char in line[:offset] + ) + + class _ExceptionPrintContext: def __init__(self): @@ -663,7 +1009,8 @@ class TracebackException: - :attr:`__suppress_context__` The *__suppress_context__* value from the original exception. - :attr:`stack` A `StackSummary` representing the traceback. - - :attr:`exc_type` The class of the original traceback. + - :attr:`exc_type` (deprecated) The class of the original traceback. + - :attr:`exc_type_str` String display of exc_type - :attr:`filename` For syntax errors - the filename where the error occurred. - :attr:`lineno` For syntax errors - the linenumber where the error @@ -681,7 +1028,7 @@ class TracebackException: def __init__(self, exc_type, exc_value, exc_traceback, *, limit=None, lookup_lines=True, capture_locals=False, compact=False, - max_group_width=15, max_group_depth=10, _seen=None): + max_group_width=15, max_group_depth=10, save_exc_type=True, _seen=None): # NB: we need to accept exc_traceback, exc_value, exc_traceback to # permit backwards compat with the existing API, otherwise we # need stub thunk objects just to glue it together. @@ -698,12 +1045,23 @@ def __init__(self, exc_type, exc_value, exc_traceback, *, limit=None, _walk_tb_with_full_positions(exc_traceback), limit=limit, lookup_lines=lookup_lines, capture_locals=capture_locals) - self.exc_type = exc_type + + self._exc_type = exc_type if save_exc_type else None + # Capture now to permit freeing resources: only complication is in the # unofficial API _format_final_exc_line self._str = _safe_string(exc_value, 'exception') self.__notes__ = getattr(exc_value, '__notes__', None) + self._is_syntax_error = False + self._have_exc_type = exc_type is not None + if exc_type is not None: + self.exc_type_qualname = exc_type.__qualname__ + self.exc_type_module = exc_type.__module__ + else: + self.exc_type_qualname = None + self.exc_type_module = None + if exc_type and issubclass(exc_type, SyntaxError): # Handle SyntaxError's specially self.filename = exc_value.filename @@ -715,6 +1073,7 @@ def __init__(self, exc_type, exc_value, exc_traceback, *, limit=None, self.offset = exc_value.offset self.end_offset = exc_value.end_offset self.msg = exc_value.msg + self._is_syntax_error = True elif exc_type and issubclass(exc_type, ImportError) and \ getattr(exc_value, "name_from", None) is not None: wrong_name = getattr(exc_value, "name_from", None) @@ -731,9 +1090,9 @@ def __init__(self, exc_type, exc_value, exc_traceback, *, limit=None, wrong_name = getattr(exc_value, "name", None) if wrong_name is not None and wrong_name in sys.stdlib_module_names: if suggestion: - self._str += f" Or did you forget to import '{wrong_name}'" + self._str += f" Or did you forget to import '{wrong_name}'?" else: - self._str += f". Did you forget to import '{wrong_name}'" + self._str += f". Did you forget to import '{wrong_name}'?" if lookup_lines: self._load_lines() self.__suppress_context__ = \ @@ -813,6 +1172,24 @@ def from_exception(cls, exc, *args, **kwargs): """Create a TracebackException from an exception.""" return cls(type(exc), exc, exc.__traceback__, *args, **kwargs) + @property + def exc_type(self): + warnings.warn('Deprecated in 3.13. Use exc_type_str instead.', + DeprecationWarning, stacklevel=2) + return self._exc_type + + @property + def exc_type_str(self): + if not self._have_exc_type: + return None + stype = self.exc_type_qualname + smod = self.exc_type_module + if smod not in ("__main__", "builtins"): + if not isinstance(smod, str): + smod = "" + stype = smod + '.' + stype + return stype + def _load_lines(self): """Private API. force all lines in the stack to be loaded.""" for frame in self.stack: @@ -826,36 +1203,45 @@ def __eq__(self, other): def __str__(self): return self._str - def format_exception_only(self, *, show_group=False, _depth=0): + def format_exception_only(self, *, show_group=False, _depth=0, **kwargs): """Format the exception part of the traceback. The return value is a generator of strings, each ending in a newline. - Normally, the generator emits a single string; however, for - SyntaxError exceptions, it emits several lines that (when - printed) display detailed information about where the syntax - error occurred. - - The message indicating which exception occurred is always the last - string in the output. + Generator yields the exception message. + For :exc:`SyntaxError` exceptions, it + also yields (before the exception message) + several lines that (when printed) + display detailed information about where the syntax error occurred. + Following the message, generator also yields + all the exception's ``__notes__``. + + When *show_group* is ``True``, and the exception is an instance of + :exc:`BaseExceptionGroup`, the nested exceptions are included as + well, recursively, with indentation relative to their nesting depth. """ + colorize = kwargs.get("colorize", False) indent = 3 * _depth * ' ' - if self.exc_type is None: - yield indent + _format_final_exc_line(None, self._str) + if not self._have_exc_type: + yield indent + _format_final_exc_line(None, self._str, colorize=colorize) return - stype = self.exc_type.__qualname__ - smod = self.exc_type.__module__ - if smod not in ("__main__", "builtins"): - if not isinstance(smod, str): - smod = "" - stype = smod + '.' + stype - - if not issubclass(self.exc_type, SyntaxError): - yield indent + _format_final_exc_line(stype, self._str) + stype = self.exc_type_str + if not self._is_syntax_error: + if _depth > 0: + # Nested exceptions needs correct handling of multiline messages. + formatted = _format_final_exc_line( + stype, self._str, insert_final_newline=False, colorize=colorize + ).split('\n') + yield from [ + indent + l + '\n' + for l in formatted + ] + else: + yield _format_final_exc_line(stype, self._str, colorize=colorize) else: - yield from [indent + l for l in self._format_syntax_error(stype)] + yield from [indent + l for l in self._format_syntax_error(stype, colorize=colorize)] if ( isinstance(self.__notes__, collections.abc.Sequence) @@ -869,15 +1255,26 @@ def format_exception_only(self, *, show_group=False, _depth=0): if self.exceptions and show_group: for ex in self.exceptions: - yield from ex.format_exception_only(show_group=show_group, _depth=_depth+1) + yield from ex.format_exception_only(show_group=show_group, _depth=_depth+1, colorize=colorize) - def _format_syntax_error(self, stype): + def _format_syntax_error(self, stype, **kwargs): """Format SyntaxError exceptions (internal helper).""" # Show exactly where the problem was found. + colorize = kwargs.get("colorize", False) filename_suffix = '' if self.lineno is not None: - yield ' File "{}", line {}\n'.format( - self.filename or "", self.lineno) + if colorize: + yield ' File {}"{}"{}, line {}{}{}\n'.format( + _ANSIColors.MAGENTA, + self.filename or "", + _ANSIColors.RESET, + _ANSIColors.MAGENTA, + self.lineno, + _ANSIColors.RESET, + ) + else: + yield ' File "{}", line {}\n'.format( + self.filename or "", self.lineno) elif self.filename is not None: filename_suffix = ' ({})'.format(self.filename) @@ -889,25 +1286,58 @@ def _format_syntax_error(self, stype): rtext = text.rstrip('\n') ltext = rtext.lstrip(' \n\f') spaces = len(rtext) - len(ltext) - yield ' {}\n'.format(ltext) - - if self.offset is not None: + if self.offset is None: + yield ' {}\n'.format(ltext) + else: offset = self.offset end_offset = self.end_offset if self.end_offset not in {None, 0} else offset - if offset == end_offset or end_offset == -1: + if self.text and offset > len(self.text): + offset = len(self.text) + 1 + if self.text and end_offset > len(self.text): + end_offset = len(self.text) + 1 + if offset >= end_offset or end_offset < 0: end_offset = offset + 1 # Convert 1-based column offset to 0-based index into stripped text colno = offset - 1 - spaces end_colno = end_offset - 1 - spaces + caretspace = ' ' if colno >= 0: # non-space whitespace (likes tabs) must be kept for alignment caretspace = ((c if c.isspace() else ' ') for c in ltext[:colno]) - yield ' {}{}'.format("".join(caretspace), ('^' * (end_colno - colno) + "\n")) + start_color = end_color = "" + if colorize: + # colorize from colno to end_colno + ltext = ( + ltext[:colno] + + _ANSIColors.BOLD_RED + ltext[colno:end_colno] + _ANSIColors.RESET + + ltext[end_colno:] + ) + start_color = _ANSIColors.BOLD_RED + end_color = _ANSIColors.RESET + yield ' {}\n'.format(ltext) + yield ' {}{}{}{}\n'.format( + "".join(caretspace), + start_color, + ('^' * (end_colno - colno)), + end_color, + ) + else: + yield ' {}\n'.format(ltext) msg = self.msg or "" - yield "{}: {}{}\n".format(stype, msg, filename_suffix) + if colorize: + yield "{}{}{}: {}{}{}{}\n".format( + _ANSIColors.BOLD_MAGENTA, + stype, + _ANSIColors.RESET, + _ANSIColors.MAGENTA, + msg, + _ANSIColors.RESET, + filename_suffix) + else: + yield "{}: {}{}\n".format(stype, msg, filename_suffix) - def format(self, *, chain=True, _ctx=None): + def format(self, *, chain=True, _ctx=None, **kwargs): """Format the exception. If chain is not *True*, *__cause__* and *__context__* will not be formatted. @@ -919,7 +1349,7 @@ def format(self, *, chain=True, _ctx=None): The message indicating which exception occurred is always the last string in the output. """ - + colorize = kwargs.get("colorize", False) if _ctx is None: _ctx = _ExceptionPrintContext() @@ -949,8 +1379,8 @@ def format(self, *, chain=True, _ctx=None): if exc.exceptions is None: if exc.stack: yield from _ctx.emit('Traceback (most recent call last):\n') - yield from _ctx.emit(exc.stack.format()) - yield from _ctx.emit(exc.format_exception_only()) + yield from _ctx.emit(exc.stack.format(colorize=colorize)) + yield from _ctx.emit(exc.format_exception_only(colorize=colorize)) elif _ctx.exception_group_depth > self.max_group_depth: # exception group, but depth exceeds limit yield from _ctx.emit( @@ -965,9 +1395,9 @@ def format(self, *, chain=True, _ctx=None): yield from _ctx.emit( 'Exception Group Traceback (most recent call last):\n', margin_char = '+' if is_toplevel else None) - yield from _ctx.emit(exc.stack.format()) + yield from _ctx.emit(exc.stack.format(colorize=colorize)) - yield from _ctx.emit(exc.format_exception_only()) + yield from _ctx.emit(exc.format_exception_only(colorize=colorize)) num_excs = len(exc.exceptions) if num_excs <= self.max_group_width: n = num_excs @@ -1008,11 +1438,12 @@ def format(self, *, chain=True, _ctx=None): _ctx.exception_group_depth = 0 - def print(self, *, file=None, chain=True): + def print(self, *, file=None, chain=True, **kwargs): """Print the result of self.format(chain=chain) to 'file'.""" + colorize = kwargs.get("colorize", False) if file is None: file = sys.stderr - for line in self.format(chain=chain): + for line in self.format(chain=chain, colorize=colorize): print(line, file=file, end="") @@ -1066,6 +1497,13 @@ def _compute_suggestion_error(exc_value, tb, wrong_name): if hasattr(self, wrong_name): return f"self.{wrong_name}" + try: + import _suggestions + except ImportError: + pass + else: + return _suggestions._generate_suggestions(d, wrong_name) + # Compute closest match if len(d) > _MAX_CANDIDATE_ITEMS: diff --git a/Lib/tty.py b/Lib/tty.py index 7d916029ff2ce9..283e5c334f5751 100644 --- a/Lib/tty.py +++ b/Lib/tty.py @@ -39,6 +39,7 @@ def cfmakeraw(mode): # Case B: MIN>0, TIME=0 # A pending read shall block until MIN (here 1) bytes are received, # or a signal is received. + mode[CC] = list(mode[CC]) mode[CC][VMIN] = 1 mode[CC][VTIME] = 0 @@ -54,6 +55,7 @@ def cfmakecbreak(mode): # Case B: MIN>0, TIME=0 # A pending read shall block until MIN (here 1) bytes are received, # or a signal is received. + mode[CC] = list(mode[CC]) mode[CC][VMIN] = 1 mode[CC][VTIME] = 0 diff --git a/Lib/turtle.py b/Lib/turtle.py index e542bc956897e9..7bfe81351b0b34 100644 --- a/Lib/turtle.py +++ b/Lib/turtle.py @@ -874,7 +874,7 @@ def __init__(self, type_, data=None): if isinstance(data, str): if data.lower().endswith(".gif") and isfile(data): data = TurtleScreen._image(data) - # else data assumed to be Photoimage + # else data assumed to be PhotoImage elif type_ == "compound": data = [] else: @@ -3920,28 +3920,33 @@ def getmethparlist(ob): function definition and the second is suitable for use in function call. The "self" parameter is not included. """ - defText = callText = "" + orig_sig = inspect.signature(ob) # bit of a hack for methods - turn it into a function # but we drop the "self" param. # Try and build one for Python defined functions - args, varargs, varkw = inspect.getargs(ob.__code__) - items2 = args[1:] - realArgs = args[1:] - defaults = ob.__defaults__ or [] - defaults = ["=%r" % (value,) for value in defaults] - defaults = [""] * (len(realArgs)-len(defaults)) + defaults - items1 = [arg + dflt for arg, dflt in zip(realArgs, defaults)] - if varargs is not None: - items1.append("*" + varargs) - items2.append("*" + varargs) - if varkw is not None: - items1.append("**" + varkw) - items2.append("**" + varkw) - defText = ", ".join(items1) - defText = "(%s)" % defText - callText = ", ".join(items2) - callText = "(%s)" % callText - return defText, callText + func_sig = orig_sig.replace( + parameters=list(orig_sig.parameters.values())[1:], + ) + + call_args = [] + for param in func_sig.parameters.values(): + match param.kind: + case ( + inspect.Parameter.POSITIONAL_ONLY + | inspect.Parameter.POSITIONAL_OR_KEYWORD + ): + call_args.append(param.name) + case inspect.Parameter.VAR_POSITIONAL: + call_args.append(f'*{param.name}') + case inspect.Parameter.KEYWORD_ONLY: + call_args.append(f'{param.name}={param.name}') + case inspect.Parameter.VAR_KEYWORD: + call_args.append(f'**{param.name}') + case _: + raise RuntimeError('Unsupported parameter kind', param.kind) + call_text = f'({', '.join(call_args)})' + + return str(func_sig), call_text def _turtle_docrevise(docstr): """To reduce docstrings from RawTurtle class for functions diff --git a/Lib/turtledemo/__main__.py b/Lib/turtledemo/__main__.py index f6c9d6aa6f9a32..2ab6c15e2c079e 100755 --- a/Lib/turtledemo/__main__.py +++ b/Lib/turtledemo/__main__.py @@ -161,7 +161,7 @@ def __init__(self, filename=None): label='Help', underline=0) root['menu'] = self.mBar - pane = PanedWindow(orient=HORIZONTAL, sashwidth=5, + pane = PanedWindow(root, orient=HORIZONTAL, sashwidth=5, sashrelief=SOLID, bg='#ddd') pane.add(self.makeTextFrame(pane)) pane.add(self.makeGraphFrame(pane)) diff --git a/Lib/types.py b/Lib/types.py index b4aa19cec40c89..1484c22ee9dffa 100644 --- a/Lib/types.py +++ b/Lib/types.py @@ -1,6 +1,7 @@ """ Define names for built-in types that aren't directly accessible as a builtin. """ + import sys # Iterators in Python aren't a matter of type but of protocol. A large @@ -330,4 +331,11 @@ def wrapped(*args, **kwargs): NoneType = type(None) NotImplementedType = type(NotImplemented) +def __getattr__(name): + if name == 'CapsuleType': + import _socket + return type(_socket.CAPI) + raise AttributeError(f"module {__name__!r} has no attribute {name!r}") + __all__ = [n for n in globals() if n[:1] != '_'] +__all__ += ['CapsuleType'] diff --git a/Lib/typing.py b/Lib/typing.py index 387b4c5ad5284b..d278b4effc7eba 100644 --- a/Lib/typing.py +++ b/Lib/typing.py @@ -23,10 +23,8 @@ from collections import defaultdict import collections.abc import copyreg -import contextlib import functools import operator -import re as stdlib_re # Avoid confusion with the typing.re namespace on <=3.11 import sys import types from types import WrapperDescriptorType, MethodWrapperType, MethodDescriptorType, GenericAlias @@ -214,8 +212,12 @@ def _should_unflatten_callable_args(typ, args): For example:: - assert collections.abc.Callable[[int, int], str].__args__ == (int, int, str) - assert collections.abc.Callable[ParamSpec, str].__args__ == (ParamSpec, str) + >>> import collections.abc + >>> P = ParamSpec('P') + >>> collections.abc.Callable[[int, int], str].__args__ == (int, int, str) + True + >>> collections.abc.Callable[P, str].__args__ == (P, str) + True As a result, if we need to reconstruct the Callable from its __args__, we need to unflatten it. @@ -257,7 +259,10 @@ def _collect_parameters(args): For example:: - assert _collect_parameters((T, Callable[P, T])) == (T, P) + >>> P = ParamSpec('P') + >>> T = TypeVar('T') + >>> _collect_parameters((T, Callable[P, T])) + (~T, ~P) """ parameters = [] for t in args: @@ -485,7 +490,7 @@ def __getitem__(self, parameters): return self._getitem(self, parameters) -class _LiteralSpecialForm(_SpecialForm, _root=True): +class _TypedCacheSpecialForm(_SpecialForm, _root=True): def __getitem__(self, parameters): if not isinstance(parameters, tuple): parameters = (parameters,) @@ -718,7 +723,7 @@ def Optional(self, parameters): arg = _type_check(parameters, f"{self} requires a single type.") return Union[arg, type(None)] -@_LiteralSpecialForm +@_TypedCacheSpecialForm @_tp_cache(typed=True) def Literal(self, *parameters): """Special typing form to define literal types (a.k.a. value types). @@ -939,13 +944,6 @@ def _is_typevar_like(x: Any) -> bool: return isinstance(x, (TypeVar, ParamSpec)) or _is_unpacked_typevartuple(x) -class _PickleUsingNameMixin: - """Mixin enabling pickling based on self.__name__.""" - - def __reduce__(self): - return self.__name__ - - def _typevar_subst(self, arg): msg = "Parameters to generic types must be types." arg = _type_check(arg, msg, is_argument=True) @@ -1672,13 +1670,14 @@ class _TypingEllipsis: _TYPING_INTERNALS = frozenset({ '__parameters__', '__orig_bases__', '__orig_class__', '_is_protocol', '_is_runtime_protocol', '__protocol_attrs__', - '__callable_proto_members_only__', '__type_params__', + '__non_callable_proto_members__', '__type_params__', }) _SPECIAL_NAMES = frozenset({ '__abstractmethods__', '__annotations__', '__dict__', '__doc__', '__init__', '__module__', '__new__', '__slots__', - '__subclasshook__', '__weakref__', '__class_getitem__' + '__subclasshook__', '__weakref__', '__class_getitem__', + '__match_args__', }) # These special attributes will be not collected as protocol members. @@ -1783,6 +1782,31 @@ def _pickle_pskwargs(pskwargs): del _pickle_psargs, _pickle_pskwargs +# Preload these once, as globals, as a micro-optimisation. +# This makes a significant difference to the time it takes +# to do `isinstance()`/`issubclass()` checks +# against runtime-checkable protocols with only one callable member. +_abc_instancecheck = ABCMeta.__instancecheck__ +_abc_subclasscheck = ABCMeta.__subclasscheck__ + + +def _type_check_issubclass_arg_1(arg): + """Raise TypeError if `arg` is not an instance of `type` + in `issubclass(arg, )`. + + In most cases, this is verified by type.__subclasscheck__. + Checking it again unnecessarily would slow down issubclass() checks, + so, we don't perform this check unless we absolutely have to. + + For various error paths, however, + we want to ensure that *this* error message is shown to the user + where relevant, rather than a typing.py-specific error message. + """ + if not isinstance(arg, type): + # Same error message as for issubclass(1, int). + raise TypeError('issubclass() arg 1 must be a class') + + class _ProtocolMeta(ABCMeta): # This metaclass is somewhat unfortunate, # but is necessary for several reasons... @@ -1809,11 +1833,6 @@ def __init__(cls, *args, **kwargs): super().__init__(*args, **kwargs) if getattr(cls, "_is_protocol", False): cls.__protocol_attrs__ = _get_protocol_attrs(cls) - # PEP 544 prohibits using issubclass() - # with protocols that have non-method members. - cls.__callable_proto_members_only__ = all( - callable(getattr(cls, attr, None)) for attr in cls.__protocol_attrs__ - ) def __subclasscheck__(cls, other): if cls is Protocol: @@ -1822,22 +1841,24 @@ def __subclasscheck__(cls, other): getattr(cls, '_is_protocol', False) and not _allow_reckless_class_checks() ): - if not isinstance(other, type): - # Same error message as for issubclass(1, int). - raise TypeError('issubclass() arg 1 must be a class') - if ( - not cls.__callable_proto_members_only__ - and cls.__dict__.get("__subclasshook__") is _proto_hook - ): - raise TypeError( - "Protocols with non-method members don't support issubclass()" - ) if not getattr(cls, '_is_runtime_protocol', False): + _type_check_issubclass_arg_1(other) raise TypeError( "Instance and class checks can only be used with " "@runtime_checkable protocols" ) - return super().__subclasscheck__(other) + if ( + # this attribute is set by @runtime_checkable: + cls.__non_callable_proto_members__ + and cls.__dict__.get("__subclasshook__") is _proto_hook + ): + _type_check_issubclass_arg_1(other) + non_method_attrs = sorted(cls.__non_callable_proto_members__) + raise TypeError( + "Protocols with non-method members don't support issubclass()." + f" Non-method members: {str(non_method_attrs)[1:-1]}." + ) + return _abc_subclasscheck(cls, other) def __instancecheck__(cls, instance): # We need this method for situations where attributes are @@ -1846,7 +1867,7 @@ def __instancecheck__(cls, instance): return type.__instancecheck__(cls, instance) if not getattr(cls, "_is_protocol", False): # i.e., it's a concrete subclass of a protocol - return super().__instancecheck__(instance) + return _abc_instancecheck(cls, instance) if ( not getattr(cls, '_is_runtime_protocol', False) and @@ -1855,7 +1876,7 @@ def __instancecheck__(cls, instance): raise TypeError("Instance and class checks can only be used with" " @runtime_checkable protocols") - if super().__instancecheck__(instance): + if _abc_instancecheck(cls, instance): return True getattr_static = _lazy_load_getattr_static() @@ -1864,7 +1885,8 @@ def __instancecheck__(cls, instance): val = getattr_static(instance, attr) except AttributeError: break - if val is None and callable(getattr(cls, attr, None)): + # this attribute is set by @runtime_checkable: + if val is None and attr not in cls.__non_callable_proto_members__: break else: return True @@ -2001,7 +2023,9 @@ def __mro_entries__(self, bases): return (self.__origin__,) -class Annotated: +@_TypedCacheSpecialForm +@_tp_cache(typed=True) +def Annotated(self, *params): """Add context-specific metadata to a type. Example: Annotated[int, runtime_check.Unsigned] indicates to the @@ -2048,30 +2072,17 @@ class Annotated: where T1, T2 etc. are TypeVars, which would be invalid, because only one type should be passed to Annotated. """ - - __slots__ = () - - def __new__(cls, *args, **kwargs): - raise TypeError("Type Annotated cannot be instantiated.") - - @_tp_cache - def __class_getitem__(cls, params): - if not isinstance(params, tuple) or len(params) < 2: - raise TypeError("Annotated[...] should be used " - "with at least two arguments (a type and an " - "annotation).") - if _is_unpacked_typevartuple(params[0]): - raise TypeError("Annotated[...] should not be used with an " - "unpacked TypeVarTuple") - msg = "Annotated[t, ...]: t must be a type." - origin = _type_check(params[0], msg, allow_special_forms=True) - metadata = tuple(params[1:]) - return _AnnotatedAlias(origin, metadata) - - def __init_subclass__(cls, *args, **kwargs): - raise TypeError( - "Cannot subclass {}.Annotated".format(cls.__module__) - ) + if len(params) < 2: + raise TypeError("Annotated[...] should be used " + "with at least two arguments (a type and an " + "annotation).") + if _is_unpacked_typevartuple(params[0]): + raise TypeError("Annotated[...] should not be used with an " + "unpacked TypeVarTuple") + msg = "Annotated[t, ...]: t must be a type." + origin = _type_check(params[0], msg, allow_special_forms=True) + metadata = tuple(params[1:]) + return _AnnotatedAlias(origin, metadata) def runtime_checkable(cls): @@ -2097,6 +2108,22 @@ def close(self): ... raise TypeError('@runtime_checkable can be only applied to protocol classes,' ' got %r' % cls) cls._is_runtime_protocol = True + # PEP 544 prohibits using issubclass() + # with protocols that have non-method members. + # See gh-113320 for why we compute this attribute here, + # rather than in `_ProtocolMeta.__init__` + cls.__non_callable_proto_members__ = set() + for attr in cls.__protocol_attrs__: + try: + is_callable = callable(getattr(cls, attr, None)) + except Exception as e: + raise TypeError( + f"Failed to determine whether protocol member {attr!r} " + "is a method member" + ) from e + else: + if not is_callable: + cls.__non_callable_proto_members__.add(attr) return cls @@ -2264,14 +2291,15 @@ def get_origin(tp): Examples:: - assert get_origin(Literal[42]) is Literal - assert get_origin(int) is None - assert get_origin(ClassVar[int]) is ClassVar - assert get_origin(Generic) is Generic - assert get_origin(Generic[T]) is Generic - assert get_origin(Union[T, int]) is Union - assert get_origin(List[Tuple[T, T]][int]) is list - assert get_origin(P.args) is P + >>> P = ParamSpec('P') + >>> assert get_origin(Literal[42]) is Literal + >>> assert get_origin(int) is None + >>> assert get_origin(ClassVar[int]) is ClassVar + >>> assert get_origin(Generic) is Generic + >>> assert get_origin(Generic[T]) is Generic + >>> assert get_origin(Union[T, int]) is Union + >>> assert get_origin(List[Tuple[T, T]][int]) is list + >>> assert get_origin(P.args) is P """ if isinstance(tp, _AnnotatedAlias): return Annotated @@ -2292,11 +2320,12 @@ def get_args(tp): Examples:: - assert get_args(Dict[str, int]) == (str, int) - assert get_args(int) == () - assert get_args(Union[int, Union[T, int], str][int]) == (int, str) - assert get_args(Union[int, Tuple[T, int]][str]) == (int, Tuple[str, int]) - assert get_args(Callable[[], T][int]) == ([], int) + >>> T = TypeVar('T') + >>> assert get_args(Dict[str, int]) == (str, int) + >>> assert get_args(int) == () + >>> assert get_args(Union[int, Union[T, int], str][int]) == (int, str) + >>> assert get_args(Union[int, Tuple[T, int]][str]) == (int, Tuple[str, int]) + >>> assert get_args(Callable[[], T][int]) == ([], int) """ if isinstance(tp, _AnnotatedAlias): return (tp.__origin__,) + tp.__metadata__ @@ -2315,12 +2344,15 @@ def is_typeddict(tp): For example:: - class Film(TypedDict): - title: str - year: int - - is_typeddict(Film) # => True - is_typeddict(Union[list, str]) # => False + >>> from typing import TypedDict + >>> class Film(TypedDict): + ... title: str + ... year: int + ... + >>> is_typeddict(Film) + True + >>> is_typeddict(dict) + False """ return isinstance(tp, _TypedDictMeta) @@ -2592,8 +2624,6 @@ class Other(Leaf): # Error reported by type checker KeysView = _alias(collections.abc.KeysView, 1) ItemsView = _alias(collections.abc.ItemsView, 2) ValuesView = _alias(collections.abc.ValuesView, 1) -ContextManager = _alias(contextlib.AbstractContextManager, 1, name='ContextManager') -AsyncContextManager = _alias(contextlib.AbstractAsyncContextManager, 1, name='AsyncContextManager') Dict = _alias(dict, 2, inst=False, name='Dict') DefaultDict = _alias(collections.defaultdict, 2, name='DefaultDict') OrderedDict = _alias(collections.OrderedDict, 2) @@ -2748,11 +2778,26 @@ def __new__(cls, typename, bases, ns): class_getitem = _generic_class_getitem nm_tpl.__class_getitem__ = classmethod(class_getitem) # update from user namespace without overriding special namedtuple attributes - for key in ns: + for key, val in ns.items(): if key in _prohibited: raise AttributeError("Cannot overwrite NamedTuple attribute " + key) - elif key not in _special and key not in nm_tpl._fields: - setattr(nm_tpl, key, ns[key]) + elif key not in _special: + if key not in nm_tpl._fields: + setattr(nm_tpl, key, val) + try: + set_name = type(val).__set_name__ + except AttributeError: + pass + else: + try: + set_name(val, nm_tpl, key) + except BaseException as e: + e.add_note( + f"Error calling __set_name__ on {type(val).__name__!r} " + f"instance {key!r} in {typename!r}" + ) + raise + if Generic in bases: nm_tpl.__init_subclass__() return nm_tpl @@ -2874,8 +2919,14 @@ def __new__(cls, name, bases, ns, total=True): for base in bases: annotations.update(base.__dict__.get('__annotations__', {})) - required_keys.update(base.__dict__.get('__required_keys__', ())) - optional_keys.update(base.__dict__.get('__optional_keys__', ())) + + base_required = base.__dict__.get('__required_keys__', set()) + required_keys |= base_required + optional_keys -= base_required + + base_optional = base.__dict__.get('__optional_keys__', set()) + required_keys -= base_optional + optional_keys |= base_optional annotations.update(own_annotations) for annotation_key, annotation_type in own_annotations.items(): @@ -2887,19 +2938,27 @@ def __new__(cls, name, bases, ns, total=True): annotation_origin = get_origin(annotation_type) if annotation_origin is Required: - required_keys.add(annotation_key) + is_required = True elif annotation_origin is NotRequired: - optional_keys.add(annotation_key) - elif total: + is_required = False + else: + is_required = total + + if is_required: required_keys.add(annotation_key) + optional_keys.discard(annotation_key) else: optional_keys.add(annotation_key) + required_keys.discard(annotation_key) + assert required_keys.isdisjoint(optional_keys), ( + f"Required keys overlap with optional keys in {name}:" + f" {required_keys=}, {optional_keys=}" + ) tp_dict.__annotations__ = annotations tp_dict.__required_keys__ = frozenset(required_keys) tp_dict.__optional_keys__ = frozenset(optional_keys) - if not hasattr(tp_dict, '__total__'): - tp_dict.__total__ = total + tp_dict.__total__ = total return tp_dict __call__ = dict # static method @@ -2921,15 +2980,15 @@ def TypedDict(typename, fields=_sentinel, /, *, total=True): Usage:: - class Point2D(TypedDict): - x: int - y: int - label: str - - a: Point2D = {'x': 1, 'y': 2, 'label': 'good'} # OK - b: Point2D = {'z': 3, 'label': 'bad'} # Fails type check - - assert Point2D(x=1, y=2, label='first') == dict(x=1, y=2, label='first') + >>> class Point2D(TypedDict): + ... x: int + ... y: int + ... label: str + ... + >>> a: Point2D = {'x': 1, 'y': 2, 'label': 'good'} # OK + >>> b: Point2D = {'z': 3, 'label': 'bad'} # Fails type check + >>> Point2D(x=1, y=2, label='first') == dict(x=1, y=2, label='first') + True The type info can be accessed via the Point2D.__annotations__ dict, and the Point2D.__required_keys__ and Point2D.__optional_keys__ frozensets. @@ -3251,12 +3310,8 @@ def __enter__(self) -> 'TextIO': pass -Pattern = _alias(stdlib_re.Pattern, 1) -Match = _alias(stdlib_re.Match, 1) - - def reveal_type[T](obj: T, /) -> T: - """Reveal the inferred type of a variable. + """Ask a static type checker to reveal the inferred type of an expression. When a static type checker encounters a call to ``reveal_type()``, it will emit the inferred type of the argument:: @@ -3268,7 +3323,7 @@ def reveal_type[T](obj: T, /) -> T: will produce output similar to 'Revealed type is "builtins.int"'. At runtime, the function prints the runtime type of the - argument and returns it unchanged. + argument and returns the argument unchanged. """ print(f"Runtime type is {type(obj).__name__!r}", file=sys.stderr) return obj @@ -3372,7 +3427,7 @@ def override[F: _Func](method: F, /) -> F: Usage:: class Base: - def method(self) -> None: ... + def method(self) -> None: pass class Child(Base): @@ -3431,11 +3486,29 @@ def get_protocol_members(tp: type, /) -> frozenset[str]: >>> class P(Protocol): ... def a(self) -> str: ... ... b: int - >>> get_protocol_members(P) - frozenset({'a', 'b'}) + >>> get_protocol_members(P) == frozenset({'a', 'b'}) + True Raise a TypeError for arguments that are not Protocols. """ if not is_protocol(tp): raise TypeError(f'{tp!r} is not a Protocol') return frozenset(tp.__protocol_attrs__) + + +def __getattr__(attr): + """Improve the import time of the typing module. + + Soft-deprecated objects which are costly to create + are only created on-demand here. + """ + if attr in {"Pattern", "Match"}: + import re + obj = _alias(getattr(re, attr), 1) + elif attr in {"ContextManager", "AsyncContextManager"}: + import contextlib + obj = _alias(getattr(contextlib, f"Abstract{attr}"), 1, name=attr) + else: + raise AttributeError(f"module {__name__!r} has no attribute {attr!r}") + globals()[attr] = obj + return obj diff --git a/Lib/unittest/async_case.py b/Lib/unittest/async_case.py index bd2a471156065b..63ff6a5d1f8b61 100644 --- a/Lib/unittest/async_case.py +++ b/Lib/unittest/async_case.py @@ -25,12 +25,15 @@ class IsolatedAsyncioTestCase(TestCase): # them inside the same task. # Note: the test case modifies event loop policy if the policy was not instantiated - # yet. + # yet, unless loop_factory=asyncio.EventLoop is set. # asyncio.get_event_loop_policy() creates a default policy on demand but never # returns None # I believe this is not an issue in user level tests but python itself for testing # should reset a policy in every test module # by calling asyncio.set_event_loop_policy(None) in tearDownModule() + # or set loop_factory=asyncio.EventLoop + + loop_factory = None def __init__(self, methodName='runTest'): super().__init__(methodName) @@ -118,7 +121,7 @@ def _callMaybeAsync(self, func, /, *args, **kwargs): def _setupAsyncioRunner(self): assert self._asyncioRunner is None, 'asyncio runner is already initialized' - runner = asyncio.Runner(debug=True) + runner = asyncio.Runner(debug=True, loop_factory=self.loop_factory) self._asyncioRunner = runner def _tearDownAsyncioRunner(self): diff --git a/Lib/unittest/case.py b/Lib/unittest/case.py index 001b640dc43ad6..811557498bb30e 100644 --- a/Lib/unittest/case.py +++ b/Lib/unittest/case.py @@ -606,7 +606,6 @@ def run(self, result=None): else: stopTestRun = None - result.startTest(self) try: testMethod = getattr(self, self._testMethodName) if (getattr(self.__class__, "__unittest_skip__", False) or @@ -617,6 +616,9 @@ def run(self, result=None): _addSkip(result, self, skip_why) return result + # Increase the number of tests only if it hasn't been skipped + result.startTest(self) + expecting_failure = ( getattr(self, "__unittest_expecting_failure__", False) or getattr(testMethod, "__unittest_expecting_failure__", False) diff --git a/Lib/unittest/loader.py b/Lib/unittest/loader.py index 678d627d7c6926..9a3e5cc4bf30e5 100644 --- a/Lib/unittest/loader.py +++ b/Lib/unittest/loader.py @@ -84,9 +84,13 @@ def loadTestsFromTestCase(self, testCaseClass): raise TypeError("Test cases should not be derived from " "TestSuite. Maybe you meant to derive from " "TestCase?") - testCaseNames = self.getTestCaseNames(testCaseClass) - if not testCaseNames and hasattr(testCaseClass, 'runTest'): - testCaseNames = ['runTest'] + if testCaseClass in (case.TestCase, case.FunctionTestCase): + # We don't load any tests from base types that should not be loaded. + testCaseNames = [] + else: + testCaseNames = self.getTestCaseNames(testCaseClass) + if not testCaseNames and hasattr(testCaseClass, 'runTest'): + testCaseNames = ['runTest'] loaded_suite = self.suiteClass(map(testCaseClass, testCaseNames)) return loaded_suite @@ -95,7 +99,11 @@ def loadTestsFromModule(self, module, *, pattern=None): tests = [] for name in dir(module): obj = getattr(module, name) - if isinstance(obj, type) and issubclass(obj, case.TestCase): + if ( + isinstance(obj, type) + and issubclass(obj, case.TestCase) + and obj not in (case.TestCase, case.FunctionTestCase) + ): tests.append(self.loadTestsFromTestCase(obj)) load_tests = getattr(module, 'load_tests', None) @@ -164,7 +172,11 @@ def loadTestsFromName(self, name, module=None): if isinstance(obj, types.ModuleType): return self.loadTestsFromModule(obj) - elif isinstance(obj, type) and issubclass(obj, case.TestCase): + elif ( + isinstance(obj, type) + and issubclass(obj, case.TestCase) + and obj not in (case.TestCase, case.FunctionTestCase) + ): return self.loadTestsFromTestCase(obj) elif (isinstance(obj, types.FunctionType) and isinstance(parent, type) and diff --git a/Lib/unittest/main.py b/Lib/unittest/main.py index d29a9f91fcca42..c3869de3f6f18e 100644 --- a/Lib/unittest/main.py +++ b/Lib/unittest/main.py @@ -269,7 +269,7 @@ def runTests(self): testRunner = self.testRunner self.result = testRunner.run(self.test) if self.exit: - if self.result.testsRun == 0: + if self.result.testsRun == 0 and len(self.result.skipped) == 0: sys.exit(_NO_TESTS_EXITCODE) elif self.result.wasSuccessful(): sys.exit(0) diff --git a/Lib/unittest/mock.py b/Lib/unittest/mock.py index e8c8360e0ae13e..93f4d9743ed2fa 100644 --- a/Lib/unittest/mock.py +++ b/Lib/unittest/mock.py @@ -857,7 +857,7 @@ def _format_mock_call_signature(self, args, kwargs): def _format_mock_failure_message(self, args, kwargs, action='call'): - message = 'expected %s not found.\nExpected: %s\nActual: %s' + message = 'expected %s not found.\nExpected: %s\n Actual: %s' expected_string = self._format_mock_call_signature(args, kwargs) call_args = self.call_args actual_string = self._format_mock_call_signature(*call_args) @@ -960,7 +960,7 @@ def assert_called_with(self, /, *args, **kwargs): if self.call_args is None: expected = self._format_mock_call_signature(args, kwargs) actual = 'not called.' - error_message = ('expected call not found.\nExpected: %s\nActual: %s' + error_message = ('expected call not found.\nExpected: %s\n Actual: %s' % (expected, actual)) raise AssertionError(error_message) @@ -1010,8 +1010,8 @@ def assert_has_calls(self, calls, any_order=False): for e in expected]) raise AssertionError( f'{problem}\n' - f'Expected: {_CallList(calls)}' - f'{self._calls_repr(prefix="Actual").rstrip(".")}' + f'Expected: {_CallList(calls)}\n' + f' Actual: {safe_repr(self.mock_calls)}' ) from cause return @@ -1085,7 +1085,7 @@ def _get_child_mock(self, /, **kw): return klass(**kw) - def _calls_repr(self, prefix="Calls"): + def _calls_repr(self): """Renders self.mock_calls as a string. Example: "\nCalls: [call(1), call(2)]." @@ -1095,7 +1095,7 @@ def _calls_repr(self, prefix="Calls"): """ if not self.mock_calls: return "" - return f"\n{prefix}: {safe_repr(self.mock_calls)}." + return f"\nCalls: {safe_repr(self.mock_calls)}." # Denylist for forbidden attribute names in safe mode @@ -2229,8 +2229,11 @@ def __get__(self, obj, _type=None): return self.create_mock() -_CODE_ATTRS = dir(CodeType) -_CODE_SIG = inspect.signature(partial(CodeType.__init__, None)) +try: + _CODE_SIG = inspect.signature(partial(CodeType.__init__, None)) + _CODE_ATTRS = dir(CodeType) +except ValueError: + _CODE_SIG = None class AsyncMockMixin(Base): @@ -2250,9 +2253,12 @@ def __init__(self, /, *args, **kwargs): self.__dict__['_mock_await_count'] = 0 self.__dict__['_mock_await_args'] = None self.__dict__['_mock_await_args_list'] = _CallList() - code_mock = NonCallableMock(spec_set=_CODE_ATTRS) - code_mock.__dict__["_spec_class"] = CodeType - code_mock.__dict__["_spec_signature"] = _CODE_SIG + if _CODE_SIG: + code_mock = NonCallableMock(spec_set=_CODE_ATTRS) + code_mock.__dict__["_spec_class"] = CodeType + code_mock.__dict__["_spec_signature"] = _CODE_SIG + else: + code_mock = NonCallableMock(spec_set=CodeType) code_mock.co_flags = ( inspect.CO_COROUTINE + inspect.CO_VARARGS diff --git a/Lib/unittest/result.py b/Lib/unittest/result.py index 3ace0a5b7bf2ef..9e56f658027f4d 100644 --- a/Lib/unittest/result.py +++ b/Lib/unittest/result.py @@ -97,10 +97,12 @@ def _restoreStdout(self): sys.stdout = self._original_stdout sys.stderr = self._original_stderr - self._stdout_buffer.seek(0) - self._stdout_buffer.truncate() - self._stderr_buffer.seek(0) - self._stderr_buffer.truncate() + if self._stdout_buffer is not None: + self._stdout_buffer.seek(0) + self._stdout_buffer.truncate() + if self._stderr_buffer is not None: + self._stderr_buffer.seek(0) + self._stderr_buffer.truncate() def stopTestRun(self): """Called once after all tests are executed. diff --git a/Lib/unittest/runner.py b/Lib/unittest/runner.py index e3c020e0ace96d..2bcadf0c998bd9 100644 --- a/Lib/unittest/runner.py +++ b/Lib/unittest/runner.py @@ -274,7 +274,7 @@ def run(self, test): infos.append("failures=%d" % failed) if errored: infos.append("errors=%d" % errored) - elif run == 0: + elif run == 0 and not skipped: self.stream.write("NO TESTS RAN") else: self.stream.write("OK") diff --git a/Lib/venv/__init__.py b/Lib/venv/__init__.py index 2173c9b13e5cf7..d960bf3bd82ac5 100644 --- a/Lib/venv/__init__.py +++ b/Lib/venv/__init__.py @@ -41,11 +41,13 @@ class EnvBuilder: environment :param prompt: Alternative terminal prefix for the environment. :param upgrade_deps: Update the base venv modules to the latest on PyPI + :param scm_ignore_files: Create ignore files for the SCMs specified by the + iterable. """ def __init__(self, system_site_packages=False, clear=False, symlinks=False, upgrade=False, with_pip=False, prompt=None, - upgrade_deps=False): + upgrade_deps=False, *, scm_ignore_files=frozenset()): self.system_site_packages = system_site_packages self.clear = clear self.symlinks = symlinks @@ -56,6 +58,7 @@ def __init__(self, system_site_packages=False, clear=False, prompt = os.path.basename(os.getcwd()) self.prompt = prompt self.upgrade_deps = upgrade_deps + self.scm_ignore_files = frozenset(map(str.lower, scm_ignore_files)) def create(self, env_dir): """ @@ -66,6 +69,8 @@ def create(self, env_dir): """ env_dir = os.path.abspath(env_dir) context = self.ensure_directories(env_dir) + for scm in self.scm_ignore_files: + getattr(self, f"create_{scm}_ignore_file")(context) # See issue 24875. We need system_site_packages to be False # until after pip is installed. true_system_site_packages = self.system_site_packages @@ -210,6 +215,8 @@ def create_configuration(self, context): args.append('--upgrade-deps') if self.orig_prompt is not None: args.append(f'--prompt="{self.orig_prompt}"') + if not self.scm_ignore_files: + args.append('--without-scm-ignore-files') args.append(context.env_dir) args = ' '.join(args) @@ -278,6 +285,19 @@ def symlink_or_copy(self, src, dst, relative_symlinks_ok=False): shutil.copyfile(src, dst) + def create_git_ignore_file(self, context): + """ + Create a .gitignore file in the environment directory. + + The contents of the file cause the entire environment directory to be + ignored by git. + """ + gitignore_path = os.path.join(context.env_dir, '.gitignore') + with open(gitignore_path, 'w', encoding='utf-8') as file: + file.write('# Created by venv; ' + 'see https://docs.python.org/3/library/venv.html\n') + file.write('*\n') + def setup_python(self, context): """ Set up a Python executable in the environment. @@ -461,11 +481,13 @@ def upgrade_dependencies(self, context): def create(env_dir, system_site_packages=False, clear=False, - symlinks=False, with_pip=False, prompt=None, upgrade_deps=False): + symlinks=False, with_pip=False, prompt=None, upgrade_deps=False, + *, scm_ignore_files=frozenset()): """Create a virtual environment in a directory.""" builder = EnvBuilder(system_site_packages=system_site_packages, clear=clear, symlinks=symlinks, with_pip=with_pip, - prompt=prompt, upgrade_deps=upgrade_deps) + prompt=prompt, upgrade_deps=upgrade_deps, + scm_ignore_files=scm_ignore_files) builder.create(env_dir) @@ -525,6 +547,11 @@ def main(args=None): dest='upgrade_deps', help=f'Upgrade core dependencies ({", ".join(CORE_VENV_DEPS)}) ' 'to the latest version in PyPI') + parser.add_argument('--without-scm-ignore-files', dest='scm_ignore_files', + action='store_const', const=frozenset(), + default=frozenset(['git']), + help='Skips adding SCM ignore files to the environment ' + 'directory (Git is supported by default).') options = parser.parse_args(args) if options.upgrade and options.clear: raise ValueError('you cannot supply --upgrade and --clear together.') @@ -534,7 +561,8 @@ def main(args=None): upgrade=options.upgrade, with_pip=options.with_pip, prompt=options.prompt, - upgrade_deps=options.upgrade_deps) + upgrade_deps=options.upgrade_deps, + scm_ignore_files=options.scm_ignore_files) for d in options.dirs: builder.create(d) diff --git a/Lib/venv/__main__.py b/Lib/venv/__main__.py index 912423e4a78198..88f55439dc210c 100644 --- a/Lib/venv/__main__.py +++ b/Lib/venv/__main__.py @@ -6,5 +6,5 @@ main() rc = 0 except Exception as e: - print('Error: %s' % e, file=sys.stderr) + print('Error:', e, file=sys.stderr) sys.exit(rc) diff --git a/Lib/venv/scripts/common/activate b/Lib/venv/scripts/common/activate index 458740a35b0d20..a4e0609045a9d5 100644 --- a/Lib/venv/scripts/common/activate +++ b/Lib/venv/scripts/common/activate @@ -14,12 +14,9 @@ deactivate () { unset _OLD_VIRTUAL_PYTHONHOME fi - # This should detect bash and zsh, which have a hash command that must - # be called to get it to forget past commands. Without forgetting + # Call hash to forget past commands. Without forgetting # past commands the $PATH changes we made may not be respected - if [ -n "${BASH:-}" -o -n "${ZSH_VERSION:-}" ] ; then - hash -r 2> /dev/null - fi + hash -r 2> /dev/null if [ -n "${_OLD_VIRTUAL_PS1:-}" ] ; then PS1="${_OLD_VIRTUAL_PS1:-}" @@ -39,14 +36,18 @@ deactivate () { deactivate nondestructive # on Windows, a path can contain colons and backslashes and has to be converted: -if [ "$OSTYPE" = "cygwin" ] || [ "$OSTYPE" = "msys" ] ; then - # transform D:\path\to\venv to /d/path/to/venv on MSYS - # and to /cygdrive/d/path/to/venv on Cygwin - export VIRTUAL_ENV=$(cygpath "__VENV_DIR__") -else - # use the path as-is - export VIRTUAL_ENV="__VENV_DIR__" -fi +case "$(uname)" in + CYGWIN*|MSYS*) + # transform D:\path\to\venv to /d/path/to/venv on MSYS + # and to /cygdrive/d/path/to/venv on Cygwin + VIRTUAL_ENV=$(cygpath "__VENV_DIR__") + export VIRTUAL_ENV + ;; + *) + # use the path as-is + export VIRTUAL_ENV="__VENV_DIR__" + ;; +esac _OLD_VIRTUAL_PATH="$PATH" PATH="$VIRTUAL_ENV/__VENV_BIN_NAME__:$PATH" @@ -69,9 +70,6 @@ if [ -z "${VIRTUAL_ENV_DISABLE_PROMPT:-}" ] ; then export PS1 fi -# This should detect bash and zsh, which have a hash command that must -# be called to get it to forget past commands. Without forgetting +# Call hash to forget past commands. Without forgetting # past commands the $PATH changes we made may not be respected -if [ -n "${BASH:-}" -o -n "${ZSH_VERSION:-}" ] ; then - hash -r 2> /dev/null -fi +hash -r 2> /dev/null diff --git a/Lib/warnings.py b/Lib/warnings.py index 32e58072b9cc33..4ad6ad027192e8 100644 --- a/Lib/warnings.py +++ b/Lib/warnings.py @@ -5,7 +5,7 @@ __all__ = ["warn", "warn_explicit", "showwarning", "formatwarning", "filterwarnings", "simplefilter", - "resetwarnings", "catch_warnings"] + "resetwarnings", "catch_warnings", "deprecated"] def showwarning(message, category, filename, lineno, file=None, line=None): """Hook to write a warning to a file; replace if you like.""" @@ -58,15 +58,16 @@ def _formatwarnmsg_impl(msg): # catch Exception, not only ImportError and RecursionError. except Exception: # don't suggest to enable tracemalloc if it's not available - tracing = True + suggest_tracemalloc = False tb = None else: - tracing = tracemalloc.is_tracing() try: + suggest_tracemalloc = not tracemalloc.is_tracing() tb = tracemalloc.get_object_traceback(msg.source) except Exception: # When a warning is logged during Python shutdown, tracemalloc # and the import machinery don't work anymore + suggest_tracemalloc = False tb = None if tb is not None: @@ -85,7 +86,7 @@ def _formatwarnmsg_impl(msg): if line: line = line.strip() s += ' %s\n' % line - elif not tracing: + elif suggest_tracemalloc: s += (f'{category}: Enable tracemalloc to get the object ' f'allocation traceback\n') return s @@ -139,14 +140,18 @@ def filterwarnings(action, message="", category=Warning, module="", lineno=0, 'lineno' -- an integer line number, 0 matches all warnings 'append' -- if true, append to the list of filters """ - assert action in ("error", "ignore", "always", "default", "module", - "once"), "invalid action: %r" % (action,) - assert isinstance(message, str), "message must be a string" - assert isinstance(category, type), "category must be a class" - assert issubclass(category, Warning), "category must be a Warning subclass" - assert isinstance(module, str), "module must be a string" - assert isinstance(lineno, int) and lineno >= 0, \ - "lineno must be an int >= 0" + if action not in {"error", "ignore", "always", "default", "module", "once"}: + raise ValueError(f"invalid action: {action!r}") + if not isinstance(message, str): + raise TypeError("message must be a string") + if not isinstance(category, type) or not issubclass(category, Warning): + raise TypeError("category must be a Warning subclass") + if not isinstance(module, str): + raise TypeError("module must be a string") + if not isinstance(lineno, int): + raise TypeError("lineno must be an int") + if lineno < 0: + raise ValueError("lineno must be an int >= 0") if message or module: import re @@ -172,10 +177,12 @@ def simplefilter(action, category=Warning, lineno=0, append=False): 'lineno' -- an integer line number, 0 matches all warnings 'append' -- if true, append to the list of filters """ - assert action in ("error", "ignore", "always", "default", "module", - "once"), "invalid action: %r" % (action,) - assert isinstance(lineno, int) and lineno >= 0, \ - "lineno must be an int >= 0" + if action not in {"error", "ignore", "always", "default", "module", "once"}: + raise ValueError(f"invalid action: {action!r}") + if not isinstance(lineno, int): + raise TypeError("lineno must be an int") + if lineno < 0: + raise ValueError("lineno must be an int >= 0") _add_filter(action, None, category, None, lineno, append=append) def _add_filter(*item, append): @@ -508,6 +515,135 @@ def __exit__(self, *exc_info): self._module._showwarnmsg_impl = self._showwarnmsg_impl +class deprecated: + """Indicate that a class, function or overload is deprecated. + + When this decorator is applied to an object, the type checker + will generate a diagnostic on usage of the deprecated object. + + Usage: + + @deprecated("Use B instead") + class A: + pass + + @deprecated("Use g instead") + def f(): + pass + + @overload + @deprecated("int support is deprecated") + def g(x: int) -> int: ... + @overload + def g(x: str) -> int: ... + + The warning specified by *category* will be emitted at runtime + on use of deprecated objects. For functions, that happens on calls; + for classes, on instantiation and on creation of subclasses. + If the *category* is ``None``, no warning is emitted at runtime. + The *stacklevel* determines where the + warning is emitted. If it is ``1`` (the default), the warning + is emitted at the direct caller of the deprecated object; if it + is higher, it is emitted further up the stack. + Static type checker behavior is not affected by the *category* + and *stacklevel* arguments. + + The deprecation message passed to the decorator is saved in the + ``__deprecated__`` attribute on the decorated object. + If applied to an overload, the decorator + must be after the ``@overload`` decorator for the attribute to + exist on the overload as returned by ``get_overloads()``. + + See PEP 702 for details. + + """ + def __init__( + self, + message: str, + /, + *, + category: type[Warning] | None = DeprecationWarning, + stacklevel: int = 1, + ) -> None: + if not isinstance(message, str): + raise TypeError( + f"Expected an object of type str for 'message', not {type(message).__name__!r}" + ) + self.message = message + self.category = category + self.stacklevel = stacklevel + + def __call__(self, arg, /): + # Make sure the inner functions created below don't + # retain a reference to self. + msg = self.message + category = self.category + stacklevel = self.stacklevel + if category is None: + arg.__deprecated__ = msg + return arg + elif isinstance(arg, type): + import functools + from types import MethodType + + original_new = arg.__new__ + + @functools.wraps(original_new) + def __new__(cls, *args, **kwargs): + if cls is arg: + warn(msg, category=category, stacklevel=stacklevel + 1) + if original_new is not object.__new__: + return original_new(cls, *args, **kwargs) + # Mirrors a similar check in object.__new__. + elif cls.__init__ is object.__init__ and (args or kwargs): + raise TypeError(f"{cls.__name__}() takes no arguments") + else: + return original_new(cls) + + arg.__new__ = staticmethod(__new__) + + original_init_subclass = arg.__init_subclass__ + # We need slightly different behavior if __init_subclass__ + # is a bound method (likely if it was implemented in Python) + if isinstance(original_init_subclass, MethodType): + original_init_subclass = original_init_subclass.__func__ + + @functools.wraps(original_init_subclass) + def __init_subclass__(*args, **kwargs): + warn(msg, category=category, stacklevel=stacklevel + 1) + return original_init_subclass(*args, **kwargs) + + arg.__init_subclass__ = classmethod(__init_subclass__) + # Or otherwise, which likely means it's a builtin such as + # object's implementation of __init_subclass__. + else: + @functools.wraps(original_init_subclass) + def __init_subclass__(*args, **kwargs): + warn(msg, category=category, stacklevel=stacklevel + 1) + return original_init_subclass(*args, **kwargs) + + arg.__init_subclass__ = __init_subclass__ + + arg.__deprecated__ = __new__.__deprecated__ = msg + __init_subclass__.__deprecated__ = msg + return arg + elif callable(arg): + import functools + + @functools.wraps(arg) + def wrapper(*args, **kwargs): + warn(msg, category=category, stacklevel=stacklevel + 1) + return arg(*args, **kwargs) + + arg.__deprecated__ = wrapper.__deprecated__ = msg + return wrapper + else: + raise TypeError( + "@deprecated decorator with non-None category must be applied to " + f"a class or callable, not {arg!r}" + ) + + _DEPRECATED_MSG = "{name!r} is deprecated and slated for removal in Python {remove}" def _deprecated(name, message=_DEPRECATED_MSG, *, remove, _version=sys.version_info): diff --git a/Lib/webbrowser.py b/Lib/webbrowser.py index 8b0628745c57fc..636e8ca459d109 100755 --- a/Lib/webbrowser.py +++ b/Lib/webbrowser.py @@ -495,7 +495,12 @@ def register_standard_browsers(): register("microsoft-edge", None, Edge("MicrosoftEdge.exe")) else: # Prefer X browsers if present - if os.environ.get("DISPLAY") or os.environ.get("WAYLAND_DISPLAY"): + # + # NOTE: Do not check for X11 browser on macOS, + # XQuartz installation sets a DISPLAY environment variable and will + # autostart when someone tries to access the display. Mac users in + # general don't need an X11 browser. + if sys.platform != "darwin" and (os.environ.get("DISPLAY") or os.environ.get("WAYLAND_DISPLAY")): try: cmd = "xdg-settings get default-web-browser".split() raw_result = subprocess.check_output(cmd, stderr=subprocess.DEVNULL) @@ -569,6 +574,7 @@ def __init__(self, name='default'): super().__init__(name) def open(self, url, new=0, autoraise=True): + sys.audit("webbrowser.open", url) if self.name == 'default': script = 'open location "%s"' % url.replace('"', '%22') # opens in default browser else: diff --git a/Lib/wsgiref/simple_server.py b/Lib/wsgiref/simple_server.py index 93d01a863adf59..a0f2397fcf0006 100644 --- a/Lib/wsgiref/simple_server.py +++ b/Lib/wsgiref/simple_server.py @@ -84,10 +84,6 @@ def get_environ(self): env['PATH_INFO'] = urllib.parse.unquote(path, 'iso-8859-1') env['QUERY_STRING'] = query - - host = self.address_string() - if host != self.client_address[0]: - env['REMOTE_HOST'] = host env['REMOTE_ADDR'] = self.client_address[0] if self.headers.get('content-type') is None: diff --git a/Lib/wsgiref/util.py b/Lib/wsgiref/util.py index cbbe094cba1624..63b923317373f5 100644 --- a/Lib/wsgiref/util.py +++ b/Lib/wsgiref/util.py @@ -4,7 +4,7 @@ __all__ = [ 'FileWrapper', 'guess_scheme', 'application_uri', 'request_uri', - 'shift_path_info', 'setup_testing_defaults', + 'shift_path_info', 'setup_testing_defaults', 'is_hop_by_hop', ] diff --git a/Lib/xml/dom/minidom.py b/Lib/xml/dom/minidom.py index ef8a159833bbc0..db51f350ea0153 100644 --- a/Lib/xml/dom/minidom.py +++ b/Lib/xml/dom/minidom.py @@ -300,12 +300,28 @@ def _in_document(node): node = node.parentNode return False -def _write_data(writer, data): +def _write_data(writer, text, attr): "Writes datachars to writer." - if data: - data = data.replace("&", "&").replace("<", "<"). \ - replace("\"", """).replace(">", ">") - writer.write(data) + if not text: + return + # See the comments in ElementTree.py for behavior and + # implementation details. + if "&" in text: + text = text.replace("&", "&") + if "<" in text: + text = text.replace("<", "<") + if ">" in text: + text = text.replace(">", ">") + if attr: + if '"' in text: + text = text.replace('"', """) + if "\r" in text: + text = text.replace("\r", " ") + if "\n" in text: + text = text.replace("\n", " ") + if "\t" in text: + text = text.replace("\t", " ") + writer.write(text) def _get_elements_by_tagName_helper(parent, name, rc): for node in parent.childNodes: @@ -883,7 +899,7 @@ def writexml(self, writer, indent="", addindent="", newl=""): for a_name in attrs.keys(): writer.write(" %s=\"" % a_name) - _write_data(writer, attrs[a_name].value) + _write_data(writer, attrs[a_name].value, True) writer.write("\"") if self.childNodes: writer.write(">") @@ -1112,7 +1128,7 @@ def splitText(self, offset): return newText def writexml(self, writer, indent="", addindent="", newl=""): - _write_data(writer, "%s%s%s" % (indent, self.data, newl)) + _write_data(writer, "%s%s%s" % (indent, self.data, newl), False) # DOM Level 3 (WD 9 April 2002) diff --git a/Lib/zipfile/__init__.py b/Lib/zipfile/__init__.py index 9fc1840ba1e534..1d8a607fc728c8 100644 --- a/Lib/zipfile/__init__.py +++ b/Lib/zipfile/__init__.py @@ -188,28 +188,42 @@ class LargeZipFile(Exception): _DD_SIGNATURE = 0x08074b50 -_EXTRA_FIELD_STRUCT = struct.Struct('= 0 and buff_offset < len(self._readbuffer): + # Just move the _offset index if the new position is in the _readbuffer + self._offset = buff_offset + read_offset = 0 # Fast seek uncompressed unencrypted file - if self._compress_type == ZIP_STORED and self._decrypter is None and read_offset > 0: + elif self._compress_type == ZIP_STORED and self._decrypter is None and read_offset > 0: # disable CRC checking after first seeking - it would be invalid self._expected_crc = None # seek actual file taking already buffered data into account @@ -1133,10 +1154,6 @@ def seek(self, offset, whence=os.SEEK_SET): # flush read buffer self._readbuffer = b'' self._offset = 0 - elif buff_offset >= 0 and buff_offset < len(self._readbuffer): - # Just move the _offset index if the new position is in the _readbuffer - self._offset = buff_offset - read_offset = 0 elif read_offset < 0: # Position is before the current position. Reset the ZipExtFile self._fileobj.seek(self._orig_compress_start) @@ -1473,6 +1490,12 @@ def _RealGetContents(self): if self.debug > 2: print("total", total) + end_offset = self.start_dir + for zinfo in sorted(self.filelist, + key=lambda zinfo: zinfo.header_offset, + reverse=True): + zinfo._end_offset = end_offset + end_offset = zinfo.header_offset def namelist(self): """Return a list of file names in the archive.""" @@ -1629,6 +1652,10 @@ def open(self, name, mode="r", pwd=None, *, force_zip64=False): 'File name in directory %r and header %r differ.' % (zinfo.orig_filename, fname)) + if (zinfo._end_offset is not None and + zef_file.tell() + zinfo.compress_size > zinfo._end_offset): + raise BadZipFile(f"Overlapped entries: {zinfo.orig_filename!r} (possible zip bomb)") + # check for encrypted flag & handle password is_encrypted = zinfo.flag_bits & _MASK_ENCRYPTED if is_encrypted: @@ -1757,7 +1784,7 @@ def _extract_member(self, member, targetpath, pwd): # filter illegal characters on Windows arcname = self._sanitize_windows_name(arcname, os.path.sep) - if not arcname: + if not arcname and not member.is_dir(): raise ValueError("Empty filename.") targetpath = os.path.join(targetpath, arcname) @@ -1963,7 +1990,7 @@ def _write_end_record(self): min_version = 0 if extra: # Append a ZIP64 field to the extra's - extra_data = _strip_extra(extra_data, (1,)) + extra_data = _Extra.strip(extra_data, (1,)) extra_data = struct.pack( '', ''), + help='Extract zipfile into target dir') + group.add_argument('-c', '--create', nargs='+', + metavar=('', ''), + help='Create zipfile from sources') + group.add_argument('-t', '--test', metavar='', + help='Test if a zipfile is valid') + parser.add_argument('--metadata-encoding', metavar='', + help='Specify encoding of member names for -l, -e and -t') + args = parser.parse_args(args) + + encoding = args.metadata_encoding + + if args.test is not None: + src = args.test + with ZipFile(src, 'r', metadata_encoding=encoding) as zf: + badfile = zf.testzip() + if badfile: + print("The following enclosed file is corrupted: {!r}".format(badfile)) + print("Done testing") + + elif args.list is not None: + src = args.list + with ZipFile(src, 'r', metadata_encoding=encoding) as zf: + zf.printdir() + + elif args.extract is not None: + src, curdir = args.extract + with ZipFile(src, 'r', metadata_encoding=encoding) as zf: + zf.extractall(curdir) + + elif args.create is not None: + if encoding: + print("Non-conforming encodings not supported with -c.", + file=sys.stderr) + sys.exit(1) + + zip_name = args.create.pop(0) + files = args.create + + def addToZip(zf, path, zippath): + if os.path.isfile(path): + zf.write(path, zippath, ZIP_DEFLATED) + elif os.path.isdir(path): + if zippath: + zf.write(path, zippath) + for nm in sorted(os.listdir(path)): + addToZip(zf, + os.path.join(path, nm), os.path.join(zippath, nm)) + # else: ignore + + with ZipFile(zip_name, 'w') as zf: + for path in files: + zippath = os.path.basename(path) + if not zippath: + zippath = os.path.basename(os.path.dirname(path)) + if zippath in ('', os.curdir, os.pardir): + zippath = '' + addToZip(zf, path, zippath) + + from ._path import ( # noqa: E402 Path, # used privately for tests CompleteDirs, # noqa: F401 ) - -# used privately for tests -from .__main__ import main # noqa: F401, E402 diff --git a/Lib/zipfile/__main__.py b/Lib/zipfile/__main__.py index a9e5fb1b8d72c4..868d99efc3c4a3 100644 --- a/Lib/zipfile/__main__.py +++ b/Lib/zipfile/__main__.py @@ -1,77 +1,4 @@ -import sys -import os -from . import ZipFile, ZIP_DEFLATED - - -def main(args=None): - import argparse - - description = 'A simple command-line interface for zipfile module.' - parser = argparse.ArgumentParser(description=description) - group = parser.add_mutually_exclusive_group(required=True) - group.add_argument('-l', '--list', metavar='', - help='Show listing of a zipfile') - group.add_argument('-e', '--extract', nargs=2, - metavar=('', ''), - help='Extract zipfile into target dir') - group.add_argument('-c', '--create', nargs='+', - metavar=('', ''), - help='Create zipfile from sources') - group.add_argument('-t', '--test', metavar='', - help='Test if a zipfile is valid') - parser.add_argument('--metadata-encoding', metavar='', - help='Specify encoding of member names for -l, -e and -t') - args = parser.parse_args(args) - - encoding = args.metadata_encoding - - if args.test is not None: - src = args.test - with ZipFile(src, 'r', metadata_encoding=encoding) as zf: - badfile = zf.testzip() - if badfile: - print("The following enclosed file is corrupted: {!r}".format(badfile)) - print("Done testing") - - elif args.list is not None: - src = args.list - with ZipFile(src, 'r', metadata_encoding=encoding) as zf: - zf.printdir() - - elif args.extract is not None: - src, curdir = args.extract - with ZipFile(src, 'r', metadata_encoding=encoding) as zf: - zf.extractall(curdir) - - elif args.create is not None: - if encoding: - print("Non-conforming encodings not supported with -c.", - file=sys.stderr) - sys.exit(1) - - zip_name = args.create.pop(0) - files = args.create - - def addToZip(zf, path, zippath): - if os.path.isfile(path): - zf.write(path, zippath, ZIP_DEFLATED) - elif os.path.isdir(path): - if zippath: - zf.write(path, zippath) - for nm in sorted(os.listdir(path)): - addToZip(zf, - os.path.join(path, nm), os.path.join(zippath, nm)) - # else: ignore - - with ZipFile(zip_name, 'w') as zf: - for path in files: - zippath = os.path.basename(path) - if not zippath: - zippath = os.path.basename(os.path.dirname(path)) - if zippath in ('', os.curdir, os.pardir): - zippath = '' - addToZip(zf, path, zippath) - +from . import main if __name__ == "__main__": main() diff --git a/Lib/zipimport.py b/Lib/zipimport.py index 5b9f614f02f7af..823a82ee830465 100644 --- a/Lib/zipimport.py +++ b/Lib/zipimport.py @@ -352,7 +352,7 @@ def _read_directory(archive): with fp: # GH-87235: On macOS all file descriptors for /dev/fd/N share the same - # file offset, reset the file offset after scanning the zipfile diretory + # file offset, reset the file offset after scanning the zipfile directory # to not cause problems when some runs 'python3 /dev/fd/9 9[^<0-9:.+-]+|<[a-zA-Z0-9+\-]+>)" + - r"((?P[+-]?\d{1,2}(:\d{2}(:\d{2})?)?)" + - r"((?P[^0-9:.+-]+|<[a-zA-Z0-9+\-]+>)" + - r"((?P[+-]?\d{1,2}(:\d{2}(:\d{2})?)?))?" + - r")?" + # dst - r")?$" # stdoff + r""" + (?P[^<0-9:.+-]+|<[a-zA-Z0-9+-]+>) + (?: + (?P[+-]?\d{1,3}(?::\d{2}(?::\d{2})?)?) + (?: + (?P[^0-9:.+-]+|<[a-zA-Z0-9+-]+>) + (?P[+-]?\d{1,3}(?::\d{2}(?::\d{2})?)?)? + )? # dst + )? # stdoff + """, + re.ASCII|re.VERBOSE ) - # fmt: on - m = parser_re.match(offset_str) + m = parser_re.fullmatch(offset_str) if m is None: raise ValueError(f"{tz_str} is not a valid TZ string") @@ -696,16 +699,17 @@ def _parse_tz_str(tz_str): def _parse_dst_start_end(dststr): - date, *time = dststr.split("/") - if date[0] == "M": + date, *time = dststr.split("/", 1) + type = date[:1] + if type == "M": n_is_julian = False - m = re.match(r"M(\d{1,2})\.(\d).(\d)$", date) + m = re.fullmatch(r"M(\d{1,2})\.(\d).(\d)", date, re.ASCII) if m is None: raise ValueError(f"Invalid dst start/end date: {dststr}") date_offset = tuple(map(int, m.groups())) offset = _CalendarOffset(*date_offset) else: - if date[0] == "J": + if type == "J": n_is_julian = True date = date[1:] else: @@ -715,38 +719,54 @@ def _parse_dst_start_end(dststr): offset = _DayOffset(doy, n_is_julian) if time: - time_components = list(map(int, time[0].split(":"))) - n_components = len(time_components) - if n_components < 3: - time_components.extend([0] * (3 - n_components)) - offset.hour, offset.minute, offset.second = time_components + offset.hour, offset.minute, offset.second = _parse_transition_time(time[0]) return offset +def _parse_transition_time(time_str): + match = re.fullmatch( + r"(?P[+-])?(?P\d{1,3})(:(?P\d{2})(:(?P\d{2}))?)?", + time_str, + re.ASCII + ) + if match is None: + raise ValueError(f"Invalid time: {time_str}") + + h, m, s = (int(v or 0) for v in match.group("h", "m", "s")) + + if h > 167: + raise ValueError( + f"Hour must be in [0, 167]: {time_str}" + ) + + if match.group("sign") == "-": + h, m, s = -h, -m, -s + + return h, m, s + + def _parse_tz_delta(tz_delta): - match = re.match( - r"(?P[+-])?(?P\d{1,2})(:(?P\d{2})(:(?P\d{2}))?)?", + match = re.fullmatch( + r"(?P[+-])?(?P\d{1,3})(:(?P\d{2})(:(?P\d{2}))?)?", tz_delta, + re.ASCII ) # Anything passed to this function should already have hit an equivalent # regular expression to find the section to parse. assert match is not None, tz_delta - h, m, s = ( - int(v) if v is not None else 0 - for v in map(match.group, ("h", "m", "s")) - ) + h, m, s = (int(v or 0) for v in match.group("h", "m", "s")) total = h * 3600 + m * 60 + s - if not -86400 < total < 86400: + if h > 24: raise ValueError( - f"Offset must be strictly between -24h and +24h: {tz_delta}" + f"Offset hours must be in [0, 24]: {tz_delta}" ) # Yes, +5 maps to an offset of -5h if match.group("sign") != "-": - total *= -1 + total = -total return total diff --git a/Mac/BuildScript/backport_gh110950_fix.patch b/Mac/BuildScript/backport_gh110950_fix.patch new file mode 100644 index 00000000000000..793f5a78d8c6ab --- /dev/null +++ b/Mac/BuildScript/backport_gh110950_fix.patch @@ -0,0 +1,25 @@ +From https://core.tcl-lang.org/tk/info/ed7cfbac8db11aa0 + +Note: the diff here is hand-tweaked so that it applies cleanly to both Tk 8.6.8 and 8.6.13. + +diff --git a/macosx/tkMacOSXInit.c b/macosx/tkMacOSXInit.c +index 71d7c3385..e6a68356c 100644 +--- a/macosx/tkMacOSXInit.c ++++ b/macosx/tkMacOSXInit.c +@@ -128,6 +128,16 @@ static int TkMacOSXGetAppPathCmd(ClientData cd, Tcl_Interp *ip, + observe(NSApplicationDidChangeScreenParametersNotification, displayChanged:); + observe(NSTextInputContextKeyboardSelectionDidChangeNotification, keyboardChanged:); + #undef observe ++} ++ ++ ++/* ++ * Fix for 10b38a7a7c. ++ */ ++ ++- (BOOL)applicationSupportsSecureRestorableState:(NSApplication *)app ++{ ++ return YES; + } + + -(void)applicationWillFinishLaunching:(NSNotification *)aNotification diff --git a/Mac/BuildScript/backport_gh71383_fix.patch b/Mac/BuildScript/backport_gh71383_fix.patch new file mode 100644 index 00000000000000..d77b1045e8c165 --- /dev/null +++ b/Mac/BuildScript/backport_gh71383_fix.patch @@ -0,0 +1,89 @@ +Adapted from https://core.tcl-lang.org/tk/info/b1876b9ebc4b + +Index: generic/tkInt.h +================================================================== +--- a/generic/tkInt.h.orig ++++ b/generic/tkInt.h +@@ -1094,10 +1094,11 @@ + /* + * Themed widget set init function: + */ + + MODULE_SCOPE int Ttk_Init(Tcl_Interp *interp); ++MODULE_SCOPE void Ttk_TkDestroyedHandler(Tcl_Interp *interp); + + /* + * Internal functions shared among Tk modules but not exported to the outside + * world: + */ + +Index: generic/tkWindow.c +================================================================== +--- a/generic/tkWindow.c.orig ++++ b/generic/tkWindow.c +@@ -1619,10 +1619,11 @@ + TkBindFree(winPtr->mainPtr); + TkDeleteAllImages(winPtr->mainPtr); + TkFontPkgFree(winPtr->mainPtr); + TkFocusFree(winPtr->mainPtr); + TkStylePkgFree(winPtr->mainPtr); ++ Ttk_TkDestroyedHandler(winPtr->mainPtr->interp); + + /* + * When embedding Tk into other applications, make sure that all + * destroy events reach the server. Otherwise the embedding + * application may also attempt to destroy the windows, resulting + +Index: generic/ttk/ttkTheme.c +================================================================== +--- a/generic/ttk/ttkTheme.c.orig ++++ b/generic/ttk/ttkTheme.c +@@ -415,17 +415,10 @@ + StylePackageData *pkgPtr = (StylePackageData *)clientData; + Tcl_HashSearch search; + Tcl_HashEntry *entryPtr; + Cleanup *cleanup; + +- /* +- * Cancel any pending ThemeChanged calls: +- */ +- if (pkgPtr->themeChangePending) { +- Tcl_CancelIdleCall(ThemeChangedProc, pkgPtr); +- } +- + /* + * Free themes. + */ + entryPtr = Tcl_FirstHashEntry(&pkgPtr->themeTable, &search); + while (entryPtr != NULL) { +@@ -528,10 +521,29 @@ + if (!pkgPtr->themeChangePending) { + Tcl_DoWhenIdle(ThemeChangedProc, pkgPtr); + pkgPtr->themeChangePending = 1; + } + } ++ ++/* Ttk_TkDestroyedHandler -- ++ * See bug [310c74ecf440]: idle calls to ThemeChangedProc() ++ * need to be canceled when Tk is destroyed, since the interp ++ * may still be active afterward; canceling them from ++ * Ttk_StylePkgFree() would be too late. ++ */ ++void Ttk_TkDestroyedHandler( ++ Tcl_Interp* interp) ++{ ++ StylePackageData* pkgPtr = GetStylePackageData(interp); ++ ++ /* ++ * Cancel any pending ThemeChanged calls: ++ */ ++ if (pkgPtr->themeChangePending) { ++ Tcl_CancelIdleCall(ThemeChangedProc, pkgPtr); ++ } ++} + + /* + * Ttk_CreateTheme -- + * Create a new theme and register it in the global theme table. + * + diff --git a/Mac/BuildScript/backport_gh92603_fix.patch b/Mac/BuildScript/backport_gh92603_fix.patch new file mode 100644 index 00000000000000..9a37b029650340 --- /dev/null +++ b/Mac/BuildScript/backport_gh92603_fix.patch @@ -0,0 +1,82 @@ +Accepted upstream for release in Tk 8.6.14: +https://core.tcl-lang.org/tk/info/cf3830280b + +--- tk8.6.13/macosx/tkMacOSXWindowEvent.c.orig ++++ tk8.6.13-patched/macosx/tkMacOSXWindowEvent.c +@@ -239,8 +239,8 @@ extern NSString *NSWindowDidOrderOffScreenNotification; + if (winPtr) { + TKContentView *view = [window contentView]; + +-#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101500 +- if (@available(macOS 10.15, *)) { ++#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101400 ++ if (@available(macOS 10.14, *)) { + [view viewDidChangeEffectiveAppearance]; + } + #endif +@@ -1237,29 +1237,8 @@ static const char *const accentNames[] = { + } else if (effectiveAppearanceName == NSAppearanceNameDarkAqua) { + TkSendVirtualEvent(tkwin, "DarkAqua", NULL); + } +- if ([NSApp macOSVersion] < 101500) { +- +- /* +- * Mojave cannot handle the KVO shenanigans that we need for the +- * highlight and accent color notifications. +- */ +- +- return; +- } + if (!defaultColor) { + defaultColor = [NSApp macOSVersion] < 110000 ? "Blue" : "Multicolor"; +- preferences = [[NSUserDefaults standardUserDefaults] retain]; +- +- /* +- * AppKit calls this method when the user changes the Accent Color +- * but not when the user changes the Highlight Color. So we register +- * to receive KVO notifications for Highlight Color as well. +- */ +- +- [preferences addObserver:self +- forKeyPath:@"AppleHighlightColor" +- options:NSKeyValueObservingOptionNew +- context:NULL]; + } + NSString *accent = [preferences stringForKey:@"AppleAccentColor"]; + NSArray *words = [[preferences stringForKey:@"AppleHighlightColor"] +--- tk8.6.13/macosx/tkMacOSXWm.c.orig ++++ tk8.6.13-patched/macosx/tkMacOSXWm.c +@@ -1289,6 +1289,11 @@ TkWmDeadWindow( + [NSApp _setMainWindow:nil]; + } + [deadNSWindow close]; ++#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101400 ++ NSUserDefaults *preferences = [NSUserDefaults standardUserDefaults]; ++ [preferences removeObserver:deadNSWindow.contentView ++ forKeyPath:@"AppleHighlightColor"]; ++#endif + [deadNSWindow release]; + + #if DEBUG_ZOMBIES > 1 +@@ -6763,6 +6768,21 @@ TkMacOSXMakeRealWindowExist( + } + TKContentView *contentView = [[TKContentView alloc] + initWithFrame:NSZeroRect]; ++#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101400 ++ NSUserDefaults *preferences = [NSUserDefaults standardUserDefaults]; ++ ++ /* ++ * AppKit calls the viewDidChangeEffectiveAppearance method when the ++ * user changes the Accent Color but not when the user changes the ++ * Highlight Color. So we register to receive KVO notifications for ++ * Highlight Color as well. ++ */ ++ ++ [preferences addObserver:contentView ++ forKeyPath:@"AppleHighlightColor" ++ options:NSKeyValueObservingOptionNew ++ context:NULL]; ++#endif + [window setContentView:contentView]; + [contentView release]; + [window setDelegate:NSApp]; diff --git a/Mac/BuildScript/build-installer.py b/Mac/BuildScript/build-installer.py index 0fc25ec74565df..32de56bcf13086 100755 --- a/Mac/BuildScript/build-installer.py +++ b/Mac/BuildScript/build-installer.py @@ -246,9 +246,9 @@ def library_recipes(): result.extend([ dict( - name="OpenSSL 3.0.9", - url="https://www.openssl.org/source/openssl-3.0.9.tar.gz", - checksum='eb1ab04781474360f77c318ab89d8c5a03abc38e63d65a603cabbf1b00a1dc90', + name="OpenSSL 3.0.11", + url="https://www.openssl.org/source/openssl-3.0.11.tar.gz", + checksum='b3425d3bb4a2218d0697eb41f7fc0cdede016ed19ca49d168b78e8d947887f55', buildrecipe=build_universal_openssl, configure=None, install=None, @@ -261,14 +261,14 @@ def library_recipes(): tcl_checksum='81656d3367af032e0ae6157eff134f89' tk_checksum='5e0faecba458ee1386078fb228d008ba' - tk_patches = ['tk868_on_10_8_10_9.patch'] + tk_patches = ['backport_gh71383_fix.patch', 'tk868_on_10_8_10_9.patch', 'backport_gh110950_fix.patch'] else: tcl_tk_ver='8.6.13' tcl_checksum='43a1fae7412f61ff11de2cfd05d28cfc3a73762f354a417c62370a54e2caf066' tk_checksum='2e65fa069a23365440a3c56c556b8673b5e32a283800d8d9b257e3f584ce0675' - tk_patches = [ ] + tk_patches = ['backport_gh92603_fix.patch', 'backport_gh71383_fix.patch', 'backport_gh110950_fix.patch'] base_url = "https://prdownloads.sourceforge.net/tcl/{what}{version}-src.tar.gz" @@ -359,9 +359,9 @@ def library_recipes(): ), ), dict( - name="SQLite 3.42.0", - url="https://sqlite.org/2023/sqlite-autoconf-3420000.tar.gz", - checksum="0c5a92bc51cf07cae45b4a1e94653dea", + name="SQLite 3.44.2", + url="https://sqlite.org/2023/sqlite-autoconf-3440200.tar.gz", + checksum="c02f40fd4f809ced95096250adc5764a", extra_cflags=('-Os ' '-DSQLITE_ENABLE_FTS5 ' '-DSQLITE_ENABLE_FTS4 ' @@ -1147,7 +1147,9 @@ def buildPython(): # will find them during its extension import sanity checks. print("Running configure...") + print(" NOTE: --with-mimalloc=no pending resolution of weak linking issues") runCommand("%s -C --enable-framework --enable-universalsdk=/ " + "--with-mimalloc=no " "--with-universal-archs=%s " "%s " "%s " @@ -1490,7 +1492,7 @@ def packageFromRecipe(targetDir, recipe): IFPkgFlagRelocatable=False, IFPkgFlagRestartAction="NoRestart", IFPkgFlagRootVolumeOnly=True, - IFPkgFlagUpdateInstalledLangauges=False, + IFPkgFlagUpdateInstalledLanguages=False, ) writePlist(pl, os.path.join(packageContents, 'Info.plist')) diff --git a/Mac/IDLE/IDLE.app/Contents/Info.plist b/Mac/IDLE/IDLE.app/Contents/Info.plist index fea06d46324999..20b97b67f41d1a 100644 --- a/Mac/IDLE/IDLE.app/Contents/Info.plist +++ b/Mac/IDLE/IDLE.app/Contents/Info.plist @@ -56,5 +56,7 @@ %version% NSHighResolutionCapable + CFBundleAllowMixedLocalizations + diff --git a/Mac/Makefile.in b/Mac/Makefile.in index 78b4499cca986a..32e3a0f55c5d71 100644 --- a/Mac/Makefile.in +++ b/Mac/Makefile.in @@ -257,6 +257,8 @@ install_IDLE: rm "$(DESTDIR)$(LIBDEST)/idlelib/config-extensions.def~" ; \ fi touch "$(DESTDIR)$(PYTHONAPPSDIR)/IDLE.app" + chmod -R ugo+rX,go-w "$(DESTDIR)$(PYTHONAPPSDIR)/IDLE.app" + chmod ugo+x "$(DESTDIR)$(PYTHONAPPSDIR)/IDLE.app/Contents/MacOS/IDLE" $(INSTALLED_PYTHONAPP): install_Python diff --git a/Mac/PythonLauncher/Makefile.in b/Mac/PythonLauncher/Makefile.in index 4c05f26e8358bc..9decadbdc60f00 100644 --- a/Mac/PythonLauncher/Makefile.in +++ b/Mac/PythonLauncher/Makefile.in @@ -27,6 +27,8 @@ install: Python\ Launcher.app -test -d "$(DESTDIR)$(PYTHONAPPSDIR)/Python Launcher.app" && rm -r "$(DESTDIR)$(PYTHONAPPSDIR)/Python Launcher.app" /bin/cp -r "Python Launcher.app" "$(DESTDIR)$(PYTHONAPPSDIR)" touch "$(DESTDIR)$(PYTHONAPPSDIR)/Python Launcher.app" + chmod -R ugo+rX,go-w "$(DESTDIR)$(PYTHONAPPSDIR)/Python Launcher.app" + chmod ugo+x "$(DESTDIR)$(PYTHONAPPSDIR)/Python Launcher.app/Contents/MacOS/Python Launcher" clean: rm -f *.o "Python Launcher" diff --git a/Mac/Resources/app/Info.plist.in b/Mac/Resources/app/Info.plist.in index 4ec828ff176e7b..8362b19b361b62 100644 --- a/Mac/Resources/app/Info.plist.in +++ b/Mac/Resources/app/Info.plist.in @@ -58,5 +58,7 @@ (c) 2001-2023 Python Software Foundation. NSHighResolutionCapable + CFBundleAllowMixedLocalizations + diff --git a/Mac/Resources/framework/Info.plist.in b/Mac/Resources/framework/Info.plist.in index e131c205ef0b28..238441ce2c76c7 100644 --- a/Mac/Resources/framework/Info.plist.in +++ b/Mac/Resources/framework/Info.plist.in @@ -24,5 +24,7 @@ ???? CFBundleVersion %VERSION% + CFBundleAllowMixedLocalizations + diff --git a/Makefile.pre.in b/Makefile.pre.in index 12409774746a30..15d419b930c181 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -100,7 +100,7 @@ CONFIGURE_LDFLAGS= @LDFLAGS@ # command line to append to these values without stomping the pre-set # values. PY_CFLAGS= $(BASECFLAGS) $(OPT) $(CONFIGURE_CFLAGS) $(CFLAGS) $(EXTRA_CFLAGS) -PY_CFLAGS_NODIST=$(CONFIGURE_CFLAGS_NODIST) $(CFLAGS_NODIST) -I$(srcdir)/Include/internal +PY_CFLAGS_NODIST=$(CONFIGURE_CFLAGS_NODIST) $(CFLAGS_NODIST) -I$(srcdir)/Include/internal -I$(srcdir)/Include/internal/mimalloc # Both CPPFLAGS and LDFLAGS need to contain the shell's value for setup.py to # be able to build extension modules using the directories specified in the # environment variables @@ -336,6 +336,20 @@ IO_OBJS= \ Modules/_io/bytesio.o \ Modules/_io/stringio.o + +########################################################################## +# mimalloc + +MIMALLOC_HEADERS= \ + $(srcdir)/Include/internal/pycore_mimalloc.h \ + $(srcdir)/Include/internal/mimalloc/mimalloc.h \ + $(srcdir)/Include/internal/mimalloc/mimalloc/atomic.h \ + $(srcdir)/Include/internal/mimalloc/mimalloc/internal.h \ + $(srcdir)/Include/internal/mimalloc/mimalloc/prim.h \ + $(srcdir)/Include/internal/mimalloc/mimalloc/track.h \ + $(srcdir)/Include/internal/mimalloc/mimalloc/types.h + + ########################################################################## # Parser @@ -347,20 +361,36 @@ PEGEN_OBJS= \ Parser/string_parser.o \ Parser/peg_api.o +TOKENIZER_OBJS= \ + Parser/lexer/buffer.o \ + Parser/lexer/lexer.o \ + Parser/lexer/state.o \ + Parser/tokenizer/file_tokenizer.o \ + Parser/tokenizer/readline_tokenizer.o \ + Parser/tokenizer/string_tokenizer.o \ + Parser/tokenizer/utf8_tokenizer.o \ + Parser/tokenizer/helpers.o PEGEN_HEADERS= \ $(srcdir)/Include/internal/pycore_parser.h \ $(srcdir)/Parser/pegen.h \ $(srcdir)/Parser/string_parser.h +TOKENIZER_HEADERS= \ + Parser/lexer/buffer.h \ + Parser/lexer/lexer.h \ + Parser/lexer/state.h \ + Parser/tokenizer/tokenizer.h \ + Parser/tokenizer/helpers.h + POBJS= \ Parser/token.o \ -PARSER_OBJS= $(POBJS) $(PEGEN_OBJS) Parser/myreadline.o Parser/tokenizer.o +PARSER_OBJS= $(POBJS) $(PEGEN_OBJS) $(TOKENIZER_OBJS) Parser/myreadline.o PARSER_HEADERS= \ $(PEGEN_HEADERS) \ - $(srcdir)/Parser/tokenizer.h + $(TOKENIZER_HEADERS) ########################################################################## # Python @@ -379,13 +409,17 @@ PYTHON_OBJS= \ Python/codecs.o \ Python/compile.o \ Python/context.o \ + Python/critical_section.o \ + Python/crossinterp.o \ Python/dynamic_annotations.o \ Python/errors.o \ - Python/executor.o \ Python/flowgraph.o \ Python/frame.o \ Python/frozenmain.o \ Python/future.o \ + Python/gc.o \ + Python/gc_free_threading.o \ + Python/gc_gil.o \ Python/getargs.o \ Python/getcompiler.o \ Python/getcopyright.o \ @@ -400,11 +434,14 @@ PYTHON_OBJS= \ Python/instrumentation.o \ Python/intrinsics.o \ Python/legacy_tracing.o \ + Python/lock.o \ Python/marshal.o \ Python/modsupport.o \ Python/mysnprintf.o \ Python/mystrtoul.o \ Python/optimizer.o \ + Python/optimizer_analysis.o \ + Python/parking_lot.o \ Python/pathconfig.o \ Python/preconfig.o \ Python/pyarena.o \ @@ -489,8 +526,6 @@ OBJECT_OBJS= \ Objects/weakrefobject.o \ @PERF_TRAMPOLINE_OBJ@ -DEEPFREEZE_OBJS = Python/deepfreeze/deepfreeze.o - ########################################################################## # objects that get linked into the Python library LIBRARY_OBJS_OMIT_FROZEN= \ @@ -503,7 +538,6 @@ LIBRARY_OBJS_OMIT_FROZEN= \ LIBRARY_OBJS= \ $(LIBRARY_OBJS_OMIT_FROZEN) \ - $(DEEPFREEZE_OBJS) \ Modules/getpath.o \ Python/frozen.o @@ -515,7 +549,7 @@ LINK_PYTHON_OBJS=@LINK_PYTHON_OBJS@ # On some systems, object files that reference DTrace probes need to be modified # in-place by dtrace(1). DTRACE_DEPS = \ - Python/ceval.o Python/import.o Python/sysmodule.o Modules/gcmodule.o + Python/ceval.o Python/gc.o Python/import.o Python/sysmodule.o ########################################################################## # decimal's libmpdec @@ -624,12 +658,15 @@ build_wasm: check-clean-src $(BUILDPYTHON) platform sharedmods \ .PHONY: check-clean-src check-clean-src: @if test -n "$(VPATH)" -a \( \ - -f "$(srcdir)/Programs/python.o" \ - -o -f "$(srcdir)\Python/frozen_modules/importlib._bootstrap.h" \ + -f "$(srcdir)/$(BUILDPYTHON)" \ + -o -f "$(srcdir)/Programs/python.o" \ + -o -f "$(srcdir)/Python/frozen_modules/importlib._bootstrap.h" \ \); then \ echo "Error: The source directory ($(srcdir)) is not clean" ; \ echo "Building Python out of the source tree (in $(abs_builddir)) requires a clean source tree ($(abs_srcdir))" ; \ - echo "Try to run: make -C \"$(srcdir)\" clean" ; \ + echo "Build artifacts such as .o files, executables, and Python/frozen_modules/*.h must not exist within $(srcdir)." ; \ + echo "Try to run:" ; \ + echo " (cd \"$(srcdir)\" && make clean || git clean -fdx -e Doc/venv)" ; \ exit 1; \ fi @@ -657,7 +694,7 @@ profile-run-stamp: $(MAKE) profile-gen-stamp # Next, run the profile task to generate the profile information. @ # FIXME: can't run for a cross build - $(LLVM_PROF_FILE) $(RUNSHARED) ./$(BUILDPYTHON) $(PROFILE_TASK) || true + $(LLVM_PROF_FILE) $(RUNSHARED) ./$(BUILDPYTHON) $(PROFILE_TASK) $(LLVM_PROF_MERGER) # Remove profile generation binary since we are done with it. $(MAKE) clean-retain-profile @@ -706,7 +743,7 @@ profile-bolt-stamp: $(BUILDPYTHON) mv "$${bin}.bolt_inst" "$${bin}"; \ done # Run instrumented binaries to collect data. - $(RUNSHARED) ./$(BUILDPYTHON) $(PROFILE_TASK) || true + $(RUNSHARED) ./$(BUILDPYTHON) $(PROFILE_TASK) # Merge all the data files together. for bin in $(BOLT_BINARIES); do \ @MERGE_FDATA@ $${bin}.*.fdata > "$${bin}.fdata"; \ @@ -768,15 +805,18 @@ coverage-report: regen-token regen-frozen @ # build with coverage info $(MAKE) coverage @ # run tests, ignore failures - $(TESTRUNNER) $(TESTOPTS) || true + $(TESTRUNNER) --fast-ci --timeout=$(TESTTIMEOUT) $(TESTOPTS) || true @ # build lcov report $(MAKE) coverage-lcov # Run "Argument Clinic" over all source files .PHONY: clinic clinic: check-clean-src $(srcdir)/Modules/_blake2/blake2s_impl.c - $(PYTHON_FOR_REGEN) $(srcdir)/Tools/clinic/clinic.py --make --srcdir $(srcdir) - $(PYTHON_FOR_REGEN) $(srcdir)/Tools/build/generate_global_objects.py + $(PYTHON_FOR_REGEN) $(srcdir)/Tools/clinic/clinic.py --make --exclude Lib/test/clinic.test.c --srcdir $(srcdir) + +.PHONY: clinic-tests +clinic-tests: check-clean-src $(srcdir)/Lib/test/clinic.test.c + $(PYTHON_FOR_REGEN) $(srcdir)/Tools/clinic/clinic.py -f $(srcdir)/Lib/test/clinic.test.c # Build the interpreter $(BUILDPYTHON): Programs/python.o $(LINK_PYTHON_DEPS) @@ -1246,13 +1286,11 @@ regen-frozen: Tools/build/freeze_modules.py $(FROZEN_FILES_IN) ############################################################################ # Deepfreeze targets -.PHONY: regen-deepfreeze -regen-deepfreeze: $(DEEPFREEZE_OBJS) - -DEEPFREEZE_DEPS=$(srcdir)/Tools/build/deepfreeze.py $(FREEZE_MODULE_DEPS) $(FROZEN_FILES_OUT) +DEEPFREEZE_C = Python/deepfreeze/deepfreeze.c +DEEPFREEZE_DEPS=$(srcdir)/Tools/build/deepfreeze.py Include/internal/pycore_global_strings.h $(FREEZE_MODULE_DEPS) $(FROZEN_FILES_OUT) # BEGIN: deepfreeze modules -Python/deepfreeze/deepfreeze.c: $(DEEPFREEZE_DEPS) +$(DEEPFREEZE_C): $(DEEPFREEZE_DEPS) $(PYTHON_FOR_FREEZE) $(srcdir)/Tools/build/deepfreeze.py \ Python/frozen_modules/importlib._bootstrap.h:importlib._bootstrap \ Python/frozen_modules/importlib._bootstrap_external.h:importlib._bootstrap_external \ @@ -1279,8 +1317,6 @@ Python/deepfreeze/deepfreeze.c: $(DEEPFREEZE_DEPS) Python/frozen_modules/frozen_only.h:frozen_only \ -o Python/deepfreeze/deepfreeze.c # END: deepfreeze modules - @echo "Note: Deepfreeze may have added some global objects," - @echo " so run 'make regen-global-objects' if necessary." # We keep this renamed target around for folks with muscle memory. .PHONY: regen-importlib @@ -1289,11 +1325,11 @@ regen-importlib: regen-frozen ############################################################################ # Global objects +# Dependencies which can add and/or remove _Py_ID() identifiers: +# - "make clinic" .PHONY: regen-global-objects -regen-global-objects: $(srcdir)/Tools/build/generate_global_objects.py +regen-global-objects: $(srcdir)/Tools/build/generate_global_objects.py clinic $(PYTHON_FOR_REGEN) $(srcdir)/Tools/build/generate_global_objects.py - @echo "Note: Global objects can be added or removed by other tools (e.g. deepfreeze), " - @echo " so be sure to re-run regen-global-objects after those tools." ############################################################################ # ABI @@ -1312,17 +1348,26 @@ check-abidump: all regen-limited-abi: all $(RUNSHARED) ./$(BUILDPYTHON) $(srcdir)/Tools/build/stable_abi.py --generate-all $(srcdir)/Misc/stable_abi.toml +############################################################################ +# Regenerate Unicode Data + +.PHONY: regen-unicodedata +regen-unicodedata: + $(PYTHON_FOR_REGEN) $(srcdir)/Tools/unicode/makeunicodedata.py + + ############################################################################ # Regenerate all generated files +# "clinic" is regenerated implicitly via "regen-global-objects". .PHONY: regen-all -regen-all: regen-cases regen-opcode regen-typeslots \ - regen-token regen-ast regen-keyword regen-sre regen-frozen clinic \ +regen-all: regen-cases regen-typeslots \ + regen-token regen-ast regen-keyword regen-sre regen-frozen \ regen-pegen-metaparser regen-pegen regen-test-frozenmain \ - regen-test-levenshtein regen-global-objects + regen-test-levenshtein regen-global-objects regen-sbom @echo - @echo "Note: make regen-stdlib-module-names, make regen-limited-abi" - @echo "and make regen-configure should be run manually" + @echo "Note: make regen-stdlib-module-names, make regen-limited-abi, " + @echo "make regen-configure and make regen-unicodedata should be run manually" ############################################################################ # Special rules for object files @@ -1396,11 +1441,13 @@ regen-pegen-metaparser: .PHONY: regen-pegen regen-pegen: @$(MKDIR_P) $(srcdir)/Parser + @$(MKDIR_P) $(srcdir)/Parser/tokenizer + @$(MKDIR_P) $(srcdir)/Parser/lexer PYTHONPATH=$(srcdir)/Tools/peg_generator $(PYTHON_FOR_REGEN) -m pegen -q c \ $(srcdir)/Grammar/python.gram \ $(srcdir)/Grammar/Tokens \ - -o $(srcdir)/Parser/parser.new.c - $(UPDATE_FILE) $(srcdir)/Parser/parser.c $(srcdir)/Parser/parser.new.c + -o $(srcdir)/Parser/parser.c.new + $(UPDATE_FILE) $(srcdir)/Parser/parser.c $(srcdir)/Parser/parser.c.new .PHONY: regen-ast regen-ast: @@ -1420,20 +1467,6 @@ regen-ast: $(UPDATE_FILE) $(srcdir)/Include/internal/pycore_ast_state.h $(srcdir)/Include/internal/pycore_ast_state.h.new $(UPDATE_FILE) $(srcdir)/Python/Python-ast.c $(srcdir)/Python/Python-ast.c.new -.PHONY: regen-opcode -regen-opcode: - # Regenerate Include/opcode.h from Lib/opcode.py - # using Tools/build/generate_opcode_h.py - $(PYTHON_FOR_REGEN) $(srcdir)/Tools/build/generate_opcode_h.py \ - $(srcdir)/Lib/opcode.py \ - $(srcdir)/Lib/_opcode_metadata.py \ - $(srcdir)/Include/opcode.h.new \ - $(srcdir)/Python/opcode_targets.h.new \ - $(srcdir)/Include/internal/pycore_opcode.h.new - $(UPDATE_FILE) $(srcdir)/Include/opcode.h $(srcdir)/Include/opcode.h.new - $(UPDATE_FILE) $(srcdir)/Python/opcode_targets.h $(srcdir)/Python/opcode_targets.h.new - $(UPDATE_FILE) $(srcdir)/Include/internal/pycore_opcode.h $(srcdir)/Include/internal/pycore_opcode.h.new - .PHONY: regen-token regen-token: # Regenerate Doc/library/token-list.inc from Grammar/Tokens @@ -1533,22 +1566,53 @@ Objects/unicodeobject.o: $(srcdir)/Objects/unicodeobject.c $(UNICODE_DEPS) Objects/dictobject.o: $(srcdir)/Objects/stringlib/eq.h Objects/setobject.o: $(srcdir)/Objects/stringlib/eq.h +Objects/obmalloc.o: $(srcdir)/Objects/mimalloc/alloc.c \ + $(srcdir)/Objects/mimalloc/alloc-aligned.c \ + $(srcdir)/Objects/mimalloc/alloc-posix.c \ + $(srcdir)/Objects/mimalloc/arena.c \ + $(srcdir)/Objects/mimalloc/bitmap.c \ + $(srcdir)/Objects/mimalloc/heap.c \ + $(srcdir)/Objects/mimalloc/init.c \ + $(srcdir)/Objects/mimalloc/options.c \ + $(srcdir)/Objects/mimalloc/os.c \ + $(srcdir)/Objects/mimalloc/page.c \ + $(srcdir)/Objects/mimalloc/random.c \ + $(srcdir)/Objects/mimalloc/segment.c \ + $(srcdir)/Objects/mimalloc/segment-map.c \ + $(srcdir)/Objects/mimalloc/stats.c \ + $(srcdir)/Objects/mimalloc/prim/prim.c \ + $(srcdir)/Objects/mimalloc/prim/osx/prim.c \ + $(srcdir)/Objects/mimalloc/prim/unix/prim.c \ + $(srcdir)/Objects/mimalloc/prim/wasi/prim.c + +Objects/mimalloc/page.o: $(srcdir)/Objects/mimalloc/page-queue.c .PHONY: regen-cases regen-cases: # Regenerate various files from Python/bytecodes.c # Pass CASESFLAG=-l to insert #line directives in the output - PYTHONPATH=$(srcdir)/Tools/cases_generator \ - $(PYTHON_FOR_REGEN) \ - $(srcdir)/Tools/cases_generator/generate_cases.py \ - $(CASESFLAG) \ - -o $(srcdir)/Python/generated_cases.c.h.new \ - -m $(srcdir)/Include/internal/pycore_opcode_metadata.h.new \ - -e $(srcdir)/Python/executor_cases.c.h.new \ - -p $(srcdir)/Lib/_opcode_metadata.py.new \ - $(srcdir)/Python/bytecodes.c + $(PYTHON_FOR_REGEN) $(srcdir)/Tools/cases_generator/opcode_id_generator.py \ + -o $(srcdir)/Include/opcode_ids.h.new $(srcdir)/Python/bytecodes.c + $(PYTHON_FOR_REGEN) $(srcdir)/Tools/cases_generator/target_generator.py \ + -o $(srcdir)/Python/opcode_targets.h.new $(srcdir)/Python/bytecodes.c + $(PYTHON_FOR_REGEN) $(srcdir)/Tools/cases_generator/uop_id_generator.py \ + -o $(srcdir)/Include/internal/pycore_uop_ids.h.new $(srcdir)/Python/bytecodes.c + $(PYTHON_FOR_REGEN) $(srcdir)/Tools/cases_generator/py_metadata_generator.py \ + -o $(srcdir)/Lib/_opcode_metadata.py.new $(srcdir)/Python/bytecodes.c + $(PYTHON_FOR_REGEN) $(srcdir)/Tools/cases_generator/tier1_generator.py \ + -o $(srcdir)/Python/generated_cases.c.h.new $(srcdir)/Python/bytecodes.c + $(PYTHON_FOR_REGEN) $(srcdir)/Tools/cases_generator/tier2_generator.py \ + -o $(srcdir)/Python/executor_cases.c.h.new $(srcdir)/Python/bytecodes.c + $(PYTHON_FOR_REGEN) $(srcdir)/Tools/cases_generator/opcode_metadata_generator.py \ + -o $(srcdir)/Include/internal/pycore_opcode_metadata.h.new $(srcdir)/Python/bytecodes.c + $(PYTHON_FOR_REGEN) $(srcdir)/Tools/cases_generator/uop_metadata_generator.py -o \ + $(srcdir)/Include/internal/pycore_uop_metadata.h.new $(srcdir)/Python/bytecodes.c $(UPDATE_FILE) $(srcdir)/Python/generated_cases.c.h $(srcdir)/Python/generated_cases.c.h.new + $(UPDATE_FILE) $(srcdir)/Include/opcode_ids.h $(srcdir)/Include/opcode_ids.h.new + $(UPDATE_FILE) $(srcdir)/Include/internal/pycore_uop_ids.h $(srcdir)/Include/internal/pycore_uop_ids.h.new + $(UPDATE_FILE) $(srcdir)/Python/opcode_targets.h $(srcdir)/Python/opcode_targets.h.new $(UPDATE_FILE) $(srcdir)/Include/internal/pycore_opcode_metadata.h $(srcdir)/Include/internal/pycore_opcode_metadata.h.new + $(UPDATE_FILE) $(srcdir)/Include/internal/pycore_uop_metadata.h $(srcdir)/Include/internal/pycore_uop_metadata.h.new $(UPDATE_FILE) $(srcdir)/Python/executor_cases.c.h $(srcdir)/Python/executor_cases.c.h.new $(UPDATE_FILE) $(srcdir)/Lib/_opcode_metadata.py $(srcdir)/Lib/_opcode_metadata.py.new @@ -1558,19 +1622,20 @@ Python/ceval.o: \ $(srcdir)/Python/ceval_macros.h \ $(srcdir)/Python/condvar.h \ $(srcdir)/Python/generated_cases.c.h \ + $(srcdir)/Python/executor_cases.c.h \ $(srcdir)/Python/opcode_targets.h -Python/executor.o: \ - $(srcdir)/Include/internal/pycore_opcode_metadata.h \ - $(srcdir)/Python/ceval_macros.h \ - $(srcdir)/Python/executor_cases.c.h - Python/flowgraph.o: \ $(srcdir)/Include/internal/pycore_opcode_metadata.h Python/optimizer.o: \ $(srcdir)/Python/executor_cases.c.h \ - $(srcdir)/Include/internal/pycore_opcode_metadata.h + $(srcdir)/Include/internal/pycore_opcode_metadata.h \ + $(srcdir)/Include/internal/pycore_optimizer.h + +Python/optimizer_analysis.o: \ + $(srcdir)/Include/internal/pycore_opcode_metadata.h \ + $(srcdir)/Include/internal/pycore_optimizer.h Python/frozen.o: $(FROZEN_FILES_OUT) @@ -1585,8 +1650,8 @@ Include/pydtrace_probes.h: $(srcdir)/Include/pydtrace.d mv $@.tmp $@ Python/ceval.o: $(srcdir)/Include/pydtrace.h +Python/gc.o: $(srcdir)/Include/pydtrace.h Python/import.o: $(srcdir)/Include/pydtrace.h -Modules/gcmodule.o: $(srcdir)/Include/pydtrace.h Python/pydtrace.o: $(srcdir)/Include/pydtrace.d $(DTRACE_DEPS) $(DTRACE) $(DFLAGS) -o $@ -G -s $< $(DTRACE_DEPS) @@ -1639,6 +1704,7 @@ PYTHON_HEADERS= \ $(srcdir)/Include/object.h \ $(srcdir)/Include/objimpl.h \ $(srcdir)/Include/opcode.h \ + $(srcdir)/Include/opcode_ids.h \ $(srcdir)/Include/osdefs.h \ $(srcdir)/Include/osmodule.h \ $(srcdir)/Include/patchlevel.h \ @@ -1702,21 +1768,25 @@ PYTHON_HEADERS= \ $(srcdir)/Include/cpython/longobject.h \ $(srcdir)/Include/cpython/memoryobject.h \ $(srcdir)/Include/cpython/methodobject.h \ - $(srcdir)/Include/cpython/modsupport.h \ $(srcdir)/Include/cpython/object.h \ $(srcdir)/Include/cpython/objimpl.h \ $(srcdir)/Include/cpython/odictobject.h \ $(srcdir)/Include/cpython/optimizer.h \ $(srcdir)/Include/cpython/picklebufobject.h \ $(srcdir)/Include/cpython/pthread_stubs.h \ + $(srcdir)/Include/cpython/pyatomic.h \ + $(srcdir)/Include/cpython/pyatomic_gcc.h \ + $(srcdir)/Include/cpython/pyatomic_std.h \ $(srcdir)/Include/cpython/pyctype.h \ $(srcdir)/Include/cpython/pydebug.h \ $(srcdir)/Include/cpython/pyerrors.h \ $(srcdir)/Include/cpython/pyfpe.h \ $(srcdir)/Include/cpython/pyframe.h \ + $(srcdir)/Include/cpython/pyhash.h \ $(srcdir)/Include/cpython/pylifecycle.h \ $(srcdir)/Include/cpython/pymem.h \ $(srcdir)/Include/cpython/pystate.h \ + $(srcdir)/Include/cpython/pystats.h \ $(srcdir)/Include/cpython/pythonrun.h \ $(srcdir)/Include/cpython/pythread.h \ $(srcdir)/Include/cpython/setobject.h \ @@ -1728,17 +1798,18 @@ PYTHON_HEADERS= \ $(srcdir)/Include/cpython/warnings.h \ $(srcdir)/Include/cpython/weakrefobject.h \ \ + $(MIMALLOC_HEADERS) \ + \ $(srcdir)/Include/internal/pycore_abstract.h \ $(srcdir)/Include/internal/pycore_asdl.h \ $(srcdir)/Include/internal/pycore_ast.h \ $(srcdir)/Include/internal/pycore_ast_state.h \ $(srcdir)/Include/internal/pycore_atexit.h \ - $(srcdir)/Include/internal/pycore_atomic.h \ - $(srcdir)/Include/internal/pycore_atomic_funcs.h \ $(srcdir)/Include/internal/pycore_bitutils.h \ $(srcdir)/Include/internal/pycore_bytes_methods.h \ $(srcdir)/Include/internal/pycore_bytesobject.h \ $(srcdir)/Include/internal/pycore_call.h \ + $(srcdir)/Include/internal/pycore_capsule.h \ $(srcdir)/Include/internal/pycore_ceval.h \ $(srcdir)/Include/internal/pycore_ceval_state.h \ $(srcdir)/Include/internal/pycore_code.h \ @@ -1747,6 +1818,8 @@ PYTHON_HEADERS= \ $(srcdir)/Include/internal/pycore_complexobject.h \ $(srcdir)/Include/internal/pycore_condvar.h \ $(srcdir)/Include/internal/pycore_context.h \ + $(srcdir)/Include/internal/pycore_critical_section.h \ + $(srcdir)/Include/internal/pycore_crossinterp.h \ $(srcdir)/Include/internal/pycore_dict.h \ $(srcdir)/Include/internal/pycore_dict_state.h \ $(srcdir)/Include/internal/pycore_descrobject.h \ @@ -1757,6 +1830,7 @@ PYTHON_HEADERS= \ $(srcdir)/Include/internal/pycore_floatobject.h \ $(srcdir)/Include/internal/pycore_format.h \ $(srcdir)/Include/internal/pycore_frame.h \ + $(srcdir)/Include/internal/pycore_freelist.h \ $(srcdir)/Include/internal/pycore_function.h \ $(srcdir)/Include/internal/pycore_genobject.h \ $(srcdir)/Include/internal/pycore_getopt.h \ @@ -1765,11 +1839,14 @@ PYTHON_HEADERS= \ $(srcdir)/Include/internal/pycore_global_objects_fini_generated.h \ $(srcdir)/Include/internal/pycore_hamt.h \ $(srcdir)/Include/internal/pycore_hashtable.h \ + $(srcdir)/Include/internal/pycore_identifier.h \ $(srcdir)/Include/internal/pycore_import.h \ $(srcdir)/Include/internal/pycore_initconfig.h \ $(srcdir)/Include/internal/pycore_interp.h \ $(srcdir)/Include/internal/pycore_intrinsics.h \ $(srcdir)/Include/internal/pycore_list.h \ + $(srcdir)/Include/internal/pycore_llist.h \ + $(srcdir)/Include/internal/pycore_lock.h \ $(srcdir)/Include/internal/pycore_long.h \ $(srcdir)/Include/internal/pycore_modsupport.h \ $(srcdir)/Include/internal/pycore_moduleobject.h \ @@ -1778,21 +1855,27 @@ PYTHON_HEADERS= \ $(srcdir)/Include/internal/pycore_object_state.h \ $(srcdir)/Include/internal/pycore_obmalloc.h \ $(srcdir)/Include/internal/pycore_obmalloc_init.h \ - $(srcdir)/Include/internal/pycore_opcode.h \ + $(srcdir)/Include/internal/pycore_opcode_metadata.h \ $(srcdir)/Include/internal/pycore_opcode_utils.h \ + $(srcdir)/Include/internal/pycore_optimizer.h \ + $(srcdir)/Include/internal/pycore_parking_lot.h \ $(srcdir)/Include/internal/pycore_pathconfig.h \ $(srcdir)/Include/internal/pycore_pyarena.h \ + $(srcdir)/Include/internal/pycore_pybuffer.h \ $(srcdir)/Include/internal/pycore_pyerrors.h \ $(srcdir)/Include/internal/pycore_pyhash.h \ $(srcdir)/Include/internal/pycore_pylifecycle.h \ $(srcdir)/Include/internal/pycore_pymem.h \ $(srcdir)/Include/internal/pycore_pymem_init.h \ $(srcdir)/Include/internal/pycore_pystate.h \ + $(srcdir)/Include/internal/pycore_pystats.h \ + $(srcdir)/Include/internal/pycore_pythonrun.h \ $(srcdir)/Include/internal/pycore_pythread.h \ $(srcdir)/Include/internal/pycore_range.h \ $(srcdir)/Include/internal/pycore_runtime.h \ $(srcdir)/Include/internal/pycore_runtime_init_generated.h \ $(srcdir)/Include/internal/pycore_runtime_init.h \ + $(srcdir)/Include/internal/pycore_semaphore.h \ $(srcdir)/Include/internal/pycore_setobject.h \ $(srcdir)/Include/internal/pycore_signal.h \ $(srcdir)/Include/internal/pycore_sliceobject.h \ @@ -1804,6 +1887,7 @@ PYTHON_HEADERS= \ $(srcdir)/Include/internal/pycore_token.h \ $(srcdir)/Include/internal/pycore_traceback.h \ $(srcdir)/Include/internal/pycore_tracemalloc.h \ + $(srcdir)/Include/internal/pycore_tstate.h \ $(srcdir)/Include/internal/pycore_tuple.h \ $(srcdir)/Include/internal/pycore_typeobject.h \ $(srcdir)/Include/internal/pycore_typevarobject.h \ @@ -1812,6 +1896,7 @@ PYTHON_HEADERS= \ $(srcdir)/Include/internal/pycore_unicodeobject.h \ $(srcdir)/Include/internal/pycore_unicodeobject_generated.h \ $(srcdir)/Include/internal/pycore_uops.h \ + $(srcdir)/Include/internal/pycore_uop_metadata.h \ $(srcdir)/Include/internal/pycore_warnings.h \ $(srcdir)/Include/internal/pycore_weakref.h \ $(DTRACE_HEADERS) \ @@ -1826,8 +1911,8 @@ $(LIBRARY_OBJS) $(MODOBJS) Programs/python.o: $(PYTHON_HEADERS) TESTOPTS= $(EXTRATESTOPTS) TESTPYTHON= $(RUNSHARED) $(PYTHON_FOR_BUILD) $(TESTPYTHONOPTS) -TESTRUNNER= $(TESTPYTHON) $(srcdir)/Tools/scripts/run_tests.py -TESTTIMEOUT= 1200 +TESTRUNNER= $(TESTPYTHON) -m test +TESTTIMEOUT= # Remove "test_python_*" directories of previous failed test jobs. # Pass TESTOPTS options because it can contain --tempdir option. @@ -1837,56 +1922,38 @@ cleantest: all # Run a basic set of regression tests. # This excludes some tests that are particularly resource-intensive. +# Similar to buildbottest, but use --fast-ci option, instead of --slow-ci. .PHONY: test test: all - $(TESTRUNNER) $(TESTOPTS) - -# Run the full test suite twice - once without .pyc files, and once with. -# In the past, we've had problems where bugs in the marshalling or -# elsewhere caused bytecode read from .pyc files to behave differently -# than bytecode generated directly from a .py source file. Sometimes -# the bytecode read from a .pyc file had the bug, sometimes the directly -# generated bytecode. This is sometimes a very shy bug needing a lot of -# sample data. -.PHONY: testall -testall: all - -find $(srcdir)/Lib -name '*.py[co]' -print | xargs rm -f - $(TESTPYTHON) -E $(srcdir)/Lib/compileall.py - -find $(srcdir)/Lib -name '*.py[co]' -print | xargs rm -f - -$(TESTRUNNER) -u all $(TESTOPTS) - $(TESTRUNNER) -u all $(TESTOPTS) + $(TESTRUNNER) --fast-ci --timeout=$(TESTTIMEOUT) $(TESTOPTS) # Run the test suite for both architectures in a Universal build on OSX. # Must be run on an Intel box. .PHONY: testuniversal testuniversal: all - @if [ `arch` != 'i386' ]; then \ - echo "This can only be used on OSX/i386" ;\ - exit 1 ;\ - fi - $(TESTRUNNER) -u all $(TESTOPTS) - $(RUNSHARED) /usr/libexec/oah/translate \ - ./$(BUILDPYTHON) -E -m test -j 0 -u all $(TESTOPTS) - -# Like testall, but with only one pass and without multiple processes. -# Run an optional script to include information about the build environment. + @if [ `arch` != 'i386' ]; then \ + echo "This can only be used on OSX/i386" ;\ + exit 1 ;\ + fi + $(TESTRUNNER) --slow-ci --timeout=$(TESTTIMEOUT) $(TESTOPTS) + $(RUNSHARED) /usr/libexec/oah/translate \ + ./$(BUILDPYTHON) -E -m test -j 0 -u all $(TESTOPTS) + +# Like test, but using --slow-ci which enables all test resources and use +# longer timeout. Run an optional pybuildbot.identify script to include +# information about the build environment. .PHONY: buildbottest buildbottest: all - -@if which pybuildbot.identify >/dev/null 2>&1; then \ - pybuildbot.identify "CC='$(CC)'" "CXX='$(CXX)'"; \ - fi - $(TESTRUNNER) -j 1 -u all -W --slowest --fail-env-changed --timeout=$(TESTTIMEOUT) $(TESTOPTS) - -# Like testall, but run Python tests with HOSTRUNNER directly. -.PHONY: hostrunnertest -hostrunnertest: all - $(RUNSHARED) $(HOSTRUNNER) ./$(BUILDPYTHON) -m test -u all $(TESTOPTS) + -@if which pybuildbot.identify >/dev/null 2>&1; then \ + pybuildbot.identify "CC='$(CC)'" "CXX='$(CXX)'"; \ + fi + $(TESTRUNNER) --slow-ci --timeout=$(TESTTIMEOUT) $(TESTOPTS) .PHONY: pythoninfo pythoninfo: all $(RUNSHARED) $(HOSTRUNNER) ./$(BUILDPYTHON) -m test.pythoninfo -QUICKTESTOPTS= $(TESTOPTS) -x test_subprocess test_io \ +QUICKTESTOPTS= -x test_subprocess test_io \ test_multibytecodec test_urllib2_localnet test_itertools \ test_multiprocessing_fork test_multiprocessing_spawn \ test_multiprocessing_forkserver \ @@ -1895,7 +1962,7 @@ QUICKTESTOPTS= $(TESTOPTS) -x test_subprocess test_io \ .PHONY: quicktest quicktest: all - $(TESTRUNNER) $(QUICKTESTOPTS) + $(TESTRUNNER) --fast-ci --timeout=$(TESTTIMEOUT) $(TESTOPTS) $(QUICKTESTOPTS) # SSL tests .PHONY: multisslcompile @@ -2110,10 +2177,12 @@ LIBSUBDIRS= asyncio \ json \ logging \ multiprocessing multiprocessing/dummy \ + pathlib \ pydoc_data \ re \ site-packages \ sqlite3 \ + sysconfig \ tkinter \ tomllib \ turtledemo \ @@ -2129,23 +2198,35 @@ LIBSUBDIRS= asyncio \ TESTSUBDIRS= idlelib/idle_test \ test \ test/audiodata \ - test/capath \ + test/archivetestdata \ + test/certdata \ + test/certdata/capath \ test/cjkencodings \ test/crashers \ + test/configdata \ test/data \ test/decimaltestdata \ test/dtracedata \ test/encoded_modules \ test/leakers \ test/libregrtest \ + test/mathdata \ + test/regrtestdata \ + test/regrtestdata/import_from_tests \ + test/regrtestdata/import_from_tests/test_regrtest_b \ test/subprocessdata \ test/support \ test/support/_hypothesis_stubs \ test/test_asyncio \ test/test_capi \ + test/test_cppext \ test/test_ctypes \ + test/test_dataclasses \ test/test_email \ test/test_email/data \ + test/test_future_stmt \ + test/test_gdb \ + test/test_inspect \ test/test_import \ test/test_import/data \ test/test_import/data/circular_imports \ @@ -2199,6 +2280,8 @@ TESTSUBDIRS= idlelib/idle_test \ test/test_importlib/resources/zipdata02 \ test/test_importlib/source \ test/test_json \ + test/test_module \ + test/test_pathlib \ test/test_peg_generator \ test/test_sqlite3 \ test/test_tkinter \ @@ -2231,11 +2314,11 @@ TESTSUBDIRS= idlelib/idle_test \ test/test_zoneinfo \ test/test_zoneinfo/data \ test/tkinterdata \ + test/tokenizedata \ test/tracedmodules \ test/typinganndata \ test/xmltestdata \ - test/xmltestdata/c14n-20 \ - test/ziptestdata + test/xmltestdata/c14n-20 COMPILEALL_OPTS=-j0 @@ -2583,12 +2666,11 @@ autoconf: .PHONY: regen-configure regen-configure: - @if command -v podman >/dev/null; then RUNTIME="podman"; else RUNTIME="docker"; fi; \ - if ! command -v $$RUNTIME; then echo "$@ needs either Podman or Docker container runtime." >&2; exit 1; fi; \ - if command -v selinuxenabled >/dev/null && selinuxenabled; then OPT=":Z"; fi; \ - CMD="$$RUNTIME run --rm --pull=always -v $(abs_srcdir):/src$$OPT quay.io/tiran/cpython_autoconf:271"; \ - echo $$CMD; \ - $$CMD || exit $? + $(srcdir)/Tools/build/regen-configure.sh + +.PHONY: regen-sbom +regen-sbom: + $(PYTHON_FOR_REGEN) $(srcdir)/Tools/build/generate_sbom.py # Create a tags file for vi tags:: @@ -2675,6 +2757,7 @@ clobber: clean -rm -rf build platform -rm -rf $(PYTHONFRAMEWORKDIR) -rm -f python-config.py python-config + -rm -rf cross-build # Make things extra clean, before making a distribution: # remove all generated files, even Makefile[.pre] @@ -2785,8 +2868,9 @@ MODULE__SHA1_DEPS=$(srcdir)/Modules/hashlib.h $(LIBHACL_HEADERS) Modules/_hacl/H MODULE__SHA2_DEPS=$(srcdir)/Modules/hashlib.h $(LIBHACL_SHA2_HEADERS) $(LIBHACL_SHA2_A) MODULE__SHA3_DEPS=$(srcdir)/Modules/hashlib.h $(LIBHACL_HEADERS) Modules/_hacl/Hacl_Hash_SHA3.h Modules/_hacl/Hacl_Hash_SHA3.c MODULE__SOCKET_DEPS=$(srcdir)/Modules/socketmodule.h $(srcdir)/Modules/addrinfo.h $(srcdir)/Modules/getaddrinfo.c $(srcdir)/Modules/getnameinfo.c -MODULE__SSL_DEPS=$(srcdir)/Modules/_ssl.h $(srcdir)/Modules/_ssl/cert.c $(srcdir)/Modules/_ssl/debughelpers.c $(srcdir)/Modules/_ssl/misc.c $(srcdir)/Modules/_ssl_data.h $(srcdir)/Modules/_ssl_data_111.h $(srcdir)/Modules/_ssl_data_300.h $(srcdir)/Modules/socketmodule.h -MODULE__TESTCAPI_DEPS=$(srcdir)/Modules/_testcapi/testcapi_long.h $(srcdir)/Modules/_testcapi/parts.h +MODULE__SSL_DEPS=$(srcdir)/Modules/_ssl.h $(srcdir)/Modules/_ssl/cert.c $(srcdir)/Modules/_ssl/debughelpers.c $(srcdir)/Modules/_ssl/misc.c $(srcdir)/Modules/_ssl_data_111.h $(srcdir)/Modules/_ssl_data_300.h $(srcdir)/Modules/socketmodule.h +MODULE__TESTCAPI_DEPS=$(srcdir)/Modules/_testcapi/testcapi_long.h $(srcdir)/Modules/_testcapi/parts.h $(srcdir)/Modules/_testcapi/util.h +MODULE__TESTINTERNALCAPI_DEPS=$(srcdir)/Modules/_testinternalcapi/parts.h MODULE__SQLITE3_DEPS=$(srcdir)/Modules/_sqlite/connection.h $(srcdir)/Modules/_sqlite/cursor.h $(srcdir)/Modules/_sqlite/microprotocols.h $(srcdir)/Modules/_sqlite/module.h $(srcdir)/Modules/_sqlite/prepare_protocol.h $(srcdir)/Modules/_sqlite/row.h $(srcdir)/Modules/_sqlite/util.h CODECS_COMMON_HEADERS=$(srcdir)/Modules/cjkcodecs/multibytecodec.h $(srcdir)/Modules/cjkcodecs/cjkcodecs.h diff --git a/Misc/ACKS b/Misc/ACKS index 8b8c5ad8434bd7..541f41f680efc8 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -31,6 +31,7 @@ Farhan Ahmad Matthew Ahrens Nir Aides Akira +Ege Akman Yaniv Aknin Jyrki Alakuijala Tatiana Al-Chueyr @@ -254,6 +255,7 @@ Curtis Bucher Colm Buckley Erik de Bueger Jan-Hein Bührman +Marc Bürg Lars Buitinck Artem Bulgakov Dick Bulterman @@ -348,6 +350,7 @@ Robbie Clemons Steve Clift Hervé Coatanhay Riccardo Coccioli +Jacob Coffee Nick Coghlan Josh Cogliati Noam Cohen @@ -503,6 +506,7 @@ Daniel Ellis Phil Elson David Ely Victor van den Elzen +Vlad Emelianov Jeff Epler Tom Epperly Gökcen Eraslan @@ -627,6 +631,7 @@ Dinu Gherman Subhendu Ghosh Jonathan Giddy Johannes Gijsbers +Stephen Gildea Michael Gilfix Julian Gindi Yannick Gingras @@ -661,6 +666,7 @@ Eddy De Greef Duane Griffin Grant Griffin Andrea Griffini +Semyon Grigoryev Duncan Grisby Olivier Grisel Fabian Groffen @@ -784,6 +790,7 @@ Thomas Holmes Craig Holmquist Philip Homburg Naofumi Honda +Constantin Hong Weipeng Hong Jeffrey Honig Rob Hooft @@ -1150,6 +1157,7 @@ Colin Marc Vincent Marchetti David Marek Doug Marien +Chris Markiewicz Sven Marnach John Marshall Alex Martelli @@ -1190,6 +1198,7 @@ Andrew McNamara Caolan McNamara Jeff McNeil Craig McPheeters +Corvin McPherson Lambert Meertens Bill van Melle Lucas Prado Melo @@ -1267,7 +1276,7 @@ R. David Murray Matti Mäki Jörg Müller Kaushik N -Dong-hee Na +Donghee Na Dale Nagata John Nagle Takahiro Nakayama @@ -1329,6 +1338,7 @@ Ethan Onstott Ken Jin Ooi Piet van Oostrum Tomas Oppelstrup +Itamar Oren Jason Orendorff Yan "yyyyyyyan" Orestes Bastien Orivel @@ -1339,7 +1349,7 @@ Michele Orrù Tomáš Orsava Oleg Oshmyan Denis Osipov -Itamar Ostricher +Savannah Ostrowski Denis S. Otkidach Peter Otten Michael Otteneder @@ -1368,6 +1378,7 @@ Peter Parente Alexandre Parenteau Dan Parisien HyeSoo Park +Moonsik Park William Park Claude Paroz Heikki Partanen @@ -1451,6 +1462,7 @@ Paul Prescod Donovan Preston Eric Price Paul Price +Matt Prodani Iuliia Proskurnia Dorian Pula Jyrki Pulliainen @@ -1474,6 +1486,7 @@ Ajith Ramachandran Dhushyanth Ramasamy Ashwin Ramaswami Jeff Ramnani +Grant Ramsay Bayard Randel Varpu Rantala Brodie Rao @@ -1562,6 +1575,7 @@ Liam Routt Todd Rovito Craig Rowland Clinton Roy +Ujan RoyBandyopadhyay Paul Rubin Sam Ruby Demur Rumed @@ -1706,6 +1720,7 @@ Roman Skurikhin Ville Skyttä Michael Sloan Nick Sloan +Tyler Smart Radek Smejkal Václav Å milauer Casper W. Smet @@ -1866,6 +1881,7 @@ Steven Troxler Brent Tubbs Anthony Tuininga Erno Tukia +Adam Turner David Turner Stephen Turner Itamar Turner-Trauring @@ -2073,7 +2089,5 @@ Jelle Zijlstra Gennadiy Zlobin Doug Zongker Peter Ã…strand -Vlad Emelianov -Andrey Doroschenko (Entries should be added in rough alphabetical order by last names) diff --git a/Misc/HISTORY b/Misc/HISTORY index e66b695f21c977..b66413277259dc 100644 --- a/Misc/HISTORY +++ b/Misc/HISTORY @@ -16169,7 +16169,7 @@ Core and Builtins codec subsystem, for example UTF-8 is turned into utf-8. - Issue #4200: Changed the atexit module to store its state in its - PyModuleDef atexitmodule. This fixes a bug with multiple subinterpeters. + PyModuleDef atexitmodule. This fixes a bug with multiple subinterpreters. - Issue #4237: io.FileIO() was raising invalid warnings caused by insufficient initialization of PyFileIOObject struct members. diff --git a/Misc/NEWS.d/3.10.0a1.rst b/Misc/NEWS.d/3.10.0a1.rst index 79d85a40df8bbe..3186de75efd9c5 100644 --- a/Misc/NEWS.d/3.10.0a1.rst +++ b/Misc/NEWS.d/3.10.0a1.rst @@ -68,7 +68,7 @@ getting the ``__bases__`` attribute leads to infinite recursion. .. section: Core and Builtins Speed up calls to ``reversed()`` by using the :pep:`590` ``vectorcall`` -calling convention. Patch by Dong-hee Na. +calling convention. Patch by Donghee Na. .. @@ -88,7 +88,7 @@ convention. Patch by Dennis Sweeney. .. section: Core and Builtins Speed up calls to ``bool()`` by using the :pep:`590` ``vectorcall`` calling -convention. Patch by Dong-hee Na. +convention. Patch by Donghee Na. .. @@ -605,8 +605,8 @@ Opt out serialization/deserialization for _random.Random .. nonce: jxJ4yn .. section: Core and Builtins -Rename `PyPegen*` functions to `PyParser*`, so that we can remove the old -set of `PyParser*` functions that were using the old parser, but keep +Rename ``PyPegen*`` functions to ``PyParser*``, so that we can remove the old +set of ``PyParser*`` functions that were using the old parser, but keep everything backwards-compatible. .. @@ -715,7 +715,7 @@ Fix refleak in _Py_fopen_obj() when PySys_Audit() fails .. section: Core and Builtins Add a state to the :mod:`!nis` module (:pep:`3121`) and apply the multiphase -initialization. Patch by Dong-hee Na. +initialization. Patch by Donghee Na. .. @@ -936,7 +936,7 @@ class. Patch by Pablo Galindo. .. section: Core and Builtins :c:func:`Py_TYPE()` is changed to the inline static function. Patch by -Dong-hee Na. +Donghee Na. .. @@ -2527,7 +2527,7 @@ in Python 3.4 and removed in Python 3.5. .. nonce: BE7zbu .. section: Library -Fix `cgi.parse_multipart` without content_length. Patch by Roger Duran +Fix ``cgi.parse_multipart`` without content_length. Patch by Roger Duran .. @@ -2596,7 +2596,7 @@ remove multiple items from a list". .. section: Documentation Fix RemovedInSphinx40Warning when building the documentation. Patch by -Dong-hee Na. +Donghee Na. .. @@ -2862,7 +2862,7 @@ Make test_gdb properly run on HP-UX. Patch by Michael Osipov. .. section: Build Update :c:macro:`Py_UNREACHABLE` to use __builtin_unreachable() if only the -compiler is able to use it. Patch by Dong-hee Na. +compiler is able to use it. Patch by Donghee Na. .. diff --git a/Misc/NEWS.d/3.10.0a2.rst b/Misc/NEWS.d/3.10.0a2.rst index 78b25779802d6e..78f4377656b0cc 100644 --- a/Misc/NEWS.d/3.10.0a2.rst +++ b/Misc/NEWS.d/3.10.0a2.rst @@ -185,7 +185,7 @@ Removed special methods ``__int__``, ``__float__``, ``__floordiv__``, Micro optimization when compute :c:member:`~PySequenceMethods.sq_item` and :c:member:`~PyMappingMethods.mp_subscript` of :class:`range`. Patch by -Dong-hee Na. +Donghee Na. .. @@ -205,7 +205,7 @@ error message using the current locale's encoding. .. nonce: iLoMVF .. section: Core and Builtins -Micro optimization for range.index if step is 1. Patch by Dong-hee Na. +Micro optimization for range.index if step is 1. Patch by Donghee Na. .. diff --git a/Misc/NEWS.d/3.10.0a3.rst b/Misc/NEWS.d/3.10.0a3.rst index 755109cbd376f4..7112819c1b4118 100644 --- a/Misc/NEWS.d/3.10.0a3.rst +++ b/Misc/NEWS.d/3.10.0a3.rst @@ -153,7 +153,7 @@ Allow an unparenthesized walrus in subscript indexes. .. section: Core and Builtins Make sure that the compiler front-end produces a well-formed control flow -graph. Be be more aggressive in the compiler back-end, as it is now safe to +graph. Be more aggressive in the compiler back-end, as it is now safe to do so. .. @@ -394,7 +394,7 @@ Removed the ``formatter`` module, which was deprecated in Python 3.4. It is somewhat obsolete, little used, and not tested. It was originally scheduled to be removed in Python 3.6, but such removals were delayed until after Python 2.7 EOL. Existing users should copy whatever classes they use into -their code. Patch by Dong-hee Na and and Terry J. Reedy. +their code. Patch by Donghee Na and and Terry J. Reedy. .. diff --git a/Misc/NEWS.d/3.10.0a4.rst b/Misc/NEWS.d/3.10.0a4.rst index 95f9319668db45..414823f162d85c 100644 --- a/Misc/NEWS.d/3.10.0a4.rst +++ b/Misc/NEWS.d/3.10.0a4.rst @@ -105,7 +105,7 @@ blocks .. section: Core and Builtins Make the :mod:`atexit` module state per-interpreter. It is now safe have -more than one :mod:`atexit` module instance. Patch by Dong-hee Na and Victor +more than one :mod:`atexit` module instance. Patch by Donghee Na and Victor Stinner. .. @@ -768,7 +768,7 @@ results. Patch by Ammar Askar. .. section: Tests Update test_nntplib to use official group name of news.aioe.org for testing. -Patch by Dong-hee Na. +Patch by Donghee Na. .. diff --git a/Misc/NEWS.d/3.10.0a6.rst b/Misc/NEWS.d/3.10.0a6.rst index 313aa689254040..c379b968c9885b 100644 --- a/Misc/NEWS.d/3.10.0a6.rst +++ b/Misc/NEWS.d/3.10.0a6.rst @@ -295,7 +295,7 @@ actual dictionary. This created problems for introspection tools. .. section: Library Added :const:`~os.O_EVTONLY`, :const:`~os.O_FSYNC`, :const:`~os.O_SYMLINK` and -:const:`~os.O_NOFOLLOW_ANY` for macOS. Patch by Dong-hee Na. +:const:`~os.O_NOFOLLOW_ANY` for macOS. Patch by Donghee Na. .. diff --git a/Misc/NEWS.d/3.10.0a7.rst b/Misc/NEWS.d/3.10.0a7.rst index 7933f71b01c14d..d9cdfbd04c88d4 100644 --- a/Misc/NEWS.d/3.10.0a7.rst +++ b/Misc/NEWS.d/3.10.0a7.rst @@ -113,7 +113,7 @@ in f-strings. Patch by Pablo Galindo. .. section: Core and Builtins Speed up calls to ``map()`` by using the :pep:`590` ``vectorcall`` calling -convention. Patch by Dong-hee Na. +convention. Patch by Donghee Na. .. @@ -240,7 +240,7 @@ of processes that don't use sigaltstack. .. section: Core and Builtins Speed up calls to ``filter()`` by using the :pep:`590` ``vectorcall`` -calling convention. Patch by Dong-hee Na. +calling convention. Patch by Donghee Na. .. @@ -274,7 +274,7 @@ Co-authored-by: Tim Peters Only handle asynchronous exceptions and requests to drop the GIL when returning from a call or on the back edges of loops. Makes sure that -:meth:`__exit__` is always called in with statements, even for interrupts. +:meth:`~object.__exit__` is always called in with statements, even for interrupts. .. diff --git a/Misc/NEWS.d/3.10.0b1.rst b/Misc/NEWS.d/3.10.0b1.rst index 3c71bc73b812a1..e7b6b93d0b6df3 100644 --- a/Misc/NEWS.d/3.10.0b1.rst +++ b/Misc/NEWS.d/3.10.0b1.rst @@ -516,7 +516,7 @@ encoding. .. section: Library Removed an unnecessary list comprehension before looping from -:func:`urllib.parse.parse_qsl`. Patch by Christoph Zwerschke and Dong-hee +:func:`urllib.parse.parse_qsl`. Patch by Christoph Zwerschke and Donghee Na. .. diff --git a/Misc/NEWS.d/3.11.0a1.rst b/Misc/NEWS.d/3.11.0a1.rst index 17ee5138dbf90f..63abcbd5a6499e 100644 --- a/Misc/NEWS.d/3.11.0a1.rst +++ b/Misc/NEWS.d/3.11.0a1.rst @@ -292,7 +292,7 @@ Fixed pickling of range iterators that iterated for over ``2**32`` times. .. section: Core and Builtins A :exc:`SyntaxError` is now raised when trying to delete :const:`__debug__`. -Patch by Dong-hee Na. +Patch by Donghee Na. .. @@ -415,7 +415,7 @@ type :class:`float` or :class:`complex`. .. section: Core and Builtins A debug variable :envvar:`PYTHONDUMPREFSFILE` is added for creating a dump -file which is generated by :option:`--with-trace-refs`. Patch by Dong-hee +file which is generated by :option:`--with-trace-refs`. Patch by Donghee Na. .. @@ -670,7 +670,7 @@ Parameter substitution of the union type with wrong types now raises .. section: Core and Builtins Update ``property_descr_set`` to use vectorcall if possible. Patch by -Dong-hee Na. +Donghee Na. .. @@ -732,7 +732,7 @@ Collapse union of equal types. E.g. the result of ``int | int`` is now On Windows, :func:`os.urandom`: uses BCryptGenRandom API instead of CryptGenRandom API which is deprecated from Microsoft Windows API. Patch by -Dong-hee Na. +Donghee Na. .. @@ -819,7 +819,7 @@ always available when needed. Patch by Mark Shannon. .. nonce: qKnSqV .. section: Core and Builtins -The threading debug (:envvar:`PYTHONTHREADDEBUG` environment variable) is +The threading debug (:envvar:`!PYTHONTHREADDEBUG` environment variable) is deprecated in Python 3.10 and will be removed in Python 3.12. This feature requires a debug build of Python. Patch by Victor Stinner. @@ -1642,9 +1642,9 @@ interval specified with nanosecond precision. .. nonce: UptGAn .. section: Library -Remove from the :mod:`configparser` module: the :class:`SafeConfigParser` -class, the :attr:`filename` property of the :class:`ParsingError` class, the -:meth:`readfp` method of the :class:`ConfigParser` class, deprecated since +Remove from the :mod:`configparser` module: the :class:`!SafeConfigParser` +class, the :attr:`!filename` property of the :class:`~configparser.ParsingError` class, the +:meth:`!readfp` method of the :class:`~configparser.ConfigParser` class, deprecated since Python 3.2. Patch by Hugo van Kemenade. @@ -1657,7 +1657,7 @@ Patch by Hugo van Kemenade. .. section: Library Pure ASCII strings are now normalized in constant time by -:func:`unicodedata.normalize`. Patch by Dong-hee Na. +:func:`unicodedata.normalize`. Patch by Donghee Na. .. @@ -1720,7 +1720,7 @@ Improve the speed and accuracy of statistics.pvariance(). .. nonce: WI9zQY .. section: Library -Remove :meth:`__getitem__` methods of +Remove :meth:`~object.__getitem__` methods of :class:`xml.dom.pulldom.DOMEventStream`, :class:`wsgiref.util.FileWrapper` and :class:`fileinput.FileInput`, deprecated since Python 3.9. @@ -1968,7 +1968,7 @@ A new function ``operator.call`` has been added, such that :class:`!webbrowser.MacOSX` is deprecated and will be removed in Python 3.13. It is untested and undocumented and also not used by :mod:`webbrowser` itself. -Patch by Dong-hee Na. +Patch by Donghee Na. .. @@ -2465,7 +2465,7 @@ generator .. section: Library Make the implementation consistency of :func:`~operator.indexOf` between C -and Python versions. Patch by Dong-hee Na. +and Python versions. Patch by Donghee Na. .. @@ -2752,7 +2752,7 @@ of reserved filenames, including those with trailing spaces or colons. .. section: Library Fix :meth:`~email.message.MIMEPart.as_string` to pass unixfrom properly. -Patch by Dong-hee Na. +Patch by Donghee Na. .. @@ -2808,8 +2808,8 @@ behaves differently than the similar implementation in :mod:`sysconfig`. .. nonce: 3hmkWw .. section: Library -:class:`smtpd.MailmanProxy` is now removed as it is unusable without an -external module, ``mailman``. Patch by Dong-hee Na. +:class:`!smtpd.MailmanProxy` is now removed as it is unusable without an +external module, ``mailman``. Patch by Donghee Na. .. @@ -2916,7 +2916,7 @@ Support PEP 515 for Fraction's initialization from string. .. nonce: qFBYpp .. section: Library -Remove deprecated functions in the :mod:`gettext`. Patch by Dong-hee Na. +Remove deprecated functions in the :mod:`gettext`. Patch by Donghee Na. .. @@ -3483,9 +3483,9 @@ Improved reprs of :mod:`threading` synchronization objects: Deprecated the following :mod:`unittest` functions, scheduled for removal in Python 3.13: -* :func:`~!unittest.findTestCases` -* :func:`~!unittest.makeSuite` -* :func:`~!unittest.getTestCaseNames` +* :func:`!findTestCases` +* :func:`!makeSuite` +* :func:`!getTestCaseNames` Use :class:`~unittest.TestLoader` methods instead: @@ -4471,7 +4471,7 @@ and modify the frozen modules. .. section: Build Add support for building with clang thin lto via --with-lto=thin/full. Patch -by Dong-hee Na and Brett Holman. +by Donghee Na and Brett Holman. .. @@ -4798,7 +4798,7 @@ Allow the Argument Clinic tool to handle ``__complex__`` special methods. Removed the 'test2to3' demo project that demonstrated using lib2to3 to support Python 2.x and Python 3.x from a single source in a distutils -package. Patch by Dong-hee Na +package. Patch by Donghee Na .. @@ -5036,15 +5036,15 @@ Limited API. Deprecate the following functions to configure the Python initialization: -* :c:func:`PySys_AddWarnOptionUnicode` -* :c:func:`PySys_AddWarnOption` -* :c:func:`PySys_AddXOption` -* :c:func:`PySys_HasWarnOptions` -* :c:func:`Py_SetPath` -* :c:func:`Py_SetProgramName` -* :c:func:`Py_SetPythonHome` -* :c:func:`Py_SetStandardStreamEncoding` -* :c:func:`_Py_SetProgramFullPath` +* :c:func:`!PySys_AddWarnOptionUnicode` +* :c:func:`!PySys_AddWarnOption` +* :c:func:`!PySys_AddXOption` +* :c:func:`!PySys_HasWarnOptions` +* :c:func:`!Py_SetPath` +* :c:func:`!Py_SetProgramName` +* :c:func:`!Py_SetPythonHome` +* :c:func:`!Py_SetStandardStreamEncoding` +* :c:func:`!_Py_SetProgramFullPath` Use the new :c:type:`PyConfig` API of the :ref:`Python Initialization Configuration ` instead (:pep:`587`). diff --git a/Misc/NEWS.d/3.11.0a2.rst b/Misc/NEWS.d/3.11.0a2.rst index cf26137dff19ef..503e489b658e4d 100644 --- a/Misc/NEWS.d/3.11.0a2.rst +++ b/Misc/NEWS.d/3.11.0a2.rst @@ -142,7 +142,7 @@ Add SipHash13 for string hash algorithm and use it by default. .. nonce: CTUT8s .. section: Core and Builtins -Fix reference leak from descr_check. Patch by Dong-hee Na. +Fix reference leak from descr_check. Patch by Donghee Na. .. @@ -263,7 +263,7 @@ Improve the generated bytecode for class and mapping patterns. .. section: Core and Builtins Speed up calls to ``enumerate()`` by using the :pep:`590` ``vectorcall`` -calling convention. Patch by Dong-hee Na. +calling convention. Patch by Donghee Na. .. @@ -396,7 +396,7 @@ Patch by Inada Naoki. .. section: Library Update :class:`~typing.ForwardRef` to support ``|`` operator. Patch by -Dong-hee Na. +Donghee Na. .. @@ -486,7 +486,7 @@ Patch by Joongi Kim. .. section: Library Empty escapechar/quotechar is not allowed when initializing -:class:`csv.Dialect`. Patch by Vajrasky Kok and Dong-hee Na. +:class:`csv.Dialect`. Patch by Vajrasky Kok and Donghee Na. .. @@ -569,7 +569,7 @@ formatting options. .. section: Library Improve error message of :class:`csv.Dialect` when initializing. Patch by -Vajrasky Kok and Dong-hee Na. +Vajrasky Kok and Donghee Na. .. diff --git a/Misc/NEWS.d/3.11.0a3.rst b/Misc/NEWS.d/3.11.0a3.rst index 7fdc191c244849..a96a59115797ee 100644 --- a/Misc/NEWS.d/3.11.0a3.rst +++ b/Misc/NEWS.d/3.11.0a3.rst @@ -615,7 +615,7 @@ Launch GNOME web browsers via gio tool instead of obsolete gvfs-open .. section: Library On Windows, :func:`time.sleep` now uses a waitable timer which supports -high-resolution timers. Patch by Dong-hee Na and Eryk Sun. +high-resolution timers. Patch by Donghee Na and Eryk Sun. .. diff --git a/Misc/NEWS.d/3.11.0a5.rst b/Misc/NEWS.d/3.11.0a5.rst index c28078da8d8339..08d94e82ed8ccf 100644 --- a/Misc/NEWS.d/3.11.0a5.rst +++ b/Misc/NEWS.d/3.11.0a5.rst @@ -127,7 +127,7 @@ Aditya. .. section: Core and Builtins Speed up calls to :meth:`weakref.ref.__call__` by using the :pep:`590` -``vectorcall`` calling convention. Patch by Dong-hee Na. +``vectorcall`` calling convention. Patch by Donghee Na. .. diff --git a/Misc/NEWS.d/3.11.0a6.rst b/Misc/NEWS.d/3.11.0a6.rst index fcec71c6f59da2..974d025c631a45 100644 --- a/Misc/NEWS.d/3.11.0a6.rst +++ b/Misc/NEWS.d/3.11.0a6.rst @@ -382,7 +382,7 @@ involving lots of brackets. Patch by Pablo Galindo. .. section: Core and Builtins :mod:`ctypes` now allocates memory on the stack instead of on the heap to -pass arguments while calling a Python callback function. Patch by Dong-hee +pass arguments while calling a Python callback function. Patch by Donghee Na. .. @@ -441,7 +441,7 @@ Add a missing call to ``va_end()`` in ``Modules/_hashopenssl.c``. .. section: Core and Builtins Use :c:func:`PyObject_Vectorcall` while calling ctypes callback function. -Patch by Dong-hee Na. +Patch by Donghee Na. .. @@ -514,7 +514,7 @@ For performance, use the optimized string-searching implementations from .. section: Library :class:`~http.server.SimpleHTTPRequestHandler` now uses HTML5 grammar. Patch -by Dong-hee Na. +by Donghee Na. .. @@ -941,7 +941,7 @@ uvloop library. Make the :class:`configparser.ConfigParser` constructor raise :exc:`TypeError` if the ``interpolation`` parameter is not of type -:class:`configparser.Interpolation` +:class:`!configparser.Interpolation` .. diff --git a/Misc/NEWS.d/3.11.0a7.rst b/Misc/NEWS.d/3.11.0a7.rst index 94c15f1c1f5237..76699632db223a 100644 --- a/Misc/NEWS.d/3.11.0a7.rst +++ b/Misc/NEWS.d/3.11.0a7.rst @@ -89,7 +89,7 @@ problem. Define :c:macro:`PY_CALL_TRAMPOLINE` to enable call trampolines. .. section: Core and Builtins Some Windows system error codes(>= 10000) are now mapped into the correct -errno and may now raise a subclass of :exc:`OSError`. Patch by Dong-hee Na. +errno and may now raise a subclass of :exc:`OSError`. Patch by Donghee Na. .. @@ -717,7 +717,7 @@ Fix :class:`asyncio.Semaphore` re-aquiring FIFO order. .. nonce: uaEDcI .. section: Library -The :mod:`asynchat`, :mod:`asyncore` and :mod:`smtpd` modules have been +The :mod:`!asynchat`, :mod:`!asyncore` and :mod:`!smtpd` modules have been deprecated since at least Python 3.6. Their documentation and deprecation warnings and have now been updated to note they will removed in Python 3.12 (:pep:`594`). @@ -1038,8 +1038,8 @@ Add optional parameter *dir_fd* in :func:`shutil.rmtree`. .. nonce: AixHW7 .. section: Library -:meth:`~!unittest.TestProgram.usageExit` is marked deprecated, to be removed -in 3.13. +:meth:`!unittest.TestProgram.usageExit` is marked as deprecated, +to be removed in Python 3.13. .. @@ -1324,7 +1324,7 @@ extensions. .. section: Tests A test case for :func:`os.sendfile` is converted from deprecated -:mod:`asyncore` (see :pep:`594`) to :mod:`asyncio`. Patch by Oleg Iarygin. +:mod:`!asyncore` (see :pep:`594`) to :mod:`asyncio`. Patch by Oleg Iarygin. .. @@ -1599,7 +1599,7 @@ Call the public :func:`sys.get_asyncgen_hooks` and .. section: C API Remove private functions ``_PySys_GetObjectId()`` and -``_PySys_SetObjectId()``. Patch by Dong-hee Na. +``_PySys_SetObjectId()``. Patch by Donghee Na. .. diff --git a/Misc/NEWS.d/3.11.0b1.rst b/Misc/NEWS.d/3.11.0b1.rst index 71efc21cbc4a61..a4cdda2cafdb43 100644 --- a/Misc/NEWS.d/3.11.0b1.rst +++ b/Misc/NEWS.d/3.11.0b1.rst @@ -185,7 +185,7 @@ functions leave the current exception unchanged. Patch by Victor Stinner. .. section: Core and Builtins Fix a minor memory leak at exit: release the memory of the -:class:`generic_alias_iterator` type. Patch by Dong-hee Na. +:class:`generic_alias_iterator` type. Patch by Donghee Na. .. @@ -2028,8 +2028,8 @@ https://gitlab.com/warsaw/pynche .. nonce: 3mQ54t .. section: C API -Deprecate the C functions: :c:func:`PySys_SetArgv`, -:c:func:`PySys_SetArgvEx`, :c:func:`PySys_SetPath`. Patch by Victor Stinner. +Deprecate the C functions: :c:func:`!PySys_SetArgv`, +:c:func:`!PySys_SetArgvEx`, :c:func:`!PySys_SetPath`. Patch by Victor Stinner. .. @@ -2068,9 +2068,9 @@ casts when the Python C API is used in C++. Patch by Victor Stinner. .. nonce: Cx-95G .. section: C API -Mark functions as deprecated by :pep:`623`: :c:func:`PyUnicode_AS_DATA`, -:c:func:`PyUnicode_AS_UNICODE`, :c:func:`PyUnicode_GET_DATA_SIZE`, -:c:func:`PyUnicode_GET_SIZE`. Patch by Victor Stinner. +Mark functions as deprecated by :pep:`623`: :c:func:`!PyUnicode_AS_DATA`, +:c:func:`!PyUnicode_AS_UNICODE`, :c:func:`!PyUnicode_GET_DATA_SIZE`, +:c:func:`!PyUnicode_GET_SIZE`. Patch by Victor Stinner. .. diff --git a/Misc/NEWS.d/3.12.0a1.rst b/Misc/NEWS.d/3.12.0a1.rst index 5178f4055e7b8e..f192bf086ed259 100644 --- a/Misc/NEWS.d/3.12.0a1.rst +++ b/Misc/NEWS.d/3.12.0a1.rst @@ -82,7 +82,7 @@ the test failed). .. nonce: eOBh8M .. section: Core and Builtins -Suppress ImportError for invalid query for help() command. Patch by Dong-hee +Suppress ImportError for invalid query for help() command. Patch by Donghee Na. .. @@ -164,7 +164,7 @@ to calculate those doing pointer arithmetic. .. section: Core and Builtins :func:`os.sched_yield` now release the GIL while calling sched_yield(2). -Patch by Dong-hee Na. +Patch by Donghee Na. .. @@ -465,7 +465,7 @@ Remove dead code from ``CALL_FUNCTION_EX`` opcode. .. nonce: VE8-zf .. section: Core and Builtins -:class:`memoryview` now supports half-floats. Patch by Dong-hee Na and +:class:`memoryview` now supports half-floats. Patch by Donghee Na and Antoine Pitrou. .. @@ -857,7 +857,7 @@ code objects could be "deduplicated" during compilation. .. section: Core and Builtins Reduce allocation size of :class:`list` from :meth:`str.split` and -:meth:`str.rsplit`. Patch by Dong-hee Na and Inada Naoki. +:meth:`str.rsplit`. Patch by Donghee Na and Inada Naoki. .. @@ -1462,7 +1462,7 @@ expression, but there's no trailing brace. For example, f"{i=". .. nonce: Jf6gAj .. section: Core and Builtins -Cache the result of :c:func:`PyCode_GetCode` function to restore the O(1) +Cache the result of :c:func:`PyCode_GetCode` function to restore the *O*\ (1) lookup of the :attr:`~types.CodeType.co_code` attribute. .. @@ -1913,7 +1913,7 @@ Stinner. .. nonce: Uxc9al .. section: Library -Allow :mod:`venv` to pass along :envvar:`PYTHON*` variables to ``ensurepip`` +Allow :mod:`venv` to pass along :envvar:`!PYTHON*` variables to ``ensurepip`` and ``pip`` when they do not impact path resolution .. @@ -3617,7 +3617,7 @@ allow access to handlers by name. .. nonce: uw6x5z .. section: Library -The :mod:`smtpd` module was removed per the schedule in :pep:`594`. +The :mod:`!smtpd` module was removed per the schedule in :pep:`594`. .. @@ -3742,7 +3742,7 @@ Fix :func:`ast.unparse` when ``ImportFrom.level`` is None Now :func:`~dis.dis` and :func:`~dis.get_instructions` handle operand values for instructions prefixed by ``EXTENDED_ARG_QUICK``. Patch by Sam Gross and -Dong-hee Na. +Donghee Na. .. @@ -5004,7 +5004,7 @@ Patch by Illia Volochii and Adam Turner. .. section: Build Fix the build process of clang compiler for :program:`_bootstrap_python` if -LTO optimization is applied. Patch by Matthias Görgens and Dong-hee Na. +LTO optimization is applied. Patch by Matthias Görgens and Donghee Na. .. @@ -5024,7 +5024,7 @@ LTO optimization is applied. Patch by Matthias Görgens and Dong-hee Na. .. section: Build CPython now uses the ThinLTO option as the default policy if the Clang -compiler accepts the flag. Patch by Dong-hee Na. +compiler accepts the flag. Patch by Donghee Na. .. @@ -5350,7 +5350,7 @@ in a virtual environment. .. nonce: FbHZuS .. section: Windows -Fix :file:`py.exe` launcher handling of ``-V:/`` option when +Fix :file:`py.exe` launcher handling of :samp:`-V:{}/` option when default preferences have been set in environment variables or configuration files. diff --git a/Misc/NEWS.d/3.12.0a2.rst b/Misc/NEWS.d/3.12.0a2.rst index f781e38665a8ea..dbc743abe8a767 100644 --- a/Misc/NEWS.d/3.12.0a2.rst +++ b/Misc/NEWS.d/3.12.0a2.rst @@ -8,7 +8,7 @@ The IDNA codec decoder used on DNS hostnames by :mod:`socket` or :mod:`asyncio` related name resolution functions no longer involves a quadratic algorithm. This prevents a potential CPU denial of service if an out-of-spec excessive length hostname involving bidirectional characters -were decoded. Some protocols such as :mod:`urllib` http ``3xx`` redirects +were decoded. Some protocols such as :mod:`urllib` http :samp:`3{xx}` redirects potentially allow for an attacker to supply such a name. Individual labels within an IDNA encoded DNS name will now raise an error @@ -111,7 +111,7 @@ back to alternative names ("python", "python."). .. section: Core and Builtins Update :mod:`faulthandler` to emit an error message with the proper -unexpected signal number. Patch by Dong-hee Na. +unexpected signal number. Patch by Donghee Na. .. @@ -695,7 +695,7 @@ Make sure ``patch.dict()`` can be applied on async functions. .. nonce: jUpzF3 .. section: Library -Remove modules :mod:`asyncore` and :mod:`asynchat`, which were deprecated by +Remove modules :mod:`!asyncore` and :mod:`!asynchat`, which were deprecated by :pep:`594`. .. diff --git a/Misc/NEWS.d/3.12.0a3.rst b/Misc/NEWS.d/3.12.0a3.rst index 3e6f8de5d911f2..ce128fd5f80c77 100644 --- a/Misc/NEWS.d/3.12.0a3.rst +++ b/Misc/NEWS.d/3.12.0a3.rst @@ -9,7 +9,7 @@ within a garbage request to be printed to the stderr server log. This is done by changing the :mod:`http.server` :class:`BaseHTTPRequestHandler` ``.log_message`` method to replace control -characters with a ``\xHH`` hex escape before printing. +characters with a :samp:`\\x{HH}` hex escape before printing. .. @@ -153,7 +153,7 @@ to specialize attribute accesses on types that haven't had .. section: Core and Builtins Allow some features of :mod:`syslog` to the main interpreter only. Patch by -Dong-hee Na. +Donghee Na. .. diff --git a/Misc/NEWS.d/3.12.0a4.rst b/Misc/NEWS.d/3.12.0a4.rst index 8951490f41b94c..ce2814bbe2e5ab 100644 --- a/Misc/NEWS.d/3.12.0a4.rst +++ b/Misc/NEWS.d/3.12.0a4.rst @@ -23,10 +23,10 @@ Remove :opcode:`UNARY_POSITIVE`, :opcode:`ASYNC_GEN_WRAP` and .. nonce: D7H6j4 .. section: Core and Builtins -Add new :opcode:`CALL_INSTRINSIC_1` instruction. Remove +Add new :opcode:`CALL_INTRINSIC_1` instruction. Remove :opcode:`IMPORT_STAR`, :opcode:`PRINT_EXPR` and :opcode:`STOPITERATION_ERROR`, replacing them with the -:opcode:`CALL_INSTRINSIC_1` instruction. +:opcode:`CALL_INTRINSIC_1` instruction. .. @@ -147,8 +147,8 @@ clinic. .. nonce: yRWQ1y .. section: Core and Builtins -Improve the output of ``co_lines`` by emitting only one entry for each line -range. +Improve the output of :meth:`codeobject.co_lines` by emitting only one entry +for each line range. .. @@ -676,7 +676,7 @@ parameter names in the C implementation. Patch by Alex Waygood. .. section: Library Update :exc:`~urllib.error.HTTPError` to be initialized properly, even if -the ``fp`` is ``None``. Patch by Dong-hee Na. +the ``fp`` is ``None``. Patch by Donghee Na. .. diff --git a/Misc/NEWS.d/3.12.0a5.rst b/Misc/NEWS.d/3.12.0a5.rst index f6f8de46cf70d9..8cf90b0e9cde46 100644 --- a/Misc/NEWS.d/3.12.0a5.rst +++ b/Misc/NEWS.d/3.12.0a5.rst @@ -38,7 +38,7 @@ would get out of sync, causing inconsistent behavior and crashes. .. section: Core and Builtins Fix wrong lineno in exception message on :keyword:`continue` or -:keyword:`break` which are not in a loop. Patch by Dong-hee Na. +:keyword:`break` which are not in a loop. Patch by Donghee Na. .. @@ -48,7 +48,7 @@ Fix wrong lineno in exception message on :keyword:`continue` or .. section: Core and Builtins Fix :func:`~unicodedata.is_normalized` to properly handle the UCD 3.2.0 -cases. Patch by Dong-hee Na. +cases. Patch by Donghee Na. .. @@ -507,7 +507,7 @@ inheritance. .. section: Build Update BOLT configration not to use depreacted usage of ``--split -functions``. Patch by Dong-hee Na. +functions``. Patch by Donghee Na. .. diff --git a/Misc/NEWS.d/3.12.0a6.rst b/Misc/NEWS.d/3.12.0a6.rst index 07967028bdee70..5bd600cd8b6fc0 100644 --- a/Misc/NEWS.d/3.12.0a6.rst +++ b/Misc/NEWS.d/3.12.0a6.rst @@ -220,7 +220,7 @@ access of ``builtins.__dict__`` keys mutates the iter object. .. section: Core and Builtins Update :mod:`tracemalloc` to handle presize of object properly. Patch by -Dong-hee Na. +Donghee Na. .. diff --git a/Misc/NEWS.d/3.12.0a7.rst b/Misc/NEWS.d/3.12.0a7.rst index 1ef81747558857..f22050b0dc377b 100644 --- a/Misc/NEWS.d/3.12.0a7.rst +++ b/Misc/NEWS.d/3.12.0a7.rst @@ -429,7 +429,7 @@ an awaitable object. Patch by Kumar Aditya. Speed up setting or deleting mutable attributes on non-dataclass subclasses of frozen dataclasses. Due to the implementation of ``__setattr__`` and ``__delattr__`` for frozen dataclasses, this previously had a time -complexity of ``O(n)``. It now has a time complexity of ``O(1)``. +complexity of *O*\ (*n*). It now has a time complexity of *O*\ (1). .. diff --git a/Misc/NEWS.d/3.12.0b1.rst b/Misc/NEWS.d/3.12.0b1.rst index 652b706880fb92..007a6ad4ffd4d4 100644 --- a/Misc/NEWS.d/3.12.0b1.rst +++ b/Misc/NEWS.d/3.12.0b1.rst @@ -213,7 +213,7 @@ attribute. .. section: Core and Builtins Reduce object creation while calling callback function from gc. Patch by -Dong-hee Na. +Donghee Na. .. @@ -464,7 +464,7 @@ unpickled. .. section: Core and Builtins Migrate :meth:`~ssl.SSLContext.set_ecdh_curve` method not to use deprecated -OpenSSL APIs. Patch by Dong-hee Na. +OpenSSL APIs. Patch by Donghee Na. .. @@ -880,7 +880,7 @@ Update the ``repr`` of :class:`typing.Unpack` according to :pep:`692`. .. section: Library Make :mod:`dis` display the names of the args for -:opcode:`CALL_INTRINSIC_*`. +:opcode:`!CALL_INTRINSIC_*`. .. @@ -2073,7 +2073,7 @@ Define ``.PHONY`` / virtual make targets consistently and properly. .. nonce: -W9BJS .. section: Build -Add gcc fallback of mkfifoat/mknodat for macOS. Patch by Dong-hee Na. +Add gcc fallback of mkfifoat/mknodat for macOS. Patch by Donghee Na. .. @@ -2372,7 +2372,7 @@ Add a new C-API function to eagerly assign a version tag to a PyTypeObject: .. section: C API :c:func:`PyObject_GC_Resize` should calculate preheader size if needed. -Patch by Dong-hee Na. +Patch by Donghee Na. .. diff --git a/Misc/NEWS.d/3.13.0a1.rst b/Misc/NEWS.d/3.13.0a1.rst new file mode 100644 index 00000000000000..102bddcee5c5c2 --- /dev/null +++ b/Misc/NEWS.d/3.13.0a1.rst @@ -0,0 +1,6748 @@ +.. date: 2023-08-22-17-39-12 +.. gh-issue: 108310 +.. nonce: fVM3sg +.. release date: 2023-10-13 +.. section: Security + +Fixed an issue where instances of :class:`ssl.SSLSocket` were vulnerable to +a bypass of the TLS handshake and included protections (like certificate +verification) and treating sent unencrypted data as if it were +post-handshake TLS encrypted data. Security issue reported as +`CVE-2023-40217 +`_ by Aapo +Oksman. Patch by Gregory P. Smith. + +.. + +.. date: 2023-08-05-03-51-05 +.. gh-issue: 107774 +.. nonce: VPjaTR +.. section: Security + +PEP 669 specifies that ``sys.monitoring.register_callback`` will generate an +audit event. Pre-releases of Python 3.12 did not generate the audit event. +This is now fixed. + +.. + +.. date: 2023-06-13-20-52-24 +.. gh-issue: 102988 +.. nonce: Kei7Vf +.. section: Security + +Reverted the :mod:`email.utils` security improvement change released in +3.12beta4 that unintentionally caused :mod:`email.utils.getaddresses` to +fail to parse email addresses with a comma in the quoted name field. See +:gh:`106669`. + +.. + +.. date: 2023-05-24-09-29-08 +.. gh-issue: 99108 +.. nonce: hwS2cr +.. section: Security + +Refresh our new HACL* built-in :mod:`hashlib` code from upstream. Built-in +SHA2 should be faster and an issue with SHA3 on 32-bit platforms is fixed. + +.. + +.. date: 2023-03-07-21-46-29 +.. gh-issue: 102509 +.. nonce: 5ouaH_ +.. section: Security + +Start initializing ``ob_digit`` during creation of :c:type:`PyLongObject` +objects. Patch by Illia Volochii. + +.. + +.. date: 2023-10-12-15-03-24 +.. gh-issue: 110782 +.. nonce: EqzIzi +.. section: Core and Builtins + +Fix crash when :class:`typing.TypeVar` is constructed with a keyword +argument. Patch by Jelle Zijlstra. + +.. + +.. date: 2023-10-12-06-32-25 +.. gh-issue: 110752 +.. nonce: FYfI0h +.. section: Core and Builtins + +Reset ``ceval.eval_breaker`` in :func:`interpreter_clear` + +.. + +.. date: 2023-10-11-16-56-54 +.. gh-issue: 110721 +.. nonce: afcSsH +.. section: Core and Builtins + +Use the :mod:`traceback` implementation for the default +:c:func:`PyErr_Display` functionality. Patch by Pablo Galindo + +.. + +.. date: 2023-10-11-13-46-14 +.. gh-issue: 110696 +.. nonce: J9kSzr +.. section: Core and Builtins + +Fix incorrect error message for invalid argument unpacking. Patch by Pablo +Galindo + +.. + +.. date: 2023-10-11-12-48-03 +.. gh-issue: 104169 +.. nonce: bPoX8u +.. section: Core and Builtins + +Split the tokenizer into two separate directories: - One part includes the +actual lexeme producing logic and lives in ``Parser/lexer``. - The second +part wraps the lexer according to the different tokenization modes we have +(string, utf-8, file, interactive, readline) and lives in +``Parser/tokenizer``. + +.. + +.. date: 2023-10-11-11-39-22 +.. gh-issue: 110688 +.. nonce: lB6Q7t +.. section: Core and Builtins + +Remove undocumented ``test_c_api`` method from :class:`set`, which was only +defined for testing purposes under ``Py_DEBUG``. Now we have proper CAPI +tests. + +.. + +.. date: 2023-10-10-00-49-35 +.. gh-issue: 104584 +.. nonce: z94TuJ +.. section: Core and Builtins + +Fix a reference leak when running with :envvar:`PYTHONUOPS` or :option:`-X +uops <-X>` enabled. + +.. + +.. date: 2023-10-08-20-08-54 +.. gh-issue: 110514 +.. nonce: Q9bdRU +.. section: Core and Builtins + +Add ``PY_THROW`` to :func:`sys.setprofile` events + +.. + +.. date: 2023-10-06-22-30-25 +.. gh-issue: 110489 +.. nonce: rI2n8A +.. section: Core and Builtins + +Optimise :func:`math.ceil` when the input is exactly a float, resulting in +about a 10% improvement. + +.. + +.. date: 2023-10-06-12-00-43 +.. gh-issue: 110455 +.. nonce: 8BjNGg +.. section: Core and Builtins + +Guard ``assert(tstate->thread_id > 0)`` with ``#ifndef HAVE_PTHREAD_STUBS``. +This allows for for pydebug builds to work under WASI which (currently) +lacks thread support. + +.. + +.. date: 2023-10-03-23-26-18 +.. gh-issue: 110309 +.. nonce: Y8nDOF +.. section: Core and Builtins + +Remove unnecessary empty constant nodes in the ast of f-string specs. + +.. + +.. date: 2023-10-03-11-43-48 +.. gh-issue: 110259 +.. nonce: ka93x5 +.. section: Core and Builtins + +Correctly identify the format spec in f-strings (with single or triple +quotes) that have multiple lines in the expression part and include a +formatting spec. Patch by Pablo Galindo + +.. + +.. date: 2023-10-02-23-17-08 +.. gh-issue: 110237 +.. nonce: _Xub0z +.. section: Core and Builtins + +Fix missing error checks for calls to ``PyList_Append`` in +``_PyEval_MatchClass``. + +.. + +.. date: 2023-10-01-02-58-00 +.. gh-issue: 110164 +.. nonce: z7TMCq +.. section: Core and Builtins + +regrtest: If the ``SOURCE_DATE_EPOCH`` environment variable is defined, +regrtest now disables tests randomization. Patch by Victor Stinner. + +.. + +.. date: 2023-09-27-21-35-49 +.. gh-issue: 109889 +.. nonce: t5hIRT +.. section: Core and Builtins + +Fix the compiler's redundant NOP detection algorithm to skip over NOPs with +no line number when looking for the next instruction's lineno. + +.. + +.. date: 2023-09-27-18-01-06 +.. gh-issue: 109853 +.. nonce: coQQiL +.. section: Core and Builtins + +``sys.path[0]`` is now set correctly for subinterpreters. + +.. + +.. date: 2023-09-26-21-26-54 +.. gh-issue: 109923 +.. nonce: WO3CHi +.. section: Core and Builtins + +Set line number on the ``POP_TOP`` that follows a ``RETURN_GENERATOR``. + +.. + +.. date: 2023-09-26-14-00-25 +.. gh-issue: 105716 +.. nonce: SUJkW1 +.. section: Core and Builtins + +Subinterpreters now correctly handle the case where they have threads +running in the background. Before, such threads would interfere with +cleaning up and destroying them, as well as prevent running another script. + +.. + +.. date: 2023-09-26-03-46-55 +.. gh-issue: 109369 +.. nonce: OJbxbF +.. section: Core and Builtins + +The internal eval_breaker and supporting flags, plus the monitoring version +have been merged into a single atomic integer to speed up checks. + +.. + +.. date: 2023-09-25-14-28-14 +.. gh-issue: 109823 +.. nonce: kbVTKF +.. section: Core and Builtins + +Fix bug where compiler does not adjust labels when removing an empty basic +block which is a jump target. + +.. + +.. date: 2023-09-25-09-24-10 +.. gh-issue: 109793 +.. nonce: zFQBkv +.. section: Core and Builtins + +The main thread no longer exits prematurely when a subinterpreter is cleaned +up during runtime finalization. The bug was a problem particularly because, +when triggered, the Python process would always return with a 0 exitcode, +even if it failed. + +.. + +.. date: 2023-09-22-13-38-17 +.. gh-issue: 109719 +.. nonce: fx5OTz +.. section: Core and Builtins + +Fix missing jump target labels when compiler reorders cold/warm blocks. + +.. + +.. date: 2023-09-22-01-44-53 +.. gh-issue: 109595 +.. nonce: fVINgD +.. section: Core and Builtins + +Add :option:`-X cpu_count <-X>` command line option to override return +results of :func:`os.cpu_count` and :func:`os.process_cpu_count`. This +option is useful for users who need to limit CPU resources of a container +system without having to modify the container (application code). Patch by +Donghee Na. + +.. + +.. date: 2023-09-20-23-04-15 +.. gh-issue: 109627 +.. nonce: xxe7De +.. section: Core and Builtins + +Fix bug where the compiler does not assign a new jump target label to a +duplicated small exit block. + +.. + +.. date: 2023-09-20-13-18-08 +.. gh-issue: 109596 +.. nonce: RG0K2G +.. section: Core and Builtins + +Fix some tokens in the grammar that were incorrectly marked as soft +keywords. Also fix some repeated rule names and ensure that repeated rules +are not allowed. Patch by Pablo Galindo + +.. + +.. date: 2023-09-18-15-35-08 +.. gh-issue: 109496 +.. nonce: Kleoz3 +.. section: Core and Builtins + +On a Python built in debug mode, :c:func:`Py_DECREF()` now calls +``_Py_NegativeRefcount()`` if the object is a dangling pointer to +deallocated memory: memory filled with ``0xDD`` "dead byte" by the debug +hook on memory allocators. The fix is to check the reference count *before* +checking for ``_Py_IsImmortal()``. Patch by Victor Stinner. + +.. + +.. date: 2023-09-14-20-15-57 +.. gh-issue: 107265 +.. nonce: qHZL_6 +.. section: Core and Builtins + +Deopt opcodes hidden by the executor when base opcode is needed + +.. + +.. date: 2023-09-13-21-04-04 +.. gh-issue: 109371 +.. nonce: HPEJr8 +.. section: Core and Builtins + +Deopted instructions correctly for tool initialization and modified the +incorrect assertion in instrumentation, when a previous tool already sets +INSTRUCTION events + +.. + +.. date: 2023-09-13-19-16-51 +.. gh-issue: 105658 +.. nonce: z2nR2u +.. section: Core and Builtins + +Fix bug where the line trace of an except block ending with a conditional +includes an excess event with the line of the conditional expression. + +.. + +.. date: 2023-09-13-08-42-45 +.. gh-issue: 109219 +.. nonce: UiN8sc +.. section: Core and Builtins + +Fix compiling type param scopes that use a name which is also free in an +inner scope. + +.. + +.. date: 2023-09-12-16-00-42 +.. gh-issue: 109351 +.. nonce: kznGeR +.. section: Core and Builtins + +Fix crash when compiling an invalid AST involving a named (walrus) +expression. + +.. + +.. date: 2023-09-12-15-45-49 +.. gh-issue: 109341 +.. nonce: 4V5bkm +.. section: Core and Builtins + +Fix crash when compiling an invalid AST involving a :class:`ast.TypeAlias`. + +.. + +.. date: 2023-09-11-15-51-55 +.. gh-issue: 109195 +.. nonce: iwxmuo +.. section: Core and Builtins + +Fix source location for the ``LOAD_*`` instruction preceding a +``LOAD_SUPER_ATTR`` to load the ``super`` global (or shadowing variable) so +that it encompasses only the name ``super`` and not the following +parentheses. + +.. + +.. date: 2023-09-11-15-11-03 +.. gh-issue: 109256 +.. nonce: 6mfhvF +.. section: Core and Builtins + +Opcode IDs for specialized opcodes are allocated in their own range to +improve stability of the IDs for the 'real' opcodes. + +.. + +.. date: 2023-09-11-12-41-42 +.. gh-issue: 109216 +.. nonce: 60QOSb +.. section: Core and Builtins + +Fix possible memory leak in :opcode:`BUILD_MAP`. + +.. + +.. date: 2023-09-10-18-53-55 +.. gh-issue: 109207 +.. nonce: Fei8bY +.. section: Core and Builtins + +Fix a SystemError in ``__repr__`` of symtable entry object. + +.. + +.. date: 2023-09-09-21-17-18 +.. gh-issue: 109179 +.. nonce: ZR8qs2 +.. section: Core and Builtins + +Fix bug where the C traceback display drops notes from :exc:`SyntaxError`. + +.. + +.. date: 2023-09-09-12-49-46 +.. gh-issue: 109118 +.. nonce: gx0X4h +.. section: Core and Builtins + +Disallow nested scopes (lambdas, generator expressions, and comprehensions) +within PEP 695 annotation scopes that are nested within classes. + +.. + +.. date: 2023-09-08-18-31-04 +.. gh-issue: 109156 +.. nonce: KK1EXI +.. section: Core and Builtins + +Add tests for de-instrumenting instructions while keeping the +instrumentation for lines + +.. + +.. date: 2023-09-08-01-50-41 +.. gh-issue: 109114 +.. nonce: adqgtb +.. section: Core and Builtins + +Relax the detection of the error message for invalid lambdas inside +f-strings to not search for arbitrary replacement fields to avoid false +positives. Patch by Pablo Galindo + +.. + +.. date: 2023-09-07-20-52-27 +.. gh-issue: 105848 +.. nonce: p799D1 +.. section: Core and Builtins + +Add a new :opcode:`CALL_KW` opcode, used for calls containing keyword +arguments. Also, fix a possible crash when jumping over method calls in a +debugger. + +.. + +.. date: 2023-09-07-18-49-01 +.. gh-issue: 109052 +.. nonce: TBU4nC +.. section: Core and Builtins + +Use the base opcode when comparing code objects to avoid interference from +instrumentation + +.. + +.. date: 2023-09-07-18-24-42 +.. gh-issue: 109118 +.. nonce: yPXRAe +.. section: Core and Builtins + +Fix interpreter crash when a NameError is raised inside the type parameters +of a generic class. + +.. + +.. date: 2023-09-07-16-05-36 +.. gh-issue: 88943 +.. nonce: rH_X3W +.. section: Core and Builtins + +Improve syntax error for non-ASCII character that follows a numerical +literal. It now points on the invalid non-ASCII character, not on the valid +numerical literal. + +.. + +.. date: 2023-09-06-22-50-25 +.. gh-issue: 108976 +.. nonce: MUKaIJ +.. section: Core and Builtins + +Fix crash that occurs after de-instrumenting a code object in a monitoring +callback. + +.. + +.. date: 2023-09-06-13-28-42 +.. gh-issue: 108732 +.. nonce: I6DkEQ +.. section: Core and Builtins + +Make iteration variables of module- and class-scoped comprehensions visible +to pdb and other tools that use ``frame.f_locals`` again. + +.. + +.. date: 2023-09-05-20-52-17 +.. gh-issue: 108959 +.. nonce: 6z45Sy +.. section: Core and Builtins + +Fix caret placement for error locations for subscript and binary operations +that involve non-semantic parentheses and spaces. Patch by Pablo Galindo + +.. + +.. date: 2023-09-05-11-31-27 +.. gh-issue: 104584 +.. nonce: IRSXA2 +.. section: Core and Builtins + +Fix a crash when running with :envvar:`PYTHONUOPS` or :option:`-X uops <-X>` +enabled and an error occurs during optimization. + +.. + +.. date: 2023-08-31-21-29-28 +.. gh-issue: 108727 +.. nonce: blNRGM +.. section: Core and Builtins + +Define ``tp_dealloc`` for ``CounterOptimizer_Type``. This fixes a segfault +on deallocation. + +.. + +.. date: 2023-08-30-15-41-47 +.. gh-issue: 108520 +.. nonce: u0ZGP_ +.. section: Core and Builtins + +Fix :meth:`multiprocessing.synchronize.SemLock.__setstate__` to properly +initialize :attr:`multiprocessing.synchronize.SemLock._is_fork_ctx`. This +fixes a regression when passing a SemLock accross nested processes. + +Rename :attr:`multiprocessing.synchronize.SemLock.is_fork_ctx` to +:attr:`multiprocessing.synchronize.SemLock._is_fork_ctx` to avoid exposing +it as public API. + +.. + +.. date: 2023-08-29-17-53-12 +.. gh-issue: 108654 +.. nonce: jbkDVo +.. section: Core and Builtins + +Restore locals shadowed by an inlined comprehension if the comprehension +raises an exception. + +.. + +.. date: 2023-08-28-22-22-15 +.. gh-issue: 108488 +.. nonce: e8-fxg +.. section: Core and Builtins + +Change the initialization of inline cache entries so that the cache entry +for ``JUMP_BACKWARD`` is initialized to zero, instead of the +``adaptive_counter_warmup()`` value used for all other instructions. This +counter, unique among instructions, counts up from zero. + +.. + +.. date: 2023-08-28-03-38-28 +.. gh-issue: 108716 +.. nonce: HJBPwt +.. section: Core and Builtins + +Turn off deep-freezing of code objects. Modules are still frozen, so that a +file system search is not needed for common modules. + +.. + +.. date: 2023-08-26-10-36-45 +.. gh-issue: 108614 +.. nonce: wl5l-W +.. section: Core and Builtins + +Add RESUME_CHECK instruction, to avoid having to handle instrumentation, +signals, and contexts switches in the tier 2 execution engine. + +.. + +.. date: 2023-08-26-04-31-01 +.. gh-issue: 108487 +.. nonce: 1Gbr9k +.. section: Core and Builtins + +Move an assert that would cause a spurious crash in a devious case that +should only trigger deoptimization. + +.. + +.. date: 2023-08-25-14-51-06 +.. gh-issue: 106176 +.. nonce: D1EA2a +.. section: Core and Builtins + +Use a ``WeakValueDictionary`` to track the lists containing the modules each +thread is currently importing. This helps avoid a reference leak from +keeping the list around longer than necessary. Weakrefs are used as GC can't +interrupt the cleanup. + +.. + +.. date: 2023-08-23-14-54-15 +.. gh-issue: 105481 +.. nonce: 40q-c4 +.. section: Core and Builtins + +The regen-opcode build stage was removed and its work is now done in +regen-cases. + +.. + +.. date: 2023-08-21-21-13-30 +.. gh-issue: 107901 +.. nonce: hszvdk +.. section: Core and Builtins + +Fix missing line number on :opcode:`JUMP_BACKWARD` at the end of a for loop. + +.. + +.. date: 2023-08-18-18-21-27 +.. gh-issue: 108113 +.. nonce: 1h0poE +.. section: Core and Builtins + +The :func:`compile` built-in can now accept a new flag, +``ast.PyCF_OPTIMIZED_AST``, which is similar to ``ast.PyCF_ONLY_AST`` except +that the returned ``AST`` is optimized according to the value of the +``optimize`` argument. + +:func:`ast.parse` now accepts an optional argument ``optimize`` which is +passed on to the :func:`compile` built-in. This makes it possible to obtain +an optimized ``AST``. + +.. + +.. date: 2023-08-15-13-06-05 +.. gh-issue: 107971 +.. nonce: lPbx04 +.. section: Core and Builtins + +Opcode IDs are generated from bytecodes.c instead of being hard coded in +opcode.py. + +.. + +.. date: 2023-08-15-11-09-50 +.. gh-issue: 107944 +.. nonce: zQLp3j +.. section: Core and Builtins + +Improve error message for function calls with bad keyword arguments. Patch +by Pablo Galindo + +.. + +.. date: 2023-08-13-17-18-22 +.. gh-issue: 108390 +.. nonce: TkBccC +.. section: Core and Builtins + +Raise an exception when setting a non-local event (``RAISE``, +``EXCEPTION_HANDLED``, etc.) in ``sys.monitoring.set_local_events``. + +Fixes crash when tracing in recursive calls to Python classes. + +.. + +.. date: 2023-08-11-16-18-19 +.. gh-issue: 108035 +.. nonce: e2msOD +.. section: Core and Builtins + +Remove the ``_PyCFrame`` struct, moving the pointer to the current +intepreter frame back to the threadstate, as it was for 3.10 and earlier. +The ``_PyCFrame`` existed as a performance optimization for tracing. Since +PEP 669 has been implemented, this optimization no longer applies. + +.. + +.. date: 2023-08-10-17-36-27 +.. gh-issue: 91051 +.. nonce: LfaeNW +.. section: Core and Builtins + +Fix abort / segfault when using all eight type watcher slots, on platforms +where ``char`` is signed by default. + +.. + +.. date: 2023-08-10-00-00-48 +.. gh-issue: 106581 +.. nonce: o7zDty +.. section: Core and Builtins + +Fix possible assertion failures and missing instrumentation events when +:envvar:`PYTHONUOPS` or :option:`-X uops <-X>` is enabled. + +.. + +.. date: 2023-08-09-15-05-27 +.. gh-issue: 107526 +.. nonce: PB32z- +.. section: Core and Builtins + +Revert converting ``vars``, ``dir``, ``next``, ``getattr``, and ``iter`` to +argument clinic. + +.. + +.. date: 2023-08-09-08-31-20 +.. gh-issue: 84805 +.. nonce: 7JRWua +.. section: Core and Builtins + +Autogenerate signature for :c:macro:`METH_NOARGS` and :c:macro:`METH_O` +extension functions. + +.. + +.. date: 2023-08-08-02-46-46 +.. gh-issue: 107758 +.. nonce: R5kyBI +.. section: Core and Builtins + +Make the ``dump_stack()`` routine used by the ``lltrace`` feature (low-level +interpreter debugging) robust against recursion by ensuring that it never +calls a ``__repr__`` method implemented in Python. Also make the similar +output for Tier-2 uops appear on ``stdout`` (instead of ``stderr``), to +match the ``lltrace`` code in ceval.c. + +.. + +.. date: 2023-08-05-15-45-07 +.. gh-issue: 107659 +.. nonce: QgtQ5M +.. section: Core and Builtins + +Add docstrings for :func:`ctypes.pointer` and :func:`ctypes.POINTER`. + +.. + +.. date: 2023-08-05-09-06-56 +.. gh-issue: 105848 +.. nonce: Drc-1- +.. section: Core and Builtins + +Modify the bytecode so that the actual callable for a :opcode:`CALL` is at a +consistent position on the stack (regardless of whether or not +bound-method-calling optimizations are active). + +.. + +.. date: 2023-08-05-04-47-18 +.. gh-issue: 107674 +.. nonce: 0sYhR2 +.. section: Core and Builtins + +Fixed performance regression in ``sys.settrace``. + +.. + +.. date: 2023-08-04-21-25-26 +.. gh-issue: 107724 +.. nonce: EbBXMr +.. section: Core and Builtins + +In pre-release versions of 3.12, up to rc1, the sys.monitoring callback +function for the ``PY_THROW`` event was missing the third, exception +argument. That is now fixed. + +.. + +.. date: 2023-08-03-13-38-14 +.. gh-issue: 84436 +.. nonce: gl1wHx +.. section: Core and Builtins + +Skip reference count modifications for many known immortal objects. + +.. + +.. date: 2023-08-03-11-13-09 +.. gh-issue: 107596 +.. nonce: T3yPGI +.. section: Core and Builtins + +Specialize subscripting :class:`str` objects by :class:`int` indexes. + +.. + +.. date: 2023-08-02-12-24-51 +.. gh-issue: 107080 +.. nonce: PNolFU +.. section: Core and Builtins + +Trace refs builds (``--with-trace-refs``) were crashing when used with +isolated subinterpreters. The problematic global state has been isolated to +each interpreter. Other fixing the crashes, this change does not affect +users. + +.. + +.. date: 2023-08-02-09-55-21 +.. gh-issue: 107557 +.. nonce: P1z-in +.. section: Core and Builtins + +Generate the cases needed for the barebones tier 2 abstract interpreter for +optimization passes in CPython. + +.. + +.. date: 2023-08-01-09-41-36 +.. gh-issue: 106608 +.. nonce: OFZogw +.. section: Core and Builtins + +Make ``_PyUOpExecutorObject`` variable length. + +.. + +.. date: 2023-07-30-18-05-11 +.. gh-issue: 100964 +.. nonce: HluhBJ +.. section: Core and Builtins + +Clear generators' exception state after ``return`` to break reference +cycles. + +.. + +.. date: 2023-07-30-14-18-49 +.. gh-issue: 107455 +.. nonce: Es53l7 +.. section: Core and Builtins + +Improve error messages when converting an incompatible type to +:class:`ctypes.c_char_p`, :class:`ctypes.c_wchar_p` and +:class:`ctypes.c_void_p`. + +.. + +.. date: 2023-07-30-05-20-16 +.. gh-issue: 107263 +.. nonce: q0IU2M +.. section: Core and Builtins + +Increase C recursion limit for functions other than the main interpreter +from 800 to 1500. This should allow functions like ``list.__repr__`` and +``json.dumps`` to handle all the inputs that they could prior to 3.12 + +.. + +.. date: 2023-07-29-22-01-30 +.. gh-issue: 104584 +.. nonce: tINuoA +.. section: Core and Builtins + +Fix an issue which caused incorrect inline caches to be read when running +with :envvar:`PYTHONUOPS` or :option:`-X uops <-X>` enabled. + +.. + +.. date: 2023-07-27-11-47-29 +.. gh-issue: 104432 +.. nonce: oGHF-z +.. section: Core and Builtins + +Fix potential unaligned memory access on C APIs involving returned sequences +of ``char *`` pointers within the :mod:`grp` and :mod:`socket` modules. +These were revealed using a ``-fsaniziter=alignment`` build on ARM macOS. +Patch by Christopher Chavez. + +.. + +.. date: 2023-07-27-11-18-04 +.. gh-issue: 106078 +.. nonce: WEy2Yn +.. section: Core and Builtins + +Isolate :mod:`!_decimal` (apply :pep:`687`). Patch by Charlie Zhao. + +.. + +.. date: 2023-07-26-21-28-06 +.. gh-issue: 106898 +.. nonce: 8Wjuiv +.. section: Core and Builtins + +Add the exception as the third argument to ``PY_UNIND`` callbacks in +``sys.monitoring``. This makes the ``PY_UNWIND`` callback consistent with +the other exception hanlding callbacks. + +.. + +.. date: 2023-07-26-18-53-34 +.. gh-issue: 106895 +.. nonce: DdEwV8 +.. section: Core and Builtins + +Raise a ``ValueError`` when a monitoring callback funtion returns +``DISABLE`` for events that cannot be disabled locally. + +.. + +.. date: 2023-07-26-12-18-10 +.. gh-issue: 106897 +.. nonce: EsGurc +.. section: Core and Builtins + +Add a ``RERAISE`` event to ``sys.monitoring``, which occurs when an +exception is reraise, either explicitly by a plain ``raise`` statement, or +implicitly in an ``except`` or ``finally`` block. + +.. + +.. date: 2023-07-25-22-35-35 +.. gh-issue: 77377 +.. nonce: EHAbXx +.. section: Core and Builtins + +Ensure that multiprocessing synchronization objects created in a fork +context are not sent to a different process created in a spawn context. This +changes a segfault into an actionable RuntimeError in the parent process. + +.. + +.. date: 2023-07-25-15-29-26 +.. gh-issue: 106931 +.. nonce: kKU1le +.. section: Core and Builtins + +Statically allocated string objects are now interned globally instead of +per-interpreter. This fixes a situation where such a string would only be +interned in a single interpreter. Normal string objects are unaffected. + +.. + +.. date: 2023-07-24-11-11-41 +.. gh-issue: 104621 +.. nonce: vM8Y_l +.. section: Core and Builtins + +Unsupported modules now always fail to be imported. + +.. + +.. date: 2023-07-23-21-16-54 +.. gh-issue: 107122 +.. nonce: VNuNcq +.. section: Core and Builtins + +Add :meth:`dbm.ndbm.ndbm.clear` to :mod:`dbm.ndbm`. Patch By Donghee Na. + +.. + +.. date: 2023-07-23-13-07-34 +.. gh-issue: 107122 +.. nonce: 9HFUyb +.. section: Core and Builtins + +Add :meth:`dbm.gnu.gdbm.clear` to :mod:`dbm.gnu`. Patch By Donghee Na. + +.. + +.. date: 2023-07-22-14-35-38 +.. gh-issue: 107015 +.. nonce: Ghp58t +.. section: Core and Builtins + +The ASYNC and AWAIT tokens are removed from the Grammar, which removes the +posibility of making ``async`` and ``await`` soft keywords when using +``feature_version<7`` in :func:`ast.parse`. + +.. + +.. date: 2023-07-21-14-37-48 +.. gh-issue: 106917 +.. nonce: 1jWp_m +.. section: Core and Builtins + +Fix classmethod-style :func:`super` method calls (i.e., where the second +argument to :func:`super`, or the implied second argument drawn from +``self/cls`` in the case of zero-arg super, is a type) when the target of +the call is not a classmethod. + +.. + +.. date: 2023-07-20-15-15-57 +.. gh-issue: 105699 +.. nonce: DdqHFg +.. section: Core and Builtins + +Python no longer crashes due an infrequent race when initialzing +per-interpreter interned strings. The crash would manifest when the +interpreter was finalized. + +.. + +.. date: 2023-07-20-12-21-37 +.. gh-issue: 105699 +.. nonce: 08ywGV +.. section: Core and Builtins + +Python no longer crashes due to an infrequent race in setting +``Py_FileSystemDefaultEncoding`` and ``Py_FileSystemDefaultEncodeErrors`` +(both deprecated), when simultaneously initializing two isolated +subinterpreters. Now they are only set during runtime initialization. + +.. + +.. date: 2023-07-20-01-15-58 +.. gh-issue: 106908 +.. nonce: cDmcVI +.. section: Core and Builtins + +Fix various hangs, reference leaks, test failures, and tracing/introspection +bugs when running with :envvar:`PYTHONUOPS` or :option:`-X uops <-X>` +enabled. + +.. + +.. date: 2023-07-18-16-13-51 +.. gh-issue: 106092 +.. nonce: bObgRM +.. section: Core and Builtins + +Fix a segmentation fault caused by a use-after-free bug in ``frame_dealloc`` +when the trashcan delays the deallocation of a ``PyFrameObject``. + +.. + +.. date: 2023-07-16-07-55-19 +.. gh-issue: 106485 +.. nonce: wPb1bH +.. section: Core and Builtins + +Reduce the number of materialized instances dictionaries by dematerializing +them when possible. + +.. + +.. date: 2023-07-13-15-59-07 +.. gh-issue: 106719 +.. nonce: jmVrsv +.. section: Core and Builtins + +No longer suppress arbitrary errors in the ``__annotations__`` getter and +setter in the type and module types. + +.. + +.. date: 2023-07-13-14-55-45 +.. gh-issue: 106723 +.. nonce: KsMufQ +.. section: Core and Builtins + +Propagate ``frozen_modules`` to multiprocessing spawned process +interpreters. + +.. + +.. date: 2023-07-12-11-18-55 +.. gh-issue: 104909 +.. nonce: DRUsuh +.. section: Core and Builtins + +Split :opcode:`LOAD_ATTR_INSTANCE_VALUE` into micro-ops. + +.. + +.. date: 2023-07-12-10-48-08 +.. gh-issue: 104909 +.. nonce: sWjcr2 +.. section: Core and Builtins + +Split :opcode:`LOAD_GLOBAL` specializations into micro-ops. + +.. + +.. date: 2023-07-10-15-30-45 +.. gh-issue: 106597 +.. nonce: WAZ14y +.. section: Core and Builtins + +A new debug structure of offsets has been added to the ``_PyRuntimeState`` +that will help out-of-process debuggers and profilers to obtain the offsets +to relevant interpreter structures in a way that is agnostic of how Python +was compiled and that doesn't require copying the headers. Patch by Pablo +Galindo + +.. + +.. date: 2023-07-06-22-46-05 +.. gh-issue: 106487 +.. nonce: u3KfAD +.. section: Core and Builtins + +Allow the *count* argument of :meth:`str.replace` to be a keyword. Patch by +Hugo van Kemenade. + +.. + +.. date: 2023-07-06-00-35-44 +.. gh-issue: 96844 +.. nonce: kwvoS- +.. section: Core and Builtins + +Improve error message of :meth:`list.remove`. Patch by Donghee Na. + +.. + +.. date: 2023-07-04-20-42-54 +.. gh-issue: 81283 +.. nonce: hfh_MD +.. section: Core and Builtins + +Compiler now strips indents from docstrings. It reduces ``pyc`` file size 5% +when the module is heavily documented. This change affects to ``__doc__`` so +tools like doctest will be affected. + +.. + +.. date: 2023-07-04-09-51-45 +.. gh-issue: 106396 +.. nonce: DmYp7x +.. section: Core and Builtins + +When the format specification of an f-string expression is empty, the parser +now generates an empty :class:`ast.JoinedStr` node for it instead of an +one-element :class:`ast.JoinedStr` with an empty string +:class:`ast.Constant`. + +.. + +.. date: 2023-07-04-04-50-14 +.. gh-issue: 100288 +.. nonce: yNQ1ez +.. section: Core and Builtins + +Specialize :opcode:`LOAD_ATTR` for non-descriptors on the class. Adds +:opcode:`LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES` and +:opcode:`LOAD_ATTR_NONDESCRIPTOR_NO_DICT`. + +.. + +.. date: 2023-07-03-11-38-43 +.. gh-issue: 106008 +.. nonce: HDf1zd +.. section: Core and Builtins + +Fix possible reference leaks when failing to optimize comparisons with +:const:`None` in the bytecode compiler. + +.. + +.. date: 2023-06-29-09-46-41 +.. gh-issue: 106145 +.. nonce: QC6-Kq +.. section: Core and Builtins + +Make ``end_lineno`` and ``end_col_offset`` required on ``type_param`` ast +nodes. + +.. + +.. date: 2023-06-29-09-42-56 +.. gh-issue: 106213 +.. nonce: TCUgzM +.. section: Core and Builtins + +Changed the way that Emscripten call trampolines work for compatibility with +Wasm/JS Promise integration. + +.. + +.. date: 2023-06-28-15-19-59 +.. gh-issue: 106182 +.. nonce: cDSFi0 +.. section: Core and Builtins + +:func:`sys.getfilesystemencoding` and :mod:`sys.getfilesystemencodeerrors` +now return interned Unicode object. + +.. + +.. date: 2023-06-28-13-19-20 +.. gh-issue: 106210 +.. nonce: oE7VMn +.. section: Core and Builtins + +Removed Emscripten import trampoline as it was no longer necessary for +Pyodide. + +.. + +.. date: 2023-06-27-00-58-26 +.. gh-issue: 104584 +.. nonce: Wu-uXy +.. section: Core and Builtins + +Added a new, experimental, tracing optimizer and interpreter (a.k.a. "tier +2"). This currently pessimizes, so don't use yet -- this is infrastructure +so we can experiment with optimizing passes. To enable it, pass ``-Xuops`` +or set ``PYTHONUOPS=1``. To get debug output, set ``PYTHONUOPSDEBUG=N`` +where ``N`` is a debug level (0-4, where 0 is no debug output and 4 is +excessively verbose). + +.. + +.. date: 2023-06-24-10-34-27 +.. gh-issue: 105775 +.. nonce: OqjoGV +.. section: Core and Builtins + +:opcode:`LOAD_CLOSURE` is now a pseudo-op. + +.. + +.. date: 2023-06-23-16-51-02 +.. gh-issue: 105730 +.. nonce: 16haMe +.. section: Core and Builtins + +Allow any callable other than type objects as the condition predicate in +:meth:`BaseExceptionGroup.split` and :meth:`BaseExceptionGroup.subgroup`. + +.. + +.. date: 2023-06-22-19-16-24 +.. gh-issue: 105979 +.. nonce: TDP2CU +.. section: Core and Builtins + +Fix crash in :func:`!_imp.get_frozen_object` due to improper exception +handling. + +.. + +.. date: 2023-06-22-17-37-35 +.. gh-issue: 106003 +.. nonce: 2Vc_Tw +.. section: Core and Builtins + +Add a new :opcode:`TO_BOOL` instruction, which performs boolean conversions +for :opcode:`POP_JUMP_IF_TRUE`, :opcode:`POP_JUMP_IF_FALSE`, and +:opcode:`UNARY_NOT` (which all expect exact :class:`bool` values now). Also, +modify the oparg of :opcode:`COMPARE_OP` to include an optional "boolean +conversion" flag. + +.. + +.. date: 2023-06-22-14-19-17 +.. gh-issue: 98931 +.. nonce: PPgvSF +.. section: Core and Builtins + +Ensure custom :exc:`SyntaxError` error messages are raised for invalid +imports with multiple targets. Patch by Pablo Galindo + +.. + +.. date: 2023-06-20-10-53-17 +.. gh-issue: 105724 +.. nonce: d23L4M +.. section: Core and Builtins + +Improve ``assert`` error messages by providing exact error range. + +.. + +.. date: 2023-06-19-11-04-01 +.. gh-issue: 105908 +.. nonce: 7oanny +.. section: Core and Builtins + +Fixed bug where :gh:`99111` breaks future import ``barry_as_FLUFL`` in the +Python REPL. + +.. + +.. date: 2023-06-15-22-11-43 +.. gh-issue: 105840 +.. nonce: Fum_g_ +.. section: Core and Builtins + +Fix possible crashes when specializing function calls with too many +``__defaults__``. + +.. + +.. date: 2023-06-15-15-54-47 +.. gh-issue: 105831 +.. nonce: -MC9Zs +.. section: Core and Builtins + +Fix an f-string bug, where using a debug expression (the ``=`` sign) that +appears in the last line of a file results to the debug buffer that holds +the expression text being one character too small. + +.. + +.. date: 2023-06-14-22-52-06 +.. gh-issue: 105800 +.. nonce: hdpPzZ +.. section: Core and Builtins + +Correctly issue :exc:`SyntaxWarning` in f-strings if invalid sequences are +used. Patch by Pablo Galindo + +.. + +.. date: 2023-06-12-16-38-31 +.. gh-issue: 105340 +.. nonce: _jRHXe +.. section: Core and Builtins + +Include the comprehension iteration variable in ``locals()`` inside a +module- or class-scope comprehension. + +.. + +.. date: 2023-06-11-09-14-30 +.. gh-issue: 105331 +.. nonce: nlZvoW +.. section: Core and Builtins + +Raise :exc:`ValueError` if the ``delay`` argument to :func:`asyncio.sleep` +is a NaN (matching :func:`time.sleep`). + +.. + +.. date: 2023-06-10-21-38-49 +.. gh-issue: 105587 +.. nonce: rL3rzv +.. section: Core and Builtins + +The runtime can't guarantee that immortal objects will not be mutated by +Extensions. Thus, this modifies _PyStaticObject_CheckRefcnt to warn instead +of asserting. + +.. + +.. date: 2023-06-09-15-25-12 +.. gh-issue: 105564 +.. nonce: sFdUu4 +.. section: Core and Builtins + +Don't include artificil newlines in the ``line`` attribute of tokens in the +APIs of the :mod:`tokenize` module. Patch by Pablo Galindo + +.. + +.. date: 2023-06-09-12-59-18 +.. gh-issue: 105549 +.. nonce: PYfTNp +.. section: Core and Builtins + +Tokenize separately ``NUMBER`` and ``NAME`` tokens that are not ambiguous. +Patch by Pablo Galindo. + +.. + +.. date: 2023-06-09-11-19-51 +.. gh-issue: 105588 +.. nonce: Y5ovpY +.. section: Core and Builtins + +Fix an issue that could result in crashes when compiling malformed +:mod:`ast` nodes. + +.. + +.. date: 2023-06-09-10-48-17 +.. gh-issue: 100987 +.. nonce: mK-xny +.. section: Core and Builtins + +Allow objects other than code objects as the "executable" in internal +frames. In the long term, this can help tools like Cython and PySpy interact +more efficiently. In the shorter term, it allows us to perform some +optimizations more simply. + +.. + +.. date: 2023-06-08-10-10-07 +.. gh-issue: 105375 +.. nonce: 35VGDd +.. section: Core and Builtins + +Fix bugs in the :mod:`builtins` module where exceptions could end up being +overwritten. + +.. + +.. date: 2023-06-08-09-54-37 +.. gh-issue: 105375 +.. nonce: kqKT3E +.. section: Core and Builtins + +Fix bug in the compiler where an exception could end up being overwritten. + +.. + +.. date: 2023-06-08-09-25-52 +.. gh-issue: 105375 +.. nonce: ocB7fT +.. section: Core and Builtins + +Improve error handling in :c:func:`PyUnicode_BuildEncodingMap` where an +exception could end up being overwritten. + +.. + +.. date: 2023-06-08-09-10-15 +.. gh-issue: 105486 +.. nonce: dev-WS +.. section: Core and Builtins + +Change the repr of ``ParamSpec`` list of args in ``types.GenericAlias``. + +.. + +.. date: 2023-06-07-21-27-55 +.. gh-issue: 105678 +.. nonce: wKOr7F +.. section: Core and Builtins + +Break the ``MAKE_FUNCTION`` instruction into two parts, ``MAKE_FUNCTION`` +which makes the function and ``SET_FUNCTION_ATTRIBUTE`` which sets the +attributes on the function. This makes the stack effect of ``MAKE_FUNCTION`` +regular to ease optimization and code generation. + +.. + +.. date: 2023-06-07-12-20-59 +.. gh-issue: 105435 +.. nonce: 6VllI0 +.. section: Core and Builtins + +Fix spurious newline character if file ends on a comment without a newline. +Patch by Pablo Galindo + +.. + +.. date: 2023-06-06-17-10-42 +.. gh-issue: 105390 +.. nonce: DvqI-e +.. section: Core and Builtins + +Correctly raise :exc:`tokenize.TokenError` exceptions instead of +:exc:`SyntaxError` for tokenize errors such as incomplete input. Patch by +Pablo Galindo + +.. + +.. date: 2023-06-06-11-37-53 +.. gh-issue: 105259 +.. nonce: E2BGKL +.. section: Core and Builtins + +Don't include newline character for trailing ``NEWLINE`` tokens emitted in +the :mod:`tokenize` module. Patch by Pablo Galindo + +.. + +.. date: 2023-06-05-23-38-43 +.. gh-issue: 104635 +.. nonce: VYZhVh +.. section: Core and Builtins + +Eliminate redundant :opcode:`STORE_FAST` instructions in the compiler. Patch +by Donghee Na and Carl Meyer. + +.. + +.. date: 2023-06-05-17-35-50 +.. gh-issue: 105324 +.. nonce: BqhiJJ +.. section: Core and Builtins + +Fix the main function of the :mod:`tokenize` module when reading from +``sys.stdin``. Patch by Pablo Galindo + +.. + +.. date: 2023-06-05-08-30-49 +.. gh-issue: 33092 +.. nonce: hZ0xSI +.. section: Core and Builtins + +Simplify and speed up interpreter for f-strings. Removes ``FORMAT_VALUE`` +opcode. Add ``CONVERT_VALUE``, ``FORMAT_SIMPLE`` and ``FORMAT_WITH_SPEC`` +opcode. Compiler emits more efficient sequence for each format expression. + +.. + +.. date: 2023-06-03-04-28-28 +.. gh-issue: 105229 +.. nonce: stEmfp +.. section: Core and Builtins + +Remove remaining two-codeunit superinstructions. All remaining +superinstructions only take a single codeunit, simplifying instrumentation +and quickening. + +.. + +.. date: 2023-06-02-19-37-29 +.. gh-issue: 105235 +.. nonce: fgFGTi +.. section: Core and Builtins + +Prevent out-of-bounds memory access during ``mmap.find()`` calls. + +.. + +.. date: 2023-06-02-17-39-19 +.. gh-issue: 98963 +.. nonce: J4wJgk +.. section: Core and Builtins + +Restore the ability for a subclass of :class:`property` to define +``__slots__`` or otherwise be dict-less by ignoring failures to set a +docstring on such a class. This behavior had regressed in 3.12beta1. An +:exc:`AttributeError` where there had not previously been one was disruptive +to existing code. + +.. + +.. date: 2023-06-02-15-15-41 +.. gh-issue: 104812 +.. nonce: dfZiG5 +.. section: Core and Builtins + +The "pending call" machinery now works for all interpreters, not just the +main interpreter, and runs in all threads, not just the main thread. Some +calls are still only done in the main thread, ergo in the main interpreter. +This change does not affect signal handling nor the existing public C-API +(``Py_AddPendingCall()``), which both still only target the main thread. The +new functionality is meant strictly for internal use for now, since +consequences of its use are not well understood yet outside some very +restricted cases. This change brings the capability in line with the +intention when the state was made per-interpreter several years ago. + +.. + +.. date: 2023-06-02-11-37-12 +.. gh-issue: 105194 +.. nonce: 4eu56B +.. section: Core and Builtins + +Do not escape with backslashes f-string format specifiers. Patch by Pablo +Galindo + +.. + +.. date: 2023-06-02-01-27-35 +.. gh-issue: 105229 +.. nonce: U05x4G +.. section: Core and Builtins + +Replace some dynamic superinstructions with single instruction equivalents. + +.. + +.. date: 2023-06-01-11-37-03 +.. gh-issue: 105162 +.. nonce: r8VCXk +.. section: Core and Builtins + +Fixed bug in generator.close()/throw() where an inner iterator would be +ignored when the outer iterator was instrumented. + +.. + +.. date: 2023-05-31-19-35-22 +.. gh-issue: 105164 +.. nonce: 6Wajph +.. section: Core and Builtins + +Ensure annotations are set up correctly if the only annotation in a block is +within a :keyword:`match` block. Patch by Jelle Zijlstra. + +.. + +.. date: 2023-05-31-16-22-29 +.. gh-issue: 105148 +.. nonce: MOlb1d +.. section: Core and Builtins + +Make ``_PyASTOptimizeState`` internal to ast_opt.c. Make ``_PyAST_Optimize`` +take two integers instead of a pointer to this struct. This avoids the need +to include pycore_compile.h in ast_opt.c. + +.. + +.. date: 2023-05-31-08-10-59 +.. gh-issue: 104799 +.. nonce: 8kDWti +.. section: Core and Builtins + +Attributes of :mod:`ast` nodes that are lists now default to the empty list +if omitted. This means that some code that previously raised +:exc:`TypeError` when the AST node was used will now proceed with the empty +list instead. Patch by Jelle Zijlstra. + +.. + +.. date: 2023-05-30-20-30-57 +.. gh-issue: 105111 +.. nonce: atn0_6 +.. section: Core and Builtins + +Remove the old trashcan macros ``Py_TRASHCAN_SAFE_BEGIN`` and +``Py_TRASHCAN_SAFE_END``. They should be replaced by the new macros +``Py_TRASHCAN_BEGIN`` and ``Py_TRASHCAN_END``. + +.. + +.. date: 2023-05-30-08-09-43 +.. gh-issue: 105035 +.. nonce: OWUlHy +.. section: Core and Builtins + +Fix :func:`super` calls on types with custom +:c:member:`~PyTypeObject.tp_getattro` implementation (e.g. meta-types.) + +.. + +.. date: 2023-05-27-21-50-48 +.. gh-issue: 105017 +.. nonce: 4sDyDV +.. section: Core and Builtins + +Show CRLF lines in the tokenize string attribute in both NL and NEWLINE +tokens. Patch by Marta Gómez. + +.. + +.. date: 2023-05-27-16-57-11 +.. gh-issue: 105013 +.. nonce: IsDgDY +.. section: Core and Builtins + +Fix handling of multiline parenthesized lambdas in +:func:`inspect.getsource`. Patch by Pablo Galindo + +.. + +.. date: 2023-05-27-16-23-16 +.. gh-issue: 105017 +.. nonce: KQrsC0 +.. section: Core and Builtins + +Do not include an additional final ``NL`` token when parsing files having +CRLF lines. Patch by Marta Gómez. + +.. + +.. date: 2023-05-26-15-16-11 +.. gh-issue: 104976 +.. nonce: 6dLitD +.. section: Core and Builtins + +Ensure that trailing ``DEDENT`` :class:`tokenize.TokenInfo` objects emitted +by the :mod:`tokenize` module are reported as in Python 3.11. Patch by Pablo +Galindo + +.. + +.. date: 2023-05-26-14-09-47 +.. gh-issue: 104972 +.. nonce: El2UjE +.. section: Core and Builtins + +Ensure that the ``line`` attribute in :class:`tokenize.TokenInfo` objects in +the :mod:`tokenize` module are always correct. Patch by Pablo Galindo + +.. + +.. date: 2023-05-25-21-40-39 +.. gh-issue: 104955 +.. nonce: LZx7jf +.. section: Core and Builtins + +Fix signature for the new :meth:`~object.__release_buffer__` slot. Patch by +Jelle Zijlstra. + +.. + +.. date: 2023-05-24-12-10-54 +.. gh-issue: 104690 +.. nonce: HX3Jou +.. section: Core and Builtins + +Starting new threads and process creation through :func:`os.fork` during +interpreter shutdown (such as from :mod:`atexit` handlers) is no longer +supported. It can lead to race condition between the main Python runtime +thread freeing thread states while internal :mod:`threading` routines are +trying to allocate and use the state of just created threads. Or forked +children trying to use the mid-shutdown runtime and thread state in the +child process. + +.. + +.. date: 2023-05-24-10-19-35 +.. gh-issue: 104879 +.. nonce: v-29NL +.. section: Core and Builtins + +Fix crash when accessing the ``__module__`` attribute of type aliases +defined outside a module. Patch by Jelle Zijlstra. + +.. + +.. date: 2023-05-24-09-59-56 +.. gh-issue: 104825 +.. nonce: mQesie +.. section: Core and Builtins + +Tokens emitted by the :mod:`tokenize` module do not include an implicit +``\n`` character in the ``line`` attribute anymore. Patch by Pablo Galindo + +.. + +.. date: 2023-05-23-00-36-02 +.. gh-issue: 104770 +.. nonce: poSkyY +.. section: Core and Builtins + +If a generator returns a value upon being closed, the value is now returned +by :meth:`generator.close`. + +.. + +.. date: 2023-05-18-12-48-39 +.. gh-issue: 89091 +.. nonce: FDzRcW +.. section: Core and Builtins + +Raise :exc:`RuntimeWarning` for unawaited async generator methods like +:meth:`~agen.asend`, :meth:`~agen.athrow` and :meth:`~agen.aclose`. Patch by +Kumar Aditya. + +.. + +.. date: 2023-04-04-00-40-04 +.. gh-issue: 96663 +.. nonce: PdR9hK +.. section: Core and Builtins + +Add a better, more introspect-able error message when setting attributes on +classes without a ``__dict__`` and no slot member for the attribute. + +.. + +.. date: 2023-03-26-19-11-10 +.. gh-issue: 93627 +.. nonce: 0UgwBL +.. section: Core and Builtins + +Update the Python pickle module implementation to match the C implementation +of the pickle module. For objects setting reduction methods like +:meth:`~object.__reduce_ex__` or :meth:`~object.__reduce__` to ``None``, +pickling will result in a :exc:`TypeError`. + +.. + +.. date: 2023-01-13-11-37-41 +.. gh-issue: 101006 +.. nonce: fuLvn2 +.. section: Core and Builtins + +Improve error handling when read :mod:`marshal` data. + +.. + +.. date: 2022-11-10-13-04-35 +.. gh-issue: 91095 +.. nonce: 4E3Pwn +.. section: Core and Builtins + +Specializes calls to most Python classes. Specifically, any class that +inherits from ``object``, or another Python class, and does not override +``__new__``. + +The specialized instruction does the following: + +1. Creates the object (by calling ``object.__new__``) +2. Pushes a shim frame to the frame stack (to cleanup after ``__init__``) +3. Pushes the frame for ``__init__`` to the frame stack + +Speeds up the instantiation of most Python classes. + +.. + +.. date: 2023-10-13-01-31-27 +.. gh-issue: 110786 +.. nonce: sThp-A +.. section: Library + +:mod:`sysconfig`'s CLI now ignores :exc:`BrokenPipeError`, making it exit +normally if its output is being piped and the pipe closes. + +.. + +.. date: 2023-10-13-00-14-17 +.. gh-issue: 103480 +.. nonce: lmdf1J +.. section: Library + +The :mod:`sysconfig` module is now a package, instead of a single-file +module. + +.. + +.. date: 2023-10-11-18-43-43 +.. gh-issue: 110733 +.. nonce: UlrgVm +.. section: Library + +Micro-optimization: Avoid calling ``min()``, ``max()`` in +:meth:`BaseEventLoop._run_once`. + +.. + +.. date: 2023-10-11-15-07-21 +.. gh-issue: 94597 +.. nonce: NbPC8t +.. section: Library + +Added :class:`asyncio.EventLoop` for use with the :func:`asyncio.run` +*loop_factory* kwarg to avoid calling the asyncio policy system. + +.. + +.. date: 2023-10-11-11-00-11 +.. gh-issue: 110682 +.. nonce: bXRFaX +.. section: Library + +:func:`runtime-checkable protocols ` used to +consider ``__match_args__`` a protocol member in ``__instancecheck__`` if it +was present on the protocol. Now, this attribute is ignored if it is +present. + +.. + +.. date: 2023-10-10-22-54-56 +.. gh-issue: 110488 +.. nonce: 2I7OiZ +.. section: Library + +Fix a couple of issues in :meth:`pathlib.PurePath.with_name`: a single dot +was incorrectly considered a valid name, and in :class:`PureWindowsPath`, a +name with an NTFS alternate data stream, like ``a:b``, was incorrectly +considered invalid. + +.. + +.. date: 2023-10-10-10-46-55 +.. gh-issue: 110590 +.. nonce: fatz-h +.. section: Library + +Fix a bug in :meth:`!_sre.compile` where :exc:`TypeError` would be +overwritten by :exc:`OverflowError` when the *code* argument was a list of +non-ints. + +.. + +.. date: 2023-10-09-19-09-32 +.. gh-issue: 65052 +.. nonce: C2mRlo +.. section: Library + +Prevent :mod:`pdb` from crashing when trying to display undisplayable +objects + +.. + +.. date: 2023-10-08-18-15-02 +.. gh-issue: 110519 +.. nonce: RDGe8- +.. section: Library + +Deprecation warning about non-integer number in :mod:`gettext` now alwais +refers to the line in the user code where gettext function or method is +used. Previously it could refer to a line in ``gettext`` code. + +.. + +.. date: 2023-10-07-21-12-28 +.. gh-issue: 89902 +.. nonce: dCokZj +.. section: Library + +Deprecate non-standard format specifier "N" for :class:`decimal.Decimal`. It +was not documented and only supported in the C implementation. + +.. + +.. date: 2023-10-07-13-50-12 +.. gh-issue: 110378 +.. nonce: Y4L8fl +.. section: Library + +:func:`~contextlib.contextmanager` and +:func:`~contextlib.asynccontextmanager` context managers now close an +invalid underlying generator object that yields more then one value. + +.. + +.. date: 2023-10-07-00-18-40 +.. gh-issue: 106670 +.. nonce: kCGyRc +.. section: Library + +In :mod:`pdb`, set convenience variable ``$_exception`` for post mortem +debugging. + +.. + +.. date: 2023-10-04-18-56-29 +.. gh-issue: 110365 +.. nonce: LCxiau +.. section: Library + +Fix :func:`termios.tcsetattr` bug that was overwritting existing errors +during parsing integers from ``term`` list. + +.. + +.. date: 2023-10-03-15-17-03 +.. gh-issue: 109653 +.. nonce: 9DYOMD +.. section: Library + +Slightly improve the import time of several standard-library modules by +deferring imports of :mod:`warnings` within those modules. Patch by Alex +Waygood. + +.. + +.. date: 2023-10-03-14-07-05 +.. gh-issue: 110273 +.. nonce: QaDUmS +.. section: Library + +:func:`dataclasses.replace` now raises TypeError instead of ValueError if +specify keyword argument for a field declared with init=False or miss +keyword argument for required InitVar field. + +.. + +.. date: 2023-10-03-00-04-26 +.. gh-issue: 110249 +.. nonce: K0mMrs +.. section: Library + +Add ``--inline-caches`` flag to ``dis`` command line. + +.. + +.. date: 2023-10-02-15-40-10 +.. gh-issue: 109653 +.. nonce: iB0peK +.. section: Library + +Fix a Python 3.12 regression in the import time of :mod:`random`. Patch by +Alex Waygood. + +.. + +.. date: 2023-10-02-15-07-28 +.. gh-issue: 110222 +.. nonce: zl_oHh +.. section: Library + +Add support of struct sequence objects in :func:`copy.replace`. Patched by +Xuehai Pan. + +.. + +.. date: 2023-10-01-01-47-21 +.. gh-issue: 109649 +.. nonce: BizOaD +.. section: Library + +:mod:`multiprocessing`, :mod:`concurrent.futures`, :mod:`compileall`: +Replace :func:`os.cpu_count` with :func:`os.process_cpu_count` to select the +default number of worker threads and processes. Get the CPU affinity if +supported. Patch by Victor Stinner. + +.. + +.. date: 2023-09-30-12-50-47 +.. gh-issue: 110150 +.. nonce: 9j0Ij5 +.. section: Library + +Fix base case handling in statistics.quantiles. Now allows a single data +point. + +.. + +.. date: 2023-09-28-18-53-11 +.. gh-issue: 110036 +.. nonce: fECxTj +.. section: Library + +On Windows, multiprocessing ``Popen.terminate()`` now catchs +:exc:`PermissionError` and get the process exit code. If the process is +still running, raise again the :exc:`PermissionError`. Otherwise, the +process terminated as expected: store its exit code. Patch by Victor +Stinner. + +.. + +.. date: 2023-09-28-18-50-33 +.. gh-issue: 110038 +.. nonce: nx_gCu +.. section: Library + +Fixed an issue that caused :meth:`KqueueSelector.select` to not return all +the ready events in some cases when a file descriptor is registered for both +read and write. + +.. + +.. date: 2023-09-28-18-08-02 +.. gh-issue: 110045 +.. nonce: 0YIGKv +.. section: Library + +Update the :mod:`symtable` module to support the new scopes introduced by +:pep:`695`. + +.. + +.. date: 2023-09-28-12-32-57 +.. gh-issue: 88402 +.. nonce: hoa3Gx +.. section: Library + +Add new variables to :py:meth:`sysconfig.get_config_vars` on Windows: +``LIBRARY``, ``LDLIBRARY``, ``LIBDIR``, ``SOABI``, and ``Py_NOGIL``. + +.. + +.. date: 2023-09-25-23-00-37 +.. gh-issue: 109631 +.. nonce: eWSqpO +.. section: Library + +:mod:`re` functions such as :func:`re.findall`, :func:`re.split`, +:func:`re.search` and :func:`re.sub` which perform short repeated matches +can now be interrupted by user. + +.. + +.. date: 2023-09-25-10-47-22 +.. gh-issue: 109653 +.. nonce: TUHrId +.. section: Library + +Reduce the import time of :mod:`email.utils` by around 43%. This results in +the import time of :mod:`email.message` falling by around 18%, which in turn +reduces the import time of :mod:`importlib.metadata` by around 6%. Patch by +Alex Waygood. + +.. + +.. date: 2023-09-25-09-59-59 +.. gh-issue: 109818 +.. nonce: dLRtT- +.. section: Library + +Fix :func:`reprlib.recursive_repr` not copying ``__type_params__`` from +decorated function. + +.. + +.. date: 2023-09-25-02-11-14 +.. gh-issue: 109047 +.. nonce: b1TrqG +.. section: Library + +:mod:`concurrent.futures`: The *executor manager thread* now catches +exceptions when adding an item to the *call queue*. During Python +finalization, creating a new thread can now raise :exc:`RuntimeError`. Catch +the exception and call ``terminate_broken()`` in this case. Patch by Victor +Stinner. + +.. + +.. date: 2023-09-24-16-43-33 +.. gh-issue: 109782 +.. nonce: gMC_7z +.. section: Library + +Ensure the signature of :func:`os.path.isdir` is identical on all platforms. +Patch by Amin Alaee. + +.. + +.. date: 2023-09-24-13-28-35 +.. gh-issue: 109653 +.. nonce: 9IFU0B +.. section: Library + +Improve import time of :mod:`functools` by around 13%. Patch by Alex +Waygood. + +.. + +.. date: 2023-09-24-06-04-14 +.. gh-issue: 109590 +.. nonce: 9EMofC +.. section: Library + +:func:`shutil.which` will prefer files with an extension in ``PATHEXT`` if +the given mode includes ``os.X_OK`` on win32. If no ``PATHEXT`` match is +found, a file without an extension in ``PATHEXT`` can be returned. This +change will have :func:`shutil.which` act more similarly to previous +behavior in Python 3.11. + +.. + +.. date: 2023-09-23-12-47-45 +.. gh-issue: 109653 +.. nonce: 9wZBfs +.. section: Library + +Reduce the import time of :mod:`enum` by over 50%. Patch by Alex Waygood. + +.. + +.. date: 2023-09-22-20-16-44 +.. gh-issue: 109593 +.. nonce: LboaNM +.. section: Library + +Avoid deadlocking on a reentrant call to the multiprocessing resource +tracker. Such a reentrant call, though unlikely, can happen if a GC pass +invokes the finalizer for a multiprocessing object such as SemLock. + +.. + +.. date: 2023-09-21-19-42-22 +.. gh-issue: 109653 +.. nonce: bL3iLH +.. section: Library + +Reduce the import time of :mod:`typing` by around a third. Patch by Alex +Waygood. + +.. + +.. date: 2023-09-21-16-21-19 +.. gh-issue: 109649 +.. nonce: YYCjAF +.. section: Library + +Add :func:`os.process_cpu_count` function to get the number of logical CPUs +usable by the calling thread of the current process. Patch by Victor +Stinner. + +.. + +.. date: 2023-09-21-14-26-44 +.. gh-issue: 74481 +.. nonce: KAUDcD +.. section: Library + +Add ``set_error_mode`` related constants in ``msvcrt`` module in Python +debug build. + +.. + +.. date: 2023-09-20-17-45-46 +.. gh-issue: 109613 +.. nonce: P13ogN +.. section: Library + +Fix :func:`os.stat` and :meth:`os.DirEntry.stat`: check for exceptions. +Previously, on Python built in debug mode, these functions could trigger a +fatal Python error (and abort the process) when a function succeeded with an +exception set. Patch by Victor Stinner. + +.. + +.. date: 2023-09-20-07-38-14 +.. gh-issue: 109599 +.. nonce: IaSLJz +.. section: Library + +Expose the type of PyCapsule objects as ``types.CapsuleType``. + +.. + +.. date: 2023-09-19-17-56-24 +.. gh-issue: 109109 +.. nonce: WJvvX2 +.. section: Library + +You can now get the raw TLS certificate chains from TLS connections via +:meth:`ssl.SSLSocket.get_verified_chain` and +:meth:`ssl.SSLSocket.get_unverified_chain` methods. + +Contributed by Mateusz Nowak. + +.. + +.. date: 2023-09-19-01-22-43 +.. gh-issue: 109559 +.. nonce: ijaycU +.. section: Library + +Update :mod:`unicodedata` database to Unicode 15.1.0. + +.. + +.. date: 2023-09-18-07-43-22 +.. gh-issue: 109543 +.. nonce: 1tOGoV +.. section: Library + +Remove unnecessary :func:`hasattr` check during :data:`typing.TypedDict` +creation. + +.. + +.. date: 2023-09-16-15-44-16 +.. gh-issue: 109495 +.. nonce: m2H5Bk +.. section: Library + +Remove unnecessary extra ``__slots__`` in :py:class:`datetime`\'s pure +python implementation to reduce memory size, as they are defined in the +superclass. Patch by James Hilton-Balfe + +.. + +.. date: 2023-09-15-17-12-53 +.. gh-issue: 109461 +.. nonce: VNFPTK +.. section: Library + +:mod:`logging`: Use a context manager for lock acquisition. + +.. + +.. date: 2023-09-15-12-20-23 +.. gh-issue: 109096 +.. nonce: VksX1D +.. section: Library + +:class:`http.server.CGIHTTPRequestHandler` has been deprecated for removal +in 3.15. Its design is old and the web world has long since moved beyond +CGI. + +.. + +.. date: 2023-09-15-10-42-30 +.. gh-issue: 109409 +.. nonce: RlffA3 +.. section: Library + +Fix error when it was possible to inherit a frozen dataclass from multiple +parents some of which were possibly not frozen. + +.. + +.. date: 2023-09-13-17-22-44 +.. gh-issue: 109375 +.. nonce: ijJHZ9 +.. section: Library + +The :mod:`pdb` ``alias`` command now prevents registering aliases without +arguments. + +.. + +.. date: 2023-09-12-13-01-55 +.. gh-issue: 109319 +.. nonce: YaCMtW +.. section: Library + +Deprecate the ``dis.HAVE_ARGUMENT`` field in favour of ``dis.hasarg``. + +.. + +.. date: 2023-09-11-00-32-18 +.. gh-issue: 107219 +.. nonce: 3zqyFT +.. section: Library + +Fix a race condition in ``concurrent.futures``. When a process in the +process pool was terminated abruptly (while the future was running or +pending), close the connection write end. If the call queue is blocked on +sending bytes to a worker process, closing the connection write end +interrupts the send, so the queue can be closed. Patch by Victor Stinner. + +.. + +.. date: 2023-09-10-20-23-20 +.. gh-issue: 66143 +.. nonce: 71xvgL +.. section: Library + +The :class:`codecs.CodecInfo` object has been made copyable and pickleable. +Patched by Robert Lehmann and Furkan Onder. + +.. + +.. date: 2023-09-09-17-09-54 +.. gh-issue: 109187 +.. nonce: dIayNW +.. section: Library + +:meth:`pathlib.Path.resolve` now treats symlink loops like other errors: in +strict mode, :exc:`OSError` is raised, and in non-strict mode, no exception +is raised. + +.. + +.. date: 2023-09-09-15-08-37 +.. gh-issue: 50644 +.. nonce: JUAZOh +.. section: Library + +Attempts to pickle or create a shallow or deep copy of :mod:`codecs` streams +now raise a TypeError. Previously, copying failed with a RecursionError, +while pickling produced wrong results that eventually caused unpickling to +fail with a RecursionError. + +.. + +.. date: 2023-09-09-09-05-41 +.. gh-issue: 109174 +.. nonce: OJea5s +.. section: Library + +Add support of :class:`types.SimpleNamespace` in :func:`copy.replace`. + +.. + +.. date: 2023-09-08-22-26-26 +.. gh-issue: 109164 +.. nonce: -9BFWR +.. section: Library + +:mod:`pdb`: Replace :mod:`getopt` with :mod:`argparse` for parsing command +line arguments. + +.. + +.. date: 2023-09-08-19-44-01 +.. gh-issue: 109151 +.. nonce: GkzkQu +.. section: Library + +Enable ``readline`` editing features in the :ref:`sqlite3 command-line +interface ` (``python -m sqlite3``). + +.. + +.. date: 2023-09-08-12-09-55 +.. gh-issue: 108987 +.. nonce: x5AIG8 +.. section: Library + +Fix :func:`_thread.start_new_thread` race condition. If a thread is created +during Python finalization, the newly spawned thread now exits immediately +instead of trying to access freed memory and lead to a crash. Patch by +Victor Stinner. + +.. + +.. date: 2023-09-06-19-33-41 +.. gh-issue: 108682 +.. nonce: 35Xnc5 +.. section: Library + +Enum: require ``names=()`` or ``type=...`` to create an empty enum using the +functional syntax. + +.. + +.. date: 2023-09-06-14-47-28 +.. gh-issue: 109033 +.. nonce: piUzDx +.. section: Library + +Exceptions raised by os.utime builtin function now include the related +filename + +.. + +.. date: 2023-09-06-06-17-23 +.. gh-issue: 108843 +.. nonce: WJMhsS +.. section: Library + +Fix an issue in :func:`ast.unparse` when unparsing f-strings containing many +quote types. + +.. + +.. date: 2023-09-03-04-37-52 +.. gh-issue: 108469 +.. nonce: kusj40 +.. section: Library + +:func:`ast.unparse` now supports new :term:`f-string` syntax introduced in +Python 3.12. Note that the :term:`f-string` quotes are reselected for +simplicity under the new syntax. (Patch by Steven Sun) + +.. + +.. date: 2023-09-01-13-14-08 +.. gh-issue: 108751 +.. nonce: 2itqwe +.. section: Library + +Add :func:`copy.replace` function which allows to create a modified copy of +an object. It supports named tuples, dataclasses, and many other objects. + +.. + +.. date: 2023-08-30-20-10-28 +.. gh-issue: 108682 +.. nonce: c2gzLQ +.. section: Library + +Enum: raise :exc:`TypeError` if ``super().__new__()`` is called from a +custom ``__new__``. + +.. + +.. date: 2023-08-29-11-29-15 +.. gh-issue: 108278 +.. nonce: -UhsnJ +.. section: Library + +Deprecate passing the callback callable by keyword for the following +:class:`sqlite3.Connection` APIs: + +* :meth:`~sqlite3.Connection.set_authorizer` +* :meth:`~sqlite3.Connection.set_progress_handler` +* :meth:`~sqlite3.Connection.set_trace_callback` + +The affected parameters will become positional-only in Python 3.15. + +Patch by Erlend E. Aasland. + +.. + +.. date: 2023-08-26-12-35-39 +.. gh-issue: 105829 +.. nonce: kyYhWI +.. section: Library + +Fix concurrent.futures.ProcessPoolExecutor deadlock + +.. + +.. date: 2023-08-26-08-38-57 +.. gh-issue: 108295 +.. nonce: Pn0QRM +.. section: Library + +Fix crashes related to use of weakrefs on :data:`typing.TypeVar`. + +.. + +.. date: 2023-08-25-00-14-34 +.. gh-issue: 108463 +.. nonce: mQApp_ +.. section: Library + +Make expressions/statements work as expected in pdb + +.. + +.. date: 2023-08-23-22-08-32 +.. gh-issue: 108277 +.. nonce: KLV-6T +.. section: Library + +Add :func:`os.timerfd_create`, :func:`os.timerfd_settime`, +:func:`os.timerfd_gettime`, :func:`os.timerfd_settime_ns`, and +:func:`os.timerfd_gettime_ns` to provide a low level interface for Linux's +timer notification file descriptor. + +.. + +.. date: 2023-08-23-17-34-39 +.. gh-issue: 107811 +.. nonce: 3Fng72 +.. section: Library + +:mod:`tarfile`: extraction of members with overly large UID or GID (e.g. on +an OS with 32-bit :c:type:`!id_t`) now fails in the same way as failing to +set the ID. + +.. + +.. date: 2023-08-22-22-29-42 +.. gh-issue: 64662 +.. nonce: jHl_Bt +.. section: Library + +Fix support for virtual tables in :meth:`sqlite3.Connection.iterdump`. Patch +by Aviv Palivoda. + +.. + +.. date: 2023-08-22-17-27-12 +.. gh-issue: 108111 +.. nonce: N7a4u_ +.. section: Library + +Fix a regression introduced in GH-101251 for 3.12, resulting in an incorrect +offset calculation in :meth:`gzip.GzipFile.seek`. + +.. + +.. date: 2023-08-22-16-18-49 +.. gh-issue: 108294 +.. nonce: KEeUcM +.. section: Library + +:func:`time.sleep` now raises an auditing event. + +.. + +.. date: 2023-08-22-13-51-10 +.. gh-issue: 108278 +.. nonce: 11d_qG +.. section: Library + +Deprecate passing name, number of arguments, and the callable as keyword +arguments, for the following :class:`sqlite3.Connection` APIs: + +* :meth:`~sqlite3.Connection.create_function` +* :meth:`~sqlite3.Connection.create_aggregate` + +The affected parameters will become positional-only in Python 3.15. + +Patch by Erlend E. Aasland. + +.. + +.. date: 2023-08-22-12-05-47 +.. gh-issue: 108322 +.. nonce: kf3NJX +.. section: Library + +Speed-up NormalDist.samples() by using the inverse CDF method instead of +calling random.gauss(). + +.. + +.. date: 2023-08-18-22-58-07 +.. gh-issue: 83417 +.. nonce: 61J4yM +.. section: Library + +Add the ability for venv to create a ``.gitignore`` file which causes the +created environment to be ignored by Git. It is on by default when venv is +called via its CLI. + +.. + +.. date: 2023-08-17-14-45-25 +.. gh-issue: 105736 +.. nonce: NJsH7r +.. section: Library + +Harmonized the pure Python version of :class:`~collections.OrderedDict` with +the C version. Now, both versions set up their internal state in +``__new__``. Formerly, the pure Python version did the set up in +``__init__``. + +.. + +.. date: 2023-08-17-12-59-35 +.. gh-issue: 108083 +.. nonce: 9J7UcT +.. section: Library + +Fix bugs in the constructor of :mod:`sqlite3.Connection` and +:meth:`sqlite3.Connection.close` where exceptions could be leaked. Patch by +Erlend E. Aasland. + +.. + +.. date: 2023-08-16-21-20-55 +.. gh-issue: 107932 +.. nonce: I7hFsp +.. section: Library + +Fix ``dis`` module to properly report and display bytecode that do not have +source lines. + +.. + +.. date: 2023-08-16-14-30-13 +.. gh-issue: 105539 +.. nonce: 29lA6c +.. section: Library + +:mod:`sqlite3` now emits an :exc:`ResourceWarning` if a +:class:`sqlite3.Connection` object is not :meth:`closed +` explicitly. Patch by Erlend E. Aasland. + +.. + +.. date: 2023-08-16-00-24-07 +.. gh-issue: 107995 +.. nonce: TlTp5t +.. section: Library + +The ``__module__`` attribute on instances of +:class:`functools.cached_property` is now set to the name of the module in +which the cached_property is defined, rather than "functools". This means +that doctests in ``cached_property`` docstrings are now properly collected +by the :mod:`doctest` module. Patch by Tyler Smart. + +.. + +.. date: 2023-08-15-18-20-00 +.. gh-issue: 107963 +.. nonce: 20g5BG +.. section: Library + +Fix :func:`multiprocessing.set_forkserver_preload` to check the given list +of modules names. Patch by Donghee Na. + +.. + +.. date: 2023-08-14-23-11-11 +.. gh-issue: 106242 +.. nonce: 71HMym +.. section: Library + +Fixes :func:`os.path.normpath` to handle embedded null characters without +truncating the path. + +.. + +.. date: 2023-08-14-20-18-59 +.. gh-issue: 81555 +.. nonce: cWdP4a +.. section: Library + +:mod:`xml.dom.minidom` now only quotes ``"`` in attributes. + +.. + +.. date: 2023-08-14-20-01-14 +.. gh-issue: 50002 +.. nonce: E-bpj8 +.. section: Library + +:mod:`xml.dom.minidom` now preserves whitespaces in attributes. + +.. + +.. date: 2023-08-14-19-49-02 +.. gh-issue: 93057 +.. nonce: 5nJwO5 +.. section: Library + +Passing more than one positional argument to :func:`sqlite3.connect` and the +:class:`sqlite3.Connection` constructor is deprecated. The remaining +parameters will become keyword-only in Python 3.15. Patch by Erlend E. +Aasland. + +.. + +.. date: 2023-08-14-17-15-59 +.. gh-issue: 76913 +.. nonce: LLD0rT +.. section: Library + +Add *merge_extra* parameter/feature to :class:`logging.LoggerAdapter` + +.. + +.. date: 2023-08-14-11-18-13 +.. gh-issue: 107913 +.. nonce: 4ooY6i +.. section: Library + +Fix possible losses of ``errno`` and ``winerror`` values in :exc:`OSError` +exceptions if they were cleared or modified by the cleanup code before +creating the exception object. + +.. + +.. date: 2023-08-10-17-36-22 +.. gh-issue: 107845 +.. nonce: dABiMJ +.. section: Library + +:func:`tarfile.data_filter` now takes the location of symlinks into account +when determining their target, so it will no longer reject some valid +tarballs with ``LinkOutsideDestinationError``. + +.. + +.. date: 2023-08-09-15-37-20 +.. gh-issue: 107812 +.. nonce: CflAXa +.. section: Library + +Extend socket's netlink support to the FreeBSD platform. + +.. + +.. date: 2023-08-09-13-49-37 +.. gh-issue: 107805 +.. nonce: ezem0k +.. section: Library + +Fix signatures of module-level generated functions in :mod:`turtle`. + +.. + +.. date: 2023-08-08-19-57-45 +.. gh-issue: 107782 +.. nonce: mInjFE +.. section: Library + +:mod:`pydoc` is now able to show signatures which are not representable in +Python, e.g. for ``getattr`` and ``dict.pop``. + +.. + +.. date: 2023-08-08-16-09-59 +.. gh-issue: 56166 +.. nonce: WUMhYG +.. section: Library + +Deprecate passing optional arguments *maxsplit*, *count* and *flags* in +module-level functions :func:`re.split`, :func:`re.sub` and :func:`re.subn` +as positional. They should only be passed by keyword. + +.. + +.. date: 2023-08-07-14-24-42 +.. gh-issue: 107710 +.. nonce: xfOCfj +.. section: Library + +Speed up :func:`logging.getHandlerNames`. + +.. + +.. date: 2023-08-07-14-12-07 +.. gh-issue: 107715 +.. nonce: 238r2f +.. section: Library + +Fix :meth:`doctest.DocTestFinder.find` in presence of class names with +special characters. Patch by Gertjan van Zwieten. + +.. + +.. date: 2023-08-06-15-29-00 +.. gh-issue: 100814 +.. nonce: h195gW +.. section: Library + +Passing a callable object as an option value to a Tkinter image now raises +the expected TclError instead of an AttributeError. + +.. + +.. date: 2023-08-06-10-52-12 +.. gh-issue: 72684 +.. nonce: Ls2mSf +.. section: Library + +Add :mod:`tkinter` widget methods: :meth:`!tk_busy_hold`, +:meth:`!tk_busy_configure`, :meth:`!tk_busy_cget`, :meth:`!tk_busy_forget`, +:meth:`!tk_busy_current`, and :meth:`!tk_busy_status`. + +.. + +.. date: 2023-08-05-05-10-41 +.. gh-issue: 106684 +.. nonce: P9zRXb +.. section: Library + +Raise :exc:`ResourceWarning` when :class:`asyncio.StreamWriter` is not +closed leading to memory leaks. Patch by Kumar Aditya. + +.. + +.. date: 2023-08-04-19-00-53 +.. gh-issue: 107465 +.. nonce: Vc1Il3 +.. section: Library + +Add :meth:`pathlib.Path.from_uri` classmethod. + +.. + +.. date: 2023-08-03-12-52-19 +.. gh-issue: 107077 +.. nonce: -pzHD6 +.. section: Library + +Seems that in some conditions, OpenSSL will return ``SSL_ERROR_SYSCALL`` +instead of ``SSL_ERROR_SSL`` when a certification verification has failed, +but the error parameters will still contain ``ERR_LIB_SSL`` and +``SSL_R_CERTIFICATE_VERIFY_FAILED``. We are now detecting this situation and +raising the appropiate ``ssl.SSLCertVerificationError``. Patch by Pablo +Galindo + +.. + +.. date: 2023-08-03-11-31-11 +.. gh-issue: 107576 +.. nonce: pO_s9I +.. section: Library + +Fix :func:`types.get_original_bases` to only return :attr:`!__orig_bases__` +if it is present on ``cls`` directly. Patch by James Hilton-Balfe. + +.. + +.. date: 2023-08-01-21-43-58 +.. gh-issue: 105481 +.. nonce: cl2ajS +.. section: Library + +Remove ``opcode.is_pseudo``, ``opcode.MIN_PSEUDO_OPCODE`` and +``opcode.MAX_PSEUDO_OPCODE``, which were added in 3.12, were never +documented and were not intended to be used externally. + +.. + +.. date: 2023-08-01-15-17-20 +.. gh-issue: 105481 +.. nonce: vMbmj_ +.. section: Library + +:data:`opcode.ENABLE_SPECIALIZATION` (which was added in 3.12 but never +documented or intended for external usage) is moved to +:data:`_opcode.ENABLE_SPECIALIZATION` where tests can access it. + +.. + +.. date: 2023-07-31-07-36-24 +.. gh-issue: 107396 +.. nonce: 3_Kh6D +.. section: Library + +tarfiles; Fixed use before assignment of self.exception for gzip +decompression + +.. + +.. date: 2023-07-29-02-36-50 +.. gh-issue: 107409 +.. nonce: HG27Nu +.. section: Library + +Set :attr:`!__wrapped__` attribute in :func:`reprlib.recursive_repr`. + +.. + +.. date: 2023-07-29-02-01-24 +.. gh-issue: 107406 +.. nonce: ze6sQP +.. section: Library + +Implement new :meth:`__repr__` method for :class:`struct.Struct`. Now it +returns ``Struct()``. + +.. + +.. date: 2023-07-28-14-56-35 +.. gh-issue: 107369 +.. nonce: bvTq8F +.. section: Library + +Optimize :func:`textwrap.indent`. It is ~30% faster for large input. Patch +by Inada Naoki. + +.. + +.. date: 2023-07-26-22-52-48 +.. gh-issue: 78722 +.. nonce: 6SKBLt +.. section: Library + +Fix issue where :meth:`pathlib.Path.iterdir` did not raise :exc:`OSError` +until iterated. + +.. + +.. date: 2023-07-23-13-05-32 +.. gh-issue: 105578 +.. nonce: XAQtyR +.. section: Library + +Deprecate :class:`typing.AnyStr` in favor of the new Type Parameter syntax. +See PEP 695. + +.. + +.. date: 2023-07-23-12-26-23 +.. gh-issue: 62519 +.. nonce: w8-81X +.. section: Library + +Make :func:`gettext.pgettext` search plural definitions when translation is +not found. + +.. + +.. date: 2023-07-22-21-57-34 +.. gh-issue: 107089 +.. nonce: Dnget2 +.. section: Library + +Shelves opened with :func:`shelve.open` have a much faster :meth:`clear` +method. Patch by James Cave. + +.. + +.. date: 2023-07-22-16-44-58 +.. gh-issue: 82500 +.. nonce: cQYoPj +.. section: Library + +Fix overflow on 32-bit systems with :mod:`asyncio` :func:`os.sendfile` +implemention. + +.. + +.. date: 2023-07-22-15-51-33 +.. gh-issue: 83006 +.. nonce: 21zaCz +.. section: Library + +Document behavior of :func:`shutil.disk_usage` for non-mounted filesystems +on Unix. + +.. + +.. date: 2023-07-22-14-29-34 +.. gh-issue: 65495 +.. nonce: fw84qM +.. section: Library + +Use lowercase ``mail from`` and ``rcpt to`` in :class:`smptlib.SMTP`. + +.. + +.. date: 2023-07-22-13-09-28 +.. gh-issue: 106186 +.. nonce: EIsUNG +.. section: Library + +Do not report ``MultipartInvariantViolationDefect`` defect when the +:class:`email.parser.Parser` class is used to parse emails with +``headersonly=True``. + +.. + +.. date: 2023-07-22-12-53-53 +.. gh-issue: 105002 +.. nonce: gkfsW0 +.. section: Library + +Fix invalid result from :meth:`PurePath.relative_to` method when attempting +to walk a "``..``" segment in *other* with *walk_up* enabled. A +:exc:`ValueError` exception is now raised in this case. + +.. + +.. date: 2023-07-20-06-00-35 +.. gh-issue: 106739 +.. nonce: W1hygr +.. section: Library + +Add the ``rtype_cache`` to the warning message (as an addition to the type +of leaked objects and the number of leaked objects already included in the +message) to make debugging leaked objects easier when the multiprocessing +resource tracker process finds leaked objects at shutdown. This helps more +quickly identify what was leaked and/or why the leaked object was not +properly cleaned up. + +.. + +.. date: 2023-07-19-10-45-24 +.. gh-issue: 106751 +.. nonce: 3HJ1of +.. section: Library + +Optimize :meth:`SelectSelector.select` for many iteration case. Patch By +Donghee Na. + +.. + +.. date: 2023-07-19-09-11-08 +.. gh-issue: 106751 +.. nonce: U9nD_B +.. section: Library + +Optimize :meth:`_PollLikeSelector.select` for many iteration case. + +.. + +.. date: 2023-07-18-23-05-12 +.. gh-issue: 106751 +.. nonce: tVvzN_ +.. section: Library + +Optimize :meth:`KqueueSelector.select` for many iteration case. Patch By +Donghee Na. + +.. + +.. date: 2023-07-17-21-45-15 +.. gh-issue: 106831 +.. nonce: RqVq9X +.. section: Library + +Fix potential missing ``NULL`` check of ``d2i_SSL_SESSION`` result in +``_ssl.c``. + +.. + +.. date: 2023-07-17-16-46-00 +.. gh-issue: 105481 +.. nonce: fek_Nn +.. section: Library + +The various opcode lists in the :mod:`dis` module are now generated from +bytecodes.c instead of explicitly constructed in opcode.py. + +.. + +.. date: 2023-07-16-23-59-33 +.. gh-issue: 106727 +.. nonce: bk3uCu +.. section: Library + +Make :func:`inspect.getsource` smarter for class for same name definitions + +.. + +.. date: 2023-07-16-10-40-34 +.. gh-issue: 106789 +.. nonce: NvyE3C +.. section: Library + +Remove import of :mod:`pprint` from :mod:`sysconfig`. + +.. + +.. date: 2023-07-15-12-52-50 +.. gh-issue: 105726 +.. nonce: NGthO8 +.. section: Library + +Added ``__slots__`` to :class:`contextlib.AbstractContextManager` and +:class:`contextlib.AbstractAsyncContextManager` so that child classes can +use ``__slots__``. + +.. + +.. date: 2023-07-15-10-24-56 +.. gh-issue: 106774 +.. nonce: FJcqCj +.. section: Library + +Update the bundled copy of pip to version 23.2.1. + +.. + +.. date: 2023-07-14-20-31-09 +.. gh-issue: 106751 +.. nonce: 52F6yQ +.. section: Library + +:mod:`selectors`: Optimize ``EpollSelector.select()`` code by moving some +code outside of the loop. + +.. + +.. date: 2023-07-14-16-54-13 +.. gh-issue: 106752 +.. nonce: BT1Yxw +.. section: Library + +Fixed several bugs in zipfile.Path, including: in +:meth:`zipfile.Path.match`, Windows separators are no longer honored (and +never were meant to be); Fixed ``name``/``suffix``/``suffixes``/``stem`` +operations when no filename is present and the Path is not at the root of +the zipfile; Reworked glob for performance and more correct matching +behavior. + +.. + +.. date: 2023-07-14-14-53-58 +.. gh-issue: 105293 +.. nonce: kimf_i +.. section: Library + +Remove call to ``SSL_CTX_set_session_id_context`` during client side context +creation in the :mod:`ssl` module. + +.. + +.. date: 2023-07-14-01-47-39 +.. gh-issue: 106734 +.. nonce: eMYSoz +.. section: Library + +Disable tab completion in multiline mode of :mod:`pdb` + +.. + +.. date: 2023-07-13-16-04-15 +.. gh-issue: 105481 +.. nonce: pYSwMj +.. section: Library + +Expose opcode metadata through :mod:`_opcode`. + +.. + +.. date: 2023-07-12-10-59-08 +.. gh-issue: 106670 +.. nonce: goQ2Sy +.. section: Library + +Add the new ``exceptions`` command to the Pdb debugger. It makes it possible +to move between chained exceptions when using post mortem debugging. + +.. + +.. date: 2023-07-12-04-58-45 +.. gh-issue: 106602 +.. nonce: dGCcXe +.. section: Library + +Add __copy__ and __deepcopy__ in :mod:`enum` + +.. + +.. date: 2023-07-12-03-04-45 +.. gh-issue: 106664 +.. nonce: ZeUG78 +.. section: Library + +:mod:`selectors`: Add ``_SelectorMapping.get()`` method and optimize +``_SelectorMapping.__getitem__()``. + +.. + +.. date: 2023-07-11-16-36-22 +.. gh-issue: 106628 +.. nonce: Kx8Zvc +.. section: Library + +Speed up parsing of emails by about 20% by not compiling a new regular +expression for every single email. + +.. + +.. date: 2023-07-11-12-34-04 +.. gh-issue: 89427 +.. nonce: GOkCp9 +.. section: Library + +Set the environment variable ``VIRTUAL_ENV_PROMPT`` at :mod:`venv` +activation, even when ``VIRTUAL_ENV_DISABLE_PROMPT`` is set. + +.. + +.. date: 2023-07-11-09-25-40 +.. gh-issue: 106530 +.. nonce: VgXrMx +.. section: Library + +Revert a change to :func:`colorsys.rgb_to_hls` that caused division by zero +for certain almost-white inputs. Patch by Terry Jan Reedy. + +.. + +.. date: 2023-07-11-08-56-40 +.. gh-issue: 106584 +.. nonce: g-SBtC +.. section: Library + +Fix exit code for ``unittest`` if all tests are skipped. Patch by Egor +Eliseev. + +.. + +.. date: 2023-07-09-13-10-54 +.. gh-issue: 106566 +.. nonce: NN35-U +.. section: Library + +Optimize ``(?!)`` (pattern which alwais fails) in regular expressions. + +.. + +.. date: 2023-07-09-01-59-24 +.. gh-issue: 106554 +.. nonce: 37c53J +.. section: Library + +:mod:`selectors`: Reduce Selector overhead by using a ``dict.get()`` to +lookup file descriptors. + +.. + +.. date: 2023-07-09-00-36-33 +.. gh-issue: 106558 +.. nonce: Zqsj6F +.. section: Library + +Remove ref cycle in callers of +:func:`~multiprocessing.managers.convert_to_error` by deleting ``result`` +from scope in a ``finally`` block. + +.. + +.. date: 2023-07-07-21-15-17 +.. gh-issue: 100502 +.. nonce: Iici1B +.. section: Library + +Add :attr:`pathlib.PurePath.pathmod` class attribute that stores the +implementation of :mod:`os.path` used for low-level path operations: either +``posixpath`` or ``ntpath``. + +.. + +.. date: 2023-07-07-18-22-07 +.. gh-issue: 106527 +.. nonce: spHQ0W +.. section: Library + +Reduce overhead to add and remove :mod:`asyncio` readers and writers. + +.. + +.. date: 2023-07-07-17-44-03 +.. gh-issue: 106524 +.. nonce: XkBV8h +.. section: Library + +Fix crash in :func:`!_sre.template` with templates containing invalid group +indices. + +.. + +.. date: 2023-07-07-16-19-59 +.. gh-issue: 106531 +.. nonce: eMfNm8 +.. section: Library + +Removed ``_legacy`` and the names it provided from ``importlib.resources``: +``Resource``, ``contents``, ``is_resource``, ``open_binary``, ``open_text``, +``path``, ``read_binary``, and ``read_text``. + +.. + +.. date: 2023-07-07-14-52-31 +.. gh-issue: 106052 +.. nonce: ak8nbs +.. section: Library + +:mod:`re` module: fix the matching of possessive quantifiers in the case of +a subpattern containing backtracking. + +.. + +.. date: 2023-07-07-13-47-28 +.. gh-issue: 106510 +.. nonce: 9n5BdC +.. section: Library + +Improve debug output for atomic groups in regular expressions. + +.. + +.. date: 2023-07-07-03-05-58 +.. gh-issue: 106503 +.. nonce: ltfeiH +.. section: Library + +Fix ref cycle in :class:`!asyncio._SelectorSocketTransport` by removing +``_write_ready`` in ``close``. + +.. + +.. date: 2023-07-05-14-34-10 +.. gh-issue: 105497 +.. nonce: HU5u89 +.. section: Library + +Fix flag mask inversion when unnamed flags exist. + +.. + +.. date: 2023-07-05-13-08-23 +.. gh-issue: 90876 +.. nonce: Qvlkfl +.. section: Library + +Prevent :mod:`multiprocessing.spawn` from failing to *import* in +environments where ``sys.executable`` is ``None``. This regressed in 3.11 +with the addition of support for path-like objects in multiprocessing. + +.. + +.. date: 2023-07-04-07-25-30 +.. gh-issue: 106403 +.. nonce: GmefbV +.. section: Library + +Instances of :class:`typing.TypeVar`, :class:`typing.ParamSpec`, +:class:`typing.ParamSpecArgs`, :class:`typing.ParamSpecKwargs`, and +:class:`typing.TypeVarTuple` once again support weak references, fixing a +regression introduced in Python 3.12.0 beta 1. Patch by Jelle Zijlstra. + +.. + +.. date: 2023-07-03-20-23-56 +.. gh-issue: 89812 +.. nonce: cFkDOE +.. section: Library + +Add private ``pathlib._PathBase`` class, which provides experimental support +for virtual filesystems, and may be made public in a future version of +Python. + +.. + +.. date: 2023-07-03-15-09-44 +.. gh-issue: 106292 +.. nonce: 3npldV +.. section: Library + +Check for an instance-dict cached value in the :meth:`__get__` method of +:func:`functools.cached_property`. This better matches the pre-3.12 behavior +and improves compatibility for users subclassing +:func:`functools.cached_property` and adding a :meth:`__set__` method. + +.. + +.. date: 2023-07-03-03-46-20 +.. gh-issue: 106350 +.. nonce: LLcTEe +.. section: Library + +Detect possible memory allocation failure in the libtommath function +:c:func:`mp_init` used by the ``_tkinter`` module. + +.. + +.. date: 2023-07-02-10-56-41 +.. gh-issue: 106330 +.. nonce: QSkIUH +.. section: Library + +Fix incorrect matching of empty paths in :meth:`pathlib.PurePath.match`. +This bug was introduced in Python 3.12.0 beta 1. + +.. + +.. date: 2023-07-01-16-51-55 +.. gh-issue: 106309 +.. nonce: hSlB17 +.. section: Library + +Deprecate :func:`typing.no_type_check_decorator`. No major type checker ever +added support for this decorator. Patch by Alex Waygood. + +.. + +.. date: 2023-07-01-16-40-54 +.. gh-issue: 102541 +.. nonce: C1ahtk +.. section: Library + +Make pydoc.doc catch bad module ImportError when output stream is not None. + +.. + +.. date: 2023-06-30-16-42-44 +.. gh-issue: 106263 +.. nonce: tk-t93 +.. section: Library + +Fix crash when calling ``repr`` with a manually constructed SignalDict +object. Patch by Charlie Zhao. + +.. + +.. date: 2023-06-29-15-10-44 +.. gh-issue: 106236 +.. nonce: EAIX4l +.. section: Library + +Replace ``assert`` statements with ``raise RuntimeError`` in +:mod:`threading`, so that ``_DummyThread`` cannot be joined even with +``-OO``. + +.. + +.. date: 2023-06-29-12-40-52 +.. gh-issue: 106238 +.. nonce: VulKb9 +.. section: Library + +Fix rare concurrency bug in lock acquisition by the logging package. + +.. + +.. date: 2023-06-27-23-22-37 +.. gh-issue: 106152 +.. nonce: ya5jBT +.. section: Library + +Added PY_THROW event hook for :mod:`cProfile` for generators + +.. + +.. date: 2023-06-25-12-28-55 +.. gh-issue: 106075 +.. nonce: W7tMRb +.. section: Library + +Added ``asyncio.taskgroups.__all__`` to ``asyncio.__all__`` for export in +star imports. + +.. + +.. date: 2023-06-25-06-57-24 +.. gh-issue: 104527 +.. nonce: TJEUkd +.. section: Library + +Zipapp will now skip over apending an archive to itself. + +.. + +.. date: 2023-06-23-22-52-24 +.. gh-issue: 106046 +.. nonce: OdLiLJ +.. section: Library + +Improve the error message from :func:`os.fspath` if called on an object +where ``__fspath__`` is set to ``None``. Patch by Alex Waygood. + +.. + +.. date: 2023-06-22-15-21-11 +.. gh-issue: 105987 +.. nonce: T7Kzrb +.. section: Library + +Fix crash due to improper reference counting in :mod:`asyncio` eager task +factory internal routines. + +.. + +.. date: 2023-06-21-19-04-27 +.. gh-issue: 105974 +.. nonce: M47n3t +.. section: Library + +Fix bug where a :class:`typing.Protocol` class that had one or more +non-callable members would raise :exc:`TypeError` when :func:`issubclass` +was called against it, even if it defined a custom ``__subclasshook__`` +method. The behaviour in Python 3.11 and lower -- which has now been +restored -- was not to raise :exc:`TypeError` in these situations if a +custom ``__subclasshook__`` method was defined. Patch by Alex Waygood. + +.. + +.. date: 2023-06-20-23-18-45 +.. gh-issue: 96145 +.. nonce: o5dTRM +.. section: Library + +Reverted addition of ``json.AttrDict``. + +.. + +.. date: 2023-06-19-22-20-41 +.. gh-issue: 89812 +.. nonce: z2l_e8 +.. section: Library + +Add :exc:`pathlib.UnsupportedOperation`, which is raised instead of +:exc:`NotImplementedError` when a path operation isn't supported. + +.. + +.. date: 2023-06-19-11-31-55 +.. gh-issue: 105808 +.. nonce: NL-quu +.. section: Library + +Fix a regression introduced in GH-101251 for 3.12, causing +:meth:`gzip.GzipFile.flush` to not flush the compressor (nor pass along the +``zip_mode`` argument). + +.. + +.. date: 2023-06-17-12-13-57 +.. gh-issue: 105481 +.. nonce: KgBH5w +.. section: Library + +:func:`~dis.stack_effect` no longer raises an exception if an ``oparg`` is +provided for an ``opcode`` that doesn't use its arg, or when it is not +provided for an ``opcode`` that does use it. In the latter case, the stack +effect is returned for ``oparg=0``. + +.. + +.. date: 2023-06-15-18-11-47 +.. gh-issue: 104799 +.. nonce: BcLzbP +.. section: Library + +Enable :func:`ast.unparse` to unparse function and class definitions created +without the new ``type_params`` field from :pep:`695`. Patch by Jelle +Zijlstra. + +.. + +.. date: 2023-06-14-18-41-18 +.. gh-issue: 105793 +.. nonce: YSoykM +.. section: Library + +Add *follow_symlinks* keyword-only argument to :meth:`pathlib.Path.is_dir` +and :meth:`~pathlib.Path.is_file`, defaulting to ``True``. + +.. + +.. date: 2023-06-14-14-32-31 +.. gh-issue: 105570 +.. nonce: sFTtQU +.. section: Library + +Deprecate two methods of creating :class:`typing.TypedDict` classes with 0 +fields using the functional syntax: ``TD = TypedDict("TD")`` and ``TD = +TypedDict("TD", None)``. Both will be disallowed in Python 3.15. To create a +``TypedDict`` class with 0 fields, either use ``class TD(TypedDict): pass`` +or ``TD = TypedDict("TD", {})``. + +.. + +.. date: 2023-06-14-10-27-34 +.. gh-issue: 105745 +.. nonce: l1ttOQ +.. section: Library + +Fix ``webbrowser.Konqueror.open`` method. + +.. + +.. date: 2023-06-13-19-38-12 +.. gh-issue: 105733 +.. nonce: WOp0mG +.. section: Library + +:mod:`ctypes`: Deprecate undocumented :func:`!ctypes.SetPointerType` and +:func:`!ctypes.ARRAY` functions. Patch by Victor Stinner. + +.. + +.. date: 2023-06-12-15-17-34 +.. gh-issue: 105687 +.. nonce: ZUonKm +.. section: Library + +Remove deprecated ``re.template``, ``re.T``, ``re.TEMPLATE``, +``sre_constans.SRE_FLAG_TEMPLATE``. + +.. + +.. date: 2023-06-12-10-40-38 +.. gh-issue: 105684 +.. nonce: yiHkFD +.. section: Library + +Supporting :meth:`asyncio.Task.set_name` is now mandatory for third party +task implementations. The undocumented :func:`!_set_task_name` function +(deprecated since 3.8) has been removed. Patch by Kumar Aditya. + +.. + +.. date: 2023-06-11-22-46-06 +.. gh-issue: 105375 +.. nonce: YkhSNt +.. section: Library + +Fix a bug in :c:func:`!_Unpickler_SetInputStream` where an exception could +end up being overwritten in case of failure. + +.. + +.. date: 2023-06-10-12-20-17 +.. gh-issue: 105626 +.. nonce: XyZein +.. section: Library + +Change the default return value of +:meth:`http.client.HTTPConnection.get_proxy_response_headers` to be ``None`` +and not ``{}``. + +.. + +.. date: 2023-06-09-23-46-23 +.. gh-issue: 105375 +.. nonce: 9KaioS +.. section: Library + +Fix bugs in :mod:`sys` where exceptions could end up being overwritten +because of deferred error handling. + +.. + +.. date: 2023-06-09-23-00-13 +.. gh-issue: 105605 +.. nonce: YuwqxY +.. section: Library + +Harden :mod:`pyexpat` error handling during module initialisation to prevent +exceptions from possibly being overwritten, and objects from being +dereferenced twice. + +.. + +.. date: 2023-06-09-22-52-45 +.. gh-issue: 105375 +.. nonce: 6igkhn +.. section: Library + +Fix bug in :mod:`decimal` where an exception could end up being overwritten. + +.. + +.. date: 2023-06-09-22-45-26 +.. gh-issue: 105375 +.. nonce: 9rp6tG +.. section: Library + +Fix bugs in :mod:`!_datetime` where exceptions could be overwritten in case +of module initialisation failure. + +.. + +.. date: 2023-06-09-22-16-46 +.. gh-issue: 105375 +.. nonce: EgVJOP +.. section: Library + +Fix bugs in :mod:`!_ssl` initialisation which could lead to leaked +references and overwritten exceptions. + +.. + +.. date: 2023-06-09-21-46-52 +.. gh-issue: 105375 +.. nonce: yrJelV +.. section: Library + +Fix a bug in :class:`array.array` where an exception could end up being +overwritten. + +.. + +.. date: 2023-06-09-21-40-45 +.. gh-issue: 105375 +.. nonce: _sZilh +.. section: Library + +Fix bugs in :mod:`_ctypes` where exceptions could end up being overwritten. + +.. + +.. date: 2023-06-09-21-30-59 +.. gh-issue: 105375 +.. nonce: eewafp +.. section: Library + +Fix a bug in the :mod:`posix` module where an exception could be +overwritten. + +.. + +.. date: 2023-06-09-21-25-14 +.. gh-issue: 105375 +.. nonce: 95g1eI +.. section: Library + +Fix bugs in :mod:`!_elementtree` where exceptions could be overwritten. + +.. + +.. date: 2023-06-09-21-11-28 +.. gh-issue: 105375 +.. nonce: 4Mxn7t +.. section: Library + +Fix bugs in :mod:`zoneinfo` where exceptions could be overwritten. + +.. + +.. date: 2023-06-09-21-04-39 +.. gh-issue: 105375 +.. nonce: bTcqS9 +.. section: Library + +Fix bugs in :mod:`errno` where exceptions could be overwritten. + +.. + +.. date: 2023-06-09-20-34-23 +.. gh-issue: 105566 +.. nonce: YxlGg1 +.. section: Library + +Deprecate creating a :class:`typing.NamedTuple` class using keyword +arguments to denote the fields (``NT = NamedTuple("NT", x=int, y=str)``). +This will be disallowed in Python 3.15. Use the class-based syntax or the +functional syntax instead. + +Two methods of creating ``NamedTuple`` classes with 0 fields using the +functional syntax are also deprecated, and will be disallowed in Python +3.15: ``NT = NamedTuple("NT")`` and ``NT = NamedTuple("NT", None)``. To +create a ``NamedTuple`` class with 0 fields, either use ``class +NT(NamedTuple): pass`` or ``NT = NamedTuple("NT", [])``. + +.. + +.. date: 2023-06-09-08-38-30 +.. gh-issue: 105545 +.. nonce: 2q3ysu +.. section: Library + +Remove deprecated in 3.11 ``webbrowser.MacOSXOSAScript._name`` attribute. + +.. + +.. date: 2023-06-08-17-49-46 +.. gh-issue: 105497 +.. nonce: K6Q8nU +.. section: Library + +Fix flag inversion when alias/mask members exist. + +.. + +.. date: 2023-06-08-15-56-45 +.. gh-issue: 105509 +.. nonce: YIG57j +.. section: Library + +:data:`typing.Annotated` is now implemented as an instance of +``typing._SpecialForm`` rather than a class. This should have no user-facing +impact for users of the :mod:`typing` module public API. + +.. + +.. date: 2023-06-08-08-58-36 +.. gh-issue: 105375 +.. nonce: bTcqS9 +.. section: Library + +Fix bugs in :mod:`pickle` where exceptions could be overwritten. + +.. + +.. date: 2023-06-07-00-13-00 +.. gh-issue: 70303 +.. nonce: frwUKH +.. section: Library + +Emit :exc:`FutureWarning` from :meth:`pathlib.Path.glob` and +:meth:`~pathlib.Path.rglob` if the given pattern ends with "``**``". In a +future Python release, patterns with this ending will match both files and +directories. Add a trailing slash to only match directories. + +.. + +.. date: 2023-06-07-00-09-52 +.. gh-issue: 105375 +.. nonce: Y_9D4n +.. section: Library + +Fix a bug in :mod:`sqlite3` where an exception could be overwritten in the +:meth:`collation ` callback. + +.. + +.. date: 2023-06-06-16-00-03 +.. gh-issue: 105382 +.. nonce: A1LgzA +.. section: Library + +Remove *cafile*, *capath* and *cadefault* parameters of the +:func:`urllib.request.urlopen` function, deprecated in Python 3.6. Patch by +Victor Stinner. + +.. + +.. date: 2023-06-06-15-32-44 +.. gh-issue: 105376 +.. nonce: W4oDQp +.. section: Library + +:mod:`logging`: Remove undocumented and untested ``Logger.warn()`` and +``LoggerAdapter.warn()`` methods and ``logging.warn()`` function. Deprecated +since Python 3.3, they were aliases to the :meth:`logging.Logger.warning` +method, :meth:`!logging.LoggerAdapter.warning` method and +:func:`logging.warning` function. Patch by Victor Stinner. + +.. + +.. date: 2023-06-06-11-50-33 +.. gh-issue: 105332 +.. nonce: tmpgRA +.. section: Library + +Revert pickling method from by-name back to by-value. + +.. + +.. date: 2023-06-05-14-43-56 +.. gh-issue: 104554 +.. nonce: pwfKIo +.. section: Library + +Add RTSPS scheme support in urllib.parse + +.. + +.. date: 2023-06-04-23-20-56 +.. gh-issue: 105292 +.. nonce: ns6XQR +.. section: Library + +Add option to :func:`traceback.format_exception_only` to recurse into the +nested exception of a :exc:`BaseExceptionGroup`. + +.. + +.. date: 2023-06-04-12-16-47 +.. gh-issue: 105280 +.. nonce: srRbCe +.. section: Library + +Fix bug where ``isinstance([], collections.abc.Mapping)`` could evaluate to +``True`` if garbage collection happened at the wrong time. The bug was +caused by changes to the implementation of :class:`typing.Protocol` in +Python 3.12. + +.. + +.. date: 2023-06-02-23-32-17 +.. gh-issue: 80480 +.. nonce: savBw9 +.. section: Library + +:mod:`array`: Add ``'w'`` typecode that represents ``Py_UCS4``. + +.. + +.. date: 2023-06-02-14-57-11 +.. gh-issue: 105239 +.. nonce: SAmuuj +.. section: Library + +Fix longstanding bug where ``issubclass(object, typing.Protocol)`` would +evaluate to ``True`` in some edge cases. Patch by Alex Waygood. + +.. + +.. date: 2023-06-02-14-23-41 +.. gh-issue: 104310 +.. nonce: UamCOB +.. section: Library + +In the beta 1 release we added a utility function for extension module +authors, to use when testing their module for support in multiple +interpreters or under a per-interpreter GIL. The name of that function has +changed from ``allowing_all_extensions`` to +``_incompatible_extension_module_restrictions``. The default for the +"disable_check" argument has change from ``True`` to ``False``, to better +match the new function name. + +.. + +.. date: 2023-06-02-02-38-26 +.. gh-issue: 105080 +.. nonce: 2imGMg +.. section: Library + +Fixed inconsistent signature on derived classes for +:func:`inspect.signature` + +.. + +.. date: 2023-05-31-16-58-42 +.. gh-issue: 105144 +.. nonce: Oqfn0V +.. section: Library + +Fix a recent regression in the :mod:`typing` module. The regression meant +that doing ``class Foo(X, typing.Protocol)``, where ``X`` was a class that +had :class:`abc.ABCMeta` as its metaclass, would then cause subsequent +``isinstance(1, X)`` calls to erroneously raise :exc:`TypeError`. Patch by +Alex Waygood. + +.. + +.. date: 2023-05-30-18-45-02 +.. gh-issue: 62948 +.. nonce: 1-5wMR +.. section: Library + +The :class:`io.IOBase` finalizer now logs the ``close()`` method errors with +:data:`sys.unraisablehook`. Previously, errors were ignored silently by +default, and only logged in :ref:`Python Development Mode ` or on +:ref:`Python built on debug mode `. Patch by Victor Stinner. + +.. + +.. date: 2023-05-30-17-39-03 +.. gh-issue: 105096 +.. nonce: pw00FW +.. section: Library + +:mod:`wave`: Deprecate the ``getmark()``, ``setmark()`` and ``getmarkers()`` +methods of the :class:`wave.Wave_read` and :class:`wave.Wave_write` classes. +They will be removed in Python 3.15. Patch by Victor Stinner. + +.. + +.. date: 2023-05-26-21-33-24 +.. gh-issue: 104992 +.. nonce: dbq9WK +.. section: Library + +Remove the untested and undocumented :meth:`!unittest.TestProgram.usageExit` +method, deprecated in Python 3.11. Patch by Hugo van Kemenade. + +.. + +.. date: 2023-05-26-21-24-06 +.. gh-issue: 104996 +.. nonce: aaW78g +.. section: Library + +Improve performance of :class:`pathlib.PurePath` initialisation by deferring +joining of paths when multiple arguments are given. + +.. + +.. date: 2023-05-26-01-31-30 +.. gh-issue: 101588 +.. nonce: RaqxFy +.. section: Library + +Deprecate undocumented copy/deepcopy/pickle support for itertools. + +.. + +.. date: 2023-05-25-23-34-54 +.. gh-issue: 103631 +.. nonce: x5Urye +.. section: Library + +Fix ``pathlib.PurePosixPath(pathlib.PureWindowsPath(...))`` not converting +path separators to restore 3.11 compatible behavior. + +.. + +.. date: 2023-05-25-22-54-20 +.. gh-issue: 104947 +.. nonce: hi6TUr +.. section: Library + +Make comparisons between :class:`pathlib.PureWindowsPath` objects consistent +across Windows and Posix to match 3.11 behavior. + +.. + +.. date: 2023-05-25-17-25-16 +.. gh-issue: 104773 +.. nonce: O6TOMc +.. section: Library + +:pep:`594`: Remove the :mod:`!audioop` module, deprecated in Python 3.11. +Patch by Victor Stinner. + +.. + +.. date: 2023-05-25-16-50-43 +.. gh-issue: 104773 +.. nonce: pmg0Fr +.. section: Library + +:pep:`594`: Remove the :mod:`!aifc` module, deprecated in Python 3.11. Patch +by Victor Stinner. + +.. + +.. date: 2023-05-25-15-54-02 +.. gh-issue: 104773 +.. nonce: nW-5MI +.. section: Library + +:pep:`594`: Remove the :mod:`!uu` module, deprecated in Python 3.11. Patch +by Victor Stinner. + +.. + +.. date: 2023-05-25-08-50-47 +.. gh-issue: 104935 +.. nonce: -rm1BR +.. section: Library + +Fix bugs with the interaction between :func:`typing.runtime_checkable` and +:class:`typing.Generic` that were introduced by the :pep:`695` +implementation. Patch by Jelle Zijlstra. + +.. + +.. date: 2023-05-25-00-53-08 +.. gh-issue: 104773 +.. nonce: Iyjtt0 +.. section: Library + +:pep:`594`: Remove the :mod:`!crypt` module and its private :mod:`!_crypt` +extension, deprecated in Python 3.11. Patch by Victor Stinner. + +.. + +.. date: 2023-05-24-23-40-22 +.. gh-issue: 104773 +.. nonce: FHA99J +.. section: Library + +:pep:`594`: Remove the :mod:`!nis` module, deprecated in Python 3.11. Patch +by Victor Stinner. + +.. + +.. date: 2023-05-24-22-50-21 +.. gh-issue: 104898 +.. nonce: UbT2S4 +.. section: Library + +Add missing :attr:`~object.__slots__` to :class:`os.PathLike`. + +.. + +.. date: 2023-05-24-22-47-13 +.. gh-issue: 104773 +.. nonce: itOIf3 +.. section: Library + +:pep:`594`: Remove the :mod:`!xdrlib` module, deprecated in Python 3.11. +Patch by Victor Stinner. + +.. + +.. date: 2023-05-24-22-22-03 +.. gh-issue: 104773 +.. nonce: NwpjhZ +.. section: Library + +:pep:`594`: Remove the :mod:`!nntplib` module, deprecated in Python 3.11. +Patch by Victor Stinner. + +.. + +.. date: 2023-05-24-21-30-40 +.. gh-issue: 104886 +.. nonce: 8TuV-_ +.. section: Library + +Remove the undocumented :class:`!configparser.LegacyInterpolation` class, +deprecated in the docstring since Python 3.2, and with a deprecation warning +since Python 3.11. Patch by Hugo van Kemenade. + +.. + +.. date: 2023-05-24-20-21-27 +.. gh-issue: 104786 +.. nonce: SmgT5_ +.. section: Library + +Remove kwargs-based :class:`typing.TypedDict` creation + +.. + +.. date: 2023-05-24-19-48-16 +.. gh-issue: 104876 +.. nonce: Z00Qnk +.. section: Library + +Remove the :meth:`!turtle.RawTurtle.settiltangle` method, deprecated in docs +since Python 3.1 and with a deprecation warning since Python 3.11. Patch by +Hugo van Kemenade. + +.. + +.. date: 2023-05-24-18-48-10 +.. gh-issue: 104773 +.. nonce: TrgUeO +.. section: Library + +:pep:`594`: Removed the :mod:`!msilib` package, deprecated in Python 3.11. + +.. + +.. date: 2023-05-24-17-47-25 +.. gh-issue: 104773 +.. nonce: TzUSY2 +.. section: Library + +:pep:`594`: Remove the :mod:`!spwd` module, deprecated in Python 3.11: the +`python-pam project `_ can be used +instead. Patch by Victor Stinner. + +.. + +.. date: 2023-05-24-17-22-56 +.. gh-issue: 75552 +.. nonce: _QlrpQ +.. section: Library + +Removed the ``tkinter.tix`` module, deprecated since Python 3.6. + +.. + +.. date: 2023-05-24-15-57-34 +.. gh-issue: 104773 +.. nonce: IHWRgg +.. section: Library + +:pep:`594`: Remove the :mod:`!chunk` module, deprecated in Python 3.11. +Patch by Victor Stinner. + +.. + +.. date: 2023-05-24-15-17-05 +.. gh-issue: 104773 +.. nonce: EmFIQ5 +.. section: Library + +:pep:`594`: Remove the :mod:`!mailcap` module, deprecated in Python 3.11. +Patch by Victor Stinner. + +.. + +.. date: 2023-05-24-14-58-13 +.. gh-issue: 104773 +.. nonce: sQaXrY +.. section: Library + +:pep:`594`: Remove the :mod:`!sunau` module, deprecated in Python 3.11. +Patch by Victor Stinner. + +.. + +.. date: 2023-05-24-14-30-14 +.. gh-issue: 104780 +.. nonce: nXGIJt +.. section: Library + +:pep:`594`: Remove the :mod:`!ossaudiodev` module, deprecated in Python +3.11. Patch Victor Stinner. + +.. + +.. date: 2023-05-24-11-45-22 +.. gh-issue: 104773 +.. nonce: R0Br4- +.. section: Library + +:pep:`594`: Remove the :mod:`!pipes` module, deprecated in Python 3.11. +Patch by Victor Stinner. + +.. + +.. date: 2023-05-24-09-55-33 +.. gh-issue: 104873 +.. nonce: BKQ54y +.. section: Library + +Add :func:`typing.get_protocol_members` to return the set of members +defining a :class:`typing.Protocol`. Add :func:`typing.is_protocol` to +check whether a class is a :class:`typing.Protocol`. Patch by Jelle +Zijlstra. + +.. + +.. date: 2023-05-24-09-34-23 +.. gh-issue: 104874 +.. nonce: oqyJSy +.. section: Library + +Document the ``__name__`` and ``__supertype__`` attributes of +:class:`typing.NewType`. Patch by Jelle Zijlstra. + +.. + +.. date: 2023-05-24-08-45-04 +.. gh-issue: 104835 +.. nonce: bN_B-B +.. section: Library + +Removed the following :mod:`unittest` functions, deprecated in Python 3.11: + +* :func:`!unittest.findTestCases` +* :func:`!unittest.makeSuite` +* :func:`!unittest.getTestCaseNames` + +Use :class:`~unittest.TestLoader` methods instead: + +* :meth:`unittest.TestLoader.loadTestsFromModule` +* :meth:`unittest.TestLoader.loadTestsFromTestCase` +* :meth:`unittest.TestLoader.getTestCaseNames` + +Patch by Hugo van Kemenade. + +.. + +.. date: 2023-05-23-21-25-54 +.. gh-issue: 104804 +.. nonce: 78fiE6 +.. section: Library + +Remove the untested and undocumented :mod:`webbrowser` :class:`!MacOSX` +class, deprecated in Python 3.11. Patch by Hugo van Kemenade. + +.. + +.. date: 2023-05-23-19-53-18 +.. gh-issue: 83863 +.. nonce: eRI5JG +.. section: Library + +Support for using :class:`pathlib.Path` objects as context managers has been +removed. Before Python 3.9, exiting the context manager marked a path as +"closed", which caused some (but not all!) methods to raise when called. +Since Python 3.9, using a path as a context manager does nothing. + +.. + +.. date: 2023-05-23-18-31-49 +.. gh-issue: 104799 +.. nonce: MJYOw6 +.. section: Library + +Adjust the location of the (see :pep:`695`) ``type_params`` field on +:class:`ast.ClassDef`, :class:`ast.AsyncFunctionDef`, and +:class:`ast.FunctionDef` to better preserve backward compatibility. Patch by +Jelle Zijlstra + +.. + +.. date: 2023-05-23-17-43-52 +.. gh-issue: 104797 +.. nonce: NR7KzF +.. section: Library + +Allow :class:`typing.Protocol` classes to inherit from +:class:`collections.abc.Buffer`. Patch by Jelle Zijlstra. + +.. + +.. date: 2023-05-23-04-01-27 +.. gh-issue: 104783 +.. nonce: QyhIoq +.. section: Library + +Remove ``locale.resetlocale()`` function deprecated in Python 3.11. Patch by +Victor Stinner. + +.. + +.. date: 2023-05-23-03-36-47 +.. gh-issue: 104780 +.. nonce: P4e3Yf +.. section: Library + +Remove the ``2to3`` program and the :mod:`!lib2to3` module, deprecated in +Python 3.11. Patch by Victor Stinner. + +.. + +.. date: 2023-05-23-02-20-13 +.. gh-issue: 104773 +.. nonce: 7K59zr +.. section: Library + +:pep:`594`: Remove the :mod:`!telnetlib` module, deprecated in Python 3.11. +Patch by Victor Stinner. + +.. + +.. date: 2023-05-23-02-13-11 +.. gh-issue: 104773 +.. nonce: JNiEjv +.. section: Library + +:pep:`594`: Remove the :mod:`!imghdr` module, deprecated in Python 3.11. +Patch by Victor Stinner. + +.. + +.. date: 2023-05-23-01-47-57 +.. gh-issue: 104773 +.. nonce: I6MQhb +.. section: Library + +:pep:`594`: Remove the :mod:`!cgi`` and :mod:`!cgitb` modules, deprecated in +Python 3.11. Patch by Victor Stinner. + +.. + +.. date: 2023-05-23-01-37-40 +.. gh-issue: 104773 +.. nonce: 8c-GsG +.. section: Library + +:pep:`594`: Remove the :mod:`!sndhdr` module, deprecated in Python 3.11. +Patch by Victor Stinner. + +.. + +.. date: 2023-05-22-18-39-53 +.. gh-issue: 104372 +.. nonce: 7tDRaK +.. section: Library + +On Linux where :mod:`subprocess` can use the ``vfork()`` syscall for faster +spawning, prevent the parent process from blocking other threads by dropping +the GIL while it waits for the vfork'ed child process ``exec()`` outcome. +This prevents spawning a binary from a slow filesystem from blocking the +rest of the application. + +.. + +.. date: 2023-05-19-19-46-22 +.. gh-issue: 99108 +.. nonce: wqCg0t +.. section: Library + +We now release the GIL around built-in :mod:`hashlib` computations of +reasonable size for the SHA families and MD5 hash functions, matching what +our OpenSSL backed hash computations already does. + +.. + +.. date: 2023-05-15-18-57-42 +.. gh-issue: 102613 +.. nonce: YD9yx- +.. section: Library + +Improve performance of :meth:`pathlib.Path.glob` when expanding a pattern +with a non-terminal "``**``" component by filtering walked paths through a +regular expression, rather than calling :func:`os.scandir` more than once on +each directory. + +.. + +.. date: 2023-05-11-23-03-00 +.. gh-issue: 104399 +.. nonce: MMatTP +.. section: Library + +Prepare the ``_tkinter`` module for building with Tcl 9.0 and future +libtommath by replacing usage of deprecated functions +:c:func:`mp_to_unsigned_bin_n` and :c:func:`mp_unsigned_bin_size` when +necessary. + +.. + +.. date: 2023-04-28-09-31-21 +.. gh-issue: 102676 +.. nonce: J8qDRa +.. section: Library + +Add fields ``start_offset``, ``cache_offset``, ``end_offset``, +``baseopname``, ``baseopcode``, ``jump_target`` and ``oparg`` to +:class:`dis.Instruction`. + +.. + +.. date: 2023-04-15-23-26-16 +.. gh-issue: 103558 +.. nonce: w9OzK4 +.. section: Library + +Fixed ``parent`` argument validation mechanism of :mod:`argparse`. Improved +test coverage. + +.. + +.. date: 2023-04-12-03-03-27 +.. gh-issue: 103464 +.. nonce: Oa_8IW +.. section: Library + +Provide helpful usage messages when parsing incorrect :mod:`pdb` commands. + +.. + +.. date: 2023-04-09-05-30-41 +.. gh-issue: 103384 +.. nonce: zAV7iB +.. section: Library + +Generalize the regex pattern ``BaseConfigurator.INDEX_PATTERN`` to allow +spaces and non-alphanumeric characters in keys. + +.. + +.. date: 2023-04-09-03-53-02 +.. gh-issue: 103124 +.. nonce: JspiNN +.. section: Library + +Added multiline statement support for :mod:`pdb` + +.. + +.. date: 2023-04-08-12-43-52 +.. gh-issue: 101162 +.. nonce: yOCd_J +.. section: Library + +Forbid using :func:`builtins.issubclass` with :class:`types.GenericAlias` as +the first argument. + +.. + +.. date: 2023-04-03-08-09-40 +.. gh-issue: 103200 +.. nonce: lq1Etz +.. section: Library + +Fix cache repopulation semantics of zipimport.invalidate_caches(). The cache +is now repopulated upon retrieving files with an invalid cache, not when the +cache is invalidated. + +.. + +.. date: 2023-03-14-01-19-57 +.. gh-issue: 100061 +.. nonce: CiXJYn +.. section: Library + +Fix a bug that causes wrong matches for regular expressions with possessive +qualifier. + +.. + +.. date: 2023-03-12-03-37-03 +.. gh-issue: 77609 +.. nonce: aOQttm +.. section: Library + +Add *follow_symlinks* argument to :meth:`pathlib.Path.glob` and +:meth:`~pathlib.Path.rglob`, defaulting to false. + +.. + +.. date: 2023-03-12-01-17-15 +.. gh-issue: 102541 +.. nonce: LK1adc +.. section: Library + +Hide traceback in :func:`help` prompt, when import failed. + +.. + +.. date: 2023-03-08-19-30-53 +.. gh-issue: 102120 +.. nonce: xkQ5Wr +.. section: Library + +Added a stream mode to ``tarfile`` that allows for reading archives without +caching info about the inner files. + +.. + +.. date: 2023-02-20-15-41-59 +.. gh-issue: 102029 +.. nonce: 9ZPG99 +.. section: Library + +Deprecate passing any arguments to :func:`threading.RLock`. + +.. + +.. date: 2023-02-20-12-00-11 +.. gh-issue: 88233 +.. nonce: o5Zb0t +.. section: Library + +Refactored ``zipfile._strip_extra`` to use higher level abstactions for +extras instead of a heavy-state loop. + +.. + +.. date: 2023-02-18-22-55-48 +.. gh-issue: 102024 +.. nonce: RUmg_D +.. section: Library + +Reduce calls of ``_idle_semaphore.release()`` in +:func:`concurrent.futures.thread._worker`. + +.. + +.. date: 2023-02-17-18-56-46 +.. gh-issue: 73435 +.. nonce: 7sTJHk +.. section: Library + +Add support for recursive wildcards in :meth:`pathlib.PurePath.match`. + +.. + +.. date: 2022-12-24-12-50-54 +.. gh-issue: 84867 +.. nonce: OhaLbU +.. section: Library + +:class:`unittest.TestLoader` no longer loads test cases from exact +:class:`unittest.TestCase` and :class:`unittest.FunctionTestCase` classes. + +.. + +.. date: 2022-11-26-22-05-22 +.. gh-issue: 99203 +.. nonce: j0DUae +.. section: Library + +Restore following CPython <= 3.10.5 behavior of :func:`shutil.make_archive`: +do not create an empty archive if ``root_dir`` is not a directory, and, in +that case, raise :class:`FileNotFoundError` or :class:`NotADirectoryError` +regardless of ``format`` choice. Beyond the brought-back behavior, the +function may now also raise these exceptions in ``dry_run`` mode. + +.. + +.. date: 2022-08-07-11-10-26 +.. gh-issue: 80480 +.. nonce: IFccj3 +.. section: Library + +Emit :exc:`DeprecationWarning` for :mod:`array`'s ``'u'`` type code, +deprecated in docs since Python 3.3. + +.. + +.. date: 2022-07-18-14-20-56 +.. gh-issue: 94924 +.. nonce: X0buz2 +.. section: Library + +:func:`unittest.mock.create_autospec` now properly returns coroutine +functions compatible with :func:`inspect.iscoroutinefunction` + +.. + +.. date: 2022-07-12-18-45-13 +.. gh-issue: 94777 +.. nonce: mOybx7 +.. section: Library + +Fix hanging :mod:`multiprocessing` ``ProcessPoolExecutor`` when a child +process crashes while data is being written in the call queue. + +.. + +.. date: 2022-05-17-10-46-44 +.. gh-issue: 92871 +.. nonce: GVogrT +.. section: Library + +Remove the ``typing.io`` and ``typing.re`` namespaces, deprecated since +Python 3.8. All items are still available from the main :mod:`typing` +module. + +.. + +.. bpo: 43633 +.. date: 2021-10-31-16-06-28 +.. nonce: vflwXv +.. section: Library + +Improve the textual representation of IPv4-mapped IPv6 addresses +(:rfc:`4291` Sections 2.2, 2.5.5.2) in :mod:`ipaddress`. Patch by Oleksandr +Pavliuk. + +.. + +.. bpo: 44850 +.. date: 2021-08-16-17-52-26 +.. nonce: r8jx5u +.. section: Library + +Improve performance of :func:`operator.methodcaller` using the :pep:`590` +``vectorcall`` convention. Patch by Anthony Lee and Pieter Eendebak. + +.. + +.. bpo: 44185 +.. date: 2021-06-24-20-45-03 +.. nonce: ZHb8yJ +.. section: Library + +:func:`unittest.mock.mock_open` will call the :func:`close` method of the +file handle mock when it is exiting from the context manager. Patch by Samet +Yaslan. + +.. + +.. bpo: 40988 +.. date: 2020-11-10-07-04-15 +.. nonce: 5kBC-O +.. section: Library + +Improve performance of :class:`functools.singledispatchmethod` by caching +the generated dispatch wrapper. Optimization suggested by frederico. Patch +by @mental32, Alex Waygood and Pieter Eendebak. + +.. + +.. bpo: 41768 +.. date: 2020-09-16-16-53-06 +.. nonce: 8_fWkC +.. section: Library + +:mod:`unittest.mock` speccing no longer calls class properties. Patch by +Melanie Witt. + +.. + +.. bpo: 18319 +.. date: 2020-05-03-00-33-15 +.. nonce: faPTlx +.. section: Library + +Ensure ``gettext(msg)`` retrieve translations even if a plural form exists. +In other words: ``gettext(msg) == ngettext(msg, '', 1)``. + +.. + +.. bpo: 17013 +.. date: 2019-09-13-13-28-10 +.. nonce: NWcgE3 +.. section: Library + +Add ``ThreadingMock`` to :mod:`unittest.mock` that can be used to create +Mock objects that can wait until they are called. Patch by Karthikeyan +Singaravelan and Mario Corchero. + +.. + +.. date: 2023-09-10-02-39-06 +.. gh-issue: 109209 +.. nonce: 0LBewo +.. section: Documentation + +The minimum Sphinx version required for the documentation is now 4.2. + +.. + +.. date: 2023-09-03-13-43-49 +.. gh-issue: 108826 +.. nonce: KG7abS +.. section: Documentation + +:mod:`dis` module command-line interface is now mentioned in documentation. + +.. + +.. date: 2023-07-26-16-33-04 +.. gh-issue: 107305 +.. nonce: qB2LS4 +.. section: Documentation + +Add documentation for :c:type:`PyInterpreterConfig` and +:c:func:`Py_NewInterpreterFromConfig`. Also clarify some of the nearby docs +relative to per-interpreter GIL. + +.. + +.. date: 2023-07-22-15-14-13 +.. gh-issue: 107008 +.. nonce: 3JQ1Vt +.. section: Documentation + +Document the :mod:`curses` module variables :const:`~curses.LINES` and +:const:`~curses.COLS`. + +.. + +.. date: 2023-07-21-11-51-57 +.. gh-issue: 106948 +.. nonce: K_JQ7j +.. section: Documentation + +Add a number of standard external names to ``nitpick_ignore``. + +.. + +.. date: 2023-06-30-19-28-59 +.. gh-issue: 106232 +.. nonce: hQ4-tz +.. section: Documentation + +Make timeit doc command lines compatible with Windows by using double quotes +for arguments. This works on linux and macOS also. + +.. + +.. date: 2023-05-31-23-05-51 +.. gh-issue: 105172 +.. nonce: SVfvkD +.. section: Documentation + +Fixed :func:`functools.lru_cache` docstring accounting for ``typed`` +argument's different handling of str and int. Patch by Bar Harel. + +.. + +.. date: 2023-05-29-14-10-24 +.. gh-issue: 105052 +.. nonce: MGFwbm +.. section: Documentation + +Update ``timeit`` doc to specify that time in seconds is just the default. + +.. + +.. date: 2023-05-28-21-01-00 +.. gh-issue: 89455 +.. nonce: qAKRrA +.. section: Documentation + +Add missing documentation for the ``max_group_depth`` and +``max_group_width`` parameters and the ``exceptions`` attribute of the +:class:`traceback.TracebackException` class. + +.. + +.. date: 2023-05-28-19-08-42 +.. gh-issue: 89412 +.. nonce: j4cg7K +.. section: Documentation + +Add missing documentation for the ``end_lineno`` and ``end_offset`` +attributes of the :class:`traceback.TracebackException` class. + +.. + +.. date: 2023-05-25-22-34-31 +.. gh-issue: 104943 +.. nonce: J2v1Pc +.. section: Documentation + +Remove mentions of old Python versions in :class:`typing.NamedTuple`. + +.. + +.. date: 2023-05-16-22-08-24 +.. gh-issue: 54738 +.. nonce: mJvCnj +.. section: Documentation + +Add documentation on how to localize the :mod:`argparse` module. + +.. + +.. date: 2023-03-19-09-39-31 +.. gh-issue: 102823 +.. nonce: OzsOz0 +.. section: Documentation + +Document the return type of ``x // y`` when ``x`` and ``y`` have type +:class:`float`. + +.. + +.. date: 2023-03-16-15-39-26 +.. gh-issue: 102759 +.. nonce: ehpHw6 +.. section: Documentation + +Align function signature for ``functools.reduce`` in documentation and +docstring with the C implementation. + +.. + +.. date: 2023-10-10-23-20-13 +.. gh-issue: 110647 +.. nonce: jKG3sY +.. section: Tests + +Fix test_stress_modifying_handlers() of test_signal. Patch by Victor +Stinner. + +.. + +.. date: 2023-10-06-02-32-18 +.. gh-issue: 103053 +.. nonce: VfxBLI +.. section: Tests + +Fix test_tools.test_freeze on FreeBSD: run "make distclean" instead of "make +clean" in the copied source directory to remove also the "python" program. +Patch by Victor Stinner. + +.. + +.. date: 2023-10-05-19-33-49 +.. gh-issue: 110167 +.. nonce: mIdj3v +.. section: Tests + +Fix a deadlock in test_socket when server fails with a timeout but the +client is still running in its thread. Don't hold a lock to call cleanup +functions in doCleanups(). One of the cleanup function waits until the +client completes, whereas the client could deadlock if it called +addCleanup() in such situation. Patch by Victor Stinner. + +.. + +.. date: 2023-10-05-14-22-48 +.. gh-issue: 110388 +.. nonce: 1-HQJO +.. section: Tests + +Add tests for :mod:`tty`. + +.. + +.. date: 2023-10-05-13-46-50 +.. gh-issue: 81002 +.. nonce: bOcuV6 +.. section: Tests + +Add tests for :mod:`termios`. + +.. + +.. date: 2023-10-04-18-27-47 +.. gh-issue: 110367 +.. nonce: Nnq1I7 +.. section: Tests + +regrtest: When using worker processes (-jN) with --verbose3 option, regrtest +can now display the worker output even if a worker process does crash. +Previously, sys.stdout and sys.stderr were replaced and so the worker output +was lost on a crash. Patch by Victor Stinner. + +.. + +.. date: 2023-10-03-10-54-09 +.. gh-issue: 110267 +.. nonce: O-c47G +.. section: Tests + +Add tests for pickling and copying PyStructSequence objects. Patched by +Xuehai Pan. + +.. + +.. date: 2023-10-01-10-27-02 +.. gh-issue: 110171 +.. nonce: ZPlo0h +.. section: Tests + +``libregrtest`` now always sets and shows ``random.seed``, so tests are more +reproducible. Use ``--randseed`` flag to pass the explicit random seed for +tests. + +.. + +.. date: 2023-09-30-20-18-38 +.. gh-issue: 110152 +.. nonce: 4Kxve1 +.. section: Tests + +Remove ``Tools/scripts/run_tests.py`` and ``make hostrunnertest``. Just run +``./python -m test --slow-ci``, ``make buildbottest`` or ``make test`` +instead. Python test runner (regrtest) now handles cross-compilation and +HOSTRUNNER. It also adds options to Python such fast ``-u -E -W default +-bb`` when ``--fast-ci`` or ``--slow-ci`` option is used. Patch by Victor +Stinner. + +.. + +.. date: 2023-09-29-14-11-30 +.. gh-issue: 110031 +.. nonce: fQnFnc +.. section: Tests + +Skip test_threading tests using thread+fork if Python is built with Address +Sanitizer (ASAN). Patch by Victor Stinner. + +.. + +.. date: 2023-09-29-12-48-42 +.. gh-issue: 110088 +.. nonce: qUhRga +.. section: Tests + +Fix test_asyncio timeouts: don't measure the maximum duration, a test should +not measure a CI performance. Only measure the minimum duration when a task +has a timeout or delay. Add ``CLOCK_RES`` to ``test_asyncio.utils``. Patch +by Victor Stinner. + +.. + +.. date: 2023-09-29-00-19-21 +.. gh-issue: 109974 +.. nonce: Sh_g-r +.. section: Tests + +Fix race conditions in test_threading lock tests. Wait until a condition is +met rather than using :func:`time.sleep` with a hardcoded number of seconds. +Patch by Victor Stinner. + +.. + +.. date: 2023-09-28-18-14-52 +.. gh-issue: 110033 +.. nonce: 2yHMx0 +.. section: Tests + +Fix ``test_interprocess_signal()`` of ``test_signal``. Make sure that the +``subprocess.Popen`` object is deleted before the test raising an exception +in a signal handler. Otherwise, ``Popen.__del__()`` can get the exception +which is logged as ``Exception ignored in: ...`` and the test fails. Patch +by Victor Stinner. + +.. + +.. date: 2023-09-28-14-47-14 +.. gh-issue: 109594 +.. nonce: DB5KPP +.. section: Tests + +Fix test_timeout() of test_concurrent_futures.test_wait. Remove the future +which may or may not complete depending if it takes longer than the timeout +ot not. Keep the second future which does not complete before wait() +timeout. Patch by Victor Stinner. + +.. + +.. date: 2023-09-28-12-25-19 +.. gh-issue: 109972 +.. nonce: GYnwIP +.. section: Tests + +Split test_gdb.py file into a test_gdb package made of multiple tests, so +tests can now be run in parallel. Patch by Victor Stinner. + +.. + +.. date: 2023-09-26-18-12-01 +.. gh-issue: 109566 +.. nonce: CP0Vhf +.. section: Tests + +regrtest: When ``--fast-ci`` or ``--slow-ci`` option is used, regrtest now +replaces the current process with a new process to add ``-u -W default -bb +-E`` options to Python. Patch by Victor Stinner. + +.. + +.. date: 2023-09-26-00-49-18 +.. gh-issue: 109748 +.. nonce: nxlT1i +.. section: Tests + +Fix ``test_zippath_from_non_installed_posix()`` of test_venv: don't copy +``__pycache__/`` sub-directories, because they can be modified by other +Python tests running in parallel. Patch by Victor Stinner. + +.. + +.. date: 2023-09-25-23-59-37 +.. gh-issue: 109739 +.. nonce: MUn7K5 +.. section: Tests + +regrtest: Fix reference leak check on Windows. Disable the load tracker on +Windows in the reference leak check mode (-R option). Patch by Victor +Stinner. + +.. + +.. date: 2023-09-25-14-41-18 +.. gh-issue: 109276 +.. nonce: uC_cWo +.. section: Tests + +regrtest: When a test fails with "env changed" and the --rerun option is +used, the test is now re-run in verbose mode in a fresh process. Patch by +Victor Stinner. + +.. + +.. date: 2023-09-20-02-32-17 +.. gh-issue: 103053 +.. nonce: AoUJuK +.. section: Tests + +Skip test_freeze_simple_script() of test_tools.test_freeze if Python is +built with ``./configure --enable-optimizations``, which means with Profile +Guided Optimization (PGO): it just makes the test too slow. The freeze tool +is tested by many other CIs with other (faster) compiler flags. Patch by +Victor Stinner. + +.. + +.. date: 2023-09-19-19-08-22 +.. gh-issue: 109580 +.. nonce: G02Zam +.. section: Tests + +Skip ``test_perf_profiler`` if Python is built with ASAN, MSAN or UBSAN +sanitizer. Python does crash randomly in this test on such build. Patch by +Victor Stinner. + +.. + +.. date: 2023-09-19-13-33-20 +.. gh-issue: 109566 +.. nonce: aX0g9o +.. section: Tests + +regrtest: Add ``--fast-ci`` and ``--slow-ci`` options. ``--fast-ci`` uses a +default timeout of 10 minutes and ``-u all,-cpu`` (skip slowest tests). +``--slow-ci`` uses a default timeout of 20 minues and ``-u all`` (run all +tests). Patch by Victor Stinner. + +.. + +.. date: 2023-09-14-23-27-40 +.. gh-issue: 109425 +.. nonce: j-uFep +.. section: Tests + +libregrtest now decodes stdout of test worker processes with the +"backslashreplace" error handler to log corrupted stdout, instead of failing +with an error and not logging the stdout. Patch by Victor Stinner. + +.. + +.. date: 2023-09-14-22-58-47 +.. gh-issue: 109396 +.. nonce: J1a4jR +.. section: Tests + +Fix ``test_socket.test_hmac_sha1()`` in FIPS mode. Use a longer key: FIPS +mode requires at least of at least 112 bits. The previous key was only 32 +bits. Patch by Victor Stinner. + +.. + +.. date: 2023-09-13-05-58-09 +.. gh-issue: 104736 +.. nonce: lA25Fu +.. section: Tests + +Fix test_gdb on Python built with LLVM clang 16 on Linux ppc64le (ex: Fedora +38). Search patterns in gdb "bt" command output to detect when gdb fails to +retrieve the traceback. For example, skip a test if ``Backtrace stopped: +frame did not save the PC`` is found. Patch by Victor Stinner. + +.. + +.. date: 2023-09-11-19-11-57 +.. gh-issue: 109276 +.. nonce: qxI4OG +.. section: Tests + +libregrtest now calls :func:`random.seed()` before running each test file +when ``-r/--randomize`` command line option is used. Moreover, it's also +called in worker processes. It should help to make tests more +deterministic. Previously, it was only called once in the main process +before running all test files and it was not called in worker processes. +Patch by Victor Stinner. + +.. + +.. date: 2023-09-11-18-19-52 +.. gh-issue: 109276 +.. nonce: btfFtT +.. section: Tests + +libregrtest now uses a separated file descriptor to write test result as +JSON. Previously, if a test wrote debug messages late around the JSON, the +main test process failed to parse JSON. Patch by Victor Stinner. + +.. + +.. date: 2023-09-10-23-05-50 +.. gh-issue: 108996 +.. nonce: tJBru6 +.. section: Tests + +Fix and enable ``test_msvcrt``. + +.. + +.. date: 2023-09-10-22-32-20 +.. gh-issue: 109237 +.. nonce: SvgKwD +.. section: Tests + +Fix ``test_site.test_underpth_basic()`` when the working directory contains +at least one non-ASCII character: encode the ``._pth`` file to UTF-8 and +enable the UTF-8 Mode to use UTF-8 for the child process stdout. Patch by +Victor Stinner. + +.. + +.. date: 2023-09-10-19-59-57 +.. gh-issue: 109230 +.. nonce: SRNLFQ +.. section: Tests + +Fix ``test_pyexpat.test_exception()``: it can now be run from a directory +different than Python source code directory. Before, the test failed in this +case. Skip the test if Modules/pyexpat.c source is not available. Skip also +the test on Python implementations other than CPython. Patch by Victor +Stinner. + +.. + +.. date: 2023-09-06-22-06-22 +.. gh-issue: 108996 +.. nonce: IBhR3U +.. section: Tests + +Add tests for ``msvcrt``. + +.. + +.. date: 2023-09-06-18-27-53 +.. gh-issue: 109015 +.. nonce: 1dS1AQ +.. section: Tests + +Fix test_asyncio, test_imaplib and test_socket tests on FreeBSD if the TCP +blackhole is enabled (``sysctl net.inet.tcp.blackhole``). Skip the few tests +which failed with ``ETIMEDOUT`` which such non standard configuration. +Currently, the `FreeBSD GCP image enables TCP and UDP blackhole +`_ (``sysctl net.inet.tcp.blackhole=2`` +and ``sysctl net.inet.udp.blackhole=1``). Patch by Victor Stinner. + +.. + +.. date: 2023-09-06-15-36-51 +.. gh-issue: 91960 +.. nonce: P3nD5v +.. section: Tests + +Skip ``test_gdb`` if gdb is unable to retrieve Python frame objects: if a +frame is ````. When Python is built with "clang -Og", gdb can +fail to retrive the *frame* parameter of ``_PyEval_EvalFrameDefault()``. In +this case, tests like ``py_bt()`` are likely to fail. Without getting access +to Python frames, ``python-gdb.py`` is mostly clueless on retrieving the +Python traceback. Moreover, ``test_gdb`` is no longer skipped on macOS if +Python is built with Clang. Patch by Victor Stinner. + +.. + +.. date: 2023-09-05-23-00-09 +.. gh-issue: 108962 +.. nonce: R4NwuU +.. section: Tests + +Skip ``test_tempfile.test_flags()`` if ``chflags()`` fails with "OSError: +[Errno 45] Operation not supported" (ex: on FreeBSD 13). Patch by Victor +Stinner. + +.. + +.. date: 2023-09-05-21-42-54 +.. gh-issue: 91960 +.. nonce: abClTs +.. section: Tests + +FreeBSD 13.2 CI coverage for pull requests is now provided by Cirrus-CI (a +hosted CI service that supports Linux, macOS, Windows, and FreeBSD). + +.. + +.. date: 2023-09-04-15-18-14 +.. gh-issue: 89392 +.. nonce: 8A4T5p +.. section: Tests + +Removed support of ``test_main()`` function in tests. They now always use +normal unittest test runner. + +.. + +.. date: 2023-09-03-21-41-10 +.. gh-issue: 108851 +.. nonce: xFTYOE +.. section: Tests + +Fix ``test_tomllib`` recursion tests for WASI buildbots: reduce the +recursion limit and compute the maximum nested array/dict depending on the +current available recursion limit. Patch by Victor Stinner. + +.. + +.. date: 2023-09-03-21-18-35 +.. gh-issue: 108851 +.. nonce: CCuHyI +.. section: Tests + +Add ``get_recursion_available()`` and ``get_recursion_depth()`` functions to +the :mod:`test.support` module. Patch by Victor Stinner. + +.. + +.. date: 2023-09-03-20-15-49 +.. gh-issue: 108834 +.. nonce: Osvmhf +.. section: Tests + +Add ``--fail-rerun option`` option to regrtest: if a test failed when then +passed when rerun in verbose mode, exit the process with exit code 2 +(error), instead of exit code 0 (success). Patch by Victor Stinner. + +.. + +.. date: 2023-09-03-06-17-12 +.. gh-issue: 108834 +.. nonce: fjV-CJ +.. section: Tests + +Rename regrtest ``--verbose2`` option (``-w``) to ``--rerun``. Keep +``--verbose2`` as a deprecated alias. Patch by Victor Stinner. + +.. + +.. date: 2023-09-03-02-01-55 +.. gh-issue: 108834 +.. nonce: iAwXzj +.. section: Tests + +When regrtest reruns failed tests in verbose mode (``./python -m test +--rerun``), tests are now rerun in fresh worker processes rather than being +executed in the main process. If a test does crash or is killed by a +timeout, the main process can detect and handle the killed worker process. +Tests are rerun in parallel if the ``-jN`` option is used to run tests in +parallel. Patch by Victor Stinner. + +.. + +.. date: 2023-09-02-19-06-52 +.. gh-issue: 108822 +.. nonce: arTbBI +.. section: Tests + +``regrtest`` now computes statistics on all tests: successes, failures and +skipped. ``test_netrc``, ``test_pep646_syntax`` and ``test_xml_etree`` now +return results in their ``test_main()`` function. Patch by Victor Stinner +and Alex Waygood. + +.. + +.. date: 2023-09-02-05-13-38 +.. gh-issue: 108794 +.. nonce: tGHXBt +.. section: Tests + +The :meth:`doctest.DocTestRunner.run` method now counts the number of +skipped tests. Add :attr:`doctest.DocTestRunner.skips` and +:attr:`doctest.TestResults.skipped` attributes. Patch by Victor Stinner. + +.. + +.. date: 2023-08-24-06-10-36 +.. gh-issue: 108388 +.. nonce: YCVB0D +.. section: Tests + +Convert test_concurrent_futures to a package of 7 sub-tests. Patch by Victor +Stinner. + +.. + +.. date: 2023-08-24-04-23-35 +.. gh-issue: 108388 +.. nonce: mr0MeE +.. section: Tests + +Split test_multiprocessing_fork, test_multiprocessing_forkserver and +test_multiprocessing_spawn into test packages. Each package is made of 4 +sub-tests: processes, threads, manager and misc. It allows running more +tests in parallel and so reduce the total test duration. Patch by Victor +Stinner. + +.. + +.. date: 2023-08-23-04-08-18 +.. gh-issue: 105776 +.. nonce: oE6wp_ +.. section: Tests + +Fix test_cppext when the C compiler command ``-std=c11`` option: remove +``-std=`` options from the compiler command. Patch by Victor Stinner. + +.. + +.. date: 2023-08-05-14-01-07 +.. gh-issue: 107652 +.. nonce: 5OxOlT +.. section: Tests + +Set up CIFuzz to run fuzz targets in GitHub Actions. Patch by Illia +Volochii. + +.. + +.. date: 2023-07-25-14-36-33 +.. gh-issue: 107237 +.. nonce: y1pY79 +.. section: Tests + +``test_logging``: Fix ``test_udp_reconnection()`` by increasing the timeout +from 100 ms to 5 minutes (LONG_TIMEOUT). Patch by Victor Stinner. + +.. + +.. date: 2023-07-24-16-56-59 +.. gh-issue: 107178 +.. nonce: Gq1usE +.. section: Tests + +Add the C API test for functions in the Mapping Protocol, the Sequence +Protocol and some functions in the Object Protocol. + +.. + +.. date: 2023-07-22-13-49-40 +.. gh-issue: 106714 +.. nonce: btYI5S +.. section: Tests + +test_capi: Fix test_no_FatalError_infinite_loop() to no longer write a +coredump, by using test.support.SuppressCrashReport. Patch by Victor +Stinner. + +.. + +.. date: 2023-07-16-02-57-08 +.. gh-issue: 104090 +.. nonce: cKtK7g +.. section: Tests + +Avoid creating a reference to the test object in +:meth:`~unittest.TestResult.collectedDurations`. + +.. + +.. date: 2023-07-14-16-20-06 +.. gh-issue: 106752 +.. nonce: gd1i6D +.. section: Tests + +Moved tests for ``zipfile.Path`` into ``Lib/test/test_zipfile/_path``. Made +``zipfile._path`` a package. + +.. + +.. date: 2023-07-12-14-07-07 +.. gh-issue: 106690 +.. nonce: NDz-oG +.. section: Tests + +Add .coveragerc to cpython repository for use with coverage package. + +.. + +.. date: 2023-06-28-02-51-08 +.. gh-issue: 101634 +.. nonce: Rayczr +.. section: Tests + +When running the Python test suite with ``-jN`` option, if a worker stdout +cannot be decoded from the locale encoding report a failed testn so the +exitcode is non-zero. Patch by Victor Stinner. + +.. + +.. date: 2023-05-29-14-49-46 +.. gh-issue: 105084 +.. nonce: lvVvoj +.. section: Tests + +When the Python build is configured ``--with-wheel-pkg-dir``, tests +requiring the ``setuptools`` and ``wheel`` wheels will search for the wheels +in ``WHEEL_PKG_DIR``. + +.. + +.. date: 2023-05-19-08-06-06 +.. gh-issue: 81005 +.. nonce: -q7m9W +.. section: Tests + +String tests are modified to reflect that ``str`` and ``unicode`` are merged +in Python 3. Patch by Daniel Fortunov. + +.. + +.. date: 2023-04-05-06-45-20 +.. gh-issue: 103186 +.. nonce: 640Eg- +.. section: Tests + +Suppress and assert expected RuntimeWarnings in test_sys_settrace.py + +.. + +.. date: 2022-06-09-21-27-38 +.. gh-issue: 69714 +.. nonce: 49tyHW +.. section: Tests + +Add additional tests to :mod:`calendar` to achieve full test coverage. + +.. + +.. date: 2023-10-06-02-15-23 +.. gh-issue: 103053 +.. nonce: --7JUF +.. section: Build + +"make check-clean-src" now also checks if the "python" program is found in +the source directory: fail with an error if it does exist. Patch by Victor +Stinner. + +.. + +.. date: 2023-10-05-11-46-20 +.. gh-issue: 109191 +.. nonce: imUkVN +.. section: Build + +Fix compile error when building with recent versions of libedit. + +.. + +.. date: 2023-10-03-17-55-09 +.. gh-issue: 110276 +.. nonce: luaKRg +.. section: Build + +No longer ignore :envvar:`PROFILE_TASK` failure silently: command used by +Profile Guided Optimization (PGO). Patch by Victor Stinner. + +.. + +.. date: 2023-09-29-21-01-48 +.. gh-issue: 109566 +.. nonce: _enldb +.. section: Build + +Remove ``make testall`` target: use ``make buildbottest`` instead. Patch by +Victor Stinner. + +.. + +.. date: 2023-09-26-16-00-50 +.. gh-issue: 109740 +.. nonce: wboWdQ +.. section: Build + +The experimental ``--disable-gil`` configure flag now includes "t" (for +"threaded") in extension ABI tags. + +.. + +.. date: 2023-09-07-19-58-05 +.. gh-issue: 109054 +.. nonce: 5r3S3l +.. section: Build + +Fix building the ``_testcapi`` extension on Linux AArch64 which requires +linking to libatomic when ```` is used: the +``_Py_atomic_or_uint64()`` function requires libatomic +``__atomic_fetch_or_8()`` on this platform. The configure script now checks +if linking to libatomic is needed and generates a new LIBATOMIC variable +used to build the _testcapi extension. Patch by Victor Stinner. + +.. + +.. date: 2023-09-02-18-04-15 +.. gh-issue: 63760 +.. nonce: r8hJ6q +.. section: Build + +Fix Solaris build: no longer redefine the ``gethostname()`` function. +Solaris defines the function since 2005. Patch by Victor Stinner, original +patch by Jakub Kulík. + +.. + +.. date: 2023-09-01-01-39-26 +.. gh-issue: 108740 +.. nonce: JHExAQ +.. section: Build + +Fix a race condition in ``make regen-all``. The ``deepfreeze.c`` source and +files generated by Argument Clinic are now generated or updated before +generating "global objects". Previously, some identifiers may miss depending +on the order in which these files were generated. Patch by Victor Stinner. + +.. + +.. date: 2023-08-30-02-52-52 +.. gh-issue: 108634 +.. nonce: 3dpBvf +.. section: Build + +Python built with :file:`configure` :option:`--with-trace-refs` (tracing +references) is now ABI compatible with Python release build and :ref:`debug +build `. Patch by Victor Stinner. + +.. + +.. date: 2023-08-29-15-05-09 +.. gh-issue: 85283 +.. nonce: tlK7G7 +.. section: Build + +The ``_stat`` C extension is now built with the :ref:`limited C API +`. Patch by Victor Stinner. + +.. + +.. date: 2023-08-24-18-36-31 +.. gh-issue: 108447 +.. nonce: Ofsygr +.. section: Build + +Fix x86_64 GNU/Hurd build + +.. + +.. date: 2023-08-09-17-05-33 +.. gh-issue: 107814 +.. nonce: c0Oapq +.. section: Build + +When calling ``find_python.bat`` with ``-q`` it did not properly silence the +output of nuget. That is now fixed. + +.. + +.. date: 2023-08-01-17-12-53 +.. gh-issue: 105481 +.. nonce: 42nsDE +.. section: Build + +Remove the make target ``regen-opcode-targets``, merge its work into +``regen-opcode`` which repeats most of the calculation. This simplifies the +code for the build and reduces code duplication. + +.. + +.. date: 2023-07-28-18-17-33 +.. gh-issue: 106881 +.. nonce: U3Ezdq +.. section: Build + +Check for ``linux/limits.h`` before including it in +``Modules/posixmodule.c``. + +.. + +.. date: 2023-07-25-02-30-00 +.. gh-issue: 95855 +.. nonce: wA7rAf +.. section: Build + +Refactor platform triplet detection code and add detection for MIPS soft +float and musl libc. + +.. + +.. date: 2023-07-23-00-38-51 +.. gh-issue: 106962 +.. nonce: VVYrWB +.. section: Build + +Detect MPI compilers in :file:`configure`. + +.. + +.. date: 2023-06-26-21-56-29 +.. gh-issue: 106118 +.. nonce: 0cCfhl +.. section: Build + +Fix compilation for platforms without :data:`!O_CLOEXEC`. The issue was +introduced with Python 3.12b1 in :gh:`103295`. Patch by Erlend Aasland. + +.. + +.. date: 2023-06-16-23-40-49 +.. gh-issue: 105875 +.. nonce: naj8v5 +.. section: Build + +SQLite 3.15.2 or newer is required to build the :mod:`sqlite3` extension +module. Patch by Erlend Aasland. + +.. + +.. date: 2023-06-06-09-08-10 +.. gh-issue: 90005 +.. nonce: 8mmeJQ +.. section: Build + +Fix a regression in :file:`configure` where we could end up unintentionally +linking with ``libbsd``. + +.. + +.. date: 2023-06-02-19-12-45 +.. gh-issue: 102404 +.. nonce: Ry9piA +.. section: Build + +Document how to perform a WASI build on Linux. Also add +Tools/wasm/build_wasi.sh as a reference implementation of the docs. + +.. + +.. date: 2023-05-26-15-44-20 +.. gh-issue: 89886 +.. nonce: _iSW-p +.. section: Build + +Autoconf 2.71 and aclocal 1.16.4 is now required to regenerate +:file:`!configure`. + +.. + +.. date: 2023-05-20-23-49-30 +.. gh-issue: 104692 +.. nonce: s5UIu5 +.. section: Build + +Include ``commoninstall`` as a prerequisite for ``bininstall`` + +This ensures that ``commoninstall`` is completed before ``bininstall`` is +started when parallel builds are used (``make -j install``), and so the +``python3`` symlink is only installed after all standard library modules are +installed. + +.. + +.. date: 2023-02-03-21-36-42 +.. gh-issue: 101538 +.. nonce: sF5F6S +.. section: Build + +Add experimental wasi-threads support. Patch by Takashi Yamamoto. + +.. + +.. date: 2023-10-06-14-20-14 +.. gh-issue: 110437 +.. nonce: xpYy9q +.. section: Windows + +Allows overriding the source of VC redistributables so that releases can be +guaranteed to never downgrade between updates. + +.. + +.. date: 2023-10-05-15-23-23 +.. gh-issue: 109286 +.. nonce: N8OzMg +.. section: Windows + +Update Windows installer to use SQLite 3.43.1. + +.. + +.. date: 2023-10-03-12-30-59 +.. gh-issue: 82367 +.. nonce: nxwfMx +.. section: Windows + +:func:`os.path.realpath` now resolves MS-DOS style file names even if the +file is not accessible. Patch by Moonsik Park. + +.. + +.. date: 2023-09-28-17-09-23 +.. gh-issue: 109991 +.. nonce: CIMftz +.. section: Windows + +Update Windows build to use OpenSSL 3.0.11. + +.. + +.. date: 2023-08-22-00-36-57 +.. gh-issue: 106242 +.. nonce: q24ITw +.. section: Windows + +Fixes :func:`~os.path.realpath` to behave consistently when passed a path +containing an embedded null character on Windows. In strict mode, it now +raises :exc:`OSError` instead of the unexpected :exc:`ValueError`, and in +non-strict mode will make the path absolute. + +.. + +.. date: 2023-08-18-00-01-21 +.. gh-issue: 83180 +.. nonce: DdLffv +.. section: Windows + +Changes the :ref:`launcher` to prefer an active virtual environment when the +launched script has a shebang line using a Unix-like virtual command, even +if the command requests a specific version of Python. + +.. + +.. date: 2023-07-18-13-01-26 +.. gh-issue: 106844 +.. nonce: mci4xO +.. section: Windows + +Fix integer overflow and truncating by the null character in +:func:`!_winapi.LCMapStringEx` which affects :func:`ntpath.normcase`. + +.. + +.. date: 2023-06-08-11-30-17 +.. gh-issue: 105436 +.. nonce: 1qlDxw +.. section: Windows + +Ensure that an empty environment block is terminated by two null characters, +as is required by Windows. + +.. + +.. date: 2023-05-31-16-14-31 +.. gh-issue: 105146 +.. nonce: gNjqq8 +.. section: Windows + +Updated the links at the end of the installer to point to Discourse rather +than the mailing lists. + +.. + +.. date: 2023-05-29-17-09-31 +.. gh-issue: 103646 +.. nonce: U8oGQx +.. section: Windows + +When installed from the Microsoft Store, ``pip`` no longer defaults to +per-user installs. However, as the install directory is unwritable, it +should automatically decide to do a per-user install anyway. This should +resolve issues when ``pip`` is passed an option that conflicts with +``--user``. + +.. + +.. date: 2023-05-29-11-38-53 +.. gh-issue: 88745 +.. nonce: cldf9G +.. section: Windows + +Improve performance of :func:`shutil.copy2` by using the operating system's +``CopyFile2`` function. This may result in subtle changes to metadata copied +along with some files, bringing them in line with normal OS behavior. + +.. + +.. date: 2023-05-24-21-00-57 +.. gh-issue: 104820 +.. nonce: ibyrpp +.. section: Windows + +Fixes :func:`~os.stat` and related functions on file systems that do not +support file ID requests. This includes FAT32 and exFAT. + +.. + +.. date: 2023-05-23-19-26-28 +.. gh-issue: 104803 +.. nonce: gqxYml +.. section: Windows + +Add :func:`os.path.isdevdrive` to detect whether a path is on a Windows Dev +Drive. Returns ``False`` on platforms that do not support Dev Drive, and is +absent on non-Windows platforms. + +.. + +.. date: 2023-10-04-23-38-24 +.. gh-issue: 109286 +.. nonce: 1ZLMaq +.. section: macOS + +Update macOS installer to use SQLite 3.43.1. + +.. + +.. date: 2023-09-27-22-35-22 +.. gh-issue: 109991 +.. nonce: -xJzaF +.. section: macOS + +Update macOS installer to use OpenSSL 3.0.11. + +.. + +.. date: 2023-07-30-23-42-20 +.. gh-issue: 99079 +.. nonce: JAtoh1 +.. section: macOS + +Update macOS installer to use OpenSSL 3.0.9. + +.. + +.. date: 2023-05-23-17-19-49 +.. gh-issue: 104719 +.. nonce: rvYXH- +.. section: IDLE + +Remove IDLE's modification of tokenize.tabsize and test other uses of +tokenize data and methods. + +.. + +.. date: 2023-09-27-23-31-54 +.. gh-issue: 109991 +.. nonce: sUUYY8 +.. section: Tools/Demos + +Update GitHub CI workflows to use OpenSSL 3.0.11 and multissltests to use +1.1.1w, 3.0.11, and 3.1.3. + +.. + +.. date: 2023-08-25-22-40-12 +.. gh-issue: 108494 +.. nonce: 4RbDdu +.. section: Tools/Demos + +`Argument Clinic `__ +now has a partial support of the :ref:`Limited API `: see +`documentation in the Python Developer's Guide +`__ +Patch by Victor Stinner. + +.. + +.. date: 2023-08-15-19-50-49 +.. gh-issue: 107704 +.. nonce: Uu84vd +.. section: Tools/Demos + +It is now possible to deprecate passing keyword arguments for +keyword-or-positional parameters with Argument Clinic, using the new ``/ +[from X.Y]`` syntax. (To be read as *"positional-only from Python version +X.Y"*.) See `documentation in the Python Developer's Guide +`__ +for more information. + +.. + +.. date: 2023-08-13-11-18-06 +.. gh-issue: 107880 +.. nonce: gBVVQ7 +.. section: Tools/Demos + +Argument Clinic can now clone :meth:`!__init__` and :meth:`!__new__` +methods. + +.. + +.. date: 2023-08-08-12-21-41 +.. gh-issue: 104683 +.. nonce: DRsAQE +.. section: Tools/Demos + +Add ``--exclude`` option to Argument Clinic CLI. + +.. + +.. date: 2023-08-07-16-30-48 +.. gh-issue: 95065 +.. nonce: -im4R5 +.. section: Tools/Demos + +Argument Clinic now supports overriding automatically generated signature by +using directive ``@text_signature``. See `documentation in the Python +Developer's Guide +`__ + +.. + +.. date: 2023-08-04-00-04-40 +.. gh-issue: 107609 +.. nonce: 2DqgtL +.. section: Tools/Demos + +Fix duplicate module check in Argument Clinic. Previously, a duplicate +definition would incorrectly be silently accepted. Patch by Erlend E. +Aasland. + +.. + +.. date: 2023-07-30-23-32-16 +.. gh-issue: 107467 +.. nonce: 5O9p3G +.. section: Tools/Demos + +The Argument Clinic command-line tool now prints to stderr instead of stdout +on failure. + +.. + +.. date: 2023-07-21-23-16-05 +.. gh-issue: 106970 +.. nonce: NLRnml +.. section: Tools/Demos + +Fix bugs in the Argument Clinic ``destination clear`` command; the +destination buffers would never be cleared, and the ``destination`` +directive parser would simply continue to the fault handler after processing +the command. Patch by Erlend E. Aasland. + +.. + +.. date: 2023-07-13-12-08-35 +.. gh-issue: 106706 +.. nonce: 29zp8E +.. section: Tools/Demos + +Change bytecode syntax for families to remove redundant name matching pseudo +syntax. + +.. + +.. date: 2023-07-03-14-06-19 +.. gh-issue: 106359 +.. nonce: RfJuR0 +.. section: Tools/Demos + +Argument Clinic now explicitly forbids "kwarg splats" in function calls used +as annotations. + +.. + +.. date: 2023-04-05-07-19-36 +.. gh-issue: 103186 +.. nonce: yEozgK +.. section: Tools/Demos + +``freeze`` now fetches ``CONFIG_ARGS`` from the original CPython instance +the Makefile uses to call utility scripts. Patch by Ijtaba Hussain. + +.. + +.. date: 2022-07-23-00-33-28 +.. gh-issue: 95065 +.. nonce: NfCCpp +.. section: Tools/Demos + +It is now possible to deprecate passing parameters positionally with +Argument Clinic, using the new ``* [from X.Y]`` syntax. (To be read as +*"keyword-only from Python version X.Y"*.) See `documentation in the Python +Developer's Guide +`__ +for more information. Patch by Erlend E. Aasland with help from Alex +Waygood, Nikita Sobolev, and Serhiy Storchaka. + +.. + +.. date: 2023-10-11-17-29-52 +.. gh-issue: 85283 +.. nonce: OsqIBF +.. section: C API + +If the :c:macro:`Py_LIMITED_API` macro is defined, +:c:macro:`!Py_BUILD_CORE`, :c:macro:`!Py_BUILD_CORE_BUILTIN` and +:c:macro:`!Py_BUILD_CORE_MODULE` macros are now undefined by ````. +Patch by Victor Stinner. + +.. + +.. date: 2023-10-03-19-01-20 +.. gh-issue: 110289 +.. nonce: YBIHEz +.. section: C API + +Add :c:func:`PyUnicode_EqualToUTF8AndSize` and +:c:func:`PyUnicode_EqualToUTF8` functions. + +.. + +.. date: 2023-10-03-06-19-10 +.. gh-issue: 110235 +.. nonce: uec5AG +.. section: C API + +Raise :exc:`TypeError` for duplicate/unknown fields in ``PyStructSequence`` +constructor. Patched by Xuehai Pan. + +.. + +.. date: 2023-10-02-13-39-57 +.. gh-issue: 110014 +.. nonce: gfQ4jU +.. section: C API + +Remove undocumented ``PY_TIMEOUT_MAX`` constant from the limited C API. +Patch by Victor Stinner. + +.. + +.. date: 2023-09-17-21-47-31 +.. gh-issue: 109521 +.. nonce: JDF6i9 +.. section: C API + +:c:func:`PyImport_GetImporter` now sets RuntimeError if it fails to get +:data:`sys.path_hooks` or :data:`sys.path_importer_cache` or they are not +list and dict correspondingly. Previously it could return NULL without +setting error in obscure cases, crash or raise SystemError if these +attributes have wrong type. + +.. + +.. date: 2023-09-12-13-09-36 +.. gh-issue: 108724 +.. nonce: -yMsC8 +.. section: C API + +Add :c:type:`PyMutex` internal-only lightweight locking API. + +.. + +.. date: 2023-09-06-00-14-49 +.. gh-issue: 85283 +.. nonce: GKY0Cc +.. section: C API + +Add :c:func:`PySys_AuditTuple` function: similar to :c:func:`PySys_Audit`, +but pass event arguments as a Python :class:`tuple` object. Patch by Victor +Stinner. + +.. + +.. date: 2023-09-04-11-47-12 +.. gh-issue: 108867 +.. nonce: Cr_LKd +.. section: C API + +Add :c:func:`PyThreadState_GetUnchecked()` function: similar to +:c:func:`PyThreadState_Get()`, but don't kill the process with a fatal error +if it is NULL. The caller is responsible to check if the result is NULL. +Previously, the function was private and known as +``_PyThreadState_UncheckedGet()``. Patch by Victor Stinner. + +.. + +.. date: 2023-09-02-22-35-55 +.. gh-issue: 108765 +.. nonce: 4TOdBT +.. section: C API + +``Python.h`` no longer includes the ```` standard header file. If +needed, it should now be included explicitly. For example, it provides +``isalpha()`` and ``tolower()`` functions which are locale dependent. Python +provides locale independent functions, like :c:func:`!Py_ISALPHA` and +:c:func:`!Py_TOLOWER`. Patch by Victor Stinner. + +.. + +.. date: 2023-09-01-21-10-29 +.. gh-issue: 108765 +.. nonce: eeXtYF +.. section: C API + +``Python.h`` no longer includes the ```` standard header file. If +needed, it should now be included explicitly. For example, it provides the +functions: ``close()``, ``getpagesize()``, ``getpid()`` and ``sysconf()``. +Patch by Victor Stinner. + +.. + +.. date: 2023-09-01-20-41-49 +.. gh-issue: 108765 +.. nonce: 5dXc1r +.. section: C API + +``Python.h`` no longer includes the ```` standard header. It was +included for the ``finite()`` function which is now provided by the +```` header. It should now be included explicitly if needed. Remove +also the ``HAVE_IEEEFP_H`` macro. Patch by Victor Stinner. + +.. + +.. date: 2023-09-01-18-42-31 +.. gh-issue: 108765 +.. nonce: IyYNDu +.. section: C API + +``Python.h`` no longer includes these standard header files: ````, +```` and ````. If needed, they should now be +included explicitly. For example, ```` provides the ``clock()`` and +``gmtime()`` functions, ```` provides the ``select()`` +function, and ```` provides the ``futimes()``, +``gettimeofday()`` and ``setitimer()`` functions. Patch by Victor Stinner. + +.. + +.. date: 2023-09-01-16-28-09 +.. gh-issue: 108511 +.. nonce: gg-QDG +.. section: C API + +Add functions :c:func:`PyObject_HasAttrWithError`, +:c:func:`PyObject_HasAttrStringWithError`, +:c:func:`PyMapping_HasKeyWithError` and +:c:func:`PyMapping_HasKeyStringWithError`. + +.. + +.. date: 2023-09-01-15-35-05 +.. gh-issue: 107073 +.. nonce: zCz0iN +.. section: C API + +Add :c:func:`PyObject_VisitManagedDict` and +:c:func:`PyObject_ClearManagedDict` functions which must be called by the +traverse and clear functions of a type using +:c:macro:`Py_TPFLAGS_MANAGED_DICT` flag. Patch by Victor Stinner. + +.. + +.. date: 2023-08-30-02-54-06 +.. gh-issue: 108634 +.. nonce: oV3Xzk +.. section: C API + +Python built with :file:`configure` :option:`--with-trace-refs` (tracing +references) now supports the :ref:`Limited API `. Patch by +Victor Stinner. + +.. + +.. date: 2023-08-24-20-08-02 +.. gh-issue: 108014 +.. nonce: 20DOSS +.. section: C API + +Add :c:func:`PyLong_AsInt` function: similar to :c:func:`PyLong_AsLong`, but +store the result in a C :c:expr:`int` instead of a C :c:expr:`long`. +Previously, it was known as the private function :c:func:`!_PyLong_AsInt` +(with an underscore prefix). Patch by Victor Stinner. + +.. + +.. date: 2023-08-22-18-45-20 +.. gh-issue: 108314 +.. nonce: nOlmwq +.. section: C API + +Add :c:func:`PyDict_ContainsString` function: same as +:c:func:`PyDict_Contains`, but *key* is specified as a :c:expr:`const char*` +UTF-8 encoded bytes string, rather than a :c:expr:`PyObject*`. Patch by +Victor Stinner. + +.. + +.. date: 2023-08-22-13-00-54 +.. gh-issue: 108337 +.. nonce: wceHZm +.. section: C API + +Add atomic operations on additional data types in pyatomic.h. + +.. + +.. date: 2023-08-16-17-16-19 +.. gh-issue: 108014 +.. nonce: wXN3CF +.. section: C API + +Add :c:func:`Py_IsFinalizing` function: check if the main Python interpreter +is :term:`shutting down `. Patch by Victor Stinner. + +.. + +.. date: 2023-08-14-10-59-03 +.. gh-issue: 107916 +.. nonce: KH4Muo +.. section: C API + +C API functions :c:func:`PyErr_SetFromErrnoWithFilename`, +:c:func:`PyErr_SetExcFromWindowsErrWithFilename` and +:c:func:`PyErr_SetFromWindowsErrWithFilename` save now the error code before +calling :c:func:`PyUnicode_DecodeFSDefault`. + +.. + +.. date: 2023-08-13-12-33-00 +.. gh-issue: 107915 +.. nonce: jQ0wOi +.. section: C API + +Such C API functions as ``PyErr_SetString()``, ``PyErr_Format()``, +``PyErr_SetFromErrnoWithFilename()`` and many others no longer crash or +ignore errors if it failed to format the error message or decode the +filename. Instead, they keep a corresponding error. + +.. + +.. date: 2023-08-10-11-12-25 +.. gh-issue: 107810 +.. nonce: oJ40Qx +.. section: C API + +Improve :exc:`DeprecationWarning` for uses of :c:type:`PyType_Spec` with +metaclasses that have custom ``tp_new``. + +.. + +.. date: 2023-07-25-17-23-08 +.. gh-issue: 107249 +.. nonce: xqk2ke +.. section: C API + +Implement the :c:macro:`Py_UNUSED` macro for Windows MSVC compiler. Patch by +Victor Stinner. + +.. + +.. date: 2023-07-25-13-41-09 +.. gh-issue: 107226 +.. nonce: N919zH +.. section: C API + +:c:func:`PyModule_AddObjectRef` is now only available in the limited API +version 3.10 or later. + +.. + +.. date: 2023-07-22-14-40-48 +.. gh-issue: 106320 +.. nonce: H3u7x4 +.. section: C API + +Remove private ``_PyUnicode_AsString()`` alias to +:c:func:`PyUnicode_AsUTF8`. It was kept for backward compatibility with +Python 3.0 - 3.2. The :c:func:`PyUnicode_AsUTF8` is available since Python +3.3. The :c:func:`PyUnicode_AsUTF8String` function can be used to keep +compatibility with Python 3.2 and older. Patch by Victor Stinner. + +.. + +.. date: 2023-07-11-01-07-39 +.. gh-issue: 106572 +.. nonce: y1b35X +.. section: C API + +Convert :c:func:`PyObject_DelAttr` and :c:func:`PyObject_DelAttrString` +macros to functions. Patch by Victor Stinner. + +.. + +.. date: 2023-07-08-12-24-17 +.. gh-issue: 106307 +.. nonce: FVnkBw +.. section: C API + +Add :c:func:`PyMapping_GetOptionalItem` function. + +.. + +.. date: 2023-07-07-19-14-00 +.. gh-issue: 106521 +.. nonce: Veh9f3 +.. section: C API + +Add :c:func:`PyObject_GetOptionalAttr` and +:c:func:`PyObject_GetOptionalAttrString` functions. + +.. + +.. date: 2023-07-02-00-00-20 +.. gh-issue: 106320 +.. nonce: tZWcvG +.. section: C API + +Remove ``_PyInterpreterState_Get()`` alias to +:c:func:`PyInterpreterState_Get()` which was kept for backward compatibility +with Python 3.8. Patch by Victor Stinner. + +.. + +.. date: 2023-07-01-21-23-33 +.. gh-issue: 106316 +.. nonce: hp2Ijw +.. section: C API + +Remove ``cpython/pytime.h`` header file: it only contained private +functions. Patch by Victor Stinner. + +.. + +.. date: 2023-06-30-09-33-25 +.. gh-issue: 106023 +.. nonce: YvYiE4 +.. section: C API + +Remove private ``_PyObject_FastCall()`` function: use +``PyObject_Vectorcall()`` which is available since Python 3.8 (:pep:`590`). +Patch by Victor Stinner. + +.. + +.. date: 2023-06-28-02-30-50 +.. gh-issue: 106168 +.. nonce: NFOZPv +.. section: C API + +If Python is built in :ref:`debug mode ` or :option:`with +assertions <--with-assertions>`, :c:func:`PyTuple_SET_ITEM` and +:c:func:`PyList_SET_ITEM` now check the index argument with an assertion. If +the assertion fails, make sure that the size is set before. Patch by Victor +Stinner. + +.. + +.. date: 2023-06-25-18-01-27 +.. gh-issue: 106084 +.. nonce: PEzqU3 +.. section: C API + +Remove the old aliases to functions calling functions which were kept for +backward compatibility with Python 3.8 provisional API: + +* ``_PyObject_CallMethodNoArgs()``: use ``PyObject_CallMethodNoArgs()`` +* ``_PyObject_CallMethodOneArg()``: use ``PyObject_CallMethodOneArg()`` +* ``_PyObject_CallOneArg()``: use ``PyObject_CallOneArg()`` +* ``_PyObject_FastCallDict()``: use ``PyObject_VectorcallDict()`` +* ``_PyObject_Vectorcall()``: use ``PyObject_Vectorcall()`` +* ``_PyObject_VectorcallMethod()``: use ``PyObject_VectorcallMethod()`` +* ``_PyVectorcall_Function()``: use ``PyVectorcall_Function()`` + +Just remove the underscore prefix to update your code. Patch by Victor +Stinner. + +.. + +.. date: 2023-06-23-02-57-15 +.. gh-issue: 106004 +.. nonce: -OToh6 +.. section: C API + +Adds :c:func:`PyDict_GetItemRef` and :c:func:`PyDict_GetItemStringRef` +functions: similar to :c:func:`PyDict_GetItemWithError` but returning a +:term:`strong reference` instead of a :term:`borrowed reference`. Patch by +Victor Stinner. + +.. + +.. date: 2023-06-22-00-25-55 +.. gh-issue: 105927 +.. nonce: GRxZtI +.. section: C API + +Deprecate the :c:func:`PyWeakref_GetObject` and +:c:func:`PyWeakref_GET_OBJECT` functions: use the new +:c:func:`PyWeakref_GetRef` function instead. Patch by Victor Stinner. + +.. + +.. date: 2023-06-20-08-59-05 +.. gh-issue: 105927 +.. nonce: DfGeEA +.. section: C API + +Add :c:func:`PyWeakref_GetRef` function: similar to +:c:func:`PyWeakref_GetObject` but returns a :term:`strong reference`, or +``NULL`` if the referent is no longer live. Patch by Victor Stinner. + +.. + +.. date: 2023-06-19-20-02-16 +.. gh-issue: 105922 +.. nonce: o4T6wO +.. section: C API + +Add :c:func:`PyImport_AddModuleRef`: similar to +:c:func:`PyImport_AddModule`, but return a :term:`strong reference` instead +of a :term:`borrowed reference`. Patch by Victor Stinner. + +.. + +.. date: 2023-06-13-14-24-55 +.. gh-issue: 105227 +.. nonce: HDL9aF +.. section: C API + +The new :c:func:`PyType_GetDict` provides the dictionary for the given type +object that is normally exposed by ``cls.__dict__``. Normally it's +sufficient to use :c:member:`~PyTypeObject.tp_dict`, but for the static +builtin types :c:member:`!tp_dict` is now always ``NULL``. +:c:func:`!PyType_GetDict()` provides the correct dict object instead. + +.. + +.. date: 2023-06-09-23-34-25 +.. gh-issue: 105375 +.. nonce: n7amiF +.. section: C API + +Fix a bug in :c:func:`PyErr_WarnExplicit` where an exception could end up +being overwritten if the API failed internally. + +.. + +.. date: 2023-06-09-19-16-57 +.. gh-issue: 105603 +.. nonce: -z6G22 +.. section: C API + +We've renamed the new (in 3.12) ``PyInterpreterConfig.own_gil`` to +``PyInterpreterConfig.gil`` and changed the meaning of the value from "bool" +to an integer with supported values of ``PyInterpreterConfig_DEFAULT_GIL``, +``PyInterpreterConfig_SHARED_GIL``, and ``PyInterpreterConfig_OWN_GIL``. The +default is "shared". + +.. + +.. date: 2023-06-09-12-35-55 +.. gh-issue: 105387 +.. nonce: wM_oL- +.. section: C API + +In the limited C API version 3.12, :c:func:`Py_INCREF` and +:c:func:`Py_DECREF` functions are now implemented as opaque function calls +to hide implementation details. Patch by Victor Stinner. + +.. + +.. date: 2023-06-06-17-43-28 +.. gh-issue: 105396 +.. nonce: FQJG5B +.. section: C API + +Deprecate the :c:func:`PyImport_ImportModuleNoBlock` function which is just +an alias to :c:func:`PyImport_ImportModule` since Python 3.3. Patch by +Victor Stinner. + +.. + +.. date: 2023-06-06-14-14-41 +.. gh-issue: 103968 +.. nonce: BTO6II +.. section: C API + +:c:func:`PyType_FromMetaclass` now allows metaclasses with ``tp_new`` set to +``NULL``. + +.. + +.. date: 2023-06-06-10-57-18 +.. gh-issue: 105268 +.. nonce: OTJUko +.. section: C API + +Remove the old private, undocumented and untested ``_PyGC_FINALIZED()`` +macro which was kept for backward compatibility with Python 3.8 and older. +Patch by Victor Stinner. + +.. + +.. date: 2023-06-01-11-24-03 +.. gh-issue: 105182 +.. nonce: l5sCw4 +.. section: C API + +Remove ``PyEval_AcquireLock()`` and ``PyEval_ReleaseLock()`` functions, +deprecated in Python 3.2. Patch by Victor Stinner. + +.. + +.. date: 2023-06-01-11-23-28 +.. gh-issue: 105182 +.. nonce: kLEHl- +.. section: C API + +Remove ``PyEval_InitThreads()`` and ``PyEval_ThreadsInitialized()`` +functions, deprecated in Python 3.9. Patch by Victor Stinner. + +.. + +.. date: 2023-06-01-09-40-30 +.. gh-issue: 105145 +.. nonce: WOOE-w +.. section: C API + +Deprecate old Python initialization functions: + +* :c:func:`PySys_ResetWarnOptions` +* :c:func:`Py_GetExecPrefix` +* :c:func:`Py_GetPath` +* :c:func:`Py_GetPrefix` +* :c:func:`Py_GetProgramFullPath` +* :c:func:`Py_GetProgramName` +* :c:func:`Py_GetPythonHome` + +Patch by Victor Stinner. + +.. + +.. date: 2023-05-31-19-38-45 +.. gh-issue: 85275 +.. nonce: doojgE +.. section: C API + +``PyObject_AsCharBuffer()``, ``PyObject_AsReadBuffer()``, +``PyObject_CheckReadBuffer()``, and ``PyObject_AsWriteBuffer()`` are +removed. Please migrate to new buffer protocol; :c:func:`PyObject_GetBuffer` +and :c:func:`PyBuffer_Release`. + +.. + +.. date: 2023-05-31-18-37-57 +.. gh-issue: 105156 +.. nonce: R4El5V +.. section: C API + +Deprecate the old ``Py_UNICODE`` and ``PY_UNICODE_TYPE`` types: use directly +the :c:type:`wchar_t` type instead. Since Python 3.3, ``Py_UNICODE`` and +``PY_UNICODE_TYPE`` are just aliases to :c:type:`wchar_t`. Patch by Victor +Stinner. + +.. + +.. date: 2023-05-31-16-51-18 +.. gh-issue: 105145 +.. nonce: b3B6lJ +.. section: C API + +Remove the following old functions to configure the Python initialization, +deprecated in Python 3.11: + +* ``PySys_AddWarnOptionUnicode()`` +* ``PySys_AddWarnOption()`` +* ``PySys_AddXOption()`` +* ``PySys_HasWarnOptions()`` +* ``PySys_SetArgvEx()`` +* ``PySys_SetArgv()`` +* ``PySys_SetPath()`` +* ``Py_SetPath()`` +* ``Py_SetProgramName()`` +* ``Py_SetPythonHome()`` +* ``Py_SetStandardStreamEncoding()`` +* ``_Py_SetProgramFullPath()`` + +Patch by Victor Stinner. + +.. + +.. date: 2023-05-30-19-11-09 +.. gh-issue: 105107 +.. nonce: YQwMnm +.. section: C API + +Remove functions deprecated in Python 3.9. + +* ``PyEval_CallObject()``, ``PyEval_CallObjectWithKeywords()``: use + :c:func:`PyObject_CallNoArgs` and :c:func:`PyObject_Call` (positional + arguments must not be *NULL*) instead. +* ``PyEval_CallFunction()``: use :c:func:`PyObject_CallFunction` instead. +* ``PyEval_CallMethod()``: use :c:func:`PyObject_CallMethod` instead. +* ``PyCFunction_Call()``: use :c:func:`PyObject_Call` instead. + +Patch by Victor Stinner. + +.. + +.. date: 2023-05-30-17-45-32 +.. gh-issue: 105115 +.. nonce: iRho1K +.. section: C API + +``PyTypeObject.tp_bases`` (and ``tp_mro``) for builtin static types are now +shared by all interpreters, whereas in 3.12-beta1 they were stored on +``PyInterpreterState``. Also note that now the tuples are immortal objects. + +.. + +.. date: 2023-05-30-10-15-13 +.. gh-issue: 105071 +.. nonce: dPtp7c +.. section: C API + +Add ``PyUnstable_Exc_PrepReraiseStar`` to the unstable C api to expose the +implementation of :keyword:`except* `. + +.. + +.. date: 2023-05-29-16-09-27 +.. gh-issue: 104922 +.. nonce: L23qaU +.. section: C API + +``PY_SSIZE_T_CLEAN`` is no longer required to use ``'#'`` formats in APIs +like :c:func:`PyArg_ParseTuple` and :c:func:`Py_BuildValue`. They uses +``Py_ssize_t`` for ``'#'`` regardless ``PY_SSIZE_T_CLEAN``. + +.. + +.. date: 2023-05-25-15-44-48 +.. gh-issue: 104584 +.. nonce: cSAoRh +.. section: C API + +Add an unstable C API for hooking in an optimizer. This is mainly internal, +but marked "unstable" to allow third-party experimentation. + +.. + +.. date: 2023-05-19-10-22-34 +.. gh-issue: 104668 +.. nonce: MLX1g9 +.. section: C API + +Don't call :c:var:`PyOS_InputHook` or :c:var:`PyOS_ReadlineFunctionPointer` +in subinterpreters, since it's generally difficult to avoid using global +state in their registered callbacks. This also avoids situations where +extensions may find themselves running in a subinterpreter they don't +support (or haven't yet been loaded in). + +.. + +.. bpo: 42327 +.. date: 2020-11-11-22-36-29 +.. nonce: ODSZBM +.. section: C API + +Add :c:func:`PyModule_Add` function: similar to +:c:func:`PyModule_AddObjectRef` and :c:func:`PyModule_AddObject`, but always +steals a reference to the value. + +.. + +.. bpo: 40309 +.. date: 2020-06-25-09-44-59 +.. nonce: CuoGoQ +.. section: C API + +Properly handle trailing spaces before closing parenthesis in +:c:func:`Py_BuildValue` format strings. diff --git a/Misc/NEWS.d/3.13.0a2.rst b/Misc/NEWS.d/3.13.0a2.rst new file mode 100644 index 00000000000000..c1b1be523325e8 --- /dev/null +++ b/Misc/NEWS.d/3.13.0a2.rst @@ -0,0 +1,1622 @@ +.. date: 2023-11-20-14-13-02 +.. gh-issue: 112243 +.. nonce: FKdQnr +.. release date: 2023-11-22 +.. section: Core and Builtins + +Don't include comments in f-string debug expressions. Patch by Pablo Galindo + +.. + +.. date: 2023-11-20-10-40-40 +.. gh-issue: 112287 +.. nonce: 15gWAK +.. section: Core and Builtins + +Slightly optimize the Tier 2 (uop) interpreter by only loading ``oparg`` and +``operand`` when needed. Also double the trace size limit again, to 512 this +time. + +.. + +.. date: 2023-11-19-15-57-23 +.. gh-issue: 112266 +.. nonce: BSJMbR +.. section: Core and Builtins + +Change docstrings of :attr:`~object.__dict__` and +:attr:`~object.__weakref__`. + +.. + +.. date: 2023-11-17-16-49-32 +.. gh-issue: 111807 +.. nonce: QvjP9_ +.. section: Core and Builtins + +Lower the max parser stack depth to 1000 under WASI debug builds. + +.. + +.. date: 2023-11-15-20-20-51 +.. gh-issue: 111798 +.. nonce: cs-3t3 +.. section: Core and Builtins + +When Python is built in debug mode, set the C recursion limit to 500 instead +of 1500. A debug build is likely built with low optimization level which +implies higher stack memory usage than a release build. Patch by Victor +Stinner. + +.. + +.. date: 2023-11-15-16-14-10 +.. gh-issue: 106529 +.. nonce: Y48ax9 +.. section: Core and Builtins + +Enable translating unspecialized ``FOR_ITER`` to Tier 2. + +.. + +.. date: 2023-11-14-22-12-11 +.. gh-issue: 111916 +.. nonce: ZGCayL +.. section: Core and Builtins + +Make hashlib related modules thread-safe without the GIL + +.. + +.. date: 2023-11-07-12-59-02 +.. gh-issue: 81137 +.. nonce: qFpJCY +.. section: Core and Builtins + +Deprecate assignment to a function's ``__code__`` field when the new code +object is of a mismatched type (e.g., from a generator to a plain function). + +.. + +.. date: 2023-11-06-16-44-09 +.. gh-issue: 79932 +.. nonce: 2qv7uD +.. section: Core and Builtins + +Raise exception if :meth:`frame.clear` is called on a suspended frame. + +.. + +.. date: 2023-11-05-20-59-10 +.. gh-issue: 81925 +.. nonce: wKHLSS +.. section: Core and Builtins + +Implement native thread ids for GNU KFreeBSD. + +.. + +.. date: 2023-11-05-06-40-35 +.. gh-issue: 111843 +.. nonce: c045cB +.. section: Core and Builtins + +Use exponential backoff to reduce the number of failed tier 2 optimization +attempts by over 99%. + +.. + +.. date: 2023-11-04-13-36-51 +.. gh-issue: 110829 +.. nonce: Pa0CJI +.. section: Core and Builtins + +Joining a thread now ensures the underlying OS thread has exited. This is +required for safer fork() in multi-threaded processes. + +.. + +.. date: 2023-11-03-22-48-29 +.. gh-issue: 109369 +.. nonce: ELYaxJ +.. section: Core and Builtins + +Make sure that tier 2 traces are de-optimized if the code is instrumented + +.. + +.. date: 2023-11-03-19-25-38 +.. gh-issue: 111772 +.. nonce: aRQvOn +.. section: Core and Builtins + +Specialize slot loads and stores for _Py_T_OBJECT as well as Py_T_OBJECT_EX + +.. + +.. date: 2023-11-03-01-23-48 +.. gh-issue: 111666 +.. nonce: l8Q8G5 +.. section: Core and Builtins + +Speed up :meth:`BaseExceptionGroup.derive`, +:meth:`BaseExceptionGroup.subgroup`, and :meth:`BaseExceptionGroup.split` by +changing how they parse passed arguments. + +.. + +.. date: 2023-11-03-01-04-55 +.. gh-issue: 111654 +.. nonce: scUhDO +.. section: Core and Builtins + +Fix runtime crash when some error happens in opcode +``LOAD_FROM_DICT_OR_DEREF``. + +.. + +.. date: 2023-11-02-15-00-57 +.. gh-issue: 111623 +.. nonce: BZxYc8 +.. section: Core and Builtins + +Add support for sharing tuples between interpreters using the +cross-interpreter API. Patch by Anthony Shaw. + +.. + +.. date: 2023-11-02-14-49-19 +.. gh-issue: 111354 +.. nonce: gIS3f- +.. section: Core and Builtins + +The oparg of :opcode:`YIELD_VALUE` is now ``1`` if the instruction is part +of a yield-from or await, and ``0`` otherwise. + +The SUSPENDED frame state is now split into ``SUSPENDED`` and +``SUSPENDED_YIELD_FROM``. This simplifies the code in ``_PyGen_yf``. + +.. + +.. date: 2023-10-31-21-33-35 +.. gh-issue: 111520 +.. nonce: vw-rxJ +.. section: Core and Builtins + +Merge the Tier 1 (bytecode) and Tier 2 (micro-ops) interpreters together, +moving the Tier 2 interpreter loop and switch into +``_PyEval_EvalFrameDefault()`` in ``Python/ceval.c``. The +``Python/executor.c`` file is gone. Also the ``TIER_ONE`` and ``TIER_TWO`` +macros are now handled by the code generator. + +**Beware!** This changes the environment variables to enable micro-ops and +their debugging to ``PYTHON_UOPS`` and ``PYTHON_LLTRACE``. + +.. + +.. date: 2023-10-31-14-25-21 +.. gh-issue: 109181 +.. nonce: 11h6Mc +.. section: Core and Builtins + +Speed up :obj:`Traceback` object creation by lazily compute the line number. +Patch by Pablo Galindo + +.. + +.. date: 2023-10-29-20-11-21 +.. gh-issue: 111420 +.. nonce: IUT-GK +.. section: Core and Builtins + +Allow type comments in parenthesized ``with`` statements + +.. + +.. date: 2023-10-29-12-33-33 +.. gh-issue: 111438 +.. nonce: bHTLLl +.. section: Core and Builtins + +Add support for sharing floats between interpreters using the +cross-interpreter API. Patch by Anthony Shaw. + +.. + +.. date: 2023-10-29-11-35-21 +.. gh-issue: 111435 +.. nonce: ageUWQ +.. section: Core and Builtins + +Add support for sharing of True and False between interpreters using the +cross-interpreter API. Patch by Anthony Shaw. + +.. + +.. date: 2023-10-27-19-38-33 +.. gh-issue: 102388 +.. nonce: vd5YUZ +.. section: Core and Builtins + +Fix a bug where ``iso2022_jp_3`` and ``iso2022_jp_2004`` codecs read out of +bounds + +.. + +.. date: 2023-10-27-12-17-49 +.. gh-issue: 111366 +.. nonce: _TSknV +.. section: Core and Builtins + +Fix an issue in the :mod:`codeop` that was causing :exc:`SyntaxError` +exceptions raised in the presence of invalid syntax to not contain precise +error messages. Patch by Pablo Galindo + +.. + +.. date: 2023-10-27-11-51-40 +.. gh-issue: 111380 +.. nonce: vgSbir +.. section: Core and Builtins + +Fix a bug that was causing :exc:`SyntaxWarning` to appear twice when parsing +if invalid syntax is encountered later. Patch by Pablo galindo + +.. + +.. date: 2023-10-27-11-22-09 +.. gh-issue: 111374 +.. nonce: e9lrPZ +.. section: Core and Builtins + +Added a new environment variable :envvar:`PYTHON_FROZEN_MODULES`. It +determines whether or not frozen modules are ignored by the import +machinery, equivalent of the :option:`-X frozen_modules <-X>` command-line +option. + +.. + +.. date: 2023-10-26-18-45-20 +.. gh-issue: 111354 +.. nonce: GrT-Wf +.. section: Core and Builtins + +Remove ``oparg`` from :opcode:`YIELD_VALUE`. Change ``oparg`` of +:opcode:`RESUME` to include information about the except-depth. These +changes make it possible to simplify the code in generator close. + +.. + +.. date: 2023-10-23-22-11-09 +.. gh-issue: 94438 +.. nonce: y2pITu +.. section: Core and Builtins + +Fix a regression that prevented jumping across ``is None`` and ``is not +None`` when debugging. Patch by Savannah Ostrowski. + +.. + +.. date: 2023-10-23-15-44-47 +.. gh-issue: 67224 +.. nonce: S4D6CR +.. section: Core and Builtins + +Show source lines in tracebacks when using the ``-c`` option when running +Python. Patch by Pablo Galindo + +.. + +.. date: 2023-10-20-23-14-06 +.. gh-issue: 111123 +.. nonce: jjVc3M +.. section: Core and Builtins + +Fix a bug where a :keyword:`global` declaration in an :keyword:`except` +block is rejected when the global is used in the :keyword:`else` block. + +.. + +.. date: 2023-10-17-11-03-45 +.. gh-issue: 110938 +.. nonce: X3sbMb +.. section: Core and Builtins + +Fix error messages for indented blocks with functions and classes with +generic type parameters. Patch by Pablo Galindo + +.. + +.. date: 2023-10-16-15-51-37 +.. gh-issue: 109214 +.. nonce: -RGTFH +.. section: Core and Builtins + +Remove unnecessary instruction pointer updates before returning from frames. + +.. + +.. date: 2023-10-16-12-12-48 +.. gh-issue: 110912 +.. nonce: uEJGi_ +.. section: Core and Builtins + +Correctly display the traceback for :exc:`MemoryError` exceptions using the +:mod:`traceback` module. Patch by Pablo Galindo + +.. + +.. date: 2023-10-15-22-18-45 +.. gh-issue: 109894 +.. nonce: UAmo06 +.. section: Core and Builtins + +Fixed crash due to improperly initialized static :exc:`MemoryError` in +subinterpreter. + +.. + +.. date: 2023-10-15-20-45-35 +.. gh-issue: 110892 +.. nonce: oA6eVY +.. section: Core and Builtins + +Return ``NULL`` for ``PyTrace_RETURN`` events caused by an exception + +.. + +.. date: 2023-10-14-12-19-34 +.. gh-issue: 110864 +.. nonce: -baPDE +.. section: Core and Builtins + +Fix argument parsing by ``_PyArg_UnpackKeywordsWithVararg`` for functions +defining pos-or-keyword, vararg, and kw-only parameters. + +.. + +.. date: 2023-10-13-16-55-55 +.. gh-issue: 109094 +.. nonce: ziL4cJ +.. section: Core and Builtins + +Replace ``prev_instr`` on the interpreter frame by ``instr_ptr`` which +points to the beginning of the instruction that is currently executing (or +will execute once the frame resumes). + +.. + +.. date: 2023-10-13-09-21-29 +.. gh-issue: 110805 +.. nonce: vhU7A7 +.. section: Core and Builtins + +Allow the repl to show source code and complete tracebacks. Patch by Pablo +Galindo + +.. + +.. date: 2023-10-12-17-15-23 +.. gh-issue: 110722 +.. nonce: sjMwQe +.. section: Core and Builtins + +Add :envvar:`PYTHON_PRESITE=package.module` to import a module early in the +interpreter lifecycle before ``site.py`` is executed. Python needs to be +:ref:`built in debug mode ` for this option to exist. + +.. + +.. date: 2023-10-12-12-09-01 +.. gh-issue: 110481 +.. nonce: 3Er3it +.. section: Core and Builtins + +Implement biased reference counting in ``--disable-gil`` builds. + +.. + +.. date: 2023-10-09-19-54-33 +.. gh-issue: 110543 +.. nonce: 1wrxO8 +.. section: Core and Builtins + +Fix regression in Python 3.12 where :meth:`types.CodeType.replace` would +produce a broken code object if called on a module or class code object that +contains a comprehension. Patch by Jelle Zijlstra. + +.. + +.. date: 2023-09-30-17-30-11 +.. gh-issue: 89519 +.. nonce: hz2pZf +.. section: Core and Builtins + +Removed chained :class:`classmethod` descriptors (introduced in +:issue:`19072`). This can no longer be used to wrap other descriptors such +as :class:`property`. The core design of this feature was flawed and caused +a number of downstream problems. To "pass-through" a :class:`classmethod`, +consider using the :attr:`!__wrapped__` attribute that was added in Python +3.10. + +.. + +.. date: 2023-09-15-23-39-43 +.. gh-issue: 103615 +.. nonce: WZavly +.. section: Core and Builtins + +Use local events for opcode tracing + +.. + +.. bpo: 46657 +.. date: 2023-09-06-12-36-11 +.. nonce: xea1T_ +.. section: Core and Builtins + +Add mimalloc memory allocator support. + +.. + +.. date: 2023-08-31-11-42-16 +.. gh-issue: 106718 +.. nonce: _-57DA +.. section: Core and Builtins + +When PyConfig.stdlib_dir is explicitly set, it's now respected and won't be +overridden by PyConfig.home. + +.. + +.. date: 2023-07-20-11-41-16 +.. gh-issue: 106905 +.. nonce: AyZpuB +.. section: Core and Builtins + +Fix incorrect SystemError about AST constructor recursion depth mismatch. + +.. + +.. date: 2022-12-27-02-51-45 +.. gh-issue: 100445 +.. nonce: C8f6ph +.. section: Core and Builtins + +Improve error message for unterminated strings with escapes. + +.. + +.. bpo: 45759 +.. date: 2021-11-10-10-40-05 +.. nonce: WJoB3D +.. section: Core and Builtins + +Improved error messages for ``elif``/``else`` statements not matching any +valid statements. Patch by Jeremiah Vivian. + +.. + +.. date: 2023-11-14-18-43-55 +.. gh-issue: 111942 +.. nonce: x1pnrj +.. section: Library + +Fix SystemError in the TextIOWrapper constructor with non-encodable "errors" +argument in non-debug mode. + +.. + +.. date: 2023-11-14-16-31-59 +.. gh-issue: 111995 +.. nonce: OoX8JJ +.. section: Library + +Added the ``NI_IDN`` constant to the :mod:`socket` module when present in C +at build time for use with :func:`socket.getnameinfo`. + +.. + +.. date: 2023-11-11-16-42-48 +.. gh-issue: 109538 +.. nonce: cMG5ux +.. section: Library + +Issue warning message instead of having :class:`RuntimeError` be displayed +when event loop has already been closed at :meth:`StreamWriter.__del__`. + +.. + +.. date: 2023-11-10-22-08-28 +.. gh-issue: 111942 +.. nonce: MDFm6v +.. section: Library + +Fix crashes in :meth:`io.TextIOWrapper.reconfigure` when pass invalid +arguments, e.g. non-string encoding. + +.. + +.. date: 2023-11-09-12-57-43 +.. gh-issue: 111460 +.. nonce: TQaz9I +.. section: Library + +:mod:`curses`: restore wide character support (including +:func:`curses.unget_wch` and :meth:`~curses.window.get_wch`) on macOS, which +was unavailable due to a regression in Python 3.12. + +.. + +.. date: 2023-11-09-10-45-56 +.. gh-issue: 103791 +.. nonce: sdfkja +.. section: Library + +:class:`contextlib.suppress` now supports suppressing exceptions raised as +part of a :exc:`BaseExceptionGroup`, in addition to the recent support for +:exc:`ExceptionGroup`. + +.. + +.. date: 2023-11-08-23-32-03 +.. gh-issue: 111835 +.. nonce: ufFiuW +.. section: Library + +The :class:`mmap.mmap` class now has an :meth:`~mmap.mmap.seekable` method +that can be used where it requires a file-like object with seekable and the +:meth:`~mmap.mmap.seek` method return the new absolute position. Patch by +Donghee Na. + +.. + +.. date: 2023-11-08-15-58-57 +.. gh-issue: 111804 +.. nonce: uAXTOL +.. section: Library + +Remove posix.fallocate() under WASI as the underlying posix_fallocate() is +not available in WASI preview2. + +.. + +.. date: 2023-11-08-11-50-49 +.. gh-issue: 111841 +.. nonce: iSqdQf +.. section: Library + +Fix truncating arguments on an embedded null character in :meth:`os.putenv` +and :meth:`os.unsetenv` on Windows. + +.. + +.. date: 2023-11-08-07-42-53 +.. gh-issue: 111768 +.. nonce: g-WpnV +.. section: Library + +:func:`wsgiref.util.is_hop_by_hop` is now exposed correctly in ``__all__``. + +.. + +.. date: 2023-11-04-21-12-27 +.. gh-issue: 80731 +.. nonce: Wq51xg +.. section: Library + +Avoid executing the default function in :class:`cmd.Cmd` in an except block + +.. + +.. date: 2023-11-04-10-24-25 +.. gh-issue: 111541 +.. nonce: x0RBI1 +.. section: Library + +Fix :mod:`doctest` for :exc:`SyntaxError` not-builtin subclasses. + +.. + +.. date: 2023-11-04-01-20-23 +.. gh-issue: 111719 +.. nonce: fUiKBD +.. section: Library + +Add extra argument validation for ``alias`` command in :mod:`pdb` + +.. + +.. date: 2023-11-02-12-15-46 +.. gh-issue: 111482 +.. nonce: FWqZIU +.. section: Library + +:mod:`time`: Make :func:`time.clock_gettime()` and +:func:`time.clock_gettime_ns()` functions up to 2x faster by faster calling +convention. Patch by Victor Stinner. + +.. + +.. date: 2023-11-01-14-03-24 +.. gh-issue: 110894 +.. nonce: 7-wZxC +.. section: Library + +Call loop exception handler for exceptions in ``client_connected_cb`` of +:func:`asyncio.start_server` so that applications can handle it. Patch by +Kumar Aditya. + +.. + +.. date: 2023-10-31-07-46-56 +.. gh-issue: 111531 +.. nonce: 6zUV_G +.. section: Library + +Fix reference leaks in ``bind_class()`` and ``bind_all()`` methods of +:mod:`tkinter` widgets. + +.. + +.. date: 2023-10-30-14-47-23 +.. gh-issue: 111246 +.. nonce: QJ_ehs +.. section: Library + +:meth:`asyncio.loop.create_unix_server` will now automatically remove the +Unix socket when the server is closed. + +.. + +.. date: 2023-10-30-08-50-46 +.. gh-issue: 111356 +.. nonce: Bc8LvA +.. section: Library + +Added :func:`io.text_encoding()`, :data:`io.DEFAULT_BUFFER_SIZE`, and +:class:`io.IncrementalNewlineDecoder` to ``io.__all__``. + +.. + +.. date: 2023-10-29-03-46-27 +.. gh-issue: 66425 +.. nonce: FWTdDo +.. section: Library + +Remove the code to set the REMOTE_HOST header from wsgiref module, as it is +unreachable. This header is used for performance reasons, which is not +necessary in the wsgiref module. + +.. + +.. date: 2023-10-28-22-11-11 +.. gh-issue: 111429 +.. nonce: mJGxuQ +.. section: Library + +Speed up :meth:`pathlib.PurePath.relative_to` and +:meth:`~pathlib.PurePath.is_relative_to`. + +.. + +.. date: 2023-10-28-04-21-17 +.. gh-issue: 111342 +.. nonce: m8Ln1k +.. section: Library + +Fixed typo in :func:`math.sumprod`. + +.. + +.. date: 2023-10-27-12-46-56 +.. gh-issue: 68166 +.. nonce: 0EbWW4 +.. section: Library + +Remove mention of not supported "vsapi" element type in +:meth:`tkinter.ttk.Style.element_create`. Add tests for ``element_create()`` +and other ``ttk.Style`` methods. Add examples for ``element_create()`` in +the documentation. + +.. + +.. date: 2023-10-27-09-56-20 +.. gh-issue: 111388 +.. nonce: SlmDbC +.. section: Library + +Add ``show_group`` parameter to :func:`traceback.format_exception_only`, +which allows to format :exc:`ExceptionGroup` instances. + +.. + +.. date: 2023-10-25-11-54-00 +.. gh-issue: 79033 +.. nonce: 5ePgFl +.. section: Library + +Another attempt at fixing :func:`asyncio.Server.wait_closed()`. It now +blocks until both conditions are true: the server is closed, *and* there are +no more active connections. (This means that in some cases where in 3.12.0 +this function would *incorrectly* have returned immediately, it will now +block; in particular, when there are no active connections but the server +hasn't been closed yet.) + +.. + +.. date: 2023-10-25-11-13-35 +.. gh-issue: 111259 +.. nonce: z7ndeA +.. section: Library + +Optimize recursive wildcards in :mod:`pathlib`. + +.. + +.. date: 2023-10-25-08-42-05 +.. gh-issue: 111295 +.. nonce: H2K4lf +.. section: Library + +Fix :mod:`time` not checking for errors when initializing. + +.. + +.. date: 2023-10-24-12-20-46 +.. gh-issue: 111253 +.. nonce: HFywSK +.. section: Library + +Add error checking during :mod:`!_socket` module init. + +.. + +.. date: 2023-10-24-12-09-46 +.. gh-issue: 111251 +.. nonce: urFYtn +.. section: Library + +Fix :mod:`_blake2` not checking for errors when initializing. + +.. + +.. date: 2023-10-23-23-14-54 +.. gh-issue: 111233 +.. nonce: sCdCC0 +.. section: Library + +Fix :mod:`select` not checking for errors when initializing. + +.. + +.. date: 2023-10-23-22-40-47 +.. gh-issue: 111230 +.. nonce: k3Jm84 +.. section: Library + +Fix :mod:`ssl` not checking for errors when initializing. + +.. + +.. date: 2023-10-23-13-53-58 +.. gh-issue: 111174 +.. nonce: Oohmzd +.. section: Library + +Fix crash in :meth:`io.BytesIO.getbuffer` called repeatedly for empty +BytesIO. + +.. + +.. date: 2023-10-22-21-28-05 +.. gh-issue: 111187 +.. nonce: _W11Ab +.. section: Library + +Postpone removal version for locale.getdefaultlocale() to Python 3.15. + +.. + +.. date: 2023-10-21-13-57-06 +.. gh-issue: 111159 +.. nonce: GoHp7s +.. section: Library + +Fix :mod:`doctest` output comparison for exceptions with notes. + +.. + +.. date: 2023-10-20-15-29-10 +.. gh-issue: 110910 +.. nonce: u2oPwX +.. section: Library + +Fix invalid state handling in :class:`asyncio.TaskGroup` and +:class:`asyncio.Timeout`. They now raise proper RuntimeError if they are +improperly used and are left in consistent state after this. + +.. + +.. date: 2023-10-19-22-46-34 +.. gh-issue: 111092 +.. nonce: hgut12 +.. section: Library + +Make turtledemo run without default root enabled. + +.. + +.. date: 2023-10-16-18-41-51 +.. gh-issue: 110944 +.. nonce: CmUKXo +.. section: Library + +Support alias and convenience vars for :mod:`pdb` completion + +.. + +.. date: 2023-10-15-08-08-26 +.. gh-issue: 110745 +.. nonce: mxEkh0 +.. section: Library + +Added *newline* parameter to :meth:`pathlib.Path.read_text`. Patch by Junya +Okabe. + +.. + +.. date: 2023-10-14-21-33-57 +.. gh-issue: 84583 +.. nonce: -Cmn4_ +.. section: Library + +Make :mod:`pdb` enter post-mortem mode even for :exc:`SyntaxError` + +.. + +.. date: 2023-10-14-20-15-53 +.. gh-issue: 80675 +.. nonce: _M-cQC +.. section: Library + +Set ``f_trace_lines = True`` on all frames upon :func:`pdb.set_trace()` + +.. + +.. date: 2023-10-13-06-47-20 +.. gh-issue: 110771 +.. nonce: opwdlc +.. section: Library + +Expose the setup and cleanup portions of ``asyncio.run_forever()`` as the +standalone methods ``asyncio.run_forever_setup()`` and +``asyncio.run_forever_cleanup()``. This allows for tighter integration with +GUI event loops. + +.. + +.. date: 2023-10-12-15-16-44 +.. gh-issue: 110774 +.. nonce: AdCb5A +.. section: Library + +Support setting the :class:`asyncio.Runner` loop_factory kwarg in +:class:`unittest.IsolatedAsyncioTestCase` + +.. + +.. date: 2023-10-10-17-56-41 +.. gh-issue: 110392 +.. nonce: 6g6CnP +.. section: Library + +Fix :func:`tty.setraw` and :func:`tty.setcbreak`: previously they returned +partially modified list of the original tty attributes. +:func:`tty.cfmakeraw` and :func:`tty.cfmakecbreak` now make a copy of the +list of special characters before modifying it. + +.. + +.. date: 2023-10-09-23-59-04 +.. gh-issue: 59013 +.. nonce: qPbS-G +.. section: Library + +Make line number of function breakpoint more precise in :mod:`pdb` + +.. + +.. date: 2023-10-08-18-38-09 +.. gh-issue: 88434 +.. nonce: 2Q_IkG +.. section: Library + +Emit deprecation warning for non-integer numbers in :mod:`gettext` functions +and methods that consider plural forms even if the translation was not +found. + +.. + +.. date: 2023-10-08-14-17-06 +.. gh-issue: 110395 +.. nonce: _tdCsV +.. section: Library + +Ensure that :func:`select.kqueue` objects correctly appear as closed in +forked children, to prevent operations on an invalid file descriptor. + +.. + +.. date: 2023-10-02-05-23-27 +.. gh-issue: 110196 +.. nonce: djwt0z +.. section: Library + +Add ``__reduce__`` method to :class:`IPv6Address` in order to keep +``scope_id`` + +.. + +.. date: 2023-09-25-20-05-41 +.. gh-issue: 109747 +.. nonce: _cRJH8 +.. section: Library + +Improve errors for unsupported look-behind patterns. Now re.error is raised +instead of OverflowError or RuntimeError for too large width of look-behind +pattern. + +.. + +.. date: 2023-09-15-12-30-21 +.. gh-issue: 109466 +.. nonce: 6ah-aw +.. section: Library + +Add the :attr:`ipaddress.IPv4Address.ipv6_mapped` property, which retuns the +IPv4-mapped IPv6 address. + +.. + +.. date: 2023-09-08-12-10-10 +.. gh-issue: 85098 +.. nonce: DfQbeJ +.. section: Library + +Implement the CLI of the :mod:`symtable` module and improve the repr of +:class:`~symtable.Symbol`. + +.. + +.. date: 2023-09-02-16-07-23 +.. gh-issue: 108791 +.. nonce: fBcAqh +.. section: Library + +Improved error handling in :mod:`pdb` command line interface, making it +produce more concise error messages. + +.. + +.. date: 2023-08-30-19-10-35 +.. gh-issue: 105931 +.. nonce: Lpwve8 +.. section: Library + +Change :mod:`compileall` to only strip the stripdir prefix from the full +path recorded in the compiled ``.pyc`` file, when the prefix matches the +start of the full path in its entirety. When the prefix does not match, no +stripping is performed and a warning to this effect is displayed. + +Previously all path components of the stripdir prefix that matched the full +path were removed, while those that did not match were left alone (including +ones interspersed between matching components). + +.. + +.. date: 2023-07-29-19-00-39 +.. gh-issue: 107431 +.. nonce: 1GzJ2p +.. section: Library + +Make the ``DictProxy`` and ``ListProxy`` types in +:mod:`multiprocessing.managers` :ref:`Generic Alias +Types` for ``[]`` use in typing contexts. + +.. + +.. date: 2023-07-13-00-24-52 +.. gh-issue: 72904 +.. nonce: Yn5-j0 +.. section: Library + +Add :func:`glob.translate`. This function converts a pathname with +shell-style wildcards to a regular expression. + +.. + +.. date: 2023-05-30-02-01-14 +.. gh-issue: 90026 +.. nonce: FyCXw8 +.. section: Library + +Define ``USE_XATTRS`` on Cygwin so that XATTR-related functions in the +:mod:`os` module become available. + +.. + +.. date: 2023-04-26-16-37-00 +.. gh-issue: 90890 +.. nonce: fIag4w +.. section: Library + +New methods :meth:`mailbox.Maildir.get_info`, +:meth:`mailbox.Maildir.set_info`, :meth:`mailbox.Maildir.get_flags`, +:meth:`mailbox.Maildir.set_flags`, :meth:`mailbox.Maildir.add_flag`, +:meth:`mailbox.Maildir.remove_flag`. These methods speed up accessing a +message's info and/or flags and are useful when it is not necessary to +access the message's contents, as when iterating over a Maildir to find +messages with specific flags. + +.. + +.. date: 2023-04-15-14-45-21 +.. gh-issue: 102956 +.. nonce: Z6qeUy +.. section: Library + +Fix returning of empty byte strings after seek in zipfile module + +.. + +.. date: 2023-03-22-02-01-30 +.. gh-issue: 102895 +.. nonce: HiEqaZ +.. section: Library + +Added a parameter ``local_exit`` for :func:`code.interact` to prevent +``exit()`` and ``quit`` from closing ``sys.stdin`` and raise ``SystemExit``. + +.. + +.. date: 2022-10-14-21-11-10 +.. gh-issue: 97928 +.. nonce: Pdxh1G +.. section: Library + +Change the behavior of :meth:`tkinter.Text.count`. It now always returns an +integer if one or less counting options are specified. Previously it could +return a single count as a 1-tuple, an integer (only if option ``"update"`` +was specified) or ``None`` if no items found. The result is now the same if +``wantobjects`` is set to ``0``. + +.. + +.. date: 2022-10-05-15-01-36 +.. gh-issue: 96954 +.. nonce: ezwkrU +.. section: Library + +Switch the storage of the unicode codepoint names to use a different +data-structure, a `directed acyclic word graph +`_. +This makes the unicodedata shared library about 440 KiB smaller. Contributed +by Carl Friedrich Bolz-Tereick using code from the PyPy project. + +.. + +.. date: 2022-05-28-20-55-07 +.. gh-issue: 73561 +.. nonce: YRmAvy +.. section: Library + +Omit the interface scope from an IPv6 address when used as Host header by +:mod:`http.client`. + +.. + +.. date: 2022-05-06-15-49-57 +.. gh-issue: 86826 +.. nonce: rf006W +.. section: Library + +:mod:`zipinfo` now supports the full range of values in the TZ string +determined by RFC 8536 and detects all invalid formats. Both Python and C +implementations now raise exceptions of the same type on invalid data. + +.. + +.. date: 2023-11-17-15-20-41 +.. gh-issue: 111808 +.. nonce: jtIayt +.. section: Tests + +Make the default value of ``test.support.infinite_recursion()`` to be +conditional based on whether optimizations were used when compiling the +interpreter. This helps with platforms like WASI whose stack size is greatly +restricted in debug builds. + +.. + +.. date: 2023-11-03-18-59-13 +.. gh-issue: 110722 +.. nonce: jvT1pb +.. section: Tests + +Gathering line coverage of standard libraries within the regression test +suite is now precise, as well as much faster. Patch by Åukasz Langa. + +.. + +.. date: 2023-10-31-22-09-25 +.. gh-issue: 110367 +.. nonce: UhQi44 +.. section: Tests + +Make regrtest ``--verbose3`` option compatible with ``--huntrleaks -jN`` +options. The ``./python -m test -j1 -R 3:3 --verbose3`` command now works as +expected. Patch by Victor Stinner. + +.. + +.. date: 2023-10-21-19-27-36 +.. gh-issue: 111165 +.. nonce: FU6mUk +.. section: Tests + +Remove no longer used functions ``run_unittest()`` and ``run_doctest()`` +from the :mod:`test.support` module. + +.. + +.. date: 2023-10-21-00-10-36 +.. gh-issue: 110932 +.. nonce: jktjJU +.. section: Tests + +Fix regrtest if the ``SOURCE_DATE_EPOCH`` environment variable is defined: +use the variable value as the random seed. Patch by Victor Stinner. + +.. + +.. date: 2023-10-17-17-54-36 +.. gh-issue: 110995 +.. nonce: Fx8KRD +.. section: Tests + +test_gdb: Fix detection of gdb built without Python scripting support. Patch +by Victor Stinner. + +.. + +.. date: 2023-10-16-13-47-24 +.. gh-issue: 110918 +.. nonce: aFgZK3 +.. section: Tests + +Test case matching patterns specified by options ``--match``, ``--ignore``, +``--matchfile`` and ``--ignorefile`` are now tested in the order of +specification, and the last match determines whether the test case be run or +ignored. + +.. + +.. date: 2023-09-15-15-00-14 +.. gh-issue: 108747 +.. nonce: ql0owS +.. section: Tests + +Add unit test for ``usercustomize`` and ``sitecustomize`` hooks from +:class:`site`. + +.. + +.. date: 2023-11-15-16-56-20 +.. gh-issue: 96954 +.. nonce: 6FYvKn +.. section: Build + +Make ``make regen-unicodedata`` work for out-of-tree builds of CPython. + +.. + +.. date: 2023-11-15-13-40-29 +.. gh-issue: 112088 +.. nonce: UJQxxh +.. section: Build + +Add ``Tools/build/regen-configure.sh`` script to regenerate the +``configure`` with an Ubuntu container image. The +``quay.io/tiran/cpython_autoconf:271`` container image +(`tiran/cpython_autoconf `_) is +no longer used. Patch by Victor Stinner. + +.. + +.. date: 2023-10-20-15-29-31 +.. gh-issue: 111046 +.. nonce: 2DxQl8 +.. section: Build + +For wasi-threads, memory is now exported to fix compatibility issues with +some wasm runtimes. + +.. + +.. date: 2023-10-17-03-10-40 +.. gh-issue: 110828 +.. nonce: 31vQ9B +.. section: Build + +AIX 32bit needs ``-latomic`` to build the :mod:`!_testcapi` extension +module. + +.. + +.. date: 2023-10-17-01-56-11 +.. gh-issue: 85283 +.. nonce: V156T2 +.. section: Build + +The ``errno``, ``md5``, ``resource``, ``winsound``, ``_ctypes_test``, +``_multiprocessing.posixshmem``, ``_scproxy``, ``_stat``, +``_testimportmultiple`` and ``_uuid`` C extensions are now built with the +:ref:`limited C API `. Patch by Victor Stinner. + +.. + +.. date: 2023-11-13-22-35-27 +.. gh-issue: 111856 +.. nonce: vEtA5z +.. section: Windows + +Fixes :func:`~os.fstat` on file systems that do not support file ID +requests. This includes FAT32 and exFAT. + +.. + +.. date: 2023-10-25-05-01-28 +.. gh-issue: 111293 +.. nonce: FSsLT6 +.. section: Windows + +Fix :data:`os.DirEntry.inode` dropping higher 64 bits of a file id on some +filesystems on Windows. + +.. + +.. date: 2023-10-19-21-46-18 +.. gh-issue: 110913 +.. nonce: CWlPfg +.. section: Windows + +WindowsConsoleIO now correctly chunks large buffers without splitting up +UTF-8 sequences. + +.. + +.. date: 2023-10-31-22-13-05 +.. gh-issue: 59703 +.. nonce: SML6Ag +.. section: macOS + +For macOS framework builds, in ``getpath.c`` use the system ``dladdr`` +function to find the path to the shared library rather than depending on +deprecated macOS APIs. + +.. + +.. date: 2023-10-18-17-26-36 +.. gh-issue: 110950 +.. nonce: sonoma +.. section: macOS + +Update macOS installer to include an upstream Tcl/Tk fix for the ``Secure +coding is not enabled for restorable state!`` warning encountered in Tkinter +on macOS 14 Sonoma. + +.. + +.. date: 2023-10-18-01-40-36 +.. gh-issue: 111015 +.. nonce: NaLI2L +.. section: macOS + +Ensure that IDLE.app and Python Launcher.app are installed with appropriate +permissions on macOS builds. + +.. + +.. date: 2023-09-02-08-49-57 +.. gh-issue: 71383 +.. nonce: Ttkchg +.. section: macOS + +Update macOS installer to include an upstream Tcl/Tk fix for the +``ttk::ThemeChanged`` error encountered in Tkinter. + +.. + +.. date: 2023-08-30-16-33-57 +.. gh-issue: 92603 +.. nonce: ATkKVO +.. section: macOS + +Update macOS installer to include a fix accepted by upstream Tcl/Tk for a +crash encountered after the first :meth:`tkinter.Tk` instance is destroyed. + +.. + +.. bpo: 35668 +.. date: 2019-01-07-06-18-25 +.. nonce: JimxP5 +.. section: IDLE + +Add docstrings to the IDLE debugger module. Fix two bugs: initialize +Idb.botframe (should be in Bdb); in Idb.in_rpc_code, check whether +prev_frame is None before trying to use it. Greatly expand test_debugger. + +.. + +.. date: 2023-11-09-13-04-29 +.. gh-issue: 111903 +.. nonce: 7Prryr +.. section: Tools/Demos + +Argument Clinic now supports the ``@critical_section`` directive that +instructs Argument Clinic to generate a critical section around the function +call, which locks the ``self`` object in ``--disable-gil`` builds. Patch by +Sam Gross. + +.. + +.. date: 2023-11-15-18-36-21 +.. gh-issue: 112026 +.. nonce: _Yybr5 +.. section: C API + +Add again the private ``_PyThreadState_UncheckedGet()`` function as an alias +to the new public :c:func:`PyThreadState_GetUnchecked` function. Patch by +Victor Stinner. + +.. + +.. date: 2023-11-15-17-10-09 +.. gh-issue: 112026 +.. nonce: ts9yyn +.. section: C API + +Restore the removed ``_PyDict_GetItemStringWithError()`` function. It is +used by numpy. Patch by Victor Stinner. + +.. + +.. date: 2023-11-15-16-07-57 +.. gh-issue: 112026 +.. nonce: bnr8dd +.. section: C API + +Restore removed private C API functions, macros and structures which have no +simple replacement for now: + +* _PyDict_GetItem_KnownHash() +* _PyDict_NewPresized() +* _PyHASH_BITS +* _PyHASH_IMAG +* _PyHASH_INF +* _PyHASH_MODULUS +* _PyHASH_MULTIPLIER +* _PyLong_Copy() +* _PyLong_FromDigits() +* _PyLong_New() +* _PyLong_Sign() +* _PyObject_CallMethodId() +* _PyObject_CallMethodNoArgs() +* _PyObject_CallMethodOneArg() +* _PyObject_CallOneArg() +* _PyObject_EXTRA_INIT +* _PyObject_FastCallDict() +* _PyObject_GetAttrId() +* _PyObject_Vectorcall() +* _PyObject_VectorcallMethod() +* _PyStack_AsDict() +* _PyThread_CurrentFrames() +* _PyUnicodeWriter structure +* _PyUnicodeWriter_Dealloc() +* _PyUnicodeWriter_Finish() +* _PyUnicodeWriter_Init() +* _PyUnicodeWriter_Prepare() +* _PyUnicodeWriter_PrepareKind() +* _PyUnicodeWriter_WriteASCIIString() +* _PyUnicodeWriter_WriteChar() +* _PyUnicodeWriter_WriteLatin1String() +* _PyUnicodeWriter_WriteStr() +* _PyUnicodeWriter_WriteSubstring() +* _PyUnicode_AsString() +* _PyUnicode_FromId() +* _PyVectorcall_Function() +* _Py_IDENTIFIER() +* _Py_c_abs() +* _Py_c_diff() +* _Py_c_neg() +* _Py_c_pow() +* _Py_c_prod() +* _Py_c_quot() +* _Py_c_sum() +* _Py_static_string() +* _Py_static_string_init() + +Patch by Victor Stinner. + +.. + +.. date: 2023-11-13-17-57-11 +.. gh-issue: 112026 +.. nonce: WJLJcI +.. section: C API + +Add again ```` and ```` includes in ``Python.h``, but +don't include them in the limited C API version 3.13 and newer. Patch by +Victor Stinner. + +.. + +.. date: 2023-11-10-10-24-28 +.. gh-issue: 111956 +.. nonce: ImE6Cx +.. section: C API + +Add internal-only one-time initialization API: ``_PyOnceFlag`` and +``_PyOnceFlag_CallOnce``. + +.. + +.. date: 2023-11-10-10-21-38 +.. gh-issue: 111262 +.. nonce: 2utB5m +.. section: C API + +Add :c:func:`PyDict_Pop` and :c:func:`PyDict_PopString` functions: remove a +key from a dictionary and optionally return the removed value. This is +similar to :meth:`dict.pop`, but without the default value and not raising +:exc:`KeyError` if the key missing. Patch by Stefan Behnel and Victor +Stinner. + +.. + +.. date: 2023-11-08-20-28-03 +.. gh-issue: 111863 +.. nonce: RPeFAX +.. section: C API + +Rename ``Py_NOGIL`` to ``Py_GIL_DISABLED``. Patch by Hugo van Kemenade. + +.. + +.. date: 2023-11-08-18-37-19 +.. gh-issue: 111138 +.. nonce: 3Ypq8h +.. section: C API + +Add :c:func:`PyList_Extend` and :c:func:`PyList_Clear` functions: similar to +Python ``list.extend()`` and ``list.clear()`` methods. Patch by Victor +Stinner. + +.. + +.. date: 2023-10-31-18-22-03 +.. gh-issue: 108765 +.. nonce: _beYv8 +.. section: C API + +On Windows, ``Python.h`` no longer includes the ```` standard +header file. If needed, it should now be included explicitly. Patch by +Victor Stinner. + +.. + +.. date: 2023-10-31-14-58-17 +.. gh-issue: 111569 +.. nonce: _V8iu4 +.. section: C API + +Implement "Python Critical Sections" from :pep:`703`. These are macros to +help replace the GIL with per-object locks in the ``--disable-gil`` build of +CPython. The macros are no-ops in the default build. + +.. + +.. date: 2023-10-30-18-13-01 +.. gh-issue: 111506 +.. nonce: EUdO22 +.. section: C API + +In the limited C API version 3.13, :c:func:`Py_SET_REFCNT` function is now +implemented as an opaque function call. Patch by Victor Stinner. + +.. + +.. date: 2023-10-19-22-39-24 +.. gh-issue: 108082 +.. nonce: uJytvc +.. section: C API + +Add :c:func:`PyErr_FormatUnraisable` function. + +.. + +.. date: 2023-10-17-10-21-59 +.. gh-issue: 110964 +.. nonce: OxqEjd +.. section: C API + +Move the undocumented private _PyArg functions and _PyArg_Parser structure +to internal C API (``pycore_modsupport.h``). Patch by Victor Stinner. + +.. + +.. date: 2023-10-13-14-18-06 +.. gh-issue: 110815 +.. nonce: tEFLVl +.. section: C API + +Support non-ASCII keyword names in :c:func:`PyArg_ParseTupleAndKeywords`. + +.. + +.. date: 2023-10-02-23-08-53 +.. gh-issue: 109587 +.. nonce: UqqnDY +.. section: C API + +Introduced :c:func:`PyUnstable_PerfTrampoline_CompileCode`, +:c:func:`PyUnstable_PerfTrampoline_SetPersistAfterFork` and +:c:func:`PyUnstable_CopyPerfMapFile`. These functions allow extension +modules to initialize trampolines eagerly, after the application is "warmed +up". This makes it possible to have perf-trampolines running in an +always-enabled fashion. + +.. + +.. date: 2023-08-28-17-40-51 +.. gh-issue: 85283 +.. nonce: raFNiD +.. section: C API + +Add the :c:func:`PySys_Audit` function to the limited C API. Patch by Victor +Stinner. + +.. + +.. date: 2023-08-28-17-34-10 +.. gh-issue: 85283 +.. nonce: f1zXcc +.. section: C API + +Add :c:func:`PyMem_RawMalloc`, :c:func:`PyMem_RawCalloc`, +:c:func:`PyMem_RawRealloc` and :c:func:`PyMem_RawFree` to the limited C API. +Patch by Victor Stinner. + +.. + +.. date: 2023-07-12-12-14-52 +.. gh-issue: 106672 +.. nonce: fkRjmi +.. section: C API + +Functions :c:func:`PyDict_GetItem`, :c:func:`PyDict_GetItemString`, +:c:func:`PyMapping_HasKey`, :c:func:`PyMapping_HasKeyString`, +:c:func:`PyObject_HasAttr`, :c:func:`PyObject_HasAttrString`, and +:c:func:`PySys_GetObject`, which clear all errors occurred during calling +the function, report now them using :func:`sys.unraisablehook`. + +.. + +.. date: 2023-06-08-21-12-44 +.. gh-issue: 67565 +.. nonce: UkK3x- +.. section: C API + +Remove redundant C-contiguity check in :file:`getargs.c`, :mod:`binascii`, +:mod:`ssl` and Argument Clinic. Patched by Stefan Krah and Furkan Onder diff --git a/Misc/NEWS.d/3.5.0a1.rst b/Misc/NEWS.d/3.5.0a1.rst index 96e59206cb1291..f793323f217070 100644 --- a/Misc/NEWS.d/3.5.0a1.rst +++ b/Misc/NEWS.d/3.5.0a1.rst @@ -2648,7 +2648,7 @@ module. .. nonce: THJSYB .. section: Library -Changed FeedParser feed() to avoid O(N\ :sup:`2`) behavior when parsing long line. +Changed FeedParser feed() to avoid *O*\ (*n*\ :sup:`2`) behavior when parsing long line. Original patch by Raymond Hettinger. .. diff --git a/Misc/NEWS.d/3.5.0rc1.rst b/Misc/NEWS.d/3.5.0rc1.rst index 1fb9bc6c04da38..64e9435b252acb 100644 --- a/Misc/NEWS.d/3.5.0rc1.rst +++ b/Misc/NEWS.d/3.5.0rc1.rst @@ -168,7 +168,7 @@ Sanad Zaki Rizvi. Idle editor default font. Switch from Courier to platform-sensitive TkFixedFont. This should not affect current customized font selections. If -there is a problem, edit $HOME/.idlerc/config-main.cfg and remove 'fontxxx' +there is a problem, edit $HOME/.idlerc/config-main.cfg and remove ':samp:`font{xxx}`' entries from [Editor Window]. Patch by Mark Roseman. .. diff --git a/Misc/NEWS.d/3.5.1rc1.rst b/Misc/NEWS.d/3.5.1rc1.rst index dc247ce2096a7d..05e1ecfaf6bc79 100644 --- a/Misc/NEWS.d/3.5.1rc1.rst +++ b/Misc/NEWS.d/3.5.1rc1.rst @@ -189,7 +189,7 @@ comprehensions correspond to the opening brace. .. nonce: 0Gh-Ty .. section: Core and Builtins -Hide the private _Py_atomic_xxx symbols from the public Python.h header to +Hide the private :samp:`_Py_atomic_{xxx}` symbols from the public Python.h header to fix a compilation error with OpenMP. PyThreadState_GET() becomes an alias to PyThreadState_Get() to avoid ABI incompatibilities. diff --git a/Misc/NEWS.d/3.5.4.rst b/Misc/NEWS.d/3.5.4.rst index cd0ca4872f1ab0..7839fa2709ecf2 100644 --- a/Misc/NEWS.d/3.5.4.rst +++ b/Misc/NEWS.d/3.5.4.rst @@ -5,4 +5,4 @@ .. section: Library ftplib.FTP.putline() now throws ValueError on commands that contains CR or -LF. Patch by Dong-hee Na. +LF. Patch by Donghee Na. diff --git a/Misc/NEWS.d/3.5.4rc1.rst b/Misc/NEWS.d/3.5.4rc1.rst index 04a035a41e7461..d65d5d14ee78bb 100644 --- a/Misc/NEWS.d/3.5.4rc1.rst +++ b/Misc/NEWS.d/3.5.4rc1.rst @@ -340,7 +340,7 @@ not keep objects alive longer than expected. .. section: Library inspect.signature() now supports callables with variable-argument parameters -wrapped with partialmethod. Patch by Dong-hee Na. +wrapped with partialmethod. Patch by Donghee Na. .. diff --git a/Misc/NEWS.d/3.6.0a2.rst b/Misc/NEWS.d/3.6.0a2.rst index 1b336d7bc5137a..05b3d9f0463c1c 100644 --- a/Misc/NEWS.d/3.6.0a2.rst +++ b/Misc/NEWS.d/3.6.0a2.rst @@ -603,7 +603,7 @@ configuring text widget colors to a new function. .. nonce: RbyFuV .. section: IDLE -Rename many `idlelib/*.py` and `idle_test/test_*.py` files. Edit files to +Rename many ``idlelib/*.py`` and ``idle_test/test_*.py`` files. Edit files to replace old names with new names when the old name referred to the module rather than the class it contained. See the issue and IDLE section in What's New in 3.6 for more. diff --git a/Misc/NEWS.d/3.6.2rc1.rst b/Misc/NEWS.d/3.6.2rc1.rst index cdf4c3d541c4ca..28eb88f79130c5 100644 --- a/Misc/NEWS.d/3.6.2rc1.rst +++ b/Misc/NEWS.d/3.6.2rc1.rst @@ -77,7 +77,7 @@ delivered to the innermost frame. .. section: Core and Builtins sys.getsizeof() on a code object now returns the sizes which includes the -code struct and sizes of objects which it references. Patch by Dong-hee Na. +code struct and sizes of objects which it references. Patch by Donghee Na. .. @@ -163,7 +163,7 @@ no longer ignored. Patch by Mircea Cosbuc. .. nonce: I2mDTz .. section: Library -Functional API of enum allows to create empty enums. Patched by Dong-hee Na +Functional API of enum allows to create empty enums. Patched by Donghee Na .. @@ -202,7 +202,7 @@ not keep objects alive longer than expected. .. section: Library inspect.signature() now supports callables with variable-argument parameters -wrapped with partialmethod. Patch by Dong-hee Na. +wrapped with partialmethod. Patch by Donghee Na. .. diff --git a/Misc/NEWS.d/3.6.3rc1.rst b/Misc/NEWS.d/3.6.3rc1.rst index 4dc2eef5d3b61b..4b2aae9dc88441 100644 --- a/Misc/NEWS.d/3.6.3rc1.rst +++ b/Misc/NEWS.d/3.6.3rc1.rst @@ -506,7 +506,7 @@ Fix handling of long oids in ssl. Based on patch by Christian Heimes. .. section: Library ftplib.FTP.putline() now throws ValueError on commands that contains CR or -LF. Patch by Dong-hee Na. +LF. Patch by Donghee Na. .. diff --git a/Misc/NEWS.d/3.6.6rc1.rst b/Misc/NEWS.d/3.6.6rc1.rst index 71a5c3ec595ba2..9624195c79043b 100644 --- a/Misc/NEWS.d/3.6.6rc1.rst +++ b/Misc/NEWS.d/3.6.6rc1.rst @@ -289,7 +289,7 @@ literals on pydoc. Patch by Andrés Delfino. .. section: Library Update error message when constructing invalid inspect.Parameters Patch by -Dong-hee Na. +Donghee Na. .. diff --git a/Misc/NEWS.d/3.7.0a1.rst b/Misc/NEWS.d/3.7.0a1.rst index 712558bf98d018..bee424241fd712 100644 --- a/Misc/NEWS.d/3.7.0a1.rst +++ b/Misc/NEWS.d/3.7.0a1.rst @@ -529,7 +529,7 @@ name are now supported. .. section: Core and Builtins sys.getsizeof() on a code object now returns the sizes which includes the -code struct and sizes of objects which it references. Patch by Dong-hee Na. +code struct and sizes of objects which it references. Patch by Donghee Na. .. @@ -2260,7 +2260,7 @@ Update zlib to 1.2.11. .. section: Library ftplib.FTP.putline() now throws ValueError on commands that contains CR or -LF. Patch by Dong-hee Na. +LF. Patch by Donghee Na. .. @@ -2329,7 +2329,7 @@ always return bytes. .. nonce: I2mDTz .. section: Library -Functional API of enum allows to create empty enums. Patched by Dong-hee Na +Functional API of enum allows to create empty enums. Patched by Donghee Na .. @@ -2612,7 +2612,7 @@ Fix handling escape characters in HZ codec. Based on patch by Ma Lin. .. section: Library inspect.signature() now supports callables with variable-argument parameters -wrapped with partialmethod. Patch by Dong-hee Na. +wrapped with partialmethod. Patch by Donghee Na. .. diff --git a/Misc/NEWS.d/3.7.0a3.rst b/Misc/NEWS.d/3.7.0a3.rst index 52df0e7e82b080..a968616f55be68 100644 --- a/Misc/NEWS.d/3.7.0a3.rst +++ b/Misc/NEWS.d/3.7.0a3.rst @@ -539,7 +539,7 @@ optional .. section: Library Updates 2to3 to convert from operator.isCallable(obj) to callable(obj). -Patch by Dong-hee Na. +Patch by Donghee Na. .. @@ -549,7 +549,7 @@ Patch by Dong-hee Na. .. section: Library inspect.signature should follow :pep:`8`, if the parameter has an annotation -and a default value. Patch by Dong-hee Na. +and a default value. Patch by Donghee Na. .. diff --git a/Misc/NEWS.d/3.7.0a4.rst b/Misc/NEWS.d/3.7.0a4.rst index f19d1a1823584b..ebae046a7a6ba0 100644 --- a/Misc/NEWS.d/3.7.0a4.rst +++ b/Misc/NEWS.d/3.7.0a4.rst @@ -842,5 +842,5 @@ Moved the pygetopt.h header into internal/, since it has no public APIs. .. nonce: LbyQt6 .. section: C API -:c:func:`Py_SetProgramName` and :c:func:`Py_SetPythonHome` now take the +:c:func:`!Py_SetProgramName` and :c:func:`!Py_SetPythonHome` now take the ``const wchar *`` arguments instead of ``wchar *``. diff --git a/Misc/NEWS.d/3.7.0b5.rst b/Misc/NEWS.d/3.7.0b5.rst index 20476993b9652a..fb29109869188b 100644 --- a/Misc/NEWS.d/3.7.0b5.rst +++ b/Misc/NEWS.d/3.7.0b5.rst @@ -418,7 +418,7 @@ trigger a ``DeprecationWarning`` and have been marked for removal in Python .. section: Library Update error message when constructing invalid inspect.Parameters Patch by -Dong-hee Na. +Donghee Na. .. diff --git a/Misc/NEWS.d/3.8.0a1.rst b/Misc/NEWS.d/3.8.0a1.rst index 467e992780382f..b56cda86f11faa 100644 --- a/Misc/NEWS.d/3.8.0a1.rst +++ b/Misc/NEWS.d/3.8.0a1.rst @@ -380,7 +380,7 @@ Implement :pep:`572` (assignment expressions). Patch by Emily Morehouse. .. nonce: voIdcp .. section: Core and Builtins -Speed up :class:`namedtuple` attribute access by 1.6x using a C fast-path +Speed up :func:`namedtuple` attribute access by 1.6x using a C fast-path for the name descriptors. Patch by Pablo Galindo. .. @@ -1965,7 +1965,7 @@ result of an internal future if it's already done. .. section: Library Add a deprecated warning for the :meth:`threading.Thread.isAlive` method. -Patch by Dong-hee Na. +Patch by Donghee Na. .. @@ -2006,8 +2006,8 @@ Improved support of custom data descriptors in :func:`help` and .. nonce: V4kNN3 .. section: Library -The `crypt` module now internally uses the `crypt_r()` library function -instead of `crypt()` when available. +The ``crypt`` module now internally uses the ``crypt_r()`` library function +instead of ``crypt()`` when available. .. @@ -3592,7 +3592,7 @@ Python 3.5. .. nonce: V8Ou3K .. section: Library -Deprecate :meth:`__getitem__` methods of +Deprecate :meth:`~object.__getitem__` methods of :class:`xml.dom.pulldom.DOMEventStream`, :class:`wsgiref.util.FileWrapper` and :class:`fileinput.FileInput`. @@ -4974,7 +4974,7 @@ Enum members. .. section: Library Update error message when constructing invalid inspect.Parameters Patch by -Dong-hee Na. +Donghee Na. .. @@ -5044,8 +5044,8 @@ functionality. .. nonce: C_K-J9 .. section: Library -`ConfigParser.items()` was fixed so that key-value pairs passed in via -`vars` are not included in the resulting output. +``ConfigParser.items()`` was fixed so that key-value pairs passed in via +:func:`vars` are not included in the resulting output. .. @@ -8253,7 +8253,7 @@ Explain how IDLE's Shell displays output. Improve the doc about IDLE running user code. The section is renamed from "IDLE -- console differences" is renamed "Running user code". It mostly -covers the implications of using custom sys.stdxxx objects. +covers the implications of using custom :samp:`sys.std{xxx}` objects. .. @@ -8765,7 +8765,7 @@ for relative path to files in current directory. .. nonce: fmehdG .. section: C API -The :c:func:`PyByteArray_Init` and :c:func:`PyByteArray_Fini` functions have +The :c:func:`!PyByteArray_Init` and :c:func:`!PyByteArray_Fini` functions have been removed. They did nothing since Python 2.7.4 and Python 3.2.0, were excluded from the limited API (stable ABI), and were not documented. @@ -8836,7 +8836,7 @@ Py_LIMITED_API. Patch by Arthur Neufeld. .. nonce: gFd85N .. section: C API -The :c:func:`_PyObject_GC_TRACK` and :c:func:`_PyObject_GC_UNTRACK` macros +The :c:func:`!_PyObject_GC_TRACK` and :c:func:`!_PyObject_GC_UNTRACK` macros have been removed from the public C API. .. diff --git a/Misc/NEWS.d/3.8.0a4.rst b/Misc/NEWS.d/3.8.0a4.rst index 524a05a7ae9704..3097245b74a511 100644 --- a/Misc/NEWS.d/3.8.0a4.rst +++ b/Misc/NEWS.d/3.8.0a4.rst @@ -124,7 +124,7 @@ Galindo. .. nonce: CjRps3 .. section: Core and Builtins -:c:func:`PyEval_AcquireLock` and :c:func:`PyEval_AcquireThread` now +:c:func:`!PyEval_AcquireLock` and :c:func:`!PyEval_AcquireThread` now terminate the current thread if called while the interpreter is finalizing, making them consistent with :c:func:`PyEval_RestoreThread`, :c:func:`Py_END_ALLOW_THREADS`, and :c:func:`PyGILState_Ensure`. @@ -255,7 +255,7 @@ all tags in a namespace. Patch by Stefan Behnel. .. nonce: Lpm-SI .. section: Library -`pathlib.path.link_to()` is now implemented. It creates a hard link pointing +``pathlib.path.link_to()`` is now implemented. It creates a hard link pointing to a path. .. @@ -1087,7 +1087,7 @@ on the ABI. Change ``PyAPI_FUNC(type)``, ``PyAPI_DATA(type)`` and ``PyMODINIT_FUNC`` macros of ``pyport.h`` when ``Py_BUILD_CORE_MODULE`` is defined. The ``Py_BUILD_CORE_MODULE`` define must be now be used to build a C extension -as a dynamic library accessing Python internals: export the PyInit_xxx() +as a dynamic library accessing Python internals: export the :samp:`PyInit_{xxx}()` function in DLL exports on Windows. .. @@ -1344,7 +1344,7 @@ Fix the argument handling in Tools/scripts/lll.py. .. nonce: vghb86 .. section: C API -Fix memory leak in :c:func:`Py_SetStandardStreamEncoding`: release memory if +Fix memory leak in :c:func:`!Py_SetStandardStreamEncoding`: release memory if the function is called twice. .. diff --git a/Misc/NEWS.d/3.8.0b1.rst b/Misc/NEWS.d/3.8.0b1.rst index 72e6b31874e373..c5e27b04ef8e8b 100644 --- a/Misc/NEWS.d/3.8.0b1.rst +++ b/Misc/NEWS.d/3.8.0b1.rst @@ -2047,6 +2047,6 @@ unbound methods. These are objects supporting the optimization given by the .. nonce: FR-dMP .. section: C API -The :c:func:`PyEval_ReInitThreads` function has been removed from the C API. +The :c:func:`!PyEval_ReInitThreads` function has been removed from the C API. It should not be called explicitly: use :c:func:`PyOS_AfterFork_Child` instead. diff --git a/Misc/NEWS.d/3.9.0a1.rst b/Misc/NEWS.d/3.9.0a1.rst index 43676836478c91..b365e5fbfb0dbe 100644 --- a/Misc/NEWS.d/3.9.0a1.rst +++ b/Misc/NEWS.d/3.9.0a1.rst @@ -33,7 +33,7 @@ Fixes audit event for :func:`os.system` to be named ``os.system``. .. section: Security Escape the server title of :class:`xmlrpc.server.DocXMLRPCServer` when -rendering the document page as HTML. (Contributed by Dong-hee Na in +rendering the document page as HTML. (Contributed by Donghee Na in :issue:`38243`.) .. @@ -203,7 +203,7 @@ arguments in decorators. .. section: Core and Builtins Fix a segmentation fault when using reverse iterators of empty ``dict`` -objects. Patch by Dong-hee Na and Inada Naoki. +objects. Patch by Donghee Na and Inada Naoki. .. @@ -280,7 +280,7 @@ visited by ``tp_traverse()`` are valid. .. section: Core and Builtins Remove unnecessary intersection and update set operation in dictview with -empty set. (Contributed by Dong-hee Na in :issue:`38210`.) +empty set. (Contributed by Donghee Na in :issue:`38210`.) .. @@ -1194,7 +1194,7 @@ Expose the Linux ``pidfd_open`` syscall as :func:`os.pidfd_open`. .. section: Library Added constants :const:`~fcntl.F_OFD_GETLK`, :const:`~fcntl.F_OFD_SETLK` and -:const:`~fcntl.F_OFD_SETLKW` to the :mod:`fcntl` module. Patch by Dong-hee +:const:`~fcntl.F_OFD_SETLKW` to the :mod:`fcntl` module. Patch by Donghee Na. .. @@ -1284,7 +1284,7 @@ Fixed erroneous equality comparison in statistics.NormalDist(). .. section: Library Added :const:`~os.CLD_KILLED` and :const:`~os.CLD_STOPPED` for -:attr:`si_code`. Patch by Dong-hee Na. +:attr:`si_code`. Patch by Donghee Na. .. @@ -1882,7 +1882,7 @@ avoid dynamic lookup. .. section: Library Update :class:`importlib.machinery.BuiltinImporter` to use -``loader._ORIGIN`` instead of a hardcoded value. Patch by Dong-hee Na. +``loader._ORIGIN`` instead of a hardcoded value. Patch by Donghee Na. .. @@ -2069,7 +2069,7 @@ Restores instantiation of Windows IOCP event loops from the non-main thread. .. section: Library Add default implementation of the :meth:`ast.NodeVisitor.visit_Constant` -method which emits a deprecation warning and calls corresponding methody +method which emits a deprecation warning and calls corresponding methods ``visit_Num()``, ``visit_Str()``, etc. .. @@ -2080,7 +2080,7 @@ method which emits a deprecation warning and calls corresponding methody .. section: Library Update test_statistics.py to verify that the statistics module works well -for both C and Python implementations. Patch by Dong-hee Na +for both C and Python implementations. Patch by Donghee Na .. @@ -2201,7 +2201,7 @@ uses more than ``SIGSTKSZ`` bytes of stack memory on some platforms. .. nonce: AmXrik .. section: Library -Add C fastpath for statistics.NormalDist.inv_cdf() Patch by Dong-hee Na +Add C fastpath for statistics.NormalDist.inv_cdf() Patch by Donghee Na .. @@ -2210,7 +2210,7 @@ Add C fastpath for statistics.NormalDist.inv_cdf() Patch by Dong-hee Na .. nonce: Ene6L- .. section: Library -Remove the deprecated method `threading.Thread.isAlive()`. Patch by Dong-hee +Remove the deprecated method `threading.Thread.isAlive()`. Patch by Donghee Na. .. @@ -2534,7 +2534,7 @@ object when `self._spec_signature` exists. Patch by Elizabeth Uselton .. nonce: iXGuoi .. section: Library -Make `from tkinter import *` import only the expected objects. +Make ``from tkinter import *`` import only the expected objects. .. @@ -3117,9 +3117,9 @@ Ensure cookies with ``expires`` attribute are handled in .. section: Library Fix an unintended ValueError from :func:`subprocess.run` when checking for -conflicting `input` and `stdin` or `capture_output` and `stdout` or `stderr` -args when they were explicitly provided but with `None` values within a -passed in `**kwargs` dict rather than as passed directly by name. Patch +conflicting *input* and *stdin* or *capture_output* and *stdout* or *stderr* +args when they were explicitly provided but with ``None`` values within a +passed in ``**kwargs`` dict rather than as passed directly by name. Patch contributed by Rémi Lapeyre. .. @@ -3546,7 +3546,7 @@ Patch by Stein Karlsen. .. nonce: XaJDei .. section: Library -lib2to3 now recognizes expressions after ``*`` and `**` like in ``f(*[] or +lib2to3 now recognizes expressions after ``*`` and ``**`` like in ``f(*[] or [])``. .. @@ -4089,7 +4089,7 @@ Increase code coverage for multiprocessing.shared_memory. .. nonce: Kl1sti .. section: Tests -Add tests for json.dump(..., skipkeys=True). Patch by Dong-hee Na. +Add tests for json.dump(..., skipkeys=True). Patch by Donghee Na. .. @@ -4118,7 +4118,7 @@ Add tests for ROT-13 codec. .. nonce: Zoe9ek .. section: Tests -Added tests for PyDateTime_xxx_GET_xxx() macros of the C API of the +Added tests for :samp:`PyDateTime_{xxx}_GET_{xxx}()` macros of the C API of the :mod:`datetime` module. Patch by Joannah Nanjekye. .. @@ -4576,7 +4576,7 @@ distutils bdist_wininst: bdist_wininst only works on Windows. .. nonce: j5ebdT .. section: Build -Many ``PyRun_XXX()`` functions like :c:func:`PyRun_String` were no longer +Many :samp:`PyRun_{XXX}()` functions like :c:func:`PyRun_String` were no longer exported in ``libpython38.dll`` by mistake. Export them again to fix the ABI compatibility. @@ -5535,7 +5535,7 @@ Tyler Kieft. .. nonce: d0bhEA .. section: C API -:c:func:`Py_SetPath` now sets :data:`sys.executable` to the program full +:c:func:`!Py_SetPath` now sets :data:`sys.executable` to the program full path (:c:func:`Py_GetProgramFullPath`) rather than to the program name (:c:func:`Py_GetProgramName`). @@ -5546,8 +5546,8 @@ path (:c:func:`Py_GetProgramFullPath`) rather than to the program name .. nonce: ZbquVK .. section: C API -Python ignored arguments passed to :c:func:`Py_SetPath`, -:c:func:`Py_SetPythonHome` and :c:func:`Py_SetProgramName`: fix Python +Python ignored arguments passed to :c:func:`!Py_SetPath`, +:c:func:`!Py_SetPythonHome` and :c:func:`!Py_SetProgramName`: fix Python initialization to use specified arguments. .. diff --git a/Misc/NEWS.d/3.9.0a3.rst b/Misc/NEWS.d/3.9.0a3.rst index 8b7ff49668e1c0..bc7f4f9c5d39c1 100644 --- a/Misc/NEWS.d/3.9.0a3.rst +++ b/Misc/NEWS.d/3.9.0a3.rst @@ -149,7 +149,7 @@ argument - by Anthony Sottile. .. section: Core and Builtins Correct the error message when calling the :func:`min` or :func:`max` with -no arguments. Patch by Dong-hee Na. +no arguments. Patch by Donghee Na. .. @@ -392,7 +392,7 @@ Remove ``fractions.gcd()`` function, deprecated since Python 3.5 .. section: Library :class:`~smtplib.LMTP` constructor now has an optional *timeout* parameter. -Patch by Dong-hee Na. +Patch by Donghee Na. .. @@ -414,7 +414,7 @@ Taskaya. :class:`~ftplib.FTP_TLS` and :class:`~ftplib.FTP_TLS` now raise a :class:`ValueError` if the given timeout for their constructor is zero to -prevent the creation of a non-blocking socket. Patch by Dong-hee Na. +prevent the creation of a non-blocking socket. Patch by Donghee Na. .. @@ -425,7 +425,7 @@ prevent the creation of a non-blocking socket. Patch by Dong-hee Na. :class:`~smtplib.SMTP` and :class:`~smtplib.SMTP_SSL` now raise a :class:`ValueError` if the given timeout for their constructor is zero to -prevent the creation of a non-blocking socket. Patch by Dong-hee Na. +prevent the creation of a non-blocking socket. Patch by Donghee Na. .. @@ -454,9 +454,9 @@ resilients to inaccessible sys.path entries (importlib_metadata v1.4.0). .. nonce: _S5VjC .. section: Library -:class:`~!nntplib.NNTP` and :class:`~!nntplib.NNTP_SSL` now raise a +:class:`!NNTP` and :class:`!NNTP_SSL` now raise a :class:`ValueError` if the given timeout for their constructor is zero to -prevent the creation of a non-blocking socket. Patch by Dong-hee Na. +prevent the creation of a non-blocking socket. Patch by Donghee Na. .. @@ -488,7 +488,7 @@ towards *y*. :class:`~poplib.POP3` and :class:`~poplib.POP3_SSL` now raise a :class:`ValueError` if the given timeout for their constructor is zero to -prevent the creation of a non-blocking socket. Patch by Dong-hee Na. +prevent the creation of a non-blocking socket. Patch by Donghee Na. .. @@ -498,7 +498,7 @@ prevent the creation of a non-blocking socket. Patch by Dong-hee Na. .. section: Library Updated the Gmane domain from news.gmane.org to news.gmane.io which is used -for examples of :class:`~!nntplib.NNTP` news reader server and nntplib tests. +for examples of :class:`!NNTP` news reader server and nntplib tests. .. @@ -571,7 +571,7 @@ new task spawning before exception raising. .. section: Library Correctly parenthesize filter-based statements that contain lambda -expressions in mod:`!lib2to3`. Patch by Dong-hee Na. +expressions in mod:`!lib2to3`. Patch by Donghee Na. .. @@ -699,7 +699,7 @@ upon inheritance. Patch by Bar Harel. :meth:`~imaplib.IMAP4.open` method now has an optional *timeout* parameter with this change. The overridden methods of :class:`~imaplib.IMAP4_SSL` and :class:`~imaplib.IMAP4_stream` were applied to this change. Patch by -Dong-hee Na. +Donghee Na. .. diff --git a/Misc/NEWS.d/3.9.0a4.rst b/Misc/NEWS.d/3.9.0a4.rst index 019b34c4082d10..e59435b5509acf 100644 --- a/Misc/NEWS.d/3.9.0a4.rst +++ b/Misc/NEWS.d/3.9.0a4.rst @@ -43,7 +43,7 @@ first item. Patch by Yonatan Goldschmidt. .. nonce: BIIX2M .. section: Core and Builtins -Update clinic tool to use :c:func:`Py_IS_TYPE`. Patch by Dong-hee Na. +Update clinic tool to use :c:func:`Py_IS_TYPE`. Patch by Donghee Na. .. @@ -141,7 +141,7 @@ collection of deleted, pickled objects. .. section: Core and Builtins Fixed a possible crash in :meth:`list.__contains__` when a list is changed -during comparing items. Patch by Dong-hee Na. +during comparing items. Patch by Donghee Na. .. @@ -152,7 +152,7 @@ during comparing items. Patch by Dong-hee Na. :term:`floor division` of float operation now has a better performance. Also the message of :exc:`ZeroDivisionError` for this operation is updated. Patch -by Dong-hee Na. +by Donghee Na. .. diff --git a/Misc/NEWS.d/3.9.0a5.rst b/Misc/NEWS.d/3.9.0a5.rst index 8a1219501e81bf..6ff05788214723 100644 --- a/Misc/NEWS.d/3.9.0a5.rst +++ b/Misc/NEWS.d/3.9.0a5.rst @@ -96,7 +96,7 @@ Port itertools module to multiphase initialization (:pep:`489`). .. section: Core and Builtins Speed up calls to ``frozenset()`` by using the :pep:`590` ``vectorcall`` -calling convention. Patch by Dong-hee Na. +calling convention. Patch by Donghee Na. .. @@ -117,7 +117,7 @@ own variable. .. section: Core and Builtins Speed up calls to ``set()`` by using the :pep:`590` ``vectorcall`` calling -convention. Patch by Dong-hee Na. +convention. Patch by Donghee Na. .. @@ -166,7 +166,7 @@ Allow executing asynchronous comprehensions on the top level when the .. section: Core and Builtins Speed up calls to ``tuple()`` by using the :pep:`590` ``vectorcall`` calling -convention. Patch by Dong-hee Na. +convention. Patch by Donghee Na. .. @@ -571,7 +571,7 @@ Fixed :func:`ast.unparse` for extended slices containing a single element .. nonce: yWq9NJ .. section: Library -Fix :mod:`json.tool` to catch :exc:`BrokenPipeError`. Patch by Dong-hee Na. +Fix :mod:`json.tool` to catch :exc:`BrokenPipeError`. Patch by Donghee Na. .. @@ -783,7 +783,7 @@ when the optional ``qop`` parameter is not present. .. section: Library HTTP status codes ``103 EARLY_HINTS`` and ``425 TOO_EARLY`` are added to -:class:`http.HTTPStatus`. Patch by Dong-hee Na. +:class:`http.HTTPStatus`. Patch by Donghee Na. .. @@ -1133,7 +1133,7 @@ module. Patch by José Roberto Meza Cabrera. .. section: C API Add :c:func:`PyModule_AddType` helper function: add a type to a module. -Patch by Dong-hee Na. +Patch by Donghee Na. .. @@ -1163,7 +1163,7 @@ Python thread state. .. nonce: R3jaTy .. section: C API -Add _PyArg_NoKwnames helper function. Patch by Dong-hee Na. +Add _PyArg_NoKwnames helper function. Patch by Donghee Na. .. @@ -1234,8 +1234,8 @@ method name in the SystemError "bad call flags" error message to ease debug. .. nonce: GOYtIm .. section: C API -Deprecated :c:func:`PyEval_InitThreads` and -:c:func:`PyEval_ThreadsInitialized`. Calling :c:func:`PyEval_InitThreads` +Deprecated :c:func:`!PyEval_InitThreads` and +:c:func:`!PyEval_ThreadsInitialized`. Calling :c:func:`!PyEval_InitThreads` now does nothing. .. diff --git a/Misc/NEWS.d/3.9.0b1.rst b/Misc/NEWS.d/3.9.0b1.rst index 15790bc425c13f..ee87315ad334e9 100644 --- a/Misc/NEWS.d/3.9.0b1.rst +++ b/Misc/NEWS.d/3.9.0b1.rst @@ -490,7 +490,7 @@ The first argument of :func:`pickle.loads` is now positional-only. .. section: Library Update :mod:`!nntplib` to merge :class:`!nntplib.NNTP` and -:class:`!nntplib._NNTPBase`. Patch by Dong-hee Na. +:class:`!nntplib._NNTPBase`. Patch by Donghee Na. .. @@ -500,7 +500,7 @@ Update :mod:`!nntplib` to merge :class:`!nntplib.NNTP` and .. section: Library Update :mod:`dbm.gnu` to use gdbm_count if possible when calling -:func:`len`. Patch by Dong-hee Na. +:func:`len`. Patch by Donghee Na. .. @@ -592,7 +592,7 @@ subdirectories in package data, matching backport in importlib_resources .. nonce: 5GuK2A .. section: Library -:meth:`imaplib.IMAP4.unselect` is added. Patch by Dong-hee Na. +:meth:`imaplib.IMAP4.unselect` is added. Patch by Donghee Na. .. diff --git a/Misc/NEWS.d/next/Build/2020-01-11-23-49-17.bpo-36351.ce8BBh.rst b/Misc/NEWS.d/next/Build/2020-01-11-23-49-17.bpo-36351.ce8BBh.rst new file mode 100644 index 00000000000000..d3cfbfc7ea1000 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2020-01-11-23-49-17.bpo-36351.ce8BBh.rst @@ -0,0 +1 @@ +Do not set ipv6type when cross-compiling. diff --git a/Misc/NEWS.d/next/Build/2020-05-01-23-44-31.bpo-11102.Fw9zeS.rst b/Misc/NEWS.d/next/Build/2020-05-01-23-44-31.bpo-11102.Fw9zeS.rst new file mode 100644 index 00000000000000..6477538edf5550 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2020-05-01-23-44-31.bpo-11102.Fw9zeS.rst @@ -0,0 +1,2 @@ +The :func:`os.major`, :func:`os.makedev`, and :func:`os.minor` functions are +now available on HP-UX v3. diff --git a/Misc/NEWS.d/next/Build/2023-02-03-21-36-42.gh-issue-101538.sF5F6S.rst b/Misc/NEWS.d/next/Build/2023-02-03-21-36-42.gh-issue-101538.sF5F6S.rst deleted file mode 100644 index 4b83c303b3d2c5..00000000000000 --- a/Misc/NEWS.d/next/Build/2023-02-03-21-36-42.gh-issue-101538.sF5F6S.rst +++ /dev/null @@ -1 +0,0 @@ -Add experimental wasi-threads support. Patch by Takashi Yamamoto. diff --git a/Misc/NEWS.d/next/Build/2023-05-20-23-49-30.gh-issue-104692.s5UIu5.rst b/Misc/NEWS.d/next/Build/2023-05-20-23-49-30.gh-issue-104692.s5UIu5.rst deleted file mode 100644 index 2936990999e1aa..00000000000000 --- a/Misc/NEWS.d/next/Build/2023-05-20-23-49-30.gh-issue-104692.s5UIu5.rst +++ /dev/null @@ -1,6 +0,0 @@ -Include ``commoninstall`` as a prerequisite for ``bininstall`` - -This ensures that ``commoninstall`` is completed before ``bininstall`` -is started when parallel builds are used (``make -j install``), and so -the ``python3`` symlink is only installed after all standard library -modules are installed. diff --git a/Misc/NEWS.d/next/Build/2023-05-26-15-44-20.gh-issue-89886._iSW-p.rst b/Misc/NEWS.d/next/Build/2023-05-26-15-44-20.gh-issue-89886._iSW-p.rst deleted file mode 100644 index 83559545e86141..00000000000000 --- a/Misc/NEWS.d/next/Build/2023-05-26-15-44-20.gh-issue-89886._iSW-p.rst +++ /dev/null @@ -1,2 +0,0 @@ -Autoconf 2.71 and aclocal 1.16.4 is now required to regenerate -:file:`!configure`. diff --git a/Misc/NEWS.d/next/Build/2023-06-02-19-12-45.gh-issue-102404.Ry9piA.rst b/Misc/NEWS.d/next/Build/2023-06-02-19-12-45.gh-issue-102404.Ry9piA.rst deleted file mode 100644 index 7fe593d77cb762..00000000000000 --- a/Misc/NEWS.d/next/Build/2023-06-02-19-12-45.gh-issue-102404.Ry9piA.rst +++ /dev/null @@ -1,2 +0,0 @@ -Document how to perform a WASI build on Linux. Also add -Tools/wasm/build_wasi.sh as a reference implementation of the docs. diff --git a/Misc/NEWS.d/next/Build/2023-06-06-09-08-10.gh-issue-90005.8mmeJQ.rst b/Misc/NEWS.d/next/Build/2023-06-06-09-08-10.gh-issue-90005.8mmeJQ.rst deleted file mode 100644 index 0a23fbf0c0fbdd..00000000000000 --- a/Misc/NEWS.d/next/Build/2023-06-06-09-08-10.gh-issue-90005.8mmeJQ.rst +++ /dev/null @@ -1 +0,0 @@ -Fix a regression in :file:`configure` where we could end up unintentionally linking with ``libbsd``. diff --git a/Misc/NEWS.d/next/Build/2023-06-16-23-40-49.gh-issue-105875.naj8v5.rst b/Misc/NEWS.d/next/Build/2023-06-16-23-40-49.gh-issue-105875.naj8v5.rst deleted file mode 100644 index 5f60e65a2f6ae8..00000000000000 --- a/Misc/NEWS.d/next/Build/2023-06-16-23-40-49.gh-issue-105875.naj8v5.rst +++ /dev/null @@ -1,2 +0,0 @@ -SQLite 3.15.2 or newer is required to build the :mod:`sqlite3` extension -module. Patch by Erlend Aasland. diff --git a/Misc/NEWS.d/next/Build/2023-06-26-21-56-29.gh-issue-106118.0cCfhl.rst b/Misc/NEWS.d/next/Build/2023-06-26-21-56-29.gh-issue-106118.0cCfhl.rst deleted file mode 100644 index f93cae5d03b539..00000000000000 --- a/Misc/NEWS.d/next/Build/2023-06-26-21-56-29.gh-issue-106118.0cCfhl.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix compilation for platforms without :data:`!O_CLOEXEC`. The issue was -introduced with Python 3.12b1 in :gh:`103295`. Patch by Erlend Aasland. diff --git a/Misc/NEWS.d/next/Build/2023-07-23-00-38-51.gh-issue-106962.VVYrWB.rst b/Misc/NEWS.d/next/Build/2023-07-23-00-38-51.gh-issue-106962.VVYrWB.rst deleted file mode 100644 index 32e196fe26d3b7..00000000000000 --- a/Misc/NEWS.d/next/Build/2023-07-23-00-38-51.gh-issue-106962.VVYrWB.rst +++ /dev/null @@ -1 +0,0 @@ -Detect MPI compilers in :file:`configure`. diff --git a/Misc/NEWS.d/next/Build/2023-07-28-18-17-33.gh-issue-106881.U3Ezdq.rst b/Misc/NEWS.d/next/Build/2023-07-28-18-17-33.gh-issue-106881.U3Ezdq.rst deleted file mode 100644 index 40b2609e95c7e9..00000000000000 --- a/Misc/NEWS.d/next/Build/2023-07-28-18-17-33.gh-issue-106881.U3Ezdq.rst +++ /dev/null @@ -1 +0,0 @@ -Check for `linux/limits.h` before including it in `Modules/posixmodule.c`. diff --git a/Misc/NEWS.d/next/Build/2023-08-01-17-12-53.gh-issue-105481.42nsDE.rst b/Misc/NEWS.d/next/Build/2023-08-01-17-12-53.gh-issue-105481.42nsDE.rst deleted file mode 100644 index 1e61c37b609469..00000000000000 --- a/Misc/NEWS.d/next/Build/2023-08-01-17-12-53.gh-issue-105481.42nsDE.rst +++ /dev/null @@ -1 +0,0 @@ -Remove the make target ``regen-opcode-targets``, merge its work into ``regen-opcode`` which repeats most of the calculation. This simplifies the code for the build and reduces code duplication. diff --git a/Misc/NEWS.d/next/Build/2023-11-27-13-55-47.gh-issue-103065.o72OiA.rst b/Misc/NEWS.d/next/Build/2023-11-27-13-55-47.gh-issue-103065.o72OiA.rst new file mode 100644 index 00000000000000..e2240b7c656a2f --- /dev/null +++ b/Misc/NEWS.d/next/Build/2023-11-27-13-55-47.gh-issue-103065.o72OiA.rst @@ -0,0 +1 @@ +Introduce ``Tools/wasm/wasi.py`` to simplify doing a WASI build. diff --git a/Misc/NEWS.d/next/Build/2023-12-08-11-33-37.gh-issue-112867.ZzDfXQ.rst b/Misc/NEWS.d/next/Build/2023-12-08-11-33-37.gh-issue-112867.ZzDfXQ.rst new file mode 100644 index 00000000000000..a36814854882bb --- /dev/null +++ b/Misc/NEWS.d/next/Build/2023-12-08-11-33-37.gh-issue-112867.ZzDfXQ.rst @@ -0,0 +1 @@ +Fix the build for the case that WITH_PYMALLOC_RADIX_TREE=0 set. diff --git a/Misc/NEWS.d/next/Build/2023-12-17-18-23-02.gh-issue-112536.8lr3Ep.rst b/Misc/NEWS.d/next/Build/2023-12-17-18-23-02.gh-issue-112536.8lr3Ep.rst new file mode 100644 index 00000000000000..a136eb47584993 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2023-12-17-18-23-02.gh-issue-112536.8lr3Ep.rst @@ -0,0 +1 @@ +Add support for thread sanitizer (TSAN) diff --git a/Misc/NEWS.d/next/Build/2023-12-21-05-35-06.gh-issue-112305.VfqQPx.rst b/Misc/NEWS.d/next/Build/2023-12-21-05-35-06.gh-issue-112305.VfqQPx.rst new file mode 100644 index 00000000000000..2df3207f4e6f6c --- /dev/null +++ b/Misc/NEWS.d/next/Build/2023-12-21-05-35-06.gh-issue-112305.VfqQPx.rst @@ -0,0 +1,3 @@ +Fixed the ``check-clean-src`` step performed on out of tree builds to detect +errant ``$(srcdir)/Python/frozen_modules/*.h`` files and recommend +appropriate source tree cleanup steps to get a working build again. diff --git a/Misc/NEWS.d/next/Build/2023-12-23-09-35-48.gh-issue-113258.GlsAyH.rst b/Misc/NEWS.d/next/Build/2023-12-23-09-35-48.gh-issue-113258.GlsAyH.rst new file mode 100644 index 00000000000000..e7256ea423b3e0 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2023-12-23-09-35-48.gh-issue-113258.GlsAyH.rst @@ -0,0 +1,2 @@ +Changed the Windows build to write out generated frozen modules into the +build tree instead of the source tree. diff --git a/Misc/NEWS.d/next/C API/2020-11-11-22-36-29.bpo-42327.ODSZBM.rst b/Misc/NEWS.d/next/C API/2020-11-11-22-36-29.bpo-42327.ODSZBM.rst deleted file mode 100644 index bcea7a1f9825b1..00000000000000 --- a/Misc/NEWS.d/next/C API/2020-11-11-22-36-29.bpo-42327.ODSZBM.rst +++ /dev/null @@ -1 +0,0 @@ -Add :c:func:`PyModule_Add` function: similar to :c:func:`PyModule_AddObjectRef` and :c:func:`PyModule_AddObject`, but always steals a reference to the value. diff --git a/Misc/NEWS.d/next/C API/2023-05-19-10-22-34.gh-issue-104668.MLX1g9.rst b/Misc/NEWS.d/next/C API/2023-05-19-10-22-34.gh-issue-104668.MLX1g9.rst deleted file mode 100644 index 7b882afd7f81a0..00000000000000 --- a/Misc/NEWS.d/next/C API/2023-05-19-10-22-34.gh-issue-104668.MLX1g9.rst +++ /dev/null @@ -1,5 +0,0 @@ -Don't call :c:var:`PyOS_InputHook` or :c:var:`PyOS_ReadlineFunctionPointer` -in subinterpreters, since it's generally difficult to avoid using global -state in their registered callbacks. This also avoids situations where -extensions may find themselves running in a subinterpreter they don't -support (or haven't yet been loaded in). diff --git a/Misc/NEWS.d/next/C API/2023-05-25-15-44-48.gh-issue-104584.cSAoRh.rst b/Misc/NEWS.d/next/C API/2023-05-25-15-44-48.gh-issue-104584.cSAoRh.rst deleted file mode 100644 index 9ce0373e8ac9d4..00000000000000 --- a/Misc/NEWS.d/next/C API/2023-05-25-15-44-48.gh-issue-104584.cSAoRh.rst +++ /dev/null @@ -1,2 +0,0 @@ -Add an unstable C API for hooking in an optimizer. This is mainly internal, -but marked "unstable" to allow third-party experimentation. diff --git a/Misc/NEWS.d/next/C API/2023-05-29-16-09-27.gh-issue-104922.L23qaU.rst b/Misc/NEWS.d/next/C API/2023-05-29-16-09-27.gh-issue-104922.L23qaU.rst deleted file mode 100644 index ca56d0b4403b8c..00000000000000 --- a/Misc/NEWS.d/next/C API/2023-05-29-16-09-27.gh-issue-104922.L23qaU.rst +++ /dev/null @@ -1,3 +0,0 @@ -``PY_SSIZE_T_CLEAN`` is no longer required to use ``'#'`` formats in APIs -like :c:func:`PyArg_ParseTuple` and :c:func:`Py_BuildValue`. They uses -``Py_ssize_t`` for ``'#'`` regardless ``PY_SSIZE_T_CLEAN``. diff --git a/Misc/NEWS.d/next/C API/2023-05-30-10-15-13.gh-issue-105071.dPtp7c.rst b/Misc/NEWS.d/next/C API/2023-05-30-10-15-13.gh-issue-105071.dPtp7c.rst deleted file mode 100644 index 3d916fcb961f62..00000000000000 --- a/Misc/NEWS.d/next/C API/2023-05-30-10-15-13.gh-issue-105071.dPtp7c.rst +++ /dev/null @@ -1 +0,0 @@ -Add ``PyUnstable_Exc_PrepReraiseStar`` to the unstable C api to expose the implementation of :keyword:`except* `. diff --git a/Misc/NEWS.d/next/C API/2023-05-30-17-45-32.gh-issue-105115.iRho1K.rst b/Misc/NEWS.d/next/C API/2023-05-30-17-45-32.gh-issue-105115.iRho1K.rst deleted file mode 100644 index 595cc0e2013d96..00000000000000 --- a/Misc/NEWS.d/next/C API/2023-05-30-17-45-32.gh-issue-105115.iRho1K.rst +++ /dev/null @@ -1,3 +0,0 @@ -``PyTypeObject.tp_bases`` (and ``tp_mro``) for builtin static types are now -shared by all interpreters, whereas in 3.12-beta1 they were stored on -``PyInterpreterState``. Also note that now the tuples are immortal objects. diff --git a/Misc/NEWS.d/next/C API/2023-05-30-19-11-09.gh-issue-105107.YQwMnm.rst b/Misc/NEWS.d/next/C API/2023-05-30-19-11-09.gh-issue-105107.YQwMnm.rst deleted file mode 100644 index 6cc758cb83962b..00000000000000 --- a/Misc/NEWS.d/next/C API/2023-05-30-19-11-09.gh-issue-105107.YQwMnm.rst +++ /dev/null @@ -1,10 +0,0 @@ -Remove functions deprecated in Python 3.9. - -* ``PyEval_CallObject()``, ``PyEval_CallObjectWithKeywords()``: use - :c:func:`PyObject_CallNoArgs` and :c:func:`PyObject_Call` (positional - arguments must not be *NULL*) instead. -* ``PyEval_CallFunction()``: use :c:func:`PyObject_CallFunction` instead. -* ``PyEval_CallMethod()``: use :c:func:`PyObject_CallMethod` instead. -* ``PyCFunction_Call()``: use :c:func:`PyObject_Call` instead. - -Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/C API/2023-05-31-16-51-18.gh-issue-105145.b3B6lJ.rst b/Misc/NEWS.d/next/C API/2023-05-31-16-51-18.gh-issue-105145.b3B6lJ.rst deleted file mode 100644 index a3ad765b696230..00000000000000 --- a/Misc/NEWS.d/next/C API/2023-05-31-16-51-18.gh-issue-105145.b3B6lJ.rst +++ /dev/null @@ -1,17 +0,0 @@ -Remove the following old functions to configure the Python initialization, -deprecated in Python 3.11: - -* ``PySys_AddWarnOptionUnicode()`` -* ``PySys_AddWarnOption()`` -* ``PySys_AddXOption()`` -* ``PySys_HasWarnOptions()`` -* ``PySys_SetArgvEx()`` -* ``PySys_SetArgv()`` -* ``PySys_SetPath()`` -* ``Py_SetPath()`` -* ``Py_SetProgramName()`` -* ``Py_SetPythonHome()`` -* ``Py_SetStandardStreamEncoding()`` -* ``_Py_SetProgramFullPath()`` - -Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/C API/2023-05-31-18-37-57.gh-issue-105156.R4El5V.rst b/Misc/NEWS.d/next/C API/2023-05-31-18-37-57.gh-issue-105156.R4El5V.rst deleted file mode 100644 index 536e484116690d..00000000000000 --- a/Misc/NEWS.d/next/C API/2023-05-31-18-37-57.gh-issue-105156.R4El5V.rst +++ /dev/null @@ -1,4 +0,0 @@ -Deprecate the old ``Py_UNICODE`` and ``PY_UNICODE_TYPE`` types: use directly -the :c:type:`wchar_t` type instead. Since Python 3.3, ``Py_UNICODE`` and -``PY_UNICODE_TYPE`` are just aliases to :c:type:`wchar_t`. Patch by Victor -Stinner. diff --git a/Misc/NEWS.d/next/C API/2023-05-31-19-38-45.gh-issue-85275.doojgE.rst b/Misc/NEWS.d/next/C API/2023-05-31-19-38-45.gh-issue-85275.doojgE.rst deleted file mode 100644 index 082b77b9035cbe..00000000000000 --- a/Misc/NEWS.d/next/C API/2023-05-31-19-38-45.gh-issue-85275.doojgE.rst +++ /dev/null @@ -1,4 +0,0 @@ -``PyObject_AsCharBuffer()``, ``PyObject_AsReadBuffer()``, -``PyObject_CheckReadBuffer()``, and ``PyObject_AsWriteBuffer()`` are -removed. Please migrate to new buffer protocol; :c:func:`PyObject_GetBuffer` -and :c:func:`PyBuffer_Release`. diff --git a/Misc/NEWS.d/next/C API/2023-06-01-09-40-30.gh-issue-105145.WOOE-w.rst b/Misc/NEWS.d/next/C API/2023-06-01-09-40-30.gh-issue-105145.WOOE-w.rst deleted file mode 100644 index 13dff769908792..00000000000000 --- a/Misc/NEWS.d/next/C API/2023-06-01-09-40-30.gh-issue-105145.WOOE-w.rst +++ /dev/null @@ -1,11 +0,0 @@ -Deprecate old Python initialization functions: - -* :c:func:`PySys_ResetWarnOptions` -* :c:func:`Py_GetExecPrefix` -* :c:func:`Py_GetPath` -* :c:func:`Py_GetPrefix` -* :c:func:`Py_GetProgramFullPath` -* :c:func:`Py_GetProgramName` -* :c:func:`Py_GetPythonHome` - -Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/C API/2023-06-01-11-23-28.gh-issue-105182.kLEHl-.rst b/Misc/NEWS.d/next/C API/2023-06-01-11-23-28.gh-issue-105182.kLEHl-.rst deleted file mode 100644 index ad9c9e51baa58b..00000000000000 --- a/Misc/NEWS.d/next/C API/2023-06-01-11-23-28.gh-issue-105182.kLEHl-.rst +++ /dev/null @@ -1,2 +0,0 @@ -Remove ``PyEval_InitThreads()`` and ``PyEval_ThreadsInitialized()`` -functions, deprecated in Python 3.9. Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/C API/2023-06-01-11-24-03.gh-issue-105182.l5sCw4.rst b/Misc/NEWS.d/next/C API/2023-06-01-11-24-03.gh-issue-105182.l5sCw4.rst deleted file mode 100644 index 0fe5487c3e2181..00000000000000 --- a/Misc/NEWS.d/next/C API/2023-06-01-11-24-03.gh-issue-105182.l5sCw4.rst +++ /dev/null @@ -1,2 +0,0 @@ -Remove ``PyEval_AcquireLock()`` and ``PyEval_ReleaseLock()`` functions, -deprecated in Python 3.2. Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/C API/2023-06-06-10-57-18.gh-issue-105268.OTJUko.rst b/Misc/NEWS.d/next/C API/2023-06-06-10-57-18.gh-issue-105268.OTJUko.rst deleted file mode 100644 index bdabfc8c203f6e..00000000000000 --- a/Misc/NEWS.d/next/C API/2023-06-06-10-57-18.gh-issue-105268.OTJUko.rst +++ /dev/null @@ -1,3 +0,0 @@ -Remove the old private, undocumented and untested ``_PyGC_FINALIZED()`` macro -which was kept for backward compatibility with Python 3.8 and older. Patch by -Victor Stinner. diff --git a/Misc/NEWS.d/next/C API/2023-06-06-14-14-41.gh-issue-103968.BTO6II.rst b/Misc/NEWS.d/next/C API/2023-06-06-14-14-41.gh-issue-103968.BTO6II.rst deleted file mode 100644 index b73103c4e0ad9e..00000000000000 --- a/Misc/NEWS.d/next/C API/2023-06-06-14-14-41.gh-issue-103968.BTO6II.rst +++ /dev/null @@ -1,2 +0,0 @@ -:c:func:`PyType_FromMetaclass` now allows metaclasses with ``tp_new`` -set to ``NULL``. diff --git a/Misc/NEWS.d/next/C API/2023-06-06-17-43-28.gh-issue-105396.FQJG5B.rst b/Misc/NEWS.d/next/C API/2023-06-06-17-43-28.gh-issue-105396.FQJG5B.rst deleted file mode 100644 index cf82f6202df17b..00000000000000 --- a/Misc/NEWS.d/next/C API/2023-06-06-17-43-28.gh-issue-105396.FQJG5B.rst +++ /dev/null @@ -1,3 +0,0 @@ -Deprecate the :c:func:`PyImport_ImportModuleNoBlock` function which is just -an alias to :c:func:`PyImport_ImportModule` since Python 3.3. Patch by -Victor Stinner. diff --git a/Misc/NEWS.d/next/C API/2023-06-09-12-35-55.gh-issue-105387.wM_oL-.rst b/Misc/NEWS.d/next/C API/2023-06-09-12-35-55.gh-issue-105387.wM_oL-.rst deleted file mode 100644 index d7ee7d2eb9d908..00000000000000 --- a/Misc/NEWS.d/next/C API/2023-06-09-12-35-55.gh-issue-105387.wM_oL-.rst +++ /dev/null @@ -1,3 +0,0 @@ -In the limited C API version 3.12, :c:func:`Py_INCREF` and -:c:func:`Py_DECREF` functions are now implemented as opaque function calls -to hide implementation details. Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/C API/2023-06-09-19-16-57.gh-issue-105603.-z6G22.rst b/Misc/NEWS.d/next/C API/2023-06-09-19-16-57.gh-issue-105603.-z6G22.rst deleted file mode 100644 index cd3d9bcdd4e285..00000000000000 --- a/Misc/NEWS.d/next/C API/2023-06-09-19-16-57.gh-issue-105603.-z6G22.rst +++ /dev/null @@ -1,5 +0,0 @@ -We've renamed the new (in 3.12) ``PyInterpreterConfig.own_gil`` to -``PyInterpreterConfig.gil`` and changed the meaning of the value from "bool" -to an integer with supported values of ``PyInterpreterConfig_DEFAULT_GIL``, -``PyInterpreterConfig_SHARED_GIL``, and ``PyInterpreterConfig_OWN_GIL``. The -default is "shared". diff --git a/Misc/NEWS.d/next/C API/2023-06-09-23-34-25.gh-issue-105375.n7amiF.rst b/Misc/NEWS.d/next/C API/2023-06-09-23-34-25.gh-issue-105375.n7amiF.rst deleted file mode 100644 index b9f95496f938ec..00000000000000 --- a/Misc/NEWS.d/next/C API/2023-06-09-23-34-25.gh-issue-105375.n7amiF.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix a bug in :c:func:`PyErr_WarnExplicit` where an exception could end up -being overwritten if the API failed internally. diff --git a/Misc/NEWS.d/next/C API/2023-06-13-14-24-55.gh-issue-105227.HDL9aF.rst b/Misc/NEWS.d/next/C API/2023-06-13-14-24-55.gh-issue-105227.HDL9aF.rst deleted file mode 100644 index 846663621e8689..00000000000000 --- a/Misc/NEWS.d/next/C API/2023-06-13-14-24-55.gh-issue-105227.HDL9aF.rst +++ /dev/null @@ -1,5 +0,0 @@ -The new :c:func:`PyType_GetDict` provides the dictionary for the given type -object that is normally exposed by ``cls.__dict__``. Normally it's -sufficient to use :c:member:`~PyTypeObject.tp_dict`, but for the static -builtin types :c:member:`!tp_dict` is now always ``NULL``. :c:func:`!PyType_GetDict()` -provides the correct dict object instead. diff --git a/Misc/NEWS.d/next/C API/2023-06-19-20-02-16.gh-issue-105922.o4T6wO.rst b/Misc/NEWS.d/next/C API/2023-06-19-20-02-16.gh-issue-105922.o4T6wO.rst deleted file mode 100644 index 7515d684184e17..00000000000000 --- a/Misc/NEWS.d/next/C API/2023-06-19-20-02-16.gh-issue-105922.o4T6wO.rst +++ /dev/null @@ -1,3 +0,0 @@ -Add :c:func:`PyImport_AddModuleRef`: similar to :c:func:`PyImport_AddModule`, -but return a :term:`strong reference` instead of a :term:`borrowed reference`. -Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/C API/2023-06-20-08-59-05.gh-issue-105927.DfGeEA.rst b/Misc/NEWS.d/next/C API/2023-06-20-08-59-05.gh-issue-105927.DfGeEA.rst deleted file mode 100644 index afa40c8ef5d686..00000000000000 --- a/Misc/NEWS.d/next/C API/2023-06-20-08-59-05.gh-issue-105927.DfGeEA.rst +++ /dev/null @@ -1,3 +0,0 @@ -Add :c:func:`PyWeakref_GetRef` function: similar to -:c:func:`PyWeakref_GetObject` but returns a :term:`strong reference`, or -``NULL`` if the referent is no longer live. Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/C API/2023-06-21-11-53-09.gh-issue-65210.PhFRBJ.rst b/Misc/NEWS.d/next/C API/2023-06-21-11-53-09.gh-issue-65210.PhFRBJ.rst new file mode 100644 index 00000000000000..a15646f4dad127 --- /dev/null +++ b/Misc/NEWS.d/next/C API/2023-06-21-11-53-09.gh-issue-65210.PhFRBJ.rst @@ -0,0 +1,3 @@ +Change the declaration of the *keywords* parameter of +:c:func:`PyArg_ParseTupleAndKeywords` and +:c:func:`PyArg_VaParseTupleAndKeywords` for better compatibility with C++. diff --git a/Misc/NEWS.d/next/C API/2023-06-22-00-25-55.gh-issue-105927.GRxZtI.rst b/Misc/NEWS.d/next/C API/2023-06-22-00-25-55.gh-issue-105927.GRxZtI.rst deleted file mode 100644 index 57982dc75e004a..00000000000000 --- a/Misc/NEWS.d/next/C API/2023-06-22-00-25-55.gh-issue-105927.GRxZtI.rst +++ /dev/null @@ -1,3 +0,0 @@ -Deprecate the :c:func:`PyWeakref_GetObject` and -:c:func:`PyWeakref_GET_OBJECT` functions: use the new -:c:func:`PyWeakref_GetRef` function instead. Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/C API/2023-06-23-02-57-15.gh-issue-106004.-OToh6.rst b/Misc/NEWS.d/next/C API/2023-06-23-02-57-15.gh-issue-106004.-OToh6.rst deleted file mode 100644 index c7a006b2bc0759..00000000000000 --- a/Misc/NEWS.d/next/C API/2023-06-23-02-57-15.gh-issue-106004.-OToh6.rst +++ /dev/null @@ -1,4 +0,0 @@ -Adds :c:func:`PyDict_GetItemRef` and :c:func:`PyDict_GetItemStringRef` -functions: similar to :c:func:`PyDict_GetItemWithError` but returning a -:term:`strong reference` instead of a :term:`borrowed reference`. Patch by -Victor Stinner. diff --git a/Misc/NEWS.d/next/C API/2023-06-25-18-01-27.gh-issue-106084.PEzqU3.rst b/Misc/NEWS.d/next/C API/2023-06-25-18-01-27.gh-issue-106084.PEzqU3.rst deleted file mode 100644 index b430f5f7ae0116..00000000000000 --- a/Misc/NEWS.d/next/C API/2023-06-25-18-01-27.gh-issue-106084.PEzqU3.rst +++ /dev/null @@ -1,13 +0,0 @@ -Remove the old aliases to functions calling functions which were kept for -backward compatibility with Python 3.8 provisional API: - -* ``_PyObject_CallMethodNoArgs()``: use ``PyObject_CallMethodNoArgs()`` -* ``_PyObject_CallMethodOneArg()``: use ``PyObject_CallMethodOneArg()`` -* ``_PyObject_CallOneArg()``: use ``PyObject_CallOneArg()`` -* ``_PyObject_FastCallDict()``: use ``PyObject_VectorcallDict()`` -* ``_PyObject_Vectorcall()``: use ``PyObject_Vectorcall()`` -* ``_PyObject_VectorcallMethod()``: use ``PyObject_VectorcallMethod()`` -* ``_PyVectorcall_Function()``: use ``PyVectorcall_Function()`` - -Just remove the underscore prefix to update your code. Patch by Victor -Stinner. diff --git a/Misc/NEWS.d/next/C API/2023-06-28-02-30-50.gh-issue-106168.NFOZPv.rst b/Misc/NEWS.d/next/C API/2023-06-28-02-30-50.gh-issue-106168.NFOZPv.rst deleted file mode 100644 index 741d709bf824b8..00000000000000 --- a/Misc/NEWS.d/next/C API/2023-06-28-02-30-50.gh-issue-106168.NFOZPv.rst +++ /dev/null @@ -1,5 +0,0 @@ -If Python is built in :ref:`debug mode ` or :option:`with -assertions <--with-assertions>`, :c:func:`PyTuple_SET_ITEM` and -:c:func:`PyList_SET_ITEM` now check the index argument with an assertion. If -the assertion fails, make sure that the size is set before. Patch by Victor -Stinner. diff --git a/Misc/NEWS.d/next/C API/2023-06-30-09-33-25.gh-issue-106023.YvYiE4.rst b/Misc/NEWS.d/next/C API/2023-06-30-09-33-25.gh-issue-106023.YvYiE4.rst deleted file mode 100644 index 3130febf61120b..00000000000000 --- a/Misc/NEWS.d/next/C API/2023-06-30-09-33-25.gh-issue-106023.YvYiE4.rst +++ /dev/null @@ -1,2 +0,0 @@ -Remove private ``_PyObject_FastCall()`` function: use ``PyObject_Vectorcall()`` -which is available since Python 3.8 (:pep:`590`). Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/C API/2023-07-01-21-23-33.gh-issue-106316.hp2Ijw.rst b/Misc/NEWS.d/next/C API/2023-07-01-21-23-33.gh-issue-106316.hp2Ijw.rst deleted file mode 100644 index 733954eb8614f2..00000000000000 --- a/Misc/NEWS.d/next/C API/2023-07-01-21-23-33.gh-issue-106316.hp2Ijw.rst +++ /dev/null @@ -1,2 +0,0 @@ -Remove ``cpython/pytime.h`` header file: it only contained private -functions. Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/C API/2023-07-02-00-00-20.gh-issue-106320.tZWcvG.rst b/Misc/NEWS.d/next/C API/2023-07-02-00-00-20.gh-issue-106320.tZWcvG.rst deleted file mode 100644 index 145d2ce7b0ceb1..00000000000000 --- a/Misc/NEWS.d/next/C API/2023-07-02-00-00-20.gh-issue-106320.tZWcvG.rst +++ /dev/null @@ -1,3 +0,0 @@ -Remove ``_PyInterpreterState_Get()`` alias to -:c:func:`PyInterpreterState_Get()` which was kept for backward compatibility -with Python 3.8. Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/C API/2023-07-07-19-14-00.gh-issue-106521.Veh9f3.rst b/Misc/NEWS.d/next/C API/2023-07-07-19-14-00.gh-issue-106521.Veh9f3.rst deleted file mode 100644 index f38fd271e8a440..00000000000000 --- a/Misc/NEWS.d/next/C API/2023-07-07-19-14-00.gh-issue-106521.Veh9f3.rst +++ /dev/null @@ -1 +0,0 @@ -Add :c:func:`PyObject_GetOptionalAttr` and :c:func:`PyObject_GetOptionalAttrString` functions. diff --git a/Misc/NEWS.d/next/C API/2023-07-08-12-24-17.gh-issue-106307.FVnkBw.rst b/Misc/NEWS.d/next/C API/2023-07-08-12-24-17.gh-issue-106307.FVnkBw.rst deleted file mode 100644 index dc1ab8d3e3fb83..00000000000000 --- a/Misc/NEWS.d/next/C API/2023-07-08-12-24-17.gh-issue-106307.FVnkBw.rst +++ /dev/null @@ -1 +0,0 @@ -Add :c:func:`PyMapping_GetOptionalItem` function. diff --git a/Misc/NEWS.d/next/C API/2023-07-11-01-07-39.gh-issue-106572.y1b35X.rst b/Misc/NEWS.d/next/C API/2023-07-11-01-07-39.gh-issue-106572.y1b35X.rst deleted file mode 100644 index 140e9fe7b9abf6..00000000000000 --- a/Misc/NEWS.d/next/C API/2023-07-11-01-07-39.gh-issue-106572.y1b35X.rst +++ /dev/null @@ -1,2 +0,0 @@ -Convert :c:func:`PyObject_DelAttr` and :c:func:`PyObject_DelAttrString` -macros to functions. Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/C API/2023-07-22-14-40-48.gh-issue-106320.H3u7x4.rst b/Misc/NEWS.d/next/C API/2023-07-22-14-40-48.gh-issue-106320.H3u7x4.rst deleted file mode 100644 index 1e0ba0d71e7555..00000000000000 --- a/Misc/NEWS.d/next/C API/2023-07-22-14-40-48.gh-issue-106320.H3u7x4.rst +++ /dev/null @@ -1,5 +0,0 @@ -Remove private ``_PyUnicode_AsString()`` alias to -:c:func:`PyUnicode_AsUTF8`. It was kept for backward compatibility with -Python 3.0 - 3.2. The :c:func:`PyUnicode_AsUTF8` is available since Python -3.3. The :c:func:`PyUnicode_AsUTF8String` function can be used to keep -compatibility with Python 3.2 and older. Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/C API/2023-07-25-13-41-09.gh-issue-107226.N919zH.rst b/Misc/NEWS.d/next/C API/2023-07-25-13-41-09.gh-issue-107226.N919zH.rst deleted file mode 100644 index 6178f18517d48f..00000000000000 --- a/Misc/NEWS.d/next/C API/2023-07-25-13-41-09.gh-issue-107226.N919zH.rst +++ /dev/null @@ -1,2 +0,0 @@ -:c:func:`PyModule_AddObjectRef` is now only available in the limited API -version 3.10 or later. diff --git a/Misc/NEWS.d/next/C API/2023-07-25-17-23-08.gh-issue-107249.xqk2ke.rst b/Misc/NEWS.d/next/C API/2023-07-25-17-23-08.gh-issue-107249.xqk2ke.rst deleted file mode 100644 index a7139024329fae..00000000000000 --- a/Misc/NEWS.d/next/C API/2023-07-25-17-23-08.gh-issue-107249.xqk2ke.rst +++ /dev/null @@ -1,2 +0,0 @@ -Implement the :c:macro:`Py_UNUSED` macro for Windows MSVC compiler. Patch by -Victor Stinner. diff --git a/Misc/NEWS.d/next/C API/2023-11-15-01-26-59.gh-issue-111545.iAoFtA.rst b/Misc/NEWS.d/next/C API/2023-11-15-01-26-59.gh-issue-111545.iAoFtA.rst new file mode 100644 index 00000000000000..7bde2498acf999 --- /dev/null +++ b/Misc/NEWS.d/next/C API/2023-11-15-01-26-59.gh-issue-111545.iAoFtA.rst @@ -0,0 +1,2 @@ +Add :c:func:`Py_HashPointer` function to hash a pointer. Patch by Victor +Stinner. diff --git a/Misc/NEWS.d/next/C API/2023-11-27-09-44-16.gh-issue-112438.GdNZiI.rst b/Misc/NEWS.d/next/C API/2023-11-27-09-44-16.gh-issue-112438.GdNZiI.rst new file mode 100644 index 00000000000000..113119efd6aebb --- /dev/null +++ b/Misc/NEWS.d/next/C API/2023-11-27-09-44-16.gh-issue-112438.GdNZiI.rst @@ -0,0 +1,2 @@ +Fix support of format units "es", "et", "es#", and "et#" in nested tuples in +:c:func:`PyArg_ParseTuple`-like functions. diff --git a/Misc/NEWS.d/next/C API/2023-12-02-02-08-11.gh-issue-106560.THvuji.rst b/Misc/NEWS.d/next/C API/2023-12-02-02-08-11.gh-issue-106560.THvuji.rst new file mode 100644 index 00000000000000..59b461ec47ad64 --- /dev/null +++ b/Misc/NEWS.d/next/C API/2023-12-02-02-08-11.gh-issue-106560.THvuji.rst @@ -0,0 +1,2 @@ +Fix redundant declarations in the public C API. Declare PyBool_Type, +PyLong_Type and PySys_Audit() only once. Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/Core and Builtins/2018-08-13-13-25-15.bpo-34392.9kIlMF.rst b/Misc/NEWS.d/next/Core and Builtins/2018-08-13-13-25-15.bpo-34392.9kIlMF.rst new file mode 100644 index 00000000000000..bc4fd1ad1f5c7c --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2018-08-13-13-25-15.bpo-34392.9kIlMF.rst @@ -0,0 +1 @@ +Added :func:`sys._is_interned`. diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-10-05-05-00-16.bpo-45369.tluk_X.rst b/Misc/NEWS.d/next/Core and Builtins/2021-10-05-05-00-16.bpo-45369.tluk_X.rst new file mode 100644 index 00000000000000..114f7457a4c7e9 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-10-05-05-00-16.bpo-45369.tluk_X.rst @@ -0,0 +1 @@ +Remove LibreSSL workarounds as per :pep:`644`. diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-01-23-18-00-10.bpo-21861.N8E1zw.rst b/Misc/NEWS.d/next/Core and Builtins/2022-01-23-18-00-10.bpo-21861.N8E1zw.rst new file mode 100644 index 00000000000000..5d99845912caf3 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2022-01-23-18-00-10.bpo-21861.N8E1zw.rst @@ -0,0 +1,3 @@ +Use the object's actual class name in :meth:`_io.FileIO.__repr__`, +:meth:`_io._WindowsConsoleIO` and :meth:`_io.TextIOWrapper.__repr__`, to +make these methods subclass friendly. diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-07-07-05-37-53.gh-issue-94606.hojJ54.rst b/Misc/NEWS.d/next/Core and Builtins/2022-07-07-05-37-53.gh-issue-94606.hojJ54.rst new file mode 100644 index 00000000000000..5201ab7d842088 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2022-07-07-05-37-53.gh-issue-94606.hojJ54.rst @@ -0,0 +1,3 @@ +Fix UnicodeEncodeError when :func:`email.message.get_payload` reads a message +with a Unicode surrogate character and the message content is not well-formed for +surrogateescape encoding. Patch by Sidney Markowitz. diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-11-10-13-04-35.gh-issue-91095.4E3Pwn.rst b/Misc/NEWS.d/next/Core and Builtins/2022-11-10-13-04-35.gh-issue-91095.4E3Pwn.rst deleted file mode 100644 index 5633097f4a3fdd..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2022-11-10-13-04-35.gh-issue-91095.4E3Pwn.rst +++ /dev/null @@ -1,11 +0,0 @@ -Specializes calls to most Python classes. Specifically, any class that -inherits from ``object``, or another Python class, and does not override -``__new__``. - -The specialized instruction does the following: - -1. Creates the object (by calling ``object.__new__``) -2. Pushes a shim frame to the frame stack (to cleanup after ``__init__``) -3. Pushes the frame for ``__init__`` to the frame stack - -Speeds up the instantiation of most Python classes. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-01-13-11-37-41.gh-issue-101006.fuLvn2.rst b/Misc/NEWS.d/next/Core and Builtins/2023-01-13-11-37-41.gh-issue-101006.fuLvn2.rst deleted file mode 100644 index c98670d8c4963d..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-01-13-11-37-41.gh-issue-101006.fuLvn2.rst +++ /dev/null @@ -1 +0,0 @@ -Improve error handling when read :mod:`marshal` data. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-04-04-00-40-04.gh-issue-96663.PdR9hK.rst b/Misc/NEWS.d/next/Core and Builtins/2023-04-04-00-40-04.gh-issue-96663.PdR9hK.rst deleted file mode 100644 index cb806b5ea7a9f3..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-04-04-00-40-04.gh-issue-96663.PdR9hK.rst +++ /dev/null @@ -1 +0,0 @@ -Add a better, more introspect-able error message when setting attributes on classes without a ``__dict__`` and no slot member for the attribute. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-05-18-12-48-39.gh-issue-89091.FDzRcW.rst b/Misc/NEWS.d/next/Core and Builtins/2023-05-18-12-48-39.gh-issue-89091.FDzRcW.rst deleted file mode 100644 index 084ea708997ef3..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-05-18-12-48-39.gh-issue-89091.FDzRcW.rst +++ /dev/null @@ -1 +0,0 @@ -Raise :exc:`RuntimeWarning` for unawaited async generator methods like :meth:`~agen.asend`, :meth:`~agen.athrow` and :meth:`~agen.aclose`. Patch by Kumar Aditya. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-05-23-00-36-02.gh-issue-104770.poSkyY.rst b/Misc/NEWS.d/next/Core and Builtins/2023-05-23-00-36-02.gh-issue-104770.poSkyY.rst deleted file mode 100644 index 2103fb7d61c21a..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-05-23-00-36-02.gh-issue-104770.poSkyY.rst +++ /dev/null @@ -1,2 +0,0 @@ -If a generator returns a value upon being closed, the value is now returned -by :meth:`generator.close`. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-05-24-09-59-56.gh-issue-104825.mQesie.rst b/Misc/NEWS.d/next/Core and Builtins/2023-05-24-09-59-56.gh-issue-104825.mQesie.rst deleted file mode 100644 index caf5d3527085f3..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-05-24-09-59-56.gh-issue-104825.mQesie.rst +++ /dev/null @@ -1,2 +0,0 @@ -Tokens emitted by the :mod:`tokenize` module do not include an implicit -``\n`` character in the ``line`` attribute anymore. Patch by Pablo Galindo diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-05-24-10-19-35.gh-issue-104879.v-29NL.rst b/Misc/NEWS.d/next/Core and Builtins/2023-05-24-10-19-35.gh-issue-104879.v-29NL.rst deleted file mode 100644 index 235f4180642be6..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-05-24-10-19-35.gh-issue-104879.v-29NL.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix crash when accessing the ``__module__`` attribute of type aliases -defined outside a module. Patch by Jelle Zijlstra. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-05-24-12-10-54.gh-issue-104690.HX3Jou.rst b/Misc/NEWS.d/next/Core and Builtins/2023-05-24-12-10-54.gh-issue-104690.HX3Jou.rst deleted file mode 100644 index 7934dd23b10691..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-05-24-12-10-54.gh-issue-104690.HX3Jou.rst +++ /dev/null @@ -1,6 +0,0 @@ -Starting new threads and process creation through :func:`os.fork` during interpreter -shutdown (such as from :mod:`atexit` handlers) is no longer supported. It can lead -to race condition between the main Python runtime thread freeing thread states while -internal :mod:`threading` routines are trying to allocate and use the state of just -created threads. Or forked children trying to use the mid-shutdown runtime and thread -state in the child process. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-05-25-21-40-39.gh-issue-104955.LZx7jf.rst b/Misc/NEWS.d/next/Core and Builtins/2023-05-25-21-40-39.gh-issue-104955.LZx7jf.rst deleted file mode 100644 index 9fccf2a41ffb6f..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-05-25-21-40-39.gh-issue-104955.LZx7jf.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix signature for the new :meth:`~object.__release_buffer__` slot. Patch by Jelle -Zijlstra. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-05-26-14-09-47.gh-issue-104972.El2UjE.rst b/Misc/NEWS.d/next/Core and Builtins/2023-05-26-14-09-47.gh-issue-104972.El2UjE.rst deleted file mode 100644 index 05d50c108c7b77..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-05-26-14-09-47.gh-issue-104972.El2UjE.rst +++ /dev/null @@ -1,2 +0,0 @@ -Ensure that the ``line`` attribute in :class:`tokenize.TokenInfo` objects in -the :mod:`tokenize` module are always correct. Patch by Pablo Galindo diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-05-26-15-16-11.gh-issue-104976.6dLitD.rst b/Misc/NEWS.d/next/Core and Builtins/2023-05-26-15-16-11.gh-issue-104976.6dLitD.rst deleted file mode 100644 index 377e8e76362687..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-05-26-15-16-11.gh-issue-104976.6dLitD.rst +++ /dev/null @@ -1,3 +0,0 @@ -Ensure that trailing ``DEDENT`` :class:`tokenize.TokenInfo` objects emitted -by the :mod:`tokenize` module are reported as in Python 3.11. Patch by Pablo -Galindo diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-05-27-16-23-16.gh-issue-105017.KQrsC0.rst b/Misc/NEWS.d/next/Core and Builtins/2023-05-27-16-23-16.gh-issue-105017.KQrsC0.rst deleted file mode 100644 index d41a2169ccb3de..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-05-27-16-23-16.gh-issue-105017.KQrsC0.rst +++ /dev/null @@ -1 +0,0 @@ -Do not include an additional final ``NL`` token when parsing files having CRLF lines. Patch by Marta Gómez. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-05-27-16-57-11.gh-issue-105013.IsDgDY.rst b/Misc/NEWS.d/next/Core and Builtins/2023-05-27-16-57-11.gh-issue-105013.IsDgDY.rst deleted file mode 100644 index a9917c2849982a..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-05-27-16-57-11.gh-issue-105013.IsDgDY.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix handling of multiline parenthesized lambdas in -:func:`inspect.getsource`. Patch by Pablo Galindo diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-05-27-21-50-48.gh-issue-105017.4sDyDV.rst b/Misc/NEWS.d/next/Core and Builtins/2023-05-27-21-50-48.gh-issue-105017.4sDyDV.rst deleted file mode 100644 index 02d653c2d658eb..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-05-27-21-50-48.gh-issue-105017.4sDyDV.rst +++ /dev/null @@ -1 +0,0 @@ -Show CRLF lines in the tokenize string attribute in both NL and NEWLINE tokens. Patch by Marta Gómez. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-05-30-08-09-43.gh-issue-105035.OWUlHy.rst b/Misc/NEWS.d/next/Core and Builtins/2023-05-30-08-09-43.gh-issue-105035.OWUlHy.rst deleted file mode 100644 index dbfcd658d945d4..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-05-30-08-09-43.gh-issue-105035.OWUlHy.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix :func:`super` calls on types with custom :c:member:`~PyTypeObject.tp_getattro` -implementation (e.g. meta-types.) diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-05-30-20-30-57.gh-issue-105111.atn0_6.rst b/Misc/NEWS.d/next/Core and Builtins/2023-05-30-20-30-57.gh-issue-105111.atn0_6.rst deleted file mode 100644 index 7f9c5cc95680d8..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-05-30-20-30-57.gh-issue-105111.atn0_6.rst +++ /dev/null @@ -1,3 +0,0 @@ -Remove the old trashcan macros -``Py_TRASHCAN_SAFE_BEGIN`` and ``Py_TRASHCAN_SAFE_END``. They should be -replaced by the new macros ``Py_TRASHCAN_BEGIN`` and ``Py_TRASHCAN_END``. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-05-31-08-10-59.gh-issue-104799.8kDWti.rst b/Misc/NEWS.d/next/Core and Builtins/2023-05-31-08-10-59.gh-issue-104799.8kDWti.rst deleted file mode 100644 index e1fe47f862529c..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-05-31-08-10-59.gh-issue-104799.8kDWti.rst +++ /dev/null @@ -1,4 +0,0 @@ -Attributes of :mod:`ast` nodes that are lists now default to the empty list -if omitted. This means that some code that previously raised -:exc:`TypeError` when the AST node was used will now proceed with the empty -list instead. Patch by Jelle Zijlstra. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-05-31-16-22-29.gh-issue-105148.MOlb1d.rst b/Misc/NEWS.d/next/Core and Builtins/2023-05-31-16-22-29.gh-issue-105148.MOlb1d.rst deleted file mode 100644 index 4dcdcdfd4287d7..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-05-31-16-22-29.gh-issue-105148.MOlb1d.rst +++ /dev/null @@ -1,3 +0,0 @@ -Make ``_PyASTOptimizeState`` internal to ast_opt.c. Make ``_PyAST_Optimize`` -take two integers instead of a pointer to this struct. This avoids the need -to include pycore_compile.h in ast_opt.c. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-05-31-19-35-22.gh-issue-105164.6Wajph.rst b/Misc/NEWS.d/next/Core and Builtins/2023-05-31-19-35-22.gh-issue-105164.6Wajph.rst deleted file mode 100644 index 7d3486c3b6e98a..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-05-31-19-35-22.gh-issue-105164.6Wajph.rst +++ /dev/null @@ -1,2 +0,0 @@ -Ensure annotations are set up correctly if the only annotation in a block is -within a :keyword:`match` block. Patch by Jelle Zijlstra. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-06-01-11-37-03.gh-issue-105162.r8VCXk.rst b/Misc/NEWS.d/next/Core and Builtins/2023-06-01-11-37-03.gh-issue-105162.r8VCXk.rst deleted file mode 100644 index adb4e8478d9c55..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-06-01-11-37-03.gh-issue-105162.r8VCXk.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fixed bug in generator.close()/throw() where an inner iterator would be -ignored when the outer iterator was instrumented. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-06-02-01-27-35.gh-issue-105229.U05x4G.rst b/Misc/NEWS.d/next/Core and Builtins/2023-06-02-01-27-35.gh-issue-105229.U05x4G.rst deleted file mode 100644 index df0c54691afb11..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-06-02-01-27-35.gh-issue-105229.U05x4G.rst +++ /dev/null @@ -1 +0,0 @@ -Replace some dynamic superinstructions with single instruction equivalents. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-06-02-11-37-12.gh-issue-105194.4eu56B.rst b/Misc/NEWS.d/next/Core and Builtins/2023-06-02-11-37-12.gh-issue-105194.4eu56B.rst deleted file mode 100644 index adee74f5894b54..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-06-02-11-37-12.gh-issue-105194.4eu56B.rst +++ /dev/null @@ -1,2 +0,0 @@ -Do not escape with backslashes f-string format specifiers. Patch by Pablo -Galindo diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-06-02-15-15-41.gh-issue-104812.dfZiG5.rst b/Misc/NEWS.d/next/Core and Builtins/2023-06-02-15-15-41.gh-issue-104812.dfZiG5.rst deleted file mode 100644 index da29a8cae61839..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-06-02-15-15-41.gh-issue-104812.dfZiG5.rst +++ /dev/null @@ -1,9 +0,0 @@ -The "pending call" machinery now works for all interpreters, not just the -main interpreter, and runs in all threads, not just the main thread. Some -calls are still only done in the main thread, ergo in the main interpreter. -This change does not affect signal handling nor the existing public C-API -(``Py_AddPendingCall()``), which both still only target the main thread. -The new functionality is meant strictly for internal use for now, since -consequences of its use are not well understood yet outside some very -restricted cases. This change brings the capability in line with the -intention when the state was made per-interpreter several years ago. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-06-02-17-39-19.gh-issue-98963.J4wJgk.rst b/Misc/NEWS.d/next/Core and Builtins/2023-06-02-17-39-19.gh-issue-98963.J4wJgk.rst deleted file mode 100644 index 4caadb0875a188..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-06-02-17-39-19.gh-issue-98963.J4wJgk.rst +++ /dev/null @@ -1,4 +0,0 @@ -Restore the ability for a subclass of :class:`property` to define ``__slots__`` -or otherwise be dict-less by ignoring failures to set a docstring on such a -class. This behavior had regressed in 3.12beta1. An :exc:`AttributeError` -where there had not previously been one was disruptive to existing code. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-06-02-19-37-29.gh-issue-105235.fgFGTi.rst b/Misc/NEWS.d/next/Core and Builtins/2023-06-02-19-37-29.gh-issue-105235.fgFGTi.rst deleted file mode 100644 index c28d0101cd4bad..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-06-02-19-37-29.gh-issue-105235.fgFGTi.rst +++ /dev/null @@ -1 +0,0 @@ -Prevent out-of-bounds memory access during ``mmap.find()`` calls. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-06-03-04-28-28.gh-issue-105229.stEmfp.rst b/Misc/NEWS.d/next/Core and Builtins/2023-06-03-04-28-28.gh-issue-105229.stEmfp.rst deleted file mode 100644 index 34fad1d4bc34d8..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-06-03-04-28-28.gh-issue-105229.stEmfp.rst +++ /dev/null @@ -1,3 +0,0 @@ -Remove remaining two-codeunit superinstructions. All remaining -superinstructions only take a single codeunit, simplifying instrumentation -and quickening. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-06-05-08-30-49.gh-issue-33092.hZ0xSI.rst b/Misc/NEWS.d/next/Core and Builtins/2023-06-05-08-30-49.gh-issue-33092.hZ0xSI.rst deleted file mode 100644 index 736fbac1a86500..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-06-05-08-30-49.gh-issue-33092.hZ0xSI.rst +++ /dev/null @@ -1,3 +0,0 @@ -Simplify and speed up interpreter for f-strings. Removes ``FORMAT_VALUE`` -opcode. Add ``CONVERT_VALUE``, ``FORMAT_SIMPLE`` and ``FORMAT_WITH_SPEC`` -opcode. Compiler emits more efficient sequence for each format expression. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-06-05-17-35-50.gh-issue-105324.BqhiJJ.rst b/Misc/NEWS.d/next/Core and Builtins/2023-06-05-17-35-50.gh-issue-105324.BqhiJJ.rst deleted file mode 100644 index 17275aed338d0d..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-06-05-17-35-50.gh-issue-105324.BqhiJJ.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix the main function of the :mod:`tokenize` module when reading from -``sys.stdin``. Patch by Pablo Galindo diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-06-05-23-38-43.gh-issue-104635.VYZhVh.rst b/Misc/NEWS.d/next/Core and Builtins/2023-06-05-23-38-43.gh-issue-104635.VYZhVh.rst deleted file mode 100644 index f20ddb56d171c3..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-06-05-23-38-43.gh-issue-104635.VYZhVh.rst +++ /dev/null @@ -1,2 +0,0 @@ -Eliminate redundant :opcode:`STORE_FAST` instructions in the compiler. Patch -by Dong-hee Na and Carl Meyer. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-06-06-11-37-53.gh-issue-105259.E2BGKL.rst b/Misc/NEWS.d/next/Core and Builtins/2023-06-06-11-37-53.gh-issue-105259.E2BGKL.rst deleted file mode 100644 index 75a63033750826..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-06-06-11-37-53.gh-issue-105259.E2BGKL.rst +++ /dev/null @@ -1,2 +0,0 @@ -Don't include newline character for trailing ``NEWLINE`` tokens emitted in -the :mod:`tokenize` module. Patch by Pablo Galindo diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-06-06-17-10-42.gh-issue-105390.DvqI-e.rst b/Misc/NEWS.d/next/Core and Builtins/2023-06-06-17-10-42.gh-issue-105390.DvqI-e.rst deleted file mode 100644 index de59b54d8f6053..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-06-06-17-10-42.gh-issue-105390.DvqI-e.rst +++ /dev/null @@ -1,3 +0,0 @@ -Correctly raise :exc:`tokenize.TokenError` exceptions instead of -:exc:`SyntaxError` for tokenize errors such as incomplete input. Patch by -Pablo Galindo diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-06-07-12-20-59.gh-issue-105435.6VllI0.rst b/Misc/NEWS.d/next/Core and Builtins/2023-06-07-12-20-59.gh-issue-105435.6VllI0.rst deleted file mode 100644 index 9e4d7e1851ccb5..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-06-07-12-20-59.gh-issue-105435.6VllI0.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix spurious newline character if file ends on a comment without a newline. -Patch by Pablo Galindo diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-06-07-21-27-55.gh-issue-105678.wKOr7F.rst b/Misc/NEWS.d/next/Core and Builtins/2023-06-07-21-27-55.gh-issue-105678.wKOr7F.rst deleted file mode 100644 index fd38c14c140414..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-06-07-21-27-55.gh-issue-105678.wKOr7F.rst +++ /dev/null @@ -1,4 +0,0 @@ -Break the ``MAKE_FUNCTION`` instruction into two parts, ``MAKE_FUNCTION`` -which makes the function and ``SET_FUNCTION_ATTRIBUTE`` which sets the -attributes on the function. This makes the stack effect of ``MAKE_FUNCTION`` -regular to ease optimization and code generation. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-06-08-09-10-15.gh-issue-105486.dev-WS.rst b/Misc/NEWS.d/next/Core and Builtins/2023-06-08-09-10-15.gh-issue-105486.dev-WS.rst deleted file mode 100644 index 9f735db3dc89c3..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-06-08-09-10-15.gh-issue-105486.dev-WS.rst +++ /dev/null @@ -1 +0,0 @@ -Change the repr of ``ParamSpec`` list of args in ``types.GenericAlias``. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-06-08-09-25-52.gh-issue-105375.ocB7fT.rst b/Misc/NEWS.d/next/Core and Builtins/2023-06-08-09-25-52.gh-issue-105375.ocB7fT.rst deleted file mode 100644 index 24fac2df4d0955..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-06-08-09-25-52.gh-issue-105375.ocB7fT.rst +++ /dev/null @@ -1,2 +0,0 @@ -Improve error handling in :c:func:`PyUnicode_BuildEncodingMap` where an -exception could end up being overwritten. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-06-08-09-54-37.gh-issue-105375.kqKT3E.rst b/Misc/NEWS.d/next/Core and Builtins/2023-06-08-09-54-37.gh-issue-105375.kqKT3E.rst deleted file mode 100644 index b4d3a1a5a3cedb..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-06-08-09-54-37.gh-issue-105375.kqKT3E.rst +++ /dev/null @@ -1 +0,0 @@ -Fix bug in the compiler where an exception could end up being overwritten. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-06-08-10-10-07.gh-issue-105375.35VGDd.rst b/Misc/NEWS.d/next/Core and Builtins/2023-06-08-10-10-07.gh-issue-105375.35VGDd.rst deleted file mode 100644 index 3ab85538f3fc43..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-06-08-10-10-07.gh-issue-105375.35VGDd.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix bugs in the :mod:`builtins` module where exceptions could end up being -overwritten. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-06-09-10-48-17.gh-issue-100987.mK-xny.rst b/Misc/NEWS.d/next/Core and Builtins/2023-06-09-10-48-17.gh-issue-100987.mK-xny.rst deleted file mode 100644 index e25789e711c35d..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-06-09-10-48-17.gh-issue-100987.mK-xny.rst +++ /dev/null @@ -1,4 +0,0 @@ -Allow objects other than code objects as the "executable" in internal -frames. In the long term, this can help tools like Cython and PySpy interact -more efficiently. In the shorter term, it allows us to perform some -optimizations more simply. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-06-09-11-19-51.gh-issue-105588.Y5ovpY.rst b/Misc/NEWS.d/next/Core and Builtins/2023-06-09-11-19-51.gh-issue-105588.Y5ovpY.rst deleted file mode 100644 index 3981dad7a49dfb..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-06-09-11-19-51.gh-issue-105588.Y5ovpY.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix an issue that could result in crashes when compiling malformed -:mod:`ast` nodes. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-06-09-12-59-18.gh-issue-105549.PYfTNp.rst b/Misc/NEWS.d/next/Core and Builtins/2023-06-09-12-59-18.gh-issue-105549.PYfTNp.rst deleted file mode 100644 index 7cb177b9353373..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-06-09-12-59-18.gh-issue-105549.PYfTNp.rst +++ /dev/null @@ -1,2 +0,0 @@ -Tokenize separately ``NUMBER`` and ``NAME`` tokens that are not ambiguous. Patch -by Pablo Galindo. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-06-09-15-25-12.gh-issue-105564.sFdUu4.rst b/Misc/NEWS.d/next/Core and Builtins/2023-06-09-15-25-12.gh-issue-105564.sFdUu4.rst deleted file mode 100644 index 9809fac49164f5..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-06-09-15-25-12.gh-issue-105564.sFdUu4.rst +++ /dev/null @@ -1,2 +0,0 @@ -Don't include artificil newlines in the ``line`` attribute of tokens in the -APIs of the :mod:`tokenize` module. Patch by Pablo Galindo diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-06-10-21-38-49.gh-issue-105587.rL3rzv.rst b/Misc/NEWS.d/next/Core and Builtins/2023-06-10-21-38-49.gh-issue-105587.rL3rzv.rst deleted file mode 100644 index 488f82c3fb574c..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-06-10-21-38-49.gh-issue-105587.rL3rzv.rst +++ /dev/null @@ -1,3 +0,0 @@ -The runtime can't guarantee that immortal objects will not be mutated by -Extensions. Thus, this modifies _PyStaticObject_CheckRefcnt to warn -instead of asserting. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-06-11-09-14-30.gh-issue-105331.nlZvoW.rst b/Misc/NEWS.d/next/Core and Builtins/2023-06-11-09-14-30.gh-issue-105331.nlZvoW.rst deleted file mode 100644 index 4a3fee0dd64ae0..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-06-11-09-14-30.gh-issue-105331.nlZvoW.rst +++ /dev/null @@ -1,2 +0,0 @@ -Raise :exc:`ValueError` if the ``delay`` argument to :func:`asyncio.sleep` is a NaN (matching :func:`time.sleep`). - diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-06-12-16-38-31.gh-issue-105340._jRHXe.rst b/Misc/NEWS.d/next/Core and Builtins/2023-06-12-16-38-31.gh-issue-105340._jRHXe.rst deleted file mode 100644 index f6d4fa8fc4d74e..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-06-12-16-38-31.gh-issue-105340._jRHXe.rst +++ /dev/null @@ -1,2 +0,0 @@ -Include the comprehension iteration variable in ``locals()`` inside a -module- or class-scope comprehension. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-06-14-22-52-06.gh-issue-105800.hdpPzZ.rst b/Misc/NEWS.d/next/Core and Builtins/2023-06-14-22-52-06.gh-issue-105800.hdpPzZ.rst deleted file mode 100644 index d6ef7b68b833c6..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-06-14-22-52-06.gh-issue-105800.hdpPzZ.rst +++ /dev/null @@ -1,2 +0,0 @@ -Correctly issue :exc:`SyntaxWarning` in f-strings if invalid sequences are -used. Patch by Pablo Galindo diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-06-15-15-54-47.gh-issue-105831.-MC9Zs.rst b/Misc/NEWS.d/next/Core and Builtins/2023-06-15-15-54-47.gh-issue-105831.-MC9Zs.rst deleted file mode 100644 index 407940add56752..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-06-15-15-54-47.gh-issue-105831.-MC9Zs.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fix an f-string bug, where using a debug expression (the ``=`` sign) that -appears in the last line of a file results to the debug buffer that holds the -expression text being one character too small. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-06-15-22-11-43.gh-issue-105840.Fum_g_.rst b/Misc/NEWS.d/next/Core and Builtins/2023-06-15-22-11-43.gh-issue-105840.Fum_g_.rst deleted file mode 100644 index 5225031292e6c7..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-06-15-22-11-43.gh-issue-105840.Fum_g_.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix possible crashes when specializing function calls with too many -``__defaults__``. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-06-19-11-04-01.gh-issue-105908.7oanny.rst b/Misc/NEWS.d/next/Core and Builtins/2023-06-19-11-04-01.gh-issue-105908.7oanny.rst deleted file mode 100644 index 03db3f064f503f..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-06-19-11-04-01.gh-issue-105908.7oanny.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed bug where :gh:`99111` breaks future import ``barry_as_FLUFL`` in the Python REPL. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-06-22-14-19-17.gh-issue-98931.PPgvSF.rst b/Misc/NEWS.d/next/Core and Builtins/2023-06-22-14-19-17.gh-issue-98931.PPgvSF.rst deleted file mode 100644 index 611660d6286263..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-06-22-14-19-17.gh-issue-98931.PPgvSF.rst +++ /dev/null @@ -1,2 +0,0 @@ -Ensure custom :exc:`SyntaxError` error messages are raised for invalid -imports with multiple targets. Patch by Pablo Galindo diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-06-22-17-37-35.gh-issue-106003.2Vc_Tw.rst b/Misc/NEWS.d/next/Core and Builtins/2023-06-22-17-37-35.gh-issue-106003.2Vc_Tw.rst deleted file mode 100644 index 47143f7eb8f383..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-06-22-17-37-35.gh-issue-106003.2Vc_Tw.rst +++ /dev/null @@ -1,5 +0,0 @@ -Add a new :opcode:`TO_BOOL` instruction, which performs boolean conversions -for :opcode:`POP_JUMP_IF_TRUE`, :opcode:`POP_JUMP_IF_FALSE`, and -:opcode:`UNARY_NOT` (which all expect exact :class:`bool` values now). Also, -modify the oparg of :opcode:`COMPARE_OP` to include an optional "boolean -conversion" flag. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-06-22-19-16-24.gh-issue-105979.TDP2CU.rst b/Misc/NEWS.d/next/Core and Builtins/2023-06-22-19-16-24.gh-issue-105979.TDP2CU.rst deleted file mode 100644 index be6962afd0c78f..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-06-22-19-16-24.gh-issue-105979.TDP2CU.rst +++ /dev/null @@ -1 +0,0 @@ -Fix crash in :func:`!_imp.get_frozen_object` due to improper exception handling. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-06-23-16-51-02.gh-issue-105730.16haMe.rst b/Misc/NEWS.d/next/Core and Builtins/2023-06-23-16-51-02.gh-issue-105730.16haMe.rst deleted file mode 100644 index fa70ee09ce27a1..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-06-23-16-51-02.gh-issue-105730.16haMe.rst +++ /dev/null @@ -1,2 +0,0 @@ -Allow any callable other than type objects as the condition predicate in -:meth:`BaseExceptionGroup.split` and :meth:`BaseExceptionGroup.subgroup`. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-06-24-10-34-27.gh-issue-105775.OqjoGV.rst b/Misc/NEWS.d/next/Core and Builtins/2023-06-24-10-34-27.gh-issue-105775.OqjoGV.rst deleted file mode 100644 index 27d0e9929794f4..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-06-24-10-34-27.gh-issue-105775.OqjoGV.rst +++ /dev/null @@ -1 +0,0 @@ -:opcode:`LOAD_CLOSURE` is now a pseudo-op. \ No newline at end of file diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-06-27-00-58-26.gh-issue-104584.Wu-uXy.rst b/Misc/NEWS.d/next/Core and Builtins/2023-06-27-00-58-26.gh-issue-104584.Wu-uXy.rst deleted file mode 100644 index a36490104ba3aa..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-06-27-00-58-26.gh-issue-104584.Wu-uXy.rst +++ /dev/null @@ -1 +0,0 @@ -Added a new, experimental, tracing optimizer and interpreter (a.k.a. "tier 2"). This currently pessimizes, so don't use yet -- this is infrastructure so we can experiment with optimizing passes. To enable it, pass ``-Xuops`` or set ``PYTHONUOPS=1``. To get debug output, set ``PYTHONUOPSDEBUG=N`` where ``N`` is a debug level (0-4, where 0 is no debug output and 4 is excessively verbose). diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-06-28-13-19-20.gh-issue-106210.oE7VMn.rst b/Misc/NEWS.d/next/Core and Builtins/2023-06-28-13-19-20.gh-issue-106210.oE7VMn.rst deleted file mode 100644 index fde549d21e440a..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-06-28-13-19-20.gh-issue-106210.oE7VMn.rst +++ /dev/null @@ -1 +0,0 @@ -Removed Emscripten import trampoline as it was no longer necessary for Pyodide. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-06-28-15-19-59.gh-issue-106182.cDSFi0.rst b/Misc/NEWS.d/next/Core and Builtins/2023-06-28-15-19-59.gh-issue-106182.cDSFi0.rst deleted file mode 100644 index ca2116b00a6659..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-06-28-15-19-59.gh-issue-106182.cDSFi0.rst +++ /dev/null @@ -1,2 +0,0 @@ -:func:`sys.getfilesystemencoding` and :mod:`sys.getfilesystemencodeerrors` -now return interned Unicode object. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-06-29-09-46-41.gh-issue-106145.QC6-Kq.rst b/Misc/NEWS.d/next/Core and Builtins/2023-06-29-09-46-41.gh-issue-106145.QC6-Kq.rst deleted file mode 100644 index 4f9445bbcbe550..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-06-29-09-46-41.gh-issue-106145.QC6-Kq.rst +++ /dev/null @@ -1,2 +0,0 @@ -Make ``end_lineno`` and ``end_col_offset`` required on ``type_param`` ast -nodes. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-07-03-11-38-43.gh-issue-106008.HDf1zd.rst b/Misc/NEWS.d/next/Core and Builtins/2023-07-03-11-38-43.gh-issue-106008.HDf1zd.rst deleted file mode 100644 index a57b892fd53242..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-07-03-11-38-43.gh-issue-106008.HDf1zd.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix possible reference leaks when failing to optimize comparisons with -:const:`None` in the bytecode compiler. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-07-04-04-50-14.gh-issue-100288.yNQ1ez.rst b/Misc/NEWS.d/next/Core and Builtins/2023-07-04-04-50-14.gh-issue-100288.yNQ1ez.rst deleted file mode 100644 index faf43bd0c2f48e..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-07-04-04-50-14.gh-issue-100288.yNQ1ez.rst +++ /dev/null @@ -1,3 +0,0 @@ -Specialize :opcode:`LOAD_ATTR` for non-descriptors on the class. Adds -:opcode:`LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES` and :opcode -`LOAD_ATTR_NONDESCRIPTOR_NO_DICT`. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-07-04-09-51-45.gh-issue-106396.DmYp7x.rst b/Misc/NEWS.d/next/Core and Builtins/2023-07-04-09-51-45.gh-issue-106396.DmYp7x.rst deleted file mode 100644 index c5767e97271d9d..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-07-04-09-51-45.gh-issue-106396.DmYp7x.rst +++ /dev/null @@ -1,3 +0,0 @@ -When the format specification of an f-string expression is empty, the parser now -generates an empty :class:`ast.JoinedStr` node for it instead of an one-element -:class:`ast.JoinedStr` with an empty string :class:`ast.Constant`. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-07-04-20-42-54.gh-issue-81283.hfh_MD.rst b/Misc/NEWS.d/next/Core and Builtins/2023-07-04-20-42-54.gh-issue-81283.hfh_MD.rst deleted file mode 100644 index f673c665fe3277..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-07-04-20-42-54.gh-issue-81283.hfh_MD.rst +++ /dev/null @@ -1,3 +0,0 @@ -Compiler now strips indents from docstrings. It reduces ``pyc`` file size 5% -when the module is heavily documented. This change affects to ``__doc__`` so -tools like doctest will be affected. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-07-06-00-35-44.gh-issue-96844.kwvoS-.rst b/Misc/NEWS.d/next/Core and Builtins/2023-07-06-00-35-44.gh-issue-96844.kwvoS-.rst deleted file mode 100644 index 55334173bc002d..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-07-06-00-35-44.gh-issue-96844.kwvoS-.rst +++ /dev/null @@ -1 +0,0 @@ -Improve error message of :meth:`list.remove`. Patch by Dong-hee Na. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-07-06-22-46-05.gh-issue-106487.u3KfAD.rst b/Misc/NEWS.d/next/Core and Builtins/2023-07-06-22-46-05.gh-issue-106487.u3KfAD.rst deleted file mode 100644 index 9e8100022bbd23..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-07-06-22-46-05.gh-issue-106487.u3KfAD.rst +++ /dev/null @@ -1,2 +0,0 @@ -Allow the *count* argument of :meth:`str.replace` to be a keyword. Patch by -Hugo van Kemenade. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-07-10-15-30-45.gh-issue-106597.WAZ14y.rst b/Misc/NEWS.d/next/Core and Builtins/2023-07-10-15-30-45.gh-issue-106597.WAZ14y.rst deleted file mode 100644 index bbe455d652f50e..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-07-10-15-30-45.gh-issue-106597.WAZ14y.rst +++ /dev/null @@ -1,5 +0,0 @@ -A new debug structure of offsets has been added to the ``_PyRuntimeState`` -that will help out-of-process debuggers and profilers to obtain the offsets -to relevant interpreter structures in a way that is agnostic of how Python -was compiled and that doesn't require copying the headers. Patch by Pablo -Galindo diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-07-12-10-48-08.gh-issue-104909.sWjcr2.rst b/Misc/NEWS.d/next/Core and Builtins/2023-07-12-10-48-08.gh-issue-104909.sWjcr2.rst deleted file mode 100644 index f20226e5c54d16..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-07-12-10-48-08.gh-issue-104909.sWjcr2.rst +++ /dev/null @@ -1 +0,0 @@ -Split :opcode:`LOAD_GLOBAL` specializations into micro-ops. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-07-12-11-18-55.gh-issue-104909.DRUsuh.rst b/Misc/NEWS.d/next/Core and Builtins/2023-07-12-11-18-55.gh-issue-104909.DRUsuh.rst deleted file mode 100644 index e0c1e67515a62c..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-07-12-11-18-55.gh-issue-104909.DRUsuh.rst +++ /dev/null @@ -1 +0,0 @@ -Split :opcode:`LOAD_ATTR_INSTANCE_VALUE` into micro-ops. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-07-13-14-55-45.gh-issue-106723.KsMufQ.rst b/Misc/NEWS.d/next/Core and Builtins/2023-07-13-14-55-45.gh-issue-106723.KsMufQ.rst deleted file mode 100644 index 207f397f17d3f3..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-07-13-14-55-45.gh-issue-106723.KsMufQ.rst +++ /dev/null @@ -1 +0,0 @@ -Propagate ``frozen_modules`` to multiprocessing spawned process interpreters. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-07-13-15-59-07.gh-issue-106719.jmVrsv.rst b/Misc/NEWS.d/next/Core and Builtins/2023-07-13-15-59-07.gh-issue-106719.jmVrsv.rst deleted file mode 100644 index dc4bef193a3220..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-07-13-15-59-07.gh-issue-106719.jmVrsv.rst +++ /dev/null @@ -1,2 +0,0 @@ -No longer suppress arbitrary errors in the ``__annotations__`` getter and -setter in the type and module types. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-07-18-16-13-51.gh-issue-106092.bObgRM.rst b/Misc/NEWS.d/next/Core and Builtins/2023-07-18-16-13-51.gh-issue-106092.bObgRM.rst deleted file mode 100644 index 7fb5b45c763e45..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-07-18-16-13-51.gh-issue-106092.bObgRM.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix a segmentation fault caused by a use-after-free bug in ``frame_dealloc`` -when the trashcan delays the deallocation of a ``PyFrameObject``. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-07-20-01-15-58.gh-issue-106908.cDmcVI.rst b/Misc/NEWS.d/next/Core and Builtins/2023-07-20-01-15-58.gh-issue-106908.cDmcVI.rst deleted file mode 100644 index 9c9b84599cb551..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-07-20-01-15-58.gh-issue-106908.cDmcVI.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fix various hangs, reference leaks, test failures, and tracing/introspection -bugs when running with :envvar:`PYTHONUOPS` or :option:`-X uops <-X>` -enabled. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-07-20-12-21-37.gh-issue-105699.08ywGV.rst b/Misc/NEWS.d/next/Core and Builtins/2023-07-20-12-21-37.gh-issue-105699.08ywGV.rst deleted file mode 100644 index 82312718cd047e..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-07-20-12-21-37.gh-issue-105699.08ywGV.rst +++ /dev/null @@ -1,4 +0,0 @@ -Python no longer crashes due to an infrequent race in setting -``Py_FileSystemDefaultEncoding`` and ``Py_FileSystemDefaultEncodeErrors`` -(both deprecated), when simultaneously initializing two isolated -subinterpreters. Now they are only set during runtime initialization. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-07-20-15-15-57.gh-issue-105699.DdqHFg.rst b/Misc/NEWS.d/next/Core and Builtins/2023-07-20-15-15-57.gh-issue-105699.DdqHFg.rst deleted file mode 100644 index 4a257c6282220f..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-07-20-15-15-57.gh-issue-105699.DdqHFg.rst +++ /dev/null @@ -1,3 +0,0 @@ -Python no longer crashes due an infrequent race when initialzing -per-interpreter interned strings. The crash would manifest when the -interpreter was finalized. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-07-21-14-37-48.gh-issue-106917.1jWp_m.rst b/Misc/NEWS.d/next/Core and Builtins/2023-07-21-14-37-48.gh-issue-106917.1jWp_m.rst deleted file mode 100644 index 82c74d5465458a..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-07-21-14-37-48.gh-issue-106917.1jWp_m.rst +++ /dev/null @@ -1,4 +0,0 @@ -Fix classmethod-style :func:`super` method calls (i.e., where the second -argument to :func:`super`, or the implied second argument drawn from -``self/cls`` in the case of zero-arg super, is a type) when the target of -the call is not a classmethod. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-07-22-14-35-38.gh-issue-107015.Ghp58t.rst b/Misc/NEWS.d/next/Core and Builtins/2023-07-22-14-35-38.gh-issue-107015.Ghp58t.rst deleted file mode 100644 index 77618a5bd50f2a..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-07-22-14-35-38.gh-issue-107015.Ghp58t.rst +++ /dev/null @@ -1,3 +0,0 @@ -The ASYNC and AWAIT tokens are removed from the Grammar, which removes the -posibility of making ``async`` and ``await`` soft keywords when using -``feature_version<7`` in :func:`ast.parse`. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-07-23-13-07-34.gh-issue-107122.9HFUyb.rst b/Misc/NEWS.d/next/Core and Builtins/2023-07-23-13-07-34.gh-issue-107122.9HFUyb.rst deleted file mode 100644 index 64ac8ac6df09b8..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-07-23-13-07-34.gh-issue-107122.9HFUyb.rst +++ /dev/null @@ -1 +0,0 @@ -Add :meth:`dbm.gnu.gdbm.clear` to :mod:`dbm.gnu`. Patch By Dong-hee Na. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-07-23-21-16-54.gh-issue-107122.VNuNcq.rst b/Misc/NEWS.d/next/Core and Builtins/2023-07-23-21-16-54.gh-issue-107122.VNuNcq.rst deleted file mode 100644 index 5b7cc98ddc6414..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-07-23-21-16-54.gh-issue-107122.VNuNcq.rst +++ /dev/null @@ -1 +0,0 @@ -Add :meth:`dbm.ndbm.ndbm.clear` to :mod:`dbm.ndbm`. Patch By Dong-hee Na. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-07-24-11-11-41.gh-issue-104621.vM8Y_l.rst b/Misc/NEWS.d/next/Core and Builtins/2023-07-24-11-11-41.gh-issue-104621.vM8Y_l.rst deleted file mode 100644 index 86c976295f2620..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-07-24-11-11-41.gh-issue-104621.vM8Y_l.rst +++ /dev/null @@ -1 +0,0 @@ -Unsupported modules now always fail to be imported. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-07-25-15-29-26.gh-issue-106931.kKU1le.rst b/Misc/NEWS.d/next/Core and Builtins/2023-07-25-15-29-26.gh-issue-106931.kKU1le.rst deleted file mode 100644 index e0def5331b6c82..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-07-25-15-29-26.gh-issue-106931.kKU1le.rst +++ /dev/null @@ -1,3 +0,0 @@ -Statically allocated string objects are now interned globally instead of -per-interpreter. This fixes a situation where such a string would only be -interned in a single interpreter. Normal string objects are unaffected. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-07-26-12-18-10.gh-issue-106897.EsGurc.rst b/Misc/NEWS.d/next/Core and Builtins/2023-07-26-12-18-10.gh-issue-106897.EsGurc.rst deleted file mode 100644 index d787dc4aad2d29..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-07-26-12-18-10.gh-issue-106897.EsGurc.rst +++ /dev/null @@ -1,3 +0,0 @@ -Add a ``RERAISE`` event to ``sys.monitoring``, which occurs when an -exception is reraise, either explicitly by a plain ``raise`` statement, or -implicitly in an ``except`` or ``finally`` block. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-07-26-18-53-34.gh-issue-106895.DdEwV8.rst b/Misc/NEWS.d/next/Core and Builtins/2023-07-26-18-53-34.gh-issue-106895.DdEwV8.rst deleted file mode 100644 index 370a29d34c860a..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-07-26-18-53-34.gh-issue-106895.DdEwV8.rst +++ /dev/null @@ -1,2 +0,0 @@ -Raise a ``ValueError`` when a monitoring callback funtion returns -``DISABLE`` for events that cannot be disabled locally. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-07-26-21-28-06.gh-issue-106898.8Wjuiv.rst b/Misc/NEWS.d/next/Core and Builtins/2023-07-26-21-28-06.gh-issue-106898.8Wjuiv.rst deleted file mode 100644 index f1b1c4c64b4aca..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-07-26-21-28-06.gh-issue-106898.8Wjuiv.rst +++ /dev/null @@ -1,3 +0,0 @@ -Add the exception as the third argument to ``PY_UNIND`` callbacks in -``sys.monitoring``. This makes the ``PY_UNWIND`` callback consistent with -the other exception hanlding callbacks. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-07-27-11-18-04.gh-issue-106078.WEy2Yn.rst b/Misc/NEWS.d/next/Core and Builtins/2023-07-27-11-18-04.gh-issue-106078.WEy2Yn.rst deleted file mode 100644 index f5a0e539e5d05f..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-07-27-11-18-04.gh-issue-106078.WEy2Yn.rst +++ /dev/null @@ -1 +0,0 @@ -Isolate :mod:`!_decimal` (apply :pep:`687`). Patch by Charlie Zhao. \ No newline at end of file diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-07-27-11-47-29.gh-issue-104432.oGHF-z.rst b/Misc/NEWS.d/next/Core and Builtins/2023-07-27-11-47-29.gh-issue-104432.oGHF-z.rst deleted file mode 100644 index e47927b4e11886..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-07-27-11-47-29.gh-issue-104432.oGHF-z.rst +++ /dev/null @@ -1,4 +0,0 @@ -Fix potential unaligned memory access on C APIs involving returned sequences -of `char *` pointers within the :mod:`grp` and :mod:`socket` modules. These -were revealed using a ``-fsaniziter=alignment`` build on ARM macOS. Patch by -Christopher Chavez. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-07-29-22-01-30.gh-issue-104584.tINuoA.rst b/Misc/NEWS.d/next/Core and Builtins/2023-07-29-22-01-30.gh-issue-104584.tINuoA.rst deleted file mode 100644 index 059524831597b7..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-07-29-22-01-30.gh-issue-104584.tINuoA.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix an issue which caused incorrect inline caches to be read when running -with :envvar:`PYTHONUOPS` or :option:`-X uops <-X>` enabled. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-07-30-05-20-16.gh-issue-107263.q0IU2M.rst b/Misc/NEWS.d/next/Core and Builtins/2023-07-30-05-20-16.gh-issue-107263.q0IU2M.rst deleted file mode 100644 index fb0940b456dae5..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-07-30-05-20-16.gh-issue-107263.q0IU2M.rst +++ /dev/null @@ -1,3 +0,0 @@ -Increase C recursion limit for functions other than the main interpreter -from 800 to 1500. This should allow functions like ``list.__repr__`` and -``json.dumps`` to handle all the inputs that they could prior to 3.12 diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-07-30-14-18-49.gh-issue-107455.Es53l7.rst b/Misc/NEWS.d/next/Core and Builtins/2023-07-30-14-18-49.gh-issue-107455.Es53l7.rst deleted file mode 100644 index 84a93251e799d5..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-07-30-14-18-49.gh-issue-107455.Es53l7.rst +++ /dev/null @@ -1,3 +0,0 @@ -Improve error messages when converting an incompatible type to -:class:`ctypes.c_char_p`, :class:`ctypes.c_wchar_p` and -:class:`ctypes.c_void_p`. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-07-30-18-05-11.gh-issue-100964.HluhBJ.rst b/Misc/NEWS.d/next/Core and Builtins/2023-07-30-18-05-11.gh-issue-100964.HluhBJ.rst deleted file mode 100644 index 99ebc926e2ce2d..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-07-30-18-05-11.gh-issue-100964.HluhBJ.rst +++ /dev/null @@ -1,2 +0,0 @@ -Clear generators' exception state after ``return`` to break reference -cycles. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-08-01-09-41-36.gh-issue-106608.OFZogw.rst b/Misc/NEWS.d/next/Core and Builtins/2023-08-01-09-41-36.gh-issue-106608.OFZogw.rst deleted file mode 100644 index 20d43a7c4f754a..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-08-01-09-41-36.gh-issue-106608.OFZogw.rst +++ /dev/null @@ -1 +0,0 @@ -Make ``_PyUOpExecutorObject`` variable length. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-08-02-12-24-51.gh-issue-107080.PNolFU.rst b/Misc/NEWS.d/next/Core and Builtins/2023-08-02-12-24-51.gh-issue-107080.PNolFU.rst deleted file mode 100644 index 5084c854360e35..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-08-02-12-24-51.gh-issue-107080.PNolFU.rst +++ /dev/null @@ -1,4 +0,0 @@ -Trace refs builds (``--with-trace-refs``) were crashing when used with -isolated subinterpreters. The problematic global state has been isolated to -each interpreter. Other fixing the crashes, this change does not affect -users. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-08-03-13-38-14.gh-issue-84436.gl1wHx.rst b/Misc/NEWS.d/next/Core and Builtins/2023-08-03-13-38-14.gh-issue-84436.gl1wHx.rst deleted file mode 100644 index 71044c32feebcc..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-08-03-13-38-14.gh-issue-84436.gl1wHx.rst +++ /dev/null @@ -1 +0,0 @@ -Skip reference count modifications for many known immortal objects. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-11-22-13-17-54.gh-issue-112320.EddM51.rst b/Misc/NEWS.d/next/Core and Builtins/2023-11-22-13-17-54.gh-issue-112320.EddM51.rst new file mode 100644 index 00000000000000..0da2fd33b0ea52 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2023-11-22-13-17-54.gh-issue-112320.EddM51.rst @@ -0,0 +1,4 @@ +The Tier 2 translator now tracks the confidence level for staying "on trace" +(i.e. not exiting back to the Tier 1 interpreter) for branch instructions +based on the number of bits set in the branch "counter". Trace translation +ends when the confidence drops below 1/3rd. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-11-24-14-10-57.gh-issue-112367.9z1IDp.rst b/Misc/NEWS.d/next/Core and Builtins/2023-11-24-14-10-57.gh-issue-112367.9z1IDp.rst new file mode 100644 index 00000000000000..991e45ad47fabe --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2023-11-24-14-10-57.gh-issue-112367.9z1IDp.rst @@ -0,0 +1,2 @@ +Avoid undefined behaviour when using the perf trampolines by not freeing the +code arenas until shutdown. Patch by Pablo Galindo diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-11-25-20-36-38.gh-issue-99606.fDY5hK.rst b/Misc/NEWS.d/next/Core and Builtins/2023-11-25-20-36-38.gh-issue-99606.fDY5hK.rst new file mode 100644 index 00000000000000..adc0e3a6bbc89a --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2023-11-25-20-36-38.gh-issue-99606.fDY5hK.rst @@ -0,0 +1,2 @@ +Make code generated for an empty f-string identical to the code of an empty +normal string. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-11-25-22-39-44.gh-issue-112387.AbBq5W.rst b/Misc/NEWS.d/next/Core and Builtins/2023-11-25-22-39-44.gh-issue-112387.AbBq5W.rst new file mode 100644 index 00000000000000..adac11bf4c90a1 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2023-11-25-22-39-44.gh-issue-112387.AbBq5W.rst @@ -0,0 +1,2 @@ +Fix error positions for decoded strings with backwards tokenize errors. +Patch by Pablo Galindo diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-11-25-22-58-49.gh-issue-112388.MU3cIM.rst b/Misc/NEWS.d/next/Core and Builtins/2023-11-25-22-58-49.gh-issue-112388.MU3cIM.rst new file mode 100644 index 00000000000000..1c82be2febda4f --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2023-11-25-22-58-49.gh-issue-112388.MU3cIM.rst @@ -0,0 +1,2 @@ +Fix an error that was causing the parser to try to overwrite tokenizer +errors. Patch by pablo Galindo diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-11-26-21-30-11.gh-issue-111058.q4DqDY.rst b/Misc/NEWS.d/next/Core and Builtins/2023-11-26-21-30-11.gh-issue-111058.q4DqDY.rst new file mode 100644 index 00000000000000..de5661f911aa82 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2023-11-26-21-30-11.gh-issue-111058.q4DqDY.rst @@ -0,0 +1,3 @@ +Change coro.cr_frame/gen.gi_frame to return ``None`` after the coroutine/generator has been closed. +This fixes a bug where :func:`~inspect.getcoroutinestate` and :func:`~inspect.getgeneratorstate` +return the wrong state for a closed coroutine/generator. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-11-27-18-55-30.gh-issue-112217.SwFLMj.rst b/Misc/NEWS.d/next/Core and Builtins/2023-11-27-18-55-30.gh-issue-112217.SwFLMj.rst new file mode 100644 index 00000000000000..d4efbab6b2d128 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2023-11-27-18-55-30.gh-issue-112217.SwFLMj.rst @@ -0,0 +1 @@ +Add check for the type of ``__cause__`` returned from calling the type ``T`` in ``raise from T``. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-12-01-08-16-10.gh-issue-95754.ae4gwy.rst b/Misc/NEWS.d/next/Core and Builtins/2023-12-01-08-16-10.gh-issue-95754.ae4gwy.rst new file mode 100644 index 00000000000000..0884bc4a4be726 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2023-12-01-08-16-10.gh-issue-95754.ae4gwy.rst @@ -0,0 +1 @@ +Provide a better error message when accessing invalid attributes on partially initialized modules. The origin of the module being accessed is now included in the message to help with the common issue of shadowing other modules. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-12-01-19-02-21.gh-issue-105967.Puq5Cn.rst b/Misc/NEWS.d/next/Core and Builtins/2023-12-01-19-02-21.gh-issue-105967.Puq5Cn.rst new file mode 100644 index 00000000000000..c69511218e3e16 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2023-12-01-19-02-21.gh-issue-105967.Puq5Cn.rst @@ -0,0 +1,4 @@ +Workaround a bug in Apple's macOS platform zlib library where +:func:`zlib.crc32` and :func:`binascii.crc32` could produce incorrect results +on multi-gigabyte inputs. Including when using :mod:`zipfile` on zips +containing large data. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-12-03-15-29-53.gh-issue-112660.gldBvh.rst b/Misc/NEWS.d/next/Core and Builtins/2023-12-03-15-29-53.gh-issue-112660.gldBvh.rst new file mode 100644 index 00000000000000..ea9052b3e35c48 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2023-12-03-15-29-53.gh-issue-112660.gldBvh.rst @@ -0,0 +1,2 @@ +Do not clear unexpected errors during formatting error messages for +ImportError and AttributeError for modules. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-12-03-19-34-51.gh-issue-112625.QWTlwS.rst b/Misc/NEWS.d/next/Core and Builtins/2023-12-03-19-34-51.gh-issue-112625.QWTlwS.rst new file mode 100644 index 00000000000000..4970e10f3f4dcb --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2023-12-03-19-34-51.gh-issue-112625.QWTlwS.rst @@ -0,0 +1 @@ +Fixes a bug where a bytearray object could be cleared while iterating over an argument in the ``bytearray.join()`` method that could result in reading memory after it was freed. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-12-04-23-09-07.gh-issue-112730.BXHlFa.rst b/Misc/NEWS.d/next/Core and Builtins/2023-12-04-23-09-07.gh-issue-112730.BXHlFa.rst new file mode 100644 index 00000000000000..51758dd5f4c318 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2023-12-04-23-09-07.gh-issue-112730.BXHlFa.rst @@ -0,0 +1 @@ +Use color to highlight error locations in tracebacks. Patch by Pablo Galindo diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-12-05-20-41-58.gh-issue-112716.hOcx0Y.rst b/Misc/NEWS.d/next/Core and Builtins/2023-12-05-20-41-58.gh-issue-112716.hOcx0Y.rst new file mode 100644 index 00000000000000..44d63269c5424a --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2023-12-05-20-41-58.gh-issue-112716.hOcx0Y.rst @@ -0,0 +1,2 @@ +Fix SystemError in the ``import`` statement and in ``__reduce__()`` methods +of builtin types when ``__builtins__`` is not a dict. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-12-07-12-00-04.gh-issue-74616.kgTGVb.rst b/Misc/NEWS.d/next/Core and Builtins/2023-12-07-12-00-04.gh-issue-74616.kgTGVb.rst new file mode 100644 index 00000000000000..5c345be9de6d0b --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2023-12-07-12-00-04.gh-issue-74616.kgTGVb.rst @@ -0,0 +1,2 @@ +:func:`input` now raises a ValueError when output on the terminal if the +prompt contains embedded null characters instead of silently truncating it. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-12-07-13-19-55.gh-issue-112125.4ADN7i.rst b/Misc/NEWS.d/next/Core and Builtins/2023-12-07-13-19-55.gh-issue-112125.4ADN7i.rst new file mode 100644 index 00000000000000..52cd45029fb8c7 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2023-12-07-13-19-55.gh-issue-112125.4ADN7i.rst @@ -0,0 +1 @@ +Fix None.__ne__(None) returning NotImplemented instead of False diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-12-11-00-50-00.gh-issue-112943.RHNZie.rst b/Misc/NEWS.d/next/Core and Builtins/2023-12-11-00-50-00.gh-issue-112943.RHNZie.rst new file mode 100644 index 00000000000000..4bc2fe7c26d904 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2023-12-11-00-50-00.gh-issue-112943.RHNZie.rst @@ -0,0 +1,2 @@ +Correctly compute end column offsets for multiline tokens in the +:mod:`tokenize` module. Patch by Pablo Galindo diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-12-11-19-53-32.gh-issue-90350.-FQy3E.rst b/Misc/NEWS.d/next/Core and Builtins/2023-12-11-19-53-32.gh-issue-90350.-FQy3E.rst new file mode 100644 index 00000000000000..6b7881bbd19f59 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2023-12-11-19-53-32.gh-issue-90350.-FQy3E.rst @@ -0,0 +1 @@ +Optimize builtin functions :func:`min` and :func:`max`. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-12-12-04-53-19.gh-issue-108866.xbJ-9a.rst b/Misc/NEWS.d/next/Core and Builtins/2023-12-12-04-53-19.gh-issue-108866.xbJ-9a.rst new file mode 100644 index 00000000000000..96606924d4a3ec --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2023-12-12-04-53-19.gh-issue-108866.xbJ-9a.rst @@ -0,0 +1,3 @@ +Change the API and contract of ``_PyExecutorObject`` to return the +next_instr pointer, instead of the frame, and to always execute at least one +instruction. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-12-13-11-45-53.gh-issue-106905.5dslTN.rst b/Misc/NEWS.d/next/Core and Builtins/2023-12-13-11-45-53.gh-issue-106905.5dslTN.rst new file mode 100644 index 00000000000000..e3a772f3354ecf --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2023-12-13-11-45-53.gh-issue-106905.5dslTN.rst @@ -0,0 +1,7 @@ +Use per AST-parser state rather than global state to track recursion depth +within the AST parser to prevent potential race condition due to +simultaneous parsing. + +The issue primarily showed up in 3.11 by multithreaded users of +:func:`ast.parse`. In 3.12 a change to when garbage collection can be +triggered prevented the race condition from occurring. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-12-14-20-08-35.gh-issue-113054.e20CtM.rst b/Misc/NEWS.d/next/Core and Builtins/2023-12-14-20-08-35.gh-issue-113054.e20CtM.rst new file mode 100644 index 00000000000000..d0729f9c44754c --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2023-12-14-20-08-35.gh-issue-113054.e20CtM.rst @@ -0,0 +1,2 @@ +Fixed bug where a redundant NOP is not removed, causing an assertion to fail +in the compiler in debug mode. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-12-15-16-26-01.gh-issue-112215.xJS6_6.rst b/Misc/NEWS.d/next/Core and Builtins/2023-12-15-16-26-01.gh-issue-112215.xJS6_6.rst new file mode 100644 index 00000000000000..01ca1cc7f79b8f --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2023-12-15-16-26-01.gh-issue-112215.xJS6_6.rst @@ -0,0 +1,3 @@ +Increase the C recursion limit by a factor of 3 for non-debug builds, except +for webassembly and s390 platforms which are unchanged. This mitigates some +regressions in 3.12 with deep recursion mixing builtin (C) and Python code. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-12-19-22-03-43.gh-issue-111375.M9vuA6.rst b/Misc/NEWS.d/next/Core and Builtins/2023-12-19-22-03-43.gh-issue-111375.M9vuA6.rst new file mode 100644 index 00000000000000..fbb517173451f8 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2023-12-19-22-03-43.gh-issue-111375.M9vuA6.rst @@ -0,0 +1,2 @@ +Only use ``NULL`` in the exception stack to indicate an exception was +handled. Patch by Carey Metcalfe. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-12-20-08-54-54.gh-issue-113212.62AUlw.rst b/Misc/NEWS.d/next/Core and Builtins/2023-12-20-08-54-54.gh-issue-113212.62AUlw.rst new file mode 100644 index 00000000000000..6edbc9c60d968c --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2023-12-20-08-54-54.gh-issue-113212.62AUlw.rst @@ -0,0 +1 @@ +Improve :py:class:`super` error messages. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-12-20-18-27-11.gh-issue-113297.BZyAI_.rst b/Misc/NEWS.d/next/Core and Builtins/2023-12-20-18-27-11.gh-issue-113297.BZyAI_.rst new file mode 100644 index 00000000000000..b6aee1f241fd23 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2023-12-20-18-27-11.gh-issue-113297.BZyAI_.rst @@ -0,0 +1 @@ +Fix segfault in the compiler on with statement with 19 context managers. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-12-31-07-46-01.gh-issue-113486.uki19C.rst b/Misc/NEWS.d/next/Core and Builtins/2023-12-31-07-46-01.gh-issue-113486.uki19C.rst new file mode 100644 index 00000000000000..42ff4a2feb15f2 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2023-12-31-07-46-01.gh-issue-113486.uki19C.rst @@ -0,0 +1 @@ +No longer issue spurious ``PY_UNWIND`` events for optimized calls to classes. diff --git a/Misc/NEWS.d/next/Core and Builtins/2024-01-01-00-07-02.gh-issue-113602.cWuTzk.rst b/Misc/NEWS.d/next/Core and Builtins/2024-01-01-00-07-02.gh-issue-113602.cWuTzk.rst new file mode 100644 index 00000000000000..5e064657348720 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2024-01-01-00-07-02.gh-issue-113602.cWuTzk.rst @@ -0,0 +1,2 @@ +Fix an error that was causing the parser to try to overwrite existing errors +and crashing in the process. Patch by Pablo Galindo diff --git a/Misc/NEWS.d/next/Core and Builtins/2024-01-01-23-57-24.gh-issue-113603.ySwovr.rst b/Misc/NEWS.d/next/Core and Builtins/2024-01-01-23-57-24.gh-issue-113603.ySwovr.rst new file mode 100644 index 00000000000000..5fe6d80dedd19d --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2024-01-01-23-57-24.gh-issue-113603.ySwovr.rst @@ -0,0 +1 @@ +Fixed bug where a redundant NOP is not removed, causing an assertion to fail in the compiler in debug mode. diff --git a/Misc/NEWS.d/next/Core and Builtins/2024-01-02-11-14-29.gh-issue-113657.CQo9vF.rst b/Misc/NEWS.d/next/Core and Builtins/2024-01-02-11-14-29.gh-issue-113657.CQo9vF.rst new file mode 100644 index 00000000000000..b520b5c2529425 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2024-01-02-11-14-29.gh-issue-113657.CQo9vF.rst @@ -0,0 +1,2 @@ +Fix an issue that caused important instruction pointer updates to be +optimized out of tier two traces. diff --git a/Misc/NEWS.d/next/Core and Builtins/2024-01-02-17-22-57.gh-issue-111488.EJH3Oh.rst b/Misc/NEWS.d/next/Core and Builtins/2024-01-02-17-22-57.gh-issue-111488.EJH3Oh.rst new file mode 100644 index 00000000000000..08f3e48f60749f --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2024-01-02-17-22-57.gh-issue-111488.EJH3Oh.rst @@ -0,0 +1,2 @@ +Changed error message in case of no 'in' keyword after 'for' in list +comprehensions diff --git a/Misc/NEWS.d/next/Core and Builtins/2024-01-03-12-19-37.gh-issue-89811.cZOj6d.rst b/Misc/NEWS.d/next/Core and Builtins/2024-01-03-12-19-37.gh-issue-89811.cZOj6d.rst new file mode 100644 index 00000000000000..90bd9814faffd5 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2024-01-03-12-19-37.gh-issue-89811.cZOj6d.rst @@ -0,0 +1,2 @@ +Check for a valid ``tp_version_tag`` before performing bytecode specializations that +rely on this value being usable. diff --git a/Misc/NEWS.d/next/Core and Builtins/2024-01-04-17-15-30.gh-issue-113703.Zsk0pY.rst b/Misc/NEWS.d/next/Core and Builtins/2024-01-04-17-15-30.gh-issue-113703.Zsk0pY.rst new file mode 100644 index 00000000000000..5db93e344724fb --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2024-01-04-17-15-30.gh-issue-113703.Zsk0pY.rst @@ -0,0 +1,2 @@ +Fix a regression in the :mod:`codeop` module that was causing it to incorrectly +identify incomplete f-strings. Patch by Pablo Galindo diff --git a/Misc/NEWS.d/next/Core and Builtins/2024-01-05-00-49-14.gh-issue-107901.6JRrb6.rst b/Misc/NEWS.d/next/Core and Builtins/2024-01-05-00-49-14.gh-issue-107901.6JRrb6.rst new file mode 100644 index 00000000000000..e44c8301bbf744 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2024-01-05-00-49-14.gh-issue-107901.6JRrb6.rst @@ -0,0 +1 @@ +Compiler changed so that synthetic jumps which are not at loop end no longer check the eval breaker. diff --git a/Misc/NEWS.d/next/Core and Builtins/2024-01-05-21-28-48.gh-issue-113753.2HNiuq.rst b/Misc/NEWS.d/next/Core and Builtins/2024-01-05-21-28-48.gh-issue-113753.2HNiuq.rst new file mode 100644 index 00000000000000..32cf2cb2a4ae56 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2024-01-05-21-28-48.gh-issue-113753.2HNiuq.rst @@ -0,0 +1,2 @@ +Fix an issue where the finalizer of ``PyAsyncGenASend`` objects might not be +called if they were allocated from a free list. diff --git a/Misc/NEWS.d/next/Core and Builtins/2024-01-08-05-36-59.gh-issue-113853.lm-6_a.rst b/Misc/NEWS.d/next/Core and Builtins/2024-01-08-05-36-59.gh-issue-113853.lm-6_a.rst new file mode 100644 index 00000000000000..d4f0a764153579 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2024-01-08-05-36-59.gh-issue-113853.lm-6_a.rst @@ -0,0 +1,2 @@ +Guarantee that all executors make progress. This then guarantees that tier 2 +execution always makes progress. diff --git a/Misc/NEWS.d/next/Core and Builtins/2024-01-08-14-34-02.gh-issue-77046.sDUh2d.rst b/Misc/NEWS.d/next/Core and Builtins/2024-01-08-14-34-02.gh-issue-77046.sDUh2d.rst new file mode 100644 index 00000000000000..9f0f144451df6c --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2024-01-08-14-34-02.gh-issue-77046.sDUh2d.rst @@ -0,0 +1,3 @@ +On Windows, file descriptors wrapping Windows handles are now created non +inheritable by default (:pep:`446`). Patch by Zackery Spytz and Victor +Stinner. diff --git a/Misc/NEWS.d/next/Core and Builtins/2024-01-11-14-03-31.gh-issue-107901.U65IyC.rst b/Misc/NEWS.d/next/Core and Builtins/2024-01-11-14-03-31.gh-issue-107901.U65IyC.rst new file mode 100644 index 00000000000000..5c81b665216f82 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2024-01-11-14-03-31.gh-issue-107901.U65IyC.rst @@ -0,0 +1 @@ +A jump leaving an exception handler back to normal code no longer checks the eval breaker. diff --git a/Misc/NEWS.d/next/Documentation/2023-05-16-22-08-24.gh-issue-54738.mJvCnj.rst b/Misc/NEWS.d/next/Documentation/2023-05-16-22-08-24.gh-issue-54738.mJvCnj.rst deleted file mode 100644 index 4da58fc982b6d7..00000000000000 --- a/Misc/NEWS.d/next/Documentation/2023-05-16-22-08-24.gh-issue-54738.mJvCnj.rst +++ /dev/null @@ -1 +0,0 @@ -Add documentation on how to localize the :mod:`argparse` module. diff --git a/Misc/NEWS.d/next/Documentation/2023-05-25-22-34-31.gh-issue-104943.J2v1Pc.rst b/Misc/NEWS.d/next/Documentation/2023-05-25-22-34-31.gh-issue-104943.J2v1Pc.rst deleted file mode 100644 index bc4d03b8e95f86..00000000000000 --- a/Misc/NEWS.d/next/Documentation/2023-05-25-22-34-31.gh-issue-104943.J2v1Pc.rst +++ /dev/null @@ -1 +0,0 @@ -Remove mentions of old Python versions in :class:`typing.NamedTuple`. diff --git a/Misc/NEWS.d/next/Documentation/2023-05-28-19-08-42.gh-issue-89412.j4cg7K.rst b/Misc/NEWS.d/next/Documentation/2023-05-28-19-08-42.gh-issue-89412.j4cg7K.rst deleted file mode 100644 index 00937e58c98595..00000000000000 --- a/Misc/NEWS.d/next/Documentation/2023-05-28-19-08-42.gh-issue-89412.j4cg7K.rst +++ /dev/null @@ -1,2 +0,0 @@ -Add missing documentation for the ``end_lineno`` and ``end_offset`` attributes -of the :class:`traceback.TracebackException` class. diff --git a/Misc/NEWS.d/next/Documentation/2023-05-28-21-01-00.gh-issue-89455.qAKRrA.rst b/Misc/NEWS.d/next/Documentation/2023-05-28-21-01-00.gh-issue-89455.qAKRrA.rst deleted file mode 100644 index fdfa4357f001b5..00000000000000 --- a/Misc/NEWS.d/next/Documentation/2023-05-28-21-01-00.gh-issue-89455.qAKRrA.rst +++ /dev/null @@ -1,3 +0,0 @@ -Add missing documentation for the ``max_group_depth`` and ``max_group_width`` -parameters and the ``exceptions`` attribute of the -:class:`traceback.TracebackException` class. diff --git a/Misc/NEWS.d/next/Documentation/2023-05-31-23-05-51.gh-issue-105172.SVfvkD.rst b/Misc/NEWS.d/next/Documentation/2023-05-31-23-05-51.gh-issue-105172.SVfvkD.rst deleted file mode 100644 index 96cf7220e53079..00000000000000 --- a/Misc/NEWS.d/next/Documentation/2023-05-31-23-05-51.gh-issue-105172.SVfvkD.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fixed :func:`functools.lru_cache` docstring accounting for ``typed`` -argument's different handling of str and int. Patch by Bar Harel. diff --git a/Misc/NEWS.d/next/Documentation/2023-06-30-19-28-59.gh-issue-106232.hQ4-tz.rst b/Misc/NEWS.d/next/Documentation/2023-06-30-19-28-59.gh-issue-106232.hQ4-tz.rst deleted file mode 100644 index bc16f92b7d6478..00000000000000 --- a/Misc/NEWS.d/next/Documentation/2023-06-30-19-28-59.gh-issue-106232.hQ4-tz.rst +++ /dev/null @@ -1,2 +0,0 @@ -Make timeit doc command lines compatible with Windows by using double quotes -for arguments. This works on linux and macOS also. diff --git a/Misc/NEWS.d/next/Documentation/2023-07-21-11-51-57.gh-issue-106948.K_JQ7j.rst b/Misc/NEWS.d/next/Documentation/2023-07-21-11-51-57.gh-issue-106948.K_JQ7j.rst deleted file mode 100644 index 42b6348153b56a..00000000000000 --- a/Misc/NEWS.d/next/Documentation/2023-07-21-11-51-57.gh-issue-106948.K_JQ7j.rst +++ /dev/null @@ -1 +0,0 @@ -Add a number of standard external names to ``nitpick_ignore``. diff --git a/Misc/NEWS.d/next/Documentation/2023-07-22-15-14-13.gh-issue-107008.3JQ1Vt.rst b/Misc/NEWS.d/next/Documentation/2023-07-22-15-14-13.gh-issue-107008.3JQ1Vt.rst deleted file mode 100644 index a0fa27ec10303e..00000000000000 --- a/Misc/NEWS.d/next/Documentation/2023-07-22-15-14-13.gh-issue-107008.3JQ1Vt.rst +++ /dev/null @@ -1,2 +0,0 @@ -Document the :mod:`curses` module variables :const:`~curses.LINES` and -:const:`~curses.COLS`. diff --git a/Misc/NEWS.d/next/Documentation/2023-07-26-16-33-04.gh-issue-107305.qB2LS4.rst b/Misc/NEWS.d/next/Documentation/2023-07-26-16-33-04.gh-issue-107305.qB2LS4.rst deleted file mode 100644 index 038f9e68a5422a..00000000000000 --- a/Misc/NEWS.d/next/Documentation/2023-07-26-16-33-04.gh-issue-107305.qB2LS4.rst +++ /dev/null @@ -1,3 +0,0 @@ -Add documentation for :c:type:`PyInterpreterConfig` and -:c:func:`Py_NewInterpreterFromConfig`. Also clarify some of the nearby docs -relative to per-interpreter GIL. diff --git a/Misc/NEWS.d/next/Documentation/2023-10-23-23-43-43.gh-issue-110746.yg77IE.rst b/Misc/NEWS.d/next/Documentation/2023-10-23-23-43-43.gh-issue-110746.yg77IE.rst new file mode 100644 index 00000000000000..215db7beb75dcf --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2023-10-23-23-43-43.gh-issue-110746.yg77IE.rst @@ -0,0 +1 @@ +Improved markup for valid options/values for methods ttk.treeview.column and ttk.treeview.heading, and for Layouts. diff --git a/Misc/NEWS.d/next/Documentation/2023-11-30-02-33-59.gh-issue-111699._O5G_y.rst b/Misc/NEWS.d/next/Documentation/2023-11-30-02-33-59.gh-issue-111699._O5G_y.rst new file mode 100644 index 00000000000000..2d31345e6c2044 --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2023-11-30-02-33-59.gh-issue-111699._O5G_y.rst @@ -0,0 +1 @@ +Relocate ``smtpd`` deprecation notice to its own section rather than under ``locale`` in What's New in Python 3.12 document diff --git a/Misc/NEWS.d/next/IDLE/2019-12-13-12-26-56.bpo-13586.1grqsR.rst b/Misc/NEWS.d/next/IDLE/2019-12-13-12-26-56.bpo-13586.1grqsR.rst new file mode 100644 index 00000000000000..1a73cad175c888 --- /dev/null +++ b/Misc/NEWS.d/next/IDLE/2019-12-13-12-26-56.bpo-13586.1grqsR.rst @@ -0,0 +1 @@ +Enter the selected text when opening the "Replace" dialog. diff --git a/Misc/NEWS.d/next/IDLE/2023-05-23-17-19-49.gh-issue-104719.rvYXH-.rst b/Misc/NEWS.d/next/IDLE/2023-05-23-17-19-49.gh-issue-104719.rvYXH-.rst deleted file mode 100644 index 3fbe04ba4f6844..00000000000000 --- a/Misc/NEWS.d/next/IDLE/2023-05-23-17-19-49.gh-issue-104719.rvYXH-.rst +++ /dev/null @@ -1,2 +0,0 @@ -Remove IDLE's modification of tokenize.tabsize and test other uses of -tokenize data and methods. diff --git a/Misc/NEWS.d/next/IDLE/2023-12-10-20-01-11.gh-issue-112898.98aWv2.rst b/Misc/NEWS.d/next/IDLE/2023-12-10-20-01-11.gh-issue-112898.98aWv2.rst new file mode 100644 index 00000000000000..1c20e46b1e5f7b --- /dev/null +++ b/Misc/NEWS.d/next/IDLE/2023-12-10-20-01-11.gh-issue-112898.98aWv2.rst @@ -0,0 +1 @@ +Fix processing unsaved files when quitting IDLE on macOS. diff --git a/Misc/NEWS.d/next/IDLE/2023-12-19-00-03-12.gh-issue-113269.lrU-IC.rst b/Misc/NEWS.d/next/IDLE/2023-12-19-00-03-12.gh-issue-113269.lrU-IC.rst new file mode 100644 index 00000000000000..72e75b7910e359 --- /dev/null +++ b/Misc/NEWS.d/next/IDLE/2023-12-19-00-03-12.gh-issue-113269.lrU-IC.rst @@ -0,0 +1 @@ +Fix test_editor hang on macOS Catalina. diff --git a/Misc/NEWS.d/next/IDLE/2024-01-05-12-24-01.gh-issue-113729.qpluea.rst b/Misc/NEWS.d/next/IDLE/2024-01-05-12-24-01.gh-issue-113729.qpluea.rst new file mode 100644 index 00000000000000..ecba30c894c34e --- /dev/null +++ b/Misc/NEWS.d/next/IDLE/2024-01-05-12-24-01.gh-issue-113729.qpluea.rst @@ -0,0 +1 @@ +Fix the "Help -> IDLE Doc" menu bug in 3.11.7 and 3.12.1. diff --git a/Misc/NEWS.d/next/Library/2019-02-12-16-12-54.bpo-21360.gkSSfx.rst b/Misc/NEWS.d/next/Library/2019-02-12-16-12-54.bpo-21360.gkSSfx.rst new file mode 100644 index 00000000000000..bc32b9fe4199f9 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-02-12-16-12-54.bpo-21360.gkSSfx.rst @@ -0,0 +1 @@ +:class:`mailbox.Maildir` now ignores files with a leading dot. diff --git a/Misc/NEWS.d/next/Library/2019-05-08-13-14-11.bpo-29779.jg33dp.rst b/Misc/NEWS.d/next/Library/2019-05-08-13-14-11.bpo-29779.jg33dp.rst new file mode 100644 index 00000000000000..49d0ba98c4a641 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-05-08-13-14-11.bpo-29779.jg33dp.rst @@ -0,0 +1,2 @@ +Add a new :envvar:`PYTHON_HISTORY` environment variable to set the location +of a ``.python_history`` file. diff --git a/Misc/NEWS.d/next/Library/2019-05-17-07-22-33.bpo-18060.5mqTQM.rst b/Misc/NEWS.d/next/Library/2019-05-17-07-22-33.bpo-18060.5mqTQM.rst new file mode 100644 index 00000000000000..3fefbc3efb63c0 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-05-17-07-22-33.bpo-18060.5mqTQM.rst @@ -0,0 +1,2 @@ +Fixed a class inheritance issue that can cause segfaults when deriving two or more levels of subclasses from a base class of Structure or Union. + diff --git a/Misc/NEWS.d/next/Library/2019-05-18-15-50-14.bpo-36959.ew6WZ4.rst b/Misc/NEWS.d/next/Library/2019-05-18-15-50-14.bpo-36959.ew6WZ4.rst new file mode 100644 index 00000000000000..1ac05a730a2086 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-05-18-15-50-14.bpo-36959.ew6WZ4.rst @@ -0,0 +1,2 @@ +Fix some error messages for invalid ISO format string combinations in ``strptime()`` that referred to directives not contained in the format string. +Patch by Gordon P. Hemsley. diff --git a/Misc/NEWS.d/next/Library/2019-06-14-22-37-32.bpo-37260.oecdIf.rst b/Misc/NEWS.d/next/Library/2019-06-14-22-37-32.bpo-37260.oecdIf.rst new file mode 100644 index 00000000000000..a5f2c5e8e18919 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-06-14-22-37-32.bpo-37260.oecdIf.rst @@ -0,0 +1,2 @@ +Fixed a race condition in :func:`shutil.rmtree` in which directory entries removed by another process or thread while ``shutil.rmtree()`` is running can cause it to raise FileNotFoundError. Patch by Jeffrey Kintscher. + diff --git a/Misc/NEWS.d/next/Library/2019-09-13-13-28-10.bpo-17013.NWcgE3.rst b/Misc/NEWS.d/next/Library/2019-09-13-13-28-10.bpo-17013.NWcgE3.rst deleted file mode 100644 index ac746c45fa9ea8..00000000000000 --- a/Misc/NEWS.d/next/Library/2019-09-13-13-28-10.bpo-17013.NWcgE3.rst +++ /dev/null @@ -1,3 +0,0 @@ -Add ``ThreadingMock`` to :mod:`unittest.mock` that can be used to create -Mock objects that can wait until they are called. Patch by Karthikeyan -Singaravelan and Mario Corchero. diff --git a/Misc/NEWS.d/next/Library/2020-03-09-15-08-29.bpo-39912.xPOBBY.rst b/Misc/NEWS.d/next/Library/2020-03-09-15-08-29.bpo-39912.xPOBBY.rst new file mode 100644 index 00000000000000..fb8579725a2d7d --- /dev/null +++ b/Misc/NEWS.d/next/Library/2020-03-09-15-08-29.bpo-39912.xPOBBY.rst @@ -0,0 +1,3 @@ +:func:`warnings.filterwarnings()` and :func:`warnings.simplefilter()` now raise +appropriate exceptions instead of ``AssertionError``. Patch contributed by +Rémi Lapeyre. diff --git a/Misc/NEWS.d/next/Library/2020-05-03-00-33-15.bpo-18319.faPTlx.rst b/Misc/NEWS.d/next/Library/2020-05-03-00-33-15.bpo-18319.faPTlx.rst deleted file mode 100644 index a1a4cf6d63725a..00000000000000 --- a/Misc/NEWS.d/next/Library/2020-05-03-00-33-15.bpo-18319.faPTlx.rst +++ /dev/null @@ -1,2 +0,0 @@ -Ensure `gettext(msg)` retrieve translations even if a plural form exists. In -other words: `gettext(msg) == ngettext(msg, '', 1)`. diff --git a/Misc/NEWS.d/next/Library/2020-05-21-23-32-46.bpo-40262.z4fQv1.rst b/Misc/NEWS.d/next/Library/2020-05-21-23-32-46.bpo-40262.z4fQv1.rst new file mode 100644 index 00000000000000..c017a1c8df09d8 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2020-05-21-23-32-46.bpo-40262.z4fQv1.rst @@ -0,0 +1,2 @@ +The :meth:`ssl.SSLSocket.recv_into` method no longer requires the *buffer* +argument to implement ``__len__`` and supports buffers with arbitrary item size. diff --git a/Misc/NEWS.d/next/Library/2020-06-15-23-44-53.bpo-19821.ihBk39.rst b/Misc/NEWS.d/next/Library/2020-06-15-23-44-53.bpo-19821.ihBk39.rst new file mode 100644 index 00000000000000..ede68106b56ff8 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2020-06-15-23-44-53.bpo-19821.ihBk39.rst @@ -0,0 +1 @@ +The :func:`!pydoc.ispackage` function has been deprecated. diff --git a/Misc/NEWS.d/next/Library/2020-07-28-20-48-05.bpo-41422.iMwnMu.rst b/Misc/NEWS.d/next/Library/2020-07-28-20-48-05.bpo-41422.iMwnMu.rst new file mode 100644 index 00000000000000..8bde68f8f2afc8 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2020-07-28-20-48-05.bpo-41422.iMwnMu.rst @@ -0,0 +1,2 @@ +Fixed memory leaks of :class:`pickle.Pickler` and :class:`pickle.Unpickler` involving cyclic references via the +internal memo mapping. diff --git a/Misc/NEWS.d/next/Library/2020-08-06-14-43-55.bpo-26791.KxoEfO.rst b/Misc/NEWS.d/next/Library/2020-08-06-14-43-55.bpo-26791.KxoEfO.rst new file mode 100644 index 00000000000000..c6f8dcb6f9269c --- /dev/null +++ b/Misc/NEWS.d/next/Library/2020-08-06-14-43-55.bpo-26791.KxoEfO.rst @@ -0,0 +1,4 @@ +:func:`shutil.move` now moves a symlink into a directory when that +directory is the target of the symlink. This provides the same behavior as +the mv shell command. The previous behavior raised an exception. Patch by +Jeffrey Kintscher. diff --git a/Misc/NEWS.d/next/Library/2020-09-16-16-53-06.bpo-41768.8_fWkC.rst b/Misc/NEWS.d/next/Library/2020-09-16-16-53-06.bpo-41768.8_fWkC.rst deleted file mode 100644 index bfd3a294d44efa..00000000000000 --- a/Misc/NEWS.d/next/Library/2020-09-16-16-53-06.bpo-41768.8_fWkC.rst +++ /dev/null @@ -1,2 +0,0 @@ -:mod:`unittest.mock` speccing no longer calls class properties. -Patch by Melanie Witt. diff --git a/Misc/NEWS.d/next/Library/2020-10-03-23-47-28.bpo-35928.E0iPAa.rst b/Misc/NEWS.d/next/Library/2020-10-03-23-47-28.bpo-35928.E0iPAa.rst new file mode 100644 index 00000000000000..c63e616458a356 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2020-10-03-23-47-28.bpo-35928.E0iPAa.rst @@ -0,0 +1,2 @@ +:class:`io.TextIOWrapper` now correctly handles the decoding buffer after +``read()`` and ``write()``. diff --git a/Misc/NEWS.d/next/Library/2020-12-14-09-31-13.bpo-35332.s22wAx.rst b/Misc/NEWS.d/next/Library/2020-12-14-09-31-13.bpo-35332.s22wAx.rst new file mode 100644 index 00000000000000..80564b99a079c6 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2020-12-14-09-31-13.bpo-35332.s22wAx.rst @@ -0,0 +1,3 @@ +The :func:`shutil.rmtree` function now ignores errors when calling +:func:`os.close` when *ignore_errors* is ``True``, and +:func:`os.close` no longer retried after error. diff --git a/Misc/NEWS.d/next/Library/2021-06-24-20-45-03.bpo-44185.ZHb8yJ.rst b/Misc/NEWS.d/next/Library/2021-06-24-20-45-03.bpo-44185.ZHb8yJ.rst deleted file mode 100644 index 056ab8d93515fb..00000000000000 --- a/Misc/NEWS.d/next/Library/2021-06-24-20-45-03.bpo-44185.ZHb8yJ.rst +++ /dev/null @@ -1,3 +0,0 @@ -:func:`unittest.mock.mock_open` will call the :func:`close` method of the file -handle mock when it is exiting from the context manager. -Patch by Samet Yaslan. diff --git a/Misc/NEWS.d/next/Library/2021-08-16-17-52-26.bpo-44850.r8jx5u.rst b/Misc/NEWS.d/next/Library/2021-08-16-17-52-26.bpo-44850.r8jx5u.rst deleted file mode 100644 index 1fe5497f856e90..00000000000000 --- a/Misc/NEWS.d/next/Library/2021-08-16-17-52-26.bpo-44850.r8jx5u.rst +++ /dev/null @@ -1,2 +0,0 @@ -Improve performance of :func:`operator.methodcaller` using the :pep:`590` ``vectorcall`` convention. -Patch by Anthony Lee and Pieter Eendebak. diff --git a/Misc/NEWS.d/next/Library/2021-10-31-16-06-28.bpo-43633.vflwXv.rst b/Misc/NEWS.d/next/Library/2021-10-31-16-06-28.bpo-43633.vflwXv.rst deleted file mode 100644 index 025de1e1a7d6ef..00000000000000 --- a/Misc/NEWS.d/next/Library/2021-10-31-16-06-28.bpo-43633.vflwXv.rst +++ /dev/null @@ -1 +0,0 @@ -Improve the textual representation of IPv4-mapped IPv6 addresses (:rfc:`4291` Sections 2.2, 2.5.5.2) in :mod:`ipaddress`. Patch by Oleksandr Pavliuk. diff --git a/Misc/NEWS.d/next/Library/2021-11-23-22-22-49.bpo-32731.kNOASr.rst b/Misc/NEWS.d/next/Library/2021-11-23-22-22-49.bpo-32731.kNOASr.rst new file mode 100644 index 00000000000000..92f3b870c11131 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-11-23-22-22-49.bpo-32731.kNOASr.rst @@ -0,0 +1,3 @@ +:func:`getpass.getuser` now raises :exc:`OSError` for all failures rather +than :exc:`ImportError` on systems lacking the :mod:`pwd` module or +:exc:`KeyError` if the password database is empty. diff --git a/Misc/NEWS.d/next/Library/2021-12-06-22-10-53.bpo-43153.J7mjSy.rst b/Misc/NEWS.d/next/Library/2021-12-06-22-10-53.bpo-43153.J7mjSy.rst new file mode 100644 index 00000000000000..7800e0a4869adf --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-12-06-22-10-53.bpo-43153.J7mjSy.rst @@ -0,0 +1,4 @@ +On Windows, ``tempfile.TemporaryDirectory`` previously masked a +``PermissionError`` with ``NotADirectoryError`` during directory cleanup. It +now correctly raises ``PermissionError`` if errors are not ignored. Patch by +Andrei Kulakov and Ken Jin. diff --git a/Misc/NEWS.d/next/Library/2022-05-17-10-46-44.gh-issue-92871.GVogrT.rst b/Misc/NEWS.d/next/Library/2022-05-17-10-46-44.gh-issue-92871.GVogrT.rst deleted file mode 100644 index 992f8afadbe912..00000000000000 --- a/Misc/NEWS.d/next/Library/2022-05-17-10-46-44.gh-issue-92871.GVogrT.rst +++ /dev/null @@ -1,2 +0,0 @@ -Remove the ``typing.io`` and ``typing.re`` namespaces, deprecated since Python -3.8. All items are still available from the main :mod:`typing` module. diff --git a/Misc/NEWS.d/next/Library/2022-07-12-18-45-13.gh-issue-94777.mOybx7.rst b/Misc/NEWS.d/next/Library/2022-07-12-18-45-13.gh-issue-94777.mOybx7.rst deleted file mode 100644 index 2c04a35fbfce13..00000000000000 --- a/Misc/NEWS.d/next/Library/2022-07-12-18-45-13.gh-issue-94777.mOybx7.rst +++ /dev/null @@ -1 +0,0 @@ -Fix hanging :mod:`multiprocessing` ``ProcessPoolExecutor`` when a child process crashes while data is being written in the call queue. diff --git a/Misc/NEWS.d/next/Library/2022-07-18-14-20-56.gh-issue-94924.X0buz2.rst b/Misc/NEWS.d/next/Library/2022-07-18-14-20-56.gh-issue-94924.X0buz2.rst deleted file mode 100644 index 7882f224e75ad5..00000000000000 --- a/Misc/NEWS.d/next/Library/2022-07-18-14-20-56.gh-issue-94924.X0buz2.rst +++ /dev/null @@ -1 +0,0 @@ -:func:`unittest.mock.create_autospec` now properly returns coroutine functions compatible with :func:`inspect.iscoroutinefunction` diff --git a/Misc/NEWS.d/next/Library/2022-08-07-11-10-26.gh-issue-80480.IFccj3.rst b/Misc/NEWS.d/next/Library/2022-08-07-11-10-26.gh-issue-80480.IFccj3.rst deleted file mode 100644 index 2d4956ffa08035..00000000000000 --- a/Misc/NEWS.d/next/Library/2022-08-07-11-10-26.gh-issue-80480.IFccj3.rst +++ /dev/null @@ -1,2 +0,0 @@ -Emit :exc:`DeprecationWarning` for :mod:`array`'s ``'u'`` type code, -deprecated in docs since Python 3.3. diff --git a/Misc/NEWS.d/next/Library/2022-12-01-16-57-44.gh-issue-91133.LKMVCV.rst b/Misc/NEWS.d/next/Library/2022-12-01-16-57-44.gh-issue-91133.LKMVCV.rst new file mode 100644 index 00000000000000..7991048fc48e03 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-12-01-16-57-44.gh-issue-91133.LKMVCV.rst @@ -0,0 +1,2 @@ +Fix a bug in :class:`tempfile.TemporaryDirectory` cleanup, which now no longer +dereferences symlinks when working around file system permission errors. diff --git a/Misc/NEWS.d/next/Library/2023-02-08-00-43-29.gh-issue-83162.ufdI9F.rst b/Misc/NEWS.d/next/Library/2023-02-08-00-43-29.gh-issue-83162.ufdI9F.rst new file mode 100644 index 00000000000000..6074dd7f101a6d --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-02-08-00-43-29.gh-issue-83162.ufdI9F.rst @@ -0,0 +1,3 @@ +Renamed :exc:`!re.error` to :exc:`PatternError` for clarity, and kept +:exc:`!re.error` for backward compatibility. Patch by Matthias Bussonnier and +Adam Chhina. diff --git a/Misc/NEWS.d/next/Library/2023-02-17-18-56-46.gh-issue-73435.7sTJHk.rst b/Misc/NEWS.d/next/Library/2023-02-17-18-56-46.gh-issue-73435.7sTJHk.rst deleted file mode 100644 index d5a2ae07700b34..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-02-17-18-56-46.gh-issue-73435.7sTJHk.rst +++ /dev/null @@ -1 +0,0 @@ -Add support for recursive wildcards in :meth:`pathlib.PurePath.match`. diff --git a/Misc/NEWS.d/next/Library/2023-02-18-22-55-48.gh-issue-102024.RUmg_D.rst b/Misc/NEWS.d/next/Library/2023-02-18-22-55-48.gh-issue-102024.RUmg_D.rst deleted file mode 100644 index bb9e28e06c5554..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-02-18-22-55-48.gh-issue-102024.RUmg_D.rst +++ /dev/null @@ -1 +0,0 @@ -Reduce calls of ``_idle_semaphore.release()`` in :func:`concurrent.futures.thread._worker`. diff --git a/Misc/NEWS.d/next/Library/2023-03-08-19-30-53.gh-issue-102120.xkQ5Wr.rst b/Misc/NEWS.d/next/Library/2023-03-08-19-30-53.gh-issue-102120.xkQ5Wr.rst deleted file mode 100644 index ca50242fdbe293..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-03-08-19-30-53.gh-issue-102120.xkQ5Wr.rst +++ /dev/null @@ -1,2 +0,0 @@ -Added a stream mode to ``tarfile`` that allows for reading -archives without caching info about the inner files. diff --git a/Misc/NEWS.d/next/Library/2023-03-12-01-17-15.gh-issue-102541.LK1adc.rst b/Misc/NEWS.d/next/Library/2023-03-12-01-17-15.gh-issue-102541.LK1adc.rst deleted file mode 100644 index 45b10679e19e2d..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-03-12-01-17-15.gh-issue-102541.LK1adc.rst +++ /dev/null @@ -1 +0,0 @@ -Hide traceback in :func:`help` prompt, when import failed. diff --git a/Misc/NEWS.d/next/Library/2023-03-12-03-37-03.gh-issue-77609.aOQttm.rst b/Misc/NEWS.d/next/Library/2023-03-12-03-37-03.gh-issue-77609.aOQttm.rst deleted file mode 100644 index 35e61088de58a6..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-03-12-03-37-03.gh-issue-77609.aOQttm.rst +++ /dev/null @@ -1,2 +0,0 @@ -Add *follow_symlinks* argument to :meth:`pathlib.Path.glob` and -:meth:`~pathlib.Path.rglob`, defaulting to false. diff --git a/Misc/NEWS.d/next/Library/2023-04-03-08-09-40.gh-issue-103200.lq1Etz.rst b/Misc/NEWS.d/next/Library/2023-04-03-08-09-40.gh-issue-103200.lq1Etz.rst deleted file mode 100644 index e264e0c81d3d90..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-04-03-08-09-40.gh-issue-103200.lq1Etz.rst +++ /dev/null @@ -1 +0,0 @@ -Fix cache repopulation semantics of zipimport.invalidate_caches(). The cache is now repopulated upon retrieving files with an invalid cache, not when the cache is invalidated. diff --git a/Misc/NEWS.d/next/Library/2023-04-09-03-53-02.gh-issue-103124.JspiNN.rst b/Misc/NEWS.d/next/Library/2023-04-09-03-53-02.gh-issue-103124.JspiNN.rst deleted file mode 100644 index 022524b369aa10..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-04-09-03-53-02.gh-issue-103124.JspiNN.rst +++ /dev/null @@ -1 +0,0 @@ -Added multiline statement support for :mod:`pdb` diff --git a/Misc/NEWS.d/next/Library/2023-04-09-21-05-43.gh-issue-66515.0DS8Ya.rst b/Misc/NEWS.d/next/Library/2023-04-09-21-05-43.gh-issue-66515.0DS8Ya.rst new file mode 100644 index 00000000000000..b9c52f3b8db52c --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-04-09-21-05-43.gh-issue-66515.0DS8Ya.rst @@ -0,0 +1,3 @@ +:class:`mailbox.MH` now supports folders that do not contain a +``.mh_sequences`` file (e.g. Claws Mail IMAP-cache folders). Patch by Serhiy +Storchaka. diff --git a/Misc/NEWS.d/next/Library/2023-04-12-03-03-27.gh-issue-103464.Oa_8IW.rst b/Misc/NEWS.d/next/Library/2023-04-12-03-03-27.gh-issue-103464.Oa_8IW.rst deleted file mode 100644 index 6afaeb6485ee40..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-04-12-03-03-27.gh-issue-103464.Oa_8IW.rst +++ /dev/null @@ -1 +0,0 @@ -Provide helpful usage messages when parsing incorrect :mod:`pdb` commands. diff --git a/Misc/NEWS.d/next/Library/2023-04-15-23-26-16.gh-issue-103558.w9OzK4.rst b/Misc/NEWS.d/next/Library/2023-04-15-23-26-16.gh-issue-103558.w9OzK4.rst deleted file mode 100644 index e62af647fcc96a..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-04-15-23-26-16.gh-issue-103558.w9OzK4.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed ``parent`` argument validation mechanism of :mod:`argparse`. Improved test coverage. diff --git a/Misc/NEWS.d/next/Library/2023-04-23-11-08-02.gh-issue-103708.Y17C7p.rst b/Misc/NEWS.d/next/Library/2023-04-23-11-08-02.gh-issue-103708.Y17C7p.rst new file mode 100644 index 00000000000000..4b7d747175df03 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-04-23-11-08-02.gh-issue-103708.Y17C7p.rst @@ -0,0 +1 @@ +Make hardcoded python name, a configurable parameter so that different implementations of python can override it instead of making huge diffs in sysconfig.py diff --git a/Misc/NEWS.d/next/Library/2023-04-28-09-31-21.gh-issue-102676.J8qDRa.rst b/Misc/NEWS.d/next/Library/2023-04-28-09-31-21.gh-issue-102676.J8qDRa.rst deleted file mode 100644 index eef89645aa533f..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-04-28-09-31-21.gh-issue-102676.J8qDRa.rst +++ /dev/null @@ -1,3 +0,0 @@ -Add fields ``start_offset``, ``cache_offset``, ``end_offset``, -``baseopname``, ``baseopcode``, ``jump_target`` and ``oparg`` to -:class:`dis.Instruction`. diff --git a/Misc/NEWS.d/next/Library/2023-04-29-20-49-13.gh-issue-104003.-8Ruk2.rst b/Misc/NEWS.d/next/Library/2023-04-29-20-49-13.gh-issue-104003.-8Ruk2.rst new file mode 100644 index 00000000000000..82d61ca8b8bc97 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-04-29-20-49-13.gh-issue-104003.-8Ruk2.rst @@ -0,0 +1,3 @@ +Add :func:`warnings.deprecated`, a decorator to mark deprecated functions to +static type checkers and to warn on usage of deprecated classes and functions. +See :pep:`702`. Patch by Jelle Zijlstra. diff --git a/Misc/NEWS.d/next/Library/2023-05-11-23-03-00.gh-issue-104399.MMatTP.rst b/Misc/NEWS.d/next/Library/2023-05-11-23-03-00.gh-issue-104399.MMatTP.rst deleted file mode 100644 index 84cc888635b415..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-05-11-23-03-00.gh-issue-104399.MMatTP.rst +++ /dev/null @@ -1,4 +0,0 @@ -Prepare the ``_tkinter`` module for building with Tcl 9.0 and future -libtommath by replacing usage of deprecated functions -:c:func:`mp_to_unsigned_bin_n` and :c:func:`mp_unsigned_bin_size` -when necessary. diff --git a/Misc/NEWS.d/next/Library/2023-05-15-18-57-42.gh-issue-102613.YD9yx-.rst b/Misc/NEWS.d/next/Library/2023-05-15-18-57-42.gh-issue-102613.YD9yx-.rst deleted file mode 100644 index 841a9e1e26d317..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-05-15-18-57-42.gh-issue-102613.YD9yx-.rst +++ /dev/null @@ -1,4 +0,0 @@ -Improve performance of :meth:`pathlib.Path.glob` when expanding a pattern with -a non-terminal "``**``" component by filtering walked paths through a regular -expression, rather than calling :func:`os.scandir` more than once on each -directory. diff --git a/Misc/NEWS.d/next/Library/2023-05-19-19-46-22.gh-issue-99108.wqCg0t.rst b/Misc/NEWS.d/next/Library/2023-05-19-19-46-22.gh-issue-99108.wqCg0t.rst deleted file mode 100644 index b595f1893609cc..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-05-19-19-46-22.gh-issue-99108.wqCg0t.rst +++ /dev/null @@ -1,3 +0,0 @@ -We now release the GIL around built-in :mod:`hashlib` computations of -reasonable size for the SHA families and MD5 hash functions, matching -what our OpenSSL backed hash computations already does. diff --git a/Misc/NEWS.d/next/Library/2023-05-22-18-39-53.gh-issue-104372.7tDRaK.rst b/Misc/NEWS.d/next/Library/2023-05-22-18-39-53.gh-issue-104372.7tDRaK.rst deleted file mode 100644 index ea13ec85543ca2..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-05-22-18-39-53.gh-issue-104372.7tDRaK.rst +++ /dev/null @@ -1,5 +0,0 @@ -On Linux where :mod:`subprocess` can use the ``vfork()`` syscall for faster -spawning, prevent the parent process from blocking other threads by dropping -the GIL while it waits for the vfork'ed child process ``exec()`` outcome. -This prevents spawning a binary from a slow filesystem from blocking the -rest of the application. diff --git a/Misc/NEWS.d/next/Library/2023-05-23-01-37-40.gh-issue-104773.8c-GsG.rst b/Misc/NEWS.d/next/Library/2023-05-23-01-37-40.gh-issue-104773.8c-GsG.rst deleted file mode 100644 index 228916158534b2..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-05-23-01-37-40.gh-issue-104773.8c-GsG.rst +++ /dev/null @@ -1,2 +0,0 @@ -:pep:`594`: Remove the :mod:`!sndhdr` module, deprecated in Python 3.11. -Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/Library/2023-05-23-01-47-57.gh-issue-104773.I6MQhb.rst b/Misc/NEWS.d/next/Library/2023-05-23-01-47-57.gh-issue-104773.I6MQhb.rst deleted file mode 100644 index 42f7a5286867cd..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-05-23-01-47-57.gh-issue-104773.I6MQhb.rst +++ /dev/null @@ -1,2 +0,0 @@ -:pep:`594`: Remove the :mod:`!cgi`` and :mod:`!cgitb` modules, deprecated in -Python 3.11. Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/Library/2023-05-23-02-13-11.gh-issue-104773.JNiEjv.rst b/Misc/NEWS.d/next/Library/2023-05-23-02-13-11.gh-issue-104773.JNiEjv.rst deleted file mode 100644 index 213b6f5b764258..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-05-23-02-13-11.gh-issue-104773.JNiEjv.rst +++ /dev/null @@ -1,2 +0,0 @@ -:pep:`594`: Remove the :mod:`!imghdr` module, deprecated in Python 3.11. -Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/Library/2023-05-23-02-20-13.gh-issue-104773.7K59zr.rst b/Misc/NEWS.d/next/Library/2023-05-23-02-20-13.gh-issue-104773.7K59zr.rst deleted file mode 100644 index 0f3162ef509a82..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-05-23-02-20-13.gh-issue-104773.7K59zr.rst +++ /dev/null @@ -1,2 +0,0 @@ -:pep:`594`: Remove the :mod:`!telnetlib` module, deprecated in Python 3.11. -Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/Library/2023-05-23-03-36-47.gh-issue-104780.P4e3Yf.rst b/Misc/NEWS.d/next/Library/2023-05-23-03-36-47.gh-issue-104780.P4e3Yf.rst deleted file mode 100644 index acdca53b4bb7d4..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-05-23-03-36-47.gh-issue-104780.P4e3Yf.rst +++ /dev/null @@ -1,2 +0,0 @@ -Remove the ``2to3`` program and the :mod:`!lib2to3` module, deprecated in -Python 3.11. Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/Library/2023-05-23-04-01-27.gh-issue-104783.QyhIoq.rst b/Misc/NEWS.d/next/Library/2023-05-23-04-01-27.gh-issue-104783.QyhIoq.rst deleted file mode 100644 index 23670e8fe14d3d..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-05-23-04-01-27.gh-issue-104783.QyhIoq.rst +++ /dev/null @@ -1,2 +0,0 @@ -Remove ``locale.resetlocale()`` function deprecated in Python 3.11. -Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/Library/2023-05-23-17-43-52.gh-issue-104797.NR7KzF.rst b/Misc/NEWS.d/next/Library/2023-05-23-17-43-52.gh-issue-104797.NR7KzF.rst deleted file mode 100644 index 60c9a0601cdc9a..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-05-23-17-43-52.gh-issue-104797.NR7KzF.rst +++ /dev/null @@ -1,2 +0,0 @@ -Allow :class:`typing.Protocol` classes to inherit from -:class:`collections.abc.Buffer`. Patch by Jelle Zijlstra. diff --git a/Misc/NEWS.d/next/Library/2023-05-23-18-31-49.gh-issue-104799.MJYOw6.rst b/Misc/NEWS.d/next/Library/2023-05-23-18-31-49.gh-issue-104799.MJYOw6.rst deleted file mode 100644 index 614918d7572969..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-05-23-18-31-49.gh-issue-104799.MJYOw6.rst +++ /dev/null @@ -1,4 +0,0 @@ -Adjust the location of the (see :pep:`695`) ``type_params`` field on -:class:`ast.ClassDef`, :class:`ast.AsyncFunctionDef`, and -:class:`ast.FunctionDef` to better preserve backward compatibility. Patch by -Jelle Zijlstra diff --git a/Misc/NEWS.d/next/Library/2023-05-23-19-53-18.gh-issue-83863.eRI5JG.rst b/Misc/NEWS.d/next/Library/2023-05-23-19-53-18.gh-issue-83863.eRI5JG.rst deleted file mode 100644 index 7a073aa37dd6ae..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-05-23-19-53-18.gh-issue-83863.eRI5JG.rst +++ /dev/null @@ -1,4 +0,0 @@ -Support for using :class:`pathlib.Path` objects as context managers has been -removed. Before Python 3.9, exiting the context manager marked a path as -"closed", which caused some (but not all!) methods to raise when called. -Since Python 3.9, using a path as a context manager does nothing. diff --git a/Misc/NEWS.d/next/Library/2023-05-23-21-25-54.gh-issue-104804.78fiE6.rst b/Misc/NEWS.d/next/Library/2023-05-23-21-25-54.gh-issue-104804.78fiE6.rst deleted file mode 100644 index 78409cf7cbc9dd..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-05-23-21-25-54.gh-issue-104804.78fiE6.rst +++ /dev/null @@ -1,2 +0,0 @@ -Remove the untested and undocumented :mod:`webbrowser` :class:`!MacOSX` class, deprecated in Python 3.11. -Patch by Hugo van Kemenade. diff --git a/Misc/NEWS.d/next/Library/2023-05-24-08-45-04.gh-issue-104835.bN_B-B.rst b/Misc/NEWS.d/next/Library/2023-05-24-08-45-04.gh-issue-104835.bN_B-B.rst deleted file mode 100644 index f8e979b47392f4..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-05-24-08-45-04.gh-issue-104835.bN_B-B.rst +++ /dev/null @@ -1,13 +0,0 @@ -Removed the following :mod:`unittest` functions, deprecated in Python 3.11: - -* :func:`!unittest.findTestCases` -* :func:`!unittest.makeSuite` -* :func:`!unittest.getTestCaseNames` - -Use :class:`~unittest.TestLoader` methods instead: - -* :meth:`unittest.TestLoader.loadTestsFromModule` -* :meth:`unittest.TestLoader.loadTestsFromTestCase` -* :meth:`unittest.TestLoader.getTestCaseNames` - -Patch by Hugo van Kemenade. diff --git a/Misc/NEWS.d/next/Library/2023-05-24-09-34-23.gh-issue-104874.oqyJSy.rst b/Misc/NEWS.d/next/Library/2023-05-24-09-34-23.gh-issue-104874.oqyJSy.rst deleted file mode 100644 index 9d5904bc146421..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-05-24-09-34-23.gh-issue-104874.oqyJSy.rst +++ /dev/null @@ -1,2 +0,0 @@ -Document the ``__name__`` and ``__supertype__`` attributes of -:class:`typing.NewType`. Patch by Jelle Zijlstra. diff --git a/Misc/NEWS.d/next/Library/2023-05-24-09-55-33.gh-issue-104873.BKQ54y.rst b/Misc/NEWS.d/next/Library/2023-05-24-09-55-33.gh-issue-104873.BKQ54y.rst deleted file mode 100644 index c901d83812f176..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-05-24-09-55-33.gh-issue-104873.BKQ54y.rst +++ /dev/null @@ -1,3 +0,0 @@ -Add :func:`typing.get_protocol_members` to return the set of members -defining a :class:`typing.Protocol`. Add :func:`typing.is_protocol` to -check whether a class is a :class:`typing.Protocol`. Patch by Jelle Zijlstra. diff --git a/Misc/NEWS.d/next/Library/2023-05-24-11-45-22.gh-issue-104773.R0Br4-.rst b/Misc/NEWS.d/next/Library/2023-05-24-11-45-22.gh-issue-104773.R0Br4-.rst deleted file mode 100644 index 31da29ec2a5928..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-05-24-11-45-22.gh-issue-104773.R0Br4-.rst +++ /dev/null @@ -1,2 +0,0 @@ -:pep:`594`: Remove the :mod:`!pipes` module, deprecated in Python 3.11. -Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/Library/2023-05-24-14-30-14.gh-issue-104780.nXGIJt.rst b/Misc/NEWS.d/next/Library/2023-05-24-14-30-14.gh-issue-104780.nXGIJt.rst deleted file mode 100644 index 62d63a6fb7605b..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-05-24-14-30-14.gh-issue-104780.nXGIJt.rst +++ /dev/null @@ -1,2 +0,0 @@ -:pep:`594`: Remove the :mod:`!ossaudiodev` module, deprecated in Python 3.11. -Patch Victor Stinner. diff --git a/Misc/NEWS.d/next/Library/2023-05-24-14-58-13.gh-issue-104773.sQaXrY.rst b/Misc/NEWS.d/next/Library/2023-05-24-14-58-13.gh-issue-104773.sQaXrY.rst deleted file mode 100644 index fc103cd9aa3982..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-05-24-14-58-13.gh-issue-104773.sQaXrY.rst +++ /dev/null @@ -1,2 +0,0 @@ -:pep:`594`: Remove the :mod:`!sunau` module, deprecated in Python 3.11. -Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/Library/2023-05-24-15-17-05.gh-issue-104773.EmFIQ5.rst b/Misc/NEWS.d/next/Library/2023-05-24-15-17-05.gh-issue-104773.EmFIQ5.rst deleted file mode 100644 index 95a99a20930c5a..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-05-24-15-17-05.gh-issue-104773.EmFIQ5.rst +++ /dev/null @@ -1,2 +0,0 @@ -:pep:`594`: Remove the :mod:`!mailcap` module, deprecated in Python 3.11. -Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/Library/2023-05-24-15-57-34.gh-issue-104773.IHWRgg.rst b/Misc/NEWS.d/next/Library/2023-05-24-15-57-34.gh-issue-104773.IHWRgg.rst deleted file mode 100644 index a2b2604f26d650..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-05-24-15-57-34.gh-issue-104773.IHWRgg.rst +++ /dev/null @@ -1,2 +0,0 @@ -:pep:`594`: Remove the :mod:`!chunk` module, deprecated in Python 3.11. -Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/Library/2023-05-24-17-22-56.gh-issue-75552._QlrpQ.rst b/Misc/NEWS.d/next/Library/2023-05-24-17-22-56.gh-issue-75552._QlrpQ.rst deleted file mode 100644 index e70712af97944f..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-05-24-17-22-56.gh-issue-75552._QlrpQ.rst +++ /dev/null @@ -1 +0,0 @@ -Removed the ``tkinter.tix`` module, deprecated since Python 3.6. diff --git a/Misc/NEWS.d/next/Library/2023-05-24-17-47-25.gh-issue-104773.TzUSY2.rst b/Misc/NEWS.d/next/Library/2023-05-24-17-47-25.gh-issue-104773.TzUSY2.rst deleted file mode 100644 index 22194895705664..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-05-24-17-47-25.gh-issue-104773.TzUSY2.rst +++ /dev/null @@ -1,3 +0,0 @@ -:pep:`594`: Remove the :mod:`!spwd` module, deprecated in Python 3.11: the -`python-pam project `_ can be used -instead. Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/Library/2023-05-24-18-48-10.gh-issue-104773.TrgUeO.rst b/Misc/NEWS.d/next/Library/2023-05-24-18-48-10.gh-issue-104773.TrgUeO.rst deleted file mode 100644 index 34f46d951abb89..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-05-24-18-48-10.gh-issue-104773.TrgUeO.rst +++ /dev/null @@ -1 +0,0 @@ -:pep:`594`: Removed the :mod:`!msilib` package, deprecated in Python 3.11. diff --git a/Misc/NEWS.d/next/Library/2023-05-24-19-48-16.gh-issue-104876.Z00Qnk.rst b/Misc/NEWS.d/next/Library/2023-05-24-19-48-16.gh-issue-104876.Z00Qnk.rst deleted file mode 100644 index ce1f5606415085..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-05-24-19-48-16.gh-issue-104876.Z00Qnk.rst +++ /dev/null @@ -1,3 +0,0 @@ -Remove the :meth:`!turtle.RawTurtle.settiltangle` method, deprecated in docs -since Python 3.1 and with a deprecation warning since Python 3.11. Patch by -Hugo van Kemenade. diff --git a/Misc/NEWS.d/next/Library/2023-05-24-20-21-27.gh-issue-104786.SmgT5_.rst b/Misc/NEWS.d/next/Library/2023-05-24-20-21-27.gh-issue-104786.SmgT5_.rst deleted file mode 100644 index aac669434ec266..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-05-24-20-21-27.gh-issue-104786.SmgT5_.rst +++ /dev/null @@ -1 +0,0 @@ -Remove kwargs-based :class:`typing.TypedDict` creation diff --git a/Misc/NEWS.d/next/Library/2023-05-24-21-30-40.gh-issue-104886.8TuV-_.rst b/Misc/NEWS.d/next/Library/2023-05-24-21-30-40.gh-issue-104886.8TuV-_.rst deleted file mode 100644 index 2f6796bed7b17c..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-05-24-21-30-40.gh-issue-104886.8TuV-_.rst +++ /dev/null @@ -1,3 +0,0 @@ -Remove the undocumented :class:`!configparser.LegacyInterpolation` class, -deprecated in the docstring since Python 3.2, and with a deprecation warning -since Python 3.11. Patch by Hugo van Kemenade. diff --git a/Misc/NEWS.d/next/Library/2023-05-24-22-22-03.gh-issue-104773.NwpjhZ.rst b/Misc/NEWS.d/next/Library/2023-05-24-22-22-03.gh-issue-104773.NwpjhZ.rst deleted file mode 100644 index f995375e0735f8..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-05-24-22-22-03.gh-issue-104773.NwpjhZ.rst +++ /dev/null @@ -1,2 +0,0 @@ -:pep:`594`: Remove the :mod:`!nntplib` module, deprecated in Python 3.11. -Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/Library/2023-05-24-22-47-13.gh-issue-104773.itOIf3.rst b/Misc/NEWS.d/next/Library/2023-05-24-22-47-13.gh-issue-104773.itOIf3.rst deleted file mode 100644 index 92ee9bf4f2baf0..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-05-24-22-47-13.gh-issue-104773.itOIf3.rst +++ /dev/null @@ -1,2 +0,0 @@ -:pep:`594`: Remove the :mod:`!xdrlib` module, deprecated in Python 3.11. -Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/Library/2023-05-24-22-50-21.gh-issue-104898.UbT2S4.rst b/Misc/NEWS.d/next/Library/2023-05-24-22-50-21.gh-issue-104898.UbT2S4.rst deleted file mode 100644 index e596ab36f5c729..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-05-24-22-50-21.gh-issue-104898.UbT2S4.rst +++ /dev/null @@ -1 +0,0 @@ -Add missing :attr:`~object.__slots__` to :class:`os.PathLike`. diff --git a/Misc/NEWS.d/next/Library/2023-05-24-23-40-22.gh-issue-104773.FHA99J.rst b/Misc/NEWS.d/next/Library/2023-05-24-23-40-22.gh-issue-104773.FHA99J.rst deleted file mode 100644 index 96c315dda79e74..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-05-24-23-40-22.gh-issue-104773.FHA99J.rst +++ /dev/null @@ -1,2 +0,0 @@ -:pep:`594`: Remove the :mod:`!nis` module, deprecated in Python 3.11. Patch -by Victor Stinner. diff --git a/Misc/NEWS.d/next/Library/2023-05-25-00-53-08.gh-issue-104773.Iyjtt0.rst b/Misc/NEWS.d/next/Library/2023-05-25-00-53-08.gh-issue-104773.Iyjtt0.rst deleted file mode 100644 index d5443aef80d488..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-05-25-00-53-08.gh-issue-104773.Iyjtt0.rst +++ /dev/null @@ -1,2 +0,0 @@ -:pep:`594`: Remove the :mod:`!crypt` module and its private :mod:`!_crypt` -extension, deprecated in Python 3.11. Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/Library/2023-05-25-08-50-47.gh-issue-104935.-rm1BR.rst b/Misc/NEWS.d/next/Library/2023-05-25-08-50-47.gh-issue-104935.-rm1BR.rst deleted file mode 100644 index 7af52bce2c9185..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-05-25-08-50-47.gh-issue-104935.-rm1BR.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fix bugs with the interaction between :func:`typing.runtime_checkable` and -:class:`typing.Generic` that were introduced by the :pep:`695` -implementation. Patch by Jelle Zijlstra. diff --git a/Misc/NEWS.d/next/Library/2023-05-25-15-54-02.gh-issue-104773.nW-5MI.rst b/Misc/NEWS.d/next/Library/2023-05-25-15-54-02.gh-issue-104773.nW-5MI.rst deleted file mode 100644 index 522e259992de27..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-05-25-15-54-02.gh-issue-104773.nW-5MI.rst +++ /dev/null @@ -1,2 +0,0 @@ -:pep:`594`: Remove the :mod:`!uu` module, deprecated in Python 3.11. Patch -by Victor Stinner. diff --git a/Misc/NEWS.d/next/Library/2023-05-25-16-50-43.gh-issue-104773.pmg0Fr.rst b/Misc/NEWS.d/next/Library/2023-05-25-16-50-43.gh-issue-104773.pmg0Fr.rst deleted file mode 100644 index 162afb6f2727a8..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-05-25-16-50-43.gh-issue-104773.pmg0Fr.rst +++ /dev/null @@ -1,2 +0,0 @@ -:pep:`594`: Remove the :mod:`!aifc` module, deprecated in Python 3.11. Patch -by Victor Stinner. diff --git a/Misc/NEWS.d/next/Library/2023-05-25-17-25-16.gh-issue-104773.O6TOMc.rst b/Misc/NEWS.d/next/Library/2023-05-25-17-25-16.gh-issue-104773.O6TOMc.rst deleted file mode 100644 index e668e75896043e..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-05-25-17-25-16.gh-issue-104773.O6TOMc.rst +++ /dev/null @@ -1,2 +0,0 @@ -:pep:`594`: Remove the :mod:`!audioop` module, deprecated in Python 3.11. -Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/Library/2023-05-25-22-54-20.gh-issue-104947.hi6TUr.rst b/Misc/NEWS.d/next/Library/2023-05-25-22-54-20.gh-issue-104947.hi6TUr.rst deleted file mode 100644 index 4af73d73d2a717..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-05-25-22-54-20.gh-issue-104947.hi6TUr.rst +++ /dev/null @@ -1,2 +0,0 @@ -Make comparisons between :class:`pathlib.PureWindowsPath` objects consistent -across Windows and Posix to match 3.11 behavior. diff --git a/Misc/NEWS.d/next/Library/2023-05-25-23-34-54.gh-issue-103631.x5Urye.rst b/Misc/NEWS.d/next/Library/2023-05-25-23-34-54.gh-issue-103631.x5Urye.rst deleted file mode 100644 index d1eb2d3ed6191f..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-05-25-23-34-54.gh-issue-103631.x5Urye.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix ``pathlib.PurePosixPath(pathlib.PureWindowsPath(...))`` not converting -path separators to restore 3.11 compatible behavior. diff --git a/Misc/NEWS.d/next/Library/2023-05-26-01-31-30.gh-issue-101588.RaqxFy.rst b/Misc/NEWS.d/next/Library/2023-05-26-01-31-30.gh-issue-101588.RaqxFy.rst deleted file mode 100644 index 07e3dc468f7d9a..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-05-26-01-31-30.gh-issue-101588.RaqxFy.rst +++ /dev/null @@ -1 +0,0 @@ -Deprecate undocumented copy/deepcopy/pickle support for itertools. diff --git a/Misc/NEWS.d/next/Library/2023-05-26-21-24-06.gh-issue-104996.aaW78g.rst b/Misc/NEWS.d/next/Library/2023-05-26-21-24-06.gh-issue-104996.aaW78g.rst deleted file mode 100644 index 8b81b681af94aa..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-05-26-21-24-06.gh-issue-104996.aaW78g.rst +++ /dev/null @@ -1,2 +0,0 @@ -Improve performance of :class:`pathlib.PurePath` initialisation by -deferring joining of paths when multiple arguments are given. diff --git a/Misc/NEWS.d/next/Library/2023-05-26-21-33-24.gh-issue-104992.dbq9WK.rst b/Misc/NEWS.d/next/Library/2023-05-26-21-33-24.gh-issue-104992.dbq9WK.rst deleted file mode 100644 index d72646a6541f19..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-05-26-21-33-24.gh-issue-104992.dbq9WK.rst +++ /dev/null @@ -1,2 +0,0 @@ -Remove the untested and undocumented :meth:`!unittest.TestProgram.usageExit` -method, deprecated in Python 3.11. Patch by Hugo van Kemenade. diff --git a/Misc/NEWS.d/next/Library/2023-05-30-17-39-03.gh-issue-105096.pw00FW.rst b/Misc/NEWS.d/next/Library/2023-05-30-17-39-03.gh-issue-105096.pw00FW.rst deleted file mode 100644 index bc82c13081f140..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-05-30-17-39-03.gh-issue-105096.pw00FW.rst +++ /dev/null @@ -1,3 +0,0 @@ -:mod:`wave`: Deprecate the ``getmark()``, ``setmark()`` and ``getmarkers()`` -methods of the :class:`wave.Wave_read` and :class:`wave.Wave_write` classes. -They will be removed in Python 3.15. Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/Library/2023-05-30-18-45-02.gh-issue-62948.1-5wMR.rst b/Misc/NEWS.d/next/Library/2023-05-30-18-45-02.gh-issue-62948.1-5wMR.rst deleted file mode 100644 index d6ba989329bce0..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-05-30-18-45-02.gh-issue-62948.1-5wMR.rst +++ /dev/null @@ -1,4 +0,0 @@ -The :class:`io.IOBase` finalizer now logs the ``close()`` method errors with -:data:`sys.unraisablehook`. Previously, errors were ignored silently by default, -and only logged in :ref:`Python Development Mode ` or on -:ref:`Python built on debug mode `. Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/Library/2023-05-31-16-58-42.gh-issue-105144.Oqfn0V.rst b/Misc/NEWS.d/next/Library/2023-05-31-16-58-42.gh-issue-105144.Oqfn0V.rst deleted file mode 100644 index 7e4d6fbc4911ba..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-05-31-16-58-42.gh-issue-105144.Oqfn0V.rst +++ /dev/null @@ -1,5 +0,0 @@ -Fix a recent regression in the :mod:`typing` module. The regression meant -that doing ``class Foo(X, typing.Protocol)``, where ``X`` was a class that -had :class:`abc.ABCMeta` as its metaclass, would then cause subsequent -``isinstance(1, X)`` calls to erroneously raise :exc:`TypeError`. Patch by -Alex Waygood. diff --git a/Misc/NEWS.d/next/Library/2023-06-02-02-38-26.gh-issue-105080.2imGMg.rst b/Misc/NEWS.d/next/Library/2023-06-02-02-38-26.gh-issue-105080.2imGMg.rst deleted file mode 100644 index efe8365a7644be..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-06-02-02-38-26.gh-issue-105080.2imGMg.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed inconsistent signature on derived classes for :func:`inspect.signature` diff --git a/Misc/NEWS.d/next/Library/2023-06-02-14-23-41.gh-issue-104310.UamCOB.rst b/Misc/NEWS.d/next/Library/2023-06-02-14-23-41.gh-issue-104310.UamCOB.rst deleted file mode 100644 index 461a3a25fe1b43..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-06-02-14-23-41.gh-issue-104310.UamCOB.rst +++ /dev/null @@ -1,7 +0,0 @@ -In the beta 1 release we added a utility function for extension module -authors, to use when testing their module for support in multiple -interpreters or under a per-interpreter GIL. The name of that function has -changed from ``allowing_all_extensions`` to -``_incompatible_extension_module_restrictions``. The default for the -"disable_check" argument has change from ``True`` to ``False``, to better -match the new function name. diff --git a/Misc/NEWS.d/next/Library/2023-06-02-14-57-11.gh-issue-105239.SAmuuj.rst b/Misc/NEWS.d/next/Library/2023-06-02-14-57-11.gh-issue-105239.SAmuuj.rst deleted file mode 100644 index 35e1b1a217b3a4..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-06-02-14-57-11.gh-issue-105239.SAmuuj.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix longstanding bug where ``issubclass(object, typing.Protocol)`` would -evaluate to ``True`` in some edge cases. Patch by Alex Waygood. diff --git a/Misc/NEWS.d/next/Library/2023-06-02-23-32-17.gh-issue-80480.savBw9.rst b/Misc/NEWS.d/next/Library/2023-06-02-23-32-17.gh-issue-80480.savBw9.rst deleted file mode 100644 index fd87efe9bde0c3..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-06-02-23-32-17.gh-issue-80480.savBw9.rst +++ /dev/null @@ -1 +0,0 @@ -:mod:`array`: Add ``'w'`` typecode that represents ``Py_UCS4``. diff --git a/Misc/NEWS.d/next/Library/2023-06-04-12-16-47.gh-issue-105280.srRbCe.rst b/Misc/NEWS.d/next/Library/2023-06-04-12-16-47.gh-issue-105280.srRbCe.rst deleted file mode 100644 index 8e469646604316..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-06-04-12-16-47.gh-issue-105280.srRbCe.rst +++ /dev/null @@ -1,4 +0,0 @@ -Fix bug where ``isinstance([], collections.abc.Mapping)`` could evaluate to -``True`` if garbage collection happened at the wrong time. The bug was -caused by changes to the implementation of :class:`typing.Protocol` in -Python 3.12. diff --git a/Misc/NEWS.d/next/Library/2023-06-04-23-20-56.gh-issue-105292.ns6XQR.rst b/Misc/NEWS.d/next/Library/2023-06-04-23-20-56.gh-issue-105292.ns6XQR.rst deleted file mode 100644 index c23e1ffd3538e3..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-06-04-23-20-56.gh-issue-105292.ns6XQR.rst +++ /dev/null @@ -1,2 +0,0 @@ -Add option to :func:`traceback.format_exception_only` to recurse into the -nested exception of a :exc:`BaseExceptionGroup`. diff --git a/Misc/NEWS.d/next/Library/2023-06-05-14-43-56.gh-issue-104554.pwfKIo.rst b/Misc/NEWS.d/next/Library/2023-06-05-14-43-56.gh-issue-104554.pwfKIo.rst deleted file mode 100644 index 9ef8c67459c406..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-06-05-14-43-56.gh-issue-104554.pwfKIo.rst +++ /dev/null @@ -1 +0,0 @@ -Add RTSPS scheme support in urllib.parse diff --git a/Misc/NEWS.d/next/Library/2023-06-06-11-50-33.gh-issue-105332.tmpgRA.rst b/Misc/NEWS.d/next/Library/2023-06-06-11-50-33.gh-issue-105332.tmpgRA.rst deleted file mode 100644 index 31b6855a6ebfad..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-06-06-11-50-33.gh-issue-105332.tmpgRA.rst +++ /dev/null @@ -1 +0,0 @@ -Revert pickling method from by-name back to by-value. diff --git a/Misc/NEWS.d/next/Library/2023-06-06-15-32-44.gh-issue-105376.W4oDQp.rst b/Misc/NEWS.d/next/Library/2023-06-06-15-32-44.gh-issue-105376.W4oDQp.rst deleted file mode 100644 index 2ed6b5e0a7ac0a..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-06-06-15-32-44.gh-issue-105376.W4oDQp.rst +++ /dev/null @@ -1,5 +0,0 @@ -:mod:`logging`: Remove undocumented and untested ``Logger.warn()`` and -``LoggerAdapter.warn()`` methods and ``logging.warn()`` function. Deprecated -since Python 3.3, they were aliases to the :meth:`logging.Logger.warning` -method, :meth:`!logging.LoggerAdapter.warning` method and -:func:`logging.warning` function. Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/Library/2023-06-06-16-00-03.gh-issue-105382.A1LgzA.rst b/Misc/NEWS.d/next/Library/2023-06-06-16-00-03.gh-issue-105382.A1LgzA.rst deleted file mode 100644 index 4e6d72745ff025..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-06-06-16-00-03.gh-issue-105382.A1LgzA.rst +++ /dev/null @@ -1,3 +0,0 @@ -Remove *cafile*, *capath* and *cadefault* parameters of the -:func:`urllib.request.urlopen` function, deprecated in Python 3.6. Patch by -Victor Stinner. diff --git a/Misc/NEWS.d/next/Library/2023-06-07-00-09-52.gh-issue-105375.Y_9D4n.rst b/Misc/NEWS.d/next/Library/2023-06-07-00-09-52.gh-issue-105375.Y_9D4n.rst deleted file mode 100644 index ec10d63822c203..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-06-07-00-09-52.gh-issue-105375.Y_9D4n.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix a bug in :mod:`sqlite3` where an exception could be overwritten in the -:meth:`collation ` callback. diff --git a/Misc/NEWS.d/next/Library/2023-06-07-00-13-00.gh-issue-70303.frwUKH.rst b/Misc/NEWS.d/next/Library/2023-06-07-00-13-00.gh-issue-70303.frwUKH.rst deleted file mode 100644 index 39a891ac5964ab..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-06-07-00-13-00.gh-issue-70303.frwUKH.rst +++ /dev/null @@ -1,4 +0,0 @@ -Emit :exc:`FutureWarning` from :meth:`pathlib.Path.glob` and -:meth:`~pathlib.Path.rglob` if the given pattern ends with "``**``". In a -future Python release, patterns with this ending will match both files and -directories. Add a trailing slash to only match directories. diff --git a/Misc/NEWS.d/next/Library/2023-06-08-08-58-36.gh-issue-105375.bTcqS9.rst b/Misc/NEWS.d/next/Library/2023-06-08-08-58-36.gh-issue-105375.bTcqS9.rst deleted file mode 100644 index 3030477c8245b5..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-06-08-08-58-36.gh-issue-105375.bTcqS9.rst +++ /dev/null @@ -1 +0,0 @@ -Fix bugs in :mod:`pickle` where exceptions could be overwritten. diff --git a/Misc/NEWS.d/next/Library/2023-06-08-17-49-46.gh-issue-105497.K6Q8nU.rst b/Misc/NEWS.d/next/Library/2023-06-08-17-49-46.gh-issue-105497.K6Q8nU.rst deleted file mode 100644 index 2d4e2091b50714..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-06-08-17-49-46.gh-issue-105497.K6Q8nU.rst +++ /dev/null @@ -1 +0,0 @@ -Fix flag inversion when alias/mask members exist. diff --git a/Misc/NEWS.d/next/Library/2023-06-09-08-38-30.gh-issue-105545.2q3ysu.rst b/Misc/NEWS.d/next/Library/2023-06-09-08-38-30.gh-issue-105545.2q3ysu.rst deleted file mode 100644 index f27692126a7ec4..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-06-09-08-38-30.gh-issue-105545.2q3ysu.rst +++ /dev/null @@ -1 +0,0 @@ -Remove deprecated in 3.11 ``webbrowser.MacOSXOSAScript._name`` attribute. diff --git a/Misc/NEWS.d/next/Library/2023-06-09-20-34-23.gh-issue-105566.YxlGg1.rst b/Misc/NEWS.d/next/Library/2023-06-09-20-34-23.gh-issue-105566.YxlGg1.rst deleted file mode 100644 index c2c497aee513d3..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-06-09-20-34-23.gh-issue-105566.YxlGg1.rst +++ /dev/null @@ -1,10 +0,0 @@ -Deprecate creating a :class:`typing.NamedTuple` class using keyword -arguments to denote the fields (``NT = NamedTuple("NT", x=int, y=str)``). -This will be disallowed in Python 3.15. -Use the class-based syntax or the functional syntax instead. - -Two methods of creating ``NamedTuple`` classes with 0 fields using the -functional syntax are also deprecated, and will be disallowed in Python 3.15: -``NT = NamedTuple("NT")`` and ``NT = NamedTuple("NT", None)``. To create a -``NamedTuple`` class with 0 fields, either use ``class NT(NamedTuple): pass`` or -``NT = NamedTuple("NT", [])``. diff --git a/Misc/NEWS.d/next/Library/2023-06-09-21-04-39.gh-issue-105375.bTcqS9.rst b/Misc/NEWS.d/next/Library/2023-06-09-21-04-39.gh-issue-105375.bTcqS9.rst deleted file mode 100644 index 3030477c8245b5..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-06-09-21-04-39.gh-issue-105375.bTcqS9.rst +++ /dev/null @@ -1 +0,0 @@ -Fix bugs in :mod:`pickle` where exceptions could be overwritten. diff --git a/Misc/NEWS.d/next/Library/2023-06-09-21-11-28.gh-issue-105375.4Mxn7t.rst b/Misc/NEWS.d/next/Library/2023-06-09-21-11-28.gh-issue-105375.4Mxn7t.rst deleted file mode 100644 index 4202b758d1db56..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-06-09-21-11-28.gh-issue-105375.4Mxn7t.rst +++ /dev/null @@ -1 +0,0 @@ -Fix bugs in :mod:`zoneinfo` where exceptions could be overwritten. diff --git a/Misc/NEWS.d/next/Library/2023-06-09-21-25-14.gh-issue-105375.95g1eI.rst b/Misc/NEWS.d/next/Library/2023-06-09-21-25-14.gh-issue-105375.95g1eI.rst deleted file mode 100644 index 1894b2b94bb334..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-06-09-21-25-14.gh-issue-105375.95g1eI.rst +++ /dev/null @@ -1 +0,0 @@ -Fix bugs in :mod:`!_elementtree` where exceptions could be overwritten. diff --git a/Misc/NEWS.d/next/Library/2023-06-09-21-30-59.gh-issue-105375.eewafp.rst b/Misc/NEWS.d/next/Library/2023-06-09-21-30-59.gh-issue-105375.eewafp.rst deleted file mode 100644 index e000f98828a211..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-06-09-21-30-59.gh-issue-105375.eewafp.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix a bug in the :mod:`posix` module where an exception could be -overwritten. diff --git a/Misc/NEWS.d/next/Library/2023-06-09-21-40-45.gh-issue-105375._sZilh.rst b/Misc/NEWS.d/next/Library/2023-06-09-21-40-45.gh-issue-105375._sZilh.rst deleted file mode 100644 index 87db4c2b4e22e3..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-06-09-21-40-45.gh-issue-105375._sZilh.rst +++ /dev/null @@ -1 +0,0 @@ -Fix bugs in :mod:`_ctypes` where exceptions could end up being overwritten. diff --git a/Misc/NEWS.d/next/Library/2023-06-09-21-46-52.gh-issue-105375.yrJelV.rst b/Misc/NEWS.d/next/Library/2023-06-09-21-46-52.gh-issue-105375.yrJelV.rst deleted file mode 100644 index 21aea1b0b4082c..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-06-09-21-46-52.gh-issue-105375.yrJelV.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix a bug in :class:`array.array` where an exception could end up being -overwritten. diff --git a/Misc/NEWS.d/next/Library/2023-06-09-22-16-46.gh-issue-105375.EgVJOP.rst b/Misc/NEWS.d/next/Library/2023-06-09-22-16-46.gh-issue-105375.EgVJOP.rst deleted file mode 100644 index 49f7df68e927cb..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-06-09-22-16-46.gh-issue-105375.EgVJOP.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix bugs in :mod:`!_ssl` initialisation which could lead to leaked -references and overwritten exceptions. diff --git a/Misc/NEWS.d/next/Library/2023-06-09-22-45-26.gh-issue-105375.9rp6tG.rst b/Misc/NEWS.d/next/Library/2023-06-09-22-45-26.gh-issue-105375.9rp6tG.rst deleted file mode 100644 index 352d7b83a71632..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-06-09-22-45-26.gh-issue-105375.9rp6tG.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix bugs in :mod:`!_datetime` where exceptions could be overwritten in case -of module initialisation failure. diff --git a/Misc/NEWS.d/next/Library/2023-06-09-22-52-45.gh-issue-105375.6igkhn.rst b/Misc/NEWS.d/next/Library/2023-06-09-22-52-45.gh-issue-105375.6igkhn.rst deleted file mode 100644 index 05e78fdc9b4076..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-06-09-22-52-45.gh-issue-105375.6igkhn.rst +++ /dev/null @@ -1 +0,0 @@ -Fix bug in :mod:`decimal` where an exception could end up being overwritten. diff --git a/Misc/NEWS.d/next/Library/2023-06-09-23-00-13.gh-issue-105605.YuwqxY.rst b/Misc/NEWS.d/next/Library/2023-06-09-23-00-13.gh-issue-105605.YuwqxY.rst deleted file mode 100644 index 5fba6d293a785e..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-06-09-23-00-13.gh-issue-105605.YuwqxY.rst +++ /dev/null @@ -1,3 +0,0 @@ -Harden :mod:`pyexpat` error handling during module initialisation to prevent -exceptions from possibly being overwritten, and objects from being -dereferenced twice. diff --git a/Misc/NEWS.d/next/Library/2023-06-09-23-46-23.gh-issue-105375.9KaioS.rst b/Misc/NEWS.d/next/Library/2023-06-09-23-46-23.gh-issue-105375.9KaioS.rst deleted file mode 100644 index b12d7c864e7b86..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-06-09-23-46-23.gh-issue-105375.9KaioS.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix bugs in :mod:`sys` where exceptions could end up being overwritten -because of deferred error handling. diff --git a/Misc/NEWS.d/next/Library/2023-06-10-12-20-17.gh-issue-105626.XyZein.rst b/Misc/NEWS.d/next/Library/2023-06-10-12-20-17.gh-issue-105626.XyZein.rst deleted file mode 100644 index 2a48361fa596c9..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-06-10-12-20-17.gh-issue-105626.XyZein.rst +++ /dev/null @@ -1,3 +0,0 @@ -Change the default return value of -:meth:`http.client.HTTPConnection.get_proxy_response_headers` to be ``None`` -and not ``{}``. diff --git a/Misc/NEWS.d/next/Library/2023-06-11-22-46-06.gh-issue-105375.YkhSNt.rst b/Misc/NEWS.d/next/Library/2023-06-11-22-46-06.gh-issue-105375.YkhSNt.rst deleted file mode 100644 index dda8f428760ba1..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-06-11-22-46-06.gh-issue-105375.YkhSNt.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix a bug in :c:func:`!_Unpickler_SetInputStream` where an exception could -end up being overwritten in case of failure. diff --git a/Misc/NEWS.d/next/Library/2023-06-12-10-40-38.gh-issue-105684.yiHkFD.rst b/Misc/NEWS.d/next/Library/2023-06-12-10-40-38.gh-issue-105684.yiHkFD.rst deleted file mode 100644 index b0d4eb328a7b34..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-06-12-10-40-38.gh-issue-105684.yiHkFD.rst +++ /dev/null @@ -1,3 +0,0 @@ -Supporting :meth:`asyncio.Task.set_name` is now mandatory for third party task implementations. -The undocumented :func:`!_set_task_name` function (deprecated since 3.8) has been removed. -Patch by Kumar Aditya. diff --git a/Misc/NEWS.d/next/Library/2023-06-12-15-17-34.gh-issue-105687.ZUonKm.rst b/Misc/NEWS.d/next/Library/2023-06-12-15-17-34.gh-issue-105687.ZUonKm.rst deleted file mode 100644 index 7966d3a566414e..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-06-12-15-17-34.gh-issue-105687.ZUonKm.rst +++ /dev/null @@ -1,2 +0,0 @@ -Remove deprecated ``re.template``, ``re.T``, ``re.TEMPLATE``, -``sre_constans.SRE_FLAG_TEMPLATE``. diff --git a/Misc/NEWS.d/next/Library/2023-06-13-19-38-12.gh-issue-105733.WOp0mG.rst b/Misc/NEWS.d/next/Library/2023-06-13-19-38-12.gh-issue-105733.WOp0mG.rst deleted file mode 100644 index 20f2ba2bcc5cb1..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-06-13-19-38-12.gh-issue-105733.WOp0mG.rst +++ /dev/null @@ -1,2 +0,0 @@ -:mod:`ctypes`: Deprecate undocumented :func:`!ctypes.SetPointerType` and -:func:`!ctypes.ARRAY` functions. Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/Library/2023-06-14-10-27-34.gh-issue-105745.l1ttOQ.rst b/Misc/NEWS.d/next/Library/2023-06-14-10-27-34.gh-issue-105745.l1ttOQ.rst deleted file mode 100644 index 7df7c5a79ec6eb..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-06-14-10-27-34.gh-issue-105745.l1ttOQ.rst +++ /dev/null @@ -1 +0,0 @@ -Fix ``webbrowser.Konqueror.open`` method. diff --git a/Misc/NEWS.d/next/Library/2023-06-14-14-32-31.gh-issue-105570.sFTtQU.rst b/Misc/NEWS.d/next/Library/2023-06-14-14-32-31.gh-issue-105570.sFTtQU.rst deleted file mode 100644 index e31a8ee256d697..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-06-14-14-32-31.gh-issue-105570.sFTtQU.rst +++ /dev/null @@ -1,5 +0,0 @@ -Deprecate two methods of creating :class:`typing.TypedDict` classes with 0 -fields using the functional syntax: ``TD = TypedDict("TD")`` and -``TD = TypedDict("TD", None)``. Both will be disallowed in Python 3.15. To create a -``TypedDict`` class with 0 fields, either use ``class TD(TypedDict): pass`` -or ``TD = TypedDict("TD", {})``. diff --git a/Misc/NEWS.d/next/Library/2023-06-14-18-41-18.gh-issue-105793.YSoykM.rst b/Misc/NEWS.d/next/Library/2023-06-14-18-41-18.gh-issue-105793.YSoykM.rst deleted file mode 100644 index 0e4090ea7eabb9..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-06-14-18-41-18.gh-issue-105793.YSoykM.rst +++ /dev/null @@ -1,2 +0,0 @@ -Add *follow_symlinks* keyword-only argument to :meth:`pathlib.Path.is_dir` and -:meth:`~pathlib.Path.is_file`, defaulting to ``True``. diff --git a/Misc/NEWS.d/next/Library/2023-06-15-18-11-47.gh-issue-104799.BcLzbP.rst b/Misc/NEWS.d/next/Library/2023-06-15-18-11-47.gh-issue-104799.BcLzbP.rst deleted file mode 100644 index d0dbff4f1553e2..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-06-15-18-11-47.gh-issue-104799.BcLzbP.rst +++ /dev/null @@ -1,3 +0,0 @@ -Enable :func:`ast.unparse` to unparse function and class definitions created -without the new ``type_params`` field from :pep:`695`. Patch by Jelle -Zijlstra. diff --git a/Misc/NEWS.d/next/Library/2023-06-17-12-13-57.gh-issue-105481.KgBH5w.rst b/Misc/NEWS.d/next/Library/2023-06-17-12-13-57.gh-issue-105481.KgBH5w.rst deleted file mode 100644 index 11084ef956dcf3..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-06-17-12-13-57.gh-issue-105481.KgBH5w.rst +++ /dev/null @@ -1,4 +0,0 @@ -:func:`~dis.stack_effect` no longer raises an exception if an ``oparg`` is -provided for an ``opcode`` that doesn't use its arg, or when it is not -provided for an ``opcode`` that does use it. In the latter case, the stack -effect is returned for ``oparg=0``. diff --git a/Misc/NEWS.d/next/Library/2023-06-19-11-31-55.gh-issue-105808.NL-quu.rst b/Misc/NEWS.d/next/Library/2023-06-19-11-31-55.gh-issue-105808.NL-quu.rst deleted file mode 100644 index 8e69fd627c28e8..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-06-19-11-31-55.gh-issue-105808.NL-quu.rst +++ /dev/null @@ -1 +0,0 @@ -Fix a regression introduced in GH-101251 for 3.12, causing :meth:`gzip.GzipFile.flush` to not flush the compressor (nor pass along the ``zip_mode`` argument). diff --git a/Misc/NEWS.d/next/Library/2023-06-19-22-20-41.gh-issue-89812.z2l_e8.rst b/Misc/NEWS.d/next/Library/2023-06-19-22-20-41.gh-issue-89812.z2l_e8.rst deleted file mode 100644 index f1ef11e26bc5fc..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-06-19-22-20-41.gh-issue-89812.z2l_e8.rst +++ /dev/null @@ -1,2 +0,0 @@ -Add :exc:`pathlib.UnsupportedOperation`, which is raised instead of -:exc:`NotImplementedError` when a path operation isn't supported. diff --git a/Misc/NEWS.d/next/Library/2023-06-20-23-18-45.gh-issue-96145.o5dTRM.rst b/Misc/NEWS.d/next/Library/2023-06-20-23-18-45.gh-issue-96145.o5dTRM.rst deleted file mode 100644 index f4fb0e46ce5e57..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-06-20-23-18-45.gh-issue-96145.o5dTRM.rst +++ /dev/null @@ -1 +0,0 @@ -Reverted addition of ``json.AttrDict``. diff --git a/Misc/NEWS.d/next/Library/2023-06-21-19-04-27.gh-issue-105974.M47n3t.rst b/Misc/NEWS.d/next/Library/2023-06-21-19-04-27.gh-issue-105974.M47n3t.rst deleted file mode 100644 index 982192e59e3a50..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-06-21-19-04-27.gh-issue-105974.M47n3t.rst +++ /dev/null @@ -1,6 +0,0 @@ -Fix bug where a :class:`typing.Protocol` class that had one or more -non-callable members would raise :exc:`TypeError` when :func:`issubclass` -was called against it, even if it defined a custom ``__subclasshook__`` -method. The behaviour in Python 3.11 and lower -- which has now been -restored -- was not to raise :exc:`TypeError` in these situations if a -custom ``__subclasshook__`` method was defined. Patch by Alex Waygood. diff --git a/Misc/NEWS.d/next/Library/2023-06-22-15-21-11.gh-issue-105987.T7Kzrb.rst b/Misc/NEWS.d/next/Library/2023-06-22-15-21-11.gh-issue-105987.T7Kzrb.rst deleted file mode 100644 index 0bc97da4edf0f9..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-06-22-15-21-11.gh-issue-105987.T7Kzrb.rst +++ /dev/null @@ -1 +0,0 @@ -Fix crash due to improper reference counting in :mod:`asyncio` eager task factory internal routines. diff --git a/Misc/NEWS.d/next/Library/2023-06-23-22-52-24.gh-issue-106046.OdLiLJ.rst b/Misc/NEWS.d/next/Library/2023-06-23-22-52-24.gh-issue-106046.OdLiLJ.rst deleted file mode 100644 index ce10a9d81dc64c..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-06-23-22-52-24.gh-issue-106046.OdLiLJ.rst +++ /dev/null @@ -1,2 +0,0 @@ -Improve the error message from :func:`os.fspath` if called on an object -where ``__fspath__`` is set to ``None``. Patch by Alex Waygood. diff --git a/Misc/NEWS.d/next/Library/2023-06-25-06-57-24.gh-issue-104527.TJEUkd.rst b/Misc/NEWS.d/next/Library/2023-06-25-06-57-24.gh-issue-104527.TJEUkd.rst deleted file mode 100644 index 50b845bcde9bbe..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-06-25-06-57-24.gh-issue-104527.TJEUkd.rst +++ /dev/null @@ -1 +0,0 @@ -Zipapp will now skip over apending an archive to itself. diff --git a/Misc/NEWS.d/next/Library/2023-06-25-12-28-55.gh-issue-106075.W7tMRb.rst b/Misc/NEWS.d/next/Library/2023-06-25-12-28-55.gh-issue-106075.W7tMRb.rst deleted file mode 100644 index d2687154a58594..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-06-25-12-28-55.gh-issue-106075.W7tMRb.rst +++ /dev/null @@ -1 +0,0 @@ -Added `asyncio.taskgroups.__all__` to `asyncio.__all__` for export in star imports. diff --git a/Misc/NEWS.d/next/Library/2023-06-27-23-22-37.gh-issue-106152.ya5jBT.rst b/Misc/NEWS.d/next/Library/2023-06-27-23-22-37.gh-issue-106152.ya5jBT.rst deleted file mode 100644 index da9d2605f46294..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-06-27-23-22-37.gh-issue-106152.ya5jBT.rst +++ /dev/null @@ -1 +0,0 @@ -Added PY_THROW event hook for :mod:`cProfile` for generators diff --git a/Misc/NEWS.d/next/Library/2023-06-29-12-40-52.gh-issue-106238.VulKb9.rst b/Misc/NEWS.d/next/Library/2023-06-29-12-40-52.gh-issue-106238.VulKb9.rst deleted file mode 100644 index 52e78382fd618e..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-06-29-12-40-52.gh-issue-106238.VulKb9.rst +++ /dev/null @@ -1 +0,0 @@ -Fix rare concurrency bug in lock acquisition by the logging package. diff --git a/Misc/NEWS.d/next/Library/2023-06-29-15-10-44.gh-issue-106236.EAIX4l.rst b/Misc/NEWS.d/next/Library/2023-06-29-15-10-44.gh-issue-106236.EAIX4l.rst deleted file mode 100644 index 036bdb6ef59f6c..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-06-29-15-10-44.gh-issue-106236.EAIX4l.rst +++ /dev/null @@ -1,2 +0,0 @@ -Replace ``assert`` statements with ``raise RuntimeError`` in -:mod:`threading`, so that ``_DummyThread`` cannot be joined even with ``-OO``. diff --git a/Misc/NEWS.d/next/Library/2023-06-30-16-42-44.gh-issue-106263.tk-t93.rst b/Misc/NEWS.d/next/Library/2023-06-30-16-42-44.gh-issue-106263.tk-t93.rst deleted file mode 100644 index 23763818d84ba5..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-06-30-16-42-44.gh-issue-106263.tk-t93.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix crash when calling ``repr`` with a manually constructed SignalDict object. -Patch by Charlie Zhao. \ No newline at end of file diff --git a/Misc/NEWS.d/next/Library/2023-07-01-16-40-54.gh-issue-102541.C1ahtk.rst b/Misc/NEWS.d/next/Library/2023-07-01-16-40-54.gh-issue-102541.C1ahtk.rst deleted file mode 100644 index efaf5db10f3e1c..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-07-01-16-40-54.gh-issue-102541.C1ahtk.rst +++ /dev/null @@ -1 +0,0 @@ -Make pydoc.doc catch bad module ImportError when output stream is not None. diff --git a/Misc/NEWS.d/next/Library/2023-07-01-16-51-55.gh-issue-106309.hSlB17.rst b/Misc/NEWS.d/next/Library/2023-07-01-16-51-55.gh-issue-106309.hSlB17.rst deleted file mode 100644 index 5bd3880520871f..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-07-01-16-51-55.gh-issue-106309.hSlB17.rst +++ /dev/null @@ -1,2 +0,0 @@ -Deprecate :func:`typing.no_type_check_decorator`. No major type checker ever -added support for this decorator. Patch by Alex Waygood. diff --git a/Misc/NEWS.d/next/Library/2023-07-02-10-56-41.gh-issue-106330.QSkIUH.rst b/Misc/NEWS.d/next/Library/2023-07-02-10-56-41.gh-issue-106330.QSkIUH.rst deleted file mode 100644 index c1f55ab658b517..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-07-02-10-56-41.gh-issue-106330.QSkIUH.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix incorrect matching of empty paths in :meth:`pathlib.PurePath.match`. -This bug was introduced in Python 3.12.0 beta 1. diff --git a/Misc/NEWS.d/next/Library/2023-07-03-03-46-20.gh-issue-106350.LLcTEe.rst b/Misc/NEWS.d/next/Library/2023-07-03-03-46-20.gh-issue-106350.LLcTEe.rst deleted file mode 100644 index 681d63a6668be8..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-07-03-03-46-20.gh-issue-106350.LLcTEe.rst +++ /dev/null @@ -1,2 +0,0 @@ -Detect possible memory allocation failure in the libtommath function :c:func:`mp_init` -used by the ``_tkinter`` module. diff --git a/Misc/NEWS.d/next/Library/2023-07-03-15-09-44.gh-issue-106292.3npldV.rst b/Misc/NEWS.d/next/Library/2023-07-03-15-09-44.gh-issue-106292.3npldV.rst deleted file mode 100644 index 233509344d509b..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-07-03-15-09-44.gh-issue-106292.3npldV.rst +++ /dev/null @@ -1,4 +0,0 @@ -Check for an instance-dict cached value in the :meth:`__get__` method of -:func:`functools.cached_property`. This better matches the pre-3.12 behavior -and improves compatibility for users subclassing -:func:`functools.cached_property` and adding a :meth:`__set__` method. diff --git a/Misc/NEWS.d/next/Library/2023-07-04-07-25-30.gh-issue-106403.GmefbV.rst b/Misc/NEWS.d/next/Library/2023-07-04-07-25-30.gh-issue-106403.GmefbV.rst deleted file mode 100644 index 4fea45f16c4f8e..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-07-04-07-25-30.gh-issue-106403.GmefbV.rst +++ /dev/null @@ -1,4 +0,0 @@ -Instances of :class:`typing.TypeVar`, :class:`typing.ParamSpec`, -:class:`typing.ParamSpecArgs`, :class:`typing.ParamSpecKwargs`, and -:class:`typing.TypeVarTuple` once again support weak references, fixing a -regression introduced in Python 3.12.0 beta 1. Patch by Jelle Zijlstra. diff --git a/Misc/NEWS.d/next/Library/2023-07-05-13-08-23.gh-issue-90876.Qvlkfl.rst b/Misc/NEWS.d/next/Library/2023-07-05-13-08-23.gh-issue-90876.Qvlkfl.rst deleted file mode 100644 index 3e062b5add6d89..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-07-05-13-08-23.gh-issue-90876.Qvlkfl.rst +++ /dev/null @@ -1,3 +0,0 @@ -Prevent :mod:`multiprocessing.spawn` from failing to *import* in environments -where ``sys.executable`` is ``None``. This regressed in 3.11 with the addition -of support for path-like objects in multiprocessing. diff --git a/Misc/NEWS.d/next/Library/2023-07-05-14-34-10.gh-issue-105497.HU5u89.rst b/Misc/NEWS.d/next/Library/2023-07-05-14-34-10.gh-issue-105497.HU5u89.rst deleted file mode 100644 index f4f2db08f73f50..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-07-05-14-34-10.gh-issue-105497.HU5u89.rst +++ /dev/null @@ -1 +0,0 @@ -Fix flag mask inversion when unnamed flags exist. diff --git a/Misc/NEWS.d/next/Library/2023-07-07-03-05-58.gh-issue-106503.ltfeiH.rst b/Misc/NEWS.d/next/Library/2023-07-07-03-05-58.gh-issue-106503.ltfeiH.rst deleted file mode 100644 index b8dd850386e86c..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-07-07-03-05-58.gh-issue-106503.ltfeiH.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix ref cycle in :class:`!asyncio._SelectorSocketTransport` by removing -``_write_ready`` in ``close``. diff --git a/Misc/NEWS.d/next/Library/2023-07-07-13-47-28.gh-issue-106510.9n5BdC.rst b/Misc/NEWS.d/next/Library/2023-07-07-13-47-28.gh-issue-106510.9n5BdC.rst deleted file mode 100644 index e0646fa9bc0211..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-07-07-13-47-28.gh-issue-106510.9n5BdC.rst +++ /dev/null @@ -1 +0,0 @@ -Improve debug output for atomic groups in regular expressions. diff --git a/Misc/NEWS.d/next/Library/2023-07-07-16-19-59.gh-issue-106531.eMfNm8.rst b/Misc/NEWS.d/next/Library/2023-07-07-16-19-59.gh-issue-106531.eMfNm8.rst deleted file mode 100644 index a52107103c4576..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-07-07-16-19-59.gh-issue-106531.eMfNm8.rst +++ /dev/null @@ -1,3 +0,0 @@ -Removed ``_legacy`` and the names it provided from ``importlib.resources``: -``Resource``, ``contents``, ``is_resource``, ``open_binary``, ``open_text``, -``path``, ``read_binary``, and ``read_text``. diff --git a/Misc/NEWS.d/next/Library/2023-07-07-17-44-03.gh-issue-106524.XkBV8h.rst b/Misc/NEWS.d/next/Library/2023-07-07-17-44-03.gh-issue-106524.XkBV8h.rst deleted file mode 100644 index f3fd070e391a66..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-07-07-17-44-03.gh-issue-106524.XkBV8h.rst +++ /dev/null @@ -1 +0,0 @@ -Fix crash in :func:`!_sre.template` with templates containing invalid group indices. diff --git a/Misc/NEWS.d/next/Library/2023-07-07-18-22-07.gh-issue-106527.spHQ0W.rst b/Misc/NEWS.d/next/Library/2023-07-07-18-22-07.gh-issue-106527.spHQ0W.rst deleted file mode 100644 index 204bda1c73eb36..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-07-07-18-22-07.gh-issue-106527.spHQ0W.rst +++ /dev/null @@ -1 +0,0 @@ -Reduce overhead to add and remove :mod:`asyncio` readers and writers. diff --git a/Misc/NEWS.d/next/Library/2023-07-07-21-15-17.gh-issue-100502.Iici1B.rst b/Misc/NEWS.d/next/Library/2023-07-07-21-15-17.gh-issue-100502.Iici1B.rst deleted file mode 100644 index eea9564118df9c..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-07-07-21-15-17.gh-issue-100502.Iici1B.rst +++ /dev/null @@ -1,3 +0,0 @@ -Add :attr:`pathlib.PurePath.pathmod` class attribute that stores the -implementation of :mod:`os.path` used for low-level path operations: either -``posixpath`` or ``ntpath``. diff --git a/Misc/NEWS.d/next/Library/2023-07-09-01-59-24.gh-issue-106554.37c53J.rst b/Misc/NEWS.d/next/Library/2023-07-09-01-59-24.gh-issue-106554.37c53J.rst deleted file mode 100644 index 2136f3aa5a8eb0..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-07-09-01-59-24.gh-issue-106554.37c53J.rst +++ /dev/null @@ -1 +0,0 @@ -:mod:`selectors`: Reduce Selector overhead by using a ``dict.get()`` to lookup file descriptors. diff --git a/Misc/NEWS.d/next/Library/2023-07-11-09-25-40.gh-issue-106530.VgXrMx.rst b/Misc/NEWS.d/next/Library/2023-07-11-09-25-40.gh-issue-106530.VgXrMx.rst deleted file mode 100644 index 09fc647cc01d21..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-07-11-09-25-40.gh-issue-106530.VgXrMx.rst +++ /dev/null @@ -1,2 +0,0 @@ -Revert a change to :func:`colorsys.rgb_to_hls` that caused division by zero -for certain almost-white inputs. Patch by Terry Jan Reedy. diff --git a/Misc/NEWS.d/next/Library/2023-07-11-12-34-04.gh-issue-89427.GOkCp9.rst b/Misc/NEWS.d/next/Library/2023-07-11-12-34-04.gh-issue-89427.GOkCp9.rst deleted file mode 100644 index 1605920cb8138b..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-07-11-12-34-04.gh-issue-89427.GOkCp9.rst +++ /dev/null @@ -1,2 +0,0 @@ -Set the environment variable ``VIRTUAL_ENV_PROMPT`` at :mod:`venv` -activation, even when ``VIRTUAL_ENV_DISABLE_PROMPT`` is set. diff --git a/Misc/NEWS.d/next/Library/2023-07-11-16-36-22.gh-issue-106628.Kx8Zvc.rst b/Misc/NEWS.d/next/Library/2023-07-11-16-36-22.gh-issue-106628.Kx8Zvc.rst deleted file mode 100644 index 6fa276e901f648..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-07-11-16-36-22.gh-issue-106628.Kx8Zvc.rst +++ /dev/null @@ -1,2 +0,0 @@ -Speed up parsing of emails by about 20% by not compiling a new regular -expression for every single email. diff --git a/Misc/NEWS.d/next/Library/2023-07-12-03-04-45.gh-issue-106664.ZeUG78.rst b/Misc/NEWS.d/next/Library/2023-07-12-03-04-45.gh-issue-106664.ZeUG78.rst deleted file mode 100644 index c278cad74bd049..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-07-12-03-04-45.gh-issue-106664.ZeUG78.rst +++ /dev/null @@ -1 +0,0 @@ -:mod:`selectors`: Add ``_SelectorMapping.get()`` method and optimize ``_SelectorMapping.__getitem__()``. diff --git a/Misc/NEWS.d/next/Library/2023-07-12-04-58-45.gh-issue-106602.dGCcXe.rst b/Misc/NEWS.d/next/Library/2023-07-12-04-58-45.gh-issue-106602.dGCcXe.rst deleted file mode 100644 index d9c122f1d3c723..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-07-12-04-58-45.gh-issue-106602.dGCcXe.rst +++ /dev/null @@ -1 +0,0 @@ -Add __copy__ and __deepcopy__ in :mod:`enum` diff --git a/Misc/NEWS.d/next/Library/2023-07-13-16-04-15.gh-issue-105481.pYSwMj.rst b/Misc/NEWS.d/next/Library/2023-07-13-16-04-15.gh-issue-105481.pYSwMj.rst deleted file mode 100644 index bc2ba51d31aa9c..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-07-13-16-04-15.gh-issue-105481.pYSwMj.rst +++ /dev/null @@ -1 +0,0 @@ -Expose opcode metadata through :mod:`_opcode`. diff --git a/Misc/NEWS.d/next/Library/2023-07-14-14-53-58.gh-issue-105293.kimf_i.rst b/Misc/NEWS.d/next/Library/2023-07-14-14-53-58.gh-issue-105293.kimf_i.rst deleted file mode 100644 index c263c8524aa962..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-07-14-14-53-58.gh-issue-105293.kimf_i.rst +++ /dev/null @@ -1,2 +0,0 @@ -Remove call to ``SSL_CTX_set_session_id_context`` during client side context -creation in the :mod:`ssl` module. diff --git a/Misc/NEWS.d/next/Library/2023-07-14-16-54-13.gh-issue-106752.BT1Yxw.rst b/Misc/NEWS.d/next/Library/2023-07-14-16-54-13.gh-issue-106752.BT1Yxw.rst deleted file mode 100644 index bbc53d76decbc3..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-07-14-16-54-13.gh-issue-106752.BT1Yxw.rst +++ /dev/null @@ -1,5 +0,0 @@ -Fixed several bugs in zipfile.Path, including: in ``Path.match`, Windows -separators are no longer honored (and never were meant to be); Fixed -``name``/``suffix``/``suffixes``/``stem`` operations when no filename is -present and the Path is not at the root of the zipfile; Reworked glob for -performance and more correct matching behavior. diff --git a/Misc/NEWS.d/next/Library/2023-07-14-20-31-09.gh-issue-106751.52F6yQ.rst b/Misc/NEWS.d/next/Library/2023-07-14-20-31-09.gh-issue-106751.52F6yQ.rst deleted file mode 100644 index 486b1f9bbd0a97..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-07-14-20-31-09.gh-issue-106751.52F6yQ.rst +++ /dev/null @@ -1 +0,0 @@ -:mod:`selectors`: Optimize ``EpollSelector.select()`` code by moving some code outside of the loop. diff --git a/Misc/NEWS.d/next/Library/2023-07-15-10-24-56.gh-issue-106774.FJcqCj.rst b/Misc/NEWS.d/next/Library/2023-07-15-10-24-56.gh-issue-106774.FJcqCj.rst deleted file mode 100644 index ed467573b89e14..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-07-15-10-24-56.gh-issue-106774.FJcqCj.rst +++ /dev/null @@ -1 +0,0 @@ -Update the bundled copy of pip to version 23.2.1. diff --git a/Misc/NEWS.d/next/Library/2023-07-15-12-52-50.gh-issue-105726.NGthO8.rst b/Misc/NEWS.d/next/Library/2023-07-15-12-52-50.gh-issue-105726.NGthO8.rst deleted file mode 100644 index 434f93240eccdf..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-07-15-12-52-50.gh-issue-105726.NGthO8.rst +++ /dev/null @@ -1,3 +0,0 @@ -Added ``__slots__`` to :class:`contextlib.AbstractContextManager` and :class:`contextlib.AbstractAsyncContextManager` -so that child classes can use ``__slots__``. - diff --git a/Misc/NEWS.d/next/Library/2023-07-16-10-40-34.gh-issue-106789.NvyE3C.rst b/Misc/NEWS.d/next/Library/2023-07-16-10-40-34.gh-issue-106789.NvyE3C.rst deleted file mode 100644 index 532f8059740daf..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-07-16-10-40-34.gh-issue-106789.NvyE3C.rst +++ /dev/null @@ -1 +0,0 @@ -Remove import of :mod:``pprint`` from :mod:``sysconfig``. diff --git a/Misc/NEWS.d/next/Library/2023-07-16-23-59-33.gh-issue-106727.bk3uCu.rst b/Misc/NEWS.d/next/Library/2023-07-16-23-59-33.gh-issue-106727.bk3uCu.rst deleted file mode 100644 index e4ea0ce1890d2f..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-07-16-23-59-33.gh-issue-106727.bk3uCu.rst +++ /dev/null @@ -1 +0,0 @@ -Make :func:`inspect.getsource` smarter for class for same name definitions diff --git a/Misc/NEWS.d/next/Library/2023-07-17-16-46-00.gh-issue-105481.fek_Nn.rst b/Misc/NEWS.d/next/Library/2023-07-17-16-46-00.gh-issue-105481.fek_Nn.rst deleted file mode 100644 index d82eb987c83e96..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-07-17-16-46-00.gh-issue-105481.fek_Nn.rst +++ /dev/null @@ -1 +0,0 @@ -The various opcode lists in the :mod:`dis` module are now generated from bytecodes.c instead of explicitly constructed in opcode.py. diff --git a/Misc/NEWS.d/next/Library/2023-07-17-21-45-15.gh-issue-106831.RqVq9X.rst b/Misc/NEWS.d/next/Library/2023-07-17-21-45-15.gh-issue-106831.RqVq9X.rst deleted file mode 100644 index d3b98626845392..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-07-17-21-45-15.gh-issue-106831.RqVq9X.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix potential missing ``NULL`` check of ``d2i_SSL_SESSION`` result in -``_ssl.c``. diff --git a/Misc/NEWS.d/next/Library/2023-07-18-23-05-12.gh-issue-106751.tVvzN_.rst b/Misc/NEWS.d/next/Library/2023-07-18-23-05-12.gh-issue-106751.tVvzN_.rst deleted file mode 100644 index 1cb8424b6221ee..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-07-18-23-05-12.gh-issue-106751.tVvzN_.rst +++ /dev/null @@ -1,2 +0,0 @@ -Optimize :meth:`KqueueSelector.select` for many iteration case. Patch By -Dong-hee Na. diff --git a/Misc/NEWS.d/next/Library/2023-07-19-09-11-08.gh-issue-106751.U9nD_B.rst b/Misc/NEWS.d/next/Library/2023-07-19-09-11-08.gh-issue-106751.U9nD_B.rst deleted file mode 100644 index b9a9b563ad2267..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-07-19-09-11-08.gh-issue-106751.U9nD_B.rst +++ /dev/null @@ -1 +0,0 @@ -Optimize :meth:`_PollLikeSelector.select` for many iteration case. diff --git a/Misc/NEWS.d/next/Library/2023-07-19-10-45-24.gh-issue-106751.3HJ1of.rst b/Misc/NEWS.d/next/Library/2023-07-19-10-45-24.gh-issue-106751.3HJ1of.rst deleted file mode 100644 index 2696b560371d13..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-07-19-10-45-24.gh-issue-106751.3HJ1of.rst +++ /dev/null @@ -1,2 +0,0 @@ -Optimize :meth:`SelectSelector.select` for many iteration case. Patch By -Dong-hee Na. diff --git a/Misc/NEWS.d/next/Library/2023-07-20-06-00-35.gh-issue-106739.W1hygr.rst b/Misc/NEWS.d/next/Library/2023-07-20-06-00-35.gh-issue-106739.W1hygr.rst deleted file mode 100644 index 168e2019395696..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-07-20-06-00-35.gh-issue-106739.W1hygr.rst +++ /dev/null @@ -1 +0,0 @@ -Add the ``rtype_cache`` to the warning message (as an addition to the type of leaked objects and the number of leaked objects already included in the message) to make debugging leaked objects easier when the multiprocessing resource tracker process finds leaked objects at shutdown. This helps more quickly identify what was leaked and/or why the leaked object was not properly cleaned up. diff --git a/Misc/NEWS.d/next/Library/2023-07-22-12-53-53.gh-issue-105002.gkfsW0.rst b/Misc/NEWS.d/next/Library/2023-07-22-12-53-53.gh-issue-105002.gkfsW0.rst deleted file mode 100644 index b4c133a5cb1244..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-07-22-12-53-53.gh-issue-105002.gkfsW0.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fix invalid result from :meth:`PurePath.relative_to` method when attempting to walk -a "``..``" segment in *other* with *walk_up* enabled. A :exc:`ValueError` exception -is now raised in this case. diff --git a/Misc/NEWS.d/next/Library/2023-07-22-13-09-28.gh-issue-106186.EIsUNG.rst b/Misc/NEWS.d/next/Library/2023-07-22-13-09-28.gh-issue-106186.EIsUNG.rst deleted file mode 100644 index 07fdcc96fa38a6..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-07-22-13-09-28.gh-issue-106186.EIsUNG.rst +++ /dev/null @@ -1,3 +0,0 @@ -Do not report ``MultipartInvariantViolationDefect`` defect -when the :class:`email.parser.Parser` class is used -to parse emails with ``headersonly=True``. diff --git a/Misc/NEWS.d/next/Library/2023-07-22-14-29-34.gh-issue-65495.fw84qM.rst b/Misc/NEWS.d/next/Library/2023-07-22-14-29-34.gh-issue-65495.fw84qM.rst deleted file mode 100644 index e75b6c0f1d6759..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-07-22-14-29-34.gh-issue-65495.fw84qM.rst +++ /dev/null @@ -1 +0,0 @@ -Use lowercase ``mail from`` and ``rcpt to`` in :class:`smptlib.SMTP`. diff --git a/Misc/NEWS.d/next/Library/2023-07-22-15-51-33.gh-issue-83006.21zaCz.rst b/Misc/NEWS.d/next/Library/2023-07-22-15-51-33.gh-issue-83006.21zaCz.rst deleted file mode 100644 index e64d1860828430..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-07-22-15-51-33.gh-issue-83006.21zaCz.rst +++ /dev/null @@ -1,2 +0,0 @@ -Document behavior of :func:`shutil.disk_usage` for non-mounted filesystems -on Unix. diff --git a/Misc/NEWS.d/next/Library/2023-07-22-16-44-58.gh-issue-82500.cQYoPj.rst b/Misc/NEWS.d/next/Library/2023-07-22-16-44-58.gh-issue-82500.cQYoPj.rst deleted file mode 100644 index 065394fd6ee712..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-07-22-16-44-58.gh-issue-82500.cQYoPj.rst +++ /dev/null @@ -1 +0,0 @@ -Fix overflow on 32-bit systems with :mod:`asyncio` :func:`os.sendfile` implemention. diff --git a/Misc/NEWS.d/next/Library/2023-07-22-21-57-34.gh-issue-107089.Dnget2.rst b/Misc/NEWS.d/next/Library/2023-07-22-21-57-34.gh-issue-107089.Dnget2.rst deleted file mode 100644 index 9d5ba1a2d7ccba..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-07-22-21-57-34.gh-issue-107089.Dnget2.rst +++ /dev/null @@ -1,2 +0,0 @@ -Shelves opened with :func:`shelve.open` have a much faster :meth:`clear` -method. Patch by James Cave. \ No newline at end of file diff --git a/Misc/NEWS.d/next/Library/2023-07-23-12-26-23.gh-issue-62519.w8-81X.rst b/Misc/NEWS.d/next/Library/2023-07-23-12-26-23.gh-issue-62519.w8-81X.rst deleted file mode 100644 index 96e2a3dcc24fb0..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-07-23-12-26-23.gh-issue-62519.w8-81X.rst +++ /dev/null @@ -1,2 +0,0 @@ -Make :func:`gettext.pgettext` search plural definitions when -translation is not found. diff --git a/Misc/NEWS.d/next/Library/2023-07-23-13-05-32.gh-issue-105578.XAQtyR.rst b/Misc/NEWS.d/next/Library/2023-07-23-13-05-32.gh-issue-105578.XAQtyR.rst deleted file mode 100644 index 4a03f5c35ff6c0..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-07-23-13-05-32.gh-issue-105578.XAQtyR.rst +++ /dev/null @@ -1,2 +0,0 @@ -Deprecate :class:`typing.AnyStr` in favor of the new Type Parameter syntax. -See PEP 695. diff --git a/Misc/NEWS.d/next/Library/2023-07-24-01-21-16.gh-issue-46376.w-xuDL.rst b/Misc/NEWS.d/next/Library/2023-07-24-01-21-16.gh-issue-46376.w-xuDL.rst deleted file mode 100644 index 8e8f0245b4539b..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-07-24-01-21-16.gh-issue-46376.w-xuDL.rst +++ /dev/null @@ -1 +0,0 @@ -Prevent memory leak and use-after-free when using pointers to pointers with ctypes diff --git a/Misc/NEWS.d/next/Library/2023-07-28-14-56-35.gh-issue-107369.bvTq8F.rst b/Misc/NEWS.d/next/Library/2023-07-28-14-56-35.gh-issue-107369.bvTq8F.rst deleted file mode 100644 index 76aeab65e90a20..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-07-28-14-56-35.gh-issue-107369.bvTq8F.rst +++ /dev/null @@ -1,2 +0,0 @@ -Optimize :func:`textwrap.indent`. It is ~30% faster for large input. Patch -by Inada Naoki. diff --git a/Misc/NEWS.d/next/Library/2023-08-01-15-17-20.gh-issue-105481.vMbmj_.rst b/Misc/NEWS.d/next/Library/2023-08-01-15-17-20.gh-issue-105481.vMbmj_.rst deleted file mode 100644 index 153c18a6f00953..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-08-01-15-17-20.gh-issue-105481.vMbmj_.rst +++ /dev/null @@ -1 +0,0 @@ -:data:`opcode.ENABLE_SPECIALIZATION` (which was added in 3.12 but never documented or intended for external usage) is moved to :data:`_opcode.ENABLE_SPECIALIZATION` where tests can access it. diff --git a/Misc/NEWS.d/next/Library/2023-08-01-21-43-58.gh-issue-105481.cl2ajS.rst b/Misc/NEWS.d/next/Library/2023-08-01-21-43-58.gh-issue-105481.cl2ajS.rst deleted file mode 100644 index d02f909e870188..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-08-01-21-43-58.gh-issue-105481.cl2ajS.rst +++ /dev/null @@ -1,2 +0,0 @@ -Remove ``opcode.is_pseudo``, ``opcode.MIN_PSEUDO_OPCODE`` and ``opcode.MAX_PSEUDO_OPCODE``, -which were added in 3.12, were never documented and were not intended to be used externally. diff --git a/Misc/NEWS.d/next/Library/2023-08-03-11-31-11.gh-issue-107576.pO_s9I.rst b/Misc/NEWS.d/next/Library/2023-08-03-11-31-11.gh-issue-107576.pO_s9I.rst deleted file mode 100644 index 67677dd3c8ed24..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-08-03-11-31-11.gh-issue-107576.pO_s9I.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fix :func:`types.get_original_bases` to only return -:attr:`!__orig_bases__` if it is present on ``cls`` directly. Patch by -James Hilton-Balfe. diff --git a/Misc/NEWS.d/next/Library/2023-08-03-12-52-19.gh-issue-107077.-pzHD6.rst b/Misc/NEWS.d/next/Library/2023-08-03-12-52-19.gh-issue-107077.-pzHD6.rst deleted file mode 100644 index ecaf437a48e0ae..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-08-03-12-52-19.gh-issue-107077.-pzHD6.rst +++ /dev/null @@ -1,6 +0,0 @@ -Seems that in some conditions, OpenSSL will return ``SSL_ERROR_SYSCALL`` -instead of ``SSL_ERROR_SSL`` when a certification verification has failed, -but the error parameters will still contain ``ERR_LIB_SSL`` and -``SSL_R_CERTIFICATE_VERIFY_FAILED``. We are now detecting this situation and -raising the appropiate ``ssl.SSLCertVerificationError``. Patch by Pablo -Galindo diff --git a/Misc/NEWS.d/next/Library/2023-08-05-05-10-41.gh-issue-106684.P9zRXb.rst b/Misc/NEWS.d/next/Library/2023-08-05-05-10-41.gh-issue-106684.P9zRXb.rst deleted file mode 100644 index 02c52d714e9df7..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-08-05-05-10-41.gh-issue-106684.P9zRXb.rst +++ /dev/null @@ -1 +0,0 @@ -Raise :exc:`ResourceWarning` when :class:`asyncio.StreamWriter` is not closed leading to memory leaks. Patch by Kumar Aditya. diff --git a/Misc/NEWS.d/next/Library/2023-08-07-21-11-24.gh-issue-102130._UyI5i.rst b/Misc/NEWS.d/next/Library/2023-08-07-21-11-24.gh-issue-102130._UyI5i.rst new file mode 100644 index 00000000000000..f582ad5df39e84 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-08-07-21-11-24.gh-issue-102130._UyI5i.rst @@ -0,0 +1 @@ +Support tab completion in :mod:`cmd` for ``editline``. diff --git a/Misc/NEWS.d/next/Library/2023-08-14-21-10-52.gh-issue-103363.u64_QI.rst b/Misc/NEWS.d/next/Library/2023-08-14-21-10-52.gh-issue-103363.u64_QI.rst new file mode 100644 index 00000000000000..d4a27d624eb5e6 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-08-14-21-10-52.gh-issue-103363.u64_QI.rst @@ -0,0 +1,2 @@ +Add *follow_symlinks* keyword-only argument to :meth:`pathlib.Path.owner` +and :meth:`~pathlib.Path.group`, defaulting to ``True``. diff --git a/Misc/NEWS.d/next/Library/2023-09-23-14-40-51.gh-issue-109786.UX3pKv.rst b/Misc/NEWS.d/next/Library/2023-09-23-14-40-51.gh-issue-109786.UX3pKv.rst new file mode 100644 index 00000000000000..07222fa339d703 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-09-23-14-40-51.gh-issue-109786.UX3pKv.rst @@ -0,0 +1,2 @@ +Fix possible reference leaks and crash when re-enter the ``__next__()`` method of +:class:`itertools.pairwise`. diff --git a/Misc/NEWS.d/next/Library/2023-09-28-13-15-51.gh-issue-109858.43e2dg.rst b/Misc/NEWS.d/next/Library/2023-09-28-13-15-51.gh-issue-109858.43e2dg.rst new file mode 100644 index 00000000000000..be279caffc46ee --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-09-28-13-15-51.gh-issue-109858.43e2dg.rst @@ -0,0 +1,3 @@ +Protect :mod:`zipfile` from "quoted-overlap" zipbomb. It now raises +BadZipFile when try to read an entry that overlaps with other entry or +central directory. diff --git a/Misc/NEWS.d/next/Library/2023-10-11-02-34-01.gh-issue-110109.RFCmHs.rst b/Misc/NEWS.d/next/Library/2023-10-11-02-34-01.gh-issue-110109.RFCmHs.rst new file mode 100644 index 00000000000000..4f12d128f49fb3 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-10-11-02-34-01.gh-issue-110109.RFCmHs.rst @@ -0,0 +1,3 @@ +Add private ``pathlib._PurePathBase`` class: a base class for +:class:`pathlib.PurePath` that omits certain magic methods. It may be made +public (along with ``_PathBase``) in future. diff --git a/Misc/NEWS.d/next/Library/2023-10-12-18-19-47.gh-issue-82300.P8-O38.rst b/Misc/NEWS.d/next/Library/2023-10-12-18-19-47.gh-issue-82300.P8-O38.rst new file mode 100644 index 00000000000000..d7e6b225489b99 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-10-12-18-19-47.gh-issue-82300.P8-O38.rst @@ -0,0 +1 @@ +Add ``track`` parameter to :class:`multiprocessing.shared_memory.SharedMemory` that allows using shared memory blocks without having to register with the POSIX resource tracker that automatically releases them upon process exit. diff --git a/Misc/NEWS.d/next/Library/2023-10-17-16-11-03.gh-issue-52161.WBYyCJ.rst b/Misc/NEWS.d/next/Library/2023-10-17-16-11-03.gh-issue-52161.WBYyCJ.rst new file mode 100644 index 00000000000000..3f598d40e4ae93 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-10-17-16-11-03.gh-issue-52161.WBYyCJ.rst @@ -0,0 +1,2 @@ +:meth:`cmd.Cmd.do_help` now cleans docstrings with :func:`inspect.cleandoc` +before writing them. Patch by Filip Åapkiewicz. diff --git a/Misc/NEWS.d/next/Library/2023-10-20-15-28-08.gh-issue-102988.dStNO7.rst b/Misc/NEWS.d/next/Library/2023-10-20-15-28-08.gh-issue-102988.dStNO7.rst new file mode 100644 index 00000000000000..3d0e9e4078c934 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-10-20-15-28-08.gh-issue-102988.dStNO7.rst @@ -0,0 +1,8 @@ +:func:`email.utils.getaddresses` and :func:`email.utils.parseaddr` now +return ``('', '')`` 2-tuples in more situations where invalid email +addresses are encountered instead of potentially inaccurate values. Add +optional *strict* parameter to these two functions: use ``strict=False`` to +get the old behavior, accept malformed inputs. +``getattr(email.utils, 'supports_strict_parsing', False)`` can be use to check +if the *strict* paramater is available. Patch by Thomas Dwyer and Victor +Stinner to improve the CVE-2023-27043 fix. diff --git a/Misc/NEWS.d/next/Library/2023-10-23-03-49-34.gh-issue-102980.aXBd54.rst b/Misc/NEWS.d/next/Library/2023-10-23-03-49-34.gh-issue-102980.aXBd54.rst new file mode 100644 index 00000000000000..d4bae4790d6fa4 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-10-23-03-49-34.gh-issue-102980.aXBd54.rst @@ -0,0 +1 @@ +Redirect the output of ``interact`` command of :mod:`pdb` to the same channel as the debugger. Add tests and improve docs. diff --git a/Misc/NEWS.d/next/Library/2023-10-23-18-42-26.gh-issue-111049.Ys7-o_.rst b/Misc/NEWS.d/next/Library/2023-10-23-18-42-26.gh-issue-111049.Ys7-o_.rst new file mode 100644 index 00000000000000..b1de348bea0a58 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-10-23-18-42-26.gh-issue-111049.Ys7-o_.rst @@ -0,0 +1,2 @@ +Fix crash during garbage collection of the :class:`io.BytesIO` buffer +object. diff --git a/Misc/NEWS.d/next/Library/2023-10-25-13-07-53.gh-issue-67790.jMn9Ad.rst b/Misc/NEWS.d/next/Library/2023-10-25-13-07-53.gh-issue-67790.jMn9Ad.rst new file mode 100644 index 00000000000000..44c5702a6551b0 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-10-25-13-07-53.gh-issue-67790.jMn9Ad.rst @@ -0,0 +1,2 @@ +Implement basic formatting support (minimum width, alignment, fill) for +:class:`fractions.Fraction`. diff --git a/Misc/NEWS.d/next/Library/2023-10-25-16-37-13.gh-issue-75666.BpsWut.rst b/Misc/NEWS.d/next/Library/2023-10-25-16-37-13.gh-issue-75666.BpsWut.rst new file mode 100644 index 00000000000000..d774cc4f7c687f --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-10-25-16-37-13.gh-issue-75666.BpsWut.rst @@ -0,0 +1,6 @@ +Fix the behavior of :mod:`tkinter` widget's ``unbind()`` method with two +arguments. Previously, ``widget.unbind(sequence, funcid)`` destroyed the +current binding for *sequence*, leaving *sequence* unbound, and deleted the +*funcid* command. Now it removes only *funcid* from the binding for +*sequence*, keeping other commands, and deletes the *funcid* command. It +leaves *sequence* unbound only if *funcid* was the last bound command. diff --git a/Misc/NEWS.d/next/Library/2023-11-02-10-13-31.gh-issue-111615.3SMixi.rst b/Misc/NEWS.d/next/Library/2023-11-02-10-13-31.gh-issue-111615.3SMixi.rst new file mode 100644 index 00000000000000..f80ab00a3adbff --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-11-02-10-13-31.gh-issue-111615.3SMixi.rst @@ -0,0 +1,2 @@ +Fix a regression caused by a fix to gh-93162 whereby you couldn't configure +a :class:`QueueHandler` without specifying handlers. diff --git a/Misc/NEWS.d/next/Library/2023-11-05-20-09-27.gh-issue-99367.HLaWKo.rst b/Misc/NEWS.d/next/Library/2023-11-05-20-09-27.gh-issue-99367.HLaWKo.rst new file mode 100644 index 00000000000000..0920da221e423f --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-11-05-20-09-27.gh-issue-99367.HLaWKo.rst @@ -0,0 +1 @@ +Do not mangle ``sys.path[0]`` in :mod:`pdb` if safe_path is set diff --git a/Misc/NEWS.d/next/Library/2023-11-08-16-11-04.gh-issue-110275.Bm6GwR.rst b/Misc/NEWS.d/next/Library/2023-11-08-16-11-04.gh-issue-110275.Bm6GwR.rst new file mode 100644 index 00000000000000..194dd5cb623f0f --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-11-08-16-11-04.gh-issue-110275.Bm6GwR.rst @@ -0,0 +1,2 @@ +Named tuple's methods ``_replace()`` and ``__replace__()`` now raise +TypeError instead of ValueError for invalid keyword arguments. diff --git a/Misc/NEWS.d/next/Library/2023-11-08-18-53-07.gh-issue-68166.1iTh4Y.rst b/Misc/NEWS.d/next/Library/2023-11-08-18-53-07.gh-issue-68166.1iTh4Y.rst new file mode 100644 index 00000000000000..30379b8fa1afaf --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-11-08-18-53-07.gh-issue-68166.1iTh4Y.rst @@ -0,0 +1,2 @@ +Add support of the "vsapi" element type in +:meth:`tkinter.ttk.Style.element_create`. diff --git a/Misc/NEWS.d/next/Library/2023-11-09-11-07-34.gh-issue-111874.dzYc3j.rst b/Misc/NEWS.d/next/Library/2023-11-09-11-07-34.gh-issue-111874.dzYc3j.rst new file mode 100644 index 00000000000000..50408202a7a5a1 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-11-09-11-07-34.gh-issue-111874.dzYc3j.rst @@ -0,0 +1,4 @@ +When creating a :class:`typing.NamedTuple` class, ensure +:func:`~object.__set_name__` is called on all objects that define +``__set_name__`` and exist in the values of the ``NamedTuple`` class's class +dictionary. Patch by Alex Waygood. diff --git a/Misc/NEWS.d/next/Library/2023-11-15-01-36-04.gh-issue-106922.qslOVH.rst b/Misc/NEWS.d/next/Library/2023-11-15-01-36-04.gh-issue-106922.qslOVH.rst new file mode 100644 index 00000000000000..b68e75ab87cd0b --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-11-15-01-36-04.gh-issue-106922.qslOVH.rst @@ -0,0 +1 @@ +Display multiple lines with ``traceback`` when errors span multiple lines. diff --git a/Misc/NEWS.d/next/Library/2023-11-15-04-53-37.gh-issue-112105.I3RcVN.rst b/Misc/NEWS.d/next/Library/2023-11-15-04-53-37.gh-issue-112105.I3RcVN.rst new file mode 100644 index 00000000000000..4243dcb190434f --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-11-15-04-53-37.gh-issue-112105.I3RcVN.rst @@ -0,0 +1 @@ +Make :func:`readline.set_completer_delims` work with libedit diff --git a/Misc/NEWS.d/next/Library/2023-11-16-10-42-15.gh-issue-112139.WpHosf.rst b/Misc/NEWS.d/next/Library/2023-11-16-10-42-15.gh-issue-112139.WpHosf.rst new file mode 100644 index 00000000000000..090dc8847d9556 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-11-16-10-42-15.gh-issue-112139.WpHosf.rst @@ -0,0 +1,3 @@ +Add :meth:`Signature.format` to format signatures to string with extra options. +And use it in :mod:`pydoc` to render more readable signatures that have new +lines between parameters. diff --git a/Misc/NEWS.d/next/Library/2023-11-16-17-18-09.gh-issue-112137.QvjGjN.rst b/Misc/NEWS.d/next/Library/2023-11-16-17-18-09.gh-issue-112137.QvjGjN.rst new file mode 100644 index 00000000000000..6b61d051966846 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-11-16-17-18-09.gh-issue-112137.QvjGjN.rst @@ -0,0 +1 @@ +Change :mod:`dis` output to display logical labels for jump targets instead of offsets. diff --git a/Misc/NEWS.d/next/Library/2023-11-21-02-58-14.gh-issue-77621.MYv5XS.rst b/Misc/NEWS.d/next/Library/2023-11-21-02-58-14.gh-issue-77621.MYv5XS.rst new file mode 100644 index 00000000000000..f3e6efc389afca --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-11-21-02-58-14.gh-issue-77621.MYv5XS.rst @@ -0,0 +1,2 @@ +Slightly improve the import time of the :mod:`pathlib` module by deferring +some imports. Patch by Barney Gale. diff --git a/Misc/NEWS.d/next/Library/2023-11-22-19-43-54.gh-issue-112292.5nDU87.rst b/Misc/NEWS.d/next/Library/2023-11-22-19-43-54.gh-issue-112292.5nDU87.rst new file mode 100644 index 00000000000000..8345e33791cde0 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-11-22-19-43-54.gh-issue-112292.5nDU87.rst @@ -0,0 +1,2 @@ +Fix a crash in :mod:`readline` when imported from a sub interpreter. Patch +by Anthony Shaw diff --git a/Misc/NEWS.d/next/Library/2023-11-22-23-08-47.gh-issue-81620.mfZ2Wf.rst b/Misc/NEWS.d/next/Library/2023-11-22-23-08-47.gh-issue-81620.mfZ2Wf.rst new file mode 100644 index 00000000000000..ff35806e4d5ed6 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-11-22-23-08-47.gh-issue-81620.mfZ2Wf.rst @@ -0,0 +1 @@ +Add extra tests for :func:`random.binomialvariate` diff --git a/Misc/NEWS.d/next/Library/2023-11-23-10-41-21.gh-issue-112332.rhTBaa.rst b/Misc/NEWS.d/next/Library/2023-11-23-10-41-21.gh-issue-112332.rhTBaa.rst new file mode 100644 index 00000000000000..bd686ad052e5b2 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-11-23-10-41-21.gh-issue-112332.rhTBaa.rst @@ -0,0 +1,2 @@ +Deprecate the ``exc_type`` field of :class:`traceback.TracebackException`. +Add ``exc_type_str`` to replace it. diff --git a/Misc/NEWS.d/next/Library/2023-11-23-12-37-22.gh-issue-112137.kM46Q6.rst b/Misc/NEWS.d/next/Library/2023-11-23-12-37-22.gh-issue-112137.kM46Q6.rst new file mode 100644 index 00000000000000..1b2e41ae96ff09 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-11-23-12-37-22.gh-issue-112137.kM46Q6.rst @@ -0,0 +1 @@ +Change :mod:`dis` output to display no-lineno as "--" instead of "None". diff --git a/Misc/NEWS.d/next/Library/2023-11-23-17-25-27.gh-issue-112345.FFApHx.rst b/Misc/NEWS.d/next/Library/2023-11-23-17-25-27.gh-issue-112345.FFApHx.rst new file mode 100644 index 00000000000000..b2b9894e6bef3a --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-11-23-17-25-27.gh-issue-112345.FFApHx.rst @@ -0,0 +1,3 @@ +Improve error message when trying to call :func:`issubclass` against a +:class:`typing.Protocol` that has non-method members. +Patch by Randolf Scholz. diff --git a/Misc/NEWS.d/next/Library/2023-11-24-09-27-01.gh-issue-112361.kYtnHW.rst b/Misc/NEWS.d/next/Library/2023-11-24-09-27-01.gh-issue-112361.kYtnHW.rst new file mode 100644 index 00000000000000..5a83f93f9fbec8 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-11-24-09-27-01.gh-issue-112361.kYtnHW.rst @@ -0,0 +1,2 @@ +Speed up a small handful of :mod:`pathlib` methods by removing some +temporary objects. diff --git a/Misc/NEWS.d/next/Library/2023-11-24-21-00-24.gh-issue-94722.GMIQIn.rst b/Misc/NEWS.d/next/Library/2023-11-24-21-00-24.gh-issue-94722.GMIQIn.rst new file mode 100644 index 00000000000000..41bd57f46ed82a --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-11-24-21-00-24.gh-issue-94722.GMIQIn.rst @@ -0,0 +1,2 @@ +Fix bug where comparison between instances of :class:`~doctest.DocTest` fails if +one of them has ``None`` as its lineno. diff --git a/Misc/NEWS.d/next/Library/2023-11-25-20-29-28.gh-issue-112405.cOtzxC.rst b/Misc/NEWS.d/next/Library/2023-11-25-20-29-28.gh-issue-112405.cOtzxC.rst new file mode 100644 index 00000000000000..f6f1bee2a0c38f --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-11-25-20-29-28.gh-issue-112405.cOtzxC.rst @@ -0,0 +1 @@ +Optimize :meth:`pathlib.PurePath.relative_to`. Patch by Alex Waygood. diff --git a/Misc/NEWS.d/next/Library/2023-11-26-13-26-56.gh-issue-112358.smhaeZ.rst b/Misc/NEWS.d/next/Library/2023-11-26-13-26-56.gh-issue-112358.smhaeZ.rst new file mode 100644 index 00000000000000..e473ded46a1309 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-11-26-13-26-56.gh-issue-112358.smhaeZ.rst @@ -0,0 +1,2 @@ +Revert change to :class:`struct.Struct` initialization that broke some cases +of subclassing. diff --git a/Misc/NEWS.d/next/Library/2023-11-26-13-44-19.gh-issue-112414.kx2E7S.rst b/Misc/NEWS.d/next/Library/2023-11-26-13-44-19.gh-issue-112414.kx2E7S.rst new file mode 100644 index 00000000000000..058e5a33227e5a --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-11-26-13-44-19.gh-issue-112414.kx2E7S.rst @@ -0,0 +1,3 @@ +Fix regression in Python 3.12 where calling :func:`repr` on a module that +had been imported using a custom :term:`loader` could fail with +:exc:`AttributeError`. Patch by Alex Waygood. diff --git a/Misc/NEWS.d/next/Library/2023-11-27-12-41-23.gh-issue-63284.q2Qi9q.rst b/Misc/NEWS.d/next/Library/2023-11-27-12-41-23.gh-issue-63284.q2Qi9q.rst new file mode 100644 index 00000000000000..abb57dccd5a91a --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-11-27-12-41-23.gh-issue-63284.q2Qi9q.rst @@ -0,0 +1 @@ +Added support for TLS-PSK (pre-shared key) mode to the :mod:`ssl` module. diff --git a/Misc/NEWS.d/next/Library/2023-11-28-02-39-30.gh-issue-101336.ya433z.rst b/Misc/NEWS.d/next/Library/2023-11-28-02-39-30.gh-issue-101336.ya433z.rst new file mode 100644 index 00000000000000..c222febae6b554 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-11-28-02-39-30.gh-issue-101336.ya433z.rst @@ -0,0 +1 @@ +Add ``keep_alive`` keyword parameter for :meth:`AbstractEventLoop.create_server` and :meth:`BaseEventLoop.create_server`. diff --git a/Misc/NEWS.d/next/Library/2023-11-28-20-01-33.gh-issue-112509.QtoKed.rst b/Misc/NEWS.d/next/Library/2023-11-28-20-01-33.gh-issue-112509.QtoKed.rst new file mode 100644 index 00000000000000..a16d67e7776bcb --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-11-28-20-01-33.gh-issue-112509.QtoKed.rst @@ -0,0 +1,3 @@ +Fix edge cases that could cause a key to be present in both the +``__required_keys__`` and ``__optional_keys__`` attributes of a +:class:`typing.TypedDict`. Patch by Jelle Zijlstra. diff --git a/Misc/NEWS.d/next/Library/2023-11-28-20-47-39.gh-issue-112328.Z2AxEY.rst b/Misc/NEWS.d/next/Library/2023-11-28-20-47-39.gh-issue-112328.Z2AxEY.rst new file mode 100644 index 00000000000000..6e6902486b7bc9 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-11-28-20-47-39.gh-issue-112328.Z2AxEY.rst @@ -0,0 +1,2 @@ +[Enum] Make ``EnumDict``, ``EnumDict.member_names``, +``EnumType._add_alias_`` and ``EnumType._add_value_alias_`` public. diff --git a/Misc/NEWS.d/next/Library/2023-11-29-02-26-32.gh-issue-112510.j-zXGc.rst b/Misc/NEWS.d/next/Library/2023-11-29-02-26-32.gh-issue-112510.j-zXGc.rst new file mode 100644 index 00000000000000..02de6fa80c1b3e --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-11-29-02-26-32.gh-issue-112510.j-zXGc.rst @@ -0,0 +1 @@ +Add :data:`readline.backend` for the backend readline uses (``editline`` or ``readline``) diff --git a/Misc/NEWS.d/next/Library/2023-11-29-10-51-41.gh-issue-112516.rFKUKN.rst b/Misc/NEWS.d/next/Library/2023-11-29-10-51-41.gh-issue-112516.rFKUKN.rst new file mode 100644 index 00000000000000..530cf992dcd77a --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-11-29-10-51-41.gh-issue-112516.rFKUKN.rst @@ -0,0 +1 @@ +Update the bundled copy of pip to version 23.3.1. diff --git a/Misc/NEWS.d/next/Library/2023-12-01-08-28-09.gh-issue-112578.bfNbfi.rst b/Misc/NEWS.d/next/Library/2023-12-01-08-28-09.gh-issue-112578.bfNbfi.rst new file mode 100644 index 00000000000000..1de5b1fe26ce6d --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-12-01-08-28-09.gh-issue-112578.bfNbfi.rst @@ -0,0 +1 @@ +Fix a spurious :exc:`RuntimeWarning` when executing the :mod:`zipfile` module. diff --git a/Misc/NEWS.d/next/Library/2023-12-01-16-09-59.gh-issue-81194.FFad1c.rst b/Misc/NEWS.d/next/Library/2023-12-01-16-09-59.gh-issue-81194.FFad1c.rst new file mode 100644 index 00000000000000..feb7a8643b97f6 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-12-01-16-09-59.gh-issue-81194.FFad1c.rst @@ -0,0 +1,3 @@ +Fix a crash in :func:`socket.if_indextoname` with specific value (UINT_MAX). +Fix an integer overflow in :func:`socket.if_indextoname` on 64-bit +non-Windows platforms. diff --git a/Misc/NEWS.d/next/Library/2023-12-01-18-05-09.gh-issue-110190.5bf-c9.rst b/Misc/NEWS.d/next/Library/2023-12-01-18-05-09.gh-issue-110190.5bf-c9.rst new file mode 100644 index 00000000000000..730b9d49119805 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-12-01-18-05-09.gh-issue-110190.5bf-c9.rst @@ -0,0 +1 @@ +Fix ctypes structs with array on Arm platform by setting ``MAX_STRUCT_SIZE`` to 32 in stgdict. Patch by Diego Russo. diff --git a/Misc/NEWS.d/next/Library/2023-12-01-21-05-46.gh-issue-112334.DmNXKh.rst b/Misc/NEWS.d/next/Library/2023-12-01-21-05-46.gh-issue-112334.DmNXKh.rst new file mode 100644 index 00000000000000..3a53a8bf84230f --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-12-01-21-05-46.gh-issue-112334.DmNXKh.rst @@ -0,0 +1,11 @@ +Fixed a performance regression in 3.12's :mod:`subprocess` on Linux where it +would no longer use the fast-path ``vfork()`` system call when it could have +due to a logic bug, instead falling back to the safe but slower ``fork()``. + +Also fixed a second 3.12.0 potential security bug. If a value of +``extra_groups=[]`` was passed to :mod:`subprocess.Popen` or related APIs, +the underlying ``setgroups(0, NULL)`` system call to clear the groups list +would not be made in the child process prior to ``exec()``. + +This was identified via code inspection in the process of fixing the first +bug. diff --git a/Misc/NEWS.d/next/Library/2023-12-02-12-55-17.gh-issue-112618.7_FT8-.rst b/Misc/NEWS.d/next/Library/2023-12-02-12-55-17.gh-issue-112618.7_FT8-.rst new file mode 100644 index 00000000000000..c732de15609c96 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-12-02-12-55-17.gh-issue-112618.7_FT8-.rst @@ -0,0 +1,2 @@ +Fix a caching bug relating to :data:`typing.Annotated`. +``Annotated[str, True]`` is no longer identical to ``Annotated[str, 1]``. diff --git a/Misc/NEWS.d/next/Library/2023-12-03-01-01-52.gh-issue-112622.1Z8cpx.rst b/Misc/NEWS.d/next/Library/2023-12-03-01-01-52.gh-issue-112622.1Z8cpx.rst new file mode 100644 index 00000000000000..91c88bac334dcb --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-12-03-01-01-52.gh-issue-112622.1Z8cpx.rst @@ -0,0 +1,2 @@ +Ensure ``name`` parameter is passed to event loop in +:func:`asyncio.create_task`. diff --git a/Misc/NEWS.d/next/Library/2023-12-03-11-15-53.gh-issue-112640.-FVwP7.rst b/Misc/NEWS.d/next/Library/2023-12-03-11-15-53.gh-issue-112640.-FVwP7.rst new file mode 100644 index 00000000000000..901d4368173a8c --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-12-03-11-15-53.gh-issue-112640.-FVwP7.rst @@ -0,0 +1,2 @@ +Add ``kwdefaults`` parameter to :data:`types.FunctionType` to set +default keyword argument values. diff --git a/Misc/NEWS.d/next/Library/2023-12-03-12-41-48.gh-issue-112645.blMsKf.rst b/Misc/NEWS.d/next/Library/2023-12-03-12-41-48.gh-issue-112645.blMsKf.rst new file mode 100644 index 00000000000000..4e8f6ebdb882e0 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-12-03-12-41-48.gh-issue-112645.blMsKf.rst @@ -0,0 +1 @@ +Remove deprecation error on passing ``onerror`` to :func:`shutil.rmtree`. diff --git a/Misc/NEWS.d/next/Library/2023-12-04-14-05-24.gh-issue-74690.eODKRm.rst b/Misc/NEWS.d/next/Library/2023-12-04-14-05-24.gh-issue-74690.eODKRm.rst new file mode 100644 index 00000000000000..36d793f787302e --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-12-04-14-05-24.gh-issue-74690.eODKRm.rst @@ -0,0 +1,5 @@ +Speedup :func:`isinstance` checks by roughly 20% for +:func:`runtime-checkable protocols ` +that only have one callable member. +Speedup :func:`issubclass` checks for these protocols by roughly 10%. +Patch by Alex Waygood. diff --git a/Misc/NEWS.d/next/Library/2023-12-04-16-45-11.gh-issue-74690.pQYP5U.rst b/Misc/NEWS.d/next/Library/2023-12-04-16-45-11.gh-issue-74690.pQYP5U.rst new file mode 100644 index 00000000000000..8102f02e941c29 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-12-04-16-45-11.gh-issue-74690.pQYP5U.rst @@ -0,0 +1,2 @@ +Speedup :func:`issubclass` checks against simple :func:`runtime-checkable +protocols ` by around 6%. Patch by Alex Waygood. diff --git a/Misc/NEWS.d/next/Library/2023-12-04-21-30-34.gh-issue-112727.jpgNRB.rst b/Misc/NEWS.d/next/Library/2023-12-04-21-30-34.gh-issue-112727.jpgNRB.rst new file mode 100644 index 00000000000000..bbe7aae5732d9a --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-12-04-21-30-34.gh-issue-112727.jpgNRB.rst @@ -0,0 +1 @@ +Speed up :meth:`pathlib.Path.absolute`. Patch by Barney Gale. diff --git a/Misc/NEWS.d/next/Library/2023-12-05-01-19-28.gh-issue-112736.rdHDrU.rst b/Misc/NEWS.d/next/Library/2023-12-05-01-19-28.gh-issue-112736.rdHDrU.rst new file mode 100644 index 00000000000000..6c09e622923af8 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-12-05-01-19-28.gh-issue-112736.rdHDrU.rst @@ -0,0 +1 @@ +The use of del-safe symbols in ``subprocess`` was refactored to allow for use in cross-platform build environments. diff --git a/Misc/NEWS.d/next/Library/2023-12-05-16-20-40.gh-issue-94692.-e5C3c.rst b/Misc/NEWS.d/next/Library/2023-12-05-16-20-40.gh-issue-94692.-e5C3c.rst new file mode 100644 index 00000000000000..c67ba6c9ececdb --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-12-05-16-20-40.gh-issue-94692.-e5C3c.rst @@ -0,0 +1,4 @@ +:func:`shutil.rmtree` now only catches OSError exceptions. Previously a +symlink attack resistant version of ``shutil.rmtree()`` could ignore or pass +to the error handler arbitrary exception when invalid arguments were +provided. diff --git a/Misc/NEWS.d/next/Library/2023-12-05-18-57-53.gh-issue-79325.P2vMVK.rst b/Misc/NEWS.d/next/Library/2023-12-05-18-57-53.gh-issue-79325.P2vMVK.rst new file mode 100644 index 00000000000000..f3c32d27b5fe66 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-12-05-18-57-53.gh-issue-79325.P2vMVK.rst @@ -0,0 +1,2 @@ +Fix an infinite recursion error in :func:`tempfile.TemporaryDirectory` +cleanup on Windows. diff --git a/Misc/NEWS.d/next/Library/2023-12-06-14-06-14.gh-issue-51944.-5qq_L.rst b/Misc/NEWS.d/next/Library/2023-12-06-14-06-14.gh-issue-51944.-5qq_L.rst new file mode 100644 index 00000000000000..821eefa7cffcd5 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-12-06-14-06-14.gh-issue-51944.-5qq_L.rst @@ -0,0 +1,6 @@ +Add the following constants to the :mod:`termios` module. These values are +present in macOS system headers: ``ALTWERASE``, ``B14400``, ``B28800``, +``B7200``, ``B76800``, ``CCAR_OFLOW``, ``CCTS_OFLOW``, ``CDSR_OFLOW``, +``CDTR_IFLOW``, ``CIGNORE``, ``CRTS_IFLOW``, ``EXTPROC``, ``IUTF8``, +``MDMBUF``, ``NL2``, ``NL3``, ``NOKERNINFO``, ``ONOEOT``, ``OXTABS``, +``VDSUSP``, ``VSTATUS``. diff --git a/Misc/NEWS.d/next/Library/2023-12-06-16-01-33.gh-issue-112800.TNsGJ-.rst b/Misc/NEWS.d/next/Library/2023-12-06-16-01-33.gh-issue-112800.TNsGJ-.rst new file mode 100644 index 00000000000000..e88eac169177a9 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-12-06-16-01-33.gh-issue-112800.TNsGJ-.rst @@ -0,0 +1,2 @@ +Fix :mod:`asyncio` ``SubprocessTransport.close()`` not to throw +``PermissionError`` when used with setuid executables. diff --git a/Misc/NEWS.d/next/Library/2023-12-07-16-55-41.gh-issue-87286.MILC9_.rst b/Misc/NEWS.d/next/Library/2023-12-07-16-55-41.gh-issue-87286.MILC9_.rst new file mode 100644 index 00000000000000..bfeec3c95207cb --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-12-07-16-55-41.gh-issue-87286.MILC9_.rst @@ -0,0 +1,3 @@ +Added :const:`LOG_FTP`, :const:`LOG_NETINFO`, :const:`LOG_REMOTEAUTH`, +:const:`LOG_INSTALL`, :const:`LOG_RAS`, and :const:`LOG_LAUNCHD` tot the +:mod:`syslog` module, all of them constants on used on macOS. diff --git a/Misc/NEWS.d/next/Library/2023-12-08-11-17-17.gh-issue-112540.Pm5egX.rst b/Misc/NEWS.d/next/Library/2023-12-08-11-17-17.gh-issue-112540.Pm5egX.rst new file mode 100644 index 00000000000000..263b13d1762bf1 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-12-08-11-17-17.gh-issue-112540.Pm5egX.rst @@ -0,0 +1,2 @@ +The statistics.geometric_mean() function now returns zero for datasets +containing a zero. Formerly, it would raise an exception. diff --git a/Misc/NEWS.d/next/Library/2023-12-11-14-12-46.gh-issue-110190.e0iEUa.rst b/Misc/NEWS.d/next/Library/2023-12-11-14-12-46.gh-issue-110190.e0iEUa.rst new file mode 100644 index 00000000000000..3bfed1e0f1dc91 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-12-11-14-12-46.gh-issue-110190.e0iEUa.rst @@ -0,0 +1 @@ +Fix ctypes structs with array on PPC64LE platform by setting ``MAX_STRUCT_SIZE`` to 64 in stgdict. Patch by Diego Russo. diff --git a/Misc/NEWS.d/next/Library/2023-12-11-16-13-15.gh-issue-112970.87jmKP.rst b/Misc/NEWS.d/next/Library/2023-12-11-16-13-15.gh-issue-112970.87jmKP.rst new file mode 100644 index 00000000000000..58ca26af511383 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-12-11-16-13-15.gh-issue-112970.87jmKP.rst @@ -0,0 +1 @@ +Use :c:func:`!closefrom` on Linux where available (e.g. glibc-2.34), rather than only FreeBSD. diff --git a/Misc/NEWS.d/next/Library/2023-12-12-05-48-17.gh-issue-112989.ZAa_eq.rst b/Misc/NEWS.d/next/Library/2023-12-12-05-48-17.gh-issue-112989.ZAa_eq.rst new file mode 100644 index 00000000000000..ceeab8cc7d6bec --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-12-12-05-48-17.gh-issue-112989.ZAa_eq.rst @@ -0,0 +1 @@ +Reduce overhead to connect sockets with :mod:`asyncio` SelectorEventLoop. diff --git a/Misc/NEWS.d/next/Library/2023-12-12-16-32-55.gh-issue-112962.ZZWXZn.rst b/Misc/NEWS.d/next/Library/2023-12-12-16-32-55.gh-issue-112962.ZZWXZn.rst new file mode 100644 index 00000000000000..b99e6bc90ae791 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-12-12-16-32-55.gh-issue-112962.ZZWXZn.rst @@ -0,0 +1,3 @@ +:mod:`dis` module functions add cache information to the +:class:`~dis.Instruction` instance rather than creating fake +:class:`~dis.Instruction` instances to represent the cache entries. diff --git a/Misc/NEWS.d/next/Library/2023-12-12-20-15-57.gh-issue-112559.IgXkje.rst b/Misc/NEWS.d/next/Library/2023-12-12-20-15-57.gh-issue-112559.IgXkje.rst new file mode 100644 index 00000000000000..c08cb7c3ba5ea5 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-12-12-20-15-57.gh-issue-112559.IgXkje.rst @@ -0,0 +1,3 @@ +:func:`signal.signal` and :func:`signal.getsignal` no longer call ``repr`` on +callable handlers. :func:`asyncio.run` and :meth:`asyncio.Runner.run` no longer +call ``repr`` on the task results. Patch by Yilei Yang. diff --git a/Misc/NEWS.d/next/Library/2023-12-13-17-08-21.gh-issue-59616.JNlWSs.rst b/Misc/NEWS.d/next/Library/2023-12-13-17-08-21.gh-issue-59616.JNlWSs.rst new file mode 100644 index 00000000000000..793ae63b4c1ff5 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-12-13-17-08-21.gh-issue-59616.JNlWSs.rst @@ -0,0 +1,3 @@ +Add support of :func:`os.lchmod` and the *follow_symlinks* argument in +:func:`os.chmod` on Windows. Note that the default value of *follow_symlinks* +in :func:`!os.lchmod` is ``False`` on Windows. diff --git a/Misc/NEWS.d/next/Library/2023-12-15-09-51-41.gh-issue-113175.RHsNwE.rst b/Misc/NEWS.d/next/Library/2023-12-15-09-51-41.gh-issue-113175.RHsNwE.rst new file mode 100644 index 00000000000000..1b43803d1a7aa4 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-12-15-09-51-41.gh-issue-113175.RHsNwE.rst @@ -0,0 +1,5 @@ +Sync with importlib_metadata 7.0, including improved type annotations, fixed +issue with symlinked packages in ``package_distributions``, added +``EntryPoints.__repr__``, introduced the ``diagnose`` script, added +``Distribution.origin`` property, and removed deprecated ``EntryPoint`` +access by numeric index (tuple behavior). diff --git a/Misc/NEWS.d/next/Library/2023-12-15-12-35-28.gh-issue-61648.G-4pz0.rst b/Misc/NEWS.d/next/Library/2023-12-15-12-35-28.gh-issue-61648.G-4pz0.rst new file mode 100644 index 00000000000000..c841e5c7f7683a --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-12-15-12-35-28.gh-issue-61648.G-4pz0.rst @@ -0,0 +1 @@ +Detect line numbers of properties in doctests. diff --git a/Misc/NEWS.d/next/Library/2023-12-15-18-10-26.gh-issue-113202.xv_Ww8.rst b/Misc/NEWS.d/next/Library/2023-12-15-18-10-26.gh-issue-113202.xv_Ww8.rst new file mode 100644 index 00000000000000..44f26aef60a33a --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-12-15-18-10-26.gh-issue-113202.xv_Ww8.rst @@ -0,0 +1 @@ +Add a ``strict`` option to ``batched()`` in the ``itertools`` module. diff --git a/Misc/NEWS.d/next/Library/2023-12-15-18-13-59.gh-issue-113119.al-569.rst b/Misc/NEWS.d/next/Library/2023-12-15-18-13-59.gh-issue-113119.al-569.rst new file mode 100644 index 00000000000000..94087b00515e97 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-12-15-18-13-59.gh-issue-113119.al-569.rst @@ -0,0 +1,2 @@ +:func:`os.posix_spawn` now accepts ``env=None``, which makes the newly spawned +process use the current process environment. Patch by Jakub Kulik. diff --git a/Misc/NEWS.d/next/Library/2023-12-15-20-29-49.gh-issue-113188.AvoraB.rst b/Misc/NEWS.d/next/Library/2023-12-15-20-29-49.gh-issue-113188.AvoraB.rst new file mode 100644 index 00000000000000..17c69572d9f2b1 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-12-15-20-29-49.gh-issue-113188.AvoraB.rst @@ -0,0 +1,6 @@ +Fix :func:`shutil.copymode` and :func:`shutil.copystat` on Windows. +Previously they worked differenly if *dst* is a symbolic link: +they modified the permission bits of *dst* itself +rather than the file it points to if *follow_symlinks* is true or *src* is +not a symbolic link, and did not modify the permission bits if +*follow_symlinks* is false and *src* is a symbolic link. diff --git a/Misc/NEWS.d/next/Library/2023-12-15-21-33-42.gh-issue-113191.Il155b.rst b/Misc/NEWS.d/next/Library/2023-12-15-21-33-42.gh-issue-113191.Il155b.rst new file mode 100644 index 00000000000000..13fe4ff5f6a8bd --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-12-15-21-33-42.gh-issue-113191.Il155b.rst @@ -0,0 +1,2 @@ +Add support of :func:`os.fchmod` and a file descriptor in :func:`os.chmod` +on Windows. diff --git a/Misc/NEWS.d/next/Library/2023-12-16-01-10-47.gh-issue-113199.oDjnjL.rst b/Misc/NEWS.d/next/Library/2023-12-16-01-10-47.gh-issue-113199.oDjnjL.rst new file mode 100644 index 00000000000000..d8e0b1731d1e3b --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-12-16-01-10-47.gh-issue-113199.oDjnjL.rst @@ -0,0 +1,3 @@ +Make ``http.client.HTTPResponse.read1`` and +``http.client.HTTPResponse.readline`` close IO after reading all data when +content length is known. Patch by Illia Volochii. diff --git a/Misc/NEWS.d/next/Library/2023-12-16-10-58-34.gh-issue-113117.0zF7bH.rst b/Misc/NEWS.d/next/Library/2023-12-16-10-58-34.gh-issue-113117.0zF7bH.rst new file mode 100644 index 00000000000000..718226a0021efe --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-12-16-10-58-34.gh-issue-113117.0zF7bH.rst @@ -0,0 +1,4 @@ +The :mod:`subprocess` module can now use the :func:`os.posix_spawn` function +with ``close_fds=True`` on platforms where +``posix_spawn_file_actions_addclosefrom_np`` is available. +Patch by Jakub Kulik. diff --git a/Misc/NEWS.d/next/Library/2023-12-16-23-56-42.gh-issue-113149.7LWgTS.rst b/Misc/NEWS.d/next/Library/2023-12-16-23-56-42.gh-issue-113149.7LWgTS.rst new file mode 100644 index 00000000000000..0faa67fefabeca --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-12-16-23-56-42.gh-issue-113149.7LWgTS.rst @@ -0,0 +1,2 @@ +Improve error message when a JSON array or object contains a trailing comma. +Patch by Carson Radtke. diff --git a/Misc/NEWS.d/next/Library/2023-12-17-04-43-57.gh-issue-113225.dhxhiZ.rst b/Misc/NEWS.d/next/Library/2023-12-17-04-43-57.gh-issue-113225.dhxhiZ.rst new file mode 100644 index 00000000000000..7160cca2e11366 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-12-17-04-43-57.gh-issue-113225.dhxhiZ.rst @@ -0,0 +1 @@ +Speed up :meth:`pathlib.Path.glob` by using :attr:`os.DirEntry.path` where possible. diff --git a/Misc/NEWS.d/next/Library/2023-12-17-10-22-55.gh-issue-112182.jLWGlr.rst b/Misc/NEWS.d/next/Library/2023-12-17-10-22-55.gh-issue-112182.jLWGlr.rst new file mode 100644 index 00000000000000..dc5bb697aac414 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-12-17-10-22-55.gh-issue-112182.jLWGlr.rst @@ -0,0 +1,3 @@ +:meth:`asyncio.futures.Future.set_exception()` now transforms :exc:`StopIteration` +into :exc:`RuntimeError` instead of hanging or other misbehavior. Patch +contributed by Jamie Phan. diff --git a/Misc/NEWS.d/next/Library/2023-12-17-13-56-30.gh-issue-87264.RgfHCv.rst b/Misc/NEWS.d/next/Library/2023-12-17-13-56-30.gh-issue-87264.RgfHCv.rst new file mode 100644 index 00000000000000..fa987d4f0af9ba --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-12-17-13-56-30.gh-issue-87264.RgfHCv.rst @@ -0,0 +1 @@ +Fixed tarfile list() method to show file type. diff --git a/Misc/NEWS.d/next/Library/2023-12-18-09-47-54.gh-issue-113246.em930H.rst b/Misc/NEWS.d/next/Library/2023-12-18-09-47-54.gh-issue-113246.em930H.rst new file mode 100644 index 00000000000000..167bb37c0e0643 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-12-18-09-47-54.gh-issue-113246.em930H.rst @@ -0,0 +1 @@ +Update bundled pip to 23.3.2. diff --git a/Misc/NEWS.d/next/Library/2023-12-20-21-18-51.gh-issue-113214.JcV9Mn.rst b/Misc/NEWS.d/next/Library/2023-12-20-21-18-51.gh-issue-113214.JcV9Mn.rst new file mode 100644 index 00000000000000..6db74cda166e92 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-12-20-21-18-51.gh-issue-113214.JcV9Mn.rst @@ -0,0 +1 @@ +Fix an ``AttributeError`` during asyncio SSL protocol aborts in SSL-over-SSL scenarios. diff --git a/Misc/NEWS.d/next/Library/2023-12-21-23-47-42.gh-issue-53502.dercJI.rst b/Misc/NEWS.d/next/Library/2023-12-21-23-47-42.gh-issue-53502.dercJI.rst new file mode 100644 index 00000000000000..aa7274161d4166 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-12-21-23-47-42.gh-issue-53502.dercJI.rst @@ -0,0 +1,2 @@ +Add a new option ``aware_datetime`` in :mod:`plistlib` to loads or dumps +aware datetime. diff --git a/Misc/NEWS.d/next/Library/2023-12-22-11-30-57.gh-issue-113320.Vp5suS.rst b/Misc/NEWS.d/next/Library/2023-12-22-11-30-57.gh-issue-113320.Vp5suS.rst new file mode 100644 index 00000000000000..6cf74f335d4d7d --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-12-22-11-30-57.gh-issue-113320.Vp5suS.rst @@ -0,0 +1,4 @@ +Fix regression in Python 3.12 where :class:`~typing.Protocol` classes that +were not marked as :func:`runtime-checkable ` +would be unnecessarily introspected, potentially causing exceptions to be +raised if the protocol had problematic members. Patch by Alex Waygood. diff --git a/Misc/NEWS.d/next/Library/2023-12-22-20-49-52.gh-issue-113407.C_O13_.rst b/Misc/NEWS.d/next/Library/2023-12-22-20-49-52.gh-issue-113407.C_O13_.rst new file mode 100644 index 00000000000000..da00977f03cefd --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-12-22-20-49-52.gh-issue-113407.C_O13_.rst @@ -0,0 +1 @@ +Fix import of :mod:`unittest.mock` when CPython is built without docstrings. diff --git a/Misc/NEWS.d/next/Library/2023-12-23-13-10-42.gh-issue-111784.Nb4L1j.rst b/Misc/NEWS.d/next/Library/2023-12-23-13-10-42.gh-issue-111784.Nb4L1j.rst new file mode 100644 index 00000000000000..51ac0752cfae84 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-12-23-13-10-42.gh-issue-111784.Nb4L1j.rst @@ -0,0 +1,5 @@ +Fix segfaults in the ``_elementtree`` module. +Fix first segfault during deallocation of ``_elementtree.XMLParser`` instances by keeping strong reference +to ``pyexpat`` module in module state for capsule lifetime. +Fix second segfault which happens in the same deallocation process by keeping strong reference +to ``_elementtree`` module in ``XMLParser`` structure for ``_elementtree`` module lifetime. diff --git a/Misc/NEWS.d/next/Library/2023-12-23-16-10-07.gh-issue-113421.w7vs08.rst b/Misc/NEWS.d/next/Library/2023-12-23-16-10-07.gh-issue-113421.w7vs08.rst new file mode 100644 index 00000000000000..2082fe6391d261 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-12-23-16-10-07.gh-issue-113421.w7vs08.rst @@ -0,0 +1 @@ +Fix multiprocessing logger for ``%(filename)s``. diff --git a/Misc/NEWS.d/next/Library/2023-12-23-16-51-17.gh-issue-113028.3Jmdoj.rst b/Misc/NEWS.d/next/Library/2023-12-23-16-51-17.gh-issue-113028.3Jmdoj.rst new file mode 100644 index 00000000000000..5f66d6a00b4d3d --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-12-23-16-51-17.gh-issue-113028.3Jmdoj.rst @@ -0,0 +1,6 @@ +When a second reference to a string appears in the input to :mod:`pickle`, +and the Python implementation is in use, +we are guaranteed that a single copy gets pickled +and a single object is shared when reloaded. +Previously, in protocol 0, when a string contained certain characters +(e.g. newline) it resulted in duplicate objects. diff --git a/Misc/NEWS.d/next/Library/2023-12-28-14-36-20.gh-issue-113543.2iWkOR.rst b/Misc/NEWS.d/next/Library/2023-12-28-14-36-20.gh-issue-113543.2iWkOR.rst new file mode 100644 index 00000000000000..5bf557bedd0204 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-12-28-14-36-20.gh-issue-113543.2iWkOR.rst @@ -0,0 +1,2 @@ +Make sure that ``webbrowser.MacOSXOSAScript`` sends ``webbrowser.open`` +audit event. diff --git a/Misc/NEWS.d/next/Library/2023-12-29-17-30-49.gh-issue-113568.UpWNAI.rst b/Misc/NEWS.d/next/Library/2023-12-29-17-30-49.gh-issue-113568.UpWNAI.rst new file mode 100644 index 00000000000000..aaca5250184122 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-12-29-17-30-49.gh-issue-113568.UpWNAI.rst @@ -0,0 +1,2 @@ +Raise audit events from :class:`pathlib.Path` and not its private base class +``PathBase``. diff --git a/Misc/NEWS.d/next/Library/2023-12-29-17-57-45.gh-issue-113569.qcRCEI.rst b/Misc/NEWS.d/next/Library/2023-12-29-17-57-45.gh-issue-113569.qcRCEI.rst new file mode 100644 index 00000000000000..9b63fc940991fe --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-12-29-17-57-45.gh-issue-113569.qcRCEI.rst @@ -0,0 +1,2 @@ +Indicate if there were no actual calls in unittest +:meth:`~unittest.mock.Mock.assert_has_calls` failure. diff --git a/Misc/NEWS.d/next/Library/2023-12-29-22-29-34.gh-issue-89850.KnxiZA.rst b/Misc/NEWS.d/next/Library/2023-12-29-22-29-34.gh-issue-89850.KnxiZA.rst new file mode 100644 index 00000000000000..90251ad353c170 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-12-29-22-29-34.gh-issue-89850.KnxiZA.rst @@ -0,0 +1,5 @@ +Add default implementations of :meth:`pickle.Pickler.persistent_id` and +:meth:`pickle.Unpickler.persistent_load` methods in the C implementation. +Calling ``super().persistent_id()`` and ``super().persistent_load()`` in +subclasses of the C implementation of :class:`pickle.Pickler` and +:class:`pickle.Unpickler` classes no longer causes infinite recursion. diff --git a/Misc/NEWS.d/next/Library/2023-12-30-20-30-05.gh-issue-113537.v1W5_X.rst b/Misc/NEWS.d/next/Library/2023-12-30-20-30-05.gh-issue-113537.v1W5_X.rst new file mode 100644 index 00000000000000..a6150815b285a9 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-12-30-20-30-05.gh-issue-113537.v1W5_X.rst @@ -0,0 +1 @@ +Support loads ``str`` in :func:`plistlib.loads`. diff --git a/Misc/NEWS.d/next/Library/2024-01-01-13-26-02.gh-issue-85567.K4U15m.rst b/Misc/NEWS.d/next/Library/2024-01-01-13-26-02.gh-issue-85567.K4U15m.rst new file mode 100644 index 00000000000000..063443e5aecc02 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-01-01-13-26-02.gh-issue-85567.K4U15m.rst @@ -0,0 +1,2 @@ +Fix resource warnings for unclosed files in :mod:`pickle` and +:mod:`pickletools` command line interfaces. diff --git a/Misc/NEWS.d/next/Library/2024-01-03-14-19-26.gh-issue-113538.ahuBCo.rst b/Misc/NEWS.d/next/Library/2024-01-03-14-19-26.gh-issue-113538.ahuBCo.rst new file mode 100644 index 00000000000000..a52076501b7bf4 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-01-03-14-19-26.gh-issue-113538.ahuBCo.rst @@ -0,0 +1,5 @@ +In :meth:`asyncio.StreamReaderProtocol.connection_made`, there is callback +that logs an error if the task wrapping the "connected callback" fails. This +callback would itself fail if the task was cancelled. Prevent this by +checking whether the task was cancelled first. If so, close the transport +but don't log an error. diff --git a/Misc/NEWS.d/next/Library/2024-01-05-12-42-07.gh-issue-113594.4t8HiR.rst b/Misc/NEWS.d/next/Library/2024-01-05-12-42-07.gh-issue-113594.4t8HiR.rst new file mode 100644 index 00000000000000..c71bc9c20e4596 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-01-05-12-42-07.gh-issue-113594.4t8HiR.rst @@ -0,0 +1,2 @@ +Fix :exc:`UnicodeEncodeError` in :mod:`email` when re-fold lines that +contain unknown-8bit encoded part followed by non-unknown-8bit encoded part. diff --git a/Misc/NEWS.d/next/Library/2024-01-05-21-52-59.gh-issue-113568._0FkpZ.rst b/Misc/NEWS.d/next/Library/2024-01-05-21-52-59.gh-issue-113568._0FkpZ.rst new file mode 100644 index 00000000000000..4900730ddff5fa --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-01-05-21-52-59.gh-issue-113568._0FkpZ.rst @@ -0,0 +1,2 @@ +Raise deprecation warnings from :class:`pathlib.PurePath` and not its +private base class ``PurePathBase``. diff --git a/Misc/NEWS.d/next/Library/2024-01-07-00-56-41.gh-issue-112932.OfhUu7.rst b/Misc/NEWS.d/next/Library/2024-01-07-00-56-41.gh-issue-112932.OfhUu7.rst new file mode 100644 index 00000000000000..c61525ca67d2b0 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-01-07-00-56-41.gh-issue-112932.OfhUu7.rst @@ -0,0 +1,3 @@ +Restore the ability for :mod:`zipfile` to ``extractall`` from zip files with +a "/" directory entry in them as is commonly added to zips by some wiki or +bug tracker data exporters. diff --git a/Misc/NEWS.d/next/Library/2024-01-07-11-45-56.gh-issue-113791.XF5xSW.rst b/Misc/NEWS.d/next/Library/2024-01-07-11-45-56.gh-issue-113791.XF5xSW.rst new file mode 100644 index 00000000000000..16e77269813560 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-01-07-11-45-56.gh-issue-113791.XF5xSW.rst @@ -0,0 +1,2 @@ +Add ``CLOCK_MONOTONIC_RAW_APPROX`` and ``CLOCK_UPTIME_RAW_APPROX`` to +:mod:`time` on macOS. These are clocks available on macOS 10.12 or later. diff --git a/Misc/NEWS.d/next/Library/2024-01-07-13-36-03.gh-issue-111693.xN2LuL.rst b/Misc/NEWS.d/next/Library/2024-01-07-13-36-03.gh-issue-111693.xN2LuL.rst new file mode 100644 index 00000000000000..2201f4702a6711 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-01-07-13-36-03.gh-issue-111693.xN2LuL.rst @@ -0,0 +1 @@ +:func:`asyncio.Condition.wait()` now re-raises the same :exc:`CancelledError` instance that may have caused it to be interrupted. Fixed race condition in :func:`asyncio.Semaphore.aquire` when interrupted with a :exc:`CancelledError`. diff --git a/Misc/NEWS.d/next/Library/2024-01-08-14-57-09.gh-issue-113781.IoTnwi.rst b/Misc/NEWS.d/next/Library/2024-01-08-14-57-09.gh-issue-113781.IoTnwi.rst new file mode 100644 index 00000000000000..141230b066e22e --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-01-08-14-57-09.gh-issue-113781.IoTnwi.rst @@ -0,0 +1,2 @@ +Silence unraisable AttributeError when warnings are emitted during Python +finalization. diff --git a/Misc/NEWS.d/next/Library/2024-01-08-19-38-42.gh-issue-96037.Yr2Y1C.rst b/Misc/NEWS.d/next/Library/2024-01-08-19-38-42.gh-issue-96037.Yr2Y1C.rst new file mode 100644 index 00000000000000..525925b08230ed --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-01-08-19-38-42.gh-issue-96037.Yr2Y1C.rst @@ -0,0 +1,2 @@ +Insert :exc:`TimeoutError` in the context of the exception that was raised +during exiting an expired :func:`asyncio.timeout` block. diff --git a/Misc/NEWS.d/next/Library/2024-01-09-08-59-43.gh-issue-113661.asvXSx.rst b/Misc/NEWS.d/next/Library/2024-01-09-08-59-43.gh-issue-113661.asvXSx.rst new file mode 100644 index 00000000000000..f4a4f1a9841d1a --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-01-09-08-59-43.gh-issue-113661.asvXSx.rst @@ -0,0 +1,3 @@ +unittest runner: Don't exit 5 if tests were skipped. The intention of +exiting 5 was to detect issues where the test suite wasn't discovered at +all. If we skipped tests, it was correctly discovered. diff --git a/Misc/NEWS.d/next/Library/2024-01-09-12-19-55.gh-issue-113848.kXoCy0.rst b/Misc/NEWS.d/next/Library/2024-01-09-12-19-55.gh-issue-113848.kXoCy0.rst new file mode 100644 index 00000000000000..8d5032ab0201f9 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-01-09-12-19-55.gh-issue-113848.kXoCy0.rst @@ -0,0 +1,3 @@ +:func:`asyncio.TaskGroup()` and :func:`asyncio.timeout()` context managers +now handle :exc:`~asyncio.CancelledError` subclasses as well as exact +:exc:`!CancelledError`. diff --git a/Misc/NEWS.d/next/Library/2024-01-10-12-03-38.gh-issue-113877.RxKlrQ.rst b/Misc/NEWS.d/next/Library/2024-01-10-12-03-38.gh-issue-113877.RxKlrQ.rst new file mode 100644 index 00000000000000..173e185fe6c632 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-01-10-12-03-38.gh-issue-113877.RxKlrQ.rst @@ -0,0 +1 @@ +Fix :mod:`tkinter` method ``winfo_pathname()`` on 64-bit Windows. diff --git a/Misc/NEWS.d/next/Security/2023-03-07-21-46-29.gh-issue-102509.5ouaH_.rst b/Misc/NEWS.d/next/Security/2023-03-07-21-46-29.gh-issue-102509.5ouaH_.rst deleted file mode 100644 index d1a8e8b5a8d3c4..00000000000000 --- a/Misc/NEWS.d/next/Security/2023-03-07-21-46-29.gh-issue-102509.5ouaH_.rst +++ /dev/null @@ -1,2 +0,0 @@ -Start initializing ``ob_digit`` during creation of :c:type:`PyLongObject` -objects. Patch by Illia Volochii. diff --git a/Misc/NEWS.d/next/Security/2023-05-24-09-29-08.gh-issue-99108.hwS2cr.rst b/Misc/NEWS.d/next/Security/2023-05-24-09-29-08.gh-issue-99108.hwS2cr.rst deleted file mode 100644 index 312ba89454b5b8..00000000000000 --- a/Misc/NEWS.d/next/Security/2023-05-24-09-29-08.gh-issue-99108.hwS2cr.rst +++ /dev/null @@ -1,2 +0,0 @@ -Refresh our new HACL* built-in :mod:`hashlib` code from upstream. Built-in -SHA2 should be faster and an issue with SHA3 on 32-bit platforms is fixed. diff --git a/Misc/NEWS.d/next/Security/2023-06-01-03-24-58.gh-issue-103142.GLWDMX.rst b/Misc/NEWS.d/next/Security/2023-06-01-03-24-58.gh-issue-103142.GLWDMX.rst deleted file mode 100644 index 7e0836879e4f81..00000000000000 --- a/Misc/NEWS.d/next/Security/2023-06-01-03-24-58.gh-issue-103142.GLWDMX.rst +++ /dev/null @@ -1,2 +0,0 @@ -The version of OpenSSL used in our binary builds has been upgraded to 1.1.1u -to address several CVEs. diff --git a/Misc/NEWS.d/next/Security/2023-06-13-20-52-24.gh-issue-102988.Kei7Vf.rst b/Misc/NEWS.d/next/Security/2023-06-13-20-52-24.gh-issue-102988.Kei7Vf.rst deleted file mode 100644 index c67ec45737b535..00000000000000 --- a/Misc/NEWS.d/next/Security/2023-06-13-20-52-24.gh-issue-102988.Kei7Vf.rst +++ /dev/null @@ -1,4 +0,0 @@ -Reverted the :mod:`email.utils` security improvement change released in -3.12beta4 that unintentionally caused :mod:`email.utils.getaddresses` to fail -to parse email addresses with a comma in the quoted name field. -See :gh:`106669`. diff --git a/Misc/NEWS.d/next/Security/2023-12-06-14-06-59.gh-issue-112302.3bl20f.rst b/Misc/NEWS.d/next/Security/2023-12-06-14-06-59.gh-issue-112302.3bl20f.rst new file mode 100644 index 00000000000000..65e4dc3762d3c0 --- /dev/null +++ b/Misc/NEWS.d/next/Security/2023-12-06-14-06-59.gh-issue-112302.3bl20f.rst @@ -0,0 +1,2 @@ +Created a Software Bill-of-Materials document and tooling for tracking +dependencies. diff --git a/Misc/NEWS.d/next/Tests/2020-05-16-18-00-21.bpo-40648.p2uPqy.rst b/Misc/NEWS.d/next/Tests/2020-05-16-18-00-21.bpo-40648.p2uPqy.rst new file mode 100644 index 00000000000000..8fbe42d263feb9 --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2020-05-16-18-00-21.bpo-40648.p2uPqy.rst @@ -0,0 +1 @@ +Test modes that file can get with chmod() on Windows. diff --git a/Misc/NEWS.d/next/Tests/2022-06-09-21-27-38.gh-issue-69714.49tyHW.rst b/Misc/NEWS.d/next/Tests/2022-06-09-21-27-38.gh-issue-69714.49tyHW.rst deleted file mode 100644 index e28b94a171c40e..00000000000000 --- a/Misc/NEWS.d/next/Tests/2022-06-09-21-27-38.gh-issue-69714.49tyHW.rst +++ /dev/null @@ -1 +0,0 @@ -Add additional tests to :mod:`calendar` to achieve full test coverage. diff --git a/Misc/NEWS.d/next/Tests/2023-05-19-08-06-06.gh-issue-81005.-q7m9W.rst b/Misc/NEWS.d/next/Tests/2023-05-19-08-06-06.gh-issue-81005.-q7m9W.rst deleted file mode 100644 index dfb653241e2607..00000000000000 --- a/Misc/NEWS.d/next/Tests/2023-05-19-08-06-06.gh-issue-81005.-q7m9W.rst +++ /dev/null @@ -1,2 +0,0 @@ -String tests are modified to reflect that ``str`` and ``unicode`` are merged -in Python 3. Patch by Daniel Fortunov. diff --git a/Misc/NEWS.d/next/Tests/2023-05-29-14-49-46.gh-issue-105084.lvVvoj.rst b/Misc/NEWS.d/next/Tests/2023-05-29-14-49-46.gh-issue-105084.lvVvoj.rst deleted file mode 100644 index 5f80d507147347..00000000000000 --- a/Misc/NEWS.d/next/Tests/2023-05-29-14-49-46.gh-issue-105084.lvVvoj.rst +++ /dev/null @@ -1,3 +0,0 @@ -When the Python build is configured ``--with-wheel-pkg-dir``, tests -requiring the ``setuptools`` and ``wheel`` wheels will search for the wheels -in ``WHEEL_PKG_DIR``. diff --git a/Misc/NEWS.d/next/Tests/2023-06-28-02-51-08.gh-issue-101634.Rayczr.rst b/Misc/NEWS.d/next/Tests/2023-06-28-02-51-08.gh-issue-101634.Rayczr.rst deleted file mode 100644 index 6fbfc84c19e1b8..00000000000000 --- a/Misc/NEWS.d/next/Tests/2023-06-28-02-51-08.gh-issue-101634.Rayczr.rst +++ /dev/null @@ -1,3 +0,0 @@ -When running the Python test suite with ``-jN`` option, if a worker stdout -cannot be decoded from the locale encoding report a failed testn so the -exitcode is non-zero. Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/Tests/2023-07-12-14-07-07.gh-issue-106690.NDz-oG.rst b/Misc/NEWS.d/next/Tests/2023-07-12-14-07-07.gh-issue-106690.NDz-oG.rst deleted file mode 100644 index e7dc0ac2220502..00000000000000 --- a/Misc/NEWS.d/next/Tests/2023-07-12-14-07-07.gh-issue-106690.NDz-oG.rst +++ /dev/null @@ -1 +0,0 @@ -Add .coveragerc to cpython repository for use with coverage package. diff --git a/Misc/NEWS.d/next/Tests/2023-07-14-16-20-06.gh-issue-106752.gd1i6D.rst b/Misc/NEWS.d/next/Tests/2023-07-14-16-20-06.gh-issue-106752.gd1i6D.rst deleted file mode 100644 index ba7257e3610808..00000000000000 --- a/Misc/NEWS.d/next/Tests/2023-07-14-16-20-06.gh-issue-106752.gd1i6D.rst +++ /dev/null @@ -1,2 +0,0 @@ -Moved tests for ``zipfile.Path`` into ``Lib/test/test_zipfile/_path``. Made -``zipfile._path`` a package. diff --git a/Misc/NEWS.d/next/Tests/2023-07-16-02-57-08.gh-issue-104090.cKtK7g.rst b/Misc/NEWS.d/next/Tests/2023-07-16-02-57-08.gh-issue-104090.cKtK7g.rst deleted file mode 100644 index 5cc6c5bbe15446..00000000000000 --- a/Misc/NEWS.d/next/Tests/2023-07-16-02-57-08.gh-issue-104090.cKtK7g.rst +++ /dev/null @@ -1 +0,0 @@ -Avoid creating a reference to the test object in :meth:`~unittest.TestResult.collectedDurations`. diff --git a/Misc/NEWS.d/next/Tests/2023-07-22-13-49-40.gh-issue-106714.btYI5S.rst b/Misc/NEWS.d/next/Tests/2023-07-22-13-49-40.gh-issue-106714.btYI5S.rst deleted file mode 100644 index 955620521c8f68..00000000000000 --- a/Misc/NEWS.d/next/Tests/2023-07-22-13-49-40.gh-issue-106714.btYI5S.rst +++ /dev/null @@ -1,3 +0,0 @@ -test_capi: Fix test_no_FatalError_infinite_loop() to no longer write a -coredump, by using test.support.SuppressCrashReport. Patch by Victor -Stinner. diff --git a/Misc/NEWS.d/next/Tests/2023-07-25-14-36-33.gh-issue-107237.y1pY79.rst b/Misc/NEWS.d/next/Tests/2023-07-25-14-36-33.gh-issue-107237.y1pY79.rst deleted file mode 100644 index a04f7eeddef174..00000000000000 --- a/Misc/NEWS.d/next/Tests/2023-07-25-14-36-33.gh-issue-107237.y1pY79.rst +++ /dev/null @@ -1,2 +0,0 @@ -``test_logging``: Fix ``test_udp_reconnection()`` by increasing the timeout -from 100 ms to 5 minutes (LONG_TIMEOUT). Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/Tests/2023-09-05-20-46-35.gh-issue-108927.TpwWav.rst b/Misc/NEWS.d/next/Tests/2023-09-05-20-46-35.gh-issue-108927.TpwWav.rst new file mode 100644 index 00000000000000..b1a78370afedb2 --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2023-09-05-20-46-35.gh-issue-108927.TpwWav.rst @@ -0,0 +1,4 @@ +Fixed order dependence in running tests in the same process +when a test that has submodules (e.g. test_importlib) follows a test that +imports its submodule (e.g. test_importlib.util) and precedes a test +(e.g. test_unittest or test_compileall) that uses that submodule. diff --git a/Misc/NEWS.d/next/Tests/2023-12-04-15-56-11.gh-issue-112334.FFc9Ti.rst b/Misc/NEWS.d/next/Tests/2023-12-04-15-56-11.gh-issue-112334.FFc9Ti.rst new file mode 100644 index 00000000000000..aeaad6e5055522 --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2023-12-04-15-56-11.gh-issue-112334.FFc9Ti.rst @@ -0,0 +1,2 @@ +Adds a regression test to verify that ``vfork()`` is used when expected by +:mod:`subprocess` on vfork enabled POSIX systems (Linux). diff --git a/Misc/NEWS.d/next/Tests/2023-12-05-19-50-03.gh-issue-112769.kdLJmS.rst b/Misc/NEWS.d/next/Tests/2023-12-05-19-50-03.gh-issue-112769.kdLJmS.rst new file mode 100644 index 00000000000000..1bbbb26fc322fa --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2023-12-05-19-50-03.gh-issue-112769.kdLJmS.rst @@ -0,0 +1,3 @@ +The tests now correctly compare zlib version when +:const:`zlib.ZLIB_RUNTIME_VERSION` contains non-integer suffixes. For +example zlib-ng defines the version as ``1.3.0.zlib-ng``. diff --git a/Misc/NEWS.d/next/Tests/2023-12-09-21-27-46.gh-issue-109980.y--500.rst b/Misc/NEWS.d/next/Tests/2023-12-09-21-27-46.gh-issue-109980.y--500.rst new file mode 100644 index 00000000000000..c475a33919db98 --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2023-12-09-21-27-46.gh-issue-109980.y--500.rst @@ -0,0 +1,2 @@ +Fix ``test_tarfile_vs_tar`` in ``test_shutil`` for macOS, where system tar +can include more information in the archive than :mod:`shutil.make_archive`. diff --git a/Misc/NEWS.d/next/Tests/2024-01-01-14-40-02.gh-issue-113633.VOY5ai.rst b/Misc/NEWS.d/next/Tests/2024-01-01-14-40-02.gh-issue-113633.VOY5ai.rst new file mode 100644 index 00000000000000..150c0d91852cdf --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2024-01-01-14-40-02.gh-issue-113633.VOY5ai.rst @@ -0,0 +1 @@ +Use module state for the _testcapi extension module. diff --git a/Misc/NEWS.d/next/Tools-Demos/2023-04-05-07-19-36.gh-issue-103186.yEozgK.rst b/Misc/NEWS.d/next/Tools-Demos/2023-04-05-07-19-36.gh-issue-103186.yEozgK.rst deleted file mode 100644 index 7e28ba6963216a..00000000000000 --- a/Misc/NEWS.d/next/Tools-Demos/2023-04-05-07-19-36.gh-issue-103186.yEozgK.rst +++ /dev/null @@ -1,2 +0,0 @@ -``freeze`` now fetches ``CONFIG_ARGS`` from the original CPython instance -the Makefile uses to call utility scripts. Patch by Ijtaba Hussain. diff --git a/Misc/NEWS.d/next/Tools-Demos/2023-07-03-14-06-19.gh-issue-106359.RfJuR0.rst b/Misc/NEWS.d/next/Tools-Demos/2023-07-03-14-06-19.gh-issue-106359.RfJuR0.rst deleted file mode 100644 index 600c265391ec5b..00000000000000 --- a/Misc/NEWS.d/next/Tools-Demos/2023-07-03-14-06-19.gh-issue-106359.RfJuR0.rst +++ /dev/null @@ -1,2 +0,0 @@ -Argument Clinic now explicitly forbids "kwarg splats" in function calls used as -annotations. diff --git a/Misc/NEWS.d/next/Tools-Demos/2023-07-13-12-08-35.gh-issue-106706.29zp8E.rst b/Misc/NEWS.d/next/Tools-Demos/2023-07-13-12-08-35.gh-issue-106706.29zp8E.rst deleted file mode 100644 index bbd8e8eddda607..00000000000000 --- a/Misc/NEWS.d/next/Tools-Demos/2023-07-13-12-08-35.gh-issue-106706.29zp8E.rst +++ /dev/null @@ -1,3 +0,0 @@ -Change bytecode syntax for families -to remove redundant name matching -pseudo syntax. diff --git a/Misc/NEWS.d/next/Tools-Demos/2023-07-21-23-16-05.gh-issue-106970.NLRnml.rst b/Misc/NEWS.d/next/Tools-Demos/2023-07-21-23-16-05.gh-issue-106970.NLRnml.rst deleted file mode 100644 index 194e3351b0470c..00000000000000 --- a/Misc/NEWS.d/next/Tools-Demos/2023-07-21-23-16-05.gh-issue-106970.NLRnml.rst +++ /dev/null @@ -1,4 +0,0 @@ -Fix bugs in the Argument Clinic ``destination clear`` command; the -destination buffers would never be cleared, and the ``destination`` -directive parser would simply continue to the fault handler after processing -the command. Patch by Erlend E. Aasland. diff --git a/Misc/NEWS.d/next/Tools-Demos/2023-07-30-23-32-16.gh-issue-107467.5O9p3G.rst b/Misc/NEWS.d/next/Tools-Demos/2023-07-30-23-32-16.gh-issue-107467.5O9p3G.rst deleted file mode 100644 index 2996837371be0f..00000000000000 --- a/Misc/NEWS.d/next/Tools-Demos/2023-07-30-23-32-16.gh-issue-107467.5O9p3G.rst +++ /dev/null @@ -1,2 +0,0 @@ -The Argument Clinic command-line tool now prints to stderr instead of stdout -on failure. diff --git a/Misc/NEWS.d/next/Tools-Demos/2023-08-04-00-04-40.gh-issue-107609.2DqgtL.rst b/Misc/NEWS.d/next/Tools-Demos/2023-08-04-00-04-40.gh-issue-107609.2DqgtL.rst deleted file mode 100644 index 080a6c15d9b8c5..00000000000000 --- a/Misc/NEWS.d/next/Tools-Demos/2023-08-04-00-04-40.gh-issue-107609.2DqgtL.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fix duplicate module check in Argument Clinic. Previously, a duplicate -definition would incorrectly be silently accepted. Patch by Erlend E. -Aasland. diff --git a/Misc/NEWS.d/next/Windows/2019-06-16-11-27-05.bpo-37308.Iz_NU_.rst b/Misc/NEWS.d/next/Windows/2019-06-16-11-27-05.bpo-37308.Iz_NU_.rst new file mode 100644 index 00000000000000..3ba29d60a23e98 --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2019-06-16-11-27-05.bpo-37308.Iz_NU_.rst @@ -0,0 +1,2 @@ +Fix mojibake in :class:`mmap.mmap` when using a non-ASCII *tagname* argument +on Windows. diff --git a/Misc/NEWS.d/next/Windows/2023-03-15-23-53-45.gh-issue-87868.4C36oQ.rst b/Misc/NEWS.d/next/Windows/2023-03-15-23-53-45.gh-issue-87868.4C36oQ.rst new file mode 100644 index 00000000000000..37e8103c9ec34b --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2023-03-15-23-53-45.gh-issue-87868.4C36oQ.rst @@ -0,0 +1,2 @@ +Correctly sort and remove duplicate environment variables in +:py:func:`!_winapi.CreateProcess`. diff --git a/Misc/NEWS.d/next/Windows/2023-05-23-19-26-28.gh-issue-104803.gqxYml.rst b/Misc/NEWS.d/next/Windows/2023-05-23-19-26-28.gh-issue-104803.gqxYml.rst deleted file mode 100644 index d2242c76189970..00000000000000 --- a/Misc/NEWS.d/next/Windows/2023-05-23-19-26-28.gh-issue-104803.gqxYml.rst +++ /dev/null @@ -1,3 +0,0 @@ -Add :func:`os.path.isdevdrive` to detect whether a path is on a Windows Dev -Drive. Returns ``False`` on platforms that do not support Dev Drive, and is -absent on non-Windows platforms. diff --git a/Misc/NEWS.d/next/Windows/2023-05-24-21-00-57.gh-issue-104820.ibyrpp.rst b/Misc/NEWS.d/next/Windows/2023-05-24-21-00-57.gh-issue-104820.ibyrpp.rst deleted file mode 100644 index 5bdfbabfaf28e1..00000000000000 --- a/Misc/NEWS.d/next/Windows/2023-05-24-21-00-57.gh-issue-104820.ibyrpp.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fixes :func:`~os.stat` and related functions on file systems that do not -support file ID requests. This includes FAT32 and exFAT. diff --git a/Misc/NEWS.d/next/Windows/2023-05-29-11-38-53.gh-issue-88745.cldf9G.rst b/Misc/NEWS.d/next/Windows/2023-05-29-11-38-53.gh-issue-88745.cldf9G.rst deleted file mode 100644 index 258eb89d50d9f5..00000000000000 --- a/Misc/NEWS.d/next/Windows/2023-05-29-11-38-53.gh-issue-88745.cldf9G.rst +++ /dev/null @@ -1,3 +0,0 @@ -Improve performance of :func:`shutil.copy2` by using the operating system's -``CopyFile2`` function. This may result in subtle changes to metadata copied -along with some files, bringing them in line with normal OS behavior. diff --git a/Misc/NEWS.d/next/Windows/2023-05-29-17-09-31.gh-issue-103646.U8oGQx.rst b/Misc/NEWS.d/next/Windows/2023-05-29-17-09-31.gh-issue-103646.U8oGQx.rst deleted file mode 100644 index 71c1e7c6594cbf..00000000000000 --- a/Misc/NEWS.d/next/Windows/2023-05-29-17-09-31.gh-issue-103646.U8oGQx.rst +++ /dev/null @@ -1,5 +0,0 @@ -When installed from the Microsoft Store, ``pip`` no longer defaults to -per-user installs. However, as the install directory is unwritable, it -should automatically decide to do a per-user install anyway. This should -resolve issues when ``pip`` is passed an option that conflicts with -``--user``. diff --git a/Misc/NEWS.d/next/Windows/2023-05-31-16-14-31.gh-issue-105146.gNjqq8.rst b/Misc/NEWS.d/next/Windows/2023-05-31-16-14-31.gh-issue-105146.gNjqq8.rst deleted file mode 100644 index 1a5208bc898207..00000000000000 --- a/Misc/NEWS.d/next/Windows/2023-05-31-16-14-31.gh-issue-105146.gNjqq8.rst +++ /dev/null @@ -1,2 +0,0 @@ -Updated the links at the end of the installer to point to Discourse rather -than the mailing lists. diff --git a/Misc/NEWS.d/next/Windows/2023-06-08-11-30-17.gh-issue-105436.1qlDxw.rst b/Misc/NEWS.d/next/Windows/2023-06-08-11-30-17.gh-issue-105436.1qlDxw.rst deleted file mode 100644 index 1e3f298096cdd6..00000000000000 --- a/Misc/NEWS.d/next/Windows/2023-06-08-11-30-17.gh-issue-105436.1qlDxw.rst +++ /dev/null @@ -1,2 +0,0 @@ -Ensure that an empty environment block is terminated by two null characters, -as is required by Windows. diff --git a/Misc/NEWS.d/next/Windows/2023-07-11-20-48-17.gh-issue-99079.CIMftz.rst b/Misc/NEWS.d/next/Windows/2023-07-11-20-48-17.gh-issue-99079.CIMftz.rst deleted file mode 100644 index 11f411be0f17c5..00000000000000 --- a/Misc/NEWS.d/next/Windows/2023-07-11-20-48-17.gh-issue-99079.CIMftz.rst +++ /dev/null @@ -1 +0,0 @@ -Update Windows build to use OpenSSL 3.0.9 diff --git a/Misc/NEWS.d/next/Windows/2023-08-08-01-42-14.gh-issue-73427.WOpiNt.rst b/Misc/NEWS.d/next/Windows/2023-08-08-01-42-14.gh-issue-73427.WOpiNt.rst new file mode 100644 index 00000000000000..830c4c54838e80 --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2023-08-08-01-42-14.gh-issue-73427.WOpiNt.rst @@ -0,0 +1,2 @@ +Deprecate :func:`sys._enablelegacywindowsfsencoding`. Use +:envvar:`PYTHONLEGACYWINDOWSFSENCODING` instead. Patch by Inada Naoki. diff --git a/Misc/NEWS.d/next/Windows/2023-12-03-19-22-37.gh-issue-112278.FiloCE.rst b/Misc/NEWS.d/next/Windows/2023-12-03-19-22-37.gh-issue-112278.FiloCE.rst new file mode 100644 index 00000000000000..0350d105d97375 --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2023-12-03-19-22-37.gh-issue-112278.FiloCE.rst @@ -0,0 +1,2 @@ +Reduce the time cost for some functions in :mod:`platform` on Windows if +current user has no permission to the WMI. diff --git a/Misc/NEWS.d/next/Windows/2023-12-05-22-56-30.gh-issue-111650.xlWmvM.rst b/Misc/NEWS.d/next/Windows/2023-12-05-22-56-30.gh-issue-111650.xlWmvM.rst new file mode 100644 index 00000000000000..5a3493356e30be --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2023-12-05-22-56-30.gh-issue-111650.xlWmvM.rst @@ -0,0 +1,3 @@ +Ensures the ``Py_GIL_DISABLED`` preprocessor variable is defined in +:file:`pyconfig.h` so that extension modules written in C are able to use +it. diff --git a/Misc/NEWS.d/next/Windows/2023-12-11-20-23-04.gh-issue-71383.9pZh6t.rst b/Misc/NEWS.d/next/Windows/2023-12-11-20-23-04.gh-issue-71383.9pZh6t.rst new file mode 100644 index 00000000000000..cf2883357a962a --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2023-12-11-20-23-04.gh-issue-71383.9pZh6t.rst @@ -0,0 +1,2 @@ +Update Tcl/Tk in Windows installer to 8.6.13 with a patch to suppress +incorrect ThemeChanged warnings. diff --git a/Misc/NEWS.d/next/Windows/2023-12-12-20-58-09.gh-issue-86179.YYSk_6.rst b/Misc/NEWS.d/next/Windows/2023-12-12-20-58-09.gh-issue-86179.YYSk_6.rst new file mode 100644 index 00000000000000..c1d96792bdae0b --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2023-12-12-20-58-09.gh-issue-86179.YYSk_6.rst @@ -0,0 +1 @@ +Fixes path calculations when launching Python on Windows through a symlink. diff --git a/Misc/NEWS.d/next/Windows/2023-12-14-19-00-29.gh-issue-113009.6LNdjz.rst b/Misc/NEWS.d/next/Windows/2023-12-14-19-00-29.gh-issue-113009.6LNdjz.rst new file mode 100644 index 00000000000000..6fd7f7f9afdfa2 --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2023-12-14-19-00-29.gh-issue-113009.6LNdjz.rst @@ -0,0 +1,5 @@ +:mod:`multiprocessing`: On Windows, fix a race condition in +``Process.terminate()``: no longer set the ``returncode`` attribute to +always call ``WaitForSingleObject()`` in ``Process.wait()``. Previously, +sometimes the process was still running after ``TerminateProcess()`` even if +``GetExitCodeProcess()`` is not ``STILL_ACTIVE``. Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/Windows/2023-12-19-10-56-46.gh-issue-111973.A9Wtsb.rst b/Misc/NEWS.d/next/Windows/2023-12-19-10-56-46.gh-issue-111973.A9Wtsb.rst new file mode 100644 index 00000000000000..0cefa4e44093f0 --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2023-12-19-10-56-46.gh-issue-111973.A9Wtsb.rst @@ -0,0 +1 @@ +Update Windows installer to use SQLite 3.44.2. diff --git a/Misc/NEWS.d/next/macOS/2023-05-30-23-30-46.gh-issue-103142.55lMXQ.rst b/Misc/NEWS.d/next/macOS/2023-05-30-23-30-46.gh-issue-103142.55lMXQ.rst deleted file mode 100644 index 1afd949d6a9f03..00000000000000 --- a/Misc/NEWS.d/next/macOS/2023-05-30-23-30-46.gh-issue-103142.55lMXQ.rst +++ /dev/null @@ -1 +0,0 @@ -Update macOS installer to use OpenSSL 1.1.1u. diff --git a/Misc/NEWS.d/next/macOS/2023-07-30-23-42-20.gh-issue-99079.JAtoh1.rst b/Misc/NEWS.d/next/macOS/2023-07-30-23-42-20.gh-issue-99079.JAtoh1.rst deleted file mode 100644 index d0eef4ec1003ce..00000000000000 --- a/Misc/NEWS.d/next/macOS/2023-07-30-23-42-20.gh-issue-99079.JAtoh1.rst +++ /dev/null @@ -1 +0,0 @@ -Update macOS installer to use OpenSSL 3.0.9. diff --git a/Misc/NEWS.d/next/macOS/2023-12-06-12-11-13.gh-issue-109981.mOHg10.rst b/Misc/NEWS.d/next/macOS/2023-12-06-12-11-13.gh-issue-109981.mOHg10.rst new file mode 100644 index 00000000000000..f86ab2c37ee6ec --- /dev/null +++ b/Misc/NEWS.d/next/macOS/2023-12-06-12-11-13.gh-issue-109981.mOHg10.rst @@ -0,0 +1,3 @@ +Use ``/dev/fd`` on macOS to determine the number of open files in +``test.support.os_helper.fd_count`` to avoid a crash with "guarded" file +descriptors when probing for open files. diff --git a/Misc/NEWS.d/next/macOS/2023-12-07-14-19-46.gh-issue-110820.DIxb_F.rst b/Misc/NEWS.d/next/macOS/2023-12-07-14-19-46.gh-issue-110820.DIxb_F.rst new file mode 100644 index 00000000000000..0badace7928745 --- /dev/null +++ b/Misc/NEWS.d/next/macOS/2023-12-07-14-19-46.gh-issue-110820.DIxb_F.rst @@ -0,0 +1,3 @@ +Make sure the preprocessor definitions for ``ALIGNOF_MAX_ALIGN_T``, +``SIZEOF_LONG_DOUBLE`` and ``HAVE_GCC_ASM_FOR_X64`` are correct for +Universal 2 builds on macOS. diff --git a/Misc/NEWS.d/next/macOS/2023-12-07-15-53-16.gh-issue-110017.UMYzMR.rst b/Misc/NEWS.d/next/macOS/2023-12-07-15-53-16.gh-issue-110017.UMYzMR.rst new file mode 100644 index 00000000000000..eab1746f1ae3f7 --- /dev/null +++ b/Misc/NEWS.d/next/macOS/2023-12-07-15-53-16.gh-issue-110017.UMYzMR.rst @@ -0,0 +1,2 @@ +Disable a signal handling stress test on macOS due to a bug in macOS +(FB13453490). diff --git a/Misc/NEWS.d/next/macOS/2023-12-10-20-30-06.gh-issue-102362.y8svbF.rst b/Misc/NEWS.d/next/macOS/2023-12-10-20-30-06.gh-issue-102362.y8svbF.rst new file mode 100644 index 00000000000000..55c5ac01434660 --- /dev/null +++ b/Misc/NEWS.d/next/macOS/2023-12-10-20-30-06.gh-issue-102362.y8svbF.rst @@ -0,0 +1,3 @@ +Make sure the result of :func:`sysconfig.get_plaform` includes at least a +major and minor versions, even if ``MACOSX_DEPLOYMENT_TARGET`` is set to +only a major version during build to match the format expected by pip. diff --git a/Misc/NEWS.d/next/macOS/2023-12-16-11-45-32.gh-issue-108269.wVgCHF.rst b/Misc/NEWS.d/next/macOS/2023-12-16-11-45-32.gh-issue-108269.wVgCHF.rst new file mode 100644 index 00000000000000..85598454abcaad --- /dev/null +++ b/Misc/NEWS.d/next/macOS/2023-12-16-11-45-32.gh-issue-108269.wVgCHF.rst @@ -0,0 +1,4 @@ +Set ``CFBundleAllowMixedLocalizations`` to true in the Info.plist for the +framework, embedded Python.app and IDLE.app with framework installs on +macOS. This allows applications to pick up the user's preferred locale when +that's different from english. diff --git a/Misc/NEWS.d/next/macOS/2023-12-19-10-50-08.gh-issue-111973.HMHJfy.rst b/Misc/NEWS.d/next/macOS/2023-12-19-10-50-08.gh-issue-111973.HMHJfy.rst new file mode 100644 index 00000000000000..0cf3abf3b71890 --- /dev/null +++ b/Misc/NEWS.d/next/macOS/2023-12-19-10-50-08.gh-issue-111973.HMHJfy.rst @@ -0,0 +1 @@ +Update macOS installer to use SQLite 3.44.2. diff --git a/Misc/NEWS.d/next/macOS/2023-12-21-09-41-42.gh-issue-87277.IF6EZZ.rst b/Misc/NEWS.d/next/macOS/2023-12-21-09-41-42.gh-issue-87277.IF6EZZ.rst new file mode 100644 index 00000000000000..4ae55c0293198a --- /dev/null +++ b/Misc/NEWS.d/next/macOS/2023-12-21-09-41-42.gh-issue-87277.IF6EZZ.rst @@ -0,0 +1,3 @@ +webbrowser: Don't look for X11 browsers on macOS. Those are generally not +used and probing for them can result in starting XQuartz even if it isn't +used otherwise. diff --git a/Misc/NEWS.d/next/macOS/2023-12-21-10-20-41.gh-issue-65701.Q2hNbN.rst b/Misc/NEWS.d/next/macOS/2023-12-21-10-20-41.gh-issue-65701.Q2hNbN.rst new file mode 100644 index 00000000000000..870b84a4d1af80 --- /dev/null +++ b/Misc/NEWS.d/next/macOS/2023-12-21-10-20-41.gh-issue-65701.Q2hNbN.rst @@ -0,0 +1,2 @@ +The :program:`freeze` tool doesn't work with framework builds of Python. +Document this and bail out early when running the tool with such a build. diff --git a/Misc/NEWS.d/next/macOS/2023-12-21-11-53-47.gh-issue-74573.MA6Vys.rst b/Misc/NEWS.d/next/macOS/2023-12-21-11-53-47.gh-issue-74573.MA6Vys.rst new file mode 100644 index 00000000000000..96dcd4765d95da --- /dev/null +++ b/Misc/NEWS.d/next/macOS/2023-12-21-11-53-47.gh-issue-74573.MA6Vys.rst @@ -0,0 +1,3 @@ +Document that :mod:`dbm.ndbm` can silently corrupt DBM files on updates when +exceeding undocumented platform limits, and can crash (segmentation fault) +when reading such a corrupted file. (FB8919203) diff --git a/Misc/NEWS.d/next/macOS/2023-12-23-22-41-07.gh-issue-110459.NaMBJy.rst b/Misc/NEWS.d/next/macOS/2023-12-23-22-41-07.gh-issue-110459.NaMBJy.rst new file mode 100644 index 00000000000000..44ffd857785f0d --- /dev/null +++ b/Misc/NEWS.d/next/macOS/2023-12-23-22-41-07.gh-issue-110459.NaMBJy.rst @@ -0,0 +1,2 @@ +Running ``configure ... --with-openssl-rpath=X/Y/Z`` no longer fails to detect +OpenSSL on macOS. diff --git a/Misc/NEWS.d/next/macOS/2023-12-28-12-18-39.gh-issue-113536.0ythg7.rst b/Misc/NEWS.d/next/macOS/2023-12-28-12-18-39.gh-issue-113536.0ythg7.rst new file mode 100644 index 00000000000000..828b872d283627 --- /dev/null +++ b/Misc/NEWS.d/next/macOS/2023-12-28-12-18-39.gh-issue-113536.0ythg7.rst @@ -0,0 +1 @@ +:func:`os.waitid` is now available on macOS diff --git a/Misc/SpecialBuilds.txt b/Misc/SpecialBuilds.txt index 5609928284d448..78201bfbd6741d 100644 --- a/Misc/SpecialBuilds.txt +++ b/Misc/SpecialBuilds.txt @@ -43,13 +43,9 @@ Py_TRACE_REFS Build option: ``./configure --with-trace-refs``. -Turn on heavy reference debugging. This is major surgery. Every PyObject grows -two more pointers, to maintain a doubly-linked list of all live heap-allocated -objects. Most built-in type objects are not in this list, as they're statically -allocated. - -Note that because the fundamental PyObject layout changes, Python modules -compiled with Py_TRACE_REFS are incompatible with modules compiled without it. +Turn on heavy reference debugging. This is major surgery. All live +heap-allocated objects are traced in a hash table. Most built-in type objects +are not in this list, as they're statically allocated. Special gimmicks: diff --git a/Misc/platform_triplet.c b/Misc/platform_triplet.c new file mode 100644 index 00000000000000..3307260544e8a6 --- /dev/null +++ b/Misc/platform_triplet.c @@ -0,0 +1,261 @@ +/* Detect platform triplet from builtin defines + * cc -E Misc/platform_triplet.c | grep '^PLATFORM_TRIPLET=' | tr -d ' ' + */ +#undef bfin +#undef cris +#undef fr30 +#undef linux +#undef hppa +#undef hpux +#undef i386 +#undef mips +#undef powerpc +#undef sparc +#undef unix +#if defined(__ANDROID__) + # Android is not a multiarch system. +#elif defined(__linux__) +/* + * BEGIN of Linux block + */ +// Detect libc (based on config.guess) +# include +# if defined(__UCLIBC__) +# error uclibc not supported +# elif defined(__dietlibc__) +# error dietlibc not supported +# elif defined(__GLIBC__) +# define LIBC gnu +# define LIBC_X32 gnux32 +# if defined(__ARM_PCS_VFP) +# define LIBC_ARM gnueabihf +# else +# define LIBC_ARM gnueabi +# endif +# if defined(__loongarch__) +# if defined(__loongarch_soft_float) +# define LIBC_LA gnusf +# elif defined(__loongarch_single_float) +# define LIBC_LA gnuf32 +# elif defined(__loongarch_double_float) +# define LIBC_LA gnu +# else +# error unknown loongarch floating-point base abi +# endif +# endif +# if defined(_MIPS_SIM) +# if defined(__mips_hard_float) +# if _MIPS_SIM == _ABIO32 +# define LIBC_MIPS gnu +# elif _MIPS_SIM == _ABIN32 +# define LIBC_MIPS gnuabin32 +# elif _MIPS_SIM == _ABI64 +# define LIBC_MIPS gnuabi64 +# else +# error unknown mips sim value +# endif +# else +# if _MIPS_SIM == _ABIO32 +# define LIBC_MIPS gnusf +# elif _MIPS_SIM == _ABIN32 +# define LIBC_MIPS gnuabin32sf +# elif _MIPS_SIM == _ABI64 +# define LIBC_MIPS gnuabi64sf +# else +# error unknown mips sim value +# endif +# endif +# endif +# if defined(__SPE__) +# define LIBC_PPC gnuspe +# else +# define LIBC_PPC gnu +# endif +# else +// Heuristic to detect musl libc +# include +# ifdef __DEFINED_va_list +# define LIBC musl +# define LIBC_X32 muslx32 +# if defined(__ARM_PCS_VFP) +# define LIBC_ARM musleabihf +# else +# define LIBC_ARM musleabi +# endif +# if defined(__loongarch__) +# if defined(__loongarch_soft_float) +# define LIBC_LA muslsf +# elif defined(__loongarch_single_float) +# define LIBC_LA muslf32 +# elif defined(__loongarch_double_float) +# define LIBC_LA musl +# else +# error unknown loongarch floating-point base abi +# endif +# endif +# if defined(_MIPS_SIM) +# if defined(__mips_hard_float) +# if _MIPS_SIM == _ABIO32 +# define LIBC_MIPS musl +# elif _MIPS_SIM == _ABIN32 +# define LIBC_MIPS musln32 +# elif _MIPS_SIM == _ABI64 +# define LIBC_MIPS musl +# else +# error unknown mips sim value +# endif +# else +# if _MIPS_SIM == _ABIO32 +# define LIBC_MIPS muslsf +# elif _MIPS_SIM == _ABIN32 +# define LIBC_MIPS musln32sf +# elif _MIPS_SIM == _ABI64 +# define LIBC_MIPS muslsf +# else +# error unknown mips sim value +# endif +# endif +# endif +# if defined(_SOFT_FLOAT) || defined(__NO_FPRS__) +# define LIBC_PPC muslsf +# else +# define LIBC_PPC musl +# endif +# else +# error unknown libc +# endif +# endif + +# if defined(__x86_64__) && defined(__LP64__) +PLATFORM_TRIPLET=x86_64-linux-LIBC +# elif defined(__x86_64__) && defined(__ILP32__) +PLATFORM_TRIPLET=x86_64-linux-LIBC_X32 +# elif defined(__i386__) +PLATFORM_TRIPLET=i386-linux-LIBC +# elif defined(__aarch64__) && defined(__AARCH64EL__) +# if defined(__ILP32__) +PLATFORM_TRIPLET=aarch64_ilp32-linux-LIBC +# else +PLATFORM_TRIPLET=aarch64-linux-LIBC +# endif +# elif defined(__aarch64__) && defined(__AARCH64EB__) +# if defined(__ILP32__) +PLATFORM_TRIPLET=aarch64_be_ilp32-linux-LIBC +# else +PLATFORM_TRIPLET=aarch64_be-linux-LIBC +# endif +# elif defined(__alpha__) +PLATFORM_TRIPLET=alpha-linux-LIBC +# elif defined(__ARM_EABI__) +# if defined(__ARMEL__) +PLATFORM_TRIPLET=arm-linux-LIBC_ARM +# else +PLATFORM_TRIPLET=armeb-linux-LIBC_ARM +# endif +# elif defined(__hppa__) +PLATFORM_TRIPLET=hppa-linux-LIBC +# elif defined(__ia64__) +PLATFORM_TRIPLET=ia64-linux-LIBC +# elif defined(__loongarch__) && defined(__loongarch_lp64) +PLATFORM_TRIPLET=loongarch64-linux-LIBC_LA +# elif defined(__m68k__) && !defined(__mcoldfire__) +PLATFORM_TRIPLET=m68k-linux-LIBC +# elif defined(__mips__) +# if defined(__mips_isa_rev) && (__mips_isa_rev >=6) +# if defined(_MIPSEL) && defined(__mips64) +PLATFORM_TRIPLET=mipsisa64r6el-linux-LIBC_MIPS +# elif defined(_MIPSEL) +PLATFORM_TRIPLET=mipsisa32r6el-linux-LIBC_MIPS +# elif defined(__mips64) +PLATFORM_TRIPLET=mipsisa64r6-linux-LIBC_MIPS +# else +PLATFORM_TRIPLET=mipsisa32r6-linux-LIBC_MIPS +# endif +# else +# if defined(_MIPSEL) && defined(__mips64) +PLATFORM_TRIPLET=mips64el-linux-LIBC_MIPS +# elif defined(_MIPSEL) +PLATFORM_TRIPLET=mipsel-linux-LIBC_MIPS +# elif defined(__mips64) +PLATFORM_TRIPLET=mips64-linux-LIBC_MIPS +# else +PLATFORM_TRIPLET=mips-linux-LIBC_MIPS +# endif +# endif +# elif defined(__or1k__) +PLATFORM_TRIPLET=or1k-linux-LIBC +# elif defined(__powerpc64__) +# if defined(__LITTLE_ENDIAN__) +PLATFORM_TRIPLET=powerpc64le-linux-LIBC +# else +PLATFORM_TRIPLET=powerpc64-linux-LIBC +# endif +# elif defined(__powerpc__) +PLATFORM_TRIPLET=powerpc-linux-LIBC_PPC +# elif defined(__s390x__) +PLATFORM_TRIPLET=s390x-linux-LIBC +# elif defined(__s390__) +PLATFORM_TRIPLET=s390-linux-LIBC +# elif defined(__sh__) && defined(__LITTLE_ENDIAN__) +PLATFORM_TRIPLET=sh4-linux-LIBC +# elif defined(__sparc__) && defined(__arch64__) +PLATFORM_TRIPLET=sparc64-linux-LIBC +# elif defined(__sparc__) +PLATFORM_TRIPLET=sparc-linux-LIBC +# elif defined(__riscv) +# if __riscv_xlen == 32 +PLATFORM_TRIPLET=riscv32-linux-LIBC +# elif __riscv_xlen == 64 +PLATFORM_TRIPLET=riscv64-linux-LIBC +# else +# error unknown platform triplet +# endif +# else +# error unknown platform triplet +# endif +/* + * END of Linux block + */ +#elif defined(__FreeBSD_kernel__) +# if defined(__LP64__) +PLATFORM_TRIPLET=x86_64-kfreebsd-gnu +# elif defined(__i386__) +PLATFORM_TRIPLET=i386-kfreebsd-gnu +# else +# error unknown platform triplet +# endif +#elif defined(__gnu_hurd__) +# if defined(__x86_64__) && defined(__LP64__) +PLATFORM_TRIPLET=x86_64-gnu +# elif defined(__i386__) +PLATFORM_TRIPLET=i386-gnu +# else +# error unknown platform triplet +# endif +#elif defined(__APPLE__) +PLATFORM_TRIPLET=darwin +#elif defined(__VXWORKS__) +PLATFORM_TRIPLET=vxworks +#elif defined(__wasm32__) +# if defined(__EMSCRIPTEN__) +PLATFORM_TRIPLET=wasm32-emscripten +# elif defined(__wasi__) +# if defined(_REENTRANT) +PLATFORM_TRIPLET=wasm32-wasi-threads +# else +PLATFORM_TRIPLET=wasm32-wasi +# endif +# else +# error unknown wasm32 platform +# endif +#elif defined(__wasm64__) +# if defined(__EMSCRIPTEN__) +PLATFORM_TRIPLET=wasm64-emscripten +# elif defined(__wasi__) +PLATFORM_TRIPLET=wasm64-wasi +# else +# error unknown wasm64 platform +# endif +#else +# error unknown platform triplet +#endif diff --git a/Misc/python.man b/Misc/python.man index bf7cf767d164a6..0f5dfa2e2289f7 100644 --- a/Misc/python.man +++ b/Misc/python.man @@ -592,8 +592,8 @@ works on Mac OS X. .IP PYTHONUSERBASE Defines the user base directory, which is used to compute the path of the user .IR site-packages -directory and Distutils installation paths for -.IR "python setup\.py install \-\-user" . +directory and installation paths for +.IR "python \-m pip install \-\-user" . .IP PYTHONPROFILEIMPORTTIME If this environment variable is set to a non-empty string, Python will show how long each import takes. This is exactly equivalent to setting @@ -601,6 +601,12 @@ show how long each import takes. This is exactly equivalent to setting .IP PYTHONBREAKPOINT If this environment variable is set to 0, it disables the default debugger. It can be set to the callable of your debugger of choice. +.IP PYTHON_COLORS +If this variable is set to 1, the interpreter will colorize various kinds of +output. Setting it to 0 deactivates this behavior. +.IP PYTHON_HISTORY +This environment variable can be used to set the location of a history file +(on Unix, it is \fI~/.python_history\fP by default). .SS Debug-mode variables Setting these variables only has an effect in a debug build of Python, that is, if Python was configured with the diff --git a/Misc/requirements-test.txt b/Misc/requirements-test.txt deleted file mode 100644 index 60e7ed20a3d510..00000000000000 --- a/Misc/requirements-test.txt +++ /dev/null @@ -1 +0,0 @@ -tzdata==2020.3 diff --git a/Misc/sbom.spdx.json b/Misc/sbom.spdx.json new file mode 100644 index 00000000000000..5b3cd04ffa7f74 --- /dev/null +++ b/Misc/sbom.spdx.json @@ -0,0 +1,2294 @@ +{ + "SPDXID": "SPDXRef-DOCUMENT", + "files": [ + { + "SPDXID": "SPDXRef-FILE-Modules-expat-COPYING", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "39e6f567a10e36b2e77727e98e60bbcb3eb3af0b" + }, + { + "algorithm": "SHA256", + "checksumValue": "122f2c27000472a201d337b9b31f7eb2b52d091b02857061a8880371612d9534" + } + ], + "fileName": "Modules/expat/COPYING" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-expat-ascii.h", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "b0235fa3cf845a7d68e8e66dd344d5e32e8951b5" + }, + { + "algorithm": "SHA256", + "checksumValue": "42f8b392c70366743eacbc60ce021389ccaa333598dd49eef6ee5c93698ca205" + } + ], + "fileName": "Modules/expat/ascii.h" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-expat-asciitab.h", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "cbb53d16ca1f35ee9c9e296116efd222ae611ed9" + }, + { + "algorithm": "SHA256", + "checksumValue": "1cc0ae749019fc0e488cd1cf245f6beaa6d4f7c55a1fc797e5aa40a408bc266b" + } + ], + "fileName": "Modules/expat/asciitab.h" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-expat-expat.h", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "ab7bb32514d170592dfb3f76e41bbdc075a4e7e0" + }, + { + "algorithm": "SHA256", + "checksumValue": "f521acdad222644365b0e81a33bcd6939a98c91b225c47582cc84bd73d96febc" + } + ], + "fileName": "Modules/expat/expat.h" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-expat-expat-config.h", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "73627287302ee3e84347c4fe21f37a9cb828bc3b" + }, + { + "algorithm": "SHA256", + "checksumValue": "f17e59f9d95eeb05694c02508aa284d332616c22cbe2e6a802d8a0710310eaab" + } + ], + "fileName": "Modules/expat/expat_config.h" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-expat-expat-external.h", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "b70ce53fdc25ae482681ae2f6623c3c8edc9c1b7" + }, + { + "algorithm": "SHA256", + "checksumValue": "86afb425ec9999eb4f1ec9ab2fb41c58c4aa5cb9bf934b8c94264670fc5a961d" + } + ], + "fileName": "Modules/expat/expat_external.h" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-expat-iasciitab.h", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "1b0e9014c0baa4c6254d2b5e6a67c70148309c34" + }, + { + "algorithm": "SHA256", + "checksumValue": "ad8b01e9f323cc4208bcd22241df383d7e8641fe3c8b3415aa513de82531f89f" + } + ], + "fileName": "Modules/expat/iasciitab.h" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-expat-internal.h", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "2790d37e7de2f13dccc4f4fb352cbdf9ed6abaa2" + }, + { + "algorithm": "SHA256", + "checksumValue": "d2efe5a1018449968a689f444cca432e3d5875aba6ad08ee18ca235d64f41bb9" + } + ], + "fileName": "Modules/expat/internal.h" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-expat-latin1tab.h", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "d335ecca380e331a0ea7dc33838a4decd93ec1e4" + }, + { + "algorithm": "SHA256", + "checksumValue": "eab66226da100372e01e42e1cbcd8ac2bbbb5c1b5f95d735289cc85c7a8fc2ba" + } + ], + "fileName": "Modules/expat/latin1tab.h" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-expat-nametab.h", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "cf2bc9626c945826602ba9170786e9a2a44645e4" + }, + { + "algorithm": "SHA256", + "checksumValue": "67dcf415d37a4b692a6a8bb46f990c02d83f2ef3d01a65cd61c8594a084246f2" + } + ], + "fileName": "Modules/expat/nametab.h" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-expat-pyexpatns.h", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "baa44fe4581895d42e8d5e83d8ce6a69b1c34dbe" + }, + { + "algorithm": "SHA256", + "checksumValue": "33a7b9ac8bf4571e23272cdf644c6f9808bd44c66b149e3c41ab3870d1888609" + } + ], + "fileName": "Modules/expat/pyexpatns.h" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-expat-siphash.h", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "2b984f806f10fbfbf72d8d1b7ba2992413c15299" + }, + { + "algorithm": "SHA256", + "checksumValue": "fbce56cd680e690043bbf572188cc2d0a25dbfc0d47ac8cb98eb3de768d4e694" + } + ], + "fileName": "Modules/expat/siphash.h" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-expat-utf8tab.h", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "b77c8fcfb551553c81d6fbd94c798c8aa04ad021" + }, + { + "algorithm": "SHA256", + "checksumValue": "8cd26bd461d334d5e1caedb3af4518d401749f2fc66d56208542b29085159c18" + } + ], + "fileName": "Modules/expat/utf8tab.h" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-expat-winconfig.h", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "e774ae6ee9391aa6ffb8f775fb74e48f4b428959" + }, + { + "algorithm": "SHA256", + "checksumValue": "3c71cea9a6174718542331971a35db317902b2433be9d8dd1cb24239b635c0cc" + } + ], + "fileName": "Modules/expat/winconfig.h" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-expat-xmlparse.c", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "b580e827e16baa6b035586ffcd4d90301e5a353f" + }, + { + "algorithm": "SHA256", + "checksumValue": "483518bbd69338eefc706cd7fc0b6039df2d3e347f64097989059ed6d2385a1e" + } + ], + "fileName": "Modules/expat/xmlparse.c" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-expat-xmlrole.c", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "5ef21312af73deb2428be3fe97a65244608e76de" + }, + { + "algorithm": "SHA256", + "checksumValue": "6fcf8c72ac0112c1b98bd2039c632a66b4c3dc516ce7c1f981390951121ef3c0" + } + ], + "fileName": "Modules/expat/xmlrole.c" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-expat-xmlrole.h", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "c1a4ea6356643d0820edb9c024c20ad2aaf562dc" + }, + { + "algorithm": "SHA256", + "checksumValue": "2b5d674be6ef20c7e3f69295176d75e68c5616e4dfce0a186fdd5e2ed8315f7a" + } + ], + "fileName": "Modules/expat/xmlrole.h" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-expat-xmltok.c", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "e6d66ae9fd61d7950c62c5d87693c30a707e8577" + }, + { + "algorithm": "SHA256", + "checksumValue": "1110f651bdccfa765ad3d6f3857a35887ab35fc0fe7f3f3488fde2b238b482e3" + } + ], + "fileName": "Modules/expat/xmltok.c" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-expat-xmltok.h", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "9c2a544875fd08ba9c2397296c97263518a410aa" + }, + { + "algorithm": "SHA256", + "checksumValue": "4299a03828b98bfe47ec6809f6e279252954a9a911dc7e0f19551bd74e3af971" + } + ], + "fileName": "Modules/expat/xmltok.h" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-expat-xmltok-impl.c", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "aa96882de8e3d1d3083124b595aa911efe44e5ad" + }, + { + "algorithm": "SHA256", + "checksumValue": "0fbcba7931707c60301305dab78d2298d96447d0a5513926d8b18135228c0818" + } + ], + "fileName": "Modules/expat/xmltok_impl.c" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-expat-xmltok-impl.h", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "788332fe8040bed71172cddedb69abd848cc62f7" + }, + { + "algorithm": "SHA256", + "checksumValue": "f05ad4fe5e98429a7349ff04f57192cac58c324601f2a2e5e697ab0bc05d36d5" + } + ], + "fileName": "Modules/expat/xmltok_impl.h" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-expat-xmltok-ns.c", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "2d82d0a1201f78d478b30d108ff8fc27ee3e2672" + }, + { + "algorithm": "SHA256", + "checksumValue": "6ce6d03193279078d55280150fe91e7370370b504a6c123a79182f28341f3e90" + } + ], + "fileName": "Modules/expat/xmltok_ns.c" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-hacl-Hacl-Hash-MD5.c", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "f77449b2b4eb99f1da0938633cc558baf9c444fb" + }, + { + "algorithm": "SHA256", + "checksumValue": "0f252967debca5b35362ca53951ea16ca8bb97a19a1d24f6695f44d50010859e" + } + ], + "fileName": "Modules/_hacl/Hacl_Hash_MD5.c" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-hacl-Hacl-Hash-MD5.h", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "c24e6779a91c840f3d65d24abbce225b608b676e" + }, + { + "algorithm": "SHA256", + "checksumValue": "9cd062e782801013e3cacaba583e44e1b5e682e217d20208d5323354d42011f1" + } + ], + "fileName": "Modules/_hacl/Hacl_Hash_MD5.h" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-hacl-Hacl-Hash-SHA1.c", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "560f6ff541b5eff480ea047b147f4212bb0db7ed" + }, + { + "algorithm": "SHA256", + "checksumValue": "0ade3ab264e912d7b4e5cdcf773db8c63e4440540d295922d74b06bcfc74c77a" + } + ], + "fileName": "Modules/_hacl/Hacl_Hash_SHA1.c" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-hacl-Hacl-Hash-SHA1.h", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "853b77d45379146faaeac5fe899b28db386ad13c" + }, + { + "algorithm": "SHA256", + "checksumValue": "b13eb14f91582703819235ea7c8f807bb93e4f1e6b695499dc1d86021dc39e72" + } + ], + "fileName": "Modules/_hacl/Hacl_Hash_SHA1.h" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-hacl-Hacl-Hash-SHA2.c", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "667120b6100c946cdaa442f1173c723339923071" + }, + { + "algorithm": "SHA256", + "checksumValue": "b189459b863341a3a9c5c78c0208b6554a2f2ac26e0748fbd4432a91db21fae6" + } + ], + "fileName": "Modules/_hacl/Hacl_Hash_SHA2.c" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-hacl-Hacl-Hash-SHA2.h", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "81db38b0b920e63ec33c7109d1144c35cf091da0" + }, + { + "algorithm": "SHA256", + "checksumValue": "631c9ba19c1c2c835bb63d3f2f22b8d76fb535edfed3c254ff2a52f12af3fe61" + } + ], + "fileName": "Modules/_hacl/Hacl_Hash_SHA2.h" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-hacl-Hacl-Hash-SHA3.c", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "9c832b98a2f2a68202d2da016fb718965d7b7602" + }, + { + "algorithm": "SHA256", + "checksumValue": "38d350d1184238966cfa821a59ae00343f362182b6c2fbea7f2651763d757fb7" + } + ], + "fileName": "Modules/_hacl/Hacl_Hash_SHA3.c" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-hacl-Hacl-Hash-SHA3.h", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "ecc766fb6f7ee85e902b593b61b41e5a728fca34" + }, + { + "algorithm": "SHA256", + "checksumValue": "bae290a94366a2460f51e8468144baaade91d9048db111e10d2e2ffddc3f98cf" + } + ], + "fileName": "Modules/_hacl/Hacl_Hash_SHA3.h" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-hacl-Hacl-Streaming-Types.h", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "ab7b4d9465a2765a07f8d5bccace7182b28ed1b8" + }, + { + "algorithm": "SHA256", + "checksumValue": "26913613f3b4f8ffff0a3e211a5ebc849159094e5e11de0a31fcb95b6105b74c" + } + ], + "fileName": "Modules/_hacl/Hacl_Streaming_Types.h" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-hacl-include-krml-FStar-UInt128-Verified.h", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "2ea61d6a236147462045f65c20311819d74db80c" + }, + { + "algorithm": "SHA256", + "checksumValue": "2c22b4d49ba06d6a3053cdc66405bd5ae953a28fcfed1ab164e8f5e0f6e2fb8b" + } + ], + "fileName": "Modules/_hacl/include/krml/FStar_UInt128_Verified.h" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-hacl-include-krml-FStar-UInt-8-16-32-64.h", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "1a647d841180ac8ca667afa968c353425e81ad0d" + }, + { + "algorithm": "SHA256", + "checksumValue": "e5d1c5854833bec7ea02e227ec35bd7b49c5fb9e0f339efa0dd83e1595f722d4" + } + ], + "fileName": "Modules/_hacl/include/krml/FStar_UInt_8_16_32_64.h" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-hacl-include-krml-fstar-uint128-struct-endianness.h", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "1987119a563a8fdc5966286e274f716dbcea77ee" + }, + { + "algorithm": "SHA256", + "checksumValue": "fe57e1bc5ce3224d106e36cb8829b5399c63a68a70b0ccd0c91d82a4565c8869" + } + ], + "fileName": "Modules/_hacl/include/krml/fstar_uint128_struct_endianness.h" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-hacl-include-krml-internal-target.h", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "903c9eb76b01f3a95c04c3bc841c2fb71dea5403" + }, + { + "algorithm": "SHA256", + "checksumValue": "08ec602c7f90a1540389c0cfc95769fa7fec251e7ca143ef83c0b9f7afcf89a7" + } + ], + "fileName": "Modules/_hacl/include/krml/internal/target.h" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-hacl-include-krml-lowstar-endianness.h", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "964e09bd99ff2366afd6193b59863fc925e7fb05" + }, + { + "algorithm": "SHA256", + "checksumValue": "3734c7942bec9a434e16df069fa45bdcb84b130f14417bc5f7bfe8546272d9f5" + } + ], + "fileName": "Modules/_hacl/include/krml/lowstar_endianness.h" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-hacl-include-krml-types.h", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "df8e0ed74a5970d09d3cc4c6e7c6c7a4c4e5015c" + }, + { + "algorithm": "SHA256", + "checksumValue": "de7444c345caa4c47902c4380500356a3ee7e199d2aab84fd8c4960410154f3d" + } + ], + "fileName": "Modules/_hacl/include/krml/types.h" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-hacl-internal-Hacl-Hash-MD5.h", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "5dd4ee3c835a0d176a6e9fecbe9752fd1474ff41" + }, + { + "algorithm": "SHA256", + "checksumValue": "d82ef594cba44203576d67b047240316bb3c542912ebb7034afa1e07888cec56" + } + ], + "fileName": "Modules/_hacl/internal/Hacl_Hash_MD5.h" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-hacl-internal-Hacl-Hash-SHA1.h", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "515b3082eb7c30597773e1c63ec46688f6da3634" + }, + { + "algorithm": "SHA256", + "checksumValue": "10aacf847006b8e0dfb64d5c327443f954db6718b4aec712fb3268230df6a752" + } + ], + "fileName": "Modules/_hacl/internal/Hacl_Hash_SHA1.h" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-hacl-internal-Hacl-Hash-SHA2.h", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "a044ec12b70ba97b67e9a312827d6270452a20ca" + }, + { + "algorithm": "SHA256", + "checksumValue": "a1426b54fa7273ba5b50817c25b2b26fc85c4d1befb14092cd27dc4c99439463" + } + ], + "fileName": "Modules/_hacl/internal/Hacl_Hash_SHA2.h" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-hacl-internal-Hacl-Hash-SHA3.h", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "cfb7b520c39a73cb84c541d370455f92b998781f" + }, + { + "algorithm": "SHA256", + "checksumValue": "fd41997f9e96b3c9a3337b1b51fab965a1e21b0c16f353d156f1a1fa00709fbf" + } + ], + "fileName": "Modules/_hacl/internal/Hacl_Hash_SHA3.h" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-hacl-python-hacl-namespaces.h", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "f5c7b3ed911af6c8d582e8b3714b0c36195dc994" + }, + { + "algorithm": "SHA256", + "checksumValue": "07de72398b12957e014e97b9ac197bceef12d6d6505c2bfe8b23ee17b94ec5fa" + } + ], + "fileName": "Modules/_hacl/python_hacl_namespaces.h" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-blake2-impl-blake2-config.h", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "ff5e3ae2360adf7279a9c54d12a1d32e16a1f223" + }, + { + "algorithm": "SHA256", + "checksumValue": "1eb919e885244e43cdf7b2104ad30dc9271513478c0026f6bfb4bad6e2f0ab42" + } + ], + "fileName": "Modules/_blake2/impl/blake2-config.h" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-blake2-impl-blake2-impl.h", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "28b947b43bdc680b9f4335712bb2a5f2d5d32623" + }, + { + "algorithm": "SHA256", + "checksumValue": "4277092643b289f1d36d32cf0fd2efc30ead8bdd99342e5da3b3609dd8ea7d86" + } + ], + "fileName": "Modules/_blake2/impl/blake2-impl.h" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-blake2-impl-blake2.h", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "caa3da7953109d0d2961e3b686d2d285c484b901" + }, + { + "algorithm": "SHA256", + "checksumValue": "2f6c9d0ecf70be474f2853b52394993625a32960e0a64eae147ef97a3a5c1460" + } + ], + "fileName": "Modules/_blake2/impl/blake2.h" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-blake2-impl-blake2b-load-sse2.h", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "029a98f87a178936d9e5211c7798b3e0fc622f94" + }, + { + "algorithm": "SHA256", + "checksumValue": "b392a6e7b43813a05609e994db5fc3552c5912bd482efc781daa0778eb56ab4e" + } + ], + "fileName": "Modules/_blake2/impl/blake2b-load-sse2.h" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-blake2-impl-blake2b-load-sse41.h", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "fb466dd72344170d09e311e5ea12de99ce071357" + }, + { + "algorithm": "SHA256", + "checksumValue": "cc3072c92164142bf2f9dda4e6c08db61be68ec15a95442415e861090d08f6a2" + } + ], + "fileName": "Modules/_blake2/impl/blake2b-load-sse41.h" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-blake2-impl-blake2b-ref.c", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "4c0d79128cf891a95b1f668031d55c0c6d2e0270" + }, + { + "algorithm": "SHA256", + "checksumValue": "07b257d44e9cc2d95d4911629c92138feafd16d63fef0a5fa7b38914dfd82349" + } + ], + "fileName": "Modules/_blake2/impl/blake2b-ref.c" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-blake2-impl-blake2b-round.h", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "4c7418e2026417c9c6736fcd305a31f23e05a661" + }, + { + "algorithm": "SHA256", + "checksumValue": "fa34a60c2d198a0585033f43fd4003f4ba279c9ebcabdf5d6650def0e6d1e914" + } + ], + "fileName": "Modules/_blake2/impl/blake2b-round.h" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-blake2-impl-blake2b.c", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "6fa074693aa7305018dfa8db48010a8ef1050ad4" + }, + { + "algorithm": "SHA256", + "checksumValue": "c8c6dd861ac193d4a0e836242ff44900f83423f86d2c2940c8c4c1e41fbd5812" + } + ], + "fileName": "Modules/_blake2/impl/blake2b.c" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-blake2-impl-blake2s-load-sse2.h", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "ad3f79b6cbe3fd812722114a0d5d08064e69e4d0" + }, + { + "algorithm": "SHA256", + "checksumValue": "57f1ac6c09f4a50d95811529062220eab4f29cec3805bc6081dec00426c6df62" + } + ], + "fileName": "Modules/_blake2/impl/blake2s-load-sse2.h" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-blake2-impl-blake2s-load-sse41.h", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "51c32d79f419f3d2eb9875cd9a7f5c0d7892f8a8" + }, + { + "algorithm": "SHA256", + "checksumValue": "ecc9e09adcbe098629eafd305596bed8d7004be1d83f326995def42bbde93b23" + } + ], + "fileName": "Modules/_blake2/impl/blake2s-load-sse41.h" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-blake2-impl-blake2s-load-xop.h", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "2749a7ba0104b765d4f56f13faf70b6eb89cf203" + }, + { + "algorithm": "SHA256", + "checksumValue": "8bc95595cec4c50f5d70f2b330d3798de07cc784e8890791b3328890e602d5c5" + } + ], + "fileName": "Modules/_blake2/impl/blake2s-load-xop.h" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-blake2-impl-blake2s-ref.c", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "883fcfe85f9063819f21b1100296d1f9eb55bac1" + }, + { + "algorithm": "SHA256", + "checksumValue": "9715c00d0f11587a139b07fa26678e6d26e44d3d4910b96158d158da2b022bfb" + } + ], + "fileName": "Modules/_blake2/impl/blake2s-ref.c" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-blake2-impl-blake2s-round.h", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "5d9f69adda40ed163b287b9ed4cedb35b88f2daa" + }, + { + "algorithm": "SHA256", + "checksumValue": "65d90111c89c43bb18a9e1d1a4fdbd9f85bebd1ff00129335b85995d0f30ee8b" + } + ], + "fileName": "Modules/_blake2/impl/blake2s-round.h" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-blake2-impl-blake2s.c", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "d2691353fa54ac6ffcd7c0a294984dc9d7968ef7" + }, + { + "algorithm": "SHA256", + "checksumValue": "cfd7948c9fd50e9f9c62f8a93b20a254d1d510a862d1092af4f187b7c1a859a3" + } + ], + "fileName": "Modules/_blake2/impl/blake2s.c" + }, + { + "SPDXID": "SPDXRef-FILE-Lib-ctypes-macholib-init-.py", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "0fbc026a9771d9675e7094790b5b945334d3cb53" + }, + { + "algorithm": "SHA256", + "checksumValue": "1e77c01eec8f167ed10b754f153c0c743c8e5196ae9c81dffc08f129ab56dbfd" + } + ], + "fileName": "Lib/ctypes/macholib/__init__.py" + }, + { + "SPDXID": "SPDXRef-FILE-Lib-ctypes-macholib-dyld.py", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "4a78ebd73ce4167c722689781a15fe0b4578e967" + }, + { + "algorithm": "SHA256", + "checksumValue": "eb8e7b17f1533bc3e86e23e8695f7a5e4b7a99ef1b1575d10af54f389161b655" + } + ], + "fileName": "Lib/ctypes/macholib/dyld.py" + }, + { + "SPDXID": "SPDXRef-FILE-Lib-ctypes-macholib-dylib.py", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "f339420cc01bd01f8d0da19b6102f099075e8bcd" + }, + { + "algorithm": "SHA256", + "checksumValue": "f19ee056b18165cc6735efab0b4ca3508be9405b9646c38113316c15e8278a6f" + } + ], + "fileName": "Lib/ctypes/macholib/dylib.py" + }, + { + "SPDXID": "SPDXRef-FILE-Lib-ctypes-macholib-framework.py", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "0b219f58467d7f193fa1de0c1b118485840d855b" + }, + { + "algorithm": "SHA256", + "checksumValue": "302439e40d9cbdd61b8b7cffd0b7e1278a6811b635044ee366a36e0d991f62da" + } + ], + "fileName": "Lib/ctypes/macholib/framework.py" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-decimal-libmpdec-README.txt", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "bda6e0bd6121f7069b420bdc0bc7c49414d948d1" + }, + { + "algorithm": "SHA256", + "checksumValue": "89926cd0fe6cfb33a2b5b7416c101e9b5d42b0d639d348e0871acf6ffc8258a3" + } + ], + "fileName": "Modules/_decimal/libmpdec/README.txt" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-decimal-libmpdec-basearith.c", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "33757ce2ec0c93c1b5e03c45a495563a00e498ae" + }, + { + "algorithm": "SHA256", + "checksumValue": "ad498362c31a5b99ab19fce320ac540cf14c5c4ec09478f0ad3858da1428113d" + } + ], + "fileName": "Modules/_decimal/libmpdec/basearith.c" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-decimal-libmpdec-basearith.h", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "bf03919412c068e6969e7ac48850f91bfcd3b2b1" + }, + { + "algorithm": "SHA256", + "checksumValue": "2eaac88a71b9bcf3144396c12dcfeced573e0e550a0050d75b9ed3903248596d" + } + ], + "fileName": "Modules/_decimal/libmpdec/basearith.h" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-decimal-libmpdec-bench.c", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "c925b7f26754ae182aaa461d51802e8b6a2bb5e9" + }, + { + "algorithm": "SHA256", + "checksumValue": "007e38542ec8d9d8805fe243b5390d79211b9360e2797a20079e833e68ad9e45" + } + ], + "fileName": "Modules/_decimal/libmpdec/bench.c" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-decimal-libmpdec-bench-full.c", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "cb22686269685a53a17afdea9ed984714e399d9d" + }, + { + "algorithm": "SHA256", + "checksumValue": "1b9e892d4b268deea835ec8906f20a1e5d25e037b2e698edcd34315613f3608c" + } + ], + "fileName": "Modules/_decimal/libmpdec/bench_full.c" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-decimal-libmpdec-bits.h", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "fc91c2450cdf1e785d1347411662294c3945eb27" + }, + { + "algorithm": "SHA256", + "checksumValue": "ce7741e58ea761a24250c0bfa10058cec8c4fd220dca70a41de3927a2e4f5376" + } + ], + "fileName": "Modules/_decimal/libmpdec/bits.h" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-decimal-libmpdec-constants.c", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "7187c18916b0a546ec19b4fc4bec43d0d9fb5fc2" + }, + { + "algorithm": "SHA256", + "checksumValue": "cd430b8657cf8a616916e02f9bd5ca044d5fc19e69333f5d427e1fdb90b0864b" + } + ], + "fileName": "Modules/_decimal/libmpdec/constants.c" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-decimal-libmpdec-constants.h", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "af9cbd016fb0ef0b30ced49c0aa4ce2ca3c20125" + }, + { + "algorithm": "SHA256", + "checksumValue": "19dc46df04abb7ee08e9a403f87c8aac8d4a077efcce314c597f8b73e22884f2" + } + ], + "fileName": "Modules/_decimal/libmpdec/constants.h" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-decimal-libmpdec-context.c", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "666162870230bebd3f2383020d908806fd03909e" + }, + { + "algorithm": "SHA256", + "checksumValue": "9a265d366f31894aad78bca7fcdc1457bc4a3aa3887ca231b7d78e41f79541c0" + } + ], + "fileName": "Modules/_decimal/libmpdec/context.c" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-decimal-libmpdec-convolute.c", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "0545547a8b37b922fbe2574fbad8fc3bf16f1d33" + }, + { + "algorithm": "SHA256", + "checksumValue": "66fe27b9bb37039cad5be32b105ed509e5aefa15c1957a9058af8ee23cddc97a" + } + ], + "fileName": "Modules/_decimal/libmpdec/convolute.c" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-decimal-libmpdec-convolute.h", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "05ff0936c5bb08f40d460f5843004a1cc0751d9b" + }, + { + "algorithm": "SHA256", + "checksumValue": "c00d17450c2b8e1d7f1eb8a084f7e6a68f257a453f8701600e860bf357c531d7" + } + ], + "fileName": "Modules/_decimal/libmpdec/convolute.h" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-decimal-libmpdec-crt.c", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "fe8176849bc99a306332ba25caa4e91bfa3c6f7d" + }, + { + "algorithm": "SHA256", + "checksumValue": "1f4e65c44864c3e911a6e91f33adec76765293e90553459e3ebce35a58898dba" + } + ], + "fileName": "Modules/_decimal/libmpdec/crt.c" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-decimal-libmpdec-crt.h", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "1930b9e0910014b3479aec4e940f02118d9e4a08" + }, + { + "algorithm": "SHA256", + "checksumValue": "7d31f1d0dd73b62964dab0f7a1724473bf87f1f95d8febf0b40c15430ae9a47c" + } + ], + "fileName": "Modules/_decimal/libmpdec/crt.h" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-decimal-libmpdec-difradix2.c", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "415c51e7d7f517b6366bec2a809610d0d38ada14" + }, + { + "algorithm": "SHA256", + "checksumValue": "0a9fef8a374f55277e9f6000b7277bb037b9763c32b156c29950422b057498bd" + } + ], + "fileName": "Modules/_decimal/libmpdec/difradix2.c" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-decimal-libmpdec-difradix2.h", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "d8a998c3bee4c3d9059ba7bf9ae6a8b64649c2ba" + }, + { + "algorithm": "SHA256", + "checksumValue": "5c6766496224de657400995b58b64db3e7084004bf00daebdd7e08d0c5995243" + } + ], + "fileName": "Modules/_decimal/libmpdec/difradix2.h" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-decimal-libmpdec-examples-README.txt", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "158f6ad18edf348efa4fdd7cf61114c77c1d22e9" + }, + { + "algorithm": "SHA256", + "checksumValue": "7b0da2758097a2688f06b3c7ca46b2ebc8329addbd28bb4f5fe95626cc81f8a9" + } + ], + "fileName": "Modules/_decimal/libmpdec/examples/README.txt" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-decimal-libmpdec-examples-compare.c", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "ef80ba26847287fb351ab0df0a78b5f08ba0b5b7" + }, + { + "algorithm": "SHA256", + "checksumValue": "452666ee4eb10a8cf0a926cb3bcf5e95b5c361fa129dbdfe27b654e6d640417e" + } + ], + "fileName": "Modules/_decimal/libmpdec/examples/compare.c" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-decimal-libmpdec-examples-div.c", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "6ca3a369b3d1e140fdc93c4fdbedb724f7daf969" + }, + { + "algorithm": "SHA256", + "checksumValue": "6d369f5a24d0bb1e7cb6a4f8b0e97a273260e7668c8a540a8fcc92e039f7af2e" + } + ], + "fileName": "Modules/_decimal/libmpdec/examples/div.c" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-decimal-libmpdec-examples-divmod.c", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "3872a28b4f77e07e1760256067ea338a8dd183f8" + }, + { + "algorithm": "SHA256", + "checksumValue": "5db54bae75ac3d7fa12f1bb0f7ce1bf797df86a81030e8c3ce44d3b1f9b958b7" + } + ], + "fileName": "Modules/_decimal/libmpdec/examples/divmod.c" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-decimal-libmpdec-examples-multiply.c", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "25dbc94fd4ee5dec21061d2d40dd5d0f88849cb1" + }, + { + "algorithm": "SHA256", + "checksumValue": "22ed39b18fa740a27aacfd29a7bb40066be24500ba49b9b1f24e2af1e039fcd9" + } + ], + "fileName": "Modules/_decimal/libmpdec/examples/multiply.c" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-decimal-libmpdec-examples-pow.c", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "13d3b7657dc2dc5000fea428f57963d520792ef7" + }, + { + "algorithm": "SHA256", + "checksumValue": "cd8c037649b3d4d6897c9acd2f92f3f9d5390433061d5e48623a5d526a3f4f9c" + } + ], + "fileName": "Modules/_decimal/libmpdec/examples/pow.c" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-decimal-libmpdec-examples-powmod.c", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "1f7e6c3d3e38df52bbcec0f5a180a8f328679618" + }, + { + "algorithm": "SHA256", + "checksumValue": "e29614b43abf1856b656a84d6b67c22cc5dc7af8cbae8ddc7acf17022220ee12" + } + ], + "fileName": "Modules/_decimal/libmpdec/examples/powmod.c" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-decimal-libmpdec-examples-shift.c", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "0bd9ce89c7987d1109eb7b0c8f1f9a1298e1422e" + }, + { + "algorithm": "SHA256", + "checksumValue": "203f2dbf11d115580cb3c7c524ac6ccca2a7b31d89545db1b6263381b5de2b6a" + } + ], + "fileName": "Modules/_decimal/libmpdec/examples/shift.c" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-decimal-libmpdec-examples-sqrt.c", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "b401ba0814e17c9164c0df26e01cc0a355382f46" + }, + { + "algorithm": "SHA256", + "checksumValue": "f3dc2ce321833bbd4b3d1d9ea6fa2e0bcc1bfe1e39abb8d55be53e46c33949db" + } + ], + "fileName": "Modules/_decimal/libmpdec/examples/sqrt.c" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-decimal-libmpdec-fnt.c", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "060615ddef089a5a8f879a57e4968d920972a0e2" + }, + { + "algorithm": "SHA256", + "checksumValue": "a9f923524d53a9445769f27405375ec3d95fa804bb11db5ee249ae047f11cfce" + } + ], + "fileName": "Modules/_decimal/libmpdec/fnt.c" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-decimal-libmpdec-fnt.h", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "b205043ebeaf065b16505a299342a992654f19b0" + }, + { + "algorithm": "SHA256", + "checksumValue": "3b03e69adf78fde68c8f87d33595d557237581d33fc067e1039eed9e9f2cc44c" + } + ], + "fileName": "Modules/_decimal/libmpdec/fnt.h" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-decimal-libmpdec-fourstep.c", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "702c27599b43280c94906235d7e1a74193ba701b" + }, + { + "algorithm": "SHA256", + "checksumValue": "cf2e69b946ec14b087e523c0ff606553070d13c23e851fb0ba1df51a728017e6" + } + ], + "fileName": "Modules/_decimal/libmpdec/fourstep.c" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-decimal-libmpdec-fourstep.h", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "ee5291c265ef1f5ae373bc243a4d96975eb3e7b5" + }, + { + "algorithm": "SHA256", + "checksumValue": "dbaced03b52d0f880c377b86c943bcb36f24d557c99a5e9732df3ad5debb5917" + } + ], + "fileName": "Modules/_decimal/libmpdec/fourstep.h" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-decimal-libmpdec-io.c", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "12402bcf7f0161adb83f78163f41cc10a5e5de5f" + }, + { + "algorithm": "SHA256", + "checksumValue": "cba044c76b6bc3ae6cfa49df1121cad7552140157b9e61e11cbb6580cc5d74cf" + } + ], + "fileName": "Modules/_decimal/libmpdec/io.c" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-decimal-libmpdec-io.h", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "28c653cd40b1ce46575e41f5dbfda5f6dd0db4d1" + }, + { + "algorithm": "SHA256", + "checksumValue": "259eab89fe27914e0e39e61199094a357ac60d86b2aab613c909040ff64a4a0c" + } + ], + "fileName": "Modules/_decimal/libmpdec/io.h" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-decimal-libmpdec-literature-REFERENCES.txt", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "218d1d7bedb335cd2c31eae89a15873c3139e13f" + }, + { + "algorithm": "SHA256", + "checksumValue": "a57e8bed93ded481ef264166aec2c49d1a7f3252f29a873ee41fff053cfd9c20" + } + ], + "fileName": "Modules/_decimal/libmpdec/literature/REFERENCES.txt" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-decimal-libmpdec-literature-bignum.txt", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "f67eab2431336cf6eeafb30cdafd7e54c251def3" + }, + { + "algorithm": "SHA256", + "checksumValue": "dc34aa122c208ce79e3fc6baee8628094ffaf6a662862dd5647836241f6ebd79" + } + ], + "fileName": "Modules/_decimal/libmpdec/literature/bignum.txt" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-decimal-libmpdec-literature-fnt.py", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "a58cfbcd8ea57d66ddfd11fb5a170138c8bbfb3a" + }, + { + "algorithm": "SHA256", + "checksumValue": "122de20eebf87274af2d02072251a94500e7df2d5ef29e81aeabeda991c079e3" + } + ], + "fileName": "Modules/_decimal/libmpdec/literature/fnt.py" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-decimal-libmpdec-literature-matrix-transform.txt", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "9a947f6b660150cbd457c4458da2956a36c5824d" + }, + { + "algorithm": "SHA256", + "checksumValue": "592659e7192e3a939b797f5bc7455455834a285f5d8b643ccd780b5114914f73" + } + ], + "fileName": "Modules/_decimal/libmpdec/literature/matrix-transform.txt" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-decimal-libmpdec-literature-mulmod-64.txt", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "69fe9afb8353b5a2b57917469c51c64ac518169d" + }, + { + "algorithm": "SHA256", + "checksumValue": "229a80ca940c594a32e3345412370cbc097043fe59c66a6153cbcf01e7837266" + } + ], + "fileName": "Modules/_decimal/libmpdec/literature/mulmod-64.txt" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-decimal-libmpdec-literature-mulmod-ppro.txt", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "720d468a1f51098036c7a0c869810fff22ed9b79" + }, + { + "algorithm": "SHA256", + "checksumValue": "f3549fc73f697a087267c7b042e30a409e191cbba69a2c0902685e507fbae9f7" + } + ], + "fileName": "Modules/_decimal/libmpdec/literature/mulmod-ppro.txt" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-decimal-libmpdec-literature-six-step.txt", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "6815ec3a39baebebe7b3f51d45d10c180a659f17" + }, + { + "algorithm": "SHA256", + "checksumValue": "bf15f73910a173c98fca9db56122b6cc71983668fa8b934c46ca21a57398ec54" + } + ], + "fileName": "Modules/_decimal/libmpdec/literature/six-step.txt" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-decimal-libmpdec-literature-umodarith.lisp", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "c91ac4438e661ce78f86e981257546e5adff39ae" + }, + { + "algorithm": "SHA256", + "checksumValue": "783a1b4b9b7143677b0c3d30ffaf28aa0cb01956409031fa38ed8011970bdee0" + } + ], + "fileName": "Modules/_decimal/libmpdec/literature/umodarith.lisp" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-decimal-libmpdec-mpalloc.c", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "7e8dfb4b7a801b48c501969b001153203b14679e" + }, + { + "algorithm": "SHA256", + "checksumValue": "5ba2f4c80302e71fb216aa247c858e0bf6c8cfabffe7980ac17d4d023c0fef2b" + } + ], + "fileName": "Modules/_decimal/libmpdec/mpalloc.c" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-decimal-libmpdec-mpalloc.h", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "bccb6a6ae76fd7f6c8a9102a78958bcad7862950" + }, + { + "algorithm": "SHA256", + "checksumValue": "f7412521de38afb837fcabc2b1d48b971b86bfaa55f3f40d58ff9e46e92debd3" + } + ], + "fileName": "Modules/_decimal/libmpdec/mpalloc.h" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-decimal-libmpdec-mpdecimal.c", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "f4539afb1ace58c52d18ffd0cc7704f53ca55182" + }, + { + "algorithm": "SHA256", + "checksumValue": "4f89b8095e408a18deff79cfb605299e615bae747898eb105d8936064f7fb626" + } + ], + "fileName": "Modules/_decimal/libmpdec/mpdecimal.c" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-decimal-libmpdec-mpdecimal.h", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "4b80e25ac49b7e1ea0d1e84967ee32a3d111fc4c" + }, + { + "algorithm": "SHA256", + "checksumValue": "ea0b9c6b296c13aed6ecaa50b463e39a9c1bdc059b84f50507fd8247b2e660f9" + } + ], + "fileName": "Modules/_decimal/libmpdec/mpdecimal.h" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-decimal-libmpdec-mpsignal.c", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "5c7305a6db0fddf64c6d97e29d3b0c402e3d5d6e" + }, + { + "algorithm": "SHA256", + "checksumValue": "653171cf2549719478417db7e9800fa0f9d99c02dec6da6876329ccf2c07b93f" + } + ], + "fileName": "Modules/_decimal/libmpdec/mpsignal.c" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-decimal-libmpdec-numbertheory.c", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "d736b874c43777ca021dde5289ea718893f39219" + }, + { + "algorithm": "SHA256", + "checksumValue": "bdbf2e246f341a3ba3f6f9d8759e7cb222eb9b15f9ed1e7c9f6a59cbb9f8bc91" + } + ], + "fileName": "Modules/_decimal/libmpdec/numbertheory.c" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-decimal-libmpdec-numbertheory.h", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "d341508d8c6dd4c4cbd8b99afc8029945f9bbe0d" + }, + { + "algorithm": "SHA256", + "checksumValue": "2f7d5b40af508fa6ac86f5d62101fa3bf683c63b24aa87c9548e3fdd13abc57b" + } + ], + "fileName": "Modules/_decimal/libmpdec/numbertheory.h" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-decimal-libmpdec-sixstep.c", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "cbd05d68bb3940d0d7d0818b14cc03b090a4dd74" + }, + { + "algorithm": "SHA256", + "checksumValue": "7602aaf98ec9525bc4b3cab9631615e1be2efd9af894002ef4e3f5ec63924fcf" + } + ], + "fileName": "Modules/_decimal/libmpdec/sixstep.c" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-decimal-libmpdec-sixstep.h", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "4c059463ec4b4522562dab24760fc64c172c9eee" + }, + { + "algorithm": "SHA256", + "checksumValue": "a191366348b3d3dd49b9090ec5c77dbd77bb3a523c01ff32adafa137e5097ce7" + } + ], + "fileName": "Modules/_decimal/libmpdec/sixstep.h" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-decimal-libmpdec-transpose.c", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "cc5593ac9fdb60480cc23fc9d6f27d85670bd35f" + }, + { + "algorithm": "SHA256", + "checksumValue": "2d12fcae512143a9376c8a0d4c1ba3008e420e024497a7e7ec64c6bec23fcddc" + } + ], + "fileName": "Modules/_decimal/libmpdec/transpose.c" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-decimal-libmpdec-transpose.h", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "2f616425756b6cbdf7d189744870b98b613455bd" + }, + { + "algorithm": "SHA256", + "checksumValue": "fafeb2b901b2b41bf0df00be7d99b84df1a78e3cc1e582e09cbfc3b6d44d4abe" + } + ], + "fileName": "Modules/_decimal/libmpdec/transpose.h" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-decimal-libmpdec-typearith.h", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "b1e9341e173cc8e219ad4aa45fad36d92cce10d3" + }, + { + "algorithm": "SHA256", + "checksumValue": "25e0a0703b51744277834e6b2398d7b7d2c17f92bf30f8b6f949e0486ae2b346" + } + ], + "fileName": "Modules/_decimal/libmpdec/typearith.h" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-decimal-libmpdec-umodarith.h", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "46f6483fce136cd3cc2f7516ee119a487d86333e" + }, + { + "algorithm": "SHA256", + "checksumValue": "bfe1ddb2ca92906456b80745adcbe02c83cadac3ef69caa21bc09b7292cc152b" + } + ], + "fileName": "Modules/_decimal/libmpdec/umodarith.h" + }, + { + "SPDXID": "SPDXRef-FILE-Modules-decimal-libmpdec-vcdiv64.asm", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "d0cc1052fcba08b773d935b0ae2dc6b80d0f2f68" + }, + { + "algorithm": "SHA256", + "checksumValue": "aacc3e47ea8f41e8840c6c67f64ec96d54696a16889903098fa1aab56949a00f" + } + ], + "fileName": "Modules/_decimal/libmpdec/vcdiv64.asm" + }, + { + "SPDXID": "SPDXRef-FILE-Lib-ensurepip-bundled-pip-23.3.2-py3-none-any.whl", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "8e48f55ab2965ee64bd55cc91a8077d184a33e30" + }, + { + "algorithm": "SHA256", + "checksumValue": "5052d7889c1f9d05224cd41741acb7c5d6fa735ab34e339624a614eaaa7e7d76" + } + ], + "fileName": "Lib/ensurepip/_bundled/pip-23.3.2-py3-none-any.whl" + } + ], + "packages": [ + { + "SPDXID": "SPDXRef-PACKAGE-expat", + "checksums": [ + { + "algorithm": "SHA256", + "checksumValue": "6b902ab103843592be5e99504f846ec109c1abb692e85347587f237a4ffa1033" + } + ], + "downloadLocation": "https://github.com/libexpat/libexpat/releases/download/R_2_5_0/expat-2.5.0.tar.gz", + "externalRefs": [ + { + "referenceCategory": "SECURITY", + "referenceLocator": "cpe:2.3:a:libexpat_project:libexpat:2.5.0:*:*:*:*:*:*:*", + "referenceType": "cpe23Type" + } + ], + "licenseConcluded": "MIT", + "name": "expat", + "originator": "Organization: Expat development team", + "primaryPackagePurpose": "SOURCE", + "versionInfo": "2.5.0" + }, + { + "SPDXID": "SPDXRef-PACKAGE-hacl-star", + "checksums": [ + { + "algorithm": "SHA256", + "checksumValue": "c23ac158b238c368389dc86bfc315263e5c0e57785da74144aea2cab9a3d51a2" + } + ], + "downloadLocation": "https://github.com/hacl-star/hacl-star/archive/521af282fdf6d60227335120f18ae9309a4b8e8c.zip", + "externalRefs": [ + { + "referenceCategory": "SECURITY", + "referenceLocator": "cpe:2.3:a:hacl-star:hacl-star:521af282fdf6d60227335120f18ae9309a4b8e8c:*:*:*:*:*:*:*", + "referenceType": "cpe23Type" + } + ], + "licenseConcluded": "Apache-2.0", + "name": "hacl-star", + "originator": "Organization: HACL* Developers", + "primaryPackagePurpose": "SOURCE", + "versionInfo": "521af282fdf6d60227335120f18ae9309a4b8e8c" + }, + { + "SPDXID": "SPDXRef-PACKAGE-libb2", + "checksums": [ + { + "algorithm": "SHA256", + "checksumValue": "53626fddce753c454a3fea581cbbc7fe9bbcf0bc70416d48fdbbf5d87ef6c72e" + } + ], + "downloadLocation": "https://github.com/BLAKE2/libb2/releases/download/v0.98.1/libb2-0.98.1.tar.gz", + "externalRefs": [ + { + "referenceCategory": "SECURITY", + "referenceLocator": "cpe:2.3:a:blake2:libb2:0.98.1:*:*:*:*:*:*:*", + "referenceType": "cpe23Type" + } + ], + "licenseConcluded": "CC0-1.0", + "name": "libb2", + "originator": "Organization: BLAKE2 - fast secure hashing", + "primaryPackagePurpose": "SOURCE", + "versionInfo": "0.98.1" + }, + { + "SPDXID": "SPDXRef-PACKAGE-macholib", + "checksums": [ + { + "algorithm": "SHA256", + "checksumValue": "c76f268f5054024e962f2515a0e522baf85313064f6740d80375afc850787a38" + } + ], + "downloadLocation": "https://files.pythonhosted.org/packages/ec/57/f0a712efc3ed982cf4038a3cee172057303b9be914c32c93b2fbec27f785/macholib-1.0.tar.gz", + "externalRefs": [ + { + "referenceCategory": "PACKAGE_MANAGER", + "referenceLocator": "pkg:pypi/macholib@1.0", + "referenceType": "purl" + } + ], + "licenseConcluded": "MIT", + "name": "macholib", + "originator": "Person: Ronald Oussoren (ronaldoussoren@mac.com)", + "primaryPackagePurpose": "SOURCE", + "versionInfo": "1.0" + }, + { + "SPDXID": "SPDXRef-PACKAGE-mpdecimal", + "checksums": [ + { + "algorithm": "SHA256", + "checksumValue": "9f9cd4c041f99b5c49ffb7b59d9f12d95b683d88585608aa56a6307667b2b21f" + } + ], + "downloadLocation": "https://www.bytereef.org/software/mpdecimal/releases/mpdecimal-2.5.1.tar.gz", + "externalRefs": [ + { + "referenceCategory": "SECURITY", + "referenceLocator": "cpe:2.3:a:bytereef:mpdecimal:2.5.1:*:*:*:*:*:*:*", + "referenceType": "cpe23Type" + } + ], + "licenseConcluded": "BSD-2-Clause", + "name": "mpdecimal", + "originator": "Organization: bytereef.org", + "primaryPackagePurpose": "SOURCE", + "versionInfo": "2.5.1" + }, + { + "SPDXID": "SPDXRef-PACKAGE-pip", + "checksums": [ + { + "algorithm": "SHA256", + "checksumValue": "5052d7889c1f9d05224cd41741acb7c5d6fa735ab34e339624a614eaaa7e7d76" + } + ], + "downloadLocation": "https://files.pythonhosted.org/packages/15/aa/3f4c7bcee2057a76562a5b33ecbd199be08cdb4443a02e26bd2c3cf6fc39/pip-23.3.2-py3-none-any.whl", + "externalRefs": [ + { + "referenceCategory": "SECURITY", + "referenceLocator": "cpe:2.3:a:pypa:pip:23.3.2:*:*:*:*:*:*:*", + "referenceType": "cpe23Type" + }, + { + "referenceCategory": "PACKAGE_MANAGER", + "referenceLocator": "pkg:pypi/pip@23.3.2", + "referenceType": "purl" + } + ], + "licenseConcluded": "MIT", + "name": "pip", + "originator": "Organization: Python Packaging Authority", + "primaryPackagePurpose": "SOURCE", + "versionInfo": "23.3.2" + } + ], + "relationships": [ + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-expat-COPYING", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-expat" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-expat-ascii.h", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-expat" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-expat-asciitab.h", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-expat" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-expat-expat.h", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-expat" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-expat-expat-config.h", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-expat" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-expat-expat-external.h", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-expat" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-expat-iasciitab.h", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-expat" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-expat-internal.h", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-expat" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-expat-latin1tab.h", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-expat" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-expat-nametab.h", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-expat" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-expat-pyexpatns.h", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-expat" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-expat-siphash.h", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-expat" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-expat-utf8tab.h", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-expat" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-expat-winconfig.h", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-expat" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-expat-xmlparse.c", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-expat" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-expat-xmlrole.c", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-expat" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-expat-xmlrole.h", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-expat" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-expat-xmltok.c", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-expat" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-expat-xmltok.h", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-expat" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-expat-xmltok-impl.c", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-expat" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-expat-xmltok-impl.h", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-expat" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-expat-xmltok-ns.c", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-expat" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-hacl-Hacl-Hash-MD5.c", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-hacl-star" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-hacl-Hacl-Hash-MD5.h", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-hacl-star" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-hacl-Hacl-Hash-SHA1.c", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-hacl-star" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-hacl-Hacl-Hash-SHA1.h", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-hacl-star" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-hacl-Hacl-Hash-SHA2.c", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-hacl-star" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-hacl-Hacl-Hash-SHA2.h", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-hacl-star" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-hacl-Hacl-Hash-SHA3.c", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-hacl-star" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-hacl-Hacl-Hash-SHA3.h", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-hacl-star" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-hacl-Hacl-Streaming-Types.h", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-hacl-star" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-hacl-include-krml-FStar-UInt128-Verified.h", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-hacl-star" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-hacl-include-krml-FStar-UInt-8-16-32-64.h", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-hacl-star" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-hacl-include-krml-fstar-uint128-struct-endianness.h", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-hacl-star" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-hacl-include-krml-internal-target.h", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-hacl-star" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-hacl-include-krml-lowstar-endianness.h", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-hacl-star" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-hacl-include-krml-types.h", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-hacl-star" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-hacl-internal-Hacl-Hash-MD5.h", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-hacl-star" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-hacl-internal-Hacl-Hash-SHA1.h", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-hacl-star" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-hacl-internal-Hacl-Hash-SHA2.h", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-hacl-star" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-hacl-internal-Hacl-Hash-SHA3.h", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-hacl-star" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-hacl-python-hacl-namespaces.h", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-hacl-star" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-blake2-impl-blake2-config.h", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-libb2" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-blake2-impl-blake2-impl.h", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-libb2" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-blake2-impl-blake2.h", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-libb2" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-blake2-impl-blake2b-load-sse2.h", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-libb2" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-blake2-impl-blake2b-load-sse41.h", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-libb2" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-blake2-impl-blake2b-ref.c", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-libb2" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-blake2-impl-blake2b-round.h", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-libb2" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-blake2-impl-blake2b.c", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-libb2" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-blake2-impl-blake2s-load-sse2.h", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-libb2" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-blake2-impl-blake2s-load-sse41.h", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-libb2" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-blake2-impl-blake2s-load-xop.h", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-libb2" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-blake2-impl-blake2s-ref.c", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-libb2" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-blake2-impl-blake2s-round.h", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-libb2" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-blake2-impl-blake2s.c", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-libb2" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Lib-ctypes-macholib-init-.py", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-macholib" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Lib-ctypes-macholib-dyld.py", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-macholib" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Lib-ctypes-macholib-dylib.py", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-macholib" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Lib-ctypes-macholib-framework.py", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-macholib" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-decimal-libmpdec-README.txt", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-mpdecimal" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-decimal-libmpdec-basearith.c", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-mpdecimal" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-decimal-libmpdec-basearith.h", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-mpdecimal" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-decimal-libmpdec-bench.c", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-mpdecimal" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-decimal-libmpdec-bench-full.c", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-mpdecimal" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-decimal-libmpdec-bits.h", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-mpdecimal" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-decimal-libmpdec-constants.c", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-mpdecimal" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-decimal-libmpdec-constants.h", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-mpdecimal" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-decimal-libmpdec-context.c", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-mpdecimal" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-decimal-libmpdec-convolute.c", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-mpdecimal" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-decimal-libmpdec-convolute.h", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-mpdecimal" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-decimal-libmpdec-crt.c", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-mpdecimal" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-decimal-libmpdec-crt.h", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-mpdecimal" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-decimal-libmpdec-difradix2.c", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-mpdecimal" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-decimal-libmpdec-difradix2.h", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-mpdecimal" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-decimal-libmpdec-examples-README.txt", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-mpdecimal" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-decimal-libmpdec-examples-compare.c", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-mpdecimal" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-decimal-libmpdec-examples-div.c", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-mpdecimal" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-decimal-libmpdec-examples-divmod.c", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-mpdecimal" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-decimal-libmpdec-examples-multiply.c", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-mpdecimal" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-decimal-libmpdec-examples-pow.c", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-mpdecimal" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-decimal-libmpdec-examples-powmod.c", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-mpdecimal" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-decimal-libmpdec-examples-shift.c", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-mpdecimal" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-decimal-libmpdec-examples-sqrt.c", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-mpdecimal" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-decimal-libmpdec-fnt.c", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-mpdecimal" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-decimal-libmpdec-fnt.h", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-mpdecimal" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-decimal-libmpdec-fourstep.c", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-mpdecimal" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-decimal-libmpdec-fourstep.h", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-mpdecimal" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-decimal-libmpdec-io.c", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-mpdecimal" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-decimal-libmpdec-io.h", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-mpdecimal" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-decimal-libmpdec-literature-REFERENCES.txt", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-mpdecimal" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-decimal-libmpdec-literature-bignum.txt", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-mpdecimal" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-decimal-libmpdec-literature-fnt.py", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-mpdecimal" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-decimal-libmpdec-literature-matrix-transform.txt", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-mpdecimal" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-decimal-libmpdec-literature-mulmod-64.txt", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-mpdecimal" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-decimal-libmpdec-literature-mulmod-ppro.txt", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-mpdecimal" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-decimal-libmpdec-literature-six-step.txt", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-mpdecimal" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-decimal-libmpdec-literature-umodarith.lisp", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-mpdecimal" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-decimal-libmpdec-mpalloc.c", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-mpdecimal" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-decimal-libmpdec-mpalloc.h", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-mpdecimal" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-decimal-libmpdec-mpdecimal.c", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-mpdecimal" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-decimal-libmpdec-mpdecimal.h", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-mpdecimal" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-decimal-libmpdec-mpsignal.c", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-mpdecimal" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-decimal-libmpdec-numbertheory.c", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-mpdecimal" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-decimal-libmpdec-numbertheory.h", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-mpdecimal" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-decimal-libmpdec-sixstep.c", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-mpdecimal" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-decimal-libmpdec-sixstep.h", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-mpdecimal" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-decimal-libmpdec-transpose.c", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-mpdecimal" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-decimal-libmpdec-transpose.h", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-mpdecimal" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-decimal-libmpdec-typearith.h", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-mpdecimal" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-decimal-libmpdec-umodarith.h", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-mpdecimal" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Modules-decimal-libmpdec-vcdiv64.asm", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-mpdecimal" + }, + { + "relatedSpdxElement": "SPDXRef-FILE-Lib-ensurepip-bundled-pip-23.3.2-py3-none-any.whl", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-PACKAGE-pip" + } + ], + "spdxVersion": "SPDX-2.3" +} \ No newline at end of file diff --git a/Misc/stable_abi.toml b/Misc/stable_abi.toml index 16d5c1a07ae3e2..22b25dd0ec141f 100644 --- a/Misc/stable_abi.toml +++ b/Misc/stable_abi.toml @@ -2450,3 +2450,34 @@ added = '3.13' [function.PyDict_GetItemStringRef] added = '3.13' +[function.PyLong_AsInt] + added = '3.13' +[function.PyObject_HasAttrWithError] + added = '3.13' +[function.PyObject_HasAttrStringWithError] + added = '3.13' +[function.PyMapping_HasKeyWithError] + added = '3.13' +[function.PyMapping_HasKeyStringWithError] + added = '3.13' +[function.Py_IsFinalizing] + added = '3.13' +[function.PyUnicode_EqualToUTF8] + added = '3.13' +[function.PyUnicode_EqualToUTF8AndSize] + added = '3.13' +[function.PyMem_RawMalloc] + added = '3.13' +[function.PyMem_RawCalloc] + added = '3.13' +[function.PyMem_RawRealloc] + added = '3.13' +[function.PyMem_RawFree] + added = '3.13' +[function.PySys_Audit] + added = '3.13' +[function.PySys_AuditTuple] + added = '3.13' +[function._Py_SetRefcnt] + added = '3.13' + abi_only = true diff --git a/Modules/Setup b/Modules/Setup index 8676f9ddce4841..8ad9a5aebbfcaa 100644 --- a/Modules/Setup +++ b/Modules/Setup @@ -155,6 +155,7 @@ PYTHONPATH=$(COREPYTHONPATH) #math mathmodule.c #mmap mmapmodule.c #select selectmodule.c +#_sysconfig _sysconfig.c # XML #_elementtree _elementtree.c @@ -272,6 +273,7 @@ PYTHONPATH=$(COREPYTHONPATH) #_xxsubinterpreters _xxsubinterpretersmodule.c #_xxinterpchannels _xxinterpchannelsmodule.c +#_xxinterpqueues _xxinterpqueuesmodule.c #_xxtestfuzz _xxtestfuzz/_xxtestfuzz.c _xxtestfuzz/fuzzer.c #_testbuffer _testbuffer.c #_testinternalcapi _testinternalcapi.c diff --git a/Modules/Setup.bootstrap.in b/Modules/Setup.bootstrap.in index 8ef0f203a82a8e..aa4e60e272653b 100644 --- a/Modules/Setup.bootstrap.in +++ b/Modules/Setup.bootstrap.in @@ -11,6 +11,7 @@ faulthandler faulthandler.c posix posixmodule.c _signal signalmodule.c _tracemalloc _tracemalloc.c +_suggestions _suggestions.c # modules used by importlib, deepfreeze, freeze, runpy, and sysconfig _codecs _codecsmodule.c @@ -19,6 +20,7 @@ errno errnomodule.c _io _io/_iomodule.c _io/iobase.c _io/fileio.c _io/bytesio.c _io/bufferedio.c _io/textio.c _io/stringio.c itertools itertoolsmodule.c _sre _sre/sre.c +_sysconfig _sysconfig.c _thread _threadmodule.c time timemodule.c _typing _typingmodule.c diff --git a/Modules/Setup.stdlib.in b/Modules/Setup.stdlib.in index 11a022e3d2044e..8a65a9cffb1b9d 100644 --- a/Modules/Setup.stdlib.in +++ b/Modules/Setup.stdlib.in @@ -41,8 +41,11 @@ @MODULE__QUEUE_TRUE@_queue _queuemodule.c @MODULE__RANDOM_TRUE@_random _randommodule.c @MODULE__STRUCT_TRUE@_struct _struct.c + +# build supports subinterpreters @MODULE__XXSUBINTERPRETERS_TRUE@_xxsubinterpreters _xxsubinterpretersmodule.c @MODULE__XXINTERPCHANNELS_TRUE@_xxinterpchannels _xxinterpchannelsmodule.c +@MODULE__XXINTERPQUEUES_TRUE@_xxinterpqueues _xxinterpqueuesmodule.c @MODULE__ZONEINFO_TRUE@_zoneinfo _zoneinfo.c # needs libm @@ -158,9 +161,10 @@ @MODULE_XXSUBTYPE_TRUE@xxsubtype xxsubtype.c @MODULE__XXTESTFUZZ_TRUE@_xxtestfuzz _xxtestfuzz/_xxtestfuzz.c _xxtestfuzz/fuzzer.c @MODULE__TESTBUFFER_TRUE@_testbuffer _testbuffer.c -@MODULE__TESTINTERNALCAPI_TRUE@_testinternalcapi _testinternalcapi.c -@MODULE__TESTCAPI_TRUE@_testcapi _testcapimodule.c _testcapi/vectorcall.c _testcapi/vectorcall_limited.c _testcapi/heaptype.c _testcapi/unicode.c _testcapi/getargs.c _testcapi/datetime.c _testcapi/docstring.c _testcapi/mem.c _testcapi/watchers.c _testcapi/long.c _testcapi/float.c _testcapi/structmember.c _testcapi/exceptions.c _testcapi/code.c _testcapi/buffer.c _testcapi/pyos.c _testcapi/immortal.c _testcapi/heaptype_relative.c _testcapi/gc.c +@MODULE__TESTINTERNALCAPI_TRUE@_testinternalcapi _testinternalcapi.c _testinternalcapi/test_lock.c _testinternalcapi/pytime.c _testinternalcapi/set.c _testinternalcapi/test_critical_sections.c +@MODULE__TESTCAPI_TRUE@_testcapi _testcapimodule.c _testcapi/vectorcall.c _testcapi/vectorcall_limited.c _testcapi/heaptype.c _testcapi/abstract.c _testcapi/bytearray.c _testcapi/bytes.c _testcapi/unicode.c _testcapi/dict.c _testcapi/set.c _testcapi/list.c _testcapi/tuple.c _testcapi/getargs.c _testcapi/datetime.c _testcapi/docstring.c _testcapi/mem.c _testcapi/watchers.c _testcapi/long.c _testcapi/float.c _testcapi/complex.c _testcapi/numbers.c _testcapi/structmember.c _testcapi/exceptions.c _testcapi/code.c _testcapi/buffer.c _testcapi/pyatomic.c _testcapi/pyos.c _testcapi/file.c _testcapi/codec.c _testcapi/immortal.c _testcapi/heaptype_relative.c _testcapi/gc.c _testcapi/sys.c _testcapi/hash.c @MODULE__TESTCLINIC_TRUE@_testclinic _testclinic.c +@MODULE__TESTCLINIC_LIMITED_TRUE@_testclinic_limited _testclinic_limited.c # Some testing modules MUST be built as shared libraries. *shared* diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c index 39c803355ba95b..c1aa849ecf1aad 100644 --- a/Modules/_asynciomodule.c +++ b/Modules/_asynciomodule.c @@ -3,6 +3,8 @@ #endif #include "Python.h" +#include "pycore_dict.h" // _PyDict_GetItem_KnownHash() +#include "pycore_modsupport.h" // _PyArg_CheckPositional() #include "pycore_moduleobject.h" // _PyModule_GetState() #include "pycore_pyerrors.h" // _PyErr_ClearExcState() #include "pycore_pylifecycle.h" // _Py_IsInterpreterFinalizing() @@ -529,7 +531,7 @@ future_init(FutureObj *fut, PyObject *loop) } if (is_true && !_Py_IsInterpreterFinalizing(_PyInterpreterState_GET())) { /* Only try to capture the traceback if the interpreter is not being - finalized. The original motivation to add a `_Py_IsFinalizing()` + finalized. The original motivation to add a `Py_IsFinalizing()` call was to prevent SIGSEGV when a Future is created in a __del__ method, which is called during the interpreter shutdown and the traceback module is already unloaded. @@ -595,12 +597,27 @@ future_set_exception(asyncio_state *state, FutureObj *fut, PyObject *exc) PyErr_SetString(PyExc_TypeError, "invalid exception object"); return NULL; } - if (Py_IS_TYPE(exc_val, (PyTypeObject *)PyExc_StopIteration)) { + if (PyErr_GivenExceptionMatches(exc_val, PyExc_StopIteration)) { + const char *msg = "StopIteration interacts badly with " + "generators and cannot be raised into a " + "Future"; + PyObject *message = PyUnicode_FromString(msg); + if (message == NULL) { + Py_DECREF(exc_val); + return NULL; + } + PyObject *err = PyObject_CallOneArg(PyExc_RuntimeError, message); + Py_DECREF(message); + if (err == NULL) { + Py_DECREF(exc_val); + return NULL; + } + assert(PyExceptionInstance_Check(err)); + + PyException_SetCause(err, Py_NewRef(exc_val)); + PyException_SetContext(err, Py_NewRef(exc_val)); Py_DECREF(exc_val); - PyErr_SetString(PyExc_TypeError, - "StopIteration interacts badly with generators " - "and cannot be raised into a Future"); - return NULL; + exc_val = err; } assert(!fut->fut_exception); @@ -815,7 +832,7 @@ FutureObj_clear(FutureObj *fut) Py_CLEAR(fut->fut_source_tb); Py_CLEAR(fut->fut_cancel_msg); Py_CLEAR(fut->fut_cancelled_exc); - _PyObject_ClearManagedDict((PyObject *)fut); + PyObject_ClearManagedDict((PyObject *)fut); return 0; } @@ -833,7 +850,7 @@ FutureObj_traverse(FutureObj *fut, visitproc visit, void *arg) Py_VISIT(fut->fut_source_tb); Py_VISIT(fut->fut_cancel_msg); Py_VISIT(fut->fut_cancelled_exc); - _PyObject_VisitManagedDict((PyObject *)fut, visit, arg); + PyObject_VisitManagedDict((PyObject *)fut, visit, arg); return 0; } @@ -2180,7 +2197,7 @@ TaskObj_traverse(TaskObj *task, visitproc visit, void *arg) Py_VISIT(fut->fut_source_tb); Py_VISIT(fut->fut_cancel_msg); Py_VISIT(fut->fut_cancelled_exc); - _PyObject_VisitManagedDict((PyObject *)fut, visit, arg); + PyObject_VisitManagedDict((PyObject *)fut, visit, arg); return 0; } @@ -2752,7 +2769,6 @@ gen_status_from_result(PyObject **result) static PyObject * task_step_impl(asyncio_state *state, TaskObj *task, PyObject *exc) { - int res; int clear_exc = 0; PyObject *result = NULL; PyObject *coro; @@ -2769,20 +2785,7 @@ task_step_impl(asyncio_state *state, TaskObj *task, PyObject *exc) if (task->task_must_cancel) { assert(exc != Py_None); - if (exc) { - /* Check if exc is a CancelledError */ - res = PyObject_IsInstance(exc, state->asyncio_CancelledError); - if (res == -1) { - /* An error occurred, abort */ - goto fail; - } - if (res == 0) { - /* exc is not CancelledError; reset it to NULL */ - exc = NULL; - } - } - - if (!exc) { + if (!exc || !PyErr_GivenExceptionMatches(exc, state->asyncio_CancelledError)) { /* exc was not a CancelledError */ exc = create_cancelled_error(state, (FutureObj*)task); @@ -3512,15 +3515,11 @@ _asyncio_current_task_impl(PyObject *module, PyObject *loop) Py_INCREF(loop); } - ret = PyDict_GetItemWithError(state->current_tasks, loop); + int rc = PyDict_GetItemRef(state->current_tasks, loop, &ret); Py_DECREF(loop); - if (ret == NULL && PyErr_Occurred()) { - return NULL; - } - else if (ret == NULL) { + if (rc == 0) { Py_RETURN_NONE; } - Py_INCREF(ret); return ret; } diff --git a/Modules/_blake2/blake2b_impl.c b/Modules/_blake2/blake2b_impl.c index c2cac98c7529eb..0c3ae5a2fac275 100644 --- a/Modules/_blake2/blake2b_impl.c +++ b/Modules/_blake2/blake2b_impl.c @@ -17,6 +17,7 @@ # define Py_BUILD_CORE_MODULE 1 #endif +#include #include "Python.h" #include "pycore_strhex.h" // _Py_strhex() @@ -42,7 +43,8 @@ typedef struct { PyObject_HEAD blake2b_param param; blake2b_state state; - PyThread_type_lock lock; + bool use_mutex; + PyMutex mutex; } BLAKE2bObject; #include "clinic/blake2b_impl.c.h" @@ -59,9 +61,11 @@ new_BLAKE2bObject(PyTypeObject *type) { BLAKE2bObject *self; self = (BLAKE2bObject *)type->tp_alloc(type, 0); - if (self != NULL) { - self->lock = NULL; + if (self == NULL) { + return NULL; } + HASHLIB_INIT_MUTEX(self); + return self; } @@ -278,18 +282,19 @@ _blake2_blake2b_update(BLAKE2bObject *self, PyObject *data) GET_BUFFER_VIEW_OR_ERROUT(data, &buf); - if (self->lock == NULL && buf.len >= HASHLIB_GIL_MINSIZE) - self->lock = PyThread_allocate_lock(); - - if (self->lock != NULL) { - Py_BEGIN_ALLOW_THREADS - PyThread_acquire_lock(self->lock, 1); - blake2b_update(&self->state, buf.buf, buf.len); - PyThread_release_lock(self->lock); - Py_END_ALLOW_THREADS + if (!self->use_mutex && buf.len >= HASHLIB_GIL_MINSIZE) { + self->use_mutex = true; + } + if (self->use_mutex) { + Py_BEGIN_ALLOW_THREADS + PyMutex_Lock(&self->mutex); + blake2b_update(&self->state, buf.buf, buf.len); + PyMutex_Unlock(&self->mutex); + Py_END_ALLOW_THREADS } else { blake2b_update(&self->state, buf.buf, buf.len); } + PyBuffer_Release(&buf); Py_RETURN_NONE; @@ -389,10 +394,6 @@ py_blake2b_dealloc(PyObject *self) /* Try not to leave state in memory. */ secure_zero_memory(&obj->param, sizeof(obj->param)); secure_zero_memory(&obj->state, sizeof(obj->state)); - if (obj->lock) { - PyThread_free_lock(obj->lock); - obj->lock = NULL; - } PyTypeObject *type = Py_TYPE(self); PyObject_Free(self); diff --git a/Modules/_blake2/blake2module.c b/Modules/_blake2/blake2module.c index 0d1d88c6603684..5df9fd3df493ee 100644 --- a/Modules/_blake2/blake2module.c +++ b/Modules/_blake2/blake2module.c @@ -74,6 +74,12 @@ _blake2_free(void *module) Py_DECREF(x); \ } while(0) +#define ADD_INT_CONST(NAME, VALUE) do { \ + if (PyModule_AddIntConstant(m, NAME, VALUE) < 0) { \ + return -1; \ + } \ +} while (0) + static int blake2_exec(PyObject *m) { @@ -95,10 +101,10 @@ blake2_exec(PyObject *m) ADD_INT(d, "MAX_KEY_SIZE", BLAKE2B_KEYBYTES); ADD_INT(d, "MAX_DIGEST_SIZE", BLAKE2B_OUTBYTES); - PyModule_AddIntConstant(m, "BLAKE2B_SALT_SIZE", BLAKE2B_SALTBYTES); - PyModule_AddIntConstant(m, "BLAKE2B_PERSON_SIZE", BLAKE2B_PERSONALBYTES); - PyModule_AddIntConstant(m, "BLAKE2B_MAX_KEY_SIZE", BLAKE2B_KEYBYTES); - PyModule_AddIntConstant(m, "BLAKE2B_MAX_DIGEST_SIZE", BLAKE2B_OUTBYTES); + ADD_INT_CONST("BLAKE2B_SALT_SIZE", BLAKE2B_SALTBYTES); + ADD_INT_CONST("BLAKE2B_PERSON_SIZE", BLAKE2B_PERSONALBYTES); + ADD_INT_CONST("BLAKE2B_MAX_KEY_SIZE", BLAKE2B_KEYBYTES); + ADD_INT_CONST("BLAKE2B_MAX_DIGEST_SIZE", BLAKE2B_OUTBYTES); /* BLAKE2s */ st->blake2s_type = (PyTypeObject *)PyType_FromModuleAndSpec( @@ -117,14 +123,17 @@ blake2_exec(PyObject *m) ADD_INT(d, "MAX_KEY_SIZE", BLAKE2S_KEYBYTES); ADD_INT(d, "MAX_DIGEST_SIZE", BLAKE2S_OUTBYTES); - PyModule_AddIntConstant(m, "BLAKE2S_SALT_SIZE", BLAKE2S_SALTBYTES); - PyModule_AddIntConstant(m, "BLAKE2S_PERSON_SIZE", BLAKE2S_PERSONALBYTES); - PyModule_AddIntConstant(m, "BLAKE2S_MAX_KEY_SIZE", BLAKE2S_KEYBYTES); - PyModule_AddIntConstant(m, "BLAKE2S_MAX_DIGEST_SIZE", BLAKE2S_OUTBYTES); + ADD_INT_CONST("BLAKE2S_SALT_SIZE", BLAKE2S_SALTBYTES); + ADD_INT_CONST("BLAKE2S_PERSON_SIZE", BLAKE2S_PERSONALBYTES); + ADD_INT_CONST("BLAKE2S_MAX_KEY_SIZE", BLAKE2S_KEYBYTES); + ADD_INT_CONST("BLAKE2S_MAX_DIGEST_SIZE", BLAKE2S_OUTBYTES); return 0; } +#undef ADD_INT +#undef ADD_INT_CONST + static PyModuleDef_Slot _blake2_slots[] = { {Py_mod_exec, blake2_exec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, diff --git a/Modules/_blake2/blake2s_impl.c b/Modules/_blake2/blake2s_impl.c index 1c47328ece13e8..3014773ab52331 100644 --- a/Modules/_blake2/blake2s_impl.c +++ b/Modules/_blake2/blake2s_impl.c @@ -17,6 +17,7 @@ # define Py_BUILD_CORE_MODULE 1 #endif +#include #include "Python.h" #include "pycore_strhex.h" // _Py_strhex() @@ -42,7 +43,8 @@ typedef struct { PyObject_HEAD blake2s_param param; blake2s_state state; - PyThread_type_lock lock; + bool use_mutex; + PyMutex mutex; } BLAKE2sObject; #include "clinic/blake2s_impl.c.h" @@ -59,9 +61,11 @@ new_BLAKE2sObject(PyTypeObject *type) { BLAKE2sObject *self; self = (BLAKE2sObject *)type->tp_alloc(type, 0); - if (self != NULL) { - self->lock = NULL; + if (self == NULL) { + return NULL; } + HASHLIB_INIT_MUTEX(self); + return self; } @@ -278,18 +282,19 @@ _blake2_blake2s_update(BLAKE2sObject *self, PyObject *data) GET_BUFFER_VIEW_OR_ERROUT(data, &buf); - if (self->lock == NULL && buf.len >= HASHLIB_GIL_MINSIZE) - self->lock = PyThread_allocate_lock(); - - if (self->lock != NULL) { - Py_BEGIN_ALLOW_THREADS - PyThread_acquire_lock(self->lock, 1); - blake2s_update(&self->state, buf.buf, buf.len); - PyThread_release_lock(self->lock); - Py_END_ALLOW_THREADS + if (!self->use_mutex && buf.len >= HASHLIB_GIL_MINSIZE) { + self->use_mutex = true; + } + if (self->use_mutex) { + Py_BEGIN_ALLOW_THREADS + PyMutex_Lock(&self->mutex); + blake2s_update(&self->state, buf.buf, buf.len); + PyMutex_Unlock(&self->mutex); + Py_END_ALLOW_THREADS } else { blake2s_update(&self->state, buf.buf, buf.len); } + PyBuffer_Release(&buf); Py_RETURN_NONE; @@ -389,10 +394,6 @@ py_blake2s_dealloc(PyObject *self) /* Try not to leave state in memory. */ secure_zero_memory(&obj->param, sizeof(obj->param)); secure_zero_memory(&obj->state, sizeof(obj->state)); - if (obj->lock) { - PyThread_free_lock(obj->lock); - obj->lock = NULL; - } PyTypeObject *type = Py_TYPE(self); PyObject_Free(self); diff --git a/Modules/_blake2/clinic/blake2b_impl.c.h b/Modules/_blake2/clinic/blake2b_impl.c.h index 99b0f098cc2b27..47d62717eb76e7 100644 --- a/Modules/_blake2/clinic/blake2b_impl.c.h +++ b/Modules/_blake2/clinic/blake2b_impl.c.h @@ -3,10 +3,11 @@ 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() +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() #endif - +#include "pycore_long.h" // _PyLong_UnsignedLong_Converter() +#include "pycore_modsupport.h" // _PyArg_UnpackKeywords() PyDoc_STRVAR(py_blake2b_new__doc__, "blake2b(data=b\'\', /, *, digest_size=_blake2.blake2b.MAX_DIGEST_SIZE,\n" @@ -85,7 +86,7 @@ py_blake2b_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) goto skip_optional_kwonly; } if (fastargs[1]) { - digest_size = _PyLong_AsInt(fastargs[1]); + digest_size = PyLong_AsInt(fastargs[1]); if (digest_size == -1 && PyErr_Occurred()) { goto exit; } @@ -97,10 +98,6 @@ py_blake2b_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) if (PyObject_GetBuffer(fastargs[2], &key, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&key, 'C')) { - _PyArg_BadArgument("blake2b", "argument 'key'", "contiguous buffer", fastargs[2]); - goto exit; - } if (!--noptargs) { goto skip_optional_kwonly; } @@ -109,10 +106,6 @@ py_blake2b_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) if (PyObject_GetBuffer(fastargs[3], &salt, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&salt, 'C')) { - _PyArg_BadArgument("blake2b", "argument 'salt'", "contiguous buffer", fastargs[3]); - goto exit; - } if (!--noptargs) { goto skip_optional_kwonly; } @@ -121,16 +114,12 @@ py_blake2b_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) if (PyObject_GetBuffer(fastargs[4], &person, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&person, 'C')) { - _PyArg_BadArgument("blake2b", "argument 'person'", "contiguous buffer", fastargs[4]); - goto exit; - } if (!--noptargs) { goto skip_optional_kwonly; } } if (fastargs[5]) { - fanout = _PyLong_AsInt(fastargs[5]); + fanout = PyLong_AsInt(fastargs[5]); if (fanout == -1 && PyErr_Occurred()) { goto exit; } @@ -139,7 +128,7 @@ py_blake2b_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) } } if (fastargs[6]) { - depth = _PyLong_AsInt(fastargs[6]); + depth = PyLong_AsInt(fastargs[6]); if (depth == -1 && PyErr_Occurred()) { goto exit; } @@ -164,7 +153,7 @@ py_blake2b_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) } } if (fastargs[9]) { - node_depth = _PyLong_AsInt(fastargs[9]); + node_depth = PyLong_AsInt(fastargs[9]); if (node_depth == -1 && PyErr_Occurred()) { goto exit; } @@ -173,7 +162,7 @@ py_blake2b_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) } } if (fastargs[10]) { - inner_size = _PyLong_AsInt(fastargs[10]); + inner_size = PyLong_AsInt(fastargs[10]); if (inner_size == -1 && PyErr_Occurred()) { goto exit; } @@ -276,4 +265,4 @@ _blake2_blake2b_hexdigest(BLAKE2bObject *self, PyObject *Py_UNUSED(ignored)) { return _blake2_blake2b_hexdigest_impl(self); } -/*[clinic end generated code: output=996b4fe396824797 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=e18eeaee40623bfc input=a9049054013a1b77]*/ diff --git a/Modules/_blake2/clinic/blake2s_impl.c.h b/Modules/_blake2/clinic/blake2s_impl.c.h index 9b821fbcd62cdb..7a0f6eeff5b5b5 100644 --- a/Modules/_blake2/clinic/blake2s_impl.c.h +++ b/Modules/_blake2/clinic/blake2s_impl.c.h @@ -3,10 +3,11 @@ 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() +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() #endif - +#include "pycore_long.h" // _PyLong_UnsignedLong_Converter() +#include "pycore_modsupport.h" // _PyArg_UnpackKeywords() PyDoc_STRVAR(py_blake2s_new__doc__, "blake2s(data=b\'\', /, *, digest_size=_blake2.blake2s.MAX_DIGEST_SIZE,\n" @@ -85,7 +86,7 @@ py_blake2s_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) goto skip_optional_kwonly; } if (fastargs[1]) { - digest_size = _PyLong_AsInt(fastargs[1]); + digest_size = PyLong_AsInt(fastargs[1]); if (digest_size == -1 && PyErr_Occurred()) { goto exit; } @@ -97,10 +98,6 @@ py_blake2s_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) if (PyObject_GetBuffer(fastargs[2], &key, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&key, 'C')) { - _PyArg_BadArgument("blake2s", "argument 'key'", "contiguous buffer", fastargs[2]); - goto exit; - } if (!--noptargs) { goto skip_optional_kwonly; } @@ -109,10 +106,6 @@ py_blake2s_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) if (PyObject_GetBuffer(fastargs[3], &salt, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&salt, 'C')) { - _PyArg_BadArgument("blake2s", "argument 'salt'", "contiguous buffer", fastargs[3]); - goto exit; - } if (!--noptargs) { goto skip_optional_kwonly; } @@ -121,16 +114,12 @@ py_blake2s_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) if (PyObject_GetBuffer(fastargs[4], &person, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&person, 'C')) { - _PyArg_BadArgument("blake2s", "argument 'person'", "contiguous buffer", fastargs[4]); - goto exit; - } if (!--noptargs) { goto skip_optional_kwonly; } } if (fastargs[5]) { - fanout = _PyLong_AsInt(fastargs[5]); + fanout = PyLong_AsInt(fastargs[5]); if (fanout == -1 && PyErr_Occurred()) { goto exit; } @@ -139,7 +128,7 @@ py_blake2s_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) } } if (fastargs[6]) { - depth = _PyLong_AsInt(fastargs[6]); + depth = PyLong_AsInt(fastargs[6]); if (depth == -1 && PyErr_Occurred()) { goto exit; } @@ -164,7 +153,7 @@ py_blake2s_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) } } if (fastargs[9]) { - node_depth = _PyLong_AsInt(fastargs[9]); + node_depth = PyLong_AsInt(fastargs[9]); if (node_depth == -1 && PyErr_Occurred()) { goto exit; } @@ -173,7 +162,7 @@ py_blake2s_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) } } if (fastargs[10]) { - inner_size = _PyLong_AsInt(fastargs[10]); + inner_size = PyLong_AsInt(fastargs[10]); if (inner_size == -1 && PyErr_Occurred()) { goto exit; } @@ -276,4 +265,4 @@ _blake2_blake2s_hexdigest(BLAKE2sObject *self, PyObject *Py_UNUSED(ignored)) { return _blake2_blake2s_hexdigest_impl(self); } -/*[clinic end generated code: output=bd0fb7639e450618 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=24690e4e2586cafd input=a9049054013a1b77]*/ diff --git a/Modules/_bz2module.c b/Modules/_bz2module.c index 0a84f25ca4cbe7..3d0d4ee5e79c2b 100644 --- a/Modules/_bz2module.c +++ b/Modules/_bz2module.c @@ -1,5 +1,9 @@ /* _bz2 - Low-level Python interface to libbzip2. */ +#ifndef Py_BUILD_CORE_BUILTIN +# define Py_BUILD_CORE_MODULE 1 +#endif + #include "Python.h" #include diff --git a/Modules/_collectionsmodule.c b/Modules/_collectionsmodule.c index f2915f83b9d968..c8cd53de5e2262 100644 --- a/Modules/_collectionsmodule.c +++ b/Modules/_collectionsmodule.c @@ -1,5 +1,6 @@ #include "Python.h" #include "pycore_call.h" // _PyObject_CallNoArgs() +#include "pycore_dict.h" // _PyDict_GetItem_KnownHash() #include "pycore_long.h" // _PyLong_GetZero() #include "pycore_moduleobject.h" // _PyModule_GetState() #include "pycore_typeobject.h" // _PyType_GetModuleState() diff --git a/Modules/_csv.c b/Modules/_csv.c index 24a57e362521db..d45a15aa8c255a 100644 --- a/Modules/_csv.c +++ b/Modules/_csv.c @@ -10,6 +10,11 @@ module instead. #define MODULE_VERSION "1.0" +// clinic/_csv.c.h uses internal pycore_modsupport.h API +#ifndef Py_BUILD_CORE_BUILTIN +# define Py_BUILD_CORE_MODULE 1 +#endif + #include "Python.h" #include // offsetof() @@ -155,15 +160,9 @@ static PyObject * get_dialect_from_registry(PyObject *name_obj, _csvstate *module_state) { PyObject *dialect_obj; - - dialect_obj = PyDict_GetItemWithError(module_state->dialects, name_obj); - if (dialect_obj == NULL) { - if (!PyErr_Occurred()) - PyErr_Format(module_state->error_obj, "unknown dialect"); + if (PyDict_GetItemRef(module_state->dialects, name_obj, &dialect_obj) == 0) { + PyErr_SetString(module_state->error_obj, "unknown dialect"); } - else - Py_INCREF(dialect_obj); - return dialect_obj; } @@ -233,7 +232,7 @@ _set_int(const char *name, int *target, PyObject *src, int dflt) "\"%s\" must be an integer", name); return -1; } - value = _PyLong_AsInt(src); + value = PyLong_AsInt(src); if (value == -1 && PyErr_Occurred()) { return -1; } @@ -838,7 +837,8 @@ parse_process_char(ReaderObj *self, _csvstate *module_state, Py_UCS4 c) self->state = START_RECORD; else { PyErr_Format(module_state->error_obj, - "new-line character seen in unquoted field - do you need to open the file in universal-newline mode?"); + "new-line character seen in unquoted field - " + "do you need to open the file with newline=''?"); return -1; } break; diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index 9aee37a9d954ef..fc16b9176fd1c0 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -110,6 +110,9 @@ bytes(cdata) #include "pycore_call.h" // _PyObject_CallNoArgs() #include "pycore_ceval.h" // _Py_EnterRecursiveCall() +#ifdef MS_WIN32 +# include "pycore_modsupport.h" // _PyArg_NoKeywords() +#endif #include @@ -181,7 +184,7 @@ _DictRemover_call(PyObject *myself, PyObject *args, PyObject *kw) DictRemoverObject *self = (DictRemoverObject *)myself; if (self->key && self->dict) { if (-1 == PyDict_DelItem(self->dict, self->key)) { - _PyErr_WriteUnraisableMsg("on calling _ctypes.DictRemover", NULL); + PyErr_FormatUnraisable("Exception ignored on calling _ctypes.DictRemover"); } Py_CLEAR(self->key); Py_CLEAR(self->dict); @@ -240,26 +243,13 @@ PyDict_SetItemProxy(PyObject *dict, PyObject *key, PyObject *item) static int _PyDict_GetItemProxy(PyObject *dict, PyObject *key, PyObject **presult) { - PyObject *item = PyDict_GetItemWithError(dict, key); - if (item == NULL) { - if (PyErr_Occurred()) { - return -1; - } - *presult = NULL; - return 0; - } - - if (!PyWeakref_CheckProxy(item)) { - *presult = Py_NewRef(item); - return 0; + int rc = PyDict_GetItemRef(dict, key, presult); + PyObject *item = *presult; + if (item && PyWeakref_CheckProxy(item)) { + rc = PyWeakref_GetRef(item, presult); + Py_DECREF(item); } - PyObject *ref; - if (PyWeakref_GetRef(item, &ref) < 0) { - return -1; - } - // ref is NULL if the referenced object was destroyed - *presult = ref; - return 0; + return rc; } /******************************************************************/ @@ -562,18 +552,19 @@ StructUnionType_new(PyTypeObject *type, PyObject *args, PyObject *kwds, int isSt dict->paramfunc = StructUnionType_paramfunc; - fields = PyDict_GetItemWithError((PyObject *)dict, &_Py_ID(_fields_)); + if (PyDict_GetItemRef((PyObject *)dict, &_Py_ID(_fields_), &fields) < 0) { + Py_DECREF(result); + return NULL; + } if (fields) { if (PyObject_SetAttr((PyObject *)result, &_Py_ID(_fields_), fields) < 0) { Py_DECREF(result); + Py_DECREF(fields); return NULL; } + Py_DECREF(fields); return (PyObject *)result; } - else if (PyErr_Occurred()) { - Py_DECREF(result); - return NULL; - } else { StgDictObject *basedict = PyType_stgdict((PyObject *)result->tp_base); @@ -1107,11 +1098,15 @@ PyCPointerType_new(PyTypeObject *type, PyObject *args, PyObject *kwds) stgdict->paramfunc = PyCPointerType_paramfunc; stgdict->flags |= TYPEFLAG_ISPOINTER; - proto = PyDict_GetItemWithError(typedict, &_Py_ID(_type_)); /* Borrowed ref */ + if (PyDict_GetItemRef(typedict, &_Py_ID(_type_), &proto) < 0) { + Py_DECREF((PyObject *)stgdict); + return NULL; + } if (proto) { StgDictObject *itemdict; const char *current_format; if (-1 == PyCPointerType_SetProto(stgdict, proto)) { + Py_DECREF(proto); Py_DECREF((PyObject *)stgdict); return NULL; } @@ -1131,15 +1126,12 @@ PyCPointerType_new(PyTypeObject *type, PyObject *args, PyObject *kwds) } else { stgdict->format = _ctypes_alloc_format_string("&", current_format); } + Py_DECREF(proto); if (stgdict->format == NULL) { Py_DECREF((PyObject *)stgdict); return NULL; } } - else if (PyErr_Occurred()) { - Py_DECREF((PyObject *)stgdict); - return NULL; - } /* create the new instance (which is a class, since we are a metatype!) */ @@ -2458,58 +2450,61 @@ make_funcptrtype_dict(StgDictObject *stgdict) stgdict->getfunc = NULL; stgdict->ffi_type_pointer = ffi_type_pointer; - ob = PyDict_GetItemWithError((PyObject *)stgdict, &_Py_ID(_flags_)); + if (PyDict_GetItemRef((PyObject *)stgdict, &_Py_ID(_flags_), &ob) < 0) { + return -1; + } if (!ob || !PyLong_Check(ob)) { - if (!PyErr_Occurred()) { - PyErr_SetString(PyExc_TypeError, + PyErr_SetString(PyExc_TypeError, "class must define _flags_ which must be an integer"); - } + Py_XDECREF(ob); return -1; } stgdict->flags = PyLong_AsUnsignedLongMask(ob) | TYPEFLAG_ISPOINTER; + Py_DECREF(ob); /* _argtypes_ is optional... */ - ob = PyDict_GetItemWithError((PyObject *)stgdict, &_Py_ID(_argtypes_)); + if (PyDict_GetItemRef((PyObject *)stgdict, &_Py_ID(_argtypes_), &ob) < 0) { + return -1; + } if (ob) { converters = converters_from_argtypes(ob); - if (!converters) + if (!converters) { + Py_DECREF(ob); return -1; - stgdict->argtypes = Py_NewRef(ob); + } + stgdict->argtypes = ob; stgdict->converters = converters; } - else if (PyErr_Occurred()) { + + if (PyDict_GetItemRef((PyObject *)stgdict, &_Py_ID(_restype_), &ob) < 0) { return -1; } - - ob = PyDict_GetItemWithError((PyObject *)stgdict, &_Py_ID(_restype_)); if (ob) { if (ob != Py_None && !PyType_stgdict(ob) && !PyCallable_Check(ob)) { PyErr_SetString(PyExc_TypeError, "_restype_ must be a type, a callable, or None"); + Py_DECREF(ob); return -1; } - stgdict->restype = Py_NewRef(ob); + stgdict->restype = ob; if (PyObject_GetOptionalAttr(ob, &_Py_ID(_check_retval_), &stgdict->checker) < 0) { return -1; } } - else if (PyErr_Occurred()) { +/* XXX later, maybe. + if (PyDict_GetItemRef((PyObject *)stgdict, &_Py _ID(_errcheck_), &ob) < 0) { return -1; } -/* XXX later, maybe. - ob = _PyDict_GetItemIdWithError((PyObject *)stgdict, &PyId__errcheck_); if (ob) { if (!PyCallable_Check(ob)) { PyErr_SetString(PyExc_TypeError, "_errcheck_ must be callable"); + Py_DECREF(ob); return -1; } - stgdict->errcheck = Py_NewRef(ob); - } - else if (PyErr_Occurred()) { - return -1; + stgdict->errcheck = ob; } */ return 0; @@ -3809,13 +3804,12 @@ _get_arg(int *pindex, PyObject *name, PyObject *defval, PyObject *inargs, PyObje return Py_NewRef(v); } if (kwds && name) { - v = PyDict_GetItemWithError(kwds, name); + if (PyDict_GetItemRef(kwds, name, &v) < 0) { + return NULL; + } if (v) { ++*pindex; - return Py_NewRef(v); - } - else if (PyErr_Occurred()) { - return NULL; + return v; } } if (defval) { @@ -4360,10 +4354,10 @@ _init_pos_args(PyObject *self, PyTypeObject *type, return index; } - for (i = 0; - i < dict->length && (i+index) < PyTuple_GET_SIZE(args); + for (i = index; + i < dict->length && i < PyTuple_GET_SIZE(args); ++i) { - PyObject *pair = PySequence_GetItem(fields, i); + PyObject *pair = PySequence_GetItem(fields, i - index); PyObject *name, *val; int res; if (!pair) @@ -4373,7 +4367,7 @@ _init_pos_args(PyObject *self, PyTypeObject *type, Py_DECREF(pair); return -1; } - val = PyTuple_GET_ITEM(args, i + index); + val = PyTuple_GET_ITEM(args, i); if (kwds) { res = PyDict_Contains(kwds, name); if (res != 0) { @@ -4394,7 +4388,7 @@ _init_pos_args(PyObject *self, PyTypeObject *type, if (res == -1) return -1; } - return index + dict->length; + return dict->length; } static int @@ -4793,6 +4787,16 @@ static PyMappingMethods Array_as_mapping = { Array_ass_subscript, }; +PyDoc_STRVAR(array_doc, +"Abstract base class for arrays.\n" +"\n" +"The recommended way to create concrete array types is by multiplying any\n" +"ctypes data type with a non-negative integer. Alternatively, you can subclass\n" +"this type and define _length_ and _type_ class variables. Array elements can\n" +"be read and written using standard subscript and slice accesses for slice\n" +"reads, the resulting object is not itself an Array." +); + PyTypeObject PyCArray_Type = { PyVarObject_HEAD_INIT(NULL, 0) "_ctypes.Array", @@ -4813,8 +4817,8 @@ PyTypeObject PyCArray_Type = { 0, /* tp_getattro */ 0, /* tp_setattro */ &PyCData_as_buffer, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ - PyDoc_STR("XXX to be provided"), /* tp_doc */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + array_doc, /* tp_doc */ (traverseproc)PyCData_traverse, /* tp_traverse */ (inquiry)PyCData_clear, /* tp_clear */ 0, /* tp_richcompare */ @@ -4857,15 +4861,12 @@ PyCArrayType_from_ctype(PyObject *itemtype, Py_ssize_t length) return NULL; PyObject *result; - if (_PyDict_GetItemProxy(cache, key, &result) < 0) { - Py_DECREF(key); - return NULL; - } - if (result) { + if (_PyDict_GetItemProxy(cache, key, &result) != 0) { + // found or error Py_DECREF(key); return result; } - + // not found if (!PyType_Check(itemtype)) { PyErr_SetString(PyExc_TypeError, "Expected a type object"); @@ -5129,8 +5130,6 @@ static PyObject * Pointer_get_contents(CDataObject *self, void *closure) { StgDictObject *stgdict; - PyObject *keep, *ptr_probe; - CDataObject *ptr2ptr; if (*(void **)self->b_ptr == NULL) { PyErr_SetString(PyExc_ValueError, @@ -5140,33 +5139,6 @@ Pointer_get_contents(CDataObject *self, void *closure) stgdict = PyObject_stgdict((PyObject *)self); assert(stgdict); /* Cannot be NULL for pointer instances */ - - keep = GetKeepedObjects(self); - if (keep != NULL) { - // check if it's a pointer to a pointer: - // pointers will have '0' key in the _objects - ptr_probe = PyDict_GetItemString(keep, "0"); - - if (ptr_probe != NULL) { - ptr2ptr = (CDataObject*) PyDict_GetItemString(keep, "1"); - if (ptr2ptr == NULL) { - PyErr_SetString(PyExc_ValueError, - "Unexpected NULL pointer in _objects"); - return NULL; - } - // don't construct a new object, - // return existing one instead to preserve refcount - assert( - *(void**) self->b_ptr == ptr2ptr->b_ptr || - *(void**) self->b_value.c == ptr2ptr->b_ptr || - *(void**) self->b_ptr == ptr2ptr->b_value.c || - *(void**) self->b_value.c == ptr2ptr->b_value.c - ); // double-check that we are returning the same thing - Py_INCREF(ptr2ptr); - return (PyObject *) ptr2ptr; - } - } - return PyCData_FromBaseObj(stgdict->proto, (PyObject *)self, 0, *(void **)self->b_ptr); diff --git a/Modules/_ctypes/_ctypes_test.c b/Modules/_ctypes/_ctypes_test.c index ddfb2c8a332a9e..ecc60417790417 100644 --- a/Modules/_ctypes/_ctypes_test.c +++ b/Modules/_ctypes/_ctypes_test.c @@ -1,10 +1,25 @@ -#include +#include "pyconfig.h" // Py_GIL_DISABLED -#ifdef MS_WIN32 -#include +#ifndef Py_GIL_DISABLED +// Need limited C API version 3.12 for Py_MOD_PER_INTERPRETER_GIL_SUPPORTED +#define Py_LIMITED_API 0x030c0000 #endif +// gh-85283: On Windows, Py_LIMITED_API requires Py_BUILD_CORE to not attempt +// linking the extension to python3.lib (which fails). Py_BUILD_CORE_MODULE is +// needed to import Python symbols. Then Python.h undefines Py_BUILD_CORE and +// Py_BUILD_CORE_MODULE if Py_LIMITED_API is defined. +#define Py_BUILD_CORE +#define Py_BUILD_CORE_MODULE + +#include + +#include // printf() #include // qsort() +#include // memset() +#ifdef MS_WIN32 +# include +#endif #define EXPORT(x) Py_EXPORTED_SYMBOL x @@ -81,11 +96,10 @@ typedef struct { } Test2; EXPORT(int) -_testfunc_array_in_struct1(Test2 in) +_testfunc_array_in_struct2(Test2 in) { int result = 0; - - for (unsigned i = 0; i < 16; i++) + for (unsigned i = 0; i < sizeof(in.data)/sizeof(in.data[0]); i++) result += in.data[i]; /* As the structure is passed by value, changes to it shouldn't be * reflected in the caller. @@ -94,22 +108,25 @@ _testfunc_array_in_struct1(Test2 in) return result; } -typedef struct { - double data[2]; -} Test3; - +/* + * Test3A struct test the MAX_STRUCT_SIZE 16 with single precision floats. + * These structs should be passed via registers on all platforms and they are + * used for within bounds tests. + */ typedef struct { float data[2]; float more_data[2]; -} Test3B; +} Test3A; EXPORT(double) -_testfunc_array_in_struct2(Test3 in) +_testfunc_array_in_struct3A(Test3A in) { double result = 0; - for (unsigned i = 0; i < 2; i++) + for (unsigned i = 0; i < sizeof(in.data)/sizeof(in.data[0]); i++) result += in.data[i]; + for (unsigned i = 0; i < sizeof(in.more_data)/sizeof(in.more_data[0]); i++) + result += in.more_data[i]; /* As the structure is passed by value, changes to it shouldn't be * reflected in the caller. */ @@ -117,20 +134,116 @@ _testfunc_array_in_struct2(Test3 in) return result; } +/* The structs Test3B..Test3E use the same functions hence using the MACRO + * to define their implementation. + */ + +#define _TESTFUNC_ARRAY_IN_STRUCT_IMPL \ + double result = 0; \ + \ + for (unsigned i = 0; i < sizeof(in.data)/sizeof(in.data[0]); i++) \ + result += in.data[i]; \ + /* As the structure is passed by value, changes to it shouldn't be \ + * reflected in the caller. \ + */ \ + memset(in.data, 0, sizeof(in.data)); \ + return result; \ + +#define _TESTFUNC_ARRAY_IN_STRUCT_SET_DEFAULTS_IMPL \ + for (unsigned i = 0; i < sizeof(s.data)/sizeof(s.data[0]); i++) \ + s.data[i] = (double)i+1; \ + return s; \ + + +/* + * Test3B struct test the MAX_STRUCT_SIZE 16 with double precision floats. + * These structs should be passed via registers on all platforms and they are + * used for within bounds tests. + */ +typedef struct { + double data[2]; +} Test3B; + EXPORT(double) -_testfunc_array_in_struct2a(Test3B in) +_testfunc_array_in_struct3B(Test3B in) { - double result = 0; + _TESTFUNC_ARRAY_IN_STRUCT_IMPL +} - for (unsigned i = 0; i < 2; i++) - result += in.data[i]; - for (unsigned i = 0; i < 2; i++) - result += in.more_data[i]; - /* As the structure is passed by value, changes to it shouldn't be - * reflected in the caller. - */ - memset(in.data, 0, sizeof(in.data)); - return result; +EXPORT(Test3B) +_testfunc_array_in_struct3B_set_defaults(void) +{ + Test3B s; + _TESTFUNC_ARRAY_IN_STRUCT_SET_DEFAULTS_IMPL +} + +/* + * Test3C struct tests the MAX_STRUCT_SIZE 32. Structs containing arrays of up + * to four floating point types are passed in registers on Arm platforms. + * This struct is used for within bounds test on Arm platfroms and for an + * out-of-bounds tests for platfroms where MAX_STRUCT_SIZE is less than 32. + * See gh-110190. + */ +typedef struct { + double data[4]; +} Test3C; + +EXPORT(double) +_testfunc_array_in_struct3C(Test3C in) +{ + _TESTFUNC_ARRAY_IN_STRUCT_IMPL +} + +EXPORT(Test3C) +_testfunc_array_in_struct3C_set_defaults(void) +{ + Test3C s; + _TESTFUNC_ARRAY_IN_STRUCT_SET_DEFAULTS_IMPL +} + +/* + * Test3D struct tests the MAX_STRUCT_SIZE 64. Structs containing arrays of up + * to eight floating point types are passed in registers on PPC64LE platforms. + * This struct is used for within bounds test on PPC64LE platfroms and for an + * out-of-bounds tests for platfroms where MAX_STRUCT_SIZE is less than 64. + * See gh-110190. + */ +typedef struct { + double data[8]; +} Test3D; + +EXPORT(double) +_testfunc_array_in_struct3D(Test3D in) +{ + _TESTFUNC_ARRAY_IN_STRUCT_IMPL +} + +EXPORT(Test3D) +_testfunc_array_in_struct3D_set_defaults(void) +{ + Test3D s; + _TESTFUNC_ARRAY_IN_STRUCT_SET_DEFAULTS_IMPL +} + +/* + * Test3E struct tests the out-of-bounds for all architectures. + * See gh-110190. + */ +typedef struct { + double data[9]; +} Test3E; + +EXPORT(double) +_testfunc_array_in_struct3E(Test3E in) +{ + _TESTFUNC_ARRAY_IN_STRUCT_IMPL +} + +EXPORT(Test3E) +_testfunc_array_in_struct3E_set_defaults(void) +{ + Test3E s; + _TESTFUNC_ARRAY_IN_STRUCT_SET_DEFAULTS_IMPL } typedef union { diff --git a/Modules/_ctypes/callbacks.c b/Modules/_ctypes/callbacks.c index 0d8ecce009a67a..154e9f43983cdb 100644 --- a/Modules/_ctypes/callbacks.c +++ b/Modules/_ctypes/callbacks.c @@ -8,9 +8,8 @@ # include #endif -#include "pycore_call.h" // _PyObject_CallNoArgs() -#include "pycore_runtime.h" // _PyRuntime -#include "pycore_global_objects.h" // _Py_ID() +#include "pycore_call.h" // _PyObject_CallNoArgs() +#include "pycore_runtime.h" // _Py_ID() #include @@ -216,8 +215,9 @@ static void _CallPythonObject(void *mem, result = PyObject_Vectorcall(callable, args, nargs, NULL); if (result == NULL) { - _PyErr_WriteUnraisableMsg("on calling ctypes callback function", - callable); + PyErr_FormatUnraisable( + "Exception ignored on calling ctypes callback function %R", + callable); } #ifdef MS_WIN32 @@ -258,9 +258,10 @@ static void _CallPythonObject(void *mem, if (keep == NULL) { /* Could not convert callback result. */ - _PyErr_WriteUnraisableMsg("on converting result " - "of ctypes callback function", - callable); + PyErr_FormatUnraisable( + "Exception ignored on converting result " + "of ctypes callback function %R", + callable); } else if (setfunc != _ctypes_get_fielddesc("O")->setfunc) { if (keep == Py_None) { @@ -270,9 +271,10 @@ static void _CallPythonObject(void *mem, else if (PyErr_WarnEx(PyExc_RuntimeWarning, "memory leak in callback function.", 1) == -1) { - _PyErr_WriteUnraisableMsg("on converting result " - "of ctypes callback function", - callable); + PyErr_FormatUnraisable( + "Exception ignored on converting result " + "of ctypes callback function %R", + callable); } } } diff --git a/Modules/_ctypes/callproc.c b/Modules/_ctypes/callproc.c index 69cf8a98af6636..3b11cd7f58ce4b 100644 --- a/Modules/_ctypes/callproc.c +++ b/Modules/_ctypes/callproc.c @@ -54,6 +54,11 @@ */ +/*[clinic input] +module _ctypes +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=476a19c49b31a75c]*/ + #ifndef Py_BUILD_CORE_BUILTIN # define Py_BUILD_CORE_MODULE 1 #endif @@ -96,8 +101,11 @@ #define DONT_USE_SEH #endif -#include "pycore_runtime.h" // _PyRuntime -#include "pycore_global_objects.h" // _Py_ID() +#include "pycore_runtime.h" // _PyRuntime +#include "pycore_global_objects.h"// _Py_ID() +#include "pycore_traceback.h" // _PyTraceback_Add() + +#include "clinic/callproc.c.h" #define CTYPES_CAPSULE_NAME_PYMEM "_ctypes pymem" @@ -160,16 +168,18 @@ _ctypes_get_errobj(int **pspace) if (error_object_name == NULL) return NULL; } - errobj = PyDict_GetItemWithError(dict, error_object_name); + if (PyDict_GetItemRef(dict, error_object_name, &errobj) < 0) { + return NULL; + } if (errobj) { if (!PyCapsule_IsValid(errobj, CTYPES_CAPSULE_NAME_PYMEM)) { PyErr_SetString(PyExc_RuntimeError, "ctypes.error_object is an invalid capsule"); + Py_DECREF(errobj); return NULL; } - Py_INCREF(errobj); } - else if (!PyErr_Occurred()) { + else { void *space = PyMem_Calloc(2, sizeof(int)); if (space == NULL) return NULL; @@ -184,9 +194,6 @@ _ctypes_get_errobj(int **pspace) return NULL; } } - else { - return NULL; - } *pspace = (int *)PyCapsule_GetPointer(errobj, CTYPES_CAPSULE_NAME_PYMEM); return errobj; } @@ -1397,7 +1404,7 @@ static PyObject *load_library(PyObject *self, PyObject *args) #ifdef _WIN64 return PyLong_FromVoidPtr(hMod); #else - return Py_BuildValue("i", hMod); + return PyLong_FromLong((int)hMod); #endif } @@ -1893,20 +1900,32 @@ unpickle(PyObject *self, PyObject *args) return NULL; } +/*[clinic input] +_ctypes.POINTER as create_pointer_type + + type as cls: object + A ctypes type. + / + +Create and return a new ctypes pointer type. + +Pointer types are cached and reused internally, +so calling this function repeatedly is cheap. +[clinic start generated code]*/ + static PyObject * -POINTER(PyObject *self, PyObject *cls) +create_pointer_type(PyObject *module, PyObject *cls) +/*[clinic end generated code: output=98c3547ab6f4f40b input=3b81cff5ff9b9d5b]*/ { PyObject *result; PyTypeObject *typ; PyObject *key; - result = PyDict_GetItemWithError(_ctypes_ptrtype_cache, cls); - if (result) { - return Py_NewRef(result); - } - else if (PyErr_Occurred()) { - return NULL; + if (PyDict_GetItemRef(_ctypes_ptrtype_cache, cls, &result) != 0) { + // found or error + return result; } + // not found if (PyUnicode_CheckExact(cls)) { PyObject *name = PyUnicode_FromFormat("LP_%U", cls); result = PyObject_CallFunction((PyObject *)Py_TYPE(&PyCPointer_Type), @@ -1944,22 +1963,34 @@ POINTER(PyObject *self, PyObject *cls) return result; } +/*[clinic input] +_ctypes.pointer as create_pointer_inst + + obj as arg: object + / + +Create a new pointer instance, pointing to 'obj'. + +The returned object is of the type POINTER(type(obj)). Note that if you +just want to pass a pointer to an object to a foreign function call, you +should use byref(obj) which is much faster. +[clinic start generated code]*/ + static PyObject * -pointer(PyObject *self, PyObject *arg) +create_pointer_inst(PyObject *module, PyObject *arg) +/*[clinic end generated code: output=3b543bc9f0de2180 input=713685fdb4d9bc27]*/ { PyObject *result; PyObject *typ; - typ = PyDict_GetItemWithError(_ctypes_ptrtype_cache, (PyObject *)Py_TYPE(arg)); - if (typ) { - return PyObject_CallOneArg(typ, arg); - } - else if (PyErr_Occurred()) { + if (PyDict_GetItemRef(_ctypes_ptrtype_cache, (PyObject *)Py_TYPE(arg), &typ) < 0) { return NULL; } - typ = POINTER(NULL, (PyObject *)Py_TYPE(arg)); - if (typ == NULL) - return NULL; + if (typ == NULL) { + typ = create_pointer_type(NULL, (PyObject *)Py_TYPE(arg)); + if (typ == NULL) + return NULL; + } result = PyObject_CallOneArg(typ, arg); Py_DECREF(typ); return result; @@ -1997,8 +2028,8 @@ buffer_info(PyObject *self, PyObject *arg) PyMethodDef _ctypes_module_methods[] = { {"get_errno", get_errno, METH_NOARGS}, {"set_errno", set_errno, METH_VARARGS}, - {"POINTER", POINTER, METH_O }, - {"pointer", pointer, METH_O }, + CREATE_POINTER_TYPE_METHODDEF + CREATE_POINTER_INST_METHODDEF {"_unpickle", unpickle, METH_VARARGS }, {"buffer_info", buffer_info, METH_O, "Return buffer interface information"}, {"resize", resize, METH_VARARGS, "Resize the memory buffer of a ctypes instance"}, diff --git a/Modules/_ctypes/cfield.c b/Modules/_ctypes/cfield.c index 128506a9eed920..bfb40e5c5393fc 100644 --- a/Modules/_ctypes/cfield.c +++ b/Modules/_ctypes/cfield.c @@ -250,8 +250,8 @@ PyCField_get_size(PyObject *self, void *data) } static PyGetSetDef PyCField_getset[] = { - { "offset", PyCField_get_offset, NULL, "offset in bytes of this field" }, - { "size", PyCField_get_size, NULL, "size in bytes of this field" }, + { "offset", PyCField_get_offset, NULL, PyDoc_STR("offset in bytes of this field") }, + { "size", PyCField_get_size, NULL, PyDoc_STR("size in bytes of this field") }, { NULL, NULL, NULL, NULL }, }; diff --git a/Modules/_ctypes/clinic/callproc.c.h b/Modules/_ctypes/clinic/callproc.c.h new file mode 100644 index 00000000000000..a787693ae67cd8 --- /dev/null +++ b/Modules/_ctypes/clinic/callproc.c.h @@ -0,0 +1,32 @@ +/*[clinic input] +preserve +[clinic start generated code]*/ + +PyDoc_STRVAR(create_pointer_type__doc__, +"POINTER($module, type, /)\n" +"--\n" +"\n" +"Create and return a new ctypes pointer type.\n" +"\n" +" type\n" +" A ctypes type.\n" +"\n" +"Pointer types are cached and reused internally,\n" +"so calling this function repeatedly is cheap."); + +#define CREATE_POINTER_TYPE_METHODDEF \ + {"POINTER", (PyCFunction)create_pointer_type, METH_O, create_pointer_type__doc__}, + +PyDoc_STRVAR(create_pointer_inst__doc__, +"pointer($module, obj, /)\n" +"--\n" +"\n" +"Create a new pointer instance, pointing to \'obj\'.\n" +"\n" +"The returned object is of the type POINTER(type(obj)). Note that if you\n" +"just want to pass a pointer to an object to a foreign function call, you\n" +"should use byref(obj) which is much faster."); + +#define CREATE_POINTER_INST_METHODDEF \ + {"pointer", (PyCFunction)create_pointer_inst, METH_O, create_pointer_inst__doc__}, +/*[clinic end generated code: output=51b311ea369e5adf input=a9049054013a1b77]*/ diff --git a/Modules/_ctypes/malloc_closure.c b/Modules/_ctypes/malloc_closure.c index 3a859322772ba7..bb4f8f21bd3f77 100644 --- a/Modules/_ctypes/malloc_closure.c +++ b/Modules/_ctypes/malloc_closure.c @@ -1,16 +1,17 @@ #ifndef Py_BUILD_CORE_BUILTIN # define Py_BUILD_CORE_MODULE 1 #endif + #include #include #ifdef MS_WIN32 -#include +# include #else -#include -#include -# if !defined(MAP_ANONYMOUS) && defined(MAP_ANON) -# define MAP_ANONYMOUS MAP_ANON -# endif +# include +# include // sysconf() +# if !defined(MAP_ANONYMOUS) && defined(MAP_ANON) +# define MAP_ANONYMOUS MAP_ANON +# endif #endif #include "ctypes.h" diff --git a/Modules/_ctypes/stgdict.c b/Modules/_ctypes/stgdict.c index 3348ebd6593d2f..fb3e20e8db3e27 100644 --- a/Modules/_ctypes/stgdict.c +++ b/Modules/_ctypes/stgdict.c @@ -9,6 +9,7 @@ #endif #include "pycore_call.h" // _PyObject_CallNoArgs() +#include "pycore_dict.h" // _PyDict_SizeOf() #include #ifdef MS_WIN32 # include @@ -385,11 +386,11 @@ PyCStructUnionType_update_stgdict(PyObject *type, PyObject *fields, int isStruct if (fields == NULL) return 0; - if (PyObject_GetOptionalAttr(type, &_Py_ID(_swappedbytes_), &tmp) < 0) { + int rc = PyObject_HasAttrWithError(type, &_Py_ID(_swappedbytes_)); + if (rc < 0) { return -1; } - if (tmp) { - Py_DECREF(tmp); + if (rc) { big_endian = !PY_BIG_ENDIAN; } else { @@ -400,7 +401,7 @@ PyCStructUnionType_update_stgdict(PyObject *type, PyObject *fields, int isStruct return -1; } if (tmp) { - pack = _PyLong_AsInt(tmp); + pack = PyLong_AsInt(tmp); Py_DECREF(tmp); if (pack < 0) { if (!PyErr_Occurred() || @@ -694,31 +695,49 @@ PyCStructUnionType_update_stgdict(PyObject *type, PyObject *fields, int isStruct stgdict->size = aligned_size; stgdict->align = total_align; - stgdict->length = len; /* ADD ffi_ofs? */ + stgdict->length = ffi_ofs + len; -#define MAX_STRUCT_SIZE 16 +/* + * The value of MAX_STRUCT_SIZE depends on the platform Python is running on. + */ +#if defined(__aarch64__) || defined(__arm__) +# define MAX_STRUCT_SIZE 32 +#elif defined(__powerpc64__) +# define MAX_STRUCT_SIZE 64 +#else +# define MAX_STRUCT_SIZE 16 +#endif if (arrays_seen && (size <= MAX_STRUCT_SIZE)) { /* - * See bpo-22273. Arrays are normally treated as pointers, which is - * fine when an array name is being passed as parameter, but not when - * passing structures by value that contain arrays. On 64-bit Linux, - * small structures passed by value are passed in registers, and in + * See bpo-22273 and gh-110190. Arrays are normally treated as + * pointers, which is fine when an array name is being passed as + * parameter, but not when passing structures by value that contain + * arrays. + * Small structures passed by value are passed in registers, and in * order to do this, libffi needs to know the true type of the array * members of structs. Treating them as pointers breaks things. * - * By small structures, we mean ones that are 16 bytes or less. In that - * case, there can't be more than 16 elements after unrolling arrays, - * as we (will) disallow bitfields. So we can collect the true ffi_type - * values in a fixed-size local array on the stack and, if any arrays - * were seen, replace the ffi_type_pointer.elements with a more - * accurate set, to allow libffi to marshal them into registers - * correctly. It means one more loop over the fields, but if we got - * here, the structure is small, so there aren't too many of those. + * Small structures have different sizes depending on the platform + * where Python is running on: + * + * * x86-64: 16 bytes or less + * * Arm platforms (both 32 and 64 bit): 32 bytes or less + * * PowerPC 64 Little Endian: 64 bytes or less * - * Although the passing in registers is specific to 64-bit Linux, the - * array-in-struct vs. pointer problem is general. But we restrict the - * type transformation to small structs nonetheless. + * In that case, there can't be more than 16, 32 or 64 elements after + * unrolling arrays, as we (will) disallow bitfields. + * So we can collect the true ffi_type values in a fixed-size local + * array on the stack and, if any arrays were seen, replace the + * ffi_type_pointer.elements with a more accurate set, to allow + * libffi to marshal them into registers correctly. + * It means one more loop over the fields, but if we got here, + * the structure is small, so there aren't too many of those. + * + * Although the passing in registers is specific to the above + * platforms, the array-in-struct vs. pointer problem is general. + * But we restrict the type transformation to small structs + * nonetheless. * * Note that although a union may be small in terms of memory usage, it * could contain many overlapping declarations of arrays, e.g. @@ -744,6 +763,8 @@ PyCStructUnionType_update_stgdict(PyObject *type, PyObject *fields, int isStruct * struct { uint_32 e1; uint_32 e2; ... uint_32 e_4; } f6; * } * + * The same principle applies for a struct 32 or 64 bytes in size. + * * So the struct/union needs setting up as follows: all non-array * elements copied across as is, and all array elements replaced with * an equivalent struct which has as many fields as the array has diff --git a/Modules/_curses_panel.c b/Modules/_curses_panel.c index 292b57c083d0c8..2ec8f34c5c220b 100644 --- a/Modules/_curses_panel.c +++ b/Modules/_curses_panel.c @@ -10,6 +10,11 @@ static const char PyCursesVersion[] = "2.1"; /* Includes */ +// clinic/_curses_panel.c.h uses internal pycore_modsupport.h API +#ifndef Py_BUILD_CORE_BUILTIN +# define Py_BUILD_CORE_MODULE 1 +#endif + #include "Python.h" #include "py_curses.h" diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index 1f5afa6fcd898d..d04d1e973af030 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -3069,8 +3069,8 @@ _curses_getwin(PyObject *module, PyObject *file) } datalen = PyBytes_GET_SIZE(data); if (fwrite(PyBytes_AS_STRING(data), 1, datalen, fp) != datalen) { - Py_DECREF(data); PyErr_SetFromErrno(PyExc_OSError); + Py_DECREF(data); goto error; } Py_DECREF(data); @@ -3673,7 +3673,7 @@ _curses_mousemask_impl(PyObject *module, unsigned long newmask) #endif /*[clinic input] -_curses.napms +_curses.napms -> int ms: int Duration in milliseconds. @@ -3682,13 +3682,13 @@ _curses.napms Sleep for specified time. [clinic start generated code]*/ -static PyObject * +static int _curses_napms_impl(PyObject *module, int ms) -/*[clinic end generated code: output=a40a1da2e39ea438 input=20cd3af2b6900f56]*/ +/*[clinic end generated code: output=5f292a6a724491bd input=c6d6e01f2f1df9f7]*/ { PyCursesInitialised; - return Py_BuildValue("i", napms(ms)); + return napms(ms); } diff --git a/Modules/_datetimemodule.c b/Modules/_datetimemodule.c index 9002a1de7fb5b7..cb5403e8461ff0 100644 --- a/Modules/_datetimemodule.c +++ b/Modules/_datetimemodule.c @@ -40,6 +40,27 @@ #define PyTimezone_Check(op) PyObject_TypeCheck(op, &PyDateTime_TimeZoneType) +typedef struct { + /* Conversion factors. */ + PyObject *us_per_ms; // 1_000 + PyObject *us_per_second; // 1_000_000 + PyObject *us_per_minute; // 1e6 * 60 as Python int + PyObject *us_per_hour; // 1e6 * 3600 as Python int + PyObject *us_per_day; // 1e6 * 3600 * 24 as Python int + PyObject *us_per_week; // 1e6 * 3600 * 24 * 7 as Python int + PyObject *seconds_per_day; // 3600 * 24 as Python int + + /* The interned UTC timezone instance */ + PyObject *utc; + + /* The interned Unix epoch datetime instance */ + PyObject *epoch; +} datetime_state; + +static datetime_state _datetime_global_state; + +#define STATIC_STATE() (&_datetime_global_state) + /*[clinic input] module datetime class datetime.datetime "PyDateTime_DateTime *" "&PyDateTime_DateTimeType" @@ -1139,11 +1160,6 @@ typedef struct PyObject *name; } PyDateTime_TimeZone; -/* The interned UTC timezone instance */ -static PyObject *PyDateTime_TimeZone_UTC; -/* The interned Epoch datetime instance */ -static PyObject *PyDateTime_Epoch; - /* Create new timezone instance checking offset range. This function does not check the name argument. Caller must assure that offset is a timedelta instance and name is either NULL @@ -1177,7 +1193,8 @@ new_timezone(PyObject *offset, PyObject *name) assert(name == NULL || PyUnicode_Check(name)); if (name == NULL && delta_bool((PyDateTime_Delta *)offset) == 0) { - return Py_NewRef(PyDateTime_TimeZone_UTC); + datetime_state *st = STATIC_STATE(); + return Py_NewRef(st->utc); } if ((GET_TD_DAYS(offset) == -1 && GET_TD_SECONDS(offset) == 0 && @@ -1390,7 +1407,8 @@ tzinfo_from_isoformat_results(int rv, int tzoffset, int tz_useconds) if (rv == 1) { // Create a timezone from offset in seconds (0 returns UTC) if (tzoffset == 0) { - return Py_NewRef(PyDateTime_TimeZone_UTC); + datetime_state *st = STATIC_STATE(); + return Py_NewRef(st->utc); } PyObject *delta = new_delta(0, tzoffset, tz_useconds, 1); @@ -1807,19 +1825,6 @@ cmperror(PyObject *a, PyObject *b) return NULL; } -/* --------------------------------------------------------------------------- - * Cached Python objects; these are set by the module init function. - */ - -/* Conversion factors. */ -static PyObject *us_per_ms = NULL; /* 1000 */ -static PyObject *us_per_second = NULL; /* 1000000 */ -static PyObject *us_per_minute = NULL; /* 1e6 * 60 as Python int */ -static PyObject *us_per_hour = NULL; /* 1e6 * 3600 as Python int */ -static PyObject *us_per_day = NULL; /* 1e6 * 3600 * 24 as Python int */ -static PyObject *us_per_week = NULL; /* 1e6*3600*24*7 as Python int */ -static PyObject *seconds_per_day = NULL; /* 3600*24 as Python int */ - /* --------------------------------------------------------------------------- * Class implementations. */ @@ -1845,7 +1850,8 @@ delta_to_microseconds(PyDateTime_Delta *self) x1 = PyLong_FromLong(GET_TD_DAYS(self)); if (x1 == NULL) goto Done; - x2 = PyNumber_Multiply(x1, seconds_per_day); /* days in seconds */ + datetime_state *st = STATIC_STATE(); + x2 = PyNumber_Multiply(x1, st->seconds_per_day); /* days in seconds */ if (x2 == NULL) goto Done; Py_SETREF(x1, NULL); @@ -1862,7 +1868,7 @@ delta_to_microseconds(PyDateTime_Delta *self) /* x1 = */ x2 = NULL; /* x3 has days+seconds in seconds */ - x1 = PyNumber_Multiply(x3, us_per_second); /* us */ + x1 = PyNumber_Multiply(x3, st->us_per_second); /* us */ if (x1 == NULL) goto Done; Py_SETREF(x3, NULL); @@ -1917,13 +1923,14 @@ microseconds_to_delta_ex(PyObject *pyus, PyTypeObject *type) PyObject *num = NULL; PyObject *result = NULL; - tuple = checked_divmod(pyus, us_per_second); + datetime_state *st = STATIC_STATE(); + tuple = checked_divmod(pyus, st->us_per_second); if (tuple == NULL) { goto Done; } num = PyTuple_GET_ITEM(tuple, 1); /* us */ - us = _PyLong_AsInt(num); + us = PyLong_AsInt(num); num = NULL; if (us == -1 && PyErr_Occurred()) { goto Done; @@ -1935,13 +1942,13 @@ microseconds_to_delta_ex(PyObject *pyus, PyTypeObject *type) num = Py_NewRef(PyTuple_GET_ITEM(tuple, 0)); /* leftover seconds */ Py_DECREF(tuple); - tuple = checked_divmod(num, seconds_per_day); + tuple = checked_divmod(num, st->seconds_per_day); if (tuple == NULL) goto Done; Py_DECREF(num); num = PyTuple_GET_ITEM(tuple, 1); /* seconds */ - s = _PyLong_AsInt(num); + s = PyLong_AsInt(num); num = NULL; if (s == -1 && PyErr_Occurred()) { goto Done; @@ -1951,7 +1958,7 @@ microseconds_to_delta_ex(PyObject *pyus, PyTypeObject *type) } num = Py_NewRef(PyTuple_GET_ITEM(tuple, 0)); /* leftover days */ - d = _PyLong_AsInt(num); + d = PyLong_AsInt(num); if (d == -1 && PyErr_Occurred()) { goto Done; } @@ -2535,28 +2542,29 @@ delta_new(PyTypeObject *type, PyObject *args, PyObject *kw) y = accum("microseconds", x, us, _PyLong_GetOne(), &leftover_us); CLEANUP; } + datetime_state *st = STATIC_STATE(); if (ms) { - y = accum("milliseconds", x, ms, us_per_ms, &leftover_us); + y = accum("milliseconds", x, ms, st->us_per_ms, &leftover_us); CLEANUP; } if (second) { - y = accum("seconds", x, second, us_per_second, &leftover_us); + y = accum("seconds", x, second, st->us_per_second, &leftover_us); CLEANUP; } if (minute) { - y = accum("minutes", x, minute, us_per_minute, &leftover_us); + y = accum("minutes", x, minute, st->us_per_minute, &leftover_us); CLEANUP; } if (hour) { - y = accum("hours", x, hour, us_per_hour, &leftover_us); + y = accum("hours", x, hour, st->us_per_hour, &leftover_us); CLEANUP; } if (day) { - y = accum("days", x, day, us_per_day, &leftover_us); + y = accum("days", x, day, st->us_per_day, &leftover_us); CLEANUP; } if (week) { - y = accum("weeks", x, week, us_per_week, &leftover_us); + y = accum("weeks", x, week, st->us_per_week, &leftover_us); CLEANUP; } if (leftover_us) { @@ -2711,7 +2719,8 @@ delta_total_seconds(PyObject *self, PyObject *Py_UNUSED(ignored)) if (total_microseconds == NULL) return NULL; - total_seconds = PyNumber_TrueDivide(total_microseconds, us_per_second); + datetime_state *st = STATIC_STATE(); + total_seconds = PyNumber_TrueDivide(total_microseconds, st->us_per_second); Py_DECREF(total_microseconds); return total_seconds; @@ -3590,6 +3599,8 @@ static PyMethodDef date_methods[] = { {"replace", _PyCFunction_CAST(date_replace), METH_VARARGS | METH_KEYWORDS, PyDoc_STR("Return date with new specified fields.")}, + {"__replace__", _PyCFunction_CAST(date_replace), METH_VARARGS | METH_KEYWORDS}, + {"__reduce__", (PyCFunction)date_reduce, METH_NOARGS, PyDoc_STR("__reduce__() -> (cls, state)")}, @@ -3941,8 +3952,10 @@ timezone_repr(PyDateTime_TimeZone *self) to use Py_TYPE(self)->tp_name here. */ const char *type_name = Py_TYPE(self)->tp_name; - if (((PyObject *)self) == PyDateTime_TimeZone_UTC) + datetime_state *st = STATIC_STATE(); + if (((PyObject *)self) == st->utc) { return PyUnicode_FromFormat("%s.utc", type_name); + } if (self->name == NULL) return PyUnicode_FromFormat("%s(%R)", type_name, self->offset); @@ -3962,11 +3975,14 @@ timezone_str(PyDateTime_TimeZone *self) if (self->name != NULL) { return Py_NewRef(self->name); } - if ((PyObject *)self == PyDateTime_TimeZone_UTC || + datetime_state *st = STATIC_STATE(); + if ((PyObject *)self == st->utc || (GET_TD_DAYS(self->offset) == 0 && GET_TD_SECONDS(self->offset) == 0 && GET_TD_MICROSECONDS(self->offset) == 0)) + { return PyUnicode_FromString("UTC"); + } /* Offset is normalized, so it is negative if days < 0 */ if (GET_TD_DAYS(self->offset) < 0) { sign = '-'; @@ -4044,8 +4060,8 @@ static PyObject * timezone_getinitargs(PyDateTime_TimeZone *self, PyObject *Py_UNUSED(ignored)) { if (self->name == NULL) - return Py_BuildValue("(O)", self->offset); - return Py_BuildValue("(OO)", self->offset, self->name); + return PyTuple_Pack(1, self->offset); + return PyTuple_Pack(2, self->offset, self->name); } static PyMethodDef timezone_methods[] = { @@ -4614,7 +4630,7 @@ time_fromisoformat(PyObject *cls, PyObject *tstr) { } int hour = 0, minute = 0, second = 0, microsecond = 0; - int tzoffset, tzimicrosecond = 0; + int tzoffset = 0, tzimicrosecond = 0; int rv = parse_isoformat_time(p, len, &hour, &minute, &second, µsecond, &tzoffset, &tzimicrosecond); @@ -4719,6 +4735,8 @@ static PyMethodDef time_methods[] = { {"replace", _PyCFunction_CAST(time_replace), METH_VARARGS | METH_KEYWORDS, PyDoc_STR("Return time with new specified fields.")}, + {"__replace__", _PyCFunction_CAST(time_replace), METH_VARARGS | METH_KEYWORDS}, + {"fromisoformat", (PyCFunction)time_fromisoformat, METH_O | METH_CLASS, PyDoc_STR("string -> time from a string in ISO 8601 format")}, @@ -5136,9 +5154,9 @@ static PyObject * datetime_utcnow(PyObject *cls, PyObject *dummy) { if (PyErr_WarnEx(PyExc_DeprecationWarning, - "datetime.utcnow() is deprecated and scheduled for removal in a " + "datetime.datetime.utcnow() is deprecated and scheduled for removal in a " "future version. Use timezone-aware objects to represent datetimes " - "in UTC: datetime.now(datetime.UTC).", 1)) + "in UTC: datetime.datetime.now(datetime.UTC).", 1)) { return NULL; } @@ -5179,9 +5197,9 @@ static PyObject * datetime_utcfromtimestamp(PyObject *cls, PyObject *args) { if (PyErr_WarnEx(PyExc_DeprecationWarning, - "datetime.utcfromtimestamp() is deprecated and scheduled for removal " + "datetime.datetime.utcfromtimestamp() is deprecated and scheduled for removal " "in a future version. Use timezone-aware objects to represent " - "datetimes in UTC: datetime.fromtimestamp(timestamp, datetime.UTC).", 1)) + "datetimes in UTC: datetime.datetime.fromtimestamp(timestamp, datetime.UTC).", 1)) { return NULL; } @@ -6130,7 +6148,8 @@ local_timezone(PyDateTime_DateTime *utc_time) PyObject *one_second; PyObject *seconds; - delta = datetime_subtract((PyObject *)utc_time, PyDateTime_Epoch); + datetime_state *st = STATIC_STATE(); + delta = datetime_subtract((PyObject *)utc_time, st->epoch); if (delta == NULL) return NULL; one_second = new_delta(0, 1, 0, 0); @@ -6242,6 +6261,7 @@ datetime_astimezone(PyDateTime_DateTime *self, PyObject *args, PyObject *kw) if (result == NULL) return NULL; + datetime_state *st = STATIC_STATE(); /* Make sure result is aware and UTC. */ if (!HASTZINFO(result)) { temp = (PyObject *)result; @@ -6253,7 +6273,7 @@ datetime_astimezone(PyDateTime_DateTime *self, PyObject *args, PyObject *kw) DATE_GET_MINUTE(result), DATE_GET_SECOND(result), DATE_GET_MICROSECOND(result), - PyDateTime_TimeZone_UTC, + st->utc, DATE_GET_FOLD(result), Py_TYPE(result)); Py_DECREF(temp); @@ -6262,7 +6282,7 @@ datetime_astimezone(PyDateTime_DateTime *self, PyObject *args, PyObject *kw) } else { /* Result is already aware - just replace tzinfo. */ - Py_SETREF(result->tzinfo, Py_NewRef(PyDateTime_TimeZone_UTC)); + Py_SETREF(result->tzinfo, Py_NewRef(st->utc)); } /* Attach new tzinfo and let fromutc() do the rest. */ @@ -6366,8 +6386,9 @@ datetime_timestamp(PyDateTime_DateTime *self, PyObject *Py_UNUSED(ignored)) PyObject *result; if (HASTZINFO(self) && self->tzinfo != Py_None) { + datetime_state *st = STATIC_STATE(); PyObject *delta; - delta = datetime_subtract((PyObject *)self, PyDateTime_Epoch); + delta = datetime_subtract((PyObject *)self, st->epoch); if (delta == NULL) return NULL; result = delta_total_seconds(delta, NULL); @@ -6579,6 +6600,8 @@ static PyMethodDef datetime_methods[] = { {"replace", _PyCFunction_CAST(datetime_replace), METH_VARARGS | METH_KEYWORDS, PyDoc_STR("Return datetime with new specified fields.")}, + {"__replace__", _PyCFunction_CAST(datetime_replace), METH_VARARGS | METH_KEYWORDS}, + {"astimezone", _PyCFunction_CAST(datetime_astimezone), METH_VARARGS | METH_KEYWORDS, PyDoc_STR("tz -> convert to local time in new timezone tz\n")}, @@ -6686,10 +6709,11 @@ get_datetime_capi(void) capi->Date_FromTimestamp = datetime_date_fromtimestamp_capi; capi->DateTime_FromDateAndTimeAndFold = new_datetime_ex2; capi->Time_FromTimeAndFold = new_time_ex2; - // Make sure this function is called after PyDateTime_TimeZone_UTC has + // Make sure this function is called after utc has // been initialized. - assert(PyDateTime_TimeZone_UTC != NULL); - capi->TimeZone_UTC = PyDateTime_TimeZone_UTC; // borrowed ref + datetime_state *st = STATIC_STATE(); + assert(st->utc != NULL); + capi->TimeZone_UTC = st->utc; // borrowed ref return capi; } @@ -6700,6 +6724,85 @@ datetime_destructor(PyObject *op) PyMem_Free(ptr); } +static int +datetime_clear(PyObject *module) +{ + datetime_state *st = STATIC_STATE(); + + Py_CLEAR(st->us_per_ms); + Py_CLEAR(st->us_per_second); + Py_CLEAR(st->us_per_minute); + Py_CLEAR(st->us_per_hour); + Py_CLEAR(st->us_per_day); + Py_CLEAR(st->us_per_week); + Py_CLEAR(st->seconds_per_day); + Py_CLEAR(st->utc); + Py_CLEAR(st->epoch); + return 0; +} + +static PyObject * +create_timezone_from_delta(int days, int sec, int ms, int normalize) +{ + PyObject *delta = new_delta(days, sec, ms, normalize); + if (delta == NULL) { + return NULL; + } + PyObject *tz = create_timezone(delta, NULL); + Py_DECREF(delta); + return tz; +} + +static int +init_state(datetime_state *st) +{ + st->us_per_ms = PyLong_FromLong(1000); + if (st->us_per_ms == NULL) { + return -1; + } + st->us_per_second = PyLong_FromLong(1000000); + if (st->us_per_second == NULL) { + return -1; + } + st->us_per_minute = PyLong_FromLong(60000000); + if (st->us_per_minute == NULL) { + return -1; + } + st->seconds_per_day = PyLong_FromLong(24 * 3600); + if (st->seconds_per_day == NULL) { + return -1; + } + + /* The rest are too big for 32-bit ints, but even + * us_per_week fits in 40 bits, so doubles should be exact. + */ + st->us_per_hour = PyLong_FromDouble(3600000000.0); + if (st->us_per_hour == NULL) { + return -1; + } + st->us_per_day = PyLong_FromDouble(86400000000.0); + if (st->us_per_day == NULL) { + return -1; + } + st->us_per_week = PyLong_FromDouble(604800000000.0); + if (st->us_per_week == NULL) { + return -1; + } + + /* Init UTC timezone */ + st->utc = create_timezone_from_delta(0, 0, 0, 0); + if (st->utc == NULL) { + return -1; + } + + /* Init Unix epoch */ + st->epoch = new_datetime(1970, 1, 1, 0, 0, 0, 0, st->utc, 0); + if (st->epoch == NULL) { + return -1; + } + return 0; +} + static int _datetime_exec(PyObject *module) { @@ -6721,23 +6824,23 @@ _datetime_exec(PyObject *module) for (size_t i = 0; i < Py_ARRAY_LENGTH(types); i++) { if (PyModule_AddType(module, types[i]) < 0) { - return -1; + goto error; } } if (PyType_Ready(&PyDateTime_IsoCalendarDateType) < 0) { - return -1; + goto error; } #define DATETIME_ADD_MACRO(dict, c, value_expr) \ do { \ PyObject *value = (value_expr); \ if (value == NULL) { \ - return -1; \ + goto error; \ } \ if (PyDict_SetItemString(dict, c, value) < 0) { \ Py_DECREF(value); \ - return -1; \ + goto error; \ } \ Py_DECREF(value); \ } while(0) @@ -6769,77 +6872,54 @@ _datetime_exec(PyObject *module) 999999, Py_None, 0)); DATETIME_ADD_MACRO(d, "resolution", new_delta(0, 0, 1, 0)); - /* timezone values */ - d = PyDateTime_TimeZoneType.tp_dict; - PyObject *delta = new_delta(0, 0, 0, 0); - if (delta == NULL) { - return -1; + datetime_state *st = STATIC_STATE(); + if (init_state(st) < 0) { + goto error; } - PyObject *x = create_timezone(delta, NULL); - Py_DECREF(delta); - if (x == NULL) { - return -1; - } - if (PyDict_SetItemString(d, "utc", x) < 0) { - Py_DECREF(x); - return -1; + /* timezone values */ + d = PyDateTime_TimeZoneType.tp_dict; + if (PyDict_SetItemString(d, "utc", st->utc) < 0) { + goto error; } - PyDateTime_TimeZone_UTC = x; - /* bpo-37642: These attributes are rounded to the nearest minute for backwards * compatibility, even though the constructor will accept a wider range of * values. This may change in the future.*/ - delta = new_delta(-1, 60, 0, 1); /* -23:59 */ - if (delta == NULL) { - return -1; - } - - x = create_timezone(delta, NULL); - Py_DECREF(delta); - DATETIME_ADD_MACRO(d, "min", x); - delta = new_delta(0, (23 * 60 + 59) * 60, 0, 0); /* +23:59 */ - if (delta == NULL) { - return -1; - } + /* -23:59 */ + PyObject *min = create_timezone_from_delta(-1, 60, 0, 1); + DATETIME_ADD_MACRO(d, "min", min); - x = create_timezone(delta, NULL); - Py_DECREF(delta); - DATETIME_ADD_MACRO(d, "max", x); + /* +23:59 */ + PyObject *max = create_timezone_from_delta(0, (23 * 60 + 59) * 60, 0, 0); + DATETIME_ADD_MACRO(d, "max", max); - /* Epoch */ - PyDateTime_Epoch = new_datetime(1970, 1, 1, 0, 0, 0, 0, - PyDateTime_TimeZone_UTC, 0); - if (PyDateTime_Epoch == NULL) { - return -1; - } - - /* module initialization */ + /* Add module level attributes */ if (PyModule_AddIntMacro(module, MINYEAR) < 0) { - return -1; + goto error; } if (PyModule_AddIntMacro(module, MAXYEAR) < 0) { - return -1; + goto error; + } + if (PyModule_AddObjectRef(module, "UTC", st->utc) < 0) { + goto error; } + /* At last, set up and add the encapsulated C API */ PyDateTime_CAPI *capi = get_datetime_capi(); if (capi == NULL) { - return -1; + goto error; } - x = PyCapsule_New(capi, PyDateTime_CAPSULE_NAME, datetime_destructor); - if (x == NULL) { + PyObject *capsule = PyCapsule_New(capi, PyDateTime_CAPSULE_NAME, + datetime_destructor); + if (capsule == NULL) { PyMem_Free(capi); - return -1; - } - - if (PyModule_Add(module, "datetime_CAPI", x) < 0) { - return -1; + goto error; } - - if (PyModule_AddObjectRef(module, "UTC", PyDateTime_TimeZone_UTC) < 0) { - return -1; + if (PyModule_Add(module, "datetime_CAPI", capsule) < 0) { + PyMem_Free(capi); + goto error; } /* A 4-year cycle has an extra leap day over what we'd get from @@ -6860,54 +6940,16 @@ _datetime_exec(PyObject *module) static_assert(DI100Y == 25 * DI4Y - 1, "DI100Y"); assert(DI100Y == days_before_year(100+1)); - us_per_ms = PyLong_FromLong(1000); - if (us_per_ms == NULL) { - goto error; - } - us_per_second = PyLong_FromLong(1000000); - if (us_per_second == NULL) { - goto error; - } - us_per_minute = PyLong_FromLong(60000000); - if (us_per_minute == NULL) { - goto error; - } - seconds_per_day = PyLong_FromLong(24 * 3600); - if (seconds_per_day == NULL) { - goto error; - } - - /* The rest are too big for 32-bit ints, but even - * us_per_week fits in 40 bits, so doubles should be exact. - */ - us_per_hour = PyLong_FromDouble(3600000000.0); - if (us_per_hour == NULL) { - goto error; - } - us_per_day = PyLong_FromDouble(86400000000.0); - if (us_per_day == NULL) { - goto error; - } - us_per_week = PyLong_FromDouble(604800000000.0); - if (us_per_week == NULL) { - goto error; - } - return 0; error: - Py_XDECREF(us_per_ms); - Py_XDECREF(us_per_second); - Py_XDECREF(us_per_minute); - Py_XDECREF(us_per_hour); - Py_XDECREF(us_per_day); - Py_XDECREF(us_per_week); - Py_XDECREF(seconds_per_day); + datetime_clear(module); return -1; } +#undef DATETIME_ADD_MACRO static struct PyModuleDef datetimemodule = { - PyModuleDef_HEAD_INIT, + .m_base = PyModuleDef_HEAD_INIT, .m_name = "_datetime", .m_doc = "Fast implementation of the datetime type.", .m_size = -1, diff --git a/Modules/_dbmmodule.c b/Modules/_dbmmodule.c index bd807698927e86..ee33fe625be3d7 100644 --- a/Modules/_dbmmodule.c +++ b/Modules/_dbmmodule.c @@ -2,6 +2,11 @@ /* DBM module using dictionary interface */ +// clinic/_dbmmodule.c.h uses internal pycore_modsupport.h API +#ifndef Py_BUILD_CORE_BUILTIN +# define Py_BUILD_CORE_MODULE 1 +#endif + #include "Python.h" #include @@ -552,11 +557,6 @@ dbmopen_impl(PyObject *module, PyObject *filename, const char *flags, } const char *name = PyBytes_AS_STRING(filenamebytes); - if (strlen(name) != (size_t)PyBytes_GET_SIZE(filenamebytes)) { - Py_DECREF(filenamebytes); - PyErr_SetString(PyExc_ValueError, "embedded null character"); - return NULL; - } PyObject *self = newdbmobject(state, name, iflags, mode); Py_DECREF(filenamebytes); return self; diff --git a/Modules/_decimal/_decimal.c b/Modules/_decimal/_decimal.c index 585214cc45d6cd..8b93f8e2cbcf0b 100644 --- a/Modules/_decimal/_decimal.c +++ b/Modules/_decimal/_decimal.c @@ -35,6 +35,7 @@ #include "complexobject.h" #include "mpdecimal.h" +#include // isascii() #include #include "docstrings.h" @@ -3592,6 +3593,12 @@ dec_format(PyObject *dec, PyObject *args) if (replace_fillchar) { dec_replace_fillchar(decstring); } + if (strchr(fmt, 'N') != NULL) { + if (PyErr_WarnEx(PyExc_DeprecationWarning, + "Format specifier 'N' is deprecated", 1) < 0) { + goto finish; + } + } result = PyUnicode_DecodeUTF8(decstring, size, NULL); @@ -5876,6 +5883,7 @@ cfunc_noargs(PyTypeObject *t, const char *name) return NULL; } +static int minalloc_is_set = 0; static int _decimal_exec(PyObject *m) @@ -5898,7 +5906,12 @@ _decimal_exec(PyObject *m) mpd_reallocfunc = PyMem_Realloc; mpd_callocfunc = mpd_callocfunc_em; mpd_free = PyMem_Free; - mpd_setminalloc(_Py_DEC_MINALLOC); + + /* Suppress the warning caused by multi-phase initialization */ + if (!minalloc_is_set) { + mpd_setminalloc(_Py_DEC_MINALLOC); + minalloc_is_set = 1; + } decimal_state *state = get_module_state(m); diff --git a/Modules/_decimal/tests/bench.py b/Modules/_decimal/tests/bench.py index 24e091b6887ccd..640290f2ec7962 100644 --- a/Modules/_decimal/tests/bench.py +++ b/Modules/_decimal/tests/bench.py @@ -7,6 +7,8 @@ import time +import sys +from functools import wraps from test.support.import_helper import import_fresh_module C = import_fresh_module('decimal', fresh=['_decimal']) @@ -64,66 +66,85 @@ def factorial(n, m): else: return factorial(n, (n+m)//2) * factorial((n+m)//2 + 1, m) +# Fix failed test cases caused by CVE-2020-10735 patch. +# See gh-95778 for details. +def increase_int_max_str_digits(maxdigits): + def _increase_int_max_str_digits(func, maxdigits=maxdigits): + @wraps(func) + def wrapper(*args, **kwargs): + previous_int_limit = sys.get_int_max_str_digits() + sys.set_int_max_str_digits(maxdigits) + ans = func(*args, **kwargs) + sys.set_int_max_str_digits(previous_int_limit) + return ans + return wrapper + return _increase_int_max_str_digits + +def test_calc_pi(): + print("\n# ======================================================================") + print("# Calculating pi, 10000 iterations") + print("# ======================================================================\n") + + to_benchmark = [pi_float, pi_decimal] + if C is not None: + to_benchmark.insert(1, pi_cdecimal) + + for prec in [9, 19]: + print("\nPrecision: %d decimal digits\n" % prec) + for func in to_benchmark: + start = time.time() + if C is not None: + C.getcontext().prec = prec + P.getcontext().prec = prec + for i in range(10000): + x = func() + print("%s:" % func.__name__.replace("pi_", "")) + print("result: %s" % str(x)) + print("time: %fs\n" % (time.time()-start)) + +@increase_int_max_str_digits(maxdigits=10000000) +def test_factorial(): + print("\n# ======================================================================") + print("# Factorial") + print("# ======================================================================\n") -print("\n# ======================================================================") -print("# Calculating pi, 10000 iterations") -print("# ======================================================================\n") - -to_benchmark = [pi_float, pi_decimal] -if C is not None: - to_benchmark.insert(1, pi_cdecimal) - -for prec in [9, 19]: - print("\nPrecision: %d decimal digits\n" % prec) - for func in to_benchmark: - start = time.time() - if C is not None: - C.getcontext().prec = prec - P.getcontext().prec = prec - for i in range(10000): - x = func() - print("%s:" % func.__name__.replace("pi_", "")) - print("result: %s" % str(x)) - print("time: %fs\n" % (time.time()-start)) - - -print("\n# ======================================================================") -print("# Factorial") -print("# ======================================================================\n") - -if C is not None: - c = C.getcontext() - c.prec = C.MAX_PREC - c.Emax = C.MAX_EMAX - c.Emin = C.MIN_EMIN + if C is not None: + c = C.getcontext() + c.prec = C.MAX_PREC + c.Emax = C.MAX_EMAX + c.Emin = C.MIN_EMIN -for n in [100000, 1000000]: + for n in [100000, 1000000]: - print("n = %d\n" % n) + print("n = %d\n" % n) - if C is not None: - # C version of decimal + if C is not None: + # C version of decimal + start_calc = time.time() + x = factorial(C.Decimal(n), 0) + end_calc = time.time() + start_conv = time.time() + sx = str(x) + end_conv = time.time() + print("cdecimal:") + print("calculation time: %fs" % (end_calc-start_calc)) + print("conversion time: %fs\n" % (end_conv-start_conv)) + + # Python integers start_calc = time.time() - x = factorial(C.Decimal(n), 0) + y = factorial(n, 0) end_calc = time.time() start_conv = time.time() - sx = str(x) - end_conv = time.time() - print("cdecimal:") - print("calculation time: %fs" % (end_calc-start_calc)) - print("conversion time: %fs\n" % (end_conv-start_conv)) + sy = str(y) + end_conv = time.time() - # Python integers - start_calc = time.time() - y = factorial(n, 0) - end_calc = time.time() - start_conv = time.time() - sy = str(y) - end_conv = time.time() + print("int:") + print("calculation time: %fs" % (end_calc-start_calc)) + print("conversion time: %fs\n\n" % (end_conv-start_conv)) - print("int:") - print("calculation time: %fs" % (end_calc-start_calc)) - print("conversion time: %fs\n\n" % (end_conv-start_conv)) + if C is not None: + assert(sx == sy) - if C is not None: - assert(sx == sy) +if __name__ == "__main__": + test_calc_pi() + test_factorial() diff --git a/Modules/_decimal/tests/deccheck.py b/Modules/_decimal/tests/deccheck.py index edf753f3704a18..bf277dd6879ffe 100644 --- a/Modules/_decimal/tests/deccheck.py +++ b/Modules/_decimal/tests/deccheck.py @@ -1301,7 +1301,7 @@ def tfunc(): out, _ = p.communicate() write_output(out, p.returncode) - N = os.cpu_count() + N = os.process_cpu_count() t = N * [None] for i in range(N): diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c index 8cb57e693d81d7..b574c96d3f9625 100644 --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -98,6 +98,7 @@ typedef struct { PyTypeObject *TreeBuilder_Type; PyTypeObject *XMLParser_Type; + PyObject *expat_capsule; struct PyExpat_CAPI *expat_capi; } elementtreestate; @@ -155,6 +156,7 @@ elementtree_clear(PyObject *m) Py_CLEAR(st->ElementIter_Type); Py_CLEAR(st->TreeBuilder_Type); Py_CLEAR(st->XMLParser_Type); + Py_CLEAR(st->expat_capsule); st->expat_capi = NULL; return 0; @@ -175,6 +177,7 @@ elementtree_traverse(PyObject *m, visitproc visit, void *arg) Py_VISIT(st->ElementIter_Type); Py_VISIT(st->TreeBuilder_Type); Py_VISIT(st->XMLParser_Type); + Py_VISIT(st->expat_capsule); return 0; } @@ -3066,6 +3069,7 @@ typedef struct { PyObject *handle_close; elementtreestate *state; + PyObject *elementtree_module; } XMLParserObject; /* helpers */ @@ -3532,12 +3536,11 @@ expat_start_doctype_handler(XMLParserObject *self, sysid_obj, NULL); Py_XDECREF(res); } - else if (PyObject_GetOptionalAttr((PyObject *)self, st->str_doctype, &res) > 0) { + else if (PyObject_HasAttrWithError((PyObject *)self, st->str_doctype) > 0) { (void)PyErr_WarnEx(PyExc_RuntimeWarning, "The doctype() method of XMLParser is ignored. " "Define doctype() method on the TreeBuilder target.", 1); - Py_DECREF(res); } Py_DECREF(doctype_name_obj); @@ -3608,7 +3611,11 @@ xmlparser_new(PyTypeObject *type, PyObject *args, PyObject *kwds) self->handle_start = self->handle_data = self->handle_end = NULL; self->handle_comment = self->handle_pi = self->handle_close = NULL; self->handle_doctype = NULL; - self->state = get_elementtree_state_by_type(type); + self->elementtree_module = PyType_GetModuleByDef(type, &elementtreemodule); + assert(self->elementtree_module != NULL); + Py_INCREF(self->elementtree_module); + // See gh-111784 for explanation why is reference to module needed here. + self->state = get_elementtree_state(self->elementtree_module); } return (PyObject *)self; } @@ -3785,6 +3792,7 @@ xmlparser_gc_clear(XMLParserObject *self) EXPAT(st, ParserFree)(parser); } + Py_CLEAR(self->elementtree_module); Py_CLEAR(self->handle_close); Py_CLEAR(self->handle_pi); Py_CLEAR(self->handle_comment); @@ -4344,7 +4352,10 @@ module_exec(PyObject *m) goto error; /* link against pyexpat */ - st->expat_capi = PyCapsule_Import(PyExpat_CAPSULE_NAME, 0); + if (!(st->expat_capsule = _PyImport_GetModuleAttrString("pyexpat", "expat_CAPI"))) + goto error; + if (!(st->expat_capi = PyCapsule_GetPointer(st->expat_capsule, PyExpat_CAPSULE_NAME))) + goto error; if (st->expat_capi) { /* check that it's usable */ if (strcmp(st->expat_capi->magic, PyExpat_CAPI_MAGIC) != 0 || @@ -4419,9 +4430,7 @@ module_exec(PyObject *m) static struct PyModuleDef_Slot elementtree_slots[] = { {Py_mod_exec, module_exec}, - // XXX gh-103092: fix isolation. - {Py_mod_multiple_interpreters, Py_MOD_MULTIPLE_INTERPRETERS_NOT_SUPPORTED}, - //{Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, + {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {0, NULL}, }; diff --git a/Modules/_functoolsmodule.c b/Modules/_functoolsmodule.c index 389ff4391de0be..9ab847165dc097 100644 --- a/Modules/_functoolsmodule.c +++ b/Modules/_functoolsmodule.c @@ -725,7 +725,7 @@ functools_reduce(PyObject *self, PyObject *args) } PyDoc_STRVAR(functools_reduce_doc, -"reduce(function, iterable[, initial]) -> value\n\ +"reduce(function, iterable[, initial], /) -> value\n\ \n\ Apply a function of two arguments cumulatively to the items of a sequence\n\ or iterable, from left to right, so as to reduce the iterable to a single\n\ @@ -1087,19 +1087,9 @@ bounded_lru_cache_wrapper(lru_cache_object *self, PyObject *args, PyObject *kwds The cache dict holds one reference to the link. We created one other reference when the link was created. The linked list only has borrowed references. */ - popresult = _PyDict_Pop_KnownHash(self->cache, link->key, - link->hash, Py_None); - if (popresult == Py_None) { - /* Getting here means that the user function call or another - thread has already removed the old key from the dictionary. - This link is now an orphan. Since we don't want to leave the - cache in an inconsistent state, we don't restore the link. */ - Py_DECREF(popresult); - Py_DECREF(link); - Py_DECREF(key); - return result; - } - if (popresult == NULL) { + int res = _PyDict_Pop_KnownHash((PyDictObject*)self->cache, link->key, + link->hash, &popresult); + if (res < 0) { /* An error arose while trying to remove the oldest key (the one being evicted) from the cache. We restore the link to its original position as the oldest link. Then we allow the @@ -1110,10 +1100,22 @@ bounded_lru_cache_wrapper(lru_cache_object *self, PyObject *args, PyObject *kwds Py_DECREF(result); return NULL; } + if (res == 0) { + /* Getting here means that the user function call or another + thread has already removed the old key from the dictionary. + This link is now an orphan. Since we don't want to leave the + cache in an inconsistent state, we don't restore the link. */ + assert(popresult == NULL); + Py_DECREF(link); + Py_DECREF(key); + return result; + } + /* Keep a reference to the old key and old result to prevent their ref counts from going to zero during the update. That will prevent potentially arbitrary object clean-up code (i.e. __del__) from running while we're still adjusting the links. */ + assert(popresult != NULL); oldkey = link->key; oldresult = link->result; @@ -1272,7 +1274,11 @@ lru_cache_dealloc(lru_cache_object *obj) static PyObject * lru_cache_call(lru_cache_object *self, PyObject *args, PyObject *kwds) { - return self->wrapper(self, args, kwds); + PyObject *result; + Py_BEGIN_CRITICAL_SECTION(self); + result = self->wrapper(self, args, kwds); + Py_END_CRITICAL_SECTION(); + return result; } static PyObject * @@ -1285,6 +1291,7 @@ lru_cache_descr_get(PyObject *self, PyObject *obj, PyObject *type) } /*[clinic input] +@critical_section _functools._lru_cache_wrapper.cache_info Report cache statistics @@ -1292,7 +1299,7 @@ Report cache statistics static PyObject * _functools__lru_cache_wrapper_cache_info_impl(PyObject *self) -/*[clinic end generated code: output=cc796a0b06dbd717 input=f05e5b6ebfe38645]*/ +/*[clinic end generated code: output=cc796a0b06dbd717 input=00e1acb31aa21ecc]*/ { lru_cache_object *_self = (lru_cache_object *) self; if (_self->maxsize == -1) { @@ -1306,6 +1313,7 @@ _functools__lru_cache_wrapper_cache_info_impl(PyObject *self) } /*[clinic input] +@critical_section _functools._lru_cache_wrapper.cache_clear Clear the cache and cache statistics @@ -1313,7 +1321,7 @@ Clear the cache and cache statistics static PyObject * _functools__lru_cache_wrapper_cache_clear_impl(PyObject *self) -/*[clinic end generated code: output=58423b35efc3e381 input=6ca59dba09b12584]*/ +/*[clinic end generated code: output=58423b35efc3e381 input=dfa33acbecf8b4b2]*/ { lru_cache_object *_self = (lru_cache_object *) self; lru_list_elem *list = lru_cache_unlink_list(_self); diff --git a/Modules/_gdbmmodule.c b/Modules/_gdbmmodule.c index eff36fd7fb669b..db868c18160fda 100644 --- a/Modules/_gdbmmodule.c +++ b/Modules/_gdbmmodule.c @@ -1,8 +1,12 @@ - /* GDBM module using dictionary interface */ /* Author: Anthony Baxter, after dbmmodule.c */ /* Doc strings: Mitch Chapman */ +// clinic/_gdbmmodule.c.h uses internal pycore_modsupport.h API +#ifndef Py_BUILD_CORE_BUILTIN +# define Py_BUILD_CORE_MODULE 1 +#endif + #include "Python.h" #include "gdbm.h" diff --git a/Modules/_hashopenssl.c b/Modules/_hashopenssl.c index ee6fb8b4b03643..0e230f332ff6cb 100644 --- a/Modules/_hashopenssl.c +++ b/Modules/_hashopenssl.c @@ -22,6 +22,7 @@ # define Py_BUILD_CORE_MODULE 1 #endif +#include #include "Python.h" #include "pycore_hashtable.h" #include "pycore_pyhash.h" // _Py_HashBytes() @@ -227,16 +228,16 @@ typedef struct { PyObject_HEAD EVP_MD_CTX *ctx; /* OpenSSL message digest context */ // Prevents undefined behavior via multiple threads entering the C API. - // The lock will be NULL before threaded access has been enabled. - PyThread_type_lock lock; /* OpenSSL context lock */ + bool use_mutex; + PyMutex mutex; /* OpenSSL context lock */ } EVPobject; typedef struct { PyObject_HEAD HMAC_CTX *ctx; /* OpenSSL hmac context */ // Prevents undefined behavior via multiple threads entering the C API. - // The lock will be NULL before threaded access has been enabled. - PyThread_type_lock lock; /* HMAC context lock */ + bool use_mutex; + PyMutex mutex; /* HMAC context lock */ } HMACobject; #include "clinic/_hashopenssl.c.h" @@ -414,8 +415,7 @@ newEVPobject(PyTypeObject *type) if (retval == NULL) { return NULL; } - - retval->lock = NULL; + HASHLIB_INIT_MUTEX(retval); retval->ctx = EVP_MD_CTX_new(); if (retval->ctx == NULL) { @@ -453,8 +453,6 @@ static void EVP_dealloc(EVPobject *self) { PyTypeObject *tp = Py_TYPE(self); - if (self->lock != NULL) - PyThread_free_lock(self->lock); EVP_MD_CTX_free(self->ctx); PyObject_Free(self); Py_DECREF(tp); @@ -582,16 +580,14 @@ EVP_update(EVPobject *self, PyObject *obj) GET_BUFFER_VIEW_OR_ERROUT(obj, &view); - if (self->lock == NULL && view.len >= HASHLIB_GIL_MINSIZE) { - self->lock = PyThread_allocate_lock(); - /* fail? lock = NULL and we fail over to non-threaded code. */ + if (!self->use_mutex && view.len >= HASHLIB_GIL_MINSIZE) { + self->use_mutex = true; } - - if (self->lock != NULL) { + if (self->use_mutex) { Py_BEGIN_ALLOW_THREADS - PyThread_acquire_lock(self->lock, 1); + PyMutex_Lock(&self->mutex); result = EVP_hash(self, view.buf, view.len); - PyThread_release_lock(self->lock); + PyMutex_Unlock(&self->mutex); Py_END_ALLOW_THREADS } else { result = EVP_hash(self, view.buf, view.len); @@ -1540,7 +1536,7 @@ _hashlib_hmac_new_impl(PyObject *module, Py_buffer *key, PyObject *msg_obj, } self->ctx = ctx; - self->lock = NULL; + HASHLIB_INIT_MUTEX(self); if ((msg_obj != NULL) && (msg_obj != Py_None)) { if (!_hmac_update(self, msg_obj)) @@ -1582,16 +1578,14 @@ _hmac_update(HMACobject *self, PyObject *obj) GET_BUFFER_VIEW_OR_ERROR(obj, &view, return 0); - if (self->lock == NULL && view.len >= HASHLIB_GIL_MINSIZE) { - self->lock = PyThread_allocate_lock(); - /* fail? lock = NULL and we fail over to non-threaded code. */ + if (!self->use_mutex && view.len >= HASHLIB_GIL_MINSIZE) { + self->use_mutex = true; } - - if (self->lock != NULL) { + if (self->use_mutex) { Py_BEGIN_ALLOW_THREADS - PyThread_acquire_lock(self->lock, 1); + PyMutex_Lock(&self->mutex); r = HMAC_Update(self->ctx, (const unsigned char*)view.buf, view.len); - PyThread_release_lock(self->lock); + PyMutex_Unlock(&self->mutex); Py_END_ALLOW_THREADS } else { r = HMAC_Update(self->ctx, (const unsigned char*)view.buf, view.len); @@ -1633,7 +1627,7 @@ _hashlib_HMAC_copy_impl(HMACobject *self) return NULL; } retval->ctx = ctx; - retval->lock = NULL; + HASHLIB_INIT_MUTEX(retval); return (PyObject *)retval; } @@ -1642,9 +1636,6 @@ static void _hmac_dealloc(HMACobject *self) { PyTypeObject *tp = Py_TYPE(self); - if (self->lock != NULL) { - PyThread_free_lock(self->lock); - } HMAC_CTX_free(self->ctx); PyObject_Free(self); Py_DECREF(tp); diff --git a/Modules/_io/_iomodule.c b/Modules/_io/_iomodule.c index 1a7920eebe0b61..173f5b55e5f732 100644 --- a/Modules/_io/_iomodule.c +++ b/Modules/_io/_iomodule.c @@ -8,9 +8,13 @@ */ #include "Python.h" -#include "_iomodule.h" -#include "pycore_pystate.h" // _PyInterpreterState_GET() +#include "pycore_abstract.h" // _PyNumber_Index() #include "pycore_initconfig.h" // _PyStatus_OK() +#include "pycore_long.h" // _PyLong_Sign() +#include "pycore_pyerrors.h" // _PyErr_ChainExceptions1() +#include "pycore_pystate.h" // _PyInterpreterState_GET() + +#include "_iomodule.h" #ifdef HAVE_SYS_TYPES_H #include diff --git a/Modules/_io/bufferedio.c b/Modules/_io/bufferedio.c index 0983a7bd151f40..f02207ace9f3d2 100644 --- a/Modules/_io/bufferedio.c +++ b/Modules/_io/bufferedio.c @@ -8,11 +8,11 @@ */ #include "Python.h" -#include "pycore_bytesobject.h" // _PyBytes_Join() -#include "pycore_call.h" // _PyObject_CallNoArgs() -#include "pycore_object.h" // _PyObject_GC_UNTRACK() -#include "pycore_pyerrors.h" // _Py_FatalErrorFormat() -#include "pycore_pylifecycle.h" // _Py_IsInterpreterFinalizing() +#include "pycore_bytesobject.h" // _PyBytes_Join() +#include "pycore_call.h" // _PyObject_CallNoArgs() +#include "pycore_object.h" // _PyObject_GC_UNTRACK() +#include "pycore_pyerrors.h" // _Py_FatalErrorFormat() +#include "pycore_pylifecycle.h" // _Py_IsInterpreterFinalizing() #include "_iomodule.h" @@ -82,6 +82,7 @@ _bufferediobase_readinto_generic(PyObject *self, Py_buffer *buffer, char readint } /*[clinic input] +@critical_section _io._BufferedIOBase.readinto buffer: Py_buffer(accept={rwbuffer}) / @@ -89,12 +90,13 @@ _io._BufferedIOBase.readinto static PyObject * _io__BufferedIOBase_readinto_impl(PyObject *self, Py_buffer *buffer) -/*[clinic end generated code: output=8c8cda6684af8038 input=00a6b9a38f29830a]*/ +/*[clinic end generated code: output=8c8cda6684af8038 input=5273d20db7f56e1a]*/ { return _bufferediobase_readinto_generic(self, buffer, 0); } /*[clinic input] +@critical_section _io._BufferedIOBase.readinto1 buffer: Py_buffer(accept={rwbuffer}) / @@ -102,7 +104,7 @@ _io._BufferedIOBase.readinto1 static PyObject * _io__BufferedIOBase_readinto1_impl(PyObject *self, Py_buffer *buffer) -/*[clinic end generated code: output=358623e4fd2b69d3 input=ebad75b4aadfb9be]*/ +/*[clinic end generated code: output=358623e4fd2b69d3 input=d6eb723dedcee654]*/ { return _bufferediobase_readinto_generic(self, buffer, 1); } @@ -431,12 +433,13 @@ buffered_dealloc(buffered *self) } /*[clinic input] +@critical_section _io._Buffered.__sizeof__ [clinic start generated code]*/ static PyObject * _io__Buffered___sizeof___impl(buffered *self) -/*[clinic end generated code: output=0231ef7f5053134e input=753c782d808d34df]*/ +/*[clinic end generated code: output=0231ef7f5053134e input=07a32d578073ea64]*/ { size_t res = _PyObject_SIZE(Py_TYPE(self)); if (self->buffer) { @@ -488,12 +491,13 @@ _io__Buffered__dealloc_warn(buffered *self, PyObject *source) /* Flush and close */ /*[clinic input] +@critical_section _io._Buffered.flush as _io__Buffered_simple_flush [clinic start generated code]*/ static PyObject * _io__Buffered_simple_flush_impl(buffered *self) -/*[clinic end generated code: output=29ebb3820db1bdfd input=f33ef045e7250767]*/ +/*[clinic end generated code: output=29ebb3820db1bdfd input=5248cb84a65f80bd]*/ { CHECK_INITIALIZED(self) return PyObject_CallMethodNoArgs(self->raw, &_Py_ID(flush)); @@ -513,20 +517,28 @@ buffered_closed(buffered *self) return closed; } +/*[clinic input] +@critical_section +@getter +_io._Buffered.closed +[clinic start generated code]*/ + static PyObject * -buffered_closed_get(buffered *self, void *context) +_io__Buffered_closed_get_impl(buffered *self) +/*[clinic end generated code: output=f08ce57290703a1a input=18eddefdfe4a3d2f]*/ { CHECK_INITIALIZED(self) return PyObject_GetAttr(self->raw, &_Py_ID(closed)); } /*[clinic input] +@critical_section _io._Buffered.close [clinic start generated code]*/ static PyObject * _io__Buffered_close_impl(buffered *self) -/*[clinic end generated code: output=7280b7b42033be0c input=d20b83d1ddd7d805]*/ +/*[clinic end generated code: output=7280b7b42033be0c input=56d95935b03fd326]*/ { PyObject *res = NULL; int r; @@ -553,17 +565,14 @@ _io__Buffered_close_impl(buffered *self) } /* flush() will most probably re-take the lock, so drop it first */ LEAVE_BUFFERED(self) - res = PyObject_CallMethodNoArgs((PyObject *)self, &_Py_ID(flush)); + r = _PyFile_Flush((PyObject *)self); if (!ENTER_BUFFERED(self)) { return NULL; } PyObject *exc = NULL; - if (res == NULL) { + if (r < 0) { exc = PyErr_GetRaisedException(); } - else { - Py_DECREF(res); - } res = PyObject_CallMethodNoArgs(self->raw, &_Py_ID(close)); @@ -586,19 +595,19 @@ _io__Buffered_close_impl(buffered *self) } /*[clinic input] +@critical_section _io._Buffered.detach [clinic start generated code]*/ static PyObject * _io__Buffered_detach_impl(buffered *self) -/*[clinic end generated code: output=dd0fc057b8b779f7 input=482762a345cc9f44]*/ +/*[clinic end generated code: output=dd0fc057b8b779f7 input=d4ef1828a678be37]*/ { - PyObject *raw, *res; + PyObject *raw; CHECK_INITIALIZED(self) - res = PyObject_CallMethodNoArgs((PyObject *)self, &_Py_ID(flush)); - if (res == NULL) + if (_PyFile_Flush((PyObject *)self) < 0) { return NULL; - Py_DECREF(res); + } raw = self->raw; self->raw = NULL; self->detached = 1; @@ -609,50 +618,68 @@ _io__Buffered_detach_impl(buffered *self) /* Inquiries */ /*[clinic input] +@critical_section _io._Buffered.seekable [clinic start generated code]*/ static PyObject * _io__Buffered_seekable_impl(buffered *self) -/*[clinic end generated code: output=90172abb5ceb6e8f input=7d35764f5fb5262b]*/ +/*[clinic end generated code: output=90172abb5ceb6e8f input=e3a4fc1d297b2fd3]*/ { CHECK_INITIALIZED(self) return PyObject_CallMethodNoArgs(self->raw, &_Py_ID(seekable)); } /*[clinic input] +@critical_section _io._Buffered.readable [clinic start generated code]*/ static PyObject * _io__Buffered_readable_impl(buffered *self) -/*[clinic end generated code: output=92afa07661ecb698 input=640619addb513b8b]*/ +/*[clinic end generated code: output=92afa07661ecb698 input=abe54107d59bca9a]*/ { CHECK_INITIALIZED(self) return PyObject_CallMethodNoArgs(self->raw, &_Py_ID(readable)); } /*[clinic input] +@critical_section _io._Buffered.writable [clinic start generated code]*/ static PyObject * _io__Buffered_writable_impl(buffered *self) -/*[clinic end generated code: output=4e3eee8d6f9d8552 input=b35ea396b2201554]*/ +/*[clinic end generated code: output=4e3eee8d6f9d8552 input=45eb76bf6a10e6f7]*/ { CHECK_INITIALIZED(self) return PyObject_CallMethodNoArgs(self->raw, &_Py_ID(writable)); } + +/*[clinic input] +@critical_section +@getter +_io._Buffered.name +[clinic start generated code]*/ + static PyObject * -buffered_name_get(buffered *self, void *context) +_io__Buffered_name_get_impl(buffered *self) +/*[clinic end generated code: output=d2adf384051d3d10 input=6b84a0e6126f545e]*/ { CHECK_INITIALIZED(self) return PyObject_GetAttr(self->raw, &_Py_ID(name)); } +/*[clinic input] +@critical_section +@getter +_io._Buffered.mode +[clinic start generated code]*/ + static PyObject * -buffered_mode_get(buffered *self, void *context) +_io__Buffered_mode_get_impl(buffered *self) +/*[clinic end generated code: output=0feb205748892fa4 input=0762d5e28542fd8c]*/ { CHECK_INITIALIZED(self) return PyObject_GetAttr(self->raw, &_Py_ID(mode)); @@ -661,24 +688,26 @@ buffered_mode_get(buffered *self, void *context) /* Lower-level APIs */ /*[clinic input] +@critical_section _io._Buffered.fileno [clinic start generated code]*/ static PyObject * _io__Buffered_fileno_impl(buffered *self) -/*[clinic end generated code: output=b717648d58a95ee3 input=768ea30b3f6314a7]*/ +/*[clinic end generated code: output=b717648d58a95ee3 input=1c4fead777bae20a]*/ { CHECK_INITIALIZED(self) return PyObject_CallMethodNoArgs(self->raw, &_Py_ID(fileno)); } /*[clinic input] +@critical_section _io._Buffered.isatty [clinic start generated code]*/ static PyObject * _io__Buffered_isatty_impl(buffered *self) -/*[clinic end generated code: output=c20e55caae67baea input=9ea007b11559bee4]*/ +/*[clinic end generated code: output=c20e55caae67baea input=e53d182d7e490e3a]*/ { CHECK_INITIALIZED(self) return PyObject_CallMethodNoArgs(self->raw, &_Py_ID(isatty)); @@ -884,12 +913,13 @@ buffered_flush_and_rewind_unlocked(buffered *self) } /*[clinic input] +@critical_section _io._Buffered.flush [clinic start generated code]*/ static PyObject * _io__Buffered_flush_impl(buffered *self) -/*[clinic end generated code: output=da2674ef1ce71f3a input=fda63444697c6bf4]*/ +/*[clinic end generated code: output=da2674ef1ce71f3a input=6b30de9f083419c2]*/ { PyObject *res; @@ -905,6 +935,7 @@ _io__Buffered_flush_impl(buffered *self) } /*[clinic input] +@critical_section _io._Buffered.peek size: Py_ssize_t = 0 / @@ -913,7 +944,7 @@ _io._Buffered.peek static PyObject * _io__Buffered_peek_impl(buffered *self, Py_ssize_t size) -/*[clinic end generated code: output=ba7a097ca230102b input=37ffb97d06ff4adb]*/ +/*[clinic end generated code: output=ba7a097ca230102b input=56733376f926d982]*/ { PyObject *res = NULL; @@ -937,6 +968,7 @@ _io__Buffered_peek_impl(buffered *self, Py_ssize_t size) } /*[clinic input] +@critical_section _io._Buffered.read size as n: Py_ssize_t(accept={int, NoneType}) = -1 / @@ -944,7 +976,7 @@ _io._Buffered.read static PyObject * _io__Buffered_read_impl(buffered *self, Py_ssize_t n) -/*[clinic end generated code: output=f41c78bb15b9bbe9 input=7df81e82e08a68a2]*/ +/*[clinic end generated code: output=f41c78bb15b9bbe9 input=bdb4b0425b295472]*/ { PyObject *res; @@ -978,6 +1010,7 @@ _io__Buffered_read_impl(buffered *self, Py_ssize_t n) } /*[clinic input] +@critical_section _io._Buffered.read1 size as n: Py_ssize_t = -1 / @@ -985,7 +1018,7 @@ _io._Buffered.read1 static PyObject * _io__Buffered_read1_impl(buffered *self, Py_ssize_t n) -/*[clinic end generated code: output=bcc4fb4e54d103a3 input=7d22de9630b61774]*/ +/*[clinic end generated code: output=bcc4fb4e54d103a3 input=3d0ad241aa52b36c]*/ { Py_ssize_t have, r; PyObject *res = NULL; @@ -1114,6 +1147,7 @@ _buffered_readinto_generic(buffered *self, Py_buffer *buffer, char readinto1) } /*[clinic input] +@critical_section _io._Buffered.readinto buffer: Py_buffer(accept={rwbuffer}) / @@ -1121,12 +1155,13 @@ _io._Buffered.readinto static PyObject * _io__Buffered_readinto_impl(buffered *self, Py_buffer *buffer) -/*[clinic end generated code: output=bcb376580b1d8170 input=ed6b98b7a20a3008]*/ +/*[clinic end generated code: output=bcb376580b1d8170 input=777c33e7adaa2bcd]*/ { return _buffered_readinto_generic(self, buffer, 0); } /*[clinic input] +@critical_section _io._Buffered.readinto1 buffer: Py_buffer(accept={rwbuffer}) / @@ -1134,7 +1169,7 @@ _io._Buffered.readinto1 static PyObject * _io__Buffered_readinto1_impl(buffered *self, Py_buffer *buffer) -/*[clinic end generated code: output=6e5c6ac5868205d6 input=4455c5d55fdf1687]*/ +/*[clinic end generated code: output=6e5c6ac5868205d6 input=ef03cc5fc92a6895]*/ { return _buffered_readinto_generic(self, buffer, 1); } @@ -1249,6 +1284,7 @@ _buffered_readline(buffered *self, Py_ssize_t limit) } /*[clinic input] +@critical_section _io._Buffered.readline size: Py_ssize_t(accept={int, NoneType}) = -1 / @@ -1256,7 +1292,7 @@ _io._Buffered.readline static PyObject * _io__Buffered_readline_impl(buffered *self, Py_ssize_t size) -/*[clinic end generated code: output=24dd2aa6e33be83c input=673b6240e315ef8a]*/ +/*[clinic end generated code: output=24dd2aa6e33be83c input=e81ca5abd4280776]*/ { CHECK_INITIALIZED(self) return _buffered_readline(self, size); @@ -1264,12 +1300,13 @@ _io__Buffered_readline_impl(buffered *self, Py_ssize_t size) /*[clinic input] +@critical_section _io._Buffered.tell [clinic start generated code]*/ static PyObject * _io__Buffered_tell_impl(buffered *self) -/*[clinic end generated code: output=386972ae84716c1e input=ad61e04a6b349573]*/ +/*[clinic end generated code: output=386972ae84716c1e input=ab12e67d8abcb42f]*/ { Py_off_t pos; @@ -1283,6 +1320,7 @@ _io__Buffered_tell_impl(buffered *self) } /*[clinic input] +@critical_section _io._Buffered.seek target as targetobj: object whence: int = 0 @@ -1291,7 +1329,7 @@ _io._Buffered.seek static PyObject * _io__Buffered_seek_impl(buffered *self, PyObject *targetobj, int whence) -/*[clinic end generated code: output=7ae0e8dc46efdefb input=a9c4920bfcba6163]*/ +/*[clinic end generated code: output=7ae0e8dc46efdefb input=b5a12be70e0ad07b]*/ { Py_off_t target, n; PyObject *res = NULL; @@ -1380,6 +1418,7 @@ _io__Buffered_seek_impl(buffered *self, PyObject *targetobj, int whence) } /*[clinic input] +@critical_section _io._Buffered.truncate cls: defining_class pos: object = None @@ -1388,7 +1427,7 @@ _io._Buffered.truncate static PyObject * _io__Buffered_truncate_impl(buffered *self, PyTypeObject *cls, PyObject *pos) -/*[clinic end generated code: output=fe3882fbffe79f1a input=f5b737d97d76303f]*/ +/*[clinic end generated code: output=fe3882fbffe79f1a input=e3cbf794575bd794]*/ { PyObject *res = NULL; @@ -2002,6 +2041,7 @@ _bufferedwriter_flush_unlocked(buffered *self) } /*[clinic input] +@critical_section _io.BufferedWriter.write buffer: Py_buffer / @@ -2009,7 +2049,7 @@ _io.BufferedWriter.write static PyObject * _io_BufferedWriter_write_impl(buffered *self, Py_buffer *buffer) -/*[clinic end generated code: output=7f8d1365759bfc6b input=dd87dd85fc7f8850]*/ +/*[clinic end generated code: output=7f8d1365759bfc6b input=6a9c041de0c337be]*/ { PyObject *res = NULL; Py_ssize_t written, avail, remaining; @@ -2486,9 +2526,9 @@ static PyMemberDef bufferedreader_members[] = { }; static PyGetSetDef bufferedreader_getset[] = { - {"closed", (getter)buffered_closed_get, NULL, NULL}, - {"name", (getter)buffered_name_get, NULL, NULL}, - {"mode", (getter)buffered_mode_get, NULL, NULL}, + _IO__BUFFERED_CLOSED_GETSETDEF + _IO__BUFFERED_NAME_GETSETDEF + _IO__BUFFERED_MODE_GETSETDEF {NULL} }; @@ -2546,9 +2586,9 @@ static PyMemberDef bufferedwriter_members[] = { }; static PyGetSetDef bufferedwriter_getset[] = { - {"closed", (getter)buffered_closed_get, NULL, NULL}, - {"name", (getter)buffered_name_get, NULL, NULL}, - {"mode", (getter)buffered_mode_get, NULL, NULL}, + _IO__BUFFERED_CLOSED_GETSETDEF + _IO__BUFFERED_NAME_GETSETDEF + _IO__BUFFERED_MODE_GETSETDEF {NULL} }; @@ -2664,9 +2704,9 @@ static PyMemberDef bufferedrandom_members[] = { }; static PyGetSetDef bufferedrandom_getset[] = { - {"closed", (getter)buffered_closed_get, NULL, NULL}, - {"name", (getter)buffered_name_get, NULL, NULL}, - {"mode", (getter)buffered_mode_get, NULL, NULL}, + _IO__BUFFERED_CLOSED_GETSETDEF + _IO__BUFFERED_NAME_GETSETDEF + _IO__BUFFERED_MODE_GETSETDEF {NULL} }; diff --git a/Modules/_io/bytesio.c b/Modules/_io/bytesio.c index 3ab503c9e3998d..4a15c8e841f25f 100644 --- a/Modules/_io/bytesio.c +++ b/Modules/_io/bytesio.c @@ -1,5 +1,7 @@ #include "Python.h" #include "pycore_object.h" +#include "pycore_sysmodule.h" // _PySys_GetSizeOf() + #include // offsetof() #include "_iomodule.h" @@ -124,12 +126,13 @@ unshare_buffer(bytesio *self, size_t size) static int resize_buffer(bytesio *self, size_t size) { + assert(self->buf != NULL); + assert(self->exports == 0); + /* Here, unsigned types are used to avoid dealing with signed integer overflow, which is undefined in C. */ size_t alloc = PyBytes_GET_SIZE(self->buf); - assert(self->buf != NULL); - /* For simplicity, stay in the range of the signed type. Anyway, Python doesn't allow strings to be longer than this. */ if (size > PY_SSIZE_T_MAX) @@ -987,7 +990,9 @@ static int bytesio_clear(bytesio *self) { Py_CLEAR(self->dict); - Py_CLEAR(self->buf); + if (self->exports == 0) { + Py_CLEAR(self->buf); + } return 0; } @@ -1072,7 +1077,7 @@ bytesiobuf_getbuffer(bytesiobuf *obj, Py_buffer *view, int flags) "bytesiobuf_getbuffer: view==NULL argument is obsolete"); return -1; } - if (SHARED_BUF(b)) { + if (b->exports == 0 && SHARED_BUF(b)) { if (unshare_buffer(b, b->string_size) < 0) return -1; } @@ -1092,13 +1097,6 @@ bytesiobuf_releasebuffer(bytesiobuf *obj, Py_buffer *view) b->exports--; } -static int -bytesiobuf_clear(bytesiobuf *self) -{ - Py_CLEAR(self->source); - return 0; -} - static int bytesiobuf_traverse(bytesiobuf *self, visitproc visit, void *arg) { @@ -1113,7 +1111,7 @@ bytesiobuf_dealloc(bytesiobuf *self) PyTypeObject *tp = Py_TYPE(self); /* bpo-31095: UnTrack is needed before calling any callbacks */ PyObject_GC_UnTrack(self); - (void)bytesiobuf_clear(self); + Py_CLEAR(self->source); tp->tp_free(self); Py_DECREF(tp); } @@ -1121,7 +1119,6 @@ bytesiobuf_dealloc(bytesiobuf *self) static PyType_Slot bytesiobuf_slots[] = { {Py_tp_dealloc, bytesiobuf_dealloc}, {Py_tp_traverse, bytesiobuf_traverse}, - {Py_tp_clear, bytesiobuf_clear}, // Buffer protocol {Py_bf_getbuffer, bytesiobuf_getbuffer}, diff --git a/Modules/_io/clinic/_iomodule.c.h b/Modules/_io/clinic/_iomodule.c.h index 6bb2f7f212a44d..112408a95df036 100644 --- a/Modules/_io/clinic/_iomodule.c.h +++ b/Modules/_io/clinic/_iomodule.c.h @@ -3,10 +3,10 @@ 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() +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() #endif - +#include "pycore_modsupport.h" // _PyArg_UnpackKeywords() PyDoc_STRVAR(_io_open__doc__, "open($module, /, file, mode=\'r\', buffering=-1, encoding=None,\n" @@ -202,7 +202,7 @@ _io_open(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kw } } if (args[2]) { - buffering = _PyLong_AsInt(args[2]); + buffering = PyLong_AsInt(args[2]); if (buffering == -1 && PyErr_Occurred()) { goto exit; } @@ -332,7 +332,7 @@ _io_text_encoding(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (nargs < 2) { goto skip_optional; } - stacklevel = _PyLong_AsInt(args[1]); + stacklevel = PyLong_AsInt(args[1]); if (stacklevel == -1 && PyErr_Occurred()) { goto exit; } @@ -404,4 +404,4 @@ _io_open_code(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObjec exit: return return_value; } -/*[clinic end generated code: output=6800c35366b1a5f3 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=5d60f4e778a600a4 input=a9049054013a1b77]*/ diff --git a/Modules/_io/clinic/bufferedio.c.h b/Modules/_io/clinic/bufferedio.c.h index 4f40fdadf8ec85..d5bec5f71f5be8 100644 --- a/Modules/_io/clinic/bufferedio.c.h +++ b/Modules/_io/clinic/bufferedio.c.h @@ -3,10 +3,12 @@ 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() +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() #endif - +#include "pycore_abstract.h" // _PyNumber_Index() +#include "pycore_critical_section.h"// Py_BEGIN_CRITICAL_SECTION() +#include "pycore_modsupport.h" // _PyArg_BadArgument() PyDoc_STRVAR(_io__BufferedIOBase_readinto__doc__, "readinto($self, buffer, /)\n" @@ -26,15 +28,12 @@ _io__BufferedIOBase_readinto(PyObject *self, PyObject *arg) Py_buffer buffer = {NULL, NULL}; if (PyObject_GetBuffer(arg, &buffer, PyBUF_WRITABLE) < 0) { - PyErr_Clear(); _PyArg_BadArgument("readinto", "argument", "read-write bytes-like object", arg); goto exit; } - if (!PyBuffer_IsContiguous(&buffer, 'C')) { - _PyArg_BadArgument("readinto", "argument", "contiguous buffer", arg); - goto exit; - } + Py_BEGIN_CRITICAL_SECTION(self); return_value = _io__BufferedIOBase_readinto_impl(self, &buffer); + Py_END_CRITICAL_SECTION(); exit: /* Cleanup for buffer */ @@ -63,15 +62,12 @@ _io__BufferedIOBase_readinto1(PyObject *self, PyObject *arg) Py_buffer buffer = {NULL, NULL}; if (PyObject_GetBuffer(arg, &buffer, PyBUF_WRITABLE) < 0) { - PyErr_Clear(); _PyArg_BadArgument("readinto1", "argument", "read-write bytes-like object", arg); goto exit; } - if (!PyBuffer_IsContiguous(&buffer, 'C')) { - _PyArg_BadArgument("readinto1", "argument", "contiguous buffer", arg); - goto exit; - } + Py_BEGIN_CRITICAL_SECTION(self); return_value = _io__BufferedIOBase_readinto1_impl(self, &buffer); + Py_END_CRITICAL_SECTION(); exit: /* Cleanup for buffer */ @@ -162,7 +158,7 @@ _io__BufferedIOBase_read(PyObject *self, PyTypeObject *cls, PyObject *const *arg if (nargs < 1) { goto skip_optional_posonly; } - size = _PyLong_AsInt(args[0]); + size = PyLong_AsInt(args[0]); if (size == -1 && PyErr_Occurred()) { goto exit; } @@ -216,7 +212,7 @@ _io__BufferedIOBase_read1(PyObject *self, PyTypeObject *cls, PyObject *const *ar if (nargs < 1) { goto skip_optional_posonly; } - size = _PyLong_AsInt(args[0]); + size = PyLong_AsInt(args[0]); if (size == -1 && PyErr_Occurred()) { goto exit; } @@ -291,7 +287,13 @@ _io__Buffered___sizeof___impl(buffered *self); static PyObject * _io__Buffered___sizeof__(buffered *self, PyObject *Py_UNUSED(ignored)) { - return _io__Buffered___sizeof___impl(self); + PyObject *return_value = NULL; + + Py_BEGIN_CRITICAL_SECTION(self); + return_value = _io__Buffered___sizeof___impl(self); + Py_END_CRITICAL_SECTION(); + + return return_value; } PyDoc_STRVAR(_io__Buffered__dealloc_warn__doc__, @@ -316,7 +318,40 @@ _io__Buffered_simple_flush_impl(buffered *self); static PyObject * _io__Buffered_simple_flush(buffered *self, PyObject *Py_UNUSED(ignored)) { - return _io__Buffered_simple_flush_impl(self); + PyObject *return_value = NULL; + + Py_BEGIN_CRITICAL_SECTION(self); + return_value = _io__Buffered_simple_flush_impl(self); + Py_END_CRITICAL_SECTION(); + + return return_value; +} + +#if defined(_io__Buffered_closed_HAS_DOCSTR) +# define _io__Buffered_closed_DOCSTR _io__Buffered_closed__doc__ +#else +# define _io__Buffered_closed_DOCSTR NULL +#endif +#if defined(_IO__BUFFERED_CLOSED_GETSETDEF) +# undef _IO__BUFFERED_CLOSED_GETSETDEF +# define _IO__BUFFERED_CLOSED_GETSETDEF {"closed", (getter)_io__Buffered_closed_get, (setter)_io__Buffered_closed_set, _io__Buffered_closed_DOCSTR}, +#else +# define _IO__BUFFERED_CLOSED_GETSETDEF {"closed", (getter)_io__Buffered_closed_get, NULL, _io__Buffered_closed_DOCSTR}, +#endif + +static PyObject * +_io__Buffered_closed_get_impl(buffered *self); + +static PyObject * +_io__Buffered_closed_get(buffered *self, void *Py_UNUSED(context)) +{ + PyObject *return_value = NULL; + + Py_BEGIN_CRITICAL_SECTION(self); + return_value = _io__Buffered_closed_get_impl(self); + Py_END_CRITICAL_SECTION(); + + return return_value; } PyDoc_STRVAR(_io__Buffered_close__doc__, @@ -333,7 +368,13 @@ _io__Buffered_close_impl(buffered *self); static PyObject * _io__Buffered_close(buffered *self, PyObject *Py_UNUSED(ignored)) { - return _io__Buffered_close_impl(self); + PyObject *return_value = NULL; + + Py_BEGIN_CRITICAL_SECTION(self); + return_value = _io__Buffered_close_impl(self); + Py_END_CRITICAL_SECTION(); + + return return_value; } PyDoc_STRVAR(_io__Buffered_detach__doc__, @@ -350,7 +391,13 @@ _io__Buffered_detach_impl(buffered *self); static PyObject * _io__Buffered_detach(buffered *self, PyObject *Py_UNUSED(ignored)) { - return _io__Buffered_detach_impl(self); + PyObject *return_value = NULL; + + Py_BEGIN_CRITICAL_SECTION(self); + return_value = _io__Buffered_detach_impl(self); + Py_END_CRITICAL_SECTION(); + + return return_value; } PyDoc_STRVAR(_io__Buffered_seekable__doc__, @@ -367,7 +414,13 @@ _io__Buffered_seekable_impl(buffered *self); static PyObject * _io__Buffered_seekable(buffered *self, PyObject *Py_UNUSED(ignored)) { - return _io__Buffered_seekable_impl(self); + PyObject *return_value = NULL; + + Py_BEGIN_CRITICAL_SECTION(self); + return_value = _io__Buffered_seekable_impl(self); + Py_END_CRITICAL_SECTION(); + + return return_value; } PyDoc_STRVAR(_io__Buffered_readable__doc__, @@ -384,7 +437,13 @@ _io__Buffered_readable_impl(buffered *self); static PyObject * _io__Buffered_readable(buffered *self, PyObject *Py_UNUSED(ignored)) { - return _io__Buffered_readable_impl(self); + PyObject *return_value = NULL; + + Py_BEGIN_CRITICAL_SECTION(self); + return_value = _io__Buffered_readable_impl(self); + Py_END_CRITICAL_SECTION(); + + return return_value; } PyDoc_STRVAR(_io__Buffered_writable__doc__, @@ -401,7 +460,67 @@ _io__Buffered_writable_impl(buffered *self); static PyObject * _io__Buffered_writable(buffered *self, PyObject *Py_UNUSED(ignored)) { - return _io__Buffered_writable_impl(self); + PyObject *return_value = NULL; + + Py_BEGIN_CRITICAL_SECTION(self); + return_value = _io__Buffered_writable_impl(self); + Py_END_CRITICAL_SECTION(); + + return return_value; +} + +#if defined(_io__Buffered_name_HAS_DOCSTR) +# define _io__Buffered_name_DOCSTR _io__Buffered_name__doc__ +#else +# define _io__Buffered_name_DOCSTR NULL +#endif +#if defined(_IO__BUFFERED_NAME_GETSETDEF) +# undef _IO__BUFFERED_NAME_GETSETDEF +# define _IO__BUFFERED_NAME_GETSETDEF {"name", (getter)_io__Buffered_name_get, (setter)_io__Buffered_name_set, _io__Buffered_name_DOCSTR}, +#else +# define _IO__BUFFERED_NAME_GETSETDEF {"name", (getter)_io__Buffered_name_get, NULL, _io__Buffered_name_DOCSTR}, +#endif + +static PyObject * +_io__Buffered_name_get_impl(buffered *self); + +static PyObject * +_io__Buffered_name_get(buffered *self, void *Py_UNUSED(context)) +{ + PyObject *return_value = NULL; + + Py_BEGIN_CRITICAL_SECTION(self); + return_value = _io__Buffered_name_get_impl(self); + Py_END_CRITICAL_SECTION(); + + return return_value; +} + +#if defined(_io__Buffered_mode_HAS_DOCSTR) +# define _io__Buffered_mode_DOCSTR _io__Buffered_mode__doc__ +#else +# define _io__Buffered_mode_DOCSTR NULL +#endif +#if defined(_IO__BUFFERED_MODE_GETSETDEF) +# undef _IO__BUFFERED_MODE_GETSETDEF +# define _IO__BUFFERED_MODE_GETSETDEF {"mode", (getter)_io__Buffered_mode_get, (setter)_io__Buffered_mode_set, _io__Buffered_mode_DOCSTR}, +#else +# define _IO__BUFFERED_MODE_GETSETDEF {"mode", (getter)_io__Buffered_mode_get, NULL, _io__Buffered_mode_DOCSTR}, +#endif + +static PyObject * +_io__Buffered_mode_get_impl(buffered *self); + +static PyObject * +_io__Buffered_mode_get(buffered *self, void *Py_UNUSED(context)) +{ + PyObject *return_value = NULL; + + Py_BEGIN_CRITICAL_SECTION(self); + return_value = _io__Buffered_mode_get_impl(self); + Py_END_CRITICAL_SECTION(); + + return return_value; } PyDoc_STRVAR(_io__Buffered_fileno__doc__, @@ -418,7 +537,13 @@ _io__Buffered_fileno_impl(buffered *self); static PyObject * _io__Buffered_fileno(buffered *self, PyObject *Py_UNUSED(ignored)) { - return _io__Buffered_fileno_impl(self); + PyObject *return_value = NULL; + + Py_BEGIN_CRITICAL_SECTION(self); + return_value = _io__Buffered_fileno_impl(self); + Py_END_CRITICAL_SECTION(); + + return return_value; } PyDoc_STRVAR(_io__Buffered_isatty__doc__, @@ -435,7 +560,13 @@ _io__Buffered_isatty_impl(buffered *self); static PyObject * _io__Buffered_isatty(buffered *self, PyObject *Py_UNUSED(ignored)) { - return _io__Buffered_isatty_impl(self); + PyObject *return_value = NULL; + + Py_BEGIN_CRITICAL_SECTION(self); + return_value = _io__Buffered_isatty_impl(self); + Py_END_CRITICAL_SECTION(); + + return return_value; } PyDoc_STRVAR(_io__Buffered_flush__doc__, @@ -452,7 +583,13 @@ _io__Buffered_flush_impl(buffered *self); static PyObject * _io__Buffered_flush(buffered *self, PyObject *Py_UNUSED(ignored)) { - return _io__Buffered_flush_impl(self); + PyObject *return_value = NULL; + + Py_BEGIN_CRITICAL_SECTION(self); + return_value = _io__Buffered_flush_impl(self); + Py_END_CRITICAL_SECTION(); + + return return_value; } PyDoc_STRVAR(_io__Buffered_peek__doc__, @@ -491,7 +628,9 @@ _io__Buffered_peek(buffered *self, PyObject *const *args, Py_ssize_t nargs) size = ival; } skip_optional: + Py_BEGIN_CRITICAL_SECTION(self); return_value = _io__Buffered_peek_impl(self, size); + Py_END_CRITICAL_SECTION(); exit: return return_value; @@ -524,7 +663,9 @@ _io__Buffered_read(buffered *self, PyObject *const *args, Py_ssize_t nargs) goto exit; } skip_optional: + Py_BEGIN_CRITICAL_SECTION(self); return_value = _io__Buffered_read_impl(self, n); + Py_END_CRITICAL_SECTION(); exit: return return_value; @@ -566,7 +707,9 @@ _io__Buffered_read1(buffered *self, PyObject *const *args, Py_ssize_t nargs) n = ival; } skip_optional: + Py_BEGIN_CRITICAL_SECTION(self); return_value = _io__Buffered_read1_impl(self, n); + Py_END_CRITICAL_SECTION(); exit: return return_value; @@ -590,15 +733,12 @@ _io__Buffered_readinto(buffered *self, PyObject *arg) Py_buffer buffer = {NULL, NULL}; if (PyObject_GetBuffer(arg, &buffer, PyBUF_WRITABLE) < 0) { - PyErr_Clear(); _PyArg_BadArgument("readinto", "argument", "read-write bytes-like object", arg); goto exit; } - if (!PyBuffer_IsContiguous(&buffer, 'C')) { - _PyArg_BadArgument("readinto", "argument", "contiguous buffer", arg); - goto exit; - } + Py_BEGIN_CRITICAL_SECTION(self); return_value = _io__Buffered_readinto_impl(self, &buffer); + Py_END_CRITICAL_SECTION(); exit: /* Cleanup for buffer */ @@ -627,15 +767,12 @@ _io__Buffered_readinto1(buffered *self, PyObject *arg) Py_buffer buffer = {NULL, NULL}; if (PyObject_GetBuffer(arg, &buffer, PyBUF_WRITABLE) < 0) { - PyErr_Clear(); _PyArg_BadArgument("readinto1", "argument", "read-write bytes-like object", arg); goto exit; } - if (!PyBuffer_IsContiguous(&buffer, 'C')) { - _PyArg_BadArgument("readinto1", "argument", "contiguous buffer", arg); - goto exit; - } + Py_BEGIN_CRITICAL_SECTION(self); return_value = _io__Buffered_readinto1_impl(self, &buffer); + Py_END_CRITICAL_SECTION(); exit: /* Cleanup for buffer */ @@ -673,7 +810,9 @@ _io__Buffered_readline(buffered *self, PyObject *const *args, Py_ssize_t nargs) goto exit; } skip_optional: + Py_BEGIN_CRITICAL_SECTION(self); return_value = _io__Buffered_readline_impl(self, size); + Py_END_CRITICAL_SECTION(); exit: return return_value; @@ -693,7 +832,13 @@ _io__Buffered_tell_impl(buffered *self); static PyObject * _io__Buffered_tell(buffered *self, PyObject *Py_UNUSED(ignored)) { - return _io__Buffered_tell_impl(self); + PyObject *return_value = NULL; + + Py_BEGIN_CRITICAL_SECTION(self); + return_value = _io__Buffered_tell_impl(self); + Py_END_CRITICAL_SECTION(); + + return return_value; } PyDoc_STRVAR(_io__Buffered_seek__doc__, @@ -721,12 +866,14 @@ _io__Buffered_seek(buffered *self, PyObject *const *args, Py_ssize_t nargs) if (nargs < 2) { goto skip_optional; } - whence = _PyLong_AsInt(args[1]); + whence = PyLong_AsInt(args[1]); if (whence == -1 && PyErr_Occurred()) { goto exit; } skip_optional: + Py_BEGIN_CRITICAL_SECTION(self); return_value = _io__Buffered_seek_impl(self, targetobj, whence); + Py_END_CRITICAL_SECTION(); exit: return return_value; @@ -772,7 +919,9 @@ _io__Buffered_truncate(buffered *self, PyTypeObject *cls, PyObject *const *args, } pos = args[0]; skip_optional_posonly: + Py_BEGIN_CRITICAL_SECTION(self); return_value = _io__Buffered_truncate_impl(self, cls, pos); + Py_END_CRITICAL_SECTION(); exit: return return_value; @@ -948,11 +1097,9 @@ _io_BufferedWriter_write(buffered *self, PyObject *arg) if (PyObject_GetBuffer(arg, &buffer, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&buffer, 'C')) { - _PyArg_BadArgument("write", "argument", "contiguous buffer", arg); - goto exit; - } + Py_BEGIN_CRITICAL_SECTION(self); return_value = _io_BufferedWriter_write_impl(self, &buffer); + Py_END_CRITICAL_SECTION(); exit: /* Cleanup for buffer */ @@ -1098,4 +1245,4 @@ _io_BufferedRandom___init__(PyObject *self, PyObject *args, PyObject *kwargs) exit: return return_value; } -/*[clinic end generated code: output=b7ddf84a5bc2bf34 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=442b05b9a117df6c input=a9049054013a1b77]*/ diff --git a/Modules/_io/clinic/bytesio.c.h b/Modules/_io/clinic/bytesio.c.h index 9550c8728c251e..37023e49087647 100644 --- a/Modules/_io/clinic/bytesio.c.h +++ b/Modules/_io/clinic/bytesio.c.h @@ -3,10 +3,11 @@ 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() +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() #endif - +#include "pycore_abstract.h" // _Py_convert_optional_to_ssize_t() +#include "pycore_modsupport.h" // _PyArg_CheckPositional() PyDoc_STRVAR(_io_BytesIO_readable__doc__, "readable($self, /)\n" @@ -328,14 +329,9 @@ _io_BytesIO_readinto(bytesio *self, PyObject *arg) Py_buffer buffer = {NULL, NULL}; if (PyObject_GetBuffer(arg, &buffer, PyBUF_WRITABLE) < 0) { - PyErr_Clear(); _PyArg_BadArgument("readinto", "argument", "read-write bytes-like object", arg); goto exit; } - if (!PyBuffer_IsContiguous(&buffer, 'C')) { - _PyArg_BadArgument("readinto", "argument", "contiguous buffer", arg); - goto exit; - } return_value = _io_BytesIO_readinto_impl(self, &buffer); exit: @@ -427,7 +423,7 @@ _io_BytesIO_seek(bytesio *self, PyObject *const *args, Py_ssize_t nargs) if (nargs < 2) { goto skip_optional; } - whence = _PyLong_AsInt(args[1]); + whence = PyLong_AsInt(args[1]); if (whence == -1 && PyErr_Occurred()) { goto exit; } @@ -538,4 +534,4 @@ _io_BytesIO___init__(PyObject *self, PyObject *args, PyObject *kwargs) exit: return return_value; } -/*[clinic end generated code: output=098584d485420b65 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=2be0e05a8871b7e2 input=a9049054013a1b77]*/ diff --git a/Modules/_io/clinic/fileio.c.h b/Modules/_io/clinic/fileio.c.h index 33a37a389d223d..cf3ba28b066cf7 100644 --- a/Modules/_io/clinic/fileio.c.h +++ b/Modules/_io/clinic/fileio.c.h @@ -3,10 +3,11 @@ 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() +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() #endif - +#include "pycore_abstract.h" // _Py_convert_optional_to_ssize_t() +#include "pycore_modsupport.h" // _PyArg_UnpackKeywords() PyDoc_STRVAR(_io_FileIO_close__doc__, "close($self, /)\n" @@ -245,14 +246,9 @@ _io_FileIO_readinto(fileio *self, PyTypeObject *cls, PyObject *const *args, Py_s goto exit; } if (PyObject_GetBuffer(args[0], &buffer, PyBUF_WRITABLE) < 0) { - PyErr_Clear(); _PyArg_BadArgument("readinto", "argument 1", "read-write bytes-like object", args[0]); goto exit; } - if (!PyBuffer_IsContiguous(&buffer, 'C')) { - _PyArg_BadArgument("readinto", "argument 1", "contiguous buffer", args[0]); - goto exit; - } return_value = _io_FileIO_readinto_impl(self, cls, &buffer); exit: @@ -381,10 +377,6 @@ _io_FileIO_write(fileio *self, PyTypeObject *cls, PyObject *const *args, Py_ssiz if (PyObject_GetBuffer(args[0], &b, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&b, 'C')) { - _PyArg_BadArgument("write", "argument 1", "contiguous buffer", args[0]); - goto exit; - } return_value = _io_FileIO_write_impl(self, cls, &b); exit: @@ -430,7 +422,7 @@ _io_FileIO_seek(fileio *self, PyObject *const *args, Py_ssize_t nargs) if (nargs < 2) { goto skip_optional; } - whence = _PyLong_AsInt(args[1]); + whence = PyLong_AsInt(args[1]); if (whence == -1 && PyErr_Occurred()) { goto exit; } @@ -536,4 +528,4 @@ _io_FileIO_isatty(fileio *self, PyObject *Py_UNUSED(ignored)) #ifndef _IO_FILEIO_TRUNCATE_METHODDEF #define _IO_FILEIO_TRUNCATE_METHODDEF #endif /* !defined(_IO_FILEIO_TRUNCATE_METHODDEF) */ -/*[clinic end generated code: output=bef47b31b644996a input=a9049054013a1b77]*/ +/*[clinic end generated code: output=1c0f4a36f76b0c6a input=a9049054013a1b77]*/ diff --git a/Modules/_io/clinic/iobase.c.h b/Modules/_io/clinic/iobase.c.h index 773e0010477053..6bdfa1444015ac 100644 --- a/Modules/_io/clinic/iobase.c.h +++ b/Modules/_io/clinic/iobase.c.h @@ -2,11 +2,8 @@ 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 - +#include "pycore_abstract.h" // _Py_convert_optional_to_ssize_t() +#include "pycore_modsupport.h" // _PyArg_UnpackKeywords() PyDoc_STRVAR(_io__IOBase_seek__doc__, "seek($self, offset, whence=os.SEEK_SET, /)\n" @@ -14,6 +11,11 @@ PyDoc_STRVAR(_io__IOBase_seek__doc__, "\n" "Change the stream position to the given byte offset.\n" "\n" +" offset\n" +" The stream position, relative to \'whence\'.\n" +" whence\n" +" The relative position to seek from.\n" +"\n" "The offset is interpreted relative to the position indicated by whence.\n" "Values for whence are:\n" "\n" @@ -55,14 +57,14 @@ _io__IOBase_seek(PyObject *self, PyTypeObject *cls, PyObject *const *args, Py_ss if (!args) { goto exit; } - offset = _PyLong_AsInt(args[0]); + offset = PyLong_AsInt(args[0]); if (offset == -1 && PyErr_Occurred()) { goto exit; } if (nargs < 2) { goto skip_optional_posonly; } - whence = _PyLong_AsInt(args[1]); + whence = PyLong_AsInt(args[1]); if (whence == -1 && PyErr_Occurred()) { goto exit; } @@ -436,4 +438,4 @@ _io__RawIOBase_readall(PyObject *self, PyObject *Py_UNUSED(ignored)) { return _io__RawIOBase_readall_impl(self); } -/*[clinic end generated code: output=301b22f8f75ce3dc input=a9049054013a1b77]*/ +/*[clinic end generated code: output=5a22bc5db0ecaacb input=a9049054013a1b77]*/ diff --git a/Modules/_io/clinic/stringio.c.h b/Modules/_io/clinic/stringio.c.h index d495dd10c16330..6bdb2181985f7d 100644 --- a/Modules/_io/clinic/stringio.c.h +++ b/Modules/_io/clinic/stringio.c.h @@ -3,10 +3,12 @@ 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() +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() #endif - +#include "pycore_abstract.h" // _Py_convert_optional_to_ssize_t() +#include "pycore_critical_section.h"// Py_BEGIN_CRITICAL_SECTION() +#include "pycore_modsupport.h" // _PyArg_CheckPositional() PyDoc_STRVAR(_io_StringIO_getvalue__doc__, "getvalue($self, /)\n" @@ -23,7 +25,13 @@ _io_StringIO_getvalue_impl(stringio *self); static PyObject * _io_StringIO_getvalue(stringio *self, PyObject *Py_UNUSED(ignored)) { - return _io_StringIO_getvalue_impl(self); + PyObject *return_value = NULL; + + Py_BEGIN_CRITICAL_SECTION(self); + return_value = _io_StringIO_getvalue_impl(self); + Py_END_CRITICAL_SECTION(); + + return return_value; } PyDoc_STRVAR(_io_StringIO_tell__doc__, @@ -41,7 +49,13 @@ _io_StringIO_tell_impl(stringio *self); static PyObject * _io_StringIO_tell(stringio *self, PyObject *Py_UNUSED(ignored)) { - return _io_StringIO_tell_impl(self); + PyObject *return_value = NULL; + + Py_BEGIN_CRITICAL_SECTION(self); + return_value = _io_StringIO_tell_impl(self); + Py_END_CRITICAL_SECTION(); + + return return_value; } PyDoc_STRVAR(_io_StringIO_read__doc__, @@ -75,7 +89,9 @@ _io_StringIO_read(stringio *self, PyObject *const *args, Py_ssize_t nargs) goto exit; } skip_optional: + Py_BEGIN_CRITICAL_SECTION(self); return_value = _io_StringIO_read_impl(self, size); + Py_END_CRITICAL_SECTION(); exit: return return_value; @@ -111,7 +127,9 @@ _io_StringIO_readline(stringio *self, PyObject *const *args, Py_ssize_t nargs) goto exit; } skip_optional: + Py_BEGIN_CRITICAL_SECTION(self); return_value = _io_StringIO_readline_impl(self, size); + Py_END_CRITICAL_SECTION(); exit: return return_value; @@ -149,7 +167,9 @@ _io_StringIO_truncate(stringio *self, PyObject *const *args, Py_ssize_t nargs) goto exit; } skip_optional: + Py_BEGIN_CRITICAL_SECTION(self); return_value = _io_StringIO_truncate_impl(self, size); + Py_END_CRITICAL_SECTION(); exit: return return_value; @@ -198,12 +218,14 @@ _io_StringIO_seek(stringio *self, PyObject *const *args, Py_ssize_t nargs) if (nargs < 2) { goto skip_optional; } - whence = _PyLong_AsInt(args[1]); + whence = PyLong_AsInt(args[1]); if (whence == -1 && PyErr_Occurred()) { goto exit; } skip_optional: + Py_BEGIN_CRITICAL_SECTION(self); return_value = _io_StringIO_seek_impl(self, pos, whence); + Py_END_CRITICAL_SECTION(); exit: return return_value; @@ -221,6 +243,21 @@ PyDoc_STRVAR(_io_StringIO_write__doc__, #define _IO_STRINGIO_WRITE_METHODDEF \ {"write", (PyCFunction)_io_StringIO_write, METH_O, _io_StringIO_write__doc__}, +static PyObject * +_io_StringIO_write_impl(stringio *self, PyObject *obj); + +static PyObject * +_io_StringIO_write(stringio *self, PyObject *obj) +{ + PyObject *return_value = NULL; + + Py_BEGIN_CRITICAL_SECTION(self); + return_value = _io_StringIO_write_impl(self, obj); + Py_END_CRITICAL_SECTION(); + + return return_value; +} + PyDoc_STRVAR(_io_StringIO_close__doc__, "close($self, /)\n" "--\n" @@ -241,7 +278,13 @@ _io_StringIO_close_impl(stringio *self); static PyObject * _io_StringIO_close(stringio *self, PyObject *Py_UNUSED(ignored)) { - return _io_StringIO_close_impl(self); + PyObject *return_value = NULL; + + Py_BEGIN_CRITICAL_SECTION(self); + return_value = _io_StringIO_close_impl(self); + Py_END_CRITICAL_SECTION(); + + return return_value; } PyDoc_STRVAR(_io_StringIO___init____doc__, @@ -329,7 +372,13 @@ _io_StringIO_readable_impl(stringio *self); static PyObject * _io_StringIO_readable(stringio *self, PyObject *Py_UNUSED(ignored)) { - return _io_StringIO_readable_impl(self); + PyObject *return_value = NULL; + + Py_BEGIN_CRITICAL_SECTION(self); + return_value = _io_StringIO_readable_impl(self); + Py_END_CRITICAL_SECTION(); + + return return_value; } PyDoc_STRVAR(_io_StringIO_writable__doc__, @@ -347,7 +396,13 @@ _io_StringIO_writable_impl(stringio *self); static PyObject * _io_StringIO_writable(stringio *self, PyObject *Py_UNUSED(ignored)) { - return _io_StringIO_writable_impl(self); + PyObject *return_value = NULL; + + Py_BEGIN_CRITICAL_SECTION(self); + return_value = _io_StringIO_writable_impl(self); + Py_END_CRITICAL_SECTION(); + + return return_value; } PyDoc_STRVAR(_io_StringIO_seekable__doc__, @@ -365,6 +420,139 @@ _io_StringIO_seekable_impl(stringio *self); static PyObject * _io_StringIO_seekable(stringio *self, PyObject *Py_UNUSED(ignored)) { - return _io_StringIO_seekable_impl(self); + PyObject *return_value = NULL; + + Py_BEGIN_CRITICAL_SECTION(self); + return_value = _io_StringIO_seekable_impl(self); + Py_END_CRITICAL_SECTION(); + + return return_value; +} + +PyDoc_STRVAR(_io_StringIO___getstate____doc__, +"__getstate__($self, /)\n" +"--\n" +"\n"); + +#define _IO_STRINGIO___GETSTATE___METHODDEF \ + {"__getstate__", (PyCFunction)_io_StringIO___getstate__, METH_NOARGS, _io_StringIO___getstate____doc__}, + +static PyObject * +_io_StringIO___getstate___impl(stringio *self); + +static PyObject * +_io_StringIO___getstate__(stringio *self, PyObject *Py_UNUSED(ignored)) +{ + PyObject *return_value = NULL; + + Py_BEGIN_CRITICAL_SECTION(self); + return_value = _io_StringIO___getstate___impl(self); + Py_END_CRITICAL_SECTION(); + + return return_value; +} + +PyDoc_STRVAR(_io_StringIO___setstate____doc__, +"__setstate__($self, state, /)\n" +"--\n" +"\n"); + +#define _IO_STRINGIO___SETSTATE___METHODDEF \ + {"__setstate__", (PyCFunction)_io_StringIO___setstate__, METH_O, _io_StringIO___setstate____doc__}, + +static PyObject * +_io_StringIO___setstate___impl(stringio *self, PyObject *state); + +static PyObject * +_io_StringIO___setstate__(stringio *self, PyObject *state) +{ + PyObject *return_value = NULL; + + Py_BEGIN_CRITICAL_SECTION(self); + return_value = _io_StringIO___setstate___impl(self, state); + Py_END_CRITICAL_SECTION(); + + return return_value; +} + +#if defined(_io_StringIO_closed_HAS_DOCSTR) +# define _io_StringIO_closed_DOCSTR _io_StringIO_closed__doc__ +#else +# define _io_StringIO_closed_DOCSTR NULL +#endif +#if defined(_IO_STRINGIO_CLOSED_GETSETDEF) +# undef _IO_STRINGIO_CLOSED_GETSETDEF +# define _IO_STRINGIO_CLOSED_GETSETDEF {"closed", (getter)_io_StringIO_closed_get, (setter)_io_StringIO_closed_set, _io_StringIO_closed_DOCSTR}, +#else +# define _IO_STRINGIO_CLOSED_GETSETDEF {"closed", (getter)_io_StringIO_closed_get, NULL, _io_StringIO_closed_DOCSTR}, +#endif + +static PyObject * +_io_StringIO_closed_get_impl(stringio *self); + +static PyObject * +_io_StringIO_closed_get(stringio *self, void *Py_UNUSED(context)) +{ + PyObject *return_value = NULL; + + Py_BEGIN_CRITICAL_SECTION(self); + return_value = _io_StringIO_closed_get_impl(self); + Py_END_CRITICAL_SECTION(); + + return return_value; +} + +#if defined(_io_StringIO_line_buffering_HAS_DOCSTR) +# define _io_StringIO_line_buffering_DOCSTR _io_StringIO_line_buffering__doc__ +#else +# define _io_StringIO_line_buffering_DOCSTR NULL +#endif +#if defined(_IO_STRINGIO_LINE_BUFFERING_GETSETDEF) +# undef _IO_STRINGIO_LINE_BUFFERING_GETSETDEF +# define _IO_STRINGIO_LINE_BUFFERING_GETSETDEF {"line_buffering", (getter)_io_StringIO_line_buffering_get, (setter)_io_StringIO_line_buffering_set, _io_StringIO_line_buffering_DOCSTR}, +#else +# define _IO_STRINGIO_LINE_BUFFERING_GETSETDEF {"line_buffering", (getter)_io_StringIO_line_buffering_get, NULL, _io_StringIO_line_buffering_DOCSTR}, +#endif + +static PyObject * +_io_StringIO_line_buffering_get_impl(stringio *self); + +static PyObject * +_io_StringIO_line_buffering_get(stringio *self, void *Py_UNUSED(context)) +{ + PyObject *return_value = NULL; + + Py_BEGIN_CRITICAL_SECTION(self); + return_value = _io_StringIO_line_buffering_get_impl(self); + Py_END_CRITICAL_SECTION(); + + return return_value; +} + +#if defined(_io_StringIO_newlines_HAS_DOCSTR) +# define _io_StringIO_newlines_DOCSTR _io_StringIO_newlines__doc__ +#else +# define _io_StringIO_newlines_DOCSTR NULL +#endif +#if defined(_IO_STRINGIO_NEWLINES_GETSETDEF) +# undef _IO_STRINGIO_NEWLINES_GETSETDEF +# define _IO_STRINGIO_NEWLINES_GETSETDEF {"newlines", (getter)_io_StringIO_newlines_get, (setter)_io_StringIO_newlines_set, _io_StringIO_newlines_DOCSTR}, +#else +# define _IO_STRINGIO_NEWLINES_GETSETDEF {"newlines", (getter)_io_StringIO_newlines_get, NULL, _io_StringIO_newlines_DOCSTR}, +#endif + +static PyObject * +_io_StringIO_newlines_get_impl(stringio *self); + +static PyObject * +_io_StringIO_newlines_get(stringio *self, void *Py_UNUSED(context)) +{ + PyObject *return_value = NULL; + + Py_BEGIN_CRITICAL_SECTION(self); + return_value = _io_StringIO_newlines_get_impl(self); + Py_END_CRITICAL_SECTION(); + + return return_value; } -/*[clinic end generated code: output=533f20ae9b773126 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=9ffea20cd32d4cd8 input=a9049054013a1b77]*/ diff --git a/Modules/_io/clinic/textio.c.h b/Modules/_io/clinic/textio.c.h index 5c2162529ff2dd..23b3cc8d71e098 100644 --- a/Modules/_io/clinic/textio.c.h +++ b/Modules/_io/clinic/textio.c.h @@ -3,10 +3,12 @@ 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() +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() #endif - +#include "pycore_abstract.h" // _Py_convert_optional_to_ssize_t() +#include "pycore_critical_section.h"// Py_BEGIN_CRITICAL_SECTION() +#include "pycore_modsupport.h" // _PyArg_UnpackKeywords() PyDoc_STRVAR(_io__TextIOBase_detach__doc__, "detach($self, /)\n" @@ -75,7 +77,7 @@ _io__TextIOBase_read(PyObject *self, PyTypeObject *cls, PyObject *const *args, P if (nargs < 1) { goto skip_optional_posonly; } - size = _PyLong_AsInt(args[0]); + size = PyLong_AsInt(args[0]); if (size == -1 && PyErr_Occurred()) { goto exit; } @@ -129,7 +131,7 @@ _io__TextIOBase_readline(PyObject *self, PyTypeObject *cls, PyObject *const *arg if (nargs < 1) { goto skip_optional_posonly; } - size = _PyLong_AsInt(args[0]); + size = PyLong_AsInt(args[0]); if (size == -1 && PyErr_Occurred()) { goto exit; } @@ -199,6 +201,89 @@ _io__TextIOBase_write(PyObject *self, PyTypeObject *cls, PyObject *const *args, return return_value; } +PyDoc_STRVAR(_io__TextIOBase_encoding__doc__, +"Encoding of the text stream.\n" +"\n" +"Subclasses should override."); +#define _io__TextIOBase_encoding_HAS_DOCSTR + +#if defined(_io__TextIOBase_encoding_HAS_DOCSTR) +# define _io__TextIOBase_encoding_DOCSTR _io__TextIOBase_encoding__doc__ +#else +# define _io__TextIOBase_encoding_DOCSTR NULL +#endif +#if defined(_IO__TEXTIOBASE_ENCODING_GETSETDEF) +# undef _IO__TEXTIOBASE_ENCODING_GETSETDEF +# define _IO__TEXTIOBASE_ENCODING_GETSETDEF {"encoding", (getter)_io__TextIOBase_encoding_get, (setter)_io__TextIOBase_encoding_set, _io__TextIOBase_encoding_DOCSTR}, +#else +# define _IO__TEXTIOBASE_ENCODING_GETSETDEF {"encoding", (getter)_io__TextIOBase_encoding_get, NULL, _io__TextIOBase_encoding_DOCSTR}, +#endif + +static PyObject * +_io__TextIOBase_encoding_get_impl(PyObject *self); + +static PyObject * +_io__TextIOBase_encoding_get(PyObject *self, void *Py_UNUSED(context)) +{ + return _io__TextIOBase_encoding_get_impl(self); +} + +PyDoc_STRVAR(_io__TextIOBase_newlines__doc__, +"Line endings translated so far.\n" +"\n" +"Only line endings translated during reading are considered.\n" +"\n" +"Subclasses should override."); +#define _io__TextIOBase_newlines_HAS_DOCSTR + +#if defined(_io__TextIOBase_newlines_HAS_DOCSTR) +# define _io__TextIOBase_newlines_DOCSTR _io__TextIOBase_newlines__doc__ +#else +# define _io__TextIOBase_newlines_DOCSTR NULL +#endif +#if defined(_IO__TEXTIOBASE_NEWLINES_GETSETDEF) +# undef _IO__TEXTIOBASE_NEWLINES_GETSETDEF +# define _IO__TEXTIOBASE_NEWLINES_GETSETDEF {"newlines", (getter)_io__TextIOBase_newlines_get, (setter)_io__TextIOBase_newlines_set, _io__TextIOBase_newlines_DOCSTR}, +#else +# define _IO__TEXTIOBASE_NEWLINES_GETSETDEF {"newlines", (getter)_io__TextIOBase_newlines_get, NULL, _io__TextIOBase_newlines_DOCSTR}, +#endif + +static PyObject * +_io__TextIOBase_newlines_get_impl(PyObject *self); + +static PyObject * +_io__TextIOBase_newlines_get(PyObject *self, void *Py_UNUSED(context)) +{ + return _io__TextIOBase_newlines_get_impl(self); +} + +PyDoc_STRVAR(_io__TextIOBase_errors__doc__, +"The error setting of the decoder or encoder.\n" +"\n" +"Subclasses should override."); +#define _io__TextIOBase_errors_HAS_DOCSTR + +#if defined(_io__TextIOBase_errors_HAS_DOCSTR) +# define _io__TextIOBase_errors_DOCSTR _io__TextIOBase_errors__doc__ +#else +# define _io__TextIOBase_errors_DOCSTR NULL +#endif +#if defined(_IO__TEXTIOBASE_ERRORS_GETSETDEF) +# undef _IO__TEXTIOBASE_ERRORS_GETSETDEF +# define _IO__TEXTIOBASE_ERRORS_GETSETDEF {"errors", (getter)_io__TextIOBase_errors_get, (setter)_io__TextIOBase_errors_set, _io__TextIOBase_errors_DOCSTR}, +#else +# define _IO__TEXTIOBASE_ERRORS_GETSETDEF {"errors", (getter)_io__TextIOBase_errors_get, NULL, _io__TextIOBase_errors_DOCSTR}, +#endif + +static PyObject * +_io__TextIOBase_errors_get_impl(PyObject *self); + +static PyObject * +_io__TextIOBase_errors_get(PyObject *self, void *Py_UNUSED(context)) +{ + return _io__TextIOBase_errors_get_impl(self); +} + PyDoc_STRVAR(_io_IncrementalNewlineDecoder___init____doc__, "IncrementalNewlineDecoder(decoder, translate, errors=\'strict\')\n" "--\n" @@ -629,7 +714,9 @@ _io_TextIOWrapper_reconfigure(textio *self, PyObject *const *args, Py_ssize_t na } write_through_obj = args[4]; skip_optional_kwonly: + Py_BEGIN_CRITICAL_SECTION(self); return_value = _io_TextIOWrapper_reconfigure_impl(self, encoding, errors, newline_obj, line_buffering_obj, write_through_obj); + Py_END_CRITICAL_SECTION(); exit: return return_value; @@ -649,7 +736,13 @@ _io_TextIOWrapper_detach_impl(textio *self); static PyObject * _io_TextIOWrapper_detach(textio *self, PyObject *Py_UNUSED(ignored)) { - return _io_TextIOWrapper_detach_impl(self); + PyObject *return_value = NULL; + + Py_BEGIN_CRITICAL_SECTION(self); + return_value = _io_TextIOWrapper_detach_impl(self); + Py_END_CRITICAL_SECTION(); + + return return_value; } PyDoc_STRVAR(_io_TextIOWrapper_write__doc__, @@ -674,7 +767,9 @@ _io_TextIOWrapper_write(textio *self, PyObject *arg) goto exit; } text = arg; + Py_BEGIN_CRITICAL_SECTION(self); return_value = _io_TextIOWrapper_write_impl(self, text); + Py_END_CRITICAL_SECTION(); exit: return return_value; @@ -707,7 +802,9 @@ _io_TextIOWrapper_read(textio *self, PyObject *const *args, Py_ssize_t nargs) goto exit; } skip_optional: + Py_BEGIN_CRITICAL_SECTION(self); return_value = _io_TextIOWrapper_read_impl(self, n); + Py_END_CRITICAL_SECTION(); exit: return return_value; @@ -749,16 +846,36 @@ _io_TextIOWrapper_readline(textio *self, PyObject *const *args, Py_ssize_t nargs size = ival; } skip_optional: + Py_BEGIN_CRITICAL_SECTION(self); return_value = _io_TextIOWrapper_readline_impl(self, size); + Py_END_CRITICAL_SECTION(); exit: return return_value; } PyDoc_STRVAR(_io_TextIOWrapper_seek__doc__, -"seek($self, cookie, whence=0, /)\n" +"seek($self, cookie, whence=os.SEEK_SET, /)\n" "--\n" -"\n"); +"\n" +"Set the stream position, and return the new stream position.\n" +"\n" +" cookie\n" +" Zero or an opaque number returned by tell().\n" +" whence\n" +" The relative position to seek from.\n" +"\n" +"Four operations are supported, given by the following argument\n" +"combinations:\n" +"\n" +"- seek(0, SEEK_SET): Rewind to the start of the stream.\n" +"- seek(cookie, SEEK_SET): Restore a previous position;\n" +" \'cookie\' must be a number returned by tell().\n" +"- seek(0, SEEK_END): Fast-forward to the end of the stream.\n" +"- seek(0, SEEK_CUR): Leave the current stream position unchanged.\n" +"\n" +"Any other argument combinations are invalid,\n" +"and may raise exceptions."); #define _IO_TEXTIOWRAPPER_SEEK_METHODDEF \ {"seek", _PyCFunction_CAST(_io_TextIOWrapper_seek), METH_FASTCALL, _io_TextIOWrapper_seek__doc__}, @@ -780,12 +897,14 @@ _io_TextIOWrapper_seek(textio *self, PyObject *const *args, Py_ssize_t nargs) if (nargs < 2) { goto skip_optional; } - whence = _PyLong_AsInt(args[1]); + whence = PyLong_AsInt(args[1]); if (whence == -1 && PyErr_Occurred()) { goto exit; } skip_optional: + Py_BEGIN_CRITICAL_SECTION(self); return_value = _io_TextIOWrapper_seek_impl(self, cookieObj, whence); + Py_END_CRITICAL_SECTION(); exit: return return_value; @@ -794,7 +913,11 @@ _io_TextIOWrapper_seek(textio *self, PyObject *const *args, Py_ssize_t nargs) PyDoc_STRVAR(_io_TextIOWrapper_tell__doc__, "tell($self, /)\n" "--\n" -"\n"); +"\n" +"Return the stream position as an opaque number.\n" +"\n" +"The return value of tell() can be given as input to seek(), to restore a\n" +"previous stream position."); #define _IO_TEXTIOWRAPPER_TELL_METHODDEF \ {"tell", (PyCFunction)_io_TextIOWrapper_tell, METH_NOARGS, _io_TextIOWrapper_tell__doc__}, @@ -805,7 +928,13 @@ _io_TextIOWrapper_tell_impl(textio *self); static PyObject * _io_TextIOWrapper_tell(textio *self, PyObject *Py_UNUSED(ignored)) { - return _io_TextIOWrapper_tell_impl(self); + PyObject *return_value = NULL; + + Py_BEGIN_CRITICAL_SECTION(self); + return_value = _io_TextIOWrapper_tell_impl(self); + Py_END_CRITICAL_SECTION(); + + return return_value; } PyDoc_STRVAR(_io_TextIOWrapper_truncate__doc__, @@ -833,7 +962,9 @@ _io_TextIOWrapper_truncate(textio *self, PyObject *const *args, Py_ssize_t nargs } pos = args[0]; skip_optional: + Py_BEGIN_CRITICAL_SECTION(self); return_value = _io_TextIOWrapper_truncate_impl(self, pos); + Py_END_CRITICAL_SECTION(); exit: return return_value; @@ -853,7 +984,13 @@ _io_TextIOWrapper_fileno_impl(textio *self); static PyObject * _io_TextIOWrapper_fileno(textio *self, PyObject *Py_UNUSED(ignored)) { - return _io_TextIOWrapper_fileno_impl(self); + PyObject *return_value = NULL; + + Py_BEGIN_CRITICAL_SECTION(self); + return_value = _io_TextIOWrapper_fileno_impl(self); + Py_END_CRITICAL_SECTION(); + + return return_value; } PyDoc_STRVAR(_io_TextIOWrapper_seekable__doc__, @@ -870,7 +1007,13 @@ _io_TextIOWrapper_seekable_impl(textio *self); static PyObject * _io_TextIOWrapper_seekable(textio *self, PyObject *Py_UNUSED(ignored)) { - return _io_TextIOWrapper_seekable_impl(self); + PyObject *return_value = NULL; + + Py_BEGIN_CRITICAL_SECTION(self); + return_value = _io_TextIOWrapper_seekable_impl(self); + Py_END_CRITICAL_SECTION(); + + return return_value; } PyDoc_STRVAR(_io_TextIOWrapper_readable__doc__, @@ -887,7 +1030,13 @@ _io_TextIOWrapper_readable_impl(textio *self); static PyObject * _io_TextIOWrapper_readable(textio *self, PyObject *Py_UNUSED(ignored)) { - return _io_TextIOWrapper_readable_impl(self); + PyObject *return_value = NULL; + + Py_BEGIN_CRITICAL_SECTION(self); + return_value = _io_TextIOWrapper_readable_impl(self); + Py_END_CRITICAL_SECTION(); + + return return_value; } PyDoc_STRVAR(_io_TextIOWrapper_writable__doc__, @@ -904,7 +1053,13 @@ _io_TextIOWrapper_writable_impl(textio *self); static PyObject * _io_TextIOWrapper_writable(textio *self, PyObject *Py_UNUSED(ignored)) { - return _io_TextIOWrapper_writable_impl(self); + PyObject *return_value = NULL; + + Py_BEGIN_CRITICAL_SECTION(self); + return_value = _io_TextIOWrapper_writable_impl(self); + Py_END_CRITICAL_SECTION(); + + return return_value; } PyDoc_STRVAR(_io_TextIOWrapper_isatty__doc__, @@ -921,7 +1076,13 @@ _io_TextIOWrapper_isatty_impl(textio *self); static PyObject * _io_TextIOWrapper_isatty(textio *self, PyObject *Py_UNUSED(ignored)) { - return _io_TextIOWrapper_isatty_impl(self); + PyObject *return_value = NULL; + + Py_BEGIN_CRITICAL_SECTION(self); + return_value = _io_TextIOWrapper_isatty_impl(self); + Py_END_CRITICAL_SECTION(); + + return return_value; } PyDoc_STRVAR(_io_TextIOWrapper_flush__doc__, @@ -938,7 +1099,13 @@ _io_TextIOWrapper_flush_impl(textio *self); static PyObject * _io_TextIOWrapper_flush(textio *self, PyObject *Py_UNUSED(ignored)) { - return _io_TextIOWrapper_flush_impl(self); + PyObject *return_value = NULL; + + Py_BEGIN_CRITICAL_SECTION(self); + return_value = _io_TextIOWrapper_flush_impl(self); + Py_END_CRITICAL_SECTION(); + + return return_value; } PyDoc_STRVAR(_io_TextIOWrapper_close__doc__, @@ -955,6 +1122,174 @@ _io_TextIOWrapper_close_impl(textio *self); static PyObject * _io_TextIOWrapper_close(textio *self, PyObject *Py_UNUSED(ignored)) { - return _io_TextIOWrapper_close_impl(self); + PyObject *return_value = NULL; + + Py_BEGIN_CRITICAL_SECTION(self); + return_value = _io_TextIOWrapper_close_impl(self); + Py_END_CRITICAL_SECTION(); + + return return_value; +} + +#if defined(_io_TextIOWrapper_name_HAS_DOCSTR) +# define _io_TextIOWrapper_name_DOCSTR _io_TextIOWrapper_name__doc__ +#else +# define _io_TextIOWrapper_name_DOCSTR NULL +#endif +#if defined(_IO_TEXTIOWRAPPER_NAME_GETSETDEF) +# undef _IO_TEXTIOWRAPPER_NAME_GETSETDEF +# define _IO_TEXTIOWRAPPER_NAME_GETSETDEF {"name", (getter)_io_TextIOWrapper_name_get, (setter)_io_TextIOWrapper_name_set, _io_TextIOWrapper_name_DOCSTR}, +#else +# define _IO_TEXTIOWRAPPER_NAME_GETSETDEF {"name", (getter)_io_TextIOWrapper_name_get, NULL, _io_TextIOWrapper_name_DOCSTR}, +#endif + +static PyObject * +_io_TextIOWrapper_name_get_impl(textio *self); + +static PyObject * +_io_TextIOWrapper_name_get(textio *self, void *Py_UNUSED(context)) +{ + PyObject *return_value = NULL; + + Py_BEGIN_CRITICAL_SECTION(self); + return_value = _io_TextIOWrapper_name_get_impl(self); + Py_END_CRITICAL_SECTION(); + + return return_value; +} + +#if defined(_io_TextIOWrapper_closed_HAS_DOCSTR) +# define _io_TextIOWrapper_closed_DOCSTR _io_TextIOWrapper_closed__doc__ +#else +# define _io_TextIOWrapper_closed_DOCSTR NULL +#endif +#if defined(_IO_TEXTIOWRAPPER_CLOSED_GETSETDEF) +# undef _IO_TEXTIOWRAPPER_CLOSED_GETSETDEF +# define _IO_TEXTIOWRAPPER_CLOSED_GETSETDEF {"closed", (getter)_io_TextIOWrapper_closed_get, (setter)_io_TextIOWrapper_closed_set, _io_TextIOWrapper_closed_DOCSTR}, +#else +# define _IO_TEXTIOWRAPPER_CLOSED_GETSETDEF {"closed", (getter)_io_TextIOWrapper_closed_get, NULL, _io_TextIOWrapper_closed_DOCSTR}, +#endif + +static PyObject * +_io_TextIOWrapper_closed_get_impl(textio *self); + +static PyObject * +_io_TextIOWrapper_closed_get(textio *self, void *Py_UNUSED(context)) +{ + PyObject *return_value = NULL; + + Py_BEGIN_CRITICAL_SECTION(self); + return_value = _io_TextIOWrapper_closed_get_impl(self); + Py_END_CRITICAL_SECTION(); + + return return_value; +} + +#if defined(_io_TextIOWrapper_newlines_HAS_DOCSTR) +# define _io_TextIOWrapper_newlines_DOCSTR _io_TextIOWrapper_newlines__doc__ +#else +# define _io_TextIOWrapper_newlines_DOCSTR NULL +#endif +#if defined(_IO_TEXTIOWRAPPER_NEWLINES_GETSETDEF) +# undef _IO_TEXTIOWRAPPER_NEWLINES_GETSETDEF +# define _IO_TEXTIOWRAPPER_NEWLINES_GETSETDEF {"newlines", (getter)_io_TextIOWrapper_newlines_get, (setter)_io_TextIOWrapper_newlines_set, _io_TextIOWrapper_newlines_DOCSTR}, +#else +# define _IO_TEXTIOWRAPPER_NEWLINES_GETSETDEF {"newlines", (getter)_io_TextIOWrapper_newlines_get, NULL, _io_TextIOWrapper_newlines_DOCSTR}, +#endif + +static PyObject * +_io_TextIOWrapper_newlines_get_impl(textio *self); + +static PyObject * +_io_TextIOWrapper_newlines_get(textio *self, void *Py_UNUSED(context)) +{ + PyObject *return_value = NULL; + + Py_BEGIN_CRITICAL_SECTION(self); + return_value = _io_TextIOWrapper_newlines_get_impl(self); + Py_END_CRITICAL_SECTION(); + + return return_value; +} + +#if defined(_io_TextIOWrapper_errors_HAS_DOCSTR) +# define _io_TextIOWrapper_errors_DOCSTR _io_TextIOWrapper_errors__doc__ +#else +# define _io_TextIOWrapper_errors_DOCSTR NULL +#endif +#if defined(_IO_TEXTIOWRAPPER_ERRORS_GETSETDEF) +# undef _IO_TEXTIOWRAPPER_ERRORS_GETSETDEF +# define _IO_TEXTIOWRAPPER_ERRORS_GETSETDEF {"errors", (getter)_io_TextIOWrapper_errors_get, (setter)_io_TextIOWrapper_errors_set, _io_TextIOWrapper_errors_DOCSTR}, +#else +# define _IO_TEXTIOWRAPPER_ERRORS_GETSETDEF {"errors", (getter)_io_TextIOWrapper_errors_get, NULL, _io_TextIOWrapper_errors_DOCSTR}, +#endif + +static PyObject * +_io_TextIOWrapper_errors_get_impl(textio *self); + +static PyObject * +_io_TextIOWrapper_errors_get(textio *self, void *Py_UNUSED(context)) +{ + PyObject *return_value = NULL; + + Py_BEGIN_CRITICAL_SECTION(self); + return_value = _io_TextIOWrapper_errors_get_impl(self); + Py_END_CRITICAL_SECTION(); + + return return_value; +} + +#if defined(_io_TextIOWrapper__CHUNK_SIZE_HAS_DOCSTR) +# define _io_TextIOWrapper__CHUNK_SIZE_DOCSTR _io_TextIOWrapper__CHUNK_SIZE__doc__ +#else +# define _io_TextIOWrapper__CHUNK_SIZE_DOCSTR NULL +#endif +#if defined(_IO_TEXTIOWRAPPER__CHUNK_SIZE_GETSETDEF) +# undef _IO_TEXTIOWRAPPER__CHUNK_SIZE_GETSETDEF +# define _IO_TEXTIOWRAPPER__CHUNK_SIZE_GETSETDEF {"_CHUNK_SIZE", (getter)_io_TextIOWrapper__CHUNK_SIZE_get, (setter)_io_TextIOWrapper__CHUNK_SIZE_set, _io_TextIOWrapper__CHUNK_SIZE_DOCSTR}, +#else +# define _IO_TEXTIOWRAPPER__CHUNK_SIZE_GETSETDEF {"_CHUNK_SIZE", (getter)_io_TextIOWrapper__CHUNK_SIZE_get, NULL, _io_TextIOWrapper__CHUNK_SIZE_DOCSTR}, +#endif + +static PyObject * +_io_TextIOWrapper__CHUNK_SIZE_get_impl(textio *self); + +static PyObject * +_io_TextIOWrapper__CHUNK_SIZE_get(textio *self, void *Py_UNUSED(context)) +{ + PyObject *return_value = NULL; + + Py_BEGIN_CRITICAL_SECTION(self); + return_value = _io_TextIOWrapper__CHUNK_SIZE_get_impl(self); + Py_END_CRITICAL_SECTION(); + + return return_value; +} + +#if defined(_IO_TEXTIOWRAPPER__CHUNK_SIZE_HAS_DOCSTR) +# define _io_TextIOWrapper__CHUNK_SIZE_DOCSTR _io_TextIOWrapper__CHUNK_SIZE__doc__ +#else +# define _io_TextIOWrapper__CHUNK_SIZE_DOCSTR NULL +#endif +#if defined(_IO_TEXTIOWRAPPER__CHUNK_SIZE_GETSETDEF) +# undef _IO_TEXTIOWRAPPER__CHUNK_SIZE_GETSETDEF +# define _IO_TEXTIOWRAPPER__CHUNK_SIZE_GETSETDEF {"_CHUNK_SIZE", (getter)_io_TextIOWrapper__CHUNK_SIZE_get, (setter)_io_TextIOWrapper__CHUNK_SIZE_set, _io_TextIOWrapper__CHUNK_SIZE_DOCSTR}, +#else +# define _IO_TEXTIOWRAPPER__CHUNK_SIZE_GETSETDEF {"_CHUNK_SIZE", NULL, (setter)_io_TextIOWrapper__CHUNK_SIZE_set, NULL}, +#endif + +static int +_io_TextIOWrapper__CHUNK_SIZE_set_impl(textio *self, PyObject *value); + +static int +_io_TextIOWrapper__CHUNK_SIZE_set(textio *self, PyObject *value, void *Py_UNUSED(context)) +{ + int return_value; + + Py_BEGIN_CRITICAL_SECTION(self); + return_value = _io_TextIOWrapper__CHUNK_SIZE_set_impl(self, value); + Py_END_CRITICAL_SECTION(); + + return return_value; } -/*[clinic end generated code: output=e1060638b65e8a63 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=d01aa598647c1385 input=a9049054013a1b77]*/ diff --git a/Modules/_io/clinic/winconsoleio.c.h b/Modules/_io/clinic/winconsoleio.c.h index cd3348dc1227cd..6cab295c44611d 100644 --- a/Modules/_io/clinic/winconsoleio.c.h +++ b/Modules/_io/clinic/winconsoleio.c.h @@ -3,10 +3,11 @@ 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() +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() #endif - +#include "pycore_abstract.h" // _Py_convert_optional_to_ssize_t() +#include "pycore_modsupport.h" // _PyArg_UnpackKeywords() #if defined(HAVE_WINDOWS_CONSOLE_IO) @@ -243,14 +244,9 @@ _io__WindowsConsoleIO_readinto(winconsoleio *self, PyTypeObject *cls, PyObject * goto exit; } if (PyObject_GetBuffer(args[0], &buffer, PyBUF_WRITABLE) < 0) { - PyErr_Clear(); _PyArg_BadArgument("readinto", "argument 1", "read-write bytes-like object", args[0]); goto exit; } - if (!PyBuffer_IsContiguous(&buffer, 'C')) { - _PyArg_BadArgument("readinto", "argument 1", "contiguous buffer", args[0]); - goto exit; - } return_value = _io__WindowsConsoleIO_readinto_impl(self, cls, &buffer); exit: @@ -391,10 +387,6 @@ _io__WindowsConsoleIO_write(winconsoleio *self, PyTypeObject *cls, PyObject *con if (PyObject_GetBuffer(args[0], &b, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&b, 'C')) { - _PyArg_BadArgument("write", "argument 1", "contiguous buffer", args[0]); - goto exit; - } return_value = _io__WindowsConsoleIO_write_impl(self, cls, &b); exit: @@ -465,4 +457,4 @@ _io__WindowsConsoleIO_isatty(winconsoleio *self, PyObject *Py_UNUSED(ignored)) #ifndef _IO__WINDOWSCONSOLEIO_ISATTY_METHODDEF #define _IO__WINDOWSCONSOLEIO_ISATTY_METHODDEF #endif /* !defined(_IO__WINDOWSCONSOLEIO_ISATTY_METHODDEF) */ -/*[clinic end generated code: output=235393758365c229 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=04108fc26b187386 input=a9049054013a1b77]*/ diff --git a/Modules/_io/fileio.c b/Modules/_io/fileio.c index 7fe37eee787e50..af4375c3640679 100644 --- a/Modules/_io/fileio.c +++ b/Modules/_io/fileio.c @@ -3,21 +3,25 @@ #include "Python.h" #include "pycore_fileutils.h" // _Py_BEGIN_SUPPRESS_IPH #include "pycore_object.h" // _PyObject_GC_UNTRACK() +#include "pycore_pyerrors.h" // _PyErr_ChainExceptions1() -#include +#include // bool +#ifdef HAVE_UNISTD_H +# include // lseek() +#endif #ifdef HAVE_SYS_TYPES_H -#include +# include #endif #ifdef HAVE_SYS_STAT_H -#include +# include #endif #ifdef HAVE_IO_H -#include +# include #endif #ifdef HAVE_FCNTL_H -#include +# include // open() #endif -#include /* For offsetof */ + #include "_iomodule.h" /* @@ -34,22 +38,23 @@ */ #ifdef MS_WINDOWS -/* can simulate truncate with Win32 API functions; see file_truncate */ -#define HAVE_FTRUNCATE -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN -#endif -#include + // can simulate truncate with Win32 API functions; see file_truncate +# define HAVE_FTRUNCATE +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +# endif +# include #endif #if BUFSIZ < (8*1024) -#define SMALLCHUNK (8*1024) +# define SMALLCHUNK (8*1024) #elif (BUFSIZ >= (2 << 25)) -#error "unreasonable BUFSIZ > 64 MiB defined" +# error "unreasonable BUFSIZ > 64 MiB defined" #else -#define SMALLCHUNK BUFSIZ +# define SMALLCHUNK BUFSIZ #endif + /*[clinic input] module _io class _io.FileIO "fileio *" "clinic_state()->PyFileIO_Type" @@ -264,7 +269,7 @@ _io_FileIO___init___impl(fileio *self, PyObject *nameobj, const char *mode, self->fd = -1; } - fd = _PyLong_AsInt(nameobj); + fd = PyLong_AsInt(nameobj); if (fd < 0) { if (!PyErr_Occurred()) { PyErr_SetString(PyExc_ValueError, @@ -393,6 +398,11 @@ _io_FileIO___init___impl(fileio *self, PyObject *nameobj, const char *mode, if (async_err) goto error; + + if (self->fd < 0) { + PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, nameobj); + goto error; + } } else { PyObject *fdobj; @@ -412,7 +422,7 @@ _io_FileIO___init___impl(fileio *self, PyObject *nameobj, const char *mode, goto error; } - self->fd = _PyLong_AsInt(fdobj); + self->fd = PyLong_AsInt(fdobj); Py_DECREF(fdobj); if (self->fd < 0) { if (!PyErr_Occurred()) { @@ -424,12 +434,7 @@ _io_FileIO___init___impl(fileio *self, PyObject *nameobj, const char *mode, goto error; } } - fd_is_own = 1; - if (self->fd < 0) { - PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, nameobj); - goto error; - } #ifndef MS_WINDOWS if (_Py_set_inheritable(self->fd, 0, atomic_flag_works) < 0) @@ -1057,8 +1062,8 @@ _io_FileIO_truncate_impl(fileio *self, PyTypeObject *cls, PyObject *posobj) Py_END_ALLOW_THREADS if (ret != 0) { - Py_DECREF(posobj); PyErr_SetFromErrno(PyExc_OSError); + Py_DECREF(posobj); return NULL; } @@ -1095,31 +1100,32 @@ static PyObject * fileio_repr(fileio *self) { PyObject *nameobj, *res; + const char *type_name = Py_TYPE((PyObject *) self)->tp_name; - if (self->fd < 0) - return PyUnicode_FromFormat("<_io.FileIO [closed]>"); + if (self->fd < 0) { + return PyUnicode_FromFormat("<%.100s [closed]>", type_name); + } if (PyObject_GetOptionalAttr((PyObject *) self, &_Py_ID(name), &nameobj) < 0) { return NULL; } if (nameobj == NULL) { res = PyUnicode_FromFormat( - "<_io.FileIO fd=%d mode='%s' closefd=%s>", - self->fd, mode_string(self), self->closefd ? "True" : "False"); + "<%.100s fd=%d mode='%s' closefd=%s>", + type_name, self->fd, mode_string(self), self->closefd ? "True" : "False"); } else { int status = Py_ReprEnter((PyObject *)self); res = NULL; if (status == 0) { res = PyUnicode_FromFormat( - "<_io.FileIO name=%R mode='%s' closefd=%s>", - nameobj, mode_string(self), self->closefd ? "True" : "False"); + "<%.100s name=%R mode='%s' closefd=%s>", + type_name, nameobj, mode_string(self), self->closefd ? "True" : "False"); Py_ReprLeave((PyObject *)self); } else if (status > 0) { PyErr_Format(PyExc_RuntimeError, - "reentrant call inside %s.__repr__", - Py_TYPE(self)->tp_name); + "reentrant call inside %.100s.__repr__", type_name); } Py_DECREF(nameobj); } diff --git a/Modules/_io/iobase.c b/Modules/_io/iobase.c index 5fd19895311c0c..4da8e5bd572d74 100644 --- a/Modules/_io/iobase.c +++ b/Modules/_io/iobase.c @@ -12,6 +12,8 @@ #include "pycore_call.h" // _PyObject_CallMethod() #include "pycore_long.h" // _PyLong_GetOne() #include "pycore_object.h" // _PyType_HasFeature() +#include "pycore_pyerrors.h" // _PyErr_ChainExceptions1() + #include // offsetof() #include "_iomodule.h" @@ -83,7 +85,9 @@ iobase_unsupported(_PyIO_State *state, const char *message) _io._IOBase.seek cls: defining_class offset: int(unused=True) + The stream position, relative to 'whence'. whence: int(unused=True, c_default='0') = os.SEEK_SET + The relative position to seek from. / Change the stream position to the given byte offset. @@ -101,7 +105,7 @@ Return the new absolute position. static PyObject * _io__IOBase_seek_impl(PyObject *self, PyTypeObject *cls, int Py_UNUSED(offset), int Py_UNUSED(whence)) -/*[clinic end generated code: output=8bd74ea6538ded53 input=8d4e6adcd08292f2]*/ +/*[clinic end generated code: output=8bd74ea6538ded53 input=74211232b363363e]*/ { _PyIO_State *state = get_io_state_by_cls(cls); return iobase_unsupported(state, "seek"); @@ -144,13 +148,9 @@ _io__IOBase_truncate_impl(PyObject *self, PyTypeObject *cls, static int iobase_is_closed(PyObject *self) { - PyObject *res; - int ret; /* This gets the derived attribute, which is *not* __IOBase_closed in most cases! */ - ret = PyObject_GetOptionalAttr(self, &_Py_ID(__IOBase_closed), &res); - Py_XDECREF(res); - return ret; + return PyObject_HasAttrWithError(self, &_Py_ID(__IOBase_closed)); } /* Flush and close methods */ @@ -265,7 +265,7 @@ static PyObject * _io__IOBase_close_impl(PyObject *self) /*[clinic end generated code: output=63c6a6f57d783d6d input=f4494d5c31dbc6b7]*/ { - int rc, closed = iobase_is_closed(self); + int rc1, rc2, closed = iobase_is_closed(self); if (closed < 0) { return NULL; @@ -274,19 +274,14 @@ _io__IOBase_close_impl(PyObject *self) Py_RETURN_NONE; } - PyObject *res = PyObject_CallMethodNoArgs(self, &_Py_ID(flush)); - + rc1 = _PyFile_Flush(self); PyObject *exc = PyErr_GetRaisedException(); - rc = PyObject_SetAttr(self, &_Py_ID(__IOBase_closed), Py_True); + rc2 = PyObject_SetAttr(self, &_Py_ID(__IOBase_closed), Py_True); _PyErr_ChainExceptions1(exc); - if (rc < 0) { - Py_CLEAR(res); - } - - if (res == NULL) + if (rc1 < 0 || rc2 < 0) { return NULL; + } - Py_DECREF(res); Py_RETURN_NONE; } diff --git a/Modules/_io/stringio.c b/Modules/_io/stringio.c index 1856b07108bab6..06bc2679e8e227 100644 --- a/Modules/_io/stringio.c +++ b/Modules/_io/stringio.c @@ -45,6 +45,10 @@ typedef struct { _PyIO_State *module_state; } stringio; +#define clinic_state() (find_io_state_by_def(Py_TYPE(self))) +#include "clinic/stringio.c.h" +#undef clinic_state + static int _io_StringIO___init__(PyObject *self, PyObject *args, PyObject *kwargs); #define CHECK_INITIALIZED(self) \ @@ -263,6 +267,7 @@ write_str(stringio *self, PyObject *obj) } /*[clinic input] +@critical_section _io.StringIO.getvalue Retrieve the entire contents of the object. @@ -270,7 +275,7 @@ Retrieve the entire contents of the object. static PyObject * _io_StringIO_getvalue_impl(stringio *self) -/*[clinic end generated code: output=27b6a7bfeaebce01 input=d23cb81d6791cf88]*/ +/*[clinic end generated code: output=27b6a7bfeaebce01 input=fb5dee06b8d467f3]*/ { CHECK_INITIALIZED(self); CHECK_CLOSED(self); @@ -281,6 +286,7 @@ _io_StringIO_getvalue_impl(stringio *self) } /*[clinic input] +@critical_section _io.StringIO.tell Tell the current file position. @@ -288,7 +294,7 @@ Tell the current file position. static PyObject * _io_StringIO_tell_impl(stringio *self) -/*[clinic end generated code: output=2e87ac67b116c77b input=ec866ebaff02f405]*/ +/*[clinic end generated code: output=2e87ac67b116c77b input=98a08f3e2dae3550]*/ { CHECK_INITIALIZED(self); CHECK_CLOSED(self); @@ -296,6 +302,7 @@ _io_StringIO_tell_impl(stringio *self) } /*[clinic input] +@critical_section _io.StringIO.read size: Py_ssize_t(accept={int, NoneType}) = -1 / @@ -308,7 +315,7 @@ is reached. Return an empty string at EOF. static PyObject * _io_StringIO_read_impl(stringio *self, Py_ssize_t size) -/*[clinic end generated code: output=ae8cf6002f71626c input=0921093383dfb92d]*/ +/*[clinic end generated code: output=ae8cf6002f71626c input=9fbef45d8aece8e7]*/ { Py_ssize_t n; Py_UCS4 *output; @@ -368,6 +375,7 @@ _stringio_readline(stringio *self, Py_ssize_t limit) } /*[clinic input] +@critical_section _io.StringIO.readline size: Py_ssize_t(accept={int, NoneType}) = -1 / @@ -379,7 +387,7 @@ Returns an empty string if EOF is hit immediately. static PyObject * _io_StringIO_readline_impl(stringio *self, Py_ssize_t size) -/*[clinic end generated code: output=cabd6452f1b7e85d input=a5bd70bf682aa276]*/ +/*[clinic end generated code: output=cabd6452f1b7e85d input=4d14b8495dea1d98]*/ { CHECK_INITIALIZED(self); CHECK_CLOSED(self); @@ -427,6 +435,7 @@ stringio_iternext(stringio *self) } /*[clinic input] +@critical_section _io.StringIO.truncate pos as size: Py_ssize_t(accept={int, NoneType}, c_default="self->pos") = None / @@ -440,7 +449,7 @@ Returns the new absolute position. static PyObject * _io_StringIO_truncate_impl(stringio *self, Py_ssize_t size) -/*[clinic end generated code: output=eb3aef8e06701365 input=5505cff90ca48b96]*/ +/*[clinic end generated code: output=eb3aef8e06701365 input=461b872dce238452]*/ { CHECK_INITIALIZED(self); CHECK_CLOSED(self); @@ -462,6 +471,7 @@ _io_StringIO_truncate_impl(stringio *self, Py_ssize_t size) } /*[clinic input] +@critical_section _io.StringIO.seek pos: Py_ssize_t whence: int = 0 @@ -478,7 +488,7 @@ Returns the new absolute position. static PyObject * _io_StringIO_seek_impl(stringio *self, Py_ssize_t pos, int whence) -/*[clinic end generated code: output=e9e0ac9a8ae71c25 input=e3855b24e7cae06a]*/ +/*[clinic end generated code: output=e9e0ac9a8ae71c25 input=c75ced09343a00d7]*/ { CHECK_INITIALIZED(self); CHECK_CLOSED(self); @@ -515,6 +525,7 @@ _io_StringIO_seek_impl(stringio *self, Py_ssize_t pos, int whence) } /*[clinic input] +@critical_section _io.StringIO.write s as obj: object / @@ -526,8 +537,8 @@ the length of the string. [clinic start generated code]*/ static PyObject * -_io_StringIO_write(stringio *self, PyObject *obj) -/*[clinic end generated code: output=0deaba91a15b94da input=cf96f3b16586e669]*/ +_io_StringIO_write_impl(stringio *self, PyObject *obj) +/*[clinic end generated code: output=d53b1d841d7db288 input=1561272c0da4651f]*/ { Py_ssize_t size; @@ -547,6 +558,7 @@ _io_StringIO_write(stringio *self, PyObject *obj) } /*[clinic input] +@critical_section _io.StringIO.close Close the IO object. @@ -559,7 +571,7 @@ This method has no effect if the file is already closed. static PyObject * _io_StringIO_close_impl(stringio *self) -/*[clinic end generated code: output=04399355cbe518f1 input=cbc10b45f35d6d46]*/ +/*[clinic end generated code: output=04399355cbe518f1 input=305d19aa29cc40b9]*/ { self->closed = 1; /* Free up some memory */ @@ -756,6 +768,7 @@ _io_StringIO___init___impl(stringio *self, PyObject *value, /* Properties and pseudo-properties */ /*[clinic input] +@critical_section _io.StringIO.readable Returns True if the IO object can be read. @@ -763,7 +776,7 @@ Returns True if the IO object can be read. static PyObject * _io_StringIO_readable_impl(stringio *self) -/*[clinic end generated code: output=b19d44dd8b1ceb99 input=39ce068b224c21ad]*/ +/*[clinic end generated code: output=b19d44dd8b1ceb99 input=6cd2ffd65a8e8763]*/ { CHECK_INITIALIZED(self); CHECK_CLOSED(self); @@ -771,6 +784,7 @@ _io_StringIO_readable_impl(stringio *self) } /*[clinic input] +@critical_section _io.StringIO.writable Returns True if the IO object can be written. @@ -778,7 +792,7 @@ Returns True if the IO object can be written. static PyObject * _io_StringIO_writable_impl(stringio *self) -/*[clinic end generated code: output=13e4dd77187074ca input=7a691353aac38835]*/ +/*[clinic end generated code: output=13e4dd77187074ca input=1b3c63dbaa761c69]*/ { CHECK_INITIALIZED(self); CHECK_CLOSED(self); @@ -786,6 +800,7 @@ _io_StringIO_writable_impl(stringio *self) } /*[clinic input] +@critical_section _io.StringIO.seekable Returns True if the IO object can be seeked. @@ -793,7 +808,7 @@ Returns True if the IO object can be seeked. static PyObject * _io_StringIO_seekable_impl(stringio *self) -/*[clinic end generated code: output=4d20b4641c756879 input=4c606d05b32952e6]*/ +/*[clinic end generated code: output=4d20b4641c756879 input=a820fad2cf085fc3]*/ { CHECK_INITIALIZED(self); CHECK_CLOSED(self); @@ -812,8 +827,15 @@ _io_StringIO_seekable_impl(stringio *self) supported. */ +/*[clinic input] +@critical_section +_io.StringIO.__getstate__ + +[clinic start generated code]*/ + static PyObject * -stringio_getstate(stringio *self, PyObject *Py_UNUSED(ignored)) +_io_StringIO___getstate___impl(stringio *self) +/*[clinic end generated code: output=780be4a996410199 input=76f27255ef83bb92]*/ { PyObject *initvalue = _io_StringIO_getvalue_impl(self); PyObject *dict; @@ -839,8 +861,17 @@ stringio_getstate(stringio *self, PyObject *Py_UNUSED(ignored)) return state; } +/*[clinic input] +@critical_section +_io.StringIO.__setstate__ + + state: object + / +[clinic start generated code]*/ + static PyObject * -stringio_setstate(stringio *self, PyObject *state) +_io_StringIO___setstate___impl(stringio *self, PyObject *state) +/*[clinic end generated code: output=cb3962bc6d5c5609 input=8a27784b11b82e47]*/ { PyObject *initarg; PyObject *position_obj; @@ -939,36 +970,53 @@ stringio_setstate(stringio *self, PyObject *state) Py_RETURN_NONE; } +/*[clinic input] +@critical_section +@getter +_io.StringIO.closed +[clinic start generated code]*/ static PyObject * -stringio_closed(stringio *self, void *context) +_io_StringIO_closed_get_impl(stringio *self) +/*[clinic end generated code: output=531ddca7954331d6 input=178d2ef24395fd49]*/ { CHECK_INITIALIZED(self); return PyBool_FromLong(self->closed); } +/*[clinic input] +@critical_section +@getter +_io.StringIO.line_buffering +[clinic start generated code]*/ + static PyObject * -stringio_line_buffering(stringio *self, void *context) +_io_StringIO_line_buffering_get_impl(stringio *self) +/*[clinic end generated code: output=360710e0112966ae input=6a7634e7f890745e]*/ { CHECK_INITIALIZED(self); CHECK_CLOSED(self); Py_RETURN_FALSE; } +/*[clinic input] +@critical_section +@getter +_io.StringIO.newlines +[clinic start generated code]*/ + static PyObject * -stringio_newlines(stringio *self, void *context) +_io_StringIO_newlines_get_impl(stringio *self) +/*[clinic end generated code: output=35d7c0b66d7e0160 input=092a14586718244b]*/ { CHECK_INITIALIZED(self); CHECK_CLOSED(self); - if (self->decoder == NULL) + if (self->decoder == NULL) { Py_RETURN_NONE; + } return PyObject_GetAttr(self->decoder, &_Py_ID(newlines)); } -#define clinic_state() (find_io_state_by_def(Py_TYPE(self))) -#include "clinic/stringio.c.h" -#undef clinic_state - static struct PyMethodDef stringio_methods[] = { _IO_STRINGIO_CLOSE_METHODDEF _IO_STRINGIO_GETVALUE_METHODDEF @@ -983,21 +1031,21 @@ static struct PyMethodDef stringio_methods[] = { _IO_STRINGIO_READABLE_METHODDEF _IO_STRINGIO_WRITABLE_METHODDEF - {"__getstate__", (PyCFunction)stringio_getstate, METH_NOARGS}, - {"__setstate__", (PyCFunction)stringio_setstate, METH_O}, + _IO_STRINGIO___GETSTATE___METHODDEF + _IO_STRINGIO___SETSTATE___METHODDEF {NULL, NULL} /* sentinel */ }; static PyGetSetDef stringio_getset[] = { - {"closed", (getter)stringio_closed, NULL, NULL}, - {"newlines", (getter)stringio_newlines, NULL, NULL}, + _IO_STRINGIO_CLOSED_GETSETDEF + _IO_STRINGIO_NEWLINES_GETSETDEF /* (following comments straight off of the original Python wrapper:) XXX Cruft to support the TextIOWrapper API. This would only be meaningful if StringIO supported the buffer attribute. Hopefully, a better solution, than adding these pseudo-attributes, will be found. */ - {"line_buffering", (getter)stringio_line_buffering, NULL, NULL}, + _IO_STRINGIO_LINE_BUFFERING_GETSETDEF {NULL} }; diff --git a/Modules/_io/textio.c b/Modules/_io/textio.c index 6ce90b2ed774c0..d794af8de2b8f0 100644 --- a/Modules/_io/textio.c +++ b/Modules/_io/textio.c @@ -7,13 +7,14 @@ */ #include "Python.h" -#include "pycore_call.h" // _PyObject_CallMethod() -#include "pycore_codecs.h" // _PyCodecInfo_GetIncrementalDecoder() -#include "pycore_interp.h" // PyInterpreterState.fs_codec -#include "pycore_long.h" // _PyLong_GetZero() -#include "pycore_fileutils.h" // _Py_GetLocaleEncoding() -#include "pycore_object.h" // _PyObject_GC_UNTRACK() -#include "pycore_pystate.h" // _PyInterpreterState_GET() +#include "pycore_call.h" // _PyObject_CallMethod() +#include "pycore_codecs.h" // _PyCodecInfo_GetIncrementalDecoder() +#include "pycore_fileutils.h" // _Py_GetLocaleEncoding() +#include "pycore_interp.h" // PyInterpreterState.fs_codec +#include "pycore_long.h" // _PyLong_GetZero() +#include "pycore_object.h" // _PyObject_GC_UNTRACK() +#include "pycore_pyerrors.h" // _PyErr_ChainExceptions1() +#include "pycore_pystate.h" // _PyInterpreterState_GET() #include "_iomodule.h" @@ -130,40 +131,52 @@ _io__TextIOBase_write_impl(PyObject *self, PyTypeObject *cls, return _unsupported(state, "write"); } -PyDoc_STRVAR(textiobase_encoding_doc, - "Encoding of the text stream.\n" - "\n" - "Subclasses should override.\n" - ); +/*[clinic input] +@getter +_io._TextIOBase.encoding + +Encoding of the text stream. + +Subclasses should override. +[clinic start generated code]*/ static PyObject * -textiobase_encoding_get(PyObject *self, void *context) +_io__TextIOBase_encoding_get_impl(PyObject *self) +/*[clinic end generated code: output=e0f5d8f548b92432 input=4736d7621dd38f43]*/ { Py_RETURN_NONE; } -PyDoc_STRVAR(textiobase_newlines_doc, - "Line endings translated so far.\n" - "\n" - "Only line endings translated during reading are considered.\n" - "\n" - "Subclasses should override.\n" - ); +/*[clinic input] +@getter +_io._TextIOBase.newlines + +Line endings translated so far. + +Only line endings translated during reading are considered. + +Subclasses should override. +[clinic start generated code]*/ static PyObject * -textiobase_newlines_get(PyObject *self, void *context) +_io__TextIOBase_newlines_get_impl(PyObject *self) +/*[clinic end generated code: output=46ec147fb9f00c2a input=a5b196d076af1164]*/ { Py_RETURN_NONE; } -PyDoc_STRVAR(textiobase_errors_doc, - "The error setting of the decoder or encoder.\n" - "\n" - "Subclasses should override.\n" - ); +/*[clinic input] +@getter +_io._TextIOBase.errors + +The error setting of the decoder or encoder. + +Subclasses should override. +[clinic start generated code]*/ static PyObject * -textiobase_errors_get(PyObject *self, void *context) +_io__TextIOBase_errors_get_impl(PyObject *self) +/*[clinic end generated code: output=c6623d6addcd087d input=974aa52d1db93a82]*/ { Py_RETURN_NONE; } @@ -178,9 +191,9 @@ static PyMethodDef textiobase_methods[] = { }; static PyGetSetDef textiobase_getset[] = { - {"encoding", (getter)textiobase_encoding_get, NULL, textiobase_encoding_doc}, - {"newlines", (getter)textiobase_newlines_get, NULL, textiobase_newlines_doc}, - {"errors", (getter)textiobase_errors_get, NULL, textiobase_errors_doc}, + _IO__TEXTIOBASE_ENCODING_GETSETDEF + _IO__TEXTIOBASE_NEWLINES_GETSETDEF + _IO__TEXTIOBASE_ERRORS_GETSETDEF {NULL} }; @@ -1019,15 +1032,10 @@ io_check_errors(PyObject *errors) return 0; } - Py_ssize_t name_length; - const char *name = PyUnicode_AsUTF8AndSize(errors, &name_length); + const char *name = _PyUnicode_AsUTF8NoNUL(errors); if (name == NULL) { return -1; } - if (strlen(name) != (size_t)name_length) { - PyErr_SetString(PyExc_ValueError, "embedded null character in errors"); - return -1; - } PyObject *handler = PyCodec_LookupError(name); if (handler != NULL) { Py_DECREF(handler); @@ -1116,6 +1124,10 @@ _io_TextIOWrapper___init___impl(textio *self, PyObject *buffer, else if (io_check_errors(errors)) { return -1; } + const char *errors_str = _PyUnicode_AsUTF8NoNUL(errors); + if (errors_str == NULL) { + return -1; + } if (validate_newline(newline) < 0) { return -1; @@ -1188,11 +1200,11 @@ _io_TextIOWrapper___init___impl(textio *self, PyObject *buffer, /* Build the decoder object */ _PyIO_State *state = find_io_state_by_def(Py_TYPE(self)); self->state = state; - if (_textiowrapper_set_decoder(self, codec_info, PyUnicode_AsUTF8(errors)) != 0) + if (_textiowrapper_set_decoder(self, codec_info, errors_str) != 0) goto error; /* Build the encoder object */ - if (_textiowrapper_set_encoder(self, codec_info, PyUnicode_AsUTF8(errors)) != 0) + if (_textiowrapper_set_encoder(self, codec_info, errors_str) != 0) goto error; /* Finished sorting out the codec details */ @@ -1222,11 +1234,10 @@ _io_TextIOWrapper___init___impl(textio *self, PyObject *buffer, goto error; self->seekable = self->telling = r; - r = PyObject_GetOptionalAttr(buffer, &_Py_ID(read1), &res); + r = PyObject_HasAttrWithError(buffer, &_Py_ID(read1)); if (r < 0) { goto error; } - Py_XDECREF(res); self->has_read1 = r; self->encoding_start_of_stream = 0; @@ -1289,35 +1300,46 @@ textiowrapper_change_encoding(textio *self, PyObject *encoding, errors = &_Py_ID(strict); } } + Py_INCREF(errors); + const char *c_encoding = PyUnicode_AsUTF8(encoding); + if (c_encoding == NULL) { + Py_DECREF(encoding); + Py_DECREF(errors); + return -1; + } const char *c_errors = PyUnicode_AsUTF8(errors); if (c_errors == NULL) { Py_DECREF(encoding); + Py_DECREF(errors); return -1; } // Create new encoder & decoder PyObject *codec_info = _PyCodec_LookupTextEncoding( - PyUnicode_AsUTF8(encoding), "codecs.open()"); + c_encoding, "codecs.open()"); if (codec_info == NULL) { Py_DECREF(encoding); + Py_DECREF(errors); return -1; } if (_textiowrapper_set_decoder(self, codec_info, c_errors) != 0 || _textiowrapper_set_encoder(self, codec_info, c_errors) != 0) { Py_DECREF(codec_info); Py_DECREF(encoding); + Py_DECREF(errors); return -1; } Py_DECREF(codec_info); Py_SETREF(self->encoding, encoding); - Py_SETREF(self->errors, Py_NewRef(errors)); + Py_SETREF(self->errors, errors); return _textiowrapper_fix_encoder_state(self); } /*[clinic input] +@critical_section _io.TextIOWrapper.reconfigure * encoding: object = None @@ -1337,12 +1359,32 @@ _io_TextIOWrapper_reconfigure_impl(textio *self, PyObject *encoding, PyObject *errors, PyObject *newline_obj, PyObject *line_buffering_obj, PyObject *write_through_obj) -/*[clinic end generated code: output=52b812ff4b3d4b0f input=671e82136e0f5822]*/ +/*[clinic end generated code: output=52b812ff4b3d4b0f input=dc3bd35ebda702a7]*/ { int line_buffering; int write_through; const char *newline = NULL; + if (encoding != Py_None && !PyUnicode_Check(encoding)) { + PyErr_Format(PyExc_TypeError, + "reconfigure() argument 'encoding' must be str or None, not %s", + Py_TYPE(encoding)->tp_name); + return NULL; + } + if (errors != Py_None && !PyUnicode_Check(errors)) { + PyErr_Format(PyExc_TypeError, + "reconfigure() argument 'errors' must be str or None, not %s", + Py_TYPE(errors)->tp_name); + return NULL; + } + if (newline_obj != NULL && newline_obj != Py_None && + !PyUnicode_Check(newline_obj)) + { + PyErr_Format(PyExc_TypeError, + "reconfigure() argument 'newline' must be str or None, not %s", + Py_TYPE(newline_obj)->tp_name); + return NULL; + } /* Check if something is in the read buffer */ if (self->decoded_chars != NULL) { if (encoding != Py_None || errors != Py_None || newline_obj != NULL) { @@ -1362,17 +1404,18 @@ _io_TextIOWrapper_reconfigure_impl(textio *self, PyObject *encoding, line_buffering = convert_optional_bool(line_buffering_obj, self->line_buffering); + if (line_buffering < 0) { + return NULL; + } write_through = convert_optional_bool(write_through_obj, self->write_through); - if (line_buffering < 0 || write_through < 0) { + if (write_through < 0) { return NULL; } - PyObject *res = PyObject_CallMethodNoArgs((PyObject *)self, &_Py_ID(flush)); - if (res == NULL) { + if (_PyFile_Flush((PyObject *)self) < 0) { return NULL; } - Py_DECREF(res); self->b2cratio = 0; if (newline_obj != NULL && set_newline(self, newline) < 0) { @@ -1444,7 +1487,7 @@ textiowrapper_traverse(textio *self, visitproc visit, void *arg) } static PyObject * -textiowrapper_closed_get(textio *self, void *context); +_io_TextIOWrapper_closed_get_impl(textio *self); /* This macro takes some shortcuts to make the common case faster. */ #define CHECK_CLOSED(self) \ @@ -1455,7 +1498,7 @@ textiowrapper_closed_get(textio *self, void *context); if (self->raw != NULL) \ r = _PyFileIO_closed(self->raw); \ else { \ - _res = textiowrapper_closed_get(self, NULL); \ + _res = _io_TextIOWrapper_closed_get_impl(self); \ if (_res == NULL) \ return NULL; \ r = PyObject_IsTrue(_res); \ @@ -1501,19 +1544,19 @@ textiowrapper_closed_get(textio *self, void *context); /*[clinic input] +@critical_section _io.TextIOWrapper.detach [clinic start generated code]*/ static PyObject * _io_TextIOWrapper_detach_impl(textio *self) -/*[clinic end generated code: output=7ba3715cd032d5f2 input=e5a71fbda9e1d9f9]*/ +/*[clinic end generated code: output=7ba3715cd032d5f2 input=c908a3b4ef203b0f]*/ { - PyObject *buffer, *res; + PyObject *buffer; CHECK_ATTACHED(self); - res = PyObject_CallMethodNoArgs((PyObject *)self, &_Py_ID(flush)); - if (res == NULL) + if (_PyFile_Flush((PyObject *)self) < 0) { return NULL; - Py_DECREF(res); + } buffer = self->buffer; self->buffer = NULL; self->detached = 1; @@ -1593,6 +1636,7 @@ _textiowrapper_writeflush(textio *self) } /*[clinic input] +@critical_section _io.TextIOWrapper.write text: unicode / @@ -1600,7 +1644,7 @@ _io.TextIOWrapper.write static PyObject * _io_TextIOWrapper_write_impl(textio *self, PyObject *text) -/*[clinic end generated code: output=d2deb0d50771fcec input=fdf19153584a0e44]*/ +/*[clinic end generated code: output=d2deb0d50771fcec input=73ec95c5c4a3489c]*/ { PyObject *ret; PyObject *b; @@ -1713,14 +1757,15 @@ _io_TextIOWrapper_write_impl(textio *self, PyObject *text) } if (needflush) { - ret = PyObject_CallMethodNoArgs(self->buffer, &_Py_ID(flush)); - if (ret == NULL) + if (_PyFile_Flush(self->buffer) < 0) { return NULL; - Py_DECREF(ret); + } } - textiowrapper_set_decoded_chars(self, NULL); - Py_CLEAR(self->snapshot); + if (self->snapshot != NULL) { + textiowrapper_set_decoded_chars(self, NULL); + Py_CLEAR(self->snapshot); + } if (self->decoder) { ret = PyObject_CallMethodNoArgs(self->decoder, &_Py_ID(reset)); @@ -1905,6 +1950,7 @@ textiowrapper_read_chunk(textio *self, Py_ssize_t size_hint) } /*[clinic input] +@critical_section _io.TextIOWrapper.read size as n: Py_ssize_t(accept={int, NoneType}) = -1 / @@ -1912,7 +1958,7 @@ _io.TextIOWrapper.read static PyObject * _io_TextIOWrapper_read_impl(textio *self, Py_ssize_t n) -/*[clinic end generated code: output=7e651ce6cc6a25a6 input=123eecbfe214aeb8]*/ +/*[clinic end generated code: output=7e651ce6cc6a25a6 input=67d14c5661121377]*/ { PyObject *result = NULL, *chunks = NULL; @@ -1955,8 +2001,10 @@ _io_TextIOWrapper_read_impl(textio *self, Py_ssize_t n) if (result == NULL) goto fail; - textiowrapper_set_decoded_chars(self, NULL); - Py_CLEAR(self->snapshot); + if (self->snapshot != NULL) { + textiowrapper_set_decoded_chars(self, NULL); + Py_CLEAR(self->snapshot); + } return result; } else { @@ -2280,6 +2328,7 @@ _textiowrapper_readline(textio *self, Py_ssize_t limit) } /*[clinic input] +@critical_section _io.TextIOWrapper.readline size: Py_ssize_t = -1 / @@ -2287,7 +2336,7 @@ _io.TextIOWrapper.readline static PyObject * _io_TextIOWrapper_readline_impl(textio *self, Py_ssize_t size) -/*[clinic end generated code: output=344afa98804e8b25 input=56c7172483b36db6]*/ +/*[clinic end generated code: output=344afa98804e8b25 input=b65bab871dc3ddba]*/ { CHECK_ATTACHED(self); return _textiowrapper_readline(self, size); @@ -2426,15 +2475,32 @@ _textiowrapper_encoder_setstate(textio *self, cookie_type *cookie) } /*[clinic input] +@critical_section _io.TextIOWrapper.seek cookie as cookieObj: object - whence: int = 0 + Zero or an opaque number returned by tell(). + whence: int(c_default='0') = os.SEEK_SET + The relative position to seek from. / + +Set the stream position, and return the new stream position. + +Four operations are supported, given by the following argument +combinations: + +- seek(0, SEEK_SET): Rewind to the start of the stream. +- seek(cookie, SEEK_SET): Restore a previous position; + 'cookie' must be a number returned by tell(). +- seek(0, SEEK_END): Fast-forward to the end of the stream. +- seek(0, SEEK_CUR): Leave the current stream position unchanged. + +Any other argument combinations are invalid, +and may raise exceptions. [clinic start generated code]*/ static PyObject * _io_TextIOWrapper_seek_impl(textio *self, PyObject *cookieObj, int whence) -/*[clinic end generated code: output=0a15679764e2d04d input=0458abeb3d7842be]*/ +/*[clinic end generated code: output=0a15679764e2d04d input=4bea78698be23d7e]*/ { PyObject *posobj; cookie_type cookie; @@ -2486,10 +2552,9 @@ _io_TextIOWrapper_seek_impl(textio *self, PyObject *cookieObj, int whence) goto fail; } - res = PyObject_CallMethodNoArgs((PyObject *)self, &_Py_ID(flush)); - if (res == NULL) + if (_PyFile_Flush((PyObject *)self) < 0) { goto fail; - Py_DECREF(res); + } textiowrapper_set_decoded_chars(self, NULL); Py_CLEAR(self->snapshot); @@ -2534,10 +2599,9 @@ _io_TextIOWrapper_seek_impl(textio *self, PyObject *cookieObj, int whence) goto fail; } - res = PyObject_CallMethodNoArgs((PyObject *)self, &_Py_ID(flush)); - if (res == NULL) + if (_PyFile_Flush((PyObject *)self) < 0) { goto fail; - Py_DECREF(res); + } /* The strategy of seek() is to go back to the safe start point * and replay the effect of read(chars_to_skip) from there. @@ -2623,12 +2687,18 @@ _io_TextIOWrapper_seek_impl(textio *self, PyObject *cookieObj, int whence) } /*[clinic input] +@critical_section _io.TextIOWrapper.tell + +Return the stream position as an opaque number. + +The return value of tell() can be given as input to seek(), to restore a +previous stream position. [clinic start generated code]*/ static PyObject * _io_TextIOWrapper_tell_impl(textio *self) -/*[clinic end generated code: output=4f168c08bf34ad5f input=9a2caf88c24f9ddf]*/ +/*[clinic end generated code: output=4f168c08bf34ad5f input=415d6b4e4f8e6e8c]*/ { PyObject *res; PyObject *posobj = NULL; @@ -2656,10 +2726,9 @@ _io_TextIOWrapper_tell_impl(textio *self) if (_textiowrapper_writeflush(self) < 0) return NULL; - res = PyObject_CallMethodNoArgs((PyObject *)self, &_Py_ID(flush)); - if (res == NULL) + if (_PyFile_Flush((PyObject *)self) < 0) { goto fail; - Py_DECREF(res); + } posobj = PyObject_CallMethodNoArgs(self->buffer, &_Py_ID(tell)); if (posobj == NULL) @@ -2855,6 +2924,7 @@ _io_TextIOWrapper_tell_impl(textio *self) } /*[clinic input] +@critical_section _io.TextIOWrapper.truncate pos: object = None / @@ -2862,16 +2932,13 @@ _io.TextIOWrapper.truncate static PyObject * _io_TextIOWrapper_truncate_impl(textio *self, PyObject *pos) -/*[clinic end generated code: output=90ec2afb9bb7745f input=56ec8baa65aea377]*/ +/*[clinic end generated code: output=90ec2afb9bb7745f input=8bddb320834c93ee]*/ { - PyObject *res; - CHECK_ATTACHED(self) - res = PyObject_CallMethodNoArgs((PyObject *)self, &_Py_ID(flush)); - if (res == NULL) + if (_PyFile_Flush((PyObject *)self) < 0) { return NULL; - Py_DECREF(res); + } return PyObject_CallMethodOneArg(self->buffer, &_Py_ID(truncate), pos); } @@ -2881,10 +2948,11 @@ textiowrapper_repr(textio *self) { PyObject *nameobj, *modeobj, *res, *s; int status; + const char *type_name = Py_TYPE(self)->tp_name; CHECK_INITIALIZED(self); - res = PyUnicode_FromString("<_io.TextIOWrapper"); + res = PyUnicode_FromFormat("<%.100s", type_name); if (res == NULL) return NULL; @@ -2892,8 +2960,8 @@ textiowrapper_repr(textio *self) if (status != 0) { if (status > 0) { PyErr_Format(PyExc_RuntimeError, - "reentrant call inside %s.__repr__", - Py_TYPE(self)->tp_name); + "reentrant call inside %.100s.__repr__", + type_name); } goto error; } @@ -2945,72 +3013,78 @@ textiowrapper_repr(textio *self) /* Inquiries */ /*[clinic input] +@critical_section _io.TextIOWrapper.fileno [clinic start generated code]*/ static PyObject * _io_TextIOWrapper_fileno_impl(textio *self) -/*[clinic end generated code: output=21490a4c3da13e6c input=c488ca83d0069f9b]*/ +/*[clinic end generated code: output=21490a4c3da13e6c input=515e1196aceb97ab]*/ { CHECK_ATTACHED(self); return PyObject_CallMethodNoArgs(self->buffer, &_Py_ID(fileno)); } /*[clinic input] +@critical_section _io.TextIOWrapper.seekable [clinic start generated code]*/ static PyObject * _io_TextIOWrapper_seekable_impl(textio *self) -/*[clinic end generated code: output=ab223dbbcffc0f00 input=8b005ca06e1fca13]*/ +/*[clinic end generated code: output=ab223dbbcffc0f00 input=71c4c092736c549b]*/ { CHECK_ATTACHED(self); return PyObject_CallMethodNoArgs(self->buffer, &_Py_ID(seekable)); } /*[clinic input] +@critical_section _io.TextIOWrapper.readable [clinic start generated code]*/ static PyObject * _io_TextIOWrapper_readable_impl(textio *self) -/*[clinic end generated code: output=72ff7ba289a8a91b input=0704ea7e01b0d3eb]*/ +/*[clinic end generated code: output=72ff7ba289a8a91b input=80438d1f01b0a89b]*/ { CHECK_ATTACHED(self); return PyObject_CallMethodNoArgs(self->buffer, &_Py_ID(readable)); } /*[clinic input] +@critical_section _io.TextIOWrapper.writable [clinic start generated code]*/ static PyObject * _io_TextIOWrapper_writable_impl(textio *self) -/*[clinic end generated code: output=a728c71790d03200 input=c41740bc9d8636e8]*/ +/*[clinic end generated code: output=a728c71790d03200 input=9d6c22befb0c340a]*/ { CHECK_ATTACHED(self); return PyObject_CallMethodNoArgs(self->buffer, &_Py_ID(writable)); } /*[clinic input] +@critical_section _io.TextIOWrapper.isatty [clinic start generated code]*/ static PyObject * _io_TextIOWrapper_isatty_impl(textio *self) -/*[clinic end generated code: output=12be1a35bace882e input=fb68d9f2c99bbfff]*/ +/*[clinic end generated code: output=12be1a35bace882e input=7f83ff04d4d1733d]*/ { CHECK_ATTACHED(self); return PyObject_CallMethodNoArgs(self->buffer, &_Py_ID(isatty)); } /*[clinic input] +@critical_section _io.TextIOWrapper.flush [clinic start generated code]*/ static PyObject * _io_TextIOWrapper_flush_impl(textio *self) -/*[clinic end generated code: output=59de9165f9c2e4d2 input=928c60590694ab85]*/ +/*[clinic end generated code: output=59de9165f9c2e4d2 input=3ac3bf521bfed59d]*/ { CHECK_ATTACHED(self); CHECK_CLOSED(self); @@ -3021,18 +3095,19 @@ _io_TextIOWrapper_flush_impl(textio *self) } /*[clinic input] +@critical_section _io.TextIOWrapper.close [clinic start generated code]*/ static PyObject * _io_TextIOWrapper_close_impl(textio *self) -/*[clinic end generated code: output=056ccf8b4876e4f4 input=9c2114315eae1948]*/ +/*[clinic end generated code: output=056ccf8b4876e4f4 input=8e12d7079d5ac5c1]*/ { PyObject *res; int r; CHECK_ATTACHED(self); - res = textiowrapper_closed_get(self, NULL); + res = _io_TextIOWrapper_closed_get_impl(self); if (res == NULL) return NULL; r = PyObject_IsTrue(res); @@ -3055,13 +3130,9 @@ _io_TextIOWrapper_close_impl(textio *self) PyErr_Clear(); } } - res = PyObject_CallMethodNoArgs((PyObject *)self, &_Py_ID(flush)); - if (res == NULL) { + if (_PyFile_Flush((PyObject *)self) < 0) { exc = PyErr_GetRaisedException(); } - else { - Py_DECREF(res); - } res = PyObject_CallMethodNoArgs(self->buffer, &_Py_ID(close)); if (exc != NULL) { @@ -3110,22 +3181,43 @@ textiowrapper_iternext(textio *self) return line; } +/*[clinic input] +@critical_section +@getter +_io.TextIOWrapper.name +[clinic start generated code]*/ + static PyObject * -textiowrapper_name_get(textio *self, void *context) +_io_TextIOWrapper_name_get_impl(textio *self) +/*[clinic end generated code: output=8c2f1d6d8756af40 input=26ecec9b39e30e07]*/ { CHECK_ATTACHED(self); return PyObject_GetAttr(self->buffer, &_Py_ID(name)); } +/*[clinic input] +@critical_section +@getter +_io.TextIOWrapper.closed +[clinic start generated code]*/ + static PyObject * -textiowrapper_closed_get(textio *self, void *context) +_io_TextIOWrapper_closed_get_impl(textio *self) +/*[clinic end generated code: output=b49b68f443a85e3c input=7dfcf43f63c7003d]*/ { CHECK_ATTACHED(self); return PyObject_GetAttr(self->buffer, &_Py_ID(closed)); } +/*[clinic input] +@critical_section +@getter +_io.TextIOWrapper.newlines +[clinic start generated code]*/ + static PyObject * -textiowrapper_newlines_get(textio *self, void *context) +_io_TextIOWrapper_newlines_get_impl(textio *self) +/*[clinic end generated code: output=53aa03ac35573180 input=610df647e514b3e8]*/ { PyObject *res; CHECK_ATTACHED(self); @@ -3137,30 +3229,51 @@ textiowrapper_newlines_get(textio *self, void *context) return res; } +/*[clinic input] +@critical_section +@getter +_io.TextIOWrapper.errors +[clinic start generated code]*/ + static PyObject * -textiowrapper_errors_get(textio *self, void *context) +_io_TextIOWrapper_errors_get_impl(textio *self) +/*[clinic end generated code: output=dca3a3ef21b09484 input=b45f983e6d43c4d8]*/ { CHECK_INITIALIZED(self); return Py_NewRef(self->errors); } +/*[clinic input] +@critical_section +@getter +_io.TextIOWrapper._CHUNK_SIZE +[clinic start generated code]*/ + static PyObject * -textiowrapper_chunk_size_get(textio *self, void *context) +_io_TextIOWrapper__CHUNK_SIZE_get_impl(textio *self) +/*[clinic end generated code: output=039925cd2df375bc input=e9715b0e06ff0fa6]*/ { CHECK_ATTACHED(self); return PyLong_FromSsize_t(self->chunk_size); } +/*[clinic input] +@critical_section +@setter +_io.TextIOWrapper._CHUNK_SIZE +[clinic start generated code]*/ + static int -textiowrapper_chunk_size_set(textio *self, PyObject *arg, void *context) +_io_TextIOWrapper__CHUNK_SIZE_set_impl(textio *self, PyObject *value) +/*[clinic end generated code: output=edb86d2db660a5ab input=32fc99861db02a0a]*/ { Py_ssize_t n; CHECK_ATTACHED_INT(self); - if (arg == NULL) { + if (value == NULL) { PyErr_SetString(PyExc_AttributeError, "cannot delete attribute"); return -1; } - n = PyNumber_AsSsize_t(arg, PyExc_ValueError); + n = PyNumber_AsSsize_t(value, PyExc_ValueError); if (n == -1 && PyErr_Occurred()) return -1; if (n <= 0) { @@ -3241,14 +3354,13 @@ static PyMemberDef textiowrapper_members[] = { }; static PyGetSetDef textiowrapper_getset[] = { - {"name", (getter)textiowrapper_name_get, NULL, NULL}, - {"closed", (getter)textiowrapper_closed_get, NULL, NULL}, + _IO_TEXTIOWRAPPER_NAME_GETSETDEF + _IO_TEXTIOWRAPPER_CLOSED_GETSETDEF /* {"mode", (getter)TextIOWrapper_mode_get, NULL, NULL}, */ - {"newlines", (getter)textiowrapper_newlines_get, NULL, NULL}, - {"errors", (getter)textiowrapper_errors_get, NULL, NULL}, - {"_CHUNK_SIZE", (getter)textiowrapper_chunk_size_get, - (setter)textiowrapper_chunk_size_set, NULL}, + _IO_TEXTIOWRAPPER_NEWLINES_GETSETDEF + _IO_TEXTIOWRAPPER_ERRORS_GETSETDEF + _IO_TEXTIOWRAPPER__CHUNK_SIZE_GETSETDEF {NULL} }; diff --git a/Modules/_io/winconsoleio.c b/Modules/_io/winconsoleio.c index a1ed7eb61e47b5..54e15555417287 100644 --- a/Modules/_io/winconsoleio.c +++ b/Modules/_io/winconsoleio.c @@ -9,6 +9,7 @@ #include "Python.h" #include "pycore_fileutils.h" // _Py_BEGIN_SUPPRESS_IPH #include "pycore_object.h" // _PyObject_GC_UNTRACK() +#include "pycore_pyerrors.h" // _PyErr_ChainExceptions1() #ifdef HAVE_WINDOWS_CONSOLE_IO @@ -133,6 +134,23 @@ char _PyIO_get_console_type(PyObject *path_or_fd) { return m; } +static DWORD +_find_last_utf8_boundary(const char *buf, DWORD len) +{ + /* This function never returns 0, returns the original len instead */ + DWORD count = 1; + if (len == 0 || (buf[len - 1] & 0x80) == 0) { + return len; + } + for (;; count++) { + if (count > 3 || count >= len) { + return len; + } + if ((buf[len - count] & 0xc0) != 0x80) { + return len - count; + } + } +} /*[clinic input] module _io @@ -280,7 +298,7 @@ _io__WindowsConsoleIO___init___impl(winconsoleio *self, PyObject *nameobj, self->fd = -1; } - fd = _PyLong_AsInt(nameobj); + fd = PyLong_AsInt(nameobj); if (fd < 0) { if (!PyErr_Occurred()) { PyErr_SetString(PyExc_ValueError, @@ -373,12 +391,12 @@ _io__WindowsConsoleIO___init___impl(winconsoleio *self, PyObject *nameobj, } if (self->writable) - self->fd = _Py_open_osfhandle_noraise(handle, _O_WRONLY | _O_BINARY); + self->fd = _Py_open_osfhandle_noraise(handle, _O_WRONLY | _O_BINARY | _O_NOINHERIT); else - self->fd = _Py_open_osfhandle_noraise(handle, _O_RDONLY | _O_BINARY); + self->fd = _Py_open_osfhandle_noraise(handle, _O_RDONLY | _O_BINARY | _O_NOINHERIT); if (self->fd < 0) { - CloseHandle(handle); PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, nameobj); + CloseHandle(handle); goto error; } } @@ -974,7 +992,7 @@ _io__WindowsConsoleIO_write_impl(winconsoleio *self, PyTypeObject *cls, { BOOL res = TRUE; wchar_t *wbuf; - DWORD len, wlen, orig_len, n = 0; + DWORD len, wlen, n = 0; HANDLE handle; if (self->fd == -1) @@ -1006,21 +1024,8 @@ _io__WindowsConsoleIO_write_impl(winconsoleio *self, PyTypeObject *cls, have to reduce and recalculate. */ while (wlen > 32766 / sizeof(wchar_t)) { len /= 2; - orig_len = len; - /* Reduce the length until we hit the final byte of a UTF-8 sequence - * (top bit is unset). Fix for github issue 82052. - */ - while (len > 0 && (((char *)b->buf)[len-1] & 0x80) != 0) - --len; - /* If we hit a length of 0, something has gone wrong. This shouldn't - * be possible, as valid UTF-8 can have at most 3 non-final bytes - * before a final one, and our buffer is way longer than that. - * But to be on the safe side, if we hit this issue we just restore - * the original length and let the console API sort it out. - */ - if (len == 0) { - len = orig_len; - } + /* Fix for github issues gh-110913 and gh-82052. */ + len = _find_last_utf8_boundary(b->buf, len); wlen = MultiByteToWideChar(CP_UTF8, 0, b->buf, len, NULL, 0); } Py_END_ALLOW_THREADS @@ -1065,15 +1070,22 @@ _io__WindowsConsoleIO_write_impl(winconsoleio *self, PyTypeObject *cls, static PyObject * winconsoleio_repr(winconsoleio *self) { - if (self->fd == -1) - return PyUnicode_FromFormat("<_io._WindowsConsoleIO [closed]>"); - - if (self->readable) - return PyUnicode_FromFormat("<_io._WindowsConsoleIO mode='rb' closefd=%s>", - self->closefd ? "True" : "False"); - if (self->writable) - return PyUnicode_FromFormat("<_io._WindowsConsoleIO mode='wb' closefd=%s>", - self->closefd ? "True" : "False"); + const char *type_name = (Py_TYPE((PyObject *)self)->tp_name); + + if (self->fd == -1) { + return PyUnicode_FromFormat("<%.100s [closed]>", type_name); + } + + if (self->readable) { + return PyUnicode_FromFormat("<%.100s mode='rb' closefd=%s>", + type_name, + self->closefd ? "True" : "False"); + } + if (self->writable) { + return PyUnicode_FromFormat("<%.100s mode='wb' closefd=%s>", + type_name, + self->closefd ? "True" : "False"); + } PyErr_SetString(PyExc_SystemError, "_WindowsConsoleIO has invalid mode"); return NULL; diff --git a/Modules/_json.c b/Modules/_json.c index c7cfe50b52faff..24b292ce70e5eb 100644 --- a/Modules/_json.c +++ b/Modules/_json.c @@ -12,7 +12,7 @@ #include "pycore_ceval.h" // _Py_EnterRecursiveCall() #include "pycore_runtime.h" // _PyRuntime -#include "pycore_global_objects.h" // _Py_ID() +#include "pycore_global_strings.h" // _Py_ID() #include // bool @@ -24,7 +24,6 @@ typedef struct _PyScannerObject { PyObject *parse_float; PyObject *parse_int; PyObject *parse_constant; - PyObject *memo; } PyScannerObject; static PyMemberDef scanner_members[] = { @@ -70,7 +69,7 @@ ascii_escape_unicode(PyObject *pystr); static PyObject * py_encode_basestring_ascii(PyObject* Py_UNUSED(self), PyObject *pystr); static PyObject * -scan_once_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *next_idx_ptr); +scan_once_unicode(PyScannerObject *s, PyObject *memo, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *next_idx_ptr); static PyObject * _build_rval_index_tuple(PyObject *rval, Py_ssize_t idx); static PyObject * @@ -631,7 +630,6 @@ scanner_traverse(PyScannerObject *self, visitproc visit, void *arg) Py_VISIT(self->parse_float); Py_VISIT(self->parse_int); Py_VISIT(self->parse_constant); - Py_VISIT(self->memo); return 0; } @@ -643,12 +641,11 @@ scanner_clear(PyScannerObject *self) Py_CLEAR(self->parse_float); Py_CLEAR(self->parse_int); Py_CLEAR(self->parse_constant); - Py_CLEAR(self->memo); return 0; } static PyObject * -_parse_object_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *next_idx_ptr) +_parse_object_unicode(PyScannerObject *s, PyObject *memo, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *next_idx_ptr) { /* Read a JSON object from PyUnicode pystr. idx is the index of the first character after the opening curly brace. @@ -665,6 +662,7 @@ _parse_object_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ss PyObject *key = NULL; int has_pairs_hook = (s->object_pairs_hook != Py_None); Py_ssize_t next_idx; + Py_ssize_t comma_idx; str = PyUnicode_DATA(pystr); kind = PyUnicode_KIND(pystr); @@ -693,7 +691,7 @@ _parse_object_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ss key = scanstring_unicode(pystr, idx + 1, s->strict, &next_idx); if (key == NULL) goto bail; - memokey = PyDict_SetDefault(s->memo, key, key); + memokey = PyDict_SetDefault(memo, key, key); if (memokey == NULL) { goto bail; } @@ -710,7 +708,7 @@ _parse_object_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ss while (idx <= end_idx && IS_WHITESPACE(PyUnicode_READ(kind, str, idx))) idx++; /* read any JSON term */ - val = scan_once_unicode(s, pystr, idx, &next_idx); + val = scan_once_unicode(s, memo, pystr, idx, &next_idx); if (val == NULL) goto bail; @@ -744,10 +742,16 @@ _parse_object_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ss raise_errmsg("Expecting ',' delimiter", pystr, idx); goto bail; } + comma_idx = idx; idx++; /* skip whitespace after , delimiter */ while (idx <= end_idx && IS_WHITESPACE(PyUnicode_READ(kind, str, idx))) idx++; + + if (idx <= end_idx && PyUnicode_READ(kind, str, idx) == '}') { + raise_errmsg("Illegal trailing comma before end of object", pystr, comma_idx); + goto bail; + } } } @@ -774,7 +778,7 @@ _parse_object_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ss } static PyObject * -_parse_array_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *next_idx_ptr) { +_parse_array_unicode(PyScannerObject *s, PyObject *memo, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *next_idx_ptr) { /* Read a JSON array from PyUnicode pystr. idx is the index of the first character after the opening brace. *next_idx_ptr is a return-by-reference index to the first character after @@ -788,6 +792,7 @@ _parse_array_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssi PyObject *val = NULL; PyObject *rval; Py_ssize_t next_idx; + Py_ssize_t comma_idx; rval = PyList_New(0); if (rval == NULL) @@ -805,7 +810,7 @@ _parse_array_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssi while (1) { /* read any JSON term */ - val = scan_once_unicode(s, pystr, idx, &next_idx); + val = scan_once_unicode(s, memo, pystr, idx, &next_idx); if (val == NULL) goto bail; @@ -825,10 +830,16 @@ _parse_array_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssi raise_errmsg("Expecting ',' delimiter", pystr, idx); goto bail; } + comma_idx = idx; idx++; /* skip whitespace after , */ while (idx <= end_idx && IS_WHITESPACE(PyUnicode_READ(kind, str, idx))) idx++; + + if (idx <= end_idx && PyUnicode_READ(kind, str, idx) == ']') { + raise_errmsg("Illegal trailing comma before end of array", pystr, comma_idx); + goto bail; + } } } @@ -986,7 +997,7 @@ _match_number_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t start, Py_ } static PyObject * -scan_once_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *next_idx_ptr) +scan_once_unicode(PyScannerObject *s, PyObject *memo, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *next_idx_ptr) { /* Read one JSON term (of any kind) from PyUnicode pystr. idx is the index of the first character of the term @@ -1022,7 +1033,7 @@ scan_once_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_ if (_Py_EnterRecursiveCall(" while decoding a JSON object " "from a unicode string")) return NULL; - res = _parse_object_unicode(s, pystr, idx + 1, next_idx_ptr); + res = _parse_object_unicode(s, memo, pystr, idx + 1, next_idx_ptr); _Py_LeaveRecursiveCall(); return res; case '[': @@ -1030,7 +1041,7 @@ scan_once_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_ if (_Py_EnterRecursiveCall(" while decoding a JSON array " "from a unicode string")) return NULL; - res = _parse_array_unicode(s, pystr, idx + 1, next_idx_ptr); + res = _parse_array_unicode(s, memo, pystr, idx + 1, next_idx_ptr); _Py_LeaveRecursiveCall(); return res; case 'n': @@ -1106,16 +1117,19 @@ scanner_call(PyScannerObject *self, PyObject *args, PyObject *kwds) if (!PyArg_ParseTupleAndKeywords(args, kwds, "On:scan_once", kwlist, &pystr, &idx)) return NULL; - if (PyUnicode_Check(pystr)) { - rval = scan_once_unicode(self, pystr, idx, &next_idx); - } - else { + if (!PyUnicode_Check(pystr)) { PyErr_Format(PyExc_TypeError, - "first argument must be a string, not %.80s", - Py_TYPE(pystr)->tp_name); + "first argument must be a string, not %.80s", + Py_TYPE(pystr)->tp_name); + return NULL; + } + + PyObject *memo = PyDict_New(); + if (memo == NULL) { return NULL; } - PyDict_Clear(self->memo); + rval = scan_once_unicode(self, memo, pystr, idx, &next_idx); + Py_DECREF(memo); if (rval == NULL) return NULL; return _build_rval_index_tuple(rval, next_idx); @@ -1137,10 +1151,6 @@ scanner_new(PyTypeObject *type, PyObject *args, PyObject *kwds) return NULL; } - s->memo = PyDict_New(); - if (s->memo == NULL) - goto bail; - /* All of these will fail "gracefully" so we don't need to verify them */ strict = PyObject_GetAttrString(ctx, "strict"); if (strict == NULL) diff --git a/Modules/_localemodule.c b/Modules/_localemodule.c index 34915de7515d63..fe8e4c5e30035b 100644 --- a/Modules/_localemodule.c +++ b/Modules/_localemodule.c @@ -10,34 +10,25 @@ This software comes with no warranty. Use at your own risk. ******************************************************************/ #include "Python.h" -#include "pycore_fileutils.h" - -#include -#include -#include -#include +#include "pycore_fileutils.h" // _Py_GetLocaleconvNumeric() +#include "pycore_pymem.h" // _PyMem_Strdup() +#include // setlocale() +#include // strlen() #ifdef HAVE_ERRNO_H -#include +# include // errno #endif - #ifdef HAVE_LANGINFO_H -#include +# include // nl_langinfo() #endif - #ifdef HAVE_LIBINTL_H -#include +# include #endif - -#ifdef HAVE_WCHAR_H -#include -#endif - -#if defined(MS_WINDOWS) -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN -#endif -#include +#ifdef MS_WINDOWS +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +# endif +# include #endif PyDoc_STRVAR(locale__doc__, "Support for POSIX locales."); @@ -736,8 +727,8 @@ _locale_bindtextdomain_impl(PyObject *module, const char *domain, } current_dirname = bindtextdomain(domain, dirname); if (current_dirname == NULL) { - Py_XDECREF(dirname_bytes); PyErr_SetFromErrno(PyExc_OSError); + Py_XDECREF(dirname_bytes); return NULL; } result = PyUnicode_DecodeLocale(current_dirname, NULL); diff --git a/Modules/_lsprof.c b/Modules/_lsprof.c index 257de4387c0ab9..8f09204097529f 100644 --- a/Modules/_lsprof.c +++ b/Modules/_lsprof.c @@ -4,7 +4,9 @@ #include "Python.h" #include "pycore_call.h" // _PyObject_CallNoArgs() +#include "pycore_ceval.h" // _PyEval_SetProfile() #include "pycore_pystate.h" // _PyThreadState_GET() + #include "rotatingtree.h" /************************************************************/ @@ -844,7 +846,7 @@ profiler_dealloc(ProfilerObject *op) if (op->flags & POF_ENABLED) { PyThreadState *tstate = _PyThreadState_GET(); if (_PyEval_SetProfile(tstate, NULL, NULL) < 0) { - _PyErr_WriteUnraisableMsg("When destroying _lsprof profiler", NULL); + PyErr_FormatUnraisable("Exception ignored when destroying _lsprof profiler"); } } diff --git a/Modules/_lzmamodule.c b/Modules/_lzmamodule.c index c548f8fa3839e0..eb90c308d16d19 100644 --- a/Modules/_lzmamodule.c +++ b/Modules/_lzmamodule.c @@ -5,6 +5,10 @@ */ +#ifndef Py_BUILD_CORE_BUILTIN +# define Py_BUILD_CORE_MODULE 1 +#endif + #include "Python.h" diff --git a/Modules/_multiprocessing/clinic/multiprocessing.c.h b/Modules/_multiprocessing/clinic/multiprocessing.c.h index 885cd5c2fff8ea..6d4f5c2afcfd39 100644 --- a/Modules/_multiprocessing/clinic/multiprocessing.c.h +++ b/Modules/_multiprocessing/clinic/multiprocessing.c.h @@ -2,11 +2,7 @@ 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 - +#include "pycore_modsupport.h" // _PyArg_CheckPositional() #if defined(MS_WINDOWS) @@ -66,7 +62,7 @@ _multiprocessing_recv(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!handle && PyErr_Occurred()) { goto exit; } - size = _PyLong_AsInt(args[1]); + size = PyLong_AsInt(args[1]); if (size == -1 && PyErr_Occurred()) { goto exit; } @@ -108,10 +104,6 @@ _multiprocessing_send(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (PyObject_GetBuffer(args[1], &buf, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&buf, 'C')) { - _PyArg_BadArgument("send", "argument 2", "contiguous buffer", args[1]); - goto exit; - } return_value = _multiprocessing_send_impl(module, handle, &buf); exit: @@ -172,4 +164,4 @@ _multiprocessing_sem_unlink(PyObject *module, PyObject *arg) #ifndef _MULTIPROCESSING_SEND_METHODDEF #define _MULTIPROCESSING_SEND_METHODDEF #endif /* !defined(_MULTIPROCESSING_SEND_METHODDEF) */ -/*[clinic end generated code: output=4a6afc67c1f5ec85 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=73b4cb8428d816da input=a9049054013a1b77]*/ diff --git a/Modules/_multiprocessing/clinic/posixshmem.c.h b/Modules/_multiprocessing/clinic/posixshmem.c.h index dd40662ce9902d..1b894ea4c67adc 100644 --- a/Modules/_multiprocessing/clinic/posixshmem.c.h +++ b/Modules/_multiprocessing/clinic/posixshmem.c.h @@ -2,12 +2,6 @@ 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 - - #if defined(HAVE_SHM_OPEN) PyDoc_STRVAR(_posixshmem_shm_open__doc__, @@ -17,69 +11,25 @@ PyDoc_STRVAR(_posixshmem_shm_open__doc__, "Open a shared memory object. Returns a file descriptor (integer)."); #define _POSIXSHMEM_SHM_OPEN_METHODDEF \ - {"shm_open", _PyCFunction_CAST(_posixshmem_shm_open), METH_FASTCALL|METH_KEYWORDS, _posixshmem_shm_open__doc__}, + {"shm_open", (PyCFunction)(void(*)(void))_posixshmem_shm_open, METH_VARARGS|METH_KEYWORDS, _posixshmem_shm_open__doc__}, static int _posixshmem_shm_open_impl(PyObject *module, PyObject *path, int flags, int mode); static PyObject * -_posixshmem_shm_open(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +_posixshmem_shm_open(PyObject *module, PyObject *args, PyObject *kwargs) { PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 3 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(path), &_Py_ID(flags), &_Py_ID(mode), }, - }; - #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[] = {"path", "flags", "mode", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "shm_open", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[3]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; + static char *_keywords[] = {"path", "flags", "mode", NULL}; PyObject *path; int flags; int mode = 511; int _return_value; - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 3, 0, argsbuf); - if (!args) { - goto exit; - } - if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("shm_open", "argument 'path'", "str", args[0]); + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Ui|i:shm_open", _keywords, + &path, &flags, &mode)) goto exit; - } - path = args[0]; - flags = _PyLong_AsInt(args[1]); - if (flags == -1 && PyErr_Occurred()) { - goto exit; - } - if (!noptargs) { - goto skip_optional_pos; - } - mode = _PyLong_AsInt(args[2]); - if (mode == -1 && PyErr_Occurred()) { - goto exit; - } -skip_optional_pos: _return_value = _posixshmem_shm_open_impl(module, path, flags, mode); if ((_return_value == -1) && PyErr_Occurred()) { goto exit; @@ -105,52 +55,21 @@ PyDoc_STRVAR(_posixshmem_shm_unlink__doc__, "region."); #define _POSIXSHMEM_SHM_UNLINK_METHODDEF \ - {"shm_unlink", _PyCFunction_CAST(_posixshmem_shm_unlink), METH_FASTCALL|METH_KEYWORDS, _posixshmem_shm_unlink__doc__}, + {"shm_unlink", (PyCFunction)(void(*)(void))_posixshmem_shm_unlink, METH_VARARGS|METH_KEYWORDS, _posixshmem_shm_unlink__doc__}, static PyObject * _posixshmem_shm_unlink_impl(PyObject *module, PyObject *path); static PyObject * -_posixshmem_shm_unlink(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +_posixshmem_shm_unlink(PyObject *module, PyObject *args, PyObject *kwargs) { PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(path), }, - }; - #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[] = {"path", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "shm_unlink", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; + static char *_keywords[] = {"path", NULL}; PyObject *path; - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); - if (!args) { + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "U:shm_unlink", _keywords, + &path)) goto exit; - } - if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("shm_unlink", "argument 'path'", "str", args[0]); - goto exit; - } - path = args[0]; return_value = _posixshmem_shm_unlink_impl(module, path); exit: @@ -166,4 +85,4 @@ _posixshmem_shm_unlink(PyObject *module, PyObject *const *args, Py_ssize_t nargs #ifndef _POSIXSHMEM_SHM_UNLINK_METHODDEF #define _POSIXSHMEM_SHM_UNLINK_METHODDEF #endif /* !defined(_POSIXSHMEM_SHM_UNLINK_METHODDEF) */ -/*[clinic end generated code: output=9b67f98885757bc4 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=be0661dbed83ea23 input=a9049054013a1b77]*/ diff --git a/Modules/_multiprocessing/clinic/semaphore.c.h b/Modules/_multiprocessing/clinic/semaphore.c.h index 35347169bc1591..7c855113113c20 100644 --- a/Modules/_multiprocessing/clinic/semaphore.c.h +++ b/Modules/_multiprocessing/clinic/semaphore.c.h @@ -3,10 +3,10 @@ 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() +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() #endif - +#include "pycore_modsupport.h" // _PyArg_UnpackKeywords() #if defined(HAVE_MP_SEMAPHORE) && defined(MS_WINDOWS) @@ -250,15 +250,15 @@ _multiprocessing_SemLock(PyTypeObject *type, PyObject *args, PyObject *kwargs) if (!fastargs) { goto exit; } - kind = _PyLong_AsInt(fastargs[0]); + kind = PyLong_AsInt(fastargs[0]); if (kind == -1 && PyErr_Occurred()) { goto exit; } - value = _PyLong_AsInt(fastargs[1]); + value = PyLong_AsInt(fastargs[1]); if (value == -1 && PyErr_Occurred()) { goto exit; } - maxvalue = _PyLong_AsInt(fastargs[2]); + maxvalue = PyLong_AsInt(fastargs[2]); if (maxvalue == -1 && PyErr_Occurred()) { goto exit; } @@ -542,4 +542,4 @@ _multiprocessing_SemLock___exit__(SemLockObject *self, PyObject *const *args, Py #ifndef _MULTIPROCESSING_SEMLOCK___EXIT___METHODDEF #define _MULTIPROCESSING_SEMLOCK___EXIT___METHODDEF #endif /* !defined(_MULTIPROCESSING_SEMLOCK___EXIT___METHODDEF) */ -/*[clinic end generated code: output=dae57a702cc01512 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=d57992037e6770b6 input=a9049054013a1b77]*/ diff --git a/Modules/_multiprocessing/multiprocessing.c b/Modules/_multiprocessing/multiprocessing.c index 16b5cb5dd9ec7a..2e6d8eb68c0243 100644 --- a/Modules/_multiprocessing/multiprocessing.c +++ b/Modules/_multiprocessing/multiprocessing.c @@ -14,16 +14,17 @@ class HANDLE_converter(CConverter): type = "HANDLE" format_unit = '"F_HANDLE"' - def parse_arg(self, argname, displayname): - return """ + def parse_arg(self, argname, displayname, *, limited_capi): + return self.format_code(""" {paramname} = PyLong_AsVoidPtr({argname}); if (!{paramname} && PyErr_Occurred()) {{{{ goto exit; }}}} - """.format(argname=argname, paramname=self.parser_name) + """, + argname=argname) [python start generated code]*/ -/*[python end generated code: output=da39a3ee5e6b4b0d input=3e537d244034affb]*/ +/*[python end generated code: output=da39a3ee5e6b4b0d input=3cf0318efc6a8772]*/ /*[clinic input] module _multiprocessing diff --git a/Modules/_multiprocessing/multiprocessing.h b/Modules/_multiprocessing/multiprocessing.h index 47257fd5d9fb26..099004b437828e 100644 --- a/Modules/_multiprocessing/multiprocessing.h +++ b/Modules/_multiprocessing/multiprocessing.h @@ -1,9 +1,18 @@ #ifndef MULTIPROCESSING_H #define MULTIPROCESSING_H +#ifndef Py_BUILD_CORE_BUILTIN +# define Py_BUILD_CORE_MODULE 1 +#endif + #include "Python.h" #include "structmember.h" #include "pythread.h" +#include "pycore_signal.h" // _PyOS_IsMainThread() + +#ifndef MS_WINDOWS +# include // sysconf() +#endif /* * Platform includes and definitions diff --git a/Modules/_multiprocessing/posixshmem.c b/Modules/_multiprocessing/posixshmem.c index debef3267f77d1..425ce10075c156 100644 --- a/Modules/_multiprocessing/posixshmem.c +++ b/Modules/_multiprocessing/posixshmem.c @@ -2,13 +2,21 @@ posixshmem - A Python extension that provides shm_open() and shm_unlink() */ +#include "pyconfig.h" // Py_GIL_DISABLED + +#ifndef Py_GIL_DISABLED +// Need limited C API version 3.12 for Py_MOD_PER_INTERPRETER_GIL_SUPPORTED +#define Py_LIMITED_API 0x030c0000 +#endif + #include -// for shm_open() and shm_unlink() +#include // EINTR #ifdef HAVE_SYS_MMAN_H -#include +# include // shm_open(), shm_unlink() #endif + /*[clinic input] module _posixshmem [clinic start generated code]*/ @@ -40,7 +48,7 @@ _posixshmem_shm_open_impl(PyObject *module, PyObject *path, int flags, { int fd; int async_err = 0; - const char *name = PyUnicode_AsUTF8(path); + const char *name = PyUnicode_AsUTF8AndSize(path, NULL); if (name == NULL) { return -1; } @@ -79,7 +87,7 @@ _posixshmem_shm_unlink_impl(PyObject *module, PyObject *path) { int rv; int async_err = 0; - const char *name = PyUnicode_AsUTF8(path); + const char *name = PyUnicode_AsUTF8AndSize(path, NULL); if (name == NULL) { return NULL; } diff --git a/Modules/_multiprocessing/semaphore.c b/Modules/_multiprocessing/semaphore.c index 771f86e5367af3..f8f2afda28d06d 100644 --- a/Modules/_multiprocessing/semaphore.c +++ b/Modules/_multiprocessing/semaphore.c @@ -9,6 +9,10 @@ #include "multiprocessing.h" +#ifdef HAVE_SYS_TIME_H +# include // gettimeofday() +#endif + #ifdef HAVE_MP_SEMAPHORE enum { RECURSIVE_MUTEX, SEMAPHORE }; @@ -516,12 +520,12 @@ _multiprocessing_SemLock_impl(PyTypeObject *type, int kind, int value, return result; failure: - if (handle != SEM_FAILED) - SEM_CLOSE(handle); - PyMem_Free(name_copy); if (!PyErr_Occurred()) { _PyMp_SetError(NULL, MP_STANDARD_ERROR); } + if (handle != SEM_FAILED) + SEM_CLOSE(handle); + PyMem_Free(name_copy); return NULL; } @@ -556,8 +560,9 @@ _multiprocessing_SemLock__rebuild_impl(PyTypeObject *type, SEM_HANDLE handle, if (name != NULL) { handle = sem_open(name, 0); if (handle == SEM_FAILED) { + PyErr_SetFromErrno(PyExc_OSError); PyMem_Free(name_copy); - return PyErr_SetFromErrno(PyExc_OSError); + return NULL; } } #endif diff --git a/Modules/_opcode.c b/Modules/_opcode.c index ad0fa736f82767..93c71377f03a76 100644 --- a/Modules/_opcode.c +++ b/Modules/_opcode.c @@ -1,7 +1,12 @@ +#ifndef Py_BUILD_CORE_BUILTIN +# define Py_BUILD_CORE_MODULE 1 +#endif + #include "Python.h" #include "compile.h" #include "opcode.h" #include "internal/pycore_code.h" +#include "internal/pycore_compile.h" #include "internal/pycore_intrinsics.h" /*[clinic input] @@ -74,7 +79,7 @@ static int _opcode_is_valid_impl(PyObject *module, int opcode) /*[clinic end generated code: output=b0d918ea1d073f65 input=fe23e0aa194ddae0]*/ { - return PyUnstable_OpcodeIsValid(opcode); + return _PyCompile_OpcodeIsValid(opcode); } /*[clinic input] @@ -90,8 +95,8 @@ static int _opcode_has_arg_impl(PyObject *module, int opcode) /*[clinic end generated code: output=7a062d3b2dcc0815 input=93d878ba6361db5f]*/ { - return PyUnstable_OpcodeIsValid(opcode) && - PyUnstable_OpcodeHasArg(opcode); + return _PyCompile_OpcodeIsValid(opcode) && + _PyCompile_OpcodeHasArg(opcode); } /*[clinic input] @@ -107,8 +112,8 @@ static int _opcode_has_const_impl(PyObject *module, int opcode) /*[clinic end generated code: output=c646d5027c634120 input=a6999e4cf13f9410]*/ { - return PyUnstable_OpcodeIsValid(opcode) && - PyUnstable_OpcodeHasConst(opcode); + return _PyCompile_OpcodeIsValid(opcode) && + _PyCompile_OpcodeHasConst(opcode); } /*[clinic input] @@ -124,8 +129,8 @@ static int _opcode_has_name_impl(PyObject *module, int opcode) /*[clinic end generated code: output=b49a83555c2fa517 input=448aa5e4bcc947ba]*/ { - return PyUnstable_OpcodeIsValid(opcode) && - PyUnstable_OpcodeHasName(opcode); + return _PyCompile_OpcodeIsValid(opcode) && + _PyCompile_OpcodeHasName(opcode); } /*[clinic input] @@ -141,8 +146,8 @@ static int _opcode_has_jump_impl(PyObject *module, int opcode) /*[clinic end generated code: output=e9c583c669f1c46a input=35f711274357a0c3]*/ { - return PyUnstable_OpcodeIsValid(opcode) && - PyUnstable_OpcodeHasJump(opcode); + return _PyCompile_OpcodeIsValid(opcode) && + _PyCompile_OpcodeHasJump(opcode); } @@ -164,8 +169,8 @@ static int _opcode_has_free_impl(PyObject *module, int opcode) /*[clinic end generated code: output=d81ae4d79af0ee26 input=117dcd5c19c1139b]*/ { - return PyUnstable_OpcodeIsValid(opcode) && - PyUnstable_OpcodeHasFree(opcode); + return _PyCompile_OpcodeIsValid(opcode) && + _PyCompile_OpcodeHasFree(opcode); } @@ -182,8 +187,8 @@ static int _opcode_has_local_impl(PyObject *module, int opcode) /*[clinic end generated code: output=da5a8616b7a5097b input=9a798ee24aaef49d]*/ { - return PyUnstable_OpcodeIsValid(opcode) && - PyUnstable_OpcodeHasLocal(opcode); + return _PyCompile_OpcodeIsValid(opcode) && + _PyCompile_OpcodeHasLocal(opcode); } /*[clinic input] @@ -199,8 +204,8 @@ static int _opcode_has_exc_impl(PyObject *module, int opcode) /*[clinic end generated code: output=41b68dff0ec82a52 input=db0e4bdb9bf13fa5]*/ { - return PyUnstable_OpcodeIsValid(opcode) && - PyUnstable_OpcodeHasExc(opcode); + return _PyCompile_OpcodeIsValid(opcode) && + _PyCompile_OpcodeHasExc(opcode); } /*[clinic input] @@ -223,6 +228,74 @@ _opcode_get_specialization_stats_impl(PyObject *module) /*[clinic input] +_opcode.get_nb_ops + +Return array of symbols of binary ops. + +Indexed by the BINARY_OP oparg value. +[clinic start generated code]*/ + +static PyObject * +_opcode_get_nb_ops_impl(PyObject *module) +/*[clinic end generated code: output=d997d306cc15426f input=9462fc544c823176]*/ +{ + PyObject *list = PyList_New(NB_OPARG_LAST + 1); + if (list == NULL) { + return NULL; + } +#define ADD_NB_OP(NUM, STR) \ + do { \ + PyObject *pair = Py_BuildValue("ss", #NUM, STR); \ + if (pair == NULL) { \ + Py_DECREF(list); \ + return NULL; \ + } \ + PyList_SET_ITEM(list, (NUM), pair); \ + } while(0); + + ADD_NB_OP(NB_ADD, "+"); + ADD_NB_OP(NB_AND, "&"); + ADD_NB_OP(NB_FLOOR_DIVIDE, "//"); + ADD_NB_OP(NB_LSHIFT, "<<"); + ADD_NB_OP(NB_MATRIX_MULTIPLY, "@"); + ADD_NB_OP(NB_MULTIPLY, "*"); + ADD_NB_OP(NB_REMAINDER, "%"); + ADD_NB_OP(NB_OR, "|"); + ADD_NB_OP(NB_POWER, "**"); + ADD_NB_OP(NB_RSHIFT, ">>"); + ADD_NB_OP(NB_SUBTRACT, "-"); + ADD_NB_OP(NB_TRUE_DIVIDE, "/"); + ADD_NB_OP(NB_XOR, "^"); + ADD_NB_OP(NB_INPLACE_ADD, "+="); + ADD_NB_OP(NB_INPLACE_AND, "&="); + ADD_NB_OP(NB_INPLACE_FLOOR_DIVIDE, "//="); + ADD_NB_OP(NB_INPLACE_LSHIFT, "<<="); + ADD_NB_OP(NB_INPLACE_MATRIX_MULTIPLY, "@="); + ADD_NB_OP(NB_INPLACE_MULTIPLY, "*="); + ADD_NB_OP(NB_INPLACE_REMAINDER, "%="); + ADD_NB_OP(NB_INPLACE_OR, "|="); + ADD_NB_OP(NB_INPLACE_POWER, "**="); + ADD_NB_OP(NB_INPLACE_RSHIFT, ">>="); + ADD_NB_OP(NB_INPLACE_SUBTRACT, "-="); + ADD_NB_OP(NB_INPLACE_TRUE_DIVIDE, "/="); + ADD_NB_OP(NB_INPLACE_XOR, "^="); + +#undef ADD_NB_OP + + for(int i = 0; i <= NB_OPARG_LAST; i++) { + if (PyList_GET_ITEM(list, i) == NULL) { + Py_DECREF(list); + PyErr_Format(PyExc_ValueError, + "Missing initialization for NB_OP %d", + i); + return NULL; + } + } + return list; +} + +/*[clinic input] + _opcode.get_intrinsic1_descs Return a list of names of the unary intrinsics. @@ -237,7 +310,7 @@ _opcode_get_intrinsic1_descs_impl(PyObject *module) return NULL; } for (int i=0; i <= MAX_INTRINSIC_1; i++) { - PyObject *name = _PyUnstable_GetUnaryIntrinsicName(i); + PyObject *name = _PyCompile_GetUnaryIntrinsicName(i); if (name == NULL) { Py_DECREF(list); return NULL; @@ -264,7 +337,7 @@ _opcode_get_intrinsic2_descs_impl(PyObject *module) return NULL; } for (int i=0; i <= MAX_INTRINSIC_2; i++) { - PyObject *name = _PyUnstable_GetBinaryIntrinsicName(i); + PyObject *name = _PyCompile_GetBinaryIntrinsicName(i); if (name == NULL) { Py_DECREF(list); return NULL; @@ -287,6 +360,7 @@ opcode_functions[] = { _OPCODE_HAS_LOCAL_METHODDEF _OPCODE_HAS_EXC_METHODDEF _OPCODE_GET_SPECIALIZATION_STATS_METHODDEF + _OPCODE_GET_NB_OPS_METHODDEF _OPCODE_GET_INTRINSIC1_DESCS_METHODDEF _OPCODE_GET_INTRINSIC2_DESCS_METHODDEF {NULL, NULL, 0, NULL} diff --git a/Modules/_pickle.c b/Modules/_pickle.c index c2b04cc513a664..f210c0ca205991 100644 --- a/Modules/_pickle.c +++ b/Modules/_pickle.c @@ -11,15 +11,17 @@ #include "Python.h" #include "pycore_bytesobject.h" // _PyBytesWriter #include "pycore_ceval.h" // _Py_EnterRecursiveCall() +#include "pycore_long.h" // _PyLong_AsByteArray() #include "pycore_moduleobject.h" // _PyModule_GetState() #include "pycore_object.h" // _PyNone_Type #include "pycore_pystate.h" // _PyThreadState_GET() #include "pycore_runtime.h" // _Py_ID() #include "pycore_setobject.h" // _PySet_NextEntry() - +#include "pycore_sysmodule.h" // _PySys_GetAttr() #include // strtol() + PyDoc_STRVAR(pickle_module_doc, "Optimized C implementation for the Python pickle module."); @@ -397,64 +399,6 @@ _Pickle_FastCall(PyObject *func, PyObject *obj) /*************************************************************************/ -/* Retrieve and deconstruct a method for avoiding a reference cycle - (pickler -> bound method of pickler -> pickler) */ -static int -init_method_ref(PyObject *self, PyObject *name, - PyObject **method_func, PyObject **method_self) -{ - PyObject *func, *func2; - int ret; - - /* *method_func and *method_self should be consistent. All refcount decrements - should be occurred after setting *method_self and *method_func. */ - ret = PyObject_GetOptionalAttr(self, name, &func); - if (func == NULL) { - *method_self = NULL; - Py_CLEAR(*method_func); - return ret; - } - - if (PyMethod_Check(func) && PyMethod_GET_SELF(func) == self) { - /* Deconstruct a bound Python method */ - *method_self = self; /* borrowed */ - func2 = PyMethod_GET_FUNCTION(func); - Py_XSETREF(*method_func, Py_NewRef(func2)); - Py_DECREF(func); - return 0; - } - else { - *method_self = NULL; - Py_XSETREF(*method_func, func); - return 0; - } -} - -/* Bind a method if it was deconstructed */ -static PyObject * -reconstruct_method(PyObject *func, PyObject *self) -{ - if (self) { - return PyMethod_New(func, self); - } - else { - return Py_NewRef(func); - } -} - -static PyObject * -call_method(PyObject *func, PyObject *self, PyObject *obj) -{ - if (self) { - return PyObject_CallFunctionObjArgs(func, self, obj, NULL); - } - else { - return PyObject_CallOneArg(func, obj); - } -} - -/*************************************************************************/ - /* Internal data type used as the unpickling stack. */ typedef struct { PyObject_VAR_HEAD @@ -666,9 +610,7 @@ typedef struct PicklerObject { PyMemoTable *memo; /* Memo table, keep track of the seen objects to support self-referential objects pickling. */ - PyObject *pers_func; /* persistent_id() method, can be NULL */ - PyObject *pers_func_self; /* borrowed reference to self if pers_func - is an unbound method, NULL otherwise */ + PyObject *persistent_id; /* persistent_id() method, can be NULL */ PyObject *dispatch_table; /* private dispatch_table, can be NULL */ PyObject *reducer_override; /* hook for invoking user-defined callbacks instead of save_global when pickling @@ -710,9 +652,7 @@ typedef struct UnpicklerObject { size_t memo_size; /* Capacity of the memo array */ size_t memo_len; /* Number of objects in the memo */ - PyObject *pers_func; /* persistent_load() method, can be NULL. */ - PyObject *pers_func_self; /* borrowed reference to self if pers_func - is an unbound method, NULL otherwise */ + PyObject *persistent_load; /* persistent_load() method, can be NULL. */ Py_buffer buffer; char *input_buffer; @@ -1165,8 +1105,7 @@ _Pickler_New(PickleState *st) } self->memo = memo; - self->pers_func = NULL; - self->pers_func_self = NULL; + self->persistent_id = NULL; self->dispatch_table = NULL; self->reducer_override = NULL; self->write = NULL; @@ -1660,8 +1599,7 @@ _Unpickler_New(PyObject *module) self->memo = memo; self->memo_size = MEMO_SIZE; self->memo_len = 0; - self->pers_func = NULL; - self->pers_func_self = NULL; + self->persistent_load = NULL; memset(&self->buffer, 0, sizeof(Py_buffer)); self->input_buffer = NULL; self->input_line = NULL; @@ -3927,7 +3865,7 @@ save_pers(PickleState *state, PicklerObject *self, PyObject *obj) const char persid_op = PERSID; const char binpersid_op = BINPERSID; - pid = call_method(self->pers_func, self->pers_func_self, obj); + pid = PyObject_CallOneArg(self->persistent_id, obj); if (pid == NULL) return -1; @@ -4315,7 +4253,7 @@ save(PickleState *st, PicklerObject *self, PyObject *obj, int pers_save) /* The extra pers_save argument is necessary to avoid calling save_pers() on its returned object. */ - if (!pers_save && self->pers_func) { + if (!pers_save && self->persistent_id) { /* save_pers() returns: -1 to signal an error; 0 if it did nothing successfully; @@ -4520,6 +4458,12 @@ save(PickleState *st, PicklerObject *self, PyObject *obj, int pers_save) return status; } +static PyObject * +persistent_id(PyObject *self, PyObject *obj) +{ + Py_RETURN_NONE; +} + static int dump(PickleState *state, PicklerObject *self, PyObject *obj) { @@ -4527,17 +4471,25 @@ dump(PickleState *state, PicklerObject *self, PyObject *obj) int status = -1; PyObject *tmp; - if (PyObject_GetOptionalAttr((PyObject *)self, &_Py_ID(reducer_override), - &tmp) < 0) { - goto error; + /* Cache the persistent_id method. */ + tmp = PyObject_GetAttr((PyObject *)self, &_Py_ID(persistent_id)); + if (tmp == NULL) { + goto error; } - /* Cache the reducer_override method, if it exists. */ - if (tmp != NULL) { - Py_XSETREF(self->reducer_override, tmp); + if (PyCFunction_Check(tmp) && + PyCFunction_GET_SELF(tmp) == (PyObject *)self && + PyCFunction_GET_FUNCTION(tmp) == persistent_id) + { + Py_CLEAR(tmp); } - else { - Py_CLEAR(self->reducer_override); + Py_XSETREF(self->persistent_id, tmp); + + /* Cache the reducer_override method, if it exists. */ + if (PyObject_GetOptionalAttr((PyObject *)self, &_Py_ID(reducer_override), + &tmp) < 0) { + goto error; } + Py_XSETREF(self->reducer_override, tmp); if (self->proto >= 2) { char header[2]; @@ -4563,11 +4515,12 @@ dump(PickleState *state, PicklerObject *self, PyObject *obj) self->framing = 0; /* Break the reference cycle we generated at the beginning this function - * call when setting the reducer_override attribute of the Pickler instance - * to a bound method of the same instance. This is important as the Pickler - * instance holds a reference to each object it has pickled (through its - * memo): thus, these objects won't be garbage-collected as long as the - * Pickler itself is not collected. */ + * call when setting the persistent_id and the reducer_override attributes + * of the Pickler instance to a bound method of the same instance. + * This is important as the Pickler instance holds a reference to each + * object it has pickled (through its memo): thus, these objects won't + * be garbage-collected as long as the Pickler itself is not collected. */ + Py_CLEAR(self->persistent_id); Py_CLEAR(self->reducer_override); return status; } @@ -4660,6 +4613,8 @@ _pickle_Pickler___sizeof___impl(PicklerObject *self) } static struct PyMethodDef Pickler_methods[] = { + {"persistent_id", persistent_id, METH_O, + PyDoc_STR("persistent_id($self, obj, /)\n--\n\n")}, _PICKLE_PICKLER_DUMP_METHODDEF _PICKLE_PICKLER_CLEAR_MEMO_METHODDEF _PICKLE_PICKLER___SIZEOF___METHODDEF @@ -4671,7 +4626,7 @@ Pickler_clear(PicklerObject *self) { Py_CLEAR(self->output_buffer); Py_CLEAR(self->write); - Py_CLEAR(self->pers_func); + Py_CLEAR(self->persistent_id); Py_CLEAR(self->dispatch_table); Py_CLEAR(self->fast_memo); Py_CLEAR(self->reducer_override); @@ -4700,11 +4655,19 @@ Pickler_traverse(PicklerObject *self, visitproc visit, void *arg) { Py_VISIT(Py_TYPE(self)); Py_VISIT(self->write); - Py_VISIT(self->pers_func); + Py_VISIT(self->persistent_id); Py_VISIT(self->dispatch_table); Py_VISIT(self->fast_memo); Py_VISIT(self->reducer_override); Py_VISIT(self->buffer_callback); + PyMemoTable *memo = self->memo; + if (memo && memo->mt_table) { + Py_ssize_t i = memo->mt_allocated; + while (--i >= 0) { + Py_VISIT(memo->mt_table[i].me_key); + } + } + return 0; } @@ -4789,11 +4752,6 @@ _pickle_Pickler___init___impl(PicklerObject *self, PyObject *file, self->fast_nesting = 0; self->fast_memo = NULL; - if (init_method_ref((PyObject *)self, &_Py_ID(persistent_id), - &self->pers_func, &self->pers_func_self) < 0) - { - return -1; - } if (self->dispatch_table != NULL) { return 0; } @@ -5042,36 +5000,6 @@ Pickler_set_memo(PicklerObject *self, PyObject *obj, void *Py_UNUSED(ignored)) return -1; } -static PyObject * -Pickler_get_persid(PicklerObject *self, void *Py_UNUSED(ignored)) -{ - if (self->pers_func == NULL) { - PyErr_SetString(PyExc_AttributeError, "persistent_id"); - return NULL; - } - return reconstruct_method(self->pers_func, self->pers_func_self); -} - -static int -Pickler_set_persid(PicklerObject *self, PyObject *value, void *Py_UNUSED(ignored)) -{ - if (value == NULL) { - PyErr_SetString(PyExc_TypeError, - "attribute deletion is not supported"); - return -1; - } - if (!PyCallable_Check(value)) { - PyErr_SetString(PyExc_TypeError, - "persistent_id must be a callable taking one argument"); - return -1; - } - - self->pers_func_self = NULL; - Py_XSETREF(self->pers_func, Py_NewRef(value)); - - return 0; -} - static PyMemberDef Pickler_members[] = { {"bin", Py_T_INT, offsetof(PicklerObject, bin)}, {"fast", Py_T_INT, offsetof(PicklerObject, fast)}, @@ -5082,8 +5010,6 @@ static PyMemberDef Pickler_members[] = { static PyGetSetDef Pickler_getsets[] = { {"memo", (getter)Pickler_get_memo, (setter)Pickler_set_memo}, - {"persistent_id", (getter)Pickler_get_persid, - (setter)Pickler_set_persid}, {NULL} }; @@ -5797,14 +5723,13 @@ instantiate(PyObject *cls, PyObject *args) into a newly created tuple. */ assert(PyTuple_Check(args)); if (!PyTuple_GET_SIZE(args) && PyType_Check(cls)) { - PyObject *func; - if (PyObject_GetOptionalAttr(cls, &_Py_ID(__getinitargs__), &func) < 0) { + int rc = PyObject_HasAttrWithError(cls, &_Py_ID(__getinitargs__)); + if (rc < 0) { return NULL; } - if (func == NULL) { + if (!rc) { return PyObject_CallMethodOneArg(cls, &_Py_ID(__new__), cls); } - Py_DECREF(func); } return PyObject_CallObject(cls, args); } @@ -6047,36 +5972,28 @@ load_persid(PickleState *st, UnpicklerObject *self) Py_ssize_t len; char *s; - if (self->pers_func) { - if ((len = _Unpickler_Readline(st, self, &s)) < 0) - return -1; - if (len < 1) - return bad_readline(st); + if ((len = _Unpickler_Readline(st, self, &s)) < 0) + return -1; + if (len < 1) + return bad_readline(st); - pid = PyUnicode_DecodeASCII(s, len - 1, "strict"); - if (pid == NULL) { - if (PyErr_ExceptionMatches(PyExc_UnicodeDecodeError)) { - PyErr_SetString(st->UnpicklingError, - "persistent IDs in protocol 0 must be " - "ASCII strings"); - } - return -1; + pid = PyUnicode_DecodeASCII(s, len - 1, "strict"); + if (pid == NULL) { + if (PyErr_ExceptionMatches(PyExc_UnicodeDecodeError)) { + PyErr_SetString(st->UnpicklingError, + "persistent IDs in protocol 0 must be " + "ASCII strings"); } - - obj = call_method(self->pers_func, self->pers_func_self, pid); - Py_DECREF(pid); - if (obj == NULL) - return -1; - - PDATA_PUSH(self->stack, obj, -1); - return 0; - } - else { - PyErr_SetString(st->UnpicklingError, - "A load persistent id instruction was encountered, " - "but no persistent_load function was specified."); return -1; } + + obj = PyObject_CallOneArg(self->persistent_load, pid); + Py_DECREF(pid); + if (obj == NULL) + return -1; + + PDATA_PUSH(self->stack, obj, -1); + return 0; } static int @@ -6084,25 +6001,17 @@ load_binpersid(PickleState *st, UnpicklerObject *self) { PyObject *pid, *obj; - if (self->pers_func) { - PDATA_POP(st, self->stack, pid); - if (pid == NULL) - return -1; - - obj = call_method(self->pers_func, self->pers_func_self, pid); - Py_DECREF(pid); - if (obj == NULL) - return -1; + PDATA_POP(st, self->stack, pid); + if (pid == NULL) + return -1; - PDATA_PUSH(self->stack, obj, -1); - return 0; - } - else { - PyErr_SetString(st->UnpicklingError, - "A load persistent id instruction was encountered, " - "but no persistent_load function was specified."); + obj = PyObject_CallOneArg(self->persistent_load, pid); + Py_DECREF(pid); + if (obj == NULL) return -1; - } + + PDATA_PUSH(self->stack, obj, -1); + return 0; } static int @@ -6828,6 +6737,7 @@ static PyObject * load(PickleState *st, UnpicklerObject *self) { PyObject *value = NULL; + PyObject *tmp; char *s = NULL; self->num_marks = 0; @@ -6837,6 +6747,13 @@ load(PickleState *st, UnpicklerObject *self) if (Py_SIZE(self->stack)) Pdata_clear(self->stack, 0); + /* Cache the persistent_load method. */ + tmp = PyObject_GetAttr((PyObject *)self, &_Py_ID(persistent_load)); + if (tmp == NULL) { + goto error; + } + Py_XSETREF(self->persistent_load, tmp); + /* Convenient macros for the dispatch while-switch loop just below. */ #define OP(opcode, load_func) \ case opcode: if (load_func(st, self) < 0) break; continue; @@ -6849,7 +6766,7 @@ load(PickleState *st, UnpicklerObject *self) if (PyErr_ExceptionMatches(st->UnpicklingError)) { PyErr_Format(PyExc_EOFError, "Ran out of input"); } - return NULL; + goto error; } switch ((enum opcode)s[0]) { @@ -6935,7 +6852,7 @@ load(PickleState *st, UnpicklerObject *self) PyErr_Format(st->UnpicklingError, "invalid load key, '\\x%02x'.", c); } - return NULL; + goto error; } } @@ -6943,14 +6860,41 @@ load(PickleState *st, UnpicklerObject *self) } if (PyErr_Occurred()) { - return NULL; + goto error; } if (_Unpickler_SkipConsumed(self) < 0) - return NULL; + goto error; + Py_CLEAR(self->persistent_load); PDATA_POP(st, self->stack, value); return value; + +error: + Py_CLEAR(self->persistent_load); + return NULL; +} + +/*[clinic input] + +_pickle.Unpickler.persistent_load + + cls: defining_class + pid: object + / + +[clinic start generated code]*/ + +static PyObject * +_pickle_Unpickler_persistent_load_impl(UnpicklerObject *self, + PyTypeObject *cls, PyObject *pid) +/*[clinic end generated code: output=9f4706f1330cb14d input=2f9554fae051276e]*/ +{ + PickleState *st = _Pickle_GetStateByClass(cls); + PyErr_SetString(st->UnpicklingError, + "A load persistent id instruction was encountered, " + "but no persistent_load function was specified."); + return NULL; } /*[clinic input] @@ -7119,6 +7063,7 @@ _pickle_Unpickler___sizeof___impl(UnpicklerObject *self) } static struct PyMethodDef Unpickler_methods[] = { + _PICKLE_UNPICKLER_PERSISTENT_LOAD_METHODDEF _PICKLE_UNPICKLER_LOAD_METHODDEF _PICKLE_UNPICKLER_FIND_CLASS_METHODDEF _PICKLE_UNPICKLER___SIZEOF___METHODDEF @@ -7133,7 +7078,7 @@ Unpickler_clear(UnpicklerObject *self) Py_CLEAR(self->read); Py_CLEAR(self->peek); Py_CLEAR(self->stack); - Py_CLEAR(self->pers_func); + Py_CLEAR(self->persistent_load); Py_CLEAR(self->buffers); if (self->buffer.buf != NULL) { PyBuffer_Release(&self->buffer); @@ -7172,8 +7117,15 @@ Unpickler_traverse(UnpicklerObject *self, visitproc visit, void *arg) Py_VISIT(self->read); Py_VISIT(self->peek); Py_VISIT(self->stack); - Py_VISIT(self->pers_func); + Py_VISIT(self->persistent_load); Py_VISIT(self->buffers); + PyObject **memo = self->memo; + if (memo) { + Py_ssize_t i = self->memo_size; + while (--i >= 0) { + Py_VISIT(memo[i]); + } + } return 0; } @@ -7231,12 +7183,6 @@ _pickle_Unpickler___init___impl(UnpicklerObject *self, PyObject *file, self->fix_imports = fix_imports; - if (init_method_ref((PyObject *)self, &_Py_ID(persistent_load), - &self->pers_func, &self->pers_func_self) < 0) - { - return -1; - } - PyTypeObject *tp = Py_TYPE(self); PickleState *state = _Pickle_FindStateByType(tp); self->stack = (Pdata *)Pdata_New(state); @@ -7505,41 +7451,8 @@ Unpickler_set_memo(UnpicklerObject *self, PyObject *obj, void *Py_UNUSED(ignored return -1; } -static PyObject * -Unpickler_get_persload(UnpicklerObject *self, void *Py_UNUSED(ignored)) -{ - if (self->pers_func == NULL) { - PyErr_SetString(PyExc_AttributeError, "persistent_load"); - return NULL; - } - return reconstruct_method(self->pers_func, self->pers_func_self); -} - -static int -Unpickler_set_persload(UnpicklerObject *self, PyObject *value, void *Py_UNUSED(ignored)) -{ - if (value == NULL) { - PyErr_SetString(PyExc_TypeError, - "attribute deletion is not supported"); - return -1; - } - if (!PyCallable_Check(value)) { - PyErr_SetString(PyExc_TypeError, - "persistent_load must be a callable taking " - "one argument"); - return -1; - } - - self->pers_func_self = NULL; - Py_XSETREF(self->pers_func, Py_NewRef(value)); - - return 0; -} - static PyGetSetDef Unpickler_getsets[] = { {"memo", (getter)Unpickler_get_memo, (setter)Unpickler_set_memo}, - {"persistent_load", (getter)Unpickler_get_persload, - (setter)Unpickler_set_persload}, {NULL} }; diff --git a/Modules/_posixsubprocess.c b/Modules/_posixsubprocess.c index ac2b0d4f55468c..d0dd8f064e0395 100644 --- a/Modules/_posixsubprocess.c +++ b/Modules/_posixsubprocess.c @@ -8,28 +8,28 @@ #include "pycore_pystate.h" #include "pycore_signal.h" // _Py_RestoreSignals() #if defined(HAVE_PIPE2) && !defined(_GNU_SOURCE) -# define _GNU_SOURCE +# define _GNU_SOURCE #endif -#include -#include +#include // close() +#include // fcntl() #ifdef HAVE_SYS_TYPES_H -#include +# include #endif #if defined(HAVE_SYS_STAT_H) -#include +# include // stat() #endif #ifdef HAVE_SYS_SYSCALL_H -#include +# include #endif #if defined(HAVE_SYS_RESOURCE_H) -#include +# include #endif #ifdef HAVE_DIRENT_H -#include +# include // opendir() +#endif +#if defined(HAVE_SETGROUPS) +# include // setgroups() #endif -#ifdef HAVE_GRP_H -#include -#endif /* HAVE_GRP_H */ #include "posixmodule.h" @@ -87,15 +87,16 @@ class pid_t_converter(CConverter): type = 'pid_t' format_unit = '" _Py_PARSE_PID "' - def parse_arg(self, argname, displayname): - return """ + def parse_arg(self, argname, displayname, *, limited_capi): + return self.format_code(""" {paramname} = PyLong_AsPid({argname}); if ({paramname} == -1 && PyErr_Occurred()) {{{{ goto exit; }}}} - """.format(argname=argname, paramname=self.parser_name) + """, + argname=argname) [python start generated code]*/ -/*[python end generated code: output=da39a3ee5e6b4b0d input=5af1c116d56cbb5a]*/ +/*[python end generated code: output=da39a3ee5e6b4b0d input=c94349aa1aad151d]*/ #include "clinic/_posixsubprocess.c.h" @@ -766,8 +767,10 @@ child_exec(char *const exec_array[], #endif #ifdef HAVE_SETGROUPS - if (extra_group_size > 0) + if (extra_group_size >= 0) { + assert((extra_group_size == 0) == (extra_groups == NULL)); POSIX_CALL(setgroups(extra_group_size, extra_groups)); + } #endif /* HAVE_SETGROUPS */ #ifdef HAVE_SETREGID @@ -1021,7 +1024,6 @@ subprocess_fork_exec_impl(PyObject *module, PyObject *process_args, pid_t pid = -1; int need_to_reenable_gc = 0; char *const *argv = NULL, *const *envp = NULL; - Py_ssize_t extra_group_size = 0; int need_after_fork = 0; int saved_errno = 0; int *c_fds_to_keep = NULL; @@ -1102,6 +1104,13 @@ subprocess_fork_exec_impl(PyObject *module, PyObject *process_args, cwd = PyBytes_AsString(cwd_obj2); } + // Special initial value meaning that subprocess API was called with + // extra_groups=None leading to _posixsubprocess.fork_exec(gids=None). + // We use this to differentiate between code desiring a setgroups(0, NULL) + // call vs no call at all. The fast vfork() code path could be used when + // there is no setgroups call. + Py_ssize_t extra_group_size = -2; + if (extra_groups_packed != Py_None) { #ifdef HAVE_SETGROUPS if (!PyList_Check(extra_groups_packed)) { diff --git a/Modules/_queuemodule.c b/Modules/_queuemodule.c index b0a36f03694507..81a06cdb79a4f2 100644 --- a/Modules/_queuemodule.c +++ b/Modules/_queuemodule.c @@ -3,6 +3,7 @@ #endif #include "Python.h" +#include "pycore_ceval.h" // _PyEval_MakePendingCalls() #include "pycore_moduleobject.h" // _PyModule_GetState() #include "pycore_time.h" // _PyTime_t @@ -213,6 +214,8 @@ _queue_SimpleQueue_get_impl(simplequeueobject *self, PyTypeObject *cls, PY_TIMEOUT_T microseconds; PyThreadState *tstate = PyThreadState_Get(); + // XXX Use PyThread_ParseTimeoutArg(). + if (block == 0) { /* Non-blocking */ microseconds = 0; diff --git a/Modules/_randommodule.c b/Modules/_randommodule.c index 7daa1f9327966f..4403e1d132c057 100644 --- a/Modules/_randommodule.c +++ b/Modules/_randommodule.c @@ -71,15 +71,19 @@ #endif #include "Python.h" +#include "pycore_long.h" // _PyLong_NumBits() +#include "pycore_modsupport.h" // _PyArg_NoKeywords() #include "pycore_moduleobject.h" // _PyModule_GetState() #include "pycore_pylifecycle.h" // _PyOS_URandomNonblock() -#include "pycore_runtime.h" + +#ifdef HAVE_UNISTD_H +# include // getpid() +#endif #ifdef HAVE_PROCESS_H # include // getpid() #endif - #ifdef MS_WINDOWS -# include +# include // GetCurrentProcessId() #endif /* Period parameters -- These are all magic. Don't change. */ @@ -171,6 +175,7 @@ genrand_uint32(RandomObject *self) */ /*[clinic input] +@critical_section _random.Random.random self: self(type="RandomObject *") @@ -180,7 +185,7 @@ random() -> x in the interval [0, 1). static PyObject * _random_Random_random_impl(RandomObject *self) -/*[clinic end generated code: output=117ff99ee53d755c input=afb2a59cbbb00349]*/ +/*[clinic end generated code: output=117ff99ee53d755c input=26492e52d26e8b7b]*/ { uint32_t a=genrand_uint32(self)>>5, b=genrand_uint32(self)>>6; return PyFloat_FromDouble((a*67108864.0+b)*(1.0/9007199254740992.0)); @@ -364,6 +369,7 @@ random_seed(RandomObject *self, PyObject *arg) } /*[clinic input] +@critical_section _random.Random.seed self: self(type="RandomObject *") @@ -378,7 +384,7 @@ of the current time and the process identifier. static PyObject * _random_Random_seed_impl(RandomObject *self, PyObject *n) -/*[clinic end generated code: output=0fad1e16ba883681 input=78d6ef0d52532a54]*/ +/*[clinic end generated code: output=0fad1e16ba883681 input=46d01d2ba938c7b1]*/ { if (random_seed(self, n) < 0) { return NULL; @@ -387,6 +393,7 @@ _random_Random_seed_impl(RandomObject *self, PyObject *n) } /*[clinic input] +@critical_section _random.Random.getstate self: self(type="RandomObject *") @@ -396,7 +403,7 @@ getstate() -> tuple containing the current state. static PyObject * _random_Random_getstate_impl(RandomObject *self) -/*[clinic end generated code: output=bf6cef0c092c7180 input=b937a487928c0e89]*/ +/*[clinic end generated code: output=bf6cef0c092c7180 input=b6621f31eb639694]*/ { PyObject *state; PyObject *element; @@ -424,6 +431,7 @@ _random_Random_getstate_impl(RandomObject *self) /*[clinic input] +@critical_section _random.Random.setstate self: self(type="RandomObject *") @@ -434,8 +442,8 @@ setstate(state) -> None. Restores generator state. [clinic start generated code]*/ static PyObject * -_random_Random_setstate(RandomObject *self, PyObject *state) -/*[clinic end generated code: output=fd1c3cd0037b6681 input=b3b4efbb1bc66af8]*/ +_random_Random_setstate_impl(RandomObject *self, PyObject *state) +/*[clinic end generated code: output=babfc2c2eac6b027 input=358e898ec07469b7]*/ { int i; unsigned long element; @@ -475,7 +483,7 @@ _random_Random_setstate(RandomObject *self, PyObject *state) } /*[clinic input] - +@critical_section _random.Random.getrandbits self: self(type="RandomObject *") @@ -487,7 +495,7 @@ getrandbits(k) -> x. Generates an int with k random bits. static PyObject * _random_Random_getrandbits_impl(RandomObject *self, int k) -/*[clinic end generated code: output=b402f82a2158887f input=8c0e6396dd176fc0]*/ +/*[clinic end generated code: output=b402f82a2158887f input=87603cd60f79f730]*/ { int i, words; uint32_t r; diff --git a/Modules/_scproxy.c b/Modules/_scproxy.c index 0df0324df55f7d..fe82e918677f9a 100644 --- a/Modules/_scproxy.c +++ b/Modules/_scproxy.c @@ -2,6 +2,14 @@ * Helper method for urllib to fetch the proxy configuration settings * using the SystemConfiguration framework. */ + +#include "pyconfig.h" // Py_GIL_DISABLED + +#ifndef Py_GIL_DISABLED +// Need limited C API version 3.12 for Py_MOD_PER_INTERPRETER_GIL_SUPPORTED +#define Py_LIMITED_API 0x030c0000 +#endif + #include #include @@ -21,8 +29,7 @@ cfstring_to_pystring(CFStringRef ref) s = CFStringGetCStringPtr(ref, kCFStringEncodingUTF8); if (s) { - return PyUnicode_DecodeUTF8( - s, strlen(s), NULL); + return PyUnicode_DecodeUTF8(s, strlen(s), NULL); } else { CFIndex len = CFStringGetLength(ref); @@ -43,8 +50,7 @@ cfstring_to_pystring(CFStringRef ref) PyMem_Free(buf); return NULL; } else { - result = PyUnicode_DecodeUTF8( - buf, strlen(buf), NULL); + result = PyUnicode_DecodeUTF8(buf, strlen(buf), NULL); PyMem_Free(buf); } return result; @@ -84,7 +90,7 @@ get_proxy_settings(PyObject* Py_UNUSED(mod), PyObject *Py_UNUSED(ignored)) if (v == NULL) goto error; r = PyDict_SetItemString(result, "exclude_simple", v); - Py_SETREF(v, NULL); + Py_CLEAR(v); if (r == -1) goto error; anArray = CFDictionaryGetValue(proxyDict, @@ -104,13 +110,11 @@ get_proxy_settings(PyObject* Py_UNUSED(mod), PyObject *Py_UNUSED(ignored)) aString = CFArrayGetValueAtIndex(anArray, i); if (aString == NULL) { - PyTuple_SetItem(v, i, Py_None); - Py_INCREF(Py_None); + PyTuple_SetItem(v, i, Py_NewRef(Py_None)); } else { PyObject* t = cfstring_to_pystring(aString); if (!t) { - PyTuple_SetItem(v, i, Py_None); - Py_INCREF(Py_None); + PyTuple_SetItem(v, i, Py_NewRef(Py_None)); } else { PyTuple_SetItem(v, i, t); } @@ -148,15 +152,13 @@ set_proxy(PyObject* proxies, const char* proto, CFDictionaryRef proxyDict, if (h) { if (aNum) { int32_t port = cfnum_to_int32(aNum); - v = PyUnicode_FromFormat("http://%U:%ld", - h, (long)port); + v = PyUnicode_FromFormat("http://%U:%ld", h, (long)port); } else { v = PyUnicode_FromFormat("http://%U", h); } Py_DECREF(h); if (!v) return -1; - r = PyDict_SetItemString(proxies, proto, - v); + r = PyDict_SetItemString(proxies, proto, v); Py_DECREF(v); return r; } @@ -249,16 +251,8 @@ static struct PyModuleDef _scproxy_module = { .m_slots = _scproxy_slots, }; -#ifdef __cplusplus -extern "C" { -#endif - PyMODINIT_FUNC PyInit__scproxy(void) { return PyModuleDef_Init(&_scproxy_module); } - -#ifdef __cplusplus -} -#endif diff --git a/Modules/_sqlite/clinic/_sqlite3.connect.c.h b/Modules/_sqlite/clinic/_sqlite3.connect.c.h new file mode 100644 index 00000000000000..1bcda7702c2568 --- /dev/null +++ b/Modules/_sqlite/clinic/_sqlite3.connect.c.h @@ -0,0 +1,31 @@ +/*[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 +#include "pycore_modsupport.h" // _PyArg_UnpackKeywords() + +PyDoc_STRVAR(pysqlite_connect__doc__, +"connect($module, /, database, timeout=5.0, detect_types=0,\n" +" isolation_level=\'\', check_same_thread=True,\n" +" factory=ConnectionType, cached_statements=128, uri=False, *,\n" +" autocommit=sqlite3.LEGACY_TRANSACTION_CONTROL)\n" +"--\n" +"\n" +"Open a connection to the SQLite database file \'database\'.\n" +"\n" +"You can use \":memory:\" to open a database connection to a database that\n" +"resides in RAM instead of on disk.\n" +"\n" +"Note: Passing more than 1 positional argument to _sqlite3.connect() is\n" +"deprecated. Parameters \'timeout\', \'detect_types\', \'isolation_level\',\n" +"\'check_same_thread\', \'factory\', \'cached_statements\' and \'uri\' will\n" +"become keyword-only parameters in Python 3.15.\n" +""); + +#define PYSQLITE_CONNECT_METHODDEF \ + {"connect", _PyCFunction_CAST(pysqlite_connect), METH_FASTCALL|METH_KEYWORDS, pysqlite_connect__doc__}, +/*[clinic end generated code: output=69b9b00da71c3c0a input=a9049054013a1b77]*/ diff --git a/Modules/_sqlite/clinic/blob.c.h b/Modules/_sqlite/clinic/blob.c.h index f3d8a35be46138..b95ba948aaf97f 100644 --- a/Modules/_sqlite/clinic/blob.c.h +++ b/Modules/_sqlite/clinic/blob.c.h @@ -2,11 +2,7 @@ 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 - +#include "pycore_modsupport.h" // _PyArg_CheckPositional() PyDoc_STRVAR(blob_close__doc__, "close($self, /)\n" @@ -57,7 +53,7 @@ blob_read(pysqlite_Blob *self, PyObject *const *args, Py_ssize_t nargs) if (nargs < 1) { goto skip_optional; } - length = _PyLong_AsInt(args[0]); + length = PyLong_AsInt(args[0]); if (length == -1 && PyErr_Occurred()) { goto exit; } @@ -92,10 +88,6 @@ blob_write(pysqlite_Blob *self, PyObject *arg) if (PyObject_GetBuffer(arg, &data, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("write", "argument", "contiguous buffer", arg); - goto exit; - } return_value = blob_write_impl(self, &data); exit: @@ -133,14 +125,14 @@ blob_seek(pysqlite_Blob *self, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("seek", nargs, 1, 2)) { goto exit; } - offset = _PyLong_AsInt(args[0]); + offset = PyLong_AsInt(args[0]); if (offset == -1 && PyErr_Occurred()) { goto exit; } if (nargs < 2) { goto skip_optional; } - origin = _PyLong_AsInt(args[1]); + origin = PyLong_AsInt(args[1]); if (origin == -1 && PyErr_Occurred()) { goto exit; } @@ -219,4 +211,4 @@ blob_exit(pysqlite_Blob *self, PyObject *const *args, Py_ssize_t nargs) exit: return return_value; } -/*[clinic end generated code: output=ad6a402f70e85977 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=31abd55660e0c5af input=a9049054013a1b77]*/ diff --git a/Modules/_sqlite/clinic/connection.c.h b/Modules/_sqlite/clinic/connection.c.h index e869d7d9e9384c..db5eb77891e52e 100644 --- a/Modules/_sqlite/clinic/connection.c.h +++ b/Modules/_sqlite/clinic/connection.c.h @@ -3,10 +3,10 @@ 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() +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() #endif - +#include "pycore_modsupport.h" // _PyArg_UnpackKeywords() static int pysqlite_connection_init_impl(pysqlite_Connection *self, PyObject *database, @@ -16,6 +16,17 @@ pysqlite_connection_init_impl(pysqlite_Connection *self, PyObject *database, int cache_size, int uri, enum autocommit_mode autocommit); +// Emit compiler warnings when we get to Python 3.15. +#if PY_VERSION_HEX >= 0x030f00C0 +# error "Update the clinic input of '_sqlite3.Connection.__init__'." +#elif PY_VERSION_HEX >= 0x030f00A0 +# ifdef _MSC_VER +# pragma message ("Update the clinic input of '_sqlite3.Connection.__init__'.") +# else +# warning "Update the clinic input of '_sqlite3.Connection.__init__'." +# endif +#endif + static int pysqlite_connection_init(PyObject *self, PyObject *args, PyObject *kwargs) { @@ -59,6 +70,17 @@ pysqlite_connection_init(PyObject *self, PyObject *args, PyObject *kwargs) int uri = 0; enum autocommit_mode autocommit = LEGACY_TRANSACTION_CONTROL; + if (nargs > 1 && nargs <= 8) { + if (PyErr_WarnEx(PyExc_DeprecationWarning, + "Passing more than 1 positional argument to _sqlite3.Connection()" + " is deprecated. Parameters 'timeout', 'detect_types', " + "'isolation_level', 'check_same_thread', 'factory', " + "'cached_statements' and 'uri' will become keyword-only " + "parameters in Python 3.15.", 1)) + { + goto exit; + } + } fastargs = _PyArg_UnpackKeywords(_PyTuple_CAST(args)->ob_item, nargs, kwargs, NULL, &_parser, 1, 8, 0, argsbuf); if (!fastargs) { goto exit; @@ -83,7 +105,7 @@ pysqlite_connection_init(PyObject *self, PyObject *args, PyObject *kwargs) } } if (fastargs[2]) { - detect_types = _PyLong_AsInt(fastargs[2]); + detect_types = PyLong_AsInt(fastargs[2]); if (detect_types == -1 && PyErr_Occurred()) { goto exit; } @@ -115,7 +137,7 @@ pysqlite_connection_init(PyObject *self, PyObject *args, PyObject *kwargs) } } if (fastargs[6]) { - cache_size = _PyLong_AsInt(fastargs[6]); + cache_size = PyLong_AsInt(fastargs[6]); if (cache_size == -1 && PyErr_Occurred()) { goto exit; } @@ -396,7 +418,12 @@ PyDoc_STRVAR(pysqlite_connection_create_function__doc__, "create_function($self, /, name, narg, func, *, deterministic=False)\n" "--\n" "\n" -"Creates a new function."); +"Creates a new function.\n" +"\n" +"Note: Passing keyword arguments \'name\', \'narg\' and \'func\' to\n" +"_sqlite3.Connection.create_function() is deprecated. Parameters\n" +"\'name\', \'narg\' and \'func\' will become positional-only in Python 3.15.\n" +""); #define PYSQLITE_CONNECTION_CREATE_FUNCTION_METHODDEF \ {"create_function", _PyCFunction_CAST(pysqlite_connection_create_function), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, pysqlite_connection_create_function__doc__}, @@ -407,6 +434,17 @@ pysqlite_connection_create_function_impl(pysqlite_Connection *self, int narg, PyObject *func, int deterministic); +// Emit compiler warnings when we get to Python 3.15. +#if PY_VERSION_HEX >= 0x030f00C0 +# error "Update the clinic input of '_sqlite3.Connection.create_function'." +#elif PY_VERSION_HEX >= 0x030f00A0 +# ifdef _MSC_VER +# pragma message ("Update the clinic input of '_sqlite3.Connection.create_function'.") +# else +# warning "Update the clinic input of '_sqlite3.Connection.create_function'." +# endif +#endif + static PyObject * pysqlite_connection_create_function(pysqlite_Connection *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { @@ -447,6 +485,16 @@ pysqlite_connection_create_function(pysqlite_Connection *self, PyTypeObject *cls if (!args) { goto exit; } + if (nargs < 3) { + if (PyErr_WarnEx(PyExc_DeprecationWarning, + "Passing keyword arguments 'name', 'narg' and 'func' to " + "_sqlite3.Connection.create_function() is deprecated. Parameters " + "'name', 'narg' and 'func' will become positional-only in Python " + "3.15.", 1)) + { + goto exit; + } + } if (!PyUnicode_Check(args[0])) { _PyArg_BadArgument("create_function", "argument 'name'", "str", args[0]); goto exit; @@ -460,7 +508,7 @@ pysqlite_connection_create_function(pysqlite_Connection *self, PyTypeObject *cls PyErr_SetString(PyExc_ValueError, "embedded null character"); goto exit; } - narg = _PyLong_AsInt(args[1]); + narg = PyLong_AsInt(args[1]); if (narg == -1 && PyErr_Occurred()) { goto exit; } @@ -543,7 +591,7 @@ create_window_function(pysqlite_Connection *self, PyTypeObject *cls, PyObject *c PyErr_SetString(PyExc_ValueError, "embedded null character"); goto exit; } - num_params = _PyLong_AsInt(args[1]); + num_params = PyLong_AsInt(args[1]); if (num_params == -1 && PyErr_Occurred()) { goto exit; } @@ -560,7 +608,13 @@ PyDoc_STRVAR(pysqlite_connection_create_aggregate__doc__, "create_aggregate($self, /, name, n_arg, aggregate_class)\n" "--\n" "\n" -"Creates a new aggregate."); +"Creates a new aggregate.\n" +"\n" +"Note: Passing keyword arguments \'name\', \'n_arg\' and \'aggregate_class\'\n" +"to _sqlite3.Connection.create_aggregate() is deprecated. Parameters\n" +"\'name\', \'n_arg\' and \'aggregate_class\' will become positional-only in\n" +"Python 3.15.\n" +""); #define PYSQLITE_CONNECTION_CREATE_AGGREGATE_METHODDEF \ {"create_aggregate", _PyCFunction_CAST(pysqlite_connection_create_aggregate), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, pysqlite_connection_create_aggregate__doc__}, @@ -571,6 +625,17 @@ pysqlite_connection_create_aggregate_impl(pysqlite_Connection *self, const char *name, int n_arg, PyObject *aggregate_class); +// Emit compiler warnings when we get to Python 3.15. +#if PY_VERSION_HEX >= 0x030f00C0 +# error "Update the clinic input of '_sqlite3.Connection.create_aggregate'." +#elif PY_VERSION_HEX >= 0x030f00A0 +# ifdef _MSC_VER +# pragma message ("Update the clinic input of '_sqlite3.Connection.create_aggregate'.") +# else +# warning "Update the clinic input of '_sqlite3.Connection.create_aggregate'." +# endif +#endif + static PyObject * pysqlite_connection_create_aggregate(pysqlite_Connection *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { @@ -609,6 +674,16 @@ pysqlite_connection_create_aggregate(pysqlite_Connection *self, PyTypeObject *cl if (!args) { goto exit; } + if (nargs < 3) { + if (PyErr_WarnEx(PyExc_DeprecationWarning, + "Passing keyword arguments 'name', 'n_arg' and 'aggregate_class' " + "to _sqlite3.Connection.create_aggregate() is deprecated. " + "Parameters 'name', 'n_arg' and 'aggregate_class' will become " + "positional-only in Python 3.15.", 1)) + { + goto exit; + } + } if (!PyUnicode_Check(args[0])) { _PyArg_BadArgument("create_aggregate", "argument 'name'", "str", args[0]); goto exit; @@ -622,7 +697,7 @@ pysqlite_connection_create_aggregate(pysqlite_Connection *self, PyTypeObject *cl PyErr_SetString(PyExc_ValueError, "embedded null character"); goto exit; } - n_arg = _PyLong_AsInt(args[1]); + n_arg = PyLong_AsInt(args[1]); if (n_arg == -1 && PyErr_Occurred()) { goto exit; } @@ -637,7 +712,12 @@ PyDoc_STRVAR(pysqlite_connection_set_authorizer__doc__, "set_authorizer($self, /, authorizer_callback)\n" "--\n" "\n" -"Sets authorizer callback."); +"Set authorizer callback.\n" +"\n" +"Note: Passing keyword argument \'authorizer_callback\' to\n" +"_sqlite3.Connection.set_authorizer() is deprecated. Parameter\n" +"\'authorizer_callback\' will become positional-only in Python 3.15.\n" +""); #define PYSQLITE_CONNECTION_SET_AUTHORIZER_METHODDEF \ {"set_authorizer", _PyCFunction_CAST(pysqlite_connection_set_authorizer), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, pysqlite_connection_set_authorizer__doc__}, @@ -647,13 +727,24 @@ pysqlite_connection_set_authorizer_impl(pysqlite_Connection *self, PyTypeObject *cls, PyObject *callable); +// Emit compiler warnings when we get to Python 3.15. +#if PY_VERSION_HEX >= 0x030f00C0 +# error "Update the clinic input of '_sqlite3.Connection.set_authorizer'." +#elif PY_VERSION_HEX >= 0x030f00A0 +# ifdef _MSC_VER +# pragma message ("Update the clinic input of '_sqlite3.Connection.set_authorizer'.") +# else +# warning "Update the clinic input of '_sqlite3.Connection.set_authorizer'." +# endif +#endif + static PyObject * pysqlite_connection_set_authorizer(pysqlite_Connection *self, PyTypeObject *cls, 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 + #define NUM_KEYWORDS 2 static struct { PyGC_Head _this_is_not_used; PyObject_VAR_HEAD @@ -683,6 +774,16 @@ pysqlite_connection_set_authorizer(pysqlite_Connection *self, PyTypeObject *cls, if (!args) { goto exit; } + if (nargs < 1) { + if (PyErr_WarnEx(PyExc_DeprecationWarning, + "Passing keyword argument 'authorizer_callback' to " + "_sqlite3.Connection.set_authorizer() is deprecated. Parameter " + "'authorizer_callback' will become positional-only in Python " + "3.15.", 1)) + { + goto exit; + } + } callable = args[0]; return_value = pysqlite_connection_set_authorizer_impl(self, cls, callable); @@ -694,7 +795,22 @@ PyDoc_STRVAR(pysqlite_connection_set_progress_handler__doc__, "set_progress_handler($self, /, progress_handler, n)\n" "--\n" "\n" -"Sets progress handler callback."); +"Set progress handler callback.\n" +"\n" +" progress_handler\n" +" A callable that takes no arguments.\n" +" If the callable returns non-zero, the current query is terminated,\n" +" and an exception is raised.\n" +" n\n" +" The number of SQLite virtual machine instructions that are\n" +" executed between invocations of \'progress_handler\'.\n" +"\n" +"If \'progress_handler\' is None or \'n\' is 0, the progress handler is disabled.\n" +"\n" +"Note: Passing keyword argument \'progress_handler\' to\n" +"_sqlite3.Connection.set_progress_handler() is deprecated. Parameter\n" +"\'progress_handler\' will become positional-only in Python 3.15.\n" +""); #define PYSQLITE_CONNECTION_SET_PROGRESS_HANDLER_METHODDEF \ {"set_progress_handler", _PyCFunction_CAST(pysqlite_connection_set_progress_handler), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, pysqlite_connection_set_progress_handler__doc__}, @@ -704,13 +820,24 @@ pysqlite_connection_set_progress_handler_impl(pysqlite_Connection *self, PyTypeObject *cls, PyObject *callable, int n); +// Emit compiler warnings when we get to Python 3.15. +#if PY_VERSION_HEX >= 0x030f00C0 +# error "Update the clinic input of '_sqlite3.Connection.set_progress_handler'." +#elif PY_VERSION_HEX >= 0x030f00A0 +# ifdef _MSC_VER +# pragma message ("Update the clinic input of '_sqlite3.Connection.set_progress_handler'.") +# else +# warning "Update the clinic input of '_sqlite3.Connection.set_progress_handler'." +# endif +#endif + static PyObject * pysqlite_connection_set_progress_handler(pysqlite_Connection *self, PyTypeObject *cls, 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 + #define NUM_KEYWORDS 3 static struct { PyGC_Head _this_is_not_used; PyObject_VAR_HEAD @@ -741,8 +868,18 @@ pysqlite_connection_set_progress_handler(pysqlite_Connection *self, PyTypeObject if (!args) { goto exit; } + if (nargs < 1) { + if (PyErr_WarnEx(PyExc_DeprecationWarning, + "Passing keyword argument 'progress_handler' to " + "_sqlite3.Connection.set_progress_handler() is deprecated. " + "Parameter 'progress_handler' will become positional-only in " + "Python 3.15.", 1)) + { + goto exit; + } + } callable = args[0]; - n = _PyLong_AsInt(args[1]); + n = PyLong_AsInt(args[1]); if (n == -1 && PyErr_Occurred()) { goto exit; } @@ -756,7 +893,12 @@ PyDoc_STRVAR(pysqlite_connection_set_trace_callback__doc__, "set_trace_callback($self, /, trace_callback)\n" "--\n" "\n" -"Sets a trace callback called for each SQL statement (passed as unicode)."); +"Set a trace callback called for each SQL statement (passed as unicode).\n" +"\n" +"Note: Passing keyword argument \'trace_callback\' to\n" +"_sqlite3.Connection.set_trace_callback() is deprecated. Parameter\n" +"\'trace_callback\' will become positional-only in Python 3.15.\n" +""); #define PYSQLITE_CONNECTION_SET_TRACE_CALLBACK_METHODDEF \ {"set_trace_callback", _PyCFunction_CAST(pysqlite_connection_set_trace_callback), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, pysqlite_connection_set_trace_callback__doc__}, @@ -766,13 +908,24 @@ pysqlite_connection_set_trace_callback_impl(pysqlite_Connection *self, PyTypeObject *cls, PyObject *callable); +// Emit compiler warnings when we get to Python 3.15. +#if PY_VERSION_HEX >= 0x030f00C0 +# error "Update the clinic input of '_sqlite3.Connection.set_trace_callback'." +#elif PY_VERSION_HEX >= 0x030f00A0 +# ifdef _MSC_VER +# pragma message ("Update the clinic input of '_sqlite3.Connection.set_trace_callback'.") +# else +# warning "Update the clinic input of '_sqlite3.Connection.set_trace_callback'." +# endif +#endif + static PyObject * pysqlite_connection_set_trace_callback(pysqlite_Connection *self, PyTypeObject *cls, 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 + #define NUM_KEYWORDS 2 static struct { PyGC_Head _this_is_not_used; PyObject_VAR_HEAD @@ -802,6 +955,16 @@ pysqlite_connection_set_trace_callback(pysqlite_Connection *self, PyTypeObject * if (!args) { goto exit; } + if (nargs < 1) { + if (PyErr_WarnEx(PyExc_DeprecationWarning, + "Passing keyword argument 'trace_callback' to " + "_sqlite3.Connection.set_trace_callback() is deprecated. " + "Parameter 'trace_callback' will become positional-only in Python" + " 3.15.", 1)) + { + goto exit; + } + } callable = args[0]; return_value = pysqlite_connection_set_trace_callback_impl(self, cls, callable); @@ -1124,7 +1287,7 @@ pysqlite_connection_backup(pysqlite_Connection *self, PyObject *const *args, Py_ goto skip_optional_kwonly; } if (args[1]) { - pages = _PyLong_AsInt(args[1]); + pages = PyLong_AsInt(args[1]); if (pages == -1 && PyErr_Occurred()) { goto exit; } @@ -1394,10 +1557,6 @@ deserialize(pysqlite_Connection *self, PyObject *const *args, Py_ssize_t nargs, if (PyObject_GetBuffer(args[0], &data, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("deserialize", "argument 1", "contiguous buffer", args[0]); - goto exit; - } } if (!noptargs) { goto skip_optional_kwonly; @@ -1516,11 +1675,11 @@ setlimit(pysqlite_Connection *self, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("setlimit", nargs, 2, 2)) { goto exit; } - category = _PyLong_AsInt(args[0]); + category = PyLong_AsInt(args[0]); if (category == -1 && PyErr_Occurred()) { goto exit; } - limit = _PyLong_AsInt(args[1]); + limit = PyLong_AsInt(args[1]); if (limit == -1 && PyErr_Occurred()) { goto exit; } @@ -1551,7 +1710,7 @@ getlimit(pysqlite_Connection *self, PyObject *arg) PyObject *return_value = NULL; int category; - category = _PyLong_AsInt(arg); + category = PyLong_AsInt(arg); if (category == -1 && PyErr_Occurred()) { goto exit; } @@ -1586,7 +1745,7 @@ setconfig(pysqlite_Connection *self, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("setconfig", nargs, 1, 2)) { goto exit; } - op = _PyLong_AsInt(args[0]); + op = PyLong_AsInt(args[0]); if (op == -1 && PyErr_Occurred()) { goto exit; } @@ -1626,7 +1785,7 @@ getconfig(pysqlite_Connection *self, PyObject *arg) int op; int _return_value; - op = _PyLong_AsInt(arg); + op = PyLong_AsInt(arg); if (op == -1 && PyErr_Occurred()) { goto exit; } @@ -1659,4 +1818,4 @@ getconfig(pysqlite_Connection *self, PyObject *arg) #ifndef DESERIALIZE_METHODDEF #define DESERIALIZE_METHODDEF #endif /* !defined(DESERIALIZE_METHODDEF) */ -/*[clinic end generated code: output=d3c6cb9326736ea5 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=90b5b9c14261b8d7 input=a9049054013a1b77]*/ diff --git a/Modules/_sqlite/clinic/cursor.c.h b/Modules/_sqlite/clinic/cursor.c.h index 08b6a732b7bac5..a13e0d0745b58d 100644 --- a/Modules/_sqlite/clinic/cursor.c.h +++ b/Modules/_sqlite/clinic/cursor.c.h @@ -3,10 +3,10 @@ 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() +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() #endif - +#include "pycore_modsupport.h" // _PyArg_CheckPositional() static int pysqlite_cursor_init_impl(pysqlite_Cursor *self, @@ -223,7 +223,7 @@ pysqlite_cursor_fetchmany(pysqlite_Cursor *self, PyObject *const *args, Py_ssize if (!noptargs) { goto skip_optional_pos; } - maxrows = _PyLong_AsInt(args[0]); + maxrows = PyLong_AsInt(args[0]); if (maxrows == -1 && PyErr_Occurred()) { goto exit; } @@ -313,4 +313,4 @@ pysqlite_cursor_close(pysqlite_Cursor *self, PyObject *Py_UNUSED(ignored)) { return pysqlite_cursor_close_impl(self); } -/*[clinic end generated code: output=831f7bc5256526d3 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=a8ce095c3c80cf65 input=a9049054013a1b77]*/ diff --git a/Modules/_sqlite/clinic/module.c.h b/Modules/_sqlite/clinic/module.c.h index 94002b015fc779..529dc4e281e0eb 100644 --- a/Modules/_sqlite/clinic/module.c.h +++ b/Modules/_sqlite/clinic/module.c.h @@ -3,10 +3,10 @@ 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() +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() #endif - +#include "pycore_modsupport.h" // _PyArg_UnpackKeywords() PyDoc_STRVAR(pysqlite_complete_statement__doc__, "complete_statement($module, /, statement)\n" @@ -159,7 +159,7 @@ pysqlite_enable_callback_trace(PyObject *module, PyObject *arg) PyObject *return_value = NULL; int enable; - enable = _PyLong_AsInt(arg); + enable = PyLong_AsInt(arg); if (enable == -1 && PyErr_Occurred()) { goto exit; } @@ -208,4 +208,4 @@ pysqlite_adapt(PyObject *module, PyObject *const *args, Py_ssize_t nargs) exit: return return_value; } -/*[clinic end generated code: output=e08e6856ae546e7b input=a9049054013a1b77]*/ +/*[clinic end generated code: output=457ab0fdbb9e1880 input=a9049054013a1b77]*/ diff --git a/Modules/_sqlite/clinic/row.c.h b/Modules/_sqlite/clinic/row.c.h index 89a48fd52da226..e8d1dbf2ba8bc9 100644 --- a/Modules/_sqlite/clinic/row.c.h +++ b/Modules/_sqlite/clinic/row.c.h @@ -2,11 +2,7 @@ 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 - +#include "pycore_modsupport.h" // _PyArg_CheckPositional() static PyObject * pysqlite_row_new_impl(PyTypeObject *type, pysqlite_Cursor *cursor, @@ -60,4 +56,4 @@ pysqlite_row_keys(pysqlite_Row *self, PyObject *Py_UNUSED(ignored)) { return pysqlite_row_keys_impl(self); } -/*[clinic end generated code: output=157b31ac3f6af1ba input=a9049054013a1b77]*/ +/*[clinic end generated code: output=788bf817acc02b8e input=a9049054013a1b77]*/ diff --git a/Modules/_sqlite/connection.c b/Modules/_sqlite/connection.c index ddd7ace81198bb..0a6633972cc5ef 100644 --- a/Modules/_sqlite/connection.c +++ b/Modules/_sqlite/connection.c @@ -33,7 +33,10 @@ #include "blob.h" #include "prepare_protocol.h" #include "util.h" + #include "pycore_import.h" // _PyImport_GetModuleAttrString() +#include "pycore_modsupport.h" // _PyArg_NoKeywords() +#include "pycore_pyerrors.h" // _PyErr_ChainExceptions1() #include "pycore_pylifecycle.h" // _Py_IsInterpreterFinalizing() #include "pycore_weakref.h" // _PyWeakref_IS_DEAD() @@ -73,16 +76,10 @@ isolation_level_converter(PyObject *str_or_none, const char **result) *result = NULL; } else if (PyUnicode_Check(str_or_none)) { - Py_ssize_t sz; - const char *str = PyUnicode_AsUTF8AndSize(str_or_none, &sz); + const char *str = _PyUnicode_AsUTF8NoNUL(str_or_none); if (str == NULL) { return 0; } - if (strlen(str) != (size_t)sz) { - PyErr_SetString(PyExc_ValueError, "embedded null character"); - return 0; - } - const char *level = get_isolation_level(str); if (level == NULL) { return 0; @@ -149,7 +146,7 @@ static void _pysqlite_drop_unused_cursor_references(pysqlite_Connection* self); static void free_callback_context(callback_context *ctx); static void set_callback_context(callback_context **ctx_pp, callback_context *ctx); -static void connection_close(pysqlite_Connection *self); +static int connection_close(pysqlite_Connection *self); PyObject *_pysqlite_query_execute(pysqlite_Cursor *, int, PyObject *, PyObject *); static PyObject * @@ -212,11 +209,11 @@ class sqlite3_int64_converter(CConverter): [python start generated code]*/ /*[python end generated code: output=da39a3ee5e6b4b0d input=dff8760fb1eba6a1]*/ -// NB: This needs to be in sync with the sqlite3.connect docstring /*[clinic input] _sqlite3.Connection.__init__ as pysqlite_connection_init database: object + * [from 3.15] timeout: double = 5.0 detect_types: int = 0 isolation_level: IsolationLevel = "" @@ -235,7 +232,7 @@ pysqlite_connection_init_impl(pysqlite_Connection *self, PyObject *database, int check_same_thread, PyObject *factory, int cache_size, int uri, enum autocommit_mode autocommit) -/*[clinic end generated code: output=cba057313ea7712f input=9b0ab6c12f674fa3]*/ +/*[clinic end generated code: output=cba057313ea7712f input=219c3dbecbae7d99]*/ { if (PySys_Audit("sqlite3.connect", "O", database) < 0) { return -1; @@ -247,10 +244,13 @@ pysqlite_connection_init_impl(pysqlite_Connection *self, PyObject *database, } if (self->initialized) { + self->initialized = 0; + PyTypeObject *tp = Py_TYPE(self); tp->tp_clear((PyObject *)self); - connection_close(self); - self->initialized = 0; + if (connection_close(self) < 0) { + return -1; + } } // Create and configure SQLite database object. @@ -334,7 +334,9 @@ pysqlite_connection_init_impl(pysqlite_Connection *self, PyObject *database, self->initialized = 1; if (autocommit == AUTOCOMMIT_DISABLED) { - (void)connection_exec_stmt(self, "BEGIN"); + if (connection_exec_stmt(self, "BEGIN") < 0) { + return -1; + } } return 0; @@ -346,6 +348,34 @@ pysqlite_connection_init_impl(pysqlite_Connection *self, PyObject *database, return -1; } +/*[clinic input] +# Create a new destination 'connect' for the docstring and methoddef only. +# This makes it possible to keep the signatures for Connection.__init__ and +# sqlite3.connect() synchronised. +output push +destination connect new file '{dirname}/clinic/_sqlite3.connect.c.h' + +# Only output the docstring and the PyMethodDef entry. +output everything suppress +output docstring_definition connect +output methoddef_define connect + +# Define the sqlite3.connect function by cloning Connection.__init__. +_sqlite3.connect as pysqlite_connect = _sqlite3.Connection.__init__ + +Open a connection to the SQLite database file 'database'. + +You can use ":memory:" to open a database connection to a database that +resides in RAM instead of on disk. +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=92260edff95d1720]*/ + +/*[clinic input] +# Restore normal Argument Clinic operation for the rest of this file. +output pop +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=b899ba9273edcce7]*/ + #define VISIT_CALLBACK_CONTEXT(ctx) \ do { \ if (ctx) { \ @@ -404,48 +434,91 @@ free_callback_contexts(pysqlite_Connection *self) static void remove_callbacks(sqlite3 *db) { - sqlite3_trace_v2(db, SQLITE_TRACE_STMT, 0, 0); + /* None of these APIs can fail, as long as they are given a valid + * database pointer. */ + assert(db != NULL); + int rc = sqlite3_trace_v2(db, SQLITE_TRACE_STMT, 0, 0); + assert(rc == SQLITE_OK), (void)rc; + sqlite3_progress_handler(db, 0, 0, (void *)0); - (void)sqlite3_set_authorizer(db, NULL, NULL); + + rc = sqlite3_set_authorizer(db, NULL, NULL); + assert(rc == SQLITE_OK), (void)rc; } -static void +static int connection_close(pysqlite_Connection *self) { - if (self->db) { - if (self->autocommit == AUTOCOMMIT_DISABLED && - !sqlite3_get_autocommit(self->db)) - { - /* If close is implicitly called as a result of interpreter - * tear-down, we must not call back into Python. */ - if (_Py_IsInterpreterFinalizing(PyInterpreterState_Get())) { - remove_callbacks(self->db); - } - (void)connection_exec_stmt(self, "ROLLBACK"); + if (self->db == NULL) { + return 0; + } + + int rc = 0; + if (self->autocommit == AUTOCOMMIT_DISABLED && + !sqlite3_get_autocommit(self->db)) + { + if (connection_exec_stmt(self, "ROLLBACK") < 0) { + rc = -1; } + } - free_callback_contexts(self); + sqlite3 *db = self->db; + self->db = NULL; - sqlite3 *db = self->db; - self->db = NULL; + Py_BEGIN_ALLOW_THREADS + /* The v2 close call always returns SQLITE_OK if given a valid database + * pointer (which we do), so we can safely ignore the return value */ + (void)sqlite3_close_v2(db); + Py_END_ALLOW_THREADS - Py_BEGIN_ALLOW_THREADS - int rc = sqlite3_close_v2(db); - assert(rc == SQLITE_OK), (void)rc; - Py_END_ALLOW_THREADS - } + free_callback_contexts(self); + return rc; } static void -connection_dealloc(pysqlite_Connection *self) +connection_finalize(PyObject *self) { - PyTypeObject *tp = Py_TYPE(self); - PyObject_GC_UnTrack(self); - tp->tp_clear((PyObject *)self); + pysqlite_Connection *con = (pysqlite_Connection *)self; + PyObject *exc = PyErr_GetRaisedException(); + + /* If close is implicitly called as a result of interpreter + * tear-down, we must not call back into Python. */ + PyInterpreterState *interp = PyInterpreterState_Get(); + int teardown = _Py_IsInterpreterFinalizing(interp); + if (teardown && con->db) { + remove_callbacks(con->db); + } /* Clean up if user has not called .close() explicitly. */ - connection_close(self); + if (con->db) { + if (PyErr_ResourceWarning(self, 1, "unclosed database in %R", self)) { + /* Spurious errors can appear at shutdown */ + if (PyErr_ExceptionMatches(PyExc_Warning)) { + PyErr_WriteUnraisable(self); + } + } + } + if (connection_close(con) < 0) { + if (teardown) { + PyErr_Clear(); + } + else { + PyErr_WriteUnraisable((PyObject *)self); + } + } + + PyErr_SetRaisedException(exc); +} +static void +connection_dealloc(PyObject *self) +{ + if (PyObject_CallFinalizerFromDealloc(self) < 0) { + return; + } + PyTypeObject *tp = Py_TYPE(self); + PyObject_GC_UnTrack(self); + tp->tp_clear(self); tp->tp_free(self); Py_DECREF(tp); } @@ -593,7 +666,9 @@ pysqlite_connection_close_impl(pysqlite_Connection *self) pysqlite_close_all_blobs(self); Py_CLEAR(self->statement_cache); - connection_close(self); + if (connection_close(self) < 0) { + return NULL; + } Py_RETURN_NONE; } @@ -1061,6 +1136,7 @@ _sqlite3.Connection.create_function as pysqlite_connection_create_function name: str narg: int func: object + / [from 3.15] * deterministic: bool = False @@ -1072,7 +1148,7 @@ pysqlite_connection_create_function_impl(pysqlite_Connection *self, PyTypeObject *cls, const char *name, int narg, PyObject *func, int deterministic) -/*[clinic end generated code: output=8a811529287ad240 input=b3e8e1d8ddaffbef]*/ +/*[clinic end generated code: output=8a811529287ad240 input=c7c313b0ca8b519e]*/ { int rc; int flags = SQLITE_UTF8; @@ -1263,6 +1339,7 @@ _sqlite3.Connection.create_aggregate as pysqlite_connection_create_aggregate name: str n_arg: int aggregate_class: object + / [from 3.15] Creates a new aggregate. [clinic start generated code]*/ @@ -1272,7 +1349,7 @@ pysqlite_connection_create_aggregate_impl(pysqlite_Connection *self, PyTypeObject *cls, const char *name, int n_arg, PyObject *aggregate_class) -/*[clinic end generated code: output=1b02d0f0aec7ff96 input=68a2a26366d4c686]*/ +/*[clinic end generated code: output=1b02d0f0aec7ff96 input=8087056db6eae1cf]*/ { int rc; @@ -1318,7 +1395,7 @@ authorizer_callback(void *ctx, int action, const char *arg1, } else { if (PyLong_Check(ret)) { - rc = _PyLong_AsInt(ret); + rc = PyLong_AsInt(ret); if (rc == -1 && PyErr_Occurred()) { print_or_clear_traceback(ctx); rc = SQLITE_DENY; @@ -1419,17 +1496,17 @@ trace_callback(unsigned int type, void *ctx, void *stmt, void *sql) _sqlite3.Connection.set_authorizer as pysqlite_connection_set_authorizer cls: defining_class - / authorizer_callback as callable: object + / [from 3.15] -Sets authorizer callback. +Set authorizer callback. [clinic start generated code]*/ static PyObject * pysqlite_connection_set_authorizer_impl(pysqlite_Connection *self, PyTypeObject *cls, PyObject *callable) -/*[clinic end generated code: output=75fa60114fc971c3 input=605d32ba92dd3eca]*/ +/*[clinic end generated code: output=75fa60114fc971c3 input=a52bd4937c588752]*/ { if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) { return NULL; @@ -1461,18 +1538,25 @@ pysqlite_connection_set_authorizer_impl(pysqlite_Connection *self, _sqlite3.Connection.set_progress_handler as pysqlite_connection_set_progress_handler cls: defining_class - / progress_handler as callable: object + A callable that takes no arguments. + If the callable returns non-zero, the current query is terminated, + and an exception is raised. + / [from 3.15] n: int + The number of SQLite virtual machine instructions that are + executed between invocations of 'progress_handler'. -Sets progress handler callback. +Set progress handler callback. + +If 'progress_handler' is None or 'n' is 0, the progress handler is disabled. [clinic start generated code]*/ static PyObject * pysqlite_connection_set_progress_handler_impl(pysqlite_Connection *self, PyTypeObject *cls, PyObject *callable, int n) -/*[clinic end generated code: output=0739957fd8034a50 input=f7c1837984bd86db]*/ +/*[clinic end generated code: output=0739957fd8034a50 input=b4d6e2ef8b4d32f9]*/ { if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) { return NULL; @@ -1498,17 +1582,17 @@ pysqlite_connection_set_progress_handler_impl(pysqlite_Connection *self, _sqlite3.Connection.set_trace_callback as pysqlite_connection_set_trace_callback cls: defining_class - / trace_callback as callable: object + / [from 3.15] -Sets a trace callback called for each SQL statement (passed as unicode). +Set a trace callback called for each SQL statement (passed as unicode). [clinic start generated code]*/ static PyObject * pysqlite_connection_set_trace_callback_impl(pysqlite_Connection *self, PyTypeObject *cls, PyObject *callable) -/*[clinic end generated code: output=d91048c03bfcee05 input=351a94210c5f81bb]*/ +/*[clinic end generated code: output=d91048c03bfcee05 input=d705d592ec03cf28]*/ { if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) { return NULL; @@ -2527,6 +2611,7 @@ static struct PyMemberDef connection_members[] = }; static PyType_Slot connection_slots[] = { + {Py_tp_finalize, connection_finalize}, {Py_tp_dealloc, connection_dealloc}, {Py_tp_doc, (void *)connection_doc}, {Py_tp_methods, connection_methods}, diff --git a/Modules/_sqlite/cursor.c b/Modules/_sqlite/cursor.c index 618ce532b2518d..f95df612328e57 100644 --- a/Modules/_sqlite/cursor.c +++ b/Modules/_sqlite/cursor.c @@ -721,7 +721,6 @@ bind_parameters(pysqlite_state *state, pysqlite_Statement *self, } else if (PyDict_Check(parameters)) { /* parameters passed as dictionary */ for (i = 1; i <= num_params_needed; i++) { - PyObject *binding_name_obj; Py_BEGIN_ALLOW_THREADS binding_name = sqlite3_bind_parameter_name(self->st, i); Py_END_ALLOW_THREADS @@ -733,17 +732,8 @@ bind_parameters(pysqlite_state *state, pysqlite_Statement *self, } binding_name++; /* skip first char (the colon) */ - binding_name_obj = PyUnicode_FromString(binding_name); - if (!binding_name_obj) { - return; - } - if (PyDict_CheckExact(parameters)) { - PyObject *item = PyDict_GetItemWithError(parameters, binding_name_obj); - current_param = Py_XNewRef(item); - } else { - current_param = PyObject_GetItem(parameters, binding_name_obj); - } - Py_DECREF(binding_name_obj); + PyObject *current_param; + (void)PyMapping_GetOptionalItemString(parameters, binding_name, ¤t_param); if (!current_param) { if (!PyErr_Occurred() || PyErr_ExceptionMatches(PyExc_LookupError)) { PyErr_Format(state->ProgrammingError, diff --git a/Modules/_sqlite/microprotocols.c b/Modules/_sqlite/microprotocols.c index 92f0148bd4c217..f77458d94a8573 100644 --- a/Modules/_sqlite/microprotocols.c +++ b/Modules/_sqlite/microprotocols.c @@ -85,17 +85,16 @@ pysqlite_microprotocols_adapt(pysqlite_state *state, PyObject *obj, if (!key) { return NULL; } - adapter = PyDict_GetItemWithError(state->psyco_adapters, key); + if (PyDict_GetItemRef(state->psyco_adapters, key, &adapter) < 0) { + Py_DECREF(key); + return NULL; + } Py_DECREF(key); if (adapter) { - Py_INCREF(adapter); adapted = PyObject_CallOneArg(adapter, obj); Py_DECREF(adapter); return adapted; } - if (PyErr_Occurred()) { - return NULL; - } /* try to have the protocol adapt this object */ if (PyObject_GetOptionalAttr(proto, state->str___adapt__, &adapter) < 0) { diff --git a/Modules/_sqlite/module.c b/Modules/_sqlite/module.c index 368e581b4f3355..46fed9f13281f3 100644 --- a/Modules/_sqlite/module.c +++ b/Modules/_sqlite/module.c @@ -48,31 +48,33 @@ module _sqlite3 [clinic start generated code]*/ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=81e330492d57488e]*/ -// NB: This needs to be in sync with the Connection.__init__ docstring. -PyDoc_STRVAR(module_connect_doc, -"connect($module, /, database, timeout=5.0, detect_types=0,\n" -" isolation_level='', check_same_thread=True,\n" -" factory=ConnectionType, cached_statements=128, uri=False, *,\n" -" autocommit=sqlite3.LEGACY_TRANSACTION_CONTROL)\n" -"--\n" -"\n" -"Opens a connection to the SQLite database file database.\n" -"\n" -"You can use \":memory:\" to open a database connection to a database that resides\n" -"in RAM instead of on disk."); - -#define PYSQLITE_CONNECT_METHODDEF \ - {"connect", _PyCFunction_CAST(module_connect), METH_FASTCALL|METH_KEYWORDS, module_connect_doc}, +/* + * We create 'clinic/_sqlite3.connect.c.h' in connection.c, in order to + * keep the signatures of sqlite3.Connection.__init__ and + * sqlite3.connect() synchronised. + */ +#include "clinic/_sqlite3.connect.c.h" static PyObject * -module_connect(PyObject *module, PyObject *const *args, Py_ssize_t nargsf, - PyObject *kwnames) +pysqlite_connect(PyObject *module, PyObject *const *args, Py_ssize_t nargsf, + PyObject *kwnames) { pysqlite_state *state = pysqlite_get_state(module); PyObject *factory = (PyObject *)state->ConnectionType; static const int FACTORY_POS = 5; Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); + if (nargs > 1 && nargs <= 8) { + if (PyErr_WarnEx(PyExc_DeprecationWarning, + "Passing more than 1 positional argument to sqlite3.connect()" + " is deprecated. Parameters 'timeout', 'detect_types', " + "'isolation_level', 'check_same_thread', 'factory', " + "'cached_statements' and 'uri' will become keyword-only " + "parameters in Python 3.15.", 1)) + { + return NULL; + } + } if (nargs > FACTORY_POS) { factory = args[FACTORY_POS]; } @@ -242,7 +244,7 @@ load_functools_lru_cache(PyObject *module) static PyMethodDef module_methods[] = { PYSQLITE_ADAPT_METHODDEF PYSQLITE_COMPLETE_STATEMENT_METHODDEF - PYSQLITE_CONNECT_METHODDEF + {"connect", _PyCFunction_CAST(pysqlite_connect), METH_FASTCALL|METH_KEYWORDS, pysqlite_connect__doc__}, PYSQLITE_ENABLE_CALLBACK_TRACE_METHODDEF PYSQLITE_REGISTER_ADAPTER_METHODDEF PYSQLITE_REGISTER_CONVERTER_METHODDEF diff --git a/Modules/_sqlite/row.c b/Modules/_sqlite/row.c index 1a1943285ce008..14555076a7e79a 100644 --- a/Modules/_sqlite/row.c +++ b/Modules/_sqlite/row.c @@ -21,6 +21,10 @@ * 3. This notice may not be removed or altered from any source distribution. */ +#ifndef Py_BUILD_CORE_BUILTIN +# define Py_BUILD_CORE_MODULE 1 +#endif + #include "row.h" #include "cursor.h" diff --git a/Modules/_sqlite/util.c b/Modules/_sqlite/util.c index 2b3bbfefa3cf5f..833a666301d8ff 100644 --- a/Modules/_sqlite/util.c +++ b/Modules/_sqlite/util.c @@ -21,7 +21,12 @@ * 3. This notice may not be removed or altered from any source distribution. */ +#ifndef Py_BUILD_CORE_BUILTIN +# define Py_BUILD_CORE_MODULE 1 +#endif + #include "module.h" +#include "pycore_long.h" // _PyLong_AsByteArray() #include "connection.h" // Returns non-NULL if a new exception should be raised diff --git a/Modules/_sre/clinic/sre.c.h b/Modules/_sre/clinic/sre.c.h index da641081ce9e3c..cd3fbbc720bdf1 100644 --- a/Modules/_sre/clinic/sre.c.h +++ b/Modules/_sre/clinic/sre.c.h @@ -3,10 +3,11 @@ 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() +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() #endif - +#include "pycore_abstract.h" // _PyNumber_Index() +#include "pycore_modsupport.h" // _PyArg_UnpackKeywords() PyDoc_STRVAR(_sre_getcodesize__doc__, "getcodesize($module, /)\n" @@ -53,7 +54,7 @@ _sre_ascii_iscased(PyObject *module, PyObject *arg) int character; int _return_value; - character = _PyLong_AsInt(arg); + character = PyLong_AsInt(arg); if (character == -1 && PyErr_Occurred()) { goto exit; } @@ -85,7 +86,7 @@ _sre_unicode_iscased(PyObject *module, PyObject *arg) int character; int _return_value; - character = _PyLong_AsInt(arg); + character = PyLong_AsInt(arg); if (character == -1 && PyErr_Occurred()) { goto exit; } @@ -117,7 +118,7 @@ _sre_ascii_tolower(PyObject *module, PyObject *arg) int character; int _return_value; - character = _PyLong_AsInt(arg); + character = PyLong_AsInt(arg); if (character == -1 && PyErr_Occurred()) { goto exit; } @@ -149,7 +150,7 @@ _sre_unicode_tolower(PyObject *module, PyObject *arg) int character; int _return_value; - character = _PyLong_AsInt(arg); + character = PyLong_AsInt(arg); if (character == -1 && PyErr_Occurred()) { goto exit; } @@ -1031,7 +1032,7 @@ _sre_compile(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject goto exit; } pattern = args[0]; - flags = _PyLong_AsInt(args[1]); + flags = PyLong_AsInt(args[1]); if (flags == -1 && PyErr_Occurred()) { goto exit; } @@ -1460,4 +1461,4 @@ _sre_SRE_Scanner_search(ScannerObject *self, PyTypeObject *cls, PyObject *const } return _sre_SRE_Scanner_search_impl(self, cls); } -/*[clinic end generated code: output=e3ba72156dd71572 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=ad513f31b99505fa input=a9049054013a1b77]*/ diff --git a/Modules/_sre/sre.c b/Modules/_sre/sre.c index c4e43a0db0f5d3..d451974b9cf81e 100644 --- a/Modules/_sre/sre.c +++ b/Modules/_sre/sre.c @@ -39,15 +39,44 @@ static const char copyright[] = " SRE 2.2.2 Copyright (c) 1997-2002 by Secret Labs AB "; #include "Python.h" +#include "pycore_dict.h" // _PyDict_Next() #include "pycore_long.h" // _PyLong_GetZero() #include "pycore_moduleobject.h" // _PyModule_GetState() +#include "sre.h" // SRE_CODE -#include "sre.h" +#include // tolower(), toupper(), isalnum() #define SRE_CODE_BITS (8 * sizeof(SRE_CODE)) -#include +// On macOS, use the wide character ctype API using btowc() +#if defined(__APPLE__) +# define USE_CTYPE_WINT_T +#endif + +static int sre_isalnum(unsigned int ch) { +#ifdef USE_CTYPE_WINT_T + return (unsigned int)iswalnum(btowc((int)ch)); +#else + return (unsigned int)isalnum((int)ch); +#endif +} + +static unsigned int sre_tolower(unsigned int ch) { +#ifdef USE_CTYPE_WINT_T + return (unsigned int)towlower(btowc((int)ch)); +#else + return (unsigned int)tolower((int)ch); +#endif +} + +static unsigned int sre_toupper(unsigned int ch) { +#ifdef USE_CTYPE_WINT_T + return (unsigned int)towupper(btowc((int)ch)); +#else + return (unsigned int)toupper((int)ch); +#endif +} /* Defining this one controls tracing: * 0 -- disabled @@ -78,9 +107,11 @@ static const char copyright[] = #if VERBOSE == 0 # define INIT_TRACE(state) +# define DO_TRACE 0 # define TRACE(v) #elif VERBOSE == 1 # define INIT_TRACE(state) int _debug = (state)->debug +# define DO_TRACE (_debug) # define TRACE(v) do { \ if (_debug) { \ printf v; \ @@ -88,6 +119,7 @@ static const char copyright[] = } while (0) #elif VERBOSE == 2 # define INIT_TRACE(state) +# define DO_TRACE 1 # define TRACE(v) printf v #else # error VERBOSE must be 0, 1 or 2 @@ -113,17 +145,17 @@ static unsigned int sre_lower_ascii(unsigned int ch) /* locale-specific character predicates */ /* !(c & ~N) == (c < N+1) for any unsigned c, this avoids * warnings when c's type supports only numbers < N+1 */ -#define SRE_LOC_IS_ALNUM(ch) (!((ch) & ~255) ? isalnum((ch)) : 0) +#define SRE_LOC_IS_ALNUM(ch) (!((ch) & ~255) ? sre_isalnum((ch)) : 0) #define SRE_LOC_IS_WORD(ch) (SRE_LOC_IS_ALNUM((ch)) || (ch) == '_') static unsigned int sre_lower_locale(unsigned int ch) { - return ((ch) < 256 ? (unsigned int)tolower((ch)) : ch); + return ((ch) < 256 ? (unsigned int)sre_tolower((ch)) : ch); } static unsigned int sre_upper_locale(unsigned int ch) { - return ((ch) < 256 ? (unsigned int)toupper((ch)) : ch); + return ((ch) < 256 ? (unsigned int)sre_toupper((ch)) : ch); } /* unicode-specific character predicates */ @@ -1479,6 +1511,9 @@ _sre_compile_impl(PyObject *module, PyObject *pattern, int flags, for (i = 0; i < n; i++) { PyObject *o = PyList_GET_ITEM(code, i); unsigned long value = PyLong_AsUnsignedLong(o); + if (value == (unsigned long)-1 && PyErr_Occurred()) { + break; + } self->code[i] = (SRE_CODE) value; if ((unsigned long) self->code[i] != value) { PyErr_SetString(PyExc_OverflowError, @@ -2038,8 +2073,6 @@ _validate_inner(SRE_CODE *code, SRE_CODE *end, Py_ssize_t groups) GET_SKIP; GET_ARG; /* 0 for lookahead, width for lookbehind */ code--; /* Back up over arg to simplify math below */ - if (arg & 0x80000000) - FAIL; /* Width too large */ /* Stop 1 before the end; we check the SUCCESS below */ if (_validate_inner(code+1, code+skip-2, groups)) FAIL; diff --git a/Modules/_sre/sre.h b/Modules/_sre/sre.h index f60078d6bb999b..83d89d57b11199 100644 --- a/Modules/_sre/sre.h +++ b/Modules/_sre/sre.h @@ -95,6 +95,7 @@ typedef struct { size_t data_stack_base; /* current repeat context */ SRE_REPEAT *repeat; + unsigned int sigcount; } SRE_STATE; typedef struct { diff --git a/Modules/_sre/sre_lib.h b/Modules/_sre/sre_lib.h index c1a774f69090b3..f5497d9ff2b93f 100644 --- a/Modules/_sre/sre_lib.h +++ b/Modules/_sre/sre_lib.h @@ -373,6 +373,19 @@ SRE(count)(SRE_STATE* state, const SRE_CODE* pattern, Py_ssize_t maxcount) state->lastindex = ctx->lastindex; \ } while (0) +#define LAST_PTR_PUSH() \ + do { \ + TRACE(("push last_ptr: %zd", \ + PTR_TO_INDEX(ctx->u.rep->last_ptr))); \ + DATA_PUSH(&ctx->u.rep->last_ptr); \ + } while (0) +#define LAST_PTR_POP() \ + do { \ + DATA_POP(&ctx->u.rep->last_ptr); \ + TRACE(("pop last_ptr: %zd", \ + PTR_TO_INDEX(ctx->u.rep->last_ptr))); \ + } while (0) + #define RETURN_ERROR(i) do { return i; } while(0) #define RETURN_FAILURE do { ret = 0; goto exit; } while(0) #define RETURN_SUCCESS do { ret = 1; goto exit; } while(0) @@ -449,8 +462,27 @@ do { \ #define DATA_LOOKUP_AT(t,p,pos) \ DATA_STACK_LOOKUP_AT(state,t,p,pos) +#define PTR_TO_INDEX(ptr) \ + ((ptr) ? ((char*)(ptr) - (char*)state->beginning) / state->charsize : -1) + +#if VERBOSE +# define MARK_TRACE(label, lastmark) \ + do if (DO_TRACE) { \ + TRACE(("%s %d marks:", (label), (lastmark)+1)); \ + for (int j = 0; j <= (lastmark); j++) { \ + if (j && (j & 1) == 0) { \ + TRACE((" ")); \ + } \ + TRACE((" %zd", PTR_TO_INDEX(state->mark[j]))); \ + } \ + TRACE(("\n")); \ + } while (0) +#else +# define MARK_TRACE(label, lastmark) +#endif #define MARK_PUSH(lastmark) \ do if (lastmark >= 0) { \ + MARK_TRACE("push", (lastmark)); \ size_t _marks_size = (lastmark+1) * sizeof(void*); \ DATA_STACK_PUSH(state, state->mark, _marks_size); \ } while (0) @@ -458,16 +490,19 @@ do { \ do if (lastmark >= 0) { \ size_t _marks_size = (lastmark+1) * sizeof(void*); \ DATA_STACK_POP(state, state->mark, _marks_size, 1); \ + MARK_TRACE("pop", (lastmark)); \ } while (0) #define MARK_POP_KEEP(lastmark) \ do if (lastmark >= 0) { \ size_t _marks_size = (lastmark+1) * sizeof(void*); \ DATA_STACK_POP(state, state->mark, _marks_size, 0); \ + MARK_TRACE("pop keep", (lastmark)); \ } while (0) #define MARK_POP_DISCARD(lastmark) \ do if (lastmark >= 0) { \ size_t _marks_size = (lastmark+1) * sizeof(void*); \ DATA_STACK_POP_DISCARD(state, _marks_size); \ + MARK_TRACE("pop discard", (lastmark)); \ } while (0) #define JUMP_NONE 0 @@ -564,7 +599,7 @@ SRE(match)(SRE_STATE* state, const SRE_CODE* pattern, int toplevel) Py_ssize_t alloc_pos, ctx_pos = -1; Py_ssize_t ret = 0; int jump; - unsigned int sigcount=0; + unsigned int sigcount = state->sigcount; SRE(match_context)* ctx; SRE(match_context)* nextctx; @@ -591,8 +626,8 @@ SRE(match)(SRE_STATE* state, const SRE_CODE* pattern, int toplevel) /* optimization info block */ /* <1=skip> <2=flags> <3=min> ... */ if (pattern[3] && (uintptr_t)(end - ptr) < pattern[3]) { - TRACE(("reject (got %zd chars, need %zd)\n", - end - ptr, (Py_ssize_t) pattern[3])); + TRACE(("reject (got %tu chars, need %zu)\n", + end - ptr, (size_t) pattern[3])); RETURN_FAILURE; } pattern += pattern[1] + 1; @@ -1150,11 +1185,11 @@ SRE(match)(SRE_STATE* state, const SRE_CODE* pattern, int toplevel) LASTMARK_SAVE(); MARK_PUSH(ctx->lastmark); /* zero-width match protection */ - DATA_PUSH(&ctx->u.rep->last_ptr); + LAST_PTR_PUSH(); ctx->u.rep->last_ptr = state->ptr; DO_JUMP(JUMP_MAX_UNTIL_2, jump_max_until_2, ctx->u.rep->pattern+3); - DATA_POP(&ctx->u.rep->last_ptr); + LAST_PTR_POP(); if (ret) { MARK_POP_DISCARD(ctx->lastmark); RETURN_ON_ERROR(ret); @@ -1235,11 +1270,11 @@ SRE(match)(SRE_STATE* state, const SRE_CODE* pattern, int toplevel) ctx->u.rep->count = ctx->count; /* zero-width match protection */ - DATA_PUSH(&ctx->u.rep->last_ptr); + LAST_PTR_PUSH(); ctx->u.rep->last_ptr = state->ptr; DO_JUMP(JUMP_MIN_UNTIL_3,jump_min_until_3, ctx->u.rep->pattern+3); - DATA_POP(&ctx->u.rep->last_ptr); + LAST_PTR_POP(); if (ret) { RETURN_ON_ERROR(ret); RETURN_SUCCESS; @@ -1336,6 +1371,10 @@ SRE(match)(SRE_STATE* state, const SRE_CODE* pattern, int toplevel) MARK_POP(ctx->lastmark); LASTMARK_RESTORE(); + /* Restore the global Input Stream pointer + since it can change after jumps. */ + state->ptr = ptr; + /* We have sufficient matches, so exit loop. */ break; } @@ -1505,7 +1544,7 @@ SRE(match)(SRE_STATE* state, const SRE_CODE* pattern, int toplevel) /* */ TRACE(("|%p|%p|ASSERT %d\n", pattern, ptr, pattern[1])); - if (ptr - (SRE_CHAR *)state->beginning < (Py_ssize_t)pattern[1]) + if ((uintptr_t)(ptr - (SRE_CHAR *)state->beginning) < pattern[1]) RETURN_FAILURE; state->ptr = ptr - pattern[1]; DO_JUMP0(JUMP_ASSERT, jump_assert, pattern+2); @@ -1518,7 +1557,7 @@ SRE(match)(SRE_STATE* state, const SRE_CODE* pattern, int toplevel) /* */ TRACE(("|%p|%p|ASSERT_NOT %d\n", pattern, ptr, pattern[1])); - if (ptr - (SRE_CHAR *)state->beginning >= (Py_ssize_t)pattern[1]) { + if ((uintptr_t)(ptr - (SRE_CHAR *)state->beginning) >= pattern[1]) { state->ptr = ptr - pattern[1]; LASTMARK_SAVE(); if (state->repeat) @@ -1563,8 +1602,10 @@ SRE(match)(SRE_STATE* state, const SRE_CODE* pattern, int toplevel) ctx_pos = ctx->last_ctx_pos; jump = ctx->jump; DATA_POP_DISCARD(ctx); - if (ctx_pos == -1) + if (ctx_pos == -1) { + state->sigcount = sigcount; return ret; + } DATA_LOOKUP_AT(SRE(match_context), ctx, ctx_pos); switch (jump) { @@ -1652,9 +1693,9 @@ SRE(search)(SRE_STATE* state, SRE_CODE* pattern) flags = pattern[2]; - if (pattern[3] && end - ptr < (Py_ssize_t)pattern[3]) { - TRACE(("reject (got %u chars, need %u)\n", - (unsigned int)(end - ptr), pattern[3])); + if (pattern[3] && (uintptr_t)(end - ptr) < pattern[3]) { + TRACE(("reject (got %tu chars, need %zu)\n", + end - ptr, (size_t) pattern[3])); return 0; } if (pattern[3] > 1) { diff --git a/Modules/_ssl.c b/Modules/_ssl.c index c001b875906d44..bc302909424227 100644 --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -27,6 +27,7 @@ #include "Python.h" #include "pycore_fileutils.h" // _PyIsSelectable_fd() +#include "pycore_pyerrors.h" // _PyErr_ChainExceptions1() #include "pycore_weakref.h" // _PyWeakref_GET_REF() /* Include symbols from _socket module */ @@ -124,10 +125,10 @@ static void _PySSLFixErrno(void) { #include "_ssl_data_31.h" #elif (OPENSSL_VERSION_NUMBER >= 0x30000000L) #include "_ssl_data_300.h" -#elif (OPENSSL_VERSION_NUMBER >= 0x10101000L) && !defined(LIBRESSL_VERSION_NUMBER) +#elif (OPENSSL_VERSION_NUMBER >= 0x10101000L) #include "_ssl_data_111.h" #else -#include "_ssl_data.h" +#error Unsupported OpenSSL version #endif /* OpenSSL API 1.1.0+ does not include version methods */ @@ -300,6 +301,10 @@ typedef struct { BIO *keylog_bio; /* Cached module state, also used in SSLSocket and SSLSession code. */ _sslmodulestate *state; +#ifndef OPENSSL_NO_PSK + PyObject *psk_client_callback; + PyObject *psk_server_callback; +#endif } PySSLContext; typedef struct { @@ -862,7 +867,7 @@ newPySSLSocket(PySSLContext *sslctx, PySocketSockObject *sock, } /* bpo43522 and OpenSSL < 1.1.1l: copy hostflags manually */ -#if !defined(LIBRESSL_VERSION_NUMBER) && OPENSSL_VERSION < 0x101010cf +#if OPENSSL_VERSION < 0x101010cf X509_VERIFY_PARAM *ssl_params = SSL_get0_param(self->ssl); X509_VERIFY_PARAM_set_hostflags(ssl_params, sslctx->hostflags); #endif @@ -888,10 +893,8 @@ newPySSLSocket(PySSLContext *sslctx, PySocketSockObject *sock, * only in combination with SSL_VERIFY_PEER flag. */ int mode = SSL_get_verify_mode(self->ssl); if (mode & SSL_VERIFY_PEER) { - int (*verify_cb)(int, X509_STORE_CTX *) = NULL; - verify_cb = SSL_get_verify_callback(self->ssl); mode |= SSL_VERIFY_POST_HANDSHAKE; - SSL_set_verify(self->ssl, mode, verify_cb); + SSL_set_verify(self->ssl, mode, NULL); } } else { /* client socket */ @@ -2992,7 +2995,6 @@ static int _set_verify_mode(PySSLContext *self, enum py_ssl_cert_requirements n) { int mode; - int (*verify_cb)(int, X509_STORE_CTX *) = NULL; switch(n) { case PY_SSL_CERT_NONE: @@ -3013,9 +3015,7 @@ _set_verify_mode(PySSLContext *self, enum py_ssl_cert_requirements n) /* bpo-37428: newPySSLSocket() sets SSL_VERIFY_POST_HANDSHAKE flag for * server sockets and SSL_set_post_handshake_auth() for client. */ - /* keep current verify cb */ - verify_cb = SSL_CTX_get_verify_callback(self->ctx); - SSL_CTX_set_verify(self->ctx, mode, verify_cb); + SSL_CTX_set_verify(self->ctx, mode, NULL); return 0; } @@ -3122,6 +3122,10 @@ _ssl__SSLContext_impl(PyTypeObject *type, int proto_version) self->alpn_protocols = NULL; self->set_sni_cb = NULL; self->state = get_ssl_state(module); +#ifndef OPENSSL_NO_PSK + self->psk_client_callback = NULL; + self->psk_server_callback = NULL; +#endif /* Don't check host name by default */ if (proto_version == PY_SSL_VERSION_TLS_CLIENT) { @@ -3234,6 +3238,10 @@ context_clear(PySSLContext *self) Py_CLEAR(self->set_sni_cb); Py_CLEAR(self->msg_cb); Py_CLEAR(self->keylog_filename); +#ifndef OPENSSL_NO_PSK + Py_CLEAR(self->psk_client_callback); + Py_CLEAR(self->psk_server_callback); +#endif if (self->keylog_bio != NULL) { PySSL_BEGIN_ALLOW_THREADS BIO_free_all(self->keylog_bio); @@ -3914,8 +3922,8 @@ _ssl__SSLContext_load_cert_chain_impl(PySSLContext *self, PyObject *certfile, /* the password callback has already set the error information */ } else if (errno != 0) { - ERR_clear_error(); PyErr_SetFromErrno(PyExc_OSError); + ERR_clear_error(); } else { _setSSLError(get_state_ctx(self), NULL, 0, __FILE__, __LINE__); @@ -3935,8 +3943,8 @@ _ssl__SSLContext_load_cert_chain_impl(PySSLContext *self, PyObject *certfile, /* the password callback has already set the error information */ } else if (errno != 0) { - ERR_clear_error(); PyErr_SetFromErrno(PyExc_OSError); + ERR_clear_error(); } else { _setSSLError(get_state_ctx(self), NULL, 0, __FILE__, __LINE__); @@ -4132,7 +4140,8 @@ _ssl__SSLContext_load_verify_locations_impl(PySSLContext *self, if (PyObject_GetBuffer(cadata, &buf, PyBUF_SIMPLE)) { goto error; } - if (!PyBuffer_IsContiguous(&buf, 'C') || buf.ndim > 1) { + assert(PyBuffer_IsContiguous(&buf, 'C')); + if (buf.ndim > 1) { PyBuffer_Release(&buf); PyErr_SetString(PyExc_TypeError, "cadata should be a contiguous buffer with " @@ -4165,8 +4174,8 @@ _ssl__SSLContext_load_verify_locations_impl(PySSLContext *self, PySSL_END_ALLOW_THREADS if (r != 1) { if (errno != 0) { - ERR_clear_error(); PyErr_SetFromErrno(PyExc_OSError); + ERR_clear_error(); } else { _setSSLError(get_state_ctx(self), NULL, 0, __FILE__, __LINE__); @@ -4213,8 +4222,8 @@ _ssl__SSLContext_load_dh_params(PySSLContext *self, PyObject *filepath) PySSL_END_ALLOW_THREADS if (dh == NULL) { if (errno != 0) { - ERR_clear_error(); PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, filepath); + ERR_clear_error(); } else { _setSSLError(get_state_ctx(self), NULL, 0, __FILE__, __LINE__); @@ -4660,6 +4669,238 @@ _ssl__SSLContext_get_ca_certs_impl(PySSLContext *self, int binary_form) return NULL; } +#ifndef OPENSSL_NO_PSK +static unsigned int psk_client_callback(SSL *s, + const char *hint, + char *identity, + unsigned int max_identity_len, + unsigned char *psk, + unsigned int max_psk_len) +{ + PyGILState_STATE gstate = PyGILState_Ensure(); + PyObject *callback = NULL; + + PySSLSocket *ssl = SSL_get_app_data(s); + if (ssl == NULL || ssl->ctx == NULL) { + goto error; + } + callback = ssl->ctx->psk_client_callback; + if (callback == NULL) { + goto error; + } + + PyObject *hint_str = (hint != NULL && hint[0] != '\0') ? + PyUnicode_DecodeUTF8(hint, strlen(hint), "strict") : + Py_NewRef(Py_None); + if (hint_str == NULL) { + /* The remote side has sent an invalid UTF-8 string + * (breaking the standard), drop the connection without + * raising a decode exception. */ + PyErr_Clear(); + goto error; + } + PyObject *result = PyObject_CallFunctionObjArgs(callback, hint_str, NULL); + Py_DECREF(hint_str); + + if (result == NULL) { + goto error; + } + + const char *psk_; + const char *identity_; + Py_ssize_t psk_len_; + Py_ssize_t identity_len_ = 0; + if (!PyArg_ParseTuple(result, "z#y#", &identity_, &identity_len_, &psk_, &psk_len_)) { + Py_DECREF(result); + goto error; + } + + if (identity_len_ + 1 > max_identity_len || psk_len_ > max_psk_len) { + Py_DECREF(result); + goto error; + } + memcpy(psk, psk_, psk_len_); + if (identity_ != NULL) { + memcpy(identity, identity_, identity_len_); + } + identity[identity_len_] = 0; + + Py_DECREF(result); + + PyGILState_Release(gstate); + return (unsigned int)psk_len_; + +error: + if (PyErr_Occurred()) { + PyErr_WriteUnraisable(callback); + } + PyGILState_Release(gstate); + return 0; +} +#endif + +/*[clinic input] +_ssl._SSLContext.set_psk_client_callback + callback: object + +[clinic start generated code]*/ + +static PyObject * +_ssl__SSLContext_set_psk_client_callback_impl(PySSLContext *self, + PyObject *callback) +/*[clinic end generated code: output=0aba86f6ed75119e input=7627bae0e5ee7635]*/ +{ +#ifndef OPENSSL_NO_PSK + if (self->protocol == PY_SSL_VERSION_TLS_SERVER) { + _setSSLError(get_state_ctx(self), + "Cannot add PSK client callback to a " + "PROTOCOL_TLS_SERVER context", 0, __FILE__, __LINE__); + return NULL; + } + + SSL_psk_client_cb_func ssl_callback; + if (callback == Py_None) { + callback = NULL; + // Delete the existing callback + ssl_callback = NULL; + } else { + if (!PyCallable_Check(callback)) { + PyErr_SetString(PyExc_TypeError, "callback must be callable"); + return NULL; + } + ssl_callback = psk_client_callback; + } + + Py_XDECREF(self->psk_client_callback); + Py_XINCREF(callback); + + self->psk_client_callback = callback; + SSL_CTX_set_psk_client_callback(self->ctx, ssl_callback); + + Py_RETURN_NONE; +#else + PyErr_SetString(PyExc_NotImplementedError, + "TLS-PSK is not supported by your OpenSSL version."); + return NULL; +#endif +} + +#ifndef OPENSSL_NO_PSK +static unsigned int psk_server_callback(SSL *s, + const char *identity, + unsigned char *psk, + unsigned int max_psk_len) +{ + PyGILState_STATE gstate = PyGILState_Ensure(); + PyObject *callback = NULL; + + PySSLSocket *ssl = SSL_get_app_data(s); + if (ssl == NULL || ssl->ctx == NULL) { + goto error; + } + callback = ssl->ctx->psk_server_callback; + if (callback == NULL) { + goto error; + } + + PyObject *identity_str = (identity != NULL && identity[0] != '\0') ? + PyUnicode_DecodeUTF8(identity, strlen(identity), "strict") : + Py_NewRef(Py_None); + if (identity_str == NULL) { + /* The remote side has sent an invalid UTF-8 string + * (breaking the standard), drop the connection without + * raising a decode exception. */ + PyErr_Clear(); + goto error; + } + PyObject *result = PyObject_CallFunctionObjArgs(callback, identity_str, NULL); + Py_DECREF(identity_str); + + if (result == NULL) { + goto error; + } + + char *psk_; + Py_ssize_t psk_len_; + if (PyBytes_AsStringAndSize(result, &psk_, &psk_len_) < 0) { + Py_DECREF(result); + goto error; + } + + if (psk_len_ > max_psk_len) { + Py_DECREF(result); + goto error; + } + memcpy(psk, psk_, psk_len_); + + Py_DECREF(result); + + PyGILState_Release(gstate); + return (unsigned int)psk_len_; + +error: + if (PyErr_Occurred()) { + PyErr_WriteUnraisable(callback); + } + PyGILState_Release(gstate); + return 0; +} +#endif + +/*[clinic input] +_ssl._SSLContext.set_psk_server_callback + callback: object + identity_hint: str(accept={str, NoneType}) = None + +[clinic start generated code]*/ + +static PyObject * +_ssl__SSLContext_set_psk_server_callback_impl(PySSLContext *self, + PyObject *callback, + const char *identity_hint) +/*[clinic end generated code: output=1f4d6a4e09a92b03 input=65d4b6022aa85ea3]*/ +{ +#ifndef OPENSSL_NO_PSK + if (self->protocol == PY_SSL_VERSION_TLS_CLIENT) { + _setSSLError(get_state_ctx(self), + "Cannot add PSK server callback to a " + "PROTOCOL_TLS_CLIENT context", 0, __FILE__, __LINE__); + return NULL; + } + + SSL_psk_server_cb_func ssl_callback; + if (callback == Py_None) { + callback = NULL; + // Delete the existing callback and hint + ssl_callback = NULL; + identity_hint = NULL; + } else { + if (!PyCallable_Check(callback)) { + PyErr_SetString(PyExc_TypeError, "callback must be callable"); + return NULL; + } + ssl_callback = psk_server_callback; + } + + if (SSL_CTX_use_psk_identity_hint(self->ctx, identity_hint) != 1) { + PyErr_SetString(PyExc_ValueError, "failed to set identity hint"); + return NULL; + } + + Py_XDECREF(self->psk_server_callback); + Py_XINCREF(callback); + + self->psk_server_callback = callback; + SSL_CTX_set_psk_server_callback(self->ctx, ssl_callback); + + Py_RETURN_NONE; +#else + PyErr_SetString(PyExc_NotImplementedError, + "TLS-PSK is not supported by your OpenSSL version."); + return NULL; +#endif +} + static PyGetSetDef context_getsetlist[] = { {"check_hostname", (getter) get_check_hostname, @@ -4714,6 +4955,8 @@ static struct PyMethodDef context_methods[] = { _SSL__SSLCONTEXT_CERT_STORE_STATS_METHODDEF _SSL__SSLCONTEXT_GET_CA_CERTS_METHODDEF _SSL__SSLCONTEXT_GET_CIPHERS_METHODDEF + _SSL__SSLCONTEXT_SET_PSK_CLIENT_CALLBACK_METHODDEF + _SSL__SSLCONTEXT_SET_PSK_SERVER_CALLBACK_METHODDEF {NULL, NULL} /* sentinel */ }; @@ -5785,52 +6028,44 @@ sslmodule_add_option(PyObject *m, const char *name, uint64_t value) static int sslmodule_init_constants(PyObject *m) { - PyModule_AddStringConstant(m, "_DEFAULT_CIPHERS", - PY_SSL_DEFAULT_CIPHER_STRING); - - PyModule_AddIntConstant(m, "SSL_ERROR_ZERO_RETURN", - PY_SSL_ERROR_ZERO_RETURN); - PyModule_AddIntConstant(m, "SSL_ERROR_WANT_READ", - PY_SSL_ERROR_WANT_READ); - PyModule_AddIntConstant(m, "SSL_ERROR_WANT_WRITE", - PY_SSL_ERROR_WANT_WRITE); - PyModule_AddIntConstant(m, "SSL_ERROR_WANT_X509_LOOKUP", - PY_SSL_ERROR_WANT_X509_LOOKUP); - PyModule_AddIntConstant(m, "SSL_ERROR_SYSCALL", - PY_SSL_ERROR_SYSCALL); - PyModule_AddIntConstant(m, "SSL_ERROR_SSL", - PY_SSL_ERROR_SSL); - PyModule_AddIntConstant(m, "SSL_ERROR_WANT_CONNECT", - PY_SSL_ERROR_WANT_CONNECT); + if (PyModule_AddStringConstant(m, "_DEFAULT_CIPHERS", + PY_SSL_DEFAULT_CIPHER_STRING) < 0) + { + return -1; + } + +#define ADD_INT_CONST(NAME, VALUE) do { \ + if (PyModule_AddIntConstant(m, NAME, VALUE) < 0) { \ + return -1; \ + } \ +} while (0) + + ADD_INT_CONST("SSL_ERROR_ZERO_RETURN", PY_SSL_ERROR_ZERO_RETURN); + ADD_INT_CONST("SSL_ERROR_WANT_READ", PY_SSL_ERROR_WANT_READ); + ADD_INT_CONST("SSL_ERROR_WANT_WRITE", PY_SSL_ERROR_WANT_WRITE); + ADD_INT_CONST("SSL_ERROR_WANT_X509_LOOKUP", PY_SSL_ERROR_WANT_X509_LOOKUP); + ADD_INT_CONST("SSL_ERROR_SYSCALL", PY_SSL_ERROR_SYSCALL); + ADD_INT_CONST("SSL_ERROR_SSL", PY_SSL_ERROR_SSL); + ADD_INT_CONST("SSL_ERROR_WANT_CONNECT", PY_SSL_ERROR_WANT_CONNECT); /* non ssl.h errorcodes */ - PyModule_AddIntConstant(m, "SSL_ERROR_EOF", - PY_SSL_ERROR_EOF); - PyModule_AddIntConstant(m, "SSL_ERROR_INVALID_ERROR_CODE", - PY_SSL_ERROR_INVALID_ERROR_CODE); + ADD_INT_CONST("SSL_ERROR_EOF", PY_SSL_ERROR_EOF); + ADD_INT_CONST("SSL_ERROR_INVALID_ERROR_CODE", + PY_SSL_ERROR_INVALID_ERROR_CODE); /* cert requirements */ - PyModule_AddIntConstant(m, "CERT_NONE", - PY_SSL_CERT_NONE); - PyModule_AddIntConstant(m, "CERT_OPTIONAL", - PY_SSL_CERT_OPTIONAL); - PyModule_AddIntConstant(m, "CERT_REQUIRED", - PY_SSL_CERT_REQUIRED); + ADD_INT_CONST("CERT_NONE", PY_SSL_CERT_NONE); + ADD_INT_CONST("CERT_OPTIONAL", PY_SSL_CERT_OPTIONAL); + ADD_INT_CONST("CERT_REQUIRED", PY_SSL_CERT_REQUIRED); /* CRL verification for verification_flags */ - PyModule_AddIntConstant(m, "VERIFY_DEFAULT", - 0); - PyModule_AddIntConstant(m, "VERIFY_CRL_CHECK_LEAF", - X509_V_FLAG_CRL_CHECK); - PyModule_AddIntConstant(m, "VERIFY_CRL_CHECK_CHAIN", - X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL); - PyModule_AddIntConstant(m, "VERIFY_X509_STRICT", - X509_V_FLAG_X509_STRICT); - PyModule_AddIntConstant(m, "VERIFY_ALLOW_PROXY_CERTS", - X509_V_FLAG_ALLOW_PROXY_CERTS); - PyModule_AddIntConstant(m, "VERIFY_X509_TRUSTED_FIRST", - X509_V_FLAG_TRUSTED_FIRST); + ADD_INT_CONST("VERIFY_DEFAULT", 0); + ADD_INT_CONST("VERIFY_CRL_CHECK_LEAF", X509_V_FLAG_CRL_CHECK); + ADD_INT_CONST("VERIFY_CRL_CHECK_CHAIN", + X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL); + ADD_INT_CONST("VERIFY_X509_STRICT", X509_V_FLAG_X509_STRICT); + ADD_INT_CONST("VERIFY_ALLOW_PROXY_CERTS", X509_V_FLAG_ALLOW_PROXY_CERTS); + ADD_INT_CONST("VERIFY_X509_TRUSTED_FIRST", X509_V_FLAG_TRUSTED_FIRST); #ifdef X509_V_FLAG_PARTIAL_CHAIN - PyModule_AddIntConstant(m, "VERIFY_X509_PARTIAL_CHAIN", - X509_V_FLAG_PARTIAL_CHAIN); + ADD_INT_CONST("VERIFY_X509_PARTIAL_CHAIN", X509_V_FLAG_PARTIAL_CHAIN); #endif /* Alert Descriptions from ssl.h */ @@ -5838,7 +6073,7 @@ sslmodule_init_constants(PyObject *m) /* http://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-6 */ #define ADD_AD_CONSTANT(s) \ - PyModule_AddIntConstant(m, "ALERT_DESCRIPTION_"#s, \ + ADD_INT_CONST("ALERT_DESCRIPTION_"#s, \ SSL_AD_##s) ADD_AD_CONSTANT(CLOSE_NOTIFY); @@ -5886,23 +6121,15 @@ sslmodule_init_constants(PyObject *m) /* protocol versions */ #ifndef OPENSSL_NO_SSL3 - PyModule_AddIntConstant(m, "PROTOCOL_SSLv3", - PY_SSL_VERSION_SSL3); + ADD_INT_CONST("PROTOCOL_SSLv3", PY_SSL_VERSION_SSL3); #endif - PyModule_AddIntConstant(m, "PROTOCOL_SSLv23", - PY_SSL_VERSION_TLS); - PyModule_AddIntConstant(m, "PROTOCOL_TLS", - PY_SSL_VERSION_TLS); - PyModule_AddIntConstant(m, "PROTOCOL_TLS_CLIENT", - PY_SSL_VERSION_TLS_CLIENT); - PyModule_AddIntConstant(m, "PROTOCOL_TLS_SERVER", - PY_SSL_VERSION_TLS_SERVER); - PyModule_AddIntConstant(m, "PROTOCOL_TLSv1", - PY_SSL_VERSION_TLS1); - PyModule_AddIntConstant(m, "PROTOCOL_TLSv1_1", - PY_SSL_VERSION_TLS1_1); - PyModule_AddIntConstant(m, "PROTOCOL_TLSv1_2", - PY_SSL_VERSION_TLS1_2); + ADD_INT_CONST("PROTOCOL_SSLv23", PY_SSL_VERSION_TLS); + ADD_INT_CONST("PROTOCOL_TLS", PY_SSL_VERSION_TLS); + ADD_INT_CONST("PROTOCOL_TLS_CLIENT", PY_SSL_VERSION_TLS_CLIENT); + ADD_INT_CONST("PROTOCOL_TLS_SERVER", PY_SSL_VERSION_TLS_SERVER); + ADD_INT_CONST("PROTOCOL_TLSv1", PY_SSL_VERSION_TLS1); + ADD_INT_CONST("PROTOCOL_TLSv1_1", PY_SSL_VERSION_TLS1_1); + ADD_INT_CONST("PROTOCOL_TLSv1_2", PY_SSL_VERSION_TLS1_2); #define ADD_OPTION(NAME, VALUE) if (sslmodule_add_option(m, NAME, (VALUE)) < 0) return -1 @@ -5947,50 +6174,52 @@ sslmodule_init_constants(PyObject *m) ADD_OPTION("OP_ENABLE_KTLS", SSL_OP_ENABLE_KTLS); #endif +#undef ADD_OPTION + #ifdef X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT - PyModule_AddIntConstant(m, "HOSTFLAG_ALWAYS_CHECK_SUBJECT", - X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT); + ADD_INT_CONST("HOSTFLAG_ALWAYS_CHECK_SUBJECT", + X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT); #endif #ifdef X509_CHECK_FLAG_NEVER_CHECK_SUBJECT - PyModule_AddIntConstant(m, "HOSTFLAG_NEVER_CHECK_SUBJECT", - X509_CHECK_FLAG_NEVER_CHECK_SUBJECT); + ADD_INT_CONST("HOSTFLAG_NEVER_CHECK_SUBJECT", + X509_CHECK_FLAG_NEVER_CHECK_SUBJECT); #endif #ifdef X509_CHECK_FLAG_NO_WILDCARDS - PyModule_AddIntConstant(m, "HOSTFLAG_NO_WILDCARDS", - X509_CHECK_FLAG_NO_WILDCARDS); + ADD_INT_CONST("HOSTFLAG_NO_WILDCARDS", + X509_CHECK_FLAG_NO_WILDCARDS); #endif #ifdef X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS - PyModule_AddIntConstant(m, "HOSTFLAG_NO_PARTIAL_WILDCARDS", - X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS); + ADD_INT_CONST("HOSTFLAG_NO_PARTIAL_WILDCARDS", + X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS); #endif #ifdef X509_CHECK_FLAG_MULTI_LABEL_WILDCARDS - PyModule_AddIntConstant(m, "HOSTFLAG_MULTI_LABEL_WILDCARDS", - X509_CHECK_FLAG_MULTI_LABEL_WILDCARDS); + ADD_INT_CONST("HOSTFLAG_MULTI_LABEL_WILDCARDS", + X509_CHECK_FLAG_MULTI_LABEL_WILDCARDS); #endif #ifdef X509_CHECK_FLAG_SINGLE_LABEL_SUBDOMAINS - PyModule_AddIntConstant(m, "HOSTFLAG_SINGLE_LABEL_SUBDOMAINS", - X509_CHECK_FLAG_SINGLE_LABEL_SUBDOMAINS); + ADD_INT_CONST("HOSTFLAG_SINGLE_LABEL_SUBDOMAINS", + X509_CHECK_FLAG_SINGLE_LABEL_SUBDOMAINS); #endif /* file types */ - PyModule_AddIntConstant(m, "ENCODING_PEM", PY_SSL_ENCODING_PEM); - PyModule_AddIntConstant(m, "ENCODING_DER", PY_SSL_ENCODING_DER); + ADD_INT_CONST("ENCODING_PEM", PY_SSL_ENCODING_PEM); + ADD_INT_CONST("ENCODING_DER", PY_SSL_ENCODING_DER); /* protocol versions */ - PyModule_AddIntConstant(m, "PROTO_MINIMUM_SUPPORTED", - PY_PROTO_MINIMUM_SUPPORTED); - PyModule_AddIntConstant(m, "PROTO_MAXIMUM_SUPPORTED", - PY_PROTO_MAXIMUM_SUPPORTED); - PyModule_AddIntConstant(m, "PROTO_SSLv3", PY_PROTO_SSLv3); - PyModule_AddIntConstant(m, "PROTO_TLSv1", PY_PROTO_TLSv1); - PyModule_AddIntConstant(m, "PROTO_TLSv1_1", PY_PROTO_TLSv1_1); - PyModule_AddIntConstant(m, "PROTO_TLSv1_2", PY_PROTO_TLSv1_2); - PyModule_AddIntConstant(m, "PROTO_TLSv1_3", PY_PROTO_TLSv1_3); + ADD_INT_CONST("PROTO_MINIMUM_SUPPORTED", PY_PROTO_MINIMUM_SUPPORTED); + ADD_INT_CONST("PROTO_MAXIMUM_SUPPORTED", PY_PROTO_MAXIMUM_SUPPORTED); + ADD_INT_CONST("PROTO_SSLv3", PY_PROTO_SSLv3); + ADD_INT_CONST("PROTO_TLSv1", PY_PROTO_TLSv1); + ADD_INT_CONST("PROTO_TLSv1_1", PY_PROTO_TLSv1_1); + ADD_INT_CONST("PROTO_TLSv1_2", PY_PROTO_TLSv1_2); + ADD_INT_CONST("PROTO_TLSv1_3", PY_PROTO_TLSv1_3); #define addbool(m, key, value) \ do { \ PyObject *bool_obj = (value) ? Py_True : Py_False; \ - PyModule_AddObjectRef((m), (key), bool_obj); \ + if (PyModule_AddObjectRef((m), (key), bool_obj) < 0) { \ + return -1; \ + } \ } while (0) addbool(m, "HAS_SNI", 1); @@ -6031,6 +6260,15 @@ sslmodule_init_constants(PyObject *m) addbool(m, "HAS_TLSv1_3", 0); #endif +#ifdef OPENSSL_NO_PSK + addbool(m, "HAS_PSK", 0); +#else + addbool(m, "HAS_PSK", 1); +#endif + +#undef addbool +#undef ADD_INT_CONST + return 0; } diff --git a/Modules/_ssl/clinic/cert.c.h b/Modules/_ssl/clinic/cert.c.h index a052ab2086fd96..0748d32291e3c5 100644 --- a/Modules/_ssl/clinic/cert.c.h +++ b/Modules/_ssl/clinic/cert.c.h @@ -3,10 +3,10 @@ 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() +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() #endif - +#include "pycore_modsupport.h" // _PyArg_UnpackKeywords() PyDoc_STRVAR(_ssl_Certificate_public_bytes__doc__, "public_bytes($self, /, format=Encoding.PEM)\n" @@ -59,7 +59,7 @@ _ssl_Certificate_public_bytes(PySSLCertificate *self, PyObject *const *args, Py_ if (!noptargs) { goto skip_optional_pos; } - format = _PyLong_AsInt(args[0]); + format = PyLong_AsInt(args[0]); if (format == -1 && PyErr_Occurred()) { goto exit; } @@ -86,4 +86,4 @@ _ssl_Certificate_get_info(PySSLCertificate *self, PyObject *Py_UNUSED(ignored)) { return _ssl_Certificate_get_info_impl(self); } -/*[clinic end generated code: output=82efada014f9b7fe input=a9049054013a1b77]*/ +/*[clinic end generated code: output=5b668226f933a677 input=a9049054013a1b77]*/ diff --git a/Modules/_ssl_data.h b/Modules/_ssl_data.h deleted file mode 100644 index 8f2994f52dfef8..00000000000000 --- a/Modules/_ssl_data.h +++ /dev/null @@ -1,6323 +0,0 @@ -/* File generated by Tools/ssl/make_ssl_data.py */ -/* Generated on 2020-04-13T21:45:54.559159 */ - -static struct py_ssl_library_code library_codes[] = { -#ifdef ERR_LIB_ASN1 - {"ASN1", ERR_LIB_ASN1}, -#endif -#ifdef ERR_LIB_ASYNC - {"ASYNC", ERR_LIB_ASYNC}, -#endif -#ifdef ERR_LIB_BIO - {"BIO", ERR_LIB_BIO}, -#endif -#ifdef ERR_LIB_BN - {"BN", ERR_LIB_BN}, -#endif -#ifdef ERR_LIB_CMS - {"CMS", ERR_LIB_CMS}, -#endif -#ifdef ERR_LIB_COMP - {"COMP", ERR_LIB_COMP}, -#endif -#ifdef ERR_LIB_CONF - {"CONF", ERR_LIB_CONF}, -#endif -#ifdef ERR_LIB_CRYPTO - {"CRYPTO", ERR_LIB_CRYPTO}, -#endif -#ifdef ERR_LIB_CT - {"CT", ERR_LIB_CT}, -#endif -#ifdef ERR_LIB_DH - {"DH", ERR_LIB_DH}, -#endif -#ifdef ERR_LIB_DSA - {"DSA", ERR_LIB_DSA}, -#endif -#ifdef ERR_LIB_EC - {"EC", ERR_LIB_EC}, -#endif -#ifdef ERR_LIB_ENGINE - {"ENGINE", ERR_LIB_ENGINE}, -#endif -#ifdef ERR_LIB_EVP - {"EVP", ERR_LIB_EVP}, -#endif -#ifdef ERR_LIB_KDF - {"KDF", ERR_LIB_KDF}, -#endif -#ifdef ERR_LIB_OCSP - {"OCSP", ERR_LIB_OCSP}, -#endif -#ifdef ERR_LIB_PEM - {"PEM", ERR_LIB_PEM}, -#endif -#ifdef ERR_LIB_PKCS12 - {"PKCS12", ERR_LIB_PKCS12}, -#endif -#ifdef ERR_LIB_PKCS7 - {"PKCS7", ERR_LIB_PKCS7}, -#endif -#ifdef ERR_LIB_RAND - {"RAND", ERR_LIB_RAND}, -#endif -#ifdef ERR_LIB_RSA - {"RSA", ERR_LIB_RSA}, -#endif -#ifdef ERR_LIB_SSL - {"SSL", ERR_LIB_SSL}, -#endif -#ifdef ERR_LIB_TS - {"TS", ERR_LIB_TS}, -#endif -#ifdef ERR_LIB_UI - {"UI", ERR_LIB_UI}, -#endif -#ifdef ERR_LIB_X509 - {"X509", ERR_LIB_X509}, -#endif -#ifdef ERR_LIB_X509V3 - {"X509V3", ERR_LIB_X509V3}, -#endif - { NULL } -}; - -static struct py_ssl_error_code error_codes[] = { - #ifdef ASN1_R_ADDING_OBJECT - {"ADDING_OBJECT", ERR_LIB_ASN1, ASN1_R_ADDING_OBJECT}, - #else - {"ADDING_OBJECT", 13, 171}, - #endif - #ifdef ASN1_R_ASN1_PARSE_ERROR - {"ASN1_PARSE_ERROR", ERR_LIB_ASN1, ASN1_R_ASN1_PARSE_ERROR}, - #else - {"ASN1_PARSE_ERROR", 13, 203}, - #endif - #ifdef ASN1_R_ASN1_SIG_PARSE_ERROR - {"ASN1_SIG_PARSE_ERROR", ERR_LIB_ASN1, ASN1_R_ASN1_SIG_PARSE_ERROR}, - #else - {"ASN1_SIG_PARSE_ERROR", 13, 204}, - #endif - #ifdef ASN1_R_AUX_ERROR - {"AUX_ERROR", ERR_LIB_ASN1, ASN1_R_AUX_ERROR}, - #else - {"AUX_ERROR", 13, 100}, - #endif - #ifdef ASN1_R_BAD_OBJECT_HEADER - {"BAD_OBJECT_HEADER", ERR_LIB_ASN1, ASN1_R_BAD_OBJECT_HEADER}, - #else - {"BAD_OBJECT_HEADER", 13, 102}, - #endif - #ifdef ASN1_R_BMPSTRING_IS_WRONG_LENGTH - {"BMPSTRING_IS_WRONG_LENGTH", ERR_LIB_ASN1, ASN1_R_BMPSTRING_IS_WRONG_LENGTH}, - #else - {"BMPSTRING_IS_WRONG_LENGTH", 13, 214}, - #endif - #ifdef ASN1_R_BN_LIB - {"BN_LIB", ERR_LIB_ASN1, ASN1_R_BN_LIB}, - #else - {"BN_LIB", 13, 105}, - #endif - #ifdef ASN1_R_BOOLEAN_IS_WRONG_LENGTH - {"BOOLEAN_IS_WRONG_LENGTH", ERR_LIB_ASN1, ASN1_R_BOOLEAN_IS_WRONG_LENGTH}, - #else - {"BOOLEAN_IS_WRONG_LENGTH", 13, 106}, - #endif - #ifdef ASN1_R_BUFFER_TOO_SMALL - {"BUFFER_TOO_SMALL", ERR_LIB_ASN1, ASN1_R_BUFFER_TOO_SMALL}, - #else - {"BUFFER_TOO_SMALL", 13, 107}, - #endif - #ifdef ASN1_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER - {"CIPHER_HAS_NO_OBJECT_IDENTIFIER", ERR_LIB_ASN1, ASN1_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER}, - #else - {"CIPHER_HAS_NO_OBJECT_IDENTIFIER", 13, 108}, - #endif - #ifdef ASN1_R_CONTEXT_NOT_INITIALISED - {"CONTEXT_NOT_INITIALISED", ERR_LIB_ASN1, ASN1_R_CONTEXT_NOT_INITIALISED}, - #else - {"CONTEXT_NOT_INITIALISED", 13, 217}, - #endif - #ifdef ASN1_R_DATA_IS_WRONG - {"DATA_IS_WRONG", ERR_LIB_ASN1, ASN1_R_DATA_IS_WRONG}, - #else - {"DATA_IS_WRONG", 13, 109}, - #endif - #ifdef ASN1_R_DECODE_ERROR - {"DECODE_ERROR", ERR_LIB_ASN1, ASN1_R_DECODE_ERROR}, - #else - {"DECODE_ERROR", 13, 110}, - #endif - #ifdef ASN1_R_DEPTH_EXCEEDED - {"DEPTH_EXCEEDED", ERR_LIB_ASN1, ASN1_R_DEPTH_EXCEEDED}, - #else - {"DEPTH_EXCEEDED", 13, 174}, - #endif - #ifdef ASN1_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED - {"DIGEST_AND_KEY_TYPE_NOT_SUPPORTED", ERR_LIB_ASN1, ASN1_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED}, - #else - {"DIGEST_AND_KEY_TYPE_NOT_SUPPORTED", 13, 198}, - #endif - #ifdef ASN1_R_ENCODE_ERROR - {"ENCODE_ERROR", ERR_LIB_ASN1, ASN1_R_ENCODE_ERROR}, - #else - {"ENCODE_ERROR", 13, 112}, - #endif - #ifdef ASN1_R_ERROR_GETTING_TIME - {"ERROR_GETTING_TIME", ERR_LIB_ASN1, ASN1_R_ERROR_GETTING_TIME}, - #else - {"ERROR_GETTING_TIME", 13, 173}, - #endif - #ifdef ASN1_R_ERROR_LOADING_SECTION - {"ERROR_LOADING_SECTION", ERR_LIB_ASN1, ASN1_R_ERROR_LOADING_SECTION}, - #else - {"ERROR_LOADING_SECTION", 13, 172}, - #endif - #ifdef ASN1_R_ERROR_SETTING_CIPHER_PARAMS - {"ERROR_SETTING_CIPHER_PARAMS", ERR_LIB_ASN1, ASN1_R_ERROR_SETTING_CIPHER_PARAMS}, - #else - {"ERROR_SETTING_CIPHER_PARAMS", 13, 114}, - #endif - #ifdef ASN1_R_EXPECTING_AN_INTEGER - {"EXPECTING_AN_INTEGER", ERR_LIB_ASN1, ASN1_R_EXPECTING_AN_INTEGER}, - #else - {"EXPECTING_AN_INTEGER", 13, 115}, - #endif - #ifdef ASN1_R_EXPECTING_AN_OBJECT - {"EXPECTING_AN_OBJECT", ERR_LIB_ASN1, ASN1_R_EXPECTING_AN_OBJECT}, - #else - {"EXPECTING_AN_OBJECT", 13, 116}, - #endif - #ifdef ASN1_R_EXPLICIT_LENGTH_MISMATCH - {"EXPLICIT_LENGTH_MISMATCH", ERR_LIB_ASN1, ASN1_R_EXPLICIT_LENGTH_MISMATCH}, - #else - {"EXPLICIT_LENGTH_MISMATCH", 13, 119}, - #endif - #ifdef ASN1_R_EXPLICIT_TAG_NOT_CONSTRUCTED - {"EXPLICIT_TAG_NOT_CONSTRUCTED", ERR_LIB_ASN1, ASN1_R_EXPLICIT_TAG_NOT_CONSTRUCTED}, - #else - {"EXPLICIT_TAG_NOT_CONSTRUCTED", 13, 120}, - #endif - #ifdef ASN1_R_FIELD_MISSING - {"FIELD_MISSING", ERR_LIB_ASN1, ASN1_R_FIELD_MISSING}, - #else - {"FIELD_MISSING", 13, 121}, - #endif - #ifdef ASN1_R_FIRST_NUM_TOO_LARGE - {"FIRST_NUM_TOO_LARGE", ERR_LIB_ASN1, ASN1_R_FIRST_NUM_TOO_LARGE}, - #else - {"FIRST_NUM_TOO_LARGE", 13, 122}, - #endif - #ifdef ASN1_R_HEADER_TOO_LONG - {"HEADER_TOO_LONG", ERR_LIB_ASN1, ASN1_R_HEADER_TOO_LONG}, - #else - {"HEADER_TOO_LONG", 13, 123}, - #endif - #ifdef ASN1_R_ILLEGAL_BITSTRING_FORMAT - {"ILLEGAL_BITSTRING_FORMAT", ERR_LIB_ASN1, ASN1_R_ILLEGAL_BITSTRING_FORMAT}, - #else - {"ILLEGAL_BITSTRING_FORMAT", 13, 175}, - #endif - #ifdef ASN1_R_ILLEGAL_BOOLEAN - {"ILLEGAL_BOOLEAN", ERR_LIB_ASN1, ASN1_R_ILLEGAL_BOOLEAN}, - #else - {"ILLEGAL_BOOLEAN", 13, 176}, - #endif - #ifdef ASN1_R_ILLEGAL_CHARACTERS - {"ILLEGAL_CHARACTERS", ERR_LIB_ASN1, ASN1_R_ILLEGAL_CHARACTERS}, - #else - {"ILLEGAL_CHARACTERS", 13, 124}, - #endif - #ifdef ASN1_R_ILLEGAL_FORMAT - {"ILLEGAL_FORMAT", ERR_LIB_ASN1, ASN1_R_ILLEGAL_FORMAT}, - #else - {"ILLEGAL_FORMAT", 13, 177}, - #endif - #ifdef ASN1_R_ILLEGAL_HEX - {"ILLEGAL_HEX", ERR_LIB_ASN1, ASN1_R_ILLEGAL_HEX}, - #else - {"ILLEGAL_HEX", 13, 178}, - #endif - #ifdef ASN1_R_ILLEGAL_IMPLICIT_TAG - {"ILLEGAL_IMPLICIT_TAG", ERR_LIB_ASN1, ASN1_R_ILLEGAL_IMPLICIT_TAG}, - #else - {"ILLEGAL_IMPLICIT_TAG", 13, 179}, - #endif - #ifdef ASN1_R_ILLEGAL_INTEGER - {"ILLEGAL_INTEGER", ERR_LIB_ASN1, ASN1_R_ILLEGAL_INTEGER}, - #else - {"ILLEGAL_INTEGER", 13, 180}, - #endif - #ifdef ASN1_R_ILLEGAL_NEGATIVE_VALUE - {"ILLEGAL_NEGATIVE_VALUE", ERR_LIB_ASN1, ASN1_R_ILLEGAL_NEGATIVE_VALUE}, - #else - {"ILLEGAL_NEGATIVE_VALUE", 13, 226}, - #endif - #ifdef ASN1_R_ILLEGAL_NESTED_TAGGING - {"ILLEGAL_NESTED_TAGGING", ERR_LIB_ASN1, ASN1_R_ILLEGAL_NESTED_TAGGING}, - #else - {"ILLEGAL_NESTED_TAGGING", 13, 181}, - #endif - #ifdef ASN1_R_ILLEGAL_NULL - {"ILLEGAL_NULL", ERR_LIB_ASN1, ASN1_R_ILLEGAL_NULL}, - #else - {"ILLEGAL_NULL", 13, 125}, - #endif - #ifdef ASN1_R_ILLEGAL_NULL_VALUE - {"ILLEGAL_NULL_VALUE", ERR_LIB_ASN1, ASN1_R_ILLEGAL_NULL_VALUE}, - #else - {"ILLEGAL_NULL_VALUE", 13, 182}, - #endif - #ifdef ASN1_R_ILLEGAL_OBJECT - {"ILLEGAL_OBJECT", ERR_LIB_ASN1, ASN1_R_ILLEGAL_OBJECT}, - #else - {"ILLEGAL_OBJECT", 13, 183}, - #endif - #ifdef ASN1_R_ILLEGAL_OPTIONAL_ANY - {"ILLEGAL_OPTIONAL_ANY", ERR_LIB_ASN1, ASN1_R_ILLEGAL_OPTIONAL_ANY}, - #else - {"ILLEGAL_OPTIONAL_ANY", 13, 126}, - #endif - #ifdef ASN1_R_ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE - {"ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE", ERR_LIB_ASN1, ASN1_R_ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE}, - #else - {"ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE", 13, 170}, - #endif - #ifdef ASN1_R_ILLEGAL_PADDING - {"ILLEGAL_PADDING", ERR_LIB_ASN1, ASN1_R_ILLEGAL_PADDING}, - #else - {"ILLEGAL_PADDING", 13, 221}, - #endif - #ifdef ASN1_R_ILLEGAL_TAGGED_ANY - {"ILLEGAL_TAGGED_ANY", ERR_LIB_ASN1, ASN1_R_ILLEGAL_TAGGED_ANY}, - #else - {"ILLEGAL_TAGGED_ANY", 13, 127}, - #endif - #ifdef ASN1_R_ILLEGAL_TIME_VALUE - {"ILLEGAL_TIME_VALUE", ERR_LIB_ASN1, ASN1_R_ILLEGAL_TIME_VALUE}, - #else - {"ILLEGAL_TIME_VALUE", 13, 184}, - #endif - #ifdef ASN1_R_ILLEGAL_ZERO_CONTENT - {"ILLEGAL_ZERO_CONTENT", ERR_LIB_ASN1, ASN1_R_ILLEGAL_ZERO_CONTENT}, - #else - {"ILLEGAL_ZERO_CONTENT", 13, 222}, - #endif - #ifdef ASN1_R_INTEGER_NOT_ASCII_FORMAT - {"INTEGER_NOT_ASCII_FORMAT", ERR_LIB_ASN1, ASN1_R_INTEGER_NOT_ASCII_FORMAT}, - #else - {"INTEGER_NOT_ASCII_FORMAT", 13, 185}, - #endif - #ifdef ASN1_R_INTEGER_TOO_LARGE_FOR_LONG - {"INTEGER_TOO_LARGE_FOR_LONG", ERR_LIB_ASN1, ASN1_R_INTEGER_TOO_LARGE_FOR_LONG}, - #else - {"INTEGER_TOO_LARGE_FOR_LONG", 13, 128}, - #endif - #ifdef ASN1_R_INVALID_BIT_STRING_BITS_LEFT - {"INVALID_BIT_STRING_BITS_LEFT", ERR_LIB_ASN1, ASN1_R_INVALID_BIT_STRING_BITS_LEFT}, - #else - {"INVALID_BIT_STRING_BITS_LEFT", 13, 220}, - #endif - #ifdef ASN1_R_INVALID_BMPSTRING_LENGTH - {"INVALID_BMPSTRING_LENGTH", ERR_LIB_ASN1, ASN1_R_INVALID_BMPSTRING_LENGTH}, - #else - {"INVALID_BMPSTRING_LENGTH", 13, 129}, - #endif - #ifdef ASN1_R_INVALID_DIGIT - {"INVALID_DIGIT", ERR_LIB_ASN1, ASN1_R_INVALID_DIGIT}, - #else - {"INVALID_DIGIT", 13, 130}, - #endif - #ifdef ASN1_R_INVALID_MIME_TYPE - {"INVALID_MIME_TYPE", ERR_LIB_ASN1, ASN1_R_INVALID_MIME_TYPE}, - #else - {"INVALID_MIME_TYPE", 13, 205}, - #endif - #ifdef ASN1_R_INVALID_MODIFIER - {"INVALID_MODIFIER", ERR_LIB_ASN1, ASN1_R_INVALID_MODIFIER}, - #else - {"INVALID_MODIFIER", 13, 186}, - #endif - #ifdef ASN1_R_INVALID_NUMBER - {"INVALID_NUMBER", ERR_LIB_ASN1, ASN1_R_INVALID_NUMBER}, - #else - {"INVALID_NUMBER", 13, 187}, - #endif - #ifdef ASN1_R_INVALID_OBJECT_ENCODING - {"INVALID_OBJECT_ENCODING", ERR_LIB_ASN1, ASN1_R_INVALID_OBJECT_ENCODING}, - #else - {"INVALID_OBJECT_ENCODING", 13, 216}, - #endif - #ifdef ASN1_R_INVALID_SCRYPT_PARAMETERS - {"INVALID_SCRYPT_PARAMETERS", ERR_LIB_ASN1, ASN1_R_INVALID_SCRYPT_PARAMETERS}, - #else - {"INVALID_SCRYPT_PARAMETERS", 13, 227}, - #endif - #ifdef ASN1_R_INVALID_SEPARATOR - {"INVALID_SEPARATOR", ERR_LIB_ASN1, ASN1_R_INVALID_SEPARATOR}, - #else - {"INVALID_SEPARATOR", 13, 131}, - #endif - #ifdef ASN1_R_INVALID_STRING_TABLE_VALUE - {"INVALID_STRING_TABLE_VALUE", ERR_LIB_ASN1, ASN1_R_INVALID_STRING_TABLE_VALUE}, - #else - {"INVALID_STRING_TABLE_VALUE", 13, 218}, - #endif - #ifdef ASN1_R_INVALID_UNIVERSALSTRING_LENGTH - {"INVALID_UNIVERSALSTRING_LENGTH", ERR_LIB_ASN1, ASN1_R_INVALID_UNIVERSALSTRING_LENGTH}, - #else - {"INVALID_UNIVERSALSTRING_LENGTH", 13, 133}, - #endif - #ifdef ASN1_R_INVALID_UTF8STRING - {"INVALID_UTF8STRING", ERR_LIB_ASN1, ASN1_R_INVALID_UTF8STRING}, - #else - {"INVALID_UTF8STRING", 13, 134}, - #endif - #ifdef ASN1_R_INVALID_VALUE - {"INVALID_VALUE", ERR_LIB_ASN1, ASN1_R_INVALID_VALUE}, - #else - {"INVALID_VALUE", 13, 219}, - #endif - #ifdef ASN1_R_LIST_ERROR - {"LIST_ERROR", ERR_LIB_ASN1, ASN1_R_LIST_ERROR}, - #else - {"LIST_ERROR", 13, 188}, - #endif - #ifdef ASN1_R_MIME_NO_CONTENT_TYPE - {"MIME_NO_CONTENT_TYPE", ERR_LIB_ASN1, ASN1_R_MIME_NO_CONTENT_TYPE}, - #else - {"MIME_NO_CONTENT_TYPE", 13, 206}, - #endif - #ifdef ASN1_R_MIME_PARSE_ERROR - {"MIME_PARSE_ERROR", ERR_LIB_ASN1, ASN1_R_MIME_PARSE_ERROR}, - #else - {"MIME_PARSE_ERROR", 13, 207}, - #endif - #ifdef ASN1_R_MIME_SIG_PARSE_ERROR - {"MIME_SIG_PARSE_ERROR", ERR_LIB_ASN1, ASN1_R_MIME_SIG_PARSE_ERROR}, - #else - {"MIME_SIG_PARSE_ERROR", 13, 208}, - #endif - #ifdef ASN1_R_MISSING_EOC - {"MISSING_EOC", ERR_LIB_ASN1, ASN1_R_MISSING_EOC}, - #else - {"MISSING_EOC", 13, 137}, - #endif - #ifdef ASN1_R_MISSING_SECOND_NUMBER - {"MISSING_SECOND_NUMBER", ERR_LIB_ASN1, ASN1_R_MISSING_SECOND_NUMBER}, - #else - {"MISSING_SECOND_NUMBER", 13, 138}, - #endif - #ifdef ASN1_R_MISSING_VALUE - {"MISSING_VALUE", ERR_LIB_ASN1, ASN1_R_MISSING_VALUE}, - #else - {"MISSING_VALUE", 13, 189}, - #endif - #ifdef ASN1_R_MSTRING_NOT_UNIVERSAL - {"MSTRING_NOT_UNIVERSAL", ERR_LIB_ASN1, ASN1_R_MSTRING_NOT_UNIVERSAL}, - #else - {"MSTRING_NOT_UNIVERSAL", 13, 139}, - #endif - #ifdef ASN1_R_MSTRING_WRONG_TAG - {"MSTRING_WRONG_TAG", ERR_LIB_ASN1, ASN1_R_MSTRING_WRONG_TAG}, - #else - {"MSTRING_WRONG_TAG", 13, 140}, - #endif - #ifdef ASN1_R_NESTED_ASN1_STRING - {"NESTED_ASN1_STRING", ERR_LIB_ASN1, ASN1_R_NESTED_ASN1_STRING}, - #else - {"NESTED_ASN1_STRING", 13, 197}, - #endif - #ifdef ASN1_R_NESTED_TOO_DEEP - {"NESTED_TOO_DEEP", ERR_LIB_ASN1, ASN1_R_NESTED_TOO_DEEP}, - #else - {"NESTED_TOO_DEEP", 13, 201}, - #endif - #ifdef ASN1_R_NON_HEX_CHARACTERS - {"NON_HEX_CHARACTERS", ERR_LIB_ASN1, ASN1_R_NON_HEX_CHARACTERS}, - #else - {"NON_HEX_CHARACTERS", 13, 141}, - #endif - #ifdef ASN1_R_NOT_ASCII_FORMAT - {"NOT_ASCII_FORMAT", ERR_LIB_ASN1, ASN1_R_NOT_ASCII_FORMAT}, - #else - {"NOT_ASCII_FORMAT", 13, 190}, - #endif - #ifdef ASN1_R_NOT_ENOUGH_DATA - {"NOT_ENOUGH_DATA", ERR_LIB_ASN1, ASN1_R_NOT_ENOUGH_DATA}, - #else - {"NOT_ENOUGH_DATA", 13, 142}, - #endif - #ifdef ASN1_R_NO_CONTENT_TYPE - {"NO_CONTENT_TYPE", ERR_LIB_ASN1, ASN1_R_NO_CONTENT_TYPE}, - #else - {"NO_CONTENT_TYPE", 13, 209}, - #endif - #ifdef ASN1_R_NO_MATCHING_CHOICE_TYPE - {"NO_MATCHING_CHOICE_TYPE", ERR_LIB_ASN1, ASN1_R_NO_MATCHING_CHOICE_TYPE}, - #else - {"NO_MATCHING_CHOICE_TYPE", 13, 143}, - #endif - #ifdef ASN1_R_NO_MULTIPART_BODY_FAILURE - {"NO_MULTIPART_BODY_FAILURE", ERR_LIB_ASN1, ASN1_R_NO_MULTIPART_BODY_FAILURE}, - #else - {"NO_MULTIPART_BODY_FAILURE", 13, 210}, - #endif - #ifdef ASN1_R_NO_MULTIPART_BOUNDARY - {"NO_MULTIPART_BOUNDARY", ERR_LIB_ASN1, ASN1_R_NO_MULTIPART_BOUNDARY}, - #else - {"NO_MULTIPART_BOUNDARY", 13, 211}, - #endif - #ifdef ASN1_R_NO_SIG_CONTENT_TYPE - {"NO_SIG_CONTENT_TYPE", ERR_LIB_ASN1, ASN1_R_NO_SIG_CONTENT_TYPE}, - #else - {"NO_SIG_CONTENT_TYPE", 13, 212}, - #endif - #ifdef ASN1_R_NULL_IS_WRONG_LENGTH - {"NULL_IS_WRONG_LENGTH", ERR_LIB_ASN1, ASN1_R_NULL_IS_WRONG_LENGTH}, - #else - {"NULL_IS_WRONG_LENGTH", 13, 144}, - #endif - #ifdef ASN1_R_OBJECT_NOT_ASCII_FORMAT - {"OBJECT_NOT_ASCII_FORMAT", ERR_LIB_ASN1, ASN1_R_OBJECT_NOT_ASCII_FORMAT}, - #else - {"OBJECT_NOT_ASCII_FORMAT", 13, 191}, - #endif - #ifdef ASN1_R_ODD_NUMBER_OF_CHARS - {"ODD_NUMBER_OF_CHARS", ERR_LIB_ASN1, ASN1_R_ODD_NUMBER_OF_CHARS}, - #else - {"ODD_NUMBER_OF_CHARS", 13, 145}, - #endif - #ifdef ASN1_R_SECOND_NUMBER_TOO_LARGE - {"SECOND_NUMBER_TOO_LARGE", ERR_LIB_ASN1, ASN1_R_SECOND_NUMBER_TOO_LARGE}, - #else - {"SECOND_NUMBER_TOO_LARGE", 13, 147}, - #endif - #ifdef ASN1_R_SEQUENCE_LENGTH_MISMATCH - {"SEQUENCE_LENGTH_MISMATCH", ERR_LIB_ASN1, ASN1_R_SEQUENCE_LENGTH_MISMATCH}, - #else - {"SEQUENCE_LENGTH_MISMATCH", 13, 148}, - #endif - #ifdef ASN1_R_SEQUENCE_NOT_CONSTRUCTED - {"SEQUENCE_NOT_CONSTRUCTED", ERR_LIB_ASN1, ASN1_R_SEQUENCE_NOT_CONSTRUCTED}, - #else - {"SEQUENCE_NOT_CONSTRUCTED", 13, 149}, - #endif - #ifdef ASN1_R_SEQUENCE_OR_SET_NEEDS_CONFIG - {"SEQUENCE_OR_SET_NEEDS_CONFIG", ERR_LIB_ASN1, ASN1_R_SEQUENCE_OR_SET_NEEDS_CONFIG}, - #else - {"SEQUENCE_OR_SET_NEEDS_CONFIG", 13, 192}, - #endif - #ifdef ASN1_R_SHORT_LINE - {"SHORT_LINE", ERR_LIB_ASN1, ASN1_R_SHORT_LINE}, - #else - {"SHORT_LINE", 13, 150}, - #endif - #ifdef ASN1_R_SIG_INVALID_MIME_TYPE - {"SIG_INVALID_MIME_TYPE", ERR_LIB_ASN1, ASN1_R_SIG_INVALID_MIME_TYPE}, - #else - {"SIG_INVALID_MIME_TYPE", 13, 213}, - #endif - #ifdef ASN1_R_STREAMING_NOT_SUPPORTED - {"STREAMING_NOT_SUPPORTED", ERR_LIB_ASN1, ASN1_R_STREAMING_NOT_SUPPORTED}, - #else - {"STREAMING_NOT_SUPPORTED", 13, 202}, - #endif - #ifdef ASN1_R_STRING_TOO_LONG - {"STRING_TOO_LONG", ERR_LIB_ASN1, ASN1_R_STRING_TOO_LONG}, - #else - {"STRING_TOO_LONG", 13, 151}, - #endif - #ifdef ASN1_R_STRING_TOO_SHORT - {"STRING_TOO_SHORT", ERR_LIB_ASN1, ASN1_R_STRING_TOO_SHORT}, - #else - {"STRING_TOO_SHORT", 13, 152}, - #endif - #ifdef ASN1_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD - {"THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD", ERR_LIB_ASN1, ASN1_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD}, - #else - {"THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD", 13, 154}, - #endif - #ifdef ASN1_R_TIME_NOT_ASCII_FORMAT - {"TIME_NOT_ASCII_FORMAT", ERR_LIB_ASN1, ASN1_R_TIME_NOT_ASCII_FORMAT}, - #else - {"TIME_NOT_ASCII_FORMAT", 13, 193}, - #endif - #ifdef ASN1_R_TOO_LARGE - {"TOO_LARGE", ERR_LIB_ASN1, ASN1_R_TOO_LARGE}, - #else - {"TOO_LARGE", 13, 223}, - #endif - #ifdef ASN1_R_TOO_LONG - {"TOO_LONG", ERR_LIB_ASN1, ASN1_R_TOO_LONG}, - #else - {"TOO_LONG", 13, 155}, - #endif - #ifdef ASN1_R_TOO_SMALL - {"TOO_SMALL", ERR_LIB_ASN1, ASN1_R_TOO_SMALL}, - #else - {"TOO_SMALL", 13, 224}, - #endif - #ifdef ASN1_R_TYPE_NOT_CONSTRUCTED - {"TYPE_NOT_CONSTRUCTED", ERR_LIB_ASN1, ASN1_R_TYPE_NOT_CONSTRUCTED}, - #else - {"TYPE_NOT_CONSTRUCTED", 13, 156}, - #endif - #ifdef ASN1_R_TYPE_NOT_PRIMITIVE - {"TYPE_NOT_PRIMITIVE", ERR_LIB_ASN1, ASN1_R_TYPE_NOT_PRIMITIVE}, - #else - {"TYPE_NOT_PRIMITIVE", 13, 195}, - #endif - #ifdef ASN1_R_UNEXPECTED_EOC - {"UNEXPECTED_EOC", ERR_LIB_ASN1, ASN1_R_UNEXPECTED_EOC}, - #else - {"UNEXPECTED_EOC", 13, 159}, - #endif - #ifdef ASN1_R_UNIVERSALSTRING_IS_WRONG_LENGTH - {"UNIVERSALSTRING_IS_WRONG_LENGTH", ERR_LIB_ASN1, ASN1_R_UNIVERSALSTRING_IS_WRONG_LENGTH}, - #else - {"UNIVERSALSTRING_IS_WRONG_LENGTH", 13, 215}, - #endif - #ifdef ASN1_R_UNKNOWN_FORMAT - {"UNKNOWN_FORMAT", ERR_LIB_ASN1, ASN1_R_UNKNOWN_FORMAT}, - #else - {"UNKNOWN_FORMAT", 13, 160}, - #endif - #ifdef ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM - {"UNKNOWN_MESSAGE_DIGEST_ALGORITHM", ERR_LIB_ASN1, ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM}, - #else - {"UNKNOWN_MESSAGE_DIGEST_ALGORITHM", 13, 161}, - #endif - #ifdef ASN1_R_UNKNOWN_OBJECT_TYPE - {"UNKNOWN_OBJECT_TYPE", ERR_LIB_ASN1, ASN1_R_UNKNOWN_OBJECT_TYPE}, - #else - {"UNKNOWN_OBJECT_TYPE", 13, 162}, - #endif - #ifdef ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE - {"UNKNOWN_PUBLIC_KEY_TYPE", ERR_LIB_ASN1, ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE}, - #else - {"UNKNOWN_PUBLIC_KEY_TYPE", 13, 163}, - #endif - #ifdef ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM - {"UNKNOWN_SIGNATURE_ALGORITHM", ERR_LIB_ASN1, ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM}, - #else - {"UNKNOWN_SIGNATURE_ALGORITHM", 13, 199}, - #endif - #ifdef ASN1_R_UNKNOWN_TAG - {"UNKNOWN_TAG", ERR_LIB_ASN1, ASN1_R_UNKNOWN_TAG}, - #else - {"UNKNOWN_TAG", 13, 194}, - #endif - #ifdef ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE - {"UNSUPPORTED_ANY_DEFINED_BY_TYPE", ERR_LIB_ASN1, ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE}, - #else - {"UNSUPPORTED_ANY_DEFINED_BY_TYPE", 13, 164}, - #endif - #ifdef ASN1_R_UNSUPPORTED_CIPHER - {"UNSUPPORTED_CIPHER", ERR_LIB_ASN1, ASN1_R_UNSUPPORTED_CIPHER}, - #else - {"UNSUPPORTED_CIPHER", 13, 228}, - #endif - #ifdef ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE - {"UNSUPPORTED_PUBLIC_KEY_TYPE", ERR_LIB_ASN1, ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE}, - #else - {"UNSUPPORTED_PUBLIC_KEY_TYPE", 13, 167}, - #endif - #ifdef ASN1_R_UNSUPPORTED_TYPE - {"UNSUPPORTED_TYPE", ERR_LIB_ASN1, ASN1_R_UNSUPPORTED_TYPE}, - #else - {"UNSUPPORTED_TYPE", 13, 196}, - #endif - #ifdef ASN1_R_WRONG_INTEGER_TYPE - {"WRONG_INTEGER_TYPE", ERR_LIB_ASN1, ASN1_R_WRONG_INTEGER_TYPE}, - #else - {"WRONG_INTEGER_TYPE", 13, 225}, - #endif - #ifdef ASN1_R_WRONG_PUBLIC_KEY_TYPE - {"WRONG_PUBLIC_KEY_TYPE", ERR_LIB_ASN1, ASN1_R_WRONG_PUBLIC_KEY_TYPE}, - #else - {"WRONG_PUBLIC_KEY_TYPE", 13, 200}, - #endif - #ifdef ASN1_R_WRONG_TAG - {"WRONG_TAG", ERR_LIB_ASN1, ASN1_R_WRONG_TAG}, - #else - {"WRONG_TAG", 13, 168}, - #endif - #ifdef ASYNC_R_FAILED_TO_SET_POOL - {"FAILED_TO_SET_POOL", ERR_LIB_ASYNC, ASYNC_R_FAILED_TO_SET_POOL}, - #else - {"FAILED_TO_SET_POOL", 51, 101}, - #endif - #ifdef ASYNC_R_FAILED_TO_SWAP_CONTEXT - {"FAILED_TO_SWAP_CONTEXT", ERR_LIB_ASYNC, ASYNC_R_FAILED_TO_SWAP_CONTEXT}, - #else - {"FAILED_TO_SWAP_CONTEXT", 51, 102}, - #endif - #ifdef ASYNC_R_INIT_FAILED - {"INIT_FAILED", ERR_LIB_ASYNC, ASYNC_R_INIT_FAILED}, - #else - {"INIT_FAILED", 51, 105}, - #endif - #ifdef ASYNC_R_INVALID_POOL_SIZE - {"INVALID_POOL_SIZE", ERR_LIB_ASYNC, ASYNC_R_INVALID_POOL_SIZE}, - #else - {"INVALID_POOL_SIZE", 51, 103}, - #endif - #ifdef BIO_R_ACCEPT_ERROR - {"ACCEPT_ERROR", ERR_LIB_BIO, BIO_R_ACCEPT_ERROR}, - #else - {"ACCEPT_ERROR", 32, 100}, - #endif - #ifdef BIO_R_ADDRINFO_ADDR_IS_NOT_AF_INET - {"ADDRINFO_ADDR_IS_NOT_AF_INET", ERR_LIB_BIO, BIO_R_ADDRINFO_ADDR_IS_NOT_AF_INET}, - #else - {"ADDRINFO_ADDR_IS_NOT_AF_INET", 32, 141}, - #endif - #ifdef BIO_R_AMBIGUOUS_HOST_OR_SERVICE - {"AMBIGUOUS_HOST_OR_SERVICE", ERR_LIB_BIO, BIO_R_AMBIGUOUS_HOST_OR_SERVICE}, - #else - {"AMBIGUOUS_HOST_OR_SERVICE", 32, 129}, - #endif - #ifdef BIO_R_BAD_FOPEN_MODE - {"BAD_FOPEN_MODE", ERR_LIB_BIO, BIO_R_BAD_FOPEN_MODE}, - #else - {"BAD_FOPEN_MODE", 32, 101}, - #endif - #ifdef BIO_R_BROKEN_PIPE - {"BROKEN_PIPE", ERR_LIB_BIO, BIO_R_BROKEN_PIPE}, - #else - {"BROKEN_PIPE", 32, 124}, - #endif - #ifdef BIO_R_CONNECT_ERROR - {"CONNECT_ERROR", ERR_LIB_BIO, BIO_R_CONNECT_ERROR}, - #else - {"CONNECT_ERROR", 32, 103}, - #endif - #ifdef BIO_R_GETHOSTBYNAME_ADDR_IS_NOT_AF_INET - {"GETHOSTBYNAME_ADDR_IS_NOT_AF_INET", ERR_LIB_BIO, BIO_R_GETHOSTBYNAME_ADDR_IS_NOT_AF_INET}, - #else - {"GETHOSTBYNAME_ADDR_IS_NOT_AF_INET", 32, 107}, - #endif - #ifdef BIO_R_GETSOCKNAME_ERROR - {"GETSOCKNAME_ERROR", ERR_LIB_BIO, BIO_R_GETSOCKNAME_ERROR}, - #else - {"GETSOCKNAME_ERROR", 32, 132}, - #endif - #ifdef BIO_R_GETSOCKNAME_TRUNCATED_ADDRESS - {"GETSOCKNAME_TRUNCATED_ADDRESS", ERR_LIB_BIO, BIO_R_GETSOCKNAME_TRUNCATED_ADDRESS}, - #else - {"GETSOCKNAME_TRUNCATED_ADDRESS", 32, 133}, - #endif - #ifdef BIO_R_GETTING_SOCKTYPE - {"GETTING_SOCKTYPE", ERR_LIB_BIO, BIO_R_GETTING_SOCKTYPE}, - #else - {"GETTING_SOCKTYPE", 32, 134}, - #endif - #ifdef BIO_R_INVALID_ARGUMENT - {"INVALID_ARGUMENT", ERR_LIB_BIO, BIO_R_INVALID_ARGUMENT}, - #else - {"INVALID_ARGUMENT", 32, 125}, - #endif - #ifdef BIO_R_INVALID_SOCKET - {"INVALID_SOCKET", ERR_LIB_BIO, BIO_R_INVALID_SOCKET}, - #else - {"INVALID_SOCKET", 32, 135}, - #endif - #ifdef BIO_R_IN_USE - {"IN_USE", ERR_LIB_BIO, BIO_R_IN_USE}, - #else - {"IN_USE", 32, 123}, - #endif - #ifdef BIO_R_LENGTH_TOO_LONG - {"LENGTH_TOO_LONG", ERR_LIB_BIO, BIO_R_LENGTH_TOO_LONG}, - #else - {"LENGTH_TOO_LONG", 32, 102}, - #endif - #ifdef BIO_R_LISTEN_V6_ONLY - {"LISTEN_V6_ONLY", ERR_LIB_BIO, BIO_R_LISTEN_V6_ONLY}, - #else - {"LISTEN_V6_ONLY", 32, 136}, - #endif - #ifdef BIO_R_LOOKUP_RETURNED_NOTHING - {"LOOKUP_RETURNED_NOTHING", ERR_LIB_BIO, BIO_R_LOOKUP_RETURNED_NOTHING}, - #else - {"LOOKUP_RETURNED_NOTHING", 32, 142}, - #endif - #ifdef BIO_R_MALFORMED_HOST_OR_SERVICE - {"MALFORMED_HOST_OR_SERVICE", ERR_LIB_BIO, BIO_R_MALFORMED_HOST_OR_SERVICE}, - #else - {"MALFORMED_HOST_OR_SERVICE", 32, 130}, - #endif - #ifdef BIO_R_NBIO_CONNECT_ERROR - {"NBIO_CONNECT_ERROR", ERR_LIB_BIO, BIO_R_NBIO_CONNECT_ERROR}, - #else - {"NBIO_CONNECT_ERROR", 32, 110}, - #endif - #ifdef BIO_R_NO_ACCEPT_ADDR_OR_SERVICE_SPECIFIED - {"NO_ACCEPT_ADDR_OR_SERVICE_SPECIFIED", ERR_LIB_BIO, BIO_R_NO_ACCEPT_ADDR_OR_SERVICE_SPECIFIED}, - #else - {"NO_ACCEPT_ADDR_OR_SERVICE_SPECIFIED", 32, 143}, - #endif - #ifdef BIO_R_NO_HOSTNAME_OR_SERVICE_SPECIFIED - {"NO_HOSTNAME_OR_SERVICE_SPECIFIED", ERR_LIB_BIO, BIO_R_NO_HOSTNAME_OR_SERVICE_SPECIFIED}, - #else - {"NO_HOSTNAME_OR_SERVICE_SPECIFIED", 32, 144}, - #endif - #ifdef BIO_R_NO_PORT_DEFINED - {"NO_PORT_DEFINED", ERR_LIB_BIO, BIO_R_NO_PORT_DEFINED}, - #else - {"NO_PORT_DEFINED", 32, 113}, - #endif - #ifdef BIO_R_NO_SUCH_FILE - {"NO_SUCH_FILE", ERR_LIB_BIO, BIO_R_NO_SUCH_FILE}, - #else - {"NO_SUCH_FILE", 32, 128}, - #endif - #ifdef BIO_R_NULL_PARAMETER - {"NULL_PARAMETER", ERR_LIB_BIO, BIO_R_NULL_PARAMETER}, - #else - {"NULL_PARAMETER", 32, 115}, - #endif - #ifdef BIO_R_UNABLE_TO_BIND_SOCKET - {"UNABLE_TO_BIND_SOCKET", ERR_LIB_BIO, BIO_R_UNABLE_TO_BIND_SOCKET}, - #else - {"UNABLE_TO_BIND_SOCKET", 32, 117}, - #endif - #ifdef BIO_R_UNABLE_TO_CREATE_SOCKET - {"UNABLE_TO_CREATE_SOCKET", ERR_LIB_BIO, BIO_R_UNABLE_TO_CREATE_SOCKET}, - #else - {"UNABLE_TO_CREATE_SOCKET", 32, 118}, - #endif - #ifdef BIO_R_UNABLE_TO_KEEPALIVE - {"UNABLE_TO_KEEPALIVE", ERR_LIB_BIO, BIO_R_UNABLE_TO_KEEPALIVE}, - #else - {"UNABLE_TO_KEEPALIVE", 32, 137}, - #endif - #ifdef BIO_R_UNABLE_TO_LISTEN_SOCKET - {"UNABLE_TO_LISTEN_SOCKET", ERR_LIB_BIO, BIO_R_UNABLE_TO_LISTEN_SOCKET}, - #else - {"UNABLE_TO_LISTEN_SOCKET", 32, 119}, - #endif - #ifdef BIO_R_UNABLE_TO_NODELAY - {"UNABLE_TO_NODELAY", ERR_LIB_BIO, BIO_R_UNABLE_TO_NODELAY}, - #else - {"UNABLE_TO_NODELAY", 32, 138}, - #endif - #ifdef BIO_R_UNABLE_TO_REUSEADDR - {"UNABLE_TO_REUSEADDR", ERR_LIB_BIO, BIO_R_UNABLE_TO_REUSEADDR}, - #else - {"UNABLE_TO_REUSEADDR", 32, 139}, - #endif - #ifdef BIO_R_UNAVAILABLE_IP_FAMILY - {"UNAVAILABLE_IP_FAMILY", ERR_LIB_BIO, BIO_R_UNAVAILABLE_IP_FAMILY}, - #else - {"UNAVAILABLE_IP_FAMILY", 32, 145}, - #endif - #ifdef BIO_R_UNINITIALIZED - {"UNINITIALIZED", ERR_LIB_BIO, BIO_R_UNINITIALIZED}, - #else - {"UNINITIALIZED", 32, 120}, - #endif - #ifdef BIO_R_UNKNOWN_INFO_TYPE - {"UNKNOWN_INFO_TYPE", ERR_LIB_BIO, BIO_R_UNKNOWN_INFO_TYPE}, - #else - {"UNKNOWN_INFO_TYPE", 32, 140}, - #endif - #ifdef BIO_R_UNSUPPORTED_IP_FAMILY - {"UNSUPPORTED_IP_FAMILY", ERR_LIB_BIO, BIO_R_UNSUPPORTED_IP_FAMILY}, - #else - {"UNSUPPORTED_IP_FAMILY", 32, 146}, - #endif - #ifdef BIO_R_UNSUPPORTED_METHOD - {"UNSUPPORTED_METHOD", ERR_LIB_BIO, BIO_R_UNSUPPORTED_METHOD}, - #else - {"UNSUPPORTED_METHOD", 32, 121}, - #endif - #ifdef BIO_R_UNSUPPORTED_PROTOCOL_FAMILY - {"UNSUPPORTED_PROTOCOL_FAMILY", ERR_LIB_BIO, BIO_R_UNSUPPORTED_PROTOCOL_FAMILY}, - #else - {"UNSUPPORTED_PROTOCOL_FAMILY", 32, 131}, - #endif - #ifdef BIO_R_WRITE_TO_READ_ONLY_BIO - {"WRITE_TO_READ_ONLY_BIO", ERR_LIB_BIO, BIO_R_WRITE_TO_READ_ONLY_BIO}, - #else - {"WRITE_TO_READ_ONLY_BIO", 32, 126}, - #endif - #ifdef BIO_R_WSASTARTUP - {"WSASTARTUP", ERR_LIB_BIO, BIO_R_WSASTARTUP}, - #else - {"WSASTARTUP", 32, 122}, - #endif - #ifdef BN_R_ARG2_LT_ARG3 - {"ARG2_LT_ARG3", ERR_LIB_BN, BN_R_ARG2_LT_ARG3}, - #else - {"ARG2_LT_ARG3", 3, 100}, - #endif - #ifdef BN_R_BAD_RECIPROCAL - {"BAD_RECIPROCAL", ERR_LIB_BN, BN_R_BAD_RECIPROCAL}, - #else - {"BAD_RECIPROCAL", 3, 101}, - #endif - #ifdef BN_R_BIGNUM_TOO_LONG - {"BIGNUM_TOO_LONG", ERR_LIB_BN, BN_R_BIGNUM_TOO_LONG}, - #else - {"BIGNUM_TOO_LONG", 3, 114}, - #endif - #ifdef BN_R_BITS_TOO_SMALL - {"BITS_TOO_SMALL", ERR_LIB_BN, BN_R_BITS_TOO_SMALL}, - #else - {"BITS_TOO_SMALL", 3, 118}, - #endif - #ifdef BN_R_CALLED_WITH_EVEN_MODULUS - {"CALLED_WITH_EVEN_MODULUS", ERR_LIB_BN, BN_R_CALLED_WITH_EVEN_MODULUS}, - #else - {"CALLED_WITH_EVEN_MODULUS", 3, 102}, - #endif - #ifdef BN_R_DIV_BY_ZERO - {"DIV_BY_ZERO", ERR_LIB_BN, BN_R_DIV_BY_ZERO}, - #else - {"DIV_BY_ZERO", 3, 103}, - #endif - #ifdef BN_R_ENCODING_ERROR - {"ENCODING_ERROR", ERR_LIB_BN, BN_R_ENCODING_ERROR}, - #else - {"ENCODING_ERROR", 3, 104}, - #endif - #ifdef BN_R_EXPAND_ON_STATIC_BIGNUM_DATA - {"EXPAND_ON_STATIC_BIGNUM_DATA", ERR_LIB_BN, BN_R_EXPAND_ON_STATIC_BIGNUM_DATA}, - #else - {"EXPAND_ON_STATIC_BIGNUM_DATA", 3, 105}, - #endif - #ifdef BN_R_INPUT_NOT_REDUCED - {"INPUT_NOT_REDUCED", ERR_LIB_BN, BN_R_INPUT_NOT_REDUCED}, - #else - {"INPUT_NOT_REDUCED", 3, 110}, - #endif - #ifdef BN_R_INVALID_LENGTH - {"INVALID_LENGTH", ERR_LIB_BN, BN_R_INVALID_LENGTH}, - #else - {"INVALID_LENGTH", 3, 106}, - #endif - #ifdef BN_R_INVALID_RANGE - {"INVALID_RANGE", ERR_LIB_BN, BN_R_INVALID_RANGE}, - #else - {"INVALID_RANGE", 3, 115}, - #endif - #ifdef BN_R_INVALID_SHIFT - {"INVALID_SHIFT", ERR_LIB_BN, BN_R_INVALID_SHIFT}, - #else - {"INVALID_SHIFT", 3, 119}, - #endif - #ifdef BN_R_NOT_A_SQUARE - {"NOT_A_SQUARE", ERR_LIB_BN, BN_R_NOT_A_SQUARE}, - #else - {"NOT_A_SQUARE", 3, 111}, - #endif - #ifdef BN_R_NOT_INITIALIZED - {"NOT_INITIALIZED", ERR_LIB_BN, BN_R_NOT_INITIALIZED}, - #else - {"NOT_INITIALIZED", 3, 107}, - #endif - #ifdef BN_R_NO_INVERSE - {"NO_INVERSE", ERR_LIB_BN, BN_R_NO_INVERSE}, - #else - {"NO_INVERSE", 3, 108}, - #endif - #ifdef BN_R_NO_SOLUTION - {"NO_SOLUTION", ERR_LIB_BN, BN_R_NO_SOLUTION}, - #else - {"NO_SOLUTION", 3, 116}, - #endif - #ifdef BN_R_PRIVATE_KEY_TOO_LARGE - {"PRIVATE_KEY_TOO_LARGE", ERR_LIB_BN, BN_R_PRIVATE_KEY_TOO_LARGE}, - #else - {"PRIVATE_KEY_TOO_LARGE", 3, 117}, - #endif - #ifdef BN_R_P_IS_NOT_PRIME - {"P_IS_NOT_PRIME", ERR_LIB_BN, BN_R_P_IS_NOT_PRIME}, - #else - {"P_IS_NOT_PRIME", 3, 112}, - #endif - #ifdef BN_R_TOO_MANY_ITERATIONS - {"TOO_MANY_ITERATIONS", ERR_LIB_BN, BN_R_TOO_MANY_ITERATIONS}, - #else - {"TOO_MANY_ITERATIONS", 3, 113}, - #endif - #ifdef BN_R_TOO_MANY_TEMPORARY_VARIABLES - {"TOO_MANY_TEMPORARY_VARIABLES", ERR_LIB_BN, BN_R_TOO_MANY_TEMPORARY_VARIABLES}, - #else - {"TOO_MANY_TEMPORARY_VARIABLES", 3, 109}, - #endif - #ifdef CMS_R_ADD_SIGNER_ERROR - {"ADD_SIGNER_ERROR", ERR_LIB_CMS, CMS_R_ADD_SIGNER_ERROR}, - #else - {"ADD_SIGNER_ERROR", 46, 99}, - #endif - #ifdef CMS_R_ATTRIBUTE_ERROR - {"ATTRIBUTE_ERROR", ERR_LIB_CMS, CMS_R_ATTRIBUTE_ERROR}, - #else - {"ATTRIBUTE_ERROR", 46, 161}, - #endif - #ifdef CMS_R_CERTIFICATE_ALREADY_PRESENT - {"CERTIFICATE_ALREADY_PRESENT", ERR_LIB_CMS, CMS_R_CERTIFICATE_ALREADY_PRESENT}, - #else - {"CERTIFICATE_ALREADY_PRESENT", 46, 175}, - #endif - #ifdef CMS_R_CERTIFICATE_HAS_NO_KEYID - {"CERTIFICATE_HAS_NO_KEYID", ERR_LIB_CMS, CMS_R_CERTIFICATE_HAS_NO_KEYID}, - #else - {"CERTIFICATE_HAS_NO_KEYID", 46, 160}, - #endif - #ifdef CMS_R_CERTIFICATE_VERIFY_ERROR - {"CERTIFICATE_VERIFY_ERROR", ERR_LIB_CMS, CMS_R_CERTIFICATE_VERIFY_ERROR}, - #else - {"CERTIFICATE_VERIFY_ERROR", 46, 100}, - #endif - #ifdef CMS_R_CIPHER_INITIALISATION_ERROR - {"CIPHER_INITIALISATION_ERROR", ERR_LIB_CMS, CMS_R_CIPHER_INITIALISATION_ERROR}, - #else - {"CIPHER_INITIALISATION_ERROR", 46, 101}, - #endif - #ifdef CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR - {"CIPHER_PARAMETER_INITIALISATION_ERROR", ERR_LIB_CMS, CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR}, - #else - {"CIPHER_PARAMETER_INITIALISATION_ERROR", 46, 102}, - #endif - #ifdef CMS_R_CMS_DATAFINAL_ERROR - {"CMS_DATAFINAL_ERROR", ERR_LIB_CMS, CMS_R_CMS_DATAFINAL_ERROR}, - #else - {"CMS_DATAFINAL_ERROR", 46, 103}, - #endif - #ifdef CMS_R_CMS_LIB - {"CMS_LIB", ERR_LIB_CMS, CMS_R_CMS_LIB}, - #else - {"CMS_LIB", 46, 104}, - #endif - #ifdef CMS_R_CONTENTIDENTIFIER_MISMATCH - {"CONTENTIDENTIFIER_MISMATCH", ERR_LIB_CMS, CMS_R_CONTENTIDENTIFIER_MISMATCH}, - #else - {"CONTENTIDENTIFIER_MISMATCH", 46, 170}, - #endif - #ifdef CMS_R_CONTENT_NOT_FOUND - {"CONTENT_NOT_FOUND", ERR_LIB_CMS, CMS_R_CONTENT_NOT_FOUND}, - #else - {"CONTENT_NOT_FOUND", 46, 105}, - #endif - #ifdef CMS_R_CONTENT_TYPE_MISMATCH - {"CONTENT_TYPE_MISMATCH", ERR_LIB_CMS, CMS_R_CONTENT_TYPE_MISMATCH}, - #else - {"CONTENT_TYPE_MISMATCH", 46, 171}, - #endif - #ifdef CMS_R_CONTENT_TYPE_NOT_COMPRESSED_DATA - {"CONTENT_TYPE_NOT_COMPRESSED_DATA", ERR_LIB_CMS, CMS_R_CONTENT_TYPE_NOT_COMPRESSED_DATA}, - #else - {"CONTENT_TYPE_NOT_COMPRESSED_DATA", 46, 106}, - #endif - #ifdef CMS_R_CONTENT_TYPE_NOT_ENVELOPED_DATA - {"CONTENT_TYPE_NOT_ENVELOPED_DATA", ERR_LIB_CMS, CMS_R_CONTENT_TYPE_NOT_ENVELOPED_DATA}, - #else - {"CONTENT_TYPE_NOT_ENVELOPED_DATA", 46, 107}, - #endif - #ifdef CMS_R_CONTENT_TYPE_NOT_SIGNED_DATA - {"CONTENT_TYPE_NOT_SIGNED_DATA", ERR_LIB_CMS, CMS_R_CONTENT_TYPE_NOT_SIGNED_DATA}, - #else - {"CONTENT_TYPE_NOT_SIGNED_DATA", 46, 108}, - #endif - #ifdef CMS_R_CONTENT_VERIFY_ERROR - {"CONTENT_VERIFY_ERROR", ERR_LIB_CMS, CMS_R_CONTENT_VERIFY_ERROR}, - #else - {"CONTENT_VERIFY_ERROR", 46, 109}, - #endif - #ifdef CMS_R_CTRL_ERROR - {"CTRL_ERROR", ERR_LIB_CMS, CMS_R_CTRL_ERROR}, - #else - {"CTRL_ERROR", 46, 110}, - #endif - #ifdef CMS_R_CTRL_FAILURE - {"CTRL_FAILURE", ERR_LIB_CMS, CMS_R_CTRL_FAILURE}, - #else - {"CTRL_FAILURE", 46, 111}, - #endif - #ifdef CMS_R_DECRYPT_ERROR - {"DECRYPT_ERROR", ERR_LIB_CMS, CMS_R_DECRYPT_ERROR}, - #else - {"DECRYPT_ERROR", 46, 112}, - #endif - #ifdef CMS_R_ERROR_GETTING_PUBLIC_KEY - {"ERROR_GETTING_PUBLIC_KEY", ERR_LIB_CMS, CMS_R_ERROR_GETTING_PUBLIC_KEY}, - #else - {"ERROR_GETTING_PUBLIC_KEY", 46, 113}, - #endif - #ifdef CMS_R_ERROR_READING_MESSAGEDIGEST_ATTRIBUTE - {"ERROR_READING_MESSAGEDIGEST_ATTRIBUTE", ERR_LIB_CMS, CMS_R_ERROR_READING_MESSAGEDIGEST_ATTRIBUTE}, - #else - {"ERROR_READING_MESSAGEDIGEST_ATTRIBUTE", 46, 114}, - #endif - #ifdef CMS_R_ERROR_SETTING_KEY - {"ERROR_SETTING_KEY", ERR_LIB_CMS, CMS_R_ERROR_SETTING_KEY}, - #else - {"ERROR_SETTING_KEY", 46, 115}, - #endif - #ifdef CMS_R_ERROR_SETTING_RECIPIENTINFO - {"ERROR_SETTING_RECIPIENTINFO", ERR_LIB_CMS, CMS_R_ERROR_SETTING_RECIPIENTINFO}, - #else - {"ERROR_SETTING_RECIPIENTINFO", 46, 116}, - #endif - #ifdef CMS_R_INVALID_ENCRYPTED_KEY_LENGTH - {"INVALID_ENCRYPTED_KEY_LENGTH", ERR_LIB_CMS, CMS_R_INVALID_ENCRYPTED_KEY_LENGTH}, - #else - {"INVALID_ENCRYPTED_KEY_LENGTH", 46, 117}, - #endif - #ifdef CMS_R_INVALID_KEY_ENCRYPTION_PARAMETER - {"INVALID_KEY_ENCRYPTION_PARAMETER", ERR_LIB_CMS, CMS_R_INVALID_KEY_ENCRYPTION_PARAMETER}, - #else - {"INVALID_KEY_ENCRYPTION_PARAMETER", 46, 176}, - #endif - #ifdef CMS_R_INVALID_KEY_LENGTH - {"INVALID_KEY_LENGTH", ERR_LIB_CMS, CMS_R_INVALID_KEY_LENGTH}, - #else - {"INVALID_KEY_LENGTH", 46, 118}, - #endif - #ifdef CMS_R_MD_BIO_INIT_ERROR - {"MD_BIO_INIT_ERROR", ERR_LIB_CMS, CMS_R_MD_BIO_INIT_ERROR}, - #else - {"MD_BIO_INIT_ERROR", 46, 119}, - #endif - #ifdef CMS_R_MESSAGEDIGEST_ATTRIBUTE_WRONG_LENGTH - {"MESSAGEDIGEST_ATTRIBUTE_WRONG_LENGTH", ERR_LIB_CMS, CMS_R_MESSAGEDIGEST_ATTRIBUTE_WRONG_LENGTH}, - #else - {"MESSAGEDIGEST_ATTRIBUTE_WRONG_LENGTH", 46, 120}, - #endif - #ifdef CMS_R_MESSAGEDIGEST_WRONG_LENGTH - {"MESSAGEDIGEST_WRONG_LENGTH", ERR_LIB_CMS, CMS_R_MESSAGEDIGEST_WRONG_LENGTH}, - #else - {"MESSAGEDIGEST_WRONG_LENGTH", 46, 121}, - #endif - #ifdef CMS_R_MSGSIGDIGEST_ERROR - {"MSGSIGDIGEST_ERROR", ERR_LIB_CMS, CMS_R_MSGSIGDIGEST_ERROR}, - #else - {"MSGSIGDIGEST_ERROR", 46, 172}, - #endif - #ifdef CMS_R_MSGSIGDIGEST_VERIFICATION_FAILURE - {"MSGSIGDIGEST_VERIFICATION_FAILURE", ERR_LIB_CMS, CMS_R_MSGSIGDIGEST_VERIFICATION_FAILURE}, - #else - {"MSGSIGDIGEST_VERIFICATION_FAILURE", 46, 162}, - #endif - #ifdef CMS_R_MSGSIGDIGEST_WRONG_LENGTH - {"MSGSIGDIGEST_WRONG_LENGTH", ERR_LIB_CMS, CMS_R_MSGSIGDIGEST_WRONG_LENGTH}, - #else - {"MSGSIGDIGEST_WRONG_LENGTH", 46, 163}, - #endif - #ifdef CMS_R_NEED_ONE_SIGNER - {"NEED_ONE_SIGNER", ERR_LIB_CMS, CMS_R_NEED_ONE_SIGNER}, - #else - {"NEED_ONE_SIGNER", 46, 164}, - #endif - #ifdef CMS_R_NOT_A_SIGNED_RECEIPT - {"NOT_A_SIGNED_RECEIPT", ERR_LIB_CMS, CMS_R_NOT_A_SIGNED_RECEIPT}, - #else - {"NOT_A_SIGNED_RECEIPT", 46, 165}, - #endif - #ifdef CMS_R_NOT_ENCRYPTED_DATA - {"NOT_ENCRYPTED_DATA", ERR_LIB_CMS, CMS_R_NOT_ENCRYPTED_DATA}, - #else - {"NOT_ENCRYPTED_DATA", 46, 122}, - #endif - #ifdef CMS_R_NOT_KEK - {"NOT_KEK", ERR_LIB_CMS, CMS_R_NOT_KEK}, - #else - {"NOT_KEK", 46, 123}, - #endif - #ifdef CMS_R_NOT_KEY_AGREEMENT - {"NOT_KEY_AGREEMENT", ERR_LIB_CMS, CMS_R_NOT_KEY_AGREEMENT}, - #else - {"NOT_KEY_AGREEMENT", 46, 181}, - #endif - #ifdef CMS_R_NOT_KEY_TRANSPORT - {"NOT_KEY_TRANSPORT", ERR_LIB_CMS, CMS_R_NOT_KEY_TRANSPORT}, - #else - {"NOT_KEY_TRANSPORT", 46, 124}, - #endif - #ifdef CMS_R_NOT_PWRI - {"NOT_PWRI", ERR_LIB_CMS, CMS_R_NOT_PWRI}, - #else - {"NOT_PWRI", 46, 177}, - #endif - #ifdef CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE - {"NOT_SUPPORTED_FOR_THIS_KEY_TYPE", ERR_LIB_CMS, CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE}, - #else - {"NOT_SUPPORTED_FOR_THIS_KEY_TYPE", 46, 125}, - #endif - #ifdef CMS_R_NO_CIPHER - {"NO_CIPHER", ERR_LIB_CMS, CMS_R_NO_CIPHER}, - #else - {"NO_CIPHER", 46, 126}, - #endif - #ifdef CMS_R_NO_CONTENT - {"NO_CONTENT", ERR_LIB_CMS, CMS_R_NO_CONTENT}, - #else - {"NO_CONTENT", 46, 127}, - #endif - #ifdef CMS_R_NO_CONTENT_TYPE - {"NO_CONTENT_TYPE", ERR_LIB_CMS, CMS_R_NO_CONTENT_TYPE}, - #else - {"NO_CONTENT_TYPE", 46, 173}, - #endif - #ifdef CMS_R_NO_DEFAULT_DIGEST - {"NO_DEFAULT_DIGEST", ERR_LIB_CMS, CMS_R_NO_DEFAULT_DIGEST}, - #else - {"NO_DEFAULT_DIGEST", 46, 128}, - #endif - #ifdef CMS_R_NO_DIGEST_SET - {"NO_DIGEST_SET", ERR_LIB_CMS, CMS_R_NO_DIGEST_SET}, - #else - {"NO_DIGEST_SET", 46, 129}, - #endif - #ifdef CMS_R_NO_KEY - {"NO_KEY", ERR_LIB_CMS, CMS_R_NO_KEY}, - #else - {"NO_KEY", 46, 130}, - #endif - #ifdef CMS_R_NO_KEY_OR_CERT - {"NO_KEY_OR_CERT", ERR_LIB_CMS, CMS_R_NO_KEY_OR_CERT}, - #else - {"NO_KEY_OR_CERT", 46, 174}, - #endif - #ifdef CMS_R_NO_MATCHING_DIGEST - {"NO_MATCHING_DIGEST", ERR_LIB_CMS, CMS_R_NO_MATCHING_DIGEST}, - #else - {"NO_MATCHING_DIGEST", 46, 131}, - #endif - #ifdef CMS_R_NO_MATCHING_RECIPIENT - {"NO_MATCHING_RECIPIENT", ERR_LIB_CMS, CMS_R_NO_MATCHING_RECIPIENT}, - #else - {"NO_MATCHING_RECIPIENT", 46, 132}, - #endif - #ifdef CMS_R_NO_MATCHING_SIGNATURE - {"NO_MATCHING_SIGNATURE", ERR_LIB_CMS, CMS_R_NO_MATCHING_SIGNATURE}, - #else - {"NO_MATCHING_SIGNATURE", 46, 166}, - #endif - #ifdef CMS_R_NO_MSGSIGDIGEST - {"NO_MSGSIGDIGEST", ERR_LIB_CMS, CMS_R_NO_MSGSIGDIGEST}, - #else - {"NO_MSGSIGDIGEST", 46, 167}, - #endif - #ifdef CMS_R_NO_PASSWORD - {"NO_PASSWORD", ERR_LIB_CMS, CMS_R_NO_PASSWORD}, - #else - {"NO_PASSWORD", 46, 178}, - #endif - #ifdef CMS_R_NO_PRIVATE_KEY - {"NO_PRIVATE_KEY", ERR_LIB_CMS, CMS_R_NO_PRIVATE_KEY}, - #else - {"NO_PRIVATE_KEY", 46, 133}, - #endif - #ifdef CMS_R_NO_PUBLIC_KEY - {"NO_PUBLIC_KEY", ERR_LIB_CMS, CMS_R_NO_PUBLIC_KEY}, - #else - {"NO_PUBLIC_KEY", 46, 134}, - #endif - #ifdef CMS_R_NO_RECEIPT_REQUEST - {"NO_RECEIPT_REQUEST", ERR_LIB_CMS, CMS_R_NO_RECEIPT_REQUEST}, - #else - {"NO_RECEIPT_REQUEST", 46, 168}, - #endif - #ifdef CMS_R_NO_SIGNERS - {"NO_SIGNERS", ERR_LIB_CMS, CMS_R_NO_SIGNERS}, - #else - {"NO_SIGNERS", 46, 135}, - #endif - #ifdef CMS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE - {"PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE", ERR_LIB_CMS, CMS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE}, - #else - {"PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE", 46, 136}, - #endif - #ifdef CMS_R_RECEIPT_DECODE_ERROR - {"RECEIPT_DECODE_ERROR", ERR_LIB_CMS, CMS_R_RECEIPT_DECODE_ERROR}, - #else - {"RECEIPT_DECODE_ERROR", 46, 169}, - #endif - #ifdef CMS_R_RECIPIENT_ERROR - {"RECIPIENT_ERROR", ERR_LIB_CMS, CMS_R_RECIPIENT_ERROR}, - #else - {"RECIPIENT_ERROR", 46, 137}, - #endif - #ifdef CMS_R_SIGNER_CERTIFICATE_NOT_FOUND - {"SIGNER_CERTIFICATE_NOT_FOUND", ERR_LIB_CMS, CMS_R_SIGNER_CERTIFICATE_NOT_FOUND}, - #else - {"SIGNER_CERTIFICATE_NOT_FOUND", 46, 138}, - #endif - #ifdef CMS_R_SIGNFINAL_ERROR - {"SIGNFINAL_ERROR", ERR_LIB_CMS, CMS_R_SIGNFINAL_ERROR}, - #else - {"SIGNFINAL_ERROR", 46, 139}, - #endif - #ifdef CMS_R_SMIME_TEXT_ERROR - {"SMIME_TEXT_ERROR", ERR_LIB_CMS, CMS_R_SMIME_TEXT_ERROR}, - #else - {"SMIME_TEXT_ERROR", 46, 140}, - #endif - #ifdef CMS_R_STORE_INIT_ERROR - {"STORE_INIT_ERROR", ERR_LIB_CMS, CMS_R_STORE_INIT_ERROR}, - #else - {"STORE_INIT_ERROR", 46, 141}, - #endif - #ifdef CMS_R_TYPE_NOT_COMPRESSED_DATA - {"TYPE_NOT_COMPRESSED_DATA", ERR_LIB_CMS, CMS_R_TYPE_NOT_COMPRESSED_DATA}, - #else - {"TYPE_NOT_COMPRESSED_DATA", 46, 142}, - #endif - #ifdef CMS_R_TYPE_NOT_DATA - {"TYPE_NOT_DATA", ERR_LIB_CMS, CMS_R_TYPE_NOT_DATA}, - #else - {"TYPE_NOT_DATA", 46, 143}, - #endif - #ifdef CMS_R_TYPE_NOT_DIGESTED_DATA - {"TYPE_NOT_DIGESTED_DATA", ERR_LIB_CMS, CMS_R_TYPE_NOT_DIGESTED_DATA}, - #else - {"TYPE_NOT_DIGESTED_DATA", 46, 144}, - #endif - #ifdef CMS_R_TYPE_NOT_ENCRYPTED_DATA - {"TYPE_NOT_ENCRYPTED_DATA", ERR_LIB_CMS, CMS_R_TYPE_NOT_ENCRYPTED_DATA}, - #else - {"TYPE_NOT_ENCRYPTED_DATA", 46, 145}, - #endif - #ifdef CMS_R_TYPE_NOT_ENVELOPED_DATA - {"TYPE_NOT_ENVELOPED_DATA", ERR_LIB_CMS, CMS_R_TYPE_NOT_ENVELOPED_DATA}, - #else - {"TYPE_NOT_ENVELOPED_DATA", 46, 146}, - #endif - #ifdef CMS_R_UNABLE_TO_FINALIZE_CONTEXT - {"UNABLE_TO_FINALIZE_CONTEXT", ERR_LIB_CMS, CMS_R_UNABLE_TO_FINALIZE_CONTEXT}, - #else - {"UNABLE_TO_FINALIZE_CONTEXT", 46, 147}, - #endif - #ifdef CMS_R_UNKNOWN_CIPHER - {"UNKNOWN_CIPHER", ERR_LIB_CMS, CMS_R_UNKNOWN_CIPHER}, - #else - {"UNKNOWN_CIPHER", 46, 148}, - #endif - #ifdef CMS_R_UNKNOWN_DIGEST_ALGORITHM - {"UNKNOWN_DIGEST_ALGORITHM", ERR_LIB_CMS, CMS_R_UNKNOWN_DIGEST_ALGORITHM}, - #else - {"UNKNOWN_DIGEST_ALGORITHM", 46, 149}, - #endif - #ifdef CMS_R_UNKNOWN_ID - {"UNKNOWN_ID", ERR_LIB_CMS, CMS_R_UNKNOWN_ID}, - #else - {"UNKNOWN_ID", 46, 150}, - #endif - #ifdef CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM - {"UNSUPPORTED_COMPRESSION_ALGORITHM", ERR_LIB_CMS, CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM}, - #else - {"UNSUPPORTED_COMPRESSION_ALGORITHM", 46, 151}, - #endif - #ifdef CMS_R_UNSUPPORTED_CONTENT_TYPE - {"UNSUPPORTED_CONTENT_TYPE", ERR_LIB_CMS, CMS_R_UNSUPPORTED_CONTENT_TYPE}, - #else - {"UNSUPPORTED_CONTENT_TYPE", 46, 152}, - #endif - #ifdef CMS_R_UNSUPPORTED_KEK_ALGORITHM - {"UNSUPPORTED_KEK_ALGORITHM", ERR_LIB_CMS, CMS_R_UNSUPPORTED_KEK_ALGORITHM}, - #else - {"UNSUPPORTED_KEK_ALGORITHM", 46, 153}, - #endif - #ifdef CMS_R_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM - {"UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM", ERR_LIB_CMS, CMS_R_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM}, - #else - {"UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM", 46, 179}, - #endif - #ifdef CMS_R_UNSUPPORTED_RECIPIENTINFO_TYPE - {"UNSUPPORTED_RECIPIENTINFO_TYPE", ERR_LIB_CMS, CMS_R_UNSUPPORTED_RECIPIENTINFO_TYPE}, - #else - {"UNSUPPORTED_RECIPIENTINFO_TYPE", 46, 155}, - #endif - #ifdef CMS_R_UNSUPPORTED_RECIPIENT_TYPE - {"UNSUPPORTED_RECIPIENT_TYPE", ERR_LIB_CMS, CMS_R_UNSUPPORTED_RECIPIENT_TYPE}, - #else - {"UNSUPPORTED_RECIPIENT_TYPE", 46, 154}, - #endif - #ifdef CMS_R_UNSUPPORTED_TYPE - {"UNSUPPORTED_TYPE", ERR_LIB_CMS, CMS_R_UNSUPPORTED_TYPE}, - #else - {"UNSUPPORTED_TYPE", 46, 156}, - #endif - #ifdef CMS_R_UNWRAP_ERROR - {"UNWRAP_ERROR", ERR_LIB_CMS, CMS_R_UNWRAP_ERROR}, - #else - {"UNWRAP_ERROR", 46, 157}, - #endif - #ifdef CMS_R_UNWRAP_FAILURE - {"UNWRAP_FAILURE", ERR_LIB_CMS, CMS_R_UNWRAP_FAILURE}, - #else - {"UNWRAP_FAILURE", 46, 180}, - #endif - #ifdef CMS_R_VERIFICATION_FAILURE - {"VERIFICATION_FAILURE", ERR_LIB_CMS, CMS_R_VERIFICATION_FAILURE}, - #else - {"VERIFICATION_FAILURE", 46, 158}, - #endif - #ifdef CMS_R_WRAP_ERROR - {"WRAP_ERROR", ERR_LIB_CMS, CMS_R_WRAP_ERROR}, - #else - {"WRAP_ERROR", 46, 159}, - #endif - #ifdef COMP_R_ZLIB_DEFLATE_ERROR - {"ZLIB_DEFLATE_ERROR", ERR_LIB_COMP, COMP_R_ZLIB_DEFLATE_ERROR}, - #else - {"ZLIB_DEFLATE_ERROR", 41, 99}, - #endif - #ifdef COMP_R_ZLIB_INFLATE_ERROR - {"ZLIB_INFLATE_ERROR", ERR_LIB_COMP, COMP_R_ZLIB_INFLATE_ERROR}, - #else - {"ZLIB_INFLATE_ERROR", 41, 100}, - #endif - #ifdef COMP_R_ZLIB_NOT_SUPPORTED - {"ZLIB_NOT_SUPPORTED", ERR_LIB_COMP, COMP_R_ZLIB_NOT_SUPPORTED}, - #else - {"ZLIB_NOT_SUPPORTED", 41, 101}, - #endif - #ifdef CONF_R_ERROR_LOADING_DSO - {"ERROR_LOADING_DSO", ERR_LIB_CONF, CONF_R_ERROR_LOADING_DSO}, - #else - {"ERROR_LOADING_DSO", 14, 110}, - #endif - #ifdef CONF_R_LIST_CANNOT_BE_NULL - {"LIST_CANNOT_BE_NULL", ERR_LIB_CONF, CONF_R_LIST_CANNOT_BE_NULL}, - #else - {"LIST_CANNOT_BE_NULL", 14, 115}, - #endif - #ifdef CONF_R_MISSING_CLOSE_SQUARE_BRACKET - {"MISSING_CLOSE_SQUARE_BRACKET", ERR_LIB_CONF, CONF_R_MISSING_CLOSE_SQUARE_BRACKET}, - #else - {"MISSING_CLOSE_SQUARE_BRACKET", 14, 100}, - #endif - #ifdef CONF_R_MISSING_EQUAL_SIGN - {"MISSING_EQUAL_SIGN", ERR_LIB_CONF, CONF_R_MISSING_EQUAL_SIGN}, - #else - {"MISSING_EQUAL_SIGN", 14, 101}, - #endif - #ifdef CONF_R_MISSING_INIT_FUNCTION - {"MISSING_INIT_FUNCTION", ERR_LIB_CONF, CONF_R_MISSING_INIT_FUNCTION}, - #else - {"MISSING_INIT_FUNCTION", 14, 112}, - #endif - #ifdef CONF_R_MODULE_INITIALIZATION_ERROR - {"MODULE_INITIALIZATION_ERROR", ERR_LIB_CONF, CONF_R_MODULE_INITIALIZATION_ERROR}, - #else - {"MODULE_INITIALIZATION_ERROR", 14, 109}, - #endif - #ifdef CONF_R_NO_CLOSE_BRACE - {"NO_CLOSE_BRACE", ERR_LIB_CONF, CONF_R_NO_CLOSE_BRACE}, - #else - {"NO_CLOSE_BRACE", 14, 102}, - #endif - #ifdef CONF_R_NO_CONF - {"NO_CONF", ERR_LIB_CONF, CONF_R_NO_CONF}, - #else - {"NO_CONF", 14, 105}, - #endif - #ifdef CONF_R_NO_CONF_OR_ENVIRONMENT_VARIABLE - {"NO_CONF_OR_ENVIRONMENT_VARIABLE", ERR_LIB_CONF, CONF_R_NO_CONF_OR_ENVIRONMENT_VARIABLE}, - #else - {"NO_CONF_OR_ENVIRONMENT_VARIABLE", 14, 106}, - #endif - #ifdef CONF_R_NO_SECTION - {"NO_SECTION", ERR_LIB_CONF, CONF_R_NO_SECTION}, - #else - {"NO_SECTION", 14, 107}, - #endif - #ifdef CONF_R_NO_SUCH_FILE - {"NO_SUCH_FILE", ERR_LIB_CONF, CONF_R_NO_SUCH_FILE}, - #else - {"NO_SUCH_FILE", 14, 114}, - #endif - #ifdef CONF_R_NO_VALUE - {"NO_VALUE", ERR_LIB_CONF, CONF_R_NO_VALUE}, - #else - {"NO_VALUE", 14, 108}, - #endif - #ifdef CONF_R_NUMBER_TOO_LARGE - {"NUMBER_TOO_LARGE", ERR_LIB_CONF, CONF_R_NUMBER_TOO_LARGE}, - #else - {"NUMBER_TOO_LARGE", 14, 121}, - #endif - #ifdef CONF_R_RECURSIVE_DIRECTORY_INCLUDE - {"RECURSIVE_DIRECTORY_INCLUDE", ERR_LIB_CONF, CONF_R_RECURSIVE_DIRECTORY_INCLUDE}, - #else - {"RECURSIVE_DIRECTORY_INCLUDE", 14, 111}, - #endif - #ifdef CONF_R_SSL_COMMAND_SECTION_EMPTY - {"SSL_COMMAND_SECTION_EMPTY", ERR_LIB_CONF, CONF_R_SSL_COMMAND_SECTION_EMPTY}, - #else - {"SSL_COMMAND_SECTION_EMPTY", 14, 117}, - #endif - #ifdef CONF_R_SSL_COMMAND_SECTION_NOT_FOUND - {"SSL_COMMAND_SECTION_NOT_FOUND", ERR_LIB_CONF, CONF_R_SSL_COMMAND_SECTION_NOT_FOUND}, - #else - {"SSL_COMMAND_SECTION_NOT_FOUND", 14, 118}, - #endif - #ifdef CONF_R_SSL_SECTION_EMPTY - {"SSL_SECTION_EMPTY", ERR_LIB_CONF, CONF_R_SSL_SECTION_EMPTY}, - #else - {"SSL_SECTION_EMPTY", 14, 119}, - #endif - #ifdef CONF_R_SSL_SECTION_NOT_FOUND - {"SSL_SECTION_NOT_FOUND", ERR_LIB_CONF, CONF_R_SSL_SECTION_NOT_FOUND}, - #else - {"SSL_SECTION_NOT_FOUND", 14, 120}, - #endif - #ifdef CONF_R_UNABLE_TO_CREATE_NEW_SECTION - {"UNABLE_TO_CREATE_NEW_SECTION", ERR_LIB_CONF, CONF_R_UNABLE_TO_CREATE_NEW_SECTION}, - #else - {"UNABLE_TO_CREATE_NEW_SECTION", 14, 103}, - #endif - #ifdef CONF_R_UNKNOWN_MODULE_NAME - {"UNKNOWN_MODULE_NAME", ERR_LIB_CONF, CONF_R_UNKNOWN_MODULE_NAME}, - #else - {"UNKNOWN_MODULE_NAME", 14, 113}, - #endif - #ifdef CONF_R_VARIABLE_EXPANSION_TOO_LONG - {"VARIABLE_EXPANSION_TOO_LONG", ERR_LIB_CONF, CONF_R_VARIABLE_EXPANSION_TOO_LONG}, - #else - {"VARIABLE_EXPANSION_TOO_LONG", 14, 116}, - #endif - #ifdef CONF_R_VARIABLE_HAS_NO_VALUE - {"VARIABLE_HAS_NO_VALUE", ERR_LIB_CONF, CONF_R_VARIABLE_HAS_NO_VALUE}, - #else - {"VARIABLE_HAS_NO_VALUE", 14, 104}, - #endif - #ifdef CRYPTO_R_FIPS_MODE_NOT_SUPPORTED - {"FIPS_MODE_NOT_SUPPORTED", ERR_LIB_CRYPTO, CRYPTO_R_FIPS_MODE_NOT_SUPPORTED}, - #else - {"FIPS_MODE_NOT_SUPPORTED", 15, 101}, - #endif - #ifdef CRYPTO_R_ILLEGAL_HEX_DIGIT - {"ILLEGAL_HEX_DIGIT", ERR_LIB_CRYPTO, CRYPTO_R_ILLEGAL_HEX_DIGIT}, - #else - {"ILLEGAL_HEX_DIGIT", 15, 102}, - #endif - #ifdef CRYPTO_R_ODD_NUMBER_OF_DIGITS - {"ODD_NUMBER_OF_DIGITS", ERR_LIB_CRYPTO, CRYPTO_R_ODD_NUMBER_OF_DIGITS}, - #else - {"ODD_NUMBER_OF_DIGITS", 15, 103}, - #endif - #ifdef CT_R_BASE64_DECODE_ERROR - {"BASE64_DECODE_ERROR", ERR_LIB_CT, CT_R_BASE64_DECODE_ERROR}, - #else - {"BASE64_DECODE_ERROR", 50, 108}, - #endif - #ifdef CT_R_INVALID_LOG_ID_LENGTH - {"INVALID_LOG_ID_LENGTH", ERR_LIB_CT, CT_R_INVALID_LOG_ID_LENGTH}, - #else - {"INVALID_LOG_ID_LENGTH", 50, 100}, - #endif - #ifdef CT_R_LOG_CONF_INVALID - {"LOG_CONF_INVALID", ERR_LIB_CT, CT_R_LOG_CONF_INVALID}, - #else - {"LOG_CONF_INVALID", 50, 109}, - #endif - #ifdef CT_R_LOG_CONF_INVALID_KEY - {"LOG_CONF_INVALID_KEY", ERR_LIB_CT, CT_R_LOG_CONF_INVALID_KEY}, - #else - {"LOG_CONF_INVALID_KEY", 50, 110}, - #endif - #ifdef CT_R_LOG_CONF_MISSING_DESCRIPTION - {"LOG_CONF_MISSING_DESCRIPTION", ERR_LIB_CT, CT_R_LOG_CONF_MISSING_DESCRIPTION}, - #else - {"LOG_CONF_MISSING_DESCRIPTION", 50, 111}, - #endif - #ifdef CT_R_LOG_CONF_MISSING_KEY - {"LOG_CONF_MISSING_KEY", ERR_LIB_CT, CT_R_LOG_CONF_MISSING_KEY}, - #else - {"LOG_CONF_MISSING_KEY", 50, 112}, - #endif - #ifdef CT_R_LOG_KEY_INVALID - {"LOG_KEY_INVALID", ERR_LIB_CT, CT_R_LOG_KEY_INVALID}, - #else - {"LOG_KEY_INVALID", 50, 113}, - #endif - #ifdef CT_R_SCT_FUTURE_TIMESTAMP - {"SCT_FUTURE_TIMESTAMP", ERR_LIB_CT, CT_R_SCT_FUTURE_TIMESTAMP}, - #else - {"SCT_FUTURE_TIMESTAMP", 50, 116}, - #endif - #ifdef CT_R_SCT_INVALID - {"SCT_INVALID", ERR_LIB_CT, CT_R_SCT_INVALID}, - #else - {"SCT_INVALID", 50, 104}, - #endif - #ifdef CT_R_SCT_INVALID_SIGNATURE - {"SCT_INVALID_SIGNATURE", ERR_LIB_CT, CT_R_SCT_INVALID_SIGNATURE}, - #else - {"SCT_INVALID_SIGNATURE", 50, 107}, - #endif - #ifdef CT_R_SCT_LIST_INVALID - {"SCT_LIST_INVALID", ERR_LIB_CT, CT_R_SCT_LIST_INVALID}, - #else - {"SCT_LIST_INVALID", 50, 105}, - #endif - #ifdef CT_R_SCT_LOG_ID_MISMATCH - {"SCT_LOG_ID_MISMATCH", ERR_LIB_CT, CT_R_SCT_LOG_ID_MISMATCH}, - #else - {"SCT_LOG_ID_MISMATCH", 50, 114}, - #endif - #ifdef CT_R_SCT_NOT_SET - {"SCT_NOT_SET", ERR_LIB_CT, CT_R_SCT_NOT_SET}, - #else - {"SCT_NOT_SET", 50, 106}, - #endif - #ifdef CT_R_SCT_UNSUPPORTED_VERSION - {"SCT_UNSUPPORTED_VERSION", ERR_LIB_CT, CT_R_SCT_UNSUPPORTED_VERSION}, - #else - {"SCT_UNSUPPORTED_VERSION", 50, 115}, - #endif - #ifdef CT_R_UNRECOGNIZED_SIGNATURE_NID - {"UNRECOGNIZED_SIGNATURE_NID", ERR_LIB_CT, CT_R_UNRECOGNIZED_SIGNATURE_NID}, - #else - {"UNRECOGNIZED_SIGNATURE_NID", 50, 101}, - #endif - #ifdef CT_R_UNSUPPORTED_ENTRY_TYPE - {"UNSUPPORTED_ENTRY_TYPE", ERR_LIB_CT, CT_R_UNSUPPORTED_ENTRY_TYPE}, - #else - {"UNSUPPORTED_ENTRY_TYPE", 50, 102}, - #endif - #ifdef CT_R_UNSUPPORTED_VERSION - {"UNSUPPORTED_VERSION", ERR_LIB_CT, CT_R_UNSUPPORTED_VERSION}, - #else - {"UNSUPPORTED_VERSION", 50, 103}, - #endif - #ifdef DH_R_BAD_GENERATOR - {"BAD_GENERATOR", ERR_LIB_DH, DH_R_BAD_GENERATOR}, - #else - {"BAD_GENERATOR", 5, 101}, - #endif - #ifdef DH_R_BN_DECODE_ERROR - {"BN_DECODE_ERROR", ERR_LIB_DH, DH_R_BN_DECODE_ERROR}, - #else - {"BN_DECODE_ERROR", 5, 109}, - #endif - #ifdef DH_R_BN_ERROR - {"BN_ERROR", ERR_LIB_DH, DH_R_BN_ERROR}, - #else - {"BN_ERROR", 5, 106}, - #endif - #ifdef DH_R_CHECK_INVALID_J_VALUE - {"CHECK_INVALID_J_VALUE", ERR_LIB_DH, DH_R_CHECK_INVALID_J_VALUE}, - #else - {"CHECK_INVALID_J_VALUE", 5, 115}, - #endif - #ifdef DH_R_CHECK_INVALID_Q_VALUE - {"CHECK_INVALID_Q_VALUE", ERR_LIB_DH, DH_R_CHECK_INVALID_Q_VALUE}, - #else - {"CHECK_INVALID_Q_VALUE", 5, 116}, - #endif - #ifdef DH_R_CHECK_PUBKEY_INVALID - {"CHECK_PUBKEY_INVALID", ERR_LIB_DH, DH_R_CHECK_PUBKEY_INVALID}, - #else - {"CHECK_PUBKEY_INVALID", 5, 122}, - #endif - #ifdef DH_R_CHECK_PUBKEY_TOO_LARGE - {"CHECK_PUBKEY_TOO_LARGE", ERR_LIB_DH, DH_R_CHECK_PUBKEY_TOO_LARGE}, - #else - {"CHECK_PUBKEY_TOO_LARGE", 5, 123}, - #endif - #ifdef DH_R_CHECK_PUBKEY_TOO_SMALL - {"CHECK_PUBKEY_TOO_SMALL", ERR_LIB_DH, DH_R_CHECK_PUBKEY_TOO_SMALL}, - #else - {"CHECK_PUBKEY_TOO_SMALL", 5, 124}, - #endif - #ifdef DH_R_CHECK_P_NOT_PRIME - {"CHECK_P_NOT_PRIME", ERR_LIB_DH, DH_R_CHECK_P_NOT_PRIME}, - #else - {"CHECK_P_NOT_PRIME", 5, 117}, - #endif - #ifdef DH_R_CHECK_P_NOT_SAFE_PRIME - {"CHECK_P_NOT_SAFE_PRIME", ERR_LIB_DH, DH_R_CHECK_P_NOT_SAFE_PRIME}, - #else - {"CHECK_P_NOT_SAFE_PRIME", 5, 118}, - #endif - #ifdef DH_R_CHECK_Q_NOT_PRIME - {"CHECK_Q_NOT_PRIME", ERR_LIB_DH, DH_R_CHECK_Q_NOT_PRIME}, - #else - {"CHECK_Q_NOT_PRIME", 5, 119}, - #endif - #ifdef DH_R_DECODE_ERROR - {"DECODE_ERROR", ERR_LIB_DH, DH_R_DECODE_ERROR}, - #else - {"DECODE_ERROR", 5, 104}, - #endif - #ifdef DH_R_INVALID_PARAMETER_NAME - {"INVALID_PARAMETER_NAME", ERR_LIB_DH, DH_R_INVALID_PARAMETER_NAME}, - #else - {"INVALID_PARAMETER_NAME", 5, 110}, - #endif - #ifdef DH_R_INVALID_PARAMETER_NID - {"INVALID_PARAMETER_NID", ERR_LIB_DH, DH_R_INVALID_PARAMETER_NID}, - #else - {"INVALID_PARAMETER_NID", 5, 114}, - #endif - #ifdef DH_R_INVALID_PUBKEY - {"INVALID_PUBKEY", ERR_LIB_DH, DH_R_INVALID_PUBKEY}, - #else - {"INVALID_PUBKEY", 5, 102}, - #endif - #ifdef DH_R_KDF_PARAMETER_ERROR - {"KDF_PARAMETER_ERROR", ERR_LIB_DH, DH_R_KDF_PARAMETER_ERROR}, - #else - {"KDF_PARAMETER_ERROR", 5, 112}, - #endif - #ifdef DH_R_KEYS_NOT_SET - {"KEYS_NOT_SET", ERR_LIB_DH, DH_R_KEYS_NOT_SET}, - #else - {"KEYS_NOT_SET", 5, 108}, - #endif - #ifdef DH_R_MISSING_PUBKEY - {"MISSING_PUBKEY", ERR_LIB_DH, DH_R_MISSING_PUBKEY}, - #else - {"MISSING_PUBKEY", 5, 125}, - #endif - #ifdef DH_R_MODULUS_TOO_LARGE - {"MODULUS_TOO_LARGE", ERR_LIB_DH, DH_R_MODULUS_TOO_LARGE}, - #else - {"MODULUS_TOO_LARGE", 5, 103}, - #endif - #ifdef DH_R_NOT_SUITABLE_GENERATOR - {"NOT_SUITABLE_GENERATOR", ERR_LIB_DH, DH_R_NOT_SUITABLE_GENERATOR}, - #else - {"NOT_SUITABLE_GENERATOR", 5, 120}, - #endif - #ifdef DH_R_NO_PARAMETERS_SET - {"NO_PARAMETERS_SET", ERR_LIB_DH, DH_R_NO_PARAMETERS_SET}, - #else - {"NO_PARAMETERS_SET", 5, 107}, - #endif - #ifdef DH_R_NO_PRIVATE_VALUE - {"NO_PRIVATE_VALUE", ERR_LIB_DH, DH_R_NO_PRIVATE_VALUE}, - #else - {"NO_PRIVATE_VALUE", 5, 100}, - #endif - #ifdef DH_R_PARAMETER_ENCODING_ERROR - {"PARAMETER_ENCODING_ERROR", ERR_LIB_DH, DH_R_PARAMETER_ENCODING_ERROR}, - #else - {"PARAMETER_ENCODING_ERROR", 5, 105}, - #endif - #ifdef DH_R_PEER_KEY_ERROR - {"PEER_KEY_ERROR", ERR_LIB_DH, DH_R_PEER_KEY_ERROR}, - #else - {"PEER_KEY_ERROR", 5, 111}, - #endif - #ifdef DH_R_SHARED_INFO_ERROR - {"SHARED_INFO_ERROR", ERR_LIB_DH, DH_R_SHARED_INFO_ERROR}, - #else - {"SHARED_INFO_ERROR", 5, 113}, - #endif - #ifdef DH_R_UNABLE_TO_CHECK_GENERATOR - {"UNABLE_TO_CHECK_GENERATOR", ERR_LIB_DH, DH_R_UNABLE_TO_CHECK_GENERATOR}, - #else - {"UNABLE_TO_CHECK_GENERATOR", 5, 121}, - #endif - #ifdef DSA_R_BAD_Q_VALUE - {"BAD_Q_VALUE", ERR_LIB_DSA, DSA_R_BAD_Q_VALUE}, - #else - {"BAD_Q_VALUE", 10, 102}, - #endif - #ifdef DSA_R_BN_DECODE_ERROR - {"BN_DECODE_ERROR", ERR_LIB_DSA, DSA_R_BN_DECODE_ERROR}, - #else - {"BN_DECODE_ERROR", 10, 108}, - #endif - #ifdef DSA_R_BN_ERROR - {"BN_ERROR", ERR_LIB_DSA, DSA_R_BN_ERROR}, - #else - {"BN_ERROR", 10, 109}, - #endif - #ifdef DSA_R_DECODE_ERROR - {"DECODE_ERROR", ERR_LIB_DSA, DSA_R_DECODE_ERROR}, - #else - {"DECODE_ERROR", 10, 104}, - #endif - #ifdef DSA_R_INVALID_DIGEST_TYPE - {"INVALID_DIGEST_TYPE", ERR_LIB_DSA, DSA_R_INVALID_DIGEST_TYPE}, - #else - {"INVALID_DIGEST_TYPE", 10, 106}, - #endif - #ifdef DSA_R_INVALID_PARAMETERS - {"INVALID_PARAMETERS", ERR_LIB_DSA, DSA_R_INVALID_PARAMETERS}, - #else - {"INVALID_PARAMETERS", 10, 112}, - #endif - #ifdef DSA_R_MISSING_PARAMETERS - {"MISSING_PARAMETERS", ERR_LIB_DSA, DSA_R_MISSING_PARAMETERS}, - #else - {"MISSING_PARAMETERS", 10, 101}, - #endif - #ifdef DSA_R_MISSING_PRIVATE_KEY - {"MISSING_PRIVATE_KEY", ERR_LIB_DSA, DSA_R_MISSING_PRIVATE_KEY}, - #else - {"MISSING_PRIVATE_KEY", 10, 111}, - #endif - #ifdef DSA_R_MODULUS_TOO_LARGE - {"MODULUS_TOO_LARGE", ERR_LIB_DSA, DSA_R_MODULUS_TOO_LARGE}, - #else - {"MODULUS_TOO_LARGE", 10, 103}, - #endif - #ifdef DSA_R_NO_PARAMETERS_SET - {"NO_PARAMETERS_SET", ERR_LIB_DSA, DSA_R_NO_PARAMETERS_SET}, - #else - {"NO_PARAMETERS_SET", 10, 107}, - #endif - #ifdef DSA_R_PARAMETER_ENCODING_ERROR - {"PARAMETER_ENCODING_ERROR", ERR_LIB_DSA, DSA_R_PARAMETER_ENCODING_ERROR}, - #else - {"PARAMETER_ENCODING_ERROR", 10, 105}, - #endif - #ifdef DSA_R_Q_NOT_PRIME - {"Q_NOT_PRIME", ERR_LIB_DSA, DSA_R_Q_NOT_PRIME}, - #else - {"Q_NOT_PRIME", 10, 113}, - #endif - #ifdef DSA_R_SEED_LEN_SMALL - {"SEED_LEN_SMALL", ERR_LIB_DSA, DSA_R_SEED_LEN_SMALL}, - #else - {"SEED_LEN_SMALL", 10, 110}, - #endif - #ifdef EC_R_ASN1_ERROR - {"ASN1_ERROR", ERR_LIB_EC, EC_R_ASN1_ERROR}, - #else - {"ASN1_ERROR", 16, 115}, - #endif - #ifdef EC_R_BAD_SIGNATURE - {"BAD_SIGNATURE", ERR_LIB_EC, EC_R_BAD_SIGNATURE}, - #else - {"BAD_SIGNATURE", 16, 156}, - #endif - #ifdef EC_R_BIGNUM_OUT_OF_RANGE - {"BIGNUM_OUT_OF_RANGE", ERR_LIB_EC, EC_R_BIGNUM_OUT_OF_RANGE}, - #else - {"BIGNUM_OUT_OF_RANGE", 16, 144}, - #endif - #ifdef EC_R_BUFFER_TOO_SMALL - {"BUFFER_TOO_SMALL", ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL}, - #else - {"BUFFER_TOO_SMALL", 16, 100}, - #endif - #ifdef EC_R_CANNOT_INVERT - {"CANNOT_INVERT", ERR_LIB_EC, EC_R_CANNOT_INVERT}, - #else - {"CANNOT_INVERT", 16, 165}, - #endif - #ifdef EC_R_COORDINATES_OUT_OF_RANGE - {"COORDINATES_OUT_OF_RANGE", ERR_LIB_EC, EC_R_COORDINATES_OUT_OF_RANGE}, - #else - {"COORDINATES_OUT_OF_RANGE", 16, 146}, - #endif - #ifdef EC_R_CURVE_DOES_NOT_SUPPORT_ECDH - {"CURVE_DOES_NOT_SUPPORT_ECDH", ERR_LIB_EC, EC_R_CURVE_DOES_NOT_SUPPORT_ECDH}, - #else - {"CURVE_DOES_NOT_SUPPORT_ECDH", 16, 160}, - #endif - #ifdef EC_R_CURVE_DOES_NOT_SUPPORT_SIGNING - {"CURVE_DOES_NOT_SUPPORT_SIGNING", ERR_LIB_EC, EC_R_CURVE_DOES_NOT_SUPPORT_SIGNING}, - #else - {"CURVE_DOES_NOT_SUPPORT_SIGNING", 16, 159}, - #endif - #ifdef EC_R_D2I_ECPKPARAMETERS_FAILURE - {"D2I_ECPKPARAMETERS_FAILURE", ERR_LIB_EC, EC_R_D2I_ECPKPARAMETERS_FAILURE}, - #else - {"D2I_ECPKPARAMETERS_FAILURE", 16, 117}, - #endif - #ifdef EC_R_DECODE_ERROR - {"DECODE_ERROR", ERR_LIB_EC, EC_R_DECODE_ERROR}, - #else - {"DECODE_ERROR", 16, 142}, - #endif - #ifdef EC_R_DISCRIMINANT_IS_ZERO - {"DISCRIMINANT_IS_ZERO", ERR_LIB_EC, EC_R_DISCRIMINANT_IS_ZERO}, - #else - {"DISCRIMINANT_IS_ZERO", 16, 118}, - #endif - #ifdef EC_R_EC_GROUP_NEW_BY_NAME_FAILURE - {"EC_GROUP_NEW_BY_NAME_FAILURE", ERR_LIB_EC, EC_R_EC_GROUP_NEW_BY_NAME_FAILURE}, - #else - {"EC_GROUP_NEW_BY_NAME_FAILURE", 16, 119}, - #endif - #ifdef EC_R_FIELD_TOO_LARGE - {"FIELD_TOO_LARGE", ERR_LIB_EC, EC_R_FIELD_TOO_LARGE}, - #else - {"FIELD_TOO_LARGE", 16, 143}, - #endif - #ifdef EC_R_GF2M_NOT_SUPPORTED - {"GF2M_NOT_SUPPORTED", ERR_LIB_EC, EC_R_GF2M_NOT_SUPPORTED}, - #else - {"GF2M_NOT_SUPPORTED", 16, 147}, - #endif - #ifdef EC_R_GROUP2PKPARAMETERS_FAILURE - {"GROUP2PKPARAMETERS_FAILURE", ERR_LIB_EC, EC_R_GROUP2PKPARAMETERS_FAILURE}, - #else - {"GROUP2PKPARAMETERS_FAILURE", 16, 120}, - #endif - #ifdef EC_R_I2D_ECPKPARAMETERS_FAILURE - {"I2D_ECPKPARAMETERS_FAILURE", ERR_LIB_EC, EC_R_I2D_ECPKPARAMETERS_FAILURE}, - #else - {"I2D_ECPKPARAMETERS_FAILURE", 16, 121}, - #endif - #ifdef EC_R_INCOMPATIBLE_OBJECTS - {"INCOMPATIBLE_OBJECTS", ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS}, - #else - {"INCOMPATIBLE_OBJECTS", 16, 101}, - #endif - #ifdef EC_R_INVALID_ARGUMENT - {"INVALID_ARGUMENT", ERR_LIB_EC, EC_R_INVALID_ARGUMENT}, - #else - {"INVALID_ARGUMENT", 16, 112}, - #endif - #ifdef EC_R_INVALID_COMPRESSED_POINT - {"INVALID_COMPRESSED_POINT", ERR_LIB_EC, EC_R_INVALID_COMPRESSED_POINT}, - #else - {"INVALID_COMPRESSED_POINT", 16, 110}, - #endif - #ifdef EC_R_INVALID_COMPRESSION_BIT - {"INVALID_COMPRESSION_BIT", ERR_LIB_EC, EC_R_INVALID_COMPRESSION_BIT}, - #else - {"INVALID_COMPRESSION_BIT", 16, 109}, - #endif - #ifdef EC_R_INVALID_CURVE - {"INVALID_CURVE", ERR_LIB_EC, EC_R_INVALID_CURVE}, - #else - {"INVALID_CURVE", 16, 141}, - #endif - #ifdef EC_R_INVALID_DIGEST - {"INVALID_DIGEST", ERR_LIB_EC, EC_R_INVALID_DIGEST}, - #else - {"INVALID_DIGEST", 16, 151}, - #endif - #ifdef EC_R_INVALID_DIGEST_TYPE - {"INVALID_DIGEST_TYPE", ERR_LIB_EC, EC_R_INVALID_DIGEST_TYPE}, - #else - {"INVALID_DIGEST_TYPE", 16, 138}, - #endif - #ifdef EC_R_INVALID_ENCODING - {"INVALID_ENCODING", ERR_LIB_EC, EC_R_INVALID_ENCODING}, - #else - {"INVALID_ENCODING", 16, 102}, - #endif - #ifdef EC_R_INVALID_FIELD - {"INVALID_FIELD", ERR_LIB_EC, EC_R_INVALID_FIELD}, - #else - {"INVALID_FIELD", 16, 103}, - #endif - #ifdef EC_R_INVALID_FORM - {"INVALID_FORM", ERR_LIB_EC, EC_R_INVALID_FORM}, - #else - {"INVALID_FORM", 16, 104}, - #endif - #ifdef EC_R_INVALID_GROUP_ORDER - {"INVALID_GROUP_ORDER", ERR_LIB_EC, EC_R_INVALID_GROUP_ORDER}, - #else - {"INVALID_GROUP_ORDER", 16, 122}, - #endif - #ifdef EC_R_INVALID_KEY - {"INVALID_KEY", ERR_LIB_EC, EC_R_INVALID_KEY}, - #else - {"INVALID_KEY", 16, 116}, - #endif - #ifdef EC_R_INVALID_OUTPUT_LENGTH - {"INVALID_OUTPUT_LENGTH", ERR_LIB_EC, EC_R_INVALID_OUTPUT_LENGTH}, - #else - {"INVALID_OUTPUT_LENGTH", 16, 161}, - #endif - #ifdef EC_R_INVALID_PEER_KEY - {"INVALID_PEER_KEY", ERR_LIB_EC, EC_R_INVALID_PEER_KEY}, - #else - {"INVALID_PEER_KEY", 16, 133}, - #endif - #ifdef EC_R_INVALID_PENTANOMIAL_BASIS - {"INVALID_PENTANOMIAL_BASIS", ERR_LIB_EC, EC_R_INVALID_PENTANOMIAL_BASIS}, - #else - {"INVALID_PENTANOMIAL_BASIS", 16, 132}, - #endif - #ifdef EC_R_INVALID_PRIVATE_KEY - {"INVALID_PRIVATE_KEY", ERR_LIB_EC, EC_R_INVALID_PRIVATE_KEY}, - #else - {"INVALID_PRIVATE_KEY", 16, 123}, - #endif - #ifdef EC_R_INVALID_TRINOMIAL_BASIS - {"INVALID_TRINOMIAL_BASIS", ERR_LIB_EC, EC_R_INVALID_TRINOMIAL_BASIS}, - #else - {"INVALID_TRINOMIAL_BASIS", 16, 137}, - #endif - #ifdef EC_R_KDF_PARAMETER_ERROR - {"KDF_PARAMETER_ERROR", ERR_LIB_EC, EC_R_KDF_PARAMETER_ERROR}, - #else - {"KDF_PARAMETER_ERROR", 16, 148}, - #endif - #ifdef EC_R_KEYS_NOT_SET - {"KEYS_NOT_SET", ERR_LIB_EC, EC_R_KEYS_NOT_SET}, - #else - {"KEYS_NOT_SET", 16, 140}, - #endif - #ifdef EC_R_LADDER_POST_FAILURE - {"LADDER_POST_FAILURE", ERR_LIB_EC, EC_R_LADDER_POST_FAILURE}, - #else - {"LADDER_POST_FAILURE", 16, 136}, - #endif - #ifdef EC_R_LADDER_PRE_FAILURE - {"LADDER_PRE_FAILURE", ERR_LIB_EC, EC_R_LADDER_PRE_FAILURE}, - #else - {"LADDER_PRE_FAILURE", 16, 153}, - #endif - #ifdef EC_R_LADDER_STEP_FAILURE - {"LADDER_STEP_FAILURE", ERR_LIB_EC, EC_R_LADDER_STEP_FAILURE}, - #else - {"LADDER_STEP_FAILURE", 16, 162}, - #endif - #ifdef EC_R_MISSING_PARAMETERS - {"MISSING_PARAMETERS", ERR_LIB_EC, EC_R_MISSING_PARAMETERS}, - #else - {"MISSING_PARAMETERS", 16, 124}, - #endif - #ifdef EC_R_MISSING_PRIVATE_KEY - {"MISSING_PRIVATE_KEY", ERR_LIB_EC, EC_R_MISSING_PRIVATE_KEY}, - #else - {"MISSING_PRIVATE_KEY", 16, 125}, - #endif - #ifdef EC_R_NEED_NEW_SETUP_VALUES - {"NEED_NEW_SETUP_VALUES", ERR_LIB_EC, EC_R_NEED_NEW_SETUP_VALUES}, - #else - {"NEED_NEW_SETUP_VALUES", 16, 157}, - #endif - #ifdef EC_R_NOT_A_NIST_PRIME - {"NOT_A_NIST_PRIME", ERR_LIB_EC, EC_R_NOT_A_NIST_PRIME}, - #else - {"NOT_A_NIST_PRIME", 16, 135}, - #endif - #ifdef EC_R_NOT_IMPLEMENTED - {"NOT_IMPLEMENTED", ERR_LIB_EC, EC_R_NOT_IMPLEMENTED}, - #else - {"NOT_IMPLEMENTED", 16, 126}, - #endif - #ifdef EC_R_NOT_INITIALIZED - {"NOT_INITIALIZED", ERR_LIB_EC, EC_R_NOT_INITIALIZED}, - #else - {"NOT_INITIALIZED", 16, 111}, - #endif - #ifdef EC_R_NO_PARAMETERS_SET - {"NO_PARAMETERS_SET", ERR_LIB_EC, EC_R_NO_PARAMETERS_SET}, - #else - {"NO_PARAMETERS_SET", 16, 139}, - #endif - #ifdef EC_R_NO_PRIVATE_VALUE - {"NO_PRIVATE_VALUE", ERR_LIB_EC, EC_R_NO_PRIVATE_VALUE}, - #else - {"NO_PRIVATE_VALUE", 16, 154}, - #endif - #ifdef EC_R_OPERATION_NOT_SUPPORTED - {"OPERATION_NOT_SUPPORTED", ERR_LIB_EC, EC_R_OPERATION_NOT_SUPPORTED}, - #else - {"OPERATION_NOT_SUPPORTED", 16, 152}, - #endif - #ifdef EC_R_PASSED_NULL_PARAMETER - {"PASSED_NULL_PARAMETER", ERR_LIB_EC, EC_R_PASSED_NULL_PARAMETER}, - #else - {"PASSED_NULL_PARAMETER", 16, 134}, - #endif - #ifdef EC_R_PEER_KEY_ERROR - {"PEER_KEY_ERROR", ERR_LIB_EC, EC_R_PEER_KEY_ERROR}, - #else - {"PEER_KEY_ERROR", 16, 149}, - #endif - #ifdef EC_R_PKPARAMETERS2GROUP_FAILURE - {"PKPARAMETERS2GROUP_FAILURE", ERR_LIB_EC, EC_R_PKPARAMETERS2GROUP_FAILURE}, - #else - {"PKPARAMETERS2GROUP_FAILURE", 16, 127}, - #endif - #ifdef EC_R_POINT_ARITHMETIC_FAILURE - {"POINT_ARITHMETIC_FAILURE", ERR_LIB_EC, EC_R_POINT_ARITHMETIC_FAILURE}, - #else - {"POINT_ARITHMETIC_FAILURE", 16, 155}, - #endif - #ifdef EC_R_POINT_AT_INFINITY - {"POINT_AT_INFINITY", ERR_LIB_EC, EC_R_POINT_AT_INFINITY}, - #else - {"POINT_AT_INFINITY", 16, 106}, - #endif - #ifdef EC_R_POINT_COORDINATES_BLIND_FAILURE - {"POINT_COORDINATES_BLIND_FAILURE", ERR_LIB_EC, EC_R_POINT_COORDINATES_BLIND_FAILURE}, - #else - {"POINT_COORDINATES_BLIND_FAILURE", 16, 163}, - #endif - #ifdef EC_R_POINT_IS_NOT_ON_CURVE - {"POINT_IS_NOT_ON_CURVE", ERR_LIB_EC, EC_R_POINT_IS_NOT_ON_CURVE}, - #else - {"POINT_IS_NOT_ON_CURVE", 16, 107}, - #endif - #ifdef EC_R_RANDOM_NUMBER_GENERATION_FAILED - {"RANDOM_NUMBER_GENERATION_FAILED", ERR_LIB_EC, EC_R_RANDOM_NUMBER_GENERATION_FAILED}, - #else - {"RANDOM_NUMBER_GENERATION_FAILED", 16, 158}, - #endif - #ifdef EC_R_SHARED_INFO_ERROR - {"SHARED_INFO_ERROR", ERR_LIB_EC, EC_R_SHARED_INFO_ERROR}, - #else - {"SHARED_INFO_ERROR", 16, 150}, - #endif - #ifdef EC_R_SLOT_FULL - {"SLOT_FULL", ERR_LIB_EC, EC_R_SLOT_FULL}, - #else - {"SLOT_FULL", 16, 108}, - #endif - #ifdef EC_R_UNDEFINED_GENERATOR - {"UNDEFINED_GENERATOR", ERR_LIB_EC, EC_R_UNDEFINED_GENERATOR}, - #else - {"UNDEFINED_GENERATOR", 16, 113}, - #endif - #ifdef EC_R_UNDEFINED_ORDER - {"UNDEFINED_ORDER", ERR_LIB_EC, EC_R_UNDEFINED_ORDER}, - #else - {"UNDEFINED_ORDER", 16, 128}, - #endif - #ifdef EC_R_UNKNOWN_COFACTOR - {"UNKNOWN_COFACTOR", ERR_LIB_EC, EC_R_UNKNOWN_COFACTOR}, - #else - {"UNKNOWN_COFACTOR", 16, 164}, - #endif - #ifdef EC_R_UNKNOWN_GROUP - {"UNKNOWN_GROUP", ERR_LIB_EC, EC_R_UNKNOWN_GROUP}, - #else - {"UNKNOWN_GROUP", 16, 129}, - #endif - #ifdef EC_R_UNKNOWN_ORDER - {"UNKNOWN_ORDER", ERR_LIB_EC, EC_R_UNKNOWN_ORDER}, - #else - {"UNKNOWN_ORDER", 16, 114}, - #endif - #ifdef EC_R_UNSUPPORTED_FIELD - {"UNSUPPORTED_FIELD", ERR_LIB_EC, EC_R_UNSUPPORTED_FIELD}, - #else - {"UNSUPPORTED_FIELD", 16, 131}, - #endif - #ifdef EC_R_WRONG_CURVE_PARAMETERS - {"WRONG_CURVE_PARAMETERS", ERR_LIB_EC, EC_R_WRONG_CURVE_PARAMETERS}, - #else - {"WRONG_CURVE_PARAMETERS", 16, 145}, - #endif - #ifdef EC_R_WRONG_ORDER - {"WRONG_ORDER", ERR_LIB_EC, EC_R_WRONG_ORDER}, - #else - {"WRONG_ORDER", 16, 130}, - #endif - #ifdef ENGINE_R_ALREADY_LOADED - {"ALREADY_LOADED", ERR_LIB_ENGINE, ENGINE_R_ALREADY_LOADED}, - #else - {"ALREADY_LOADED", 38, 100}, - #endif - #ifdef ENGINE_R_ARGUMENT_IS_NOT_A_NUMBER - {"ARGUMENT_IS_NOT_A_NUMBER", ERR_LIB_ENGINE, ENGINE_R_ARGUMENT_IS_NOT_A_NUMBER}, - #else - {"ARGUMENT_IS_NOT_A_NUMBER", 38, 133}, - #endif - #ifdef ENGINE_R_CMD_NOT_EXECUTABLE - {"CMD_NOT_EXECUTABLE", ERR_LIB_ENGINE, ENGINE_R_CMD_NOT_EXECUTABLE}, - #else - {"CMD_NOT_EXECUTABLE", 38, 134}, - #endif - #ifdef ENGINE_R_COMMAND_TAKES_INPUT - {"COMMAND_TAKES_INPUT", ERR_LIB_ENGINE, ENGINE_R_COMMAND_TAKES_INPUT}, - #else - {"COMMAND_TAKES_INPUT", 38, 135}, - #endif - #ifdef ENGINE_R_COMMAND_TAKES_NO_INPUT - {"COMMAND_TAKES_NO_INPUT", ERR_LIB_ENGINE, ENGINE_R_COMMAND_TAKES_NO_INPUT}, - #else - {"COMMAND_TAKES_NO_INPUT", 38, 136}, - #endif - #ifdef ENGINE_R_CONFLICTING_ENGINE_ID - {"CONFLICTING_ENGINE_ID", ERR_LIB_ENGINE, ENGINE_R_CONFLICTING_ENGINE_ID}, - #else - {"CONFLICTING_ENGINE_ID", 38, 103}, - #endif - #ifdef ENGINE_R_CTRL_COMMAND_NOT_IMPLEMENTED - {"CTRL_COMMAND_NOT_IMPLEMENTED", ERR_LIB_ENGINE, ENGINE_R_CTRL_COMMAND_NOT_IMPLEMENTED}, - #else - {"CTRL_COMMAND_NOT_IMPLEMENTED", 38, 119}, - #endif - #ifdef ENGINE_R_DSO_FAILURE - {"DSO_FAILURE", ERR_LIB_ENGINE, ENGINE_R_DSO_FAILURE}, - #else - {"DSO_FAILURE", 38, 104}, - #endif - #ifdef ENGINE_R_DSO_NOT_FOUND - {"DSO_NOT_FOUND", ERR_LIB_ENGINE, ENGINE_R_DSO_NOT_FOUND}, - #else - {"DSO_NOT_FOUND", 38, 132}, - #endif - #ifdef ENGINE_R_ENGINES_SECTION_ERROR - {"ENGINES_SECTION_ERROR", ERR_LIB_ENGINE, ENGINE_R_ENGINES_SECTION_ERROR}, - #else - {"ENGINES_SECTION_ERROR", 38, 148}, - #endif - #ifdef ENGINE_R_ENGINE_CONFIGURATION_ERROR - {"ENGINE_CONFIGURATION_ERROR", ERR_LIB_ENGINE, ENGINE_R_ENGINE_CONFIGURATION_ERROR}, - #else - {"ENGINE_CONFIGURATION_ERROR", 38, 102}, - #endif - #ifdef ENGINE_R_ENGINE_IS_NOT_IN_LIST - {"ENGINE_IS_NOT_IN_LIST", ERR_LIB_ENGINE, ENGINE_R_ENGINE_IS_NOT_IN_LIST}, - #else - {"ENGINE_IS_NOT_IN_LIST", 38, 105}, - #endif - #ifdef ENGINE_R_ENGINE_SECTION_ERROR - {"ENGINE_SECTION_ERROR", ERR_LIB_ENGINE, ENGINE_R_ENGINE_SECTION_ERROR}, - #else - {"ENGINE_SECTION_ERROR", 38, 149}, - #endif - #ifdef ENGINE_R_FAILED_LOADING_PRIVATE_KEY - {"FAILED_LOADING_PRIVATE_KEY", ERR_LIB_ENGINE, ENGINE_R_FAILED_LOADING_PRIVATE_KEY}, - #else - {"FAILED_LOADING_PRIVATE_KEY", 38, 128}, - #endif - #ifdef ENGINE_R_FAILED_LOADING_PUBLIC_KEY - {"FAILED_LOADING_PUBLIC_KEY", ERR_LIB_ENGINE, ENGINE_R_FAILED_LOADING_PUBLIC_KEY}, - #else - {"FAILED_LOADING_PUBLIC_KEY", 38, 129}, - #endif - #ifdef ENGINE_R_FINISH_FAILED - {"FINISH_FAILED", ERR_LIB_ENGINE, ENGINE_R_FINISH_FAILED}, - #else - {"FINISH_FAILED", 38, 106}, - #endif - #ifdef ENGINE_R_ID_OR_NAME_MISSING - {"ID_OR_NAME_MISSING", ERR_LIB_ENGINE, ENGINE_R_ID_OR_NAME_MISSING}, - #else - {"ID_OR_NAME_MISSING", 38, 108}, - #endif - #ifdef ENGINE_R_INIT_FAILED - {"INIT_FAILED", ERR_LIB_ENGINE, ENGINE_R_INIT_FAILED}, - #else - {"INIT_FAILED", 38, 109}, - #endif - #ifdef ENGINE_R_INTERNAL_LIST_ERROR - {"INTERNAL_LIST_ERROR", ERR_LIB_ENGINE, ENGINE_R_INTERNAL_LIST_ERROR}, - #else - {"INTERNAL_LIST_ERROR", 38, 110}, - #endif - #ifdef ENGINE_R_INVALID_ARGUMENT - {"INVALID_ARGUMENT", ERR_LIB_ENGINE, ENGINE_R_INVALID_ARGUMENT}, - #else - {"INVALID_ARGUMENT", 38, 143}, - #endif - #ifdef ENGINE_R_INVALID_CMD_NAME - {"INVALID_CMD_NAME", ERR_LIB_ENGINE, ENGINE_R_INVALID_CMD_NAME}, - #else - {"INVALID_CMD_NAME", 38, 137}, - #endif - #ifdef ENGINE_R_INVALID_CMD_NUMBER - {"INVALID_CMD_NUMBER", ERR_LIB_ENGINE, ENGINE_R_INVALID_CMD_NUMBER}, - #else - {"INVALID_CMD_NUMBER", 38, 138}, - #endif - #ifdef ENGINE_R_INVALID_INIT_VALUE - {"INVALID_INIT_VALUE", ERR_LIB_ENGINE, ENGINE_R_INVALID_INIT_VALUE}, - #else - {"INVALID_INIT_VALUE", 38, 151}, - #endif - #ifdef ENGINE_R_INVALID_STRING - {"INVALID_STRING", ERR_LIB_ENGINE, ENGINE_R_INVALID_STRING}, - #else - {"INVALID_STRING", 38, 150}, - #endif - #ifdef ENGINE_R_NOT_INITIALISED - {"NOT_INITIALISED", ERR_LIB_ENGINE, ENGINE_R_NOT_INITIALISED}, - #else - {"NOT_INITIALISED", 38, 117}, - #endif - #ifdef ENGINE_R_NOT_LOADED - {"NOT_LOADED", ERR_LIB_ENGINE, ENGINE_R_NOT_LOADED}, - #else - {"NOT_LOADED", 38, 112}, - #endif - #ifdef ENGINE_R_NO_CONTROL_FUNCTION - {"NO_CONTROL_FUNCTION", ERR_LIB_ENGINE, ENGINE_R_NO_CONTROL_FUNCTION}, - #else - {"NO_CONTROL_FUNCTION", 38, 120}, - #endif - #ifdef ENGINE_R_NO_INDEX - {"NO_INDEX", ERR_LIB_ENGINE, ENGINE_R_NO_INDEX}, - #else - {"NO_INDEX", 38, 144}, - #endif - #ifdef ENGINE_R_NO_LOAD_FUNCTION - {"NO_LOAD_FUNCTION", ERR_LIB_ENGINE, ENGINE_R_NO_LOAD_FUNCTION}, - #else - {"NO_LOAD_FUNCTION", 38, 125}, - #endif - #ifdef ENGINE_R_NO_REFERENCE - {"NO_REFERENCE", ERR_LIB_ENGINE, ENGINE_R_NO_REFERENCE}, - #else - {"NO_REFERENCE", 38, 130}, - #endif - #ifdef ENGINE_R_NO_SUCH_ENGINE - {"NO_SUCH_ENGINE", ERR_LIB_ENGINE, ENGINE_R_NO_SUCH_ENGINE}, - #else - {"NO_SUCH_ENGINE", 38, 116}, - #endif - #ifdef ENGINE_R_UNIMPLEMENTED_CIPHER - {"UNIMPLEMENTED_CIPHER", ERR_LIB_ENGINE, ENGINE_R_UNIMPLEMENTED_CIPHER}, - #else - {"UNIMPLEMENTED_CIPHER", 38, 146}, - #endif - #ifdef ENGINE_R_UNIMPLEMENTED_DIGEST - {"UNIMPLEMENTED_DIGEST", ERR_LIB_ENGINE, ENGINE_R_UNIMPLEMENTED_DIGEST}, - #else - {"UNIMPLEMENTED_DIGEST", 38, 147}, - #endif - #ifdef ENGINE_R_UNIMPLEMENTED_PUBLIC_KEY_METHOD - {"UNIMPLEMENTED_PUBLIC_KEY_METHOD", ERR_LIB_ENGINE, ENGINE_R_UNIMPLEMENTED_PUBLIC_KEY_METHOD}, - #else - {"UNIMPLEMENTED_PUBLIC_KEY_METHOD", 38, 101}, - #endif - #ifdef ENGINE_R_VERSION_INCOMPATIBILITY - {"VERSION_INCOMPATIBILITY", ERR_LIB_ENGINE, ENGINE_R_VERSION_INCOMPATIBILITY}, - #else - {"VERSION_INCOMPATIBILITY", 38, 145}, - #endif - #ifdef EVP_R_AES_KEY_SETUP_FAILED - {"AES_KEY_SETUP_FAILED", ERR_LIB_EVP, EVP_R_AES_KEY_SETUP_FAILED}, - #else - {"AES_KEY_SETUP_FAILED", 6, 143}, - #endif - #ifdef EVP_R_ARIA_KEY_SETUP_FAILED - {"ARIA_KEY_SETUP_FAILED", ERR_LIB_EVP, EVP_R_ARIA_KEY_SETUP_FAILED}, - #else - {"ARIA_KEY_SETUP_FAILED", 6, 176}, - #endif - #ifdef EVP_R_BAD_DECRYPT - {"BAD_DECRYPT", ERR_LIB_EVP, EVP_R_BAD_DECRYPT}, - #else - {"BAD_DECRYPT", 6, 100}, - #endif - #ifdef EVP_R_BAD_KEY_LENGTH - {"BAD_KEY_LENGTH", ERR_LIB_EVP, EVP_R_BAD_KEY_LENGTH}, - #else - {"BAD_KEY_LENGTH", 6, 195}, - #endif - #ifdef EVP_R_BUFFER_TOO_SMALL - {"BUFFER_TOO_SMALL", ERR_LIB_EVP, EVP_R_BUFFER_TOO_SMALL}, - #else - {"BUFFER_TOO_SMALL", 6, 155}, - #endif - #ifdef EVP_R_CAMELLIA_KEY_SETUP_FAILED - {"CAMELLIA_KEY_SETUP_FAILED", ERR_LIB_EVP, EVP_R_CAMELLIA_KEY_SETUP_FAILED}, - #else - {"CAMELLIA_KEY_SETUP_FAILED", 6, 157}, - #endif - #ifdef EVP_R_CIPHER_PARAMETER_ERROR - {"CIPHER_PARAMETER_ERROR", ERR_LIB_EVP, EVP_R_CIPHER_PARAMETER_ERROR}, - #else - {"CIPHER_PARAMETER_ERROR", 6, 122}, - #endif - #ifdef EVP_R_COMMAND_NOT_SUPPORTED - {"COMMAND_NOT_SUPPORTED", ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED}, - #else - {"COMMAND_NOT_SUPPORTED", 6, 147}, - #endif - #ifdef EVP_R_COPY_ERROR - {"COPY_ERROR", ERR_LIB_EVP, EVP_R_COPY_ERROR}, - #else - {"COPY_ERROR", 6, 173}, - #endif - #ifdef EVP_R_CTRL_NOT_IMPLEMENTED - {"CTRL_NOT_IMPLEMENTED", ERR_LIB_EVP, EVP_R_CTRL_NOT_IMPLEMENTED}, - #else - {"CTRL_NOT_IMPLEMENTED", 6, 132}, - #endif - #ifdef EVP_R_CTRL_OPERATION_NOT_IMPLEMENTED - {"CTRL_OPERATION_NOT_IMPLEMENTED", ERR_LIB_EVP, EVP_R_CTRL_OPERATION_NOT_IMPLEMENTED}, - #else - {"CTRL_OPERATION_NOT_IMPLEMENTED", 6, 133}, - #endif - #ifdef EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH - {"DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH", ERR_LIB_EVP, EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH}, - #else - {"DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH", 6, 138}, - #endif - #ifdef EVP_R_DECODE_ERROR - {"DECODE_ERROR", ERR_LIB_EVP, EVP_R_DECODE_ERROR}, - #else - {"DECODE_ERROR", 6, 114}, - #endif - #ifdef EVP_R_DIFFERENT_KEY_TYPES - {"DIFFERENT_KEY_TYPES", ERR_LIB_EVP, EVP_R_DIFFERENT_KEY_TYPES}, - #else - {"DIFFERENT_KEY_TYPES", 6, 101}, - #endif - #ifdef EVP_R_DIFFERENT_PARAMETERS - {"DIFFERENT_PARAMETERS", ERR_LIB_EVP, EVP_R_DIFFERENT_PARAMETERS}, - #else - {"DIFFERENT_PARAMETERS", 6, 153}, - #endif - #ifdef EVP_R_ERROR_LOADING_SECTION - {"ERROR_LOADING_SECTION", ERR_LIB_EVP, EVP_R_ERROR_LOADING_SECTION}, - #else - {"ERROR_LOADING_SECTION", 6, 165}, - #endif - #ifdef EVP_R_ERROR_SETTING_FIPS_MODE - {"ERROR_SETTING_FIPS_MODE", ERR_LIB_EVP, EVP_R_ERROR_SETTING_FIPS_MODE}, - #else - {"ERROR_SETTING_FIPS_MODE", 6, 166}, - #endif - #ifdef EVP_R_EXPECTING_AN_HMAC_KEY - {"EXPECTING_AN_HMAC_KEY", ERR_LIB_EVP, EVP_R_EXPECTING_AN_HMAC_KEY}, - #else - {"EXPECTING_AN_HMAC_KEY", 6, 174}, - #endif - #ifdef EVP_R_EXPECTING_AN_RSA_KEY - {"EXPECTING_AN_RSA_KEY", ERR_LIB_EVP, EVP_R_EXPECTING_AN_RSA_KEY}, - #else - {"EXPECTING_AN_RSA_KEY", 6, 127}, - #endif - #ifdef EVP_R_EXPECTING_A_DH_KEY - {"EXPECTING_A_DH_KEY", ERR_LIB_EVP, EVP_R_EXPECTING_A_DH_KEY}, - #else - {"EXPECTING_A_DH_KEY", 6, 128}, - #endif - #ifdef EVP_R_EXPECTING_A_DSA_KEY - {"EXPECTING_A_DSA_KEY", ERR_LIB_EVP, EVP_R_EXPECTING_A_DSA_KEY}, - #else - {"EXPECTING_A_DSA_KEY", 6, 129}, - #endif - #ifdef EVP_R_EXPECTING_A_EC_KEY - {"EXPECTING_A_EC_KEY", ERR_LIB_EVP, EVP_R_EXPECTING_A_EC_KEY}, - #else - {"EXPECTING_A_EC_KEY", 6, 142}, - #endif - #ifdef EVP_R_EXPECTING_A_POLY1305_KEY - {"EXPECTING_A_POLY1305_KEY", ERR_LIB_EVP, EVP_R_EXPECTING_A_POLY1305_KEY}, - #else - {"EXPECTING_A_POLY1305_KEY", 6, 164}, - #endif - #ifdef EVP_R_EXPECTING_A_SIPHASH_KEY - {"EXPECTING_A_SIPHASH_KEY", ERR_LIB_EVP, EVP_R_EXPECTING_A_SIPHASH_KEY}, - #else - {"EXPECTING_A_SIPHASH_KEY", 6, 175}, - #endif - #ifdef EVP_R_FIPS_MODE_NOT_SUPPORTED - {"FIPS_MODE_NOT_SUPPORTED", ERR_LIB_EVP, EVP_R_FIPS_MODE_NOT_SUPPORTED}, - #else - {"FIPS_MODE_NOT_SUPPORTED", 6, 167}, - #endif - #ifdef EVP_R_GET_RAW_KEY_FAILED - {"GET_RAW_KEY_FAILED", ERR_LIB_EVP, EVP_R_GET_RAW_KEY_FAILED}, - #else - {"GET_RAW_KEY_FAILED", 6, 182}, - #endif - #ifdef EVP_R_ILLEGAL_SCRYPT_PARAMETERS - {"ILLEGAL_SCRYPT_PARAMETERS", ERR_LIB_EVP, EVP_R_ILLEGAL_SCRYPT_PARAMETERS}, - #else - {"ILLEGAL_SCRYPT_PARAMETERS", 6, 171}, - #endif - #ifdef EVP_R_INITIALIZATION_ERROR - {"INITIALIZATION_ERROR", ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR}, - #else - {"INITIALIZATION_ERROR", 6, 134}, - #endif - #ifdef EVP_R_INPUT_NOT_INITIALIZED - {"INPUT_NOT_INITIALIZED", ERR_LIB_EVP, EVP_R_INPUT_NOT_INITIALIZED}, - #else - {"INPUT_NOT_INITIALIZED", 6, 111}, - #endif - #ifdef EVP_R_INVALID_DIGEST - {"INVALID_DIGEST", ERR_LIB_EVP, EVP_R_INVALID_DIGEST}, - #else - {"INVALID_DIGEST", 6, 152}, - #endif - #ifdef EVP_R_INVALID_FIPS_MODE - {"INVALID_FIPS_MODE", ERR_LIB_EVP, EVP_R_INVALID_FIPS_MODE}, - #else - {"INVALID_FIPS_MODE", 6, 168}, - #endif - #ifdef EVP_R_INVALID_IV_LENGTH - {"INVALID_IV_LENGTH", ERR_LIB_EVP, EVP_R_INVALID_IV_LENGTH}, - #else - {"INVALID_IV_LENGTH", 6, 194}, - #endif - #ifdef EVP_R_INVALID_KEY - {"INVALID_KEY", ERR_LIB_EVP, EVP_R_INVALID_KEY}, - #else - {"INVALID_KEY", 6, 163}, - #endif - #ifdef EVP_R_INVALID_KEY_LENGTH - {"INVALID_KEY_LENGTH", ERR_LIB_EVP, EVP_R_INVALID_KEY_LENGTH}, - #else - {"INVALID_KEY_LENGTH", 6, 130}, - #endif - #ifdef EVP_R_INVALID_OPERATION - {"INVALID_OPERATION", ERR_LIB_EVP, EVP_R_INVALID_OPERATION}, - #else - {"INVALID_OPERATION", 6, 148}, - #endif - #ifdef EVP_R_KEYGEN_FAILURE - {"KEYGEN_FAILURE", ERR_LIB_EVP, EVP_R_KEYGEN_FAILURE}, - #else - {"KEYGEN_FAILURE", 6, 120}, - #endif - #ifdef EVP_R_KEY_SETUP_FAILED - {"KEY_SETUP_FAILED", ERR_LIB_EVP, EVP_R_KEY_SETUP_FAILED}, - #else - {"KEY_SETUP_FAILED", 6, 180}, - #endif - #ifdef EVP_R_MEMORY_LIMIT_EXCEEDED - {"MEMORY_LIMIT_EXCEEDED", ERR_LIB_EVP, EVP_R_MEMORY_LIMIT_EXCEEDED}, - #else - {"MEMORY_LIMIT_EXCEEDED", 6, 172}, - #endif - #ifdef EVP_R_MESSAGE_DIGEST_IS_NULL - {"MESSAGE_DIGEST_IS_NULL", ERR_LIB_EVP, EVP_R_MESSAGE_DIGEST_IS_NULL}, - #else - {"MESSAGE_DIGEST_IS_NULL", 6, 159}, - #endif - #ifdef EVP_R_METHOD_NOT_SUPPORTED - {"METHOD_NOT_SUPPORTED", ERR_LIB_EVP, EVP_R_METHOD_NOT_SUPPORTED}, - #else - {"METHOD_NOT_SUPPORTED", 6, 144}, - #endif - #ifdef EVP_R_MISSING_PARAMETERS - {"MISSING_PARAMETERS", ERR_LIB_EVP, EVP_R_MISSING_PARAMETERS}, - #else - {"MISSING_PARAMETERS", 6, 103}, - #endif - #ifdef EVP_R_NOT_XOF_OR_INVALID_LENGTH - {"NOT_XOF_OR_INVALID_LENGTH", ERR_LIB_EVP, EVP_R_NOT_XOF_OR_INVALID_LENGTH}, - #else - {"NOT_XOF_OR_INVALID_LENGTH", 6, 178}, - #endif - #ifdef EVP_R_NO_CIPHER_SET - {"NO_CIPHER_SET", ERR_LIB_EVP, EVP_R_NO_CIPHER_SET}, - #else - {"NO_CIPHER_SET", 6, 131}, - #endif - #ifdef EVP_R_NO_DEFAULT_DIGEST - {"NO_DEFAULT_DIGEST", ERR_LIB_EVP, EVP_R_NO_DEFAULT_DIGEST}, - #else - {"NO_DEFAULT_DIGEST", 6, 158}, - #endif - #ifdef EVP_R_NO_DIGEST_SET - {"NO_DIGEST_SET", ERR_LIB_EVP, EVP_R_NO_DIGEST_SET}, - #else - {"NO_DIGEST_SET", 6, 139}, - #endif - #ifdef EVP_R_NO_KEY_SET - {"NO_KEY_SET", ERR_LIB_EVP, EVP_R_NO_KEY_SET}, - #else - {"NO_KEY_SET", 6, 154}, - #endif - #ifdef EVP_R_NO_OPERATION_SET - {"NO_OPERATION_SET", ERR_LIB_EVP, EVP_R_NO_OPERATION_SET}, - #else - {"NO_OPERATION_SET", 6, 149}, - #endif - #ifdef EVP_R_ONLY_ONESHOT_SUPPORTED - {"ONLY_ONESHOT_SUPPORTED", ERR_LIB_EVP, EVP_R_ONLY_ONESHOT_SUPPORTED}, - #else - {"ONLY_ONESHOT_SUPPORTED", 6, 177}, - #endif - #ifdef EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE - {"OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE", ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE}, - #else - {"OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE", 6, 150}, - #endif - #ifdef EVP_R_OPERATON_NOT_INITIALIZED - {"OPERATON_NOT_INITIALIZED", ERR_LIB_EVP, EVP_R_OPERATON_NOT_INITIALIZED}, - #else - {"OPERATON_NOT_INITIALIZED", 6, 151}, - #endif - #ifdef EVP_R_PARTIALLY_OVERLAPPING - {"PARTIALLY_OVERLAPPING", ERR_LIB_EVP, EVP_R_PARTIALLY_OVERLAPPING}, - #else - {"PARTIALLY_OVERLAPPING", 6, 162}, - #endif - #ifdef EVP_R_PBKDF2_ERROR - {"PBKDF2_ERROR", ERR_LIB_EVP, EVP_R_PBKDF2_ERROR}, - #else - {"PBKDF2_ERROR", 6, 181}, - #endif - #ifdef EVP_R_PKEY_APPLICATION_ASN1_METHOD_ALREADY_REGISTERED - {"PKEY_APPLICATION_ASN1_METHOD_ALREADY_REGISTERED", ERR_LIB_EVP, EVP_R_PKEY_APPLICATION_ASN1_METHOD_ALREADY_REGISTERED}, - #else - {"PKEY_APPLICATION_ASN1_METHOD_ALREADY_REGISTERED", 6, 179}, - #endif - #ifdef EVP_R_PRIVATE_KEY_DECODE_ERROR - {"PRIVATE_KEY_DECODE_ERROR", ERR_LIB_EVP, EVP_R_PRIVATE_KEY_DECODE_ERROR}, - #else - {"PRIVATE_KEY_DECODE_ERROR", 6, 145}, - #endif - #ifdef EVP_R_PRIVATE_KEY_ENCODE_ERROR - {"PRIVATE_KEY_ENCODE_ERROR", ERR_LIB_EVP, EVP_R_PRIVATE_KEY_ENCODE_ERROR}, - #else - {"PRIVATE_KEY_ENCODE_ERROR", 6, 146}, - #endif - #ifdef EVP_R_PUBLIC_KEY_NOT_RSA - {"PUBLIC_KEY_NOT_RSA", ERR_LIB_EVP, EVP_R_PUBLIC_KEY_NOT_RSA}, - #else - {"PUBLIC_KEY_NOT_RSA", 6, 106}, - #endif - #ifdef EVP_R_UNKNOWN_CIPHER - {"UNKNOWN_CIPHER", ERR_LIB_EVP, EVP_R_UNKNOWN_CIPHER}, - #else - {"UNKNOWN_CIPHER", 6, 160}, - #endif - #ifdef EVP_R_UNKNOWN_DIGEST - {"UNKNOWN_DIGEST", ERR_LIB_EVP, EVP_R_UNKNOWN_DIGEST}, - #else - {"UNKNOWN_DIGEST", 6, 161}, - #endif - #ifdef EVP_R_UNKNOWN_OPTION - {"UNKNOWN_OPTION", ERR_LIB_EVP, EVP_R_UNKNOWN_OPTION}, - #else - {"UNKNOWN_OPTION", 6, 169}, - #endif - #ifdef EVP_R_UNKNOWN_PBE_ALGORITHM - {"UNKNOWN_PBE_ALGORITHM", ERR_LIB_EVP, EVP_R_UNKNOWN_PBE_ALGORITHM}, - #else - {"UNKNOWN_PBE_ALGORITHM", 6, 121}, - #endif - #ifdef EVP_R_UNSUPPORTED_ALGORITHM - {"UNSUPPORTED_ALGORITHM", ERR_LIB_EVP, EVP_R_UNSUPPORTED_ALGORITHM}, - #else - {"UNSUPPORTED_ALGORITHM", 6, 156}, - #endif - #ifdef EVP_R_UNSUPPORTED_CIPHER - {"UNSUPPORTED_CIPHER", ERR_LIB_EVP, EVP_R_UNSUPPORTED_CIPHER}, - #else - {"UNSUPPORTED_CIPHER", 6, 107}, - #endif - #ifdef EVP_R_UNSUPPORTED_KEYLENGTH - {"UNSUPPORTED_KEYLENGTH", ERR_LIB_EVP, EVP_R_UNSUPPORTED_KEYLENGTH}, - #else - {"UNSUPPORTED_KEYLENGTH", 6, 123}, - #endif - #ifdef EVP_R_UNSUPPORTED_KEY_DERIVATION_FUNCTION - {"UNSUPPORTED_KEY_DERIVATION_FUNCTION", ERR_LIB_EVP, EVP_R_UNSUPPORTED_KEY_DERIVATION_FUNCTION}, - #else - {"UNSUPPORTED_KEY_DERIVATION_FUNCTION", 6, 124}, - #endif - #ifdef EVP_R_UNSUPPORTED_KEY_SIZE - {"UNSUPPORTED_KEY_SIZE", ERR_LIB_EVP, EVP_R_UNSUPPORTED_KEY_SIZE}, - #else - {"UNSUPPORTED_KEY_SIZE", 6, 108}, - #endif - #ifdef EVP_R_UNSUPPORTED_NUMBER_OF_ROUNDS - {"UNSUPPORTED_NUMBER_OF_ROUNDS", ERR_LIB_EVP, EVP_R_UNSUPPORTED_NUMBER_OF_ROUNDS}, - #else - {"UNSUPPORTED_NUMBER_OF_ROUNDS", 6, 135}, - #endif - #ifdef EVP_R_UNSUPPORTED_PRF - {"UNSUPPORTED_PRF", ERR_LIB_EVP, EVP_R_UNSUPPORTED_PRF}, - #else - {"UNSUPPORTED_PRF", 6, 125}, - #endif - #ifdef EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM - {"UNSUPPORTED_PRIVATE_KEY_ALGORITHM", ERR_LIB_EVP, EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM}, - #else - {"UNSUPPORTED_PRIVATE_KEY_ALGORITHM", 6, 118}, - #endif - #ifdef EVP_R_UNSUPPORTED_SALT_TYPE - {"UNSUPPORTED_SALT_TYPE", ERR_LIB_EVP, EVP_R_UNSUPPORTED_SALT_TYPE}, - #else - {"UNSUPPORTED_SALT_TYPE", 6, 126}, - #endif - #ifdef EVP_R_WRAP_MODE_NOT_ALLOWED - {"WRAP_MODE_NOT_ALLOWED", ERR_LIB_EVP, EVP_R_WRAP_MODE_NOT_ALLOWED}, - #else - {"WRAP_MODE_NOT_ALLOWED", 6, 170}, - #endif - #ifdef EVP_R_WRONG_FINAL_BLOCK_LENGTH - {"WRONG_FINAL_BLOCK_LENGTH", ERR_LIB_EVP, EVP_R_WRONG_FINAL_BLOCK_LENGTH}, - #else - {"WRONG_FINAL_BLOCK_LENGTH", 6, 109}, - #endif - #ifdef EVP_R_XTS_DUPLICATED_KEYS - {"XTS_DUPLICATED_KEYS", ERR_LIB_EVP, EVP_R_XTS_DUPLICATED_KEYS}, - #else - {"XTS_DUPLICATED_KEYS", 6, 183}, - #endif - #ifdef KDF_R_INVALID_DIGEST - {"INVALID_DIGEST", ERR_LIB_KDF, KDF_R_INVALID_DIGEST}, - #else - {"INVALID_DIGEST", 52, 100}, - #endif - #ifdef KDF_R_MISSING_ITERATION_COUNT - {"MISSING_ITERATION_COUNT", ERR_LIB_KDF, KDF_R_MISSING_ITERATION_COUNT}, - #else - {"MISSING_ITERATION_COUNT", 52, 109}, - #endif - #ifdef KDF_R_MISSING_KEY - {"MISSING_KEY", ERR_LIB_KDF, KDF_R_MISSING_KEY}, - #else - {"MISSING_KEY", 52, 104}, - #endif - #ifdef KDF_R_MISSING_MESSAGE_DIGEST - {"MISSING_MESSAGE_DIGEST", ERR_LIB_KDF, KDF_R_MISSING_MESSAGE_DIGEST}, - #else - {"MISSING_MESSAGE_DIGEST", 52, 105}, - #endif - #ifdef KDF_R_MISSING_PARAMETER - {"MISSING_PARAMETER", ERR_LIB_KDF, KDF_R_MISSING_PARAMETER}, - #else - {"MISSING_PARAMETER", 52, 101}, - #endif - #ifdef KDF_R_MISSING_PASS - {"MISSING_PASS", ERR_LIB_KDF, KDF_R_MISSING_PASS}, - #else - {"MISSING_PASS", 52, 110}, - #endif - #ifdef KDF_R_MISSING_SALT - {"MISSING_SALT", ERR_LIB_KDF, KDF_R_MISSING_SALT}, - #else - {"MISSING_SALT", 52, 111}, - #endif - #ifdef KDF_R_MISSING_SECRET - {"MISSING_SECRET", ERR_LIB_KDF, KDF_R_MISSING_SECRET}, - #else - {"MISSING_SECRET", 52, 107}, - #endif - #ifdef KDF_R_MISSING_SEED - {"MISSING_SEED", ERR_LIB_KDF, KDF_R_MISSING_SEED}, - #else - {"MISSING_SEED", 52, 106}, - #endif - #ifdef KDF_R_UNKNOWN_PARAMETER_TYPE - {"UNKNOWN_PARAMETER_TYPE", ERR_LIB_KDF, KDF_R_UNKNOWN_PARAMETER_TYPE}, - #else - {"UNKNOWN_PARAMETER_TYPE", 52, 103}, - #endif - #ifdef KDF_R_VALUE_ERROR - {"VALUE_ERROR", ERR_LIB_KDF, KDF_R_VALUE_ERROR}, - #else - {"VALUE_ERROR", 52, 108}, - #endif - #ifdef KDF_R_VALUE_MISSING - {"VALUE_MISSING", ERR_LIB_KDF, KDF_R_VALUE_MISSING}, - #else - {"VALUE_MISSING", 52, 102}, - #endif - #ifdef OCSP_R_CERTIFICATE_VERIFY_ERROR - {"CERTIFICATE_VERIFY_ERROR", ERR_LIB_OCSP, OCSP_R_CERTIFICATE_VERIFY_ERROR}, - #else - {"CERTIFICATE_VERIFY_ERROR", 39, 101}, - #endif - #ifdef OCSP_R_DIGEST_ERR - {"DIGEST_ERR", ERR_LIB_OCSP, OCSP_R_DIGEST_ERR}, - #else - {"DIGEST_ERR", 39, 102}, - #endif - #ifdef OCSP_R_ERROR_IN_NEXTUPDATE_FIELD - {"ERROR_IN_NEXTUPDATE_FIELD", ERR_LIB_OCSP, OCSP_R_ERROR_IN_NEXTUPDATE_FIELD}, - #else - {"ERROR_IN_NEXTUPDATE_FIELD", 39, 122}, - #endif - #ifdef OCSP_R_ERROR_IN_THISUPDATE_FIELD - {"ERROR_IN_THISUPDATE_FIELD", ERR_LIB_OCSP, OCSP_R_ERROR_IN_THISUPDATE_FIELD}, - #else - {"ERROR_IN_THISUPDATE_FIELD", 39, 123}, - #endif - #ifdef OCSP_R_ERROR_PARSING_URL - {"ERROR_PARSING_URL", ERR_LIB_OCSP, OCSP_R_ERROR_PARSING_URL}, - #else - {"ERROR_PARSING_URL", 39, 121}, - #endif - #ifdef OCSP_R_MISSING_OCSPSIGNING_USAGE - {"MISSING_OCSPSIGNING_USAGE", ERR_LIB_OCSP, OCSP_R_MISSING_OCSPSIGNING_USAGE}, - #else - {"MISSING_OCSPSIGNING_USAGE", 39, 103}, - #endif - #ifdef OCSP_R_NEXTUPDATE_BEFORE_THISUPDATE - {"NEXTUPDATE_BEFORE_THISUPDATE", ERR_LIB_OCSP, OCSP_R_NEXTUPDATE_BEFORE_THISUPDATE}, - #else - {"NEXTUPDATE_BEFORE_THISUPDATE", 39, 124}, - #endif - #ifdef OCSP_R_NOT_BASIC_RESPONSE - {"NOT_BASIC_RESPONSE", ERR_LIB_OCSP, OCSP_R_NOT_BASIC_RESPONSE}, - #else - {"NOT_BASIC_RESPONSE", 39, 104}, - #endif - #ifdef OCSP_R_NO_CERTIFICATES_IN_CHAIN - {"NO_CERTIFICATES_IN_CHAIN", ERR_LIB_OCSP, OCSP_R_NO_CERTIFICATES_IN_CHAIN}, - #else - {"NO_CERTIFICATES_IN_CHAIN", 39, 105}, - #endif - #ifdef OCSP_R_NO_RESPONSE_DATA - {"NO_RESPONSE_DATA", ERR_LIB_OCSP, OCSP_R_NO_RESPONSE_DATA}, - #else - {"NO_RESPONSE_DATA", 39, 108}, - #endif - #ifdef OCSP_R_NO_REVOKED_TIME - {"NO_REVOKED_TIME", ERR_LIB_OCSP, OCSP_R_NO_REVOKED_TIME}, - #else - {"NO_REVOKED_TIME", 39, 109}, - #endif - #ifdef OCSP_R_NO_SIGNER_KEY - {"NO_SIGNER_KEY", ERR_LIB_OCSP, OCSP_R_NO_SIGNER_KEY}, - #else - {"NO_SIGNER_KEY", 39, 130}, - #endif - #ifdef OCSP_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE - {"PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE", ERR_LIB_OCSP, OCSP_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE}, - #else - {"PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE", 39, 110}, - #endif - #ifdef OCSP_R_REQUEST_NOT_SIGNED - {"REQUEST_NOT_SIGNED", ERR_LIB_OCSP, OCSP_R_REQUEST_NOT_SIGNED}, - #else - {"REQUEST_NOT_SIGNED", 39, 128}, - #endif - #ifdef OCSP_R_RESPONSE_CONTAINS_NO_REVOCATION_DATA - {"RESPONSE_CONTAINS_NO_REVOCATION_DATA", ERR_LIB_OCSP, OCSP_R_RESPONSE_CONTAINS_NO_REVOCATION_DATA}, - #else - {"RESPONSE_CONTAINS_NO_REVOCATION_DATA", 39, 111}, - #endif - #ifdef OCSP_R_ROOT_CA_NOT_TRUSTED - {"ROOT_CA_NOT_TRUSTED", ERR_LIB_OCSP, OCSP_R_ROOT_CA_NOT_TRUSTED}, - #else - {"ROOT_CA_NOT_TRUSTED", 39, 112}, - #endif - #ifdef OCSP_R_SERVER_RESPONSE_ERROR - {"SERVER_RESPONSE_ERROR", ERR_LIB_OCSP, OCSP_R_SERVER_RESPONSE_ERROR}, - #else - {"SERVER_RESPONSE_ERROR", 39, 114}, - #endif - #ifdef OCSP_R_SERVER_RESPONSE_PARSE_ERROR - {"SERVER_RESPONSE_PARSE_ERROR", ERR_LIB_OCSP, OCSP_R_SERVER_RESPONSE_PARSE_ERROR}, - #else - {"SERVER_RESPONSE_PARSE_ERROR", 39, 115}, - #endif - #ifdef OCSP_R_SIGNATURE_FAILURE - {"SIGNATURE_FAILURE", ERR_LIB_OCSP, OCSP_R_SIGNATURE_FAILURE}, - #else - {"SIGNATURE_FAILURE", 39, 117}, - #endif - #ifdef OCSP_R_SIGNER_CERTIFICATE_NOT_FOUND - {"SIGNER_CERTIFICATE_NOT_FOUND", ERR_LIB_OCSP, OCSP_R_SIGNER_CERTIFICATE_NOT_FOUND}, - #else - {"SIGNER_CERTIFICATE_NOT_FOUND", 39, 118}, - #endif - #ifdef OCSP_R_STATUS_EXPIRED - {"STATUS_EXPIRED", ERR_LIB_OCSP, OCSP_R_STATUS_EXPIRED}, - #else - {"STATUS_EXPIRED", 39, 125}, - #endif - #ifdef OCSP_R_STATUS_NOT_YET_VALID - {"STATUS_NOT_YET_VALID", ERR_LIB_OCSP, OCSP_R_STATUS_NOT_YET_VALID}, - #else - {"STATUS_NOT_YET_VALID", 39, 126}, - #endif - #ifdef OCSP_R_STATUS_TOO_OLD - {"STATUS_TOO_OLD", ERR_LIB_OCSP, OCSP_R_STATUS_TOO_OLD}, - #else - {"STATUS_TOO_OLD", 39, 127}, - #endif - #ifdef OCSP_R_UNKNOWN_MESSAGE_DIGEST - {"UNKNOWN_MESSAGE_DIGEST", ERR_LIB_OCSP, OCSP_R_UNKNOWN_MESSAGE_DIGEST}, - #else - {"UNKNOWN_MESSAGE_DIGEST", 39, 119}, - #endif - #ifdef OCSP_R_UNKNOWN_NID - {"UNKNOWN_NID", ERR_LIB_OCSP, OCSP_R_UNKNOWN_NID}, - #else - {"UNKNOWN_NID", 39, 120}, - #endif - #ifdef OCSP_R_UNSUPPORTED_REQUESTORNAME_TYPE - {"UNSUPPORTED_REQUESTORNAME_TYPE", ERR_LIB_OCSP, OCSP_R_UNSUPPORTED_REQUESTORNAME_TYPE}, - #else - {"UNSUPPORTED_REQUESTORNAME_TYPE", 39, 129}, - #endif - #ifdef PEM_R_BAD_BASE64_DECODE - {"BAD_BASE64_DECODE", ERR_LIB_PEM, PEM_R_BAD_BASE64_DECODE}, - #else - {"BAD_BASE64_DECODE", 9, 100}, - #endif - #ifdef PEM_R_BAD_DECRYPT - {"BAD_DECRYPT", ERR_LIB_PEM, PEM_R_BAD_DECRYPT}, - #else - {"BAD_DECRYPT", 9, 101}, - #endif - #ifdef PEM_R_BAD_END_LINE - {"BAD_END_LINE", ERR_LIB_PEM, PEM_R_BAD_END_LINE}, - #else - {"BAD_END_LINE", 9, 102}, - #endif - #ifdef PEM_R_BAD_IV_CHARS - {"BAD_IV_CHARS", ERR_LIB_PEM, PEM_R_BAD_IV_CHARS}, - #else - {"BAD_IV_CHARS", 9, 103}, - #endif - #ifdef PEM_R_BAD_MAGIC_NUMBER - {"BAD_MAGIC_NUMBER", ERR_LIB_PEM, PEM_R_BAD_MAGIC_NUMBER}, - #else - {"BAD_MAGIC_NUMBER", 9, 116}, - #endif - #ifdef PEM_R_BAD_PASSWORD_READ - {"BAD_PASSWORD_READ", ERR_LIB_PEM, PEM_R_BAD_PASSWORD_READ}, - #else - {"BAD_PASSWORD_READ", 9, 104}, - #endif - #ifdef PEM_R_BAD_VERSION_NUMBER - {"BAD_VERSION_NUMBER", ERR_LIB_PEM, PEM_R_BAD_VERSION_NUMBER}, - #else - {"BAD_VERSION_NUMBER", 9, 117}, - #endif - #ifdef PEM_R_BIO_WRITE_FAILURE - {"BIO_WRITE_FAILURE", ERR_LIB_PEM, PEM_R_BIO_WRITE_FAILURE}, - #else - {"BIO_WRITE_FAILURE", 9, 118}, - #endif - #ifdef PEM_R_CIPHER_IS_NULL - {"CIPHER_IS_NULL", ERR_LIB_PEM, PEM_R_CIPHER_IS_NULL}, - #else - {"CIPHER_IS_NULL", 9, 127}, - #endif - #ifdef PEM_R_ERROR_CONVERTING_PRIVATE_KEY - {"ERROR_CONVERTING_PRIVATE_KEY", ERR_LIB_PEM, PEM_R_ERROR_CONVERTING_PRIVATE_KEY}, - #else - {"ERROR_CONVERTING_PRIVATE_KEY", 9, 115}, - #endif - #ifdef PEM_R_EXPECTING_PRIVATE_KEY_BLOB - {"EXPECTING_PRIVATE_KEY_BLOB", ERR_LIB_PEM, PEM_R_EXPECTING_PRIVATE_KEY_BLOB}, - #else - {"EXPECTING_PRIVATE_KEY_BLOB", 9, 119}, - #endif - #ifdef PEM_R_EXPECTING_PUBLIC_KEY_BLOB - {"EXPECTING_PUBLIC_KEY_BLOB", ERR_LIB_PEM, PEM_R_EXPECTING_PUBLIC_KEY_BLOB}, - #else - {"EXPECTING_PUBLIC_KEY_BLOB", 9, 120}, - #endif - #ifdef PEM_R_HEADER_TOO_LONG - {"HEADER_TOO_LONG", ERR_LIB_PEM, PEM_R_HEADER_TOO_LONG}, - #else - {"HEADER_TOO_LONG", 9, 128}, - #endif - #ifdef PEM_R_INCONSISTENT_HEADER - {"INCONSISTENT_HEADER", ERR_LIB_PEM, PEM_R_INCONSISTENT_HEADER}, - #else - {"INCONSISTENT_HEADER", 9, 121}, - #endif - #ifdef PEM_R_KEYBLOB_HEADER_PARSE_ERROR - {"KEYBLOB_HEADER_PARSE_ERROR", ERR_LIB_PEM, PEM_R_KEYBLOB_HEADER_PARSE_ERROR}, - #else - {"KEYBLOB_HEADER_PARSE_ERROR", 9, 122}, - #endif - #ifdef PEM_R_KEYBLOB_TOO_SHORT - {"KEYBLOB_TOO_SHORT", ERR_LIB_PEM, PEM_R_KEYBLOB_TOO_SHORT}, - #else - {"KEYBLOB_TOO_SHORT", 9, 123}, - #endif - #ifdef PEM_R_MISSING_DEK_IV - {"MISSING_DEK_IV", ERR_LIB_PEM, PEM_R_MISSING_DEK_IV}, - #else - {"MISSING_DEK_IV", 9, 129}, - #endif - #ifdef PEM_R_NOT_DEK_INFO - {"NOT_DEK_INFO", ERR_LIB_PEM, PEM_R_NOT_DEK_INFO}, - #else - {"NOT_DEK_INFO", 9, 105}, - #endif - #ifdef PEM_R_NOT_ENCRYPTED - {"NOT_ENCRYPTED", ERR_LIB_PEM, PEM_R_NOT_ENCRYPTED}, - #else - {"NOT_ENCRYPTED", 9, 106}, - #endif - #ifdef PEM_R_NOT_PROC_TYPE - {"NOT_PROC_TYPE", ERR_LIB_PEM, PEM_R_NOT_PROC_TYPE}, - #else - {"NOT_PROC_TYPE", 9, 107}, - #endif - #ifdef PEM_R_NO_START_LINE - {"NO_START_LINE", ERR_LIB_PEM, PEM_R_NO_START_LINE}, - #else - {"NO_START_LINE", 9, 108}, - #endif - #ifdef PEM_R_PROBLEMS_GETTING_PASSWORD - {"PROBLEMS_GETTING_PASSWORD", ERR_LIB_PEM, PEM_R_PROBLEMS_GETTING_PASSWORD}, - #else - {"PROBLEMS_GETTING_PASSWORD", 9, 109}, - #endif - #ifdef PEM_R_PUBLIC_KEY_NO_RSA - {"PUBLIC_KEY_NO_RSA", ERR_LIB_PEM, PEM_R_PUBLIC_KEY_NO_RSA}, - #else - {"PUBLIC_KEY_NO_RSA", 9, 110}, - #endif - #ifdef PEM_R_PVK_DATA_TOO_SHORT - {"PVK_DATA_TOO_SHORT", ERR_LIB_PEM, PEM_R_PVK_DATA_TOO_SHORT}, - #else - {"PVK_DATA_TOO_SHORT", 9, 124}, - #endif - #ifdef PEM_R_PVK_TOO_SHORT - {"PVK_TOO_SHORT", ERR_LIB_PEM, PEM_R_PVK_TOO_SHORT}, - #else - {"PVK_TOO_SHORT", 9, 125}, - #endif - #ifdef PEM_R_READ_KEY - {"READ_KEY", ERR_LIB_PEM, PEM_R_READ_KEY}, - #else - {"READ_KEY", 9, 111}, - #endif - #ifdef PEM_R_SHORT_HEADER - {"SHORT_HEADER", ERR_LIB_PEM, PEM_R_SHORT_HEADER}, - #else - {"SHORT_HEADER", 9, 112}, - #endif - #ifdef PEM_R_UNEXPECTED_DEK_IV - {"UNEXPECTED_DEK_IV", ERR_LIB_PEM, PEM_R_UNEXPECTED_DEK_IV}, - #else - {"UNEXPECTED_DEK_IV", 9, 130}, - #endif - #ifdef PEM_R_UNSUPPORTED_CIPHER - {"UNSUPPORTED_CIPHER", ERR_LIB_PEM, PEM_R_UNSUPPORTED_CIPHER}, - #else - {"UNSUPPORTED_CIPHER", 9, 113}, - #endif - #ifdef PEM_R_UNSUPPORTED_ENCRYPTION - {"UNSUPPORTED_ENCRYPTION", ERR_LIB_PEM, PEM_R_UNSUPPORTED_ENCRYPTION}, - #else - {"UNSUPPORTED_ENCRYPTION", 9, 114}, - #endif - #ifdef PEM_R_UNSUPPORTED_KEY_COMPONENTS - {"UNSUPPORTED_KEY_COMPONENTS", ERR_LIB_PEM, PEM_R_UNSUPPORTED_KEY_COMPONENTS}, - #else - {"UNSUPPORTED_KEY_COMPONENTS", 9, 126}, - #endif - #ifdef PKCS12_R_CANT_PACK_STRUCTURE - {"CANT_PACK_STRUCTURE", ERR_LIB_PKCS12, PKCS12_R_CANT_PACK_STRUCTURE}, - #else - {"CANT_PACK_STRUCTURE", 35, 100}, - #endif - #ifdef PKCS12_R_CONTENT_TYPE_NOT_DATA - {"CONTENT_TYPE_NOT_DATA", ERR_LIB_PKCS12, PKCS12_R_CONTENT_TYPE_NOT_DATA}, - #else - {"CONTENT_TYPE_NOT_DATA", 35, 121}, - #endif - #ifdef PKCS12_R_DECODE_ERROR - {"DECODE_ERROR", ERR_LIB_PKCS12, PKCS12_R_DECODE_ERROR}, - #else - {"DECODE_ERROR", 35, 101}, - #endif - #ifdef PKCS12_R_ENCODE_ERROR - {"ENCODE_ERROR", ERR_LIB_PKCS12, PKCS12_R_ENCODE_ERROR}, - #else - {"ENCODE_ERROR", 35, 102}, - #endif - #ifdef PKCS12_R_ENCRYPT_ERROR - {"ENCRYPT_ERROR", ERR_LIB_PKCS12, PKCS12_R_ENCRYPT_ERROR}, - #else - {"ENCRYPT_ERROR", 35, 103}, - #endif - #ifdef PKCS12_R_ERROR_SETTING_ENCRYPTED_DATA_TYPE - {"ERROR_SETTING_ENCRYPTED_DATA_TYPE", ERR_LIB_PKCS12, PKCS12_R_ERROR_SETTING_ENCRYPTED_DATA_TYPE}, - #else - {"ERROR_SETTING_ENCRYPTED_DATA_TYPE", 35, 120}, - #endif - #ifdef PKCS12_R_INVALID_NULL_ARGUMENT - {"INVALID_NULL_ARGUMENT", ERR_LIB_PKCS12, PKCS12_R_INVALID_NULL_ARGUMENT}, - #else - {"INVALID_NULL_ARGUMENT", 35, 104}, - #endif - #ifdef PKCS12_R_INVALID_NULL_PKCS12_POINTER - {"INVALID_NULL_PKCS12_POINTER", ERR_LIB_PKCS12, PKCS12_R_INVALID_NULL_PKCS12_POINTER}, - #else - {"INVALID_NULL_PKCS12_POINTER", 35, 105}, - #endif - #ifdef PKCS12_R_IV_GEN_ERROR - {"IV_GEN_ERROR", ERR_LIB_PKCS12, PKCS12_R_IV_GEN_ERROR}, - #else - {"IV_GEN_ERROR", 35, 106}, - #endif - #ifdef PKCS12_R_KEY_GEN_ERROR - {"KEY_GEN_ERROR", ERR_LIB_PKCS12, PKCS12_R_KEY_GEN_ERROR}, - #else - {"KEY_GEN_ERROR", 35, 107}, - #endif - #ifdef PKCS12_R_MAC_ABSENT - {"MAC_ABSENT", ERR_LIB_PKCS12, PKCS12_R_MAC_ABSENT}, - #else - {"MAC_ABSENT", 35, 108}, - #endif - #ifdef PKCS12_R_MAC_GENERATION_ERROR - {"MAC_GENERATION_ERROR", ERR_LIB_PKCS12, PKCS12_R_MAC_GENERATION_ERROR}, - #else - {"MAC_GENERATION_ERROR", 35, 109}, - #endif - #ifdef PKCS12_R_MAC_SETUP_ERROR - {"MAC_SETUP_ERROR", ERR_LIB_PKCS12, PKCS12_R_MAC_SETUP_ERROR}, - #else - {"MAC_SETUP_ERROR", 35, 110}, - #endif - #ifdef PKCS12_R_MAC_STRING_SET_ERROR - {"MAC_STRING_SET_ERROR", ERR_LIB_PKCS12, PKCS12_R_MAC_STRING_SET_ERROR}, - #else - {"MAC_STRING_SET_ERROR", 35, 111}, - #endif - #ifdef PKCS12_R_MAC_VERIFY_FAILURE - {"MAC_VERIFY_FAILURE", ERR_LIB_PKCS12, PKCS12_R_MAC_VERIFY_FAILURE}, - #else - {"MAC_VERIFY_FAILURE", 35, 113}, - #endif - #ifdef PKCS12_R_PARSE_ERROR - {"PARSE_ERROR", ERR_LIB_PKCS12, PKCS12_R_PARSE_ERROR}, - #else - {"PARSE_ERROR", 35, 114}, - #endif - #ifdef PKCS12_R_PKCS12_ALGOR_CIPHERINIT_ERROR - {"PKCS12_ALGOR_CIPHERINIT_ERROR", ERR_LIB_PKCS12, PKCS12_R_PKCS12_ALGOR_CIPHERINIT_ERROR}, - #else - {"PKCS12_ALGOR_CIPHERINIT_ERROR", 35, 115}, - #endif - #ifdef PKCS12_R_PKCS12_CIPHERFINAL_ERROR - {"PKCS12_CIPHERFINAL_ERROR", ERR_LIB_PKCS12, PKCS12_R_PKCS12_CIPHERFINAL_ERROR}, - #else - {"PKCS12_CIPHERFINAL_ERROR", 35, 116}, - #endif - #ifdef PKCS12_R_PKCS12_PBE_CRYPT_ERROR - {"PKCS12_PBE_CRYPT_ERROR", ERR_LIB_PKCS12, PKCS12_R_PKCS12_PBE_CRYPT_ERROR}, - #else - {"PKCS12_PBE_CRYPT_ERROR", 35, 117}, - #endif - #ifdef PKCS12_R_UNKNOWN_DIGEST_ALGORITHM - {"UNKNOWN_DIGEST_ALGORITHM", ERR_LIB_PKCS12, PKCS12_R_UNKNOWN_DIGEST_ALGORITHM}, - #else - {"UNKNOWN_DIGEST_ALGORITHM", 35, 118}, - #endif - #ifdef PKCS12_R_UNSUPPORTED_PKCS12_MODE - {"UNSUPPORTED_PKCS12_MODE", ERR_LIB_PKCS12, PKCS12_R_UNSUPPORTED_PKCS12_MODE}, - #else - {"UNSUPPORTED_PKCS12_MODE", 35, 119}, - #endif - #ifdef PKCS7_R_CERTIFICATE_VERIFY_ERROR - {"CERTIFICATE_VERIFY_ERROR", ERR_LIB_PKCS7, PKCS7_R_CERTIFICATE_VERIFY_ERROR}, - #else - {"CERTIFICATE_VERIFY_ERROR", 33, 117}, - #endif - #ifdef PKCS7_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER - {"CIPHER_HAS_NO_OBJECT_IDENTIFIER", ERR_LIB_PKCS7, PKCS7_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER}, - #else - {"CIPHER_HAS_NO_OBJECT_IDENTIFIER", 33, 144}, - #endif - #ifdef PKCS7_R_CIPHER_NOT_INITIALIZED - {"CIPHER_NOT_INITIALIZED", ERR_LIB_PKCS7, PKCS7_R_CIPHER_NOT_INITIALIZED}, - #else - {"CIPHER_NOT_INITIALIZED", 33, 116}, - #endif - #ifdef PKCS7_R_CONTENT_AND_DATA_PRESENT - {"CONTENT_AND_DATA_PRESENT", ERR_LIB_PKCS7, PKCS7_R_CONTENT_AND_DATA_PRESENT}, - #else - {"CONTENT_AND_DATA_PRESENT", 33, 118}, - #endif - #ifdef PKCS7_R_CTRL_ERROR - {"CTRL_ERROR", ERR_LIB_PKCS7, PKCS7_R_CTRL_ERROR}, - #else - {"CTRL_ERROR", 33, 152}, - #endif - #ifdef PKCS7_R_DECRYPT_ERROR - {"DECRYPT_ERROR", ERR_LIB_PKCS7, PKCS7_R_DECRYPT_ERROR}, - #else - {"DECRYPT_ERROR", 33, 119}, - #endif - #ifdef PKCS7_R_DIGEST_FAILURE - {"DIGEST_FAILURE", ERR_LIB_PKCS7, PKCS7_R_DIGEST_FAILURE}, - #else - {"DIGEST_FAILURE", 33, 101}, - #endif - #ifdef PKCS7_R_ENCRYPTION_CTRL_FAILURE - {"ENCRYPTION_CTRL_FAILURE", ERR_LIB_PKCS7, PKCS7_R_ENCRYPTION_CTRL_FAILURE}, - #else - {"ENCRYPTION_CTRL_FAILURE", 33, 149}, - #endif - #ifdef PKCS7_R_ENCRYPTION_NOT_SUPPORTED_FOR_THIS_KEY_TYPE - {"ENCRYPTION_NOT_SUPPORTED_FOR_THIS_KEY_TYPE", ERR_LIB_PKCS7, PKCS7_R_ENCRYPTION_NOT_SUPPORTED_FOR_THIS_KEY_TYPE}, - #else - {"ENCRYPTION_NOT_SUPPORTED_FOR_THIS_KEY_TYPE", 33, 150}, - #endif - #ifdef PKCS7_R_ERROR_ADDING_RECIPIENT - {"ERROR_ADDING_RECIPIENT", ERR_LIB_PKCS7, PKCS7_R_ERROR_ADDING_RECIPIENT}, - #else - {"ERROR_ADDING_RECIPIENT", 33, 120}, - #endif - #ifdef PKCS7_R_ERROR_SETTING_CIPHER - {"ERROR_SETTING_CIPHER", ERR_LIB_PKCS7, PKCS7_R_ERROR_SETTING_CIPHER}, - #else - {"ERROR_SETTING_CIPHER", 33, 121}, - #endif - #ifdef PKCS7_R_INVALID_NULL_POINTER - {"INVALID_NULL_POINTER", ERR_LIB_PKCS7, PKCS7_R_INVALID_NULL_POINTER}, - #else - {"INVALID_NULL_POINTER", 33, 143}, - #endif - #ifdef PKCS7_R_INVALID_SIGNED_DATA_TYPE - {"INVALID_SIGNED_DATA_TYPE", ERR_LIB_PKCS7, PKCS7_R_INVALID_SIGNED_DATA_TYPE}, - #else - {"INVALID_SIGNED_DATA_TYPE", 33, 155}, - #endif - #ifdef PKCS7_R_NO_CONTENT - {"NO_CONTENT", ERR_LIB_PKCS7, PKCS7_R_NO_CONTENT}, - #else - {"NO_CONTENT", 33, 122}, - #endif - #ifdef PKCS7_R_NO_DEFAULT_DIGEST - {"NO_DEFAULT_DIGEST", ERR_LIB_PKCS7, PKCS7_R_NO_DEFAULT_DIGEST}, - #else - {"NO_DEFAULT_DIGEST", 33, 151}, - #endif - #ifdef PKCS7_R_NO_MATCHING_DIGEST_TYPE_FOUND - {"NO_MATCHING_DIGEST_TYPE_FOUND", ERR_LIB_PKCS7, PKCS7_R_NO_MATCHING_DIGEST_TYPE_FOUND}, - #else - {"NO_MATCHING_DIGEST_TYPE_FOUND", 33, 154}, - #endif - #ifdef PKCS7_R_NO_RECIPIENT_MATCHES_CERTIFICATE - {"NO_RECIPIENT_MATCHES_CERTIFICATE", ERR_LIB_PKCS7, PKCS7_R_NO_RECIPIENT_MATCHES_CERTIFICATE}, - #else - {"NO_RECIPIENT_MATCHES_CERTIFICATE", 33, 115}, - #endif - #ifdef PKCS7_R_NO_SIGNATURES_ON_DATA - {"NO_SIGNATURES_ON_DATA", ERR_LIB_PKCS7, PKCS7_R_NO_SIGNATURES_ON_DATA}, - #else - {"NO_SIGNATURES_ON_DATA", 33, 123}, - #endif - #ifdef PKCS7_R_NO_SIGNERS - {"NO_SIGNERS", ERR_LIB_PKCS7, PKCS7_R_NO_SIGNERS}, - #else - {"NO_SIGNERS", 33, 142}, - #endif - #ifdef PKCS7_R_OPERATION_NOT_SUPPORTED_ON_THIS_TYPE - {"OPERATION_NOT_SUPPORTED_ON_THIS_TYPE", ERR_LIB_PKCS7, PKCS7_R_OPERATION_NOT_SUPPORTED_ON_THIS_TYPE}, - #else - {"OPERATION_NOT_SUPPORTED_ON_THIS_TYPE", 33, 104}, - #endif - #ifdef PKCS7_R_PKCS7_ADD_SIGNATURE_ERROR - {"PKCS7_ADD_SIGNATURE_ERROR", ERR_LIB_PKCS7, PKCS7_R_PKCS7_ADD_SIGNATURE_ERROR}, - #else - {"PKCS7_ADD_SIGNATURE_ERROR", 33, 124}, - #endif - #ifdef PKCS7_R_PKCS7_ADD_SIGNER_ERROR - {"PKCS7_ADD_SIGNER_ERROR", ERR_LIB_PKCS7, PKCS7_R_PKCS7_ADD_SIGNER_ERROR}, - #else - {"PKCS7_ADD_SIGNER_ERROR", 33, 153}, - #endif - #ifdef PKCS7_R_PKCS7_DATASIGN - {"PKCS7_DATASIGN", ERR_LIB_PKCS7, PKCS7_R_PKCS7_DATASIGN}, - #else - {"PKCS7_DATASIGN", 33, 145}, - #endif - #ifdef PKCS7_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE - {"PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE", ERR_LIB_PKCS7, PKCS7_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE}, - #else - {"PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE", 33, 127}, - #endif - #ifdef PKCS7_R_SIGNATURE_FAILURE - {"SIGNATURE_FAILURE", ERR_LIB_PKCS7, PKCS7_R_SIGNATURE_FAILURE}, - #else - {"SIGNATURE_FAILURE", 33, 105}, - #endif - #ifdef PKCS7_R_SIGNER_CERTIFICATE_NOT_FOUND - {"SIGNER_CERTIFICATE_NOT_FOUND", ERR_LIB_PKCS7, PKCS7_R_SIGNER_CERTIFICATE_NOT_FOUND}, - #else - {"SIGNER_CERTIFICATE_NOT_FOUND", 33, 128}, - #endif - #ifdef PKCS7_R_SIGNING_CTRL_FAILURE - {"SIGNING_CTRL_FAILURE", ERR_LIB_PKCS7, PKCS7_R_SIGNING_CTRL_FAILURE}, - #else - {"SIGNING_CTRL_FAILURE", 33, 147}, - #endif - #ifdef PKCS7_R_SIGNING_NOT_SUPPORTED_FOR_THIS_KEY_TYPE - {"SIGNING_NOT_SUPPORTED_FOR_THIS_KEY_TYPE", ERR_LIB_PKCS7, PKCS7_R_SIGNING_NOT_SUPPORTED_FOR_THIS_KEY_TYPE}, - #else - {"SIGNING_NOT_SUPPORTED_FOR_THIS_KEY_TYPE", 33, 148}, - #endif - #ifdef PKCS7_R_SMIME_TEXT_ERROR - {"SMIME_TEXT_ERROR", ERR_LIB_PKCS7, PKCS7_R_SMIME_TEXT_ERROR}, - #else - {"SMIME_TEXT_ERROR", 33, 129}, - #endif - #ifdef PKCS7_R_UNABLE_TO_FIND_CERTIFICATE - {"UNABLE_TO_FIND_CERTIFICATE", ERR_LIB_PKCS7, PKCS7_R_UNABLE_TO_FIND_CERTIFICATE}, - #else - {"UNABLE_TO_FIND_CERTIFICATE", 33, 106}, - #endif - #ifdef PKCS7_R_UNABLE_TO_FIND_MEM_BIO - {"UNABLE_TO_FIND_MEM_BIO", ERR_LIB_PKCS7, PKCS7_R_UNABLE_TO_FIND_MEM_BIO}, - #else - {"UNABLE_TO_FIND_MEM_BIO", 33, 107}, - #endif - #ifdef PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST - {"UNABLE_TO_FIND_MESSAGE_DIGEST", ERR_LIB_PKCS7, PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST}, - #else - {"UNABLE_TO_FIND_MESSAGE_DIGEST", 33, 108}, - #endif - #ifdef PKCS7_R_UNKNOWN_DIGEST_TYPE - {"UNKNOWN_DIGEST_TYPE", ERR_LIB_PKCS7, PKCS7_R_UNKNOWN_DIGEST_TYPE}, - #else - {"UNKNOWN_DIGEST_TYPE", 33, 109}, - #endif - #ifdef PKCS7_R_UNKNOWN_OPERATION - {"UNKNOWN_OPERATION", ERR_LIB_PKCS7, PKCS7_R_UNKNOWN_OPERATION}, - #else - {"UNKNOWN_OPERATION", 33, 110}, - #endif - #ifdef PKCS7_R_UNSUPPORTED_CIPHER_TYPE - {"UNSUPPORTED_CIPHER_TYPE", ERR_LIB_PKCS7, PKCS7_R_UNSUPPORTED_CIPHER_TYPE}, - #else - {"UNSUPPORTED_CIPHER_TYPE", 33, 111}, - #endif - #ifdef PKCS7_R_UNSUPPORTED_CONTENT_TYPE - {"UNSUPPORTED_CONTENT_TYPE", ERR_LIB_PKCS7, PKCS7_R_UNSUPPORTED_CONTENT_TYPE}, - #else - {"UNSUPPORTED_CONTENT_TYPE", 33, 112}, - #endif - #ifdef PKCS7_R_WRONG_CONTENT_TYPE - {"WRONG_CONTENT_TYPE", ERR_LIB_PKCS7, PKCS7_R_WRONG_CONTENT_TYPE}, - #else - {"WRONG_CONTENT_TYPE", 33, 113}, - #endif - #ifdef PKCS7_R_WRONG_PKCS7_TYPE - {"WRONG_PKCS7_TYPE", ERR_LIB_PKCS7, PKCS7_R_WRONG_PKCS7_TYPE}, - #else - {"WRONG_PKCS7_TYPE", 33, 114}, - #endif - #ifdef RAND_R_ADDITIONAL_INPUT_TOO_LONG - {"ADDITIONAL_INPUT_TOO_LONG", ERR_LIB_RAND, RAND_R_ADDITIONAL_INPUT_TOO_LONG}, - #else - {"ADDITIONAL_INPUT_TOO_LONG", 36, 102}, - #endif - #ifdef RAND_R_ALREADY_INSTANTIATED - {"ALREADY_INSTANTIATED", ERR_LIB_RAND, RAND_R_ALREADY_INSTANTIATED}, - #else - {"ALREADY_INSTANTIATED", 36, 103}, - #endif - #ifdef RAND_R_ARGUMENT_OUT_OF_RANGE - {"ARGUMENT_OUT_OF_RANGE", ERR_LIB_RAND, RAND_R_ARGUMENT_OUT_OF_RANGE}, - #else - {"ARGUMENT_OUT_OF_RANGE", 36, 105}, - #endif - #ifdef RAND_R_CANNOT_OPEN_FILE - {"CANNOT_OPEN_FILE", ERR_LIB_RAND, RAND_R_CANNOT_OPEN_FILE}, - #else - {"CANNOT_OPEN_FILE", 36, 121}, - #endif - #ifdef RAND_R_DRBG_ALREADY_INITIALIZED - {"DRBG_ALREADY_INITIALIZED", ERR_LIB_RAND, RAND_R_DRBG_ALREADY_INITIALIZED}, - #else - {"DRBG_ALREADY_INITIALIZED", 36, 129}, - #endif - #ifdef RAND_R_DRBG_NOT_INITIALISED - {"DRBG_NOT_INITIALISED", ERR_LIB_RAND, RAND_R_DRBG_NOT_INITIALISED}, - #else - {"DRBG_NOT_INITIALISED", 36, 104}, - #endif - #ifdef RAND_R_ENTROPY_INPUT_TOO_LONG - {"ENTROPY_INPUT_TOO_LONG", ERR_LIB_RAND, RAND_R_ENTROPY_INPUT_TOO_LONG}, - #else - {"ENTROPY_INPUT_TOO_LONG", 36, 106}, - #endif - #ifdef RAND_R_ENTROPY_OUT_OF_RANGE - {"ENTROPY_OUT_OF_RANGE", ERR_LIB_RAND, RAND_R_ENTROPY_OUT_OF_RANGE}, - #else - {"ENTROPY_OUT_OF_RANGE", 36, 124}, - #endif - #ifdef RAND_R_ERROR_ENTROPY_POOL_WAS_IGNORED - {"ERROR_ENTROPY_POOL_WAS_IGNORED", ERR_LIB_RAND, RAND_R_ERROR_ENTROPY_POOL_WAS_IGNORED}, - #else - {"ERROR_ENTROPY_POOL_WAS_IGNORED", 36, 127}, - #endif - #ifdef RAND_R_ERROR_INITIALISING_DRBG - {"ERROR_INITIALISING_DRBG", ERR_LIB_RAND, RAND_R_ERROR_INITIALISING_DRBG}, - #else - {"ERROR_INITIALISING_DRBG", 36, 107}, - #endif - #ifdef RAND_R_ERROR_INSTANTIATING_DRBG - {"ERROR_INSTANTIATING_DRBG", ERR_LIB_RAND, RAND_R_ERROR_INSTANTIATING_DRBG}, - #else - {"ERROR_INSTANTIATING_DRBG", 36, 108}, - #endif - #ifdef RAND_R_ERROR_RETRIEVING_ADDITIONAL_INPUT - {"ERROR_RETRIEVING_ADDITIONAL_INPUT", ERR_LIB_RAND, RAND_R_ERROR_RETRIEVING_ADDITIONAL_INPUT}, - #else - {"ERROR_RETRIEVING_ADDITIONAL_INPUT", 36, 109}, - #endif - #ifdef RAND_R_ERROR_RETRIEVING_ENTROPY - {"ERROR_RETRIEVING_ENTROPY", ERR_LIB_RAND, RAND_R_ERROR_RETRIEVING_ENTROPY}, - #else - {"ERROR_RETRIEVING_ENTROPY", 36, 110}, - #endif - #ifdef RAND_R_ERROR_RETRIEVING_NONCE - {"ERROR_RETRIEVING_NONCE", ERR_LIB_RAND, RAND_R_ERROR_RETRIEVING_NONCE}, - #else - {"ERROR_RETRIEVING_NONCE", 36, 111}, - #endif - #ifdef RAND_R_FAILED_TO_CREATE_LOCK - {"FAILED_TO_CREATE_LOCK", ERR_LIB_RAND, RAND_R_FAILED_TO_CREATE_LOCK}, - #else - {"FAILED_TO_CREATE_LOCK", 36, 126}, - #endif - #ifdef RAND_R_FUNC_NOT_IMPLEMENTED - {"FUNC_NOT_IMPLEMENTED", ERR_LIB_RAND, RAND_R_FUNC_NOT_IMPLEMENTED}, - #else - {"FUNC_NOT_IMPLEMENTED", 36, 101}, - #endif - #ifdef RAND_R_FWRITE_ERROR - {"FWRITE_ERROR", ERR_LIB_RAND, RAND_R_FWRITE_ERROR}, - #else - {"FWRITE_ERROR", 36, 123}, - #endif - #ifdef RAND_R_GENERATE_ERROR - {"GENERATE_ERROR", ERR_LIB_RAND, RAND_R_GENERATE_ERROR}, - #else - {"GENERATE_ERROR", 36, 112}, - #endif - #ifdef RAND_R_INTERNAL_ERROR - {"INTERNAL_ERROR", ERR_LIB_RAND, RAND_R_INTERNAL_ERROR}, - #else - {"INTERNAL_ERROR", 36, 113}, - #endif - #ifdef RAND_R_IN_ERROR_STATE - {"IN_ERROR_STATE", ERR_LIB_RAND, RAND_R_IN_ERROR_STATE}, - #else - {"IN_ERROR_STATE", 36, 114}, - #endif - #ifdef RAND_R_NOT_A_REGULAR_FILE - {"NOT_A_REGULAR_FILE", ERR_LIB_RAND, RAND_R_NOT_A_REGULAR_FILE}, - #else - {"NOT_A_REGULAR_FILE", 36, 122}, - #endif - #ifdef RAND_R_NOT_INSTANTIATED - {"NOT_INSTANTIATED", ERR_LIB_RAND, RAND_R_NOT_INSTANTIATED}, - #else - {"NOT_INSTANTIATED", 36, 115}, - #endif - #ifdef RAND_R_NO_DRBG_IMPLEMENTATION_SELECTED - {"NO_DRBG_IMPLEMENTATION_SELECTED", ERR_LIB_RAND, RAND_R_NO_DRBG_IMPLEMENTATION_SELECTED}, - #else - {"NO_DRBG_IMPLEMENTATION_SELECTED", 36, 128}, - #endif - #ifdef RAND_R_PARENT_LOCKING_NOT_ENABLED - {"PARENT_LOCKING_NOT_ENABLED", ERR_LIB_RAND, RAND_R_PARENT_LOCKING_NOT_ENABLED}, - #else - {"PARENT_LOCKING_NOT_ENABLED", 36, 130}, - #endif - #ifdef RAND_R_PARENT_STRENGTH_TOO_WEAK - {"PARENT_STRENGTH_TOO_WEAK", ERR_LIB_RAND, RAND_R_PARENT_STRENGTH_TOO_WEAK}, - #else - {"PARENT_STRENGTH_TOO_WEAK", 36, 131}, - #endif - #ifdef RAND_R_PERSONALISATION_STRING_TOO_LONG - {"PERSONALISATION_STRING_TOO_LONG", ERR_LIB_RAND, RAND_R_PERSONALISATION_STRING_TOO_LONG}, - #else - {"PERSONALISATION_STRING_TOO_LONG", 36, 116}, - #endif - #ifdef RAND_R_PREDICTION_RESISTANCE_NOT_SUPPORTED - {"PREDICTION_RESISTANCE_NOT_SUPPORTED", ERR_LIB_RAND, RAND_R_PREDICTION_RESISTANCE_NOT_SUPPORTED}, - #else - {"PREDICTION_RESISTANCE_NOT_SUPPORTED", 36, 133}, - #endif - #ifdef RAND_R_PRNG_NOT_SEEDED - {"PRNG_NOT_SEEDED", ERR_LIB_RAND, RAND_R_PRNG_NOT_SEEDED}, - #else - {"PRNG_NOT_SEEDED", 36, 100}, - #endif - #ifdef RAND_R_RANDOM_POOL_OVERFLOW - {"RANDOM_POOL_OVERFLOW", ERR_LIB_RAND, RAND_R_RANDOM_POOL_OVERFLOW}, - #else - {"RANDOM_POOL_OVERFLOW", 36, 125}, - #endif - #ifdef RAND_R_RANDOM_POOL_UNDERFLOW - {"RANDOM_POOL_UNDERFLOW", ERR_LIB_RAND, RAND_R_RANDOM_POOL_UNDERFLOW}, - #else - {"RANDOM_POOL_UNDERFLOW", 36, 134}, - #endif - #ifdef RAND_R_REQUEST_TOO_LARGE_FOR_DRBG - {"REQUEST_TOO_LARGE_FOR_DRBG", ERR_LIB_RAND, RAND_R_REQUEST_TOO_LARGE_FOR_DRBG}, - #else - {"REQUEST_TOO_LARGE_FOR_DRBG", 36, 117}, - #endif - #ifdef RAND_R_RESEED_ERROR - {"RESEED_ERROR", ERR_LIB_RAND, RAND_R_RESEED_ERROR}, - #else - {"RESEED_ERROR", 36, 118}, - #endif - #ifdef RAND_R_SELFTEST_FAILURE - {"SELFTEST_FAILURE", ERR_LIB_RAND, RAND_R_SELFTEST_FAILURE}, - #else - {"SELFTEST_FAILURE", 36, 119}, - #endif - #ifdef RAND_R_TOO_LITTLE_NONCE_REQUESTED - {"TOO_LITTLE_NONCE_REQUESTED", ERR_LIB_RAND, RAND_R_TOO_LITTLE_NONCE_REQUESTED}, - #else - {"TOO_LITTLE_NONCE_REQUESTED", 36, 135}, - #endif - #ifdef RAND_R_TOO_MUCH_NONCE_REQUESTED - {"TOO_MUCH_NONCE_REQUESTED", ERR_LIB_RAND, RAND_R_TOO_MUCH_NONCE_REQUESTED}, - #else - {"TOO_MUCH_NONCE_REQUESTED", 36, 136}, - #endif - #ifdef RAND_R_UNSUPPORTED_DRBG_FLAGS - {"UNSUPPORTED_DRBG_FLAGS", ERR_LIB_RAND, RAND_R_UNSUPPORTED_DRBG_FLAGS}, - #else - {"UNSUPPORTED_DRBG_FLAGS", 36, 132}, - #endif - #ifdef RAND_R_UNSUPPORTED_DRBG_TYPE - {"UNSUPPORTED_DRBG_TYPE", ERR_LIB_RAND, RAND_R_UNSUPPORTED_DRBG_TYPE}, - #else - {"UNSUPPORTED_DRBG_TYPE", 36, 120}, - #endif - #ifdef RSA_R_ALGORITHM_MISMATCH - {"ALGORITHM_MISMATCH", ERR_LIB_RSA, RSA_R_ALGORITHM_MISMATCH}, - #else - {"ALGORITHM_MISMATCH", 4, 100}, - #endif - #ifdef RSA_R_BAD_E_VALUE - {"BAD_E_VALUE", ERR_LIB_RSA, RSA_R_BAD_E_VALUE}, - #else - {"BAD_E_VALUE", 4, 101}, - #endif - #ifdef RSA_R_BAD_FIXED_HEADER_DECRYPT - {"BAD_FIXED_HEADER_DECRYPT", ERR_LIB_RSA, RSA_R_BAD_FIXED_HEADER_DECRYPT}, - #else - {"BAD_FIXED_HEADER_DECRYPT", 4, 102}, - #endif - #ifdef RSA_R_BAD_PAD_BYTE_COUNT - {"BAD_PAD_BYTE_COUNT", ERR_LIB_RSA, RSA_R_BAD_PAD_BYTE_COUNT}, - #else - {"BAD_PAD_BYTE_COUNT", 4, 103}, - #endif - #ifdef RSA_R_BAD_SIGNATURE - {"BAD_SIGNATURE", ERR_LIB_RSA, RSA_R_BAD_SIGNATURE}, - #else - {"BAD_SIGNATURE", 4, 104}, - #endif - #ifdef RSA_R_BLOCK_TYPE_IS_NOT_01 - {"BLOCK_TYPE_IS_NOT_01", ERR_LIB_RSA, RSA_R_BLOCK_TYPE_IS_NOT_01}, - #else - {"BLOCK_TYPE_IS_NOT_01", 4, 106}, - #endif - #ifdef RSA_R_BLOCK_TYPE_IS_NOT_02 - {"BLOCK_TYPE_IS_NOT_02", ERR_LIB_RSA, RSA_R_BLOCK_TYPE_IS_NOT_02}, - #else - {"BLOCK_TYPE_IS_NOT_02", 4, 107}, - #endif - #ifdef RSA_R_DATA_GREATER_THAN_MOD_LEN - {"DATA_GREATER_THAN_MOD_LEN", ERR_LIB_RSA, RSA_R_DATA_GREATER_THAN_MOD_LEN}, - #else - {"DATA_GREATER_THAN_MOD_LEN", 4, 108}, - #endif - #ifdef RSA_R_DATA_TOO_LARGE - {"DATA_TOO_LARGE", ERR_LIB_RSA, RSA_R_DATA_TOO_LARGE}, - #else - {"DATA_TOO_LARGE", 4, 109}, - #endif - #ifdef RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE - {"DATA_TOO_LARGE_FOR_KEY_SIZE", ERR_LIB_RSA, RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE}, - #else - {"DATA_TOO_LARGE_FOR_KEY_SIZE", 4, 110}, - #endif - #ifdef RSA_R_DATA_TOO_LARGE_FOR_MODULUS - {"DATA_TOO_LARGE_FOR_MODULUS", ERR_LIB_RSA, RSA_R_DATA_TOO_LARGE_FOR_MODULUS}, - #else - {"DATA_TOO_LARGE_FOR_MODULUS", 4, 132}, - #endif - #ifdef RSA_R_DATA_TOO_SMALL - {"DATA_TOO_SMALL", ERR_LIB_RSA, RSA_R_DATA_TOO_SMALL}, - #else - {"DATA_TOO_SMALL", 4, 111}, - #endif - #ifdef RSA_R_DATA_TOO_SMALL_FOR_KEY_SIZE - {"DATA_TOO_SMALL_FOR_KEY_SIZE", ERR_LIB_RSA, RSA_R_DATA_TOO_SMALL_FOR_KEY_SIZE}, - #else - {"DATA_TOO_SMALL_FOR_KEY_SIZE", 4, 122}, - #endif - #ifdef RSA_R_DIGEST_DOES_NOT_MATCH - {"DIGEST_DOES_NOT_MATCH", ERR_LIB_RSA, RSA_R_DIGEST_DOES_NOT_MATCH}, - #else - {"DIGEST_DOES_NOT_MATCH", 4, 158}, - #endif - #ifdef RSA_R_DIGEST_NOT_ALLOWED - {"DIGEST_NOT_ALLOWED", ERR_LIB_RSA, RSA_R_DIGEST_NOT_ALLOWED}, - #else - {"DIGEST_NOT_ALLOWED", 4, 145}, - #endif - #ifdef RSA_R_DIGEST_TOO_BIG_FOR_RSA_KEY - {"DIGEST_TOO_BIG_FOR_RSA_KEY", ERR_LIB_RSA, RSA_R_DIGEST_TOO_BIG_FOR_RSA_KEY}, - #else - {"DIGEST_TOO_BIG_FOR_RSA_KEY", 4, 112}, - #endif - #ifdef RSA_R_DMP1_NOT_CONGRUENT_TO_D - {"DMP1_NOT_CONGRUENT_TO_D", ERR_LIB_RSA, RSA_R_DMP1_NOT_CONGRUENT_TO_D}, - #else - {"DMP1_NOT_CONGRUENT_TO_D", 4, 124}, - #endif - #ifdef RSA_R_DMQ1_NOT_CONGRUENT_TO_D - {"DMQ1_NOT_CONGRUENT_TO_D", ERR_LIB_RSA, RSA_R_DMQ1_NOT_CONGRUENT_TO_D}, - #else - {"DMQ1_NOT_CONGRUENT_TO_D", 4, 125}, - #endif - #ifdef RSA_R_D_E_NOT_CONGRUENT_TO_1 - {"D_E_NOT_CONGRUENT_TO_1", ERR_LIB_RSA, RSA_R_D_E_NOT_CONGRUENT_TO_1}, - #else - {"D_E_NOT_CONGRUENT_TO_1", 4, 123}, - #endif - #ifdef RSA_R_FIRST_OCTET_INVALID - {"FIRST_OCTET_INVALID", ERR_LIB_RSA, RSA_R_FIRST_OCTET_INVALID}, - #else - {"FIRST_OCTET_INVALID", 4, 133}, - #endif - #ifdef RSA_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE - {"ILLEGAL_OR_UNSUPPORTED_PADDING_MODE", ERR_LIB_RSA, RSA_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE}, - #else - {"ILLEGAL_OR_UNSUPPORTED_PADDING_MODE", 4, 144}, - #endif - #ifdef RSA_R_INVALID_DIGEST - {"INVALID_DIGEST", ERR_LIB_RSA, RSA_R_INVALID_DIGEST}, - #else - {"INVALID_DIGEST", 4, 157}, - #endif - #ifdef RSA_R_INVALID_DIGEST_LENGTH - {"INVALID_DIGEST_LENGTH", ERR_LIB_RSA, RSA_R_INVALID_DIGEST_LENGTH}, - #else - {"INVALID_DIGEST_LENGTH", 4, 143}, - #endif - #ifdef RSA_R_INVALID_HEADER - {"INVALID_HEADER", ERR_LIB_RSA, RSA_R_INVALID_HEADER}, - #else - {"INVALID_HEADER", 4, 137}, - #endif - #ifdef RSA_R_INVALID_LABEL - {"INVALID_LABEL", ERR_LIB_RSA, RSA_R_INVALID_LABEL}, - #else - {"INVALID_LABEL", 4, 160}, - #endif - #ifdef RSA_R_INVALID_MESSAGE_LENGTH - {"INVALID_MESSAGE_LENGTH", ERR_LIB_RSA, RSA_R_INVALID_MESSAGE_LENGTH}, - #else - {"INVALID_MESSAGE_LENGTH", 4, 131}, - #endif - #ifdef RSA_R_INVALID_MGF1_MD - {"INVALID_MGF1_MD", ERR_LIB_RSA, RSA_R_INVALID_MGF1_MD}, - #else - {"INVALID_MGF1_MD", 4, 156}, - #endif - #ifdef RSA_R_INVALID_MULTI_PRIME_KEY - {"INVALID_MULTI_PRIME_KEY", ERR_LIB_RSA, RSA_R_INVALID_MULTI_PRIME_KEY}, - #else - {"INVALID_MULTI_PRIME_KEY", 4, 167}, - #endif - #ifdef RSA_R_INVALID_OAEP_PARAMETERS - {"INVALID_OAEP_PARAMETERS", ERR_LIB_RSA, RSA_R_INVALID_OAEP_PARAMETERS}, - #else - {"INVALID_OAEP_PARAMETERS", 4, 161}, - #endif - #ifdef RSA_R_INVALID_PADDING - {"INVALID_PADDING", ERR_LIB_RSA, RSA_R_INVALID_PADDING}, - #else - {"INVALID_PADDING", 4, 138}, - #endif - #ifdef RSA_R_INVALID_PADDING_MODE - {"INVALID_PADDING_MODE", ERR_LIB_RSA, RSA_R_INVALID_PADDING_MODE}, - #else - {"INVALID_PADDING_MODE", 4, 141}, - #endif - #ifdef RSA_R_INVALID_PSS_PARAMETERS - {"INVALID_PSS_PARAMETERS", ERR_LIB_RSA, RSA_R_INVALID_PSS_PARAMETERS}, - #else - {"INVALID_PSS_PARAMETERS", 4, 149}, - #endif - #ifdef RSA_R_INVALID_PSS_SALTLEN - {"INVALID_PSS_SALTLEN", ERR_LIB_RSA, RSA_R_INVALID_PSS_SALTLEN}, - #else - {"INVALID_PSS_SALTLEN", 4, 146}, - #endif - #ifdef RSA_R_INVALID_SALT_LENGTH - {"INVALID_SALT_LENGTH", ERR_LIB_RSA, RSA_R_INVALID_SALT_LENGTH}, - #else - {"INVALID_SALT_LENGTH", 4, 150}, - #endif - #ifdef RSA_R_INVALID_TRAILER - {"INVALID_TRAILER", ERR_LIB_RSA, RSA_R_INVALID_TRAILER}, - #else - {"INVALID_TRAILER", 4, 139}, - #endif - #ifdef RSA_R_INVALID_X931_DIGEST - {"INVALID_X931_DIGEST", ERR_LIB_RSA, RSA_R_INVALID_X931_DIGEST}, - #else - {"INVALID_X931_DIGEST", 4, 142}, - #endif - #ifdef RSA_R_IQMP_NOT_INVERSE_OF_Q - {"IQMP_NOT_INVERSE_OF_Q", ERR_LIB_RSA, RSA_R_IQMP_NOT_INVERSE_OF_Q}, - #else - {"IQMP_NOT_INVERSE_OF_Q", 4, 126}, - #endif - #ifdef RSA_R_KEY_PRIME_NUM_INVALID - {"KEY_PRIME_NUM_INVALID", ERR_LIB_RSA, RSA_R_KEY_PRIME_NUM_INVALID}, - #else - {"KEY_PRIME_NUM_INVALID", 4, 165}, - #endif - #ifdef RSA_R_KEY_SIZE_TOO_SMALL - {"KEY_SIZE_TOO_SMALL", ERR_LIB_RSA, RSA_R_KEY_SIZE_TOO_SMALL}, - #else - {"KEY_SIZE_TOO_SMALL", 4, 120}, - #endif - #ifdef RSA_R_LAST_OCTET_INVALID - {"LAST_OCTET_INVALID", ERR_LIB_RSA, RSA_R_LAST_OCTET_INVALID}, - #else - {"LAST_OCTET_INVALID", 4, 134}, - #endif - #ifdef RSA_R_MGF1_DIGEST_NOT_ALLOWED - {"MGF1_DIGEST_NOT_ALLOWED", ERR_LIB_RSA, RSA_R_MGF1_DIGEST_NOT_ALLOWED}, - #else - {"MGF1_DIGEST_NOT_ALLOWED", 4, 152}, - #endif - #ifdef RSA_R_MISSING_PRIVATE_KEY - {"MISSING_PRIVATE_KEY", ERR_LIB_RSA, RSA_R_MISSING_PRIVATE_KEY}, - #else - {"MISSING_PRIVATE_KEY", 4, 179}, - #endif - #ifdef RSA_R_MODULUS_TOO_LARGE - {"MODULUS_TOO_LARGE", ERR_LIB_RSA, RSA_R_MODULUS_TOO_LARGE}, - #else - {"MODULUS_TOO_LARGE", 4, 105}, - #endif - #ifdef RSA_R_MP_COEFFICIENT_NOT_INVERSE_OF_R - {"MP_COEFFICIENT_NOT_INVERSE_OF_R", ERR_LIB_RSA, RSA_R_MP_COEFFICIENT_NOT_INVERSE_OF_R}, - #else - {"MP_COEFFICIENT_NOT_INVERSE_OF_R", 4, 168}, - #endif - #ifdef RSA_R_MP_EXPONENT_NOT_CONGRUENT_TO_D - {"MP_EXPONENT_NOT_CONGRUENT_TO_D", ERR_LIB_RSA, RSA_R_MP_EXPONENT_NOT_CONGRUENT_TO_D}, - #else - {"MP_EXPONENT_NOT_CONGRUENT_TO_D", 4, 169}, - #endif - #ifdef RSA_R_MP_R_NOT_PRIME - {"MP_R_NOT_PRIME", ERR_LIB_RSA, RSA_R_MP_R_NOT_PRIME}, - #else - {"MP_R_NOT_PRIME", 4, 170}, - #endif - #ifdef RSA_R_NO_PUBLIC_EXPONENT - {"NO_PUBLIC_EXPONENT", ERR_LIB_RSA, RSA_R_NO_PUBLIC_EXPONENT}, - #else - {"NO_PUBLIC_EXPONENT", 4, 140}, - #endif - #ifdef RSA_R_NULL_BEFORE_BLOCK_MISSING - {"NULL_BEFORE_BLOCK_MISSING", ERR_LIB_RSA, RSA_R_NULL_BEFORE_BLOCK_MISSING}, - #else - {"NULL_BEFORE_BLOCK_MISSING", 4, 113}, - #endif - #ifdef RSA_R_N_DOES_NOT_EQUAL_PRODUCT_OF_PRIMES - {"N_DOES_NOT_EQUAL_PRODUCT_OF_PRIMES", ERR_LIB_RSA, RSA_R_N_DOES_NOT_EQUAL_PRODUCT_OF_PRIMES}, - #else - {"N_DOES_NOT_EQUAL_PRODUCT_OF_PRIMES", 4, 172}, - #endif - #ifdef RSA_R_N_DOES_NOT_EQUAL_P_Q - {"N_DOES_NOT_EQUAL_P_Q", ERR_LIB_RSA, RSA_R_N_DOES_NOT_EQUAL_P_Q}, - #else - {"N_DOES_NOT_EQUAL_P_Q", 4, 127}, - #endif - #ifdef RSA_R_OAEP_DECODING_ERROR - {"OAEP_DECODING_ERROR", ERR_LIB_RSA, RSA_R_OAEP_DECODING_ERROR}, - #else - {"OAEP_DECODING_ERROR", 4, 121}, - #endif - #ifdef RSA_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE - {"OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE", ERR_LIB_RSA, RSA_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE}, - #else - {"OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE", 4, 148}, - #endif - #ifdef RSA_R_PADDING_CHECK_FAILED - {"PADDING_CHECK_FAILED", ERR_LIB_RSA, RSA_R_PADDING_CHECK_FAILED}, - #else - {"PADDING_CHECK_FAILED", 4, 114}, - #endif - #ifdef RSA_R_PKCS_DECODING_ERROR - {"PKCS_DECODING_ERROR", ERR_LIB_RSA, RSA_R_PKCS_DECODING_ERROR}, - #else - {"PKCS_DECODING_ERROR", 4, 159}, - #endif - #ifdef RSA_R_PSS_SALTLEN_TOO_SMALL - {"PSS_SALTLEN_TOO_SMALL", ERR_LIB_RSA, RSA_R_PSS_SALTLEN_TOO_SMALL}, - #else - {"PSS_SALTLEN_TOO_SMALL", 4, 164}, - #endif - #ifdef RSA_R_P_NOT_PRIME - {"P_NOT_PRIME", ERR_LIB_RSA, RSA_R_P_NOT_PRIME}, - #else - {"P_NOT_PRIME", 4, 128}, - #endif - #ifdef RSA_R_Q_NOT_PRIME - {"Q_NOT_PRIME", ERR_LIB_RSA, RSA_R_Q_NOT_PRIME}, - #else - {"Q_NOT_PRIME", 4, 129}, - #endif - #ifdef RSA_R_RSA_OPERATIONS_NOT_SUPPORTED - {"RSA_OPERATIONS_NOT_SUPPORTED", ERR_LIB_RSA, RSA_R_RSA_OPERATIONS_NOT_SUPPORTED}, - #else - {"RSA_OPERATIONS_NOT_SUPPORTED", 4, 130}, - #endif - #ifdef RSA_R_SLEN_CHECK_FAILED - {"SLEN_CHECK_FAILED", ERR_LIB_RSA, RSA_R_SLEN_CHECK_FAILED}, - #else - {"SLEN_CHECK_FAILED", 4, 136}, - #endif - #ifdef RSA_R_SLEN_RECOVERY_FAILED - {"SLEN_RECOVERY_FAILED", ERR_LIB_RSA, RSA_R_SLEN_RECOVERY_FAILED}, - #else - {"SLEN_RECOVERY_FAILED", 4, 135}, - #endif - #ifdef RSA_R_SSLV3_ROLLBACK_ATTACK - {"SSLV3_ROLLBACK_ATTACK", ERR_LIB_RSA, RSA_R_SSLV3_ROLLBACK_ATTACK}, - #else - {"SSLV3_ROLLBACK_ATTACK", 4, 115}, - #endif - #ifdef RSA_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD - {"THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD", ERR_LIB_RSA, RSA_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD}, - #else - {"THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD", 4, 116}, - #endif - #ifdef RSA_R_UNKNOWN_ALGORITHM_TYPE - {"UNKNOWN_ALGORITHM_TYPE", ERR_LIB_RSA, RSA_R_UNKNOWN_ALGORITHM_TYPE}, - #else - {"UNKNOWN_ALGORITHM_TYPE", 4, 117}, - #endif - #ifdef RSA_R_UNKNOWN_DIGEST - {"UNKNOWN_DIGEST", ERR_LIB_RSA, RSA_R_UNKNOWN_DIGEST}, - #else - {"UNKNOWN_DIGEST", 4, 166}, - #endif - #ifdef RSA_R_UNKNOWN_MASK_DIGEST - {"UNKNOWN_MASK_DIGEST", ERR_LIB_RSA, RSA_R_UNKNOWN_MASK_DIGEST}, - #else - {"UNKNOWN_MASK_DIGEST", 4, 151}, - #endif - #ifdef RSA_R_UNKNOWN_PADDING_TYPE - {"UNKNOWN_PADDING_TYPE", ERR_LIB_RSA, RSA_R_UNKNOWN_PADDING_TYPE}, - #else - {"UNKNOWN_PADDING_TYPE", 4, 118}, - #endif - #ifdef RSA_R_UNSUPPORTED_ENCRYPTION_TYPE - {"UNSUPPORTED_ENCRYPTION_TYPE", ERR_LIB_RSA, RSA_R_UNSUPPORTED_ENCRYPTION_TYPE}, - #else - {"UNSUPPORTED_ENCRYPTION_TYPE", 4, 162}, - #endif - #ifdef RSA_R_UNSUPPORTED_LABEL_SOURCE - {"UNSUPPORTED_LABEL_SOURCE", ERR_LIB_RSA, RSA_R_UNSUPPORTED_LABEL_SOURCE}, - #else - {"UNSUPPORTED_LABEL_SOURCE", 4, 163}, - #endif - #ifdef RSA_R_UNSUPPORTED_MASK_ALGORITHM - {"UNSUPPORTED_MASK_ALGORITHM", ERR_LIB_RSA, RSA_R_UNSUPPORTED_MASK_ALGORITHM}, - #else - {"UNSUPPORTED_MASK_ALGORITHM", 4, 153}, - #endif - #ifdef RSA_R_UNSUPPORTED_MASK_PARAMETER - {"UNSUPPORTED_MASK_PARAMETER", ERR_LIB_RSA, RSA_R_UNSUPPORTED_MASK_PARAMETER}, - #else - {"UNSUPPORTED_MASK_PARAMETER", 4, 154}, - #endif - #ifdef RSA_R_UNSUPPORTED_SIGNATURE_TYPE - {"UNSUPPORTED_SIGNATURE_TYPE", ERR_LIB_RSA, RSA_R_UNSUPPORTED_SIGNATURE_TYPE}, - #else - {"UNSUPPORTED_SIGNATURE_TYPE", 4, 155}, - #endif - #ifdef RSA_R_VALUE_MISSING - {"VALUE_MISSING", ERR_LIB_RSA, RSA_R_VALUE_MISSING}, - #else - {"VALUE_MISSING", 4, 147}, - #endif - #ifdef RSA_R_WRONG_SIGNATURE_LENGTH - {"WRONG_SIGNATURE_LENGTH", ERR_LIB_RSA, RSA_R_WRONG_SIGNATURE_LENGTH}, - #else - {"WRONG_SIGNATURE_LENGTH", 4, 119}, - #endif - #ifdef SSL_R_APPLICATION_DATA_AFTER_CLOSE_NOTIFY - {"APPLICATION_DATA_AFTER_CLOSE_NOTIFY", ERR_LIB_SSL, SSL_R_APPLICATION_DATA_AFTER_CLOSE_NOTIFY}, - #else - {"APPLICATION_DATA_AFTER_CLOSE_NOTIFY", 20, 291}, - #endif - #ifdef SSL_R_APP_DATA_IN_HANDSHAKE - {"APP_DATA_IN_HANDSHAKE", ERR_LIB_SSL, SSL_R_APP_DATA_IN_HANDSHAKE}, - #else - {"APP_DATA_IN_HANDSHAKE", 20, 100}, - #endif - #ifdef SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT - {"ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT", ERR_LIB_SSL, SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT}, - #else - {"ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT", 20, 272}, - #endif - #ifdef SSL_R_AT_LEAST_TLS_1_0_NEEDED_IN_FIPS_MODE - {"AT_LEAST_TLS_1_0_NEEDED_IN_FIPS_MODE", ERR_LIB_SSL, SSL_R_AT_LEAST_TLS_1_0_NEEDED_IN_FIPS_MODE}, - #else - {"AT_LEAST_TLS_1_0_NEEDED_IN_FIPS_MODE", 20, 143}, - #endif - #ifdef SSL_R_AT_LEAST_TLS_1_2_NEEDED_IN_SUITEB_MODE - {"AT_LEAST_TLS_1_2_NEEDED_IN_SUITEB_MODE", ERR_LIB_SSL, SSL_R_AT_LEAST_TLS_1_2_NEEDED_IN_SUITEB_MODE}, - #else - {"AT_LEAST_TLS_1_2_NEEDED_IN_SUITEB_MODE", 20, 158}, - #endif - #ifdef SSL_R_BAD_CHANGE_CIPHER_SPEC - {"BAD_CHANGE_CIPHER_SPEC", ERR_LIB_SSL, SSL_R_BAD_CHANGE_CIPHER_SPEC}, - #else - {"BAD_CHANGE_CIPHER_SPEC", 20, 103}, - #endif - #ifdef SSL_R_BAD_CIPHER - {"BAD_CIPHER", ERR_LIB_SSL, SSL_R_BAD_CIPHER}, - #else - {"BAD_CIPHER", 20, 186}, - #endif - #ifdef SSL_R_BAD_DATA - {"BAD_DATA", ERR_LIB_SSL, SSL_R_BAD_DATA}, - #else - {"BAD_DATA", 20, 390}, - #endif - #ifdef SSL_R_BAD_DATA_RETURNED_BY_CALLBACK - {"BAD_DATA_RETURNED_BY_CALLBACK", ERR_LIB_SSL, SSL_R_BAD_DATA_RETURNED_BY_CALLBACK}, - #else - {"BAD_DATA_RETURNED_BY_CALLBACK", 20, 106}, - #endif - #ifdef SSL_R_BAD_DECOMPRESSION - {"BAD_DECOMPRESSION", ERR_LIB_SSL, SSL_R_BAD_DECOMPRESSION}, - #else - {"BAD_DECOMPRESSION", 20, 107}, - #endif - #ifdef SSL_R_BAD_DH_VALUE - {"BAD_DH_VALUE", ERR_LIB_SSL, SSL_R_BAD_DH_VALUE}, - #else - {"BAD_DH_VALUE", 20, 102}, - #endif - #ifdef SSL_R_BAD_DIGEST_LENGTH - {"BAD_DIGEST_LENGTH", ERR_LIB_SSL, SSL_R_BAD_DIGEST_LENGTH}, - #else - {"BAD_DIGEST_LENGTH", 20, 111}, - #endif - #ifdef SSL_R_BAD_EARLY_DATA - {"BAD_EARLY_DATA", ERR_LIB_SSL, SSL_R_BAD_EARLY_DATA}, - #else - {"BAD_EARLY_DATA", 20, 233}, - #endif - #ifdef SSL_R_BAD_ECC_CERT - {"BAD_ECC_CERT", ERR_LIB_SSL, SSL_R_BAD_ECC_CERT}, - #else - {"BAD_ECC_CERT", 20, 304}, - #endif - #ifdef SSL_R_BAD_ECDSA_SIGNATURE - {"BAD_ECDSA_SIGNATURE", ERR_LIB_SSL, SSL_R_BAD_ECDSA_SIGNATURE}, - #else - {"BAD_ECDSA_SIGNATURE", 20, 305}, - #endif - #ifdef SSL_R_BAD_ECPOINT - {"BAD_ECPOINT", ERR_LIB_SSL, SSL_R_BAD_ECPOINT}, - #else - {"BAD_ECPOINT", 20, 306}, - #endif - #ifdef SSL_R_BAD_EXTENSION - {"BAD_EXTENSION", ERR_LIB_SSL, SSL_R_BAD_EXTENSION}, - #else - {"BAD_EXTENSION", 20, 110}, - #endif - #ifdef SSL_R_BAD_HANDSHAKE_LENGTH - {"BAD_HANDSHAKE_LENGTH", ERR_LIB_SSL, SSL_R_BAD_HANDSHAKE_LENGTH}, - #else - {"BAD_HANDSHAKE_LENGTH", 20, 332}, - #endif - #ifdef SSL_R_BAD_HANDSHAKE_STATE - {"BAD_HANDSHAKE_STATE", ERR_LIB_SSL, SSL_R_BAD_HANDSHAKE_STATE}, - #else - {"BAD_HANDSHAKE_STATE", 20, 236}, - #endif - #ifdef SSL_R_BAD_HELLO_REQUEST - {"BAD_HELLO_REQUEST", ERR_LIB_SSL, SSL_R_BAD_HELLO_REQUEST}, - #else - {"BAD_HELLO_REQUEST", 20, 105}, - #endif - #ifdef SSL_R_BAD_HRR_VERSION - {"BAD_HRR_VERSION", ERR_LIB_SSL, SSL_R_BAD_HRR_VERSION}, - #else - {"BAD_HRR_VERSION", 20, 263}, - #endif - #ifdef SSL_R_BAD_KEY_SHARE - {"BAD_KEY_SHARE", ERR_LIB_SSL, SSL_R_BAD_KEY_SHARE}, - #else - {"BAD_KEY_SHARE", 20, 108}, - #endif - #ifdef SSL_R_BAD_KEY_UPDATE - {"BAD_KEY_UPDATE", ERR_LIB_SSL, SSL_R_BAD_KEY_UPDATE}, - #else - {"BAD_KEY_UPDATE", 20, 122}, - #endif - #ifdef SSL_R_BAD_LEGACY_VERSION - {"BAD_LEGACY_VERSION", ERR_LIB_SSL, SSL_R_BAD_LEGACY_VERSION}, - #else - {"BAD_LEGACY_VERSION", 20, 292}, - #endif - #ifdef SSL_R_BAD_LENGTH - {"BAD_LENGTH", ERR_LIB_SSL, SSL_R_BAD_LENGTH}, - #else - {"BAD_LENGTH", 20, 271}, - #endif - #ifdef SSL_R_BAD_MAC_LENGTH - {"BAD_MAC_LENGTH", ERR_LIB_SSL, SSL_R_BAD_MAC_LENGTH}, - #else - {"BAD_MAC_LENGTH", 20, 333}, - #endif - #ifdef SSL_R_BAD_PACKET - {"BAD_PACKET", ERR_LIB_SSL, SSL_R_BAD_PACKET}, - #else - {"BAD_PACKET", 20, 240}, - #endif - #ifdef SSL_R_BAD_PACKET_LENGTH - {"BAD_PACKET_LENGTH", ERR_LIB_SSL, SSL_R_BAD_PACKET_LENGTH}, - #else - {"BAD_PACKET_LENGTH", 20, 115}, - #endif - #ifdef SSL_R_BAD_PROTOCOL_VERSION_NUMBER - {"BAD_PROTOCOL_VERSION_NUMBER", ERR_LIB_SSL, SSL_R_BAD_PROTOCOL_VERSION_NUMBER}, - #else - {"BAD_PROTOCOL_VERSION_NUMBER", 20, 116}, - #endif - #ifdef SSL_R_BAD_PSK - {"BAD_PSK", ERR_LIB_SSL, SSL_R_BAD_PSK}, - #else - {"BAD_PSK", 20, 219}, - #endif - #ifdef SSL_R_BAD_PSK_IDENTITY - {"BAD_PSK_IDENTITY", ERR_LIB_SSL, SSL_R_BAD_PSK_IDENTITY}, - #else - {"BAD_PSK_IDENTITY", 20, 114}, - #endif - #ifdef SSL_R_BAD_PSK_IDENTITY_HINT_LENGTH - {"BAD_PSK_IDENTITY_HINT_LENGTH", ERR_LIB_SSL, SSL_R_BAD_PSK_IDENTITY_HINT_LENGTH}, - #else - {"BAD_PSK_IDENTITY_HINT_LENGTH", 20, 316}, - #endif - #ifdef SSL_R_BAD_RECORD_TYPE - {"BAD_RECORD_TYPE", ERR_LIB_SSL, SSL_R_BAD_RECORD_TYPE}, - #else - {"BAD_RECORD_TYPE", 20, 443}, - #endif - #ifdef SSL_R_BAD_RSA_ENCRYPT - {"BAD_RSA_ENCRYPT", ERR_LIB_SSL, SSL_R_BAD_RSA_ENCRYPT}, - #else - {"BAD_RSA_ENCRYPT", 20, 119}, - #endif - #ifdef SSL_R_BAD_SIGNATURE - {"BAD_SIGNATURE", ERR_LIB_SSL, SSL_R_BAD_SIGNATURE}, - #else - {"BAD_SIGNATURE", 20, 123}, - #endif - #ifdef SSL_R_BAD_SRP_A_LENGTH - {"BAD_SRP_A_LENGTH", ERR_LIB_SSL, SSL_R_BAD_SRP_A_LENGTH}, - #else - {"BAD_SRP_A_LENGTH", 20, 347}, - #endif - #ifdef SSL_R_BAD_SRP_B_LENGTH - {"BAD_SRP_B_LENGTH", ERR_LIB_SSL, SSL_R_BAD_SRP_B_LENGTH}, - #else - {"BAD_SRP_B_LENGTH", 20, 348}, - #endif - #ifdef SSL_R_BAD_SRP_G_LENGTH - {"BAD_SRP_G_LENGTH", ERR_LIB_SSL, SSL_R_BAD_SRP_G_LENGTH}, - #else - {"BAD_SRP_G_LENGTH", 20, 349}, - #endif - #ifdef SSL_R_BAD_SRP_N_LENGTH - {"BAD_SRP_N_LENGTH", ERR_LIB_SSL, SSL_R_BAD_SRP_N_LENGTH}, - #else - {"BAD_SRP_N_LENGTH", 20, 350}, - #endif - #ifdef SSL_R_BAD_SRP_PARAMETERS - {"BAD_SRP_PARAMETERS", ERR_LIB_SSL, SSL_R_BAD_SRP_PARAMETERS}, - #else - {"BAD_SRP_PARAMETERS", 20, 371}, - #endif - #ifdef SSL_R_BAD_SRP_S_LENGTH - {"BAD_SRP_S_LENGTH", ERR_LIB_SSL, SSL_R_BAD_SRP_S_LENGTH}, - #else - {"BAD_SRP_S_LENGTH", 20, 351}, - #endif - #ifdef SSL_R_BAD_SRTP_MKI_VALUE - {"BAD_SRTP_MKI_VALUE", ERR_LIB_SSL, SSL_R_BAD_SRTP_MKI_VALUE}, - #else - {"BAD_SRTP_MKI_VALUE", 20, 352}, - #endif - #ifdef SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST - {"BAD_SRTP_PROTECTION_PROFILE_LIST", ERR_LIB_SSL, SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST}, - #else - {"BAD_SRTP_PROTECTION_PROFILE_LIST", 20, 353}, - #endif - #ifdef SSL_R_BAD_SSL_FILETYPE - {"BAD_SSL_FILETYPE", ERR_LIB_SSL, SSL_R_BAD_SSL_FILETYPE}, - #else - {"BAD_SSL_FILETYPE", 20, 124}, - #endif - #ifdef SSL_R_BAD_VALUE - {"BAD_VALUE", ERR_LIB_SSL, SSL_R_BAD_VALUE}, - #else - {"BAD_VALUE", 20, 384}, - #endif - #ifdef SSL_R_BAD_WRITE_RETRY - {"BAD_WRITE_RETRY", ERR_LIB_SSL, SSL_R_BAD_WRITE_RETRY}, - #else - {"BAD_WRITE_RETRY", 20, 127}, - #endif - #ifdef SSL_R_BINDER_DOES_NOT_VERIFY - {"BINDER_DOES_NOT_VERIFY", ERR_LIB_SSL, SSL_R_BINDER_DOES_NOT_VERIFY}, - #else - {"BINDER_DOES_NOT_VERIFY", 20, 253}, - #endif - #ifdef SSL_R_BIO_NOT_SET - {"BIO_NOT_SET", ERR_LIB_SSL, SSL_R_BIO_NOT_SET}, - #else - {"BIO_NOT_SET", 20, 128}, - #endif - #ifdef SSL_R_BLOCK_CIPHER_PAD_IS_WRONG - {"BLOCK_CIPHER_PAD_IS_WRONG", ERR_LIB_SSL, SSL_R_BLOCK_CIPHER_PAD_IS_WRONG}, - #else - {"BLOCK_CIPHER_PAD_IS_WRONG", 20, 129}, - #endif - #ifdef SSL_R_BN_LIB - {"BN_LIB", ERR_LIB_SSL, SSL_R_BN_LIB}, - #else - {"BN_LIB", 20, 130}, - #endif - #ifdef SSL_R_CALLBACK_FAILED - {"CALLBACK_FAILED", ERR_LIB_SSL, SSL_R_CALLBACK_FAILED}, - #else - {"CALLBACK_FAILED", 20, 234}, - #endif - #ifdef SSL_R_CANNOT_CHANGE_CIPHER - {"CANNOT_CHANGE_CIPHER", ERR_LIB_SSL, SSL_R_CANNOT_CHANGE_CIPHER}, - #else - {"CANNOT_CHANGE_CIPHER", 20, 109}, - #endif - #ifdef SSL_R_CA_DN_LENGTH_MISMATCH - {"CA_DN_LENGTH_MISMATCH", ERR_LIB_SSL, SSL_R_CA_DN_LENGTH_MISMATCH}, - #else - {"CA_DN_LENGTH_MISMATCH", 20, 131}, - #endif - #ifdef SSL_R_CA_KEY_TOO_SMALL - {"CA_KEY_TOO_SMALL", ERR_LIB_SSL, SSL_R_CA_KEY_TOO_SMALL}, - #else - {"CA_KEY_TOO_SMALL", 20, 397}, - #endif - #ifdef SSL_R_CA_MD_TOO_WEAK - {"CA_MD_TOO_WEAK", ERR_LIB_SSL, SSL_R_CA_MD_TOO_WEAK}, - #else - {"CA_MD_TOO_WEAK", 20, 398}, - #endif - #ifdef SSL_R_CCS_RECEIVED_EARLY - {"CCS_RECEIVED_EARLY", ERR_LIB_SSL, SSL_R_CCS_RECEIVED_EARLY}, - #else - {"CCS_RECEIVED_EARLY", 20, 133}, - #endif - #ifdef SSL_R_CERTIFICATE_VERIFY_FAILED - {"CERTIFICATE_VERIFY_FAILED", ERR_LIB_SSL, SSL_R_CERTIFICATE_VERIFY_FAILED}, - #else - {"CERTIFICATE_VERIFY_FAILED", 20, 134}, - #endif - #ifdef SSL_R_CERT_CB_ERROR - {"CERT_CB_ERROR", ERR_LIB_SSL, SSL_R_CERT_CB_ERROR}, - #else - {"CERT_CB_ERROR", 20, 377}, - #endif - #ifdef SSL_R_CERT_LENGTH_MISMATCH - {"CERT_LENGTH_MISMATCH", ERR_LIB_SSL, SSL_R_CERT_LENGTH_MISMATCH}, - #else - {"CERT_LENGTH_MISMATCH", 20, 135}, - #endif - #ifdef SSL_R_CIPHERSUITE_DIGEST_HAS_CHANGED - {"CIPHERSUITE_DIGEST_HAS_CHANGED", ERR_LIB_SSL, SSL_R_CIPHERSUITE_DIGEST_HAS_CHANGED}, - #else - {"CIPHERSUITE_DIGEST_HAS_CHANGED", 20, 218}, - #endif - #ifdef SSL_R_CIPHER_CODE_WRONG_LENGTH - {"CIPHER_CODE_WRONG_LENGTH", ERR_LIB_SSL, SSL_R_CIPHER_CODE_WRONG_LENGTH}, - #else - {"CIPHER_CODE_WRONG_LENGTH", 20, 137}, - #endif - #ifdef SSL_R_CIPHER_OR_HASH_UNAVAILABLE - {"CIPHER_OR_HASH_UNAVAILABLE", ERR_LIB_SSL, SSL_R_CIPHER_OR_HASH_UNAVAILABLE}, - #else - {"CIPHER_OR_HASH_UNAVAILABLE", 20, 138}, - #endif - #ifdef SSL_R_CLIENTHELLO_TLSEXT - {"CLIENTHELLO_TLSEXT", ERR_LIB_SSL, SSL_R_CLIENTHELLO_TLSEXT}, - #else - {"CLIENTHELLO_TLSEXT", 20, 226}, - #endif - #ifdef SSL_R_COMPRESSED_LENGTH_TOO_LONG - {"COMPRESSED_LENGTH_TOO_LONG", ERR_LIB_SSL, SSL_R_COMPRESSED_LENGTH_TOO_LONG}, - #else - {"COMPRESSED_LENGTH_TOO_LONG", 20, 140}, - #endif - #ifdef SSL_R_COMPRESSION_DISABLED - {"COMPRESSION_DISABLED", ERR_LIB_SSL, SSL_R_COMPRESSION_DISABLED}, - #else - {"COMPRESSION_DISABLED", 20, 343}, - #endif - #ifdef SSL_R_COMPRESSION_FAILURE - {"COMPRESSION_FAILURE", ERR_LIB_SSL, SSL_R_COMPRESSION_FAILURE}, - #else - {"COMPRESSION_FAILURE", 20, 141}, - #endif - #ifdef SSL_R_COMPRESSION_ID_NOT_WITHIN_PRIVATE_RANGE - {"COMPRESSION_ID_NOT_WITHIN_PRIVATE_RANGE", ERR_LIB_SSL, SSL_R_COMPRESSION_ID_NOT_WITHIN_PRIVATE_RANGE}, - #else - {"COMPRESSION_ID_NOT_WITHIN_PRIVATE_RANGE", 20, 307}, - #endif - #ifdef SSL_R_COMPRESSION_LIBRARY_ERROR - {"COMPRESSION_LIBRARY_ERROR", ERR_LIB_SSL, SSL_R_COMPRESSION_LIBRARY_ERROR}, - #else - {"COMPRESSION_LIBRARY_ERROR", 20, 142}, - #endif - #ifdef SSL_R_CONNECTION_TYPE_NOT_SET - {"CONNECTION_TYPE_NOT_SET", ERR_LIB_SSL, SSL_R_CONNECTION_TYPE_NOT_SET}, - #else - {"CONNECTION_TYPE_NOT_SET", 20, 144}, - #endif - #ifdef SSL_R_CONTEXT_NOT_DANE_ENABLED - {"CONTEXT_NOT_DANE_ENABLED", ERR_LIB_SSL, SSL_R_CONTEXT_NOT_DANE_ENABLED}, - #else - {"CONTEXT_NOT_DANE_ENABLED", 20, 167}, - #endif - #ifdef SSL_R_COOKIE_GEN_CALLBACK_FAILURE - {"COOKIE_GEN_CALLBACK_FAILURE", ERR_LIB_SSL, SSL_R_COOKIE_GEN_CALLBACK_FAILURE}, - #else - {"COOKIE_GEN_CALLBACK_FAILURE", 20, 400}, - #endif - #ifdef SSL_R_COOKIE_MISMATCH - {"COOKIE_MISMATCH", ERR_LIB_SSL, SSL_R_COOKIE_MISMATCH}, - #else - {"COOKIE_MISMATCH", 20, 308}, - #endif - #ifdef SSL_R_CUSTOM_EXT_HANDLER_ALREADY_INSTALLED - {"CUSTOM_EXT_HANDLER_ALREADY_INSTALLED", ERR_LIB_SSL, SSL_R_CUSTOM_EXT_HANDLER_ALREADY_INSTALLED}, - #else - {"CUSTOM_EXT_HANDLER_ALREADY_INSTALLED", 20, 206}, - #endif - #ifdef SSL_R_DANE_ALREADY_ENABLED - {"DANE_ALREADY_ENABLED", ERR_LIB_SSL, SSL_R_DANE_ALREADY_ENABLED}, - #else - {"DANE_ALREADY_ENABLED", 20, 172}, - #endif - #ifdef SSL_R_DANE_CANNOT_OVERRIDE_MTYPE_FULL - {"DANE_CANNOT_OVERRIDE_MTYPE_FULL", ERR_LIB_SSL, SSL_R_DANE_CANNOT_OVERRIDE_MTYPE_FULL}, - #else - {"DANE_CANNOT_OVERRIDE_MTYPE_FULL", 20, 173}, - #endif - #ifdef SSL_R_DANE_NOT_ENABLED - {"DANE_NOT_ENABLED", ERR_LIB_SSL, SSL_R_DANE_NOT_ENABLED}, - #else - {"DANE_NOT_ENABLED", 20, 175}, - #endif - #ifdef SSL_R_DANE_TLSA_BAD_CERTIFICATE - {"DANE_TLSA_BAD_CERTIFICATE", ERR_LIB_SSL, SSL_R_DANE_TLSA_BAD_CERTIFICATE}, - #else - {"DANE_TLSA_BAD_CERTIFICATE", 20, 180}, - #endif - #ifdef SSL_R_DANE_TLSA_BAD_CERTIFICATE_USAGE - {"DANE_TLSA_BAD_CERTIFICATE_USAGE", ERR_LIB_SSL, SSL_R_DANE_TLSA_BAD_CERTIFICATE_USAGE}, - #else - {"DANE_TLSA_BAD_CERTIFICATE_USAGE", 20, 184}, - #endif - #ifdef SSL_R_DANE_TLSA_BAD_DATA_LENGTH - {"DANE_TLSA_BAD_DATA_LENGTH", ERR_LIB_SSL, SSL_R_DANE_TLSA_BAD_DATA_LENGTH}, - #else - {"DANE_TLSA_BAD_DATA_LENGTH", 20, 189}, - #endif - #ifdef SSL_R_DANE_TLSA_BAD_DIGEST_LENGTH - {"DANE_TLSA_BAD_DIGEST_LENGTH", ERR_LIB_SSL, SSL_R_DANE_TLSA_BAD_DIGEST_LENGTH}, - #else - {"DANE_TLSA_BAD_DIGEST_LENGTH", 20, 192}, - #endif - #ifdef SSL_R_DANE_TLSA_BAD_MATCHING_TYPE - {"DANE_TLSA_BAD_MATCHING_TYPE", ERR_LIB_SSL, SSL_R_DANE_TLSA_BAD_MATCHING_TYPE}, - #else - {"DANE_TLSA_BAD_MATCHING_TYPE", 20, 200}, - #endif - #ifdef SSL_R_DANE_TLSA_BAD_PUBLIC_KEY - {"DANE_TLSA_BAD_PUBLIC_KEY", ERR_LIB_SSL, SSL_R_DANE_TLSA_BAD_PUBLIC_KEY}, - #else - {"DANE_TLSA_BAD_PUBLIC_KEY", 20, 201}, - #endif - #ifdef SSL_R_DANE_TLSA_BAD_SELECTOR - {"DANE_TLSA_BAD_SELECTOR", ERR_LIB_SSL, SSL_R_DANE_TLSA_BAD_SELECTOR}, - #else - {"DANE_TLSA_BAD_SELECTOR", 20, 202}, - #endif - #ifdef SSL_R_DANE_TLSA_NULL_DATA - {"DANE_TLSA_NULL_DATA", ERR_LIB_SSL, SSL_R_DANE_TLSA_NULL_DATA}, - #else - {"DANE_TLSA_NULL_DATA", 20, 203}, - #endif - #ifdef SSL_R_DATA_BETWEEN_CCS_AND_FINISHED - {"DATA_BETWEEN_CCS_AND_FINISHED", ERR_LIB_SSL, SSL_R_DATA_BETWEEN_CCS_AND_FINISHED}, - #else - {"DATA_BETWEEN_CCS_AND_FINISHED", 20, 145}, - #endif - #ifdef SSL_R_DATA_LENGTH_TOO_LONG - {"DATA_LENGTH_TOO_LONG", ERR_LIB_SSL, SSL_R_DATA_LENGTH_TOO_LONG}, - #else - {"DATA_LENGTH_TOO_LONG", 20, 146}, - #endif - #ifdef SSL_R_DECRYPTION_FAILED - {"DECRYPTION_FAILED", ERR_LIB_SSL, SSL_R_DECRYPTION_FAILED}, - #else - {"DECRYPTION_FAILED", 20, 147}, - #endif - #ifdef SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC - {"DECRYPTION_FAILED_OR_BAD_RECORD_MAC", ERR_LIB_SSL, SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC}, - #else - {"DECRYPTION_FAILED_OR_BAD_RECORD_MAC", 20, 281}, - #endif - #ifdef SSL_R_DH_KEY_TOO_SMALL - {"DH_KEY_TOO_SMALL", ERR_LIB_SSL, SSL_R_DH_KEY_TOO_SMALL}, - #else - {"DH_KEY_TOO_SMALL", 20, 394}, - #endif - #ifdef SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG - {"DH_PUBLIC_VALUE_LENGTH_IS_WRONG", ERR_LIB_SSL, SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG}, - #else - {"DH_PUBLIC_VALUE_LENGTH_IS_WRONG", 20, 148}, - #endif - #ifdef SSL_R_DIGEST_CHECK_FAILED - {"DIGEST_CHECK_FAILED", ERR_LIB_SSL, SSL_R_DIGEST_CHECK_FAILED}, - #else - {"DIGEST_CHECK_FAILED", 20, 149}, - #endif - #ifdef SSL_R_DTLS_MESSAGE_TOO_BIG - {"DTLS_MESSAGE_TOO_BIG", ERR_LIB_SSL, SSL_R_DTLS_MESSAGE_TOO_BIG}, - #else - {"DTLS_MESSAGE_TOO_BIG", 20, 334}, - #endif - #ifdef SSL_R_DUPLICATE_COMPRESSION_ID - {"DUPLICATE_COMPRESSION_ID", ERR_LIB_SSL, SSL_R_DUPLICATE_COMPRESSION_ID}, - #else - {"DUPLICATE_COMPRESSION_ID", 20, 309}, - #endif - #ifdef SSL_R_ECC_CERT_NOT_FOR_KEY_AGREEMENT - {"ECC_CERT_NOT_FOR_KEY_AGREEMENT", ERR_LIB_SSL, SSL_R_ECC_CERT_NOT_FOR_KEY_AGREEMENT}, - #else - {"ECC_CERT_NOT_FOR_KEY_AGREEMENT", 20, 317}, - #endif - #ifdef SSL_R_ECC_CERT_NOT_FOR_SIGNING - {"ECC_CERT_NOT_FOR_SIGNING", ERR_LIB_SSL, SSL_R_ECC_CERT_NOT_FOR_SIGNING}, - #else - {"ECC_CERT_NOT_FOR_SIGNING", 20, 318}, - #endif - #ifdef SSL_R_ECC_CERT_SHOULD_HAVE_RSA_SIGNATURE - {"ECC_CERT_SHOULD_HAVE_RSA_SIGNATURE", ERR_LIB_SSL, SSL_R_ECC_CERT_SHOULD_HAVE_RSA_SIGNATURE}, - #else - {"ECC_CERT_SHOULD_HAVE_RSA_SIGNATURE", 20, 322}, - #endif - #ifdef SSL_R_ECC_CERT_SHOULD_HAVE_SHA1_SIGNATURE - {"ECC_CERT_SHOULD_HAVE_SHA1_SIGNATURE", ERR_LIB_SSL, SSL_R_ECC_CERT_SHOULD_HAVE_SHA1_SIGNATURE}, - #else - {"ECC_CERT_SHOULD_HAVE_SHA1_SIGNATURE", 20, 323}, - #endif - #ifdef SSL_R_ECDH_REQUIRED_FOR_SUITEB_MODE - {"ECDH_REQUIRED_FOR_SUITEB_MODE", ERR_LIB_SSL, SSL_R_ECDH_REQUIRED_FOR_SUITEB_MODE}, - #else - {"ECDH_REQUIRED_FOR_SUITEB_MODE", 20, 374}, - #endif - #ifdef SSL_R_ECGROUP_TOO_LARGE_FOR_CIPHER - {"ECGROUP_TOO_LARGE_FOR_CIPHER", ERR_LIB_SSL, SSL_R_ECGROUP_TOO_LARGE_FOR_CIPHER}, - #else - {"ECGROUP_TOO_LARGE_FOR_CIPHER", 20, 310}, - #endif - #ifdef SSL_R_EE_KEY_TOO_SMALL - {"EE_KEY_TOO_SMALL", ERR_LIB_SSL, SSL_R_EE_KEY_TOO_SMALL}, - #else - {"EE_KEY_TOO_SMALL", 20, 399}, - #endif - #ifdef SSL_R_EMPTY_SRTP_PROTECTION_PROFILE_LIST - {"EMPTY_SRTP_PROTECTION_PROFILE_LIST", ERR_LIB_SSL, SSL_R_EMPTY_SRTP_PROTECTION_PROFILE_LIST}, - #else - {"EMPTY_SRTP_PROTECTION_PROFILE_LIST", 20, 354}, - #endif - #ifdef SSL_R_ENCRYPTED_LENGTH_TOO_LONG - {"ENCRYPTED_LENGTH_TOO_LONG", ERR_LIB_SSL, SSL_R_ENCRYPTED_LENGTH_TOO_LONG}, - #else - {"ENCRYPTED_LENGTH_TOO_LONG", 20, 150}, - #endif - #ifdef SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST - {"ERROR_IN_RECEIVED_CIPHER_LIST", ERR_LIB_SSL, SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST}, - #else - {"ERROR_IN_RECEIVED_CIPHER_LIST", 20, 151}, - #endif - #ifdef SSL_R_ERROR_SETTING_TLSA_BASE_DOMAIN - {"ERROR_SETTING_TLSA_BASE_DOMAIN", ERR_LIB_SSL, SSL_R_ERROR_SETTING_TLSA_BASE_DOMAIN}, - #else - {"ERROR_SETTING_TLSA_BASE_DOMAIN", 20, 204}, - #endif - #ifdef SSL_R_EXCEEDS_MAX_FRAGMENT_SIZE - {"EXCEEDS_MAX_FRAGMENT_SIZE", ERR_LIB_SSL, SSL_R_EXCEEDS_MAX_FRAGMENT_SIZE}, - #else - {"EXCEEDS_MAX_FRAGMENT_SIZE", 20, 194}, - #endif - #ifdef SSL_R_EXCESSIVE_MESSAGE_SIZE - {"EXCESSIVE_MESSAGE_SIZE", ERR_LIB_SSL, SSL_R_EXCESSIVE_MESSAGE_SIZE}, - #else - {"EXCESSIVE_MESSAGE_SIZE", 20, 152}, - #endif - #ifdef SSL_R_EXTENSION_NOT_RECEIVED - {"EXTENSION_NOT_RECEIVED", ERR_LIB_SSL, SSL_R_EXTENSION_NOT_RECEIVED}, - #else - {"EXTENSION_NOT_RECEIVED", 20, 279}, - #endif - #ifdef SSL_R_EXTRA_DATA_IN_MESSAGE - {"EXTRA_DATA_IN_MESSAGE", ERR_LIB_SSL, SSL_R_EXTRA_DATA_IN_MESSAGE}, - #else - {"EXTRA_DATA_IN_MESSAGE", 20, 153}, - #endif - #ifdef SSL_R_EXT_LENGTH_MISMATCH - {"EXT_LENGTH_MISMATCH", ERR_LIB_SSL, SSL_R_EXT_LENGTH_MISMATCH}, - #else - {"EXT_LENGTH_MISMATCH", 20, 163}, - #endif - #ifdef SSL_R_FAILED_TO_INIT_ASYNC - {"FAILED_TO_INIT_ASYNC", ERR_LIB_SSL, SSL_R_FAILED_TO_INIT_ASYNC}, - #else - {"FAILED_TO_INIT_ASYNC", 20, 405}, - #endif - #ifdef SSL_R_FRAGMENTED_CLIENT_HELLO - {"FRAGMENTED_CLIENT_HELLO", ERR_LIB_SSL, SSL_R_FRAGMENTED_CLIENT_HELLO}, - #else - {"FRAGMENTED_CLIENT_HELLO", 20, 401}, - #endif - #ifdef SSL_R_GOT_A_FIN_BEFORE_A_CCS - {"GOT_A_FIN_BEFORE_A_CCS", ERR_LIB_SSL, SSL_R_GOT_A_FIN_BEFORE_A_CCS}, - #else - {"GOT_A_FIN_BEFORE_A_CCS", 20, 154}, - #endif - #ifdef SSL_R_GOT_NEXT_PROTO_BEFORE_A_CCS - {"GOT_NEXT_PROTO_BEFORE_A_CCS", ERR_LIB_SSL, SSL_R_GOT_NEXT_PROTO_BEFORE_A_CCS}, - #else - {"GOT_NEXT_PROTO_BEFORE_A_CCS", 20, 355}, - #endif - #ifdef SSL_R_GOT_NEXT_PROTO_WITHOUT_EXTENSION - {"GOT_NEXT_PROTO_WITHOUT_EXTENSION", ERR_LIB_SSL, SSL_R_GOT_NEXT_PROTO_WITHOUT_EXTENSION}, - #else - {"GOT_NEXT_PROTO_WITHOUT_EXTENSION", 20, 356}, - #endif - #ifdef SSL_R_HTTPS_PROXY_REQUEST - {"HTTPS_PROXY_REQUEST", ERR_LIB_SSL, SSL_R_HTTPS_PROXY_REQUEST}, - #else - {"HTTPS_PROXY_REQUEST", 20, 155}, - #endif - #ifdef SSL_R_HTTP_REQUEST - {"HTTP_REQUEST", ERR_LIB_SSL, SSL_R_HTTP_REQUEST}, - #else - {"HTTP_REQUEST", 20, 156}, - #endif - #ifdef SSL_R_ILLEGAL_POINT_COMPRESSION - {"ILLEGAL_POINT_COMPRESSION", ERR_LIB_SSL, SSL_R_ILLEGAL_POINT_COMPRESSION}, - #else - {"ILLEGAL_POINT_COMPRESSION", 20, 162}, - #endif - #ifdef SSL_R_ILLEGAL_SUITEB_DIGEST - {"ILLEGAL_SUITEB_DIGEST", ERR_LIB_SSL, SSL_R_ILLEGAL_SUITEB_DIGEST}, - #else - {"ILLEGAL_SUITEB_DIGEST", 20, 380}, - #endif - #ifdef SSL_R_INAPPROPRIATE_FALLBACK - {"INAPPROPRIATE_FALLBACK", ERR_LIB_SSL, SSL_R_INAPPROPRIATE_FALLBACK}, - #else - {"INAPPROPRIATE_FALLBACK", 20, 373}, - #endif - #ifdef SSL_R_INCONSISTENT_COMPRESSION - {"INCONSISTENT_COMPRESSION", ERR_LIB_SSL, SSL_R_INCONSISTENT_COMPRESSION}, - #else - {"INCONSISTENT_COMPRESSION", 20, 340}, - #endif - #ifdef SSL_R_INCONSISTENT_EARLY_DATA_ALPN - {"INCONSISTENT_EARLY_DATA_ALPN", ERR_LIB_SSL, SSL_R_INCONSISTENT_EARLY_DATA_ALPN}, - #else - {"INCONSISTENT_EARLY_DATA_ALPN", 20, 222}, - #endif - #ifdef SSL_R_INCONSISTENT_EARLY_DATA_SNI - {"INCONSISTENT_EARLY_DATA_SNI", ERR_LIB_SSL, SSL_R_INCONSISTENT_EARLY_DATA_SNI}, - #else - {"INCONSISTENT_EARLY_DATA_SNI", 20, 231}, - #endif - #ifdef SSL_R_INCONSISTENT_EXTMS - {"INCONSISTENT_EXTMS", ERR_LIB_SSL, SSL_R_INCONSISTENT_EXTMS}, - #else - {"INCONSISTENT_EXTMS", 20, 104}, - #endif - #ifdef SSL_R_INSUFFICIENT_SECURITY - {"INSUFFICIENT_SECURITY", ERR_LIB_SSL, SSL_R_INSUFFICIENT_SECURITY}, - #else - {"INSUFFICIENT_SECURITY", 20, 241}, - #endif - #ifdef SSL_R_INVALID_ALERT - {"INVALID_ALERT", ERR_LIB_SSL, SSL_R_INVALID_ALERT}, - #else - {"INVALID_ALERT", 20, 205}, - #endif - #ifdef SSL_R_INVALID_CCS_MESSAGE - {"INVALID_CCS_MESSAGE", ERR_LIB_SSL, SSL_R_INVALID_CCS_MESSAGE}, - #else - {"INVALID_CCS_MESSAGE", 20, 260}, - #endif - #ifdef SSL_R_INVALID_CERTIFICATE_OR_ALG - {"INVALID_CERTIFICATE_OR_ALG", ERR_LIB_SSL, SSL_R_INVALID_CERTIFICATE_OR_ALG}, - #else - {"INVALID_CERTIFICATE_OR_ALG", 20, 238}, - #endif - #ifdef SSL_R_INVALID_COMMAND - {"INVALID_COMMAND", ERR_LIB_SSL, SSL_R_INVALID_COMMAND}, - #else - {"INVALID_COMMAND", 20, 280}, - #endif - #ifdef SSL_R_INVALID_COMPRESSION_ALGORITHM - {"INVALID_COMPRESSION_ALGORITHM", ERR_LIB_SSL, SSL_R_INVALID_COMPRESSION_ALGORITHM}, - #else - {"INVALID_COMPRESSION_ALGORITHM", 20, 341}, - #endif - #ifdef SSL_R_INVALID_CONFIG - {"INVALID_CONFIG", ERR_LIB_SSL, SSL_R_INVALID_CONFIG}, - #else - {"INVALID_CONFIG", 20, 283}, - #endif - #ifdef SSL_R_INVALID_CONFIGURATION_NAME - {"INVALID_CONFIGURATION_NAME", ERR_LIB_SSL, SSL_R_INVALID_CONFIGURATION_NAME}, - #else - {"INVALID_CONFIGURATION_NAME", 20, 113}, - #endif - #ifdef SSL_R_INVALID_CONTEXT - {"INVALID_CONTEXT", ERR_LIB_SSL, SSL_R_INVALID_CONTEXT}, - #else - {"INVALID_CONTEXT", 20, 282}, - #endif - #ifdef SSL_R_INVALID_CT_VALIDATION_TYPE - {"INVALID_CT_VALIDATION_TYPE", ERR_LIB_SSL, SSL_R_INVALID_CT_VALIDATION_TYPE}, - #else - {"INVALID_CT_VALIDATION_TYPE", 20, 212}, - #endif - #ifdef SSL_R_INVALID_KEY_UPDATE_TYPE - {"INVALID_KEY_UPDATE_TYPE", ERR_LIB_SSL, SSL_R_INVALID_KEY_UPDATE_TYPE}, - #else - {"INVALID_KEY_UPDATE_TYPE", 20, 120}, - #endif - #ifdef SSL_R_INVALID_MAX_EARLY_DATA - {"INVALID_MAX_EARLY_DATA", ERR_LIB_SSL, SSL_R_INVALID_MAX_EARLY_DATA}, - #else - {"INVALID_MAX_EARLY_DATA", 20, 174}, - #endif - #ifdef SSL_R_INVALID_NULL_CMD_NAME - {"INVALID_NULL_CMD_NAME", ERR_LIB_SSL, SSL_R_INVALID_NULL_CMD_NAME}, - #else - {"INVALID_NULL_CMD_NAME", 20, 385}, - #endif - #ifdef SSL_R_INVALID_SEQUENCE_NUMBER - {"INVALID_SEQUENCE_NUMBER", ERR_LIB_SSL, SSL_R_INVALID_SEQUENCE_NUMBER}, - #else - {"INVALID_SEQUENCE_NUMBER", 20, 402}, - #endif - #ifdef SSL_R_INVALID_SERVERINFO_DATA - {"INVALID_SERVERINFO_DATA", ERR_LIB_SSL, SSL_R_INVALID_SERVERINFO_DATA}, - #else - {"INVALID_SERVERINFO_DATA", 20, 388}, - #endif - #ifdef SSL_R_INVALID_SESSION_ID - {"INVALID_SESSION_ID", ERR_LIB_SSL, SSL_R_INVALID_SESSION_ID}, - #else - {"INVALID_SESSION_ID", 20, 999}, - #endif - #ifdef SSL_R_INVALID_SRP_USERNAME - {"INVALID_SRP_USERNAME", ERR_LIB_SSL, SSL_R_INVALID_SRP_USERNAME}, - #else - {"INVALID_SRP_USERNAME", 20, 357}, - #endif - #ifdef SSL_R_INVALID_STATUS_RESPONSE - {"INVALID_STATUS_RESPONSE", ERR_LIB_SSL, SSL_R_INVALID_STATUS_RESPONSE}, - #else - {"INVALID_STATUS_RESPONSE", 20, 328}, - #endif - #ifdef SSL_R_INVALID_TICKET_KEYS_LENGTH - {"INVALID_TICKET_KEYS_LENGTH", ERR_LIB_SSL, SSL_R_INVALID_TICKET_KEYS_LENGTH}, - #else - {"INVALID_TICKET_KEYS_LENGTH", 20, 325}, - #endif - #ifdef SSL_R_KRB5_S_TKT_NYV - {"KRB5_S_TKT_NYV", ERR_LIB_SSL, SSL_R_KRB5_S_TKT_NYV}, - #else - {"KRB5_S_TKT_NYV", 20, 294}, - #endif - #ifdef SSL_R_KRB5_S_TKT_SKEW - {"KRB5_S_TKT_SKEW", ERR_LIB_SSL, SSL_R_KRB5_S_TKT_SKEW}, - #else - {"KRB5_S_TKT_SKEW", 20, 295}, - #endif - #ifdef SSL_R_LENGTH_MISMATCH - {"LENGTH_MISMATCH", ERR_LIB_SSL, SSL_R_LENGTH_MISMATCH}, - #else - {"LENGTH_MISMATCH", 20, 159}, - #endif - #ifdef SSL_R_LENGTH_TOO_LONG - {"LENGTH_TOO_LONG", ERR_LIB_SSL, SSL_R_LENGTH_TOO_LONG}, - #else - {"LENGTH_TOO_LONG", 20, 404}, - #endif - #ifdef SSL_R_LENGTH_TOO_SHORT - {"LENGTH_TOO_SHORT", ERR_LIB_SSL, SSL_R_LENGTH_TOO_SHORT}, - #else - {"LENGTH_TOO_SHORT", 20, 160}, - #endif - #ifdef SSL_R_LIBRARY_BUG - {"LIBRARY_BUG", ERR_LIB_SSL, SSL_R_LIBRARY_BUG}, - #else - {"LIBRARY_BUG", 20, 274}, - #endif - #ifdef SSL_R_LIBRARY_HAS_NO_CIPHERS - {"LIBRARY_HAS_NO_CIPHERS", ERR_LIB_SSL, SSL_R_LIBRARY_HAS_NO_CIPHERS}, - #else - {"LIBRARY_HAS_NO_CIPHERS", 20, 161}, - #endif - #ifdef SSL_R_MESSAGE_TOO_LONG - {"MESSAGE_TOO_LONG", ERR_LIB_SSL, SSL_R_MESSAGE_TOO_LONG}, - #else - {"MESSAGE_TOO_LONG", 20, 296}, - #endif - #ifdef SSL_R_MISSING_DSA_SIGNING_CERT - {"MISSING_DSA_SIGNING_CERT", ERR_LIB_SSL, SSL_R_MISSING_DSA_SIGNING_CERT}, - #else - {"MISSING_DSA_SIGNING_CERT", 20, 165}, - #endif - #ifdef SSL_R_MISSING_ECDH_CERT - {"MISSING_ECDH_CERT", ERR_LIB_SSL, SSL_R_MISSING_ECDH_CERT}, - #else - {"MISSING_ECDH_CERT", 20, 382}, - #endif - #ifdef SSL_R_MISSING_ECDSA_SIGNING_CERT - {"MISSING_ECDSA_SIGNING_CERT", ERR_LIB_SSL, SSL_R_MISSING_ECDSA_SIGNING_CERT}, - #else - {"MISSING_ECDSA_SIGNING_CERT", 20, 381}, - #endif - #ifdef SSL_R_MISSING_FATAL - {"MISSING_FATAL", ERR_LIB_SSL, SSL_R_MISSING_FATAL}, - #else - {"MISSING_FATAL", 20, 256}, - #endif - #ifdef SSL_R_MISSING_PARAMETERS - {"MISSING_PARAMETERS", ERR_LIB_SSL, SSL_R_MISSING_PARAMETERS}, - #else - {"MISSING_PARAMETERS", 20, 290}, - #endif - #ifdef SSL_R_MISSING_RSA_CERTIFICATE - {"MISSING_RSA_CERTIFICATE", ERR_LIB_SSL, SSL_R_MISSING_RSA_CERTIFICATE}, - #else - {"MISSING_RSA_CERTIFICATE", 20, 168}, - #endif - #ifdef SSL_R_MISSING_RSA_ENCRYPTING_CERT - {"MISSING_RSA_ENCRYPTING_CERT", ERR_LIB_SSL, SSL_R_MISSING_RSA_ENCRYPTING_CERT}, - #else - {"MISSING_RSA_ENCRYPTING_CERT", 20, 169}, - #endif - #ifdef SSL_R_MISSING_RSA_SIGNING_CERT - {"MISSING_RSA_SIGNING_CERT", ERR_LIB_SSL, SSL_R_MISSING_RSA_SIGNING_CERT}, - #else - {"MISSING_RSA_SIGNING_CERT", 20, 170}, - #endif - #ifdef SSL_R_MISSING_SIGALGS_EXTENSION - {"MISSING_SIGALGS_EXTENSION", ERR_LIB_SSL, SSL_R_MISSING_SIGALGS_EXTENSION}, - #else - {"MISSING_SIGALGS_EXTENSION", 20, 112}, - #endif - #ifdef SSL_R_MISSING_SIGNING_CERT - {"MISSING_SIGNING_CERT", ERR_LIB_SSL, SSL_R_MISSING_SIGNING_CERT}, - #else - {"MISSING_SIGNING_CERT", 20, 221}, - #endif - #ifdef SSL_R_MISSING_SRP_PARAM - {"MISSING_SRP_PARAM", ERR_LIB_SSL, SSL_R_MISSING_SRP_PARAM}, - #else - {"MISSING_SRP_PARAM", 20, 358}, - #endif - #ifdef SSL_R_MISSING_SUPPORTED_GROUPS_EXTENSION - {"MISSING_SUPPORTED_GROUPS_EXTENSION", ERR_LIB_SSL, SSL_R_MISSING_SUPPORTED_GROUPS_EXTENSION}, - #else - {"MISSING_SUPPORTED_GROUPS_EXTENSION", 20, 209}, - #endif - #ifdef SSL_R_MISSING_TMP_DH_KEY - {"MISSING_TMP_DH_KEY", ERR_LIB_SSL, SSL_R_MISSING_TMP_DH_KEY}, - #else - {"MISSING_TMP_DH_KEY", 20, 171}, - #endif - #ifdef SSL_R_MISSING_TMP_ECDH_KEY - {"MISSING_TMP_ECDH_KEY", ERR_LIB_SSL, SSL_R_MISSING_TMP_ECDH_KEY}, - #else - {"MISSING_TMP_ECDH_KEY", 20, 311}, - #endif - #ifdef SSL_R_MIXED_HANDSHAKE_AND_NON_HANDSHAKE_DATA - {"MIXED_HANDSHAKE_AND_NON_HANDSHAKE_DATA", ERR_LIB_SSL, SSL_R_MIXED_HANDSHAKE_AND_NON_HANDSHAKE_DATA}, - #else - {"MIXED_HANDSHAKE_AND_NON_HANDSHAKE_DATA", 20, 293}, - #endif - #ifdef SSL_R_MULTIPLE_SGC_RESTARTS - {"MULTIPLE_SGC_RESTARTS", ERR_LIB_SSL, SSL_R_MULTIPLE_SGC_RESTARTS}, - #else - {"MULTIPLE_SGC_RESTARTS", 20, 346}, - #endif - #ifdef SSL_R_NOT_ON_RECORD_BOUNDARY - {"NOT_ON_RECORD_BOUNDARY", ERR_LIB_SSL, SSL_R_NOT_ON_RECORD_BOUNDARY}, - #else - {"NOT_ON_RECORD_BOUNDARY", 20, 182}, - #endif - #ifdef SSL_R_NOT_REPLACING_CERTIFICATE - {"NOT_REPLACING_CERTIFICATE", ERR_LIB_SSL, SSL_R_NOT_REPLACING_CERTIFICATE}, - #else - {"NOT_REPLACING_CERTIFICATE", 20, 289}, - #endif - #ifdef SSL_R_NOT_SERVER - {"NOT_SERVER", ERR_LIB_SSL, SSL_R_NOT_SERVER}, - #else - {"NOT_SERVER", 20, 284}, - #endif - #ifdef SSL_R_NO_APPLICATION_PROTOCOL - {"NO_APPLICATION_PROTOCOL", ERR_LIB_SSL, SSL_R_NO_APPLICATION_PROTOCOL}, - #else - {"NO_APPLICATION_PROTOCOL", 20, 235}, - #endif - #ifdef SSL_R_NO_CERTIFICATES_RETURNED - {"NO_CERTIFICATES_RETURNED", ERR_LIB_SSL, SSL_R_NO_CERTIFICATES_RETURNED}, - #else - {"NO_CERTIFICATES_RETURNED", 20, 176}, - #endif - #ifdef SSL_R_NO_CERTIFICATE_ASSIGNED - {"NO_CERTIFICATE_ASSIGNED", ERR_LIB_SSL, SSL_R_NO_CERTIFICATE_ASSIGNED}, - #else - {"NO_CERTIFICATE_ASSIGNED", 20, 177}, - #endif - #ifdef SSL_R_NO_CERTIFICATE_SET - {"NO_CERTIFICATE_SET", ERR_LIB_SSL, SSL_R_NO_CERTIFICATE_SET}, - #else - {"NO_CERTIFICATE_SET", 20, 179}, - #endif - #ifdef SSL_R_NO_CHANGE_FOLLOWING_HRR - {"NO_CHANGE_FOLLOWING_HRR", ERR_LIB_SSL, SSL_R_NO_CHANGE_FOLLOWING_HRR}, - #else - {"NO_CHANGE_FOLLOWING_HRR", 20, 214}, - #endif - #ifdef SSL_R_NO_CIPHERS_AVAILABLE - {"NO_CIPHERS_AVAILABLE", ERR_LIB_SSL, SSL_R_NO_CIPHERS_AVAILABLE}, - #else - {"NO_CIPHERS_AVAILABLE", 20, 181}, - #endif - #ifdef SSL_R_NO_CIPHERS_SPECIFIED - {"NO_CIPHERS_SPECIFIED", ERR_LIB_SSL, SSL_R_NO_CIPHERS_SPECIFIED}, - #else - {"NO_CIPHERS_SPECIFIED", 20, 183}, - #endif - #ifdef SSL_R_NO_CIPHER_MATCH - {"NO_CIPHER_MATCH", ERR_LIB_SSL, SSL_R_NO_CIPHER_MATCH}, - #else - {"NO_CIPHER_MATCH", 20, 185}, - #endif - #ifdef SSL_R_NO_CLIENT_CERT_METHOD - {"NO_CLIENT_CERT_METHOD", ERR_LIB_SSL, SSL_R_NO_CLIENT_CERT_METHOD}, - #else - {"NO_CLIENT_CERT_METHOD", 20, 331}, - #endif - #ifdef SSL_R_NO_COMPRESSION_SPECIFIED - {"NO_COMPRESSION_SPECIFIED", ERR_LIB_SSL, SSL_R_NO_COMPRESSION_SPECIFIED}, - #else - {"NO_COMPRESSION_SPECIFIED", 20, 187}, - #endif - #ifdef SSL_R_NO_COOKIE_CALLBACK_SET - {"NO_COOKIE_CALLBACK_SET", ERR_LIB_SSL, SSL_R_NO_COOKIE_CALLBACK_SET}, - #else - {"NO_COOKIE_CALLBACK_SET", 20, 287}, - #endif - #ifdef SSL_R_NO_GOST_CERTIFICATE_SENT_BY_PEER - {"NO_GOST_CERTIFICATE_SENT_BY_PEER", ERR_LIB_SSL, SSL_R_NO_GOST_CERTIFICATE_SENT_BY_PEER}, - #else - {"NO_GOST_CERTIFICATE_SENT_BY_PEER", 20, 330}, - #endif - #ifdef SSL_R_NO_METHOD_SPECIFIED - {"NO_METHOD_SPECIFIED", ERR_LIB_SSL, SSL_R_NO_METHOD_SPECIFIED}, - #else - {"NO_METHOD_SPECIFIED", 20, 188}, - #endif - #ifdef SSL_R_NO_PEM_EXTENSIONS - {"NO_PEM_EXTENSIONS", ERR_LIB_SSL, SSL_R_NO_PEM_EXTENSIONS}, - #else - {"NO_PEM_EXTENSIONS", 20, 389}, - #endif - #ifdef SSL_R_NO_PRIVATE_KEY_ASSIGNED - {"NO_PRIVATE_KEY_ASSIGNED", ERR_LIB_SSL, SSL_R_NO_PRIVATE_KEY_ASSIGNED}, - #else - {"NO_PRIVATE_KEY_ASSIGNED", 20, 190}, - #endif - #ifdef SSL_R_NO_PROTOCOLS_AVAILABLE - {"NO_PROTOCOLS_AVAILABLE", ERR_LIB_SSL, SSL_R_NO_PROTOCOLS_AVAILABLE}, - #else - {"NO_PROTOCOLS_AVAILABLE", 20, 191}, - #endif - #ifdef SSL_R_NO_RENEGOTIATION - {"NO_RENEGOTIATION", ERR_LIB_SSL, SSL_R_NO_RENEGOTIATION}, - #else - {"NO_RENEGOTIATION", 20, 339}, - #endif - #ifdef SSL_R_NO_REQUIRED_DIGEST - {"NO_REQUIRED_DIGEST", ERR_LIB_SSL, SSL_R_NO_REQUIRED_DIGEST}, - #else - {"NO_REQUIRED_DIGEST", 20, 324}, - #endif - #ifdef SSL_R_NO_SHARED_CIPHER - {"NO_SHARED_CIPHER", ERR_LIB_SSL, SSL_R_NO_SHARED_CIPHER}, - #else - {"NO_SHARED_CIPHER", 20, 193}, - #endif - #ifdef SSL_R_NO_SHARED_GROUPS - {"NO_SHARED_GROUPS", ERR_LIB_SSL, SSL_R_NO_SHARED_GROUPS}, - #else - {"NO_SHARED_GROUPS", 20, 410}, - #endif - #ifdef SSL_R_NO_SHARED_SIGNATURE_ALGORITHMS - {"NO_SHARED_SIGNATURE_ALGORITHMS", ERR_LIB_SSL, SSL_R_NO_SHARED_SIGNATURE_ALGORITHMS}, - #else - {"NO_SHARED_SIGNATURE_ALGORITHMS", 20, 376}, - #endif - #ifdef SSL_R_NO_SRTP_PROFILES - {"NO_SRTP_PROFILES", ERR_LIB_SSL, SSL_R_NO_SRTP_PROFILES}, - #else - {"NO_SRTP_PROFILES", 20, 359}, - #endif - #ifdef SSL_R_NO_SUITABLE_KEY_SHARE - {"NO_SUITABLE_KEY_SHARE", ERR_LIB_SSL, SSL_R_NO_SUITABLE_KEY_SHARE}, - #else - {"NO_SUITABLE_KEY_SHARE", 20, 101}, - #endif - #ifdef SSL_R_NO_SUITABLE_SIGNATURE_ALGORITHM - {"NO_SUITABLE_SIGNATURE_ALGORITHM", ERR_LIB_SSL, SSL_R_NO_SUITABLE_SIGNATURE_ALGORITHM}, - #else - {"NO_SUITABLE_SIGNATURE_ALGORITHM", 20, 118}, - #endif - #ifdef SSL_R_NO_VALID_SCTS - {"NO_VALID_SCTS", ERR_LIB_SSL, SSL_R_NO_VALID_SCTS}, - #else - {"NO_VALID_SCTS", 20, 216}, - #endif - #ifdef SSL_R_NO_VERIFY_COOKIE_CALLBACK - {"NO_VERIFY_COOKIE_CALLBACK", ERR_LIB_SSL, SSL_R_NO_VERIFY_COOKIE_CALLBACK}, - #else - {"NO_VERIFY_COOKIE_CALLBACK", 20, 403}, - #endif - #ifdef SSL_R_NULL_SSL_CTX - {"NULL_SSL_CTX", ERR_LIB_SSL, SSL_R_NULL_SSL_CTX}, - #else - {"NULL_SSL_CTX", 20, 195}, - #endif - #ifdef SSL_R_NULL_SSL_METHOD_PASSED - {"NULL_SSL_METHOD_PASSED", ERR_LIB_SSL, SSL_R_NULL_SSL_METHOD_PASSED}, - #else - {"NULL_SSL_METHOD_PASSED", 20, 196}, - #endif - #ifdef SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED - {"OLD_SESSION_CIPHER_NOT_RETURNED", ERR_LIB_SSL, SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED}, - #else - {"OLD_SESSION_CIPHER_NOT_RETURNED", 20, 197}, - #endif - #ifdef SSL_R_OLD_SESSION_COMPRESSION_ALGORITHM_NOT_RETURNED - {"OLD_SESSION_COMPRESSION_ALGORITHM_NOT_RETURNED", ERR_LIB_SSL, SSL_R_OLD_SESSION_COMPRESSION_ALGORITHM_NOT_RETURNED}, - #else - {"OLD_SESSION_COMPRESSION_ALGORITHM_NOT_RETURNED", 20, 344}, - #endif - #ifdef SSL_R_ONLY_DTLS_1_2_ALLOWED_IN_SUITEB_MODE - {"ONLY_DTLS_1_2_ALLOWED_IN_SUITEB_MODE", ERR_LIB_SSL, SSL_R_ONLY_DTLS_1_2_ALLOWED_IN_SUITEB_MODE}, - #else - {"ONLY_DTLS_1_2_ALLOWED_IN_SUITEB_MODE", 20, 387}, - #endif - #ifdef SSL_R_ONLY_TLS_1_2_ALLOWED_IN_SUITEB_MODE - {"ONLY_TLS_1_2_ALLOWED_IN_SUITEB_MODE", ERR_LIB_SSL, SSL_R_ONLY_TLS_1_2_ALLOWED_IN_SUITEB_MODE}, - #else - {"ONLY_TLS_1_2_ALLOWED_IN_SUITEB_MODE", 20, 379}, - #endif - #ifdef SSL_R_ONLY_TLS_ALLOWED_IN_FIPS_MODE - {"ONLY_TLS_ALLOWED_IN_FIPS_MODE", ERR_LIB_SSL, SSL_R_ONLY_TLS_ALLOWED_IN_FIPS_MODE}, - #else - {"ONLY_TLS_ALLOWED_IN_FIPS_MODE", 20, 297}, - #endif - #ifdef SSL_R_OPAQUE_PRF_INPUT_TOO_LONG - {"OPAQUE_PRF_INPUT_TOO_LONG", ERR_LIB_SSL, SSL_R_OPAQUE_PRF_INPUT_TOO_LONG}, - #else - {"OPAQUE_PRF_INPUT_TOO_LONG", 20, 327}, - #endif - #ifdef SSL_R_OVERFLOW_ERROR - {"OVERFLOW_ERROR", ERR_LIB_SSL, SSL_R_OVERFLOW_ERROR}, - #else - {"OVERFLOW_ERROR", 20, 237}, - #endif - #ifdef SSL_R_PACKET_LENGTH_TOO_LONG - {"PACKET_LENGTH_TOO_LONG", ERR_LIB_SSL, SSL_R_PACKET_LENGTH_TOO_LONG}, - #else - {"PACKET_LENGTH_TOO_LONG", 20, 198}, - #endif - #ifdef SSL_R_PARSE_TLSEXT - {"PARSE_TLSEXT", ERR_LIB_SSL, SSL_R_PARSE_TLSEXT}, - #else - {"PARSE_TLSEXT", 20, 227}, - #endif - #ifdef SSL_R_PATH_TOO_LONG - {"PATH_TOO_LONG", ERR_LIB_SSL, SSL_R_PATH_TOO_LONG}, - #else - {"PATH_TOO_LONG", 20, 270}, - #endif - #ifdef SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE - {"PEER_DID_NOT_RETURN_A_CERTIFICATE", ERR_LIB_SSL, SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE}, - #else - {"PEER_DID_NOT_RETURN_A_CERTIFICATE", 20, 199}, - #endif - #ifdef SSL_R_PEM_NAME_BAD_PREFIX - {"PEM_NAME_BAD_PREFIX", ERR_LIB_SSL, SSL_R_PEM_NAME_BAD_PREFIX}, - #else - {"PEM_NAME_BAD_PREFIX", 20, 391}, - #endif - #ifdef SSL_R_PEM_NAME_TOO_SHORT - {"PEM_NAME_TOO_SHORT", ERR_LIB_SSL, SSL_R_PEM_NAME_TOO_SHORT}, - #else - {"PEM_NAME_TOO_SHORT", 20, 392}, - #endif - #ifdef SSL_R_PIPELINE_FAILURE - {"PIPELINE_FAILURE", ERR_LIB_SSL, SSL_R_PIPELINE_FAILURE}, - #else - {"PIPELINE_FAILURE", 20, 406}, - #endif - #ifdef SSL_R_POST_HANDSHAKE_AUTH_ENCODING_ERR - {"POST_HANDSHAKE_AUTH_ENCODING_ERR", ERR_LIB_SSL, SSL_R_POST_HANDSHAKE_AUTH_ENCODING_ERR}, - #else - {"POST_HANDSHAKE_AUTH_ENCODING_ERR", 20, 278}, - #endif - #ifdef SSL_R_PRIVATE_KEY_MISMATCH - {"PRIVATE_KEY_MISMATCH", ERR_LIB_SSL, SSL_R_PRIVATE_KEY_MISMATCH}, - #else - {"PRIVATE_KEY_MISMATCH", 20, 288}, - #endif - #ifdef SSL_R_PROTOCOL_IS_SHUTDOWN - {"PROTOCOL_IS_SHUTDOWN", ERR_LIB_SSL, SSL_R_PROTOCOL_IS_SHUTDOWN}, - #else - {"PROTOCOL_IS_SHUTDOWN", 20, 207}, - #endif - #ifdef SSL_R_PSK_IDENTITY_NOT_FOUND - {"PSK_IDENTITY_NOT_FOUND", ERR_LIB_SSL, SSL_R_PSK_IDENTITY_NOT_FOUND}, - #else - {"PSK_IDENTITY_NOT_FOUND", 20, 223}, - #endif - #ifdef SSL_R_PSK_NO_CLIENT_CB - {"PSK_NO_CLIENT_CB", ERR_LIB_SSL, SSL_R_PSK_NO_CLIENT_CB}, - #else - {"PSK_NO_CLIENT_CB", 20, 224}, - #endif - #ifdef SSL_R_PSK_NO_SERVER_CB - {"PSK_NO_SERVER_CB", ERR_LIB_SSL, SSL_R_PSK_NO_SERVER_CB}, - #else - {"PSK_NO_SERVER_CB", 20, 225}, - #endif - #ifdef SSL_R_READ_BIO_NOT_SET - {"READ_BIO_NOT_SET", ERR_LIB_SSL, SSL_R_READ_BIO_NOT_SET}, - #else - {"READ_BIO_NOT_SET", 20, 211}, - #endif - #ifdef SSL_R_READ_TIMEOUT_EXPIRED - {"READ_TIMEOUT_EXPIRED", ERR_LIB_SSL, SSL_R_READ_TIMEOUT_EXPIRED}, - #else - {"READ_TIMEOUT_EXPIRED", 20, 312}, - #endif - #ifdef SSL_R_RECORD_LENGTH_MISMATCH - {"RECORD_LENGTH_MISMATCH", ERR_LIB_SSL, SSL_R_RECORD_LENGTH_MISMATCH}, - #else - {"RECORD_LENGTH_MISMATCH", 20, 213}, - #endif - #ifdef SSL_R_RECORD_TOO_SMALL - {"RECORD_TOO_SMALL", ERR_LIB_SSL, SSL_R_RECORD_TOO_SMALL}, - #else - {"RECORD_TOO_SMALL", 20, 298}, - #endif - #ifdef SSL_R_RENEGOTIATE_EXT_TOO_LONG - {"RENEGOTIATE_EXT_TOO_LONG", ERR_LIB_SSL, SSL_R_RENEGOTIATE_EXT_TOO_LONG}, - #else - {"RENEGOTIATE_EXT_TOO_LONG", 20, 335}, - #endif - #ifdef SSL_R_RENEGOTIATION_ENCODING_ERR - {"RENEGOTIATION_ENCODING_ERR", ERR_LIB_SSL, SSL_R_RENEGOTIATION_ENCODING_ERR}, - #else - {"RENEGOTIATION_ENCODING_ERR", 20, 336}, - #endif - #ifdef SSL_R_RENEGOTIATION_MISMATCH - {"RENEGOTIATION_MISMATCH", ERR_LIB_SSL, SSL_R_RENEGOTIATION_MISMATCH}, - #else - {"RENEGOTIATION_MISMATCH", 20, 337}, - #endif - #ifdef SSL_R_REQUEST_PENDING - {"REQUEST_PENDING", ERR_LIB_SSL, SSL_R_REQUEST_PENDING}, - #else - {"REQUEST_PENDING", 20, 285}, - #endif - #ifdef SSL_R_REQUEST_SENT - {"REQUEST_SENT", ERR_LIB_SSL, SSL_R_REQUEST_SENT}, - #else - {"REQUEST_SENT", 20, 286}, - #endif - #ifdef SSL_R_REQUIRED_CIPHER_MISSING - {"REQUIRED_CIPHER_MISSING", ERR_LIB_SSL, SSL_R_REQUIRED_CIPHER_MISSING}, - #else - {"REQUIRED_CIPHER_MISSING", 20, 215}, - #endif - #ifdef SSL_R_REQUIRED_COMPRESSION_ALGORITHM_MISSING - {"REQUIRED_COMPRESSION_ALGORITHM_MISSING", ERR_LIB_SSL, SSL_R_REQUIRED_COMPRESSION_ALGORITHM_MISSING}, - #else - {"REQUIRED_COMPRESSION_ALGORITHM_MISSING", 20, 342}, - #endif - #ifdef SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING - {"SCSV_RECEIVED_WHEN_RENEGOTIATING", ERR_LIB_SSL, SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING}, - #else - {"SCSV_RECEIVED_WHEN_RENEGOTIATING", 20, 345}, - #endif - #ifdef SSL_R_SCT_VERIFICATION_FAILED - {"SCT_VERIFICATION_FAILED", ERR_LIB_SSL, SSL_R_SCT_VERIFICATION_FAILED}, - #else - {"SCT_VERIFICATION_FAILED", 20, 208}, - #endif - #ifdef SSL_R_SERVERHELLO_TLSEXT - {"SERVERHELLO_TLSEXT", ERR_LIB_SSL, SSL_R_SERVERHELLO_TLSEXT}, - #else - {"SERVERHELLO_TLSEXT", 20, 275}, - #endif - #ifdef SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED - {"SESSION_ID_CONTEXT_UNINITIALIZED", ERR_LIB_SSL, SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED}, - #else - {"SESSION_ID_CONTEXT_UNINITIALIZED", 20, 277}, - #endif - #ifdef SSL_R_SHUTDOWN_WHILE_IN_INIT - {"SHUTDOWN_WHILE_IN_INIT", ERR_LIB_SSL, SSL_R_SHUTDOWN_WHILE_IN_INIT}, - #else - {"SHUTDOWN_WHILE_IN_INIT", 20, 407}, - #endif - #ifdef SSL_R_SIGNATURE_ALGORITHMS_ERROR - {"SIGNATURE_ALGORITHMS_ERROR", ERR_LIB_SSL, SSL_R_SIGNATURE_ALGORITHMS_ERROR}, - #else - {"SIGNATURE_ALGORITHMS_ERROR", 20, 360}, - #endif - #ifdef SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE - {"SIGNATURE_FOR_NON_SIGNING_CERTIFICATE", ERR_LIB_SSL, SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE}, - #else - {"SIGNATURE_FOR_NON_SIGNING_CERTIFICATE", 20, 220}, - #endif - #ifdef SSL_R_SRP_A_CALC - {"SRP_A_CALC", ERR_LIB_SSL, SSL_R_SRP_A_CALC}, - #else - {"SRP_A_CALC", 20, 361}, - #endif - #ifdef SSL_R_SRTP_COULD_NOT_ALLOCATE_PROFILES - {"SRTP_COULD_NOT_ALLOCATE_PROFILES", ERR_LIB_SSL, SSL_R_SRTP_COULD_NOT_ALLOCATE_PROFILES}, - #else - {"SRTP_COULD_NOT_ALLOCATE_PROFILES", 20, 362}, - #endif - #ifdef SSL_R_SRTP_PROTECTION_PROFILE_LIST_TOO_LONG - {"SRTP_PROTECTION_PROFILE_LIST_TOO_LONG", ERR_LIB_SSL, SSL_R_SRTP_PROTECTION_PROFILE_LIST_TOO_LONG}, - #else - {"SRTP_PROTECTION_PROFILE_LIST_TOO_LONG", 20, 363}, - #endif - #ifdef SSL_R_SRTP_UNKNOWN_PROTECTION_PROFILE - {"SRTP_UNKNOWN_PROTECTION_PROFILE", ERR_LIB_SSL, SSL_R_SRTP_UNKNOWN_PROTECTION_PROFILE}, - #else - {"SRTP_UNKNOWN_PROTECTION_PROFILE", 20, 364}, - #endif - #ifdef SSL_R_SSL2_CONNECTION_ID_TOO_LONG - {"SSL2_CONNECTION_ID_TOO_LONG", ERR_LIB_SSL, SSL_R_SSL2_CONNECTION_ID_TOO_LONG}, - #else - {"SSL2_CONNECTION_ID_TOO_LONG", 20, 299}, - #endif - #ifdef SSL_R_SSL3_EXT_INVALID_ECPOINTFORMAT - {"SSL3_EXT_INVALID_ECPOINTFORMAT", ERR_LIB_SSL, SSL_R_SSL3_EXT_INVALID_ECPOINTFORMAT}, - #else - {"SSL3_EXT_INVALID_ECPOINTFORMAT", 20, 321}, - #endif - #ifdef SSL_R_SSL3_EXT_INVALID_MAX_FRAGMENT_LENGTH - {"SSL3_EXT_INVALID_MAX_FRAGMENT_LENGTH", ERR_LIB_SSL, SSL_R_SSL3_EXT_INVALID_MAX_FRAGMENT_LENGTH}, - #else - {"SSL3_EXT_INVALID_MAX_FRAGMENT_LENGTH", 20, 232}, - #endif - #ifdef SSL_R_SSL3_EXT_INVALID_SERVERNAME - {"SSL3_EXT_INVALID_SERVERNAME", ERR_LIB_SSL, SSL_R_SSL3_EXT_INVALID_SERVERNAME}, - #else - {"SSL3_EXT_INVALID_SERVERNAME", 20, 319}, - #endif - #ifdef SSL_R_SSL3_EXT_INVALID_SERVERNAME_TYPE - {"SSL3_EXT_INVALID_SERVERNAME_TYPE", ERR_LIB_SSL, SSL_R_SSL3_EXT_INVALID_SERVERNAME_TYPE}, - #else - {"SSL3_EXT_INVALID_SERVERNAME_TYPE", 20, 320}, - #endif - #ifdef SSL_R_SSL3_SESSION_ID_TOO_LONG - {"SSL3_SESSION_ID_TOO_LONG", ERR_LIB_SSL, SSL_R_SSL3_SESSION_ID_TOO_LONG}, - #else - {"SSL3_SESSION_ID_TOO_LONG", 20, 300}, - #endif - #ifdef SSL_R_SSLV3_ALERT_BAD_CERTIFICATE - {"SSLV3_ALERT_BAD_CERTIFICATE", ERR_LIB_SSL, SSL_R_SSLV3_ALERT_BAD_CERTIFICATE}, - #else - {"SSLV3_ALERT_BAD_CERTIFICATE", 20, 1042}, - #endif - #ifdef SSL_R_SSLV3_ALERT_BAD_RECORD_MAC - {"SSLV3_ALERT_BAD_RECORD_MAC", ERR_LIB_SSL, SSL_R_SSLV3_ALERT_BAD_RECORD_MAC}, - #else - {"SSLV3_ALERT_BAD_RECORD_MAC", 20, 1020}, - #endif - #ifdef SSL_R_SSLV3_ALERT_CERTIFICATE_EXPIRED - {"SSLV3_ALERT_CERTIFICATE_EXPIRED", ERR_LIB_SSL, SSL_R_SSLV3_ALERT_CERTIFICATE_EXPIRED}, - #else - {"SSLV3_ALERT_CERTIFICATE_EXPIRED", 20, 1045}, - #endif - #ifdef SSL_R_SSLV3_ALERT_CERTIFICATE_REVOKED - {"SSLV3_ALERT_CERTIFICATE_REVOKED", ERR_LIB_SSL, SSL_R_SSLV3_ALERT_CERTIFICATE_REVOKED}, - #else - {"SSLV3_ALERT_CERTIFICATE_REVOKED", 20, 1044}, - #endif - #ifdef SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN - {"SSLV3_ALERT_CERTIFICATE_UNKNOWN", ERR_LIB_SSL, SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN}, - #else - {"SSLV3_ALERT_CERTIFICATE_UNKNOWN", 20, 1046}, - #endif - #ifdef SSL_R_SSLV3_ALERT_DECOMPRESSION_FAILURE - {"SSLV3_ALERT_DECOMPRESSION_FAILURE", ERR_LIB_SSL, SSL_R_SSLV3_ALERT_DECOMPRESSION_FAILURE}, - #else - {"SSLV3_ALERT_DECOMPRESSION_FAILURE", 20, 1030}, - #endif - #ifdef SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE - {"SSLV3_ALERT_HANDSHAKE_FAILURE", ERR_LIB_SSL, SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE}, - #else - {"SSLV3_ALERT_HANDSHAKE_FAILURE", 20, 1040}, - #endif - #ifdef SSL_R_SSLV3_ALERT_ILLEGAL_PARAMETER - {"SSLV3_ALERT_ILLEGAL_PARAMETER", ERR_LIB_SSL, SSL_R_SSLV3_ALERT_ILLEGAL_PARAMETER}, - #else - {"SSLV3_ALERT_ILLEGAL_PARAMETER", 20, 1047}, - #endif - #ifdef SSL_R_SSLV3_ALERT_NO_CERTIFICATE - {"SSLV3_ALERT_NO_CERTIFICATE", ERR_LIB_SSL, SSL_R_SSLV3_ALERT_NO_CERTIFICATE}, - #else - {"SSLV3_ALERT_NO_CERTIFICATE", 20, 1041}, - #endif - #ifdef SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE - {"SSLV3_ALERT_UNEXPECTED_MESSAGE", ERR_LIB_SSL, SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE}, - #else - {"SSLV3_ALERT_UNEXPECTED_MESSAGE", 20, 1010}, - #endif - #ifdef SSL_R_SSLV3_ALERT_UNSUPPORTED_CERTIFICATE - {"SSLV3_ALERT_UNSUPPORTED_CERTIFICATE", ERR_LIB_SSL, SSL_R_SSLV3_ALERT_UNSUPPORTED_CERTIFICATE}, - #else - {"SSLV3_ALERT_UNSUPPORTED_CERTIFICATE", 20, 1043}, - #endif - #ifdef SSL_R_SSL_COMMAND_SECTION_EMPTY - {"SSL_COMMAND_SECTION_EMPTY", ERR_LIB_SSL, SSL_R_SSL_COMMAND_SECTION_EMPTY}, - #else - {"SSL_COMMAND_SECTION_EMPTY", 20, 117}, - #endif - #ifdef SSL_R_SSL_COMMAND_SECTION_NOT_FOUND - {"SSL_COMMAND_SECTION_NOT_FOUND", ERR_LIB_SSL, SSL_R_SSL_COMMAND_SECTION_NOT_FOUND}, - #else - {"SSL_COMMAND_SECTION_NOT_FOUND", 20, 125}, - #endif - #ifdef SSL_R_SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION - {"SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION", ERR_LIB_SSL, SSL_R_SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION}, - #else - {"SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION", 20, 228}, - #endif - #ifdef SSL_R_SSL_HANDSHAKE_FAILURE - {"SSL_HANDSHAKE_FAILURE", ERR_LIB_SSL, SSL_R_SSL_HANDSHAKE_FAILURE}, - #else - {"SSL_HANDSHAKE_FAILURE", 20, 229}, - #endif - #ifdef SSL_R_SSL_LIBRARY_HAS_NO_CIPHERS - {"SSL_LIBRARY_HAS_NO_CIPHERS", ERR_LIB_SSL, SSL_R_SSL_LIBRARY_HAS_NO_CIPHERS}, - #else - {"SSL_LIBRARY_HAS_NO_CIPHERS", 20, 230}, - #endif - #ifdef SSL_R_SSL_NEGATIVE_LENGTH - {"SSL_NEGATIVE_LENGTH", ERR_LIB_SSL, SSL_R_SSL_NEGATIVE_LENGTH}, - #else - {"SSL_NEGATIVE_LENGTH", 20, 372}, - #endif - #ifdef SSL_R_SSL_SECTION_EMPTY - {"SSL_SECTION_EMPTY", ERR_LIB_SSL, SSL_R_SSL_SECTION_EMPTY}, - #else - {"SSL_SECTION_EMPTY", 20, 126}, - #endif - #ifdef SSL_R_SSL_SECTION_NOT_FOUND - {"SSL_SECTION_NOT_FOUND", ERR_LIB_SSL, SSL_R_SSL_SECTION_NOT_FOUND}, - #else - {"SSL_SECTION_NOT_FOUND", 20, 136}, - #endif - #ifdef SSL_R_SSL_SESSION_ID_CALLBACK_FAILED - {"SSL_SESSION_ID_CALLBACK_FAILED", ERR_LIB_SSL, SSL_R_SSL_SESSION_ID_CALLBACK_FAILED}, - #else - {"SSL_SESSION_ID_CALLBACK_FAILED", 20, 301}, - #endif - #ifdef SSL_R_SSL_SESSION_ID_CONFLICT - {"SSL_SESSION_ID_CONFLICT", ERR_LIB_SSL, SSL_R_SSL_SESSION_ID_CONFLICT}, - #else - {"SSL_SESSION_ID_CONFLICT", 20, 302}, - #endif - #ifdef SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG - {"SSL_SESSION_ID_CONTEXT_TOO_LONG", ERR_LIB_SSL, SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG}, - #else - {"SSL_SESSION_ID_CONTEXT_TOO_LONG", 20, 273}, - #endif - #ifdef SSL_R_SSL_SESSION_ID_HAS_BAD_LENGTH - {"SSL_SESSION_ID_HAS_BAD_LENGTH", ERR_LIB_SSL, SSL_R_SSL_SESSION_ID_HAS_BAD_LENGTH}, - #else - {"SSL_SESSION_ID_HAS_BAD_LENGTH", 20, 303}, - #endif - #ifdef SSL_R_SSL_SESSION_ID_TOO_LONG - {"SSL_SESSION_ID_TOO_LONG", ERR_LIB_SSL, SSL_R_SSL_SESSION_ID_TOO_LONG}, - #else - {"SSL_SESSION_ID_TOO_LONG", 20, 408}, - #endif - #ifdef SSL_R_SSL_SESSION_VERSION_MISMATCH - {"SSL_SESSION_VERSION_MISMATCH", ERR_LIB_SSL, SSL_R_SSL_SESSION_VERSION_MISMATCH}, - #else - {"SSL_SESSION_VERSION_MISMATCH", 20, 210}, - #endif - #ifdef SSL_R_STILL_IN_INIT - {"STILL_IN_INIT", ERR_LIB_SSL, SSL_R_STILL_IN_INIT}, - #else - {"STILL_IN_INIT", 20, 121}, - #endif - #ifdef SSL_R_TLSV13_ALERT_CERTIFICATE_REQUIRED - {"TLSV13_ALERT_CERTIFICATE_REQUIRED", ERR_LIB_SSL, SSL_R_TLSV13_ALERT_CERTIFICATE_REQUIRED}, - #else - {"TLSV13_ALERT_CERTIFICATE_REQUIRED", 20, 1116}, - #endif - #ifdef SSL_R_TLSV13_ALERT_MISSING_EXTENSION - {"TLSV13_ALERT_MISSING_EXTENSION", ERR_LIB_SSL, SSL_R_TLSV13_ALERT_MISSING_EXTENSION}, - #else - {"TLSV13_ALERT_MISSING_EXTENSION", 20, 1109}, - #endif - #ifdef SSL_R_TLSV1_ALERT_ACCESS_DENIED - {"TLSV1_ALERT_ACCESS_DENIED", ERR_LIB_SSL, SSL_R_TLSV1_ALERT_ACCESS_DENIED}, - #else - {"TLSV1_ALERT_ACCESS_DENIED", 20, 1049}, - #endif - #ifdef SSL_R_TLSV1_ALERT_DECODE_ERROR - {"TLSV1_ALERT_DECODE_ERROR", ERR_LIB_SSL, SSL_R_TLSV1_ALERT_DECODE_ERROR}, - #else - {"TLSV1_ALERT_DECODE_ERROR", 20, 1050}, - #endif - #ifdef SSL_R_TLSV1_ALERT_DECRYPTION_FAILED - {"TLSV1_ALERT_DECRYPTION_FAILED", ERR_LIB_SSL, SSL_R_TLSV1_ALERT_DECRYPTION_FAILED}, - #else - {"TLSV1_ALERT_DECRYPTION_FAILED", 20, 1021}, - #endif - #ifdef SSL_R_TLSV1_ALERT_DECRYPT_ERROR - {"TLSV1_ALERT_DECRYPT_ERROR", ERR_LIB_SSL, SSL_R_TLSV1_ALERT_DECRYPT_ERROR}, - #else - {"TLSV1_ALERT_DECRYPT_ERROR", 20, 1051}, - #endif - #ifdef SSL_R_TLSV1_ALERT_EXPORT_RESTRICTION - {"TLSV1_ALERT_EXPORT_RESTRICTION", ERR_LIB_SSL, SSL_R_TLSV1_ALERT_EXPORT_RESTRICTION}, - #else - {"TLSV1_ALERT_EXPORT_RESTRICTION", 20, 1060}, - #endif - #ifdef SSL_R_TLSV1_ALERT_INAPPROPRIATE_FALLBACK - {"TLSV1_ALERT_INAPPROPRIATE_FALLBACK", ERR_LIB_SSL, SSL_R_TLSV1_ALERT_INAPPROPRIATE_FALLBACK}, - #else - {"TLSV1_ALERT_INAPPROPRIATE_FALLBACK", 20, 1086}, - #endif - #ifdef SSL_R_TLSV1_ALERT_INSUFFICIENT_SECURITY - {"TLSV1_ALERT_INSUFFICIENT_SECURITY", ERR_LIB_SSL, SSL_R_TLSV1_ALERT_INSUFFICIENT_SECURITY}, - #else - {"TLSV1_ALERT_INSUFFICIENT_SECURITY", 20, 1071}, - #endif - #ifdef SSL_R_TLSV1_ALERT_INTERNAL_ERROR - {"TLSV1_ALERT_INTERNAL_ERROR", ERR_LIB_SSL, SSL_R_TLSV1_ALERT_INTERNAL_ERROR}, - #else - {"TLSV1_ALERT_INTERNAL_ERROR", 20, 1080}, - #endif - #ifdef SSL_R_TLSV1_ALERT_NO_RENEGOTIATION - {"TLSV1_ALERT_NO_RENEGOTIATION", ERR_LIB_SSL, SSL_R_TLSV1_ALERT_NO_RENEGOTIATION}, - #else - {"TLSV1_ALERT_NO_RENEGOTIATION", 20, 1100}, - #endif - #ifdef SSL_R_TLSV1_ALERT_PROTOCOL_VERSION - {"TLSV1_ALERT_PROTOCOL_VERSION", ERR_LIB_SSL, SSL_R_TLSV1_ALERT_PROTOCOL_VERSION}, - #else - {"TLSV1_ALERT_PROTOCOL_VERSION", 20, 1070}, - #endif - #ifdef SSL_R_TLSV1_ALERT_RECORD_OVERFLOW - {"TLSV1_ALERT_RECORD_OVERFLOW", ERR_LIB_SSL, SSL_R_TLSV1_ALERT_RECORD_OVERFLOW}, - #else - {"TLSV1_ALERT_RECORD_OVERFLOW", 20, 1022}, - #endif - #ifdef SSL_R_TLSV1_ALERT_UNKNOWN_CA - {"TLSV1_ALERT_UNKNOWN_CA", ERR_LIB_SSL, SSL_R_TLSV1_ALERT_UNKNOWN_CA}, - #else - {"TLSV1_ALERT_UNKNOWN_CA", 20, 1048}, - #endif - #ifdef SSL_R_TLSV1_ALERT_USER_CANCELLED - {"TLSV1_ALERT_USER_CANCELLED", ERR_LIB_SSL, SSL_R_TLSV1_ALERT_USER_CANCELLED}, - #else - {"TLSV1_ALERT_USER_CANCELLED", 20, 1090}, - #endif - #ifdef SSL_R_TLSV1_BAD_CERTIFICATE_HASH_VALUE - {"TLSV1_BAD_CERTIFICATE_HASH_VALUE", ERR_LIB_SSL, SSL_R_TLSV1_BAD_CERTIFICATE_HASH_VALUE}, - #else - {"TLSV1_BAD_CERTIFICATE_HASH_VALUE", 20, 1114}, - #endif - #ifdef SSL_R_TLSV1_BAD_CERTIFICATE_STATUS_RESPONSE - {"TLSV1_BAD_CERTIFICATE_STATUS_RESPONSE", ERR_LIB_SSL, SSL_R_TLSV1_BAD_CERTIFICATE_STATUS_RESPONSE}, - #else - {"TLSV1_BAD_CERTIFICATE_STATUS_RESPONSE", 20, 1113}, - #endif - #ifdef SSL_R_TLSV1_CERTIFICATE_UNOBTAINABLE - {"TLSV1_CERTIFICATE_UNOBTAINABLE", ERR_LIB_SSL, SSL_R_TLSV1_CERTIFICATE_UNOBTAINABLE}, - #else - {"TLSV1_CERTIFICATE_UNOBTAINABLE", 20, 1111}, - #endif - #ifdef SSL_R_TLSV1_UNRECOGNIZED_NAME - {"TLSV1_UNRECOGNIZED_NAME", ERR_LIB_SSL, SSL_R_TLSV1_UNRECOGNIZED_NAME}, - #else - {"TLSV1_UNRECOGNIZED_NAME", 20, 1112}, - #endif - #ifdef SSL_R_TLSV1_UNSUPPORTED_EXTENSION - {"TLSV1_UNSUPPORTED_EXTENSION", ERR_LIB_SSL, SSL_R_TLSV1_UNSUPPORTED_EXTENSION}, - #else - {"TLSV1_UNSUPPORTED_EXTENSION", 20, 1110}, - #endif - #ifdef SSL_R_TLS_HEARTBEAT_PEER_DOESNT_ACCEPT - {"TLS_HEARTBEAT_PEER_DOESNT_ACCEPT", ERR_LIB_SSL, SSL_R_TLS_HEARTBEAT_PEER_DOESNT_ACCEPT}, - #else - {"TLS_HEARTBEAT_PEER_DOESNT_ACCEPT", 20, 365}, - #endif - #ifdef SSL_R_TLS_HEARTBEAT_PENDING - {"TLS_HEARTBEAT_PENDING", ERR_LIB_SSL, SSL_R_TLS_HEARTBEAT_PENDING}, - #else - {"TLS_HEARTBEAT_PENDING", 20, 366}, - #endif - #ifdef SSL_R_TLS_ILLEGAL_EXPORTER_LABEL - {"TLS_ILLEGAL_EXPORTER_LABEL", ERR_LIB_SSL, SSL_R_TLS_ILLEGAL_EXPORTER_LABEL}, - #else - {"TLS_ILLEGAL_EXPORTER_LABEL", 20, 367}, - #endif - #ifdef SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST - {"TLS_INVALID_ECPOINTFORMAT_LIST", ERR_LIB_SSL, SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST}, - #else - {"TLS_INVALID_ECPOINTFORMAT_LIST", 20, 157}, - #endif - #ifdef SSL_R_TOO_MANY_KEY_UPDATES - {"TOO_MANY_KEY_UPDATES", ERR_LIB_SSL, SSL_R_TOO_MANY_KEY_UPDATES}, - #else - {"TOO_MANY_KEY_UPDATES", 20, 132}, - #endif - #ifdef SSL_R_TOO_MANY_WARN_ALERTS - {"TOO_MANY_WARN_ALERTS", ERR_LIB_SSL, SSL_R_TOO_MANY_WARN_ALERTS}, - #else - {"TOO_MANY_WARN_ALERTS", 20, 409}, - #endif - #ifdef SSL_R_TOO_MUCH_EARLY_DATA - {"TOO_MUCH_EARLY_DATA", ERR_LIB_SSL, SSL_R_TOO_MUCH_EARLY_DATA}, - #else - {"TOO_MUCH_EARLY_DATA", 20, 164}, - #endif - #ifdef SSL_R_UNABLE_TO_DECODE_ECDH_CERTS - {"UNABLE_TO_DECODE_ECDH_CERTS", ERR_LIB_SSL, SSL_R_UNABLE_TO_DECODE_ECDH_CERTS}, - #else - {"UNABLE_TO_DECODE_ECDH_CERTS", 20, 313}, - #endif - #ifdef SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS - {"UNABLE_TO_FIND_ECDH_PARAMETERS", ERR_LIB_SSL, SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS}, - #else - {"UNABLE_TO_FIND_ECDH_PARAMETERS", 20, 314}, - #endif - #ifdef SSL_R_UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS - {"UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS", ERR_LIB_SSL, SSL_R_UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS}, - #else - {"UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS", 20, 239}, - #endif - #ifdef SSL_R_UNABLE_TO_LOAD_SSL3_MD5_ROUTINES - {"UNABLE_TO_LOAD_SSL3_MD5_ROUTINES", ERR_LIB_SSL, SSL_R_UNABLE_TO_LOAD_SSL3_MD5_ROUTINES}, - #else - {"UNABLE_TO_LOAD_SSL3_MD5_ROUTINES", 20, 242}, - #endif - #ifdef SSL_R_UNABLE_TO_LOAD_SSL3_SHA1_ROUTINES - {"UNABLE_TO_LOAD_SSL3_SHA1_ROUTINES", ERR_LIB_SSL, SSL_R_UNABLE_TO_LOAD_SSL3_SHA1_ROUTINES}, - #else - {"UNABLE_TO_LOAD_SSL3_SHA1_ROUTINES", 20, 243}, - #endif - #ifdef SSL_R_UNEXPECTED_CCS_MESSAGE - {"UNEXPECTED_CCS_MESSAGE", ERR_LIB_SSL, SSL_R_UNEXPECTED_CCS_MESSAGE}, - #else - {"UNEXPECTED_CCS_MESSAGE", 20, 262}, - #endif - #ifdef SSL_R_UNEXPECTED_END_OF_EARLY_DATA - {"UNEXPECTED_END_OF_EARLY_DATA", ERR_LIB_SSL, SSL_R_UNEXPECTED_END_OF_EARLY_DATA}, - #else - {"UNEXPECTED_END_OF_EARLY_DATA", 20, 178}, - #endif - #ifdef SSL_R_UNEXPECTED_MESSAGE - {"UNEXPECTED_MESSAGE", ERR_LIB_SSL, SSL_R_UNEXPECTED_MESSAGE}, - #else - {"UNEXPECTED_MESSAGE", 20, 244}, - #endif - #ifdef SSL_R_UNEXPECTED_RECORD - {"UNEXPECTED_RECORD", ERR_LIB_SSL, SSL_R_UNEXPECTED_RECORD}, - #else - {"UNEXPECTED_RECORD", 20, 245}, - #endif - #ifdef SSL_R_UNINITIALIZED - {"UNINITIALIZED", ERR_LIB_SSL, SSL_R_UNINITIALIZED}, - #else - {"UNINITIALIZED", 20, 276}, - #endif - #ifdef SSL_R_UNKNOWN_ALERT_TYPE - {"UNKNOWN_ALERT_TYPE", ERR_LIB_SSL, SSL_R_UNKNOWN_ALERT_TYPE}, - #else - {"UNKNOWN_ALERT_TYPE", 20, 246}, - #endif - #ifdef SSL_R_UNKNOWN_CERTIFICATE_TYPE - {"UNKNOWN_CERTIFICATE_TYPE", ERR_LIB_SSL, SSL_R_UNKNOWN_CERTIFICATE_TYPE}, - #else - {"UNKNOWN_CERTIFICATE_TYPE", 20, 247}, - #endif - #ifdef SSL_R_UNKNOWN_CIPHER_RETURNED - {"UNKNOWN_CIPHER_RETURNED", ERR_LIB_SSL, SSL_R_UNKNOWN_CIPHER_RETURNED}, - #else - {"UNKNOWN_CIPHER_RETURNED", 20, 248}, - #endif - #ifdef SSL_R_UNKNOWN_CIPHER_TYPE - {"UNKNOWN_CIPHER_TYPE", ERR_LIB_SSL, SSL_R_UNKNOWN_CIPHER_TYPE}, - #else - {"UNKNOWN_CIPHER_TYPE", 20, 249}, - #endif - #ifdef SSL_R_UNKNOWN_CMD_NAME - {"UNKNOWN_CMD_NAME", ERR_LIB_SSL, SSL_R_UNKNOWN_CMD_NAME}, - #else - {"UNKNOWN_CMD_NAME", 20, 386}, - #endif - #ifdef SSL_R_UNKNOWN_COMMAND - {"UNKNOWN_COMMAND", ERR_LIB_SSL, SSL_R_UNKNOWN_COMMAND}, - #else - {"UNKNOWN_COMMAND", 20, 139}, - #endif - #ifdef SSL_R_UNKNOWN_DIGEST - {"UNKNOWN_DIGEST", ERR_LIB_SSL, SSL_R_UNKNOWN_DIGEST}, - #else - {"UNKNOWN_DIGEST", 20, 368}, - #endif - #ifdef SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE - {"UNKNOWN_KEY_EXCHANGE_TYPE", ERR_LIB_SSL, SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE}, - #else - {"UNKNOWN_KEY_EXCHANGE_TYPE", 20, 250}, - #endif - #ifdef SSL_R_UNKNOWN_PKEY_TYPE - {"UNKNOWN_PKEY_TYPE", ERR_LIB_SSL, SSL_R_UNKNOWN_PKEY_TYPE}, - #else - {"UNKNOWN_PKEY_TYPE", 20, 251}, - #endif - #ifdef SSL_R_UNKNOWN_PROTOCOL - {"UNKNOWN_PROTOCOL", ERR_LIB_SSL, SSL_R_UNKNOWN_PROTOCOL}, - #else - {"UNKNOWN_PROTOCOL", 20, 252}, - #endif - #ifdef SSL_R_UNKNOWN_SSL_VERSION - {"UNKNOWN_SSL_VERSION", ERR_LIB_SSL, SSL_R_UNKNOWN_SSL_VERSION}, - #else - {"UNKNOWN_SSL_VERSION", 20, 254}, - #endif - #ifdef SSL_R_UNKNOWN_STATE - {"UNKNOWN_STATE", ERR_LIB_SSL, SSL_R_UNKNOWN_STATE}, - #else - {"UNKNOWN_STATE", 20, 255}, - #endif - #ifdef SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED - {"UNSAFE_LEGACY_RENEGOTIATION_DISABLED", ERR_LIB_SSL, SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED}, - #else - {"UNSAFE_LEGACY_RENEGOTIATION_DISABLED", 20, 338}, - #endif - #ifdef SSL_R_UNSOLICITED_EXTENSION - {"UNSOLICITED_EXTENSION", ERR_LIB_SSL, SSL_R_UNSOLICITED_EXTENSION}, - #else - {"UNSOLICITED_EXTENSION", 20, 217}, - #endif - #ifdef SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM - {"UNSUPPORTED_COMPRESSION_ALGORITHM", ERR_LIB_SSL, SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM}, - #else - {"UNSUPPORTED_COMPRESSION_ALGORITHM", 20, 257}, - #endif - #ifdef SSL_R_UNSUPPORTED_DIGEST_TYPE - {"UNSUPPORTED_DIGEST_TYPE", ERR_LIB_SSL, SSL_R_UNSUPPORTED_DIGEST_TYPE}, - #else - {"UNSUPPORTED_DIGEST_TYPE", 20, 326}, - #endif - #ifdef SSL_R_UNSUPPORTED_ELLIPTIC_CURVE - {"UNSUPPORTED_ELLIPTIC_CURVE", ERR_LIB_SSL, SSL_R_UNSUPPORTED_ELLIPTIC_CURVE}, - #else - {"UNSUPPORTED_ELLIPTIC_CURVE", 20, 315}, - #endif - #ifdef SSL_R_UNSUPPORTED_PROTOCOL - {"UNSUPPORTED_PROTOCOL", ERR_LIB_SSL, SSL_R_UNSUPPORTED_PROTOCOL}, - #else - {"UNSUPPORTED_PROTOCOL", 20, 258}, - #endif - #ifdef SSL_R_UNSUPPORTED_SSL_VERSION - {"UNSUPPORTED_SSL_VERSION", ERR_LIB_SSL, SSL_R_UNSUPPORTED_SSL_VERSION}, - #else - {"UNSUPPORTED_SSL_VERSION", 20, 259}, - #endif - #ifdef SSL_R_UNSUPPORTED_STATUS_TYPE - {"UNSUPPORTED_STATUS_TYPE", ERR_LIB_SSL, SSL_R_UNSUPPORTED_STATUS_TYPE}, - #else - {"UNSUPPORTED_STATUS_TYPE", 20, 329}, - #endif - #ifdef SSL_R_USE_SRTP_NOT_NEGOTIATED - {"USE_SRTP_NOT_NEGOTIATED", ERR_LIB_SSL, SSL_R_USE_SRTP_NOT_NEGOTIATED}, - #else - {"USE_SRTP_NOT_NEGOTIATED", 20, 369}, - #endif - #ifdef SSL_R_VERSION_TOO_HIGH - {"VERSION_TOO_HIGH", ERR_LIB_SSL, SSL_R_VERSION_TOO_HIGH}, - #else - {"VERSION_TOO_HIGH", 20, 166}, - #endif - #ifdef SSL_R_VERSION_TOO_LOW - {"VERSION_TOO_LOW", ERR_LIB_SSL, SSL_R_VERSION_TOO_LOW}, - #else - {"VERSION_TOO_LOW", 20, 396}, - #endif - #ifdef SSL_R_WRONG_CERTIFICATE_TYPE - {"WRONG_CERTIFICATE_TYPE", ERR_LIB_SSL, SSL_R_WRONG_CERTIFICATE_TYPE}, - #else - {"WRONG_CERTIFICATE_TYPE", 20, 383}, - #endif - #ifdef SSL_R_WRONG_CIPHER_RETURNED - {"WRONG_CIPHER_RETURNED", ERR_LIB_SSL, SSL_R_WRONG_CIPHER_RETURNED}, - #else - {"WRONG_CIPHER_RETURNED", 20, 261}, - #endif - #ifdef SSL_R_WRONG_CURVE - {"WRONG_CURVE", ERR_LIB_SSL, SSL_R_WRONG_CURVE}, - #else - {"WRONG_CURVE", 20, 378}, - #endif - #ifdef SSL_R_WRONG_SIGNATURE_LENGTH - {"WRONG_SIGNATURE_LENGTH", ERR_LIB_SSL, SSL_R_WRONG_SIGNATURE_LENGTH}, - #else - {"WRONG_SIGNATURE_LENGTH", 20, 264}, - #endif - #ifdef SSL_R_WRONG_SIGNATURE_SIZE - {"WRONG_SIGNATURE_SIZE", ERR_LIB_SSL, SSL_R_WRONG_SIGNATURE_SIZE}, - #else - {"WRONG_SIGNATURE_SIZE", 20, 265}, - #endif - #ifdef SSL_R_WRONG_SIGNATURE_TYPE - {"WRONG_SIGNATURE_TYPE", ERR_LIB_SSL, SSL_R_WRONG_SIGNATURE_TYPE}, - #else - {"WRONG_SIGNATURE_TYPE", 20, 370}, - #endif - #ifdef SSL_R_WRONG_SSL_VERSION - {"WRONG_SSL_VERSION", ERR_LIB_SSL, SSL_R_WRONG_SSL_VERSION}, - #else - {"WRONG_SSL_VERSION", 20, 266}, - #endif - #ifdef SSL_R_WRONG_VERSION_NUMBER - {"WRONG_VERSION_NUMBER", ERR_LIB_SSL, SSL_R_WRONG_VERSION_NUMBER}, - #else - {"WRONG_VERSION_NUMBER", 20, 267}, - #endif - #ifdef SSL_R_X509_LIB - {"X509_LIB", ERR_LIB_SSL, SSL_R_X509_LIB}, - #else - {"X509_LIB", 20, 268}, - #endif - #ifdef SSL_R_X509_VERIFICATION_SETUP_PROBLEMS - {"X509_VERIFICATION_SETUP_PROBLEMS", ERR_LIB_SSL, SSL_R_X509_VERIFICATION_SETUP_PROBLEMS}, - #else - {"X509_VERIFICATION_SETUP_PROBLEMS", 20, 269}, - #endif - #ifdef TS_R_BAD_PKCS7_TYPE - {"BAD_PKCS7_TYPE", ERR_LIB_TS, TS_R_BAD_PKCS7_TYPE}, - #else - {"BAD_PKCS7_TYPE", 47, 132}, - #endif - #ifdef TS_R_BAD_TYPE - {"BAD_TYPE", ERR_LIB_TS, TS_R_BAD_TYPE}, - #else - {"BAD_TYPE", 47, 133}, - #endif - #ifdef TS_R_CANNOT_LOAD_CERT - {"CANNOT_LOAD_CERT", ERR_LIB_TS, TS_R_CANNOT_LOAD_CERT}, - #else - {"CANNOT_LOAD_CERT", 47, 137}, - #endif - #ifdef TS_R_CANNOT_LOAD_KEY - {"CANNOT_LOAD_KEY", ERR_LIB_TS, TS_R_CANNOT_LOAD_KEY}, - #else - {"CANNOT_LOAD_KEY", 47, 138}, - #endif - #ifdef TS_R_CERTIFICATE_VERIFY_ERROR - {"CERTIFICATE_VERIFY_ERROR", ERR_LIB_TS, TS_R_CERTIFICATE_VERIFY_ERROR}, - #else - {"CERTIFICATE_VERIFY_ERROR", 47, 100}, - #endif - #ifdef TS_R_COULD_NOT_SET_ENGINE - {"COULD_NOT_SET_ENGINE", ERR_LIB_TS, TS_R_COULD_NOT_SET_ENGINE}, - #else - {"COULD_NOT_SET_ENGINE", 47, 127}, - #endif - #ifdef TS_R_COULD_NOT_SET_TIME - {"COULD_NOT_SET_TIME", ERR_LIB_TS, TS_R_COULD_NOT_SET_TIME}, - #else - {"COULD_NOT_SET_TIME", 47, 115}, - #endif - #ifdef TS_R_DETACHED_CONTENT - {"DETACHED_CONTENT", ERR_LIB_TS, TS_R_DETACHED_CONTENT}, - #else - {"DETACHED_CONTENT", 47, 134}, - #endif - #ifdef TS_R_ESS_ADD_SIGNING_CERT_ERROR - {"ESS_ADD_SIGNING_CERT_ERROR", ERR_LIB_TS, TS_R_ESS_ADD_SIGNING_CERT_ERROR}, - #else - {"ESS_ADD_SIGNING_CERT_ERROR", 47, 116}, - #endif - #ifdef TS_R_ESS_ADD_SIGNING_CERT_V2_ERROR - {"ESS_ADD_SIGNING_CERT_V2_ERROR", ERR_LIB_TS, TS_R_ESS_ADD_SIGNING_CERT_V2_ERROR}, - #else - {"ESS_ADD_SIGNING_CERT_V2_ERROR", 47, 139}, - #endif - #ifdef TS_R_ESS_SIGNING_CERTIFICATE_ERROR - {"ESS_SIGNING_CERTIFICATE_ERROR", ERR_LIB_TS, TS_R_ESS_SIGNING_CERTIFICATE_ERROR}, - #else - {"ESS_SIGNING_CERTIFICATE_ERROR", 47, 101}, - #endif - #ifdef TS_R_INVALID_NULL_POINTER - {"INVALID_NULL_POINTER", ERR_LIB_TS, TS_R_INVALID_NULL_POINTER}, - #else - {"INVALID_NULL_POINTER", 47, 102}, - #endif - #ifdef TS_R_INVALID_SIGNER_CERTIFICATE_PURPOSE - {"INVALID_SIGNER_CERTIFICATE_PURPOSE", ERR_LIB_TS, TS_R_INVALID_SIGNER_CERTIFICATE_PURPOSE}, - #else - {"INVALID_SIGNER_CERTIFICATE_PURPOSE", 47, 117}, - #endif - #ifdef TS_R_MESSAGE_IMPRINT_MISMATCH - {"MESSAGE_IMPRINT_MISMATCH", ERR_LIB_TS, TS_R_MESSAGE_IMPRINT_MISMATCH}, - #else - {"MESSAGE_IMPRINT_MISMATCH", 47, 103}, - #endif - #ifdef TS_R_NONCE_MISMATCH - {"NONCE_MISMATCH", ERR_LIB_TS, TS_R_NONCE_MISMATCH}, - #else - {"NONCE_MISMATCH", 47, 104}, - #endif - #ifdef TS_R_NONCE_NOT_RETURNED - {"NONCE_NOT_RETURNED", ERR_LIB_TS, TS_R_NONCE_NOT_RETURNED}, - #else - {"NONCE_NOT_RETURNED", 47, 105}, - #endif - #ifdef TS_R_NO_CONTENT - {"NO_CONTENT", ERR_LIB_TS, TS_R_NO_CONTENT}, - #else - {"NO_CONTENT", 47, 106}, - #endif - #ifdef TS_R_NO_TIME_STAMP_TOKEN - {"NO_TIME_STAMP_TOKEN", ERR_LIB_TS, TS_R_NO_TIME_STAMP_TOKEN}, - #else - {"NO_TIME_STAMP_TOKEN", 47, 107}, - #endif - #ifdef TS_R_PKCS7_ADD_SIGNATURE_ERROR - {"PKCS7_ADD_SIGNATURE_ERROR", ERR_LIB_TS, TS_R_PKCS7_ADD_SIGNATURE_ERROR}, - #else - {"PKCS7_ADD_SIGNATURE_ERROR", 47, 118}, - #endif - #ifdef TS_R_PKCS7_ADD_SIGNED_ATTR_ERROR - {"PKCS7_ADD_SIGNED_ATTR_ERROR", ERR_LIB_TS, TS_R_PKCS7_ADD_SIGNED_ATTR_ERROR}, - #else - {"PKCS7_ADD_SIGNED_ATTR_ERROR", 47, 119}, - #endif - #ifdef TS_R_PKCS7_TO_TS_TST_INFO_FAILED - {"PKCS7_TO_TS_TST_INFO_FAILED", ERR_LIB_TS, TS_R_PKCS7_TO_TS_TST_INFO_FAILED}, - #else - {"PKCS7_TO_TS_TST_INFO_FAILED", 47, 129}, - #endif - #ifdef TS_R_POLICY_MISMATCH - {"POLICY_MISMATCH", ERR_LIB_TS, TS_R_POLICY_MISMATCH}, - #else - {"POLICY_MISMATCH", 47, 108}, - #endif - #ifdef TS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE - {"PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE", ERR_LIB_TS, TS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE}, - #else - {"PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE", 47, 120}, - #endif - #ifdef TS_R_RESPONSE_SETUP_ERROR - {"RESPONSE_SETUP_ERROR", ERR_LIB_TS, TS_R_RESPONSE_SETUP_ERROR}, - #else - {"RESPONSE_SETUP_ERROR", 47, 121}, - #endif - #ifdef TS_R_SIGNATURE_FAILURE - {"SIGNATURE_FAILURE", ERR_LIB_TS, TS_R_SIGNATURE_FAILURE}, - #else - {"SIGNATURE_FAILURE", 47, 109}, - #endif - #ifdef TS_R_THERE_MUST_BE_ONE_SIGNER - {"THERE_MUST_BE_ONE_SIGNER", ERR_LIB_TS, TS_R_THERE_MUST_BE_ONE_SIGNER}, - #else - {"THERE_MUST_BE_ONE_SIGNER", 47, 110}, - #endif - #ifdef TS_R_TIME_SYSCALL_ERROR - {"TIME_SYSCALL_ERROR", ERR_LIB_TS, TS_R_TIME_SYSCALL_ERROR}, - #else - {"TIME_SYSCALL_ERROR", 47, 122}, - #endif - #ifdef TS_R_TOKEN_NOT_PRESENT - {"TOKEN_NOT_PRESENT", ERR_LIB_TS, TS_R_TOKEN_NOT_PRESENT}, - #else - {"TOKEN_NOT_PRESENT", 47, 130}, - #endif - #ifdef TS_R_TOKEN_PRESENT - {"TOKEN_PRESENT", ERR_LIB_TS, TS_R_TOKEN_PRESENT}, - #else - {"TOKEN_PRESENT", 47, 131}, - #endif - #ifdef TS_R_TSA_NAME_MISMATCH - {"TSA_NAME_MISMATCH", ERR_LIB_TS, TS_R_TSA_NAME_MISMATCH}, - #else - {"TSA_NAME_MISMATCH", 47, 111}, - #endif - #ifdef TS_R_TSA_UNTRUSTED - {"TSA_UNTRUSTED", ERR_LIB_TS, TS_R_TSA_UNTRUSTED}, - #else - {"TSA_UNTRUSTED", 47, 112}, - #endif - #ifdef TS_R_TST_INFO_SETUP_ERROR - {"TST_INFO_SETUP_ERROR", ERR_LIB_TS, TS_R_TST_INFO_SETUP_ERROR}, - #else - {"TST_INFO_SETUP_ERROR", 47, 123}, - #endif - #ifdef TS_R_TS_DATASIGN - {"TS_DATASIGN", ERR_LIB_TS, TS_R_TS_DATASIGN}, - #else - {"TS_DATASIGN", 47, 124}, - #endif - #ifdef TS_R_UNACCEPTABLE_POLICY - {"UNACCEPTABLE_POLICY", ERR_LIB_TS, TS_R_UNACCEPTABLE_POLICY}, - #else - {"UNACCEPTABLE_POLICY", 47, 125}, - #endif - #ifdef TS_R_UNSUPPORTED_MD_ALGORITHM - {"UNSUPPORTED_MD_ALGORITHM", ERR_LIB_TS, TS_R_UNSUPPORTED_MD_ALGORITHM}, - #else - {"UNSUPPORTED_MD_ALGORITHM", 47, 126}, - #endif - #ifdef TS_R_UNSUPPORTED_VERSION - {"UNSUPPORTED_VERSION", ERR_LIB_TS, TS_R_UNSUPPORTED_VERSION}, - #else - {"UNSUPPORTED_VERSION", 47, 113}, - #endif - #ifdef TS_R_VAR_BAD_VALUE - {"VAR_BAD_VALUE", ERR_LIB_TS, TS_R_VAR_BAD_VALUE}, - #else - {"VAR_BAD_VALUE", 47, 135}, - #endif - #ifdef TS_R_VAR_LOOKUP_FAILURE - {"VAR_LOOKUP_FAILURE", ERR_LIB_TS, TS_R_VAR_LOOKUP_FAILURE}, - #else - {"VAR_LOOKUP_FAILURE", 47, 136}, - #endif - #ifdef TS_R_WRONG_CONTENT_TYPE - {"WRONG_CONTENT_TYPE", ERR_LIB_TS, TS_R_WRONG_CONTENT_TYPE}, - #else - {"WRONG_CONTENT_TYPE", 47, 114}, - #endif - #ifdef UI_R_COMMON_OK_AND_CANCEL_CHARACTERS - {"COMMON_OK_AND_CANCEL_CHARACTERS", ERR_LIB_UI, UI_R_COMMON_OK_AND_CANCEL_CHARACTERS}, - #else - {"COMMON_OK_AND_CANCEL_CHARACTERS", 40, 104}, - #endif - #ifdef UI_R_INDEX_TOO_LARGE - {"INDEX_TOO_LARGE", ERR_LIB_UI, UI_R_INDEX_TOO_LARGE}, - #else - {"INDEX_TOO_LARGE", 40, 102}, - #endif - #ifdef UI_R_INDEX_TOO_SMALL - {"INDEX_TOO_SMALL", ERR_LIB_UI, UI_R_INDEX_TOO_SMALL}, - #else - {"INDEX_TOO_SMALL", 40, 103}, - #endif - #ifdef UI_R_NO_RESULT_BUFFER - {"NO_RESULT_BUFFER", ERR_LIB_UI, UI_R_NO_RESULT_BUFFER}, - #else - {"NO_RESULT_BUFFER", 40, 105}, - #endif - #ifdef UI_R_PROCESSING_ERROR - {"PROCESSING_ERROR", ERR_LIB_UI, UI_R_PROCESSING_ERROR}, - #else - {"PROCESSING_ERROR", 40, 107}, - #endif - #ifdef UI_R_RESULT_TOO_LARGE - {"RESULT_TOO_LARGE", ERR_LIB_UI, UI_R_RESULT_TOO_LARGE}, - #else - {"RESULT_TOO_LARGE", 40, 100}, - #endif - #ifdef UI_R_RESULT_TOO_SMALL - {"RESULT_TOO_SMALL", ERR_LIB_UI, UI_R_RESULT_TOO_SMALL}, - #else - {"RESULT_TOO_SMALL", 40, 101}, - #endif - #ifdef UI_R_SYSASSIGN_ERROR - {"SYSASSIGN_ERROR", ERR_LIB_UI, UI_R_SYSASSIGN_ERROR}, - #else - {"SYSASSIGN_ERROR", 40, 109}, - #endif - #ifdef UI_R_SYSDASSGN_ERROR - {"SYSDASSGN_ERROR", ERR_LIB_UI, UI_R_SYSDASSGN_ERROR}, - #else - {"SYSDASSGN_ERROR", 40, 110}, - #endif - #ifdef UI_R_SYSQIOW_ERROR - {"SYSQIOW_ERROR", ERR_LIB_UI, UI_R_SYSQIOW_ERROR}, - #else - {"SYSQIOW_ERROR", 40, 111}, - #endif - #ifdef UI_R_UNKNOWN_CONTROL_COMMAND - {"UNKNOWN_CONTROL_COMMAND", ERR_LIB_UI, UI_R_UNKNOWN_CONTROL_COMMAND}, - #else - {"UNKNOWN_CONTROL_COMMAND", 40, 106}, - #endif - #ifdef UI_R_UNKNOWN_TTYGET_ERRNO_VALUE - {"UNKNOWN_TTYGET_ERRNO_VALUE", ERR_LIB_UI, UI_R_UNKNOWN_TTYGET_ERRNO_VALUE}, - #else - {"UNKNOWN_TTYGET_ERRNO_VALUE", 40, 108}, - #endif - #ifdef UI_R_USER_DATA_DUPLICATION_UNSUPPORTED - {"USER_DATA_DUPLICATION_UNSUPPORTED", ERR_LIB_UI, UI_R_USER_DATA_DUPLICATION_UNSUPPORTED}, - #else - {"USER_DATA_DUPLICATION_UNSUPPORTED", 40, 112}, - #endif - #ifdef X509V3_R_BAD_IP_ADDRESS - {"BAD_IP_ADDRESS", ERR_LIB_X509V3, X509V3_R_BAD_IP_ADDRESS}, - #else - {"BAD_IP_ADDRESS", 34, 118}, - #endif - #ifdef X509V3_R_BAD_OBJECT - {"BAD_OBJECT", ERR_LIB_X509V3, X509V3_R_BAD_OBJECT}, - #else - {"BAD_OBJECT", 34, 119}, - #endif - #ifdef X509V3_R_BN_DEC2BN_ERROR - {"BN_DEC2BN_ERROR", ERR_LIB_X509V3, X509V3_R_BN_DEC2BN_ERROR}, - #else - {"BN_DEC2BN_ERROR", 34, 100}, - #endif - #ifdef X509V3_R_BN_TO_ASN1_INTEGER_ERROR - {"BN_TO_ASN1_INTEGER_ERROR", ERR_LIB_X509V3, X509V3_R_BN_TO_ASN1_INTEGER_ERROR}, - #else - {"BN_TO_ASN1_INTEGER_ERROR", 34, 101}, - #endif - #ifdef X509V3_R_DIRNAME_ERROR - {"DIRNAME_ERROR", ERR_LIB_X509V3, X509V3_R_DIRNAME_ERROR}, - #else - {"DIRNAME_ERROR", 34, 149}, - #endif - #ifdef X509V3_R_DISTPOINT_ALREADY_SET - {"DISTPOINT_ALREADY_SET", ERR_LIB_X509V3, X509V3_R_DISTPOINT_ALREADY_SET}, - #else - {"DISTPOINT_ALREADY_SET", 34, 160}, - #endif - #ifdef X509V3_R_DUPLICATE_ZONE_ID - {"DUPLICATE_ZONE_ID", ERR_LIB_X509V3, X509V3_R_DUPLICATE_ZONE_ID}, - #else - {"DUPLICATE_ZONE_ID", 34, 133}, - #endif - #ifdef X509V3_R_ERROR_CONVERTING_ZONE - {"ERROR_CONVERTING_ZONE", ERR_LIB_X509V3, X509V3_R_ERROR_CONVERTING_ZONE}, - #else - {"ERROR_CONVERTING_ZONE", 34, 131}, - #endif - #ifdef X509V3_R_ERROR_CREATING_EXTENSION - {"ERROR_CREATING_EXTENSION", ERR_LIB_X509V3, X509V3_R_ERROR_CREATING_EXTENSION}, - #else - {"ERROR_CREATING_EXTENSION", 34, 144}, - #endif - #ifdef X509V3_R_ERROR_IN_EXTENSION - {"ERROR_IN_EXTENSION", ERR_LIB_X509V3, X509V3_R_ERROR_IN_EXTENSION}, - #else - {"ERROR_IN_EXTENSION", 34, 128}, - #endif - #ifdef X509V3_R_EXPECTED_A_SECTION_NAME - {"EXPECTED_A_SECTION_NAME", ERR_LIB_X509V3, X509V3_R_EXPECTED_A_SECTION_NAME}, - #else - {"EXPECTED_A_SECTION_NAME", 34, 137}, - #endif - #ifdef X509V3_R_EXTENSION_EXISTS - {"EXTENSION_EXISTS", ERR_LIB_X509V3, X509V3_R_EXTENSION_EXISTS}, - #else - {"EXTENSION_EXISTS", 34, 145}, - #endif - #ifdef X509V3_R_EXTENSION_NAME_ERROR - {"EXTENSION_NAME_ERROR", ERR_LIB_X509V3, X509V3_R_EXTENSION_NAME_ERROR}, - #else - {"EXTENSION_NAME_ERROR", 34, 115}, - #endif - #ifdef X509V3_R_EXTENSION_NOT_FOUND - {"EXTENSION_NOT_FOUND", ERR_LIB_X509V3, X509V3_R_EXTENSION_NOT_FOUND}, - #else - {"EXTENSION_NOT_FOUND", 34, 102}, - #endif - #ifdef X509V3_R_EXTENSION_SETTING_NOT_SUPPORTED - {"EXTENSION_SETTING_NOT_SUPPORTED", ERR_LIB_X509V3, X509V3_R_EXTENSION_SETTING_NOT_SUPPORTED}, - #else - {"EXTENSION_SETTING_NOT_SUPPORTED", 34, 103}, - #endif - #ifdef X509V3_R_EXTENSION_VALUE_ERROR - {"EXTENSION_VALUE_ERROR", ERR_LIB_X509V3, X509V3_R_EXTENSION_VALUE_ERROR}, - #else - {"EXTENSION_VALUE_ERROR", 34, 116}, - #endif - #ifdef X509V3_R_ILLEGAL_EMPTY_EXTENSION - {"ILLEGAL_EMPTY_EXTENSION", ERR_LIB_X509V3, X509V3_R_ILLEGAL_EMPTY_EXTENSION}, - #else - {"ILLEGAL_EMPTY_EXTENSION", 34, 151}, - #endif - #ifdef X509V3_R_INCORRECT_POLICY_SYNTAX_TAG - {"INCORRECT_POLICY_SYNTAX_TAG", ERR_LIB_X509V3, X509V3_R_INCORRECT_POLICY_SYNTAX_TAG}, - #else - {"INCORRECT_POLICY_SYNTAX_TAG", 34, 152}, - #endif - #ifdef X509V3_R_INVALID_ASNUMBER - {"INVALID_ASNUMBER", ERR_LIB_X509V3, X509V3_R_INVALID_ASNUMBER}, - #else - {"INVALID_ASNUMBER", 34, 162}, - #endif - #ifdef X509V3_R_INVALID_ASRANGE - {"INVALID_ASRANGE", ERR_LIB_X509V3, X509V3_R_INVALID_ASRANGE}, - #else - {"INVALID_ASRANGE", 34, 163}, - #endif - #ifdef X509V3_R_INVALID_BOOLEAN_STRING - {"INVALID_BOOLEAN_STRING", ERR_LIB_X509V3, X509V3_R_INVALID_BOOLEAN_STRING}, - #else - {"INVALID_BOOLEAN_STRING", 34, 104}, - #endif - #ifdef X509V3_R_INVALID_EXTENSION_STRING - {"INVALID_EXTENSION_STRING", ERR_LIB_X509V3, X509V3_R_INVALID_EXTENSION_STRING}, - #else - {"INVALID_EXTENSION_STRING", 34, 105}, - #endif - #ifdef X509V3_R_INVALID_INHERITANCE - {"INVALID_INHERITANCE", ERR_LIB_X509V3, X509V3_R_INVALID_INHERITANCE}, - #else - {"INVALID_INHERITANCE", 34, 165}, - #endif - #ifdef X509V3_R_INVALID_IPADDRESS - {"INVALID_IPADDRESS", ERR_LIB_X509V3, X509V3_R_INVALID_IPADDRESS}, - #else - {"INVALID_IPADDRESS", 34, 166}, - #endif - #ifdef X509V3_R_INVALID_MULTIPLE_RDNS - {"INVALID_MULTIPLE_RDNS", ERR_LIB_X509V3, X509V3_R_INVALID_MULTIPLE_RDNS}, - #else - {"INVALID_MULTIPLE_RDNS", 34, 161}, - #endif - #ifdef X509V3_R_INVALID_NAME - {"INVALID_NAME", ERR_LIB_X509V3, X509V3_R_INVALID_NAME}, - #else - {"INVALID_NAME", 34, 106}, - #endif - #ifdef X509V3_R_INVALID_NULL_ARGUMENT - {"INVALID_NULL_ARGUMENT", ERR_LIB_X509V3, X509V3_R_INVALID_NULL_ARGUMENT}, - #else - {"INVALID_NULL_ARGUMENT", 34, 107}, - #endif - #ifdef X509V3_R_INVALID_NULL_NAME - {"INVALID_NULL_NAME", ERR_LIB_X509V3, X509V3_R_INVALID_NULL_NAME}, - #else - {"INVALID_NULL_NAME", 34, 108}, - #endif - #ifdef X509V3_R_INVALID_NULL_VALUE - {"INVALID_NULL_VALUE", ERR_LIB_X509V3, X509V3_R_INVALID_NULL_VALUE}, - #else - {"INVALID_NULL_VALUE", 34, 109}, - #endif - #ifdef X509V3_R_INVALID_NUMBER - {"INVALID_NUMBER", ERR_LIB_X509V3, X509V3_R_INVALID_NUMBER}, - #else - {"INVALID_NUMBER", 34, 140}, - #endif - #ifdef X509V3_R_INVALID_NUMBERS - {"INVALID_NUMBERS", ERR_LIB_X509V3, X509V3_R_INVALID_NUMBERS}, - #else - {"INVALID_NUMBERS", 34, 141}, - #endif - #ifdef X509V3_R_INVALID_OBJECT_IDENTIFIER - {"INVALID_OBJECT_IDENTIFIER", ERR_LIB_X509V3, X509V3_R_INVALID_OBJECT_IDENTIFIER}, - #else - {"INVALID_OBJECT_IDENTIFIER", 34, 110}, - #endif - #ifdef X509V3_R_INVALID_OPTION - {"INVALID_OPTION", ERR_LIB_X509V3, X509V3_R_INVALID_OPTION}, - #else - {"INVALID_OPTION", 34, 138}, - #endif - #ifdef X509V3_R_INVALID_POLICY_IDENTIFIER - {"INVALID_POLICY_IDENTIFIER", ERR_LIB_X509V3, X509V3_R_INVALID_POLICY_IDENTIFIER}, - #else - {"INVALID_POLICY_IDENTIFIER", 34, 134}, - #endif - #ifdef X509V3_R_INVALID_PROXY_POLICY_SETTING - {"INVALID_PROXY_POLICY_SETTING", ERR_LIB_X509V3, X509V3_R_INVALID_PROXY_POLICY_SETTING}, - #else - {"INVALID_PROXY_POLICY_SETTING", 34, 153}, - #endif - #ifdef X509V3_R_INVALID_PURPOSE - {"INVALID_PURPOSE", ERR_LIB_X509V3, X509V3_R_INVALID_PURPOSE}, - #else - {"INVALID_PURPOSE", 34, 146}, - #endif - #ifdef X509V3_R_INVALID_SAFI - {"INVALID_SAFI", ERR_LIB_X509V3, X509V3_R_INVALID_SAFI}, - #else - {"INVALID_SAFI", 34, 164}, - #endif - #ifdef X509V3_R_INVALID_SECTION - {"INVALID_SECTION", ERR_LIB_X509V3, X509V3_R_INVALID_SECTION}, - #else - {"INVALID_SECTION", 34, 135}, - #endif - #ifdef X509V3_R_INVALID_SYNTAX - {"INVALID_SYNTAX", ERR_LIB_X509V3, X509V3_R_INVALID_SYNTAX}, - #else - {"INVALID_SYNTAX", 34, 143}, - #endif - #ifdef X509V3_R_ISSUER_DECODE_ERROR - {"ISSUER_DECODE_ERROR", ERR_LIB_X509V3, X509V3_R_ISSUER_DECODE_ERROR}, - #else - {"ISSUER_DECODE_ERROR", 34, 126}, - #endif - #ifdef X509V3_R_MISSING_VALUE - {"MISSING_VALUE", ERR_LIB_X509V3, X509V3_R_MISSING_VALUE}, - #else - {"MISSING_VALUE", 34, 124}, - #endif - #ifdef X509V3_R_NEED_ORGANIZATION_AND_NUMBERS - {"NEED_ORGANIZATION_AND_NUMBERS", ERR_LIB_X509V3, X509V3_R_NEED_ORGANIZATION_AND_NUMBERS}, - #else - {"NEED_ORGANIZATION_AND_NUMBERS", 34, 142}, - #endif - #ifdef X509V3_R_NO_CONFIG_DATABASE - {"NO_CONFIG_DATABASE", ERR_LIB_X509V3, X509V3_R_NO_CONFIG_DATABASE}, - #else - {"NO_CONFIG_DATABASE", 34, 136}, - #endif - #ifdef X509V3_R_NO_ISSUER_CERTIFICATE - {"NO_ISSUER_CERTIFICATE", ERR_LIB_X509V3, X509V3_R_NO_ISSUER_CERTIFICATE}, - #else - {"NO_ISSUER_CERTIFICATE", 34, 121}, - #endif - #ifdef X509V3_R_NO_ISSUER_DETAILS - {"NO_ISSUER_DETAILS", ERR_LIB_X509V3, X509V3_R_NO_ISSUER_DETAILS}, - #else - {"NO_ISSUER_DETAILS", 34, 127}, - #endif - #ifdef X509V3_R_NO_POLICY_IDENTIFIER - {"NO_POLICY_IDENTIFIER", ERR_LIB_X509V3, X509V3_R_NO_POLICY_IDENTIFIER}, - #else - {"NO_POLICY_IDENTIFIER", 34, 139}, - #endif - #ifdef X509V3_R_NO_PROXY_CERT_POLICY_LANGUAGE_DEFINED - {"NO_PROXY_CERT_POLICY_LANGUAGE_DEFINED", ERR_LIB_X509V3, X509V3_R_NO_PROXY_CERT_POLICY_LANGUAGE_DEFINED}, - #else - {"NO_PROXY_CERT_POLICY_LANGUAGE_DEFINED", 34, 154}, - #endif - #ifdef X509V3_R_NO_PUBLIC_KEY - {"NO_PUBLIC_KEY", ERR_LIB_X509V3, X509V3_R_NO_PUBLIC_KEY}, - #else - {"NO_PUBLIC_KEY", 34, 114}, - #endif - #ifdef X509V3_R_NO_SUBJECT_DETAILS - {"NO_SUBJECT_DETAILS", ERR_LIB_X509V3, X509V3_R_NO_SUBJECT_DETAILS}, - #else - {"NO_SUBJECT_DETAILS", 34, 125}, - #endif - #ifdef X509V3_R_OPERATION_NOT_DEFINED - {"OPERATION_NOT_DEFINED", ERR_LIB_X509V3, X509V3_R_OPERATION_NOT_DEFINED}, - #else - {"OPERATION_NOT_DEFINED", 34, 148}, - #endif - #ifdef X509V3_R_OTHERNAME_ERROR - {"OTHERNAME_ERROR", ERR_LIB_X509V3, X509V3_R_OTHERNAME_ERROR}, - #else - {"OTHERNAME_ERROR", 34, 147}, - #endif - #ifdef X509V3_R_POLICY_LANGUAGE_ALREADY_DEFINED - {"POLICY_LANGUAGE_ALREADY_DEFINED", ERR_LIB_X509V3, X509V3_R_POLICY_LANGUAGE_ALREADY_DEFINED}, - #else - {"POLICY_LANGUAGE_ALREADY_DEFINED", 34, 155}, - #endif - #ifdef X509V3_R_POLICY_PATH_LENGTH - {"POLICY_PATH_LENGTH", ERR_LIB_X509V3, X509V3_R_POLICY_PATH_LENGTH}, - #else - {"POLICY_PATH_LENGTH", 34, 156}, - #endif - #ifdef X509V3_R_POLICY_PATH_LENGTH_ALREADY_DEFINED - {"POLICY_PATH_LENGTH_ALREADY_DEFINED", ERR_LIB_X509V3, X509V3_R_POLICY_PATH_LENGTH_ALREADY_DEFINED}, - #else - {"POLICY_PATH_LENGTH_ALREADY_DEFINED", 34, 157}, - #endif - #ifdef X509V3_R_POLICY_WHEN_PROXY_LANGUAGE_REQUIRES_NO_POLICY - {"POLICY_WHEN_PROXY_LANGUAGE_REQUIRES_NO_POLICY", ERR_LIB_X509V3, X509V3_R_POLICY_WHEN_PROXY_LANGUAGE_REQUIRES_NO_POLICY}, - #else - {"POLICY_WHEN_PROXY_LANGUAGE_REQUIRES_NO_POLICY", 34, 159}, - #endif - #ifdef X509V3_R_SECTION_NOT_FOUND - {"SECTION_NOT_FOUND", ERR_LIB_X509V3, X509V3_R_SECTION_NOT_FOUND}, - #else - {"SECTION_NOT_FOUND", 34, 150}, - #endif - #ifdef X509V3_R_UNABLE_TO_GET_ISSUER_DETAILS - {"UNABLE_TO_GET_ISSUER_DETAILS", ERR_LIB_X509V3, X509V3_R_UNABLE_TO_GET_ISSUER_DETAILS}, - #else - {"UNABLE_TO_GET_ISSUER_DETAILS", 34, 122}, - #endif - #ifdef X509V3_R_UNABLE_TO_GET_ISSUER_KEYID - {"UNABLE_TO_GET_ISSUER_KEYID", ERR_LIB_X509V3, X509V3_R_UNABLE_TO_GET_ISSUER_KEYID}, - #else - {"UNABLE_TO_GET_ISSUER_KEYID", 34, 123}, - #endif - #ifdef X509V3_R_UNKNOWN_BIT_STRING_ARGUMENT - {"UNKNOWN_BIT_STRING_ARGUMENT", ERR_LIB_X509V3, X509V3_R_UNKNOWN_BIT_STRING_ARGUMENT}, - #else - {"UNKNOWN_BIT_STRING_ARGUMENT", 34, 111}, - #endif - #ifdef X509V3_R_UNKNOWN_EXTENSION - {"UNKNOWN_EXTENSION", ERR_LIB_X509V3, X509V3_R_UNKNOWN_EXTENSION}, - #else - {"UNKNOWN_EXTENSION", 34, 129}, - #endif - #ifdef X509V3_R_UNKNOWN_EXTENSION_NAME - {"UNKNOWN_EXTENSION_NAME", ERR_LIB_X509V3, X509V3_R_UNKNOWN_EXTENSION_NAME}, - #else - {"UNKNOWN_EXTENSION_NAME", 34, 130}, - #endif - #ifdef X509V3_R_UNKNOWN_OPTION - {"UNKNOWN_OPTION", ERR_LIB_X509V3, X509V3_R_UNKNOWN_OPTION}, - #else - {"UNKNOWN_OPTION", 34, 120}, - #endif - #ifdef X509V3_R_UNSUPPORTED_OPTION - {"UNSUPPORTED_OPTION", ERR_LIB_X509V3, X509V3_R_UNSUPPORTED_OPTION}, - #else - {"UNSUPPORTED_OPTION", 34, 117}, - #endif - #ifdef X509V3_R_UNSUPPORTED_TYPE - {"UNSUPPORTED_TYPE", ERR_LIB_X509V3, X509V3_R_UNSUPPORTED_TYPE}, - #else - {"UNSUPPORTED_TYPE", 34, 167}, - #endif - #ifdef X509V3_R_USER_TOO_LONG - {"USER_TOO_LONG", ERR_LIB_X509V3, X509V3_R_USER_TOO_LONG}, - #else - {"USER_TOO_LONG", 34, 132}, - #endif - #ifdef X509_R_AKID_MISMATCH - {"AKID_MISMATCH", ERR_LIB_X509, X509_R_AKID_MISMATCH}, - #else - {"AKID_MISMATCH", 11, 110}, - #endif - #ifdef X509_R_BAD_SELECTOR - {"BAD_SELECTOR", ERR_LIB_X509, X509_R_BAD_SELECTOR}, - #else - {"BAD_SELECTOR", 11, 133}, - #endif - #ifdef X509_R_BAD_X509_FILETYPE - {"BAD_X509_FILETYPE", ERR_LIB_X509, X509_R_BAD_X509_FILETYPE}, - #else - {"BAD_X509_FILETYPE", 11, 100}, - #endif - #ifdef X509_R_BASE64_DECODE_ERROR - {"BASE64_DECODE_ERROR", ERR_LIB_X509, X509_R_BASE64_DECODE_ERROR}, - #else - {"BASE64_DECODE_ERROR", 11, 118}, - #endif - #ifdef X509_R_CANT_CHECK_DH_KEY - {"CANT_CHECK_DH_KEY", ERR_LIB_X509, X509_R_CANT_CHECK_DH_KEY}, - #else - {"CANT_CHECK_DH_KEY", 11, 114}, - #endif - #ifdef X509_R_CERT_ALREADY_IN_HASH_TABLE - {"CERT_ALREADY_IN_HASH_TABLE", ERR_LIB_X509, X509_R_CERT_ALREADY_IN_HASH_TABLE}, - #else - {"CERT_ALREADY_IN_HASH_TABLE", 11, 101}, - #endif - #ifdef X509_R_CRL_ALREADY_DELTA - {"CRL_ALREADY_DELTA", ERR_LIB_X509, X509_R_CRL_ALREADY_DELTA}, - #else - {"CRL_ALREADY_DELTA", 11, 127}, - #endif - #ifdef X509_R_CRL_VERIFY_FAILURE - {"CRL_VERIFY_FAILURE", ERR_LIB_X509, X509_R_CRL_VERIFY_FAILURE}, - #else - {"CRL_VERIFY_FAILURE", 11, 131}, - #endif - #ifdef X509_R_ERR_ASN1_LIB - {"ERR_ASN1_LIB", ERR_LIB_X509, X509_R_ERR_ASN1_LIB}, - #else - {"ERR_ASN1_LIB", 11, 102}, - #endif - #ifdef X509_R_IDP_MISMATCH - {"IDP_MISMATCH", ERR_LIB_X509, X509_R_IDP_MISMATCH}, - #else - {"IDP_MISMATCH", 11, 128}, - #endif - #ifdef X509_R_INVALID_ATTRIBUTES - {"INVALID_ATTRIBUTES", ERR_LIB_X509, X509_R_INVALID_ATTRIBUTES}, - #else - {"INVALID_ATTRIBUTES", 11, 138}, - #endif - #ifdef X509_R_INVALID_DIRECTORY - {"INVALID_DIRECTORY", ERR_LIB_X509, X509_R_INVALID_DIRECTORY}, - #else - {"INVALID_DIRECTORY", 11, 113}, - #endif - #ifdef X509_R_INVALID_FIELD_NAME - {"INVALID_FIELD_NAME", ERR_LIB_X509, X509_R_INVALID_FIELD_NAME}, - #else - {"INVALID_FIELD_NAME", 11, 119}, - #endif - #ifdef X509_R_INVALID_TRUST - {"INVALID_TRUST", ERR_LIB_X509, X509_R_INVALID_TRUST}, - #else - {"INVALID_TRUST", 11, 123}, - #endif - #ifdef X509_R_ISSUER_MISMATCH - {"ISSUER_MISMATCH", ERR_LIB_X509, X509_R_ISSUER_MISMATCH}, - #else - {"ISSUER_MISMATCH", 11, 129}, - #endif - #ifdef X509_R_KEY_TYPE_MISMATCH - {"KEY_TYPE_MISMATCH", ERR_LIB_X509, X509_R_KEY_TYPE_MISMATCH}, - #else - {"KEY_TYPE_MISMATCH", 11, 115}, - #endif - #ifdef X509_R_KEY_VALUES_MISMATCH - {"KEY_VALUES_MISMATCH", ERR_LIB_X509, X509_R_KEY_VALUES_MISMATCH}, - #else - {"KEY_VALUES_MISMATCH", 11, 116}, - #endif - #ifdef X509_R_LOADING_CERT_DIR - {"LOADING_CERT_DIR", ERR_LIB_X509, X509_R_LOADING_CERT_DIR}, - #else - {"LOADING_CERT_DIR", 11, 103}, - #endif - #ifdef X509_R_LOADING_DEFAULTS - {"LOADING_DEFAULTS", ERR_LIB_X509, X509_R_LOADING_DEFAULTS}, - #else - {"LOADING_DEFAULTS", 11, 104}, - #endif - #ifdef X509_R_METHOD_NOT_SUPPORTED - {"METHOD_NOT_SUPPORTED", ERR_LIB_X509, X509_R_METHOD_NOT_SUPPORTED}, - #else - {"METHOD_NOT_SUPPORTED", 11, 124}, - #endif - #ifdef X509_R_NAME_TOO_LONG - {"NAME_TOO_LONG", ERR_LIB_X509, X509_R_NAME_TOO_LONG}, - #else - {"NAME_TOO_LONG", 11, 134}, - #endif - #ifdef X509_R_NEWER_CRL_NOT_NEWER - {"NEWER_CRL_NOT_NEWER", ERR_LIB_X509, X509_R_NEWER_CRL_NOT_NEWER}, - #else - {"NEWER_CRL_NOT_NEWER", 11, 132}, - #endif - #ifdef X509_R_NO_CERTIFICATE_FOUND - {"NO_CERTIFICATE_FOUND", ERR_LIB_X509, X509_R_NO_CERTIFICATE_FOUND}, - #else - {"NO_CERTIFICATE_FOUND", 11, 135}, - #endif - #ifdef X509_R_NO_CERTIFICATE_OR_CRL_FOUND - {"NO_CERTIFICATE_OR_CRL_FOUND", ERR_LIB_X509, X509_R_NO_CERTIFICATE_OR_CRL_FOUND}, - #else - {"NO_CERTIFICATE_OR_CRL_FOUND", 11, 136}, - #endif - #ifdef X509_R_NO_CERT_SET_FOR_US_TO_VERIFY - {"NO_CERT_SET_FOR_US_TO_VERIFY", ERR_LIB_X509, X509_R_NO_CERT_SET_FOR_US_TO_VERIFY}, - #else - {"NO_CERT_SET_FOR_US_TO_VERIFY", 11, 105}, - #endif - #ifdef X509_R_NO_CRL_FOUND - {"NO_CRL_FOUND", ERR_LIB_X509, X509_R_NO_CRL_FOUND}, - #else - {"NO_CRL_FOUND", 11, 137}, - #endif - #ifdef X509_R_NO_CRL_NUMBER - {"NO_CRL_NUMBER", ERR_LIB_X509, X509_R_NO_CRL_NUMBER}, - #else - {"NO_CRL_NUMBER", 11, 130}, - #endif - #ifdef X509_R_PUBLIC_KEY_DECODE_ERROR - {"PUBLIC_KEY_DECODE_ERROR", ERR_LIB_X509, X509_R_PUBLIC_KEY_DECODE_ERROR}, - #else - {"PUBLIC_KEY_DECODE_ERROR", 11, 125}, - #endif - #ifdef X509_R_PUBLIC_KEY_ENCODE_ERROR - {"PUBLIC_KEY_ENCODE_ERROR", ERR_LIB_X509, X509_R_PUBLIC_KEY_ENCODE_ERROR}, - #else - {"PUBLIC_KEY_ENCODE_ERROR", 11, 126}, - #endif - #ifdef X509_R_SHOULD_RETRY - {"SHOULD_RETRY", ERR_LIB_X509, X509_R_SHOULD_RETRY}, - #else - {"SHOULD_RETRY", 11, 106}, - #endif - #ifdef X509_R_UNABLE_TO_FIND_PARAMETERS_IN_CHAIN - {"UNABLE_TO_FIND_PARAMETERS_IN_CHAIN", ERR_LIB_X509, X509_R_UNABLE_TO_FIND_PARAMETERS_IN_CHAIN}, - #else - {"UNABLE_TO_FIND_PARAMETERS_IN_CHAIN", 11, 107}, - #endif - #ifdef X509_R_UNABLE_TO_GET_CERTS_PUBLIC_KEY - {"UNABLE_TO_GET_CERTS_PUBLIC_KEY", ERR_LIB_X509, X509_R_UNABLE_TO_GET_CERTS_PUBLIC_KEY}, - #else - {"UNABLE_TO_GET_CERTS_PUBLIC_KEY", 11, 108}, - #endif - #ifdef X509_R_UNKNOWN_KEY_TYPE - {"UNKNOWN_KEY_TYPE", ERR_LIB_X509, X509_R_UNKNOWN_KEY_TYPE}, - #else - {"UNKNOWN_KEY_TYPE", 11, 117}, - #endif - #ifdef X509_R_UNKNOWN_NID - {"UNKNOWN_NID", ERR_LIB_X509, X509_R_UNKNOWN_NID}, - #else - {"UNKNOWN_NID", 11, 109}, - #endif - #ifdef X509_R_UNKNOWN_PURPOSE_ID - {"UNKNOWN_PURPOSE_ID", ERR_LIB_X509, X509_R_UNKNOWN_PURPOSE_ID}, - #else - {"UNKNOWN_PURPOSE_ID", 11, 121}, - #endif - #ifdef X509_R_UNKNOWN_TRUST_ID - {"UNKNOWN_TRUST_ID", ERR_LIB_X509, X509_R_UNKNOWN_TRUST_ID}, - #else - {"UNKNOWN_TRUST_ID", 11, 120}, - #endif - #ifdef X509_R_UNSUPPORTED_ALGORITHM - {"UNSUPPORTED_ALGORITHM", ERR_LIB_X509, X509_R_UNSUPPORTED_ALGORITHM}, - #else - {"UNSUPPORTED_ALGORITHM", 11, 111}, - #endif - #ifdef X509_R_WRONG_LOOKUP_TYPE - {"WRONG_LOOKUP_TYPE", ERR_LIB_X509, X509_R_WRONG_LOOKUP_TYPE}, - #else - {"WRONG_LOOKUP_TYPE", 11, 112}, - #endif - #ifdef X509_R_WRONG_TYPE - {"WRONG_TYPE", ERR_LIB_X509, X509_R_WRONG_TYPE}, - #else - {"WRONG_TYPE", 11, 122}, - #endif - { NULL } -}; diff --git a/Modules/_stat.c b/Modules/_stat.c index 6cea26175dee5e..80f8a92668976b 100644 --- a/Modules/_stat.c +++ b/Modules/_stat.c @@ -11,12 +11,15 @@ * */ -#include "Python.h" +#include "pyconfig.h" // Py_GIL_DISABLED -#ifdef __cplusplus -extern "C" { +#ifndef Py_GIL_DISABLED +// Need limited C API version 3.13 for PyModule_Add() on Windows +#define Py_LIMITED_API 0x030d0000 #endif +#include "Python.h" + #ifdef HAVE_SYS_TYPES_H #include #endif /* HAVE_SYS_TYPES_H */ @@ -631,7 +634,3 @@ PyInit__stat(void) { return PyModuleDef_Init(&statmodule); } - -#ifdef __cplusplus -} -#endif diff --git a/Modules/_statisticsmodule.c b/Modules/_statisticsmodule.c index 1d5465fbe6d04e..a04a2a779a5d3d 100644 --- a/Modules/_statisticsmodule.c +++ b/Modules/_statisticsmodule.c @@ -1,5 +1,10 @@ /* statistics accelerator C extension: _statistics module. */ +// clinic/_statisticsmodule.c.h uses internal pycore_modsupport.h API +#ifndef Py_BUILD_CORE_BUILTIN +# define Py_BUILD_CORE_MODULE 1 +#endif + #include "Python.h" #include "clinic/_statisticsmodule.c.h" diff --git a/Modules/_struct.c b/Modules/_struct.c index 425715ad030d4d..bd16fa89f18945 100644 --- a/Modules/_struct.c +++ b/Modules/_struct.c @@ -9,9 +9,9 @@ #include "Python.h" #include "pycore_bytesobject.h" // _PyBytesWriter +#include "pycore_long.h" // _PyLong_AsByteArray() #include "pycore_moduleobject.h" // _PyModule_GetState() -#include #include // offsetof() /*[clinic input] @@ -107,19 +107,22 @@ class cache_struct_converter(CConverter): type = 'PyStructObject *' converter = 'cache_struct_converter' c_default = "NULL" + broken_limited_capi = True - def parse_arg(self, argname, displayname): - return """ + def parse_arg(self, argname, displayname, *, limited_capi): + assert not limited_capi + return self.format_code(""" if (!{converter}(module, {argname}, &{paramname})) {{{{ goto exit; }}}} - """.format(argname=argname, paramname=self.name, - converter=self.converter) + """, + argname=argname, + converter=self.converter) def cleanup(self): return "Py_XDECREF(%s);\n" % self.name [python start generated code]*/ -/*[python end generated code: output=da39a3ee5e6b4b0d input=d6746621c2fb1a7d]*/ +/*[python end generated code: output=da39a3ee5e6b4b0d input=c33b27d6b06006c6]*/ static int cache_struct_converter(PyObject *, PyObject *, PyStructObject **); @@ -1550,9 +1553,28 @@ prepare_s(PyStructObject *self) return -1; } +static PyObject * +s_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + PyObject *self; + + assert(type != NULL); + allocfunc alloc_func = PyType_GetSlot(type, Py_tp_alloc); + assert(alloc_func != NULL); + + self = alloc_func(type, 0); + if (self != NULL) { + PyStructObject *s = (PyStructObject*)self; + s->s_format = Py_NewRef(Py_None); + s->s_codes = NULL; + s->s_size = -1; + s->s_len = -1; + } + return self; +} + /*[clinic input] -@classmethod -Struct.__new__ +Struct.__init__ format: object @@ -1564,24 +1586,16 @@ the format string. See help(struct) for more on format strings. [clinic start generated code]*/ -static PyObject * -Struct_impl(PyTypeObject *type, PyObject *format) -/*[clinic end generated code: output=49468b044e334308 input=8b91868eb1df0e28]*/ +static int +Struct___init___impl(PyStructObject *self, PyObject *format) +/*[clinic end generated code: output=b8e80862444e92d0 input=192a4575a3dde802]*/ { - allocfunc alloc = PyType_GetSlot(type, Py_tp_alloc); - assert(alloc != NULL); - PyStructObject *self = (PyStructObject *)alloc(type, 0); - - if (self == NULL) { - return NULL; - } + int ret = 0; if (PyUnicode_Check(format)) { format = PyUnicode_AsASCIIString(format); - if (format == NULL) { - Py_DECREF(self); - return NULL; - } + if (format == NULL) + return -1; } else { Py_INCREF(format); @@ -1589,24 +1603,19 @@ Struct_impl(PyTypeObject *type, PyObject *format) if (!PyBytes_Check(format)) { Py_DECREF(format); - Py_DECREF(self); PyErr_Format(PyExc_TypeError, "Struct() argument 1 must be a str or bytes object, " "not %.200s", _PyType_Name(Py_TYPE(format))); - return NULL; + return -1; } - self->s_format = format; + Py_SETREF(self->s_format, format); - if (prepare_s(self) < 0) { - Py_DECREF(self); - return NULL; - } - return (PyObject *)self; + ret = prepare_s(self); + return ret; } - static int s_clear(PyStructObject *s) { @@ -2164,6 +2173,19 @@ s_sizeof(PyStructObject *self, void *unused) return PyLong_FromSize_t(size); } +static PyObject * +s_repr(PyStructObject *self) +{ + PyObject* fmt = PyUnicode_FromStringAndSize( + PyBytes_AS_STRING(self->s_format), PyBytes_GET_SIZE(self->s_format)); + if (fmt == NULL) { + return NULL; + } + PyObject* s = PyUnicode_FromFormat("%s(%R)", _PyType_Name(Py_TYPE(self)), fmt); + Py_DECREF(fmt); + return s; +} + /* List of functions */ static struct PyMethodDef s_methods[] = { @@ -2182,8 +2204,8 @@ static PyMemberDef s_members[] = { }; static PyGetSetDef s_getsetlist[] = { - {"format", (getter)s_get_format, (setter)NULL, "struct format string", NULL}, - {"size", (getter)s_get_size, (setter)NULL, "struct size in bytes", NULL}, + {"format", (getter)s_get_format, (setter)NULL, PyDoc_STR("struct format string"), NULL}, + {"size", (getter)s_get_size, (setter)NULL, PyDoc_STR("struct size in bytes"), NULL}, {NULL} /* sentinel */ }; @@ -2196,14 +2218,16 @@ static PyType_Slot PyStructType_slots[] = { {Py_tp_dealloc, s_dealloc}, {Py_tp_getattro, PyObject_GenericGetAttr}, {Py_tp_setattro, PyObject_GenericSetAttr}, + {Py_tp_repr, s_repr}, {Py_tp_doc, (void*)s__doc__}, {Py_tp_traverse, s_traverse}, {Py_tp_clear, s_clear}, {Py_tp_methods, s_methods}, {Py_tp_members, s_members}, {Py_tp_getset, s_getsetlist}, - {Py_tp_new, Struct}, + {Py_tp_init, Struct___init__}, {Py_tp_alloc, PyType_GenericAlloc}, + {Py_tp_new, s_new}, {Py_tp_free, PyObject_GC_Del}, {0, 0}, }; @@ -2233,20 +2257,13 @@ cache_struct_converter(PyObject *module, PyObject *fmt, PyStructObject **ptr) return 1; } - if (state->cache == NULL) { - state->cache = PyDict_New(); - if (state->cache == NULL) - return 0; + if (PyDict_GetItemRef(state->cache, fmt, &s_object) < 0) { + return 0; } - - s_object = PyDict_GetItemWithError(state->cache, fmt); if (s_object != NULL) { - *ptr = (PyStructObject *)Py_NewRef(s_object); + *ptr = (PyStructObject *)s_object; return Py_CLEANUP_SUPPORTED; } - else if (PyErr_Occurred()) { - return 0; - } s_object = PyObject_CallOneArg(state->PyStructType, fmt); if (s_object != NULL) { @@ -2271,7 +2288,7 @@ static PyObject * _clearcache_impl(PyObject *module) /*[clinic end generated code: output=ce4fb8a7bf7cb523 input=463eaae04bab3211]*/ { - Py_CLEAR(get_struct_state(module)->cache); + PyDict_Clear(get_struct_state(module)->cache); Py_RETURN_NONE; } @@ -2495,6 +2512,11 @@ _structmodule_exec(PyObject *m) { _structmodulestate *state = get_struct_state(m); + state->cache = PyDict_New(); + if (state->cache == NULL) { + return -1; + } + state->PyStructType = PyType_FromModuleAndSpec( m, &PyStructType_spec, NULL); if (state->PyStructType == NULL) { diff --git a/Modules/_suggestions.c b/Modules/_suggestions.c new file mode 100644 index 00000000000000..30b524d70c1211 --- /dev/null +++ b/Modules/_suggestions.c @@ -0,0 +1,63 @@ +#include "Python.h" +#include "pycore_pyerrors.h" +#include "clinic/_suggestions.c.h" + +/*[clinic input] +module _suggestions +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=e58d81fafad5637b]*/ + +/*[clinic input] +_suggestions._generate_suggestions + candidates: object + item: unicode + / +Returns the candidate in candidates that's closest to item +[clinic start generated code]*/ + +static PyObject * +_suggestions__generate_suggestions_impl(PyObject *module, + PyObject *candidates, PyObject *item) +/*[clinic end generated code: output=79be7b653ae5e7ca input=ba2a8dddc654e33a]*/ +{ + // Check if dir is a list + if (!PyList_Check(candidates)) { + PyErr_SetString(PyExc_TypeError, "candidates must be a list"); + return NULL; + } + + // Check if all elements in the list are Unicode + Py_ssize_t size = PyList_Size(candidates); + for (Py_ssize_t i = 0; i < size; ++i) { + PyObject *elem = PyList_GetItem(candidates, i); + if (!PyUnicode_Check(elem)) { + PyErr_SetString(PyExc_TypeError, "all elements in 'candidates' must be strings"); + return NULL; + } + } + + PyObject* result = _Py_CalculateSuggestions(candidates, item); + if (!result && !PyErr_Occurred()) { + Py_RETURN_NONE; + } + return result; +} + + +static PyMethodDef module_methods[] = { + _SUGGESTIONS__GENERATE_SUGGESTIONS_METHODDEF + {NULL, NULL, 0, NULL} // Sentinel +}; + +static struct PyModuleDef suggestions_module = { + PyModuleDef_HEAD_INIT, + "_suggestions", + NULL, + -1, + module_methods +}; + +PyMODINIT_FUNC PyInit__suggestions(void) { + return PyModule_Create(&suggestions_module); +} + diff --git a/Modules/_sysconfig.c b/Modules/_sysconfig.c new file mode 100644 index 00000000000000..c76b9e6b3ebafa --- /dev/null +++ b/Modules/_sysconfig.c @@ -0,0 +1,98 @@ +// _sysconfig provides data for the Python sysconfig module + +#ifndef Py_BUILD_CORE_BUILTIN +# define Py_BUILD_CORE_MODULE 1 +#endif + +#include "Python.h" + +#include "pycore_importdl.h" // _PyImport_DynLoadFiletab +#include "pycore_long.h" // _PyLong_GetZero, _PyLong_GetOne + + +/*[clinic input] +module _sysconfig +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=0a7c02d3e212ac97]*/ + +#include "clinic/_sysconfig.c.h" + +#ifdef MS_WINDOWS +static int +add_string_value(PyObject *dict, const char *key, const char *str_value) +{ + PyObject *value = PyUnicode_FromString(str_value); + if (value == NULL) { + return -1; + } + int err = PyDict_SetItemString(dict, key, value); + Py_DECREF(value); + return err; +} +#endif + +/*[clinic input] +_sysconfig.config_vars + +Returns a dictionary containing build variables intended to be exposed by sysconfig. +[clinic start generated code]*/ + +static PyObject * +_sysconfig_config_vars_impl(PyObject *module) +/*[clinic end generated code: output=9c41cdee63ea9487 input=391ff42f3af57d01]*/ +{ + PyObject *config = PyDict_New(); + if (config == NULL) { + return NULL; + } + +#ifdef MS_WINDOWS + if (add_string_value(config, "EXT_SUFFIX", PYD_TAGGED_SUFFIX) < 0) { + Py_DECREF(config); + return NULL; + } + if (add_string_value(config, "SOABI", PYD_SOABI) < 0) { + Py_DECREF(config); + return NULL; + } +#endif + +#ifdef Py_GIL_DISABLED + PyObject *py_gil_disabled = _PyLong_GetOne(); +#else + PyObject *py_gil_disabled = _PyLong_GetZero(); +#endif + if (PyDict_SetItemString(config, "Py_GIL_DISABLED", py_gil_disabled) < 0) { + Py_DECREF(config); + return NULL; + } + + return config; +} + +PyDoc_STRVAR(sysconfig__doc__, +"A helper for the sysconfig module."); + +static struct PyMethodDef sysconfig_methods[] = { + _SYSCONFIG_CONFIG_VARS_METHODDEF + {NULL, NULL} +}; + +static PyModuleDef_Slot sysconfig_slots[] = { + {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, + {0, NULL} +}; + +static PyModuleDef sysconfig_module = { + .m_base = PyModuleDef_HEAD_INIT, + .m_name = "_sysconfig", + .m_doc = sysconfig__doc__, + .m_methods = sysconfig_methods, + .m_slots = sysconfig_slots, +}; + +PyMODINIT_FUNC +PyInit__sysconfig(void) +{ + return PyModuleDef_Init(&sysconfig_module); +} diff --git a/Modules/_testcapi/abstract.c b/Modules/_testcapi/abstract.c new file mode 100644 index 00000000000000..a8ba009eb6a54b --- /dev/null +++ b/Modules/_testcapi/abstract.c @@ -0,0 +1,715 @@ +#include "parts.h" +#include "util.h" + + +static PyObject * +object_repr(PyObject *self, PyObject *arg) +{ + NULLABLE(arg); + return PyObject_Repr(arg); +} + +static PyObject * +object_ascii(PyObject *self, PyObject *arg) +{ + NULLABLE(arg); + return PyObject_ASCII(arg); +} + +static PyObject * +object_str(PyObject *self, PyObject *arg) +{ + NULLABLE(arg); + return PyObject_Str(arg); +} + +static PyObject * +object_bytes(PyObject *self, PyObject *arg) +{ + NULLABLE(arg); + return PyObject_Bytes(arg); +} + +static PyObject * +object_getattr(PyObject *self, PyObject *args) +{ + PyObject *obj, *attr_name; + if (!PyArg_ParseTuple(args, "OO", &obj, &attr_name)) { + return NULL; + } + NULLABLE(obj); + NULLABLE(attr_name); + return PyObject_GetAttr(obj, attr_name); +} + +static PyObject * +object_getattrstring(PyObject *self, PyObject *args) +{ + PyObject *obj; + const char *attr_name; + Py_ssize_t size; + if (!PyArg_ParseTuple(args, "Oz#", &obj, &attr_name, &size)) { + return NULL; + } + NULLABLE(obj); + return PyObject_GetAttrString(obj, attr_name); +} + +static PyObject * +object_getoptionalattr(PyObject *self, PyObject *args) +{ + PyObject *obj, *attr_name, *value = UNINITIALIZED_PTR; + if (!PyArg_ParseTuple(args, "OO", &obj, &attr_name)) { + return NULL; + } + NULLABLE(obj); + NULLABLE(attr_name); + + switch (PyObject_GetOptionalAttr(obj, attr_name, &value)) { + case -1: + assert(value == NULL); + return NULL; + case 0: + assert(value == NULL); + return Py_NewRef(PyExc_AttributeError); + case 1: + return value; + default: + Py_FatalError("PyObject_GetOptionalAttr() returned invalid code"); + Py_UNREACHABLE(); + } +} + +static PyObject * +object_getoptionalattrstring(PyObject *self, PyObject *args) +{ + PyObject *obj, *value = UNINITIALIZED_PTR; + const char *attr_name; + Py_ssize_t size; + if (!PyArg_ParseTuple(args, "Oz#", &obj, &attr_name, &size)) { + return NULL; + } + NULLABLE(obj); + + switch (PyObject_GetOptionalAttrString(obj, attr_name, &value)) { + case -1: + assert(value == NULL); + return NULL; + case 0: + assert(value == NULL); + return Py_NewRef(PyExc_AttributeError); + case 1: + return value; + default: + Py_FatalError("PyObject_GetOptionalAttrString() returned invalid code"); + Py_UNREACHABLE(); + } +} + +static PyObject * +object_hasattr(PyObject *self, PyObject *args) +{ + PyObject *obj, *attr_name; + if (!PyArg_ParseTuple(args, "OO", &obj, &attr_name)) { + return NULL; + } + NULLABLE(obj); + NULLABLE(attr_name); + return PyLong_FromLong(PyObject_HasAttr(obj, attr_name)); +} + +static PyObject * +object_hasattrstring(PyObject *self, PyObject *args) +{ + PyObject *obj; + const char *attr_name; + Py_ssize_t size; + if (!PyArg_ParseTuple(args, "Oz#", &obj, &attr_name, &size)) { + return NULL; + } + NULLABLE(obj); + return PyLong_FromLong(PyObject_HasAttrString(obj, attr_name)); +} + +static PyObject * +object_hasattrwitherror(PyObject *self, PyObject *args) +{ + PyObject *obj, *attr_name; + if (!PyArg_ParseTuple(args, "OO", &obj, &attr_name)) { + return NULL; + } + NULLABLE(obj); + NULLABLE(attr_name); + RETURN_INT(PyObject_HasAttrWithError(obj, attr_name)); +} + +static PyObject * +object_hasattrstringwitherror(PyObject *self, PyObject *args) +{ + PyObject *obj; + const char *attr_name; + Py_ssize_t size; + if (!PyArg_ParseTuple(args, "Oz#", &obj, &attr_name, &size)) { + return NULL; + } + NULLABLE(obj); + RETURN_INT(PyObject_HasAttrStringWithError(obj, attr_name)); +} + +static PyObject * +object_setattr(PyObject *self, PyObject *args) +{ + PyObject *obj, *attr_name, *value; + if (!PyArg_ParseTuple(args, "OOO", &obj, &attr_name, &value)) { + return NULL; + } + NULLABLE(obj); + NULLABLE(attr_name); + NULLABLE(value); + RETURN_INT(PyObject_SetAttr(obj, attr_name, value)); +} + +static PyObject * +object_setattrstring(PyObject *self, PyObject *args) +{ + PyObject *obj, *value; + const char *attr_name; + Py_ssize_t size; + if (!PyArg_ParseTuple(args, "Oz#O", &obj, &attr_name, &size, &value)) { + return NULL; + } + NULLABLE(obj); + NULLABLE(value); + RETURN_INT(PyObject_SetAttrString(obj, attr_name, value)); +} + +static PyObject * +object_delattr(PyObject *self, PyObject *args) +{ + PyObject *obj, *attr_name; +if (!PyArg_ParseTuple(args, "OO", &obj, &attr_name)) { + return NULL; + } + NULLABLE(obj); + NULLABLE(attr_name); + RETURN_INT(PyObject_DelAttr(obj, attr_name)); +} + +static PyObject * +object_delattrstring(PyObject *self, PyObject *args) +{ + PyObject *obj; + const char *attr_name; + Py_ssize_t size; + if (!PyArg_ParseTuple(args, "Oz#", &obj, &attr_name, &size)) { + return NULL; + } + NULLABLE(obj); + RETURN_INT(PyObject_DelAttrString(obj, attr_name)); +} + +static PyObject * +number_check(PyObject *self, PyObject *obj) +{ + NULLABLE(obj); + return PyBool_FromLong(PyNumber_Check(obj)); +} + +static PyObject * +mapping_check(PyObject *self, PyObject *obj) +{ + NULLABLE(obj); + return PyLong_FromLong(PyMapping_Check(obj)); +} + +static PyObject * +mapping_size(PyObject *self, PyObject *obj) +{ + NULLABLE(obj); + RETURN_SIZE(PyMapping_Size(obj)); +} + +static PyObject * +mapping_length(PyObject *self, PyObject *obj) +{ + NULLABLE(obj); + RETURN_SIZE(PyMapping_Length(obj)); +} + +static PyObject * +object_getitem(PyObject *self, PyObject *args) +{ + PyObject *mapping, *key; + if (!PyArg_ParseTuple(args, "OO", &mapping, &key)) { + return NULL; + } + NULLABLE(mapping); + NULLABLE(key); + return PyObject_GetItem(mapping, key); +} + +static PyObject * +mapping_getitemstring(PyObject *self, PyObject *args) +{ + PyObject *mapping; + const char *key; + Py_ssize_t size; + if (!PyArg_ParseTuple(args, "Oz#", &mapping, &key, &size)) { + return NULL; + } + NULLABLE(mapping); + return PyMapping_GetItemString(mapping, key); +} + +static PyObject * +mapping_getoptionalitem(PyObject *self, PyObject *args) +{ + PyObject *obj, *attr_name, *value = UNINITIALIZED_PTR; + if (!PyArg_ParseTuple(args, "OO", &obj, &attr_name)) { + return NULL; + } + NULLABLE(obj); + NULLABLE(attr_name); + + switch (PyMapping_GetOptionalItem(obj, attr_name, &value)) { + case -1: + assert(value == NULL); + return NULL; + case 0: + assert(value == NULL); + return Py_NewRef(PyExc_KeyError); + case 1: + return value; + default: + Py_FatalError("PyMapping_GetOptionalItem() returned invalid code"); + Py_UNREACHABLE(); + } +} + +static PyObject * +mapping_getoptionalitemstring(PyObject *self, PyObject *args) +{ + PyObject *obj, *value = UNINITIALIZED_PTR; + const char *attr_name; + Py_ssize_t size; + if (!PyArg_ParseTuple(args, "Oz#", &obj, &attr_name, &size)) { + return NULL; + } + NULLABLE(obj); + + switch (PyMapping_GetOptionalItemString(obj, attr_name, &value)) { + case -1: + assert(value == NULL); + return NULL; + case 0: + assert(value == NULL); + return Py_NewRef(PyExc_KeyError); + case 1: + return value; + default: + Py_FatalError("PyMapping_GetOptionalItemString() returned invalid code"); + Py_UNREACHABLE(); + } +} + +static PyObject * +mapping_haskey(PyObject *self, PyObject *args) +{ + PyObject *mapping, *key; + if (!PyArg_ParseTuple(args, "OO", &mapping, &key)) { + return NULL; + } + NULLABLE(mapping); + NULLABLE(key); + return PyLong_FromLong(PyMapping_HasKey(mapping, key)); +} + +static PyObject * +mapping_haskeystring(PyObject *self, PyObject *args) +{ + PyObject *mapping; + const char *key; + Py_ssize_t size; + if (!PyArg_ParseTuple(args, "Oz#", &mapping, &key, &size)) { + return NULL; + } + NULLABLE(mapping); + return PyLong_FromLong(PyMapping_HasKeyString(mapping, key)); +} + +static PyObject * +mapping_haskeywitherror(PyObject *self, PyObject *args) +{ + PyObject *mapping, *key; + if (!PyArg_ParseTuple(args, "OO", &mapping, &key)) { + return NULL; + } + NULLABLE(mapping); + NULLABLE(key); + RETURN_INT(PyMapping_HasKeyWithError(mapping, key)); +} + +static PyObject * +mapping_haskeystringwitherror(PyObject *self, PyObject *args) +{ + PyObject *mapping; + const char *key; + Py_ssize_t size; + if (!PyArg_ParseTuple(args, "Oz#", &mapping, &key, &size)) { + return NULL; + } + NULLABLE(mapping); + RETURN_INT(PyMapping_HasKeyStringWithError(mapping, key)); +} + +static PyObject * +object_setitem(PyObject *self, PyObject *args) +{ + PyObject *mapping, *key, *value; + if (!PyArg_ParseTuple(args, "OOO", &mapping, &key, &value)) { + return NULL; + } + NULLABLE(mapping); + NULLABLE(key); + NULLABLE(value); + RETURN_INT(PyObject_SetItem(mapping, key, value)); +} + +static PyObject * +mapping_setitemstring(PyObject *self, PyObject *args) +{ + PyObject *mapping, *value; + const char *key; + Py_ssize_t size; + if (!PyArg_ParseTuple(args, "Oz#O", &mapping, &key, &size, &value)) { + return NULL; + } + NULLABLE(mapping); + NULLABLE(value); + RETURN_INT(PyMapping_SetItemString(mapping, key, value)); +} + +static PyObject * +object_delitem(PyObject *self, PyObject *args) +{ + PyObject *mapping, *key; + if (!PyArg_ParseTuple(args, "OO", &mapping, &key)) { + return NULL; + } + NULLABLE(mapping); + NULLABLE(key); + RETURN_INT(PyObject_DelItem(mapping, key)); +} + +static PyObject * +mapping_delitem(PyObject *self, PyObject *args) +{ + PyObject *mapping, *key; + if (!PyArg_ParseTuple(args, "OO", &mapping, &key)) { + return NULL; + } + NULLABLE(mapping); + NULLABLE(key); + RETURN_INT(PyMapping_DelItem(mapping, key)); +} + +static PyObject * +mapping_delitemstring(PyObject *self, PyObject *args) +{ + PyObject *mapping; + const char *key; + Py_ssize_t size; + if (!PyArg_ParseTuple(args, "Oz#", &mapping, &key, &size)) { + return NULL; + } + NULLABLE(mapping); + RETURN_INT(PyMapping_DelItemString(mapping, key)); +} + +static PyObject * +mapping_keys(PyObject *self, PyObject *obj) +{ + NULLABLE(obj); + return PyMapping_Keys(obj); +} + +static PyObject * +mapping_values(PyObject *self, PyObject *obj) +{ + NULLABLE(obj); + return PyMapping_Values(obj); +} + +static PyObject * +mapping_items(PyObject *self, PyObject *obj) +{ + NULLABLE(obj); + return PyMapping_Items(obj); +} + + +static PyObject * +sequence_check(PyObject* self, PyObject *obj) +{ + NULLABLE(obj); + return PyLong_FromLong(PySequence_Check(obj)); +} + +static PyObject * +sequence_size(PyObject* self, PyObject *obj) +{ + NULLABLE(obj); + RETURN_SIZE(PySequence_Size(obj)); +} + +static PyObject * +sequence_length(PyObject* self, PyObject *obj) +{ + NULLABLE(obj); + RETURN_SIZE(PySequence_Length(obj)); +} + +static PyObject * +sequence_concat(PyObject *self, PyObject *args) +{ + PyObject *seq1, *seq2; + if (!PyArg_ParseTuple(args, "OO", &seq1, &seq2)) { + return NULL; + } + NULLABLE(seq1); + NULLABLE(seq2); + + return PySequence_Concat(seq1, seq2); +} + +static PyObject * +sequence_repeat(PyObject *self, PyObject *args) +{ + PyObject *seq; + Py_ssize_t count; + if (!PyArg_ParseTuple(args, "On", &seq, &count)) { + return NULL; + } + NULLABLE(seq); + + return PySequence_Repeat(seq, count); +} + +static PyObject * +sequence_inplaceconcat(PyObject *self, PyObject *args) +{ + PyObject *seq1, *seq2; + if (!PyArg_ParseTuple(args, "OO", &seq1, &seq2)) { + return NULL; + } + NULLABLE(seq1); + NULLABLE(seq2); + + return PySequence_InPlaceConcat(seq1, seq2); +} + +static PyObject * +sequence_inplacerepeat(PyObject *self, PyObject *args) +{ + PyObject *seq; + Py_ssize_t count; + if (!PyArg_ParseTuple(args, "On", &seq, &count)) { + return NULL; + } + NULLABLE(seq); + + return PySequence_InPlaceRepeat(seq, count); +} + +static PyObject * +sequence_getitem(PyObject *self, PyObject *args) +{ + PyObject *seq; + Py_ssize_t i; + if (!PyArg_ParseTuple(args, "On", &seq, &i)) { + return NULL; + } + NULLABLE(seq); + + return PySequence_GetItem(seq, i); +} + +static PyObject * +sequence_setitem(PyObject *self, PyObject *args) +{ + Py_ssize_t i; + PyObject *seq, *val; + if (!PyArg_ParseTuple(args, "OnO", &seq, &i, &val)) { + return NULL; + } + NULLABLE(seq); + NULLABLE(val); + + RETURN_INT(PySequence_SetItem(seq, i, val)); +} + + +static PyObject * +sequence_delitem(PyObject *self, PyObject *args) +{ + Py_ssize_t i; + PyObject *seq; + if (!PyArg_ParseTuple(args, "On", &seq, &i)) { + return NULL; + } + NULLABLE(seq); + + RETURN_INT(PySequence_DelItem(seq, i)); +} + +static PyObject * +sequence_setslice(PyObject* self, PyObject *args) +{ + PyObject *sequence, *obj; + Py_ssize_t i1, i2; + if (!PyArg_ParseTuple(args, "OnnO", &sequence, &i1, &i2, &obj)) { + return NULL; + } + NULLABLE(sequence); + NULLABLE(obj); + + RETURN_INT(PySequence_SetSlice(sequence, i1, i2, obj)); +} + +static PyObject * +sequence_delslice(PyObject *self, PyObject *args) +{ + PyObject *sequence; + Py_ssize_t i1, i2; + if (!PyArg_ParseTuple(args, "Onn", &sequence, &i1, &i2)) { + return NULL; + } + NULLABLE(sequence); + + RETURN_INT(PySequence_DelSlice(sequence, i1, i2)); +} + +static PyObject * +sequence_count(PyObject *self, PyObject *args) +{ + PyObject *seq, *value; + if (!PyArg_ParseTuple(args, "OO", &seq, &value)) { + return NULL; + } + NULLABLE(seq); + NULLABLE(value); + + RETURN_SIZE(PySequence_Count(seq, value)); +} + +static PyObject * +sequence_contains(PyObject *self, PyObject *args) +{ + PyObject *seq, *value; + if (!PyArg_ParseTuple(args, "OO", &seq, &value)) { + return NULL; + } + NULLABLE(seq); + NULLABLE(value); + + RETURN_INT(PySequence_Contains(seq, value)); +} + +static PyObject * +sequence_index(PyObject *self, PyObject *args) +{ + PyObject *seq, *value; + if (!PyArg_ParseTuple(args, "OO", &seq, &value)) { + return NULL; + } + NULLABLE(seq); + NULLABLE(value); + + RETURN_SIZE(PySequence_Index(seq, value)); +} + +static PyObject * +sequence_list(PyObject *self, PyObject *obj) +{ + NULLABLE(obj); + return PySequence_List(obj); +} + +static PyObject * +sequence_tuple(PyObject *self, PyObject *obj) +{ + NULLABLE(obj); + return PySequence_Tuple(obj); +} + + +static PyMethodDef test_methods[] = { + {"object_repr", object_repr, METH_O}, + {"object_ascii", object_ascii, METH_O}, + {"object_str", object_str, METH_O}, + {"object_bytes", object_bytes, METH_O}, + + {"object_getattr", object_getattr, METH_VARARGS}, + {"object_getattrstring", object_getattrstring, METH_VARARGS}, + {"object_getoptionalattr", object_getoptionalattr, METH_VARARGS}, + {"object_getoptionalattrstring", object_getoptionalattrstring, METH_VARARGS}, + {"object_hasattr", object_hasattr, METH_VARARGS}, + {"object_hasattrstring", object_hasattrstring, METH_VARARGS}, + {"object_hasattrwitherror", object_hasattrwitherror, METH_VARARGS}, + {"object_hasattrstringwitherror", object_hasattrstringwitherror, METH_VARARGS}, + {"object_setattr", object_setattr, METH_VARARGS}, + {"object_setattrstring", object_setattrstring, METH_VARARGS}, + {"object_delattr", object_delattr, METH_VARARGS}, + {"object_delattrstring", object_delattrstring, METH_VARARGS}, + + {"number_check", number_check, METH_O}, + {"mapping_check", mapping_check, METH_O}, + {"mapping_size", mapping_size, METH_O}, + {"mapping_length", mapping_length, METH_O}, + {"object_getitem", object_getitem, METH_VARARGS}, + {"mapping_getitemstring", mapping_getitemstring, METH_VARARGS}, + {"mapping_getoptionalitem", mapping_getoptionalitem, METH_VARARGS}, + {"mapping_getoptionalitemstring", mapping_getoptionalitemstring, METH_VARARGS}, + {"mapping_haskey", mapping_haskey, METH_VARARGS}, + {"mapping_haskeystring", mapping_haskeystring, METH_VARARGS}, + {"mapping_haskeywitherror", mapping_haskeywitherror, METH_VARARGS}, + {"mapping_haskeystringwitherror", mapping_haskeystringwitherror, METH_VARARGS}, + {"object_setitem", object_setitem, METH_VARARGS}, + {"mapping_setitemstring", mapping_setitemstring, METH_VARARGS}, + {"object_delitem", object_delitem, METH_VARARGS}, + {"mapping_delitem", mapping_delitem, METH_VARARGS}, + {"mapping_delitemstring", mapping_delitemstring, METH_VARARGS}, + {"mapping_keys", mapping_keys, METH_O}, + {"mapping_values", mapping_values, METH_O}, + {"mapping_items", mapping_items, METH_O}, + + {"sequence_check", sequence_check, METH_O}, + {"sequence_size", sequence_size, METH_O}, + {"sequence_length", sequence_length, METH_O}, + {"sequence_concat", sequence_concat, METH_VARARGS}, + {"sequence_repeat", sequence_repeat, METH_VARARGS}, + {"sequence_inplaceconcat", sequence_inplaceconcat, METH_VARARGS}, + {"sequence_inplacerepeat", sequence_inplacerepeat, METH_VARARGS}, + {"sequence_getitem", sequence_getitem, METH_VARARGS}, + {"sequence_setitem", sequence_setitem, METH_VARARGS}, + {"sequence_delitem", sequence_delitem, METH_VARARGS}, + {"sequence_setslice", sequence_setslice, METH_VARARGS}, + {"sequence_delslice", sequence_delslice, METH_VARARGS}, + {"sequence_count", sequence_count, METH_VARARGS}, + {"sequence_contains", sequence_contains, METH_VARARGS}, + {"sequence_index", sequence_index, METH_VARARGS}, + {"sequence_list", sequence_list, METH_O}, + {"sequence_tuple", sequence_tuple, METH_O}, + + {NULL}, +}; + +int +_PyTestCapi_Init_Abstract(PyObject *m) +{ + if (PyModule_AddFunctions(m, test_methods) < 0) { + return -1; + } + + return 0; +} diff --git a/Modules/_testcapi/bytearray.c b/Modules/_testcapi/bytearray.c new file mode 100644 index 00000000000000..dc47ed2c306f40 --- /dev/null +++ b/Modules/_testcapi/bytearray.c @@ -0,0 +1,123 @@ +#include "parts.h" +#include "util.h" + + +/* Test PyByteArray_Check() */ +static PyObject * +bytearray_check(PyObject *Py_UNUSED(module), PyObject *obj) +{ + NULLABLE(obj); + return PyLong_FromLong(PyByteArray_Check(obj)); +} + +/* Test PyByteArray_CheckExact() */ +static PyObject * +bytearray_checkexact(PyObject *Py_UNUSED(module), PyObject *obj) +{ + NULLABLE(obj); + return PyLong_FromLong(PyByteArray_CheckExact(obj)); +} + +/* Test PyByteArray_FromStringAndSize() */ +static PyObject * +bytearray_fromstringandsize(PyObject *Py_UNUSED(module), PyObject *args) +{ + const char *s; + Py_ssize_t bsize; + Py_ssize_t size = -100; + + if (!PyArg_ParseTuple(args, "z#|n", &s, &bsize, &size)) { + return NULL; + } + + if (size == -100) { + size = bsize; + } + return PyByteArray_FromStringAndSize(s, size); +} + +/* Test PyByteArray_FromObject() */ +static PyObject * +bytearray_fromobject(PyObject *Py_UNUSED(module), PyObject *arg) +{ + NULLABLE(arg); + return PyByteArray_FromObject(arg); +} + +/* Test PyByteArray_Size() */ +static PyObject * +bytearray_size(PyObject *Py_UNUSED(module), PyObject *arg) +{ + NULLABLE(arg); + RETURN_SIZE(PyByteArray_Size(arg)); +} + +/* Test PyUnicode_AsString() */ +static PyObject * +bytearray_asstring(PyObject *Py_UNUSED(module), PyObject *args) +{ + PyObject *obj; + Py_ssize_t buflen; + const char *s; + + if (!PyArg_ParseTuple(args, "On", &obj, &buflen)) + return NULL; + + NULLABLE(obj); + s = PyByteArray_AsString(obj); + if (s == NULL) + return NULL; + + return PyByteArray_FromStringAndSize(s, buflen); +} + +/* Test PyByteArray_Concat() */ +static PyObject * +bytearray_concat(PyObject *Py_UNUSED(module), PyObject *args) +{ + PyObject *left, *right; + + if (!PyArg_ParseTuple(args, "OO", &left, &right)) + return NULL; + + NULLABLE(left); + NULLABLE(right); + return PyByteArray_Concat(left, right); +} + +/* Test PyByteArray_Resize() */ +static PyObject * +bytearray_resize(PyObject *Py_UNUSED(module), PyObject *args) +{ + PyObject *obj; + Py_ssize_t size; + + if (!PyArg_ParseTuple(args, "On", &obj, &size)) + return NULL; + + NULLABLE(obj); + RETURN_INT(PyByteArray_Resize(obj, size)); +} + + +static PyMethodDef test_methods[] = { + {"bytearray_check", bytearray_check, METH_O}, + {"bytearray_checkexact", bytearray_checkexact, METH_O}, + {"bytearray_fromstringandsize", bytearray_fromstringandsize, METH_VARARGS}, + {"bytearray_fromobject", bytearray_fromobject, METH_O}, + {"bytearray_size", bytearray_size, METH_O}, + {"bytearray_asstring", bytearray_asstring, METH_VARARGS}, + {"bytearray_concat", bytearray_concat, METH_VARARGS}, + {"bytearray_resize", bytearray_resize, METH_VARARGS}, + {NULL}, +}; + +int +_PyTestCapi_Init_ByteArray(PyObject *m) +{ + if (PyModule_AddFunctions(m, test_methods) < 0) { + return -1; + } + + return 0; +} diff --git a/Modules/_testcapi/bytes.c b/Modules/_testcapi/bytes.c new file mode 100644 index 00000000000000..da10503f6f6856 --- /dev/null +++ b/Modules/_testcapi/bytes.c @@ -0,0 +1,255 @@ +#include "parts.h" +#include "util.h" + + +/* Test PyBytes_Check() */ +static PyObject * +bytes_check(PyObject *Py_UNUSED(module), PyObject *obj) +{ + NULLABLE(obj); + return PyLong_FromLong(PyBytes_Check(obj)); +} + +/* Test PyBytes_CheckExact() */ +static PyObject * +bytes_checkexact(PyObject *Py_UNUSED(module), PyObject *obj) +{ + NULLABLE(obj); + return PyLong_FromLong(PyBytes_CheckExact(obj)); +} + +/* Test PyBytes_FromStringAndSize() */ +static PyObject * +bytes_fromstringandsize(PyObject *Py_UNUSED(module), PyObject *args) +{ + const char *s; + Py_ssize_t bsize; + Py_ssize_t size = -100; + + if (!PyArg_ParseTuple(args, "z#|n", &s, &bsize, &size)) { + return NULL; + } + + if (size == -100) { + size = bsize; + } + return PyBytes_FromStringAndSize(s, size); +} + +/* Test PyBytes_FromString() */ +static PyObject * +bytes_fromstring(PyObject *Py_UNUSED(module), PyObject *arg) +{ + const char *s; + Py_ssize_t size; + + if (!PyArg_Parse(arg, "z#", &s, &size)) { + return NULL; + } + return PyBytes_FromString(s); +} + +/* Test PyBytes_FromObject() */ +static PyObject * +bytes_fromobject(PyObject *Py_UNUSED(module), PyObject *arg) +{ + NULLABLE(arg); + return PyBytes_FromObject(arg); +} + +/* Test PyBytes_Size() */ +static PyObject * +bytes_size(PyObject *Py_UNUSED(module), PyObject *arg) +{ + NULLABLE(arg); + RETURN_SIZE(PyBytes_Size(arg)); +} + +/* Test PyUnicode_AsString() */ +static PyObject * +bytes_asstring(PyObject *Py_UNUSED(module), PyObject *args) +{ + PyObject *obj; + Py_ssize_t buflen; + const char *s; + + if (!PyArg_ParseTuple(args, "On", &obj, &buflen)) + return NULL; + + NULLABLE(obj); + s = PyBytes_AsString(obj); + if (s == NULL) + return NULL; + + return PyBytes_FromStringAndSize(s, buflen); +} + +/* Test PyBytes_AsStringAndSize() */ +static PyObject * +bytes_asstringandsize(PyObject *Py_UNUSED(module), PyObject *args) +{ + PyObject *obj; + Py_ssize_t buflen; + char *s = UNINITIALIZED_PTR; + Py_ssize_t size = UNINITIALIZED_SIZE; + + if (!PyArg_ParseTuple(args, "On", &obj, &buflen)) + return NULL; + + NULLABLE(obj); + if (PyBytes_AsStringAndSize(obj, &s, &size) < 0) { + return NULL; + } + + if (s == NULL) { + return Py_BuildValue("(On)", Py_None, size); + } + else { + return Py_BuildValue("(y#n)", s, buflen, size); + } +} + +static PyObject * +bytes_asstringandsize_null(PyObject *Py_UNUSED(module), PyObject *args) +{ + PyObject *obj; + Py_ssize_t buflen; + char *s = UNINITIALIZED_PTR; + + if (!PyArg_ParseTuple(args, "On", &obj, &buflen)) + return NULL; + + NULLABLE(obj); + if (PyBytes_AsStringAndSize(obj, &s, NULL) < 0) { + return NULL; + } + + if (s == NULL) { + Py_RETURN_NONE; + } + else { + return PyBytes_FromStringAndSize(s, buflen); + } +} + +/* Test PyBytes_Repr() */ +static PyObject * +bytes_repr(PyObject *Py_UNUSED(module), PyObject *args) +{ + PyObject *obj; + int smartquotes; + if (!PyArg_ParseTuple(args, "Oi", &obj, &smartquotes)) + return NULL; + + NULLABLE(obj); + return PyBytes_Repr(obj, smartquotes); +} + +/* Test PyBytes_Concat() */ +static PyObject * +bytes_concat(PyObject *Py_UNUSED(module), PyObject *args) +{ + PyObject *left, *right; + int new = 0; + + if (!PyArg_ParseTuple(args, "OO|p", &left, &right, &new)) + return NULL; + + NULLABLE(left); + NULLABLE(right); + if (new) { + assert(left != NULL); + assert(PyBytes_CheckExact(left)); + left = PyBytes_FromStringAndSize(PyBytes_AS_STRING(left), + PyBytes_GET_SIZE(left)); + if (left == NULL) { + return NULL; + } + } + else { + Py_XINCREF(left); + } + PyBytes_Concat(&left, right); + if (left == NULL && !PyErr_Occurred()) { + Py_RETURN_NONE; + } + return left; +} + +/* Test PyBytes_ConcatAndDel() */ +static PyObject * +bytes_concatanddel(PyObject *Py_UNUSED(module), PyObject *args) +{ + PyObject *left, *right; + int new = 0; + + if (!PyArg_ParseTuple(args, "OO|p", &left, &right, &new)) + return NULL; + + NULLABLE(left); + NULLABLE(right); + if (new) { + assert(left != NULL); + assert(PyBytes_CheckExact(left)); + left = PyBytes_FromStringAndSize(PyBytes_AS_STRING(left), + PyBytes_GET_SIZE(left)); + if (left == NULL) { + return NULL; + } + } + else { + Py_XINCREF(left); + } + Py_XINCREF(right); + PyBytes_ConcatAndDel(&left, right); + if (left == NULL && !PyErr_Occurred()) { + Py_RETURN_NONE; + } + return left; +} + +/* Test PyBytes_DecodeEscape() */ +static PyObject * +bytes_decodeescape(PyObject *Py_UNUSED(module), PyObject *args) +{ + const char *s; + Py_ssize_t bsize; + Py_ssize_t size = -100; + const char *errors = NULL; + + if (!PyArg_ParseTuple(args, "z#|zn", &s, &bsize, &errors, &size)) + return NULL; + + if (size == -100) { + size = bsize; + } + return PyBytes_DecodeEscape(s, size, errors, 0, NULL); +} + + +static PyMethodDef test_methods[] = { + {"bytes_check", bytes_check, METH_O}, + {"bytes_checkexact", bytes_checkexact, METH_O}, + {"bytes_fromstringandsize", bytes_fromstringandsize, METH_VARARGS}, + {"bytes_fromstring", bytes_fromstring, METH_O}, + {"bytes_fromobject", bytes_fromobject, METH_O}, + {"bytes_size", bytes_size, METH_O}, + {"bytes_asstring", bytes_asstring, METH_VARARGS}, + {"bytes_asstringandsize", bytes_asstringandsize, METH_VARARGS}, + {"bytes_asstringandsize_null", bytes_asstringandsize_null, METH_VARARGS}, + {"bytes_repr", bytes_repr, METH_VARARGS}, + {"bytes_concat", bytes_concat, METH_VARARGS}, + {"bytes_concatanddel", bytes_concatanddel, METH_VARARGS}, + {"bytes_decodeescape", bytes_decodeescape, METH_VARARGS}, + {NULL}, +}; + +int +_PyTestCapi_Init_Bytes(PyObject *m) +{ + if (PyModule_AddFunctions(m, test_methods) < 0) { + return -1; + } + + return 0; +} diff --git a/Modules/_testcapi/clinic/exceptions.c.h b/Modules/_testcapi/clinic/exceptions.c.h index 01730ffa2ed036..a797444c1a72b9 100644 --- a/Modules/_testcapi/clinic/exceptions.c.h +++ b/Modules/_testcapi/clinic/exceptions.c.h @@ -3,10 +3,10 @@ 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() +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() #endif - +#include "pycore_modsupport.h" // _PyArg_CheckPositional() PyDoc_STRVAR(_testcapi_err_set_raised__doc__, "err_set_raised($module, exception, /)\n" @@ -215,6 +215,68 @@ _testcapi_exc_set_object_fetch(PyObject *module, PyObject *const *args, Py_ssize return return_value; } +PyDoc_STRVAR(_testcapi_err_setstring__doc__, +"err_setstring($module, exc, value, /)\n" +"--\n" +"\n"); + +#define _TESTCAPI_ERR_SETSTRING_METHODDEF \ + {"err_setstring", _PyCFunction_CAST(_testcapi_err_setstring), METH_FASTCALL, _testcapi_err_setstring__doc__}, + +static PyObject * +_testcapi_err_setstring_impl(PyObject *module, PyObject *exc, + const char *value, Py_ssize_t value_length); + +static PyObject * +_testcapi_err_setstring(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *exc; + const char *value; + Py_ssize_t value_length; + + if (!_PyArg_ParseStack(args, nargs, "Oz#:err_setstring", + &exc, &value, &value_length)) { + goto exit; + } + return_value = _testcapi_err_setstring_impl(module, exc, value, value_length); + +exit: + return return_value; +} + +PyDoc_STRVAR(_testcapi_err_setfromerrnowithfilename__doc__, +"err_setfromerrnowithfilename($module, error, exc, value, /)\n" +"--\n" +"\n"); + +#define _TESTCAPI_ERR_SETFROMERRNOWITHFILENAME_METHODDEF \ + {"err_setfromerrnowithfilename", _PyCFunction_CAST(_testcapi_err_setfromerrnowithfilename), METH_FASTCALL, _testcapi_err_setfromerrnowithfilename__doc__}, + +static PyObject * +_testcapi_err_setfromerrnowithfilename_impl(PyObject *module, int error, + PyObject *exc, const char *value, + Py_ssize_t value_length); + +static PyObject * +_testcapi_err_setfromerrnowithfilename(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int error; + PyObject *exc; + const char *value; + Py_ssize_t value_length; + + if (!_PyArg_ParseStack(args, nargs, "iOz#:err_setfromerrnowithfilename", + &error, &exc, &value, &value_length)) { + goto exit; + } + return_value = _testcapi_err_setfromerrnowithfilename_impl(module, error, exc, value, value_length); + +exit: + return return_value; +} + PyDoc_STRVAR(_testcapi_raise_exception__doc__, "raise_exception($module, exception, num_args, /)\n" "--\n" @@ -237,7 +299,7 @@ _testcapi_raise_exception(PyObject *module, PyObject *const *args, Py_ssize_t na goto exit; } exc = args[0]; - num_args = _PyLong_AsInt(args[1]); + num_args = PyLong_AsInt(args[1]); if (num_args == -1 && PyErr_Occurred()) { goto exit; } @@ -333,38 +395,6 @@ PyDoc_STRVAR(_testcapi_set_exception__doc__, #define _TESTCAPI_SET_EXCEPTION_METHODDEF \ {"set_exception", (PyCFunction)_testcapi_set_exception, METH_O, _testcapi_set_exception__doc__}, -PyDoc_STRVAR(_testcapi_write_unraisable_exc__doc__, -"write_unraisable_exc($module, exception, err_msg, obj, /)\n" -"--\n" -"\n"); - -#define _TESTCAPI_WRITE_UNRAISABLE_EXC_METHODDEF \ - {"write_unraisable_exc", _PyCFunction_CAST(_testcapi_write_unraisable_exc), METH_FASTCALL, _testcapi_write_unraisable_exc__doc__}, - -static PyObject * -_testcapi_write_unraisable_exc_impl(PyObject *module, PyObject *exc, - PyObject *err_msg, PyObject *obj); - -static PyObject * -_testcapi_write_unraisable_exc(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - PyObject *exc; - PyObject *err_msg; - PyObject *obj; - - if (!_PyArg_CheckPositional("write_unraisable_exc", nargs, 3, 3)) { - goto exit; - } - exc = args[0]; - err_msg = args[1]; - obj = args[2]; - return_value = _testcapi_write_unraisable_exc_impl(module, exc, err_msg, obj); - -exit: - return return_value; -} - PyDoc_STRVAR(_testcapi_traceback_print__doc__, "traceback_print($module, traceback, file, /)\n" "--\n" @@ -426,4 +456,4 @@ _testcapi_unstable_exc_prep_reraise_star(PyObject *module, PyObject *const *args exit: return return_value; } -/*[clinic end generated code: output=fd6aef54f195c77b input=a9049054013a1b77]*/ +/*[clinic end generated code: output=0b11ef105030a48e input=a9049054013a1b77]*/ diff --git a/Modules/_testcapi/clinic/float.c.h b/Modules/_testcapi/clinic/float.c.h index c1dff2a9ac5789..d5a00c8072da1e 100644 --- a/Modules/_testcapi/clinic/float.c.h +++ b/Modules/_testcapi/clinic/float.c.h @@ -2,11 +2,7 @@ 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 - +#include "pycore_modsupport.h" // _PyArg_CheckPositional() PyDoc_STRVAR(_testcapi_float_pack__doc__, "float_pack($module, size, d, le, /)\n" @@ -31,7 +27,7 @@ _testcapi_float_pack(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("float_pack", nargs, 3, 3)) { goto exit; } - size = _PyLong_AsInt(args[0]); + size = PyLong_AsInt(args[0]); if (size == -1 && PyErr_Occurred()) { goto exit; } @@ -45,7 +41,7 @@ _testcapi_float_pack(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } } - le = _PyLong_AsInt(args[2]); + le = PyLong_AsInt(args[2]); if (le == -1 && PyErr_Occurred()) { goto exit; } @@ -85,4 +81,4 @@ _testcapi_float_unpack(PyObject *module, PyObject *const *args, Py_ssize_t nargs exit: return return_value; } -/*[clinic end generated code: output=083e5df26cd5fbeb input=a9049054013a1b77]*/ +/*[clinic end generated code: output=b43dfd3a77fe04ba input=a9049054013a1b77]*/ diff --git a/Modules/_testcapi/clinic/long.c.h b/Modules/_testcapi/clinic/long.c.h index 95885e0ae17a6c..e2f7042be12c48 100644 --- a/Modules/_testcapi/clinic/long.c.h +++ b/Modules/_testcapi/clinic/long.c.h @@ -2,12 +2,6 @@ preserve [clinic start generated code]*/ -#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) -# include "pycore_gc.h" // PyGC_Head -# include "pycore_runtime.h" // _Py_ID() -#endif - - PyDoc_STRVAR(_testcapi_test_long_api__doc__, "test_long_api($module, /)\n" "--\n" @@ -139,23 +133,6 @@ _testcapi_test_long_as_double(PyObject *module, PyObject *Py_UNUSED(ignored)) return _testcapi_test_long_as_double_impl(module); } -PyDoc_STRVAR(_testcapi_test_long_numbits__doc__, -"test_long_numbits($module, /)\n" -"--\n" -"\n"); - -#define _TESTCAPI_TEST_LONG_NUMBITS_METHODDEF \ - {"test_long_numbits", (PyCFunction)_testcapi_test_long_numbits, METH_NOARGS, _testcapi_test_long_numbits__doc__}, - -static PyObject * -_testcapi_test_long_numbits_impl(PyObject *module); - -static PyObject * -_testcapi_test_long_numbits(PyObject *module, PyObject *Py_UNUSED(ignored)) -{ - return _testcapi_test_long_numbits_impl(module); -} - PyDoc_STRVAR(_testcapi_call_long_compact_api__doc__, "call_long_compact_api($module, arg, /)\n" "--\n" @@ -163,4 +140,12 @@ PyDoc_STRVAR(_testcapi_call_long_compact_api__doc__, #define _TESTCAPI_CALL_LONG_COMPACT_API_METHODDEF \ {"call_long_compact_api", (PyCFunction)_testcapi_call_long_compact_api, METH_O, _testcapi_call_long_compact_api__doc__}, -/*[clinic end generated code: output=d000a1b58fa81eab input=a9049054013a1b77]*/ + +PyDoc_STRVAR(_testcapi_PyLong_AsInt__doc__, +"PyLong_AsInt($module, arg, /)\n" +"--\n" +"\n"); + +#define _TESTCAPI_PYLONG_ASINT_METHODDEF \ + {"PyLong_AsInt", (PyCFunction)_testcapi_PyLong_AsInt, METH_O, _testcapi_PyLong_AsInt__doc__}, +/*[clinic end generated code: output=de762870526e241d input=a9049054013a1b77]*/ diff --git a/Modules/_testcapi/clinic/vectorcall.c.h b/Modules/_testcapi/clinic/vectorcall.c.h index 728c0d382565a7..c6049a438dc8fc 100644 --- a/Modules/_testcapi/clinic/vectorcall.c.h +++ b/Modules/_testcapi/clinic/vectorcall.c.h @@ -2,11 +2,7 @@ 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 - +#include "pycore_modsupport.h" // _PyArg_CheckPositional() PyDoc_STRVAR(_testcapi_pyobject_fastcalldict__doc__, "pyobject_fastcalldict($module, func, func_args, kwargs, /)\n" @@ -210,4 +206,4 @@ _testcapi_has_vectorcall_flag(PyObject *module, PyObject *arg) exit: return return_value; } -/*[clinic end generated code: output=beaf6beac3d13c25 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=210ae67caab177ba input=a9049054013a1b77]*/ diff --git a/Modules/_testcapi/clinic/vectorcall_limited.c.h b/Modules/_testcapi/clinic/vectorcall_limited.c.h new file mode 100644 index 00000000000000..a233aefec79ecd --- /dev/null +++ b/Modules/_testcapi/clinic/vectorcall_limited.c.h @@ -0,0 +1,20 @@ +/*[clinic input] +preserve +[clinic start generated code]*/ + +PyDoc_STRVAR(_testcapi_call_vectorcall__doc__, +"call_vectorcall($module, callable, /)\n" +"--\n" +"\n"); + +#define _TESTCAPI_CALL_VECTORCALL_METHODDEF \ + {"call_vectorcall", (PyCFunction)_testcapi_call_vectorcall, METH_O, _testcapi_call_vectorcall__doc__}, + +PyDoc_STRVAR(_testcapi_call_vectorcall_method__doc__, +"call_vectorcall_method($module, callable, /)\n" +"--\n" +"\n"); + +#define _TESTCAPI_CALL_VECTORCALL_METHOD_METHODDEF \ + {"call_vectorcall_method", (PyCFunction)_testcapi_call_vectorcall_method, METH_O, _testcapi_call_vectorcall_method__doc__}, +/*[clinic end generated code: output=e980906a39602528 input=a9049054013a1b77]*/ diff --git a/Modules/_testcapi/clinic/watchers.c.h b/Modules/_testcapi/clinic/watchers.c.h index 975244bd59a36b..ebd71d119fa347 100644 --- a/Modules/_testcapi/clinic/watchers.c.h +++ b/Modules/_testcapi/clinic/watchers.c.h @@ -2,11 +2,7 @@ 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 - +#include "pycore_modsupport.h" // _PyArg_CheckPositional() PyDoc_STRVAR(_testcapi_watch_dict__doc__, "watch_dict($module, watcher_id, dict, /)\n" @@ -29,7 +25,7 @@ _testcapi_watch_dict(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("watch_dict", nargs, 2, 2)) { goto exit; } - watcher_id = _PyLong_AsInt(args[0]); + watcher_id = PyLong_AsInt(args[0]); if (watcher_id == -1 && PyErr_Occurred()) { goto exit; } @@ -61,7 +57,7 @@ _testcapi_unwatch_dict(PyObject *module, PyObject *const *args, Py_ssize_t nargs if (!_PyArg_CheckPositional("unwatch_dict", nargs, 2, 2)) { goto exit; } - watcher_id = _PyLong_AsInt(args[0]); + watcher_id = PyLong_AsInt(args[0]); if (watcher_id == -1 && PyErr_Occurred()) { goto exit; } @@ -93,7 +89,7 @@ _testcapi_watch_type(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("watch_type", nargs, 2, 2)) { goto exit; } - watcher_id = _PyLong_AsInt(args[0]); + watcher_id = PyLong_AsInt(args[0]); if (watcher_id == -1 && PyErr_Occurred()) { goto exit; } @@ -125,7 +121,7 @@ _testcapi_unwatch_type(PyObject *module, PyObject *const *args, Py_ssize_t nargs if (!_PyArg_CheckPositional("unwatch_type", nargs, 2, 2)) { goto exit; } - watcher_id = _PyLong_AsInt(args[0]); + watcher_id = PyLong_AsInt(args[0]); if (watcher_id == -1 && PyErr_Occurred()) { goto exit; } @@ -195,4 +191,4 @@ _testcapi_set_func_kwdefaults_via_capi(PyObject *module, PyObject *const *args, exit: return return_value; } -/*[clinic end generated code: output=12c375089125d165 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=0e07ce7f295917a5 input=a9049054013a1b77]*/ diff --git a/Modules/_testcapi/code.c b/Modules/_testcapi/code.c index cadaf5eb94692e..c0193489b6f340 100644 --- a/Modules/_testcapi/code.c +++ b/Modules/_testcapi/code.c @@ -1,4 +1,5 @@ #include "parts.h" +#include "util.h" static Py_ssize_t get_code_extra_index(PyInterpreterState* interp) { @@ -9,12 +10,12 @@ get_code_extra_index(PyInterpreterState* interp) { PyObject *interp_dict = PyInterpreterState_GetDict(interp); // borrowed assert(interp_dict); // real users would handle missing dict... somehow - PyObject *index_obj = _PyDict_GetItemStringWithError(interp_dict, key); // borrowed + PyObject *index_obj; + if (PyDict_GetItemStringRef(interp_dict, key, &index_obj) < 0) { + goto finally; + } Py_ssize_t index = 0; if (!index_obj) { - if (PyErr_Occurred()) { - goto finally; - } index = PyUnstable_Eval_RequestCodeExtraIndex(NULL); if (index < 0 || PyErr_Occurred()) { goto finally; @@ -31,6 +32,7 @@ get_code_extra_index(PyInterpreterState* interp) { } else { index = PyLong_AsSsize_t(index_obj); + Py_DECREF(index_obj); if (index == -1 && PyErr_Occurred()) { goto finally; } @@ -74,7 +76,7 @@ test_code_extra(PyObject* self, PyObject *Py_UNUSED(callable)) } // Check the value is initially NULL - void *extra; + void *extra = UNINITIALIZED_PTR; int res = PyUnstable_Code_GetExtra(test_func_code, code_extra_index, &extra); if (res < 0) { goto finally; @@ -87,6 +89,7 @@ test_code_extra(PyObject* self, PyObject *Py_UNUSED(callable)) goto finally; } // Assert it was set correctly + extra = UNINITIALIZED_PTR; res = PyUnstable_Code_GetExtra(test_func_code, code_extra_index, &extra); if (res < 0) { goto finally; diff --git a/Modules/_testcapi/codec.c b/Modules/_testcapi/codec.c new file mode 100644 index 00000000000000..d13f51e20331a1 --- /dev/null +++ b/Modules/_testcapi/codec.c @@ -0,0 +1,17 @@ +#include "parts.h" +#include "util.h" + + +static PyMethodDef test_methods[] = { + {NULL}, +}; + +int +_PyTestCapi_Init_Codec(PyObject *m) +{ + if (PyModule_AddFunctions(m, test_methods) < 0){ + return -1; + } + + return 0; +} diff --git a/Modules/_testcapi/complex.c b/Modules/_testcapi/complex.c new file mode 100644 index 00000000000000..4a70217eb90d62 --- /dev/null +++ b/Modules/_testcapi/complex.c @@ -0,0 +1,167 @@ +#include "parts.h" +#include "util.h" + + +static PyObject * +complex_check(PyObject *Py_UNUSED(module), PyObject *obj) +{ + NULLABLE(obj); + return PyLong_FromLong(PyComplex_Check(obj)); +} + +static PyObject * +complex_checkexact(PyObject *Py_UNUSED(module), PyObject *obj) +{ + NULLABLE(obj); + return PyLong_FromLong(PyComplex_CheckExact(obj)); +} + +static PyObject * +complex_fromccomplex(PyObject *Py_UNUSED(module), PyObject *obj) +{ + Py_complex complex; + + if (!PyArg_Parse(obj, "D", &complex)) { + return NULL; + } + + return PyComplex_FromCComplex(complex); +} + +static PyObject * +complex_fromdoubles(PyObject *Py_UNUSED(module), PyObject *args) +{ + double real, imag; + + if (!PyArg_ParseTuple(args, "dd", &real, &imag)) { + return NULL; + } + + return PyComplex_FromDoubles(real, imag); +} + +static PyObject * +complex_realasdouble(PyObject *Py_UNUSED(module), PyObject *obj) +{ + double real; + + NULLABLE(obj); + real = PyComplex_RealAsDouble(obj); + + if (real == -1. && PyErr_Occurred()) { + return NULL; + } + + return PyFloat_FromDouble(real); +} + +static PyObject * +complex_imagasdouble(PyObject *Py_UNUSED(module), PyObject *obj) +{ + double imag; + + NULLABLE(obj); + imag = PyComplex_ImagAsDouble(obj); + + if (imag == -1. && PyErr_Occurred()) { + return NULL; + } + + return PyFloat_FromDouble(imag); +} + +static PyObject * +complex_asccomplex(PyObject *Py_UNUSED(module), PyObject *obj) +{ + Py_complex complex; + + NULLABLE(obj); + complex = PyComplex_AsCComplex(obj); + + if (complex.real == -1. && PyErr_Occurred()) { + return NULL; + } + + return PyComplex_FromCComplex(complex); +} + +static PyObject* +_py_c_neg(PyObject *Py_UNUSED(module), PyObject *num) +{ + Py_complex complex; + + complex = PyComplex_AsCComplex(num); + if (complex.real == -1. && PyErr_Occurred()) { + return NULL; + } + + return PyComplex_FromCComplex(_Py_c_neg(complex)); +} + +#define _PY_C_FUNC2(suffix) \ + static PyObject * \ + _py_c_##suffix(PyObject *Py_UNUSED(module), PyObject *args) \ + { \ + Py_complex num, exp, res; \ + \ + if (!PyArg_ParseTuple(args, "DD", &num, &exp)) { \ + return NULL; \ + } \ + \ + errno = 0; \ + res = _Py_c_##suffix(num, exp); \ + return Py_BuildValue("Di", &res, errno); \ + }; + +_PY_C_FUNC2(sum) +_PY_C_FUNC2(diff) +_PY_C_FUNC2(prod) +_PY_C_FUNC2(quot) +_PY_C_FUNC2(pow) + +static PyObject* +_py_c_abs(PyObject *Py_UNUSED(module), PyObject* obj) +{ + Py_complex complex; + double res; + + NULLABLE(obj); + complex = PyComplex_AsCComplex(obj); + + if (complex.real == -1. && PyErr_Occurred()) { + return NULL; + } + + errno = 0; + res = _Py_c_abs(complex); + return Py_BuildValue("di", res, errno); +} + + +static PyMethodDef test_methods[] = { + {"complex_check", complex_check, METH_O}, + {"complex_checkexact", complex_checkexact, METH_O}, + {"complex_fromccomplex", complex_fromccomplex, METH_O}, + {"complex_fromdoubles", complex_fromdoubles, METH_VARARGS}, + {"complex_realasdouble", complex_realasdouble, METH_O}, + {"complex_imagasdouble", complex_imagasdouble, METH_O}, + {"complex_asccomplex", complex_asccomplex, METH_O}, + {"_py_c_sum", _py_c_sum, METH_VARARGS}, + {"_py_c_diff", _py_c_diff, METH_VARARGS}, + {"_py_c_neg", _py_c_neg, METH_O}, + {"_py_c_prod", _py_c_prod, METH_VARARGS}, + {"_py_c_quot", _py_c_quot, METH_VARARGS}, + {"_py_c_pow", _py_c_pow, METH_VARARGS}, + {"_py_c_abs", _py_c_abs, METH_O}, + {NULL}, +}; + +int +_PyTestCapi_Init_Complex(PyObject *mod) +{ + if (PyModule_AddFunctions(mod, test_methods) < 0) { + return -1; + } + + return 0; +} diff --git a/Modules/_testcapi/datetime.c b/Modules/_testcapi/datetime.c index 88f992915fa8c1..b1796039f0d83a 100644 --- a/Modules/_testcapi/datetime.c +++ b/Modules/_testcapi/datetime.c @@ -85,17 +85,25 @@ make_timezones_capi(PyObject *self, PyObject *args) { PyObject *offset = PyDelta_FromDSU(0, -18000, 0); PyObject *name = PyUnicode_FromString("EST"); + if (offset == NULL || name == NULL) { + Py_XDECREF(offset); + Py_XDECREF(name); + return NULL; + } PyObject *est_zone_capi = PyDateTimeAPI->TimeZone_FromTimeZone(offset, name); PyObject *est_zone_macro = PyTimeZone_FromOffsetAndName(offset, name); PyObject *est_zone_macro_noname = PyTimeZone_FromOffset(offset); - - Py_DecRef(offset); - Py_DecRef(name); - + Py_DECREF(offset); + Py_DECREF(name); + if (est_zone_capi == NULL || est_zone_macro == NULL || + est_zone_macro_noname == NULL) + { + goto error; + } PyObject *rv = PyTuple_New(3); if (rv == NULL) { - return NULL; + goto error; } PyTuple_SET_ITEM(rv, 0, est_zone_capi); @@ -103,6 +111,11 @@ make_timezones_capi(PyObject *self, PyObject *args) PyTuple_SET_ITEM(rv, 2, est_zone_macro_noname); return rv; +error: + Py_XDECREF(est_zone_capi); + Py_XDECREF(est_zone_macro); + Py_XDECREF(est_zone_macro_noname); + return NULL; } static PyObject * @@ -110,6 +123,11 @@ get_timezones_offset_zero(PyObject *self, PyObject *args) { PyObject *offset = PyDelta_FromDSU(0, 0, 0); PyObject *name = PyUnicode_FromString(""); + if (offset == NULL || name == NULL) { + Py_XDECREF(offset); + Py_XDECREF(name); + return NULL; + } // These two should return the UTC singleton PyObject *utc_singleton_0 = PyTimeZone_FromOffset(offset); @@ -117,16 +135,28 @@ get_timezones_offset_zero(PyObject *self, PyObject *args) // This one will return +00:00 zone, but not the UTC singleton PyObject *non_utc_zone = PyTimeZone_FromOffsetAndName(offset, name); - - Py_DecRef(offset); - Py_DecRef(name); + Py_DECREF(offset); + Py_DECREF(name); + if (utc_singleton_0 == NULL || utc_singleton_1 == NULL || + non_utc_zone == NULL) + { + goto error; + } PyObject *rv = PyTuple_New(3); + if (rv == NULL) { + goto error; + } PyTuple_SET_ITEM(rv, 0, utc_singleton_0); PyTuple_SET_ITEM(rv, 1, utc_singleton_1); PyTuple_SET_ITEM(rv, 2, non_utc_zone); return rv; +error: + Py_XDECREF(utc_singleton_0); + Py_XDECREF(utc_singleton_1); + Py_XDECREF(non_utc_zone); + return NULL; } static PyObject * diff --git a/Modules/_testcapi/dict.c b/Modules/_testcapi/dict.c new file mode 100644 index 00000000000000..42e056b7d07a31 --- /dev/null +++ b/Modules/_testcapi/dict.c @@ -0,0 +1,458 @@ +#include "parts.h" +#include "util.h" + + +static PyObject * +dict_check(PyObject *self, PyObject *obj) +{ + NULLABLE(obj); + return PyLong_FromLong(PyDict_Check(obj)); +} + +static PyObject * +dict_checkexact(PyObject *self, PyObject *obj) +{ + NULLABLE(obj); + return PyLong_FromLong(PyDict_CheckExact(obj)); +} + +static PyObject * +dict_new(PyObject *self, PyObject *Py_UNUSED(ignored)) +{ + return PyDict_New(); +} + +static PyObject * +dictproxy_new(PyObject *self, PyObject *obj) +{ + NULLABLE(obj); + return PyDictProxy_New(obj); +} + +static PyObject * +dict_clear(PyObject *self, PyObject *obj) +{ + PyDict_Clear(obj); + Py_RETURN_NONE; +} + +static PyObject * +dict_copy(PyObject *self, PyObject *obj) +{ + NULLABLE(obj); + return PyDict_Copy(obj); +} + +static PyObject * +dict_contains(PyObject *self, PyObject *args) +{ + PyObject *obj, *key; + if (!PyArg_ParseTuple(args, "OO", &obj, &key)) { + return NULL; + } + NULLABLE(obj); + NULLABLE(key); + RETURN_INT(PyDict_Contains(obj, key)); +} + +static PyObject * +dict_containsstring(PyObject *self, PyObject *args) +{ + PyObject *obj; + const char *key; + Py_ssize_t size; + if (!PyArg_ParseTuple(args, "Oz#", &obj, &key, &size)) { + return NULL; + } + NULLABLE(obj); + RETURN_INT(PyDict_ContainsString(obj, key)); +} + +static PyObject * +dict_size(PyObject *self, PyObject *obj) +{ + NULLABLE(obj); + RETURN_SIZE(PyDict_Size(obj)); +} + +static PyObject * +dict_getitem(PyObject *self, PyObject *args) +{ + PyObject *mapping, *key; + if (!PyArg_ParseTuple(args, "OO", &mapping, &key)) { + return NULL; + } + NULLABLE(mapping); + NULLABLE(key); + PyObject *value = PyDict_GetItem(mapping, key); + if (value == NULL) { + if (PyErr_Occurred()) { + return NULL; + } + return Py_NewRef(PyExc_KeyError); + } + return Py_NewRef(value); +} + +static PyObject * +dict_getitemstring(PyObject *self, PyObject *args) +{ + PyObject *mapping; + const char *key; + Py_ssize_t size; + if (!PyArg_ParseTuple(args, "Oz#", &mapping, &key, &size)) { + return NULL; + } + NULLABLE(mapping); + PyObject *value = PyDict_GetItemString(mapping, key); + if (value == NULL) { + if (PyErr_Occurred()) { + return NULL; + } + return Py_NewRef(PyExc_KeyError); + } + return Py_NewRef(value); +} + +static PyObject * +dict_getitemwitherror(PyObject *self, PyObject *args) +{ + PyObject *mapping, *key; + if (!PyArg_ParseTuple(args, "OO", &mapping, &key)) { + return NULL; + } + NULLABLE(mapping); + NULLABLE(key); + PyObject *value = PyDict_GetItemWithError(mapping, key); + if (value == NULL) { + if (PyErr_Occurred()) { + return NULL; + } + return Py_NewRef(PyExc_KeyError); + } + return Py_NewRef(value); +} + + +static PyObject * +dict_getitemref(PyObject *self, PyObject *args) +{ + PyObject *obj, *attr_name, *value = UNINITIALIZED_PTR; + if (!PyArg_ParseTuple(args, "OO", &obj, &attr_name)) { + return NULL; + } + NULLABLE(obj); + NULLABLE(attr_name); + + switch (PyDict_GetItemRef(obj, attr_name, &value)) { + case -1: + assert(value == NULL); + return NULL; + case 0: + assert(value == NULL); + return Py_NewRef(PyExc_KeyError); + case 1: + return value; + default: + Py_FatalError("PyMapping_GetItemRef() returned invalid code"); + Py_UNREACHABLE(); + } +} + +static PyObject * +dict_getitemstringref(PyObject *self, PyObject *args) +{ + PyObject *obj, *value = UNINITIALIZED_PTR; + const char *attr_name; + Py_ssize_t size; + if (!PyArg_ParseTuple(args, "Oz#", &obj, &attr_name, &size)) { + return NULL; + } + NULLABLE(obj); + + switch (PyDict_GetItemStringRef(obj, attr_name, &value)) { + case -1: + assert(value == NULL); + return NULL; + case 0: + assert(value == NULL); + return Py_NewRef(PyExc_KeyError); + case 1: + return value; + default: + Py_FatalError("PyDict_GetItemStringRef() returned invalid code"); + Py_UNREACHABLE(); + } +} + +static PyObject * +dict_setitem(PyObject *self, PyObject *args) +{ + PyObject *mapping, *key, *value; + if (!PyArg_ParseTuple(args, "OOO", &mapping, &key, &value)) { + return NULL; + } + NULLABLE(mapping); + NULLABLE(key); + NULLABLE(value); + RETURN_INT(PyDict_SetItem(mapping, key, value)); +} + +static PyObject * +dict_setitemstring(PyObject *self, PyObject *args) +{ + PyObject *mapping, *value; + const char *key; + Py_ssize_t size; + if (!PyArg_ParseTuple(args, "Oz#O", &mapping, &key, &size, &value)) { + return NULL; + } + NULLABLE(mapping); + NULLABLE(value); + RETURN_INT(PyDict_SetItemString(mapping, key, value)); +} + +static PyObject * +dict_setdefault(PyObject *self, PyObject *args) +{ + PyObject *mapping, *key, *defaultobj; + if (!PyArg_ParseTuple(args, "OOO", &mapping, &key, &defaultobj)) { + return NULL; + } + NULLABLE(mapping); + NULLABLE(key); + NULLABLE(defaultobj); + return PyDict_SetDefault(mapping, key, defaultobj); +} + +static PyObject * +dict_delitem(PyObject *self, PyObject *args) +{ + PyObject *mapping, *key; + if (!PyArg_ParseTuple(args, "OO", &mapping, &key)) { + return NULL; + } + NULLABLE(mapping); + NULLABLE(key); + RETURN_INT(PyDict_DelItem(mapping, key)); +} + +static PyObject * +dict_delitemstring(PyObject *self, PyObject *args) +{ + PyObject *mapping; + const char *key; + Py_ssize_t size; + if (!PyArg_ParseTuple(args, "Oz#", &mapping, &key, &size)) { + return NULL; + } + NULLABLE(mapping); + RETURN_INT(PyDict_DelItemString(mapping, key)); +} + +static PyObject * +dict_keys(PyObject *self, PyObject *obj) +{ + NULLABLE(obj); + return PyDict_Keys(obj); +} + +static PyObject * +dict_values(PyObject *self, PyObject *obj) +{ + NULLABLE(obj); + return PyDict_Values(obj); +} + +static PyObject * +dict_items(PyObject *self, PyObject *obj) +{ + NULLABLE(obj); + return PyDict_Items(obj); +} + +static PyObject * +dict_next(PyObject *self, PyObject *args) +{ + PyObject *mapping, *key = UNINITIALIZED_PTR, *value = UNINITIALIZED_PTR; + Py_ssize_t pos; + if (!PyArg_ParseTuple(args, "On", &mapping, &pos)) { + return NULL; + } + NULLABLE(mapping); + int rc = PyDict_Next(mapping, &pos, &key, &value); + if (rc != 0) { + return Py_BuildValue("inOO", rc, pos, key, value); + } + assert(key == UNINITIALIZED_PTR); + assert(value == UNINITIALIZED_PTR); + if (PyErr_Occurred()) { + return NULL; + } + Py_RETURN_NONE; +} + +static PyObject * +dict_merge(PyObject *self, PyObject *args) +{ + PyObject *mapping, *mapping2; + int override; + if (!PyArg_ParseTuple(args, "OOi", &mapping, &mapping2, &override)) { + return NULL; + } + NULLABLE(mapping); + NULLABLE(mapping2); + RETURN_INT(PyDict_Merge(mapping, mapping2, override)); +} + +static PyObject * +dict_update(PyObject *self, PyObject *args) +{ + PyObject *mapping, *mapping2; + if (!PyArg_ParseTuple(args, "OO", &mapping, &mapping2)) { + return NULL; + } + NULLABLE(mapping); + NULLABLE(mapping2); + RETURN_INT(PyDict_Update(mapping, mapping2)); +} + +static PyObject * +dict_mergefromseq2(PyObject *self, PyObject *args) +{ + PyObject *mapping, *seq; + int override; + if (!PyArg_ParseTuple(args, "OOi", &mapping, &seq, &override)) { + return NULL; + } + NULLABLE(mapping); + NULLABLE(seq); + RETURN_INT(PyDict_MergeFromSeq2(mapping, seq, override)); +} + + +static PyObject * +dict_pop(PyObject *self, PyObject *args) +{ + // Test PyDict_Pop(dict, key, &value) + PyObject *dict, *key; + if (!PyArg_ParseTuple(args, "OO", &dict, &key)) { + return NULL; + } + NULLABLE(dict); + NULLABLE(key); + PyObject *result = UNINITIALIZED_PTR; + int res = PyDict_Pop(dict, key, &result); + if (res < 0) { + assert(result == NULL); + return NULL; + } + if (res == 0) { + assert(result == NULL); + result = Py_NewRef(Py_None); + } + else { + assert(result != NULL); + } + return Py_BuildValue("iN", res, result); +} + + +static PyObject * +dict_pop_null(PyObject *self, PyObject *args) +{ + // Test PyDict_Pop(dict, key, NULL) + PyObject *dict, *key; + if (!PyArg_ParseTuple(args, "OO", &dict, &key)) { + return NULL; + } + NULLABLE(dict); + NULLABLE(key); + RETURN_INT(PyDict_Pop(dict, key, NULL)); +} + + +static PyObject * +dict_popstring(PyObject *self, PyObject *args) +{ + PyObject *dict; + const char *key; + Py_ssize_t key_size; + if (!PyArg_ParseTuple(args, "Oz#", &dict, &key, &key_size)) { + return NULL; + } + NULLABLE(dict); + PyObject *result = UNINITIALIZED_PTR; + int res = PyDict_PopString(dict, key, &result); + if (res < 0) { + assert(result == NULL); + return NULL; + } + if (res == 0) { + assert(result == NULL); + result = Py_NewRef(Py_None); + } + else { + assert(result != NULL); + } + return Py_BuildValue("iN", res, result); +} + + +static PyObject * +dict_popstring_null(PyObject *self, PyObject *args) +{ + PyObject *dict; + const char *key; + Py_ssize_t key_size; + if (!PyArg_ParseTuple(args, "Oz#", &dict, &key, &key_size)) { + return NULL; + } + NULLABLE(dict); + RETURN_INT(PyDict_PopString(dict, key, NULL)); +} + + +static PyMethodDef test_methods[] = { + {"dict_check", dict_check, METH_O}, + {"dict_checkexact", dict_checkexact, METH_O}, + {"dict_new", dict_new, METH_NOARGS}, + {"dictproxy_new", dictproxy_new, METH_O}, + {"dict_clear", dict_clear, METH_O}, + {"dict_copy", dict_copy, METH_O}, + {"dict_size", dict_size, METH_O}, + {"dict_getitem", dict_getitem, METH_VARARGS}, + {"dict_getitemwitherror", dict_getitemwitherror, METH_VARARGS}, + {"dict_getitemstring", dict_getitemstring, METH_VARARGS}, + {"dict_getitemref", dict_getitemref, METH_VARARGS}, + {"dict_getitemstringref", dict_getitemstringref, METH_VARARGS}, + {"dict_contains", dict_contains, METH_VARARGS}, + {"dict_containsstring", dict_containsstring, METH_VARARGS}, + {"dict_setitem", dict_setitem, METH_VARARGS}, + {"dict_setitemstring", dict_setitemstring, METH_VARARGS}, + {"dict_delitem", dict_delitem, METH_VARARGS}, + {"dict_delitemstring", dict_delitemstring, METH_VARARGS}, + {"dict_setdefault", dict_setdefault, METH_VARARGS}, + {"dict_keys", dict_keys, METH_O}, + {"dict_values", dict_values, METH_O}, + {"dict_items", dict_items, METH_O}, + {"dict_next", dict_next, METH_VARARGS}, + {"dict_merge", dict_merge, METH_VARARGS}, + {"dict_update", dict_update, METH_VARARGS}, + {"dict_mergefromseq2", dict_mergefromseq2, METH_VARARGS}, + {"dict_pop", dict_pop, METH_VARARGS}, + {"dict_pop_null", dict_pop_null, METH_VARARGS}, + {"dict_popstring", dict_popstring, METH_VARARGS}, + {"dict_popstring_null", dict_popstring_null, METH_VARARGS}, + {NULL}, +}; + +int +_PyTestCapi_Init_Dict(PyObject *m) +{ + if (PyModule_AddFunctions(m, test_methods) < 0) { + return -1; + } + + return 0; +} diff --git a/Modules/_testcapi/docstring.c b/Modules/_testcapi/docstring.c index a997c54a8a69c4..d99fbdd904b594 100644 --- a/Modules/_testcapi/docstring.c +++ b/Modules/_testcapi/docstring.c @@ -66,42 +66,132 @@ test_with_docstring(PyObject *self, PyObject *Py_UNUSED(ignored)) static PyMethodDef test_methods[] = { {"docstring_empty", - (PyCFunction)test_with_docstring, METH_NOARGS, + (PyCFunction)test_with_docstring, METH_VARARGS, docstring_empty}, {"docstring_no_signature", + (PyCFunction)test_with_docstring, METH_VARARGS, + docstring_no_signature}, + {"docstring_no_signature_noargs", (PyCFunction)test_with_docstring, METH_NOARGS, docstring_no_signature}, + {"docstring_no_signature_o", + (PyCFunction)test_with_docstring, METH_O, + docstring_no_signature}, {"docstring_with_invalid_signature", - (PyCFunction)test_with_docstring, METH_NOARGS, + (PyCFunction)test_with_docstring, METH_VARARGS, docstring_with_invalid_signature}, {"docstring_with_invalid_signature2", - (PyCFunction)test_with_docstring, METH_NOARGS, + (PyCFunction)test_with_docstring, METH_VARARGS, docstring_with_invalid_signature2}, {"docstring_with_signature", - (PyCFunction)test_with_docstring, METH_NOARGS, + (PyCFunction)test_with_docstring, METH_VARARGS, docstring_with_signature}, {"docstring_with_signature_and_extra_newlines", - (PyCFunction)test_with_docstring, METH_NOARGS, + (PyCFunction)test_with_docstring, METH_VARARGS, docstring_with_signature_and_extra_newlines}, {"docstring_with_signature_but_no_doc", - (PyCFunction)test_with_docstring, METH_NOARGS, + (PyCFunction)test_with_docstring, METH_VARARGS, docstring_with_signature_but_no_doc}, {"docstring_with_signature_with_defaults", - (PyCFunction)test_with_docstring, METH_NOARGS, + (PyCFunction)test_with_docstring, METH_VARARGS, docstring_with_signature_with_defaults}, {"no_docstring", - (PyCFunction)test_with_docstring, METH_NOARGS}, + (PyCFunction)test_with_docstring, METH_VARARGS}, {"test_with_docstring", - test_with_docstring, METH_NOARGS, + test_with_docstring, METH_VARARGS, PyDoc_STR("This is a pretty normal docstring.")}, + {"func_with_unrepresentable_signature", + (PyCFunction)test_with_docstring, METH_VARARGS, + PyDoc_STR( + "func_with_unrepresentable_signature($module, /, a, b=)\n" + "--\n\n" + "This docstring has a signature with unrepresentable default." + )}, + {NULL}, +}; + +static PyMethodDef DocStringNoSignatureTest_methods[] = { + {"meth_noargs", + (PyCFunction)test_with_docstring, METH_NOARGS, + docstring_no_signature}, + {"meth_o", + (PyCFunction)test_with_docstring, METH_O, + docstring_no_signature}, + {"meth_noargs_class", + (PyCFunction)test_with_docstring, METH_NOARGS|METH_CLASS, + docstring_no_signature}, + {"meth_o_class", + (PyCFunction)test_with_docstring, METH_O|METH_CLASS, + docstring_no_signature}, + {"meth_noargs_static", + (PyCFunction)test_with_docstring, METH_NOARGS|METH_STATIC, + docstring_no_signature}, + {"meth_o_static", + (PyCFunction)test_with_docstring, METH_O|METH_STATIC, + docstring_no_signature}, + {"meth_noargs_coexist", + (PyCFunction)test_with_docstring, METH_NOARGS|METH_COEXIST, + docstring_no_signature}, + {"meth_o_coexist", + (PyCFunction)test_with_docstring, METH_O|METH_COEXIST, + docstring_no_signature}, + {NULL}, +}; + +static PyTypeObject DocStringNoSignatureTest = { + PyVarObject_HEAD_INIT(NULL, 0) + .tp_name = "_testcapi.DocStringNoSignatureTest", + .tp_basicsize = sizeof(PyObject), + .tp_flags = Py_TPFLAGS_DEFAULT, + .tp_methods = DocStringNoSignatureTest_methods, + .tp_new = PyType_GenericNew, +}; + +static PyMethodDef DocStringUnrepresentableSignatureTest_methods[] = { + {"meth", + (PyCFunction)test_with_docstring, METH_VARARGS, + PyDoc_STR( + "meth($self, /, a, b=)\n" + "--\n\n" + "This docstring has a signature with unrepresentable default." + )}, + {"classmeth", + (PyCFunction)test_with_docstring, METH_VARARGS|METH_CLASS, + PyDoc_STR( + "classmeth($type, /, a, b=)\n" + "--\n\n" + "This docstring has a signature with unrepresentable default." + )}, + {"staticmeth", + (PyCFunction)test_with_docstring, METH_VARARGS|METH_STATIC, + PyDoc_STR( + "staticmeth(a, b=)\n" + "--\n\n" + "This docstring has a signature with unrepresentable default." + )}, {NULL}, }; +static PyTypeObject DocStringUnrepresentableSignatureTest = { + PyVarObject_HEAD_INIT(NULL, 0) + .tp_name = "_testcapi.DocStringUnrepresentableSignatureTest", + .tp_basicsize = sizeof(PyObject), + .tp_flags = Py_TPFLAGS_DEFAULT, + .tp_methods = DocStringUnrepresentableSignatureTest_methods, + .tp_new = PyType_GenericNew, +}; + int _PyTestCapi_Init_Docstring(PyObject *mod) { if (PyModule_AddFunctions(mod, test_methods) < 0) { return -1; } + if (PyModule_AddType(mod, &DocStringNoSignatureTest) < 0) { + return -1; + } + if (PyModule_AddType(mod, &DocStringUnrepresentableSignatureTest) < 0) { + return -1; + } return 0; } diff --git a/Modules/_testcapi/exceptions.c b/Modules/_testcapi/exceptions.c index a627bf1717fe0c..42a9915143e6fa 100644 --- a/Modules/_testcapi/exceptions.c +++ b/Modules/_testcapi/exceptions.c @@ -1,6 +1,11 @@ +// clinic/exceptions.c.h uses internal pycore_modsupport.h API +#define PYTESTCAPI_NEED_INTERNAL_API + #include "parts.h" +#include "util.h" #include "clinic/exceptions.c.h" + /*[clinic input] module _testcapi [clinic start generated code]*/ @@ -118,17 +123,57 @@ _testcapi_exc_set_object_fetch_impl(PyObject *module, PyObject *exc, PyObject *obj) /*[clinic end generated code: output=7a5ff5f6d3cf687f input=77ec686f1f95fa38]*/ { - PyObject *type; - PyObject *value; - PyObject *tb; + PyObject *type = UNINITIALIZED_PTR; + PyObject *value = UNINITIALIZED_PTR; + PyObject *tb = UNINITIALIZED_PTR; PyErr_SetObject(exc, obj); PyErr_Fetch(&type, &value, &tb); + assert(type != UNINITIALIZED_PTR); + assert(value != UNINITIALIZED_PTR); + assert(tb != UNINITIALIZED_PTR); Py_XDECREF(type); Py_XDECREF(tb); return value; } +/*[clinic input] +_testcapi.err_setstring + exc: object + value: str(zeroes=True, accept={robuffer, str, NoneType}) + / +[clinic start generated code]*/ + +static PyObject * +_testcapi_err_setstring_impl(PyObject *module, PyObject *exc, + const char *value, Py_ssize_t value_length) +/*[clinic end generated code: output=fba8705e5703dd3f input=e8a95fad66d9004b]*/ +{ + NULLABLE(exc); + PyErr_SetString(exc, value); + return NULL; +} + +/*[clinic input] +_testcapi.err_setfromerrnowithfilename + error: int + exc: object + value: str(zeroes=True, accept={robuffer, str, NoneType}) + / +[clinic start generated code]*/ + +static PyObject * +_testcapi_err_setfromerrnowithfilename_impl(PyObject *module, int error, + PyObject *exc, const char *value, + Py_ssize_t value_length) +/*[clinic end generated code: output=d02df5749a01850e input=ff7c384234bf097f]*/ +{ + NULLABLE(exc); + errno = error; + PyErr_SetFromErrnoWithFilename(exc, value); + return NULL; +} + /*[clinic input] _testcapi.raise_exception exception as exc: object @@ -205,7 +250,7 @@ _testcapi_set_exc_info_impl(PyObject *module, PyObject *new_type, PyObject *new_value, PyObject *new_tb) /*[clinic end generated code: output=b55fa35dec31300e input=ea9f19e0f55fe5b3]*/ { - PyObject *type, *value, *tb; + PyObject *type = UNINITIALIZED_PTR, *value = UNINITIALIZED_PTR, *tb = UNINITIALIZED_PTR; PyErr_GetExcInfo(&type, &value, &tb); Py_INCREF(new_type); @@ -239,36 +284,6 @@ _testcapi_set_exception(PyObject *module, PyObject *new_exc) return exc; } -/*[clinic input] -_testcapi.write_unraisable_exc - exception as exc: object - err_msg: object - obj: object - / -[clinic start generated code]*/ - -static PyObject * -_testcapi_write_unraisable_exc_impl(PyObject *module, PyObject *exc, - PyObject *err_msg, PyObject *obj) -/*[clinic end generated code: output=39827c5e0a8c2092 input=582498da5b2ee6cf]*/ -{ - - const char *err_msg_utf8; - if (err_msg != Py_None) { - err_msg_utf8 = PyUnicode_AsUTF8(err_msg); - if (err_msg_utf8 == NULL) { - return NULL; - } - } - else { - err_msg_utf8 = NULL; - } - - PyErr_SetObject((PyObject *)Py_TYPE(exc), exc); - _PyErr_WriteUnraisableMsg(err_msg_utf8, obj); - Py_RETURN_NONE; -} - /*[clinic input] _testcapi.traceback_print traceback: object @@ -288,6 +303,46 @@ _testcapi_traceback_print_impl(PyObject *module, PyObject *traceback, Py_RETURN_NONE; } +static PyObject * +err_writeunraisable(PyObject *Py_UNUSED(module), PyObject *args) +{ + PyObject *exc, *obj; + if (!PyArg_ParseTuple(args, "OO", &exc, &obj)) { + return NULL; + } + NULLABLE(exc); + NULLABLE(obj); + if (exc) { + PyErr_SetRaisedException(Py_NewRef(exc)); + } + PyErr_WriteUnraisable(obj); + Py_RETURN_NONE; +} + +static PyObject * +err_formatunraisable(PyObject *Py_UNUSED(module), PyObject *args) +{ + PyObject *exc; + const char *fmt; + Py_ssize_t fmtlen; + PyObject *objs[10] = {NULL}; + + if (!PyArg_ParseTuple(args, "Oz#|OOOOOOOOOO", &exc, &fmt, &fmtlen, + &objs[0], &objs[1], &objs[2], &objs[3], &objs[4], + &objs[5], &objs[6], &objs[7], &objs[8], &objs[9])) + { + return NULL; + } + NULLABLE(exc); + if (exc) { + PyErr_SetRaisedException(Py_NewRef(exc)); + } + PyErr_FormatUnraisable(fmt, + objs[0], objs[1], objs[2], objs[3], objs[4], + objs[5], objs[6], objs[7], objs[8], objs[9]); + Py_RETURN_NONE; +} + /*[clinic input] _testcapi.unstable_exc_prep_reraise_star orig: object @@ -332,18 +387,21 @@ static PyTypeObject PyRecursingInfinitelyError_Type = { static PyMethodDef test_methods[] = { {"err_restore", err_restore, METH_VARARGS}, + {"err_writeunraisable", err_writeunraisable, METH_VARARGS}, + {"err_formatunraisable", err_formatunraisable, METH_VARARGS}, _TESTCAPI_ERR_SET_RAISED_METHODDEF _TESTCAPI_EXCEPTION_PRINT_METHODDEF _TESTCAPI_FATAL_ERROR_METHODDEF _TESTCAPI_MAKE_EXCEPTION_WITH_DOC_METHODDEF _TESTCAPI_EXC_SET_OBJECT_METHODDEF _TESTCAPI_EXC_SET_OBJECT_FETCH_METHODDEF + _TESTCAPI_ERR_SETSTRING_METHODDEF + _TESTCAPI_ERR_SETFROMERRNOWITHFILENAME_METHODDEF _TESTCAPI_RAISE_EXCEPTION_METHODDEF _TESTCAPI_RAISE_MEMORYERROR_METHODDEF _TESTCAPI_SET_EXC_INFO_METHODDEF _TESTCAPI_SET_EXCEPTION_METHODDEF _TESTCAPI_TRACEBACK_PRINT_METHODDEF - _TESTCAPI_WRITE_UNRAISABLE_EXC_METHODDEF _TESTCAPI_UNSTABLE_EXC_PREP_RERAISE_STAR_METHODDEF {NULL}, }; diff --git a/Modules/_testcapi/file.c b/Modules/_testcapi/file.c new file mode 100644 index 00000000000000..634563f6ea12cb --- /dev/null +++ b/Modules/_testcapi/file.c @@ -0,0 +1,17 @@ +#include "parts.h" +#include "util.h" + + +static PyMethodDef test_methods[] = { + {NULL}, +}; + +int +_PyTestCapi_Init_File(PyObject *m) +{ + if (PyModule_AddFunctions(m, test_methods) < 0){ + return -1; + } + + return 0; +} diff --git a/Modules/_testcapi/float.c b/Modules/_testcapi/float.c index cff53fb950fcc6..4fcbaf3bb2aa1e 100644 --- a/Modules/_testcapi/float.c +++ b/Modules/_testcapi/float.c @@ -1,7 +1,76 @@ +// clinic/float.c.h uses internal pycore_modsupport.h API +#define PYTESTCAPI_NEED_INTERNAL_API + #include "parts.h" +#include "util.h" #include "clinic/float.c.h" +static PyObject * +float_check(PyObject *Py_UNUSED(module), PyObject *obj) +{ + NULLABLE(obj); + return PyLong_FromLong(PyFloat_Check(obj)); +} + +static PyObject * +float_checkexact(PyObject *Py_UNUSED(module), PyObject *obj) +{ + NULLABLE(obj); + return PyLong_FromLong(PyFloat_CheckExact(obj)); +} + +static PyObject * +float_fromstring(PyObject *Py_UNUSED(module), PyObject *obj) +{ + NULLABLE(obj); + return PyFloat_FromString(obj); +} + +static PyObject * +float_fromdouble(PyObject *Py_UNUSED(module), PyObject *obj) +{ + double d; + + if (!PyArg_Parse(obj, "d", &d)) { + return NULL; + } + + return PyFloat_FromDouble(d); +} + +static PyObject * +float_asdouble(PyObject *Py_UNUSED(module), PyObject *obj) +{ + double d; + + NULLABLE(obj); + d = PyFloat_AsDouble(obj); + if (d == -1. && PyErr_Occurred()) { + return NULL; + } + + return PyFloat_FromDouble(d); +} + +static PyObject * +float_getinfo(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(arg)) +{ + return PyFloat_GetInfo(); +} + +static PyObject * +float_getmax(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(arg)) +{ + return PyFloat_FromDouble(PyFloat_GetMax()); +} + +static PyObject * +float_getmin(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(arg)) +{ + return PyFloat_FromDouble(PyFloat_GetMin()); +} + /*[clinic input] module _testcapi [clinic start generated code]*/ @@ -96,6 +165,14 @@ _testcapi_float_unpack_impl(PyObject *module, const char *data, } static PyMethodDef test_methods[] = { + {"float_check", float_check, METH_O}, + {"float_checkexact", float_checkexact, METH_O}, + {"float_fromstring", float_fromstring, METH_O}, + {"float_fromdouble", float_fromdouble, METH_O}, + {"float_asdouble", float_asdouble, METH_O}, + {"float_getinfo", float_getinfo, METH_NOARGS}, + {"float_getmax", float_getmax, METH_NOARGS}, + {"float_getmin", float_getmin, METH_NOARGS}, _TESTCAPI_FLOAT_PACK_METHODDEF _TESTCAPI_FLOAT_UNPACK_METHODDEF {NULL}, diff --git a/Modules/_testcapi/gc.c b/Modules/_testcapi/gc.c index 829200ad12cd3c..f4feaaafbdc6cc 100644 --- a/Modules/_testcapi/gc.c +++ b/Modules/_testcapi/gc.c @@ -126,9 +126,7 @@ slot_tp_del(PyObject *self) * never happened. */ { - Py_ssize_t refcnt = Py_REFCNT(self); - _Py_NewReferenceNoTotal(self); - Py_SET_REFCNT(self, refcnt); + _Py_ResurrectReference(self); } assert(!PyType_IS_GC(Py_TYPE(self)) || PyObject_GC_IsTracked(self)); } diff --git a/Modules/_testcapi/getargs.c b/Modules/_testcapi/getargs.c index 10a1c1dd05253d..33e8af7d7bbb39 100644 --- a/Modules/_testcapi/getargs.c +++ b/Modules/_testcapi/getargs.c @@ -13,9 +13,9 @@ parse_tuple_and_keywords(PyObject *self, PyObject *args) const char *sub_format; PyObject *sub_keywords; - double buffers[8][4]; /* double ensures alignment where necessary */ - PyObject *converted[8]; - char *keywords[8 + 1]; /* space for NULL at end */ +#define MAX_PARAMS 8 + double buffers[MAX_PARAMS][4]; /* double ensures alignment where necessary */ + char *keywords[MAX_PARAMS + 1]; /* space for NULL at end */ PyObject *return_value = NULL; @@ -35,11 +35,10 @@ parse_tuple_and_keywords(PyObject *self, PyObject *args) } memset(buffers, 0, sizeof(buffers)); - memset(converted, 0, sizeof(converted)); memset(keywords, 0, sizeof(keywords)); Py_ssize_t size = PySequence_Fast_GET_SIZE(sub_keywords); - if (size > 8) { + if (size > MAX_PARAMS) { PyErr_SetString(PyExc_ValueError, "parse_tuple_and_keywords: too many keywords in sub_keywords"); goto exit; @@ -47,29 +46,60 @@ parse_tuple_and_keywords(PyObject *self, PyObject *args) for (Py_ssize_t i = 0; i < size; i++) { PyObject *o = PySequence_Fast_GET_ITEM(sub_keywords, i); - if (!PyUnicode_FSConverter(o, (void *)(converted + i))) { + if (PyUnicode_Check(o)) { + keywords[i] = (char *)PyUnicode_AsUTF8(o); + if (keywords[i] == NULL) { + goto exit; + } + } + else if (PyBytes_Check(o)) { + keywords[i] = PyBytes_AS_STRING(o); + } + else { PyErr_Format(PyExc_ValueError, "parse_tuple_and_keywords: " - "could not convert keywords[%zd] to narrow string", i); + "keywords must be str or bytes", i); goto exit; } - keywords[i] = PyBytes_AS_STRING(converted[i]); } + assert(MAX_PARAMS == 8); int result = PyArg_ParseTupleAndKeywords(sub_args, sub_kwargs, sub_format, keywords, buffers + 0, buffers + 1, buffers + 2, buffers + 3, buffers + 4, buffers + 5, buffers + 6, buffers + 7); if (result) { - return_value = Py_NewRef(Py_None); + int objects_only = 1; + int count = 0; + for (const char *f = sub_format; *f; f++) { + if (Py_ISALNUM(*f)) { + if (strchr("OSUY", *f) == NULL) { + objects_only = 0; + break; + } + count++; + } + } + if (objects_only) { + return_value = PyTuple_New(count); + if (return_value == NULL) { + goto exit; + } + for (Py_ssize_t i = 0; i < count; i++) { + PyObject *arg = *(PyObject **)(buffers + i); + if (arg == NULL) { + arg = Py_None; + } + PyTuple_SET_ITEM(return_value, i, Py_NewRef(arg)); + } + } + else { + return_value = Py_NewRef(Py_None); + } } exit: - size = sizeof(converted) / sizeof(converted[0]); - for (Py_ssize_t i = 0; i < size; i++) { - Py_XDECREF(converted[i]); - } return return_value; } @@ -112,32 +142,25 @@ getargs_w_star(PyObject *self, PyObject *args) } static PyObject * -test_empty_argparse(PyObject *self, PyObject *Py_UNUSED(ignored)) +getargs_empty(PyObject *self, PyObject *args, PyObject *kwargs) { /* Test that formats can begin with '|'. See issue #4720. */ - PyObject *dict = NULL; - static char *kwlist[] = {NULL}; - PyObject *tuple = PyTuple_New(0); - if (!tuple) { - return NULL; - } + assert(PyTuple_CheckExact(args)); + assert(kwargs == NULL || PyDict_CheckExact(kwargs)); + int result; - if (!(result = PyArg_ParseTuple(tuple, "|:test_empty_argparse"))) { - goto done; - } - dict = PyDict_New(); - if (!dict) { - goto done; - } - result = PyArg_ParseTupleAndKeywords(tuple, dict, "|:test_empty_argparse", - kwlist); - done: - Py_DECREF(tuple); - Py_XDECREF(dict); + if (kwargs != NULL && PyDict_GET_SIZE(kwargs) > 0) { + static char *kwlist[] = {NULL}; + result = PyArg_ParseTupleAndKeywords(args, kwargs, "|:getargs_empty", + kwlist); + } + else { + result = PyArg_ParseTuple(args, "|:getargs_empty"); + } if (!result) { return NULL; } - Py_RETURN_NONE; + return PyLong_FromLong(result); } /* Test tuple argument processing */ @@ -328,75 +351,6 @@ getargs_K(PyObject *self, PyObject *args) return PyLong_FromUnsignedLongLong(value); } -/* This function not only tests the 'k' getargs code, but also the - PyLong_AsUnsignedLongMask() function. */ -static PyObject * -test_k_code(PyObject *self, PyObject *Py_UNUSED(ignored)) -{ - PyObject *tuple, *num; - unsigned long value; - - tuple = PyTuple_New(1); - if (tuple == NULL) { - return NULL; - } - - /* a number larger than ULONG_MAX even on 64-bit platforms */ - num = PyLong_FromString("FFFFFFFFFFFFFFFFFFFFFFFF", NULL, 16); - if (num == NULL) { - return NULL; - } - - value = PyLong_AsUnsignedLongMask(num); - if (value != ULONG_MAX) { - PyErr_SetString(PyExc_AssertionError, - "test_k_code: " - "PyLong_AsUnsignedLongMask() returned wrong value for long 0xFFF...FFF"); - return NULL; - } - - PyTuple_SET_ITEM(tuple, 0, num); - - value = 0; - if (!PyArg_ParseTuple(tuple, "k:test_k_code", &value)) { - return NULL; - } - if (value != ULONG_MAX) { - PyErr_SetString(PyExc_AssertionError, - "test_k_code: k code returned wrong value for long 0xFFF...FFF"); - return NULL; - } - - Py_DECREF(num); - num = PyLong_FromString("-FFFFFFFF000000000000000042", NULL, 16); - if (num == NULL) { - return NULL; - } - - value = PyLong_AsUnsignedLongMask(num); - if (value != (unsigned long)-0x42) { - PyErr_SetString(PyExc_AssertionError, - "test_k_code: " - "PyLong_AsUnsignedLongMask() returned wrong value for long -0xFFF..000042"); - return NULL; - } - - PyTuple_SET_ITEM(tuple, 0, num); - - value = 0; - if (!PyArg_ParseTuple(tuple, "k:test_k_code", &value)) { - return NULL; - } - if (value != (unsigned long)-0x42) { - PyErr_SetString(PyExc_AssertionError, - "test_k_code: k code returned wrong value for long -0xFFF..000042"); - return NULL; - } - - Py_DECREF(tuple); - Py_RETURN_NONE; -} - static PyObject * getargs_f(PyObject *self, PyObject *args) { @@ -589,54 +543,6 @@ getargs_y_hash(PyObject *self, PyObject *args) return PyBytes_FromStringAndSize(str, size); } -static PyObject * -getargs_u(PyObject *self, PyObject *args) -{ - wchar_t *str; - if (!PyArg_ParseTuple(args, "u", &str)) { - return NULL; - } - return PyUnicode_FromWideChar(str, -1); -} - -static PyObject * -getargs_u_hash(PyObject *self, PyObject *args) -{ - wchar_t *str; - Py_ssize_t size; - if (!PyArg_ParseTuple(args, "u#", &str, &size)) { - return NULL; - } - return PyUnicode_FromWideChar(str, size); -} - -static PyObject * -getargs_Z(PyObject *self, PyObject *args) -{ - wchar_t *str; - if (!PyArg_ParseTuple(args, "Z", &str)) { - return NULL; - } - if (str != NULL) { - return PyUnicode_FromWideChar(str, -1); - } - Py_RETURN_NONE; -} - -static PyObject * -getargs_Z_hash(PyObject *self, PyObject *args) -{ - wchar_t *str; - Py_ssize_t size; - if (!PyArg_ParseTuple(args, "Z#", &str, &size)) { - return NULL; - } - if (str != NULL) { - return PyUnicode_FromWideChar(str, size); - } - Py_RETURN_NONE; -} - static PyObject * getargs_es(PyObject *self, PyObject *args) { @@ -725,95 +631,6 @@ getargs_et_hash(PyObject *self, PyObject *args) return result; } -/* Test the L code for PyArg_ParseTuple. This should deliver a long long - for both long and int arguments. The test may leak a little memory if - it fails. -*/ -static PyObject * -test_L_code(PyObject *self, PyObject *Py_UNUSED(ignored)) -{ - PyObject *tuple, *num; - long long value; - - tuple = PyTuple_New(1); - if (tuple == NULL) { - return NULL; - } - - num = PyLong_FromLong(42); - if (num == NULL) { - return NULL; - } - - PyTuple_SET_ITEM(tuple, 0, num); - - value = -1; - if (!PyArg_ParseTuple(tuple, "L:test_L_code", &value)) { - return NULL; - } - if (value != 42) { - PyErr_SetString(PyExc_AssertionError, - "test_L_code: L code returned wrong value for long 42"); - return NULL; - } - - Py_DECREF(num); - num = PyLong_FromLong(42); - if (num == NULL) { - return NULL; - } - - PyTuple_SET_ITEM(tuple, 0, num); - - value = -1; - if (!PyArg_ParseTuple(tuple, "L:test_L_code", &value)) { - return NULL; - } - if (value != 42) { - PyErr_SetString(PyExc_AssertionError, - "test_L_code: L code returned wrong value for int 42"); - return NULL; - } - - Py_DECREF(tuple); - Py_RETURN_NONE; -} - -/* Test the s and z codes for PyArg_ParseTuple. -*/ -static PyObject * -test_s_code(PyObject *self, PyObject *Py_UNUSED(ignored)) -{ - /* Unicode strings should be accepted */ - PyObject *tuple = PyTuple_New(1); - if (tuple == NULL) { - return NULL; - } - - PyObject *obj = PyUnicode_Decode("t\xeate", strlen("t\xeate"), - "latin-1", NULL); - if (obj == NULL) { - return NULL; - } - - PyTuple_SET_ITEM(tuple, 0, obj); - - /* These two blocks used to raise a TypeError: - * "argument must be string without null bytes, not str" - */ - char *value; - if (!PyArg_ParseTuple(tuple, "s:test_s_code1", &value)) { - return NULL; - } - - if (!PyArg_ParseTuple(tuple, "z:test_s_code2", &value)) { - return NULL; - } - - Py_DECREF(tuple); - Py_RETURN_NONE; -} - static PyObject * gh_99240_clear_args(PyObject *self, PyObject *args) { @@ -845,8 +662,6 @@ static PyMethodDef test_methods[] = { {"getargs_S", getargs_S, METH_VARARGS}, {"getargs_U", getargs_U, METH_VARARGS}, {"getargs_Y", getargs_Y, METH_VARARGS}, - {"getargs_Z", getargs_Z, METH_VARARGS}, - {"getargs_Z_hash", getargs_Z_hash, METH_VARARGS}, {"getargs_b", getargs_b, METH_VARARGS}, {"getargs_c", getargs_c, METH_VARARGS}, {"getargs_d", getargs_d, METH_VARARGS}, @@ -868,9 +683,8 @@ static PyMethodDef test_methods[] = { {"getargs_s_hash", getargs_s_hash, METH_VARARGS}, {"getargs_s_star", getargs_s_star, METH_VARARGS}, {"getargs_tuple", getargs_tuple, METH_VARARGS}, - {"getargs_u", getargs_u, METH_VARARGS}, - {"getargs_u_hash", getargs_u_hash, METH_VARARGS}, {"getargs_w_star", getargs_w_star, METH_VARARGS}, + {"getargs_empty", _PyCFunction_CAST(getargs_empty), METH_VARARGS|METH_KEYWORDS}, {"getargs_y", getargs_y, METH_VARARGS}, {"getargs_y_hash", getargs_y_hash, METH_VARARGS}, {"getargs_y_star", getargs_y_star, METH_VARARGS}, @@ -878,10 +692,6 @@ static PyMethodDef test_methods[] = { {"getargs_z_hash", getargs_z_hash, METH_VARARGS}, {"getargs_z_star", getargs_z_star, METH_VARARGS}, {"parse_tuple_and_keywords", parse_tuple_and_keywords, METH_VARARGS}, - {"test_L_code", test_L_code, METH_NOARGS}, - {"test_empty_argparse", test_empty_argparse, METH_NOARGS}, - {"test_k_code", test_k_code, METH_NOARGS}, - {"test_s_code", test_s_code, METH_NOARGS}, {"gh_99240_clear_args", gh_99240_clear_args, METH_VARARGS}, {NULL}, }; diff --git a/Modules/_testcapi/hash.c b/Modules/_testcapi/hash.c new file mode 100644 index 00000000000000..aee76787dcddb3 --- /dev/null +++ b/Modules/_testcapi/hash.c @@ -0,0 +1,72 @@ +#include "parts.h" +#include "util.h" + +static PyObject * +hash_getfuncdef(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args)) +{ + // bind PyHash_GetFuncDef() + PyHash_FuncDef *def = PyHash_GetFuncDef(); + + PyObject *types = PyImport_ImportModule("types"); + if (types == NULL) { + return NULL; + } + + PyObject *result = PyObject_CallMethod(types, "SimpleNamespace", NULL); + Py_DECREF(types); + if (result == NULL) { + return NULL; + } + + // ignore PyHash_FuncDef.hash + + PyObject *value = PyUnicode_FromString(def->name); + int res = PyObject_SetAttrString(result, "name", value); + Py_DECREF(value); + if (res < 0) { + return NULL; + } + + value = PyLong_FromLong(def->hash_bits); + res = PyObject_SetAttrString(result, "hash_bits", value); + Py_DECREF(value); + if (res < 0) { + return NULL; + } + + value = PyLong_FromLong(def->seed_bits); + res = PyObject_SetAttrString(result, "seed_bits", value); + Py_DECREF(value); + if (res < 0) { + return NULL; + } + + return result; +} + + +static PyObject * +hash_pointer(PyObject *Py_UNUSED(module), PyObject *arg) +{ + void *ptr = PyLong_AsVoidPtr(arg); + if (ptr == NULL && PyErr_Occurred()) { + return NULL; + } + + Py_hash_t hash = Py_HashPointer(ptr); + Py_BUILD_ASSERT(sizeof(long long) >= sizeof(hash)); + return PyLong_FromLongLong(hash); +} + + +static PyMethodDef test_methods[] = { + {"hash_getfuncdef", hash_getfuncdef, METH_NOARGS}, + {"hash_pointer", hash_pointer, METH_O}, + {NULL}, +}; + +int +_PyTestCapi_Init_Hash(PyObject *m) +{ + return PyModule_AddFunctions(m, test_methods); +} diff --git a/Modules/_testcapi/heaptype.c b/Modules/_testcapi/heaptype.c index d14a1763184207..4526583a8059d9 100644 --- a/Modules/_testcapi/heaptype.c +++ b/Modules/_testcapi/heaptype.c @@ -805,13 +805,13 @@ static int heapmanaged_traverse(HeapCTypeObject *self, visitproc visit, void *arg) { Py_VISIT(Py_TYPE(self)); - return _PyObject_VisitManagedDict((PyObject *)self, visit, arg); + return PyObject_VisitManagedDict((PyObject *)self, visit, arg); } static int heapmanaged_clear(HeapCTypeObject *self) { - _PyObject_ClearManagedDict((PyObject *)self); + PyObject_ClearManagedDict((PyObject *)self); return 0; } @@ -819,7 +819,7 @@ static void heapmanaged_dealloc(HeapCTypeObject *self) { PyTypeObject *tp = Py_TYPE(self); - _PyObject_ClearManagedDict((PyObject *)self); + PyObject_ClearManagedDict((PyObject *)self); PyObject_GC_UnTrack(self); PyObject_GC_Del(self); Py_DECREF(tp); diff --git a/Modules/_testcapi/heaptype_relative.c b/Modules/_testcapi/heaptype_relative.c index c247ca33b33708..52bda75736b316 100644 --- a/Modules/_testcapi/heaptype_relative.c +++ b/Modules/_testcapi/heaptype_relative.c @@ -1,10 +1,13 @@ +#include "pyconfig.h" // Py_GIL_DISABLED + +#ifndef Py_GIL_DISABLED #define Py_LIMITED_API 0x030c0000 // 3.12 +#endif + #include "parts.h" #include // max_align_t #include // memset -#ifdef LIMITED_API_AVAILABLE - static PyType_Slot empty_slots[] = { {0, NULL}, }; @@ -339,5 +342,3 @@ _PyTestCapi_Init_HeaptypeRelative(PyObject *m) { return 0; } - -#endif // LIMITED_API_AVAILABLE diff --git a/Modules/_testcapi/list.c b/Modules/_testcapi/list.c new file mode 100644 index 00000000000000..10e18699f01bc1 --- /dev/null +++ b/Modules/_testcapi/list.c @@ -0,0 +1,216 @@ +#include "parts.h" +#include "util.h" + +static PyObject * +list_check(PyObject* Py_UNUSED(module), PyObject *obj) +{ + NULLABLE(obj); + return PyLong_FromLong(PyList_Check(obj)); +} + +static PyObject * +list_check_exact(PyObject* Py_UNUSED(module), PyObject *obj) +{ + NULLABLE(obj); + return PyLong_FromLong(PyList_CheckExact(obj)); +} + +static PyObject * +list_new(PyObject* Py_UNUSED(module), PyObject *obj) +{ + return PyList_New(PyLong_AsSsize_t(obj)); +} + +static PyObject * +list_size(PyObject *Py_UNUSED(module), PyObject *obj) +{ + NULLABLE(obj); + RETURN_SIZE(PyList_Size(obj)); +} + +static PyObject * +list_get_size(PyObject *Py_UNUSED(module), PyObject *obj) +{ + NULLABLE(obj); + RETURN_SIZE(PyList_GET_SIZE(obj)); +} + +static PyObject * +list_getitem(PyObject *Py_UNUSED(module), PyObject *args) +{ + PyObject *obj; + Py_ssize_t i; + if (!PyArg_ParseTuple(args, "On", &obj, &i)) { + return NULL; + } + NULLABLE(obj); + return Py_XNewRef(PyList_GetItem(obj, i)); +} + +static PyObject * +list_get_item(PyObject *Py_UNUSED(module), PyObject *args) +{ + PyObject *obj; + Py_ssize_t i; + if (!PyArg_ParseTuple(args, "On", &obj, &i)) { + return NULL; + } + NULLABLE(obj); + return Py_XNewRef(PyList_GET_ITEM(obj, i)); +} + +static PyObject * +list_setitem(PyObject *Py_UNUSED(module), PyObject *args) +{ + PyObject *obj, *value; + Py_ssize_t i; + if (!PyArg_ParseTuple(args, "OnO", &obj, &i, &value)) { + return NULL; + } + NULLABLE(obj); + NULLABLE(value); + RETURN_INT(PyList_SetItem(obj, i, Py_XNewRef(value))); + +} + +static PyObject * +list_set_item(PyObject *Py_UNUSED(module), PyObject *args) +{ + PyObject *obj, *value; + Py_ssize_t i; + if (!PyArg_ParseTuple(args, "OnO", &obj, &i, &value)) { + return NULL; + } + NULLABLE(obj); + NULLABLE(value); + PyList_SET_ITEM(obj, i, Py_XNewRef(value)); + Py_RETURN_NONE; + +} + +static PyObject * +list_insert(PyObject *Py_UNUSED(module), PyObject *args) +{ + PyObject *obj, *value; + Py_ssize_t where; + if (!PyArg_ParseTuple(args, "OnO", &obj, &where, &value)) { + return NULL; + } + NULLABLE(obj); + NULLABLE(value); + RETURN_INT(PyList_Insert(obj, where, Py_XNewRef(value))); + +} + +static PyObject * +list_append(PyObject *Py_UNUSED(module), PyObject *args) +{ + PyObject *obj, *value; + if (!PyArg_ParseTuple(args, "OO", &obj, &value)) { + return NULL; + } + NULLABLE(obj); + NULLABLE(value); + RETURN_INT(PyList_Append(obj, value)); +} + +static PyObject * +list_getslice(PyObject *Py_UNUSED(module), PyObject *args) +{ + PyObject *obj; + Py_ssize_t ilow, ihigh; + if (!PyArg_ParseTuple(args, "Onn", &obj, &ilow, &ihigh)) { + return NULL; + } + NULLABLE(obj); + return PyList_GetSlice(obj, ilow, ihigh); + +} + +static PyObject * +list_setslice(PyObject *Py_UNUSED(module), PyObject *args) +{ + PyObject *obj, *value; + Py_ssize_t ilow, ihigh; + if (!PyArg_ParseTuple(args, "OnnO", &obj, &ilow, &ihigh, &value)) { + return NULL; + } + NULLABLE(obj); + NULLABLE(value); + RETURN_INT(PyList_SetSlice(obj, ilow, ihigh, value)); +} + +static PyObject * +list_sort(PyObject* Py_UNUSED(module), PyObject *obj) +{ + NULLABLE(obj); + RETURN_INT(PyList_Sort(obj)); +} + +static PyObject * +list_reverse(PyObject* Py_UNUSED(module), PyObject *obj) +{ + NULLABLE(obj); + RETURN_INT(PyList_Reverse(obj)); +} + +static PyObject * +list_astuple(PyObject* Py_UNUSED(module), PyObject *obj) +{ + NULLABLE(obj); + return PyList_AsTuple(obj); +} + + +static PyObject * +list_clear(PyObject* Py_UNUSED(module), PyObject *obj) +{ + NULLABLE(obj); + RETURN_INT(PyList_Clear(obj)); +} + + +static PyObject * +list_extend(PyObject* Py_UNUSED(module), PyObject *args) +{ + PyObject *obj, *arg; + if (!PyArg_ParseTuple(args, "OO", &obj, &arg)) { + return NULL; + } + NULLABLE(obj); + NULLABLE(arg); + RETURN_INT(PyList_Extend(obj, arg)); +} + + +static PyMethodDef test_methods[] = { + {"list_check", list_check, METH_O}, + {"list_check_exact", list_check_exact, METH_O}, + {"list_new", list_new, METH_O}, + {"list_size", list_size, METH_O}, + {"list_get_size", list_get_size, METH_O}, + {"list_getitem", list_getitem, METH_VARARGS}, + {"list_get_item", list_get_item, METH_VARARGS}, + {"list_setitem", list_setitem, METH_VARARGS}, + {"list_set_item", list_set_item, METH_VARARGS}, + {"list_insert", list_insert, METH_VARARGS}, + {"list_append", list_append, METH_VARARGS}, + {"list_getslice", list_getslice, METH_VARARGS}, + {"list_setslice", list_setslice, METH_VARARGS}, + {"list_sort", list_sort, METH_O}, + {"list_reverse", list_reverse, METH_O}, + {"list_astuple", list_astuple, METH_O}, + {"list_clear", list_clear, METH_O}, + {"list_extend", list_extend, METH_VARARGS}, + {NULL}, +}; + +int +_PyTestCapi_Init_List(PyObject *m) +{ + if (PyModule_AddFunctions(m, test_methods) < 0) { + return -1; + } + + return 0; +} diff --git a/Modules/_testcapi/long.c b/Modules/_testcapi/long.c index ede43f60d06f95..32ad8d32ab8523 100644 --- a/Modules/_testcapi/long.c +++ b/Modules/_testcapi/long.c @@ -1,4 +1,9 @@ +#ifndef Py_BUILD_CORE_BUILTIN +# define Py_BUILD_CORE_MODULE 1 +#endif + #include "parts.h" +#include "util.h" #include "clinic/long.c.h" /*[clinic input] @@ -37,6 +42,9 @@ raise_test_long_error(const char* msg) return raiseTestError("test_long_api", msg); } +// Test PyLong_FromLong()/PyLong_AsLong() +// and PyLong_FromUnsignedLong()/PyLong_AsUnsignedLong(). + #define TESTNAME test_long_api_inner #define TYPENAME long #define F_S_TO_PY PyLong_FromLong @@ -64,6 +72,9 @@ _testcapi_test_long_api_impl(PyObject *module) #undef F_U_TO_PY #undef F_PY_TO_U +// Test PyLong_FromLongLong()/PyLong_AsLongLong() +// and PyLong_FromUnsignedLongLong()/PyLong_AsUnsignedLongLong(). + static PyObject * raise_test_longlong_error(const char* msg) { @@ -524,57 +535,6 @@ _testcapi_test_long_as_double_impl(PyObject *module) return Py_None; } -/*[clinic input] -_testcapi.test_long_numbits -[clinic start generated code]*/ - -static PyObject * -_testcapi_test_long_numbits_impl(PyObject *module) -/*[clinic end generated code: output=9eaf8458cb15d7f7 input=265c02d48a13059e]*/ -{ - struct triple { - long input; - size_t nbits; - int sign; - } testcases[] = {{0, 0, 0}, - {1L, 1, 1}, - {-1L, 1, -1}, - {2L, 2, 1}, - {-2L, 2, -1}, - {3L, 2, 1}, - {-3L, 2, -1}, - {4L, 3, 1}, - {-4L, 3, -1}, - {0x7fffL, 15, 1}, /* one Python int digit */ - {-0x7fffL, 15, -1}, - {0xffffL, 16, 1}, - {-0xffffL, 16, -1}, - {0xfffffffL, 28, 1}, - {-0xfffffffL, 28, -1}}; - size_t i; - - for (i = 0; i < Py_ARRAY_LENGTH(testcases); ++i) { - size_t nbits; - int sign; - PyObject *plong; - - plong = PyLong_FromLong(testcases[i].input); - if (plong == NULL) - return NULL; - nbits = _PyLong_NumBits(plong); - sign = _PyLong_Sign(plong); - - Py_DECREF(plong); - if (nbits != testcases[i].nbits) - return raiseTestError("test_long_numbits", - "wrong result for _PyLong_NumBits"); - if (sign != testcases[i].sign) - return raiseTestError("test_long_numbits", - "wrong result for _PyLong_Sign"); - } - Py_RETURN_NONE; -} - /*[clinic input] _testcapi.call_long_compact_api arg: object @@ -595,6 +555,227 @@ _testcapi_call_long_compact_api(PyObject *module, PyObject *arg) return Py_BuildValue("in", is_compact, value); } +static PyObject * +pylong_check(PyObject *module, PyObject *obj) +{ + NULLABLE(obj); + return PyLong_FromLong(PyLong_Check(obj)); +} + +static PyObject * +pylong_checkexact(PyObject *module, PyObject *obj) +{ + NULLABLE(obj); + return PyLong_FromLong(PyLong_CheckExact(obj)); +} + +static PyObject * +pylong_fromdouble(PyObject *module, PyObject *arg) +{ + double value; + if (!PyArg_Parse(arg, "d", &value)) { + return NULL; + } + return PyLong_FromDouble(value); +} + +static PyObject * +pylong_fromstring(PyObject *module, PyObject *args) +{ + const char *str; + Py_ssize_t len; + int base; + char *end = UNINITIALIZED_PTR; + if (!PyArg_ParseTuple(args, "z#i", &str, &len, &base)) { + return NULL; + } + + PyObject *result = PyLong_FromString(str, &end, base); + if (result == NULL) { + // XXX 'end' is not always set. + return NULL; + } + return Py_BuildValue("Nn", result, (Py_ssize_t)(end - str)); +} + +static PyObject * +pylong_fromunicodeobject(PyObject *module, PyObject *args) +{ + PyObject *unicode; + int base; + if (!PyArg_ParseTuple(args, "Oi", &unicode, &base)) { + return NULL; + } + + NULLABLE(unicode); + return PyLong_FromUnicodeObject(unicode, base); +} + +static PyObject * +pylong_fromvoidptr(PyObject *module, PyObject *arg) +{ + NULLABLE(arg); + return PyLong_FromVoidPtr((void *)arg); +} + +/*[clinic input] +_testcapi.PyLong_AsInt + arg: object + / +[clinic start generated code]*/ + +static PyObject * +_testcapi_PyLong_AsInt(PyObject *module, PyObject *arg) +/*[clinic end generated code: output=0df9f19de5fa575b input=9561b97105493a67]*/ +{ + NULLABLE(arg); + assert(!PyErr_Occurred()); + int value = PyLong_AsInt(arg); + if (value == -1 && PyErr_Occurred()) { + return NULL; + } + return PyLong_FromLong(value); +} + +static PyObject * +pylong_aslong(PyObject *module, PyObject *arg) +{ + NULLABLE(arg); + long value = PyLong_AsLong(arg); + if (value == -1 && PyErr_Occurred()) { + return NULL; + } + return PyLong_FromLong(value); +} + +static PyObject * +pylong_aslongandoverflow(PyObject *module, PyObject *arg) +{ + NULLABLE(arg); + int overflow = UNINITIALIZED_INT; + long value = PyLong_AsLongAndOverflow(arg, &overflow); + if (value == -1 && PyErr_Occurred()) { + assert(overflow == -1); + return NULL; + } + return Py_BuildValue("li", value, overflow); +} + +static PyObject * +pylong_asunsignedlong(PyObject *module, PyObject *arg) +{ + NULLABLE(arg); + unsigned long value = PyLong_AsUnsignedLong(arg); + if (value == (unsigned long)-1 && PyErr_Occurred()) { + return NULL; + } + return PyLong_FromUnsignedLong(value); +} + +static PyObject * +pylong_asunsignedlongmask(PyObject *module, PyObject *arg) +{ + NULLABLE(arg); + unsigned long value = PyLong_AsUnsignedLongMask(arg); + if (value == (unsigned long)-1 && PyErr_Occurred()) { + return NULL; + } + return PyLong_FromUnsignedLong(value); +} + +static PyObject * +pylong_aslonglong(PyObject *module, PyObject *arg) +{ + NULLABLE(arg); + long long value = PyLong_AsLongLong(arg); + if (value == -1 && PyErr_Occurred()) { + return NULL; + } + return PyLong_FromLongLong(value); +} + +static PyObject * +pylong_aslonglongandoverflow(PyObject *module, PyObject *arg) +{ + NULLABLE(arg); + int overflow = UNINITIALIZED_INT; + long long value = PyLong_AsLongLongAndOverflow(arg, &overflow); + if (value == -1 && PyErr_Occurred()) { + assert(overflow == -1); + return NULL; + } + return Py_BuildValue("Li", value, overflow); +} + +static PyObject * +pylong_asunsignedlonglong(PyObject *module, PyObject *arg) +{ + NULLABLE(arg); + unsigned long long value = PyLong_AsUnsignedLongLong(arg); + if (value == (unsigned long long)-1 && PyErr_Occurred()) { + return NULL; + } + return PyLong_FromUnsignedLongLong(value); +} + +static PyObject * +pylong_asunsignedlonglongmask(PyObject *module, PyObject *arg) +{ + NULLABLE(arg); + unsigned long long value = PyLong_AsUnsignedLongLongMask(arg); + if (value == (unsigned long long)-1 && PyErr_Occurred()) { + return NULL; + } + return PyLong_FromUnsignedLongLong(value); +} + +static PyObject * +pylong_as_ssize_t(PyObject *module, PyObject *arg) +{ + NULLABLE(arg); + Py_ssize_t value = PyLong_AsSsize_t(arg); + if (value == -1 && PyErr_Occurred()) { + return NULL; + } + return PyLong_FromSsize_t(value); +} + +static PyObject * +pylong_as_size_t(PyObject *module, PyObject *arg) +{ + NULLABLE(arg); + size_t value = PyLong_AsSize_t(arg); + if (value == (size_t)-1 && PyErr_Occurred()) { + return NULL; + } + return PyLong_FromSize_t(value); +} + +static PyObject * +pylong_asdouble(PyObject *module, PyObject *arg) +{ + NULLABLE(arg); + double value = PyLong_AsDouble(arg); + if (value == -1.0 && PyErr_Occurred()) { + return NULL; + } + return PyFloat_FromDouble(value); +} + +static PyObject * +pylong_asvoidptr(PyObject *module, PyObject *arg) +{ + NULLABLE(arg); + void *value = PyLong_AsVoidPtr(arg); + if (value == NULL) { + if (PyErr_Occurred()) { + return NULL; + } + Py_RETURN_NONE; + } + return Py_NewRef((PyObject *)value); +} + static PyMethodDef test_methods[] = { _TESTCAPI_TEST_LONG_AND_OVERFLOW_METHODDEF _TESTCAPI_TEST_LONG_API_METHODDEF @@ -602,9 +783,27 @@ static PyMethodDef test_methods[] = { _TESTCAPI_TEST_LONG_AS_SIZE_T_METHODDEF _TESTCAPI_TEST_LONG_AS_UNSIGNED_LONG_LONG_MASK_METHODDEF _TESTCAPI_TEST_LONG_LONG_AND_OVERFLOW_METHODDEF - _TESTCAPI_TEST_LONG_NUMBITS_METHODDEF _TESTCAPI_TEST_LONGLONG_API_METHODDEF _TESTCAPI_CALL_LONG_COMPACT_API_METHODDEF + {"pylong_check", pylong_check, METH_O}, + {"pylong_checkexact", pylong_checkexact, METH_O}, + {"pylong_fromdouble", pylong_fromdouble, METH_O}, + {"pylong_fromstring", pylong_fromstring, METH_VARARGS}, + {"pylong_fromunicodeobject", pylong_fromunicodeobject, METH_VARARGS}, + {"pylong_fromvoidptr", pylong_fromvoidptr, METH_O}, + _TESTCAPI_PYLONG_ASINT_METHODDEF + {"pylong_aslong", pylong_aslong, METH_O}, + {"pylong_aslongandoverflow", pylong_aslongandoverflow, METH_O}, + {"pylong_asunsignedlong", pylong_asunsignedlong, METH_O}, + {"pylong_asunsignedlongmask", pylong_asunsignedlongmask, METH_O}, + {"pylong_aslonglong", pylong_aslonglong, METH_O}, + {"pylong_aslonglongandoverflow", pylong_aslonglongandoverflow, METH_O}, + {"pylong_asunsignedlonglong", pylong_asunsignedlonglong, METH_O}, + {"pylong_asunsignedlonglongmask", pylong_asunsignedlonglongmask, METH_O}, + {"pylong_as_ssize_t", pylong_as_ssize_t, METH_O}, + {"pylong_as_size_t", pylong_as_size_t, METH_O}, + {"pylong_asdouble", pylong_asdouble, METH_O}, + {"pylong_asvoidptr", pylong_asvoidptr, METH_O}, {NULL}, }; diff --git a/Modules/_testcapi/mem.c b/Modules/_testcapi/mem.c index ef9234d7f8955f..ab4ad934644c38 100644 --- a/Modules/_testcapi/mem.c +++ b/Modules/_testcapi/mem.c @@ -613,5 +613,14 @@ _PyTestCapi_Init_Mem(PyObject *mod) return -1; } +#ifdef WITH_MIMALLOC + v = Py_True; +#else + v = Py_False; +#endif + if (PyModule_AddObjectRef(mod, "WITH_MIMALLOC", v) < 0) { + return -1; + } + return 0; } diff --git a/Modules/_testcapi/numbers.c b/Modules/_testcapi/numbers.c new file mode 100644 index 00000000000000..6f7fa3fa7a4186 --- /dev/null +++ b/Modules/_testcapi/numbers.c @@ -0,0 +1,16 @@ +#include "parts.h" +#include "util.h" + +static PyMethodDef test_methods[] = { + {NULL}, +}; + +int +_PyTestCapi_Init_Numbers(PyObject *mod) +{ + if (PyModule_AddFunctions(mod, test_methods) < 0) { + return -1; + } + + return 0; +} diff --git a/Modules/_testcapi/parts.h b/Modules/_testcapi/parts.h index aaec0a61916948..29817edd69b134 100644 --- a/Modules/_testcapi/parts.h +++ b/Modules/_testcapi/parts.h @@ -1,31 +1,38 @@ #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 #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. - +#ifdef PYTESTCAPI_NEED_INTERNAL_API +# ifndef Py_BUILD_CORE_BUILTIN +# define Py_BUILD_CORE_MODULE 1 +# endif #else + // The _testcapi extension tests the public C API: header files in Include/ + // and Include/cpython/ directories. The internal C API must not be tested + // by _testcapi: use _testinternalcapi for that. + // + // _testcapi C files can built with the Py_BUILD_CORE_BUILTIN macro defined + // if one of the Modules/Setup files asks to build _testcapi as "static" + // (gh-109723). + // + // The Visual Studio projects builds _testcapi with Py_BUILD_CORE_MODULE. +# undef Py_BUILD_CORE_MODULE +# undef Py_BUILD_CORE_BUILTIN +#endif #include "Python.h" +#if defined(Py_BUILD_CORE) && !defined(PYTESTCAPI_NEED_INTERNAL_API) +# error "_testcapi must test the public Python C API, not the internal C API" +#endif + int _PyTestCapi_Init_Vectorcall(PyObject *module); int _PyTestCapi_Init_Heaptype(PyObject *module); +int _PyTestCapi_Init_Abstract(PyObject *module); +int _PyTestCapi_Init_ByteArray(PyObject *module); +int _PyTestCapi_Init_Bytes(PyObject *module); int _PyTestCapi_Init_Unicode(PyObject *module); int _PyTestCapi_Init_GetArgs(PyObject *module); int _PyTestCapi_Init_DateTime(PyObject *module); @@ -34,18 +41,26 @@ int _PyTestCapi_Init_Mem(PyObject *module); int _PyTestCapi_Init_Watchers(PyObject *module); int _PyTestCapi_Init_Long(PyObject *module); int _PyTestCapi_Init_Float(PyObject *module); +int _PyTestCapi_Init_Complex(PyObject *module); +int _PyTestCapi_Init_Numbers(PyObject *module); +int _PyTestCapi_Init_Dict(PyObject *module); +int _PyTestCapi_Init_Set(PyObject *module); +int _PyTestCapi_Init_List(PyObject *module); +int _PyTestCapi_Init_Tuple(PyObject *module); int _PyTestCapi_Init_Structmember(PyObject *module); int _PyTestCapi_Init_Exceptions(PyObject *module); int _PyTestCapi_Init_Code(PyObject *module); int _PyTestCapi_Init_Buffer(PyObject *module); +int _PyTestCapi_Init_PyAtomic(PyObject *module); int _PyTestCapi_Init_PyOS(PyObject *module); +int _PyTestCapi_Init_File(PyObject *module); +int _PyTestCapi_Init_Codec(PyObject *module); int _PyTestCapi_Init_Immortal(PyObject *module); -int _PyTestCapi_Init_GC(PyObject *mod); +int _PyTestCapi_Init_GC(PyObject *module); +int _PyTestCapi_Init_Sys(PyObject *module); +int _PyTestCapi_Init_Hash(PyObject *module); -#ifdef LIMITED_API_AVAILABLE int _PyTestCapi_Init_VectorcallLimited(PyObject *module); int _PyTestCapi_Init_HeaptypeRelative(PyObject *module); -#endif // LIMITED_API_AVAILABLE -#endif #endif // Py_TESTCAPI_PARTS_H diff --git a/Modules/_testcapi/pyatomic.c b/Modules/_testcapi/pyatomic.c new file mode 100644 index 00000000000000..4f72844535ebd6 --- /dev/null +++ b/Modules/_testcapi/pyatomic.c @@ -0,0 +1,191 @@ +/* + * C Extension module to smoke test pyatomic.h API. + * + * This only tests basic functionality, not any synchronizing ordering. + */ + +#include "parts.h" + +// We define atomic bitwise operations on these types +#define FOR_BITWISE_TYPES(V) \ + V(uint8, uint8_t) \ + V(uint16, uint16_t) \ + V(uint32, uint32_t) \ + V(uint64, uint64_t) \ + V(uintptr, uintptr_t) + +// We define atomic addition on these types +#define FOR_ARITHMETIC_TYPES(V) \ + FOR_BITWISE_TYPES(V) \ + V(int, int) \ + V(uint, unsigned int) \ + V(int8, int8_t) \ + V(int16, int16_t) \ + V(int32, int32_t) \ + V(int64, int64_t) \ + V(intptr, intptr_t) \ + V(ssize, Py_ssize_t) + +// We define atomic load, store, exchange, and compare_exchange on these types +#define FOR_ALL_TYPES(V) \ + FOR_ARITHMETIC_TYPES(V) \ + V(ptr, void*) + +#define IMPL_TEST_ADD(suffix, dtype) \ +static PyObject * \ +test_atomic_add_##suffix(PyObject *self, PyObject *obj) { \ + dtype x = 0; \ + assert(_Py_atomic_add_##suffix(&x, 1) == 0); \ + assert(x == 1); \ + assert(_Py_atomic_add_##suffix(&x, 2) == 1); \ + assert(x == 3); \ + assert(_Py_atomic_add_##suffix(&x, -2) == 3); \ + assert(x == 1); \ + assert(_Py_atomic_add_##suffix(&x, -1) == 1); \ + assert(x == 0); \ + assert(_Py_atomic_add_##suffix(&x, -1) == 0); \ + assert(x == (dtype)-1); \ + assert(_Py_atomic_add_##suffix(&x, -2) == (dtype)-1); \ + assert(x == (dtype)-3); \ + assert(_Py_atomic_add_##suffix(&x, 2) == (dtype)-3); \ + assert(x == (dtype)-1); \ + Py_RETURN_NONE; \ +} +FOR_ARITHMETIC_TYPES(IMPL_TEST_ADD) + +#define IMPL_TEST_COMPARE_EXCHANGE(suffix, dtype) \ +static PyObject * \ +test_atomic_compare_exchange_##suffix(PyObject *self, PyObject *obj) { \ + dtype x = (dtype)0; \ + dtype y = (dtype)1; \ + dtype z = (dtype)2; \ + assert(_Py_atomic_compare_exchange_##suffix(&x, &y, z) == 0); \ + assert(x == 0); \ + assert(y == 0); \ + assert(_Py_atomic_compare_exchange_##suffix(&x, &y, z) == 1); \ + assert(x == z); \ + assert(y == 0); \ + assert(_Py_atomic_compare_exchange_##suffix(&x, &y, z) == 0); \ + assert(x == z); \ + assert(y == z); \ + Py_RETURN_NONE; \ +} +FOR_ALL_TYPES(IMPL_TEST_COMPARE_EXCHANGE) + +#define IMPL_TEST_EXCHANGE(suffix, dtype) \ +static PyObject * \ +test_atomic_exchange_##suffix(PyObject *self, PyObject *obj) { \ + dtype x = (dtype)0; \ + dtype y = (dtype)1; \ + dtype z = (dtype)2; \ + assert(_Py_atomic_exchange_##suffix(&x, y) == (dtype)0); \ + assert(x == (dtype)1); \ + assert(_Py_atomic_exchange_##suffix(&x, z) == (dtype)1); \ + assert(x == (dtype)2); \ + assert(_Py_atomic_exchange_##suffix(&x, y) == (dtype)2); \ + assert(x == (dtype)1); \ + Py_RETURN_NONE; \ +} +FOR_ALL_TYPES(IMPL_TEST_EXCHANGE) + +#define IMPL_TEST_LOAD_STORE(suffix, dtype) \ +static PyObject * \ +test_atomic_load_store_##suffix(PyObject *self, PyObject *obj) { \ + dtype x = (dtype)0; \ + dtype y = (dtype)1; \ + dtype z = (dtype)2; \ + assert(_Py_atomic_load_##suffix(&x) == (dtype)0); \ + assert(x == (dtype)0); \ + _Py_atomic_store_##suffix(&x, y); \ + assert(_Py_atomic_load_##suffix(&x) == (dtype)1); \ + assert(x == (dtype)1); \ + _Py_atomic_store_##suffix##_relaxed(&x, z); \ + assert(_Py_atomic_load_##suffix##_relaxed(&x) == (dtype)2); \ + assert(x == (dtype)2); \ + Py_RETURN_NONE; \ +} +FOR_ALL_TYPES(IMPL_TEST_LOAD_STORE) + +#define IMPL_TEST_AND_OR(suffix, dtype) \ +static PyObject * \ +test_atomic_and_or_##suffix(PyObject *self, PyObject *obj) { \ + dtype x = (dtype)0; \ + dtype y = (dtype)1; \ + dtype z = (dtype)3; \ + assert(_Py_atomic_or_##suffix(&x, z) == (dtype)0); \ + assert(x == (dtype)3); \ + assert(_Py_atomic_and_##suffix(&x, y) == (dtype)3); \ + assert(x == (dtype)1); \ + Py_RETURN_NONE; \ +} +FOR_BITWISE_TYPES(IMPL_TEST_AND_OR) + +static PyObject * +test_atomic_fences(PyObject *self, PyObject *obj) { + // Just make sure that the fences compile. We are not + // testing any synchronizing ordering. + _Py_atomic_fence_seq_cst(); + _Py_atomic_fence_release(); + Py_RETURN_NONE; +} + +static PyObject * +test_atomic_release_acquire(PyObject *self, PyObject *obj) { + void *x = NULL; + void *y = &y; + assert(_Py_atomic_load_ptr_acquire(&x) == NULL); + _Py_atomic_store_ptr_release(&x, y); + assert(x == y); + assert(_Py_atomic_load_ptr_acquire(&x) == y); + Py_RETURN_NONE; +} + +static PyObject * +test_atomic_load_store_int_release_acquire(PyObject *self, PyObject *obj) { \ + int x = 0; + int y = 1; + int z = 2; + assert(_Py_atomic_load_int_acquire(&x) == 0); + _Py_atomic_store_int_release(&x, y); + assert(x == y); + assert(_Py_atomic_load_int_acquire(&x) == y); + _Py_atomic_store_int_release(&x, z); + assert(x == z); + assert(_Py_atomic_load_int_acquire(&x) == z); + Py_RETURN_NONE; +} + +// NOTE: all tests should start with "test_atomic_" to be included +// in test_pyatomic.py + +#define BIND_TEST_ADD(suffix, dtype) \ + {"test_atomic_add_" #suffix, test_atomic_add_##suffix, METH_NOARGS}, +#define BIND_TEST_COMPARE_EXCHANGE(suffix, dtype) \ + {"test_atomic_compare_exchange_" #suffix, test_atomic_compare_exchange_##suffix, METH_NOARGS}, +#define BIND_TEST_EXCHANGE(suffix, dtype) \ + {"test_atomic_exchange_" #suffix, test_atomic_exchange_##suffix, METH_NOARGS}, +#define BIND_TEST_LOAD_STORE(suffix, dtype) \ + {"test_atomic_load_store_" #suffix, test_atomic_load_store_##suffix, METH_NOARGS}, +#define BIND_TEST_AND_OR(suffix, dtype) \ + {"test_atomic_and_or_" #suffix, test_atomic_and_or_##suffix, METH_NOARGS}, + +static PyMethodDef test_methods[] = { + FOR_ARITHMETIC_TYPES(BIND_TEST_ADD) + FOR_ALL_TYPES(BIND_TEST_COMPARE_EXCHANGE) + FOR_ALL_TYPES(BIND_TEST_EXCHANGE) + FOR_ALL_TYPES(BIND_TEST_LOAD_STORE) + FOR_BITWISE_TYPES(BIND_TEST_AND_OR) + {"test_atomic_fences", test_atomic_fences, METH_NOARGS}, + {"test_atomic_release_acquire", test_atomic_release_acquire, METH_NOARGS}, + {"test_atomic_load_store_int_release_acquire", test_atomic_load_store_int_release_acquire, METH_NOARGS}, + {NULL, NULL} /* sentinel */ +}; + +int +_PyTestCapi_Init_PyAtomic(PyObject *mod) +{ + if (PyModule_AddFunctions(mod, test_methods) < 0) { + return -1; + } + return 0; +} diff --git a/Modules/_testcapi/set.c b/Modules/_testcapi/set.c new file mode 100644 index 00000000000000..2fbd0aeffcd9f9 --- /dev/null +++ b/Modules/_testcapi/set.c @@ -0,0 +1,197 @@ +#include "parts.h" +#include "util.h" + +static PyObject * +set_check(PyObject *self, PyObject *obj) +{ + NULLABLE(obj); + RETURN_INT(PySet_Check(obj)); +} + +static PyObject * +set_checkexact(PyObject *self, PyObject *obj) +{ + NULLABLE(obj); + RETURN_INT(PySet_CheckExact(obj)); +} + +static PyObject * +frozenset_check(PyObject *self, PyObject *obj) +{ + NULLABLE(obj); + RETURN_INT(PyFrozenSet_Check(obj)); +} + +static PyObject * +frozenset_checkexact(PyObject *self, PyObject *obj) +{ + NULLABLE(obj); + RETURN_INT(PyFrozenSet_CheckExact(obj)); +} + +static PyObject * +anyset_check(PyObject *self, PyObject *obj) +{ + NULLABLE(obj); + RETURN_INT(PyAnySet_Check(obj)); +} + +static PyObject * +anyset_checkexact(PyObject *self, PyObject *obj) +{ + NULLABLE(obj); + RETURN_INT(PyAnySet_CheckExact(obj)); +} + +static PyObject * +set_new(PyObject *self, PyObject *args) +{ + PyObject *iterable = NULL; + if (!PyArg_ParseTuple(args, "|O", &iterable)) { + return NULL; + } + return PySet_New(iterable); +} + +static PyObject * +frozenset_new(PyObject *self, PyObject *args) +{ + PyObject *iterable = NULL; + if (!PyArg_ParseTuple(args, "|O", &iterable)) { + return NULL; + } + return PyFrozenSet_New(iterable); +} + +static PyObject * +set_size(PyObject *self, PyObject *obj) +{ + NULLABLE(obj); + RETURN_SIZE(PySet_Size(obj)); +} + +static PyObject * +set_get_size(PyObject *self, PyObject *obj) +{ + NULLABLE(obj); + RETURN_SIZE(PySet_GET_SIZE(obj)); +} + +static PyObject * +set_contains(PyObject *self, PyObject *args) +{ + PyObject *obj, *item; + if (!PyArg_ParseTuple(args, "OO", &obj, &item)) { + return NULL; + } + NULLABLE(obj); + NULLABLE(item); + RETURN_INT(PySet_Contains(obj, item)); +} + +static PyObject * +set_add(PyObject *self, PyObject *args) +{ + PyObject *obj, *item; + if (!PyArg_ParseTuple(args, "OO", &obj, &item)) { + return NULL; + } + NULLABLE(obj); + NULLABLE(item); + RETURN_INT(PySet_Add(obj, item)); +} + +static PyObject * +set_discard(PyObject *self, PyObject *args) +{ + PyObject *obj, *item; + if (!PyArg_ParseTuple(args, "OO", &obj, &item)) { + return NULL; + } + NULLABLE(obj); + NULLABLE(item); + RETURN_INT(PySet_Discard(obj, item)); +} + +static PyObject * +set_pop(PyObject *self, PyObject *obj) +{ + NULLABLE(obj); + return PySet_Pop(obj); +} + +static PyObject * +set_clear(PyObject *self, PyObject *obj) +{ + NULLABLE(obj); + RETURN_INT(PySet_Clear(obj)); +} + +static PyObject * +test_frozenset_add_in_capi(PyObject *self, PyObject *Py_UNUSED(obj)) +{ + // Test that `frozenset` can be used with `PySet_Add`, + // when frozenset is just created in CAPI. + PyObject *fs = PyFrozenSet_New(NULL); + if (fs == NULL) { + return NULL; + } + PyObject *num = PyLong_FromLong(1); + if (num == NULL) { + goto error; + } + if (PySet_Add(fs, num) < 0) { + goto error; + } + int contains = PySet_Contains(fs, num); + if (contains < 0) { + goto error; + } + else if (contains == 0) { + goto unexpected; + } + Py_DECREF(fs); + Py_DECREF(num); + Py_RETURN_NONE; + +unexpected: + PyErr_SetString(PyExc_ValueError, "set does not contain expected value"); +error: + Py_DECREF(fs); + Py_XDECREF(num); + return NULL; +} + +static PyMethodDef test_methods[] = { + {"set_check", set_check, METH_O}, + {"set_checkexact", set_checkexact, METH_O}, + {"frozenset_check", frozenset_check, METH_O}, + {"frozenset_checkexact", frozenset_checkexact, METH_O}, + {"anyset_check", anyset_check, METH_O}, + {"anyset_checkexact", anyset_checkexact, METH_O}, + + {"set_new", set_new, METH_VARARGS}, + {"frozenset_new", frozenset_new, METH_VARARGS}, + + {"set_size", set_size, METH_O}, + {"set_get_size", set_get_size, METH_O}, + {"set_contains", set_contains, METH_VARARGS}, + {"set_add", set_add, METH_VARARGS}, + {"set_discard", set_discard, METH_VARARGS}, + {"set_pop", set_pop, METH_O}, + {"set_clear", set_clear, METH_O}, + + {"test_frozenset_add_in_capi", test_frozenset_add_in_capi, METH_NOARGS}, + + {NULL}, +}; + +int +_PyTestCapi_Init_Set(PyObject *m) +{ + if (PyModule_AddFunctions(m, test_methods) < 0) { + return -1; + } + + return 0; +} diff --git a/Modules/_testcapi/sys.c b/Modules/_testcapi/sys.c new file mode 100644 index 00000000000000..aa40e3cd5b9b29 --- /dev/null +++ b/Modules/_testcapi/sys.c @@ -0,0 +1,56 @@ +#include "parts.h" +#include "util.h" + + +static PyObject * +sys_getobject(PyObject *Py_UNUSED(module), PyObject *arg) +{ + const char *name; + Py_ssize_t size; + if (!PyArg_Parse(arg, "z#", &name, &size)) { + return NULL; + } + PyObject *result = PySys_GetObject(name); + if (result == NULL) { + result = PyExc_AttributeError; + } + return Py_NewRef(result); +} + +static PyObject * +sys_setobject(PyObject *Py_UNUSED(module), PyObject *args) +{ + const char *name; + Py_ssize_t size; + PyObject *value; + if (!PyArg_ParseTuple(args, "z#O", &name, &size, &value)) { + return NULL; + } + NULLABLE(value); + RETURN_INT(PySys_SetObject(name, value)); +} + +static PyObject * +sys_getxoptions(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(ignored)) +{ + PyObject *result = PySys_GetXOptions(); + return Py_XNewRef(result); +} + + +static PyMethodDef test_methods[] = { + {"sys_getobject", sys_getobject, METH_O}, + {"sys_setobject", sys_setobject, METH_VARARGS}, + {"sys_getxoptions", sys_getxoptions, METH_NOARGS}, + {NULL}, +}; + +int +_PyTestCapi_Init_Sys(PyObject *m) +{ + if (PyModule_AddFunctions(m, test_methods) < 0) { + return -1; + } + + return 0; +} diff --git a/Modules/_testcapi/tuple.c b/Modules/_testcapi/tuple.c new file mode 100644 index 00000000000000..95dde8c0edadbe --- /dev/null +++ b/Modules/_testcapi/tuple.c @@ -0,0 +1,17 @@ +#include "parts.h" +#include "util.h" + + +static PyMethodDef test_methods[] = { + {NULL}, +}; + +int +_PyTestCapi_Init_Tuple(PyObject *m) +{ + if (PyModule_AddFunctions(m, test_methods) < 0){ + return -1; + } + + return 0; +} diff --git a/Modules/_testcapi/unicode.c b/Modules/_testcapi/unicode.c index b4c6c4b5e3ce1a..a10183dddeca98 100644 --- a/Modules/_testcapi/unicode.c +++ b/Modules/_testcapi/unicode.c @@ -1,6 +1,7 @@ #include // ptrdiff_t #include "parts.h" +#include "util.h" static struct PyModuleDef *_testcapimodule = NULL; // set at initialization @@ -101,7 +102,6 @@ test_widechar(PyObject *self, PyObject *Py_UNUSED(ignored)) Py_RETURN_NONE; } -#define NULLABLE(x) do { if (x == Py_None) x = NULL; } while (0); static PyObject * unicode_copy(PyObject *unicode) @@ -347,13 +347,8 @@ unicode_substring(PyObject *self, PyObject *args) static PyObject * unicode_getlength(PyObject *self, PyObject *arg) { - Py_ssize_t result; - NULLABLE(arg); - result = PyUnicode_GetLength(arg); - if (result == -1) - return NULL; - return PyLong_FromSsize_t(result); + RETURN_SIZE(PyUnicode_GetLength(arg)); } /* Test PyUnicode_ReadChar() */ @@ -482,16 +477,12 @@ static PyObject * unicode_aswidechar_null(PyObject *self, PyObject *args) { PyObject *unicode; - Py_ssize_t buflen, size; + Py_ssize_t buflen; if (!PyArg_ParseTuple(args, "On", &unicode, &buflen)) return NULL; NULLABLE(unicode); - size = PyUnicode_AsWideChar(unicode, NULL, buflen); - if (size == -1) { - return NULL; - } - return PyLong_FromSsize_t(size); + RETURN_SIZE(PyUnicode_AsWideChar(unicode, NULL, buflen)); } /* Test PyUnicode_AsWideCharString() */ @@ -499,7 +490,7 @@ static PyObject * unicode_aswidecharstring(PyObject *self, PyObject *args) { PyObject *unicode, *result; - Py_ssize_t size = 100; + Py_ssize_t size = UNINITIALIZED_SIZE; wchar_t *buffer; if (!PyArg_ParseTuple(args, "O", &unicode)) @@ -507,8 +498,10 @@ unicode_aswidecharstring(PyObject *self, PyObject *args) NULLABLE(unicode); buffer = PyUnicode_AsWideCharString(unicode, &size); - if (buffer == NULL) + if (buffer == NULL) { + assert(size == UNINITIALIZED_SIZE); return NULL; + } result = PyUnicode_FromWideChar(buffer, size + 1); PyMem_Free(buffer); @@ -633,15 +626,17 @@ unicode_asutf8andsize(PyObject *self, PyObject *args) PyObject *unicode; Py_ssize_t buflen; const char *s; - Py_ssize_t size = -100; + Py_ssize_t size = UNINITIALIZED_SIZE; if (!PyArg_ParseTuple(args, "On", &unicode, &buflen)) return NULL; NULLABLE(unicode); s = PyUnicode_AsUTF8AndSize(unicode, &size); - if (s == NULL) + if (s == NULL) { + assert(size == -1); return NULL; + } return Py_BuildValue("(y#n)", s, buflen, size); } @@ -735,7 +730,7 @@ unicode_decodeutf7stateful(PyObject *self, PyObject *args) const char *data; Py_ssize_t size; const char *errors = NULL; - Py_ssize_t consumed; + Py_ssize_t consumed = UNINITIALIZED_SIZE; PyObject *result; if (!PyArg_ParseTuple(args, "y#|z", &data, &size, &errors)) @@ -743,6 +738,7 @@ unicode_decodeutf7stateful(PyObject *self, PyObject *args) result = PyUnicode_DecodeUTF7Stateful(data, size, errors, &consumed); if (!result) { + assert(consumed == UNINITIALIZED_SIZE); return NULL; } return Py_BuildValue("(Nn)", result, consumed); @@ -769,7 +765,7 @@ unicode_decodeutf8stateful(PyObject *self, PyObject *args) const char *data; Py_ssize_t size; const char *errors = NULL; - Py_ssize_t consumed = 123456789; + Py_ssize_t consumed = UNINITIALIZED_SIZE; PyObject *result; if (!PyArg_ParseTuple(args, "y#|z", &data, &size, &errors)) @@ -777,6 +773,7 @@ unicode_decodeutf8stateful(PyObject *self, PyObject *args) result = PyUnicode_DecodeUTF8Stateful(data, size, errors, &consumed); if (!result) { + assert(consumed == UNINITIALIZED_SIZE); return NULL; } return Py_BuildValue("(Nn)", result, consumed); @@ -797,7 +794,7 @@ unicode_decodeutf32(PyObject *self, PyObject *args) const char *data; Py_ssize_t size; const char *errors = NULL; - int byteorder; + int byteorder = UNINITIALIZED_INT; PyObject *result; if (!PyArg_ParseTuple(args, "iy#|z", &byteorder, &data, &size, &errors)) @@ -817,8 +814,8 @@ unicode_decodeutf32stateful(PyObject *self, PyObject *args) const char *data; Py_ssize_t size; const char *errors = NULL; - int byteorder; - Py_ssize_t consumed; + int byteorder = UNINITIALIZED_INT; + Py_ssize_t consumed = UNINITIALIZED_SIZE; PyObject *result; if (!PyArg_ParseTuple(args, "iy#|z", &byteorder, &data, &size, &errors)) @@ -826,6 +823,7 @@ unicode_decodeutf32stateful(PyObject *self, PyObject *args) result = PyUnicode_DecodeUTF32Stateful(data, size, errors, &byteorder, &consumed); if (!result) { + assert(consumed == UNINITIALIZED_SIZE); return NULL; } return Py_BuildValue("(iNn)", byteorder, result, consumed); @@ -846,7 +844,7 @@ unicode_decodeutf16(PyObject *self, PyObject *args) const char *data; Py_ssize_t size; const char *errors = NULL; - int byteorder = 0; + int byteorder = UNINITIALIZED_INT; PyObject *result; if (!PyArg_ParseTuple(args, "iy#|z", &byteorder, &data, &size, &errors)) @@ -866,8 +864,8 @@ unicode_decodeutf16stateful(PyObject *self, PyObject *args) const char *data; Py_ssize_t size; const char *errors = NULL; - int byteorder; - Py_ssize_t consumed; + int byteorder = UNINITIALIZED_INT; + Py_ssize_t consumed = UNINITIALIZED_SIZE; PyObject *result; if (!PyArg_ParseTuple(args, "iy#|z", &byteorder, &data, &size, &errors)) @@ -875,6 +873,7 @@ unicode_decodeutf16stateful(PyObject *self, PyObject *args) result = PyUnicode_DecodeUTF16Stateful(data, size, errors, &byteorder, &consumed); if (!result) { + assert(consumed == UNINITIALIZED_SIZE); return NULL; } return Py_BuildValue("(iNn)", byteorder, result, consumed); @@ -1028,7 +1027,7 @@ unicode_decodembcsstateful(PyObject *self, PyObject *args) const char *data; Py_ssize_t size; const char *errors = NULL; - Py_ssize_t consumed; + Py_ssize_t consumed = UNINITIALIZED_SIZE; PyObject *result; if (!PyArg_ParseTuple(args, "y#|z", &data, &size, &errors)) @@ -1036,6 +1035,7 @@ unicode_decodembcsstateful(PyObject *self, PyObject *args) result = PyUnicode_DecodeMBCSStateful(data, size, errors, &consumed); if (!result) { + assert(consumed == UNINITIALIZED_SIZE); return NULL; } return Py_BuildValue("(Nn)", result, consumed); @@ -1049,7 +1049,7 @@ unicode_decodecodepagestateful(PyObject *self, PyObject *args) const char *data; Py_ssize_t size; const char *errors = NULL; - Py_ssize_t consumed; + Py_ssize_t consumed = UNINITIALIZED_SIZE; PyObject *result; if (!PyArg_ParseTuple(args, "iy#|z", &code_page, &data, &size, &errors)) @@ -1057,6 +1057,7 @@ unicode_decodecodepagestateful(PyObject *self, PyObject *args) result = PyUnicode_DecodeCodePageStateful(code_page, data, size, errors, &consumed); if (!result) { + assert(consumed == UNINITIALIZED_SIZE); return NULL; } return Py_BuildValue("(Nn)", result, consumed); @@ -1293,17 +1294,13 @@ unicode_count(PyObject *self, PyObject *args) PyObject *substr; Py_ssize_t start; Py_ssize_t end; - Py_ssize_t result; if (!PyArg_ParseTuple(args, "OOnn", &str, &substr, &start, &end)) return NULL; NULLABLE(str); NULLABLE(substr); - result = PyUnicode_Count(str, substr, start, end); - if (result == -1) - return NULL; - return PyLong_FromSsize_t(result); + RETURN_SIZE(PyUnicode_Count(str, substr, start, end)); } /* Test PyUnicode_Find() */ @@ -1323,8 +1320,11 @@ unicode_find(PyObject *self, PyObject *args) NULLABLE(str); NULLABLE(substr); result = PyUnicode_Find(str, substr, start, end, direction); - if (result == -2) + if (result == -2) { + assert(PyErr_Occurred()); return NULL; + } + assert(!PyErr_Occurred()); return PyLong_FromSsize_t(result); } @@ -1337,17 +1337,13 @@ unicode_tailmatch(PyObject *self, PyObject *args) Py_ssize_t start; Py_ssize_t end; int direction; - Py_ssize_t result; if (!PyArg_ParseTuple(args, "OOnni", &str, &substr, &start, &end, &direction)) return NULL; NULLABLE(str); NULLABLE(substr); - result = PyUnicode_Tailmatch(str, substr, start, end, direction); - if (result == -1) - return NULL; - return PyLong_FromSsize_t(result); + RETURN_SIZE(PyUnicode_Tailmatch(str, substr, start, end, direction)); } /* Test PyUnicode_FindChar() */ @@ -1366,10 +1362,12 @@ unicode_findchar(PyObject *self, PyObject *args) } NULLABLE(str); result = PyUnicode_FindChar(str, (Py_UCS4)ch, start, end, direction); - if (result == -2) + if (result == -2) { + assert(PyErr_Occurred()); return NULL; - else - return PyLong_FromSsize_t(result); + } + assert(!PyErr_Occurred()); + return PyLong_FromSsize_t(result); } /* Test PyUnicode_Replace() */ @@ -1407,6 +1405,7 @@ unicode_compare(PyObject *self, PyObject *args) if (result == -1 && PyErr_Occurred()) { return NULL; } + assert(!PyErr_Occurred()); return PyLong_FromLong(result); } @@ -1430,6 +1429,48 @@ unicode_comparewithasciistring(PyObject *self, PyObject *args) return PyLong_FromLong(result); } +/* Test PyUnicode_EqualToUTF8() */ +static PyObject * +unicode_equaltoutf8(PyObject *self, PyObject *args) +{ + PyObject *left; + const char *right = NULL; + Py_ssize_t right_len; + int result; + + if (!PyArg_ParseTuple(args, "Oz#", &left, &right, &right_len)) { + return NULL; + } + + NULLABLE(left); + result = PyUnicode_EqualToUTF8(left, right); + assert(!PyErr_Occurred()); + return PyLong_FromLong(result); +} + +/* Test PyUnicode_EqualToUTF8AndSize() */ +static PyObject * +unicode_equaltoutf8andsize(PyObject *self, PyObject *args) +{ + PyObject *left; + const char *right = NULL; + Py_ssize_t right_len; + Py_ssize_t size = -100; + int result; + + if (!PyArg_ParseTuple(args, "Oz#|n", &left, &right, &right_len, &size)) { + return NULL; + } + + NULLABLE(left); + if (size == -100) { + size = right_len; + } + result = PyUnicode_EqualToUTF8AndSize(left, right, size); + assert(!PyErr_Occurred()); + return PyLong_FromLong(result); +} + /* Test PyUnicode_RichCompare() */ static PyObject * unicode_richcompare(PyObject *self, PyObject *args) @@ -1467,32 +1508,21 @@ unicode_contains(PyObject *self, PyObject *args) { PyObject *container; PyObject *element; - int result; if (!PyArg_ParseTuple(args, "OO", &container, &element)) return NULL; NULLABLE(container); NULLABLE(element); - result = PyUnicode_Contains(container, element); - if (result == -1 && PyErr_Occurred()) { - return NULL; - } - return PyLong_FromLong(result); + RETURN_INT(PyUnicode_Contains(container, element)); } /* Test PyUnicode_IsIdentifier() */ static PyObject * unicode_isidentifier(PyObject *self, PyObject *arg) { - int result; - NULLABLE(arg); - result = PyUnicode_IsIdentifier(arg); - if (result == -1 && PyErr_Occurred()) { - return NULL; - } - return PyLong_FromLong(result); + RETURN_INT(PyUnicode_IsIdentifier(arg)); } /* Test PyUnicode_CopyCharacters() */ @@ -2056,6 +2086,8 @@ static PyMethodDef TestMethods[] = { {"unicode_replace", unicode_replace, METH_VARARGS}, {"unicode_compare", unicode_compare, METH_VARARGS}, {"unicode_comparewithasciistring",unicode_comparewithasciistring,METH_VARARGS}, + {"unicode_equaltoutf8", unicode_equaltoutf8, METH_VARARGS}, + {"unicode_equaltoutf8andsize",unicode_equaltoutf8andsize, METH_VARARGS}, {"unicode_richcompare", unicode_richcompare, METH_VARARGS}, {"unicode_format", unicode_format, METH_VARARGS}, {"unicode_contains", unicode_contains, METH_VARARGS}, diff --git a/Modules/_testcapi/util.h b/Modules/_testcapi/util.h new file mode 100644 index 00000000000000..f26d7656a10138 --- /dev/null +++ b/Modules/_testcapi/util.h @@ -0,0 +1,33 @@ +#define NULLABLE(x) do { \ + if (x == Py_None) { \ + x = NULL; \ + } \ + } while (0); + +#define RETURN_INT(value) do { \ + int _ret = (value); \ + if (_ret == -1) { \ + assert(PyErr_Occurred()); \ + return NULL; \ + } \ + assert(!PyErr_Occurred()); \ + return PyLong_FromLong(_ret); \ + } while (0) + +#define RETURN_SIZE(value) do { \ + Py_ssize_t _ret = (value); \ + if (_ret == -1) { \ + assert(PyErr_Occurred()); \ + return NULL; \ + } \ + assert(!PyErr_Occurred()); \ + return PyLong_FromSsize_t(_ret); \ + } while (0) + +/* Marker to check that pointer value was set. */ +static const char uninitialized[] = "uninitialized"; +#define UNINITIALIZED_PTR ((void *)uninitialized) +/* Marker to check that Py_ssize_t value was set. */ +#define UNINITIALIZED_SIZE ((Py_ssize_t)236892191) +/* Marker to check that integer value was set. */ +#define UNINITIALIZED_INT (63256717) diff --git a/Modules/_testcapi/vectorcall.c b/Modules/_testcapi/vectorcall.c index 2b5110fcba2c91..b30c5e8704c8af 100644 --- a/Modules/_testcapi/vectorcall.c +++ b/Modules/_testcapi/vectorcall.c @@ -1,3 +1,6 @@ +// clinic/vectorcall.c.h uses internal pycore_modsupport.h API +#define PYTESTCAPI_NEED_INTERNAL_API + #include "parts.h" #include "clinic/vectorcall.c.h" diff --git a/Modules/_testcapi/vectorcall_limited.c b/Modules/_testcapi/vectorcall_limited.c index a96925e840121a..d7070d37bb9e9b 100644 --- a/Modules/_testcapi/vectorcall_limited.c +++ b/Modules/_testcapi/vectorcall_limited.c @@ -1,11 +1,18 @@ -#define Py_LIMITED_API 0x030c0000 // 3.12 -#include "parts.h" +/* Test Vectorcall in the limited API */ -#ifdef LIMITED_API_AVAILABLE +#include "pyconfig.h" // Py_GIL_DISABLED +#ifndef Py_GIL_DISABLED +#define Py_LIMITED_API 0x030c0000 // 3.12 +#endif +#include "parts.h" +#include "clinic/vectorcall_limited.c.h" -/* Test Vectorcall in the limited API */ +/*[clinic input] +module _testcapi +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=6361033e795369fc]*/ static PyObject * LimitedVectorCallClass_tpcall(PyObject *self, PyObject *args, PyObject *kwargs) { @@ -32,8 +39,16 @@ LimitedVectorCallClass_new(PyTypeObject *tp, PyTypeObject *a, PyTypeObject *kw) return self; } +/*[clinic input] +_testcapi.call_vectorcall + + callable: object + / +[clinic start generated code]*/ + static PyObject * -call_vectorcall(PyObject* self, PyObject *callable) +_testcapi_call_vectorcall(PyObject *module, PyObject *callable) +/*[clinic end generated code: output=bae81eec97fcaad7 input=55d88f92240957ee]*/ { PyObject *args[3] = { NULL, NULL, NULL }; PyObject *kwname = NULL, *kwnames = NULL, *result = NULL; @@ -77,8 +92,16 @@ call_vectorcall(PyObject* self, PyObject *callable) return result; } +/*[clinic input] +_testcapi.call_vectorcall_method + + callable: object + / +[clinic start generated code]*/ + static PyObject * -call_vectorcall_method(PyObject* self, PyObject *callable) +_testcapi_call_vectorcall_method(PyObject *module, PyObject *callable) +/*[clinic end generated code: output=e661f48dda08b6fb input=5ba81c27511395b6]*/ { PyObject *args[3] = { NULL, NULL, NULL }; PyObject *name = NULL, *kwname = NULL, @@ -153,8 +176,8 @@ static PyType_Spec LimitedVectorCallClass_spec = { }; static PyMethodDef TestMethods[] = { - {"call_vectorcall", call_vectorcall, METH_O}, - {"call_vectorcall_method", call_vectorcall_method, METH_O}, + _TESTCAPI_CALL_VECTORCALL_METHODDEF + _TESTCAPI_CALL_VECTORCALL_METHOD_METHODDEF {NULL}, }; @@ -172,8 +195,6 @@ _PyTestCapi_Init_VectorcallLimited(PyObject *m) { if (PyModule_AddType(m, (PyTypeObject *)LimitedVectorCallClass) < 0) { return -1; } - + Py_DECREF(LimitedVectorCallClass); return 0; } - -#endif // LIMITED_API_AVAILABLE diff --git a/Modules/_testcapi/watchers.c b/Modules/_testcapi/watchers.c index 4cf567b3314980..a763ff46a3c290 100644 --- a/Modules/_testcapi/watchers.c +++ b/Modules/_testcapi/watchers.c @@ -1,3 +1,6 @@ +// clinic/watchers.c.h uses internal pycore_modsupport.h API +#define PYTESTCAPI_NEED_INTERNAL_API + #include "parts.h" #include "clinic/watchers.c.h" @@ -295,6 +298,7 @@ _testcapi_unwatch_type_impl(PyObject *module, int watcher_id, PyObject *type) // Test code object watching #define NUM_CODE_WATCHERS 2 +static int code_watcher_ids[NUM_CODE_WATCHERS] = {-1, -1}; static int num_code_object_created_events[NUM_CODE_WATCHERS] = {0, 0}; static int num_code_object_destroyed_events[NUM_CODE_WATCHERS] = {0, 0}; @@ -345,11 +349,13 @@ add_code_watcher(PyObject *self, PyObject *which_watcher) long which_l = PyLong_AsLong(which_watcher); if (which_l == 0) { watcher_id = PyCode_AddWatcher(first_code_object_callback); + code_watcher_ids[0] = watcher_id; num_code_object_created_events[0] = 0; num_code_object_destroyed_events[0] = 0; } else if (which_l == 1) { watcher_id = PyCode_AddWatcher(second_code_object_callback); + code_watcher_ids[1] = watcher_id; num_code_object_created_events[1] = 0; num_code_object_destroyed_events[1] = 0; } @@ -375,9 +381,14 @@ clear_code_watcher(PyObject *self, PyObject *watcher_id) return NULL; } // reset static events counters - if (watcher_id_l >= 0 && watcher_id_l < NUM_CODE_WATCHERS) { - num_code_object_created_events[watcher_id_l] = 0; - num_code_object_destroyed_events[watcher_id_l] = 0; + if (watcher_id_l >= 0) { + for (int i = 0; i < NUM_CODE_WATCHERS; i++) { + if (watcher_id_l == code_watcher_ids[i]) { + code_watcher_ids[i] = -1; + num_code_object_created_events[i] = 0; + num_code_object_destroyed_events[i] = 0; + } + } } Py_RETURN_NONE; } diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index 2286a925e36e2c..a0b21b7efbd971 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -5,56 +5,60 @@ * standard Python regression test, via Lib/test/test_capi.py. */ -/* This module tests the public (Include/ and Include/cpython/) C API. - The internal C API must not be used here: use _testinternalcapi for that. - - The Visual Studio projects builds _testcapi with Py_BUILD_CORE_MODULE - macro defined, but only the public C API must be tested here. */ - -#undef Py_BUILD_CORE_MODULE -#undef Py_BUILD_CORE_BUILTIN - -/* Always enable assertions */ -#undef NDEBUG +// Include parts.h first since it takes care of NDEBUG and Py_BUILD_CORE macros +// and including Python.h. +// +// Several parts of this module are broken out into files in _testcapi/. +// Include definitions from there. +#include "_testcapi/parts.h" -#include "Python.h" -#include "frameobject.h" // PyFrame_New -#include "marshal.h" // PyMarshal_WriteLongToFile +#include "frameobject.h" // PyFrame_New() +#include "interpreteridobject.h" // PyInterpreterID_Type +#include "marshal.h" // PyMarshal_WriteLongToFile() #include // FLT_MAX #include #include // offsetof() -#ifndef MS_WINDOWS -# include -#endif #ifdef HAVE_SYS_WAIT_H # include // W_STOPCODE #endif -#ifdef Py_BUILD_CORE -# error "_testcapi must test the public Python C API, not CPython internal C API" -#endif - #ifdef bool -# error "The public headers should not include , see bpo-46748" +# error "The public headers should not include , see gh-48924" #endif -// Several parts of this module are broken out into files in _testcapi/. -// Include definitions from there. -#include "_testcapi/parts.h" +#include "_testcapi/util.h" + // Forward declarations static struct PyModuleDef _testcapimodule; -static PyObject *TestError; /* set to exception object in init */ +// Module state +typedef struct { + PyObject *error; // _testcapi.error object +} testcapistate_t; -/* Raise TestError with test_name + ": " + msg, and return NULL. */ +static testcapistate_t* +get_testcapi_state(PyObject *module) +{ + void *state = PyModule_GetState(module); + assert(state != NULL); + return (testcapistate_t *)state; +} static PyObject * -raiseTestError(const char* test_name, const char* msg) +get_testerror(PyObject *self) { + testcapistate_t *state = get_testcapi_state(self); + return state->error; +} + +/* Raise _testcapi.error with test_name + ": " + msg, and return NULL. */ + +static PyObject * +raiseTestError(PyObject *self, const char* test_name, const char* msg) { - PyErr_Format(TestError, "%s: %s", test_name, msg); + PyErr_Format(get_testerror(self), "%s: %s", test_name, msg); return NULL; } @@ -65,10 +69,10 @@ raiseTestError(const char* test_name, const char* msg) platforms have these hardcoded. Better safe than sorry. */ static PyObject* -sizeof_error(const char* fatname, const char* typname, +sizeof_error(PyObject *self, const char* fatname, const char* typname, int expected, int got) { - PyErr_Format(TestError, + PyErr_Format(get_testerror(self), "%s #define == %d but sizeof(%s) == %d", fatname, expected, typname, got); return (PyObject*)NULL; @@ -79,7 +83,7 @@ test_config(PyObject *self, PyObject *Py_UNUSED(ignored)) { #define CHECK_SIZEOF(FATNAME, TYPE) \ if (FATNAME != sizeof(TYPE)) \ - return sizeof_error(#FATNAME, #TYPE, FATNAME, sizeof(TYPE)) + return sizeof_error(self, #FATNAME, #TYPE, FATNAME, sizeof(TYPE)) CHECK_SIZEOF(SIZEOF_SHORT, short); CHECK_SIZEOF(SIZEOF_INT, int); @@ -102,7 +106,7 @@ test_sizeof_c_types(PyObject *self, PyObject *Py_UNUSED(ignored)) #endif #define CHECK_SIZEOF(TYPE, EXPECTED) \ if (EXPECTED != sizeof(TYPE)) { \ - PyErr_Format(TestError, \ + PyErr_Format(get_testerror(self), \ "sizeof(%s) = %u instead of %u", \ #TYPE, sizeof(TYPE), EXPECTED); \ return (PyObject*)NULL; \ @@ -110,7 +114,7 @@ test_sizeof_c_types(PyObject *self, PyObject *Py_UNUSED(ignored)) #define IS_SIGNED(TYPE) (((TYPE)-1) < (TYPE)0) #define CHECK_SIGNNESS(TYPE, SIGNED) \ if (IS_SIGNED(TYPE) != SIGNED) { \ - PyErr_Format(TestError, \ + PyErr_Format(get_testerror(self), \ "%s signness is, instead of %i", \ #TYPE, IS_SIGNED(TYPE), SIGNED); \ return (PyObject*)NULL; \ @@ -183,7 +187,7 @@ test_list_api(PyObject *self, PyObject *Py_UNUSED(ignored)) for (i = 0; i < NLIST; ++i) { PyObject* anint = PyList_GET_ITEM(list, i); if (PyLong_AS_LONG(anint) != NLIST-1-i) { - PyErr_SetString(TestError, + PyErr_SetString(get_testerror(self), "test_list_api: reverse screwed up"); Py_DECREF(list); return (PyObject*)NULL; @@ -196,7 +200,7 @@ test_list_api(PyObject *self, PyObject *Py_UNUSED(ignored)) } static int -test_dict_inner(int count) +test_dict_inner(PyObject *self, int count) { Py_ssize_t pos = 0, iterations = 0; int i; @@ -209,40 +213,50 @@ test_dict_inner(int count) for (i = 0; i < count; i++) { v = PyLong_FromLong(i); if (v == NULL) { - return -1; + goto error; } if (PyDict_SetItem(dict, v, v) < 0) { Py_DECREF(v); - return -1; + goto error; } Py_DECREF(v); } + k = v = UNINITIALIZED_PTR; while (PyDict_Next(dict, &pos, &k, &v)) { PyObject *o; iterations++; + assert(k != UNINITIALIZED_PTR); + assert(v != UNINITIALIZED_PTR); i = PyLong_AS_LONG(v) + 1; o = PyLong_FromLong(i); - if (o == NULL) - return -1; + if (o == NULL) { + goto error; + } if (PyDict_SetItem(dict, k, o) < 0) { Py_DECREF(o); - return -1; + goto error; } Py_DECREF(o); + k = v = UNINITIALIZED_PTR; } + assert(k == UNINITIALIZED_PTR); + assert(v == UNINITIALIZED_PTR); Py_DECREF(dict); if (iterations != count) { PyErr_SetString( - TestError, + get_testerror(self), "test_dict_iteration: dict iteration went wrong "); return -1; } else { return 0; } +error: + Py_DECREF(dict); + return -1; } @@ -253,7 +267,7 @@ test_dict_iteration(PyObject* self, PyObject *Py_UNUSED(ignored)) int i; for (i = 0; i < 200; i++) { - if (test_dict_inner(i) < 0) { + if (test_dict_inner(self, i) < 0) { return NULL; } } @@ -261,26 +275,6 @@ test_dict_iteration(PyObject* self, PyObject *Py_UNUSED(ignored)) Py_RETURN_NONE; } -static PyObject* -dict_getitem_knownhash(PyObject *self, PyObject *args) -{ - PyObject *mp, *key, *result; - Py_ssize_t hash; - - if (!PyArg_ParseTuple(args, "OOn:dict_getitem_knownhash", - &mp, &key, &hash)) { - return NULL; - } - - result = _PyDict_GetItem_KnownHash(mp, key, (Py_hash_t)hash); - if (result == NULL && !PyErr_Occurred()) { - _PyErr_SetKeyError(key); - return NULL; - } - - return Py_XNewRef(result); -} - /* Issue #4701: Check that PyObject_Hash implicitly calls * PyType_Ready if it hasn't already been called */ @@ -357,14 +351,14 @@ test_lazy_hash_inheritance(PyObject* self, PyObject *Py_UNUSED(ignored)) if (obj == NULL) { PyErr_Clear(); PyErr_SetString( - TestError, + get_testerror(self), "test_lazy_hash_inheritance: failed to create object"); return NULL; } if (type->tp_dict != NULL) { PyErr_SetString( - TestError, + get_testerror(self), "test_lazy_hash_inheritance: type initialised too soon"); Py_DECREF(obj); return NULL; @@ -374,7 +368,7 @@ test_lazy_hash_inheritance(PyObject* self, PyObject *Py_UNUSED(ignored)) if ((hash == -1) && PyErr_Occurred()) { PyErr_Clear(); PyErr_SetString( - TestError, + get_testerror(self), "test_lazy_hash_inheritance: could not hash object"); Py_DECREF(obj); return NULL; @@ -382,7 +376,7 @@ test_lazy_hash_inheritance(PyObject* self, PyObject *Py_UNUSED(ignored)) if (type->tp_dict == NULL) { PyErr_SetString( - TestError, + get_testerror(self), "test_lazy_hash_inheritance: type not initialised by hash()"); Py_DECREF(obj); return NULL; @@ -390,7 +384,7 @@ test_lazy_hash_inheritance(PyObject* self, PyObject *Py_UNUSED(ignored)) if (type->tp_hash != PyType_Type.tp_hash) { PyErr_SetString( - TestError, + get_testerror(self), "test_lazy_hash_inheritance: unexpected hash function"); Py_DECREF(obj); return NULL; @@ -414,8 +408,43 @@ raise_error(void *unused) return NULL; } +static PyObject * +py_buildvalue(PyObject *self, PyObject *args) +{ + const char *fmt; + PyObject *objs[10] = {NULL}; + if (!PyArg_ParseTuple(args, "s|OOOOOOOOOO", &fmt, + &objs[0], &objs[1], &objs[2], &objs[3], &objs[4], + &objs[5], &objs[6], &objs[7], &objs[8], &objs[9])) + { + return NULL; + } + for(int i = 0; i < 10; i++) { + NULLABLE(objs[i]); + } + return Py_BuildValue(fmt, + objs[0], objs[1], objs[2], objs[3], objs[4], + objs[5], objs[6], objs[7], objs[8], objs[9]); +} + +static PyObject * +py_buildvalue_ints(PyObject *self, PyObject *args) +{ + const char *fmt; + unsigned int values[10] = {0}; + if (!PyArg_ParseTuple(args, "s|IIIIIIIIII", &fmt, + &values[0], &values[1], &values[2], &values[3], &values[4], + &values[5], &values[6], &values[7], &values[8], &values[9])) + { + return NULL; + } + return Py_BuildValue(fmt, + values[0], values[1], values[2], values[3], values[4], + values[5], values[6], values[7], values[8], values[9]); +} + static int -test_buildvalue_N_error(const char *fmt) +test_buildvalue_N_error(PyObject *self, const char *fmt) { PyObject *arg, *res; @@ -431,7 +460,7 @@ test_buildvalue_N_error(const char *fmt) } Py_DECREF(res); if (Py_REFCNT(arg) != 1) { - PyErr_Format(TestError, "test_buildvalue_N: " + PyErr_Format(get_testerror(self), "test_buildvalue_N: " "arg was not decrefed in successful " "Py_BuildValue(\"%s\")", fmt); return -1; @@ -440,13 +469,13 @@ test_buildvalue_N_error(const char *fmt) Py_INCREF(arg); res = Py_BuildValue(fmt, raise_error, NULL, arg); if (res != NULL || !PyErr_Occurred()) { - PyErr_Format(TestError, "test_buildvalue_N: " + PyErr_Format(get_testerror(self), "test_buildvalue_N: " "Py_BuildValue(\"%s\") didn't complain", fmt); return -1; } PyErr_Clear(); if (Py_REFCNT(arg) != 1) { - PyErr_Format(TestError, "test_buildvalue_N: " + PyErr_Format(get_testerror(self), "test_buildvalue_N: " "arg was not decrefed in failed " "Py_BuildValue(\"%s\")", fmt); return -1; @@ -470,25 +499,25 @@ test_buildvalue_N(PyObject *self, PyObject *Py_UNUSED(ignored)) return NULL; } if (res != arg) { - return raiseTestError("test_buildvalue_N", + return raiseTestError(self, "test_buildvalue_N", "Py_BuildValue(\"N\") returned wrong result"); } if (Py_REFCNT(arg) != 2) { - return raiseTestError("test_buildvalue_N", + return raiseTestError(self, "test_buildvalue_N", "arg was not decrefed in Py_BuildValue(\"N\")"); } Py_DECREF(res); Py_DECREF(arg); - if (test_buildvalue_N_error("O&N") < 0) + if (test_buildvalue_N_error(self, "O&N") < 0) return NULL; - if (test_buildvalue_N_error("(O&N)") < 0) + if (test_buildvalue_N_error(self, "(O&N)") < 0) return NULL; - if (test_buildvalue_N_error("[O&N]") < 0) + if (test_buildvalue_N_error(self, "[O&N]") < 0) return NULL; - if (test_buildvalue_N_error("{O&N}") < 0) + if (test_buildvalue_N_error(self, "{O&N}") < 0) return NULL; - if (test_buildvalue_N_error("{()O&(())N}") < 0) + if (test_buildvalue_N_error(self, "{()O&(())N}") < 0) return NULL; Py_RETURN_NONE; @@ -562,6 +591,12 @@ static PyType_Spec HeapTypeNameType_Spec = { .slots = HeapTypeNameType_slots, }; +static PyObject * +get_heaptype_for_name(PyObject *self, PyObject *Py_UNUSED(ignored)) +{ + return PyType_FromSpec(&HeapTypeNameType_Spec); +} + static PyObject * test_get_type_name(PyObject *self, PyObject *Py_UNUSED(ignored)) { @@ -892,7 +927,7 @@ test_string_to_double(PyObject *self, PyObject *Py_UNUSED(ignored)) { Py_RETURN_NONE; fail: - return raiseTestError("test_string_to_double", msg); + return raiseTestError(self, "test_string_to_double", msg); #undef CHECK_STRING #undef CHECK_INVALID } @@ -1043,7 +1078,7 @@ test_capsule(PyObject *self, PyObject *Py_UNUSED(ignored)) exit: if (error) { - return raiseTestError("test_capsule", error); + return raiseTestError(self, "test_capsule", error); } Py_RETURN_NONE; #undef FAIL @@ -1254,7 +1289,7 @@ test_from_contiguous(PyObject* self, PyObject *Py_UNUSED(ignored)) ptr = view.buf; for (i = 0; i < 5; i++) { if (ptr[2*i] != i) { - PyErr_SetString(TestError, + PyErr_SetString(get_testerror(self), "test_from_contiguous: incorrect result"); return NULL; } @@ -1267,7 +1302,7 @@ test_from_contiguous(PyObject* self, PyObject *Py_UNUSED(ignored)) ptr = view.buf; for (i = 0; i < 5; i++) { if (*(ptr-2*i) != i) { - PyErr_SetString(TestError, + PyErr_SetString(get_testerror(self), "test_from_contiguous: incorrect result"); return NULL; } @@ -1320,7 +1355,7 @@ test_pep3118_obsolete_write_locks(PyObject* self, PyObject *Py_UNUSED(ignored)) Py_RETURN_NONE; error: - PyErr_SetString(TestError, + PyErr_SetString(get_testerror(self), "test_pep3118_obsolete_write_locks: failure"); return NULL; } @@ -1343,19 +1378,13 @@ static PyObject * test_PyBuffer_SizeFromFormat(PyObject *self, PyObject *args) { const char *format; - Py_ssize_t result; if (!PyArg_ParseTuple(args, "s:test_PyBuffer_SizeFromFormat", &format)) { return NULL; } - result = PyBuffer_SizeFromFormat(format); - if (result == -1) { - return NULL; - } - - return PyLong_FromSsize_t(result); + RETURN_SIZE(PyBuffer_SizeFromFormat(format)); } /* Test that the fatal error from not having a current thread doesn't @@ -1444,154 +1473,34 @@ run_in_subinterp(PyObject *self, PyObject *args) return PyLong_FromLong(r); } -/* To run some code in a sub-interpreter. */ static PyObject * -run_in_subinterp_with_config(PyObject *self, PyObject *args, PyObject *kwargs) -{ - const char *code; - int use_main_obmalloc = -1; - int allow_fork = -1; - int allow_exec = -1; - int allow_threads = -1; - int allow_daemon_threads = -1; - int check_multi_interp_extensions = -1; - int gil = -1; - int r; - PyThreadState *substate, *mainstate; - /* only initialise 'cflags.cf_flags' to test backwards compatibility */ - PyCompilerFlags cflags = {0}; - - static char *kwlist[] = {"code", - "use_main_obmalloc", - "allow_fork", - "allow_exec", - "allow_threads", - "allow_daemon_threads", - "check_multi_interp_extensions", - "gil", - NULL}; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "s$ppppppi:run_in_subinterp_with_config", kwlist, - &code, &use_main_obmalloc, - &allow_fork, &allow_exec, - &allow_threads, &allow_daemon_threads, - &check_multi_interp_extensions, - &gil)) { - return NULL; - } - if (use_main_obmalloc < 0) { - PyErr_SetString(PyExc_ValueError, "missing use_main_obmalloc"); - return NULL; - } - if (allow_fork < 0) { - PyErr_SetString(PyExc_ValueError, "missing allow_fork"); - return NULL; - } - if (allow_exec < 0) { - PyErr_SetString(PyExc_ValueError, "missing allow_exec"); - return NULL; - } - if (allow_threads < 0) { - PyErr_SetString(PyExc_ValueError, "missing allow_threads"); - return NULL; - } - if (gil < 0) { - PyErr_SetString(PyExc_ValueError, "missing gil"); - return NULL; - } - if (allow_daemon_threads < 0) { - PyErr_SetString(PyExc_ValueError, "missing allow_daemon_threads"); - return NULL; - } - if (check_multi_interp_extensions < 0) { - PyErr_SetString(PyExc_ValueError, "missing check_multi_interp_extensions"); - return NULL; - } - - mainstate = PyThreadState_Get(); - - PyThreadState_Swap(NULL); - - const PyInterpreterConfig config = { - .use_main_obmalloc = use_main_obmalloc, - .allow_fork = allow_fork, - .allow_exec = allow_exec, - .allow_threads = allow_threads, - .allow_daemon_threads = allow_daemon_threads, - .check_multi_interp_extensions = check_multi_interp_extensions, - .gil = gil, - }; - PyStatus status = Py_NewInterpreterFromConfig(&substate, &config); - if (PyStatus_Exception(status)) { - /* Since no new thread state was created, there is no exception to - propagate; raise a fresh one after swapping in the old thread - state. */ - PyThreadState_Swap(mainstate); - _PyErr_SetFromPyStatus(status); - PyObject *exc = PyErr_GetRaisedException(); - PyErr_SetString(PyExc_RuntimeError, "sub-interpreter creation failed"); - _PyErr_ChainExceptions1(exc); - return NULL; - } - assert(substate != NULL); - r = PyRun_SimpleStringFlags(code, &cflags); - Py_EndInterpreter(substate); - - PyThreadState_Swap(mainstate); - - return PyLong_FromLong(r); -} - -static void -_xid_capsule_destructor(PyObject *capsule) +get_interpreterid_type(PyObject *self, PyObject *Py_UNUSED(ignored)) { - _PyCrossInterpreterData *data = \ - (_PyCrossInterpreterData *)PyCapsule_GetPointer(capsule, NULL); - if (data != NULL) { - assert(_PyCrossInterpreterData_Release(data) == 0); - PyMem_Free(data); - } + return Py_NewRef(&PyInterpreterID_Type); } static PyObject * -get_crossinterp_data(PyObject *self, PyObject *args) +link_interpreter_refcount(PyObject *self, PyObject *idobj) { - PyObject *obj = NULL; - if (!PyArg_ParseTuple(args, "O:get_crossinterp_data", &obj)) { - return NULL; - } - - _PyCrossInterpreterData *data = PyMem_NEW(_PyCrossInterpreterData, 1); - if (data == NULL) { - PyErr_NoMemory(); - return NULL; - } - if (_PyObject_GetCrossInterpreterData(obj, data) != 0) { - PyMem_Free(data); + PyInterpreterState *interp = PyInterpreterID_LookUp(idobj); + if (interp == NULL) { + assert(PyErr_Occurred()); return NULL; } - PyObject *capsule = PyCapsule_New(data, NULL, _xid_capsule_destructor); - if (capsule == NULL) { - assert(_PyCrossInterpreterData_Release(data) == 0); - PyMem_Free(data); - } - return capsule; + _PyInterpreterState_RequireIDRef(interp, 1); + Py_RETURN_NONE; } static PyObject * -restore_crossinterp_data(PyObject *self, PyObject *args) +unlink_interpreter_refcount(PyObject *self, PyObject *idobj) { - PyObject *capsule = NULL; - if (!PyArg_ParseTuple(args, "O:restore_crossinterp_data", &capsule)) { - return NULL; - } - - _PyCrossInterpreterData *data = \ - (_PyCrossInterpreterData *)PyCapsule_GetPointer(capsule, NULL); - if (data == NULL) { + PyInterpreterState *interp = PyInterpreterID_LookUp(idobj); + if (interp == NULL) { + assert(PyErr_Occurred()); return NULL; } - return _PyCrossInterpreterData_NewObject(data); + _PyInterpreterState_RequireIDRef(interp, 0); + Py_RETURN_NONE; } static PyMethodDef ml; @@ -1668,7 +1577,9 @@ test_structseq_newtype_doesnt_leak(PyObject *Py_UNUSED(self), descr.n_in_sequence = 1; PyTypeObject* structseq_type = PyStructSequence_NewType(&descr); - assert(structseq_type != NULL); + if (structseq_type == NULL) { + return NULL; + } assert(PyType_Check(structseq_type)); assert(PyType_FastSubclass(structseq_type, Py_TPFLAGS_TUPLE_SUBCLASS)); Py_DECREF(structseq_type); @@ -1983,7 +1894,7 @@ return_result_with_error(PyObject *self, PyObject *args) Py_RETURN_NONE; } -static PyObject* +static PyObject * getitem_with_error(PyObject *self, PyObject *args) { PyObject *map, *key; @@ -2060,96 +1971,12 @@ py_w_stopcode(PyObject *self, PyObject *args) #endif -static PyObject * -get_mapping_keys(PyObject* self, PyObject *obj) -{ - return PyMapping_Keys(obj); -} - -static PyObject * -get_mapping_values(PyObject* self, PyObject *obj) -{ - return PyMapping_Values(obj); -} - -static PyObject * -get_mapping_items(PyObject* self, PyObject *obj) -{ - return PyMapping_Items(obj); -} - -static PyObject * -test_mapping_has_key_string(PyObject *self, PyObject *Py_UNUSED(args)) -{ - PyObject *context = PyDict_New(); - PyObject *val = PyLong_FromLong(1); - - // Since this uses `const char*` it is easier to test this in C: - PyDict_SetItemString(context, "a", val); - if (!PyMapping_HasKeyString(context, "a")) { - PyErr_SetString(PyExc_RuntimeError, - "Existing mapping key does not exist"); - return NULL; - } - if (PyMapping_HasKeyString(context, "b")) { - PyErr_SetString(PyExc_RuntimeError, - "Missing mapping key exists"); - return NULL; - } - - Py_DECREF(val); - Py_DECREF(context); - Py_RETURN_NONE; -} - -static PyObject * -mapping_has_key(PyObject* self, PyObject *args) -{ - PyObject *context, *key; - if (!PyArg_ParseTuple(args, "OO", &context, &key)) { - return NULL; - } - return PyLong_FromLong(PyMapping_HasKey(context, key)); -} - -static PyObject * -sequence_set_slice(PyObject* self, PyObject *args) -{ - PyObject *sequence, *obj; - Py_ssize_t i1, i2; - if (!PyArg_ParseTuple(args, "OnnO", &sequence, &i1, &i2, &obj)) { - return NULL; - } - - int res = PySequence_SetSlice(sequence, i1, i2, obj); - if (res == -1) { - return NULL; - } - Py_RETURN_NONE; -} - -static PyObject * -sequence_del_slice(PyObject* self, PyObject *args) -{ - PyObject *sequence; - Py_ssize_t i1, i2; - if (!PyArg_ParseTuple(args, "Onn", &sequence, &i1, &i2)) { - return NULL; - } - - int res = PySequence_DelSlice(sequence, i1, i2); - if (res == -1) { - return NULL; - } - Py_RETURN_NONE; -} - static PyObject * test_pythread_tss_key_state(PyObject *self, PyObject *args) { Py_tss_t tss_key = Py_tss_NEEDS_INIT; if (PyThread_tss_is_created(&tss_key)) { - return raiseTestError("test_pythread_tss_key_state", + return raiseTestError(self, "test_pythread_tss_key_state", "TSS key not in an uninitialized state at " "creation time"); } @@ -2158,19 +1985,19 @@ test_pythread_tss_key_state(PyObject *self, PyObject *args) return NULL; } if (!PyThread_tss_is_created(&tss_key)) { - return raiseTestError("test_pythread_tss_key_state", + return raiseTestError(self, "test_pythread_tss_key_state", "PyThread_tss_create succeeded, " "but with TSS key in an uninitialized state"); } if (PyThread_tss_create(&tss_key) != 0) { - return raiseTestError("test_pythread_tss_key_state", + return raiseTestError(self, "test_pythread_tss_key_state", "PyThread_tss_create unsuccessful with " "an already initialized key"); } #define CHECK_TSS_API(expr) \ (void)(expr); \ if (!PyThread_tss_is_created(&tss_key)) { \ - return raiseTestError("test_pythread_tss_key_state", \ + return raiseTestError(self, "test_pythread_tss_key_state", \ "TSS key initialization state was not " \ "preserved after calling " #expr); } CHECK_TSS_API(PyThread_tss_set(&tss_key, NULL)); @@ -2178,7 +2005,7 @@ test_pythread_tss_key_state(PyObject *self, PyObject *args) #undef CHECK_TSS_API PyThread_tss_delete(&tss_key); if (PyThread_tss_is_created(&tss_key)) { - return raiseTestError("test_pythread_tss_key_state", + return raiseTestError(self, "test_pythread_tss_key_state", "PyThread_tss_delete called, but did not " "set the key state to uninitialized"); } @@ -2189,7 +2016,7 @@ test_pythread_tss_key_state(PyObject *self, PyObject *args) return NULL; } if (PyThread_tss_is_created(ptr_key)) { - return raiseTestError("test_pythread_tss_key_state", + return raiseTestError(self, "test_pythread_tss_key_state", "TSS key not in an uninitialized state at " "allocation time"); } @@ -2199,22 +2026,15 @@ test_pythread_tss_key_state(PyObject *self, PyObject *args) } -static PyObject* -new_hamt(PyObject *self, PyObject *args) -{ - return _PyContext_NewHamtForTests(); -} - - /* def bad_get(self, obj, cls): cls() return repr(self) */ static PyObject* -bad_get(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +bad_get(PyObject *module, PyObject *args) { PyObject *self, *obj, *cls; - if (!_PyArg_UnpackStack(args, nargs, "bad_get", 3, 3, &self, &obj, &cls)) { + if (!PyArg_ParseTuple(args, "OOO", &self, &obj, &cls)) { return NULL; } @@ -2244,73 +2064,27 @@ negative_refcount(PyObject *self, PyObject *Py_UNUSED(args)) Py_RETURN_NONE; } -#endif - static PyObject * -sequence_getitem(PyObject *self, PyObject *args) +decref_freed_object(PyObject *self, PyObject *Py_UNUSED(args)) { - PyObject *seq; - Py_ssize_t i; - if (!PyArg_ParseTuple(args, "On", &seq, &i)) { + PyObject *obj = PyUnicode_FromString("decref_freed_object"); + if (obj == NULL) { return NULL; } - return PySequence_GetItem(seq, i); -} - + assert(Py_REFCNT(obj) == 1); -static PyObject * -sequence_setitem(PyObject *self, PyObject *args) -{ - Py_ssize_t i; - PyObject *seq, *val; - if (!PyArg_ParseTuple(args, "OnO", &seq, &i, &val)) { - return NULL; - } - if (PySequence_SetItem(seq, i, val)) { - return NULL; - } - Py_RETURN_NONE; -} + // Deallocate the memory + Py_DECREF(obj); + // obj is a now a dangling pointer + // gh-109496: If Python is built in debug mode, Py_DECREF() must call + // _Py_NegativeRefcount() and abort Python. + Py_DECREF(obj); -static PyObject * -sequence_delitem(PyObject *self, PyObject *args) -{ - Py_ssize_t i; - PyObject *seq; - if (!PyArg_ParseTuple(args, "On", &seq, &i)) { - return NULL; - } - if (PySequence_DelItem(seq, i)) { - return NULL; - } Py_RETURN_NONE; } - -static PyObject * -hasattr_string(PyObject *self, PyObject* args) -{ - PyObject* obj; - PyObject* attr_name; - - if (!PyArg_UnpackTuple(args, "hasattr_string", 2, 2, &obj, &attr_name)) { - return NULL; - } - - if (!PyUnicode_Check(attr_name)) { - PyErr_SetString(PyExc_TypeError, "attribute name must a be string"); - return PyErr_Occurred(); - } - - const char *name_str = PyUnicode_AsUTF8(attr_name); - if (PyObject_HasAttrString(obj, name_str)) { - Py_RETURN_TRUE; - } - else { - Py_RETURN_FALSE; - } -} +#endif /* Functions for testing C calling conventions (METH_*) are named meth_*, @@ -2635,6 +2409,32 @@ type_get_version(PyObject *self, PyObject *type) return res; } +static PyObject * +type_modified(PyObject *self, PyObject *type) +{ + if (!PyType_Check(type)) { + PyErr_SetString(PyExc_TypeError, "argument must be a type"); + return NULL; + } + PyType_Modified((PyTypeObject *)type); + Py_RETURN_NONE; +} + +// Circumvents standard version assignment machinery - use with caution and only on +// short-lived heap types +static PyObject * +type_assign_specific_version_unsafe(PyObject *self, PyObject *args) +{ + PyTypeObject *type; + unsigned int version; + if (!PyArg_ParseTuple(args, "Oi:type_assign_specific_version_unsafe", &type, &version)) { + return NULL; + } + assert(!PyType_HasFeature(type, Py_TPFLAGS_IMMUTABLETYPE)); + type->tp_version_tag = version; + type->tp_flags |= Py_TPFLAGS_VALID_VERSION_TAG; + Py_RETURN_NONE; +} static PyObject * type_assign_version(PyObject *self, PyObject *type) @@ -2727,8 +2527,8 @@ test_tstate_capi(PyObject *self, PyObject *Py_UNUSED(args)) PyThreadState *tstate2 = PyThreadState_Get(); assert(tstate2 == tstate); - // private _PyThreadState_UncheckedGet() - PyThreadState *tstate3 = _PyThreadState_UncheckedGet(); + // PyThreadState_GetUnchecked() + PyThreadState *tstate3 = PyThreadState_GetUnchecked(); assert(tstate3 == tstate); // PyThreadState_EnterTracing(), PyThreadState_LeaveTracing() @@ -3192,7 +2992,7 @@ settrace_to_error(PyObject *self, PyObject *list) static PyObject * clear_managed_dict(PyObject *self, PyObject *obj) { - _PyObject_ClearManagedDict(obj); + PyObject_ClearManagedDict(obj); Py_RETURN_NONE; } @@ -3400,7 +3200,7 @@ test_weakref_capi(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args)) assert(Py_REFCNT(obj) == refcnt); // test PyWeakref_GetRef(), reference is alive - PyObject *ref = Py_True; // marker to check that value was set + PyObject *ref = UNINITIALIZED_PTR; assert(PyWeakref_GetRef(weakref, &ref) == 1); assert(ref == obj); assert(Py_REFCNT(obj) == (refcnt + 1)); @@ -3422,7 +3222,7 @@ test_weakref_capi(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args)) assert(PyWeakref_GET_OBJECT(weakref) == Py_None); // test PyWeakref_GetRef(), reference is dead - ref = Py_True; + ref = UNINITIALIZED_PTR; assert(PyWeakref_GetRef(weakref, &ref) == 0); assert(ref == NULL); @@ -3434,7 +3234,7 @@ test_weakref_capi(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args)) // test PyWeakref_GetRef(), invalid type assert(!PyErr_Occurred()); - ref = Py_True; + ref = UNINITIALIZED_PTR; assert(PyWeakref_GetRef(invalid_weakref, &ref) == -1); assert(PyErr_ExceptionMatches(PyExc_TypeError)); PyErr_Clear(); @@ -3446,7 +3246,7 @@ test_weakref_capi(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args)) PyErr_Clear(); // test PyWeakref_GetRef(NULL) - ref = Py_True; // marker to check that value was set + ref = UNINITIALIZED_PTR; assert(PyWeakref_GetRef(NULL, &ref) == -1); assert(PyErr_ExceptionMatches(PyExc_SystemError)); assert(ref == NULL); @@ -3465,203 +3265,12 @@ test_weakref_capi(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args)) } -static PyObject * -test_dict_capi(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args)) -{ - assert(!PyErr_Occurred()); - - PyObject *dict= NULL, *key = NULL, *missing_key = NULL, *value = NULL; - PyObject *invalid_key = NULL; - int res; - - // test PyDict_New() - dict = PyDict_New(); - if (dict == NULL) { - goto error; - } - - key = PyUnicode_FromString("key"); - if (key == NULL) { - goto error; - } - - missing_key = PyUnicode_FromString("missing_key"); - if (missing_key == NULL) { - goto error; - } - - value = PyUnicode_FromString("value"); - if (value == NULL) { - goto error; - } - - // test PyDict_SetItem() - Py_ssize_t key_refcnt = Py_REFCNT(key); - Py_ssize_t value_refcnt = Py_REFCNT(value); - res = PyDict_SetItem(dict, key, value); - if (res < 0) { - goto error; - } - assert(res == 0); - assert(Py_REFCNT(key) == (key_refcnt + 1)); - assert(Py_REFCNT(value) == (value_refcnt + 1)); - - // test PyDict_SetItemString() - res = PyDict_SetItemString(dict, "key", value); - if (res < 0) { - goto error; - } - assert(res == 0); - assert(Py_REFCNT(key) == (key_refcnt + 1)); - assert(Py_REFCNT(value) == (value_refcnt + 1)); - - // test PyDict_Size() - assert(PyDict_Size(dict) == 1); - - // test PyDict_Contains(), key is present - assert(PyDict_Contains(dict, key) == 1); - - // test PyDict_GetItem(), key is present - assert(PyDict_GetItem(dict, key) == value); - - // test PyDict_GetItemString(), key is present - assert(PyDict_GetItemString(dict, "key") == value); - - // test PyDict_GetItemWithError(), key is present - assert(PyDict_GetItemWithError(dict, key) == value); - assert(!PyErr_Occurred()); - - // test PyDict_GetItemRef(), key is present - PyObject *get_value = Py_Ellipsis; // marker value - assert(PyDict_GetItemRef(dict, key, &get_value) == 1); - assert(get_value == value); - Py_DECREF(get_value); - - // test PyDict_GetItemStringRef(), key is present - get_value = Py_Ellipsis; // marker value - assert(PyDict_GetItemStringRef(dict, "key", &get_value) == 1); - assert(get_value == value); - Py_DECREF(get_value); - - // test PyDict_Contains(), missing key - assert(PyDict_Contains(dict, missing_key) == 0); - - // test PyDict_GetItem(), missing key - assert(PyDict_GetItem(dict, missing_key) == NULL); - assert(!PyErr_Occurred()); - - // test PyDict_GetItemString(), missing key - assert(PyDict_GetItemString(dict, "missing_key") == NULL); - assert(!PyErr_Occurred()); - - // test PyDict_GetItemWithError(), missing key - assert(PyDict_GetItem(dict, missing_key) == NULL); - assert(!PyErr_Occurred()); - - // test PyDict_GetItemRef(), missing key - get_value = Py_Ellipsis; // marker value - assert(PyDict_GetItemRef(dict, missing_key, &get_value) == 0); - assert(!PyErr_Occurred()); - assert(get_value == NULL); - - // test PyDict_GetItemStringRef(), missing key - get_value = Py_Ellipsis; // marker value - assert(PyDict_GetItemStringRef(dict, "missing_key", &get_value) == 0); - assert(!PyErr_Occurred()); - assert(get_value == NULL); - - // test PyDict_GetItem(), invalid dict - PyObject *invalid_dict = key; // borrowed reference - assert(PyDict_GetItem(invalid_dict, key) == NULL); - assert(!PyErr_Occurred()); - - // test PyDict_GetItemWithError(), invalid dict - assert(PyDict_GetItemWithError(invalid_dict, key) == NULL); - assert(PyErr_ExceptionMatches(PyExc_SystemError)); - PyErr_Clear(); - - // test PyDict_GetItemRef(), invalid dict - get_value = Py_Ellipsis; // marker value - assert(PyDict_GetItemRef(invalid_dict, key, &get_value) == -1); - assert(PyErr_ExceptionMatches(PyExc_SystemError)); - PyErr_Clear(); - assert(get_value == NULL); - - // test PyDict_GetItemStringRef(), invalid dict - get_value = Py_Ellipsis; // marker value - assert(PyDict_GetItemStringRef(invalid_dict, "key", &get_value) == -1); - assert(PyErr_ExceptionMatches(PyExc_SystemError)); - PyErr_Clear(); - assert(get_value == NULL); - - invalid_key = PyList_New(0); - if (invalid_key == NULL) { - goto error; - } - - // test PyDict_Contains(), invalid key - assert(PyDict_Contains(dict, invalid_key) == -1); - assert(PyErr_ExceptionMatches(PyExc_TypeError)); - PyErr_Clear(); - - // test PyDict_GetItem(), invalid key - assert(PyDict_GetItem(dict, invalid_key) == NULL); - assert(!PyErr_Occurred()); - - // test PyDict_GetItemWithError(), invalid key - assert(PyDict_GetItemWithError(dict, invalid_key) == NULL); - assert(PyErr_ExceptionMatches(PyExc_TypeError)); - PyErr_Clear(); - - // test PyDict_GetItemRef(), invalid key - get_value = Py_Ellipsis; // marker value - assert(PyDict_GetItemRef(dict, invalid_key, &get_value) == -1); - assert(PyErr_ExceptionMatches(PyExc_TypeError)); - PyErr_Clear(); - assert(get_value == NULL); - - // test PyDict_DelItem(), key is present - assert(PyDict_DelItem(dict, key) == 0); - assert(PyDict_Size(dict) == 0); - - // test PyDict_DelItem(), missing key - assert(PyDict_DelItem(dict, missing_key) == -1); - assert(PyErr_ExceptionMatches(PyExc_KeyError)); - PyErr_Clear(); - - // test PyDict_DelItem(), invalid key - assert(PyDict_DelItem(dict, invalid_key) == -1); - assert(PyErr_ExceptionMatches(PyExc_TypeError)); - PyErr_Clear(); - - // test PyDict_Clear() - PyDict_Clear(dict); - - Py_DECREF(dict); - Py_DECREF(key); - Py_DECREF(missing_key); - Py_DECREF(value); - Py_DECREF(invalid_key); - - Py_RETURN_NONE; - -error: - Py_XDECREF(dict); - Py_XDECREF(key); - Py_XDECREF(missing_key); - Py_XDECREF(value); - Py_XDECREF(invalid_key); - return NULL; -} - - static PyMethodDef TestMethods[] = { {"set_errno", set_errno, METH_VARARGS}, {"test_config", test_config, METH_NOARGS}, {"test_sizeof_c_types", test_sizeof_c_types, METH_NOARGS}, {"test_list_api", test_list_api, METH_NOARGS}, {"test_dict_iteration", test_dict_iteration, METH_NOARGS}, - {"dict_getitem_knownhash", dict_getitem_knownhash, METH_VARARGS}, {"test_lazy_hash_inheritance", test_lazy_hash_inheritance,METH_NOARGS}, {"test_xincref_doesnt_leak",test_xincref_doesnt_leak, METH_NOARGS}, {"test_incref_doesnt_leak", test_incref_doesnt_leak, METH_NOARGS}, @@ -3683,8 +3292,11 @@ static PyMethodDef TestMethods[] = { #endif {"getbuffer_with_null_view", getbuffer_with_null_view, METH_O}, {"PyBuffer_SizeFromFormat", test_PyBuffer_SizeFromFormat, METH_VARARGS}, + {"py_buildvalue", py_buildvalue, METH_VARARGS}, + {"py_buildvalue_ints", py_buildvalue_ints, METH_VARARGS}, {"test_buildvalue_N", test_buildvalue_N, METH_NOARGS}, {"test_get_statictype_slots", test_get_statictype_slots, METH_NOARGS}, + {"get_heaptype_for_name", get_heaptype_for_name, METH_NOARGS}, {"test_get_type_name", test_get_type_name, METH_NOARGS}, {"test_get_type_qualname", test_get_type_qualname, METH_NOARGS}, {"test_get_type_dict", test_get_type_dict, METH_NOARGS}, @@ -3705,11 +3317,9 @@ static PyMethodDef TestMethods[] = { {"crash_no_current_thread", crash_no_current_thread, METH_NOARGS}, {"test_current_tstate_matches", test_current_tstate_matches, METH_NOARGS}, {"run_in_subinterp", run_in_subinterp, METH_VARARGS}, - {"run_in_subinterp_with_config", - _PyCFunction_CAST(run_in_subinterp_with_config), - METH_VARARGS | METH_KEYWORDS}, - {"get_crossinterp_data", get_crossinterp_data, METH_VARARGS}, - {"restore_crossinterp_data", restore_crossinterp_data, METH_VARARGS}, + {"get_interpreterid_type", get_interpreterid_type, METH_NOARGS}, + {"link_interpreter_refcount", link_interpreter_refcount, METH_O}, + {"unlink_interpreter_refcount", unlink_interpreter_refcount, METH_O}, {"create_cfunction", create_cfunction, METH_NOARGS}, {"call_in_temporary_c_thread", call_in_temporary_c_thread, METH_VARARGS, PyDoc_STR("set_error_class(error_class) -> None")}, @@ -3736,23 +3346,12 @@ static PyMethodDef TestMethods[] = { #ifdef W_STOPCODE {"W_STOPCODE", py_w_stopcode, METH_VARARGS}, #endif - {"get_mapping_keys", get_mapping_keys, METH_O}, - {"get_mapping_values", get_mapping_values, METH_O}, - {"get_mapping_items", get_mapping_items, METH_O}, - {"test_mapping_has_key_string", test_mapping_has_key_string, METH_NOARGS}, - {"mapping_has_key", mapping_has_key, METH_VARARGS}, - {"sequence_set_slice", sequence_set_slice, METH_VARARGS}, - {"sequence_del_slice", sequence_del_slice, METH_VARARGS}, {"test_pythread_tss_key_state", test_pythread_tss_key_state, METH_VARARGS}, - {"hamt", new_hamt, METH_NOARGS}, - {"bad_get", _PyCFunction_CAST(bad_get), METH_FASTCALL}, + {"bad_get", bad_get, METH_VARARGS}, #ifdef Py_REF_DEBUG {"negative_refcount", negative_refcount, METH_NOARGS}, + {"decref_freed_object", decref_freed_object, METH_NOARGS}, #endif - {"sequence_getitem", sequence_getitem, METH_VARARGS}, - {"sequence_setitem", sequence_setitem, METH_VARARGS}, - {"sequence_delitem", sequence_delitem, METH_VARARGS}, - {"hasattr_string", hasattr_string, METH_VARARGS}, {"meth_varargs", meth_varargs, METH_VARARGS}, {"meth_varargs_keywords", _PyCFunction_CAST(meth_varargs_keywords), METH_VARARGS|METH_KEYWORDS}, {"meth_o", meth_o, METH_O}, @@ -3769,6 +3368,9 @@ static PyMethodDef TestMethods[] = { {"test_py_is_macros", test_py_is_macros, METH_NOARGS}, {"test_py_is_funcs", test_py_is_funcs, METH_NOARGS}, {"type_get_version", type_get_version, METH_O, PyDoc_STR("type->tp_version_tag")}, + {"type_modified", type_modified, METH_O, PyDoc_STR("PyType_Modified")}, + {"type_assign_specific_version_unsafe", type_assign_specific_version_unsafe, METH_VARARGS, + PyDoc_STR("forcefully assign type->tp_version_tag")}, {"type_assign_version", type_assign_version, METH_O, PyDoc_STR("PyUnstable_Type_AssignVersionTag")}, {"type_get_tp_bases", type_get_tp_bases, METH_O}, {"type_get_tp_mro", type_get_tp_mro, METH_O}, @@ -3800,7 +3402,6 @@ static PyMethodDef TestMethods[] = { {"function_set_kw_defaults", function_set_kw_defaults, METH_VARARGS, NULL}, {"check_pyimport_addmodule", check_pyimport_addmodule, METH_VARARGS}, {"test_weakref_capi", test_weakref_capi, METH_NOARGS}, - {"test_dict_capi", test_dict_capi, METH_NOARGS}, {NULL, NULL} /* sentinel */ }; @@ -4276,14 +3877,9 @@ static PyTypeObject ContainerNoGC_type = { static struct PyModuleDef _testcapimodule = { PyModuleDef_HEAD_INIT, - "_testcapi", - NULL, - -1, - TestMethods, - NULL, - NULL, - NULL, - NULL + .m_name = "_testcapi", + .m_size = sizeof(testcapistate_t), + .m_methods = TestMethods, }; /* Per PEP 489, this module will not be converted to multi-phase initialization @@ -4367,17 +3963,20 @@ PyInit__testcapi(void) PyModule_AddObject(m, "ULLONG_MAX", PyLong_FromUnsignedLongLong(ULLONG_MAX)); PyModule_AddObject(m, "PY_SSIZE_T_MAX", PyLong_FromSsize_t(PY_SSIZE_T_MAX)); PyModule_AddObject(m, "PY_SSIZE_T_MIN", PyLong_FromSsize_t(PY_SSIZE_T_MIN)); + PyModule_AddObject(m, "SIZE_MAX", PyLong_FromSize_t(SIZE_MAX)); PyModule_AddObject(m, "SIZEOF_WCHAR_T", PyLong_FromSsize_t(sizeof(wchar_t))); + PyModule_AddObject(m, "SIZEOF_VOID_P", PyLong_FromSsize_t(sizeof(void*))); PyModule_AddObject(m, "SIZEOF_TIME_T", PyLong_FromSsize_t(sizeof(time_t))); PyModule_AddObject(m, "Py_Version", PyLong_FromUnsignedLong(Py_Version)); Py_INCREF(&PyInstanceMethod_Type); PyModule_AddObject(m, "instancemethod", (PyObject *)&PyInstanceMethod_Type); PyModule_AddIntConstant(m, "the_number_three", 3); + PyModule_AddIntMacro(m, Py_C_RECURSION_LIMIT); - TestError = PyErr_NewException("_testcapi.error", NULL, NULL); - Py_INCREF(TestError); - PyModule_AddObject(m, "error", TestError); + testcapistate_t *state = get_testcapi_state(m); + state->error = PyErr_NewException("_testcapi.error", NULL, NULL); + PyModule_AddObject(m, "error", state->error); if (PyType_Ready(&ContainerNoGC_type) < 0) { return NULL; @@ -4394,6 +3993,15 @@ PyInit__testcapi(void) if (_PyTestCapi_Init_Heaptype(m) < 0) { return NULL; } + if (_PyTestCapi_Init_Abstract(m) < 0) { + return NULL; + } + if (_PyTestCapi_Init_ByteArray(m) < 0) { + return NULL; + } + if (_PyTestCapi_Init_Bytes(m) < 0) { + return NULL; + } if (_PyTestCapi_Init_Unicode(m) < 0) { return NULL; } @@ -4418,6 +4026,24 @@ PyInit__testcapi(void) if (_PyTestCapi_Init_Float(m) < 0) { return NULL; } + if (_PyTestCapi_Init_Complex(m) < 0) { + return NULL; + } + if (_PyTestCapi_Init_Numbers(m) < 0) { + return NULL; + } + if (_PyTestCapi_Init_Dict(m) < 0) { + return NULL; + } + if (_PyTestCapi_Init_Set(m) < 0) { + return NULL; + } + if (_PyTestCapi_Init_List(m) < 0) { + return NULL; + } + if (_PyTestCapi_Init_Tuple(m) < 0) { + return NULL; + } if (_PyTestCapi_Init_Structmember(m) < 0) { return NULL; } @@ -4433,24 +4059,33 @@ PyInit__testcapi(void) if (_PyTestCapi_Init_PyOS(m) < 0) { return NULL; } + if (_PyTestCapi_Init_File(m) < 0) { + return NULL; + } + if (_PyTestCapi_Init_Codec(m) < 0) { + return NULL; + } + if (_PyTestCapi_Init_Sys(m) < 0) { + return NULL; + } if (_PyTestCapi_Init_Immortal(m) < 0) { return NULL; } if (_PyTestCapi_Init_GC(m) < 0) { 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_PyAtomic(m) < 0) { + return NULL; + } if (_PyTestCapi_Init_VectorcallLimited(m) < 0) { return NULL; } if (_PyTestCapi_Init_HeaptypeRelative(m) < 0) { return NULL; } -#endif + if (_PyTestCapi_Init_Hash(m) < 0) { + return NULL; + } PyState_AddModule(m, &_testcapimodule); return m; diff --git a/Modules/_testclinic.c b/Modules/_testclinic.c index 8ba8f8ecadec7a..15e0093f15ba1e 100644 --- a/Modules/_testclinic.c +++ b/Modules/_testclinic.c @@ -1128,6 +1128,26 @@ gh_99240_double_free_impl(PyObject *module, char *a, char *b) Py_RETURN_NONE; } +/*[clinic input] +null_or_tuple_for_varargs + + name: object + *constraints: object + covariant: bool = False + +See https://github.com/python/cpython/issues/110864 +[clinic start generated code]*/ + +static PyObject * +null_or_tuple_for_varargs_impl(PyObject *module, PyObject *name, + PyObject *constraints, int covariant) +/*[clinic end generated code: output=a785b35421358983 input=c9bce186637956b3]*/ +{ + assert(name != NULL); + assert(constraints != NULL); + PyObject *c = covariant ? Py_True : Py_False; + return pack_arguments_newref(3, name, constraints, c); +} /*[clinic input] _testclinic.clone_f1 as clone_f1 @@ -1193,6 +1213,605 @@ clone_with_conv_f2_impl(PyObject *module, custom_t path) } +/*[clinic input] +output push +destination deprstar new file '{dirname}/clinic/_testclinic_depr.c.h' +output everything deprstar +#output methoddef_ifndef buffer 1 +output docstring_prototype suppress +output parser_prototype suppress +output impl_definition block +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=32116eac48a42d34]*/ + + +// Mock Python version 3.8 +#define _SAVED_PY_VERSION PY_VERSION_HEX +#undef PY_VERSION_HEX +#define PY_VERSION_HEX 0x03080000 + + +#include "clinic/_testclinic_depr.c.h" + + +/*[clinic input] +class _testclinic.DeprStarNew "PyObject *" "PyObject" +@classmethod +_testclinic.DeprStarNew.__new__ as depr_star_new + * [from 3.14] + a: object = None +The deprecation message should use the class name instead of __new__. +[clinic start generated code]*/ + +static PyObject * +depr_star_new_impl(PyTypeObject *type, PyObject *a) +/*[clinic end generated code: output=bdbb36244f90cf46 input=fdd640db964b4dc1]*/ +{ + return type->tp_alloc(type, 0); +} + +/*[clinic input] +_testclinic.DeprStarNew.cloned as depr_star_new_clone = _testclinic.DeprStarNew.__new__ +[clinic start generated code]*/ + +static PyObject * +depr_star_new_clone_impl(PyObject *type, PyObject *a) +/*[clinic end generated code: output=3b17bf885fa736bc input=ea659285d5dbec6c]*/ +{ + Py_RETURN_NONE; +} + +static struct PyMethodDef depr_star_new_methods[] = { + DEPR_STAR_NEW_CLONE_METHODDEF + {NULL, NULL} +}; + +static PyTypeObject DeprStarNew = { + PyVarObject_HEAD_INIT(NULL, 0) + .tp_name = "_testclinic.DeprStarNew", + .tp_basicsize = sizeof(PyObject), + .tp_new = depr_star_new, + .tp_flags = Py_TPFLAGS_DEFAULT, + .tp_methods = depr_star_new_methods, +}; + + +/*[clinic input] +class _testclinic.DeprStarInit "PyObject *" "PyObject" +_testclinic.DeprStarInit.__init__ as depr_star_init + * [from 3.14] + a: object = None +The deprecation message should use the class name instead of __init__. +[clinic start generated code]*/ + +static int +depr_star_init_impl(PyObject *self, PyObject *a) +/*[clinic end generated code: output=8d27b43c286d3ecc input=5575b77229d5e2be]*/ +{ + return 0; +} + +/*[clinic input] +_testclinic.DeprStarInit.cloned as depr_star_init_clone = _testclinic.DeprStarInit.__init__ +[clinic start generated code]*/ + +static PyObject * +depr_star_init_clone_impl(PyObject *self, PyObject *a) +/*[clinic end generated code: output=ddfe8a1b5531e7cc input=561e103fe7f8e94f]*/ +{ + Py_RETURN_NONE; +} + +static struct PyMethodDef depr_star_init_methods[] = { + DEPR_STAR_INIT_CLONE_METHODDEF + {NULL, NULL} +}; + +static PyTypeObject DeprStarInit = { + PyVarObject_HEAD_INIT(NULL, 0) + .tp_name = "_testclinic.DeprStarInit", + .tp_basicsize = sizeof(PyObject), + .tp_new = PyType_GenericNew, + .tp_init = depr_star_init, + .tp_flags = Py_TPFLAGS_DEFAULT, + .tp_methods = depr_star_init_methods, +}; + + +/*[clinic input] +class _testclinic.DeprStarInitNoInline "PyObject *" "PyObject" +_testclinic.DeprStarInitNoInline.__init__ as depr_star_init_noinline + a: object + * [from 3.14] + b: object + c: object = None + * + # Force to use _PyArg_ParseTupleAndKeywordsFast. + d: str(accept={str, robuffer}, zeroes=True) = '' +[clinic start generated code]*/ + +static int +depr_star_init_noinline_impl(PyObject *self, PyObject *a, PyObject *b, + PyObject *c, const char *d, Py_ssize_t d_length) +/*[clinic end generated code: output=9b31fc167f1bf9f7 input=5a887543122bca48]*/ +{ + return 0; +} + +static PyTypeObject DeprStarInitNoInline = { + PyVarObject_HEAD_INIT(NULL, 0) + .tp_name = "_testclinic.DeprStarInitNoInline", + .tp_basicsize = sizeof(PyObject), + .tp_new = PyType_GenericNew, + .tp_init = depr_star_init_noinline, + .tp_flags = Py_TPFLAGS_DEFAULT, +}; + + +/*[clinic input] +class _testclinic.DeprKwdNew "PyObject *" "PyObject" +@classmethod +_testclinic.DeprKwdNew.__new__ as depr_kwd_new + a: object = None + / [from 3.14] +The deprecation message should use the class name instead of __new__. +[clinic start generated code]*/ + +static PyObject * +depr_kwd_new_impl(PyTypeObject *type, PyObject *a) +/*[clinic end generated code: output=618d07afc5616149 input=6c7d13c471013c10]*/ +{ + return type->tp_alloc(type, 0); +} + +static PyTypeObject DeprKwdNew = { + PyVarObject_HEAD_INIT(NULL, 0) + .tp_name = "_testclinic.DeprKwdNew", + .tp_basicsize = sizeof(PyObject), + .tp_new = depr_kwd_new, + .tp_flags = Py_TPFLAGS_DEFAULT, +}; + + +/*[clinic input] +class _testclinic.DeprKwdInit "PyObject *" "PyObject" +_testclinic.DeprKwdInit.__init__ as depr_kwd_init + a: object = None + / [from 3.14] +The deprecation message should use the class name instead of __init__. +[clinic start generated code]*/ + +static int +depr_kwd_init_impl(PyObject *self, PyObject *a) +/*[clinic end generated code: output=6e02eb724a85d840 input=b9bf3c20f012d539]*/ +{ + return 0; +} + +static PyTypeObject DeprKwdInit = { + PyVarObject_HEAD_INIT(NULL, 0) + .tp_name = "_testclinic.DeprKwdInit", + .tp_basicsize = sizeof(PyObject), + .tp_new = PyType_GenericNew, + .tp_init = depr_kwd_init, + .tp_flags = Py_TPFLAGS_DEFAULT, +}; + + +/*[clinic input] +class _testclinic.DeprKwdInitNoInline "PyObject *" "PyObject" +_testclinic.DeprKwdInitNoInline.__init__ as depr_kwd_init_noinline + a: object + / + b: object + c: object = None + / [from 3.14] + # Force to use _PyArg_ParseTupleAndKeywordsFast. + d: str(accept={str, robuffer}, zeroes=True) = '' +[clinic start generated code]*/ + +static int +depr_kwd_init_noinline_impl(PyObject *self, PyObject *a, PyObject *b, + PyObject *c, const char *d, Py_ssize_t d_length) +/*[clinic end generated code: output=27759d70ddd25873 input=c19d982c8c70a930]*/ +{ + return 0; +} + +static PyTypeObject DeprKwdInitNoInline = { + PyVarObject_HEAD_INIT(NULL, 0) + .tp_name = "_testclinic.DeprKwdInitNoInline", + .tp_basicsize = sizeof(PyObject), + .tp_new = PyType_GenericNew, + .tp_init = depr_kwd_init_noinline, + .tp_flags = Py_TPFLAGS_DEFAULT, +}; + + +/*[clinic input] +depr_star_pos0_len1 + * [from 3.14] + a: object +[clinic start generated code]*/ + +static PyObject * +depr_star_pos0_len1_impl(PyObject *module, PyObject *a) +/*[clinic end generated code: output=e1c6c2b423129499 input=089b9aee25381b69]*/ +{ + Py_RETURN_NONE; +} + + +/*[clinic input] +depr_star_pos0_len2 + * [from 3.14] + a: object + b: object +[clinic start generated code]*/ + +static PyObject * +depr_star_pos0_len2_impl(PyObject *module, PyObject *a, PyObject *b) +/*[clinic end generated code: output=96df9be39859c7e4 input=65c83a32e01495c6]*/ +{ + Py_RETURN_NONE; +} + + +/*[clinic input] +depr_star_pos0_len3_with_kwd + * [from 3.14] + a: object + b: object + c: object + * + d: object +[clinic start generated code]*/ + +static PyObject * +depr_star_pos0_len3_with_kwd_impl(PyObject *module, PyObject *a, PyObject *b, + PyObject *c, PyObject *d) +/*[clinic end generated code: output=7f2531eda837052f input=b33f620f57d9270f]*/ +{ + Py_RETURN_NONE; +} + + +/*[clinic input] +depr_star_pos1_len1_opt + a: object + * [from 3.14] + b: object = None +[clinic start generated code]*/ + +static PyObject * +depr_star_pos1_len1_opt_impl(PyObject *module, PyObject *a, PyObject *b) +/*[clinic end generated code: output=b5b4e326ee3b216f input=4a4b8ff72eae9ff7]*/ +{ + Py_RETURN_NONE; +} + + +/*[clinic input] +depr_star_pos1_len1 + a: object + * [from 3.14] + b: object +[clinic start generated code]*/ + +static PyObject * +depr_star_pos1_len1_impl(PyObject *module, PyObject *a, PyObject *b) +/*[clinic end generated code: output=eab92e37d5b0a480 input=1e7787a9fe5f62a0]*/ +{ + Py_RETURN_NONE; +} + + +/*[clinic input] +depr_star_pos1_len2_with_kwd + a: object + * [from 3.14] + b: object + c: object + * + d: object +[clinic start generated code]*/ + +static PyObject * +depr_star_pos1_len2_with_kwd_impl(PyObject *module, PyObject *a, PyObject *b, + PyObject *c, PyObject *d) +/*[clinic end generated code: output=3bccab672b7cfbb8 input=6bc7bd742fa8be15]*/ +{ + Py_RETURN_NONE; +} + + +/*[clinic input] +depr_star_pos2_len1 + a: object + b: object + * [from 3.14] + c: object +[clinic start generated code]*/ + +static PyObject * +depr_star_pos2_len1_impl(PyObject *module, PyObject *a, PyObject *b, + PyObject *c) +/*[clinic end generated code: output=20f5b230e9beeb70 input=5fc3e1790dec00d5]*/ +{ + Py_RETURN_NONE; +} + + +/*[clinic input] +depr_star_pos2_len2 + a: object + b: object + * [from 3.14] + c: object + d: object +[clinic start generated code]*/ + +static PyObject * +depr_star_pos2_len2_impl(PyObject *module, PyObject *a, PyObject *b, + PyObject *c, PyObject *d) +/*[clinic end generated code: output=9f90ed8fbce27d7a input=9cc8003b89d38779]*/ +{ + Py_RETURN_NONE; +} + + +/*[clinic input] +depr_star_pos2_len2_with_kwd + a: object + b: object + * [from 3.14] + c: object + d: object + * + e: object +[clinic start generated code]*/ + +static PyObject * +depr_star_pos2_len2_with_kwd_impl(PyObject *module, PyObject *a, PyObject *b, + PyObject *c, PyObject *d, PyObject *e) +/*[clinic end generated code: output=05432c4f20527215 input=831832d90534da91]*/ +{ + Py_RETURN_NONE; +} + + +/*[clinic input] +depr_star_noinline + a: object + * [from 3.14] + b: object + c: object = None + * + # Force to use _PyArg_ParseStackAndKeywords. + d: str(accept={str, robuffer}, zeroes=True) = '' +[clinic start generated code]*/ + +static PyObject * +depr_star_noinline_impl(PyObject *module, PyObject *a, PyObject *b, + PyObject *c, const char *d, Py_ssize_t d_length) +/*[clinic end generated code: output=cc27dacf5c2754af input=d36cc862a2daef98]*/ +{ + Py_RETURN_NONE; +} + + +/*[clinic input] +depr_star_multi + a: object + * [from 3.16] + b: object + * [from 3.15] + c: object + d: object + * [from 3.14] + e: object + f: object + g: object + * + h: object +[clinic start generated code]*/ + +static PyObject * +depr_star_multi_impl(PyObject *module, PyObject *a, PyObject *b, PyObject *c, + PyObject *d, PyObject *e, PyObject *f, PyObject *g, + PyObject *h) +/*[clinic end generated code: output=77681653f4202068 input=3ebd05d888a957ea]*/ +{ + Py_RETURN_NONE; +} + + +/*[clinic input] +depr_kwd_required_1 + a: object + / + b: object + / [from 3.14] +[clinic start generated code]*/ + +static PyObject * +depr_kwd_required_1_impl(PyObject *module, PyObject *a, PyObject *b) +/*[clinic end generated code: output=1d8ab19ea78418af input=53f2c398b828462d]*/ +{ + Py_RETURN_NONE; +} + + +/*[clinic input] +depr_kwd_required_2 + a: object + / + b: object + c: object + / [from 3.14] +[clinic start generated code]*/ + +static PyObject * +depr_kwd_required_2_impl(PyObject *module, PyObject *a, PyObject *b, + PyObject *c) +/*[clinic end generated code: output=44a89cb82509ddde input=a2b0ef37de8a01a7]*/ +{ + Py_RETURN_NONE; +} + + +/*[clinic input] +depr_kwd_optional_1 + a: object + / + b: object = None + / [from 3.14] +[clinic start generated code]*/ + +static PyObject * +depr_kwd_optional_1_impl(PyObject *module, PyObject *a, PyObject *b) +/*[clinic end generated code: output=a8a3d67efcc7b058 input=e416981eb78c3053]*/ +{ + Py_RETURN_NONE; +} + + +/*[clinic input] +depr_kwd_optional_2 + a: object + / + b: object = None + c: object = None + / [from 3.14] +[clinic start generated code]*/ + +static PyObject * +depr_kwd_optional_2_impl(PyObject *module, PyObject *a, PyObject *b, + PyObject *c) +/*[clinic end generated code: output=aa2d967f26fdb9f6 input=cae3afb783bfc855]*/ +{ + Py_RETURN_NONE; +} + + +/*[clinic input] +depr_kwd_optional_3 + a: object = None + b: object = None + c: object = None + / [from 3.14] +[clinic start generated code]*/ + +static PyObject * +depr_kwd_optional_3_impl(PyObject *module, PyObject *a, PyObject *b, + PyObject *c) +/*[clinic end generated code: output=a26025bf6118fd07 input=c9183b2f9ccaf992]*/ +{ + Py_RETURN_NONE; +} + + +/*[clinic input] +depr_kwd_required_optional + a: object + / + b: object + c: object = None + / [from 3.14] +[clinic start generated code]*/ + +static PyObject * +depr_kwd_required_optional_impl(PyObject *module, PyObject *a, PyObject *b, + PyObject *c) +/*[clinic end generated code: output=e53a8b7a250d8ffc input=23237a046f8388f5]*/ +{ + Py_RETURN_NONE; +} + + +/*[clinic input] +depr_kwd_noinline + a: object + / + b: object + c: object = None + / [from 3.14] + # Force to use _PyArg_ParseStackAndKeywords. + d: str(accept={str, robuffer}, zeroes=True) = '' +[clinic start generated code]*/ + +static PyObject * +depr_kwd_noinline_impl(PyObject *module, PyObject *a, PyObject *b, + PyObject *c, const char *d, Py_ssize_t d_length) +/*[clinic end generated code: output=f59da8113f2bad7c input=1d6db65bebb069d7]*/ +{ + Py_RETURN_NONE; +} + + +/*[clinic input] +depr_kwd_multi + a: object + / + b: object + / [from 3.14] + c: object + d: object + / [from 3.15] + e: object + f: object + g: object + / [from 3.16] + h: object +[clinic start generated code]*/ + +static PyObject * +depr_kwd_multi_impl(PyObject *module, PyObject *a, PyObject *b, PyObject *c, + PyObject *d, PyObject *e, PyObject *f, PyObject *g, + PyObject *h) +/*[clinic end generated code: output=ddfbde80fe1942e1 input=7a074e621c79efd7]*/ +{ + Py_RETURN_NONE; +} + + +/*[clinic input] +depr_multi + a: object + / + b: object + / [from 3.14] + c: object + / [from 3.15] + d: object + * [from 3.15] + e: object + * [from 3.14] + f: object + * + g: object +[clinic start generated code]*/ + +static PyObject * +depr_multi_impl(PyObject *module, PyObject *a, PyObject *b, PyObject *c, + PyObject *d, PyObject *e, PyObject *f, PyObject *g) +/*[clinic end generated code: output=f81c92852ca2d4ee input=5b847c5e44bedd02]*/ +{ + Py_RETURN_NONE; +} + + +// Reset PY_VERSION_HEX +#undef PY_VERSION_HEX +#define PY_VERSION_HEX _SAVED_PY_VERSION +#undef _SAVED_PY_VERSION + + +/*[clinic input] +output pop +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=e7c7c42daced52b0]*/ + static PyMethodDef tester_methods[] = { TEST_EMPTY_FUNCTION_METHODDEF OBJECTS_CONVERTER_METHODDEF @@ -1244,10 +1863,32 @@ static PyMethodDef tester_methods[] = { GH_32092_KW_PASS_METHODDEF GH_99233_REFCOUNT_METHODDEF GH_99240_DOUBLE_FREE_METHODDEF + NULL_OR_TUPLE_FOR_VARARGS_METHODDEF CLONE_F1_METHODDEF CLONE_F2_METHODDEF CLONE_WITH_CONV_F1_METHODDEF CLONE_WITH_CONV_F2_METHODDEF + + DEPR_STAR_POS0_LEN1_METHODDEF + DEPR_STAR_POS0_LEN2_METHODDEF + DEPR_STAR_POS0_LEN3_WITH_KWD_METHODDEF + DEPR_STAR_POS1_LEN1_OPT_METHODDEF + DEPR_STAR_POS1_LEN1_METHODDEF + DEPR_STAR_POS1_LEN2_WITH_KWD_METHODDEF + DEPR_STAR_POS2_LEN1_METHODDEF + DEPR_STAR_POS2_LEN2_METHODDEF + DEPR_STAR_POS2_LEN2_WITH_KWD_METHODDEF + DEPR_STAR_NOINLINE_METHODDEF + DEPR_STAR_MULTI_METHODDEF + DEPR_KWD_REQUIRED_1_METHODDEF + DEPR_KWD_REQUIRED_2_METHODDEF + DEPR_KWD_OPTIONAL_1_METHODDEF + DEPR_KWD_OPTIONAL_2_METHODDEF + DEPR_KWD_OPTIONAL_3_METHODDEF + DEPR_KWD_REQUIRED_OPTIONAL_METHODDEF + DEPR_KWD_NOINLINE_METHODDEF + DEPR_KWD_MULTI_METHODDEF + DEPR_MULTI_METHODDEF {NULL, NULL} }; @@ -1261,7 +1902,33 @@ static struct PyModuleDef _testclinic_module = { PyMODINIT_FUNC PyInit__testclinic(void) { - return PyModule_Create(&_testclinic_module); + PyObject *m = PyModule_Create(&_testclinic_module); + if (m == NULL) { + return NULL; + } + if (PyModule_AddType(m, &DeprStarNew) < 0) { + goto error; + } + if (PyModule_AddType(m, &DeprStarInit) < 0) { + goto error; + } + if (PyModule_AddType(m, &DeprStarInitNoInline) < 0) { + goto error; + } + if (PyModule_AddType(m, &DeprKwdNew) < 0) { + goto error; + } + if (PyModule_AddType(m, &DeprKwdInit) < 0) { + goto error; + } + if (PyModule_AddType(m, &DeprKwdInitNoInline) < 0) { + goto error; + } + return m; + +error: + Py_DECREF(m); + return NULL; } #undef RETURN_PACKED_ARGS diff --git a/Modules/_testclinic_limited.c b/Modules/_testclinic_limited.c new file mode 100644 index 00000000000000..ef595be0b626db --- /dev/null +++ b/Modules/_testclinic_limited.c @@ -0,0 +1,97 @@ +// _testclinic_limited can built with the Py_BUILD_CORE_BUILTIN macro defined +// if one of the Modules/Setup files asks to build it as "static" (gh-109723). +#undef Py_BUILD_CORE +#undef Py_BUILD_CORE_MODULE +#undef Py_BUILD_CORE_BUILTIN + +#include "pyconfig.h" // Py_GIL_DISABLED + +#ifndef Py_GIL_DISABLED +// For now, only limited C API 3.13 is supported +#define Py_LIMITED_API 0x030d0000 +#endif + +/* Always enable assertions */ +#undef NDEBUG + +#include "Python.h" + + +#include "clinic/_testclinic_limited.c.h" + + +/*[clinic input] +module _testclinic_limited +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=dd408149a4fc0dbb]*/ + + +/*[clinic input] +test_empty_function + +[clinic start generated code]*/ + +static PyObject * +test_empty_function_impl(PyObject *module) +/*[clinic end generated code: output=0f8aeb3ddced55cb input=0dd7048651ad4ae4]*/ +{ + Py_RETURN_NONE; +} + + +/*[clinic input] +my_int_func -> int + + arg: int + / + +[clinic start generated code]*/ + +static int +my_int_func_impl(PyObject *module, int arg) +/*[clinic end generated code: output=761cd54582f10e4f input=16eb8bba71d82740]*/ +{ + return arg; +} + + +/*[clinic input] +my_int_sum -> int + + x: int + y: int + / + +[clinic start generated code]*/ + +static int +my_int_sum_impl(PyObject *module, int x, int y) +/*[clinic end generated code: output=3e52db9ab5f37e2f input=0edb6796813bf2d3]*/ +{ + return x + y; +} + + +static PyMethodDef tester_methods[] = { + TEST_EMPTY_FUNCTION_METHODDEF + MY_INT_FUNC_METHODDEF + MY_INT_SUM_METHODDEF + {NULL, NULL} +}; + +static struct PyModuleDef _testclinic_module = { + PyModuleDef_HEAD_INIT, + .m_name = "_testclinic_limited", + .m_size = 0, + .m_methods = tester_methods, +}; + +PyMODINIT_FUNC +PyInit__testclinic_limited(void) +{ + PyObject *m = PyModule_Create(&_testclinic_module); + if (m == NULL) { + return NULL; + } + return m; +} diff --git a/Modules/_testimportmultiple.c b/Modules/_testimportmultiple.c index 1caeb66eb8c858..7e6556ad400cde 100644 --- a/Modules/_testimportmultiple.c +++ b/Modules/_testimportmultiple.c @@ -3,7 +3,14 @@ * file (issue16421). This file defines 3 modules (_testimportmodule, * foo, bar), only the first one is called the same as the compiled file. */ -#include + +#include "pyconfig.h" // Py_GIL_DISABLED + +#ifndef Py_GIL_DISABLED +#define Py_LIMITED_API 0x03020000 +#endif + +#include static struct PyModuleDef _testimportmultiple = { PyModuleDef_HEAD_INIT, @@ -54,4 +61,3 @@ static struct PyModuleDef _barmodule = { PyMODINIT_FUNC PyInit__testimportmultiple_bar(void){ return PyModule_Create(&_barmodule); } - diff --git a/Modules/_testinternalcapi.c b/Modules/_testinternalcapi.c index f28b46dd9846c8..7d277df164d3ec 100644 --- a/Modules/_testinternalcapi.c +++ b/Modules/_testinternalcapi.c @@ -10,31 +10,31 @@ #undef NDEBUG #include "Python.h" -#include "pycore_atomic_funcs.h" // _Py_atomic_int_get() -#include "pycore_bitutils.h" // _Py_bswap32() -#include "pycore_bytesobject.h" // _PyBytes_Find() -#include "pycore_compile.h" // _PyCompile_CodeGen, _PyCompile_OptimizeCfg, _PyCompile_Assemble, _PyCompile_CleanDoc -#include "pycore_ceval.h" // _PyEval_AddPendingCall -#include "pycore_fileutils.h" // _Py_normpath -#include "pycore_frame.h" // _PyInterpreterFrame -#include "pycore_gc.h" // PyGC_Head -#include "pycore_hashtable.h" // _Py_hashtable_new() -#include "pycore_initconfig.h" // _Py_GetConfigsAsDict() -#include "pycore_interp.h" // _PyInterpreterState_GetConfigCopy() -#include "pycore_object.h" // _PyObject_IsFreed() -#include "pycore_pathconfig.h" // _PyPathConfig_ClearGlobal() -#include "pycore_pyerrors.h" // _Py_UTF8_Edit_Cost() -#include "pycore_pystate.h" // _PyThreadState_GET() - -#include "frameobject.h" -#include "interpreteridobject.h" // PyInterpreterID_LookUp() -#include "osdefs.h" // MAXPATHLEN +#include "pycore_bitutils.h" // _Py_bswap32() +#include "pycore_bytesobject.h" // _PyBytes_Find() +#include "pycore_ceval.h" // _PyEval_AddPendingCall() +#include "pycore_compile.h" // _PyCompile_CodeGen() +#include "pycore_context.h" // _PyContext_NewHamtForTests() +#include "pycore_dict.h" // _PyDictOrValues_GetValues() +#include "pycore_fileutils.h" // _Py_normpath() +#include "pycore_frame.h" // _PyInterpreterFrame +#include "pycore_gc.h" // PyGC_Head +#include "pycore_hashtable.h" // _Py_hashtable_new() +#include "pycore_initconfig.h" // _Py_GetConfigsAsDict() +#include "pycore_interp.h" // _PyInterpreterState_GetConfigCopy() +#include "pycore_long.h" // _PyLong_Sign() +#include "pycore_object.h" // _PyObject_IsFreed() +#include "pycore_pathconfig.h" // _PyPathConfig_ClearGlobal() +#include "pycore_pyerrors.h" // _PyErr_ChainExceptions1() +#include "pycore_pystate.h" // _PyThreadState_GET() +#include "pycore_typeobject.h" // _PyType_GetModuleName() + +#include "interpreteridobject.h" // PyInterpreterID_LookUp() #include "clinic/_testinternalcapi.c.h" -#ifdef MS_WINDOWS -# include // struct timeval -#endif +// Include test definitions from _testinternalcapi/ +#include "_testinternalcapi/parts.h" #define MODULE_NAME "_testinternalcapi" @@ -110,6 +110,14 @@ get_recursion_depth(PyObject *self, PyObject *Py_UNUSED(args)) } +static PyObject* +get_c_recursion_remaining(PyObject *self, PyObject *Py_UNUSED(args)) +{ + PyThreadState *tstate = _PyThreadState_GET(); + return PyLong_FromLong(tstate->c_recursion_remaining); +} + + static PyObject* test_bswap(PyObject *self, PyObject *Py_UNUSED(args)) { @@ -350,17 +358,6 @@ test_reset_path_config(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(arg)) } -static PyObject* -test_atomic_funcs(PyObject *self, PyObject *Py_UNUSED(args)) -{ - // Test _Py_atomic_size_get() and _Py_atomic_size_set() - Py_ssize_t var = 1; - _Py_atomic_size_set(&var, 2); - assert(_Py_atomic_size_get(&var) == 2); - Py_RETURN_NONE; -} - - static int check_edit_cost(const char *a, const char *b, Py_ssize_t expected) { @@ -687,7 +684,11 @@ record_eval(PyThreadState *tstate, struct _PyInterpreterFrame *f, int exc) assert(module != NULL); module_state *state = get_module_state(module); Py_DECREF(module); - PyList_Append(state->record_list, ((PyFunctionObject *)f->f_funcobj)->func_name); + int res = PyList_Append(state->record_list, + ((PyFunctionObject *)f->f_funcobj)->func_name); + if (res < 0) { + return NULL; + } } return _PyEval_EvalFrameDefault(tstate, f, exc); } @@ -1010,6 +1011,32 @@ get_executor(PyObject *self, PyObject *const *args, Py_ssize_t nargs) return (PyObject *)PyUnstable_GetExecutor((PyCodeObject *)code, ioffset); } +static PyObject * +add_executor_dependency(PyObject *self, PyObject *args) +{ + PyObject *exec; + PyObject *obj; + if (!PyArg_ParseTuple(args, "OO", &exec, &obj)) { + return NULL; + } + /* No way to tell in general if exec is an executor, so we only accept + * counting_executor */ + if (strcmp(Py_TYPE(exec)->tp_name, "counting_executor")) { + PyErr_SetString(PyExc_TypeError, "argument must be a counting_executor"); + return NULL; + } + _Py_Executor_DependsOn((_PyExecutorObject *)exec, obj); + Py_RETURN_NONE; +} + +static PyObject * +invalidate_executors(PyObject *self, PyObject *obj) +{ + PyInterpreterState *interp = PyInterpreterState_Get(); + _Py_Executors_InvalidateDependency(interp, obj); + Py_RETURN_NONE; +} + static int _pending_callback(void *arg) { /* we assume the argument is callable object to which we own a reference */ @@ -1122,250 +1149,6 @@ pending_identify(PyObject *self, PyObject *args) return res; } - -static PyObject * -test_pytime_fromseconds(PyObject *self, PyObject *args) -{ - int seconds; - if (!PyArg_ParseTuple(args, "i", &seconds)) { - return NULL; - } - _PyTime_t ts = _PyTime_FromSeconds(seconds); - return _PyTime_AsNanosecondsObject(ts); -} - -static int -check_time_rounding(int round) -{ - if (round != _PyTime_ROUND_FLOOR - && round != _PyTime_ROUND_CEILING - && round != _PyTime_ROUND_HALF_EVEN - && round != _PyTime_ROUND_UP) - { - PyErr_SetString(PyExc_ValueError, "invalid rounding"); - return -1; - } - return 0; -} - -static PyObject * -test_pytime_fromsecondsobject(PyObject *self, PyObject *args) -{ - PyObject *obj; - int round; - if (!PyArg_ParseTuple(args, "Oi", &obj, &round)) { - return NULL; - } - if (check_time_rounding(round) < 0) { - return NULL; - } - _PyTime_t ts; - if (_PyTime_FromSecondsObject(&ts, obj, round) == -1) { - return NULL; - } - return _PyTime_AsNanosecondsObject(ts); -} - -static PyObject * -test_pytime_assecondsdouble(PyObject *self, PyObject *args) -{ - PyObject *obj; - if (!PyArg_ParseTuple(args, "O", &obj)) { - return NULL; - } - _PyTime_t ts; - if (_PyTime_FromNanosecondsObject(&ts, obj) < 0) { - return NULL; - } - double d = _PyTime_AsSecondsDouble(ts); - return PyFloat_FromDouble(d); -} - -static PyObject * -test_PyTime_AsTimeval(PyObject *self, PyObject *args) -{ - PyObject *obj; - int round; - if (!PyArg_ParseTuple(args, "Oi", &obj, &round)) { - return NULL; - } - if (check_time_rounding(round) < 0) { - return NULL; - } - _PyTime_t t; - if (_PyTime_FromNanosecondsObject(&t, obj) < 0) { - return NULL; - } - struct timeval tv; - if (_PyTime_AsTimeval(t, &tv, round) < 0) { - return NULL; - } - - PyObject *seconds = PyLong_FromLongLong(tv.tv_sec); - if (seconds == NULL) { - return NULL; - } - return Py_BuildValue("Nl", seconds, (long)tv.tv_usec); -} - -static PyObject * -test_PyTime_AsTimeval_clamp(PyObject *self, PyObject *args) -{ - PyObject *obj; - int round; - if (!PyArg_ParseTuple(args, "Oi", &obj, &round)) { - return NULL; - } - if (check_time_rounding(round) < 0) { - return NULL; - } - _PyTime_t t; - if (_PyTime_FromNanosecondsObject(&t, obj) < 0) { - return NULL; - } - struct timeval tv; - _PyTime_AsTimeval_clamp(t, &tv, round); - - PyObject *seconds = PyLong_FromLongLong(tv.tv_sec); - if (seconds == NULL) { - return NULL; - } - return Py_BuildValue("Nl", seconds, (long)tv.tv_usec); -} - -#ifdef HAVE_CLOCK_GETTIME -static PyObject * -test_PyTime_AsTimespec(PyObject *self, PyObject *args) -{ - PyObject *obj; - if (!PyArg_ParseTuple(args, "O", &obj)) { - return NULL; - } - _PyTime_t t; - if (_PyTime_FromNanosecondsObject(&t, obj) < 0) { - return NULL; - } - struct timespec ts; - if (_PyTime_AsTimespec(t, &ts) == -1) { - return NULL; - } - return Py_BuildValue("Nl", _PyLong_FromTime_t(ts.tv_sec), ts.tv_nsec); -} - -static PyObject * -test_PyTime_AsTimespec_clamp(PyObject *self, PyObject *args) -{ - PyObject *obj; - if (!PyArg_ParseTuple(args, "O", &obj)) { - return NULL; - } - _PyTime_t t; - if (_PyTime_FromNanosecondsObject(&t, obj) < 0) { - return NULL; - } - struct timespec ts; - _PyTime_AsTimespec_clamp(t, &ts); - return Py_BuildValue("Nl", _PyLong_FromTime_t(ts.tv_sec), ts.tv_nsec); -} -#endif - -static PyObject * -test_PyTime_AsMilliseconds(PyObject *self, PyObject *args) -{ - PyObject *obj; - int round; - if (!PyArg_ParseTuple(args, "Oi", &obj, &round)) { - return NULL; - } - _PyTime_t t; - if (_PyTime_FromNanosecondsObject(&t, obj) < 0) { - return NULL; - } - if (check_time_rounding(round) < 0) { - return NULL; - } - _PyTime_t ms = _PyTime_AsMilliseconds(t, round); - _PyTime_t ns = _PyTime_FromNanoseconds(ms); - return _PyTime_AsNanosecondsObject(ns); -} - -static PyObject * -test_PyTime_AsMicroseconds(PyObject *self, PyObject *args) -{ - PyObject *obj; - int round; - if (!PyArg_ParseTuple(args, "Oi", &obj, &round)) { - return NULL; - } - _PyTime_t t; - if (_PyTime_FromNanosecondsObject(&t, obj) < 0) { - return NULL; - } - if (check_time_rounding(round) < 0) { - return NULL; - } - _PyTime_t us = _PyTime_AsMicroseconds(t, round); - _PyTime_t ns = _PyTime_FromNanoseconds(us); - return _PyTime_AsNanosecondsObject(ns); -} - -static PyObject * -test_pytime_object_to_time_t(PyObject *self, PyObject *args) -{ - PyObject *obj; - time_t sec; - int round; - if (!PyArg_ParseTuple(args, "Oi", &obj, &round)) { - return NULL; - } - if (check_time_rounding(round) < 0) { - return NULL; - } - if (_PyTime_ObjectToTime_t(obj, &sec, round) == -1) { - return NULL; - } - return _PyLong_FromTime_t(sec); -} - -static PyObject * -test_pytime_object_to_timeval(PyObject *self, PyObject *args) -{ - PyObject *obj; - time_t sec; - long usec; - int round; - if (!PyArg_ParseTuple(args, "Oi", &obj, &round)) { - return NULL; - } - if (check_time_rounding(round) < 0) { - return NULL; - } - if (_PyTime_ObjectToTimeval(obj, &sec, &usec, round) == -1) { - return NULL; - } - return Py_BuildValue("Nl", _PyLong_FromTime_t(sec), usec); -} - -static PyObject * -test_pytime_object_to_timespec(PyObject *self, PyObject *args) -{ - PyObject *obj; - time_t sec; - long nsec; - int round; - if (!PyArg_ParseTuple(args, "Oi", &obj, &round)) { - return NULL; - } - if (check_time_rounding(round) < 0) { - return NULL; - } - if (_PyTime_ObjectToTimespec(obj, &sec, &nsec, round) == -1) { - return NULL; - } - return Py_BuildValue("Nl", _PyLong_FromTime_t(sec), nsec); -} - - static PyObject * tracemalloc_get_traceback(PyObject *self, PyObject *args) { @@ -1530,10 +1313,344 @@ test_pymem_getallocatorsname(PyObject *self, PyObject *args) return PyUnicode_FromString(name); } +static PyObject * +get_object_dict_values(PyObject *self, PyObject *obj) +{ + PyTypeObject *type = Py_TYPE(obj); + if (!_PyType_HasFeature(type, Py_TPFLAGS_MANAGED_DICT)) { + Py_RETURN_NONE; + } + PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(obj); + if (!_PyDictOrValues_IsValues(dorv)) { + Py_RETURN_NONE; + } + PyDictValues *values = _PyDictOrValues_GetValues(dorv); + PyDictKeysObject *keys = ((PyHeapTypeObject *)type)->ht_cached_keys; + assert(keys != NULL); + int size = (int)keys->dk_nentries; + assert(size >= 0); + PyObject *res = PyTuple_New(size); + if (res == NULL) { + return NULL; + } + _Py_DECLARE_STR(anon_null, ""); + for(int i = 0; i < size; i++) { + PyObject *item = values->values[i]; + if (item == NULL) { + item = &_Py_STR(anon_null); + } + else { + Py_INCREF(item); + } + PyTuple_SET_ITEM(res, i, item); + } + return res; +} + + +static PyObject* +new_hamt(PyObject *self, PyObject *args) +{ + return _PyContext_NewHamtForTests(); +} + + +static PyObject* +dict_getitem_knownhash(PyObject *self, PyObject *args) +{ + PyObject *mp, *key, *result; + Py_ssize_t hash; + + if (!PyArg_ParseTuple(args, "OOn:dict_getitem_knownhash", + &mp, &key, &hash)) { + return NULL; + } + + result = _PyDict_GetItem_KnownHash(mp, key, (Py_hash_t)hash); + if (result == NULL && !PyErr_Occurred()) { + _PyErr_SetKeyError(key); + return NULL; + } + + return Py_XNewRef(result); +} + + +/* To run some code in a sub-interpreter. */ +static PyObject * +run_in_subinterp_with_config(PyObject *self, PyObject *args, PyObject *kwargs) +{ + const char *code; + int use_main_obmalloc = -1; + int allow_fork = -1; + int allow_exec = -1; + int allow_threads = -1; + int allow_daemon_threads = -1; + int check_multi_interp_extensions = -1; + int gil = -1; + int r; + PyThreadState *substate, *mainstate; + /* only initialise 'cflags.cf_flags' to test backwards compatibility */ + PyCompilerFlags cflags = {0}; + + static char *kwlist[] = {"code", + "use_main_obmalloc", + "allow_fork", + "allow_exec", + "allow_threads", + "allow_daemon_threads", + "check_multi_interp_extensions", + "gil", + NULL}; + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "s$ppppppi:run_in_subinterp_with_config", kwlist, + &code, &use_main_obmalloc, + &allow_fork, &allow_exec, + &allow_threads, &allow_daemon_threads, + &check_multi_interp_extensions, + &gil)) { + return NULL; + } + if (use_main_obmalloc < 0) { + PyErr_SetString(PyExc_ValueError, "missing use_main_obmalloc"); + return NULL; + } + if (allow_fork < 0) { + PyErr_SetString(PyExc_ValueError, "missing allow_fork"); + return NULL; + } + if (allow_exec < 0) { + PyErr_SetString(PyExc_ValueError, "missing allow_exec"); + return NULL; + } + if (allow_threads < 0) { + PyErr_SetString(PyExc_ValueError, "missing allow_threads"); + return NULL; + } + if (gil < 0) { + PyErr_SetString(PyExc_ValueError, "missing gil"); + return NULL; + } + if (allow_daemon_threads < 0) { + PyErr_SetString(PyExc_ValueError, "missing allow_daemon_threads"); + return NULL; + } + if (check_multi_interp_extensions < 0) { + PyErr_SetString(PyExc_ValueError, "missing check_multi_interp_extensions"); + return NULL; + } + + mainstate = PyThreadState_Get(); + + PyThreadState_Swap(NULL); + + const PyInterpreterConfig config = { + .use_main_obmalloc = use_main_obmalloc, + .allow_fork = allow_fork, + .allow_exec = allow_exec, + .allow_threads = allow_threads, + .allow_daemon_threads = allow_daemon_threads, + .check_multi_interp_extensions = check_multi_interp_extensions, + .gil = gil, + }; + PyStatus status = Py_NewInterpreterFromConfig(&substate, &config); + if (PyStatus_Exception(status)) { + /* Since no new thread state was created, there is no exception to + propagate; raise a fresh one after swapping in the old thread + state. */ + PyThreadState_Swap(mainstate); + _PyErr_SetFromPyStatus(status); + PyObject *exc = PyErr_GetRaisedException(); + PyErr_SetString(PyExc_RuntimeError, "sub-interpreter creation failed"); + _PyErr_ChainExceptions1(exc); + return NULL; + } + assert(substate != NULL); + r = PyRun_SimpleStringFlags(code, &cflags); + Py_EndInterpreter(substate); + + PyThreadState_Swap(mainstate); + + return PyLong_FromLong(r); +} + + +static PyObject * +get_interpreter_refcount(PyObject *self, PyObject *idobj) +{ + PyInterpreterState *interp = PyInterpreterID_LookUp(idobj); + if (interp == NULL) { + return NULL; + } + return PyLong_FromLongLong(interp->id_refcount); +} + + +static void +_xid_capsule_destructor(PyObject *capsule) +{ + _PyCrossInterpreterData *data = \ + (_PyCrossInterpreterData *)PyCapsule_GetPointer(capsule, NULL); + if (data != NULL) { + assert(_PyCrossInterpreterData_Release(data) == 0); + _PyCrossInterpreterData_Free(data); + } +} + +static PyObject * +get_crossinterp_data(PyObject *self, PyObject *args) +{ + PyObject *obj = NULL; + if (!PyArg_ParseTuple(args, "O:get_crossinterp_data", &obj)) { + return NULL; + } + + _PyCrossInterpreterData *data = _PyCrossInterpreterData_New(); + if (data == NULL) { + return NULL; + } + if (_PyObject_GetCrossInterpreterData(obj, data) != 0) { + _PyCrossInterpreterData_Free(data); + return NULL; + } + PyObject *capsule = PyCapsule_New(data, NULL, _xid_capsule_destructor); + if (capsule == NULL) { + assert(_PyCrossInterpreterData_Release(data) == 0); + _PyCrossInterpreterData_Free(data); + } + return capsule; +} + +static PyObject * +restore_crossinterp_data(PyObject *self, PyObject *args) +{ + PyObject *capsule = NULL; + if (!PyArg_ParseTuple(args, "O:restore_crossinterp_data", &capsule)) { + return NULL; + } + + _PyCrossInterpreterData *data = \ + (_PyCrossInterpreterData *)PyCapsule_GetPointer(capsule, NULL); + if (data == NULL) { + return NULL; + } + return _PyCrossInterpreterData_NewObject(data); +} + + +static PyObject * +raiseTestError(const char* test_name, const char* msg) +{ + PyErr_Format(PyExc_AssertionError, "%s: %s", test_name, msg); + return NULL; +} + + +/*[clinic input] +_testinternalcapi.test_long_numbits +[clinic start generated code]*/ + +static PyObject * +_testinternalcapi_test_long_numbits_impl(PyObject *module) +/*[clinic end generated code: output=745d62d120359434 input=f14ca6f638e44dad]*/ +{ + struct triple { + long input; + size_t nbits; + int sign; + } testcases[] = {{0, 0, 0}, + {1L, 1, 1}, + {-1L, 1, -1}, + {2L, 2, 1}, + {-2L, 2, -1}, + {3L, 2, 1}, + {-3L, 2, -1}, + {4L, 3, 1}, + {-4L, 3, -1}, + {0x7fffL, 15, 1}, /* one Python int digit */ + {-0x7fffL, 15, -1}, + {0xffffL, 16, 1}, + {-0xffffL, 16, -1}, + {0xfffffffL, 28, 1}, + {-0xfffffffL, 28, -1}}; + size_t i; + + for (i = 0; i < Py_ARRAY_LENGTH(testcases); ++i) { + size_t nbits; + int sign; + PyObject *plong; + + plong = PyLong_FromLong(testcases[i].input); + if (plong == NULL) + return NULL; + nbits = _PyLong_NumBits(plong); + sign = _PyLong_Sign(plong); + + Py_DECREF(plong); + if (nbits != testcases[i].nbits) + return raiseTestError("test_long_numbits", + "wrong result for _PyLong_NumBits"); + if (sign != testcases[i].sign) + return raiseTestError("test_long_numbits", + "wrong result for _PyLong_Sign"); + } + Py_RETURN_NONE; +} + +static PyObject * +compile_perf_trampoline_entry(PyObject *self, PyObject *args) +{ + PyObject *co; + if (!PyArg_ParseTuple(args, "O!", &PyCode_Type, &co)) { + return NULL; + } + int ret = PyUnstable_PerfTrampoline_CompileCode((PyCodeObject *)co); + if (ret != 0) { + PyErr_SetString(PyExc_AssertionError, "Failed to compile trampoline"); + return NULL; + } + return PyLong_FromLong(ret); +} + +static PyObject * +perf_trampoline_set_persist_after_fork(PyObject *self, PyObject *args) +{ + int enable; + if (!PyArg_ParseTuple(args, "i", &enable)) { + return NULL; + } + int ret = PyUnstable_PerfTrampoline_SetPersistAfterFork(enable); + if (ret == 0) { + PyErr_SetString(PyExc_AssertionError, "Failed to set persist_after_fork"); + return NULL; + } + return PyLong_FromLong(ret); +} + + +static PyObject * +get_type_module_name(PyObject *self, PyObject *type) +{ + assert(PyType_Check(type)); + return _PyType_GetModuleName((PyTypeObject *)type); +} + + +#ifdef Py_GIL_DISABLED +static PyObject * +get_py_thread_id(PyObject *self, PyObject *Py_UNUSED(ignored)) +{ + uintptr_t tid = _Py_ThreadId(); + Py_BUILD_ASSERT(sizeof(unsigned long long) >= sizeof(tid)); + return PyLong_FromUnsignedLongLong(tid); +} +#endif + static PyMethodDef module_functions[] = { {"get_configs", get_configs, METH_NOARGS}, {"get_recursion_depth", get_recursion_depth, METH_NOARGS}, + {"get_c_recursion_remaining", get_c_recursion_remaining, METH_NOARGS}, {"test_bswap", test_bswap, METH_NOARGS}, {"test_popcount", test_popcount, METH_NOARGS}, {"test_bit_length", test_bit_length, METH_NOARGS}, @@ -1541,7 +1658,6 @@ static PyMethodDef module_functions[] = { {"get_config", test_get_config, METH_NOARGS}, {"set_config", test_set_config, METH_O}, {"reset_path_config", test_reset_path_config, METH_NOARGS}, - {"test_atomic_funcs", test_atomic_funcs, METH_NOARGS}, {"test_edit_cost", test_edit_cost, METH_NOARGS}, {"test_bytes_find", test_bytes_find, METH_NOARGS}, {"normalize_path", normalize_path, METH_O, NULL}, @@ -1566,23 +1682,11 @@ static PyMethodDef module_functions[] = { {"get_executor", _PyCFunction_CAST(get_executor), METH_FASTCALL, NULL}, {"get_counter_optimizer", get_counter_optimizer, METH_NOARGS, NULL}, {"get_uop_optimizer", get_uop_optimizer, METH_NOARGS, NULL}, + {"add_executor_dependency", add_executor_dependency, METH_VARARGS, NULL}, + {"invalidate_executors", invalidate_executors, METH_O, NULL}, {"pending_threadfunc", _PyCFunction_CAST(pending_threadfunc), METH_VARARGS | METH_KEYWORDS}, {"pending_identify", pending_identify, METH_VARARGS, NULL}, - {"_PyTime_AsMicroseconds", test_PyTime_AsMicroseconds, METH_VARARGS}, - {"_PyTime_AsMilliseconds", test_PyTime_AsMilliseconds, METH_VARARGS}, - {"_PyTime_AsSecondsDouble", test_pytime_assecondsdouble, METH_VARARGS}, -#ifdef HAVE_CLOCK_GETTIME - {"_PyTime_AsTimespec", test_PyTime_AsTimespec, METH_VARARGS}, - {"_PyTime_AsTimespec_clamp", test_PyTime_AsTimespec_clamp, METH_VARARGS}, -#endif - {"_PyTime_AsTimeval", test_PyTime_AsTimeval, METH_VARARGS}, - {"_PyTime_AsTimeval_clamp", test_PyTime_AsTimeval_clamp, METH_VARARGS}, - {"_PyTime_FromSeconds", test_pytime_fromseconds, METH_VARARGS}, - {"_PyTime_FromSecondsObject", test_pytime_fromsecondsobject, METH_VARARGS}, - {"_PyTime_ObjectToTime_t", test_pytime_object_to_time_t, METH_VARARGS}, - {"_PyTime_ObjectToTimespec", test_pytime_object_to_timespec, METH_VARARGS}, - {"_PyTime_ObjectToTimeval", test_pytime_object_to_timeval, METH_VARARGS}, {"_PyTraceMalloc_GetTraceback", tracemalloc_get_traceback, METH_VARARGS}, {"test_tstate_capi", test_tstate_capi, METH_NOARGS, NULL}, {"_PyUnicode_TransformDecimalAndSpaceToASCII", unicode_transformdecimalandspacetoascii, METH_O}, @@ -1594,6 +1698,22 @@ static PyMethodDef module_functions[] = { {"check_pyobject_uninitialized_is_freed", check_pyobject_uninitialized_is_freed, METH_NOARGS}, {"pymem_getallocatorsname", test_pymem_getallocatorsname, METH_NOARGS}, + {"get_object_dict_values", get_object_dict_values, METH_O}, + {"hamt", new_hamt, METH_NOARGS}, + {"dict_getitem_knownhash", dict_getitem_knownhash, METH_VARARGS}, + {"run_in_subinterp_with_config", + _PyCFunction_CAST(run_in_subinterp_with_config), + METH_VARARGS | METH_KEYWORDS}, + {"get_interpreter_refcount", get_interpreter_refcount, METH_O}, + {"compile_perf_trampoline_entry", compile_perf_trampoline_entry, METH_VARARGS}, + {"perf_trampoline_set_persist_after_fork", perf_trampoline_set_persist_after_fork, METH_VARARGS}, + {"get_crossinterp_data", get_crossinterp_data, METH_VARARGS}, + {"restore_crossinterp_data", restore_crossinterp_data, METH_VARARGS}, + _TESTINTERNALCAPI_TEST_LONG_NUMBITS_METHODDEF + {"get_type_module_name", get_type_module_name, METH_O}, +#ifdef Py_GIL_DISABLED + {"py_thread_id", get_py_thread_id, METH_NOARGS}, +#endif {NULL, NULL} /* sentinel */ }; @@ -1603,11 +1723,29 @@ static PyMethodDef module_functions[] = { static int module_exec(PyObject *module) { + if (_PyTestInternalCapi_Init_Lock(module) < 0) { + return 1; + } + if (_PyTestInternalCapi_Init_PyTime(module) < 0) { + return 1; + } + if (_PyTestInternalCapi_Init_Set(module) < 0) { + return 1; + } + if (_PyTestInternalCapi_Init_CriticalSection(module) < 0) { + return 1; + } + if (PyModule_Add(module, "SIZEOF_PYGC_HEAD", PyLong_FromSsize_t(sizeof(PyGC_Head))) < 0) { return 1; } + if (PyModule_Add(module, "SIZEOF_PYOBJECT", + PyLong_FromSsize_t(sizeof(PyObject))) < 0) { + return 1; + } + if (PyModule_Add(module, "SIZEOF_TIME_T", PyLong_FromSsize_t(sizeof(time_t))) < 0) { return 1; diff --git a/Modules/_testinternalcapi/README.txt b/Modules/_testinternalcapi/README.txt new file mode 100644 index 00000000000000..eb071135e4c592 --- /dev/null +++ b/Modules/_testinternalcapi/README.txt @@ -0,0 +1,5 @@ +Tests in this directory are compiled into the _testinternalcapi extension. +The main file for the extension is Modules/_testinternalcapimodule.c, which +calls `_PyTestInternalCapi_Init_*` from these functions. + +See Modules/_testcapi/README.txt for guideline when writing C test code. \ No newline at end of file diff --git a/Modules/_testinternalcapi/clinic/test_lock.c.h b/Modules/_testinternalcapi/clinic/test_lock.c.h new file mode 100644 index 00000000000000..86875767343cd2 --- /dev/null +++ b/Modules/_testinternalcapi/clinic/test_lock.c.h @@ -0,0 +1,75 @@ +/*[clinic input] +preserve +[clinic start generated code]*/ + +#include "pycore_abstract.h" // _PyNumber_Index() +#include "pycore_modsupport.h" // _PyArg_CheckPositional() + +PyDoc_STRVAR(_testinternalcapi_benchmark_locks__doc__, +"benchmark_locks($module, num_threads, use_pymutex=True,\n" +" critical_section_length=1, time_ms=1000, /)\n" +"--\n" +"\n"); + +#define _TESTINTERNALCAPI_BENCHMARK_LOCKS_METHODDEF \ + {"benchmark_locks", _PyCFunction_CAST(_testinternalcapi_benchmark_locks), METH_FASTCALL, _testinternalcapi_benchmark_locks__doc__}, + +static PyObject * +_testinternalcapi_benchmark_locks_impl(PyObject *module, + Py_ssize_t num_threads, + int use_pymutex, + int critical_section_length, + int time_ms); + +static PyObject * +_testinternalcapi_benchmark_locks(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + Py_ssize_t num_threads; + int use_pymutex = 1; + int critical_section_length = 1; + int time_ms = 1000; + + if (!_PyArg_CheckPositional("benchmark_locks", nargs, 1, 4)) { + goto exit; + } + { + Py_ssize_t ival = -1; + PyObject *iobj = _PyNumber_Index(args[0]); + if (iobj != NULL) { + ival = PyLong_AsSsize_t(iobj); + Py_DECREF(iobj); + } + if (ival == -1 && PyErr_Occurred()) { + goto exit; + } + num_threads = ival; + } + if (nargs < 2) { + goto skip_optional; + } + use_pymutex = PyObject_IsTrue(args[1]); + if (use_pymutex < 0) { + goto exit; + } + if (nargs < 3) { + goto skip_optional; + } + critical_section_length = PyLong_AsInt(args[2]); + if (critical_section_length == -1 && PyErr_Occurred()) { + goto exit; + } + if (nargs < 4) { + goto skip_optional; + } + time_ms = PyLong_AsInt(args[3]); + if (time_ms == -1 && PyErr_Occurred()) { + goto exit; + } +skip_optional: + return_value = _testinternalcapi_benchmark_locks_impl(module, num_threads, use_pymutex, critical_section_length, time_ms); + +exit: + return return_value; +} +/*[clinic end generated code: output=105105d759c0c271 input=a9049054013a1b77]*/ diff --git a/Modules/_testinternalcapi/parts.h b/Modules/_testinternalcapi/parts.h new file mode 100644 index 00000000000000..49a1395f499fc3 --- /dev/null +++ b/Modules/_testinternalcapi/parts.h @@ -0,0 +1,18 @@ +#ifndef Py_TESTINTERNALCAPI_PARTS_H +#define Py_TESTINTERNALCAPI_PARTS_H + +// Always enable assertions +#undef NDEBUG + +#ifndef Py_BUILD_CORE_BUILTIN +# define Py_BUILD_CORE_MODULE 1 +#endif + +#include "Python.h" + +int _PyTestInternalCapi_Init_Lock(PyObject *module); +int _PyTestInternalCapi_Init_PyTime(PyObject *module); +int _PyTestInternalCapi_Init_Set(PyObject *module); +int _PyTestInternalCapi_Init_CriticalSection(PyObject *module); + +#endif // Py_TESTINTERNALCAPI_PARTS_H diff --git a/Modules/_testinternalcapi/pytime.c b/Modules/_testinternalcapi/pytime.c new file mode 100644 index 00000000000000..2b5f9eb0ef2851 --- /dev/null +++ b/Modules/_testinternalcapi/pytime.c @@ -0,0 +1,279 @@ +/* Test pycore_time.h */ + +#include "parts.h" + +#include "pycore_time.h" + +#ifdef MS_WINDOWS +# include // struct timeval +#endif + + +static PyObject * +test_pytime_fromseconds(PyObject *self, PyObject *args) +{ + int seconds; + if (!PyArg_ParseTuple(args, "i", &seconds)) { + return NULL; + } + _PyTime_t ts = _PyTime_FromSeconds(seconds); + return _PyTime_AsNanosecondsObject(ts); +} + +static int +check_time_rounding(int round) +{ + if (round != _PyTime_ROUND_FLOOR + && round != _PyTime_ROUND_CEILING + && round != _PyTime_ROUND_HALF_EVEN + && round != _PyTime_ROUND_UP) + { + PyErr_SetString(PyExc_ValueError, "invalid rounding"); + return -1; + } + return 0; +} + +static PyObject * +test_pytime_fromsecondsobject(PyObject *self, PyObject *args) +{ + PyObject *obj; + int round; + if (!PyArg_ParseTuple(args, "Oi", &obj, &round)) { + return NULL; + } + if (check_time_rounding(round) < 0) { + return NULL; + } + _PyTime_t ts; + if (_PyTime_FromSecondsObject(&ts, obj, round) == -1) { + return NULL; + } + return _PyTime_AsNanosecondsObject(ts); +} + +static PyObject * +test_pytime_assecondsdouble(PyObject *self, PyObject *args) +{ + PyObject *obj; + if (!PyArg_ParseTuple(args, "O", &obj)) { + return NULL; + } + _PyTime_t ts; + if (_PyTime_FromNanosecondsObject(&ts, obj) < 0) { + return NULL; + } + double d = _PyTime_AsSecondsDouble(ts); + return PyFloat_FromDouble(d); +} + +static PyObject * +test_PyTime_AsTimeval(PyObject *self, PyObject *args) +{ + PyObject *obj; + int round; + if (!PyArg_ParseTuple(args, "Oi", &obj, &round)) { + return NULL; + } + if (check_time_rounding(round) < 0) { + return NULL; + } + _PyTime_t t; + if (_PyTime_FromNanosecondsObject(&t, obj) < 0) { + return NULL; + } + struct timeval tv; + if (_PyTime_AsTimeval(t, &tv, round) < 0) { + return NULL; + } + + PyObject *seconds = PyLong_FromLongLong(tv.tv_sec); + if (seconds == NULL) { + return NULL; + } + return Py_BuildValue("Nl", seconds, (long)tv.tv_usec); +} + +static PyObject * +test_PyTime_AsTimeval_clamp(PyObject *self, PyObject *args) +{ + PyObject *obj; + int round; + if (!PyArg_ParseTuple(args, "Oi", &obj, &round)) { + return NULL; + } + if (check_time_rounding(round) < 0) { + return NULL; + } + _PyTime_t t; + if (_PyTime_FromNanosecondsObject(&t, obj) < 0) { + return NULL; + } + struct timeval tv; + _PyTime_AsTimeval_clamp(t, &tv, round); + + PyObject *seconds = PyLong_FromLongLong(tv.tv_sec); + if (seconds == NULL) { + return NULL; + } + return Py_BuildValue("Nl", seconds, (long)tv.tv_usec); +} + +#ifdef HAVE_CLOCK_GETTIME +static PyObject * +test_PyTime_AsTimespec(PyObject *self, PyObject *args) +{ + PyObject *obj; + if (!PyArg_ParseTuple(args, "O", &obj)) { + return NULL; + } + _PyTime_t t; + if (_PyTime_FromNanosecondsObject(&t, obj) < 0) { + return NULL; + } + struct timespec ts; + if (_PyTime_AsTimespec(t, &ts) == -1) { + return NULL; + } + return Py_BuildValue("Nl", _PyLong_FromTime_t(ts.tv_sec), ts.tv_nsec); +} + +static PyObject * +test_PyTime_AsTimespec_clamp(PyObject *self, PyObject *args) +{ + PyObject *obj; + if (!PyArg_ParseTuple(args, "O", &obj)) { + return NULL; + } + _PyTime_t t; + if (_PyTime_FromNanosecondsObject(&t, obj) < 0) { + return NULL; + } + struct timespec ts; + _PyTime_AsTimespec_clamp(t, &ts); + return Py_BuildValue("Nl", _PyLong_FromTime_t(ts.tv_sec), ts.tv_nsec); +} +#endif + +static PyObject * +test_PyTime_AsMilliseconds(PyObject *self, PyObject *args) +{ + PyObject *obj; + int round; + if (!PyArg_ParseTuple(args, "Oi", &obj, &round)) { + return NULL; + } + _PyTime_t t; + if (_PyTime_FromNanosecondsObject(&t, obj) < 0) { + return NULL; + } + if (check_time_rounding(round) < 0) { + return NULL; + } + _PyTime_t ms = _PyTime_AsMilliseconds(t, round); + _PyTime_t ns = _PyTime_FromNanoseconds(ms); + return _PyTime_AsNanosecondsObject(ns); +} + +static PyObject * +test_PyTime_AsMicroseconds(PyObject *self, PyObject *args) +{ + PyObject *obj; + int round; + if (!PyArg_ParseTuple(args, "Oi", &obj, &round)) { + return NULL; + } + _PyTime_t t; + if (_PyTime_FromNanosecondsObject(&t, obj) < 0) { + return NULL; + } + if (check_time_rounding(round) < 0) { + return NULL; + } + _PyTime_t us = _PyTime_AsMicroseconds(t, round); + _PyTime_t ns = _PyTime_FromNanoseconds(us); + return _PyTime_AsNanosecondsObject(ns); +} + +static PyObject * +test_pytime_object_to_time_t(PyObject *self, PyObject *args) +{ + PyObject *obj; + time_t sec; + int round; + if (!PyArg_ParseTuple(args, "Oi", &obj, &round)) { + return NULL; + } + if (check_time_rounding(round) < 0) { + return NULL; + } + if (_PyTime_ObjectToTime_t(obj, &sec, round) == -1) { + return NULL; + } + return _PyLong_FromTime_t(sec); +} + +static PyObject * +test_pytime_object_to_timeval(PyObject *self, PyObject *args) +{ + PyObject *obj; + time_t sec; + long usec; + int round; + if (!PyArg_ParseTuple(args, "Oi", &obj, &round)) { + return NULL; + } + if (check_time_rounding(round) < 0) { + return NULL; + } + if (_PyTime_ObjectToTimeval(obj, &sec, &usec, round) == -1) { + return NULL; + } + return Py_BuildValue("Nl", _PyLong_FromTime_t(sec), usec); +} + +static PyObject * +test_pytime_object_to_timespec(PyObject *self, PyObject *args) +{ + PyObject *obj; + time_t sec; + long nsec; + int round; + if (!PyArg_ParseTuple(args, "Oi", &obj, &round)) { + return NULL; + } + if (check_time_rounding(round) < 0) { + return NULL; + } + if (_PyTime_ObjectToTimespec(obj, &sec, &nsec, round) == -1) { + return NULL; + } + return Py_BuildValue("Nl", _PyLong_FromTime_t(sec), nsec); +} + +static PyMethodDef TestMethods[] = { + {"_PyTime_AsMicroseconds", test_PyTime_AsMicroseconds, METH_VARARGS}, + {"_PyTime_AsMilliseconds", test_PyTime_AsMilliseconds, METH_VARARGS}, + {"_PyTime_AsSecondsDouble", test_pytime_assecondsdouble, METH_VARARGS}, +#ifdef HAVE_CLOCK_GETTIME + {"_PyTime_AsTimespec", test_PyTime_AsTimespec, METH_VARARGS}, + {"_PyTime_AsTimespec_clamp", test_PyTime_AsTimespec_clamp, METH_VARARGS}, +#endif + {"_PyTime_AsTimeval", test_PyTime_AsTimeval, METH_VARARGS}, + {"_PyTime_AsTimeval_clamp", test_PyTime_AsTimeval_clamp, METH_VARARGS}, + {"_PyTime_FromSeconds", test_pytime_fromseconds, METH_VARARGS}, + {"_PyTime_FromSecondsObject", test_pytime_fromsecondsobject, METH_VARARGS}, + {"_PyTime_ObjectToTime_t", test_pytime_object_to_time_t, METH_VARARGS}, + {"_PyTime_ObjectToTimespec", test_pytime_object_to_timespec, METH_VARARGS}, + {"_PyTime_ObjectToTimeval", test_pytime_object_to_timeval, METH_VARARGS}, + {NULL, NULL} /* sentinel */ +}; + +int +_PyTestInternalCapi_Init_PyTime(PyObject *m) +{ + if (PyModule_AddFunctions(m, TestMethods) < 0) { + return -1; + } + return 0; +} diff --git a/Modules/_testinternalcapi/set.c b/Modules/_testinternalcapi/set.c new file mode 100644 index 00000000000000..0305a7885d217c --- /dev/null +++ b/Modules/_testinternalcapi/set.c @@ -0,0 +1,59 @@ +#include "parts.h" +#include "../_testcapi/util.h" // NULLABLE, RETURN_INT + +#include "pycore_setobject.h" + + +static PyObject * +set_update(PyObject *self, PyObject *args) +{ + PyObject *set, *iterable; + if (!PyArg_ParseTuple(args, "OO", &set, &iterable)) { + return NULL; + } + NULLABLE(set); + NULLABLE(iterable); + RETURN_INT(_PySet_Update(set, iterable)); +} + +static PyObject * +set_next_entry(PyObject *self, PyObject *args) +{ + int rc; + Py_ssize_t pos; + Py_hash_t hash = (Py_hash_t)UNINITIALIZED_SIZE; + PyObject *set, *item = UNINITIALIZED_PTR; + if (!PyArg_ParseTuple(args, "On", &set, &pos)) { + return NULL; + } + NULLABLE(set); + + rc = _PySet_NextEntry(set, &pos, &item, &hash); + if (rc == 1) { + return Py_BuildValue("innO", rc, pos, hash, item); + } + assert(item == UNINITIALIZED_PTR); + assert(hash == (Py_hash_t)UNINITIALIZED_SIZE); + if (rc == -1) { + return NULL; + } + assert(rc == 0); + Py_RETURN_NONE; +} + + +static PyMethodDef TestMethods[] = { + {"set_update", set_update, METH_VARARGS}, + {"set_next_entry", set_next_entry, METH_VARARGS}, + + {NULL}, +}; + +int +_PyTestInternalCapi_Init_Set(PyObject *m) +{ + if (PyModule_AddFunctions(m, TestMethods) < 0) { + return -1; + } + return 0; +} diff --git a/Modules/_testinternalcapi/test_critical_sections.c b/Modules/_testinternalcapi/test_critical_sections.c new file mode 100644 index 00000000000000..1f7e311558b27c --- /dev/null +++ b/Modules/_testinternalcapi/test_critical_sections.c @@ -0,0 +1,217 @@ +/* + * C Extension module to test pycore_critical_section.h API. + */ + +#include "parts.h" + +#include "pycore_critical_section.h" + +#ifdef Py_GIL_DISABLED +#define assert_nogil assert +#define assert_gil(x) +#else +#define assert_gil assert +#define assert_nogil(x) +#endif + + +static PyObject * +test_critical_sections(PyObject *self, PyObject *Py_UNUSED(args)) +{ + PyObject *d1 = PyDict_New(); + assert(d1 != NULL); + + PyObject *d2 = PyDict_New(); + assert(d2 != NULL); + + // Beginning a critical section should lock the associated object and + // push the critical section onto the thread's stack (in Py_GIL_DISABLED builds). + Py_BEGIN_CRITICAL_SECTION(d1); + assert_nogil(PyMutex_IsLocked(&d1->ob_mutex)); + assert_nogil(_PyCriticalSection_IsActive(PyThreadState_GET()->critical_section)); + assert_gil(PyThreadState_GET()->critical_section == 0); + Py_END_CRITICAL_SECTION(); + assert_nogil(!PyMutex_IsLocked(&d1->ob_mutex)); + + assert_nogil(!PyMutex_IsLocked(&d1->ob_mutex)); + assert_nogil(!PyMutex_IsLocked(&d2->ob_mutex)); + Py_BEGIN_CRITICAL_SECTION2(d1, d2); + assert_nogil(PyMutex_IsLocked(&d1->ob_mutex)); + assert_nogil(PyMutex_IsLocked(&d2->ob_mutex)); + Py_END_CRITICAL_SECTION2(); + assert_nogil(!PyMutex_IsLocked(&d1->ob_mutex)); + assert_nogil(!PyMutex_IsLocked(&d2->ob_mutex)); + + // Passing the same object twice should work (and not deadlock). + assert_nogil(!PyMutex_IsLocked(&d2->ob_mutex)); + Py_BEGIN_CRITICAL_SECTION2(d2, d2); + assert_nogil(PyMutex_IsLocked(&d2->ob_mutex)); + Py_END_CRITICAL_SECTION2(); + assert_nogil(!PyMutex_IsLocked(&d2->ob_mutex)); + + Py_DECREF(d2); + Py_DECREF(d1); + Py_RETURN_NONE; +} + +static void +lock_unlock_object(PyObject *obj, int recurse_depth) +{ + Py_BEGIN_CRITICAL_SECTION(obj); + if (recurse_depth > 0) { + lock_unlock_object(obj, recurse_depth - 1); + } + Py_END_CRITICAL_SECTION(); +} + +static void +lock_unlock_two_objects(PyObject *a, PyObject *b, int recurse_depth) +{ + Py_BEGIN_CRITICAL_SECTION2(a, b); + if (recurse_depth > 0) { + lock_unlock_two_objects(a, b, recurse_depth - 1); + } + Py_END_CRITICAL_SECTION2(); +} + + +// Test that nested critical sections do not deadlock if they attempt to lock +// the same object. +static PyObject * +test_critical_sections_nest(PyObject *self, PyObject *Py_UNUSED(args)) +{ + PyObject *a = PyDict_New(); + assert(a != NULL); + PyObject *b = PyDict_New(); + assert(b != NULL); + + // Locking an object recursively with this API should not deadlock. + assert_nogil(!PyMutex_IsLocked(&a->ob_mutex)); + Py_BEGIN_CRITICAL_SECTION(a); + assert_nogil(PyMutex_IsLocked(&a->ob_mutex)); + lock_unlock_object(a, 10); + assert_nogil(PyMutex_IsLocked(&a->ob_mutex)); + Py_END_CRITICAL_SECTION(); + assert_nogil(!PyMutex_IsLocked(&a->ob_mutex)); + + // Same test but with two objects. + Py_BEGIN_CRITICAL_SECTION2(b, a); + lock_unlock_two_objects(a, b, 10); + assert_nogil(PyMutex_IsLocked(&a->ob_mutex)); + assert_nogil(PyMutex_IsLocked(&b->ob_mutex)); + Py_END_CRITICAL_SECTION2(); + + Py_DECREF(b); + Py_DECREF(a); + Py_RETURN_NONE; +} + +// Test that a critical section is suspended by a Py_BEGIN_ALLOW_THREADS and +// resumed by a Py_END_ALLOW_THREADS. +static PyObject * +test_critical_sections_suspend(PyObject *self, PyObject *Py_UNUSED(args)) +{ + PyObject *a = PyDict_New(); + assert(a != NULL); + + Py_BEGIN_CRITICAL_SECTION(a); + assert_nogil(PyMutex_IsLocked(&a->ob_mutex)); + + // Py_BEGIN_ALLOW_THREADS should suspend the active critical section + Py_BEGIN_ALLOW_THREADS + assert_nogil(!PyMutex_IsLocked(&a->ob_mutex)); + Py_END_ALLOW_THREADS; + + // After Py_END_ALLOW_THREADS the critical section should be resumed. + assert_nogil(PyMutex_IsLocked(&a->ob_mutex)); + Py_END_CRITICAL_SECTION(); + + Py_DECREF(a); + Py_RETURN_NONE; +} + +struct test_data { + PyObject *obj1; + PyObject *obj2; + PyObject *obj3; + Py_ssize_t countdown; + PyEvent done_event; +}; + +static void +thread_critical_sections(void *arg) +{ + const Py_ssize_t NUM_ITERS = 200; + struct test_data *test_data = arg; + PyGILState_STATE gil = PyGILState_Ensure(); + + for (Py_ssize_t i = 0; i < NUM_ITERS; i++) { + Py_BEGIN_CRITICAL_SECTION(test_data->obj1); + Py_END_CRITICAL_SECTION(); + + Py_BEGIN_CRITICAL_SECTION(test_data->obj2); + lock_unlock_object(test_data->obj1, 1); + Py_END_CRITICAL_SECTION(); + + Py_BEGIN_CRITICAL_SECTION2(test_data->obj3, test_data->obj1); + lock_unlock_object(test_data->obj2, 2); + Py_END_CRITICAL_SECTION2(); + + Py_BEGIN_CRITICAL_SECTION(test_data->obj3); + Py_BEGIN_ALLOW_THREADS + Py_END_ALLOW_THREADS + Py_END_CRITICAL_SECTION(); + } + + PyGILState_Release(gil); + if (_Py_atomic_add_ssize(&test_data->countdown, -1) == 1) { + // last thread to finish sets done_event + _PyEvent_Notify(&test_data->done_event); + } +} + +#ifdef Py_CAN_START_THREADS +static PyObject * +test_critical_sections_threads(PyObject *self, PyObject *Py_UNUSED(args)) +{ + const Py_ssize_t NUM_THREADS = 4; + struct test_data test_data = { + .obj1 = PyDict_New(), + .obj2 = PyDict_New(), + .obj3 = PyDict_New(), + .countdown = NUM_THREADS, + }; + assert(test_data.obj1 != NULL); + assert(test_data.obj2 != NULL); + assert(test_data.obj3 != NULL); + + for (int i = 0; i < NUM_THREADS; i++) { + PyThread_start_new_thread(&thread_critical_sections, &test_data); + } + PyEvent_Wait(&test_data.done_event); + + Py_DECREF(test_data.obj3); + Py_DECREF(test_data.obj2); + Py_DECREF(test_data.obj1); + Py_RETURN_NONE; +} +#endif + +static PyMethodDef test_methods[] = { + {"test_critical_sections", test_critical_sections, METH_NOARGS}, + {"test_critical_sections_nest", test_critical_sections_nest, METH_NOARGS}, + {"test_critical_sections_suspend", test_critical_sections_suspend, METH_NOARGS}, +#ifdef Py_CAN_START_THREADS + {"test_critical_sections_threads", test_critical_sections_threads, METH_NOARGS}, +#endif + {NULL, NULL} /* sentinel */ +}; + +int +_PyTestInternalCapi_Init_CriticalSection(PyObject *mod) +{ + if (PyModule_AddFunctions(mod, test_methods) < 0) { + return -1; + } + return 0; +} diff --git a/Modules/_testinternalcapi/test_lock.c b/Modules/_testinternalcapi/test_lock.c new file mode 100644 index 00000000000000..83081f73a72f64 --- /dev/null +++ b/Modules/_testinternalcapi/test_lock.c @@ -0,0 +1,492 @@ +// C Extension module to test pycore_lock.h API + +#include "parts.h" + +#include "pycore_lock.h" +#include "clinic/test_lock.c.h" + +#ifdef MS_WINDOWS +#define WIN32_LEAN_AND_MEAN +#include +#else +#include // usleep() +#endif + +/*[clinic input] +module _testinternalcapi +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=7bb583d8c9eb9a78]*/ + + +static void +pysleep(int ms) +{ +#ifdef MS_WINDOWS + Sleep(ms); +#else + usleep(ms * 1000); +#endif +} + +static PyObject * +test_lock_basic(PyObject *self, PyObject *obj) +{ + PyMutex m = (PyMutex){0}; + + // uncontended lock and unlock + PyMutex_Lock(&m); + assert(m.v == 1); + PyMutex_Unlock(&m); + assert(m.v == 0); + + Py_RETURN_NONE; +} + +struct test_lock2_data { + PyMutex m; + PyEvent done; + int started; +}; + +static void +lock_thread(void *arg) +{ + struct test_lock2_data *test_data = arg; + PyMutex *m = &test_data->m; + _Py_atomic_store_int(&test_data->started, 1); + + PyMutex_Lock(m); + assert(m->v == 1); + + PyMutex_Unlock(m); + assert(m->v == 0); + + _PyEvent_Notify(&test_data->done); +} + +static PyObject * +test_lock_two_threads(PyObject *self, PyObject *obj) +{ + // lock attempt by two threads + struct test_lock2_data test_data; + memset(&test_data, 0, sizeof(test_data)); + + PyMutex_Lock(&test_data.m); + assert(test_data.m.v == 1); + + PyThread_start_new_thread(lock_thread, &test_data); + + // wait up to two seconds for the lock_thread to attempt to lock "m" + int iters = 0; + uint8_t v; + do { + pysleep(10); // allow some time for the other thread to try to lock + v = _Py_atomic_load_uint8_relaxed(&test_data.m.v); + assert(v == 1 || v == 3); + iters++; + } while (v != 3 && iters < 200); + + // both the "locked" and the "has parked" bits should be set + assert(test_data.m.v == 3); + + PyMutex_Unlock(&test_data.m); + PyEvent_Wait(&test_data.done); + assert(test_data.m.v == 0); + + Py_RETURN_NONE; +} + +#define COUNTER_THREADS 5 +#define COUNTER_ITERS 10000 + +struct test_data_counter { + PyMutex m; + Py_ssize_t counter; +}; + +struct thread_data_counter { + struct test_data_counter *test_data; + PyEvent done_event; +}; + +static void +counter_thread(void *arg) +{ + struct thread_data_counter *thread_data = arg; + struct test_data_counter *test_data = thread_data->test_data; + + for (Py_ssize_t i = 0; i < COUNTER_ITERS; i++) { + PyMutex_Lock(&test_data->m); + test_data->counter++; + PyMutex_Unlock(&test_data->m); + } + _PyEvent_Notify(&thread_data->done_event); +} + +static PyObject * +test_lock_counter(PyObject *self, PyObject *obj) +{ + // Test with rapidly locking and unlocking mutex + struct test_data_counter test_data; + memset(&test_data, 0, sizeof(test_data)); + + struct thread_data_counter thread_data[COUNTER_THREADS]; + memset(&thread_data, 0, sizeof(thread_data)); + + for (Py_ssize_t i = 0; i < COUNTER_THREADS; i++) { + thread_data[i].test_data = &test_data; + PyThread_start_new_thread(counter_thread, &thread_data[i]); + } + + for (Py_ssize_t i = 0; i < COUNTER_THREADS; i++) { + PyEvent_Wait(&thread_data[i].done_event); + } + + assert(test_data.counter == COUNTER_THREADS * COUNTER_ITERS); + Py_RETURN_NONE; +} + +#define SLOW_COUNTER_ITERS 100 + +static void +slow_counter_thread(void *arg) +{ + struct thread_data_counter *thread_data = arg; + struct test_data_counter *test_data = thread_data->test_data; + + for (Py_ssize_t i = 0; i < SLOW_COUNTER_ITERS; i++) { + PyMutex_Lock(&test_data->m); + if (i % 7 == 0) { + pysleep(2); + } + test_data->counter++; + PyMutex_Unlock(&test_data->m); + } + _PyEvent_Notify(&thread_data->done_event); +} + +static PyObject * +test_lock_counter_slow(PyObject *self, PyObject *obj) +{ + // Test lock/unlock with occasional "long" critical section, which will + // trigger handoff of the lock. + struct test_data_counter test_data; + memset(&test_data, 0, sizeof(test_data)); + + struct thread_data_counter thread_data[COUNTER_THREADS]; + memset(&thread_data, 0, sizeof(thread_data)); + + for (Py_ssize_t i = 0; i < COUNTER_THREADS; i++) { + thread_data[i].test_data = &test_data; + PyThread_start_new_thread(slow_counter_thread, &thread_data[i]); + } + + for (Py_ssize_t i = 0; i < COUNTER_THREADS; i++) { + PyEvent_Wait(&thread_data[i].done_event); + } + + assert(test_data.counter == COUNTER_THREADS * SLOW_COUNTER_ITERS); + Py_RETURN_NONE; +} + +struct bench_data_locks { + int stop; + int use_pymutex; + int critical_section_length; + char padding[200]; + PyThread_type_lock lock; + PyMutex m; + double value; + Py_ssize_t total_iters; +}; + +struct bench_thread_data { + struct bench_data_locks *bench_data; + Py_ssize_t iters; + PyEvent done; +}; + +static void +thread_benchmark_locks(void *arg) +{ + struct bench_thread_data *thread_data = arg; + struct bench_data_locks *bench_data = thread_data->bench_data; + int use_pymutex = bench_data->use_pymutex; + int critical_section_length = bench_data->critical_section_length; + + double my_value = 1.0; + Py_ssize_t iters = 0; + while (!_Py_atomic_load_int_relaxed(&bench_data->stop)) { + if (use_pymutex) { + PyMutex_Lock(&bench_data->m); + for (int i = 0; i < critical_section_length; i++) { + bench_data->value += my_value; + my_value = bench_data->value; + } + PyMutex_Unlock(&bench_data->m); + } + else { + PyThread_acquire_lock(bench_data->lock, 1); + for (int i = 0; i < critical_section_length; i++) { + bench_data->value += my_value; + my_value = bench_data->value; + } + PyThread_release_lock(bench_data->lock); + } + iters++; + } + + thread_data->iters = iters; + _Py_atomic_add_ssize(&bench_data->total_iters, iters); + _PyEvent_Notify(&thread_data->done); +} + +/*[clinic input] +_testinternalcapi.benchmark_locks + + num_threads: Py_ssize_t + use_pymutex: bool = True + critical_section_length: int = 1 + time_ms: int = 1000 + / + +[clinic start generated code]*/ + +static PyObject * +_testinternalcapi_benchmark_locks_impl(PyObject *module, + Py_ssize_t num_threads, + int use_pymutex, + int critical_section_length, + int time_ms) +/*[clinic end generated code: output=381df8d7e9a74f18 input=f3aeaf688738c121]*/ +{ + // Run from Tools/lockbench/lockbench.py + // Based on the WebKit lock benchmarks: + // https://github.com/WebKit/WebKit/blob/main/Source/WTF/benchmarks/LockSpeedTest.cpp + // See also https://webkit.org/blog/6161/locking-in-webkit/ + PyObject *thread_iters = NULL; + PyObject *res = NULL; + + struct bench_data_locks bench_data; + memset(&bench_data, 0, sizeof(bench_data)); + bench_data.use_pymutex = use_pymutex; + bench_data.critical_section_length = critical_section_length; + + bench_data.lock = PyThread_allocate_lock(); + if (bench_data.lock == NULL) { + return PyErr_NoMemory(); + } + + struct bench_thread_data *thread_data = NULL; + thread_data = PyMem_Calloc(num_threads, sizeof(*thread_data)); + if (thread_data == NULL) { + PyErr_NoMemory(); + goto exit; + } + + thread_iters = PyList_New(num_threads); + if (thread_iters == NULL) { + goto exit; + } + + _PyTime_t start = _PyTime_GetMonotonicClock(); + + for (Py_ssize_t i = 0; i < num_threads; i++) { + thread_data[i].bench_data = &bench_data; + PyThread_start_new_thread(thread_benchmark_locks, &thread_data[i]); + } + + // Let the threads run for `time_ms` milliseconds + pysleep(time_ms); + _Py_atomic_store_int(&bench_data.stop, 1); + + // Wait for the threads to finish + for (Py_ssize_t i = 0; i < num_threads; i++) { + PyEvent_Wait(&thread_data[i].done); + } + + Py_ssize_t total_iters = bench_data.total_iters; + _PyTime_t end = _PyTime_GetMonotonicClock(); + + // Return the total number of acquisitions and the number of acquisitions + // for each thread. + for (Py_ssize_t i = 0; i < num_threads; i++) { + PyObject *iter = PyLong_FromSsize_t(thread_data[i].iters); + if (iter == NULL) { + goto exit; + } + PyList_SET_ITEM(thread_iters, i, iter); + } + + double rate = total_iters * 1000000000.0 / (end - start); + res = Py_BuildValue("(dO)", rate, thread_iters); + +exit: + PyThread_free_lock(bench_data.lock); + PyMem_Free(thread_data); + Py_XDECREF(thread_iters); + return res; +} + +static PyObject * +test_lock_benchmark(PyObject *module, PyObject *obj) +{ + // Just make sure the benchmark runs without crashing + PyObject *res = _testinternalcapi_benchmark_locks_impl( + module, 1, 1, 1, 100); + if (res == NULL) { + return NULL; + } + Py_DECREF(res); + Py_RETURN_NONE; +} + +static int +init_maybe_fail(void *arg) +{ + int *counter = (int *)arg; + (*counter)++; + if (*counter < 5) { + // failure + return -1; + } + assert(*counter == 5); + return 0; +} + +static PyObject * +test_lock_once(PyObject *self, PyObject *obj) +{ + _PyOnceFlag once = {0}; + int counter = 0; + for (int i = 0; i < 10; i++) { + int res = _PyOnceFlag_CallOnce(&once, init_maybe_fail, &counter); + if (i < 4) { + assert(res == -1); + } + else { + assert(res == 0); + assert(counter == 5); + } + } + Py_RETURN_NONE; +} + +struct test_rwlock_data { + Py_ssize_t nthreads; + _PyRWMutex rw; + PyEvent step1; + PyEvent step2; + PyEvent step3; + PyEvent done; +}; + +static void +rdlock_thread(void *arg) +{ + struct test_rwlock_data *test_data = arg; + + // Acquire the lock in read mode + _PyRWMutex_RLock(&test_data->rw); + PyEvent_Wait(&test_data->step1); + _PyRWMutex_RUnlock(&test_data->rw); + + _PyRWMutex_RLock(&test_data->rw); + PyEvent_Wait(&test_data->step3); + _PyRWMutex_RUnlock(&test_data->rw); + + if (_Py_atomic_add_ssize(&test_data->nthreads, -1) == 1) { + _PyEvent_Notify(&test_data->done); + } +} +static void +wrlock_thread(void *arg) +{ + struct test_rwlock_data *test_data = arg; + + // First acquire the lock in write mode + _PyRWMutex_Lock(&test_data->rw); + PyEvent_Wait(&test_data->step2); + _PyRWMutex_Unlock(&test_data->rw); + + if (_Py_atomic_add_ssize(&test_data->nthreads, -1) == 1) { + _PyEvent_Notify(&test_data->done); + } +} + +static void +wait_until(uintptr_t *ptr, uintptr_t value) +{ + // wait up to two seconds for *ptr == value + int iters = 0; + uintptr_t bits; + do { + pysleep(10); + bits = _Py_atomic_load_uintptr(ptr); + iters++; + } while (bits != value && iters < 200); +} + +static PyObject * +test_lock_rwlock(PyObject *self, PyObject *obj) +{ + struct test_rwlock_data test_data = {.nthreads = 3}; + + _PyRWMutex_Lock(&test_data.rw); + assert(test_data.rw.bits == 1); + + _PyRWMutex_Unlock(&test_data.rw); + assert(test_data.rw.bits == 0); + + // Start two readers + PyThread_start_new_thread(rdlock_thread, &test_data); + PyThread_start_new_thread(rdlock_thread, &test_data); + + // wait up to two seconds for the threads to attempt to read-lock "rw" + wait_until(&test_data.rw.bits, 8); + assert(test_data.rw.bits == 8); + + // start writer (while readers hold lock) + PyThread_start_new_thread(wrlock_thread, &test_data); + wait_until(&test_data.rw.bits, 10); + assert(test_data.rw.bits == 10); + + // readers release lock, writer should acquire it + _PyEvent_Notify(&test_data.step1); + wait_until(&test_data.rw.bits, 3); + assert(test_data.rw.bits == 3); + + // writer releases lock, readers acquire it + _PyEvent_Notify(&test_data.step2); + wait_until(&test_data.rw.bits, 8); + assert(test_data.rw.bits == 8); + + // readers release lock again + _PyEvent_Notify(&test_data.step3); + wait_until(&test_data.rw.bits, 0); + assert(test_data.rw.bits == 0); + + PyEvent_Wait(&test_data.done); + Py_RETURN_NONE; +} + +static PyMethodDef test_methods[] = { + {"test_lock_basic", test_lock_basic, METH_NOARGS}, + {"test_lock_two_threads", test_lock_two_threads, METH_NOARGS}, + {"test_lock_counter", test_lock_counter, METH_NOARGS}, + {"test_lock_counter_slow", test_lock_counter_slow, METH_NOARGS}, + _TESTINTERNALCAPI_BENCHMARK_LOCKS_METHODDEF + {"test_lock_benchmark", test_lock_benchmark, METH_NOARGS}, + {"test_lock_once", test_lock_once, METH_NOARGS}, + {"test_lock_rwlock", test_lock_rwlock, METH_NOARGS}, + {NULL, NULL} /* sentinel */ +}; + +int +_PyTestInternalCapi_Init_Lock(PyObject *mod) +{ + if (PyModule_AddFunctions(mod, test_methods) < 0) { + return -1; + } + return 0; +} diff --git a/Modules/_testmultiphase.c b/Modules/_testmultiphase.c index fdef06168bfc86..21c5f696a4f2ec 100644 --- a/Modules/_testmultiphase.c +++ b/Modules/_testmultiphase.c @@ -6,6 +6,7 @@ #endif #include "Python.h" +#include "pycore_modsupport.h" // _PyArg_CheckPositional() #include "pycore_namespace.h" // _PyNamespace_New() /* State for testing module state access from methods */ diff --git a/Modules/_threadmodule.c b/Modules/_threadmodule.c index 52f44d04523459..afcf646e3bc19e 100644 --- a/Modules/_threadmodule.c +++ b/Modules/_threadmodule.c @@ -7,10 +7,10 @@ #include "pycore_moduleobject.h" // _PyModule_GetState() #include "pycore_pylifecycle.h" #include "pycore_pystate.h" // _PyThreadState_SetCurrent() +#include "pycore_sysmodule.h" // _PySys_GetAttr() #include "pycore_weakref.h" // _PyWeakref_GET_REF() -#include // offsetof() - +#include // offsetof() #ifdef HAVE_SIGNAL_H # include // SIGINT #endif @@ -22,12 +22,13 @@ // Forward declarations static struct PyModuleDef thread_module; - +// Module state typedef struct { PyTypeObject *excepthook_type; PyTypeObject *lock_type; PyTypeObject *local_type; PyTypeObject *local_dummy_type; + PyTypeObject *thread_handle_type; } thread_module_state; static inline thread_module_state* @@ -38,6 +39,145 @@ get_thread_state(PyObject *module) return (thread_module_state *)state; } +// _ThreadHandle type + +typedef struct { + PyObject_HEAD + PyThread_ident_t ident; + PyThread_handle_t handle; + char joinable; +} ThreadHandleObject; + +static ThreadHandleObject* +new_thread_handle(thread_module_state* state) +{ + ThreadHandleObject* self = PyObject_New(ThreadHandleObject, state->thread_handle_type); + if (self == NULL) { + return NULL; + } + self->ident = 0; + self->handle = 0; + self->joinable = 0; + return self; +} + +static void +ThreadHandle_dealloc(ThreadHandleObject *self) +{ + PyObject *tp = (PyObject *) Py_TYPE(self); + if (self->joinable) { + int ret = PyThread_detach_thread(self->handle); + if (ret) { + PyErr_SetString(ThreadError, "Failed detaching thread"); + PyErr_WriteUnraisable(tp); + } + } + PyObject_Free(self); + Py_DECREF(tp); +} + +static PyObject * +ThreadHandle_repr(ThreadHandleObject *self) +{ + return PyUnicode_FromFormat("<%s object: ident=%" PY_FORMAT_THREAD_IDENT_T ">", + Py_TYPE(self)->tp_name, self->ident); +} + +static PyObject * +ThreadHandle_get_ident(ThreadHandleObject *self, void *ignored) +{ + return PyLong_FromUnsignedLongLong(self->ident); +} + + +static PyObject * +ThreadHandle_after_fork_alive(ThreadHandleObject *self, void* ignored) +{ + PyThread_update_thread_after_fork(&self->ident, &self->handle); + Py_RETURN_NONE; +} + +static PyObject * +ThreadHandle_after_fork_dead(ThreadHandleObject *self, void* ignored) +{ + // Disallow calls to detach() and join() as they could crash. + self->joinable = 0; + Py_RETURN_NONE; +} + +static PyObject * +ThreadHandle_detach(ThreadHandleObject *self, void* ignored) +{ + if (!self->joinable) { + PyErr_SetString(PyExc_ValueError, + "the thread is not joinable and thus cannot be detached"); + return NULL; + } + self->joinable = 0; + // This is typically short so no need to release the GIL + int ret = PyThread_detach_thread(self->handle); + if (ret) { + PyErr_SetString(ThreadError, "Failed detaching thread"); + return NULL; + } + Py_RETURN_NONE; +} + +static PyObject * +ThreadHandle_join(ThreadHandleObject *self, void* ignored) +{ + if (!self->joinable) { + PyErr_SetString(PyExc_ValueError, "the thread is not joinable"); + return NULL; + } + if (self->ident == PyThread_get_thread_ident_ex()) { + // PyThread_join_thread() would deadlock or error out. + PyErr_SetString(ThreadError, "Cannot join current thread"); + return NULL; + } + // Before actually joining, we must first mark the thread as non-joinable, + // as joining several times simultaneously or sequentially is undefined behavior. + self->joinable = 0; + int ret; + Py_BEGIN_ALLOW_THREADS + ret = PyThread_join_thread(self->handle); + Py_END_ALLOW_THREADS + if (ret) { + PyErr_SetString(ThreadError, "Failed joining thread"); + return NULL; + } + Py_RETURN_NONE; +} + +static PyGetSetDef ThreadHandle_getsetlist[] = { + {"ident", (getter)ThreadHandle_get_ident, NULL, NULL}, + {0}, +}; + +static PyMethodDef ThreadHandle_methods[] = +{ + {"after_fork_alive", (PyCFunction)ThreadHandle_after_fork_alive, METH_NOARGS}, + {"after_fork_dead", (PyCFunction)ThreadHandle_after_fork_dead, METH_NOARGS}, + {"detach", (PyCFunction)ThreadHandle_detach, METH_NOARGS}, + {"join", (PyCFunction)ThreadHandle_join, METH_NOARGS}, + {0, 0} +}; + +static PyType_Slot ThreadHandle_Type_slots[] = { + {Py_tp_dealloc, (destructor)ThreadHandle_dealloc}, + {Py_tp_repr, (reprfunc)ThreadHandle_repr}, + {Py_tp_getset, ThreadHandle_getsetlist}, + {Py_tp_methods, ThreadHandle_methods}, + {0, 0} +}; + +static PyType_Spec ThreadHandle_Type_spec = { + "_thread._ThreadHandle", + sizeof(ThreadHandleObject), + 0, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION, + ThreadHandle_Type_slots, +}; /* Lock objects */ @@ -73,57 +213,10 @@ lock_dealloc(lockobject *self) Py_DECREF(tp); } -/* Helper to acquire an interruptible lock with a timeout. If the lock acquire - * is interrupted, signal handlers are run, and if they raise an exception, - * PY_LOCK_INTR is returned. Otherwise, PY_LOCK_ACQUIRED or PY_LOCK_FAILURE - * are returned, depending on whether the lock can be acquired within the - * timeout. - */ -static PyLockStatus +static inline PyLockStatus acquire_timed(PyThread_type_lock lock, _PyTime_t timeout) { - PyThreadState *tstate = _PyThreadState_GET(); - _PyTime_t endtime = 0; - if (timeout > 0) { - endtime = _PyDeadline_Init(timeout); - } - - PyLockStatus r; - do { - _PyTime_t microseconds; - microseconds = _PyTime_AsMicroseconds(timeout, _PyTime_ROUND_CEILING); - - /* first a simple non-blocking try without releasing the GIL */ - r = PyThread_acquire_lock_timed(lock, 0, 0); - if (r == PY_LOCK_FAILURE && microseconds != 0) { - Py_BEGIN_ALLOW_THREADS - r = PyThread_acquire_lock_timed(lock, microseconds, 1); - Py_END_ALLOW_THREADS - } - - if (r == PY_LOCK_INTR) { - /* Run signal handlers if we were interrupted. Propagate - * exceptions from signal handlers, such as KeyboardInterrupt, by - * passing up PY_LOCK_INTR. */ - if (_PyEval_MakePendingCalls(tstate) < 0) { - return PY_LOCK_INTR; - } - - /* If we're using a timeout, recompute the timeout after processing - * signals, since those can take time. */ - if (timeout > 0) { - timeout = _PyDeadline_Get(endtime); - - /* Check for negative values, since those mean block forever. - */ - if (timeout < 0) { - r = PY_LOCK_FAILURE; - } - } - } - } while (r == PY_LOCK_INTR); /* Retry if we were interrupted. */ - - return r; + return PyThread_acquire_lock_timed_with_retries(lock, timeout); } static int @@ -133,14 +226,15 @@ lock_acquire_parse_args(PyObject *args, PyObject *kwds, char *kwlist[] = {"blocking", "timeout", NULL}; int blocking = 1; PyObject *timeout_obj = NULL; - const _PyTime_t unset_timeout = _PyTime_FromSeconds(-1); - - *timeout = unset_timeout ; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|pO:acquire", kwlist, &blocking, &timeout_obj)) return -1; + // XXX Use PyThread_ParseTimeoutArg(). + + const _PyTime_t unset_timeout = _PyTime_FromSeconds(-1); + *timeout = unset_timeout; + if (timeout_obj && _PyTime_FromSecondsObject(timeout, timeout_obj, _PyTime_ROUND_TIMEOUT) < 0) @@ -153,7 +247,7 @@ lock_acquire_parse_args(PyObject *args, PyObject *kwds, } if (*timeout < 0 && *timeout != unset_timeout) { PyErr_SetString(PyExc_ValueError, - "timeout value must be positive"); + "timeout value must be a non-negative number"); return -1; } if (!blocking) @@ -320,7 +414,7 @@ static PyType_Spec lock_type_spec = { typedef struct { PyObject_HEAD PyThread_type_lock rlock_lock; - unsigned long rlock_owner; + PyThread_ident_t rlock_owner; unsigned long rlock_count; PyObject *in_weakreflist; } rlockobject; @@ -357,13 +451,13 @@ static PyObject * rlock_acquire(rlockobject *self, PyObject *args, PyObject *kwds) { _PyTime_t timeout; - unsigned long tid; + PyThread_ident_t tid; PyLockStatus r = PY_LOCK_ACQUIRED; if (lock_acquire_parse_args(args, kwds, &timeout) < 0) return NULL; - tid = PyThread_get_thread_ident(); + tid = PyThread_get_thread_ident_ex(); if (self->rlock_count > 0 && tid == self->rlock_owner) { unsigned long count = self->rlock_count + 1; if (count <= self->rlock_count) { @@ -406,7 +500,7 @@ the lock is taken and its internal counter initialized to 1."); static PyObject * rlock_release(rlockobject *self, PyObject *Py_UNUSED(ignored)) { - unsigned long tid = PyThread_get_thread_ident(); + PyThread_ident_t tid = PyThread_get_thread_ident_ex(); if (self->rlock_count == 0 || self->rlock_owner != tid) { PyErr_SetString(PyExc_RuntimeError, @@ -435,11 +529,12 @@ to be available for other threads."); static PyObject * rlock_acquire_restore(rlockobject *self, PyObject *args) { - unsigned long owner; + PyThread_ident_t owner; unsigned long count; int r = 1; - if (!PyArg_ParseTuple(args, "(kk):_acquire_restore", &count, &owner)) + if (!PyArg_ParseTuple(args, "(k" Py_PARSE_THREAD_IDENT_T "):_acquire_restore", + &count, &owner)) return NULL; if (!PyThread_acquire_lock(self->rlock_lock, 0)) { @@ -465,7 +560,7 @@ For internal use by `threading.Condition`."); static PyObject * rlock_release_save(rlockobject *self, PyObject *Py_UNUSED(ignored)) { - unsigned long owner; + PyThread_ident_t owner; unsigned long count; if (self->rlock_count == 0) { @@ -479,7 +574,7 @@ rlock_release_save(rlockobject *self, PyObject *Py_UNUSED(ignored)) self->rlock_count = 0; self->rlock_owner = 0; PyThread_release_lock(self->rlock_lock); - return Py_BuildValue("kk", count, owner); + return Py_BuildValue("k" Py_PARSE_THREAD_IDENT_T, count, owner); } PyDoc_STRVAR(rlock_release_save_doc, @@ -487,11 +582,23 @@ PyDoc_STRVAR(rlock_release_save_doc, \n\ For internal use by `threading.Condition`."); +static PyObject * +rlock_recursion_count(rlockobject *self, PyObject *Py_UNUSED(ignored)) +{ + PyThread_ident_t tid = PyThread_get_thread_ident_ex(); + return PyLong_FromUnsignedLong( + self->rlock_owner == tid ? self->rlock_count : 0UL); +} + +PyDoc_STRVAR(rlock_recursion_count_doc, +"_recursion_count() -> int\n\ +\n\ +For internal use by reentrancy checks."); static PyObject * rlock_is_owned(rlockobject *self, PyObject *Py_UNUSED(ignored)) { - unsigned long tid = PyThread_get_thread_ident(); + PyThread_ident_t tid = PyThread_get_thread_ident_ex(); if (self->rlock_count > 0 && self->rlock_owner == tid) { Py_RETURN_TRUE; @@ -527,7 +634,8 @@ rlock_new(PyTypeObject *type, PyObject *args, PyObject *kwds) static PyObject * rlock_repr(rlockobject *self) { - return PyUnicode_FromFormat("<%s %s object owner=%ld count=%lu at %p>", + return PyUnicode_FromFormat( + "<%s %s object owner=%" PY_FORMAT_THREAD_IDENT_T " count=%lu at %p>", self->rlock_count ? "locked" : "unlocked", Py_TYPE(self)->tp_name, self->rlock_owner, self->rlock_count, self); @@ -562,6 +670,8 @@ static PyMethodDef rlock_methods[] = { METH_VARARGS, rlock_acquire_restore_doc}, {"_release_save", (PyCFunction)rlock_release_save, METH_NOARGS, rlock_release_save_doc}, + {"_recursion_count", (PyCFunction)rlock_recursion_count, + METH_NOARGS, rlock_recursion_count_doc}, {"__enter__", _PyCFunction_CAST(rlock_acquire), METH_VARARGS | METH_KEYWORDS, rlock_acquire_doc}, {"__exit__", (PyCFunction)rlock_release, @@ -857,11 +967,8 @@ local_clear(localobject *self) HEAD_UNLOCK(runtime); while (tstate) { if (tstate->dict) { - PyObject *v = _PyDict_Pop(tstate->dict, self->key, Py_None); - if (v != NULL) { - Py_DECREF(v); - } - else { + if (PyDict_Pop(tstate->dict, self->key, NULL) < 0) { + // Silently ignore error PyErr_Clear(); } } @@ -1008,12 +1115,10 @@ local_getattro(localobject *self, PyObject *name) } /* Optimization: just look in dict ourselves */ - PyObject *value = PyDict_GetItemWithError(ldict, name); - if (value != NULL) { - return Py_NewRef(value); - } - if (PyErr_Occurred()) { - return NULL; + PyObject *value; + if (PyDict_GetItemRef(ldict, name, &value) != 0) { + // found or error + return value; } /* Fall back on generic to get __class__ and __dict__ */ @@ -1048,22 +1153,22 @@ _localdummy_destroyed(PyObject *localweakref, PyObject *dummyweakref) /* Module functions */ struct bootstate { - PyInterpreterState *interp; + PyThreadState *tstate; PyObject *func; PyObject *args; PyObject *kwargs; - PyThreadState *tstate; - _PyRuntimeState *runtime; }; static void -thread_bootstate_free(struct bootstate *boot) +thread_bootstate_free(struct bootstate *boot, int decref) { - Py_DECREF(boot->func); - Py_DECREF(boot->args); - Py_XDECREF(boot->kwargs); - PyMem_Free(boot); + if (decref) { + Py_DECREF(boot->func); + Py_DECREF(boot->args); + Py_XDECREF(boot->kwargs); + } + PyMem_RawFree(boot); } @@ -1071,9 +1176,27 @@ static void thread_run(void *boot_raw) { struct bootstate *boot = (struct bootstate *) boot_raw; - PyThreadState *tstate; + PyThreadState *tstate = boot->tstate; + + // gh-108987: If _thread.start_new_thread() is called before or while + // Python is being finalized, thread_run() can called *after*. + // _PyRuntimeState_SetFinalizing() is called. At this point, all Python + // threads must exit, except of the thread calling Py_Finalize() whch holds + // the GIL and must not exit. + // + // At this stage, tstate can be a dangling pointer (point to freed memory), + // it's ok to call _PyThreadState_MustExit() with a dangling pointer. + if (_PyThreadState_MustExit(tstate)) { + // Don't call PyThreadState_Clear() nor _PyThreadState_DeleteCurrent(). + // These functions are called on tstate indirectly by Py_Finalize() + // which calls _PyInterpreterState_Clear(). + // + // Py_DECREF() cannot be called because the GIL is not held: leak + // references on purpose. Python is being finalized anyway. + thread_bootstate_free(boot, 0); + goto exit; + } - tstate = boot->tstate; _PyThreadState_Bind(tstate); PyEval_AcquireThread(tstate); tstate->interp->threads.count++; @@ -1084,21 +1207,25 @@ thread_run(void *boot_raw) /* SystemExit is ignored silently */ PyErr_Clear(); else { - _PyErr_WriteUnraisableMsg("in thread started by", boot->func); + PyErr_FormatUnraisable( + "Exception ignored in thread started by %R", boot->func); } } else { Py_DECREF(res); } - thread_bootstate_free(boot); + thread_bootstate_free(boot, 1); + tstate->interp->threads.count--; PyThreadState_Clear(tstate); _PyThreadState_DeleteCurrent(tstate); +exit: // bpo-44434: Don't call explicitly PyThread_exit_thread(). On Linux with // the glibc, pthread_exit() can abort the whole process if dlopen() fails // to open the libgcc_s.so library (ex: EMFILE error). + return; } static PyObject * @@ -1119,11 +1246,66 @@ PyDoc_STRVAR(daemon_threads_allowed_doc, Return True if daemon threads are allowed in the current interpreter,\n\ and False otherwise.\n"); +static int +do_start_new_thread(thread_module_state* state, + PyObject *func, PyObject* args, PyObject* kwargs, + int joinable, + PyThread_ident_t* ident, PyThread_handle_t* handle) +{ + PyInterpreterState *interp = _PyInterpreterState_GET(); + if (!_PyInterpreterState_HasFeature(interp, Py_RTFLAGS_THREADS)) { + PyErr_SetString(PyExc_RuntimeError, + "thread is not supported for isolated subinterpreters"); + return -1; + } + if (interp->finalizing) { + PyErr_SetString(PyExc_RuntimeError, + "can't create new thread at interpreter shutdown"); + return -1; + } + + // gh-109795: Use PyMem_RawMalloc() instead of PyMem_Malloc(), + // because it should be possible to call thread_bootstate_free() + // without holding the GIL. + struct bootstate *boot = PyMem_RawMalloc(sizeof(struct bootstate)); + if (boot == NULL) { + PyErr_NoMemory(); + return -1; + } + boot->tstate = _PyThreadState_New(interp, _PyThreadState_WHENCE_THREADING); + if (boot->tstate == NULL) { + PyMem_RawFree(boot); + if (!PyErr_Occurred()) { + PyErr_NoMemory(); + } + return -1; + } + boot->func = Py_NewRef(func); + boot->args = Py_NewRef(args); + boot->kwargs = Py_XNewRef(kwargs); + + int err; + if (joinable) { + err = PyThread_start_joinable_thread(thread_run, (void*) boot, ident, handle); + } else { + *handle = 0; + *ident = PyThread_start_new_thread(thread_run, (void*) boot); + err = (*ident == PYTHREAD_INVALID_THREAD_ID); + } + if (err) { + PyErr_SetString(ThreadError, "can't start new thread"); + PyThreadState_Clear(boot->tstate); + thread_bootstate_free(boot, 1); + return -1; + } + return 0; +} + static PyObject * -thread_PyThread_start_new_thread(PyObject *self, PyObject *fargs) +thread_PyThread_start_new_thread(PyObject *module, PyObject *fargs) { - _PyRuntimeState *runtime = &_PyRuntime; PyObject *func, *args, *kwargs = NULL; + thread_module_state *state = get_thread_state(module); if (!PyArg_UnpackTuple(fargs, "start_new_thread", 2, 3, &func, &args, &kwargs)) @@ -1149,56 +1331,73 @@ thread_PyThread_start_new_thread(PyObject *self, PyObject *fargs) return NULL; } - PyInterpreterState *interp = _PyInterpreterState_GET(); - if (!_PyInterpreterState_HasFeature(interp, Py_RTFLAGS_THREADS)) { - PyErr_SetString(PyExc_RuntimeError, - "thread is not supported for isolated subinterpreters"); + PyThread_ident_t ident = 0; + PyThread_handle_t handle; + if (do_start_new_thread(state, func, args, kwargs, /*joinable=*/ 0, + &ident, &handle)) { return NULL; } - if (interp->finalizing) { - PyErr_SetString(PyExc_RuntimeError, - "can't create new thread at interpreter shutdown"); + return PyLong_FromUnsignedLongLong(ident); +} + +PyDoc_STRVAR(start_new_doc, +"start_new_thread(function, args[, kwargs])\n\ +(start_new() is an obsolete synonym)\n\ +\n\ +Start a new thread and return its identifier.\n\ +\n\ +The thread will call the function with positional arguments from the\n\ +tuple args and keyword arguments taken from the optional dictionary\n\ +kwargs. The thread exits when the function returns; the return value\n\ +is ignored. The thread will also exit when the function raises an\n\ +unhandled exception; a stack trace will be printed unless the exception\n\ +is SystemExit.\n"); + +static PyObject * +thread_PyThread_start_joinable_thread(PyObject *module, PyObject *func) +{ + thread_module_state *state = get_thread_state(module); + + if (!PyCallable_Check(func)) { + PyErr_SetString(PyExc_TypeError, + "thread function must be callable"); return NULL; } - struct bootstate *boot = PyMem_NEW(struct bootstate, 1); - if (boot == NULL) { - return PyErr_NoMemory(); - } - boot->interp = _PyInterpreterState_GET(); - boot->tstate = _PyThreadState_New(boot->interp); - if (boot->tstate == NULL) { - PyMem_Free(boot); - if (!PyErr_Occurred()) { - return PyErr_NoMemory(); - } + if (PySys_Audit("_thread.start_joinable_thread", "O", func) < 0) { return NULL; } - boot->runtime = runtime; - boot->func = Py_NewRef(func); - boot->args = Py_NewRef(args); - boot->kwargs = Py_XNewRef(kwargs); - unsigned long ident = PyThread_start_new_thread(thread_run, (void*) boot); - if (ident == PYTHREAD_INVALID_THREAD_ID) { - PyErr_SetString(ThreadError, "can't start new thread"); - PyThreadState_Clear(boot->tstate); - thread_bootstate_free(boot); + PyObject* args = PyTuple_New(0); + if (args == NULL) { + return NULL; + } + ThreadHandleObject* hobj = new_thread_handle(state); + if (hobj == NULL) { + Py_DECREF(args); return NULL; } - return PyLong_FromUnsignedLong(ident); + if (do_start_new_thread(state, func, args, /*kwargs=*/ NULL, /*joinable=*/ 1, + &hobj->ident, &hobj->handle)) { + Py_DECREF(args); + Py_DECREF(hobj); + return NULL; + } + Py_DECREF(args); + hobj->joinable = 1; + return (PyObject*) hobj; } -PyDoc_STRVAR(start_new_doc, -"start_new_thread(function, args[, kwargs])\n\ -(start_new() is an obsolete synonym)\n\ +PyDoc_STRVAR(start_joinable_doc, +"start_joinable_thread(function)\n\ +\n\ +*For internal use only*: start a new thread.\n\ \n\ -Start a new thread and return its identifier. The thread will call the\n\ -function with positional arguments from the tuple args and keyword arguments\n\ -taken from the optional dictionary kwargs. The thread exits when the\n\ -function returns; the return value is ignored. The thread will also exit\n\ -when the function raises an unhandled exception; a stack trace will be\n\ -printed unless the exception is SystemExit.\n"); +Like start_new_thread(), this starts a new thread calling the given function.\n\ +Unlike start_new_thread(), this returns a handle object with methods to join\n\ +or detach the given thread.\n\ +This function is not for third-party code, please use the\n\ +`threading` module instead.\n"); static PyObject * thread_PyThread_exit_thread(PyObject *self, PyObject *Py_UNUSED(ignored)) @@ -1258,12 +1457,12 @@ information about locks."); static PyObject * thread_get_ident(PyObject *self, PyObject *Py_UNUSED(ignored)) { - unsigned long ident = PyThread_get_thread_ident(); + PyThread_ident_t ident = PyThread_get_thread_ident_ex(); if (ident == PYTHREAD_INVALID_THREAD_ID) { PyErr_SetString(ThreadError, "no current thread ident"); return NULL; } - return PyLong_FromUnsignedLong(ident); + return PyLong_FromUnsignedLongLong(ident); } PyDoc_STRVAR(get_ident_doc, @@ -1450,8 +1649,8 @@ thread_excepthook_file(PyObject *file, PyObject *exc_type, PyObject *exc_value, Py_DECREF(name); } else { - unsigned long ident = PyThread_get_thread_ident(); - PyObject *str = PyUnicode_FromFormat("%lu", ident); + PyThread_ident_t ident = PyThread_get_thread_ident_ex(); + PyObject *str = PyUnicode_FromFormat("%" PY_FORMAT_THREAD_IDENT_T, ident); if (str != NULL) { if (PyFile_WriteObject(str, file, Py_PRINT_RAW) < 0) { Py_DECREF(str); @@ -1476,11 +1675,9 @@ thread_excepthook_file(PyObject *file, PyObject *exc_type, PyObject *exc_value, _PyErr_Display(file, exc_type, exc_value, exc_traceback); /* Call file.flush() */ - PyObject *res = PyObject_CallMethodNoArgs(file, &_Py_ID(flush)); - if (!res) { + if (_PyFile_Flush(file) < 0) { return -1; } - Py_DECREF(res); return 0; } @@ -1569,11 +1766,25 @@ PyDoc_STRVAR(excepthook_doc, \n\ Handle uncaught Thread.run() exception."); +static PyObject * +thread__is_main_interpreter(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + PyInterpreterState *interp = _PyInterpreterState_GET(); + return PyBool_FromLong(_Py_IsMainInterpreter(interp)); +} + +PyDoc_STRVAR(thread__is_main_interpreter_doc, +"_is_main_interpreter()\n\ +\n\ +Return True if the current interpreter is the main Python interpreter."); + static PyMethodDef thread_methods[] = { {"start_new_thread", (PyCFunction)thread_PyThread_start_new_thread, METH_VARARGS, start_new_doc}, {"start_new", (PyCFunction)thread_PyThread_start_new_thread, METH_VARARGS, start_new_doc}, + {"start_joinable_thread", (PyCFunction)thread_PyThread_start_joinable_thread, + METH_O, start_joinable_doc}, {"daemon_threads_allowed", (PyCFunction)thread_daemon_threads_allowed, METH_NOARGS, daemon_threads_allowed_doc}, {"allocate_lock", thread_PyThread_allocate_lock, @@ -1598,8 +1809,10 @@ static PyMethodDef thread_methods[] = { METH_VARARGS, stack_size_doc}, {"_set_sentinel", thread__set_sentinel, METH_NOARGS, _set_sentinel_doc}, - {"_excepthook", thread_excepthook, + {"_excepthook", thread_excepthook, METH_O, excepthook_doc}, + {"_is_main_interpreter", thread__is_main_interpreter, + METH_NOARGS, thread__is_main_interpreter_doc}, {NULL, NULL} /* sentinel */ }; @@ -1615,6 +1828,15 @@ thread_module_exec(PyObject *module) // Initialize the C thread library PyThread_init_thread(); + // _ThreadHandle + state->thread_handle_type = (PyTypeObject *)PyType_FromSpec(&ThreadHandle_Type_spec); + if (state->thread_handle_type == NULL) { + return -1; + } + if (PyDict_SetItemString(d, "_ThreadHandle", (PyObject *)state->thread_handle_type) < 0) { + return -1; + } + // Lock state->lock_type = (PyTypeObject *)PyType_FromSpec(&lock_type_spec); if (state->lock_type == NULL) { @@ -1688,6 +1910,7 @@ thread_module_traverse(PyObject *module, visitproc visit, void *arg) Py_VISIT(state->lock_type); Py_VISIT(state->local_type); Py_VISIT(state->local_dummy_type); + Py_VISIT(state->thread_handle_type); return 0; } @@ -1699,6 +1922,7 @@ thread_module_clear(PyObject *module) Py_CLEAR(state->lock_type); Py_CLEAR(state->local_type); Py_CLEAR(state->local_dummy_type); + Py_CLEAR(state->thread_handle_type); return 0; } diff --git a/Modules/_tkinter.c b/Modules/_tkinter.c index 663b4117683629..f6181168a85ae1 100644 --- a/Modules/_tkinter.c +++ b/Modules/_tkinter.c @@ -26,15 +26,14 @@ Copyright (C) 1994 Steen Lumholt. #endif #include "Python.h" -#include #ifdef MS_WINDOWS # include "pycore_fileutils.h" // _Py_stat() #endif -#include "pycore_long.h" +#include "pycore_long.h" // _PyLong_IsNegative() #ifdef MS_WINDOWS -#include +# include #endif #define CHECK_SIZE(size, elemsize) \ @@ -46,11 +45,11 @@ Copyright (C) 1994 Steen Lumholt. #define TCL_THREADS #ifdef TK_FRAMEWORK -#include -#include +# include +# include #else -#include -#include +# include +# include #endif #include "tkinter.h" @@ -736,8 +735,9 @@ newPyTclObject(Tcl_Obj *arg) } static void -PyTclObject_dealloc(PyTclObject *self) +PyTclObject_dealloc(PyObject *_self) { + PyTclObject *self = (PyTclObject *)_self; PyObject *tp = (PyObject *) Py_TYPE(self); Tcl_DecrRefCount(self->value); Py_XDECREF(self->string); @@ -750,8 +750,9 @@ PyDoc_STRVAR(PyTclObject_string__doc__, "the string representation of this object, either as str or bytes"); static PyObject * -PyTclObject_string(PyTclObject *self, void *ignored) +PyTclObject_string(PyObject *_self, void *ignored) { + PyTclObject *self = (PyTclObject *)_self; if (!self->string) { self->string = unicodeFromTclObj(self->value); if (!self->string) @@ -761,8 +762,9 @@ PyTclObject_string(PyTclObject *self, void *ignored) } static PyObject * -PyTclObject_str(PyTclObject *self) +PyTclObject_str(PyObject *_self) { + PyTclObject *self = (PyTclObject *)_self; if (self->string) { return Py_NewRef(self->string); } @@ -771,9 +773,10 @@ PyTclObject_str(PyTclObject *self) } static PyObject * -PyTclObject_repr(PyTclObject *self) +PyTclObject_repr(PyObject *_self) { - PyObject *repr, *str = PyTclObject_str(self); + PyTclObject *self = (PyTclObject *)_self; + PyObject *repr, *str = PyTclObject_str(_self); if (str == NULL) return NULL; repr = PyUnicode_FromFormat("<%s object: %R>", @@ -810,23 +813,24 @@ PyTclObject_richcompare(PyObject *self, PyObject *other, int op) PyDoc_STRVAR(get_typename__doc__, "name of the Tcl type"); static PyObject* -get_typename(PyTclObject* obj, void* ignored) +get_typename(PyObject *self, void* ignored) { + PyTclObject *obj = (PyTclObject *)self; return unicodeFromTclString(obj->value->typePtr->name); } static PyGetSetDef PyTclObject_getsetlist[] = { - {"typename", (getter)get_typename, NULL, get_typename__doc__}, - {"string", (getter)PyTclObject_string, NULL, + {"typename", get_typename, NULL, get_typename__doc__}, + {"string", PyTclObject_string, NULL, PyTclObject_string__doc__}, {0}, }; static PyType_Slot PyTclObject_Type_slots[] = { - {Py_tp_dealloc, (destructor)PyTclObject_dealloc}, - {Py_tp_repr, (reprfunc)PyTclObject_repr}, - {Py_tp_str, (reprfunc)PyTclObject_str}, + {Py_tp_dealloc, PyTclObject_dealloc}, + {Py_tp_repr, PyTclObject_repr}, + {Py_tp_str, PyTclObject_str}, {Py_tp_getattro, PyObject_GenericGetAttr}, {Py_tp_richcompare, PyTclObject_richcompare}, {Py_tp_getset, PyTclObject_getsetlist}, @@ -1203,7 +1207,7 @@ typedef struct Tkapp_CallEvent { Tcl_Condition *done; } Tkapp_CallEvent; -void +static void Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc) { int i; @@ -1307,8 +1311,9 @@ Tkapp_ObjectResult(TkappObject *self) hold the Python lock. */ static int -Tkapp_CallProc(Tkapp_CallEvent *e, int flags) +Tkapp_CallProc(Tcl_Event *evPtr, int flags) { + Tkapp_CallEvent *e = (Tkapp_CallEvent *)evPtr; Tcl_Obj *objStore[ARGSZ]; Tcl_Obj **objv; int objc; @@ -1386,7 +1391,7 @@ Tkapp_Call(PyObject *selfptr, PyObject *args) PyErr_NoMemory(); return NULL; } - ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc; + ev->ev.proc = Tkapp_CallProc; ev->self = self; ev->args = args; ev->res = &res; @@ -1625,8 +1630,9 @@ var_perform(VarEvent *ev) } static int -var_proc(VarEvent* ev, int flags) +var_proc(Tcl_Event *evPtr, int flags) { + VarEvent *ev = (VarEvent *)evPtr; ENTER_PYTHON var_perform(ev); Tcl_MutexLock(&var_mutex); @@ -1664,7 +1670,7 @@ var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags) ev->res = &res; ev->exc = &exc; ev->cond = &cond; - ev->ev.proc = (Tcl_EventProc*)var_proc; + ev->ev.proc = var_proc; Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &var_mutex); Tcl_ConditionFinalize(&cond); if (!res) { @@ -2237,8 +2243,9 @@ typedef struct CommandEvent{ } CommandEvent; static int -Tkapp_CommandProc(CommandEvent *ev, int flags) +Tkapp_CommandProc(Tcl_Event *evPtr, int flags) { + CommandEvent *ev = (CommandEvent *)evPtr; if (ev->create) *ev->status = Tcl_CreateObjCommand( ev->interp, ev->name, PythonCmd, @@ -2291,7 +2298,7 @@ _tkinter_tkapp_createcommand_impl(TkappObject *self, const char *name, PyMem_Free(data); return NULL; } - ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc; + ev->ev.proc = Tkapp_CommandProc; ev->interp = self->interp; ev->create = 1; ev->name = name; @@ -2344,7 +2351,7 @@ _tkinter_tkapp_deletecommand_impl(TkappObject *self, const char *name) PyErr_NoMemory(); return NULL; } - ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc; + ev->ev.proc = Tkapp_CommandProc; ev->interp = self->interp; ev->create = 0; ev->name = name; diff --git a/Modules/_tracemalloc.c b/Modules/_tracemalloc.c index f3f4af9aba08c1..6dba3cac01c1c8 100644 --- a/Modules/_tracemalloc.c +++ b/Modules/_tracemalloc.c @@ -1,4 +1,5 @@ #include "Python.h" +#include "pycore_tracemalloc.h" // _PyTraceMalloc_IsTracing #include "clinic/_tracemalloc.c.h" diff --git a/Modules/_typingmodule.c b/Modules/_typingmodule.c index 59d3a80a9305db..9ea72bf89ce0b2 100644 --- a/Modules/_typingmodule.c +++ b/Modules/_typingmodule.c @@ -40,7 +40,7 @@ static PyMethodDef typing_methods[] = { }; PyDoc_STRVAR(typing_doc, -"Accelerators for the typing module.\n"); +"Primitives and accelerators for the typing module.\n"); static int _typing_exec(PyObject *m) diff --git a/Modules/_uuidmodule.c b/Modules/_uuidmodule.c index 2f5be1c5144d83..4b6852c0d0ec73 100644 --- a/Modules/_uuidmodule.c +++ b/Modules/_uuidmodule.c @@ -3,6 +3,13 @@ * DCE compatible Universally Unique Identifier library. */ +#include "pyconfig.h" // Py_GIL_DISABLED + +#ifndef Py_GIL_DISABLED +// Need limited C API version 3.12 for Py_MOD_PER_INTERPRETER_GIL_SUPPORTED +#define Py_LIMITED_API 0x030c0000 +#endif + #include "Python.h" #if defined(HAVE_UUID_H) // AIX, FreeBSD, libuuid with pkgconf diff --git a/Modules/_weakref.c b/Modules/_weakref.c index 4e2862e7467c3d..7225dbc9ce4a1b 100644 --- a/Modules/_weakref.c +++ b/Modules/_weakref.c @@ -1,8 +1,7 @@ #include "Python.h" -#include "pycore_dict.h" // _PyDict_DelItemIf() -#include "pycore_object.h" // _PyObject_GET_WEAKREFS_LISTPTR -#include "pycore_weakref.h" // _PyWeakref_IS_DEAD() - +#include "pycore_dict.h" // _PyDict_DelItemIf() +#include "pycore_object.h" // _PyObject_GET_WEAKREFS_LISTPTR() +#include "pycore_weakref.h" // _PyWeakref_IS_DEAD() #define GET_WEAKREFS_LISTPTR(o) \ ((PyWeakReference **) _PyObject_GET_WEAKREFS_LISTPTR(o)) @@ -15,7 +14,7 @@ module _weakref #include "clinic/_weakref.c.h" /*[clinic input] - +@critical_section object _weakref.getweakrefcount -> Py_ssize_t object: object @@ -26,15 +25,14 @@ Return the number of weak references to 'object'. static Py_ssize_t _weakref_getweakrefcount_impl(PyObject *module, PyObject *object) -/*[clinic end generated code: output=301806d59558ff3e input=cedb69711b6a2507]*/ +/*[clinic end generated code: output=301806d59558ff3e input=6535a580f1d0ebdc]*/ { - PyWeakReference **list; - - if (!_PyType_SUPPORTS_WEAKREFS(Py_TYPE(object))) + if (!_PyType_SUPPORTS_WEAKREFS(Py_TYPE(object))) { return 0; - - list = GET_WEAKREFS_LISTPTR(object); - return _PyWeakref_GetWeakrefCount(*list); + } + PyWeakReference **list = GET_WEAKREFS_LISTPTR(object); + Py_ssize_t count = _PyWeakref_GetWeakrefCount(*list); + return count; } @@ -79,6 +77,7 @@ _weakref__remove_dead_weakref_impl(PyObject *module, PyObject *dct, /*[clinic input] +@critical_section object _weakref.getweakrefs object: object / @@ -87,8 +86,8 @@ Return a list of all weak reference objects pointing to 'object'. [clinic start generated code]*/ static PyObject * -_weakref_getweakrefs(PyObject *module, PyObject *object) -/*[clinic end generated code: output=25c7731d8e011824 input=00c6d0e5d3206693]*/ +_weakref_getweakrefs_impl(PyObject *module, PyObject *object) +/*[clinic end generated code: output=5ec268989fb8f035 input=3dea95b8f5b31bbb]*/ { if (!_PyType_SUPPORTS_WEAKREFS(Py_TYPE(object))) { return PyList_New(0); diff --git a/Modules/_winapi.c b/Modules/_winapi.c index 0edb36d18dd3ff..a26850e825b492 100644 --- a/Modules/_winapi.c +++ b/Modules/_winapi.c @@ -212,7 +212,7 @@ class DWORD_return_converter(CReturnConverter): self.declare(data) self.err_occurred_if("_return_value == PY_DWORD_MAX", data) data.return_conversion.append( - 'return_value = Py_BuildValue("k", _return_value);\n') + 'return_value = PyLong_FromUnsignedLong(_return_value);\n') class LPVOID_return_converter(CReturnConverter): type = 'LPVOID' @@ -223,7 +223,7 @@ class LPVOID_return_converter(CReturnConverter): data.return_conversion.append( 'return_value = HANDLE_TO_PYNUM(_return_value);\n') [python start generated code]*/ -/*[python end generated code: output=da39a3ee5e6b4b0d input=011ee0c3a2244bfe]*/ +/*[python end generated code: output=da39a3ee5e6b4b0d input=ef52a757a1830d92]*/ #include "clinic/_winapi.c.h" @@ -774,12 +774,157 @@ gethandle(PyObject* obj, const char* name) return ret; } +static PyObject * +sortenvironmentkey(PyObject *module, PyObject *item) +{ + return _winapi_LCMapStringEx_impl(NULL, LOCALE_NAME_INVARIANT, + LCMAP_UPPERCASE, item); +} + +static PyMethodDef sortenvironmentkey_def = { + "sortenvironmentkey", _PyCFunction_CAST(sortenvironmentkey), METH_O, "", +}; + +static int +sort_environment_keys(PyObject *keys) +{ + PyObject *keyfunc = PyCFunction_New(&sortenvironmentkey_def, NULL); + if (keyfunc == NULL) { + return -1; + } + PyObject *kwnames = Py_BuildValue("(s)", "key"); + if (kwnames == NULL) { + Py_DECREF(keyfunc); + return -1; + } + PyObject *args[] = { keys, keyfunc }; + PyObject *ret = PyObject_VectorcallMethod(&_Py_ID(sort), args, 1, kwnames); + Py_DECREF(keyfunc); + Py_DECREF(kwnames); + if (ret == NULL) { + return -1; + } + Py_DECREF(ret); + + return 0; +} + +static int +compare_string_ordinal(PyObject *str1, PyObject *str2, int *result) +{ + wchar_t *s1 = PyUnicode_AsWideCharString(str1, NULL); + if (s1 == NULL) { + return -1; + } + wchar_t *s2 = PyUnicode_AsWideCharString(str2, NULL); + if (s2 == NULL) { + PyMem_Free(s1); + return -1; + } + *result = CompareStringOrdinal(s1, -1, s2, -1, TRUE); + PyMem_Free(s1); + PyMem_Free(s2); + return 0; +} + +static PyObject * +dedup_environment_keys(PyObject *keys) +{ + PyObject *result = PyList_New(0); + if (result == NULL) { + return NULL; + } + + // Iterate over the pre-ordered keys, check whether the current key is equal + // to the next key (ignoring case), if different, insert the current value + // into the result list. If they are equal, do nothing because we always + // want to keep the last inserted one. + for (Py_ssize_t i = 0; i < PyList_GET_SIZE(keys); i++) { + PyObject *key = PyList_GET_ITEM(keys, i); + + // The last key will always be kept. + if (i + 1 == PyList_GET_SIZE(keys)) { + if (PyList_Append(result, key) < 0) { + Py_DECREF(result); + return NULL; + } + continue; + } + + PyObject *next_key = PyList_GET_ITEM(keys, i + 1); + int compare_result; + if (compare_string_ordinal(key, next_key, &compare_result) < 0) { + Py_DECREF(result); + return NULL; + } + if (compare_result == CSTR_EQUAL) { + continue; + } + if (PyList_Append(result, key) < 0) { + Py_DECREF(result); + return NULL; + } + } + + return result; +} + +static PyObject * +normalize_environment(PyObject *environment) +{ + PyObject *keys = PyMapping_Keys(environment); + if (keys == NULL) { + return NULL; + } + + if (sort_environment_keys(keys) < 0) { + Py_DECREF(keys); + return NULL; + } + + PyObject *normalized_keys = dedup_environment_keys(keys); + Py_DECREF(keys); + if (normalized_keys == NULL) { + return NULL; + } + + PyObject *result = PyDict_New(); + if (result == NULL) { + Py_DECREF(normalized_keys); + return NULL; + } + + for (int i = 0; i < PyList_GET_SIZE(normalized_keys); i++) { + PyObject *key = PyList_GET_ITEM(normalized_keys, i); + PyObject *value = PyObject_GetItem(environment, key); + if (value == NULL) { + Py_DECREF(normalized_keys); + Py_DECREF(result); + return NULL; + } + + int ret = PyObject_SetItem(result, key, value); + Py_DECREF(value); + if (ret < 0) { + Py_DECREF(normalized_keys); + Py_DECREF(result); + return NULL; + } + } + + Py_DECREF(normalized_keys); + + return result; +} + static wchar_t * getenvironment(PyObject* environment) { Py_ssize_t i, envsize, totalsize; wchar_t *buffer = NULL, *p, *end; - PyObject *keys, *values; + PyObject *normalized_environment = NULL; + PyObject *keys = NULL; + PyObject *values = NULL; /* convert environment dictionary to windows environment string */ if (! PyMapping_Check(environment)) { @@ -788,11 +933,16 @@ getenvironment(PyObject* environment) return NULL; } - keys = PyMapping_Keys(environment); - if (!keys) { + normalized_environment = normalize_environment(environment); + if (normalize_environment == NULL) { return NULL; } - values = PyMapping_Values(environment); + + keys = PyMapping_Keys(normalized_environment); + if (!keys) { + goto error; + } + values = PyMapping_Values(normalized_environment); if (!values) { goto error; } @@ -884,6 +1034,7 @@ getenvironment(PyObject* environment) cleanup: error: + Py_XDECREF(normalized_environment); Py_XDECREF(keys); Py_XDECREF(values); return buffer; @@ -1539,40 +1690,56 @@ _winapi.LCMapStringEx locale: LPCWSTR flags: DWORD - src: LPCWSTR + src: unicode [clinic start generated code]*/ static PyObject * _winapi_LCMapStringEx_impl(PyObject *module, LPCWSTR locale, DWORD flags, - LPCWSTR src) -/*[clinic end generated code: output=cf4713d80e2b47c9 input=9fe26f95d5ab0001]*/ + PyObject *src) +/*[clinic end generated code: output=b90e6b26e028ff0a input=3e3dcd9b8164012f]*/ { if (flags & (LCMAP_SORTHANDLE | LCMAP_HASH | LCMAP_BYTEREV | LCMAP_SORTKEY)) { return PyErr_Format(PyExc_ValueError, "unsupported flags"); } - int dest_size = LCMapStringEx(locale, flags, src, -1, NULL, 0, + Py_ssize_t src_size; + wchar_t *src_ = PyUnicode_AsWideCharString(src, &src_size); + if (!src_) { + return NULL; + } + if (src_size > INT_MAX) { + PyMem_Free(src_); + PyErr_SetString(PyExc_OverflowError, "input string is too long"); + return NULL; + } + + int dest_size = LCMapStringEx(locale, flags, src_, (int)src_size, NULL, 0, NULL, NULL, 0); - if (dest_size == 0) { - return PyErr_SetFromWindowsErr(0); + if (dest_size <= 0) { + DWORD error = GetLastError(); + PyMem_Free(src_); + return PyErr_SetFromWindowsErr(error); } wchar_t* dest = PyMem_NEW(wchar_t, dest_size); if (dest == NULL) { + PyMem_Free(src_); return PyErr_NoMemory(); } - int nmapped = LCMapStringEx(locale, flags, src, -1, dest, dest_size, + int nmapped = LCMapStringEx(locale, flags, src_, (int)src_size, dest, dest_size, NULL, NULL, 0); - if (nmapped == 0) { + if (nmapped <= 0) { DWORD error = GetLastError(); + PyMem_Free(src_); PyMem_DEL(dest); return PyErr_SetFromWindowsErr(error); } - PyObject *ret = PyUnicode_FromWideChar(dest, dest_size - 1); + PyMem_Free(src_); + PyObject *ret = PyUnicode_FromWideChar(dest, nmapped); PyMem_DEL(dest); return ret; diff --git a/Modules/_xxinterpchannelsmodule.c b/Modules/_xxinterpchannelsmodule.c index 1e418414767db8..4e9b8a82a3f630 100644 --- a/Modules/_xxinterpchannelsmodule.c +++ b/Modules/_xxinterpchannelsmodule.c @@ -1,8 +1,21 @@ /* interpreters module */ /* low-level access to interpreter primitives */ +#ifndef Py_BUILD_CORE_BUILTIN +# define Py_BUILD_CORE_MODULE 1 +#endif + #include "Python.h" #include "interpreteridobject.h" +#include "pycore_crossinterp.h" // struct _xid +#include "pycore_interp.h" // _PyInterpreterState_LookUpID() + +#ifdef MS_WINDOWS +#define WIN32_LEAN_AND_MEAN +#include // SwitchToThread() +#elif defined(HAVE_SCHED_H) +#include // sched_yield() +#endif /* @@ -15,7 +28,7 @@ _globals (static struct globals): next_id; (int64_t) mutex (PyThread_type_lock) head (linked list of struct _channelref *): - id (int64_t) + cid (int64_t) objcount (Py_ssize_t) next (struct _channelref *): ... @@ -29,7 +42,7 @@ _globals (static struct globals): numsendopen (int64_t) numrecvopen (int64_t) send (struct _channelend *): - interp (int64_t) + interpid (int64_t) open (int) next (struct _channelend *) recv (struct _channelend *): @@ -42,7 +55,7 @@ _globals (static struct globals): data (_PyCrossInterpreterData *): data (void *) obj (PyObject *) - interp (int64_t) + interpid (int64_t) new_object (xid_newobjectfunc) free (xid_freefunc) last (struct _channelitem *): @@ -76,6 +89,73 @@ API.. The module does not create any objects that are shared globally. PyMem_RawFree(VAR) +struct xid_class_registry { + size_t count; +#define MAX_XID_CLASSES 5 + struct { + PyTypeObject *cls; + } added[MAX_XID_CLASSES]; +}; + +static int +register_xid_class(PyTypeObject *cls, crossinterpdatafunc shared, + struct xid_class_registry *classes) +{ + int res = _PyCrossInterpreterData_RegisterClass(cls, shared); + if (res == 0) { + assert(classes->count < MAX_XID_CLASSES); + // The class has refs elsewhere, so we need to incref here. + classes->added[classes->count].cls = cls; + classes->count += 1; + } + return res; +} + +static void +clear_xid_class_registry(struct xid_class_registry *classes) +{ + while (classes->count > 0) { + classes->count -= 1; + PyTypeObject *cls = classes->added[classes->count].cls; + _PyCrossInterpreterData_UnregisterClass(cls); + } +} + +#define XID_IGNORE_EXC 1 +#define XID_FREE 2 + +static int +_release_xid_data(_PyCrossInterpreterData *data, int flags) +{ + int ignoreexc = flags & XID_IGNORE_EXC; + PyObject *exc; + if (ignoreexc) { + exc = PyErr_GetRaisedException(); + } + int res; + if (flags & XID_FREE) { + res = _PyCrossInterpreterData_ReleaseAndRawFree(data); + } + else { + res = _PyCrossInterpreterData_Release(data); + } + if (res < 0) { + /* The owning interpreter is already destroyed. */ + if (ignoreexc) { + // XXX Emit a warning? + PyErr_Clear(); + } + } + if (flags & XID_FREE) { + /* Either way, we free the data. */ + } + if (ignoreexc) { + PyErr_SetRaisedException(exc); + } + return res; +} + + static PyInterpreterState * _get_current_interp(void) { @@ -123,7 +203,7 @@ get_module_from_type(PyTypeObject *cls) static PyObject * add_new_exception(PyObject *mod, const char *name, PyObject *base) { - assert(!PyObject_HasAttrString(mod, name)); + assert(!PyObject_HasAttrStringWithError(mod, name)); PyObject *exctype = PyErr_NewException(name, base, NULL); if (exctype == NULL) { return NULL; @@ -140,10 +220,11 @@ add_new_exception(PyObject *mod, const char *name, PyObject *base) add_new_exception(MOD, MODULE_NAME "." Py_STRINGIFY(NAME), BASE) static PyTypeObject * -add_new_type(PyObject *mod, PyType_Spec *spec, crossinterpdatafunc shared) +add_new_type(PyObject *mod, PyType_Spec *spec, crossinterpdatafunc shared, + struct xid_class_registry *classes) { - PyTypeObject *cls = (PyTypeObject *)PyType_FromMetaclass( - NULL, mod, spec, NULL); + PyTypeObject *cls = (PyTypeObject *)PyType_FromModuleAndSpec( + mod, spec, NULL); if (cls == NULL) { return NULL; } @@ -152,7 +233,7 @@ add_new_type(PyObject *mod, PyType_Spec *spec, crossinterpdatafunc shared) return NULL; } if (shared != NULL) { - if (_PyCrossInterpreterData_RegisterClass(cls, shared)) { + if (register_xid_class(cls, shared, classes)) { Py_DECREF(cls); return NULL; } @@ -161,31 +242,37 @@ add_new_type(PyObject *mod, PyType_Spec *spec, crossinterpdatafunc shared) } static int -_release_xid_data(_PyCrossInterpreterData *data, int ignoreexc) +wait_for_lock(PyThread_type_lock mutex, PY_TIMEOUT_T timeout) { - PyObject *exc; - if (ignoreexc) { - exc = PyErr_GetRaisedException(); - } - int res = _PyCrossInterpreterData_Release(data); - if (res < 0) { - /* The owning interpreter is already destroyed. */ - if (ignoreexc) { - // XXX Emit a warning? - PyErr_Clear(); - } + PyLockStatus res = PyThread_acquire_lock_timed_with_retries(mutex, timeout); + if (res == PY_LOCK_INTR) { + /* KeyboardInterrupt, etc. */ + assert(PyErr_Occurred()); + return -1; } - if (ignoreexc) { - PyErr_SetRaisedException(exc); + else if (res == PY_LOCK_FAILURE) { + assert(!PyErr_Occurred()); + assert(timeout > 0); + PyErr_SetString(PyExc_TimeoutError, "timed out"); + return -1; } - return res; + assert(res == PY_LOCK_ACQUIRED); + PyThread_release_lock(mutex); + return 0; } /* module state *************************************************************/ typedef struct { + struct xid_class_registry xid_classes; + + /* Added at runtime by interpreters module. */ + PyTypeObject *send_channel_type; + PyTypeObject *recv_channel_type; + /* heap types */ + PyTypeObject *ChannelInfoType; PyTypeObject *ChannelIDType; /* exceptions */ @@ -205,10 +292,30 @@ get_module_state(PyObject *mod) return state; } +static module_state * +_get_current_module_state(void) +{ + PyObject *mod = _get_current_module(); + if (mod == NULL) { + // XXX import it? + PyErr_SetString(PyExc_RuntimeError, + MODULE_NAME " module not imported yet"); + return NULL; + } + module_state *state = get_module_state(mod); + Py_DECREF(mod); + return state; +} + static int traverse_module_state(module_state *state, visitproc visit, void *arg) { + /* external types */ + Py_VISIT(state->send_channel_type); + Py_VISIT(state->recv_channel_type); + /* heap types */ + Py_VISIT(state->ChannelInfoType); Py_VISIT(state->ChannelIDType); /* exceptions */ @@ -224,7 +331,12 @@ traverse_module_state(module_state *state, visitproc visit, void *arg) static int clear_module_state(module_state *state) { + /* external types */ + Py_CLEAR(state->send_channel_type); + Py_CLEAR(state->recv_channel_type); + /* heap types */ + Py_CLEAR(state->ChannelInfoType); if (state->ChannelIDType != NULL) { (void)_PyCrossInterpreterData_UnregisterClass(state->ChannelIDType); } @@ -247,6 +359,7 @@ clear_module_state(module_state *state) #define CHANNEL_BOTH 0 #define CHANNEL_RECV -1 + /* channel errors */ #define ERR_CHANNEL_NOT_FOUND -2 @@ -257,6 +370,7 @@ clear_module_state(module_state *state) #define ERR_CHANNEL_MUTEX_INIT -7 #define ERR_CHANNELS_MUTEX_INIT -8 #define ERR_NO_NEXT_CHANNEL_ID -9 +#define ERR_CHANNEL_CLOSED_WAITING -10 static int exceptions_init(PyObject *mod) @@ -308,6 +422,10 @@ handle_channel_error(int err, PyObject *mod, int64_t cid) PyErr_Format(state->ChannelClosedError, "channel %" PRId64 " is closed", cid); } + else if (err == ERR_CHANNEL_CLOSED_WAITING) { + PyErr_Format(state->ChannelClosedError, + "channel %" PRId64 " has closed", cid); + } else if (err == ERR_CHANNEL_INTERP_CLOSED) { PyErr_Format(state->ChannelClosedError, "channel %" PRId64 " is already closed", cid); @@ -340,38 +458,148 @@ handle_channel_error(int err, PyObject *mod, int64_t cid) return 1; } + /* the channel queue */ +typedef uintptr_t _channelitem_id_t; + +typedef struct wait_info { + PyThread_type_lock mutex; + enum { + WAITING_NO_STATUS = 0, + WAITING_ACQUIRED = 1, + WAITING_RELEASING = 2, + WAITING_RELEASED = 3, + } status; + int received; + _channelitem_id_t itemid; +} _waiting_t; + +static int +_waiting_init(_waiting_t *waiting) +{ + PyThread_type_lock mutex = PyThread_allocate_lock(); + if (mutex == NULL) { + PyErr_NoMemory(); + return -1; + } + + *waiting = (_waiting_t){ + .mutex = mutex, + .status = WAITING_NO_STATUS, + }; + return 0; +} + +static void +_waiting_clear(_waiting_t *waiting) +{ + assert(waiting->status != WAITING_ACQUIRED + && waiting->status != WAITING_RELEASING); + if (waiting->mutex != NULL) { + PyThread_free_lock(waiting->mutex); + waiting->mutex = NULL; + } +} + +static _channelitem_id_t +_waiting_get_itemid(_waiting_t *waiting) +{ + return waiting->itemid; +} + +static void +_waiting_acquire(_waiting_t *waiting) +{ + assert(waiting->status == WAITING_NO_STATUS); + PyThread_acquire_lock(waiting->mutex, NOWAIT_LOCK); + waiting->status = WAITING_ACQUIRED; +} + +static void +_waiting_release(_waiting_t *waiting, int received) +{ + assert(waiting->mutex != NULL); + assert(waiting->status == WAITING_ACQUIRED); + assert(!waiting->received); + + waiting->status = WAITING_RELEASING; + PyThread_release_lock(waiting->mutex); + if (waiting->received != received) { + assert(received == 1); + waiting->received = received; + } + waiting->status = WAITING_RELEASED; +} + +static void +_waiting_finish_releasing(_waiting_t *waiting) +{ + while (waiting->status == WAITING_RELEASING) { +#ifdef MS_WINDOWS + SwitchToThread(); +#elif defined(HAVE_SCHED_H) + sched_yield(); +#endif + } +} + struct _channelitem; typedef struct _channelitem { _PyCrossInterpreterData *data; + _waiting_t *waiting; struct _channelitem *next; } _channelitem; -static _channelitem * -_channelitem_new(void) +static inline _channelitem_id_t +_channelitem_ID(_channelitem *item) { - _channelitem *item = GLOBAL_MALLOC(_channelitem); - if (item == NULL) { - PyErr_NoMemory(); - return NULL; + return (_channelitem_id_t)item; +} + +static void +_channelitem_init(_channelitem *item, + _PyCrossInterpreterData *data, _waiting_t *waiting) +{ + *item = (_channelitem){ + .data = data, + .waiting = waiting, + }; + if (waiting != NULL) { + waiting->itemid = _channelitem_ID(item); } - item->data = NULL; - item->next = NULL; - return item; } static void _channelitem_clear(_channelitem *item) { + item->next = NULL; + if (item->data != NULL) { - (void)_release_xid_data(item->data, 1); - // It was allocated in _channel_send(). - GLOBAL_FREE(item->data); + // It was allocated in channel_send(). + (void)_release_xid_data(item->data, XID_IGNORE_EXC & XID_FREE); item->data = NULL; } - item->next = NULL; + + if (item->waiting != NULL) { + if (item->waiting->status == WAITING_ACQUIRED) { + _waiting_release(item->waiting, 0); + } + item->waiting = NULL; + } +} + +static _channelitem * +_channelitem_new(_PyCrossInterpreterData *data, _waiting_t *waiting) +{ + _channelitem *item = GLOBAL_MALLOC(_channelitem); + if (item == NULL) { + PyErr_NoMemory(); + return NULL; + } + _channelitem_init(item, data, waiting); + return item; } static void @@ -391,13 +619,17 @@ _channelitem_free_all(_channelitem *item) } } -static _PyCrossInterpreterData * -_channelitem_popped(_channelitem *item) +static void +_channelitem_popped(_channelitem *item, + _PyCrossInterpreterData **p_data, _waiting_t **p_waiting) { - _PyCrossInterpreterData *data = item->data; + assert(item->waiting == NULL || item->waiting->status == WAITING_ACQUIRED); + *p_data = item->data; + *p_waiting = item->waiting; + // We clear them here, so they won't be released in _channelitem_clear(). item->data = NULL; + item->waiting = NULL; _channelitem_free(item); - return data; } typedef struct _channelqueue { @@ -437,13 +669,13 @@ _channelqueue_free(_channelqueue *queue) } static int -_channelqueue_put(_channelqueue *queue, _PyCrossInterpreterData *data) +_channelqueue_put(_channelqueue *queue, + _PyCrossInterpreterData *data, _waiting_t *waiting) { - _channelitem *item = _channelitem_new(); + _channelitem *item = _channelitem_new(data, waiting); if (item == NULL) { return -1; } - item->data = data; queue->count += 1; if (queue->first == NULL) { @@ -453,15 +685,21 @@ _channelqueue_put(_channelqueue *queue, _PyCrossInterpreterData *data) queue->last->next = item; } queue->last = item; + + if (waiting != NULL) { + _waiting_acquire(waiting); + } + return 0; } -static _PyCrossInterpreterData * -_channelqueue_get(_channelqueue *queue) +static int +_channelqueue_get(_channelqueue *queue, + _PyCrossInterpreterData **p_data, _waiting_t **p_waiting) { _channelitem *item = queue->first; if (item == NULL) { - return NULL; + return ERR_CHANNEL_EMPTY; } queue->first = item->next; if (queue->last == item) { @@ -469,18 +707,84 @@ _channelqueue_get(_channelqueue *queue) } queue->count -= 1; - return _channelitem_popped(item); + _channelitem_popped(item, p_data, p_waiting); + return 0; +} + +static int +_channelqueue_find(_channelqueue *queue, _channelitem_id_t itemid, + _channelitem **p_item, _channelitem **p_prev) +{ + _channelitem *prev = NULL; + _channelitem *item = NULL; + if (queue->first != NULL) { + if (_channelitem_ID(queue->first) == itemid) { + item = queue->first; + } + else { + prev = queue->first; + while (prev->next != NULL) { + if (_channelitem_ID(prev->next) == itemid) { + item = prev->next; + break; + } + prev = prev->next; + } + if (item == NULL) { + prev = NULL; + } + } + } + if (p_item != NULL) { + *p_item = item; + } + if (p_prev != NULL) { + *p_prev = prev; + } + return (item != NULL); +} + +static void +_channelqueue_remove(_channelqueue *queue, _channelitem_id_t itemid, + _PyCrossInterpreterData **p_data, _waiting_t **p_waiting) +{ + _channelitem *prev = NULL; + _channelitem *item = NULL; + int found = _channelqueue_find(queue, itemid, &item, &prev); + if (!found) { + return; + } + + assert(item->waiting != NULL); + assert(!item->waiting->received); + if (prev == NULL) { + assert(queue->first == item); + queue->first = item->next; + } + else { + assert(queue->first != item); + assert(prev->next == item); + prev->next = item->next; + } + item->next = NULL; + + if (queue->last == item) { + queue->last = prev; + } + queue->count -= 1; + + _channelitem_popped(item, p_data, p_waiting); } static void -_channelqueue_drop_interpreter(_channelqueue *queue, int64_t interp) +_channelqueue_clear_interpreter(_channelqueue *queue, int64_t interpid) { _channelitem *prev = NULL; _channelitem *next = queue->first; while (next != NULL) { _channelitem *item = next; next = item->next; - if (item->data->interp == interp) { + if (item->data->interpid == interpid) { if (prev == NULL) { queue->first = item->next; } @@ -496,18 +800,19 @@ _channelqueue_drop_interpreter(_channelqueue *queue, int64_t interp) } } + /* channel-interpreter associations */ struct _channelend; typedef struct _channelend { struct _channelend *next; - int64_t interp; + int64_t interpid; int open; } _channelend; static _channelend * -_channelend_new(int64_t interp) +_channelend_new(int64_t interpid) { _channelend *end = GLOBAL_MALLOC(_channelend); if (end == NULL) { @@ -515,7 +820,7 @@ _channelend_new(int64_t interp) return NULL; } end->next = NULL; - end->interp = interp; + end->interpid = interpid; end->open = 1; return end; } @@ -537,12 +842,12 @@ _channelend_free_all(_channelend *end) } static _channelend * -_channelend_find(_channelend *first, int64_t interp, _channelend **pprev) +_channelend_find(_channelend *first, int64_t interpid, _channelend **pprev) { _channelend *prev = NULL; _channelend *end = first; while (end != NULL) { - if (end->interp == interp) { + if (end->interpid == interpid) { break; } prev = end; @@ -599,10 +904,10 @@ _channelends_free(_channelends *ends) } static _channelend * -_channelends_add(_channelends *ends, _channelend *prev, int64_t interp, +_channelends_add(_channelends *ends, _channelend *prev, int64_t interpid, int send) { - _channelend *end = _channelend_new(interp); + _channelend *end = _channelend_new(interpid); if (end == NULL) { return NULL; } @@ -628,11 +933,11 @@ _channelends_add(_channelends *ends, _channelend *prev, int64_t interp, } static int -_channelends_associate(_channelends *ends, int64_t interp, int send) +_channelends_associate(_channelends *ends, int64_t interpid, int send) { _channelend *prev; _channelend *end = _channelend_find(send ? ends->send : ends->recv, - interp, &prev); + interpid, &prev); if (end != NULL) { if (!end->open) { return ERR_CHANNEL_CLOSED; @@ -640,7 +945,7 @@ _channelends_associate(_channelends *ends, int64_t interp, int send) // already associated return 0; } - if (_channelends_add(ends, prev, interp, send) == NULL) { + if (_channelends_add(ends, prev, interpid, send) == NULL) { return -1; } return 0; @@ -650,16 +955,20 @@ static int _channelends_is_open(_channelends *ends) { if (ends->numsendopen != 0 || ends->numrecvopen != 0) { + // At least one interpreter is still associated with the channel + // (and hasn't been released). return 1; } + // XXX This is wrong if an end can ever be removed. if (ends->send == NULL && ends->recv == NULL) { + // The channel has never had any interpreters associated with it. return 1; } return 0; } static void -_channelends_close_end(_channelends *ends, _channelend *end, int send) +_channelends_release_end(_channelends *ends, _channelend *end, int send) { end->open = 0; if (send) { @@ -671,51 +980,37 @@ _channelends_close_end(_channelends *ends, _channelend *end, int send) } static int -_channelends_close_interpreter(_channelends *ends, int64_t interp, int which) +_channelends_release_interpreter(_channelends *ends, int64_t interpid, int which) { _channelend *prev; _channelend *end; if (which >= 0) { // send/both - end = _channelend_find(ends->send, interp, &prev); + end = _channelend_find(ends->send, interpid, &prev); if (end == NULL) { // never associated so add it - end = _channelends_add(ends, prev, interp, 1); + end = _channelends_add(ends, prev, interpid, 1); if (end == NULL) { return -1; } } - _channelends_close_end(ends, end, 1); + _channelends_release_end(ends, end, 1); } if (which <= 0) { // recv/both - end = _channelend_find(ends->recv, interp, &prev); + end = _channelend_find(ends->recv, interpid, &prev); if (end == NULL) { // never associated so add it - end = _channelends_add(ends, prev, interp, 0); + end = _channelends_add(ends, prev, interpid, 0); if (end == NULL) { return -1; } } - _channelends_close_end(ends, end, 0); + _channelends_release_end(ends, end, 0); } return 0; } static void -_channelends_drop_interpreter(_channelends *ends, int64_t interp) -{ - _channelend *end; - end = _channelend_find(ends->send, interp, NULL); - if (end != NULL) { - _channelends_close_end(ends, end, 1); - } - end = _channelend_find(ends->recv, interp, NULL); - if (end != NULL) { - _channelends_close_end(ends, end, 0); - } -} - -static void -_channelends_close_all(_channelends *ends, int which, int force) +_channelends_release_all(_channelends *ends, int which, int force) { // XXX Handle the ends. // XXX Handle force is True. @@ -723,16 +1018,32 @@ _channelends_close_all(_channelends *ends, int which, int force) // Ensure all the "send"-associated interpreters are closed. _channelend *end; for (end = ends->send; end != NULL; end = end->next) { - _channelends_close_end(ends, end, 1); + _channelends_release_end(ends, end, 1); } // Ensure all the "recv"-associated interpreters are closed. for (end = ends->recv; end != NULL; end = end->next) { - _channelends_close_end(ends, end, 0); + _channelends_release_end(ends, end, 0); } } -/* channels */ +static void +_channelends_clear_interpreter(_channelends *ends, int64_t interpid) +{ + // XXX Actually remove the entries? + _channelend *end; + end = _channelend_find(ends->send, interpid, NULL); + if (end != NULL) { + _channelends_release_end(ends, end, 1); + } + end = _channelend_find(ends->recv, interpid, NULL); + if (end != NULL) { + _channelends_release_end(ends, end, 0); + } +} + + +/* each channel's state */ struct _channel; struct _channel_closing; @@ -745,12 +1056,12 @@ typedef struct _channel { _channelends *ends; int open; struct _channel_closing *closing; -} _PyChannelState; +} _channel_state; -static _PyChannelState * +static _channel_state * _channel_new(PyThread_type_lock mutex) { - _PyChannelState *chan = GLOBAL_MALLOC(_PyChannelState); + _channel_state *chan = GLOBAL_MALLOC(_channel_state); if (chan == NULL) { return NULL; } @@ -772,7 +1083,7 @@ _channel_new(PyThread_type_lock mutex) } static void -_channel_free(_PyChannelState *chan) +_channel_free(_channel_state *chan) { _channel_clear_closing(chan); PyThread_acquire_lock(chan->mutex, WAIT_LOCK); @@ -785,8 +1096,8 @@ _channel_free(_PyChannelState *chan) } static int -_channel_add(_PyChannelState *chan, int64_t interp, - _PyCrossInterpreterData *data) +_channel_add(_channel_state *chan, int64_t interpid, + _PyCrossInterpreterData *data, _waiting_t *waiting) { int res = -1; PyThread_acquire_lock(chan->mutex, WAIT_LOCK); @@ -795,14 +1106,15 @@ _channel_add(_PyChannelState *chan, int64_t interp, res = ERR_CHANNEL_CLOSED; goto done; } - if (_channelends_associate(chan->ends, interp, 1) != 0) { + if (_channelends_associate(chan->ends, interpid, 1) != 0) { res = ERR_CHANNEL_INTERP_CLOSED; goto done; } - if (_channelqueue_put(chan->queue, data) != 0) { + if (_channelqueue_put(chan->queue, data, waiting) != 0) { goto done; } + // Any errors past this point must cause a _waiting_release() call. res = 0; done: @@ -811,8 +1123,8 @@ _channel_add(_PyChannelState *chan, int64_t interp, } static int -_channel_next(_PyChannelState *chan, int64_t interp, - _PyCrossInterpreterData **res) +_channel_next(_channel_state *chan, int64_t interpid, + _PyCrossInterpreterData **p_data, _waiting_t **p_waiting) { int err = 0; PyThread_acquire_lock(chan->mutex, WAIT_LOCK); @@ -821,16 +1133,17 @@ _channel_next(_PyChannelState *chan, int64_t interp, err = ERR_CHANNEL_CLOSED; goto done; } - if (_channelends_associate(chan->ends, interp, 0) != 0) { + if (_channelends_associate(chan->ends, interpid, 0) != 0) { err = ERR_CHANNEL_INTERP_CLOSED; goto done; } - _PyCrossInterpreterData *data = _channelqueue_get(chan->queue); - if (data == NULL && !PyErr_Occurred() && chan->closing != NULL) { + int empty = _channelqueue_get(chan->queue, p_data, p_waiting); + assert(empty == 0 || empty == ERR_CHANNEL_EMPTY); + assert(!PyErr_Occurred()); + if (empty && chan->closing != NULL) { chan->open = 0; } - *res = data; done: PyThread_release_lock(chan->mutex); @@ -840,8 +1153,28 @@ _channel_next(_PyChannelState *chan, int64_t interp, return err; } +static void +_channel_remove(_channel_state *chan, _channelitem_id_t itemid) +{ + _PyCrossInterpreterData *data = NULL; + _waiting_t *waiting = NULL; + + PyThread_acquire_lock(chan->mutex, WAIT_LOCK); + _channelqueue_remove(chan->queue, itemid, &data, &waiting); + PyThread_release_lock(chan->mutex); + + (void)_release_xid_data(data, XID_IGNORE_EXC | XID_FREE); + if (waiting != NULL) { + _waiting_release(waiting, 0); + } + + if (chan->queue->count == 0) { + _channel_finish_closing(chan); + } +} + static int -_channel_close_interpreter(_PyChannelState *chan, int64_t interp, int end) +_channel_release_interpreter(_channel_state *chan, int64_t interpid, int end) { PyThread_acquire_lock(chan->mutex, WAIT_LOCK); @@ -851,10 +1184,12 @@ _channel_close_interpreter(_PyChannelState *chan, int64_t interp, int end) goto done; } - if (_channelends_close_interpreter(chan->ends, interp, end) != 0) { + if (_channelends_release_interpreter(chan->ends, interpid, end) != 0) { goto done; } chan->open = _channelends_is_open(chan->ends); + // XXX Clear the queue if not empty? + // XXX Activate the "closing" mechanism? res = 0; done: @@ -862,20 +1197,8 @@ _channel_close_interpreter(_PyChannelState *chan, int64_t interp, int end) return res; } -static void -_channel_drop_interpreter(_PyChannelState *chan, int64_t interp) -{ - PyThread_acquire_lock(chan->mutex, WAIT_LOCK); - - _channelqueue_drop_interpreter(chan->queue, interp); - _channelends_drop_interpreter(chan->ends, interp); - chan->open = _channelends_is_open(chan->ends); - - PyThread_release_lock(chan->mutex); -} - static int -_channel_close_all(_PyChannelState *chan, int end, int force) +_channel_release_all(_channel_state *chan, int end, int force) { int res = -1; PyThread_acquire_lock(chan->mutex, WAIT_LOCK); @@ -889,12 +1212,13 @@ _channel_close_all(_PyChannelState *chan, int end, int force) res = ERR_CHANNEL_NOT_EMPTY; goto done; } + // XXX Clear the queue? chan->open = 0; // We *could* also just leave these in place, since we've marked // the channel as closed already. - _channelends_close_all(chan->ends, end, force); + _channelends_release_all(chan->ends, end, force); res = 0; done: @@ -902,25 +1226,39 @@ _channel_close_all(_PyChannelState *chan, int end, int force) return res; } +static void +_channel_clear_interpreter(_channel_state *chan, int64_t interpid) +{ + PyThread_acquire_lock(chan->mutex, WAIT_LOCK); + + _channelqueue_clear_interpreter(chan->queue, interpid); + _channelends_clear_interpreter(chan->ends, interpid); + chan->open = _channelends_is_open(chan->ends); + + PyThread_release_lock(chan->mutex); +} + + /* the set of channels */ struct _channelref; typedef struct _channelref { - int64_t id; - _PyChannelState *chan; + int64_t cid; + _channel_state *chan; struct _channelref *next; + // The number of ChannelID objects referring to this channel. Py_ssize_t objcount; } _channelref; static _channelref * -_channelref_new(int64_t id, _PyChannelState *chan) +_channelref_new(int64_t cid, _channel_state *chan) { _channelref *ref = GLOBAL_MALLOC(_channelref); if (ref == NULL) { return NULL; } - ref->id = id; + ref->cid = cid; ref->chan = chan; ref->next = NULL; ref->objcount = 0; @@ -930,7 +1268,7 @@ _channelref_new(int64_t id, _PyChannelState *chan) //static void //_channelref_clear(_channelref *ref) //{ -// ref->id = -1; +// ref->cid = -1; // ref->chan = NULL; // ref->next = NULL; // ref->objcount = 0; @@ -947,12 +1285,12 @@ _channelref_free(_channelref *ref) } static _channelref * -_channelref_find(_channelref *first, int64_t id, _channelref **pprev) +_channelref_find(_channelref *first, int64_t cid, _channelref **pprev) { _channelref *prev = NULL; _channelref *ref = first; while (ref != NULL) { - if (ref->id == id) { + if (ref->cid == cid) { break; } prev = ref; @@ -964,6 +1302,7 @@ _channelref_find(_channelref *first, int64_t id, _channelref **pprev) return ref; } + typedef struct _channels { PyThread_type_lock mutex; _channelref *head; @@ -994,27 +1333,27 @@ _channels_fini(_channels *channels) static int64_t _channels_next_id(_channels *channels) // needs lock { - int64_t id = channels->next_id; - if (id < 0) { + int64_t cid = channels->next_id; + if (cid < 0) { /* overflow */ return -1; } channels->next_id += 1; - return id; + return cid; } static int -_channels_lookup(_channels *channels, int64_t id, PyThread_type_lock *pmutex, - _PyChannelState **res) +_channels_lookup(_channels *channels, int64_t cid, PyThread_type_lock *pmutex, + _channel_state **res) { int err = -1; - _PyChannelState *chan = NULL; + _channel_state *chan = NULL; PyThread_acquire_lock(channels->mutex, WAIT_LOCK); if (pmutex != NULL) { *pmutex = NULL; } - _channelref *ref = _channelref_find(channels->head, id, NULL); + _channelref *ref = _channelref_find(channels->head, cid, NULL); if (ref == NULL) { err = ERR_CHANNEL_NOT_FOUND; goto done; @@ -1041,18 +1380,18 @@ _channels_lookup(_channels *channels, int64_t id, PyThread_type_lock *pmutex, } static int64_t -_channels_add(_channels *channels, _PyChannelState *chan) +_channels_add(_channels *channels, _channel_state *chan) { int64_t cid = -1; PyThread_acquire_lock(channels->mutex, WAIT_LOCK); // Create a new ref. - int64_t id = _channels_next_id(channels); - if (id < 0) { + int64_t _cid = _channels_next_id(channels); + if (_cid < 0) { cid = ERR_NO_NEXT_CHANNEL_ID; goto done; } - _channelref *ref = _channelref_new(id, chan); + _channelref *ref = _channelref_new(_cid, chan); if (ref == NULL) { goto done; } @@ -1063,17 +1402,17 @@ _channels_add(_channels *channels, _PyChannelState *chan) channels->head = ref; channels->numopen += 1; - cid = id; + cid = _cid; done: PyThread_release_lock(channels->mutex); return cid; } /* forward */ -static int _channel_set_closing(struct _channelref *, PyThread_type_lock); +static int _channel_set_closing(_channelref *, PyThread_type_lock); static int -_channels_close(_channels *channels, int64_t cid, _PyChannelState **pchan, +_channels_close(_channels *channels, int64_t cid, _channel_state **pchan, int end, int force) { int res = -1; @@ -1097,7 +1436,7 @@ _channels_close(_channels *channels, int64_t cid, _PyChannelState **pchan, goto done; } else { - int err = _channel_close_all(ref->chan, end, force); + int err = _channel_release_all(ref->chan, end, force); if (err != 0) { if (end == CHANNEL_SEND && err == ERR_CHANNEL_NOT_EMPTY) { if (ref->chan->closing != NULL) { @@ -1139,7 +1478,7 @@ _channels_close(_channels *channels, int64_t cid, _PyChannelState **pchan, static void _channels_remove_ref(_channels *channels, _channelref *ref, _channelref *prev, - _PyChannelState **pchan) + _channel_state **pchan) { if (ref == channels->head) { channels->head = ref->next; @@ -1156,7 +1495,7 @@ _channels_remove_ref(_channels *channels, _channelref *ref, _channelref *prev, } static int -_channels_remove(_channels *channels, int64_t id, _PyChannelState **pchan) +_channels_remove(_channels *channels, int64_t cid, _channel_state **pchan) { int res = -1; PyThread_acquire_lock(channels->mutex, WAIT_LOCK); @@ -1166,7 +1505,7 @@ _channels_remove(_channels *channels, int64_t id, _PyChannelState **pchan) } _channelref *prev = NULL; - _channelref *ref = _channelref_find(channels->head, id, &prev); + _channelref *ref = _channelref_find(channels->head, cid, &prev); if (ref == NULL) { res = ERR_CHANNEL_NOT_FOUND; goto done; @@ -1181,12 +1520,12 @@ _channels_remove(_channels *channels, int64_t id, _PyChannelState **pchan) } static int -_channels_add_id_object(_channels *channels, int64_t id) +_channels_add_id_object(_channels *channels, int64_t cid) { int res = -1; PyThread_acquire_lock(channels->mutex, WAIT_LOCK); - _channelref *ref = _channelref_find(channels->head, id, NULL); + _channelref *ref = _channelref_find(channels->head, cid, NULL); if (ref == NULL) { res = ERR_CHANNEL_NOT_FOUND; goto done; @@ -1200,12 +1539,12 @@ _channels_add_id_object(_channels *channels, int64_t id) } static void -_channels_drop_id_object(_channels *channels, int64_t id) +_channels_release_cid_object(_channels *channels, int64_t cid) { PyThread_acquire_lock(channels->mutex, WAIT_LOCK); _channelref *prev = NULL; - _channelref *ref = _channelref_find(channels->head, id, &prev); + _channelref *ref = _channelref_find(channels->head, cid, &prev); if (ref == NULL) { // Already destroyed. goto done; @@ -1214,7 +1553,7 @@ _channels_drop_id_object(_channels *channels, int64_t id) // Destroy if no longer used. if (ref->objcount == 0) { - _PyChannelState *chan = NULL; + _channel_state *chan = NULL; _channels_remove_ref(channels, ref, prev, &chan); if (chan != NULL) { _channel_free(chan); @@ -1236,7 +1575,7 @@ _channels_list_all(_channels *channels, int64_t *count) } _channelref *ref = channels->head; for (int64_t i=0; ref != NULL; ref = ref->next, i++) { - ids[i] = ref->id; + ids[i] = ref->cid; } *count = channels->numopen; @@ -1247,29 +1586,30 @@ _channels_list_all(_channels *channels, int64_t *count) } static void -_channels_drop_interpreter(_channels *channels, int64_t interp) +_channels_clear_interpreter(_channels *channels, int64_t interpid) { PyThread_acquire_lock(channels->mutex, WAIT_LOCK); _channelref *ref = channels->head; for (; ref != NULL; ref = ref->next) { if (ref->chan != NULL) { - _channel_drop_interpreter(ref->chan, interp); + _channel_clear_interpreter(ref->chan, interpid); } } PyThread_release_lock(channels->mutex); } + /* support for closing non-empty channels */ struct _channel_closing { - struct _channelref *ref; + _channelref *ref; }; static int -_channel_set_closing(struct _channelref *ref, PyThread_type_lock mutex) { - struct _channel *chan = ref->chan; +_channel_set_closing(_channelref *ref, PyThread_type_lock mutex) { + _channel_state *chan = ref->chan; if (chan == NULL) { // already closed return 0; @@ -1293,7 +1633,7 @@ _channel_set_closing(struct _channelref *ref, PyThread_type_lock mutex) { } static void -_channel_clear_closing(struct _channel *chan) { +_channel_clear_closing(_channel_state *chan) { PyThread_acquire_lock(chan->mutex, WAIT_LOCK); if (chan->closing != NULL) { GLOBAL_FREE(chan->closing); @@ -1303,7 +1643,7 @@ _channel_clear_closing(struct _channel *chan) { } static void -_channel_finish_closing(struct _channel *chan) { +_channel_finish_closing(_channel_state *chan) { struct _channel_closing *closing = chan->closing; if (closing == NULL) { return; @@ -1315,32 +1655,35 @@ _channel_finish_closing(struct _channel *chan) { _channel_free(chan); } + /* "high"-level channel-related functions */ +// Create a new channel. static int64_t -_channel_create(_channels *channels) +channel_create(_channels *channels) { PyThread_type_lock mutex = PyThread_allocate_lock(); if (mutex == NULL) { return ERR_CHANNEL_MUTEX_INIT; } - _PyChannelState *chan = _channel_new(mutex); + _channel_state *chan = _channel_new(mutex); if (chan == NULL) { PyThread_free_lock(mutex); return -1; } - int64_t id = _channels_add(channels, chan); - if (id < 0) { + int64_t cid = _channels_add(channels, chan); + if (cid < 0) { _channel_free(chan); } - return id; + return cid; } +// Completely destroy the channel. static int -_channel_destroy(_channels *channels, int64_t id) +channel_destroy(_channels *channels, int64_t cid) { - _PyChannelState *chan = NULL; - int err = _channels_remove(channels, id, &chan); + _channel_state *chan = NULL; + int err = _channels_remove(channels, cid, &chan); if (err != 0) { return err; } @@ -1350,18 +1693,23 @@ _channel_destroy(_channels *channels, int64_t id) return 0; } +// Push an object onto the channel. +// The current interpreter gets associated with the send end of the channel. +// Optionally request to be notified when it is received. static int -_channel_send(_channels *channels, int64_t id, PyObject *obj) +channel_send(_channels *channels, int64_t cid, PyObject *obj, + _waiting_t *waiting) { PyInterpreterState *interp = _get_current_interp(); if (interp == NULL) { return -1; } + int64_t interpid = PyInterpreterState_GetID(interp); // Look up the channel. PyThread_type_lock mutex = NULL; - _PyChannelState *chan = NULL; - int err = _channels_lookup(channels, id, &mutex, &chan); + _channel_state *chan = NULL; + int err = _channels_lookup(channels, cid, &mutex, &chan); if (err != 0) { return err; } @@ -1386,7 +1734,7 @@ _channel_send(_channels *channels, int64_t id, PyObject *obj) } // Add the data to the channel. - int res = _channel_add(chan, PyInterpreterState_GetID(interp), data); + int res = _channel_add(chan, interpid, data, waiting); PyThread_release_lock(mutex); if (res != 0) { // We may chain an exception here: @@ -1398,13 +1746,90 @@ _channel_send(_channels *channels, int64_t id, PyObject *obj) return 0; } -static int -_channel_recv(_channels *channels, int64_t id, PyObject **res) +// Basically, un-send an object. +static void +channel_clear_sent(_channels *channels, int64_t cid, _waiting_t *waiting) { - int err; - *res = NULL; + // Look up the channel. + PyThread_type_lock mutex = NULL; + _channel_state *chan = NULL; + int err = _channels_lookup(channels, cid, &mutex, &chan); + if (err != 0) { + // The channel was already closed, etc. + assert(waiting->status == WAITING_RELEASED); + return; // Ignore the error. + } + assert(chan != NULL); + // Past this point we are responsible for releasing the mutex. - PyInterpreterState *interp = _get_current_interp(); + _channelitem_id_t itemid = _waiting_get_itemid(waiting); + _channel_remove(chan, itemid); + + PyThread_release_lock(mutex); +} + +// Like channel_send(), but strictly wait for the object to be received. +static int +channel_send_wait(_channels *channels, int64_t cid, PyObject *obj, + PY_TIMEOUT_T timeout) +{ + // We use a stack variable here, so we must ensure that &waiting + // is not held by any channel item at the point this function exits. + _waiting_t waiting; + if (_waiting_init(&waiting) < 0) { + assert(PyErr_Occurred()); + return -1; + } + + /* Queue up the object. */ + int res = channel_send(channels, cid, obj, &waiting); + if (res < 0) { + assert(waiting.status == WAITING_NO_STATUS); + goto finally; + } + + /* Wait until the object is received. */ + if (wait_for_lock(waiting.mutex, timeout) < 0) { + assert(PyErr_Occurred()); + _waiting_finish_releasing(&waiting); + /* The send() call is failing now, so make sure the item + won't be received. */ + channel_clear_sent(channels, cid, &waiting); + assert(waiting.status == WAITING_RELEASED); + if (!waiting.received) { + res = -1; + goto finally; + } + // XXX Emit a warning if not a TimeoutError? + PyErr_Clear(); + } + else { + _waiting_finish_releasing(&waiting); + assert(waiting.status == WAITING_RELEASED); + if (!waiting.received) { + res = ERR_CHANNEL_CLOSED_WAITING; + goto finally; + } + } + + /* success! */ + res = 0; + +finally: + _waiting_clear(&waiting); + return res; +} + +// Pop the next object off the channel. Fail if empty. +// The current interpreter gets associated with the recv end of the channel. +// XXX Support a "wait" mutex? +static int +channel_recv(_channels *channels, int64_t cid, PyObject **res) +{ + int err; + *res = NULL; + + PyInterpreterState *interp = _get_current_interp(); if (interp == NULL) { // XXX Is this always an error? if (PyErr_Occurred()) { @@ -1412,11 +1837,12 @@ _channel_recv(_channels *channels, int64_t id, PyObject **res) } return 0; } + int64_t interpid = PyInterpreterState_GetID(interp); // Look up the channel. PyThread_type_lock mutex = NULL; - _PyChannelState *chan = NULL; - err = _channels_lookup(channels, id, &mutex, &chan); + _channel_state *chan = NULL; + err = _channels_lookup(channels, cid, &mutex, &chan); if (err != 0) { return err; } @@ -1425,7 +1851,8 @@ _channel_recv(_channels *channels, int64_t id, PyObject **res) // Pop off the next item from the channel. _PyCrossInterpreterData *data = NULL; - err = _channel_next(chan, PyInterpreterState_GetID(interp), &data); + _waiting_t *waiting = NULL; + err = _channel_next(chan, interpid, &data, &waiting); PyThread_release_lock(mutex); if (err != 0) { return err; @@ -1439,59 +1866,77 @@ _channel_recv(_channels *channels, int64_t id, PyObject **res) PyObject *obj = _PyCrossInterpreterData_NewObject(data); if (obj == NULL) { assert(PyErr_Occurred()); - (void)_release_xid_data(data, 1); - // It was allocated in _channel_send(). - GLOBAL_FREE(data); + // It was allocated in channel_send(), so we free it. + (void)_release_xid_data(data, XID_IGNORE_EXC | XID_FREE); + if (waiting != NULL) { + _waiting_release(waiting, 0); + } return -1; } - int release_res = _release_xid_data(data, 0); - // It was allocated in _channel_send(). - GLOBAL_FREE(data); + // It was allocated in channel_send(), so we free it. + int release_res = _release_xid_data(data, XID_FREE); if (release_res < 0) { // The source interpreter has been destroyed already. assert(PyErr_Occurred()); Py_DECREF(obj); + if (waiting != NULL) { + _waiting_release(waiting, 0); + } return -1; } + // Notify the sender. + if (waiting != NULL) { + _waiting_release(waiting, 1); + } + *res = obj; return 0; } +// Disallow send/recv for the current interpreter. +// The channel is marked as closed if no other interpreters +// are currently associated. static int -_channel_drop(_channels *channels, int64_t id, int send, int recv) +channel_release(_channels *channels, int64_t cid, int send, int recv) { PyInterpreterState *interp = _get_current_interp(); if (interp == NULL) { return -1; } + int64_t interpid = PyInterpreterState_GetID(interp); // Look up the channel. PyThread_type_lock mutex = NULL; - _PyChannelState *chan = NULL; - int err = _channels_lookup(channels, id, &mutex, &chan); + _channel_state *chan = NULL; + int err = _channels_lookup(channels, cid, &mutex, &chan); if (err != 0) { return err; } // Past this point we are responsible for releasing the mutex. // Close one or both of the two ends. - int res = _channel_close_interpreter(chan, PyInterpreterState_GetID(interp), send-recv); + int res = _channel_release_interpreter(chan, interpid, send-recv); PyThread_release_lock(mutex); return res; } +// Close the channel (for all interpreters). Fail if it's already closed. +// Close immediately if it's empty. Otherwise, disallow sending and +// finally close once empty. Optionally, immediately clear and close it. static int -_channel_close(_channels *channels, int64_t id, int end, int force) +channel_close(_channels *channels, int64_t cid, int end, int force) { - return _channels_close(channels, id, NULL, end, force); + return _channels_close(channels, cid, NULL, end, force); } +// Return true if the identified interpreter is associated +// with the given end of the channel. static int -_channel_is_associated(_channels *channels, int64_t cid, int64_t interp, +channel_is_associated(_channels *channels, int64_t cid, int64_t interpid, int send) { - _PyChannelState *chan = NULL; + _channel_state *chan = NULL; int err = _channels_lookup(channels, cid, NULL, &chan); if (err != 0) { return err; @@ -1501,16 +1946,247 @@ _channel_is_associated(_channels *channels, int64_t cid, int64_t interp, } _channelend *end = _channelend_find(send ? chan->ends->send : chan->ends->recv, - interp, NULL); + interpid, NULL); return (end != NULL && end->open); } + +/* channel info */ + +struct channel_info { + struct { + // 1: closed; -1: closing + int closed; + struct { + Py_ssize_t nsend_only; // not released + Py_ssize_t nsend_only_released; + Py_ssize_t nrecv_only; // not released + Py_ssize_t nrecv_only_released; + Py_ssize_t nboth; // not released + Py_ssize_t nboth_released; + Py_ssize_t nboth_send_released; + Py_ssize_t nboth_recv_released; + } all; + struct { + // 1: associated; -1: released + int send; + int recv; + } cur; + } status; + Py_ssize_t count; +}; + +static int +_channel_get_info(_channels *channels, int64_t cid, struct channel_info *info) +{ + int err = 0; + *info = (struct channel_info){0}; + + // Get the current interpreter. + PyInterpreterState *interp = _get_current_interp(); + if (interp == NULL) { + return -1; + } + Py_ssize_t interpid = PyInterpreterState_GetID(interp); + + // Hold the global lock until we're done. + PyThread_acquire_lock(channels->mutex, WAIT_LOCK); + + // Find the channel. + _channelref *ref = _channelref_find(channels->head, cid, NULL); + if (ref == NULL) { + err = ERR_CHANNEL_NOT_FOUND; + goto finally; + } + _channel_state *chan = ref->chan; + + // Check if open. + if (chan == NULL) { + info->status.closed = 1; + goto finally; + } + if (!chan->open) { + assert(chan->queue->count == 0); + info->status.closed = 1; + goto finally; + } + if (chan->closing != NULL) { + assert(chan->queue->count > 0); + info->status.closed = -1; + } + else { + info->status.closed = 0; + } + + // Get the number of queued objects. + info->count = chan->queue->count; + + // Get the ends statuses. + assert(info->status.cur.send == 0); + assert(info->status.cur.recv == 0); + _channelend *send = chan->ends->send; + while (send != NULL) { + if (send->interpid == interpid) { + info->status.cur.send = send->open ? 1 : -1; + } + + if (send->open) { + info->status.all.nsend_only += 1; + } + else { + info->status.all.nsend_only_released += 1; + } + send = send->next; + } + _channelend *recv = chan->ends->recv; + while (recv != NULL) { + if (recv->interpid == interpid) { + info->status.cur.recv = recv->open ? 1 : -1; + } + + // XXX This is O(n*n). Why do we have 2 linked lists? + _channelend *send = chan->ends->send; + while (send != NULL) { + if (send->interpid == recv->interpid) { + break; + } + send = send->next; + } + if (send == NULL) { + if (recv->open) { + info->status.all.nrecv_only += 1; + } + else { + info->status.all.nrecv_only_released += 1; + } + } + else { + if (recv->open) { + if (send->open) { + info->status.all.nboth += 1; + info->status.all.nsend_only -= 1; + } + else { + info->status.all.nboth_recv_released += 1; + info->status.all.nsend_only_released -= 1; + } + } + else { + if (send->open) { + info->status.all.nboth_send_released += 1; + info->status.all.nsend_only -= 1; + } + else { + info->status.all.nboth_released += 1; + info->status.all.nsend_only_released -= 1; + } + } + } + recv = recv->next; + } + +finally: + PyThread_release_lock(channels->mutex); + return err; +} + +PyDoc_STRVAR(channel_info_doc, +"ChannelInfo\n\ +\n\ +A named tuple of a channel's state."); + +static PyStructSequence_Field channel_info_fields[] = { + {"open", "both ends are open"}, + {"closing", "send is closed, recv is non-empty"}, + {"closed", "both ends are closed"}, + {"count", "queued objects"}, + + {"num_interp_send", "interpreters bound to the send end"}, + {"num_interp_send_released", + "interpreters bound to the send end and released"}, + + {"num_interp_recv", "interpreters bound to the send end"}, + {"num_interp_recv_released", + "interpreters bound to the send end and released"}, + + {"num_interp_both", "interpreters bound to both ends"}, + {"num_interp_both_released", + "interpreters bound to both ends and released_from_both"}, + {"num_interp_both_send_released", + "interpreters bound to both ends and released_from_the send end"}, + {"num_interp_both_recv_released", + "interpreters bound to both ends and released_from_the recv end"}, + + {"send_associated", "current interpreter is bound to the send end"}, + {"send_released", "current interpreter *was* bound to the send end"}, + {"recv_associated", "current interpreter is bound to the recv end"}, + {"recv_released", "current interpreter *was* bound to the recv end"}, + {0} +}; + +static PyStructSequence_Desc channel_info_desc = { + .name = MODULE_NAME ".ChannelInfo", + .doc = channel_info_doc, + .fields = channel_info_fields, + .n_in_sequence = 8, +}; + +static PyObject * +new_channel_info(PyObject *mod, struct channel_info *info) +{ + module_state *state = get_module_state(mod); + if (state == NULL) { + return NULL; + } + + assert(state->ChannelInfoType != NULL); + PyObject *self = PyStructSequence_New(state->ChannelInfoType); + if (self == NULL) { + return NULL; + } + + int pos = 0; +#define SET_BOOL(val) \ + PyStructSequence_SET_ITEM(self, pos++, \ + Py_NewRef(val ? Py_True : Py_False)) +#define SET_COUNT(val) \ + do { \ + PyObject *obj = PyLong_FromLongLong(val); \ + if (obj == NULL) { \ + Py_CLEAR(info); \ + return NULL; \ + } \ + PyStructSequence_SET_ITEM(self, pos++, obj); \ + } while(0) + SET_BOOL(info->status.closed == 0); + SET_BOOL(info->status.closed == -1); + SET_BOOL(info->status.closed == 1); + SET_COUNT(info->count); + SET_COUNT(info->status.all.nsend_only); + SET_COUNT(info->status.all.nsend_only_released); + SET_COUNT(info->status.all.nrecv_only); + SET_COUNT(info->status.all.nrecv_only_released); + SET_COUNT(info->status.all.nboth); + SET_COUNT(info->status.all.nboth_released); + SET_COUNT(info->status.all.nboth_send_released); + SET_COUNT(info->status.all.nboth_recv_released); + SET_BOOL(info->status.cur.send == 1); + SET_BOOL(info->status.cur.send == -1); + SET_BOOL(info->status.cur.recv == 1); + SET_BOOL(info->status.cur.recv == -1); +#undef SET_COUNT +#undef SET_BOOL + assert(!PyErr_Occurred()); + return self; +} + + /* ChannelID class */ typedef struct channelid { PyObject_HEAD - int64_t id; + int64_t cid; int end; int resolve; _channels *channels; @@ -1519,17 +2195,20 @@ typedef struct channelid { struct channel_id_converter_data { PyObject *module; int64_t cid; + int end; }; static int channel_id_converter(PyObject *arg, void *ptr) { int64_t cid; + int end = 0; struct channel_id_converter_data *data = ptr; module_state *state = get_module_state(data->module); assert(state != NULL); if (PyObject_TypeCheck(arg, state->ChannelIDType)) { - cid = ((channelid *)arg)->id; + cid = ((channelid *)arg)->cid; + end = ((channelid *)arg)->end; } else if (PyIndex_Check(arg)) { cid = PyLong_AsLongLong(arg); @@ -1549,6 +2228,7 @@ channel_id_converter(PyObject *arg, void *ptr) return 0; } data->cid = cid; + data->end = end; return 1; } @@ -1562,7 +2242,7 @@ newchannelid(PyTypeObject *cls, int64_t cid, int end, _channels *channels, if (self == NULL) { return -1; } - self->id = cid; + self->cid = cid; self->end = end; self->resolve = resolve; self->channels = channels; @@ -1590,6 +2270,7 @@ _channelid_new(PyObject *mod, PyTypeObject *cls, { static char *kwlist[] = {"id", "send", "recv", "force", "_resolve", NULL}; int64_t cid; + int end; struct channel_id_converter_data cid_data = { .module = mod, }; @@ -1604,6 +2285,7 @@ _channelid_new(PyObject *mod, PyTypeObject *cls, return NULL; } cid = cid_data.cid; + end = cid_data.end; // Handle "send" and "recv". if (send == 0 && recv == 0) { @@ -1611,33 +2293,36 @@ _channelid_new(PyObject *mod, PyTypeObject *cls, "'send' and 'recv' cannot both be False"); return NULL; } - - int end = 0; - if (send == 1) { + else if (send == 1) { if (recv == 0 || recv == -1) { end = CHANNEL_SEND; } + else { + assert(recv == 1); + end = 0; + } } else if (recv == 1) { + assert(send == 0 || send == -1); end = CHANNEL_RECV; } - PyObject *id = NULL; + PyObject *cidobj = NULL; int err = newchannelid(cls, cid, end, _global_channels(), force, resolve, - (channelid **)&id); + (channelid **)&cidobj); if (handle_channel_error(err, mod, cid)) { - assert(id == NULL); + assert(cidobj == NULL); return NULL; } - assert(id != NULL); - return id; + assert(cidobj != NULL); + return cidobj; } static void channelid_dealloc(PyObject *self) { - int64_t cid = ((channelid *)self)->id; + int64_t cid = ((channelid *)self)->cid; _channels *channels = ((channelid *)self)->channels; PyTypeObject *tp = Py_TYPE(self); @@ -1650,7 +2335,7 @@ channelid_dealloc(PyObject *self) // like we do for _abc._abc_data? Py_DECREF(tp); - _channels_drop_id_object(channels, cid); + _channels_release_cid_object(channels, cid); } static PyObject * @@ -1659,44 +2344,44 @@ channelid_repr(PyObject *self) PyTypeObject *type = Py_TYPE(self); const char *name = _PyType_Name(type); - channelid *cid = (channelid *)self; + channelid *cidobj = (channelid *)self; const char *fmt; - if (cid->end == CHANNEL_SEND) { + if (cidobj->end == CHANNEL_SEND) { fmt = "%s(%" PRId64 ", send=True)"; } - else if (cid->end == CHANNEL_RECV) { + else if (cidobj->end == CHANNEL_RECV) { fmt = "%s(%" PRId64 ", recv=True)"; } else { fmt = "%s(%" PRId64 ")"; } - return PyUnicode_FromFormat(fmt, name, cid->id); + return PyUnicode_FromFormat(fmt, name, cidobj->cid); } static PyObject * channelid_str(PyObject *self) { - channelid *cid = (channelid *)self; - return PyUnicode_FromFormat("%" PRId64 "", cid->id); + channelid *cidobj = (channelid *)self; + return PyUnicode_FromFormat("%" PRId64 "", cidobj->cid); } static PyObject * channelid_int(PyObject *self) { - channelid *cid = (channelid *)self; - return PyLong_FromLongLong(cid->id); + channelid *cidobj = (channelid *)self; + return PyLong_FromLongLong(cidobj->cid); } static Py_hash_t channelid_hash(PyObject *self) { - channelid *cid = (channelid *)self; - PyObject *id = PyLong_FromLongLong(cid->id); - if (id == NULL) { + channelid *cidobj = (channelid *)self; + PyObject *pyid = PyLong_FromLongLong(cidobj->cid); + if (pyid == NULL) { return -1; } - Py_hash_t hash = PyObject_Hash(id); - Py_DECREF(id); + Py_hash_t hash = PyObject_Hash(pyid); + Py_DECREF(pyid); return hash; } @@ -1722,11 +2407,11 @@ channelid_richcompare(PyObject *self, PyObject *other, int op) goto done; } - channelid *cid = (channelid *)self; + channelid *cidobj = (channelid *)self; int equal; if (PyObject_TypeCheck(other, state->ChannelIDType)) { - channelid *othercid = (channelid *)other; - equal = (cid->end == othercid->end) && (cid->id == othercid->id); + channelid *othercidobj = (channelid *)other; + equal = (cidobj->end == othercidobj->end) && (cidobj->cid == othercidobj->cid); } else if (PyLong_Check(other)) { /* Fast path */ @@ -1735,10 +2420,10 @@ channelid_richcompare(PyObject *self, PyObject *other, int op) if (othercid == -1 && PyErr_Occurred()) { goto done; } - equal = !overflow && (othercid >= 0) && (cid->id == othercid); + equal = !overflow && (othercid >= 0) && (cidobj->cid == othercid); } else if (PyNumber_Check(other)) { - PyObject *pyid = PyLong_FromLongLong(cid->id); + PyObject *pyid = PyLong_FromLongLong(cidobj->cid); if (pyid == NULL) { goto done; } @@ -1763,25 +2448,16 @@ channelid_richcompare(PyObject *self, PyObject *other, int op) return res; } +static PyTypeObject * _get_current_channelend_type(int end); + static PyObject * -_channel_from_cid(PyObject *cid, int end) +_channelobj_from_cidobj(PyObject *cidobj, int end) { - PyObject *highlevel = PyImport_ImportModule("interpreters"); - if (highlevel == NULL) { - PyErr_Clear(); - highlevel = PyImport_ImportModule("test.support.interpreters"); - if (highlevel == NULL) { - return NULL; - } - } - const char *clsname = (end == CHANNEL_RECV) ? "RecvChannel" : - "SendChannel"; - PyObject *cls = PyObject_GetAttrString(highlevel, clsname); - Py_DECREF(highlevel); + PyObject *cls = (PyObject *)_get_current_channelend_type(end); if (cls == NULL) { return NULL; } - PyObject *chan = PyObject_CallFunctionObjArgs(cls, cid, NULL); + PyObject *chan = PyObject_CallFunctionObjArgs(cls, cidobj, NULL); Py_DECREF(cls); if (chan == NULL) { return NULL; @@ -1790,7 +2466,7 @@ _channel_from_cid(PyObject *cid, int end) } struct _channelid_xid { - int64_t id; + int64_t cid; int end; int resolve; }; @@ -1812,16 +2488,16 @@ _channelid_from_xid(_PyCrossInterpreterData *data) } // Note that we do not preserve the "resolve" flag. - PyObject *cid = NULL; - int err = newchannelid(state->ChannelIDType, xid->id, xid->end, + PyObject *cidobj = NULL; + int err = newchannelid(state->ChannelIDType, xid->cid, xid->end, _global_channels(), 0, 0, - (channelid **)&cid); + (channelid **)&cidobj); if (err != 0) { - assert(cid == NULL); - (void)handle_channel_error(err, mod, xid->id); + assert(cidobj == NULL); + (void)handle_channel_error(err, mod, xid->cid); goto done; } - assert(cid != NULL); + assert(cidobj != NULL); if (xid->end == 0) { goto done; } @@ -1830,17 +2506,17 @@ _channelid_from_xid(_PyCrossInterpreterData *data) } /* Try returning a high-level channel end but fall back to the ID. */ - PyObject *chan = _channel_from_cid(cid, xid->end); + PyObject *chan = _channelobj_from_cidobj(cidobj, xid->end); if (chan == NULL) { PyErr_Clear(); goto done; } - Py_DECREF(cid); - cid = chan; + Py_DECREF(cidobj); + cidobj = chan; done: Py_DECREF(mod); - return cid; + return cidobj; } static int @@ -1855,7 +2531,7 @@ _channelid_shared(PyThreadState *tstate, PyObject *obj, return -1; } struct _channelid_xid *xid = (struct _channelid_xid *)data->data; - xid->id = ((channelid *)obj)->id; + xid->cid = ((channelid *)obj)->cid; xid->end = ((channelid *)obj)->end; xid->resolve = ((channelid *)obj)->resolve; return 0; @@ -1865,30 +2541,30 @@ static PyObject * channelid_end(PyObject *self, void *end) { int force = 1; - channelid *cid = (channelid *)self; + channelid *cidobj = (channelid *)self; if (end != NULL) { - PyObject *id = NULL; - int err = newchannelid(Py_TYPE(self), cid->id, *(int *)end, - cid->channels, force, cid->resolve, - (channelid **)&id); + PyObject *obj = NULL; + int err = newchannelid(Py_TYPE(self), cidobj->cid, *(int *)end, + cidobj->channels, force, cidobj->resolve, + (channelid **)&obj); if (err != 0) { - assert(id == NULL); + assert(obj == NULL); PyObject *mod = get_module_from_type(Py_TYPE(self)); if (mod == NULL) { return NULL; } - (void)handle_channel_error(err, mod, cid->id); + (void)handle_channel_error(err, mod, cidobj->cid); Py_DECREF(mod); return NULL; } - assert(id != NULL); - return id; + assert(obj != NULL); + return obj; } - if (cid->end == CHANNEL_SEND) { + if (cidobj->end == CHANNEL_SEND) { return PyUnicode_InternFromString("send"); } - if (cid->end == CHANNEL_RECV) { + if (cidobj->end == CHANNEL_RECV) { return PyUnicode_InternFromString("recv"); } return PyUnicode_InternFromString("both"); @@ -1910,7 +2586,7 @@ static PyGetSetDef channelid_getsets[] = { PyDoc_STRVAR(channelid_doc, "A channel ID identifies a channel and may be used as an int."); -static PyType_Slot ChannelIDType_slots[] = { +static PyType_Slot channelid_typeslots[] = { {Py_tp_dealloc, (destructor)channelid_dealloc}, {Py_tp_doc, (void *)channelid_doc}, {Py_tp_repr, (reprfunc)channelid_repr}, @@ -1924,15 +2600,119 @@ static PyType_Slot ChannelIDType_slots[] = { {0, NULL}, }; -static PyType_Spec ChannelIDType_spec = { +static PyType_Spec channelid_typespec = { .name = MODULE_NAME ".ChannelID", .basicsize = sizeof(channelid), .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_DISALLOW_INSTANTIATION | Py_TPFLAGS_IMMUTABLETYPE), - .slots = ChannelIDType_slots, + .slots = channelid_typeslots, }; +/* SendChannel and RecvChannel classes */ + +// XXX Use a new __xid__ protocol instead? + +static PyTypeObject * +_get_current_channelend_type(int end) +{ + module_state *state = _get_current_module_state(); + if (state == NULL) { + return NULL; + } + PyTypeObject *cls; + if (end == CHANNEL_SEND) { + cls = state->send_channel_type; + } + else { + assert(end == CHANNEL_RECV); + cls = state->recv_channel_type; + } + if (cls == NULL) { + // Force the module to be loaded, to register the type. + PyObject *highlevel = PyImport_ImportModule("interpreters.channel"); + if (highlevel == NULL) { + PyErr_Clear(); + highlevel = PyImport_ImportModule("test.support.interpreters.channel"); + if (highlevel == NULL) { + return NULL; + } + } + Py_DECREF(highlevel); + if (end == CHANNEL_SEND) { + cls = state->send_channel_type; + } + else { + cls = state->recv_channel_type; + } + assert(cls != NULL); + } + return cls; +} + +static PyObject * +_channelend_from_xid(_PyCrossInterpreterData *data) +{ + channelid *cidobj = (channelid *)_channelid_from_xid(data); + if (cidobj == NULL) { + return NULL; + } + PyTypeObject *cls = _get_current_channelend_type(cidobj->end); + if (cls == NULL) { + Py_DECREF(cidobj); + return NULL; + } + PyObject *obj = PyObject_CallOneArg((PyObject *)cls, (PyObject *)cidobj); + Py_DECREF(cidobj); + return obj; +} + +static int +_channelend_shared(PyThreadState *tstate, PyObject *obj, + _PyCrossInterpreterData *data) +{ + PyObject *cidobj = PyObject_GetAttrString(obj, "_id"); + if (cidobj == NULL) { + return -1; + } + int res = _channelid_shared(tstate, cidobj, data); + Py_DECREF(cidobj); + if (res < 0) { + return -1; + } + data->new_object = _channelend_from_xid; + return 0; +} + +static int +set_channelend_types(PyObject *mod, PyTypeObject *send, PyTypeObject *recv) +{ + module_state *state = get_module_state(mod); + if (state == NULL) { + return -1; + } + struct xid_class_registry *xid_classes = &state->xid_classes; + + if (state->send_channel_type != NULL + || state->recv_channel_type != NULL) + { + PyErr_SetString(PyExc_TypeError, "already registered"); + return -1; + } + state->send_channel_type = (PyTypeObject *)Py_NewRef(send); + state->recv_channel_type = (PyTypeObject *)Py_NewRef(recv); + + if (register_xid_class(send, _channelend_shared, xid_classes)) { + return -1; + } + if (register_xid_class(recv, _channelend_shared, xid_classes)) { + return -1; + } + + return 0; +} + + /* module level code ********************************************************/ /* globals is the process-global state for the module. It holds all @@ -1988,15 +2768,15 @@ clear_interpreter(void *data) } PyInterpreterState *interp = (PyInterpreterState *)data; assert(interp == _get_current_interp()); - int64_t id = PyInterpreterState_GetID(interp); - _channels_drop_interpreter(&_globals.channels, id); + int64_t interpid = PyInterpreterState_GetID(interp); + _channels_clear_interpreter(&_globals.channels, interpid); } static PyObject * -channel_create(PyObject *self, PyObject *Py_UNUSED(ignored)) +channelsmod_create(PyObject *self, PyObject *Py_UNUSED(ignored)) { - int64_t cid = _channel_create(&_globals.channels); + int64_t cid = channel_create(&_globals.channels); if (cid < 0) { (void)handle_channel_error(-1, self, cid); return NULL; @@ -2005,30 +2785,30 @@ channel_create(PyObject *self, PyObject *Py_UNUSED(ignored)) if (state == NULL) { return NULL; } - PyObject *id = NULL; + PyObject *cidobj = NULL; int err = newchannelid(state->ChannelIDType, cid, 0, &_globals.channels, 0, 0, - (channelid **)&id); + (channelid **)&cidobj); if (handle_channel_error(err, self, cid)) { - assert(id == NULL); - err = _channel_destroy(&_globals.channels, cid); + assert(cidobj == NULL); + err = channel_destroy(&_globals.channels, cid); if (handle_channel_error(err, self, cid)) { // XXX issue a warning? } return NULL; } - assert(id != NULL); - assert(((channelid *)id)->channels != NULL); - return id; + assert(cidobj != NULL); + assert(((channelid *)cidobj)->channels != NULL); + return cidobj; } -PyDoc_STRVAR(channel_create_doc, +PyDoc_STRVAR(channelsmod_create_doc, "channel_create() -> cid\n\ \n\ Create a new cross-interpreter channel and return a unique generated ID."); static PyObject * -channel_destroy(PyObject *self, PyObject *args, PyObject *kwds) +channelsmod_destroy(PyObject *self, PyObject *args, PyObject *kwds) { static char *kwlist[] = {"cid", NULL}; int64_t cid; @@ -2041,21 +2821,21 @@ channel_destroy(PyObject *self, PyObject *args, PyObject *kwds) } cid = cid_data.cid; - int err = _channel_destroy(&_globals.channels, cid); + int err = channel_destroy(&_globals.channels, cid); if (handle_channel_error(err, self, cid)) { return NULL; } Py_RETURN_NONE; } -PyDoc_STRVAR(channel_destroy_doc, +PyDoc_STRVAR(channelsmod_destroy_doc, "channel_destroy(cid)\n\ \n\ Close and finalize the channel. Afterward attempts to use the channel\n\ will behave as though it never existed."); static PyObject * -channel_list_all(PyObject *self, PyObject *Py_UNUSED(ignored)) +channelsmod_list_all(PyObject *self, PyObject *Py_UNUSED(ignored)) { int64_t count = 0; int64_t *cids = _channels_list_all(&_globals.channels, &count); @@ -2077,17 +2857,17 @@ channel_list_all(PyObject *self, PyObject *Py_UNUSED(ignored)) } int64_t *cur = cids; for (int64_t i=0; i < count; cur++, i++) { - PyObject *id = NULL; + PyObject *cidobj = NULL; int err = newchannelid(state->ChannelIDType, *cur, 0, &_globals.channels, 0, 0, - (channelid **)&id); + (channelid **)&cidobj); if (handle_channel_error(err, self, *cur)) { - assert(id == NULL); + assert(cidobj == NULL); Py_SETREF(ids, NULL); break; } - assert(id != NULL); - PyList_SET_ITEM(ids, (Py_ssize_t)i, id); + assert(cidobj != NULL); + PyList_SET_ITEM(ids, (Py_ssize_t)i, cidobj); } finally: @@ -2095,13 +2875,13 @@ channel_list_all(PyObject *self, PyObject *Py_UNUSED(ignored)) return ids; } -PyDoc_STRVAR(channel_list_all_doc, +PyDoc_STRVAR(channelsmod_list_all_doc, "channel_list_all() -> [cid]\n\ \n\ Return the list of all IDs for active channels."); static PyObject * -channel_list_interpreters(PyObject *self, PyObject *args, PyObject *kwds) +channelsmod_list_interpreters(PyObject *self, PyObject *args, PyObject *kwds) { static char *kwlist[] = {"cid", "send", NULL}; int64_t cid; /* Channel ID */ @@ -2109,8 +2889,8 @@ channel_list_interpreters(PyObject *self, PyObject *args, PyObject *kwds) .module = self, }; int send = 0; /* Send or receive end? */ - int64_t id; - PyObject *ids, *id_obj; + int64_t interpid; + PyObject *ids, *interpid_obj; PyInterpreterState *interp; if (!PyArg_ParseTupleAndKeywords( @@ -2127,20 +2907,20 @@ channel_list_interpreters(PyObject *self, PyObject *args, PyObject *kwds) interp = PyInterpreterState_Head(); while (interp != NULL) { - id = PyInterpreterState_GetID(interp); - assert(id >= 0); - int res = _channel_is_associated(&_globals.channels, cid, id, send); + interpid = PyInterpreterState_GetID(interp); + assert(interpid >= 0); + int res = channel_is_associated(&_globals.channels, cid, interpid, send); if (res < 0) { (void)handle_channel_error(res, self, cid); goto except; } if (res) { - id_obj = PyInterpreterState_GetIDObject(interp); - if (id_obj == NULL) { + interpid_obj = PyInterpreterState_GetIDObject(interp); + if (interpid_obj == NULL) { goto except; } - res = PyList_Insert(ids, 0, id_obj); - Py_DECREF(id_obj); + res = PyList_Insert(ids, 0, interpid_obj); + Py_DECREF(interpid_obj); if (res < 0) { goto except; } @@ -2157,7 +2937,7 @@ channel_list_interpreters(PyObject *self, PyObject *args, PyObject *kwds) return ids; } -PyDoc_STRVAR(channel_list_interpreters_doc, +PyDoc_STRVAR(channelsmod_list_interpreters_doc, "channel_list_interpreters(cid, *, send) -> [id]\n\ \n\ Return the list of all interpreter IDs associated with an end of the channel.\n\ @@ -2167,34 +2947,100 @@ receive end."); static PyObject * -channel_send(PyObject *self, PyObject *args, PyObject *kwds) +channelsmod_send(PyObject *self, PyObject *args, PyObject *kwds) { - static char *kwlist[] = {"cid", "obj", NULL}; - int64_t cid; + static char *kwlist[] = {"cid", "obj", "blocking", "timeout", NULL}; struct channel_id_converter_data cid_data = { .module = self, }; PyObject *obj; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&O:channel_send", kwlist, - channel_id_converter, &cid_data, &obj)) { + int blocking = 1; + PyObject *timeout_obj = NULL; + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&O|$pO:channel_send", kwlist, + channel_id_converter, &cid_data, &obj, + &blocking, &timeout_obj)) { return NULL; } - cid = cid_data.cid; - int err = _channel_send(&_globals.channels, cid, obj); + int64_t cid = cid_data.cid; + PY_TIMEOUT_T timeout; + if (PyThread_ParseTimeoutArg(timeout_obj, blocking, &timeout) < 0) { + return NULL; + } + + /* Queue up the object. */ + int err = 0; + if (blocking) { + err = channel_send_wait(&_globals.channels, cid, obj, timeout); + } + else { + err = channel_send(&_globals.channels, cid, obj, NULL); + } if (handle_channel_error(err, self, cid)) { return NULL; } + Py_RETURN_NONE; } -PyDoc_STRVAR(channel_send_doc, -"channel_send(cid, obj)\n\ +PyDoc_STRVAR(channelsmod_send_doc, +"channel_send(cid, obj, blocking=True)\n\ \n\ -Add the object's data to the channel's queue."); +Add the object's data to the channel's queue.\n\ +By default this waits for the object to be received."); static PyObject * -channel_recv(PyObject *self, PyObject *args, PyObject *kwds) +channelsmod_send_buffer(PyObject *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"cid", "obj", "blocking", "timeout", NULL}; + struct channel_id_converter_data cid_data = { + .module = self, + }; + PyObject *obj; + int blocking = 1; + PyObject *timeout_obj = NULL; + if (!PyArg_ParseTupleAndKeywords(args, kwds, + "O&O|$pO:channel_send_buffer", kwlist, + channel_id_converter, &cid_data, &obj, + &blocking, &timeout_obj)) { + return NULL; + } + + int64_t cid = cid_data.cid; + PY_TIMEOUT_T timeout; + if (PyThread_ParseTimeoutArg(timeout_obj, blocking, &timeout) < 0) { + return NULL; + } + + PyObject *tempobj = PyMemoryView_FromObject(obj); + if (tempobj == NULL) { + return NULL; + } + + /* Queue up the object. */ + int err = 0; + if (blocking) { + err = channel_send_wait(&_globals.channels, cid, tempobj, timeout); + } + else { + err = channel_send(&_globals.channels, cid, tempobj, NULL); + } + Py_DECREF(tempobj); + if (handle_channel_error(err, self, cid)) { + return NULL; + } + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(channelsmod_send_buffer_doc, +"channel_send_buffer(cid, obj, blocking=True)\n\ +\n\ +Add the object's buffer to the channel's queue.\n\ +By default this waits for the object to be received."); + +static PyObject * +channelsmod_recv(PyObject *self, PyObject *args, PyObject *kwds) { static char *kwlist[] = {"cid", "default", NULL}; int64_t cid; @@ -2209,7 +3055,7 @@ channel_recv(PyObject *self, PyObject *args, PyObject *kwds) cid = cid_data.cid; PyObject *obj = NULL; - int err = _channel_recv(&_globals.channels, cid, &obj); + int err = channel_recv(&_globals.channels, cid, &obj); if (handle_channel_error(err, self, cid)) { return NULL; } @@ -2226,7 +3072,7 @@ channel_recv(PyObject *self, PyObject *args, PyObject *kwds) return obj; } -PyDoc_STRVAR(channel_recv_doc, +PyDoc_STRVAR(channelsmod_recv_doc, "channel_recv(cid, [default]) -> obj\n\ \n\ Return a new object from the data at the front of the channel's queue.\n\ @@ -2235,7 +3081,7 @@ If there is nothing to receive then raise ChannelEmptyError, unless\n\ a default value is provided. In that case return it."); static PyObject * -channel_close(PyObject *self, PyObject *args, PyObject *kwds) +channelsmod_close(PyObject *self, PyObject *args, PyObject *kwds) { static char *kwlist[] = {"cid", "send", "recv", "force", NULL}; int64_t cid; @@ -2253,14 +3099,14 @@ channel_close(PyObject *self, PyObject *args, PyObject *kwds) } cid = cid_data.cid; - int err = _channel_close(&_globals.channels, cid, send-recv, force); + int err = channel_close(&_globals.channels, cid, send-recv, force); if (handle_channel_error(err, self, cid)) { return NULL; } Py_RETURN_NONE; } -PyDoc_STRVAR(channel_close_doc, +PyDoc_STRVAR(channelsmod_close_doc, "channel_close(cid, *, send=None, recv=None, force=False)\n\ \n\ Close the channel for all interpreters.\n\ @@ -2288,7 +3134,7 @@ Once the channel's ID has no more ref counts in any interpreter\n\ the channel will be destroyed."); static PyObject * -channel_release(PyObject *self, PyObject *args, PyObject *kwds) +channelsmod_release(PyObject *self, PyObject *args, PyObject *kwds) { // Note that only the current interpreter is affected. static char *kwlist[] = {"cid", "send", "recv", "force", NULL}; @@ -2314,14 +3160,14 @@ channel_release(PyObject *self, PyObject *args, PyObject *kwds) // XXX Handle force is True. // XXX Fix implicit release. - int err = _channel_drop(&_globals.channels, cid, send, recv); + int err = channel_release(&_globals.channels, cid, send, recv); if (handle_channel_error(err, self, cid)) { return NULL; } Py_RETURN_NONE; } -PyDoc_STRVAR(channel_release_doc, +PyDoc_STRVAR(channelsmod_release_doc, "channel_release(cid, *, send=None, recv=None, force=True)\n\ \n\ Close the channel for the current interpreter. 'send' and 'recv'\n\ @@ -2329,40 +3175,101 @@ Close the channel for the current interpreter. 'send' and 'recv'\n\ ends are closed. Closing an already closed end is a noop."); static PyObject * -channel__channel_id(PyObject *self, PyObject *args, PyObject *kwds) +channelsmod_get_info(PyObject *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"cid", NULL}; + struct channel_id_converter_data cid_data = { + .module = self, + }; + if (!PyArg_ParseTupleAndKeywords(args, kwds, + "O&:_get_info", kwlist, + channel_id_converter, &cid_data)) { + return NULL; + } + int64_t cid = cid_data.cid; + + struct channel_info info; + int err = _channel_get_info(&_globals.channels, cid, &info); + if (handle_channel_error(err, self, cid)) { + return NULL; + } + return new_channel_info(self, &info); +} + +PyDoc_STRVAR(channelsmod_get_info_doc, +"get_info(cid)\n\ +\n\ +Return details about the channel."); + +static PyObject * +channelsmod__channel_id(PyObject *self, PyObject *args, PyObject *kwds) { module_state *state = get_module_state(self); if (state == NULL) { return NULL; } PyTypeObject *cls = state->ChannelIDType; + PyObject *mod = get_module_from_owned_type(cls); - if (mod == NULL) { + assert(mod == self); + Py_DECREF(mod); + + return _channelid_new(self, cls, args, kwds); +} + +static PyObject * +channelsmod__register_end_types(PyObject *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"send", "recv", NULL}; + PyObject *send; + PyObject *recv; + if (!PyArg_ParseTupleAndKeywords(args, kwds, + "OO:_register_end_types", kwlist, + &send, &recv)) { return NULL; } - PyObject *cid = _channelid_new(mod, cls, args, kwds); - Py_DECREF(mod); - return cid; + if (!PyType_Check(send)) { + PyErr_SetString(PyExc_TypeError, "expected a type for 'send'"); + return NULL; + } + if (!PyType_Check(recv)) { + PyErr_SetString(PyExc_TypeError, "expected a type for 'recv'"); + return NULL; + } + PyTypeObject *cls_send = (PyTypeObject *)send; + PyTypeObject *cls_recv = (PyTypeObject *)recv; + + if (set_channelend_types(self, cls_send, cls_recv) < 0) { + return NULL; + } + + Py_RETURN_NONE; } static PyMethodDef module_functions[] = { - {"create", channel_create, - METH_NOARGS, channel_create_doc}, - {"destroy", _PyCFunction_CAST(channel_destroy), - METH_VARARGS | METH_KEYWORDS, channel_destroy_doc}, - {"list_all", channel_list_all, - METH_NOARGS, channel_list_all_doc}, - {"list_interpreters", _PyCFunction_CAST(channel_list_interpreters), - METH_VARARGS | METH_KEYWORDS, channel_list_interpreters_doc}, - {"send", _PyCFunction_CAST(channel_send), - METH_VARARGS | METH_KEYWORDS, channel_send_doc}, - {"recv", _PyCFunction_CAST(channel_recv), - METH_VARARGS | METH_KEYWORDS, channel_recv_doc}, - {"close", _PyCFunction_CAST(channel_close), - METH_VARARGS | METH_KEYWORDS, channel_close_doc}, - {"release", _PyCFunction_CAST(channel_release), - METH_VARARGS | METH_KEYWORDS, channel_release_doc}, - {"_channel_id", _PyCFunction_CAST(channel__channel_id), + {"create", channelsmod_create, + METH_NOARGS, channelsmod_create_doc}, + {"destroy", _PyCFunction_CAST(channelsmod_destroy), + METH_VARARGS | METH_KEYWORDS, channelsmod_destroy_doc}, + {"list_all", channelsmod_list_all, + METH_NOARGS, channelsmod_list_all_doc}, + {"list_interpreters", _PyCFunction_CAST(channelsmod_list_interpreters), + METH_VARARGS | METH_KEYWORDS, channelsmod_list_interpreters_doc}, + {"send", _PyCFunction_CAST(channelsmod_send), + METH_VARARGS | METH_KEYWORDS, channelsmod_send_doc}, + {"send_buffer", _PyCFunction_CAST(channelsmod_send_buffer), + METH_VARARGS | METH_KEYWORDS, channelsmod_send_buffer_doc}, + {"recv", _PyCFunction_CAST(channelsmod_recv), + METH_VARARGS | METH_KEYWORDS, channelsmod_recv_doc}, + {"close", _PyCFunction_CAST(channelsmod_close), + METH_VARARGS | METH_KEYWORDS, channelsmod_close_doc}, + {"release", _PyCFunction_CAST(channelsmod_release), + METH_VARARGS | METH_KEYWORDS, channelsmod_release_doc}, + {"get_info", _PyCFunction_CAST(channelsmod_get_info), + METH_VARARGS | METH_KEYWORDS, channelsmod_get_info_doc}, + {"_channel_id", _PyCFunction_CAST(channelsmod__channel_id), + METH_VARARGS | METH_KEYWORDS, NULL}, + {"_register_end_types", _PyCFunction_CAST(channelsmod__register_end_types), METH_VARARGS | METH_KEYWORDS, NULL}, {NULL, NULL} /* sentinel */ @@ -2381,6 +3288,13 @@ module_exec(PyObject *mod) if (_globals_init() != 0) { return -1; } + struct xid_class_registry *xid_classes = NULL; + + module_state *state = get_module_state(mod); + if (state == NULL) { + goto error; + } + xid_classes = &state->xid_classes; /* Add exception types */ if (exceptions_init(mod) != 0) { @@ -2388,25 +3302,33 @@ module_exec(PyObject *mod) } /* Add other types */ - module_state *state = get_module_state(mod); - if (state == NULL) { + + // ChannelInfo + state->ChannelInfoType = PyStructSequence_NewType(&channel_info_desc); + if (state->ChannelInfoType == NULL) { + goto error; + } + if (PyModule_AddType(mod, state->ChannelInfoType) < 0) { goto error; } // ChannelID state->ChannelIDType = add_new_type( - mod, &ChannelIDType_spec, _channelid_shared); + mod, &channelid_typespec, _channelid_shared, xid_classes); if (state->ChannelIDType == NULL) { goto error; } - // Make sure chnnels drop objects owned by this interpreter + /* Make sure chnnels drop objects owned by this interpreter. */ PyInterpreterState *interp = _get_current_interp(); PyUnstable_AtExit(interp, clear_interpreter, (void *)interp); return 0; error: + if (xid_classes != NULL) { + clear_xid_class_registry(xid_classes); + } _globals_fini(); return -1; } @@ -2431,6 +3353,11 @@ module_clear(PyObject *mod) { module_state *state = get_module_state(mod); assert(state != NULL); + + // Before clearing anything, we unregister the various XID types. */ + clear_xid_class_registry(&state->xid_classes); + + // Now we clear the module state. clear_module_state(state); return 0; } @@ -2440,7 +3367,13 @@ module_free(void *mod) { module_state *state = get_module_state(mod); assert(state != NULL); + + // Before clearing anything, we unregister the various XID types. */ + clear_xid_class_registry(&state->xid_classes); + + // Now we clear the module state. clear_module_state(state); + _globals_fini(); } diff --git a/Modules/_xxinterpqueuesmodule.c b/Modules/_xxinterpqueuesmodule.c new file mode 100644 index 00000000000000..537ba9188055dd --- /dev/null +++ b/Modules/_xxinterpqueuesmodule.c @@ -0,0 +1,1687 @@ +/* interpreters module */ +/* low-level access to interpreter primitives */ + +#ifndef Py_BUILD_CORE_BUILTIN +# define Py_BUILD_CORE_MODULE 1 +#endif + +#include "Python.h" +#include "pycore_crossinterp.h" // struct _xid + + +#define MODULE_NAME "_xxinterpqueues" + + +#define GLOBAL_MALLOC(TYPE) \ + PyMem_RawMalloc(sizeof(TYPE)) +#define GLOBAL_FREE(VAR) \ + PyMem_RawFree(VAR) + + +#define XID_IGNORE_EXC 1 +#define XID_FREE 2 + +static int +_release_xid_data(_PyCrossInterpreterData *data, int flags) +{ + int ignoreexc = flags & XID_IGNORE_EXC; + PyObject *exc; + if (ignoreexc) { + exc = PyErr_GetRaisedException(); + } + int res; + if (flags & XID_FREE) { + res = _PyCrossInterpreterData_ReleaseAndRawFree(data); + } + else { + res = _PyCrossInterpreterData_Release(data); + } + if (res < 0) { + /* The owning interpreter is already destroyed. */ + if (ignoreexc) { + // XXX Emit a warning? + PyErr_Clear(); + } + } + if (flags & XID_FREE) { + /* Either way, we free the data. */ + } + if (ignoreexc) { + PyErr_SetRaisedException(exc); + } + return res; +} + + +static PyInterpreterState * +_get_current_interp(void) +{ + // PyInterpreterState_Get() aborts if lookup fails, so don't need + // to check the result for NULL. + return PyInterpreterState_Get(); +} + +static PyObject * +_get_current_module(void) +{ + PyObject *name = PyUnicode_FromString(MODULE_NAME); + if (name == NULL) { + return NULL; + } + PyObject *mod = PyImport_GetModule(name); + Py_DECREF(name); + if (mod == NULL) { + return NULL; + } + assert(mod != Py_None); + return mod; +} + + +struct idarg_int64_converter_data { + // input: + const char *label; + // output: + int64_t id; +}; + +static int +idarg_int64_converter(PyObject *arg, void *ptr) +{ + int64_t id; + struct idarg_int64_converter_data *data = ptr; + + const char *label = data->label; + if (label == NULL) { + label = "ID"; + } + + if (PyIndex_Check(arg)) { + int overflow = 0; + id = PyLong_AsLongLongAndOverflow(arg, &overflow); + if (id == -1 && PyErr_Occurred()) { + return 0; + } + else if (id == -1 && overflow == 1) { + PyErr_Format(PyExc_OverflowError, + "max %s is %lld, got %R", label, INT64_MAX, arg); + return 0; + } + else if (id < 0) { + PyErr_Format(PyExc_ValueError, + "%s must be a non-negative int, got %R", label, arg); + return 0; + } + } + else { + PyErr_Format(PyExc_TypeError, + "%s must be an int, got %.100s", + label, Py_TYPE(arg)->tp_name); + return 0; + } + data->id = id; + return 1; +} + + +/* module state *************************************************************/ + +typedef struct { + /* external types (added at runtime by interpreters module) */ + PyTypeObject *queue_type; + + /* QueueError (and its subclasses) */ + PyObject *QueueError; + PyObject *QueueNotFoundError; + PyObject *QueueEmpty; + PyObject *QueueFull; +} module_state; + +static inline module_state * +get_module_state(PyObject *mod) +{ + assert(mod != NULL); + module_state *state = PyModule_GetState(mod); + assert(state != NULL); + return state; +} + +static int +traverse_module_state(module_state *state, visitproc visit, void *arg) +{ + /* external types */ + Py_VISIT(state->queue_type); + + /* QueueError */ + Py_VISIT(state->QueueError); + Py_VISIT(state->QueueNotFoundError); + Py_VISIT(state->QueueEmpty); + Py_VISIT(state->QueueFull); + + return 0; +} + +static int +clear_module_state(module_state *state) +{ + /* external types */ + Py_CLEAR(state->queue_type); + + /* QueueError */ + Py_CLEAR(state->QueueError); + Py_CLEAR(state->QueueNotFoundError); + Py_CLEAR(state->QueueEmpty); + Py_CLEAR(state->QueueFull); + + return 0; +} + + +/* error codes **************************************************************/ + +#define ERR_EXCEPTION_RAISED (-1) +// multi-queue errors +#define ERR_QUEUES_ALLOC (-11) +#define ERR_QUEUE_ALLOC (-12) +#define ERR_NO_NEXT_QUEUE_ID (-13) +#define ERR_QUEUE_NOT_FOUND (-14) +// single-queue errors +#define ERR_QUEUE_EMPTY (-21) +#define ERR_QUEUE_FULL (-22) + +static int +resolve_module_errcode(module_state *state, int errcode, int64_t qid, + PyObject **p_exctype, PyObject **p_msgobj) +{ + PyObject *exctype = NULL; + PyObject *msg = NULL; + switch (errcode) { + case ERR_NO_NEXT_QUEUE_ID: + exctype = state->QueueError; + msg = PyUnicode_FromString("ran out of queue IDs"); + break; + case ERR_QUEUE_NOT_FOUND: + exctype = state->QueueNotFoundError; + msg = PyUnicode_FromFormat("queue %" PRId64 " not found", qid); + break; + case ERR_QUEUE_EMPTY: + exctype = state->QueueEmpty; + msg = PyUnicode_FromFormat("queue %" PRId64 " is empty", qid); + break; + case ERR_QUEUE_FULL: + exctype = state->QueueFull; + msg = PyUnicode_FromFormat("queue %" PRId64 " is full", qid); + break; + default: + PyErr_Format(PyExc_ValueError, + "unsupported error code %d", errcode); + return -1; + } + + if (msg == NULL) { + assert(PyErr_Occurred()); + return -1; + } + *p_exctype = exctype; + *p_msgobj = msg; + return 0; +} + + +/* QueueError ***************************************************************/ + +static int +add_exctype(PyObject *mod, PyObject **p_state_field, + const char *qualname, const char *doc, PyObject *base) +{ +#ifndef NDEBUG + const char *dot = strrchr(qualname, '.'); + assert(dot != NULL); + const char *name = dot+1; + assert(*p_state_field == NULL); + assert(!PyObject_HasAttrStringWithError(mod, name)); +#endif + PyObject *exctype = PyErr_NewExceptionWithDoc(qualname, doc, base, NULL); + if (exctype == NULL) { + return -1; + } + if (PyModule_AddType(mod, (PyTypeObject *)exctype) < 0) { + Py_DECREF(exctype); + return -1; + } + *p_state_field = exctype; + return 0; +} + +static int +add_QueueError(PyObject *mod) +{ + module_state *state = get_module_state(mod); + +#define PREFIX "test.support.interpreters." +#define ADD_EXCTYPE(NAME, BASE, DOC) \ + if (add_exctype(mod, &state->NAME, PREFIX #NAME, DOC, BASE) < 0) { \ + return -1; \ + } + ADD_EXCTYPE(QueueError, PyExc_RuntimeError, + "Indicates that a queue-related error happened.") + ADD_EXCTYPE(QueueNotFoundError, state->QueueError, NULL) + ADD_EXCTYPE(QueueEmpty, state->QueueError, NULL) + ADD_EXCTYPE(QueueFull, state->QueueError, NULL) +#undef ADD_EXCTYPE +#undef PREFIX + + return 0; +} + +static int +handle_queue_error(int err, PyObject *mod, int64_t qid) +{ + if (err == 0) { + assert(!PyErr_Occurred()); + return 0; + } + assert(err < 0); + assert((err == -1) == (PyErr_Occurred() != NULL)); + + module_state *state; + switch (err) { + case ERR_QUEUE_ALLOC: // fall through + case ERR_QUEUES_ALLOC: + PyErr_NoMemory(); + break; + default: + state = get_module_state(mod); + assert(state->QueueError != NULL); + PyObject *exctype = NULL; + PyObject *msg = NULL; + if (resolve_module_errcode(state, err, qid, &exctype, &msg) < 0) { + return -1; + } + PyObject *exc = PyObject_CallOneArg(exctype, msg); + Py_DECREF(msg); + if (exc == NULL) { + return -1; + } + PyErr_SetObject(exctype, exc); + Py_DECREF(exc); + } + return 1; +} + + +/* the basic queue **********************************************************/ + +struct _queueitem; + +typedef struct _queueitem { + _PyCrossInterpreterData *data; + struct _queueitem *next; +} _queueitem; + +static void +_queueitem_init(_queueitem *item, _PyCrossInterpreterData *data) +{ + *item = (_queueitem){ + .data = data, + }; +} + +static void +_queueitem_clear(_queueitem *item) +{ + item->next = NULL; + + if (item->data != NULL) { + // It was allocated in queue_put(). + (void)_release_xid_data(item->data, XID_IGNORE_EXC & XID_FREE); + item->data = NULL; + } +} + +static _queueitem * +_queueitem_new(_PyCrossInterpreterData *data) +{ + _queueitem *item = GLOBAL_MALLOC(_queueitem); + if (item == NULL) { + PyErr_NoMemory(); + return NULL; + } + _queueitem_init(item, data); + return item; +} + +static void +_queueitem_free(_queueitem *item) +{ + _queueitem_clear(item); + GLOBAL_FREE(item); +} + +static void +_queueitem_free_all(_queueitem *item) +{ + while (item != NULL) { + _queueitem *last = item; + item = item->next; + _queueitem_free(last); + } +} + +static void +_queueitem_popped(_queueitem *item, _PyCrossInterpreterData **p_data) +{ + *p_data = item->data; + // We clear them here, so they won't be released in _queueitem_clear(). + item->data = NULL; + _queueitem_free(item); +} + + +/* the queue */ +typedef struct _queue { + Py_ssize_t num_waiters; // protected by global lock + PyThread_type_lock mutex; + int alive; + struct _queueitems { + Py_ssize_t maxsize; + Py_ssize_t count; + _queueitem *first; + _queueitem *last; + } items; +} _queue; + +static int +_queue_init(_queue *queue, Py_ssize_t maxsize) +{ + PyThread_type_lock mutex = PyThread_allocate_lock(); + if (mutex == NULL) { + return ERR_QUEUE_ALLOC; + } + *queue = (_queue){ + .mutex = mutex, + .alive = 1, + .items = { + .maxsize = maxsize, + }, + }; + return 0; +} + +static void +_queue_clear(_queue *queue) +{ + assert(!queue->alive); + assert(queue->num_waiters == 0); + _queueitem_free_all(queue->items.first); + assert(queue->mutex != NULL); + PyThread_free_lock(queue->mutex); + *queue = (_queue){0}; +} + +static void +_queue_kill_and_wait(_queue *queue) +{ + // Mark it as dead. + PyThread_acquire_lock(queue->mutex, WAIT_LOCK); + assert(queue->alive); + queue->alive = 0; + PyThread_release_lock(queue->mutex); + + // Wait for all waiters to fail. + while (queue->num_waiters > 0) { + PyThread_acquire_lock(queue->mutex, WAIT_LOCK); + PyThread_release_lock(queue->mutex); + }; +} + +static void +_queue_mark_waiter(_queue *queue, PyThread_type_lock parent_mutex) +{ + if (parent_mutex != NULL) { + PyThread_acquire_lock(parent_mutex, WAIT_LOCK); + queue->num_waiters += 1; + PyThread_release_lock(parent_mutex); + } + else { + // The caller must be holding the parent lock already. + queue->num_waiters += 1; + } +} + +static void +_queue_unmark_waiter(_queue *queue, PyThread_type_lock parent_mutex) +{ + if (parent_mutex != NULL) { + PyThread_acquire_lock(parent_mutex, WAIT_LOCK); + queue->num_waiters -= 1; + PyThread_release_lock(parent_mutex); + } + else { + // The caller must be holding the parent lock already. + queue->num_waiters -= 1; + } +} + +static int +_queue_lock(_queue *queue) +{ + // The queue must be marked as a waiter already. + PyThread_acquire_lock(queue->mutex, WAIT_LOCK); + if (!queue->alive) { + PyThread_release_lock(queue->mutex); + return ERR_QUEUE_NOT_FOUND; + } + return 0; +} + +static void +_queue_unlock(_queue *queue) +{ + PyThread_release_lock(queue->mutex); +} + +static int +_queue_add(_queue *queue, _PyCrossInterpreterData *data) +{ + int err = _queue_lock(queue); + if (err < 0) { + return err; + } + + Py_ssize_t maxsize = queue->items.maxsize; + if (maxsize <= 0) { + maxsize = PY_SSIZE_T_MAX; + } + if (queue->items.count >= maxsize) { + _queue_unlock(queue); + return ERR_QUEUE_FULL; + } + + _queueitem *item = _queueitem_new(data); + if (item == NULL) { + _queue_unlock(queue); + return -1; + } + + queue->items.count += 1; + if (queue->items.first == NULL) { + queue->items.first = item; + } + else { + queue->items.last->next = item; + } + queue->items.last = item; + + _queue_unlock(queue); + return 0; +} + +static int +_queue_next(_queue *queue, _PyCrossInterpreterData **p_data) +{ + int err = _queue_lock(queue); + if (err < 0) { + return err; + } + + assert(queue->items.count >= 0); + _queueitem *item = queue->items.first; + if (item == NULL) { + _queue_unlock(queue); + return ERR_QUEUE_EMPTY; + } + queue->items.first = item->next; + if (queue->items.last == item) { + queue->items.last = NULL; + } + queue->items.count -= 1; + + _queueitem_popped(item, p_data); + + _queue_unlock(queue); + return 0; +} + +static int +_queue_get_maxsize(_queue *queue, Py_ssize_t *p_maxsize) +{ + int err = _queue_lock(queue); + if (err < 0) { + return err; + } + + *p_maxsize = queue->items.maxsize; + + _queue_unlock(queue); + return 0; +} + +static int +_queue_is_full(_queue *queue, int *p_is_full) +{ + int err = _queue_lock(queue); + if (err < 0) { + return err; + } + + assert(queue->items.count <= queue->items.maxsize); + *p_is_full = queue->items.count == queue->items.maxsize; + + _queue_unlock(queue); + return 0; +} + +static int +_queue_get_count(_queue *queue, Py_ssize_t *p_count) +{ + int err = _queue_lock(queue); + if (err < 0) { + return err; + } + + *p_count = queue->items.count; + + _queue_unlock(queue); + return 0; +} + +static void +_queue_clear_interpreter(_queue *queue, int64_t interpid) +{ + int err = _queue_lock(queue); + if (err == ERR_QUEUE_NOT_FOUND) { + // The queue is already destroyed, so there's nothing to clear. + assert(!PyErr_Occurred()); + return; + } + assert(err == 0); // There should be no other errors. + + _queueitem *prev = NULL; + _queueitem *next = queue->items.first; + while (next != NULL) { + _queueitem *item = next; + next = item->next; + if (item->data->interpid == interpid) { + if (prev == NULL) { + queue->items.first = item->next; + } + else { + prev->next = item->next; + } + _queueitem_free(item); + queue->items.count -= 1; + } + else { + prev = item; + } + } + + _queue_unlock(queue); +} + + +/* external queue references ************************************************/ + +struct _queueref; + +typedef struct _queueref { + struct _queueref *next; + int64_t qid; + Py_ssize_t refcount; + _queue *queue; +} _queueref; + +static _queueref * +_queuerefs_find(_queueref *first, int64_t qid, _queueref **pprev) +{ + _queueref *prev = NULL; + _queueref *ref = first; + while (ref != NULL) { + if (ref->qid == qid) { + break; + } + prev = ref; + ref = ref->next; + } + if (pprev != NULL) { + *pprev = prev; + } + return ref; +} + + +/* a collection of queues ***************************************************/ + +typedef struct _queues { + PyThread_type_lock mutex; + _queueref *head; + int64_t count; + int64_t next_id; +} _queues; + +static void +_queues_init(_queues *queues, PyThread_type_lock mutex) +{ + queues->mutex = mutex; + queues->head = NULL; + queues->count = 0; + queues->next_id = 1; +} + +static void +_queues_fini(_queues *queues) +{ + assert(queues->count == 0); + assert(queues->head == NULL); + if (queues->mutex != NULL) { + PyThread_free_lock(queues->mutex); + queues->mutex = NULL; + } +} + +static int64_t +_queues_next_id(_queues *queues) // needs lock +{ + int64_t qid = queues->next_id; + if (qid < 0) { + /* overflow */ + return ERR_NO_NEXT_QUEUE_ID; + } + queues->next_id += 1; + return qid; +} + +static int +_queues_lookup(_queues *queues, int64_t qid, _queue **res) +{ + PyThread_acquire_lock(queues->mutex, WAIT_LOCK); + + _queueref *ref = _queuerefs_find(queues->head, qid, NULL); + if (ref == NULL) { + PyThread_release_lock(queues->mutex); + return ERR_QUEUE_NOT_FOUND; + } + assert(ref->queue != NULL); + _queue *queue = ref->queue; + _queue_mark_waiter(queue, NULL); + // The caller must unmark it. + + PyThread_release_lock(queues->mutex); + + *res = queue; + return 0; +} + +static int64_t +_queues_add(_queues *queues, _queue *queue) +{ + int64_t qid = -1; + PyThread_acquire_lock(queues->mutex, WAIT_LOCK); + + // Create a new ref. + int64_t _qid = _queues_next_id(queues); + if (_qid < 0) { + goto done; + } + _queueref *ref = GLOBAL_MALLOC(_queueref); + if (ref == NULL) { + qid = ERR_QUEUE_ALLOC; + goto done; + } + *ref = (_queueref){ + .qid = _qid, + .queue = queue, + }; + + // Add it to the list. + // We assume that the queue is a new one (not already in the list). + ref->next = queues->head; + queues->head = ref; + queues->count += 1; + + qid = _qid; +done: + PyThread_release_lock(queues->mutex); + return qid; +} + +static void +_queues_remove_ref(_queues *queues, _queueref *ref, _queueref *prev, + _queue **p_queue) +{ + assert(ref->queue != NULL); + + if (ref == queues->head) { + queues->head = ref->next; + } + else { + prev->next = ref->next; + } + ref->next = NULL; + queues->count -= 1; + + *p_queue = ref->queue; + ref->queue = NULL; + GLOBAL_FREE(ref); +} + +static int +_queues_remove(_queues *queues, int64_t qid, _queue **p_queue) +{ + PyThread_acquire_lock(queues->mutex, WAIT_LOCK); + + _queueref *prev = NULL; + _queueref *ref = _queuerefs_find(queues->head, qid, &prev); + if (ref == NULL) { + PyThread_release_lock(queues->mutex); + return ERR_QUEUE_NOT_FOUND; + } + + _queues_remove_ref(queues, ref, prev, p_queue); + PyThread_release_lock(queues->mutex); + + return 0; +} + +static int +_queues_incref(_queues *queues, int64_t qid) +{ + // XXX Track interpreter IDs? + int res = -1; + PyThread_acquire_lock(queues->mutex, WAIT_LOCK); + + _queueref *ref = _queuerefs_find(queues->head, qid, NULL); + if (ref == NULL) { + assert(!PyErr_Occurred()); + res = ERR_QUEUE_NOT_FOUND; + goto done; + } + ref->refcount += 1; + + res = 0; +done: + PyThread_release_lock(queues->mutex); + return res; +} + +static void _queue_free(_queue *); + +static void +_queues_decref(_queues *queues, int64_t qid) +{ + PyThread_acquire_lock(queues->mutex, WAIT_LOCK); + + _queueref *prev = NULL; + _queueref *ref = _queuerefs_find(queues->head, qid, &prev); + if (ref == NULL) { + assert(!PyErr_Occurred()); + // Already destroyed. + // XXX Warn? + goto finally; + } + assert(ref->refcount > 0); + ref->refcount -= 1; + + // Destroy if no longer used. + assert(ref->queue != NULL); + if (ref->refcount == 0) { + _queue *queue = NULL; + _queues_remove_ref(queues, ref, prev, &queue); + PyThread_release_lock(queues->mutex); + + _queue_kill_and_wait(queue); + _queue_free(queue); + return; + } + +finally: + PyThread_release_lock(queues->mutex); +} + +static int64_t * +_queues_list_all(_queues *queues, int64_t *count) +{ + int64_t *qids = NULL; + PyThread_acquire_lock(queues->mutex, WAIT_LOCK); + int64_t *ids = PyMem_NEW(int64_t, (Py_ssize_t)(queues->count)); + if (ids == NULL) { + goto done; + } + _queueref *ref = queues->head; + for (int64_t i=0; ref != NULL; ref = ref->next, i++) { + ids[i] = ref->qid; + } + *count = queues->count; + + qids = ids; +done: + PyThread_release_lock(queues->mutex); + return qids; +} + +static void +_queues_clear_interpreter(_queues *queues, int64_t interpid) +{ + PyThread_acquire_lock(queues->mutex, WAIT_LOCK); + + _queueref *ref = queues->head; + for (; ref != NULL; ref = ref->next) { + assert(ref->queue != NULL); + _queue_clear_interpreter(ref->queue, interpid); + } + + PyThread_release_lock(queues->mutex); +} + + +/* "high"-level queue-related functions *************************************/ + +static void +_queue_free(_queue *queue) +{ + _queue_clear(queue); + GLOBAL_FREE(queue); +} + +// Create a new queue. +static int64_t +queue_create(_queues *queues, Py_ssize_t maxsize) +{ + _queue *queue = GLOBAL_MALLOC(_queue); + if (queue == NULL) { + return ERR_QUEUE_ALLOC; + } + int err = _queue_init(queue, maxsize); + if (err < 0) { + GLOBAL_FREE(queue); + return (int64_t)err; + } + int64_t qid = _queues_add(queues, queue); + if (qid < 0) { + _queue_clear(queue); + GLOBAL_FREE(queue); + } + return qid; +} + +// Completely destroy the queue. +static int +queue_destroy(_queues *queues, int64_t qid) +{ + _queue *queue = NULL; + int err = _queues_remove(queues, qid, &queue); + if (err < 0) { + return err; + } + _queue_kill_and_wait(queue); + _queue_free(queue); + return 0; +} + +// Push an object onto the queue. +static int +queue_put(_queues *queues, int64_t qid, PyObject *obj) +{ + // Look up the queue. + _queue *queue = NULL; + int err = _queues_lookup(queues, qid, &queue); + if (err != 0) { + return err; + } + assert(queue != NULL); + + // Convert the object to cross-interpreter data. + _PyCrossInterpreterData *data = GLOBAL_MALLOC(_PyCrossInterpreterData); + if (data == NULL) { + _queue_unmark_waiter(queue, queues->mutex); + return -1; + } + if (_PyObject_GetCrossInterpreterData(obj, data) != 0) { + _queue_unmark_waiter(queue, queues->mutex); + GLOBAL_FREE(data); + return -1; + } + + // Add the data to the queue. + int res = _queue_add(queue, data); + _queue_unmark_waiter(queue, queues->mutex); + if (res != 0) { + // We may chain an exception here: + (void)_release_xid_data(data, 0); + GLOBAL_FREE(data); + return res; + } + + return 0; +} + +// Pop the next object off the queue. Fail if empty. +// XXX Support a "wait" mutex? +static int +queue_get(_queues *queues, int64_t qid, PyObject **res) +{ + int err; + *res = NULL; + + // Look up the queue. + _queue *queue = NULL; + err = _queues_lookup(queues, qid, &queue); + if (err != 0) { + return err; + } + // Past this point we are responsible for releasing the mutex. + assert(queue != NULL); + + // Pop off the next item from the queue. + _PyCrossInterpreterData *data = NULL; + err = _queue_next(queue, &data); + _queue_unmark_waiter(queue, queues->mutex); + if (err != 0) { + return err; + } + else if (data == NULL) { + assert(!PyErr_Occurred()); + return 0; + } + + // Convert the data back to an object. + PyObject *obj = _PyCrossInterpreterData_NewObject(data); + if (obj == NULL) { + assert(PyErr_Occurred()); + // It was allocated in queue_put(), so we free it. + (void)_release_xid_data(data, XID_IGNORE_EXC | XID_FREE); + return -1; + } + // It was allocated in queue_put(), so we free it. + int release_res = _release_xid_data(data, XID_FREE); + if (release_res < 0) { + // The source interpreter has been destroyed already. + assert(PyErr_Occurred()); + Py_DECREF(obj); + return -1; + } + + *res = obj; + return 0; +} + +static int +queue_get_maxsize(_queues *queues, int64_t qid, Py_ssize_t *p_maxsize) +{ + _queue *queue = NULL; + int err = _queues_lookup(queues, qid, &queue); + if (err < 0) { + return err; + } + err = _queue_get_maxsize(queue, p_maxsize); + _queue_unmark_waiter(queue, queues->mutex); + return err; +} + +static int +queue_is_full(_queues *queues, int64_t qid, int *p_is_full) +{ + _queue *queue = NULL; + int err = _queues_lookup(queues, qid, &queue); + if (err < 0) { + return err; + } + err = _queue_is_full(queue, p_is_full); + _queue_unmark_waiter(queue, queues->mutex); + return err; +} + +static int +queue_get_count(_queues *queues, int64_t qid, Py_ssize_t *p_count) +{ + _queue *queue = NULL; + int err = _queues_lookup(queues, qid, &queue); + if (err < 0) { + return err; + } + err = _queue_get_count(queue, p_count); + _queue_unmark_waiter(queue, queues->mutex); + return err; +} + + +/* external Queue objects ***************************************************/ + +static int _queueobj_shared(PyThreadState *, + PyObject *, _PyCrossInterpreterData *); + +static int +set_external_queue_type(PyObject *module, PyTypeObject *queue_type) +{ + module_state *state = get_module_state(module); + + if (state->queue_type != NULL) { + PyErr_SetString(PyExc_TypeError, "already registered"); + return -1; + } + state->queue_type = (PyTypeObject *)Py_NewRef(queue_type); + + if (_PyCrossInterpreterData_RegisterClass(queue_type, _queueobj_shared) < 0) { + return -1; + } + + return 0; +} + +static PyTypeObject * +get_external_queue_type(PyObject *module) +{ + module_state *state = get_module_state(module); + + PyTypeObject *cls = state->queue_type; + if (cls == NULL) { + // Force the module to be loaded, to register the type. + PyObject *highlevel = PyImport_ImportModule("interpreters.queue"); + if (highlevel == NULL) { + PyErr_Clear(); + highlevel = PyImport_ImportModule("test.support.interpreters.queue"); + if (highlevel == NULL) { + return NULL; + } + } + Py_DECREF(highlevel); + cls = state->queue_type; + assert(cls != NULL); + } + return cls; +} + + +// XXX Use a new __xid__ protocol instead? + +struct _queueid_xid { + int64_t qid; +}; + +static _queues * _get_global_queues(void); + +static void * +_queueid_xid_new(int64_t qid) +{ + _queues *queues = _get_global_queues(); + if (_queues_incref(queues, qid) < 0) { + return NULL; + } + + struct _queueid_xid *data = PyMem_RawMalloc(sizeof(struct _queueid_xid)); + if (data == NULL) { + _queues_incref(queues, qid); + return NULL; + } + data->qid = qid; + return (void *)data; +} + +static void +_queueid_xid_free(void *data) +{ + int64_t qid = ((struct _queueid_xid *)data)->qid; + PyMem_RawFree(data); + _queues *queues = _get_global_queues(); + _queues_decref(queues, qid); +} + +static PyObject * +_queueobj_from_xid(_PyCrossInterpreterData *data) +{ + int64_t qid = *(int64_t *)data->data; + PyObject *qidobj = PyLong_FromLongLong(qid); + if (qidobj == NULL) { + return NULL; + } + + PyObject *mod = _get_current_module(); + if (mod == NULL) { + // XXX import it? + PyErr_SetString(PyExc_RuntimeError, + MODULE_NAME " module not imported yet"); + return NULL; + } + + PyTypeObject *cls = get_external_queue_type(mod); + Py_DECREF(mod); + if (cls == NULL) { + Py_DECREF(qidobj); + return NULL; + } + PyObject *obj = PyObject_CallOneArg((PyObject *)cls, (PyObject *)qidobj); + Py_DECREF(qidobj); + return obj; +} + +static int +_queueobj_shared(PyThreadState *tstate, PyObject *queueobj, + _PyCrossInterpreterData *data) +{ + PyObject *qidobj = PyObject_GetAttrString(queueobj, "_id"); + if (qidobj == NULL) { + return -1; + } + struct idarg_int64_converter_data converted = { + .label = "queue ID", + }; + int res = idarg_int64_converter(qidobj, &converted); + Py_DECREF(qidobj); + if (!res) { + assert(PyErr_Occurred()); + return -1; + } + + void *raw = _queueid_xid_new(converted.id); + if (raw == NULL) { + Py_DECREF(qidobj); + return -1; + } + _PyCrossInterpreterData_Init(data, tstate->interp, raw, NULL, + _queueobj_from_xid); + Py_DECREF(qidobj); + data->free = _queueid_xid_free; + return 0; +} + + +/* module level code ********************************************************/ + +/* globals is the process-global state for the module. It holds all + the data that we need to share between interpreters, so it cannot + hold PyObject values. */ +static struct globals { + int module_count; + _queues queues; +} _globals = {0}; + +static int +_globals_init(void) +{ + // XXX This isn't thread-safe. + _globals.module_count++; + if (_globals.module_count > 1) { + // Already initialized. + return 0; + } + + assert(_globals.queues.mutex == NULL); + PyThread_type_lock mutex = PyThread_allocate_lock(); + if (mutex == NULL) { + return ERR_QUEUES_ALLOC; + } + _queues_init(&_globals.queues, mutex); + return 0; +} + +static void +_globals_fini(void) +{ + // XXX This isn't thread-safe. + _globals.module_count--; + if (_globals.module_count > 0) { + return; + } + + _queues_fini(&_globals.queues); +} + +static _queues * +_get_global_queues(void) +{ + return &_globals.queues; +} + + +static void +clear_interpreter(void *data) +{ + if (_globals.module_count == 0) { + return; + } + PyInterpreterState *interp = (PyInterpreterState *)data; + assert(interp == _get_current_interp()); + int64_t interpid = PyInterpreterState_GetID(interp); + _queues_clear_interpreter(&_globals.queues, interpid); +} + + +typedef struct idarg_int64_converter_data qidarg_converter_data; + +static int +qidarg_converter(PyObject *arg, void *ptr) +{ + qidarg_converter_data *data = ptr; + if (data->label == NULL) { + data->label = "queue ID"; + } + return idarg_int64_converter(arg, ptr); +} + + +static PyObject * +queuesmod_create(PyObject *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"maxsize", NULL}; + Py_ssize_t maxsize = -1; + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|n:create", kwlist, + &maxsize)) { + return NULL; + } + + int64_t qid = queue_create(&_globals.queues, maxsize); + if (qid < 0) { + (void)handle_queue_error((int)qid, self, qid); + return NULL; + } + + PyObject *qidobj = PyLong_FromLongLong(qid); + if (qidobj == NULL) { + PyObject *exc = PyErr_GetRaisedException(); + int err = queue_destroy(&_globals.queues, qid); + if (handle_queue_error(err, self, qid)) { + // XXX issue a warning? + PyErr_Clear(); + } + PyErr_SetRaisedException(exc); + return NULL; + } + + return qidobj; +} + +PyDoc_STRVAR(queuesmod_create_doc, +"create() -> qid\n\ +\n\ +Create a new cross-interpreter queue and return its unique generated ID.\n\ +It is a new reference as though bind() had been called on the queue."); + +static PyObject * +queuesmod_destroy(PyObject *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"qid", NULL}; + qidarg_converter_data qidarg; + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&:destroy", kwlist, + qidarg_converter, &qidarg)) { + return NULL; + } + int64_t qid = qidarg.id; + + int err = queue_destroy(&_globals.queues, qid); + if (handle_queue_error(err, self, qid)) { + return NULL; + } + Py_RETURN_NONE; +} + +PyDoc_STRVAR(queuesmod_destroy_doc, +"destroy(qid)\n\ +\n\ +Clear and destroy the queue. Afterward attempts to use the queue\n\ +will behave as though it never existed."); + +static PyObject * +queuesmod_list_all(PyObject *self, PyObject *Py_UNUSED(ignored)) +{ + int64_t count = 0; + int64_t *qids = _queues_list_all(&_globals.queues, &count); + if (qids == NULL) { + if (count == 0) { + return PyList_New(0); + } + return NULL; + } + PyObject *ids = PyList_New((Py_ssize_t)count); + if (ids == NULL) { + goto finally; + } + int64_t *cur = qids; + for (int64_t i=0; i < count; cur++, i++) { + PyObject *qidobj = PyLong_FromLongLong(*cur); + if (qidobj == NULL) { + Py_SETREF(ids, NULL); + break; + } + PyList_SET_ITEM(ids, (Py_ssize_t)i, qidobj); + } + +finally: + PyMem_Free(qids); + return ids; +} + +PyDoc_STRVAR(queuesmod_list_all_doc, +"list_all() -> [qid]\n\ +\n\ +Return the list of IDs for all queues."); + +static PyObject * +queuesmod_put(PyObject *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"qid", "obj", NULL}; + qidarg_converter_data qidarg; + PyObject *obj; + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&O:put", kwlist, + qidarg_converter, &qidarg, &obj)) { + return NULL; + } + int64_t qid = qidarg.id; + + /* Queue up the object. */ + int err = queue_put(&_globals.queues, qid, obj); + if (handle_queue_error(err, self, qid)) { + return NULL; + } + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(queuesmod_put_doc, +"put(qid, obj)\n\ +\n\ +Add the object's data to the queue."); + +static PyObject * +queuesmod_get(PyObject *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"qid", "default", NULL}; + qidarg_converter_data qidarg; + PyObject *dflt = NULL; + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&|O:get", kwlist, + qidarg_converter, &qidarg, &dflt)) { + return NULL; + } + int64_t qid = qidarg.id; + + PyObject *obj = NULL; + int err = queue_get(&_globals.queues, qid, &obj); + if (err == ERR_QUEUE_EMPTY && dflt != NULL) { + assert(obj == NULL); + obj = Py_NewRef(dflt); + } + else if (handle_queue_error(err, self, qid)) { + return NULL; + } + return obj; +} + +PyDoc_STRVAR(queuesmod_get_doc, +"get(qid, [default]) -> obj\n\ +\n\ +Return a new object from the data at the front of the queue.\n\ +\n\ +If there is nothing to receive then raise QueueEmpty, unless\n\ +a default value is provided. In that case return it."); + +static PyObject * +queuesmod_bind(PyObject *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"qid", NULL}; + qidarg_converter_data qidarg; + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&:bind", kwlist, + qidarg_converter, &qidarg)) { + return NULL; + } + int64_t qid = qidarg.id; + + // XXX Check module state if bound already. + + int err = _queues_incref(&_globals.queues, qid); + if (handle_queue_error(err, self, qid)) { + return NULL; + } + + // XXX Update module state. + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(queuesmod_bind_doc, +"bind(qid)\n\ +\n\ +Take a reference to the identified queue.\n\ +The queue is not destroyed until there are no references left."); + +static PyObject * +queuesmod_release(PyObject *self, PyObject *args, PyObject *kwds) +{ + // Note that only the current interpreter is affected. + static char *kwlist[] = {"qid", NULL}; + qidarg_converter_data qidarg; + if (!PyArg_ParseTupleAndKeywords(args, kwds, + "O&:release", kwlist, + qidarg_converter, &qidarg)) { + return NULL; + } + int64_t qid = qidarg.id; + + // XXX Check module state if bound already. + // XXX Update module state. + + _queues_decref(&_globals.queues, qid); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(queuesmod_release_doc, +"release(qid)\n\ +\n\ +Release a reference to the queue.\n\ +The queue is destroyed once there are no references left."); + +static PyObject * +queuesmod_get_maxsize(PyObject *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"qid", NULL}; + qidarg_converter_data qidarg; + if (!PyArg_ParseTupleAndKeywords(args, kwds, + "O&:get_maxsize", kwlist, + qidarg_converter, &qidarg)) { + return NULL; + } + int64_t qid = qidarg.id; + + Py_ssize_t maxsize = -1; + int err = queue_get_maxsize(&_globals.queues, qid, &maxsize); + if (handle_queue_error(err, self, qid)) { + return NULL; + } + return PyLong_FromLongLong(maxsize); +} + +PyDoc_STRVAR(queuesmod_get_maxsize_doc, +"get_maxsize(qid)\n\ +\n\ +Return the maximum number of items in the queue."); + +static PyObject * +queuesmod_is_full(PyObject *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"qid", NULL}; + qidarg_converter_data qidarg; + if (!PyArg_ParseTupleAndKeywords(args, kwds, + "O&:is_full", kwlist, + qidarg_converter, &qidarg)) { + return NULL; + } + int64_t qid = qidarg.id; + + int is_full = 0; + int err = queue_is_full(&_globals.queues, qid, &is_full); + if (handle_queue_error(err, self, qid)) { + return NULL; + } + if (is_full) { + Py_RETURN_TRUE; + } + Py_RETURN_FALSE; +} + +PyDoc_STRVAR(queuesmod_is_full_doc, +"is_full(qid)\n\ +\n\ +Return true if the queue has a maxsize and has reached it."); + +static PyObject * +queuesmod_get_count(PyObject *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"qid", NULL}; + qidarg_converter_data qidarg; + if (!PyArg_ParseTupleAndKeywords(args, kwds, + "O&:get_count", kwlist, + qidarg_converter, &qidarg)) { + return NULL; + } + int64_t qid = qidarg.id; + + Py_ssize_t count = -1; + int err = queue_get_count(&_globals.queues, qid, &count); + if (handle_queue_error(err, self, qid)) { + return NULL; + } + assert(count >= 0); + return PyLong_FromSsize_t(count); +} + +PyDoc_STRVAR(queuesmod_get_count_doc, +"get_count(qid)\n\ +\n\ +Return the number of items in the queue."); + +static PyObject * +queuesmod__register_queue_type(PyObject *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"queuetype", NULL}; + PyObject *queuetype; + if (!PyArg_ParseTupleAndKeywords(args, kwds, + "O:_register_queue_type", kwlist, + &queuetype)) { + return NULL; + } + if (!PyType_Check(queuetype)) { + PyErr_SetString(PyExc_TypeError, "expected a type for 'queuetype'"); + return NULL; + } + PyTypeObject *cls_queue = (PyTypeObject *)queuetype; + + if (set_external_queue_type(self, cls_queue) < 0) { + return NULL; + } + + Py_RETURN_NONE; +} + +static PyMethodDef module_functions[] = { + {"create", _PyCFunction_CAST(queuesmod_create), + METH_VARARGS | METH_KEYWORDS, queuesmod_create_doc}, + {"destroy", _PyCFunction_CAST(queuesmod_destroy), + METH_VARARGS | METH_KEYWORDS, queuesmod_destroy_doc}, + {"list_all", queuesmod_list_all, + METH_NOARGS, queuesmod_list_all_doc}, + {"put", _PyCFunction_CAST(queuesmod_put), + METH_VARARGS | METH_KEYWORDS, queuesmod_put_doc}, + {"get", _PyCFunction_CAST(queuesmod_get), + METH_VARARGS | METH_KEYWORDS, queuesmod_get_doc}, + {"bind", _PyCFunction_CAST(queuesmod_bind), + METH_VARARGS | METH_KEYWORDS, queuesmod_bind_doc}, + {"release", _PyCFunction_CAST(queuesmod_release), + METH_VARARGS | METH_KEYWORDS, queuesmod_release_doc}, + {"get_maxsize", _PyCFunction_CAST(queuesmod_get_maxsize), + METH_VARARGS | METH_KEYWORDS, queuesmod_get_maxsize_doc}, + {"is_full", _PyCFunction_CAST(queuesmod_is_full), + METH_VARARGS | METH_KEYWORDS, queuesmod_is_full_doc}, + {"get_count", _PyCFunction_CAST(queuesmod_get_count), + METH_VARARGS | METH_KEYWORDS, queuesmod_get_count_doc}, + {"_register_queue_type", _PyCFunction_CAST(queuesmod__register_queue_type), + METH_VARARGS | METH_KEYWORDS, NULL}, + + {NULL, NULL} /* sentinel */ +}; + + +/* initialization function */ + +PyDoc_STRVAR(module_doc, +"This module provides primitive operations to manage Python interpreters.\n\ +The 'interpreters' module provides a more convenient interface."); + +static int +module_exec(PyObject *mod) +{ + if (_globals_init() != 0) { + return -1; + } + + /* Add exception types */ + if (add_QueueError(mod) < 0) { + goto error; + } + + /* Make sure queues drop objects owned by this interpreter. */ + PyInterpreterState *interp = _get_current_interp(); + PyUnstable_AtExit(interp, clear_interpreter, (void *)interp); + + return 0; + +error: + _globals_fini(); + return -1; +} + +static struct PyModuleDef_Slot module_slots[] = { + {Py_mod_exec, module_exec}, + {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, + {0, NULL}, +}; + +static int +module_traverse(PyObject *mod, visitproc visit, void *arg) +{ + module_state *state = get_module_state(mod); + traverse_module_state(state, visit, arg); + return 0; +} + +static int +module_clear(PyObject *mod) +{ + module_state *state = get_module_state(mod); + + if (state->queue_type != NULL) { + (void)_PyCrossInterpreterData_UnregisterClass(state->queue_type); + } + + // Now we clear the module state. + clear_module_state(state); + return 0; +} + +static void +module_free(void *mod) +{ + module_state *state = get_module_state(mod); + + // Now we clear the module state. + clear_module_state(state); + + _globals_fini(); +} + +static struct PyModuleDef moduledef = { + .m_base = PyModuleDef_HEAD_INIT, + .m_name = MODULE_NAME, + .m_doc = module_doc, + .m_size = sizeof(module_state), + .m_methods = module_functions, + .m_slots = module_slots, + .m_traverse = module_traverse, + .m_clear = module_clear, + .m_free = (freefunc)module_free, +}; + +PyMODINIT_FUNC +PyInit__xxinterpqueues(void) +{ + return PyModuleDef_Init(&moduledef); +} diff --git a/Modules/_xxsubinterpretersmodule.c b/Modules/_xxsubinterpretersmodule.c index 31373f8fdf8c71..4e9e13457a9eb3 100644 --- a/Modules/_xxsubinterpretersmodule.c +++ b/Modules/_xxsubinterpretersmodule.c @@ -1,29 +1,28 @@ /* interpreters module */ /* low-level access to interpreter primitives */ +#ifndef Py_BUILD_CORE_BUILTIN +# define Py_BUILD_CORE_MODULE 1 +#endif + #include "Python.h" +#include "pycore_abstract.h" // _PyIndex_Check() +#include "pycore_crossinterp.h" // struct _xid +#include "pycore_interp.h" // _PyInterpreterState_IDIncref() +#include "pycore_initconfig.h" // _PyErr_SetFromPyStatus() +#include "pycore_long.h" // _PyLong_IsNegative() +#include "pycore_modsupport.h" // _PyArg_BadArgument() +#include "pycore_pybuffer.h" // _PyBuffer_ReleaseInInterpreterAndRawFree() +#include "pycore_pyerrors.h" // _Py_excinfo +#include "pycore_pystate.h" // _PyInterpreterState_SetRunningMain() + #include "interpreteridobject.h" +#include "marshal.h" // PyMarshal_ReadObjectFromString() #define MODULE_NAME "_xxsubinterpreters" -static const char * -_copy_raw_string(PyObject *strobj) -{ - const char *str = PyUnicode_AsUTF8(strobj); - if (str == NULL) { - return NULL; - } - char *copied = PyMem_RawMalloc(strlen(str)+1); - if (copied == NULL) { - PyErr_NoMemory(); - return NULL; - } - strcpy(copied, str); - return copied; -} - static PyInterpreterState * _get_current_interp(void) { @@ -32,462 +31,473 @@ _get_current_interp(void) return PyInterpreterState_Get(); } -static PyObject * -add_new_exception(PyObject *mod, const char *name, PyObject *base) +static int64_t +pylong_to_interpid(PyObject *idobj) { - assert(!PyObject_HasAttrString(mod, name)); - PyObject *exctype = PyErr_NewException(name, base, NULL); - if (exctype == NULL) { - return NULL; + assert(PyLong_CheckExact(idobj)); + + if (_PyLong_IsNegative((PyLongObject *)idobj)) { + PyErr_Format(PyExc_ValueError, + "interpreter ID must be a non-negative int, got %R", + idobj); + return -1; } - int res = PyModule_AddType(mod, (PyTypeObject *)exctype); - if (res < 0) { - Py_DECREF(exctype); - return NULL; + + int overflow; + long long id = PyLong_AsLongLongAndOverflow(idobj, &overflow); + if (id == -1) { + if (!overflow) { + assert(PyErr_Occurred()); + return -1; + } + assert(!PyErr_Occurred()); + // For now, we don't worry about if LLONG_MAX < INT64_MAX. + goto bad_id; } - return exctype; -} +#if LLONG_MAX > INT64_MAX + if (id > INT64_MAX) { + goto bad_id; + } +#endif + return (int64_t)id; -#define ADD_NEW_EXCEPTION(MOD, NAME, BASE) \ - add_new_exception(MOD, MODULE_NAME "." Py_STRINGIFY(NAME), BASE) +bad_id: + PyErr_Format(PyExc_RuntimeError, + "unrecognized interpreter ID %O", idobj); + return -1; +} -static int -_release_xid_data(_PyCrossInterpreterData *data, int ignoreexc) +static int64_t +convert_interpid_obj(PyObject *arg) { - PyObject *exc; - if (ignoreexc) { - exc = PyErr_GetRaisedException(); - } - int res = _PyCrossInterpreterData_Release(data); - if (res < 0) { - /* The owning interpreter is already destroyed. */ - _PyCrossInterpreterData_Clear(NULL, data); - if (ignoreexc) { - // XXX Emit a warning? - PyErr_Clear(); + int64_t id = -1; + if (_PyIndex_Check(arg)) { + PyObject *idobj = PyNumber_Long(arg); + if (idobj == NULL) { + return -1; + } + id = pylong_to_interpid(idobj); + Py_DECREF(idobj); + if (id < 0) { + return -1; } } - if (ignoreexc) { - PyErr_SetRaisedException(exc); + else { + PyErr_Format(PyExc_TypeError, + "interpreter ID must be an int, got %.100s", + Py_TYPE(arg)->tp_name); + return -1; } - return res; + return id; } +static PyInterpreterState * +look_up_interp(PyObject *arg) +{ + int64_t id = convert_interpid_obj(arg); + if (id < 0) { + return NULL; + } + return _PyInterpreterState_LookUpID(id); +} -/* module state *************************************************************/ - -typedef struct { - /* exceptions */ - PyObject *RunFailedError; -} module_state; -static inline module_state * -get_module_state(PyObject *mod) +static PyObject * +interpid_to_pylong(int64_t id) { - assert(mod != NULL); - module_state *state = PyModule_GetState(mod); - assert(state != NULL); - return state; + assert(id < LLONG_MAX); + return PyLong_FromLongLong(id); } -static int -traverse_module_state(module_state *state, visitproc visit, void *arg) +static PyObject * +get_interpid_obj(PyInterpreterState *interp) { - /* exceptions */ - Py_VISIT(state->RunFailedError); - - return 0; + if (_PyInterpreterState_IDInitref(interp) != 0) { + return NULL; + }; + int64_t id = PyInterpreterState_GetID(interp); + if (id < 0) { + return NULL; + } + return interpid_to_pylong(id); } -static int -clear_module_state(module_state *state) +static PyObject * +_get_current_module(void) { - /* exceptions */ - Py_CLEAR(state->RunFailedError); - - return 0; + PyObject *name = PyUnicode_FromString(MODULE_NAME); + if (name == NULL) { + return NULL; + } + PyObject *mod = PyImport_GetModule(name); + Py_DECREF(name); + if (mod == NULL) { + return NULL; + } + assert(mod != Py_None); + return mod; } -/* data-sharing-specific code ***********************************************/ +/* Cross-interpreter Buffer Views *******************************************/ -struct _sharednsitem { - const char *name; - _PyCrossInterpreterData data; -}; +// XXX Release when the original interpreter is destroyed. -static void _sharednsitem_clear(struct _sharednsitem *); // forward +typedef struct { + PyObject_HEAD + Py_buffer *view; + int64_t interpid; +} XIBufferViewObject; -static int -_sharednsitem_init(struct _sharednsitem *item, PyObject *key, PyObject *value) +static PyObject * +xibufferview_from_xid(PyTypeObject *cls, _PyCrossInterpreterData *data) { - item->name = _copy_raw_string(key); - if (item->name == NULL) { - return -1; - } - if (_PyObject_GetCrossInterpreterData(value, &item->data) != 0) { - _sharednsitem_clear(item); - return -1; + assert(data->data != NULL); + assert(data->obj == NULL); + assert(data->interpid >= 0); + XIBufferViewObject *self = PyObject_Malloc(sizeof(XIBufferViewObject)); + if (self == NULL) { + return NULL; } - return 0; + PyObject_Init((PyObject *)self, cls); + self->view = (Py_buffer *)data->data; + self->interpid = data->interpid; + return (PyObject *)self; } static void -_sharednsitem_clear(struct _sharednsitem *item) +xibufferview_dealloc(XIBufferViewObject *self) { - if (item->name != NULL) { - PyMem_RawFree((void *)item->name); - item->name = NULL; + PyInterpreterState *interp = _PyInterpreterState_LookUpID(self->interpid); + /* If the interpreter is no longer alive then we have problems, + since other objects may be using the buffer still. */ + assert(interp != NULL); + + if (_PyBuffer_ReleaseInInterpreterAndRawFree(interp, self->view) < 0) { + // XXX Emit a warning? + PyErr_Clear(); } - (void)_release_xid_data(&item->data, 1); + + PyTypeObject *tp = Py_TYPE(self); + tp->tp_free(self); + /* "Instances of heap-allocated types hold a reference to their type." + * See: https://docs.python.org/3.11/howto/isolating-extensions.html#garbage-collection-protocol + * See: https://docs.python.org/3.11/c-api/typeobj.html#c.PyTypeObject.tp_traverse + */ + // XXX Why don't we implement Py_TPFLAGS_HAVE_GC, e.g. Py_tp_traverse, + // like we do for _abc._abc_data? + Py_DECREF(tp); } static int -_sharednsitem_apply(struct _sharednsitem *item, PyObject *ns) +xibufferview_getbuf(XIBufferViewObject *self, Py_buffer *view, int flags) { - PyObject *name = PyUnicode_FromString(item->name); - if (name == NULL) { - return -1; - } - PyObject *value = _PyCrossInterpreterData_NewObject(&item->data); - if (value == NULL) { - Py_DECREF(name); - return -1; - } - int res = PyDict_SetItem(ns, name, value); - Py_DECREF(name); - Py_DECREF(value); - return res; + /* Only PyMemoryView_FromObject() should ever call this, + via _memoryview_from_xid() below. */ + *view = *self->view; + view->obj = (PyObject *)self; + // XXX Should we leave it alone? + view->internal = NULL; + return 0; } -typedef struct _sharedns { - Py_ssize_t len; - struct _sharednsitem* items; -} _sharedns; +static PyType_Slot XIBufferViewType_slots[] = { + {Py_tp_dealloc, (destructor)xibufferview_dealloc}, + {Py_bf_getbuffer, (getbufferproc)xibufferview_getbuf}, + // We don't bother with Py_bf_releasebuffer since we don't need it. + {0, NULL}, +}; + +static PyType_Spec XIBufferViewType_spec = { + .name = MODULE_NAME ".CrossInterpreterBufferView", + .basicsize = sizeof(XIBufferViewObject), + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | + Py_TPFLAGS_DISALLOW_INSTANTIATION | Py_TPFLAGS_IMMUTABLETYPE), + .slots = XIBufferViewType_slots, +}; + + +static PyTypeObject * _get_current_xibufferview_type(void); -static _sharedns * -_sharedns_new(Py_ssize_t len) +static PyObject * +_memoryview_from_xid(_PyCrossInterpreterData *data) { - _sharedns *shared = PyMem_NEW(_sharedns, 1); - if (shared == NULL) { - PyErr_NoMemory(); + PyTypeObject *cls = _get_current_xibufferview_type(); + if (cls == NULL) { return NULL; } - shared->len = len; - shared->items = PyMem_NEW(struct _sharednsitem, len); - if (shared->items == NULL) { - PyErr_NoMemory(); - PyMem_Free(shared); + PyObject *obj = xibufferview_from_xid(cls, data); + if (obj == NULL) { return NULL; } - return shared; + return PyMemoryView_FromObject(obj); } -static void -_sharedns_free(_sharedns *shared) +static int +_memoryview_shared(PyThreadState *tstate, PyObject *obj, + _PyCrossInterpreterData *data) { - for (Py_ssize_t i=0; i < shared->len; i++) { - _sharednsitem_clear(&shared->items[i]); + Py_buffer *view = PyMem_RawMalloc(sizeof(Py_buffer)); + if (view == NULL) { + return -1; } - PyMem_Free(shared->items); - PyMem_Free(shared); + if (PyObject_GetBuffer(obj, view, PyBUF_FULL_RO) < 0) { + PyMem_RawFree(view); + return -1; + } + _PyCrossInterpreterData_Init(data, tstate->interp, view, NULL, + _memoryview_from_xid); + return 0; } -static _sharedns * -_get_shared_ns(PyObject *shareable) +static int +register_memoryview_xid(PyObject *mod, PyTypeObject **p_state) { - if (shareable == NULL || shareable == Py_None) { - return NULL; + // XIBufferView + assert(*p_state == NULL); + PyTypeObject *cls = (PyTypeObject *)PyType_FromModuleAndSpec( + mod, &XIBufferViewType_spec, NULL); + if (cls == NULL) { + return -1; } - Py_ssize_t len = PyDict_Size(shareable); - if (len == 0) { - return NULL; + if (PyModule_AddType(mod, cls) < 0) { + Py_DECREF(cls); + return -1; } + *p_state = cls; - _sharedns *shared = _sharedns_new(len); - if (shared == NULL) { - return NULL; - } - Py_ssize_t pos = 0; - for (Py_ssize_t i=0; i < len; i++) { - PyObject *key, *value; - if (PyDict_Next(shareable, &pos, &key, &value) == 0) { - break; - } - if (_sharednsitem_init(&shared->items[i], key, value) != 0) { - break; - } - } - if (PyErr_Occurred()) { - _sharedns_free(shared); - return NULL; + // Register XID for the builtin memoryview type. + if (_PyCrossInterpreterData_RegisterClass( + &PyMemoryView_Type, _memoryview_shared) < 0) { + return -1; } - return shared; -} + // We don't ever bother un-registering memoryview. -static int -_sharedns_apply(_sharedns *shared, PyObject *ns) -{ - for (Py_ssize_t i=0; i < shared->len; i++) { - if (_sharednsitem_apply(&shared->items[i], ns) != 0) { - return -1; - } - } return 0; } -// Ultimately we'd like to preserve enough information about the -// exception and traceback that we could re-constitute (or at least -// simulate, a la traceback.TracebackException), and even chain, a copy -// of the exception in the calling interpreter. -typedef struct _sharedexception { - const char *name; - const char *msg; -} _sharedexception; -static const struct _sharedexception no_exception = { - .name = NULL, - .msg = NULL, -}; +/* module state *************************************************************/ -static void -_sharedexception_clear(_sharedexception *exc) +typedef struct { + int _notused; + + /* heap types */ + PyTypeObject *XIBufferViewType; +} module_state; + +static inline module_state * +get_module_state(PyObject *mod) { - if (exc->name != NULL) { - PyMem_RawFree((void *)exc->name); - } - if (exc->msg != NULL) { - PyMem_RawFree((void *)exc->msg); - } + assert(mod != NULL); + module_state *state = PyModule_GetState(mod); + assert(state != NULL); + return state; } -static const char * -_sharedexception_bind(PyObject *exc, _sharedexception *sharedexc) +static module_state * +_get_current_module_state(void) { - assert(exc != NULL); - const char *failure = NULL; - - PyObject *nameobj = PyUnicode_FromString(Py_TYPE(exc)->tp_name); - if (nameobj == NULL) { - failure = "unable to format exception type name"; - goto error; - } - sharedexc->name = _copy_raw_string(nameobj); - Py_DECREF(nameobj); - if (sharedexc->name == NULL) { - if (PyErr_ExceptionMatches(PyExc_MemoryError)) { - failure = "out of memory copying exception type name"; - } else { - failure = "unable to encode and copy exception type name"; - } - goto error; + PyObject *mod = _get_current_module(); + if (mod == NULL) { + // XXX import it? + PyErr_SetString(PyExc_RuntimeError, + MODULE_NAME " module not imported yet"); + return NULL; } + module_state *state = get_module_state(mod); + Py_DECREF(mod); + return state; +} - if (exc != NULL) { - PyObject *msgobj = PyUnicode_FromFormat("%S", exc); - if (msgobj == NULL) { - failure = "unable to format exception message"; - goto error; - } - sharedexc->msg = _copy_raw_string(msgobj); - Py_DECREF(msgobj); - if (sharedexc->msg == NULL) { - if (PyErr_ExceptionMatches(PyExc_MemoryError)) { - failure = "out of memory copying exception message"; - } else { - failure = "unable to encode and copy exception message"; - } - goto error; - } - } +static int +traverse_module_state(module_state *state, visitproc visit, void *arg) +{ + /* heap types */ + Py_VISIT(state->XIBufferViewType); - return NULL; + return 0; +} -error: - assert(failure != NULL); - PyErr_Clear(); - _sharedexception_clear(sharedexc); - *sharedexc = no_exception; - return failure; +static int +clear_module_state(module_state *state) +{ + /* heap types */ + Py_CLEAR(state->XIBufferViewType); + + return 0; } -static void -_sharedexception_apply(_sharedexception *exc, PyObject *wrapperclass) + +static PyTypeObject * +_get_current_xibufferview_type(void) { - if (exc->name != NULL) { - if (exc->msg != NULL) { - PyErr_Format(wrapperclass, "%s: %s", exc->name, exc->msg); - } - else { - PyErr_SetString(wrapperclass, exc->name); - } - } - else if (exc->msg != NULL) { - PyErr_SetString(wrapperclass, exc->msg); - } - else { - PyErr_SetNone(wrapperclass); + module_state *state = _get_current_module_state(); + if (state == NULL) { + return NULL; } + return state->XIBufferViewType; } -/* interpreter-specific code ************************************************/ +/* Python code **************************************************************/ -static int -exceptions_init(PyObject *mod) +static const char * +check_code_str(PyUnicodeObject *text) { - module_state *state = get_module_state(mod); - if (state == NULL) { - return -1; + assert(text != NULL); + if (PyUnicode_GET_LENGTH(text) == 0) { + return "too short"; } -#define ADD(NAME, BASE) \ - do { \ - assert(state->NAME == NULL); \ - state->NAME = ADD_NEW_EXCEPTION(mod, NAME, BASE); \ - if (state->NAME == NULL) { \ - return -1; \ - } \ - } while (0) - - // An uncaught exception came out of interp_run_string(). - ADD(RunFailedError, PyExc_RuntimeError); -#undef ADD + // XXX Verify that it parses? - return 0; + return NULL; } -static int -_is_running(PyInterpreterState *interp) +static const char * +check_code_object(PyCodeObject *code) { - PyThreadState *tstate = PyInterpreterState_ThreadHead(interp); - if (PyThreadState_Next(tstate) != NULL) { - PyErr_SetString(PyExc_RuntimeError, - "interpreter has more than one thread"); - return -1; + assert(code != NULL); + if (code->co_argcount > 0 + || code->co_posonlyargcount > 0 + || code->co_kwonlyargcount > 0 + || code->co_flags & (CO_VARARGS | CO_VARKEYWORDS)) + { + return "arguments not supported"; } - - assert(!PyErr_Occurred()); - struct _PyInterpreterFrame *frame = tstate->cframe->current_frame; - if (frame == NULL) { - return 0; + if (code->co_ncellvars > 0) { + return "closures not supported"; } - return 1; -} + // We trust that no code objects under co_consts have unbound cell vars. -static int -_ensure_not_running(PyInterpreterState *interp) -{ - int is_running = _is_running(interp); - if (is_running < 0) { - return -1; + if (code->co_executors != NULL + || code->_co_instrumentation_version > 0) + { + return "only basic functions are supported"; } - if (is_running) { - PyErr_Format(PyExc_RuntimeError, "interpreter already running"); - return -1; + if (code->_co_monitoring != NULL) { + return "only basic functions are supported"; } - return 0; + if (code->co_extra != NULL) { + return "only basic functions are supported"; + } + + return NULL; } -static int -_run_script(PyInterpreterState *interp, const char *codestr, - _sharedns *shared, _sharedexception *sharedexc) +#define RUN_TEXT 1 +#define RUN_CODE 2 + +static const char * +get_code_str(PyObject *arg, Py_ssize_t *len_p, PyObject **bytes_p, int *flags_p) { - PyObject *excval = NULL; - PyObject *main_mod = PyUnstable_InterpreterState_GetMainModule(interp); - if (main_mod == NULL) { - goto error; - } - PyObject *ns = PyModule_GetDict(main_mod); // borrowed - Py_DECREF(main_mod); - if (ns == NULL) { - goto error; + const char *codestr = NULL; + Py_ssize_t len = -1; + PyObject *bytes_obj = NULL; + int flags = 0; + + if (PyUnicode_Check(arg)) { + assert(PyUnicode_CheckExact(arg) + && (check_code_str((PyUnicodeObject *)arg) == NULL)); + codestr = PyUnicode_AsUTF8AndSize(arg, &len); + if (codestr == NULL) { + return NULL; + } + if (strlen(codestr) != (size_t)len) { + PyErr_SetString(PyExc_ValueError, + "source code string cannot contain null bytes"); + return NULL; + } + flags = RUN_TEXT; } - Py_INCREF(ns); + else { + assert(PyCode_Check(arg) + && (check_code_object((PyCodeObject *)arg) == NULL)); + flags = RUN_CODE; - // Apply the cross-interpreter data. - if (shared != NULL) { - if (_sharedns_apply(shared, ns) != 0) { - Py_DECREF(ns); - goto error; + // Serialize the code object. + bytes_obj = PyMarshal_WriteObjectToString(arg, Py_MARSHAL_VERSION); + if (bytes_obj == NULL) { + return NULL; } + codestr = PyBytes_AS_STRING(bytes_obj); + len = PyBytes_GET_SIZE(bytes_obj); } - // Run the string (see PyRun_SimpleStringFlags). - PyObject *result = PyRun_StringFlags(codestr, Py_file_input, ns, ns, NULL); - Py_DECREF(ns); - if (result == NULL) { - goto error; - } - else { - Py_DECREF(result); // We throw away the result. - } + *flags_p = flags; + *bytes_p = bytes_obj; + *len_p = len; + return codestr; +} - *sharedexc = no_exception; - return 0; -error: - excval = PyErr_GetRaisedException(); - const char *failure = _sharedexception_bind(excval, sharedexc); - if (failure != NULL) { - fprintf(stderr, - "RunFailedError: script raised an uncaught exception (%s)", - failure); - PyErr_Clear(); - } - Py_XDECREF(excval); - assert(!PyErr_Occurred()); - return -1; -} +/* interpreter-specific code ************************************************/ static int -_run_script_in_interpreter(PyObject *mod, PyInterpreterState *interp, - const char *codestr, PyObject *shareables) +_run_script(PyObject *ns, const char *codestr, Py_ssize_t codestrlen, int flags) { - if (_ensure_not_running(interp) < 0) { - return -1; + PyObject *result = NULL; + if (flags & RUN_TEXT) { + result = PyRun_StringFlags(codestr, Py_file_input, ns, ns, NULL); + } + else if (flags & RUN_CODE) { + PyObject *code = PyMarshal_ReadObjectFromString(codestr, codestrlen); + if (code != NULL) { + result = PyEval_EvalCode(code, ns, ns); + Py_DECREF(code); + } } - module_state *state = get_module_state(mod); - - _sharedns *shared = _get_shared_ns(shareables); - if (shared == NULL && PyErr_Occurred()) { + else { + Py_UNREACHABLE(); + } + if (result == NULL) { return -1; } + Py_DECREF(result); // We throw away the result. + return 0; +} - // Switch to interpreter. - PyThreadState *save_tstate = NULL; - if (interp != PyInterpreterState_Get()) { - // XXX Using the "head" thread isn't strictly correct. - PyThreadState *tstate = PyInterpreterState_ThreadHead(interp); - // XXX Possible GILState issues? - save_tstate = PyThreadState_Swap(tstate); +static int +_run_in_interpreter(PyInterpreterState *interp, + const char *codestr, Py_ssize_t codestrlen, + PyObject *shareables, int flags, + PyObject **p_excinfo) +{ + assert(!PyErr_Occurred()); + _PyXI_session session = {0}; + + // Prep and switch interpreters. + if (_PyXI_Enter(&session, interp, shareables) < 0) { + assert(!PyErr_Occurred()); + PyObject *excinfo = _PyXI_ApplyError(session.error); + if (excinfo != NULL) { + *p_excinfo = excinfo; + } + assert(PyErr_Occurred()); + return -1; } // Run the script. - _sharedexception exc = {NULL, NULL}; - int result = _run_script(interp, codestr, shared, &exc); + int res = _run_script(session.main_ns, codestr, codestrlen, flags); - // Switch back. - if (save_tstate != NULL) { - PyThreadState_Swap(save_tstate); - } + // Clean up and switch back. + _PyXI_Exit(&session); // Propagate any exception out to the caller. - if (exc.name != NULL) { - assert(state != NULL); - _sharedexception_apply(&exc, state->RunFailedError); - } - else if (result != 0) { - // We were unable to allocate a shared exception. - PyErr_NoMemory(); + assert(!PyErr_Occurred()); + if (res < 0) { + PyObject *excinfo = _PyXI_ApplyCapturedException(&session); + if (excinfo != NULL) { + *p_excinfo = excinfo; + } } - - if (shared != NULL) { - _sharedns_free(shared); + else { + assert(!_PyXI_HasCapturedException(&session)); } - return result; + return res; } @@ -510,6 +520,7 @@ interp_create(PyObject *self, PyObject *args, PyObject *kwds) const PyInterpreterConfig config = isolated ? (PyInterpreterConfig)_PyInterpreterConfig_INIT : (PyInterpreterConfig)_PyInterpreterConfig_LEGACY_INIT; + // XXX Possible GILState issues? PyThreadState *tstate = NULL; PyStatus status = Py_NewInterpreterFromConfig(&tstate, &config); @@ -525,8 +536,9 @@ interp_create(PyObject *self, PyObject *args, PyObject *kwds) return NULL; } assert(tstate != NULL); + PyInterpreterState *interp = PyThreadState_GetInterpreter(tstate); - PyObject *idobj = PyInterpreterState_GetIDObject(interp); + PyObject *idobj = get_interpid_obj(interp); if (idobj == NULL) { // XXX Possible GILState issues? save_tstate = PyThreadState_Swap(tstate); @@ -534,6 +546,12 @@ interp_create(PyObject *self, PyObject *args, PyObject *kwds) PyThreadState_Swap(save_tstate); return NULL; } + + PyThreadState_Swap(tstate); + PyThreadState_Clear(tstate); + PyThreadState_Swap(save_tstate); + PyThreadState_Delete(tstate); + _PyInterpreterState_RequireIDRef(interp, 1); return idobj; } @@ -541,7 +559,9 @@ interp_create(PyObject *self, PyObject *args, PyObject *kwds) PyDoc_STRVAR(create_doc, "create() -> ID\n\ \n\ -Create a new interpreter and return a unique generated ID."); +Create a new interpreter and return a unique generated ID.\n\ +\n\ +The caller is responsible for destroying the interpreter before exiting."); static PyObject * @@ -556,7 +576,7 @@ interp_destroy(PyObject *self, PyObject *args, PyObject *kwds) } // Look up the interpreter. - PyInterpreterState *interp = PyInterpreterID_LookUp(id); + PyInterpreterState *interp = look_up_interp(id); if (interp == NULL) { return NULL; } @@ -575,12 +595,14 @@ interp_destroy(PyObject *self, PyObject *args, PyObject *kwds) // Ensure the interpreter isn't running. /* XXX We *could* support destroying a running interpreter but aren't going to worry about it for now. */ - if (_ensure_not_running(interp) < 0) { + if (_PyInterpreterState_IsRunningMain(interp)) { + PyErr_Format(PyExc_RuntimeError, "interpreter running"); return NULL; } // Destroy the interpreter. - PyThreadState *tstate = PyInterpreterState_ThreadHead(interp); + PyThreadState *tstate = PyThreadState_New(interp); + tstate->_whence = _PyThreadState_WHENCE_INTERP; // XXX Possible GILState issues? PyThreadState *save_tstate = PyThreadState_Swap(tstate); Py_EndInterpreter(tstate); @@ -611,7 +633,7 @@ interp_list_all(PyObject *self, PyObject *Py_UNUSED(ignored)) interp = PyInterpreterState_Head(); while (interp != NULL) { - id = PyInterpreterState_GetIDObject(interp); + id = get_interpid_obj(interp); if (id == NULL) { Py_DECREF(ids); return NULL; @@ -643,7 +665,7 @@ interp_get_current(PyObject *self, PyObject *Py_UNUSED(ignored)) if (interp == NULL) { return NULL; } - return PyInterpreterState_GetIDObject(interp); + return get_interpid_obj(interp); } PyDoc_STRVAR(get_current_doc, @@ -657,7 +679,7 @@ interp_get_main(PyObject *self, PyObject *Py_UNUSED(ignored)) { // Currently, 0 is always the main interpreter. int64_t id = 0; - return PyInterpreterID_New(id); + return PyLong_FromLongLong(id); } PyDoc_STRVAR(get_main_doc, @@ -665,16 +687,13 @@ PyDoc_STRVAR(get_main_doc, \n\ Return the ID of main interpreter."); - static PyObject * -interp_run_string(PyObject *self, PyObject *args, PyObject *kwds) +interp_set___main___attrs(PyObject *self, PyObject *args) { - static char *kwlist[] = {"id", "script", "shared", NULL}; - PyObject *id, *code; - PyObject *shared = NULL; - if (!PyArg_ParseTupleAndKeywords(args, kwds, - "OU|O:run_string", kwlist, - &id, &code, &shared)) { + PyObject *id, *updates; + if (!PyArg_ParseTuple(args, "OO:" MODULE_NAME ".set___main___attrs", + &id, &updates)) + { return NULL; } @@ -684,31 +703,276 @@ interp_run_string(PyObject *self, PyObject *args, PyObject *kwds) return NULL; } + // Check the updates. + if (updates != Py_None) { + Py_ssize_t size = PyObject_Size(updates); + if (size < 0) { + return NULL; + } + if (size == 0) { + PyErr_SetString(PyExc_ValueError, + "arg 2 must be a non-empty mapping"); + return NULL; + } + } + + _PyXI_session session = {0}; + + // Prep and switch interpreters, including apply the updates. + if (_PyXI_Enter(&session, interp, updates) < 0) { + if (!PyErr_Occurred()) { + _PyXI_ApplyCapturedException(&session); + assert(PyErr_Occurred()); + } + else { + assert(!_PyXI_HasCapturedException(&session)); + } + return NULL; + } + + // Clean up and switch back. + _PyXI_Exit(&session); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(set___main___attrs_doc, +"set___main___attrs(id, ns)\n\ +\n\ +Bind the given attributes in the interpreter's __main__ module."); + +static PyUnicodeObject * +convert_script_arg(PyObject *arg, const char *fname, const char *displayname, + const char *expected) +{ + PyUnicodeObject *str = NULL; + if (PyUnicode_CheckExact(arg)) { + str = (PyUnicodeObject *)Py_NewRef(arg); + } + else if (PyUnicode_Check(arg)) { + // XXX str = PyUnicode_FromObject(arg); + str = (PyUnicodeObject *)Py_NewRef(arg); + } + else { + _PyArg_BadArgument(fname, displayname, expected, arg); + return NULL; + } + + const char *err = check_code_str(str); + if (err != NULL) { + Py_DECREF(str); + PyErr_Format(PyExc_ValueError, + "%.200s(): bad script text (%s)", fname, err); + return NULL; + } + + return str; +} + +static PyCodeObject * +convert_code_arg(PyObject *arg, const char *fname, const char *displayname, + const char *expected) +{ + const char *kind = NULL; + PyCodeObject *code = NULL; + if (PyFunction_Check(arg)) { + if (PyFunction_GetClosure(arg) != NULL) { + PyErr_Format(PyExc_ValueError, + "%.200s(): closures not supported", fname); + return NULL; + } + code = (PyCodeObject *)PyFunction_GetCode(arg); + if (code == NULL) { + if (PyErr_Occurred()) { + // This chains. + PyErr_Format(PyExc_ValueError, + "%.200s(): bad func", fname); + } + else { + PyErr_Format(PyExc_ValueError, + "%.200s(): func.__code__ missing", fname); + } + return NULL; + } + Py_INCREF(code); + kind = "func"; + } + else if (PyCode_Check(arg)) { + code = (PyCodeObject *)Py_NewRef(arg); + kind = "code object"; + } + else { + _PyArg_BadArgument(fname, displayname, expected, arg); + return NULL; + } + + const char *err = check_code_object(code); + if (err != NULL) { + Py_DECREF(code); + PyErr_Format(PyExc_ValueError, + "%.200s(): bad %s (%s)", fname, kind, err); + return NULL; + } + + return code; +} + +static int +_interp_exec(PyObject *self, + PyObject *id_arg, PyObject *code_arg, PyObject *shared_arg, + PyObject **p_excinfo) +{ + // Look up the interpreter. + PyInterpreterState *interp = look_up_interp(id_arg); + if (interp == NULL) { + return -1; + } + // Extract code. - Py_ssize_t size; - const char *codestr = PyUnicode_AsUTF8AndSize(code, &size); + Py_ssize_t codestrlen = -1; + PyObject *bytes_obj = NULL; + int flags = 0; + const char *codestr = get_code_str(code_arg, + &codestrlen, &bytes_obj, &flags); if (codestr == NULL) { + return -1; + } + + // Run the code in the interpreter. + int res = _run_in_interpreter(interp, codestr, codestrlen, + shared_arg, flags, p_excinfo); + Py_XDECREF(bytes_obj); + if (res < 0) { + return -1; + } + + return 0; +} + +static PyObject * +interp_exec(PyObject *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"id", "code", "shared", NULL}; + PyObject *id, *code; + PyObject *shared = NULL; + if (!PyArg_ParseTupleAndKeywords(args, kwds, + "OO|O:" MODULE_NAME ".exec", kwlist, + &id, &code, &shared)) { return NULL; } - if (strlen(codestr) != (size_t)size) { - PyErr_SetString(PyExc_ValueError, - "source code string cannot contain null bytes"); + + const char *expected = "a string, a function, or a code object"; + if (PyUnicode_Check(code)) { + code = (PyObject *)convert_script_arg(code, MODULE_NAME ".exec", + "argument 2", expected); + } + else { + code = (PyObject *)convert_code_arg(code, MODULE_NAME ".exec", + "argument 2", expected); + } + if (code == NULL) { return NULL; } - // Run the code in the interpreter. - if (_run_script_in_interpreter(self, interp, codestr, shared) != 0) { + PyObject *excinfo = NULL; + int res = _interp_exec(self, id, code, shared, &excinfo); + Py_DECREF(code); + if (res < 0) { + assert((excinfo == NULL) != (PyErr_Occurred() == NULL)); + return excinfo; + } + Py_RETURN_NONE; +} + +PyDoc_STRVAR(exec_doc, +"exec(id, code, shared=None)\n\ +\n\ +Execute the provided code in the identified interpreter.\n\ +This is equivalent to running the builtin exec() under the target\n\ +interpreter, using the __dict__ of its __main__ module as both\n\ +globals and locals.\n\ +\n\ +\"code\" may be a string containing the text of a Python script.\n\ +\n\ +Functions (and code objects) are also supported, with some restrictions.\n\ +The code/function must not take any arguments or be a closure\n\ +(i.e. have cell vars). Methods and other callables are not supported.\n\ +\n\ +If a function is provided, its code object is used and all its state\n\ +is ignored, including its __globals__ dict."); + +static PyObject * +interp_run_string(PyObject *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"id", "script", "shared", NULL}; + PyObject *id, *script; + PyObject *shared = NULL; + if (!PyArg_ParseTupleAndKeywords(args, kwds, + "OU|O:" MODULE_NAME ".run_string", kwlist, + &id, &script, &shared)) { + return NULL; + } + + script = (PyObject *)convert_script_arg(script, MODULE_NAME ".exec", + "argument 2", "a string"); + if (script == NULL) { return NULL; } + + PyObject *excinfo = NULL; + int res = _interp_exec(self, id, script, shared, &excinfo); + Py_DECREF(script); + if (res < 0) { + assert((excinfo == NULL) != (PyErr_Occurred() == NULL)); + return excinfo; + } Py_RETURN_NONE; } PyDoc_STRVAR(run_string_doc, -"run_string(id, script, shared)\n\ +"run_string(id, script, shared=None)\n\ \n\ Execute the provided string in the identified interpreter.\n\ \n\ -See PyRun_SimpleStrings."); +(See " MODULE_NAME ".exec()."); + +static PyObject * +interp_run_func(PyObject *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"id", "func", "shared", NULL}; + PyObject *id, *func; + PyObject *shared = NULL; + if (!PyArg_ParseTupleAndKeywords(args, kwds, + "OO|O:" MODULE_NAME ".run_func", kwlist, + &id, &func, &shared)) { + return NULL; + } + + PyCodeObject *code = convert_code_arg(func, MODULE_NAME ".exec", + "argument 2", + "a function or a code object"); + if (code == NULL) { + return NULL; + } + + PyObject *excinfo = NULL; + int res = _interp_exec(self, id, (PyObject *)code, shared, &excinfo); + Py_DECREF(code); + if (res < 0) { + assert((excinfo == NULL) != (PyErr_Occurred() == NULL)); + return excinfo; + } + Py_RETURN_NONE; +} + +PyDoc_STRVAR(run_func_doc, +"run_func(id, func, shared=None)\n\ +\n\ +Execute the body of the provided function in the identified interpreter.\n\ +Code objects are also supported. In both cases, closures and args\n\ +are not supported. Methods and other callables are not supported either.\n\ +\n\ +(See " MODULE_NAME ".exec()."); static PyObject * @@ -745,15 +1009,11 @@ interp_is_running(PyObject *self, PyObject *args, PyObject *kwds) return NULL; } - PyInterpreterState *interp = PyInterpreterID_LookUp(id); + PyInterpreterState *interp = look_up_interp(id); if (interp == NULL) { return NULL; } - int is_running = _is_running(interp); - if (is_running < 0) { - return NULL; - } - if (is_running) { + if (_PyInterpreterState_IsRunningMain(interp)) { Py_RETURN_TRUE; } Py_RETURN_FALSE; @@ -764,6 +1024,50 @@ PyDoc_STRVAR(is_running_doc, \n\ Return whether or not the identified interpreter is running."); + +static PyObject * +interp_incref(PyObject *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"id", NULL}; + PyObject *id; + if (!PyArg_ParseTupleAndKeywords(args, kwds, + "O:_incref", kwlist, &id)) { + return NULL; + } + + PyInterpreterState *interp = look_up_interp(id); + if (interp == NULL) { + return NULL; + } + if (_PyInterpreterState_IDInitref(interp) < 0) { + return NULL; + } + _PyInterpreterState_IDIncref(interp); + + Py_RETURN_NONE; +} + + +static PyObject * +interp_decref(PyObject *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"id", NULL}; + PyObject *id; + if (!PyArg_ParseTupleAndKeywords(args, kwds, + "O:_incref", kwlist, &id)) { + return NULL; + } + + PyInterpreterState *interp = look_up_interp(id); + if (interp == NULL) { + return NULL; + } + _PyInterpreterState_IDDecref(interp); + + Py_RETURN_NONE; +} + + static PyMethodDef module_functions[] = { {"create", _PyCFunction_CAST(interp_create), METH_VARARGS | METH_KEYWORDS, create_doc}, @@ -778,12 +1082,23 @@ static PyMethodDef module_functions[] = { {"is_running", _PyCFunction_CAST(interp_is_running), METH_VARARGS | METH_KEYWORDS, is_running_doc}, + {"exec", _PyCFunction_CAST(interp_exec), + METH_VARARGS | METH_KEYWORDS, exec_doc}, {"run_string", _PyCFunction_CAST(interp_run_string), METH_VARARGS | METH_KEYWORDS, run_string_doc}, + {"run_func", _PyCFunction_CAST(interp_run_func), + METH_VARARGS | METH_KEYWORDS, run_func_doc}, + {"set___main___attrs", _PyCFunction_CAST(interp_set___main___attrs), + METH_VARARGS, set___main___attrs_doc}, {"is_shareable", _PyCFunction_CAST(object_is_shareable), METH_VARARGS | METH_KEYWORDS, is_shareable_doc}, + {"_incref", _PyCFunction_CAST(interp_incref), + METH_VARARGS | METH_KEYWORDS, NULL}, + {"_decref", _PyCFunction_CAST(interp_decref), + METH_VARARGS | METH_KEYWORDS, NULL}, + {NULL, NULL} /* sentinel */ }; @@ -797,13 +1112,17 @@ The 'interpreters' module provides a more convenient interface."); static int module_exec(PyObject *mod) { - /* Add exception types */ - if (exceptions_init(mod) != 0) { + module_state *state = get_module_state(mod); + + // exceptions + if (PyModule_AddType(mod, (PyTypeObject *)PyExc_InterpreterError) < 0) { + goto error; + } + if (PyModule_AddType(mod, (PyTypeObject *)PyExc_InterpreterNotFoundError) < 0) { goto error; } - // PyInterpreterID - if (PyModule_AddType(mod, &PyInterpreterID_Type) < 0) { + if (register_memoryview_xid(mod, &state->XIBufferViewType) < 0) { goto error; } diff --git a/Modules/_xxtestfuzz/README.rst b/Modules/_xxtestfuzz/README.rst index 42bd02a03cbedd..b951858458c82f 100644 --- a/Modules/_xxtestfuzz/README.rst +++ b/Modules/_xxtestfuzz/README.rst @@ -13,6 +13,9 @@ oss-fuzz will regularly pull from CPython, discover all the tests in automatically be run in oss-fuzz, while also being smoke-tested as part of CPython's test suite. +In addition, the tests are run on GitHub Actions using CIFuzz for PRs to the +main branch changing relevant files. + Adding a new fuzz test ---------------------- diff --git a/Modules/_xxtestfuzz/dictionaries/fuzz_elementtree_parsewhole.dict b/Modules/_xxtestfuzz/dictionaries/fuzz_elementtree_parsewhole.dict new file mode 100644 index 00000000000000..e1b58cdb248238 --- /dev/null +++ b/Modules/_xxtestfuzz/dictionaries/fuzz_elementtree_parsewhole.dict @@ -0,0 +1,134 @@ +tok_1="<" +tok_2=">" +tok_3="/" +tok_4="" +tok_6="" +tok_7="version" +tok_8="encoding" +tok_9="UTF-8" +tok_9a="UTF-16" +tok_9b="ASCII" +tok_9c="LATIN-1" +tok_9d="UTF-32" +tok_9e="UTF-7" +tok_10="\"" +tok_11="&" +tok_11a="&#" +tok_11b=";" +tok_12="'" +tok_13="" +tok_14="" +tag_doctype="" +tag_open_close="" +tag_open_exclamation="" +tag_xml_q="" + +encoding_utf="UTF-" +encoding_iso1="ISO-8859" +encoding_iso3="ISO-10646-UCS" +encoding_iso5="ISO-LATIN-1" +encoding_jis="SHIFT_JIS" +encoding_utf7="UTF-7" +encoding_utf16le="UTF-16BE" +encoding_utf16le="UTF-16LE" +encoding_ascii="US-ASCII" +encoding_latin1="latin1" diff --git a/Modules/_xxtestfuzz/dictionaries/fuzz_pycompile.dict b/Modules/_xxtestfuzz/dictionaries/fuzz_pycompile.dict new file mode 100644 index 00000000000000..c6a44d946284ef --- /dev/null +++ b/Modules/_xxtestfuzz/dictionaries/fuzz_pycompile.dict @@ -0,0 +1,165 @@ +# bits of syntax +"( " +") " +"[ " +"] " +": " +", " +"; " +"{ " +"} " + +# operators +"+ " +"- " +"* " +"** " +"/ " +"// " +"| " +"& " +"< " +"> " +"= " +". " +"% " +"` " +"^ " +"~ " +"@ " +"== " +"!= " +"<> " +"<< " +"<= " +">= " +">> " +"+= " +"-= " +"*= " +"** " +"/= " +"//= " +"|= " +"%= " +"&= " +"^= " +"<<= " +">>= " +"**= " +":= " +"@= " + +# whitespace +" " +":\\n " + +# type signatures and functions +"-> " +": List[int]" +": Dict[int, str]" + +"# type:" +"# type: List[int]" +"# type: Dict[int, str]" + +", *" +", /" +", *args" +", **kwargs" +", x=42" + + +# literals +"0x0a" +"0b0000" +"42" +"0o70" +"42j" +"42.01" +"-5" +"+42e-3" +"0_0_0" +"1e1_0" +".1_4" + +"{}" + +# variable names +"x" +"y" + +# strings +"r'x'" + +"b'x'" + +"rb\"x\"" + +"br\"x\"" + +"f'{x + 5}'" +"f\"{x + 5}\"" + +"'''" +"\"\"\"" + +"\\u" +"\\x" + +# keywords +"def " +"del " +"pass " +"break " +"continue " +"return " +"raise " +"from " +"import " +".. " +"... " +"__future__ " +"as " +"global " +"nonlocal " +"assert " +"print " +"if " +"elif " +"else: " +"while " +"try: " +"except " +"finally: " +"with " +"lambda " +"or " +"and " +"not " +"None " +"__peg_parser__" +"True " +"False " +"yield " +"async " +"await " +"for " +"in " +"is " +"class " + +# shebangs and encodings +"#!" +"# coding:" +"# coding=" +"# coding: latin-1" +"# coding=latin-1" +"# coding: utf-8" +"# coding=utf-8" +"# coding: ascii" +"# coding=ascii" +"# coding: cp860" +"# coding=cp860" +"# coding: gbk" +"# coding=gbk" diff --git a/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/c14nComment.xml b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/c14nComment.xml new file mode 100644 index 00000000000000..e95aa302d04fdb --- /dev/null +++ b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/c14nComment.xml @@ -0,0 +1,4 @@ + + true + + diff --git a/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/c14nDefault.xml b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/c14nDefault.xml new file mode 100644 index 00000000000000..c1364142cc59bf --- /dev/null +++ b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/c14nDefault.xml @@ -0,0 +1,3 @@ + + + diff --git a/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/c14nPrefix.xml b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/c14nPrefix.xml new file mode 100644 index 00000000000000..fb233b42b1334f --- /dev/null +++ b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/c14nPrefix.xml @@ -0,0 +1,4 @@ + + sequential + + diff --git a/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/c14nPrefixQname.xml b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/c14nPrefixQname.xml new file mode 100644 index 00000000000000..23188eedbc2451 --- /dev/null +++ b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/c14nPrefixQname.xml @@ -0,0 +1,7 @@ + + sequential + + + + + diff --git a/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/c14nPrefixQnameXpathElem.xml b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/c14nPrefixQnameXpathElem.xml new file mode 100644 index 00000000000000..626fc48f410fa0 --- /dev/null +++ b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/c14nPrefixQnameXpathElem.xml @@ -0,0 +1,8 @@ + + sequential + + + + + + diff --git a/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/c14nQname.xml b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/c14nQname.xml new file mode 100644 index 00000000000000..919e5903f5ce6e --- /dev/null +++ b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/c14nQname.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/c14nQnameElem.xml b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/c14nQnameElem.xml new file mode 100644 index 00000000000000..0321f8061952e6 --- /dev/null +++ b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/c14nQnameElem.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/c14nQnameXpathElem.xml b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/c14nQnameXpathElem.xml new file mode 100644 index 00000000000000..c4890bc8b01d5e --- /dev/null +++ b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/c14nQnameXpathElem.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/c14nTrim.xml b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/c14nTrim.xml new file mode 100644 index 00000000000000..ccb9cf65db7235 --- /dev/null +++ b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/c14nTrim.xml @@ -0,0 +1,4 @@ + + true + + diff --git a/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/expat224_utf8_bug.xml b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/expat224_utf8_bug.xml new file mode 100644 index 00000000000000..d66a8e6b50f93b --- /dev/null +++ b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/expat224_utf8_bug.xml @@ -0,0 +1,2 @@ + diff --git a/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/inC14N1.xml b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/inC14N1.xml new file mode 100644 index 00000000000000..ed450c7341d382 --- /dev/null +++ b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/inC14N1.xml @@ -0,0 +1,14 @@ + + + + + + +Hello, world! + + + + + + diff --git a/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/inC14N2.xml b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/inC14N2.xml new file mode 100644 index 00000000000000..74eeea147c3791 --- /dev/null +++ b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/inC14N2.xml @@ -0,0 +1,11 @@ + + + A B + + A + + B + A B + C + + diff --git a/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/inC14N3.xml b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/inC14N3.xml new file mode 100644 index 00000000000000..fea78213f1ae69 --- /dev/null +++ b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/inC14N3.xml @@ -0,0 +1,18 @@ +]> + + + + + + + + + + + + + + diff --git a/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/inC14N4.xml b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/inC14N4.xml new file mode 100644 index 00000000000000..909a847435b86c --- /dev/null +++ b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/inC14N4.xml @@ -0,0 +1,13 @@ + + +]> + + First line Second line + 2 + "0" && value<"10" ?"valid":"error"]]> + valid + + + + diff --git a/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/inC14N5.xml b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/inC14N5.xml new file mode 100644 index 00000000000000..501161bad5187f --- /dev/null +++ b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/inC14N5.xml @@ -0,0 +1,12 @@ + + + + + +]> + + &ent1;, &ent2;! + + + diff --git a/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/inC14N6.xml b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/inC14N6.xml new file mode 100644 index 00000000000000..31e2071867257c --- /dev/null +++ b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/inC14N6.xml @@ -0,0 +1,2 @@ + +© diff --git a/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/inNsContent.xml b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/inNsContent.xml new file mode 100644 index 00000000000000..b9924660ba6da3 --- /dev/null +++ b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/inNsContent.xml @@ -0,0 +1,4 @@ + + xsd:string + /soap-env:body/child::b:foo[@att1 != "c:val" and @att2 != 'xsd:string'] + diff --git a/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/inNsDefault.xml b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/inNsDefault.xml new file mode 100644 index 00000000000000..3e0d323bad27c2 --- /dev/null +++ b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/inNsDefault.xml @@ -0,0 +1,3 @@ + + + diff --git a/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/inNsPushdown.xml b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/inNsPushdown.xml new file mode 100644 index 00000000000000..daa67d83f15914 --- /dev/null +++ b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/inNsPushdown.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/inNsRedecl.xml b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/inNsRedecl.xml new file mode 100644 index 00000000000000..10bd97beda3baa --- /dev/null +++ b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/inNsRedecl.xml @@ -0,0 +1,3 @@ + + + diff --git a/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/inNsSort.xml b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/inNsSort.xml new file mode 100644 index 00000000000000..8e9fc01c647b24 --- /dev/null +++ b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/inNsSort.xml @@ -0,0 +1,4 @@ + + + + diff --git a/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/inNsSuperfluous.xml b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/inNsSuperfluous.xml new file mode 100644 index 00000000000000..f77720f7b0b09d --- /dev/null +++ b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/inNsSuperfluous.xml @@ -0,0 +1,4 @@ + + + + diff --git a/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/inNsXml.xml b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/inNsXml.xml new file mode 100644 index 00000000000000..7520cf3fb9eb28 --- /dev/null +++ b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/inNsXml.xml @@ -0,0 +1,3 @@ + + data + diff --git a/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inC14N1_c14nComment.xml b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inC14N1_c14nComment.xml new file mode 100644 index 00000000000000..d98d16840c6bcc --- /dev/null +++ b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inC14N1_c14nComment.xml @@ -0,0 +1,6 @@ + +Hello, world! + + + \ No newline at end of file diff --git a/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inC14N1_c14nDefault.xml b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inC14N1_c14nDefault.xml new file mode 100644 index 00000000000000..af9a9770578e9d --- /dev/null +++ b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inC14N1_c14nDefault.xml @@ -0,0 +1,4 @@ + +Hello, world! + \ No newline at end of file diff --git a/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inC14N2_c14nDefault.xml b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inC14N2_c14nDefault.xml new file mode 100644 index 00000000000000..2afa15ccb36382 --- /dev/null +++ b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inC14N2_c14nDefault.xml @@ -0,0 +1,11 @@ + + + A B + + A + + B + A B + C + + \ No newline at end of file diff --git a/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inC14N2_c14nTrim.xml b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inC14N2_c14nTrim.xml new file mode 100644 index 00000000000000..7a1dc32946bce3 --- /dev/null +++ b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inC14N2_c14nTrim.xml @@ -0,0 +1 @@ +A BABA BC \ No newline at end of file diff --git a/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inC14N3_c14nDefault.xml b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inC14N3_c14nDefault.xml new file mode 100644 index 00000000000000..662e108aa8a1e4 --- /dev/null +++ b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inC14N3_c14nDefault.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inC14N3_c14nPrefix.xml b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inC14N3_c14nPrefix.xml new file mode 100644 index 00000000000000..041e1ec8ebe59a --- /dev/null +++ b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inC14N3_c14nPrefix.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inC14N3_c14nTrim.xml b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inC14N3_c14nTrim.xml new file mode 100644 index 00000000000000..4f35ad9662df3b --- /dev/null +++ b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inC14N3_c14nTrim.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inC14N4_c14nDefault.xml b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inC14N4_c14nDefault.xml new file mode 100644 index 00000000000000..243d0e61f2e94f --- /dev/null +++ b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inC14N4_c14nDefault.xml @@ -0,0 +1,10 @@ + + First line +Second line + 2 + value>"0" && value<"10" ?"valid":"error" + valid + + + + \ No newline at end of file diff --git a/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inC14N4_c14nTrim.xml b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inC14N4_c14nTrim.xml new file mode 100644 index 00000000000000..24d83ba8ab0012 --- /dev/null +++ b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inC14N4_c14nTrim.xml @@ -0,0 +1,2 @@ +First line +Second line2value>"0" && value<"10" ?"valid":"error"valid \ No newline at end of file diff --git a/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inC14N5_c14nDefault.xml b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inC14N5_c14nDefault.xml new file mode 100644 index 00000000000000..c232e740aee4a7 --- /dev/null +++ b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inC14N5_c14nDefault.xml @@ -0,0 +1,3 @@ + + Hello, world! + \ No newline at end of file diff --git a/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inC14N5_c14nTrim.xml b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inC14N5_c14nTrim.xml new file mode 100644 index 00000000000000..3fa84b1e986014 --- /dev/null +++ b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inC14N5_c14nTrim.xml @@ -0,0 +1 @@ +Hello, world! \ No newline at end of file diff --git a/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inC14N6_c14nDefault.xml b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inC14N6_c14nDefault.xml new file mode 100644 index 00000000000000..0be38f98cb1398 --- /dev/null +++ b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inC14N6_c14nDefault.xml @@ -0,0 +1 @@ +© \ No newline at end of file diff --git a/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inNsContent_c14nDefault.xml b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inNsContent_c14nDefault.xml new file mode 100644 index 00000000000000..62d7e004a44034 --- /dev/null +++ b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inNsContent_c14nDefault.xml @@ -0,0 +1,4 @@ + + xsd:string + /soap-env:body/child::b:foo[@att1 != "c:val" and @att2 != 'xsd:string'] + \ No newline at end of file diff --git a/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inNsContent_c14nPrefixQnameXpathElem.xml b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inNsContent_c14nPrefixQnameXpathElem.xml new file mode 100644 index 00000000000000..20e1c2e9d6dfb4 --- /dev/null +++ b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inNsContent_c14nPrefixQnameXpathElem.xml @@ -0,0 +1,4 @@ + + n1:string + /n3:body/child::n2:foo[@att1 != "c:val" and @att2 != 'xsd:string'] + \ No newline at end of file diff --git a/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inNsContent_c14nQnameElem.xml b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inNsContent_c14nQnameElem.xml new file mode 100644 index 00000000000000..db8680daa033d7 --- /dev/null +++ b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inNsContent_c14nQnameElem.xml @@ -0,0 +1,4 @@ + + xsd:string + /soap-env:body/child::b:foo[@att1 != "c:val" and @att2 != 'xsd:string'] + \ No newline at end of file diff --git a/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inNsContent_c14nQnameXpathElem.xml b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inNsContent_c14nQnameXpathElem.xml new file mode 100644 index 00000000000000..df3b21579fac5e --- /dev/null +++ b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inNsContent_c14nQnameXpathElem.xml @@ -0,0 +1,4 @@ + + xsd:string + /soap-env:body/child::b:foo[@att1 != "c:val" and @att2 != 'xsd:string'] + \ No newline at end of file diff --git a/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inNsDefault_c14nDefault.xml b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inNsDefault_c14nDefault.xml new file mode 100644 index 00000000000000..674b076dd6d9a6 --- /dev/null +++ b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inNsDefault_c14nDefault.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inNsDefault_c14nPrefix.xml b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inNsDefault_c14nPrefix.xml new file mode 100644 index 00000000000000..83edaae91e7423 --- /dev/null +++ b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inNsDefault_c14nPrefix.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inNsPushdown_c14nDefault.xml b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inNsPushdown_c14nDefault.xml new file mode 100644 index 00000000000000..fa4f21b5d0af55 --- /dev/null +++ b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inNsPushdown_c14nDefault.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inNsPushdown_c14nPrefix.xml b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inNsPushdown_c14nPrefix.xml new file mode 100644 index 00000000000000..6d579200c9dc8c --- /dev/null +++ b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inNsPushdown_c14nPrefix.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inNsRedecl_c14nDefault.xml b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inNsRedecl_c14nDefault.xml new file mode 100644 index 00000000000000..ba37f925103c70 --- /dev/null +++ b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inNsRedecl_c14nDefault.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inNsRedecl_c14nPrefix.xml b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inNsRedecl_c14nPrefix.xml new file mode 100644 index 00000000000000..af3bb2d6f062cd --- /dev/null +++ b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inNsRedecl_c14nPrefix.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inNsSort_c14nDefault.xml b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inNsSort_c14nDefault.xml new file mode 100644 index 00000000000000..8a92c5c61c2c2c --- /dev/null +++ b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inNsSort_c14nDefault.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inNsSort_c14nPrefix.xml b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inNsSort_c14nPrefix.xml new file mode 100644 index 00000000000000..8d44c84fe5d307 --- /dev/null +++ b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inNsSort_c14nPrefix.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inNsSuperfluous_c14nDefault.xml b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inNsSuperfluous_c14nDefault.xml new file mode 100644 index 00000000000000..6bb862d763d737 --- /dev/null +++ b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inNsSuperfluous_c14nDefault.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inNsSuperfluous_c14nPrefix.xml b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inNsSuperfluous_c14nPrefix.xml new file mode 100644 index 00000000000000..700a16d42a7746 --- /dev/null +++ b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inNsSuperfluous_c14nPrefix.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inNsXml_c14nDefault.xml b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inNsXml_c14nDefault.xml new file mode 100644 index 00000000000000..1689f3bf423dc5 --- /dev/null +++ b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inNsXml_c14nDefault.xml @@ -0,0 +1,3 @@ + + data + \ No newline at end of file diff --git a/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inNsXml_c14nPrefix.xml b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inNsXml_c14nPrefix.xml new file mode 100644 index 00000000000000..38508a47f6b904 --- /dev/null +++ b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inNsXml_c14nPrefix.xml @@ -0,0 +1,3 @@ + + data + \ No newline at end of file diff --git a/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inNsXml_c14nPrefixQname.xml b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inNsXml_c14nPrefixQname.xml new file mode 100644 index 00000000000000..867980f82bfa59 --- /dev/null +++ b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inNsXml_c14nPrefixQname.xml @@ -0,0 +1,3 @@ + + data + \ No newline at end of file diff --git a/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inNsXml_c14nQname.xml b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inNsXml_c14nQname.xml new file mode 100644 index 00000000000000..0300f9d562db30 --- /dev/null +++ b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/out_inNsXml_c14nQname.xml @@ -0,0 +1,3 @@ + + data + \ No newline at end of file diff --git a/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/simple-ns.xml b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/simple-ns.xml new file mode 100644 index 00000000000000..f1f34b2e29c73e --- /dev/null +++ b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/simple-ns.xml @@ -0,0 +1,7 @@ + + + + text + texttail + + diff --git a/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/simple.xml b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/simple.xml new file mode 100644 index 00000000000000..b88c2c7e69a088 --- /dev/null +++ b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/simple.xml @@ -0,0 +1,6 @@ + + + text + texttail + + diff --git a/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/test.xml b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/test.xml new file mode 100644 index 00000000000000..92136da76d3581 --- /dev/null +++ b/Modules/_xxtestfuzz/fuzz_elementtree_parsewhole_corpus/test.xml @@ -0,0 +1,115 @@ + + +Introduction to XSL +

Introduction to XSL

+ + + +
+

Overview +

+
    + +
  • 1.Intro
  • + +
  • 2.History
  • + +
  • 3.XSL Basics
  • + +
  • Lunch
  • + +
  • 4.An XML Data Model
  • + +
  • 5.XSL Patterns
  • + +
  • 6.XSL Templates
  • + +
  • 7.XSL Formatting Model +
  • + +
+ + + + + + +
+

Intro

+
    + +
  • Who am I?
  • + +
  • Who are you?
  • + +
  • Why are we here? +
  • + +
+ + + + + + +
+

History: XML and SGML

+
    + +
  • XML is a subset of SGML.
  • + +
  • SGML allows the separation of abstract content from formatting.
  • + +
  • Also one of XML's primary virtues (in the doc publishing domain). +
  • + +
+ + + + + + +
+

History: What are stylesheets?

+
    + +
  • Stylesheets specify the formatting of SGML/XML documents.
  • + +
  • Stylesheets put the "style" back into documents.
  • + +
  • New York Times content+NYT Stylesheet = NYT paper +
  • + +
+ + + + + + +
+

History: FOSI

+
    + +
  • FOSI: "Formatted Output Specification Instance" +
      +
    • MIL-STD-28001 +
    • + +
    • FOSI's are SGML documents +
    • + +
    • A stylesheet for another document +
    • +
  • + +
  • Obsolete but implemented... +
  • + +
+ + +µ + + diff --git a/Modules/_xxtestfuzz/fuzz_pycompile_corpus/input1.py b/Modules/_xxtestfuzz/fuzz_pycompile_corpus/input1.py new file mode 100644 index 00000000000000..c43994dda29eed --- /dev/null +++ b/Modules/_xxtestfuzz/fuzz_pycompile_corpus/input1.py @@ -0,0 +1,7 @@ +from __future__ import annotations + +def test() -> None: + x: list[int] = [] + x: dict[int, str] = {} + x: set[bytes] = {} + print(5 + 42 * 3, x) diff --git a/Modules/_xxtestfuzz/fuzz_pycompile_corpus/input2.py b/Modules/_xxtestfuzz/fuzz_pycompile_corpus/input2.py new file mode 100644 index 00000000000000..7be326e95be0eb --- /dev/null +++ b/Modules/_xxtestfuzz/fuzz_pycompile_corpus/input2.py @@ -0,0 +1,5 @@ +class Foo(metaclass=42): + __slots__ = ['x'] + pass + +foo = Foo() diff --git a/Modules/_xxtestfuzz/fuzz_pycompile_corpus/input3.py b/Modules/_xxtestfuzz/fuzz_pycompile_corpus/input3.py new file mode 100644 index 00000000000000..9bc3a45ebe75da --- /dev/null +++ b/Modules/_xxtestfuzz/fuzz_pycompile_corpus/input3.py @@ -0,0 +1,6 @@ +def evens(): + i = 0 + while True: + i += 1 + if i % 2 == 0: + yield i diff --git a/Modules/_xxtestfuzz/fuzz_pycompile_corpus/input4.py b/Modules/_xxtestfuzz/fuzz_pycompile_corpus/input4.py new file mode 100644 index 00000000000000..490de90fb97b39 --- /dev/null +++ b/Modules/_xxtestfuzz/fuzz_pycompile_corpus/input4.py @@ -0,0 +1,3 @@ +async def hello(name: str): + await name + print(name) diff --git a/Modules/_xxtestfuzz/fuzz_pycompile_corpus/input5.py b/Modules/_xxtestfuzz/fuzz_pycompile_corpus/input5.py new file mode 100644 index 00000000000000..4cfcfe590ebc95 --- /dev/null +++ b/Modules/_xxtestfuzz/fuzz_pycompile_corpus/input5.py @@ -0,0 +1,7 @@ +try: + eval('importer exporter... really long matches') +except SyntaxError: + print("nothing to see here") +finally: + print("all done here") + raise diff --git a/Modules/_xxtestfuzz/fuzz_pycompile_corpus/input6.py b/Modules/_xxtestfuzz/fuzz_pycompile_corpus/input6.py new file mode 100644 index 00000000000000..d8e59ade503a8c --- /dev/null +++ b/Modules/_xxtestfuzz/fuzz_pycompile_corpus/input6.py @@ -0,0 +1,8 @@ +"""Some module docstring""" +import sys + +def main(): + print("Hello world!", file=sys.stderr) + +if __name__ == '__main__': + main() diff --git a/Modules/_xxtestfuzz/fuzz_tests.txt b/Modules/_xxtestfuzz/fuzz_tests.txt index 4e046ecf6d898c..ea6f982eefc9da 100644 --- a/Modules/_xxtestfuzz/fuzz_tests.txt +++ b/Modules/_xxtestfuzz/fuzz_tests.txt @@ -7,3 +7,5 @@ fuzz_sre_match fuzz_csv_reader fuzz_struct_unpack fuzz_ast_literal_eval +fuzz_elementtree_parsewhole +fuzz_pycompile diff --git a/Modules/_xxtestfuzz/fuzzer.c b/Modules/_xxtestfuzz/fuzzer.c index 54f8a42273401f..e133b4d3c44480 100644 --- a/Modules/_xxtestfuzz/fuzzer.c +++ b/Modules/_xxtestfuzz/fuzzer.c @@ -193,37 +193,33 @@ static int fuzz_json_loads(const char* data, size_t size) { #define MAX_RE_TEST_SIZE 0x10000 -PyObject* sre_compile_method = NULL; -PyObject* sre_error_exception = NULL; -int SRE_FLAG_DEBUG = 0; +PyObject* re_compile_method = NULL; +PyObject* re_error_exception = NULL; +int RE_FLAG_DEBUG = 0; /* Called by LLVMFuzzerTestOneInput for initialization */ static int init_sre_compile(void) { /* Import sre_compile.compile and sre.error */ - PyObject* sre_compile_module = PyImport_ImportModule("sre_compile"); - if (sre_compile_module == NULL) { + PyObject* re_module = PyImport_ImportModule("re"); + if (re_module == NULL) { return 0; } - sre_compile_method = PyObject_GetAttrString(sre_compile_module, "compile"); - if (sre_compile_method == NULL) { + re_compile_method = PyObject_GetAttrString(re_module, "compile"); + if (re_compile_method == NULL) { return 0; } - PyObject* sre_constants = PyImport_ImportModule("sre_constants"); - if (sre_constants == NULL) { + re_error_exception = PyObject_GetAttrString(re_module, "error"); + if (re_error_exception == NULL) { return 0; } - sre_error_exception = PyObject_GetAttrString(sre_constants, "error"); - if (sre_error_exception == NULL) { - return 0; - } - PyObject* debug_flag = PyObject_GetAttrString(sre_constants, "SRE_FLAG_DEBUG"); + PyObject* debug_flag = PyObject_GetAttrString(re_module, "DEBUG"); if (debug_flag == NULL) { return 0; } - SRE_FLAG_DEBUG = PyLong_AsLong(debug_flag); + RE_FLAG_DEBUG = PyLong_AsLong(debug_flag); return 1; } -/* Fuzz _sre.compile(x) */ +/* Fuzz re.compile(x) */ static int fuzz_sre_compile(const char* data, size_t size) { /* Ignore really long regex patterns that will timeout the fuzzer */ if (size > MAX_RE_TEST_SIZE) { @@ -236,7 +232,7 @@ static int fuzz_sre_compile(const char* data, size_t size) { uint16_t flags = ((uint16_t*) data)[0]; /* We remove the SRE_FLAG_DEBUG if present. This is because it prints to stdout which greatly decreases fuzzing speed */ - flags &= ~SRE_FLAG_DEBUG; + flags &= ~RE_FLAG_DEBUG; /* Pull the pattern from the remaining bytes */ PyObject* pattern_bytes = PyBytes_FromStringAndSize(data + 2, size - 2); @@ -249,9 +245,9 @@ static int fuzz_sre_compile(const char* data, size_t size) { return 0; } - /* compiled = _sre.compile(data[2:], data[0:2] */ + /* compiled = re.compile(data[2:], data[0:2] */ PyObject* compiled = PyObject_CallFunctionObjArgs( - sre_compile_method, pattern_bytes, flags_obj, NULL); + re_compile_method, pattern_bytes, flags_obj, NULL); /* Ignore ValueError as the fuzzer will more than likely generate some invalid combination of flags */ if (compiled == NULL && PyErr_ExceptionMatches(PyExc_ValueError)) { @@ -267,7 +263,7 @@ static int fuzz_sre_compile(const char* data, size_t size) { PyErr_Clear(); } /* Ignore re.error */ - if (compiled == NULL && PyErr_ExceptionMatches(sre_error_exception)) { + if (compiled == NULL && PyErr_ExceptionMatches(re_error_exception)) { PyErr_Clear(); } @@ -443,6 +439,125 @@ static int fuzz_ast_literal_eval(const char* data, size_t size) { return 0; } +#define MAX_ELEMENTTREE_PARSEWHOLE_TEST_SIZE 0x100000 +PyObject* xmlparser_type = NULL; +PyObject* bytesio_type = NULL; +/* Called by LLVMFuzzerTestOneInput for initialization */ +static int init_elementtree_parsewhole(void) { + PyObject* elementtree_module = PyImport_ImportModule("_elementtree"); + if (elementtree_module == NULL) { + return 0; + } + xmlparser_type = PyObject_GetAttrString(elementtree_module, "XMLParser"); + Py_DECREF(elementtree_module); + if (xmlparser_type == NULL) { + return 0; + } + + + PyObject* io_module = PyImport_ImportModule("io"); + if (io_module == NULL) { + return 0; + } + bytesio_type = PyObject_GetAttrString(io_module, "BytesIO"); + Py_DECREF(io_module); + if (bytesio_type == NULL) { + return 0; + } + + return 1; +} +/* Fuzz _elementtree.XMLParser._parse_whole(x) */ +static int fuzz_elementtree_parsewhole(const char* data, size_t size) { + if (size > MAX_ELEMENTTREE_PARSEWHOLE_TEST_SIZE) { + return 0; + } + + PyObject *input = PyObject_CallFunction(bytesio_type, "y#", data, (Py_ssize_t)size); + if (input == NULL) { + assert(PyErr_Occurred()); + PyErr_Print(); + abort(); + } + + PyObject *xmlparser_instance = PyObject_CallObject(xmlparser_type, NULL); + if (xmlparser_instance == NULL) { + assert(PyErr_Occurred()); + PyErr_Print(); + abort(); + } + + PyObject *result = PyObject_CallMethod(xmlparser_instance, "_parse_whole", "O", input); + if (result == NULL) { + /* Ignore exception here, which can be caused by invalid XML input */ + PyErr_Clear(); + } else { + Py_DECREF(result); + } + + Py_DECREF(xmlparser_instance); + Py_DECREF(input); + + return 0; +} + +#define MAX_PYCOMPILE_TEST_SIZE 16384 +static char pycompile_scratch[MAX_PYCOMPILE_TEST_SIZE]; + +static const int start_vals[] = {Py_eval_input, Py_single_input, Py_file_input}; +const size_t NUM_START_VALS = sizeof(start_vals) / sizeof(start_vals[0]); + +static const int optimize_vals[] = {-1, 0, 1, 2}; +const size_t NUM_OPTIMIZE_VALS = sizeof(optimize_vals) / sizeof(optimize_vals[0]); + +/* Fuzz `PyCompileStringExFlags` using a variety of input parameters. + * That function is essentially behind the `compile` builtin */ +static int fuzz_pycompile(const char* data, size_t size) { + // Ignore overly-large inputs, and account for a NUL terminator + if (size > MAX_PYCOMPILE_TEST_SIZE - 1) { + return 0; + } + + // Need 2 bytes for parameter selection + if (size < 2) { + return 0; + } + + // Use first byte to determine element of `start_vals` to use + unsigned char start_idx = (unsigned char) data[0]; + int start = start_vals[start_idx % NUM_START_VALS]; + + // Use second byte to determine element of `optimize_vals` to use + unsigned char optimize_idx = (unsigned char) data[1]; + int optimize = optimize_vals[optimize_idx % NUM_OPTIMIZE_VALS]; + + // Create a NUL-terminated C string from the remaining input + memcpy(pycompile_scratch, data + 2, size - 2); + // Put a NUL terminator just after the copied data. (Space was reserved already.) + pycompile_scratch[size - 2] = '\0'; + + // XXX: instead of always using NULL for the `flags` value to + // `Py_CompileStringExFlags`, there are many flags that conditionally + // change parser behavior: + // + // #define PyCF_TYPE_COMMENTS 0x1000 + // #define PyCF_ALLOW_TOP_LEVEL_AWAIT 0x2000 + // #define PyCF_ONLY_AST 0x0400 + // + // It would be good to test various combinations of these, too. + PyCompilerFlags *flags = NULL; + + PyObject *result = Py_CompileStringExFlags(pycompile_scratch, "", start, flags, optimize); + if (result == NULL) { + /* compilation failed, most likely from a syntax error */ + PyErr_Clear(); + } else { + Py_DECREF(result); + } + + return 0; +} + /* Run fuzzer and abort on failure. */ static int _run_fuzz(const uint8_t *data, size_t size, int(*fuzzer)(const char* , size_t)) { int rv = fuzzer((const char*) data, size); @@ -531,13 +646,8 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { #if !defined(_Py_FUZZ_ONE) || defined(_Py_FUZZ_fuzz_sre_compile) static int SRE_COMPILE_INITIALIZED = 0; if (!SRE_COMPILE_INITIALIZED && !init_sre_compile()) { - if (!PyErr_ExceptionMatches(PyExc_DeprecationWarning)) { - PyErr_Print(); - abort(); - } - else { - PyErr_Clear(); - } + PyErr_Print(); + abort(); } else { SRE_COMPILE_INITIALIZED = 1; } @@ -578,6 +688,20 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { } rv |= _run_fuzz(data, size, fuzz_ast_literal_eval); +#endif +#if !defined(_Py_FUZZ_ONE) || defined(_Py_FUZZ_fuzz_elementtree_parsewhole) + static int ELEMENTTREE_PARSEWHOLE_INITIALIZED = 0; + if (!ELEMENTTREE_PARSEWHOLE_INITIALIZED && !init_elementtree_parsewhole()) { + PyErr_Print(); + abort(); + } else { + ELEMENTTREE_PARSEWHOLE_INITIALIZED = 1; + } + + rv |= _run_fuzz(data, size, fuzz_elementtree_parsewhole); +#endif +#if !defined(_Py_FUZZ_ONE) || defined(_Py_FUZZ_fuzz_pycompile) + rv |= _run_fuzz(data, size, fuzz_pycompile); #endif return rv; } diff --git a/Modules/_zoneinfo.c b/Modules/_zoneinfo.c index fb0b4b40b2ad5d..fcd4af64df0be9 100644 --- a/Modules/_zoneinfo.c +++ b/Modules/_zoneinfo.c @@ -4,14 +4,13 @@ #include "Python.h" #include "pycore_long.h" // _PyLong_GetOne() +#include "pycore_pyerrors.h" // _PyErr_ChainExceptions1() +#include "datetime.h" // PyDateTime_TZInfo -#include -#include +#include // offsetof() #include -#include "datetime.h" - #include "clinic/_zoneinfo.c.h" /*[clinic input] module zoneinfo @@ -62,21 +61,21 @@ struct TransitionRuleType { typedef struct { TransitionRuleType base; - uint8_t month; - uint8_t week; - uint8_t day; - int8_t hour; - int8_t minute; - int8_t second; + uint8_t month; /* 1 - 12 */ + uint8_t week; /* 1 - 5 */ + uint8_t day; /* 0 - 6 */ + int16_t hour; /* -167 - 167, RFC 8536 §3.3.1 */ + int8_t minute; /* signed 2 digits */ + int8_t second; /* signed 2 digits */ } CalendarRule; typedef struct { TransitionRuleType base; - uint8_t julian; - unsigned int day; - int8_t hour; - int8_t minute; - int8_t second; + uint8_t julian; /* 0, 1 */ + uint16_t day; /* 0 - 365 */ + int16_t hour; /* -167 - 167, RFC 8536 §3.3.1 */ + int8_t minute; /* signed 2 digits */ + int8_t second; /* signed 2 digits */ } DayRule; struct StrongCacheNode { @@ -134,15 +133,14 @@ ts_to_local(size_t *trans_idx, int64_t *trans_utc, long *utcoff, static int parse_tz_str(zoneinfo_state *state, PyObject *tz_str_obj, _tzrule *out); -static Py_ssize_t -parse_abbr(const char *const p, PyObject **abbr); -static Py_ssize_t -parse_tz_delta(const char *const p, long *total_seconds); -static Py_ssize_t -parse_transition_time(const char *const p, int8_t *hour, int8_t *minute, - int8_t *second); -static Py_ssize_t -parse_transition_rule(const char *const p, TransitionRuleType **out); +static int +parse_abbr(const char **p, PyObject **abbr); +static int +parse_tz_delta(const char **p, long *total_seconds); +static int +parse_transition_time(const char **p, int *hour, int *minute, int *second); +static int +parse_transition_rule(const char **p, TransitionRuleType **out); static _ttinfo * find_tzrule_ttinfo(_tzrule *rule, int64_t ts, unsigned char fold, int year); @@ -422,7 +420,7 @@ zoneinfo_ZoneInfo_from_file_impl(PyTypeObject *type, PyTypeObject *cls, return NULL; } - file_repr = PyUnicode_FromFormat("%R", file_obj); + file_repr = PyObject_Repr(file_obj); if (file_repr == NULL) { goto error; } @@ -818,7 +816,7 @@ zoneinfo_ZoneInfo__unpickle_impl(PyTypeObject *type, PyTypeObject *cls, /*[clinic end generated code: output=556712fc709deecb input=6ac8c73eed3de316]*/ { if (from_cache) { - PyObject *val_args = Py_BuildValue("(O)", key); + PyObject *val_args = PyTuple_Pack(1, key); if (val_args == NULL) { return NULL; } @@ -855,28 +853,19 @@ load_timedelta(zoneinfo_state *state, long seconds) if (pyoffset == NULL) { return NULL; } - rv = PyDict_GetItemWithError(state->TIMEDELTA_CACHE, pyoffset); - if (rv == NULL) { - if (PyErr_Occurred()) { - goto error; - } + if (PyDict_GetItemRef(state->TIMEDELTA_CACHE, pyoffset, &rv) == 0) { PyObject *tmp = PyDateTimeAPI->Delta_FromDelta( 0, seconds, 0, 1, PyDateTimeAPI->DeltaType); - if (tmp == NULL) { - goto error; + if (tmp != NULL) { + rv = PyDict_SetDefault(state->TIMEDELTA_CACHE, pyoffset, tmp); + Py_XINCREF(rv); + Py_DECREF(tmp); } - - rv = PyDict_SetDefault(state->TIMEDELTA_CACHE, pyoffset, tmp); - Py_DECREF(tmp); } - Py_XINCREF(rv); Py_DECREF(pyoffset); return rv; -error: - Py_DECREF(pyoffset); - return NULL; } /* Constructor for _ttinfo object - this starts by initializing the _ttinfo @@ -1328,14 +1317,14 @@ calendarrule_year_to_timestamp(TransitionRuleType *base_self, int year) } int64_t ordinal = ymd_to_ord(year, self->month, month_day) - EPOCHORDINAL; - return ((ordinal * 86400) + (int64_t)(self->hour * 3600) + - (int64_t)(self->minute * 60) + (int64_t)(self->second)); + return ordinal * 86400 + (int64_t)self->hour * 3600 + + (int64_t)self->minute * 60 + self->second; } /* Constructor for CalendarRule. */ int -calendarrule_new(uint8_t month, uint8_t week, uint8_t day, int8_t hour, - int8_t minute, int8_t second, CalendarRule *out) +calendarrule_new(int month, int week, int day, int hour, + int minute, int second, CalendarRule *out) { // These bounds come from the POSIX standard, which describes an Mm.n.d // rule as: @@ -1344,33 +1333,36 @@ calendarrule_new(uint8_t month, uint8_t week, uint8_t day, int8_t hour, // 5, 1 <= m <= 12, where week 5 means "the last d day in month m" which // may occur in either the fourth or the fifth week). Week 1 is the first // week in which the d'th day occurs. Day zero is Sunday. - if (month <= 0 || month > 12) { - PyErr_Format(PyExc_ValueError, "Month must be in (0, 12]"); + if (month < 1 || month > 12) { + PyErr_Format(PyExc_ValueError, "Month must be in [1, 12]"); return -1; } - if (week <= 0 || week > 5) { - PyErr_Format(PyExc_ValueError, "Week must be in (0, 5]"); + if (week < 1 || week > 5) { + PyErr_Format(PyExc_ValueError, "Week must be in [1, 5]"); return -1; } - // If the 'day' parameter type is changed to a signed type, - // "day < 0" check must be added. - if (/* day < 0 || */ day > 6) { + if (day < 0 || day > 6) { PyErr_Format(PyExc_ValueError, "Day must be in [0, 6]"); return -1; } + if (hour < -167 || hour > 167) { + PyErr_Format(PyExc_ValueError, "Hour must be in [0, 167]"); + return -1; + } + TransitionRuleType base = {&calendarrule_year_to_timestamp}; CalendarRule new_offset = { .base = base, - .month = month, - .week = week, - .day = day, - .hour = hour, - .minute = minute, - .second = second, + .month = (uint8_t)month, + .week = (uint8_t)week, + .day = (uint8_t)day, + .hour = (int16_t)hour, + .minute = (int8_t)minute, + .second = (int8_t)second, }; *out = new_offset; @@ -1410,40 +1402,45 @@ dayrule_year_to_timestamp(TransitionRuleType *base_self, int year) // always transitions on a given calendar day (other than February 29th), // you would use a Julian day, e.g. J91 always refers to April 1st and J365 // always refers to December 31st. - unsigned int day = self->day; + uint16_t day = self->day; if (self->julian && day >= 59 && is_leap_year(year)) { day += 1; } - return ((days_before_year + day) * 86400) + (self->hour * 3600) + - (self->minute * 60) + self->second; + return (days_before_year + day) * 86400 + (int64_t)self->hour * 3600 + + (int64_t)self->minute * 60 + self->second; } /* Constructor for DayRule. */ static int -dayrule_new(uint8_t julian, unsigned int day, int8_t hour, int8_t minute, - int8_t second, DayRule *out) +dayrule_new(int julian, int day, int hour, int minute, + int second, DayRule *out) { // The POSIX standard specifies that Julian days must be in the range (1 <= // n <= 365) and that non-Julian (they call it "0-based Julian") days must // be in the range (0 <= n <= 365). if (day < julian || day > 365) { - PyErr_Format(PyExc_ValueError, "day must be in [%u, 365], not: %u", + PyErr_Format(PyExc_ValueError, "day must be in [%d, 365], not: %d", julian, day); return -1; } + if (hour < -167 || hour > 167) { + PyErr_Format(PyExc_ValueError, "Hour must be in [0, 167]"); + return -1; + } + TransitionRuleType base = { &dayrule_year_to_timestamp, }; DayRule tmp = { .base = base, - .julian = julian, - .day = day, - .hour = hour, - .minute = minute, - .second = second, + .julian = (uint8_t)julian, + .day = (int16_t)day, + .hour = (int16_t)hour, + .minute = (int8_t)minute, + .second = (int8_t)second, }; *out = tmp; @@ -1600,21 +1597,18 @@ parse_tz_str(zoneinfo_state *state, PyObject *tz_str_obj, _tzrule *out) const char *p = tz_str; // Read the `std` abbreviation, which must be at least 3 characters long. - Py_ssize_t num_chars = parse_abbr(p, &std_abbr); - if (num_chars < 1) { - PyErr_Format(PyExc_ValueError, "Invalid STD format in %R", tz_str_obj); + if (parse_abbr(&p, &std_abbr)) { + if (!PyErr_Occurred()) { + PyErr_Format(PyExc_ValueError, "Invalid STD format in %R", tz_str_obj); + } goto error; } - p += num_chars; - // Now read the STD offset, which is required - num_chars = parse_tz_delta(p, &std_offset); - if (num_chars < 0) { + if (parse_tz_delta(&p, &std_offset)) { PyErr_Format(PyExc_ValueError, "Invalid STD offset in %R", tz_str_obj); goto error; } - p += num_chars; // If the string ends here, there is no DST, otherwise we must parse the // DST abbreviation and start and end dates and times. @@ -1622,12 +1616,12 @@ parse_tz_str(zoneinfo_state *state, PyObject *tz_str_obj, _tzrule *out) goto complete; } - num_chars = parse_abbr(p, &dst_abbr); - if (num_chars < 1) { - PyErr_Format(PyExc_ValueError, "Invalid DST format in %R", tz_str_obj); + if (parse_abbr(&p, &dst_abbr)) { + if (!PyErr_Occurred()) { + PyErr_Format(PyExc_ValueError, "Invalid DST format in %R", tz_str_obj); + } goto error; } - p += num_chars; if (*p == ',') { // From the POSIX standard: @@ -1637,14 +1631,11 @@ parse_tz_str(zoneinfo_state *state, PyObject *tz_str_obj, _tzrule *out) dst_offset = std_offset + 3600; } else { - num_chars = parse_tz_delta(p, &dst_offset); - if (num_chars < 0) { + if (parse_tz_delta(&p, &dst_offset)) { PyErr_Format(PyExc_ValueError, "Invalid DST offset in %R", tz_str_obj); goto error; } - - p += num_chars; } TransitionRuleType **transitions[2] = {&start, &end}; @@ -1657,14 +1648,12 @@ parse_tz_str(zoneinfo_state *state, PyObject *tz_str_obj, _tzrule *out) } p++; - num_chars = parse_transition_rule(p, transitions[i]); - if (num_chars < 0) { + if (parse_transition_rule(&p, transitions[i])) { PyErr_Format(PyExc_ValueError, "Malformed transition rule in TZ string: %R", tz_str_obj); goto error; } - p += num_chars; } if (*p != '\0') { @@ -1699,21 +1688,25 @@ parse_tz_str(zoneinfo_state *state, PyObject *tz_str_obj, _tzrule *out) } static int -parse_uint(const char *const p, uint8_t *value) +parse_digits(const char **p, int min, int max, int *value) { - if (!isdigit(*p)) { - return -1; + assert(max <= 3); + *value = 0; + for (int i = 0; i < max; i++, (*p)++) { + if (!Py_ISDIGIT(**p)) { + return (i < min) ? -1 : 0; + } + *value *= 10; + *value += (**p) - '0'; } - - *value = (*p) - '0'; return 0; } /* Parse the STD and DST abbreviations from a TZ string. */ -static Py_ssize_t -parse_abbr(const char *const p, PyObject **abbr) +static int +parse_abbr(const char **p, PyObject **abbr) { - const char *ptr = p; + const char *ptr = *p; const char *str_start; const char *str_end; @@ -1732,7 +1725,7 @@ parse_abbr(const char *const p, PyObject **abbr) // '+' ) character, or the minus-sign ( '-' ) character. The std // and dst fields in this case shall not include the quoting // characters. - if (!isalpha(buff) && !isdigit(buff) && buff != '+' && + if (!Py_ISALPHA(buff) && !Py_ISDIGIT(buff) && buff != '+' && buff != '-') { return -1; } @@ -1742,16 +1735,19 @@ parse_abbr(const char *const p, PyObject **abbr) ptr++; } else { - str_start = p; + str_start = ptr; // From the POSIX standard: // // In the unquoted form, all characters in these fields shall be // alphabetic characters from the portable character set in the // current locale. - while (isalpha(*ptr)) { + while (Py_ISALPHA(*ptr)) { ptr++; } str_end = ptr; + if (str_end == str_start) { + return -1; + } } *abbr = PyUnicode_FromStringAndSize(str_start, str_end - str_start); @@ -1759,12 +1755,13 @@ parse_abbr(const char *const p, PyObject **abbr) return -1; } - return ptr - p; + *p = ptr; + return 0; } /* Parse a UTC offset from a TZ str. */ -static Py_ssize_t -parse_tz_delta(const char *const p, long *total_seconds) +static int +parse_tz_delta(const char **p, long *total_seconds) { // From the POSIX spec: // @@ -1779,75 +1776,30 @@ parse_tz_delta(const char *const p, long *total_seconds) // The POSIX spec says that the values for `hour` must be between 0 and 24 // hours, but RFC 8536 §3.3.1 specifies that the hours part of the // transition times may be signed and range from -167 to 167. - long sign = -1; - long hours = 0; - long minutes = 0; - long seconds = 0; - - const char *ptr = p; - char buff = *ptr; - if (buff == '-' || buff == '+') { - // Negative numbers correspond to *positive* offsets, from the spec: - // - // If preceded by a '-', the timezone shall be east of the Prime - // Meridian; otherwise, it shall be west (which may be indicated by - // an optional preceding '+' ). - if (buff == '-') { - sign = 1; - } + int hours = 0; + int minutes = 0; + int seconds = 0; - ptr++; - } - - // The hour can be 1 or 2 numeric characters - for (size_t i = 0; i < 2; ++i) { - buff = *ptr; - if (!isdigit(buff)) { - if (i == 0) { - return -1; - } - else { - break; - } - } - - hours *= 10; - hours += buff - '0'; - ptr++; - } - - if (hours > 24 || hours < 0) { + if (parse_transition_time(p, &hours, &minutes, &seconds)) { return -1; } - // Minutes and seconds always of the format ":dd" - long *outputs[2] = {&minutes, &seconds}; - for (size_t i = 0; i < 2; ++i) { - if (*ptr != ':') { - goto complete; - } - ptr++; - - for (size_t j = 0; j < 2; ++j) { - buff = *ptr; - if (!isdigit(buff)) { - return -1; - } - *(outputs[i]) *= 10; - *(outputs[i]) += buff - '0'; - ptr++; - } + if (hours > 24 || hours < -24) { + return -1; } -complete: - *total_seconds = sign * ((hours * 3600) + (minutes * 60) + seconds); - - return ptr - p; + // Negative numbers correspond to *positive* offsets, from the spec: + // + // If preceded by a '-', the timezone shall be east of the Prime + // Meridian; otherwise, it shall be west (which may be indicated by + // an optional preceding '+' ). + *total_seconds = -((hours * 3600L) + (minutes * 60) + seconds); + return 0; } /* Parse the date portion of a transition rule. */ -static Py_ssize_t -parse_transition_rule(const char *const p, TransitionRuleType **out) +static int +parse_transition_rule(const char **p, TransitionRuleType **out) { // The full transition rule indicates when to change back and forth between // STD and DST, and has the form: @@ -1859,10 +1811,10 @@ parse_transition_rule(const char *const p, TransitionRuleType **out) // does not include the ',' at the end of the first rule. // // The POSIX spec states that if *time* is not given, the default is 02:00. - const char *ptr = p; - int8_t hour = 2; - int8_t minute = 0; - int8_t second = 0; + const char *ptr = *p; + int hour = 2; + int minute = 0; + int second = 0; // Rules come in one of three flavors: // @@ -1871,44 +1823,30 @@ parse_transition_rule(const char *const p, TransitionRuleType **out) // 3. Mm.n.d: Specifying by month, week and day-of-week. if (*ptr == 'M') { - uint8_t month, week, day; + int month, week, day; ptr++; - if (parse_uint(ptr, &month)) { + + if (parse_digits(&ptr, 1, 2, &month)) { return -1; } - ptr++; - if (*ptr != '.') { - uint8_t tmp; - if (parse_uint(ptr, &tmp)) { - return -1; - } - - month *= 10; - month += tmp; - ptr++; + if (*ptr++ != '.') { + return -1; } - - uint8_t *values[2] = {&week, &day}; - for (size_t i = 0; i < 2; ++i) { - if (*ptr != '.') { - return -1; - } - ptr++; - - if (parse_uint(ptr, values[i])) { - return -1; - } - ptr++; + if (parse_digits(&ptr, 1, 1, &week)) { + return -1; + } + if (*ptr++ != '.') { + return -1; + } + if (parse_digits(&ptr, 1, 1, &day)) { + return -1; } if (*ptr == '/') { ptr++; - Py_ssize_t num_chars = - parse_transition_time(ptr, &hour, &minute, &second); - if (num_chars < 0) { + if (parse_transition_time(&ptr, &hour, &minute, &second)) { return -1; } - ptr += num_chars; } CalendarRule *rv = PyMem_Calloc(1, sizeof(CalendarRule)); @@ -1924,33 +1862,22 @@ parse_transition_rule(const char *const p, TransitionRuleType **out) *out = (TransitionRuleType *)rv; } else { - uint8_t julian = 0; - unsigned int day = 0; + int julian = 0; + int day = 0; if (*ptr == 'J') { julian = 1; ptr++; } - for (size_t i = 0; i < 3; ++i) { - if (!isdigit(*ptr)) { - if (i == 0) { - return -1; - } - break; - } - day *= 10; - day += (*ptr) - '0'; - ptr++; + if (parse_digits(&ptr, 1, 3, &day)) { + return -1; } if (*ptr == '/') { ptr++; - Py_ssize_t num_chars = - parse_transition_time(ptr, &hour, &minute, &second); - if (num_chars < 0) { + if (parse_transition_time(&ptr, &hour, &minute, &second)) { return -1; } - ptr += num_chars; } DayRule *rv = PyMem_Calloc(1, sizeof(DayRule)); @@ -1965,13 +1892,13 @@ parse_transition_rule(const char *const p, TransitionRuleType **out) *out = (TransitionRuleType *)rv; } - return ptr - p; + *p = ptr; + return 0; } /* Parse the time portion of a transition rule (e.g. following an /) */ -static Py_ssize_t -parse_transition_time(const char *const p, int8_t *hour, int8_t *minute, - int8_t *second) +static int +parse_transition_time(const char **p, int *hour, int *minute, int *second) { // From the spec: // @@ -1983,12 +1910,9 @@ parse_transition_time(const char *const p, int8_t *hour, int8_t *minute, // h[h][:mm[:ss]] // // RFC 8536 also allows transition times to be signed and to range from - // -167 to +167, but the current version only supports [0, 99]. - // - // TODO: Support the full range of transition hours. - int8_t *components[3] = {hour, minute, second}; - const char *ptr = p; - int8_t sign = 1; + // -167 to +167. + const char *ptr = *p; + int sign = 1; if (*ptr == '-' || *ptr == '+') { if (*ptr == '-') { @@ -1997,32 +1921,31 @@ parse_transition_time(const char *const p, int8_t *hour, int8_t *minute, ptr++; } - for (size_t i = 0; i < 3; ++i) { - if (i > 0) { - if (*ptr != ':') { - break; - } - ptr++; + // The hour can be 1 to 3 numeric characters + if (parse_digits(&ptr, 1, 3, hour)) { + return -1; + } + *hour *= sign; + + // Minutes and seconds always of the format ":dd" + if (*ptr == ':') { + ptr++; + if (parse_digits(&ptr, 2, 2, minute)) { + return -1; } + *minute *= sign; - uint8_t buff = 0; - for (size_t j = 0; j < 2; j++) { - if (!isdigit(*ptr)) { - if (i == 0 && j > 0) { - break; - } + if (*ptr == ':') { + ptr++; + if (parse_digits(&ptr, 2, 2, second)) { return -1; } - - buff *= 10; - buff += (*ptr) - '0'; - ptr++; + *second *= sign; } - - *(components[i]) = sign * buff; } - return ptr - p; + *p = ptr; + return 0; } /* Constructor for a _tzrule. @@ -2377,8 +2300,8 @@ get_local_timestamp(PyObject *dt, int64_t *local_ts) } } - *local_ts = (int64_t)(ord - EPOCHORDINAL) * 86400 + - (int64_t)(hour * 3600 + minute * 60 + second); + *local_ts = (int64_t)(ord - EPOCHORDINAL) * 86400L + + (int64_t)(hour * 3600L + minute * 60 + second); return 0; } diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c index a40a5b75b63d4f..b97ade6126fa08 100644 --- a/Modules/arraymodule.c +++ b/Modules/arraymodule.c @@ -8,9 +8,11 @@ #endif #include "Python.h" +#include "pycore_bytesobject.h" // _PyBytes_Repeat #include "pycore_call.h" // _PyObject_CallMethod() +#include "pycore_ceval.h" // _PyEval_GetBuiltin() +#include "pycore_modsupport.h" // _PyArg_NoKeywords() #include "pycore_moduleobject.h" // _PyModule_GetState() -#include "pycore_bytesobject.h" // _PyBytes_Repeat #include // offsetof() #include diff --git a/Modules/atexitmodule.c b/Modules/atexitmodule.c index cec177cfc2f9c8..b6f1bcbca67916 100644 --- a/Modules/atexitmodule.c +++ b/Modules/atexitmodule.c @@ -7,7 +7,7 @@ */ #include "Python.h" -#include "pycore_atexit.h" +#include "pycore_atexit.h" // export _Py_AtExit() #include "pycore_initconfig.h" // _PyStatus_NO_MEMORY #include "pycore_interp.h" // PyInterpreterState.atexit #include "pycore_pystate.h" // _PyInterpreterState_GET @@ -136,7 +136,8 @@ atexit_callfuncs(struct atexit_state *state) PyObject* the_func = Py_NewRef(cb->func); PyObject *res = PyObject_Call(cb->func, cb->args, cb->kwargs); if (res == NULL) { - _PyErr_WriteUnraisableMsg("in atexit callback", the_func); + PyErr_FormatUnraisable( + "Exception ignored in atexit callback %R", the_func); } else { Py_DECREF(res); diff --git a/Modules/binascii.c b/Modules/binascii.c index a87a2ef2e89927..86493241a1fb7e 100644 --- a/Modules/binascii.c +++ b/Modules/binascii.c @@ -185,13 +185,7 @@ ascii_buffer_converter(PyObject *arg, Py_buffer *buf) "not '%.100s'", Py_TYPE(arg)->tp_name); return 0; } - if (!PyBuffer_IsContiguous(buf, 'C')) { - PyErr_Format(PyExc_TypeError, - "argument should be a contiguous buffer, " - "not '%.100s'", Py_TYPE(arg)->tp_name); - PyBuffer_Release(buf); - return 0; - } + assert(PyBuffer_IsContiguous(buf, 'C')); return Py_CLEANUP_SUPPORTED; } @@ -776,12 +770,20 @@ binascii_crc32_impl(PyObject *module, Py_buffer *data, unsigned int crc) Py_BEGIN_ALLOW_THREADS /* Avoid truncation of length for very large buffers. crc32() takes - length as an unsigned int, which may be narrower than Py_ssize_t. */ - while ((size_t)len > UINT_MAX) { - crc = crc32(crc, buf, UINT_MAX); - buf += (size_t) UINT_MAX; - len -= (size_t) UINT_MAX; + length as an unsigned int, which may be narrower than Py_ssize_t. + We further limit size due to bugs in Apple's macOS zlib. + See https://github.com/python/cpython/issues/105967 + */ +#define ZLIB_CRC_CHUNK_SIZE 0x40000000 +#if ZLIB_CRC_CHUNK_SIZE > INT_MAX +# error "unsupported less than 32-bit platform?" +#endif + while ((size_t)len > ZLIB_CRC_CHUNK_SIZE) { + crc = crc32(crc, buf, ZLIB_CRC_CHUNK_SIZE); + buf += (size_t) ZLIB_CRC_CHUNK_SIZE; + len -= (size_t) ZLIB_CRC_CHUNK_SIZE; } +#undef ZLIB_CRC_CHUNK_SIZE crc = crc32(crc, buf, (unsigned int)len); Py_END_ALLOW_THREADS } else { diff --git a/Modules/cjkcodecs/_codecs_iso2022.c b/Modules/cjkcodecs/_codecs_iso2022.c index 86bb73b982a551..e8835ad0909633 100644 --- a/Modules/cjkcodecs/_codecs_iso2022.c +++ b/Modules/cjkcodecs/_codecs_iso2022.c @@ -207,8 +207,9 @@ ENCODER(iso2022) encoded = MAP_UNMAPPABLE; for (dsg = CONFIG_DESIGNATIONS; dsg->mark; dsg++) { + Py_UCS4 buf[2] = {c, 0}; Py_ssize_t length = 1; - encoded = dsg->encoder(codec, &c, &length); + encoded = dsg->encoder(codec, buf, &length); if (encoded == MAP_MULTIPLE_AVAIL) { /* this implementation won't work for pair * of non-bmp characters. */ @@ -217,9 +218,11 @@ ENCODER(iso2022) return MBERR_TOOFEW; length = -1; } - else + else { + buf[1] = INCHAR2; length = 2; - encoded = dsg->encoder(codec, &c, &length); + } + encoded = dsg->encoder(codec, buf, &length); if (encoded != MAP_UNMAPPABLE) { insize = length; break; diff --git a/Modules/cjkcodecs/clinic/multibytecodec.c.h b/Modules/cjkcodecs/clinic/multibytecodec.c.h index 1b41c231eac5d8..305ade17b1f1aa 100644 --- a/Modules/cjkcodecs/clinic/multibytecodec.c.h +++ b/Modules/cjkcodecs/clinic/multibytecodec.c.h @@ -3,10 +3,10 @@ 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() +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() #endif - +#include "pycore_modsupport.h" // _PyArg_UnpackKeywords() PyDoc_STRVAR(_multibytecodec_MultibyteCodec_encode__doc__, "encode($self, /, input, errors=None)\n" @@ -154,10 +154,6 @@ _multibytecodec_MultibyteCodec_decode(MultibyteCodecObject *self, PyObject *cons if (PyObject_GetBuffer(args[0], &input, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&input, 'C')) { - _PyArg_BadArgument("decode", "argument 'input'", "contiguous buffer", args[0]); - goto exit; - } if (!noptargs) { goto skip_optional_pos; } @@ -374,10 +370,6 @@ _multibytecodec_MultibyteIncrementalDecoder_decode(MultibyteIncrementalDecoderOb if (PyObject_GetBuffer(args[0], &input, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&input, 'C')) { - _PyArg_BadArgument("decode", "argument 'input'", "contiguous buffer", args[0]); - goto exit; - } if (!noptargs) { goto skip_optional_pos; } @@ -690,4 +682,4 @@ PyDoc_STRVAR(_multibytecodec___create_codec__doc__, #define _MULTIBYTECODEC___CREATE_CODEC_METHODDEF \ {"__create_codec", (PyCFunction)_multibytecodec___create_codec, METH_O, _multibytecodec___create_codec__doc__}, -/*[clinic end generated code: output=5f0e8dacddb0ac76 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=219a363662d2fbff input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_abc.c.h b/Modules/clinic/_abc.c.h index 2adec818c91311..04681fa2206a2a 100644 --- a/Modules/clinic/_abc.c.h +++ b/Modules/clinic/_abc.c.h @@ -2,11 +2,7 @@ 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 - +#include "pycore_modsupport.h" // _PyArg_CheckPositional() PyDoc_STRVAR(_abc__reset_registry__doc__, "_reset_registry($module, self, /)\n" @@ -165,4 +161,4 @@ _abc_get_cache_token(PyObject *module, PyObject *Py_UNUSED(ignored)) { return _abc_get_cache_token_impl(module); } -/*[clinic end generated code: output=c2e69611a495c98d input=a9049054013a1b77]*/ +/*[clinic end generated code: output=1989b6716c950e17 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_asynciomodule.c.h b/Modules/clinic/_asynciomodule.c.h index 6a780a80cd0bc4..d941c280a4300b 100644 --- a/Modules/clinic/_asynciomodule.c.h +++ b/Modules/clinic/_asynciomodule.c.h @@ -3,10 +3,10 @@ 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() +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() #endif - +#include "pycore_modsupport.h" // _PyArg_UnpackKeywords() PyDoc_STRVAR(_asyncio_Future___init____doc__, "Future(*, loop=None)\n" @@ -1487,4 +1487,4 @@ _asyncio_current_task(PyObject *module, PyObject *const *args, Py_ssize_t nargs, exit: return return_value; } -/*[clinic end generated code: output=6b0e283177b07639 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=f3864d8e2af7635f input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_bisectmodule.c.h b/Modules/clinic/_bisectmodule.c.h index 7944f5219b02a3..9955d0edb2699f 100644 --- a/Modules/clinic/_bisectmodule.c.h +++ b/Modules/clinic/_bisectmodule.c.h @@ -3,10 +3,11 @@ 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() +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() #endif - +#include "pycore_abstract.h" // _PyNumber_Index() +#include "pycore_modsupport.h" // _PyArg_UnpackKeywords() PyDoc_STRVAR(_bisect_bisect_right__doc__, "bisect_right($module, /, a, x, lo=0, hi=None, *, key=None)\n" @@ -433,4 +434,4 @@ _bisect_insort_left(PyObject *module, PyObject *const *args, Py_ssize_t nargs, P exit: return return_value; } -/*[clinic end generated code: output=5a7fa64bf9b262f3 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=4af5bd405149bf5f input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_bz2module.c.h b/Modules/clinic/_bz2module.c.h index d7797d639ae32e..de7b3993596446 100644 --- a/Modules/clinic/_bz2module.c.h +++ b/Modules/clinic/_bz2module.c.h @@ -3,10 +3,11 @@ 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() +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() #endif - +#include "pycore_abstract.h" // _PyNumber_Index() +#include "pycore_modsupport.h" // _PyArg_BadArgument() PyDoc_STRVAR(_bz2_BZ2Compressor_compress__doc__, "compress($self, data, /)\n" @@ -34,10 +35,6 @@ _bz2_BZ2Compressor_compress(BZ2Compressor *self, PyObject *arg) if (PyObject_GetBuffer(arg, &data, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("compress", "argument", "contiguous buffer", arg); - goto exit; - } return_value = _bz2_BZ2Compressor_compress_impl(self, &data); exit: @@ -102,7 +99,7 @@ _bz2_BZ2Compressor(PyTypeObject *type, PyObject *args, PyObject *kwargs) if (PyTuple_GET_SIZE(args) < 1) { goto skip_optional; } - compresslevel = _PyLong_AsInt(PyTuple_GET_ITEM(args, 0)); + compresslevel = PyLong_AsInt(PyTuple_GET_ITEM(args, 0)); if (compresslevel == -1 && PyErr_Occurred()) { goto exit; } @@ -180,10 +177,6 @@ _bz2_BZ2Decompressor_decompress(BZ2Decompressor *self, PyObject *const *args, Py if (PyObject_GetBuffer(args[0], &data, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("decompress", "argument 'data'", "contiguous buffer", args[0]); - goto exit; - } if (!noptargs) { goto skip_optional_pos; } @@ -241,4 +234,4 @@ _bz2_BZ2Decompressor(PyTypeObject *type, PyObject *args, PyObject *kwargs) exit: return return_value; } -/*[clinic end generated code: output=805400e4805098ec input=a9049054013a1b77]*/ +/*[clinic end generated code: output=8daa62f47cc4853d input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_codecsmodule.c.h b/Modules/clinic/_codecsmodule.c.h index 2275b6b9685276..12fea806ab5209 100644 --- a/Modules/clinic/_codecsmodule.c.h +++ b/Modules/clinic/_codecsmodule.c.h @@ -3,10 +3,10 @@ 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() +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() #endif - +#include "pycore_modsupport.h" // _PyArg_BadArgument() PyDoc_STRVAR(_codecs_register__doc__, "register($module, search_function, /)\n" @@ -303,10 +303,6 @@ _codecs_escape_decode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (PyObject_GetBuffer(args[0], &data, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("escape_decode", "argument 1", "contiguous buffer", args[0]); - goto exit; - } } if (nargs < 2) { goto skip_optional; @@ -422,10 +418,6 @@ _codecs_utf_7_decode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (PyObject_GetBuffer(args[0], &data, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("utf_7_decode", "argument 1", "contiguous buffer", args[0]); - goto exit; - } if (nargs < 2) { goto skip_optional; } @@ -492,10 +484,6 @@ _codecs_utf_8_decode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (PyObject_GetBuffer(args[0], &data, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("utf_8_decode", "argument 1", "contiguous buffer", args[0]); - goto exit; - } if (nargs < 2) { goto skip_optional; } @@ -562,10 +550,6 @@ _codecs_utf_16_decode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (PyObject_GetBuffer(args[0], &data, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("utf_16_decode", "argument 1", "contiguous buffer", args[0]); - goto exit; - } if (nargs < 2) { goto skip_optional; } @@ -632,10 +616,6 @@ _codecs_utf_16_le_decode(PyObject *module, PyObject *const *args, Py_ssize_t nar if (PyObject_GetBuffer(args[0], &data, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("utf_16_le_decode", "argument 1", "contiguous buffer", args[0]); - goto exit; - } if (nargs < 2) { goto skip_optional; } @@ -702,10 +682,6 @@ _codecs_utf_16_be_decode(PyObject *module, PyObject *const *args, Py_ssize_t nar if (PyObject_GetBuffer(args[0], &data, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("utf_16_be_decode", "argument 1", "contiguous buffer", args[0]); - goto exit; - } if (nargs < 2) { goto skip_optional; } @@ -774,10 +750,6 @@ _codecs_utf_16_ex_decode(PyObject *module, PyObject *const *args, Py_ssize_t nar if (PyObject_GetBuffer(args[0], &data, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("utf_16_ex_decode", "argument 1", "contiguous buffer", args[0]); - goto exit; - } if (nargs < 2) { goto skip_optional; } @@ -802,7 +774,7 @@ _codecs_utf_16_ex_decode(PyObject *module, PyObject *const *args, Py_ssize_t nar if (nargs < 3) { goto skip_optional; } - byteorder = _PyLong_AsInt(args[2]); + byteorder = PyLong_AsInt(args[2]); if (byteorder == -1 && PyErr_Occurred()) { goto exit; } @@ -851,10 +823,6 @@ _codecs_utf_32_decode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (PyObject_GetBuffer(args[0], &data, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("utf_32_decode", "argument 1", "contiguous buffer", args[0]); - goto exit; - } if (nargs < 2) { goto skip_optional; } @@ -921,10 +889,6 @@ _codecs_utf_32_le_decode(PyObject *module, PyObject *const *args, Py_ssize_t nar if (PyObject_GetBuffer(args[0], &data, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("utf_32_le_decode", "argument 1", "contiguous buffer", args[0]); - goto exit; - } if (nargs < 2) { goto skip_optional; } @@ -991,10 +955,6 @@ _codecs_utf_32_be_decode(PyObject *module, PyObject *const *args, Py_ssize_t nar if (PyObject_GetBuffer(args[0], &data, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("utf_32_be_decode", "argument 1", "contiguous buffer", args[0]); - goto exit; - } if (nargs < 2) { goto skip_optional; } @@ -1063,10 +1023,6 @@ _codecs_utf_32_ex_decode(PyObject *module, PyObject *const *args, Py_ssize_t nar if (PyObject_GetBuffer(args[0], &data, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("utf_32_ex_decode", "argument 1", "contiguous buffer", args[0]); - goto exit; - } if (nargs < 2) { goto skip_optional; } @@ -1091,7 +1047,7 @@ _codecs_utf_32_ex_decode(PyObject *module, PyObject *const *args, Py_ssize_t nar if (nargs < 3) { goto skip_optional; } - byteorder = _PyLong_AsInt(args[2]); + byteorder = PyLong_AsInt(args[2]); if (byteorder == -1 && PyErr_Occurred()) { goto exit; } @@ -1149,10 +1105,6 @@ _codecs_unicode_escape_decode(PyObject *module, PyObject *const *args, Py_ssize_ if (PyObject_GetBuffer(args[0], &data, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("unicode_escape_decode", "argument 1", "contiguous buffer", args[0]); - goto exit; - } } if (nargs < 2) { goto skip_optional; @@ -1229,10 +1181,6 @@ _codecs_raw_unicode_escape_decode(PyObject *module, PyObject *const *args, Py_ss if (PyObject_GetBuffer(args[0], &data, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("raw_unicode_escape_decode", "argument 1", "contiguous buffer", args[0]); - goto exit; - } } if (nargs < 2) { goto skip_optional; @@ -1299,10 +1247,6 @@ _codecs_latin_1_decode(PyObject *module, PyObject *const *args, Py_ssize_t nargs if (PyObject_GetBuffer(args[0], &data, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("latin_1_decode", "argument 1", "contiguous buffer", args[0]); - goto exit; - } if (nargs < 2) { goto skip_optional; } @@ -1361,10 +1305,6 @@ _codecs_ascii_decode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (PyObject_GetBuffer(args[0], &data, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("ascii_decode", "argument 1", "contiguous buffer", args[0]); - goto exit; - } if (nargs < 2) { goto skip_optional; } @@ -1424,10 +1364,6 @@ _codecs_charmap_decode(PyObject *module, PyObject *const *args, Py_ssize_t nargs if (PyObject_GetBuffer(args[0], &data, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("charmap_decode", "argument 1", "contiguous buffer", args[0]); - goto exit; - } if (nargs < 2) { goto skip_optional; } @@ -1493,10 +1429,6 @@ _codecs_mbcs_decode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (PyObject_GetBuffer(args[0], &data, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("mbcs_decode", "argument 1", "contiguous buffer", args[0]); - goto exit; - } if (nargs < 2) { goto skip_optional; } @@ -1567,10 +1499,6 @@ _codecs_oem_decode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (PyObject_GetBuffer(args[0], &data, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("oem_decode", "argument 1", "contiguous buffer", args[0]); - goto exit; - } if (nargs < 2) { goto skip_optional; } @@ -1639,17 +1567,13 @@ _codecs_code_page_decode(PyObject *module, PyObject *const *args, Py_ssize_t nar if (!_PyArg_CheckPositional("code_page_decode", nargs, 2, 4)) { goto exit; } - codepage = _PyLong_AsInt(args[0]); + codepage = PyLong_AsInt(args[0]); if (codepage == -1 && PyErr_Occurred()) { goto exit; } if (PyObject_GetBuffer(args[1], &data, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("code_page_decode", "argument 2", "contiguous buffer", args[1]); - goto exit; - } if (nargs < 3) { goto skip_optional; } @@ -1726,10 +1650,6 @@ _codecs_readbuffer_encode(PyObject *module, PyObject *const *args, Py_ssize_t na if (PyObject_GetBuffer(args[0], &data, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("readbuffer_encode", "argument 1", "contiguous buffer", args[0]); - goto exit; - } } if (nargs < 2) { goto skip_optional; @@ -1926,7 +1846,7 @@ _codecs_utf_16_encode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (nargs < 3) { goto skip_optional; } - byteorder = _PyLong_AsInt(args[2]); + byteorder = PyLong_AsInt(args[2]); if (byteorder == -1 && PyErr_Occurred()) { goto exit; } @@ -2099,7 +2019,7 @@ _codecs_utf_32_encode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (nargs < 3) { goto skip_optional; } - byteorder = _PyLong_AsInt(args[2]); + byteorder = PyLong_AsInt(args[2]); if (byteorder == -1 && PyErr_Occurred()) { goto exit; } @@ -2669,7 +2589,7 @@ _codecs_code_page_encode(PyObject *module, PyObject *const *args, Py_ssize_t nar if (!_PyArg_CheckPositional("code_page_encode", nargs, 2, 3)) { goto exit; } - code_page = _PyLong_AsInt(args[0]); + code_page = PyLong_AsInt(args[0]); if (code_page == -1 && PyErr_Occurred()) { goto exit; } @@ -2818,4 +2738,4 @@ _codecs_lookup_error(PyObject *module, PyObject *arg) #ifndef _CODECS_CODE_PAGE_ENCODE_METHODDEF #define _CODECS_CODE_PAGE_ENCODE_METHODDEF #endif /* !defined(_CODECS_CODE_PAGE_ENCODE_METHODDEF) */ -/*[clinic end generated code: output=0f52053d31533376 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=d8d9e372f7ccba35 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_collectionsmodule.c.h b/Modules/clinic/_collectionsmodule.c.h index 3882d069216e28..591ab50c76a8e8 100644 --- a/Modules/clinic/_collectionsmodule.c.h +++ b/Modules/clinic/_collectionsmodule.c.h @@ -2,11 +2,8 @@ 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 - +#include "pycore_abstract.h" // _PyNumber_Index() +#include "pycore_modsupport.h" // _PyArg_CheckPositional() PyDoc_STRVAR(_collections__count_elements__doc__, "_count_elements($module, mapping, iterable, /)\n" @@ -75,4 +72,4 @@ tuplegetter_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) exit: return return_value; } -/*[clinic end generated code: output=00e516317d2b8bed input=a9049054013a1b77]*/ +/*[clinic end generated code: output=c896a72f8c45930d input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_contextvarsmodule.c.h b/Modules/clinic/_contextvarsmodule.c.h index 461d4845635ef0..b1885e41c355d2 100644 --- a/Modules/clinic/_contextvarsmodule.c.h +++ b/Modules/clinic/_contextvarsmodule.c.h @@ -2,12 +2,6 @@ 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(_contextvars_copy_context__doc__, "copy_context($module, /)\n" "--\n" @@ -24,4 +18,4 @@ _contextvars_copy_context(PyObject *module, PyObject *Py_UNUSED(ignored)) { return _contextvars_copy_context_impl(module); } -/*[clinic end generated code: output=1736c27450823e70 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=26e07024451baf52 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_csv.c.h b/Modules/clinic/_csv.c.h index 8900946350a524..2442bdcde5679f 100644 --- a/Modules/clinic/_csv.c.h +++ b/Modules/clinic/_csv.c.h @@ -3,10 +3,10 @@ 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() +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() #endif - +#include "pycore_modsupport.h" // _PyArg_UnpackKeywords() PyDoc_STRVAR(_csv_list_dialects__doc__, "list_dialects($module, /)\n" @@ -206,4 +206,4 @@ _csv_field_size_limit(PyObject *module, PyObject *const *args, Py_ssize_t nargs, exit: return return_value; } -/*[clinic end generated code: output=94374e41eb2806ee input=a9049054013a1b77]*/ +/*[clinic end generated code: output=9ec59717f5414d8b input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_curses_panel.c.h b/Modules/clinic/_curses_panel.c.h index bb6cc90f0438c0..7945d93b5433f7 100644 --- a/Modules/clinic/_curses_panel.c.h +++ b/Modules/clinic/_curses_panel.c.h @@ -2,11 +2,7 @@ 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 - +#include "pycore_modsupport.h" // _PyArg_UnpackKeywords() PyDoc_STRVAR(_curses_panel_panel_bottom__doc__, "bottom($self, /)\n" @@ -190,11 +186,11 @@ _curses_panel_panel_move(PyCursesPanelObject *self, PyTypeObject *cls, PyObject if (!args) { goto exit; } - y = _PyLong_AsInt(args[0]); + y = PyLong_AsInt(args[0]); if (y == -1 && PyErr_Occurred()) { goto exit; } - x = _PyLong_AsInt(args[1]); + x = PyLong_AsInt(args[1]); if (x == -1 && PyErr_Occurred()) { goto exit; } @@ -422,4 +418,4 @@ _curses_panel_update_panels(PyObject *module, PyObject *Py_UNUSED(ignored)) { return _curses_panel_update_panels_impl(module); } -/*[clinic end generated code: output=8d0533681891523c input=a9049054013a1b77]*/ +/*[clinic end generated code: output=636beecf71d96ff1 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_cursesmodule.c.h b/Modules/clinic/_cursesmodule.c.h index 9d99d41af5d2d9..f7e0aaf7b23649 100644 --- a/Modules/clinic/_cursesmodule.c.h +++ b/Modules/clinic/_cursesmodule.c.h @@ -3,10 +3,10 @@ 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() +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() #endif - +#include "pycore_modsupport.h" // _PyArg_CheckPositional() PyDoc_STRVAR(_curses_window_addch__doc__, "addch([y, x,] ch, [attr=_curses.A_NORMAL])\n" @@ -708,11 +708,11 @@ _curses_window_enclose(PyCursesWindowObject *self, PyObject *const *args, Py_ssi if (!_PyArg_CheckPositional("enclose", nargs, 2, 2)) { goto exit; } - y = _PyLong_AsInt(args[0]); + y = PyLong_AsInt(args[0]); if (y == -1 && PyErr_Occurred()) { goto exit; } - x = _PyLong_AsInt(args[1]); + x = PyLong_AsInt(args[1]); if (x == -1 && PyErr_Occurred()) { goto exit; } @@ -1264,7 +1264,7 @@ _curses_window_is_linetouched(PyCursesWindowObject *self, PyObject *arg) PyObject *return_value = NULL; int line; - line = _PyLong_AsInt(arg); + line = PyLong_AsInt(arg); if (line == -1 && PyErr_Occurred()) { goto exit; } @@ -1508,11 +1508,11 @@ _curses_window_redrawln(PyCursesWindowObject *self, PyObject *const *args, Py_ss if (!_PyArg_CheckPositional("redrawln", nargs, 2, 2)) { goto exit; } - beg = _PyLong_AsInt(args[0]); + beg = PyLong_AsInt(args[0]); if (beg == -1 && PyErr_Occurred()) { goto exit; } - num = _PyLong_AsInt(args[1]); + num = PyLong_AsInt(args[1]); if (num == -1 && PyErr_Occurred()) { goto exit; } @@ -1607,11 +1607,11 @@ _curses_window_setscrreg(PyCursesWindowObject *self, PyObject *const *args, Py_s if (!_PyArg_CheckPositional("setscrreg", nargs, 2, 2)) { goto exit; } - top = _PyLong_AsInt(args[0]); + top = PyLong_AsInt(args[0]); if (top == -1 && PyErr_Occurred()) { goto exit; } - bottom = _PyLong_AsInt(args[1]); + bottom = PyLong_AsInt(args[1]); if (bottom == -1 && PyErr_Occurred()) { goto exit; } @@ -2009,7 +2009,7 @@ _curses_color_pair(PyObject *module, PyObject *arg) PyObject *return_value = NULL; int pair_number; - pair_number = _PyLong_AsInt(arg); + pair_number = PyLong_AsInt(arg); if (pair_number == -1 && PyErr_Occurred()) { goto exit; } @@ -2045,7 +2045,7 @@ _curses_curs_set(PyObject *module, PyObject *arg) PyObject *return_value = NULL; int visibility; - visibility = _PyLong_AsInt(arg); + visibility = PyLong_AsInt(arg); if (visibility == -1 && PyErr_Occurred()) { goto exit; } @@ -2120,7 +2120,7 @@ _curses_delay_output(PyObject *module, PyObject *arg) PyObject *return_value = NULL; int ms; - ms = _PyLong_AsInt(arg); + ms = PyLong_AsInt(arg); if (ms == -1 && PyErr_Occurred()) { goto exit; } @@ -2363,15 +2363,15 @@ _curses_ungetmouse(PyObject *module, PyObject *const *args, Py_ssize_t nargs) id = (short) ival; } } - x = _PyLong_AsInt(args[1]); + x = PyLong_AsInt(args[1]); if (x == -1 && PyErr_Occurred()) { goto exit; } - y = _PyLong_AsInt(args[2]); + y = PyLong_AsInt(args[2]); if (y == -1 && PyErr_Occurred()) { goto exit; } - z = _PyLong_AsInt(args[3]); + z = PyLong_AsInt(args[3]); if (z == -1 && PyErr_Occurred()) { goto exit; } @@ -2525,7 +2525,7 @@ _curses_has_key(PyObject *module, PyObject *arg) PyObject *return_value = NULL; int key; - key = _PyLong_AsInt(arg); + key = PyLong_AsInt(arg); if (key == -1 && PyErr_Occurred()) { goto exit; } @@ -2744,7 +2744,7 @@ _curses_setupterm(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyO goto skip_optional_pos; } } - fd = _PyLong_AsInt(args[1]); + fd = PyLong_AsInt(args[1]); if (fd == -1 && PyErr_Occurred()) { goto exit; } @@ -2808,7 +2808,7 @@ _curses_set_escdelay(PyObject *module, PyObject *arg) PyObject *return_value = NULL; int ms; - ms = _PyLong_AsInt(arg); + ms = PyLong_AsInt(arg); if (ms == -1 && PyErr_Occurred()) { goto exit; } @@ -2871,7 +2871,7 @@ _curses_set_tabsize(PyObject *module, PyObject *arg) PyObject *return_value = NULL; int size; - size = _PyLong_AsInt(arg); + size = PyLong_AsInt(arg); if (size == -1 && PyErr_Occurred()) { goto exit; } @@ -2957,11 +2957,11 @@ _curses_is_term_resized(PyObject *module, PyObject *const *args, Py_ssize_t narg if (!_PyArg_CheckPositional("is_term_resized", nargs, 2, 2)) { goto exit; } - nlines = _PyLong_AsInt(args[0]); + nlines = PyLong_AsInt(args[0]); if (nlines == -1 && PyErr_Occurred()) { goto exit; } - ncols = _PyLong_AsInt(args[1]); + ncols = PyLong_AsInt(args[1]); if (ncols == -1 && PyErr_Occurred()) { goto exit; } @@ -2994,7 +2994,7 @@ _curses_keyname(PyObject *module, PyObject *arg) PyObject *return_value = NULL; int key; - key = _PyLong_AsInt(arg); + key = PyLong_AsInt(arg); if (key == -1 && PyErr_Occurred()) { goto exit; } @@ -3101,7 +3101,7 @@ _curses_mouseinterval(PyObject *module, PyObject *arg) PyObject *return_value = NULL; int interval; - interval = _PyLong_AsInt(arg); + interval = PyLong_AsInt(arg); if (interval == -1 && PyErr_Occurred()) { goto exit; } @@ -3163,7 +3163,7 @@ PyDoc_STRVAR(_curses_napms__doc__, #define _CURSES_NAPMS_METHODDEF \ {"napms", (PyCFunction)_curses_napms, METH_O, _curses_napms__doc__}, -static PyObject * +static int _curses_napms_impl(PyObject *module, int ms); static PyObject * @@ -3171,12 +3171,17 @@ _curses_napms(PyObject *module, PyObject *arg) { PyObject *return_value = NULL; int ms; + int _return_value; - ms = _PyLong_AsInt(arg); + ms = PyLong_AsInt(arg); if (ms == -1 && PyErr_Occurred()) { goto exit; } - return_value = _curses_napms_impl(module, ms); + _return_value = _curses_napms_impl(module, ms); + if ((_return_value == -1) && PyErr_Occurred()) { + goto exit; + } + return_value = PyLong_FromLong((long)_return_value); exit: return return_value; @@ -3209,11 +3214,11 @@ _curses_newpad(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("newpad", nargs, 2, 2)) { goto exit; } - nlines = _PyLong_AsInt(args[0]); + nlines = PyLong_AsInt(args[0]); if (nlines == -1 && PyErr_Occurred()) { goto exit; } - ncols = _PyLong_AsInt(args[1]); + ncols = PyLong_AsInt(args[1]); if (ncols == -1 && PyErr_Occurred()) { goto exit; } @@ -3471,7 +3476,7 @@ _curses_pair_number(PyObject *module, PyObject *arg) PyObject *return_value = NULL; int attr; - attr = _PyLong_AsInt(arg); + attr = PyLong_AsInt(arg); if (attr == -1 && PyErr_Occurred()) { goto exit; } @@ -3700,11 +3705,11 @@ _curses_resizeterm(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("resizeterm", nargs, 2, 2)) { goto exit; } - nlines = _PyLong_AsInt(args[0]); + nlines = PyLong_AsInt(args[0]); if (nlines == -1 && PyErr_Occurred()) { goto exit; } - ncols = _PyLong_AsInt(args[1]); + ncols = PyLong_AsInt(args[1]); if (ncols == -1 && PyErr_Occurred()) { goto exit; } @@ -3751,11 +3756,11 @@ _curses_resize_term(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("resize_term", nargs, 2, 2)) { goto exit; } - nlines = _PyLong_AsInt(args[0]); + nlines = PyLong_AsInt(args[0]); if (nlines == -1 && PyErr_Occurred()) { goto exit; } - ncols = _PyLong_AsInt(args[1]); + ncols = PyLong_AsInt(args[1]); if (ncols == -1 && PyErr_Occurred()) { goto exit; } @@ -3816,11 +3821,11 @@ _curses_setsyx(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("setsyx", nargs, 2, 2)) { goto exit; } - y = _PyLong_AsInt(args[0]); + y = PyLong_AsInt(args[0]); if (y == -1 && PyErr_Occurred()) { goto exit; } - x = _PyLong_AsInt(args[1]); + x = PyLong_AsInt(args[1]); if (x == -1 && PyErr_Occurred()) { goto exit; } @@ -4089,7 +4094,7 @@ _curses_typeahead(PyObject *module, PyObject *arg) PyObject *return_value = NULL; int fd; - fd = _PyLong_AsInt(arg); + fd = PyLong_AsInt(arg); if (fd == -1 && PyErr_Occurred()) { goto exit; } @@ -4313,4 +4318,4 @@ _curses_has_extended_color_support(PyObject *module, PyObject *Py_UNUSED(ignored #ifndef _CURSES_USE_DEFAULT_COLORS_METHODDEF #define _CURSES_USE_DEFAULT_COLORS_METHODDEF #endif /* !defined(_CURSES_USE_DEFAULT_COLORS_METHODDEF) */ -/*[clinic end generated code: output=27a2364193b503c1 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=96887782374f070a input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_datetimemodule.c.h b/Modules/clinic/_datetimemodule.c.h index 51e51e3791cc24..1ee50fc2a13762 100644 --- a/Modules/clinic/_datetimemodule.c.h +++ b/Modules/clinic/_datetimemodule.c.h @@ -3,10 +3,10 @@ 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() +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() #endif - +#include "pycore_modsupport.h" // _PyArg_UnpackKeywords() PyDoc_STRVAR(datetime_date_fromtimestamp__doc__, "fromtimestamp($type, timestamp, /)\n" @@ -64,15 +64,15 @@ iso_calendar_date_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) if (!fastargs) { goto exit; } - year = _PyLong_AsInt(fastargs[0]); + year = PyLong_AsInt(fastargs[0]); if (year == -1 && PyErr_Occurred()) { goto exit; } - week = _PyLong_AsInt(fastargs[1]); + week = PyLong_AsInt(fastargs[1]); if (week == -1 && PyErr_Occurred()) { goto exit; } - weekday = _PyLong_AsInt(fastargs[2]); + weekday = PyLong_AsInt(fastargs[2]); if (weekday == -1 && PyErr_Occurred()) { goto exit; } @@ -146,4 +146,4 @@ datetime_datetime_now(PyTypeObject *type, PyObject *const *args, Py_ssize_t narg exit: return return_value; } -/*[clinic end generated code: output=42654669940e0e3a input=a9049054013a1b77]*/ +/*[clinic end generated code: output=562813dd3e164794 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_dbmmodule.c.h b/Modules/clinic/_dbmmodule.c.h index 98aac07423c8ab..5a4aba2825e03a 100644 --- a/Modules/clinic/_dbmmodule.c.h +++ b/Modules/clinic/_dbmmodule.c.h @@ -2,11 +2,7 @@ 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 - +#include "pycore_modsupport.h" // _PyArg_UnpackKeywords() PyDoc_STRVAR(_dbm_dbm_close__doc__, "close($self, /)\n" @@ -212,7 +208,7 @@ dbmopen(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (nargs < 3) { goto skip_optional; } - mode = _PyLong_AsInt(args[2]); + mode = PyLong_AsInt(args[2]); if (mode == -1 && PyErr_Occurred()) { goto exit; } @@ -222,4 +218,4 @@ dbmopen(PyObject *module, PyObject *const *args, Py_ssize_t nargs) exit: return return_value; } -/*[clinic end generated code: output=b3053c67ecfcc29c input=a9049054013a1b77]*/ +/*[clinic end generated code: output=96fdd4bd7bd256c5 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_elementtree.c.h b/Modules/clinic/_elementtree.c.h index a0bc751ca21ee8..02375c8a61e73e 100644 --- a/Modules/clinic/_elementtree.c.h +++ b/Modules/clinic/_elementtree.c.h @@ -3,10 +3,11 @@ 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() +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() #endif - +#include "pycore_abstract.h" // _PyNumber_Index() +#include "pycore_modsupport.h" // _PyArg_UnpackKeywords() PyDoc_STRVAR(_elementtree_Element_append__doc__, "append($self, subelement, /)\n" @@ -1218,4 +1219,4 @@ _elementtree_XMLParser__setevents(XMLParserObject *self, PyObject *const *args, exit: return return_value; } -/*[clinic end generated code: output=40767b1a98e54b60 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=8fdaa17d3262800a input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_functoolsmodule.c.h b/Modules/clinic/_functoolsmodule.c.h index 9c79e6430413bf..e98984dc4d3a09 100644 --- a/Modules/clinic/_functoolsmodule.c.h +++ b/Modules/clinic/_functoolsmodule.c.h @@ -3,10 +3,11 @@ 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() +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() #endif - +#include "pycore_critical_section.h"// Py_BEGIN_CRITICAL_SECTION() +#include "pycore_modsupport.h" // _PyArg_UnpackKeywords() PyDoc_STRVAR(_functools_cmp_to_key__doc__, "cmp_to_key($module, /, mycmp)\n" @@ -81,7 +82,13 @@ _functools__lru_cache_wrapper_cache_info_impl(PyObject *self); static PyObject * _functools__lru_cache_wrapper_cache_info(PyObject *self, PyObject *Py_UNUSED(ignored)) { - return _functools__lru_cache_wrapper_cache_info_impl(self); + PyObject *return_value = NULL; + + Py_BEGIN_CRITICAL_SECTION(self); + return_value = _functools__lru_cache_wrapper_cache_info_impl(self); + Py_END_CRITICAL_SECTION(); + + return return_value; } PyDoc_STRVAR(_functools__lru_cache_wrapper_cache_clear__doc__, @@ -99,6 +106,12 @@ _functools__lru_cache_wrapper_cache_clear_impl(PyObject *self); static PyObject * _functools__lru_cache_wrapper_cache_clear(PyObject *self, PyObject *Py_UNUSED(ignored)) { - return _functools__lru_cache_wrapper_cache_clear_impl(self); + PyObject *return_value = NULL; + + Py_BEGIN_CRITICAL_SECTION(self); + return_value = _functools__lru_cache_wrapper_cache_clear_impl(self); + Py_END_CRITICAL_SECTION(); + + return return_value; } -/*[clinic end generated code: output=7e7f3bcf9ed61f23 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=755265bb6d5ea751 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_gdbmmodule.c.h b/Modules/clinic/_gdbmmodule.c.h index 76f6db318f8cc5..c7164e519d0e7d 100644 --- a/Modules/clinic/_gdbmmodule.c.h +++ b/Modules/clinic/_gdbmmodule.c.h @@ -2,11 +2,7 @@ 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 - +#include "pycore_modsupport.h" // _PyArg_CheckPositional() PyDoc_STRVAR(_gdbm_gdbm_get__doc__, "get($self, key, default=None, /)\n" @@ -334,7 +330,7 @@ dbmopen(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (nargs < 3) { goto skip_optional; } - mode = _PyLong_AsInt(args[2]); + mode = PyLong_AsInt(args[2]); if (mode == -1 && PyErr_Occurred()) { goto exit; } @@ -344,4 +340,4 @@ dbmopen(PyObject *module, PyObject *const *args, Py_ssize_t nargs) exit: return return_value; } -/*[clinic end generated code: output=8c613cbd88e57480 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=c5ee922363d5a81f input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_hashopenssl.c.h b/Modules/clinic/_hashopenssl.c.h index fb61a444018dbb..58650dff288444 100644 --- a/Modules/clinic/_hashopenssl.c.h +++ b/Modules/clinic/_hashopenssl.c.h @@ -3,10 +3,11 @@ 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() +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() #endif - +#include "pycore_abstract.h" // _PyNumber_Index() +#include "pycore_modsupport.h" // _PyArg_UnpackKeywords() PyDoc_STRVAR(EVP_copy__doc__, "copy($self, /)\n" @@ -1289,17 +1290,9 @@ pbkdf2_hmac(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject if (PyObject_GetBuffer(args[1], &password, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&password, 'C')) { - _PyArg_BadArgument("pbkdf2_hmac", "argument 'password'", "contiguous buffer", args[1]); - goto exit; - } if (PyObject_GetBuffer(args[2], &salt, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&salt, 'C')) { - _PyArg_BadArgument("pbkdf2_hmac", "argument 'salt'", "contiguous buffer", args[2]); - goto exit; - } iterations = PyLong_AsLong(args[3]); if (iterations == -1 && PyErr_Occurred()) { goto exit; @@ -1387,10 +1380,6 @@ _hashlib_scrypt(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObj if (PyObject_GetBuffer(args[0], &password, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&password, 'C')) { - _PyArg_BadArgument("scrypt", "argument 'password'", "contiguous buffer", args[0]); - goto exit; - } if (!noptargs) { goto skip_optional_kwonly; } @@ -1398,10 +1387,6 @@ _hashlib_scrypt(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObj if (PyObject_GetBuffer(args[1], &salt, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&salt, 'C')) { - _PyArg_BadArgument("scrypt", "argument 'salt'", "contiguous buffer", args[1]); - goto exit; - } if (!--noptargs) { goto skip_optional_kwonly; } @@ -1521,17 +1506,9 @@ _hashlib_hmac_singleshot(PyObject *module, PyObject *const *args, Py_ssize_t nar if (PyObject_GetBuffer(args[0], &key, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&key, 'C')) { - _PyArg_BadArgument("hmac_digest", "argument 'key'", "contiguous buffer", args[0]); - goto exit; - } if (PyObject_GetBuffer(args[1], &msg, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&msg, 'C')) { - _PyArg_BadArgument("hmac_digest", "argument 'msg'", "contiguous buffer", args[1]); - goto exit; - } digest = args[2]; return_value = _hashlib_hmac_singleshot_impl(module, &key, &msg, digest); @@ -1603,10 +1580,6 @@ _hashlib_hmac_new(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyO if (PyObject_GetBuffer(args[0], &key, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&key, 'C')) { - _PyArg_BadArgument("hmac_new", "argument 'key'", "contiguous buffer", args[0]); - goto exit; - } if (!noptargs) { goto skip_optional_pos; } @@ -1851,4 +1824,4 @@ _hashlib_compare_digest(PyObject *module, PyObject *const *args, Py_ssize_t narg #ifndef _HASHLIB_SCRYPT_METHODDEF #define _HASHLIB_SCRYPT_METHODDEF #endif /* !defined(_HASHLIB_SCRYPT_METHODDEF) */ -/*[clinic end generated code: output=b339e255db698147 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=b7eddeb3d6ccdeec input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_heapqmodule.c.h b/Modules/clinic/_heapqmodule.c.h index 3ee3f51702fa30..9046307990773b 100644 --- a/Modules/clinic/_heapqmodule.c.h +++ b/Modules/clinic/_heapqmodule.c.h @@ -2,11 +2,7 @@ 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 - +#include "pycore_modsupport.h" // _PyArg_CheckPositional() PyDoc_STRVAR(_heapq_heappush__doc__, "heappush($module, heap, item, /)\n" @@ -271,4 +267,4 @@ _heapq__heapify_max(PyObject *module, PyObject *arg) exit: return return_value; } -/*[clinic end generated code: output=29e99a48c57f82bb input=a9049054013a1b77]*/ +/*[clinic end generated code: output=05f2afdf3bc54c9d input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_localemodule.c.h b/Modules/clinic/_localemodule.c.h index 9d65c0876a1a33..5e0880b0d0bb4c 100644 --- a/Modules/clinic/_localemodule.c.h +++ b/Modules/clinic/_localemodule.c.h @@ -2,11 +2,7 @@ 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 - +#include "pycore_modsupport.h" // _PyArg_CheckPositional() PyDoc_STRVAR(_locale_setlocale__doc__, "setlocale($module, category, locale=, /)\n" @@ -30,7 +26,7 @@ _locale_setlocale(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("setlocale", nargs, 1, 2)) { goto exit; } - category = _PyLong_AsInt(args[0]); + category = PyLong_AsInt(args[0]); if (category == -1 && PyErr_Occurred()) { goto exit; } @@ -196,7 +192,7 @@ _locale_nl_langinfo(PyObject *module, PyObject *arg) PyObject *return_value = NULL; int item; - item = _PyLong_AsInt(arg); + item = PyLong_AsInt(arg); if (item == -1 && PyErr_Occurred()) { goto exit; } @@ -373,7 +369,7 @@ _locale_dcgettext(PyObject *module, PyObject *const *args, Py_ssize_t nargs) PyErr_SetString(PyExc_ValueError, "embedded null character"); goto exit; } - category = _PyLong_AsInt(args[2]); + category = PyLong_AsInt(args[2]); if (category == -1 && PyErr_Occurred()) { goto exit; } @@ -599,4 +595,4 @@ _locale_getencoding(PyObject *module, PyObject *Py_UNUSED(ignored)) #ifndef _LOCALE_BIND_TEXTDOMAIN_CODESET_METHODDEF #define _LOCALE_BIND_TEXTDOMAIN_CODESET_METHODDEF #endif /* !defined(_LOCALE_BIND_TEXTDOMAIN_CODESET_METHODDEF) */ -/*[clinic end generated code: output=9dbd0b4bf5767edd input=a9049054013a1b77]*/ +/*[clinic end generated code: output=034a3c219466d207 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_lsprof.c.h b/Modules/clinic/_lsprof.c.h index 5fcc7ae02e3b00..dfc003eb54774c 100644 --- a/Modules/clinic/_lsprof.c.h +++ b/Modules/clinic/_lsprof.c.h @@ -2,12 +2,6 @@ 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(_lsprof_Profiler_getstats__doc__, "getstats($self, /)\n" "--\n" @@ -51,4 +45,4 @@ _lsprof_Profiler_getstats(ProfilerObject *self, PyTypeObject *cls, PyObject *con } return _lsprof_Profiler_getstats_impl(self, cls); } -/*[clinic end generated code: output=7425d3481349629a input=a9049054013a1b77]*/ +/*[clinic end generated code: output=0615a53cce828f06 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_lzmamodule.c.h b/Modules/clinic/_lzmamodule.c.h index 9b396a56683921..51fab5eab3f7dc 100644 --- a/Modules/clinic/_lzmamodule.c.h +++ b/Modules/clinic/_lzmamodule.c.h @@ -3,10 +3,11 @@ 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() +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() #endif - +#include "pycore_abstract.h" // _PyNumber_Index() +#include "pycore_modsupport.h" // _PyArg_BadArgument() PyDoc_STRVAR(_lzma_LZMACompressor_compress__doc__, "compress($self, data, /)\n" @@ -34,10 +35,6 @@ _lzma_LZMACompressor_compress(Compressor *self, PyObject *arg) if (PyObject_GetBuffer(arg, &data, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("compress", "argument", "contiguous buffer", arg); - goto exit; - } return_value = _lzma_LZMACompressor_compress_impl(self, &data); exit: @@ -138,10 +135,6 @@ _lzma_LZMADecompressor_decompress(Decompressor *self, PyObject *const *args, Py_ if (PyObject_GetBuffer(args[0], &data, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("decompress", "argument 'data'", "contiguous buffer", args[0]); - goto exit; - } if (!noptargs) { goto skip_optional_pos; } @@ -241,7 +234,7 @@ _lzma_LZMADecompressor(PyTypeObject *type, PyObject *args, PyObject *kwargs) goto skip_optional_pos; } if (fastargs[0]) { - format = _PyLong_AsInt(fastargs[0]); + format = PyLong_AsInt(fastargs[0]); if (format == -1 && PyErr_Occurred()) { goto exit; } @@ -283,7 +276,7 @@ _lzma_is_check_supported(PyObject *module, PyObject *arg) PyObject *return_value = NULL; int check_id; - check_id = _PyLong_AsInt(arg); + check_id = PyLong_AsInt(arg); if (check_id == -1 && PyErr_Occurred()) { goto exit; } @@ -324,10 +317,6 @@ _lzma__decode_filter_properties(PyObject *module, PyObject *const *args, Py_ssiz if (PyObject_GetBuffer(args[1], &encoded_props, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&encoded_props, 'C')) { - _PyArg_BadArgument("_decode_filter_properties", "argument 2", "contiguous buffer", args[1]); - goto exit; - } return_value = _lzma__decode_filter_properties_impl(module, filter_id, &encoded_props); exit: @@ -338,4 +327,4 @@ _lzma__decode_filter_properties(PyObject *module, PyObject *const *args, Py_ssiz return return_value; } -/*[clinic end generated code: output=96c1fbdada1ef232 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=5e79c05ace76dc96 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_opcode.c.h b/Modules/clinic/_opcode.c.h index e1fc5ba17f7078..c7fd0f9f8a7420 100644 --- a/Modules/clinic/_opcode.c.h +++ b/Modules/clinic/_opcode.c.h @@ -3,10 +3,10 @@ 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() +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() #endif - +#include "pycore_modsupport.h" // _PyArg_UnpackKeywords() PyDoc_STRVAR(_opcode_stack_effect__doc__, "stack_effect($module, opcode, oparg=None, /, *, jump=None)\n" @@ -61,7 +61,7 @@ _opcode_stack_effect(PyObject *module, PyObject *const *args, Py_ssize_t nargs, if (!args) { goto exit; } - opcode = _PyLong_AsInt(args[0]); + opcode = PyLong_AsInt(args[0]); if (opcode == -1 && PyErr_Occurred()) { goto exit; } @@ -135,7 +135,7 @@ _opcode_is_valid(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyOb if (!args) { goto exit; } - opcode = _PyLong_AsInt(args[0]); + opcode = PyLong_AsInt(args[0]); if (opcode == -1 && PyErr_Occurred()) { goto exit; } @@ -198,7 +198,7 @@ _opcode_has_arg(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObj if (!args) { goto exit; } - opcode = _PyLong_AsInt(args[0]); + opcode = PyLong_AsInt(args[0]); if (opcode == -1 && PyErr_Occurred()) { goto exit; } @@ -261,7 +261,7 @@ _opcode_has_const(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyO if (!args) { goto exit; } - opcode = _PyLong_AsInt(args[0]); + opcode = PyLong_AsInt(args[0]); if (opcode == -1 && PyErr_Occurred()) { goto exit; } @@ -324,7 +324,7 @@ _opcode_has_name(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyOb if (!args) { goto exit; } - opcode = _PyLong_AsInt(args[0]); + opcode = PyLong_AsInt(args[0]); if (opcode == -1 && PyErr_Occurred()) { goto exit; } @@ -387,7 +387,7 @@ _opcode_has_jump(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyOb if (!args) { goto exit; } - opcode = _PyLong_AsInt(args[0]); + opcode = PyLong_AsInt(args[0]); if (opcode == -1 && PyErr_Occurred()) { goto exit; } @@ -455,7 +455,7 @@ _opcode_has_free(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyOb if (!args) { goto exit; } - opcode = _PyLong_AsInt(args[0]); + opcode = PyLong_AsInt(args[0]); if (opcode == -1 && PyErr_Occurred()) { goto exit; } @@ -518,7 +518,7 @@ _opcode_has_local(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyO if (!args) { goto exit; } - opcode = _PyLong_AsInt(args[0]); + opcode = PyLong_AsInt(args[0]); if (opcode == -1 && PyErr_Occurred()) { goto exit; } @@ -581,7 +581,7 @@ _opcode_has_exc(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObj if (!args) { goto exit; } - opcode = _PyLong_AsInt(args[0]); + opcode = PyLong_AsInt(args[0]); if (opcode == -1 && PyErr_Occurred()) { goto exit; } @@ -613,6 +613,26 @@ _opcode_get_specialization_stats(PyObject *module, PyObject *Py_UNUSED(ignored)) return _opcode_get_specialization_stats_impl(module); } +PyDoc_STRVAR(_opcode_get_nb_ops__doc__, +"get_nb_ops($module, /)\n" +"--\n" +"\n" +"Return array of symbols of binary ops.\n" +"\n" +"Indexed by the BINARY_OP oparg value."); + +#define _OPCODE_GET_NB_OPS_METHODDEF \ + {"get_nb_ops", (PyCFunction)_opcode_get_nb_ops, METH_NOARGS, _opcode_get_nb_ops__doc__}, + +static PyObject * +_opcode_get_nb_ops_impl(PyObject *module); + +static PyObject * +_opcode_get_nb_ops(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _opcode_get_nb_ops_impl(module); +} + PyDoc_STRVAR(_opcode_get_intrinsic1_descs__doc__, "get_intrinsic1_descs($module, /)\n" "--\n" @@ -648,4 +668,4 @@ _opcode_get_intrinsic2_descs(PyObject *module, PyObject *Py_UNUSED(ignored)) { return _opcode_get_intrinsic2_descs_impl(module); } -/*[clinic end generated code: output=d85de5f2887b3661 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=a1052bb1deffb7f2 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_operator.c.h b/Modules/clinic/_operator.c.h index b68e6e0144a586..08615d690922a1 100644 --- a/Modules/clinic/_operator.c.h +++ b/Modules/clinic/_operator.c.h @@ -2,11 +2,8 @@ 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 - +#include "pycore_abstract.h" // _PyNumber_Index() +#include "pycore_modsupport.h" // _PyArg_CheckPositional() PyDoc_STRVAR(_operator_truth__doc__, "truth($module, a, /)\n" @@ -1492,4 +1489,4 @@ _operator__compare_digest(PyObject *module, PyObject *const *args, Py_ssize_t na exit: return return_value; } -/*[clinic end generated code: output=227cbcfed44f736e input=a9049054013a1b77]*/ +/*[clinic end generated code: output=ddbba2cd943571eb input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_pickle.c.h b/Modules/clinic/_pickle.c.h index 539acc34a05cc1..fb086925e3941d 100644 --- a/Modules/clinic/_pickle.c.h +++ b/Modules/clinic/_pickle.c.h @@ -3,10 +3,10 @@ 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() +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() #endif - +#include "pycore_modsupport.h" // _PyArg_UnpackKeywords() PyDoc_STRVAR(_pickle_Pickler_clear_memo__doc__, "clear_memo($self, /)\n" @@ -266,6 +266,49 @@ _pickle_PicklerMemoProxy___reduce__(PicklerMemoProxyObject *self, PyObject *Py_U return _pickle_PicklerMemoProxy___reduce___impl(self); } +PyDoc_STRVAR(_pickle_Unpickler_persistent_load__doc__, +"persistent_load($self, pid, /)\n" +"--\n" +"\n"); + +#define _PICKLE_UNPICKLER_PERSISTENT_LOAD_METHODDEF \ + {"persistent_load", _PyCFunction_CAST(_pickle_Unpickler_persistent_load), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _pickle_Unpickler_persistent_load__doc__}, + +static PyObject * +_pickle_Unpickler_persistent_load_impl(UnpicklerObject *self, + PyTypeObject *cls, PyObject *pid); + +static PyObject * +_pickle_Unpickler_persistent_load(UnpicklerObject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + # define KWTUPLE (PyObject *)&_Py_SINGLETON(tuple_empty) + #else + # define KWTUPLE NULL + #endif + + static const char * const _keywords[] = {"", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "persistent_load", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + PyObject *pid; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + pid = args[0]; + return_value = _pickle_Unpickler_persistent_load_impl(self, cls, pid); + +exit: + return return_value; +} + PyDoc_STRVAR(_pickle_Unpickler_load__doc__, "load($self, /)\n" "--\n" @@ -1034,4 +1077,4 @@ _pickle_loads(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObjec exit: return return_value; } -/*[clinic end generated code: output=a0e04b85e7bae626 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=ebe78653233827a6 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_posixsubprocess.c.h b/Modules/clinic/_posixsubprocess.c.h index f08878cf668908..dd7644de6b7534 100644 --- a/Modules/clinic/_posixsubprocess.c.h +++ b/Modules/clinic/_posixsubprocess.c.h @@ -2,11 +2,7 @@ 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 - +#include "pycore_modsupport.h" // _PyArg_CheckPositional() PyDoc_STRVAR(subprocess_fork_exec__doc__, "fork_exec($module, args, executable_list, close_fds, pass_fds, cwd,\n" @@ -98,35 +94,35 @@ subprocess_fork_exec(PyObject *module, PyObject *const *args, Py_ssize_t nargs) py_fds_to_keep = args[3]; cwd_obj = args[4]; env_list = args[5]; - p2cread = _PyLong_AsInt(args[6]); + p2cread = PyLong_AsInt(args[6]); if (p2cread == -1 && PyErr_Occurred()) { goto exit; } - p2cwrite = _PyLong_AsInt(args[7]); + p2cwrite = PyLong_AsInt(args[7]); if (p2cwrite == -1 && PyErr_Occurred()) { goto exit; } - c2pread = _PyLong_AsInt(args[8]); + c2pread = PyLong_AsInt(args[8]); if (c2pread == -1 && PyErr_Occurred()) { goto exit; } - c2pwrite = _PyLong_AsInt(args[9]); + c2pwrite = PyLong_AsInt(args[9]); if (c2pwrite == -1 && PyErr_Occurred()) { goto exit; } - errread = _PyLong_AsInt(args[10]); + errread = PyLong_AsInt(args[10]); if (errread == -1 && PyErr_Occurred()) { goto exit; } - errwrite = _PyLong_AsInt(args[11]); + errwrite = PyLong_AsInt(args[11]); if (errwrite == -1 && PyErr_Occurred()) { goto exit; } - errpipe_read = _PyLong_AsInt(args[12]); + errpipe_read = PyLong_AsInt(args[12]); if (errpipe_read == -1 && PyErr_Occurred()) { goto exit; } - errpipe_write = _PyLong_AsInt(args[13]); + errpipe_write = PyLong_AsInt(args[13]); if (errpipe_write == -1 && PyErr_Occurred()) { goto exit; } @@ -145,7 +141,7 @@ subprocess_fork_exec(PyObject *module, PyObject *const *args, Py_ssize_t nargs) gid_object = args[17]; extra_groups_packed = args[18]; uid_object = args[19]; - child_umask = _PyLong_AsInt(args[20]); + child_umask = PyLong_AsInt(args[20]); if (child_umask == -1 && PyErr_Occurred()) { goto exit; } @@ -159,4 +155,4 @@ subprocess_fork_exec(PyObject *module, PyObject *const *args, Py_ssize_t nargs) exit: return return_value; } -/*[clinic end generated code: output=46d71e86845c93d7 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=48555f5965a871be input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_queuemodule.c.h b/Modules/clinic/_queuemodule.c.h index 94fb59a5b17a49..8e2a430835e35f 100644 --- a/Modules/clinic/_queuemodule.c.h +++ b/Modules/clinic/_queuemodule.c.h @@ -3,10 +3,10 @@ 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() +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() #endif - +#include "pycore_modsupport.h" // _PyArg_NoKeywords() PyDoc_STRVAR(simplequeue_new__doc__, "SimpleQueue()\n" @@ -331,4 +331,4 @@ _queue_SimpleQueue_qsize(simplequeueobject *self, PyObject *Py_UNUSED(ignored)) exit: return return_value; } -/*[clinic end generated code: output=9a72a8d1b5767f6a input=a9049054013a1b77]*/ +/*[clinic end generated code: output=457310b20cb61cf8 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_randommodule.c.h b/Modules/clinic/_randommodule.c.h index ec8531ce006649..6193acac67e7ac 100644 --- a/Modules/clinic/_randommodule.c.h +++ b/Modules/clinic/_randommodule.c.h @@ -2,11 +2,8 @@ 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 - +#include "pycore_critical_section.h"// Py_BEGIN_CRITICAL_SECTION() +#include "pycore_modsupport.h" // _PyArg_CheckPositional() PyDoc_STRVAR(_random_Random_random__doc__, "random($self, /)\n" @@ -23,7 +20,13 @@ _random_Random_random_impl(RandomObject *self); static PyObject * _random_Random_random(RandomObject *self, PyObject *Py_UNUSED(ignored)) { - return _random_Random_random_impl(self); + PyObject *return_value = NULL; + + Py_BEGIN_CRITICAL_SECTION(self); + return_value = _random_Random_random_impl(self); + Py_END_CRITICAL_SECTION(); + + return return_value; } PyDoc_STRVAR(_random_Random_seed__doc__, @@ -55,7 +58,9 @@ _random_Random_seed(RandomObject *self, PyObject *const *args, Py_ssize_t nargs) } n = args[0]; skip_optional: + Py_BEGIN_CRITICAL_SECTION(self); return_value = _random_Random_seed_impl(self, n); + Py_END_CRITICAL_SECTION(); exit: return return_value; @@ -76,7 +81,13 @@ _random_Random_getstate_impl(RandomObject *self); static PyObject * _random_Random_getstate(RandomObject *self, PyObject *Py_UNUSED(ignored)) { - return _random_Random_getstate_impl(self); + PyObject *return_value = NULL; + + Py_BEGIN_CRITICAL_SECTION(self); + return_value = _random_Random_getstate_impl(self); + Py_END_CRITICAL_SECTION(); + + return return_value; } PyDoc_STRVAR(_random_Random_setstate__doc__, @@ -88,6 +99,21 @@ PyDoc_STRVAR(_random_Random_setstate__doc__, #define _RANDOM_RANDOM_SETSTATE_METHODDEF \ {"setstate", (PyCFunction)_random_Random_setstate, METH_O, _random_Random_setstate__doc__}, +static PyObject * +_random_Random_setstate_impl(RandomObject *self, PyObject *state); + +static PyObject * +_random_Random_setstate(RandomObject *self, PyObject *state) +{ + PyObject *return_value = NULL; + + Py_BEGIN_CRITICAL_SECTION(self); + return_value = _random_Random_setstate_impl(self, state); + Py_END_CRITICAL_SECTION(); + + return return_value; +} + PyDoc_STRVAR(_random_Random_getrandbits__doc__, "getrandbits($self, k, /)\n" "--\n" @@ -106,13 +132,15 @@ _random_Random_getrandbits(RandomObject *self, PyObject *arg) PyObject *return_value = NULL; int k; - k = _PyLong_AsInt(arg); + k = PyLong_AsInt(arg); if (k == -1 && PyErr_Occurred()) { goto exit; } + Py_BEGIN_CRITICAL_SECTION(self); return_value = _random_Random_getrandbits_impl(self, k); + Py_END_CRITICAL_SECTION(); exit: return return_value; } -/*[clinic end generated code: output=bc17406a886824fc input=a9049054013a1b77]*/ +/*[clinic end generated code: output=bf49ece1d341b1b6 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_ssl.c.h b/Modules/clinic/_ssl.c.h index 9f967ddc8e3061..19c0f619b92f45 100644 --- a/Modules/clinic/_ssl.c.h +++ b/Modules/clinic/_ssl.c.h @@ -3,10 +3,11 @@ 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() +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() #endif - +#include "pycore_abstract.h" // _PyNumber_Index() +#include "pycore_modsupport.h" // _PyArg_CheckPositional() PyDoc_STRVAR(_ssl__SSLSocket_do_handshake__doc__, "do_handshake($self, /)\n" @@ -236,10 +237,6 @@ _ssl__SSLSocket_write(PySSLSocket *self, PyObject *arg) if (PyObject_GetBuffer(arg, &b, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&b, 'C')) { - _PyArg_BadArgument("write", "argument", "contiguous buffer", arg); - goto exit; - } return_value = _ssl__SSLSocket_write_impl(self, &b); exit: @@ -445,7 +442,7 @@ _ssl__SSLContext(PyTypeObject *type, PyObject *args, PyObject *kwargs) if (!_PyArg_CheckPositional("_SSLContext", PyTuple_GET_SIZE(args), 1, 1)) { goto exit; } - proto_version = _PyLong_AsInt(PyTuple_GET_ITEM(args, 0)); + proto_version = PyLong_AsInt(PyTuple_GET_ITEM(args, 0)); if (proto_version == -1 && PyErr_Occurred()) { goto exit; } @@ -529,10 +526,6 @@ _ssl__SSLContext__set_alpn_protocols(PySSLContext *self, PyObject *arg) if (PyObject_GetBuffer(arg, &protos, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&protos, 'C')) { - _PyArg_BadArgument("_set_alpn_protocols", "argument", "contiguous buffer", arg); - goto exit; - } return_value = _ssl__SSLContext__set_alpn_protocols_impl(self, &protos); exit: @@ -1021,6 +1014,141 @@ _ssl__SSLContext_get_ca_certs(PySSLContext *self, PyObject *const *args, Py_ssiz return return_value; } +PyDoc_STRVAR(_ssl__SSLContext_set_psk_client_callback__doc__, +"set_psk_client_callback($self, /, callback)\n" +"--\n" +"\n"); + +#define _SSL__SSLCONTEXT_SET_PSK_CLIENT_CALLBACK_METHODDEF \ + {"set_psk_client_callback", _PyCFunction_CAST(_ssl__SSLContext_set_psk_client_callback), METH_FASTCALL|METH_KEYWORDS, _ssl__SSLContext_set_psk_client_callback__doc__}, + +static PyObject * +_ssl__SSLContext_set_psk_client_callback_impl(PySSLContext *self, + PyObject *callback); + +static PyObject * +_ssl__SSLContext_set_psk_client_callback(PySSLContext *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(callback), }, + }; + #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[] = {"callback", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "set_psk_client_callback", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + PyObject *callback; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + callback = args[0]; + return_value = _ssl__SSLContext_set_psk_client_callback_impl(self, callback); + +exit: + return return_value; +} + +PyDoc_STRVAR(_ssl__SSLContext_set_psk_server_callback__doc__, +"set_psk_server_callback($self, /, callback, identity_hint=None)\n" +"--\n" +"\n"); + +#define _SSL__SSLCONTEXT_SET_PSK_SERVER_CALLBACK_METHODDEF \ + {"set_psk_server_callback", _PyCFunction_CAST(_ssl__SSLContext_set_psk_server_callback), METH_FASTCALL|METH_KEYWORDS, _ssl__SSLContext_set_psk_server_callback__doc__}, + +static PyObject * +_ssl__SSLContext_set_psk_server_callback_impl(PySSLContext *self, + PyObject *callback, + const char *identity_hint); + +static PyObject * +_ssl__SSLContext_set_psk_server_callback(PySSLContext *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 2 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(callback), &_Py_ID(identity_hint), }, + }; + #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[] = {"callback", "identity_hint", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "set_psk_server_callback", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[2]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + PyObject *callback; + const char *identity_hint = NULL; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 2, 0, argsbuf); + if (!args) { + goto exit; + } + callback = args[0]; + if (!noptargs) { + goto skip_optional_pos; + } + if (args[1] == Py_None) { + identity_hint = NULL; + } + else if (PyUnicode_Check(args[1])) { + Py_ssize_t identity_hint_length; + identity_hint = PyUnicode_AsUTF8AndSize(args[1], &identity_hint_length); + if (identity_hint == NULL) { + goto exit; + } + if (strlen(identity_hint) != (size_t)identity_hint_length) { + PyErr_SetString(PyExc_ValueError, "embedded null character"); + goto exit; + } + } + else { + _PyArg_BadArgument("set_psk_server_callback", "argument 'identity_hint'", "str or None", args[1]); + goto exit; + } +skip_optional_pos: + return_value = _ssl__SSLContext_set_psk_server_callback_impl(self, callback, identity_hint); + +exit: + return return_value; +} + static PyObject * _ssl_MemoryBIO_impl(PyTypeObject *type); @@ -1073,7 +1201,7 @@ _ssl_MemoryBIO_read(PySSLMemoryBIO *self, PyObject *const *args, Py_ssize_t narg if (nargs < 1) { goto skip_optional; } - len = _PyLong_AsInt(args[0]); + len = PyLong_AsInt(args[0]); if (len == -1 && PyErr_Occurred()) { goto exit; } @@ -1107,10 +1235,6 @@ _ssl_MemoryBIO_write(PySSLMemoryBIO *self, PyObject *arg) if (PyObject_GetBuffer(arg, &b, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&b, 'C')) { - _PyArg_BadArgument("write", "argument", "contiguous buffer", arg); - goto exit; - } return_value = _ssl_MemoryBIO_write_impl(self, &b); exit: @@ -1179,10 +1303,6 @@ _ssl_RAND_add(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (PyObject_GetBuffer(args[0], &view, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&view, 'C')) { - _PyArg_BadArgument("RAND_add", "argument 1", "contiguous buffer", args[0]); - goto exit; - } } if (PyFloat_CheckExact(args[1])) { entropy = PyFloat_AS_DOUBLE(args[1]); @@ -1223,7 +1343,7 @@ _ssl_RAND_bytes(PyObject *module, PyObject *arg) PyObject *return_value = NULL; int n; - n = _PyLong_AsInt(arg); + n = PyLong_AsInt(arg); if (n == -1 && PyErr_Occurred()) { goto exit; } @@ -1372,7 +1492,7 @@ _ssl_nid2obj(PyObject *module, PyObject *arg) PyObject *return_value = NULL; int nid; - nid = _PyLong_AsInt(arg); + nid = PyLong_AsInt(arg); if (nid == -1 && PyErr_Occurred()) { goto exit; } @@ -1542,4 +1662,4 @@ _ssl_enum_crls(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObje #ifndef _SSL_ENUM_CRLS_METHODDEF #define _SSL_ENUM_CRLS_METHODDEF #endif /* !defined(_SSL_ENUM_CRLS_METHODDEF) */ -/*[clinic end generated code: output=4d9b81fa81f520f0 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=6342ea0062ab16c7 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_statisticsmodule.c.h b/Modules/clinic/_statisticsmodule.c.h index 4dedadd2939ad6..653a2138aaad70 100644 --- a/Modules/clinic/_statisticsmodule.c.h +++ b/Modules/clinic/_statisticsmodule.c.h @@ -2,11 +2,7 @@ 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 - +#include "pycore_modsupport.h" // _PyArg_CheckPositional() PyDoc_STRVAR(_statistics__normal_dist_inv_cdf__doc__, "_normal_dist_inv_cdf($module, p, mu, sigma, /)\n" @@ -71,4 +67,4 @@ _statistics__normal_dist_inv_cdf(PyObject *module, PyObject *const *args, Py_ssi exit: return return_value; } -/*[clinic end generated code: output=6899dc752cc6b457 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=e7cead17f9f3e19f input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_struct.c.h b/Modules/clinic/_struct.c.h index c3cf179ed4c040..1a07532bdd75ad 100644 --- a/Modules/clinic/_struct.c.h +++ b/Modules/clinic/_struct.c.h @@ -3,12 +3,13 @@ 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() +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() #endif +#include "pycore_abstract.h" // _PyNumber_Index() +#include "pycore_modsupport.h" // _PyArg_UnpackKeywords() - -PyDoc_STRVAR(Struct__doc__, +PyDoc_STRVAR(Struct___init____doc__, "Struct(format)\n" "--\n" "\n" @@ -19,13 +20,13 @@ PyDoc_STRVAR(Struct__doc__, "\n" "See help(struct) for more on format strings."); -static PyObject * -Struct_impl(PyTypeObject *type, PyObject *format); +static int +Struct___init___impl(PyStructObject *self, PyObject *format); -static PyObject * -Struct(PyTypeObject *type, PyObject *args, PyObject *kwargs) +static int +Struct___init__(PyObject *self, PyObject *args, PyObject *kwargs) { - PyObject *return_value = NULL; + int return_value = -1; #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) #define NUM_KEYWORDS 1 @@ -61,7 +62,7 @@ Struct(PyTypeObject *type, PyObject *args, PyObject *kwargs) goto exit; } format = fastargs[0]; - return_value = Struct_impl(type, format); + return_value = Struct___init___impl((PyStructObject *)self, format); exit: return return_value; @@ -93,10 +94,6 @@ Struct_unpack(PyStructObject *self, PyObject *arg) if (PyObject_GetBuffer(arg, &buffer, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&buffer, 'C')) { - _PyArg_BadArgument("unpack", "argument", "contiguous buffer", arg); - goto exit; - } return_value = Struct_unpack_impl(self, &buffer); exit: @@ -169,10 +166,6 @@ Struct_unpack_from(PyStructObject *self, PyObject *const *args, Py_ssize_t nargs if (PyObject_GetBuffer(args[0], &buffer, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&buffer, 'C')) { - _PyArg_BadArgument("unpack_from", "argument 'buffer'", "contiguous buffer", args[0]); - goto exit; - } if (!noptargs) { goto skip_optional_pos; } @@ -299,10 +292,6 @@ unpack(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (PyObject_GetBuffer(args[1], &buffer, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&buffer, 'C')) { - _PyArg_BadArgument("unpack", "argument 2", "contiguous buffer", args[1]); - goto exit; - } return_value = unpack_impl(module, s_object, &buffer); exit: @@ -378,10 +367,6 @@ unpack_from(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject if (PyObject_GetBuffer(args[1], &buffer, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&buffer, 'C')) { - _PyArg_BadArgument("unpack_from", "argument 'buffer'", "contiguous buffer", args[1]); - goto exit; - } if (!noptargs) { goto skip_optional_pos; } @@ -451,4 +436,4 @@ iter_unpack(PyObject *module, PyObject *const *args, Py_ssize_t nargs) return return_value; } -/*[clinic end generated code: output=f3d6e06f80368998 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=67bd299e5d72fee0 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_suggestions.c.h b/Modules/clinic/_suggestions.c.h new file mode 100644 index 00000000000000..51484b13d5af89 --- /dev/null +++ b/Modules/clinic/_suggestions.c.h @@ -0,0 +1,41 @@ +/*[clinic input] +preserve +[clinic start generated code]*/ + +#include "pycore_modsupport.h" // _PyArg_CheckPositional() + +PyDoc_STRVAR(_suggestions__generate_suggestions__doc__, +"_generate_suggestions($module, candidates, item, /)\n" +"--\n" +"\n" +"Returns the candidate in candidates that\'s closest to item"); + +#define _SUGGESTIONS__GENERATE_SUGGESTIONS_METHODDEF \ + {"_generate_suggestions", _PyCFunction_CAST(_suggestions__generate_suggestions), METH_FASTCALL, _suggestions__generate_suggestions__doc__}, + +static PyObject * +_suggestions__generate_suggestions_impl(PyObject *module, + PyObject *candidates, PyObject *item); + +static PyObject * +_suggestions__generate_suggestions(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *candidates; + PyObject *item; + + if (!_PyArg_CheckPositional("_generate_suggestions", nargs, 2, 2)) { + goto exit; + } + candidates = args[0]; + if (!PyUnicode_Check(args[1])) { + _PyArg_BadArgument("_generate_suggestions", "argument 2", "str", args[1]); + goto exit; + } + item = args[1]; + return_value = _suggestions__generate_suggestions_impl(module, candidates, item); + +exit: + return return_value; +} +/*[clinic end generated code: output=1d8e963cdae30b13 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_sysconfig.c.h b/Modules/clinic/_sysconfig.c.h new file mode 100644 index 00000000000000..eb3d396298bb21 --- /dev/null +++ b/Modules/clinic/_sysconfig.c.h @@ -0,0 +1,22 @@ +/*[clinic input] +preserve +[clinic start generated code]*/ + +PyDoc_STRVAR(_sysconfig_config_vars__doc__, +"config_vars($module, /)\n" +"--\n" +"\n" +"Returns a dictionary containing build variables intended to be exposed by sysconfig."); + +#define _SYSCONFIG_CONFIG_VARS_METHODDEF \ + {"config_vars", (PyCFunction)_sysconfig_config_vars, METH_NOARGS, _sysconfig_config_vars__doc__}, + +static PyObject * +_sysconfig_config_vars_impl(PyObject *module); + +static PyObject * +_sysconfig_config_vars(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _sysconfig_config_vars_impl(module); +} +/*[clinic end generated code: output=25d395cf02eced1f input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_testclinic.c.h b/Modules/clinic/_testclinic.c.h index 51c3a7824dbebd..fea30e778381de 100644 --- a/Modules/clinic/_testclinic.c.h +++ b/Modules/clinic/_testclinic.c.h @@ -3,10 +3,12 @@ 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() +# include "pycore_gc.h" // PyGC_Head #endif - +#include "pycore_abstract.h" // _PyNumber_Index() +#include "pycore_long.h" // _PyLong_UnsignedShort_Converter() +#include "pycore_modsupport.h" // _PyArg_CheckPositional() +#include "pycore_runtime.h" // _Py_ID() PyDoc_STRVAR(test_empty_function__doc__, "test_empty_function($module, /)\n" @@ -181,7 +183,7 @@ bool_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (nargs < 3) { goto skip_optional; } - c = _PyLong_AsInt(args[2]); + c = PyLong_AsInt(args[2]); if (c == -1 && PyErr_Occurred()) { goto exit; } @@ -627,14 +629,14 @@ int_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (nargs < 1) { goto skip_optional; } - a = _PyLong_AsInt(args[0]); + a = PyLong_AsInt(args[0]); if (a == -1 && PyErr_Occurred()) { goto exit; } if (nargs < 2) { goto skip_optional; } - b = _PyLong_AsInt(args[1]); + b = PyLong_AsInt(args[1]); if (b == -1 && PyErr_Occurred()) { goto exit; } @@ -2812,6 +2814,76 @@ gh_99240_double_free(PyObject *module, PyObject *const *args, Py_ssize_t nargs) return return_value; } +PyDoc_STRVAR(null_or_tuple_for_varargs__doc__, +"null_or_tuple_for_varargs($module, /, name, *constraints,\n" +" covariant=False)\n" +"--\n" +"\n" +"See https://github.com/python/cpython/issues/110864"); + +#define NULL_OR_TUPLE_FOR_VARARGS_METHODDEF \ + {"null_or_tuple_for_varargs", _PyCFunction_CAST(null_or_tuple_for_varargs), METH_FASTCALL|METH_KEYWORDS, null_or_tuple_for_varargs__doc__}, + +static PyObject * +null_or_tuple_for_varargs_impl(PyObject *module, PyObject *name, + PyObject *constraints, int covariant); + +static PyObject * +null_or_tuple_for_varargs(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(name), &_Py_ID(covariant), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"name", "covariant", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "null_or_tuple_for_varargs", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[3]; + Py_ssize_t noptargs = Py_MIN(nargs, 1) + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + PyObject *name; + PyObject *constraints = NULL; + int covariant = 0; + + args = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, 1, argsbuf); + if (!args) { + goto exit; + } + name = args[0]; + constraints = args[1]; + if (!noptargs) { + goto skip_optional_kwonly; + } + covariant = PyObject_IsTrue(args[2]); + if (covariant < 0) { + goto exit; + } +skip_optional_kwonly: + return_value = null_or_tuple_for_varargs_impl(module, name, constraints, covariant); + +exit: + Py_XDECREF(constraints); + return return_value; +} + PyDoc_STRVAR(clone_f1__doc__, "clone_f1($module, /, path)\n" "--\n" @@ -3069,4 +3141,4 @@ clone_with_conv_f2(PyObject *module, PyObject *const *args, Py_ssize_t nargs, Py exit: return return_value; } -/*[clinic end generated code: output=0de394419fefe7cf input=a9049054013a1b77]*/ +/*[clinic end generated code: output=90743ac900d60f9f input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_testclinic_depr.c.h b/Modules/clinic/_testclinic_depr.c.h new file mode 100644 index 00000000000000..732c3810408399 --- /dev/null +++ b/Modules/clinic/_testclinic_depr.c.h @@ -0,0 +1,2396 @@ +/*[clinic input] +preserve +[clinic start generated code]*/ + +#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) +# include "pycore_gc.h" // PyGC_Head +#endif +#include "pycore_abstract.h" // _PyNumber_Index() +#include "pycore_long.h" // _PyLong_UnsignedShort_Converter() +#include "pycore_modsupport.h" // _PyArg_CheckPositional() +#include "pycore_runtime.h" // _Py_ID() + +PyDoc_STRVAR(depr_star_new__doc__, +"DeprStarNew(a=None)\n" +"--\n" +"\n" +"The deprecation message should use the class name instead of __new__.\n" +"\n" +"Note: Passing positional arguments to _testclinic.DeprStarNew() is\n" +"deprecated. Parameter \'a\' will become a keyword-only parameter in\n" +"Python 3.14.\n" +""); + +static PyObject * +depr_star_new_impl(PyTypeObject *type, PyObject *a); + +// Emit compiler warnings when we get to Python 3.14. +#if PY_VERSION_HEX >= 0x030e00C0 +# error "Update the clinic input of '_testclinic.DeprStarNew.__new__'." +#elif PY_VERSION_HEX >= 0x030e00A0 +# ifdef _MSC_VER +# pragma message ("Update the clinic input of '_testclinic.DeprStarNew.__new__'.") +# else +# warning "Update the clinic input of '_testclinic.DeprStarNew.__new__'." +# endif +#endif + +static PyObject * +depr_star_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(a), }, + }; + #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[] = {"a", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "DeprStarNew", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + PyObject * const *fastargs; + Py_ssize_t nargs = PyTuple_GET_SIZE(args); + Py_ssize_t noptargs = nargs + (kwargs ? PyDict_GET_SIZE(kwargs) : 0) - 0; + PyObject *a = Py_None; + + if (nargs == 1) { + if (PyErr_WarnEx(PyExc_DeprecationWarning, + "Passing positional arguments to _testclinic.DeprStarNew() is " + "deprecated. Parameter 'a' will become a keyword-only parameter " + "in Python 3.14.", 1)) + { + goto exit; + } + } + fastargs = _PyArg_UnpackKeywords(_PyTuple_CAST(args)->ob_item, nargs, kwargs, NULL, &_parser, 0, 1, 0, argsbuf); + if (!fastargs) { + goto exit; + } + if (!noptargs) { + goto skip_optional_pos; + } + a = fastargs[0]; +skip_optional_pos: + return_value = depr_star_new_impl(type, a); + +exit: + return return_value; +} + +PyDoc_STRVAR(depr_star_new_clone__doc__, +"cloned($self, /, a=None)\n" +"--\n" +"\n" +"Note: Passing positional arguments to _testclinic.DeprStarNew.cloned()\n" +"is deprecated. Parameter \'a\' will become a keyword-only parameter in\n" +"Python 3.14.\n" +""); + +#define DEPR_STAR_NEW_CLONE_METHODDEF \ + {"cloned", _PyCFunction_CAST(depr_star_new_clone), METH_FASTCALL|METH_KEYWORDS, depr_star_new_clone__doc__}, + +static PyObject * +depr_star_new_clone_impl(PyObject *type, PyObject *a); + +// Emit compiler warnings when we get to Python 3.14. +#if PY_VERSION_HEX >= 0x030e00C0 +# error "Update the clinic input of '_testclinic.DeprStarNew.cloned'." +#elif PY_VERSION_HEX >= 0x030e00A0 +# ifdef _MSC_VER +# pragma message ("Update the clinic input of '_testclinic.DeprStarNew.cloned'.") +# else +# warning "Update the clinic input of '_testclinic.DeprStarNew.cloned'." +# endif +#endif + +static PyObject * +depr_star_new_clone(PyObject *type, 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(a), }, + }; + #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[] = {"a", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "cloned", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; + PyObject *a = Py_None; + + if (nargs == 1) { + if (PyErr_WarnEx(PyExc_DeprecationWarning, + "Passing positional arguments to _testclinic.DeprStarNew.cloned()" + " is deprecated. Parameter 'a' will become a keyword-only " + "parameter in Python 3.14.", 1)) + { + goto exit; + } + } + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf); + if (!args) { + goto exit; + } + if (!noptargs) { + goto skip_optional_pos; + } + a = args[0]; +skip_optional_pos: + return_value = depr_star_new_clone_impl(type, a); + +exit: + return return_value; +} + +PyDoc_STRVAR(depr_star_init__doc__, +"DeprStarInit(a=None)\n" +"--\n" +"\n" +"The deprecation message should use the class name instead of __init__.\n" +"\n" +"Note: Passing positional arguments to _testclinic.DeprStarInit() is\n" +"deprecated. Parameter \'a\' will become a keyword-only parameter in\n" +"Python 3.14.\n" +""); + +static int +depr_star_init_impl(PyObject *self, PyObject *a); + +// Emit compiler warnings when we get to Python 3.14. +#if PY_VERSION_HEX >= 0x030e00C0 +# error "Update the clinic input of '_testclinic.DeprStarInit.__init__'." +#elif PY_VERSION_HEX >= 0x030e00A0 +# ifdef _MSC_VER +# pragma message ("Update the clinic input of '_testclinic.DeprStarInit.__init__'.") +# else +# warning "Update the clinic input of '_testclinic.DeprStarInit.__init__'." +# endif +#endif + +static int +depr_star_init(PyObject *self, PyObject *args, PyObject *kwargs) +{ + int return_value = -1; + #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(a), }, + }; + #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[] = {"a", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "DeprStarInit", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + PyObject * const *fastargs; + Py_ssize_t nargs = PyTuple_GET_SIZE(args); + Py_ssize_t noptargs = nargs + (kwargs ? PyDict_GET_SIZE(kwargs) : 0) - 0; + PyObject *a = Py_None; + + if (nargs == 1) { + if (PyErr_WarnEx(PyExc_DeprecationWarning, + "Passing positional arguments to _testclinic.DeprStarInit() is " + "deprecated. Parameter 'a' will become a keyword-only parameter " + "in Python 3.14.", 1)) + { + goto exit; + } + } + fastargs = _PyArg_UnpackKeywords(_PyTuple_CAST(args)->ob_item, nargs, kwargs, NULL, &_parser, 0, 1, 0, argsbuf); + if (!fastargs) { + goto exit; + } + if (!noptargs) { + goto skip_optional_pos; + } + a = fastargs[0]; +skip_optional_pos: + return_value = depr_star_init_impl(self, a); + +exit: + return return_value; +} + +PyDoc_STRVAR(depr_star_init_clone__doc__, +"cloned($self, /, a=None)\n" +"--\n" +"\n" +"Note: Passing positional arguments to\n" +"_testclinic.DeprStarInit.cloned() is deprecated. Parameter \'a\' will\n" +"become a keyword-only parameter in Python 3.14.\n" +""); + +#define DEPR_STAR_INIT_CLONE_METHODDEF \ + {"cloned", _PyCFunction_CAST(depr_star_init_clone), METH_FASTCALL|METH_KEYWORDS, depr_star_init_clone__doc__}, + +static PyObject * +depr_star_init_clone_impl(PyObject *self, PyObject *a); + +// Emit compiler warnings when we get to Python 3.14. +#if PY_VERSION_HEX >= 0x030e00C0 +# error "Update the clinic input of '_testclinic.DeprStarInit.cloned'." +#elif PY_VERSION_HEX >= 0x030e00A0 +# ifdef _MSC_VER +# pragma message ("Update the clinic input of '_testclinic.DeprStarInit.cloned'.") +# else +# warning "Update the clinic input of '_testclinic.DeprStarInit.cloned'." +# endif +#endif + +static PyObject * +depr_star_init_clone(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(a), }, + }; + #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[] = {"a", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "cloned", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; + PyObject *a = Py_None; + + if (nargs == 1) { + if (PyErr_WarnEx(PyExc_DeprecationWarning, + "Passing positional arguments to " + "_testclinic.DeprStarInit.cloned() is deprecated. Parameter 'a' " + "will become a keyword-only parameter in Python 3.14.", 1)) + { + goto exit; + } + } + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf); + if (!args) { + goto exit; + } + if (!noptargs) { + goto skip_optional_pos; + } + a = args[0]; +skip_optional_pos: + return_value = depr_star_init_clone_impl(self, a); + +exit: + return return_value; +} + +static int +depr_star_init_noinline_impl(PyObject *self, PyObject *a, PyObject *b, + PyObject *c, const char *d, Py_ssize_t d_length); + +// Emit compiler warnings when we get to Python 3.14. +#if PY_VERSION_HEX >= 0x030e00C0 +# error "Update the clinic input of '_testclinic.DeprStarInitNoInline.__init__'." +#elif PY_VERSION_HEX >= 0x030e00A0 +# ifdef _MSC_VER +# pragma message ("Update the clinic input of '_testclinic.DeprStarInitNoInline.__init__'.") +# else +# warning "Update the clinic input of '_testclinic.DeprStarInitNoInline.__init__'." +# endif +#endif + +static int +depr_star_init_noinline(PyObject *self, PyObject *args, PyObject *kwargs) +{ + int return_value = -1; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 4 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(a), &_Py_ID(b), &_Py_ID(c), &_Py_ID(d), }, + }; + #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[] = {"a", "b", "c", "d", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .format = "OO|O$s#:DeprStarInitNoInline", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + Py_ssize_t nargs = PyTuple_GET_SIZE(args); + PyObject *a; + PyObject *b; + PyObject *c = Py_None; + const char *d = ""; + Py_ssize_t d_length; + + if (nargs > 1 && nargs <= 3) { + if (PyErr_WarnEx(PyExc_DeprecationWarning, + "Passing more than 1 positional argument to " + "_testclinic.DeprStarInitNoInline() is deprecated. Parameters 'b'" + " and 'c' will become keyword-only parameters in Python 3.14.", 1)) + { + goto exit; + } + } + if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser, + &a, &b, &c, &d, &d_length)) { + goto exit; + } + return_value = depr_star_init_noinline_impl(self, a, b, c, d, d_length); + +exit: + return return_value; +} + +PyDoc_STRVAR(depr_kwd_new__doc__, +"DeprKwdNew(a=None)\n" +"--\n" +"\n" +"The deprecation message should use the class name instead of __new__.\n" +"\n" +"Note: Passing keyword argument \'a\' to _testclinic.DeprKwdNew() is\n" +"deprecated. Parameter \'a\' will become positional-only in Python 3.14.\n" +""); + +static PyObject * +depr_kwd_new_impl(PyTypeObject *type, PyObject *a); + +// Emit compiler warnings when we get to Python 3.14. +#if PY_VERSION_HEX >= 0x030e00C0 +# error "Update the clinic input of '_testclinic.DeprKwdNew.__new__'." +#elif PY_VERSION_HEX >= 0x030e00A0 +# ifdef _MSC_VER +# pragma message ("Update the clinic input of '_testclinic.DeprKwdNew.__new__'.") +# else +# warning "Update the clinic input of '_testclinic.DeprKwdNew.__new__'." +# endif +#endif + +static PyObject * +depr_kwd_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(a), }, + }; + #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[] = {"a", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "DeprKwdNew", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + PyObject * const *fastargs; + Py_ssize_t nargs = PyTuple_GET_SIZE(args); + Py_ssize_t noptargs = nargs + (kwargs ? PyDict_GET_SIZE(kwargs) : 0) - 0; + PyObject *a = Py_None; + + fastargs = _PyArg_UnpackKeywords(_PyTuple_CAST(args)->ob_item, nargs, kwargs, NULL, &_parser, 0, 1, 0, argsbuf); + if (!fastargs) { + goto exit; + } + if (kwargs && PyDict_GET_SIZE(kwargs) && nargs < 1 && fastargs[0]) { + if (PyErr_WarnEx(PyExc_DeprecationWarning, + "Passing keyword argument 'a' to _testclinic.DeprKwdNew() is " + "deprecated. Parameter 'a' will become positional-only in Python " + "3.14.", 1)) + { + goto exit; + } + } + if (!noptargs) { + goto skip_optional_pos; + } + a = fastargs[0]; +skip_optional_pos: + return_value = depr_kwd_new_impl(type, a); + +exit: + return return_value; +} + +PyDoc_STRVAR(depr_kwd_init__doc__, +"DeprKwdInit(a=None)\n" +"--\n" +"\n" +"The deprecation message should use the class name instead of __init__.\n" +"\n" +"Note: Passing keyword argument \'a\' to _testclinic.DeprKwdInit() is\n" +"deprecated. Parameter \'a\' will become positional-only in Python 3.14.\n" +""); + +static int +depr_kwd_init_impl(PyObject *self, PyObject *a); + +// Emit compiler warnings when we get to Python 3.14. +#if PY_VERSION_HEX >= 0x030e00C0 +# error "Update the clinic input of '_testclinic.DeprKwdInit.__init__'." +#elif PY_VERSION_HEX >= 0x030e00A0 +# ifdef _MSC_VER +# pragma message ("Update the clinic input of '_testclinic.DeprKwdInit.__init__'.") +# else +# warning "Update the clinic input of '_testclinic.DeprKwdInit.__init__'." +# endif +#endif + +static int +depr_kwd_init(PyObject *self, PyObject *args, PyObject *kwargs) +{ + int return_value = -1; + #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(a), }, + }; + #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[] = {"a", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "DeprKwdInit", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + PyObject * const *fastargs; + Py_ssize_t nargs = PyTuple_GET_SIZE(args); + Py_ssize_t noptargs = nargs + (kwargs ? PyDict_GET_SIZE(kwargs) : 0) - 0; + PyObject *a = Py_None; + + fastargs = _PyArg_UnpackKeywords(_PyTuple_CAST(args)->ob_item, nargs, kwargs, NULL, &_parser, 0, 1, 0, argsbuf); + if (!fastargs) { + goto exit; + } + if (kwargs && PyDict_GET_SIZE(kwargs) && nargs < 1 && fastargs[0]) { + if (PyErr_WarnEx(PyExc_DeprecationWarning, + "Passing keyword argument 'a' to _testclinic.DeprKwdInit() is " + "deprecated. Parameter 'a' will become positional-only in Python " + "3.14.", 1)) + { + goto exit; + } + } + if (!noptargs) { + goto skip_optional_pos; + } + a = fastargs[0]; +skip_optional_pos: + return_value = depr_kwd_init_impl(self, a); + +exit: + return return_value; +} + +static int +depr_kwd_init_noinline_impl(PyObject *self, PyObject *a, PyObject *b, + PyObject *c, const char *d, Py_ssize_t d_length); + +// Emit compiler warnings when we get to Python 3.14. +#if PY_VERSION_HEX >= 0x030e00C0 +# error "Update the clinic input of '_testclinic.DeprKwdInitNoInline.__init__'." +#elif PY_VERSION_HEX >= 0x030e00A0 +# ifdef _MSC_VER +# pragma message ("Update the clinic input of '_testclinic.DeprKwdInitNoInline.__init__'.") +# else +# warning "Update the clinic input of '_testclinic.DeprKwdInitNoInline.__init__'." +# endif +#endif + +static int +depr_kwd_init_noinline(PyObject *self, PyObject *args, PyObject *kwargs) +{ + int return_value = -1; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 3 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(b), &_Py_ID(c), &_Py_ID(d), }, + }; + #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[] = {"", "b", "c", "d", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .format = "OO|Os#:DeprKwdInitNoInline", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + Py_ssize_t nargs = PyTuple_GET_SIZE(args); + PyObject *a; + PyObject *b; + PyObject *c = Py_None; + const char *d = ""; + Py_ssize_t d_length; + + if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser, + &a, &b, &c, &d, &d_length)) { + goto exit; + } + if (kwargs && PyDict_GET_SIZE(kwargs) && ((nargs < 2) || (nargs < 3 && PyDict_Contains(kwargs, &_Py_ID(c))))) { + if (PyErr_Occurred()) { // PyDict_Contains() above can fail + goto exit; + } + if (PyErr_WarnEx(PyExc_DeprecationWarning, + "Passing keyword arguments 'b' and 'c' to " + "_testclinic.DeprKwdInitNoInline() is deprecated. Parameters 'b' " + "and 'c' will become positional-only in Python 3.14.", 1)) + { + goto exit; + } + } + return_value = depr_kwd_init_noinline_impl(self, a, b, c, d, d_length); + +exit: + return return_value; +} + +PyDoc_STRVAR(depr_star_pos0_len1__doc__, +"depr_star_pos0_len1($module, /, a)\n" +"--\n" +"\n" +"Note: Passing positional arguments to depr_star_pos0_len1() is\n" +"deprecated. Parameter \'a\' will become a keyword-only parameter in\n" +"Python 3.14.\n" +""); + +#define DEPR_STAR_POS0_LEN1_METHODDEF \ + {"depr_star_pos0_len1", _PyCFunction_CAST(depr_star_pos0_len1), METH_FASTCALL|METH_KEYWORDS, depr_star_pos0_len1__doc__}, + +static PyObject * +depr_star_pos0_len1_impl(PyObject *module, PyObject *a); + +// Emit compiler warnings when we get to Python 3.14. +#if PY_VERSION_HEX >= 0x030e00C0 +# error "Update the clinic input of 'depr_star_pos0_len1'." +#elif PY_VERSION_HEX >= 0x030e00A0 +# ifdef _MSC_VER +# pragma message ("Update the clinic input of 'depr_star_pos0_len1'.") +# else +# warning "Update the clinic input of 'depr_star_pos0_len1'." +# endif +#endif + +static PyObject * +depr_star_pos0_len1(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(a), }, + }; + #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[] = {"a", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "depr_star_pos0_len1", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + PyObject *a; + + if (nargs == 1) { + if (PyErr_WarnEx(PyExc_DeprecationWarning, + "Passing positional arguments to depr_star_pos0_len1() is " + "deprecated. Parameter 'a' will become a keyword-only parameter " + "in Python 3.14.", 1)) + { + goto exit; + } + } + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + a = args[0]; + return_value = depr_star_pos0_len1_impl(module, a); + +exit: + return return_value; +} + +PyDoc_STRVAR(depr_star_pos0_len2__doc__, +"depr_star_pos0_len2($module, /, a, b)\n" +"--\n" +"\n" +"Note: Passing positional arguments to depr_star_pos0_len2() is\n" +"deprecated. Parameters \'a\' and \'b\' will become keyword-only parameters\n" +"in Python 3.14.\n" +""); + +#define DEPR_STAR_POS0_LEN2_METHODDEF \ + {"depr_star_pos0_len2", _PyCFunction_CAST(depr_star_pos0_len2), METH_FASTCALL|METH_KEYWORDS, depr_star_pos0_len2__doc__}, + +static PyObject * +depr_star_pos0_len2_impl(PyObject *module, PyObject *a, PyObject *b); + +// Emit compiler warnings when we get to Python 3.14. +#if PY_VERSION_HEX >= 0x030e00C0 +# error "Update the clinic input of 'depr_star_pos0_len2'." +#elif PY_VERSION_HEX >= 0x030e00A0 +# ifdef _MSC_VER +# pragma message ("Update the clinic input of 'depr_star_pos0_len2'.") +# else +# warning "Update the clinic input of 'depr_star_pos0_len2'." +# endif +#endif + +static PyObject * +depr_star_pos0_len2(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(a), &_Py_ID(b), }, + }; + #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[] = {"a", "b", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "depr_star_pos0_len2", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[2]; + PyObject *a; + PyObject *b; + + if (nargs > 0 && nargs <= 2) { + if (PyErr_WarnEx(PyExc_DeprecationWarning, + "Passing positional arguments to depr_star_pos0_len2() is " + "deprecated. Parameters 'a' and 'b' will become keyword-only " + "parameters in Python 3.14.", 1)) + { + goto exit; + } + } + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); + if (!args) { + goto exit; + } + a = args[0]; + b = args[1]; + return_value = depr_star_pos0_len2_impl(module, a, b); + +exit: + return return_value; +} + +PyDoc_STRVAR(depr_star_pos0_len3_with_kwd__doc__, +"depr_star_pos0_len3_with_kwd($module, /, a, b, c, *, d)\n" +"--\n" +"\n" +"Note: Passing positional arguments to depr_star_pos0_len3_with_kwd()\n" +"is deprecated. Parameters \'a\', \'b\' and \'c\' will become keyword-only\n" +"parameters in Python 3.14.\n" +""); + +#define DEPR_STAR_POS0_LEN3_WITH_KWD_METHODDEF \ + {"depr_star_pos0_len3_with_kwd", _PyCFunction_CAST(depr_star_pos0_len3_with_kwd), METH_FASTCALL|METH_KEYWORDS, depr_star_pos0_len3_with_kwd__doc__}, + +static PyObject * +depr_star_pos0_len3_with_kwd_impl(PyObject *module, PyObject *a, PyObject *b, + PyObject *c, PyObject *d); + +// Emit compiler warnings when we get to Python 3.14. +#if PY_VERSION_HEX >= 0x030e00C0 +# error "Update the clinic input of 'depr_star_pos0_len3_with_kwd'." +#elif PY_VERSION_HEX >= 0x030e00A0 +# ifdef _MSC_VER +# pragma message ("Update the clinic input of 'depr_star_pos0_len3_with_kwd'.") +# else +# warning "Update the clinic input of 'depr_star_pos0_len3_with_kwd'." +# endif +#endif + +static PyObject * +depr_star_pos0_len3_with_kwd(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 4 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(a), &_Py_ID(b), &_Py_ID(c), &_Py_ID(d), }, + }; + #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[] = {"a", "b", "c", "d", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "depr_star_pos0_len3_with_kwd", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[4]; + PyObject *a; + PyObject *b; + PyObject *c; + PyObject *d; + + if (nargs > 0 && nargs <= 3) { + if (PyErr_WarnEx(PyExc_DeprecationWarning, + "Passing positional arguments to depr_star_pos0_len3_with_kwd() " + "is deprecated. Parameters 'a', 'b' and 'c' will become " + "keyword-only parameters in Python 3.14.", 1)) + { + goto exit; + } + } + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 3, 3, 1, argsbuf); + if (!args) { + goto exit; + } + a = args[0]; + b = args[1]; + c = args[2]; + d = args[3]; + return_value = depr_star_pos0_len3_with_kwd_impl(module, a, b, c, d); + +exit: + return return_value; +} + +PyDoc_STRVAR(depr_star_pos1_len1_opt__doc__, +"depr_star_pos1_len1_opt($module, /, a, b=None)\n" +"--\n" +"\n" +"Note: Passing 2 positional arguments to depr_star_pos1_len1_opt() is\n" +"deprecated. Parameter \'b\' will become a keyword-only parameter in\n" +"Python 3.14.\n" +""); + +#define DEPR_STAR_POS1_LEN1_OPT_METHODDEF \ + {"depr_star_pos1_len1_opt", _PyCFunction_CAST(depr_star_pos1_len1_opt), METH_FASTCALL|METH_KEYWORDS, depr_star_pos1_len1_opt__doc__}, + +static PyObject * +depr_star_pos1_len1_opt_impl(PyObject *module, PyObject *a, PyObject *b); + +// Emit compiler warnings when we get to Python 3.14. +#if PY_VERSION_HEX >= 0x030e00C0 +# error "Update the clinic input of 'depr_star_pos1_len1_opt'." +#elif PY_VERSION_HEX >= 0x030e00A0 +# ifdef _MSC_VER +# pragma message ("Update the clinic input of 'depr_star_pos1_len1_opt'.") +# else +# warning "Update the clinic input of 'depr_star_pos1_len1_opt'." +# endif +#endif + +static PyObject * +depr_star_pos1_len1_opt(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(a), &_Py_ID(b), }, + }; + #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[] = {"a", "b", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "depr_star_pos1_len1_opt", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[2]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + PyObject *a; + PyObject *b = Py_None; + + if (nargs == 2) { + if (PyErr_WarnEx(PyExc_DeprecationWarning, + "Passing 2 positional arguments to depr_star_pos1_len1_opt() is " + "deprecated. Parameter 'b' will become a keyword-only parameter " + "in Python 3.14.", 1)) + { + goto exit; + } + } + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 2, 0, argsbuf); + if (!args) { + goto exit; + } + a = args[0]; + if (!noptargs) { + goto skip_optional_pos; + } + b = args[1]; +skip_optional_pos: + return_value = depr_star_pos1_len1_opt_impl(module, a, b); + +exit: + return return_value; +} + +PyDoc_STRVAR(depr_star_pos1_len1__doc__, +"depr_star_pos1_len1($module, /, a, b)\n" +"--\n" +"\n" +"Note: Passing 2 positional arguments to depr_star_pos1_len1() is\n" +"deprecated. Parameter \'b\' will become a keyword-only parameter in\n" +"Python 3.14.\n" +""); + +#define DEPR_STAR_POS1_LEN1_METHODDEF \ + {"depr_star_pos1_len1", _PyCFunction_CAST(depr_star_pos1_len1), METH_FASTCALL|METH_KEYWORDS, depr_star_pos1_len1__doc__}, + +static PyObject * +depr_star_pos1_len1_impl(PyObject *module, PyObject *a, PyObject *b); + +// Emit compiler warnings when we get to Python 3.14. +#if PY_VERSION_HEX >= 0x030e00C0 +# error "Update the clinic input of 'depr_star_pos1_len1'." +#elif PY_VERSION_HEX >= 0x030e00A0 +# ifdef _MSC_VER +# pragma message ("Update the clinic input of 'depr_star_pos1_len1'.") +# else +# warning "Update the clinic input of 'depr_star_pos1_len1'." +# endif +#endif + +static PyObject * +depr_star_pos1_len1(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(a), &_Py_ID(b), }, + }; + #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[] = {"a", "b", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "depr_star_pos1_len1", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[2]; + PyObject *a; + PyObject *b; + + if (nargs == 2) { + if (PyErr_WarnEx(PyExc_DeprecationWarning, + "Passing 2 positional arguments to depr_star_pos1_len1() is " + "deprecated. Parameter 'b' will become a keyword-only parameter " + "in Python 3.14.", 1)) + { + goto exit; + } + } + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); + if (!args) { + goto exit; + } + a = args[0]; + b = args[1]; + return_value = depr_star_pos1_len1_impl(module, a, b); + +exit: + return return_value; +} + +PyDoc_STRVAR(depr_star_pos1_len2_with_kwd__doc__, +"depr_star_pos1_len2_with_kwd($module, /, a, b, c, *, d)\n" +"--\n" +"\n" +"Note: Passing more than 1 positional argument to\n" +"depr_star_pos1_len2_with_kwd() is deprecated. Parameters \'b\' and \'c\'\n" +"will become keyword-only parameters in Python 3.14.\n" +""); + +#define DEPR_STAR_POS1_LEN2_WITH_KWD_METHODDEF \ + {"depr_star_pos1_len2_with_kwd", _PyCFunction_CAST(depr_star_pos1_len2_with_kwd), METH_FASTCALL|METH_KEYWORDS, depr_star_pos1_len2_with_kwd__doc__}, + +static PyObject * +depr_star_pos1_len2_with_kwd_impl(PyObject *module, PyObject *a, PyObject *b, + PyObject *c, PyObject *d); + +// Emit compiler warnings when we get to Python 3.14. +#if PY_VERSION_HEX >= 0x030e00C0 +# error "Update the clinic input of 'depr_star_pos1_len2_with_kwd'." +#elif PY_VERSION_HEX >= 0x030e00A0 +# ifdef _MSC_VER +# pragma message ("Update the clinic input of 'depr_star_pos1_len2_with_kwd'.") +# else +# warning "Update the clinic input of 'depr_star_pos1_len2_with_kwd'." +# endif +#endif + +static PyObject * +depr_star_pos1_len2_with_kwd(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 4 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(a), &_Py_ID(b), &_Py_ID(c), &_Py_ID(d), }, + }; + #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[] = {"a", "b", "c", "d", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "depr_star_pos1_len2_with_kwd", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[4]; + PyObject *a; + PyObject *b; + PyObject *c; + PyObject *d; + + if (nargs > 1 && nargs <= 3) { + if (PyErr_WarnEx(PyExc_DeprecationWarning, + "Passing more than 1 positional argument to " + "depr_star_pos1_len2_with_kwd() is deprecated. Parameters 'b' and" + " 'c' will become keyword-only parameters in Python 3.14.", 1)) + { + goto exit; + } + } + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 3, 3, 1, argsbuf); + if (!args) { + goto exit; + } + a = args[0]; + b = args[1]; + c = args[2]; + d = args[3]; + return_value = depr_star_pos1_len2_with_kwd_impl(module, a, b, c, d); + +exit: + return return_value; +} + +PyDoc_STRVAR(depr_star_pos2_len1__doc__, +"depr_star_pos2_len1($module, /, a, b, c)\n" +"--\n" +"\n" +"Note: Passing 3 positional arguments to depr_star_pos2_len1() is\n" +"deprecated. Parameter \'c\' will become a keyword-only parameter in\n" +"Python 3.14.\n" +""); + +#define DEPR_STAR_POS2_LEN1_METHODDEF \ + {"depr_star_pos2_len1", _PyCFunction_CAST(depr_star_pos2_len1), METH_FASTCALL|METH_KEYWORDS, depr_star_pos2_len1__doc__}, + +static PyObject * +depr_star_pos2_len1_impl(PyObject *module, PyObject *a, PyObject *b, + PyObject *c); + +// Emit compiler warnings when we get to Python 3.14. +#if PY_VERSION_HEX >= 0x030e00C0 +# error "Update the clinic input of 'depr_star_pos2_len1'." +#elif PY_VERSION_HEX >= 0x030e00A0 +# ifdef _MSC_VER +# pragma message ("Update the clinic input of 'depr_star_pos2_len1'.") +# else +# warning "Update the clinic input of 'depr_star_pos2_len1'." +# endif +#endif + +static PyObject * +depr_star_pos2_len1(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 3 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(a), &_Py_ID(b), &_Py_ID(c), }, + }; + #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[] = {"a", "b", "c", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "depr_star_pos2_len1", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[3]; + PyObject *a; + PyObject *b; + PyObject *c; + + if (nargs == 3) { + if (PyErr_WarnEx(PyExc_DeprecationWarning, + "Passing 3 positional arguments to depr_star_pos2_len1() is " + "deprecated. Parameter 'c' will become a keyword-only parameter " + "in Python 3.14.", 1)) + { + goto exit; + } + } + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 3, 3, 0, argsbuf); + if (!args) { + goto exit; + } + a = args[0]; + b = args[1]; + c = args[2]; + return_value = depr_star_pos2_len1_impl(module, a, b, c); + +exit: + return return_value; +} + +PyDoc_STRVAR(depr_star_pos2_len2__doc__, +"depr_star_pos2_len2($module, /, a, b, c, d)\n" +"--\n" +"\n" +"Note: Passing more than 2 positional arguments to\n" +"depr_star_pos2_len2() is deprecated. Parameters \'c\' and \'d\' will\n" +"become keyword-only parameters in Python 3.14.\n" +""); + +#define DEPR_STAR_POS2_LEN2_METHODDEF \ + {"depr_star_pos2_len2", _PyCFunction_CAST(depr_star_pos2_len2), METH_FASTCALL|METH_KEYWORDS, depr_star_pos2_len2__doc__}, + +static PyObject * +depr_star_pos2_len2_impl(PyObject *module, PyObject *a, PyObject *b, + PyObject *c, PyObject *d); + +// Emit compiler warnings when we get to Python 3.14. +#if PY_VERSION_HEX >= 0x030e00C0 +# error "Update the clinic input of 'depr_star_pos2_len2'." +#elif PY_VERSION_HEX >= 0x030e00A0 +# ifdef _MSC_VER +# pragma message ("Update the clinic input of 'depr_star_pos2_len2'.") +# else +# warning "Update the clinic input of 'depr_star_pos2_len2'." +# endif +#endif + +static PyObject * +depr_star_pos2_len2(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 4 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(a), &_Py_ID(b), &_Py_ID(c), &_Py_ID(d), }, + }; + #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[] = {"a", "b", "c", "d", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "depr_star_pos2_len2", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[4]; + PyObject *a; + PyObject *b; + PyObject *c; + PyObject *d; + + if (nargs > 2 && nargs <= 4) { + if (PyErr_WarnEx(PyExc_DeprecationWarning, + "Passing more than 2 positional arguments to " + "depr_star_pos2_len2() is deprecated. Parameters 'c' and 'd' will" + " become keyword-only parameters in Python 3.14.", 1)) + { + goto exit; + } + } + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 4, 4, 0, argsbuf); + if (!args) { + goto exit; + } + a = args[0]; + b = args[1]; + c = args[2]; + d = args[3]; + return_value = depr_star_pos2_len2_impl(module, a, b, c, d); + +exit: + return return_value; +} + +PyDoc_STRVAR(depr_star_pos2_len2_with_kwd__doc__, +"depr_star_pos2_len2_with_kwd($module, /, a, b, c, d, *, e)\n" +"--\n" +"\n" +"Note: Passing more than 2 positional arguments to\n" +"depr_star_pos2_len2_with_kwd() is deprecated. Parameters \'c\' and \'d\'\n" +"will become keyword-only parameters in Python 3.14.\n" +""); + +#define DEPR_STAR_POS2_LEN2_WITH_KWD_METHODDEF \ + {"depr_star_pos2_len2_with_kwd", _PyCFunction_CAST(depr_star_pos2_len2_with_kwd), METH_FASTCALL|METH_KEYWORDS, depr_star_pos2_len2_with_kwd__doc__}, + +static PyObject * +depr_star_pos2_len2_with_kwd_impl(PyObject *module, PyObject *a, PyObject *b, + PyObject *c, PyObject *d, PyObject *e); + +// Emit compiler warnings when we get to Python 3.14. +#if PY_VERSION_HEX >= 0x030e00C0 +# error "Update the clinic input of 'depr_star_pos2_len2_with_kwd'." +#elif PY_VERSION_HEX >= 0x030e00A0 +# ifdef _MSC_VER +# pragma message ("Update the clinic input of 'depr_star_pos2_len2_with_kwd'.") +# else +# warning "Update the clinic input of 'depr_star_pos2_len2_with_kwd'." +# endif +#endif + +static PyObject * +depr_star_pos2_len2_with_kwd(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 5 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(a), &_Py_ID(b), &_Py_ID(c), &_Py_ID(d), &_Py_ID(e), }, + }; + #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[] = {"a", "b", "c", "d", "e", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "depr_star_pos2_len2_with_kwd", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[5]; + PyObject *a; + PyObject *b; + PyObject *c; + PyObject *d; + PyObject *e; + + if (nargs > 2 && nargs <= 4) { + if (PyErr_WarnEx(PyExc_DeprecationWarning, + "Passing more than 2 positional arguments to " + "depr_star_pos2_len2_with_kwd() is deprecated. Parameters 'c' and" + " 'd' will become keyword-only parameters in Python 3.14.", 1)) + { + goto exit; + } + } + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 4, 4, 1, argsbuf); + if (!args) { + goto exit; + } + a = args[0]; + b = args[1]; + c = args[2]; + d = args[3]; + e = args[4]; + return_value = depr_star_pos2_len2_with_kwd_impl(module, a, b, c, d, e); + +exit: + return return_value; +} + +PyDoc_STRVAR(depr_star_noinline__doc__, +"depr_star_noinline($module, /, a, b, c=None, *, d=\'\')\n" +"--\n" +"\n" +"Note: Passing more than 1 positional argument to depr_star_noinline()\n" +"is deprecated. Parameters \'b\' and \'c\' will become keyword-only\n" +"parameters in Python 3.14.\n" +""); + +#define DEPR_STAR_NOINLINE_METHODDEF \ + {"depr_star_noinline", _PyCFunction_CAST(depr_star_noinline), METH_FASTCALL|METH_KEYWORDS, depr_star_noinline__doc__}, + +static PyObject * +depr_star_noinline_impl(PyObject *module, PyObject *a, PyObject *b, + PyObject *c, const char *d, Py_ssize_t d_length); + +// Emit compiler warnings when we get to Python 3.14. +#if PY_VERSION_HEX >= 0x030e00C0 +# error "Update the clinic input of 'depr_star_noinline'." +#elif PY_VERSION_HEX >= 0x030e00A0 +# ifdef _MSC_VER +# pragma message ("Update the clinic input of 'depr_star_noinline'.") +# else +# warning "Update the clinic input of 'depr_star_noinline'." +# endif +#endif + +static PyObject * +depr_star_noinline(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 4 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(a), &_Py_ID(b), &_Py_ID(c), &_Py_ID(d), }, + }; + #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[] = {"a", "b", "c", "d", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .format = "OO|O$s#:depr_star_noinline", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *a; + PyObject *b; + PyObject *c = Py_None; + const char *d = ""; + Py_ssize_t d_length; + + if (nargs > 1 && nargs <= 3) { + if (PyErr_WarnEx(PyExc_DeprecationWarning, + "Passing more than 1 positional argument to depr_star_noinline() " + "is deprecated. Parameters 'b' and 'c' will become keyword-only " + "parameters in Python 3.14.", 1)) + { + goto exit; + } + } + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, + &a, &b, &c, &d, &d_length)) { + goto exit; + } + return_value = depr_star_noinline_impl(module, a, b, c, d, d_length); + +exit: + return return_value; +} + +PyDoc_STRVAR(depr_star_multi__doc__, +"depr_star_multi($module, /, a, b, c, d, e, f, g, *, h)\n" +"--\n" +"\n" +"Note: Passing more than 1 positional argument to depr_star_multi() is\n" +"deprecated. Parameter \'b\' will become a keyword-only parameter in\n" +"Python 3.16. Parameters \'c\' and \'d\' will become keyword-only\n" +"parameters in Python 3.15. Parameters \'e\', \'f\' and \'g\' will become\n" +"keyword-only parameters in Python 3.14.\n" +""); + +#define DEPR_STAR_MULTI_METHODDEF \ + {"depr_star_multi", _PyCFunction_CAST(depr_star_multi), METH_FASTCALL|METH_KEYWORDS, depr_star_multi__doc__}, + +static PyObject * +depr_star_multi_impl(PyObject *module, PyObject *a, PyObject *b, PyObject *c, + PyObject *d, PyObject *e, PyObject *f, PyObject *g, + PyObject *h); + +// Emit compiler warnings when we get to Python 3.14. +#if PY_VERSION_HEX >= 0x030e00C0 +# error "Update the clinic input of 'depr_star_multi'." +#elif PY_VERSION_HEX >= 0x030e00A0 +# ifdef _MSC_VER +# pragma message ("Update the clinic input of 'depr_star_multi'.") +# else +# warning "Update the clinic input of 'depr_star_multi'." +# endif +#endif + +static PyObject * +depr_star_multi(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 8 + 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(a), &_Py_ID(b), &_Py_ID(c), &_Py_ID(d), &_Py_ID(e), &_Py_ID(f), &_Py_ID(g), &_Py_ID(h), }, + }; + #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[] = {"a", "b", "c", "d", "e", "f", "g", "h", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "depr_star_multi", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[8]; + PyObject *a; + PyObject *b; + PyObject *c; + PyObject *d; + PyObject *e; + PyObject *f; + PyObject *g; + PyObject *h; + + if (nargs > 1 && nargs <= 7) { + if (PyErr_WarnEx(PyExc_DeprecationWarning, + "Passing more than 1 positional argument to depr_star_multi() is " + "deprecated. Parameter 'b' will become a keyword-only parameter " + "in Python 3.16. Parameters 'c' and 'd' will become keyword-only " + "parameters in Python 3.15. Parameters 'e', 'f' and 'g' will " + "become keyword-only parameters in Python 3.14.", 1)) + { + goto exit; + } + } + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 7, 7, 1, argsbuf); + if (!args) { + goto exit; + } + a = args[0]; + b = args[1]; + c = args[2]; + d = args[3]; + e = args[4]; + f = args[5]; + g = args[6]; + h = args[7]; + return_value = depr_star_multi_impl(module, a, b, c, d, e, f, g, h); + +exit: + return return_value; +} + +PyDoc_STRVAR(depr_kwd_required_1__doc__, +"depr_kwd_required_1($module, a, /, b)\n" +"--\n" +"\n" +"Note: Passing keyword argument \'b\' to depr_kwd_required_1() is\n" +"deprecated. Parameter \'b\' will become positional-only in Python 3.14.\n" +""); + +#define DEPR_KWD_REQUIRED_1_METHODDEF \ + {"depr_kwd_required_1", _PyCFunction_CAST(depr_kwd_required_1), METH_FASTCALL|METH_KEYWORDS, depr_kwd_required_1__doc__}, + +static PyObject * +depr_kwd_required_1_impl(PyObject *module, PyObject *a, PyObject *b); + +// Emit compiler warnings when we get to Python 3.14. +#if PY_VERSION_HEX >= 0x030e00C0 +# error "Update the clinic input of 'depr_kwd_required_1'." +#elif PY_VERSION_HEX >= 0x030e00A0 +# ifdef _MSC_VER +# pragma message ("Update the clinic input of 'depr_kwd_required_1'.") +# else +# warning "Update the clinic input of 'depr_kwd_required_1'." +# endif +#endif + +static PyObject * +depr_kwd_required_1(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(b), }, + }; + #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[] = {"", "b", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "depr_kwd_required_1", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[2]; + PyObject *a; + PyObject *b; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); + if (!args) { + goto exit; + } + if (nargs < 2) { + if (PyErr_WarnEx(PyExc_DeprecationWarning, + "Passing keyword argument 'b' to depr_kwd_required_1() is " + "deprecated. Parameter 'b' will become positional-only in Python " + "3.14.", 1)) + { + goto exit; + } + } + a = args[0]; + b = args[1]; + return_value = depr_kwd_required_1_impl(module, a, b); + +exit: + return return_value; +} + +PyDoc_STRVAR(depr_kwd_required_2__doc__, +"depr_kwd_required_2($module, a, /, b, c)\n" +"--\n" +"\n" +"Note: Passing keyword arguments \'b\' and \'c\' to depr_kwd_required_2()\n" +"is deprecated. Parameters \'b\' and \'c\' will become positional-only in\n" +"Python 3.14.\n" +""); + +#define DEPR_KWD_REQUIRED_2_METHODDEF \ + {"depr_kwd_required_2", _PyCFunction_CAST(depr_kwd_required_2), METH_FASTCALL|METH_KEYWORDS, depr_kwd_required_2__doc__}, + +static PyObject * +depr_kwd_required_2_impl(PyObject *module, PyObject *a, PyObject *b, + PyObject *c); + +// Emit compiler warnings when we get to Python 3.14. +#if PY_VERSION_HEX >= 0x030e00C0 +# error "Update the clinic input of 'depr_kwd_required_2'." +#elif PY_VERSION_HEX >= 0x030e00A0 +# ifdef _MSC_VER +# pragma message ("Update the clinic input of 'depr_kwd_required_2'.") +# else +# warning "Update the clinic input of 'depr_kwd_required_2'." +# endif +#endif + +static PyObject * +depr_kwd_required_2(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(b), &_Py_ID(c), }, + }; + #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[] = {"", "b", "c", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "depr_kwd_required_2", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[3]; + PyObject *a; + PyObject *b; + PyObject *c; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 3, 3, 0, argsbuf); + if (!args) { + goto exit; + } + if (nargs < 3) { + if (PyErr_WarnEx(PyExc_DeprecationWarning, + "Passing keyword arguments 'b' and 'c' to depr_kwd_required_2() " + "is deprecated. Parameters 'b' and 'c' will become " + "positional-only in Python 3.14.", 1)) + { + goto exit; + } + } + a = args[0]; + b = args[1]; + c = args[2]; + return_value = depr_kwd_required_2_impl(module, a, b, c); + +exit: + return return_value; +} + +PyDoc_STRVAR(depr_kwd_optional_1__doc__, +"depr_kwd_optional_1($module, a, /, b=None)\n" +"--\n" +"\n" +"Note: Passing keyword argument \'b\' to depr_kwd_optional_1() is\n" +"deprecated. Parameter \'b\' will become positional-only in Python 3.14.\n" +""); + +#define DEPR_KWD_OPTIONAL_1_METHODDEF \ + {"depr_kwd_optional_1", _PyCFunction_CAST(depr_kwd_optional_1), METH_FASTCALL|METH_KEYWORDS, depr_kwd_optional_1__doc__}, + +static PyObject * +depr_kwd_optional_1_impl(PyObject *module, PyObject *a, PyObject *b); + +// Emit compiler warnings when we get to Python 3.14. +#if PY_VERSION_HEX >= 0x030e00C0 +# error "Update the clinic input of 'depr_kwd_optional_1'." +#elif PY_VERSION_HEX >= 0x030e00A0 +# ifdef _MSC_VER +# pragma message ("Update the clinic input of 'depr_kwd_optional_1'.") +# else +# warning "Update the clinic input of 'depr_kwd_optional_1'." +# endif +#endif + +static PyObject * +depr_kwd_optional_1(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(b), }, + }; + #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[] = {"", "b", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "depr_kwd_optional_1", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[2]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + PyObject *a; + PyObject *b = Py_None; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 2, 0, argsbuf); + if (!args) { + goto exit; + } + if (kwnames && PyTuple_GET_SIZE(kwnames) && nargs < 2 && args[1]) { + if (PyErr_WarnEx(PyExc_DeprecationWarning, + "Passing keyword argument 'b' to depr_kwd_optional_1() is " + "deprecated. Parameter 'b' will become positional-only in Python " + "3.14.", 1)) + { + goto exit; + } + } + a = args[0]; + if (!noptargs) { + goto skip_optional_pos; + } + b = args[1]; +skip_optional_pos: + return_value = depr_kwd_optional_1_impl(module, a, b); + +exit: + return return_value; +} + +PyDoc_STRVAR(depr_kwd_optional_2__doc__, +"depr_kwd_optional_2($module, a, /, b=None, c=None)\n" +"--\n" +"\n" +"Note: Passing keyword arguments \'b\' and \'c\' to depr_kwd_optional_2()\n" +"is deprecated. Parameters \'b\' and \'c\' will become positional-only in\n" +"Python 3.14.\n" +""); + +#define DEPR_KWD_OPTIONAL_2_METHODDEF \ + {"depr_kwd_optional_2", _PyCFunction_CAST(depr_kwd_optional_2), METH_FASTCALL|METH_KEYWORDS, depr_kwd_optional_2__doc__}, + +static PyObject * +depr_kwd_optional_2_impl(PyObject *module, PyObject *a, PyObject *b, + PyObject *c); + +// Emit compiler warnings when we get to Python 3.14. +#if PY_VERSION_HEX >= 0x030e00C0 +# error "Update the clinic input of 'depr_kwd_optional_2'." +#elif PY_VERSION_HEX >= 0x030e00A0 +# ifdef _MSC_VER +# pragma message ("Update the clinic input of 'depr_kwd_optional_2'.") +# else +# warning "Update the clinic input of 'depr_kwd_optional_2'." +# endif +#endif + +static PyObject * +depr_kwd_optional_2(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(b), &_Py_ID(c), }, + }; + #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[] = {"", "b", "c", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "depr_kwd_optional_2", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[3]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + PyObject *a; + PyObject *b = Py_None; + PyObject *c = Py_None; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 3, 0, argsbuf); + if (!args) { + goto exit; + } + if (kwnames && PyTuple_GET_SIZE(kwnames) && ((nargs < 2 && args[1]) || (nargs < 3 && args[2]))) { + if (PyErr_WarnEx(PyExc_DeprecationWarning, + "Passing keyword arguments 'b' and 'c' to depr_kwd_optional_2() " + "is deprecated. Parameters 'b' and 'c' will become " + "positional-only in Python 3.14.", 1)) + { + goto exit; + } + } + a = args[0]; + if (!noptargs) { + goto skip_optional_pos; + } + if (args[1]) { + b = args[1]; + if (!--noptargs) { + goto skip_optional_pos; + } + } + c = args[2]; +skip_optional_pos: + return_value = depr_kwd_optional_2_impl(module, a, b, c); + +exit: + return return_value; +} + +PyDoc_STRVAR(depr_kwd_optional_3__doc__, +"depr_kwd_optional_3($module, /, a=None, b=None, c=None)\n" +"--\n" +"\n" +"Note: Passing keyword arguments \'a\', \'b\' and \'c\' to\n" +"depr_kwd_optional_3() is deprecated. Parameters \'a\', \'b\' and \'c\' will\n" +"become positional-only in Python 3.14.\n" +""); + +#define DEPR_KWD_OPTIONAL_3_METHODDEF \ + {"depr_kwd_optional_3", _PyCFunction_CAST(depr_kwd_optional_3), METH_FASTCALL|METH_KEYWORDS, depr_kwd_optional_3__doc__}, + +static PyObject * +depr_kwd_optional_3_impl(PyObject *module, PyObject *a, PyObject *b, + PyObject *c); + +// Emit compiler warnings when we get to Python 3.14. +#if PY_VERSION_HEX >= 0x030e00C0 +# error "Update the clinic input of 'depr_kwd_optional_3'." +#elif PY_VERSION_HEX >= 0x030e00A0 +# ifdef _MSC_VER +# pragma message ("Update the clinic input of 'depr_kwd_optional_3'.") +# else +# warning "Update the clinic input of 'depr_kwd_optional_3'." +# endif +#endif + +static PyObject * +depr_kwd_optional_3(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 3 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(a), &_Py_ID(b), &_Py_ID(c), }, + }; + #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[] = {"a", "b", "c", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "depr_kwd_optional_3", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[3]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; + PyObject *a = Py_None; + PyObject *b = Py_None; + PyObject *c = Py_None; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 3, 0, argsbuf); + if (!args) { + goto exit; + } + if (kwnames && PyTuple_GET_SIZE(kwnames) && ((nargs < 1 && args[0]) || (nargs < 2 && args[1]) || (nargs < 3 && args[2]))) { + if (PyErr_WarnEx(PyExc_DeprecationWarning, + "Passing keyword arguments 'a', 'b' and 'c' to " + "depr_kwd_optional_3() is deprecated. Parameters 'a', 'b' and 'c'" + " will become positional-only in Python 3.14.", 1)) + { + goto exit; + } + } + if (!noptargs) { + goto skip_optional_pos; + } + if (args[0]) { + a = args[0]; + if (!--noptargs) { + goto skip_optional_pos; + } + } + if (args[1]) { + b = args[1]; + if (!--noptargs) { + goto skip_optional_pos; + } + } + c = args[2]; +skip_optional_pos: + return_value = depr_kwd_optional_3_impl(module, a, b, c); + +exit: + return return_value; +} + +PyDoc_STRVAR(depr_kwd_required_optional__doc__, +"depr_kwd_required_optional($module, a, /, b, c=None)\n" +"--\n" +"\n" +"Note: Passing keyword arguments \'b\' and \'c\' to\n" +"depr_kwd_required_optional() is deprecated. Parameters \'b\' and \'c\'\n" +"will become positional-only in Python 3.14.\n" +""); + +#define DEPR_KWD_REQUIRED_OPTIONAL_METHODDEF \ + {"depr_kwd_required_optional", _PyCFunction_CAST(depr_kwd_required_optional), METH_FASTCALL|METH_KEYWORDS, depr_kwd_required_optional__doc__}, + +static PyObject * +depr_kwd_required_optional_impl(PyObject *module, PyObject *a, PyObject *b, + PyObject *c); + +// Emit compiler warnings when we get to Python 3.14. +#if PY_VERSION_HEX >= 0x030e00C0 +# error "Update the clinic input of 'depr_kwd_required_optional'." +#elif PY_VERSION_HEX >= 0x030e00A0 +# ifdef _MSC_VER +# pragma message ("Update the clinic input of 'depr_kwd_required_optional'.") +# else +# warning "Update the clinic input of 'depr_kwd_required_optional'." +# endif +#endif + +static PyObject * +depr_kwd_required_optional(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(b), &_Py_ID(c), }, + }; + #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[] = {"", "b", "c", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "depr_kwd_required_optional", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[3]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; + PyObject *a; + PyObject *b; + PyObject *c = Py_None; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 3, 0, argsbuf); + if (!args) { + goto exit; + } + if (kwnames && PyTuple_GET_SIZE(kwnames) && ((nargs < 2) || (nargs < 3 && args[2]))) { + if (PyErr_WarnEx(PyExc_DeprecationWarning, + "Passing keyword arguments 'b' and 'c' to " + "depr_kwd_required_optional() is deprecated. Parameters 'b' and " + "'c' will become positional-only in Python 3.14.", 1)) + { + goto exit; + } + } + a = args[0]; + b = args[1]; + if (!noptargs) { + goto skip_optional_pos; + } + c = args[2]; +skip_optional_pos: + return_value = depr_kwd_required_optional_impl(module, a, b, c); + +exit: + return return_value; +} + +PyDoc_STRVAR(depr_kwd_noinline__doc__, +"depr_kwd_noinline($module, a, /, b, c=None, d=\'\')\n" +"--\n" +"\n" +"Note: Passing keyword arguments \'b\' and \'c\' to depr_kwd_noinline() is\n" +"deprecated. Parameters \'b\' and \'c\' will become positional-only in\n" +"Python 3.14.\n" +""); + +#define DEPR_KWD_NOINLINE_METHODDEF \ + {"depr_kwd_noinline", _PyCFunction_CAST(depr_kwd_noinline), METH_FASTCALL|METH_KEYWORDS, depr_kwd_noinline__doc__}, + +static PyObject * +depr_kwd_noinline_impl(PyObject *module, PyObject *a, PyObject *b, + PyObject *c, const char *d, Py_ssize_t d_length); + +// Emit compiler warnings when we get to Python 3.14. +#if PY_VERSION_HEX >= 0x030e00C0 +# error "Update the clinic input of 'depr_kwd_noinline'." +#elif PY_VERSION_HEX >= 0x030e00A0 +# ifdef _MSC_VER +# pragma message ("Update the clinic input of 'depr_kwd_noinline'.") +# else +# warning "Update the clinic input of 'depr_kwd_noinline'." +# endif +#endif + +static PyObject * +depr_kwd_noinline(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 3 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(b), &_Py_ID(c), &_Py_ID(d), }, + }; + #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[] = {"", "b", "c", "d", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .format = "OO|Os#:depr_kwd_noinline", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *a; + PyObject *b; + PyObject *c = Py_None; + const char *d = ""; + Py_ssize_t d_length; + + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, + &a, &b, &c, &d, &d_length)) { + goto exit; + } + if (kwnames && PyTuple_GET_SIZE(kwnames) && ((nargs < 2) || (nargs < 3 && PySequence_Contains(kwnames, &_Py_ID(c))))) { + if (PyErr_Occurred()) { // PySequence_Contains() above can fail + goto exit; + } + if (PyErr_WarnEx(PyExc_DeprecationWarning, + "Passing keyword arguments 'b' and 'c' to depr_kwd_noinline() is " + "deprecated. Parameters 'b' and 'c' will become positional-only " + "in Python 3.14.", 1)) + { + goto exit; + } + } + return_value = depr_kwd_noinline_impl(module, a, b, c, d, d_length); + +exit: + return return_value; +} + +PyDoc_STRVAR(depr_kwd_multi__doc__, +"depr_kwd_multi($module, a, /, b, c, d, e, f, g, h)\n" +"--\n" +"\n" +"Note: Passing keyword arguments \'b\', \'c\', \'d\', \'e\', \'f\' and \'g\' to\n" +"depr_kwd_multi() is deprecated. Parameter \'b\' will become positional-\n" +"only in Python 3.14. Parameters \'c\' and \'d\' will become positional-\n" +"only in Python 3.15. Parameters \'e\', \'f\' and \'g\' will become\n" +"positional-only in Python 3.16.\n" +""); + +#define DEPR_KWD_MULTI_METHODDEF \ + {"depr_kwd_multi", _PyCFunction_CAST(depr_kwd_multi), METH_FASTCALL|METH_KEYWORDS, depr_kwd_multi__doc__}, + +static PyObject * +depr_kwd_multi_impl(PyObject *module, PyObject *a, PyObject *b, PyObject *c, + PyObject *d, PyObject *e, PyObject *f, PyObject *g, + PyObject *h); + +// Emit compiler warnings when we get to Python 3.14. +#if PY_VERSION_HEX >= 0x030e00C0 +# error "Update the clinic input of 'depr_kwd_multi'." +#elif PY_VERSION_HEX >= 0x030e00A0 +# ifdef _MSC_VER +# pragma message ("Update the clinic input of 'depr_kwd_multi'.") +# else +# warning "Update the clinic input of 'depr_kwd_multi'." +# endif +#endif + +static PyObject * +depr_kwd_multi(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 7 + 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(b), &_Py_ID(c), &_Py_ID(d), &_Py_ID(e), &_Py_ID(f), &_Py_ID(g), &_Py_ID(h), }, + }; + #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[] = {"", "b", "c", "d", "e", "f", "g", "h", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "depr_kwd_multi", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[8]; + PyObject *a; + PyObject *b; + PyObject *c; + PyObject *d; + PyObject *e; + PyObject *f; + PyObject *g; + PyObject *h; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 8, 8, 0, argsbuf); + if (!args) { + goto exit; + } + if (nargs < 7) { + if (PyErr_WarnEx(PyExc_DeprecationWarning, + "Passing keyword arguments 'b', 'c', 'd', 'e', 'f' and 'g' to " + "depr_kwd_multi() is deprecated. Parameter 'b' will become " + "positional-only in Python 3.14. Parameters 'c' and 'd' will " + "become positional-only in Python 3.15. Parameters 'e', 'f' and " + "'g' will become positional-only in Python 3.16.", 1)) + { + goto exit; + } + } + a = args[0]; + b = args[1]; + c = args[2]; + d = args[3]; + e = args[4]; + f = args[5]; + g = args[6]; + h = args[7]; + return_value = depr_kwd_multi_impl(module, a, b, c, d, e, f, g, h); + +exit: + return return_value; +} + +PyDoc_STRVAR(depr_multi__doc__, +"depr_multi($module, a, /, b, c, d, e, f, *, g)\n" +"--\n" +"\n" +"Note: Passing keyword arguments \'b\' and \'c\' to depr_multi() is\n" +"deprecated. Parameter \'b\' will become positional-only in Python 3.14.\n" +"Parameter \'c\' will become positional-only in Python 3.15.\n" +"\n" +"\n" +"Note: Passing more than 4 positional arguments to depr_multi() is\n" +"deprecated. Parameter \'e\' will become a keyword-only parameter in\n" +"Python 3.15. Parameter \'f\' will become a keyword-only parameter in\n" +"Python 3.14.\n" +""); + +#define DEPR_MULTI_METHODDEF \ + {"depr_multi", _PyCFunction_CAST(depr_multi), METH_FASTCALL|METH_KEYWORDS, depr_multi__doc__}, + +static PyObject * +depr_multi_impl(PyObject *module, PyObject *a, PyObject *b, PyObject *c, + PyObject *d, PyObject *e, PyObject *f, PyObject *g); + +// Emit compiler warnings when we get to Python 3.14. +#if PY_VERSION_HEX >= 0x030e00C0 +# error "Update the clinic input of 'depr_multi'." +#elif PY_VERSION_HEX >= 0x030e00A0 +# ifdef _MSC_VER +# pragma message ("Update the clinic input of 'depr_multi'.") +# else +# warning "Update the clinic input of 'depr_multi'." +# endif +#endif + +static PyObject * +depr_multi(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 6 + 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(b), &_Py_ID(c), &_Py_ID(d), &_Py_ID(e), &_Py_ID(f), &_Py_ID(g), }, + }; + #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[] = {"", "b", "c", "d", "e", "f", "g", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "depr_multi", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[7]; + PyObject *a; + PyObject *b; + PyObject *c; + PyObject *d; + PyObject *e; + PyObject *f; + PyObject *g; + + if (nargs > 4 && nargs <= 6) { + if (PyErr_WarnEx(PyExc_DeprecationWarning, + "Passing more than 4 positional arguments to depr_multi() is " + "deprecated. Parameter 'e' will become a keyword-only parameter " + "in Python 3.15. Parameter 'f' will become a keyword-only " + "parameter in Python 3.14.", 1)) + { + goto exit; + } + } + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 6, 6, 1, argsbuf); + if (!args) { + goto exit; + } + if (nargs < 3) { + if (PyErr_WarnEx(PyExc_DeprecationWarning, + "Passing keyword arguments 'b' and 'c' to depr_multi() is " + "deprecated. Parameter 'b' will become positional-only in Python " + "3.14. Parameter 'c' will become positional-only in Python 3.15.", 1)) + { + goto exit; + } + } + a = args[0]; + b = args[1]; + c = args[2]; + d = args[3]; + e = args[4]; + f = args[5]; + g = args[6]; + return_value = depr_multi_impl(module, a, b, c, d, e, f, g); + +exit: + return return_value; +} +/*[clinic end generated code: output=2c19d1804ba6e53b input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_testclinic_limited.c.h b/Modules/clinic/_testclinic_limited.c.h new file mode 100644 index 00000000000000..eff72cee24975c --- /dev/null +++ b/Modules/clinic/_testclinic_limited.c.h @@ -0,0 +1,94 @@ +/*[clinic input] +preserve +[clinic start generated code]*/ + +PyDoc_STRVAR(test_empty_function__doc__, +"test_empty_function($module, /)\n" +"--\n" +"\n"); + +#define TEST_EMPTY_FUNCTION_METHODDEF \ + {"test_empty_function", (PyCFunction)test_empty_function, METH_NOARGS, test_empty_function__doc__}, + +static PyObject * +test_empty_function_impl(PyObject *module); + +static PyObject * +test_empty_function(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return test_empty_function_impl(module); +} + +PyDoc_STRVAR(my_int_func__doc__, +"my_int_func($module, arg, /)\n" +"--\n" +"\n"); + +#define MY_INT_FUNC_METHODDEF \ + {"my_int_func", (PyCFunction)my_int_func, METH_O, my_int_func__doc__}, + +static int +my_int_func_impl(PyObject *module, int arg); + +static PyObject * +my_int_func(PyObject *module, PyObject *arg_) +{ + PyObject *return_value = NULL; + int arg; + int _return_value; + + arg = PyLong_AsInt(arg_); + if (arg == -1 && PyErr_Occurred()) { + goto exit; + } + _return_value = my_int_func_impl(module, arg); + if ((_return_value == -1) && PyErr_Occurred()) { + goto exit; + } + return_value = PyLong_FromLong((long)_return_value); + +exit: + return return_value; +} + +PyDoc_STRVAR(my_int_sum__doc__, +"my_int_sum($module, x, y, /)\n" +"--\n" +"\n"); + +#define MY_INT_SUM_METHODDEF \ + {"my_int_sum", (PyCFunction)(void(*)(void))my_int_sum, METH_FASTCALL, my_int_sum__doc__}, + +static int +my_int_sum_impl(PyObject *module, int x, int y); + +static PyObject * +my_int_sum(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int x; + int y; + int _return_value; + + if (nargs != 2) { + PyErr_Format(PyExc_TypeError, "my_int_sum expected 2 arguments, got %zd", nargs); + goto exit; + } + x = PyLong_AsInt(args[0]); + if (x == -1 && PyErr_Occurred()) { + goto exit; + } + y = PyLong_AsInt(args[1]); + if (y == -1 && PyErr_Occurred()) { + goto exit; + } + _return_value = my_int_sum_impl(module, x, y); + if ((_return_value == -1) && PyErr_Occurred()) { + goto exit; + } + return_value = PyLong_FromLong((long)_return_value); + +exit: + return return_value; +} +/*[clinic end generated code: output=5cf64baf978d2288 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_testinternalcapi.c.h b/Modules/clinic/_testinternalcapi.c.h index 9419dcd751a0e9..cba2a943d03456 100644 --- a/Modules/clinic/_testinternalcapi.c.h +++ b/Modules/clinic/_testinternalcapi.c.h @@ -3,10 +3,10 @@ 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() +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() #endif - +#include "pycore_modsupport.h" // _PyArg_UnpackKeywords() PyDoc_STRVAR(_testinternalcapi_compiler_cleandoc__doc__, "compiler_cleandoc($module, /, doc)\n" @@ -123,14 +123,14 @@ _testinternalcapi_compiler_codegen(PyObject *module, PyObject *const *args, Py_s } ast = args[0]; filename = args[1]; - optimize = _PyLong_AsInt(args[2]); + optimize = PyLong_AsInt(args[2]); if (optimize == -1 && PyErr_Occurred()) { goto exit; } if (!noptargs) { goto skip_optional_pos; } - compile_mode = _PyLong_AsInt(args[3]); + compile_mode = PyLong_AsInt(args[3]); if (compile_mode == -1 && PyErr_Occurred()) { goto exit; } @@ -194,7 +194,7 @@ _testinternalcapi_optimize_cfg(PyObject *module, PyObject *const *args, Py_ssize } instructions = args[0]; consts = args[1]; - nlocals = _PyLong_AsInt(args[2]); + nlocals = PyLong_AsInt(args[2]); if (nlocals == -1 && PyErr_Occurred()) { goto exit; } @@ -265,4 +265,21 @@ _testinternalcapi_assemble_code_object(PyObject *module, PyObject *const *args, exit: return return_value; } -/*[clinic end generated code: output=811d50772c8f285a input=a9049054013a1b77]*/ + +PyDoc_STRVAR(_testinternalcapi_test_long_numbits__doc__, +"test_long_numbits($module, /)\n" +"--\n" +"\n"); + +#define _TESTINTERNALCAPI_TEST_LONG_NUMBITS_METHODDEF \ + {"test_long_numbits", (PyCFunction)_testinternalcapi_test_long_numbits, METH_NOARGS, _testinternalcapi_test_long_numbits__doc__}, + +static PyObject * +_testinternalcapi_test_long_numbits_impl(PyObject *module); + +static PyObject * +_testinternalcapi_test_long_numbits(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _testinternalcapi_test_long_numbits_impl(module); +} +/*[clinic end generated code: output=679bf53bbae20085 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_testmultiphase.c.h b/Modules/clinic/_testmultiphase.c.h index 42ec7475e5e4be..c0a00954c16cbe 100644 --- a/Modules/clinic/_testmultiphase.c.h +++ b/Modules/clinic/_testmultiphase.c.h @@ -3,10 +3,10 @@ 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() +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() #endif - +#include "pycore_modsupport.h" // _PyArg_UnpackKeywords() PyDoc_STRVAR(_testmultiphase_StateAccessType_get_defining_module__doc__, "get_defining_module($self, /)\n" @@ -117,7 +117,7 @@ _testmultiphase_StateAccessType_increment_count_clinic(StateAccessTypeObject *se goto skip_optional_pos; } if (args[0]) { - n = _PyLong_AsInt(args[0]); + n = PyLong_AsInt(args[0]); if (n == -1 && PyErr_Occurred()) { goto exit; } @@ -162,4 +162,4 @@ _testmultiphase_StateAccessType_get_count(StateAccessTypeObject *self, PyTypeObj } return _testmultiphase_StateAccessType_get_count_impl(self, cls); } -/*[clinic end generated code: output=52ea97ab2f03bb6d input=a9049054013a1b77]*/ +/*[clinic end generated code: output=d8c262af27b3b98d input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_tkinter.c.h b/Modules/clinic/_tkinter.c.h index 96c6ee26f426c3..188bcc773cfc41 100644 --- a/Modules/clinic/_tkinter.c.h +++ b/Modules/clinic/_tkinter.c.h @@ -2,11 +2,7 @@ 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 - +#include "pycore_modsupport.h" // _PyArg_BadArgument() PyDoc_STRVAR(_tkinter_tkapp_eval__doc__, "eval($self, script, /)\n" @@ -432,7 +428,7 @@ _tkinter_tkapp_createfilehandler(TkappObject *self, PyObject *const *args, Py_ss goto exit; } file = args[0]; - mask = _PyLong_AsInt(args[1]); + mask = PyLong_AsInt(args[1]); if (mask == -1 && PyErr_Occurred()) { goto exit; } @@ -496,7 +492,7 @@ _tkinter_tkapp_createtimerhandler(TkappObject *self, PyObject *const *args, Py_s if (!_PyArg_CheckPositional("createtimerhandler", nargs, 2, 2)) { goto exit; } - milliseconds = _PyLong_AsInt(args[0]); + milliseconds = PyLong_AsInt(args[0]); if (milliseconds == -1 && PyErr_Occurred()) { goto exit; } @@ -530,7 +526,7 @@ _tkinter_tkapp_mainloop(TkappObject *self, PyObject *const *args, Py_ssize_t nar if (nargs < 1) { goto skip_optional; } - threshold = _PyLong_AsInt(args[0]); + threshold = PyLong_AsInt(args[0]); if (threshold == -1 && PyErr_Occurred()) { goto exit; } @@ -564,7 +560,7 @@ _tkinter_tkapp_dooneevent(TkappObject *self, PyObject *const *args, Py_ssize_t n if (nargs < 1) { goto skip_optional; } - flags = _PyLong_AsInt(args[0]); + flags = PyLong_AsInt(args[0]); if (flags == -1 && PyErr_Occurred()) { goto exit; } @@ -820,7 +816,7 @@ _tkinter_setbusywaitinterval(PyObject *module, PyObject *arg) PyObject *return_value = NULL; int new_val; - new_val = _PyLong_AsInt(arg); + new_val = PyLong_AsInt(arg); if (new_val == -1 && PyErr_Occurred()) { goto exit; } @@ -865,4 +861,4 @@ _tkinter_getbusywaitinterval(PyObject *module, PyObject *Py_UNUSED(ignored)) #ifndef _TKINTER_TKAPP_DELETEFILEHANDLER_METHODDEF #define _TKINTER_TKAPP_DELETEFILEHANDLER_METHODDEF #endif /* !defined(_TKINTER_TKAPP_DELETEFILEHANDLER_METHODDEF) */ -/*[clinic end generated code: output=2a4e3bf8448604b5 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=d447501ec5aa9447 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_tracemalloc.c.h b/Modules/clinic/_tracemalloc.c.h index a89cd9aabca8d6..1d100247423991 100644 --- a/Modules/clinic/_tracemalloc.c.h +++ b/Modules/clinic/_tracemalloc.c.h @@ -2,11 +2,7 @@ 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 - +#include "pycore_modsupport.h" // _PyArg_CheckPositional() PyDoc_STRVAR(_tracemalloc_is_tracing__doc__, "is_tracing($module, /)\n" @@ -107,7 +103,7 @@ _tracemalloc_start(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (nargs < 1) { goto skip_optional; } - nframe = _PyLong_AsInt(args[0]); + nframe = PyLong_AsInt(args[0]); if (nframe == -1 && PyErr_Occurred()) { goto exit; } @@ -218,4 +214,4 @@ _tracemalloc_reset_peak(PyObject *module, PyObject *Py_UNUSED(ignored)) { return _tracemalloc_reset_peak_impl(module); } -/*[clinic end generated code: output=44e3f8553aae2535 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=9d4d884b156c2ddb input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_typingmodule.c.h b/Modules/clinic/_typingmodule.c.h index f980aa0d0844da..ea415e67153ed8 100644 --- a/Modules/clinic/_typingmodule.c.h +++ b/Modules/clinic/_typingmodule.c.h @@ -2,12 +2,6 @@ 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(_typing__idfunc__doc__, "_idfunc($module, x, /)\n" "--\n" @@ -15,4 +9,4 @@ PyDoc_STRVAR(_typing__idfunc__doc__, #define _TYPING__IDFUNC_METHODDEF \ {"_idfunc", (PyCFunction)_typing__idfunc, METH_O, _typing__idfunc__doc__}, -/*[clinic end generated code: output=97457fda45072c7d input=a9049054013a1b77]*/ +/*[clinic end generated code: output=e7ea2a3cb7ab301a input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_weakref.c.h b/Modules/clinic/_weakref.c.h index 48feb042cac039..550b6c4d71a015 100644 --- a/Modules/clinic/_weakref.c.h +++ b/Modules/clinic/_weakref.c.h @@ -2,11 +2,8 @@ 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 - +#include "pycore_critical_section.h"// Py_BEGIN_CRITICAL_SECTION() +#include "pycore_modsupport.h" // _PyArg_CheckPositional() PyDoc_STRVAR(_weakref_getweakrefcount__doc__, "getweakrefcount($module, object, /)\n" @@ -26,7 +23,9 @@ _weakref_getweakrefcount(PyObject *module, PyObject *object) PyObject *return_value = NULL; Py_ssize_t _return_value; + Py_BEGIN_CRITICAL_SECTION(object); _return_value = _weakref_getweakrefcount_impl(module, object); + Py_END_CRITICAL_SECTION(); if ((_return_value == -1) && PyErr_Occurred()) { goto exit; } @@ -80,6 +79,21 @@ PyDoc_STRVAR(_weakref_getweakrefs__doc__, #define _WEAKREF_GETWEAKREFS_METHODDEF \ {"getweakrefs", (PyCFunction)_weakref_getweakrefs, METH_O, _weakref_getweakrefs__doc__}, +static PyObject * +_weakref_getweakrefs_impl(PyObject *module, PyObject *object); + +static PyObject * +_weakref_getweakrefs(PyObject *module, PyObject *object) +{ + PyObject *return_value = NULL; + + Py_BEGIN_CRITICAL_SECTION(object); + return_value = _weakref_getweakrefs_impl(module, object); + Py_END_CRITICAL_SECTION(); + + return return_value; +} + PyDoc_STRVAR(_weakref_proxy__doc__, "proxy($module, object, callback=None, /)\n" "--\n" @@ -116,4 +130,4 @@ _weakref_proxy(PyObject *module, PyObject *const *args, Py_ssize_t nargs) exit: return return_value; } -/*[clinic end generated code: output=28265e89d583273d input=a9049054013a1b77]*/ +/*[clinic end generated code: output=d5d30707212a9870 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_winapi.c.h b/Modules/clinic/_winapi.c.h index 8f46b8f1095e98..3a3231c051ef71 100644 --- a/Modules/clinic/_winapi.c.h +++ b/Modules/clinic/_winapi.c.h @@ -3,10 +3,11 @@ 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() +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() #endif - +#include "pycore_long.h" // _PyLong_Size_t_Converter() +#include "pycore_modsupport.h" // _PyArg_UnpackKeywords() PyDoc_STRVAR(_winapi_Overlapped_GetOverlappedResult__doc__, "GetOverlappedResult($self, wait, /)\n" @@ -567,7 +568,7 @@ _winapi_GetExitCodeProcess(PyObject *module, PyObject *arg) if ((_return_value == PY_DWORD_MAX) && PyErr_Occurred()) { goto exit; } - return_value = Py_BuildValue("k", _return_value); + return_value = PyLong_FromUnsignedLong(_return_value); exit: return return_value; @@ -594,7 +595,7 @@ _winapi_GetLastError(PyObject *module, PyObject *Py_UNUSED(ignored)) if ((_return_value == PY_DWORD_MAX) && PyErr_Occurred()) { goto exit; } - return_value = Py_BuildValue("k", _return_value); + return_value = PyLong_FromUnsignedLong(_return_value); exit: return return_value; @@ -884,7 +885,7 @@ PyDoc_STRVAR(_winapi_LCMapStringEx__doc__, static PyObject * _winapi_LCMapStringEx_impl(PyObject *module, LPCWSTR locale, DWORD flags, - LPCWSTR src); + PyObject *src); static PyObject * _winapi_LCMapStringEx(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) @@ -911,16 +912,16 @@ _winapi_LCMapStringEx(PyObject *module, PyObject *const *args, Py_ssize_t nargs, static const char * const _keywords[] = {"locale", "flags", "src", NULL}; static _PyArg_Parser _parser = { .keywords = _keywords, - .format = "O&kO&:LCMapStringEx", + .format = "O&kU:LCMapStringEx", .kwtuple = KWTUPLE, }; #undef KWTUPLE LPCWSTR locale = NULL; DWORD flags; - LPCWSTR src = NULL; + PyObject *src; if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, - _PyUnicode_WideCharString_Converter, &locale, &flags, _PyUnicode_WideCharString_Converter, &src)) { + _PyUnicode_WideCharString_Converter, &locale, &flags, &src)) { goto exit; } return_value = _winapi_LCMapStringEx_impl(module, locale, flags, src); @@ -928,8 +929,6 @@ _winapi_LCMapStringEx(PyObject *module, PyObject *const *args, Py_ssize_t nargs, exit: /* Cleanup for locale */ PyMem_Free((void *)locale); - /* Cleanup for src */ - PyMem_Free((void *)src); return return_value; } @@ -1306,7 +1305,7 @@ _winapi_GetFileType(PyObject *module, PyObject *const *args, Py_ssize_t nargs, P if ((_return_value == PY_DWORD_MAX) && PyErr_Occurred()) { goto exit; } - return_value = Py_BuildValue("k", _return_value); + return_value = PyLong_FromUnsignedLong(_return_value); exit: return return_value; @@ -1480,4 +1479,4 @@ _winapi_CopyFile2(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyO return return_value; } -/*[clinic end generated code: output=f32fe6ecdbffd74d input=a9049054013a1b77]*/ +/*[clinic end generated code: output=e1a9908bb82a6379 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_zoneinfo.c.h b/Modules/clinic/_zoneinfo.c.h index ae62865e0f67df..9905b6425e2f79 100644 --- a/Modules/clinic/_zoneinfo.c.h +++ b/Modules/clinic/_zoneinfo.c.h @@ -3,10 +3,10 @@ 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() +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() #endif - +#include "pycore_modsupport.h" // _PyArg_UnpackKeywords() PyDoc_STRVAR(zoneinfo_ZoneInfo_from_file__doc__, "from_file($type, file_obj, /, key=None)\n" @@ -372,4 +372,4 @@ zoneinfo_ZoneInfo__unpickle(PyTypeObject *type, PyTypeObject *cls, PyObject *con exit: return return_value; } -/*[clinic end generated code: output=54051388dfc408af input=a9049054013a1b77]*/ +/*[clinic end generated code: output=2a15f32fdd2ab6cd input=a9049054013a1b77]*/ diff --git a/Modules/clinic/arraymodule.c.h b/Modules/clinic/arraymodule.c.h index 600931835ecac1..dbce0313541649 100644 --- a/Modules/clinic/arraymodule.c.h +++ b/Modules/clinic/arraymodule.c.h @@ -2,11 +2,8 @@ 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 - +#include "pycore_abstract.h" // _PyNumber_Index() +#include "pycore_modsupport.h" // _PyArg_CheckPositional() PyDoc_STRVAR(array_array___copy____doc__, "__copy__($self, /)\n" @@ -445,10 +442,6 @@ array_array_frombytes(arrayobject *self, PyObject *arg) if (PyObject_GetBuffer(arg, &buffer, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&buffer, 'C')) { - _PyArg_BadArgument("frombytes", "argument", "contiguous buffer", arg); - goto exit; - } return_value = array_array_frombytes_impl(self, &buffer); exit: @@ -589,7 +582,7 @@ array__array_reconstructor(PyObject *module, PyObject *const *args, Py_ssize_t n goto exit; } typecode = PyUnicode_READ_CHAR(args[1], 0); - mformat_code = _PyLong_AsInt(args[2]); + mformat_code = PyLong_AsInt(args[2]); if (mformat_code == -1 && PyErr_Occurred()) { goto exit; } @@ -674,4 +667,4 @@ PyDoc_STRVAR(array_arrayiterator___setstate____doc__, #define ARRAY_ARRAYITERATOR___SETSTATE___METHODDEF \ {"__setstate__", (PyCFunction)array_arrayiterator___setstate__, METH_O, array_arrayiterator___setstate____doc__}, -/*[clinic end generated code: output=11595e9f38d6d500 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=bf086c01e7e482bf input=a9049054013a1b77]*/ diff --git a/Modules/clinic/binascii.c.h b/Modules/clinic/binascii.c.h index 63566dfb10e74f..1adca415dfee12 100644 --- a/Modules/clinic/binascii.c.h +++ b/Modules/clinic/binascii.c.h @@ -3,10 +3,10 @@ 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() +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() #endif - +#include "pycore_modsupport.h" // _PyArg_UnpackKeywords() PyDoc_STRVAR(binascii_a2b_uu__doc__, "a2b_uu($module, data, /)\n" @@ -92,10 +92,6 @@ binascii_b2a_uu(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObj if (PyObject_GetBuffer(args[0], &data, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("b2a_uu", "argument 1", "contiguous buffer", args[0]); - goto exit; - } if (!noptargs) { goto skip_optional_kwonly; } @@ -243,10 +239,6 @@ binascii_b2a_base64(PyObject *module, PyObject *const *args, Py_ssize_t nargs, P if (PyObject_GetBuffer(args[0], &data, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("b2a_base64", "argument 1", "contiguous buffer", args[0]); - goto exit; - } if (!noptargs) { goto skip_optional_kwonly; } @@ -291,10 +283,6 @@ binascii_crc_hqx(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (PyObject_GetBuffer(args[0], &data, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("crc_hqx", "argument 1", "contiguous buffer", args[0]); - goto exit; - } crc = (unsigned int)PyLong_AsUnsignedLongMask(args[1]); if (crc == (unsigned int)-1 && PyErr_Occurred()) { goto exit; @@ -336,10 +324,6 @@ binascii_crc32(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (PyObject_GetBuffer(args[0], &data, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("crc32", "argument 1", "contiguous buffer", args[0]); - goto exit; - } if (nargs < 2) { goto skip_optional; } @@ -435,10 +419,6 @@ binascii_b2a_hex(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyOb if (PyObject_GetBuffer(args[0], &data, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("b2a_hex", "argument 'data'", "contiguous buffer", args[0]); - goto exit; - } if (!noptargs) { goto skip_optional_pos; } @@ -448,7 +428,7 @@ binascii_b2a_hex(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyOb goto skip_optional_pos; } } - bytes_per_sep = _PyLong_AsInt(args[2]); + bytes_per_sep = PyLong_AsInt(args[2]); if (bytes_per_sep == -1 && PyErr_Occurred()) { goto exit; } @@ -528,10 +508,6 @@ binascii_hexlify(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyOb if (PyObject_GetBuffer(args[0], &data, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("hexlify", "argument 'data'", "contiguous buffer", args[0]); - goto exit; - } if (!noptargs) { goto skip_optional_pos; } @@ -541,7 +517,7 @@ binascii_hexlify(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyOb goto skip_optional_pos; } } - bytes_per_sep = _PyLong_AsInt(args[2]); + bytes_per_sep = PyLong_AsInt(args[2]); if (bytes_per_sep == -1 && PyErr_Occurred()) { goto exit; } @@ -755,10 +731,6 @@ binascii_b2a_qp(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObj if (PyObject_GetBuffer(args[0], &data, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("b2a_qp", "argument 'data'", "contiguous buffer", args[0]); - goto exit; - } if (!noptargs) { goto skip_optional_pos; } @@ -795,4 +767,4 @@ binascii_b2a_qp(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObj return return_value; } -/*[clinic end generated code: output=ab156917c9db79d2 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=968767b663ed889d input=a9049054013a1b77]*/ diff --git a/Modules/clinic/cmathmodule.c.h b/Modules/clinic/cmathmodule.c.h index 941448e76e80de..b709204af1d959 100644 --- a/Modules/clinic/cmathmodule.c.h +++ b/Modules/clinic/cmathmodule.c.h @@ -3,10 +3,10 @@ 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() +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() #endif - +#include "pycore_modsupport.h" // _PyArg_CheckPositional() PyDoc_STRVAR(cmath_acos__doc__, "acos($module, z, /)\n" @@ -982,4 +982,4 @@ cmath_isclose(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObjec exit: return return_value; } -/*[clinic end generated code: output=87f609786ef270cd input=a9049054013a1b77]*/ +/*[clinic end generated code: output=364093af55bfe53f input=a9049054013a1b77]*/ diff --git a/Modules/clinic/fcntlmodule.c.h b/Modules/clinic/fcntlmodule.c.h index 20eb50b0e76b38..5dc2fc068d0f7e 100644 --- a/Modules/clinic/fcntlmodule.c.h +++ b/Modules/clinic/fcntlmodule.c.h @@ -2,11 +2,8 @@ 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 - +#include "pycore_fileutils.h" // _PyLong_FileDescriptor_Converter() +#include "pycore_modsupport.h" // _PyArg_CheckPositional() PyDoc_STRVAR(fcntl_fcntl__doc__, "fcntl($module, fd, cmd, arg=0, /)\n" @@ -44,7 +41,7 @@ fcntl_fcntl(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyLong_FileDescriptor_Converter(args[0], &fd)) { goto exit; } - code = _PyLong_AsInt(args[1]); + code = PyLong_AsInt(args[1]); if (code == -1 && PyErr_Occurred()) { goto exit; } @@ -164,7 +161,7 @@ fcntl_flock(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyLong_FileDescriptor_Converter(args[0], &fd)) { goto exit; } - code = _PyLong_AsInt(args[1]); + code = PyLong_AsInt(args[1]); if (code == -1 && PyErr_Occurred()) { goto exit; } @@ -224,7 +221,7 @@ fcntl_lockf(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyLong_FileDescriptor_Converter(args[0], &fd)) { goto exit; } - code = _PyLong_AsInt(args[1]); + code = PyLong_AsInt(args[1]); if (code == -1 && PyErr_Occurred()) { goto exit; } @@ -239,7 +236,7 @@ fcntl_lockf(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (nargs < 5) { goto skip_optional; } - whence = _PyLong_AsInt(args[4]); + whence = PyLong_AsInt(args[4]); if (whence == -1 && PyErr_Occurred()) { goto exit; } @@ -249,4 +246,4 @@ fcntl_lockf(PyObject *module, PyObject *const *args, Py_ssize_t nargs) exit: return return_value; } -/*[clinic end generated code: output=1db859412172dd53 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=732e33ba92042031 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/gcmodule.c.h b/Modules/clinic/gcmodule.c.h index 2d18e2ee0978e0..d50d170589a2cd 100644 --- a/Modules/clinic/gcmodule.c.h +++ b/Modules/clinic/gcmodule.c.h @@ -3,10 +3,11 @@ 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() +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() #endif - +#include "pycore_abstract.h" // _Py_convert_optional_to_ssize_t() +#include "pycore_modsupport.h" // _PyArg_UnpackKeywords() PyDoc_STRVAR(gc_enable__doc__, "enable($module, /)\n" @@ -131,7 +132,7 @@ gc_collect(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject * if (!noptargs) { goto skip_optional_pos; } - generation = _PyLong_AsInt(args[0]); + generation = PyLong_AsInt(args[0]); if (generation == -1 && PyErr_Occurred()) { goto exit; } @@ -175,7 +176,7 @@ gc_set_debug(PyObject *module, PyObject *arg) PyObject *return_value = NULL; int flags; - flags = _PyLong_AsInt(arg); + flags = PyLong_AsInt(arg); if (flags == -1 && PyErr_Occurred()) { goto exit; } @@ -213,6 +214,58 @@ gc_get_debug(PyObject *module, PyObject *Py_UNUSED(ignored)) return return_value; } +PyDoc_STRVAR(gc_set_threshold__doc__, +"set_threshold(threshold0, [threshold1, [threshold2]])\n" +"Set the collection thresholds (the collection frequency).\n" +"\n" +"Setting \'threshold0\' to zero disables collection."); + +#define GC_SET_THRESHOLD_METHODDEF \ + {"set_threshold", (PyCFunction)gc_set_threshold, METH_VARARGS, gc_set_threshold__doc__}, + +static PyObject * +gc_set_threshold_impl(PyObject *module, int threshold0, int group_right_1, + int threshold1, int group_right_2, int threshold2); + +static PyObject * +gc_set_threshold(PyObject *module, PyObject *args) +{ + PyObject *return_value = NULL; + int threshold0; + int group_right_1 = 0; + int threshold1 = 0; + int group_right_2 = 0; + int threshold2 = 0; + + switch (PyTuple_GET_SIZE(args)) { + case 1: + if (!PyArg_ParseTuple(args, "i:set_threshold", &threshold0)) { + goto exit; + } + break; + case 2: + if (!PyArg_ParseTuple(args, "ii:set_threshold", &threshold0, &threshold1)) { + goto exit; + } + group_right_1 = 1; + break; + case 3: + if (!PyArg_ParseTuple(args, "iii:set_threshold", &threshold0, &threshold1, &threshold2)) { + goto exit; + } + group_right_1 = 1; + group_right_2 = 1; + break; + default: + PyErr_SetString(PyExc_TypeError, "gc.set_threshold requires 1 to 3 arguments"); + goto exit; + } + return_value = gc_set_threshold_impl(module, threshold0, group_right_1, threshold1, group_right_2, threshold2); + +exit: + return return_value; +} + PyDoc_STRVAR(gc_get_threshold__doc__, "get_threshold($module, /)\n" "--\n" @@ -249,6 +302,76 @@ gc_get_count(PyObject *module, PyObject *Py_UNUSED(ignored)) return gc_get_count_impl(module); } +PyDoc_STRVAR(gc_get_referrers__doc__, +"get_referrers($module, /, *objs)\n" +"--\n" +"\n" +"Return the list of objects that directly refer to any of \'objs\'."); + +#define GC_GET_REFERRERS_METHODDEF \ + {"get_referrers", _PyCFunction_CAST(gc_get_referrers), METH_FASTCALL, gc_get_referrers__doc__}, + +static PyObject * +gc_get_referrers_impl(PyObject *module, PyObject *args); + +static PyObject * +gc_get_referrers(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *__clinic_args = NULL; + + if (!_PyArg_CheckPositional("get_referrers", nargs, 0, PY_SSIZE_T_MAX)) { + goto exit; + } + __clinic_args = PyTuple_New(nargs - 0); + if (!__clinic_args) { + goto exit; + } + for (Py_ssize_t i = 0; i < nargs - 0; ++i) { + PyTuple_SET_ITEM(__clinic_args, i, Py_NewRef(args[0 + i])); + } + return_value = gc_get_referrers_impl(module, __clinic_args); + +exit: + Py_XDECREF(__clinic_args); + return return_value; +} + +PyDoc_STRVAR(gc_get_referents__doc__, +"get_referents($module, /, *objs)\n" +"--\n" +"\n" +"Return the list of objects that are directly referred to by \'objs\'."); + +#define GC_GET_REFERENTS_METHODDEF \ + {"get_referents", _PyCFunction_CAST(gc_get_referents), METH_FASTCALL, gc_get_referents__doc__}, + +static PyObject * +gc_get_referents_impl(PyObject *module, PyObject *args); + +static PyObject * +gc_get_referents(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *__clinic_args = NULL; + + if (!_PyArg_CheckPositional("get_referents", nargs, 0, PY_SSIZE_T_MAX)) { + goto exit; + } + __clinic_args = PyTuple_New(nargs - 0); + if (!__clinic_args) { + goto exit; + } + for (Py_ssize_t i = 0; i < nargs - 0; ++i) { + PyTuple_SET_ITEM(__clinic_args, i, Py_NewRef(args[0 + i])); + } + return_value = gc_get_referents_impl(module, __clinic_args); + +exit: + Py_XDECREF(__clinic_args); + return return_value; +} + PyDoc_STRVAR(gc_get_objects__doc__, "get_objects($module, /, generation=None)\n" "--\n" @@ -424,4 +547,4 @@ gc_get_freeze_count(PyObject *module, PyObject *Py_UNUSED(ignored)) exit: return return_value; } -/*[clinic end generated code: output=66432ac0e17fd04f input=a9049054013a1b77]*/ +/*[clinic end generated code: output=258f92524c1141fc input=a9049054013a1b77]*/ diff --git a/Modules/clinic/grpmodule.c.h b/Modules/clinic/grpmodule.c.h index 38de3ce68ceb7f..1da061f3fd8eb1 100644 --- a/Modules/clinic/grpmodule.c.h +++ b/Modules/clinic/grpmodule.c.h @@ -3,10 +3,10 @@ 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() +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() #endif - +#include "pycore_modsupport.h" // _PyArg_UnpackKeywords() PyDoc_STRVAR(grp_getgrgid__doc__, "getgrgid($module, /, id)\n" @@ -146,4 +146,4 @@ grp_getgrall(PyObject *module, PyObject *Py_UNUSED(ignored)) { return grp_getgrall_impl(module); } -/*[clinic end generated code: output=e685227ed5d9be9f input=a9049054013a1b77]*/ +/*[clinic end generated code: output=2f7011384604d38d input=a9049054013a1b77]*/ diff --git a/Modules/clinic/itertoolsmodule.c.h b/Modules/clinic/itertoolsmodule.c.h index 32278bf715aa98..3ec479943a83d4 100644 --- a/Modules/clinic/itertoolsmodule.c.h +++ b/Modules/clinic/itertoolsmodule.c.h @@ -3,13 +3,14 @@ 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() +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() #endif - +#include "pycore_abstract.h" // _PyNumber_Index() +#include "pycore_modsupport.h" // _PyArg_UnpackKeywords() PyDoc_STRVAR(batched_new__doc__, -"batched(iterable, n)\n" +"batched(iterable, n, *, strict=False)\n" "--\n" "\n" "Batch data into tuples of length n. The last batch may be shorter than n.\n" @@ -24,10 +25,14 @@ PyDoc_STRVAR(batched_new__doc__, " ...\n" " (\'A\', \'B\', \'C\')\n" " (\'D\', \'E\', \'F\')\n" -" (\'G\',)"); +" (\'G\',)\n" +"\n" +"If \"strict\" is True, raises a ValueError if the final batch is shorter\n" +"than n."); static PyObject * -batched_new_impl(PyTypeObject *type, PyObject *iterable, Py_ssize_t n); +batched_new_impl(PyTypeObject *type, PyObject *iterable, Py_ssize_t n, + int strict); static PyObject * batched_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) @@ -35,14 +40,14 @@ batched_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) PyObject *return_value = NULL; #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - #define NUM_KEYWORDS 2 + #define NUM_KEYWORDS 3 static struct { PyGC_Head _this_is_not_used; PyObject_VAR_HEAD PyObject *ob_item[NUM_KEYWORDS]; } _kwtuple = { .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(iterable), &_Py_ID(n), }, + .ob_item = { &_Py_ID(iterable), &_Py_ID(n), &_Py_ID(strict), }, }; #undef NUM_KEYWORDS #define KWTUPLE (&_kwtuple.ob_base.ob_base) @@ -51,18 +56,20 @@ batched_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) # define KWTUPLE NULL #endif // !Py_BUILD_CORE - static const char * const _keywords[] = {"iterable", "n", NULL}; + static const char * const _keywords[] = {"iterable", "n", "strict", NULL}; static _PyArg_Parser _parser = { .keywords = _keywords, .fname = "batched", .kwtuple = KWTUPLE, }; #undef KWTUPLE - PyObject *argsbuf[2]; + PyObject *argsbuf[3]; PyObject * const *fastargs; Py_ssize_t nargs = PyTuple_GET_SIZE(args); + Py_ssize_t noptargs = nargs + (kwargs ? PyDict_GET_SIZE(kwargs) : 0) - 2; PyObject *iterable; Py_ssize_t n; + int strict = 0; fastargs = _PyArg_UnpackKeywords(_PyTuple_CAST(args)->ob_item, nargs, kwargs, NULL, &_parser, 2, 2, 0, argsbuf); if (!fastargs) { @@ -81,7 +88,15 @@ batched_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) } n = ival; } - return_value = batched_new_impl(type, iterable, n); + if (!noptargs) { + goto skip_optional_kwonly; + } + strict = PyObject_IsTrue(fastargs[2]); + if (strict < 0) { + goto exit; + } +skip_optional_kwonly: + return_value = batched_new_impl(type, iterable, n, strict); exit: return return_value; @@ -913,4 +928,4 @@ itertools_count(PyTypeObject *type, PyObject *args, PyObject *kwargs) exit: return return_value; } -/*[clinic end generated code: output=111cbd102c2a23c9 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=c6a515f765da86b5 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/mathmodule.c.h b/Modules/clinic/mathmodule.c.h index c16c1b083985f2..ca14c03f16f706 100644 --- a/Modules/clinic/mathmodule.c.h +++ b/Modules/clinic/mathmodule.c.h @@ -3,10 +3,10 @@ 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() +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() #endif - +#include "pycore_modsupport.h" // _PyArg_CheckPositional() PyDoc_STRVAR(math_ceil__doc__, "ceil($module, x, /)\n" @@ -950,4 +950,4 @@ math_ulp(PyObject *module, PyObject *arg) exit: return return_value; } -/*[clinic end generated code: output=91a0357265a2a553 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=6b2eeaed8d8a76d5 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/md5module.c.h b/Modules/clinic/md5module.c.h index b4602104f18042..7d4d3108dab9b6 100644 --- a/Modules/clinic/md5module.c.h +++ b/Modules/clinic/md5module.c.h @@ -3,10 +3,10 @@ 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() +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() #endif - +#include "pycore_modsupport.h" // _PyArg_UnpackKeywords() PyDoc_STRVAR(MD5Type_copy__doc__, "copy($self, /)\n" @@ -148,4 +148,4 @@ _md5_md5(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kw exit: return return_value; } -/*[clinic end generated code: output=b4924c9905cc9f34 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=bfadda44914804a8 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/overlapped.c.h b/Modules/clinic/overlapped.c.h index 89928312211b60..8b285e4a8f0a72 100644 --- a/Modules/clinic/overlapped.c.h +++ b/Modules/clinic/overlapped.c.h @@ -3,10 +3,11 @@ 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() +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() #endif - +#include "pycore_long.h" // _PyLong_UnsignedLong_Converter() +#include "pycore_modsupport.h" // _PyArg_CheckPositional() PyDoc_STRVAR(_overlapped_CreateIoCompletionPort__doc__, "CreateIoCompletionPort($module, handle, port, key, concurrency, /)\n" @@ -288,11 +289,11 @@ _overlapped_CreateEvent(PyObject *module, PyObject *const *args, Py_ssize_t narg goto exit; } EventAttributes = args[0]; - ManualReset = _PyLong_AsInt(args[1]); + ManualReset = PyLong_AsInt(args[1]); if (ManualReset == -1 && PyErr_Occurred()) { goto exit; } - InitialState = _PyLong_AsInt(args[2]); + InitialState = PyLong_AsInt(args[2]); if (InitialState == -1 && PyErr_Occurred()) { goto exit; } @@ -402,7 +403,7 @@ _overlapped_BindLocal(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!Socket && PyErr_Occurred()) { goto exit; } - Family = _PyLong_AsInt(args[1]); + Family = PyLong_AsInt(args[1]); if (Family == -1 && PyErr_Occurred()) { goto exit; } @@ -546,7 +547,7 @@ _overlapped_Overlapped_getresult(OverlappedObject *self, PyObject *const *args, if (nargs < 1) { goto skip_optional; } - wait = _PyLong_AsInt(args[0]); + wait = PyLong_AsInt(args[0]); if (wait == -1 && PyErr_Occurred()) { goto exit; } @@ -623,10 +624,6 @@ _overlapped_Overlapped_ReadFileInto(OverlappedObject *self, PyObject *const *arg if (PyObject_GetBuffer(args[1], &bufobj, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&bufobj, 'C')) { - _PyArg_BadArgument("ReadFileInto", "argument 2", "contiguous buffer", args[1]); - goto exit; - } return_value = _overlapped_Overlapped_ReadFileInto_impl(self, handle, &bufobj); exit: @@ -714,10 +711,6 @@ _overlapped_Overlapped_WSARecvInto(OverlappedObject *self, PyObject *const *args if (PyObject_GetBuffer(args[1], &bufobj, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&bufobj, 'C')) { - _PyArg_BadArgument("WSARecvInto", "argument 2", "contiguous buffer", args[1]); - goto exit; - } if (!_PyLong_UnsignedLong_Converter(args[2], &flags)) { goto exit; } @@ -762,10 +755,6 @@ _overlapped_Overlapped_WriteFile(OverlappedObject *self, PyObject *const *args, if (PyObject_GetBuffer(args[1], &bufobj, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&bufobj, 'C')) { - _PyArg_BadArgument("WriteFile", "argument 2", "contiguous buffer", args[1]); - goto exit; - } return_value = _overlapped_Overlapped_WriteFile_impl(self, handle, &bufobj); exit: @@ -808,10 +797,6 @@ _overlapped_Overlapped_WSASend(OverlappedObject *self, PyObject *const *args, Py if (PyObject_GetBuffer(args[1], &bufobj, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&bufobj, 'C')) { - _PyArg_BadArgument("WSASend", "argument 2", "contiguous buffer", args[1]); - goto exit; - } if (!_PyLong_UnsignedLong_Converter(args[2], &flags)) { goto exit; } @@ -1137,10 +1122,6 @@ _overlapped_Overlapped_WSASendTo(OverlappedObject *self, PyObject *const *args, if (PyObject_GetBuffer(args[1], &bufobj, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&bufobj, 'C')) { - _PyArg_BadArgument("WSASendTo", "argument 2", "contiguous buffer", args[1]); - goto exit; - } if (!_PyLong_UnsignedLong_Converter(args[2], &flags)) { goto exit; } @@ -1238,10 +1219,6 @@ _overlapped_Overlapped_WSARecvFromInto(OverlappedObject *self, PyObject *const * if (PyObject_GetBuffer(args[1], &bufobj, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&bufobj, 'C')) { - _PyArg_BadArgument("WSARecvFromInto", "argument 2", "contiguous buffer", args[1]); - goto exit; - } if (!_PyLong_UnsignedLong_Converter(args[2], &size)) { goto exit; } @@ -1262,4 +1239,4 @@ _overlapped_Overlapped_WSARecvFromInto(OverlappedObject *self, PyObject *const * return return_value; } -/*[clinic end generated code: output=05fd038b8a81272d input=a9049054013a1b77]*/ +/*[clinic end generated code: output=958cbddbcc355f47 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/posixmodule.c.h b/Modules/clinic/posixmodule.c.h index 81e3162e679d16..ba3e1cfa8dbc21 100644 --- a/Modules/clinic/posixmodule.c.h +++ b/Modules/clinic/posixmodule.c.h @@ -3,10 +3,13 @@ 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() +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() #endif - +#include "pycore_abstract.h" // _PyNumber_Index() +#include "pycore_fileutils.h" // _PyLong_FileDescriptor_Converter() +#include "pycore_long.h" // _PyLong_UnsignedInt_Converter() +#include "pycore_modsupport.h" // _PyArg_UnpackKeywords() PyDoc_STRVAR(os_stat__doc__, "stat($module, /, path, *, dir_fd=None, follow_symlinks=True)\n" @@ -262,7 +265,7 @@ os_access(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *k if (!path_converter(args[0], &path)) { goto exit; } - mode = _PyLong_AsInt(args[1]); + mode = PyLong_AsInt(args[1]); if (mode == -1 && PyErr_Occurred()) { goto exit; } @@ -327,7 +330,7 @@ os_ttyname(PyObject *module, PyObject *arg) PyObject *return_value = NULL; int fd; - fd = _PyLong_AsInt(arg); + fd = PyLong_AsInt(arg); if (fd == -1 && PyErr_Occurred()) { goto exit; } @@ -490,7 +493,8 @@ os_fchdir(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *k #endif /* defined(HAVE_FCHDIR) */ PyDoc_STRVAR(os_chmod__doc__, -"chmod($module, /, path, mode, *, dir_fd=None, follow_symlinks=True)\n" +"chmod($module, /, path, mode, *, dir_fd=None,\n" +" follow_symlinks=(os.name != \'nt\'))\n" "--\n" "\n" "Change the access permissions of a file.\n" @@ -559,7 +563,7 @@ os_chmod(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kw path_t path = PATH_T_INITIALIZE("chmod", "path", 0, PATH_HAVE_FCHMOD); int mode; int dir_fd = DEFAULT_DIR_FD; - int follow_symlinks = 1; + int follow_symlinks = CHMOD_DEFAULT_FOLLOW_SYMLINKS; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); if (!args) { @@ -568,7 +572,7 @@ os_chmod(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kw if (!path_converter(args[0], &path)) { goto exit; } - mode = _PyLong_AsInt(args[1]); + mode = PyLong_AsInt(args[1]); if (mode == -1 && PyErr_Occurred()) { goto exit; } @@ -597,7 +601,7 @@ os_chmod(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kw return return_value; } -#if defined(HAVE_FCHMOD) +#if (defined(HAVE_FCHMOD) || defined(MS_WINDOWS)) PyDoc_STRVAR(os_fchmod__doc__, "fchmod($module, /, fd, mode)\n" @@ -658,11 +662,11 @@ os_fchmod(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *k if (!args) { goto exit; } - fd = _PyLong_AsInt(args[0]); + fd = PyLong_AsInt(args[0]); if (fd == -1 && PyErr_Occurred()) { goto exit; } - mode = _PyLong_AsInt(args[1]); + mode = PyLong_AsInt(args[1]); if (mode == -1 && PyErr_Occurred()) { goto exit; } @@ -672,9 +676,9 @@ os_fchmod(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *k return return_value; } -#endif /* defined(HAVE_FCHMOD) */ +#endif /* (defined(HAVE_FCHMOD) || defined(MS_WINDOWS)) */ -#if defined(HAVE_LCHMOD) +#if (defined(HAVE_LCHMOD) || defined(MS_WINDOWS)) PyDoc_STRVAR(os_lchmod__doc__, "lchmod($module, /, path, mode)\n" @@ -731,7 +735,7 @@ os_lchmod(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *k if (!path_converter(args[0], &path)) { goto exit; } - mode = _PyLong_AsInt(args[1]); + mode = PyLong_AsInt(args[1]); if (mode == -1 && PyErr_Occurred()) { goto exit; } @@ -744,7 +748,7 @@ os_lchmod(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *k return return_value; } -#endif /* defined(HAVE_LCHMOD) */ +#endif /* (defined(HAVE_LCHMOD) || defined(MS_WINDOWS)) */ #if defined(HAVE_CHFLAGS) @@ -1284,7 +1288,7 @@ os_fchown(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *k if (!args) { goto exit; } - fd = _PyLong_AsInt(args[0]); + fd = PyLong_AsInt(args[0]); if (fd == -1 && PyErr_Occurred()) { goto exit; } @@ -1846,6 +1850,40 @@ os__getfinalpathname(PyObject *module, PyObject *arg) #if defined(MS_WINDOWS) +PyDoc_STRVAR(os__findfirstfile__doc__, +"_findfirstfile($module, path, /)\n" +"--\n" +"\n" +"A function to get the real file name without accessing the file in Windows."); + +#define OS__FINDFIRSTFILE_METHODDEF \ + {"_findfirstfile", (PyCFunction)os__findfirstfile, METH_O, os__findfirstfile__doc__}, + +static PyObject * +os__findfirstfile_impl(PyObject *module, path_t *path); + +static PyObject * +os__findfirstfile(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + path_t path = PATH_T_INITIALIZE("_findfirstfile", "path", 0, 0); + + if (!path_converter(arg, &path)) { + goto exit; + } + return_value = os__findfirstfile_impl(module, &path); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + + return return_value; +} + +#endif /* defined(MS_WINDOWS) */ + +#if defined(MS_WINDOWS) + PyDoc_STRVAR(os__getvolumepathname__doc__, "_getvolumepathname($module, /, path)\n" "--\n" @@ -1975,7 +2013,7 @@ os__path_splitroot(PyObject *module, PyObject *const *args, Py_ssize_t nargs, Py #if defined(MS_WINDOWS) PyDoc_STRVAR(os__path_isdir__doc__, -"_path_isdir($module, /, path)\n" +"_path_isdir($module, /, s)\n" "--\n" "\n" "Return true if the pathname refers to an existing directory."); @@ -1984,7 +2022,7 @@ PyDoc_STRVAR(os__path_isdir__doc__, {"_path_isdir", _PyCFunction_CAST(os__path_isdir), METH_FASTCALL|METH_KEYWORDS, os__path_isdir__doc__}, static PyObject * -os__path_isdir_impl(PyObject *module, PyObject *path); +os__path_isdir_impl(PyObject *module, PyObject *s); static PyObject * os__path_isdir(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) @@ -1999,7 +2037,7 @@ os__path_isdir(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObje PyObject *ob_item[NUM_KEYWORDS]; } _kwtuple = { .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(path), }, + .ob_item = { &_Py_ID(s), }, }; #undef NUM_KEYWORDS #define KWTUPLE (&_kwtuple.ob_base.ob_base) @@ -2008,7 +2046,7 @@ os__path_isdir(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObje # define KWTUPLE NULL #endif // !Py_BUILD_CORE - static const char * const _keywords[] = {"path", NULL}; + static const char * const _keywords[] = {"s", NULL}; static _PyArg_Parser _parser = { .keywords = _keywords, .fname = "_path_isdir", @@ -2016,14 +2054,14 @@ os__path_isdir(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObje }; #undef KWTUPLE PyObject *argsbuf[1]; - PyObject *path; + PyObject *s; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); if (!args) { goto exit; } - path = args[0]; - return_value = os__path_isdir_impl(module, path); + s = args[0]; + return_value = os__path_isdir_impl(module, s); exit: return return_value; @@ -2329,7 +2367,7 @@ os_mkdir(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kw goto skip_optional_pos; } if (args[1]) { - mode = _PyLong_AsInt(args[1]); + mode = PyLong_AsInt(args[1]); if (mode == -1 && PyErr_Occurred()) { goto exit; } @@ -2374,7 +2412,7 @@ os_nice(PyObject *module, PyObject *arg) PyObject *return_value = NULL; int increment; - increment = _PyLong_AsInt(arg); + increment = PyLong_AsInt(arg); if (increment == -1 && PyErr_Occurred()) { goto exit; } @@ -2437,11 +2475,11 @@ os_getpriority(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObje if (!args) { goto exit; } - which = _PyLong_AsInt(args[0]); + which = PyLong_AsInt(args[0]); if (which == -1 && PyErr_Occurred()) { goto exit; } - who = _PyLong_AsInt(args[1]); + who = PyLong_AsInt(args[1]); if (who == -1 && PyErr_Occurred()) { goto exit; } @@ -2505,15 +2543,15 @@ os_setpriority(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObje if (!args) { goto exit; } - which = _PyLong_AsInt(args[0]); + which = PyLong_AsInt(args[0]); if (which == -1 && PyErr_Occurred()) { goto exit; } - who = _PyLong_AsInt(args[1]); + who = PyLong_AsInt(args[1]); if (who == -1 && PyErr_Occurred()) { goto exit; } - priority = _PyLong_AsInt(args[2]); + priority = PyLong_AsInt(args[2]); if (priority == -1 && PyErr_Occurred()) { goto exit; } @@ -2944,7 +2982,7 @@ os_umask(PyObject *module, PyObject *arg) PyObject *return_value = NULL; int mask; - mask = _PyLong_AsInt(arg); + mask = PyLong_AsInt(arg); if (mask == -1 && PyErr_Occurred()) { goto exit; } @@ -3298,7 +3336,7 @@ os__exit(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kw if (!args) { goto exit; } - status = _PyLong_AsInt(args[0]); + status = PyLong_AsInt(args[0]); if (status == -1 && PyErr_Occurred()) { goto exit; } @@ -3759,7 +3797,7 @@ os_spawnv(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("spawnv", nargs, 3, 3)) { goto exit; } - mode = _PyLong_AsInt(args[0]); + mode = PyLong_AsInt(args[0]); if (mode == -1 && PyErr_Occurred()) { goto exit; } @@ -3814,7 +3852,7 @@ os_spawnve(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("spawnve", nargs, 4, 4)) { goto exit; } - mode = _PyLong_AsInt(args[0]); + mode = PyLong_AsInt(args[0]); if (mode == -1 && PyErr_Occurred()) { goto exit; } @@ -4023,7 +4061,7 @@ os_sched_get_priority_max(PyObject *module, PyObject *const *args, Py_ssize_t na if (!args) { goto exit; } - policy = _PyLong_AsInt(args[0]); + policy = PyLong_AsInt(args[0]); if (policy == -1 && PyErr_Occurred()) { goto exit; } @@ -4085,7 +4123,7 @@ os_sched_get_priority_min(PyObject *module, PyObject *const *args, Py_ssize_t na if (!args) { goto exit; } - policy = _PyLong_AsInt(args[0]); + policy = PyLong_AsInt(args[0]); if (policy == -1 && PyErr_Occurred()) { goto exit; } @@ -4644,7 +4682,7 @@ os_getgrouplist(PyObject *module, PyObject *const *args, Py_ssize_t nargs) PyErr_SetString(PyExc_ValueError, "embedded null character"); goto exit; } - basegid = _PyLong_AsInt(args[1]); + basegid = PyLong_AsInt(args[1]); if (basegid == -1 && PyErr_Occurred()) { goto exit; } @@ -4762,7 +4800,7 @@ os_initgroups(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!PyUnicode_FSConverter(args[0], &oname)) { goto exit; } - gid = _PyLong_AsInt(args[1]); + gid = PyLong_AsInt(args[1]); if (gid == -1 && PyErr_Occurred()) { goto exit; } @@ -5078,7 +5116,7 @@ os_plock(PyObject *module, PyObject *arg) PyObject *return_value = NULL; int op; - op = _PyLong_AsInt(arg); + op = PyLong_AsInt(arg); if (op == -1 && PyErr_Occurred()) { goto exit; } @@ -5356,7 +5394,7 @@ os_wait3(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kw if (!args) { goto exit; } - options = _PyLong_AsInt(args[0]); + options = PyLong_AsInt(args[0]); if (options == -1 && PyErr_Occurred()) { goto exit; } @@ -5429,7 +5467,7 @@ os_wait4(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kw #endif /* defined(HAVE_WAIT4) */ -#if (defined(HAVE_WAITID) && !defined(__APPLE__)) +#if defined(HAVE_WAITID) PyDoc_STRVAR(os_waitid__doc__, "waitid($module, idtype, id, options, /)\n" @@ -5472,7 +5510,7 @@ os_waitid(PyObject *module, PyObject *const *args, Py_ssize_t nargs) return return_value; } -#endif /* (defined(HAVE_WAITID) && !defined(__APPLE__)) */ +#endif /* defined(HAVE_WAITID) */ #if defined(HAVE_WAITPID) @@ -5699,7 +5737,7 @@ os_setns(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kw if (!noptargs) { goto skip_optional_pos; } - nstype = _PyLong_AsInt(args[1]); + nstype = PyLong_AsInt(args[1]); if (nstype == -1 && PyErr_Occurred()) { goto exit; } @@ -5765,7 +5803,7 @@ os_unshare(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject * if (!args) { goto exit; } - flags = _PyLong_AsInt(args[0]); + flags = PyLong_AsInt(args[0]); if (flags == -1 && PyErr_Occurred()) { goto exit; } @@ -5960,8 +5998,6 @@ os_symlink(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject * #endif /* defined(HAVE_SYMLINK) */ -#if defined(HAVE_TIMES) - PyDoc_STRVAR(os_times__doc__, "times($module, /)\n" "--\n" @@ -5984,7 +6020,375 @@ os_times(PyObject *module, PyObject *Py_UNUSED(ignored)) return os_times_impl(module); } -#endif /* defined(HAVE_TIMES) */ +#if defined(HAVE_TIMERFD_CREATE) + +PyDoc_STRVAR(os_timerfd_create__doc__, +"timerfd_create($module, clockid, /, *, flags=0)\n" +"--\n" +"\n" +"Create and return a timer file descriptor.\n" +"\n" +" clockid\n" +" A valid clock ID constant as timer file descriptor.\n" +"\n" +" time.CLOCK_REALTIME\n" +" time.CLOCK_MONOTONIC\n" +" time.CLOCK_BOOTTIME\n" +" flags\n" +" 0 or a bit mask of os.TFD_NONBLOCK or os.TFD_CLOEXEC.\n" +"\n" +" os.TFD_NONBLOCK\n" +" If *TFD_NONBLOCK* is set as a flag, read doesn\'t blocks.\n" +" If *TFD_NONBLOCK* is not set as a flag, read block until the timer fires.\n" +"\n" +" os.TFD_CLOEXEC\n" +" If *TFD_CLOEXEC* is set as a flag, enable the close-on-exec flag"); + +#define OS_TIMERFD_CREATE_METHODDEF \ + {"timerfd_create", _PyCFunction_CAST(os_timerfd_create), METH_FASTCALL|METH_KEYWORDS, os_timerfd_create__doc__}, + +static PyObject * +os_timerfd_create_impl(PyObject *module, int clockid, int flags); + +static PyObject * +os_timerfd_create(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(flags), }, + }; + #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[] = {"", "flags", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "timerfd_create", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[2]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + int clockid; + int flags = 0; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + clockid = PyLong_AsInt(args[0]); + if (clockid == -1 && PyErr_Occurred()) { + goto exit; + } + if (!noptargs) { + goto skip_optional_kwonly; + } + flags = PyLong_AsInt(args[1]); + if (flags == -1 && PyErr_Occurred()) { + goto exit; + } +skip_optional_kwonly: + return_value = os_timerfd_create_impl(module, clockid, flags); + +exit: + return return_value; +} + +#endif /* defined(HAVE_TIMERFD_CREATE) */ + +#if defined(HAVE_TIMERFD_CREATE) + +PyDoc_STRVAR(os_timerfd_settime__doc__, +"timerfd_settime($module, fd, /, *, flags=0, initial=0.0, interval=0.0)\n" +"--\n" +"\n" +"Alter a timer file descriptor\'s internal timer in seconds.\n" +"\n" +" fd\n" +" A timer file descriptor.\n" +" flags\n" +" 0 or a bit mask of TFD_TIMER_ABSTIME or TFD_TIMER_CANCEL_ON_SET.\n" +" initial\n" +" The initial expiration time, in seconds.\n" +" interval\n" +" The timer\'s interval, in seconds."); + +#define OS_TIMERFD_SETTIME_METHODDEF \ + {"timerfd_settime", _PyCFunction_CAST(os_timerfd_settime), METH_FASTCALL|METH_KEYWORDS, os_timerfd_settime__doc__}, + +static PyObject * +os_timerfd_settime_impl(PyObject *module, int fd, int flags, double initial, + double interval); + +static PyObject * +os_timerfd_settime(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 3 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(flags), &_Py_ID(initial), &_Py_ID(interval), }, + }; + #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[] = {"", "flags", "initial", "interval", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "timerfd_settime", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[4]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + int fd; + int flags = 0; + double initial = 0.0; + double interval = 0.0; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + if (!_PyLong_FileDescriptor_Converter(args[0], &fd)) { + goto exit; + } + if (!noptargs) { + goto skip_optional_kwonly; + } + if (args[1]) { + flags = PyLong_AsInt(args[1]); + if (flags == -1 && PyErr_Occurred()) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + if (args[2]) { + if (PyFloat_CheckExact(args[2])) { + initial = PyFloat_AS_DOUBLE(args[2]); + } + else + { + initial = PyFloat_AsDouble(args[2]); + if (initial == -1.0 && PyErr_Occurred()) { + goto exit; + } + } + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + if (PyFloat_CheckExact(args[3])) { + interval = PyFloat_AS_DOUBLE(args[3]); + } + else + { + interval = PyFloat_AsDouble(args[3]); + if (interval == -1.0 && PyErr_Occurred()) { + goto exit; + } + } +skip_optional_kwonly: + return_value = os_timerfd_settime_impl(module, fd, flags, initial, interval); + +exit: + return return_value; +} + +#endif /* defined(HAVE_TIMERFD_CREATE) */ + +#if defined(HAVE_TIMERFD_CREATE) + +PyDoc_STRVAR(os_timerfd_settime_ns__doc__, +"timerfd_settime_ns($module, fd, /, *, flags=0, initial=0, interval=0)\n" +"--\n" +"\n" +"Alter a timer file descriptor\'s internal timer in nanoseconds.\n" +"\n" +" fd\n" +" A timer file descriptor.\n" +" flags\n" +" 0 or a bit mask of TFD_TIMER_ABSTIME or TFD_TIMER_CANCEL_ON_SET.\n" +" initial\n" +" initial expiration timing in seconds.\n" +" interval\n" +" interval for the timer in seconds."); + +#define OS_TIMERFD_SETTIME_NS_METHODDEF \ + {"timerfd_settime_ns", _PyCFunction_CAST(os_timerfd_settime_ns), METH_FASTCALL|METH_KEYWORDS, os_timerfd_settime_ns__doc__}, + +static PyObject * +os_timerfd_settime_ns_impl(PyObject *module, int fd, int flags, + long long initial, long long interval); + +static PyObject * +os_timerfd_settime_ns(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 3 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(flags), &_Py_ID(initial), &_Py_ID(interval), }, + }; + #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[] = {"", "flags", "initial", "interval", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "timerfd_settime_ns", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[4]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + int fd; + int flags = 0; + long long initial = 0; + long long interval = 0; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + if (!_PyLong_FileDescriptor_Converter(args[0], &fd)) { + goto exit; + } + if (!noptargs) { + goto skip_optional_kwonly; + } + if (args[1]) { + flags = PyLong_AsInt(args[1]); + if (flags == -1 && PyErr_Occurred()) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + if (args[2]) { + initial = PyLong_AsLongLong(args[2]); + if (initial == -1 && PyErr_Occurred()) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + interval = PyLong_AsLongLong(args[3]); + if (interval == -1 && PyErr_Occurred()) { + goto exit; + } +skip_optional_kwonly: + return_value = os_timerfd_settime_ns_impl(module, fd, flags, initial, interval); + +exit: + return return_value; +} + +#endif /* defined(HAVE_TIMERFD_CREATE) */ + +#if defined(HAVE_TIMERFD_CREATE) + +PyDoc_STRVAR(os_timerfd_gettime__doc__, +"timerfd_gettime($module, fd, /)\n" +"--\n" +"\n" +"Return a tuple of a timer file descriptor\'s (interval, next expiration) in float seconds.\n" +"\n" +" fd\n" +" A timer file descriptor."); + +#define OS_TIMERFD_GETTIME_METHODDEF \ + {"timerfd_gettime", (PyCFunction)os_timerfd_gettime, METH_O, os_timerfd_gettime__doc__}, + +static PyObject * +os_timerfd_gettime_impl(PyObject *module, int fd); + +static PyObject * +os_timerfd_gettime(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int fd; + + if (!_PyLong_FileDescriptor_Converter(arg, &fd)) { + goto exit; + } + return_value = os_timerfd_gettime_impl(module, fd); + +exit: + return return_value; +} + +#endif /* defined(HAVE_TIMERFD_CREATE) */ + +#if defined(HAVE_TIMERFD_CREATE) + +PyDoc_STRVAR(os_timerfd_gettime_ns__doc__, +"timerfd_gettime_ns($module, fd, /)\n" +"--\n" +"\n" +"Return a tuple of a timer file descriptor\'s (interval, next expiration) in nanoseconds.\n" +"\n" +" fd\n" +" A timer file descriptor."); + +#define OS_TIMERFD_GETTIME_NS_METHODDEF \ + {"timerfd_gettime_ns", (PyCFunction)os_timerfd_gettime_ns, METH_O, os_timerfd_gettime_ns__doc__}, + +static PyObject * +os_timerfd_gettime_ns_impl(PyObject *module, int fd); + +static PyObject * +os_timerfd_gettime_ns(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int fd; + + if (!_PyLong_FileDescriptor_Converter(arg, &fd)) { + goto exit; + } + return_value = os_timerfd_gettime_ns_impl(module, fd); + +exit: + return return_value; +} + +#endif /* defined(HAVE_TIMERFD_CREATE) */ #if defined(HAVE_GETSID) @@ -6092,7 +6496,7 @@ os_tcgetpgrp(PyObject *module, PyObject *arg) PyObject *return_value = NULL; int fd; - fd = _PyLong_AsInt(arg); + fd = PyLong_AsInt(arg); if (fd == -1 && PyErr_Occurred()) { goto exit; } @@ -6198,7 +6602,7 @@ os_open(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwn if (!path_converter(args[0], &path)) { goto exit; } - flags = _PyLong_AsInt(args[1]); + flags = PyLong_AsInt(args[1]); if (flags == -1 && PyErr_Occurred()) { goto exit; } @@ -6206,7 +6610,7 @@ os_open(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwn goto skip_optional_pos; } if (args[2]) { - mode = _PyLong_AsInt(args[2]); + mode = PyLong_AsInt(args[2]); if (mode == -1 && PyErr_Occurred()) { goto exit; } @@ -6283,7 +6687,7 @@ os_close(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kw if (!args) { goto exit; } - fd = _PyLong_AsInt(args[0]); + fd = PyLong_AsInt(args[0]); if (fd == -1 && PyErr_Occurred()) { goto exit; } @@ -6315,11 +6719,11 @@ os_closerange(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("closerange", nargs, 2, 2)) { goto exit; } - fd_low = _PyLong_AsInt(args[0]); + fd_low = PyLong_AsInt(args[0]); if (fd_low == -1 && PyErr_Occurred()) { goto exit; } - fd_high = _PyLong_AsInt(args[1]); + fd_high = PyLong_AsInt(args[1]); if (fd_high == -1 && PyErr_Occurred()) { goto exit; } @@ -6348,7 +6752,7 @@ os_dup(PyObject *module, PyObject *arg) int fd; int _return_value; - fd = _PyLong_AsInt(arg); + fd = PyLong_AsInt(arg); if (fd == -1 && PyErr_Occurred()) { goto exit; } @@ -6416,11 +6820,11 @@ os_dup2(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwn if (!args) { goto exit; } - fd = _PyLong_AsInt(args[0]); + fd = PyLong_AsInt(args[0]); if (fd == -1 && PyErr_Occurred()) { goto exit; } - fd2 = _PyLong_AsInt(args[1]); + fd2 = PyLong_AsInt(args[1]); if (fd2 == -1 && PyErr_Occurred()) { goto exit; } @@ -6476,11 +6880,11 @@ os_lockf(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("lockf", nargs, 3, 3)) { goto exit; } - fd = _PyLong_AsInt(args[0]); + fd = PyLong_AsInt(args[0]); if (fd == -1 && PyErr_Occurred()) { goto exit; } - command = _PyLong_AsInt(args[1]); + command = PyLong_AsInt(args[1]); if (command == -1 && PyErr_Occurred()) { goto exit; } @@ -6496,13 +6900,22 @@ os_lockf(PyObject *module, PyObject *const *args, Py_ssize_t nargs) #endif /* defined(HAVE_LOCKF) */ PyDoc_STRVAR(os_lseek__doc__, -"lseek($module, fd, position, how, /)\n" +"lseek($module, fd, position, whence, /)\n" "--\n" "\n" "Set the position of a file descriptor. Return the new position.\n" "\n" -"Return the new cursor position in number of bytes\n" -"relative to the beginning of the file."); +" fd\n" +" An open file descriptor, as returned by os.open().\n" +" position\n" +" Position, interpreted relative to \'whence\'.\n" +" whence\n" +" The relative position to seek from. Valid values are:\n" +" - SEEK_SET: seek from the start of the file.\n" +" - SEEK_CUR: seek from the current file position.\n" +" - SEEK_END: seek from the end of the file.\n" +"\n" +"The return value is the number of bytes relative to the beginning of the file."); #define OS_LSEEK_METHODDEF \ {"lseek", _PyCFunction_CAST(os_lseek), METH_FASTCALL, os_lseek__doc__}, @@ -6522,14 +6935,14 @@ os_lseek(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("lseek", nargs, 3, 3)) { goto exit; } - fd = _PyLong_AsInt(args[0]); + fd = PyLong_AsInt(args[0]); if (fd == -1 && PyErr_Occurred()) { goto exit; } if (!Py_off_t_converter(args[1], &position)) { goto exit; } - how = _PyLong_AsInt(args[2]); + how = PyLong_AsInt(args[2]); if (how == -1 && PyErr_Occurred()) { goto exit; } @@ -6565,7 +6978,7 @@ os_read(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("read", nargs, 2, 2)) { goto exit; } - fd = _PyLong_AsInt(args[0]); + fd = PyLong_AsInt(args[0]); if (fd == -1 && PyErr_Occurred()) { goto exit; } @@ -6620,7 +7033,7 @@ os_readv(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("readv", nargs, 2, 2)) { goto exit; } - fd = _PyLong_AsInt(args[0]); + fd = PyLong_AsInt(args[0]); if (fd == -1 && PyErr_Occurred()) { goto exit; } @@ -6665,7 +7078,7 @@ os_pread(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("pread", nargs, 3, 3)) { goto exit; } - fd = _PyLong_AsInt(args[0]); + fd = PyLong_AsInt(args[0]); if (fd == -1 && PyErr_Occurred()) { goto exit; } @@ -6734,7 +7147,7 @@ os_preadv(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("preadv", nargs, 3, 4)) { goto exit; } - fd = _PyLong_AsInt(args[0]); + fd = PyLong_AsInt(args[0]); if (fd == -1 && PyErr_Occurred()) { goto exit; } @@ -6745,7 +7158,7 @@ os_preadv(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (nargs < 4) { goto skip_optional; } - flags = _PyLong_AsInt(args[3]); + flags = PyLong_AsInt(args[3]); if (flags == -1 && PyErr_Occurred()) { goto exit; } @@ -6785,17 +7198,13 @@ os_write(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("write", nargs, 2, 2)) { goto exit; } - fd = _PyLong_AsInt(args[0]); + fd = PyLong_AsInt(args[0]); if (fd == -1 && PyErr_Occurred()) { goto exit; } if (PyObject_GetBuffer(args[1], &data, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("write", "argument 2", "contiguous buffer", args[1]); - goto exit; - } _return_value = os_write_impl(module, fd, &data); if ((_return_value == -1) && PyErr_Occurred()) { goto exit; @@ -6871,11 +7280,11 @@ os_sendfile(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject if (!args) { goto exit; } - out_fd = _PyLong_AsInt(args[0]); + out_fd = PyLong_AsInt(args[0]); if (out_fd == -1 && PyErr_Occurred()) { goto exit; } - in_fd = _PyLong_AsInt(args[1]); + in_fd = PyLong_AsInt(args[1]); if (in_fd == -1 && PyErr_Occurred()) { goto exit; } @@ -6900,7 +7309,7 @@ os_sendfile(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject goto skip_optional_pos; } } - flags = _PyLong_AsInt(args[6]); + flags = PyLong_AsInt(args[6]); if (flags == -1 && PyErr_Occurred()) { goto exit; } @@ -6973,11 +7382,11 @@ os_sendfile(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject if (!args) { goto exit; } - out_fd = _PyLong_AsInt(args[0]); + out_fd = PyLong_AsInt(args[0]); if (out_fd == -1 && PyErr_Occurred()) { goto exit; } - in_fd = _PyLong_AsInt(args[1]); + in_fd = PyLong_AsInt(args[1]); if (in_fd == -1 && PyErr_Occurred()) { goto exit; } @@ -7011,7 +7420,7 @@ os_sendfile(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject goto skip_optional_pos; } } - flags = _PyLong_AsInt(args[6]); + flags = PyLong_AsInt(args[6]); if (flags == -1 && PyErr_Occurred()) { goto exit; } @@ -7078,11 +7487,11 @@ os_sendfile(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject if (!args) { goto exit; } - out_fd = _PyLong_AsInt(args[0]); + out_fd = PyLong_AsInt(args[0]); if (out_fd == -1 && PyErr_Occurred()) { goto exit; } - in_fd = _PyLong_AsInt(args[1]); + in_fd = PyLong_AsInt(args[1]); if (in_fd == -1 && PyErr_Occurred()) { goto exit; } @@ -7132,15 +7541,15 @@ os__fcopyfile(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("_fcopyfile", nargs, 3, 3)) { goto exit; } - in_fd = _PyLong_AsInt(args[0]); + in_fd = PyLong_AsInt(args[0]); if (in_fd == -1 && PyErr_Occurred()) { goto exit; } - out_fd = _PyLong_AsInt(args[1]); + out_fd = PyLong_AsInt(args[1]); if (out_fd == -1 && PyErr_Occurred()) { goto exit; } - flags = _PyLong_AsInt(args[2]); + flags = PyLong_AsInt(args[2]); if (flags == -1 && PyErr_Occurred()) { goto exit; } @@ -7203,7 +7612,7 @@ os_fstat(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kw if (!args) { goto exit; } - fd = _PyLong_AsInt(args[0]); + fd = PyLong_AsInt(args[0]); if (fd == -1 && PyErr_Occurred()) { goto exit; } @@ -7235,7 +7644,7 @@ os_isatty(PyObject *module, PyObject *arg) int fd; int _return_value; - fd = _PyLong_AsInt(arg); + fd = PyLong_AsInt(arg); if (fd == -1 && PyErr_Occurred()) { goto exit; } @@ -7300,7 +7709,7 @@ os_pipe2(PyObject *module, PyObject *arg) PyObject *return_value = NULL; int flags; - flags = _PyLong_AsInt(arg); + flags = PyLong_AsInt(arg); if (flags == -1 && PyErr_Occurred()) { goto exit; } @@ -7340,7 +7749,7 @@ os_writev(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("writev", nargs, 2, 2)) { goto exit; } - fd = _PyLong_AsInt(args[0]); + fd = PyLong_AsInt(args[0]); if (fd == -1 && PyErr_Occurred()) { goto exit; } @@ -7387,17 +7796,13 @@ os_pwrite(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("pwrite", nargs, 3, 3)) { goto exit; } - fd = _PyLong_AsInt(args[0]); + fd = PyLong_AsInt(args[0]); if (fd == -1 && PyErr_Occurred()) { goto exit; } if (PyObject_GetBuffer(args[1], &buffer, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&buffer, 'C')) { - _PyArg_BadArgument("pwrite", "argument 2", "contiguous buffer", args[1]); - goto exit; - } if (!Py_off_t_converter(args[2], &offset)) { goto exit; } @@ -7461,7 +7866,7 @@ os_pwritev(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("pwritev", nargs, 3, 4)) { goto exit; } - fd = _PyLong_AsInt(args[0]); + fd = PyLong_AsInt(args[0]); if (fd == -1 && PyErr_Occurred()) { goto exit; } @@ -7472,7 +7877,7 @@ os_pwritev(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (nargs < 4) { goto skip_optional; } - flags = _PyLong_AsInt(args[3]); + flags = PyLong_AsInt(args[3]); if (flags == -1 && PyErr_Occurred()) { goto exit; } @@ -7560,11 +7965,11 @@ os_copy_file_range(PyObject *module, PyObject *const *args, Py_ssize_t nargs, Py if (!args) { goto exit; } - src = _PyLong_AsInt(args[0]); + src = PyLong_AsInt(args[0]); if (src == -1 && PyErr_Occurred()) { goto exit; } - dst = _PyLong_AsInt(args[1]); + dst = PyLong_AsInt(args[1]); if (dst == -1 && PyErr_Occurred()) { goto exit; } @@ -7675,11 +8080,11 @@ os_splice(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *k if (!args) { goto exit; } - src = _PyLong_AsInt(args[0]); + src = PyLong_AsInt(args[0]); if (src == -1 && PyErr_Occurred()) { goto exit; } - dst = _PyLong_AsInt(args[1]); + dst = PyLong_AsInt(args[1]); if (dst == -1 && PyErr_Occurred()) { goto exit; } @@ -7787,7 +8192,7 @@ os_mkfifo(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *k goto skip_optional_pos; } if (args[1]) { - mode = _PyLong_AsInt(args[1]); + mode = PyLong_AsInt(args[1]); if (mode == -1 && PyErr_Occurred()) { goto exit; } @@ -7888,7 +8293,7 @@ os_mknod(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kw goto skip_optional_pos; } if (args[1]) { - mode = _PyLong_AsInt(args[1]); + mode = PyLong_AsInt(args[1]); if (mode == -1 && PyErr_Occurred()) { goto exit; } @@ -8020,11 +8425,11 @@ os_makedev(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("makedev", nargs, 2, 2)) { goto exit; } - major = _PyLong_AsInt(args[0]); + major = PyLong_AsInt(args[0]); if (major == -1 && PyErr_Occurred()) { goto exit; } - minor = _PyLong_AsInt(args[1]); + minor = PyLong_AsInt(args[1]); if (minor == -1 && PyErr_Occurred()) { goto exit; } @@ -8064,7 +8469,7 @@ os_ftruncate(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("ftruncate", nargs, 2, 2)) { goto exit; } - fd = _PyLong_AsInt(args[0]); + fd = PyLong_AsInt(args[0]); if (fd == -1 && PyErr_Occurred()) { goto exit; } @@ -8150,7 +8555,7 @@ os_truncate(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject #endif /* (defined HAVE_TRUNCATE || defined MS_WINDOWS) */ -#if (defined(HAVE_POSIX_FALLOCATE) && !defined(POSIX_FADVISE_AIX_BUG)) +#if (defined(HAVE_POSIX_FALLOCATE) && !defined(POSIX_FADVISE_AIX_BUG) && !defined(__wasi__)) PyDoc_STRVAR(os_posix_fallocate__doc__, "posix_fallocate($module, fd, offset, length, /)\n" @@ -8179,7 +8584,7 @@ os_posix_fallocate(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("posix_fallocate", nargs, 3, 3)) { goto exit; } - fd = _PyLong_AsInt(args[0]); + fd = PyLong_AsInt(args[0]); if (fd == -1 && PyErr_Occurred()) { goto exit; } @@ -8195,7 +8600,7 @@ os_posix_fallocate(PyObject *module, PyObject *const *args, Py_ssize_t nargs) return return_value; } -#endif /* (defined(HAVE_POSIX_FALLOCATE) && !defined(POSIX_FADVISE_AIX_BUG)) */ +#endif /* (defined(HAVE_POSIX_FALLOCATE) && !defined(POSIX_FADVISE_AIX_BUG) && !defined(__wasi__)) */ #if (defined(HAVE_POSIX_FADVISE) && !defined(POSIX_FADVISE_AIX_BUG)) @@ -8232,7 +8637,7 @@ os_posix_fadvise(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("posix_fadvise", nargs, 4, 4)) { goto exit; } - fd = _PyLong_AsInt(args[0]); + fd = PyLong_AsInt(args[0]); if (fd == -1 && PyErr_Occurred()) { goto exit; } @@ -8242,7 +8647,7 @@ os_posix_fadvise(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!Py_off_t_converter(args[2], &length)) { goto exit; } - advice = _PyLong_AsInt(args[3]); + advice = PyLong_AsInt(args[3]); if (advice == -1 && PyErr_Occurred()) { goto exit; } @@ -8424,7 +8829,7 @@ os_strerror(PyObject *module, PyObject *arg) PyObject *return_value = NULL; int code; - code = _PyLong_AsInt(arg); + code = PyLong_AsInt(arg); if (code == -1 && PyErr_Occurred()) { goto exit; } @@ -8455,7 +8860,7 @@ os_WCOREDUMP(PyObject *module, PyObject *arg) int status; int _return_value; - status = _PyLong_AsInt(arg); + status = PyLong_AsInt(arg); if (status == -1 && PyErr_Occurred()) { goto exit; } @@ -8525,7 +8930,7 @@ os_WIFCONTINUED(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObj if (!args) { goto exit; } - status = _PyLong_AsInt(args[0]); + status = PyLong_AsInt(args[0]); if (status == -1 && PyErr_Occurred()) { goto exit; } @@ -8592,7 +8997,7 @@ os_WIFSTOPPED(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObjec if (!args) { goto exit; } - status = _PyLong_AsInt(args[0]); + status = PyLong_AsInt(args[0]); if (status == -1 && PyErr_Occurred()) { goto exit; } @@ -8659,7 +9064,7 @@ os_WIFSIGNALED(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObje if (!args) { goto exit; } - status = _PyLong_AsInt(args[0]); + status = PyLong_AsInt(args[0]); if (status == -1 && PyErr_Occurred()) { goto exit; } @@ -8726,7 +9131,7 @@ os_WIFEXITED(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject if (!args) { goto exit; } - status = _PyLong_AsInt(args[0]); + status = PyLong_AsInt(args[0]); if (status == -1 && PyErr_Occurred()) { goto exit; } @@ -8793,7 +9198,7 @@ os_WEXITSTATUS(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObje if (!args) { goto exit; } - status = _PyLong_AsInt(args[0]); + status = PyLong_AsInt(args[0]); if (status == -1 && PyErr_Occurred()) { goto exit; } @@ -8860,7 +9265,7 @@ os_WTERMSIG(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject if (!args) { goto exit; } - status = _PyLong_AsInt(args[0]); + status = PyLong_AsInt(args[0]); if (status == -1 && PyErr_Occurred()) { goto exit; } @@ -8927,7 +9332,7 @@ os_WSTOPSIG(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject if (!args) { goto exit; } - status = _PyLong_AsInt(args[0]); + status = PyLong_AsInt(args[0]); if (status == -1 && PyErr_Occurred()) { goto exit; } @@ -8965,7 +9370,7 @@ os_fstatvfs(PyObject *module, PyObject *arg) PyObject *return_value = NULL; int fd; - fd = _PyLong_AsInt(arg); + fd = PyLong_AsInt(arg); if (fd == -1 && PyErr_Occurred()) { goto exit; } @@ -9442,7 +9847,7 @@ os_startfile(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject goto skip_optional_pos; } } - show_cmd = _PyLong_AsInt(args[4]); + show_cmd = PyLong_AsInt(args[4]); if (show_cmd == -1 && PyErr_Occurred()) { goto exit; } @@ -9541,7 +9946,7 @@ os_device_encoding(PyObject *module, PyObject *const *args, Py_ssize_t nargs, Py if (!args) { goto exit; } - fd = _PyLong_AsInt(args[0]); + fd = PyLong_AsInt(args[0]); if (fd == -1 && PyErr_Occurred()) { goto exit; } @@ -9836,15 +10241,11 @@ os_setxattr(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject if (PyObject_GetBuffer(args[2], &value, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&value, 'C')) { - _PyArg_BadArgument("setxattr", "argument 'value'", "contiguous buffer", args[2]); - goto exit; - } if (!noptargs) { goto skip_optional_pos; } if (args[3]) { - flags = _PyLong_AsInt(args[3]); + flags = PyLong_AsInt(args[3]); if (flags == -1 && PyErr_Occurred()) { goto exit; } @@ -10220,7 +10621,7 @@ os_eventfd(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject * if (!noptargs) { goto skip_optional_pos; } - flags = _PyLong_AsInt(args[1]); + flags = PyLong_AsInt(args[1]); if (flags == -1 && PyErr_Occurred()) { goto exit; } @@ -10397,7 +10798,7 @@ os_get_terminal_size(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (nargs < 1) { goto skip_optional; } - fd = _PyLong_AsInt(args[0]); + fd = PyLong_AsInt(args[0]); if (fd == -1 && PyErr_Occurred()) { goto exit; } @@ -10414,11 +10815,9 @@ PyDoc_STRVAR(os_cpu_count__doc__, "cpu_count($module, /)\n" "--\n" "\n" -"Return the number of CPUs in the system; return None if indeterminable.\n" +"Return the number of logical CPUs in the system.\n" "\n" -"This number is not equivalent to the number of CPUs the current process can\n" -"use. The number of usable CPUs can be obtained with\n" -"``len(os.sched_getaffinity(0))``"); +"Return None if indeterminable."); #define OS_CPU_COUNT_METHODDEF \ {"cpu_count", (PyCFunction)os_cpu_count, METH_NOARGS, os_cpu_count__doc__}, @@ -10451,7 +10850,7 @@ os_get_inheritable(PyObject *module, PyObject *arg) int fd; int _return_value; - fd = _PyLong_AsInt(arg); + fd = PyLong_AsInt(arg); if (fd == -1 && PyErr_Occurred()) { goto exit; } @@ -10487,11 +10886,11 @@ os_set_inheritable(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("set_inheritable", nargs, 2, 2)) { goto exit; } - fd = _PyLong_AsInt(args[0]); + fd = PyLong_AsInt(args[0]); if (fd == -1 && PyErr_Occurred()) { goto exit; } - inheritable = _PyLong_AsInt(args[1]); + inheritable = PyLong_AsInt(args[1]); if (inheritable == -1 && PyErr_Occurred()) { goto exit; } @@ -10592,7 +10991,7 @@ os_get_blocking(PyObject *module, PyObject *arg) int fd; int _return_value; - fd = _PyLong_AsInt(arg); + fd = PyLong_AsInt(arg); if (fd == -1 && PyErr_Occurred()) { goto exit; } @@ -10631,7 +11030,7 @@ os_set_blocking(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("set_blocking", nargs, 2, 2)) { goto exit; } - fd = _PyLong_AsInt(args[0]); + fd = PyLong_AsInt(args[0]); if (fd == -1 && PyErr_Occurred()) { goto exit; } @@ -10684,22 +11083,18 @@ PyDoc_STRVAR(os_DirEntry_is_junction__doc__, "Return True if the entry is a junction; cached per entry."); #define OS_DIRENTRY_IS_JUNCTION_METHODDEF \ - {"is_junction", _PyCFunction_CAST(os_DirEntry_is_junction), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, os_DirEntry_is_junction__doc__}, + {"is_junction", (PyCFunction)os_DirEntry_is_junction, METH_NOARGS, os_DirEntry_is_junction__doc__}, static int -os_DirEntry_is_junction_impl(DirEntry *self, PyTypeObject *defining_class); +os_DirEntry_is_junction_impl(DirEntry *self); static PyObject * -os_DirEntry_is_junction(DirEntry *self, PyTypeObject *defining_class, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +os_DirEntry_is_junction(DirEntry *self, PyObject *Py_UNUSED(ignored)) { PyObject *return_value = NULL; int _return_value; - if (nargs) { - PyErr_SetString(PyExc_TypeError, "is_junction() takes no arguments"); - goto exit; - } - _return_value = os_DirEntry_is_junction_impl(self, defining_class); + _return_value = os_DirEntry_is_junction_impl(self); if ((_return_value == -1) && PyErr_Occurred()) { goto exit; } @@ -11144,7 +11539,7 @@ os_getrandom(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject if (!noptargs) { goto skip_optional_pos; } - flags = _PyLong_AsInt(args[1]); + flags = PyLong_AsInt(args[1]); if (flags == -1 && PyErr_Occurred()) { goto exit; } @@ -11362,6 +11757,28 @@ os_waitstatus_to_exitcode(PyObject *module, PyObject *const *args, Py_ssize_t na #endif /* (defined(WIFEXITED) || defined(MS_WINDOWS)) */ +#if defined(MS_WINDOWS) + +PyDoc_STRVAR(os__supports_virtual_terminal__doc__, +"_supports_virtual_terminal($module, /)\n" +"--\n" +"\n" +"Checks if virtual terminal is supported in windows"); + +#define OS__SUPPORTS_VIRTUAL_TERMINAL_METHODDEF \ + {"_supports_virtual_terminal", (PyCFunction)os__supports_virtual_terminal, METH_NOARGS, os__supports_virtual_terminal__doc__}, + +static PyObject * +os__supports_virtual_terminal_impl(PyObject *module); + +static PyObject * +os__supports_virtual_terminal(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return os__supports_virtual_terminal_impl(module); +} + +#endif /* defined(MS_WINDOWS) */ + #ifndef OS_TTYNAME_METHODDEF #define OS_TTYNAME_METHODDEF #endif /* !defined(OS_TTYNAME_METHODDEF) */ @@ -11446,6 +11863,10 @@ os_waitstatus_to_exitcode(PyObject *module, PyObject *const *args, Py_ssize_t na #define OS__GETFINALPATHNAME_METHODDEF #endif /* !defined(OS__GETFINALPATHNAME_METHODDEF) */ +#ifndef OS__FINDFIRSTFILE_METHODDEF + #define OS__FINDFIRSTFILE_METHODDEF +#endif /* !defined(OS__FINDFIRSTFILE_METHODDEF) */ + #ifndef OS__GETVOLUMEPATHNAME_METHODDEF #define OS__GETVOLUMEPATHNAME_METHODDEF #endif /* !defined(OS__GETVOLUMEPATHNAME_METHODDEF) */ @@ -11714,9 +12135,25 @@ os_waitstatus_to_exitcode(PyObject *module, PyObject *const *args, Py_ssize_t na #define OS_SYMLINK_METHODDEF #endif /* !defined(OS_SYMLINK_METHODDEF) */ -#ifndef OS_TIMES_METHODDEF - #define OS_TIMES_METHODDEF -#endif /* !defined(OS_TIMES_METHODDEF) */ +#ifndef OS_TIMERFD_CREATE_METHODDEF + #define OS_TIMERFD_CREATE_METHODDEF +#endif /* !defined(OS_TIMERFD_CREATE_METHODDEF) */ + +#ifndef OS_TIMERFD_SETTIME_METHODDEF + #define OS_TIMERFD_SETTIME_METHODDEF +#endif /* !defined(OS_TIMERFD_SETTIME_METHODDEF) */ + +#ifndef OS_TIMERFD_SETTIME_NS_METHODDEF + #define OS_TIMERFD_SETTIME_NS_METHODDEF +#endif /* !defined(OS_TIMERFD_SETTIME_NS_METHODDEF) */ + +#ifndef OS_TIMERFD_GETTIME_METHODDEF + #define OS_TIMERFD_GETTIME_METHODDEF +#endif /* !defined(OS_TIMERFD_GETTIME_METHODDEF) */ + +#ifndef OS_TIMERFD_GETTIME_NS_METHODDEF + #define OS_TIMERFD_GETTIME_NS_METHODDEF +#endif /* !defined(OS_TIMERFD_GETTIME_NS_METHODDEF) */ #ifndef OS_GETSID_METHODDEF #define OS_GETSID_METHODDEF @@ -11981,4 +12418,8 @@ os_waitstatus_to_exitcode(PyObject *module, PyObject *const *args, Py_ssize_t na #ifndef OS_WAITSTATUS_TO_EXITCODE_METHODDEF #define OS_WAITSTATUS_TO_EXITCODE_METHODDEF #endif /* !defined(OS_WAITSTATUS_TO_EXITCODE_METHODDEF) */ -/*[clinic end generated code: output=a85a386b212b0631 input=a9049054013a1b77]*/ + +#ifndef OS__SUPPORTS_VIRTUAL_TERMINAL_METHODDEF + #define OS__SUPPORTS_VIRTUAL_TERMINAL_METHODDEF +#endif /* !defined(OS__SUPPORTS_VIRTUAL_TERMINAL_METHODDEF) */ +/*[clinic end generated code: output=18c128534c355d84 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/pwdmodule.c.h b/Modules/clinic/pwdmodule.c.h index 748c873b1c8a45..43d4825031c7e6 100644 --- a/Modules/clinic/pwdmodule.c.h +++ b/Modules/clinic/pwdmodule.c.h @@ -2,11 +2,7 @@ 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 - +#include "pycore_modsupport.h" // _PyArg_BadArgument() PyDoc_STRVAR(pwd_getpwuid__doc__, "getpwuid($module, uidobj, /)\n" @@ -77,4 +73,4 @@ pwd_getpwall(PyObject *module, PyObject *Py_UNUSED(ignored)) #ifndef PWD_GETPWALL_METHODDEF #define PWD_GETPWALL_METHODDEF #endif /* !defined(PWD_GETPWALL_METHODDEF) */ -/*[clinic end generated code: output=1edf1e26cd2762db input=a9049054013a1b77]*/ +/*[clinic end generated code: output=5a8fb12939ff4ea3 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/pyexpat.c.h b/Modules/clinic/pyexpat.c.h index 34937c5d594f5c..a5b93e68598204 100644 --- a/Modules/clinic/pyexpat.c.h +++ b/Modules/clinic/pyexpat.c.h @@ -3,10 +3,10 @@ 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() +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() #endif - +#include "pycore_modsupport.h" // _PyArg_UnpackKeywords() PyDoc_STRVAR(pyexpat_xmlparser_Parse__doc__, "Parse($self, data, isfinal=False, /)\n" @@ -288,7 +288,7 @@ pyexpat_xmlparser_SetParamEntityParsing(xmlparseobject *self, PyObject *arg) PyObject *return_value = NULL; int flag; - flag = _PyLong_AsInt(arg); + flag = PyLong_AsInt(arg); if (flag == -1 && PyErr_Occurred()) { goto exit; } @@ -498,4 +498,4 @@ pyexpat_ErrorString(PyObject *module, PyObject *arg) #ifndef PYEXPAT_XMLPARSER_USEFOREIGNDTD_METHODDEF #define PYEXPAT_XMLPARSER_USEFOREIGNDTD_METHODDEF #endif /* !defined(PYEXPAT_XMLPARSER_USEFOREIGNDTD_METHODDEF) */ -/*[clinic end generated code: output=63efc62e24a7b5a7 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=48c4296e43777df4 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/readline.c.h b/Modules/clinic/readline.c.h index 83d93ef7e7b4f1..1c616d60f097cc 100644 --- a/Modules/clinic/readline.c.h +++ b/Modules/clinic/readline.c.h @@ -2,11 +2,7 @@ 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 - +#include "pycore_modsupport.h" // _PyArg_CheckPositional() PyDoc_STRVAR(readline_parse_and_bind__doc__, "parse_and_bind($module, string, /)\n" @@ -146,7 +142,7 @@ readline_append_history_file(PyObject *module, PyObject *const *args, Py_ssize_t if (!_PyArg_CheckPositional("append_history_file", nargs, 1, 2)) { goto exit; } - nelements = _PyLong_AsInt(args[0]); + nelements = PyLong_AsInt(args[0]); if (nelements == -1 && PyErr_Occurred()) { goto exit; } @@ -183,7 +179,7 @@ readline_set_history_length(PyObject *module, PyObject *arg) PyObject *return_value = NULL; int length; - length = _PyLong_AsInt(arg); + length = PyLong_AsInt(arg); if (length == -1 && PyErr_Occurred()) { goto exit; } @@ -404,7 +400,7 @@ readline_remove_history_item(PyObject *module, PyObject *arg) PyObject *return_value = NULL; int entry_number; - entry_number = _PyLong_AsInt(arg); + entry_number = PyLong_AsInt(arg); if (entry_number == -1 && PyErr_Occurred()) { goto exit; } @@ -439,7 +435,7 @@ readline_replace_history_item(PyObject *module, PyObject *const *args, Py_ssize_ if (!_PyArg_CheckPositional("replace_history_item", nargs, 2, 2)) { goto exit; } - entry_number = _PyLong_AsInt(args[0]); + entry_number = PyLong_AsInt(args[0]); if (entry_number == -1 && PyErr_Occurred()) { goto exit; } @@ -582,7 +578,7 @@ readline_get_history_item(PyObject *module, PyObject *arg) PyObject *return_value = NULL; int idx; - idx = _PyLong_AsInt(arg); + idx = PyLong_AsInt(arg); if (idx == -1 && PyErr_Occurred()) { goto exit; } @@ -688,4 +684,4 @@ readline_redisplay(PyObject *module, PyObject *Py_UNUSED(ignored)) #ifndef READLINE_CLEAR_HISTORY_METHODDEF #define READLINE_CLEAR_HISTORY_METHODDEF #endif /* !defined(READLINE_CLEAR_HISTORY_METHODDEF) */ -/*[clinic end generated code: output=d66c3df7e72f93c4 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=358ab465285c7949 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/resource.c.h b/Modules/clinic/resource.c.h index d0ca8e7150fa86..9eda7de27532a1 100644 --- a/Modules/clinic/resource.c.h +++ b/Modules/clinic/resource.c.h @@ -2,12 +2,6 @@ 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 - - #if defined(HAVE_GETRUSAGE) PyDoc_STRVAR(resource_getrusage__doc__, @@ -27,7 +21,7 @@ resource_getrusage(PyObject *module, PyObject *arg) PyObject *return_value = NULL; int who; - who = _PyLong_AsInt(arg); + who = PyLong_AsInt(arg); if (who == -1 && PyErr_Occurred()) { goto exit; } @@ -56,7 +50,7 @@ resource_getrlimit(PyObject *module, PyObject *arg) PyObject *return_value = NULL; int resource; - resource = _PyLong_AsInt(arg); + resource = PyLong_AsInt(arg); if (resource == -1 && PyErr_Occurred()) { goto exit; } @@ -72,7 +66,7 @@ PyDoc_STRVAR(resource_setrlimit__doc__, "\n"); #define RESOURCE_SETRLIMIT_METHODDEF \ - {"setrlimit", _PyCFunction_CAST(resource_setrlimit), METH_FASTCALL, resource_setrlimit__doc__}, + {"setrlimit", (PyCFunction)(void(*)(void))resource_setrlimit, METH_FASTCALL, resource_setrlimit__doc__}, static PyObject * resource_setrlimit_impl(PyObject *module, int resource, PyObject *limits); @@ -84,10 +78,11 @@ resource_setrlimit(PyObject *module, PyObject *const *args, Py_ssize_t nargs) int resource; PyObject *limits; - if (!_PyArg_CheckPositional("setrlimit", nargs, 2, 2)) { + if (nargs != 2) { + PyErr_Format(PyExc_TypeError, "setrlimit expected 2 arguments, got %zd", nargs); goto exit; } - resource = _PyLong_AsInt(args[0]); + resource = PyLong_AsInt(args[0]); if (resource == -1 && PyErr_Occurred()) { goto exit; } @@ -106,7 +101,7 @@ PyDoc_STRVAR(resource_prlimit__doc__, "\n"); #define RESOURCE_PRLIMIT_METHODDEF \ - {"prlimit", _PyCFunction_CAST(resource_prlimit), METH_FASTCALL, resource_prlimit__doc__}, + {"prlimit", (PyCFunction)(void(*)(void))resource_prlimit, METH_FASTCALL, resource_prlimit__doc__}, static PyObject * resource_prlimit_impl(PyObject *module, pid_t pid, int resource, @@ -120,14 +115,19 @@ resource_prlimit(PyObject *module, PyObject *const *args, Py_ssize_t nargs) int resource; PyObject *limits = Py_None; - if (!_PyArg_CheckPositional("prlimit", nargs, 2, 3)) { + if (nargs < 2) { + PyErr_Format(PyExc_TypeError, "prlimit expected at least 2 arguments, got %zd", nargs); + goto exit; + } + if (nargs > 3) { + PyErr_Format(PyExc_TypeError, "prlimit expected at most 3 arguments, got %zd", nargs); goto exit; } pid = PyLong_AsPid(args[0]); if (pid == -1 && PyErr_Occurred()) { goto exit; } - resource = _PyLong_AsInt(args[1]); + resource = PyLong_AsInt(args[1]); if (resource == -1 && PyErr_Occurred()) { goto exit; } @@ -178,4 +178,4 @@ resource_getpagesize(PyObject *module, PyObject *Py_UNUSED(ignored)) #ifndef RESOURCE_PRLIMIT_METHODDEF #define RESOURCE_PRLIMIT_METHODDEF #endif /* !defined(RESOURCE_PRLIMIT_METHODDEF) */ -/*[clinic end generated code: output=2fbec74335a57230 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=e45883ace510414a input=a9049054013a1b77]*/ diff --git a/Modules/clinic/selectmodule.c.h b/Modules/clinic/selectmodule.c.h index f44ca1d70a1e86..67e76d4c89f59a 100644 --- a/Modules/clinic/selectmodule.c.h +++ b/Modules/clinic/selectmodule.c.h @@ -3,10 +3,12 @@ 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() +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() #endif - +#include "pycore_fileutils.h" // _PyLong_FileDescriptor_Converter() +#include "pycore_long.h" // _PyLong_UnsignedShort_Converter() +#include "pycore_modsupport.h" // _PyArg_CheckPositional() PyDoc_STRVAR(select_select__doc__, "select($module, rlist, wlist, xlist, timeout=None, /)\n" @@ -568,7 +570,7 @@ select_epoll(PyTypeObject *type, PyObject *args, PyObject *kwargs) goto skip_optional_pos; } if (fastargs[0]) { - sizehint = _PyLong_AsInt(fastargs[0]); + sizehint = PyLong_AsInt(fastargs[0]); if (sizehint == -1 && PyErr_Occurred()) { goto exit; } @@ -576,7 +578,7 @@ select_epoll(PyTypeObject *type, PyObject *args, PyObject *kwargs) goto skip_optional_pos; } } - flags = _PyLong_AsInt(fastargs[1]); + flags = PyLong_AsInt(fastargs[1]); if (flags == -1 && PyErr_Occurred()) { goto exit; } @@ -655,7 +657,7 @@ select_epoll_fromfd(PyTypeObject *type, PyObject *arg) PyObject *return_value = NULL; int fd; - fd = _PyLong_AsInt(arg); + fd = PyLong_AsInt(arg); if (fd == -1 && PyErr_Occurred()) { goto exit; } @@ -954,7 +956,7 @@ select_epoll_poll(pyEpoll_Object *self, PyObject *const *args, Py_ssize_t nargs, goto skip_optional_pos; } } - maxevents = _PyLong_AsInt(args[1]); + maxevents = PyLong_AsInt(args[1]); if (maxevents == -1 && PyErr_Occurred()) { goto exit; } @@ -1145,7 +1147,7 @@ select_kqueue_fromfd(PyTypeObject *type, PyObject *arg) PyObject *return_value = NULL; int fd; - fd = _PyLong_AsInt(arg); + fd = PyLong_AsInt(arg); if (fd == -1 && PyErr_Occurred()) { goto exit; } @@ -1193,7 +1195,7 @@ select_kqueue_control(kqueue_queue_Object *self, PyObject *const *args, Py_ssize goto exit; } changelist = args[0]; - maxevents = _PyLong_AsInt(args[1]); + maxevents = PyLong_AsInt(args[1]); if (maxevents == -1 && PyErr_Occurred()) { goto exit; } @@ -1309,4 +1311,4 @@ select_kqueue_control(kqueue_queue_Object *self, PyObject *const *args, Py_ssize #ifndef SELECT_KQUEUE_CONTROL_METHODDEF #define SELECT_KQUEUE_CONTROL_METHODDEF #endif /* !defined(SELECT_KQUEUE_CONTROL_METHODDEF) */ -/*[clinic end generated code: output=64516114287e894d input=a9049054013a1b77]*/ +/*[clinic end generated code: output=4c2dcb31cb17c2c6 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/sha1module.c.h b/Modules/clinic/sha1module.c.h index ad15ddaadfc86c..ee391656fb67c3 100644 --- a/Modules/clinic/sha1module.c.h +++ b/Modules/clinic/sha1module.c.h @@ -3,10 +3,10 @@ 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() +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() #endif - +#include "pycore_modsupport.h" // _PyArg_UnpackKeywords() PyDoc_STRVAR(SHA1Type_copy__doc__, "copy($self, /)\n" @@ -148,4 +148,4 @@ _sha1_sha1(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject * exit: return return_value; } -/*[clinic end generated code: output=4d1293ca3472acdb input=a9049054013a1b77]*/ +/*[clinic end generated code: output=41fc7579213b57b4 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/sha2module.c.h b/Modules/clinic/sha2module.c.h index 8f855ca345e47a..ec31d5545be4c1 100644 --- a/Modules/clinic/sha2module.c.h +++ b/Modules/clinic/sha2module.c.h @@ -3,10 +3,10 @@ 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() +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() #endif - +#include "pycore_modsupport.h" // _PyArg_UnpackKeywords() PyDoc_STRVAR(SHA256Type_copy__doc__, "copy($self, /)\n" @@ -437,4 +437,4 @@ _sha2_sha384(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject exit: return return_value; } -/*[clinic end generated code: output=f81dacb48f3fee72 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=1482d9de086e45c4 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/sha3module.c.h b/Modules/clinic/sha3module.c.h index 299803a3420bf6..738e9589503900 100644 --- a/Modules/clinic/sha3module.c.h +++ b/Modules/clinic/sha3module.c.h @@ -3,10 +3,11 @@ 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() +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() #endif - +#include "pycore_long.h" // _PyLong_UnsignedLong_Converter() +#include "pycore_modsupport.h" // _PyArg_UnpackKeywords() PyDoc_STRVAR(py_sha3_new__doc__, "sha3_224(data=b\'\', /, *, usedforsecurity=True)\n" @@ -193,4 +194,4 @@ _sha3_shake_128_hexdigest(SHA3object *self, PyObject *arg) exit: return return_value; } -/*[clinic end generated code: output=907cb475f3dc9ee0 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=a8e76a880d1421ec input=a9049054013a1b77]*/ diff --git a/Modules/clinic/signalmodule.c.h b/Modules/clinic/signalmodule.c.h index 3b3c6ba150a1ad..bc33e066654364 100644 --- a/Modules/clinic/signalmodule.c.h +++ b/Modules/clinic/signalmodule.c.h @@ -2,11 +2,7 @@ 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 - +#include "pycore_modsupport.h" // _PyArg_CheckPositional() PyDoc_STRVAR(signal_default_int_handler__doc__, "default_int_handler($module, signalnum, frame, /)\n" @@ -33,7 +29,7 @@ signal_default_int_handler(PyObject *module, PyObject *const *args, Py_ssize_t n if (!_PyArg_CheckPositional("default_int_handler", nargs, 2, 2)) { goto exit; } - signalnum = _PyLong_AsInt(args[0]); + signalnum = PyLong_AsInt(args[0]); if (signalnum == -1 && PyErr_Occurred()) { goto exit; } @@ -65,7 +61,7 @@ signal_alarm(PyObject *module, PyObject *arg) int seconds; long _return_value; - seconds = _PyLong_AsInt(arg); + seconds = PyLong_AsInt(arg); if (seconds == -1 && PyErr_Occurred()) { goto exit; } @@ -121,7 +117,7 @@ signal_raise_signal(PyObject *module, PyObject *arg) PyObject *return_value = NULL; int signalnum; - signalnum = _PyLong_AsInt(arg); + signalnum = PyLong_AsInt(arg); if (signalnum == -1 && PyErr_Occurred()) { goto exit; } @@ -160,7 +156,7 @@ signal_signal(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("signal", nargs, 2, 2)) { goto exit; } - signalnum = _PyLong_AsInt(args[0]); + signalnum = PyLong_AsInt(args[0]); if (signalnum == -1 && PyErr_Occurred()) { goto exit; } @@ -195,7 +191,7 @@ signal_getsignal(PyObject *module, PyObject *arg) PyObject *return_value = NULL; int signalnum; - signalnum = _PyLong_AsInt(arg); + signalnum = PyLong_AsInt(arg); if (signalnum == -1 && PyErr_Occurred()) { goto exit; } @@ -227,7 +223,7 @@ signal_strsignal(PyObject *module, PyObject *arg) PyObject *return_value = NULL; int signalnum; - signalnum = _PyLong_AsInt(arg); + signalnum = PyLong_AsInt(arg); if (signalnum == -1 && PyErr_Occurred()) { goto exit; } @@ -264,11 +260,11 @@ signal_siginterrupt(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("siginterrupt", nargs, 2, 2)) { goto exit; } - signalnum = _PyLong_AsInt(args[0]); + signalnum = PyLong_AsInt(args[0]); if (signalnum == -1 && PyErr_Occurred()) { goto exit; } - flag = _PyLong_AsInt(args[1]); + flag = PyLong_AsInt(args[1]); if (flag == -1 && PyErr_Occurred()) { goto exit; } @@ -311,7 +307,7 @@ signal_setitimer(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("setitimer", nargs, 2, 3)) { goto exit; } - which = _PyLong_AsInt(args[0]); + which = PyLong_AsInt(args[0]); if (which == -1 && PyErr_Occurred()) { goto exit; } @@ -349,7 +345,7 @@ signal_getitimer(PyObject *module, PyObject *arg) PyObject *return_value = NULL; int which; - which = _PyLong_AsInt(arg); + which = PyLong_AsInt(arg); if (which == -1 && PyErr_Occurred()) { goto exit; } @@ -385,7 +381,7 @@ signal_pthread_sigmask(PyObject *module, PyObject *const *args, Py_ssize_t nargs if (!_PyArg_CheckPositional("pthread_sigmask", nargs, 2, 2)) { goto exit; } - how = _PyLong_AsInt(args[0]); + how = PyLong_AsInt(args[0]); if (how == -1 && PyErr_Occurred()) { goto exit; } @@ -587,7 +583,7 @@ signal_pthread_kill(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } thread_id = PyLong_AsUnsignedLongMask(args[0]); - signalnum = _PyLong_AsInt(args[1]); + signalnum = PyLong_AsInt(args[1]); if (signalnum == -1 && PyErr_Occurred()) { goto exit; } @@ -626,11 +622,11 @@ signal_pidfd_send_signal(PyObject *module, PyObject *const *args, Py_ssize_t nar if (!_PyArg_CheckPositional("pidfd_send_signal", nargs, 2, 4)) { goto exit; } - pidfd = _PyLong_AsInt(args[0]); + pidfd = PyLong_AsInt(args[0]); if (pidfd == -1 && PyErr_Occurred()) { goto exit; } - signalnum = _PyLong_AsInt(args[1]); + signalnum = PyLong_AsInt(args[1]); if (signalnum == -1 && PyErr_Occurred()) { goto exit; } @@ -641,7 +637,7 @@ signal_pidfd_send_signal(PyObject *module, PyObject *const *args, Py_ssize_t nar if (nargs < 4) { goto skip_optional; } - flags = _PyLong_AsInt(args[3]); + flags = PyLong_AsInt(args[3]); if (flags == -1 && PyErr_Occurred()) { goto exit; } @@ -705,4 +701,4 @@ signal_pidfd_send_signal(PyObject *module, PyObject *const *args, Py_ssize_t nar #ifndef SIGNAL_PIDFD_SEND_SIGNAL_METHODDEF #define SIGNAL_PIDFD_SEND_SIGNAL_METHODDEF #endif /* !defined(SIGNAL_PIDFD_SEND_SIGNAL_METHODDEF) */ -/*[clinic end generated code: output=2b54dc607f6e3146 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=5a9928cb2dc75b5f input=a9049054013a1b77]*/ diff --git a/Modules/clinic/socketmodule.c.h b/Modules/clinic/socketmodule.c.h index 8ff1044d013b0f..3f4056efff2fec 100644 --- a/Modules/clinic/socketmodule.c.h +++ b/Modules/clinic/socketmodule.c.h @@ -3,10 +3,10 @@ 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() +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() #endif - +#include "pycore_modsupport.h" // _PyArg_UnpackKeywords() static int sock_initobj_impl(PySocketSockObject *self, int family, int type, int proto, @@ -58,7 +58,7 @@ sock_initobj(PyObject *self, PyObject *args, PyObject *kwargs) goto skip_optional_pos; } if (fastargs[0]) { - family = _PyLong_AsInt(fastargs[0]); + family = PyLong_AsInt(fastargs[0]); if (family == -1 && PyErr_Occurred()) { goto exit; } @@ -67,7 +67,7 @@ sock_initobj(PyObject *self, PyObject *args, PyObject *kwargs) } } if (fastargs[1]) { - type = _PyLong_AsInt(fastargs[1]); + type = PyLong_AsInt(fastargs[1]); if (type == -1 && PyErr_Occurred()) { goto exit; } @@ -76,7 +76,7 @@ sock_initobj(PyObject *self, PyObject *args, PyObject *kwargs) } } if (fastargs[2]) { - proto = _PyLong_AsInt(fastargs[2]); + proto = PyLong_AsInt(fastargs[2]); if (proto == -1 && PyErr_Occurred()) { goto exit; } @@ -91,4 +91,172 @@ sock_initobj(PyObject *self, PyObject *args, PyObject *kwargs) exit: return return_value; } -/*[clinic end generated code: output=987155ac4b48a198 input=a9049054013a1b77]*/ + +PyDoc_STRVAR(_socket_socket_ntohs__doc__, +"ntohs($self, x, /)\n" +"--\n" +"\n" +"Convert a 16-bit unsigned integer from network to host byte order."); + +#define _SOCKET_SOCKET_NTOHS_METHODDEF \ + {"ntohs", (PyCFunction)_socket_socket_ntohs, METH_O, _socket_socket_ntohs__doc__}, + +static PyObject * +_socket_socket_ntohs_impl(PySocketSockObject *self, int x); + +static PyObject * +_socket_socket_ntohs(PySocketSockObject *self, PyObject *arg) +{ + PyObject *return_value = NULL; + int x; + + x = PyLong_AsInt(arg); + if (x == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = _socket_socket_ntohs_impl(self, x); + +exit: + return return_value; +} + +PyDoc_STRVAR(_socket_socket_htons__doc__, +"htons($self, x, /)\n" +"--\n" +"\n" +"Convert a 16-bit unsigned integer from host to network byte order."); + +#define _SOCKET_SOCKET_HTONS_METHODDEF \ + {"htons", (PyCFunction)_socket_socket_htons, METH_O, _socket_socket_htons__doc__}, + +static PyObject * +_socket_socket_htons_impl(PySocketSockObject *self, int x); + +static PyObject * +_socket_socket_htons(PySocketSockObject *self, PyObject *arg) +{ + PyObject *return_value = NULL; + int x; + + x = PyLong_AsInt(arg); + if (x == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = _socket_socket_htons_impl(self, x); + +exit: + return return_value; +} + +PyDoc_STRVAR(_socket_socket_inet_aton__doc__, +"inet_aton($self, ip_addr, /)\n" +"--\n" +"\n" +"Convert an IP address in string format (123.45.67.89) to the 32-bit packed binary format used in low-level network functions."); + +#define _SOCKET_SOCKET_INET_ATON_METHODDEF \ + {"inet_aton", (PyCFunction)_socket_socket_inet_aton, METH_O, _socket_socket_inet_aton__doc__}, + +static PyObject * +_socket_socket_inet_aton_impl(PySocketSockObject *self, const char *ip_addr); + +static PyObject * +_socket_socket_inet_aton(PySocketSockObject *self, PyObject *arg) +{ + PyObject *return_value = NULL; + const char *ip_addr; + + if (!PyUnicode_Check(arg)) { + _PyArg_BadArgument("inet_aton", "argument", "str", arg); + goto exit; + } + Py_ssize_t ip_addr_length; + ip_addr = PyUnicode_AsUTF8AndSize(arg, &ip_addr_length); + if (ip_addr == NULL) { + goto exit; + } + if (strlen(ip_addr) != (size_t)ip_addr_length) { + PyErr_SetString(PyExc_ValueError, "embedded null character"); + goto exit; + } + return_value = _socket_socket_inet_aton_impl(self, ip_addr); + +exit: + return return_value; +} + +#if defined(HAVE_INET_NTOA) + +PyDoc_STRVAR(_socket_socket_inet_ntoa__doc__, +"inet_ntoa($self, packed_ip, /)\n" +"--\n" +"\n" +"Convert an IP address from 32-bit packed binary format to string format."); + +#define _SOCKET_SOCKET_INET_NTOA_METHODDEF \ + {"inet_ntoa", (PyCFunction)_socket_socket_inet_ntoa, METH_O, _socket_socket_inet_ntoa__doc__}, + +static PyObject * +_socket_socket_inet_ntoa_impl(PySocketSockObject *self, Py_buffer *packed_ip); + +static PyObject * +_socket_socket_inet_ntoa(PySocketSockObject *self, PyObject *arg) +{ + PyObject *return_value = NULL; + Py_buffer packed_ip = {NULL, NULL}; + + if (PyObject_GetBuffer(arg, &packed_ip, PyBUF_SIMPLE) != 0) { + goto exit; + } + return_value = _socket_socket_inet_ntoa_impl(self, &packed_ip); + +exit: + /* Cleanup for packed_ip */ + if (packed_ip.obj) { + PyBuffer_Release(&packed_ip); + } + + return return_value; +} + +#endif /* defined(HAVE_INET_NTOA) */ + +#if (defined(HAVE_IF_NAMEINDEX) || defined(MS_WINDOWS)) + +PyDoc_STRVAR(_socket_socket_if_nametoindex__doc__, +"if_nametoindex($self, oname, /)\n" +"--\n" +"\n" +"Returns the interface index corresponding to the interface name if_name."); + +#define _SOCKET_SOCKET_IF_NAMETOINDEX_METHODDEF \ + {"if_nametoindex", (PyCFunction)_socket_socket_if_nametoindex, METH_O, _socket_socket_if_nametoindex__doc__}, + +static PyObject * +_socket_socket_if_nametoindex_impl(PySocketSockObject *self, PyObject *oname); + +static PyObject * +_socket_socket_if_nametoindex(PySocketSockObject *self, PyObject *arg) +{ + PyObject *return_value = NULL; + PyObject *oname; + + if (!PyUnicode_FSConverter(arg, &oname)) { + goto exit; + } + return_value = _socket_socket_if_nametoindex_impl(self, oname); + +exit: + return return_value; +} + +#endif /* (defined(HAVE_IF_NAMEINDEX) || defined(MS_WINDOWS)) */ + +#ifndef _SOCKET_SOCKET_INET_NTOA_METHODDEF + #define _SOCKET_SOCKET_INET_NTOA_METHODDEF +#endif /* !defined(_SOCKET_SOCKET_INET_NTOA_METHODDEF) */ + +#ifndef _SOCKET_SOCKET_IF_NAMETOINDEX_METHODDEF + #define _SOCKET_SOCKET_IF_NAMETOINDEX_METHODDEF +#endif /* !defined(_SOCKET_SOCKET_IF_NAMETOINDEX_METHODDEF) */ +/*[clinic end generated code: output=eb37b5d88a1e4661 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/symtablemodule.c.h b/Modules/clinic/symtablemodule.c.h index 04fdb9f2d9b776..2ecd3afc00d2be 100644 --- a/Modules/clinic/symtablemodule.c.h +++ b/Modules/clinic/symtablemodule.c.h @@ -2,11 +2,7 @@ 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 - +#include "pycore_modsupport.h" // _PyArg_CheckPositional() PyDoc_STRVAR(_symtable_symtable__doc__, "symtable($module, source, filename, startstr, /)\n" @@ -54,4 +50,4 @@ _symtable_symtable(PyObject *module, PyObject *const *args, Py_ssize_t nargs) exit: return return_value; } -/*[clinic end generated code: output=07716ddbd6c7efe1 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=931964a76a72f850 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/syslogmodule.c.h b/Modules/clinic/syslogmodule.c.h index 3e0792b88060c0..58b0ea57b065b3 100644 --- a/Modules/clinic/syslogmodule.c.h +++ b/Modules/clinic/syslogmodule.c.h @@ -3,10 +3,10 @@ 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() +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() #endif - +#include "pycore_modsupport.h" // _PyArg_UnpackKeywords() PyDoc_STRVAR(syslog_openlog__doc__, "openlog($module, /, ident=, logoption=0,\n" @@ -251,4 +251,4 @@ syslog_LOG_UPTO(PyObject *module, PyObject *arg) exit: return return_value; } -/*[clinic end generated code: output=b8124c0977ed6177 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=86ca2fd84b2da98e input=a9049054013a1b77]*/ diff --git a/Modules/clinic/termios.c.h b/Modules/clinic/termios.c.h index 78863e53c42ffb..1c340681e5862f 100644 --- a/Modules/clinic/termios.c.h +++ b/Modules/clinic/termios.c.h @@ -2,11 +2,8 @@ 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 - +#include "pycore_fileutils.h" // _PyLong_FileDescriptor_Converter() +#include "pycore_modsupport.h" // _PyArg_CheckPositional() PyDoc_STRVAR(termios_tcgetattr__doc__, "tcgetattr($module, fd, /)\n" @@ -75,7 +72,7 @@ termios_tcsetattr(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyLong_FileDescriptor_Converter(args[0], &fd)) { goto exit; } - when = _PyLong_AsInt(args[1]); + when = PyLong_AsInt(args[1]); if (when == -1 && PyErr_Occurred()) { goto exit; } @@ -114,7 +111,7 @@ termios_tcsendbreak(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyLong_FileDescriptor_Converter(args[0], &fd)) { goto exit; } - duration = _PyLong_AsInt(args[1]); + duration = PyLong_AsInt(args[1]); if (duration == -1 && PyErr_Occurred()) { goto exit; } @@ -180,7 +177,7 @@ termios_tcflush(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyLong_FileDescriptor_Converter(args[0], &fd)) { goto exit; } - queue = _PyLong_AsInt(args[1]); + queue = PyLong_AsInt(args[1]); if (queue == -1 && PyErr_Occurred()) { goto exit; } @@ -219,7 +216,7 @@ termios_tcflow(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyLong_FileDescriptor_Converter(args[0], &fd)) { goto exit; } - action = _PyLong_AsInt(args[1]); + action = PyLong_AsInt(args[1]); if (action == -1 && PyErr_Occurred()) { goto exit; } @@ -292,4 +289,4 @@ termios_tcsetwinsize(PyObject *module, PyObject *const *args, Py_ssize_t nargs) exit: return return_value; } -/*[clinic end generated code: output=d286a3906a051869 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=f31382658135c774 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/timemodule.c.h b/Modules/clinic/timemodule.c.h new file mode 100644 index 00000000000000..bbc0748f9a9c0d --- /dev/null +++ b/Modules/clinic/timemodule.c.h @@ -0,0 +1,74 @@ +/*[clinic input] +preserve +[clinic start generated code]*/ + +#if defined(HAVE_CLOCK_GETTIME) + +PyDoc_STRVAR(time_clock_gettime__doc__, +"clock_gettime($module, clk_id, /)\n" +"--\n" +"\n" +"Return the time of the specified clock clk_id as a float."); + +#define TIME_CLOCK_GETTIME_METHODDEF \ + {"clock_gettime", (PyCFunction)time_clock_gettime, METH_O, time_clock_gettime__doc__}, + +static PyObject * +time_clock_gettime_impl(PyObject *module, clockid_t clk_id); + +static PyObject * +time_clock_gettime(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + clockid_t clk_id; + + if (!time_clockid_converter(arg, &clk_id)) { + goto exit; + } + return_value = time_clock_gettime_impl(module, clk_id); + +exit: + return return_value; +} + +#endif /* defined(HAVE_CLOCK_GETTIME) */ + +#if defined(HAVE_CLOCK_GETTIME) + +PyDoc_STRVAR(time_clock_gettime_ns__doc__, +"clock_gettime_ns($module, clk_id, /)\n" +"--\n" +"\n" +"Return the time of the specified clock clk_id as nanoseconds (int)."); + +#define TIME_CLOCK_GETTIME_NS_METHODDEF \ + {"clock_gettime_ns", (PyCFunction)time_clock_gettime_ns, METH_O, time_clock_gettime_ns__doc__}, + +static PyObject * +time_clock_gettime_ns_impl(PyObject *module, clockid_t clk_id); + +static PyObject * +time_clock_gettime_ns(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + clockid_t clk_id; + + if (!time_clockid_converter(arg, &clk_id)) { + goto exit; + } + return_value = time_clock_gettime_ns_impl(module, clk_id); + +exit: + return return_value; +} + +#endif /* defined(HAVE_CLOCK_GETTIME) */ + +#ifndef TIME_CLOCK_GETTIME_METHODDEF + #define TIME_CLOCK_GETTIME_METHODDEF +#endif /* !defined(TIME_CLOCK_GETTIME_METHODDEF) */ + +#ifndef TIME_CLOCK_GETTIME_NS_METHODDEF + #define TIME_CLOCK_GETTIME_NS_METHODDEF +#endif /* !defined(TIME_CLOCK_GETTIME_NS_METHODDEF) */ +/*[clinic end generated code: output=b589a2132aa9df47 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/unicodedata.c.h b/Modules/clinic/unicodedata.c.h index ec30f9017e3702..739f498f1d2672 100644 --- a/Modules/clinic/unicodedata.c.h +++ b/Modules/clinic/unicodedata.c.h @@ -2,11 +2,7 @@ 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 - +#include "pycore_modsupport.h" // _PyArg_CheckPositional() PyDoc_STRVAR(unicodedata_UCD_decimal__doc__, "decimal($self, chr, default=, /)\n" @@ -523,4 +519,4 @@ unicodedata_UCD_lookup(PyObject *self, PyObject *arg) exit: return return_value; } -/*[clinic end generated code: output=43e551ecaa985a40 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=ea30f89007b2bfff input=a9049054013a1b77]*/ diff --git a/Modules/clinic/zlibmodule.c.h b/Modules/clinic/zlibmodule.c.h index 65412b2435ade1..6b09abe309bf48 100644 --- a/Modules/clinic/zlibmodule.c.h +++ b/Modules/clinic/zlibmodule.c.h @@ -3,10 +3,11 @@ 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() +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() #endif - +#include "pycore_abstract.h" // _PyNumber_Index() +#include "pycore_modsupport.h" // _PyArg_UnpackKeywords() PyDoc_STRVAR(zlib_compress__doc__, "compress($module, data, /, level=Z_DEFAULT_COMPRESSION, wbits=MAX_WBITS)\n" @@ -69,15 +70,11 @@ zlib_compress(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObjec if (PyObject_GetBuffer(args[0], &data, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("compress", "argument 1", "contiguous buffer", args[0]); - goto exit; - } if (!noptargs) { goto skip_optional_pos; } if (args[1]) { - level = _PyLong_AsInt(args[1]); + level = PyLong_AsInt(args[1]); if (level == -1 && PyErr_Occurred()) { goto exit; } @@ -85,7 +82,7 @@ zlib_compress(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObjec goto skip_optional_pos; } } - wbits = _PyLong_AsInt(args[2]); + wbits = PyLong_AsInt(args[2]); if (wbits == -1 && PyErr_Occurred()) { goto exit; } @@ -163,15 +160,11 @@ zlib_decompress(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObj if (PyObject_GetBuffer(args[0], &data, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("decompress", "argument 1", "contiguous buffer", args[0]); - goto exit; - } if (!noptargs) { goto skip_optional_pos; } if (args[1]) { - wbits = _PyLong_AsInt(args[1]); + wbits = PyLong_AsInt(args[1]); if (wbits == -1 && PyErr_Occurred()) { goto exit; } @@ -286,7 +279,7 @@ zlib_compressobj(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyOb goto skip_optional_pos; } if (args[0]) { - level = _PyLong_AsInt(args[0]); + level = PyLong_AsInt(args[0]); if (level == -1 && PyErr_Occurred()) { goto exit; } @@ -295,7 +288,7 @@ zlib_compressobj(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyOb } } if (args[1]) { - method = _PyLong_AsInt(args[1]); + method = PyLong_AsInt(args[1]); if (method == -1 && PyErr_Occurred()) { goto exit; } @@ -304,7 +297,7 @@ zlib_compressobj(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyOb } } if (args[2]) { - wbits = _PyLong_AsInt(args[2]); + wbits = PyLong_AsInt(args[2]); if (wbits == -1 && PyErr_Occurred()) { goto exit; } @@ -313,7 +306,7 @@ zlib_compressobj(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyOb } } if (args[3]) { - memLevel = _PyLong_AsInt(args[3]); + memLevel = PyLong_AsInt(args[3]); if (memLevel == -1 && PyErr_Occurred()) { goto exit; } @@ -322,7 +315,7 @@ zlib_compressobj(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyOb } } if (args[4]) { - strategy = _PyLong_AsInt(args[4]); + strategy = PyLong_AsInt(args[4]); if (strategy == -1 && PyErr_Occurred()) { goto exit; } @@ -333,10 +326,6 @@ zlib_compressobj(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyOb if (PyObject_GetBuffer(args[5], &zdict, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&zdict, 'C')) { - _PyArg_BadArgument("compressobj", "argument 'zdict'", "contiguous buffer", args[5]); - goto exit; - } skip_optional_pos: return_value = zlib_compressobj_impl(module, level, method, wbits, memLevel, strategy, &zdict); @@ -409,7 +398,7 @@ zlib_decompressobj(PyObject *module, PyObject *const *args, Py_ssize_t nargs, Py goto skip_optional_pos; } if (args[0]) { - wbits = _PyLong_AsInt(args[0]); + wbits = PyLong_AsInt(args[0]); if (wbits == -1 && PyErr_Occurred()) { goto exit; } @@ -472,10 +461,6 @@ zlib_Compress_compress(compobject *self, PyTypeObject *cls, PyObject *const *arg if (PyObject_GetBuffer(args[0], &data, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("compress", "argument 1", "contiguous buffer", args[0]); - goto exit; - } return_value = zlib_Compress_compress_impl(self, cls, &data); exit: @@ -552,10 +537,6 @@ zlib_Decompress_decompress(compobject *self, PyTypeObject *cls, PyObject *const if (PyObject_GetBuffer(args[0], &data, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("decompress", "argument 1", "contiguous buffer", args[0]); - goto exit; - } if (!noptargs) { goto skip_optional_pos; } @@ -628,7 +609,7 @@ zlib_Compress_flush(compobject *self, PyTypeObject *cls, PyObject *const *args, if (nargs < 1) { goto skip_optional_posonly; } - mode = _PyLong_AsInt(args[0]); + mode = PyLong_AsInt(args[0]); if (mode == -1 && PyErr_Occurred()) { goto exit; } @@ -964,10 +945,6 @@ zlib_ZlibDecompressor_decompress(ZlibDecompressor *self, PyObject *const *args, if (PyObject_GetBuffer(args[0], &data, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("decompress", "argument 'data'", "contiguous buffer", args[0]); - goto exit; - } if (!noptargs) { goto skip_optional_pos; } @@ -1025,10 +1002,6 @@ zlib_adler32(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (PyObject_GetBuffer(args[0], &data, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("adler32", "argument 1", "contiguous buffer", args[0]); - goto exit; - } if (nargs < 2) { goto skip_optional; } @@ -1079,10 +1052,6 @@ zlib_crc32(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (PyObject_GetBuffer(args[0], &data, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("crc32", "argument 1", "contiguous buffer", args[0]); - goto exit; - } if (nargs < 2) { goto skip_optional; } @@ -1129,4 +1098,4 @@ zlib_crc32(PyObject *module, PyObject *const *args, Py_ssize_t nargs) #ifndef ZLIB_DECOMPRESS___DEEPCOPY___METHODDEF #define ZLIB_DECOMPRESS___DEEPCOPY___METHODDEF #endif /* !defined(ZLIB_DECOMPRESS___DEEPCOPY___METHODDEF) */ -/*[clinic end generated code: output=57ff7b511ab23132 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=6dd97dc851c39031 input=a9049054013a1b77]*/ diff --git a/Modules/config.c.in b/Modules/config.c.in index 6081f95759538f..53b4fb285498d0 100644 --- a/Modules/config.c.in +++ b/Modules/config.c.in @@ -45,7 +45,7 @@ struct _inittab _PyImport_Inittab[] = { /* This lives in Python/Python-ast.c */ {"_ast", PyInit__ast}, - /* This lives in Python/Python-tokenizer.c */ + /* This lives in Python/Python-tokenize.c */ {"_tokenize", PyInit__tokenize}, /* These entries are here for sys.builtin_module_names */ diff --git a/Modules/errnomodule.c b/Modules/errnomodule.c index 301ad8313bc512..1100e9f6094352 100644 --- a/Modules/errnomodule.c +++ b/Modules/errnomodule.c @@ -1,41 +1,49 @@ - /* Errno module */ +#include "pyconfig.h" // Py_GIL_DISABLED + +#ifndef Py_GIL_DISABLED +// Need limited C API version 3.12 for Py_MOD_PER_INTERPRETER_GIL_SUPPORTED +#define Py_LIMITED_API 0x030c0000 +#endif + #include "Python.h" +#include // EPIPE /* Windows socket errors (WSA*) */ #ifdef MS_WINDOWS -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN -#endif -#include -/* The following constants were added to errno.h in VS2010 but have - preferred WSA equivalents. */ -#undef EADDRINUSE -#undef EADDRNOTAVAIL -#undef EAFNOSUPPORT -#undef EALREADY -#undef ECONNABORTED -#undef ECONNREFUSED -#undef ECONNRESET -#undef EDESTADDRREQ -#undef EHOSTUNREACH -#undef EINPROGRESS -#undef EISCONN -#undef ELOOP -#undef EMSGSIZE -#undef ENETDOWN -#undef ENETRESET -#undef ENETUNREACH -#undef ENOBUFS -#undef ENOPROTOOPT -#undef ENOTCONN -#undef ENOTSOCK -#undef EOPNOTSUPP -#undef EPROTONOSUPPORT -#undef EPROTOTYPE -#undef ETIMEDOUT -#undef EWOULDBLOCK +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +# endif +# include + + // The following constants were added to errno.h in VS2010 but have + // preferred WSA equivalents. +# undef EADDRINUSE +# undef EADDRNOTAVAIL +# undef EAFNOSUPPORT +# undef EALREADY +# undef ECONNABORTED +# undef ECONNREFUSED +# undef ECONNRESET +# undef EDESTADDRREQ +# undef EHOSTUNREACH +# undef EINPROGRESS +# undef EISCONN +# undef ELOOP +# undef EMSGSIZE +# undef ENETDOWN +# undef ENETRESET +# undef ENETUNREACH +# undef ENOBUFS +# undef ENOPROTOOPT +# undef ENOTCONN +# undef ENOTSOCK +# undef EOPNOTSUPP +# undef EPROTONOSUPPORT +# undef EPROTOTYPE +# undef ETIMEDOUT +# undef EWOULDBLOCK #endif /* diff --git a/Modules/faulthandler.c b/Modules/faulthandler.c index 428b090193f093..a2e3c2300b3ce8 100644 --- a/Modules/faulthandler.c +++ b/Modules/faulthandler.c @@ -3,10 +3,13 @@ #include "pycore_pyerrors.h" // _Py_DumpExtensionModules #include "pycore_pystate.h" // _PyThreadState_GET() #include "pycore_signal.h" // Py_NSIG +#include "pycore_sysmodule.h" // _PySys_GetAttr() #include "pycore_traceback.h" // _Py_DumpTracebackThreads -#include -#include +#ifdef HAVE_UNISTD_H +# include // _exit() +#endif +#include // sigaction() #include // abort() #if defined(HAVE_PTHREAD_SIGMASK) && !defined(HAVE_BROKEN_PTHREAD_SIGMASK) && defined(HAVE_PTHREAD_H) # include @@ -15,7 +18,7 @@ # include #endif #ifdef HAVE_SYS_RESOURCE_H -# include +# include // setrlimit() #endif #if defined(FAULTHANDLER_USE_ALT_STACK) && defined(HAVE_LINUX_AUXVEC_H) && defined(HAVE_SYS_AUXV_H) @@ -23,10 +26,11 @@ # include // getauxval() #endif + /* Allocate at maximum 100 MiB of the stack to raise the stack overflow */ #define STACK_OVERFLOW_MAX_SIZE (100 * 1024 * 1024) -#define PUTS(fd, str) _Py_write_noraise(fd, str, strlen(str)) +#define PUTS(fd, str) (void)_Py_write_noraise(fd, str, strlen(str)) // clang uses __attribute__((no_sanitize("undefined"))) @@ -115,7 +119,7 @@ faulthandler_get_fileno(PyObject **file_ptr) } } else if (PyLong_Check(file)) { - fd = _PyLong_AsInt(file); + fd = PyLong_AsInt(file); if (fd == -1 && PyErr_Occurred()) return -1; if (fd < 0) { @@ -145,10 +149,7 @@ faulthandler_get_fileno(PyObject **file_ptr) return -1; } - result = PyObject_CallMethodNoArgs(file, &_Py_ID(flush)); - if (result != NULL) - Py_DECREF(result); - else { + if (_PyFile_Flush(file) < 0) { /* ignore flush() error */ PyErr_Clear(); } @@ -176,7 +177,6 @@ faulthandler_dump_traceback(int fd, int all_threads, PyInterpreterState *interp) { static volatile int reentrant = 0; - PyThreadState *tstate; if (reentrant) return; @@ -191,7 +191,7 @@ faulthandler_dump_traceback(int fd, int all_threads, fault if the thread released the GIL, and so this function cannot be used. Read the thread specific storage (TSS) instead: call PyGILState_GetThisThreadState(). */ - tstate = PyGILState_GetThisThreadState(); + PyThreadState *tstate = PyGILState_GetThisThreadState(); if (all_threads) { (void)_Py_DumpTracebackThreads(fd, NULL, tstate); @@ -414,11 +414,10 @@ faulthandler_allocate_stack(void) int err = sigaltstack(&stack, &old_stack); if (err) { + PyErr_SetFromErrno(PyExc_OSError); /* Release the stack to retry sigaltstack() next time */ PyMem_Free(stack.ss_sp); stack.ss_sp = NULL; - - PyErr_SetFromErrno(PyExc_OSError); return -1; } return 0; @@ -576,7 +575,7 @@ faulthandler_thread(void *unused) /* Timeout => dump traceback */ assert(st == PY_LOCK_FAILURE); - _Py_write_noraise(thread.fd, thread.header, (int)thread.header_len); + (void)_Py_write_noraise(thread.fd, thread.header, (int)thread.header_len); errmsg = _Py_DumpTracebackThreads(thread.fd, thread.interp, NULL); ok = (errmsg == NULL); diff --git a/Modules/fcntlmodule.c b/Modules/fcntlmodule.c index e530621fd269a1..fd03abf0561da6 100644 --- a/Modules/fcntlmodule.c +++ b/Modules/fcntlmodule.c @@ -1,5 +1,9 @@ /* fcntl module */ +#ifndef Py_BUILD_CORE_BUILTIN +# define Py_BUILD_CORE_MODULE 1 +#endif + #include "Python.h" #ifdef HAVE_SYS_FILE_H @@ -208,11 +212,12 @@ fcntl_ioctl_impl(PyObject *module, int fd, unsigned int code, if (mutate_arg && (len <= IOCTL_BUFSZ)) { memcpy(str, buf, len); } - PyBuffer_Release(&pstr); /* No further access to str below this point */ if (ret < 0) { PyErr_SetFromErrno(PyExc_OSError); + PyBuffer_Release(&pstr); return NULL; } + PyBuffer_Release(&pstr); if (mutate_arg) { return PyLong_FromLong(ret); } @@ -237,8 +242,8 @@ fcntl_ioctl_impl(PyObject *module, int fd, unsigned int code, ret = ioctl(fd, code, buf); Py_END_ALLOW_THREADS if (ret < 0) { - PyBuffer_Release(&pstr); PyErr_SetFromErrno(PyExc_OSError); + PyBuffer_Release(&pstr); return NULL; } PyBuffer_Release(&pstr); diff --git a/Modules/gcmodule.c b/Modules/gcmodule.c index 35a35091bf4511..ffddef34ecce7a 100644 --- a/Modules/gcmodule.c +++ b/Modules/gcmodule.c @@ -1,1508 +1,27 @@ /* - - Reference Cycle Garbage Collection - ================================== - - Neil Schemenauer - - Based on a post on the python-dev list. Ideas from Guido van Rossum, - Eric Tiedemann, and various others. - - http://www.arctrix.com/nas/python/gc/ - - The following mailing list threads provide a historical perspective on - the design of this module. Note that a fair amount of refinement has - occurred since those discussions. - - http://mail.python.org/pipermail/python-dev/2000-March/002385.html - http://mail.python.org/pipermail/python-dev/2000-March/002434.html - http://mail.python.org/pipermail/python-dev/2000-March/002497.html - - For a highlevel view of the collection process, read the collect - function. - -*/ - -#include "Python.h" -#include "pycore_context.h" -#include "pycore_dict.h" // _PyDict_MaybeUntrack() -#include "pycore_initconfig.h" -#include "pycore_interp.h" // PyInterpreterState.gc -#include "pycore_object.h" -#include "pycore_pyerrors.h" -#include "pycore_pystate.h" // _PyThreadState_GET() -#include "pycore_weakref.h" // _PyWeakref_ClearRef() -#include "pydtrace.h" - -typedef struct _gc_runtime_state GCState; - -/*[clinic input] -module gc -[clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=b5c9690ecc842d79]*/ - - -#ifdef Py_DEBUG -# define GC_DEBUG -#endif - -#define GC_NEXT _PyGCHead_NEXT -#define GC_PREV _PyGCHead_PREV - -// update_refs() set this bit for all objects in current generation. -// subtract_refs() and move_unreachable() uses this to distinguish -// visited object is in GCing or not. -// -// move_unreachable() removes this flag from reachable objects. -// Only unreachable objects have this flag. -// -// No objects in interpreter have this flag after GC ends. -#define PREV_MASK_COLLECTING _PyGC_PREV_MASK_COLLECTING - -// Lowest bit of _gc_next is used for UNREACHABLE flag. -// -// This flag represents the object is in unreachable list in move_unreachable() -// -// Although this flag is used only in move_unreachable(), move_unreachable() -// doesn't clear this flag to skip unnecessary iteration. -// move_legacy_finalizers() removes this flag instead. -// Between them, unreachable list is not normal list and we can not use -// most gc_list_* functions for it. -#define NEXT_MASK_UNREACHABLE (1) - -#define AS_GC(op) _Py_AS_GC(op) -#define FROM_GC(gc) _Py_FROM_GC(gc) - - -static inline int -gc_is_collecting(PyGC_Head *g) -{ - return (g->_gc_prev & PREV_MASK_COLLECTING) != 0; -} - -static inline void -gc_clear_collecting(PyGC_Head *g) -{ - g->_gc_prev &= ~PREV_MASK_COLLECTING; -} - -static inline Py_ssize_t -gc_get_refs(PyGC_Head *g) -{ - return (Py_ssize_t)(g->_gc_prev >> _PyGC_PREV_SHIFT); -} - -static inline void -gc_set_refs(PyGC_Head *g, Py_ssize_t refs) -{ - g->_gc_prev = (g->_gc_prev & ~_PyGC_PREV_MASK) - | ((uintptr_t)(refs) << _PyGC_PREV_SHIFT); -} - -static inline void -gc_reset_refs(PyGC_Head *g, Py_ssize_t refs) -{ - g->_gc_prev = (g->_gc_prev & _PyGC_PREV_MASK_FINALIZED) - | PREV_MASK_COLLECTING - | ((uintptr_t)(refs) << _PyGC_PREV_SHIFT); -} - -static inline void -gc_decref(PyGC_Head *g) -{ - _PyObject_ASSERT_WITH_MSG(FROM_GC(g), - gc_get_refs(g) > 0, - "refcount is too small"); - g->_gc_prev -= 1 << _PyGC_PREV_SHIFT; -} - -/* set for debugging information */ -#define DEBUG_STATS (1<<0) /* print collection statistics */ -#define DEBUG_COLLECTABLE (1<<1) /* print collectable objects */ -#define DEBUG_UNCOLLECTABLE (1<<2) /* print uncollectable objects */ -#define DEBUG_SAVEALL (1<<5) /* save all garbage in gc.garbage */ -#define DEBUG_LEAK DEBUG_COLLECTABLE | \ - DEBUG_UNCOLLECTABLE | \ - DEBUG_SAVEALL - -#define GEN_HEAD(gcstate, n) (&(gcstate)->generations[n].head) - - -static GCState * -get_gc_state(void) -{ - PyInterpreterState *interp = _PyInterpreterState_GET(); - return &interp->gc; -} - - -void -_PyGC_InitState(GCState *gcstate) -{ -#define INIT_HEAD(GEN) \ - do { \ - GEN.head._gc_next = (uintptr_t)&GEN.head; \ - GEN.head._gc_prev = (uintptr_t)&GEN.head; \ - } while (0) - - for (int i = 0; i < NUM_GENERATIONS; i++) { - assert(gcstate->generations[i].count == 0); - INIT_HEAD(gcstate->generations[i]); - }; - gcstate->generation0 = GEN_HEAD(gcstate, 0); - INIT_HEAD(gcstate->permanent_generation); - -#undef INIT_HEAD -} - - -PyStatus -_PyGC_Init(PyInterpreterState *interp) -{ - GCState *gcstate = &interp->gc; - - gcstate->garbage = PyList_New(0); - if (gcstate->garbage == NULL) { - return _PyStatus_NO_MEMORY(); - } - - gcstate->callbacks = PyList_New(0); - if (gcstate->callbacks == NULL) { - return _PyStatus_NO_MEMORY(); - } - - return _PyStatus_OK(); -} - - -/* -_gc_prev values ---------------- - -Between collections, _gc_prev is used for doubly linked list. - -Lowest two bits of _gc_prev are used for flags. -PREV_MASK_COLLECTING is used only while collecting and cleared before GC ends -or _PyObject_GC_UNTRACK() is called. - -During a collection, _gc_prev is temporary used for gc_refs, and the gc list -is singly linked until _gc_prev is restored. - -gc_refs - At the start of a collection, update_refs() copies the true refcount - to gc_refs, for each object in the generation being collected. - subtract_refs() then adjusts gc_refs so that it equals the number of - times an object is referenced directly from outside the generation - being collected. - -PREV_MASK_COLLECTING - Objects in generation being collected are marked PREV_MASK_COLLECTING in - update_refs(). - - -_gc_next values ---------------- - -_gc_next takes these values: - -0 - The object is not tracked - -!= 0 - Pointer to the next object in the GC list. - Additionally, lowest bit is used temporary for - NEXT_MASK_UNREACHABLE flag described below. - -NEXT_MASK_UNREACHABLE - move_unreachable() then moves objects not reachable (whether directly or - indirectly) from outside the generation into an "unreachable" set and - set this flag. - - Objects that are found to be reachable have gc_refs set to 1. - When this flag is set for the reachable object, the object must be in - "unreachable" set. - The flag is unset and the object is moved back to "reachable" set. - - move_legacy_finalizers() will remove this flag from "unreachable" set. -*/ - -/*** list functions ***/ - -static inline void -gc_list_init(PyGC_Head *list) -{ - // List header must not have flags. - // We can assign pointer by simple cast. - list->_gc_prev = (uintptr_t)list; - list->_gc_next = (uintptr_t)list; -} - -static inline int -gc_list_is_empty(PyGC_Head *list) -{ - return (list->_gc_next == (uintptr_t)list); -} - -/* Append `node` to `list`. */ -static inline void -gc_list_append(PyGC_Head *node, PyGC_Head *list) -{ - PyGC_Head *last = (PyGC_Head *)list->_gc_prev; - - // last <-> node - _PyGCHead_SET_PREV(node, last); - _PyGCHead_SET_NEXT(last, node); - - // node <-> list - _PyGCHead_SET_NEXT(node, list); - list->_gc_prev = (uintptr_t)node; -} - -/* Remove `node` from the gc list it's currently in. */ -static inline void -gc_list_remove(PyGC_Head *node) -{ - PyGC_Head *prev = GC_PREV(node); - PyGC_Head *next = GC_NEXT(node); - - _PyGCHead_SET_NEXT(prev, next); - _PyGCHead_SET_PREV(next, prev); - - node->_gc_next = 0; /* object is not currently tracked */ -} - -/* Move `node` from the gc list it's currently in (which is not explicitly - * named here) to the end of `list`. This is semantically the same as - * gc_list_remove(node) followed by gc_list_append(node, list). - */ -static void -gc_list_move(PyGC_Head *node, PyGC_Head *list) -{ - /* Unlink from current list. */ - PyGC_Head *from_prev = GC_PREV(node); - PyGC_Head *from_next = GC_NEXT(node); - _PyGCHead_SET_NEXT(from_prev, from_next); - _PyGCHead_SET_PREV(from_next, from_prev); - - /* Relink at end of new list. */ - // list must not have flags. So we can skip macros. - PyGC_Head *to_prev = (PyGC_Head*)list->_gc_prev; - _PyGCHead_SET_PREV(node, to_prev); - _PyGCHead_SET_NEXT(to_prev, node); - list->_gc_prev = (uintptr_t)node; - _PyGCHead_SET_NEXT(node, list); -} - -/* append list `from` onto list `to`; `from` becomes an empty list */ -static void -gc_list_merge(PyGC_Head *from, PyGC_Head *to) -{ - assert(from != to); - if (!gc_list_is_empty(from)) { - PyGC_Head *to_tail = GC_PREV(to); - PyGC_Head *from_head = GC_NEXT(from); - PyGC_Head *from_tail = GC_PREV(from); - assert(from_head != from); - assert(from_tail != from); - - _PyGCHead_SET_NEXT(to_tail, from_head); - _PyGCHead_SET_PREV(from_head, to_tail); - - _PyGCHead_SET_NEXT(from_tail, to); - _PyGCHead_SET_PREV(to, from_tail); - } - gc_list_init(from); -} - -static Py_ssize_t -gc_list_size(PyGC_Head *list) -{ - PyGC_Head *gc; - Py_ssize_t n = 0; - for (gc = GC_NEXT(list); gc != list; gc = GC_NEXT(gc)) { - n++; - } - return n; -} - -/* Walk the list and mark all objects as non-collecting */ -static inline void -gc_list_clear_collecting(PyGC_Head *collectable) -{ - PyGC_Head *gc; - for (gc = GC_NEXT(collectable); gc != collectable; gc = GC_NEXT(gc)) { - gc_clear_collecting(gc); - } -} - -/* Append objects in a GC list to a Python list. - * Return 0 if all OK, < 0 if error (out of memory for list) - */ -static int -append_objects(PyObject *py_list, PyGC_Head *gc_list) -{ - PyGC_Head *gc; - for (gc = GC_NEXT(gc_list); gc != gc_list; gc = GC_NEXT(gc)) { - PyObject *op = FROM_GC(gc); - if (op != py_list) { - if (PyList_Append(py_list, op)) { - return -1; /* exception */ - } - } - } - return 0; -} - -// Constants for validate_list's flags argument. -enum flagstates {collecting_clear_unreachable_clear, - collecting_clear_unreachable_set, - collecting_set_unreachable_clear, - collecting_set_unreachable_set}; - -#ifdef GC_DEBUG -// validate_list checks list consistency. And it works as document -// describing when flags are expected to be set / unset. -// `head` must be a doubly-linked gc list, although it's fine (expected!) if -// the prev and next pointers are "polluted" with flags. -// What's checked: -// - The `head` pointers are not polluted. -// - The objects' PREV_MASK_COLLECTING and NEXT_MASK_UNREACHABLE flags are all -// `set or clear, as specified by the 'flags' argument. -// - The prev and next pointers are mutually consistent. -static void -validate_list(PyGC_Head *head, enum flagstates flags) -{ - assert((head->_gc_prev & PREV_MASK_COLLECTING) == 0); - assert((head->_gc_next & NEXT_MASK_UNREACHABLE) == 0); - uintptr_t prev_value = 0, next_value = 0; - switch (flags) { - case collecting_clear_unreachable_clear: - break; - case collecting_set_unreachable_clear: - prev_value = PREV_MASK_COLLECTING; - break; - case collecting_clear_unreachable_set: - next_value = NEXT_MASK_UNREACHABLE; - break; - case collecting_set_unreachable_set: - prev_value = PREV_MASK_COLLECTING; - next_value = NEXT_MASK_UNREACHABLE; - break; - default: - assert(! "bad internal flags argument"); - } - PyGC_Head *prev = head; - PyGC_Head *gc = GC_NEXT(head); - while (gc != head) { - PyGC_Head *trueprev = GC_PREV(gc); - PyGC_Head *truenext = (PyGC_Head *)(gc->_gc_next & ~NEXT_MASK_UNREACHABLE); - assert(truenext != NULL); - assert(trueprev == prev); - assert((gc->_gc_prev & PREV_MASK_COLLECTING) == prev_value); - assert((gc->_gc_next & NEXT_MASK_UNREACHABLE) == next_value); - prev = gc; - gc = truenext; - } - assert(prev == GC_PREV(head)); -} -#else -#define validate_list(x, y) do{}while(0) -#endif - -/*** end of list stuff ***/ - - -/* Set all gc_refs = ob_refcnt. After this, gc_refs is > 0 and - * PREV_MASK_COLLECTING bit is set for all objects in containers. - */ -static void -update_refs(PyGC_Head *containers) -{ - PyGC_Head *next; - PyGC_Head *gc = GC_NEXT(containers); - - while (gc != containers) { - next = GC_NEXT(gc); - /* Move any object that might have become immortal to the - * permanent generation as the reference count is not accurately - * reflecting the actual number of live references to this object - */ - if (_Py_IsImmortal(FROM_GC(gc))) { - gc_list_move(gc, &get_gc_state()->permanent_generation.head); - gc = next; - continue; - } - gc_reset_refs(gc, Py_REFCNT(FROM_GC(gc))); - /* Python's cyclic gc should never see an incoming refcount - * of 0: if something decref'ed to 0, it should have been - * deallocated immediately at that time. - * Possible cause (if the assert triggers): a tp_dealloc - * routine left a gc-aware object tracked during its teardown - * phase, and did something-- or allowed something to happen -- - * that called back into Python. gc can trigger then, and may - * see the still-tracked dying object. Before this assert - * was added, such mistakes went on to allow gc to try to - * delete the object again. In a debug build, that caused - * a mysterious segfault, when _Py_ForgetReference tried - * to remove the object from the doubly-linked list of all - * objects a second time. In a release build, an actual - * double deallocation occurred, which leads to corruption - * of the allocator's internal bookkeeping pointers. That's - * so serious that maybe this should be a release-build - * check instead of an assert? - */ - _PyObject_ASSERT(FROM_GC(gc), gc_get_refs(gc) != 0); - gc = next; - } -} - -/* A traversal callback for subtract_refs. */ -static int -visit_decref(PyObject *op, void *parent) -{ - OBJECT_STAT_INC(object_visits); - _PyObject_ASSERT(_PyObject_CAST(parent), !_PyObject_IsFreed(op)); - - if (_PyObject_IS_GC(op)) { - PyGC_Head *gc = AS_GC(op); - /* We're only interested in gc_refs for objects in the - * generation being collected, which can be recognized - * because only they have positive gc_refs. - */ - if (gc_is_collecting(gc)) { - gc_decref(gc); - } - } - return 0; -} - -/* Subtract internal references from gc_refs. After this, gc_refs is >= 0 - * for all objects in containers, and is GC_REACHABLE for all tracked gc - * objects not in containers. The ones with gc_refs > 0 are directly - * reachable from outside containers, and so can't be collected. - */ -static void -subtract_refs(PyGC_Head *containers) -{ - traverseproc traverse; - PyGC_Head *gc = GC_NEXT(containers); - for (; gc != containers; gc = GC_NEXT(gc)) { - PyObject *op = FROM_GC(gc); - traverse = Py_TYPE(op)->tp_traverse; - (void) traverse(op, - (visitproc)visit_decref, - op); - } -} - -/* A traversal callback for move_unreachable. */ -static int -visit_reachable(PyObject *op, PyGC_Head *reachable) -{ - OBJECT_STAT_INC(object_visits); - if (!_PyObject_IS_GC(op)) { - return 0; - } - - PyGC_Head *gc = AS_GC(op); - const Py_ssize_t gc_refs = gc_get_refs(gc); - - // Ignore objects in other generation. - // This also skips objects "to the left" of the current position in - // move_unreachable's scan of the 'young' list - they've already been - // traversed, and no longer have the PREV_MASK_COLLECTING flag. - if (! gc_is_collecting(gc)) { - return 0; - } - // It would be a logic error elsewhere if the collecting flag were set on - // an untracked object. - assert(gc->_gc_next != 0); - - if (gc->_gc_next & NEXT_MASK_UNREACHABLE) { - /* This had gc_refs = 0 when move_unreachable got - * to it, but turns out it's reachable after all. - * Move it back to move_unreachable's 'young' list, - * and move_unreachable will eventually get to it - * again. - */ - // Manually unlink gc from unreachable list because the list functions - // don't work right in the presence of NEXT_MASK_UNREACHABLE flags. - PyGC_Head *prev = GC_PREV(gc); - PyGC_Head *next = (PyGC_Head*)(gc->_gc_next & ~NEXT_MASK_UNREACHABLE); - _PyObject_ASSERT(FROM_GC(prev), - prev->_gc_next & NEXT_MASK_UNREACHABLE); - _PyObject_ASSERT(FROM_GC(next), - next->_gc_next & NEXT_MASK_UNREACHABLE); - prev->_gc_next = gc->_gc_next; // copy NEXT_MASK_UNREACHABLE - _PyGCHead_SET_PREV(next, prev); - - gc_list_append(gc, reachable); - gc_set_refs(gc, 1); - } - else if (gc_refs == 0) { - /* This is in move_unreachable's 'young' list, but - * the traversal hasn't yet gotten to it. All - * we need to do is tell move_unreachable that it's - * reachable. - */ - gc_set_refs(gc, 1); - } - /* Else there's nothing to do. - * If gc_refs > 0, it must be in move_unreachable's 'young' - * list, and move_unreachable will eventually get to it. - */ - else { - _PyObject_ASSERT_WITH_MSG(op, gc_refs > 0, "refcount is too small"); - } - return 0; -} - -/* Move the unreachable objects from young to unreachable. After this, - * all objects in young don't have PREV_MASK_COLLECTING flag and - * unreachable have the flag. - * All objects in young after this are directly or indirectly reachable - * from outside the original young; and all objects in unreachable are - * not. - * - * This function restores _gc_prev pointer. young and unreachable are - * doubly linked list after this function. - * But _gc_next in unreachable list has NEXT_MASK_UNREACHABLE flag. - * So we can not gc_list_* functions for unreachable until we remove the flag. - */ -static void -move_unreachable(PyGC_Head *young, PyGC_Head *unreachable) -{ - // previous elem in the young list, used for restore gc_prev. - PyGC_Head *prev = young; - PyGC_Head *gc = GC_NEXT(young); - - /* Invariants: all objects "to the left" of us in young are reachable - * (directly or indirectly) from outside the young list as it was at entry. - * - * All other objects from the original young "to the left" of us are in - * unreachable now, and have NEXT_MASK_UNREACHABLE. All objects to the - * left of us in 'young' now have been scanned, and no objects here - * or to the right have been scanned yet. - */ - - while (gc != young) { - if (gc_get_refs(gc)) { - /* gc is definitely reachable from outside the - * original 'young'. Mark it as such, and traverse - * its pointers to find any other objects that may - * be directly reachable from it. Note that the - * call to tp_traverse may append objects to young, - * so we have to wait until it returns to determine - * the next object to visit. - */ - PyObject *op = FROM_GC(gc); - traverseproc traverse = Py_TYPE(op)->tp_traverse; - _PyObject_ASSERT_WITH_MSG(op, gc_get_refs(gc) > 0, - "refcount is too small"); - // NOTE: visit_reachable may change gc->_gc_next when - // young->_gc_prev == gc. Don't do gc = GC_NEXT(gc) before! - (void) traverse(op, - (visitproc)visit_reachable, - (void *)young); - // relink gc_prev to prev element. - _PyGCHead_SET_PREV(gc, prev); - // gc is not COLLECTING state after here. - gc_clear_collecting(gc); - prev = gc; - } - else { - /* This *may* be unreachable. To make progress, - * assume it is. gc isn't directly reachable from - * any object we've already traversed, but may be - * reachable from an object we haven't gotten to yet. - * visit_reachable will eventually move gc back into - * young if that's so, and we'll see it again. - */ - // Move gc to unreachable. - // No need to gc->next->prev = prev because it is single linked. - prev->_gc_next = gc->_gc_next; - - // We can't use gc_list_append() here because we use - // NEXT_MASK_UNREACHABLE here. - PyGC_Head *last = GC_PREV(unreachable); - // NOTE: Since all objects in unreachable set has - // NEXT_MASK_UNREACHABLE flag, we set it unconditionally. - // But this may pollute the unreachable list head's 'next' pointer - // too. That's semantically senseless but expedient here - the - // damage is repaired when this function ends. - last->_gc_next = (NEXT_MASK_UNREACHABLE | (uintptr_t)gc); - _PyGCHead_SET_PREV(gc, last); - gc->_gc_next = (NEXT_MASK_UNREACHABLE | (uintptr_t)unreachable); - unreachable->_gc_prev = (uintptr_t)gc; - } - gc = (PyGC_Head*)prev->_gc_next; - } - // young->_gc_prev must be last element remained in the list. - young->_gc_prev = (uintptr_t)prev; - // don't let the pollution of the list head's next pointer leak - unreachable->_gc_next &= ~NEXT_MASK_UNREACHABLE; -} - -static void -untrack_tuples(PyGC_Head *head) -{ - PyGC_Head *next, *gc = GC_NEXT(head); - while (gc != head) { - PyObject *op = FROM_GC(gc); - next = GC_NEXT(gc); - if (PyTuple_CheckExact(op)) { - _PyTuple_MaybeUntrack(op); - } - gc = next; - } -} - -/* Try to untrack all currently tracked dictionaries */ -static void -untrack_dicts(PyGC_Head *head) -{ - PyGC_Head *next, *gc = GC_NEXT(head); - while (gc != head) { - PyObject *op = FROM_GC(gc); - next = GC_NEXT(gc); - if (PyDict_CheckExact(op)) { - _PyDict_MaybeUntrack(op); - } - gc = next; - } -} - -/* Return true if object has a pre-PEP 442 finalization method. */ -static int -has_legacy_finalizer(PyObject *op) -{ - return Py_TYPE(op)->tp_del != NULL; -} - -/* Move the objects in unreachable with tp_del slots into `finalizers`. - * - * This function also removes NEXT_MASK_UNREACHABLE flag - * from _gc_next in unreachable. - */ -static void -move_legacy_finalizers(PyGC_Head *unreachable, PyGC_Head *finalizers) -{ - PyGC_Head *gc, *next; - assert((unreachable->_gc_next & NEXT_MASK_UNREACHABLE) == 0); - - /* March over unreachable. Move objects with finalizers into - * `finalizers`. - */ - for (gc = GC_NEXT(unreachable); gc != unreachable; gc = next) { - PyObject *op = FROM_GC(gc); - - _PyObject_ASSERT(op, gc->_gc_next & NEXT_MASK_UNREACHABLE); - gc->_gc_next &= ~NEXT_MASK_UNREACHABLE; - next = (PyGC_Head*)gc->_gc_next; - - if (has_legacy_finalizer(op)) { - gc_clear_collecting(gc); - gc_list_move(gc, finalizers); - } - } -} - -static inline void -clear_unreachable_mask(PyGC_Head *unreachable) -{ - /* Check that the list head does not have the unreachable bit set */ - assert(((uintptr_t)unreachable & NEXT_MASK_UNREACHABLE) == 0); - - PyGC_Head *gc, *next; - assert((unreachable->_gc_next & NEXT_MASK_UNREACHABLE) == 0); - for (gc = GC_NEXT(unreachable); gc != unreachable; gc = next) { - _PyObject_ASSERT((PyObject*)FROM_GC(gc), gc->_gc_next & NEXT_MASK_UNREACHABLE); - gc->_gc_next &= ~NEXT_MASK_UNREACHABLE; - next = (PyGC_Head*)gc->_gc_next; - } - validate_list(unreachable, collecting_set_unreachable_clear); -} - -/* A traversal callback for move_legacy_finalizer_reachable. */ -static int -visit_move(PyObject *op, PyGC_Head *tolist) -{ - OBJECT_STAT_INC(object_visits); - if (_PyObject_IS_GC(op)) { - PyGC_Head *gc = AS_GC(op); - if (gc_is_collecting(gc)) { - gc_list_move(gc, tolist); - gc_clear_collecting(gc); - } - } - return 0; -} - -/* Move objects that are reachable from finalizers, from the unreachable set - * into finalizers set. - */ -static void -move_legacy_finalizer_reachable(PyGC_Head *finalizers) -{ - traverseproc traverse; - PyGC_Head *gc = GC_NEXT(finalizers); - for (; gc != finalizers; gc = GC_NEXT(gc)) { - /* Note that the finalizers list may grow during this. */ - traverse = Py_TYPE(FROM_GC(gc))->tp_traverse; - (void) traverse(FROM_GC(gc), - (visitproc)visit_move, - (void *)finalizers); - } -} - -/* Clear all weakrefs to unreachable objects, and if such a weakref has a - * callback, invoke it if necessary. Note that it's possible for such - * weakrefs to be outside the unreachable set -- indeed, those are precisely - * the weakrefs whose callbacks must be invoked. See gc_weakref.txt for - * overview & some details. Some weakrefs with callbacks may be reclaimed - * directly by this routine; the number reclaimed is the return value. Other - * weakrefs with callbacks may be moved into the `old` generation. Objects - * moved into `old` have gc_refs set to GC_REACHABLE; the objects remaining in - * unreachable are left at GC_TENTATIVELY_UNREACHABLE. When this returns, - * no object in `unreachable` is weakly referenced anymore. - */ -static int -handle_weakrefs(PyGC_Head *unreachable, PyGC_Head *old) -{ - PyGC_Head *gc; - PyObject *op; /* generally FROM_GC(gc) */ - PyWeakReference *wr; /* generally a cast of op */ - PyGC_Head wrcb_to_call; /* weakrefs with callbacks to call */ - PyGC_Head *next; - int num_freed = 0; - - gc_list_init(&wrcb_to_call); - - /* Clear all weakrefs to the objects in unreachable. If such a weakref - * also has a callback, move it into `wrcb_to_call` if the callback - * needs to be invoked. Note that we cannot invoke any callbacks until - * all weakrefs to unreachable objects are cleared, lest the callback - * resurrect an unreachable object via a still-active weakref. We - * make another pass over wrcb_to_call, invoking callbacks, after this - * pass completes. - */ - for (gc = GC_NEXT(unreachable); gc != unreachable; gc = next) { - PyWeakReference **wrlist; - - op = FROM_GC(gc); - next = GC_NEXT(gc); - - if (PyWeakref_Check(op)) { - /* A weakref inside the unreachable set must be cleared. If we - * allow its callback to execute inside delete_garbage(), it - * could expose objects that have tp_clear already called on - * them. Or, it could resurrect unreachable objects. One way - * this can happen is if some container objects do not implement - * tp_traverse. Then, wr_object can be outside the unreachable - * set but can be deallocated as a result of breaking the - * reference cycle. If we don't clear the weakref, the callback - * will run and potentially cause a crash. See bpo-38006 for - * one example. - */ - _PyWeakref_ClearRef((PyWeakReference *)op); - } - - if (! _PyType_SUPPORTS_WEAKREFS(Py_TYPE(op))) - continue; - - /* It supports weakrefs. Does it have any? - * - * This is never triggered for static types so we can avoid the - * (slightly) more costly _PyObject_GET_WEAKREFS_LISTPTR(). - */ - wrlist = _PyObject_GET_WEAKREFS_LISTPTR_FROM_OFFSET(op); - - /* `op` may have some weakrefs. March over the list, clear - * all the weakrefs, and move the weakrefs with callbacks - * that must be called into wrcb_to_call. - */ - for (wr = *wrlist; wr != NULL; wr = *wrlist) { - PyGC_Head *wrasgc; /* AS_GC(wr) */ - - /* _PyWeakref_ClearRef clears the weakref but leaves - * the callback pointer intact. Obscure: it also - * changes *wrlist. - */ - _PyObject_ASSERT((PyObject *)wr, wr->wr_object == op); - _PyWeakref_ClearRef(wr); - _PyObject_ASSERT((PyObject *)wr, wr->wr_object == Py_None); - if (wr->wr_callback == NULL) { - /* no callback */ - continue; - } - - /* Headache time. `op` is going away, and is weakly referenced by - * `wr`, which has a callback. Should the callback be invoked? If wr - * is also trash, no: - * - * 1. There's no need to call it. The object and the weakref are - * both going away, so it's legitimate to pretend the weakref is - * going away first. The user has to ensure a weakref outlives its - * referent if they want a guarantee that the wr callback will get - * invoked. - * - * 2. It may be catastrophic to call it. If the callback is also in - * cyclic trash (CT), then although the CT is unreachable from - * outside the current generation, CT may be reachable from the - * callback. Then the callback could resurrect insane objects. - * - * Since the callback is never needed and may be unsafe in this case, - * wr is simply left in the unreachable set. Note that because we - * already called _PyWeakref_ClearRef(wr), its callback will never - * trigger. - * - * OTOH, if wr isn't part of CT, we should invoke the callback: the - * weakref outlived the trash. Note that since wr isn't CT in this - * case, its callback can't be CT either -- wr acted as an external - * root to this generation, and therefore its callback did too. So - * nothing in CT is reachable from the callback either, so it's hard - * to imagine how calling it later could create a problem for us. wr - * is moved to wrcb_to_call in this case. - */ - if (gc_is_collecting(AS_GC((PyObject *)wr))) { - /* it should already have been cleared above */ - assert(wr->wr_object == Py_None); - continue; - } - - /* Create a new reference so that wr can't go away - * before we can process it again. - */ - Py_INCREF(wr); - - /* Move wr to wrcb_to_call, for the next pass. */ - wrasgc = AS_GC((PyObject *)wr); - assert(wrasgc != next); /* wrasgc is reachable, but - next isn't, so they can't - be the same */ - gc_list_move(wrasgc, &wrcb_to_call); - } - } - - /* Invoke the callbacks we decided to honor. It's safe to invoke them - * because they can't reference unreachable objects. - */ - while (! gc_list_is_empty(&wrcb_to_call)) { - PyObject *temp; - PyObject *callback; - - gc = (PyGC_Head*)wrcb_to_call._gc_next; - op = FROM_GC(gc); - _PyObject_ASSERT(op, PyWeakref_Check(op)); - wr = (PyWeakReference *)op; - callback = wr->wr_callback; - _PyObject_ASSERT(op, callback != NULL); - - /* copy-paste of weakrefobject.c's handle_callback() */ - temp = PyObject_CallOneArg(callback, (PyObject *)wr); - if (temp == NULL) - PyErr_WriteUnraisable(callback); - else - Py_DECREF(temp); - - /* Give up the reference we created in the first pass. When - * op's refcount hits 0 (which it may or may not do right now), - * op's tp_dealloc will decref op->wr_callback too. Note - * that the refcount probably will hit 0 now, and because this - * weakref was reachable to begin with, gc didn't already - * add it to its count of freed objects. Example: a reachable - * weak value dict maps some key to this reachable weakref. - * The callback removes this key->weakref mapping from the - * dict, leaving no other references to the weakref (excepting - * ours). - */ - Py_DECREF(op); - if (wrcb_to_call._gc_next == (uintptr_t)gc) { - /* object is still alive -- move it */ - gc_list_move(gc, old); - } - else { - ++num_freed; - } - } - - return num_freed; -} - -static void -debug_cycle(const char *msg, PyObject *op) -{ - PySys_FormatStderr("gc: %s <%s %p>\n", - msg, Py_TYPE(op)->tp_name, op); -} - -/* Handle uncollectable garbage (cycles with tp_del slots, and stuff reachable - * only from such cycles). - * If DEBUG_SAVEALL, all objects in finalizers are appended to the module - * garbage list (a Python list), else only the objects in finalizers with - * __del__ methods are appended to garbage. All objects in finalizers are - * merged into the old list regardless. - */ -static void -handle_legacy_finalizers(PyThreadState *tstate, - GCState *gcstate, - PyGC_Head *finalizers, PyGC_Head *old) -{ - assert(!_PyErr_Occurred(tstate)); - assert(gcstate->garbage != NULL); - - PyGC_Head *gc = GC_NEXT(finalizers); - for (; gc != finalizers; gc = GC_NEXT(gc)) { - PyObject *op = FROM_GC(gc); - - if ((gcstate->debug & DEBUG_SAVEALL) || has_legacy_finalizer(op)) { - if (PyList_Append(gcstate->garbage, op) < 0) { - _PyErr_Clear(tstate); - break; - } - } - } - - gc_list_merge(finalizers, old); -} - -/* Run first-time finalizers (if any) on all the objects in collectable. - * Note that this may remove some (or even all) of the objects from the - * list, due to refcounts falling to 0. - */ -static void -finalize_garbage(PyThreadState *tstate, PyGC_Head *collectable) -{ - destructor finalize; - PyGC_Head seen; - - /* While we're going through the loop, `finalize(op)` may cause op, or - * other objects, to be reclaimed via refcounts falling to zero. So - * there's little we can rely on about the structure of the input - * `collectable` list across iterations. For safety, we always take the - * first object in that list and move it to a temporary `seen` list. - * If objects vanish from the `collectable` and `seen` lists we don't - * care. - */ - gc_list_init(&seen); - - while (!gc_list_is_empty(collectable)) { - PyGC_Head *gc = GC_NEXT(collectable); - PyObject *op = FROM_GC(gc); - gc_list_move(gc, &seen); - if (!_PyGCHead_FINALIZED(gc) && - (finalize = Py_TYPE(op)->tp_finalize) != NULL) { - _PyGCHead_SET_FINALIZED(gc); - Py_INCREF(op); - finalize(op); - assert(!_PyErr_Occurred(tstate)); - Py_DECREF(op); - } - } - gc_list_merge(&seen, collectable); -} - -/* Break reference cycles by clearing the containers involved. This is - * tricky business as the lists can be changing and we don't know which - * objects may be freed. It is possible I screwed something up here. - */ -static void -delete_garbage(PyThreadState *tstate, GCState *gcstate, - PyGC_Head *collectable, PyGC_Head *old) -{ - assert(!_PyErr_Occurred(tstate)); - - while (!gc_list_is_empty(collectable)) { - PyGC_Head *gc = GC_NEXT(collectable); - PyObject *op = FROM_GC(gc); - - _PyObject_ASSERT_WITH_MSG(op, Py_REFCNT(op) > 0, - "refcount is too small"); - - if (gcstate->debug & DEBUG_SAVEALL) { - assert(gcstate->garbage != NULL); - if (PyList_Append(gcstate->garbage, op) < 0) { - _PyErr_Clear(tstate); - } - } - else { - inquiry clear; - if ((clear = Py_TYPE(op)->tp_clear) != NULL) { - Py_INCREF(op); - (void) clear(op); - if (_PyErr_Occurred(tstate)) { - _PyErr_WriteUnraisableMsg("in tp_clear of", - (PyObject*)Py_TYPE(op)); - } - Py_DECREF(op); - } - } - if (GC_NEXT(collectable) == gc) { - /* object is still alive, move it, it may die later */ - gc_clear_collecting(gc); - gc_list_move(gc, old); - } - } -} - -/* Clear all free lists - * All free lists are cleared during the collection of the highest generation. - * Allocated items in the free list may keep a pymalloc arena occupied. - * Clearing the free lists may give back memory to the OS earlier. - */ -static void -clear_freelists(PyInterpreterState *interp) -{ - _PyTuple_ClearFreeList(interp); - _PyFloat_ClearFreeList(interp); - _PyList_ClearFreeList(interp); - _PyDict_ClearFreeList(interp); - _PyAsyncGen_ClearFreeLists(interp); - _PyContext_ClearFreeList(interp); -} - -// Show stats for objects in each generations -static void -show_stats_each_generations(GCState *gcstate) -{ - char buf[100]; - size_t pos = 0; - - for (int i = 0; i < NUM_GENERATIONS && pos < sizeof(buf); i++) { - pos += PyOS_snprintf(buf+pos, sizeof(buf)-pos, - " %zd", - gc_list_size(GEN_HEAD(gcstate, i))); - } - - PySys_FormatStderr( - "gc: objects in each generation:%s\n" - "gc: objects in permanent generation: %zd\n", - buf, gc_list_size(&gcstate->permanent_generation.head)); -} - -/* Deduce which objects among "base" are unreachable from outside the list - and move them to 'unreachable'. The process consist in the following steps: - -1. Copy all reference counts to a different field (gc_prev is used to hold - this copy to save memory). -2. Traverse all objects in "base" and visit all referred objects using - "tp_traverse" and for every visited object, subtract 1 to the reference - count (the one that we copied in the previous step). After this step, all - objects that can be reached directly from outside must have strictly positive - reference count, while all unreachable objects must have a count of exactly 0. -3. Identify all unreachable objects (the ones with 0 reference count) and move - them to the "unreachable" list. This step also needs to move back to "base" all - objects that were initially marked as unreachable but are referred transitively - by the reachable objects (the ones with strictly positive reference count). - -Contracts: - - * The "base" has to be a valid list with no mask set. - - * The "unreachable" list must be uninitialized (this function calls - gc_list_init over 'unreachable'). - -IMPORTANT: This function leaves 'unreachable' with the NEXT_MASK_UNREACHABLE -flag set but it does not clear it to skip unnecessary iteration. Before the -flag is cleared (for example, by using 'clear_unreachable_mask' function or -by a call to 'move_legacy_finalizers'), the 'unreachable' list is not a normal -list and we can not use most gc_list_* functions for it. */ -static inline void -deduce_unreachable(PyGC_Head *base, PyGC_Head *unreachable) { - validate_list(base, collecting_clear_unreachable_clear); - /* Using ob_refcnt and gc_refs, calculate which objects in the - * container set are reachable from outside the set (i.e., have a - * refcount greater than 0 when all the references within the - * set are taken into account). - */ - update_refs(base); // gc_prev is used for gc_refs - subtract_refs(base); - - /* Leave everything reachable from outside base in base, and move - * everything else (in base) to unreachable. - * - * NOTE: This used to move the reachable objects into a reachable - * set instead. But most things usually turn out to be reachable, - * so it's more efficient to move the unreachable things. It "sounds slick" - * to move the unreachable objects, until you think about it - the reason it - * pays isn't actually obvious. - * - * Suppose we create objects A, B, C in that order. They appear in the young - * generation in the same order. If B points to A, and C to B, and C is - * reachable from outside, then the adjusted refcounts will be 0, 0, and 1 - * respectively. - * - * When move_unreachable finds A, A is moved to the unreachable list. The - * same for B when it's first encountered. Then C is traversed, B is moved - * _back_ to the reachable list. B is eventually traversed, and then A is - * moved back to the reachable list. - * - * So instead of not moving at all, the reachable objects B and A are moved - * twice each. Why is this a win? A straightforward algorithm to move the - * reachable objects instead would move A, B, and C once each. - * - * The key is that this dance leaves the objects in order C, B, A - it's - * reversed from the original order. On all _subsequent_ scans, none of - * them will move. Since most objects aren't in cycles, this can save an - * unbounded number of moves across an unbounded number of later collections. - * It can cost more only the first time the chain is scanned. - * - * Drawback: move_unreachable is also used to find out what's still trash - * after finalizers may resurrect objects. In _that_ case most unreachable - * objects will remain unreachable, so it would be more efficient to move - * the reachable objects instead. But this is a one-time cost, probably not - * worth complicating the code to speed just a little. - */ - gc_list_init(unreachable); - move_unreachable(base, unreachable); // gc_prev is pointer again - validate_list(base, collecting_clear_unreachable_clear); - validate_list(unreachable, collecting_set_unreachable_set); -} - -/* Handle objects that may have resurrected after a call to 'finalize_garbage', moving - them to 'old_generation' and placing the rest on 'still_unreachable'. - - Contracts: - * After this function 'unreachable' must not be used anymore and 'still_unreachable' - will contain the objects that did not resurrect. - - * The "still_unreachable" list must be uninitialized (this function calls - gc_list_init over 'still_unreachable'). - -IMPORTANT: After a call to this function, the 'still_unreachable' set will have the -PREV_MARK_COLLECTING set, but the objects in this set are going to be removed so -we can skip the expense of clearing the flag to avoid extra iteration. */ -static inline void -handle_resurrected_objects(PyGC_Head *unreachable, PyGC_Head* still_unreachable, - PyGC_Head *old_generation) -{ - // Remove the PREV_MASK_COLLECTING from unreachable - // to prepare it for a new call to 'deduce_unreachable' - gc_list_clear_collecting(unreachable); - - // After the call to deduce_unreachable, the 'still_unreachable' set will - // have the PREV_MARK_COLLECTING set, but the objects are going to be - // removed so we can skip the expense of clearing the flag. - PyGC_Head* resurrected = unreachable; - deduce_unreachable(resurrected, still_unreachable); - clear_unreachable_mask(still_unreachable); - - // Move the resurrected objects to the old generation for future collection. - gc_list_merge(resurrected, old_generation); -} - -/* This is the main function. Read this to understand how the - * collection process works. */ -static Py_ssize_t -gc_collect_main(PyThreadState *tstate, int generation, - Py_ssize_t *n_collected, Py_ssize_t *n_uncollectable, - int nofail) -{ - GC_STAT_ADD(generation, collections, 1); -#ifdef Py_STATS - if (_py_stats) { - _py_stats->object_stats.object_visits = 0; - } -#endif - int i; - Py_ssize_t m = 0; /* # objects collected */ - Py_ssize_t n = 0; /* # unreachable objects that couldn't be collected */ - PyGC_Head *young; /* the generation we are examining */ - PyGC_Head *old; /* next older generation */ - PyGC_Head unreachable; /* non-problematic unreachable trash */ - PyGC_Head finalizers; /* objects with, & reachable from, __del__ */ - PyGC_Head *gc; - _PyTime_t t1 = 0; /* initialize to prevent a compiler warning */ - GCState *gcstate = &tstate->interp->gc; - - // gc_collect_main() must not be called before _PyGC_Init - // or after _PyGC_Fini() - assert(gcstate->garbage != NULL); - assert(!_PyErr_Occurred(tstate)); - - if (gcstate->debug & DEBUG_STATS) { - PySys_WriteStderr("gc: collecting generation %d...\n", generation); - show_stats_each_generations(gcstate); - t1 = _PyTime_GetPerfCounter(); - } - - if (PyDTrace_GC_START_ENABLED()) - PyDTrace_GC_START(generation); - - /* update collection and allocation counters */ - if (generation+1 < NUM_GENERATIONS) - gcstate->generations[generation+1].count += 1; - for (i = 0; i <= generation; i++) - gcstate->generations[i].count = 0; - - /* merge younger generations with one we are currently collecting */ - for (i = 0; i < generation; i++) { - gc_list_merge(GEN_HEAD(gcstate, i), GEN_HEAD(gcstate, generation)); - } - - /* handy references */ - young = GEN_HEAD(gcstate, generation); - if (generation < NUM_GENERATIONS-1) - old = GEN_HEAD(gcstate, generation+1); - else - old = young; - validate_list(old, collecting_clear_unreachable_clear); - - deduce_unreachable(young, &unreachable); - - untrack_tuples(young); - /* Move reachable objects to next generation. */ - if (young != old) { - if (generation == NUM_GENERATIONS - 2) { - gcstate->long_lived_pending += gc_list_size(young); - } - gc_list_merge(young, old); - } - else { - /* We only un-track dicts in full collections, to avoid quadratic - dict build-up. See issue #14775. */ - untrack_dicts(young); - gcstate->long_lived_pending = 0; - gcstate->long_lived_total = gc_list_size(young); - } - - /* All objects in unreachable are trash, but objects reachable from - * legacy finalizers (e.g. tp_del) can't safely be deleted. - */ - gc_list_init(&finalizers); - // NEXT_MASK_UNREACHABLE is cleared here. - // After move_legacy_finalizers(), unreachable is normal list. - move_legacy_finalizers(&unreachable, &finalizers); - /* finalizers contains the unreachable objects with a legacy finalizer; - * unreachable objects reachable *from* those are also uncollectable, - * and we move those into the finalizers list too. - */ - move_legacy_finalizer_reachable(&finalizers); - - validate_list(&finalizers, collecting_clear_unreachable_clear); - validate_list(&unreachable, collecting_set_unreachable_clear); - - /* Print debugging information. */ - if (gcstate->debug & DEBUG_COLLECTABLE) { - for (gc = GC_NEXT(&unreachable); gc != &unreachable; gc = GC_NEXT(gc)) { - debug_cycle("collectable", FROM_GC(gc)); - } - } - - /* Clear weakrefs and invoke callbacks as necessary. */ - m += handle_weakrefs(&unreachable, old); - - validate_list(old, collecting_clear_unreachable_clear); - validate_list(&unreachable, collecting_set_unreachable_clear); - - /* Call tp_finalize on objects which have one. */ - finalize_garbage(tstate, &unreachable); - - /* Handle any objects that may have resurrected after the call - * to 'finalize_garbage' and continue the collection with the - * objects that are still unreachable */ - PyGC_Head final_unreachable; - handle_resurrected_objects(&unreachable, &final_unreachable, old); - - /* Call tp_clear on objects in the final_unreachable set. This will cause - * the reference cycles to be broken. It may also cause some objects - * in finalizers to be freed. - */ - m += gc_list_size(&final_unreachable); - delete_garbage(tstate, gcstate, &final_unreachable, old); - - /* Collect statistics on uncollectable objects found and print - * debugging information. */ - for (gc = GC_NEXT(&finalizers); gc != &finalizers; gc = GC_NEXT(gc)) { - n++; - if (gcstate->debug & DEBUG_UNCOLLECTABLE) - debug_cycle("uncollectable", FROM_GC(gc)); - } - if (gcstate->debug & DEBUG_STATS) { - double d = _PyTime_AsSecondsDouble(_PyTime_GetPerfCounter() - t1); - PySys_WriteStderr( - "gc: done, %zd unreachable, %zd uncollectable, %.4fs elapsed\n", - n+m, n, d); - } - - /* Append instances in the uncollectable set to a Python - * reachable list of garbage. The programmer has to deal with - * this if they insist on creating this type of structure. - */ - handle_legacy_finalizers(tstate, gcstate, &finalizers, old); - validate_list(old, collecting_clear_unreachable_clear); - - /* Clear free list only during the collection of the highest - * generation */ - if (generation == NUM_GENERATIONS-1) { - clear_freelists(tstate->interp); - } - - if (_PyErr_Occurred(tstate)) { - if (nofail) { - _PyErr_Clear(tstate); - } - else { - _PyErr_WriteUnraisableMsg("in garbage collection", NULL); - } - } - - /* Update stats */ - if (n_collected) { - *n_collected = m; - } - if (n_uncollectable) { - *n_uncollectable = n; - } - - struct gc_generation_stats *stats = &gcstate->generation_stats[generation]; - stats->collections++; - stats->collected += m; - stats->uncollectable += n; - - GC_STAT_ADD(generation, objects_collected, m); -#ifdef Py_STATS - if (_py_stats) { - GC_STAT_ADD(generation, object_visits, - _py_stats->object_stats.object_visits); - _py_stats->object_stats.object_visits = 0; - } -#endif - - if (PyDTrace_GC_DONE_ENABLED()) { - PyDTrace_GC_DONE(n + m); - } - - assert(!_PyErr_Occurred(tstate)); - return n + m; -} - -/* Invoke progress callbacks to notify clients that garbage collection - * is starting or stopping + * Python interface to the garbage collector. + * + * See Python/gc.c for the implementation of the garbage collector. */ -static void -invoke_gc_callback(PyThreadState *tstate, const char *phase, - int generation, Py_ssize_t collected, - Py_ssize_t uncollectable) -{ - assert(!_PyErr_Occurred(tstate)); - - /* we may get called very early */ - GCState *gcstate = &tstate->interp->gc; - if (gcstate->callbacks == NULL) { - return; - } - - /* The local variable cannot be rebound, check it for sanity */ - assert(PyList_CheckExact(gcstate->callbacks)); - PyObject *info = NULL; - if (PyList_GET_SIZE(gcstate->callbacks) != 0) { - info = Py_BuildValue("{sisnsn}", - "generation", generation, - "collected", collected, - "uncollectable", uncollectable); - if (info == NULL) { - PyErr_WriteUnraisable(NULL); - return; - } - } - - PyObject *phase_obj = PyUnicode_FromString(phase); - if (phase_obj == NULL) { - Py_XDECREF(info); - PyErr_WriteUnraisable(NULL); - return; - } - PyObject *stack[] = {phase_obj, info}; - for (Py_ssize_t i=0; icallbacks); i++) { - PyObject *r, *cb = PyList_GET_ITEM(gcstate->callbacks, i); - Py_INCREF(cb); /* make sure cb doesn't go away */ - r = PyObject_Vectorcall(cb, stack, 2, NULL); - if (r == NULL) { - PyErr_WriteUnraisable(cb); - } - else { - Py_DECREF(r); - } - Py_DECREF(cb); - } - Py_DECREF(phase_obj); - Py_XDECREF(info); - assert(!_PyErr_Occurred(tstate)); -} +#include "Python.h" +#include "pycore_gc.h" +#include "pycore_object.h" // _PyObject_IS_GC() +#include "pycore_pystate.h" // _PyInterpreterState_GET() -/* Perform garbage collection of a generation and invoke - * progress callbacks. - */ -static Py_ssize_t -gc_collect_with_callback(PyThreadState *tstate, int generation) -{ - assert(!_PyErr_Occurred(tstate)); - Py_ssize_t result, collected, uncollectable; - invoke_gc_callback(tstate, "start", generation, 0, 0); - result = gc_collect_main(tstate, generation, &collected, &uncollectable, 0); - invoke_gc_callback(tstate, "stop", generation, collected, uncollectable); - assert(!_PyErr_Occurred(tstate)); - return result; -} +typedef struct _gc_runtime_state GCState; -static Py_ssize_t -gc_collect_generations(PyThreadState *tstate) +static GCState * +get_gc_state(void) { - GCState *gcstate = &tstate->interp->gc; - /* Find the oldest generation (highest numbered) where the count - * exceeds the threshold. Objects in the that generation and - * generations younger than it will be collected. */ - Py_ssize_t n = 0; - for (int i = NUM_GENERATIONS-1; i >= 0; i--) { - if (gcstate->generations[i].count > gcstate->generations[i].threshold) { - /* Avoid quadratic performance degradation in number - of tracked objects (see also issue #4074): - - To limit the cost of garbage collection, there are two strategies; - - make each collection faster, e.g. by scanning fewer objects - - do less collections - This heuristic is about the latter strategy. - - In addition to the various configurable thresholds, we only trigger a - full collection if the ratio - - long_lived_pending / long_lived_total - - is above a given value (hardwired to 25%). - - The reason is that, while "non-full" collections (i.e., collections of - the young and middle generations) will always examine roughly the same - number of objects -- determined by the aforementioned thresholds --, - the cost of a full collection is proportional to the total number of - long-lived objects, which is virtually unbounded. - - Indeed, it has been remarked that doing a full collection every - of object creations entails a dramatic performance - degradation in workloads which consist in creating and storing lots of - long-lived objects (e.g. building a large list of GC-tracked objects would - show quadratic performance, instead of linear as expected: see issue #4074). - - Using the above ratio, instead, yields amortized linear performance in - the total number of objects (the effect of which can be summarized - thusly: "each full garbage collection is more and more costly as the - number of objects grows, but we do fewer and fewer of them"). - - This heuristic was suggested by Martin von Löwis on python-dev in - June 2008. His original analysis and proposal can be found at: - http://mail.python.org/pipermail/python-dev/2008-June/080579.html - */ - if (i == NUM_GENERATIONS - 1 - && gcstate->long_lived_pending < gcstate->long_lived_total / 4) - continue; - n = gc_collect_with_callback(tstate, i); - break; - } - } - return n; + PyInterpreterState *interp = _PyInterpreterState_GET(); + return &interp->gc; } +/*[clinic input] +module gc +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=b5c9690ecc842d79]*/ #include "clinic/gcmodule.c.h" /*[clinic input] @@ -1571,18 +90,7 @@ gc_collect_impl(PyObject *module, int generation) return -1; } - GCState *gcstate = &tstate->interp->gc; - Py_ssize_t n; - if (gcstate->collecting) { - /* already collecting, don't do anything */ - n = 0; - } - else { - gcstate->collecting = 1; - n = gc_collect_with_callback(tstate, generation); - gcstate->collecting = 0; - } - return n; + return _PyGC_Collect(tstate, generation, _Py_GC_REASON_MANUAL); } /*[clinic input] @@ -1626,24 +134,41 @@ gc_get_debug_impl(PyObject *module) return gcstate->debug; } -PyDoc_STRVAR(gc_set_thresh__doc__, -"set_threshold(threshold0, [threshold1, threshold2]) -> None\n" -"\n" -"Sets the collection thresholds. Setting threshold0 to zero disables\n" -"collection.\n"); +/*[clinic input] +gc.set_threshold + + threshold0: int + [ + threshold1: int + [ + threshold2: int + ] + ] + / + +Set the collection thresholds (the collection frequency). + +Setting 'threshold0' to zero disables collection. +[clinic start generated code]*/ static PyObject * -gc_set_threshold(PyObject *self, PyObject *args) +gc_set_threshold_impl(PyObject *module, int threshold0, int group_right_1, + int threshold1, int group_right_2, int threshold2) +/*[clinic end generated code: output=2e3c7c7dd59060f3 input=0d9612db50984eec]*/ { GCState *gcstate = get_gc_state(); - if (!PyArg_ParseTuple(args, "i|ii:set_threshold", - &gcstate->generations[0].threshold, - &gcstate->generations[1].threshold, - &gcstate->generations[2].threshold)) - return NULL; - for (int i = 3; i < NUM_GENERATIONS; i++) { + + gcstate->generations[0].threshold = threshold0; + if (group_right_1) { + gcstate->generations[1].threshold = threshold1; + } + if (group_right_2) { + gcstate->generations[2].threshold = threshold2; + /* generations higher than 2 get the same threshold */ - gcstate->generations[i].threshold = gcstate->generations[2].threshold; + for (int i = 3; i < NUM_GENERATIONS; i++) { + gcstate->generations[i].threshold = gcstate->generations[2].threshold; + } } Py_RETURN_NONE; } @@ -1682,74 +207,45 @@ gc_get_count_impl(PyObject *module) gcstate->generations[2].count); } -static int -referrersvisit(PyObject* obj, PyObject *objs) -{ - Py_ssize_t i; - for (i = 0; i < PyTuple_GET_SIZE(objs); i++) - if (PyTuple_GET_ITEM(objs, i) == obj) - return 1; - return 0; -} +/*[clinic input] +gc.get_referrers -static int -gc_referrers_for(PyObject *objs, PyGC_Head *list, PyObject *resultlist) -{ - PyGC_Head *gc; - PyObject *obj; - traverseproc traverse; - for (gc = GC_NEXT(list); gc != list; gc = GC_NEXT(gc)) { - obj = FROM_GC(gc); - traverse = Py_TYPE(obj)->tp_traverse; - if (obj == objs || obj == resultlist) - continue; - if (traverse(obj, (visitproc)referrersvisit, objs)) { - if (PyList_Append(resultlist, obj) < 0) - return 0; /* error */ - } - } - return 1; /* no error */ -} + *objs as args: object -PyDoc_STRVAR(gc_get_referrers__doc__, -"get_referrers(*objs) -> list\n\ -Return the list of objects that directly refer to any of objs."); +Return the list of objects that directly refer to any of 'objs'. +[clinic start generated code]*/ static PyObject * -gc_get_referrers(PyObject *self, PyObject *args) +gc_get_referrers_impl(PyObject *module, PyObject *args) +/*[clinic end generated code: output=296a09587f6a86b5 input=bae96961b14a0922]*/ { if (PySys_Audit("gc.get_referrers", "(O)", args) < 0) { return NULL; } - PyObject *result = PyList_New(0); - if (!result) { - return NULL; - } - - GCState *gcstate = get_gc_state(); - for (int i = 0; i < NUM_GENERATIONS; i++) { - if (!(gc_referrers_for(args, GEN_HEAD(gcstate, i), result))) { - Py_DECREF(result); - return NULL; - } - } - return result; + PyInterpreterState *interp = _PyInterpreterState_GET(); + return _PyGC_GetReferrers(interp, args); } /* Append obj to list; return true if error (out of memory), false if OK. */ static int -referentsvisit(PyObject *obj, PyObject *list) +referentsvisit(PyObject *obj, void *arg) { + PyObject *list = arg; return PyList_Append(list, obj) < 0; } -PyDoc_STRVAR(gc_get_referents__doc__, -"get_referents(*objs) -> list\n\ -Return the list of objects that are directly referred to by objs."); +/*[clinic input] +gc.get_referents + + *objs as args: object + +Return the list of objects that are directly referred to by 'objs'. +[clinic start generated code]*/ static PyObject * -gc_get_referents(PyObject *self, PyObject *args) +gc_get_referents_impl(PyObject *module, PyObject *args) +/*[clinic end generated code: output=d47dc02cefd06fe8 input=b3ceab0c34038cbf]*/ { Py_ssize_t i; if (PySys_Audit("gc.get_referents", "(O)", args) < 0) { @@ -1769,7 +265,7 @@ gc_get_referents(PyObject *self, PyObject *args) traverse = Py_TYPE(obj)->tp_traverse; if (! traverse) continue; - if (traverse(obj, (visitproc)referentsvisit, result)) { + if (traverse(obj, referentsvisit, result)) { Py_DECREF(result); return NULL; } @@ -1792,54 +288,25 @@ static PyObject * gc_get_objects_impl(PyObject *module, Py_ssize_t generation) /*[clinic end generated code: output=48b35fea4ba6cb0e input=ef7da9df9806754c]*/ { - PyThreadState *tstate = _PyThreadState_GET(); - int i; - PyObject* result; - GCState *gcstate = &tstate->interp->gc; - if (PySys_Audit("gc.get_objects", "n", generation) < 0) { return NULL; } - result = PyList_New(0); - if (result == NULL) { - return NULL; - } - - /* If generation is passed, we extract only that generation */ - if (generation != -1) { - if (generation >= NUM_GENERATIONS) { - _PyErr_Format(tstate, PyExc_ValueError, - "generation parameter must be less than the number of " - "available generations (%i)", - NUM_GENERATIONS); - goto error; - } - - if (generation < 0) { - _PyErr_SetString(tstate, PyExc_ValueError, - "generation parameter cannot be negative"); - goto error; - } - - if (append_objects(result, GEN_HEAD(gcstate, generation))) { - goto error; - } - - return result; + if (generation >= NUM_GENERATIONS) { + return PyErr_Format(PyExc_ValueError, + "generation parameter must be less than the number of " + "available generations (%i)", + NUM_GENERATIONS); } - /* If generation is not passed or None, get all objects from all generations */ - for (i = 0; i < NUM_GENERATIONS; i++) { - if (append_objects(result, GEN_HEAD(gcstate, i))) { - goto error; - } + if (generation < -1) { + PyErr_SetString(PyExc_ValueError, + "generation parameter cannot be negative"); + return NULL; } - return result; -error: - Py_DECREF(result); - return NULL; + PyInterpreterState *interp = _PyInterpreterState_GET(); + return _PyGC_GetObjects(interp, generation); } /*[clinic input] @@ -1947,11 +414,8 @@ static PyObject * gc_freeze_impl(PyObject *module) /*[clinic end generated code: output=502159d9cdc4c139 input=b602b16ac5febbe5]*/ { - GCState *gcstate = get_gc_state(); - for (int i = 0; i < NUM_GENERATIONS; ++i) { - gc_list_merge(GEN_HEAD(gcstate, i), &gcstate->permanent_generation.head); - gcstate->generations[i].count = 0; - } + PyInterpreterState *interp = _PyInterpreterState_GET(); + _PyGC_Freeze(interp); Py_RETURN_NONE; } @@ -1967,9 +431,8 @@ static PyObject * gc_unfreeze_impl(PyObject *module) /*[clinic end generated code: output=1c15f2043b25e169 input=2dd52b170f4cef6c]*/ { - GCState *gcstate = get_gc_state(); - gc_list_merge(&gcstate->permanent_generation.head, - GEN_HEAD(gcstate, NUM_GENERATIONS-1)); + PyInterpreterState *interp = _PyInterpreterState_GET(); + _PyGC_Unfreeze(interp); Py_RETURN_NONE; } @@ -1983,8 +446,8 @@ static Py_ssize_t gc_get_freeze_count_impl(PyObject *module) /*[clinic end generated code: output=61cbd9f43aa032e1 input=45ffbc65cfe2a6ed]*/ { - GCState *gcstate = get_gc_state(); - return gc_list_size(&gcstate->permanent_generation.head); + PyInterpreterState *interp = _PyInterpreterState_GET(); + return _PyGC_GetFreezeCount(interp); } @@ -2017,17 +480,15 @@ static PyMethodDef GcMethods[] = { GC_SET_DEBUG_METHODDEF GC_GET_DEBUG_METHODDEF GC_GET_COUNT_METHODDEF - {"set_threshold", gc_set_threshold, METH_VARARGS, gc_set_thresh__doc__}, + GC_SET_THRESHOLD_METHODDEF GC_GET_THRESHOLD_METHODDEF GC_COLLECT_METHODDEF GC_GET_OBJECTS_METHODDEF GC_GET_STATS_METHODDEF GC_IS_TRACKED_METHODDEF GC_IS_FINALIZED_METHODDEF - {"get_referrers", gc_get_referrers, METH_VARARGS, - gc_get_referrers__doc__}, - {"get_referents", gc_get_referents, METH_VARARGS, - gc_get_referents__doc__}, + GC_GET_REFERRERS_METHODDEF + GC_GET_REFERENTS_METHODDEF GC_FREEZE_METHODDEF GC_UNFREEZE_METHODDEF GC_GET_FREEZE_COUNT_METHODDEF @@ -2050,7 +511,7 @@ gcmodule_exec(PyObject *module) return -1; } -#define ADD_INT(NAME) if (PyModule_AddIntConstant(module, #NAME, NAME) < 0) { return -1; } +#define ADD_INT(NAME) if (PyModule_AddIntConstant(module, #NAME, _PyGC_ ## NAME) < 0) { return -1; } ADD_INT(DEBUG_STATS); ADD_INT(DEBUG_COLLECTABLE); ADD_INT(DEBUG_UNCOLLECTABLE); @@ -2080,379 +541,3 @@ PyInit_gc(void) { return PyModuleDef_Init(&gcmodule); } - -/* C API for controlling the state of the garbage collector */ -int -PyGC_Enable(void) -{ - GCState *gcstate = get_gc_state(); - int old_state = gcstate->enabled; - gcstate->enabled = 1; - return old_state; -} - -int -PyGC_Disable(void) -{ - GCState *gcstate = get_gc_state(); - int old_state = gcstate->enabled; - gcstate->enabled = 0; - return old_state; -} - -int -PyGC_IsEnabled(void) -{ - GCState *gcstate = get_gc_state(); - return gcstate->enabled; -} - -/* Public API to invoke gc.collect() from C */ -Py_ssize_t -PyGC_Collect(void) -{ - PyThreadState *tstate = _PyThreadState_GET(); - GCState *gcstate = &tstate->interp->gc; - - if (!gcstate->enabled) { - return 0; - } - - Py_ssize_t n; - if (gcstate->collecting) { - /* already collecting, don't do anything */ - n = 0; - } - else { - gcstate->collecting = 1; - PyObject *exc = _PyErr_GetRaisedException(tstate); - n = gc_collect_with_callback(tstate, NUM_GENERATIONS - 1); - _PyErr_SetRaisedException(tstate, exc); - gcstate->collecting = 0; - } - - return n; -} - -Py_ssize_t -_PyGC_CollectNoFail(PyThreadState *tstate) -{ - /* Ideally, this function is only called on interpreter shutdown, - and therefore not recursively. Unfortunately, when there are daemon - threads, a daemon thread can start a cyclic garbage collection - during interpreter shutdown (and then never finish it). - See http://bugs.python.org/issue8713#msg195178 for an example. - */ - GCState *gcstate = &tstate->interp->gc; - if (gcstate->collecting) { - return 0; - } - - Py_ssize_t n; - gcstate->collecting = 1; - n = gc_collect_main(tstate, NUM_GENERATIONS - 1, NULL, NULL, 1); - gcstate->collecting = 0; - return n; -} - -void -_PyGC_DumpShutdownStats(PyInterpreterState *interp) -{ - GCState *gcstate = &interp->gc; - if (!(gcstate->debug & DEBUG_SAVEALL) - && gcstate->garbage != NULL && PyList_GET_SIZE(gcstate->garbage) > 0) { - const char *message; - if (gcstate->debug & DEBUG_UNCOLLECTABLE) - message = "gc: %zd uncollectable objects at " \ - "shutdown"; - else - message = "gc: %zd uncollectable objects at " \ - "shutdown; use gc.set_debug(gc.DEBUG_UNCOLLECTABLE) to list them"; - /* PyErr_WarnFormat does too many things and we are at shutdown, - the warnings module's dependencies (e.g. linecache) may be gone - already. */ - if (PyErr_WarnExplicitFormat(PyExc_ResourceWarning, "gc", 0, - "gc", NULL, message, - PyList_GET_SIZE(gcstate->garbage))) - PyErr_WriteUnraisable(NULL); - if (gcstate->debug & DEBUG_UNCOLLECTABLE) { - PyObject *repr = NULL, *bytes = NULL; - repr = PyObject_Repr(gcstate->garbage); - if (!repr || !(bytes = PyUnicode_EncodeFSDefault(repr))) - PyErr_WriteUnraisable(gcstate->garbage); - else { - PySys_WriteStderr( - " %s\n", - PyBytes_AS_STRING(bytes) - ); - } - Py_XDECREF(repr); - Py_XDECREF(bytes); - } - } -} - - -void -_PyGC_Fini(PyInterpreterState *interp) -{ - GCState *gcstate = &interp->gc; - Py_CLEAR(gcstate->garbage); - Py_CLEAR(gcstate->callbacks); - - /* We expect that none of this interpreters objects are shared - with other interpreters. - See https://github.com/python/cpython/issues/90228. */ -} - -/* for debugging */ -void -_PyGC_Dump(PyGC_Head *g) -{ - _PyObject_Dump(FROM_GC(g)); -} - - -#ifdef Py_DEBUG -static int -visit_validate(PyObject *op, void *parent_raw) -{ - PyObject *parent = _PyObject_CAST(parent_raw); - if (_PyObject_IsFreed(op)) { - _PyObject_ASSERT_FAILED_MSG(parent, - "PyObject_GC_Track() object is not valid"); - } - return 0; -} -#endif - - -/* extension modules might be compiled with GC support so these - functions must always be available */ - -void -PyObject_GC_Track(void *op_raw) -{ - PyObject *op = _PyObject_CAST(op_raw); - if (_PyObject_GC_IS_TRACKED(op)) { - _PyObject_ASSERT_FAILED_MSG(op, - "object already tracked " - "by the garbage collector"); - } - _PyObject_GC_TRACK(op); - -#ifdef Py_DEBUG - /* Check that the object is valid: validate objects traversed - by tp_traverse() */ - traverseproc traverse = Py_TYPE(op)->tp_traverse; - (void)traverse(op, visit_validate, op); -#endif -} - -void -PyObject_GC_UnTrack(void *op_raw) -{ - PyObject *op = _PyObject_CAST(op_raw); - /* Obscure: the Py_TRASHCAN mechanism requires that we be able to - * call PyObject_GC_UnTrack twice on an object. - */ - if (_PyObject_GC_IS_TRACKED(op)) { - _PyObject_GC_UNTRACK(op); - } -} - -int -PyObject_IS_GC(PyObject *obj) -{ - return _PyObject_IS_GC(obj); -} - -void -_Py_ScheduleGC(PyInterpreterState *interp) -{ - GCState *gcstate = &interp->gc; - if (gcstate->collecting == 1) { - return; - } - struct _ceval_state *ceval = &interp->ceval; - if (!_Py_atomic_load_relaxed(&ceval->gc_scheduled)) { - _Py_atomic_store_relaxed(&ceval->gc_scheduled, 1); - _Py_atomic_store_relaxed(&ceval->eval_breaker, 1); - } -} - -void -_PyObject_GC_Link(PyObject *op) -{ - PyGC_Head *g = AS_GC(op); - assert(((uintptr_t)g & (sizeof(uintptr_t)-1)) == 0); // g must be correctly aligned - - PyThreadState *tstate = _PyThreadState_GET(); - GCState *gcstate = &tstate->interp->gc; - g->_gc_next = 0; - g->_gc_prev = 0; - gcstate->generations[0].count++; /* number of allocated GC objects */ - if (gcstate->generations[0].count > gcstate->generations[0].threshold && - gcstate->enabled && - gcstate->generations[0].threshold && - !gcstate->collecting && - !_PyErr_Occurred(tstate)) - { - _Py_ScheduleGC(tstate->interp); - } -} - -void -_Py_RunGC(PyThreadState *tstate) -{ - GCState *gcstate = &tstate->interp->gc; - gcstate->collecting = 1; - gc_collect_generations(tstate); - gcstate->collecting = 0; -} - -static PyObject * -gc_alloc(size_t basicsize, size_t presize) -{ - PyThreadState *tstate = _PyThreadState_GET(); - if (basicsize > PY_SSIZE_T_MAX - presize) { - return _PyErr_NoMemory(tstate); - } - size_t size = presize + basicsize; - char *mem = PyObject_Malloc(size); - if (mem == NULL) { - return _PyErr_NoMemory(tstate); - } - ((PyObject **)mem)[0] = NULL; - ((PyObject **)mem)[1] = NULL; - PyObject *op = (PyObject *)(mem + presize); - _PyObject_GC_Link(op); - return op; -} - -PyObject * -_PyObject_GC_New(PyTypeObject *tp) -{ - size_t presize = _PyType_PreHeaderSize(tp); - PyObject *op = gc_alloc(_PyObject_SIZE(tp), presize); - if (op == NULL) { - return NULL; - } - _PyObject_Init(op, tp); - return op; -} - -PyVarObject * -_PyObject_GC_NewVar(PyTypeObject *tp, Py_ssize_t nitems) -{ - PyVarObject *op; - - if (nitems < 0) { - PyErr_BadInternalCall(); - return NULL; - } - size_t presize = _PyType_PreHeaderSize(tp); - size_t size = _PyObject_VAR_SIZE(tp, nitems); - op = (PyVarObject *)gc_alloc(size, presize); - if (op == NULL) { - return NULL; - } - _PyObject_InitVar(op, tp, nitems); - return op; -} - -PyObject * -PyUnstable_Object_GC_NewWithExtraData(PyTypeObject *tp, size_t extra_size) -{ - size_t presize = _PyType_PreHeaderSize(tp); - PyObject *op = gc_alloc(_PyObject_SIZE(tp) + extra_size, presize); - if (op == NULL) { - return NULL; - } - memset(op, 0, _PyObject_SIZE(tp) + extra_size); - _PyObject_Init(op, tp); - return op; -} - -PyVarObject * -_PyObject_GC_Resize(PyVarObject *op, Py_ssize_t nitems) -{ - const size_t basicsize = _PyObject_VAR_SIZE(Py_TYPE(op), nitems); - const size_t presize = _PyType_PreHeaderSize(((PyObject *)op)->ob_type); - _PyObject_ASSERT((PyObject *)op, !_PyObject_GC_IS_TRACKED(op)); - if (basicsize > (size_t)PY_SSIZE_T_MAX - presize) { - return (PyVarObject *)PyErr_NoMemory(); - } - char *mem = (char *)op - presize; - mem = (char *)PyObject_Realloc(mem, presize + basicsize); - if (mem == NULL) { - return (PyVarObject *)PyErr_NoMemory(); - } - op = (PyVarObject *) (mem + presize); - Py_SET_SIZE(op, nitems); - return op; -} - -void -PyObject_GC_Del(void *op) -{ - size_t presize = _PyType_PreHeaderSize(((PyObject *)op)->ob_type); - PyGC_Head *g = AS_GC(op); - if (_PyObject_GC_IS_TRACKED(op)) { -#ifdef Py_DEBUG - if (PyErr_WarnExplicitFormat(PyExc_ResourceWarning, "gc", 0, - "gc", NULL, "Object of type %s is not untracked before destruction", - ((PyObject*)op)->ob_type->tp_name)) { - PyErr_WriteUnraisable(NULL); - } -#endif - gc_list_remove(g); - } - GCState *gcstate = get_gc_state(); - if (gcstate->generations[0].count > 0) { - gcstate->generations[0].count--; - } - PyObject_Free(((char *)op)-presize); -} - -int -PyObject_GC_IsTracked(PyObject* obj) -{ - if (_PyObject_IS_GC(obj) && _PyObject_GC_IS_TRACKED(obj)) { - return 1; - } - return 0; -} - -int -PyObject_GC_IsFinalized(PyObject *obj) -{ - if (_PyObject_IS_GC(obj) && _PyGC_FINALIZED(obj)) { - return 1; - } - return 0; -} - -void -PyUnstable_GC_VisitObjects(gcvisitobjects_t callback, void *arg) -{ - size_t i; - GCState *gcstate = get_gc_state(); - int origenstate = gcstate->enabled; - gcstate->enabled = 0; - for (i = 0; i < NUM_GENERATIONS; i++) { - PyGC_Head *gc_list, *gc; - gc_list = GEN_HEAD(gcstate, i); - for (gc = GC_NEXT(gc_list); gc != gc_list; gc = GC_NEXT(gc)) { - PyObject *op = FROM_GC(gc); - Py_INCREF(op); - int res = callback(op, arg); - Py_DECREF(op); - if (!res) { - goto done; - } - } - } -done: - gcstate->enabled = origenstate; -} diff --git a/Modules/getaddrinfo.c b/Modules/getaddrinfo.c index f1c28d7d9312ac..6fb6062a6520d9 100644 --- a/Modules/getaddrinfo.c +++ b/Modules/getaddrinfo.c @@ -51,7 +51,6 @@ #include #include #include -#include #include #include "addrinfo.h" @@ -228,8 +227,9 @@ str_isnumber(const char *p) { unsigned char *q = (unsigned char *)p; while (*q) { - if (! isdigit(*q)) + if (!Py_ISDIGIT(*q)) { return NO; + } q++; } return YES; diff --git a/Modules/getpath.c b/Modules/getpath.c index 76e3c7e65249f4..a3c8fc269d1c3c 100644 --- a/Modules/getpath.c +++ b/Modules/getpath.c @@ -5,6 +5,7 @@ #include "pycore_initconfig.h" // _PyStatus_EXCEPTION() #include "pycore_pathconfig.h" // _PyPathConfig_ReadGlobal() #include "pycore_pymem.h" // _PyMem_RawWcsdup() +#include "pycore_pystate.h" // _PyThreadState_GET() #include "marshal.h" // PyMarshal_ReadObjectFromString #include "osdefs.h" // DELIM @@ -16,11 +17,12 @@ #endif #ifdef __APPLE__ +# include # include #endif /* Reference the precompiled getpath.py */ -#include "../Python/frozen_modules/getpath.h" +#include "Python/frozen_modules/getpath.h" #if (!defined(PREFIX) || !defined(EXEC_PREFIX) \ || !defined(VERSION) || !defined(VPATH) \ @@ -342,11 +344,12 @@ getpath_readlines(PyObject *Py_UNUSED(self), PyObject *args) return NULL; } FILE *fp = _Py_wfopen(path, L"rb"); - PyMem_Free((void *)path); if (!fp) { PyErr_SetFromErrno(PyExc_OSError); + PyMem_Free((void *)path); return NULL; } + PyMem_Free((void *)path); r = PyList_New(0); if (!r) { @@ -499,6 +502,54 @@ getpath_realpath(PyObject *Py_UNUSED(self) , PyObject *args) PyMem_Free((void *)path); PyMem_Free((void *)narrow); return r; +#elif defined(MS_WINDOWS) + HANDLE hFile; + wchar_t resolved[MAXPATHLEN+1]; + int len = 0, err; + Py_ssize_t pathlen; + PyObject *result; + + wchar_t *path = PyUnicode_AsWideCharString(pathobj, &pathlen); + if (!path) { + return NULL; + } + if (wcslen(path) != pathlen) { + PyErr_SetString(PyExc_ValueError, "path contains embedded nulls"); + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + hFile = CreateFileW(path, 0, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); + if (hFile != INVALID_HANDLE_VALUE) { + len = GetFinalPathNameByHandleW(hFile, resolved, MAXPATHLEN, VOLUME_NAME_DOS); + err = len ? 0 : GetLastError(); + CloseHandle(hFile); + } else { + err = GetLastError(); + } + Py_END_ALLOW_THREADS + + if (err) { + PyErr_SetFromWindowsErr(err); + result = NULL; + } else if (len <= MAXPATHLEN) { + const wchar_t *p = resolved; + if (0 == wcsncmp(p, L"\\\\?\\", 4)) { + if (GetFileAttributesW(&p[4]) != INVALID_FILE_ATTRIBUTES) { + p += 4; + len -= 4; + } + } + if (CompareStringOrdinal(path, (int)pathlen, p, len, TRUE) == CSTR_EQUAL) { + result = Py_NewRef(pathobj); + } else { + result = PyUnicode_FromWideChar(p, len); + } + } else { + result = Py_NewRef(pathobj); + } + PyMem_Free(path); + return result; #endif return Py_NewRef(pathobj); @@ -766,16 +817,11 @@ library_to_dict(PyObject *dict, const char *key) which is in the framework, not relative to the executable, which may be outside of the framework. Except when we're in the build directory... */ - NSSymbol symbol = NSLookupAndBindSymbol("_Py_Initialize"); - if (symbol != NULL) { - NSModule pythonModule = NSModuleForSymbol(symbol); - if (pythonModule != NULL) { - /* Use dylib functions to find out where the framework was loaded from */ - const char *path = NSLibraryNameForModule(pythonModule); - if (path) { - strncpy(modPath, path, MAXPATHLEN); - modPathInitialized = 1; - } + Dl_info pythonInfo; + if (dladdr(&Py_Initialize, &pythonInfo)) { + if (pythonInfo.dli_fname) { + strncpy(modPath, pythonInfo.dli_fname, MAXPATHLEN); + modPathInitialized = 1; } } } @@ -819,7 +865,7 @@ _PyConfig_InitPathConfig(PyConfig *config, int compute_path_config) return status; } - if (!_PyThreadState_UncheckedGet()) { + if (!_PyThreadState_GET()) { return PyStatus_Error("cannot calculate path configuration without GIL"); } @@ -908,7 +954,7 @@ _PyConfig_InitPathConfig(PyConfig *config, int compute_path_config) ) { Py_DECREF(co); Py_DECREF(dict); - _PyErr_WriteUnraisableMsg("error evaluating initial values", NULL); + PyErr_FormatUnraisable("Exception ignored in preparing getpath"); return PyStatus_Error("error evaluating initial values"); } @@ -917,30 +963,13 @@ _PyConfig_InitPathConfig(PyConfig *config, int compute_path_config) if (!r) { Py_DECREF(dict); - _PyErr_WriteUnraisableMsg("error evaluating path", NULL); + PyErr_FormatUnraisable("Exception ignored in running getpath"); return PyStatus_Error("error evaluating path"); } Py_DECREF(r); -#if 0 - PyObject *it = PyObject_GetIter(configDict); - for (PyObject *k = PyIter_Next(it); k; k = PyIter_Next(it)) { - if (!strcmp("__builtins__", PyUnicode_AsUTF8(k))) { - Py_DECREF(k); - continue; - } - fprintf(stderr, "%s = ", PyUnicode_AsUTF8(k)); - PyObject *o = PyDict_GetItem(configDict, k); - o = PyObject_Repr(o); - fprintf(stderr, "%s\n", PyUnicode_AsUTF8(o)); - Py_DECREF(o); - Py_DECREF(k); - } - Py_DECREF(it); -#endif - if (_PyConfig_FromDict(config, configDict) < 0) { - _PyErr_WriteUnraisableMsg("reading getpath results", NULL); + PyErr_FormatUnraisable("Exception ignored in reading getpath results"); Py_DECREF(dict); return PyStatus_Error("error getting getpath results"); } @@ -949,4 +978,3 @@ _PyConfig_InitPathConfig(PyConfig *config, int compute_path_config) return _PyStatus_OK(); } - diff --git a/Modules/getpath.py b/Modules/getpath.py index 9913fcba497d30..1410ffdbed8c70 100644 --- a/Modules/getpath.py +++ b/Modules/getpath.py @@ -229,17 +229,16 @@ def search_up(prefix, *landmarks, test=isfile): pythonpath = config.get('module_search_paths') pythonpath_was_set = config.get('module_search_paths_set') +stdlib_dir = config.get('stdlib_dir') +stdlib_dir_was_set_in_config = bool(stdlib_dir) real_executable_dir = None -stdlib_dir = None platstdlib_dir = None # ****************************************************************************** # CALCULATE program_name # ****************************************************************************** -program_name_was_set = bool(program_name) - if not program_name: try: program_name = config.get('orig_argv', [])[0] @@ -509,11 +508,12 @@ def search_up(prefix, *landmarks, test=isfile): build_stdlib_prefix = build_prefix else: build_stdlib_prefix = search_up(build_prefix, *BUILDSTDLIB_LANDMARKS) - # Always use the build prefix for stdlib - if build_stdlib_prefix: - stdlib_dir = joinpath(build_stdlib_prefix, 'Lib') - else: - stdlib_dir = joinpath(build_prefix, 'Lib') + # Use the build prefix for stdlib when not explicitly set + if not stdlib_dir_was_set_in_config: + if build_stdlib_prefix: + stdlib_dir = joinpath(build_stdlib_prefix, 'Lib') + else: + stdlib_dir = joinpath(build_prefix, 'Lib') # Only use the build prefix for prefix if it hasn't already been set if not prefix: prefix = build_stdlib_prefix @@ -545,8 +545,9 @@ def search_up(prefix, *landmarks, test=isfile): prefix, had_delim, exec_prefix = home.partition(DELIM) if not had_delim: exec_prefix = prefix - # Reset the standard library directory if it was already set - stdlib_dir = None + # Reset the standard library directory if it was not explicitly set + if not stdlib_dir_was_set_in_config: + stdlib_dir = None # First try to detect prefix by looking alongside our runtime library, if known @@ -562,7 +563,8 @@ def search_up(prefix, *landmarks, test=isfile): if STDLIB_SUBDIR and STDLIB_LANDMARKS and not prefix: if any(isfile(joinpath(library_dir, f)) for f in STDLIB_LANDMARKS): prefix = library_dir - stdlib_dir = joinpath(prefix, STDLIB_SUBDIR) + if not stdlib_dir_was_set_in_config: + stdlib_dir = joinpath(prefix, STDLIB_SUBDIR) # Detect prefix by looking for zip file @@ -573,7 +575,7 @@ def search_up(prefix, *landmarks, test=isfile): prefix = executable_dir else: prefix = search_up(executable_dir, ZIP_LANDMARK) - if prefix: + if prefix and not stdlib_dir_was_set_in_config: stdlib_dir = joinpath(prefix, STDLIB_SUBDIR) if not isdir(stdlib_dir): stdlib_dir = None diff --git a/Modules/grpmodule.c b/Modules/grpmodule.c index f5709296334a8f..9756f1c2fb15b1 100644 --- a/Modules/grpmodule.c +++ b/Modules/grpmodule.c @@ -1,10 +1,16 @@ /* UNIX group file access module */ +// clinic/grpmodule.c.h uses internal pycore_modsupport.h API +#ifndef Py_BUILD_CORE_BUILTIN +# define Py_BUILD_CORE_MODULE 1 +#endif + #include "Python.h" #include "posixmodule.h" -#include +#include // getgrgid_r() +#include // sysconf() #include "clinic/grpmodule.c.h" /*[clinic input] diff --git a/Modules/hashlib.h b/Modules/hashlib.h index a8bad9dd87a939..7105e68af7b806 100644 --- a/Modules/hashlib.h +++ b/Modules/hashlib.h @@ -1,5 +1,7 @@ /* Common code for use by all hashlib related modules. */ +#include "pycore_lock.h" // PyMutex + /* * Given a PyObject* obj, fill in the Py_buffer* viewp with the result * of PyObject_GetBuffer. Sets an exception and issues the erraction @@ -48,18 +50,28 @@ #include "pythread.h" #define ENTER_HASHLIB(obj) \ - if ((obj)->lock) { \ - if (!PyThread_acquire_lock((obj)->lock, 0)) { \ - Py_BEGIN_ALLOW_THREADS \ - PyThread_acquire_lock((obj)->lock, 1); \ - Py_END_ALLOW_THREADS \ - } \ + if ((obj)->use_mutex) { \ + PyMutex_Lock(&(obj)->mutex); \ } #define LEAVE_HASHLIB(obj) \ - if ((obj)->lock) { \ - PyThread_release_lock((obj)->lock); \ + if ((obj)->use_mutex) { \ + PyMutex_Unlock(&(obj)->mutex); \ } +#ifdef Py_GIL_DISABLED +#define HASHLIB_INIT_MUTEX(obj) \ + do { \ + (obj)->mutex = (PyMutex){0}; \ + (obj)->use_mutex = true; \ + } while (0) +#else +#define HASHLIB_INIT_MUTEX(obj) \ + do { \ + (obj)->mutex = (PyMutex){0}; \ + (obj)->use_mutex = false; \ + } while (0) +#endif + /* TODO(gpshead): We should make this a module or class attribute * to allow the user to optimize based on the platform they're using. */ #define HASHLIB_GIL_MINSIZE 2048 diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c index 0ab6d330e87793..164741495c7baf 100644 --- a/Modules/itertoolsmodule.c +++ b/Modules/itertoolsmodule.c @@ -1,5 +1,6 @@ #include "Python.h" #include "pycore_call.h" // _PyObject_CallNoArgs() +#include "pycore_ceval.h" // _PyEval_GetBuiltin() #include "pycore_long.h" // _PyLong_GetZero() #include "pycore_moduleobject.h" // _PyModule_GetState() #include "pycore_typeobject.h" // _PyType_GetModuleState() @@ -104,20 +105,11 @@ class itertools.pairwise "pairwiseobject *" "clinic_state()->pairwise_type" /* batched object ************************************************************/ -/* Note: The built-in zip() function includes a "strict" argument - that was needed because that function would silently truncate data, - and there was no easy way for a user to detect the data loss. - The same reasoning does not apply to batched() which never drops data. - Instead, batched() produces a shorter tuple which can be handled - as the user sees fit. If requested, it would be reasonable to add - "fillvalue" support which had demonstrated value in zip_longest(). - For now, the API is kept simple and clean. - */ - typedef struct { PyObject_HEAD PyObject *it; Py_ssize_t batch_size; + bool strict; } batchedobject; /*[clinic input] @@ -125,6 +117,9 @@ typedef struct { itertools.batched.__new__ as batched_new iterable: object n: Py_ssize_t + * + strict: bool = False + Batch data into tuples of length n. The last batch may be shorter than n. Loops over the input iterable and accumulates data into tuples @@ -139,11 +134,15 @@ or when the input iterable is exhausted. ('D', 'E', 'F') ('G',) +If "strict" is True, raises a ValueError if the final batch is shorter +than n. + [clinic start generated code]*/ static PyObject * -batched_new_impl(PyTypeObject *type, PyObject *iterable, Py_ssize_t n) -/*[clinic end generated code: output=7ebc954d655371b6 input=ffd70726927c5129]*/ +batched_new_impl(PyTypeObject *type, PyObject *iterable, Py_ssize_t n, + int strict) +/*[clinic end generated code: output=c6de11b061529d3e input=7814b47e222f5467]*/ { PyObject *it; batchedobject *bo; @@ -169,6 +168,7 @@ batched_new_impl(PyTypeObject *type, PyObject *iterable, Py_ssize_t n) } bo->batch_size = n; bo->it = it; + bo->strict = (bool) strict; return (PyObject *)bo; } @@ -232,6 +232,12 @@ batched_next(batchedobject *bo) Py_DECREF(result); return NULL; } + if (bo->strict) { + Py_CLEAR(bo->it); + Py_DECREF(result); + PyErr_SetString(PyExc_ValueError, "batched(): incomplete batch"); + return NULL; + } _PyTuple_Resize(&result, i); return result; } @@ -329,21 +335,30 @@ pairwise_next(pairwiseobject *po) return NULL; } if (old == NULL) { - po->old = old = (*Py_TYPE(it)->tp_iternext)(it); + old = (*Py_TYPE(it)->tp_iternext)(it); + Py_XSETREF(po->old, old); if (old == NULL) { Py_CLEAR(po->it); return NULL; } + it = po->it; + if (it == NULL) { + Py_CLEAR(po->old); + return NULL; + } } + Py_INCREF(old); new = (*Py_TYPE(it)->tp_iternext)(it); if (new == NULL) { Py_CLEAR(po->it); Py_CLEAR(po->old); + Py_DECREF(old); return NULL; } /* Future optimization: Reuse the result tuple as we do in enumerate() */ result = PyTuple_Pack(2, old, new); - Py_SETREF(po->old, new); + Py_XSETREF(po->old, new); + Py_DECREF(old); return result; } diff --git a/Modules/main.c b/Modules/main.c index a5c009321d607f..df2ce550245088 100644 --- a/Modules/main.c +++ b/Modules/main.c @@ -7,6 +7,7 @@ #include "pycore_pathconfig.h" // _PyPathConfig_ComputeSysPath0() #include "pycore_pylifecycle.h" // _Py_PreInitializeFromPyArgv() #include "pycore_pystate.h" // _PyInterpreterState_GET() +#include "pycore_pythonrun.h" // _PyRun_AnyFileObject() /* Includes for exit_sigint() */ #include // perror() @@ -25,10 +26,6 @@ "Type \"help\", \"copyright\", \"credits\" or \"license\" " \ "for more information." -#ifdef __cplusplus -extern "C" { -#endif - /* --- pymain_init() ---------------------------------------------- */ static PyStatus @@ -252,7 +249,7 @@ pymain_run_command(wchar_t *command) PyCompilerFlags cf = _PyCompilerFlags_INIT; cf.cf_flags |= PyCF_IGNORE_COOKIE; - ret = PyRun_SimpleStringFlags(PyBytes_AsString(bytes), &cf); + ret = _PyRun_SimpleStringFlagsWithName(PyBytes_AsString(bytes), "", &cf); Py_DECREF(bytes); return (ret != 0); @@ -559,6 +556,11 @@ pymain_run_python(int *exitcode) goto error; } + // XXX Calculate config->sys_path_0 in getpath.py. + // The tricky part is that we can't check the path importers yet + // at that point. + assert(config->sys_path_0 == NULL); + if (config->run_filename != NULL) { /* If filename is a package (ex: directory or ZIP file) which contains __main__.py, main_importer_path is set to filename and will be @@ -574,29 +576,45 @@ pymain_run_python(int *exitcode) // import readline and rlcompleter before script dir is added to sys.path pymain_import_readline(config); + PyObject *path0 = NULL; if (main_importer_path != NULL) { - if (pymain_sys_path_add_path0(interp, main_importer_path) < 0) { - goto error; - } + path0 = Py_NewRef(main_importer_path); } else if (!config->safe_path) { - PyObject *path0 = NULL; int res = _PyPathConfig_ComputeSysPath0(&config->argv, &path0); if (res < 0) { goto error; } - - if (res > 0) { - if (pymain_sys_path_add_path0(interp, path0) < 0) { - Py_DECREF(path0); - goto error; - } + else if (res == 0) { + Py_CLEAR(path0); + } + } + // XXX Apply config->sys_path_0 in init_interp_main(). We have + // to be sure to get readline/rlcompleter imported at the correct time. + if (path0 != NULL) { + wchar_t *wstr = PyUnicode_AsWideCharString(path0, NULL); + if (wstr == NULL) { + Py_DECREF(path0); + goto error; + } + config->sys_path_0 = _PyMem_RawWcsdup(wstr); + PyMem_Free(wstr); + if (config->sys_path_0 == NULL) { Py_DECREF(path0); + goto error; + } + int res = pymain_sys_path_add_path0(interp, path0); + Py_DECREF(path0); + if (res < 0) { + goto error; } } pymain_header(config); + _PyInterpreterState_SetRunningMain(interp); + assert(!PyErr_Occurred()); + if (config->run_command) { *exitcode = pymain_run_command(config->run_command); } @@ -620,6 +638,7 @@ pymain_run_python(int *exitcode) *exitcode = pymain_exit_err_print(); done: + _PyInterpreterState_SetNotRunningMain(interp); Py_XDECREF(main_importer_path); } @@ -741,7 +760,3 @@ Py_BytesMain(int argc, char **argv) .wchar_argv = NULL}; return pymain_main(&args); } - -#ifdef __cplusplus -} -#endif diff --git a/Modules/mathmodule.c b/Modules/mathmodule.c index 0d238c086ac78f..2a796c1c55d2f0 100644 --- a/Modules/mathmodule.c +++ b/Modules/mathmodule.c @@ -57,6 +57,7 @@ raised for division by zero and mod by zero. #endif #include "Python.h" +#include "pycore_abstract.h" // _PyNumber_Index() #include "pycore_bitutils.h" // _Py_bit_length() #include "pycore_call.h" // _PyObject_CallNoArgs() #include "pycore_long.h" // _PyLong_GetZero() @@ -758,13 +759,17 @@ m_log10(double x) static PyObject * math_gcd(PyObject *module, PyObject * const *args, Py_ssize_t nargs) { - PyObject *res, *x; - Py_ssize_t i; + // Fast-path for the common case: gcd(int, int) + if (nargs == 2 && PyLong_CheckExact(args[0]) && PyLong_CheckExact(args[1])) + { + return _PyLong_GCD(args[0], args[1]); + } if (nargs == 0) { return PyLong_FromLong(0); } - res = PyNumber_Index(args[0]); + + PyObject *res = PyNumber_Index(args[0]); if (res == NULL) { return NULL; } @@ -774,8 +779,8 @@ math_gcd(PyObject *module, PyObject * const *args, Py_ssize_t nargs) } PyObject *one = _PyLong_GetOne(); // borrowed ref - for (i = 1; i < nargs; i++) { - x = _PyNumber_Index(args[i]); + for (Py_ssize_t i = 1; i < nargs; i++) { + PyObject *x = _PyNumber_Index(args[i]); if (x == NULL) { Py_DECREF(res); return NULL; @@ -1124,8 +1129,12 @@ static PyObject * math_ceil(PyObject *module, PyObject *number) /*[clinic end generated code: output=6c3b8a78bc201c67 input=2725352806399cab]*/ { + double x; - if (!PyFloat_CheckExact(number)) { + if (PyFloat_CheckExact(number)) { + x = PyFloat_AS_DOUBLE(number); + } + else { math_module_state *state = get_math_module_state(module); PyObject *method = _PyObject_LookupSpecial(number, state->str___ceil__); if (method != NULL) { @@ -1135,11 +1144,10 @@ math_ceil(PyObject *module, PyObject *number) } if (PyErr_Occurred()) return NULL; + x = PyFloat_AsDouble(number); + if (x == -1.0 && PyErr_Occurred()) + return NULL; } - double x = PyFloat_AsDouble(number); - if (x == -1.0 && PyErr_Occurred()) - return NULL; - return PyLong_FromDouble(ceil(x)); } @@ -1195,8 +1203,7 @@ math_floor(PyObject *module, PyObject *number) if (PyFloat_CheckExact(number)) { x = PyFloat_AS_DOUBLE(number); } - else - { + else { math_module_state *state = get_math_module_state(module); PyObject *method = _PyObject_LookupSpecial(number, state->str___floor__); if (method != NULL) { @@ -2194,12 +2201,10 @@ math_modf_impl(PyObject *module, double x) double y; /* some platforms don't do the right thing for NaNs and infinities, so we take care of special cases directly. */ - if (!Py_IS_FINITE(x)) { - if (Py_IS_INFINITY(x)) - return Py_BuildValue("(dd)", copysign(0., x), x); - else if (Py_IS_NAN(x)) - return Py_BuildValue("(dd)", x, x); - } + if (Py_IS_INFINITY(x)) + return Py_BuildValue("(dd)", copysign(0., x), x); + else if (Py_IS_NAN(x)) + return Py_BuildValue("(dd)", x, x); errno = 0; x = modf(x, &y); @@ -2831,7 +2836,7 @@ math_sumprod_impl(PyObject *module, PyObject *p, PyObject *q) PyErr_Clear(); goto finalize_flt_path; } - } else if (q_type_float && (PyLong_CheckExact(p_i) || PyBool_Check(q_i))) { + } else if (q_type_float && (PyLong_CheckExact(p_i) || PyBool_Check(p_i))) { flt_q = PyFloat_AS_DOUBLE(q_i); flt_p = PyLong_AsDouble(p_i); if (flt_p == -1.0 && PyErr_Occurred()) { @@ -2949,7 +2954,8 @@ math_pow_impl(PyObject *module, double x, double y) else /* y < 0. */ r = odd_y ? copysign(0., x) : 0.; } - else if (Py_IS_INFINITY(y)) { + else { + assert(Py_IS_INFINITY(y)); if (fabs(x) == 1.0) r = 1.; else if (y > 0. && fabs(x) > 1.0) @@ -3479,9 +3485,7 @@ static const uint8_t factorial_trailing_zeros[] = { static PyObject * perm_comb_small(unsigned long long n, unsigned long long k, int iscomb) { - if (k == 0) { - return PyLong_FromLong(1); - } + assert(k != 0); /* For small enough n and k the result fits in the 64-bit range and can * be calculated without allocating intermediate PyLong objects. */ diff --git a/Modules/md5module.c b/Modules/md5module.c index 5463effb507de6..7d2b3275f213fd 100644 --- a/Modules/md5module.c +++ b/Modules/md5module.c @@ -15,14 +15,13 @@ */ /* MD5 objects */ + #ifndef Py_BUILD_CORE_BUILTIN # define Py_BUILD_CORE_MODULE 1 #endif #include "Python.h" #include "hashlib.h" -#include "pycore_strhex.h" // _Py_strhex() -#include "pycore_typeobject.h" // _PyType_GetModuleState() /*[clinic input] module _md5 @@ -50,8 +49,8 @@ typedef long long MD5_INT64; /* 64-bit integer */ typedef struct { PyObject_HEAD // Prevents undefined behavior via multiple threads entering the C API. - // The lock will be NULL before threaded access has been enabled. - PyThread_type_lock lock; + bool use_mutex; + PyMutex mutex; Hacl_Streaming_MD5_state *hash_state; } MD5object; @@ -74,7 +73,11 @@ static MD5object * newMD5object(MD5State * st) { MD5object *md5 = (MD5object *)PyObject_GC_New(MD5object, st->md5_type); - md5->lock = NULL; + if (!md5) { + return NULL; + } + HASHLIB_INIT_MUTEX(md5); + PyObject_GC_Track(md5); return md5; } @@ -91,10 +94,7 @@ static void MD5_dealloc(MD5object *ptr) { Hacl_Streaming_MD5_legacy_free(ptr->hash_state); - if (ptr->lock != NULL) { - PyThread_free_lock(ptr->lock); - } - PyTypeObject *tp = Py_TYPE(ptr); + PyTypeObject *tp = Py_TYPE((PyObject*)ptr); PyObject_GC_UnTrack(ptr); PyObject_GC_Del(ptr); Py_DECREF(tp); @@ -115,7 +115,7 @@ static PyObject * MD5Type_copy_impl(MD5object *self, PyTypeObject *cls) /*[clinic end generated code: output=bf055e08244bf5ee input=d89087dcfb2a8620]*/ { - MD5State *st = _PyType_GetModuleState(cls); + MD5State *st = PyType_GetModuleState(cls); MD5object *newobj; if ((newobj = newMD5object(st))==NULL) @@ -158,7 +158,16 @@ MD5Type_hexdigest_impl(MD5object *self) ENTER_HASHLIB(self); Hacl_Streaming_MD5_legacy_finish(self->hash_state, digest); LEAVE_HASHLIB(self); - return _Py_strhex((const char*)digest, MD5_DIGESTSIZE); + + const char *hexdigits = "0123456789abcdef"; + char digest_hex[MD5_DIGESTSIZE * 2]; + char *str = digest_hex; + for (size_t i=0; i < MD5_DIGESTSIZE; i++) { + unsigned char byte = digest[i]; + *str++ = hexdigits[byte >> 4]; + *str++ = hexdigits[byte & 0x0f]; + } + return PyUnicode_FromStringAndSize(digest_hex, sizeof(digest_hex)); } static void update(Hacl_Streaming_MD5_state *state, uint8_t *buf, Py_ssize_t len) { @@ -189,14 +198,14 @@ MD5Type_update(MD5object *self, PyObject *obj) GET_BUFFER_VIEW_OR_ERROUT(obj, &buf); - if (self->lock == NULL && buf.len >= HASHLIB_GIL_MINSIZE) { - self->lock = PyThread_allocate_lock(); + if (!self->use_mutex && buf.len >= HASHLIB_GIL_MINSIZE) { + self->use_mutex = true; } - if (self->lock != NULL) { + if (self->use_mutex) { Py_BEGIN_ALLOW_THREADS - PyThread_acquire_lock(self->lock, 1); + PyMutex_Lock(&self->mutex); update(self->hash_state, buf.buf, buf.len); - PyThread_release_lock(self->lock); + PyMutex_Unlock(&self->mutex); Py_END_ALLOW_THREADS } else { update(self->hash_state, buf.buf, buf.len); diff --git a/Modules/mmapmodule.c b/Modules/mmapmodule.c index 5c131570123560..d0014e3a0429e4 100644 --- a/Modules/mmapmodule.c +++ b/Modules/mmapmodule.c @@ -23,14 +23,14 @@ #endif #include +#include "pycore_abstract.h" // _Py_convert_optional_to_ssize_t() #include "pycore_bytesobject.h" // _PyBytes_Find() #include "pycore_fileutils.h" // _Py_stat_struct #include // offsetof() - -// to support MS_WINDOWS_SYSTEM OpenFileMappingA / CreateFileMappingA -// need to be replaced with OpenFileMappingW / CreateFileMappingW -#if !defined(MS_WINDOWS) || defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_GAMES) +#ifndef MS_WINDOWS +# include // close() +#endif #ifndef MS_WINDOWS #define UNIX @@ -112,7 +112,7 @@ typedef struct { #ifdef MS_WINDOWS HANDLE map_handle; HANDLE file_handle; - char * tagname; + wchar_t * tagname; #endif #ifdef UNIX @@ -167,7 +167,7 @@ mmap_object_dealloc(mmap_object *m_obj) } static PyObject * -mmap_close_method(mmap_object *self, PyObject *unused) +mmap_close_method(mmap_object *self, PyObject *Py_UNUSED(ignored)) { if (self->exports > 0) { PyErr_SetString(PyExc_BufferError, "cannot close "\ @@ -256,7 +256,7 @@ do { \ static PyObject * mmap_read_byte_method(mmap_object *self, - PyObject *unused) + PyObject *Py_UNUSED(ignored)) { CHECK_VALID(NULL); if (self->pos >= self->size) { @@ -268,7 +268,7 @@ mmap_read_byte_method(mmap_object *self, static PyObject * mmap_read_line_method(mmap_object *self, - PyObject *unused) + PyObject *Py_UNUSED(ignored)) { Py_ssize_t remaining; char *start, *eol; @@ -456,7 +456,7 @@ mmap_write_byte_method(mmap_object *self, static PyObject * mmap_size_method(mmap_object *self, - PyObject *unused) + PyObject *Py_UNUSED(ignored)) { CHECK_VALID(NULL); @@ -530,7 +530,7 @@ mmap_resize_method(mmap_object *self, CloseHandle(self->map_handle); /* if the file mapping still exists, it cannot be resized. */ if (self->tagname) { - self->map_handle = OpenFileMappingA(FILE_MAP_WRITE, FALSE, + self->map_handle = OpenFileMappingW(FILE_MAP_WRITE, FALSE, self->tagname); if (self->map_handle) { PyErr_SetFromWindowsErr(ERROR_USER_MAPPED_FILE); @@ -559,7 +559,7 @@ mmap_resize_method(mmap_object *self, /* create a new file mapping and map a new view */ /* FIXME: call CreateFileMappingW with wchar_t tagname */ - self->map_handle = CreateFileMappingA( + self->map_handle = CreateFileMappingW( self->file_handle, NULL, PAGE_READWRITE, @@ -653,7 +653,7 @@ mmap_resize_method(mmap_object *self, } static PyObject * -mmap_tell_method(mmap_object *self, PyObject *unused) +mmap_tell_method(mmap_object *self, PyObject *Py_UNUSED(ignored)) { CHECK_VALID(NULL); return PyLong_FromSize_t(self->pos); @@ -725,7 +725,7 @@ mmap_seek_method(mmap_object *self, PyObject *args) if (where > self->size || where < 0) goto onoutofrange; self->pos = where; - Py_RETURN_NONE; + return PyLong_FromSsize_t(self->pos); } onoutofrange: @@ -733,6 +733,12 @@ mmap_seek_method(mmap_object *self, PyObject *args) return NULL; } +static PyObject * +mmap_seekable_method(mmap_object *self, PyObject *Py_UNUSED(ignored)) +{ + Py_RETURN_TRUE; +} + static PyObject * mmap_move_method(mmap_object *self, PyObject *args) { @@ -831,11 +837,11 @@ mmap__repr__method(PyObject *self) #ifdef MS_WINDOWS static PyObject * -mmap__sizeof__method(mmap_object *self, void *unused) +mmap__sizeof__method(mmap_object *self, void *Py_UNUSED(ignored)) { size_t res = _PyObject_SIZE(Py_TYPE(self)); if (self->tagname) { - res += strlen(self->tagname) + 1; + res += (wcslen(self->tagname) + 1) * sizeof(self->tagname[0]); } return PyLong_FromSize_t(res); } @@ -901,6 +907,7 @@ static struct PyMethodDef mmap_object_methods[] = { {"readline", (PyCFunction) mmap_read_line_method, METH_NOARGS}, {"resize", (PyCFunction) mmap_resize_method, METH_VARARGS}, {"seek", (PyCFunction) mmap_seek_method, METH_VARARGS}, + {"seekable", (PyCFunction) mmap_seekable_method, METH_NOARGS}, {"size", (PyCFunction) mmap_size_method, METH_NOARGS}, {"tell", (PyCFunction) mmap_tell_method, METH_NOARGS}, {"write", (PyCFunction) mmap_write_method, METH_VARARGS}, @@ -1355,6 +1362,7 @@ new_mmap_object(PyTypeObject *type, PyObject *args, PyObject *kwdict) m_obj->data = mmap(NULL, map_size, prot, flags, fd, offset); Py_END_ALLOW_THREADS + int saved_errno = errno; if (devzero != -1) { close(devzero); } @@ -1362,6 +1370,7 @@ new_mmap_object(PyTypeObject *type, PyObject *args, PyObject *kwdict) if (m_obj->data == (char *)-1) { m_obj->data = NULL; Py_DECREF(m_obj); + errno = saved_errno; PyErr_SetFromErrno(PyExc_OSError); return NULL; } @@ -1387,7 +1396,7 @@ new_mmap_object(PyTypeObject *type, PyObject *args, PyObject *kwdict) DWORD off_lo; /* lower 32 bits of offset */ DWORD size_hi; /* upper 32 bits of size */ DWORD size_lo; /* lower 32 bits of size */ - const char *tagname = ""; + PyObject *tagname = Py_None; DWORD dwErr = 0; int fileno; HANDLE fh = 0; @@ -1397,7 +1406,7 @@ new_mmap_object(PyTypeObject *type, PyObject *args, PyObject *kwdict) "tagname", "access", "offset", NULL }; - if (!PyArg_ParseTupleAndKeywords(args, kwdict, "in|ziL", keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwdict, "in|OiL", keywords, &fileno, &map_size, &tagname, &access, &offset)) { return NULL; @@ -1530,17 +1539,19 @@ new_mmap_object(PyTypeObject *type, PyObject *args, PyObject *kwdict) m_obj->weakreflist = NULL; m_obj->exports = 0; /* set the tag name */ - if (tagname != NULL && *tagname != '\0') { - m_obj->tagname = PyMem_Malloc(strlen(tagname)+1); + if (!Py_IsNone(tagname)) { + if (!PyUnicode_Check(tagname)) { + Py_DECREF(m_obj); + return PyErr_Format(PyExc_TypeError, "expected str or None for " + "'tagname', not %.200s", + Py_TYPE(tagname)->tp_name); + } + m_obj->tagname = PyUnicode_AsWideCharString(tagname, NULL); if (m_obj->tagname == NULL) { - PyErr_NoMemory(); Py_DECREF(m_obj); return NULL; } - strcpy(m_obj->tagname, tagname); } - else - m_obj->tagname = NULL; m_obj->access = (access_mode)access; size_hi = (DWORD)(size >> 32); @@ -1549,7 +1560,7 @@ new_mmap_object(PyTypeObject *type, PyObject *args, PyObject *kwdict) off_lo = (DWORD)(offset & 0xFFFFFFFF); /* For files, it would be sufficient to pass 0 as size. For anonymous maps, we have to pass the size explicitly. */ - m_obj->map_handle = CreateFileMappingA(m_obj->file_handle, + m_obj->map_handle = CreateFileMappingW(m_obj->file_handle, NULL, flProtect, size_hi, @@ -1758,5 +1769,3 @@ PyInit_mmap(void) { return PyModuleDef_Init(&mmapmodule); } - -#endif /* !MS_WINDOWS || MS_WINDOWS_DESKTOP || MS_WINDOWS_GAMES */ diff --git a/Modules/overlapped.c b/Modules/overlapped.c index 271f6ce7e2d916..fd40e91d0f50c4 100644 --- a/Modules/overlapped.c +++ b/Modules/overlapped.c @@ -7,8 +7,11 @@ /* XXX check overflow and DWORD <-> Py_ssize_t conversions Check itemsize */ -#include "Python.h" +#ifndef Py_BUILD_CORE_BUILTIN +# define Py_BUILD_CORE_MODULE 1 +#endif +#include "Python.h" #define WINDOWS_LEAN_AND_MEAN #include @@ -35,13 +38,14 @@ class pointer_converter(CConverter): format_unit = '"F_POINTER"' - def parse_arg(self, argname, displayname): - return """ + def parse_arg(self, argname, displayname, *, limited_capi): + return self.format_code(""" {paramname} = PyLong_AsVoidPtr({argname}); if (!{paramname} && PyErr_Occurred()) {{{{ goto exit; }}}} - """.format(argname=argname, paramname=self.parser_name) + """, + argname=argname) class OVERLAPPED_converter(pointer_converter): type = 'OVERLAPPED *' @@ -52,13 +56,14 @@ class HANDLE_converter(pointer_converter): class ULONG_PTR_converter(pointer_converter): type = 'ULONG_PTR' - def parse_arg(self, argname, displayname): - return """ + def parse_arg(self, argname, displayname, *, limited_capi): + return self.format_code(""" {paramname} = (uintptr_t)PyLong_AsVoidPtr({argname}); if (!{paramname} && PyErr_Occurred()) {{{{ goto exit; }}}} - """.format(argname=argname, paramname=self.parser_name) + """, + argname=argname) class DWORD_converter(unsigned_long_converter): type = 'DWORD' @@ -66,7 +71,7 @@ class DWORD_converter(unsigned_long_converter): class BOOL_converter(int_converter): type = 'BOOL' [python start generated code]*/ -/*[python end generated code: output=da39a3ee5e6b4b0d input=8a07ea3018f4cec8]*/ +/*[python end generated code: output=da39a3ee5e6b4b0d input=436f4440630a304c]*/ /*[clinic input] module _overlapped @@ -367,8 +372,9 @@ _overlapped_RegisterWaitWithQueue_impl(PyObject *module, HANDLE Object, &NewWaitObject, Object, PostToQueueCallback, pdata, Milliseconds, WT_EXECUTEINWAITTHREAD | WT_EXECUTEONLYONCE)) { + SetFromWindowsErr(0); PyMem_RawFree(pdata); - return SetFromWindowsErr(0); + return NULL; } return Py_BuildValue(F_HANDLE, NewWaitObject); @@ -593,8 +599,7 @@ _overlapped_FormatMessage_impl(PyObject *module, DWORD code) if (n) { while (iswspace(lpMsgBuf[n-1])) --n; - lpMsgBuf[n] = L'\0'; - res = Py_BuildValue("u", lpMsgBuf); + res = PyUnicode_FromWideChar(lpMsgBuf, n); } else { res = PyUnicode_FromFormat("unknown error code %u", code); } diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index a42e41c081e5b7..179497a21b5a95 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -12,6 +12,7 @@ #ifdef __VXWORKS__ # include "pycore_bitutils.h" // _Py_popcount32() #endif +#include "pycore_abstract.h" // _PyNumber_Index() #include "pycore_call.h" // _PyObject_CallNoArgs() #include "pycore_ceval.h" // _PyEval_ReInitThreads() #include "pycore_fileutils.h" // _Py_closerange() @@ -23,6 +24,10 @@ #include "pycore_pystate.h" // _PyInterpreterState_GET() #include "pycore_signal.h" // Py_NSIG +#ifdef HAVE_UNISTD_H +# include // symlink() +#endif + #ifdef MS_WINDOWS # include # if !defined(MS_WINDOWS_GAMES) || defined(MS_WINDOWS_DESKTOP) @@ -36,7 +41,6 @@ # endif /* MS_WINDOWS_DESKTOP | MS_WINDOWS_SYSTEM */ #endif - #ifndef MS_WINDOWS # include "posixmodule.h" #else @@ -56,6 +60,17 @@ #include // ctermid() #include // system() +#ifdef HAVE_SYS_TIME_H +# include // futimes() +#endif + + +// SGI apparently needs this forward declaration +#ifdef HAVE__GETPTY +# include // mode_t + extern char * _getpty(int *, int, mode_t, int); +#endif + /* * A number of APIs are available on macOS from a certain macOS version. @@ -210,10 +225,6 @@ #endif -#ifdef __cplusplus -extern "C" { -#endif - PyDoc_STRVAR(posix__doc__, "This module provides access to operating system functionality that is\n\ standardized by the C Standard and the POSIX standard (a thinly\n\ @@ -225,15 +236,16 @@ corresponding Unix manual entries for more information on calls."); # include #endif +#ifdef HAVE_SYS_TYPES_H +/* Should be included before on HP-UX v3 */ +# include +#endif /* HAVE_SYS_TYPES_H */ + #ifdef HAVE_SYS_SYSMACROS_H /* GNU C Library: major(), minor(), makedev() */ # include #endif -#ifdef HAVE_SYS_TYPES_H -# include -#endif /* HAVE_SYS_TYPES_H */ - #ifdef HAVE_SYS_STAT_H # include #endif /* HAVE_SYS_STAT_H */ @@ -277,17 +289,19 @@ corresponding Unix manual entries for more information on calls."); # include #endif -#ifdef HAVE_COPY_FILE_RANGE -# include -#endif - #if !defined(CPU_ALLOC) && defined(HAVE_SCHED_SETAFFINITY) # undef HAVE_SCHED_SETAFFINITY #endif -#if defined(HAVE_SYS_XATTR_H) && defined(HAVE_LINUX_LIMITS_H) && !defined(__FreeBSD_kernel__) && !defined(__GNU__) -# define USE_XATTRS -# include // Needed for XATTR_SIZE_MAX on musl libc. +#if defined(HAVE_SYS_XATTR_H) +# if defined(HAVE_LINUX_LIMITS_H) && !defined(__FreeBSD_kernel__) && !defined(__GNU__) +# define USE_XATTRS +# include // Needed for XATTR_SIZE_MAX on musl libc. +# endif +# if defined(__CYGWIN__) +# define USE_XATTRS +# include // Needed for XATTR_SIZE_MAX and XATTR_LIST_MAX. +# endif #endif #ifdef USE_XATTRS @@ -543,6 +557,11 @@ extern char *ctermid_r(char *); # include #endif +/* timerfd_create() */ +#ifdef HAVE_SYS_TIMERFD_H +# include +#endif + #ifdef _Py_MEMORY_SANITIZER # include #endif @@ -1005,13 +1024,17 @@ typedef struct { PyObject *TerminalSizeType; PyObject *TimesResultType; PyObject *UnameResultType; -#if defined(HAVE_WAITID) && !defined(__APPLE__) +#if defined(HAVE_WAITID) PyObject *WaitidResultType; #endif #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4) PyObject *struct_rusage; #endif PyObject *st_mode; +#ifndef MS_WINDOWS + // times() clock frequency in hertz; used by os.times() + long ticks_per_second; +#endif } _posixstate; @@ -1535,6 +1558,7 @@ _Py_Sigset_Converter(PyObject *obj, void *addr) ** man environ(7). */ #include +#define USE_DARWIN_NS_GET_ENVIRON 1 #elif !defined(_MSC_VER) && (!defined(__WATCOMC__) || defined(__QNX__) || defined(__VXWORKS__)) extern char **environ; #endif /* !_MSC_VER */ @@ -1557,7 +1581,7 @@ convertenviron(void) through main() instead of wmain(). */ (void)_wgetenv(L""); e = _wenviron; -#elif defined(WITH_NEXT_FRAMEWORK) || (defined(__APPLE__) && defined(Py_ENABLE_SHARED)) +#elif defined(USE_DARWIN_NS_GET_ENVIRON) /* environ is not accessible as an extern in a shared object on OSX; use _NSGetEnviron to resolve it. The value changes if you add environment variables between calls to Py_Initialize, so don't cache the value. */ @@ -2268,7 +2292,7 @@ static PyStructSequence_Desc statvfs_result_desc = { 10 }; -#if defined(HAVE_WAITID) && !defined(__APPLE__) +#if defined(HAVE_WAITID) PyDoc_STRVAR(waitid_result__doc__, "waitid_result: Result from waitid.\n\n\ This object may be accessed either as a tuple of\n\ @@ -2343,7 +2367,7 @@ _posix_clear(PyObject *module) Py_CLEAR(state->TerminalSizeType); Py_CLEAR(state->TimesResultType); Py_CLEAR(state->UnameResultType); -#if defined(HAVE_WAITID) && !defined(__APPLE__) +#if defined(HAVE_WAITID) Py_CLEAR(state->WaitidResultType); #endif #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4) @@ -2368,7 +2392,7 @@ _posix_traverse(PyObject *module, visitproc visit, void *arg) Py_VISIT(state->TerminalSizeType); Py_VISIT(state->TimesResultType); Py_VISIT(state->UnameResultType); -#if defined(HAVE_WAITID) && !defined(__APPLE__) +#if defined(HAVE_WAITID) Py_VISIT(state->WaitidResultType); #endif #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4) @@ -2384,21 +2408,26 @@ _posix_free(void *module) _posix_clear((PyObject *)module); } -static void +static int fill_time(PyObject *module, PyObject *v, int s_index, int f_index, int ns_index, time_t sec, unsigned long nsec) { - PyObject *s = _PyLong_FromTime_t(sec); - PyObject *ns_fractional = PyLong_FromUnsignedLong(nsec); + assert(!PyErr_Occurred()); + + int res = -1; PyObject *s_in_ns = NULL; PyObject *ns_total = NULL; PyObject *float_s = NULL; - if (!(s && ns_fractional)) + PyObject *s = _PyLong_FromTime_t(sec); + PyObject *ns_fractional = PyLong_FromUnsignedLong(nsec); + if (!(s && ns_fractional)) { goto exit; + } s_in_ns = PyNumber_Multiply(s, get_posix_state(module)->billion); - if (!s_in_ns) + if (!s_in_ns) { goto exit; + } ns_total = PyNumber_Add(s_in_ns, ns_fractional); if (!ns_total) @@ -2421,12 +2450,17 @@ fill_time(PyObject *module, PyObject *v, int s_index, int f_index, int ns_index, PyStructSequence_SET_ITEM(v, ns_index, ns_total); ns_total = NULL; } + + assert(!PyErr_Occurred()); + res = 0; + exit: Py_XDECREF(s); Py_XDECREF(ns_fractional); Py_XDECREF(s_in_ns); Py_XDECREF(ns_total); Py_XDECREF(float_s); + return res; } #ifdef MS_WINDOWS @@ -2461,34 +2495,47 @@ _pystat_l128_from_l64_l64(uint64_t low, uint64_t high) static PyObject* _pystat_fromstructstat(PyObject *module, STRUCT_STAT *st) { - unsigned long ansec, mnsec, cnsec; + assert(!PyErr_Occurred()); + PyObject *StatResultType = get_posix_state(module)->StatResultType; PyObject *v = PyStructSequence_New((PyTypeObject *)StatResultType); - if (v == NULL) + if (v == NULL) { return NULL; + } + +#define SET_ITEM(pos, expr) \ + do { \ + PyObject *obj = (expr); \ + if (obj == NULL) { \ + goto error; \ + } \ + PyStructSequence_SET_ITEM(v, (pos), obj); \ + } while (0) - PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long)st->st_mode)); + SET_ITEM(0, PyLong_FromLong((long)st->st_mode)); #ifdef MS_WINDOWS - PyStructSequence_SET_ITEM(v, 1, _pystat_l128_from_l64_l64(st->st_ino, st->st_ino_high)); - PyStructSequence_SET_ITEM(v, 2, PyLong_FromUnsignedLongLong(st->st_dev)); + SET_ITEM(1, _pystat_l128_from_l64_l64(st->st_ino, st->st_ino_high)); + SET_ITEM(2, PyLong_FromUnsignedLongLong(st->st_dev)); #else static_assert(sizeof(unsigned long long) >= sizeof(st->st_ino), "stat.st_ino is larger than unsigned long long"); - PyStructSequence_SET_ITEM(v, 1, PyLong_FromUnsignedLongLong(st->st_ino)); - PyStructSequence_SET_ITEM(v, 2, _PyLong_FromDev(st->st_dev)); + SET_ITEM(1, PyLong_FromUnsignedLongLong(st->st_ino)); + SET_ITEM(2, _PyLong_FromDev(st->st_dev)); #endif - PyStructSequence_SET_ITEM(v, 3, PyLong_FromLong((long)st->st_nlink)); + SET_ITEM(3, PyLong_FromLong((long)st->st_nlink)); #if defined(MS_WINDOWS) - PyStructSequence_SET_ITEM(v, 4, PyLong_FromLong(0)); - PyStructSequence_SET_ITEM(v, 5, PyLong_FromLong(0)); + SET_ITEM(4, PyLong_FromLong(0)); + SET_ITEM(5, PyLong_FromLong(0)); #else - PyStructSequence_SET_ITEM(v, 4, _PyLong_FromUid(st->st_uid)); - PyStructSequence_SET_ITEM(v, 5, _PyLong_FromGid(st->st_gid)); + SET_ITEM(4, _PyLong_FromUid(st->st_uid)); + SET_ITEM(5, _PyLong_FromGid(st->st_gid)); #endif static_assert(sizeof(long long) >= sizeof(st->st_size), "stat.st_size is larger than long long"); - PyStructSequence_SET_ITEM(v, 6, PyLong_FromLongLong(st->st_size)); + SET_ITEM(6, PyLong_FromLongLong(st->st_size)); + // Set st_atime, st_mtime and st_ctime + unsigned long ansec, mnsec, cnsec; #if defined(HAVE_STAT_TV_NSEC) ansec = st->st_atim.tv_nsec; mnsec = st->st_mtim.tv_nsec; @@ -2504,67 +2551,67 @@ _pystat_fromstructstat(PyObject *module, STRUCT_STAT *st) #else ansec = mnsec = cnsec = 0; #endif - fill_time(module, v, 7, 10, 13, st->st_atime, ansec); - fill_time(module, v, 8, 11, 14, st->st_mtime, mnsec); - fill_time(module, v, 9, 12, 15, st->st_ctime, cnsec); + if (fill_time(module, v, 7, 10, 13, st->st_atime, ansec) < 0) { + goto error; + } + if (fill_time(module, v, 8, 11, 14, st->st_mtime, mnsec) < 0) { + goto error; + } + if (fill_time(module, v, 9, 12, 15, st->st_ctime, cnsec) < 0) { + goto error; + } #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE - PyStructSequence_SET_ITEM(v, ST_BLKSIZE_IDX, - PyLong_FromLong((long)st->st_blksize)); + SET_ITEM(ST_BLKSIZE_IDX, PyLong_FromLong((long)st->st_blksize)); #endif #ifdef HAVE_STRUCT_STAT_ST_BLOCKS - PyStructSequence_SET_ITEM(v, ST_BLOCKS_IDX, - PyLong_FromLong((long)st->st_blocks)); + SET_ITEM(ST_BLOCKS_IDX, PyLong_FromLong((long)st->st_blocks)); #endif #ifdef HAVE_STRUCT_STAT_ST_RDEV - PyStructSequence_SET_ITEM(v, ST_RDEV_IDX, - PyLong_FromLong((long)st->st_rdev)); + SET_ITEM(ST_RDEV_IDX, PyLong_FromLong((long)st->st_rdev)); #endif #ifdef HAVE_STRUCT_STAT_ST_GEN - PyStructSequence_SET_ITEM(v, ST_GEN_IDX, - PyLong_FromLong((long)st->st_gen)); + SET_ITEM(ST_GEN_IDX, PyLong_FromLong((long)st->st_gen)); #endif #if defined(HAVE_STRUCT_STAT_ST_BIRTHTIME) { - PyObject *val; - unsigned long bsec,bnsec; + unsigned long bsec, bnsec; bsec = (long)st->st_birthtime; #ifdef HAVE_STAT_TV_NSEC2 bnsec = st->st_birthtimespec.tv_nsec; #else bnsec = 0; #endif - val = PyFloat_FromDouble(bsec + 1e-9*bnsec); - PyStructSequence_SET_ITEM(v, ST_BIRTHTIME_IDX, - val); + SET_ITEM(ST_BIRTHTIME_IDX, PyFloat_FromDouble(bsec + bnsec * 1e-9)); } #elif defined(MS_WINDOWS) - fill_time(module, v, -1, ST_BIRTHTIME_IDX, ST_BIRTHTIME_NS_IDX, - st->st_birthtime, st->st_birthtime_nsec); + if (fill_time(module, v, -1, ST_BIRTHTIME_IDX, ST_BIRTHTIME_NS_IDX, + st->st_birthtime, st->st_birthtime_nsec) < 0) { + goto error; + } #endif #ifdef HAVE_STRUCT_STAT_ST_FLAGS - PyStructSequence_SET_ITEM(v, ST_FLAGS_IDX, - PyLong_FromLong((long)st->st_flags)); + SET_ITEM(ST_FLAGS_IDX, PyLong_FromLong((long)st->st_flags)); #endif #ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES - PyStructSequence_SET_ITEM(v, ST_FILE_ATTRIBUTES_IDX, - PyLong_FromUnsignedLong(st->st_file_attributes)); + SET_ITEM(ST_FILE_ATTRIBUTES_IDX, + PyLong_FromUnsignedLong(st->st_file_attributes)); #endif #ifdef HAVE_STRUCT_STAT_ST_FSTYPE - PyStructSequence_SET_ITEM(v, ST_FSTYPE_IDX, - PyUnicode_FromString(st->st_fstype)); + SET_ITEM(ST_FSTYPE_IDX, PyUnicode_FromString(st->st_fstype)); #endif #ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG - PyStructSequence_SET_ITEM(v, ST_REPARSE_TAG_IDX, - PyLong_FromUnsignedLong(st->st_reparse_tag)); + SET_ITEM(ST_REPARSE_TAG_IDX, PyLong_FromUnsignedLong(st->st_reparse_tag)); #endif - if (PyErr_Occurred()) { - Py_DECREF(v); - return NULL; - } - + assert(!PyErr_Occurred()); return v; + +error: + Py_DECREF(v); + return NULL; + +#undef SET_ITEM } /* POSIX methods */ @@ -2809,6 +2856,8 @@ FTRUNCATE #ifdef MS_WINDOWS #undef PATH_HAVE_FTRUNCATE #define PATH_HAVE_FTRUNCATE 1 + #undef PATH_HAVE_FCHMOD + #define PATH_HAVE_FCHMOD 1 #endif /*[python input] @@ -3264,6 +3313,60 @@ os_fchdir_impl(PyObject *module, int fd) } #endif /* HAVE_FCHDIR */ +#ifdef MS_WINDOWS +# define CHMOD_DEFAULT_FOLLOW_SYMLINKS 0 +#else +# define CHMOD_DEFAULT_FOLLOW_SYMLINKS 1 +#endif + +#ifdef MS_WINDOWS +static int +win32_lchmod(LPCWSTR path, int mode) +{ + DWORD attr = GetFileAttributesW(path); + if (attr == INVALID_FILE_ATTRIBUTES) { + return 0; + } + if (mode & _S_IWRITE) { + attr &= ~FILE_ATTRIBUTE_READONLY; + } + else { + attr |= FILE_ATTRIBUTE_READONLY; + } + return SetFileAttributesW(path, attr); +} + +static int +win32_hchmod(HANDLE hfile, int mode) +{ + FILE_BASIC_INFO info; + if (!GetFileInformationByHandleEx(hfile, FileBasicInfo, + &info, sizeof(info))) + { + return 0; + } + if (mode & _S_IWRITE) { + info.FileAttributes &= ~FILE_ATTRIBUTE_READONLY; + } + else { + info.FileAttributes |= FILE_ATTRIBUTE_READONLY; + } + return SetFileInformationByHandle(hfile, FileBasicInfo, + &info, sizeof(info)); +} + +static int +win32_fchmod(int fd, int mode) +{ + HANDLE hfile = _Py_get_osfhandle_noraise(fd); + if (hfile == INVALID_HANDLE_VALUE) { + SetLastError(ERROR_INVALID_HANDLE); + return 0; + } + return win32_hchmod(hfile, mode); +} + +#endif /* MS_WINDOWS */ /*[clinic input] os.chmod @@ -3286,7 +3389,8 @@ os.chmod and path should be relative; path will then be relative to that directory. - follow_symlinks: bool = True + follow_symlinks: bool(c_default="CHMOD_DEFAULT_FOLLOW_SYMLINKS", \ + py_default="(os.name != 'nt')") = CHMOD_DEFAULT_FOLLOW_SYMLINKS If False, and the last element of the path is a symbolic link, chmod will modify the symbolic link itself instead of the file the link points to. @@ -3303,20 +3407,16 @@ dir_fd and follow_symlinks may not be implemented on your platform. static PyObject * os_chmod_impl(PyObject *module, path_t *path, int mode, int dir_fd, int follow_symlinks) -/*[clinic end generated code: output=5cf6a94915cc7bff input=674a14bc998de09d]*/ +/*[clinic end generated code: output=5cf6a94915cc7bff input=fcf115d174b9f3d8]*/ { int result; -#ifdef MS_WINDOWS - DWORD attr; -#endif - #ifdef HAVE_FCHMODAT int fchmodat_nofollow_unsupported = 0; int fchmodat_unsupported = 0; #endif -#if !(defined(HAVE_FCHMODAT) || defined(HAVE_LCHMOD)) +#if !(defined(HAVE_FCHMODAT) || defined(HAVE_LCHMOD) || defined(MS_WINDOWS)) if (follow_symlinks_specified("chmod", follow_symlinks)) return NULL; #endif @@ -3327,19 +3427,25 @@ os_chmod_impl(PyObject *module, path_t *path, int mode, int dir_fd, } #ifdef MS_WINDOWS + result = 0; Py_BEGIN_ALLOW_THREADS - attr = GetFileAttributesW(path->wide); - if (attr == INVALID_FILE_ATTRIBUTES) - result = 0; + if (path->fd != -1) { + result = win32_fchmod(path->fd, mode); + } + else if (follow_symlinks) { + HANDLE hfile = CreateFileW(path->wide, + FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES, + 0, NULL, + OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); + if (hfile != INVALID_HANDLE_VALUE) { + result = win32_hchmod(hfile, mode); + (void)CloseHandle(hfile); + } + } else { - if (mode & _S_IWRITE) - attr &= ~FILE_ATTRIBUTE_READONLY; - else - attr |= FILE_ATTRIBUTE_READONLY; - result = SetFileAttributesW(path->wide, attr); + result = win32_lchmod(path->wide, mode); } Py_END_ALLOW_THREADS - if (!result) { return path_error(path); } @@ -3428,7 +3534,7 @@ os_chmod_impl(PyObject *module, path_t *path, int mode, int dir_fd, } -#ifdef HAVE_FCHMOD +#if defined(HAVE_FCHMOD) || defined(MS_WINDOWS) /*[clinic input] os.fchmod @@ -3450,12 +3556,21 @@ os_fchmod_impl(PyObject *module, int fd, int mode) /*[clinic end generated code: output=afd9bc05b4e426b3 input=b5594618bbbc22df]*/ { int res; - int async_err = 0; if (PySys_Audit("os.chmod", "iii", fd, mode, -1) < 0) { return NULL; } +#ifdef MS_WINDOWS + res = 0; + Py_BEGIN_ALLOW_THREADS + res = win32_fchmod(fd, mode); + Py_END_ALLOW_THREADS + if (!res) { + return PyErr_SetFromWindowsErr(0); + } +#else /* MS_WINDOWS */ + int async_err = 0; do { Py_BEGIN_ALLOW_THREADS res = fchmod(fd, mode); @@ -3463,13 +3578,14 @@ os_fchmod_impl(PyObject *module, int fd, int mode) } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); if (res != 0) return (!async_err) ? posix_error() : NULL; +#endif /* MS_WINDOWS */ Py_RETURN_NONE; } -#endif /* HAVE_FCHMOD */ +#endif /* HAVE_FCHMOD || MS_WINDOWS */ -#ifdef HAVE_LCHMOD +#if defined(HAVE_LCHMOD) || defined(MS_WINDOWS) /*[clinic input] os.lchmod @@ -3490,6 +3606,15 @@ os_lchmod_impl(PyObject *module, path_t *path, int mode) if (PySys_Audit("os.chmod", "Oii", path->object, mode, -1) < 0) { return NULL; } +#ifdef MS_WINDOWS + Py_BEGIN_ALLOW_THREADS + res = win32_lchmod(path->wide, mode); + Py_END_ALLOW_THREADS + if (!res) { + path_error(path); + return NULL; + } +#else /* MS_WINDOWS */ Py_BEGIN_ALLOW_THREADS res = lchmod(path->narrow, mode); Py_END_ALLOW_THREADS @@ -3497,9 +3622,10 @@ os_lchmod_impl(PyObject *module, path_t *path, int mode) path_error(path); return NULL; } +#endif /* MS_WINDOWS */ Py_RETURN_NONE; } -#endif /* HAVE_LCHMOD */ +#endif /* HAVE_LCHMOD || MS_WINDOWS */ #ifdef HAVE_CHFLAGS @@ -3876,9 +4002,10 @@ posix_getcwd(int use_bytes) return NULL; } if (!len) { + PyErr_SetFromWindowsErr(0); if (wbuf2 != wbuf) PyMem_RawFree(wbuf2); - return PyErr_SetFromWindowsErr(0); + return NULL; } PyObject *resobj = PyUnicode_FromWideChar(wbuf2, len); @@ -3926,8 +4053,9 @@ posix_getcwd(int use_bytes) return PyErr_NoMemory(); } if (cwd == NULL) { + posix_error(); PyMem_RawFree(buf); - return posix_error(); + return NULL; } PyObject *obj; @@ -4139,8 +4267,8 @@ _listdir_windows_no_opendir(path_t *path, PyObject *list) int error = GetLastError(); if (error == ERROR_FILE_NOT_FOUND) goto exit; - Py_DECREF(list); - list = path_error(path); + path_error(path); + Py_CLEAR(list); goto exit; } do { @@ -4153,12 +4281,12 @@ _listdir_windows_no_opendir(path_t *path, PyObject *list) Py_SETREF(v, PyUnicode_EncodeFSDefault(v)); } if (v == NULL) { - Py_SETREF(list, NULL); + Py_CLEAR(list); break; } if (PyList_Append(list, v) != 0) { Py_DECREF(v); - Py_SETREF(list, NULL); + Py_CLEAR(list); break; } Py_DECREF(v); @@ -4169,8 +4297,8 @@ _listdir_windows_no_opendir(path_t *path, PyObject *list) /* FindNextFile sets error to ERROR_NO_MORE_FILES if it got to the end of the directory. */ if (!result && GetLastError() != ERROR_NO_MORE_FILES) { - Py_DECREF(list); - list = path_error(path); + path_error(path); + Py_CLEAR(list); goto exit; } } while (result == TRUE); @@ -4179,8 +4307,8 @@ _listdir_windows_no_opendir(path_t *path, PyObject *list) if (hFindFile != INVALID_HANDLE_VALUE) { if (FindClose(hFindFile) == FALSE) { if (list != NULL) { - Py_DECREF(list); - list = path_error(path); + path_error(path); + Py_CLEAR(list); } } } @@ -4242,7 +4370,8 @@ _posix_listdir(path_t *path, PyObject *list) } if (dirp == NULL) { - list = path_error(path); + path_error(path); + list = NULL; #ifdef HAVE_FDOPENDIR if (fd != -1) { Py_BEGIN_ALLOW_THREADS @@ -4264,8 +4393,8 @@ _posix_listdir(path_t *path, PyObject *list) if (errno == 0) { break; } else { - Py_DECREF(list); - list = path_error(path); + path_error(path); + Py_CLEAR(list); goto exit; } } @@ -4776,6 +4905,37 @@ os__getfinalpathname_impl(PyObject *module, path_t *path) return result; } +/*[clinic input] +os._findfirstfile + path: path_t + / +A function to get the real file name without accessing the file in Windows. +[clinic start generated code]*/ + +static PyObject * +os__findfirstfile_impl(PyObject *module, path_t *path) +/*[clinic end generated code: output=106dd3f0779c83dd input=0734dff70f60e1a8]*/ +{ + PyObject *result; + HANDLE hFindFile; + WIN32_FIND_DATAW wFileData; + WCHAR *wRealFileName; + + Py_BEGIN_ALLOW_THREADS + hFindFile = FindFirstFileW(path->wide, &wFileData); + Py_END_ALLOW_THREADS + + if (hFindFile == INVALID_HANDLE_VALUE) { + path_error(path); + return NULL; + } + + wRealFileName = wFileData.cFileName; + result = PyUnicode_FromWideChar(wRealFileName, wcslen(wRealFileName)); + FindClose(hFindFile); + return result; +} + /*[clinic input] os._getvolumepathname @@ -4874,25 +5034,25 @@ os__path_splitroot_impl(PyObject *module, path_t *path) /*[clinic input] os._path_isdir - path: 'O' + s: 'O' Return true if the pathname refers to an existing directory. [clinic start generated code]*/ static PyObject * -os__path_isdir_impl(PyObject *module, PyObject *path) -/*[clinic end generated code: output=00faea0af309669d input=b1d2571cf7291aaf]*/ +os__path_isdir_impl(PyObject *module, PyObject *s) +/*[clinic end generated code: output=9d87ab3c8b8a4e61 input=c17f7ef21d22d64e]*/ { HANDLE hfile; BOOL close_file = TRUE; FILE_BASIC_INFO info; - path_t _path = PATH_T_INITIALIZE("isdir", "path", 0, 1); + path_t _path = PATH_T_INITIALIZE("isdir", "s", 0, 1); int result; BOOL slow_path = TRUE; FILE_STAT_BASIC_INFORMATION statInfo; - if (!path_converter(path, &_path)) { + if (!path_converter(s, &_path)) { path_cleanup(&_path); if (PyErr_ExceptionMatches(PyExc_ValueError)) { PyErr_Clear(); @@ -5274,7 +5434,9 @@ os__path_normpath_impl(PyObject *module, PyObject *path) if (!buffer) { return NULL; } - PyObject *result = PyUnicode_FromWideChar(_Py_normpath(buffer, len), -1); + Py_ssize_t norm_len; + wchar_t *norm_path = _Py_normpath_and_size(buffer, len, &norm_len); + PyObject *result = PyUnicode_FromWideChar(norm_path, norm_len); PyMem_Free(buffer); return result; } @@ -6290,11 +6452,7 @@ os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns, _Py_time_t_to_FILE_TIME(utime.mtime_s, utime.mtime_ns, &mtime); } if (!SetFileTime(hFile, NULL, &atime, &mtime)) { - /* Avoid putting the file name into the error here, - as that may confuse the user into believing that - something is wrong with the file, when it also - could be the time stamp that gives a problem. */ - PyErr_SetFromWindowsErr(0); + path_error(path); CloseHandle(hFile); return NULL; } @@ -6334,8 +6492,7 @@ os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns, #endif if (result < 0) { - /* see previous comment about not putting filename in error here */ - posix_error(); + path_error(path); return NULL; } @@ -6606,8 +6763,9 @@ os_execv_impl(PyObject *module, path_t *path, PyObject *argv) /* If we get here it's definitely an error */ + posix_error(); free_string_array(argvlist, argc); - return posix_error(); + return NULL; } @@ -6710,6 +6868,9 @@ enum posix_spawn_file_actions_identifier { POSIX_SPAWN_OPEN, POSIX_SPAWN_CLOSE, POSIX_SPAWN_DUP2 +#ifdef HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSEFROM_NP + ,POSIX_SPAWN_CLOSEFROM +#endif }; #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM) @@ -6819,7 +6980,7 @@ parse_posix_spawn_flags(PyObject *module, const char *func_name, PyObject *setpg goto fail; } if (py_schedpolicy != Py_None) { - int schedpolicy = _PyLong_AsInt(py_schedpolicy); + int schedpolicy = PyLong_AsInt(py_schedpolicy); if (schedpolicy == -1 && PyErr_Occurred()) { goto fail; @@ -6911,11 +7072,12 @@ parse_file_actions(PyObject *file_actions, } errno = posix_spawn_file_actions_addopen(file_actionsp, fd, PyBytes_AS_STRING(path), oflag, (mode_t)mode); - Py_DECREF(path); if (errno) { posix_error(); + Py_DECREF(path); goto fail; } + Py_DECREF(path); break; } case POSIX_SPAWN_CLOSE: { @@ -6949,6 +7111,24 @@ parse_file_actions(PyObject *file_actions, } break; } +#ifdef HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSEFROM_NP + case POSIX_SPAWN_CLOSEFROM: { + int fd; + if (!PyArg_ParseTuple(file_action, "Oi" + ";A closefrom file_action tuple must have 2 elements", + &tag_obj, &fd)) + { + goto fail; + } + errno = posix_spawn_file_actions_addclosefrom_np(file_actionsp, + fd); + if (errno) { + posix_error(); + goto fail; + } + break; + } +#endif default: { PyErr_SetString(PyExc_TypeError, "Unknown file_actions identifier"); @@ -7004,9 +7184,9 @@ py_posix_spawn(int use_posix_spawnp, PyObject *module, path_t *path, PyObject *a return NULL; } - if (!PyMapping_Check(env)) { + if (!PyMapping_Check(env) && env != Py_None) { PyErr_Format(PyExc_TypeError, - "%s: environment must be a mapping object", func_name); + "%s: environment must be a mapping object or None", func_name); goto exit; } @@ -7020,9 +7200,21 @@ py_posix_spawn(int use_posix_spawnp, PyObject *module, path_t *path, PyObject *a goto exit; } - envlist = parse_envlist(env, &envc); - if (envlist == NULL) { - goto exit; +#ifdef USE_DARWIN_NS_GET_ENVIRON + // There is no environ global in this situation. + char **environ = NULL; +#endif + + if (env == Py_None) { +#ifdef USE_DARWIN_NS_GET_ENVIRON + environ = *_NSGetEnviron(); +#endif + envlist = environ; + } else { + envlist = parse_envlist(env, &envc); + if (envlist == NULL) { + goto exit; + } } if (file_actions != NULL && file_actions != Py_None) { @@ -7085,7 +7277,7 @@ py_posix_spawn(int use_posix_spawnp, PyObject *module, path_t *path, PyObject *a if (attrp) { (void)posix_spawnattr_destroy(attrp); } - if (envlist) { + if (envlist && envlist != environ) { free_string_array(envlist, envc); } if (argvlist) { @@ -7312,12 +7504,15 @@ os_spawnv_impl(PyObject *module, int mode, path_t *path, PyObject *argv) _Py_END_SUPPRESS_IPH Py_END_ALLOW_THREADS + int saved_errno = errno; free_string_array(argvlist, argc); - if (spawnval == -1) - return posix_error(); - else - return Py_BuildValue(_Py_PARSE_INTPTR, spawnval); + if (spawnval == -1) { + errno = saved_errno; + posix_error(); + return NULL; + } + return Py_BuildValue(_Py_PARSE_INTPTR, spawnval); } /*[clinic input] @@ -7635,6 +7830,7 @@ os_fork1_impl(PyObject *module) } PyOS_BeforeFork(); pid = fork1(); + int saved_errno = errno; if (pid == 0) { /* child: this clobbers and resets the import lock. */ PyOS_AfterFork_Child(); @@ -7643,8 +7839,10 @@ os_fork1_impl(PyObject *module) /* parent: release the import lock. */ PyOS_AfterFork_Parent(); } - if (pid == -1) + if (pid == -1) { + errno = saved_errno; return posix_error(); + } return PyLong_FromPid(pid); } #endif /* HAVE_FORK1 */ @@ -7680,6 +7878,7 @@ os_fork_impl(PyObject *module) } PyOS_BeforeFork(); pid = fork(); + int saved_errno = errno; if (pid == 0) { /* child: this clobbers and resets the import lock. */ PyOS_AfterFork_Child(); @@ -7688,8 +7887,10 @@ os_fork_impl(PyObject *module) /* parent: release the import lock. */ PyOS_AfterFork_Parent(); } - if (pid == -1) + if (pid == -1) { + errno = saved_errno; return posix_error(); + } return PyLong_FromPid(pid); } #endif /* HAVE_FORK */ @@ -8092,39 +8293,45 @@ static PyObject * os_sched_getaffinity_impl(PyObject *module, pid_t pid) /*[clinic end generated code: output=f726f2c193c17a4f input=983ce7cb4a565980]*/ { - int cpu, ncpus, count; + int ncpus = NCPUS_START; size_t setsize; - cpu_set_t *mask = NULL; - PyObject *res = NULL; + cpu_set_t *mask; - ncpus = NCPUS_START; while (1) { setsize = CPU_ALLOC_SIZE(ncpus); mask = CPU_ALLOC(ncpus); - if (mask == NULL) + if (mask == NULL) { return PyErr_NoMemory(); - if (sched_getaffinity(pid, setsize, mask) == 0) + } + if (sched_getaffinity(pid, setsize, mask) == 0) { break; + } CPU_FREE(mask); - if (errno != EINVAL) + if (errno != EINVAL) { return posix_error(); + } if (ncpus > INT_MAX / 2) { - PyErr_SetString(PyExc_OverflowError, "could not allocate " - "a large enough CPU set"); + PyErr_SetString(PyExc_OverflowError, + "could not allocate a large enough CPU set"); return NULL; } - ncpus = ncpus * 2; + ncpus *= 2; } - res = PySet_New(NULL); - if (res == NULL) + PyObject *res = PySet_New(NULL); + if (res == NULL) { goto error; - for (cpu = 0, count = CPU_COUNT_S(setsize, mask); count; cpu++) { + } + + int cpu = 0; + int count = CPU_COUNT_S(setsize, mask); + for (; count; cpu++) { if (CPU_ISSET_S(cpu, setsize, mask)) { PyObject *cpu_num = PyLong_FromLong(cpu); --count; - if (cpu_num == NULL) + if (cpu_num == NULL) { goto error; + } if (PySet_Add(res, cpu_num)) { Py_DECREF(cpu_num); goto error; @@ -8136,12 +8343,12 @@ os_sched_getaffinity_impl(PyObject *module, pid_t pid) return res; error: - if (mask) + if (mask) { CPU_FREE(mask); + } Py_XDECREF(res); return NULL; } - #endif /* HAVE_SCHED_SETAFFINITY */ #endif /* HAVE_SCHED_H */ @@ -8226,13 +8433,17 @@ os_openpty_impl(PyObject *module) /* change permission of slave */ if (grantpt(master_fd) < 0) { + int saved_errno = errno; PyOS_setsig(SIGCHLD, sig_saved); + errno = saved_errno; goto posix_error; } /* unlock slave */ if (unlockpt(master_fd) < 0) { + int saved_errno = errno; PyOS_setsig(SIGCHLD, sig_saved); + errno = saved_errno; goto posix_error; } @@ -8596,8 +8807,9 @@ os_getgroups_impl(PyObject *module) n = getgroups(n, grouplist); if (n == -1) { + posix_error(); PyMem_Free(grouplist); - return posix_error(); + return NULL; } PyObject *result = PyList_New(n); @@ -9164,8 +9376,9 @@ os_setgroups(PyObject *module, PyObject *groups) } if (setgroups(len, grouplist) < 0) { + posix_error(); PyMem_Free(grouplist); - return posix_error(); + return NULL; } PyMem_Free(grouplist); Py_RETURN_NONE; @@ -9305,7 +9518,7 @@ os_wait4_impl(PyObject *module, pid_t pid, int options) #endif /* HAVE_WAIT4 */ -#if defined(HAVE_WAITID) && !defined(__APPLE__) +#if defined(HAVE_WAITID) /*[clinic input] os.waitid @@ -9362,7 +9575,7 @@ os_waitid_impl(PyObject *module, idtype_t idtype, id_t id, int options) return result; } -#endif /* defined(HAVE_WAITID) && !defined(__APPLE__) */ +#endif /* defined(HAVE_WAITID) */ #if defined(HAVE_WAITPID) @@ -9891,8 +10104,6 @@ os_symlink_impl(PyObject *module, path_t *src, path_t *dst, #endif /* HAVE_SYMLINK */ - - static PyStructSequence_Field times_result_fields[] = { {"user", "user time"}, {"system", "system time"}, @@ -9918,12 +10129,6 @@ static PyStructSequence_Desc times_result_desc = { 5 }; -#ifdef MS_WINDOWS -#define HAVE_TIMES /* mandatory, for the method table */ -#endif - -#ifdef HAVE_TIMES - static PyObject * build_times_result(PyObject *module, double user, double system, double children_user, double children_system, @@ -9969,8 +10174,8 @@ All fields are floating point numbers. static PyObject * os_times_impl(PyObject *module) /*[clinic end generated code: output=35f640503557d32a input=2bf9df3d6ab2e48b]*/ -#ifdef MS_WINDOWS { +#ifdef MS_WINDOWS FILETIME create, exit, kernel, user; HANDLE hProc; hProc = GetCurrentProcess(); @@ -9988,29 +10193,248 @@ os_times_impl(PyObject *module) (double)0, (double)0, (double)0); -} #else /* MS_WINDOWS */ -{ - struct tms t; - clock_t c; + _posixstate *state = get_posix_state(module); + long ticks_per_second = state->ticks_per_second; + + struct tms process; + clock_t elapsed; errno = 0; - c = times(&t); - if (c == (clock_t) -1) { + elapsed = times(&process); + if (elapsed == (clock_t) -1) { return posix_error(); } - assert(_PyRuntime.time.ticks_per_second_initialized); -#define ticks_per_second _PyRuntime.time.ticks_per_second + return build_times_result(module, - (double)t.tms_utime / ticks_per_second, - (double)t.tms_stime / ticks_per_second, - (double)t.tms_cutime / ticks_per_second, - (double)t.tms_cstime / ticks_per_second, - (double)c / ticks_per_second); -#undef ticks_per_second -} + (double)process.tms_utime / ticks_per_second, + (double)process.tms_stime / ticks_per_second, + (double)process.tms_cutime / ticks_per_second, + (double)process.tms_cstime / ticks_per_second, + (double)elapsed / ticks_per_second); #endif /* MS_WINDOWS */ -#endif /* HAVE_TIMES */ +} + + +#if defined(HAVE_TIMERFD_CREATE) +#define ONE_SECOND_IN_NS (1000 * 1000 * 1000) +#define EXTRACT_NSEC(value) (long)( ( (double)(value) - (time_t)(value) ) * 1e9) +#define CONVERT_SEC_AND_NSEC_TO_DOUBLE(sec, nsec) ( (double)(sec) + (double)(nsec) * 1e-9 ) + +static PyObject * +build_itimerspec(const struct itimerspec* curr_value) +{ + double _value = CONVERT_SEC_AND_NSEC_TO_DOUBLE(curr_value->it_value.tv_sec, + curr_value->it_value.tv_nsec); + PyObject *value = PyFloat_FromDouble(_value); + if (value == NULL) { + return NULL; + } + double _interval = CONVERT_SEC_AND_NSEC_TO_DOUBLE(curr_value->it_interval.tv_sec, + curr_value->it_interval.tv_nsec); + PyObject *interval = PyFloat_FromDouble(_interval); + if (interval == NULL) { + Py_DECREF(value); + return NULL; + } + PyObject *tuple = PyTuple_Pack(2, value, interval); + Py_DECREF(interval); + Py_DECREF(value); + return tuple; +} + +static PyObject * +build_itimerspec_ns(const struct itimerspec* curr_value) +{ + _PyTime_t value, interval; + if (_PyTime_FromTimespec(&value, &curr_value->it_value) < 0) { + return NULL; + } + if (_PyTime_FromTimespec(&interval, &curr_value->it_interval) < 0) { + return NULL; + } + return Py_BuildValue("LL", value, interval); +} + +/*[clinic input] +os.timerfd_create + + clockid: int + A valid clock ID constant as timer file descriptor. + + time.CLOCK_REALTIME + time.CLOCK_MONOTONIC + time.CLOCK_BOOTTIME + / + * + flags: int = 0 + 0 or a bit mask of os.TFD_NONBLOCK or os.TFD_CLOEXEC. + + os.TFD_NONBLOCK + If *TFD_NONBLOCK* is set as a flag, read doesn't blocks. + If *TFD_NONBLOCK* is not set as a flag, read block until the timer fires. + + os.TFD_CLOEXEC + If *TFD_CLOEXEC* is set as a flag, enable the close-on-exec flag + +Create and return a timer file descriptor. +[clinic start generated code]*/ + +static PyObject * +os_timerfd_create_impl(PyObject *module, int clockid, int flags) +/*[clinic end generated code: output=1caae80fb168004a input=64b7020c5ac0b8f4]*/ + +{ + int fd; + Py_BEGIN_ALLOW_THREADS + flags |= TFD_CLOEXEC; // PEP 446: always create non-inheritable FD + fd = timerfd_create(clockid, flags); + Py_END_ALLOW_THREADS + if (fd == -1) { + return PyErr_SetFromErrno(PyExc_OSError); + } + return PyLong_FromLong(fd); +} + +/*[clinic input] +os.timerfd_settime + + fd: fildes + A timer file descriptor. + / + * + flags: int = 0 + 0 or a bit mask of TFD_TIMER_ABSTIME or TFD_TIMER_CANCEL_ON_SET. + initial: double = 0.0 + The initial expiration time, in seconds. + interval: double = 0.0 + The timer's interval, in seconds. + +Alter a timer file descriptor's internal timer in seconds. +[clinic start generated code]*/ + +static PyObject * +os_timerfd_settime_impl(PyObject *module, int fd, int flags, double initial, + double interval) +/*[clinic end generated code: output=0dda31115317adb9 input=6c24e47e7a4d799e]*/ +{ + struct itimerspec new_value; + struct itimerspec old_value; + int result; + if (_PyTime_AsTimespec(_PyTime_FromSecondsDouble(initial, _PyTime_ROUND_FLOOR), &new_value.it_value) < 0) { + PyErr_SetString(PyExc_ValueError, "invalid initial value"); + return NULL; + } + if (_PyTime_AsTimespec(_PyTime_FromSecondsDouble(interval, _PyTime_ROUND_FLOOR), &new_value.it_interval) < 0) { + PyErr_SetString(PyExc_ValueError, "invalid interval value"); + return NULL; + } + Py_BEGIN_ALLOW_THREADS + result = timerfd_settime(fd, flags, &new_value, &old_value); + Py_END_ALLOW_THREADS + if (result == -1) { + return PyErr_SetFromErrno(PyExc_OSError); + } + return build_itimerspec(&old_value); +} + + +/*[clinic input] +os.timerfd_settime_ns + + fd: fildes + A timer file descriptor. + / + * + flags: int = 0 + 0 or a bit mask of TFD_TIMER_ABSTIME or TFD_TIMER_CANCEL_ON_SET. + initial: long_long = 0 + initial expiration timing in seconds. + interval: long_long = 0 + interval for the timer in seconds. + +Alter a timer file descriptor's internal timer in nanoseconds. +[clinic start generated code]*/ + +static PyObject * +os_timerfd_settime_ns_impl(PyObject *module, int fd, int flags, + long long initial, long long interval) +/*[clinic end generated code: output=6273ec7d7b4cc0b3 input=261e105d6e42f5bc]*/ +{ + struct itimerspec new_value; + struct itimerspec old_value; + int result; + if (_PyTime_AsTimespec(initial, &new_value.it_value) < 0) { + PyErr_SetString(PyExc_ValueError, "invalid initial value"); + return NULL; + } + if (_PyTime_AsTimespec(interval, &new_value.it_interval) < 0) { + PyErr_SetString(PyExc_ValueError, "invalid interval value"); + return NULL; + } + Py_BEGIN_ALLOW_THREADS + result = timerfd_settime(fd, flags, &new_value, &old_value); + Py_END_ALLOW_THREADS + if (result == -1) { + return PyErr_SetFromErrno(PyExc_OSError); + } + return build_itimerspec_ns(&old_value); +} + +/*[clinic input] +os.timerfd_gettime + + fd: fildes + A timer file descriptor. + / + +Return a tuple of a timer file descriptor's (interval, next expiration) in float seconds. +[clinic start generated code]*/ + +static PyObject * +os_timerfd_gettime_impl(PyObject *module, int fd) +/*[clinic end generated code: output=ec5a94a66cfe6ab4 input=8148e3430870da1c]*/ +{ + struct itimerspec curr_value; + int result; + Py_BEGIN_ALLOW_THREADS + result = timerfd_gettime(fd, &curr_value); + Py_END_ALLOW_THREADS + if (result == -1) { + return PyErr_SetFromErrno(PyExc_OSError); + } + return build_itimerspec(&curr_value); +} + +/*[clinic input] +os.timerfd_gettime_ns + + fd: fildes + A timer file descriptor. + / + +Return a tuple of a timer file descriptor's (interval, next expiration) in nanoseconds. +[clinic start generated code]*/ + +static PyObject * +os_timerfd_gettime_ns_impl(PyObject *module, int fd) +/*[clinic end generated code: output=580633a4465f39fe input=a825443e4c6b40ac]*/ +{ + struct itimerspec curr_value; + int result; + Py_BEGIN_ALLOW_THREADS + result = timerfd_gettime(fd, &curr_value); + Py_END_ALLOW_THREADS + if (result == -1) { + return PyErr_SetFromErrno(PyExc_OSError); + } + return build_itimerspec_ns(&curr_value); +} + +#undef ONE_SECOND_IN_NS +#undef EXTRACT_NSEC + +#endif /* HAVE_TIMERFD_CREATE */ #ifdef HAVE_GETSID /*[clinic input] @@ -10422,19 +10846,24 @@ os_lockf_impl(PyObject *module, int fd, int command, Py_off_t length) os.lseek -> Py_off_t fd: int + An open file descriptor, as returned by os.open(). position: Py_off_t - how: int + Position, interpreted relative to 'whence'. + whence as how: int + The relative position to seek from. Valid values are: + - SEEK_SET: seek from the start of the file. + - SEEK_CUR: seek from the current file position. + - SEEK_END: seek from the end of the file. / Set the position of a file descriptor. Return the new position. -Return the new cursor position in number of bytes -relative to the beginning of the file. +The return value is the number of bytes relative to the beginning of the file. [clinic start generated code]*/ static Py_off_t os_lseek_impl(PyObject *module, int fd, Py_off_t position, int how) -/*[clinic end generated code: output=971e1efb6b30bd2f input=902654ad3f96a6d3]*/ +/*[clinic end generated code: output=971e1efb6b30bd2f input=f096e754c5367504]*/ { Py_off_t result; @@ -10607,10 +11036,13 @@ os_readv_impl(PyObject *module, int fd, PyObject *buffers) Py_END_ALLOW_THREADS } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); + int saved_errno = errno; iov_cleanup(iov, buf, cnt); if (n < 0) { - if (!async_err) + if (!async_err) { + errno = saved_errno; posix_error(); + } return -1; } @@ -10659,8 +11091,11 @@ os_pread_impl(PyObject *module, int fd, Py_ssize_t length, Py_off_t offset) } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); if (n < 0) { + if (!async_err) { + posix_error(); + } Py_DECREF(buffer); - return (!async_err) ? posix_error() : NULL; + return NULL; } if (n != length) _PyBytes_Resize(&buffer, n); @@ -10757,9 +11192,11 @@ os_preadv_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset, #endif + int saved_errno = errno; iov_cleanup(iov, buf, cnt); if (n < 0) { if (!async_err) { + errno = saved_errno; posix_error(); } return -1; @@ -10928,32 +11365,34 @@ os_sendfile_impl(PyObject *module, int out_fd, int in_fd, PyObject *offobj, } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); _Py_END_SUPPRESS_IPH + int saved_errno = errno; if (sf.headers != NULL) iov_cleanup(sf.headers, hbuf, sf.hdr_cnt); if (sf.trailers != NULL) iov_cleanup(sf.trailers, tbuf, sf.trl_cnt); if (ret < 0) { - if ((errno == EAGAIN) || (errno == EBUSY)) { + if ((saved_errno == EAGAIN) || (saved_errno == EBUSY)) { if (sbytes != 0) { // some data has been sent goto done; } - else { - // no data has been sent; upper application is supposed - // to retry on EAGAIN or EBUSY - return posix_error(); - } + // no data has been sent; upper application is supposed + // to retry on EAGAIN or EBUSY } - return (!async_err) ? posix_error() : NULL; + if (!async_err) { + errno = saved_errno; + posix_error(); + } + return NULL; } goto done; done: #if !defined(HAVE_LARGEFILE_SUPPORT) - return Py_BuildValue("l", sbytes); + return PyLong_FromLong(sbytes); #else - return Py_BuildValue("L", sbytes); + return PyLong_FromLongLong(sbytes); #endif #else @@ -10966,7 +11405,7 @@ os_sendfile_impl(PyObject *module, int out_fd, int in_fd, PyObject *offobj, } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); if (ret < 0) return (!async_err) ? posix_error() : NULL; - return Py_BuildValue("n", ret); + return PyLong_FromSsize_t(ret); } #endif off_t offset; @@ -10987,7 +11426,7 @@ os_sendfile_impl(PyObject *module, int out_fd, int in_fd, PyObject *offobj, return (!async_err) ? posix_error() : NULL; if (offset >= st.st_size) { - return Py_BuildValue("i", 0); + return PyLong_FromLong(0); } // On illumos specifically sendfile() may perform a partial write but @@ -11013,7 +11452,7 @@ os_sendfile_impl(PyObject *module, int out_fd, int in_fd, PyObject *offobj, } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); if (ret < 0) return (!async_err) ? posix_error() : NULL; - return Py_BuildValue("n", ret); + return PyLong_FromSsize_t(ret); #endif } #endif /* HAVE_SENDFILE */ @@ -11139,8 +11578,8 @@ os_pipe_impl(PyObject *module) Py_BEGIN_ALLOW_THREADS ok = CreatePipe(&read, &write, &attr, 0); if (ok) { - fds[0] = _Py_open_osfhandle_noraise(read, _O_RDONLY); - fds[1] = _Py_open_osfhandle_noraise(write, _O_WRONLY); + fds[0] = _Py_open_osfhandle_noraise(read, _O_RDONLY | _O_NOINHERIT); + fds[1] = _Py_open_osfhandle_noraise(write, _O_WRONLY | _O_NOINHERIT); if (fds[0] == -1 || fds[1] == -1) { CloseHandle(read); CloseHandle(write); @@ -11262,10 +11701,10 @@ os_writev_impl(PyObject *module, int fd, PyObject *buffers) Py_END_ALLOW_THREADS } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); - iov_cleanup(iov, buf, cnt); if (result < 0 && !async_err) posix_error(); + iov_cleanup(iov, buf, cnt); return result; } #endif /* HAVE_WRITEV */ @@ -11400,13 +11839,13 @@ os_pwritev_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset, #endif - iov_cleanup(iov, buf, cnt); if (result < 0) { if (!async_err) { posix_error(); } - return -1; + result = -1; } + iov_cleanup(iov, buf, cnt); return result; } @@ -11834,7 +12273,10 @@ os_truncate_impl(PyObject *module, path_t *path, Py_off_t length) #endif -#if defined(HAVE_POSIX_FALLOCATE) && !defined(POSIX_FADVISE_AIX_BUG) +/* GH-111804: Due to posix_fallocate() not having consistent semantics across + OSs, support was dropped in WASI preview2. */ +#if defined(HAVE_POSIX_FALLOCATE) && !defined(POSIX_FADVISE_AIX_BUG) && \ + !defined(__wasi__) /*[clinic input] os.posix_fallocate @@ -11872,7 +12314,7 @@ os_posix_fallocate_impl(PyObject *module, int fd, Py_off_t offset, errno = result; return posix_error(); } -#endif /* HAVE_POSIX_FALLOCATE) && !POSIX_FADVISE_AIX_BUG */ +#endif /* HAVE_POSIX_FALLOCATE) && !POSIX_FADVISE_AIX_BUG && !defined(__wasi__) */ #if defined(HAVE_POSIX_FADVISE) && !defined(POSIX_FADVISE_AIX_BUG) @@ -11946,7 +12388,6 @@ win32_putenv(PyObject *name, PyObject *value) } Py_ssize_t size; - /* PyUnicode_AsWideCharString() rejects embedded null characters */ wchar_t *env = PyUnicode_AsWideCharString(unicode, &size); Py_DECREF(unicode); @@ -11960,6 +12401,12 @@ win32_putenv(PyObject *name, PyObject *value) PyMem_Free(env); return NULL; } + if (wcslen(env) != (size_t)size) { + PyErr_SetString(PyExc_ValueError, + "embedded null character"); + PyMem_Free(env); + return NULL; + } /* _wputenv() and SetEnvironmentVariableW() update the environment in the Process Environment Block (PEB). _wputenv() also updates CRT 'environ' @@ -11968,12 +12415,13 @@ win32_putenv(PyObject *name, PyObject *value) Prefer _wputenv() to be compatible with C libraries using CRT variables and CRT functions using these variables (ex: getenv()). */ int err = _wputenv(env); - PyMem_Free(env); if (err) { posix_error(); + PyMem_Free(env); return NULL; } + PyMem_Free(env); Py_RETURN_NONE; } @@ -12477,7 +12925,7 @@ conv_confname(PyObject *arg, int *valuep, struct constdef *table, size_t tablesize) { if (PyLong_Check(arg)) { - int value = _PyLong_AsInt(arg); + int value = PyLong_AsInt(arg); if (value == -1 && PyErr_Occurred()) return 0; *valuep = value; @@ -13815,10 +14263,12 @@ os_getxattr_impl(PyObject *module, path_t *path, path_t *attribute, Py_END_ALLOW_THREADS; if (result < 0) { - Py_DECREF(buffer); - if (errno == ERANGE) + if (errno == ERANGE) { + Py_DECREF(buffer); continue; + } path_error(path); + Py_DECREF(buffer); return NULL; } @@ -14264,48 +14714,57 @@ os_get_terminal_size_impl(PyObject *module, int fd) } #endif /* defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL) */ - /*[clinic input] os.cpu_count -Return the number of CPUs in the system; return None if indeterminable. +Return the number of logical CPUs in the system. -This number is not equivalent to the number of CPUs the current process can -use. The number of usable CPUs can be obtained with -``len(os.sched_getaffinity(0))`` +Return None if indeterminable. [clinic start generated code]*/ static PyObject * os_cpu_count_impl(PyObject *module) -/*[clinic end generated code: output=5fc29463c3936a9c input=e7c8f4ba6dbbadd3]*/ +/*[clinic end generated code: output=5fc29463c3936a9c input=ba2f6f8980a0e2eb]*/ { + const PyConfig *config = _Py_GetConfig(); + if (config->cpu_count > 0) { + return PyLong_FromLong(config->cpu_count); + } + int ncpu = 0; #ifdef MS_WINDOWS -#ifdef MS_WINDOWS_DESKTOP +# ifdef MS_WINDOWS_DESKTOP ncpu = GetActiveProcessorCount(ALL_PROCESSOR_GROUPS); -#endif +# else + ncpu = 0; +# endif + #elif defined(__hpux) ncpu = mpctl(MPC_GETNUMSPUS, NULL, NULL); + #elif defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN) ncpu = sysconf(_SC_NPROCESSORS_ONLN); + #elif defined(__VXWORKS__) ncpu = _Py_popcount32(vxCpuEnabledGet()); + #elif defined(__DragonFly__) || \ defined(__OpenBSD__) || \ defined(__FreeBSD__) || \ defined(__NetBSD__) || \ defined(__APPLE__) - int mib[2]; + ncpu = 0; size_t len = sizeof(ncpu); - mib[0] = CTL_HW; - mib[1] = HW_NCPU; - if (sysctl(mib, 2, &ncpu, &len, NULL, 0) != 0) + int mib[2] = {CTL_HW, HW_NCPU}; + if (sysctl(mib, 2, &ncpu, &len, NULL, 0) != 0) { ncpu = 0; + } #endif - if (ncpu >= 1) - return PyLong_FromLong(ncpu); - else + + if (ncpu < 1) { Py_RETURN_NONE; + } + return PyLong_FromLong(ncpu); } @@ -14468,6 +14927,7 @@ typedef struct { #ifdef MS_WINDOWS struct _Py_stat_struct win32_lstat; uint64_t win32_file_index; + uint64_t win32_file_index_high; int got_file_index; #else /* POSIX */ #ifdef HAVE_DIRENT_D_TYPE @@ -14524,15 +14984,13 @@ os_DirEntry_is_symlink_impl(DirEntry *self, PyTypeObject *defining_class) /*[clinic input] os.DirEntry.is_junction -> bool - defining_class: defining_class - / Return True if the entry is a junction; cached per entry. [clinic start generated code]*/ static int -os_DirEntry_is_junction_impl(DirEntry *self, PyTypeObject *defining_class) -/*[clinic end generated code: output=7061a07b0ef2cd1f input=475cd36fb7d4723f]*/ +os_DirEntry_is_junction_impl(DirEntry *self) +/*[clinic end generated code: output=97f64d5d99eeccb5 input=4fc8e701eea118a1]*/ { #ifdef MS_WINDOWS return self->win32_lstat.st_reparse_tag == IO_REPARSE_TAG_MOUNT_POINT; @@ -14585,14 +15043,19 @@ DirEntry_fetch_stat(PyObject *module, DirEntry *self, int follow_symlinks) } Py_END_ALLOW_THREADS } + + int saved_errno = errno; #if defined(MS_WINDOWS) PyMem_Free(path); #else Py_DECREF(ub); #endif - if (result != 0) - return path_object_error(self->path); + if (result != 0) { + errno = saved_errno; + path_object_error(self->path); + return NULL; + } return _pystat_fromstructstat(module, &st); } @@ -14784,17 +15247,20 @@ os_DirEntry_inode_impl(DirEntry *self) wchar_t *path = PyUnicode_AsWideCharString(unicode, NULL); Py_DECREF(unicode); result = LSTAT(path, &stat); + + int saved_errno = errno; PyMem_Free(path); - if (result != 0) + if (result != 0) { + errno = saved_errno; return path_object_error(self->path); + } self->win32_file_index = stat.st_ino; + self->win32_file_index_high = stat.st_ino_high; self->got_file_index = 1; } - static_assert(sizeof(unsigned long long) >= sizeof(self->win32_file_index), - "DirEntry.win32_file_index is larger than unsigned long long"); - return PyLong_FromUnsignedLongLong(self->win32_file_index); + return _pystat_l128_from_l64_l64(self->win32_file_index, self->win32_file_index_high); #else /* POSIX */ static_assert(sizeof(unsigned long long) >= sizeof(self->d_ino), "DirEntry.d_ino is larger than unsigned long long"); @@ -15351,12 +15817,12 @@ os_scandir_impl(PyObject *module, path_t *path) iterator->handle = FindFirstFileW(path_strW, &iterator->file_data); Py_END_ALLOW_THREADS - PyMem_Free(path_strW); - if (iterator->handle == INVALID_HANDLE_VALUE) { path_error(&iterator->path); + PyMem_Free(path_strW); goto error; } + PyMem_Free(path_strW); #else /* POSIX */ errno = 0; #ifdef HAVE_FDOPENDIR @@ -15661,7 +16127,7 @@ os_waitstatus_to_exitcode_impl(PyObject *module, PyObject *status_obj) /*[clinic end generated code: output=db50b1b0ba3c7153 input=7fe2d7fdaea3db42]*/ { #ifndef MS_WINDOWS - int status = _PyLong_AsInt(status_obj); + int status = PyLong_AsInt(status_obj); if (status == -1 && PyErr_Occurred()) { return NULL; } @@ -15721,6 +16187,26 @@ os_waitstatus_to_exitcode_impl(PyObject *module, PyObject *status_obj) } #endif +#if defined(MS_WINDOWS) +/*[clinic input] +os._supports_virtual_terminal + +Checks if virtual terminal is supported in windows +[clinic start generated code]*/ + +static PyObject * +os__supports_virtual_terminal_impl(PyObject *module) +/*[clinic end generated code: output=bd0556a6d9d99fe6 input=0752c98e5d321542]*/ +{ + DWORD mode = 0; + HANDLE handle = GetStdHandle(STD_ERROR_HANDLE); + if (!GetConsoleMode(handle, &mode)) { + Py_RETURN_FALSE; + } + return PyBool_FromLong(mode & ENABLE_VIRTUAL_TERMINAL_PROCESSING); +} +#endif + static PyMethodDef posix_methods[] = { @@ -15878,6 +16364,7 @@ static PyMethodDef posix_methods[] = { OS__GETFULLPATHNAME_METHODDEF OS__GETDISKUSAGE_METHODDEF OS__GETFINALPATHNAME_METHODDEF + OS__FINDFIRSTFILE_METHODDEF OS__GETVOLUMEPATHNAME_METHODDEF OS__PATH_SPLITROOT_METHODDEF OS__PATH_NORMPATH_METHODDEF @@ -15913,12 +16400,19 @@ static PyMethodDef posix_methods[] = { OS_WAITSTATUS_TO_EXITCODE_METHODDEF OS_SETNS_METHODDEF OS_UNSHARE_METHODDEF + OS_TIMERFD_CREATE_METHODDEF + OS_TIMERFD_SETTIME_METHODDEF + OS_TIMERFD_SETTIME_NS_METHODDEF + OS_TIMERFD_GETTIME_METHODDEF + OS_TIMERFD_GETTIME_NS_METHODDEF OS__PATH_ISDEVDRIVE_METHODDEF OS__PATH_ISDIR_METHODDEF OS__PATH_ISFILE_METHODDEF OS__PATH_ISLINK_METHODDEF OS__PATH_EXISTS_METHODDEF + + OS__SUPPORTS_VIRTUAL_TERMINAL_METHODDEF {NULL, NULL} /* Sentinel */ }; @@ -16228,6 +16722,19 @@ all_ins(PyObject *m) if (PyModule_AddIntMacro(m, SF_NOCACHE)) return -1; #endif +#ifdef TFD_NONBLOCK + if (PyModule_AddIntMacro(m, TFD_NONBLOCK)) return -1; +#endif +#ifdef TFD_CLOEXEC + if (PyModule_AddIntMacro(m, TFD_CLOEXEC)) return -1; +#endif +#ifdef TFD_TIMER_ABSTIME + if (PyModule_AddIntMacro(m, TFD_TIMER_ABSTIME)) return -1; +#endif +#ifdef TFD_TIMER_CANCEL_ON_SET + if (PyModule_AddIntMacro(m, TFD_TIMER_CANCEL_ON_SET)) return -1; +#endif + /* constants for posix_fadvise */ #ifdef POSIX_FADV_NORMAL if (PyModule_AddIntMacro(m, POSIX_FADV_NORMAL)) return -1; @@ -16330,6 +16837,9 @@ all_ins(PyObject *m) if (PyModule_AddIntConstant(m, "POSIX_SPAWN_OPEN", POSIX_SPAWN_OPEN)) return -1; if (PyModule_AddIntConstant(m, "POSIX_SPAWN_CLOSE", POSIX_SPAWN_CLOSE)) return -1; if (PyModule_AddIntConstant(m, "POSIX_SPAWN_DUP2", POSIX_SPAWN_DUP2)) return -1; +#ifdef HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSEFROM_NP + if (PyModule_AddIntMacro(m, POSIX_SPAWN_CLOSEFROM)) return -1; +#endif #endif #if defined(HAVE_SPAWNV) || defined (HAVE_RTPSPAWN) @@ -16626,6 +17136,10 @@ static const struct have_function { {"HAVE_EVENTFD", NULL}, #endif +#ifdef HAVE_TIMERFD_CREATE + {"HAVE_TIMERFD_CREATE", NULL}, +#endif + #ifdef HAVE_FACCESSAT { "HAVE_FACCESSAT", probe_faccessat }, #endif @@ -16795,7 +17309,7 @@ posixmodule_exec(PyObject *m) return -1; } -#if defined(HAVE_WAITID) && !defined(__APPLE__) +#if defined(HAVE_WAITID) waitid_result_desc.name = MODNAME ".waitid_result"; state->WaitidResultType = (PyObject *)PyStructSequence_NewType(&waitid_result_desc); if (PyModule_AddObjectRef(m, "waitid_result", state->WaitidResultType) < 0) { @@ -16898,6 +17412,15 @@ posixmodule_exec(PyObject *m) Py_DECREF(unicode); } +#ifndef MS_WINDOWS + if (_Py_GetTicksPerSecond(&state->ticks_per_second) < 0) { + PyErr_SetString(PyExc_RuntimeError, + "cannot read ticks_per_second"); + return -1; + } + assert(state->ticks_per_second >= 1); +#endif + return PyModule_Add(m, "_have_functions", list); } @@ -16925,7 +17448,3 @@ INITFUNC(void) { return PyModuleDef_Init(&posixmodule); } - -#ifdef __cplusplus -} -#endif diff --git a/Modules/posixmodule.h b/Modules/posixmodule.h index 5452ffbf17acfc..8827ce153fed8c 100644 --- a/Modules/posixmodule.h +++ b/Modules/posixmodule.h @@ -2,31 +2,37 @@ #ifndef Py_POSIXMODULE_H #define Py_POSIXMODULE_H +#ifndef Py_LIMITED_API #ifdef __cplusplus extern "C" { #endif #ifdef HAVE_SYS_TYPES_H -#include +# include // uid_t #endif -#ifndef Py_LIMITED_API #ifndef MS_WINDOWS -PyAPI_FUNC(PyObject *) _PyLong_FromUid(uid_t); -PyAPI_FUNC(PyObject *) _PyLong_FromGid(gid_t); +extern PyObject* _PyLong_FromUid(uid_t); + +// Export for 'grp' shared extension +PyAPI_FUNC(PyObject*) _PyLong_FromGid(gid_t); + +// Export for '_posixsubprocess' shared extension PyAPI_FUNC(int) _Py_Uid_Converter(PyObject *, uid_t *); + +// Export for 'grp' shared extension PyAPI_FUNC(int) _Py_Gid_Converter(PyObject *, gid_t *); -#endif /* MS_WINDOWS */ +#endif // !MS_WINDOWS -#if defined(PYPTHREAD_SIGMASK) || defined(HAVE_SIGWAIT) || \ - defined(HAVE_SIGWAITINFO) || defined(HAVE_SIGTIMEDWAIT) -# define HAVE_SIGSET_T +#if (defined(PYPTHREAD_SIGMASK) || defined(HAVE_SIGWAIT) \ + || defined(HAVE_SIGWAITINFO) || defined(HAVE_SIGTIMEDWAIT)) +# define HAVE_SIGSET_T #endif -PyAPI_FUNC(int) _Py_Sigset_Converter(PyObject *, void *); -#endif /* Py_LIMITED_API */ +extern int _Py_Sigset_Converter(PyObject *, void *); #ifdef __cplusplus } #endif -#endif /* !Py_POSIXMODULE_H */ +#endif // !Py_LIMITED_API +#endif // !Py_POSIXMODULE_H diff --git a/Modules/pwdmodule.c b/Modules/pwdmodule.c index cc2e2a43893971..b7034369c4731e 100644 --- a/Modules/pwdmodule.c +++ b/Modules/pwdmodule.c @@ -4,7 +4,8 @@ #include "Python.h" #include "posixmodule.h" -#include +#include // getpwuid() +#include // sysconf() #include "clinic/pwdmodule.c.h" /*[clinic input] diff --git a/Modules/pyexpat.c b/Modules/pyexpat.c index a8ce84c0bb9f05..ec44892d101e44 100644 --- a/Modules/pyexpat.c +++ b/Modules/pyexpat.c @@ -5,8 +5,8 @@ #include "Python.h" #include "pycore_import.h" // _PyImport_SetModule() #include "pycore_pyhash.h" // _Py_HashSecret +#include "pycore_traceback.h" // _PyTraceback_Add() -#include #include // offsetof() #include "expat.h" #include "pyexpat.h" @@ -240,19 +240,12 @@ string_intern(xmlparseobject *self, const char* str) return result; if (!self->intern) return result; - value = PyDict_GetItemWithError(self->intern, result); - if (!value) { - if (!PyErr_Occurred() && - PyDict_SetItem(self->intern, result, result) == 0) - { - return result; - } - else { - Py_DECREF(result); - return NULL; - } + if (PyDict_GetItemRef(self->intern, result, &value) == 0 && + PyDict_SetItem(self->intern, result, result) == 0) + { + return result; } - Py_INCREF(value); + assert((value != NULL) == !PyErr_Occurred()); Py_DECREF(result); return value; } @@ -895,7 +888,7 @@ static PyObject * pyexpat_xmlparser_GetBase_impl(xmlparseobject *self) /*[clinic end generated code: output=2886cb21f9a8739a input=918d71c38009620e]*/ { - return Py_BuildValue("z", XML_GetBase(self->itself)); + return conv_string_to_unicode(XML_GetBase(self->itself)); } /*[clinic input] @@ -1585,7 +1578,7 @@ static PyObject * pyexpat_ErrorString_impl(PyObject *module, long code) /*[clinic end generated code: output=2feae50d166f2174 input=cc67de010d9e62b3]*/ { - return Py_BuildValue("z", XML_ErrorString((int)code)); + return conv_string_to_unicode(XML_ErrorString((int)code)); } /* List of methods defined in the module */ @@ -2069,9 +2062,7 @@ pyexpat_free(void *module) static PyModuleDef_Slot pyexpat_slots[] = { {Py_mod_exec, pyexpat_exec}, - // XXX gh-103092: fix isolation. - {Py_mod_multiple_interpreters, Py_MOD_MULTIPLE_INTERPRETERS_NOT_SUPPORTED}, - //{Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, + {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {0, NULL} }; diff --git a/Modules/readline.c b/Modules/readline.c index 6729a09cb0da5e..e29051c37f8827 100644 --- a/Modules/readline.c +++ b/Modules/readline.c @@ -12,14 +12,13 @@ #include "Python.h" #include "pycore_pylifecycle.h" // _Py_SetLocaleFromEnv() -#include -#include -#include +#include // errno +#include // SIGWINCH #include // free() -#ifdef HAVE_SYS_TIME_H -#include +#include // strdup() +#ifdef HAVE_SYS_SELECT_H +# include // select() #endif -#include #if defined(HAVE_SETLOCALE) /* GNU readline() mistakenly sets the LC_CTYPE locale. @@ -27,7 +26,7 @@ * We must save and restore the locale around the rl_initialize() call. */ #define SAVE_LOCALE -#include +# include // setlocale() #endif #ifdef SAVE_LOCALE @@ -148,8 +147,19 @@ readline_free(void *m) static PyModuleDef readlinemodule; -#define readlinestate_global ((readlinestate *)PyModule_GetState(PyState_FindModule(&readlinemodule))) - +static inline readlinestate* +get_hook_module_state(void) +{ + PyObject *mod = PyState_FindModule(&readlinemodule); + if (mod == NULL){ + PyErr_Clear(); + return NULL; + } + Py_INCREF(mod); + readlinestate *state = get_readline_state(mod); + Py_DECREF(mod); + return state; +} /* Convert to/from multibyte C strings */ @@ -439,15 +449,16 @@ readline_set_completion_display_matches_hook_impl(PyObject *module, PyObject *function) /*[clinic end generated code: output=516e5cb8db75a328 input=4f0bfd5ab0179a26]*/ { + readlinestate *state = get_readline_state(module); PyObject *result = set_hook("completion_display_matches_hook", - &readlinestate_global->completion_display_matches_hook, + &state->completion_display_matches_hook, function); #ifdef HAVE_RL_COMPLETION_DISPLAY_MATCHES_HOOK /* We cannot set this hook globally, since it replaces the default completion display. */ rl_completion_display_matches_hook = - readlinestate_global->completion_display_matches_hook ? -#if defined(_RL_FUNCTION_TYPEDEF) + state->completion_display_matches_hook ? +#if defined(HAVE_RL_COMPDISP_FUNC_T) (rl_compdisp_func_t *)on_completion_display_matches_hook : 0; #else (VFunction *)on_completion_display_matches_hook : 0; @@ -473,7 +484,8 @@ static PyObject * readline_set_startup_hook_impl(PyObject *module, PyObject *function) /*[clinic end generated code: output=02cd0e0c4fa082ad input=7783b4334b26d16d]*/ { - return set_hook("startup_hook", &readlinestate_global->startup_hook, + readlinestate *state = get_readline_state(module); + return set_hook("startup_hook", &state->startup_hook, function); } @@ -498,7 +510,8 @@ static PyObject * readline_set_pre_input_hook_impl(PyObject *module, PyObject *function) /*[clinic end generated code: output=fe1a96505096f464 input=4f3eaeaf7ce1fdbe]*/ { - return set_hook("pre_input_hook", &readlinestate_global->pre_input_hook, + readlinestate *state = get_readline_state(module); + return set_hook("pre_input_hook", &state->pre_input_hook, function); } #endif @@ -531,7 +544,8 @@ static PyObject * readline_get_begidx_impl(PyObject *module) /*[clinic end generated code: output=362616ee8ed1b2b1 input=e083b81c8eb4bac3]*/ { - return Py_NewRef(readlinestate_global->begidx); + readlinestate *state = get_readline_state(module); + return Py_NewRef(state->begidx); } /* Get the ending index for the scope of the tab-completion */ @@ -546,7 +560,8 @@ static PyObject * readline_get_endidx_impl(PyObject *module) /*[clinic end generated code: output=7f763350b12d7517 input=d4c7e34a625fd770]*/ { - return Py_NewRef(readlinestate_global->endidx); + readlinestate *state = get_readline_state(module); + return Py_NewRef(state->endidx); } /* Set the tab-completion word-delimiters that readline uses */ @@ -577,6 +592,13 @@ readline_set_completer_delims(PyObject *module, PyObject *string) if (break_chars) { free(completer_word_break_characters); completer_word_break_characters = break_chars; +#ifdef WITH_EDITLINE + rl_basic_word_break_characters = break_chars; +#else + if (using_libedit_emulation) { + rl_basic_word_break_characters = break_chars; + } +#endif rl_completer_word_break_characters = break_chars; Py_RETURN_NONE; } @@ -773,7 +795,8 @@ static PyObject * readline_set_completer_impl(PyObject *module, PyObject *function) /*[clinic end generated code: output=171a2a60f81d3204 input=51e81e13118eb877]*/ { - return set_hook("completer", &readlinestate_global->completer, function); + readlinestate *state = get_readline_state(module); + return set_hook("completer", &state->completer, function); } /*[clinic input] @@ -786,10 +809,11 @@ static PyObject * readline_get_completer_impl(PyObject *module) /*[clinic end generated code: output=6e6bbd8226d14475 input=6457522e56d70d13]*/ { - if (readlinestate_global->completer == NULL) { + readlinestate *state = get_readline_state(module); + if (state->completer == NULL) { Py_RETURN_NONE; } - return Py_NewRef(readlinestate_global->completer); + return Py_NewRef(state->completer); } /* Private function to get current length of history. XXX It may be @@ -1001,7 +1025,7 @@ on_hook(PyObject *func) if (r == Py_None) result = 0; else { - result = _PyLong_AsInt(r); + result = PyLong_AsInt(r); if (result == -1 && PyErr_Occurred()) goto error; } @@ -1020,12 +1044,17 @@ static int #if defined(_RL_FUNCTION_TYPEDEF) on_startup_hook(void) #else -on_startup_hook(void) +on_startup_hook(const char *Py_UNUSED(text), int Py_UNUSED(state)) #endif { int r; PyGILState_STATE gilstate = PyGILState_Ensure(); - r = on_hook(readlinestate_global->startup_hook); + readlinestate *state = get_hook_module_state(); + if (state == NULL) { + PyGILState_Release(gilstate); + return -1; + } + r = on_hook(state->startup_hook); PyGILState_Release(gilstate); return r; } @@ -1035,12 +1064,17 @@ static int #if defined(_RL_FUNCTION_TYPEDEF) on_pre_input_hook(void) #else -on_pre_input_hook(void) +on_pre_input_hook(const char *Py_UNUSED(text), int Py_UNUSED(state)) #endif { int r; PyGILState_STATE gilstate = PyGILState_Ensure(); - r = on_hook(readlinestate_global->pre_input_hook); + readlinestate *state = get_hook_module_state(); + if (state == NULL) { + PyGILState_Release(gilstate); + return -1; + } + r = on_hook(state->pre_input_hook); PyGILState_Release(gilstate); return r; } @@ -1057,6 +1091,11 @@ on_completion_display_matches_hook(char **matches, int i; PyObject *sub, *m=NULL, *s=NULL, *r=NULL; PyGILState_STATE gilstate = PyGILState_Ensure(); + readlinestate *state = get_hook_module_state(); + if (state == NULL) { + PyGILState_Release(gilstate); + return; + } m = PyList_New(num_matches); if (m == NULL) goto error; @@ -1067,7 +1106,7 @@ on_completion_display_matches_hook(char **matches, PyList_SET_ITEM(m, i, s); } sub = decode(matches[0]); - r = PyObject_CallFunction(readlinestate_global->completion_display_matches_hook, + r = PyObject_CallFunction(state->completion_display_matches_hook, "NNi", sub, m, max_length); m=NULL; @@ -1115,12 +1154,17 @@ static char * on_completion(const char *text, int state) { char *result = NULL; - if (readlinestate_global->completer != NULL) { + PyGILState_STATE gilstate = PyGILState_Ensure(); + readlinestate *module_state = get_hook_module_state(); + if (module_state == NULL) { + PyGILState_Release(gilstate); + return NULL; + } + if (module_state->completer != NULL) { PyObject *r = NULL, *t; - PyGILState_STATE gilstate = PyGILState_Ensure(); rl_attempted_completion_over = 1; t = decode(text); - r = PyObject_CallFunction(readlinestate_global->completer, "Ni", t, state); + r = PyObject_CallFunction(module_state->completer, "Ni", t, state); if (r == NULL) goto error; if (r == Py_None) { @@ -1142,6 +1186,7 @@ on_completion(const char *text, int state) PyGILState_Release(gilstate); return result; } + PyGILState_Release(gilstate); return result; } @@ -1157,6 +1202,7 @@ flex_complete(const char *text, int start, int end) size_t start_size, end_size; wchar_t *s; PyGILState_STATE gilstate = PyGILState_Ensure(); + readlinestate *state = get_hook_module_state(); #ifdef HAVE_RL_COMPLETION_APPEND_CHARACTER rl_completion_append_character ='\0'; #endif @@ -1184,10 +1230,12 @@ flex_complete(const char *text, int start, int end) end = start + (int)end_size; done: - Py_XDECREF(readlinestate_global->begidx); - Py_XDECREF(readlinestate_global->endidx); - readlinestate_global->begidx = PyLong_FromLong((long) start); - readlinestate_global->endidx = PyLong_FromLong((long) end); + if (state) { + Py_XDECREF(state->begidx); + Py_XDECREF(state->endidx); + state->begidx = PyLong_FromLong((long) start); + state->endidx = PyLong_FromLong((long) end); + } result = completion_matches((char *)text, *on_completion); PyGILState_Release(gilstate); return result; @@ -1264,6 +1312,15 @@ setup_readline(readlinestate *mod_state) completer_word_break_characters = strdup(" \t\n`~!@#$%^&*()-=+[{]}\\|;:'\",<>/?"); /* All nonalphanums except '.' */ +#ifdef WITH_EDITLINE + // libedit uses rl_basic_word_break_characters instead of + // rl_completer_word_break_characters as complete delimiter + rl_basic_word_break_characters = completer_word_break_characters; +#else + if (using_libedit_emulation) { + rl_basic_word_break_characters = completer_word_break_characters; + } +#endif rl_completer_word_break_characters = completer_word_break_characters; mod_state->begidx = PyLong_FromLong(0L); @@ -1333,7 +1390,8 @@ readline_until_enter_or_signal(const char *prompt, int *signal) int has_input = 0, err = 0; while (!has_input) - { struct timeval timeout = {0, 100000}; /* 0.1 seconds */ + { + struct timeval timeout = {0, 100000}; // 100 ms (0.1 seconds) /* [Bug #1552726] Only limit the pause if an input hook has been defined. */ @@ -1476,6 +1534,7 @@ static struct PyModuleDef readlinemodule = { PyMODINIT_FUNC PyInit_readline(void) { + const char *backend = "readline"; PyObject *m; readlinestate *mod_state; @@ -1483,8 +1542,10 @@ PyInit_readline(void) using_libedit_emulation = 1; } - if (using_libedit_emulation) + if (using_libedit_emulation) { readlinemodule.m_doc = doc_module_le; + backend = "editline"; + } m = PyModule_Create(&readlinemodule); @@ -1506,13 +1567,22 @@ PyInit_readline(void) goto error; } + if (PyModule_AddStringConstant(m, "backend", backend) < 0) { + goto error; + } + mod_state = (readlinestate *) PyModule_GetState(m); + if (mod_state == NULL){ + goto error; + } PyOS_ReadlineFunctionPointer = call_readline; if (setup_readline(mod_state) < 0) { PyErr_NoMemory(); goto error; } - + if (PyErr_Occurred()){ + goto error; + } return m; error: diff --git a/Modules/resource.c b/Modules/resource.c index 4614f5e98cc888..19020b8cc1b6db 100644 --- a/Modules/resource.c +++ b/Modules/resource.c @@ -1,13 +1,15 @@ +#include "pyconfig.h" // Py_GIL_DISABLED -#include "Python.h" -#include -#ifdef HAVE_SYS_TIME_H -#include +#ifndef Py_GIL_DISABLED +// Need limited C API version 3.13 for PySys_Audit() +#define Py_LIMITED_API 0x030d0000 #endif -#include + +#include "Python.h" +#include // errno #include -#include -#include +#include // getrusage() +#include // getpagesize() /* On some systems, these aren't in any header file. On others they are, with inconsistent prototypes. @@ -28,15 +30,16 @@ class pid_t_converter(CConverter): type = 'pid_t' format_unit = '" _Py_PARSE_PID "' - def parse_arg(self, argname, displayname): - return """ + def parse_arg(self, argname, displayname, *, limited_capi): + return self.format_code(""" {paramname} = PyLong_AsPid({argname}); if ({paramname} == -1 && PyErr_Occurred()) {{{{ goto exit; }}}} - """.format(argname=argname, paramname=self.parser_name) + """, + argname=argname) [python start generated code]*/ -/*[python end generated code: output=da39a3ee5e6b4b0d input=5af1c116d56cbb5a]*/ +/*[python end generated code: output=da39a3ee5e6b4b0d input=c94349aa1aad151d]*/ #include "clinic/resource.c.h" @@ -120,24 +123,24 @@ resource_getrusage_impl(PyObject *module, int who) if (!result) return NULL; - PyStructSequence_SET_ITEM(result, 0, + PyStructSequence_SetItem(result, 0, PyFloat_FromDouble(doubletime(ru.ru_utime))); - PyStructSequence_SET_ITEM(result, 1, + PyStructSequence_SetItem(result, 1, PyFloat_FromDouble(doubletime(ru.ru_stime))); - PyStructSequence_SET_ITEM(result, 2, PyLong_FromLong(ru.ru_maxrss)); - PyStructSequence_SET_ITEM(result, 3, PyLong_FromLong(ru.ru_ixrss)); - PyStructSequence_SET_ITEM(result, 4, PyLong_FromLong(ru.ru_idrss)); - PyStructSequence_SET_ITEM(result, 5, PyLong_FromLong(ru.ru_isrss)); - PyStructSequence_SET_ITEM(result, 6, PyLong_FromLong(ru.ru_minflt)); - PyStructSequence_SET_ITEM(result, 7, PyLong_FromLong(ru.ru_majflt)); - PyStructSequence_SET_ITEM(result, 8, PyLong_FromLong(ru.ru_nswap)); - PyStructSequence_SET_ITEM(result, 9, PyLong_FromLong(ru.ru_inblock)); - PyStructSequence_SET_ITEM(result, 10, PyLong_FromLong(ru.ru_oublock)); - PyStructSequence_SET_ITEM(result, 11, PyLong_FromLong(ru.ru_msgsnd)); - PyStructSequence_SET_ITEM(result, 12, PyLong_FromLong(ru.ru_msgrcv)); - PyStructSequence_SET_ITEM(result, 13, PyLong_FromLong(ru.ru_nsignals)); - PyStructSequence_SET_ITEM(result, 14, PyLong_FromLong(ru.ru_nvcsw)); - PyStructSequence_SET_ITEM(result, 15, PyLong_FromLong(ru.ru_nivcsw)); + PyStructSequence_SetItem(result, 2, PyLong_FromLong(ru.ru_maxrss)); + PyStructSequence_SetItem(result, 3, PyLong_FromLong(ru.ru_ixrss)); + PyStructSequence_SetItem(result, 4, PyLong_FromLong(ru.ru_idrss)); + PyStructSequence_SetItem(result, 5, PyLong_FromLong(ru.ru_isrss)); + PyStructSequence_SetItem(result, 6, PyLong_FromLong(ru.ru_minflt)); + PyStructSequence_SetItem(result, 7, PyLong_FromLong(ru.ru_majflt)); + PyStructSequence_SetItem(result, 8, PyLong_FromLong(ru.ru_nswap)); + PyStructSequence_SetItem(result, 9, PyLong_FromLong(ru.ru_inblock)); + PyStructSequence_SetItem(result, 10, PyLong_FromLong(ru.ru_oublock)); + PyStructSequence_SetItem(result, 11, PyLong_FromLong(ru.ru_msgsnd)); + PyStructSequence_SetItem(result, 12, PyLong_FromLong(ru.ru_msgrcv)); + PyStructSequence_SetItem(result, 13, PyLong_FromLong(ru.ru_nsignals)); + PyStructSequence_SetItem(result, 14, PyLong_FromLong(ru.ru_nvcsw)); + PyStructSequence_SetItem(result, 15, PyLong_FromLong(ru.ru_nivcsw)); if (PyErr_Occurred()) { Py_DECREF(result); @@ -157,13 +160,13 @@ py2rlimit(PyObject *limits, struct rlimit *rl_out) /* Here limits is a borrowed reference */ return -1; - if (PyTuple_GET_SIZE(limits) != 2) { + if (PyTuple_Size(limits) != 2) { PyErr_SetString(PyExc_ValueError, "expected a tuple of 2 integers"); goto error; } - curobj = PyTuple_GET_ITEM(limits, 0); - maxobj = PyTuple_GET_ITEM(limits, 1); + curobj = PyTuple_GetItem(limits, 0); // borrowed + maxobj = PyTuple_GetItem(limits, 1); // borrowed #if !defined(HAVE_LARGEFILE_SUPPORT) rl_out->rlim_cur = PyLong_AsLong(curobj); if (rl_out->rlim_cur == (rlim_t)-1 && PyErr_Occurred()) diff --git a/Modules/selectmodule.c b/Modules/selectmodule.c index 94d246960f4410..1dbde3e9e6ca5d 100644 --- a/Modules/selectmodule.c +++ b/Modules/selectmodule.c @@ -14,9 +14,14 @@ #include "Python.h" #include "pycore_fileutils.h" // _Py_set_inheritable() +#include "pycore_import.h" // _PyImport_GetModuleAttrString() #include "pycore_time.h" // _PyTime_t +#include #include // offsetof() +#ifndef MS_WINDOWS +# include // close() +#endif #ifdef HAVE_SYS_DEVPOLL_H #include @@ -72,13 +77,26 @@ extern void bzero(void *, int); # define POLLPRI 0 #endif +#ifdef HAVE_KQUEUE +// Linked list to track kqueue objects with an open fd, so +// that we can invalidate them at fork; +typedef struct _kqueue_list_item { + struct kqueue_queue_Object *obj; + struct _kqueue_list_item *next; +} _kqueue_list_item, *_kqueue_list; +#endif + typedef struct { PyObject *close; PyTypeObject *poll_Type; PyTypeObject *devpoll_Type; PyTypeObject *pyEpoll_Type; +#ifdef HAVE_KQUEUE PyTypeObject *kqueue_event_Type; PyTypeObject *kqueue_queue_Type; + _kqueue_list kqueue_open_list; + bool kqueue_tracking_initialized; +#endif } _selectstate; static struct PyModuleDef selectmodule; @@ -1294,8 +1312,8 @@ newPyEpoll_Object(PyTypeObject *type, int sizehint, SOCKET fd) self->epfd = fd; } if (self->epfd < 0) { - Py_DECREF(self); PyErr_SetFromErrno(PyExc_OSError); + Py_DECREF(self); return NULL; } @@ -1751,7 +1769,7 @@ typedef struct { #define kqueue_event_Check(op, state) (PyObject_TypeCheck((op), state->kqueue_event_Type)) -typedef struct { +typedef struct kqueue_queue_Object { PyObject_HEAD SOCKET kqfd; /* kqueue control fd */ } kqueue_queue_Object; @@ -1937,6 +1955,107 @@ kqueue_queue_err_closed(void) return NULL; } +static PyObject* +kqueue_tracking_after_fork(PyObject *module) { + _selectstate *state = get_select_state(module); + _kqueue_list_item *item = state->kqueue_open_list; + state->kqueue_open_list = NULL; + while (item) { + // Safety: we hold the GIL, and references are removed from this list + // before the object is deallocated. + kqueue_queue_Object *obj = item->obj; + assert(obj->kqfd != -1); + obj->kqfd = -1; + _kqueue_list_item *next = item->next; + PyMem_Free(item); + item = next; + } + Py_RETURN_NONE; +} + +static PyMethodDef kqueue_tracking_after_fork_def = { + "kqueue_tracking_after_fork", (PyCFunction)kqueue_tracking_after_fork, + METH_NOARGS, "Invalidate open select.kqueue objects after fork." +}; + +static void +kqueue_tracking_init(PyObject *module) { + _selectstate *state = get_select_state(module); + assert(state->kqueue_open_list == NULL); + // Register a callback to invalidate kqueues with open fds after fork. + PyObject *register_at_fork = NULL, *cb = NULL, *args = NULL, + *kwargs = NULL, *result = NULL; + register_at_fork = _PyImport_GetModuleAttrString("posix", + "register_at_fork"); + if (register_at_fork == NULL) { + goto finally; + } + cb = PyCFunction_New(&kqueue_tracking_after_fork_def, module); + if (cb == NULL) { + goto finally; + } + args = PyTuple_New(0); + assert(args != NULL); + kwargs = Py_BuildValue("{sO}", "after_in_child", cb); + if (kwargs == NULL) { + goto finally; + } + result = PyObject_Call(register_at_fork, args, kwargs); + +finally: + if (PyErr_Occurred()) { + // There are a few reasons registration can fail, especially if someone + // touched posix.register_at_fork. But everything else still works so + // instead of raising we issue a warning and move along. + PyObject *exc = PyErr_GetRaisedException(); + PyObject *exctype = (PyObject*)Py_TYPE(exc); + PyErr_WarnFormat(PyExc_RuntimeWarning, 1, + "An exception of type %S was raised while registering an " + "after-fork handler for select.kqueue objects: %S", exctype, exc); + Py_DECREF(exc); + } + Py_XDECREF(register_at_fork); + Py_XDECREF(cb); + Py_XDECREF(args); + Py_XDECREF(kwargs); + Py_XDECREF(result); + state->kqueue_tracking_initialized = true; +} + +static int +kqueue_tracking_add(_selectstate *state, kqueue_queue_Object *self) { + if (!state->kqueue_tracking_initialized) { + kqueue_tracking_init(PyType_GetModule(Py_TYPE(self))); + } + assert(self->kqfd >= 0); + _kqueue_list_item *item = PyMem_New(_kqueue_list_item, 1); + if (item == NULL) { + PyErr_NoMemory(); + return -1; + } + item->obj = self; + item->next = state->kqueue_open_list; + state->kqueue_open_list = item; + return 0; +} + +static void +kqueue_tracking_remove(_selectstate *state, kqueue_queue_Object *self) { + _kqueue_list *listptr = &state->kqueue_open_list; + while (*listptr != NULL) { + _kqueue_list_item *item = *listptr; + if (item->obj == self) { + *listptr = item->next; + PyMem_Free(item); + return; + } + listptr = &item->next; + } + // The item should be in the list when we remove it, + // and it should only be removed once at close time. + assert(0); +} + static int kqueue_queue_internal_close(kqueue_queue_Object *self) { @@ -1944,6 +2063,8 @@ kqueue_queue_internal_close(kqueue_queue_Object *self) if (self->kqfd >= 0) { int kqfd = self->kqfd; self->kqfd = -1; + _selectstate *state = _selectstate_by_type(Py_TYPE(self)); + kqueue_tracking_remove(state, self); Py_BEGIN_ALLOW_THREADS if (close(kqfd) < 0) save_errno = errno; @@ -1973,8 +2094,8 @@ newKqueue_Object(PyTypeObject *type, SOCKET fd) self->kqfd = fd; } if (self->kqfd < 0) { - Py_DECREF(self); PyErr_SetFromErrno(PyExc_OSError); + Py_DECREF(self); return NULL; } @@ -1984,6 +2105,13 @@ newKqueue_Object(PyTypeObject *type, SOCKET fd) return NULL; } } + + _selectstate *state = _selectstate_by_type(type); + if (kqueue_tracking_add(state, self) < 0) { + Py_DECREF(self); + return NULL; + } + return (PyObject *)self; } @@ -2014,13 +2142,11 @@ select_kqueue_impl(PyTypeObject *type) } static void -kqueue_queue_dealloc(kqueue_queue_Object *self) +kqueue_queue_finalize(kqueue_queue_Object *self) { - PyTypeObject* type = Py_TYPE(self); + PyObject* error = PyErr_GetRaisedException(); kqueue_queue_internal_close(self); - freefunc kqueue_free = PyType_GetSlot(type, Py_tp_free); - kqueue_free((PyObject *)self); - Py_DECREF((PyObject *)type); + PyErr_SetRaisedException(error); } /*[clinic input] @@ -2354,11 +2480,11 @@ static PyMethodDef kqueue_queue_methods[] = { }; static PyType_Slot kqueue_queue_Type_slots[] = { - {Py_tp_dealloc, kqueue_queue_dealloc}, {Py_tp_doc, (void*)select_kqueue__doc__}, {Py_tp_getset, kqueue_queue_getsetlist}, {Py_tp_methods, kqueue_queue_methods}, {Py_tp_new, select_kqueue}, + {Py_tp_finalize, kqueue_queue_finalize}, {0, 0}, }; @@ -2403,8 +2529,11 @@ _select_traverse(PyObject *module, visitproc visit, void *arg) Py_VISIT(state->poll_Type); Py_VISIT(state->devpoll_Type); Py_VISIT(state->pyEpoll_Type); +#ifdef HAVE_KQUEUE Py_VISIT(state->kqueue_event_Type); Py_VISIT(state->kqueue_queue_Type); + // state->kqueue_open_list only holds borrowed refs +#endif return 0; } @@ -2417,8 +2546,10 @@ _select_clear(PyObject *module) Py_CLEAR(state->poll_Type); Py_CLEAR(state->devpoll_Type); Py_CLEAR(state->pyEpoll_Type); +#ifdef HAVE_KQUEUE Py_CLEAR(state->kqueue_event_Type); Py_CLEAR(state->kqueue_queue_Type); +#endif return 0; } @@ -2441,12 +2572,18 @@ _select_exec(PyObject *m) return -1; } +#define ADD_INT(VAL) do { \ + if (PyModule_AddIntConstant((m), #VAL, (VAL)) < 0) { \ + return -1; \ + } \ +} while (0) + #ifdef PIPE_BUF #ifdef HAVE_BROKEN_PIPE_BUF #undef PIPE_BUF #define PIPE_BUF 512 #endif - PyModule_AddIntMacro(m, PIPE_BUF); + ADD_INT(PIPE_BUF); #endif #if defined(HAVE_POLL) && !defined(HAVE_BROKEN_POLL) @@ -2465,31 +2602,31 @@ _select_exec(PyObject *m) return -1; } - PyModule_AddIntMacro(m, POLLIN); - PyModule_AddIntMacro(m, POLLPRI); - PyModule_AddIntMacro(m, POLLOUT); - PyModule_AddIntMacro(m, POLLERR); - PyModule_AddIntMacro(m, POLLHUP); - PyModule_AddIntMacro(m, POLLNVAL); + ADD_INT(POLLIN); + ADD_INT(POLLPRI); + ADD_INT(POLLOUT); + ADD_INT(POLLERR); + ADD_INT(POLLHUP); + ADD_INT(POLLNVAL); #ifdef POLLRDNORM - PyModule_AddIntMacro(m, POLLRDNORM); + ADD_INT(POLLRDNORM); #endif #ifdef POLLRDBAND - PyModule_AddIntMacro(m, POLLRDBAND); + ADD_INT(POLLRDBAND); #endif #ifdef POLLWRNORM - PyModule_AddIntMacro(m, POLLWRNORM); + ADD_INT(POLLWRNORM); #endif #ifdef POLLWRBAND - PyModule_AddIntMacro(m, POLLWRBAND); + ADD_INT(POLLWRBAND); #endif #ifdef POLLMSG - PyModule_AddIntMacro(m, POLLMSG); + ADD_INT(POLLMSG); #endif #ifdef POLLRDHUP /* Kernel 2.6.17+ */ - PyModule_AddIntMacro(m, POLLRDHUP); + ADD_INT(POLLRDHUP); #endif } #endif /* HAVE_POLL */ @@ -2512,46 +2649,57 @@ _select_exec(PyObject *m) return -1; } - PyModule_AddIntMacro(m, EPOLLIN); - PyModule_AddIntMacro(m, EPOLLOUT); - PyModule_AddIntMacro(m, EPOLLPRI); - PyModule_AddIntMacro(m, EPOLLERR); - PyModule_AddIntMacro(m, EPOLLHUP); + ADD_INT(EPOLLIN); + ADD_INT(EPOLLOUT); + ADD_INT(EPOLLPRI); + ADD_INT(EPOLLERR); + ADD_INT(EPOLLHUP); #ifdef EPOLLRDHUP /* Kernel 2.6.17 */ - PyModule_AddIntMacro(m, EPOLLRDHUP); + ADD_INT(EPOLLRDHUP); #endif - PyModule_AddIntMacro(m, EPOLLET); + ADD_INT(EPOLLET); #ifdef EPOLLONESHOT /* Kernel 2.6.2+ */ - PyModule_AddIntMacro(m, EPOLLONESHOT); + ADD_INT(EPOLLONESHOT); #endif #ifdef EPOLLEXCLUSIVE - PyModule_AddIntMacro(m, EPOLLEXCLUSIVE); + ADD_INT(EPOLLEXCLUSIVE); #endif #ifdef EPOLLRDNORM - PyModule_AddIntMacro(m, EPOLLRDNORM); + ADD_INT(EPOLLRDNORM); #endif #ifdef EPOLLRDBAND - PyModule_AddIntMacro(m, EPOLLRDBAND); + ADD_INT(EPOLLRDBAND); #endif #ifdef EPOLLWRNORM - PyModule_AddIntMacro(m, EPOLLWRNORM); + ADD_INT(EPOLLWRNORM); #endif #ifdef EPOLLWRBAND - PyModule_AddIntMacro(m, EPOLLWRBAND); + ADD_INT(EPOLLWRBAND); #endif #ifdef EPOLLMSG - PyModule_AddIntMacro(m, EPOLLMSG); + ADD_INT(EPOLLMSG); #endif #ifdef EPOLL_CLOEXEC - PyModule_AddIntMacro(m, EPOLL_CLOEXEC); + ADD_INT(EPOLL_CLOEXEC); #endif #endif /* HAVE_EPOLL */ +#undef ADD_INT + +#define ADD_INT_CONST(NAME, VAL) \ + do { \ + if (PyModule_AddIntConstant(m, NAME, VAL) < 0) { \ + return -1; \ + } \ + } while (0) + #ifdef HAVE_KQUEUE + state->kqueue_open_list = NULL; + state->kqueue_event_Type = (PyTypeObject *)PyType_FromModuleAndSpec( m, &kqueue_event_Type_spec, NULL); if (state->kqueue_event_Type == NULL) { @@ -2571,80 +2719,83 @@ _select_exec(PyObject *m) } /* event filters */ - PyModule_AddIntConstant(m, "KQ_FILTER_READ", EVFILT_READ); - PyModule_AddIntConstant(m, "KQ_FILTER_WRITE", EVFILT_WRITE); + ADD_INT_CONST("KQ_FILTER_READ", EVFILT_READ); + ADD_INT_CONST("KQ_FILTER_WRITE", EVFILT_WRITE); #ifdef EVFILT_AIO - PyModule_AddIntConstant(m, "KQ_FILTER_AIO", EVFILT_AIO); + ADD_INT_CONST("KQ_FILTER_AIO", EVFILT_AIO); #endif #ifdef EVFILT_VNODE - PyModule_AddIntConstant(m, "KQ_FILTER_VNODE", EVFILT_VNODE); + ADD_INT_CONST("KQ_FILTER_VNODE", EVFILT_VNODE); #endif #ifdef EVFILT_PROC - PyModule_AddIntConstant(m, "KQ_FILTER_PROC", EVFILT_PROC); + ADD_INT_CONST("KQ_FILTER_PROC", EVFILT_PROC); #endif #ifdef EVFILT_NETDEV - PyModule_AddIntConstant(m, "KQ_FILTER_NETDEV", EVFILT_NETDEV); + ADD_INT_CONST("KQ_FILTER_NETDEV", EVFILT_NETDEV); #endif #ifdef EVFILT_SIGNAL - PyModule_AddIntConstant(m, "KQ_FILTER_SIGNAL", EVFILT_SIGNAL); + ADD_INT_CONST("KQ_FILTER_SIGNAL", EVFILT_SIGNAL); #endif - PyModule_AddIntConstant(m, "KQ_FILTER_TIMER", EVFILT_TIMER); + ADD_INT_CONST("KQ_FILTER_TIMER", EVFILT_TIMER); /* event flags */ - PyModule_AddIntConstant(m, "KQ_EV_ADD", EV_ADD); - PyModule_AddIntConstant(m, "KQ_EV_DELETE", EV_DELETE); - PyModule_AddIntConstant(m, "KQ_EV_ENABLE", EV_ENABLE); - PyModule_AddIntConstant(m, "KQ_EV_DISABLE", EV_DISABLE); - PyModule_AddIntConstant(m, "KQ_EV_ONESHOT", EV_ONESHOT); - PyModule_AddIntConstant(m, "KQ_EV_CLEAR", EV_CLEAR); + ADD_INT_CONST("KQ_EV_ADD", EV_ADD); + ADD_INT_CONST("KQ_EV_DELETE", EV_DELETE); + ADD_INT_CONST("KQ_EV_ENABLE", EV_ENABLE); + ADD_INT_CONST("KQ_EV_DISABLE", EV_DISABLE); + ADD_INT_CONST("KQ_EV_ONESHOT", EV_ONESHOT); + ADD_INT_CONST("KQ_EV_CLEAR", EV_CLEAR); #ifdef EV_SYSFLAGS - PyModule_AddIntConstant(m, "KQ_EV_SYSFLAGS", EV_SYSFLAGS); + ADD_INT_CONST("KQ_EV_SYSFLAGS", EV_SYSFLAGS); #endif #ifdef EV_FLAG1 - PyModule_AddIntConstant(m, "KQ_EV_FLAG1", EV_FLAG1); + ADD_INT_CONST("KQ_EV_FLAG1", EV_FLAG1); #endif - PyModule_AddIntConstant(m, "KQ_EV_EOF", EV_EOF); - PyModule_AddIntConstant(m, "KQ_EV_ERROR", EV_ERROR); + ADD_INT_CONST("KQ_EV_EOF", EV_EOF); + ADD_INT_CONST("KQ_EV_ERROR", EV_ERROR); /* READ WRITE filter flag */ #ifdef NOTE_LOWAT - PyModule_AddIntConstant(m, "KQ_NOTE_LOWAT", NOTE_LOWAT); + ADD_INT_CONST("KQ_NOTE_LOWAT", NOTE_LOWAT); #endif /* VNODE filter flags */ #ifdef EVFILT_VNODE - PyModule_AddIntConstant(m, "KQ_NOTE_DELETE", NOTE_DELETE); - PyModule_AddIntConstant(m, "KQ_NOTE_WRITE", NOTE_WRITE); - PyModule_AddIntConstant(m, "KQ_NOTE_EXTEND", NOTE_EXTEND); - PyModule_AddIntConstant(m, "KQ_NOTE_ATTRIB", NOTE_ATTRIB); - PyModule_AddIntConstant(m, "KQ_NOTE_LINK", NOTE_LINK); - PyModule_AddIntConstant(m, "KQ_NOTE_RENAME", NOTE_RENAME); - PyModule_AddIntConstant(m, "KQ_NOTE_REVOKE", NOTE_REVOKE); + ADD_INT_CONST("KQ_NOTE_DELETE", NOTE_DELETE); + ADD_INT_CONST("KQ_NOTE_WRITE", NOTE_WRITE); + ADD_INT_CONST("KQ_NOTE_EXTEND", NOTE_EXTEND); + ADD_INT_CONST("KQ_NOTE_ATTRIB", NOTE_ATTRIB); + ADD_INT_CONST("KQ_NOTE_LINK", NOTE_LINK); + ADD_INT_CONST("KQ_NOTE_RENAME", NOTE_RENAME); + ADD_INT_CONST("KQ_NOTE_REVOKE", NOTE_REVOKE); #endif /* PROC filter flags */ #ifdef EVFILT_PROC - PyModule_AddIntConstant(m, "KQ_NOTE_EXIT", NOTE_EXIT); - PyModule_AddIntConstant(m, "KQ_NOTE_FORK", NOTE_FORK); - PyModule_AddIntConstant(m, "KQ_NOTE_EXEC", NOTE_EXEC); - PyModule_AddIntConstant(m, "KQ_NOTE_PCTRLMASK", NOTE_PCTRLMASK); - PyModule_AddIntConstant(m, "KQ_NOTE_PDATAMASK", NOTE_PDATAMASK); - - PyModule_AddIntConstant(m, "KQ_NOTE_TRACK", NOTE_TRACK); - PyModule_AddIntConstant(m, "KQ_NOTE_CHILD", NOTE_CHILD); - PyModule_AddIntConstant(m, "KQ_NOTE_TRACKERR", NOTE_TRACKERR); + ADD_INT_CONST("KQ_NOTE_EXIT", NOTE_EXIT); + ADD_INT_CONST("KQ_NOTE_FORK", NOTE_FORK); + ADD_INT_CONST("KQ_NOTE_EXEC", NOTE_EXEC); + ADD_INT_CONST("KQ_NOTE_PCTRLMASK", NOTE_PCTRLMASK); + ADD_INT_CONST("KQ_NOTE_PDATAMASK", NOTE_PDATAMASK); + + ADD_INT_CONST("KQ_NOTE_TRACK", NOTE_TRACK); + ADD_INT_CONST("KQ_NOTE_CHILD", NOTE_CHILD); + ADD_INT_CONST("KQ_NOTE_TRACKERR", NOTE_TRACKERR); #endif /* NETDEV filter flags */ #ifdef EVFILT_NETDEV - PyModule_AddIntConstant(m, "KQ_NOTE_LINKUP", NOTE_LINKUP); - PyModule_AddIntConstant(m, "KQ_NOTE_LINKDOWN", NOTE_LINKDOWN); - PyModule_AddIntConstant(m, "KQ_NOTE_LINKINV", NOTE_LINKINV); + ADD_INT_CONST("KQ_NOTE_LINKUP", NOTE_LINKUP); + ADD_INT_CONST("KQ_NOTE_LINKDOWN", NOTE_LINKDOWN); + ADD_INT_CONST("KQ_NOTE_LINKINV", NOTE_LINKINV); #endif #endif /* HAVE_KQUEUE */ + +#undef ADD_INT_CONST + return 0; } diff --git a/Modules/sha1module.c b/Modules/sha1module.c index 3fd53123229ac4..eda6b5608d52f7 100644 --- a/Modules/sha1module.c +++ b/Modules/sha1module.c @@ -49,7 +49,8 @@ typedef long long SHA1_INT64; /* 64-bit integer */ typedef struct { PyObject_HEAD // Prevents undefined behavior via multiple threads entering the C API. - // The lock will be NULL before threaded access has been enabled. + bool use_mutex; + PyMutex mutex; PyThread_type_lock lock; Hacl_Streaming_SHA1_state *hash_state; } SHA1object; @@ -76,7 +77,8 @@ newSHA1object(SHA1State *st) if (sha == NULL) { return NULL; } - sha->lock = NULL; + HASHLIB_INIT_MUTEX(sha); + PyObject_GC_Track(sha); return sha; } @@ -94,9 +96,6 @@ static void SHA1_dealloc(SHA1object *ptr) { Hacl_Streaming_SHA1_legacy_free(ptr->hash_state); - if (ptr->lock != NULL) { - PyThread_free_lock(ptr->lock); - } PyTypeObject *tp = Py_TYPE(ptr); PyObject_GC_UnTrack(ptr); PyObject_GC_Del(ptr); @@ -192,14 +191,14 @@ SHA1Type_update(SHA1object *self, PyObject *obj) GET_BUFFER_VIEW_OR_ERROUT(obj, &buf); - if (self->lock == NULL && buf.len >= HASHLIB_GIL_MINSIZE) { - self->lock = PyThread_allocate_lock(); + if (!self->use_mutex && buf.len >= HASHLIB_GIL_MINSIZE) { + self->use_mutex = true; } - if (self->lock != NULL) { + if (self->use_mutex) { Py_BEGIN_ALLOW_THREADS - PyThread_acquire_lock(self->lock, 1); + PyMutex_Lock(&self->mutex); update(self->hash_state, buf.buf, buf.len); - PyThread_release_lock(self->lock); + PyMutex_Unlock(&self->mutex); Py_END_ALLOW_THREADS } else { update(self->hash_state, buf.buf, buf.len); diff --git a/Modules/sha2module.c b/Modules/sha2module.c index 6ad1ff2e05bfd8..968493ba51b50d 100644 --- a/Modules/sha2module.c +++ b/Modules/sha2module.c @@ -53,8 +53,8 @@ typedef struct { PyObject_HEAD int digestsize; // Prevents undefined behavior via multiple threads entering the C API. - // The lock will be NULL before threaded access has been enabled. - PyThread_type_lock lock; + bool use_mutex; + PyMutex mutex; Hacl_Streaming_SHA2_state_sha2_256 *state; } SHA256object; @@ -62,8 +62,8 @@ typedef struct { PyObject_HEAD int digestsize; // Prevents undefined behavior via multiple threads entering the C API. - // The lock will be NULL before threaded access has been enabled. - PyThread_type_lock lock; + bool use_mutex; + PyMutex mutex; Hacl_Streaming_SHA2_state_sha2_512 *state; } SHA512object; @@ -106,7 +106,8 @@ newSHA224object(sha2_state *state) if (!sha) { return NULL; } - sha->lock = NULL; + HASHLIB_INIT_MUTEX(sha); + PyObject_GC_Track(sha); return sha; } @@ -119,7 +120,8 @@ newSHA256object(sha2_state *state) if (!sha) { return NULL; } - sha->lock = NULL; + HASHLIB_INIT_MUTEX(sha); + PyObject_GC_Track(sha); return sha; } @@ -132,7 +134,8 @@ newSHA384object(sha2_state *state) if (!sha) { return NULL; } - sha->lock = NULL; + HASHLIB_INIT_MUTEX(sha); + PyObject_GC_Track(sha); return sha; } @@ -145,7 +148,8 @@ newSHA512object(sha2_state *state) if (!sha) { return NULL; } - sha->lock = NULL; + HASHLIB_INIT_MUTEX(sha); + PyObject_GC_Track(sha); return sha; } @@ -163,9 +167,6 @@ static void SHA256_dealloc(SHA256object *ptr) { Hacl_Streaming_SHA2_free_256(ptr->state); - if (ptr->lock != NULL) { - PyThread_free_lock(ptr->lock); - } PyTypeObject *tp = Py_TYPE(ptr); PyObject_GC_UnTrack(ptr); PyObject_GC_Del(ptr); @@ -176,9 +177,6 @@ static void SHA512_dealloc(SHA512object *ptr) { Hacl_Streaming_SHA2_free_512(ptr->state); - if (ptr->lock != NULL) { - PyThread_free_lock(ptr->lock); - } PyTypeObject *tp = Py_TYPE(ptr); PyObject_GC_UnTrack(ptr); PyObject_GC_Del(ptr); @@ -376,14 +374,14 @@ SHA256Type_update(SHA256object *self, PyObject *obj) GET_BUFFER_VIEW_OR_ERROUT(obj, &buf); - if (self->lock == NULL && buf.len >= HASHLIB_GIL_MINSIZE) { - self->lock = PyThread_allocate_lock(); + if (!self->use_mutex && buf.len >= HASHLIB_GIL_MINSIZE) { + self->use_mutex = true; } - if (self->lock != NULL) { + if (self->use_mutex) { Py_BEGIN_ALLOW_THREADS - PyThread_acquire_lock(self->lock, 1); + PyMutex_Lock(&self->mutex); update_256(self->state, buf.buf, buf.len); - PyThread_release_lock(self->lock); + PyMutex_Unlock(&self->mutex); Py_END_ALLOW_THREADS } else { update_256(self->state, buf.buf, buf.len); @@ -410,14 +408,14 @@ SHA512Type_update(SHA512object *self, PyObject *obj) GET_BUFFER_VIEW_OR_ERROUT(obj, &buf); - if (self->lock == NULL && buf.len >= HASHLIB_GIL_MINSIZE) { - self->lock = PyThread_allocate_lock(); + if (!self->use_mutex && buf.len >= HASHLIB_GIL_MINSIZE) { + self->use_mutex = true; } - if (self->lock != NULL) { + if (self->use_mutex) { Py_BEGIN_ALLOW_THREADS - PyThread_acquire_lock(self->lock, 1); + PyMutex_Lock(&self->mutex); update_512(self->state, buf.buf, buf.len); - PyThread_release_lock(self->lock); + PyMutex_Unlock(&self->mutex); Py_END_ALLOW_THREADS } else { update_512(self->state, buf.buf, buf.len); diff --git a/Modules/sha3module.c b/Modules/sha3module.c index 558d2005cff617..d9d2f6c385a68b 100644 --- a/Modules/sha3module.c +++ b/Modules/sha3module.c @@ -61,8 +61,8 @@ class _sha3.shake_256 "SHA3object *" "&SHAKE256type" typedef struct { PyObject_HEAD // Prevents undefined behavior via multiple threads entering the C API. - // The lock will be NULL before threaded access has been enabled. - PyThread_type_lock lock; + bool use_mutex; + PyMutex mutex; Hacl_Streaming_Keccak_state *hash_state; } SHA3object; @@ -76,7 +76,8 @@ newSHA3object(PyTypeObject *type) if (newobj == NULL) { return NULL; } - newobj->lock = NULL; + HASHLIB_INIT_MUTEX(newobj); + return newobj; } @@ -169,9 +170,6 @@ static void SHA3_dealloc(SHA3object *self) { Hacl_Streaming_Keccak_free(self->hash_state); - if (self->lock != NULL) { - PyThread_free_lock(self->lock); - } PyTypeObject *tp = Py_TYPE(self); PyObject_Free(self); Py_DECREF(tp); @@ -257,19 +255,22 @@ _sha3_sha3_224_update(SHA3object *self, PyObject *data) /*[clinic end generated code: output=d3223352286ed357 input=a887f54dcc4ae227]*/ { Py_buffer buf; + GET_BUFFER_VIEW_OR_ERROUT(data, &buf); - if (self->lock == NULL && buf.len >= HASHLIB_GIL_MINSIZE) { - self->lock = PyThread_allocate_lock(); + + if (!self->use_mutex && buf.len >= HASHLIB_GIL_MINSIZE) { + self->use_mutex = true; } - if (self->lock != NULL) { + if (self->use_mutex) { Py_BEGIN_ALLOW_THREADS - PyThread_acquire_lock(self->lock, 1); + PyMutex_Lock(&self->mutex); sha3_update(self->hash_state, buf.buf, buf.len); - PyThread_release_lock(self->lock); + PyMutex_Unlock(&self->mutex); Py_END_ALLOW_THREADS } else { sha3_update(self->hash_state, buf.buf, buf.len); } + PyBuffer_Release(&buf); Py_RETURN_NONE; } diff --git a/Modules/signalmodule.c b/Modules/signalmodule.c index 3adb2e8dfe58d8..394a997b20c06d 100644 --- a/Modules/signalmodule.c +++ b/Modules/signalmodule.c @@ -4,7 +4,6 @@ /* XXX Signals should be recorded per thread, now we have thread state. */ #include "Python.h" -#include "pycore_atomic.h" // _Py_atomic_int #include "pycore_call.h" // _PyObject_Call() #include "pycore_ceval.h" // _PyEval_SignalReceived() #include "pycore_emscripten_signal.h" // _Py_CHECK_EMSCRIPTEN_SIGNALS @@ -16,12 +15,15 @@ #include "pycore_signal.h" // _Py_RestoreSignals() #ifndef MS_WINDOWS -# include "posixmodule.h" +# include "posixmodule.h" // _PyLong_FromUid() #endif #ifdef MS_WINDOWS -# include "socketmodule.h" /* needed for SOCKET_T */ +# include "socketmodule.h" // SOCKET_T #endif +#ifdef HAVE_UNISTD_H +# include // alarm() +#endif #ifdef MS_WINDOWS # ifdef HAVE_PROCESS_H # include @@ -29,16 +31,16 @@ #endif #ifdef HAVE_SIGNAL_H -# include +# include // sigaction() #endif #ifdef HAVE_SYS_SYSCALL_H -# include +# include // __NR_pidfd_send_signal #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef HAVE_SYS_TIME_H -# include +# include // setitimer() #endif #if defined(HAVE_PTHREAD_SIGMASK) && !defined(HAVE_BROKEN_PTHREAD_SIGMASK) @@ -124,13 +126,15 @@ typedef struct { Py_LOCAL_INLINE(PyObject *) get_handler(int i) { - return (PyObject *)_Py_atomic_load(&Handlers[i].func); + return (PyObject *)_Py_atomic_load_ptr(&Handlers[i].func); } Py_LOCAL_INLINE(void) set_handler(int i, PyObject* func) { - _Py_atomic_store(&Handlers[i].func, (uintptr_t)func); + /* Store func with atomic operation to ensure + that PyErr_SetInterrupt is async-signal-safe. */ + _Py_atomic_store_ptr(&Handlers[i].func, func); } @@ -240,8 +244,7 @@ report_wakeup_write_error(void *data) errno = (int) (intptr_t) data; PyObject *exc = PyErr_GetRaisedException(); PyErr_SetFromErrno(PyExc_OSError); - _PyErr_WriteUnraisableMsg("when trying to write to the signal wakeup fd", - NULL); + PyErr_FormatUnraisable("Exception ignored when trying to write to the signal wakeup fd"); PyErr_SetRaisedException(exc); errno = save_errno; return 0; @@ -258,7 +261,7 @@ report_wakeup_send_error(void* data) recognizes the error codes used by both GetLastError() and WSAGetLastError */ PyErr_SetExcFromWindowsErr(PyExc_OSError, send_errno); - _PyErr_WriteUnraisableMsg("when trying to send to the signal wakeup fd", NULL); + PyErr_FormatUnraisable("Exception ignored when trying to send to the signal wakeup fd"); PyErr_SetRaisedException(exc); return 0; } @@ -267,11 +270,11 @@ report_wakeup_send_error(void* data) static void trip_signal(int sig_num) { - _Py_atomic_store_relaxed(&Handlers[sig_num].tripped, 1); + _Py_atomic_store_int(&Handlers[sig_num].tripped, 1); /* Set is_tripped after setting .tripped, as it gets cleared in PyErr_CheckSignals() before .tripped. */ - _Py_atomic_store(&is_tripped, 1); + _Py_atomic_store_int(&is_tripped, 1); /* Signals are always handled by the main interpreter */ PyInterpreterState *interp = _PyInterpreterState_Main(); @@ -315,7 +318,7 @@ trip_signal(int sig_num) _PyEval_AddPendingCall(interp, report_wakeup_send_error, (void *)(intptr_t) last_error, - 1); + _Py_PENDING_MAINTHREADONLY); } } } @@ -335,7 +338,7 @@ trip_signal(int sig_num) _PyEval_AddPendingCall(interp, report_wakeup_write_error, (void *)(intptr_t)errno, - 1); + _Py_PENDING_MAINTHREADONLY); } } } @@ -656,7 +659,7 @@ signal_strsignal_impl(PyObject *module, int signalnum) Py_RETURN_NONE; #endif - return Py_BuildValue("s", res); + return PyUnicode_FromString(res); } #ifdef HAVE_SIGINTERRUPT @@ -1731,7 +1734,7 @@ _PySignal_Fini(void) // Restore default signals and clear handlers for (int signum = 1; signum < Py_NSIG; signum++) { PyObject *func = get_handler(signum); - _Py_atomic_store_relaxed(&Handlers[signum].tripped, 0); + _Py_atomic_store_int_relaxed(&Handlers[signum].tripped, 0); set_handler(signum, NULL); if (func != NULL && func != Py_None @@ -1767,9 +1770,8 @@ PyErr_CheckSignals(void) Python code to ensure signals are handled. Checking for the GC here allows long running native code to clean cycles created using the C-API even if it doesn't run the evaluation loop */ - struct _ceval_state *interp_ceval_state = &tstate->interp->ceval; - if (_Py_atomic_load_relaxed(&interp_ceval_state->gc_scheduled)) { - _Py_atomic_store_relaxed(&interp_ceval_state->gc_scheduled, 0); + if (_Py_eval_breaker_bit_is_set(tstate->interp, _PY_GC_SCHEDULED_BIT)) { + _Py_set_eval_breaker_bit(tstate->interp, _PY_GC_SCHEDULED_BIT, 0); _Py_RunGC(tstate); } @@ -1786,7 +1788,7 @@ int _PyErr_CheckSignalsTstate(PyThreadState *tstate) { _Py_CHECK_EMSCRIPTEN_SIGNALS(); - if (!_Py_atomic_load(&is_tripped)) { + if (!_Py_atomic_load_int(&is_tripped)) { return 0; } @@ -1804,15 +1806,15 @@ _PyErr_CheckSignalsTstate(PyThreadState *tstate) * we receive a signal i after we zero is_tripped and before we * check Handlers[i].tripped. */ - _Py_atomic_store(&is_tripped, 0); + _Py_atomic_store_int(&is_tripped, 0); _PyInterpreterFrame *frame = _PyThreadState_GetFrame(tstate); signal_state_t *state = &signal_global_state; for (int i = 1; i < Py_NSIG; i++) { - if (!_Py_atomic_load_relaxed(&Handlers[i].tripped)) { + if (!_Py_atomic_load_int_relaxed(&Handlers[i].tripped)) { continue; } - _Py_atomic_store_relaxed(&Handlers[i].tripped, 0); + _Py_atomic_store_int_relaxed(&Handlers[i].tripped, 0); /* Signal handlers can be modified while a signal is received, * and therefore the fact that trip_signal() or PyErr_SetInterrupt() @@ -1858,7 +1860,7 @@ _PyErr_CheckSignalsTstate(PyThreadState *tstate) } if (!result) { /* On error, re-schedule a call to _PyErr_CheckSignalsTstate() */ - _Py_atomic_store(&is_tripped, 1); + _Py_atomic_store_int(&is_tripped, 1); return -1; } @@ -1976,7 +1978,7 @@ _PySignal_Init(int install_signal_handlers) #endif for (int signum = 1; signum < Py_NSIG; signum++) { - _Py_atomic_store_relaxed(&Handlers[signum].tripped, 0); + _Py_atomic_store_int_relaxed(&Handlers[signum].tripped, 0); } if (install_signal_handlers) { @@ -1998,11 +2000,11 @@ _PyOS_InterruptOccurred(PyThreadState *tstate) return 0; } - if (!_Py_atomic_load_relaxed(&Handlers[SIGINT].tripped)) { + if (!_Py_atomic_load_int_relaxed(&Handlers[SIGINT].tripped)) { return 0; } - _Py_atomic_store_relaxed(&Handlers[SIGINT].tripped, 0); + _Py_atomic_store_int_relaxed(&Handlers[SIGINT].tripped, 0); return 1; } @@ -2020,13 +2022,13 @@ PyOS_InterruptOccurred(void) static void _clear_pending_signals(void) { - if (!_Py_atomic_load(&is_tripped)) { + if (!_Py_atomic_load_int(&is_tripped)) { return; } - _Py_atomic_store(&is_tripped, 0); + _Py_atomic_store_int(&is_tripped, 0); for (int i = 1; i < Py_NSIG; ++i) { - _Py_atomic_store_relaxed(&Handlers[i].tripped, 0); + _Py_atomic_store_int_relaxed(&Handlers[i].tripped, 0); } } diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index bb5edc368decb3..0a0e0e78656f76 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -106,12 +106,12 @@ Local naming conventions: #endif #include "Python.h" +#include "pycore_capsule.h" // _PyCapsule_SetTraverse() #include "pycore_fileutils.h" // _Py_set_inheritable() #include "pycore_moduleobject.h" // _PyModule_GetState - #ifdef _Py_MEMORY_SANITIZER -# include +# include #endif /* Socket object documentation */ @@ -263,7 +263,7 @@ shutdown(how) -- shut down traffic in one or both directions\n\ #ifdef HAVE_NETDB_H # include #endif -# include +#include // close() /* Headers needed for inet_ntoa() and inet_addr() */ # include @@ -392,16 +392,10 @@ remove_unusable_flags(PyObject *m) break; } else { - PyObject *flag_name = PyUnicode_FromString(win_runtime_flags[i].flag_name); - if (flag_name == NULL) { - return -1; - } - PyObject *v = _PyDict_Pop(dict, flag_name, Py_None); - Py_DECREF(flag_name); - if (v == NULL) { + if (PyDict_PopString(dict, win_runtime_flags[i].flag_name, + NULL) < 0) { return -1; } - Py_DECREF(v); } } return 0; @@ -4878,17 +4872,17 @@ sock_sendmsg_afalg(PySocketSockObject *self, PyObject *args, PyObject *kwds) /* op is a required, keyword-only argument >= 0 */ if (opobj != NULL) { - op = _PyLong_AsInt(opobj); + op = PyLong_AsInt(opobj); } if (op < 0) { - /* override exception from _PyLong_AsInt() */ + /* override exception from PyLong_AsInt() */ PyErr_SetString(PyExc_TypeError, "Invalid or missing argument 'op'"); goto finally; } /* assoclen is optional but must be >= 0 */ if (assoclenobj != NULL) { - assoclen = _PyLong_AsInt(assoclenobj); + assoclen = PyLong_AsInt(assoclenobj); if (assoclen == -1 && PyErr_Occurred()) { goto finally; } @@ -5006,7 +5000,7 @@ sock_shutdown(PySocketSockObject *s, PyObject *arg) int how; int res; - how = _PyLong_AsInt(arg); + how = PyLong_AsInt(arg); if (how == -1 && PyErr_Occurred()) return NULL; Py_BEGIN_ALLOW_THREADS @@ -5397,8 +5391,8 @@ sock_initobj_impl(PySocketSockObject *self, int family, int type, int proto, } if (!SetHandleInformation((HANDLE)fd, HANDLE_FLAG_INHERIT, 0)) { - closesocket(fd); PyErr_SetFromWindowsErr(0); + closesocket(fd); return -1; } @@ -5612,8 +5606,9 @@ socket_gethostname(PyObject *self, PyObject *unused) name, &size)) { + PyErr_SetFromWindowsErr(0); PyMem_Free(name); - return PyErr_SetFromWindowsErr(0); + return NULL; } result = PyUnicode_FromWideChar(name, size); @@ -5650,8 +5645,9 @@ socket_sethostname(PyObject *self, PyObject *args) Py_buffer buf; int res, flag = 0; -#ifdef _AIX -/* issue #18259, not declared in any useful header file */ +#if defined(_AIX) || (defined(__sun) && defined(__SVR4) && Py_SUNOS_VERSION <= 510) +/* issue #18259, sethostname is not declared in any useful header file on AIX + * the same is true for Solaris 10 */ extern int sethostname(const char *, size_t); #endif @@ -6211,8 +6207,8 @@ socket_dup(PyObject *self, PyObject *fdobj) } if (!SetHandleInformation((HANDLE)newfd, HANDLE_FLAG_INHERIT, 0)) { - closesocket(newfd); PyErr_SetFromWindowsErr(0); + closesocket(newfd); return NULL; } #else @@ -6330,14 +6326,18 @@ AF_UNIX if defined on the platform; otherwise, the default is AF_INET."); #endif /* HAVE_SOCKETPAIR */ +/*[clinic input] +_socket.socket.ntohs + x: int + / + +Convert a 16-bit unsigned integer from network to host byte order. +[clinic start generated code]*/ + static PyObject * -socket_ntohs(PyObject *self, PyObject *args) +_socket_socket_ntohs_impl(PySocketSockObject *self, int x) +/*[clinic end generated code: output=a828a61a9fb205b2 input=9a79cb3a71652147]*/ { - int x; - - if (!PyArg_ParseTuple(args, "i:ntohs", &x)) { - return NULL; - } if (x < 0) { PyErr_SetString(PyExc_OverflowError, "ntohs: can't convert negative Python int to C " @@ -6353,11 +6353,6 @@ socket_ntohs(PyObject *self, PyObject *args) return PyLong_FromUnsignedLong(ntohs((unsigned short)x)); } -PyDoc_STRVAR(ntohs_doc, -"ntohs(integer) -> integer\n\ -\n\ -Convert a 16-bit unsigned integer from network to host byte order."); - static PyObject * socket_ntohl(PyObject *self, PyObject *arg) @@ -6393,14 +6388,18 @@ PyDoc_STRVAR(ntohl_doc, Convert a 32-bit integer from network to host byte order."); +/*[clinic input] +_socket.socket.htons + x: int + / + +Convert a 16-bit unsigned integer from host to network byte order. +[clinic start generated code]*/ + static PyObject * -socket_htons(PyObject *self, PyObject *args) +_socket_socket_htons_impl(PySocketSockObject *self, int x) +/*[clinic end generated code: output=d785ee692312da47 input=053252d8416f4337]*/ { - int x; - - if (!PyArg_ParseTuple(args, "i:htons", &x)) { - return NULL; - } if (x < 0) { PyErr_SetString(PyExc_OverflowError, "htons: can't convert negative Python int to C " @@ -6416,11 +6415,6 @@ socket_htons(PyObject *self, PyObject *args) return PyLong_FromUnsignedLong(htons((unsigned short)x)); } -PyDoc_STRVAR(htons_doc, -"htons(integer) -> integer\n\ -\n\ -Convert a 16-bit unsigned integer from host to network byte order."); - static PyObject * socket_htonl(PyObject *self, PyObject *arg) @@ -6457,14 +6451,17 @@ Convert a 32-bit integer from host to network byte order."); /* socket.inet_aton() and socket.inet_ntoa() functions. */ -PyDoc_STRVAR(inet_aton_doc, -"inet_aton(string) -> bytes giving packed 32-bit IP representation\n\ -\n\ -Convert an IP address in string format (123.45.67.89) to the 32-bit packed\n\ -binary format used in low-level network functions."); +/*[clinic input] +_socket.socket.inet_aton + ip_addr: str + / -static PyObject* -socket_inet_aton(PyObject *self, PyObject *args) +Convert an IP address in string format (123.45.67.89) to the 32-bit packed binary format used in low-level network functions. +[clinic start generated code]*/ + +static PyObject * +_socket_socket_inet_aton_impl(PySocketSockObject *self, const char *ip_addr) +/*[clinic end generated code: output=5bfe11a255423d8c input=a120e20cb52b9488]*/ { #ifdef HAVE_INET_ATON struct in_addr buf; @@ -6477,11 +6474,6 @@ socket_inet_aton(PyObject *self, PyObject *args) /* Have to use inet_addr() instead */ unsigned int packed_addr; #endif - const char *ip_addr; - - if (!PyArg_ParseTuple(args, "s:inet_aton", &ip_addr)) - return NULL; - #ifdef HAVE_INET_ATON @@ -6530,30 +6522,29 @@ socket_inet_aton(PyObject *self, PyObject *args) } #ifdef HAVE_INET_NTOA -PyDoc_STRVAR(inet_ntoa_doc, -"inet_ntoa(packed_ip) -> ip_address_string\n\ -\n\ -Convert an IP address from 32-bit packed binary format to string format"); +/*[clinic input] +_socket.socket.inet_ntoa + packed_ip: Py_buffer + / -static PyObject* -socket_inet_ntoa(PyObject *self, PyObject *args) +Convert an IP address from 32-bit packed binary format to string format. +[clinic start generated code]*/ + +static PyObject * +_socket_socket_inet_ntoa_impl(PySocketSockObject *self, Py_buffer *packed_ip) +/*[clinic end generated code: output=b671880a3f62461b input=95c2c4a1b2ee957c]*/ { - Py_buffer packed_ip; struct in_addr packed_addr; - if (!PyArg_ParseTuple(args, "y*:inet_ntoa", &packed_ip)) { - return NULL; - } - - if (packed_ip.len != sizeof(packed_addr)) { + if (packed_ip->len != sizeof(packed_addr)) { PyErr_SetString(PyExc_OSError, "packed IP wrong length for inet_ntoa"); - PyBuffer_Release(&packed_ip); + PyBuffer_Release(packed_ip); return NULL; } - memcpy(&packed_addr, packed_ip.buf, packed_ip.len); - PyBuffer_Release(&packed_ip); + memcpy(&packed_addr, packed_ip->buf, packed_ip->len); + PyBuffer_Release(packed_ip); SUPPRESS_DEPRECATED_CALL return PyUnicode_FromString(inet_ntoa(packed_addr)); @@ -6659,11 +6650,12 @@ socket_inet_ntop(PyObject *self, PyObject *args) /* inet_ntop guarantee NUL-termination of resulting string. */ retval = inet_ntop(af, packed_ip.buf, ip, sizeof(ip)); - PyBuffer_Release(&packed_ip); if (!retval) { PyErr_SetFromErrno(PyExc_OSError); + PyBuffer_Release(&packed_ip); return NULL; } else { + PyBuffer_Release(&packed_ip); return PyUnicode_FromString(retval); } } @@ -7002,8 +6994,8 @@ socket_if_nameindex(PyObject *self, PyObject *arg) ni = if_nameindex(); if (ni == NULL) { - Py_DECREF(list); PyErr_SetFromErrno(PyExc_OSError); + Py_DECREF(list); return NULL; } @@ -7046,18 +7038,23 @@ PyDoc_STRVAR(if_nameindex_doc, \n\ Returns a list of network interface information (index, name) tuples."); +/*[clinic input] +_socket.socket.if_nametoindex + oname: object(converter="PyUnicode_FSConverter") + / + +Returns the interface index corresponding to the interface name if_name. +[clinic start generated code]*/ + static PyObject * -socket_if_nametoindex(PyObject *self, PyObject *args) +_socket_socket_if_nametoindex_impl(PySocketSockObject *self, PyObject *oname) +/*[clinic end generated code: output=f7fc00511a309a8e input=662688054482cd46]*/ { - PyObject *oname; #ifdef MS_WINDOWS NET_IFINDEX index; #else unsigned long index; #endif - if (!PyArg_ParseTuple(args, "O&:if_nametoindex", - PyUnicode_FSConverter, &oname)) - return NULL; index = if_nametoindex(PyBytes_AS_STRING(oname)); Py_DECREF(oname); @@ -7070,25 +7067,27 @@ socket_if_nametoindex(PyObject *self, PyObject *args) return PyLong_FromUnsignedLong(index); } -PyDoc_STRVAR(if_nametoindex_doc, -"if_nametoindex(if_name)\n\ -\n\ -Returns the interface index corresponding to the interface name if_name."); static PyObject * socket_if_indextoname(PyObject *self, PyObject *arg) { + unsigned long index_long = PyLong_AsUnsignedLong(arg); + if (index_long == (unsigned long) -1 && PyErr_Occurred()) { + return NULL; + } + #ifdef MS_WINDOWS - NET_IFINDEX index; + NET_IFINDEX index = (NET_IFINDEX)index_long; #else - unsigned long index; + unsigned int index = (unsigned int)index_long; #endif - char name[IF_NAMESIZE + 1]; - index = PyLong_AsUnsignedLong(arg); - if (index == (unsigned long) -1) + if ((unsigned long)index != index_long) { + PyErr_SetString(PyExc_OverflowError, "index is too large"); return NULL; + } + char name[IF_NAMESIZE + 1]; if (if_indextoname(index, name) == NULL) { PyErr_SetFromErrno(PyExc_OSError); return NULL; @@ -7212,19 +7211,15 @@ static PyMethodDef socket_methods[] = { {"socketpair", socket_socketpair, METH_VARARGS, socketpair_doc}, #endif - {"ntohs", socket_ntohs, - METH_VARARGS, ntohs_doc}, + _SOCKET_SOCKET_NTOHS_METHODDEF {"ntohl", socket_ntohl, METH_O, ntohl_doc}, - {"htons", socket_htons, - METH_VARARGS, htons_doc}, + _SOCKET_SOCKET_HTONS_METHODDEF {"htonl", socket_htonl, METH_O, htonl_doc}, - {"inet_aton", socket_inet_aton, - METH_VARARGS, inet_aton_doc}, + _SOCKET_SOCKET_INET_ATON_METHODDEF #ifdef HAVE_INET_NTOA - {"inet_ntoa", socket_inet_ntoa, - METH_VARARGS, inet_ntoa_doc}, + _SOCKET_SOCKET_INET_NTOA_METHODDEF #endif #ifdef HAVE_INET_PTON {"inet_pton", socket_inet_pton, @@ -7247,8 +7242,7 @@ static PyMethodDef socket_methods[] = { #if defined(HAVE_IF_NAMEINDEX) || defined(MS_WINDOWS) {"if_nameindex", socket_if_nameindex, METH_NOARGS, if_nameindex_doc}, - {"if_nametoindex", socket_if_nametoindex, - METH_VARARGS, if_nametoindex_doc}, + _SOCKET_SOCKET_IF_NAMETOINDEX_METHODDEF {"if_indextoname", socket_if_indextoname, METH_O, if_indextoname_doc}, #endif @@ -7314,20 +7308,39 @@ os_init(void) } #endif +static int +sock_capi_traverse(PyObject *capsule, visitproc visit, void *arg) +{ + PySocketModule_APIObject *capi = PyCapsule_GetPointer(capsule, PySocket_CAPSULE_NAME); + assert(capi != NULL); + Py_VISIT(capi->Sock_Type); + return 0; +} + +static int +sock_capi_clear(PyObject *capsule) +{ + PySocketModule_APIObject *capi = PyCapsule_GetPointer(capsule, PySocket_CAPSULE_NAME); + assert(capi != NULL); + Py_CLEAR(capi->Sock_Type); + return 0; +} + static void -sock_free_api(PySocketModule_APIObject *capi) +sock_capi_free(PySocketModule_APIObject *capi) { - Py_DECREF(capi->Sock_Type); + Py_XDECREF(capi->Sock_Type); // sock_capi_free() can clear it Py_DECREF(capi->error); Py_DECREF(capi->timeout_error); PyMem_Free(capi); } static void -sock_destroy_api(PyObject *capsule) +sock_capi_destroy(PyObject *capsule) { void *capi = PyCapsule_GetPointer(capsule, PySocket_CAPSULE_NAME); - sock_free_api(capi); + assert(capi != NULL); + sock_capi_free(capi); } static PySocketModule_APIObject * @@ -7432,11 +7445,17 @@ socket_exec(PyObject *m) } PyObject *capsule = PyCapsule_New(capi, PySocket_CAPSULE_NAME, - sock_destroy_api); + sock_capi_destroy); if (capsule == NULL) { - sock_free_api(capi); + sock_capi_free(capi); + goto error; + } + if (_PyCapsule_SetTraverse(capsule, + sock_capi_traverse, sock_capi_clear) < 0) { + sock_capi_free(capi); goto error; } + if (PyModule_Add(m, PySocket_CAPI_NAME, capsule) < 0) { goto error; } @@ -7694,10 +7713,10 @@ socket_exec(PyObject *m) /* FreeBSD divert(4) */ #ifdef PF_DIVERT - PyModule_AddIntMacro(m, PF_DIVERT); + ADD_INT_MACRO(m, PF_DIVERT); #endif #ifdef AF_DIVERT - PyModule_AddIntMacro(m, AF_DIVERT); + ADD_INT_MACRO(m, AF_DIVERT); #endif #ifdef AF_PACKET @@ -8790,6 +8809,9 @@ socket_exec(PyObject *m) #ifdef NI_DGRAM ADD_INT_MACRO(m, NI_DGRAM); #endif +#ifdef NI_IDN + ADD_INT_MACRO(m, NI_IDN); +#endif /* shutdown() parameters */ #ifdef SHUT_RD diff --git a/Modules/socketmodule.h b/Modules/socketmodule.h index 663ae3d6e0dd6c..47146a28e02c8f 100644 --- a/Modules/socketmodule.h +++ b/Modules/socketmodule.h @@ -100,6 +100,8 @@ typedef int socklen_t; # include # endif # include +#elif defined(HAVE_NETLINK_NETLINK_H) +# include #else # undef AF_NETLINK #endif diff --git a/Modules/symtablemodule.c b/Modules/symtablemodule.c index 1cc319cc3410d8..ddc9ac3324356d 100644 --- a/Modules/symtablemodule.c +++ b/Modules/symtablemodule.c @@ -1,4 +1,5 @@ #include "Python.h" +#include "pycore_pythonrun.h" // _Py_SourceAsString() #include "pycore_symtable.h" // struct symtable #include "clinic/symtablemodule.c.h" @@ -85,6 +86,14 @@ symtable_init_constants(PyObject *m) if (PyModule_AddIntConstant(m, "TYPE_CLASS", ClassBlock) < 0) return -1; if (PyModule_AddIntConstant(m, "TYPE_MODULE", ModuleBlock) < 0) return -1; + if (PyModule_AddIntConstant(m, "TYPE_ANNOTATION", AnnotationBlock) < 0) + return -1; + if (PyModule_AddIntConstant(m, "TYPE_TYPE_VAR_BOUND", TypeVarBoundBlock) < 0) + return -1; + if (PyModule_AddIntConstant(m, "TYPE_TYPE_ALIAS", TypeAliasBlock) < 0) + return -1; + if (PyModule_AddIntConstant(m, "TYPE_TYPE_PARAM", TypeParamBlock) < 0) + return -1; if (PyModule_AddIntMacro(m, LOCAL) < 0) return -1; if (PyModule_AddIntMacro(m, GLOBAL_EXPLICIT) < 0) return -1; diff --git a/Modules/syslogmodule.c b/Modules/syslogmodule.c index 6db8de9c491dd9..62c7816f891ee2 100644 --- a/Modules/syslogmodule.c +++ b/Modules/syslogmodule.c @@ -49,6 +49,11 @@ Revision history: /* syslog module */ +// clinic/syslogmodule.c.h uses internal pycore_modsupport.h API +#ifndef Py_BUILD_CORE_BUILTIN +# define Py_BUILD_CORE_MODULE 1 +#endif + #include "Python.h" #include "osdefs.h" // SEP @@ -401,6 +406,30 @@ syslog_exec(PyObject *module) ADD_INT_MACRO(module, LOG_AUTHPRIV); #endif +#ifdef LOG_FTP + ADD_INT_MACRO(module, LOG_FTP); +#endif + +#ifdef LOG_NETINFO + ADD_INT_MACRO(module, LOG_NETINFO); +#endif + +#ifdef LOG_REMOTEAUTH + ADD_INT_MACRO(module, LOG_REMOTEAUTH); +#endif + +#ifdef LOG_INSTALL + ADD_INT_MACRO(module, LOG_INSTALL); +#endif + +#ifdef LOG_RAS + ADD_INT_MACRO(module, LOG_RAS); +#endif + +#ifdef LOG_LAUNCHD + ADD_INT_MACRO(module, LOG_LAUNCHD); +#endif + return 0; } diff --git a/Modules/termios.c b/Modules/termios.c index 6b254104ed1e21..c4f0fd9d50044a 100644 --- a/Modules/termios.c +++ b/Modules/termios.c @@ -1,11 +1,22 @@ /* termios.c -- POSIX terminal I/O module implementation. */ +#ifndef Py_BUILD_CORE_BUILTIN +# define Py_BUILD_CORE_MODULE 1 +#endif + #include "Python.h" -/* Apparently, on SGI, termios.h won't define CTRL if _XOPEN_SOURCE - is defined, so we define it here. */ +// On QNX 6, struct termio must be declared by including sys/termio.h +// if TCGETA, TCSETA, TCSETAW, or TCSETAF are used. sys/termio.h must +// be included before termios.h or it will generate an error. +#if defined(HAVE_SYS_TERMIO_H) && !defined(__hpux) +# include +#endif + +// Apparently, on SGI, termios.h won't define CTRL if _XOPEN_SOURCE +// is defined, so we define it here. #if defined(__sgi) -#define CTRL(c) ((c)&037) +# define CTRL(c) ((c)&037) #endif #if defined(__sun) @@ -16,6 +27,9 @@ #include #include +#if defined(__sun) && defined(__SVR4) +# include // ioctl() +#endif /* HP-UX requires that this be included to pick up MDCD, MCTS, MDSR, * MDTR, MRI, and MRTS (apparently used internally by some things @@ -106,7 +120,7 @@ termios_tcgetattr_impl(PyObject *module, int fd) v = PyBytes_FromStringAndSize(&ch, 1); if (v == NULL) goto err; - PyList_SetItem(cc, i, v); + PyList_SET_ITEM(cc, i, v); } /* Convert the MIN and TIME slots to integer. On some systems, the @@ -114,29 +128,44 @@ termios_tcgetattr_impl(PyObject *module, int fd) only do this in noncanonical input mode. */ if ((mode.c_lflag & ICANON) == 0) { v = PyLong_FromLong((long)mode.c_cc[VMIN]); - if (v == NULL) + if (v == NULL) { goto err; - PyList_SetItem(cc, VMIN, v); + } + if (PyList_SetItem(cc, VMIN, v) < 0) { + goto err; + } v = PyLong_FromLong((long)mode.c_cc[VTIME]); - if (v == NULL) + if (v == NULL) { + goto err; + } + if (PyList_SetItem(cc, VTIME, v) < 0) { goto err; - PyList_SetItem(cc, VTIME, v); + } } - if (!(v = PyList_New(7))) - goto err; - - PyList_SetItem(v, 0, PyLong_FromLong((long)mode.c_iflag)); - PyList_SetItem(v, 1, PyLong_FromLong((long)mode.c_oflag)); - PyList_SetItem(v, 2, PyLong_FromLong((long)mode.c_cflag)); - PyList_SetItem(v, 3, PyLong_FromLong((long)mode.c_lflag)); - PyList_SetItem(v, 4, PyLong_FromLong((long)ispeed)); - PyList_SetItem(v, 5, PyLong_FromLong((long)ospeed)); - if (PyErr_Occurred()) { - Py_DECREF(v); + if (!(v = PyList_New(7))) { goto err; } - PyList_SetItem(v, 6, cc); + +#define ADD_LONG_ITEM(index, val) \ + do { \ + PyObject *l = PyLong_FromLong((long)val); \ + if (l == NULL) { \ + Py_DECREF(v); \ + goto err; \ + } \ + PyList_SET_ITEM(v, index, l); \ + } while (0) + + ADD_LONG_ITEM(0, mode.c_iflag); + ADD_LONG_ITEM(1, mode.c_oflag); + ADD_LONG_ITEM(2, mode.c_cflag); + ADD_LONG_ITEM(3, mode.c_lflag); + ADD_LONG_ITEM(4, ispeed); + ADD_LONG_ITEM(5, ospeed); +#undef ADD_LONG_ITEM + + PyList_SET_ITEM(v, 6, cc); return v; err: Py_DECREF(cc); @@ -183,17 +212,25 @@ termios_tcsetattr_impl(PyObject *module, int fd, int when, PyObject *term) return PyErr_SetFromErrno(state->TermiosError); } - mode.c_iflag = (tcflag_t) PyLong_AsLong(PyList_GetItem(term, 0)); - mode.c_oflag = (tcflag_t) PyLong_AsLong(PyList_GetItem(term, 1)); - mode.c_cflag = (tcflag_t) PyLong_AsLong(PyList_GetItem(term, 2)); - mode.c_lflag = (tcflag_t) PyLong_AsLong(PyList_GetItem(term, 3)); - speed_t ispeed = (speed_t) PyLong_AsLong(PyList_GetItem(term, 4)); - speed_t ospeed = (speed_t) PyLong_AsLong(PyList_GetItem(term, 5)); - PyObject *cc = PyList_GetItem(term, 6); - if (PyErr_Occurred()) { - return NULL; - } - + speed_t ispeed, ospeed; +#define SET_FROM_LIST(TYPE, VAR, LIST, N) do { \ + PyObject *item = PyList_GET_ITEM(LIST, N); \ + long num = PyLong_AsLong(item); \ + if (num == -1 && PyErr_Occurred()) { \ + return NULL; \ + } \ + VAR = (TYPE)num; \ +} while (0) + + SET_FROM_LIST(tcflag_t, mode.c_iflag, term, 0); + SET_FROM_LIST(tcflag_t, mode.c_oflag, term, 1); + SET_FROM_LIST(tcflag_t, mode.c_cflag, term, 2); + SET_FROM_LIST(tcflag_t, mode.c_lflag, term, 3); + SET_FROM_LIST(speed_t, ispeed, term, 4); + SET_FROM_LIST(speed_t, ospeed, term, 5); +#undef SET_FROM_LIST + + PyObject *cc = PyList_GET_ITEM(term, 6); if (!PyList_Check(cc) || PyList_Size(cc) != NCCS) { PyErr_Format(PyExc_TypeError, "tcsetattr: attributes[6] must be %d element list", @@ -208,8 +245,13 @@ termios_tcsetattr_impl(PyObject *module, int fd, int when, PyObject *term) if (PyBytes_Check(v) && PyBytes_Size(v) == 1) mode.c_cc[i] = (cc_t) * PyBytes_AsString(v); - else if (PyLong_Check(v)) - mode.c_cc[i] = (cc_t) PyLong_AsLong(v); + else if (PyLong_Check(v)) { + long num = PyLong_AsLong(v); + if (num == -1 && PyErr_Occurred()) { + return NULL; + } + mode.c_cc[i] = (cc_t)num; + } else { PyErr_SetString(PyExc_TypeError, "tcsetattr: elements of attributes must be characters or integers"); @@ -660,6 +702,9 @@ static struct constant { #ifdef IMAXBEL {"IMAXBEL", IMAXBEL}, #endif +#ifdef IUTF8 + {"IUTF8", IUTF8}, +#endif /* struct termios.c_oflag constants */ {"OPOST", OPOST}, @@ -684,6 +729,12 @@ static struct constant { #ifdef OFDEL {"OFDEL", OFDEL}, #endif +#ifdef OXTABS + {"OXTABS", OXTABS}, +#endif +#ifdef ONOEOT + {"ONOEOT", ONOEOT}, +#endif #ifdef NLDLY {"NLDLY", NLDLY}, #endif @@ -710,6 +761,12 @@ static struct constant { #ifdef NL1 {"NL1", NL1}, #endif +#ifdef NL2 + {"NL2", NL2}, +#endif +#ifdef NL3 + {"NL3", NL3}, +#endif #ifdef CR0 {"CR0", CR0}, #endif @@ -757,6 +814,9 @@ static struct constant { #endif /* struct termios.c_cflag constants */ +#ifdef CIGNORE + {"CIGNORE", CIGNORE}, +#endif {"CSIZE", CSIZE}, {"CSTOPB", CSTOPB}, {"CREAD", CREAD}, @@ -771,6 +831,25 @@ static struct constant { {"CRTSCTS", (long)CRTSCTS}, #endif +#ifdef CRTS_IFLOW + {"CRTS_IFLOW", CRTS_IFLOW}, +#endif +#ifdef CDTR_IFLOW + {"CDTR_IFLOW", CDTR_IFLOW}, +#endif +#ifdef CDSR_OFLOW + {"CDSR_OFLOW", CDSR_OFLOW}, +#endif +#ifdef CCTS_OFLOW + {"CCTS_OFLOW", CCTS_OFLOW}, +#endif +#ifdef CCAR_OFLOW + {"CCAR_OFLOW", CCAR_OFLOW}, +#endif +#ifdef MDMBUF + {"MDMBUF", MDMBUF}, +#endif + /* struct termios.c_cflag-related values (character size) */ {"CS5", CS5}, {"CS6", CS6}, @@ -778,6 +857,9 @@ static struct constant { {"CS8", CS8}, /* struct termios.c_lflag constants */ +#ifdef ALTWERASE + {"ALTWERASE", ALTWERASE}, +#endif {"ISIG", ISIG}, {"ICANON", ICANON}, #ifdef XCASE @@ -798,6 +880,9 @@ static struct constant { #endif #ifdef FLUSHO {"FLUSHO", FLUSHO}, +#endif +#ifdef NOKERNINFO + {"NOKERNINFO", NOKERNINFO}, #endif {"NOFLSH", NOFLSH}, {"TOSTOP", TOSTOP}, @@ -805,6 +890,9 @@ static struct constant { {"PENDIN", PENDIN}, #endif {"IEXTEN", IEXTEN}, +#ifdef EXTPROC + {"EXTPROC", EXTPROC}, +#endif /* indexes into the control chars array returned by tcgetattr() */ {"VINTR", VINTR}, @@ -813,6 +901,9 @@ static struct constant { {"VKILL", VKILL}, {"VEOF", VEOF}, {"VTIME", VTIME}, +#ifdef VSTATUS + {"VSTATUS", VSTATUS}, +#endif {"VMIN", VMIN}, #ifdef VSWTC /* The #defines above ensure that if either is defined, both are, @@ -823,6 +914,9 @@ static struct constant { {"VSTART", VSTART}, {"VSTOP", VSTOP}, {"VSUSP", VSUSP}, +#ifdef VDSUSP + {"VDSUSP", VDSUSP}, +#endif {"VEOL", VEOL}, #ifdef VREPRINT {"VREPRINT", VREPRINT}, @@ -841,6 +935,18 @@ static struct constant { #endif +#ifdef B7200 + {"B7200", B7200}, +#endif +#ifdef B14400 + {"B14400", B14400}, +#endif +#ifdef B28800 + {"B28800", B28800}, +#endif +#ifdef B76800 + {"B76800", B76800}, +#endif #ifdef B460800 {"B460800", B460800}, #endif diff --git a/Modules/timemodule.c b/Modules/timemodule.c index 912710219bd014..2b0d3900dbddd6 100644 --- a/Modules/timemodule.c +++ b/Modules/timemodule.c @@ -6,22 +6,21 @@ #include "pycore_namespace.h" // _PyNamespace_New() #include "pycore_runtime.h" // _Py_ID() -#include - +#include // clock() #ifdef HAVE_SYS_TIMES_H -# include +# include // times() #endif #ifdef HAVE_SYS_TYPES_H # include #endif #if defined(HAVE_SYS_RESOURCE_H) -# include +# include // getrusage(RUSAGE_SELF) #endif #ifdef QUICKWIN # include #endif #if defined(HAVE_PTHREAD_H) -# include +# include // pthread_getcpuclockid() #endif #if defined(_AIX) # include @@ -64,54 +63,10 @@ #define SEC_TO_NS (1000 * 1000 * 1000) -#if defined(HAVE_TIMES) || defined(HAVE_CLOCK) -static int -check_ticks_per_second(long tps, const char *context) -{ - /* Effectively, check that _PyTime_MulDiv(t, SEC_TO_NS, ticks_per_second) - cannot overflow. */ - if (tps >= 0 && (_PyTime_t)tps > _PyTime_MAX / SEC_TO_NS) { - PyErr_Format(PyExc_OverflowError, "%s is too large", context); - return -1; - } - return 0; -} -#endif /* HAVE_TIMES || HAVE_CLOCK */ - -#ifdef HAVE_TIMES - -# define ticks_per_second _PyRuntime.time.ticks_per_second - -static void -ensure_ticks_per_second(void) -{ - if (_PyRuntime.time.ticks_per_second_initialized) { - return; - } - _PyRuntime.time.ticks_per_second_initialized = 1; -# if defined(HAVE_SYSCONF) && defined(_SC_CLK_TCK) - ticks_per_second = sysconf(_SC_CLK_TCK); - if (ticks_per_second < 1) { - ticks_per_second = -1; - } -# elif defined(HZ) - ticks_per_second = HZ; -# else - ticks_per_second = 60; /* magic fallback value; may be bogus */ -# endif -} - -#endif /* HAVE_TIMES */ - - -PyStatus -_PyTime_Init(void) -{ -#ifdef HAVE_TIMES - ensure_ticks_per_second(); -#endif - return PyStatus_Ok(); -} +/*[clinic input] +module time +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=a668a08771581f36]*/ /* Forward declarations */ @@ -120,6 +75,14 @@ static int pysleep(_PyTime_t timeout); typedef struct { PyTypeObject *struct_time_type; +#ifdef HAVE_TIMES + // times() clock frequency in hertz + _PyTimeFraction times_base; +#endif +#ifdef HAVE_CLOCK + // clock() frequency in hertz + _PyTimeFraction clock_base; +#endif } time_module_state; static inline time_module_state* @@ -179,7 +142,7 @@ PyDoc_STRVAR(time_ns_doc, \n\ Return the current time in nanoseconds since the Epoch."); -#if defined(HAVE_CLOCK) +#ifdef HAVE_CLOCK #ifndef CLOCKS_PER_SEC # ifdef CLK_TCK @@ -190,15 +153,13 @@ Return the current time in nanoseconds since the Epoch."); #endif static int -_PyTime_GetClockWithInfo(_PyTime_t *tp, _Py_clock_info_t *info) +py_clock(time_module_state *state, _PyTime_t *tp, _Py_clock_info_t *info) { - if (check_ticks_per_second(CLOCKS_PER_SEC, "CLOCKS_PER_SEC") < 0) { - return -1; - } + _PyTimeFraction *base = &state->clock_base; if (info) { info->implementation = "clock()"; - info->resolution = 1.0 / (double)CLOCKS_PER_SEC; + info->resolution = _PyTimeFraction_Resolution(base); info->monotonic = 1; info->adjustable = 0; } @@ -210,7 +171,7 @@ _PyTime_GetClockWithInfo(_PyTime_t *tp, _Py_clock_info_t *info) "or its value cannot be represented"); return -1; } - _PyTime_t ns = _PyTime_MulDiv(ticks, SEC_TO_NS, (_PyTime_t)CLOCKS_PER_SEC); + _PyTime_t ns = _PyTimeFraction_Mul(ticks, base); *tp = _PyTime_FromNanoseconds(ns); return 0; } @@ -228,23 +189,52 @@ _PyTime_GetClockWithInfo(_PyTime_t *tp, _Py_clock_info_t *info) #pragma clang diagnostic ignored "-Wunguarded-availability" #endif -static PyObject * -time_clock_gettime(PyObject *self, PyObject *args) +static int +time_clockid_converter(PyObject *obj, clockid_t *p) { - int ret; - struct timespec tp; - -#if defined(_AIX) && (SIZEOF_LONG == 8) - long clk_id; - if (!PyArg_ParseTuple(args, "l:clock_gettime", &clk_id)) { +#ifdef _AIX + long long clk_id = PyLong_AsLongLong(obj); #else - int clk_id; - if (!PyArg_ParseTuple(args, "i:clock_gettime", &clk_id)) { + int clk_id = PyLong_AsInt(obj); #endif - return NULL; + if (clk_id == -1 && PyErr_Occurred()) { + PyErr_Format(PyExc_TypeError, + "clk_id should be integer, not %s", + _PyType_Name(Py_TYPE(obj))); + return 0; } - ret = clock_gettime((clockid_t)clk_id, &tp); + // Make sure that we picked the right type (check sizes type) + Py_BUILD_ASSERT(sizeof(clk_id) == sizeof(*p)); + *p = (clockid_t)clk_id; + return 1; +} + +/*[python input] + +class clockid_t_converter(CConverter): + type = "clockid_t" + converter = 'time_clockid_converter' + +[python start generated code]*/ +/*[python end generated code: output=da39a3ee5e6b4b0d input=53867111501f46c8]*/ + + +/*[clinic input] +time.clock_gettime + + clk_id: clockid_t + / + +Return the time of the specified clock clk_id as a float. +[clinic start generated code]*/ + +static PyObject * +time_clock_gettime_impl(PyObject *module, clockid_t clk_id) +/*[clinic end generated code: output=832b9ebc03328020 input=7e89fcc42ca15e5d]*/ +{ + struct timespec tp; + int ret = clock_gettime(clk_id, &tp); if (ret != 0) { PyErr_SetFromErrno(PyExc_OSError); return NULL; @@ -252,38 +242,32 @@ time_clock_gettime(PyObject *self, PyObject *args) return PyFloat_FromDouble(tp.tv_sec + tp.tv_nsec * 1e-9); } -PyDoc_STRVAR(clock_gettime_doc, -"clock_gettime(clk_id) -> float\n\ -\n\ -Return the time of the specified clock clk_id."); +/*[clinic input] +time.clock_gettime_ns + + clk_id: clockid_t + / + +Return the time of the specified clock clk_id as nanoseconds (int). +[clinic start generated code]*/ static PyObject * -time_clock_gettime_ns(PyObject *self, PyObject *args) +time_clock_gettime_ns_impl(PyObject *module, clockid_t clk_id) +/*[clinic end generated code: output=4a045c3a36e60044 input=aabc248db8c8e3e5]*/ { - int ret; - int clk_id; struct timespec ts; - _PyTime_t t; - - if (!PyArg_ParseTuple(args, "i:clock_gettime", &clk_id)) { - return NULL; - } - - ret = clock_gettime((clockid_t)clk_id, &ts); + int ret = clock_gettime(clk_id, &ts); if (ret != 0) { PyErr_SetFromErrno(PyExc_OSError); return NULL; } + + _PyTime_t t; if (_PyTime_FromTimespec(&t, &ts) < 0) { return NULL; } return _PyTime_AsNanosecondsObject(t); } - -PyDoc_STRVAR(clock_gettime_ns_doc, -"clock_gettime_ns(clk_id) -> int\n\ -\n\ -Return the time of the specified clock clk_id as nanoseconds."); #endif /* HAVE_CLOCK_GETTIME */ #ifdef HAVE_CLOCK_SETTIME @@ -414,6 +398,10 @@ Return the clk_id of a thread's CPU time clock."); static PyObject * time_sleep(PyObject *self, PyObject *timeout_obj) { + if (PySys_Audit("time.sleep", "O", timeout_obj) < 0) { + return NULL; + } + _PyTime_t timeout; if (_PyTime_FromSecondsObject(&timeout, timeout_obj, _PyTime_ROUND_TIMEOUT)) return NULL; @@ -1245,8 +1233,38 @@ PyDoc_STRVAR(perf_counter_ns_doc, \n\ Performance counter for benchmarking as nanoseconds."); + +#ifdef HAVE_TIMES static int -_PyTime_GetProcessTimeWithInfo(_PyTime_t *tp, _Py_clock_info_t *info) +process_time_times(time_module_state *state, _PyTime_t *tp, + _Py_clock_info_t *info) +{ + _PyTimeFraction *base = &state->times_base; + + struct tms process; + if (times(&process) == (clock_t)-1) { + return 0; + } + + if (info) { + info->implementation = "times()"; + info->resolution = _PyTimeFraction_Resolution(base); + info->monotonic = 1; + info->adjustable = 0; + } + + _PyTime_t ns; + ns = _PyTimeFraction_Mul(process.tms_utime, base); + ns += _PyTimeFraction_Mul(process.tms_stime, base); + *tp = _PyTime_FromNanoseconds(ns); + return 1; +} +#endif + + +static int +py_process_time(time_module_state *state, _PyTime_t *tp, + _Py_clock_info_t *info) { #if defined(MS_WINDOWS) HANDLE process; @@ -1349,41 +1367,27 @@ _PyTime_GetProcessTimeWithInfo(_PyTime_t *tp, _Py_clock_info_t *info) /* times() */ #ifdef HAVE_TIMES - struct tms t; - - if (times(&t) != (clock_t)-1) { - assert(_PyRuntime.time.ticks_per_second_initialized); - if (check_ticks_per_second(ticks_per_second, "_SC_CLK_TCK") < 0) { - return -1; - } - if (ticks_per_second != -1) { - if (info) { - info->implementation = "times()"; - info->monotonic = 1; - info->adjustable = 0; - info->resolution = 1.0 / (double)ticks_per_second; - } - - _PyTime_t ns; - ns = _PyTime_MulDiv(t.tms_utime, SEC_TO_NS, ticks_per_second); - ns += _PyTime_MulDiv(t.tms_stime, SEC_TO_NS, ticks_per_second); - *tp = _PyTime_FromNanoseconds(ns); - return 0; - } + int res = process_time_times(state, tp, info); + if (res < 0) { + return -1; + } + if (res == 1) { + return 0; } + // times() failed, ignore failure #endif - /* clock */ - /* Currently, Python 3 requires clock() to build: see issue #22624 */ - return _PyTime_GetClockWithInfo(tp, info); + /* clock(). Python 3 requires clock() to build (see gh-66814) */ + return py_clock(state, tp, info); #endif } static PyObject * -time_process_time(PyObject *self, PyObject *unused) +time_process_time(PyObject *module, PyObject *unused) { + time_module_state *state = get_time_state(module); _PyTime_t t; - if (_PyTime_GetProcessTimeWithInfo(&t, NULL) < 0) { + if (py_process_time(state, &t, NULL) < 0) { return NULL; } return _PyFloat_FromPyTime(t); @@ -1395,10 +1399,11 @@ PyDoc_STRVAR(process_time_doc, Process time for profiling: sum of the kernel and user-space CPU time."); static PyObject * -time_process_time_ns(PyObject *self, PyObject *unused) +time_process_time_ns(PyObject *module, PyObject *unused) { + time_module_state *state = get_time_state(module); _PyTime_t t; - if (_PyTime_GetProcessTimeWithInfo(&t, NULL) < 0) { + if (py_process_time(state, &t, NULL) < 0) { return NULL; } return _PyTime_AsNanosecondsObject(t); @@ -1585,7 +1590,7 @@ sum of the kernel and user-space CPU time."); static PyObject * -time_get_clock_info(PyObject *self, PyObject *args) +time_get_clock_info(PyObject *module, PyObject *args) { char *name; _Py_clock_info_t info; @@ -1624,7 +1629,8 @@ time_get_clock_info(PyObject *self, PyObject *args) } } else if (strcmp(name, "process_time") == 0) { - if (_PyTime_GetProcessTimeWithInfo(&t, &info) < 0) { + time_module_state *state = get_time_state(module); + if (py_process_time(state, &t, &info) < 0) { return NULL; } } @@ -1737,6 +1743,12 @@ get_gmtoff(time_t t, struct tm *p) static int init_timezone(PyObject *m) { +#define ADD_INT(NAME, VALUE) do { \ + if (PyModule_AddIntConstant(m, NAME, VALUE) < 0) { \ + return -1; \ + } \ +} while (0) + assert(!PyErr_Occurred()); /* This code moved from PyInit_time wholesale to allow calling it from @@ -1760,13 +1772,13 @@ init_timezone(PyObject *m) #if !defined(MS_WINDOWS) || defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_SYSTEM) tzset(); #endif - PyModule_AddIntConstant(m, "timezone", _Py_timezone); + ADD_INT("timezone", _Py_timezone); #ifdef HAVE_ALTZONE - PyModule_AddIntConstant(m, "altzone", altzone); + ADD_INT("altzone", altzone); #else - PyModule_AddIntConstant(m, "altzone", _Py_timezone-3600); + ADD_INT("altzone", _Py_timezone-3600); #endif - PyModule_AddIntConstant(m, "daylight", _Py_daylight); + ADD_INT("daylight", _Py_daylight); #ifdef MS_WINDOWS TIME_ZONE_INFORMATION tzinfo = {0}; GetTimeZoneInformation(&tzinfo); @@ -1825,20 +1837,21 @@ init_timezone(PyObject *m) PyObject *tzname_obj; if (janzone < julyzone) { /* DST is reversed in the southern hemisphere */ - PyModule_AddIntConstant(m, "timezone", julyzone); - PyModule_AddIntConstant(m, "altzone", janzone); - PyModule_AddIntConstant(m, "daylight", janzone != julyzone); + ADD_INT("timezone", julyzone); + ADD_INT("altzone", janzone); + ADD_INT("daylight", janzone != julyzone); tzname_obj = Py_BuildValue("(zz)", julyname, janname); } else { - PyModule_AddIntConstant(m, "timezone", janzone); - PyModule_AddIntConstant(m, "altzone", julyzone); - PyModule_AddIntConstant(m, "daylight", janzone != julyzone); + ADD_INT("timezone", janzone); + ADD_INT("altzone", julyzone); + ADD_INT("daylight", janzone != julyzone); tzname_obj = Py_BuildValue("(zz)", janname, julyname); } if (PyModule_Add(m, "tzname", tzname_obj) < 0) { return -1; } #endif // !HAVE_DECL_TZNAME +#undef ADD_INT if (PyErr_Occurred()) { return -1; @@ -1847,12 +1860,16 @@ init_timezone(PyObject *m) } +// Include Argument Clinic code after defining converters such as +// time_clockid_converter(). +#include "clinic/timemodule.c.h" + static PyMethodDef time_methods[] = { {"time", time_time, METH_NOARGS, time_doc}, {"time_ns", time_time_ns, METH_NOARGS, time_ns_doc}, #ifdef HAVE_CLOCK_GETTIME - {"clock_gettime", time_clock_gettime, METH_VARARGS, clock_gettime_doc}, - {"clock_gettime_ns",time_clock_gettime_ns, METH_VARARGS, clock_gettime_ns_doc}, + TIME_CLOCK_GETTIME_METHODDEF + TIME_CLOCK_GETTIME_NS_METHODDEF #endif #ifdef HAVE_CLOCK_SETTIME {"clock_settime", time_clock_settime, METH_VARARGS, clock_settime_doc}, @@ -1976,20 +1993,16 @@ time_exec(PyObject *module) return -1; } #endif - #ifdef CLOCK_MONOTONIC - if (PyModule_AddIntMacro(module, CLOCK_MONOTONIC) < 0) { return -1; } - #endif #ifdef CLOCK_MONOTONIC_RAW if (PyModule_AddIntMacro(module, CLOCK_MONOTONIC_RAW) < 0) { return -1; } #endif - #ifdef CLOCK_HIGHRES if (PyModule_AddIntMacro(module, CLOCK_HIGHRES) < 0) { return -1; @@ -2000,7 +2013,6 @@ time_exec(PyObject *module) return -1; } #endif - #ifdef CLOCK_THREAD_CPUTIME_ID if (PyModule_AddIntMacro(module, CLOCK_THREAD_CPUTIME_ID) < 0) { return -1; @@ -2027,10 +2039,19 @@ time_exec(PyObject *module) } #endif #ifdef CLOCK_UPTIME_RAW - if (PyModule_AddIntMacro(module, CLOCK_UPTIME_RAW) < 0) { return -1; } +#endif +#ifdef CLOCK_MONOTONIC_RAW_APPROX + if (PyModule_AddIntMacro(module, CLOCK_MONOTONIC_RAW_APPROX) < 0) { + return -1; + } +#endif +#ifdef CLOCK_UPTIME_RAW_APPROX + if (PyModule_AddIntMacro(module, CLOCK_UPTIME_RAW_APPROX) < 0) { + return -1; + } #endif } @@ -2073,6 +2094,28 @@ time_exec(PyObject *module) } #endif +#ifdef HAVE_TIMES + long ticks_per_second; + if (_Py_GetTicksPerSecond(&ticks_per_second) < 0) { + PyErr_SetString(PyExc_RuntimeError, + "cannot read ticks_per_second"); + return -1; + } + if (_PyTimeFraction_Set(&state->times_base, SEC_TO_NS, + ticks_per_second) < 0) { + PyErr_Format(PyExc_OverflowError, "ticks_per_second is too large"); + return -1; + } +#endif + +#ifdef HAVE_CLOCK + if (_PyTimeFraction_Set(&state->clock_base, SEC_TO_NS, + CLOCKS_PER_SEC) < 0) { + PyErr_Format(PyExc_OverflowError, "CLOCKS_PER_SEC is too large"); + return -1; + } +#endif + return 0; } diff --git a/Modules/unicodedata.c b/Modules/unicodedata.c index c1e22f3868931f..6ae35b9372b830 100644 --- a/Modules/unicodedata.c +++ b/Modules/unicodedata.c @@ -977,21 +977,6 @@ unicodedata_UCD_normalize_impl(PyObject *self, PyObject *form, /* -------------------------------------------------------------------- */ /* database code (cut and pasted from the unidb package) */ -static unsigned long -_gethash(const char *s, int len, int scale) -{ - int i; - unsigned long h = 0; - unsigned long ix; - for (i = 0; i < len; i++) { - h = (h * scale) + (unsigned char) Py_TOUPPER(s[i]); - ix = h & 0xff000000; - if (ix) - h = (h ^ ((ix>>24) & 0xff)) & 0x00ffffff; - } - return h; -} - static const char * const hangul_syllables[][3] = { { "G", "A", "" }, { "GG", "AE", "G" }, @@ -1035,6 +1020,7 @@ is_unified_ideograph(Py_UCS4 code) (0x2B740 <= code && code <= 0x2B81D) || /* CJK Ideograph Extension D */ (0x2B820 <= code && code <= 0x2CEA1) || /* CJK Ideograph Extension E */ (0x2CEB0 <= code && code <= 0x2EBE0) || /* CJK Ideograph Extension F */ + (0x2EBF0 <= code && code <= 0x2EE5D) || /* CJK Ideograph Extension I */ (0x30000 <= code && code <= 0x3134A) || /* CJK Ideograph Extension G */ (0x31350 <= code && code <= 0x323AF); /* CJK Ideograph Extension H */ } @@ -1045,6 +1031,247 @@ is_unified_ideograph(Py_UCS4 code) #define IS_NAMED_SEQ(cp) ((cp >= named_sequences_start) && \ (cp < named_sequences_end)) + +// DAWG decoding functions + +static unsigned int +_dawg_decode_varint_unsigned(unsigned int index, unsigned int* result) +{ + unsigned int res = 0; + unsigned int shift = 0; + for (;;) { + unsigned char byte = packed_name_dawg[index]; + res |= (byte & 0x7f) << shift; + index++; + shift += 7; + if (!(byte & 0x80)) { + *result = res; + return index; + } + } +} + +static int +_dawg_match_edge(const char* name, unsigned int namelen, unsigned int size, + unsigned int label_offset, unsigned int namepos) +{ + // This returns 1 if the edge matched, 0 if it didn't (but further edges + // could match) and -1 if the name cannot match at all. + if (size > 1 && namepos + size > namelen) { + return 0; + } + for (unsigned int i = 0; i < size; i++) { + if (packed_name_dawg[label_offset + i] != Py_TOUPPER(name[namepos + i])) { + if (i > 0) { + return -1; // cannot match at all + } + return 0; + } + } + return 1; +} + +// reading DAWG node information: +// a node is encoded by a varint. The lowest bit of that int is set if the node +// is a final, accepting state. The higher bits of that int represent the +// number of names that are encoded by the sub-DAWG started by this node. It's +// used to compute the position of a name. +// +// the starting node of the DAWG is at position 0. +// +// the varint representing a node is followed by the node's edges, the encoding +// is described below + + +static unsigned int +_dawg_decode_node(unsigned int node_offset, bool* final) +{ + unsigned int num; + node_offset = _dawg_decode_varint_unsigned(node_offset, &num); + *final = num & 1; + return node_offset; +} + +static bool +_dawg_node_is_final(unsigned int node_offset) +{ + unsigned int num; + _dawg_decode_varint_unsigned(node_offset, &num); + return num & 1; +} + +static unsigned int +_dawg_node_descendant_count(unsigned int node_offset) +{ + unsigned int num; + _dawg_decode_varint_unsigned(node_offset, &num); + return num >> 1; +} + + +// reading DAWG edge information: +// a DAWG edge is comprised of the following information: +// (1) the size of the label of the string attached to the edge +// (2) the characters of that edge +// (3) the target node +// (4) whether the edge is the last edge in the list of edges following a node +// +// this information is encoded in a compact form as follows: +// +// +---------+-----------------+--------------+-------------------- +// | varint | size (if != 1) | label chars | ... next edge ... +// +---------+-----------------+--------------+-------------------- +// +// - first comes a varint +// - the lowest bit of that varint is whether the edge is final (4) +// - the second lowest bit of that varint is true if the size of +// the length of the label is 1 (1) +// - the rest of the varint is an offset that can be used to compute +// the offset of the target node of that edge (3) +// - if the size is not 1, the first varint is followed by a +// character encoding the number of characters of the label (1) +// (unicode character names aren't larger than 256 bytes, therefore each +// edge label can be at most 256 chars, but is usually smaller) +// - the next size bytes are the characters of the label (2) +// +// the offset of the target node is computed as follows: the number in the +// upper bits of the varint needs to be added to the offset of the target node +// of the previous edge. For the first edge, where there is no previous target +// node, the offset of the first edge is used. +// The intuition here is that edges going out from a node often lead to nodes +// that are close by, leading to small offsets from the current node and thus +// fewer bytes. +// +// There is a special case: if a final node has no outgoing edges, it has to be +// followed by a 0 byte to indicate that there are no edges (because the end of +// the edge list is normally indicated in a bit in the edge encoding). This is +// indicated by _dawg_decode_edge returning -1 + + +static int +_dawg_decode_edge(bool is_first_edge, unsigned int prev_target_node_offset, + unsigned int edge_offset, unsigned int* size, + unsigned int* label_offset, unsigned int* target_node_offset) +{ + unsigned int num; + edge_offset = _dawg_decode_varint_unsigned(edge_offset, &num); + if (num == 0 && is_first_edge) { + return -1; // trying to decode past a final node without outgoing edges + } + bool last_edge = num & 1; + num >>= 1; + bool len_is_one = num & 1; + num >>= 1; + *target_node_offset = prev_target_node_offset + num; + if (len_is_one) { + *size = 1; + } else { + *size = packed_name_dawg[edge_offset++]; + } + *label_offset = edge_offset; + return last_edge; +} + +static int +_lookup_dawg_packed(const char* name, unsigned int namelen) +{ + unsigned int stringpos = 0; + unsigned int node_offset = 0; + unsigned int result = 0; // this is the number of final nodes that we skipped to match name + while (stringpos < namelen) { + bool final; + unsigned int edge_offset = _dawg_decode_node(node_offset, &final); + unsigned int prev_target_node_offset = edge_offset; + bool is_first_edge = true; + for (;;) { + unsigned int size; + unsigned int label_offset, target_node_offset; + int last_edge = _dawg_decode_edge( + is_first_edge, prev_target_node_offset, edge_offset, + &size, &label_offset, &target_node_offset); + if (last_edge == -1) { + return -1; + } + is_first_edge = false; + prev_target_node_offset = target_node_offset; + int matched = _dawg_match_edge(name, namelen, size, label_offset, stringpos); + if (matched == -1) { + return -1; + } + if (matched) { + if (final) + result += 1; + stringpos += size; + node_offset = target_node_offset; + break; + } + if (last_edge) { + return -1; + } + result += _dawg_node_descendant_count(target_node_offset); + edge_offset = label_offset + size; + } + } + if (_dawg_node_is_final(node_offset)) { + return result; + } + return -1; +} + +static int +_inverse_dawg_lookup(char* buffer, unsigned int buflen, unsigned int pos) +{ + unsigned int node_offset = 0; + unsigned int bufpos = 0; + for (;;) { + bool final; + unsigned int edge_offset = _dawg_decode_node(node_offset, &final); + + if (final) { + if (pos == 0) { + if (bufpos + 1 == buflen) { + return 0; + } + buffer[bufpos] = '\0'; + return 1; + } + pos--; + } + unsigned int prev_target_node_offset = edge_offset; + bool is_first_edge = true; + for (;;) { + unsigned int size; + unsigned int label_offset, target_node_offset; + int last_edge = _dawg_decode_edge( + is_first_edge, prev_target_node_offset, edge_offset, + &size, &label_offset, &target_node_offset); + if (last_edge == -1) { + return 0; + } + is_first_edge = false; + prev_target_node_offset = target_node_offset; + + unsigned int descendant_count = _dawg_node_descendant_count(target_node_offset); + if (pos < descendant_count) { + if (bufpos + size >= buflen) { + return 0; // buffer overflow + } + for (unsigned int i = 0; i < size; i++) { + buffer[bufpos++] = packed_name_dawg[label_offset++]; + } + node_offset = target_node_offset; + break; + } else if (!last_edge) { + pos -= descendant_count; + edge_offset = label_offset + size; + } else { + return 0; + } + } + } +} + + static int _getucname(PyObject *self, Py_UCS4 code, char* buffer, int buflen, int with_alias_and_seq) @@ -1053,9 +1280,6 @@ _getucname(PyObject *self, * If with_alias_and_seq is 1, check for names in the Private Use Area 15 * that we are using for aliases and named sequences. */ int offset; - int i; - int word; - const unsigned char* w; if (code >= 0x110000) return 0; @@ -1106,45 +1330,15 @@ _getucname(PyObject *self, return 1; } - /* get offset into phrasebook */ - offset = phrasebook_offset1[(code>>phrasebook_shift)]; - offset = phrasebook_offset2[(offset<>DAWG_CODEPOINT_TO_POS_SHIFT)]; + offset = dawg_codepoint_to_pos_index2[(offset<= 0) { - word = (word << 8) + phrasebook[offset+1]; - offset += 2; - } else - word = phrasebook[offset++]; - if (i) { - if (i > buflen) - return 0; /* buffer overflow */ - buffer[i++] = ' '; - } - /* copy word string from lexicon. the last character in the - word has bit 7 set. the last word in a string ends with - 0x80 */ - w = lexicon + lexicon_offset[word]; - while (*w < 128) { - if (i >= buflen) - return 0; /* buffer overflow */ - buffer[i++] = *w++; - } - if (i >= buflen) - return 0; /* buffer overflow */ - buffer[i++] = *w & 127; - if (*w == 128) - break; /* end of word */ - } - - return 1; + assert(buflen >= 0); + return _inverse_dawg_lookup(buffer, Py_SAFE_DOWNCAST(buflen, int, unsigned int), offset); } static int @@ -1156,21 +1350,6 @@ capi_getucname(Py_UCS4 code, } -static int -_cmpname(PyObject *self, int code, const char* name, int namelen) -{ - /* check if code corresponds to the given name */ - int i; - char buffer[NAME_MAXLEN+1]; - if (!_getucname(self, code, buffer, NAME_MAXLEN, 1)) - return 0; - for (i = 0; i < namelen; i++) { - if (Py_TOUPPER(name[i]) != buffer[i]) - return 0; - } - return buffer[namelen] == '\0'; -} - static void find_syllable(const char *str, int *len, int *pos, int count, int column) { @@ -1192,31 +1371,25 @@ find_syllable(const char *str, int *len, int *pos, int count, int column) } static int -_check_alias_and_seq(unsigned int cp, Py_UCS4* code, int with_named_seq) +_check_alias_and_seq(Py_UCS4* code, int with_named_seq) { /* check if named sequences are allowed */ - if (!with_named_seq && IS_NAMED_SEQ(cp)) + if (!with_named_seq && IS_NAMED_SEQ(*code)) return 0; /* if the code point is in the PUA range that we use for aliases, * convert it to obtain the right code point */ - if (IS_ALIAS(cp)) - *code = name_aliases[cp-aliases_start]; - else - *code = cp; + if (IS_ALIAS(*code)) + *code = name_aliases[*code-aliases_start]; return 1; } + static int -_getcode(PyObject* self, - const char* name, int namelen, Py_UCS4* code, int with_named_seq) +_getcode(const char* name, int namelen, Py_UCS4* code) { /* Return the code point associated with the given name. - * Named aliases are resolved too (unless self != NULL (i.e. we are using - * 3.2.0)). If with_named_seq is 1, returns the PUA code point that we are - * using for the named sequence, and the caller must then convert it. */ - unsigned int h, v; - unsigned int mask = code_size-1; - unsigned int i, incr; + * Named aliases are not resolved, they are returned as a code point in the + * PUA */ /* Check for hangul syllables. */ if (strncmp(name, "HANGUL SYLLABLE ", 16) == 0) { @@ -1239,6 +1412,7 @@ _getcode(PyObject* self, /* Check for unified ideographs. */ if (strncmp(name, "CJK UNIFIED IDEOGRAPH-", 22) == 0) { /* Four or five hexdigits must follow. */ + unsigned int v; v = 0; name += 22; namelen -= 22; @@ -1260,41 +1434,24 @@ _getcode(PyObject* self, return 1; } - /* the following is the same as python's dictionary lookup, with - only minor changes. see the makeunicodedata script for more - details */ - - h = (unsigned int) _gethash(name, namelen, code_magic); - i = (~h) & mask; - v = code_hash[i]; - if (!v) + assert(namelen >= 0); + int position = _lookup_dawg_packed(name, Py_SAFE_DOWNCAST(namelen, int, unsigned int)); + if (position < 0) { return 0; - if (_cmpname(self, v, name, namelen)) { - return _check_alias_and_seq(v, code, with_named_seq); - } - incr = (h ^ (h >> 3)) & mask; - if (!incr) - incr = mask; - for (;;) { - i = (i + incr) & mask; - v = code_hash[i]; - if (!v) - return 0; - if (_cmpname(self, v, name, namelen)) { - return _check_alias_and_seq(v, code, with_named_seq); - } - incr = incr << 1; - if (incr > mask) - incr = incr ^ code_poly; } + *code = dawg_pos_to_codepoint[position]; + return 1; } + static int capi_getcode(const char* name, int namelen, Py_UCS4* code, int with_named_seq) { - return _getcode(NULL, name, namelen, code, with_named_seq); - + if (!_getcode(name, namelen, code)) { + return 0; + } + return _check_alias_and_seq(code, with_named_seq); } static void @@ -1387,10 +1544,17 @@ unicodedata_UCD_lookup_impl(PyObject *self, const char *name, return NULL; } - if (!_getcode(self, name, (int)name_length, &code, 1)) { + if (!_getcode(name, (int)name_length, &code)) { PyErr_Format(PyExc_KeyError, "undefined character name '%s'", name); return NULL; } + if (UCD_Check(self)) { + /* in 3.2.0 there are no aliases and named sequences */ + if (IS_ALIAS(code) || IS_NAMED_SEQ(code)) { + PyErr_Format(PyExc_KeyError, "undefined character name '%s'", name); + return 0; + } + } /* check if code is in the PUA range that we use for named sequences and convert it */ if (IS_NAMED_SEQ(code)) { @@ -1399,6 +1563,9 @@ unicodedata_UCD_lookup_impl(PyObject *self, const char *name, named_sequences[index].seq, named_sequences[index].seqlen); } + if (IS_ALIAS(code)) { + code = name_aliases[code-aliases_start]; + } return PyUnicode_FromOrdinal(code); } diff --git a/Modules/unicodedata_db.h b/Modules/unicodedata_db.h index 4c4b2f589c50bf..3e210863448b78 100644 --- a/Modules/unicodedata_db.h +++ b/Modules/unicodedata_db.h @@ -1,6 +1,6 @@ -/* this file was generated by Tools/unicode/makeunicodedata.py 3.3 */ +/* this file was generated by ./Tools/unicode/makeunicodedata.py 3.3 */ -#define UNIDATA_VERSION "15.0.0" +#define UNIDATA_VERSION "15.1.0" /* a list of unique database records */ const _PyUnicode_DatabaseRecord _PyUnicode_Database_Records[] = { {0, 0, 0, 0, 0, 0}, @@ -810,46 +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, 271, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, - 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, - 121, 121, 121, 121, 273, 272, 272, 272, 272, 272, 272, 272, 272, 272, - 272, 274, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, + 101, 101, 101, 271, 101, 101, 101, 101, 272, 273, 273, 273, 273, 273, + 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, + 121, 121, 121, 121, 274, 273, 273, 273, 273, 273, 273, 273, 273, 273, + 273, 275, 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, 275, 101, + 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 276, 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, 276, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, - 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, - 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, - 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, - 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, - 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, - 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, - 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, - 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, - 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, - 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, - 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, - 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, - 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, - 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, - 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, - 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, - 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, - 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, - 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, - 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, - 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, - 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, - 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, - 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, - 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, - 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, - 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, - 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, - 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, - 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, - 272, 272, 272, 272, 272, 272, 272, 272, 272, 274, 137, 137, 137, 137, + 101, 101, 101, 277, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, + 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, + 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, + 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, + 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, + 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, + 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, + 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, + 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, + 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, + 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, + 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, + 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, + 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, + 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, + 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, + 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, + 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, + 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, + 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, + 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, + 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, + 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, + 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, + 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, + 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, + 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, + 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, + 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, + 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, + 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, + 273, 273, 273, 273, 273, 273, 273, 273, 273, 275, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, @@ -1215,7 +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, 277, 137, 278, 279, 137, 137, 137, 137, + 137, 137, 137, 137, 137, 137, 278, 137, 279, 280, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, @@ -1288,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, 280, 120, 120, 120, 120, 120, 120, + 120, 120, 120, 120, 120, 120, 120, 281, 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, @@ -1325,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, 280, + 120, 281, }; static const unsigned short index2[] = { @@ -2016,58 +2016,57 @@ static const unsigned short index2[] = { 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, - 243, 0, 0, 0, 0, 252, 253, 253, 253, 243, 254, 172, 255, 256, 257, 256, - 257, 256, 257, 256, 257, 256, 257, 243, 243, 256, 257, 256, 257, 256, - 257, 256, 257, 258, 259, 260, 260, 243, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 261, 262, 263, 264, 265, 265, 258, 254, 254, 254, 254, - 254, 251, 243, 266, 266, 266, 254, 172, 253, 243, 26, 0, 172, 172, 172, - 172, 172, 172, 172, 172, 172, 172, 172, 267, 172, 267, 172, 267, 172, + 243, 243, 243, 243, 243, 252, 253, 253, 253, 243, 254, 172, 255, 256, + 257, 256, 257, 256, 257, 256, 257, 256, 257, 243, 243, 256, 257, 256, + 257, 256, 257, 256, 257, 258, 259, 260, 260, 243, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 261, 262, 263, 264, 265, 265, 258, 254, 254, + 254, 254, 254, 251, 243, 266, 266, 266, 254, 172, 253, 243, 26, 0, 172, + 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 267, 172, 267, 172, 267, 172, 267, 172, 267, 172, 267, 172, 267, 172, 267, 172, 267, 172, - 267, 172, 267, 172, 172, 267, 172, 267, 172, 267, 172, 172, 172, 172, - 172, 172, 267, 267, 172, 267, 267, 172, 267, 267, 172, 267, 267, 172, - 267, 267, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, - 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 267, 172, 172, 0, 0, - 268, 268, 269, 269, 254, 270, 271, 258, 172, 172, 172, 172, 172, 172, - 172, 172, 172, 172, 172, 267, 172, 267, 172, 267, 172, 267, 172, 267, + 267, 172, 267, 172, 267, 172, 172, 267, 172, 267, 172, 267, 172, 172, + 172, 172, 172, 172, 267, 267, 172, 267, 267, 172, 267, 267, 172, 267, + 267, 172, 267, 267, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, + 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 267, 172, + 172, 0, 0, 268, 268, 269, 269, 254, 270, 271, 258, 172, 172, 172, 172, + 172, 172, 172, 172, 172, 172, 172, 267, 172, 267, 172, 267, 172, 267, 172, 267, 172, 267, 172, 267, 172, 267, 172, 267, 172, 267, 172, 267, - 172, 172, 267, 172, 267, 172, 267, 172, 172, 172, 172, 172, 172, 267, - 267, 172, 267, 267, 172, 267, 267, 172, 267, 267, 172, 267, 267, 172, + 172, 267, 172, 172, 267, 172, 267, 172, 267, 172, 172, 172, 172, 172, + 172, 267, 267, 172, 267, 267, 172, 267, 267, 172, 267, 267, 172, 267, + 267, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, + 172, 172, 172, 172, 172, 172, 172, 172, 172, 267, 172, 172, 267, 267, + 267, 267, 253, 254, 254, 270, 271, 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, 267, 172, 172, 267, 267, 267, 267, - 253, 254, 254, 270, 271, 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, 0, 271, 271, 271, 271, 271, + 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 0, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, - 271, 271, 271, 271, 271, 0, 272, 272, 273, 273, 273, 273, 274, 274, 274, - 274, 274, 274, 274, 274, 274, 274, 172, 172, 172, 172, 172, 172, 172, + 271, 271, 271, 271, 271, 271, 271, 0, 272, 272, 273, 273, 273, 273, 274, + 274, 274, 274, 274, 274, 274, 274, 274, 274, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, - 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 243, 243, 243, + 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 172, 172, + 243, 243, 243, 243, 243, 243, 243, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 243, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, + 172, 172, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, + 274, 274, 274, 251, 251, 0, 273, 273, 273, 273, 273, 273, 273, 273, 273, + 273, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, - 274, 251, 251, 0, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 274, - 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, - 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, - 274, 275, 275, 275, 275, 275, 275, 275, 275, 251, 276, 276, 276, 276, - 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 274, 274, 274, - 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, - 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 251, 251, 251, - 272, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 274, 274, 274, + 274, 274, 274, 275, 275, 275, 275, 275, 275, 275, 275, 251, 276, 276, + 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, + 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 251, + 251, 251, 272, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, - 274, 274, 274, 274, 274, 274, 274, 274, 276, 276, 276, 276, 276, 276, - 276, 276, 276, 276, 276, 276, 276, 276, 276, 274, 274, 274, 274, 274, - 274, 274, 274, 274, 274, 274, 274, 251, 251, 251, 251, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, + 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 276, 276, 276, 276, + 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 274, 274, 274, + 274, 274, 274, 274, 274, 274, 274, 274, 274, 251, 251, 251, 251, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, @@ -2078,17 +2077,18 @@ static const unsigned short index2[] = { 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, - 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 251, 251, 251, 251, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, + 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 251, 251, + 251, 251, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, - 274, 251, 251, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, + 274, 274, 274, 251, 251, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, - 274, 274, 274, 274, 274, 274, 251, 172, 172, 172, 172, 172, 172, 172, + 274, 274, 274, 274, 274, 274, 274, 274, 251, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, @@ -2102,12 +2102,12 @@ 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, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 172, 172, 172, 172, 172, 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, 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, 172, 172, 172, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, - 172, 172, 172, 172, 254, 172, 172, 172, 172, 172, 172, 172, 172, 172, + 172, 172, 172, 172, 172, 254, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, @@ -2115,12 +2115,12 @@ 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, 0, 0, 0, 243, + 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 0, 0, 0, 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, 243, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 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, 53, 53, 53, 53, 53, 53, 83, 83, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 53, 138, 138, 138, 48, 48, 48, @@ -3339,6 +3339,15 @@ 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, 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, + 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, + 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, + 172, 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, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, @@ -3350,9 +3359,9 @@ static const unsigned short index2[] = { 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 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, + 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, 281, 281, 281, 281, 281, 281, 281, 281, 281, + 280, 280, 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, @@ -3368,33 +3377,33 @@ static const unsigned short index2[] = { 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 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, + 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, 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, 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, + 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, 0, 177, 0, 0, 0, 0, 0, + 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, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, + 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, 177, 177, 177, 177, 177, 177, 71, 71, 71, + 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, 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, @@ -3408,7 +3417,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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 279, 279, + 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, 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, @@ -3417,7 +3426,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, 279, 279, 279, 279, 279, 279, 279, 279, 279, 0, 0, + 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 0, 0, }; /* decomposition data */ @@ -6027,385 +6036,199 @@ static const change_record change_records_3_2_0[] = { { 9, 255, 255, 255, 255, 0 }, { 255, 255, 255, 1, 255, 0 }, { 255, 20, 255, 255, 255, 0 }, - { 255, 255, 255, 255, 255, 1e+16 }, + { 255, 255, 255, 255, 255, 1000000000000.0 }, { 255, 255, 255, 255, 255, 1e+20 }, { 255, 19, 255, 255, 255, -1 }, { 1, 255, 255, 0, 255, 0 }, }; static const unsigned char changes_3_2_0_index[] = { - 0, 1, 2, 2, 3, 4, 5, 6, 2, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, - 19, 20, 21, 22, 23, 24, 25, 2, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, - 36, 37, 2, 2, 2, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, - 52, 52, 2, 53, 2, 2, 54, 55, 56, 57, 58, 2, 59, 60, 61, 62, 2, 63, 64, - 65, 66, 67, 68, 68, 2, 69, 2, 2, 70, 71, 52, 72, 73, 74, 75, 2, 2, 2, 76, - 77, 78, 79, 80, 81, 82, 83, 84, 85, 2, 2, 2, 2, 2, 2, 86, 2, 2, 2, 2, 2, - 87, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 88, 2, 89, 2, 2, 2, 2, 2, 2, 2, 2, - 90, 91, 2, 2, 2, 2, 2, 2, 2, 92, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 93, - 94, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 95, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 96, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 97, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 98, 99, 2, 2, 2, 2, 2, 2, 2, 2, 100, 52, - 52, 101, 102, 52, 103, 104, 105, 106, 107, 108, 109, 110, 111, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 112, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 113, 114, 115, 116, 117, 118, 2, 2, 119, 120, 121, - 2, 122, 123, 124, 125, 126, 127, 2, 128, 129, 130, 131, 132, 133, 134, - 52, 52, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, - 2, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 2, 159, 160, 2, - 161, 162, 163, 164, 2, 165, 166, 167, 168, 169, 170, 171, 2, 172, 173, - 174, 175, 2, 176, 177, 178, 52, 52, 52, 52, 52, 52, 52, 179, 180, 52, - 181, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 182, 52, - 52, 52, 52, 52, 52, 52, 52, 183, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 52, 52, 52, 52, - 184, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 52, 52, 52, - 52, 185, 186, 187, 188, 2, 2, 2, 2, 189, 190, 191, 192, 52, 52, 52, 52, - 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, - 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, - 52, 52, 52, 52, 52, 52, 52, 102, 52, 52, 52, 52, 52, 52, 52, 52, 52, 183, - 193, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 194, 52, - 52, 195, 52, 52, 196, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 197, 198, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 199, 181, 2, 2, 200, 201, - 202, 203, 204, 2, 2, 205, 2, 2, 2, 206, 207, 208, 52, 52, 52, 52, 52, - 209, 2, 2, 2, 2, 2, 2, 2, 2, 210, 2, 211, 212, 213, 2, 2, 214, 2, 2, 2, - 215, 2, 2, 2, 2, 2, 216, 52, 217, 218, 2, 2, 2, 2, 2, 219, 220, 221, 2, - 222, 223, 2, 2, 224, 225, 52, 226, 227, 2, 52, 52, 52, 52, 52, 52, 52, - 228, 229, 230, 231, 232, 52, 52, 233, 234, 52, 235, 2, 2, 2, 2, 2, 2, 2, - 2, 236, 237, 97, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 86, 238, 2, - 239, 240, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 241, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 242, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 243, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 244, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 245, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, - 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 246, - 52, 247, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, - 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, - 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 248, 52, 52, 52, 52, 52, 52, 52, - 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, - 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, - 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 249, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 241, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 52, 52, 52, 52, 52, 52, 52, 52, 52, - 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, - 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 250, 52, 52, 52, 52, 52, 52, - 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, - 52, 52, 52, 52, 52, 52, 52, 52, 251, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 52, 252, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + 1, 21, 22, 23, 24, 25, 26, 27, 28, 29, 1, 30, 31, 32, 33, 34, 35, 36, 37, + 38, 39, 1, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 1, 1, 1, 50, 1, 1, 51, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 52, 53, 54, 55, 56, 1, + 57, 1, 1, 1, 58, 1, 1, 1, 1, 1, 1, 59, 1, 1, 1, 60, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 61, 1, 55, 1, 1, 1, 1, 1, 1, 62, 1, 1, 63, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 64, 1, 1, 1, 1, 1, 65, 1, 66, 1, 67, 1, + 1, 1, 1, 1, 1, 1, 1, 68, 69, 1, 1, 1, 70, 28, 71, 72, 73, 74, 75, 76, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 77, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 78, 79, 80, 1, 81, 82, 83, 84, 85, 86, 87, 88, 89, 28, 90, + 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, + 107, 108, 109, 110, 111, 112, 113, 114, 28, 28, 28, 115, 116, 117, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 118, 28, 28, 28, 28, 119, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 28, 28, 120, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 28, 28, 121, + 122, 1, 1, 123, 124, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 125, 28, 28, 28, 28, 126, 127, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 128, 28, 129, 130, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 131, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 132, 1, 133, + 134, 135, 136, 1, 137, 138, 28, 28, 139, 1, 1, 1, 1, 140, 141, 142, 143, + 1, 144, 1, 1, 145, 146, 147, 1, 1, 148, 149, 150, 1, 151, 152, 153, 28, + 28, 28, 154, 155, 156, 28, 157, 158, 1, 1, 1, 1, 159, 67, 1, 1, 1, 1, 1, + 1, 1, 160, 161, 162, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 163, 1, 1, 1, 1, 1, 164, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 165, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 166, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 167, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 168, 169, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, + 170, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 171, 28, 28, 43, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 163, 1, 1, 1, 1, 1, 1, 1, 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 172, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 173, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 174, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, }; static const unsigned char changes_3_2_0_data[] = { @@ -6426,153 +6249,169 @@ static const unsigned char changes_3_2_0_data[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, - 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 10, 0, 9, 9, 0, 0, 0, 9, 9, - 9, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, + 10, 0, 9, 9, 0, 0, 0, 9, 9, 9, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 9, 9, 9, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, - 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 0, 9, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, - 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 13, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 9, 9, 0, 0, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 9, 0, 0, 0, 0, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 9, 9, 9, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, + 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 9, 0, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 0, 0, 0, - 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, - 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 9, 9, 9, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 16, 17, 18, 19, 0, 0, 9, - 9, 9, 9, 0, 0, 9, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 15, 16, 17, 18, 19, 0, 0, 9, 9, 9, 9, 0, 0, 9, 0, + 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, + 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, - 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, + 0, 0, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, - 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 9, 9, 9, 0, 0, 9, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, - 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, + 0, 0, 9, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 20, 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 9, 9, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 9, 9, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, - 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 9, 9, 9, 0, 9, 9, 9, 9, - 9, 9, 9, 9, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 9, 9, 0, 20, 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, + 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 9, 9, 0, 0, 0, 0, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 9, + 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 9, 0, 0, 9, 0, 0, 9, 0, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 9, 0, 0, 0, - 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 21, 21, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 9, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, - 9, 9, 9, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 0, 0, 0, 9, 0, 0, 9, 0, 0, 9, 0, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 9, 0, 0, + 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 9, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 21, 21, 21, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 9, 0, 0, 9, 0, 0, 0, 0, 0, 0, + 0, 9, 9, 9, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 9, 0, 0, 22, 22, 22, 22, 22, 22, 22, 22, + 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 9, 0, 0, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 9, 9, 0, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -6618,82 +6457,98 @@ static const unsigned char changes_3_2_0_data[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 21, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, - 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, - 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 33, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 9, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, + 0, 0, 0, 0, 0, 33, 33, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 34, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 0, 0, 0, 0, 9, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 0, 0, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, + 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 9, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 9, 9, 9, 9, 9, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, - 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, + 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -6726,74 +6581,97 @@ static const unsigned char changes_3_2_0_data[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 47, 47, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 50, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 47, 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, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 50, 11, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 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, 0, 0, 0, + 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 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, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 9, 9, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 9, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 0, 0, 0, 0, 9, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 9, 0, 0, + 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 9, 0, + 0, 0, 0, 9, 9, 9, 0, 9, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 9, 0, 9, 0, 0, 0, 0, 9, 9, 9, 0, 9, 0, 0, 0, 0, 0, 0, 0, 9, - 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 37, 37, 37, 37, 37, + 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, - 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 0, 0, 0, 0, 0, 0, + 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, @@ -6802,26 +6680,31 @@ static const unsigned char changes_3_2_0_data[] = { 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 0, 0, 0, 0, 0, 9, - 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, - 9, 0, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, - 9, 0, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, - 9, 0, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 0, 9, 0, 0, 0, 0, 0, 9, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, + 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, + 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, + 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 32, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -6829,526 +6712,984 @@ static const unsigned char changes_3_2_0_data[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, - 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 19, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 55, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 55, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 0, 0, 0, 0, 0, 9, 9, 0, 9, 0, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, + 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 0, 0, 9, 9, 9, 9, 9, 9, 0, 0, 9, 9, + 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, + 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 19, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 19, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 0, 0, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 49, 50, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 0, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, + 21, 21, 21, 21, 21, 0, 0, 0, 1, 1, 21, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 0, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, + 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 0, 0, 0, 0, 0, 9, 9, 9, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, + 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, - 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, + 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, + 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, + 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, + 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 9, 9, 0, 9, 0, 9, 9, 9, 9, 9, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, + 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, + 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, + 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, + 9, 9, 9, 9, 0, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, - 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, + 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 0, 0, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 0, 0, 0, 9, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, + 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, + 0, 9, 9, 9, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, + 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, + 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 0, 0, 9, 9, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, + 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, + 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 9, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 0, 9, 0, 9, 9, 9, 9, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, + 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 0, 9, 9, + 9, 9, 9, 9, 9, 9, 0, 0, 9, 9, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 0, 9, 9, + 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 9, 9, 0, 0, 9, 9, 9, 0, + 0, 9, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 0, 0, 9, + 9, 9, 9, 9, 9, 9, 0, 0, 0, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, + 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, + 0, 0, 9, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, + 9, 9, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, + 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 0, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 9, 0, 9, 9, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 0, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 0, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, + 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 0, 0, 9, 9, 9, 9, 9, - 9, 0, 0, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, - 9, 0, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, - 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, - 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 19, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 0, 0, 9, 9, 9, 9, 9, 9, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 49, 50, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, + 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, + 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 0, 0, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, + 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, - 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 21, 21, 21, - 21, 21, 0, 0, 0, 1, 1, 21, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, - 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, - 14, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 0, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 9, 9, 9, - 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 19, - 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, - 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 0, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 0, - 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, - 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 0, 0, 9, 0, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 0, 0, - 0, 9, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 0, 0, 0, 0, 0, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, - 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 0, 9, 9, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 0, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 0, 0, 9, 9, 9, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, - 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 9, 9, - 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 0, 9, 9, 9, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, + 9, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 9, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, - 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 0, 9, 0, 9, 9, 9, 9, 0, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, - 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, - 9, 9, 0, 0, 9, 9, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 0, 9, 9, 9, 9, 9, 0, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 9, 9, 0, 0, 9, 9, 9, 0, 0, 9, 0, 0, - 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 0, 0, 9, 9, 9, 9, 9, - 9, 9, 0, 0, 0, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, + 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, + 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 9, 0, - 0, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 0, 0, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, - 9, 9, 9, 9, 0, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 0, 0, 0, 9, 0, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, - 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 9, 9, 9, - 9, 9, 9, 0, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 0, - 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -7356,94 +7697,66 @@ static const unsigned char changes_3_2_0_data[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 0, 0, 0, 0, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 57, 0, 0, 0, + 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, - 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, - 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, - 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, - 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, + 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, + 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 9, 9, 9, 9, + 9, 9, 9, 0, 9, 9, 0, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, - 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, + 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -7453,317 +7766,346 @@ static const unsigned char changes_3_2_0_data[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 0, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 9, 9, 9, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, - 0, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, + 0, 9, 9, 9, 9, 0, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, + 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 57, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 0, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, + 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 0, 0, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 0, 9, 9, 9, 9, 9, - 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, - 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 0, 9, 9, 0, 9, 0, 0, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, + 9, 0, 9, 0, 9, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 9, 0, 9, 0, 9, 0, 9, 9, + 9, 0, 9, 9, 0, 9, 0, 0, 9, 0, 9, 0, 9, 0, 9, 0, 9, 0, 9, 9, 0, 9, 0, 0, + 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 0, 9, 9, 9, 9, 0, 9, + 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 9, 9, 9, 0, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, + 9, 9, 9, 9, 9, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, - 9, 9, 9, 9, 0, 9, 9, 9, 9, 0, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, + 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, - 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 0, 9, 9, 0, 9, 0, 0, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 0, 9, 9, 9, 9, 0, 9, 0, 9, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 9, 0, 9, 0, - 9, 0, 9, 9, 9, 0, 9, 9, 0, 9, 0, 0, 9, 0, 9, 0, 9, 0, 9, 0, 9, 0, 9, 9, - 0, 9, 0, 0, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 0, 9, 9, - 9, 9, 0, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 9, 9, 9, 0, 9, 9, 9, 9, 9, 0, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, + 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, + 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, + 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, + 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, - 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 9, 9, 9, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, + 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, + 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, - 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, - 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, + 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, }; static const change_record* get_change_3_2_0(Py_UCS4 n) @@ -7771,8 +8113,8 @@ static const change_record* get_change_3_2_0(Py_UCS4 n) int index; if (n >= 0x110000) index = 0; else { - index = changes_3_2_0_index[n>>7]; - index = changes_3_2_0_data[(index<<7)+(n & 127)]; + index = changes_3_2_0_index[n>>8]; + index = changes_3_2_0_data[(index<<8)+(n & 255)]; } return change_records_3_2_0+index; } diff --git a/Modules/unicodename_db.h b/Modules/unicodename_db.h index f6320c43e53f77..4fe60ad5ed4452 100644 --- a/Modules/unicodename_db.h +++ b/Modules/unicodename_db.h @@ -1,30124 +1,17171 @@ -/* this file was generated by Tools/unicode/makeunicodedata.py 3.3 */ +/* this file was generated by ./Tools/unicode/makeunicodedata.py 3.3 */ #define NAME_MAXLEN 256 -/* lexicon */ -static const unsigned char lexicon[] = { - 76, 69, 84, 84, 69, 210, 83, 77, 65, 76, 204, 83, 73, 71, 206, 87, 73, - 84, 200, 83, 89, 76, 76, 65, 66, 76, 197, 67, 65, 80, 73, 84, 65, 204, - 72, 73, 69, 82, 79, 71, 76, 89, 80, 200, 76, 65, 84, 73, 206, 65, 82, 65, - 66, 73, 195, 67, 85, 78, 69, 73, 70, 79, 82, 205, 89, 201, 67, 74, 203, - 77, 65, 84, 72, 69, 77, 65, 84, 73, 67, 65, 204, 69, 71, 89, 80, 84, 73, - 65, 206, 67, 79, 77, 80, 65, 84, 73, 66, 73, 76, 73, 84, 217, 83, 89, 77, - 66, 79, 204, 68, 73, 71, 73, 212, 86, 79, 87, 69, 204, 84, 65, 78, 71, - 85, 212, 70, 79, 82, 77, 128, 67, 65, 78, 65, 68, 73, 65, 206, 83, 89, - 76, 76, 65, 66, 73, 67, 211, 65, 78, 196, 83, 73, 71, 78, 87, 82, 73, 84, - 73, 78, 199, 84, 73, 77, 69, 211, 66, 65, 77, 85, 205, 83, 67, 82, 73, - 80, 212, 66, 79, 76, 196, 65, 78, 65, 84, 79, 76, 73, 65, 206, 72, 65, - 78, 71, 85, 204, 78, 85, 77, 66, 69, 210, 76, 73, 78, 69, 65, 210, 67, - 79, 77, 66, 73, 78, 73, 78, 199, 76, 73, 71, 65, 84, 85, 82, 197, 71, 82, - 69, 69, 203, 69, 84, 72, 73, 79, 80, 73, 195, 77, 85, 83, 73, 67, 65, - 204, 67, 89, 82, 73, 76, 76, 73, 195, 70, 79, 210, 75, 72, 73, 84, 65, - 206, 193, 73, 84, 65, 76, 73, 195, 84, 65, 77, 73, 204, 76, 69, 70, 212, - 78, 85, 83, 72, 213, 67, 73, 82, 67, 76, 69, 196, 82, 65, 68, 73, 67, 65, - 204, 83, 65, 78, 83, 45, 83, 69, 82, 73, 198, 82, 73, 71, 72, 212, 83, - 81, 85, 65, 82, 197, 77, 79, 68, 73, 70, 73, 69, 210, 70, 73, 78, 65, - 204, 84, 65, 201, 68, 79, 85, 66, 76, 197, 83, 73, 71, 78, 128, 65, 82, - 82, 79, 87, 128, 65, 66, 79, 86, 69, 128, 86, 65, 201, 66, 69, 76, 79, - 87, 128, 72, 69, 78, 84, 65, 73, 71, 65, 78, 193, 66, 76, 65, 67, 203, - 87, 72, 73, 84, 197, 65, 82, 82, 79, 215, 65, 128, 85, 128, 86, 65, 82, - 73, 65, 84, 73, 79, 206, 73, 128, 66, 82, 65, 73, 76, 76, 197, 80, 65, - 84, 84, 69, 82, 206, 75, 65, 84, 65, 75, 65, 78, 193, 66, 89, 90, 65, 78, - 84, 73, 78, 197, 79, 128, 68, 79, 212, 73, 83, 79, 76, 65, 84, 69, 196, - 77, 65, 82, 75, 128, 194, 79, 198, 77, 89, 65, 78, 77, 65, 210, 86, 69, - 82, 84, 73, 67, 65, 204, 77, 73, 68, 68, 76, 197, 75, 65, 78, 71, 88, - 201, 75, 73, 75, 65, 75, 85, 201, 77, 69, 78, 68, 197, 84, 73, 66, 69, - 84, 65, 206, 77, 65, 82, 203, 72, 69, 65, 86, 217, 73, 78, 73, 84, 73, - 65, 204, 72, 77, 79, 78, 199, 79, 78, 197, 77, 69, 69, 205, 65, 66, 79, - 86, 197, 67, 79, 80, 84, 73, 195, 75, 72, 77, 69, 210, 82, 73, 71, 72, - 84, 87, 65, 82, 68, 211, 90, 78, 65, 77, 69, 78, 78, 217, 67, 65, 82, 82, - 73, 69, 210, 89, 69, 200, 68, 69, 86, 65, 78, 65, 71, 65, 82, 201, 71, - 69, 79, 82, 71, 73, 65, 206, 72, 79, 79, 75, 128, 67, 72, 69, 82, 79, 75, - 69, 197, 77, 79, 78, 71, 79, 76, 73, 65, 206, 84, 87, 207, 83, 84, 82, - 79, 75, 69, 128, 79, 78, 69, 128, 80, 76, 85, 211, 84, 87, 79, 128, 76, - 79, 87, 69, 210, 66, 79, 216, 83, 81, 85, 65, 82, 69, 196, 83, 89, 77, - 66, 79, 76, 128, 80, 72, 65, 83, 69, 45, 197, 84, 72, 82, 69, 197, 85, - 80, 80, 69, 210, 86, 79, 67, 65, 76, 73, 195, 76, 69, 70, 84, 87, 65, 82, - 68, 211, 84, 207, 67, 79, 78, 83, 79, 78, 65, 78, 212, 77, 73, 65, 207, - 68, 82, 65, 87, 73, 78, 71, 211, 84, 73, 76, 197, 68, 85, 80, 76, 79, 89, - 65, 206, 74, 79, 78, 71, 83, 69, 79, 78, 199, 80, 65, 82, 69, 78, 84, 72, - 69, 83, 73, 90, 69, 196, 84, 72, 65, 205, 71, 79, 78, 68, 201, 76, 79, - 215, 65, 76, 69, 198, 72, 65, 76, 198, 85, 208, 70, 79, 85, 82, 128, 71, - 76, 65, 71, 79, 76, 73, 84, 73, 195, 72, 69, 66, 82, 69, 215, 72, 73, 71, - 200, 84, 72, 82, 69, 69, 128, 79, 86, 69, 210, 72, 65, 128, 73, 78, 68, - 69, 216, 77, 65, 76, 65, 89, 65, 76, 65, 205, 83, 73, 89, 65, 209, 68, - 79, 87, 206, 80, 65, 72, 65, 87, 200, 67, 72, 79, 83, 69, 79, 78, 199, - 66, 65, 76, 73, 78, 69, 83, 197, 70, 73, 86, 69, 128, 72, 65, 76, 70, 87, - 73, 68, 84, 200, 72, 65, 78, 68, 45, 70, 73, 83, 212, 77, 69, 82, 79, 73, - 84, 73, 195, 84, 85, 82, 78, 69, 196, 73, 68, 69, 79, 71, 82, 65, 80, 72, - 73, 195, 75, 65, 128, 76, 73, 71, 72, 212, 73, 68, 69, 79, 71, 82, 65, - 205, 80, 72, 65, 83, 69, 45, 196, 84, 79, 128, 65, 76, 67, 72, 69, 77, - 73, 67, 65, 204, 78, 69, 85, 77, 197, 66, 82, 65, 72, 77, 201, 84, 79, - 78, 197, 66, 65, 82, 128, 82, 65, 128, 83, 73, 78, 72, 65, 76, 193, 78, - 85, 77, 69, 82, 73, 195, 80, 65, 128, 83, 73, 88, 128, 89, 65, 128, 69, - 73, 71, 72, 84, 128, 76, 65, 128, 77, 65, 128, 83, 69, 86, 69, 78, 128, - 84, 72, 85, 77, 194, 72, 85, 78, 71, 65, 82, 73, 65, 206, 78, 73, 78, 69, - 128, 76, 79, 78, 199, 78, 65, 128, 66, 65, 82, 194, 72, 65, 200, 82, 73, - 71, 72, 84, 128, 66, 76, 79, 67, 203, 68, 79, 84, 211, 78, 79, 82, 84, - 200, 83, 65, 128, 84, 72, 79, 85, 83, 65, 78, 68, 128, 84, 65, 128, 90, - 90, 89, 88, 128, 90, 90, 89, 84, 128, 90, 90, 89, 82, 88, 128, 90, 90, - 89, 82, 128, 90, 90, 89, 80, 128, 90, 90, 89, 65, 128, 90, 90, 89, 128, - 90, 90, 85, 88, 128, 90, 90, 85, 82, 88, 128, 90, 90, 85, 82, 128, 90, - 90, 85, 80, 128, 90, 90, 85, 128, 90, 90, 83, 89, 65, 128, 90, 90, 83, - 65, 128, 90, 90, 79, 88, 128, 90, 90, 79, 80, 128, 90, 90, 79, 128, 90, - 90, 73, 88, 128, 90, 90, 73, 84, 128, 90, 90, 73, 80, 128, 90, 90, 73, - 69, 88, 128, 90, 90, 73, 69, 84, 128, 90, 90, 73, 69, 80, 128, 90, 90, - 73, 69, 128, 90, 90, 73, 128, 90, 90, 69, 88, 128, 90, 90, 69, 80, 128, - 90, 90, 69, 69, 128, 90, 90, 69, 128, 90, 90, 65, 88, 128, 90, 90, 65, - 84, 128, 90, 90, 65, 80, 128, 90, 90, 65, 65, 128, 90, 90, 65, 128, 90, - 89, 71, 79, 83, 128, 90, 87, 83, 80, 128, 90, 87, 78, 74, 128, 90, 87, - 78, 66, 83, 80, 128, 90, 87, 74, 128, 90, 87, 202, 90, 87, 65, 82, 65, - 75, 65, 89, 128, 90, 87, 65, 128, 90, 85, 84, 128, 90, 85, 79, 88, 128, - 90, 85, 79, 80, 128, 90, 85, 79, 128, 90, 85, 77, 128, 90, 85, 66, 85, - 82, 128, 90, 85, 53, 128, 90, 85, 181, 90, 213, 90, 83, 72, 65, 128, 90, - 82, 65, 128, 90, 81, 65, 80, 72, 193, 90, 79, 84, 128, 90, 79, 79, 128, - 90, 79, 77, 66, 73, 69, 128, 90, 79, 65, 128, 90, 77, 69, 89, 84, 83, 65, - 128, 90, 76, 65, 77, 193, 90, 76, 65, 128, 90, 76, 193, 90, 74, 69, 128, - 90, 73, 90, 50, 128, 90, 73, 81, 65, 65, 128, 90, 73, 80, 80, 69, 82, 45, - 77, 79, 85, 84, 200, 90, 73, 78, 79, 82, 128, 90, 73, 76, 68, 69, 128, - 90, 73, 71, 90, 65, 199, 90, 73, 71, 128, 90, 73, 68, 193, 90, 73, 66, - 128, 90, 73, 194, 90, 73, 51, 128, 90, 201, 90, 72, 89, 88, 128, 90, 72, - 89, 84, 128, 90, 72, 89, 82, 88, 128, 90, 72, 89, 82, 128, 90, 72, 89, - 80, 128, 90, 72, 89, 128, 90, 72, 87, 69, 128, 90, 72, 87, 65, 128, 90, - 72, 85, 88, 128, 90, 72, 85, 84, 128, 90, 72, 85, 82, 88, 128, 90, 72, - 85, 82, 128, 90, 72, 85, 80, 128, 90, 72, 85, 79, 88, 128, 90, 72, 85, - 79, 80, 128, 90, 72, 85, 79, 128, 90, 72, 85, 128, 90, 72, 79, 88, 128, - 90, 72, 79, 84, 128, 90, 72, 79, 80, 128, 90, 72, 79, 79, 128, 90, 72, - 79, 73, 128, 90, 72, 79, 128, 90, 72, 73, 86, 69, 84, 69, 128, 90, 72, - 73, 76, 128, 90, 72, 73, 128, 90, 72, 69, 88, 128, 90, 72, 69, 84, 128, - 90, 72, 69, 80, 128, 90, 72, 69, 69, 128, 90, 72, 69, 128, 90, 72, 197, - 90, 72, 65, 89, 73, 78, 128, 90, 72, 65, 88, 128, 90, 72, 65, 84, 128, - 90, 72, 65, 82, 128, 90, 72, 65, 80, 128, 90, 72, 65, 73, 78, 128, 90, - 72, 65, 65, 128, 90, 72, 65, 128, 90, 72, 128, 90, 69, 86, 79, 75, 128, - 90, 69, 85, 83, 128, 90, 69, 84, 65, 128, 90, 69, 82, 79, 128, 90, 69, - 82, 207, 90, 69, 78, 128, 90, 69, 77, 76, 89, 65, 128, 90, 69, 77, 76, - 74, 65, 128, 90, 69, 76, 79, 128, 90, 69, 66, 82, 193, 90, 69, 50, 128, - 90, 197, 90, 65, 89, 78, 128, 90, 65, 89, 73, 78, 45, 89, 79, 68, 72, - 128, 90, 65, 89, 73, 78, 128, 90, 65, 89, 73, 206, 90, 65, 86, 73, 89, - 65, 78, 73, 128, 90, 65, 84, 65, 128, 90, 65, 82, 81, 65, 128, 90, 65, - 82, 76, 128, 90, 65, 81, 69, 198, 90, 65, 80, 89, 65, 84, 89, 77, 73, - 128, 90, 65, 80, 89, 65, 84, 79, 89, 128, 90, 65, 80, 89, 65, 84, 79, - 217, 90, 65, 80, 89, 65, 84, 65, 89, 65, 128, 90, 65, 78, 79, 90, 72, 69, - 75, 128, 90, 65, 78, 65, 66, 65, 90, 65, 210, 90, 65, 77, 88, 128, 90, - 65, 76, 128, 90, 65, 204, 90, 65, 75, 82, 89, 84, 79, 69, 128, 90, 65, - 75, 82, 89, 84, 65, 89, 65, 128, 90, 65, 75, 82, 89, 84, 65, 89, 193, 90, - 65, 73, 78, 128, 90, 65, 73, 206, 90, 65, 73, 128, 90, 65, 72, 128, 90, - 65, 200, 90, 65, 71, 128, 90, 65, 69, 70, 128, 90, 65, 68, 69, 82, 90, - 72, 75, 65, 128, 90, 65, 55, 128, 90, 193, 90, 48, 49, 54, 72, 128, 90, - 48, 49, 54, 71, 128, 90, 48, 49, 54, 70, 128, 90, 48, 49, 54, 69, 128, - 90, 48, 49, 54, 68, 128, 90, 48, 49, 54, 67, 128, 90, 48, 49, 54, 66, - 128, 90, 48, 49, 54, 65, 128, 90, 48, 49, 54, 128, 90, 48, 49, 53, 73, - 128, 90, 48, 49, 53, 72, 128, 90, 48, 49, 53, 71, 128, 90, 48, 49, 53, - 70, 128, 90, 48, 49, 53, 69, 128, 90, 48, 49, 53, 68, 128, 90, 48, 49, - 53, 67, 128, 90, 48, 49, 53, 66, 128, 90, 48, 49, 53, 65, 128, 90, 48, - 49, 53, 128, 90, 48, 49, 52, 128, 90, 48, 49, 51, 128, 90, 48, 49, 50, - 128, 90, 48, 49, 49, 128, 90, 48, 49, 48, 128, 90, 48, 48, 57, 128, 90, - 48, 48, 56, 128, 90, 48, 48, 55, 128, 90, 48, 48, 54, 128, 90, 48, 48, - 53, 65, 128, 90, 48, 48, 53, 128, 90, 48, 48, 52, 65, 128, 90, 48, 48, - 52, 128, 90, 48, 48, 51, 66, 128, 90, 48, 48, 51, 65, 128, 90, 48, 48, - 51, 128, 90, 48, 48, 50, 68, 128, 90, 48, 48, 50, 67, 128, 90, 48, 48, - 50, 66, 128, 90, 48, 48, 50, 65, 128, 90, 48, 48, 50, 128, 90, 48, 48, - 49, 128, 90, 128, 218, 89, 89, 88, 128, 89, 89, 84, 128, 89, 89, 82, 88, - 128, 89, 89, 82, 128, 89, 89, 80, 128, 89, 89, 69, 128, 89, 89, 65, 65, - 128, 89, 89, 65, 128, 89, 89, 128, 89, 87, 79, 79, 128, 89, 87, 79, 128, - 89, 87, 73, 73, 128, 89, 87, 73, 128, 89, 87, 69, 128, 89, 87, 65, 65, - 128, 89, 87, 65, 128, 89, 86, 128, 89, 85, 88, 128, 89, 85, 87, 79, 81, - 128, 89, 85, 85, 75, 65, 76, 69, 65, 80, 73, 78, 84, 85, 128, 89, 85, 85, - 128, 89, 85, 84, 128, 89, 85, 83, 128, 89, 85, 211, 89, 85, 82, 88, 128, - 89, 85, 82, 128, 89, 85, 81, 128, 89, 85, 209, 89, 85, 80, 128, 89, 85, - 79, 88, 128, 89, 85, 79, 84, 128, 89, 85, 79, 80, 128, 89, 85, 79, 77, - 128, 89, 85, 79, 128, 89, 85, 78, 128, 89, 85, 77, 128, 89, 85, 74, 128, - 89, 85, 73, 128, 89, 85, 69, 81, 128, 89, 85, 69, 128, 89, 85, 68, 72, - 128, 89, 85, 68, 200, 89, 85, 65, 78, 128, 89, 85, 65, 69, 78, 128, 89, - 85, 45, 89, 69, 79, 128, 89, 85, 45, 89, 69, 128, 89, 85, 45, 85, 128, - 89, 85, 45, 79, 128, 89, 85, 45, 73, 128, 89, 85, 45, 69, 79, 128, 89, - 85, 45, 69, 128, 89, 85, 45, 65, 69, 128, 89, 85, 45, 65, 128, 89, 85, - 45, 52, 128, 89, 85, 45, 51, 128, 89, 85, 45, 50, 128, 89, 85, 45, 49, - 128, 89, 85, 128, 89, 213, 89, 82, 89, 128, 89, 80, 83, 73, 76, 73, 128, - 89, 80, 79, 82, 82, 79, 73, 128, 89, 80, 79, 75, 82, 73, 83, 73, 83, 128, - 89, 80, 79, 75, 82, 73, 83, 73, 211, 89, 80, 79, 71, 69, 71, 82, 65, 77, - 77, 69, 78, 73, 128, 89, 79, 89, 128, 89, 79, 88, 128, 89, 79, 87, 68, - 128, 89, 79, 85, 84, 72, 70, 85, 76, 78, 69, 83, 83, 128, 89, 79, 85, 84, - 72, 70, 85, 204, 89, 79, 213, 89, 79, 84, 128, 89, 79, 212, 89, 79, 82, - 73, 128, 89, 79, 81, 128, 89, 79, 209, 89, 79, 80, 128, 89, 79, 79, 128, - 89, 79, 77, 79, 128, 89, 79, 71, 72, 128, 89, 79, 68, 128, 89, 79, 196, - 89, 79, 65, 128, 89, 79, 45, 89, 79, 128, 89, 79, 45, 89, 69, 79, 128, - 89, 79, 45, 89, 65, 69, 128, 89, 79, 45, 89, 65, 128, 89, 79, 45, 79, - 128, 89, 79, 45, 73, 128, 89, 79, 45, 69, 79, 128, 89, 79, 45, 65, 69, - 128, 89, 79, 45, 65, 128, 89, 79, 45, 54, 128, 89, 79, 45, 53, 128, 89, - 79, 45, 52, 128, 89, 79, 45, 51, 128, 89, 79, 45, 50, 128, 89, 79, 45, - 49, 128, 89, 207, 89, 73, 90, 69, 84, 128, 89, 73, 88, 128, 89, 73, 87, - 78, 128, 89, 73, 84, 128, 89, 73, 80, 128, 89, 73, 78, 71, 128, 89, 73, - 73, 128, 89, 73, 72, 128, 89, 73, 199, 89, 73, 69, 88, 128, 89, 73, 69, - 84, 128, 89, 73, 69, 80, 128, 89, 73, 69, 69, 128, 89, 73, 69, 128, 89, - 73, 68, 68, 73, 83, 200, 89, 73, 45, 85, 128, 89, 73, 128, 89, 72, 69, - 128, 89, 72, 65, 128, 89, 70, 69, 83, 73, 83, 128, 89, 70, 69, 83, 73, - 211, 89, 70, 69, 206, 89, 69, 90, 73, 68, 201, 89, 69, 89, 128, 89, 69, - 87, 128, 89, 69, 85, 88, 128, 89, 69, 85, 82, 65, 69, 128, 89, 69, 85, - 81, 128, 89, 69, 85, 77, 128, 89, 69, 85, 65, 69, 84, 128, 89, 69, 85, - 65, 69, 128, 89, 69, 84, 73, 86, 128, 89, 69, 83, 84, 85, 128, 89, 69, - 83, 73, 69, 85, 78, 71, 45, 83, 83, 65, 78, 71, 75, 73, 89, 69, 79, 75, - 128, 89, 69, 83, 73, 69, 85, 78, 71, 45, 83, 73, 79, 83, 128, 89, 69, 83, - 73, 69, 85, 78, 71, 45, 80, 65, 78, 83, 73, 79, 83, 128, 89, 69, 83, 73, - 69, 85, 78, 71, 45, 77, 73, 69, 85, 77, 128, 89, 69, 83, 73, 69, 85, 78, - 71, 45, 75, 73, 89, 69, 79, 75, 128, 89, 69, 83, 73, 69, 85, 78, 71, 45, - 75, 72, 73, 69, 85, 75, 72, 128, 89, 69, 83, 73, 69, 85, 78, 71, 45, 72, - 73, 69, 85, 72, 128, 89, 69, 83, 73, 69, 85, 78, 71, 128, 89, 69, 82, 85, - 128, 89, 69, 82, 213, 89, 69, 82, 73, 128, 89, 69, 82, 65, 200, 89, 69, - 82, 128, 89, 69, 79, 82, 73, 78, 72, 73, 69, 85, 72, 128, 89, 69, 79, 45, - 89, 65, 128, 89, 69, 79, 45, 85, 128, 89, 69, 79, 45, 79, 128, 89, 69, - 78, 73, 83, 69, 201, 89, 69, 78, 65, 80, 128, 89, 69, 78, 128, 89, 69, - 206, 89, 69, 76, 76, 79, 87, 128, 89, 69, 76, 76, 79, 215, 89, 69, 73, - 78, 128, 89, 69, 72, 128, 89, 69, 69, 71, 128, 89, 69, 69, 128, 89, 69, - 65, 210, 89, 69, 65, 128, 89, 65, 90, 90, 128, 89, 65, 90, 72, 128, 89, - 65, 90, 128, 89, 65, 89, 68, 128, 89, 65, 89, 65, 78, 78, 65, 128, 89, - 65, 89, 128, 89, 65, 87, 78, 73, 78, 199, 89, 65, 87, 78, 128, 89, 65, - 87, 128, 89, 65, 86, 128, 89, 65, 85, 128, 89, 65, 84, 84, 128, 89, 65, - 84, 73, 128, 89, 65, 84, 72, 128, 89, 65, 84, 128, 89, 65, 83, 83, 128, - 89, 65, 83, 72, 128, 89, 65, 83, 128, 89, 65, 82, 82, 128, 89, 65, 82, - 78, 128, 89, 65, 82, 128, 89, 65, 210, 89, 65, 81, 128, 89, 65, 80, 128, - 89, 65, 78, 83, 65, 89, 65, 128, 89, 65, 78, 71, 128, 89, 65, 78, 199, - 89, 65, 78, 128, 89, 65, 77, 79, 75, 128, 89, 65, 77, 65, 75, 75, 65, 78, - 128, 89, 65, 77, 128, 89, 65, 76, 128, 89, 65, 75, 72, 72, 128, 89, 65, - 75, 72, 128, 89, 65, 75, 65, 83, 72, 128, 89, 65, 75, 128, 89, 65, 74, - 85, 82, 86, 69, 68, 73, 195, 89, 65, 74, 128, 89, 65, 73, 128, 89, 65, - 72, 72, 128, 89, 65, 72, 128, 89, 65, 71, 78, 128, 89, 65, 71, 72, 72, - 128, 89, 65, 71, 72, 128, 89, 65, 71, 128, 89, 65, 70, 213, 89, 65, 70, - 128, 89, 65, 69, 77, 77, 65, 69, 128, 89, 65, 68, 72, 128, 89, 65, 68, - 68, 72, 128, 89, 65, 68, 68, 128, 89, 65, 68, 128, 89, 65, 67, 72, 128, - 89, 65, 66, 72, 128, 89, 65, 66, 128, 89, 65, 65, 82, 85, 128, 89, 65, - 65, 73, 128, 89, 65, 65, 68, 79, 128, 89, 65, 45, 89, 79, 128, 89, 65, - 45, 85, 128, 89, 65, 45, 79, 128, 89, 65, 45, 53, 128, 89, 65, 45, 52, - 128, 89, 65, 45, 51, 128, 89, 65, 45, 50, 128, 89, 65, 45, 49, 128, 89, - 48, 48, 56, 128, 89, 48, 48, 55, 128, 89, 48, 48, 54, 128, 89, 48, 48, - 53, 128, 89, 48, 48, 52, 128, 89, 48, 48, 51, 128, 89, 48, 48, 50, 128, - 89, 48, 48, 49, 65, 128, 89, 48, 48, 49, 128, 89, 45, 67, 82, 69, 197, - 88, 89, 88, 128, 88, 89, 85, 128, 88, 89, 84, 128, 88, 89, 82, 88, 128, - 88, 89, 82, 128, 88, 89, 80, 128, 88, 89, 79, 79, 74, 128, 88, 89, 79, - 79, 128, 88, 89, 79, 128, 88, 89, 73, 128, 88, 89, 69, 69, 205, 88, 89, - 69, 69, 128, 88, 89, 69, 128, 88, 89, 65, 65, 128, 88, 89, 65, 128, 88, - 89, 128, 88, 87, 73, 128, 88, 87, 69, 69, 128, 88, 87, 69, 128, 88, 87, - 65, 65, 128, 88, 87, 65, 128, 88, 87, 128, 88, 215, 88, 86, 69, 128, 88, - 86, 65, 128, 88, 85, 79, 88, 128, 88, 85, 79, 128, 88, 85, 128, 88, 83, - 72, 65, 65, 89, 65, 84, 72, 73, 89, 65, 128, 88, 79, 88, 128, 88, 79, 84, - 128, 88, 79, 82, 128, 88, 79, 80, 72, 128, 88, 79, 80, 128, 88, 79, 65, - 128, 88, 79, 128, 88, 73, 88, 128, 88, 73, 84, 128, 88, 73, 82, 79, 206, - 88, 73, 80, 128, 88, 73, 69, 88, 128, 88, 73, 69, 84, 128, 88, 73, 69, - 80, 128, 88, 73, 69, 128, 88, 73, 65, 78, 71, 81, 201, 88, 73, 65, 66, - 128, 88, 73, 128, 88, 72, 69, 89, 78, 128, 88, 71, 128, 88, 69, 89, 78, - 128, 88, 69, 83, 84, 69, 211, 88, 69, 72, 128, 88, 69, 69, 128, 88, 69, - 128, 88, 65, 85, 83, 128, 88, 65, 85, 128, 88, 65, 80, 72, 128, 88, 65, - 78, 128, 88, 65, 65, 128, 88, 65, 128, 88, 48, 48, 56, 65, 128, 88, 48, - 48, 56, 128, 88, 48, 48, 55, 128, 88, 48, 48, 54, 65, 128, 88, 48, 48, - 54, 128, 88, 48, 48, 53, 128, 88, 48, 48, 52, 66, 128, 88, 48, 48, 52, - 65, 128, 88, 48, 48, 52, 128, 88, 48, 48, 51, 128, 88, 48, 48, 50, 128, - 88, 48, 48, 49, 128, 88, 45, 216, 88, 45, 82, 65, 89, 128, 87, 90, 128, - 87, 89, 78, 78, 128, 87, 89, 78, 206, 87, 86, 73, 128, 87, 86, 69, 128, - 87, 86, 65, 128, 87, 86, 128, 87, 85, 80, 128, 87, 85, 79, 88, 128, 87, - 85, 79, 80, 128, 87, 85, 79, 128, 87, 85, 78, 74, 207, 87, 85, 78, 128, - 87, 85, 76, 85, 128, 87, 85, 76, 213, 87, 85, 73, 128, 87, 85, 69, 128, - 87, 85, 65, 69, 84, 128, 87, 85, 65, 69, 78, 128, 87, 85, 128, 87, 82, - 217, 87, 82, 79, 78, 71, 128, 87, 82, 73, 83, 212, 87, 82, 73, 78, 75, - 76, 69, 83, 128, 87, 82, 73, 78, 75, 76, 69, 211, 87, 82, 73, 78, 75, 76, - 69, 68, 128, 87, 82, 69, 83, 84, 76, 69, 82, 83, 128, 87, 82, 69, 78, 67, - 72, 128, 87, 82, 69, 65, 84, 200, 87, 82, 65, 80, 80, 69, 196, 87, 82, - 65, 80, 128, 87, 79, 88, 128, 87, 79, 87, 128, 87, 79, 82, 83, 72, 73, - 80, 128, 87, 79, 82, 82, 73, 69, 196, 87, 79, 82, 77, 128, 87, 79, 82, - 76, 196, 87, 79, 82, 75, 69, 82, 128, 87, 79, 82, 75, 128, 87, 79, 82, - 203, 87, 79, 82, 68, 83, 80, 65, 67, 69, 128, 87, 79, 82, 196, 87, 79, - 80, 128, 87, 79, 79, 78, 128, 87, 79, 79, 76, 128, 87, 79, 79, 68, 83, - 45, 67, 82, 69, 197, 87, 79, 79, 68, 128, 87, 79, 78, 128, 87, 79, 206, - 87, 79, 77, 69, 78, 211, 87, 79, 77, 69, 206, 87, 79, 77, 65, 78, 211, - 87, 79, 77, 65, 78, 128, 87, 79, 77, 65, 206, 87, 79, 76, 79, 83, 79, - 128, 87, 79, 76, 198, 87, 79, 69, 128, 87, 79, 65, 128, 87, 79, 45, 55, - 128, 87, 79, 45, 54, 128, 87, 79, 45, 53, 128, 87, 79, 45, 52, 128, 87, - 79, 45, 51, 128, 87, 79, 45, 50, 128, 87, 79, 45, 49, 128, 87, 73, 84, - 72, 79, 85, 212, 87, 73, 84, 72, 73, 78, 128, 87, 73, 84, 72, 73, 206, - 87, 73, 82, 69, 76, 69, 83, 83, 128, 87, 73, 82, 69, 196, 87, 73, 78, 84, - 69, 82, 128, 87, 73, 78, 75, 73, 78, 199, 87, 73, 78, 75, 128, 87, 73, - 78, 74, 65, 128, 87, 73, 78, 71, 83, 128, 87, 73, 78, 71, 128, 87, 73, - 78, 69, 128, 87, 73, 78, 197, 87, 73, 78, 68, 85, 128, 87, 73, 78, 68, - 79, 87, 128, 87, 73, 78, 68, 128, 87, 73, 78, 196, 87, 73, 78, 128, 87, - 73, 76, 84, 69, 196, 87, 73, 71, 78, 89, 65, 78, 128, 87, 73, 71, 71, 76, - 217, 87, 73, 71, 71, 76, 69, 83, 128, 87, 73, 68, 84, 72, 128, 87, 73, - 68, 69, 78, 73, 78, 199, 87, 73, 68, 69, 45, 72, 69, 65, 68, 69, 196, 87, - 73, 68, 197, 87, 73, 65, 78, 71, 87, 65, 65, 75, 128, 87, 73, 65, 78, 71, - 128, 87, 73, 45, 53, 128, 87, 73, 45, 52, 128, 87, 73, 45, 51, 128, 87, - 73, 45, 50, 128, 87, 73, 45, 49, 128, 87, 72, 79, 76, 197, 87, 72, 73, - 84, 69, 45, 70, 69, 65, 84, 72, 69, 82, 69, 196, 87, 72, 73, 84, 69, 128, - 87, 72, 69, 69, 76, 69, 196, 87, 72, 69, 69, 76, 67, 72, 65, 73, 82, 128, - 87, 72, 69, 69, 76, 67, 72, 65, 73, 210, 87, 72, 69, 69, 76, 128, 87, 72, - 69, 69, 204, 87, 72, 69, 65, 84, 128, 87, 72, 65, 76, 69, 128, 87, 72, - 128, 87, 71, 128, 87, 69, 88, 128, 87, 69, 85, 88, 128, 87, 69, 212, 87, - 69, 83, 84, 69, 82, 206, 87, 69, 83, 84, 45, 67, 82, 69, 197, 87, 69, 83, - 84, 128, 87, 69, 83, 212, 87, 69, 80, 128, 87, 69, 79, 128, 87, 69, 78, - 128, 87, 69, 76, 76, 128, 87, 69, 73, 71, 72, 212, 87, 69, 73, 69, 82, - 83, 84, 82, 65, 83, 211, 87, 69, 73, 128, 87, 69, 69, 78, 128, 87, 69, - 68, 71, 69, 45, 84, 65, 73, 76, 69, 196, 87, 69, 68, 71, 69, 128, 87, 69, - 68, 68, 73, 78, 71, 128, 87, 69, 66, 128, 87, 69, 65, 82, 217, 87, 69, - 65, 80, 79, 78, 128, 87, 69, 45, 52, 128, 87, 69, 45, 51, 128, 87, 69, - 45, 50, 128, 87, 69, 45, 49, 128, 87, 67, 128, 87, 66, 128, 87, 65, 89, - 128, 87, 65, 217, 87, 65, 88, 73, 78, 199, 87, 65, 88, 128, 87, 65, 87, - 45, 65, 89, 73, 78, 45, 82, 69, 83, 72, 128, 87, 65, 87, 128, 87, 65, - 215, 87, 65, 86, 217, 87, 65, 86, 73, 78, 199, 87, 65, 86, 69, 83, 128, - 87, 65, 86, 69, 128, 87, 65, 86, 197, 87, 65, 85, 128, 87, 65, 84, 84, - 79, 128, 87, 65, 84, 69, 82, 77, 69, 76, 79, 78, 128, 87, 65, 84, 69, 82, - 128, 87, 65, 84, 69, 210, 87, 65, 84, 67, 72, 128, 87, 65, 84, 128, 87, - 65, 83, 84, 73, 78, 71, 128, 87, 65, 83, 84, 69, 66, 65, 83, 75, 69, 84, - 128, 87, 65, 83, 83, 65, 76, 76, 65, 77, 128, 87, 65, 83, 76, 65, 128, - 87, 65, 83, 76, 193, 87, 65, 83, 65, 76, 76, 65, 77, 128, 87, 65, 83, 65, - 76, 76, 65, 205, 87, 65, 83, 45, 83, 65, 76, 65, 65, 77, 128, 87, 65, 82, - 78, 73, 78, 199, 87, 65, 82, 65, 78, 199, 87, 65, 81, 70, 65, 128, 87, - 65, 80, 128, 87, 65, 78, 73, 78, 199, 87, 65, 78, 71, 75, 85, 79, 81, - 128, 87, 65, 78, 68, 69, 82, 69, 82, 128, 87, 65, 78, 68, 128, 87, 65, - 78, 67, 72, 207, 87, 65, 78, 128, 87, 65, 76, 76, 80, 76, 65, 78, 197, - 87, 65, 76, 76, 69, 196, 87, 65, 76, 76, 128, 87, 65, 76, 204, 87, 65, - 76, 75, 128, 87, 65, 76, 203, 87, 65, 73, 84, 73, 78, 71, 128, 87, 65, - 73, 83, 84, 128, 87, 65, 73, 128, 87, 65, 70, 70, 76, 69, 128, 87, 65, - 69, 78, 128, 87, 65, 69, 128, 87, 65, 68, 68, 65, 128, 87, 65, 65, 86, - 85, 128, 87, 65, 65, 74, 73, 66, 128, 87, 65, 65, 65, 76, 73, 72, 69, - 197, 87, 65, 45, 84, 65, 65, 65, 76, 65, 65, 128, 87, 65, 45, 83, 65, 76, - 76, 65, 77, 128, 87, 65, 45, 65, 65, 76, 73, 72, 128, 87, 65, 45, 53, - 128, 87, 65, 45, 52, 128, 87, 65, 45, 51, 128, 87, 65, 45, 50, 128, 87, - 65, 45, 49, 128, 87, 193, 87, 48, 50, 53, 128, 87, 48, 50, 52, 65, 128, - 87, 48, 50, 52, 128, 87, 48, 50, 51, 128, 87, 48, 50, 50, 128, 87, 48, - 50, 49, 128, 87, 48, 50, 48, 128, 87, 48, 49, 57, 128, 87, 48, 49, 56, - 65, 128, 87, 48, 49, 56, 128, 87, 48, 49, 55, 65, 128, 87, 48, 49, 55, - 128, 87, 48, 49, 54, 128, 87, 48, 49, 53, 128, 87, 48, 49, 52, 65, 128, - 87, 48, 49, 52, 128, 87, 48, 49, 51, 128, 87, 48, 49, 50, 128, 87, 48, - 49, 49, 128, 87, 48, 49, 48, 65, 128, 87, 48, 49, 48, 128, 87, 48, 48, - 57, 65, 128, 87, 48, 48, 57, 128, 87, 48, 48, 56, 128, 87, 48, 48, 55, - 128, 87, 48, 48, 54, 128, 87, 48, 48, 53, 128, 87, 48, 48, 52, 128, 87, - 48, 48, 51, 65, 128, 87, 48, 48, 51, 128, 87, 48, 48, 50, 128, 87, 48, - 48, 49, 128, 86, 90, 77, 69, 84, 128, 86, 90, 128, 86, 89, 88, 128, 86, - 89, 84, 128, 86, 89, 83, 79, 75, 79, 128, 86, 89, 83, 79, 75, 207, 86, - 89, 82, 88, 128, 86, 89, 82, 128, 86, 89, 80, 128, 86, 89, 128, 86, 88, - 128, 86, 87, 74, 128, 86, 87, 65, 128, 86, 87, 128, 86, 85, 88, 128, 86, - 85, 85, 128, 86, 85, 84, 128, 86, 85, 82, 88, 128, 86, 85, 82, 128, 86, - 85, 80, 128, 86, 85, 76, 71, 65, 210, 86, 85, 76, 67, 65, 78, 85, 83, - 128, 86, 85, 69, 81, 128, 86, 84, 83, 128, 86, 84, 128, 86, 83, 57, 57, - 128, 86, 83, 57, 56, 128, 86, 83, 57, 55, 128, 86, 83, 57, 54, 128, 86, - 83, 57, 53, 128, 86, 83, 57, 52, 128, 86, 83, 57, 51, 128, 86, 83, 57, - 50, 128, 86, 83, 57, 49, 128, 86, 83, 57, 48, 128, 86, 83, 57, 128, 86, - 83, 56, 57, 128, 86, 83, 56, 56, 128, 86, 83, 56, 55, 128, 86, 83, 56, - 54, 128, 86, 83, 56, 53, 128, 86, 83, 56, 52, 128, 86, 83, 56, 51, 128, - 86, 83, 56, 50, 128, 86, 83, 56, 49, 128, 86, 83, 56, 48, 128, 86, 83, - 56, 128, 86, 83, 55, 57, 128, 86, 83, 55, 56, 128, 86, 83, 55, 55, 128, - 86, 83, 55, 54, 128, 86, 83, 55, 53, 128, 86, 83, 55, 52, 128, 86, 83, - 55, 51, 128, 86, 83, 55, 50, 128, 86, 83, 55, 49, 128, 86, 83, 55, 48, - 128, 86, 83, 55, 128, 86, 83, 54, 57, 128, 86, 83, 54, 56, 128, 86, 83, - 54, 55, 128, 86, 83, 54, 54, 128, 86, 83, 54, 53, 128, 86, 83, 54, 52, - 128, 86, 83, 54, 51, 128, 86, 83, 54, 50, 128, 86, 83, 54, 49, 128, 86, - 83, 54, 48, 128, 86, 83, 54, 128, 86, 83, 53, 57, 128, 86, 83, 53, 56, - 128, 86, 83, 53, 55, 128, 86, 83, 53, 54, 128, 86, 83, 53, 53, 128, 86, - 83, 53, 52, 128, 86, 83, 53, 51, 128, 86, 83, 53, 50, 128, 86, 83, 53, - 49, 128, 86, 83, 53, 48, 128, 86, 83, 53, 128, 86, 83, 52, 57, 128, 86, - 83, 52, 56, 128, 86, 83, 52, 55, 128, 86, 83, 52, 54, 128, 86, 83, 52, - 53, 128, 86, 83, 52, 52, 128, 86, 83, 52, 51, 128, 86, 83, 52, 50, 128, - 86, 83, 52, 49, 128, 86, 83, 52, 48, 128, 86, 83, 52, 128, 86, 83, 51, - 57, 128, 86, 83, 51, 56, 128, 86, 83, 51, 55, 128, 86, 83, 51, 54, 128, - 86, 83, 51, 53, 128, 86, 83, 51, 52, 128, 86, 83, 51, 51, 128, 86, 83, - 51, 50, 128, 86, 83, 51, 49, 128, 86, 83, 51, 48, 128, 86, 83, 51, 128, - 86, 83, 50, 57, 128, 86, 83, 50, 56, 128, 86, 83, 50, 55, 128, 86, 83, - 50, 54, 128, 86, 83, 50, 53, 54, 128, 86, 83, 50, 53, 53, 128, 86, 83, - 50, 53, 52, 128, 86, 83, 50, 53, 51, 128, 86, 83, 50, 53, 50, 128, 86, - 83, 50, 53, 49, 128, 86, 83, 50, 53, 48, 128, 86, 83, 50, 53, 128, 86, - 83, 50, 52, 57, 128, 86, 83, 50, 52, 56, 128, 86, 83, 50, 52, 55, 128, - 86, 83, 50, 52, 54, 128, 86, 83, 50, 52, 53, 128, 86, 83, 50, 52, 52, - 128, 86, 83, 50, 52, 51, 128, 86, 83, 50, 52, 50, 128, 86, 83, 50, 52, - 49, 128, 86, 83, 50, 52, 48, 128, 86, 83, 50, 52, 128, 86, 83, 50, 51, - 57, 128, 86, 83, 50, 51, 56, 128, 86, 83, 50, 51, 55, 128, 86, 83, 50, - 51, 54, 128, 86, 83, 50, 51, 53, 128, 86, 83, 50, 51, 52, 128, 86, 83, - 50, 51, 51, 128, 86, 83, 50, 51, 50, 128, 86, 83, 50, 51, 49, 128, 86, - 83, 50, 51, 48, 128, 86, 83, 50, 51, 128, 86, 83, 50, 50, 57, 128, 86, - 83, 50, 50, 56, 128, 86, 83, 50, 50, 55, 128, 86, 83, 50, 50, 54, 128, - 86, 83, 50, 50, 53, 128, 86, 83, 50, 50, 52, 128, 86, 83, 50, 50, 51, - 128, 86, 83, 50, 50, 50, 128, 86, 83, 50, 50, 49, 128, 86, 83, 50, 50, - 48, 128, 86, 83, 50, 50, 128, 86, 83, 50, 49, 57, 128, 86, 83, 50, 49, - 56, 128, 86, 83, 50, 49, 55, 128, 86, 83, 50, 49, 54, 128, 86, 83, 50, - 49, 53, 128, 86, 83, 50, 49, 52, 128, 86, 83, 50, 49, 51, 128, 86, 83, - 50, 49, 50, 128, 86, 83, 50, 49, 49, 128, 86, 83, 50, 49, 48, 128, 86, - 83, 50, 49, 128, 86, 83, 50, 48, 57, 128, 86, 83, 50, 48, 56, 128, 86, - 83, 50, 48, 55, 128, 86, 83, 50, 48, 54, 128, 86, 83, 50, 48, 53, 128, - 86, 83, 50, 48, 52, 128, 86, 83, 50, 48, 51, 128, 86, 83, 50, 48, 50, - 128, 86, 83, 50, 48, 49, 128, 86, 83, 50, 48, 48, 128, 86, 83, 50, 48, - 128, 86, 83, 50, 128, 86, 83, 49, 57, 57, 128, 86, 83, 49, 57, 56, 128, - 86, 83, 49, 57, 55, 128, 86, 83, 49, 57, 54, 128, 86, 83, 49, 57, 53, - 128, 86, 83, 49, 57, 52, 128, 86, 83, 49, 57, 51, 128, 86, 83, 49, 57, - 50, 128, 86, 83, 49, 57, 49, 128, 86, 83, 49, 57, 48, 128, 86, 83, 49, - 57, 128, 86, 83, 49, 56, 57, 128, 86, 83, 49, 56, 56, 128, 86, 83, 49, - 56, 55, 128, 86, 83, 49, 56, 54, 128, 86, 83, 49, 56, 53, 128, 86, 83, - 49, 56, 52, 128, 86, 83, 49, 56, 51, 128, 86, 83, 49, 56, 50, 128, 86, - 83, 49, 56, 49, 128, 86, 83, 49, 56, 48, 128, 86, 83, 49, 56, 128, 86, - 83, 49, 55, 57, 128, 86, 83, 49, 55, 56, 128, 86, 83, 49, 55, 55, 128, - 86, 83, 49, 55, 54, 128, 86, 83, 49, 55, 53, 128, 86, 83, 49, 55, 52, - 128, 86, 83, 49, 55, 51, 128, 86, 83, 49, 55, 50, 128, 86, 83, 49, 55, - 49, 128, 86, 83, 49, 55, 48, 128, 86, 83, 49, 55, 128, 86, 83, 49, 54, - 57, 128, 86, 83, 49, 54, 56, 128, 86, 83, 49, 54, 55, 128, 86, 83, 49, - 54, 54, 128, 86, 83, 49, 54, 53, 128, 86, 83, 49, 54, 52, 128, 86, 83, - 49, 54, 51, 128, 86, 83, 49, 54, 50, 128, 86, 83, 49, 54, 49, 128, 86, - 83, 49, 54, 48, 128, 86, 83, 49, 54, 128, 86, 83, 49, 53, 57, 128, 86, - 83, 49, 53, 56, 128, 86, 83, 49, 53, 55, 128, 86, 83, 49, 53, 54, 128, - 86, 83, 49, 53, 53, 128, 86, 83, 49, 53, 52, 128, 86, 83, 49, 53, 51, - 128, 86, 83, 49, 53, 50, 128, 86, 83, 49, 53, 49, 128, 86, 83, 49, 53, - 48, 128, 86, 83, 49, 53, 128, 86, 83, 49, 52, 57, 128, 86, 83, 49, 52, - 56, 128, 86, 83, 49, 52, 55, 128, 86, 83, 49, 52, 54, 128, 86, 83, 49, - 52, 53, 128, 86, 83, 49, 52, 52, 128, 86, 83, 49, 52, 51, 128, 86, 83, - 49, 52, 50, 128, 86, 83, 49, 52, 49, 128, 86, 83, 49, 52, 48, 128, 86, - 83, 49, 52, 128, 86, 83, 49, 51, 57, 128, 86, 83, 49, 51, 56, 128, 86, - 83, 49, 51, 55, 128, 86, 83, 49, 51, 54, 128, 86, 83, 49, 51, 53, 128, - 86, 83, 49, 51, 52, 128, 86, 83, 49, 51, 51, 128, 86, 83, 49, 51, 50, - 128, 86, 83, 49, 51, 49, 128, 86, 83, 49, 51, 48, 128, 86, 83, 49, 51, - 128, 86, 83, 49, 50, 57, 128, 86, 83, 49, 50, 56, 128, 86, 83, 49, 50, - 55, 128, 86, 83, 49, 50, 54, 128, 86, 83, 49, 50, 53, 128, 86, 83, 49, - 50, 52, 128, 86, 83, 49, 50, 51, 128, 86, 83, 49, 50, 50, 128, 86, 83, - 49, 50, 49, 128, 86, 83, 49, 50, 48, 128, 86, 83, 49, 50, 128, 86, 83, - 49, 49, 57, 128, 86, 83, 49, 49, 56, 128, 86, 83, 49, 49, 55, 128, 86, - 83, 49, 49, 54, 128, 86, 83, 49, 49, 53, 128, 86, 83, 49, 49, 52, 128, - 86, 83, 49, 49, 51, 128, 86, 83, 49, 49, 50, 128, 86, 83, 49, 49, 49, - 128, 86, 83, 49, 49, 48, 128, 86, 83, 49, 49, 128, 86, 83, 49, 48, 57, - 128, 86, 83, 49, 48, 56, 128, 86, 83, 49, 48, 55, 128, 86, 83, 49, 48, - 54, 128, 86, 83, 49, 48, 53, 128, 86, 83, 49, 48, 52, 128, 86, 83, 49, - 48, 51, 128, 86, 83, 49, 48, 50, 128, 86, 83, 49, 48, 49, 128, 86, 83, - 49, 48, 48, 128, 86, 83, 49, 48, 128, 86, 83, 49, 128, 86, 83, 128, 86, - 82, 65, 75, 72, 73, 89, 193, 86, 82, 65, 67, 72, 89, 128, 86, 81, 128, - 86, 79, 88, 128, 86, 79, 87, 69, 76, 45, 67, 65, 82, 82, 73, 69, 210, 86, - 79, 87, 128, 86, 79, 85, 128, 86, 79, 84, 128, 86, 79, 211, 86, 79, 80, - 128, 86, 79, 79, 73, 128, 86, 79, 79, 128, 86, 79, 77, 73, 84, 73, 78, - 71, 128, 86, 79, 77, 128, 86, 79, 76, 85, 77, 197, 86, 79, 76, 84, 65, - 71, 197, 86, 79, 76, 76, 69, 89, 66, 65, 76, 76, 128, 86, 79, 76, 67, 65, - 78, 79, 128, 86, 79, 76, 65, 80, 85, 203, 86, 79, 73, 68, 69, 196, 86, - 79, 73, 196, 86, 79, 73, 67, 73, 78, 71, 128, 86, 79, 73, 67, 69, 76, 69, - 83, 211, 86, 79, 73, 67, 69, 196, 86, 79, 68, 128, 86, 79, 67, 65, 76, - 73, 90, 65, 84, 73, 79, 206, 86, 79, 67, 65, 204, 86, 79, 128, 86, 73, - 89, 79, 128, 86, 73, 88, 128, 86, 73, 84, 82, 73, 79, 76, 45, 50, 128, - 86, 73, 84, 82, 73, 79, 76, 128, 86, 73, 84, 72, 75, 85, 81, 201, 86, 73, - 84, 65, 69, 45, 50, 128, 86, 73, 84, 65, 69, 128, 86, 73, 84, 128, 86, - 73, 83, 73, 71, 79, 84, 72, 73, 195, 86, 73, 83, 65, 82, 71, 65, 89, 65, - 128, 86, 73, 83, 65, 82, 71, 65, 128, 86, 73, 83, 65, 82, 71, 193, 86, - 73, 82, 73, 65, 77, 128, 86, 73, 82, 71, 79, 128, 86, 73, 82, 71, 65, - 128, 86, 73, 82, 65, 77, 65, 128, 86, 73, 80, 128, 86, 73, 79, 76, 73, - 78, 128, 86, 73, 78, 69, 71, 65, 82, 45, 51, 128, 86, 73, 78, 69, 71, 65, - 82, 45, 50, 128, 86, 73, 78, 69, 71, 65, 82, 128, 86, 73, 78, 69, 71, 65, - 210, 86, 73, 78, 69, 128, 86, 73, 78, 197, 86, 73, 78, 128, 86, 73, 76, - 76, 65, 71, 69, 128, 86, 73, 73, 128, 86, 73, 71, 73, 78, 84, 73, 76, 69, - 128, 86, 73, 69, 88, 128, 86, 73, 69, 87, 73, 78, 199, 86, 73, 69, 87, - 69, 82, 128, 86, 73, 69, 87, 68, 65, 84, 193, 86, 73, 69, 84, 78, 65, 77, - 69, 83, 197, 86, 73, 69, 84, 128, 86, 73, 69, 212, 86, 73, 69, 80, 128, - 86, 73, 69, 128, 86, 73, 68, 74, 45, 50, 128, 86, 73, 68, 74, 128, 86, - 73, 68, 69, 79, 67, 65, 83, 83, 69, 84, 84, 69, 128, 86, 73, 68, 69, 207, - 86, 73, 68, 65, 128, 86, 73, 67, 84, 79, 82, 217, 86, 73, 66, 82, 65, 84, - 73, 79, 206, 86, 72, 65, 128, 86, 70, 65, 128, 86, 69, 89, 90, 128, 86, - 69, 88, 128, 86, 69, 87, 128, 86, 69, 215, 86, 69, 85, 88, 128, 86, 69, - 85, 77, 128, 86, 69, 85, 65, 69, 80, 69, 78, 128, 86, 69, 85, 65, 69, - 128, 86, 69, 83, 84, 65, 128, 86, 69, 83, 84, 128, 86, 69, 83, 83, 69, - 204, 86, 69, 82, 217, 86, 69, 82, 84, 73, 67, 65, 76, 76, 89, 128, 86, - 69, 82, 84, 73, 67, 65, 76, 76, 217, 86, 69, 82, 84, 73, 67, 65, 76, 45, - 48, 54, 45, 48, 54, 128, 86, 69, 82, 84, 73, 67, 65, 76, 45, 48, 54, 45, - 48, 53, 128, 86, 69, 82, 84, 73, 67, 65, 76, 45, 48, 54, 45, 48, 52, 128, - 86, 69, 82, 84, 73, 67, 65, 76, 45, 48, 54, 45, 48, 51, 128, 86, 69, 82, - 84, 73, 67, 65, 76, 45, 48, 54, 45, 48, 50, 128, 86, 69, 82, 84, 73, 67, - 65, 76, 45, 48, 54, 45, 48, 49, 128, 86, 69, 82, 84, 73, 67, 65, 76, 45, - 48, 54, 45, 48, 48, 128, 86, 69, 82, 84, 73, 67, 65, 76, 45, 48, 53, 45, - 48, 54, 128, 86, 69, 82, 84, 73, 67, 65, 76, 45, 48, 53, 45, 48, 53, 128, - 86, 69, 82, 84, 73, 67, 65, 76, 45, 48, 53, 45, 48, 52, 128, 86, 69, 82, - 84, 73, 67, 65, 76, 45, 48, 53, 45, 48, 51, 128, 86, 69, 82, 84, 73, 67, - 65, 76, 45, 48, 53, 45, 48, 50, 128, 86, 69, 82, 84, 73, 67, 65, 76, 45, - 48, 53, 45, 48, 49, 128, 86, 69, 82, 84, 73, 67, 65, 76, 45, 48, 53, 45, - 48, 48, 128, 86, 69, 82, 84, 73, 67, 65, 76, 45, 48, 52, 45, 48, 54, 128, - 86, 69, 82, 84, 73, 67, 65, 76, 45, 48, 52, 45, 48, 53, 128, 86, 69, 82, - 84, 73, 67, 65, 76, 45, 48, 52, 45, 48, 52, 128, 86, 69, 82, 84, 73, 67, - 65, 76, 45, 48, 52, 45, 48, 51, 128, 86, 69, 82, 84, 73, 67, 65, 76, 45, - 48, 52, 45, 48, 50, 128, 86, 69, 82, 84, 73, 67, 65, 76, 45, 48, 52, 45, - 48, 49, 128, 86, 69, 82, 84, 73, 67, 65, 76, 45, 48, 52, 45, 48, 48, 128, - 86, 69, 82, 84, 73, 67, 65, 76, 45, 48, 51, 45, 48, 54, 128, 86, 69, 82, - 84, 73, 67, 65, 76, 45, 48, 51, 45, 48, 53, 128, 86, 69, 82, 84, 73, 67, - 65, 76, 45, 48, 51, 45, 48, 52, 128, 86, 69, 82, 84, 73, 67, 65, 76, 45, - 48, 51, 45, 48, 51, 128, 86, 69, 82, 84, 73, 67, 65, 76, 45, 48, 51, 45, - 48, 50, 128, 86, 69, 82, 84, 73, 67, 65, 76, 45, 48, 51, 45, 48, 49, 128, - 86, 69, 82, 84, 73, 67, 65, 76, 45, 48, 51, 45, 48, 48, 128, 86, 69, 82, - 84, 73, 67, 65, 76, 45, 48, 50, 45, 48, 54, 128, 86, 69, 82, 84, 73, 67, - 65, 76, 45, 48, 50, 45, 48, 53, 128, 86, 69, 82, 84, 73, 67, 65, 76, 45, - 48, 50, 45, 48, 52, 128, 86, 69, 82, 84, 73, 67, 65, 76, 45, 48, 50, 45, - 48, 51, 128, 86, 69, 82, 84, 73, 67, 65, 76, 45, 48, 50, 45, 48, 50, 128, - 86, 69, 82, 84, 73, 67, 65, 76, 45, 48, 50, 45, 48, 49, 128, 86, 69, 82, - 84, 73, 67, 65, 76, 45, 48, 50, 45, 48, 48, 128, 86, 69, 82, 84, 73, 67, - 65, 76, 45, 48, 49, 45, 48, 54, 128, 86, 69, 82, 84, 73, 67, 65, 76, 45, - 48, 49, 45, 48, 53, 128, 86, 69, 82, 84, 73, 67, 65, 76, 45, 48, 49, 45, - 48, 52, 128, 86, 69, 82, 84, 73, 67, 65, 76, 45, 48, 49, 45, 48, 51, 128, - 86, 69, 82, 84, 73, 67, 65, 76, 45, 48, 49, 45, 48, 50, 128, 86, 69, 82, - 84, 73, 67, 65, 76, 45, 48, 49, 45, 48, 49, 128, 86, 69, 82, 84, 73, 67, - 65, 76, 45, 48, 49, 45, 48, 48, 128, 86, 69, 82, 84, 73, 67, 65, 76, 45, - 48, 48, 45, 48, 54, 128, 86, 69, 82, 84, 73, 67, 65, 76, 45, 48, 48, 45, - 48, 53, 128, 86, 69, 82, 84, 73, 67, 65, 76, 45, 48, 48, 45, 48, 52, 128, - 86, 69, 82, 84, 73, 67, 65, 76, 45, 48, 48, 45, 48, 51, 128, 86, 69, 82, - 84, 73, 67, 65, 76, 45, 48, 48, 45, 48, 50, 128, 86, 69, 82, 84, 73, 67, - 65, 76, 45, 48, 48, 45, 48, 49, 128, 86, 69, 82, 84, 73, 67, 65, 76, 45, - 48, 48, 45, 48, 48, 128, 86, 69, 82, 84, 73, 67, 65, 76, 128, 86, 69, 82, - 83, 73, 67, 76, 69, 128, 86, 69, 82, 83, 197, 86, 69, 82, 71, 69, 128, - 86, 69, 82, 68, 73, 71, 82, 73, 83, 128, 86, 69, 82, 128, 86, 69, 80, - 128, 86, 69, 78, 68, 128, 86, 69, 76, 73, 128, 86, 69, 73, 76, 128, 86, - 69, 72, 73, 67, 76, 69, 128, 86, 69, 72, 128, 86, 69, 200, 86, 69, 69, - 128, 86, 69, 197, 86, 69, 68, 69, 128, 86, 69, 67, 84, 79, 210, 86, 67, - 128, 86, 65, 89, 65, 78, 78, 65, 128, 86, 65, 88, 128, 86, 65, 86, 128, - 86, 65, 214, 86, 65, 85, 128, 86, 65, 84, 72, 89, 128, 86, 65, 84, 128, - 86, 65, 83, 84, 78, 69, 83, 211, 86, 65, 83, 73, 83, 128, 86, 65, 82, 89, - 211, 86, 65, 82, 73, 75, 65, 128, 86, 65, 82, 73, 65, 78, 84, 128, 86, - 65, 82, 73, 65, 78, 212, 86, 65, 82, 73, 65, 128, 86, 65, 82, 73, 193, - 86, 65, 82, 69, 73, 65, 201, 86, 65, 82, 69, 73, 193, 86, 65, 82, 65, 65, - 75, 65, 78, 128, 86, 65, 80, 79, 85, 82, 83, 128, 86, 65, 80, 128, 86, - 65, 78, 69, 128, 86, 65, 77, 80, 73, 82, 69, 128, 86, 65, 77, 65, 71, 79, - 77, 85, 75, 72, 65, 128, 86, 65, 77, 65, 71, 79, 77, 85, 75, 72, 193, 86, - 65, 76, 76, 69, 89, 128, 86, 65, 75, 65, 73, 89, 65, 82, 65, 65, 128, 86, - 65, 74, 128, 86, 65, 73, 128, 86, 65, 72, 128, 86, 65, 200, 86, 65, 65, - 86, 85, 128, 86, 65, 65, 128, 86, 193, 86, 48, 52, 48, 65, 128, 86, 48, - 52, 48, 128, 86, 48, 51, 57, 128, 86, 48, 51, 56, 128, 86, 48, 51, 55, - 65, 128, 86, 48, 51, 55, 128, 86, 48, 51, 54, 128, 86, 48, 51, 53, 128, - 86, 48, 51, 52, 128, 86, 48, 51, 51, 65, 128, 86, 48, 51, 51, 128, 86, - 48, 51, 50, 128, 86, 48, 51, 49, 65, 128, 86, 48, 51, 49, 128, 86, 48, - 51, 48, 65, 128, 86, 48, 51, 48, 128, 86, 48, 50, 57, 65, 128, 86, 48, - 50, 57, 128, 86, 48, 50, 56, 65, 128, 86, 48, 50, 56, 128, 86, 48, 50, - 55, 128, 86, 48, 50, 54, 128, 86, 48, 50, 53, 128, 86, 48, 50, 52, 128, - 86, 48, 50, 51, 65, 128, 86, 48, 50, 51, 128, 86, 48, 50, 50, 128, 86, - 48, 50, 49, 128, 86, 48, 50, 48, 76, 128, 86, 48, 50, 48, 75, 128, 86, - 48, 50, 48, 74, 128, 86, 48, 50, 48, 73, 128, 86, 48, 50, 48, 72, 128, - 86, 48, 50, 48, 71, 128, 86, 48, 50, 48, 70, 128, 86, 48, 50, 48, 69, - 128, 86, 48, 50, 48, 68, 128, 86, 48, 50, 48, 67, 128, 86, 48, 50, 48, - 66, 128, 86, 48, 50, 48, 65, 128, 86, 48, 50, 48, 128, 86, 48, 49, 57, - 128, 86, 48, 49, 56, 128, 86, 48, 49, 55, 128, 86, 48, 49, 54, 128, 86, - 48, 49, 53, 128, 86, 48, 49, 52, 128, 86, 48, 49, 51, 128, 86, 48, 49, - 50, 66, 128, 86, 48, 49, 50, 65, 128, 86, 48, 49, 50, 128, 86, 48, 49, - 49, 68, 128, 86, 48, 49, 49, 67, 128, 86, 48, 49, 49, 66, 128, 86, 48, - 49, 49, 65, 128, 86, 48, 49, 49, 128, 86, 48, 49, 48, 128, 86, 48, 48, - 57, 128, 86, 48, 48, 56, 128, 86, 48, 48, 55, 66, 128, 86, 48, 48, 55, - 65, 128, 86, 48, 48, 55, 128, 86, 48, 48, 54, 128, 86, 48, 48, 53, 128, - 86, 48, 48, 52, 128, 86, 48, 48, 51, 128, 86, 48, 48, 50, 65, 128, 86, - 48, 48, 50, 128, 86, 48, 48, 49, 73, 128, 86, 48, 48, 49, 72, 128, 86, - 48, 48, 49, 71, 128, 86, 48, 48, 49, 70, 128, 86, 48, 48, 49, 69, 128, - 86, 48, 48, 49, 68, 128, 86, 48, 48, 49, 67, 128, 86, 48, 48, 49, 66, - 128, 86, 48, 48, 49, 65, 128, 86, 48, 48, 49, 128, 85, 90, 85, 128, 85, - 90, 72, 65, 75, 75, 85, 128, 85, 90, 51, 128, 85, 90, 179, 85, 90, 128, - 85, 89, 71, 72, 85, 210, 85, 89, 65, 78, 78, 65, 128, 85, 89, 128, 85, - 87, 85, 128, 85, 85, 89, 65, 78, 78, 65, 128, 85, 85, 85, 85, 128, 85, - 85, 85, 51, 128, 85, 85, 85, 50, 128, 85, 85, 69, 128, 85, 84, 85, 75, - 73, 128, 85, 83, 83, 85, 51, 128, 85, 83, 83, 85, 128, 85, 83, 72, 88, - 128, 85, 83, 72, 85, 77, 88, 128, 85, 83, 72, 69, 78, 78, 65, 128, 85, - 83, 72, 50, 128, 85, 83, 72, 128, 85, 83, 200, 85, 83, 69, 196, 85, 83, - 69, 45, 50, 128, 85, 83, 69, 45, 49, 128, 85, 83, 69, 128, 85, 83, 197, - 85, 82, 85, 218, 85, 82, 85, 83, 128, 85, 82, 85, 68, 65, 128, 85, 82, - 85, 68, 193, 85, 82, 85, 128, 85, 82, 213, 85, 82, 78, 128, 85, 82, 73, - 78, 69, 128, 85, 82, 73, 51, 128, 85, 82, 73, 128, 85, 82, 65, 78, 85, - 83, 128, 85, 82, 65, 128, 85, 82, 52, 128, 85, 82, 50, 128, 85, 82, 178, - 85, 80, 87, 65, 82, 68, 83, 128, 85, 80, 87, 65, 82, 68, 211, 85, 80, 87, - 65, 82, 68, 128, 85, 80, 87, 65, 82, 196, 85, 80, 84, 85, 82, 78, 128, - 85, 80, 83, 73, 76, 79, 78, 128, 85, 80, 83, 73, 76, 79, 206, 85, 80, 83, - 73, 68, 69, 45, 68, 79, 87, 206, 85, 80, 82, 73, 71, 72, 212, 85, 80, 80, - 69, 82, 128, 85, 80, 65, 68, 72, 77, 65, 78, 73, 89, 65, 128, 85, 80, 45, - 80, 79, 73, 78, 84, 73, 78, 199, 85, 79, 78, 128, 85, 79, 71, 128, 85, - 78, 78, 128, 85, 78, 77, 65, 82, 82, 73, 69, 196, 85, 78, 75, 78, 79, 87, - 78, 128, 85, 78, 75, 128, 85, 78, 73, 86, 69, 82, 83, 65, 204, 85, 78, - 73, 84, 89, 128, 85, 78, 73, 84, 69, 196, 85, 78, 73, 84, 128, 85, 78, - 73, 212, 85, 78, 73, 79, 78, 128, 85, 78, 73, 79, 206, 85, 78, 73, 70, - 79, 82, 77, 128, 85, 78, 73, 70, 73, 69, 196, 85, 78, 73, 67, 79, 82, - 206, 85, 78, 69, 86, 69, 206, 85, 78, 68, 207, 85, 78, 68, 69, 82, 84, - 73, 69, 128, 85, 78, 68, 69, 82, 76, 73, 78, 197, 85, 78, 68, 69, 82, 68, - 79, 84, 128, 85, 78, 68, 69, 82, 66, 65, 82, 128, 85, 78, 68, 69, 82, - 128, 85, 78, 68, 69, 210, 85, 78, 67, 73, 193, 85, 78, 67, 69, 82, 84, - 65, 73, 78, 84, 217, 85, 78, 66, 76, 69, 78, 68, 69, 196, 85, 78, 65, 83, - 80, 73, 82, 65, 84, 69, 68, 128, 85, 78, 65, 80, 128, 85, 78, 65, 77, 85, - 83, 69, 196, 85, 78, 65, 128, 85, 206, 85, 77, 85, 77, 128, 85, 77, 85, - 205, 85, 77, 66, 82, 69, 76, 76, 65, 128, 85, 77, 66, 82, 69, 76, 76, - 193, 85, 77, 66, 73, 78, 128, 85, 75, 85, 128, 85, 75, 82, 65, 73, 78, - 73, 65, 206, 85, 75, 65, 82, 65, 128, 85, 75, 65, 82, 193, 85, 75, 128, - 85, 73, 90, 128, 85, 73, 88, 128, 85, 73, 85, 90, 128, 85, 73, 85, 88, - 128, 85, 73, 85, 81, 128, 85, 73, 85, 67, 128, 85, 73, 81, 128, 85, 73, - 76, 76, 69, 65, 78, 78, 128, 85, 73, 71, 72, 85, 210, 85, 73, 67, 128, - 85, 72, 68, 128, 85, 71, 65, 82, 73, 84, 73, 195, 85, 69, 90, 128, 85, - 69, 89, 128, 85, 69, 88, 128, 85, 69, 78, 128, 85, 69, 73, 128, 85, 69, - 69, 128, 85, 69, 67, 128, 85, 69, 65, 128, 85, 68, 85, 71, 128, 85, 68, - 65, 84, 84, 65, 128, 85, 68, 65, 84, 84, 193, 85, 68, 65, 82, 75, 65, - 128, 85, 68, 65, 65, 84, 128, 85, 68, 128, 85, 196, 85, 66, 85, 70, 73, - 76, 73, 128, 85, 66, 72, 65, 89, 65, 84, 207, 85, 66, 65, 68, 65, 77, 65, - 128, 85, 66, 128, 85, 65, 84, 72, 128, 85, 65, 78, 71, 128, 85, 65, 128, - 85, 178, 85, 48, 52, 50, 128, 85, 48, 52, 49, 128, 85, 48, 52, 48, 128, - 85, 48, 51, 57, 128, 85, 48, 51, 56, 128, 85, 48, 51, 55, 128, 85, 48, - 51, 54, 128, 85, 48, 51, 53, 128, 85, 48, 51, 52, 128, 85, 48, 51, 51, - 128, 85, 48, 51, 50, 65, 128, 85, 48, 51, 50, 128, 85, 48, 51, 49, 128, - 85, 48, 51, 48, 128, 85, 48, 50, 57, 65, 128, 85, 48, 50, 57, 128, 85, - 48, 50, 56, 128, 85, 48, 50, 55, 128, 85, 48, 50, 54, 128, 85, 48, 50, - 53, 128, 85, 48, 50, 52, 128, 85, 48, 50, 51, 65, 128, 85, 48, 50, 51, - 128, 85, 48, 50, 50, 128, 85, 48, 50, 49, 128, 85, 48, 50, 48, 128, 85, - 48, 49, 57, 128, 85, 48, 49, 56, 128, 85, 48, 49, 55, 128, 85, 48, 49, - 54, 128, 85, 48, 49, 53, 128, 85, 48, 49, 52, 128, 85, 48, 49, 51, 128, - 85, 48, 49, 50, 128, 85, 48, 49, 49, 128, 85, 48, 49, 48, 128, 85, 48, - 48, 57, 128, 85, 48, 48, 56, 128, 85, 48, 48, 55, 128, 85, 48, 48, 54, - 66, 128, 85, 48, 48, 54, 65, 128, 85, 48, 48, 54, 128, 85, 48, 48, 53, - 128, 85, 48, 48, 52, 128, 85, 48, 48, 51, 128, 85, 48, 48, 50, 128, 85, - 48, 48, 49, 128, 85, 45, 83, 72, 65, 80, 69, 196, 85, 45, 73, 45, 73, - 128, 85, 45, 69, 79, 45, 69, 85, 128, 85, 45, 66, 82, 74, 71, 85, 128, - 85, 45, 53, 128, 84, 90, 85, 128, 84, 90, 79, 65, 128, 84, 90, 79, 128, - 84, 90, 73, 210, 84, 90, 73, 128, 84, 90, 69, 69, 128, 84, 90, 69, 128, - 84, 90, 65, 65, 128, 84, 90, 65, 128, 84, 90, 128, 84, 89, 210, 84, 89, - 80, 69, 45, 183, 84, 89, 80, 69, 45, 54, 128, 84, 89, 80, 69, 45, 182, - 84, 89, 80, 69, 45, 53, 128, 84, 89, 80, 69, 45, 181, 84, 89, 80, 69, 45, - 52, 128, 84, 89, 80, 69, 45, 180, 84, 89, 80, 69, 45, 51, 128, 84, 89, - 80, 69, 45, 179, 84, 89, 80, 69, 45, 178, 84, 89, 80, 69, 45, 49, 45, 50, - 128, 84, 89, 80, 69, 45, 177, 84, 89, 80, 197, 84, 89, 79, 128, 84, 89, - 73, 128, 84, 89, 69, 128, 84, 89, 65, 89, 128, 84, 89, 65, 128, 84, 88, - 87, 86, 128, 84, 88, 87, 214, 84, 88, 72, 69, 69, 202, 84, 88, 65, 128, - 84, 87, 79, 79, 128, 84, 87, 79, 45, 87, 65, 217, 84, 87, 79, 45, 84, 72, - 73, 82, 84, 89, 128, 84, 87, 79, 45, 76, 73, 78, 197, 84, 87, 79, 45, 72, - 69, 65, 68, 69, 196, 84, 87, 79, 45, 69, 205, 84, 87, 79, 45, 67, 73, 82, - 67, 76, 197, 84, 87, 73, 83, 84, 73, 78, 71, 128, 84, 87, 73, 83, 84, 69, - 196, 84, 87, 73, 73, 128, 84, 87, 73, 128, 84, 87, 69, 78, 84, 89, 45, - 84, 87, 79, 128, 84, 87, 69, 78, 84, 89, 45, 84, 87, 207, 84, 87, 69, 78, - 84, 89, 45, 84, 72, 82, 69, 69, 128, 84, 87, 69, 78, 84, 89, 45, 83, 73, - 88, 128, 84, 87, 69, 78, 84, 89, 45, 83, 69, 86, 69, 78, 128, 84, 87, 69, - 78, 84, 89, 45, 79, 78, 69, 128, 84, 87, 69, 78, 84, 89, 45, 78, 73, 78, - 69, 128, 84, 87, 69, 78, 84, 89, 45, 70, 79, 85, 82, 128, 84, 87, 69, 78, - 84, 89, 45, 70, 73, 86, 69, 128, 84, 87, 69, 78, 84, 89, 45, 70, 73, 86, - 197, 84, 87, 69, 78, 84, 89, 45, 69, 73, 71, 72, 84, 200, 84, 87, 69, 78, - 84, 89, 45, 69, 73, 71, 72, 84, 128, 84, 87, 69, 78, 84, 89, 128, 84, 87, - 69, 78, 84, 217, 84, 87, 69, 78, 84, 73, 69, 84, 72, 83, 128, 84, 87, 69, - 78, 84, 73, 69, 84, 72, 128, 84, 87, 69, 76, 86, 69, 45, 84, 72, 73, 82, - 84, 89, 128, 84, 87, 69, 76, 86, 69, 128, 84, 87, 69, 76, 86, 197, 84, - 87, 69, 76, 70, 84, 72, 83, 128, 84, 87, 69, 76, 70, 84, 72, 128, 84, 87, - 69, 128, 84, 87, 65, 65, 128, 84, 87, 65, 128, 84, 86, 82, 73, 68, 79, - 128, 84, 86, 73, 77, 65, 68, 85, 210, 84, 85, 88, 69, 68, 79, 128, 84, - 85, 88, 128, 84, 85, 85, 77, 85, 128, 84, 85, 85, 128, 84, 85, 84, 84, - 89, 128, 84, 85, 84, 69, 89, 65, 83, 65, 84, 128, 84, 85, 84, 128, 84, - 85, 82, 88, 128, 84, 85, 82, 85, 128, 84, 85, 82, 84, 76, 69, 128, 84, - 85, 82, 79, 50, 128, 84, 85, 82, 78, 83, 84, 73, 76, 69, 128, 84, 85, 82, - 206, 84, 85, 82, 75, 73, 83, 200, 84, 85, 82, 75, 73, 195, 84, 85, 82, - 75, 69, 89, 128, 84, 85, 82, 66, 65, 78, 128, 84, 85, 82, 128, 84, 85, - 210, 84, 85, 80, 78, 73, 128, 84, 85, 80, 128, 84, 85, 79, 88, 128, 84, - 85, 79, 84, 128, 84, 85, 79, 80, 128, 84, 85, 79, 128, 84, 85, 78, 78, - 89, 128, 84, 85, 77, 69, 84, 69, 83, 128, 84, 85, 77, 66, 76, 69, 210, - 84, 85, 77, 65, 69, 128, 84, 85, 77, 128, 84, 85, 205, 84, 85, 76, 73, - 80, 128, 84, 85, 75, 87, 69, 78, 84, 73, 83, 128, 84, 85, 75, 128, 84, - 85, 71, 82, 73, 203, 84, 85, 71, 50, 128, 84, 85, 71, 178, 84, 85, 66, - 69, 128, 84, 85, 66, 128, 84, 85, 65, 82, 69, 199, 84, 85, 65, 69, 80, - 128, 84, 85, 65, 69, 128, 84, 85, 45, 84, 79, 128, 84, 85, 45, 52, 128, - 84, 85, 45, 51, 128, 84, 85, 45, 50, 128, 84, 85, 45, 49, 128, 84, 213, - 84, 84, 85, 85, 128, 84, 84, 85, 68, 68, 65, 71, 128, 84, 84, 85, 68, 68, - 65, 65, 71, 128, 84, 84, 85, 128, 84, 84, 84, 72, 65, 128, 84, 84, 84, - 65, 128, 84, 84, 83, 85, 128, 84, 84, 83, 79, 128, 84, 84, 83, 73, 128, - 84, 84, 83, 69, 69, 128, 84, 84, 83, 69, 128, 84, 84, 83, 65, 128, 84, - 84, 79, 79, 128, 84, 84, 73, 73, 128, 84, 84, 73, 128, 84, 84, 72, 87, - 69, 128, 84, 84, 72, 85, 128, 84, 84, 72, 79, 79, 128, 84, 84, 72, 79, - 128, 84, 84, 72, 73, 128, 84, 84, 72, 69, 69, 128, 84, 84, 72, 69, 128, - 84, 84, 72, 65, 65, 128, 84, 84, 72, 128, 84, 84, 69, 72, 69, 72, 128, - 84, 84, 69, 72, 69, 200, 84, 84, 69, 72, 128, 84, 84, 69, 200, 84, 84, - 69, 69, 128, 84, 84, 65, 89, 65, 78, 78, 65, 128, 84, 84, 65, 85, 128, - 84, 84, 65, 73, 128, 84, 84, 65, 65, 128, 84, 84, 50, 128, 84, 83, 87, - 69, 128, 84, 83, 87, 66, 128, 84, 83, 87, 65, 128, 84, 83, 86, 128, 84, - 83, 83, 69, 128, 84, 83, 83, 65, 128, 84, 83, 79, 214, 84, 83, 73, 85, - 128, 84, 83, 72, 85, 71, 83, 128, 84, 83, 72, 79, 79, 75, 128, 84, 83, - 72, 79, 79, 203, 84, 83, 72, 79, 79, 74, 128, 84, 83, 72, 69, 83, 128, - 84, 83, 72, 69, 71, 128, 84, 83, 72, 69, 199, 84, 83, 72, 69, 69, 74, - 128, 84, 83, 72, 69, 128, 84, 83, 72, 65, 194, 84, 83, 72, 65, 128, 84, - 83, 69, 82, 69, 128, 84, 83, 69, 69, 66, 128, 84, 83, 65, 84, 193, 84, - 83, 65, 68, 73, 128, 84, 83, 65, 68, 201, 84, 83, 65, 66, 128, 84, 83, - 65, 65, 68, 73, 89, 128, 84, 83, 65, 65, 128, 84, 83, 193, 84, 82, 89, - 66, 76, 73, 79, 206, 84, 82, 89, 65, 83, 79, 83, 84, 82, 69, 76, 78, 65, - 89, 65, 128, 84, 82, 89, 65, 83, 79, 80, 79, 86, 79, 68, 78, 65, 89, 65, - 128, 84, 82, 89, 65, 83, 79, 71, 76, 65, 83, 78, 65, 89, 65, 128, 84, 82, - 89, 65, 83, 75, 65, 128, 84, 82, 85, 84, 72, 128, 84, 82, 85, 78, 75, - 128, 84, 82, 85, 78, 67, 65, 84, 69, 196, 84, 82, 85, 77, 80, 69, 84, - 128, 84, 82, 85, 77, 80, 45, 57, 128, 84, 82, 85, 77, 80, 45, 56, 128, - 84, 82, 85, 77, 80, 45, 55, 128, 84, 82, 85, 77, 80, 45, 54, 128, 84, 82, - 85, 77, 80, 45, 53, 128, 84, 82, 85, 77, 80, 45, 52, 128, 84, 82, 85, 77, - 80, 45, 51, 128, 84, 82, 85, 77, 80, 45, 50, 49, 128, 84, 82, 85, 77, 80, - 45, 50, 48, 128, 84, 82, 85, 77, 80, 45, 50, 128, 84, 82, 85, 77, 80, 45, - 49, 57, 128, 84, 82, 85, 77, 80, 45, 49, 56, 128, 84, 82, 85, 77, 80, 45, - 49, 55, 128, 84, 82, 85, 77, 80, 45, 49, 54, 128, 84, 82, 85, 77, 80, 45, - 49, 53, 128, 84, 82, 85, 77, 80, 45, 49, 52, 128, 84, 82, 85, 77, 80, 45, - 49, 51, 128, 84, 82, 85, 77, 80, 45, 49, 50, 128, 84, 82, 85, 77, 80, 45, - 49, 49, 128, 84, 82, 85, 77, 80, 45, 49, 48, 128, 84, 82, 85, 77, 80, 45, - 49, 128, 84, 82, 85, 69, 128, 84, 82, 85, 197, 84, 82, 85, 67, 75, 128, - 84, 82, 79, 80, 73, 67, 65, 204, 84, 82, 79, 80, 72, 89, 128, 84, 82, 79, - 77, 73, 75, 79, 83, 89, 78, 65, 71, 77, 65, 128, 84, 82, 79, 77, 73, 75, - 79, 80, 83, 73, 70, 73, 83, 84, 79, 78, 128, 84, 82, 79, 77, 73, 75, 79, - 80, 65, 82, 65, 75, 65, 76, 69, 83, 77, 65, 128, 84, 82, 79, 77, 73, 75, - 79, 78, 128, 84, 82, 79, 77, 73, 75, 79, 206, 84, 82, 79, 77, 73, 75, 79, - 76, 89, 71, 73, 83, 77, 65, 128, 84, 82, 79, 76, 76, 69, 89, 66, 85, 83, - 128, 84, 82, 79, 76, 76, 69, 89, 128, 84, 82, 79, 76, 76, 128, 84, 82, - 79, 75, 85, 84, 65, 83, 84, 201, 84, 82, 79, 69, 90, 69, 78, 73, 65, 206, - 84, 82, 73, 85, 77, 80, 72, 128, 84, 82, 73, 84, 79, 211, 84, 82, 73, 84, - 73, 77, 79, 82, 73, 79, 78, 128, 84, 82, 73, 83, 73, 77, 79, 85, 128, 84, - 82, 73, 83, 69, 77, 69, 128, 84, 82, 73, 80, 79, 68, 128, 84, 82, 73, 80, - 76, 73, 128, 84, 82, 73, 80, 76, 69, 128, 84, 82, 73, 80, 76, 197, 84, - 82, 73, 79, 206, 84, 82, 73, 76, 76, 73, 79, 78, 83, 128, 84, 82, 73, 76, - 76, 128, 84, 82, 73, 73, 83, 65, 80, 128, 84, 82, 73, 71, 82, 65, 77, 77, - 79, 211, 84, 82, 73, 71, 82, 65, 205, 84, 82, 73, 71, 79, 82, 71, 79, 78, - 128, 84, 82, 73, 70, 79, 78, 73, 65, 83, 128, 84, 82, 73, 70, 79, 76, 73, - 65, 84, 197, 84, 82, 73, 68, 69, 78, 84, 128, 84, 82, 73, 68, 69, 78, - 212, 84, 82, 73, 67, 79, 76, 79, 78, 128, 84, 82, 73, 65, 78, 71, 85, 76, - 65, 210, 84, 82, 73, 65, 78, 71, 76, 69, 45, 82, 79, 85, 78, 196, 84, 82, - 73, 65, 78, 71, 76, 69, 45, 72, 69, 65, 68, 69, 196, 84, 82, 73, 65, 78, - 71, 76, 69, 128, 84, 82, 73, 65, 78, 71, 76, 197, 84, 82, 73, 65, 128, - 84, 82, 73, 128, 84, 82, 69, 83, 86, 69, 84, 76, 89, 128, 84, 82, 69, 83, - 86, 69, 84, 76, 79, 128, 84, 82, 69, 83, 86, 69, 84, 76, 65, 89, 65, 128, - 84, 82, 69, 83, 73, 76, 76, 79, 128, 84, 82, 69, 78, 68, 128, 84, 82, 69, - 78, 196, 84, 82, 69, 77, 79, 76, 79, 45, 51, 128, 84, 82, 69, 77, 79, 76, - 79, 45, 50, 128, 84, 82, 69, 77, 79, 76, 79, 45, 49, 128, 84, 82, 69, 69, - 128, 84, 82, 69, 197, 84, 82, 69, 68, 69, 67, 73, 76, 69, 128, 84, 82, - 69, 65, 68, 73, 78, 71, 128, 84, 82, 65, 89, 128, 84, 82, 65, 86, 69, 76, - 45, 87, 65, 76, 76, 80, 76, 65, 78, 197, 84, 82, 65, 86, 69, 76, 45, 70, - 76, 79, 79, 82, 80, 76, 65, 78, 197, 84, 82, 65, 80, 69, 90, 73, 85, 77, - 128, 84, 82, 65, 80, 128, 84, 82, 65, 78, 83, 86, 69, 82, 83, 65, 204, - 84, 82, 65, 78, 83, 80, 79, 83, 73, 84, 73, 79, 206, 84, 82, 65, 78, 83, - 80, 76, 85, 84, 79, 128, 84, 82, 65, 78, 83, 77, 73, 212, 84, 82, 65, 78, - 83, 77, 73, 83, 83, 73, 79, 78, 128, 84, 82, 65, 78, 83, 77, 73, 83, 83, - 73, 79, 206, 84, 82, 65, 77, 87, 65, 89, 128, 84, 82, 65, 77, 128, 84, - 82, 65, 205, 84, 82, 65, 73, 78, 128, 84, 82, 65, 73, 206, 84, 82, 65, - 73, 76, 73, 78, 199, 84, 82, 65, 70, 70, 73, 67, 128, 84, 82, 65, 70, 70, - 73, 195, 84, 82, 65, 68, 73, 84, 73, 79, 78, 65, 204, 84, 82, 65, 68, - 197, 84, 82, 65, 67, 84, 79, 82, 128, 84, 82, 65, 67, 75, 66, 65, 76, 76, - 128, 84, 82, 65, 67, 75, 128, 84, 82, 65, 128, 84, 82, 128, 84, 79, 89, - 79, 82, 128, 84, 79, 88, 128, 84, 79, 87, 69, 82, 128, 84, 79, 87, 65, - 82, 68, 211, 84, 79, 86, 128, 84, 79, 85, 82, 78, 79, 73, 211, 84, 79, - 85, 67, 72, 84, 79, 78, 197, 84, 79, 85, 67, 72, 73, 78, 199, 84, 79, 85, - 67, 72, 69, 211, 84, 79, 85, 67, 200, 84, 79, 84, 207, 84, 79, 84, 65, - 204, 84, 79, 84, 128, 84, 79, 83, 128, 84, 79, 82, 84, 79, 73, 83, 197, - 84, 79, 82, 83, 79, 45, 87, 65, 76, 76, 80, 76, 65, 78, 197, 84, 79, 82, - 83, 79, 45, 70, 76, 79, 79, 82, 80, 76, 65, 78, 197, 84, 79, 82, 83, 79, - 128, 84, 79, 82, 78, 65, 68, 79, 128, 84, 79, 82, 67, 85, 76, 85, 83, - 128, 84, 79, 82, 67, 85, 76, 85, 211, 84, 79, 82, 67, 72, 128, 84, 79, - 81, 128, 84, 79, 80, 66, 65, 82, 128, 84, 79, 80, 45, 76, 73, 71, 72, 84, - 69, 196, 84, 79, 80, 128, 84, 79, 208, 84, 79, 79, 84, 72, 66, 82, 85, - 83, 72, 128, 84, 79, 79, 84, 72, 128, 84, 79, 79, 78, 128, 84, 79, 79, - 76, 66, 79, 88, 128, 84, 79, 78, 79, 83, 128, 84, 79, 78, 71, 85, 69, - 128, 84, 79, 78, 71, 85, 197, 84, 79, 78, 71, 128, 84, 79, 78, 69, 45, - 86, 128, 84, 79, 78, 69, 45, 83, 128, 84, 79, 78, 69, 45, 77, 128, 84, - 79, 78, 69, 45, 74, 128, 84, 79, 78, 69, 45, 71, 128, 84, 79, 78, 69, 45, - 68, 128, 84, 79, 78, 69, 45, 66, 128, 84, 79, 78, 69, 45, 56, 128, 84, - 79, 78, 69, 45, 55, 128, 84, 79, 78, 69, 45, 54, 128, 84, 79, 78, 69, 45, - 53, 128, 84, 79, 78, 69, 45, 52, 128, 84, 79, 78, 69, 45, 51, 128, 84, - 79, 78, 69, 45, 50, 128, 84, 79, 78, 69, 45, 49, 128, 84, 79, 78, 69, - 128, 84, 79, 78, 65, 204, 84, 79, 77, 80, 73, 128, 84, 79, 77, 65, 84, - 79, 128, 84, 79, 76, 79, 78, 71, 128, 84, 79, 75, 89, 207, 84, 79, 73, - 76, 69, 84, 128, 84, 79, 71, 69, 84, 72, 69, 82, 128, 84, 79, 68, 207, - 84, 79, 67, 72, 75, 65, 128, 84, 79, 65, 78, 68, 65, 75, 72, 73, 65, 84, - 128, 84, 79, 65, 128, 84, 79, 45, 82, 65, 128, 84, 79, 45, 54, 128, 84, - 79, 45, 53, 128, 84, 79, 45, 52, 128, 84, 79, 45, 51, 128, 84, 79, 45, - 50, 128, 84, 79, 45, 49, 128, 84, 78, 128, 84, 76, 86, 128, 84, 76, 85, - 128, 84, 76, 73, 128, 84, 76, 72, 89, 65, 128, 84, 76, 72, 87, 69, 128, - 84, 76, 72, 85, 128, 84, 76, 72, 79, 79, 128, 84, 76, 72, 79, 128, 84, - 76, 72, 73, 128, 84, 76, 72, 69, 69, 128, 84, 76, 72, 69, 128, 84, 76, - 72, 65, 128, 84, 76, 69, 69, 128, 84, 76, 65, 128, 84, 74, 69, 128, 84, - 73, 88, 128, 84, 73, 87, 82, 128, 84, 73, 87, 78, 128, 84, 73, 87, 65, - 218, 84, 73, 84, 85, 65, 69, 80, 128, 84, 73, 84, 76, 79, 128, 84, 73, - 84, 76, 207, 84, 73, 84, 193, 84, 73, 84, 128, 84, 73, 82, 89, 65, 75, - 128, 84, 73, 82, 84, 193, 84, 73, 82, 79, 78, 73, 65, 206, 84, 73, 82, - 72, 85, 84, 193, 84, 73, 82, 69, 196, 84, 73, 82, 128, 84, 73, 210, 84, - 73, 80, 80, 73, 128, 84, 73, 80, 69, 72, 65, 128, 84, 73, 80, 128, 84, - 73, 208, 84, 73, 78, 89, 128, 84, 73, 78, 217, 84, 73, 78, 78, 69, 128, - 84, 73, 78, 67, 84, 85, 82, 69, 128, 84, 73, 78, 65, 71, 77, 65, 128, 84, - 73, 77, 69, 83, 128, 84, 73, 77, 69, 210, 84, 73, 77, 69, 128, 84, 73, - 76, 84, 73, 78, 71, 128, 84, 73, 76, 84, 73, 78, 199, 84, 73, 76, 84, - 128, 84, 73, 76, 69, 83, 128, 84, 73, 76, 68, 69, 128, 84, 73, 76, 68, - 197, 84, 73, 76, 128, 84, 73, 204, 84, 73, 75, 72, 89, 128, 84, 73, 75, - 72, 65, 89, 65, 128, 84, 73, 75, 72, 65, 89, 193, 84, 73, 75, 69, 85, 84, - 45, 84, 72, 73, 69, 85, 84, 72, 128, 84, 73, 75, 69, 85, 84, 45, 83, 73, - 79, 83, 45, 75, 73, 89, 69, 79, 75, 128, 84, 73, 75, 69, 85, 84, 45, 83, - 73, 79, 83, 128, 84, 73, 75, 69, 85, 84, 45, 82, 73, 69, 85, 76, 128, 84, - 73, 75, 69, 85, 84, 45, 80, 73, 69, 85, 80, 128, 84, 73, 75, 69, 85, 84, - 45, 77, 73, 69, 85, 77, 128, 84, 73, 75, 69, 85, 84, 45, 75, 73, 89, 69, - 79, 75, 128, 84, 73, 75, 69, 85, 84, 45, 67, 73, 69, 85, 67, 128, 84, 73, - 75, 69, 85, 84, 45, 67, 72, 73, 69, 85, 67, 72, 128, 84, 73, 75, 69, 85, - 84, 128, 84, 73, 75, 69, 85, 212, 84, 73, 71, 72, 84, 76, 89, 45, 67, 76, - 79, 83, 69, 196, 84, 73, 71, 72, 212, 84, 73, 71, 69, 82, 128, 84, 73, - 71, 69, 210, 84, 73, 70, 73, 78, 65, 71, 200, 84, 73, 69, 88, 128, 84, - 73, 69, 80, 128, 84, 73, 197, 84, 73, 67, 75, 69, 84, 83, 128, 84, 73, - 67, 75, 69, 84, 128, 84, 73, 67, 75, 128, 84, 73, 67, 203, 84, 73, 65, - 82, 65, 128, 84, 73, 50, 128, 84, 73, 45, 55, 128, 84, 73, 45, 54, 128, - 84, 73, 45, 53, 128, 84, 73, 45, 52, 128, 84, 73, 45, 51, 128, 84, 73, - 45, 50, 128, 84, 73, 45, 49, 128, 84, 72, 90, 128, 84, 72, 89, 79, 79, - 205, 84, 72, 87, 79, 79, 128, 84, 72, 87, 79, 128, 84, 72, 87, 73, 73, - 128, 84, 72, 87, 73, 128, 84, 72, 87, 69, 69, 128, 84, 72, 87, 65, 65, - 128, 84, 72, 87, 65, 128, 84, 72, 85, 82, 211, 84, 72, 85, 82, 73, 83, - 65, 218, 84, 72, 85, 78, 71, 128, 84, 72, 85, 78, 68, 69, 82, 83, 84, 79, - 82, 77, 128, 84, 72, 85, 78, 68, 69, 82, 128, 84, 72, 85, 78, 68, 69, - 210, 84, 72, 85, 77, 66, 211, 84, 72, 85, 77, 66, 128, 84, 72, 82, 79, - 87, 73, 78, 199, 84, 72, 82, 79, 85, 71, 72, 128, 84, 72, 82, 79, 85, 71, - 200, 84, 72, 82, 69, 69, 45, 84, 72, 73, 82, 84, 89, 128, 84, 72, 82, 69, - 69, 45, 81, 85, 65, 82, 84, 69, 210, 84, 72, 82, 69, 69, 45, 80, 69, 82, - 45, 69, 205, 84, 72, 82, 69, 69, 45, 76, 73, 78, 197, 84, 72, 82, 69, 69, - 45, 76, 69, 71, 71, 69, 196, 84, 72, 82, 69, 69, 45, 72, 85, 78, 68, 82, - 69, 68, 45, 65, 78, 68, 45, 84, 87, 69, 78, 84, 73, 69, 84, 72, 128, 84, - 72, 82, 69, 69, 45, 69, 205, 84, 72, 82, 69, 69, 45, 68, 79, 212, 84, 72, - 82, 69, 69, 45, 196, 84, 72, 82, 69, 69, 45, 67, 73, 82, 67, 76, 197, 84, - 72, 82, 69, 65, 68, 128, 84, 72, 79, 85, 83, 65, 78, 68, 83, 128, 84, 72, - 79, 85, 83, 65, 78, 68, 211, 84, 72, 79, 85, 83, 65, 78, 196, 84, 72, 79, - 85, 71, 72, 212, 84, 72, 79, 85, 128, 84, 72, 79, 82, 78, 128, 84, 72, - 79, 82, 206, 84, 72, 79, 78, 71, 128, 84, 72, 79, 78, 199, 84, 72, 79, - 77, 128, 84, 72, 79, 74, 128, 84, 72, 79, 65, 128, 84, 72, 207, 84, 72, - 73, 85, 84, 72, 128, 84, 72, 73, 84, 65, 128, 84, 72, 73, 82, 84, 89, 45, - 83, 69, 67, 79, 78, 68, 128, 84, 72, 73, 82, 84, 89, 45, 83, 69, 67, 79, - 78, 196, 84, 72, 73, 82, 84, 89, 45, 79, 78, 69, 128, 84, 72, 73, 82, 84, - 89, 45, 70, 73, 86, 197, 84, 72, 73, 82, 84, 217, 84, 72, 73, 82, 84, 69, - 69, 78, 128, 84, 72, 73, 82, 84, 69, 69, 206, 84, 72, 73, 82, 68, 83, - 128, 84, 72, 73, 82, 68, 211, 84, 72, 73, 82, 68, 45, 83, 84, 65, 71, - 197, 84, 72, 73, 82, 68, 128, 84, 72, 73, 82, 196, 84, 72, 73, 78, 75, - 73, 78, 199, 84, 72, 73, 78, 71, 128, 84, 72, 73, 73, 128, 84, 72, 73, - 71, 72, 128, 84, 72, 73, 69, 85, 84, 200, 84, 72, 73, 67, 203, 84, 72, - 73, 65, 66, 128, 84, 72, 69, 89, 128, 84, 72, 69, 84, 72, 69, 128, 84, - 72, 69, 84, 72, 128, 84, 72, 69, 84, 65, 128, 84, 72, 69, 84, 193, 84, - 72, 69, 83, 80, 73, 65, 206, 84, 72, 69, 83, 69, 79, 83, 128, 84, 72, 69, - 83, 69, 79, 211, 84, 72, 69, 211, 84, 72, 69, 82, 77, 79, 77, 69, 84, 69, - 82, 128, 84, 72, 69, 82, 77, 79, 68, 89, 78, 65, 77, 73, 67, 128, 84, 72, - 69, 82, 69, 70, 79, 82, 69, 128, 84, 72, 69, 82, 197, 84, 72, 69, 206, - 84, 72, 69, 77, 65, 84, 73, 83, 77, 79, 211, 84, 72, 69, 77, 65, 128, 84, - 72, 69, 77, 193, 84, 72, 69, 72, 128, 84, 72, 69, 200, 84, 72, 69, 65, - 128, 84, 72, 197, 84, 72, 65, 87, 128, 84, 72, 65, 78, 84, 72, 65, 75, - 72, 65, 84, 128, 84, 72, 65, 78, 78, 65, 128, 84, 72, 65, 78, 128, 84, - 72, 65, 206, 84, 72, 65, 77, 69, 68, 72, 128, 84, 72, 65, 76, 128, 84, - 72, 65, 204, 84, 72, 65, 74, 128, 84, 72, 65, 201, 84, 72, 65, 72, 65, - 78, 128, 84, 72, 65, 65, 78, 193, 84, 72, 65, 65, 76, 85, 128, 84, 72, - 45, 67, 82, 69, 197, 84, 69, 88, 84, 128, 84, 69, 88, 212, 84, 69, 88, - 128, 84, 69, 86, 73, 82, 128, 84, 69, 85, 84, 69, 85, 88, 128, 84, 69, - 85, 84, 69, 85, 87, 69, 78, 128, 84, 69, 85, 84, 128, 84, 69, 85, 78, - 128, 84, 69, 85, 65, 69, 81, 128, 84, 69, 85, 65, 69, 78, 128, 84, 69, - 85, 128, 84, 69, 84, 82, 65, 83, 73, 77, 79, 85, 128, 84, 69, 84, 82, 65, - 83, 69, 77, 69, 128, 84, 69, 84, 82, 65, 80, 76, 73, 128, 84, 69, 84, 82, - 65, 71, 82, 65, 205, 84, 69, 84, 82, 65, 70, 79, 78, 73, 65, 83, 128, 84, - 69, 84, 72, 128, 84, 69, 84, 200, 84, 69, 84, 65, 82, 84, 79, 211, 84, - 69, 84, 65, 82, 84, 73, 77, 79, 82, 73, 79, 78, 128, 84, 69, 84, 128, 84, - 69, 212, 84, 69, 83, 212, 84, 69, 83, 83, 69, 82, 65, 128, 84, 69, 83, - 83, 69, 82, 193, 84, 69, 83, 83, 65, 82, 79, 206, 84, 69, 83, 200, 84, - 69, 82, 77, 73, 78, 65, 84, 79, 82, 128, 84, 69, 82, 77, 73, 78, 65, 204, - 84, 69, 80, 128, 84, 69, 78, 85, 84, 79, 128, 84, 69, 78, 85, 128, 84, - 69, 78, 213, 84, 69, 78, 84, 72, 128, 84, 69, 78, 84, 128, 84, 69, 78, - 83, 69, 128, 84, 69, 78, 83, 197, 84, 69, 78, 83, 128, 84, 69, 78, 211, - 84, 69, 78, 78, 73, 211, 84, 69, 78, 71, 197, 84, 69, 78, 45, 84, 72, 73, - 82, 84, 89, 128, 84, 69, 78, 128, 84, 69, 206, 84, 69, 77, 80, 85, 211, - 84, 69, 77, 80, 76, 69, 128, 84, 69, 76, 85, 71, 213, 84, 69, 76, 85, - 128, 84, 69, 76, 79, 85, 211, 84, 69, 76, 76, 69, 210, 84, 69, 76, 73, - 83, 72, 193, 84, 69, 76, 69, 86, 73, 83, 73, 79, 78, 128, 84, 69, 76, 69, - 83, 67, 79, 80, 69, 128, 84, 69, 76, 69, 80, 72, 79, 78, 69, 128, 84, 69, - 76, 69, 80, 72, 79, 78, 197, 84, 69, 76, 69, 73, 65, 128, 84, 69, 76, 69, - 71, 82, 65, 80, 200, 84, 69, 75, 128, 84, 69, 73, 87, 83, 128, 84, 69, - 71, 69, 72, 128, 84, 69, 69, 84, 72, 128, 84, 69, 69, 84, 200, 84, 69, - 69, 78, 83, 128, 84, 69, 69, 69, 69, 128, 84, 69, 197, 84, 69, 68, 85, - 78, 71, 128, 84, 69, 68, 68, 217, 84, 69, 65, 82, 83, 128, 84, 69, 65, - 82, 211, 84, 69, 65, 82, 68, 82, 79, 80, 45, 83, 80, 79, 75, 69, 196, 84, - 69, 65, 82, 68, 82, 79, 80, 45, 83, 72, 65, 78, 75, 69, 196, 84, 69, 65, - 82, 68, 82, 79, 80, 45, 66, 65, 82, 66, 69, 196, 84, 69, 65, 82, 45, 79, - 70, 198, 84, 69, 65, 82, 128, 84, 69, 65, 80, 79, 84, 128, 84, 69, 65, - 67, 85, 208, 84, 69, 65, 128, 84, 69, 45, 85, 128, 84, 69, 45, 57, 128, - 84, 69, 45, 56, 128, 84, 69, 45, 55, 128, 84, 69, 45, 54, 128, 84, 69, - 45, 53, 128, 84, 69, 45, 52, 128, 84, 69, 45, 51, 128, 84, 69, 45, 50, - 128, 84, 69, 45, 49, 128, 84, 67, 72, 69, 72, 69, 72, 128, 84, 67, 72, - 69, 72, 69, 200, 84, 67, 72, 69, 72, 128, 84, 67, 72, 69, 200, 84, 67, - 72, 69, 128, 84, 195, 84, 65, 89, 128, 84, 65, 88, 73, 128, 84, 65, 88, - 128, 84, 65, 87, 69, 76, 76, 69, 77, 69, 212, 84, 65, 87, 65, 128, 84, - 65, 87, 128, 84, 65, 215, 84, 65, 86, 73, 89, 65, 78, 73, 128, 84, 65, - 86, 128, 84, 65, 214, 84, 65, 85, 82, 85, 83, 128, 84, 65, 85, 77, 128, - 84, 65, 213, 84, 65, 84, 87, 69, 69, 76, 128, 84, 65, 84, 87, 69, 69, - 204, 84, 65, 84, 84, 79, 79, 69, 196, 84, 65, 84, 128, 84, 65, 83, 83, - 73, 128, 84, 65, 83, 72, 69, 69, 76, 128, 84, 65, 83, 128, 84, 65, 82, - 85, 78, 71, 128, 84, 65, 82, 84, 65, 82, 45, 50, 128, 84, 65, 82, 84, 65, - 82, 128, 84, 65, 82, 71, 69, 84, 128, 84, 65, 81, 128, 84, 65, 80, 69, - 82, 128, 84, 65, 80, 197, 84, 65, 80, 128, 84, 65, 79, 128, 84, 65, 78, - 78, 69, 196, 84, 65, 78, 71, 83, 193, 84, 65, 78, 71, 69, 82, 73, 78, 69, - 128, 84, 65, 78, 71, 69, 78, 84, 128, 84, 65, 78, 71, 69, 78, 212, 84, - 65, 78, 199, 84, 65, 78, 65, 66, 65, 84, 193, 84, 65, 78, 65, 128, 84, - 65, 78, 128, 84, 65, 77, 73, 78, 71, 128, 84, 65, 77, 65, 206, 84, 65, - 77, 65, 76, 69, 128, 84, 65, 77, 128, 84, 65, 76, 76, 217, 84, 65, 76, - 76, 128, 84, 65, 76, 204, 84, 65, 76, 73, 78, 71, 128, 84, 65, 76, 73, - 78, 199, 84, 65, 76, 69, 78, 84, 83, 128, 84, 65, 76, 69, 78, 212, 84, - 65, 75, 82, 201, 84, 65, 75, 72, 65, 76, 76, 85, 83, 128, 84, 65, 75, 69, - 79, 85, 212, 84, 65, 75, 69, 128, 84, 65, 75, 52, 128, 84, 65, 75, 180, - 84, 65, 75, 128, 84, 65, 73, 83, 89, 79, 85, 128, 84, 65, 73, 76, 76, 69, - 83, 211, 84, 65, 73, 76, 128, 84, 65, 73, 204, 84, 65, 72, 65, 76, 65, - 128, 84, 65, 72, 128, 84, 65, 200, 84, 65, 71, 66, 65, 78, 87, 193, 84, - 65, 71, 65, 76, 79, 199, 84, 65, 71, 128, 84, 65, 199, 84, 65, 69, 206, - 84, 65, 67, 79, 128, 84, 65, 67, 75, 128, 84, 65, 67, 203, 84, 65, 66, - 85, 76, 65, 84, 73, 79, 78, 128, 84, 65, 66, 85, 76, 65, 84, 73, 79, 206, - 84, 65, 66, 83, 128, 84, 65, 66, 76, 69, 128, 84, 65, 66, 76, 197, 84, - 65, 66, 65, 65, 82, 65, 75, 193, 84, 65, 66, 128, 84, 65, 194, 84, 65, - 65, 83, 72, 65, 69, 128, 84, 65, 65, 81, 128, 84, 65, 65, 77, 128, 84, - 65, 65, 76, 85, 74, 193, 84, 65, 65, 73, 128, 84, 65, 65, 70, 128, 84, - 65, 50, 128, 84, 65, 45, 82, 79, 76, 128, 84, 65, 45, 52, 128, 84, 65, - 45, 51, 128, 84, 65, 45, 50, 128, 84, 65, 45, 49, 128, 84, 48, 51, 54, - 128, 84, 48, 51, 53, 128, 84, 48, 51, 52, 128, 84, 48, 51, 51, 65, 128, - 84, 48, 51, 51, 128, 84, 48, 51, 50, 65, 128, 84, 48, 51, 50, 128, 84, - 48, 51, 49, 128, 84, 48, 51, 48, 128, 84, 48, 50, 57, 128, 84, 48, 50, - 56, 128, 84, 48, 50, 55, 128, 84, 48, 50, 54, 128, 84, 48, 50, 53, 128, - 84, 48, 50, 52, 128, 84, 48, 50, 51, 128, 84, 48, 50, 50, 128, 84, 48, - 50, 49, 128, 84, 48, 50, 48, 128, 84, 48, 49, 57, 128, 84, 48, 49, 56, - 128, 84, 48, 49, 55, 128, 84, 48, 49, 54, 65, 128, 84, 48, 49, 54, 128, - 84, 48, 49, 53, 128, 84, 48, 49, 52, 128, 84, 48, 49, 51, 128, 84, 48, - 49, 50, 128, 84, 48, 49, 49, 65, 128, 84, 48, 49, 49, 128, 84, 48, 49, - 48, 128, 84, 48, 48, 57, 65, 128, 84, 48, 48, 57, 128, 84, 48, 48, 56, - 65, 128, 84, 48, 48, 56, 128, 84, 48, 48, 55, 65, 128, 84, 48, 48, 55, - 128, 84, 48, 48, 54, 128, 84, 48, 48, 53, 128, 84, 48, 48, 52, 128, 84, - 48, 48, 51, 65, 128, 84, 48, 48, 51, 128, 84, 48, 48, 50, 128, 84, 48, - 48, 49, 128, 84, 45, 83, 72, 73, 82, 84, 128, 84, 45, 82, 69, 88, 128, - 83, 90, 90, 128, 83, 90, 87, 71, 128, 83, 90, 87, 65, 128, 83, 90, 85, - 128, 83, 90, 79, 128, 83, 90, 73, 128, 83, 90, 69, 69, 128, 83, 90, 69, - 128, 83, 90, 65, 65, 128, 83, 90, 65, 128, 83, 90, 128, 83, 89, 88, 128, - 83, 89, 84, 128, 83, 89, 83, 84, 69, 205, 83, 89, 82, 88, 128, 83, 89, - 82, 77, 65, 84, 73, 75, 73, 128, 83, 89, 82, 77, 65, 128, 83, 89, 82, 73, - 78, 71, 69, 128, 83, 89, 82, 73, 65, 195, 83, 89, 82, 128, 83, 89, 80, - 128, 83, 89, 79, 85, 87, 65, 128, 83, 89, 78, 69, 86, 77, 65, 128, 83, - 89, 78, 68, 69, 83, 77, 79, 211, 83, 89, 78, 67, 72, 82, 79, 78, 79, 85, - 211, 83, 89, 78, 65, 71, 79, 71, 85, 69, 128, 83, 89, 78, 65, 71, 77, - 193, 83, 89, 78, 65, 70, 73, 128, 83, 89, 78, 128, 83, 89, 77, 77, 69, - 84, 82, 89, 128, 83, 89, 77, 77, 69, 84, 82, 73, 195, 83, 89, 77, 66, 79, - 76, 83, 128, 83, 89, 77, 66, 79, 76, 211, 83, 89, 77, 66, 79, 76, 45, 57, - 128, 83, 89, 77, 66, 79, 76, 45, 56, 128, 83, 89, 77, 66, 79, 76, 45, 55, - 128, 83, 89, 77, 66, 79, 76, 45, 54, 128, 83, 89, 77, 66, 79, 76, 45, 53, - 52, 128, 83, 89, 77, 66, 79, 76, 45, 53, 51, 128, 83, 89, 77, 66, 79, 76, - 45, 53, 50, 128, 83, 89, 77, 66, 79, 76, 45, 53, 49, 128, 83, 89, 77, 66, - 79, 76, 45, 53, 48, 128, 83, 89, 77, 66, 79, 76, 45, 53, 128, 83, 89, 77, - 66, 79, 76, 45, 52, 57, 128, 83, 89, 77, 66, 79, 76, 45, 52, 56, 128, 83, - 89, 77, 66, 79, 76, 45, 52, 55, 128, 83, 89, 77, 66, 79, 76, 45, 52, 53, - 128, 83, 89, 77, 66, 79, 76, 45, 52, 51, 128, 83, 89, 77, 66, 79, 76, 45, - 52, 50, 128, 83, 89, 77, 66, 79, 76, 45, 52, 48, 128, 83, 89, 77, 66, 79, - 76, 45, 52, 128, 83, 89, 77, 66, 79, 76, 45, 51, 57, 128, 83, 89, 77, 66, - 79, 76, 45, 51, 56, 128, 83, 89, 77, 66, 79, 76, 45, 51, 55, 128, 83, 89, - 77, 66, 79, 76, 45, 51, 54, 128, 83, 89, 77, 66, 79, 76, 45, 51, 50, 128, - 83, 89, 77, 66, 79, 76, 45, 51, 48, 128, 83, 89, 77, 66, 79, 76, 45, 51, - 128, 83, 89, 77, 66, 79, 76, 45, 50, 57, 128, 83, 89, 77, 66, 79, 76, 45, - 50, 55, 128, 83, 89, 77, 66, 79, 76, 45, 50, 54, 128, 83, 89, 77, 66, 79, - 76, 45, 50, 53, 128, 83, 89, 77, 66, 79, 76, 45, 50, 52, 128, 83, 89, 77, - 66, 79, 76, 45, 50, 51, 128, 83, 89, 77, 66, 79, 76, 45, 50, 50, 128, 83, - 89, 77, 66, 79, 76, 45, 50, 49, 128, 83, 89, 77, 66, 79, 76, 45, 50, 48, - 128, 83, 89, 77, 66, 79, 76, 45, 50, 128, 83, 89, 77, 66, 79, 76, 45, 49, - 57, 128, 83, 89, 77, 66, 79, 76, 45, 49, 56, 128, 83, 89, 77, 66, 79, 76, - 45, 49, 55, 128, 83, 89, 77, 66, 79, 76, 45, 49, 54, 128, 83, 89, 77, 66, - 79, 76, 45, 49, 53, 128, 83, 89, 77, 66, 79, 76, 45, 49, 52, 128, 83, 89, - 77, 66, 79, 76, 45, 49, 51, 128, 83, 89, 77, 66, 79, 76, 45, 49, 50, 128, - 83, 89, 77, 66, 79, 76, 45, 49, 49, 128, 83, 89, 77, 66, 79, 76, 45, 49, - 48, 128, 83, 89, 77, 66, 79, 76, 45, 49, 128, 83, 89, 76, 79, 84, 201, - 83, 89, 73, 128, 83, 89, 128, 83, 87, 90, 128, 83, 87, 85, 78, 199, 83, - 87, 79, 82, 68, 83, 128, 83, 87, 79, 82, 68, 128, 83, 87, 79, 79, 128, - 83, 87, 79, 128, 83, 87, 73, 82, 204, 83, 87, 73, 77, 83, 85, 73, 84, - 128, 83, 87, 73, 77, 77, 73, 78, 71, 128, 83, 87, 73, 77, 77, 69, 82, - 128, 83, 87, 73, 73, 128, 83, 87, 73, 128, 83, 87, 71, 128, 83, 87, 69, - 69, 84, 128, 83, 87, 69, 69, 212, 83, 87, 69, 65, 84, 128, 83, 87, 69, - 65, 212, 83, 87, 65, 83, 200, 83, 87, 65, 80, 80, 73, 78, 71, 128, 83, - 87, 65, 78, 128, 83, 87, 65, 65, 128, 83, 87, 128, 83, 86, 65, 83, 84, - 201, 83, 86, 65, 82, 73, 84, 65, 128, 83, 86, 65, 82, 73, 84, 193, 83, - 85, 88, 128, 83, 85, 85, 128, 83, 85, 84, 85, 72, 128, 83, 85, 84, 82, - 193, 83, 85, 84, 128, 83, 85, 83, 80, 69, 78, 83, 73, 79, 206, 83, 85, - 83, 72, 73, 128, 83, 85, 82, 89, 65, 128, 83, 85, 82, 88, 128, 83, 85, - 82, 82, 79, 85, 78, 68, 128, 83, 85, 82, 82, 79, 85, 78, 196, 83, 85, 82, - 70, 69, 82, 128, 83, 85, 82, 70, 65, 67, 197, 83, 85, 82, 69, 128, 83, - 85, 82, 65, 78, 71, 128, 83, 85, 82, 57, 128, 83, 85, 82, 128, 83, 85, - 210, 83, 85, 80, 82, 65, 76, 73, 78, 69, 65, 210, 83, 85, 80, 69, 82, 86, - 73, 83, 69, 128, 83, 85, 80, 69, 82, 86, 73, 76, 76, 65, 73, 78, 128, 83, - 85, 80, 69, 82, 83, 69, 84, 128, 83, 85, 80, 69, 82, 83, 69, 212, 83, 85, - 80, 69, 82, 83, 67, 82, 73, 80, 212, 83, 85, 80, 69, 82, 73, 77, 80, 79, - 83, 69, 196, 83, 85, 80, 69, 82, 72, 69, 82, 79, 128, 83, 85, 80, 69, 82, - 70, 73, 88, 69, 196, 83, 85, 80, 69, 210, 83, 85, 80, 128, 83, 85, 79, - 88, 128, 83, 85, 79, 80, 128, 83, 85, 79, 128, 83, 85, 78, 83, 69, 212, - 83, 85, 78, 82, 73, 83, 69, 128, 83, 85, 78, 82, 73, 83, 197, 83, 85, 78, - 71, 76, 65, 83, 83, 69, 83, 128, 83, 85, 78, 71, 128, 83, 85, 78, 70, 76, - 79, 87, 69, 82, 128, 83, 85, 78, 68, 65, 78, 69, 83, 197, 83, 85, 78, - 128, 83, 85, 206, 83, 85, 77, 77, 69, 82, 128, 83, 85, 77, 77, 65, 84, - 73, 79, 78, 128, 83, 85, 77, 77, 65, 84, 73, 79, 206, 83, 85, 77, 65, 83, - 72, 128, 83, 85, 77, 128, 83, 85, 76, 70, 85, 82, 128, 83, 85, 75, 85, - 78, 128, 83, 85, 75, 85, 206, 83, 85, 75, 85, 128, 83, 85, 75, 213, 83, - 85, 73, 84, 65, 66, 76, 69, 128, 83, 85, 73, 212, 83, 85, 72, 85, 82, - 128, 83, 85, 69, 128, 83, 85, 68, 50, 128, 83, 85, 68, 128, 83, 85, 67, - 75, 73, 78, 199, 83, 85, 67, 75, 69, 68, 128, 83, 85, 67, 203, 83, 85, - 67, 67, 69, 69, 68, 83, 128, 83, 85, 67, 67, 69, 69, 68, 211, 83, 85, 67, - 67, 69, 69, 68, 128, 83, 85, 67, 67, 69, 69, 196, 83, 85, 66, 85, 78, 73, - 84, 128, 83, 85, 66, 83, 84, 73, 84, 85, 84, 73, 79, 206, 83, 85, 66, 83, - 84, 73, 84, 85, 84, 69, 128, 83, 85, 66, 83, 84, 73, 84, 85, 84, 197, 83, - 85, 66, 83, 69, 84, 128, 83, 85, 66, 83, 69, 212, 83, 85, 66, 83, 67, 82, - 73, 80, 212, 83, 85, 66, 80, 85, 78, 67, 84, 73, 83, 128, 83, 85, 66, 76, - 73, 78, 69, 65, 210, 83, 85, 66, 76, 73, 77, 65, 84, 73, 79, 78, 128, 83, - 85, 66, 76, 73, 77, 65, 84, 69, 45, 51, 128, 83, 85, 66, 76, 73, 77, 65, - 84, 69, 45, 50, 128, 83, 85, 66, 76, 73, 77, 65, 84, 69, 128, 83, 85, 66, - 76, 73, 77, 65, 84, 197, 83, 85, 66, 74, 79, 73, 78, 69, 82, 128, 83, 85, - 66, 74, 79, 73, 78, 69, 196, 83, 85, 66, 74, 69, 67, 84, 128, 83, 85, 66, - 73, 84, 79, 128, 83, 85, 66, 72, 65, 65, 78, 65, 72, 213, 83, 85, 66, 71, - 82, 79, 85, 80, 128, 83, 85, 66, 71, 82, 79, 85, 208, 83, 85, 66, 128, - 83, 85, 65, 77, 128, 83, 85, 65, 69, 84, 128, 83, 85, 65, 69, 78, 128, - 83, 85, 65, 69, 128, 83, 85, 65, 66, 128, 83, 85, 65, 128, 83, 85, 45, - 56, 128, 83, 85, 45, 55, 128, 83, 85, 45, 54, 128, 83, 85, 45, 53, 128, - 83, 85, 45, 52, 128, 83, 85, 45, 51, 128, 83, 85, 45, 50, 128, 83, 85, - 45, 49, 128, 83, 213, 83, 84, 88, 128, 83, 84, 87, 65, 128, 83, 84, 85, - 80, 65, 128, 83, 84, 85, 70, 70, 69, 196, 83, 84, 85, 68, 89, 128, 83, - 84, 85, 68, 73, 207, 83, 84, 85, 67, 75, 45, 79, 85, 212, 83, 84, 83, - 128, 83, 84, 82, 79, 78, 199, 83, 84, 82, 79, 75, 69, 83, 128, 83, 84, - 82, 79, 75, 69, 211, 83, 84, 82, 79, 75, 69, 45, 57, 128, 83, 84, 82, 79, - 75, 69, 45, 56, 128, 83, 84, 82, 79, 75, 69, 45, 55, 128, 83, 84, 82, 79, - 75, 69, 45, 54, 128, 83, 84, 82, 79, 75, 69, 45, 53, 128, 83, 84, 82, 79, - 75, 69, 45, 52, 128, 83, 84, 82, 79, 75, 69, 45, 51, 128, 83, 84, 82, 79, - 75, 69, 45, 50, 128, 83, 84, 82, 79, 75, 69, 45, 49, 49, 128, 83, 84, 82, - 79, 75, 69, 45, 49, 48, 128, 83, 84, 82, 79, 75, 69, 45, 49, 128, 83, 84, - 82, 79, 75, 197, 83, 84, 82, 73, 80, 69, 128, 83, 84, 82, 73, 78, 71, - 128, 83, 84, 82, 73, 78, 199, 83, 84, 82, 73, 75, 69, 84, 72, 82, 79, 85, - 71, 72, 128, 83, 84, 82, 73, 75, 197, 83, 84, 82, 73, 68, 69, 128, 83, - 84, 82, 73, 67, 84, 76, 217, 83, 84, 82, 69, 84, 67, 72, 69, 196, 83, 84, - 82, 69, 84, 67, 72, 128, 83, 84, 82, 69, 83, 211, 83, 84, 82, 69, 78, 71, - 84, 72, 128, 83, 84, 82, 69, 76, 193, 83, 84, 82, 69, 65, 77, 69, 82, - 128, 83, 84, 82, 65, 87, 66, 69, 82, 82, 89, 128, 83, 84, 82, 65, 87, - 128, 83, 84, 82, 65, 84, 85, 77, 45, 50, 128, 83, 84, 82, 65, 84, 85, 77, - 128, 83, 84, 82, 65, 84, 85, 205, 83, 84, 82, 65, 84, 73, 65, 206, 83, - 84, 82, 65, 78, 78, 79, 128, 83, 84, 82, 65, 78, 78, 207, 83, 84, 82, 65, - 73, 78, 69, 82, 128, 83, 84, 82, 65, 73, 71, 72, 84, 78, 69, 83, 83, 128, - 83, 84, 82, 65, 73, 71, 72, 84, 128, 83, 84, 82, 65, 73, 71, 72, 212, 83, - 84, 82, 65, 73, 70, 128, 83, 84, 82, 65, 71, 71, 73, 83, 77, 65, 84, 65, - 128, 83, 84, 79, 86, 69, 128, 83, 84, 79, 82, 69, 128, 83, 84, 79, 80, - 87, 65, 84, 67, 72, 128, 83, 84, 79, 80, 80, 73, 78, 71, 128, 83, 84, 79, - 80, 80, 65, 71, 69, 128, 83, 84, 79, 80, 73, 84, 83, 65, 128, 83, 84, 79, - 80, 73, 84, 83, 193, 83, 84, 79, 80, 128, 83, 84, 79, 208, 83, 84, 79, - 78, 69, 128, 83, 84, 79, 67, 75, 128, 83, 84, 79, 67, 203, 83, 84, 73, - 82, 82, 85, 208, 83, 84, 73, 77, 77, 69, 128, 83, 84, 73, 76, 204, 83, - 84, 73, 76, 197, 83, 84, 73, 71, 77, 65, 128, 83, 84, 73, 67, 75, 73, 78, - 199, 83, 84, 73, 67, 203, 83, 84, 69, 84, 72, 79, 83, 67, 79, 80, 69, - 128, 83, 84, 69, 82, 69, 79, 128, 83, 84, 69, 80, 128, 83, 84, 69, 78, - 79, 71, 82, 65, 80, 72, 73, 195, 83, 84, 69, 77, 128, 83, 84, 69, 65, 77, - 217, 83, 84, 69, 65, 77, 73, 78, 199, 83, 84, 69, 65, 77, 128, 83, 84, - 69, 65, 205, 83, 84, 65, 86, 82, 79, 85, 128, 83, 84, 65, 86, 82, 79, 83, - 128, 83, 84, 65, 86, 82, 79, 211, 83, 84, 65, 85, 82, 79, 83, 128, 83, - 84, 65, 84, 89, 65, 128, 83, 84, 65, 84, 89, 193, 83, 84, 65, 84, 85, - 197, 83, 84, 65, 84, 73, 79, 78, 128, 83, 84, 65, 84, 69, 82, 83, 128, - 83, 84, 65, 84, 69, 128, 83, 84, 65, 82, 84, 73, 78, 199, 83, 84, 65, 82, - 84, 128, 83, 84, 65, 82, 212, 83, 84, 65, 82, 83, 128, 83, 84, 65, 82, - 82, 69, 196, 83, 84, 65, 82, 75, 128, 83, 84, 65, 82, 128, 83, 84, 65, - 210, 83, 84, 65, 78, 68, 83, 84, 73, 76, 76, 128, 83, 84, 65, 78, 68, 73, - 78, 199, 83, 84, 65, 78, 68, 65, 82, 196, 83, 84, 65, 78, 68, 128, 83, - 84, 65, 78, 128, 83, 84, 65, 77, 80, 69, 196, 83, 84, 65, 76, 76, 73, 79, - 78, 128, 83, 84, 65, 70, 70, 128, 83, 84, 65, 70, 198, 83, 84, 65, 68, - 73, 85, 77, 128, 83, 84, 65, 67, 75, 69, 196, 83, 84, 65, 67, 67, 65, 84, - 79, 128, 83, 84, 65, 67, 67, 65, 84, 73, 83, 83, 73, 77, 79, 128, 83, 84, - 50, 128, 83, 83, 89, 88, 128, 83, 83, 89, 84, 128, 83, 83, 89, 82, 88, - 128, 83, 83, 89, 82, 128, 83, 83, 89, 80, 128, 83, 83, 89, 128, 83, 83, - 85, 88, 128, 83, 83, 85, 85, 128, 83, 83, 85, 84, 128, 83, 83, 85, 80, - 128, 83, 83, 79, 88, 128, 83, 83, 79, 84, 128, 83, 83, 79, 80, 128, 83, - 83, 79, 79, 128, 83, 83, 79, 128, 83, 83, 73, 88, 128, 83, 83, 73, 84, - 128, 83, 83, 73, 80, 128, 83, 83, 73, 73, 128, 83, 83, 73, 69, 88, 128, - 83, 83, 73, 69, 80, 128, 83, 83, 73, 69, 128, 83, 83, 72, 73, 78, 128, - 83, 83, 72, 69, 128, 83, 83, 69, 88, 128, 83, 83, 69, 80, 128, 83, 83, - 69, 69, 128, 83, 83, 65, 88, 128, 83, 83, 65, 85, 128, 83, 83, 65, 84, - 128, 83, 83, 65, 80, 128, 83, 83, 65, 78, 71, 89, 69, 83, 73, 69, 85, 78, - 71, 128, 83, 83, 65, 78, 71, 89, 69, 79, 82, 73, 78, 72, 73, 69, 85, 72, - 128, 83, 83, 65, 78, 71, 84, 73, 75, 69, 85, 84, 45, 80, 73, 69, 85, 80, - 128, 83, 83, 65, 78, 71, 84, 73, 75, 69, 85, 84, 128, 83, 83, 65, 78, 71, - 84, 72, 73, 69, 85, 84, 72, 128, 83, 83, 65, 78, 71, 83, 73, 79, 83, 45, - 84, 73, 75, 69, 85, 84, 128, 83, 83, 65, 78, 71, 83, 73, 79, 83, 45, 80, - 73, 69, 85, 80, 128, 83, 83, 65, 78, 71, 83, 73, 79, 83, 45, 75, 73, 89, - 69, 79, 75, 128, 83, 83, 65, 78, 71, 83, 73, 79, 83, 128, 83, 83, 65, 78, - 71, 82, 73, 69, 85, 76, 45, 75, 72, 73, 69, 85, 75, 72, 128, 83, 83, 65, - 78, 71, 82, 73, 69, 85, 76, 128, 83, 83, 65, 78, 71, 80, 73, 69, 85, 80, - 128, 83, 83, 65, 78, 71, 78, 73, 69, 85, 78, 128, 83, 83, 65, 78, 71, 77, - 73, 69, 85, 77, 128, 83, 83, 65, 78, 71, 73, 69, 85, 78, 71, 128, 83, 83, - 65, 78, 71, 72, 73, 69, 85, 72, 128, 83, 83, 65, 78, 71, 67, 73, 69, 85, - 67, 45, 72, 73, 69, 85, 72, 128, 83, 83, 65, 78, 71, 67, 73, 69, 85, 67, - 128, 83, 83, 65, 78, 71, 65, 82, 65, 69, 65, 128, 83, 83, 65, 73, 128, - 83, 83, 65, 65, 128, 83, 83, 51, 128, 83, 83, 50, 128, 83, 82, 69, 68, - 78, 197, 83, 82, 128, 83, 81, 85, 73, 83, 200, 83, 81, 85, 73, 82, 82, - 69, 204, 83, 81, 85, 73, 71, 71, 76, 197, 83, 81, 85, 73, 68, 128, 83, - 81, 85, 69, 69, 90, 69, 68, 128, 83, 81, 85, 69, 69, 90, 197, 83, 81, 85, - 65, 212, 83, 81, 85, 65, 82, 69, 83, 128, 83, 81, 85, 65, 82, 69, 68, - 128, 83, 81, 85, 65, 82, 69, 128, 83, 80, 89, 128, 83, 80, 87, 65, 128, - 83, 80, 85, 78, 71, 211, 83, 80, 82, 79, 85, 84, 128, 83, 80, 82, 73, 78, - 71, 83, 128, 83, 80, 82, 73, 78, 71, 128, 83, 80, 82, 69, 67, 72, 71, 69, - 83, 65, 78, 199, 83, 80, 82, 69, 65, 68, 128, 83, 80, 82, 69, 65, 196, - 83, 80, 79, 85, 84, 73, 78, 199, 83, 80, 79, 84, 128, 83, 80, 79, 82, 84, - 211, 83, 80, 79, 79, 78, 128, 83, 80, 79, 79, 204, 83, 80, 79, 78, 71, - 69, 128, 83, 80, 79, 128, 83, 80, 76, 73, 84, 84, 73, 78, 199, 83, 80, - 76, 73, 84, 128, 83, 80, 76, 73, 212, 83, 80, 76, 65, 89, 69, 68, 128, - 83, 80, 76, 65, 83, 72, 73, 78, 199, 83, 80, 73, 82, 73, 84, 85, 211, 83, - 80, 73, 82, 73, 84, 128, 83, 80, 73, 82, 73, 212, 83, 80, 73, 82, 65, 78, - 84, 128, 83, 80, 73, 82, 65, 76, 128, 83, 80, 73, 82, 65, 204, 83, 80, - 73, 78, 69, 128, 83, 80, 73, 68, 69, 82, 217, 83, 80, 73, 68, 69, 82, - 128, 83, 80, 73, 68, 69, 210, 83, 80, 73, 67, 69, 128, 83, 80, 73, 128, - 83, 80, 72, 69, 82, 73, 67, 65, 204, 83, 80, 69, 83, 77, 73, 76, 207, 83, - 80, 69, 78, 212, 83, 80, 69, 69, 68, 66, 79, 65, 84, 128, 83, 80, 69, 69, - 67, 72, 128, 83, 80, 69, 69, 67, 200, 83, 80, 69, 67, 73, 65, 76, 128, - 83, 80, 69, 65, 82, 128, 83, 80, 69, 65, 75, 73, 78, 199, 83, 80, 69, 65, - 75, 69, 82, 128, 83, 80, 69, 65, 75, 69, 210, 83, 80, 69, 65, 75, 45, 78, - 79, 45, 69, 86, 73, 204, 83, 80, 69, 128, 83, 80, 65, 84, 72, 73, 128, - 83, 80, 65, 82, 75, 76, 73, 78, 199, 83, 80, 65, 82, 75, 76, 69, 83, 128, - 83, 80, 65, 82, 75, 76, 69, 82, 128, 83, 80, 65, 82, 75, 76, 69, 128, 83, - 80, 65, 71, 72, 69, 84, 84, 73, 128, 83, 80, 65, 68, 69, 83, 128, 83, 80, - 65, 68, 197, 83, 80, 65, 67, 73, 78, 199, 83, 80, 65, 67, 197, 83, 80, - 65, 128, 83, 79, 89, 79, 77, 66, 207, 83, 79, 89, 128, 83, 79, 87, 73, - 76, 207, 83, 79, 87, 128, 83, 79, 85, 84, 72, 69, 82, 206, 83, 79, 85, - 84, 72, 45, 83, 76, 65, 86, 69, 217, 83, 79, 85, 84, 200, 83, 79, 85, 82, - 67, 69, 128, 83, 79, 85, 78, 68, 128, 83, 79, 85, 78, 196, 83, 79, 85, - 78, 65, 80, 128, 83, 79, 85, 128, 83, 79, 83, 128, 83, 79, 82, 79, 67, - 72, 89, 193, 83, 79, 82, 73, 128, 83, 79, 82, 193, 83, 79, 81, 128, 83, - 79, 79, 206, 83, 79, 78, 74, 65, 77, 128, 83, 79, 78, 71, 128, 83, 79, - 78, 128, 83, 79, 77, 80, 69, 78, 199, 83, 79, 77, 128, 83, 79, 205, 83, - 79, 76, 73, 68, 85, 83, 128, 83, 79, 76, 73, 68, 85, 211, 83, 79, 76, 73, - 196, 83, 79, 76, 68, 73, 69, 82, 128, 83, 79, 72, 128, 83, 79, 71, 68, - 73, 65, 206, 83, 79, 70, 84, 87, 65, 82, 69, 45, 70, 85, 78, 67, 84, 73, - 79, 206, 83, 79, 70, 84, 78, 69, 83, 83, 128, 83, 79, 70, 84, 66, 65, 76, - 76, 128, 83, 79, 70, 212, 83, 79, 198, 83, 79, 67, 75, 83, 128, 83, 79, - 67, 73, 69, 84, 89, 128, 83, 79, 67, 67, 69, 210, 83, 79, 65, 80, 128, - 83, 79, 65, 128, 83, 79, 45, 55, 128, 83, 79, 45, 54, 128, 83, 79, 45, - 53, 128, 83, 79, 45, 52, 128, 83, 79, 45, 51, 128, 83, 79, 45, 50, 128, - 83, 79, 45, 49, 128, 83, 207, 83, 78, 79, 87, 77, 65, 78, 128, 83, 78, - 79, 87, 77, 65, 206, 83, 78, 79, 87, 70, 76, 65, 75, 69, 128, 83, 78, 79, - 87, 66, 79, 65, 82, 68, 69, 82, 128, 83, 78, 79, 87, 128, 83, 78, 79, - 215, 83, 78, 79, 85, 84, 128, 83, 78, 79, 85, 212, 83, 78, 69, 69, 90, - 73, 78, 199, 83, 78, 65, 208, 83, 78, 65, 75, 69, 128, 83, 78, 65, 75, - 197, 83, 78, 65, 73, 76, 128, 83, 78, 193, 83, 77, 79, 75, 73, 78, 199, - 83, 77, 73, 82, 75, 73, 78, 199, 83, 77, 73, 76, 73, 78, 199, 83, 77, 73, - 76, 69, 128, 83, 77, 73, 76, 197, 83, 77, 69, 65, 82, 128, 83, 77, 65, - 83, 200, 83, 77, 65, 76, 76, 69, 210, 83, 77, 65, 76, 76, 128, 83, 76, - 85, 82, 128, 83, 76, 79, 90, 72, 73, 84, 73, 69, 128, 83, 76, 79, 90, 72, - 73, 84, 73, 197, 83, 76, 79, 87, 76, 89, 128, 83, 76, 79, 87, 128, 83, - 76, 79, 215, 83, 76, 79, 86, 79, 128, 83, 76, 79, 84, 72, 128, 83, 76, - 79, 212, 83, 76, 79, 80, 73, 78, 199, 83, 76, 79, 80, 69, 128, 83, 76, - 79, 65, 206, 83, 76, 73, 78, 71, 128, 83, 76, 73, 71, 72, 84, 76, 217, - 83, 76, 73, 68, 73, 78, 71, 128, 83, 76, 73, 68, 69, 82, 128, 83, 76, 73, - 68, 69, 128, 83, 76, 73, 67, 69, 128, 83, 76, 73, 67, 197, 83, 76, 69, - 85, 84, 200, 83, 76, 69, 69, 80, 217, 83, 76, 69, 69, 80, 73, 78, 199, - 83, 76, 69, 69, 208, 83, 76, 69, 68, 128, 83, 76, 65, 86, 79, 78, 73, - 195, 83, 76, 65, 86, 69, 128, 83, 76, 65, 83, 72, 128, 83, 76, 65, 83, - 200, 83, 76, 65, 78, 84, 69, 196, 83, 75, 87, 65, 128, 83, 75, 87, 128, - 83, 75, 85, 78, 75, 128, 83, 75, 85, 76, 76, 128, 83, 75, 85, 76, 204, - 83, 75, 79, 66, 65, 128, 83, 75, 76, 73, 82, 79, 206, 83, 75, 73, 78, - 128, 83, 75, 73, 69, 82, 128, 83, 75, 201, 83, 75, 69, 87, 69, 196, 83, - 75, 65, 84, 69, 66, 79, 65, 82, 68, 128, 83, 75, 65, 84, 69, 128, 83, 75, - 65, 77, 69, 89, 84, 83, 193, 83, 75, 128, 83, 74, 69, 128, 83, 73, 90, - 197, 83, 73, 88, 84, 89, 45, 70, 79, 85, 82, 84, 72, 83, 128, 83, 73, 88, - 84, 89, 45, 70, 79, 85, 82, 84, 72, 128, 83, 73, 88, 84, 89, 45, 70, 79, - 85, 82, 84, 200, 83, 73, 88, 84, 89, 128, 83, 73, 88, 84, 217, 83, 73, - 88, 84, 72, 83, 128, 83, 73, 88, 84, 72, 211, 83, 73, 88, 84, 72, 128, - 83, 73, 88, 84, 69, 69, 78, 84, 72, 83, 128, 83, 73, 88, 84, 69, 69, 78, - 84, 72, 45, 50, 128, 83, 73, 88, 84, 69, 69, 78, 84, 72, 45, 49, 128, 83, - 73, 88, 84, 69, 69, 78, 84, 72, 128, 83, 73, 88, 84, 69, 69, 78, 84, 200, - 83, 73, 88, 84, 69, 69, 78, 128, 83, 73, 88, 84, 69, 69, 206, 83, 73, 88, - 45, 84, 72, 73, 82, 84, 89, 128, 83, 73, 88, 45, 83, 84, 82, 73, 78, 199, - 83, 73, 88, 45, 80, 69, 82, 45, 69, 205, 83, 73, 88, 45, 76, 73, 78, 197, - 83, 73, 216, 83, 73, 84, 69, 128, 83, 73, 83, 65, 128, 83, 73, 82, 82, - 65, 72, 128, 83, 73, 82, 73, 78, 71, 85, 128, 83, 73, 79, 83, 45, 84, 72, - 73, 69, 85, 84, 72, 128, 83, 73, 79, 83, 45, 83, 83, 65, 78, 71, 83, 73, - 79, 83, 128, 83, 73, 79, 83, 45, 82, 73, 69, 85, 76, 128, 83, 73, 79, 83, - 45, 80, 73, 69, 85, 80, 45, 75, 73, 89, 69, 79, 75, 128, 83, 73, 79, 83, - 45, 80, 72, 73, 69, 85, 80, 72, 128, 83, 73, 79, 83, 45, 80, 65, 78, 83, - 73, 79, 83, 128, 83, 73, 79, 83, 45, 78, 73, 69, 85, 78, 128, 83, 73, 79, - 83, 45, 77, 73, 69, 85, 77, 128, 83, 73, 79, 83, 45, 75, 72, 73, 69, 85, - 75, 72, 128, 83, 73, 79, 83, 45, 75, 65, 80, 89, 69, 79, 85, 78, 80, 73, - 69, 85, 80, 128, 83, 73, 79, 83, 45, 73, 69, 85, 78, 71, 128, 83, 73, 79, - 83, 45, 72, 73, 69, 85, 72, 128, 83, 73, 79, 83, 45, 67, 73, 69, 85, 67, - 128, 83, 73, 79, 83, 45, 67, 72, 73, 69, 85, 67, 72, 128, 83, 73, 79, - 211, 83, 73, 78, 85, 83, 79, 73, 196, 83, 73, 78, 79, 76, 79, 71, 73, 67, - 65, 204, 83, 73, 78, 78, 89, 73, 73, 89, 72, 69, 128, 83, 73, 78, 75, 73, - 78, 71, 128, 83, 73, 78, 71, 76, 69, 45, 83, 72, 73, 70, 84, 45, 51, 128, - 83, 73, 78, 71, 76, 69, 45, 83, 72, 73, 70, 84, 45, 50, 128, 83, 73, 78, - 71, 76, 69, 45, 76, 73, 78, 197, 83, 73, 78, 71, 76, 69, 128, 83, 73, 78, - 71, 76, 197, 83, 73, 78, 71, 65, 65, 84, 128, 83, 73, 78, 197, 83, 73, - 78, 68, 72, 201, 83, 73, 78, 128, 83, 73, 206, 83, 73, 77, 85, 76, 84, - 65, 78, 69, 79, 85, 83, 128, 83, 73, 77, 85, 76, 84, 65, 78, 69, 79, 85, - 211, 83, 73, 77, 80, 76, 73, 70, 73, 69, 196, 83, 73, 77, 73, 76, 65, 82, - 128, 83, 73, 77, 73, 76, 65, 210, 83, 73, 77, 65, 78, 83, 73, 211, 83, - 73, 77, 65, 76, 85, 78, 71, 85, 206, 83, 73, 77, 65, 128, 83, 73, 76, 86, - 69, 82, 128, 83, 73, 76, 75, 128, 83, 73, 76, 73, 81, 85, 193, 83, 73, - 76, 72, 79, 85, 69, 84, 84, 69, 128, 83, 73, 76, 72, 79, 85, 69, 84, 84, - 197, 83, 73, 76, 65, 51, 128, 83, 73, 75, 73, 128, 83, 73, 75, 50, 128, - 83, 73, 75, 178, 83, 73, 71, 78, 83, 128, 83, 73, 71, 77, 79, 73, 196, - 83, 73, 71, 77, 65, 128, 83, 73, 71, 77, 193, 83, 73, 71, 69, 204, 83, - 73, 71, 52, 128, 83, 73, 71, 180, 83, 73, 71, 128, 83, 73, 69, 69, 128, - 83, 73, 68, 69, 87, 65, 89, 211, 83, 73, 68, 69, 128, 83, 73, 68, 197, - 83, 73, 68, 68, 72, 73, 128, 83, 73, 68, 68, 72, 65, 77, 128, 83, 73, 68, - 68, 72, 65, 205, 83, 73, 67, 75, 78, 69, 83, 83, 128, 83, 73, 67, 75, 76, - 69, 128, 83, 73, 66, 197, 83, 73, 65, 128, 83, 73, 45, 54, 128, 83, 73, - 45, 53, 128, 83, 73, 45, 52, 128, 83, 73, 45, 51, 128, 83, 73, 45, 50, - 128, 83, 73, 45, 49, 128, 83, 201, 83, 72, 89, 88, 128, 83, 72, 89, 84, - 128, 83, 72, 89, 82, 88, 128, 83, 72, 89, 82, 128, 83, 72, 89, 80, 128, - 83, 72, 89, 69, 128, 83, 72, 89, 65, 128, 83, 72, 89, 128, 83, 72, 87, - 79, 89, 128, 83, 72, 87, 79, 79, 128, 83, 72, 87, 79, 128, 83, 72, 87, - 73, 73, 128, 83, 72, 87, 73, 128, 83, 72, 87, 69, 128, 83, 72, 87, 197, - 83, 72, 87, 65, 65, 128, 83, 72, 87, 65, 128, 83, 72, 86, 128, 83, 72, - 85, 88, 128, 83, 72, 85, 85, 128, 83, 72, 85, 84, 84, 76, 69, 67, 79, 67, - 75, 128, 83, 72, 85, 84, 128, 83, 72, 85, 82, 88, 128, 83, 72, 85, 82, - 128, 83, 72, 85, 80, 128, 83, 72, 85, 79, 88, 128, 83, 72, 85, 79, 80, - 128, 83, 72, 85, 79, 128, 83, 72, 85, 77, 128, 83, 72, 85, 76, 128, 83, - 72, 85, 70, 70, 76, 197, 83, 72, 85, 69, 81, 128, 83, 72, 85, 69, 78, 83, - 72, 85, 69, 84, 128, 83, 72, 85, 66, 85, 82, 128, 83, 72, 85, 65, 78, 71, - 88, 73, 128, 83, 72, 85, 50, 128, 83, 72, 85, 178, 83, 72, 85, 128, 83, - 72, 84, 65, 80, 73, 67, 128, 83, 72, 84, 65, 128, 83, 72, 82, 85, 71, - 128, 83, 72, 82, 79, 79, 128, 83, 72, 82, 79, 128, 83, 72, 82, 73, 78, - 69, 128, 83, 72, 82, 73, 77, 80, 128, 83, 72, 82, 73, 73, 128, 83, 72, - 82, 73, 128, 83, 72, 82, 65, 65, 128, 83, 72, 82, 65, 128, 83, 72, 79, - 89, 128, 83, 72, 79, 88, 128, 83, 72, 79, 87, 69, 82, 128, 83, 72, 79, - 85, 76, 68, 69, 82, 69, 196, 83, 72, 79, 85, 76, 68, 69, 210, 83, 72, 79, - 85, 128, 83, 72, 79, 84, 128, 83, 72, 79, 82, 84, 83, 128, 83, 72, 79, - 82, 84, 211, 83, 72, 79, 82, 84, 72, 65, 78, 196, 83, 72, 79, 82, 84, 69, - 78, 69, 82, 128, 83, 72, 79, 82, 84, 67, 65, 75, 69, 128, 83, 72, 79, 82, - 84, 45, 84, 87, 73, 71, 45, 89, 82, 128, 83, 72, 79, 82, 84, 45, 84, 87, - 73, 71, 45, 84, 89, 210, 83, 72, 79, 82, 84, 45, 84, 87, 73, 71, 45, 83, - 79, 204, 83, 72, 79, 82, 84, 45, 84, 87, 73, 71, 45, 79, 83, 211, 83, 72, - 79, 82, 84, 45, 84, 87, 73, 71, 45, 78, 65, 85, 196, 83, 72, 79, 82, 84, - 45, 84, 87, 73, 71, 45, 77, 65, 68, 210, 83, 72, 79, 82, 84, 45, 84, 87, - 73, 71, 45, 72, 65, 71, 65, 76, 204, 83, 72, 79, 82, 84, 45, 84, 87, 73, - 71, 45, 66, 74, 65, 82, 75, 65, 206, 83, 72, 79, 82, 84, 45, 84, 87, 73, - 71, 45, 65, 210, 83, 72, 79, 82, 84, 128, 83, 72, 79, 82, 212, 83, 72, - 79, 81, 128, 83, 72, 79, 209, 83, 72, 79, 80, 80, 73, 78, 199, 83, 72, - 79, 80, 128, 83, 72, 79, 79, 84, 73, 78, 199, 83, 72, 79, 79, 84, 128, - 83, 72, 79, 79, 73, 128, 83, 72, 79, 79, 128, 83, 72, 79, 71, 201, 83, - 72, 79, 199, 83, 72, 79, 69, 83, 128, 83, 72, 79, 69, 128, 83, 72, 79, - 197, 83, 72, 79, 67, 75, 69, 196, 83, 72, 79, 65, 128, 83, 72, 79, 128, - 83, 72, 73, 89, 89, 65, 65, 76, 65, 65, 128, 83, 72, 73, 84, 65, 128, 83, - 72, 73, 84, 193, 83, 72, 73, 82, 212, 83, 72, 73, 82, 65, 69, 128, 83, - 72, 73, 82, 128, 83, 72, 73, 210, 83, 72, 73, 81, 128, 83, 72, 73, 78, - 84, 207, 83, 72, 73, 78, 73, 71, 128, 83, 72, 73, 78, 68, 193, 83, 72, - 73, 206, 83, 72, 73, 77, 65, 128, 83, 72, 73, 77, 193, 83, 72, 73, 77, - 128, 83, 72, 73, 205, 83, 72, 73, 73, 78, 128, 83, 72, 73, 73, 128, 83, - 72, 73, 70, 212, 83, 72, 73, 69, 76, 68, 128, 83, 72, 73, 68, 128, 83, - 72, 73, 196, 83, 72, 72, 65, 128, 83, 72, 72, 193, 83, 72, 69, 88, 128, - 83, 72, 69, 86, 65, 128, 83, 72, 69, 85, 88, 128, 83, 72, 69, 85, 79, 81, - 128, 83, 72, 69, 85, 65, 69, 81, 84, 85, 128, 83, 72, 69, 85, 65, 69, 81, - 128, 83, 72, 69, 85, 65, 69, 128, 83, 72, 69, 84, 128, 83, 72, 69, 212, - 83, 72, 69, 83, 72, 76, 65, 77, 128, 83, 72, 69, 83, 72, 73, 71, 128, 83, - 72, 69, 83, 72, 73, 199, 83, 72, 69, 83, 72, 50, 128, 83, 72, 69, 83, 72, - 128, 83, 72, 69, 83, 200, 83, 72, 69, 81, 69, 204, 83, 72, 69, 80, 128, - 83, 72, 69, 78, 128, 83, 72, 69, 76, 76, 128, 83, 72, 69, 76, 204, 83, - 72, 69, 76, 70, 128, 83, 72, 69, 73, 128, 83, 72, 69, 71, 57, 128, 83, - 72, 69, 69, 80, 128, 83, 72, 69, 69, 78, 85, 128, 83, 72, 69, 69, 78, - 128, 83, 72, 69, 69, 206, 83, 72, 69, 69, 128, 83, 72, 69, 45, 71, 79, - 65, 84, 128, 83, 72, 197, 83, 72, 67, 72, 79, 79, 73, 128, 83, 72, 67, - 72, 65, 128, 83, 72, 65, 89, 128, 83, 72, 65, 88, 128, 83, 72, 65, 86, - 73, 89, 65, 78, 73, 128, 83, 72, 65, 86, 73, 65, 206, 83, 72, 65, 86, 69, - 196, 83, 72, 65, 85, 128, 83, 72, 65, 84, 128, 83, 72, 65, 82, 85, 128, - 83, 72, 65, 82, 213, 83, 72, 65, 82, 80, 128, 83, 72, 65, 82, 208, 83, - 72, 65, 82, 75, 128, 83, 72, 65, 82, 65, 68, 193, 83, 72, 65, 82, 65, - 128, 83, 72, 65, 82, 50, 128, 83, 72, 65, 82, 178, 83, 72, 65, 80, 73, - 78, 71, 128, 83, 72, 65, 80, 69, 83, 128, 83, 72, 65, 80, 197, 83, 72, - 65, 80, 128, 83, 72, 65, 78, 71, 128, 83, 72, 65, 78, 128, 83, 72, 65, - 206, 83, 72, 65, 77, 82, 79, 67, 75, 128, 83, 72, 65, 76, 83, 72, 69, 76, - 69, 84, 128, 83, 72, 65, 76, 76, 79, 215, 83, 72, 65, 75, 84, 73, 128, - 83, 72, 65, 75, 73, 78, 71, 128, 83, 72, 65, 75, 73, 78, 199, 83, 72, 65, - 75, 69, 82, 128, 83, 72, 65, 75, 128, 83, 72, 65, 73, 128, 83, 72, 65, - 70, 84, 128, 83, 72, 65, 70, 212, 83, 72, 65, 68, 79, 87, 69, 196, 83, - 72, 65, 68, 69, 196, 83, 72, 65, 68, 69, 128, 83, 72, 65, 68, 197, 83, - 72, 65, 68, 68, 65, 128, 83, 72, 65, 68, 68, 193, 83, 72, 65, 68, 128, - 83, 72, 65, 196, 83, 72, 65, 66, 54, 128, 83, 72, 65, 65, 128, 83, 72, - 65, 54, 128, 83, 72, 65, 182, 83, 72, 65, 51, 128, 83, 72, 65, 179, 83, - 71, 82, 193, 83, 71, 79, 210, 83, 71, 67, 128, 83, 71, 65, 215, 83, 71, - 65, 194, 83, 71, 128, 83, 69, 89, 75, 128, 83, 69, 88, 84, 85, 76, 193, - 83, 69, 88, 84, 73, 76, 69, 128, 83, 69, 88, 84, 65, 78, 84, 45, 54, 128, - 83, 69, 88, 84, 65, 78, 84, 45, 53, 54, 128, 83, 69, 88, 84, 65, 78, 84, - 45, 53, 128, 83, 69, 88, 84, 65, 78, 84, 45, 52, 54, 128, 83, 69, 88, 84, - 65, 78, 84, 45, 52, 53, 54, 128, 83, 69, 88, 84, 65, 78, 84, 45, 52, 53, - 128, 83, 69, 88, 84, 65, 78, 84, 45, 52, 128, 83, 69, 88, 84, 65, 78, 84, - 45, 51, 54, 128, 83, 69, 88, 84, 65, 78, 84, 45, 51, 53, 54, 128, 83, 69, - 88, 84, 65, 78, 84, 45, 51, 53, 128, 83, 69, 88, 84, 65, 78, 84, 45, 51, - 52, 54, 128, 83, 69, 88, 84, 65, 78, 84, 45, 51, 52, 53, 54, 128, 83, 69, - 88, 84, 65, 78, 84, 45, 51, 52, 53, 128, 83, 69, 88, 84, 65, 78, 84, 45, - 51, 52, 128, 83, 69, 88, 84, 65, 78, 84, 45, 51, 128, 83, 69, 88, 84, 65, - 78, 84, 45, 50, 54, 128, 83, 69, 88, 84, 65, 78, 84, 45, 50, 53, 54, 128, - 83, 69, 88, 84, 65, 78, 84, 45, 50, 53, 128, 83, 69, 88, 84, 65, 78, 84, - 45, 50, 52, 53, 54, 128, 83, 69, 88, 84, 65, 78, 84, 45, 50, 52, 53, 128, - 83, 69, 88, 84, 65, 78, 84, 45, 50, 52, 128, 83, 69, 88, 84, 65, 78, 84, - 45, 50, 51, 54, 128, 83, 69, 88, 84, 65, 78, 84, 45, 50, 51, 53, 54, 128, - 83, 69, 88, 84, 65, 78, 84, 45, 50, 51, 53, 128, 83, 69, 88, 84, 65, 78, - 84, 45, 50, 51, 52, 54, 128, 83, 69, 88, 84, 65, 78, 84, 45, 50, 51, 52, - 53, 54, 128, 83, 69, 88, 84, 65, 78, 84, 45, 50, 51, 52, 53, 128, 83, 69, - 88, 84, 65, 78, 84, 45, 50, 51, 52, 128, 83, 69, 88, 84, 65, 78, 84, 45, - 50, 51, 128, 83, 69, 88, 84, 65, 78, 84, 45, 50, 128, 83, 69, 88, 84, 65, - 78, 84, 45, 49, 54, 128, 83, 69, 88, 84, 65, 78, 84, 45, 49, 53, 54, 128, - 83, 69, 88, 84, 65, 78, 84, 45, 49, 53, 128, 83, 69, 88, 84, 65, 78, 84, - 45, 49, 52, 54, 128, 83, 69, 88, 84, 65, 78, 84, 45, 49, 52, 53, 54, 128, - 83, 69, 88, 84, 65, 78, 84, 45, 49, 52, 53, 128, 83, 69, 88, 84, 65, 78, - 84, 45, 49, 52, 128, 83, 69, 88, 84, 65, 78, 84, 45, 49, 51, 54, 128, 83, - 69, 88, 84, 65, 78, 84, 45, 49, 51, 53, 54, 128, 83, 69, 88, 84, 65, 78, - 84, 45, 49, 51, 52, 54, 128, 83, 69, 88, 84, 65, 78, 84, 45, 49, 51, 52, - 53, 54, 128, 83, 69, 88, 84, 65, 78, 84, 45, 49, 51, 52, 53, 128, 83, 69, - 88, 84, 65, 78, 84, 45, 49, 51, 52, 128, 83, 69, 88, 84, 65, 78, 84, 45, - 49, 51, 128, 83, 69, 88, 84, 65, 78, 84, 45, 49, 50, 54, 128, 83, 69, 88, - 84, 65, 78, 84, 45, 49, 50, 53, 54, 128, 83, 69, 88, 84, 65, 78, 84, 45, - 49, 50, 53, 128, 83, 69, 88, 84, 65, 78, 84, 45, 49, 50, 52, 54, 128, 83, - 69, 88, 84, 65, 78, 84, 45, 49, 50, 52, 53, 54, 128, 83, 69, 88, 84, 65, - 78, 84, 45, 49, 50, 52, 53, 128, 83, 69, 88, 84, 65, 78, 84, 45, 49, 50, - 52, 128, 83, 69, 88, 84, 65, 78, 84, 45, 49, 50, 51, 54, 128, 83, 69, 88, - 84, 65, 78, 84, 45, 49, 50, 51, 53, 54, 128, 83, 69, 88, 84, 65, 78, 84, - 45, 49, 50, 51, 53, 128, 83, 69, 88, 84, 65, 78, 84, 45, 49, 50, 51, 52, - 54, 128, 83, 69, 88, 84, 65, 78, 84, 45, 49, 50, 51, 52, 53, 128, 83, 69, - 88, 84, 65, 78, 84, 45, 49, 50, 51, 52, 128, 83, 69, 88, 84, 65, 78, 84, - 45, 49, 50, 51, 128, 83, 69, 88, 84, 65, 78, 84, 45, 49, 50, 128, 83, 69, - 88, 84, 65, 78, 84, 45, 49, 128, 83, 69, 88, 84, 65, 78, 211, 83, 69, 87, - 73, 78, 199, 83, 69, 86, 69, 82, 65, 78, 67, 69, 128, 83, 69, 86, 69, 78, - 84, 89, 128, 83, 69, 86, 69, 78, 84, 217, 83, 69, 86, 69, 78, 84, 72, - 128, 83, 69, 86, 69, 78, 84, 69, 69, 78, 128, 83, 69, 86, 69, 78, 84, 69, - 69, 206, 83, 69, 86, 69, 78, 45, 84, 72, 73, 82, 84, 89, 128, 83, 69, 86, - 69, 206, 83, 69, 85, 88, 128, 83, 69, 85, 78, 89, 65, 77, 128, 83, 69, - 85, 65, 69, 81, 128, 83, 69, 84, 70, 79, 78, 128, 83, 69, 83, 84, 69, 82, - 84, 73, 85, 211, 83, 69, 83, 81, 85, 73, 81, 85, 65, 68, 82, 65, 84, 69, - 128, 83, 69, 83, 65, 77, 197, 83, 69, 82, 86, 73, 67, 197, 83, 69, 82, - 73, 79, 85, 211, 83, 69, 82, 73, 70, 83, 128, 83, 69, 82, 73, 70, 211, - 83, 69, 82, 73, 70, 128, 83, 69, 81, 85, 69, 78, 84, 73, 65, 76, 128, 83, - 69, 81, 85, 69, 78, 67, 197, 83, 69, 80, 84, 85, 80, 76, 197, 83, 69, 80, - 84, 69, 77, 66, 69, 82, 128, 83, 69, 80, 65, 82, 65, 84, 79, 82, 128, 83, - 69, 80, 65, 82, 65, 84, 79, 210, 83, 69, 80, 65, 82, 65, 84, 69, 196, 83, - 69, 78, 84, 79, 128, 83, 69, 78, 84, 73, 128, 83, 69, 78, 84, 65, 71, 79, - 78, 128, 83, 69, 77, 85, 78, 67, 73, 193, 83, 69, 77, 75, 65, 84, 72, - 128, 83, 69, 77, 75, 128, 83, 69, 77, 73, 86, 79, 87, 69, 204, 83, 69, - 77, 73, 83, 79, 70, 212, 83, 69, 77, 73, 83, 69, 88, 84, 73, 76, 69, 128, - 83, 69, 77, 73, 77, 73, 78, 73, 77, 193, 83, 69, 77, 73, 68, 73, 82, 69, - 67, 212, 83, 69, 77, 73, 67, 79, 76, 79, 78, 128, 83, 69, 77, 73, 67, 79, - 76, 79, 206, 83, 69, 77, 73, 67, 73, 82, 67, 85, 76, 65, 210, 83, 69, 77, - 73, 67, 73, 82, 67, 76, 197, 83, 69, 77, 73, 66, 82, 69, 86, 73, 211, 83, - 69, 77, 73, 45, 86, 79, 73, 67, 69, 196, 83, 69, 76, 70, 73, 69, 128, 83, - 69, 76, 70, 128, 83, 69, 76, 69, 78, 65, 128, 83, 69, 76, 69, 67, 84, 79, - 82, 45, 57, 57, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 57, 56, 128, 83, - 69, 76, 69, 67, 84, 79, 82, 45, 57, 55, 128, 83, 69, 76, 69, 67, 84, 79, - 82, 45, 57, 54, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 57, 53, 128, 83, - 69, 76, 69, 67, 84, 79, 82, 45, 57, 52, 128, 83, 69, 76, 69, 67, 84, 79, - 82, 45, 57, 51, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 57, 50, 128, 83, - 69, 76, 69, 67, 84, 79, 82, 45, 57, 49, 128, 83, 69, 76, 69, 67, 84, 79, - 82, 45, 57, 48, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 57, 128, 83, 69, - 76, 69, 67, 84, 79, 82, 45, 56, 57, 128, 83, 69, 76, 69, 67, 84, 79, 82, - 45, 56, 56, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 56, 55, 128, 83, 69, - 76, 69, 67, 84, 79, 82, 45, 56, 54, 128, 83, 69, 76, 69, 67, 84, 79, 82, - 45, 56, 53, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 56, 52, 128, 83, 69, - 76, 69, 67, 84, 79, 82, 45, 56, 51, 128, 83, 69, 76, 69, 67, 84, 79, 82, - 45, 56, 50, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 56, 49, 128, 83, 69, - 76, 69, 67, 84, 79, 82, 45, 56, 48, 128, 83, 69, 76, 69, 67, 84, 79, 82, - 45, 56, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 55, 57, 128, 83, 69, 76, - 69, 67, 84, 79, 82, 45, 55, 56, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, - 55, 55, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 55, 54, 128, 83, 69, 76, - 69, 67, 84, 79, 82, 45, 55, 53, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, - 55, 52, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 55, 51, 128, 83, 69, 76, - 69, 67, 84, 79, 82, 45, 55, 50, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, - 55, 49, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 55, 48, 128, 83, 69, 76, - 69, 67, 84, 79, 82, 45, 55, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 54, - 57, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 54, 56, 128, 83, 69, 76, 69, - 67, 84, 79, 82, 45, 54, 55, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 54, - 54, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 54, 53, 128, 83, 69, 76, 69, - 67, 84, 79, 82, 45, 54, 52, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 54, - 51, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 54, 50, 128, 83, 69, 76, 69, - 67, 84, 79, 82, 45, 54, 49, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 54, - 48, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 54, 128, 83, 69, 76, 69, 67, - 84, 79, 82, 45, 53, 57, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 53, 56, - 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 53, 55, 128, 83, 69, 76, 69, 67, - 84, 79, 82, 45, 53, 54, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 53, 53, - 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 53, 52, 128, 83, 69, 76, 69, 67, - 84, 79, 82, 45, 53, 51, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 53, 50, - 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 53, 49, 128, 83, 69, 76, 69, 67, - 84, 79, 82, 45, 53, 48, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 53, 128, - 83, 69, 76, 69, 67, 84, 79, 82, 45, 52, 57, 128, 83, 69, 76, 69, 67, 84, - 79, 82, 45, 52, 56, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 52, 55, 128, - 83, 69, 76, 69, 67, 84, 79, 82, 45, 52, 54, 128, 83, 69, 76, 69, 67, 84, - 79, 82, 45, 52, 53, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 52, 52, 128, - 83, 69, 76, 69, 67, 84, 79, 82, 45, 52, 51, 128, 83, 69, 76, 69, 67, 84, - 79, 82, 45, 52, 50, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 52, 49, 128, - 83, 69, 76, 69, 67, 84, 79, 82, 45, 52, 48, 128, 83, 69, 76, 69, 67, 84, - 79, 82, 45, 52, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 51, 57, 128, 83, - 69, 76, 69, 67, 84, 79, 82, 45, 51, 56, 128, 83, 69, 76, 69, 67, 84, 79, - 82, 45, 51, 55, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 51, 54, 128, 83, - 69, 76, 69, 67, 84, 79, 82, 45, 51, 53, 128, 83, 69, 76, 69, 67, 84, 79, - 82, 45, 51, 52, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 51, 51, 128, 83, - 69, 76, 69, 67, 84, 79, 82, 45, 51, 50, 128, 83, 69, 76, 69, 67, 84, 79, - 82, 45, 51, 49, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 51, 48, 128, 83, - 69, 76, 69, 67, 84, 79, 82, 45, 51, 128, 83, 69, 76, 69, 67, 84, 79, 82, - 45, 50, 57, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 50, 56, 128, 83, 69, - 76, 69, 67, 84, 79, 82, 45, 50, 55, 128, 83, 69, 76, 69, 67, 84, 79, 82, - 45, 50, 54, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 50, 53, 54, 128, 83, - 69, 76, 69, 67, 84, 79, 82, 45, 50, 53, 53, 128, 83, 69, 76, 69, 67, 84, - 79, 82, 45, 50, 53, 52, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 50, 53, - 51, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 50, 53, 50, 128, 83, 69, 76, - 69, 67, 84, 79, 82, 45, 50, 53, 49, 128, 83, 69, 76, 69, 67, 84, 79, 82, - 45, 50, 53, 48, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 50, 53, 128, 83, - 69, 76, 69, 67, 84, 79, 82, 45, 50, 52, 57, 128, 83, 69, 76, 69, 67, 84, - 79, 82, 45, 50, 52, 56, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 50, 52, - 55, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 50, 52, 54, 128, 83, 69, 76, - 69, 67, 84, 79, 82, 45, 50, 52, 53, 128, 83, 69, 76, 69, 67, 84, 79, 82, - 45, 50, 52, 52, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 50, 52, 51, 128, - 83, 69, 76, 69, 67, 84, 79, 82, 45, 50, 52, 50, 128, 83, 69, 76, 69, 67, - 84, 79, 82, 45, 50, 52, 49, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 50, - 52, 48, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 50, 52, 128, 83, 69, 76, - 69, 67, 84, 79, 82, 45, 50, 51, 57, 128, 83, 69, 76, 69, 67, 84, 79, 82, - 45, 50, 51, 56, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 50, 51, 55, 128, - 83, 69, 76, 69, 67, 84, 79, 82, 45, 50, 51, 54, 128, 83, 69, 76, 69, 67, - 84, 79, 82, 45, 50, 51, 53, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 50, - 51, 52, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 50, 51, 51, 128, 83, 69, - 76, 69, 67, 84, 79, 82, 45, 50, 51, 50, 128, 83, 69, 76, 69, 67, 84, 79, - 82, 45, 50, 51, 49, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 50, 51, 48, - 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 50, 51, 128, 83, 69, 76, 69, 67, - 84, 79, 82, 45, 50, 50, 57, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 50, - 50, 56, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 50, 50, 55, 128, 83, 69, - 76, 69, 67, 84, 79, 82, 45, 50, 50, 54, 128, 83, 69, 76, 69, 67, 84, 79, - 82, 45, 50, 50, 53, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 50, 50, 52, - 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 50, 50, 51, 128, 83, 69, 76, 69, - 67, 84, 79, 82, 45, 50, 50, 50, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, - 50, 50, 49, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 50, 50, 48, 128, 83, - 69, 76, 69, 67, 84, 79, 82, 45, 50, 50, 128, 83, 69, 76, 69, 67, 84, 79, - 82, 45, 50, 49, 57, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 50, 49, 56, - 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 50, 49, 55, 128, 83, 69, 76, 69, - 67, 84, 79, 82, 45, 50, 49, 54, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, - 50, 49, 53, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 50, 49, 52, 128, 83, - 69, 76, 69, 67, 84, 79, 82, 45, 50, 49, 51, 128, 83, 69, 76, 69, 67, 84, - 79, 82, 45, 50, 49, 50, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 50, 49, - 49, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 50, 49, 48, 128, 83, 69, 76, - 69, 67, 84, 79, 82, 45, 50, 49, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, - 50, 48, 57, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 50, 48, 56, 128, 83, - 69, 76, 69, 67, 84, 79, 82, 45, 50, 48, 55, 128, 83, 69, 76, 69, 67, 84, - 79, 82, 45, 50, 48, 54, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 50, 48, - 53, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 50, 48, 52, 128, 83, 69, 76, - 69, 67, 84, 79, 82, 45, 50, 48, 51, 128, 83, 69, 76, 69, 67, 84, 79, 82, - 45, 50, 48, 50, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 50, 48, 49, 128, - 83, 69, 76, 69, 67, 84, 79, 82, 45, 50, 48, 48, 128, 83, 69, 76, 69, 67, - 84, 79, 82, 45, 50, 48, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 50, 128, - 83, 69, 76, 69, 67, 84, 79, 82, 45, 49, 57, 57, 128, 83, 69, 76, 69, 67, - 84, 79, 82, 45, 49, 57, 56, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 49, - 57, 55, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 49, 57, 54, 128, 83, 69, - 76, 69, 67, 84, 79, 82, 45, 49, 57, 53, 128, 83, 69, 76, 69, 67, 84, 79, - 82, 45, 49, 57, 52, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 49, 57, 51, - 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 49, 57, 50, 128, 83, 69, 76, 69, - 67, 84, 79, 82, 45, 49, 57, 49, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, - 49, 57, 48, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 49, 57, 128, 83, 69, - 76, 69, 67, 84, 79, 82, 45, 49, 56, 57, 128, 83, 69, 76, 69, 67, 84, 79, - 82, 45, 49, 56, 56, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 49, 56, 55, - 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 49, 56, 54, 128, 83, 69, 76, 69, - 67, 84, 79, 82, 45, 49, 56, 53, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, - 49, 56, 52, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 49, 56, 51, 128, 83, - 69, 76, 69, 67, 84, 79, 82, 45, 49, 56, 50, 128, 83, 69, 76, 69, 67, 84, - 79, 82, 45, 49, 56, 49, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 49, 56, - 48, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 49, 56, 128, 83, 69, 76, 69, - 67, 84, 79, 82, 45, 49, 55, 57, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, - 49, 55, 56, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 49, 55, 55, 128, 83, - 69, 76, 69, 67, 84, 79, 82, 45, 49, 55, 54, 128, 83, 69, 76, 69, 67, 84, - 79, 82, 45, 49, 55, 53, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 49, 55, - 52, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 49, 55, 51, 128, 83, 69, 76, - 69, 67, 84, 79, 82, 45, 49, 55, 50, 128, 83, 69, 76, 69, 67, 84, 79, 82, - 45, 49, 55, 49, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 49, 55, 48, 128, - 83, 69, 76, 69, 67, 84, 79, 82, 45, 49, 55, 128, 83, 69, 76, 69, 67, 84, - 79, 82, 45, 49, 54, 57, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 49, 54, - 56, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 49, 54, 55, 128, 83, 69, 76, - 69, 67, 84, 79, 82, 45, 49, 54, 54, 128, 83, 69, 76, 69, 67, 84, 79, 82, - 45, 49, 54, 53, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 49, 54, 52, 128, - 83, 69, 76, 69, 67, 84, 79, 82, 45, 49, 54, 51, 128, 83, 69, 76, 69, 67, - 84, 79, 82, 45, 49, 54, 50, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 49, - 54, 49, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 49, 54, 48, 128, 83, 69, - 76, 69, 67, 84, 79, 82, 45, 49, 54, 128, 83, 69, 76, 69, 67, 84, 79, 82, - 45, 49, 53, 57, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 49, 53, 56, 128, - 83, 69, 76, 69, 67, 84, 79, 82, 45, 49, 53, 55, 128, 83, 69, 76, 69, 67, - 84, 79, 82, 45, 49, 53, 54, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 49, - 53, 53, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 49, 53, 52, 128, 83, 69, - 76, 69, 67, 84, 79, 82, 45, 49, 53, 51, 128, 83, 69, 76, 69, 67, 84, 79, - 82, 45, 49, 53, 50, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 49, 53, 49, - 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 49, 53, 48, 128, 83, 69, 76, 69, - 67, 84, 79, 82, 45, 49, 53, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 49, - 52, 57, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 49, 52, 56, 128, 83, 69, - 76, 69, 67, 84, 79, 82, 45, 49, 52, 55, 128, 83, 69, 76, 69, 67, 84, 79, - 82, 45, 49, 52, 54, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 49, 52, 53, - 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 49, 52, 52, 128, 83, 69, 76, 69, - 67, 84, 79, 82, 45, 49, 52, 51, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, - 49, 52, 50, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 49, 52, 49, 128, 83, - 69, 76, 69, 67, 84, 79, 82, 45, 49, 52, 48, 128, 83, 69, 76, 69, 67, 84, - 79, 82, 45, 49, 52, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 49, 51, 57, - 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 49, 51, 56, 128, 83, 69, 76, 69, - 67, 84, 79, 82, 45, 49, 51, 55, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, - 49, 51, 54, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 49, 51, 53, 128, 83, - 69, 76, 69, 67, 84, 79, 82, 45, 49, 51, 52, 128, 83, 69, 76, 69, 67, 84, - 79, 82, 45, 49, 51, 51, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 49, 51, - 50, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 49, 51, 49, 128, 83, 69, 76, - 69, 67, 84, 79, 82, 45, 49, 51, 48, 128, 83, 69, 76, 69, 67, 84, 79, 82, - 45, 49, 51, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 49, 50, 57, 128, 83, - 69, 76, 69, 67, 84, 79, 82, 45, 49, 50, 56, 128, 83, 69, 76, 69, 67, 84, - 79, 82, 45, 49, 50, 55, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 49, 50, - 54, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 49, 50, 53, 128, 83, 69, 76, - 69, 67, 84, 79, 82, 45, 49, 50, 52, 128, 83, 69, 76, 69, 67, 84, 79, 82, - 45, 49, 50, 51, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 49, 50, 50, 128, - 83, 69, 76, 69, 67, 84, 79, 82, 45, 49, 50, 49, 128, 83, 69, 76, 69, 67, - 84, 79, 82, 45, 49, 50, 48, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 49, - 50, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 49, 49, 57, 128, 83, 69, 76, - 69, 67, 84, 79, 82, 45, 49, 49, 56, 128, 83, 69, 76, 69, 67, 84, 79, 82, - 45, 49, 49, 55, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 49, 49, 54, 128, - 83, 69, 76, 69, 67, 84, 79, 82, 45, 49, 49, 53, 128, 83, 69, 76, 69, 67, - 84, 79, 82, 45, 49, 49, 52, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 49, - 49, 51, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 49, 49, 50, 128, 83, 69, - 76, 69, 67, 84, 79, 82, 45, 49, 49, 49, 128, 83, 69, 76, 69, 67, 84, 79, - 82, 45, 49, 49, 48, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 49, 49, 128, - 83, 69, 76, 69, 67, 84, 79, 82, 45, 49, 48, 57, 128, 83, 69, 76, 69, 67, - 84, 79, 82, 45, 49, 48, 56, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 49, - 48, 55, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 49, 48, 54, 128, 83, 69, - 76, 69, 67, 84, 79, 82, 45, 49, 48, 53, 128, 83, 69, 76, 69, 67, 84, 79, - 82, 45, 49, 48, 52, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 49, 48, 51, - 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 49, 48, 50, 128, 83, 69, 76, 69, - 67, 84, 79, 82, 45, 49, 48, 49, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, - 49, 48, 48, 128, 83, 69, 76, 69, 67, 84, 79, 82, 45, 49, 48, 128, 83, 69, - 76, 69, 67, 84, 79, 82, 45, 49, 128, 83, 69, 76, 69, 67, 84, 79, 82, 128, - 83, 69, 76, 69, 67, 84, 79, 210, 83, 69, 76, 69, 67, 84, 69, 196, 83, 69, - 73, 83, 77, 65, 128, 83, 69, 73, 83, 77, 193, 83, 69, 72, 128, 83, 69, - 71, 79, 76, 128, 83, 69, 71, 78, 79, 128, 83, 69, 71, 77, 69, 78, 84, 69, - 196, 83, 69, 71, 77, 69, 78, 84, 128, 83, 69, 69, 86, 128, 83, 69, 69, - 78, 85, 128, 83, 69, 69, 78, 128, 83, 69, 69, 206, 83, 69, 69, 68, 76, - 73, 78, 71, 128, 83, 69, 69, 45, 78, 79, 45, 69, 86, 73, 204, 83, 69, 68, - 78, 65, 128, 83, 69, 67, 84, 79, 82, 128, 83, 69, 67, 84, 73, 79, 78, - 128, 83, 69, 67, 84, 73, 79, 206, 83, 69, 67, 82, 69, 84, 128, 83, 69, - 67, 65, 78, 84, 128, 83, 69, 66, 65, 84, 66, 69, 73, 212, 83, 69, 65, 84, - 128, 83, 69, 65, 76, 128, 83, 69, 65, 71, 85, 76, 204, 83, 69, 45, 53, - 128, 83, 69, 45, 52, 128, 83, 69, 45, 51, 128, 83, 68, 79, 78, 199, 83, - 68, 128, 83, 67, 87, 65, 128, 83, 67, 82, 85, 80, 76, 69, 128, 83, 67, - 82, 79, 76, 76, 128, 83, 67, 82, 73, 80, 84, 128, 83, 67, 82, 69, 87, 68, - 82, 73, 86, 69, 82, 128, 83, 67, 82, 69, 69, 78, 128, 83, 67, 82, 69, 69, - 206, 83, 67, 82, 69, 65, 77, 73, 78, 199, 83, 67, 79, 84, 211, 83, 67, - 79, 82, 80, 73, 85, 83, 128, 83, 67, 79, 82, 80, 73, 79, 78, 128, 83, 67, - 79, 82, 69, 128, 83, 67, 79, 79, 84, 69, 82, 128, 83, 67, 73, 83, 83, 79, - 82, 83, 128, 83, 67, 73, 128, 83, 67, 72, 87, 65, 128, 83, 67, 72, 87, - 193, 83, 67, 72, 82, 79, 69, 68, 69, 82, 128, 83, 67, 72, 79, 79, 76, - 128, 83, 67, 72, 79, 79, 204, 83, 67, 72, 79, 76, 65, 82, 128, 83, 67, - 72, 69, 77, 193, 83, 67, 69, 80, 84, 69, 210, 83, 67, 65, 82, 70, 128, - 83, 67, 65, 78, 68, 73, 67, 85, 83, 128, 83, 67, 65, 78, 68, 73, 67, 85, - 211, 83, 67, 65, 206, 83, 67, 65, 76, 69, 83, 128, 83, 66, 85, 194, 83, - 66, 82, 85, 204, 83, 65, 89, 73, 83, 201, 83, 65, 89, 65, 78, 78, 65, - 128, 83, 65, 89, 128, 83, 65, 88, 79, 80, 72, 79, 78, 69, 128, 83, 65, - 88, 73, 77, 65, 84, 65, 128, 83, 65, 87, 65, 78, 128, 83, 65, 87, 128, - 83, 65, 86, 79, 85, 82, 73, 78, 199, 83, 65, 85, 82, 79, 80, 79, 68, 128, - 83, 65, 85, 82, 65, 83, 72, 84, 82, 193, 83, 65, 85, 73, 76, 128, 83, 65, - 85, 67, 69, 82, 128, 83, 65, 84, 85, 82, 78, 128, 83, 65, 84, 75, 65, 65, - 78, 75, 85, 85, 128, 83, 65, 84, 75, 65, 65, 78, 128, 83, 65, 84, 69, 76, - 76, 73, 84, 69, 128, 83, 65, 84, 69, 76, 76, 73, 84, 197, 83, 65, 84, 67, - 72, 69, 76, 128, 83, 65, 84, 65, 78, 71, 65, 128, 83, 65, 83, 72, 128, - 83, 65, 83, 65, 75, 128, 83, 65, 82, 73, 128, 83, 65, 82, 193, 83, 65, - 82, 128, 83, 65, 81, 128, 83, 65, 80, 65, 128, 83, 65, 78, 89, 79, 79, - 71, 193, 83, 65, 78, 89, 65, 75, 193, 83, 65, 78, 84, 73, 73, 77, 85, - 128, 83, 65, 78, 83, 75, 82, 73, 212, 83, 65, 78, 78, 89, 65, 128, 83, - 65, 78, 71, 65, 50, 128, 83, 65, 78, 68, 87, 73, 67, 72, 128, 83, 65, 78, - 68, 72, 201, 83, 65, 78, 68, 65, 76, 128, 83, 65, 78, 65, 72, 128, 83, - 65, 78, 128, 83, 65, 77, 89, 79, 203, 83, 65, 77, 86, 65, 84, 128, 83, - 65, 77, 80, 73, 128, 83, 65, 77, 80, 72, 65, 79, 128, 83, 65, 77, 75, 65, - 128, 83, 65, 77, 69, 75, 72, 128, 83, 65, 77, 69, 75, 200, 83, 65, 77, - 66, 65, 128, 83, 65, 77, 65, 82, 73, 84, 65, 206, 83, 65, 77, 128, 83, - 65, 76, 85, 84, 73, 78, 199, 83, 65, 76, 84, 73, 82, 69, 128, 83, 65, 76, - 84, 73, 82, 197, 83, 65, 76, 84, 73, 76, 76, 79, 128, 83, 65, 76, 84, 45, - 50, 128, 83, 65, 76, 84, 128, 83, 65, 76, 212, 83, 65, 76, 76, 65, 76, - 76, 65, 72, 213, 83, 65, 76, 76, 65, 76, 76, 65, 72, 79, 213, 83, 65, 76, - 76, 65, 76, 76, 65, 65, 72, 213, 83, 65, 76, 76, 193, 83, 65, 76, 65, - 205, 83, 65, 76, 65, 68, 128, 83, 65, 76, 65, 65, 77, 85, 72, 213, 83, - 65, 76, 65, 128, 83, 65, 76, 45, 65, 77, 77, 79, 78, 73, 65, 67, 128, 83, - 65, 76, 128, 83, 65, 75, 84, 65, 128, 83, 65, 75, 79, 84, 128, 83, 65, - 75, 73, 78, 128, 83, 65, 75, 72, 193, 83, 65, 75, 69, 85, 65, 69, 128, - 83, 65, 75, 197, 83, 65, 74, 68, 65, 72, 128, 83, 65, 73, 76, 66, 79, 65, - 84, 128, 83, 65, 73, 76, 128, 83, 65, 73, 75, 85, 82, 85, 128, 83, 65, - 72, 128, 83, 65, 71, 73, 84, 84, 65, 82, 73, 85, 83, 128, 83, 65, 71, 65, - 128, 83, 65, 71, 128, 83, 65, 199, 83, 65, 70, 72, 65, 128, 83, 65, 70, - 69, 84, 217, 83, 65, 68, 72, 69, 128, 83, 65, 68, 72, 197, 83, 65, 68, - 69, 128, 83, 65, 68, 128, 83, 65, 196, 83, 65, 67, 82, 73, 70, 73, 67, - 73, 65, 204, 83, 65, 65, 73, 128, 83, 65, 65, 68, 72, 85, 128, 83, 65, - 45, 73, 128, 83, 65, 45, 56, 128, 83, 65, 45, 55, 128, 83, 65, 45, 54, - 128, 83, 65, 45, 53, 128, 83, 65, 45, 52, 128, 83, 65, 45, 51, 128, 83, - 65, 45, 50, 128, 83, 65, 45, 49, 128, 83, 48, 52, 54, 128, 83, 48, 52, - 53, 128, 83, 48, 52, 52, 128, 83, 48, 52, 51, 128, 83, 48, 52, 50, 128, - 83, 48, 52, 49, 128, 83, 48, 52, 48, 128, 83, 48, 51, 57, 128, 83, 48, - 51, 56, 128, 83, 48, 51, 55, 128, 83, 48, 51, 54, 128, 83, 48, 51, 53, - 65, 128, 83, 48, 51, 53, 128, 83, 48, 51, 52, 128, 83, 48, 51, 51, 128, - 83, 48, 51, 50, 128, 83, 48, 51, 49, 128, 83, 48, 51, 48, 128, 83, 48, - 50, 57, 128, 83, 48, 50, 56, 128, 83, 48, 50, 55, 128, 83, 48, 50, 54, - 66, 128, 83, 48, 50, 54, 65, 128, 83, 48, 50, 54, 128, 83, 48, 50, 53, - 128, 83, 48, 50, 52, 128, 83, 48, 50, 51, 128, 83, 48, 50, 50, 128, 83, - 48, 50, 49, 128, 83, 48, 50, 48, 128, 83, 48, 49, 57, 128, 83, 48, 49, - 56, 128, 83, 48, 49, 55, 65, 128, 83, 48, 49, 55, 128, 83, 48, 49, 54, - 128, 83, 48, 49, 53, 128, 83, 48, 49, 52, 66, 128, 83, 48, 49, 52, 65, - 128, 83, 48, 49, 52, 128, 83, 48, 49, 51, 128, 83, 48, 49, 50, 128, 83, - 48, 49, 49, 128, 83, 48, 49, 48, 128, 83, 48, 48, 57, 128, 83, 48, 48, - 56, 128, 83, 48, 48, 55, 128, 83, 48, 48, 54, 65, 128, 83, 48, 48, 54, - 128, 83, 48, 48, 53, 128, 83, 48, 48, 52, 128, 83, 48, 48, 51, 128, 83, - 48, 48, 50, 65, 128, 83, 48, 48, 50, 128, 83, 48, 48, 49, 128, 83, 45, - 87, 128, 83, 45, 83, 72, 65, 80, 69, 196, 82, 89, 89, 128, 82, 89, 88, - 128, 82, 89, 84, 128, 82, 89, 82, 88, 128, 82, 89, 82, 128, 82, 89, 80, - 128, 82, 87, 79, 79, 128, 82, 87, 79, 128, 82, 87, 73, 73, 128, 82, 87, - 73, 128, 82, 87, 69, 69, 128, 82, 87, 69, 128, 82, 87, 65, 72, 65, 128, - 82, 87, 65, 65, 128, 82, 87, 65, 128, 82, 85, 88, 128, 82, 85, 85, 66, - 85, 82, 85, 128, 82, 85, 85, 128, 82, 85, 84, 128, 82, 85, 83, 83, 73, - 65, 206, 82, 85, 83, 73, 128, 82, 85, 82, 88, 128, 82, 85, 82, 128, 82, - 85, 80, 73, 73, 128, 82, 85, 80, 69, 197, 82, 85, 80, 128, 82, 85, 79, - 88, 128, 82, 85, 79, 80, 128, 82, 85, 79, 128, 82, 85, 78, 79, 85, 84, - 128, 82, 85, 78, 78, 73, 78, 199, 82, 85, 78, 78, 69, 82, 128, 82, 85, - 78, 73, 195, 82, 85, 78, 128, 82, 85, 77, 201, 82, 85, 77, 65, 201, 82, - 85, 77, 128, 82, 85, 205, 82, 85, 76, 69, 82, 128, 82, 85, 76, 69, 45, - 68, 69, 76, 65, 89, 69, 68, 128, 82, 85, 76, 69, 128, 82, 85, 76, 65, 73, - 128, 82, 85, 75, 75, 65, 75, 72, 65, 128, 82, 85, 73, 83, 128, 82, 85, - 71, 66, 217, 82, 85, 68, 73, 77, 69, 78, 84, 193, 82, 85, 66, 76, 197, - 82, 85, 194, 82, 85, 65, 128, 82, 85, 45, 54, 128, 82, 85, 45, 53, 128, - 82, 85, 45, 52, 128, 82, 85, 45, 51, 128, 82, 85, 45, 50, 128, 82, 85, - 45, 49, 128, 82, 84, 72, 65, 78, 199, 82, 84, 69, 128, 82, 84, 65, 71, - 83, 128, 82, 84, 65, 71, 211, 82, 82, 89, 88, 128, 82, 82, 89, 84, 128, - 82, 82, 89, 82, 88, 128, 82, 82, 89, 82, 128, 82, 82, 89, 80, 128, 82, - 82, 85, 88, 128, 82, 82, 85, 85, 128, 82, 82, 85, 84, 128, 82, 82, 85, - 82, 88, 128, 82, 82, 85, 82, 128, 82, 82, 85, 80, 128, 82, 82, 85, 79, - 88, 128, 82, 82, 85, 79, 128, 82, 82, 85, 128, 82, 82, 82, 65, 128, 82, - 82, 79, 88, 128, 82, 82, 79, 84, 128, 82, 82, 79, 80, 128, 82, 82, 79, - 79, 128, 82, 82, 79, 128, 82, 82, 73, 73, 128, 82, 82, 73, 128, 82, 82, - 69, 88, 128, 82, 82, 69, 84, 128, 82, 82, 69, 80, 128, 82, 82, 69, 72, - 128, 82, 82, 69, 200, 82, 82, 69, 69, 128, 82, 82, 69, 128, 82, 82, 65, - 88, 128, 82, 82, 65, 85, 128, 82, 82, 65, 73, 128, 82, 82, 65, 65, 128, - 82, 79, 87, 66, 79, 65, 84, 128, 82, 79, 85, 78, 68, 69, 196, 82, 79, 85, - 78, 68, 45, 84, 73, 80, 80, 69, 196, 82, 79, 84, 85, 78, 68, 65, 128, 82, - 79, 84, 65, 84, 73, 79, 78, 83, 128, 82, 79, 84, 65, 84, 73, 79, 78, 45, - 87, 65, 76, 76, 80, 76, 65, 78, 197, 82, 79, 84, 65, 84, 73, 79, 78, 45, - 70, 76, 79, 79, 82, 80, 76, 65, 78, 197, 82, 79, 84, 65, 84, 73, 79, 78, - 128, 82, 79, 84, 65, 84, 73, 79, 206, 82, 79, 84, 65, 84, 69, 196, 82, - 79, 83, 72, 128, 82, 79, 83, 69, 84, 84, 69, 128, 82, 79, 83, 69, 128, - 82, 79, 79, 84, 128, 82, 79, 79, 83, 84, 69, 82, 128, 82, 79, 79, 77, - 128, 82, 79, 79, 75, 128, 82, 79, 79, 203, 82, 79, 79, 70, 128, 82, 79, - 77, 65, 78, 73, 65, 206, 82, 79, 77, 65, 206, 82, 79, 77, 128, 82, 79, - 76, 76, 73, 78, 199, 82, 79, 76, 76, 69, 210, 82, 79, 76, 76, 69, 68, 45, - 85, 208, 82, 79, 76, 204, 82, 79, 72, 73, 78, 71, 89, 193, 82, 79, 71, - 79, 77, 128, 82, 79, 71, 128, 82, 79, 196, 82, 79, 67, 75, 69, 84, 128, - 82, 79, 67, 203, 82, 79, 67, 128, 82, 79, 66, 79, 212, 82, 79, 66, 65, - 84, 128, 82, 79, 65, 83, 84, 69, 196, 82, 79, 65, 82, 128, 82, 79, 65, - 128, 82, 79, 45, 54, 128, 82, 79, 45, 53, 128, 82, 79, 45, 52, 128, 82, - 79, 45, 51, 128, 82, 79, 45, 50, 128, 82, 79, 45, 49, 128, 82, 78, 89, - 73, 78, 199, 82, 78, 79, 79, 78, 128, 82, 78, 79, 79, 206, 82, 78, 65, - 205, 82, 77, 84, 128, 82, 76, 79, 128, 82, 76, 77, 128, 82, 76, 73, 128, - 82, 76, 69, 128, 82, 74, 69, 211, 82, 74, 69, 128, 82, 74, 197, 82, 73, - 84, 85, 65, 76, 128, 82, 73, 84, 84, 79, 82, 85, 128, 82, 73, 84, 83, 73, - 128, 82, 73, 83, 73, 78, 199, 82, 73, 83, 72, 128, 82, 73, 82, 65, 128, - 82, 73, 80, 80, 76, 197, 82, 73, 80, 128, 82, 73, 78, 71, 211, 82, 73, - 78, 71, 73, 78, 199, 82, 73, 78, 71, 69, 196, 82, 73, 78, 70, 79, 82, 90, - 65, 78, 68, 79, 128, 82, 73, 206, 82, 73, 77, 71, 66, 65, 128, 82, 73, - 77, 128, 82, 73, 75, 82, 73, 75, 128, 82, 73, 71, 86, 69, 68, 73, 195, - 82, 73, 71, 72, 84, 87, 65, 82, 68, 83, 128, 82, 73, 71, 72, 84, 72, 65, - 78, 196, 82, 73, 71, 72, 84, 45, 84, 79, 45, 76, 69, 70, 212, 82, 73, 71, - 72, 84, 45, 83, 73, 68, 197, 82, 73, 71, 72, 84, 45, 83, 72, 65, 68, 79, - 87, 69, 196, 82, 73, 71, 72, 84, 45, 83, 72, 65, 68, 69, 196, 82, 73, 71, - 72, 84, 45, 80, 79, 73, 78, 84, 73, 78, 199, 82, 73, 71, 72, 84, 45, 76, - 73, 71, 72, 84, 69, 196, 82, 73, 71, 72, 84, 45, 72, 65, 78, 68, 69, 196, - 82, 73, 71, 72, 84, 45, 72, 65, 78, 196, 82, 73, 71, 72, 84, 45, 70, 65, - 67, 73, 78, 199, 82, 73, 70, 76, 69, 128, 82, 73, 69, 85, 76, 45, 89, 69, - 83, 73, 69, 85, 78, 71, 128, 82, 73, 69, 85, 76, 45, 89, 69, 79, 82, 73, - 78, 72, 73, 69, 85, 72, 45, 72, 73, 69, 85, 72, 128, 82, 73, 69, 85, 76, - 45, 89, 69, 79, 82, 73, 78, 72, 73, 69, 85, 72, 128, 82, 73, 69, 85, 76, - 45, 84, 73, 75, 69, 85, 84, 45, 72, 73, 69, 85, 72, 128, 82, 73, 69, 85, - 76, 45, 84, 73, 75, 69, 85, 84, 128, 82, 73, 69, 85, 76, 45, 84, 72, 73, - 69, 85, 84, 72, 128, 82, 73, 69, 85, 76, 45, 83, 83, 65, 78, 71, 84, 73, - 75, 69, 85, 84, 128, 82, 73, 69, 85, 76, 45, 83, 83, 65, 78, 71, 83, 73, - 79, 83, 128, 82, 73, 69, 85, 76, 45, 83, 83, 65, 78, 71, 80, 73, 69, 85, - 80, 128, 82, 73, 69, 85, 76, 45, 83, 83, 65, 78, 71, 75, 73, 89, 69, 79, - 75, 128, 82, 73, 69, 85, 76, 45, 83, 73, 79, 83, 128, 82, 73, 69, 85, 76, - 45, 80, 73, 69, 85, 80, 45, 84, 73, 75, 69, 85, 84, 128, 82, 73, 69, 85, - 76, 45, 80, 73, 69, 85, 80, 45, 83, 73, 79, 83, 128, 82, 73, 69, 85, 76, - 45, 80, 73, 69, 85, 80, 45, 80, 72, 73, 69, 85, 80, 72, 128, 82, 73, 69, - 85, 76, 45, 80, 73, 69, 85, 80, 45, 72, 73, 69, 85, 72, 128, 82, 73, 69, - 85, 76, 45, 80, 73, 69, 85, 80, 128, 82, 73, 69, 85, 76, 45, 80, 72, 73, - 69, 85, 80, 72, 128, 82, 73, 69, 85, 76, 45, 80, 65, 78, 83, 73, 79, 83, - 128, 82, 73, 69, 85, 76, 45, 78, 73, 69, 85, 78, 128, 82, 73, 69, 85, 76, - 45, 77, 73, 69, 85, 77, 45, 83, 73, 79, 83, 128, 82, 73, 69, 85, 76, 45, - 77, 73, 69, 85, 77, 45, 75, 73, 89, 69, 79, 75, 128, 82, 73, 69, 85, 76, - 45, 77, 73, 69, 85, 77, 45, 72, 73, 69, 85, 72, 128, 82, 73, 69, 85, 76, - 45, 77, 73, 69, 85, 77, 128, 82, 73, 69, 85, 76, 45, 75, 73, 89, 69, 79, - 75, 45, 83, 73, 79, 83, 128, 82, 73, 69, 85, 76, 45, 75, 73, 89, 69, 79, - 75, 45, 72, 73, 69, 85, 72, 128, 82, 73, 69, 85, 76, 45, 75, 73, 89, 69, - 79, 75, 128, 82, 73, 69, 85, 76, 45, 75, 65, 80, 89, 69, 79, 85, 78, 80, - 73, 69, 85, 80, 128, 82, 73, 69, 85, 76, 45, 72, 73, 69, 85, 72, 128, 82, - 73, 69, 85, 76, 45, 67, 73, 69, 85, 67, 128, 82, 73, 69, 85, 204, 82, 73, - 69, 76, 128, 82, 73, 69, 69, 128, 82, 73, 67, 75, 83, 72, 65, 87, 128, - 82, 73, 67, 69, 77, 128, 82, 73, 67, 69, 128, 82, 73, 67, 197, 82, 73, - 66, 66, 79, 78, 128, 82, 73, 66, 66, 79, 206, 82, 73, 65, 204, 82, 73, - 45, 55, 128, 82, 73, 45, 54, 128, 82, 73, 45, 53, 128, 82, 73, 45, 52, - 128, 82, 73, 45, 51, 128, 82, 73, 45, 50, 128, 82, 73, 45, 49, 128, 82, - 72, 79, 84, 73, 195, 82, 72, 79, 128, 82, 72, 207, 82, 72, 73, 78, 79, - 67, 69, 82, 79, 83, 128, 82, 72, 65, 128, 82, 72, 128, 82, 71, 89, 73, - 78, 71, 83, 128, 82, 71, 89, 65, 78, 128, 82, 71, 89, 193, 82, 69, 86, - 79, 76, 86, 73, 78, 199, 82, 69, 86, 79, 76, 85, 84, 73, 79, 78, 128, 82, - 69, 86, 77, 65, 128, 82, 69, 86, 73, 65, 128, 82, 69, 86, 69, 82, 83, 69, - 68, 45, 83, 67, 72, 87, 65, 128, 82, 69, 86, 69, 82, 83, 69, 68, 128, 82, - 69, 86, 69, 82, 83, 69, 196, 82, 69, 86, 69, 82, 83, 197, 82, 69, 85, 88, - 128, 82, 69, 85, 128, 82, 69, 84, 85, 82, 78, 128, 82, 69, 84, 85, 82, - 206, 82, 69, 84, 82, 79, 70, 76, 69, 216, 82, 69, 84, 82, 69, 65, 84, - 128, 82, 69, 84, 79, 82, 84, 128, 82, 69, 83, 85, 80, 73, 78, 85, 83, - 128, 82, 69, 83, 84, 82, 79, 79, 77, 128, 82, 69, 83, 84, 82, 73, 67, 84, - 69, 196, 82, 69, 83, 84, 128, 82, 69, 83, 80, 79, 78, 83, 69, 128, 82, - 69, 83, 79, 85, 82, 67, 69, 128, 82, 69, 83, 79, 76, 85, 84, 73, 79, 78, - 128, 82, 69, 83, 73, 83, 84, 65, 78, 67, 69, 128, 82, 69, 83, 73, 68, 69, - 78, 67, 69, 128, 82, 69, 83, 72, 45, 65, 89, 73, 78, 45, 68, 65, 76, 69, - 84, 72, 128, 82, 69, 83, 72, 45, 65, 89, 73, 78, 128, 82, 69, 83, 200, - 82, 69, 82, 69, 78, 71, 71, 65, 78, 128, 82, 69, 82, 69, 75, 65, 78, 128, - 82, 69, 80, 82, 69, 83, 69, 78, 84, 128, 82, 69, 80, 76, 65, 67, 69, 77, - 69, 78, 212, 82, 69, 80, 72, 65, 128, 82, 69, 80, 72, 128, 82, 69, 80, - 69, 84, 73, 84, 73, 79, 206, 82, 69, 80, 69, 65, 84, 69, 196, 82, 69, 80, - 69, 65, 84, 128, 82, 69, 80, 69, 65, 212, 82, 69, 80, 65, 89, 65, 128, - 82, 69, 80, 65, 128, 82, 69, 80, 193, 82, 69, 78, 84, 79, 71, 69, 78, - 128, 82, 69, 78, 128, 82, 69, 206, 82, 69, 77, 85, 128, 82, 69, 77, 73, - 78, 68, 69, 210, 82, 69, 77, 69, 68, 89, 128, 82, 69, 76, 73, 71, 73, 79, - 78, 128, 82, 69, 76, 73, 69, 86, 69, 196, 82, 69, 76, 69, 65, 83, 69, - 128, 82, 69, 76, 65, 88, 69, 68, 128, 82, 69, 76, 65, 84, 73, 79, 78, 65, - 204, 82, 69, 76, 65, 84, 73, 79, 78, 128, 82, 69, 76, 65, 65, 128, 82, - 69, 74, 65, 78, 199, 82, 69, 73, 87, 65, 128, 82, 69, 73, 196, 82, 69, - 73, 128, 82, 69, 71, 85, 76, 85, 83, 45, 52, 128, 82, 69, 71, 85, 76, 85, - 83, 45, 51, 128, 82, 69, 71, 85, 76, 85, 83, 45, 50, 128, 82, 69, 71, 85, - 76, 85, 83, 128, 82, 69, 71, 85, 76, 85, 211, 82, 69, 71, 73, 83, 84, 69, - 82, 69, 196, 82, 69, 71, 73, 79, 78, 65, 204, 82, 69, 71, 73, 65, 45, 50, - 128, 82, 69, 71, 73, 65, 128, 82, 69, 70, 79, 82, 77, 69, 196, 82, 69, - 70, 69, 82, 69, 78, 67, 197, 82, 69, 68, 85, 80, 76, 73, 67, 65, 84, 73, - 79, 78, 128, 82, 69, 67, 89, 67, 76, 73, 78, 199, 82, 69, 67, 89, 67, 76, - 69, 196, 82, 69, 67, 84, 73, 76, 73, 78, 69, 65, 210, 82, 69, 67, 84, 65, - 78, 71, 85, 76, 65, 210, 82, 69, 67, 84, 65, 78, 71, 76, 69, 128, 82, 69, - 67, 84, 65, 78, 71, 76, 197, 82, 69, 67, 82, 69, 65, 84, 73, 79, 78, 65, - 204, 82, 69, 67, 79, 82, 68, 73, 78, 199, 82, 69, 67, 79, 82, 68, 69, 82, - 128, 82, 69, 67, 79, 82, 68, 128, 82, 69, 67, 79, 82, 196, 82, 69, 67, - 73, 84, 65, 84, 73, 86, 197, 82, 69, 67, 69, 80, 84, 73, 86, 197, 82, 69, - 67, 69, 73, 86, 69, 82, 128, 82, 69, 67, 69, 73, 86, 69, 210, 82, 69, 67, - 69, 73, 80, 84, 128, 82, 69, 65, 76, 71, 65, 82, 45, 50, 128, 82, 69, 65, - 76, 71, 65, 82, 128, 82, 69, 65, 72, 77, 85, 75, 128, 82, 69, 65, 68, 73, - 78, 199, 82, 69, 65, 67, 72, 128, 82, 69, 45, 52, 128, 82, 69, 45, 51, - 128, 82, 69, 45, 50, 128, 82, 69, 45, 49, 128, 82, 68, 207, 82, 68, 69, - 204, 82, 66, 65, 83, 193, 82, 65, 90, 83, 69, 75, 65, 128, 82, 65, 90, - 79, 82, 128, 82, 65, 89, 83, 128, 82, 65, 89, 211, 82, 65, 89, 65, 78, - 78, 65, 128, 82, 65, 86, 78, 79, 128, 82, 65, 84, 73, 79, 128, 82, 65, - 84, 72, 65, 128, 82, 65, 84, 72, 193, 82, 65, 84, 65, 128, 82, 65, 84, - 128, 82, 65, 83, 87, 65, 68, 73, 128, 82, 65, 83, 79, 85, 204, 82, 65, - 83, 72, 65, 128, 82, 65, 81, 128, 82, 65, 80, 73, 83, 77, 65, 128, 82, - 65, 78, 71, 197, 82, 65, 78, 65, 128, 82, 65, 78, 128, 82, 65, 77, 211, - 82, 65, 77, 66, 65, 84, 128, 82, 65, 75, 72, 65, 78, 71, 128, 82, 65, 75, - 65, 65, 82, 65, 65, 78, 83, 65, 89, 65, 128, 82, 65, 73, 83, 73, 78, 199, - 82, 65, 73, 83, 69, 68, 128, 82, 65, 73, 83, 69, 196, 82, 65, 73, 78, 66, - 79, 87, 128, 82, 65, 73, 76, 87, 65, 89, 128, 82, 65, 73, 76, 87, 65, - 217, 82, 65, 73, 76, 128, 82, 65, 73, 68, 207, 82, 65, 73, 68, 65, 128, - 82, 65, 72, 77, 65, 84, 85, 76, 76, 65, 200, 82, 65, 72, 73, 77, 65, 72, - 85, 205, 82, 65, 72, 73, 77, 65, 72, 213, 82, 65, 70, 69, 128, 82, 65, - 69, 77, 128, 82, 65, 68, 73, 79, 65, 67, 84, 73, 86, 197, 82, 65, 68, 73, - 79, 128, 82, 65, 68, 73, 207, 82, 65, 68, 201, 82, 65, 68, 128, 82, 65, - 196, 82, 65, 67, 81, 85, 69, 212, 82, 65, 67, 73, 78, 71, 128, 82, 65, - 67, 73, 78, 199, 82, 65, 67, 67, 79, 79, 78, 128, 82, 65, 66, 66, 73, 84, - 128, 82, 65, 66, 66, 73, 212, 82, 65, 66, 128, 82, 65, 65, 73, 128, 82, - 65, 51, 128, 82, 65, 50, 128, 82, 65, 45, 75, 65, 82, 65, 128, 82, 65, - 45, 52, 128, 82, 65, 45, 51, 128, 82, 65, 45, 50, 128, 82, 65, 45, 49, - 128, 82, 48, 50, 57, 128, 82, 48, 50, 56, 128, 82, 48, 50, 55, 128, 82, - 48, 50, 54, 128, 82, 48, 50, 53, 128, 82, 48, 50, 52, 128, 82, 48, 50, - 51, 128, 82, 48, 50, 50, 128, 82, 48, 50, 49, 128, 82, 48, 50, 48, 128, - 82, 48, 49, 57, 128, 82, 48, 49, 56, 128, 82, 48, 49, 55, 128, 82, 48, - 49, 54, 65, 128, 82, 48, 49, 54, 128, 82, 48, 49, 53, 128, 82, 48, 49, - 52, 128, 82, 48, 49, 51, 128, 82, 48, 49, 50, 128, 82, 48, 49, 49, 128, - 82, 48, 49, 48, 65, 128, 82, 48, 49, 48, 128, 82, 48, 48, 57, 128, 82, - 48, 48, 56, 128, 82, 48, 48, 55, 128, 82, 48, 48, 54, 128, 82, 48, 48, - 53, 128, 82, 48, 48, 52, 128, 82, 48, 48, 51, 66, 128, 82, 48, 48, 51, - 65, 128, 82, 48, 48, 51, 128, 82, 48, 48, 50, 65, 128, 82, 48, 48, 50, - 128, 82, 48, 48, 49, 128, 82, 45, 67, 82, 69, 197, 81, 89, 88, 128, 81, - 89, 85, 128, 81, 89, 84, 128, 81, 89, 82, 88, 128, 81, 89, 82, 128, 81, - 89, 80, 128, 81, 89, 79, 128, 81, 89, 73, 128, 81, 89, 69, 69, 128, 81, - 89, 69, 128, 81, 89, 65, 65, 128, 81, 89, 65, 128, 81, 89, 128, 81, 87, - 73, 128, 81, 87, 69, 69, 128, 81, 87, 69, 128, 81, 87, 65, 65, 128, 81, - 87, 65, 128, 81, 85, 88, 128, 81, 85, 86, 128, 81, 85, 85, 86, 128, 81, - 85, 85, 128, 81, 85, 84, 128, 81, 85, 83, 72, 83, 72, 65, 89, 65, 128, - 81, 85, 82, 88, 128, 81, 85, 82, 128, 81, 85, 80, 128, 81, 85, 79, 88, - 128, 81, 85, 79, 84, 197, 81, 85, 79, 84, 65, 84, 73, 79, 206, 81, 85, - 79, 84, 128, 81, 85, 79, 80, 128, 81, 85, 79, 128, 81, 85, 75, 128, 81, - 85, 73, 78, 84, 73, 76, 69, 128, 81, 85, 73, 78, 84, 69, 83, 83, 69, 78, - 67, 69, 128, 81, 85, 73, 78, 68, 73, 67, 69, 83, 73, 77, 193, 81, 85, 73, - 78, 67, 85, 78, 88, 128, 81, 85, 73, 78, 65, 82, 73, 85, 211, 81, 85, 73, - 76, 212, 81, 85, 73, 76, 76, 128, 81, 85, 73, 67, 203, 81, 85, 73, 128, - 81, 85, 70, 128, 81, 85, 69, 83, 84, 73, 79, 78, 69, 196, 81, 85, 69, 83, - 84, 73, 79, 78, 128, 81, 85, 69, 83, 84, 73, 79, 206, 81, 85, 69, 69, 78, - 128, 81, 85, 69, 69, 206, 81, 85, 69, 128, 81, 85, 68, 68, 73, 83, 193, - 81, 85, 66, 85, 84, 83, 128, 81, 85, 65, 84, 69, 82, 78, 73, 79, 206, 81, - 85, 65, 82, 84, 69, 82, 83, 128, 81, 85, 65, 82, 84, 69, 82, 211, 81, 85, - 65, 82, 84, 69, 82, 128, 81, 85, 65, 79, 65, 82, 128, 81, 85, 65, 78, 84, - 73, 84, 217, 81, 85, 65, 68, 82, 85, 80, 76, 197, 81, 85, 65, 68, 82, 65, - 78, 84, 128, 81, 85, 65, 68, 82, 65, 78, 212, 81, 85, 65, 68, 67, 79, 76, - 79, 78, 128, 81, 85, 65, 68, 128, 81, 85, 65, 196, 81, 85, 65, 128, 81, - 85, 128, 81, 208, 81, 79, 88, 128, 81, 79, 84, 128, 81, 79, 80, 72, 128, - 81, 79, 80, 65, 128, 81, 79, 80, 128, 81, 79, 79, 128, 81, 79, 207, 81, - 79, 70, 128, 81, 79, 198, 81, 79, 65, 128, 81, 79, 128, 81, 78, 128, 81, - 73, 88, 128, 81, 73, 84, 83, 65, 128, 81, 73, 84, 128, 81, 73, 80, 128, - 81, 73, 73, 128, 81, 73, 70, 128, 81, 73, 69, 88, 128, 81, 73, 69, 84, - 128, 81, 73, 69, 80, 128, 81, 73, 69, 128, 81, 73, 128, 81, 72, 87, 73, - 128, 81, 72, 87, 69, 69, 128, 81, 72, 87, 69, 128, 81, 72, 87, 65, 65, - 128, 81, 72, 87, 65, 128, 81, 72, 85, 128, 81, 72, 79, 80, 72, 128, 81, - 72, 79, 128, 81, 72, 73, 128, 81, 72, 69, 69, 128, 81, 72, 69, 128, 81, - 72, 65, 85, 128, 81, 72, 65, 65, 128, 81, 72, 65, 128, 81, 71, 65, 128, - 81, 69, 84, 65, 78, 65, 128, 81, 69, 69, 128, 81, 69, 128, 81, 65, 89, - 128, 81, 65, 85, 128, 81, 65, 84, 65, 78, 128, 81, 65, 83, 82, 128, 81, - 65, 82, 78, 69, 217, 81, 65, 82, 128, 81, 65, 81, 128, 81, 65, 80, 72, - 128, 81, 65, 77, 65, 84, 83, 128, 81, 65, 77, 65, 84, 211, 81, 65, 76, - 193, 81, 65, 73, 82, 84, 72, 82, 65, 128, 81, 65, 73, 128, 81, 65, 70, - 128, 81, 65, 198, 81, 65, 68, 77, 65, 128, 81, 65, 65, 73, 128, 81, 65, - 65, 70, 85, 128, 81, 65, 65, 70, 128, 81, 48, 48, 55, 128, 81, 48, 48, - 54, 128, 81, 48, 48, 53, 128, 81, 48, 48, 52, 128, 81, 48, 48, 51, 128, - 81, 48, 48, 50, 128, 81, 48, 48, 49, 128, 80, 90, 128, 80, 89, 88, 128, - 80, 89, 84, 128, 80, 89, 82, 88, 128, 80, 89, 82, 128, 80, 89, 80, 128, - 80, 87, 79, 89, 128, 80, 87, 79, 79, 128, 80, 87, 79, 128, 80, 87, 207, - 80, 87, 73, 73, 128, 80, 87, 73, 128, 80, 87, 69, 69, 128, 80, 87, 69, - 128, 80, 87, 65, 65, 128, 80, 87, 128, 80, 86, 128, 80, 85, 90, 90, 76, - 197, 80, 85, 88, 128, 80, 85, 85, 84, 128, 80, 85, 85, 128, 80, 85, 84, - 82, 69, 70, 65, 67, 84, 73, 79, 78, 128, 80, 85, 84, 78, 65, 89, 65, 128, - 80, 85, 84, 128, 80, 85, 212, 80, 85, 83, 72, 80, 73, 78, 128, 80, 85, - 83, 72, 80, 73, 75, 65, 128, 80, 85, 83, 72, 73, 78, 199, 80, 85, 82, 88, - 128, 80, 85, 82, 83, 69, 128, 80, 85, 82, 80, 76, 197, 80, 85, 82, 78, - 65, 77, 65, 128, 80, 85, 82, 73, 84, 89, 128, 80, 85, 82, 73, 70, 89, - 128, 80, 85, 82, 128, 80, 85, 81, 128, 80, 85, 80, 128, 80, 85, 79, 88, - 128, 80, 85, 79, 80, 128, 80, 85, 79, 128, 80, 85, 78, 71, 65, 65, 77, - 128, 80, 85, 78, 71, 128, 80, 85, 78, 67, 84, 85, 211, 80, 85, 78, 67, - 84, 85, 65, 84, 73, 79, 78, 128, 80, 85, 78, 67, 84, 85, 65, 84, 73, 79, - 206, 80, 85, 77, 80, 128, 80, 85, 77, 128, 80, 85, 70, 70, 69, 68, 128, - 80, 85, 69, 128, 80, 85, 67, 75, 128, 80, 85, 66, 76, 73, 195, 80, 85, - 194, 80, 85, 65, 81, 128, 80, 85, 65, 69, 128, 80, 85, 65, 67, 72, 85, - 197, 80, 85, 50, 128, 80, 85, 49, 128, 80, 85, 128, 80, 84, 72, 65, 72, - 193, 80, 84, 69, 128, 80, 83, 73, 76, 201, 80, 83, 73, 70, 73, 83, 84, - 79, 83, 89, 78, 65, 71, 77, 65, 128, 80, 83, 73, 70, 73, 83, 84, 79, 80, - 65, 82, 65, 75, 65, 76, 69, 83, 77, 65, 128, 80, 83, 73, 70, 73, 83, 84, - 79, 206, 80, 83, 73, 70, 73, 83, 84, 79, 76, 89, 71, 73, 83, 77, 65, 128, - 80, 83, 73, 128, 80, 83, 65, 76, 84, 69, 210, 80, 83, 128, 80, 82, 79, - 86, 69, 128, 80, 82, 79, 84, 79, 86, 65, 82, 89, 211, 80, 82, 79, 84, 79, - 211, 80, 82, 79, 84, 69, 67, 84, 69, 196, 80, 82, 79, 83, 84, 65, 89, 65, - 128, 80, 82, 79, 83, 71, 69, 71, 82, 65, 77, 77, 69, 78, 73, 128, 80, 82, - 79, 83, 69, 82, 80, 73, 78, 65, 128, 80, 82, 79, 80, 79, 82, 84, 73, 79, - 78, 65, 204, 80, 82, 79, 80, 79, 82, 84, 73, 79, 78, 128, 80, 82, 79, 80, - 69, 82, 84, 217, 80, 82, 79, 80, 69, 76, 76, 69, 210, 80, 82, 79, 79, 70, - 128, 80, 82, 79, 76, 79, 78, 71, 69, 196, 80, 82, 79, 76, 65, 84, 73, 79, - 78, 197, 80, 82, 79, 74, 69, 67, 84, 79, 82, 128, 80, 82, 79, 74, 69, 67, - 84, 73, 86, 69, 128, 80, 82, 79, 74, 69, 67, 84, 73, 79, 78, 128, 80, 82, - 79, 72, 73, 66, 73, 84, 69, 196, 80, 82, 79, 71, 82, 69, 83, 83, 128, 80, - 82, 79, 71, 82, 65, 205, 80, 82, 79, 70, 79, 85, 78, 68, 128, 80, 82, 79, - 68, 85, 67, 84, 128, 80, 82, 79, 68, 85, 67, 212, 80, 82, 79, 66, 73, 78, - 199, 80, 82, 73, 90, 78, 65, 203, 80, 82, 73, 86, 65, 84, 69, 128, 80, - 82, 73, 86, 65, 84, 197, 80, 82, 73, 86, 65, 67, 217, 80, 82, 73, 83, 72, - 84, 72, 65, 77, 65, 84, 82, 193, 80, 82, 73, 78, 84, 83, 128, 80, 82, 73, - 78, 84, 69, 82, 128, 80, 82, 73, 78, 84, 69, 210, 80, 82, 73, 78, 84, - 128, 80, 82, 73, 78, 212, 80, 82, 73, 78, 67, 69, 83, 83, 128, 80, 82, - 73, 78, 67, 69, 128, 80, 82, 73, 77, 69, 128, 80, 82, 73, 77, 197, 80, - 82, 69, 86, 73, 79, 85, 211, 80, 82, 69, 84, 90, 69, 76, 128, 80, 82, 69, - 83, 83, 69, 196, 80, 82, 69, 83, 69, 84, 128, 80, 82, 69, 83, 69, 78, 84, - 65, 84, 73, 79, 206, 80, 82, 69, 83, 67, 82, 73, 80, 84, 73, 79, 206, 80, - 82, 69, 80, 79, 78, 68, 69, 82, 65, 78, 67, 69, 128, 80, 82, 69, 78, 75, - 72, 65, 128, 80, 82, 69, 71, 78, 65, 78, 212, 80, 82, 69, 70, 73, 88, 69, - 196, 80, 82, 69, 70, 65, 67, 197, 80, 82, 69, 67, 73, 80, 73, 84, 65, 84, - 69, 128, 80, 82, 69, 67, 69, 68, 73, 78, 199, 80, 82, 69, 67, 69, 68, 69, - 83, 128, 80, 82, 69, 67, 69, 68, 69, 211, 80, 82, 69, 67, 69, 68, 69, - 196, 80, 82, 69, 67, 69, 68, 69, 128, 80, 82, 69, 67, 69, 68, 197, 80, - 82, 65, 89, 69, 210, 80, 82, 65, 77, 45, 80, 73, 73, 128, 80, 82, 65, 77, - 45, 80, 73, 201, 80, 82, 65, 77, 45, 77, 85, 79, 89, 128, 80, 82, 65, 77, - 45, 77, 85, 79, 217, 80, 82, 65, 77, 45, 66, 85, 79, 78, 128, 80, 82, 65, - 77, 45, 66, 85, 79, 206, 80, 82, 65, 77, 45, 66, 69, 73, 128, 80, 82, 65, - 77, 45, 66, 69, 201, 80, 82, 65, 77, 128, 80, 82, 65, 205, 80, 82, 128, - 80, 80, 86, 128, 80, 80, 77, 128, 80, 80, 65, 128, 80, 79, 89, 128, 80, - 79, 88, 128, 80, 79, 87, 69, 82, 211, 80, 79, 87, 69, 82, 128, 80, 79, - 87, 69, 210, 80, 79, 87, 68, 69, 82, 69, 196, 80, 79, 87, 68, 69, 82, - 128, 80, 79, 86, 89, 83, 72, 69, 128, 80, 79, 86, 89, 83, 72, 197, 80, - 79, 86, 79, 68, 78, 89, 128, 80, 79, 85, 82, 73, 78, 199, 80, 79, 85, 78, - 196, 80, 79, 85, 76, 84, 82, 217, 80, 79, 85, 67, 72, 128, 80, 79, 84, - 84, 69, 196, 80, 79, 84, 65, 84, 79, 128, 80, 79, 84, 65, 66, 76, 197, - 80, 79, 212, 80, 79, 83, 84, 80, 79, 83, 73, 84, 73, 79, 206, 80, 79, 83, - 84, 66, 79, 88, 128, 80, 79, 83, 84, 65, 204, 80, 79, 83, 84, 128, 80, - 79, 83, 212, 80, 79, 83, 83, 69, 83, 83, 73, 79, 78, 128, 80, 79, 83, 83, - 69, 83, 83, 73, 79, 206, 80, 79, 83, 73, 84, 73, 79, 78, 83, 128, 80, 79, - 83, 73, 84, 73, 79, 78, 128, 80, 79, 83, 69, 73, 68, 79, 78, 128, 80, 79, - 82, 84, 65, 66, 76, 197, 80, 79, 82, 82, 69, 67, 84, 85, 83, 128, 80, 79, - 82, 82, 69, 67, 84, 85, 211, 80, 79, 80, 80, 73, 78, 199, 80, 79, 80, 80, - 69, 82, 128, 80, 79, 80, 67, 79, 82, 78, 128, 80, 79, 80, 128, 80, 79, - 208, 80, 79, 79, 68, 76, 69, 128, 80, 79, 79, 128, 80, 79, 78, 68, 79, - 128, 80, 79, 206, 80, 79, 77, 77, 69, 69, 128, 80, 79, 77, 77, 69, 197, - 80, 79, 76, 85, 80, 79, 86, 79, 68, 78, 65, 89, 65, 128, 80, 79, 76, 79, - 128, 80, 79, 76, 78, 65, 89, 65, 128, 80, 79, 76, 76, 85, 128, 80, 79, - 76, 75, 85, 76, 73, 90, 77, 89, 128, 80, 79, 76, 73, 83, 72, 128, 80, 79, - 76, 73, 83, 200, 80, 79, 76, 73, 67, 197, 80, 79, 76, 201, 80, 79, 76, - 69, 128, 80, 79, 76, 197, 80, 79, 75, 82, 89, 84, 73, 69, 128, 80, 79, - 75, 79, 74, 73, 128, 80, 79, 73, 78, 84, 211, 80, 79, 73, 78, 84, 79, - 128, 80, 79, 73, 78, 84, 69, 82, 128, 80, 79, 73, 78, 84, 69, 196, 80, - 79, 73, 78, 84, 128, 80, 79, 73, 78, 212, 80, 79, 69, 84, 82, 217, 80, - 79, 69, 84, 73, 195, 80, 79, 68, 86, 69, 82, 84, 75, 65, 128, 80, 79, 68, - 67, 72, 65, 83, 72, 73, 69, 77, 128, 80, 79, 68, 67, 72, 65, 83, 72, 73, - 69, 128, 80, 79, 68, 67, 72, 65, 83, 72, 73, 197, 80, 79, 68, 65, 84, 85, - 83, 128, 80, 79, 67, 75, 69, 212, 80, 79, 65, 128, 80, 207, 80, 78, 69, - 85, 77, 65, 84, 65, 128, 80, 76, 85, 84, 207, 80, 76, 85, 84, 65, 128, - 80, 76, 85, 83, 45, 77, 73, 78, 85, 211, 80, 76, 85, 83, 128, 80, 76, 85, - 82, 65, 76, 128, 80, 76, 85, 78, 71, 69, 82, 128, 80, 76, 85, 77, 69, - 196, 80, 76, 85, 77, 128, 80, 76, 85, 75, 128, 80, 76, 85, 71, 128, 80, - 76, 85, 128, 80, 76, 79, 87, 128, 80, 76, 79, 80, 72, 85, 128, 80, 76, - 72, 65, 85, 128, 80, 76, 69, 84, 72, 82, 79, 78, 128, 80, 76, 69, 65, 68, - 73, 78, 199, 80, 76, 68, 128, 80, 76, 65, 89, 73, 78, 199, 80, 76, 65, - 89, 71, 82, 79, 85, 78, 196, 80, 76, 65, 84, 69, 128, 80, 76, 65, 83, 84, - 73, 67, 83, 128, 80, 76, 65, 78, 84, 128, 80, 76, 65, 78, 69, 84, 128, - 80, 76, 65, 78, 69, 128, 80, 76, 65, 78, 67, 203, 80, 76, 65, 75, 128, - 80, 76, 65, 71, 73, 79, 211, 80, 76, 65, 67, 69, 72, 79, 76, 68, 69, 82, - 128, 80, 76, 65, 67, 69, 72, 79, 76, 68, 69, 210, 80, 76, 65, 67, 197, - 80, 76, 65, 67, 65, 82, 68, 128, 80, 76, 65, 128, 80, 73, 90, 90, 73, 67, - 65, 84, 79, 128, 80, 73, 90, 90, 65, 128, 80, 73, 88, 128, 80, 73, 87, - 82, 128, 80, 73, 84, 67, 72, 70, 79, 82, 75, 128, 80, 73, 84, 67, 72, 70, - 79, 82, 203, 80, 73, 84, 128, 80, 73, 83, 84, 79, 76, 128, 80, 73, 83, - 69, 76, 69, 72, 128, 80, 73, 83, 67, 69, 83, 128, 80, 73, 82, 73, 71, - 128, 80, 73, 82, 73, 199, 80, 73, 82, 73, 69, 69, 78, 128, 80, 73, 82, - 65, 67, 89, 128, 80, 73, 82, 50, 128, 80, 73, 80, 73, 78, 71, 128, 80, - 73, 80, 65, 69, 77, 71, 66, 73, 69, 69, 128, 80, 73, 80, 65, 69, 77, 66, - 65, 128, 80, 73, 80, 128, 80, 73, 78, 87, 72, 69, 69, 204, 80, 73, 78, - 203, 80, 73, 78, 69, 65, 80, 80, 76, 69, 128, 80, 73, 78, 197, 80, 73, - 78, 67, 72, 73, 78, 199, 80, 73, 78, 67, 72, 69, 196, 80, 73, 78, 65, 84, - 65, 128, 80, 73, 78, 65, 82, 66, 79, 82, 65, 83, 128, 80, 73, 76, 76, - 128, 80, 73, 76, 197, 80, 73, 76, 67, 82, 79, 215, 80, 73, 75, 85, 82, - 85, 128, 80, 73, 75, 79, 128, 80, 73, 71, 128, 80, 73, 199, 80, 73, 69, - 88, 128, 80, 73, 69, 85, 80, 45, 84, 72, 73, 69, 85, 84, 72, 128, 80, 73, - 69, 85, 80, 45, 83, 83, 65, 78, 71, 83, 73, 79, 83, 128, 80, 73, 69, 85, - 80, 45, 83, 73, 79, 83, 45, 84, 73, 75, 69, 85, 84, 128, 80, 73, 69, 85, - 80, 45, 83, 73, 79, 83, 45, 84, 72, 73, 69, 85, 84, 72, 128, 80, 73, 69, - 85, 80, 45, 83, 73, 79, 83, 45, 80, 73, 69, 85, 80, 128, 80, 73, 69, 85, - 80, 45, 83, 73, 79, 83, 45, 75, 73, 89, 69, 79, 75, 128, 80, 73, 69, 85, - 80, 45, 83, 73, 79, 83, 45, 67, 73, 69, 85, 67, 128, 80, 73, 69, 85, 80, - 45, 82, 73, 69, 85, 76, 45, 80, 72, 73, 69, 85, 80, 72, 128, 80, 73, 69, - 85, 80, 45, 82, 73, 69, 85, 76, 128, 80, 73, 69, 85, 80, 45, 78, 73, 69, - 85, 78, 128, 80, 73, 69, 85, 80, 45, 77, 73, 69, 85, 77, 128, 80, 73, 69, - 85, 80, 45, 75, 72, 73, 69, 85, 75, 72, 128, 80, 73, 69, 85, 80, 45, 67, - 73, 69, 85, 67, 128, 80, 73, 69, 85, 80, 45, 67, 72, 73, 69, 85, 67, 72, - 128, 80, 73, 69, 85, 208, 80, 73, 69, 84, 128, 80, 73, 69, 80, 128, 80, - 73, 69, 69, 84, 128, 80, 73, 69, 69, 81, 128, 80, 73, 69, 67, 69, 128, - 80, 73, 69, 128, 80, 73, 67, 84, 85, 82, 69, 128, 80, 73, 67, 75, 85, - 208, 80, 73, 67, 75, 69, 84, 128, 80, 73, 67, 75, 128, 80, 73, 65, 83, - 85, 84, 79, 82, 85, 128, 80, 73, 65, 83, 84, 82, 197, 80, 73, 65, 83, 77, - 193, 80, 73, 65, 78, 79, 128, 80, 201, 80, 72, 87, 65, 128, 80, 72, 85, - 84, 72, 65, 79, 128, 80, 72, 85, 210, 80, 72, 85, 78, 71, 128, 80, 72, - 82, 65, 83, 69, 128, 80, 72, 79, 78, 69, 83, 128, 80, 72, 79, 76, 85, 83, - 128, 80, 72, 79, 69, 78, 73, 67, 73, 65, 206, 80, 72, 79, 65, 128, 80, - 72, 79, 128, 80, 72, 207, 80, 72, 78, 65, 69, 203, 80, 72, 73, 78, 84, - 72, 85, 128, 80, 72, 73, 76, 79, 83, 79, 80, 72, 69, 82, 211, 80, 72, 73, - 76, 73, 80, 80, 73, 78, 197, 80, 72, 73, 69, 85, 80, 72, 45, 84, 72, 73, - 69, 85, 84, 72, 128, 80, 72, 73, 69, 85, 80, 72, 45, 83, 73, 79, 83, 128, - 80, 72, 73, 69, 85, 80, 72, 45, 80, 73, 69, 85, 80, 128, 80, 72, 73, 69, - 85, 80, 72, 45, 72, 73, 69, 85, 72, 128, 80, 72, 73, 69, 85, 80, 200, 80, - 72, 73, 128, 80, 72, 201, 80, 72, 69, 69, 128, 80, 72, 69, 128, 80, 72, - 65, 83, 69, 45, 198, 80, 72, 65, 83, 69, 45, 195, 80, 72, 65, 83, 69, 45, - 194, 80, 72, 65, 83, 69, 45, 193, 80, 72, 65, 82, 89, 78, 71, 69, 65, - 204, 80, 72, 65, 82, 128, 80, 72, 65, 78, 128, 80, 72, 65, 77, 128, 80, - 72, 65, 73, 83, 84, 79, 211, 80, 72, 65, 71, 83, 45, 80, 193, 80, 72, 65, - 66, 128, 80, 72, 65, 65, 82, 75, 65, 65, 128, 80, 72, 65, 65, 128, 80, - 71, 128, 80, 70, 128, 80, 69, 85, 88, 128, 80, 69, 85, 84, 65, 69, 128, - 80, 69, 85, 84, 128, 80, 69, 84, 82, 201, 80, 69, 84, 65, 83, 84, 79, 75, - 79, 85, 70, 73, 83, 77, 65, 128, 80, 69, 84, 65, 83, 84, 73, 128, 80, 69, - 84, 65, 83, 77, 65, 128, 80, 69, 84, 65, 76, 76, 69, 196, 80, 69, 83, 79, - 128, 80, 69, 83, 207, 80, 69, 83, 72, 50, 128, 80, 69, 83, 72, 178, 80, - 69, 83, 69, 84, 193, 80, 69, 211, 80, 69, 82, 84, 72, 207, 80, 69, 82, - 83, 80, 69, 67, 84, 73, 86, 69, 128, 80, 69, 82, 83, 79, 78, 65, 204, 80, - 69, 82, 83, 79, 78, 128, 80, 69, 82, 83, 79, 206, 80, 69, 82, 83, 73, 65, - 206, 80, 69, 82, 83, 69, 86, 69, 82, 73, 78, 199, 80, 69, 82, 80, 69, 78, - 68, 73, 67, 85, 76, 65, 82, 128, 80, 69, 82, 80, 69, 78, 68, 73, 67, 85, - 76, 65, 210, 80, 69, 82, 78, 73, 206, 80, 69, 82, 77, 73, 84, 84, 69, - 196, 80, 69, 82, 77, 73, 195, 80, 69, 82, 77, 65, 78, 69, 78, 212, 80, - 69, 82, 73, 83, 80, 79, 77, 69, 78, 73, 128, 80, 69, 82, 73, 83, 80, 79, - 77, 69, 78, 201, 80, 69, 82, 70, 79, 82, 77, 73, 78, 199, 80, 69, 82, 70, - 69, 67, 84, 85, 205, 80, 69, 82, 70, 69, 67, 84, 65, 128, 80, 69, 82, 70, - 69, 67, 84, 193, 80, 69, 82, 69, 86, 79, 68, 75, 65, 128, 80, 69, 82, 69, - 86, 79, 68, 75, 193, 80, 69, 82, 67, 85, 83, 83, 73, 86, 69, 128, 80, 69, - 82, 67, 69, 78, 212, 80, 69, 80, 80, 69, 82, 128, 80, 69, 80, 69, 84, - 128, 80, 69, 80, 69, 212, 80, 69, 79, 82, 84, 200, 80, 69, 79, 80, 76, - 69, 128, 80, 69, 79, 80, 76, 197, 80, 69, 78, 84, 65, 84, 72, 76, 79, 78, - 128, 80, 69, 78, 84, 65, 83, 69, 77, 69, 128, 80, 69, 78, 84, 65, 71, 82, - 65, 77, 128, 80, 69, 78, 84, 65, 71, 79, 78, 128, 80, 69, 78, 83, 85, - 128, 80, 69, 78, 83, 73, 86, 197, 80, 69, 78, 78, 217, 80, 69, 78, 78, - 65, 78, 84, 128, 80, 69, 78, 73, 72, 73, 128, 80, 69, 78, 71, 85, 73, 78, - 128, 80, 69, 78, 71, 75, 65, 76, 128, 80, 69, 78, 69, 84, 82, 65, 84, 73, - 79, 78, 128, 80, 69, 78, 67, 73, 76, 128, 80, 69, 206, 80, 69, 76, 65, - 83, 84, 79, 78, 128, 80, 69, 76, 65, 83, 84, 79, 206, 80, 69, 73, 84, 72, - 128, 80, 69, 72, 69, 72, 128, 80, 69, 72, 69, 200, 80, 69, 72, 128, 80, - 69, 200, 80, 69, 69, 90, 73, 128, 80, 69, 69, 83, 72, 73, 128, 80, 69, - 69, 80, 128, 80, 69, 69, 77, 128, 80, 69, 69, 75, 73, 78, 199, 80, 69, - 69, 73, 128, 80, 69, 69, 128, 80, 69, 68, 69, 83, 84, 82, 73, 65, 78, 83, - 128, 80, 69, 68, 69, 83, 84, 82, 73, 65, 78, 128, 80, 69, 68, 69, 83, 84, - 65, 76, 128, 80, 69, 68, 69, 83, 84, 65, 204, 80, 69, 68, 65, 204, 80, - 69, 65, 78, 85, 84, 83, 128, 80, 69, 65, 75, 211, 80, 69, 65, 67, 79, 67, - 75, 128, 80, 69, 65, 67, 72, 128, 80, 69, 65, 67, 69, 128, 80, 69, 65, - 67, 197, 80, 69, 193, 80, 68, 73, 128, 80, 68, 70, 128, 80, 68, 128, 80, - 67, 128, 80, 65, 90, 69, 82, 128, 80, 65, 89, 69, 82, 79, 75, 128, 80, - 65, 89, 65, 78, 78, 65, 128, 80, 65, 89, 128, 80, 65, 88, 128, 80, 65, - 87, 78, 128, 80, 65, 87, 206, 80, 65, 215, 80, 65, 86, 73, 89, 65, 78, - 73, 128, 80, 65, 85, 83, 197, 80, 65, 85, 75, 128, 80, 65, 85, 128, 80, - 65, 213, 80, 65, 84, 84, 217, 80, 65, 84, 84, 69, 82, 78, 128, 80, 65, - 84, 72, 65, 77, 65, 83, 65, 84, 128, 80, 65, 84, 72, 65, 75, 75, 85, 128, - 80, 65, 84, 200, 80, 65, 84, 65, 75, 128, 80, 65, 84, 65, 72, 128, 80, - 65, 84, 128, 80, 65, 83, 85, 81, 128, 80, 65, 83, 83, 80, 79, 82, 212, - 80, 65, 83, 83, 73, 86, 69, 45, 80, 85, 76, 76, 45, 85, 80, 45, 79, 85, - 84, 80, 85, 212, 80, 65, 83, 83, 73, 86, 69, 45, 80, 85, 76, 76, 45, 68, - 79, 87, 78, 45, 79, 85, 84, 80, 85, 212, 80, 65, 83, 83, 73, 77, 66, 65, - 78, 71, 128, 80, 65, 83, 83, 69, 78, 71, 69, 210, 80, 65, 83, 83, 69, - 196, 80, 65, 83, 72, 84, 65, 128, 80, 65, 83, 72, 65, 69, 128, 80, 65, - 83, 69, 81, 128, 80, 65, 83, 65, 78, 71, 65, 206, 80, 65, 82, 85, 77, - 128, 80, 65, 82, 84, 217, 80, 65, 82, 84, 78, 69, 82, 83, 72, 73, 208, - 80, 65, 82, 84, 73, 65, 76, 76, 89, 45, 82, 69, 67, 89, 67, 76, 69, 196, - 80, 65, 82, 84, 73, 65, 204, 80, 65, 82, 84, 72, 73, 65, 206, 80, 65, 82, - 212, 80, 65, 82, 82, 79, 84, 128, 80, 65, 82, 75, 128, 80, 65, 82, 73, - 67, 72, 79, 78, 128, 80, 65, 82, 69, 83, 84, 73, 71, 77, 69, 78, 79, 206, - 80, 65, 82, 69, 82, 69, 78, 128, 80, 65, 82, 69, 78, 84, 72, 69, 83, 73, - 83, 128, 80, 65, 82, 69, 78, 84, 72, 69, 83, 73, 211, 80, 65, 82, 69, 78, - 84, 72, 69, 83, 69, 211, 80, 65, 82, 65, 80, 72, 82, 65, 83, 197, 80, 65, - 82, 65, 76, 76, 69, 76, 79, 71, 82, 65, 77, 128, 80, 65, 82, 65, 76, 76, - 69, 76, 128, 80, 65, 82, 65, 76, 76, 69, 204, 80, 65, 82, 65, 75, 76, 73, - 84, 73, 75, 73, 128, 80, 65, 82, 65, 75, 76, 73, 84, 73, 75, 201, 80, 65, - 82, 65, 75, 76, 73, 84, 128, 80, 65, 82, 65, 75, 65, 76, 69, 83, 77, 193, - 80, 65, 82, 65, 71, 82, 65, 80, 72, 85, 211, 80, 65, 82, 65, 71, 82, 65, - 80, 72, 79, 83, 128, 80, 65, 82, 65, 71, 82, 65, 80, 72, 128, 80, 65, 82, - 65, 71, 82, 65, 80, 200, 80, 65, 82, 65, 67, 72, 85, 84, 69, 128, 80, 65, - 82, 65, 128, 80, 65, 82, 128, 80, 65, 80, 89, 82, 85, 83, 128, 80, 65, - 80, 69, 82, 67, 76, 73, 80, 83, 128, 80, 65, 80, 69, 82, 67, 76, 73, 80, - 128, 80, 65, 80, 69, 82, 128, 80, 65, 80, 69, 210, 80, 65, 80, 128, 80, - 65, 208, 80, 65, 207, 80, 65, 78, 89, 85, 75, 85, 128, 80, 65, 78, 89, - 73, 75, 85, 128, 80, 65, 78, 89, 69, 67, 69, 75, 128, 80, 65, 78, 89, 65, - 78, 71, 71, 65, 128, 80, 65, 78, 89, 65, 75, 82, 65, 128, 80, 65, 78, 84, - 73, 128, 80, 65, 78, 84, 201, 80, 65, 78, 83, 73, 79, 83, 45, 80, 73, 69, - 85, 80, 128, 80, 65, 78, 83, 73, 79, 83, 45, 75, 65, 80, 89, 69, 79, 85, - 78, 80, 73, 69, 85, 80, 128, 80, 65, 78, 79, 78, 71, 79, 78, 65, 78, 128, - 80, 65, 78, 79, 76, 79, 78, 71, 128, 80, 65, 78, 71, 87, 73, 83, 65, 68, - 128, 80, 65, 78, 71, 82, 65, 78, 71, 75, 69, 80, 128, 80, 65, 78, 71, 79, - 76, 65, 84, 128, 80, 65, 78, 71, 76, 79, 78, 71, 128, 80, 65, 78, 71, 76, - 65, 89, 65, 82, 128, 80, 65, 78, 71, 75, 79, 78, 128, 80, 65, 78, 71, 75, - 65, 84, 128, 80, 65, 78, 71, 72, 85, 76, 85, 128, 80, 65, 78, 71, 128, - 80, 65, 78, 69, 85, 76, 69, 85, 78, 71, 128, 80, 65, 78, 68, 193, 80, 65, - 78, 67, 65, 75, 69, 83, 128, 80, 65, 78, 65, 77, 128, 80, 65, 78, 65, 69, - 76, 65, 69, 78, 71, 128, 80, 65, 78, 128, 80, 65, 206, 80, 65, 77, 85, - 78, 71, 75, 65, 72, 128, 80, 65, 77, 85, 68, 80, 79, 68, 128, 80, 65, 77, - 83, 72, 65, 69, 128, 80, 65, 77, 80, 72, 89, 76, 73, 65, 206, 80, 65, 77, - 73, 78, 71, 75, 65, 76, 128, 80, 65, 77, 69, 80, 69, 84, 128, 80, 65, 77, - 69, 78, 69, 78, 71, 128, 80, 65, 77, 65, 68, 65, 128, 80, 65, 77, 65, 68, - 193, 80, 65, 77, 65, 65, 69, 72, 128, 80, 65, 76, 85, 84, 65, 128, 80, - 65, 76, 79, 67, 72, 75, 65, 128, 80, 65, 76, 77, 89, 82, 69, 78, 197, 80, - 65, 76, 77, 211, 80, 65, 76, 77, 128, 80, 65, 76, 205, 80, 65, 76, 76, - 65, 87, 65, 128, 80, 65, 76, 76, 65, 83, 128, 80, 65, 76, 75, 65, 128, - 80, 65, 76, 201, 80, 65, 76, 69, 84, 84, 69, 128, 80, 65, 76, 65, 85, 78, - 199, 80, 65, 76, 65, 84, 65, 76, 73, 90, 69, 196, 80, 65, 76, 65, 84, 65, - 76, 73, 90, 65, 84, 73, 79, 78, 128, 80, 65, 76, 65, 84, 65, 204, 80, 65, - 75, 80, 65, 203, 80, 65, 73, 89, 65, 78, 78, 79, 73, 128, 80, 65, 73, 82, - 84, 72, 82, 65, 128, 80, 65, 73, 82, 69, 196, 80, 65, 73, 78, 84, 66, 82, - 85, 83, 72, 128, 80, 65, 73, 128, 80, 65, 72, 76, 65, 86, 201, 80, 65, - 72, 128, 80, 65, 71, 79, 68, 65, 128, 80, 65, 71, 69, 83, 128, 80, 65, - 71, 69, 82, 128, 80, 65, 71, 197, 80, 65, 68, 77, 193, 80, 65, 68, 68, - 76, 197, 80, 65, 68, 68, 73, 78, 199, 80, 65, 68, 193, 80, 65, 68, 128, - 80, 65, 67, 75, 73, 78, 71, 128, 80, 65, 67, 75, 65, 71, 69, 128, 80, 65, - 65, 84, 85, 128, 80, 65, 65, 83, 69, 78, 84, 79, 128, 80, 65, 65, 82, 65, - 77, 128, 80, 65, 65, 82, 65, 69, 128, 80, 65, 65, 77, 128, 80, 65, 65, - 73, 128, 80, 65, 65, 45, 80, 73, 76, 76, 65, 128, 80, 65, 65, 128, 80, - 50, 128, 80, 48, 49, 49, 128, 80, 48, 49, 48, 128, 80, 48, 48, 57, 128, - 80, 48, 48, 56, 128, 80, 48, 48, 55, 128, 80, 48, 48, 54, 128, 80, 48, - 48, 53, 128, 80, 48, 48, 52, 128, 80, 48, 48, 51, 65, 128, 80, 48, 48, - 51, 128, 80, 48, 48, 50, 128, 80, 48, 48, 49, 65, 128, 80, 48, 48, 49, - 128, 79, 90, 128, 79, 89, 83, 84, 69, 82, 128, 79, 89, 82, 65, 78, 73, - 83, 77, 193, 79, 89, 65, 78, 78, 65, 128, 79, 88, 73, 65, 128, 79, 88, - 73, 193, 79, 88, 69, 73, 65, 201, 79, 88, 69, 73, 193, 79, 87, 76, 128, - 79, 86, 69, 82, 83, 84, 82, 85, 67, 203, 79, 86, 69, 82, 82, 73, 68, 69, - 128, 79, 86, 69, 82, 76, 79, 78, 199, 79, 86, 69, 82, 76, 73, 78, 69, - 128, 79, 86, 69, 82, 76, 65, 89, 128, 79, 86, 69, 82, 76, 65, 217, 79, - 86, 69, 82, 76, 65, 80, 80, 73, 78, 199, 79, 86, 69, 82, 76, 65, 80, 128, - 79, 86, 69, 82, 76, 65, 73, 68, 128, 79, 86, 69, 82, 76, 65, 73, 196, 79, - 86, 69, 82, 72, 69, 65, 84, 69, 196, 79, 86, 69, 82, 66, 65, 82, 128, 79, - 86, 65, 76, 128, 79, 86, 65, 204, 79, 85, 84, 76, 73, 78, 69, 196, 79, - 85, 84, 76, 73, 78, 69, 128, 79, 85, 84, 69, 210, 79, 85, 84, 66, 79, - 216, 79, 85, 78, 75, 73, 193, 79, 85, 78, 67, 69, 128, 79, 85, 78, 67, - 197, 79, 84, 85, 128, 79, 84, 84, 79, 77, 65, 206, 79, 84, 84, 69, 82, - 128, 79, 84, 84, 65, 86, 193, 79, 84, 84, 128, 79, 84, 83, 69, 67, 72, - 75, 65, 128, 79, 84, 72, 69, 82, 211, 79, 84, 72, 69, 210, 79, 84, 72, - 65, 76, 65, 206, 79, 84, 72, 65, 76, 128, 79, 83, 79, 75, 65, 128, 79, - 83, 79, 75, 193, 79, 83, 77, 65, 78, 89, 193, 79, 83, 67, 128, 79, 83, - 65, 71, 197, 79, 82, 84, 72, 79, 71, 79, 78, 65, 204, 79, 82, 84, 72, 79, - 68, 79, 216, 79, 82, 78, 65, 84, 197, 79, 82, 78, 65, 77, 69, 78, 84, 83, - 128, 79, 82, 78, 65, 77, 69, 78, 84, 128, 79, 82, 78, 65, 77, 69, 78, - 212, 79, 82, 75, 72, 79, 206, 79, 82, 73, 89, 193, 79, 82, 73, 71, 73, - 78, 65, 204, 79, 82, 73, 71, 73, 78, 128, 79, 82, 69, 45, 50, 128, 79, - 82, 68, 73, 78, 65, 204, 79, 82, 68, 69, 210, 79, 82, 67, 85, 83, 128, - 79, 82, 67, 72, 73, 68, 128, 79, 82, 65, 78, 71, 85, 84, 65, 78, 128, 79, - 82, 65, 78, 71, 197, 79, 80, 84, 73, 79, 206, 79, 80, 84, 73, 67, 65, - 204, 79, 80, 80, 82, 69, 83, 83, 73, 79, 78, 128, 79, 80, 80, 79, 83, 73, - 84, 73, 79, 78, 128, 79, 80, 80, 79, 83, 73, 78, 199, 79, 80, 80, 79, 83, - 69, 128, 79, 80, 72, 73, 85, 67, 72, 85, 83, 128, 79, 80, 69, 82, 65, 84, - 79, 82, 128, 79, 80, 69, 82, 65, 84, 79, 210, 79, 80, 69, 82, 65, 84, 73, - 78, 199, 79, 80, 69, 78, 73, 78, 199, 79, 80, 69, 78, 45, 80, 128, 79, - 80, 69, 78, 45, 79, 85, 84, 76, 73, 78, 69, 196, 79, 80, 69, 78, 45, 79, - 128, 79, 80, 69, 78, 45, 207, 79, 80, 69, 78, 45, 72, 69, 65, 68, 69, - 196, 79, 80, 69, 78, 45, 67, 73, 82, 67, 85, 73, 84, 45, 79, 85, 84, 80, - 85, 212, 79, 80, 69, 78, 128, 79, 80, 69, 206, 79, 79, 90, 69, 128, 79, - 79, 89, 65, 78, 78, 65, 128, 79, 79, 85, 128, 79, 79, 77, 85, 128, 79, - 79, 72, 128, 79, 79, 69, 128, 79, 79, 66, 79, 79, 70, 73, 76, 73, 128, - 79, 78, 85, 128, 79, 78, 83, 85, 128, 79, 78, 78, 128, 79, 78, 75, 65, - 82, 128, 79, 78, 73, 79, 78, 128, 79, 78, 69, 83, 69, 76, 70, 128, 79, - 78, 69, 45, 87, 65, 217, 79, 78, 69, 45, 84, 72, 73, 82, 84, 89, 128, 79, - 78, 69, 45, 80, 73, 69, 67, 197, 79, 78, 69, 45, 76, 73, 78, 197, 79, 78, - 69, 45, 72, 85, 78, 68, 82, 69, 68, 45, 65, 78, 68, 45, 83, 73, 88, 84, - 73, 69, 84, 72, 128, 79, 78, 67, 79, 77, 73, 78, 199, 79, 78, 65, 80, - 128, 79, 78, 45, 79, 70, 198, 79, 77, 73, 83, 83, 73, 79, 206, 79, 77, - 73, 67, 82, 79, 78, 128, 79, 77, 73, 67, 82, 79, 206, 79, 77, 69, 84, - 128, 79, 77, 69, 71, 65, 128, 79, 77, 69, 71, 193, 79, 77, 65, 76, 79, - 78, 128, 79, 76, 73, 86, 69, 128, 79, 76, 73, 71, 79, 206, 79, 76, 68, - 128, 79, 75, 84, 207, 79, 75, 65, 82, 65, 128, 79, 75, 65, 82, 193, 79, - 74, 79, 68, 128, 79, 74, 73, 66, 87, 65, 217, 79, 74, 69, 79, 78, 128, - 79, 73, 78, 128, 79, 73, 76, 128, 79, 73, 204, 79, 72, 77, 128, 79, 72, - 205, 79, 71, 82, 69, 128, 79, 71, 79, 78, 69, 75, 128, 79, 71, 79, 78, - 69, 203, 79, 71, 72, 65, 205, 79, 70, 70, 73, 67, 69, 82, 128, 79, 70, - 70, 73, 67, 69, 128, 79, 70, 70, 73, 67, 197, 79, 70, 70, 128, 79, 69, - 89, 128, 79, 69, 82, 128, 79, 69, 75, 128, 79, 69, 69, 128, 79, 68, 69, - 78, 128, 79, 68, 68, 128, 79, 68, 196, 79, 67, 84, 79, 80, 85, 83, 128, - 79, 67, 84, 79, 66, 69, 82, 128, 79, 67, 84, 69, 212, 79, 67, 84, 65, 71, - 79, 78, 65, 204, 79, 67, 84, 65, 71, 79, 78, 128, 79, 67, 210, 79, 67, - 76, 79, 67, 75, 128, 79, 67, 72, 75, 79, 77, 128, 79, 67, 67, 85, 76, 84, - 65, 84, 73, 79, 78, 128, 79, 67, 67, 76, 85, 83, 73, 79, 78, 128, 79, 66, - 83, 84, 82, 85, 67, 84, 73, 79, 78, 128, 79, 66, 83, 69, 82, 86, 69, 210, - 79, 66, 79, 76, 211, 79, 66, 79, 204, 79, 66, 79, 70, 73, 76, 73, 128, - 79, 66, 76, 73, 81, 85, 197, 79, 66, 76, 65, 75, 79, 128, 79, 66, 76, 65, - 67, 72, 75, 79, 128, 79, 66, 74, 69, 67, 212, 79, 66, 69, 76, 85, 83, - 128, 79, 66, 69, 76, 79, 83, 128, 79, 66, 128, 79, 65, 89, 128, 79, 65, - 75, 128, 79, 65, 66, 79, 65, 70, 73, 76, 73, 128, 79, 193, 79, 48, 53, - 49, 128, 79, 48, 53, 48, 66, 128, 79, 48, 53, 48, 65, 128, 79, 48, 53, - 48, 128, 79, 48, 52, 57, 128, 79, 48, 52, 56, 128, 79, 48, 52, 55, 128, - 79, 48, 52, 54, 128, 79, 48, 52, 53, 128, 79, 48, 52, 52, 128, 79, 48, - 52, 51, 128, 79, 48, 52, 50, 128, 79, 48, 52, 49, 128, 79, 48, 52, 48, - 128, 79, 48, 51, 57, 128, 79, 48, 51, 56, 128, 79, 48, 51, 55, 128, 79, - 48, 51, 54, 68, 128, 79, 48, 51, 54, 67, 128, 79, 48, 51, 54, 66, 128, - 79, 48, 51, 54, 65, 128, 79, 48, 51, 54, 128, 79, 48, 51, 53, 128, 79, - 48, 51, 52, 128, 79, 48, 51, 51, 65, 128, 79, 48, 51, 51, 128, 79, 48, - 51, 50, 128, 79, 48, 51, 49, 128, 79, 48, 51, 48, 65, 128, 79, 48, 51, - 48, 128, 79, 48, 50, 57, 65, 128, 79, 48, 50, 57, 128, 79, 48, 50, 56, - 128, 79, 48, 50, 55, 128, 79, 48, 50, 54, 128, 79, 48, 50, 53, 65, 128, - 79, 48, 50, 53, 128, 79, 48, 50, 52, 65, 128, 79, 48, 50, 52, 128, 79, - 48, 50, 51, 128, 79, 48, 50, 50, 128, 79, 48, 50, 49, 128, 79, 48, 50, - 48, 65, 128, 79, 48, 50, 48, 128, 79, 48, 49, 57, 65, 128, 79, 48, 49, - 57, 128, 79, 48, 49, 56, 128, 79, 48, 49, 55, 128, 79, 48, 49, 54, 128, - 79, 48, 49, 53, 128, 79, 48, 49, 52, 128, 79, 48, 49, 51, 128, 79, 48, - 49, 50, 128, 79, 48, 49, 49, 128, 79, 48, 49, 48, 67, 128, 79, 48, 49, - 48, 66, 128, 79, 48, 49, 48, 65, 128, 79, 48, 49, 48, 128, 79, 48, 48, - 57, 128, 79, 48, 48, 56, 128, 79, 48, 48, 55, 128, 79, 48, 48, 54, 70, - 128, 79, 48, 48, 54, 69, 128, 79, 48, 48, 54, 68, 128, 79, 48, 48, 54, - 67, 128, 79, 48, 48, 54, 66, 128, 79, 48, 48, 54, 65, 128, 79, 48, 48, - 54, 128, 79, 48, 48, 53, 65, 128, 79, 48, 48, 53, 128, 79, 48, 48, 52, - 128, 79, 48, 48, 51, 128, 79, 48, 48, 50, 128, 79, 48, 48, 49, 65, 128, - 79, 48, 48, 49, 128, 79, 45, 89, 69, 128, 79, 45, 79, 45, 73, 128, 79, - 45, 69, 128, 78, 90, 89, 88, 128, 78, 90, 89, 84, 128, 78, 90, 89, 82, - 88, 128, 78, 90, 89, 82, 128, 78, 90, 89, 80, 128, 78, 90, 89, 128, 78, - 90, 85, 88, 128, 78, 90, 85, 82, 88, 128, 78, 90, 85, 82, 128, 78, 90, - 85, 81, 128, 78, 90, 85, 80, 128, 78, 90, 85, 79, 88, 128, 78, 90, 85, - 79, 128, 78, 90, 85, 206, 78, 90, 85, 128, 78, 90, 79, 88, 128, 78, 90, - 79, 80, 128, 78, 90, 73, 88, 128, 78, 90, 73, 84, 128, 78, 90, 73, 80, - 128, 78, 90, 73, 69, 88, 128, 78, 90, 73, 69, 80, 128, 78, 90, 73, 69, - 128, 78, 90, 73, 128, 78, 90, 69, 88, 128, 78, 90, 69, 85, 77, 128, 78, - 90, 69, 128, 78, 90, 65, 88, 128, 78, 90, 65, 84, 128, 78, 90, 65, 81, - 128, 78, 90, 65, 80, 128, 78, 90, 65, 128, 78, 90, 193, 78, 89, 87, 65, - 128, 78, 89, 85, 88, 128, 78, 89, 85, 85, 128, 78, 89, 85, 84, 128, 78, - 89, 85, 80, 128, 78, 89, 85, 79, 88, 128, 78, 89, 85, 79, 80, 128, 78, - 89, 85, 79, 128, 78, 89, 85, 78, 128, 78, 89, 85, 69, 128, 78, 89, 85, - 128, 78, 89, 79, 88, 128, 78, 89, 79, 84, 128, 78, 89, 79, 80, 128, 78, - 89, 79, 79, 128, 78, 89, 79, 78, 128, 78, 89, 79, 65, 128, 78, 89, 79, - 128, 78, 89, 74, 65, 128, 78, 89, 73, 88, 128, 78, 89, 73, 84, 128, 78, - 89, 73, 212, 78, 89, 73, 211, 78, 89, 73, 210, 78, 89, 73, 80, 128, 78, - 89, 73, 78, 45, 68, 79, 128, 78, 89, 73, 78, 128, 78, 89, 73, 73, 128, - 78, 89, 73, 69, 88, 128, 78, 89, 73, 69, 84, 128, 78, 89, 73, 69, 80, - 128, 78, 89, 73, 69, 128, 78, 89, 73, 65, 75, 69, 78, 199, 78, 89, 73, - 128, 78, 89, 201, 78, 89, 72, 65, 128, 78, 89, 69, 84, 128, 78, 89, 69, - 212, 78, 89, 69, 78, 128, 78, 89, 69, 72, 128, 78, 89, 69, 200, 78, 89, - 69, 69, 128, 78, 89, 69, 128, 78, 89, 196, 78, 89, 67, 65, 128, 78, 89, - 65, 85, 128, 78, 89, 65, 74, 128, 78, 89, 65, 73, 128, 78, 89, 65, 72, - 128, 78, 89, 65, 69, 77, 65, 69, 128, 78, 89, 65, 65, 128, 78, 87, 79, - 79, 128, 78, 87, 79, 128, 78, 87, 73, 73, 128, 78, 87, 73, 128, 78, 87, - 69, 128, 78, 87, 65, 65, 128, 78, 87, 65, 128, 78, 87, 128, 78, 86, 128, - 78, 85, 88, 128, 78, 85, 85, 78, 128, 78, 85, 85, 128, 78, 85, 84, 73, - 76, 76, 85, 128, 78, 85, 84, 128, 78, 85, 212, 78, 85, 82, 88, 128, 78, - 85, 82, 128, 78, 85, 80, 128, 78, 85, 79, 88, 128, 78, 85, 79, 80, 128, - 78, 85, 79, 128, 78, 85, 78, 85, 90, 128, 78, 85, 78, 85, 218, 78, 85, - 78, 71, 128, 78, 85, 78, 65, 86, 85, 212, 78, 85, 78, 65, 86, 73, 203, - 78, 85, 78, 128, 78, 85, 206, 78, 85, 77, 69, 82, 207, 78, 85, 77, 69, - 82, 65, 84, 79, 210, 78, 85, 77, 69, 82, 65, 204, 78, 85, 77, 66, 69, 82, - 83, 128, 78, 85, 77, 66, 69, 82, 128, 78, 85, 77, 128, 78, 85, 76, 76, - 128, 78, 85, 76, 204, 78, 85, 76, 128, 78, 85, 75, 84, 65, 128, 78, 85, - 75, 84, 193, 78, 85, 69, 78, 71, 128, 78, 85, 69, 128, 78, 85, 66, 73, - 65, 206, 78, 85, 65, 69, 128, 78, 85, 49, 49, 128, 78, 85, 49, 177, 78, - 85, 48, 50, 50, 65, 128, 78, 85, 48, 50, 50, 128, 78, 85, 48, 50, 49, - 128, 78, 85, 48, 50, 48, 128, 78, 85, 48, 49, 57, 128, 78, 85, 48, 49, - 56, 65, 128, 78, 85, 48, 49, 56, 128, 78, 85, 48, 49, 55, 128, 78, 85, - 48, 49, 54, 128, 78, 85, 48, 49, 53, 128, 78, 85, 48, 49, 52, 128, 78, - 85, 48, 49, 51, 128, 78, 85, 48, 49, 50, 128, 78, 85, 48, 49, 49, 65, - 128, 78, 85, 48, 49, 49, 128, 78, 85, 48, 49, 48, 65, 128, 78, 85, 48, - 49, 48, 128, 78, 85, 48, 48, 57, 128, 78, 85, 48, 48, 56, 128, 78, 85, - 48, 48, 55, 128, 78, 85, 48, 48, 54, 128, 78, 85, 48, 48, 53, 128, 78, - 85, 48, 48, 52, 128, 78, 85, 48, 48, 51, 128, 78, 85, 48, 48, 50, 128, - 78, 85, 48, 48, 49, 128, 78, 85, 45, 51, 128, 78, 85, 45, 50, 128, 78, - 85, 45, 49, 128, 78, 84, 88, 73, 86, 128, 78, 84, 88, 65, 128, 78, 84, - 85, 85, 128, 78, 84, 85, 77, 128, 78, 84, 85, 74, 128, 78, 84, 213, 78, - 84, 83, 65, 85, 128, 78, 84, 83, 65, 128, 78, 84, 79, 81, 80, 69, 78, - 128, 78, 84, 79, 71, 128, 78, 84, 79, 199, 78, 84, 73, 69, 197, 78, 84, - 72, 65, 85, 128, 78, 84, 69, 85, 78, 71, 66, 65, 128, 78, 84, 69, 85, 77, - 128, 78, 84, 69, 78, 128, 78, 84, 69, 69, 128, 78, 84, 65, 80, 128, 78, - 84, 65, 208, 78, 84, 65, 65, 128, 78, 84, 65, 128, 78, 83, 85, 79, 212, - 78, 83, 85, 78, 128, 78, 83, 85, 77, 128, 78, 83, 79, 77, 128, 78, 83, - 73, 69, 69, 84, 128, 78, 83, 73, 69, 69, 80, 128, 78, 83, 73, 69, 69, - 128, 78, 83, 72, 85, 84, 128, 78, 83, 72, 85, 212, 78, 83, 72, 85, 79, - 80, 128, 78, 83, 72, 85, 69, 128, 78, 83, 72, 73, 69, 69, 128, 78, 83, - 72, 69, 69, 128, 78, 83, 72, 65, 81, 128, 78, 83, 72, 65, 128, 78, 83, - 69, 85, 65, 69, 78, 128, 78, 83, 69, 78, 128, 78, 83, 65, 128, 78, 82, - 89, 88, 128, 78, 82, 89, 84, 128, 78, 82, 89, 82, 88, 128, 78, 82, 89, - 82, 128, 78, 82, 89, 80, 128, 78, 82, 89, 128, 78, 82, 85, 88, 128, 78, - 82, 85, 84, 128, 78, 82, 85, 82, 88, 128, 78, 82, 85, 82, 128, 78, 82, - 85, 80, 128, 78, 82, 85, 65, 128, 78, 82, 85, 128, 78, 82, 79, 88, 128, - 78, 82, 79, 80, 128, 78, 82, 79, 128, 78, 82, 69, 88, 128, 78, 82, 69, - 84, 128, 78, 82, 69, 211, 78, 82, 69, 80, 128, 78, 82, 69, 128, 78, 82, - 65, 88, 128, 78, 82, 65, 84, 128, 78, 82, 65, 80, 128, 78, 82, 65, 128, - 78, 81, 73, 71, 128, 78, 81, 65, 128, 78, 80, 76, 65, 128, 78, 80, 65, - 128, 78, 79, 90, 72, 75, 65, 128, 78, 79, 89, 128, 78, 79, 88, 128, 78, - 79, 87, 67, 128, 78, 79, 86, 73, 76, 69, 128, 78, 79, 86, 69, 77, 66, 69, - 82, 128, 78, 79, 84, 84, 79, 128, 78, 79, 84, 69, 83, 128, 78, 79, 84, - 69, 72, 69, 65, 68, 128, 78, 79, 84, 69, 72, 69, 65, 196, 78, 79, 84, 69, - 66, 79, 79, 75, 128, 78, 79, 84, 69, 66, 79, 79, 203, 78, 79, 84, 69, - 128, 78, 79, 84, 197, 78, 79, 84, 67, 72, 69, 196, 78, 79, 84, 67, 72, - 128, 78, 79, 84, 65, 84, 73, 79, 206, 78, 79, 84, 128, 78, 79, 212, 78, - 79, 83, 69, 128, 78, 79, 83, 197, 78, 79, 82, 84, 72, 87, 69, 83, 212, - 78, 79, 82, 84, 72, 69, 82, 206, 78, 79, 82, 84, 72, 69, 65, 83, 84, 45, - 80, 79, 73, 78, 84, 73, 78, 199, 78, 79, 82, 77, 65, 204, 78, 79, 82, 68, - 73, 195, 78, 79, 210, 78, 79, 80, 128, 78, 79, 79, 78, 85, 128, 78, 79, - 79, 128, 78, 79, 78, 70, 79, 82, 75, 73, 78, 71, 128, 78, 79, 78, 45, 80, - 79, 84, 65, 66, 76, 197, 78, 79, 78, 45, 74, 79, 73, 78, 69, 82, 128, 78, - 79, 78, 45, 66, 82, 69, 65, 75, 73, 78, 199, 78, 79, 78, 128, 78, 79, 77, - 73, 83, 77, 193, 78, 79, 77, 73, 78, 65, 204, 78, 79, 75, 72, 85, 75, - 128, 78, 79, 68, 69, 128, 78, 79, 65, 128, 78, 79, 45, 66, 82, 69, 65, - 203, 78, 79, 45, 53, 128, 78, 79, 45, 52, 128, 78, 79, 45, 51, 128, 78, - 79, 45, 50, 128, 78, 79, 45, 49, 128, 78, 78, 85, 85, 128, 78, 78, 85, - 128, 78, 78, 79, 79, 128, 78, 78, 78, 85, 85, 128, 78, 78, 78, 85, 128, - 78, 78, 78, 79, 79, 128, 78, 78, 78, 79, 128, 78, 78, 78, 73, 73, 128, - 78, 78, 78, 73, 128, 78, 78, 78, 69, 69, 128, 78, 78, 78, 69, 128, 78, - 78, 78, 65, 85, 128, 78, 78, 78, 65, 73, 128, 78, 78, 78, 65, 65, 128, - 78, 78, 78, 65, 128, 78, 78, 78, 128, 78, 78, 72, 65, 128, 78, 78, 71, - 79, 79, 128, 78, 78, 71, 79, 128, 78, 78, 71, 73, 73, 128, 78, 78, 71, - 73, 128, 78, 78, 71, 65, 65, 128, 78, 78, 71, 65, 128, 78, 78, 71, 128, - 78, 78, 66, 83, 80, 128, 78, 77, 128, 78, 76, 65, 85, 128, 78, 76, 48, - 50, 48, 128, 78, 76, 48, 49, 57, 128, 78, 76, 48, 49, 56, 128, 78, 76, - 48, 49, 55, 65, 128, 78, 76, 48, 49, 55, 128, 78, 76, 48, 49, 54, 128, - 78, 76, 48, 49, 53, 128, 78, 76, 48, 49, 52, 128, 78, 76, 48, 49, 51, - 128, 78, 76, 48, 49, 50, 128, 78, 76, 48, 49, 49, 128, 78, 76, 48, 49, - 48, 128, 78, 76, 48, 48, 57, 128, 78, 76, 48, 48, 56, 128, 78, 76, 48, - 48, 55, 128, 78, 76, 48, 48, 54, 128, 78, 76, 48, 48, 53, 65, 128, 78, - 76, 48, 48, 53, 128, 78, 76, 48, 48, 52, 128, 78, 76, 48, 48, 51, 128, - 78, 76, 48, 48, 50, 128, 78, 76, 48, 48, 49, 128, 78, 76, 128, 78, 75, - 79, 77, 128, 78, 75, 207, 78, 75, 73, 78, 68, 73, 128, 78, 75, 65, 85, - 128, 78, 75, 65, 65, 82, 65, 69, 128, 78, 75, 65, 128, 78, 74, 89, 88, - 128, 78, 74, 89, 84, 128, 78, 74, 89, 82, 88, 128, 78, 74, 89, 82, 128, - 78, 74, 89, 80, 128, 78, 74, 89, 128, 78, 74, 85, 88, 128, 78, 74, 85, - 82, 88, 128, 78, 74, 85, 82, 128, 78, 74, 85, 81, 65, 128, 78, 74, 85, - 80, 128, 78, 74, 85, 79, 88, 128, 78, 74, 85, 79, 128, 78, 74, 85, 69, - 81, 128, 78, 74, 85, 65, 69, 128, 78, 74, 85, 128, 78, 74, 79, 88, 128, - 78, 74, 79, 84, 128, 78, 74, 79, 80, 128, 78, 74, 79, 79, 128, 78, 74, - 79, 128, 78, 74, 73, 88, 128, 78, 74, 73, 84, 128, 78, 74, 73, 80, 128, - 78, 74, 73, 69, 88, 128, 78, 74, 73, 69, 84, 128, 78, 74, 73, 69, 80, - 128, 78, 74, 73, 69, 69, 128, 78, 74, 73, 69, 128, 78, 74, 73, 128, 78, - 74, 201, 78, 74, 69, 85, 88, 128, 78, 74, 69, 85, 84, 128, 78, 74, 69, - 85, 65, 69, 78, 65, 128, 78, 74, 69, 85, 65, 69, 77, 128, 78, 74, 69, 69, - 69, 69, 128, 78, 74, 69, 69, 128, 78, 74, 69, 197, 78, 74, 69, 128, 78, - 74, 65, 81, 128, 78, 74, 65, 80, 128, 78, 74, 65, 69, 77, 76, 73, 128, - 78, 74, 65, 69, 77, 128, 78, 74, 65, 65, 128, 78, 73, 90, 75, 207, 78, - 73, 88, 128, 78, 73, 84, 82, 69, 128, 78, 73, 83, 65, 71, 128, 78, 73, - 82, 85, 71, 85, 128, 78, 73, 80, 128, 78, 73, 78, 84, 72, 128, 78, 73, - 78, 74, 65, 128, 78, 73, 78, 69, 84, 89, 128, 78, 73, 78, 69, 84, 217, - 78, 73, 78, 69, 84, 69, 69, 78, 128, 78, 73, 78, 69, 84, 69, 69, 206, 78, - 73, 78, 69, 45, 84, 72, 73, 82, 84, 89, 128, 78, 73, 78, 69, 45, 76, 73, - 75, 197, 78, 73, 78, 197, 78, 73, 78, 68, 65, 50, 128, 78, 73, 78, 68, - 65, 178, 78, 73, 78, 57, 128, 78, 73, 78, 128, 78, 73, 77, 128, 78, 73, - 205, 78, 73, 75, 79, 76, 83, 66, 85, 82, 199, 78, 73, 75, 72, 65, 72, 73, - 84, 128, 78, 73, 75, 65, 72, 73, 84, 128, 78, 73, 75, 65, 128, 78, 73, - 72, 83, 72, 86, 65, 83, 65, 128, 78, 73, 71, 73, 68, 65, 77, 73, 78, 128, - 78, 73, 71, 73, 68, 65, 69, 83, 72, 128, 78, 73, 71, 72, 84, 128, 78, 73, - 71, 72, 212, 78, 73, 71, 71, 65, 72, 73, 84, 65, 128, 78, 73, 69, 88, - 128, 78, 73, 69, 85, 78, 45, 84, 73, 75, 69, 85, 84, 128, 78, 73, 69, 85, - 78, 45, 84, 72, 73, 69, 85, 84, 72, 128, 78, 73, 69, 85, 78, 45, 83, 73, - 79, 83, 128, 78, 73, 69, 85, 78, 45, 82, 73, 69, 85, 76, 128, 78, 73, 69, - 85, 78, 45, 80, 73, 69, 85, 80, 128, 78, 73, 69, 85, 78, 45, 80, 65, 78, - 83, 73, 79, 83, 128, 78, 73, 69, 85, 78, 45, 75, 73, 89, 69, 79, 75, 128, - 78, 73, 69, 85, 78, 45, 72, 73, 69, 85, 72, 128, 78, 73, 69, 85, 78, 45, - 67, 73, 69, 85, 67, 128, 78, 73, 69, 85, 78, 45, 67, 72, 73, 69, 85, 67, - 72, 128, 78, 73, 69, 85, 206, 78, 73, 69, 80, 128, 78, 73, 69, 128, 78, - 73, 66, 128, 78, 73, 65, 128, 78, 73, 50, 128, 78, 73, 45, 84, 69, 128, - 78, 73, 45, 55, 128, 78, 73, 45, 54, 128, 78, 73, 45, 53, 128, 78, 73, - 45, 52, 128, 78, 73, 45, 51, 128, 78, 73, 45, 50, 128, 78, 73, 45, 49, - 128, 78, 72, 85, 69, 128, 78, 72, 74, 65, 128, 78, 72, 65, 89, 128, 78, - 72, 128, 78, 71, 89, 69, 128, 78, 71, 86, 69, 128, 78, 71, 85, 85, 128, - 78, 71, 85, 79, 88, 128, 78, 71, 85, 79, 84, 128, 78, 71, 85, 79, 128, - 78, 71, 85, 65, 78, 128, 78, 71, 85, 65, 69, 84, 128, 78, 71, 85, 65, 69, - 128, 78, 71, 79, 88, 128, 78, 71, 79, 85, 128, 78, 71, 79, 213, 78, 71, - 79, 84, 128, 78, 71, 79, 81, 128, 78, 71, 79, 80, 128, 78, 71, 79, 78, - 128, 78, 71, 79, 77, 128, 78, 71, 79, 69, 72, 128, 78, 71, 79, 69, 200, - 78, 71, 207, 78, 71, 75, 89, 69, 69, 128, 78, 71, 75, 87, 65, 69, 78, - 128, 78, 71, 75, 85, 80, 128, 78, 71, 75, 85, 78, 128, 78, 71, 75, 85, - 77, 128, 78, 71, 75, 85, 69, 78, 90, 69, 85, 77, 128, 78, 71, 75, 85, - 197, 78, 71, 75, 73, 78, 68, 201, 78, 71, 75, 73, 69, 69, 128, 78, 71, - 75, 69, 85, 88, 128, 78, 71, 75, 69, 85, 82, 73, 128, 78, 71, 75, 69, 85, - 65, 69, 81, 128, 78, 71, 75, 69, 85, 65, 69, 77, 128, 78, 71, 75, 65, 81, - 128, 78, 71, 75, 65, 80, 128, 78, 71, 75, 65, 65, 77, 73, 128, 78, 71, - 75, 65, 128, 78, 71, 73, 69, 88, 128, 78, 71, 73, 69, 80, 128, 78, 71, - 73, 69, 128, 78, 71, 72, 65, 128, 78, 71, 71, 87, 65, 69, 78, 128, 78, - 71, 71, 85, 82, 65, 69, 128, 78, 71, 71, 85, 80, 128, 78, 71, 71, 85, 79, - 81, 128, 78, 71, 71, 85, 79, 209, 78, 71, 71, 85, 79, 78, 128, 78, 71, - 71, 85, 79, 77, 128, 78, 71, 71, 85, 77, 128, 78, 71, 71, 85, 69, 69, 84, - 128, 78, 71, 71, 85, 65, 69, 83, 72, 65, 197, 78, 71, 71, 85, 65, 69, - 206, 78, 71, 71, 85, 65, 128, 78, 71, 71, 85, 128, 78, 71, 71, 79, 79, - 128, 78, 71, 71, 79, 128, 78, 71, 71, 73, 128, 78, 71, 71, 69, 85, 88, - 128, 78, 71, 71, 69, 85, 65, 69, 84, 128, 78, 71, 71, 69, 85, 65, 69, - 128, 78, 71, 71, 69, 213, 78, 71, 71, 69, 78, 128, 78, 71, 71, 69, 69, - 84, 128, 78, 71, 71, 69, 69, 69, 69, 128, 78, 71, 71, 69, 69, 128, 78, - 71, 71, 69, 128, 78, 71, 71, 65, 80, 128, 78, 71, 71, 65, 65, 77, 65, 69, - 128, 78, 71, 71, 65, 65, 77, 128, 78, 71, 71, 65, 65, 128, 78, 71, 71, - 128, 78, 71, 69, 88, 128, 78, 71, 69, 85, 82, 69, 85, 84, 128, 78, 71, - 69, 80, 128, 78, 71, 69, 78, 128, 78, 71, 69, 69, 128, 78, 71, 69, 65, - 68, 65, 76, 128, 78, 71, 65, 88, 128, 78, 71, 65, 85, 128, 78, 71, 65, - 84, 128, 78, 71, 65, 211, 78, 71, 65, 81, 128, 78, 71, 65, 80, 128, 78, - 71, 65, 78, 71, 85, 128, 78, 71, 65, 78, 128, 78, 71, 65, 73, 128, 78, - 71, 65, 72, 128, 78, 71, 65, 65, 73, 128, 78, 71, 193, 78, 70, 128, 78, - 69, 88, 212, 78, 69, 88, 128, 78, 69, 87, 83, 80, 65, 80, 69, 82, 128, - 78, 69, 87, 76, 73, 78, 69, 128, 78, 69, 87, 76, 73, 78, 197, 78, 69, 87, - 193, 78, 69, 87, 128, 78, 69, 215, 78, 69, 85, 84, 82, 65, 76, 128, 78, - 69, 85, 84, 82, 65, 204, 78, 69, 85, 84, 69, 82, 128, 78, 69, 84, 87, 79, - 82, 75, 69, 196, 78, 69, 212, 78, 69, 83, 84, 73, 78, 199, 78, 69, 83, - 84, 69, 196, 78, 69, 83, 84, 128, 78, 69, 83, 212, 78, 69, 83, 83, 85, - 83, 128, 78, 69, 82, 196, 78, 69, 81, 85, 68, 65, 65, 128, 78, 69, 80, - 84, 85, 78, 69, 128, 78, 69, 80, 84, 85, 78, 197, 78, 69, 80, 79, 83, 84, - 79, 89, 65, 78, 78, 65, 89, 65, 128, 78, 69, 80, 128, 78, 69, 79, 128, - 78, 69, 207, 78, 69, 78, 79, 69, 128, 78, 69, 78, 65, 78, 79, 128, 78, - 69, 78, 128, 78, 69, 77, 75, 65, 128, 78, 69, 76, 128, 78, 69, 73, 84, - 72, 69, 210, 78, 69, 71, 65, 84, 73, 86, 197, 78, 69, 71, 65, 84, 73, 79, - 206, 78, 69, 71, 65, 84, 69, 196, 78, 69, 69, 68, 76, 69, 128, 78, 69, - 67, 75, 84, 73, 69, 128, 78, 69, 67, 75, 128, 78, 69, 66, 69, 78, 83, 84, - 73, 77, 77, 69, 128, 78, 69, 45, 75, 79, 128, 78, 68, 85, 88, 128, 78, - 68, 85, 84, 128, 78, 68, 85, 82, 88, 128, 78, 68, 85, 82, 128, 78, 68, - 85, 80, 128, 78, 68, 85, 78, 128, 78, 68, 213, 78, 68, 79, 88, 128, 78, - 68, 79, 84, 128, 78, 68, 79, 80, 128, 78, 68, 79, 79, 128, 78, 68, 79, - 78, 128, 78, 68, 79, 77, 66, 85, 128, 78, 68, 79, 76, 197, 78, 68, 73, - 88, 128, 78, 68, 73, 84, 128, 78, 68, 73, 81, 128, 78, 68, 73, 80, 128, - 78, 68, 73, 69, 88, 128, 78, 68, 73, 69, 128, 78, 68, 73, 68, 65, 128, - 78, 68, 73, 65, 81, 128, 78, 68, 69, 88, 128, 78, 68, 69, 85, 88, 128, - 78, 68, 69, 85, 84, 128, 78, 68, 69, 85, 65, 69, 82, 69, 69, 128, 78, 68, - 69, 80, 128, 78, 68, 69, 69, 128, 78, 68, 69, 128, 78, 68, 65, 88, 128, - 78, 68, 65, 84, 128, 78, 68, 65, 80, 128, 78, 68, 65, 77, 128, 78, 68, - 65, 65, 78, 71, 71, 69, 85, 65, 69, 84, 128, 78, 68, 65, 65, 128, 78, 68, - 65, 193, 78, 67, 72, 65, 85, 128, 78, 67, 65, 128, 78, 66, 89, 88, 128, - 78, 66, 89, 84, 128, 78, 66, 89, 82, 88, 128, 78, 66, 89, 82, 128, 78, - 66, 89, 80, 128, 78, 66, 89, 128, 78, 66, 85, 88, 128, 78, 66, 85, 84, - 128, 78, 66, 85, 82, 88, 128, 78, 66, 85, 82, 128, 78, 66, 85, 80, 128, - 78, 66, 85, 128, 78, 66, 79, 88, 128, 78, 66, 79, 84, 128, 78, 66, 79, - 80, 128, 78, 66, 79, 128, 78, 66, 73, 88, 128, 78, 66, 73, 84, 128, 78, - 66, 73, 80, 128, 78, 66, 73, 69, 88, 128, 78, 66, 73, 69, 80, 128, 78, - 66, 73, 69, 128, 78, 66, 73, 128, 78, 66, 72, 128, 78, 66, 65, 88, 128, - 78, 66, 65, 84, 128, 78, 66, 65, 80, 128, 78, 66, 65, 128, 78, 65, 90, - 65, 210, 78, 65, 89, 65, 78, 78, 65, 128, 78, 65, 89, 128, 78, 65, 88, - 73, 65, 206, 78, 65, 88, 128, 78, 65, 85, 84, 72, 83, 128, 78, 65, 85, - 83, 69, 65, 84, 69, 196, 78, 65, 85, 68, 73, 218, 78, 65, 84, 85, 82, 65, - 204, 78, 65, 84, 84, 73, 76, 73, 203, 78, 65, 84, 73, 79, 78, 65, 204, - 78, 65, 83, 75, 65, 80, 201, 78, 65, 83, 72, 73, 128, 78, 65, 83, 65, 76, - 73, 90, 69, 196, 78, 65, 83, 65, 76, 73, 90, 65, 84, 73, 79, 78, 128, 78, - 65, 83, 65, 76, 73, 90, 65, 84, 73, 79, 206, 78, 65, 83, 65, 204, 78, 65, - 82, 82, 79, 215, 78, 65, 82, 128, 78, 65, 81, 128, 78, 65, 79, 211, 78, - 65, 78, 83, 65, 78, 65, 81, 128, 78, 65, 78, 71, 77, 79, 78, 84, 72, 79, - 128, 78, 65, 78, 68, 73, 78, 65, 71, 65, 82, 201, 78, 65, 78, 68, 128, - 78, 65, 78, 65, 128, 78, 65, 77, 69, 128, 78, 65, 77, 197, 78, 65, 77, - 50, 128, 78, 65, 75, 65, 65, 82, 193, 78, 65, 75, 128, 78, 65, 73, 82, - 193, 78, 65, 73, 204, 78, 65, 71, 82, 201, 78, 65, 71, 65, 82, 128, 78, - 65, 71, 65, 128, 78, 65, 71, 193, 78, 65, 71, 128, 78, 65, 199, 78, 65, - 69, 128, 78, 65, 66, 76, 65, 128, 78, 65, 66, 65, 84, 65, 69, 65, 206, - 78, 65, 65, 83, 73, 75, 89, 65, 89, 65, 128, 78, 65, 65, 75, 83, 73, 75, - 89, 65, 89, 65, 128, 78, 65, 65, 73, 128, 78, 65, 193, 78, 65, 52, 128, - 78, 65, 50, 128, 78, 65, 45, 57, 128, 78, 65, 45, 56, 128, 78, 65, 45, - 55, 128, 78, 65, 45, 54, 128, 78, 65, 45, 53, 128, 78, 65, 45, 52, 128, - 78, 65, 45, 51, 128, 78, 65, 45, 50, 128, 78, 65, 45, 49, 128, 78, 48, - 52, 50, 128, 78, 48, 52, 49, 128, 78, 48, 52, 48, 128, 78, 48, 51, 57, - 128, 78, 48, 51, 56, 128, 78, 48, 51, 55, 65, 128, 78, 48, 51, 55, 128, - 78, 48, 51, 54, 128, 78, 48, 51, 53, 65, 128, 78, 48, 51, 53, 128, 78, - 48, 51, 52, 65, 128, 78, 48, 51, 52, 128, 78, 48, 51, 51, 65, 128, 78, - 48, 51, 51, 128, 78, 48, 51, 50, 128, 78, 48, 51, 49, 128, 78, 48, 51, - 48, 128, 78, 48, 50, 57, 128, 78, 48, 50, 56, 128, 78, 48, 50, 55, 128, - 78, 48, 50, 54, 128, 78, 48, 50, 53, 65, 128, 78, 48, 50, 53, 128, 78, - 48, 50, 52, 128, 78, 48, 50, 51, 128, 78, 48, 50, 50, 128, 78, 48, 50, - 49, 128, 78, 48, 50, 48, 128, 78, 48, 49, 57, 128, 78, 48, 49, 56, 66, - 128, 78, 48, 49, 56, 65, 128, 78, 48, 49, 56, 128, 78, 48, 49, 55, 128, - 78, 48, 49, 54, 128, 78, 48, 49, 53, 128, 78, 48, 49, 52, 128, 78, 48, - 49, 51, 128, 78, 48, 49, 50, 128, 78, 48, 49, 49, 128, 78, 48, 49, 48, - 128, 78, 48, 48, 57, 128, 78, 48, 48, 56, 128, 78, 48, 48, 55, 128, 78, - 48, 48, 54, 128, 78, 48, 48, 53, 128, 78, 48, 48, 52, 128, 78, 48, 48, - 51, 128, 78, 48, 48, 50, 128, 78, 48, 48, 49, 128, 78, 45, 77, 85, 45, - 77, 79, 45, 50, 128, 78, 45, 77, 85, 45, 77, 79, 45, 49, 128, 78, 45, 67, - 82, 69, 197, 78, 45, 65, 82, 217, 77, 90, 128, 77, 89, 88, 128, 77, 89, - 84, 128, 77, 89, 83, 76, 73, 84, 69, 128, 77, 89, 80, 128, 77, 89, 65, - 128, 77, 89, 193, 77, 87, 79, 79, 128, 77, 87, 79, 128, 77, 87, 73, 73, - 128, 77, 87, 73, 128, 77, 87, 69, 69, 128, 77, 87, 69, 128, 77, 87, 65, - 65, 128, 77, 87, 65, 128, 77, 87, 128, 77, 215, 77, 86, 83, 128, 77, 86, - 79, 80, 128, 77, 86, 73, 128, 77, 86, 69, 85, 65, 69, 78, 71, 65, 77, - 128, 77, 86, 128, 77, 214, 77, 85, 88, 128, 77, 85, 85, 86, 85, 90, 72, - 65, 75, 75, 85, 128, 77, 85, 85, 83, 73, 75, 65, 84, 79, 65, 78, 128, 77, - 85, 85, 82, 68, 72, 65, 74, 193, 77, 85, 85, 128, 77, 85, 84, 72, 65, 76, - 73, 89, 65, 128, 77, 85, 84, 128, 77, 85, 83, 73, 67, 128, 77, 85, 83, - 73, 195, 77, 85, 83, 72, 82, 79, 79, 77, 128, 77, 85, 83, 72, 51, 128, - 77, 85, 83, 72, 179, 77, 85, 83, 72, 128, 77, 85, 83, 200, 77, 85, 83, - 128, 77, 85, 82, 88, 128, 77, 85, 82, 71, 85, 50, 128, 77, 85, 82, 69, - 128, 77, 85, 82, 68, 65, 128, 77, 85, 82, 68, 193, 77, 85, 82, 128, 77, - 85, 81, 68, 65, 77, 128, 77, 85, 80, 128, 77, 85, 79, 88, 128, 77, 85, - 79, 84, 128, 77, 85, 79, 80, 128, 77, 85, 79, 77, 65, 69, 128, 77, 85, - 79, 128, 77, 85, 78, 83, 85, 66, 128, 77, 85, 78, 68, 65, 82, 201, 77, - 85, 78, 65, 72, 128, 77, 85, 78, 128, 77, 85, 76, 84, 73, 83, 69, 84, - 128, 77, 85, 76, 84, 73, 83, 69, 212, 77, 85, 76, 84, 73, 80, 76, 73, 67, - 65, 84, 73, 79, 78, 128, 77, 85, 76, 84, 73, 80, 76, 73, 67, 65, 84, 73, - 79, 206, 77, 85, 76, 84, 73, 80, 76, 69, 128, 77, 85, 76, 84, 73, 80, 76, - 197, 77, 85, 76, 84, 73, 79, 67, 85, 76, 65, 210, 77, 85, 76, 84, 73, 77, - 65, 80, 128, 77, 85, 76, 84, 201, 77, 85, 76, 84, 65, 78, 201, 77, 85, - 75, 80, 72, 82, 69, 78, 71, 128, 77, 85, 75, 75, 85, 82, 85, 78, 73, 128, - 77, 85, 73, 78, 128, 77, 85, 72, 79, 82, 128, 77, 85, 71, 83, 128, 77, - 85, 71, 128, 77, 85, 199, 77, 85, 69, 78, 128, 77, 85, 69, 128, 77, 85, - 67, 72, 128, 77, 85, 67, 200, 77, 85, 67, 65, 65, 68, 128, 77, 85, 65, - 83, 128, 77, 85, 65, 78, 128, 77, 85, 65, 69, 128, 77, 85, 45, 71, 65, - 65, 72, 76, 65, 193, 77, 85, 45, 52, 128, 77, 85, 45, 51, 128, 77, 85, - 45, 50, 128, 77, 85, 45, 49, 128, 77, 213, 77, 84, 65, 86, 82, 85, 76, - 201, 77, 83, 128, 77, 82, 207, 77, 82, 65, 67, 72, 78, 89, 128, 77, 82, - 65, 67, 72, 78, 79, 84, 73, 75, 72, 65, 89, 65, 128, 77, 82, 65, 67, 72, - 78, 79, 128, 77, 82, 65, 67, 72, 78, 65, 89, 65, 128, 77, 210, 77, 81, - 128, 77, 80, 65, 128, 77, 79, 89, 65, 73, 128, 77, 79, 88, 128, 77, 79, - 86, 73, 197, 77, 79, 86, 69, 211, 77, 79, 86, 69, 77, 69, 78, 84, 45, 87, - 65, 76, 76, 80, 76, 65, 78, 197, 77, 79, 86, 69, 77, 69, 78, 84, 45, 72, - 73, 78, 71, 197, 77, 79, 86, 69, 77, 69, 78, 84, 45, 70, 76, 79, 79, 82, - 80, 76, 65, 78, 197, 77, 79, 86, 69, 77, 69, 78, 84, 45, 68, 73, 65, 71, - 79, 78, 65, 204, 77, 79, 86, 69, 77, 69, 78, 84, 128, 77, 79, 86, 69, 77, - 69, 78, 212, 77, 79, 86, 69, 196, 77, 79, 86, 69, 128, 77, 79, 85, 84, - 72, 128, 77, 79, 85, 83, 69, 128, 77, 79, 85, 83, 197, 77, 79, 85, 78, - 84, 65, 73, 78, 83, 128, 77, 79, 85, 78, 84, 65, 73, 78, 128, 77, 79, 85, - 78, 84, 65, 73, 206, 77, 79, 85, 78, 212, 77, 79, 85, 78, 68, 128, 77, - 79, 85, 78, 196, 77, 79, 84, 79, 82, 87, 65, 89, 128, 77, 79, 84, 79, 82, - 73, 90, 69, 196, 77, 79, 84, 79, 82, 67, 89, 67, 76, 69, 128, 77, 79, 84, - 79, 210, 77, 79, 84, 72, 69, 82, 128, 77, 79, 84, 72, 69, 210, 77, 79, - 84, 128, 77, 79, 83, 81, 85, 73, 84, 79, 128, 77, 79, 83, 81, 85, 69, - 128, 77, 79, 82, 84, 85, 85, 77, 128, 77, 79, 82, 84, 65, 82, 128, 77, - 79, 82, 80, 72, 79, 76, 79, 71, 73, 67, 65, 204, 77, 79, 82, 78, 73, 78, - 71, 128, 77, 79, 80, 128, 77, 79, 79, 83, 69, 45, 67, 82, 69, 197, 77, - 79, 79, 83, 69, 128, 77, 79, 79, 78, 128, 77, 79, 79, 206, 77, 79, 79, - 77, 80, 85, 81, 128, 77, 79, 79, 77, 69, 85, 84, 128, 77, 79, 79, 68, - 128, 77, 79, 79, 196, 77, 79, 79, 128, 77, 79, 78, 84, 73, 69, 69, 78, - 128, 77, 79, 78, 84, 72, 128, 77, 79, 78, 84, 200, 77, 79, 78, 83, 84, - 69, 82, 128, 77, 79, 78, 79, 83, 84, 65, 66, 76, 197, 77, 79, 78, 79, 83, - 80, 65, 67, 197, 77, 79, 78, 79, 82, 65, 73, 76, 128, 77, 79, 78, 79, 71, - 82, 65, 80, 200, 77, 79, 78, 79, 71, 82, 65, 77, 77, 79, 211, 77, 79, 78, - 79, 71, 82, 65, 205, 77, 79, 78, 79, 70, 79, 78, 73, 65, 83, 128, 77, 79, - 78, 79, 67, 85, 76, 65, 210, 77, 79, 78, 79, 67, 76, 69, 128, 77, 79, 78, - 75, 69, 89, 128, 77, 79, 78, 75, 69, 217, 77, 79, 78, 73, 128, 77, 79, - 78, 71, 75, 69, 85, 65, 69, 81, 128, 77, 79, 78, 69, 89, 45, 77, 79, 85, - 84, 200, 77, 79, 78, 69, 217, 77, 79, 78, 128, 77, 79, 206, 77, 79, 76, - 128, 77, 79, 75, 72, 65, 83, 83, 65, 83, 128, 77, 79, 72, 65, 77, 77, 65, - 196, 77, 79, 68, 85, 76, 207, 77, 79, 68, 73, 70, 73, 69, 82, 45, 57, - 128, 77, 79, 68, 73, 70, 73, 69, 82, 45, 56, 128, 77, 79, 68, 73, 70, 73, - 69, 82, 45, 55, 128, 77, 79, 68, 73, 70, 73, 69, 82, 45, 54, 128, 77, 79, - 68, 73, 70, 73, 69, 82, 45, 53, 128, 77, 79, 68, 73, 70, 73, 69, 82, 45, - 52, 128, 77, 79, 68, 73, 70, 73, 69, 82, 45, 51, 128, 77, 79, 68, 73, 70, - 73, 69, 82, 45, 50, 128, 77, 79, 68, 73, 70, 73, 69, 82, 45, 49, 54, 128, - 77, 79, 68, 73, 70, 73, 69, 82, 45, 49, 53, 128, 77, 79, 68, 73, 70, 73, - 69, 82, 45, 49, 52, 128, 77, 79, 68, 73, 70, 73, 69, 82, 45, 49, 51, 128, - 77, 79, 68, 73, 70, 73, 69, 82, 45, 49, 50, 128, 77, 79, 68, 73, 70, 73, - 69, 82, 45, 49, 49, 128, 77, 79, 68, 73, 70, 73, 69, 82, 45, 49, 48, 128, - 77, 79, 68, 73, 70, 73, 69, 82, 128, 77, 79, 68, 201, 77, 79, 68, 69, 83, - 84, 89, 128, 77, 79, 68, 69, 82, 206, 77, 79, 68, 69, 77, 128, 77, 79, - 68, 69, 76, 83, 128, 77, 79, 68, 69, 76, 128, 77, 79, 68, 69, 128, 77, - 79, 66, 73, 76, 197, 77, 79, 65, 128, 77, 79, 45, 54, 128, 77, 79, 45, - 53, 128, 77, 79, 45, 52, 128, 77, 79, 45, 51, 128, 77, 207, 77, 78, 89, - 65, 205, 77, 78, 65, 83, 128, 77, 77, 83, 80, 128, 77, 77, 128, 77, 205, - 77, 76, 65, 128, 77, 76, 128, 77, 75, 80, 65, 82, 65, 209, 77, 73, 88, - 128, 77, 73, 84, 128, 77, 73, 83, 82, 65, 128, 77, 73, 82, 82, 79, 82, - 128, 77, 73, 82, 82, 79, 210, 77, 73, 82, 73, 66, 65, 65, 82, 85, 128, - 77, 73, 82, 73, 128, 77, 73, 82, 69, 68, 128, 77, 73, 80, 128, 77, 73, - 78, 89, 128, 77, 73, 78, 85, 83, 45, 79, 82, 45, 80, 76, 85, 211, 77, 73, - 78, 85, 83, 128, 77, 73, 78, 78, 65, 206, 77, 73, 78, 73, 83, 84, 69, 82, - 128, 77, 73, 78, 73, 77, 73, 90, 69, 128, 77, 73, 78, 73, 77, 65, 128, - 77, 73, 78, 73, 68, 73, 83, 67, 128, 77, 73, 78, 73, 66, 85, 83, 128, 77, - 73, 78, 68, 85, 128, 77, 73, 77, 69, 128, 77, 73, 77, 128, 77, 73, 76, - 76, 73, 79, 78, 83, 128, 77, 73, 76, 76, 73, 79, 78, 211, 77, 73, 76, 76, - 69, 84, 128, 77, 73, 76, 76, 197, 77, 73, 76, 204, 77, 73, 76, 75, 217, - 77, 73, 76, 75, 128, 77, 73, 76, 73, 84, 65, 82, 217, 77, 73, 76, 128, - 77, 73, 75, 85, 82, 79, 78, 128, 77, 73, 75, 82, 79, 206, 77, 73, 75, 82, - 73, 128, 77, 73, 73, 78, 128, 77, 73, 73, 77, 128, 77, 73, 73, 128, 77, - 73, 199, 77, 73, 69, 88, 128, 77, 73, 69, 85, 77, 45, 84, 73, 75, 69, 85, - 84, 128, 77, 73, 69, 85, 77, 45, 83, 83, 65, 78, 71, 83, 73, 79, 83, 128, - 77, 73, 69, 85, 77, 45, 83, 83, 65, 78, 71, 78, 73, 69, 85, 78, 128, 77, - 73, 69, 85, 77, 45, 82, 73, 69, 85, 76, 128, 77, 73, 69, 85, 77, 45, 80, - 73, 69, 85, 80, 45, 83, 73, 79, 83, 128, 77, 73, 69, 85, 77, 45, 80, 73, - 69, 85, 80, 128, 77, 73, 69, 85, 77, 45, 80, 65, 78, 83, 73, 79, 83, 128, - 77, 73, 69, 85, 77, 45, 78, 73, 69, 85, 78, 128, 77, 73, 69, 85, 77, 45, - 67, 73, 69, 85, 67, 128, 77, 73, 69, 85, 77, 45, 67, 72, 73, 69, 85, 67, - 72, 128, 77, 73, 69, 85, 205, 77, 73, 69, 80, 128, 77, 73, 69, 69, 128, - 77, 73, 69, 128, 77, 73, 68, 76, 73, 78, 197, 77, 73, 68, 68, 76, 69, 45, - 87, 69, 76, 83, 200, 77, 73, 68, 68, 76, 69, 128, 77, 73, 68, 45, 76, 69, - 86, 69, 204, 77, 73, 68, 45, 72, 69, 73, 71, 72, 212, 77, 73, 196, 77, - 73, 67, 82, 79, 83, 67, 79, 80, 69, 128, 77, 73, 67, 82, 79, 80, 72, 79, - 78, 69, 128, 77, 73, 67, 82, 79, 66, 69, 128, 77, 73, 67, 82, 207, 77, - 73, 67, 210, 77, 73, 45, 55, 128, 77, 73, 45, 54, 128, 77, 73, 45, 53, - 128, 77, 73, 45, 52, 128, 77, 73, 45, 51, 128, 77, 73, 45, 50, 128, 77, - 73, 45, 49, 128, 77, 72, 90, 128, 77, 72, 65, 128, 77, 72, 128, 77, 71, - 85, 88, 128, 77, 71, 85, 84, 128, 77, 71, 85, 82, 88, 128, 77, 71, 85, - 82, 128, 77, 71, 85, 80, 128, 77, 71, 85, 79, 88, 128, 77, 71, 85, 79, - 80, 128, 77, 71, 85, 79, 128, 77, 71, 85, 128, 77, 71, 79, 88, 128, 77, - 71, 79, 84, 128, 77, 71, 79, 80, 128, 77, 71, 79, 128, 77, 71, 207, 77, - 71, 73, 69, 88, 128, 77, 71, 73, 69, 128, 77, 71, 69, 88, 128, 77, 71, - 69, 80, 128, 77, 71, 69, 128, 77, 71, 66, 85, 128, 77, 71, 66, 79, 79, - 128, 77, 71, 66, 79, 70, 85, 77, 128, 77, 71, 66, 79, 128, 77, 71, 66, - 73, 128, 77, 71, 66, 69, 85, 78, 128, 77, 71, 66, 69, 78, 128, 77, 71, - 66, 69, 69, 128, 77, 71, 66, 69, 128, 77, 71, 66, 65, 83, 65, 81, 128, - 77, 71, 66, 65, 83, 65, 128, 77, 71, 65, 88, 128, 77, 71, 65, 84, 128, - 77, 71, 65, 80, 128, 77, 71, 65, 128, 77, 71, 128, 77, 70, 79, 78, 128, - 77, 70, 79, 206, 77, 70, 79, 128, 77, 70, 73, 89, 65, 81, 128, 77, 70, - 73, 69, 69, 128, 77, 70, 69, 85, 84, 128, 77, 70, 69, 85, 81, 128, 77, - 70, 69, 85, 65, 69, 128, 77, 70, 65, 65, 128, 77, 69, 90, 90, 79, 128, - 77, 69, 88, 128, 77, 69, 85, 212, 77, 69, 85, 81, 128, 77, 69, 85, 78, - 74, 79, 77, 78, 68, 69, 85, 81, 128, 77, 69, 85, 78, 128, 77, 69, 84, 82, - 79, 128, 77, 69, 84, 82, 73, 67, 65, 204, 77, 69, 84, 82, 73, 65, 128, - 77, 69, 84, 82, 69, 84, 69, 211, 77, 69, 84, 79, 66, 69, 76, 85, 83, 128, - 77, 69, 84, 69, 75, 128, 77, 69, 84, 69, 71, 128, 77, 69, 84, 65, 76, - 128, 77, 69, 84, 193, 77, 69, 83, 83, 69, 78, 73, 65, 206, 77, 69, 83, - 83, 65, 71, 69, 128, 77, 69, 83, 83, 65, 71, 197, 77, 69, 83, 79, 128, - 77, 69, 83, 73, 128, 77, 69, 83, 72, 128, 77, 69, 82, 80, 69, 82, 83, 79, - 78, 128, 77, 69, 82, 75, 72, 65, 128, 77, 69, 82, 75, 72, 193, 77, 69, - 82, 73, 68, 73, 65, 78, 83, 128, 77, 69, 82, 73, 128, 77, 69, 82, 71, 69, - 128, 77, 69, 82, 67, 85, 82, 89, 128, 77, 69, 82, 67, 85, 82, 217, 77, - 69, 78, 79, 82, 65, 200, 77, 69, 78, 79, 69, 128, 77, 69, 78, 68, 85, 84, - 128, 77, 69, 78, 128, 77, 69, 77, 79, 128, 77, 69, 77, 66, 69, 82, 83, - 72, 73, 80, 128, 77, 69, 77, 66, 69, 82, 128, 77, 69, 77, 66, 69, 210, - 77, 69, 77, 45, 81, 79, 80, 72, 128, 77, 69, 77, 128, 77, 69, 205, 77, - 69, 76, 84, 73, 78, 199, 77, 69, 76, 79, 68, 73, 195, 77, 69, 76, 73, 75, - 128, 77, 69, 73, 90, 73, 128, 77, 69, 71, 65, 84, 79, 78, 128, 77, 69, - 71, 65, 80, 72, 79, 78, 69, 128, 77, 69, 71, 65, 76, 73, 128, 77, 69, 69, - 84, 79, 82, 85, 128, 77, 69, 69, 84, 69, 201, 77, 69, 69, 84, 128, 77, - 69, 69, 77, 85, 128, 77, 69, 69, 77, 128, 77, 69, 69, 202, 77, 69, 69, - 69, 69, 128, 77, 69, 68, 73, 85, 77, 128, 77, 69, 68, 73, 85, 205, 77, - 69, 68, 73, 69, 86, 65, 204, 77, 69, 68, 73, 67, 73, 78, 69, 128, 77, 69, - 68, 73, 67, 65, 204, 77, 69, 68, 73, 65, 204, 77, 69, 68, 69, 70, 65, 73, - 68, 82, 73, 206, 77, 69, 68, 65, 76, 128, 77, 69, 67, 72, 73, 75, 128, - 77, 69, 67, 72, 73, 203, 77, 69, 67, 72, 65, 78, 73, 67, 65, 204, 77, 69, - 65, 84, 128, 77, 69, 65, 212, 77, 69, 65, 83, 85, 82, 69, 196, 77, 69, - 65, 83, 85, 82, 69, 128, 77, 69, 65, 83, 85, 82, 197, 77, 69, 45, 77, 65, - 128, 77, 69, 45, 50, 128, 77, 69, 45, 49, 128, 77, 68, 85, 206, 77, 196, - 77, 67, 72, 213, 77, 67, 72, 65, 206, 77, 67, 128, 77, 195, 77, 66, 85, - 85, 128, 77, 66, 85, 79, 81, 128, 77, 66, 85, 79, 128, 77, 66, 85, 69, - 128, 77, 66, 85, 65, 69, 77, 128, 77, 66, 85, 65, 69, 128, 77, 66, 79, - 79, 128, 77, 66, 79, 128, 77, 66, 73, 84, 128, 77, 66, 73, 212, 77, 66, - 73, 82, 73, 69, 69, 78, 128, 77, 66, 73, 128, 77, 66, 69, 85, 88, 128, - 77, 66, 69, 85, 82, 73, 128, 77, 66, 69, 85, 77, 128, 77, 66, 69, 82, 65, - 69, 128, 77, 66, 69, 78, 128, 77, 66, 69, 69, 75, 69, 69, 84, 128, 77, - 66, 69, 69, 128, 77, 66, 69, 128, 77, 66, 65, 81, 128, 77, 66, 65, 78, - 89, 73, 128, 77, 66, 65, 65, 82, 65, 69, 128, 77, 66, 65, 65, 75, 69, 84, - 128, 77, 66, 65, 65, 128, 77, 66, 65, 193, 77, 66, 193, 77, 66, 52, 128, - 77, 66, 51, 128, 77, 66, 50, 128, 77, 65, 89, 69, 203, 77, 65, 89, 65, - 78, 78, 65, 128, 77, 65, 89, 65, 206, 77, 65, 89, 128, 77, 65, 88, 73, - 77, 73, 90, 69, 128, 77, 65, 88, 73, 77, 65, 128, 77, 65, 88, 128, 77, - 65, 85, 128, 77, 65, 84, 84, 79, 67, 75, 128, 77, 65, 84, 82, 73, 88, - 128, 77, 65, 84, 69, 82, 73, 65, 76, 83, 128, 77, 65, 84, 128, 77, 65, - 83, 213, 77, 65, 83, 83, 73, 78, 71, 128, 77, 65, 83, 83, 65, 71, 69, - 128, 77, 65, 83, 79, 82, 193, 77, 65, 83, 75, 128, 77, 65, 83, 203, 77, - 65, 83, 72, 70, 65, 65, 84, 128, 77, 65, 83, 72, 50, 128, 77, 65, 83, 67, - 85, 76, 73, 78, 197, 77, 65, 83, 65, 82, 65, 205, 77, 65, 82, 89, 128, - 77, 65, 82, 87, 65, 82, 201, 77, 65, 82, 85, 75, 85, 128, 77, 65, 82, 84, - 89, 82, 73, 193, 77, 65, 82, 84, 73, 65, 204, 77, 65, 82, 82, 89, 73, 78, - 199, 77, 65, 82, 82, 73, 65, 71, 197, 77, 65, 82, 82, 65, 84, 65, 78, - 128, 77, 65, 82, 75, 211, 77, 65, 82, 75, 69, 82, 128, 77, 65, 82, 75, - 45, 52, 128, 77, 65, 82, 75, 45, 51, 128, 77, 65, 82, 75, 45, 50, 128, - 77, 65, 82, 75, 45, 49, 128, 77, 65, 82, 69, 128, 77, 65, 82, 67, 72, 69, - 206, 77, 65, 82, 67, 72, 128, 77, 65, 82, 67, 65, 84, 79, 45, 83, 84, 65, - 67, 67, 65, 84, 79, 128, 77, 65, 82, 67, 65, 84, 79, 128, 77, 65, 82, 67, - 65, 83, 73, 84, 69, 128, 77, 65, 82, 66, 85, 84, 65, 128, 77, 65, 82, 66, - 85, 84, 193, 77, 65, 82, 65, 67, 65, 83, 128, 77, 65, 82, 128, 77, 65, - 81, 65, 70, 128, 77, 65, 81, 128, 77, 65, 80, 76, 197, 77, 65, 80, 73, - 81, 128, 77, 65, 208, 77, 65, 79, 128, 77, 65, 78, 85, 65, 204, 77, 65, - 78, 84, 69, 76, 80, 73, 69, 67, 197, 77, 65, 78, 83, 89, 79, 78, 128, 77, - 65, 78, 83, 85, 65, 69, 128, 77, 65, 78, 78, 65, 218, 77, 65, 78, 78, 65, - 128, 77, 65, 78, 73, 67, 72, 65, 69, 65, 206, 77, 65, 78, 71, 79, 128, - 77, 65, 78, 71, 65, 76, 65, 77, 128, 77, 65, 78, 68, 65, 82, 73, 78, 128, - 77, 65, 78, 68, 65, 73, 76, 73, 78, 199, 77, 65, 78, 68, 65, 73, 195, 77, - 65, 78, 67, 72, 213, 77, 65, 78, 65, 212, 77, 65, 78, 65, 67, 76, 69, 83, - 128, 77, 65, 77, 77, 79, 84, 72, 128, 77, 65, 76, 84, 69, 83, 197, 77, - 65, 76, 207, 77, 65, 76, 69, 69, 82, 73, 128, 77, 65, 76, 197, 77, 65, - 76, 65, 75, 79, 206, 77, 65, 75, 83, 85, 82, 65, 128, 77, 65, 75, 83, 85, - 82, 193, 77, 65, 75, 69, 77, 65, 75, 69, 128, 77, 65, 75, 65, 83, 65, - 210, 77, 65, 73, 90, 69, 128, 77, 65, 73, 89, 65, 77, 79, 75, 128, 77, - 65, 73, 84, 65, 73, 75, 72, 85, 128, 77, 65, 73, 82, 85, 128, 77, 65, 73, - 77, 85, 65, 78, 128, 77, 65, 73, 77, 65, 76, 65, 73, 128, 77, 65, 73, 76, - 66, 79, 216, 77, 65, 73, 75, 85, 82, 79, 128, 77, 65, 73, 68, 69, 78, - 128, 77, 65, 73, 128, 77, 65, 72, 74, 79, 78, 199, 77, 65, 72, 72, 65, - 128, 77, 65, 72, 65, 80, 82, 65, 78, 65, 128, 77, 65, 72, 65, 80, 65, 75, - 72, 128, 77, 65, 72, 65, 74, 65, 78, 201, 77, 65, 72, 65, 65, 80, 82, 65, - 65, 78, 193, 77, 65, 72, 128, 77, 65, 71, 78, 73, 70, 89, 73, 78, 199, - 77, 65, 71, 78, 69, 84, 128, 77, 65, 71, 73, 195, 77, 65, 71, 69, 128, - 77, 65, 69, 83, 73, 128, 77, 65, 69, 78, 89, 73, 128, 77, 65, 69, 78, 74, - 69, 84, 128, 77, 65, 69, 77, 86, 69, 85, 88, 128, 77, 65, 69, 77, 75, 80, - 69, 78, 128, 77, 65, 69, 77, 71, 66, 73, 69, 69, 128, 77, 65, 69, 77, 66, - 71, 66, 73, 69, 69, 128, 77, 65, 69, 77, 66, 65, 128, 77, 65, 69, 77, - 128, 77, 65, 69, 76, 69, 69, 128, 77, 65, 69, 75, 69, 85, 80, 128, 77, - 65, 68, 89, 65, 128, 77, 65, 68, 85, 128, 77, 65, 68, 68, 65, 72, 128, - 77, 65, 68, 68, 65, 200, 77, 65, 68, 68, 65, 128, 77, 65, 68, 68, 193, - 77, 65, 67, 82, 79, 78, 45, 71, 82, 65, 86, 69, 128, 77, 65, 67, 82, 79, - 78, 45, 66, 82, 69, 86, 69, 128, 77, 65, 67, 82, 79, 78, 45, 65, 67, 85, - 84, 69, 128, 77, 65, 67, 82, 79, 78, 128, 77, 65, 67, 82, 79, 206, 77, - 65, 67, 72, 73, 78, 69, 128, 77, 65, 65, 89, 89, 65, 65, 128, 77, 65, 65, - 73, 128, 77, 65, 65, 128, 77, 65, 50, 128, 77, 65, 45, 55, 128, 77, 65, - 45, 54, 128, 77, 65, 45, 53, 128, 77, 65, 45, 52, 128, 77, 65, 45, 51, - 128, 77, 65, 45, 50, 128, 77, 65, 45, 49, 128, 77, 49, 57, 183, 77, 49, - 57, 182, 77, 49, 57, 181, 77, 49, 57, 180, 77, 49, 57, 179, 77, 49, 57, - 178, 77, 49, 57, 177, 77, 49, 57, 176, 77, 49, 56, 185, 77, 49, 56, 184, - 77, 49, 56, 183, 77, 49, 56, 182, 77, 49, 56, 181, 77, 49, 56, 180, 77, - 49, 56, 179, 77, 49, 56, 178, 77, 49, 56, 177, 77, 49, 56, 176, 77, 49, - 55, 185, 77, 49, 55, 184, 77, 49, 55, 183, 77, 49, 55, 182, 77, 49, 55, - 181, 77, 49, 55, 180, 77, 49, 55, 179, 77, 49, 55, 178, 77, 49, 55, 177, - 77, 49, 55, 176, 77, 49, 54, 185, 77, 49, 54, 184, 77, 49, 54, 183, 77, - 49, 54, 182, 77, 49, 54, 181, 77, 49, 54, 180, 77, 49, 54, 179, 77, 49, - 54, 178, 77, 49, 54, 177, 77, 49, 54, 176, 77, 49, 53, 185, 77, 49, 53, - 184, 77, 49, 53, 183, 77, 49, 53, 182, 77, 49, 53, 181, 77, 49, 53, 180, - 77, 49, 53, 179, 77, 49, 53, 178, 77, 49, 53, 177, 77, 49, 53, 176, 77, - 49, 52, 185, 77, 49, 52, 184, 77, 49, 52, 183, 77, 49, 52, 182, 77, 49, - 52, 181, 77, 49, 52, 180, 77, 49, 52, 179, 77, 49, 52, 178, 77, 49, 52, - 177, 77, 49, 52, 176, 77, 49, 51, 185, 77, 49, 51, 184, 77, 49, 51, 183, - 77, 49, 51, 182, 77, 49, 51, 181, 77, 49, 51, 180, 77, 49, 51, 179, 77, - 49, 51, 178, 77, 49, 51, 177, 77, 49, 51, 176, 77, 49, 50, 185, 77, 49, - 50, 184, 77, 49, 50, 183, 77, 49, 50, 182, 77, 49, 50, 181, 77, 49, 50, - 180, 77, 49, 50, 179, 77, 49, 50, 178, 77, 49, 50, 177, 77, 49, 50, 176, - 77, 49, 49, 185, 77, 49, 49, 184, 77, 49, 49, 183, 77, 49, 49, 182, 77, - 49, 49, 181, 77, 49, 49, 180, 77, 49, 49, 179, 77, 49, 49, 178, 77, 49, - 49, 177, 77, 49, 49, 176, 77, 49, 48, 185, 77, 49, 48, 184, 77, 49, 48, - 183, 77, 49, 48, 182, 77, 49, 48, 181, 77, 49, 48, 180, 77, 49, 48, 179, - 77, 49, 48, 178, 77, 49, 48, 177, 77, 49, 48, 176, 77, 48, 57, 185, 77, - 48, 57, 184, 77, 48, 57, 183, 77, 48, 57, 182, 77, 48, 57, 181, 77, 48, - 57, 180, 77, 48, 57, 179, 77, 48, 57, 178, 77, 48, 57, 177, 77, 48, 57, - 176, 77, 48, 56, 185, 77, 48, 56, 184, 77, 48, 56, 183, 77, 48, 56, 182, - 77, 48, 56, 181, 77, 48, 56, 180, 77, 48, 56, 179, 77, 48, 56, 178, 77, - 48, 56, 177, 77, 48, 56, 176, 77, 48, 55, 185, 77, 48, 55, 184, 77, 48, - 55, 183, 77, 48, 55, 182, 77, 48, 55, 181, 77, 48, 55, 180, 77, 48, 55, - 179, 77, 48, 55, 178, 77, 48, 55, 177, 77, 48, 55, 176, 77, 48, 54, 185, - 77, 48, 54, 184, 77, 48, 54, 183, 77, 48, 54, 182, 77, 48, 54, 181, 77, - 48, 54, 180, 77, 48, 54, 179, 77, 48, 54, 178, 77, 48, 54, 177, 77, 48, - 54, 176, 77, 48, 53, 185, 77, 48, 53, 184, 77, 48, 53, 183, 77, 48, 53, - 182, 77, 48, 53, 181, 77, 48, 53, 180, 77, 48, 53, 179, 77, 48, 53, 178, - 77, 48, 53, 177, 77, 48, 53, 176, 77, 48, 52, 185, 77, 48, 52, 184, 77, - 48, 52, 183, 77, 48, 52, 182, 77, 48, 52, 181, 77, 48, 52, 52, 128, 77, - 48, 52, 180, 77, 48, 52, 51, 128, 77, 48, 52, 179, 77, 48, 52, 50, 128, - 77, 48, 52, 178, 77, 48, 52, 49, 128, 77, 48, 52, 177, 77, 48, 52, 48, - 65, 128, 77, 48, 52, 48, 128, 77, 48, 52, 176, 77, 48, 51, 57, 128, 77, - 48, 51, 185, 77, 48, 51, 56, 128, 77, 48, 51, 184, 77, 48, 51, 55, 128, - 77, 48, 51, 183, 77, 48, 51, 54, 128, 77, 48, 51, 182, 77, 48, 51, 53, - 128, 77, 48, 51, 181, 77, 48, 51, 52, 128, 77, 48, 51, 180, 77, 48, 51, - 51, 66, 128, 77, 48, 51, 51, 65, 128, 77, 48, 51, 51, 128, 77, 48, 51, - 179, 77, 48, 51, 50, 128, 77, 48, 51, 178, 77, 48, 51, 49, 65, 128, 77, - 48, 51, 49, 128, 77, 48, 51, 177, 77, 48, 51, 48, 128, 77, 48, 51, 176, - 77, 48, 50, 57, 128, 77, 48, 50, 185, 77, 48, 50, 56, 65, 128, 77, 48, - 50, 56, 128, 77, 48, 50, 184, 77, 48, 50, 55, 128, 77, 48, 50, 183, 77, - 48, 50, 54, 128, 77, 48, 50, 182, 77, 48, 50, 53, 128, 77, 48, 50, 181, - 77, 48, 50, 52, 65, 128, 77, 48, 50, 52, 128, 77, 48, 50, 180, 77, 48, - 50, 51, 128, 77, 48, 50, 179, 77, 48, 50, 50, 65, 128, 77, 48, 50, 50, - 128, 77, 48, 50, 178, 77, 48, 50, 49, 128, 77, 48, 50, 177, 77, 48, 50, - 48, 128, 77, 48, 50, 176, 77, 48, 49, 57, 128, 77, 48, 49, 185, 77, 48, - 49, 56, 128, 77, 48, 49, 184, 77, 48, 49, 55, 65, 128, 77, 48, 49, 55, - 128, 77, 48, 49, 183, 77, 48, 49, 54, 65, 128, 77, 48, 49, 54, 128, 77, - 48, 49, 182, 77, 48, 49, 53, 65, 128, 77, 48, 49, 53, 128, 77, 48, 49, - 181, 77, 48, 49, 52, 128, 77, 48, 49, 180, 77, 48, 49, 51, 128, 77, 48, - 49, 179, 77, 48, 49, 50, 72, 128, 77, 48, 49, 50, 71, 128, 77, 48, 49, - 50, 70, 128, 77, 48, 49, 50, 69, 128, 77, 48, 49, 50, 68, 128, 77, 48, - 49, 50, 67, 128, 77, 48, 49, 50, 66, 128, 77, 48, 49, 50, 65, 128, 77, - 48, 49, 50, 128, 77, 48, 49, 178, 77, 48, 49, 49, 128, 77, 48, 49, 177, - 77, 48, 49, 48, 65, 128, 77, 48, 49, 48, 128, 77, 48, 49, 176, 77, 48, - 48, 57, 128, 77, 48, 48, 185, 77, 48, 48, 56, 128, 77, 48, 48, 184, 77, - 48, 48, 55, 128, 77, 48, 48, 183, 77, 48, 48, 54, 128, 77, 48, 48, 182, - 77, 48, 48, 53, 128, 77, 48, 48, 181, 77, 48, 48, 52, 128, 77, 48, 48, - 180, 77, 48, 48, 51, 65, 128, 77, 48, 48, 51, 128, 77, 48, 48, 179, 77, - 48, 48, 50, 128, 77, 48, 48, 178, 77, 48, 48, 49, 66, 128, 77, 48, 48, - 49, 65, 128, 77, 48, 48, 49, 128, 77, 48, 48, 177, 76, 218, 76, 89, 89, - 128, 76, 89, 88, 128, 76, 89, 84, 128, 76, 89, 82, 88, 128, 76, 89, 82, - 128, 76, 89, 80, 128, 76, 89, 73, 84, 128, 76, 89, 73, 78, 199, 76, 89, - 68, 73, 65, 206, 76, 89, 67, 73, 65, 206, 76, 88, 128, 76, 87, 79, 79, - 128, 76, 87, 79, 128, 76, 87, 73, 73, 128, 76, 87, 73, 128, 76, 87, 69, - 128, 76, 87, 65, 65, 128, 76, 87, 65, 128, 76, 85, 88, 128, 76, 85, 85, - 128, 76, 85, 84, 128, 76, 85, 82, 88, 128, 76, 85, 80, 128, 76, 85, 79, - 88, 128, 76, 85, 79, 84, 128, 76, 85, 79, 80, 128, 76, 85, 79, 128, 76, - 85, 78, 71, 83, 73, 128, 76, 85, 78, 71, 83, 128, 76, 85, 78, 65, 84, - 197, 76, 85, 78, 65, 210, 76, 85, 205, 76, 85, 76, 128, 76, 85, 73, 83, - 128, 76, 85, 72, 85, 82, 128, 76, 85, 72, 128, 76, 85, 200, 76, 85, 71, - 71, 65, 71, 69, 128, 76, 85, 71, 65, 76, 128, 76, 85, 71, 65, 204, 76, - 85, 69, 128, 76, 85, 197, 76, 85, 66, 128, 76, 85, 65, 69, 80, 128, 76, - 85, 51, 128, 76, 85, 50, 128, 76, 85, 178, 76, 82, 79, 128, 76, 82, 77, - 128, 76, 82, 73, 128, 76, 82, 69, 128, 76, 79, 90, 69, 78, 71, 69, 128, - 76, 79, 90, 69, 78, 71, 197, 76, 79, 88, 128, 76, 79, 87, 69, 82, 69, - 196, 76, 79, 87, 45, 82, 69, 86, 69, 82, 83, 69, 68, 45, 185, 76, 79, 87, - 45, 77, 73, 196, 76, 79, 87, 45, 70, 65, 76, 76, 73, 78, 199, 76, 79, 87, - 45, 185, 76, 79, 86, 197, 76, 79, 85, 82, 69, 128, 76, 79, 85, 68, 83, - 80, 69, 65, 75, 69, 82, 128, 76, 79, 85, 68, 76, 217, 76, 79, 84, 85, 83, - 128, 76, 79, 84, 85, 211, 76, 79, 84, 73, 79, 206, 76, 79, 84, 128, 76, - 79, 83, 212, 76, 79, 83, 83, 76, 69, 83, 83, 128, 76, 79, 82, 82, 89, - 128, 76, 79, 82, 82, 65, 73, 78, 69, 128, 76, 79, 81, 128, 76, 79, 80, - 128, 76, 79, 79, 84, 128, 76, 79, 79, 80, 69, 196, 76, 79, 79, 80, 128, - 76, 79, 79, 208, 76, 79, 79, 78, 128, 76, 79, 79, 203, 76, 79, 79, 128, - 76, 79, 78, 83, 85, 77, 128, 76, 79, 78, 71, 65, 128, 76, 79, 78, 71, - 193, 76, 79, 78, 71, 45, 76, 69, 71, 71, 69, 196, 76, 79, 78, 71, 45, 66, - 82, 65, 78, 67, 72, 45, 89, 82, 128, 76, 79, 78, 71, 45, 66, 82, 65, 78, - 67, 72, 45, 83, 79, 204, 76, 79, 78, 71, 45, 66, 82, 65, 78, 67, 72, 45, - 79, 83, 211, 76, 79, 78, 71, 45, 66, 82, 65, 78, 67, 72, 45, 77, 65, 68, - 210, 76, 79, 78, 71, 45, 66, 82, 65, 78, 67, 72, 45, 72, 65, 71, 65, 76, - 204, 76, 79, 78, 71, 45, 66, 82, 65, 78, 67, 72, 45, 65, 210, 76, 79, 77, - 77, 65, 69, 128, 76, 79, 77, 75, 65, 128, 76, 79, 77, 128, 76, 79, 205, - 76, 79, 76, 76, 73, 80, 79, 80, 128, 76, 79, 76, 76, 128, 76, 79, 71, - 210, 76, 79, 71, 79, 84, 89, 80, 197, 76, 79, 71, 79, 71, 82, 65, 205, - 76, 79, 71, 128, 76, 79, 68, 69, 83, 84, 79, 78, 69, 128, 76, 79, 67, 79, - 77, 79, 84, 73, 86, 69, 128, 76, 79, 67, 75, 73, 78, 71, 45, 83, 72, 73, - 70, 212, 76, 79, 67, 65, 84, 73, 86, 69, 128, 76, 79, 67, 65, 84, 73, 79, - 78, 45, 87, 65, 76, 76, 80, 76, 65, 78, 197, 76, 79, 67, 65, 84, 73, 79, - 78, 45, 70, 76, 79, 79, 82, 80, 76, 65, 78, 197, 76, 79, 67, 65, 84, 73, - 79, 78, 128, 76, 79, 67, 65, 84, 73, 79, 206, 76, 79, 66, 83, 84, 69, 82, - 128, 76, 79, 65, 128, 76, 78, 128, 76, 76, 85, 85, 128, 76, 76, 79, 79, - 128, 76, 76, 76, 85, 85, 128, 76, 76, 76, 85, 128, 76, 76, 76, 79, 79, - 128, 76, 76, 76, 79, 128, 76, 76, 76, 73, 73, 128, 76, 76, 76, 73, 128, - 76, 76, 76, 69, 69, 128, 76, 76, 76, 69, 128, 76, 76, 76, 65, 85, 128, - 76, 76, 76, 65, 73, 128, 76, 76, 76, 65, 65, 128, 76, 76, 76, 65, 128, - 76, 76, 76, 128, 76, 76, 72, 65, 128, 76, 76, 65, 77, 65, 128, 76, 74, - 85, 68, 73, 74, 69, 128, 76, 74, 69, 128, 76, 74, 128, 76, 73, 90, 65, - 82, 68, 128, 76, 73, 88, 128, 76, 73, 87, 78, 128, 76, 73, 86, 82, 197, - 76, 73, 84, 84, 76, 69, 128, 76, 73, 84, 84, 76, 197, 76, 73, 84, 84, 69, - 210, 76, 73, 84, 82, 193, 76, 73, 84, 200, 76, 73, 83, 213, 76, 73, 83, - 128, 76, 73, 82, 193, 76, 73, 81, 85, 73, 68, 128, 76, 73, 81, 85, 73, - 196, 76, 73, 81, 128, 76, 73, 80, 83, 84, 73, 67, 75, 128, 76, 73, 80, - 211, 76, 73, 208, 76, 73, 78, 75, 73, 78, 199, 76, 73, 78, 75, 69, 196, - 76, 73, 78, 203, 76, 73, 78, 71, 83, 65, 128, 76, 73, 78, 69, 83, 128, - 76, 73, 78, 69, 211, 76, 73, 78, 69, 45, 57, 128, 76, 73, 78, 69, 45, 55, - 128, 76, 73, 78, 69, 45, 51, 128, 76, 73, 78, 69, 45, 49, 128, 76, 73, - 77, 77, 85, 52, 128, 76, 73, 77, 77, 85, 50, 128, 76, 73, 77, 77, 85, - 128, 76, 73, 77, 77, 213, 76, 73, 77, 73, 84, 69, 196, 76, 73, 77, 73, - 84, 65, 84, 73, 79, 78, 128, 76, 73, 77, 73, 84, 128, 76, 73, 77, 69, - 128, 76, 73, 77, 66, 213, 76, 73, 77, 66, 211, 76, 73, 77, 194, 76, 73, - 76, 89, 128, 76, 73, 76, 73, 84, 72, 128, 76, 73, 76, 128, 76, 73, 71, - 72, 84, 78, 73, 78, 71, 128, 76, 73, 71, 72, 84, 78, 73, 78, 199, 76, 73, - 71, 72, 84, 72, 79, 85, 83, 69, 128, 76, 73, 71, 72, 84, 128, 76, 73, 71, - 65, 84, 73, 78, 199, 76, 73, 70, 84, 69, 82, 128, 76, 73, 70, 69, 128, - 76, 73, 69, 88, 128, 76, 73, 69, 84, 128, 76, 73, 69, 80, 128, 76, 73, - 69, 69, 128, 76, 73, 69, 128, 76, 73, 68, 128, 76, 73, 67, 75, 73, 78, - 199, 76, 73, 66, 82, 65, 128, 76, 73, 66, 69, 82, 84, 89, 128, 76, 73, - 65, 66, 73, 76, 73, 84, 217, 76, 72, 73, 73, 128, 76, 72, 65, 86, 73, 89, - 65, 78, 73, 128, 76, 72, 65, 199, 76, 72, 65, 65, 128, 76, 72, 128, 76, - 69, 90, 72, 128, 76, 69, 90, 200, 76, 69, 88, 128, 76, 69, 86, 73, 84, - 65, 84, 73, 78, 71, 128, 76, 69, 86, 69, 76, 45, 51, 128, 76, 69, 86, 69, - 76, 45, 50, 128, 76, 69, 85, 77, 128, 76, 69, 85, 65, 69, 80, 128, 76, - 69, 85, 65, 69, 77, 128, 76, 69, 85, 128, 76, 69, 213, 76, 69, 84, 84, - 69, 82, 83, 128, 76, 69, 84, 84, 69, 82, 128, 76, 69, 212, 76, 69, 83, - 83, 69, 210, 76, 69, 83, 83, 45, 84, 72, 65, 78, 128, 76, 69, 83, 83, 45, - 84, 72, 65, 206, 76, 69, 83, 72, 128, 76, 69, 80, 67, 72, 193, 76, 69, - 80, 128, 76, 69, 79, 80, 65, 82, 68, 128, 76, 69, 79, 128, 76, 69, 78, - 84, 73, 67, 85, 76, 65, 210, 76, 69, 78, 73, 83, 128, 76, 69, 78, 73, - 211, 76, 69, 78, 71, 84, 72, 69, 78, 69, 82, 128, 76, 69, 78, 71, 84, 72, - 45, 55, 128, 76, 69, 78, 71, 84, 72, 45, 54, 128, 76, 69, 78, 71, 84, 72, - 45, 53, 128, 76, 69, 78, 71, 84, 72, 45, 52, 128, 76, 69, 78, 71, 84, 72, - 45, 51, 128, 76, 69, 78, 71, 84, 72, 45, 50, 128, 76, 69, 78, 71, 84, 72, - 45, 49, 128, 76, 69, 78, 71, 84, 200, 76, 69, 78, 71, 65, 128, 76, 69, - 78, 71, 193, 76, 69, 77, 79, 78, 128, 76, 69, 77, 79, 73, 128, 76, 69, - 76, 69, 84, 128, 76, 69, 76, 69, 212, 76, 69, 203, 76, 69, 73, 77, 77, - 65, 128, 76, 69, 73, 77, 77, 193, 76, 69, 73, 128, 76, 69, 71, 83, 128, - 76, 69, 71, 73, 79, 78, 128, 76, 69, 71, 69, 84, 79, 211, 76, 69, 71, - 128, 76, 69, 199, 76, 69, 70, 84, 87, 65, 82, 68, 83, 128, 76, 69, 70, - 84, 45, 84, 79, 45, 82, 73, 71, 72, 212, 76, 69, 70, 84, 45, 83, 84, 69, - 205, 76, 69, 70, 84, 45, 83, 73, 68, 197, 76, 69, 70, 84, 45, 83, 72, 65, - 68, 69, 196, 76, 69, 70, 84, 45, 80, 79, 73, 78, 84, 73, 78, 199, 76, 69, - 70, 84, 45, 76, 73, 71, 72, 84, 69, 196, 76, 69, 70, 84, 45, 72, 65, 78, - 68, 69, 196, 76, 69, 70, 84, 45, 72, 65, 78, 196, 76, 69, 70, 84, 45, 70, - 65, 67, 73, 78, 199, 76, 69, 70, 84, 128, 76, 69, 69, 82, 65, 69, 87, 65, - 128, 76, 69, 69, 75, 128, 76, 69, 69, 69, 69, 128, 76, 69, 68, 71, 69, - 82, 128, 76, 69, 65, 84, 72, 69, 82, 128, 76, 69, 65, 78, 73, 78, 199, - 76, 69, 65, 70, 217, 76, 69, 65, 70, 128, 76, 69, 65, 198, 76, 69, 65, - 68, 69, 82, 128, 76, 69, 65, 196, 76, 68, 65, 78, 128, 76, 68, 50, 128, - 76, 67, 201, 76, 67, 197, 76, 65, 90, 217, 76, 65, 89, 65, 78, 78, 65, - 128, 76, 65, 88, 128, 76, 65, 87, 128, 76, 65, 215, 76, 65, 85, 76, 65, - 128, 76, 65, 85, 75, 65, 218, 76, 65, 85, 74, 128, 76, 65, 85, 71, 72, - 73, 78, 71, 128, 76, 65, 84, 73, 78, 65, 84, 197, 76, 65, 84, 73, 75, - 128, 76, 65, 84, 69, 82, 65, 204, 76, 65, 84, 197, 76, 65, 83, 212, 76, - 65, 82, 89, 78, 71, 69, 65, 204, 76, 65, 82, 201, 76, 65, 82, 71, 69, 83, - 84, 128, 76, 65, 82, 71, 69, 210, 76, 65, 82, 71, 69, 128, 76, 65, 82, - 71, 197, 76, 65, 81, 128, 76, 65, 80, 65, 81, 128, 76, 65, 207, 76, 65, - 78, 84, 69, 82, 78, 128, 76, 65, 78, 84, 65, 78, 71, 128, 76, 65, 78, 71, - 85, 65, 71, 197, 76, 65, 78, 69, 83, 128, 76, 65, 78, 196, 76, 65, 78, - 128, 76, 65, 77, 80, 128, 76, 65, 77, 69, 68, 72, 128, 76, 65, 77, 69, - 68, 128, 76, 65, 77, 69, 196, 76, 65, 77, 69, 128, 76, 65, 77, 197, 76, - 65, 77, 68, 65, 128, 76, 65, 77, 68, 128, 76, 65, 77, 66, 68, 193, 76, - 65, 77, 65, 68, 72, 128, 76, 65, 76, 128, 76, 65, 204, 76, 65, 75, 75, - 72, 65, 78, 71, 89, 65, 79, 128, 76, 65, 75, 72, 65, 78, 128, 76, 65, 75, - 72, 128, 76, 65, 75, 200, 76, 65, 75, 45, 55, 52, 57, 128, 76, 65, 75, - 45, 55, 50, 52, 128, 76, 65, 75, 45, 54, 54, 56, 128, 76, 65, 75, 45, 54, - 52, 56, 128, 76, 65, 75, 45, 54, 52, 184, 76, 65, 75, 45, 54, 51, 54, - 128, 76, 65, 75, 45, 54, 49, 55, 128, 76, 65, 75, 45, 54, 49, 183, 76, - 65, 75, 45, 54, 48, 56, 128, 76, 65, 75, 45, 53, 53, 48, 128, 76, 65, 75, - 45, 52, 57, 53, 128, 76, 65, 75, 45, 52, 57, 51, 128, 76, 65, 75, 45, 52, - 57, 50, 128, 76, 65, 75, 45, 52, 57, 48, 128, 76, 65, 75, 45, 52, 56, 51, - 128, 76, 65, 75, 45, 52, 55, 48, 128, 76, 65, 75, 45, 52, 53, 55, 128, - 76, 65, 75, 45, 52, 53, 48, 128, 76, 65, 75, 45, 52, 52, 57, 128, 76, 65, - 75, 45, 52, 52, 185, 76, 65, 75, 45, 52, 52, 49, 128, 76, 65, 75, 45, 51, - 57, 48, 128, 76, 65, 75, 45, 51, 56, 52, 128, 76, 65, 75, 45, 51, 56, 51, - 128, 76, 65, 75, 45, 51, 52, 56, 128, 76, 65, 75, 45, 51, 52, 55, 128, - 76, 65, 75, 45, 51, 52, 51, 128, 76, 65, 75, 45, 50, 54, 54, 128, 76, 65, - 75, 45, 50, 54, 53, 128, 76, 65, 75, 45, 50, 51, 56, 128, 76, 65, 75, 45, - 50, 50, 56, 128, 76, 65, 75, 45, 50, 50, 53, 128, 76, 65, 75, 45, 50, 50, - 48, 128, 76, 65, 75, 45, 50, 49, 57, 128, 76, 65, 75, 45, 50, 49, 48, - 128, 76, 65, 75, 45, 49, 52, 50, 128, 76, 65, 75, 45, 49, 51, 48, 128, - 76, 65, 75, 45, 48, 57, 50, 128, 76, 65, 75, 45, 48, 56, 49, 128, 76, 65, - 75, 45, 48, 56, 177, 76, 65, 75, 45, 48, 56, 48, 128, 76, 65, 75, 45, 48, - 55, 185, 76, 65, 75, 45, 48, 54, 50, 128, 76, 65, 75, 45, 48, 53, 49, - 128, 76, 65, 75, 45, 48, 53, 48, 128, 76, 65, 75, 45, 48, 51, 48, 128, - 76, 65, 75, 45, 48, 50, 53, 128, 76, 65, 75, 45, 48, 50, 49, 128, 76, 65, - 75, 45, 48, 50, 48, 128, 76, 65, 75, 45, 48, 48, 51, 128, 76, 65, 74, 65, - 78, 89, 65, 76, 65, 78, 128, 76, 65, 73, 78, 199, 76, 65, 201, 76, 65, - 72, 83, 72, 85, 128, 76, 65, 72, 128, 76, 65, 71, 85, 83, 128, 76, 65, - 71, 213, 76, 65, 71, 65, 82, 128, 76, 65, 71, 65, 210, 76, 65, 71, 65, - 66, 128, 76, 65, 71, 65, 194, 76, 65, 69, 86, 128, 76, 65, 69, 128, 76, - 65, 68, 217, 76, 65, 68, 68, 69, 82, 128, 76, 65, 67, 82, 79, 83, 83, - 197, 76, 65, 67, 75, 128, 76, 65, 67, 65, 128, 76, 65, 66, 79, 85, 82, - 73, 78, 71, 128, 76, 65, 66, 79, 82, 128, 76, 65, 66, 73, 65, 76, 73, 90, - 65, 84, 73, 79, 206, 76, 65, 66, 73, 65, 204, 76, 65, 66, 69, 76, 128, - 76, 65, 66, 65, 84, 128, 76, 65, 194, 76, 65, 65, 78, 65, 69, 128, 76, - 65, 65, 78, 128, 76, 65, 65, 77, 85, 128, 76, 65, 65, 73, 128, 76, 54, - 128, 76, 52, 128, 76, 51, 128, 76, 50, 128, 76, 48, 48, 54, 65, 128, 76, - 48, 48, 50, 65, 128, 76, 45, 84, 89, 80, 197, 76, 45, 83, 72, 65, 80, 69, - 196, 75, 89, 85, 82, 73, 73, 128, 75, 89, 85, 128, 75, 89, 79, 128, 75, - 89, 76, 73, 83, 77, 65, 128, 75, 89, 73, 128, 75, 89, 69, 128, 75, 89, - 65, 84, 72, 79, 211, 75, 89, 65, 65, 128, 75, 89, 65, 128, 75, 88, 87, - 73, 128, 75, 88, 87, 69, 69, 128, 75, 88, 87, 69, 128, 75, 88, 87, 65, - 65, 128, 75, 88, 87, 65, 128, 75, 88, 85, 128, 75, 88, 79, 128, 75, 88, - 73, 128, 75, 88, 69, 69, 128, 75, 88, 69, 128, 75, 88, 65, 65, 128, 75, - 88, 65, 128, 75, 87, 86, 128, 75, 87, 85, 51, 49, 56, 128, 75, 87, 79, - 79, 128, 75, 87, 79, 128, 75, 87, 77, 128, 75, 87, 73, 73, 128, 75, 87, - 73, 128, 75, 87, 69, 69, 128, 75, 87, 69, 128, 75, 87, 66, 128, 75, 87, - 65, 89, 128, 75, 87, 65, 69, 84, 128, 75, 87, 65, 65, 128, 75, 86, 65, - 128, 75, 86, 128, 75, 85, 90, 72, 73, 128, 75, 85, 88, 128, 75, 85, 86, - 128, 75, 85, 85, 72, 128, 75, 85, 84, 128, 75, 85, 83, 77, 65, 128, 75, - 85, 83, 72, 85, 50, 128, 75, 85, 83, 72, 85, 178, 75, 85, 82, 88, 128, - 75, 85, 82, 85, 90, 69, 73, 82, 79, 128, 75, 85, 82, 84, 128, 75, 85, 82, - 79, 79, 78, 69, 128, 75, 85, 82, 128, 75, 85, 210, 75, 85, 81, 128, 75, - 85, 80, 78, 65, 89, 65, 128, 75, 85, 79, 88, 128, 75, 85, 79, 80, 128, - 75, 85, 79, 208, 75, 85, 79, 77, 128, 75, 85, 79, 128, 75, 85, 78, 71, - 128, 75, 85, 78, 68, 68, 65, 76, 73, 89, 65, 128, 75, 85, 76, 128, 75, - 85, 204, 75, 85, 71, 128, 75, 85, 70, 73, 83, 77, 65, 128, 75, 85, 69, - 84, 128, 75, 85, 66, 128, 75, 85, 65, 86, 128, 75, 85, 65, 66, 128, 75, - 85, 65, 128, 75, 85, 55, 128, 75, 85, 52, 128, 75, 85, 180, 75, 85, 51, - 128, 75, 85, 179, 75, 85, 45, 55, 128, 75, 85, 45, 54, 128, 75, 85, 45, - 53, 128, 75, 85, 45, 52, 128, 75, 85, 45, 51, 128, 75, 85, 45, 50, 128, - 75, 85, 45, 49, 128, 75, 84, 128, 75, 83, 83, 85, 85, 128, 75, 83, 83, - 85, 128, 75, 83, 83, 79, 79, 128, 75, 83, 83, 79, 128, 75, 83, 83, 73, - 73, 128, 75, 83, 83, 73, 128, 75, 83, 83, 69, 69, 128, 75, 83, 83, 69, - 128, 75, 83, 83, 65, 85, 128, 75, 83, 83, 65, 73, 128, 75, 83, 83, 65, - 65, 128, 75, 83, 83, 65, 128, 75, 83, 83, 128, 75, 83, 73, 128, 75, 82, - 89, 90, 72, 69, 86, 65, 89, 65, 128, 75, 82, 89, 90, 72, 69, 77, 128, 75, - 82, 89, 90, 72, 69, 205, 75, 82, 89, 90, 72, 128, 75, 82, 89, 90, 200, - 75, 82, 89, 85, 75, 79, 86, 65, 89, 65, 128, 75, 82, 89, 85, 75, 79, 86, - 65, 89, 193, 75, 82, 89, 85, 75, 128, 75, 82, 89, 85, 203, 75, 82, 79, - 78, 79, 83, 128, 75, 82, 69, 77, 65, 83, 84, 73, 128, 75, 82, 65, 84, 73, - 77, 79, 89, 80, 79, 82, 82, 79, 79, 78, 128, 75, 82, 65, 84, 73, 77, 79, - 75, 79, 85, 70, 73, 83, 77, 65, 128, 75, 82, 65, 84, 73, 77, 65, 84, 65, - 128, 75, 82, 65, 84, 73, 77, 193, 75, 80, 85, 128, 75, 80, 79, 81, 128, - 75, 80, 79, 79, 128, 75, 80, 79, 128, 75, 80, 73, 128, 75, 80, 69, 85, - 88, 128, 75, 80, 69, 69, 128, 75, 80, 69, 128, 75, 80, 65, 82, 65, 81, - 128, 75, 80, 65, 78, 128, 75, 80, 65, 72, 128, 75, 80, 65, 128, 75, 80, - 128, 75, 79, 88, 128, 75, 79, 86, 85, 85, 128, 75, 79, 86, 128, 75, 79, - 84, 79, 128, 75, 79, 82, 85, 78, 65, 128, 75, 79, 82, 79, 78, 73, 83, - 128, 75, 79, 82, 79, 78, 128, 75, 79, 82, 69, 65, 206, 75, 79, 82, 65, - 78, 73, 195, 75, 79, 81, 78, 68, 79, 78, 128, 75, 79, 80, 80, 65, 128, - 75, 79, 80, 128, 75, 79, 79, 86, 128, 75, 79, 79, 80, 79, 128, 75, 79, - 79, 77, 85, 85, 84, 128, 75, 79, 79, 66, 128, 75, 79, 79, 128, 75, 79, - 78, 84, 69, 86, 77, 65, 128, 75, 79, 78, 84, 69, 86, 77, 193, 75, 79, 77, - 201, 75, 79, 77, 66, 85, 86, 65, 128, 75, 79, 77, 66, 85, 86, 193, 75, - 79, 77, 66, 213, 75, 79, 75, 79, 128, 75, 79, 75, 69, 128, 75, 79, 75, - 128, 75, 79, 203, 75, 79, 73, 78, 73, 128, 75, 79, 73, 128, 75, 79, 201, - 75, 79, 72, 128, 75, 79, 71, 72, 79, 77, 128, 75, 79, 69, 84, 128, 75, - 79, 66, 89, 76, 65, 128, 75, 79, 66, 128, 75, 79, 65, 76, 65, 128, 75, - 79, 65, 128, 75, 79, 45, 75, 73, 128, 75, 79, 45, 51, 128, 75, 79, 45, - 50, 128, 75, 79, 45, 49, 128, 75, 78, 85, 67, 75, 76, 69, 83, 128, 75, - 78, 85, 67, 75, 76, 69, 128, 75, 78, 79, 84, 128, 75, 78, 79, 66, 83, - 128, 75, 78, 73, 71, 72, 84, 45, 82, 79, 79, 75, 128, 75, 78, 73, 71, 72, - 84, 45, 81, 85, 69, 69, 78, 128, 75, 78, 73, 71, 72, 84, 45, 66, 73, 83, - 72, 79, 80, 128, 75, 78, 73, 71, 72, 84, 128, 75, 78, 73, 71, 72, 212, - 75, 78, 73, 70, 69, 128, 75, 78, 73, 70, 197, 75, 78, 69, 69, 76, 73, 78, - 199, 75, 77, 128, 75, 205, 75, 76, 89, 85, 67, 72, 69, 86, 79, 89, 128, - 75, 76, 89, 85, 67, 72, 69, 86, 65, 89, 65, 128, 75, 76, 89, 85, 67, 72, - 69, 86, 65, 89, 193, 75, 76, 89, 85, 67, 72, 69, 80, 79, 86, 79, 68, 78, - 89, 128, 75, 76, 89, 85, 67, 72, 69, 80, 79, 86, 79, 68, 78, 65, 89, 65, - 128, 75, 76, 89, 85, 67, 72, 69, 78, 69, 80, 79, 83, 84, 79, 89, 65, 78, - 78, 89, 128, 75, 76, 89, 85, 67, 72, 69, 78, 69, 80, 79, 83, 84, 79, 89, - 65, 78, 78, 65, 89, 65, 128, 75, 76, 89, 85, 67, 72, 128, 75, 76, 73, 84, - 79, 78, 128, 75, 76, 65, 83, 77, 65, 128, 75, 76, 65, 83, 77, 193, 75, - 76, 65, 128, 75, 76, 128, 75, 75, 79, 128, 75, 75, 73, 128, 75, 75, 69, - 69, 128, 75, 75, 69, 128, 75, 75, 65, 128, 75, 75, 128, 75, 74, 69, 128, - 75, 73, 89, 69, 79, 75, 45, 84, 73, 75, 69, 85, 84, 128, 75, 73, 89, 69, - 79, 75, 45, 83, 73, 79, 83, 45, 75, 73, 89, 69, 79, 75, 128, 75, 73, 89, - 69, 79, 75, 45, 82, 73, 69, 85, 76, 128, 75, 73, 89, 69, 79, 75, 45, 80, - 73, 69, 85, 80, 128, 75, 73, 89, 69, 79, 75, 45, 78, 73, 69, 85, 78, 128, - 75, 73, 89, 69, 79, 75, 45, 75, 72, 73, 69, 85, 75, 72, 128, 75, 73, 89, - 69, 79, 75, 45, 67, 72, 73, 69, 85, 67, 72, 128, 75, 73, 89, 69, 79, 203, - 75, 73, 88, 128, 75, 73, 87, 73, 70, 82, 85, 73, 84, 128, 75, 73, 87, - 128, 75, 73, 86, 128, 75, 73, 84, 69, 128, 75, 73, 84, 128, 75, 73, 83, - 83, 73, 78, 199, 75, 73, 83, 83, 128, 75, 73, 83, 211, 75, 73, 83, 73, - 77, 53, 128, 75, 73, 83, 73, 77, 181, 75, 73, 83, 72, 128, 75, 73, 83, - 65, 76, 128, 75, 73, 82, 79, 87, 65, 84, 84, 79, 128, 75, 73, 82, 79, 77, - 69, 69, 84, 79, 82, 85, 128, 75, 73, 82, 79, 71, 85, 82, 65, 77, 85, 128, - 75, 73, 82, 79, 128, 75, 73, 82, 71, 72, 73, 218, 75, 73, 81, 128, 75, - 73, 80, 128, 75, 73, 208, 75, 73, 78, 83, 72, 73, 80, 128, 75, 73, 78, - 78, 193, 75, 73, 78, 68, 69, 82, 71, 65, 82, 84, 69, 78, 128, 75, 73, 77, - 79, 78, 79, 128, 75, 73, 76, 76, 69, 82, 128, 75, 73, 73, 90, 72, 128, - 75, 73, 73, 128, 75, 73, 72, 128, 75, 73, 69, 88, 128, 75, 73, 69, 86, - 65, 206, 75, 73, 69, 80, 128, 75, 73, 69, 69, 77, 128, 75, 73, 69, 128, - 75, 73, 68, 128, 75, 73, 196, 75, 73, 67, 75, 128, 75, 73, 66, 128, 75, - 73, 65, 86, 128, 75, 73, 65, 66, 128, 75, 73, 45, 56, 128, 75, 73, 45, - 55, 128, 75, 73, 45, 54, 128, 75, 73, 45, 53, 128, 75, 73, 45, 52, 128, - 75, 73, 45, 51, 128, 75, 73, 45, 50, 128, 75, 73, 45, 49, 128, 75, 72, - 90, 128, 75, 72, 87, 65, 73, 128, 75, 72, 85, 69, 78, 45, 76, 85, 197, - 75, 72, 85, 69, 206, 75, 72, 85, 68, 65, 87, 65, 68, 201, 75, 72, 85, 68, - 65, 77, 128, 75, 72, 85, 65, 84, 128, 75, 72, 79, 85, 128, 75, 72, 79, - 212, 75, 72, 79, 78, 78, 65, 128, 75, 72, 79, 78, 128, 75, 72, 79, 77, - 85, 84, 128, 75, 72, 79, 75, 72, 76, 79, 205, 75, 72, 79, 74, 75, 201, - 75, 72, 79, 128, 75, 72, 207, 75, 72, 77, 213, 75, 72, 73, 84, 128, 75, - 72, 73, 78, 89, 65, 128, 75, 72, 73, 69, 85, 75, 200, 75, 72, 73, 128, - 75, 72, 201, 75, 72, 72, 79, 128, 75, 72, 72, 65, 128, 75, 72, 69, 84, - 72, 128, 75, 72, 69, 73, 128, 75, 72, 69, 69, 128, 75, 72, 69, 128, 75, - 72, 65, 86, 128, 75, 72, 65, 82, 79, 83, 72, 84, 72, 201, 75, 72, 65, 82, - 128, 75, 72, 65, 80, 72, 128, 75, 72, 65, 78, 199, 75, 72, 65, 78, 68, - 65, 128, 75, 72, 65, 78, 68, 193, 75, 72, 65, 77, 84, 201, 75, 72, 65, - 77, 73, 76, 79, 128, 75, 72, 65, 75, 65, 83, 83, 73, 65, 206, 75, 72, 65, - 73, 128, 75, 72, 65, 72, 128, 75, 72, 65, 200, 75, 72, 65, 70, 128, 75, - 72, 65, 66, 128, 75, 72, 65, 65, 128, 75, 71, 128, 75, 69, 89, 67, 65, - 80, 128, 75, 69, 89, 67, 65, 208, 75, 69, 89, 66, 79, 65, 82, 68, 128, - 75, 69, 89, 66, 79, 65, 82, 196, 75, 69, 88, 128, 75, 69, 86, 128, 75, - 69, 85, 89, 69, 85, 88, 128, 75, 69, 85, 83, 72, 69, 85, 65, 69, 80, 128, - 75, 69, 85, 83, 69, 85, 88, 128, 75, 69, 85, 80, 85, 81, 128, 75, 69, 85, - 79, 212, 75, 69, 85, 77, 128, 75, 69, 85, 75, 69, 85, 84, 78, 68, 65, - 128, 75, 69, 85, 75, 65, 81, 128, 75, 69, 85, 65, 69, 84, 77, 69, 85, 78, - 128, 75, 69, 85, 65, 69, 82, 73, 128, 75, 69, 84, 84, 201, 75, 69, 83, - 72, 50, 128, 75, 69, 82, 69, 84, 128, 75, 69, 79, 87, 128, 75, 69, 78, - 84, 73, 77, 65, 84, 65, 128, 75, 69, 78, 84, 73, 77, 65, 84, 193, 75, 69, - 78, 84, 73, 77, 193, 75, 69, 78, 65, 84, 128, 75, 69, 78, 128, 75, 69, - 206, 75, 69, 77, 80, 85, 76, 128, 75, 69, 77, 80, 85, 204, 75, 69, 77, - 80, 76, 73, 128, 75, 69, 77, 80, 76, 201, 75, 69, 77, 80, 72, 82, 69, 78, - 71, 128, 75, 69, 77, 66, 65, 78, 71, 128, 75, 69, 76, 86, 73, 206, 75, - 69, 72, 69, 72, 128, 75, 69, 72, 69, 200, 75, 69, 72, 128, 75, 69, 70, - 85, 76, 65, 128, 75, 69, 69, 86, 128, 75, 69, 69, 83, 85, 128, 75, 69, - 69, 80, 73, 78, 199, 75, 69, 69, 78, 71, 128, 75, 69, 69, 66, 128, 75, - 69, 66, 128, 75, 69, 65, 65, 69, 128, 75, 67, 65, 76, 128, 75, 66, 128, - 75, 65, 90, 65, 75, 200, 75, 65, 89, 65, 78, 78, 65, 128, 75, 65, 89, 65, - 200, 75, 65, 88, 128, 75, 65, 87, 86, 128, 75, 65, 87, 73, 128, 75, 65, - 87, 201, 75, 65, 87, 66, 128, 75, 65, 86, 89, 75, 65, 128, 75, 65, 86, - 89, 75, 193, 75, 65, 86, 128, 75, 65, 85, 86, 128, 75, 65, 85, 78, 65, - 128, 75, 65, 85, 206, 75, 65, 85, 66, 128, 75, 65, 84, 79, 128, 75, 65, - 84, 72, 73, 83, 84, 73, 128, 75, 65, 84, 72, 65, 75, 193, 75, 65, 84, 65, - 86, 65, 83, 77, 65, 128, 75, 65, 84, 65, 86, 193, 75, 65, 84, 65, 75, 65, - 78, 65, 45, 72, 73, 82, 65, 71, 65, 78, 193, 75, 65, 83, 82, 65, 84, 65, - 78, 128, 75, 65, 83, 82, 65, 84, 65, 206, 75, 65, 83, 82, 65, 128, 75, - 65, 83, 82, 193, 75, 65, 83, 75, 65, 76, 128, 75, 65, 83, 75, 65, 204, - 75, 65, 83, 72, 77, 73, 82, 201, 75, 65, 82, 83, 72, 65, 78, 65, 128, 75, - 65, 82, 79, 82, 73, 73, 128, 75, 65, 82, 79, 82, 65, 78, 128, 75, 65, 82, - 79, 82, 128, 75, 65, 82, 207, 75, 65, 82, 69, 206, 75, 65, 82, 65, 84, - 84, 79, 128, 75, 65, 82, 65, 78, 128, 75, 65, 80, 89, 69, 79, 85, 78, 83, - 83, 65, 78, 71, 80, 73, 69, 85, 80, 128, 75, 65, 80, 89, 69, 79, 85, 78, - 82, 73, 69, 85, 76, 128, 75, 65, 80, 89, 69, 79, 85, 78, 80, 72, 73, 69, - 85, 80, 72, 128, 75, 65, 80, 89, 69, 79, 85, 78, 77, 73, 69, 85, 77, 128, - 75, 65, 80, 80, 65, 128, 75, 65, 80, 80, 193, 75, 65, 80, 79, 128, 75, - 65, 80, 72, 128, 75, 65, 80, 65, 76, 128, 75, 65, 80, 65, 128, 75, 65, - 208, 75, 65, 78, 84, 65, 74, 193, 75, 65, 78, 78, 65, 68, 193, 75, 65, - 78, 71, 65, 82, 79, 79, 128, 75, 65, 78, 71, 128, 75, 65, 78, 199, 75, - 65, 78, 65, 75, 79, 128, 75, 65, 77, 52, 128, 75, 65, 77, 50, 128, 75, - 65, 77, 128, 75, 65, 75, 84, 79, 86, 73, 203, 75, 65, 75, 79, 128, 75, - 65, 75, 65, 66, 65, 84, 128, 75, 65, 75, 128, 75, 65, 203, 75, 65, 73, - 86, 128, 75, 65, 73, 84, 72, 201, 75, 65, 73, 82, 73, 128, 75, 65, 73, - 66, 128, 75, 65, 73, 128, 75, 65, 201, 75, 65, 70, 65, 128, 75, 65, 70, - 128, 75, 65, 198, 75, 65, 68, 53, 128, 75, 65, 68, 181, 75, 65, 68, 52, - 128, 75, 65, 68, 51, 128, 75, 65, 68, 179, 75, 65, 68, 50, 128, 75, 65, - 68, 128, 75, 65, 67, 72, 75, 65, 128, 75, 65, 66, 193, 75, 65, 66, 128, - 75, 65, 65, 86, 128, 75, 65, 65, 73, 128, 75, 65, 65, 70, 85, 128, 75, - 65, 65, 70, 128, 75, 65, 65, 67, 85, 128, 75, 65, 65, 66, 65, 128, 75, - 65, 65, 66, 128, 75, 65, 50, 128, 75, 65, 178, 75, 65, 45, 75, 69, 128, - 75, 65, 45, 57, 128, 75, 65, 45, 56, 128, 75, 65, 45, 55, 128, 75, 65, - 45, 54, 128, 75, 65, 45, 53, 128, 75, 65, 45, 52, 128, 75, 65, 45, 51, - 128, 75, 65, 45, 50, 128, 75, 65, 45, 49, 49, 128, 75, 65, 45, 49, 48, - 128, 75, 65, 45, 49, 128, 75, 48, 48, 56, 128, 75, 48, 48, 55, 128, 75, - 48, 48, 54, 128, 75, 48, 48, 53, 128, 75, 48, 48, 52, 128, 75, 48, 48, - 51, 128, 75, 48, 48, 50, 128, 75, 48, 48, 49, 128, 74, 87, 65, 128, 74, - 85, 85, 128, 74, 85, 84, 128, 74, 85, 83, 84, 73, 70, 73, 67, 65, 84, 73, - 79, 78, 128, 74, 85, 80, 73, 84, 69, 82, 128, 74, 85, 79, 84, 128, 74, - 85, 79, 80, 128, 74, 85, 78, 79, 128, 74, 85, 78, 71, 83, 69, 79, 78, - 199, 74, 85, 78, 69, 128, 74, 85, 76, 89, 128, 74, 85, 71, 71, 76, 73, - 78, 71, 128, 74, 85, 69, 85, 73, 128, 74, 85, 68, 85, 76, 128, 74, 85, - 68, 71, 69, 128, 74, 85, 68, 69, 79, 45, 83, 80, 65, 78, 73, 83, 200, 74, - 79, 89, 83, 84, 73, 67, 75, 128, 74, 79, 89, 79, 85, 211, 74, 79, 89, - 128, 74, 79, 86, 69, 128, 74, 79, 212, 74, 79, 78, 71, 128, 74, 79, 78, - 193, 74, 79, 75, 69, 82, 128, 74, 79, 73, 78, 84, 83, 128, 74, 79, 73, - 78, 69, 68, 128, 74, 79, 73, 78, 128, 74, 79, 65, 128, 74, 78, 89, 65, - 128, 74, 74, 89, 88, 128, 74, 74, 89, 84, 128, 74, 74, 89, 80, 128, 74, - 74, 89, 128, 74, 74, 85, 88, 128, 74, 74, 85, 84, 128, 74, 74, 85, 82, - 88, 128, 74, 74, 85, 82, 128, 74, 74, 85, 80, 128, 74, 74, 85, 79, 88, - 128, 74, 74, 85, 79, 80, 128, 74, 74, 85, 79, 128, 74, 74, 85, 128, 74, - 74, 79, 88, 128, 74, 74, 79, 84, 128, 74, 74, 79, 80, 128, 74, 74, 79, - 128, 74, 74, 73, 88, 128, 74, 74, 73, 84, 128, 74, 74, 73, 80, 128, 74, - 74, 73, 69, 88, 128, 74, 74, 73, 69, 84, 128, 74, 74, 73, 69, 80, 128, - 74, 74, 73, 69, 128, 74, 74, 73, 128, 74, 74, 69, 69, 128, 74, 74, 69, - 128, 74, 74, 65, 128, 74, 73, 76, 128, 74, 73, 73, 77, 128, 74, 73, 73, - 128, 74, 73, 72, 86, 65, 77, 85, 76, 73, 89, 65, 128, 74, 73, 71, 83, 65, - 215, 74, 73, 65, 128, 74, 72, 79, 88, 128, 74, 72, 79, 128, 74, 72, 69, - 72, 128, 74, 72, 65, 89, 73, 78, 128, 74, 72, 65, 78, 128, 74, 72, 65, - 77, 128, 74, 72, 65, 65, 128, 74, 72, 65, 128, 74, 69, 85, 128, 74, 69, - 82, 85, 83, 65, 76, 69, 77, 128, 74, 69, 82, 65, 206, 74, 69, 82, 65, - 128, 74, 69, 82, 128, 74, 69, 76, 76, 89, 70, 73, 83, 72, 128, 74, 69, - 72, 128, 74, 69, 200, 74, 69, 71, 79, 71, 65, 78, 128, 74, 69, 69, 77, - 128, 74, 69, 69, 205, 74, 69, 65, 78, 83, 128, 74, 65, 89, 78, 128, 74, - 65, 89, 73, 78, 128, 74, 65, 89, 65, 78, 78, 65, 128, 74, 65, 87, 128, - 74, 65, 86, 73, 89, 65, 78, 73, 128, 74, 65, 86, 65, 78, 69, 83, 197, 74, - 65, 85, 128, 74, 65, 82, 128, 74, 65, 80, 65, 78, 69, 83, 197, 74, 65, - 80, 65, 78, 128, 74, 65, 78, 85, 65, 82, 89, 128, 74, 65, 76, 76, 65, 74, - 65, 76, 65, 76, 79, 85, 72, 79, 85, 128, 74, 65, 76, 76, 128, 74, 65, 73, - 206, 74, 65, 73, 128, 74, 65, 72, 128, 74, 65, 68, 69, 128, 74, 65, 67, - 75, 83, 128, 74, 65, 67, 75, 45, 79, 45, 76, 65, 78, 84, 69, 82, 78, 128, - 74, 65, 67, 203, 74, 45, 83, 73, 77, 80, 76, 73, 70, 73, 69, 196, 73, 90, - 72, 73, 84, 83, 65, 128, 73, 90, 72, 73, 84, 83, 193, 73, 90, 72, 69, - 128, 73, 90, 65, 75, 65, 89, 193, 73, 89, 69, 75, 128, 73, 89, 65, 78, - 78, 65, 128, 73, 85, 74, 65, 128, 73, 84, 211, 73, 84, 69, 82, 65, 84, - 73, 79, 206, 73, 84, 69, 77, 128, 73, 83, 83, 72, 65, 82, 128, 73, 83, - 79, 83, 67, 69, 76, 69, 211, 73, 83, 79, 78, 128, 73, 83, 79, 206, 73, - 83, 79, 76, 65, 84, 69, 128, 73, 83, 76, 65, 78, 68, 128, 73, 83, 72, 77, - 65, 65, 77, 128, 73, 83, 69, 78, 45, 73, 83, 69, 78, 128, 73, 83, 65, 75, - 73, 193, 73, 83, 45, 80, 73, 76, 76, 65, 128, 73, 82, 85, 89, 65, 78, 78, - 65, 128, 73, 82, 85, 85, 89, 65, 78, 78, 65, 128, 73, 82, 79, 78, 45, 67, - 79, 80, 80, 69, 210, 73, 82, 79, 78, 128, 73, 82, 66, 128, 73, 79, 84, - 73, 70, 73, 69, 196, 73, 79, 84, 65, 84, 69, 196, 73, 79, 84, 65, 128, - 73, 79, 84, 193, 73, 79, 82, 128, 73, 79, 78, 71, 128, 73, 79, 68, 72, - 65, 68, 72, 128, 73, 78, 86, 73, 83, 73, 66, 76, 197, 73, 78, 86, 69, 82, - 84, 69, 68, 128, 73, 78, 86, 69, 82, 84, 69, 196, 73, 78, 86, 69, 82, 84, - 69, 66, 82, 65, 84, 69, 128, 73, 78, 86, 69, 82, 83, 197, 73, 78, 84, 82, - 79, 68, 85, 67, 69, 82, 128, 73, 78, 84, 73, 128, 73, 78, 84, 69, 82, 83, - 89, 76, 76, 65, 66, 73, 195, 73, 78, 84, 69, 82, 83, 69, 67, 84, 73, 79, - 78, 128, 73, 78, 84, 69, 82, 83, 69, 67, 84, 73, 79, 206, 73, 78, 84, 69, - 82, 83, 69, 67, 84, 73, 78, 199, 73, 78, 84, 69, 82, 82, 79, 66, 65, 78, - 71, 128, 73, 78, 84, 69, 82, 82, 79, 66, 65, 78, 199, 73, 78, 84, 69, 82, - 80, 79, 76, 65, 84, 73, 79, 206, 73, 78, 84, 69, 82, 76, 79, 67, 75, 69, - 196, 73, 78, 84, 69, 82, 76, 73, 78, 69, 65, 210, 73, 78, 84, 69, 82, 76, - 65, 67, 69, 196, 73, 78, 84, 69, 82, 73, 79, 210, 73, 78, 84, 69, 82, 69, - 83, 212, 73, 78, 84, 69, 82, 67, 65, 76, 65, 84, 69, 128, 73, 78, 84, 69, - 71, 82, 65, 84, 73, 79, 78, 128, 73, 78, 84, 69, 71, 82, 65, 84, 73, 79, - 206, 73, 78, 84, 69, 71, 82, 65, 76, 128, 73, 78, 84, 69, 71, 82, 65, - 204, 73, 78, 83, 85, 76, 65, 210, 73, 78, 83, 84, 82, 85, 77, 69, 78, 84, - 65, 204, 73, 78, 83, 73, 68, 69, 128, 73, 78, 83, 73, 68, 197, 73, 78, - 83, 69, 82, 84, 73, 79, 206, 73, 78, 83, 69, 82, 212, 73, 78, 83, 69, 67, - 84, 128, 73, 78, 83, 67, 82, 73, 80, 84, 73, 79, 78, 65, 204, 73, 78, 80, - 85, 212, 73, 78, 78, 79, 67, 69, 78, 67, 69, 128, 73, 78, 78, 78, 128, - 73, 78, 78, 69, 82, 128, 73, 78, 78, 69, 210, 73, 78, 78, 128, 73, 78, - 73, 78, 71, 85, 128, 73, 78, 72, 73, 66, 73, 212, 73, 78, 72, 69, 82, 69, - 78, 212, 73, 78, 72, 65, 76, 69, 128, 73, 78, 71, 87, 65, 90, 128, 73, - 78, 70, 79, 82, 77, 65, 84, 73, 79, 206, 73, 78, 70, 76, 85, 69, 78, 67, - 69, 128, 73, 78, 70, 73, 78, 73, 84, 89, 128, 73, 78, 70, 73, 78, 73, 84, - 217, 73, 78, 68, 85, 83, 84, 82, 73, 65, 204, 73, 78, 68, 73, 82, 69, 67, - 212, 73, 78, 68, 73, 67, 84, 73, 79, 206, 73, 78, 68, 73, 67, 65, 84, 79, - 82, 128, 73, 78, 68, 73, 67, 65, 84, 79, 210, 73, 78, 68, 73, 195, 73, - 78, 68, 73, 65, 206, 73, 78, 68, 69, 88, 128, 73, 78, 68, 69, 80, 69, 78, - 68, 69, 78, 212, 73, 78, 67, 82, 69, 77, 69, 78, 84, 128, 73, 78, 67, 82, - 69, 65, 83, 69, 211, 73, 78, 67, 82, 69, 65, 83, 69, 128, 73, 78, 67, 82, - 69, 65, 83, 197, 73, 78, 67, 79, 77, 80, 76, 69, 84, 197, 73, 78, 67, 79, - 77, 73, 78, 199, 73, 78, 67, 76, 85, 68, 73, 78, 199, 73, 78, 67, 72, - 128, 73, 78, 66, 79, 216, 73, 78, 65, 80, 128, 73, 78, 45, 65, 76, 65, - 70, 128, 73, 77, 80, 69, 82, 73, 65, 204, 73, 77, 80, 69, 82, 70, 69, 67, - 84, 85, 205, 73, 77, 80, 69, 82, 70, 69, 67, 84, 65, 128, 73, 77, 80, 69, - 82, 70, 69, 67, 84, 193, 73, 77, 78, 128, 73, 77, 73, 83, 69, 79, 211, - 73, 77, 73, 78, 51, 128, 73, 77, 73, 78, 128, 73, 77, 73, 206, 73, 77, - 73, 70, 84, 72, 79, 82, 79, 78, 128, 73, 77, 73, 70, 84, 72, 79, 82, 65, - 128, 73, 77, 73, 70, 79, 78, 79, 78, 128, 73, 77, 73, 68, 73, 65, 82, 71, - 79, 78, 128, 73, 77, 65, 71, 197, 73, 77, 65, 65, 76, 65, 128, 73, 76, - 85, 89, 65, 78, 78, 65, 128, 73, 76, 85, 89, 128, 73, 76, 85, 85, 89, 65, - 78, 78, 65, 128, 73, 76, 85, 84, 128, 73, 76, 73, 77, 77, 85, 52, 128, - 73, 76, 73, 77, 77, 85, 51, 128, 73, 76, 73, 77, 77, 85, 128, 73, 76, 73, - 77, 77, 213, 73, 76, 50, 128, 73, 75, 73, 82, 128, 73, 75, 65, 82, 65, - 128, 73, 75, 65, 82, 193, 73, 74, 128, 73, 73, 89, 65, 78, 78, 65, 128, - 73, 71, 73, 128, 73, 71, 201, 73, 71, 71, 87, 83, 128, 73, 70, 73, 78, - 128, 73, 69, 85, 78, 71, 45, 84, 73, 75, 69, 85, 84, 128, 73, 69, 85, 78, - 71, 45, 84, 72, 73, 69, 85, 84, 72, 128, 73, 69, 85, 78, 71, 45, 82, 73, - 69, 85, 76, 128, 73, 69, 85, 78, 71, 45, 80, 73, 69, 85, 80, 128, 73, 69, - 85, 78, 71, 45, 80, 72, 73, 69, 85, 80, 72, 128, 73, 69, 85, 78, 71, 45, - 67, 73, 69, 85, 67, 128, 73, 69, 85, 78, 71, 45, 67, 72, 73, 69, 85, 67, - 72, 128, 73, 69, 85, 78, 199, 73, 68, 76, 69, 128, 73, 68, 73, 77, 128, - 73, 68, 73, 205, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 68, 57, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 68, 56, 128, 73, 68, - 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 68, 55, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 70, 65, 68, 54, 128, 73, 68, 69, 79, 71, 82, 65, 80, - 72, 45, 70, 65, 68, 53, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, - 65, 68, 52, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 68, 51, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 68, 50, 128, 73, 68, - 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 68, 49, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 70, 65, 68, 48, 128, 73, 68, 69, 79, 71, 82, 65, 80, - 72, 45, 70, 65, 67, 70, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, - 65, 67, 69, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 67, 68, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 67, 67, 128, 73, 68, - 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 67, 66, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 70, 65, 67, 65, 128, 73, 68, 69, 79, 71, 82, 65, 80, - 72, 45, 70, 65, 67, 57, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, - 65, 67, 56, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 67, 55, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 67, 54, 128, 73, 68, - 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 67, 53, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 70, 65, 67, 52, 128, 73, 68, 69, 79, 71, 82, 65, 80, - 72, 45, 70, 65, 67, 51, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, - 65, 67, 50, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 67, 49, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 67, 48, 128, 73, 68, - 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 66, 70, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 70, 65, 66, 69, 128, 73, 68, 69, 79, 71, 82, 65, 80, - 72, 45, 70, 65, 66, 68, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, - 65, 66, 67, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 66, 66, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 66, 65, 128, 73, 68, - 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 66, 57, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 70, 65, 66, 56, 128, 73, 68, 69, 79, 71, 82, 65, 80, - 72, 45, 70, 65, 66, 55, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, - 65, 66, 54, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 66, 53, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 66, 52, 128, 73, 68, - 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 66, 51, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 70, 65, 66, 50, 128, 73, 68, 69, 79, 71, 82, 65, 80, - 72, 45, 70, 65, 66, 49, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, - 65, 66, 48, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 65, 70, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 65, 69, 128, 73, 68, - 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 65, 68, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 70, 65, 65, 67, 128, 73, 68, 69, 79, 71, 82, 65, 80, - 72, 45, 70, 65, 65, 66, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, - 65, 65, 65, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 65, 57, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 65, 56, 128, 73, 68, - 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 65, 55, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 70, 65, 65, 54, 128, 73, 68, 69, 79, 71, 82, 65, 80, - 72, 45, 70, 65, 65, 53, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, - 65, 65, 52, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 65, 51, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 65, 50, 128, 73, 68, - 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 65, 49, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 70, 65, 65, 48, 128, 73, 68, 69, 79, 71, 82, 65, 80, - 72, 45, 70, 65, 57, 70, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, - 65, 57, 69, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 57, 68, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 57, 67, 128, 73, 68, - 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 57, 66, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 70, 65, 57, 65, 128, 73, 68, 69, 79, 71, 82, 65, 80, - 72, 45, 70, 65, 57, 57, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, - 65, 57, 56, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 57, 55, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 57, 54, 128, 73, 68, - 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 57, 53, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 70, 65, 57, 52, 128, 73, 68, 69, 79, 71, 82, 65, 80, - 72, 45, 70, 65, 57, 51, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, - 65, 57, 50, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 57, 49, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 57, 48, 128, 73, 68, - 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 56, 70, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 70, 65, 56, 69, 128, 73, 68, 69, 79, 71, 82, 65, 80, - 72, 45, 70, 65, 56, 68, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, - 65, 56, 67, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 56, 66, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 56, 65, 128, 73, 68, - 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 56, 57, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 70, 65, 56, 56, 128, 73, 68, 69, 79, 71, 82, 65, 80, - 72, 45, 70, 65, 56, 55, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, - 65, 56, 54, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 56, 53, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 56, 52, 128, 73, 68, - 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 56, 51, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 70, 65, 56, 50, 128, 73, 68, 69, 79, 71, 82, 65, 80, - 72, 45, 70, 65, 56, 49, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, - 65, 56, 48, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 55, 70, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 55, 69, 128, 73, 68, - 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 55, 68, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 70, 65, 55, 67, 128, 73, 68, 69, 79, 71, 82, 65, 80, - 72, 45, 70, 65, 55, 66, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, - 65, 55, 65, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 55, 57, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 55, 56, 128, 73, 68, - 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 55, 55, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 70, 65, 55, 54, 128, 73, 68, 69, 79, 71, 82, 65, 80, - 72, 45, 70, 65, 55, 53, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, - 65, 55, 52, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 55, 51, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 55, 50, 128, 73, 68, - 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 55, 49, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 70, 65, 55, 48, 128, 73, 68, 69, 79, 71, 82, 65, 80, - 72, 45, 70, 65, 54, 68, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, - 65, 54, 67, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 54, 66, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 54, 65, 128, 73, 68, - 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 54, 57, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 70, 65, 54, 56, 128, 73, 68, 69, 79, 71, 82, 65, 80, - 72, 45, 70, 65, 54, 55, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, - 65, 54, 54, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 54, 53, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 54, 52, 128, 73, 68, - 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 54, 51, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 70, 65, 54, 50, 128, 73, 68, 69, 79, 71, 82, 65, 80, - 72, 45, 70, 65, 54, 49, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, - 65, 54, 48, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 53, 70, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 53, 69, 128, 73, 68, - 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 53, 68, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 70, 65, 53, 67, 128, 73, 68, 69, 79, 71, 82, 65, 80, - 72, 45, 70, 65, 53, 66, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, - 65, 53, 65, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 53, 57, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 53, 56, 128, 73, 68, - 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 53, 55, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 70, 65, 53, 54, 128, 73, 68, 69, 79, 71, 82, 65, 80, - 72, 45, 70, 65, 53, 53, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, - 65, 53, 52, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 53, 51, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 53, 50, 128, 73, 68, - 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 53, 49, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 70, 65, 53, 48, 128, 73, 68, 69, 79, 71, 82, 65, 80, - 72, 45, 70, 65, 52, 70, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, - 65, 52, 69, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 52, 68, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 52, 67, 128, 73, 68, - 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 52, 66, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 70, 65, 52, 65, 128, 73, 68, 69, 79, 71, 82, 65, 80, - 72, 45, 70, 65, 52, 57, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, - 65, 52, 56, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 52, 55, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 52, 54, 128, 73, 68, - 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 52, 53, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 70, 65, 52, 52, 128, 73, 68, 69, 79, 71, 82, 65, 80, - 72, 45, 70, 65, 52, 51, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, - 65, 52, 50, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 52, 49, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 52, 48, 128, 73, 68, - 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 51, 70, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 70, 65, 51, 69, 128, 73, 68, 69, 79, 71, 82, 65, 80, - 72, 45, 70, 65, 51, 68, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, - 65, 51, 67, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 51, 66, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 51, 65, 128, 73, 68, - 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 51, 57, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 70, 65, 51, 56, 128, 73, 68, 69, 79, 71, 82, 65, 80, - 72, 45, 70, 65, 51, 55, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, - 65, 51, 54, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 51, 53, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 51, 52, 128, 73, 68, - 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 51, 51, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 70, 65, 51, 50, 128, 73, 68, 69, 79, 71, 82, 65, 80, - 72, 45, 70, 65, 51, 49, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, - 65, 51, 48, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 50, 70, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 50, 69, 128, 73, 68, - 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 50, 68, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 70, 65, 50, 67, 128, 73, 68, 69, 79, 71, 82, 65, 80, - 72, 45, 70, 65, 50, 66, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, - 65, 50, 65, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 50, 57, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 50, 56, 128, 73, 68, - 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 50, 55, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 70, 65, 50, 54, 128, 73, 68, 69, 79, 71, 82, 65, 80, - 72, 45, 70, 65, 50, 53, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, - 65, 50, 52, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 50, 51, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 50, 50, 128, 73, 68, - 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 50, 49, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 70, 65, 50, 48, 128, 73, 68, 69, 79, 71, 82, 65, 80, - 72, 45, 70, 65, 49, 70, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, - 65, 49, 69, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 49, 68, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 49, 67, 128, 73, 68, - 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 49, 66, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 70, 65, 49, 65, 128, 73, 68, 69, 79, 71, 82, 65, 80, - 72, 45, 70, 65, 49, 57, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, - 65, 49, 56, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 49, 55, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 49, 54, 128, 73, 68, - 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 49, 53, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 70, 65, 49, 52, 128, 73, 68, 69, 79, 71, 82, 65, 80, - 72, 45, 70, 65, 49, 51, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, - 65, 49, 50, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 49, 49, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 49, 48, 128, 73, 68, - 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 48, 70, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 70, 65, 48, 69, 128, 73, 68, 69, 79, 71, 82, 65, 80, - 72, 45, 70, 65, 48, 68, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, - 65, 48, 67, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 48, 66, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 48, 65, 128, 73, 68, - 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 48, 57, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 70, 65, 48, 56, 128, 73, 68, 69, 79, 71, 82, 65, 80, - 72, 45, 70, 65, 48, 55, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, - 65, 48, 54, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 48, 53, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 48, 52, 128, 73, 68, - 69, 79, 71, 82, 65, 80, 72, 45, 70, 65, 48, 51, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 70, 65, 48, 50, 128, 73, 68, 69, 79, 71, 82, 65, 80, - 72, 45, 70, 65, 48, 49, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, - 65, 48, 48, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 70, 70, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 70, 69, 128, 73, 68, - 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 70, 68, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 70, 57, 70, 67, 128, 73, 68, 69, 79, 71, 82, 65, 80, - 72, 45, 70, 57, 70, 66, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, - 57, 70, 65, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 70, 57, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 70, 56, 128, 73, 68, - 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 70, 55, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 70, 57, 70, 54, 128, 73, 68, 69, 79, 71, 82, 65, 80, - 72, 45, 70, 57, 70, 53, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, - 57, 70, 52, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 70, 51, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 70, 50, 128, 73, 68, - 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 70, 49, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 70, 57, 70, 48, 128, 73, 68, 69, 79, 71, 82, 65, 80, - 72, 45, 70, 57, 69, 70, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, - 57, 69, 69, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 69, 68, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 69, 67, 128, 73, 68, - 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 69, 66, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 70, 57, 69, 65, 128, 73, 68, 69, 79, 71, 82, 65, 80, - 72, 45, 70, 57, 69, 57, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, - 57, 69, 56, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 69, 55, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 69, 54, 128, 73, 68, - 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 69, 53, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 70, 57, 69, 52, 128, 73, 68, 69, 79, 71, 82, 65, 80, - 72, 45, 70, 57, 69, 51, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, - 57, 69, 50, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 69, 49, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 69, 48, 128, 73, 68, - 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 68, 70, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 70, 57, 68, 69, 128, 73, 68, 69, 79, 71, 82, 65, 80, - 72, 45, 70, 57, 68, 68, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, - 57, 68, 67, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 68, 66, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 68, 65, 128, 73, 68, - 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 68, 57, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 70, 57, 68, 56, 128, 73, 68, 69, 79, 71, 82, 65, 80, - 72, 45, 70, 57, 68, 55, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, - 57, 68, 54, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 68, 53, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 68, 52, 128, 73, 68, - 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 68, 51, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 70, 57, 68, 50, 128, 73, 68, 69, 79, 71, 82, 65, 80, - 72, 45, 70, 57, 68, 49, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, - 57, 68, 48, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 67, 70, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 67, 69, 128, 73, 68, - 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 67, 68, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 70, 57, 67, 67, 128, 73, 68, 69, 79, 71, 82, 65, 80, - 72, 45, 70, 57, 67, 66, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, - 57, 67, 65, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 67, 57, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 67, 56, 128, 73, 68, - 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 67, 55, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 70, 57, 67, 54, 128, 73, 68, 69, 79, 71, 82, 65, 80, - 72, 45, 70, 57, 67, 53, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, - 57, 67, 52, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 67, 51, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 67, 50, 128, 73, 68, - 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 67, 49, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 70, 57, 67, 48, 128, 73, 68, 69, 79, 71, 82, 65, 80, - 72, 45, 70, 57, 66, 70, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, - 57, 66, 69, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 66, 68, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 66, 67, 128, 73, 68, - 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 66, 66, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 70, 57, 66, 65, 128, 73, 68, 69, 79, 71, 82, 65, 80, - 72, 45, 70, 57, 66, 57, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, - 57, 66, 56, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 66, 55, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 66, 54, 128, 73, 68, - 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 66, 53, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 70, 57, 66, 52, 128, 73, 68, 69, 79, 71, 82, 65, 80, - 72, 45, 70, 57, 66, 51, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, - 57, 66, 50, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 66, 49, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 66, 48, 128, 73, 68, - 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 65, 70, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 70, 57, 65, 69, 128, 73, 68, 69, 79, 71, 82, 65, 80, - 72, 45, 70, 57, 65, 68, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, - 57, 65, 67, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 65, 66, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 65, 65, 128, 73, 68, - 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 65, 57, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 70, 57, 65, 56, 128, 73, 68, 69, 79, 71, 82, 65, 80, - 72, 45, 70, 57, 65, 55, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, - 57, 65, 54, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 65, 53, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 65, 52, 128, 73, 68, - 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 65, 51, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 70, 57, 65, 50, 128, 73, 68, 69, 79, 71, 82, 65, 80, - 72, 45, 70, 57, 65, 49, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, - 57, 65, 48, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 57, 70, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 57, 69, 128, 73, 68, - 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 57, 68, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 70, 57, 57, 67, 128, 73, 68, 69, 79, 71, 82, 65, 80, - 72, 45, 70, 57, 57, 66, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, - 57, 57, 65, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 57, 57, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 57, 56, 128, 73, 68, - 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 57, 55, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 70, 57, 57, 54, 128, 73, 68, 69, 79, 71, 82, 65, 80, - 72, 45, 70, 57, 57, 53, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, - 57, 57, 52, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 57, 51, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 57, 50, 128, 73, 68, - 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 57, 49, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 70, 57, 57, 48, 128, 73, 68, 69, 79, 71, 82, 65, 80, - 72, 45, 70, 57, 56, 70, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, - 57, 56, 69, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 56, 68, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 56, 67, 128, 73, 68, - 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 56, 66, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 70, 57, 56, 65, 128, 73, 68, 69, 79, 71, 82, 65, 80, - 72, 45, 70, 57, 56, 57, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, - 57, 56, 56, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 56, 55, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 56, 54, 128, 73, 68, - 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 56, 53, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 70, 57, 56, 52, 128, 73, 68, 69, 79, 71, 82, 65, 80, - 72, 45, 70, 57, 56, 51, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, - 57, 56, 50, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 56, 49, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 56, 48, 128, 73, 68, - 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 55, 70, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 70, 57, 55, 69, 128, 73, 68, 69, 79, 71, 82, 65, 80, - 72, 45, 70, 57, 55, 68, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, - 57, 55, 67, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 55, 66, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 55, 65, 128, 73, 68, - 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 55, 57, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 70, 57, 55, 56, 128, 73, 68, 69, 79, 71, 82, 65, 80, - 72, 45, 70, 57, 55, 55, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, - 57, 55, 54, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 55, 53, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 55, 52, 128, 73, 68, - 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 55, 51, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 70, 57, 55, 50, 128, 73, 68, 69, 79, 71, 82, 65, 80, - 72, 45, 70, 57, 55, 49, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, - 57, 55, 48, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 54, 70, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 54, 69, 128, 73, 68, - 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 54, 68, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 70, 57, 54, 67, 128, 73, 68, 69, 79, 71, 82, 65, 80, - 72, 45, 70, 57, 54, 66, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, - 57, 54, 65, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 54, 57, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 54, 56, 128, 73, 68, - 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 54, 55, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 70, 57, 54, 54, 128, 73, 68, 69, 79, 71, 82, 65, 80, - 72, 45, 70, 57, 54, 53, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, - 57, 54, 52, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 54, 51, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 54, 50, 128, 73, 68, - 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 54, 49, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 70, 57, 54, 48, 128, 73, 68, 69, 79, 71, 82, 65, 80, - 72, 45, 70, 57, 53, 70, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, - 57, 53, 69, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 53, 68, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 53, 67, 128, 73, 68, - 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 53, 66, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 70, 57, 53, 65, 128, 73, 68, 69, 79, 71, 82, 65, 80, - 72, 45, 70, 57, 53, 57, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, - 57, 53, 56, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 53, 55, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 53, 54, 128, 73, 68, - 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 53, 53, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 70, 57, 53, 52, 128, 73, 68, 69, 79, 71, 82, 65, 80, - 72, 45, 70, 57, 53, 51, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, - 57, 53, 50, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 53, 49, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 53, 48, 128, 73, 68, - 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 52, 70, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 70, 57, 52, 69, 128, 73, 68, 69, 79, 71, 82, 65, 80, - 72, 45, 70, 57, 52, 68, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, - 57, 52, 67, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 52, 66, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 52, 65, 128, 73, 68, - 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 52, 57, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 70, 57, 52, 56, 128, 73, 68, 69, 79, 71, 82, 65, 80, - 72, 45, 70, 57, 52, 55, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, - 57, 52, 54, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 52, 53, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 52, 52, 128, 73, 68, - 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 52, 51, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 70, 57, 52, 50, 128, 73, 68, 69, 79, 71, 82, 65, 80, - 72, 45, 70, 57, 52, 49, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, - 57, 52, 48, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 51, 70, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 51, 69, 128, 73, 68, - 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 51, 68, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 70, 57, 51, 67, 128, 73, 68, 69, 79, 71, 82, 65, 80, - 72, 45, 70, 57, 51, 66, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, - 57, 51, 65, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 51, 57, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 51, 56, 128, 73, 68, - 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 51, 55, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 70, 57, 51, 54, 128, 73, 68, 69, 79, 71, 82, 65, 80, - 72, 45, 70, 57, 51, 53, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, - 57, 51, 52, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 51, 51, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 51, 50, 128, 73, 68, - 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 51, 49, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 70, 57, 51, 48, 128, 73, 68, 69, 79, 71, 82, 65, 80, - 72, 45, 70, 57, 50, 70, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, - 57, 50, 69, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 50, 68, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 50, 67, 128, 73, 68, - 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 50, 66, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 70, 57, 50, 65, 128, 73, 68, 69, 79, 71, 82, 65, 80, - 72, 45, 70, 57, 50, 57, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, - 57, 50, 56, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 50, 55, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 50, 54, 128, 73, 68, - 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 50, 53, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 70, 57, 50, 52, 128, 73, 68, 69, 79, 71, 82, 65, 80, - 72, 45, 70, 57, 50, 51, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, - 57, 50, 50, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 50, 49, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 50, 48, 128, 73, 68, - 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 49, 70, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 70, 57, 49, 69, 128, 73, 68, 69, 79, 71, 82, 65, 80, - 72, 45, 70, 57, 49, 68, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, - 57, 49, 67, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 49, 66, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 49, 65, 128, 73, 68, - 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 49, 57, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 70, 57, 49, 56, 128, 73, 68, 69, 79, 71, 82, 65, 80, - 72, 45, 70, 57, 49, 55, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, - 57, 49, 54, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 49, 53, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 49, 52, 128, 73, 68, - 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 49, 51, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 70, 57, 49, 50, 128, 73, 68, 69, 79, 71, 82, 65, 80, - 72, 45, 70, 57, 49, 49, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, - 57, 49, 48, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 48, 70, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 48, 69, 128, 73, 68, - 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 48, 68, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 70, 57, 48, 67, 128, 73, 68, 69, 79, 71, 82, 65, 80, - 72, 45, 70, 57, 48, 66, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, - 57, 48, 65, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 48, 57, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 48, 56, 128, 73, 68, - 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 48, 55, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 70, 57, 48, 54, 128, 73, 68, 69, 79, 71, 82, 65, 80, - 72, 45, 70, 57, 48, 53, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, - 57, 48, 52, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 48, 51, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 48, 50, 128, 73, 68, - 69, 79, 71, 82, 65, 80, 72, 45, 70, 57, 48, 49, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 70, 57, 48, 48, 128, 73, 68, 69, 79, 71, 82, 65, 80, - 72, 45, 57, 49, 52, 68, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 57, - 48, 52, 65, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 56, 68, 55, 48, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 56, 67, 65, 57, 128, 73, 68, - 69, 79, 71, 82, 65, 80, 72, 45, 56, 57, 69, 51, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 55, 68, 52, 50, 128, 73, 68, 69, 79, 71, 82, 65, 80, - 72, 45, 55, 65, 55, 65, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 55, - 57, 56, 49, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 55, 54, 68, 55, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 55, 53, 51, 51, 128, 73, 68, - 69, 79, 71, 82, 65, 80, 72, 45, 55, 53, 49, 70, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 55, 49, 50, 49, 128, 73, 68, 69, 79, 71, 82, 65, 80, - 72, 45, 55, 48, 66, 57, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 54, - 70, 49, 52, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 54, 69, 56, 48, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 54, 55, 50, 67, 128, 73, 68, - 69, 79, 71, 82, 65, 80, 72, 45, 54, 55, 48, 57, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 54, 55, 48, 56, 128, 73, 68, 69, 79, 71, 82, 65, 80, - 72, 45, 54, 54, 50, 48, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 54, - 53, 66, 48, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 54, 53, 57, 57, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 54, 53, 53, 55, 128, 73, 68, - 69, 79, 71, 82, 65, 80, 72, 45, 54, 51, 53, 53, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 54, 51, 48, 55, 128, 73, 68, 69, 79, 71, 82, 65, 80, - 72, 45, 54, 50, 57, 53, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 54, - 50, 53, 51, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 54, 50, 52, 66, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 53, 70, 56, 67, 128, 73, 68, - 69, 79, 71, 82, 65, 80, 72, 45, 53, 68, 69, 54, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 53, 66, 56, 57, 128, 73, 68, 69, 79, 71, 82, 65, 80, - 72, 45, 53, 66, 53, 55, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 53, - 57, 50, 57, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 53, 57, 49, 65, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 53, 56, 70, 48, 128, 73, 68, - 69, 79, 71, 82, 65, 80, 72, 45, 53, 53, 66, 54, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 53, 52, 51, 57, 128, 73, 68, 69, 79, 71, 82, 65, 80, - 72, 45, 53, 52, 48, 56, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 53, - 51, 70, 51, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 53, 51, 67, 67, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 53, 50, 68, 68, 128, 73, 68, - 69, 79, 71, 82, 65, 80, 72, 45, 53, 50, 55, 50, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 53, 50, 52, 68, 128, 73, 68, 69, 79, 71, 82, 65, 80, - 72, 45, 53, 50, 49, 68, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 53, - 49, 56, 68, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 52, 69, 65, 52, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 52, 69, 56, 67, 128, 73, 68, - 69, 79, 71, 82, 65, 80, 72, 45, 52, 69, 50, 68, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 52, 69, 48, 57, 128, 73, 68, 69, 79, 71, 82, 65, 80, - 72, 45, 52, 69, 48, 48, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, - 70, 65, 49, 68, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 65, - 49, 67, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 65, 49, 66, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 65, 49, 65, 128, 73, - 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 65, 49, 57, 128, 73, 68, 69, - 79, 71, 82, 65, 80, 72, 45, 50, 70, 65, 49, 56, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 50, 70, 65, 49, 55, 128, 73, 68, 69, 79, 71, 82, 65, - 80, 72, 45, 50, 70, 65, 49, 54, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, - 45, 50, 70, 65, 49, 53, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, - 70, 65, 49, 52, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 65, - 49, 51, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 65, 49, 50, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 65, 49, 49, 128, 73, - 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 65, 49, 48, 128, 73, 68, 69, - 79, 71, 82, 65, 80, 72, 45, 50, 70, 65, 48, 70, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 50, 70, 65, 48, 69, 128, 73, 68, 69, 79, 71, 82, 65, - 80, 72, 45, 50, 70, 65, 48, 68, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, - 45, 50, 70, 65, 48, 67, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, - 70, 65, 48, 66, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 65, - 48, 65, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 65, 48, 57, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 65, 48, 56, 128, 73, - 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 65, 48, 55, 128, 73, 68, 69, - 79, 71, 82, 65, 80, 72, 45, 50, 70, 65, 48, 54, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 50, 70, 65, 48, 53, 128, 73, 68, 69, 79, 71, 82, 65, - 80, 72, 45, 50, 70, 65, 48, 52, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, - 45, 50, 70, 65, 48, 51, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, - 70, 65, 48, 50, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 65, - 48, 49, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 65, 48, 48, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 70, 70, 128, 73, - 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 70, 69, 128, 73, 68, 69, - 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 70, 68, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 50, 70, 57, 70, 67, 128, 73, 68, 69, 79, 71, 82, 65, - 80, 72, 45, 50, 70, 57, 70, 66, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, - 45, 50, 70, 57, 70, 65, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, - 70, 57, 70, 57, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, - 70, 56, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 70, 55, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 70, 54, 128, 73, - 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 70, 53, 128, 73, 68, 69, - 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 70, 52, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 50, 70, 57, 70, 51, 128, 73, 68, 69, 79, 71, 82, 65, - 80, 72, 45, 50, 70, 57, 70, 50, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, - 45, 50, 70, 57, 70, 49, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, - 70, 57, 70, 48, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, - 69, 70, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 69, 69, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 69, 68, 128, 73, - 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 69, 67, 128, 73, 68, 69, - 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 69, 66, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 50, 70, 57, 69, 65, 128, 73, 68, 69, 79, 71, 82, 65, - 80, 72, 45, 50, 70, 57, 69, 57, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, - 45, 50, 70, 57, 69, 56, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, - 70, 57, 69, 55, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, - 69, 54, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 69, 53, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 69, 52, 128, 73, - 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 69, 51, 128, 73, 68, 69, - 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 69, 50, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 50, 70, 57, 69, 49, 128, 73, 68, 69, 79, 71, 82, 65, - 80, 72, 45, 50, 70, 57, 69, 48, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, - 45, 50, 70, 57, 68, 70, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, - 70, 57, 68, 69, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, - 68, 68, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 68, 67, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 68, 66, 128, 73, - 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 68, 65, 128, 73, 68, 69, - 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 68, 57, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 50, 70, 57, 68, 56, 128, 73, 68, 69, 79, 71, 82, 65, - 80, 72, 45, 50, 70, 57, 68, 55, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, - 45, 50, 70, 57, 68, 54, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, - 70, 57, 68, 53, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, - 68, 52, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 68, 51, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 68, 50, 128, 73, - 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 68, 49, 128, 73, 68, 69, - 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 68, 48, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 50, 70, 57, 67, 70, 128, 73, 68, 69, 79, 71, 82, 65, - 80, 72, 45, 50, 70, 57, 67, 69, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, - 45, 50, 70, 57, 67, 68, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, - 70, 57, 67, 67, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, - 67, 66, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 67, 65, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 67, 57, 128, 73, - 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 67, 56, 128, 73, 68, 69, - 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 67, 55, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 50, 70, 57, 67, 54, 128, 73, 68, 69, 79, 71, 82, 65, - 80, 72, 45, 50, 70, 57, 67, 53, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, - 45, 50, 70, 57, 67, 52, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, - 70, 57, 67, 51, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, - 67, 50, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 67, 49, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 67, 48, 128, 73, - 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 66, 70, 128, 73, 68, 69, - 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 66, 69, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 50, 70, 57, 66, 68, 128, 73, 68, 69, 79, 71, 82, 65, - 80, 72, 45, 50, 70, 57, 66, 67, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, - 45, 50, 70, 57, 66, 66, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, - 70, 57, 66, 65, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, - 66, 57, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 66, 56, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 66, 55, 128, 73, - 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 66, 54, 128, 73, 68, 69, - 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 66, 53, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 50, 70, 57, 66, 52, 128, 73, 68, 69, 79, 71, 82, 65, - 80, 72, 45, 50, 70, 57, 66, 51, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, - 45, 50, 70, 57, 66, 50, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, - 70, 57, 66, 49, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, - 66, 48, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 65, 70, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 65, 69, 128, 73, - 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 65, 68, 128, 73, 68, 69, - 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 65, 67, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 50, 70, 57, 65, 66, 128, 73, 68, 69, 79, 71, 82, 65, - 80, 72, 45, 50, 70, 57, 65, 65, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, - 45, 50, 70, 57, 65, 57, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, - 70, 57, 65, 56, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, - 65, 55, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 65, 54, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 65, 53, 128, 73, - 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 65, 52, 128, 73, 68, 69, - 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 65, 51, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 50, 70, 57, 65, 50, 128, 73, 68, 69, 79, 71, 82, 65, - 80, 72, 45, 50, 70, 57, 65, 49, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, - 45, 50, 70, 57, 65, 48, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, - 70, 57, 57, 70, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, - 57, 69, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 57, 68, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 57, 67, 128, 73, - 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 57, 66, 128, 73, 68, 69, - 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 57, 65, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 50, 70, 57, 57, 57, 128, 73, 68, 69, 79, 71, 82, 65, - 80, 72, 45, 50, 70, 57, 57, 56, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, - 45, 50, 70, 57, 57, 55, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, - 70, 57, 57, 54, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, - 57, 53, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 57, 52, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 57, 51, 128, 73, - 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 57, 50, 128, 73, 68, 69, - 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 57, 49, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 50, 70, 57, 57, 48, 128, 73, 68, 69, 79, 71, 82, 65, - 80, 72, 45, 50, 70, 57, 56, 70, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, - 45, 50, 70, 57, 56, 69, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, - 70, 57, 56, 68, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, - 56, 67, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 56, 66, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 56, 65, 128, 73, - 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 56, 57, 128, 73, 68, 69, - 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 56, 56, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 50, 70, 57, 56, 55, 128, 73, 68, 69, 79, 71, 82, 65, - 80, 72, 45, 50, 70, 57, 56, 54, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, - 45, 50, 70, 57, 56, 53, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, - 70, 57, 56, 52, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, - 56, 51, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 56, 50, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 56, 49, 128, 73, - 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 56, 48, 128, 73, 68, 69, - 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 55, 70, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 50, 70, 57, 55, 69, 128, 73, 68, 69, 79, 71, 82, 65, - 80, 72, 45, 50, 70, 57, 55, 68, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, - 45, 50, 70, 57, 55, 67, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, - 70, 57, 55, 66, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, - 55, 65, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 55, 57, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 55, 56, 128, 73, - 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 55, 55, 128, 73, 68, 69, - 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 55, 54, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 50, 70, 57, 55, 53, 128, 73, 68, 69, 79, 71, 82, 65, - 80, 72, 45, 50, 70, 57, 55, 52, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, - 45, 50, 70, 57, 55, 51, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, - 70, 57, 55, 50, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, - 55, 49, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 55, 48, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 54, 70, 128, 73, - 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 54, 69, 128, 73, 68, 69, - 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 54, 68, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 50, 70, 57, 54, 67, 128, 73, 68, 69, 79, 71, 82, 65, - 80, 72, 45, 50, 70, 57, 54, 66, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, - 45, 50, 70, 57, 54, 65, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, - 70, 57, 54, 57, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, - 54, 56, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 54, 55, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 54, 54, 128, 73, - 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 54, 53, 128, 73, 68, 69, - 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 54, 52, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 50, 70, 57, 54, 51, 128, 73, 68, 69, 79, 71, 82, 65, - 80, 72, 45, 50, 70, 57, 54, 50, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, - 45, 50, 70, 57, 54, 49, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, - 70, 57, 54, 48, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, - 53, 70, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 53, 69, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 53, 68, 128, 73, - 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 53, 67, 128, 73, 68, 69, - 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 53, 66, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 50, 70, 57, 53, 65, 128, 73, 68, 69, 79, 71, 82, 65, - 80, 72, 45, 50, 70, 57, 53, 57, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, - 45, 50, 70, 57, 53, 56, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, - 70, 57, 53, 55, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, - 53, 54, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 53, 53, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 53, 52, 128, 73, - 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 53, 51, 128, 73, 68, 69, - 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 53, 50, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 50, 70, 57, 53, 49, 128, 73, 68, 69, 79, 71, 82, 65, - 80, 72, 45, 50, 70, 57, 53, 48, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, - 45, 50, 70, 57, 52, 70, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, - 70, 57, 52, 69, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, - 52, 68, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 52, 67, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 52, 66, 128, 73, - 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 52, 65, 128, 73, 68, 69, - 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 52, 57, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 50, 70, 57, 52, 56, 128, 73, 68, 69, 79, 71, 82, 65, - 80, 72, 45, 50, 70, 57, 52, 55, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, - 45, 50, 70, 57, 52, 54, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, - 70, 57, 52, 53, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, - 52, 52, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 52, 51, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 52, 50, 128, 73, - 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 52, 49, 128, 73, 68, 69, - 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 52, 48, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 50, 70, 57, 51, 70, 128, 73, 68, 69, 79, 71, 82, 65, - 80, 72, 45, 50, 70, 57, 51, 69, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, - 45, 50, 70, 57, 51, 68, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, - 70, 57, 51, 67, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, - 51, 66, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 51, 65, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 51, 57, 128, 73, - 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 51, 56, 128, 73, 68, 69, - 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 51, 55, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 50, 70, 57, 51, 54, 128, 73, 68, 69, 79, 71, 82, 65, - 80, 72, 45, 50, 70, 57, 51, 53, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, - 45, 50, 70, 57, 51, 52, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, - 70, 57, 51, 51, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, - 51, 50, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 51, 49, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 51, 48, 128, 73, - 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 50, 70, 128, 73, 68, 69, - 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 50, 69, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 50, 70, 57, 50, 68, 128, 73, 68, 69, 79, 71, 82, 65, - 80, 72, 45, 50, 70, 57, 50, 67, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, - 45, 50, 70, 57, 50, 66, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, - 70, 57, 50, 65, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, - 50, 57, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 50, 56, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 50, 55, 128, 73, - 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 50, 54, 128, 73, 68, 69, - 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 50, 53, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 50, 70, 57, 50, 52, 128, 73, 68, 69, 79, 71, 82, 65, - 80, 72, 45, 50, 70, 57, 50, 51, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, - 45, 50, 70, 57, 50, 50, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, - 70, 57, 50, 49, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, - 50, 48, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 49, 70, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 49, 69, 128, 73, - 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 49, 68, 128, 73, 68, 69, - 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 49, 67, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 50, 70, 57, 49, 66, 128, 73, 68, 69, 79, 71, 82, 65, - 80, 72, 45, 50, 70, 57, 49, 65, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, - 45, 50, 70, 57, 49, 57, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, - 70, 57, 49, 56, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, - 49, 55, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 49, 54, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 49, 53, 128, 73, - 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 49, 52, 128, 73, 68, 69, - 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 49, 51, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 50, 70, 57, 49, 50, 128, 73, 68, 69, 79, 71, 82, 65, - 80, 72, 45, 50, 70, 57, 49, 49, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, - 45, 50, 70, 57, 49, 48, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, - 70, 57, 48, 70, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, - 48, 69, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 48, 68, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 48, 67, 128, 73, - 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 48, 66, 128, 73, 68, 69, - 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 48, 65, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 50, 70, 57, 48, 57, 128, 73, 68, 69, 79, 71, 82, 65, - 80, 72, 45, 50, 70, 57, 48, 56, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, - 45, 50, 70, 57, 48, 55, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, - 70, 57, 48, 54, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, - 48, 53, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 48, 52, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 48, 51, 128, 73, - 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 48, 50, 128, 73, 68, 69, - 79, 71, 82, 65, 80, 72, 45, 50, 70, 57, 48, 49, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 50, 70, 57, 48, 48, 128, 73, 68, 69, 79, 71, 82, 65, - 80, 72, 45, 50, 70, 56, 70, 70, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, - 45, 50, 70, 56, 70, 69, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, - 70, 56, 70, 68, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, - 70, 67, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 70, 66, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 70, 65, 128, 73, - 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 70, 57, 128, 73, 68, 69, - 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 70, 56, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 50, 70, 56, 70, 55, 128, 73, 68, 69, 79, 71, 82, 65, - 80, 72, 45, 50, 70, 56, 70, 54, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, - 45, 50, 70, 56, 70, 53, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, - 70, 56, 70, 52, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, - 70, 51, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 70, 50, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 70, 49, 128, 73, - 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 70, 48, 128, 73, 68, 69, - 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 69, 70, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 50, 70, 56, 69, 69, 128, 73, 68, 69, 79, 71, 82, 65, - 80, 72, 45, 50, 70, 56, 69, 68, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, - 45, 50, 70, 56, 69, 67, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, - 70, 56, 69, 66, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, - 69, 65, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 69, 57, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 69, 56, 128, 73, - 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 69, 55, 128, 73, 68, 69, - 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 69, 54, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 50, 70, 56, 69, 53, 128, 73, 68, 69, 79, 71, 82, 65, - 80, 72, 45, 50, 70, 56, 69, 52, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, - 45, 50, 70, 56, 69, 51, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, - 70, 56, 69, 50, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, - 69, 49, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 69, 48, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 68, 70, 128, 73, - 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 68, 69, 128, 73, 68, 69, - 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 68, 68, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 50, 70, 56, 68, 67, 128, 73, 68, 69, 79, 71, 82, 65, - 80, 72, 45, 50, 70, 56, 68, 66, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, - 45, 50, 70, 56, 68, 65, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, - 70, 56, 68, 57, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, - 68, 56, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 68, 55, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 68, 54, 128, 73, - 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 68, 53, 128, 73, 68, 69, - 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 68, 52, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 50, 70, 56, 68, 51, 128, 73, 68, 69, 79, 71, 82, 65, - 80, 72, 45, 50, 70, 56, 68, 50, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, - 45, 50, 70, 56, 68, 49, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, - 70, 56, 68, 48, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, - 67, 70, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 67, 69, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 67, 68, 128, 73, - 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 67, 67, 128, 73, 68, 69, - 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 67, 66, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 50, 70, 56, 67, 65, 128, 73, 68, 69, 79, 71, 82, 65, - 80, 72, 45, 50, 70, 56, 67, 57, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, - 45, 50, 70, 56, 67, 56, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, - 70, 56, 67, 55, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, - 67, 54, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 67, 53, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 67, 52, 128, 73, - 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 67, 51, 128, 73, 68, 69, - 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 67, 50, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 50, 70, 56, 67, 49, 128, 73, 68, 69, 79, 71, 82, 65, - 80, 72, 45, 50, 70, 56, 67, 48, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, - 45, 50, 70, 56, 66, 70, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, - 70, 56, 66, 69, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, - 66, 68, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 66, 67, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 66, 66, 128, 73, - 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 66, 65, 128, 73, 68, 69, - 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 66, 57, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 50, 70, 56, 66, 56, 128, 73, 68, 69, 79, 71, 82, 65, - 80, 72, 45, 50, 70, 56, 66, 55, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, - 45, 50, 70, 56, 66, 54, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, - 70, 56, 66, 53, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, - 66, 52, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 66, 51, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 66, 50, 128, 73, - 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 66, 49, 128, 73, 68, 69, - 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 66, 48, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 50, 70, 56, 65, 70, 128, 73, 68, 69, 79, 71, 82, 65, - 80, 72, 45, 50, 70, 56, 65, 69, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, - 45, 50, 70, 56, 65, 68, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, - 70, 56, 65, 67, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, - 65, 66, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 65, 65, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 65, 57, 128, 73, - 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 65, 56, 128, 73, 68, 69, - 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 65, 55, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 50, 70, 56, 65, 54, 128, 73, 68, 69, 79, 71, 82, 65, - 80, 72, 45, 50, 70, 56, 65, 53, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, - 45, 50, 70, 56, 65, 52, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, - 70, 56, 65, 51, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, - 65, 50, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 65, 49, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 65, 48, 128, 73, - 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 57, 70, 128, 73, 68, 69, - 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 57, 69, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 50, 70, 56, 57, 68, 128, 73, 68, 69, 79, 71, 82, 65, - 80, 72, 45, 50, 70, 56, 57, 67, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, - 45, 50, 70, 56, 57, 66, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, - 70, 56, 57, 65, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, - 57, 57, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 57, 56, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 57, 55, 128, 73, - 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 57, 54, 128, 73, 68, 69, - 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 57, 53, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 50, 70, 56, 57, 52, 128, 73, 68, 69, 79, 71, 82, 65, - 80, 72, 45, 50, 70, 56, 57, 51, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, - 45, 50, 70, 56, 57, 50, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, - 70, 56, 57, 49, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, - 57, 48, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 56, 70, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 56, 69, 128, 73, - 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 56, 68, 128, 73, 68, 69, - 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 56, 67, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 50, 70, 56, 56, 66, 128, 73, 68, 69, 79, 71, 82, 65, - 80, 72, 45, 50, 70, 56, 56, 65, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, - 45, 50, 70, 56, 56, 57, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, - 70, 56, 56, 56, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, - 56, 55, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 56, 54, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 56, 53, 128, 73, - 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 56, 52, 128, 73, 68, 69, - 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 56, 51, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 50, 70, 56, 56, 50, 128, 73, 68, 69, 79, 71, 82, 65, - 80, 72, 45, 50, 70, 56, 56, 49, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, - 45, 50, 70, 56, 56, 48, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, - 70, 56, 55, 70, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, - 55, 69, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 55, 68, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 55, 67, 128, 73, - 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 55, 66, 128, 73, 68, 69, - 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 55, 65, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 50, 70, 56, 55, 57, 128, 73, 68, 69, 79, 71, 82, 65, - 80, 72, 45, 50, 70, 56, 55, 56, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, - 45, 50, 70, 56, 55, 55, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, - 70, 56, 55, 54, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, - 55, 53, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 55, 52, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 55, 51, 128, 73, - 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 55, 50, 128, 73, 68, 69, - 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 55, 49, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 50, 70, 56, 55, 48, 128, 73, 68, 69, 79, 71, 82, 65, - 80, 72, 45, 50, 70, 56, 54, 70, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, - 45, 50, 70, 56, 54, 69, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, - 70, 56, 54, 68, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, - 54, 67, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 54, 66, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 54, 65, 128, 73, - 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 54, 57, 128, 73, 68, 69, - 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 54, 56, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 50, 70, 56, 54, 55, 128, 73, 68, 69, 79, 71, 82, 65, - 80, 72, 45, 50, 70, 56, 54, 54, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, - 45, 50, 70, 56, 54, 53, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, - 70, 56, 54, 52, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, - 54, 51, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 54, 50, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 54, 49, 128, 73, - 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 54, 48, 128, 73, 68, 69, - 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 53, 70, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 50, 70, 56, 53, 69, 128, 73, 68, 69, 79, 71, 82, 65, - 80, 72, 45, 50, 70, 56, 53, 68, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, - 45, 50, 70, 56, 53, 67, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, - 70, 56, 53, 66, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, - 53, 65, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 53, 57, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 53, 56, 128, 73, - 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 53, 55, 128, 73, 68, 69, - 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 53, 54, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 50, 70, 56, 53, 53, 128, 73, 68, 69, 79, 71, 82, 65, - 80, 72, 45, 50, 70, 56, 53, 52, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, - 45, 50, 70, 56, 53, 51, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, - 70, 56, 53, 50, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, - 53, 49, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 53, 48, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 52, 70, 128, 73, - 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 52, 69, 128, 73, 68, 69, - 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 52, 68, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 50, 70, 56, 52, 67, 128, 73, 68, 69, 79, 71, 82, 65, - 80, 72, 45, 50, 70, 56, 52, 66, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, - 45, 50, 70, 56, 52, 65, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, - 70, 56, 52, 57, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, - 52, 56, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 52, 55, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 52, 54, 128, 73, - 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 52, 53, 128, 73, 68, 69, - 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 52, 52, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 50, 70, 56, 52, 51, 128, 73, 68, 69, 79, 71, 82, 65, - 80, 72, 45, 50, 70, 56, 52, 50, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, - 45, 50, 70, 56, 52, 49, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, - 70, 56, 52, 48, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, - 51, 70, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 51, 69, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 51, 68, 128, 73, - 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 51, 67, 128, 73, 68, 69, - 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 51, 66, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 50, 70, 56, 51, 65, 128, 73, 68, 69, 79, 71, 82, 65, - 80, 72, 45, 50, 70, 56, 51, 57, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, - 45, 50, 70, 56, 51, 56, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, - 70, 56, 51, 55, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, - 51, 54, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 51, 53, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 51, 52, 128, 73, - 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 51, 51, 128, 73, 68, 69, - 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 51, 50, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 50, 70, 56, 51, 49, 128, 73, 68, 69, 79, 71, 82, 65, - 80, 72, 45, 50, 70, 56, 51, 48, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, - 45, 50, 70, 56, 50, 70, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, - 70, 56, 50, 69, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, - 50, 68, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 50, 67, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 50, 66, 128, 73, - 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 50, 65, 128, 73, 68, 69, - 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 50, 57, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 50, 70, 56, 50, 56, 128, 73, 68, 69, 79, 71, 82, 65, - 80, 72, 45, 50, 70, 56, 50, 55, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, - 45, 50, 70, 56, 50, 54, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, - 70, 56, 50, 53, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, - 50, 52, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 50, 51, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 50, 50, 128, 73, - 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 50, 49, 128, 73, 68, 69, - 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 50, 48, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 50, 70, 56, 49, 70, 128, 73, 68, 69, 79, 71, 82, 65, - 80, 72, 45, 50, 70, 56, 49, 69, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, - 45, 50, 70, 56, 49, 68, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, - 70, 56, 49, 67, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, - 49, 66, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 49, 65, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 49, 57, 128, 73, - 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 49, 56, 128, 73, 68, 69, - 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 49, 55, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 50, 70, 56, 49, 54, 128, 73, 68, 69, 79, 71, 82, 65, - 80, 72, 45, 50, 70, 56, 49, 53, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, - 45, 50, 70, 56, 49, 52, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, - 70, 56, 49, 51, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, - 49, 50, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 49, 49, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 49, 48, 128, 73, - 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 48, 70, 128, 73, 68, 69, - 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 48, 69, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 50, 70, 56, 48, 68, 128, 73, 68, 69, 79, 71, 82, 65, - 80, 72, 45, 50, 70, 56, 48, 67, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, - 45, 50, 70, 56, 48, 66, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, - 70, 56, 48, 65, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, - 48, 57, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 48, 56, - 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 48, 55, 128, 73, - 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 48, 54, 128, 73, 68, 69, - 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, 48, 53, 128, 73, 68, 69, 79, 71, - 82, 65, 80, 72, 45, 50, 70, 56, 48, 52, 128, 73, 68, 69, 79, 71, 82, 65, - 80, 72, 45, 50, 70, 56, 48, 51, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, - 45, 50, 70, 56, 48, 50, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, - 70, 56, 48, 49, 128, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 50, 70, 56, - 48, 48, 128, 73, 68, 69, 79, 71, 82, 65, 80, 200, 73, 68, 69, 78, 84, 73, - 70, 73, 67, 65, 84, 73, 79, 78, 128, 73, 68, 69, 78, 84, 73, 70, 73, 67, - 65, 84, 73, 79, 206, 73, 68, 69, 78, 84, 73, 67, 65, 204, 73, 68, 68, - 128, 73, 67, 79, 78, 128, 73, 67, 72, 79, 85, 128, 73, 67, 72, 79, 83, - 128, 73, 67, 72, 73, 77, 65, 84, 79, 83, 128, 73, 67, 72, 65, 68, 73, 78, - 128, 73, 67, 69, 76, 65, 78, 68, 73, 67, 45, 89, 82, 128, 73, 66, 73, 70, - 73, 76, 73, 128, 73, 65, 85, 68, 65, 128, 73, 48, 49, 53, 128, 73, 48, - 49, 52, 128, 73, 48, 49, 51, 128, 73, 48, 49, 50, 128, 73, 48, 49, 49, - 65, 128, 73, 48, 49, 49, 128, 73, 48, 49, 48, 65, 128, 73, 48, 49, 48, - 128, 73, 48, 48, 57, 65, 128, 73, 48, 48, 57, 128, 73, 48, 48, 56, 128, - 73, 48, 48, 55, 128, 73, 48, 48, 54, 128, 73, 48, 48, 53, 65, 128, 73, - 48, 48, 53, 128, 73, 48, 48, 52, 128, 73, 48, 48, 51, 128, 73, 48, 48, - 50, 128, 73, 48, 48, 49, 128, 73, 45, 89, 85, 128, 73, 45, 89, 79, 128, - 73, 45, 89, 69, 79, 128, 73, 45, 89, 69, 128, 73, 45, 89, 65, 69, 128, - 73, 45, 89, 65, 45, 79, 128, 73, 45, 89, 65, 128, 73, 45, 79, 45, 73, - 128, 73, 45, 79, 128, 73, 45, 69, 85, 128, 73, 45, 66, 69, 65, 77, 128, - 73, 45, 65, 82, 65, 69, 65, 128, 73, 45, 65, 128, 72, 90, 90, 90, 71, - 128, 72, 90, 90, 90, 128, 72, 90, 90, 80, 128, 72, 90, 90, 128, 72, 90, - 87, 71, 128, 72, 90, 87, 128, 72, 90, 84, 128, 72, 90, 71, 128, 72, 89, - 83, 84, 69, 82, 69, 83, 73, 211, 72, 89, 80, 79, 68, 73, 65, 83, 84, 79, - 76, 69, 128, 72, 89, 80, 72, 69, 78, 65, 84, 73, 79, 206, 72, 89, 80, 72, - 69, 78, 45, 77, 73, 78, 85, 83, 128, 72, 89, 80, 72, 69, 78, 128, 72, 89, - 80, 72, 69, 206, 72, 89, 71, 73, 69, 73, 65, 128, 72, 89, 71, 73, 69, 65, - 128, 72, 89, 65, 67, 73, 78, 84, 72, 128, 72, 88, 87, 71, 128, 72, 88, - 85, 79, 88, 128, 72, 88, 85, 79, 84, 128, 72, 88, 85, 79, 80, 128, 72, - 88, 85, 79, 128, 72, 88, 79, 88, 128, 72, 88, 79, 84, 128, 72, 88, 79, - 80, 128, 72, 88, 79, 128, 72, 88, 73, 88, 128, 72, 88, 73, 84, 128, 72, - 88, 73, 80, 128, 72, 88, 73, 69, 88, 128, 72, 88, 73, 69, 84, 128, 72, - 88, 73, 69, 80, 128, 72, 88, 73, 69, 128, 72, 88, 73, 128, 72, 88, 69, - 88, 128, 72, 88, 69, 80, 128, 72, 88, 69, 128, 72, 88, 65, 88, 128, 72, - 88, 65, 84, 128, 72, 88, 65, 80, 128, 72, 88, 65, 128, 72, 87, 85, 128, - 72, 87, 65, 73, 82, 128, 72, 87, 65, 72, 128, 72, 85, 86, 65, 128, 72, - 85, 83, 72, 69, 196, 72, 85, 83, 72, 128, 72, 85, 82, 65, 78, 128, 72, - 85, 79, 84, 128, 72, 85, 78, 68, 82, 69, 68, 83, 128, 72, 85, 78, 68, 82, - 69, 68, 211, 72, 85, 78, 68, 82, 69, 68, 128, 72, 85, 78, 68, 82, 69, - 196, 72, 85, 78, 128, 72, 85, 77, 208, 72, 85, 77, 65, 78, 128, 72, 85, - 77, 65, 206, 72, 85, 76, 50, 128, 72, 85, 73, 73, 84, 79, 128, 72, 85, - 71, 71, 73, 78, 71, 128, 72, 85, 71, 71, 73, 78, 199, 72, 85, 66, 50, - 128, 72, 85, 66, 178, 72, 85, 66, 128, 72, 85, 65, 82, 65, 68, 68, 79, - 128, 72, 85, 65, 78, 128, 72, 85, 45, 51, 128, 72, 85, 45, 50, 128, 72, - 85, 45, 49, 128, 72, 84, 84, 65, 128, 72, 84, 83, 128, 72, 84, 74, 128, - 72, 82, 89, 86, 78, 73, 193, 72, 80, 87, 71, 128, 72, 80, 65, 128, 72, - 80, 128, 72, 79, 85, 83, 197, 72, 79, 85, 82, 71, 76, 65, 83, 83, 128, - 72, 79, 85, 82, 71, 76, 65, 83, 211, 72, 79, 85, 82, 128, 72, 79, 85, - 210, 72, 79, 84, 69, 76, 128, 72, 79, 84, 65, 128, 72, 79, 83, 80, 73, - 84, 65, 76, 128, 72, 79, 82, 83, 69, 128, 72, 79, 82, 83, 197, 72, 79, - 82, 82, 128, 72, 79, 82, 78, 83, 128, 72, 79, 82, 73, 90, 79, 78, 84, 65, - 76, 76, 89, 128, 72, 79, 82, 73, 90, 79, 78, 84, 65, 76, 76, 217, 72, 79, - 82, 73, 90, 79, 78, 84, 65, 76, 45, 48, 54, 45, 48, 54, 128, 72, 79, 82, - 73, 90, 79, 78, 84, 65, 76, 45, 48, 54, 45, 48, 53, 128, 72, 79, 82, 73, - 90, 79, 78, 84, 65, 76, 45, 48, 54, 45, 48, 52, 128, 72, 79, 82, 73, 90, - 79, 78, 84, 65, 76, 45, 48, 54, 45, 48, 51, 128, 72, 79, 82, 73, 90, 79, - 78, 84, 65, 76, 45, 48, 54, 45, 48, 50, 128, 72, 79, 82, 73, 90, 79, 78, - 84, 65, 76, 45, 48, 54, 45, 48, 49, 128, 72, 79, 82, 73, 90, 79, 78, 84, - 65, 76, 45, 48, 54, 45, 48, 48, 128, 72, 79, 82, 73, 90, 79, 78, 84, 65, - 76, 45, 48, 53, 45, 48, 54, 128, 72, 79, 82, 73, 90, 79, 78, 84, 65, 76, - 45, 48, 53, 45, 48, 53, 128, 72, 79, 82, 73, 90, 79, 78, 84, 65, 76, 45, - 48, 53, 45, 48, 52, 128, 72, 79, 82, 73, 90, 79, 78, 84, 65, 76, 45, 48, - 53, 45, 48, 51, 128, 72, 79, 82, 73, 90, 79, 78, 84, 65, 76, 45, 48, 53, - 45, 48, 50, 128, 72, 79, 82, 73, 90, 79, 78, 84, 65, 76, 45, 48, 53, 45, - 48, 49, 128, 72, 79, 82, 73, 90, 79, 78, 84, 65, 76, 45, 48, 53, 45, 48, - 48, 128, 72, 79, 82, 73, 90, 79, 78, 84, 65, 76, 45, 48, 52, 45, 48, 54, - 128, 72, 79, 82, 73, 90, 79, 78, 84, 65, 76, 45, 48, 52, 45, 48, 53, 128, - 72, 79, 82, 73, 90, 79, 78, 84, 65, 76, 45, 48, 52, 45, 48, 52, 128, 72, - 79, 82, 73, 90, 79, 78, 84, 65, 76, 45, 48, 52, 45, 48, 51, 128, 72, 79, - 82, 73, 90, 79, 78, 84, 65, 76, 45, 48, 52, 45, 48, 50, 128, 72, 79, 82, - 73, 90, 79, 78, 84, 65, 76, 45, 48, 52, 45, 48, 49, 128, 72, 79, 82, 73, - 90, 79, 78, 84, 65, 76, 45, 48, 52, 45, 48, 48, 128, 72, 79, 82, 73, 90, - 79, 78, 84, 65, 76, 45, 48, 51, 45, 48, 54, 128, 72, 79, 82, 73, 90, 79, - 78, 84, 65, 76, 45, 48, 51, 45, 48, 53, 128, 72, 79, 82, 73, 90, 79, 78, - 84, 65, 76, 45, 48, 51, 45, 48, 52, 128, 72, 79, 82, 73, 90, 79, 78, 84, - 65, 76, 45, 48, 51, 45, 48, 51, 128, 72, 79, 82, 73, 90, 79, 78, 84, 65, - 76, 45, 48, 51, 45, 48, 50, 128, 72, 79, 82, 73, 90, 79, 78, 84, 65, 76, - 45, 48, 51, 45, 48, 49, 128, 72, 79, 82, 73, 90, 79, 78, 84, 65, 76, 45, - 48, 51, 45, 48, 48, 128, 72, 79, 82, 73, 90, 79, 78, 84, 65, 76, 45, 48, - 50, 45, 48, 54, 128, 72, 79, 82, 73, 90, 79, 78, 84, 65, 76, 45, 48, 50, - 45, 48, 53, 128, 72, 79, 82, 73, 90, 79, 78, 84, 65, 76, 45, 48, 50, 45, - 48, 52, 128, 72, 79, 82, 73, 90, 79, 78, 84, 65, 76, 45, 48, 50, 45, 48, - 51, 128, 72, 79, 82, 73, 90, 79, 78, 84, 65, 76, 45, 48, 50, 45, 48, 50, - 128, 72, 79, 82, 73, 90, 79, 78, 84, 65, 76, 45, 48, 50, 45, 48, 49, 128, - 72, 79, 82, 73, 90, 79, 78, 84, 65, 76, 45, 48, 50, 45, 48, 48, 128, 72, - 79, 82, 73, 90, 79, 78, 84, 65, 76, 45, 48, 49, 45, 48, 54, 128, 72, 79, - 82, 73, 90, 79, 78, 84, 65, 76, 45, 48, 49, 45, 48, 53, 128, 72, 79, 82, - 73, 90, 79, 78, 84, 65, 76, 45, 48, 49, 45, 48, 52, 128, 72, 79, 82, 73, - 90, 79, 78, 84, 65, 76, 45, 48, 49, 45, 48, 51, 128, 72, 79, 82, 73, 90, - 79, 78, 84, 65, 76, 45, 48, 49, 45, 48, 50, 128, 72, 79, 82, 73, 90, 79, - 78, 84, 65, 76, 45, 48, 49, 45, 48, 49, 128, 72, 79, 82, 73, 90, 79, 78, - 84, 65, 76, 45, 48, 49, 45, 48, 48, 128, 72, 79, 82, 73, 90, 79, 78, 84, - 65, 76, 45, 48, 48, 45, 48, 54, 128, 72, 79, 82, 73, 90, 79, 78, 84, 65, - 76, 45, 48, 48, 45, 48, 53, 128, 72, 79, 82, 73, 90, 79, 78, 84, 65, 76, - 45, 48, 48, 45, 48, 52, 128, 72, 79, 82, 73, 90, 79, 78, 84, 65, 76, 45, - 48, 48, 45, 48, 51, 128, 72, 79, 82, 73, 90, 79, 78, 84, 65, 76, 45, 48, - 48, 45, 48, 50, 128, 72, 79, 82, 73, 90, 79, 78, 84, 65, 76, 45, 48, 48, - 45, 48, 49, 128, 72, 79, 82, 73, 90, 79, 78, 84, 65, 76, 45, 48, 48, 45, - 48, 48, 128, 72, 79, 82, 73, 90, 79, 78, 84, 65, 76, 128, 72, 79, 82, 73, - 90, 79, 78, 84, 65, 204, 72, 79, 82, 73, 128, 72, 79, 82, 193, 72, 79, - 79, 85, 128, 72, 79, 79, 82, 85, 128, 72, 79, 79, 80, 128, 72, 79, 79, - 78, 128, 72, 79, 79, 75, 69, 68, 128, 72, 79, 79, 75, 69, 196, 72, 79, - 78, 69, 89, 66, 69, 69, 128, 72, 79, 78, 69, 217, 72, 79, 77, 79, 84, 72, - 69, 84, 73, 67, 128, 72, 79, 77, 79, 84, 72, 69, 84, 73, 195, 72, 79, 76, - 79, 128, 72, 79, 76, 76, 79, 215, 72, 79, 76, 69, 128, 72, 79, 76, 68, - 73, 78, 199, 72, 79, 76, 65, 77, 128, 72, 79, 76, 65, 205, 72, 79, 75, - 65, 128, 72, 79, 67, 75, 69, 217, 72, 79, 67, 72, 79, 128, 72, 79, 45, - 56, 128, 72, 79, 45, 55, 128, 72, 79, 45, 54, 128, 72, 79, 45, 53, 128, - 72, 79, 45, 52, 128, 72, 79, 45, 51, 128, 72, 79, 45, 50, 128, 72, 79, - 45, 49, 128, 72, 78, 85, 84, 128, 72, 78, 85, 79, 88, 128, 72, 78, 85, - 79, 128, 72, 78, 85, 66, 128, 72, 78, 79, 88, 128, 72, 78, 79, 84, 128, - 72, 78, 79, 80, 128, 72, 78, 73, 88, 128, 72, 78, 73, 84, 128, 72, 78, - 73, 80, 128, 72, 78, 73, 69, 88, 128, 72, 78, 73, 69, 84, 128, 72, 78, - 73, 69, 80, 128, 72, 78, 73, 69, 128, 72, 78, 73, 128, 72, 78, 69, 88, - 128, 72, 78, 69, 80, 128, 72, 78, 69, 128, 72, 78, 65, 88, 128, 72, 78, - 65, 85, 128, 72, 78, 65, 84, 128, 72, 78, 65, 80, 128, 72, 78, 65, 128, - 72, 77, 89, 88, 128, 72, 77, 89, 82, 88, 128, 72, 77, 89, 82, 128, 72, - 77, 89, 80, 128, 72, 77, 89, 128, 72, 77, 85, 88, 128, 72, 77, 85, 84, - 128, 72, 77, 85, 82, 88, 128, 72, 77, 85, 82, 128, 72, 77, 85, 80, 128, - 72, 77, 85, 79, 88, 128, 72, 77, 85, 79, 80, 128, 72, 77, 85, 79, 128, - 72, 77, 85, 128, 72, 77, 79, 88, 128, 72, 77, 79, 84, 128, 72, 77, 79, - 80, 128, 72, 77, 79, 128, 72, 77, 73, 88, 128, 72, 77, 73, 84, 128, 72, - 77, 73, 80, 128, 72, 77, 73, 69, 88, 128, 72, 77, 73, 69, 80, 128, 72, - 77, 73, 69, 128, 72, 77, 73, 128, 72, 77, 69, 128, 72, 77, 65, 88, 128, - 72, 77, 65, 84, 128, 72, 77, 65, 80, 128, 72, 77, 65, 128, 72, 76, 89, - 88, 128, 72, 76, 89, 84, 128, 72, 76, 89, 82, 88, 128, 72, 76, 89, 82, - 128, 72, 76, 89, 80, 128, 72, 76, 89, 128, 72, 76, 85, 88, 128, 72, 76, - 85, 84, 128, 72, 76, 85, 82, 88, 128, 72, 76, 85, 82, 128, 72, 76, 85, - 80, 128, 72, 76, 85, 79, 88, 128, 72, 76, 85, 79, 80, 128, 72, 76, 85, - 79, 128, 72, 76, 85, 128, 72, 76, 79, 88, 128, 72, 76, 79, 80, 128, 72, - 76, 79, 128, 72, 76, 73, 88, 128, 72, 76, 73, 84, 128, 72, 76, 73, 80, - 128, 72, 76, 73, 69, 88, 128, 72, 76, 73, 69, 80, 128, 72, 76, 73, 69, - 128, 72, 76, 73, 128, 72, 76, 69, 88, 128, 72, 76, 69, 80, 128, 72, 76, - 69, 128, 72, 76, 65, 88, 128, 72, 76, 65, 85, 128, 72, 76, 65, 84, 128, - 72, 76, 65, 80, 128, 72, 76, 65, 128, 72, 76, 128, 72, 75, 128, 72, 73, - 90, 66, 128, 72, 73, 89, 79, 128, 72, 73, 84, 84, 73, 78, 199, 72, 73, - 83, 84, 79, 82, 73, 195, 72, 73, 82, 73, 81, 128, 72, 73, 80, 80, 79, 80, - 79, 84, 65, 77, 85, 83, 128, 72, 73, 78, 71, 69, 68, 128, 72, 73, 78, 71, - 69, 196, 72, 73, 78, 71, 69, 128, 72, 73, 78, 68, 213, 72, 73, 75, 73, - 78, 199, 72, 73, 71, 72, 45, 83, 80, 69, 69, 196, 72, 73, 71, 72, 45, 82, - 69, 86, 69, 82, 83, 69, 68, 45, 185, 72, 73, 71, 72, 45, 76, 79, 215, 72, - 73, 71, 72, 45, 72, 69, 69, 76, 69, 196, 72, 73, 69, 88, 128, 72, 73, 69, - 85, 72, 45, 83, 73, 79, 83, 128, 72, 73, 69, 85, 72, 45, 82, 73, 69, 85, - 76, 128, 72, 73, 69, 85, 72, 45, 80, 73, 69, 85, 80, 128, 72, 73, 69, 85, - 72, 45, 78, 73, 69, 85, 78, 128, 72, 73, 69, 85, 72, 45, 77, 73, 69, 85, - 77, 128, 72, 73, 69, 85, 200, 72, 73, 69, 82, 79, 71, 76, 89, 80, 72, 73, - 195, 72, 73, 68, 73, 78, 199, 72, 73, 68, 69, 84, 128, 72, 73, 68, 69, - 128, 72, 73, 66, 73, 83, 67, 85, 83, 128, 72, 73, 45, 82, 69, 83, 128, - 72, 73, 45, 55, 128, 72, 73, 45, 54, 128, 72, 73, 45, 53, 128, 72, 73, - 45, 52, 128, 72, 73, 45, 51, 128, 72, 73, 45, 50, 128, 72, 73, 45, 49, - 128, 72, 72, 89, 85, 128, 72, 72, 89, 79, 128, 72, 72, 89, 73, 128, 72, - 72, 89, 69, 69, 128, 72, 72, 89, 69, 128, 72, 72, 89, 65, 65, 128, 72, - 72, 89, 65, 128, 72, 72, 87, 73, 128, 72, 72, 87, 69, 69, 128, 72, 72, - 87, 69, 128, 72, 72, 87, 65, 128, 72, 72, 85, 128, 72, 72, 73, 128, 72, - 72, 69, 69, 128, 72, 72, 69, 128, 72, 72, 65, 65, 128, 72, 71, 128, 72, - 69, 89, 84, 128, 72, 69, 88, 73, 70, 79, 82, 205, 72, 69, 88, 65, 71, 82, - 65, 205, 72, 69, 88, 65, 71, 79, 78, 128, 72, 69, 82, 85, 84, 85, 128, - 72, 69, 82, 85, 128, 72, 69, 82, 77, 73, 84, 73, 65, 206, 72, 69, 82, 77, - 73, 79, 78, 73, 65, 206, 72, 69, 82, 77, 69, 83, 128, 72, 69, 82, 69, - 128, 72, 69, 82, 66, 128, 72, 69, 82, 65, 69, 85, 205, 72, 69, 78, 71, - 128, 72, 69, 78, 199, 72, 69, 77, 80, 128, 72, 69, 76, 77, 69, 84, 128, - 72, 69, 76, 77, 69, 212, 72, 69, 76, 205, 72, 69, 76, 76, 83, 67, 72, 82, - 69, 73, 66, 69, 210, 72, 69, 76, 73, 88, 128, 72, 69, 76, 73, 67, 79, 80, - 84, 69, 82, 128, 72, 69, 75, 85, 84, 65, 65, 82, 85, 128, 72, 69, 73, 83, - 69, 73, 128, 72, 69, 73, 71, 72, 84, 128, 72, 69, 69, 73, 128, 72, 69, - 68, 71, 69, 72, 79, 71, 128, 72, 69, 65, 86, 89, 128, 72, 69, 65, 86, 69, - 78, 76, 217, 72, 69, 65, 86, 69, 78, 128, 72, 69, 65, 86, 69, 206, 72, - 69, 65, 82, 84, 83, 128, 72, 69, 65, 82, 84, 45, 83, 72, 65, 80, 69, 196, - 72, 69, 65, 82, 84, 128, 72, 69, 65, 82, 212, 72, 69, 65, 82, 73, 78, - 199, 72, 69, 65, 82, 45, 78, 79, 45, 69, 86, 73, 204, 72, 69, 65, 68, 83, - 84, 82, 79, 75, 69, 128, 72, 69, 65, 68, 83, 84, 79, 78, 69, 128, 72, 69, - 65, 68, 83, 84, 79, 78, 197, 72, 69, 65, 68, 83, 67, 65, 82, 70, 128, 72, - 69, 65, 68, 80, 72, 79, 78, 69, 128, 72, 69, 65, 68, 73, 78, 71, 128, 72, - 69, 65, 68, 45, 66, 65, 78, 68, 65, 71, 69, 128, 72, 69, 45, 55, 128, 72, - 69, 45, 54, 128, 72, 69, 45, 53, 128, 72, 69, 45, 52, 128, 72, 69, 45, - 51, 128, 72, 69, 45, 50, 128, 72, 69, 45, 49, 128, 72, 68, 82, 128, 72, - 67, 128, 72, 66, 65, 83, 65, 45, 69, 83, 65, 83, 193, 72, 66, 65, 83, - 193, 72, 65, 89, 65, 78, 78, 65, 128, 72, 65, 87, 74, 128, 72, 65, 86, - 69, 128, 72, 65, 85, 80, 84, 83, 84, 73, 77, 77, 69, 128, 72, 65, 85, 77, - 69, 65, 128, 72, 65, 213, 72, 65, 84, 82, 65, 206, 72, 65, 84, 72, 73, - 128, 72, 65, 84, 69, 128, 72, 65, 84, 67, 72, 73, 78, 199, 72, 65, 84, - 65, 198, 72, 65, 83, 69, 210, 72, 65, 83, 65, 78, 84, 65, 128, 72, 65, - 82, 80, 79, 79, 78, 128, 72, 65, 82, 80, 79, 79, 206, 72, 65, 82, 77, 79, - 78, 73, 67, 128, 72, 65, 82, 75, 76, 69, 65, 206, 72, 65, 82, 68, 78, 69, - 83, 83, 128, 72, 65, 82, 196, 72, 65, 82, 66, 65, 72, 65, 89, 128, 72, - 65, 80, 80, 217, 72, 65, 78, 85, 78, 79, 207, 72, 65, 78, 73, 70, 201, - 72, 65, 78, 71, 90, 72, 79, 213, 72, 65, 78, 68, 83, 72, 65, 75, 69, 128, - 72, 65, 78, 68, 83, 128, 72, 65, 78, 68, 211, 72, 65, 78, 68, 76, 69, 83, - 128, 72, 65, 78, 68, 76, 69, 128, 72, 65, 78, 68, 66, 65, 76, 76, 128, - 72, 65, 78, 68, 66, 65, 71, 128, 72, 65, 78, 68, 45, 79, 86, 65, 76, 128, - 72, 65, 78, 68, 45, 79, 86, 65, 204, 72, 65, 78, 68, 45, 72, 79, 79, 75, - 128, 72, 65, 78, 68, 45, 72, 79, 79, 203, 72, 65, 78, 68, 45, 72, 73, 78, - 71, 69, 128, 72, 65, 78, 68, 45, 72, 73, 78, 71, 197, 72, 65, 78, 68, 45, - 70, 76, 65, 84, 128, 72, 65, 78, 68, 45, 70, 76, 65, 212, 72, 65, 78, 68, - 45, 70, 73, 83, 84, 128, 72, 65, 78, 68, 45, 67, 85, 82, 76, 73, 67, 85, - 69, 128, 72, 65, 78, 68, 45, 67, 85, 82, 76, 73, 67, 85, 197, 72, 65, 78, - 68, 45, 67, 85, 80, 128, 72, 65, 78, 68, 45, 67, 85, 208, 72, 65, 78, 68, - 45, 67, 76, 65, 87, 128, 72, 65, 78, 68, 45, 67, 76, 65, 215, 72, 65, 78, - 68, 45, 67, 73, 82, 67, 76, 69, 128, 72, 65, 78, 68, 45, 67, 73, 82, 67, - 76, 197, 72, 65, 78, 68, 45, 65, 78, 71, 76, 69, 128, 72, 65, 78, 68, 45, - 65, 78, 71, 76, 197, 72, 65, 78, 68, 128, 72, 65, 78, 45, 65, 75, 65, 84, - 128, 72, 65, 77, 90, 65, 128, 72, 65, 77, 90, 193, 72, 65, 77, 83, 84, - 69, 210, 72, 65, 77, 83, 65, 128, 72, 65, 77, 77, 69, 82, 128, 72, 65, - 77, 77, 69, 210, 72, 65, 77, 66, 85, 82, 71, 69, 82, 128, 72, 65, 76, 81, - 65, 128, 72, 65, 76, 79, 128, 72, 65, 76, 70, 45, 67, 73, 82, 67, 76, - 197, 72, 65, 76, 70, 45, 50, 128, 72, 65, 76, 70, 45, 49, 128, 72, 65, - 76, 70, 128, 72, 65, 76, 66, 69, 82, 68, 128, 72, 65, 76, 65, 78, 84, 65, - 128, 72, 65, 73, 84, 85, 128, 72, 65, 73, 211, 72, 65, 73, 82, 67, 85, - 84, 128, 72, 65, 71, 76, 65, 218, 72, 65, 71, 76, 128, 72, 65, 70, 85, - 75, 72, 65, 128, 72, 65, 70, 85, 75, 72, 128, 72, 65, 69, 71, 204, 72, - 65, 68, 69, 83, 128, 72, 65, 65, 82, 85, 128, 72, 65, 65, 77, 128, 72, - 65, 193, 72, 65, 45, 72, 65, 128, 72, 65, 45, 57, 128, 72, 65, 45, 56, - 128, 72, 65, 45, 55, 128, 72, 65, 45, 54, 128, 72, 65, 45, 53, 128, 72, - 65, 45, 52, 128, 72, 65, 45, 51, 128, 72, 65, 45, 50, 128, 72, 65, 45, - 49, 49, 128, 72, 65, 45, 49, 48, 128, 72, 65, 45, 49, 128, 72, 48, 48, - 56, 128, 72, 48, 48, 55, 128, 72, 48, 48, 54, 65, 128, 72, 48, 48, 54, - 128, 72, 48, 48, 53, 128, 72, 48, 48, 52, 128, 72, 48, 48, 51, 128, 72, - 48, 48, 50, 128, 72, 48, 48, 49, 128, 72, 45, 84, 89, 80, 197, 71, 89, - 85, 128, 71, 89, 79, 78, 128, 71, 89, 79, 128, 71, 89, 73, 128, 71, 89, - 70, 213, 71, 89, 69, 69, 128, 71, 89, 65, 83, 128, 71, 89, 65, 65, 128, - 71, 89, 65, 128, 71, 89, 128, 71, 87, 85, 128, 71, 87, 73, 128, 71, 87, - 69, 69, 128, 71, 87, 69, 128, 71, 87, 65, 65, 128, 71, 87, 65, 128, 71, - 87, 128, 71, 86, 65, 78, 71, 128, 71, 86, 128, 71, 85, 82, 85, 83, 72, - 128, 71, 85, 82, 85, 78, 128, 71, 85, 82, 77, 85, 75, 72, 201, 71, 85, - 82, 65, 77, 85, 84, 79, 78, 128, 71, 85, 82, 65, 71, 197, 71, 85, 82, 55, - 128, 71, 85, 78, 85, 128, 71, 85, 78, 213, 71, 85, 78, 74, 65, 76, 193, - 71, 85, 205, 71, 85, 76, 128, 71, 85, 74, 65, 82, 65, 84, 201, 71, 85, - 73, 84, 65, 82, 128, 71, 85, 73, 68, 197, 71, 85, 199, 71, 85, 69, 73, - 128, 71, 85, 69, 72, 128, 71, 85, 69, 200, 71, 85, 68, 128, 71, 85, 196, - 71, 85, 65, 82, 68, 83, 77, 65, 78, 128, 71, 85, 65, 82, 68, 69, 68, 78, - 69, 83, 83, 128, 71, 85, 65, 82, 68, 69, 196, 71, 85, 65, 82, 68, 128, - 71, 85, 65, 82, 65, 78, 201, 71, 85, 193, 71, 85, 178, 71, 84, 69, 210, - 71, 83, 85, 77, 128, 71, 83, 85, 205, 71, 82, 213, 71, 82, 79, 87, 73, - 78, 199, 71, 82, 79, 85, 78, 68, 128, 71, 82, 79, 78, 84, 72, 73, 83, 77, - 65, 84, 65, 128, 71, 82, 79, 77, 79, 80, 79, 86, 79, 68, 78, 65, 89, 65, - 128, 71, 82, 79, 77, 79, 80, 79, 86, 79, 68, 78, 65, 89, 193, 71, 82, 79, - 77, 79, 75, 82, 89, 90, 72, 69, 86, 65, 89, 65, 128, 71, 82, 79, 77, 79, - 75, 82, 89, 90, 72, 69, 86, 65, 89, 193, 71, 82, 79, 77, 78, 65, 89, 65, - 128, 71, 82, 79, 77, 78, 65, 89, 193, 71, 82, 73, 78, 78, 73, 78, 199, - 71, 82, 73, 77, 65, 67, 73, 78, 199, 71, 82, 69, 217, 71, 82, 69, 71, 79, - 82, 73, 65, 206, 71, 82, 69, 69, 78, 128, 71, 82, 69, 69, 206, 71, 82, - 69, 65, 84, 78, 69, 83, 83, 128, 71, 82, 69, 65, 84, 69, 82, 45, 84, 72, - 65, 78, 128, 71, 82, 69, 65, 84, 69, 82, 45, 84, 72, 65, 206, 71, 82, 69, - 65, 84, 69, 210, 71, 82, 69, 65, 212, 71, 82, 65, 86, 69, 89, 65, 82, - 196, 71, 82, 65, 86, 69, 45, 77, 65, 67, 82, 79, 78, 128, 71, 82, 65, 86, - 69, 45, 65, 67, 85, 84, 69, 45, 71, 82, 65, 86, 69, 128, 71, 82, 65, 86, - 197, 71, 82, 65, 84, 69, 82, 128, 71, 82, 65, 83, 83, 128, 71, 82, 65, - 83, 211, 71, 82, 65, 83, 208, 71, 82, 65, 80, 72, 69, 77, 197, 71, 82, - 65, 80, 69, 83, 128, 71, 82, 65, 78, 84, 72, 193, 71, 82, 65, 77, 77, - 193, 71, 82, 65, 73, 78, 128, 71, 82, 65, 70, 128, 71, 82, 65, 68, 85, - 65, 84, 73, 79, 206, 71, 82, 65, 68, 85, 65, 76, 128, 71, 82, 65, 67, 69, - 128, 71, 82, 65, 67, 197, 71, 80, 65, 128, 71, 79, 82, 84, 72, 77, 73, - 75, 79, 206, 71, 79, 82, 84, 128, 71, 79, 82, 73, 76, 76, 65, 128, 71, - 79, 82, 71, 79, 84, 69, 82, 73, 128, 71, 79, 82, 71, 79, 83, 89, 78, 84, - 72, 69, 84, 79, 78, 128, 71, 79, 82, 71, 79, 206, 71, 79, 82, 71, 73, - 128, 71, 79, 82, 65, 90, 68, 207, 71, 79, 82, 65, 128, 71, 79, 79, 83, - 69, 128, 71, 79, 79, 196, 71, 79, 78, 71, 71, 79, 78, 71, 128, 71, 79, - 76, 85, 66, 67, 72, 73, 203, 71, 79, 76, 70, 69, 82, 128, 71, 79, 76, 68, - 128, 71, 79, 75, 128, 71, 79, 73, 78, 199, 71, 79, 71, 71, 76, 69, 83, - 128, 71, 79, 66, 76, 73, 78, 128, 71, 79, 65, 76, 128, 71, 79, 65, 204, - 71, 79, 65, 128, 71, 78, 89, 73, 83, 128, 71, 78, 65, 86, 73, 89, 65, 78, - 73, 128, 71, 76, 79, 87, 73, 78, 199, 71, 76, 79, 86, 69, 83, 128, 71, - 76, 79, 86, 69, 128, 71, 76, 79, 84, 84, 65, 204, 71, 76, 79, 66, 197, - 71, 76, 73, 83, 83, 65, 78, 68, 207, 71, 76, 69, 73, 67, 200, 71, 76, 65, - 71, 79, 76, 73, 128, 71, 76, 65, 128, 71, 74, 69, 128, 71, 73, 88, 128, - 71, 73, 84, 128, 71, 73, 83, 72, 128, 71, 73, 83, 200, 71, 73, 83, 65, - 76, 128, 71, 73, 82, 85, 68, 65, 65, 128, 71, 73, 82, 76, 211, 71, 73, - 82, 76, 128, 71, 73, 82, 65, 70, 70, 197, 71, 73, 82, 51, 128, 71, 73, - 82, 179, 71, 73, 82, 50, 128, 71, 73, 82, 178, 71, 73, 80, 128, 71, 73, - 78, 73, 73, 128, 71, 73, 78, 71, 69, 210, 71, 73, 77, 69, 76, 45, 72, 69, - 84, 72, 128, 71, 73, 77, 69, 76, 128, 71, 73, 77, 69, 204, 71, 73, 77, - 128, 71, 73, 71, 65, 128, 71, 73, 71, 128, 71, 73, 70, 212, 71, 73, 69, - 84, 128, 71, 73, 68, 73, 77, 128, 71, 73, 66, 66, 79, 85, 211, 71, 73, - 66, 65, 128, 71, 73, 52, 128, 71, 73, 180, 71, 72, 90, 128, 71, 72, 87, - 65, 128, 71, 72, 85, 78, 78, 65, 128, 71, 72, 85, 78, 78, 193, 71, 72, - 85, 128, 71, 72, 79, 85, 128, 71, 72, 79, 83, 84, 128, 71, 72, 79, 128, - 71, 72, 73, 77, 69, 76, 128, 71, 72, 73, 128, 71, 72, 72, 65, 128, 71, - 72, 69, 89, 83, 128, 71, 72, 69, 85, 88, 128, 71, 72, 69, 85, 78, 128, - 71, 72, 69, 85, 71, 72, 69, 85, 65, 69, 77, 128, 71, 72, 69, 85, 71, 72, - 69, 78, 128, 71, 72, 69, 85, 65, 69, 82, 65, 69, 128, 71, 72, 69, 85, 65, - 69, 71, 72, 69, 85, 65, 69, 128, 71, 72, 69, 84, 128, 71, 72, 69, 69, - 128, 71, 72, 69, 128, 71, 72, 197, 71, 72, 65, 89, 78, 128, 71, 72, 65, - 82, 65, 69, 128, 71, 72, 65, 80, 128, 71, 72, 65, 78, 128, 71, 72, 65, - 77, 77, 65, 128, 71, 72, 65, 77, 65, 76, 128, 71, 72, 65, 73, 78, 85, - 128, 71, 72, 65, 73, 78, 128, 71, 72, 65, 73, 206, 71, 72, 65, 68, 128, - 71, 72, 65, 65, 77, 65, 69, 128, 71, 72, 65, 65, 128, 71, 71, 87, 73, - 128, 71, 71, 87, 69, 69, 128, 71, 71, 87, 69, 128, 71, 71, 87, 65, 65, - 128, 71, 71, 87, 65, 128, 71, 71, 85, 88, 128, 71, 71, 85, 84, 128, 71, - 71, 85, 82, 88, 128, 71, 71, 85, 82, 128, 71, 71, 85, 79, 88, 128, 71, - 71, 85, 79, 84, 128, 71, 71, 85, 79, 80, 128, 71, 71, 85, 79, 128, 71, - 71, 79, 88, 128, 71, 71, 79, 84, 128, 71, 71, 79, 80, 128, 71, 71, 73, - 88, 128, 71, 71, 73, 84, 128, 71, 71, 73, 69, 88, 128, 71, 71, 73, 69, - 80, 128, 71, 71, 73, 69, 128, 71, 71, 69, 88, 128, 71, 71, 69, 84, 128, - 71, 71, 69, 80, 128, 71, 71, 65, 88, 128, 71, 71, 65, 84, 128, 71, 69, - 84, 193, 71, 69, 83, 84, 85, 82, 69, 128, 71, 69, 83, 72, 85, 128, 71, - 69, 83, 72, 84, 73, 78, 128, 71, 69, 83, 72, 84, 73, 206, 71, 69, 83, 72, - 50, 128, 71, 69, 82, 83, 72, 65, 89, 73, 77, 128, 71, 69, 82, 77, 65, - 206, 71, 69, 82, 69, 83, 72, 128, 71, 69, 82, 69, 83, 200, 71, 69, 79, - 77, 69, 84, 82, 73, 67, 65, 76, 76, 217, 71, 69, 79, 77, 69, 84, 82, 73, - 195, 71, 69, 78, 84, 76, 197, 71, 69, 78, 73, 84, 73, 86, 69, 128, 71, - 69, 78, 73, 75, 201, 71, 69, 78, 73, 69, 128, 71, 69, 78, 69, 82, 73, - 195, 71, 69, 78, 69, 82, 65, 76, 128, 71, 69, 77, 73, 78, 73, 128, 71, - 69, 77, 73, 78, 65, 84, 73, 79, 206, 71, 69, 77, 73, 78, 65, 84, 197, 71, - 69, 205, 71, 69, 69, 77, 128, 71, 69, 68, 79, 76, 65, 128, 71, 69, 68, - 69, 128, 71, 69, 66, 207, 71, 69, 66, 193, 71, 69, 65, 82, 128, 71, 69, - 65, 210, 71, 69, 50, 50, 128, 71, 68, 65, 78, 128, 71, 67, 73, 71, 128, - 71, 67, 65, 206, 71, 66, 79, 78, 128, 71, 66, 73, 69, 197, 71, 66, 69, - 85, 88, 128, 71, 66, 69, 84, 128, 71, 66, 65, 89, 73, 128, 71, 66, 65, - 75, 85, 82, 85, 78, 69, 78, 128, 71, 66, 128, 71, 65, 89, 65, 78, 85, 75, - 73, 84, 84, 65, 128, 71, 65, 89, 65, 78, 78, 65, 128, 71, 65, 89, 128, - 71, 65, 85, 78, 84, 76, 69, 84, 128, 71, 65, 84, 72, 69, 82, 73, 78, 71, - 128, 71, 65, 84, 72, 69, 82, 73, 78, 199, 71, 65, 84, 69, 128, 71, 65, - 83, 72, 65, 78, 128, 71, 65, 82, 83, 72, 85, 78, 73, 128, 71, 65, 82, 79, - 78, 128, 71, 65, 82, 77, 69, 78, 84, 128, 71, 65, 82, 76, 73, 67, 128, - 71, 65, 82, 68, 69, 78, 128, 71, 65, 82, 51, 128, 71, 65, 80, 80, 69, - 196, 71, 65, 208, 71, 65, 78, 77, 65, 128, 71, 65, 78, 71, 73, 65, 128, - 71, 65, 78, 68, 193, 71, 65, 78, 50, 128, 71, 65, 78, 178, 71, 65, 77, - 77, 65, 128, 71, 65, 77, 76, 65, 128, 71, 65, 77, 76, 128, 71, 65, 77, - 69, 128, 71, 65, 77, 197, 71, 65, 77, 65, 78, 128, 71, 65, 77, 65, 76, - 128, 71, 65, 77, 65, 204, 71, 65, 76, 201, 71, 65, 71, 128, 71, 65, 70, - 128, 71, 65, 198, 71, 65, 69, 84, 84, 65, 45, 80, 73, 76, 76, 65, 128, - 71, 65, 68, 79, 76, 128, 71, 65, 68, 128, 71, 65, 196, 71, 65, 66, 65, - 128, 71, 65, 66, 193, 71, 65, 65, 70, 85, 128, 71, 65, 178, 71, 48, 53, - 52, 128, 71, 48, 53, 51, 128, 71, 48, 53, 50, 128, 71, 48, 53, 49, 128, - 71, 48, 53, 48, 128, 71, 48, 52, 57, 128, 71, 48, 52, 56, 128, 71, 48, - 52, 55, 128, 71, 48, 52, 54, 128, 71, 48, 52, 53, 65, 128, 71, 48, 52, - 53, 128, 71, 48, 52, 52, 128, 71, 48, 52, 51, 65, 128, 71, 48, 52, 51, - 128, 71, 48, 52, 50, 128, 71, 48, 52, 49, 128, 71, 48, 52, 48, 128, 71, - 48, 51, 57, 128, 71, 48, 51, 56, 128, 71, 48, 51, 55, 65, 128, 71, 48, - 51, 55, 128, 71, 48, 51, 54, 65, 128, 71, 48, 51, 54, 128, 71, 48, 51, - 53, 128, 71, 48, 51, 52, 128, 71, 48, 51, 51, 128, 71, 48, 51, 50, 128, - 71, 48, 51, 49, 128, 71, 48, 51, 48, 128, 71, 48, 50, 57, 128, 71, 48, - 50, 56, 128, 71, 48, 50, 55, 128, 71, 48, 50, 54, 65, 128, 71, 48, 50, - 54, 128, 71, 48, 50, 53, 128, 71, 48, 50, 52, 128, 71, 48, 50, 51, 128, - 71, 48, 50, 50, 128, 71, 48, 50, 49, 128, 71, 48, 50, 48, 65, 128, 71, - 48, 50, 48, 128, 71, 48, 49, 57, 128, 71, 48, 49, 56, 128, 71, 48, 49, - 55, 128, 71, 48, 49, 54, 128, 71, 48, 49, 53, 128, 71, 48, 49, 52, 128, - 71, 48, 49, 51, 128, 71, 48, 49, 50, 128, 71, 48, 49, 49, 65, 128, 71, - 48, 49, 49, 128, 71, 48, 49, 48, 128, 71, 48, 48, 57, 128, 71, 48, 48, - 56, 128, 71, 48, 48, 55, 66, 128, 71, 48, 48, 55, 65, 128, 71, 48, 48, - 55, 128, 71, 48, 48, 54, 65, 128, 71, 48, 48, 54, 128, 71, 48, 48, 53, - 128, 71, 48, 48, 52, 128, 71, 48, 48, 51, 128, 71, 48, 48, 50, 128, 71, - 48, 48, 49, 128, 70, 89, 88, 128, 70, 89, 84, 128, 70, 89, 80, 128, 70, - 89, 65, 128, 70, 87, 73, 128, 70, 87, 69, 69, 128, 70, 87, 69, 128, 70, - 87, 65, 65, 128, 70, 87, 65, 128, 70, 86, 83, 52, 128, 70, 86, 83, 51, - 128, 70, 86, 83, 50, 128, 70, 86, 83, 49, 128, 70, 85, 88, 128, 70, 85, - 84, 128, 70, 85, 83, 69, 128, 70, 85, 83, 193, 70, 85, 82, 88, 128, 70, - 85, 80, 128, 70, 85, 78, 69, 82, 65, 204, 70, 85, 78, 67, 84, 73, 79, 78, - 65, 204, 70, 85, 78, 67, 84, 73, 79, 78, 128, 70, 85, 76, 76, 87, 73, 68, - 84, 200, 70, 85, 76, 76, 78, 69, 83, 83, 128, 70, 85, 76, 204, 70, 85, - 74, 73, 128, 70, 85, 69, 84, 128, 70, 85, 69, 204, 70, 85, 69, 128, 70, - 85, 65, 128, 70, 84, 72, 79, 82, 193, 70, 83, 73, 128, 70, 82, 79, 87, - 78, 73, 78, 71, 128, 70, 82, 79, 87, 78, 73, 78, 199, 70, 82, 79, 87, 78, - 128, 70, 82, 79, 87, 206, 70, 82, 79, 78, 84, 45, 84, 73, 76, 84, 69, - 196, 70, 82, 79, 78, 84, 45, 70, 65, 67, 73, 78, 199, 70, 82, 79, 78, - 212, 70, 82, 79, 205, 70, 82, 79, 71, 128, 70, 82, 79, 199, 70, 82, 73, - 84, 85, 128, 70, 82, 73, 69, 83, 128, 70, 82, 73, 69, 196, 70, 82, 73, - 67, 65, 84, 73, 86, 69, 128, 70, 82, 69, 84, 66, 79, 65, 82, 68, 128, 70, - 82, 69, 78, 67, 200, 70, 82, 69, 69, 90, 73, 78, 199, 70, 82, 69, 69, - 128, 70, 82, 69, 197, 70, 82, 65, 78, 75, 211, 70, 82, 65, 78, 195, 70, - 82, 65, 77, 69, 83, 128, 70, 82, 65, 77, 69, 128, 70, 82, 65, 77, 197, - 70, 82, 65, 75, 84, 85, 210, 70, 82, 65, 71, 82, 65, 78, 84, 128, 70, 82, - 65, 71, 77, 69, 78, 84, 128, 70, 82, 65, 67, 84, 73, 79, 206, 70, 79, 88, - 128, 70, 79, 216, 70, 79, 85, 82, 84, 69, 69, 78, 128, 70, 79, 85, 82, - 84, 69, 69, 206, 70, 79, 85, 82, 45, 84, 72, 73, 82, 84, 89, 128, 70, 79, - 85, 82, 45, 83, 84, 82, 73, 78, 199, 70, 79, 85, 82, 45, 80, 69, 82, 45, - 69, 205, 70, 79, 85, 82, 45, 76, 73, 78, 197, 70, 79, 85, 210, 70, 79, - 85, 78, 84, 65, 73, 78, 128, 70, 79, 85, 78, 84, 65, 73, 206, 70, 79, 83, - 84, 69, 82, 73, 78, 71, 128, 70, 79, 82, 87, 65, 82, 68, 128, 70, 79, 82, - 87, 65, 82, 196, 70, 79, 82, 84, 89, 45, 70, 73, 86, 197, 70, 79, 82, 84, - 89, 128, 70, 79, 82, 84, 217, 70, 79, 82, 84, 85, 78, 69, 128, 70, 79, - 82, 84, 85, 78, 197, 70, 79, 82, 84, 73, 69, 84, 72, 128, 70, 79, 82, 84, - 69, 128, 70, 79, 82, 77, 211, 70, 79, 82, 77, 69, 69, 128, 70, 79, 82, - 77, 69, 197, 70, 79, 82, 77, 65, 84, 84, 73, 78, 71, 128, 70, 79, 82, 77, - 65, 212, 70, 79, 82, 75, 69, 196, 70, 79, 82, 69, 72, 69, 65, 196, 70, - 79, 82, 67, 69, 83, 128, 70, 79, 82, 67, 69, 128, 70, 79, 80, 128, 70, - 79, 79, 84, 83, 84, 79, 79, 76, 128, 70, 79, 79, 84, 80, 82, 73, 78, 84, - 83, 128, 70, 79, 79, 84, 78, 79, 84, 197, 70, 79, 79, 84, 66, 65, 76, 76, - 128, 70, 79, 79, 84, 128, 70, 79, 79, 76, 128, 70, 79, 79, 68, 128, 70, - 79, 79, 128, 70, 79, 78, 212, 70, 79, 78, 71, 77, 65, 78, 128, 70, 79, - 78, 68, 85, 69, 128, 70, 79, 77, 128, 70, 79, 76, 76, 89, 128, 70, 79, - 76, 76, 79, 87, 73, 78, 71, 128, 70, 79, 76, 68, 73, 78, 199, 70, 79, 76, - 68, 69, 82, 128, 70, 79, 76, 68, 69, 196, 70, 79, 71, 71, 89, 128, 70, - 79, 71, 128, 70, 207, 70, 77, 128, 70, 76, 89, 73, 78, 199, 70, 76, 89, - 128, 70, 76, 85, 84, 84, 69, 82, 73, 78, 71, 128, 70, 76, 85, 84, 84, 69, - 82, 73, 78, 199, 70, 76, 85, 84, 69, 128, 70, 76, 85, 83, 72, 69, 196, - 70, 76, 79, 87, 73, 78, 199, 70, 76, 79, 87, 69, 82, 83, 128, 70, 76, 79, - 87, 69, 210, 70, 76, 79, 85, 82, 73, 83, 72, 128, 70, 76, 79, 82, 69, 84, - 84, 69, 128, 70, 76, 79, 82, 65, 204, 70, 76, 79, 80, 80, 217, 70, 76, - 79, 79, 82, 128, 70, 76, 79, 79, 210, 70, 76, 73, 80, 128, 70, 76, 73, - 71, 72, 84, 128, 70, 76, 73, 67, 203, 70, 76, 69, 88, 85, 83, 128, 70, - 76, 69, 88, 69, 196, 70, 76, 69, 88, 128, 70, 76, 69, 85, 82, 79, 78, - 128, 70, 76, 69, 85, 82, 45, 68, 69, 45, 76, 73, 83, 128, 70, 76, 65, 84, - 84, 69, 78, 69, 196, 70, 76, 65, 84, 78, 69, 83, 83, 128, 70, 76, 65, 84, - 66, 82, 69, 65, 68, 128, 70, 76, 65, 83, 72, 128, 70, 76, 65, 77, 73, 78, - 71, 79, 128, 70, 76, 65, 77, 69, 128, 70, 76, 65, 71, 83, 128, 70, 76, - 65, 71, 45, 53, 128, 70, 76, 65, 71, 45, 52, 128, 70, 76, 65, 71, 45, 51, - 128, 70, 76, 65, 71, 45, 50, 128, 70, 76, 65, 71, 45, 49, 128, 70, 76, - 65, 71, 128, 70, 76, 65, 199, 70, 76, 65, 128, 70, 76, 128, 70, 73, 88, - 69, 68, 45, 70, 79, 82, 205, 70, 73, 88, 128, 70, 73, 86, 69, 45, 84, 72, - 73, 82, 84, 89, 128, 70, 73, 86, 69, 45, 76, 73, 78, 197, 70, 73, 86, 69, - 45, 76, 73, 75, 197, 70, 73, 84, 90, 80, 65, 84, 82, 73, 67, 203, 70, 73, - 84, 65, 128, 70, 73, 84, 128, 70, 73, 83, 84, 69, 196, 70, 73, 83, 72, - 73, 78, 199, 70, 73, 83, 72, 72, 79, 79, 75, 128, 70, 73, 83, 72, 72, 79, - 79, 203, 70, 73, 83, 72, 69, 89, 69, 128, 70, 73, 83, 200, 70, 73, 82, - 83, 212, 70, 73, 82, 73, 128, 70, 73, 82, 69, 87, 79, 82, 75, 83, 128, - 70, 73, 82, 69, 87, 79, 82, 203, 70, 73, 82, 69, 67, 82, 65, 67, 75, 69, - 82, 128, 70, 73, 82, 69, 128, 70, 73, 82, 197, 70, 73, 80, 128, 70, 73, - 78, 73, 84, 197, 70, 73, 78, 71, 69, 82, 83, 128, 70, 73, 78, 71, 69, 82, - 211, 70, 73, 78, 71, 69, 82, 78, 65, 73, 76, 83, 128, 70, 73, 78, 71, 69, - 82, 69, 196, 70, 73, 78, 71, 69, 82, 45, 80, 79, 83, 212, 70, 73, 78, 71, - 69, 82, 128, 70, 73, 78, 71, 69, 210, 70, 73, 78, 65, 78, 67, 73, 65, 76, - 128, 70, 73, 78, 65, 76, 128, 70, 73, 76, 205, 70, 73, 76, 76, 69, 82, - 45, 50, 128, 70, 73, 76, 76, 69, 82, 45, 49, 128, 70, 73, 76, 76, 69, 82, - 128, 70, 73, 76, 76, 69, 196, 70, 73, 76, 76, 128, 70, 73, 76, 204, 70, - 73, 76, 197, 70, 73, 73, 128, 70, 73, 71, 85, 82, 69, 45, 51, 128, 70, - 73, 71, 85, 82, 69, 45, 50, 128, 70, 73, 71, 85, 82, 69, 45, 49, 128, 70, - 73, 71, 85, 82, 69, 128, 70, 73, 71, 85, 82, 197, 70, 73, 71, 72, 84, - 128, 70, 73, 70, 84, 89, 128, 70, 73, 70, 84, 217, 70, 73, 70, 84, 72, - 83, 128, 70, 73, 70, 84, 72, 128, 70, 73, 70, 84, 69, 69, 78, 128, 70, - 73, 70, 84, 69, 69, 206, 70, 73, 69, 76, 68, 128, 70, 73, 69, 76, 196, - 70, 72, 84, 79, 82, 193, 70, 70, 76, 128, 70, 70, 73, 128, 70, 69, 85, - 88, 128, 70, 69, 85, 70, 69, 85, 65, 69, 84, 128, 70, 69, 84, 72, 128, - 70, 69, 83, 84, 73, 86, 65, 76, 128, 70, 69, 82, 82, 89, 128, 70, 69, 82, - 82, 73, 211, 70, 69, 82, 77, 65, 84, 65, 128, 70, 69, 82, 77, 65, 84, - 193, 70, 69, 79, 200, 70, 69, 78, 199, 70, 69, 78, 67, 69, 82, 128, 70, - 69, 78, 67, 69, 128, 70, 69, 77, 73, 78, 73, 78, 197, 70, 69, 77, 65, 76, - 69, 128, 70, 69, 77, 65, 76, 197, 70, 69, 76, 76, 79, 87, 83, 72, 73, 80, - 128, 70, 69, 73, 128, 70, 69, 72, 213, 70, 69, 72, 128, 70, 69, 200, 70, - 69, 69, 78, 71, 128, 70, 69, 69, 77, 128, 70, 69, 69, 68, 128, 70, 69, - 69, 196, 70, 69, 69, 128, 70, 69, 66, 82, 85, 65, 82, 89, 128, 70, 69, - 65, 84, 72, 69, 82, 128, 70, 69, 65, 84, 72, 69, 210, 70, 69, 65, 82, 78, - 128, 70, 69, 65, 82, 70, 85, 204, 70, 69, 65, 82, 128, 70, 65, 89, 65, - 78, 78, 65, 128, 70, 65, 89, 128, 70, 65, 88, 128, 70, 65, 216, 70, 65, - 84, 73, 71, 85, 69, 128, 70, 65, 84, 72, 69, 82, 128, 70, 65, 84, 72, 69, - 210, 70, 65, 84, 72, 65, 84, 65, 78, 128, 70, 65, 84, 72, 65, 84, 65, - 206, 70, 65, 84, 72, 65, 128, 70, 65, 84, 72, 193, 70, 65, 84, 128, 70, - 65, 83, 84, 128, 70, 65, 82, 83, 201, 70, 65, 82, 128, 70, 65, 81, 128, - 70, 65, 80, 128, 70, 65, 78, 71, 128, 70, 65, 78, 69, 82, 79, 83, 73, - 211, 70, 65, 78, 128, 70, 65, 77, 73, 76, 89, 128, 70, 65, 77, 128, 70, - 65, 76, 76, 69, 206, 70, 65, 76, 65, 70, 69, 76, 128, 70, 65, 74, 128, - 70, 65, 73, 82, 89, 128, 70, 65, 73, 76, 85, 82, 69, 128, 70, 65, 73, 72, - 85, 128, 70, 65, 73, 66, 128, 70, 65, 72, 82, 69, 78, 72, 69, 73, 84, - 128, 70, 65, 67, 84, 79, 82, 89, 128, 70, 65, 67, 84, 79, 210, 70, 65, - 67, 83, 73, 77, 73, 76, 197, 70, 65, 67, 73, 78, 71, 83, 128, 70, 65, 67, - 69, 45, 54, 128, 70, 65, 67, 69, 45, 53, 128, 70, 65, 67, 69, 45, 52, - 128, 70, 65, 67, 69, 45, 51, 128, 70, 65, 67, 69, 45, 50, 128, 70, 65, - 67, 69, 45, 49, 128, 70, 65, 65, 77, 65, 69, 128, 70, 65, 65, 73, 128, - 70, 65, 65, 70, 85, 128, 70, 48, 53, 51, 128, 70, 48, 53, 50, 128, 70, - 48, 53, 49, 67, 128, 70, 48, 53, 49, 66, 128, 70, 48, 53, 49, 65, 128, - 70, 48, 53, 49, 128, 70, 48, 53, 48, 128, 70, 48, 52, 57, 128, 70, 48, - 52, 56, 128, 70, 48, 52, 55, 65, 128, 70, 48, 52, 55, 128, 70, 48, 52, - 54, 65, 128, 70, 48, 52, 54, 128, 70, 48, 52, 53, 65, 128, 70, 48, 52, - 53, 128, 70, 48, 52, 52, 128, 70, 48, 52, 51, 128, 70, 48, 52, 50, 128, - 70, 48, 52, 49, 128, 70, 48, 52, 48, 128, 70, 48, 51, 57, 128, 70, 48, - 51, 56, 65, 128, 70, 48, 51, 56, 128, 70, 48, 51, 55, 65, 128, 70, 48, - 51, 55, 128, 70, 48, 51, 54, 128, 70, 48, 51, 53, 128, 70, 48, 51, 52, - 128, 70, 48, 51, 51, 128, 70, 48, 51, 50, 128, 70, 48, 51, 49, 65, 128, - 70, 48, 51, 49, 128, 70, 48, 51, 48, 128, 70, 48, 50, 57, 128, 70, 48, - 50, 56, 128, 70, 48, 50, 55, 128, 70, 48, 50, 54, 128, 70, 48, 50, 53, - 128, 70, 48, 50, 52, 128, 70, 48, 50, 51, 128, 70, 48, 50, 50, 128, 70, - 48, 50, 49, 65, 128, 70, 48, 50, 49, 128, 70, 48, 50, 48, 128, 70, 48, - 49, 57, 128, 70, 48, 49, 56, 128, 70, 48, 49, 55, 128, 70, 48, 49, 54, - 128, 70, 48, 49, 53, 128, 70, 48, 49, 52, 128, 70, 48, 49, 51, 65, 128, - 70, 48, 49, 51, 128, 70, 48, 49, 50, 128, 70, 48, 49, 49, 128, 70, 48, - 49, 48, 128, 70, 48, 48, 57, 128, 70, 48, 48, 56, 128, 70, 48, 48, 55, - 128, 70, 48, 48, 54, 128, 70, 48, 48, 53, 128, 70, 48, 48, 52, 128, 70, - 48, 48, 51, 128, 70, 48, 48, 50, 128, 70, 48, 48, 49, 65, 128, 70, 48, - 48, 49, 128, 69, 90, 83, 128, 69, 90, 69, 78, 128, 69, 90, 69, 206, 69, - 89, 89, 89, 128, 69, 89, 69, 83, 128, 69, 89, 69, 211, 69, 89, 69, 76, - 65, 83, 72, 69, 211, 69, 89, 69, 71, 76, 65, 83, 83, 69, 83, 128, 69, 89, - 69, 71, 65, 90, 69, 45, 87, 65, 76, 76, 80, 76, 65, 78, 197, 69, 89, 69, - 71, 65, 90, 69, 45, 70, 76, 79, 79, 82, 80, 76, 65, 78, 197, 69, 89, 69, - 66, 82, 79, 87, 211, 69, 89, 69, 66, 82, 79, 215, 69, 89, 197, 69, 89, - 66, 69, 89, 70, 73, 76, 73, 128, 69, 89, 65, 78, 78, 65, 128, 69, 88, 84, - 82, 69, 77, 69, 76, 217, 69, 88, 84, 82, 65, 84, 69, 82, 82, 69, 83, 84, - 82, 73, 65, 204, 69, 88, 84, 82, 65, 45, 76, 79, 215, 69, 88, 84, 82, 65, - 45, 72, 73, 71, 200, 69, 88, 84, 82, 193, 69, 88, 84, 73, 78, 71, 85, 73, - 83, 72, 69, 82, 128, 69, 88, 84, 69, 78, 83, 73, 79, 78, 128, 69, 88, 84, - 69, 78, 68, 69, 68, 128, 69, 88, 84, 69, 78, 68, 69, 196, 69, 88, 80, 82, - 69, 83, 83, 73, 79, 78, 76, 69, 83, 211, 69, 88, 80, 79, 78, 69, 78, 212, - 69, 88, 80, 76, 79, 68, 73, 78, 199, 69, 88, 79, 128, 69, 88, 207, 69, - 88, 73, 83, 84, 83, 128, 69, 88, 73, 83, 84, 128, 69, 88, 72, 65, 85, 83, - 84, 73, 79, 78, 128, 69, 88, 72, 65, 76, 69, 128, 69, 88, 67, 76, 65, 77, - 65, 84, 73, 79, 78, 128, 69, 88, 67, 76, 65, 77, 65, 84, 73, 79, 206, 69, - 88, 67, 73, 84, 69, 77, 69, 78, 84, 128, 69, 88, 67, 72, 65, 78, 71, 69, - 128, 69, 88, 67, 69, 83, 83, 128, 69, 88, 67, 69, 76, 76, 69, 78, 84, - 128, 69, 87, 69, 128, 69, 86, 69, 82, 217, 69, 86, 69, 82, 71, 82, 69, - 69, 206, 69, 86, 69, 78, 73, 78, 71, 128, 69, 85, 82, 79, 80, 69, 65, - 206, 69, 85, 82, 79, 80, 69, 45, 65, 70, 82, 73, 67, 65, 128, 69, 85, 82, - 79, 45, 67, 85, 82, 82, 69, 78, 67, 217, 69, 85, 82, 207, 69, 85, 76, 69, - 210, 69, 85, 45, 85, 128, 69, 85, 45, 79, 128, 69, 85, 45, 69, 85, 128, - 69, 85, 45, 69, 79, 128, 69, 85, 45, 69, 128, 69, 85, 45, 65, 128, 69, - 84, 88, 128, 69, 84, 84, 128, 69, 84, 78, 65, 72, 84, 65, 128, 69, 84, - 72, 69, 204, 69, 84, 69, 82, 79, 206, 69, 84, 69, 82, 78, 73, 84, 89, - 128, 69, 84, 69, 82, 78, 73, 84, 217, 69, 84, 66, 128, 69, 83, 90, 128, - 69, 83, 85, 75, 85, 85, 68, 79, 128, 69, 83, 84, 73, 77, 65, 84, 69, 83, - 128, 69, 83, 84, 73, 77, 65, 84, 69, 196, 69, 83, 72, 69, 51, 128, 69, - 83, 72, 50, 49, 128, 69, 83, 72, 49, 54, 128, 69, 83, 67, 65, 80, 69, - 128, 69, 83, 67, 128, 69, 83, 65, 128, 69, 83, 45, 84, 69, 128, 69, 83, - 45, 51, 128, 69, 83, 45, 50, 128, 69, 83, 45, 49, 128, 69, 82, 82, 79, - 82, 45, 66, 65, 82, 82, 69, 196, 69, 82, 82, 128, 69, 82, 73, 211, 69, - 82, 73, 78, 50, 128, 69, 82, 73, 78, 178, 69, 82, 71, 128, 69, 82, 65, - 83, 197, 69, 81, 85, 73, 86, 65, 76, 69, 78, 212, 69, 81, 85, 73, 76, 65, - 84, 69, 82, 65, 204, 69, 81, 85, 73, 72, 79, 80, 80, 69, 82, 128, 69, 81, - 85, 73, 72, 79, 80, 80, 69, 210, 69, 81, 85, 73, 68, 128, 69, 81, 85, 73, - 65, 78, 71, 85, 76, 65, 210, 69, 81, 85, 65, 76, 83, 128, 69, 81, 85, 65, - 76, 211, 69, 81, 85, 65, 76, 128, 69, 81, 85, 65, 204, 69, 80, 83, 73, - 76, 79, 78, 128, 69, 80, 83, 73, 76, 79, 206, 69, 80, 79, 67, 72, 128, - 69, 80, 73, 71, 82, 65, 80, 72, 73, 195, 69, 80, 73, 68, 65, 85, 82, 69, - 65, 206, 69, 80, 69, 78, 84, 72, 69, 84, 73, 195, 69, 80, 69, 71, 69, 82, - 77, 65, 128, 69, 80, 65, 67, 212, 69, 79, 84, 128, 69, 79, 77, 128, 69, - 79, 76, 72, 88, 128, 69, 79, 76, 128, 69, 79, 72, 128, 69, 78, 89, 128, - 69, 78, 86, 69, 76, 79, 80, 69, 128, 69, 78, 86, 69, 76, 79, 80, 197, 69, - 78, 85, 77, 69, 82, 65, 84, 73, 79, 206, 69, 78, 84, 82, 89, 45, 50, 128, - 69, 78, 84, 82, 89, 45, 49, 128, 69, 78, 84, 82, 89, 128, 69, 78, 84, 82, - 217, 69, 78, 84, 72, 85, 83, 73, 65, 83, 77, 128, 69, 78, 84, 69, 82, 80, - 82, 73, 83, 69, 128, 69, 78, 84, 69, 82, 73, 78, 199, 69, 78, 84, 69, 82, - 128, 69, 78, 84, 69, 210, 69, 78, 84, 45, 83, 72, 65, 80, 69, 196, 69, - 78, 81, 85, 73, 82, 89, 128, 69, 78, 81, 128, 69, 78, 79, 211, 69, 78, - 78, 73, 128, 69, 78, 78, 128, 69, 78, 76, 65, 82, 71, 69, 77, 69, 78, 84, - 128, 69, 78, 71, 73, 78, 69, 128, 69, 78, 68, 79, 70, 79, 78, 79, 78, - 128, 69, 78, 68, 73, 78, 199, 69, 78, 68, 69, 80, 128, 69, 78, 68, 69, - 65, 86, 79, 85, 82, 128, 69, 78, 67, 79, 85, 78, 84, 69, 82, 83, 128, 69, - 78, 67, 76, 79, 83, 85, 82, 69, 83, 128, 69, 78, 67, 76, 79, 83, 85, 82, - 69, 128, 69, 78, 67, 76, 79, 83, 73, 78, 199, 69, 78, 67, 128, 69, 78, - 65, 82, 88, 73, 211, 69, 78, 65, 82, 77, 79, 78, 73, 79, 211, 69, 77, 80, - 84, 217, 69, 77, 80, 72, 65, 84, 73, 195, 69, 77, 80, 72, 65, 83, 73, - 211, 69, 77, 79, 74, 201, 69, 77, 66, 82, 79, 73, 68, 69, 82, 89, 128, - 69, 77, 66, 76, 69, 77, 128, 69, 77, 66, 69, 76, 76, 73, 83, 72, 77, 69, - 78, 84, 128, 69, 77, 66, 69, 68, 68, 73, 78, 71, 128, 69, 76, 89, 77, 65, - 73, 195, 69, 76, 89, 128, 69, 76, 84, 128, 69, 76, 76, 73, 80, 84, 73, - 195, 69, 76, 76, 73, 80, 83, 73, 83, 128, 69, 76, 76, 73, 80, 83, 69, - 128, 69, 76, 73, 70, 73, 128, 69, 76, 73, 70, 128, 69, 76, 69, 86, 69, - 78, 45, 84, 72, 73, 82, 84, 89, 128, 69, 76, 69, 86, 69, 78, 128, 69, 76, - 69, 86, 69, 206, 69, 76, 69, 86, 65, 84, 85, 211, 69, 76, 69, 86, 65, 84, - 79, 82, 128, 69, 76, 69, 80, 72, 65, 78, 84, 128, 69, 76, 69, 77, 69, 78, - 212, 69, 76, 69, 67, 84, 82, 79, 78, 73, 67, 83, 128, 69, 76, 69, 67, 84, - 82, 73, 67, 65, 204, 69, 76, 69, 67, 84, 82, 73, 195, 69, 76, 66, 65, 83, - 65, 206, 69, 76, 65, 77, 73, 84, 69, 128, 69, 76, 65, 77, 73, 84, 197, - 69, 76, 65, 70, 82, 79, 78, 128, 69, 75, 83, 84, 82, 69, 80, 84, 79, 78, - 128, 69, 75, 83, 128, 69, 75, 70, 79, 78, 73, 84, 73, 75, 79, 78, 128, - 69, 75, 65, 82, 65, 128, 69, 75, 65, 77, 128, 69, 74, 69, 67, 212, 69, - 73, 83, 128, 69, 73, 71, 72, 84, 89, 128, 69, 73, 71, 72, 84, 217, 69, - 73, 71, 72, 84, 73, 69, 84, 72, 83, 128, 69, 73, 71, 72, 84, 73, 69, 84, - 72, 128, 69, 73, 71, 72, 84, 72, 83, 128, 69, 73, 71, 72, 84, 72, 211, - 69, 73, 71, 72, 84, 72, 128, 69, 73, 71, 72, 84, 69, 69, 78, 128, 69, 73, - 71, 72, 84, 69, 69, 206, 69, 73, 71, 72, 84, 45, 84, 72, 73, 82, 84, 89, - 128, 69, 73, 69, 128, 69, 72, 87, 65, 218, 69, 72, 84, 83, 65, 128, 69, - 72, 84, 65, 128, 69, 72, 80, 65, 128, 69, 72, 75, 65, 128, 69, 72, 67, - 72, 65, 128, 69, 71, 89, 80, 84, 79, 76, 79, 71, 73, 67, 65, 204, 69, 71, - 89, 128, 69, 71, 73, 82, 128, 69, 71, 71, 83, 128, 69, 71, 71, 128, 69, - 69, 89, 65, 78, 78, 65, 128, 69, 69, 75, 65, 65, 128, 69, 69, 72, 128, - 69, 69, 66, 69, 69, 70, 73, 76, 73, 128, 69, 68, 73, 84, 79, 82, 73, 65, - 204, 69, 68, 73, 78, 128, 69, 68, 68, 128, 69, 67, 83, 128, 69, 67, 76, - 73, 80, 83, 69, 128, 69, 66, 69, 70, 73, 76, 73, 128, 69, 65, 83, 84, 69, - 82, 206, 69, 65, 83, 84, 128, 69, 65, 83, 212, 69, 65, 82, 84, 72, 76, - 217, 69, 65, 82, 84, 72, 128, 69, 65, 82, 84, 200, 69, 65, 82, 76, 217, - 69, 65, 77, 72, 65, 78, 67, 72, 79, 76, 76, 128, 69, 65, 71, 76, 69, 128, - 69, 65, 68, 72, 65, 68, 72, 128, 69, 65, 66, 72, 65, 68, 72, 128, 69, - 178, 69, 48, 51, 56, 128, 69, 48, 51, 55, 128, 69, 48, 51, 54, 128, 69, - 48, 51, 52, 65, 128, 69, 48, 51, 52, 128, 69, 48, 51, 51, 128, 69, 48, - 51, 50, 128, 69, 48, 51, 49, 128, 69, 48, 51, 48, 128, 69, 48, 50, 57, - 128, 69, 48, 50, 56, 65, 128, 69, 48, 50, 56, 128, 69, 48, 50, 55, 128, - 69, 48, 50, 54, 128, 69, 48, 50, 53, 128, 69, 48, 50, 52, 128, 69, 48, - 50, 51, 128, 69, 48, 50, 50, 128, 69, 48, 50, 49, 128, 69, 48, 50, 48, - 65, 128, 69, 48, 50, 48, 128, 69, 48, 49, 57, 128, 69, 48, 49, 56, 128, - 69, 48, 49, 55, 65, 128, 69, 48, 49, 55, 128, 69, 48, 49, 54, 65, 128, - 69, 48, 49, 54, 128, 69, 48, 49, 53, 128, 69, 48, 49, 52, 128, 69, 48, - 49, 51, 128, 69, 48, 49, 50, 128, 69, 48, 49, 49, 128, 69, 48, 49, 48, - 128, 69, 48, 48, 57, 65, 128, 69, 48, 48, 57, 128, 69, 48, 48, 56, 65, - 128, 69, 48, 48, 56, 128, 69, 48, 48, 55, 128, 69, 48, 48, 54, 128, 69, - 48, 48, 53, 128, 69, 48, 48, 52, 128, 69, 48, 48, 51, 128, 69, 48, 48, - 50, 128, 69, 48, 48, 49, 128, 69, 45, 77, 65, 73, 204, 68, 90, 90, 72, - 69, 128, 68, 90, 90, 69, 128, 68, 90, 90, 65, 128, 68, 90, 89, 73, 128, - 68, 90, 89, 65, 89, 128, 68, 90, 87, 69, 128, 68, 90, 85, 128, 68, 90, - 79, 128, 68, 90, 74, 69, 128, 68, 90, 73, 84, 65, 128, 68, 90, 73, 128, - 68, 90, 72, 79, 73, 128, 68, 90, 72, 69, 128, 68, 90, 72, 65, 128, 68, - 90, 69, 76, 79, 128, 68, 90, 69, 69, 128, 68, 90, 69, 128, 68, 90, 65, - 89, 128, 68, 90, 65, 65, 128, 68, 90, 65, 128, 68, 90, 128, 68, 218, 68, - 89, 79, 128, 68, 89, 207, 68, 89, 78, 65, 77, 73, 195, 68, 89, 69, 72, - 128, 68, 89, 69, 200, 68, 89, 65, 78, 128, 68, 87, 79, 128, 68, 87, 69, - 128, 68, 87, 65, 128, 68, 86, 85, 77, 89, 193, 68, 86, 79, 69, 84, 79, - 67, 72, 73, 69, 128, 68, 86, 79, 69, 67, 72, 69, 76, 78, 79, 80, 79, 86, - 79, 68, 78, 65, 89, 65, 128, 68, 86, 79, 69, 67, 72, 69, 76, 78, 79, 80, - 79, 86, 79, 68, 78, 65, 89, 193, 68, 86, 79, 69, 67, 72, 69, 76, 78, 79, - 75, 82, 89, 90, 72, 69, 86, 65, 89, 65, 128, 68, 86, 79, 69, 67, 72, 69, - 76, 78, 65, 89, 65, 128, 68, 86, 79, 69, 67, 72, 69, 76, 78, 65, 89, 193, - 68, 86, 73, 83, 86, 65, 82, 65, 128, 68, 86, 68, 128, 68, 86, 193, 68, - 86, 128, 68, 85, 84, 73, 69, 83, 128, 68, 85, 83, 75, 128, 68, 85, 83, - 72, 69, 78, 78, 65, 128, 68, 85, 82, 65, 84, 73, 79, 78, 128, 68, 85, 82, - 50, 128, 68, 85, 80, 79, 78, 68, 73, 85, 211, 68, 85, 79, 88, 128, 68, - 85, 79, 128, 68, 85, 78, 52, 128, 68, 85, 78, 51, 128, 68, 85, 78, 179, - 68, 85, 77, 80, 76, 73, 78, 71, 128, 68, 85, 77, 128, 68, 85, 204, 68, - 85, 72, 128, 68, 85, 71, 85, 68, 128, 68, 85, 199, 68, 85, 68, 65, 128, - 68, 85, 67, 75, 128, 68, 85, 66, 50, 128, 68, 85, 66, 128, 68, 85, 194, - 68, 82, 89, 128, 68, 82, 217, 68, 82, 85, 77, 83, 84, 73, 67, 75, 83, - 128, 68, 82, 85, 77, 128, 68, 82, 85, 205, 68, 82, 79, 80, 83, 128, 68, - 82, 79, 80, 76, 69, 84, 128, 68, 82, 79, 80, 45, 83, 72, 65, 68, 79, 87, - 69, 196, 68, 82, 79, 208, 68, 82, 79, 79, 76, 73, 78, 199, 68, 82, 79, - 77, 69, 68, 65, 82, 217, 68, 82, 73, 86, 69, 128, 68, 82, 73, 86, 197, - 68, 82, 73, 78, 75, 128, 68, 82, 73, 204, 68, 82, 69, 83, 83, 128, 68, - 82, 69, 65, 77, 217, 68, 82, 65, 85, 71, 72, 84, 211, 68, 82, 65, 77, - 128, 68, 82, 65, 205, 68, 82, 65, 71, 79, 78, 128, 68, 82, 65, 71, 79, - 206, 68, 82, 65, 70, 84, 73, 78, 199, 68, 82, 65, 67, 72, 77, 65, 83, - 128, 68, 82, 65, 67, 72, 77, 65, 128, 68, 82, 65, 67, 72, 77, 193, 68, - 79, 87, 78, 87, 65, 82, 68, 83, 128, 68, 79, 87, 78, 87, 65, 82, 68, 211, - 68, 79, 87, 78, 87, 65, 82, 196, 68, 79, 87, 78, 83, 67, 65, 76, 73, 78, - 199, 68, 79, 87, 78, 45, 80, 79, 73, 78, 84, 73, 78, 199, 68, 79, 87, 78, - 128, 68, 79, 86, 69, 128, 68, 79, 86, 197, 68, 79, 85, 71, 72, 78, 85, - 84, 128, 68, 79, 85, 66, 84, 128, 68, 79, 85, 66, 76, 69, 196, 68, 79, - 85, 66, 76, 69, 45, 83, 84, 82, 85, 67, 203, 68, 79, 85, 66, 76, 69, 45, - 76, 73, 78, 69, 196, 68, 79, 85, 66, 76, 69, 45, 76, 73, 78, 197, 68, 79, - 85, 66, 76, 69, 45, 69, 78, 68, 69, 196, 68, 79, 85, 66, 76, 69, 128, 68, - 79, 84, 84, 69, 68, 45, 80, 128, 68, 79, 84, 84, 69, 68, 45, 78, 128, 68, - 79, 84, 84, 69, 68, 45, 76, 128, 68, 79, 84, 84, 69, 68, 128, 68, 79, 84, - 84, 69, 196, 68, 79, 84, 83, 45, 56, 128, 68, 79, 84, 83, 45, 55, 56, - 128, 68, 79, 84, 83, 45, 55, 128, 68, 79, 84, 83, 45, 54, 56, 128, 68, - 79, 84, 83, 45, 54, 55, 56, 128, 68, 79, 84, 83, 45, 54, 55, 128, 68, 79, - 84, 83, 45, 54, 128, 68, 79, 84, 83, 45, 53, 56, 128, 68, 79, 84, 83, 45, - 53, 55, 56, 128, 68, 79, 84, 83, 45, 53, 55, 128, 68, 79, 84, 83, 45, 53, - 54, 56, 128, 68, 79, 84, 83, 45, 53, 54, 55, 56, 128, 68, 79, 84, 83, 45, - 53, 54, 55, 128, 68, 79, 84, 83, 45, 53, 54, 128, 68, 79, 84, 83, 45, 53, - 128, 68, 79, 84, 83, 45, 52, 56, 128, 68, 79, 84, 83, 45, 52, 55, 56, - 128, 68, 79, 84, 83, 45, 52, 55, 128, 68, 79, 84, 83, 45, 52, 54, 56, - 128, 68, 79, 84, 83, 45, 52, 54, 55, 56, 128, 68, 79, 84, 83, 45, 52, 54, - 55, 128, 68, 79, 84, 83, 45, 52, 54, 128, 68, 79, 84, 83, 45, 52, 53, 56, - 128, 68, 79, 84, 83, 45, 52, 53, 55, 56, 128, 68, 79, 84, 83, 45, 52, 53, - 55, 128, 68, 79, 84, 83, 45, 52, 53, 54, 56, 128, 68, 79, 84, 83, 45, 52, - 53, 54, 55, 56, 128, 68, 79, 84, 83, 45, 52, 53, 54, 55, 128, 68, 79, 84, - 83, 45, 52, 53, 54, 128, 68, 79, 84, 83, 45, 52, 53, 128, 68, 79, 84, 83, - 45, 52, 128, 68, 79, 84, 83, 45, 51, 56, 128, 68, 79, 84, 83, 45, 51, 55, - 56, 128, 68, 79, 84, 83, 45, 51, 55, 128, 68, 79, 84, 83, 45, 51, 54, 56, - 128, 68, 79, 84, 83, 45, 51, 54, 55, 56, 128, 68, 79, 84, 83, 45, 51, 54, - 55, 128, 68, 79, 84, 83, 45, 51, 54, 128, 68, 79, 84, 83, 45, 51, 53, 56, - 128, 68, 79, 84, 83, 45, 51, 53, 55, 56, 128, 68, 79, 84, 83, 45, 51, 53, - 55, 128, 68, 79, 84, 83, 45, 51, 53, 54, 56, 128, 68, 79, 84, 83, 45, 51, - 53, 54, 55, 56, 128, 68, 79, 84, 83, 45, 51, 53, 54, 55, 128, 68, 79, 84, - 83, 45, 51, 53, 54, 128, 68, 79, 84, 83, 45, 51, 53, 128, 68, 79, 84, 83, - 45, 51, 52, 56, 128, 68, 79, 84, 83, 45, 51, 52, 55, 56, 128, 68, 79, 84, - 83, 45, 51, 52, 55, 128, 68, 79, 84, 83, 45, 51, 52, 54, 56, 128, 68, 79, - 84, 83, 45, 51, 52, 54, 55, 56, 128, 68, 79, 84, 83, 45, 51, 52, 54, 55, - 128, 68, 79, 84, 83, 45, 51, 52, 54, 128, 68, 79, 84, 83, 45, 51, 52, 53, - 56, 128, 68, 79, 84, 83, 45, 51, 52, 53, 55, 56, 128, 68, 79, 84, 83, 45, - 51, 52, 53, 55, 128, 68, 79, 84, 83, 45, 51, 52, 53, 54, 56, 128, 68, 79, - 84, 83, 45, 51, 52, 53, 54, 55, 56, 128, 68, 79, 84, 83, 45, 51, 52, 53, - 54, 55, 128, 68, 79, 84, 83, 45, 51, 52, 53, 54, 128, 68, 79, 84, 83, 45, - 51, 52, 53, 128, 68, 79, 84, 83, 45, 51, 52, 128, 68, 79, 84, 83, 45, 51, - 128, 68, 79, 84, 83, 45, 50, 56, 128, 68, 79, 84, 83, 45, 50, 55, 56, - 128, 68, 79, 84, 83, 45, 50, 55, 128, 68, 79, 84, 83, 45, 50, 54, 56, - 128, 68, 79, 84, 83, 45, 50, 54, 55, 56, 128, 68, 79, 84, 83, 45, 50, 54, - 55, 128, 68, 79, 84, 83, 45, 50, 54, 128, 68, 79, 84, 83, 45, 50, 53, 56, - 128, 68, 79, 84, 83, 45, 50, 53, 55, 56, 128, 68, 79, 84, 83, 45, 50, 53, - 55, 128, 68, 79, 84, 83, 45, 50, 53, 54, 56, 128, 68, 79, 84, 83, 45, 50, - 53, 54, 55, 56, 128, 68, 79, 84, 83, 45, 50, 53, 54, 55, 128, 68, 79, 84, - 83, 45, 50, 53, 54, 128, 68, 79, 84, 83, 45, 50, 53, 128, 68, 79, 84, 83, - 45, 50, 52, 56, 128, 68, 79, 84, 83, 45, 50, 52, 55, 56, 128, 68, 79, 84, - 83, 45, 50, 52, 55, 128, 68, 79, 84, 83, 45, 50, 52, 54, 56, 128, 68, 79, - 84, 83, 45, 50, 52, 54, 55, 56, 128, 68, 79, 84, 83, 45, 50, 52, 54, 55, - 128, 68, 79, 84, 83, 45, 50, 52, 54, 128, 68, 79, 84, 83, 45, 50, 52, 53, - 56, 128, 68, 79, 84, 83, 45, 50, 52, 53, 55, 56, 128, 68, 79, 84, 83, 45, - 50, 52, 53, 55, 128, 68, 79, 84, 83, 45, 50, 52, 53, 54, 56, 128, 68, 79, - 84, 83, 45, 50, 52, 53, 54, 55, 56, 128, 68, 79, 84, 83, 45, 50, 52, 53, - 54, 55, 128, 68, 79, 84, 83, 45, 50, 52, 53, 54, 128, 68, 79, 84, 83, 45, - 50, 52, 53, 128, 68, 79, 84, 83, 45, 50, 52, 128, 68, 79, 84, 83, 45, 50, - 51, 56, 128, 68, 79, 84, 83, 45, 50, 51, 55, 56, 128, 68, 79, 84, 83, 45, - 50, 51, 55, 128, 68, 79, 84, 83, 45, 50, 51, 54, 56, 128, 68, 79, 84, 83, - 45, 50, 51, 54, 55, 56, 128, 68, 79, 84, 83, 45, 50, 51, 54, 55, 128, 68, - 79, 84, 83, 45, 50, 51, 54, 128, 68, 79, 84, 83, 45, 50, 51, 53, 56, 128, - 68, 79, 84, 83, 45, 50, 51, 53, 55, 56, 128, 68, 79, 84, 83, 45, 50, 51, - 53, 55, 128, 68, 79, 84, 83, 45, 50, 51, 53, 54, 56, 128, 68, 79, 84, 83, - 45, 50, 51, 53, 54, 55, 56, 128, 68, 79, 84, 83, 45, 50, 51, 53, 54, 55, - 128, 68, 79, 84, 83, 45, 50, 51, 53, 54, 128, 68, 79, 84, 83, 45, 50, 51, - 53, 128, 68, 79, 84, 83, 45, 50, 51, 52, 56, 128, 68, 79, 84, 83, 45, 50, - 51, 52, 55, 56, 128, 68, 79, 84, 83, 45, 50, 51, 52, 55, 128, 68, 79, 84, - 83, 45, 50, 51, 52, 54, 56, 128, 68, 79, 84, 83, 45, 50, 51, 52, 54, 55, - 56, 128, 68, 79, 84, 83, 45, 50, 51, 52, 54, 55, 128, 68, 79, 84, 83, 45, - 50, 51, 52, 54, 128, 68, 79, 84, 83, 45, 50, 51, 52, 53, 56, 128, 68, 79, - 84, 83, 45, 50, 51, 52, 53, 55, 56, 128, 68, 79, 84, 83, 45, 50, 51, 52, - 53, 55, 128, 68, 79, 84, 83, 45, 50, 51, 52, 53, 54, 56, 128, 68, 79, 84, - 83, 45, 50, 51, 52, 53, 54, 55, 56, 128, 68, 79, 84, 83, 45, 50, 51, 52, - 53, 54, 55, 128, 68, 79, 84, 83, 45, 50, 51, 52, 53, 54, 128, 68, 79, 84, - 83, 45, 50, 51, 52, 53, 128, 68, 79, 84, 83, 45, 50, 51, 52, 128, 68, 79, - 84, 83, 45, 50, 51, 128, 68, 79, 84, 83, 45, 50, 128, 68, 79, 84, 83, 45, - 49, 56, 128, 68, 79, 84, 83, 45, 49, 55, 56, 128, 68, 79, 84, 83, 45, 49, - 55, 128, 68, 79, 84, 83, 45, 49, 54, 56, 128, 68, 79, 84, 83, 45, 49, 54, - 55, 56, 128, 68, 79, 84, 83, 45, 49, 54, 55, 128, 68, 79, 84, 83, 45, 49, - 54, 128, 68, 79, 84, 83, 45, 49, 53, 56, 128, 68, 79, 84, 83, 45, 49, 53, - 55, 56, 128, 68, 79, 84, 83, 45, 49, 53, 55, 128, 68, 79, 84, 83, 45, 49, - 53, 54, 56, 128, 68, 79, 84, 83, 45, 49, 53, 54, 55, 56, 128, 68, 79, 84, - 83, 45, 49, 53, 54, 55, 128, 68, 79, 84, 83, 45, 49, 53, 54, 128, 68, 79, - 84, 83, 45, 49, 53, 128, 68, 79, 84, 83, 45, 49, 52, 56, 128, 68, 79, 84, - 83, 45, 49, 52, 55, 56, 128, 68, 79, 84, 83, 45, 49, 52, 55, 128, 68, 79, - 84, 83, 45, 49, 52, 54, 56, 128, 68, 79, 84, 83, 45, 49, 52, 54, 55, 56, - 128, 68, 79, 84, 83, 45, 49, 52, 54, 55, 128, 68, 79, 84, 83, 45, 49, 52, - 54, 128, 68, 79, 84, 83, 45, 49, 52, 53, 56, 128, 68, 79, 84, 83, 45, 49, - 52, 53, 55, 56, 128, 68, 79, 84, 83, 45, 49, 52, 53, 55, 128, 68, 79, 84, - 83, 45, 49, 52, 53, 54, 56, 128, 68, 79, 84, 83, 45, 49, 52, 53, 54, 55, - 56, 128, 68, 79, 84, 83, 45, 49, 52, 53, 54, 55, 128, 68, 79, 84, 83, 45, - 49, 52, 53, 54, 128, 68, 79, 84, 83, 45, 49, 52, 53, 128, 68, 79, 84, 83, - 45, 49, 52, 128, 68, 79, 84, 83, 45, 49, 51, 56, 128, 68, 79, 84, 83, 45, - 49, 51, 55, 56, 128, 68, 79, 84, 83, 45, 49, 51, 55, 128, 68, 79, 84, 83, - 45, 49, 51, 54, 56, 128, 68, 79, 84, 83, 45, 49, 51, 54, 55, 56, 128, 68, - 79, 84, 83, 45, 49, 51, 54, 55, 128, 68, 79, 84, 83, 45, 49, 51, 54, 128, - 68, 79, 84, 83, 45, 49, 51, 53, 56, 128, 68, 79, 84, 83, 45, 49, 51, 53, - 55, 56, 128, 68, 79, 84, 83, 45, 49, 51, 53, 55, 128, 68, 79, 84, 83, 45, - 49, 51, 53, 54, 56, 128, 68, 79, 84, 83, 45, 49, 51, 53, 54, 55, 56, 128, - 68, 79, 84, 83, 45, 49, 51, 53, 54, 55, 128, 68, 79, 84, 83, 45, 49, 51, - 53, 54, 128, 68, 79, 84, 83, 45, 49, 51, 53, 128, 68, 79, 84, 83, 45, 49, - 51, 52, 56, 128, 68, 79, 84, 83, 45, 49, 51, 52, 55, 56, 128, 68, 79, 84, - 83, 45, 49, 51, 52, 55, 128, 68, 79, 84, 83, 45, 49, 51, 52, 54, 56, 128, - 68, 79, 84, 83, 45, 49, 51, 52, 54, 55, 56, 128, 68, 79, 84, 83, 45, 49, - 51, 52, 54, 55, 128, 68, 79, 84, 83, 45, 49, 51, 52, 54, 128, 68, 79, 84, - 83, 45, 49, 51, 52, 53, 56, 128, 68, 79, 84, 83, 45, 49, 51, 52, 53, 55, - 56, 128, 68, 79, 84, 83, 45, 49, 51, 52, 53, 55, 128, 68, 79, 84, 83, 45, - 49, 51, 52, 53, 54, 56, 128, 68, 79, 84, 83, 45, 49, 51, 52, 53, 54, 55, - 56, 128, 68, 79, 84, 83, 45, 49, 51, 52, 53, 54, 55, 128, 68, 79, 84, 83, - 45, 49, 51, 52, 53, 54, 128, 68, 79, 84, 83, 45, 49, 51, 52, 53, 128, 68, - 79, 84, 83, 45, 49, 51, 52, 128, 68, 79, 84, 83, 45, 49, 51, 128, 68, 79, - 84, 83, 45, 49, 50, 56, 128, 68, 79, 84, 83, 45, 49, 50, 55, 56, 128, 68, - 79, 84, 83, 45, 49, 50, 55, 128, 68, 79, 84, 83, 45, 49, 50, 54, 56, 128, - 68, 79, 84, 83, 45, 49, 50, 54, 55, 56, 128, 68, 79, 84, 83, 45, 49, 50, - 54, 55, 128, 68, 79, 84, 83, 45, 49, 50, 54, 128, 68, 79, 84, 83, 45, 49, - 50, 53, 56, 128, 68, 79, 84, 83, 45, 49, 50, 53, 55, 56, 128, 68, 79, 84, - 83, 45, 49, 50, 53, 55, 128, 68, 79, 84, 83, 45, 49, 50, 53, 54, 56, 128, - 68, 79, 84, 83, 45, 49, 50, 53, 54, 55, 56, 128, 68, 79, 84, 83, 45, 49, - 50, 53, 54, 55, 128, 68, 79, 84, 83, 45, 49, 50, 53, 54, 128, 68, 79, 84, - 83, 45, 49, 50, 53, 128, 68, 79, 84, 83, 45, 49, 50, 52, 56, 128, 68, 79, - 84, 83, 45, 49, 50, 52, 55, 56, 128, 68, 79, 84, 83, 45, 49, 50, 52, 55, - 128, 68, 79, 84, 83, 45, 49, 50, 52, 54, 56, 128, 68, 79, 84, 83, 45, 49, - 50, 52, 54, 55, 56, 128, 68, 79, 84, 83, 45, 49, 50, 52, 54, 55, 128, 68, - 79, 84, 83, 45, 49, 50, 52, 54, 128, 68, 79, 84, 83, 45, 49, 50, 52, 53, - 56, 128, 68, 79, 84, 83, 45, 49, 50, 52, 53, 55, 56, 128, 68, 79, 84, 83, - 45, 49, 50, 52, 53, 55, 128, 68, 79, 84, 83, 45, 49, 50, 52, 53, 54, 56, - 128, 68, 79, 84, 83, 45, 49, 50, 52, 53, 54, 55, 56, 128, 68, 79, 84, 83, - 45, 49, 50, 52, 53, 54, 55, 128, 68, 79, 84, 83, 45, 49, 50, 52, 53, 54, - 128, 68, 79, 84, 83, 45, 49, 50, 52, 53, 128, 68, 79, 84, 83, 45, 49, 50, - 52, 128, 68, 79, 84, 83, 45, 49, 50, 51, 56, 128, 68, 79, 84, 83, 45, 49, - 50, 51, 55, 56, 128, 68, 79, 84, 83, 45, 49, 50, 51, 55, 128, 68, 79, 84, - 83, 45, 49, 50, 51, 54, 56, 128, 68, 79, 84, 83, 45, 49, 50, 51, 54, 55, - 56, 128, 68, 79, 84, 83, 45, 49, 50, 51, 54, 55, 128, 68, 79, 84, 83, 45, - 49, 50, 51, 54, 128, 68, 79, 84, 83, 45, 49, 50, 51, 53, 56, 128, 68, 79, - 84, 83, 45, 49, 50, 51, 53, 55, 56, 128, 68, 79, 84, 83, 45, 49, 50, 51, - 53, 55, 128, 68, 79, 84, 83, 45, 49, 50, 51, 53, 54, 56, 128, 68, 79, 84, - 83, 45, 49, 50, 51, 53, 54, 55, 56, 128, 68, 79, 84, 83, 45, 49, 50, 51, - 53, 54, 55, 128, 68, 79, 84, 83, 45, 49, 50, 51, 53, 54, 128, 68, 79, 84, - 83, 45, 49, 50, 51, 53, 128, 68, 79, 84, 83, 45, 49, 50, 51, 52, 56, 128, - 68, 79, 84, 83, 45, 49, 50, 51, 52, 55, 56, 128, 68, 79, 84, 83, 45, 49, - 50, 51, 52, 55, 128, 68, 79, 84, 83, 45, 49, 50, 51, 52, 54, 56, 128, 68, - 79, 84, 83, 45, 49, 50, 51, 52, 54, 55, 56, 128, 68, 79, 84, 83, 45, 49, - 50, 51, 52, 54, 55, 128, 68, 79, 84, 83, 45, 49, 50, 51, 52, 54, 128, 68, - 79, 84, 83, 45, 49, 50, 51, 52, 53, 56, 128, 68, 79, 84, 83, 45, 49, 50, - 51, 52, 53, 55, 56, 128, 68, 79, 84, 83, 45, 49, 50, 51, 52, 53, 55, 128, - 68, 79, 84, 83, 45, 49, 50, 51, 52, 53, 54, 56, 128, 68, 79, 84, 83, 45, - 49, 50, 51, 52, 53, 54, 55, 56, 128, 68, 79, 84, 83, 45, 49, 50, 51, 52, - 53, 54, 55, 128, 68, 79, 84, 83, 45, 49, 50, 51, 52, 53, 54, 128, 68, 79, - 84, 83, 45, 49, 50, 51, 52, 53, 128, 68, 79, 84, 83, 45, 49, 50, 51, 52, - 128, 68, 79, 84, 83, 45, 49, 50, 51, 128, 68, 79, 84, 83, 45, 49, 50, - 128, 68, 79, 84, 83, 45, 49, 128, 68, 79, 84, 83, 128, 68, 79, 84, 76, - 69, 83, 211, 68, 79, 82, 85, 128, 68, 79, 82, 79, 77, 197, 68, 79, 79, - 82, 128, 68, 79, 79, 78, 71, 128, 68, 79, 78, 75, 69, 89, 128, 68, 79, - 78, 71, 128, 68, 79, 77, 73, 78, 207, 68, 79, 77, 65, 73, 206, 68, 79, - 76, 80, 72, 73, 78, 128, 68, 79, 76, 76, 83, 128, 68, 79, 76, 76, 65, - 210, 68, 79, 76, 73, 85, 77, 128, 68, 79, 75, 77, 65, 73, 128, 68, 79, - 73, 84, 128, 68, 79, 73, 78, 199, 68, 79, 73, 128, 68, 79, 71, 82, 193, - 68, 79, 71, 128, 68, 79, 199, 68, 79, 69, 211, 68, 79, 68, 79, 128, 68, - 79, 68, 69, 75, 65, 84, 65, 128, 68, 79, 67, 85, 77, 69, 78, 84, 128, 68, - 79, 67, 85, 77, 69, 78, 212, 68, 79, 66, 82, 79, 128, 68, 79, 65, 67, 72, - 65, 83, 72, 77, 69, 69, 128, 68, 79, 65, 67, 72, 65, 83, 72, 77, 69, 197, - 68, 79, 65, 128, 68, 79, 45, 79, 128, 68, 78, 193, 68, 77, 128, 68, 205, - 68, 76, 85, 128, 68, 76, 79, 128, 68, 76, 73, 128, 68, 76, 72, 89, 65, - 128, 68, 76, 72, 65, 128, 68, 76, 69, 69, 128, 68, 76, 65, 128, 68, 76, - 128, 68, 75, 65, 82, 128, 68, 75, 65, 210, 68, 74, 69, 82, 86, 73, 128, - 68, 74, 69, 82, 86, 128, 68, 74, 69, 128, 68, 74, 65, 128, 68, 73, 90, - 90, 217, 68, 73, 89, 193, 68, 73, 86, 79, 82, 67, 197, 68, 73, 86, 73, - 83, 73, 79, 78, 128, 68, 73, 86, 73, 83, 73, 79, 206, 68, 73, 86, 73, 78, - 199, 68, 73, 86, 73, 78, 65, 84, 73, 79, 78, 128, 68, 73, 86, 73, 68, 69, - 83, 128, 68, 73, 86, 73, 68, 69, 82, 83, 128, 68, 73, 86, 73, 68, 69, 82, - 128, 68, 73, 86, 73, 68, 69, 196, 68, 73, 86, 73, 68, 69, 128, 68, 73, - 86, 73, 68, 197, 68, 73, 86, 69, 211, 68, 73, 86, 69, 82, 71, 69, 78, 67, - 69, 128, 68, 73, 84, 84, 207, 68, 73, 83, 84, 79, 82, 84, 73, 79, 78, - 128, 68, 73, 83, 84, 73, 78, 71, 85, 73, 83, 72, 128, 68, 73, 83, 84, 73, - 76, 76, 128, 68, 73, 83, 83, 79, 76, 86, 69, 45, 50, 128, 68, 73, 83, 83, - 79, 76, 86, 69, 128, 68, 73, 83, 80, 85, 84, 69, 196, 68, 73, 83, 80, 69, - 82, 83, 73, 79, 78, 128, 68, 73, 83, 75, 128, 68, 73, 83, 73, 77, 79, 85, - 128, 68, 73, 83, 72, 128, 68, 73, 83, 71, 85, 73, 83, 69, 196, 68, 73, - 83, 67, 79, 78, 84, 73, 78, 85, 79, 85, 211, 68, 73, 83, 195, 68, 73, 83, - 65, 80, 80, 79, 73, 78, 84, 69, 196, 68, 73, 83, 65, 66, 76, 69, 196, 68, - 73, 82, 71, 193, 68, 73, 82, 69, 67, 84, 76, 217, 68, 73, 82, 69, 67, 84, - 73, 79, 78, 65, 204, 68, 73, 82, 69, 67, 84, 73, 79, 206, 68, 73, 80, 84, - 69, 128, 68, 73, 80, 80, 69, 82, 128, 68, 73, 80, 76, 79, 85, 78, 128, - 68, 73, 80, 76, 73, 128, 68, 73, 80, 76, 201, 68, 73, 78, 71, 66, 65, - 212, 68, 73, 206, 68, 73, 77, 77, 73, 78, 71, 128, 68, 73, 77, 73, 78, - 85, 84, 73, 79, 78, 45, 51, 128, 68, 73, 77, 73, 78, 85, 84, 73, 79, 78, - 45, 50, 128, 68, 73, 77, 73, 78, 85, 84, 73, 79, 78, 45, 49, 128, 68, 73, - 77, 73, 78, 73, 83, 72, 77, 69, 78, 84, 128, 68, 73, 77, 73, 68, 73, 193, - 68, 73, 77, 69, 78, 83, 73, 79, 78, 65, 204, 68, 73, 77, 69, 78, 83, 73, - 79, 206, 68, 73, 77, 50, 128, 68, 73, 77, 178, 68, 73, 76, 128, 68, 73, - 71, 82, 65, 80, 72, 128, 68, 73, 71, 82, 65, 80, 200, 68, 73, 71, 82, 65, - 77, 77, 79, 211, 68, 73, 71, 82, 65, 77, 77, 193, 68, 73, 71, 82, 65, - 205, 68, 73, 71, 79, 82, 71, 79, 78, 128, 68, 73, 71, 79, 82, 71, 79, - 206, 68, 73, 71, 73, 84, 83, 128, 68, 73, 71, 65, 77, 77, 65, 128, 68, - 73, 71, 193, 68, 73, 70, 84, 79, 71, 71, 79, 211, 68, 73, 70, 79, 78, 73, - 65, 83, 128, 68, 73, 70, 70, 73, 67, 85, 76, 84, 217, 68, 73, 70, 70, 73, - 67, 85, 76, 84, 73, 69, 83, 128, 68, 73, 70, 70, 69, 82, 69, 78, 84, 73, - 65, 76, 128, 68, 73, 70, 70, 69, 82, 69, 78, 67, 197, 68, 73, 70, 65, 84, - 128, 68, 73, 69, 83, 73, 83, 128, 68, 73, 69, 83, 73, 211, 68, 73, 69, - 83, 69, 204, 68, 73, 69, 80, 128, 68, 73, 197, 68, 73, 66, 128, 68, 73, - 65, 84, 79, 78, 79, 206, 68, 73, 65, 84, 79, 78, 73, 75, 201, 68, 73, 65, - 83, 84, 79, 76, 201, 68, 73, 65, 77, 79, 78, 68, 83, 128, 68, 73, 65, 77, - 79, 78, 68, 128, 68, 73, 65, 77, 79, 78, 196, 68, 73, 65, 77, 69, 84, 69, - 210, 68, 73, 65, 76, 89, 84, 73, 75, 65, 128, 68, 73, 65, 76, 89, 84, 73, - 75, 193, 68, 73, 65, 76, 69, 67, 84, 45, 208, 68, 73, 65, 71, 79, 78, 65, - 76, 128, 68, 73, 65, 69, 82, 69, 83, 73, 90, 69, 196, 68, 73, 65, 69, 82, - 69, 83, 73, 83, 45, 82, 73, 78, 71, 128, 68, 73, 65, 69, 82, 69, 83, 73, - 83, 128, 68, 73, 65, 69, 82, 69, 83, 73, 211, 68, 72, 79, 85, 128, 68, - 72, 79, 79, 128, 68, 72, 79, 128, 68, 72, 73, 73, 128, 68, 72, 72, 85, - 128, 68, 72, 72, 79, 79, 128, 68, 72, 72, 79, 128, 68, 72, 72, 73, 128, - 68, 72, 72, 69, 69, 128, 68, 72, 72, 69, 128, 68, 72, 72, 65, 128, 68, - 72, 69, 69, 128, 68, 72, 65, 82, 77, 65, 128, 68, 72, 65, 77, 69, 68, 72, - 128, 68, 72, 65, 76, 69, 84, 72, 128, 68, 72, 65, 76, 65, 84, 72, 128, - 68, 72, 65, 76, 128, 68, 72, 65, 68, 72, 69, 128, 68, 72, 65, 65, 76, 85, - 128, 68, 72, 65, 65, 128, 68, 72, 65, 128, 68, 69, 90, 200, 68, 69, 89, - 84, 69, 82, 79, 213, 68, 69, 89, 84, 69, 82, 79, 211, 68, 69, 88, 73, 65, - 128, 68, 69, 86, 73, 67, 197, 68, 69, 86, 69, 76, 79, 80, 77, 69, 78, 84, - 128, 68, 69, 85, 78, 71, 128, 68, 69, 83, 75, 84, 79, 208, 68, 69, 83, - 203, 68, 69, 83, 73, 71, 78, 128, 68, 69, 83, 73, 128, 68, 69, 83, 69, - 82, 84, 128, 68, 69, 83, 69, 82, 212, 68, 69, 83, 69, 82, 69, 212, 68, - 69, 83, 67, 82, 73, 80, 84, 73, 79, 206, 68, 69, 83, 67, 69, 78, 68, 73, - 78, 199, 68, 69, 83, 67, 69, 78, 68, 69, 82, 128, 68, 69, 82, 69, 84, 45, - 72, 73, 68, 69, 84, 128, 68, 69, 82, 69, 84, 128, 68, 69, 82, 69, 76, 73, - 67, 212, 68, 69, 82, 66, 73, 84, 83, 65, 128, 68, 69, 80, 84, 72, 128, - 68, 69, 80, 65, 82, 84, 85, 82, 69, 128, 68, 69, 80, 65, 82, 84, 77, 69, - 78, 212, 68, 69, 80, 65, 82, 84, 73, 78, 199, 68, 69, 78, 84, 73, 83, 84, - 82, 217, 68, 69, 78, 84, 65, 204, 68, 69, 78, 79, 77, 73, 78, 65, 84, 79, - 82, 128, 68, 69, 78, 79, 77, 73, 78, 65, 84, 79, 210, 68, 69, 78, 78, 69, - 78, 128, 68, 69, 78, 71, 128, 68, 69, 78, 197, 68, 69, 78, 65, 82, 73, - 85, 211, 68, 69, 77, 69, 83, 84, 86, 69, 78, 78, 217, 68, 69, 76, 84, 65, - 128, 68, 69, 76, 84, 193, 68, 69, 76, 84, 128, 68, 69, 76, 80, 72, 73, - 195, 68, 69, 76, 73, 86, 69, 82, 217, 68, 69, 76, 73, 86, 69, 82, 65, 78, - 67, 69, 128, 68, 69, 76, 73, 77, 73, 84, 69, 82, 128, 68, 69, 76, 73, 77, - 73, 84, 69, 210, 68, 69, 76, 73, 67, 73, 79, 85, 211, 68, 69, 76, 69, 84, - 73, 79, 206, 68, 69, 76, 69, 84, 69, 128, 68, 69, 76, 69, 84, 197, 68, - 69, 75, 65, 128, 68, 69, 75, 128, 68, 69, 73, 128, 68, 69, 72, 73, 128, - 68, 69, 71, 82, 69, 69, 83, 128, 68, 69, 71, 82, 69, 197, 68, 69, 70, 73, - 78, 73, 84, 73, 79, 78, 128, 68, 69, 70, 69, 67, 84, 73, 86, 69, 78, 69, - 83, 211, 68, 69, 69, 82, 128, 68, 69, 69, 80, 76, 89, 128, 68, 69, 69, - 76, 128, 68, 69, 67, 82, 69, 83, 67, 69, 78, 68, 79, 128, 68, 69, 67, 82, - 69, 65, 83, 69, 128, 68, 69, 67, 82, 69, 65, 83, 197, 68, 69, 67, 79, 82, - 65, 84, 73, 86, 197, 68, 69, 67, 79, 82, 65, 84, 73, 79, 78, 128, 68, 69, - 67, 73, 83, 73, 86, 69, 78, 69, 83, 83, 128, 68, 69, 67, 73, 77, 65, 204, - 68, 69, 67, 73, 68, 85, 79, 85, 211, 68, 69, 67, 69, 77, 66, 69, 82, 128, - 68, 69, 67, 65, 89, 69, 68, 128, 68, 69, 66, 73, 212, 68, 69, 65, 84, 72, - 128, 68, 69, 65, 198, 68, 69, 65, 68, 128, 68, 68, 87, 65, 128, 68, 68, - 85, 88, 128, 68, 68, 85, 84, 128, 68, 68, 85, 82, 88, 128, 68, 68, 85, - 82, 128, 68, 68, 85, 80, 128, 68, 68, 85, 79, 88, 128, 68, 68, 85, 79, - 80, 128, 68, 68, 85, 79, 128, 68, 68, 85, 128, 68, 68, 79, 88, 128, 68, - 68, 79, 84, 128, 68, 68, 79, 80, 128, 68, 68, 79, 65, 128, 68, 68, 73, - 88, 128, 68, 68, 73, 84, 128, 68, 68, 73, 80, 128, 68, 68, 73, 69, 88, - 128, 68, 68, 73, 69, 80, 128, 68, 68, 73, 69, 128, 68, 68, 73, 128, 68, - 68, 72, 85, 128, 68, 68, 72, 79, 128, 68, 68, 72, 69, 69, 128, 68, 68, - 72, 69, 128, 68, 68, 72, 65, 65, 128, 68, 68, 72, 65, 128, 68, 68, 69, - 88, 128, 68, 68, 69, 80, 128, 68, 68, 69, 69, 128, 68, 68, 69, 128, 68, - 68, 68, 72, 65, 128, 68, 68, 68, 65, 128, 68, 68, 65, 89, 65, 78, 78, 65, - 128, 68, 68, 65, 88, 128, 68, 68, 65, 84, 128, 68, 68, 65, 80, 128, 68, - 68, 65, 76, 128, 68, 68, 65, 204, 68, 68, 65, 72, 65, 76, 128, 68, 68, - 65, 72, 65, 204, 68, 68, 65, 65, 128, 68, 67, 83, 128, 68, 67, 72, 69, - 128, 68, 67, 52, 128, 68, 67, 51, 128, 68, 67, 50, 128, 68, 67, 49, 128, - 68, 194, 68, 65, 89, 45, 78, 73, 71, 72, 84, 128, 68, 65, 217, 68, 65, - 87, 66, 128, 68, 65, 86, 73, 89, 65, 78, 73, 128, 68, 65, 86, 73, 68, - 128, 68, 65, 84, 197, 68, 65, 83, 73, 65, 128, 68, 65, 83, 73, 193, 68, - 65, 83, 72, 69, 196, 68, 65, 83, 72, 128, 68, 65, 83, 200, 68, 65, 83, - 69, 73, 65, 128, 68, 65, 82, 84, 128, 68, 65, 82, 75, 69, 78, 73, 78, 71, - 128, 68, 65, 82, 75, 69, 78, 73, 78, 199, 68, 65, 82, 203, 68, 65, 82, - 71, 65, 128, 68, 65, 82, 65, 52, 128, 68, 65, 82, 65, 51, 128, 68, 65, - 82, 128, 68, 65, 80, 45, 80, 82, 65, 205, 68, 65, 80, 45, 80, 73, 201, - 68, 65, 80, 45, 77, 85, 79, 217, 68, 65, 80, 45, 66, 85, 79, 206, 68, 65, - 80, 45, 66, 69, 201, 68, 65, 208, 68, 65, 78, 84, 65, 89, 65, 76, 65, 78, - 128, 68, 65, 78, 84, 65, 74, 193, 68, 65, 78, 71, 79, 128, 68, 65, 78, - 71, 128, 68, 65, 78, 199, 68, 65, 78, 68, 65, 128, 68, 65, 78, 67, 73, - 78, 71, 128, 68, 65, 78, 67, 69, 82, 128, 68, 65, 77, 80, 128, 68, 65, - 77, 208, 68, 65, 77, 77, 65, 84, 65, 78, 128, 68, 65, 77, 77, 65, 84, 65, - 206, 68, 65, 77, 77, 65, 128, 68, 65, 77, 77, 193, 68, 65, 77, 65, 82, - 85, 128, 68, 65, 77, 65, 71, 69, 68, 128, 68, 65, 77, 65, 71, 69, 196, - 68, 65, 76, 69, 84, 72, 45, 82, 69, 83, 72, 128, 68, 65, 76, 69, 84, 128, - 68, 65, 76, 69, 212, 68, 65, 76, 68, 65, 128, 68, 65, 76, 65, 84, 72, - 128, 68, 65, 76, 65, 84, 200, 68, 65, 76, 65, 84, 128, 68, 65, 73, 82, - 128, 68, 65, 73, 78, 71, 128, 68, 65, 73, 128, 68, 65, 72, 89, 65, 65, - 85, 83, 72, 45, 50, 128, 68, 65, 72, 89, 65, 65, 85, 83, 72, 128, 68, 65, - 71, 83, 128, 68, 65, 71, 71, 69, 82, 128, 68, 65, 71, 71, 69, 210, 68, - 65, 71, 69, 83, 72, 128, 68, 65, 71, 69, 83, 200, 68, 65, 71, 66, 65, 83, - 73, 78, 78, 65, 128, 68, 65, 71, 65, 218, 68, 65, 71, 65, 76, 71, 65, - 128, 68, 65, 71, 51, 128, 68, 65, 199, 68, 65, 69, 78, 71, 128, 68, 65, - 69, 199, 68, 65, 68, 128, 68, 65, 196, 68, 65, 65, 83, 85, 128, 68, 65, - 65, 76, 73, 128, 68, 65, 65, 68, 72, 85, 128, 68, 48, 54, 55, 72, 128, - 68, 48, 54, 55, 71, 128, 68, 48, 54, 55, 70, 128, 68, 48, 54, 55, 69, - 128, 68, 48, 54, 55, 68, 128, 68, 48, 54, 55, 67, 128, 68, 48, 54, 55, - 66, 128, 68, 48, 54, 55, 65, 128, 68, 48, 54, 55, 128, 68, 48, 54, 54, - 128, 68, 48, 54, 53, 128, 68, 48, 54, 52, 128, 68, 48, 54, 51, 128, 68, - 48, 54, 50, 128, 68, 48, 54, 49, 128, 68, 48, 54, 48, 128, 68, 48, 53, - 57, 128, 68, 48, 53, 56, 128, 68, 48, 53, 55, 128, 68, 48, 53, 54, 128, - 68, 48, 53, 53, 128, 68, 48, 53, 52, 65, 128, 68, 48, 53, 52, 128, 68, - 48, 53, 51, 128, 68, 48, 53, 50, 65, 128, 68, 48, 53, 50, 128, 68, 48, - 53, 49, 128, 68, 48, 53, 48, 73, 128, 68, 48, 53, 48, 72, 128, 68, 48, - 53, 48, 71, 128, 68, 48, 53, 48, 70, 128, 68, 48, 53, 48, 69, 128, 68, - 48, 53, 48, 68, 128, 68, 48, 53, 48, 67, 128, 68, 48, 53, 48, 66, 128, - 68, 48, 53, 48, 65, 128, 68, 48, 53, 48, 128, 68, 48, 52, 57, 128, 68, - 48, 52, 56, 65, 128, 68, 48, 52, 56, 128, 68, 48, 52, 55, 128, 68, 48, - 52, 54, 65, 128, 68, 48, 52, 54, 128, 68, 48, 52, 53, 128, 68, 48, 52, - 52, 128, 68, 48, 52, 51, 128, 68, 48, 52, 50, 128, 68, 48, 52, 49, 128, - 68, 48, 52, 48, 128, 68, 48, 51, 57, 128, 68, 48, 51, 56, 128, 68, 48, - 51, 55, 128, 68, 48, 51, 54, 128, 68, 48, 51, 53, 128, 68, 48, 51, 52, - 65, 128, 68, 48, 51, 52, 128, 68, 48, 51, 51, 128, 68, 48, 51, 50, 128, - 68, 48, 51, 49, 65, 128, 68, 48, 51, 49, 128, 68, 48, 51, 48, 128, 68, - 48, 50, 57, 128, 68, 48, 50, 56, 128, 68, 48, 50, 55, 65, 128, 68, 48, - 50, 55, 128, 68, 48, 50, 54, 128, 68, 48, 50, 53, 128, 68, 48, 50, 52, - 128, 68, 48, 50, 51, 128, 68, 48, 50, 50, 128, 68, 48, 50, 49, 128, 68, - 48, 50, 48, 128, 68, 48, 49, 57, 128, 68, 48, 49, 56, 128, 68, 48, 49, - 55, 128, 68, 48, 49, 54, 128, 68, 48, 49, 53, 128, 68, 48, 49, 52, 128, - 68, 48, 49, 51, 128, 68, 48, 49, 50, 128, 68, 48, 49, 49, 128, 68, 48, - 49, 48, 128, 68, 48, 48, 57, 128, 68, 48, 48, 56, 65, 128, 68, 48, 48, - 56, 128, 68, 48, 48, 55, 128, 68, 48, 48, 54, 128, 68, 48, 48, 53, 128, - 68, 48, 48, 52, 128, 68, 48, 48, 51, 128, 68, 48, 48, 50, 128, 68, 48, - 48, 49, 128, 67, 89, 88, 128, 67, 89, 84, 128, 67, 89, 82, 88, 128, 67, - 89, 82, 69, 78, 65, 73, 195, 67, 89, 82, 128, 67, 89, 80, 82, 79, 45, 77, - 73, 78, 79, 65, 206, 67, 89, 80, 82, 73, 79, 212, 67, 89, 80, 69, 82, 85, - 83, 128, 67, 89, 80, 128, 67, 89, 76, 73, 78, 68, 82, 73, 67, 73, 84, 89, - 128, 67, 89, 67, 76, 79, 78, 69, 128, 67, 89, 65, 89, 128, 67, 89, 65, - 87, 128, 67, 89, 65, 128, 67, 87, 79, 79, 128, 67, 87, 79, 128, 67, 87, - 73, 73, 128, 67, 87, 73, 128, 67, 87, 69, 79, 82, 84, 72, 128, 67, 87, - 69, 128, 67, 87, 65, 65, 128, 67, 85, 88, 128, 67, 85, 85, 128, 67, 85, - 212, 67, 85, 83, 84, 79, 77, 83, 128, 67, 85, 83, 84, 79, 77, 69, 210, - 67, 85, 83, 84, 65, 82, 68, 128, 67, 85, 83, 80, 128, 67, 85, 82, 88, - 128, 67, 85, 82, 86, 73, 78, 199, 67, 85, 82, 86, 69, 68, 128, 67, 85, - 82, 86, 69, 196, 67, 85, 82, 86, 69, 128, 67, 85, 82, 86, 197, 67, 85, - 82, 83, 73, 86, 197, 67, 85, 82, 82, 217, 67, 85, 82, 82, 69, 78, 84, - 128, 67, 85, 82, 82, 69, 78, 212, 67, 85, 82, 76, 217, 67, 85, 82, 76, - 73, 78, 199, 67, 85, 82, 76, 69, 196, 67, 85, 82, 76, 128, 67, 85, 82, - 128, 67, 85, 80, 80, 69, 68, 128, 67, 85, 80, 80, 69, 196, 67, 85, 80, - 73, 68, 79, 128, 67, 85, 80, 67, 65, 75, 69, 128, 67, 85, 79, 88, 128, - 67, 85, 79, 80, 128, 67, 85, 79, 128, 67, 85, 205, 67, 85, 76, 84, 73, - 86, 65, 84, 73, 79, 206, 67, 85, 67, 85, 77, 66, 69, 82, 128, 67, 85, 66, - 69, 68, 128, 67, 85, 66, 69, 128, 67, 85, 66, 197, 67, 85, 65, 84, 82, - 73, 76, 76, 79, 128, 67, 85, 65, 84, 82, 73, 76, 76, 207, 67, 85, 65, - 205, 67, 83, 73, 128, 67, 82, 89, 83, 84, 65, 204, 67, 82, 89, 80, 84, - 79, 71, 82, 65, 77, 77, 73, 195, 67, 82, 89, 73, 78, 199, 67, 82, 85, 90, - 69, 73, 82, 207, 67, 82, 85, 84, 67, 72, 128, 67, 82, 85, 67, 73, 70, 79, - 82, 205, 67, 82, 85, 67, 73, 66, 76, 69, 45, 53, 128, 67, 82, 85, 67, 73, - 66, 76, 69, 45, 52, 128, 67, 82, 85, 67, 73, 66, 76, 69, 45, 51, 128, 67, - 82, 85, 67, 73, 66, 76, 69, 45, 50, 128, 67, 82, 85, 67, 73, 66, 76, 69, - 128, 67, 82, 79, 87, 78, 128, 67, 82, 79, 83, 83, 73, 78, 71, 128, 67, - 82, 79, 83, 83, 73, 78, 199, 67, 82, 79, 83, 83, 72, 65, 84, 67, 200, 67, - 82, 79, 83, 83, 69, 68, 45, 84, 65, 73, 76, 128, 67, 82, 79, 83, 83, 69, - 68, 128, 67, 82, 79, 83, 83, 69, 196, 67, 82, 79, 83, 83, 66, 79, 78, 69, - 83, 128, 67, 82, 79, 83, 83, 66, 65, 82, 128, 67, 82, 79, 83, 83, 128, - 67, 82, 79, 83, 211, 67, 82, 79, 80, 128, 67, 82, 79, 73, 88, 128, 67, - 82, 79, 73, 83, 83, 65, 78, 84, 128, 67, 82, 79, 67, 85, 211, 67, 82, 79, - 67, 79, 68, 73, 76, 69, 128, 67, 82, 73, 67, 75, 69, 84, 128, 67, 82, 73, - 67, 75, 69, 212, 67, 82, 69, 83, 67, 69, 78, 84, 83, 128, 67, 82, 69, 83, - 67, 69, 78, 84, 128, 67, 82, 69, 83, 67, 69, 78, 212, 67, 82, 69, 68, 73, - 212, 67, 82, 69, 65, 84, 73, 86, 197, 67, 82, 69, 65, 77, 128, 67, 82, - 65, 89, 79, 78, 128, 67, 82, 65, 66, 128, 67, 82, 128, 67, 79, 88, 128, - 67, 79, 87, 66, 79, 217, 67, 79, 87, 128, 67, 79, 215, 67, 79, 86, 69, - 82, 73, 78, 199, 67, 79, 86, 69, 82, 128, 67, 79, 85, 80, 76, 197, 67, - 79, 85, 78, 84, 73, 78, 199, 67, 79, 85, 78, 84, 69, 82, 83, 73, 78, 75, - 128, 67, 79, 85, 78, 84, 69, 82, 66, 79, 82, 69, 128, 67, 79, 85, 78, 67, - 73, 204, 67, 79, 85, 67, 200, 67, 79, 84, 128, 67, 79, 82, 82, 69, 83, - 80, 79, 78, 68, 211, 67, 79, 82, 82, 69, 67, 84, 128, 67, 79, 82, 80, 83, - 69, 128, 67, 79, 82, 80, 79, 82, 65, 84, 73, 79, 78, 128, 67, 79, 82, 79, - 78, 73, 83, 128, 67, 79, 82, 78, 73, 83, 200, 67, 79, 82, 78, 69, 82, 83, - 128, 67, 79, 82, 78, 69, 82, 128, 67, 79, 82, 78, 69, 210, 67, 79, 82, - 75, 128, 67, 79, 82, 65, 76, 128, 67, 79, 80, 89, 82, 73, 71, 72, 84, - 128, 67, 79, 80, 89, 82, 73, 71, 72, 212, 67, 79, 80, 89, 76, 69, 70, - 212, 67, 79, 80, 89, 128, 67, 79, 80, 82, 79, 68, 85, 67, 84, 128, 67, - 79, 80, 80, 69, 82, 45, 50, 128, 67, 79, 80, 80, 69, 82, 128, 67, 79, 80, - 128, 67, 79, 79, 76, 128, 67, 79, 79, 75, 73, 78, 71, 128, 67, 79, 79, - 75, 73, 69, 128, 67, 79, 79, 75, 69, 196, 67, 79, 79, 128, 67, 79, 78, - 86, 69, 82, 71, 73, 78, 199, 67, 79, 78, 86, 69, 78, 73, 69, 78, 67, 197, - 67, 79, 78, 84, 82, 79, 76, 128, 67, 79, 78, 84, 82, 79, 204, 67, 79, 78, - 84, 82, 65, 82, 73, 69, 84, 89, 128, 67, 79, 78, 84, 82, 65, 67, 84, 73, - 79, 78, 128, 67, 79, 78, 84, 79, 85, 82, 69, 196, 67, 79, 78, 84, 79, 85, - 210, 67, 79, 78, 84, 73, 78, 85, 73, 78, 199, 67, 79, 78, 84, 73, 78, 85, - 65, 84, 73, 79, 206, 67, 79, 78, 84, 69, 78, 84, 73, 79, 78, 128, 67, 79, - 78, 84, 69, 77, 80, 76, 65, 84, 73, 79, 78, 128, 67, 79, 78, 84, 65, 73, - 78, 211, 67, 79, 78, 84, 65, 73, 78, 73, 78, 199, 67, 79, 78, 84, 65, 73, - 206, 67, 79, 78, 84, 65, 67, 84, 128, 67, 79, 78, 83, 84, 82, 85, 67, 84, - 73, 79, 78, 128, 67, 79, 78, 83, 84, 82, 85, 67, 84, 73, 79, 206, 67, 79, - 78, 83, 84, 65, 78, 84, 128, 67, 79, 78, 83, 84, 65, 78, 212, 67, 79, 78, - 83, 84, 65, 78, 67, 89, 128, 67, 79, 78, 83, 69, 67, 85, 84, 73, 86, 197, - 67, 79, 78, 74, 85, 78, 67, 84, 73, 79, 78, 128, 67, 79, 78, 74, 85, 71, - 65, 84, 197, 67, 79, 78, 74, 79, 73, 78, 73, 78, 199, 67, 79, 78, 74, 79, - 73, 78, 69, 82, 128, 67, 79, 78, 74, 79, 73, 78, 69, 68, 128, 67, 79, 78, - 74, 79, 73, 78, 69, 196, 67, 79, 78, 73, 67, 65, 204, 67, 79, 78, 71, 82, - 85, 69, 78, 212, 67, 79, 78, 71, 82, 65, 84, 85, 76, 65, 84, 73, 79, 78, - 128, 67, 79, 78, 70, 85, 83, 69, 196, 67, 79, 78, 70, 79, 85, 78, 68, 69, - 196, 67, 79, 78, 70, 76, 73, 67, 84, 128, 67, 79, 78, 70, 69, 84, 84, - 201, 67, 79, 78, 67, 65, 86, 69, 45, 83, 73, 68, 69, 196, 67, 79, 78, 67, - 65, 86, 69, 45, 80, 79, 73, 78, 84, 69, 196, 67, 79, 77, 80, 85, 84, 69, - 82, 83, 128, 67, 79, 77, 80, 85, 84, 69, 82, 128, 67, 79, 77, 80, 82, 69, - 83, 83, 73, 79, 78, 128, 67, 79, 77, 80, 82, 69, 83, 83, 69, 196, 67, 79, - 77, 80, 79, 83, 73, 84, 73, 79, 78, 128, 67, 79, 77, 80, 79, 83, 73, 84, - 73, 79, 206, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 55, 54, 56, 128, 67, - 79, 77, 80, 79, 78, 69, 78, 84, 45, 55, 54, 55, 128, 67, 79, 77, 80, 79, - 78, 69, 78, 84, 45, 55, 54, 54, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, - 45, 55, 54, 53, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 55, 54, 52, - 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 55, 54, 51, 128, 67, 79, 77, - 80, 79, 78, 69, 78, 84, 45, 55, 54, 50, 128, 67, 79, 77, 80, 79, 78, 69, - 78, 84, 45, 55, 54, 49, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 55, - 54, 48, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 55, 53, 57, 128, 67, - 79, 77, 80, 79, 78, 69, 78, 84, 45, 55, 53, 56, 128, 67, 79, 77, 80, 79, - 78, 69, 78, 84, 45, 55, 53, 55, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, - 45, 55, 53, 54, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 55, 53, 53, - 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 55, 53, 52, 128, 67, 79, 77, - 80, 79, 78, 69, 78, 84, 45, 55, 53, 51, 128, 67, 79, 77, 80, 79, 78, 69, - 78, 84, 45, 55, 53, 50, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 55, - 53, 49, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 55, 53, 48, 128, 67, - 79, 77, 80, 79, 78, 69, 78, 84, 45, 55, 52, 57, 128, 67, 79, 77, 80, 79, - 78, 69, 78, 84, 45, 55, 52, 56, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, - 45, 55, 52, 55, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 55, 52, 54, - 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 55, 52, 53, 128, 67, 79, 77, - 80, 79, 78, 69, 78, 84, 45, 55, 52, 52, 128, 67, 79, 77, 80, 79, 78, 69, - 78, 84, 45, 55, 52, 51, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 55, - 52, 50, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 55, 52, 49, 128, 67, - 79, 77, 80, 79, 78, 69, 78, 84, 45, 55, 52, 48, 128, 67, 79, 77, 80, 79, - 78, 69, 78, 84, 45, 55, 51, 57, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, - 45, 55, 51, 56, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 55, 51, 55, - 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 55, 51, 54, 128, 67, 79, 77, - 80, 79, 78, 69, 78, 84, 45, 55, 51, 53, 128, 67, 79, 77, 80, 79, 78, 69, - 78, 84, 45, 55, 51, 52, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 55, - 51, 51, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 55, 51, 50, 128, 67, - 79, 77, 80, 79, 78, 69, 78, 84, 45, 55, 51, 49, 128, 67, 79, 77, 80, 79, - 78, 69, 78, 84, 45, 55, 51, 48, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, - 45, 55, 50, 57, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 55, 50, 56, - 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 55, 50, 55, 128, 67, 79, 77, - 80, 79, 78, 69, 78, 84, 45, 55, 50, 54, 128, 67, 79, 77, 80, 79, 78, 69, - 78, 84, 45, 55, 50, 53, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 55, - 50, 52, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 55, 50, 51, 128, 67, - 79, 77, 80, 79, 78, 69, 78, 84, 45, 55, 50, 50, 128, 67, 79, 77, 80, 79, - 78, 69, 78, 84, 45, 55, 50, 49, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, - 45, 55, 50, 48, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 55, 49, 57, - 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 55, 49, 56, 128, 67, 79, 77, - 80, 79, 78, 69, 78, 84, 45, 55, 49, 55, 128, 67, 79, 77, 80, 79, 78, 69, - 78, 84, 45, 55, 49, 54, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 55, - 49, 53, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 55, 49, 52, 128, 67, - 79, 77, 80, 79, 78, 69, 78, 84, 45, 55, 49, 51, 128, 67, 79, 77, 80, 79, - 78, 69, 78, 84, 45, 55, 49, 50, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, - 45, 55, 49, 49, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 55, 49, 48, - 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 55, 48, 57, 128, 67, 79, 77, - 80, 79, 78, 69, 78, 84, 45, 55, 48, 56, 128, 67, 79, 77, 80, 79, 78, 69, - 78, 84, 45, 55, 48, 55, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 55, - 48, 54, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 55, 48, 53, 128, 67, - 79, 77, 80, 79, 78, 69, 78, 84, 45, 55, 48, 52, 128, 67, 79, 77, 80, 79, - 78, 69, 78, 84, 45, 55, 48, 51, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, - 45, 55, 48, 50, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 55, 48, 49, - 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 55, 48, 48, 128, 67, 79, 77, - 80, 79, 78, 69, 78, 84, 45, 54, 57, 57, 128, 67, 79, 77, 80, 79, 78, 69, - 78, 84, 45, 54, 57, 56, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 54, - 57, 55, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 54, 57, 54, 128, 67, - 79, 77, 80, 79, 78, 69, 78, 84, 45, 54, 57, 53, 128, 67, 79, 77, 80, 79, - 78, 69, 78, 84, 45, 54, 57, 52, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, - 45, 54, 57, 51, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 54, 57, 50, - 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 54, 57, 49, 128, 67, 79, 77, - 80, 79, 78, 69, 78, 84, 45, 54, 57, 48, 128, 67, 79, 77, 80, 79, 78, 69, - 78, 84, 45, 54, 56, 57, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 54, - 56, 56, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 54, 56, 55, 128, 67, - 79, 77, 80, 79, 78, 69, 78, 84, 45, 54, 56, 54, 128, 67, 79, 77, 80, 79, - 78, 69, 78, 84, 45, 54, 56, 53, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, - 45, 54, 56, 52, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 54, 56, 51, - 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 54, 56, 50, 128, 67, 79, 77, - 80, 79, 78, 69, 78, 84, 45, 54, 56, 49, 128, 67, 79, 77, 80, 79, 78, 69, - 78, 84, 45, 54, 56, 48, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 54, - 55, 57, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 54, 55, 56, 128, 67, - 79, 77, 80, 79, 78, 69, 78, 84, 45, 54, 55, 55, 128, 67, 79, 77, 80, 79, - 78, 69, 78, 84, 45, 54, 55, 54, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, - 45, 54, 55, 53, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 54, 55, 52, - 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 54, 55, 51, 128, 67, 79, 77, - 80, 79, 78, 69, 78, 84, 45, 54, 55, 50, 128, 67, 79, 77, 80, 79, 78, 69, - 78, 84, 45, 54, 55, 49, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 54, - 55, 48, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 54, 54, 57, 128, 67, - 79, 77, 80, 79, 78, 69, 78, 84, 45, 54, 54, 56, 128, 67, 79, 77, 80, 79, - 78, 69, 78, 84, 45, 54, 54, 55, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, - 45, 54, 54, 54, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 54, 54, 53, - 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 54, 54, 52, 128, 67, 79, 77, - 80, 79, 78, 69, 78, 84, 45, 54, 54, 51, 128, 67, 79, 77, 80, 79, 78, 69, - 78, 84, 45, 54, 54, 50, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 54, - 54, 49, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 54, 54, 48, 128, 67, - 79, 77, 80, 79, 78, 69, 78, 84, 45, 54, 53, 57, 128, 67, 79, 77, 80, 79, - 78, 69, 78, 84, 45, 54, 53, 56, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, - 45, 54, 53, 55, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 54, 53, 54, - 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 54, 53, 53, 128, 67, 79, 77, - 80, 79, 78, 69, 78, 84, 45, 54, 53, 52, 128, 67, 79, 77, 80, 79, 78, 69, - 78, 84, 45, 54, 53, 51, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 54, - 53, 50, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 54, 53, 49, 128, 67, - 79, 77, 80, 79, 78, 69, 78, 84, 45, 54, 53, 48, 128, 67, 79, 77, 80, 79, - 78, 69, 78, 84, 45, 54, 52, 57, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, - 45, 54, 52, 56, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 54, 52, 55, - 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 54, 52, 54, 128, 67, 79, 77, - 80, 79, 78, 69, 78, 84, 45, 54, 52, 53, 128, 67, 79, 77, 80, 79, 78, 69, - 78, 84, 45, 54, 52, 52, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 54, - 52, 51, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 54, 52, 50, 128, 67, - 79, 77, 80, 79, 78, 69, 78, 84, 45, 54, 52, 49, 128, 67, 79, 77, 80, 79, - 78, 69, 78, 84, 45, 54, 52, 48, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, - 45, 54, 51, 57, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 54, 51, 56, - 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 54, 51, 55, 128, 67, 79, 77, - 80, 79, 78, 69, 78, 84, 45, 54, 51, 54, 128, 67, 79, 77, 80, 79, 78, 69, - 78, 84, 45, 54, 51, 53, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 54, - 51, 52, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 54, 51, 51, 128, 67, - 79, 77, 80, 79, 78, 69, 78, 84, 45, 54, 51, 50, 128, 67, 79, 77, 80, 79, - 78, 69, 78, 84, 45, 54, 51, 49, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, - 45, 54, 51, 48, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 54, 50, 57, - 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 54, 50, 56, 128, 67, 79, 77, - 80, 79, 78, 69, 78, 84, 45, 54, 50, 55, 128, 67, 79, 77, 80, 79, 78, 69, - 78, 84, 45, 54, 50, 54, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 54, - 50, 53, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 54, 50, 52, 128, 67, - 79, 77, 80, 79, 78, 69, 78, 84, 45, 54, 50, 51, 128, 67, 79, 77, 80, 79, - 78, 69, 78, 84, 45, 54, 50, 50, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, - 45, 54, 50, 49, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 54, 50, 48, - 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 54, 49, 57, 128, 67, 79, 77, - 80, 79, 78, 69, 78, 84, 45, 54, 49, 56, 128, 67, 79, 77, 80, 79, 78, 69, - 78, 84, 45, 54, 49, 55, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 54, - 49, 54, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 54, 49, 53, 128, 67, - 79, 77, 80, 79, 78, 69, 78, 84, 45, 54, 49, 52, 128, 67, 79, 77, 80, 79, - 78, 69, 78, 84, 45, 54, 49, 51, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, - 45, 54, 49, 50, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 54, 49, 49, - 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 54, 49, 48, 128, 67, 79, 77, - 80, 79, 78, 69, 78, 84, 45, 54, 48, 57, 128, 67, 79, 77, 80, 79, 78, 69, - 78, 84, 45, 54, 48, 56, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 54, - 48, 55, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 54, 48, 54, 128, 67, - 79, 77, 80, 79, 78, 69, 78, 84, 45, 54, 48, 53, 128, 67, 79, 77, 80, 79, - 78, 69, 78, 84, 45, 54, 48, 52, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, - 45, 54, 48, 51, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 54, 48, 50, - 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 54, 48, 49, 128, 67, 79, 77, - 80, 79, 78, 69, 78, 84, 45, 54, 48, 48, 128, 67, 79, 77, 80, 79, 78, 69, - 78, 84, 45, 53, 57, 57, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 53, - 57, 56, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 53, 57, 55, 128, 67, - 79, 77, 80, 79, 78, 69, 78, 84, 45, 53, 57, 54, 128, 67, 79, 77, 80, 79, - 78, 69, 78, 84, 45, 53, 57, 53, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, - 45, 53, 57, 52, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 53, 57, 51, - 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 53, 57, 50, 128, 67, 79, 77, - 80, 79, 78, 69, 78, 84, 45, 53, 57, 49, 128, 67, 79, 77, 80, 79, 78, 69, - 78, 84, 45, 53, 57, 48, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 53, - 56, 57, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 53, 56, 56, 128, 67, - 79, 77, 80, 79, 78, 69, 78, 84, 45, 53, 56, 55, 128, 67, 79, 77, 80, 79, - 78, 69, 78, 84, 45, 53, 56, 54, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, - 45, 53, 56, 53, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 53, 56, 52, - 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 53, 56, 51, 128, 67, 79, 77, - 80, 79, 78, 69, 78, 84, 45, 53, 56, 50, 128, 67, 79, 77, 80, 79, 78, 69, - 78, 84, 45, 53, 56, 49, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 53, - 56, 48, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 53, 55, 57, 128, 67, - 79, 77, 80, 79, 78, 69, 78, 84, 45, 53, 55, 56, 128, 67, 79, 77, 80, 79, - 78, 69, 78, 84, 45, 53, 55, 55, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, - 45, 53, 55, 54, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 53, 55, 53, - 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 53, 55, 52, 128, 67, 79, 77, - 80, 79, 78, 69, 78, 84, 45, 53, 55, 51, 128, 67, 79, 77, 80, 79, 78, 69, - 78, 84, 45, 53, 55, 50, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 53, - 55, 49, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 53, 55, 48, 128, 67, - 79, 77, 80, 79, 78, 69, 78, 84, 45, 53, 54, 57, 128, 67, 79, 77, 80, 79, - 78, 69, 78, 84, 45, 53, 54, 56, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, - 45, 53, 54, 55, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 53, 54, 54, - 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 53, 54, 53, 128, 67, 79, 77, - 80, 79, 78, 69, 78, 84, 45, 53, 54, 52, 128, 67, 79, 77, 80, 79, 78, 69, - 78, 84, 45, 53, 54, 51, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 53, - 54, 50, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 53, 54, 49, 128, 67, - 79, 77, 80, 79, 78, 69, 78, 84, 45, 53, 54, 48, 128, 67, 79, 77, 80, 79, - 78, 69, 78, 84, 45, 53, 53, 57, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, - 45, 53, 53, 56, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 53, 53, 55, - 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 53, 53, 54, 128, 67, 79, 77, - 80, 79, 78, 69, 78, 84, 45, 53, 53, 53, 128, 67, 79, 77, 80, 79, 78, 69, - 78, 84, 45, 53, 53, 52, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 53, - 53, 51, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 53, 53, 50, 128, 67, - 79, 77, 80, 79, 78, 69, 78, 84, 45, 53, 53, 49, 128, 67, 79, 77, 80, 79, - 78, 69, 78, 84, 45, 53, 53, 48, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, - 45, 53, 52, 57, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 53, 52, 56, - 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 53, 52, 55, 128, 67, 79, 77, - 80, 79, 78, 69, 78, 84, 45, 53, 52, 54, 128, 67, 79, 77, 80, 79, 78, 69, - 78, 84, 45, 53, 52, 53, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 53, - 52, 52, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 53, 52, 51, 128, 67, - 79, 77, 80, 79, 78, 69, 78, 84, 45, 53, 52, 50, 128, 67, 79, 77, 80, 79, - 78, 69, 78, 84, 45, 53, 52, 49, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, - 45, 53, 52, 48, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 53, 51, 57, - 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 53, 51, 56, 128, 67, 79, 77, - 80, 79, 78, 69, 78, 84, 45, 53, 51, 55, 128, 67, 79, 77, 80, 79, 78, 69, - 78, 84, 45, 53, 51, 54, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 53, - 51, 53, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 53, 51, 52, 128, 67, - 79, 77, 80, 79, 78, 69, 78, 84, 45, 53, 51, 51, 128, 67, 79, 77, 80, 79, - 78, 69, 78, 84, 45, 53, 51, 50, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, - 45, 53, 51, 49, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 53, 51, 48, - 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 53, 50, 57, 128, 67, 79, 77, - 80, 79, 78, 69, 78, 84, 45, 53, 50, 56, 128, 67, 79, 77, 80, 79, 78, 69, - 78, 84, 45, 53, 50, 55, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 53, - 50, 54, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 53, 50, 53, 128, 67, - 79, 77, 80, 79, 78, 69, 78, 84, 45, 53, 50, 52, 128, 67, 79, 77, 80, 79, - 78, 69, 78, 84, 45, 53, 50, 51, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, - 45, 53, 50, 50, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 53, 50, 49, - 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 53, 50, 48, 128, 67, 79, 77, - 80, 79, 78, 69, 78, 84, 45, 53, 49, 57, 128, 67, 79, 77, 80, 79, 78, 69, - 78, 84, 45, 53, 49, 56, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 53, - 49, 55, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 53, 49, 54, 128, 67, - 79, 77, 80, 79, 78, 69, 78, 84, 45, 53, 49, 53, 128, 67, 79, 77, 80, 79, - 78, 69, 78, 84, 45, 53, 49, 52, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, - 45, 53, 49, 51, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 53, 49, 50, - 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 53, 49, 49, 128, 67, 79, 77, - 80, 79, 78, 69, 78, 84, 45, 53, 49, 48, 128, 67, 79, 77, 80, 79, 78, 69, - 78, 84, 45, 53, 48, 57, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 53, - 48, 56, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 53, 48, 55, 128, 67, - 79, 77, 80, 79, 78, 69, 78, 84, 45, 53, 48, 54, 128, 67, 79, 77, 80, 79, - 78, 69, 78, 84, 45, 53, 48, 53, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, - 45, 53, 48, 52, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 53, 48, 51, - 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 53, 48, 50, 128, 67, 79, 77, - 80, 79, 78, 69, 78, 84, 45, 53, 48, 49, 128, 67, 79, 77, 80, 79, 78, 69, - 78, 84, 45, 53, 48, 48, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 52, - 57, 57, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 52, 57, 56, 128, 67, - 79, 77, 80, 79, 78, 69, 78, 84, 45, 52, 57, 55, 128, 67, 79, 77, 80, 79, - 78, 69, 78, 84, 45, 52, 57, 54, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, - 45, 52, 57, 53, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 52, 57, 52, - 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 52, 57, 51, 128, 67, 79, 77, - 80, 79, 78, 69, 78, 84, 45, 52, 57, 50, 128, 67, 79, 77, 80, 79, 78, 69, - 78, 84, 45, 52, 57, 49, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 52, - 57, 48, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 52, 56, 57, 128, 67, - 79, 77, 80, 79, 78, 69, 78, 84, 45, 52, 56, 56, 128, 67, 79, 77, 80, 79, - 78, 69, 78, 84, 45, 52, 56, 55, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, - 45, 52, 56, 54, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 52, 56, 53, - 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 52, 56, 52, 128, 67, 79, 77, - 80, 79, 78, 69, 78, 84, 45, 52, 56, 51, 128, 67, 79, 77, 80, 79, 78, 69, - 78, 84, 45, 52, 56, 50, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 52, - 56, 49, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 52, 56, 48, 128, 67, - 79, 77, 80, 79, 78, 69, 78, 84, 45, 52, 55, 57, 128, 67, 79, 77, 80, 79, - 78, 69, 78, 84, 45, 52, 55, 56, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, - 45, 52, 55, 55, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 52, 55, 54, - 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 52, 55, 53, 128, 67, 79, 77, - 80, 79, 78, 69, 78, 84, 45, 52, 55, 52, 128, 67, 79, 77, 80, 79, 78, 69, - 78, 84, 45, 52, 55, 51, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 52, - 55, 50, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 52, 55, 49, 128, 67, - 79, 77, 80, 79, 78, 69, 78, 84, 45, 52, 55, 48, 128, 67, 79, 77, 80, 79, - 78, 69, 78, 84, 45, 52, 54, 57, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, - 45, 52, 54, 56, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 52, 54, 55, - 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 52, 54, 54, 128, 67, 79, 77, - 80, 79, 78, 69, 78, 84, 45, 52, 54, 53, 128, 67, 79, 77, 80, 79, 78, 69, - 78, 84, 45, 52, 54, 52, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 52, - 54, 51, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 52, 54, 50, 128, 67, - 79, 77, 80, 79, 78, 69, 78, 84, 45, 52, 54, 49, 128, 67, 79, 77, 80, 79, - 78, 69, 78, 84, 45, 52, 54, 48, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, - 45, 52, 53, 57, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 52, 53, 56, - 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 52, 53, 55, 128, 67, 79, 77, - 80, 79, 78, 69, 78, 84, 45, 52, 53, 54, 128, 67, 79, 77, 80, 79, 78, 69, - 78, 84, 45, 52, 53, 53, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 52, - 53, 52, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 52, 53, 51, 128, 67, - 79, 77, 80, 79, 78, 69, 78, 84, 45, 52, 53, 50, 128, 67, 79, 77, 80, 79, - 78, 69, 78, 84, 45, 52, 53, 49, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, - 45, 52, 53, 48, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 52, 52, 57, - 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 52, 52, 56, 128, 67, 79, 77, - 80, 79, 78, 69, 78, 84, 45, 52, 52, 55, 128, 67, 79, 77, 80, 79, 78, 69, - 78, 84, 45, 52, 52, 54, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 52, - 52, 53, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 52, 52, 52, 128, 67, - 79, 77, 80, 79, 78, 69, 78, 84, 45, 52, 52, 51, 128, 67, 79, 77, 80, 79, - 78, 69, 78, 84, 45, 52, 52, 50, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, - 45, 52, 52, 49, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 52, 52, 48, - 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 52, 51, 57, 128, 67, 79, 77, - 80, 79, 78, 69, 78, 84, 45, 52, 51, 56, 128, 67, 79, 77, 80, 79, 78, 69, - 78, 84, 45, 52, 51, 55, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 52, - 51, 54, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 52, 51, 53, 128, 67, - 79, 77, 80, 79, 78, 69, 78, 84, 45, 52, 51, 52, 128, 67, 79, 77, 80, 79, - 78, 69, 78, 84, 45, 52, 51, 51, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, - 45, 52, 51, 50, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 52, 51, 49, - 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 52, 51, 48, 128, 67, 79, 77, - 80, 79, 78, 69, 78, 84, 45, 52, 50, 57, 128, 67, 79, 77, 80, 79, 78, 69, - 78, 84, 45, 52, 50, 56, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 52, - 50, 55, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 52, 50, 54, 128, 67, - 79, 77, 80, 79, 78, 69, 78, 84, 45, 52, 50, 53, 128, 67, 79, 77, 80, 79, - 78, 69, 78, 84, 45, 52, 50, 52, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, - 45, 52, 50, 51, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 52, 50, 50, - 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 52, 50, 49, 128, 67, 79, 77, - 80, 79, 78, 69, 78, 84, 45, 52, 50, 48, 128, 67, 79, 77, 80, 79, 78, 69, - 78, 84, 45, 52, 49, 57, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 52, - 49, 56, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 52, 49, 55, 128, 67, - 79, 77, 80, 79, 78, 69, 78, 84, 45, 52, 49, 54, 128, 67, 79, 77, 80, 79, - 78, 69, 78, 84, 45, 52, 49, 53, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, - 45, 52, 49, 52, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 52, 49, 51, - 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 52, 49, 50, 128, 67, 79, 77, - 80, 79, 78, 69, 78, 84, 45, 52, 49, 49, 128, 67, 79, 77, 80, 79, 78, 69, - 78, 84, 45, 52, 49, 48, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 52, - 48, 57, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 52, 48, 56, 128, 67, - 79, 77, 80, 79, 78, 69, 78, 84, 45, 52, 48, 55, 128, 67, 79, 77, 80, 79, - 78, 69, 78, 84, 45, 52, 48, 54, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, - 45, 52, 48, 53, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 52, 48, 52, - 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 52, 48, 51, 128, 67, 79, 77, - 80, 79, 78, 69, 78, 84, 45, 52, 48, 50, 128, 67, 79, 77, 80, 79, 78, 69, - 78, 84, 45, 52, 48, 49, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 52, - 48, 48, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 51, 57, 57, 128, 67, - 79, 77, 80, 79, 78, 69, 78, 84, 45, 51, 57, 56, 128, 67, 79, 77, 80, 79, - 78, 69, 78, 84, 45, 51, 57, 55, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, - 45, 51, 57, 54, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 51, 57, 53, - 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 51, 57, 52, 128, 67, 79, 77, - 80, 79, 78, 69, 78, 84, 45, 51, 57, 51, 128, 67, 79, 77, 80, 79, 78, 69, - 78, 84, 45, 51, 57, 50, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 51, - 57, 49, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 51, 57, 48, 128, 67, - 79, 77, 80, 79, 78, 69, 78, 84, 45, 51, 56, 57, 128, 67, 79, 77, 80, 79, - 78, 69, 78, 84, 45, 51, 56, 56, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, - 45, 51, 56, 55, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 51, 56, 54, - 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 51, 56, 53, 128, 67, 79, 77, - 80, 79, 78, 69, 78, 84, 45, 51, 56, 52, 128, 67, 79, 77, 80, 79, 78, 69, - 78, 84, 45, 51, 56, 51, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 51, - 56, 50, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 51, 56, 49, 128, 67, - 79, 77, 80, 79, 78, 69, 78, 84, 45, 51, 56, 48, 128, 67, 79, 77, 80, 79, - 78, 69, 78, 84, 45, 51, 55, 57, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, - 45, 51, 55, 56, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 51, 55, 55, - 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 51, 55, 54, 128, 67, 79, 77, - 80, 79, 78, 69, 78, 84, 45, 51, 55, 53, 128, 67, 79, 77, 80, 79, 78, 69, - 78, 84, 45, 51, 55, 52, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 51, - 55, 51, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 51, 55, 50, 128, 67, - 79, 77, 80, 79, 78, 69, 78, 84, 45, 51, 55, 49, 128, 67, 79, 77, 80, 79, - 78, 69, 78, 84, 45, 51, 55, 48, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, - 45, 51, 54, 57, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 51, 54, 56, - 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 51, 54, 55, 128, 67, 79, 77, - 80, 79, 78, 69, 78, 84, 45, 51, 54, 54, 128, 67, 79, 77, 80, 79, 78, 69, - 78, 84, 45, 51, 54, 53, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 51, - 54, 52, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 51, 54, 51, 128, 67, - 79, 77, 80, 79, 78, 69, 78, 84, 45, 51, 54, 50, 128, 67, 79, 77, 80, 79, - 78, 69, 78, 84, 45, 51, 54, 49, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, - 45, 51, 54, 48, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 51, 53, 57, - 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 51, 53, 56, 128, 67, 79, 77, - 80, 79, 78, 69, 78, 84, 45, 51, 53, 55, 128, 67, 79, 77, 80, 79, 78, 69, - 78, 84, 45, 51, 53, 54, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 51, - 53, 53, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 51, 53, 52, 128, 67, - 79, 77, 80, 79, 78, 69, 78, 84, 45, 51, 53, 51, 128, 67, 79, 77, 80, 79, - 78, 69, 78, 84, 45, 51, 53, 50, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, - 45, 51, 53, 49, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 51, 53, 48, - 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 51, 52, 57, 128, 67, 79, 77, - 80, 79, 78, 69, 78, 84, 45, 51, 52, 56, 128, 67, 79, 77, 80, 79, 78, 69, - 78, 84, 45, 51, 52, 55, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 51, - 52, 54, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 51, 52, 53, 128, 67, - 79, 77, 80, 79, 78, 69, 78, 84, 45, 51, 52, 52, 128, 67, 79, 77, 80, 79, - 78, 69, 78, 84, 45, 51, 52, 51, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, - 45, 51, 52, 50, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 51, 52, 49, - 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 51, 52, 48, 128, 67, 79, 77, - 80, 79, 78, 69, 78, 84, 45, 51, 51, 57, 128, 67, 79, 77, 80, 79, 78, 69, - 78, 84, 45, 51, 51, 56, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 51, - 51, 55, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 51, 51, 54, 128, 67, - 79, 77, 80, 79, 78, 69, 78, 84, 45, 51, 51, 53, 128, 67, 79, 77, 80, 79, - 78, 69, 78, 84, 45, 51, 51, 52, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, - 45, 51, 51, 51, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 51, 51, 50, - 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 51, 51, 49, 128, 67, 79, 77, - 80, 79, 78, 69, 78, 84, 45, 51, 51, 48, 128, 67, 79, 77, 80, 79, 78, 69, - 78, 84, 45, 51, 50, 57, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 51, - 50, 56, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 51, 50, 55, 128, 67, - 79, 77, 80, 79, 78, 69, 78, 84, 45, 51, 50, 54, 128, 67, 79, 77, 80, 79, - 78, 69, 78, 84, 45, 51, 50, 53, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, - 45, 51, 50, 52, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 51, 50, 51, - 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 51, 50, 50, 128, 67, 79, 77, - 80, 79, 78, 69, 78, 84, 45, 51, 50, 49, 128, 67, 79, 77, 80, 79, 78, 69, - 78, 84, 45, 51, 50, 48, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 51, - 49, 57, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 51, 49, 56, 128, 67, - 79, 77, 80, 79, 78, 69, 78, 84, 45, 51, 49, 55, 128, 67, 79, 77, 80, 79, - 78, 69, 78, 84, 45, 51, 49, 54, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, - 45, 51, 49, 53, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 51, 49, 52, - 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 51, 49, 51, 128, 67, 79, 77, - 80, 79, 78, 69, 78, 84, 45, 51, 49, 50, 128, 67, 79, 77, 80, 79, 78, 69, - 78, 84, 45, 51, 49, 49, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 51, - 49, 48, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 51, 48, 57, 128, 67, - 79, 77, 80, 79, 78, 69, 78, 84, 45, 51, 48, 56, 128, 67, 79, 77, 80, 79, - 78, 69, 78, 84, 45, 51, 48, 55, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, - 45, 51, 48, 54, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 51, 48, 53, - 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 51, 48, 52, 128, 67, 79, 77, - 80, 79, 78, 69, 78, 84, 45, 51, 48, 51, 128, 67, 79, 77, 80, 79, 78, 69, - 78, 84, 45, 51, 48, 50, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 51, - 48, 49, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 51, 48, 48, 128, 67, - 79, 77, 80, 79, 78, 69, 78, 84, 45, 50, 57, 57, 128, 67, 79, 77, 80, 79, - 78, 69, 78, 84, 45, 50, 57, 56, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, - 45, 50, 57, 55, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 50, 57, 54, - 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 50, 57, 53, 128, 67, 79, 77, - 80, 79, 78, 69, 78, 84, 45, 50, 57, 52, 128, 67, 79, 77, 80, 79, 78, 69, - 78, 84, 45, 50, 57, 51, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 50, - 57, 50, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 50, 57, 49, 128, 67, - 79, 77, 80, 79, 78, 69, 78, 84, 45, 50, 57, 48, 128, 67, 79, 77, 80, 79, - 78, 69, 78, 84, 45, 50, 56, 57, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, - 45, 50, 56, 56, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 50, 56, 55, - 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 50, 56, 54, 128, 67, 79, 77, - 80, 79, 78, 69, 78, 84, 45, 50, 56, 53, 128, 67, 79, 77, 80, 79, 78, 69, - 78, 84, 45, 50, 56, 52, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 50, - 56, 51, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 50, 56, 50, 128, 67, - 79, 77, 80, 79, 78, 69, 78, 84, 45, 50, 56, 49, 128, 67, 79, 77, 80, 79, - 78, 69, 78, 84, 45, 50, 56, 48, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, - 45, 50, 55, 57, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 50, 55, 56, - 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 50, 55, 55, 128, 67, 79, 77, - 80, 79, 78, 69, 78, 84, 45, 50, 55, 54, 128, 67, 79, 77, 80, 79, 78, 69, - 78, 84, 45, 50, 55, 53, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 50, - 55, 52, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 50, 55, 51, 128, 67, - 79, 77, 80, 79, 78, 69, 78, 84, 45, 50, 55, 50, 128, 67, 79, 77, 80, 79, - 78, 69, 78, 84, 45, 50, 55, 49, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, - 45, 50, 55, 48, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 50, 54, 57, - 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 50, 54, 56, 128, 67, 79, 77, - 80, 79, 78, 69, 78, 84, 45, 50, 54, 55, 128, 67, 79, 77, 80, 79, 78, 69, - 78, 84, 45, 50, 54, 54, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 50, - 54, 53, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 50, 54, 52, 128, 67, - 79, 77, 80, 79, 78, 69, 78, 84, 45, 50, 54, 51, 128, 67, 79, 77, 80, 79, - 78, 69, 78, 84, 45, 50, 54, 50, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, - 45, 50, 54, 49, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 50, 54, 48, - 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 50, 53, 57, 128, 67, 79, 77, - 80, 79, 78, 69, 78, 84, 45, 50, 53, 56, 128, 67, 79, 77, 80, 79, 78, 69, - 78, 84, 45, 50, 53, 55, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 50, - 53, 54, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 50, 53, 53, 128, 67, - 79, 77, 80, 79, 78, 69, 78, 84, 45, 50, 53, 52, 128, 67, 79, 77, 80, 79, - 78, 69, 78, 84, 45, 50, 53, 51, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, - 45, 50, 53, 50, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 50, 53, 49, - 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 50, 53, 48, 128, 67, 79, 77, - 80, 79, 78, 69, 78, 84, 45, 50, 52, 57, 128, 67, 79, 77, 80, 79, 78, 69, - 78, 84, 45, 50, 52, 56, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 50, - 52, 55, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 50, 52, 54, 128, 67, - 79, 77, 80, 79, 78, 69, 78, 84, 45, 50, 52, 53, 128, 67, 79, 77, 80, 79, - 78, 69, 78, 84, 45, 50, 52, 52, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, - 45, 50, 52, 51, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 50, 52, 50, - 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 50, 52, 49, 128, 67, 79, 77, - 80, 79, 78, 69, 78, 84, 45, 50, 52, 48, 128, 67, 79, 77, 80, 79, 78, 69, - 78, 84, 45, 50, 51, 57, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 50, - 51, 56, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 50, 51, 55, 128, 67, - 79, 77, 80, 79, 78, 69, 78, 84, 45, 50, 51, 54, 128, 67, 79, 77, 80, 79, - 78, 69, 78, 84, 45, 50, 51, 53, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, - 45, 50, 51, 52, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 50, 51, 51, - 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 50, 51, 50, 128, 67, 79, 77, - 80, 79, 78, 69, 78, 84, 45, 50, 51, 49, 128, 67, 79, 77, 80, 79, 78, 69, - 78, 84, 45, 50, 51, 48, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 50, - 50, 57, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 50, 50, 56, 128, 67, - 79, 77, 80, 79, 78, 69, 78, 84, 45, 50, 50, 55, 128, 67, 79, 77, 80, 79, - 78, 69, 78, 84, 45, 50, 50, 54, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, - 45, 50, 50, 53, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 50, 50, 52, - 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 50, 50, 51, 128, 67, 79, 77, - 80, 79, 78, 69, 78, 84, 45, 50, 50, 50, 128, 67, 79, 77, 80, 79, 78, 69, - 78, 84, 45, 50, 50, 49, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 50, - 50, 48, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 50, 49, 57, 128, 67, - 79, 77, 80, 79, 78, 69, 78, 84, 45, 50, 49, 56, 128, 67, 79, 77, 80, 79, - 78, 69, 78, 84, 45, 50, 49, 55, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, - 45, 50, 49, 54, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 50, 49, 53, - 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 50, 49, 52, 128, 67, 79, 77, - 80, 79, 78, 69, 78, 84, 45, 50, 49, 51, 128, 67, 79, 77, 80, 79, 78, 69, - 78, 84, 45, 50, 49, 50, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 50, - 49, 49, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 50, 49, 48, 128, 67, - 79, 77, 80, 79, 78, 69, 78, 84, 45, 50, 48, 57, 128, 67, 79, 77, 80, 79, - 78, 69, 78, 84, 45, 50, 48, 56, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, - 45, 50, 48, 55, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 50, 48, 54, - 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 50, 48, 53, 128, 67, 79, 77, - 80, 79, 78, 69, 78, 84, 45, 50, 48, 52, 128, 67, 79, 77, 80, 79, 78, 69, - 78, 84, 45, 50, 48, 51, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 50, - 48, 50, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 50, 48, 49, 128, 67, - 79, 77, 80, 79, 78, 69, 78, 84, 45, 50, 48, 48, 128, 67, 79, 77, 80, 79, - 78, 69, 78, 84, 45, 49, 57, 57, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, - 45, 49, 57, 56, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 49, 57, 55, - 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 49, 57, 54, 128, 67, 79, 77, - 80, 79, 78, 69, 78, 84, 45, 49, 57, 53, 128, 67, 79, 77, 80, 79, 78, 69, - 78, 84, 45, 49, 57, 52, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 49, - 57, 51, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 49, 57, 50, 128, 67, - 79, 77, 80, 79, 78, 69, 78, 84, 45, 49, 57, 49, 128, 67, 79, 77, 80, 79, - 78, 69, 78, 84, 45, 49, 57, 48, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, - 45, 49, 56, 57, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 49, 56, 56, - 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 49, 56, 55, 128, 67, 79, 77, - 80, 79, 78, 69, 78, 84, 45, 49, 56, 54, 128, 67, 79, 77, 80, 79, 78, 69, - 78, 84, 45, 49, 56, 53, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 49, - 56, 52, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 49, 56, 51, 128, 67, - 79, 77, 80, 79, 78, 69, 78, 84, 45, 49, 56, 50, 128, 67, 79, 77, 80, 79, - 78, 69, 78, 84, 45, 49, 56, 49, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, - 45, 49, 56, 48, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 49, 55, 57, - 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 49, 55, 56, 128, 67, 79, 77, - 80, 79, 78, 69, 78, 84, 45, 49, 55, 55, 128, 67, 79, 77, 80, 79, 78, 69, - 78, 84, 45, 49, 55, 54, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 49, - 55, 53, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 49, 55, 52, 128, 67, - 79, 77, 80, 79, 78, 69, 78, 84, 45, 49, 55, 51, 128, 67, 79, 77, 80, 79, - 78, 69, 78, 84, 45, 49, 55, 50, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, - 45, 49, 55, 49, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 49, 55, 48, - 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 49, 54, 57, 128, 67, 79, 77, - 80, 79, 78, 69, 78, 84, 45, 49, 54, 56, 128, 67, 79, 77, 80, 79, 78, 69, - 78, 84, 45, 49, 54, 55, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 49, - 54, 54, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 49, 54, 53, 128, 67, - 79, 77, 80, 79, 78, 69, 78, 84, 45, 49, 54, 52, 128, 67, 79, 77, 80, 79, - 78, 69, 78, 84, 45, 49, 54, 51, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, - 45, 49, 54, 50, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 49, 54, 49, - 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 49, 54, 48, 128, 67, 79, 77, - 80, 79, 78, 69, 78, 84, 45, 49, 53, 57, 128, 67, 79, 77, 80, 79, 78, 69, - 78, 84, 45, 49, 53, 56, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 49, - 53, 55, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 49, 53, 54, 128, 67, - 79, 77, 80, 79, 78, 69, 78, 84, 45, 49, 53, 53, 128, 67, 79, 77, 80, 79, - 78, 69, 78, 84, 45, 49, 53, 52, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, - 45, 49, 53, 51, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 49, 53, 50, - 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 49, 53, 49, 128, 67, 79, 77, - 80, 79, 78, 69, 78, 84, 45, 49, 53, 48, 128, 67, 79, 77, 80, 79, 78, 69, - 78, 84, 45, 49, 52, 57, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 49, - 52, 56, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 49, 52, 55, 128, 67, - 79, 77, 80, 79, 78, 69, 78, 84, 45, 49, 52, 54, 128, 67, 79, 77, 80, 79, - 78, 69, 78, 84, 45, 49, 52, 53, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, - 45, 49, 52, 52, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 49, 52, 51, - 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 49, 52, 50, 128, 67, 79, 77, - 80, 79, 78, 69, 78, 84, 45, 49, 52, 49, 128, 67, 79, 77, 80, 79, 78, 69, - 78, 84, 45, 49, 52, 48, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 49, - 51, 57, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 49, 51, 56, 128, 67, - 79, 77, 80, 79, 78, 69, 78, 84, 45, 49, 51, 55, 128, 67, 79, 77, 80, 79, - 78, 69, 78, 84, 45, 49, 51, 54, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, - 45, 49, 51, 53, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 49, 51, 52, - 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 49, 51, 51, 128, 67, 79, 77, - 80, 79, 78, 69, 78, 84, 45, 49, 51, 50, 128, 67, 79, 77, 80, 79, 78, 69, - 78, 84, 45, 49, 51, 49, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 49, - 51, 48, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 49, 50, 57, 128, 67, - 79, 77, 80, 79, 78, 69, 78, 84, 45, 49, 50, 56, 128, 67, 79, 77, 80, 79, - 78, 69, 78, 84, 45, 49, 50, 55, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, - 45, 49, 50, 54, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 49, 50, 53, - 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 49, 50, 52, 128, 67, 79, 77, - 80, 79, 78, 69, 78, 84, 45, 49, 50, 51, 128, 67, 79, 77, 80, 79, 78, 69, - 78, 84, 45, 49, 50, 50, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 49, - 50, 49, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 49, 50, 48, 128, 67, - 79, 77, 80, 79, 78, 69, 78, 84, 45, 49, 49, 57, 128, 67, 79, 77, 80, 79, - 78, 69, 78, 84, 45, 49, 49, 56, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, - 45, 49, 49, 55, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 49, 49, 54, - 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 49, 49, 53, 128, 67, 79, 77, - 80, 79, 78, 69, 78, 84, 45, 49, 49, 52, 128, 67, 79, 77, 80, 79, 78, 69, - 78, 84, 45, 49, 49, 51, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 49, - 49, 50, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 49, 49, 49, 128, 67, - 79, 77, 80, 79, 78, 69, 78, 84, 45, 49, 49, 48, 128, 67, 79, 77, 80, 79, - 78, 69, 78, 84, 45, 49, 48, 57, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, - 45, 49, 48, 56, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 49, 48, 55, - 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 49, 48, 54, 128, 67, 79, 77, - 80, 79, 78, 69, 78, 84, 45, 49, 48, 53, 128, 67, 79, 77, 80, 79, 78, 69, - 78, 84, 45, 49, 48, 52, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 49, - 48, 51, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 49, 48, 50, 128, 67, - 79, 77, 80, 79, 78, 69, 78, 84, 45, 49, 48, 49, 128, 67, 79, 77, 80, 79, - 78, 69, 78, 84, 45, 49, 48, 48, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, - 45, 48, 57, 57, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 48, 57, 56, - 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 48, 57, 55, 128, 67, 79, 77, - 80, 79, 78, 69, 78, 84, 45, 48, 57, 54, 128, 67, 79, 77, 80, 79, 78, 69, - 78, 84, 45, 48, 57, 53, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 48, - 57, 52, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 48, 57, 51, 128, 67, - 79, 77, 80, 79, 78, 69, 78, 84, 45, 48, 57, 50, 128, 67, 79, 77, 80, 79, - 78, 69, 78, 84, 45, 48, 57, 49, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, - 45, 48, 57, 48, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 48, 56, 57, - 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 48, 56, 56, 128, 67, 79, 77, - 80, 79, 78, 69, 78, 84, 45, 48, 56, 55, 128, 67, 79, 77, 80, 79, 78, 69, - 78, 84, 45, 48, 56, 54, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 48, - 56, 53, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 48, 56, 52, 128, 67, - 79, 77, 80, 79, 78, 69, 78, 84, 45, 48, 56, 51, 128, 67, 79, 77, 80, 79, - 78, 69, 78, 84, 45, 48, 56, 50, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, - 45, 48, 56, 49, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 48, 56, 48, - 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 48, 55, 57, 128, 67, 79, 77, - 80, 79, 78, 69, 78, 84, 45, 48, 55, 56, 128, 67, 79, 77, 80, 79, 78, 69, - 78, 84, 45, 48, 55, 55, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 48, - 55, 54, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 48, 55, 53, 128, 67, - 79, 77, 80, 79, 78, 69, 78, 84, 45, 48, 55, 52, 128, 67, 79, 77, 80, 79, - 78, 69, 78, 84, 45, 48, 55, 51, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, - 45, 48, 55, 50, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 48, 55, 49, - 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 48, 55, 48, 128, 67, 79, 77, - 80, 79, 78, 69, 78, 84, 45, 48, 54, 57, 128, 67, 79, 77, 80, 79, 78, 69, - 78, 84, 45, 48, 54, 56, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 48, - 54, 55, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 48, 54, 54, 128, 67, - 79, 77, 80, 79, 78, 69, 78, 84, 45, 48, 54, 53, 128, 67, 79, 77, 80, 79, - 78, 69, 78, 84, 45, 48, 54, 52, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, - 45, 48, 54, 51, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 48, 54, 50, - 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 48, 54, 49, 128, 67, 79, 77, - 80, 79, 78, 69, 78, 84, 45, 48, 54, 48, 128, 67, 79, 77, 80, 79, 78, 69, - 78, 84, 45, 48, 53, 57, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 48, - 53, 56, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 48, 53, 55, 128, 67, - 79, 77, 80, 79, 78, 69, 78, 84, 45, 48, 53, 54, 128, 67, 79, 77, 80, 79, - 78, 69, 78, 84, 45, 48, 53, 53, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, - 45, 48, 53, 52, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 48, 53, 51, - 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 48, 53, 50, 128, 67, 79, 77, - 80, 79, 78, 69, 78, 84, 45, 48, 53, 49, 128, 67, 79, 77, 80, 79, 78, 69, - 78, 84, 45, 48, 53, 48, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 48, - 52, 57, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 48, 52, 56, 128, 67, - 79, 77, 80, 79, 78, 69, 78, 84, 45, 48, 52, 55, 128, 67, 79, 77, 80, 79, - 78, 69, 78, 84, 45, 48, 52, 54, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, - 45, 48, 52, 53, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 48, 52, 52, - 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 48, 52, 51, 128, 67, 79, 77, - 80, 79, 78, 69, 78, 84, 45, 48, 52, 50, 128, 67, 79, 77, 80, 79, 78, 69, - 78, 84, 45, 48, 52, 49, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 48, - 52, 48, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 48, 51, 57, 128, 67, - 79, 77, 80, 79, 78, 69, 78, 84, 45, 48, 51, 56, 128, 67, 79, 77, 80, 79, - 78, 69, 78, 84, 45, 48, 51, 55, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, - 45, 48, 51, 54, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 48, 51, 53, - 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 48, 51, 52, 128, 67, 79, 77, - 80, 79, 78, 69, 78, 84, 45, 48, 51, 51, 128, 67, 79, 77, 80, 79, 78, 69, - 78, 84, 45, 48, 51, 50, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 48, - 51, 49, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 48, 51, 48, 128, 67, - 79, 77, 80, 79, 78, 69, 78, 84, 45, 48, 50, 57, 128, 67, 79, 77, 80, 79, - 78, 69, 78, 84, 45, 48, 50, 56, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, - 45, 48, 50, 55, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 48, 50, 54, - 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 48, 50, 53, 128, 67, 79, 77, - 80, 79, 78, 69, 78, 84, 45, 48, 50, 52, 128, 67, 79, 77, 80, 79, 78, 69, - 78, 84, 45, 48, 50, 51, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 48, - 50, 50, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 48, 50, 49, 128, 67, - 79, 77, 80, 79, 78, 69, 78, 84, 45, 48, 50, 48, 128, 67, 79, 77, 80, 79, - 78, 69, 78, 84, 45, 48, 49, 57, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, - 45, 48, 49, 56, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 48, 49, 55, - 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 48, 49, 54, 128, 67, 79, 77, - 80, 79, 78, 69, 78, 84, 45, 48, 49, 53, 128, 67, 79, 77, 80, 79, 78, 69, - 78, 84, 45, 48, 49, 52, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 48, - 49, 51, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 48, 49, 50, 128, 67, - 79, 77, 80, 79, 78, 69, 78, 84, 45, 48, 49, 49, 128, 67, 79, 77, 80, 79, - 78, 69, 78, 84, 45, 48, 49, 48, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, - 45, 48, 48, 57, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 48, 48, 56, - 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 48, 48, 55, 128, 67, 79, 77, - 80, 79, 78, 69, 78, 84, 45, 48, 48, 54, 128, 67, 79, 77, 80, 79, 78, 69, - 78, 84, 45, 48, 48, 53, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 48, - 48, 52, 128, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, 48, 48, 51, 128, 67, - 79, 77, 80, 79, 78, 69, 78, 84, 45, 48, 48, 50, 128, 67, 79, 77, 80, 79, - 78, 69, 78, 84, 45, 48, 48, 49, 128, 67, 79, 77, 80, 79, 78, 69, 78, 212, - 67, 79, 77, 80, 76, 73, 65, 78, 67, 69, 128, 67, 79, 77, 80, 76, 69, 84, - 73, 79, 78, 128, 67, 79, 77, 80, 76, 69, 84, 69, 68, 128, 67, 79, 77, 80, - 76, 69, 77, 69, 78, 84, 128, 67, 79, 77, 80, 65, 83, 83, 128, 67, 79, 77, - 80, 65, 82, 69, 128, 67, 79, 77, 77, 79, 206, 67, 79, 77, 77, 69, 82, 67, - 73, 65, 204, 67, 79, 77, 77, 65, 78, 68, 128, 67, 79, 77, 77, 65, 128, - 67, 79, 77, 77, 193, 67, 79, 77, 69, 84, 128, 67, 79, 77, 66, 73, 78, 69, - 68, 128, 67, 79, 77, 66, 73, 78, 65, 84, 73, 79, 78, 128, 67, 79, 77, 66, - 128, 67, 79, 76, 85, 77, 78, 128, 67, 79, 76, 79, 82, 128, 67, 79, 76, - 76, 73, 83, 73, 79, 206, 67, 79, 76, 76, 128, 67, 79, 76, 196, 67, 79, - 73, 78, 128, 67, 79, 70, 70, 73, 78, 128, 67, 79, 69, 78, 71, 128, 67, - 79, 69, 78, 199, 67, 79, 68, 65, 128, 67, 79, 67, 79, 78, 85, 84, 128, - 67, 79, 67, 75, 84, 65, 73, 204, 67, 79, 67, 75, 82, 79, 65, 67, 72, 128, - 67, 79, 65, 84, 128, 67, 79, 65, 83, 84, 69, 82, 128, 67, 79, 65, 128, - 67, 77, 51, 48, 50, 128, 67, 77, 51, 48, 49, 128, 67, 77, 49, 49, 52, - 128, 67, 77, 49, 49, 50, 128, 67, 77, 49, 49, 48, 128, 67, 77, 49, 48, - 57, 128, 67, 77, 49, 48, 56, 128, 67, 77, 49, 48, 55, 128, 67, 77, 49, - 48, 53, 128, 67, 77, 49, 48, 52, 128, 67, 77, 49, 48, 51, 128, 67, 77, - 49, 48, 50, 128, 67, 77, 49, 48, 49, 128, 67, 77, 49, 48, 48, 128, 67, - 77, 48, 57, 57, 128, 67, 77, 48, 57, 56, 128, 67, 77, 48, 57, 55, 128, - 67, 77, 48, 57, 54, 128, 67, 77, 48, 57, 53, 128, 67, 77, 48, 57, 52, - 128, 67, 77, 48, 57, 50, 128, 67, 77, 48, 57, 49, 128, 67, 77, 48, 57, - 48, 128, 67, 77, 48, 56, 57, 128, 67, 77, 48, 56, 56, 128, 67, 77, 48, - 56, 55, 128, 67, 77, 48, 56, 54, 128, 67, 77, 48, 56, 53, 128, 67, 77, - 48, 56, 52, 128, 67, 77, 48, 56, 51, 128, 67, 77, 48, 56, 50, 128, 67, - 77, 48, 56, 49, 128, 67, 77, 48, 56, 48, 128, 67, 77, 48, 55, 57, 128, - 67, 77, 48, 55, 56, 128, 67, 77, 48, 55, 54, 128, 67, 77, 48, 55, 53, 66, - 128, 67, 77, 48, 55, 53, 128, 67, 77, 48, 55, 52, 128, 67, 77, 48, 55, - 51, 128, 67, 77, 48, 55, 50, 128, 67, 77, 48, 55, 49, 128, 67, 77, 48, - 55, 48, 128, 67, 77, 48, 54, 57, 128, 67, 77, 48, 54, 56, 128, 67, 77, - 48, 54, 55, 128, 67, 77, 48, 54, 54, 128, 67, 77, 48, 54, 52, 128, 67, - 77, 48, 54, 51, 128, 67, 77, 48, 54, 50, 128, 67, 77, 48, 54, 49, 128, - 67, 77, 48, 54, 48, 128, 67, 77, 48, 53, 57, 128, 67, 77, 48, 53, 56, - 128, 67, 77, 48, 53, 54, 128, 67, 77, 48, 53, 53, 128, 67, 77, 48, 53, - 52, 128, 67, 77, 48, 53, 51, 128, 67, 77, 48, 53, 50, 128, 67, 77, 48, - 53, 49, 128, 67, 77, 48, 53, 48, 128, 67, 77, 48, 52, 57, 128, 67, 77, - 48, 52, 55, 128, 67, 77, 48, 52, 54, 128, 67, 77, 48, 52, 52, 128, 67, - 77, 48, 52, 49, 128, 67, 77, 48, 52, 48, 128, 67, 77, 48, 51, 57, 128, - 67, 77, 48, 51, 56, 128, 67, 77, 48, 51, 55, 128, 67, 77, 48, 51, 54, - 128, 67, 77, 48, 51, 53, 128, 67, 77, 48, 51, 52, 128, 67, 77, 48, 51, - 51, 128, 67, 77, 48, 51, 48, 128, 67, 77, 48, 50, 57, 128, 67, 77, 48, - 50, 56, 128, 67, 77, 48, 50, 55, 128, 67, 77, 48, 50, 54, 128, 67, 77, - 48, 50, 53, 128, 67, 77, 48, 50, 52, 128, 67, 77, 48, 50, 51, 128, 67, - 77, 48, 50, 49, 128, 67, 77, 48, 49, 57, 128, 67, 77, 48, 49, 55, 128, - 67, 77, 48, 49, 53, 128, 67, 77, 48, 49, 51, 128, 67, 77, 48, 49, 50, 66, - 128, 67, 77, 48, 49, 50, 128, 67, 77, 48, 49, 49, 128, 67, 77, 48, 49, - 48, 128, 67, 77, 48, 48, 57, 128, 67, 77, 48, 48, 56, 128, 67, 77, 48, - 48, 55, 128, 67, 77, 48, 48, 54, 128, 67, 77, 48, 48, 53, 128, 67, 77, - 48, 48, 52, 128, 67, 77, 48, 48, 50, 128, 67, 77, 48, 48, 49, 128, 67, - 77, 128, 67, 205, 67, 76, 85, 83, 84, 69, 82, 45, 73, 78, 73, 84, 73, 65, - 204, 67, 76, 85, 83, 84, 69, 82, 45, 70, 73, 78, 65, 204, 67, 76, 85, 83, - 84, 69, 210, 67, 76, 85, 66, 83, 128, 67, 76, 85, 66, 45, 83, 80, 79, 75, - 69, 196, 67, 76, 85, 66, 128, 67, 76, 85, 194, 67, 76, 79, 87, 206, 67, - 76, 79, 86, 69, 82, 128, 67, 76, 79, 85, 68, 128, 67, 76, 79, 85, 196, - 67, 76, 79, 84, 72, 69, 83, 128, 67, 76, 79, 84, 72, 128, 67, 76, 79, 83, - 69, 84, 128, 67, 76, 79, 83, 69, 78, 69, 83, 83, 128, 67, 76, 79, 83, 69, - 68, 128, 67, 76, 79, 83, 197, 67, 76, 79, 67, 75, 87, 73, 83, 197, 67, - 76, 79, 67, 203, 67, 76, 73, 86, 73, 83, 128, 67, 76, 73, 80, 66, 79, 65, - 82, 68, 128, 67, 76, 73, 78, 75, 73, 78, 199, 67, 76, 73, 78, 71, 73, 78, - 199, 67, 76, 73, 77, 66, 73, 78, 71, 128, 67, 76, 73, 77, 65, 67, 85, 83, - 128, 67, 76, 73, 70, 70, 128, 67, 76, 73, 67, 75, 128, 67, 76, 73, 67, - 203, 67, 76, 69, 70, 45, 50, 128, 67, 76, 69, 70, 45, 49, 128, 67, 76, - 69, 70, 128, 67, 76, 69, 198, 67, 76, 69, 65, 86, 69, 82, 128, 67, 76, - 69, 65, 210, 67, 76, 65, 83, 83, 73, 67, 65, 204, 67, 76, 65, 80, 80, 73, - 78, 199, 67, 76, 65, 80, 80, 69, 210, 67, 76, 65, 78, 128, 67, 76, 65, - 206, 67, 76, 65, 77, 83, 72, 69, 76, 204, 67, 76, 65, 73, 77, 128, 67, - 76, 128, 67, 73, 88, 128, 67, 73, 86, 73, 76, 73, 65, 78, 128, 67, 73, - 84, 89, 83, 67, 65, 80, 69, 128, 67, 73, 84, 89, 83, 67, 65, 80, 197, 67, - 73, 84, 201, 67, 73, 84, 65, 84, 73, 79, 206, 67, 73, 84, 128, 67, 73, - 82, 67, 85, 211, 67, 73, 82, 67, 85, 77, 70, 76, 69, 88, 128, 67, 73, 82, - 67, 85, 77, 70, 76, 69, 216, 67, 73, 82, 67, 85, 76, 65, 84, 73, 79, 206, - 67, 73, 82, 67, 76, 73, 78, 71, 128, 67, 73, 82, 67, 76, 73, 78, 199, 67, - 73, 82, 67, 76, 69, 83, 128, 67, 73, 82, 67, 76, 69, 211, 67, 73, 82, 67, - 76, 69, 68, 128, 67, 73, 80, 128, 67, 73, 78, 78, 65, 66, 65, 82, 128, - 67, 73, 78, 69, 77, 65, 128, 67, 73, 206, 67, 73, 77, 128, 67, 73, 205, - 67, 73, 73, 128, 67, 73, 69, 88, 128, 67, 73, 69, 85, 67, 45, 83, 83, 65, - 78, 71, 80, 73, 69, 85, 80, 128, 67, 73, 69, 85, 67, 45, 80, 73, 69, 85, - 80, 128, 67, 73, 69, 85, 67, 45, 73, 69, 85, 78, 71, 128, 67, 73, 69, 85, - 195, 67, 73, 69, 84, 128, 67, 73, 69, 80, 128, 67, 73, 69, 128, 67, 72, - 89, 88, 128, 67, 72, 89, 84, 128, 67, 72, 89, 82, 88, 128, 67, 72, 89, - 82, 128, 67, 72, 89, 80, 128, 67, 72, 87, 86, 128, 67, 72, 85, 88, 128, - 67, 72, 85, 82, 88, 128, 67, 72, 85, 82, 67, 72, 128, 67, 72, 85, 82, - 128, 67, 72, 85, 80, 128, 67, 72, 85, 79, 88, 128, 67, 72, 85, 79, 84, - 128, 67, 72, 85, 79, 80, 128, 67, 72, 85, 79, 128, 67, 72, 85, 76, 65, - 128, 67, 72, 85, 128, 67, 72, 82, 89, 83, 65, 78, 84, 72, 69, 77, 85, 77, - 128, 67, 72, 82, 79, 78, 79, 85, 128, 67, 72, 82, 79, 78, 79, 78, 128, - 67, 72, 82, 79, 77, 193, 67, 72, 82, 79, 193, 67, 72, 82, 73, 86, 73, - 128, 67, 72, 82, 73, 83, 84, 77, 65, 83, 128, 67, 72, 82, 73, 83, 84, 77, - 65, 211, 67, 72, 79, 89, 128, 67, 72, 79, 88, 128, 67, 72, 79, 84, 128, - 67, 72, 79, 82, 69, 86, 77, 193, 67, 72, 79, 82, 65, 83, 77, 73, 65, 206, - 67, 72, 79, 80, 83, 84, 73, 67, 75, 83, 128, 67, 72, 79, 80, 128, 67, 72, - 79, 75, 69, 128, 67, 72, 79, 69, 128, 67, 72, 79, 67, 79, 76, 65, 84, - 197, 67, 72, 79, 65, 128, 67, 72, 73, 84, 85, 69, 85, 77, 83, 83, 65, 78, - 71, 83, 73, 79, 83, 128, 67, 72, 73, 84, 85, 69, 85, 77, 83, 83, 65, 78, - 71, 67, 73, 69, 85, 67, 128, 67, 72, 73, 84, 85, 69, 85, 77, 83, 73, 79, - 83, 128, 67, 72, 73, 84, 85, 69, 85, 77, 67, 73, 69, 85, 67, 128, 67, 72, - 73, 84, 85, 69, 85, 77, 67, 72, 73, 69, 85, 67, 72, 128, 67, 72, 73, 82, - 79, 78, 128, 67, 72, 73, 82, 69, 84, 128, 67, 72, 73, 80, 77, 85, 78, 75, - 128, 67, 72, 73, 78, 79, 79, 203, 67, 72, 73, 78, 71, 128, 67, 72, 73, - 78, 69, 83, 197, 67, 72, 73, 78, 128, 67, 72, 73, 77, 69, 128, 67, 72, - 73, 77, 128, 67, 72, 73, 76, 76, 213, 67, 72, 73, 76, 68, 82, 69, 206, - 67, 72, 73, 76, 68, 128, 67, 72, 73, 76, 128, 67, 72, 73, 75, 201, 67, - 72, 73, 69, 85, 67, 72, 45, 75, 72, 73, 69, 85, 75, 72, 128, 67, 72, 73, - 69, 85, 67, 72, 45, 72, 73, 69, 85, 72, 128, 67, 72, 73, 69, 85, 67, 200, - 67, 72, 73, 67, 75, 69, 78, 128, 67, 72, 73, 67, 75, 128, 67, 72, 73, - 128, 67, 72, 201, 67, 72, 72, 73, 77, 128, 67, 72, 72, 65, 128, 67, 72, - 69, 88, 128, 67, 72, 69, 86, 82, 79, 78, 128, 67, 72, 69, 86, 82, 79, - 206, 67, 72, 69, 84, 128, 67, 72, 69, 83, 84, 78, 85, 84, 128, 67, 72, - 69, 83, 84, 128, 67, 72, 69, 83, 211, 67, 72, 69, 82, 89, 128, 67, 72, - 69, 82, 82, 217, 67, 72, 69, 82, 82, 73, 69, 83, 128, 67, 72, 69, 81, 85, - 69, 82, 69, 196, 67, 72, 69, 80, 128, 67, 72, 69, 76, 89, 85, 83, 84, 75, - 65, 128, 67, 72, 69, 76, 78, 85, 128, 67, 72, 69, 73, 78, 65, 80, 128, - 67, 72, 69, 73, 75, 72, 69, 73, 128, 67, 72, 69, 73, 75, 72, 65, 78, 128, - 67, 72, 69, 69, 83, 197, 67, 72, 69, 69, 82, 73, 78, 199, 67, 72, 69, 69, - 77, 128, 67, 72, 69, 69, 75, 211, 67, 72, 69, 69, 75, 128, 67, 72, 69, - 69, 128, 67, 72, 69, 67, 75, 69, 210, 67, 72, 69, 67, 75, 128, 67, 72, - 69, 67, 203, 67, 72, 197, 67, 72, 65, 88, 128, 67, 72, 65, 86, 73, 89, - 65, 78, 73, 128, 67, 72, 65, 84, 84, 65, 87, 65, 128, 67, 72, 65, 84, - 128, 67, 72, 65, 83, 72, 75, 65, 128, 67, 72, 65, 83, 72, 75, 193, 67, - 72, 65, 82, 84, 128, 67, 72, 65, 82, 212, 67, 72, 65, 82, 73, 79, 84, - 128, 67, 72, 65, 82, 73, 79, 212, 67, 72, 65, 82, 65, 67, 84, 69, 82, 83, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 70, 66, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 70, 65, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 70, 57, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 66, 50, 70, 56, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 66, 50, 70, 55, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 66, 50, 70, 54, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 66, 50, 70, 53, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, - 70, 52, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 70, 51, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 70, 50, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 70, 49, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 70, 48, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 66, 50, 69, 70, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 66, 50, 69, 69, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 66, 50, 69, 68, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 66, 50, 69, 67, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, - 69, 66, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 69, 65, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 69, 57, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 69, 56, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 69, 55, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 66, 50, 69, 54, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 66, 50, 69, 53, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 66, 50, 69, 52, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 66, 50, 69, 51, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, - 69, 50, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 69, 49, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 69, 48, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 68, 70, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 68, 69, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 66, 50, 68, 68, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 66, 50, 68, 67, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 66, 50, 68, 66, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 66, 50, 68, 65, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, - 68, 57, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 68, 56, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 68, 55, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 68, 54, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 68, 53, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 66, 50, 68, 52, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 66, 50, 68, 51, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 66, 50, 68, 50, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 66, 50, 68, 49, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, - 68, 48, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 67, 70, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 67, 69, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 67, 68, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 67, 67, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 66, 50, 67, 66, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 66, 50, 67, 65, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 66, 50, 67, 57, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 66, 50, 67, 56, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, - 67, 55, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 67, 54, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 67, 53, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 67, 52, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 67, 51, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 66, 50, 67, 50, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 66, 50, 67, 49, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 66, 50, 67, 48, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 66, 50, 66, 70, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, - 66, 69, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 66, 68, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 66, 67, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 66, 66, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 66, 65, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 66, 50, 66, 57, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 66, 50, 66, 56, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 66, 50, 66, 55, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 66, 50, 66, 54, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, - 66, 53, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 66, 52, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 66, 51, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 66, 50, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 66, 49, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 66, 50, 66, 48, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 66, 50, 65, 70, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 66, 50, 65, 69, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 66, 50, 65, 68, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, - 65, 67, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 65, 66, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 65, 65, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 65, 57, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 65, 56, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 66, 50, 65, 55, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 66, 50, 65, 54, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 66, 50, 65, 53, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 66, 50, 65, 52, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, - 65, 51, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 65, 50, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 65, 49, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 65, 48, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 57, 70, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 66, 50, 57, 69, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 66, 50, 57, 68, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 66, 50, 57, 67, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 66, 50, 57, 66, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, - 57, 65, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 57, 57, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 57, 56, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 57, 55, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 57, 54, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 66, 50, 57, 53, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 66, 50, 57, 52, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 66, 50, 57, 51, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 66, 50, 57, 50, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, - 57, 49, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 57, 48, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 56, 70, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 56, 69, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 56, 68, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 66, 50, 56, 67, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 66, 50, 56, 66, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 66, 50, 56, 65, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 66, 50, 56, 57, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, - 56, 56, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 56, 55, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 56, 54, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 56, 53, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 56, 52, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 66, 50, 56, 51, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 66, 50, 56, 50, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 66, 50, 56, 49, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 66, 50, 56, 48, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, - 55, 70, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 55, 69, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 55, 68, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 55, 67, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 55, 66, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 66, 50, 55, 65, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 66, 50, 55, 57, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 66, 50, 55, 56, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 66, 50, 55, 55, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, - 55, 54, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 55, 53, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 55, 52, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 55, 51, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 55, 50, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 66, 50, 55, 49, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 66, 50, 55, 48, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 66, 50, 54, 70, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 66, 50, 54, 69, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, - 54, 68, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 54, 67, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 54, 66, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 54, 65, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 54, 57, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 66, 50, 54, 56, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 66, 50, 54, 55, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 66, 50, 54, 54, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 66, 50, 54, 53, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, - 54, 52, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 54, 51, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 54, 50, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 54, 49, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 54, 48, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 66, 50, 53, 70, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 66, 50, 53, 69, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 66, 50, 53, 68, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 66, 50, 53, 67, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, - 53, 66, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 53, 65, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 53, 57, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 53, 56, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 53, 55, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 66, 50, 53, 54, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 66, 50, 53, 53, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 66, 50, 53, 52, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 66, 50, 53, 51, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, - 53, 50, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 53, 49, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 53, 48, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 52, 70, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 52, 69, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 66, 50, 52, 68, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 66, 50, 52, 67, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 66, 50, 52, 66, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 66, 50, 52, 65, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, - 52, 57, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 52, 56, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 52, 55, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 52, 54, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 52, 53, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 66, 50, 52, 52, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 66, 50, 52, 51, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 66, 50, 52, 50, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 66, 50, 52, 49, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, - 52, 48, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 51, 70, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 51, 69, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 51, 68, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 51, 67, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 66, 50, 51, 66, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 66, 50, 51, 65, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 66, 50, 51, 57, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 66, 50, 51, 56, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, - 51, 55, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 51, 54, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 51, 53, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 51, 52, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 51, 51, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 66, 50, 51, 50, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 66, 50, 51, 49, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 66, 50, 51, 48, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 66, 50, 50, 70, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, - 50, 69, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 50, 68, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 50, 67, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 50, 66, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 50, 65, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 66, 50, 50, 57, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 66, 50, 50, 56, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 66, 50, 50, 55, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 66, 50, 50, 54, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, - 50, 53, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 50, 52, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 50, 51, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 50, 50, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 50, 49, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 66, 50, 50, 48, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 66, 50, 49, 70, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 66, 50, 49, 69, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 66, 50, 49, 68, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, - 49, 67, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 49, 66, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 49, 65, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 49, 57, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 49, 56, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 66, 50, 49, 55, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 66, 50, 49, 54, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 66, 50, 49, 53, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 66, 50, 49, 52, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, - 49, 51, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 49, 50, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 49, 49, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 49, 48, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 48, 70, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 66, 50, 48, 69, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 66, 50, 48, 68, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 66, 50, 48, 67, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 66, 50, 48, 66, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, - 48, 65, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 48, 57, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 48, 56, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 48, 55, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 48, 54, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 66, 50, 48, 53, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 66, 50, 48, 52, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 66, 50, 48, 51, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 66, 50, 48, 50, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, - 48, 49, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 50, 48, 48, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 49, 70, 70, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 49, 70, 69, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 66, 49, 70, 68, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 66, 49, 70, 67, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 66, 49, 70, 66, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 66, 49, 70, 65, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 66, 49, 70, 57, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 49, - 70, 56, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 49, 70, 55, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 49, 70, 54, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 49, 70, 53, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 66, 49, 70, 52, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 66, 49, 70, 51, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 66, 49, 70, 50, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 66, 49, 70, 49, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 66, 49, 70, 48, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 49, - 69, 70, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 49, 69, 69, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 49, 69, 68, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 49, 69, 67, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 66, 49, 69, 66, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 66, 49, 69, 65, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 66, 49, 69, 57, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 66, 49, 69, 56, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 66, 49, 69, 55, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 49, - 69, 54, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 49, 69, 53, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 49, 69, 52, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 49, 69, 51, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 66, 49, 69, 50, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 66, 49, 69, 49, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 66, 49, 69, 48, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 66, 49, 68, 70, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 66, 49, 68, 69, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 49, - 68, 68, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 49, 68, 67, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 49, 68, 66, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 49, 68, 65, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 66, 49, 68, 57, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 66, 49, 68, 56, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 66, 49, 68, 55, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 66, 49, 68, 54, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 66, 49, 68, 53, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 49, - 68, 52, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 49, 68, 51, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 49, 68, 50, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 49, 68, 49, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 66, 49, 68, 48, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 66, 49, 67, 70, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 66, 49, 67, 69, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 66, 49, 67, 68, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 66, 49, 67, 67, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 49, - 67, 66, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 49, 67, 65, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 49, 67, 57, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 49, 67, 56, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 66, 49, 67, 55, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 66, 49, 67, 54, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 66, 49, 67, 53, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 66, 49, 67, 52, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 66, 49, 67, 51, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 49, - 67, 50, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 49, 67, 49, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 49, 67, 48, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 49, 66, 70, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 66, 49, 66, 69, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 66, 49, 66, 68, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 66, 49, 66, 67, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 66, 49, 66, 66, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 66, 49, 66, 65, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 49, - 66, 57, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 49, 66, 56, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 49, 66, 55, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 49, 66, 54, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 66, 49, 66, 53, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 66, 49, 66, 52, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 66, 49, 66, 51, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 66, 49, 66, 50, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 66, 49, 66, 49, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 49, - 66, 48, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 49, 65, 70, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 49, 65, 69, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 49, 65, 68, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 66, 49, 65, 67, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 66, 49, 65, 66, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 66, 49, 65, 65, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 66, 49, 65, 57, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 66, 49, 65, 56, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 49, - 65, 55, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 49, 65, 54, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 49, 65, 53, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 49, 65, 52, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 66, 49, 65, 51, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 66, 49, 65, 50, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 66, 49, 65, 49, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 66, 49, 65, 48, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 66, 49, 57, 70, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 49, - 57, 69, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 49, 57, 68, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 49, 57, 67, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 49, 57, 66, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 66, 49, 57, 65, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 66, 49, 57, 57, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 66, 49, 57, 56, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 66, 49, 57, 55, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 66, 49, 57, 54, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 49, - 57, 53, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 49, 57, 52, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 49, 57, 51, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 49, 57, 50, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 66, 49, 57, 49, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 66, 49, 57, 48, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 66, 49, 56, 70, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 66, 49, 56, 69, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 66, 49, 56, 68, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 49, - 56, 67, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 49, 56, 66, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 49, 56, 65, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 49, 56, 57, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 66, 49, 56, 56, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 66, 49, 56, 55, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 66, 49, 56, 54, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 66, 49, 56, 53, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 66, 49, 56, 52, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 49, - 56, 51, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 49, 56, 50, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 49, 56, 49, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 49, 56, 48, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 66, 49, 55, 70, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 66, 49, 55, 69, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 66, 49, 55, 68, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 66, 49, 55, 67, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 66, 49, 55, 66, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 49, - 55, 65, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 49, 55, 57, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 49, 55, 56, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 49, 55, 55, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 66, 49, 55, 54, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 66, 49, 55, 53, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 66, 49, 55, 52, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 66, 49, 55, 51, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 66, 49, 55, 50, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 49, - 55, 49, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, 49, 55, 48, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 68, 53, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 68, 52, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 68, 51, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 56, 67, 68, 50, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 56, 67, 68, 49, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 56, 67, 68, 48, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 56, 67, 67, 70, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, - 67, 69, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 67, 68, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 67, 67, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 67, 66, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 67, 65, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 56, 67, 67, 57, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 56, 67, 67, 56, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 56, 67, 67, 55, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 56, 67, 67, 54, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, - 67, 53, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 67, 52, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 67, 51, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 67, 50, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 67, 49, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 56, 67, 67, 48, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 56, 67, 66, 70, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 56, 67, 66, 69, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 56, 67, 66, 68, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, - 66, 67, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 66, 66, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 66, 65, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 66, 57, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 66, 56, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 56, 67, 66, 55, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 56, 67, 66, 54, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 56, 67, 66, 53, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 56, 67, 66, 52, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, - 66, 51, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 66, 50, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 66, 49, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 66, 48, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 65, 70, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 56, 67, 65, 69, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 56, 67, 65, 68, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 56, 67, 65, 67, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 56, 67, 65, 66, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, - 65, 65, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 65, 57, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 65, 56, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 65, 55, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 65, 54, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 56, 67, 65, 53, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 56, 67, 65, 52, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 56, 67, 65, 51, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 56, 67, 65, 50, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, - 65, 49, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 65, 48, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 57, 70, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 57, 69, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 57, 68, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 56, 67, 57, 67, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 56, 67, 57, 66, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 56, 67, 57, 65, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 56, 67, 57, 57, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, - 57, 56, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 57, 55, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 57, 54, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 57, 53, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 57, 52, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 56, 67, 57, 51, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 56, 67, 57, 50, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 56, 67, 57, 49, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 56, 67, 57, 48, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, - 56, 70, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 56, 69, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 56, 68, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 56, 67, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 56, 66, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 56, 67, 56, 65, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 56, 67, 56, 57, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 56, 67, 56, 56, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 56, 67, 56, 55, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, - 56, 54, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 56, 53, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 56, 52, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 56, 51, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 56, 50, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 56, 67, 56, 49, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 56, 67, 56, 48, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 56, 67, 55, 70, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 56, 67, 55, 69, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, - 55, 68, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 55, 67, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 55, 66, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 55, 65, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 55, 57, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 56, 67, 55, 56, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 56, 67, 55, 55, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 56, 67, 55, 54, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 56, 67, 55, 53, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, - 55, 52, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 55, 51, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 55, 50, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 55, 49, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 55, 48, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 56, 67, 54, 70, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 56, 67, 54, 69, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 56, 67, 54, 68, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 56, 67, 54, 67, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, - 54, 66, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 54, 65, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 54, 57, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 54, 56, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 54, 55, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 56, 67, 54, 54, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 56, 67, 54, 53, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 56, 67, 54, 52, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 56, 67, 54, 51, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, - 54, 50, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 54, 49, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 54, 48, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 53, 70, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 53, 69, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 56, 67, 53, 68, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 56, 67, 53, 67, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 56, 67, 53, 66, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 56, 67, 53, 65, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, - 53, 57, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 53, 56, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 53, 55, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 53, 54, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 53, 53, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 56, 67, 53, 52, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 56, 67, 53, 51, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 56, 67, 53, 50, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 56, 67, 53, 49, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, - 53, 48, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 52, 70, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 52, 69, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 52, 68, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 52, 67, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 56, 67, 52, 66, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 56, 67, 52, 65, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 56, 67, 52, 57, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 56, 67, 52, 56, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, - 52, 55, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 52, 54, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 52, 53, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 52, 52, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 52, 51, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 56, 67, 52, 50, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 56, 67, 52, 49, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 56, 67, 52, 48, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 56, 67, 51, 70, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, - 51, 69, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 51, 68, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 51, 67, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 51, 66, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 51, 65, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 56, 67, 51, 57, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 56, 67, 51, 56, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 56, 67, 51, 55, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 56, 67, 51, 54, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, - 51, 53, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 51, 52, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 51, 51, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 51, 50, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 51, 49, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 56, 67, 51, 48, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 56, 67, 50, 70, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 56, 67, 50, 69, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 56, 67, 50, 68, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, - 50, 67, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 50, 66, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 50, 65, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 50, 57, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 50, 56, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 56, 67, 50, 55, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 56, 67, 50, 54, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 56, 67, 50, 53, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 56, 67, 50, 52, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, - 50, 51, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 50, 50, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 50, 49, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 50, 48, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 49, 70, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 56, 67, 49, 69, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 56, 67, 49, 68, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 56, 67, 49, 67, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 56, 67, 49, 66, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, - 49, 65, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 49, 57, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 49, 56, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 49, 55, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 49, 54, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 56, 67, 49, 53, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 56, 67, 49, 52, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 56, 67, 49, 51, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 56, 67, 49, 50, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, - 49, 49, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 49, 48, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 48, 70, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 48, 69, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 48, 68, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 56, 67, 48, 67, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 56, 67, 48, 66, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 56, 67, 48, 65, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 56, 67, 48, 57, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, - 48, 56, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 48, 55, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 48, 54, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 48, 53, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 56, 67, 48, 52, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 56, 67, 48, 51, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 56, 67, 48, 50, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 56, 67, 48, 49, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 56, 67, 48, 48, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, - 70, 70, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 70, 69, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 70, 68, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 70, 67, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 70, 66, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 56, 66, 70, 65, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 56, 66, 70, 57, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 56, 66, 70, 56, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 56, 66, 70, 55, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, - 70, 54, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 70, 53, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 70, 52, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 70, 51, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 70, 50, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 56, 66, 70, 49, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 56, 66, 70, 48, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 56, 66, 69, 70, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 56, 66, 69, 69, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, - 69, 68, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 69, 67, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 69, 66, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 69, 65, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 69, 57, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 56, 66, 69, 56, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 56, 66, 69, 55, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 56, 66, 69, 54, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 56, 66, 69, 53, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, - 69, 52, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 69, 51, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 69, 50, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 69, 49, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 69, 48, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 56, 66, 68, 70, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 56, 66, 68, 69, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 56, 66, 68, 68, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 56, 66, 68, 67, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, - 68, 66, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 68, 65, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 68, 57, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 68, 56, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 68, 55, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 56, 66, 68, 54, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 56, 66, 68, 53, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 56, 66, 68, 52, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 56, 66, 68, 51, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, - 68, 50, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 68, 49, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 68, 48, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 67, 70, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 67, 69, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 56, 66, 67, 68, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 56, 66, 67, 67, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 56, 66, 67, 66, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 56, 66, 67, 65, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, - 67, 57, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 67, 56, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 67, 55, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 67, 54, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 67, 53, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 56, 66, 67, 52, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 56, 66, 67, 51, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 56, 66, 67, 50, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 56, 66, 67, 49, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, - 67, 48, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 66, 70, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 66, 69, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 66, 68, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 66, 67, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 56, 66, 66, 66, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 56, 66, 66, 65, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 56, 66, 66, 57, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 56, 66, 66, 56, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, - 66, 55, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 66, 54, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 66, 53, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 66, 52, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 66, 51, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 56, 66, 66, 50, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 56, 66, 66, 49, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 56, 66, 66, 48, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 56, 66, 65, 70, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, - 65, 69, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 65, 68, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 65, 67, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 65, 66, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 65, 65, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 56, 66, 65, 57, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 56, 66, 65, 56, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 56, 66, 65, 55, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 56, 66, 65, 54, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, - 65, 53, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 65, 52, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 65, 51, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 65, 50, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 65, 49, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 56, 66, 65, 48, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 56, 66, 57, 70, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 56, 66, 57, 69, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 56, 66, 57, 68, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, - 57, 67, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 57, 66, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 57, 65, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 57, 57, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 57, 56, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 56, 66, 57, 55, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 56, 66, 57, 54, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 56, 66, 57, 53, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 56, 66, 57, 52, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, - 57, 51, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 57, 50, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 57, 49, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 57, 48, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 56, 70, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 56, 66, 56, 69, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 56, 66, 56, 68, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 56, 66, 56, 67, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 56, 66, 56, 66, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, - 56, 65, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 56, 57, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 56, 56, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 56, 55, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 56, 54, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 56, 66, 56, 53, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 56, 66, 56, 52, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 56, 66, 56, 51, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 56, 66, 56, 50, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, - 56, 49, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 56, 48, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 55, 70, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 55, 69, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 55, 68, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 56, 66, 55, 67, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 56, 66, 55, 66, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 56, 66, 55, 65, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 56, 66, 55, 57, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, - 55, 56, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 55, 55, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 55, 54, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 55, 53, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 55, 52, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 56, 66, 55, 51, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 56, 66, 55, 50, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 56, 66, 55, 49, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 56, 66, 55, 48, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, - 54, 70, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 54, 69, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 54, 68, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 54, 67, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 54, 66, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 56, 66, 54, 65, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 56, 66, 54, 57, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 56, 66, 54, 56, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 56, 66, 54, 55, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, - 54, 54, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 54, 53, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 54, 52, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 54, 51, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 54, 50, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 56, 66, 54, 49, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 56, 66, 54, 48, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 56, 66, 53, 70, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 56, 66, 53, 69, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, - 53, 68, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 53, 67, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 53, 66, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 53, 65, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 53, 57, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 56, 66, 53, 56, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 56, 66, 53, 55, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 56, 66, 53, 54, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 56, 66, 53, 53, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, - 53, 52, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 53, 51, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 53, 50, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 53, 49, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 53, 48, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 56, 66, 52, 70, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 56, 66, 52, 69, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 56, 66, 52, 68, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 56, 66, 52, 67, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, - 52, 66, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 52, 65, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 52, 57, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 52, 56, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 52, 55, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 56, 66, 52, 54, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 56, 66, 52, 53, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 56, 66, 52, 52, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 56, 66, 52, 51, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, - 52, 50, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 52, 49, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 52, 48, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 51, 70, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 51, 69, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 56, 66, 51, 68, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 56, 66, 51, 67, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 56, 66, 51, 66, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 56, 66, 51, 65, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, - 51, 57, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 51, 56, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 51, 55, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 51, 54, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 51, 53, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 56, 66, 51, 52, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 56, 66, 51, 51, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 56, 66, 51, 50, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 56, 66, 51, 49, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, - 51, 48, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 50, 70, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 50, 69, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 50, 68, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 50, 67, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 56, 66, 50, 66, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 56, 66, 50, 65, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 56, 66, 50, 57, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 56, 66, 50, 56, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, - 50, 55, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 50, 54, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 50, 53, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 50, 52, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 50, 51, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 56, 66, 50, 50, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 56, 66, 50, 49, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 56, 66, 50, 48, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 56, 66, 49, 70, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, - 49, 69, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 49, 68, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 49, 67, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 49, 66, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 49, 65, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 56, 66, 49, 57, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 56, 66, 49, 56, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 56, 66, 49, 55, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 56, 66, 49, 54, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, - 49, 53, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 49, 52, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 49, 51, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 49, 50, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 49, 49, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 56, 66, 49, 48, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 56, 66, 48, 70, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 56, 66, 48, 69, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 56, 66, 48, 68, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, - 48, 67, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 48, 66, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 48, 65, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 48, 57, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 48, 56, 128, 67, 72, 65, 82, 65, - 67, 84, 69, 82, 45, 49, 56, 66, 48, 55, 128, 67, 72, 65, 82, 65, 67, 84, - 69, 82, 45, 49, 56, 66, 48, 54, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, - 45, 49, 56, 66, 48, 53, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, - 56, 66, 48, 52, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, - 48, 51, 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 48, 50, - 128, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 48, 49, 128, 67, - 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 66, 48, 48, 128, 67, 72, 65, - 82, 65, 67, 84, 69, 82, 128, 67, 72, 65, 82, 65, 67, 84, 69, 210, 67, 72, - 65, 82, 128, 67, 72, 65, 80, 84, 69, 82, 128, 67, 72, 65, 80, 128, 67, - 72, 65, 78, 71, 128, 67, 72, 65, 78, 128, 67, 72, 65, 77, 75, 79, 128, - 67, 72, 65, 77, 73, 76, 79, 78, 128, 67, 72, 65, 77, 73, 76, 73, 128, 67, - 72, 65, 205, 67, 72, 65, 75, 77, 193, 67, 72, 65, 73, 78, 83, 128, 67, - 72, 65, 68, 65, 128, 67, 72, 65, 196, 67, 72, 65, 65, 128, 67, 71, 74, - 128, 67, 69, 88, 128, 67, 69, 86, 73, 84, 85, 128, 67, 69, 82, 69, 83, - 128, 67, 69, 82, 69, 77, 79, 78, 89, 128, 67, 69, 82, 69, 75, 128, 67, - 69, 82, 45, 87, 65, 128, 67, 69, 80, 128, 67, 69, 79, 78, 71, 67, 72, 73, - 69, 85, 77, 83, 83, 65, 78, 71, 83, 73, 79, 83, 128, 67, 69, 79, 78, 71, - 67, 72, 73, 69, 85, 77, 83, 83, 65, 78, 71, 67, 73, 69, 85, 67, 128, 67, - 69, 79, 78, 71, 67, 72, 73, 69, 85, 77, 83, 73, 79, 83, 128, 67, 69, 79, - 78, 71, 67, 72, 73, 69, 85, 77, 67, 73, 69, 85, 67, 128, 67, 69, 79, 78, - 71, 67, 72, 73, 69, 85, 77, 67, 72, 73, 69, 85, 67, 72, 128, 67, 69, 78, - 84, 85, 82, 73, 65, 204, 67, 69, 78, 84, 82, 69, 76, 73, 78, 197, 67, 69, - 78, 84, 82, 69, 68, 128, 67, 69, 78, 84, 82, 69, 196, 67, 69, 78, 84, 82, - 69, 128, 67, 69, 78, 84, 82, 197, 67, 69, 78, 84, 82, 65, 76, 73, 90, 65, - 84, 73, 79, 206, 67, 69, 78, 128, 67, 69, 76, 84, 73, 195, 67, 69, 76, - 83, 73, 85, 83, 128, 67, 69, 76, 69, 66, 82, 65, 84, 73, 79, 78, 128, 67, - 69, 73, 82, 84, 128, 67, 69, 73, 76, 73, 78, 71, 128, 67, 69, 73, 76, 73, - 78, 199, 67, 69, 69, 86, 128, 67, 69, 69, 66, 128, 67, 69, 69, 128, 67, - 69, 68, 73, 76, 76, 65, 128, 67, 69, 68, 73, 76, 76, 193, 67, 69, 68, - 201, 67, 69, 67, 69, 75, 128, 67, 69, 67, 65, 75, 128, 67, 69, 67, 65, - 203, 67, 69, 65, 76, 67, 128, 67, 67, 85, 128, 67, 67, 79, 128, 67, 67, - 73, 128, 67, 67, 72, 85, 128, 67, 67, 72, 79, 128, 67, 67, 72, 73, 128, - 67, 67, 72, 72, 85, 128, 67, 67, 72, 72, 79, 128, 67, 67, 72, 72, 73, - 128, 67, 67, 72, 72, 69, 69, 128, 67, 67, 72, 72, 69, 128, 67, 67, 72, - 72, 65, 65, 128, 67, 67, 72, 72, 65, 128, 67, 67, 72, 69, 69, 128, 67, - 67, 72, 69, 128, 67, 67, 72, 65, 65, 128, 67, 67, 72, 65, 128, 67, 67, - 72, 128, 67, 67, 69, 69, 128, 67, 67, 65, 65, 128, 67, 65, 89, 78, 128, - 67, 65, 89, 65, 78, 78, 65, 128, 67, 65, 88, 128, 67, 65, 86, 69, 128, - 67, 65, 85, 84, 73, 79, 206, 67, 65, 85, 76, 68, 82, 79, 78, 128, 67, 65, - 85, 68, 65, 84, 197, 67, 65, 85, 68, 65, 128, 67, 65, 85, 67, 65, 83, 73, - 65, 206, 67, 65, 85, 128, 67, 65, 84, 65, 87, 65, 128, 67, 65, 84, 128, - 67, 65, 212, 67, 65, 83, 84, 76, 69, 128, 67, 65, 83, 75, 69, 212, 67, - 65, 82, 89, 83, 84, 73, 65, 206, 67, 65, 82, 84, 87, 72, 69, 69, 76, 128, - 67, 65, 82, 84, 82, 73, 68, 71, 69, 128, 67, 65, 82, 84, 128, 67, 65, 82, - 211, 67, 65, 82, 82, 79, 84, 128, 67, 65, 82, 82, 73, 65, 71, 197, 67, - 65, 82, 80, 69, 78, 84, 82, 217, 67, 65, 82, 208, 67, 65, 82, 79, 85, 83, - 69, 204, 67, 65, 82, 79, 78, 128, 67, 65, 82, 79, 206, 67, 65, 82, 73, - 203, 67, 65, 82, 73, 65, 206, 67, 65, 82, 69, 84, 128, 67, 65, 82, 69, - 212, 67, 65, 82, 197, 67, 65, 82, 68, 83, 128, 67, 65, 82, 196, 67, 65, - 82, 128, 67, 65, 210, 67, 65, 80, 85, 212, 67, 65, 80, 84, 73, 86, 69, - 128, 67, 65, 80, 82, 73, 67, 79, 82, 78, 128, 67, 65, 80, 80, 69, 196, - 67, 65, 80, 79, 128, 67, 65, 80, 73, 84, 85, 76, 85, 77, 128, 67, 65, 80, - 73, 84, 65, 76, 128, 67, 65, 78, 84, 73, 76, 76, 65, 84, 73, 79, 206, 67, - 65, 78, 79, 69, 128, 67, 65, 78, 78, 79, 78, 128, 67, 65, 78, 78, 69, - 196, 67, 65, 78, 199, 67, 65, 78, 69, 128, 67, 65, 78, 68, 89, 128, 67, - 65, 78, 68, 82, 65, 66, 73, 78, 68, 85, 128, 67, 65, 78, 68, 82, 65, 66, - 73, 78, 68, 213, 67, 65, 78, 68, 82, 65, 128, 67, 65, 78, 68, 82, 193, - 67, 65, 78, 68, 76, 69, 128, 67, 65, 78, 67, 69, 82, 128, 67, 65, 78, 67, - 69, 76, 76, 65, 84, 73, 79, 206, 67, 65, 78, 67, 69, 76, 128, 67, 65, 78, - 67, 69, 204, 67, 65, 78, 128, 67, 65, 77, 80, 73, 78, 71, 128, 67, 65, - 77, 78, 85, 195, 67, 65, 77, 69, 82, 65, 128, 67, 65, 77, 69, 82, 193, - 67, 65, 77, 69, 76, 128, 67, 65, 76, 89, 65, 128, 67, 65, 76, 89, 193, - 67, 65, 76, 88, 128, 67, 65, 76, 76, 128, 67, 65, 76, 204, 67, 65, 76, - 69, 78, 68, 65, 82, 128, 67, 65, 76, 69, 78, 68, 65, 210, 67, 65, 76, 67, - 85, 76, 65, 84, 79, 82, 128, 67, 65, 76, 67, 128, 67, 65, 75, 82, 65, - 128, 67, 65, 75, 197, 67, 65, 73, 128, 67, 65, 72, 128, 67, 65, 69, 83, - 85, 82, 65, 128, 67, 65, 68, 85, 67, 69, 85, 83, 128, 67, 65, 68, 193, - 67, 65, 67, 84, 85, 83, 128, 67, 65, 66, 76, 69, 87, 65, 89, 128, 67, 65, - 66, 73, 78, 69, 84, 128, 67, 65, 66, 66, 65, 71, 69, 45, 84, 82, 69, 69, - 128, 67, 65, 65, 78, 71, 128, 67, 65, 65, 73, 128, 67, 193, 67, 48, 50, - 52, 128, 67, 48, 50, 51, 128, 67, 48, 50, 50, 128, 67, 48, 50, 49, 128, - 67, 48, 50, 48, 128, 67, 48, 49, 57, 128, 67, 48, 49, 56, 128, 67, 48, - 49, 55, 128, 67, 48, 49, 54, 128, 67, 48, 49, 53, 128, 67, 48, 49, 52, - 128, 67, 48, 49, 51, 128, 67, 48, 49, 50, 128, 67, 48, 49, 49, 128, 67, - 48, 49, 48, 65, 128, 67, 48, 49, 48, 128, 67, 48, 48, 57, 128, 67, 48, - 48, 56, 128, 67, 48, 48, 55, 128, 67, 48, 48, 54, 128, 67, 48, 48, 53, - 128, 67, 48, 48, 52, 128, 67, 48, 48, 51, 128, 67, 48, 48, 50, 67, 128, - 67, 48, 48, 50, 66, 128, 67, 48, 48, 50, 65, 128, 67, 48, 48, 50, 128, - 67, 48, 48, 49, 128, 67, 45, 83, 73, 77, 80, 76, 73, 70, 73, 69, 196, 67, - 45, 51, 57, 128, 67, 45, 49, 56, 128, 66, 90, 85, 78, 199, 66, 90, 72, - 201, 66, 89, 84, 197, 66, 89, 69, 76, 79, 82, 85, 83, 83, 73, 65, 78, 45, - 85, 75, 82, 65, 73, 78, 73, 65, 206, 66, 88, 71, 128, 66, 87, 73, 128, - 66, 87, 69, 69, 128, 66, 87, 69, 128, 66, 87, 65, 128, 66, 85, 85, 77, - 73, 83, 72, 128, 66, 85, 84, 84, 79, 78, 128, 66, 85, 84, 84, 79, 206, - 66, 85, 84, 84, 69, 82, 70, 76, 89, 128, 66, 85, 84, 84, 69, 82, 128, 66, - 85, 212, 66, 85, 83, 84, 211, 66, 85, 83, 212, 66, 85, 83, 83, 89, 69, - 82, 85, 128, 66, 85, 83, 73, 78, 69, 83, 211, 66, 85, 211, 66, 85, 82, - 213, 66, 85, 82, 82, 73, 84, 79, 128, 66, 85, 82, 50, 128, 66, 85, 210, - 66, 85, 79, 89, 128, 66, 85, 79, 88, 128, 66, 85, 79, 80, 128, 66, 85, - 78, 78, 217, 66, 85, 78, 71, 128, 66, 85, 77, 80, 217, 66, 85, 76, 85, - 71, 128, 66, 85, 76, 85, 199, 66, 85, 76, 76, 83, 69, 89, 69, 128, 66, - 85, 76, 76, 211, 66, 85, 76, 76, 72, 79, 82, 78, 128, 66, 85, 76, 76, 72, - 79, 82, 206, 66, 85, 76, 76, 69, 84, 128, 66, 85, 76, 76, 69, 212, 66, - 85, 76, 76, 128, 66, 85, 76, 66, 128, 66, 85, 75, 89, 128, 66, 85, 73, - 76, 68, 73, 78, 71, 83, 128, 66, 85, 73, 76, 68, 73, 78, 71, 128, 66, 85, - 73, 76, 68, 73, 78, 199, 66, 85, 72, 73, 196, 66, 85, 71, 73, 78, 69, 83, - 197, 66, 85, 71, 128, 66, 85, 70, 70, 65, 76, 79, 128, 66, 85, 68, 128, - 66, 85, 67, 75, 76, 69, 128, 66, 85, 67, 75, 69, 84, 128, 66, 85, 66, 66, - 76, 69, 83, 128, 66, 85, 66, 66, 76, 69, 128, 66, 85, 66, 66, 76, 197, - 66, 83, 84, 65, 82, 128, 66, 83, 75, 85, 210, 66, 83, 75, 65, 173, 66, - 83, 68, 85, 211, 66, 82, 85, 83, 200, 66, 82, 79, 87, 206, 66, 82, 79, - 79, 77, 128, 66, 82, 79, 78, 90, 69, 128, 66, 82, 79, 75, 69, 206, 66, - 82, 79, 67, 67, 79, 76, 73, 128, 66, 82, 79, 65, 196, 66, 82, 73, 83, 84, - 76, 69, 128, 66, 82, 73, 71, 72, 84, 78, 69, 83, 211, 66, 82, 73, 69, 70, - 83, 128, 66, 82, 73, 69, 70, 67, 65, 83, 69, 128, 66, 82, 73, 68, 71, - 197, 66, 82, 73, 68, 197, 66, 82, 73, 67, 75, 128, 66, 82, 73, 128, 66, - 82, 69, 86, 73, 83, 128, 66, 82, 69, 86, 69, 45, 77, 65, 67, 82, 79, 78, - 128, 66, 82, 69, 86, 197, 66, 82, 69, 65, 84, 72, 217, 66, 82, 69, 65, - 84, 200, 66, 82, 69, 65, 83, 84, 45, 70, 69, 69, 68, 73, 78, 71, 128, 66, - 82, 69, 65, 75, 84, 72, 82, 79, 85, 71, 72, 128, 66, 82, 68, 193, 66, 82, - 65, 78, 67, 72, 73, 78, 199, 66, 82, 65, 78, 67, 72, 69, 83, 128, 66, 82, - 65, 78, 67, 72, 128, 66, 82, 65, 78, 67, 200, 66, 82, 65, 75, 67, 69, 84, - 128, 66, 82, 65, 73, 78, 128, 66, 82, 65, 67, 75, 69, 84, 211, 66, 82, - 65, 67, 75, 69, 84, 69, 196, 66, 82, 65, 67, 75, 69, 84, 128, 66, 82, 65, - 67, 75, 69, 212, 66, 82, 65, 67, 69, 128, 66, 81, 128, 66, 80, 72, 128, - 66, 79, 89, 211, 66, 79, 89, 128, 66, 79, 88, 73, 78, 199, 66, 79, 87, - 84, 73, 69, 128, 66, 79, 87, 84, 73, 197, 66, 79, 87, 76, 73, 78, 71, - 128, 66, 79, 87, 76, 128, 66, 79, 87, 204, 66, 79, 87, 73, 78, 199, 66, - 79, 215, 66, 79, 85, 81, 85, 69, 84, 128, 66, 79, 85, 81, 85, 69, 212, - 66, 79, 85, 78, 68, 65, 82, 217, 66, 79, 84, 84, 79, 77, 45, 83, 72, 65, - 68, 69, 196, 66, 79, 84, 84, 79, 77, 45, 76, 73, 71, 72, 84, 69, 196, 66, - 79, 84, 84, 79, 77, 128, 66, 79, 84, 84, 79, 205, 66, 79, 84, 84, 76, 69, - 128, 66, 79, 84, 84, 76, 197, 66, 79, 84, 200, 66, 79, 82, 90, 89, 128, - 66, 79, 82, 90, 65, 89, 65, 128, 66, 79, 82, 85, 84, 79, 128, 66, 79, 82, - 65, 88, 45, 51, 128, 66, 79, 82, 65, 88, 45, 50, 128, 66, 79, 82, 65, 88, - 128, 66, 79, 80, 79, 77, 79, 70, 207, 66, 79, 79, 84, 83, 128, 66, 79, - 79, 84, 128, 66, 79, 79, 77, 69, 82, 65, 78, 71, 128, 66, 79, 79, 75, 83, - 128, 66, 79, 79, 75, 77, 65, 82, 75, 128, 66, 79, 79, 75, 77, 65, 82, - 203, 66, 79, 78, 69, 128, 66, 79, 77, 66, 128, 66, 79, 77, 128, 66, 79, - 76, 84, 128, 66, 79, 76, 212, 66, 79, 72, 65, 73, 82, 73, 195, 66, 79, - 68, 89, 128, 66, 79, 68, 217, 66, 79, 65, 82, 128, 66, 79, 65, 128, 66, - 76, 85, 69, 66, 69, 82, 82, 73, 69, 83, 128, 66, 76, 85, 69, 128, 66, 76, - 85, 197, 66, 76, 79, 87, 73, 78, 199, 66, 76, 79, 87, 70, 73, 83, 72, - 128, 66, 76, 79, 215, 66, 76, 79, 83, 83, 79, 77, 128, 66, 76, 79, 79, - 68, 128, 66, 76, 79, 78, 196, 66, 76, 79, 67, 75, 45, 55, 128, 66, 76, - 79, 67, 75, 45, 54, 128, 66, 76, 79, 67, 75, 45, 53, 128, 66, 76, 79, 67, - 75, 45, 52, 128, 66, 76, 79, 67, 75, 45, 51, 128, 66, 76, 79, 67, 75, 45, - 50, 128, 66, 76, 79, 67, 75, 45, 49, 51, 53, 56, 128, 66, 76, 79, 67, 75, - 128, 66, 76, 73, 78, 203, 66, 76, 65, 78, 75, 128, 66, 76, 65, 78, 203, - 66, 76, 65, 68, 197, 66, 76, 65, 67, 75, 76, 69, 84, 84, 69, 210, 66, 76, - 65, 67, 75, 70, 79, 79, 212, 66, 76, 65, 67, 75, 45, 76, 69, 84, 84, 69, - 210, 66, 76, 65, 67, 75, 45, 70, 69, 65, 84, 72, 69, 82, 69, 196, 66, 76, - 65, 67, 75, 128, 66, 75, 65, 173, 66, 73, 84, 84, 69, 82, 128, 66, 73, - 84, 73, 78, 199, 66, 73, 84, 197, 66, 73, 84, 67, 79, 73, 206, 66, 73, - 83, 79, 78, 128, 66, 73, 83, 77, 85, 84, 200, 66, 73, 83, 77, 73, 76, 76, - 65, 200, 66, 73, 83, 72, 79, 208, 66, 73, 83, 69, 67, 84, 73, 78, 199, - 66, 73, 83, 65, 72, 128, 66, 73, 82, 85, 128, 66, 73, 82, 84, 72, 68, 65, - 217, 66, 73, 82, 71, 65, 128, 66, 73, 82, 71, 193, 66, 73, 82, 68, 128, - 66, 73, 79, 72, 65, 90, 65, 82, 196, 66, 73, 78, 79, 86, 73, 76, 69, 128, - 66, 73, 78, 79, 67, 85, 76, 65, 210, 66, 73, 78, 68, 73, 78, 199, 66, 73, - 78, 68, 73, 128, 66, 73, 78, 65, 82, 217, 66, 73, 76, 76, 73, 79, 78, 83, - 128, 66, 73, 76, 76, 73, 65, 82, 68, 83, 128, 66, 73, 76, 76, 69, 196, - 66, 73, 76, 65, 66, 73, 65, 204, 66, 73, 75, 73, 78, 73, 128, 66, 73, 71, - 128, 66, 73, 199, 66, 73, 69, 84, 128, 66, 73, 68, 69, 78, 84, 65, 204, - 66, 73, 68, 65, 75, 85, 79, 206, 66, 73, 67, 89, 67, 76, 73, 83, 84, 128, - 66, 73, 67, 89, 67, 76, 69, 83, 128, 66, 73, 67, 89, 67, 76, 69, 128, 66, - 73, 67, 69, 80, 83, 128, 66, 73, 66, 76, 69, 45, 67, 82, 69, 197, 66, 73, - 66, 128, 66, 201, 66, 72, 85, 128, 66, 72, 79, 79, 128, 66, 72, 79, 128, - 66, 72, 73, 128, 66, 72, 69, 84, 72, 128, 66, 72, 69, 69, 128, 66, 72, - 69, 128, 66, 72, 65, 84, 84, 73, 80, 82, 79, 76, 213, 66, 72, 65, 77, - 128, 66, 72, 65, 76, 69, 128, 66, 72, 65, 76, 197, 66, 72, 65, 73, 75, - 83, 85, 75, 201, 66, 72, 65, 65, 128, 66, 72, 65, 128, 66, 69, 89, 89, - 65, 76, 128, 66, 69, 88, 128, 66, 69, 86, 69, 82, 65, 71, 69, 128, 66, - 69, 86, 69, 82, 65, 71, 197, 66, 69, 84, 87, 69, 69, 78, 128, 66, 69, 84, - 87, 69, 69, 206, 66, 69, 84, 72, 128, 66, 69, 84, 65, 128, 66, 69, 84, - 193, 66, 69, 212, 66, 69, 83, 73, 68, 197, 66, 69, 82, 75, 65, 78, 65, - 206, 66, 69, 82, 66, 69, 210, 66, 69, 80, 128, 66, 69, 79, 82, 195, 66, - 69, 78, 90, 69, 78, 197, 66, 69, 78, 84, 207, 66, 69, 78, 84, 128, 66, - 69, 78, 212, 66, 69, 78, 71, 65, 76, 201, 66, 69, 78, 68, 69, 128, 66, - 69, 78, 68, 128, 66, 69, 78, 196, 66, 69, 206, 66, 69, 76, 84, 128, 66, - 69, 76, 212, 66, 69, 76, 79, 215, 66, 69, 76, 76, 72, 79, 208, 66, 69, - 76, 76, 128, 66, 69, 76, 204, 66, 69, 76, 71, 84, 72, 79, 210, 66, 69, - 73, 84, 72, 128, 66, 69, 72, 73, 78, 196, 66, 69, 72, 69, 72, 128, 66, - 69, 72, 69, 200, 66, 69, 72, 128, 66, 69, 200, 66, 69, 71, 73, 78, 78, - 73, 78, 71, 128, 66, 69, 71, 73, 78, 78, 69, 82, 128, 66, 69, 71, 73, - 206, 66, 69, 70, 79, 82, 197, 66, 69, 69, 84, 76, 69, 128, 66, 69, 69, - 84, 65, 128, 66, 69, 69, 210, 66, 69, 69, 72, 73, 86, 69, 128, 66, 69, - 69, 72, 128, 66, 69, 69, 200, 66, 69, 67, 65, 85, 83, 69, 128, 66, 69, - 65, 86, 69, 82, 128, 66, 69, 65, 86, 69, 210, 66, 69, 65, 84, 73, 78, - 199, 66, 69, 65, 84, 128, 66, 69, 65, 82, 68, 69, 196, 66, 69, 65, 82, - 128, 66, 69, 65, 210, 66, 69, 65, 78, 83, 128, 66, 69, 65, 78, 128, 66, - 69, 65, 77, 69, 196, 66, 69, 65, 68, 83, 128, 66, 69, 65, 67, 200, 66, - 67, 65, 68, 128, 66, 67, 65, 196, 66, 66, 89, 88, 128, 66, 66, 89, 84, - 128, 66, 66, 89, 80, 128, 66, 66, 89, 128, 66, 66, 85, 88, 128, 66, 66, - 85, 84, 128, 66, 66, 85, 82, 88, 128, 66, 66, 85, 82, 128, 66, 66, 85, - 80, 128, 66, 66, 85, 79, 88, 128, 66, 66, 85, 79, 80, 128, 66, 66, 85, - 79, 128, 66, 66, 85, 128, 66, 66, 79, 88, 128, 66, 66, 79, 84, 128, 66, - 66, 79, 80, 128, 66, 66, 79, 128, 66, 66, 73, 88, 128, 66, 66, 73, 80, - 128, 66, 66, 73, 69, 88, 128, 66, 66, 73, 69, 84, 128, 66, 66, 73, 69, - 80, 128, 66, 66, 73, 69, 128, 66, 66, 73, 128, 66, 66, 69, 88, 128, 66, - 66, 69, 80, 128, 66, 66, 69, 69, 128, 66, 66, 65, 88, 128, 66, 66, 65, - 84, 128, 66, 66, 65, 80, 128, 66, 66, 65, 65, 128, 66, 65, 89, 65, 78, - 78, 65, 128, 66, 65, 85, 128, 66, 65, 84, 84, 69, 82, 89, 128, 66, 65, - 84, 72, 84, 85, 66, 128, 66, 65, 84, 72, 65, 77, 65, 83, 65, 84, 128, 66, - 65, 84, 72, 128, 66, 65, 84, 200, 66, 65, 84, 65, 203, 66, 65, 83, 83, - 65, 128, 66, 65, 83, 83, 193, 66, 65, 83, 75, 69, 84, 66, 65, 76, 204, - 66, 65, 83, 72, 75, 73, 210, 66, 65, 83, 72, 128, 66, 65, 83, 69, 76, 73, - 78, 197, 66, 65, 83, 69, 66, 65, 76, 76, 128, 66, 65, 83, 69, 128, 66, - 65, 83, 197, 66, 65, 82, 83, 128, 66, 65, 82, 211, 66, 65, 82, 82, 73, - 69, 82, 128, 66, 65, 82, 82, 69, 75, 72, 128, 66, 65, 82, 82, 69, 69, - 128, 66, 65, 82, 82, 69, 197, 66, 65, 82, 76, 73, 78, 69, 128, 66, 65, - 82, 76, 69, 89, 128, 66, 65, 82, 73, 89, 79, 79, 83, 65, 78, 128, 66, 65, - 82, 66, 69, 210, 66, 65, 82, 65, 50, 128, 66, 65, 210, 66, 65, 78, 84, - 79, 67, 128, 66, 65, 78, 75, 78, 79, 84, 197, 66, 65, 78, 75, 128, 66, - 65, 78, 203, 66, 65, 78, 74, 79, 128, 66, 65, 78, 68, 128, 66, 65, 78, - 65, 78, 65, 128, 66, 65, 78, 50, 128, 66, 65, 78, 178, 66, 65, 77, 66, - 79, 79, 83, 128, 66, 65, 77, 66, 79, 79, 128, 66, 65, 76, 85, 68, 65, - 128, 66, 65, 76, 76, 80, 79, 73, 78, 212, 66, 65, 76, 76, 79, 84, 128, - 66, 65, 76, 76, 79, 212, 66, 65, 76, 76, 79, 79, 78, 45, 83, 80, 79, 75, - 69, 196, 66, 65, 76, 76, 79, 79, 78, 128, 66, 65, 76, 76, 69, 212, 66, - 65, 76, 68, 128, 66, 65, 76, 65, 71, 128, 66, 65, 76, 128, 66, 65, 204, - 66, 65, 73, 82, 75, 65, 78, 128, 66, 65, 73, 77, 65, 73, 128, 66, 65, 72, - 84, 128, 66, 65, 72, 73, 82, 71, 79, 77, 85, 75, 72, 65, 128, 66, 65, 72, - 65, 82, 50, 128, 66, 65, 72, 65, 82, 178, 66, 65, 72, 128, 66, 65, 71, - 85, 69, 84, 84, 197, 66, 65, 71, 83, 128, 66, 65, 71, 71, 65, 71, 197, - 66, 65, 71, 69, 76, 128, 66, 65, 71, 65, 128, 66, 65, 71, 51, 128, 66, - 65, 199, 66, 65, 68, 77, 73, 78, 84, 79, 206, 66, 65, 68, 71, 69, 82, - 128, 66, 65, 68, 71, 69, 128, 66, 65, 196, 66, 65, 67, 84, 82, 73, 65, - 206, 66, 65, 67, 79, 78, 128, 66, 65, 67, 75, 87, 65, 82, 68, 128, 66, - 65, 67, 75, 83, 80, 65, 67, 69, 128, 66, 65, 67, 75, 83, 76, 65, 83, 72, - 128, 66, 65, 67, 75, 83, 76, 65, 83, 200, 66, 65, 67, 75, 83, 76, 65, 78, - 84, 69, 196, 66, 65, 67, 75, 72, 65, 78, 196, 66, 65, 67, 75, 45, 84, 73, - 76, 84, 69, 196, 66, 65, 67, 75, 128, 66, 65, 67, 203, 66, 65, 66, 89, - 128, 66, 65, 66, 217, 66, 65, 65, 82, 69, 82, 85, 128, 66, 65, 45, 50, - 128, 66, 51, 48, 53, 128, 66, 50, 53, 180, 66, 50, 52, 183, 66, 50, 52, - 179, 66, 50, 52, 178, 66, 50, 52, 177, 66, 50, 52, 176, 66, 50, 51, 179, - 66, 50, 51, 177, 66, 50, 51, 176, 66, 50, 50, 181, 66, 50, 50, 176, 66, - 49, 57, 177, 66, 49, 55, 182, 66, 49, 55, 179, 66, 49, 54, 57, 128, 66, - 49, 54, 56, 128, 66, 49, 54, 55, 128, 66, 49, 54, 54, 128, 66, 49, 54, - 53, 128, 66, 49, 54, 52, 128, 66, 49, 54, 179, 66, 49, 54, 178, 66, 49, - 54, 49, 128, 66, 49, 54, 48, 128, 66, 49, 53, 185, 66, 49, 53, 56, 128, - 66, 49, 53, 55, 128, 66, 49, 53, 182, 66, 49, 53, 53, 128, 66, 49, 53, - 52, 128, 66, 49, 53, 51, 128, 66, 49, 53, 50, 128, 66, 49, 53, 177, 66, - 49, 53, 48, 128, 66, 49, 52, 54, 128, 66, 49, 52, 181, 66, 49, 52, 50, - 128, 66, 49, 52, 177, 66, 49, 52, 176, 66, 49, 51, 181, 66, 49, 51, 179, - 66, 49, 51, 50, 128, 66, 49, 51, 177, 66, 49, 51, 176, 66, 49, 50, 184, - 66, 49, 50, 183, 66, 49, 50, 181, 66, 49, 50, 179, 66, 49, 50, 178, 66, - 49, 50, 177, 66, 49, 50, 176, 66, 49, 48, 57, 205, 66, 49, 48, 57, 198, - 66, 49, 48, 56, 205, 66, 49, 48, 56, 198, 66, 49, 48, 55, 205, 66, 49, - 48, 55, 198, 66, 49, 48, 54, 205, 66, 49, 48, 54, 198, 66, 49, 48, 53, - 205, 66, 49, 48, 53, 198, 66, 49, 48, 181, 66, 49, 48, 180, 66, 49, 48, - 178, 66, 49, 48, 176, 66, 48, 57, 177, 66, 48, 57, 176, 66, 48, 56, 57, - 128, 66, 48, 56, 183, 66, 48, 56, 54, 128, 66, 48, 56, 181, 66, 48, 56, - 51, 128, 66, 48, 56, 50, 128, 66, 48, 56, 177, 66, 48, 56, 176, 66, 48, - 55, 57, 128, 66, 48, 55, 184, 66, 48, 55, 183, 66, 48, 55, 182, 66, 48, - 55, 181, 66, 48, 55, 180, 66, 48, 55, 179, 66, 48, 55, 178, 66, 48, 55, - 177, 66, 48, 55, 176, 66, 48, 54, 185, 66, 48, 54, 184, 66, 48, 54, 183, - 66, 48, 54, 182, 66, 48, 54, 181, 66, 48, 54, 52, 128, 66, 48, 54, 51, - 128, 66, 48, 54, 178, 66, 48, 54, 177, 66, 48, 54, 176, 66, 48, 53, 185, - 66, 48, 53, 184, 66, 48, 53, 183, 66, 48, 53, 54, 128, 66, 48, 53, 181, - 66, 48, 53, 180, 66, 48, 53, 179, 66, 48, 53, 178, 66, 48, 53, 177, 66, - 48, 53, 176, 66, 48, 52, 57, 128, 66, 48, 52, 184, 66, 48, 52, 55, 128, - 66, 48, 52, 182, 66, 48, 52, 181, 66, 48, 52, 180, 66, 48, 52, 179, 66, - 48, 52, 178, 66, 48, 52, 177, 66, 48, 52, 176, 66, 48, 51, 185, 66, 48, - 51, 184, 66, 48, 51, 183, 66, 48, 51, 182, 66, 48, 51, 52, 128, 66, 48, - 51, 179, 66, 48, 51, 178, 66, 48, 51, 177, 66, 48, 51, 176, 66, 48, 50, - 185, 66, 48, 50, 184, 66, 48, 50, 183, 66, 48, 50, 182, 66, 48, 50, 181, - 66, 48, 50, 180, 66, 48, 50, 179, 66, 48, 50, 50, 128, 66, 48, 50, 177, - 66, 48, 50, 176, 66, 48, 49, 57, 128, 66, 48, 49, 56, 128, 66, 48, 49, - 183, 66, 48, 49, 182, 66, 48, 49, 181, 66, 48, 49, 180, 66, 48, 49, 179, - 66, 48, 49, 178, 66, 48, 49, 177, 66, 48, 49, 176, 66, 48, 48, 57, 128, - 66, 48, 48, 185, 66, 48, 48, 56, 128, 66, 48, 48, 184, 66, 48, 48, 55, - 128, 66, 48, 48, 183, 66, 48, 48, 54, 128, 66, 48, 48, 182, 66, 48, 48, - 53, 65, 128, 66, 48, 48, 53, 128, 66, 48, 48, 181, 66, 48, 48, 52, 128, - 66, 48, 48, 180, 66, 48, 48, 51, 128, 66, 48, 48, 179, 66, 48, 48, 50, - 128, 66, 48, 48, 178, 66, 48, 48, 49, 128, 66, 48, 48, 177, 65, 90, 90, - 193, 65, 90, 85, 128, 65, 89, 66, 128, 65, 89, 65, 72, 128, 65, 88, 69, - 128, 65, 87, 90, 128, 65, 87, 88, 128, 65, 87, 81, 128, 65, 87, 69, 128, - 65, 87, 67, 128, 65, 87, 65, 217, 65, 86, 79, 67, 65, 68, 79, 128, 65, - 86, 69, 83, 84, 65, 206, 65, 86, 69, 82, 65, 71, 197, 65, 86, 65, 75, 82, - 65, 72, 65, 83, 65, 78, 89, 65, 128, 65, 86, 65, 71, 82, 65, 72, 65, 128, - 65, 85, 89, 65, 78, 78, 65, 128, 65, 85, 84, 85, 77, 78, 128, 65, 85, 84, - 79, 77, 79, 66, 73, 76, 69, 128, 65, 85, 84, 79, 77, 65, 84, 69, 196, 65, - 85, 84, 207, 65, 85, 83, 84, 82, 65, 204, 65, 85, 82, 73, 80, 73, 71, 77, - 69, 78, 84, 128, 65, 85, 82, 65, 77, 65, 90, 68, 65, 65, 72, 65, 128, 65, - 85, 82, 65, 77, 65, 90, 68, 65, 65, 45, 50, 128, 65, 85, 82, 65, 77, 65, - 90, 68, 65, 65, 128, 65, 85, 78, 78, 128, 65, 85, 71, 85, 83, 84, 128, - 65, 85, 71, 77, 69, 78, 84, 65, 84, 73, 79, 206, 65, 85, 69, 128, 65, 85, - 66, 69, 82, 71, 73, 78, 69, 128, 65, 84, 84, 73, 195, 65, 84, 84, 72, 65, - 67, 65, 78, 128, 65, 84, 84, 69, 78, 84, 73, 79, 78, 128, 65, 84, 84, 65, - 203, 65, 84, 84, 65, 67, 72, 73, 78, 199, 65, 84, 84, 65, 67, 72, 69, - 196, 65, 84, 79, 205, 65, 84, 78, 65, 200, 65, 84, 77, 65, 65, 85, 128, - 65, 84, 73, 89, 65, 128, 65, 84, 73, 85, 128, 65, 84, 73, 75, 82, 65, 77, - 65, 128, 65, 84, 72, 76, 69, 84, 73, 195, 65, 84, 72, 65, 82, 86, 65, 86, - 69, 68, 73, 195, 65, 84, 72, 65, 80, 65, 83, 67, 65, 206, 65, 84, 72, 45, - 84, 72, 65, 76, 65, 84, 72, 65, 128, 65, 83, 90, 128, 65, 83, 89, 85, 82, - 193, 65, 83, 89, 77, 80, 84, 79, 84, 73, 67, 65, 76, 76, 217, 65, 83, 84, - 82, 79, 78, 79, 77, 73, 67, 65, 204, 65, 83, 84, 82, 79, 76, 79, 71, 73, - 67, 65, 204, 65, 83, 84, 82, 65, 69, 65, 128, 65, 83, 84, 79, 78, 73, 83, - 72, 69, 196, 65, 83, 84, 69, 82, 73, 83, 77, 128, 65, 83, 84, 69, 82, 73, - 83, 75, 211, 65, 83, 84, 69, 82, 73, 83, 75, 128, 65, 83, 84, 69, 82, 73, - 83, 203, 65, 83, 84, 69, 82, 73, 83, 67, 85, 83, 128, 65, 83, 83, 89, 82, - 73, 65, 206, 65, 83, 83, 69, 82, 84, 73, 79, 78, 128, 65, 83, 80, 73, 82, - 65, 84, 73, 79, 78, 128, 65, 83, 80, 73, 82, 65, 84, 69, 196, 65, 83, 80, - 69, 82, 128, 65, 83, 73, 65, 45, 65, 85, 83, 84, 82, 65, 76, 73, 65, 128, - 65, 83, 72, 71, 65, 66, 128, 65, 83, 72, 69, 83, 128, 65, 83, 72, 57, - 128, 65, 83, 72, 51, 128, 65, 83, 72, 178, 65, 83, 67, 73, 193, 65, 83, - 67, 69, 78, 84, 128, 65, 83, 67, 69, 78, 68, 73, 78, 199, 65, 83, 65, 76, - 50, 128, 65, 83, 45, 83, 65, 76, 65, 65, 84, 213, 65, 83, 45, 83, 65, 74, - 68, 65, 128, 65, 82, 85, 72, 85, 65, 128, 65, 82, 84, 211, 65, 82, 84, - 73, 83, 212, 65, 82, 84, 73, 67, 85, 76, 65, 84, 69, 196, 65, 82, 84, 65, - 66, 197, 65, 82, 84, 65, 128, 65, 82, 83, 69, 79, 83, 128, 65, 82, 83, - 69, 79, 211, 65, 82, 83, 69, 78, 73, 67, 128, 65, 82, 82, 79, 87, 83, - 128, 65, 82, 82, 79, 87, 211, 65, 82, 82, 79, 87, 72, 69, 65, 68, 83, - 128, 65, 82, 82, 79, 87, 72, 69, 65, 68, 45, 83, 72, 65, 80, 69, 196, 65, - 82, 82, 79, 87, 72, 69, 65, 68, 128, 65, 82, 82, 79, 87, 72, 69, 65, 196, - 65, 82, 82, 79, 87, 45, 84, 65, 73, 76, 128, 65, 82, 82, 73, 86, 73, 78, - 71, 128, 65, 82, 82, 73, 86, 69, 128, 65, 82, 82, 65, 89, 128, 65, 82, - 80, 69, 71, 71, 73, 65, 84, 207, 65, 82, 79, 85, 83, 73, 78, 199, 65, 82, - 79, 85, 82, 193, 65, 82, 79, 85, 78, 68, 45, 80, 82, 79, 70, 73, 76, 69, - 128, 65, 82, 79, 85, 78, 196, 65, 82, 77, 89, 128, 65, 82, 77, 211, 65, - 82, 77, 79, 85, 82, 128, 65, 82, 77, 69, 78, 73, 65, 206, 65, 82, 77, - 128, 65, 82, 205, 65, 82, 76, 65, 85, 199, 65, 82, 75, 84, 73, 75, 207, - 65, 82, 75, 65, 66, 128, 65, 82, 75, 65, 65, 78, 85, 128, 65, 82, 73, 83, - 84, 69, 82, 65, 128, 65, 82, 73, 83, 84, 69, 82, 193, 65, 82, 73, 69, 83, - 128, 65, 82, 71, 79, 84, 69, 82, 73, 128, 65, 82, 71, 79, 83, 89, 78, 84, - 72, 69, 84, 79, 78, 128, 65, 82, 71, 73, 128, 65, 82, 69, 80, 65, 128, - 65, 82, 69, 65, 128, 65, 82, 68, 72, 65, 86, 73, 83, 65, 82, 71, 65, 128, - 65, 82, 68, 72, 65, 67, 65, 78, 68, 82, 65, 128, 65, 82, 67, 72, 65, 73, - 79, 78, 128, 65, 82, 67, 72, 65, 73, 79, 206, 65, 82, 67, 72, 65, 73, - 195, 65, 82, 67, 200, 65, 82, 67, 128, 65, 82, 195, 65, 82, 65, 77, 65, - 73, 195, 65, 82, 65, 69, 65, 69, 128, 65, 82, 65, 69, 65, 45, 85, 128, - 65, 82, 65, 69, 65, 45, 73, 128, 65, 82, 65, 69, 65, 45, 69, 79, 128, 65, - 82, 65, 69, 65, 45, 69, 128, 65, 82, 65, 69, 65, 45, 65, 128, 65, 82, 65, - 68, 128, 65, 82, 65, 196, 65, 82, 65, 66, 73, 67, 45, 73, 78, 68, 73, - 195, 65, 82, 65, 66, 73, 65, 206, 65, 82, 45, 82, 85, 66, 128, 65, 82, - 45, 82, 65, 72, 77, 65, 206, 65, 82, 45, 82, 65, 72, 69, 69, 77, 128, 65, - 81, 85, 65, 82, 73, 85, 83, 128, 65, 81, 85, 65, 70, 79, 82, 84, 73, 83, - 128, 65, 81, 85, 193, 65, 80, 85, 206, 65, 80, 82, 73, 76, 128, 65, 80, - 80, 82, 79, 88, 73, 77, 65, 84, 69, 76, 217, 65, 80, 80, 82, 79, 88, 73, - 77, 65, 84, 69, 128, 65, 80, 80, 82, 79, 65, 67, 72, 69, 211, 65, 80, 80, - 82, 79, 65, 67, 72, 128, 65, 80, 80, 76, 73, 67, 65, 84, 73, 79, 78, 128, - 65, 80, 80, 76, 73, 67, 65, 84, 73, 79, 206, 65, 80, 79, 84, 72, 69, 83, - 128, 65, 80, 79, 84, 72, 69, 77, 65, 128, 65, 80, 79, 83, 84, 82, 79, 80, - 72, 69, 128, 65, 80, 79, 83, 84, 82, 79, 70, 79, 83, 128, 65, 80, 79, 83, - 84, 82, 79, 70, 79, 211, 65, 80, 79, 83, 84, 82, 79, 70, 79, 201, 65, 80, - 79, 76, 76, 79, 78, 128, 65, 80, 79, 68, 69, 88, 73, 65, 128, 65, 80, 79, - 68, 69, 82, 77, 193, 65, 80, 76, 79, 85, 78, 128, 65, 80, 76, 201, 65, - 80, 204, 65, 80, 73, 78, 128, 65, 80, 69, 83, 207, 65, 80, 67, 128, 65, - 80, 65, 82, 84, 128, 65, 80, 65, 65, 84, 79, 128, 65, 79, 85, 128, 65, - 79, 82, 128, 65, 78, 89, 128, 65, 78, 85, 83, 86, 65, 82, 65, 89, 65, - 128, 65, 78, 85, 83, 86, 65, 82, 65, 128, 65, 78, 85, 83, 86, 65, 82, - 193, 65, 78, 85, 68, 65, 84, 84, 65, 128, 65, 78, 85, 68, 65, 84, 84, - 193, 65, 78, 84, 73, 82, 69, 83, 84, 82, 73, 67, 84, 73, 79, 78, 128, 65, - 78, 84, 73, 77, 79, 78, 89, 45, 50, 128, 65, 78, 84, 73, 77, 79, 78, 89, - 128, 65, 78, 84, 73, 77, 79, 78, 217, 65, 78, 84, 73, 77, 79, 78, 73, 65, - 84, 69, 128, 65, 78, 84, 73, 75, 69, 78, 79, 77, 65, 128, 65, 78, 84, 73, - 75, 69, 78, 79, 75, 89, 76, 73, 83, 77, 65, 128, 65, 78, 84, 73, 70, 79, - 78, 73, 65, 128, 65, 78, 84, 73, 67, 76, 79, 67, 75, 87, 73, 83, 69, 45, - 82, 79, 84, 65, 84, 69, 196, 65, 78, 84, 73, 67, 76, 79, 67, 75, 87, 73, - 83, 69, 128, 65, 78, 84, 73, 67, 76, 79, 67, 75, 87, 73, 83, 197, 65, 78, - 84, 69, 78, 78, 65, 128, 65, 78, 84, 69, 78, 78, 193, 65, 78, 84, 65, 82, - 71, 79, 77, 85, 75, 72, 65, 128, 65, 78, 83, 85, 218, 65, 78, 83, 72, 69, - 128, 65, 78, 80, 69, 65, 128, 65, 78, 207, 65, 78, 78, 85, 73, 84, 217, - 65, 78, 78, 79, 84, 65, 84, 73, 79, 206, 65, 78, 78, 65, 65, 85, 128, 65, - 78, 75, 72, 128, 65, 78, 74, 73, 128, 65, 78, 73, 77, 65, 76, 128, 65, - 78, 72, 85, 78, 78, 65, 128, 65, 78, 72, 85, 77, 65, 65, 128, 65, 78, 72, - 85, 77, 128, 65, 78, 72, 85, 128, 65, 78, 72, 65, 65, 128, 65, 78, 72, - 128, 65, 78, 71, 85, 76, 65, 82, 128, 65, 78, 71, 85, 73, 83, 72, 69, - 196, 65, 78, 71, 83, 84, 82, 79, 205, 65, 78, 71, 82, 217, 65, 78, 71, - 76, 73, 67, 65, 78, 193, 65, 78, 71, 76, 69, 68, 128, 65, 78, 71, 76, 69, - 196, 65, 78, 71, 75, 72, 65, 78, 75, 72, 85, 128, 65, 78, 71, 75, 65, - 128, 65, 78, 71, 69, 210, 65, 78, 71, 69, 76, 128, 65, 78, 71, 69, 68, - 128, 65, 78, 68, 65, 80, 128, 65, 78, 67, 79, 82, 65, 128, 65, 78, 67, - 72, 79, 82, 128, 65, 78, 65, 84, 82, 73, 67, 72, 73, 83, 77, 65, 128, 65, - 78, 65, 84, 79, 77, 73, 67, 65, 204, 65, 78, 65, 80, 128, 65, 78, 45, 78, - 73, 83, 70, 128, 65, 77, 85, 76, 69, 84, 128, 65, 77, 80, 83, 128, 65, - 77, 80, 72, 79, 82, 65, 128, 65, 77, 80, 69, 82, 83, 65, 78, 68, 128, 65, - 77, 80, 69, 82, 83, 65, 78, 196, 65, 77, 79, 85, 78, 212, 65, 77, 69, 82, - 73, 67, 65, 83, 128, 65, 77, 69, 82, 73, 67, 65, 206, 65, 77, 66, 85, 76, - 65, 78, 67, 69, 128, 65, 77, 66, 193, 65, 77, 66, 128, 65, 77, 65, 82, - 128, 65, 77, 65, 210, 65, 77, 65, 76, 71, 65, 77, 65, 84, 73, 79, 206, - 65, 77, 65, 76, 71, 65, 77, 128, 65, 76, 86, 69, 79, 76, 65, 210, 65, 76, - 85, 77, 128, 65, 76, 84, 69, 82, 78, 65, 84, 73, 86, 197, 65, 76, 84, 69, - 82, 78, 65, 84, 73, 79, 206, 65, 76, 84, 69, 82, 78, 65, 84, 73, 78, 71, - 128, 65, 76, 84, 69, 82, 78, 65, 84, 73, 78, 199, 65, 76, 84, 69, 82, 78, - 65, 84, 69, 128, 65, 76, 84, 69, 82, 78, 65, 84, 197, 65, 76, 84, 65, - 128, 65, 76, 80, 72, 65, 128, 65, 76, 80, 72, 193, 65, 76, 80, 65, 80, - 82, 65, 78, 65, 128, 65, 76, 80, 65, 80, 82, 65, 65, 78, 193, 65, 76, 80, - 65, 128, 65, 76, 77, 79, 83, 212, 65, 76, 76, 79, 128, 65, 76, 76, 73, - 65, 78, 67, 69, 128, 65, 76, 76, 201, 65, 76, 76, 65, 200, 65, 76, 76, - 65, 65, 72, 128, 65, 76, 75, 65, 76, 73, 45, 50, 128, 65, 76, 75, 65, 76, - 73, 128, 65, 76, 73, 71, 78, 69, 196, 65, 76, 73, 70, 85, 128, 65, 76, - 73, 70, 128, 65, 76, 73, 198, 65, 76, 73, 69, 78, 128, 65, 76, 73, 69, - 206, 65, 76, 71, 73, 218, 65, 76, 70, 65, 128, 65, 76, 69, 85, 212, 65, - 76, 69, 82, 84, 128, 65, 76, 69, 80, 72, 128, 65, 76, 69, 77, 66, 73, 67, - 128, 65, 76, 69, 70, 128, 65, 76, 66, 65, 78, 73, 65, 206, 65, 76, 65, - 89, 78, 65, 65, 128, 65, 76, 65, 89, 72, 73, 77, 65, 193, 65, 76, 65, 89, - 72, 73, 205, 65, 76, 65, 89, 72, 201, 65, 76, 65, 89, 72, 69, 128, 65, - 76, 65, 89, 72, 197, 65, 76, 65, 89, 72, 65, 193, 65, 76, 65, 82, 205, - 65, 76, 65, 80, 72, 128, 65, 76, 45, 76, 65, 75, 85, 78, 65, 128, 65, 76, - 45, 74, 85, 90, 128, 65, 75, 85, 82, 213, 65, 75, 84, 73, 69, 83, 69, 76, - 83, 75, 65, 66, 128, 65, 75, 83, 65, 128, 65, 75, 72, 77, 73, 77, 73, - 195, 65, 75, 66, 65, 210, 65, 75, 65, 82, 65, 128, 65, 75, 65, 82, 193, - 65, 73, 89, 65, 78, 78, 65, 128, 65, 73, 86, 73, 76, 73, 203, 65, 73, 86, - 65, 128, 65, 73, 84, 79, 206, 65, 73, 82, 80, 76, 65, 78, 69, 128, 65, - 73, 82, 80, 76, 65, 78, 197, 65, 73, 78, 213, 65, 73, 78, 78, 128, 65, - 73, 76, 77, 128, 65, 73, 75, 65, 82, 65, 128, 65, 73, 72, 86, 85, 83, - 128, 65, 72, 83, 68, 65, 128, 65, 72, 83, 65, 128, 65, 72, 79, 205, 65, - 72, 65, 78, 199, 65, 72, 65, 71, 71, 65, 210, 65, 72, 65, 68, 128, 65, - 71, 85, 78, 71, 128, 65, 71, 79, 71, 201, 65, 71, 71, 82, 65, 86, 65, 84, - 73, 79, 78, 128, 65, 71, 71, 82, 65, 86, 65, 84, 69, 196, 65, 71, 65, 73, - 78, 83, 212, 65, 71, 65, 73, 78, 128, 65, 70, 84, 69, 210, 65, 70, 83, - 65, 65, 81, 128, 65, 70, 82, 73, 67, 65, 206, 65, 70, 79, 82, 69, 77, 69, - 78, 84, 73, 79, 78, 69, 68, 128, 65, 70, 71, 72, 65, 78, 201, 65, 70, 70, - 82, 73, 67, 65, 84, 73, 79, 206, 65, 70, 70, 73, 216, 65, 69, 89, 65, 78, - 78, 65, 128, 65, 69, 89, 128, 65, 69, 83, 67, 85, 76, 65, 80, 73, 85, 83, - 128, 65, 69, 83, 67, 128, 65, 69, 83, 128, 65, 69, 82, 73, 65, 204, 65, - 69, 82, 128, 65, 69, 76, 65, 45, 80, 73, 76, 76, 65, 128, 65, 69, 76, - 128, 65, 69, 75, 128, 65, 69, 71, 69, 65, 206, 65, 69, 71, 128, 65, 69, - 69, 89, 65, 78, 78, 65, 128, 65, 69, 69, 128, 65, 69, 68, 65, 45, 80, 73, - 76, 76, 65, 128, 65, 69, 68, 128, 65, 69, 66, 128, 65, 68, 86, 65, 78, - 84, 65, 71, 69, 128, 65, 68, 86, 65, 78, 67, 69, 128, 65, 68, 85, 76, 84, - 128, 65, 68, 77, 73, 83, 83, 73, 79, 206, 65, 68, 77, 69, 84, 79, 83, - 128, 65, 68, 76, 65, 205, 65, 68, 72, 69, 83, 73, 86, 197, 65, 68, 69, - 71, 128, 65, 68, 69, 199, 65, 68, 68, 82, 69, 83, 83, 69, 196, 65, 68, - 68, 82, 69, 83, 211, 65, 68, 68, 65, 75, 128, 65, 68, 65, 203, 65, 67, - 85, 84, 69, 45, 77, 65, 67, 82, 79, 78, 128, 65, 67, 85, 84, 69, 45, 71, - 82, 65, 86, 69, 45, 65, 67, 85, 84, 69, 128, 65, 67, 85, 84, 197, 65, 67, - 84, 85, 65, 76, 76, 217, 65, 67, 84, 73, 86, 65, 84, 197, 65, 67, 82, 79, - 80, 72, 79, 78, 73, 195, 65, 67, 75, 78, 79, 87, 76, 69, 68, 71, 69, 128, - 65, 67, 67, 85, 77, 85, 76, 65, 84, 73, 79, 78, 128, 65, 67, 67, 79, 85, - 78, 212, 65, 67, 67, 79, 82, 68, 73, 79, 78, 128, 65, 67, 67, 79, 77, 77, - 79, 68, 65, 84, 73, 79, 78, 128, 65, 67, 67, 69, 80, 84, 128, 65, 67, 67, - 69, 78, 84, 45, 83, 84, 65, 67, 67, 65, 84, 79, 128, 65, 67, 67, 69, 78, - 84, 128, 65, 67, 67, 69, 78, 212, 65, 67, 65, 68, 69, 77, 217, 65, 66, - 89, 83, 77, 65, 204, 65, 66, 85, 78, 68, 65, 78, 67, 69, 128, 65, 66, 75, - 72, 65, 83, 73, 65, 206, 65, 66, 66, 82, 69, 86, 73, 65, 84, 73, 79, 206, - 65, 66, 65, 70, 73, 76, 73, 128, 65, 66, 65, 67, 85, 83, 128, 65, 66, - 178, 65, 66, 49, 57, 49, 128, 65, 66, 49, 56, 56, 128, 65, 66, 49, 56, - 48, 128, 65, 66, 49, 55, 49, 128, 65, 66, 49, 54, 52, 128, 65, 66, 49, - 51, 49, 66, 128, 65, 66, 49, 51, 49, 65, 128, 65, 66, 49, 50, 51, 128, - 65, 66, 49, 50, 50, 128, 65, 66, 49, 50, 48, 128, 65, 66, 49, 49, 56, - 128, 65, 66, 48, 56, 55, 128, 65, 66, 48, 56, 54, 128, 65, 66, 48, 56, - 53, 128, 65, 66, 48, 56, 50, 128, 65, 66, 48, 56, 49, 128, 65, 66, 48, - 56, 48, 128, 65, 66, 48, 55, 57, 128, 65, 66, 48, 55, 56, 128, 65, 66, - 48, 55, 55, 128, 65, 66, 48, 55, 54, 128, 65, 66, 48, 55, 52, 128, 65, - 66, 48, 55, 51, 128, 65, 66, 48, 55, 48, 128, 65, 66, 48, 54, 57, 128, - 65, 66, 48, 54, 55, 128, 65, 66, 48, 54, 54, 128, 65, 66, 48, 54, 53, - 128, 65, 66, 48, 54, 49, 128, 65, 66, 48, 54, 48, 128, 65, 66, 48, 53, - 57, 128, 65, 66, 48, 53, 56, 128, 65, 66, 48, 53, 55, 128, 65, 66, 48, - 53, 54, 128, 65, 66, 48, 53, 53, 128, 65, 66, 48, 53, 52, 128, 65, 66, - 48, 53, 51, 128, 65, 66, 48, 53, 49, 128, 65, 66, 48, 53, 48, 128, 65, - 66, 48, 52, 57, 128, 65, 66, 48, 52, 56, 128, 65, 66, 48, 52, 55, 128, - 65, 66, 48, 52, 54, 128, 65, 66, 48, 52, 53, 128, 65, 66, 48, 52, 52, - 128, 65, 66, 48, 52, 49, 128, 65, 66, 48, 52, 48, 128, 65, 66, 48, 51, - 57, 128, 65, 66, 48, 51, 56, 128, 65, 66, 48, 51, 55, 128, 65, 66, 48, - 51, 52, 128, 65, 66, 48, 51, 49, 128, 65, 66, 48, 51, 48, 128, 65, 66, - 48, 50, 57, 128, 65, 66, 48, 50, 56, 128, 65, 66, 48, 50, 55, 128, 65, - 66, 48, 50, 54, 128, 65, 66, 48, 50, 52, 128, 65, 66, 48, 50, 51, 77, - 128, 65, 66, 48, 50, 51, 128, 65, 66, 48, 50, 50, 77, 128, 65, 66, 48, - 50, 50, 70, 128, 65, 66, 48, 50, 50, 128, 65, 66, 48, 50, 49, 77, 128, - 65, 66, 48, 50, 49, 70, 128, 65, 66, 48, 50, 49, 128, 65, 66, 48, 50, 48, - 128, 65, 66, 48, 49, 55, 128, 65, 66, 48, 49, 54, 128, 65, 66, 48, 49, - 51, 128, 65, 66, 48, 49, 49, 128, 65, 66, 48, 49, 48, 128, 65, 66, 48, - 48, 57, 128, 65, 66, 48, 48, 56, 128, 65, 66, 48, 48, 55, 128, 65, 66, - 48, 48, 54, 128, 65, 66, 48, 48, 53, 128, 65, 66, 48, 48, 52, 128, 65, - 66, 48, 48, 51, 128, 65, 66, 48, 48, 50, 128, 65, 66, 48, 48, 49, 128, - 65, 65, 90, 72, 65, 65, 75, 75, 85, 128, 65, 65, 89, 73, 78, 128, 65, 65, - 89, 65, 78, 78, 65, 128, 65, 65, 89, 128, 65, 65, 87, 128, 65, 65, 79, - 128, 65, 65, 74, 128, 65, 65, 66, 65, 65, 70, 73, 76, 73, 128, 65, 65, - 48, 51, 50, 128, 65, 65, 48, 51, 49, 128, 65, 65, 48, 51, 48, 128, 65, - 65, 48, 50, 57, 128, 65, 65, 48, 50, 56, 128, 65, 65, 48, 50, 55, 128, - 65, 65, 48, 50, 54, 128, 65, 65, 48, 50, 53, 128, 65, 65, 48, 50, 52, - 128, 65, 65, 48, 50, 51, 128, 65, 65, 48, 50, 50, 128, 65, 65, 48, 50, - 49, 128, 65, 65, 48, 50, 48, 128, 65, 65, 48, 49, 57, 128, 65, 65, 48, - 49, 56, 128, 65, 65, 48, 49, 55, 128, 65, 65, 48, 49, 54, 128, 65, 65, - 48, 49, 53, 128, 65, 65, 48, 49, 52, 128, 65, 65, 48, 49, 51, 128, 65, - 65, 48, 49, 50, 128, 65, 65, 48, 49, 49, 128, 65, 65, 48, 49, 48, 128, - 65, 65, 48, 48, 57, 128, 65, 65, 48, 48, 56, 128, 65, 65, 48, 48, 55, 66, - 128, 65, 65, 48, 48, 55, 65, 128, 65, 65, 48, 48, 55, 128, 65, 65, 48, - 48, 54, 128, 65, 65, 48, 48, 53, 128, 65, 65, 48, 48, 52, 128, 65, 65, - 48, 48, 51, 128, 65, 65, 48, 48, 50, 128, 65, 65, 48, 48, 49, 128, 65, - 56, 48, 55, 128, 65, 56, 48, 54, 128, 65, 56, 48, 53, 128, 65, 56, 48, - 52, 128, 65, 56, 48, 51, 128, 65, 56, 48, 50, 128, 65, 56, 48, 49, 128, - 65, 56, 48, 48, 128, 65, 55, 51, 178, 65, 55, 50, 182, 65, 55, 49, 183, - 65, 55, 49, 181, 65, 55, 49, 180, 65, 55, 49, 179, 65, 55, 49, 178, 65, - 55, 49, 177, 65, 55, 49, 176, 65, 55, 48, 57, 45, 182, 65, 55, 48, 57, - 45, 180, 65, 55, 48, 57, 45, 179, 65, 55, 48, 57, 45, 178, 65, 55, 48, - 185, 65, 55, 48, 184, 65, 55, 48, 183, 65, 55, 48, 182, 65, 55, 48, 181, - 65, 55, 48, 180, 65, 55, 48, 179, 65, 55, 48, 178, 65, 55, 48, 177, 65, - 54, 54, 52, 128, 65, 54, 54, 51, 128, 65, 54, 54, 50, 128, 65, 54, 54, - 49, 128, 65, 54, 54, 48, 128, 65, 54, 53, 57, 128, 65, 54, 53, 56, 128, - 65, 54, 53, 55, 128, 65, 54, 53, 54, 128, 65, 54, 53, 53, 128, 65, 54, - 53, 52, 128, 65, 54, 53, 51, 128, 65, 54, 53, 50, 128, 65, 54, 53, 49, - 128, 65, 54, 52, 57, 128, 65, 54, 52, 56, 128, 65, 54, 52, 54, 128, 65, - 54, 52, 53, 128, 65, 54, 52, 52, 128, 65, 54, 52, 51, 128, 65, 54, 52, - 50, 128, 65, 54, 52, 48, 128, 65, 54, 51, 56, 128, 65, 54, 51, 55, 128, - 65, 54, 51, 52, 128, 65, 54, 50, 57, 128, 65, 54, 50, 56, 128, 65, 54, - 50, 55, 128, 65, 54, 50, 54, 128, 65, 54, 50, 52, 128, 65, 54, 50, 51, - 128, 65, 54, 50, 50, 128, 65, 54, 50, 49, 128, 65, 54, 50, 48, 128, 65, - 54, 49, 57, 128, 65, 54, 49, 56, 128, 65, 54, 49, 55, 128, 65, 54, 49, - 54, 128, 65, 54, 49, 53, 128, 65, 54, 49, 52, 128, 65, 54, 49, 51, 128, - 65, 54, 49, 50, 128, 65, 54, 49, 49, 128, 65, 54, 49, 48, 128, 65, 54, - 48, 57, 128, 65, 54, 48, 56, 128, 65, 54, 48, 54, 128, 65, 54, 48, 52, - 128, 65, 54, 48, 51, 128, 65, 54, 48, 50, 128, 65, 54, 48, 49, 128, 65, - 54, 48, 48, 128, 65, 53, 57, 56, 128, 65, 53, 57, 54, 128, 65, 53, 57, - 53, 128, 65, 53, 57, 52, 128, 65, 53, 57, 50, 128, 65, 53, 57, 49, 128, - 65, 53, 56, 57, 128, 65, 53, 56, 56, 128, 65, 53, 56, 55, 128, 65, 53, - 56, 54, 128, 65, 53, 56, 53, 128, 65, 53, 56, 52, 128, 65, 53, 56, 51, - 128, 65, 53, 56, 50, 128, 65, 53, 56, 49, 128, 65, 53, 56, 48, 128, 65, - 53, 55, 57, 128, 65, 53, 55, 56, 128, 65, 53, 55, 55, 128, 65, 53, 55, - 54, 128, 65, 53, 55, 53, 128, 65, 53, 55, 52, 128, 65, 53, 55, 51, 128, - 65, 53, 55, 50, 128, 65, 53, 55, 49, 128, 65, 53, 55, 48, 128, 65, 53, - 54, 57, 128, 65, 53, 54, 56, 128, 65, 53, 54, 54, 128, 65, 53, 54, 53, - 128, 65, 53, 54, 52, 128, 65, 53, 54, 51, 128, 65, 53, 53, 57, 128, 65, - 53, 53, 55, 128, 65, 53, 53, 54, 128, 65, 53, 53, 53, 128, 65, 53, 53, - 52, 128, 65, 53, 53, 51, 128, 65, 53, 53, 50, 128, 65, 53, 53, 49, 128, - 65, 53, 53, 48, 128, 65, 53, 52, 57, 128, 65, 53, 52, 56, 128, 65, 53, - 52, 55, 128, 65, 53, 52, 53, 128, 65, 53, 52, 50, 128, 65, 53, 52, 49, - 128, 65, 53, 52, 48, 128, 65, 53, 51, 57, 128, 65, 53, 51, 56, 128, 65, - 53, 51, 55, 128, 65, 53, 51, 54, 128, 65, 53, 51, 53, 128, 65, 53, 51, - 52, 128, 65, 53, 51, 50, 128, 65, 53, 51, 49, 128, 65, 53, 51, 48, 128, - 65, 53, 50, 57, 128, 65, 53, 50, 56, 128, 65, 53, 50, 55, 128, 65, 53, - 50, 54, 128, 65, 53, 50, 53, 128, 65, 53, 50, 52, 128, 65, 53, 50, 51, - 128, 65, 53, 50, 50, 128, 65, 53, 50, 49, 128, 65, 53, 50, 48, 128, 65, - 53, 49, 57, 128, 65, 53, 49, 56, 128, 65, 53, 49, 55, 128, 65, 53, 49, - 54, 128, 65, 53, 49, 53, 128, 65, 53, 49, 52, 128, 65, 53, 49, 51, 128, - 65, 53, 49, 50, 128, 65, 53, 49, 49, 128, 65, 53, 49, 48, 128, 65, 53, - 48, 57, 128, 65, 53, 48, 56, 128, 65, 53, 48, 55, 128, 65, 53, 48, 54, - 128, 65, 53, 48, 53, 128, 65, 53, 48, 52, 128, 65, 53, 48, 51, 128, 65, - 53, 48, 50, 128, 65, 53, 48, 49, 128, 65, 52, 57, 55, 128, 65, 52, 57, - 54, 128, 65, 52, 57, 53, 128, 65, 52, 57, 52, 128, 65, 52, 57, 51, 128, - 65, 52, 57, 50, 128, 65, 52, 57, 49, 128, 65, 52, 57, 48, 128, 65, 52, - 56, 57, 128, 65, 52, 56, 56, 128, 65, 52, 56, 55, 128, 65, 52, 56, 54, - 128, 65, 52, 56, 53, 128, 65, 52, 56, 52, 128, 65, 52, 56, 51, 128, 65, - 52, 56, 50, 128, 65, 52, 56, 49, 128, 65, 52, 56, 48, 128, 65, 52, 55, - 57, 128, 65, 52, 55, 56, 128, 65, 52, 55, 55, 128, 65, 52, 55, 54, 128, - 65, 52, 55, 53, 128, 65, 52, 55, 52, 128, 65, 52, 55, 51, 128, 65, 52, - 55, 50, 128, 65, 52, 55, 49, 128, 65, 52, 55, 48, 128, 65, 52, 54, 57, - 128, 65, 52, 54, 56, 128, 65, 52, 54, 55, 128, 65, 52, 54, 54, 128, 65, - 52, 54, 53, 128, 65, 52, 54, 52, 128, 65, 52, 54, 51, 128, 65, 52, 54, - 50, 128, 65, 52, 54, 49, 128, 65, 52, 54, 48, 128, 65, 52, 53, 57, 128, - 65, 52, 53, 56, 128, 65, 52, 53, 55, 65, 128, 65, 52, 53, 55, 128, 65, - 52, 53, 54, 128, 65, 52, 53, 53, 128, 65, 52, 53, 52, 128, 65, 52, 53, - 51, 128, 65, 52, 53, 50, 128, 65, 52, 53, 49, 128, 65, 52, 53, 48, 65, - 128, 65, 52, 53, 48, 128, 65, 52, 52, 57, 128, 65, 52, 52, 56, 128, 65, - 52, 52, 55, 128, 65, 52, 52, 54, 128, 65, 52, 52, 53, 128, 65, 52, 52, - 52, 128, 65, 52, 52, 51, 128, 65, 52, 52, 50, 128, 65, 52, 52, 49, 128, - 65, 52, 52, 48, 128, 65, 52, 51, 57, 128, 65, 52, 51, 56, 128, 65, 52, - 51, 55, 128, 65, 52, 51, 54, 128, 65, 52, 51, 53, 128, 65, 52, 51, 52, - 128, 65, 52, 51, 51, 128, 65, 52, 51, 50, 128, 65, 52, 51, 49, 128, 65, - 52, 51, 48, 128, 65, 52, 50, 57, 128, 65, 52, 50, 56, 128, 65, 52, 50, - 55, 128, 65, 52, 50, 54, 128, 65, 52, 50, 53, 128, 65, 52, 50, 52, 128, - 65, 52, 50, 51, 128, 65, 52, 50, 50, 128, 65, 52, 50, 49, 128, 65, 52, - 50, 48, 128, 65, 52, 49, 57, 128, 65, 52, 49, 56, 45, 86, 65, 83, 128, - 65, 52, 49, 56, 128, 65, 52, 49, 55, 45, 86, 65, 83, 128, 65, 52, 49, 55, - 128, 65, 52, 49, 54, 45, 86, 65, 83, 128, 65, 52, 49, 54, 128, 65, 52, - 49, 53, 45, 86, 65, 83, 128, 65, 52, 49, 53, 128, 65, 52, 49, 52, 45, 86, - 65, 83, 128, 65, 52, 49, 52, 128, 65, 52, 49, 51, 45, 86, 65, 83, 128, - 65, 52, 49, 51, 128, 65, 52, 49, 50, 45, 86, 65, 83, 128, 65, 52, 49, 50, - 128, 65, 52, 49, 49, 45, 86, 65, 83, 128, 65, 52, 49, 49, 128, 65, 52, - 49, 48, 193, 65, 52, 49, 48, 45, 86, 65, 83, 128, 65, 52, 49, 176, 65, - 52, 48, 57, 45, 86, 65, 83, 128, 65, 52, 48, 57, 128, 65, 52, 48, 56, 45, - 86, 65, 83, 128, 65, 52, 48, 56, 128, 65, 52, 48, 55, 45, 86, 65, 83, - 128, 65, 52, 48, 55, 128, 65, 52, 48, 54, 45, 86, 65, 83, 128, 65, 52, - 48, 54, 128, 65, 52, 48, 53, 45, 86, 65, 83, 128, 65, 52, 48, 53, 128, - 65, 52, 48, 52, 45, 86, 65, 83, 128, 65, 52, 48, 52, 128, 65, 52, 48, 51, - 45, 86, 65, 83, 128, 65, 52, 48, 51, 128, 65, 52, 48, 50, 45, 86, 65, 83, - 128, 65, 52, 48, 50, 128, 65, 52, 48, 49, 45, 86, 65, 83, 128, 65, 52, - 48, 49, 128, 65, 52, 48, 48, 45, 86, 65, 83, 128, 65, 52, 48, 48, 128, - 65, 51, 57, 57, 128, 65, 51, 57, 56, 128, 65, 51, 57, 55, 128, 65, 51, - 57, 54, 128, 65, 51, 57, 53, 128, 65, 51, 57, 52, 128, 65, 51, 57, 179, - 65, 51, 57, 50, 128, 65, 51, 57, 49, 128, 65, 51, 57, 48, 128, 65, 51, - 56, 57, 128, 65, 51, 56, 56, 128, 65, 51, 56, 55, 128, 65, 51, 56, 54, - 65, 128, 65, 51, 56, 54, 128, 65, 51, 56, 53, 128, 65, 51, 56, 52, 128, - 65, 51, 56, 51, 65, 128, 65, 51, 56, 179, 65, 51, 56, 50, 128, 65, 51, - 56, 49, 65, 128, 65, 51, 56, 49, 128, 65, 51, 56, 48, 128, 65, 51, 55, - 57, 128, 65, 51, 55, 56, 128, 65, 51, 55, 55, 128, 65, 51, 55, 54, 128, - 65, 51, 55, 53, 128, 65, 51, 55, 52, 128, 65, 51, 55, 51, 128, 65, 51, - 55, 50, 128, 65, 51, 55, 49, 65, 128, 65, 51, 55, 49, 128, 65, 51, 55, - 48, 128, 65, 51, 54, 57, 128, 65, 51, 54, 56, 65, 128, 65, 51, 54, 56, - 128, 65, 51, 54, 55, 128, 65, 51, 54, 54, 128, 65, 51, 54, 53, 128, 65, - 51, 54, 52, 65, 128, 65, 51, 54, 52, 128, 65, 51, 54, 51, 128, 65, 51, - 54, 50, 128, 65, 51, 54, 49, 128, 65, 51, 54, 48, 128, 65, 51, 53, 57, - 65, 128, 65, 51, 53, 57, 128, 65, 51, 53, 56, 128, 65, 51, 53, 55, 128, - 65, 51, 53, 54, 128, 65, 51, 53, 53, 128, 65, 51, 53, 52, 128, 65, 51, - 53, 51, 128, 65, 51, 53, 50, 128, 65, 51, 53, 49, 128, 65, 51, 53, 48, - 128, 65, 51, 52, 57, 128, 65, 51, 52, 56, 128, 65, 51, 52, 55, 128, 65, - 51, 52, 54, 128, 65, 51, 52, 53, 128, 65, 51, 52, 52, 128, 65, 51, 52, - 51, 128, 65, 51, 52, 50, 128, 65, 51, 52, 49, 128, 65, 51, 52, 48, 128, - 65, 51, 51, 57, 128, 65, 51, 51, 56, 128, 65, 51, 51, 55, 128, 65, 51, - 51, 54, 67, 128, 65, 51, 51, 54, 66, 128, 65, 51, 51, 54, 65, 128, 65, - 51, 51, 54, 128, 65, 51, 51, 53, 128, 65, 51, 51, 52, 128, 65, 51, 51, - 51, 128, 65, 51, 51, 50, 67, 128, 65, 51, 51, 50, 66, 128, 65, 51, 51, - 50, 65, 128, 65, 51, 51, 50, 128, 65, 51, 51, 49, 128, 65, 51, 51, 48, - 128, 65, 51, 50, 57, 65, 128, 65, 51, 50, 57, 128, 65, 51, 50, 56, 128, - 65, 51, 50, 55, 128, 65, 51, 50, 54, 128, 65, 51, 50, 53, 128, 65, 51, - 50, 52, 128, 65, 51, 50, 51, 128, 65, 51, 50, 50, 128, 65, 51, 50, 49, - 128, 65, 51, 50, 48, 128, 65, 51, 49, 57, 128, 65, 51, 49, 56, 128, 65, - 51, 49, 55, 128, 65, 51, 49, 54, 128, 65, 51, 49, 53, 128, 65, 51, 49, - 52, 128, 65, 51, 49, 51, 67, 128, 65, 51, 49, 51, 66, 128, 65, 51, 49, - 51, 65, 128, 65, 51, 49, 51, 128, 65, 51, 49, 50, 128, 65, 51, 49, 49, - 128, 65, 51, 49, 48, 128, 65, 51, 48, 57, 67, 128, 65, 51, 48, 57, 66, - 128, 65, 51, 48, 57, 65, 128, 65, 51, 48, 57, 128, 65, 51, 48, 56, 128, - 65, 51, 48, 55, 128, 65, 51, 48, 54, 128, 65, 51, 48, 53, 128, 65, 51, - 48, 52, 128, 65, 51, 48, 51, 128, 65, 51, 48, 50, 128, 65, 51, 48, 49, - 128, 65, 51, 48, 48, 128, 65, 50, 57, 57, 65, 128, 65, 50, 57, 57, 128, - 65, 50, 57, 56, 128, 65, 50, 57, 55, 128, 65, 50, 57, 54, 128, 65, 50, - 57, 53, 128, 65, 50, 57, 52, 65, 128, 65, 50, 57, 52, 128, 65, 50, 57, - 51, 128, 65, 50, 57, 50, 128, 65, 50, 57, 49, 128, 65, 50, 57, 48, 128, - 65, 50, 56, 57, 65, 128, 65, 50, 56, 57, 128, 65, 50, 56, 56, 128, 65, - 50, 56, 55, 128, 65, 50, 56, 54, 128, 65, 50, 56, 53, 128, 65, 50, 56, - 52, 128, 65, 50, 56, 51, 128, 65, 50, 56, 50, 128, 65, 50, 56, 49, 128, - 65, 50, 56, 48, 128, 65, 50, 55, 57, 128, 65, 50, 55, 56, 128, 65, 50, - 55, 55, 128, 65, 50, 55, 54, 128, 65, 50, 55, 53, 128, 65, 50, 55, 52, - 128, 65, 50, 55, 51, 128, 65, 50, 55, 50, 128, 65, 50, 55, 49, 128, 65, - 50, 55, 48, 128, 65, 50, 54, 57, 128, 65, 50, 54, 56, 128, 65, 50, 54, - 55, 65, 128, 65, 50, 54, 55, 128, 65, 50, 54, 54, 128, 65, 50, 54, 53, - 128, 65, 50, 54, 52, 128, 65, 50, 54, 51, 128, 65, 50, 54, 50, 128, 65, - 50, 54, 49, 128, 65, 50, 54, 48, 128, 65, 50, 53, 57, 128, 65, 50, 53, - 56, 128, 65, 50, 53, 55, 128, 65, 50, 53, 54, 128, 65, 50, 53, 53, 128, - 65, 50, 53, 52, 128, 65, 50, 53, 51, 128, 65, 50, 53, 50, 128, 65, 50, - 53, 49, 128, 65, 50, 53, 48, 128, 65, 50, 52, 57, 128, 65, 50, 52, 56, - 128, 65, 50, 52, 55, 128, 65, 50, 52, 54, 128, 65, 50, 52, 53, 128, 65, - 50, 52, 52, 128, 65, 50, 52, 51, 128, 65, 50, 52, 50, 128, 65, 50, 52, - 49, 128, 65, 50, 52, 48, 128, 65, 50, 51, 57, 128, 65, 50, 51, 56, 128, - 65, 50, 51, 55, 128, 65, 50, 51, 54, 128, 65, 50, 51, 53, 128, 65, 50, - 51, 52, 128, 65, 50, 51, 51, 128, 65, 50, 51, 50, 128, 65, 50, 51, 49, - 128, 65, 50, 51, 48, 128, 65, 50, 50, 57, 128, 65, 50, 50, 56, 128, 65, - 50, 50, 55, 65, 128, 65, 50, 50, 55, 128, 65, 50, 50, 54, 128, 65, 50, - 50, 53, 128, 65, 50, 50, 52, 128, 65, 50, 50, 51, 128, 65, 50, 50, 50, - 128, 65, 50, 50, 49, 128, 65, 50, 50, 48, 128, 65, 50, 49, 57, 128, 65, - 50, 49, 56, 128, 65, 50, 49, 55, 128, 65, 50, 49, 54, 65, 128, 65, 50, - 49, 54, 128, 65, 50, 49, 53, 65, 128, 65, 50, 49, 53, 128, 65, 50, 49, - 52, 128, 65, 50, 49, 51, 128, 65, 50, 49, 50, 128, 65, 50, 49, 49, 128, - 65, 50, 49, 48, 128, 65, 50, 48, 57, 65, 128, 65, 50, 48, 57, 128, 65, - 50, 48, 56, 128, 65, 50, 48, 55, 65, 128, 65, 50, 48, 55, 128, 65, 50, - 48, 54, 128, 65, 50, 48, 53, 128, 65, 50, 48, 52, 128, 65, 50, 48, 51, - 128, 65, 50, 48, 50, 66, 128, 65, 50, 48, 50, 65, 128, 65, 50, 48, 50, - 128, 65, 50, 48, 49, 128, 65, 50, 48, 48, 128, 65, 49, 57, 57, 128, 65, - 49, 57, 56, 128, 65, 49, 57, 55, 128, 65, 49, 57, 54, 128, 65, 49, 57, - 53, 128, 65, 49, 57, 52, 128, 65, 49, 57, 51, 128, 65, 49, 57, 50, 128, - 65, 49, 57, 49, 128, 65, 49, 57, 48, 128, 65, 49, 56, 57, 128, 65, 49, - 56, 56, 128, 65, 49, 56, 55, 128, 65, 49, 56, 54, 128, 65, 49, 56, 53, - 128, 65, 49, 56, 52, 128, 65, 49, 56, 51, 128, 65, 49, 56, 50, 128, 65, - 49, 56, 49, 128, 65, 49, 56, 48, 128, 65, 49, 55, 57, 128, 65, 49, 55, - 56, 128, 65, 49, 55, 55, 128, 65, 49, 55, 54, 128, 65, 49, 55, 53, 128, - 65, 49, 55, 52, 128, 65, 49, 55, 51, 128, 65, 49, 55, 50, 128, 65, 49, - 55, 49, 128, 65, 49, 55, 48, 128, 65, 49, 54, 57, 128, 65, 49, 54, 56, - 128, 65, 49, 54, 55, 128, 65, 49, 54, 54, 128, 65, 49, 54, 53, 128, 65, - 49, 54, 52, 128, 65, 49, 54, 51, 128, 65, 49, 54, 50, 128, 65, 49, 54, - 49, 128, 65, 49, 54, 48, 128, 65, 49, 53, 57, 128, 65, 49, 53, 56, 128, - 65, 49, 53, 55, 128, 65, 49, 53, 54, 128, 65, 49, 53, 53, 128, 65, 49, - 53, 52, 128, 65, 49, 53, 51, 128, 65, 49, 53, 50, 128, 65, 49, 53, 49, - 128, 65, 49, 53, 48, 128, 65, 49, 52, 57, 128, 65, 49, 52, 56, 128, 65, - 49, 52, 55, 128, 65, 49, 52, 54, 128, 65, 49, 52, 53, 128, 65, 49, 52, - 52, 128, 65, 49, 52, 51, 128, 65, 49, 52, 50, 128, 65, 49, 52, 49, 128, - 65, 49, 52, 48, 128, 65, 49, 51, 57, 128, 65, 49, 51, 56, 128, 65, 49, - 51, 55, 128, 65, 49, 51, 54, 128, 65, 49, 51, 53, 65, 128, 65, 49, 51, - 53, 128, 65, 49, 51, 52, 128, 65, 49, 51, 51, 128, 65, 49, 51, 50, 128, - 65, 49, 51, 49, 67, 128, 65, 49, 51, 49, 128, 65, 49, 51, 48, 128, 65, - 49, 50, 57, 128, 65, 49, 50, 56, 128, 65, 49, 50, 55, 128, 65, 49, 50, - 54, 128, 65, 49, 50, 53, 65, 128, 65, 49, 50, 53, 128, 65, 49, 50, 52, - 128, 65, 49, 50, 51, 128, 65, 49, 50, 50, 128, 65, 49, 50, 49, 128, 65, - 49, 50, 48, 66, 128, 65, 49, 50, 48, 128, 65, 49, 49, 57, 128, 65, 49, - 49, 56, 128, 65, 49, 49, 55, 128, 65, 49, 49, 54, 128, 65, 49, 49, 53, - 65, 128, 65, 49, 49, 53, 128, 65, 49, 49, 52, 128, 65, 49, 49, 51, 128, - 65, 49, 49, 50, 128, 65, 49, 49, 49, 128, 65, 49, 49, 48, 66, 128, 65, - 49, 49, 48, 65, 128, 65, 49, 49, 48, 128, 65, 49, 48, 57, 128, 65, 49, - 48, 56, 128, 65, 49, 48, 55, 67, 128, 65, 49, 48, 55, 66, 128, 65, 49, - 48, 55, 65, 128, 65, 49, 48, 55, 128, 65, 49, 48, 54, 128, 65, 49, 48, - 53, 66, 128, 65, 49, 48, 53, 65, 128, 65, 49, 48, 53, 128, 65, 49, 48, - 52, 67, 128, 65, 49, 48, 52, 66, 128, 65, 49, 48, 52, 65, 128, 65, 49, - 48, 52, 128, 65, 49, 48, 51, 128, 65, 49, 48, 50, 65, 128, 65, 49, 48, - 50, 128, 65, 49, 48, 49, 65, 128, 65, 49, 48, 49, 128, 65, 49, 48, 48, - 65, 128, 65, 49, 48, 48, 45, 49, 48, 50, 128, 65, 49, 48, 48, 128, 65, - 48, 57, 57, 128, 65, 48, 57, 56, 65, 128, 65, 48, 57, 56, 128, 65, 48, - 57, 55, 65, 128, 65, 48, 57, 55, 128, 65, 48, 57, 54, 128, 65, 48, 57, - 53, 128, 65, 48, 57, 52, 128, 65, 48, 57, 51, 128, 65, 48, 57, 50, 128, - 65, 48, 57, 49, 128, 65, 48, 57, 48, 128, 65, 48, 56, 57, 128, 65, 48, - 56, 56, 128, 65, 48, 56, 55, 128, 65, 48, 56, 54, 128, 65, 48, 56, 53, - 128, 65, 48, 56, 52, 128, 65, 48, 56, 51, 128, 65, 48, 56, 50, 128, 65, - 48, 56, 49, 128, 65, 48, 56, 48, 128, 65, 48, 55, 57, 128, 65, 48, 55, - 56, 128, 65, 48, 55, 55, 128, 65, 48, 55, 54, 128, 65, 48, 55, 53, 128, - 65, 48, 55, 52, 128, 65, 48, 55, 51, 128, 65, 48, 55, 50, 128, 65, 48, - 55, 49, 128, 65, 48, 55, 48, 128, 65, 48, 54, 57, 128, 65, 48, 54, 56, - 128, 65, 48, 54, 55, 128, 65, 48, 54, 54, 67, 128, 65, 48, 54, 54, 66, - 128, 65, 48, 54, 54, 65, 128, 65, 48, 54, 54, 128, 65, 48, 54, 53, 128, - 65, 48, 54, 52, 128, 65, 48, 54, 51, 128, 65, 48, 54, 50, 128, 65, 48, - 54, 49, 128, 65, 48, 54, 48, 128, 65, 48, 53, 57, 128, 65, 48, 53, 56, - 128, 65, 48, 53, 55, 128, 65, 48, 53, 54, 128, 65, 48, 53, 53, 128, 65, - 48, 53, 52, 128, 65, 48, 53, 51, 128, 65, 48, 53, 50, 128, 65, 48, 53, - 49, 128, 65, 48, 53, 48, 128, 65, 48, 52, 57, 128, 65, 48, 52, 56, 128, - 65, 48, 52, 55, 128, 65, 48, 52, 54, 66, 128, 65, 48, 52, 54, 65, 128, - 65, 48, 52, 54, 128, 65, 48, 52, 53, 65, 128, 65, 48, 52, 53, 128, 65, - 48, 52, 52, 128, 65, 48, 52, 51, 65, 128, 65, 48, 52, 51, 128, 65, 48, - 52, 50, 65, 128, 65, 48, 52, 50, 128, 65, 48, 52, 49, 65, 128, 65, 48, - 52, 49, 128, 65, 48, 52, 48, 65, 128, 65, 48, 52, 48, 128, 65, 48, 51, - 57, 65, 128, 65, 48, 51, 57, 128, 65, 48, 51, 56, 128, 65, 48, 51, 55, - 128, 65, 48, 51, 54, 128, 65, 48, 51, 53, 128, 65, 48, 51, 52, 128, 65, - 48, 51, 51, 128, 65, 48, 51, 50, 65, 128, 65, 48, 50, 56, 66, 128, 65, - 48, 50, 54, 65, 128, 65, 48, 49, 55, 65, 128, 65, 48, 49, 52, 65, 128, - 65, 48, 49, 48, 65, 128, 65, 48, 48, 54, 66, 128, 65, 48, 48, 54, 65, - 128, 65, 48, 48, 53, 65, 128, 65, 45, 87, 79, 128, 65, 45, 69, 85, 128, - 45, 85, 205, 45, 80, 72, 82, 85, 128, 45, 75, 72, 89, 85, 196, 45, 75, - 72, 89, 73, 76, 128, 45, 68, 90, 85, 196, 45, 67, 72, 65, 210, 45, 67, - 72, 65, 76, 128, -}; - -static const unsigned int lexicon_offset[] = { - 0, 0, 6, 11, 15, 19, 27, 34, 44, 49, 55, 64, 66, 69, 81, 89, 102, 108, - 113, 118, 124, 129, 137, 146, 149, 160, 165, 170, 176, 180, 189, 195, - 201, 207, 216, 224, 229, 237, 244, 177, 252, 255, 261, 262, 268, 273, - 277, 282, 289, 296, 306, 311, 317, 325, 330, 333, 339, 344, 350, 356, - 359, 365, 375, 380, 385, 390, 392, 394, 403, 405, 412, 354, 419, 427, - 436, 438, 441, 449, 454, 455, 457, 464, 472, 478, 484, 491, 496, 503, - 507, 512, 519, 524, 527, 531, 536, 542, 547, 557, 565, 572, 575, 585, - 593, 598, 606, 615, 618, 625, 629, 633, 637, 642, 645, 652, 659, 666, - 671, 676, 683, 692, 694, 703, 707, 715, 719, 727, 281, 736, 749, 753, - 758, 761, 765, 769, 771, 776, 786, 792, 796, 802, 806, 809, 814, 823, - 828, 832, 774, 838, 846, 854, 859, 868, 877, 885, 891, 902, 905, 910, - 918, 925, 928, 938, 943, 949, 953, 957, 960, 967, 974, 977, 981, 984, - 657, 990, 993, 996, 1002, 1007, 1016, 1021, 1025, 1028, 1032, 1035, 1041, - 1046, 1050, 617, 1055, 1058, 1067, 1070, 1075, 1080, 1086, 1091, 1096, - 1101, 1105, 1110, 1116, 1121, 1126, 1130, 1136, 1141, 1146, 1151, 1155, - 1160, 1165, 1170, 1176, 1182, 1188, 1193, 1197, 1202, 1207, 1212, 1216, - 1221, 1226, 1231, 1236, 1071, 1076, 1081, 1087, 1092, 1240, 1102, 1246, - 1251, 1256, 1263, 1267, 1270, 1279, 1106, 1283, 1111, 1117, 1122, 1287, - 1292, 1297, 1301, 1305, 1311, 1315, 1127, 1318, 1320, 1137, 1325, 1329, - 1142, 1335, 1147, 1339, 1343, 1350, 1152, 1354, 1362, 1367, 1371, 1374, - 1378, 1156, 1161, 1383, 1389, 1166, 1401, 1407, 1413, 1419, 1171, 1183, - 1189, 1423, 1427, 1431, 1434, 1194, 1438, 1440, 1445, 1450, 1456, 1461, - 1466, 1470, 1475, 1480, 1485, 1490, 1496, 1501, 1506, 1512, 1518, 1523, - 1527, 1532, 1537, 1542, 1547, 1552, 1556, 1564, 1569, 1573, 1578, 1583, - 1588, 1593, 1597, 1600, 1607, 1612, 1617, 1622, 1627, 1633, 1638, 1642, - 1198, 1645, 1651, 1656, 1661, 1666, 1203, 1670, 1674, 1681, 1688, 1208, - 1693, 1698, 1213, 1702, 1704, 1709, 1720, 1726, 1217, 1731, 1740, 1222, - 1745, 1751, 1756, 1761, 1771, 1780, 1788, 1227, 1798, 1807, 1816, 1821, - 1825, 1828, 1837, 1847, 1856, 1861, 1865, 1869, 1873, 1876, 1880, 1885, - 1232, 1895, 1237, 1899, 1901, 1907, 1913, 1919, 1925, 1931, 1937, 1943, - 1949, 1954, 1960, 1966, 1972, 1978, 1984, 1990, 1996, 2002, 2008, 2013, - 2018, 2023, 2028, 2033, 2038, 2043, 2048, 2053, 2058, 2064, 2069, 2075, - 2080, 2086, 2092, 2097, 2103, 2109, 2115, 2121, 2126, 2131, 2133, 2134, - 2138, 2142, 2147, 2151, 2155, 2159, 2164, 2168, 2171, 2176, 2180, 2185, - 2189, 2193, 2198, 2202, 2205, 2209, 2215, 2229, 2233, 2237, 2241, 2244, - 2249, 2253, 2257, 2260, 2264, 2269, 2274, 2279, 2284, 2288, 2292, 2296, - 2300, 2304, 2309, 2313, 2318, 2322, 2327, 2333, 2340, 2346, 2351, 2356, - 2361, 2367, 2372, 2378, 2383, 2388, 2393, 2398, 2403, 2406, 2408, 1088, - 2412, 2419, 2427, 2437, 2446, 2460, 2464, 2468, 2473, 2486, 2494, 2497, - 2501, 2504, 2509, 2513, 2516, 2520, 2524, 2529, 1715, 2534, 2538, 2541, - 2545, 2551, 2558, 2565, 2571, 2576, 2581, 2587, 2593, 2598, 2603, 2608, - 2613, 2618, 2623, 2548, 2628, 1706, 2630, 2636, 2640, 2645, 2649, 2653, - 1603, 1728, 2658, 2662, 2666, 2669, 2674, 2679, 2684, 2689, 2693, 2700, - 2705, 2708, 2712, 2716, 2723, 2729, 2733, 2739, 2743, 2747, 2752, 2759, - 2764, 2769, 2776, 2782, 2788, 2794, 2815, 2829, 2846, 2861, 2877, 2894, - 2909, 2918, 2923, 2927, 2932, 2937, 2941, 2953, 2960, 2966, 2336, 2972, - 2979, 2985, 2989, 2992, 2999, 3005, 3010, 3014, 3019, 3023, 3027, 2156, - 3031, 3036, 3041, 3045, 3050, 3058, 3062, 3069, 3074, 3078, 3082, 3086, - 3091, 3096, 3101, 3105, 3110, 3115, 3119, 3124, 3129, 3133, 3136, 3140, - 3144, 3152, 3157, 3161, 3165, 3171, 3180, 3184, 3188, 3194, 3199, 3206, - 3210, 3220, 3224, 3228, 3233, 3237, 3242, 3248, 3253, 3257, 3261, 3265, - 2561, 3273, 3278, 3284, 3289, 3293, 3298, 3303, 3307, 3313, 3318, 2160, - 3324, 3330, 3335, 3340, 3345, 3350, 3355, 3360, 3365, 3370, 3375, 3380, - 3385, 3390, 3395, 3400, 3406, 3411, 1103, 101, 3417, 3421, 3425, 3429, - 3434, 3438, 3442, 3448, 3453, 3457, 3461, 3466, 3471, 3475, 3480, 3484, - 3487, 3491, 3496, 3500, 3505, 3509, 3512, 3514, 3518, 3522, 3527, 3531, - 3534, 3547, 3551, 3555, 3559, 3564, 3568, 3572, 3575, 3579, 3583, 3588, - 3592, 3597, 3602, 3607, 3611, 3618, 3623, 3626, 3632, 3635, 3640, 3646, - 3650, 3654, 3657, 3662, 3666, 3671, 3675, 3679, 3682, 3688, 3693, 3698, - 3704, 3709, 3714, 3720, 3726, 3731, 3736, 3741, 3746, 3749, 979, 644, - 3755, 3758, 3763, 3767, 3771, 3775, 3779, 3782, 3786, 3791, 3796, 3800, - 3805, 3809, 3814, 3818, 3822, 3826, 3832, 3838, 3841, 3844, 153, 3850, - 3855, 3864, 3872, 3881, 3891, 3898, 3904, 3911, 3916, 3920, 3924, 3932, - 3939, 3944, 3949, 3956, 3961, 3965, 3975, 3979, 3983, 3988, 3993, 4003, - 2172, 4008, 4012, 4015, 4021, 4026, 4032, 4038, 4043, 4050, 4054, 4058, - 4062, 4067, 4072, 4077, 4082, 4087, 4092, 634, 616, 1264, 4097, 4104, - 4111, 4117, 4126, 4131, 4138, 4145, 4150, 4156, 4162, 4167, 4172, 4176, - 4182, 4189, 4194, 4198, 4202, 2181, 4208, 4216, 4222, 4230, 863, 4236, - 4244, 4255, 4259, 4269, 4275, 4280, 4285, 4290, 4295, 2186, 4300, 4305, - 4320, 4326, 4333, 4344, 4354, 4360, 4365, 4371, 4377, 4380, 4383, 4387, - 4392, 4395, 4402, 4411, 4416, 4420, 4424, 4428, 4432, 4437, 4443, 4454, - 4458, 3492, 4463, 4475, 4481, 4489, 4493, 4498, 4505, 4510, 4515, 4520, - 1472, 4525, 4528, 4531, 4535, 4538, 4544, 4548, 4562, 4566, 4569, 4573, - 4579, 4585, 4590, 4594, 4598, 4604, 4615, 4621, 4626, 4632, 4636, 4644, - 4656, 4666, 4672, 4677, 4686, 4694, 4705, 4712, 4718, 4724, 4728, 4734, - 4743, 4752, 4757, 4763, 4767, 4776, 4782, 4787, 4791, 4796, 4800, 4808, - 4814, 4818, 4825, 4830, 4834, 4840, 4846, 4853, 2194, 4862, 4873, 4883, - 4892, 4897, 4902, 4907, 4912, 1280, 4917, 4919, 4924, 4930, 4935, 4940, - 4945, 4950, 4955, 4960, 4966, 4971, 4977, 4982, 4987, 4992, 4998, 5003, - 5008, 5013, 5018, 5024, 5029, 5035, 5040, 5045, 5050, 5055, 5060, 5065, - 5071, 5076, 5081, 348, 389, 5086, 5092, 5095, 5099, 5103, 5110, 5116, - 5121, 5125, 5129, 5132, 5135, 5139, 5143, 5146, 5150, 5154, 5158, 5163, - 5167, 5171, 5177, 5186, 4843, 5191, 5195, 5198, 5203, 5208, 5213, 5218, - 5223, 5228, 5233, 5238, 5243, 5248, 5252, 5257, 5262, 5267, 5272, 5277, - 5282, 5287, 5292, 5297, 5302, 5306, 5311, 5316, 5321, 5326, 5331, 5336, - 5341, 5346, 5351, 5356, 5360, 5365, 5370, 5375, 5380, 5385, 5390, 5395, - 5400, 5405, 5410, 5414, 5419, 5424, 5429, 5434, 5439, 5444, 5449, 5454, - 5459, 5464, 5468, 5473, 5478, 5483, 5488, 5493, 5498, 5503, 5508, 5513, - 5518, 5522, 5527, 5532, 5537, 5542, 5547, 5552, 5557, 5562, 5567, 5572, - 5576, 5581, 5586, 5591, 5596, 5602, 5608, 5614, 5620, 5626, 5632, 5638, - 5643, 5649, 5655, 5661, 5667, 5673, 5679, 5685, 5691, 5697, 5703, 5708, - 5714, 5720, 5726, 5732, 5738, 5744, 5750, 5756, 5762, 5768, 5773, 5779, - 5785, 5791, 5797, 5803, 5809, 5815, 5821, 5827, 5833, 5838, 5844, 5850, - 5856, 5862, 5868, 5874, 5880, 5886, 5892, 5898, 5903, 5909, 5915, 5921, - 5927, 5933, 5939, 5945, 5951, 5957, 5963, 5968, 5972, 5978, 5984, 5990, - 5996, 6002, 6008, 6014, 6020, 6026, 6032, 6037, 6043, 6049, 6055, 6061, - 6067, 6073, 6079, 6085, 6091, 6097, 6102, 6108, 6114, 6120, 6126, 6132, - 6138, 6144, 6150, 6156, 6162, 6167, 6173, 6179, 6185, 6191, 6197, 6203, - 6209, 6215, 6221, 6227, 6232, 6238, 6244, 6250, 6256, 6262, 6268, 6274, - 6280, 6286, 6292, 6297, 6303, 6309, 6315, 6321, 6327, 6333, 6339, 6345, - 6351, 6357, 6362, 6368, 6374, 6380, 6386, 6392, 6398, 6404, 6410, 6416, - 6422, 6427, 6433, 6439, 6445, 6451, 6457, 6463, 6469, 6475, 6481, 6487, - 6492, 6498, 6504, 6510, 6516, 6522, 6528, 6534, 6540, 6546, 6552, 6557, - 6563, 6569, 6575, 6581, 6587, 6593, 6599, 6605, 6611, 6617, 6622, 6626, - 6629, 6637, 6644, 6647, 6651, 6664, 6668, 6672, 6676, 6679, 6683, 6688, - 6692, 6701, 6705, 6711, 6718, 6729, 6737, 6744, 6750, 6754, 6762, 6771, - 6777, 6781, 6793, 6798, 6801, 6806, 6810, 6820, 6828, 6836, 6844, 6850, - 6854, 6864, 6874, 6882, 6889, 6896, 6902, 6908, 6915, 6919, 6926, 6936, - 6946, 6954, 6961, 6966, 6970, 6974, 6982, 6986, 6996, 7001, 7008, 7015, - 7023, 7033, 7038, 7042, 7047, 7051, 7058, 7063, 7077, 7082, 7087, 7094, - 3768, 7103, 7107, 7111, 7116, 7120, 7124, 7127, 7132, 7137, 7146, 7152, - 7158, 7163, 7169, 7173, 7184, 7194, 7209, 7224, 7239, 7254, 7269, 7284, - 7299, 7314, 7329, 7344, 7359, 7374, 7389, 7404, 7419, 7434, 7449, 7464, - 7479, 7494, 7509, 7524, 7539, 7554, 7569, 7584, 7599, 7614, 7629, 7644, - 7659, 7674, 7689, 7704, 7719, 7734, 7749, 7764, 7779, 7794, 7809, 7824, - 7839, 7854, 7869, 7884, 7899, 7914, 7929, 7938, 7947, 7952, 7958, 7968, - 7972, 7976, 7981, 7986, 7991, 7999, 8003, 8006, 8010, 3215, 8013, 8018, - 353, 534, 8024, 8027, 8035, 8039, 8043, 8046, 8050, 8056, 8060, 8068, - 8074, 8079, 8086, 8094, 8101, 8107, 8112, 8119, 8125, 8134, 8142, 8146, - 8151, 8159, 8171, 8182, 8189, 8200, 8204, 8208, 8212, 8215, 8221, 3519, - 8225, 8227, 8233, 8238, 8243, 8248, 8254, 8259, 8264, 8269, 8274, 8280, - 8285, 8290, 8296, 8301, 8307, 8312, 8318, 8323, 8329, 8334, 8339, 8344, - 8349, 8354, 8360, 8365, 8370, 8375, 8381, 8387, 8393, 8399, 8405, 8411, - 8417, 8423, 8429, 8435, 8441, 8447, 8452, 8457, 8462, 8467, 8472, 8477, - 8482, 8487, 8493, 8499, 8504, 8510, 8516, 8522, 8528, 8533, 8538, 8543, - 8548, 8554, 8560, 8565, 8570, 8575, 8580, 8585, 8591, 8596, 8602, 8608, - 8614, 8620, 8626, 8632, 8638, 8644, 8650, 2203, 8045, 8655, 8659, 8667, - 8671, 8674, 8677, 8683, 8690, 1107, 8693, 8697, 8705, 8710, 8715, 8706, - 8720, 2230, 8724, 8730, 8736, 8741, 8746, 8753, 8761, 8766, 8770, 8773, - 8777, 8783, 8789, 8793, 1653, 631, 8796, 8800, 8805, 8811, 8816, 8820, - 8823, 8827, 8833, 8838, 8842, 8849, 8853, 8857, 8861, 773, 8681, 2254, - 8864, 8872, 8879, 8886, 8892, 8899, 8907, 8914, 8925, 8932, 8938, 8950, - 1123, 1288, 1293, 8961, 8965, 1298, 8969, 8973, 8982, 8990, 8994, 9003, - 9009, 9015, 9020, 9024, 9030, 9035, 9043, 9050, 2914, 9057, 9063, 9067, - 9076, 9085, 9094, 9103, 9109, 9114, 9119, 9130, 9139, 9151, 9156, 9164, - 2289, 9168, 9170, 9175, 9179, 9188, 9196, 1302, 168, 3810, 3815, 9202, - 9206, 9215, 9221, 9226, 9229, 9233, 9237, 9242, 9247, 9252, 9257, 9261, - 9270, 9276, 2301, 9280, 2906, 9284, 9292, 9296, 9300, 2305, 9304, 9308, - 9312, 9316, 9320, 2310, 9324, 9329, 9336, 9342, 9349, 9355, 9358, 9254, - 9360, 9368, 9376, 9384, 9387, 9392, 2323, 9397, 8717, 9400, 9402, 9407, - 9412, 9417, 9422, 9427, 9432, 9437, 9442, 9447, 9452, 9458, 9463, 9468, - 9473, 9479, 9484, 9489, 9494, 9499, 9504, 9509, 9515, 9520, 9525, 9530, - 9535, 9540, 9545, 9550, 9555, 9560, 9565, 9570, 9575, 9580, 9585, 9590, - 9595, 9600, 9606, 9612, 9617, 9622, 9627, 9632, 9637, 2334, 2341, 2347, - 9642, 9650, 9656, 9664, 2373, 2379, 9672, 2384, 2389, 2394, 2399, 9676, - 9680, 9685, 9689, 9693, 9697, 9702, 9706, 9711, 9715, 9718, 9721, 9727, - 9734, 9740, 9747, 9753, 9760, 9766, 9773, 9779, 9785, 9794, 9800, 9804, - 9808, 9812, 9816, 9821, 9825, 9830, 9834, 9840, 9844, 9849, 9856, 9867, - 9875, 9885, 9891, 9901, 9910, 9917, 9922, 9926, 9937, 9947, 9960, 9971, - 9984, 9995, 10007, 10019, 10031, 10042, 10055, 10068, 10075, 10081, - 10092, 10102, 10116, 10123, 10129, 10138, 10146, 10150, 10155, 10159, - 10166, 10174, 10181, 10185, 10191, 10195, 10201, 10211, 10215, 10220, - 10225, 10232, 10238, 8894, 10248, 10252, 10259, 10265, 10272, 10279, - 10283, 10286, 10292, 10296, 10301, 10306, 10311, 10315, 10321, 10329, - 10336, 10342, 10346, 10349, 10355, 10365, 10369, 10375, 10380, 10384, - 10389, 10393, 10399, 10405, 10410, 10416, 10421, 10426, 10431, 2226, - 10436, 10438, 10443, 10451, 10460, 10464, 10470, 10475, 10480, 10485, - 10490, 10496, 10501, 10506, 4600, 10511, 10516, 10520, 10526, 10531, - 10537, 10542, 10547, 10553, 10558, 10465, 10564, 10568, 10575, 10581, - 10586, 10590, 7073, 10595, 10604, 10609, 10614, 9332, 9339, 10619, 3088, - 10623, 10628, 10633, 10638, 10476, 10642, 10647, 10652, 10481, 10656, - 10486, 10661, 10668, 10675, 10681, 10688, 10694, 10700, 10705, 10712, - 10717, 10722, 10727, 10733, 10491, 10497, 10739, 10744, 10750, 10755, - 10760, 10768, 1358, 10773, 1048, 10776, 10784, 10800, 10816, 10831, - 10839, 10845, 10851, 10860, 10868, 10876, 10884, 10892, 10900, 10908, - 10916, 10924, 10933, 10942, 10950, 10959, 10968, 10977, 10986, 10995, - 11004, 11013, 11022, 11031, 11040, 11048, 11053, 11057, 11063, 11071, - 11078, 11093, 11110, 11129, 11138, 11146, 11161, 11172, 11180, 11186, - 11196, 11206, 11214, 11220, 11232, 11241, 11249, 11256, 11263, 11270, - 11276, 11281, 11291, 11297, 11305, 11315, 11322, 11332, 11342, 11352, - 11360, 11367, 11376, 11386, 11400, 11415, 11424, 11432, 11437, 11441, - 11451, 11461, 11473, 11482, 11488, 11493, 11503, 11513, 11523, 11528, - 11532, 11542, 11551, 11556, 11572, 11589, 11599, 11604, 11615, 11628, - 11639, 11647, 11660, 11672, 11680, 11685, 11689, 11695, 11700, 11708, - 11716, 11723, 11734, 11739, 11747, 11757, 11763, 11767, 11770, 11776, - 11780, 11786, 11793, 11797, 11805, 11814, 11822, 11829, 11834, 11838, - 11843, 11847, 11851, 11859, 11874, 11890, 11896, 11904, 11913, 11921, - 11927, 11931, 11938, 11949, 11953, 11956, 11967, 11973, 11978, 10507, - 11986, 11992, 11999, 12005, 12010, 12017, 12024, 12031, 12038, 12045, - 12052, 12059, 12066, 12073, 12080, 12087, 12094, 12101, 12108, 12115, - 12120, 11106, 12125, 12131, 12138, 12145, 12150, 12157, 12166, 12170, - 12177, 12189, 12193, 12199, 12204, 12209, 12214, 12219, 12224, 12229, - 12232, 12236, 11457, 12240, 12244, 12250, 12256, 12261, 12267, 12272, - 12277, 12283, 12288, 12293, 10228, 12298, 12302, 12306, 12310, 12315, - 12320, 12325, 12333, 12339, 12344, 12348, 12352, 12359, 12364, 12372, - 12379, 12384, 12388, 12391, 12397, 12404, 12408, 12411, 12416, 12420, - 4639, 12426, 12435, 46, 12443, 12449, 12454, 12459, 12467, 12474, 12479, - 6991, 12485, 12491, 12496, 12500, 12503, 12509, 12517, 12524, 12539, - 12558, 12570, 12583, 12596, 12609, 12623, 12636, 12651, 12658, 10512, - 12664, 12678, 12683, 12689, 12694, 12702, 12707, 9072, 12712, 12715, - 12723, 12730, 12735, 12739, 12745, 12749, 12754, 12759, 12764, 12769, - 12774, 12779, 3093, 11194, 12784, 12788, 12794, 12800, 12805, 12811, - 12816, 10521, 12822, 12828, 12833, 12838, 12846, 12852, 12865, 12873, - 12880, 12886, 10527, 12892, 12900, 12908, 12915, 12928, 12941, 12953, - 12963, 12975, 13003, 13011, 13020, 13027, 13039, 13046, 13056, 13065, - 13073, 13080, 13085, 13091, 10532, 13096, 13102, 13107, 13112, 13117, - 10538, 13122, 13125, 13132, 13138, 13152, 13165, 13176, 9860, 13187, - 13193, 13202, 13210, 13217, 13223, 13234, 13240, 13245, 13253, 4113, - 13259, 13264, 12531, 13270, 13277, 13282, 10543, 13288, 13293, 13300, - 13306, 13312, 13317, 13325, 13333, 13340, 13344, 13356, 13370, 13380, - 13385, 13389, 13400, 13406, 13411, 13416, 10548, 13420, 10554, 13425, - 13428, 13433, 13445, 13452, 13457, 13461, 13469, 13474, 13478, 13483, - 13487, 13494, 13500, 10559, 10466, 13507, 3098, 17, 13514, 13519, 13523, - 13527, 13533, 13541, 13551, 13556, 13561, 13568, 13575, 13579, 13590, - 13600, 13609, 13618, 13630, 13635, 13639, 13647, 13661, 13665, 13668, - 13672, 13680, 13687, 13695, 13699, 13710, 13718, 13722, 13729, 13734, - 13738, 13744, 13749, 13755, 13760, 13765, 13769, 13775, 13780, 13791, - 13795, 13798, 13804, 13811, 13817, 13822, 13828, 13834, 13841, 13852, - 13862, 13872, 13881, 13888, 13897, 13901, 10569, 10576, 10582, 10587, - 13907, 13913, 13919, 13924, 13930, 10591, 13936, 13939, 13946, 13951, - 13957, 13962, 13977, 13993, 14008, 14016, 14021, 14028, 14034, 14038, - 14043, 14048, 14053, 14058, 14063, 14068, 14073, 14078, 14083, 1561, 383, - 14088, 14096, 14103, 14109, 14114, 14119, 10596, 14121, 14125, 14130, - 14134, 14144, 14149, 14153, 14156, 14165, 14169, 14172, 14179, 10605, - 14184, 14187, 14195, 14202, 14210, 14214, 14220, 14228, 14232, 14239, - 14248, 14255, 14251, 14262, 14266, 14272, 14276, 14280, 14284, 14290, - 14296, 14306, 14314, 14321, 14325, 14333, 14338, 14342, 14349, 14354, - 14361, 14365, 14370, 14375, 14379, 14386, 14392, 14400, 14406, 14411, - 14421, 14428, 14433, 14438, 14442, 14446, 14454, 4469, 14462, 14467, - 10610, 14471, 14478, 14482, 14485, 14493, 14500, 14504, 14507, 6846, - 14511, 14516, 14521, 14525, 14536, 14546, 14551, 14557, 14562, 14571, - 14575, 14578, 14586, 14591, 14596, 14603, 14608, 4865, 10615, 14613, - 14617, 14624, 14629, 14634, 14639, 7021, 14644, 14649, 14654, 14659, - 14665, 14670, 14676, 14681, 14686, 14691, 14696, 14701, 14706, 14711, - 14716, 14721, 14726, 14731, 14736, 14741, 14746, 14751, 14756, 14762, - 14767, 14772, 14777, 14782, 14787, 14793, 14798, 14803, 14809, 14814, - 14820, 14825, 14831, 14836, 14841, 14846, 14851, 14857, 14862, 14867, - 14872, 14880, 988, 112, 14886, 14890, 14895, 14900, 14904, 14908, 14912, - 14917, 14921, 14926, 14930, 14933, 14937, 14941, 14947, 14952, 14962, - 14968, 14976, 14982, 14986, 14990, 14997, 15005, 15014, 15025, 15035, - 15042, 15049, 15053, 15062, 15071, 15079, 15086, 15095, 15104, 15113, - 15122, 15132, 15142, 15152, 15162, 15172, 15181, 15191, 15201, 15211, - 15221, 15231, 15241, 15251, 15260, 15270, 15280, 15290, 15300, 15310, - 15320, 15329, 15339, 15349, 15359, 15369, 15379, 15389, 15399, 15409, - 15419, 15428, 15438, 15448, 15458, 15468, 15478, 15488, 15498, 15508, - 15518, 15528, 15537, 15543, 1132, 15547, 15550, 15554, 15559, 15566, - 15572, 15577, 15581, 15586, 15595, 15604, 15612, 15617, 15621, 15625, - 15631, 15636, 15642, 10624, 15647, 15652, 15661, 15666, 10634, 15671, - 11444, 11454, 11464, 15674, 15680, 15688, 10639, 15695, 15699, 15703, - 15709, 15714, 15718, 15728, 15734, 15740, 15745, 15754, 15762, 15769, - 15776, 15781, 15788, 15793, 15797, 15800, 15811, 15821, 15834, 15843, - 15851, 15862, 15874, 15884, 15894, 15899, 15903, 15908, 15913, 15917, - 15923, 15931, 15938, 15949, 15954, 15964, 15973, 15977, 15980, 15987, - 15997, 16006, 16013, 16017, 16024, 16030, 16035, 16040, 16044, 15590, - 16053, 16057, 16063, 16067, 16072, 16076, 16083, 16090, 16094, 16103, - 16111, 16119, 16126, 16134, 16146, 16157, 16167, 16174, 16180, 16189, - 16200, 16209, 16221, 16233, 16245, 16255, 16264, 16274, 16283, 16291, - 16298, 16308, 16317, 16325, 16329, 16334, 16340, 16346, 16351, 16356, - 16360, 16365, 16370, 16375, 16380, 16385, 16390, 16395, 8738, 16400, - 16402, 16406, 16411, 16417, 16424, 16430, 16436, 16445, 16449, 16455, - 16463, 16470, 16479, 16488, 16497, 16506, 16515, 16524, 16533, 16542, - 16552, 16562, 16571, 16577, 16584, 16591, 16597, 16611, 16617, 16624, - 16632, 16641, 16649, 16655, 16664, 16670, 16679, 16690, 16696, 16706, - 16714, 16721, 16729, 16737, 16744, 16753, 16766, 16775, 16783, 16790, - 16803, 16809, 16815, 16825, 16834, 16843, 16852, 16860, 16865, 16869, - 16875, 16881, 16886, 16893, 16900, 10242, 16905, 16910, 16917, 16925, - 16930, 16942, 16949, 16954, 16966, 14943, 16971, 16977, 16985, 16991, - 16996, 17004, 17012, 17019, 17027, 17034, 17040, 17046, 17054, 17062, - 17068, 17076, 17082, 17087, 17093, 17100, 17106, 17111, 17115, 17126, - 17134, 17142, 17148, 17153, 17160, 17169, 17175, 17180, 17188, 17195, - 17204, 17218, 4413, 17222, 17227, 17232, 17238, 17243, 17248, 17252, - 17257, 17262, 17267, 8737, 17272, 17277, 17282, 17287, 17292, 17296, - 17301, 17306, 17311, 17316, 17322, 17328, 14216, 17333, 17339, 17344, - 17349, 17354, 10643, 17359, 17364, 17369, 17374, 17379, 17393, 17410, - 17428, 17440, 17453, 17470, 17486, 17503, 17513, 17532, 17543, 17554, - 17565, 2803, 17576, 17587, 17598, 17615, 17626, 17637, 17642, 10648, - 17647, 17651, 2483, 17655, 17661, 17664, 17670, 17678, 17686, 17692, - 17701, 17708, 17713, 17721, 17729, 17736, 17740, 17745, 17751, 17758, - 17766, 17773, 17785, 17792, 17798, 17806, 17811, 17817, 17823, 17828, - 13971, 17835, 17839, 17848, 17854, 17859, 17867, 17876, 17884, 17891, - 17897, 17905, 17912, 17918, 17924, 17931, 17938, 17944, 17950, 17954, - 17963, 17971, 17976, 17986, 17993, 17999, 18007, 18013, 18021, 18029, - 18036, 18049, 18053, 18060, 18069, 18078, 18087, 18095, 18105, 18112, - 18117, 3969, 18124, 18129, 1248, 18133, 18140, 17273, 18144, 18150, - 18154, 18162, 18174, 18179, 18186, 18192, 18197, 18204, 17278, 18208, - 18212, 18220, 18225, 18229, 17283, 18233, 17288, 18237, 18244, 18249, - 18253, 18260, 18264, 18267, 18275, 18282, 18287, 18295, 18299, 18306, - 18323, 18332, 18341, 18345, 18348, 18354, 18362, 18368, 18373, 18377, - 18382, 18387, 18392, 18397, 18402, 18407, 4047, 18412, 18414, 18422, - 18429, 18439, 18451, 18456, 18460, 18466, 18471, 18479, 18483, 18489, - 18494, 18500, 18503, 18510, 18518, 18525, 18531, 18536, 18542, 18547, - 18554, 18560, 18565, 18575, 18584, 18591, 18596, 18600, 18606, 18612, - 18616, 18623, 18629, 18634, 18640, 18648, 18656, 18663, 18669, 18675, - 18680, 18686, 18692, 18700, 18705, 18710, 18718, 18724, 18730, 18735, - 18742, 18747, 18751, 18757, 18763, 18768, 18774, 18781, 18786, 18792, - 18795, 18801, 18812, 18818, 18827, 18830, 18834, 18838, 18852, 18865, - 18877, 18883, 18888, 18895, 18901, 18907, 18918, 18930, 18942, 18952, - 18961, 18969, 18976, 18987, 18997, 19007, 19015, 19018, 17302, 19023, - 19028, 19035, 17307, 17458, 19043, 19056, 19071, 19082, 17475, 19100, - 19113, 19126, 19137, 12546, 19148, 19161, 19180, 19191, 19202, 19213, - 2824, 19226, 19230, 19238, 19249, 19260, 19268, 19283, 19298, 19309, - 19316, 19322, 19330, 19334, 19340, 19344, 19347, 19360, 19372, 19382, - 19390, 19397, 19405, 19415, 19420, 19427, 19432, 19439, 19450, 19460, - 19466, 19471, 19476, 17312, 19480, 19486, 19493, 19499, 19504, 19509, - 19514, 19518, 17317, 17323, 19522, 17329, 19527, 19535, 19540, 19544, - 19551, 19559, 19566, 19575, 19582, 19586, 19590, 19595, 19600, 19605, - 19610, 19615, 10487, 19620, 19622, 19627, 19632, 19638, 19643, 19648, - 19653, 19658, 19662, 19668, 19674, 19679, 19685, 19690, 19695, 19699, - 19705, 19710, 19714, 19719, 19724, 19736, 19741, 19747, 19752, 19757, - 19763, 19769, 19774, 19779, 19784, 19791, 19797, 19808, 19815, 19824, - 19829, 19833, 279, 19837, 19845, 19850, 19856, 19862, 19867, 19874, - 19881, 19887, 19892, 19898, 19903, 19908, 19913, 19920, 19930, 19938, - 19943, 19948, 19955, 19961, 19970, 19980, 19990, 20004, 20018, 20032, - 20046, 20061, 20076, 20093, 20111, 20124, 20130, 20135, 20140, 20144, - 20152, 20157, 20165, 20171, 20177, 20182, 20187, 20191, 20197, 20202, - 20206, 20213, 20218, 20222, 20233, 20239, 20244, 20249, 20256, 20261, - 20265, 3927, 20270, 20276, 20283, 17334, 20289, 20293, 20299, 20304, - 20309, 20313, 20319, 20324, 20329, 20336, 20341, 15730, 20345, 20350, - 20354, 20359, 20365, 20371, 20378, 20388, 20396, 20403, 20408, 20412, - 20421, 20429, 20436, 20443, 20449, 20454, 20460, 20465, 20470, 20476, - 20481, 20487, 20492, 20498, 20504, 20511, 20517, 20522, 20527, 10713, - 20536, 20539, 20547, 20553, 20558, 20563, 20573, 20580, 20586, 20591, - 20596, 20602, 20607, 20613, 20618, 20624, 20631, 20637, 20643, 20648, - 20656, 20663, 20668, 20673, 20679, 20684, 20688, 20697, 20708, 20715, - 20722, 20730, 20737, 20744, 20749, 20754, 20760, 20765, 20773, 20779, - 20785, 20790, 20797, 20803, 20808, 20812, 20818, 20823, 20828, 20832, - 20837, 1321, 8762, 3112, 20841, 20845, 20849, 20853, 20857, 20861, 20864, - 20869, 20876, 20884, 20894, 20905, 20915, 20926, 20938, 20949, 20959, - 20970, 20982, 20993, 21005, 21018, 21030, 21041, 21051, 21062, 21074, - 21085, 21098, 21110, 21121, 21133, 21146, 21158, 21171, 21185, 21198, - 21210, 21221, 21231, 21242, 21254, 21265, 21277, 21290, 21302, 21313, - 21325, 21338, 21351, 21365, 21378, 21390, 21401, 21413, 21426, 21438, - 21451, 21465, 21478, 21490, 21503, 21517, 21530, 21544, 21558, 21571, - 21583, 21594, 21604, 17345, 21611, 21617, 21627, 21635, 21642, 21650, - 21660, 21669, 21682, 21687, 21692, 21700, 21707, 15839, 15848, 21714, - 21724, 21739, 21745, 21752, 21759, 21766, 21772, 21778, 21789, 21797, - 21805, 21815, 21825, 21834, 17350, 21843, 21849, 21855, 21864, 21872, - 21880, 21885, 21894, 21902, 21914, 21924, 21934, 21944, 21953, 21965, - 21975, 21985, 21996, 22003, 22008, 22015, 22027, 22039, 22051, 22063, - 22075, 22087, 22099, 22111, 22123, 22135, 22146, 22158, 22170, 22182, - 22194, 22206, 22218, 22230, 22242, 22254, 22266, 22277, 22289, 22301, - 22313, 22325, 22337, 22349, 22361, 22373, 22385, 22397, 22408, 22420, - 22432, 22444, 22456, 22468, 22480, 22492, 22504, 22516, 22528, 22539, - 22551, 22563, 22575, 22587, 22599, 22611, 22623, 22635, 22647, 22659, - 22670, 22682, 22694, 22706, 22718, 22730, 22742, 22754, 22766, 22778, - 22790, 22801, 22813, 22825, 22837, 22849, 22861, 22873, 22885, 22897, - 22909, 22921, 22932, 22944, 22956, 22968, 22980, 22993, 23006, 23019, - 23032, 23045, 23058, 23071, 23083, 23096, 23109, 23122, 23135, 23148, - 23161, 23174, 23187, 23200, 23213, 23225, 23238, 23251, 23264, 23277, - 23290, 23303, 23316, 23329, 23342, 23355, 23367, 23380, 23393, 23406, - 23419, 23432, 23445, 23458, 23471, 23484, 23497, 23509, 23522, 23535, - 23548, 23561, 23574, 23587, 23600, 23613, 23626, 23639, 23651, 23664, - 23677, 23690, 23703, 23716, 23729, 23742, 23755, 23768, 23781, 23793, - 23804, 23817, 23830, 23843, 23856, 23869, 23882, 23895, 23908, 23921, - 23934, 23946, 23959, 23972, 23985, 23998, 24011, 24024, 24037, 24050, - 24063, 24076, 24088, 24101, 24114, 24127, 24140, 24153, 24166, 24179, - 24192, 24205, 24218, 24230, 24243, 24256, 24269, 24282, 24295, 24308, - 24321, 24334, 24347, 24360, 24372, 24385, 24398, 24411, 24424, 24437, - 24450, 24463, 24476, 24489, 24502, 24514, 24527, 24540, 24553, 24566, - 24579, 24592, 24605, 24618, 24631, 24644, 24656, 24669, 24682, 24695, - 24708, 24721, 24734, 24747, 24760, 24773, 24786, 24798, 24811, 24824, - 24837, 24850, 24863, 24876, 24889, 24902, 24915, 24928, 24940, 24953, - 24966, 24979, 24992, 25005, 25018, 25031, 25044, 25057, 25070, 25082, - 25095, 25108, 25121, 25134, 25147, 25160, 25173, 25186, 25199, 25212, - 25224, 25235, 25244, 25252, 25260, 25267, 25273, 25277, 25283, 25289, - 25298, 25306, 25311, 25317, 25322, 25326, 25335, 10492, 25346, 25352, - 25359, 25367, 25374, 13145, 13159, 25381, 25388, 25397, 25402, 25407, - 25414, 25419, 25424, 8778, 8784, 8790, 25429, 25434, 25437, 25442, 25450, - 25457, 25464, 25476, 25483, 25489, 25498, 25503, 25512, 25521, 25527, - 25535, 25544, 25548, 25554, 25559, 25569, 25576, 25582, 25590, 25596, - 25603, 25609, 25619, 25628, 25632, 25639, 25643, 25648, 25654, 25662, - 25666, 25676, 17360, 25685, 25691, 25695, 25704, 25713, 25723, 25729, - 17365, 25736, 25743, 25754, 25762, 25772, 25781, 25789, 10207, 25797, - 25802, 25808, 25813, 25817, 25821, 25825, 11301, 25830, 25838, 25845, - 25854, 25862, 25869, 25876, 25885, 25891, 1062, 25898, 25904, 25908, - 25914, 25921, 25927, 25935, 25941, 25948, 25954, 25960, 25969, 25973, - 25981, 25989, 25996, 26005, 26012, 26017, 26021, 26031, 26042, 26053, - 26058, 26063, 26069, 26078, 26083, 26096, 9000, 26100, 26106, 26112, - 26118, 26123, 26131, 26135, 26142, 26151, 26156, 17638, 26164, 26168, - 26180, 26185, 26189, 26192, 26198, 26204, 26210, 26215, 26220, 26224, - 26227, 26238, 26243, 10769, 26250, 26255, 26260, 26265, 26270, 26275, - 26280, 26285, 26290, 10774, 26295, 26300, 26305, 26310, 26315, 26320, - 26325, 26330, 26335, 26340, 26345, 26350, 26356, 26361, 26366, 26371, - 26376, 26381, 26386, 26391, 26396, 26401, 26407, 26413, 26418, 26423, - 26428, 26433, 26438, 26443, 26448, 26453, 26458, 26464, 26469, 26474, - 26479, 26485, 26491, 26496, 26501, 26506, 26511, 26516, 26521, 26526, - 26531, 26537, 26542, 26547, 26552, 26557, 26563, 26568, 26573, 26577, - 1244, 145, 26585, 26589, 26593, 26597, 26602, 26606, 15736, 2409, 26610, - 26615, 26619, 26624, 26628, 26633, 26637, 26643, 26648, 26652, 26656, - 26664, 26668, 26672, 26679, 26684, 26689, 26693, 26699, 26704, 26708, - 26713, 26718, 26722, 26729, 26736, 26743, 26748, 26752, 26756, 26761, - 26765, 26768, 26774, 26787, 26792, 26798, 26807, 26812, 11049, 26817, - 26826, 26831, 26834, 26838, 26843, 26848, 26853, 26858, 26863, 2920, - 2925, 26868, 26874, 26878, 26884, 3888, 26889, 26894, 26899, 26905, - 26910, 16686, 26915, 26920, 26925, 26930, 26936, 26941, 26946, 26952, - 26957, 26961, 26966, 26971, 26976, 26981, 26986, 26990, 26995, 26999, - 27004, 27009, 27014, 27019, 27023, 27028, 27032, 27037, 27042, 27047, - 26962, 3121, 26967, 27052, 27060, 27067, 11395, 27079, 27087, 27097, - 27115, 27134, 27143, 27151, 26972, 27158, 27163, 27171, 26977, 27176, - 27181, 27189, 27194, 27199, 27203, 19858, 27208, 27216, 27221, 27225, - 27232, 27238, 27247, 27251, 27259, 27265, 27269, 27272, 20692, 27279, - 27283, 27287, 27292, 27298, 27305, 27310, 10234, 27314, 27319, 27324, - 27329, 27334, 27339, 1663, 1668, 27344, 27350, 27356, 27361, 27365, - 27369, 27373, 27377, 27381, 27385, 27389, 27393, 25470, 27396, 27403, - 27411, 27417, 27423, 27428, 27433, 27439, 27443, 27448, 27455, 16586, - 16593, 27461, 27473, 27476, 27483, 27487, 19883, 27494, 27502, 27513, - 27522, 27535, 27545, 27559, 27571, 27585, 27598, 27610, 27620, 27632, - 27638, 27653, 27677, 27695, 27714, 27727, 27741, 27759, 27775, 27792, - 27810, 27821, 27840, 27857, 27877, 27895, 27907, 27921, 27935, 27947, - 27964, 27983, 28001, 28013, 28031, 28050, 17518, 28063, 28083, 28095, - 12577, 28107, 28112, 28117, 28122, 28131, 28137, 28142, 28146, 28153, - 28159, 28163, 28168, 28173, 28178, 28183, 28188, 28193, 2506, 28198, - 28204, 28208, 28211, 28222, 28226, 28229, 28237, 28243, 14882, 28247, - 28256, 28267, 28273, 28279, 28294, 28303, 28311, 28318, 28323, 28327, - 28334, 28340, 28349, 28357, 28364, 28374, 28383, 28393, 28398, 28407, - 28416, 28427, 28438, 28448, 28465, 4557, 28475, 28479, 28489, 28497, - 28507, 28518, 28524, 28529, 28539, 28547, 28554, 28560, 28567, 28572, - 27010, 28576, 28585, 28589, 28592, 28597, 28605, 28612, 28621, 28629, - 28637, 28645, 28655, 28664, 28670, 28676, 28682, 28686, 27015, 27020, - 28690, 28700, 28710, 28720, 28728, 28735, 28745, 28753, 28761, 28767, - 28775, 798, 28784, 17725, 649, 28798, 28807, 28815, 28826, 28837, 28847, - 28856, 28868, 28877, 28886, 28893, 28899, 28909, 28918, 28927, 28935, - 28943, 28953, 28961, 28969, 28976, 28982, 28987, 28992, 28997, 8156, - 29002, 29005, 29009, 29014, 29022, 29028, 29033, 29037, 3751, 27033, - 29045, 27038, 29051, 29057, 29063, 29068, 29073, 29077, 29085, 29091, - 29097, 29101, 3912, 29109, 29114, 29119, 29123, 29127, 11681, 29134, - 29142, 29156, 29163, 29170, 29176, 11690, 11696, 29184, 29192, 29199, - 29204, 29209, 27043, 29215, 29226, 29235, 19031, 29243, 29248, 2755, - 29253, 29264, 29270, 29275, 29279, 29283, 29286, 29293, 29300, 29306, - 29314, 29321, 29327, 29331, 8196, 29336, 29340, 29344, 29352, 29357, - 29362, 29367, 1696, 29372, 29377, 29382, 29387, 29392, 29397, 29402, - 29407, 29412, 29417, 29422, 29427, 29432, 29437, 29443, 29448, 29453, - 29458, 29463, 29468, 29473, 29479, 29484, 29489, 29494, 29499, 29504, - 29509, 29514, 29520, 29526, 29531, 29537, 29542, 29547, 5, 29553, 29557, - 29561, 29565, 29570, 29574, 29578, 29582, 29586, 29591, 29595, 29600, - 29604, 29607, 29611, 29616, 29620, 29625, 29629, 29633, 29637, 29642, - 29646, 29650, 29660, 29665, 29669, 29673, 29678, 29683, 29692, 29697, - 29702, 29706, 29710, 29719, 29732, 29744, 29753, 29762, 29767, 29773, - 29778, 29782, 29786, 29796, 29805, 29813, 29819, 29824, 29828, 29835, - 29842, 29852, 29861, 29869, 12934, 29877, 29884, 29892, 29901, 29910, - 29918, 29928, 29933, 29937, 29941, 29944, 29946, 29950, 29954, 29959, - 29964, 29968, 29972, 29975, 29979, 29982, 29986, 29989, 29992, 29996, - 30002, 30006, 30010, 30014, 30018, 30023, 30028, 30033, 30037, 30040, - 30045, 30051, 30056, 30062, 30067, 30071, 30077, 30081, 30085, 30090, - 30094, 30099, 30104, 30108, 30112, 30119, 30123, 30126, 30130, 30134, - 30140, 30145, 30151, 30155, 30159, 30164, 30171, 30177, 30181, 30190, - 30194, 30198, 30201, 30207, 30212, 30218, 1385, 1748, 30223, 30228, - 30233, 30238, 30243, 30248, 30253, 2213, 827, 30258, 30261, 30265, 30269, - 30274, 30278, 17737, 30282, 30287, 30292, 30296, 30299, 30304, 30308, - 30313, 30317, 17741, 30322, 30325, 30328, 30334, 30338, 30343, 30347, - 30360, 30368, 30372, 30375, 30383, 30392, 30399, 30404, 30410, 30416, - 30424, 30431, 30438, 30442, 30446, 30450, 30455, 30460, 30464, 30472, - 30477, 30484, 30496, 30507, 30512, 30516, 30523, 30527, 30532, 30538, - 30541, 30546, 30551, 30558, 30562, 30566, 30569, 30575, 8900, 2413, - 30579, 30584, 30600, 11100, 30620, 30629, 30645, 30649, 30656, 30659, - 30665, 30675, 30681, 30690, 30699, 30714, 30725, 30737, 30748, 30756, - 30765, 30771, 30780, 30790, 30800, 30811, 30822, 30832, 30841, 30848, - 30857, 30865, 30872, 30879, 30886, 30894, 30901, 30908, 30921, 30928, - 30936, 30943, 30949, 30954, 30963, 30970, 30976, 30981, 30989, 30997, - 31004, 31011, 28499, 31023, 31035, 31049, 31057, 31065, 31073, 31080, - 31092, 31101, 31110, 31118, 31126, 31134, 31141, 31147, 31156, 31164, - 31174, 31183, 31193, 31202, 31211, 31219, 31224, 31228, 31231, 31235, - 31239, 31243, 31247, 31251, 31257, 31263, 31268, 31276, 31283, 31291, - 31298, 10806, 17799, 31306, 31313, 31318, 31325, 31331, 31337, 31344, - 14024, 31351, 31354, 31366, 31374, 31380, 31385, 31389, 31400, 31410, - 31420, 11620, 31429, 31438, 31446, 31456, 31465, 31472, 31479, 31487, - 31491, 17818, 31494, 31501, 31505, 4501, 31511, 31514, 31521, 31527, - 31541, 31546, 31554, 31560, 31571, 31578, 31584, 31590, 31594, 31599, - 31603, 31612, 31619, 31625, 8953, 31632, 31640, 31647, 31653, 31658, - 31664, 31670, 31680, 31692, 31703, 31713, 11252, 31721, 31727, 17836, - 31731, 31733, 31236, 11633, 31742, 31747, 31753, 31763, 31768, 31775, - 31783, 31789, 31794, 31799, 31804, 31808, 31813, 31820, 31826, 31835, - 31843, 31847, 31854, 31864, 31870, 31879, 31885, 31892, 4771, 31898, - 31904, 31909, 31916, 31928, 31939, 31944, 31952, 31956, 31966, 31972, - 31976, 31981, 31991, 32000, 32004, 32011, 32019, 32026, 32032, 32037, - 32045, 32052, 32057, 32064, 32076, 32085, 32089, 32097, 15656, 32101, - 32111, 32115, 32123, 32130, 32137, 30379, 32148, 32153, 32157, 32164, - 32171, 26695, 31161, 32176, 32180, 32183, 27827, 32188, 32202, 32218, - 32236, 32255, 32272, 32290, 27846, 32307, 32327, 27863, 32339, 32351, - 19087, 32363, 27883, 32377, 32389, 12590, 32403, 32408, 32413, 32418, - 32424, 32430, 32436, 32440, 32448, 32454, 32461, 32466, 32476, 32483, - 32489, 12128, 32495, 32497, 32502, 32510, 32514, 31816, 32520, 32527, - 13866, 13876, 32534, 32541, 32551, 32556, 32560, 32563, 32569, 32577, - 32589, 32599, 32615, 32628, 32642, 19105, 32656, 32663, 32667, 32670, - 32675, 32679, 32686, 32693, 32700, 32707, 32717, 32722, 32727, 32732, - 32740, 32748, 32753, 32762, 28520, 3561, 32767, 32770, 32773, 32778, - 32785, 32790, 32795, 32811, 32819, 32827, 10864, 32835, 32840, 32844, - 32850, 32855, 32861, 32864, 32870, 32882, 32890, 32897, 32903, 32910, - 32921, 32935, 32948, 32954, 32963, 32969, 32978, 32990, 33001, 33011, - 33020, 33029, 33037, 33047, 33056, 33067, 673, 33074, 33081, 33087, - 33092, 33098, 33105, 33111, 33122, 33132, 33142, 33151, 33157, 33164, - 33169, 33177, 33184, 33192, 33200, 33212, 7142, 33219, 33222, 33231, - 33239, 33245, 33251, 33256, 33260, 33263, 33269, 33276, 33281, 33286, - 33293, 33298, 33302, 33314, 33325, 33334, 33342, 18008, 33347, 33355, - 33360, 33368, 33374, 33380, 33385, 13859, 9802, 33388, 33392, 33396, - 33399, 33402, 33408, 33416, 33424, 33428, 33432, 33437, 33441, 33444, - 33453, 33458, 33463, 33467, 33470, 33475, 33483, 33494, 33503, 33507, - 33513, 33519, 33523, 33529, 33537, 33559, 33583, 33594, 33603, 33609, - 33616, 33623, 33629, 33637, 33643, 33648, 33659, 33677, 33684, 33692, - 33696, 33703, 33708, 33717, 33730, 33738, 33750, 33761, 33772, 33782, - 33796, 33805, 33813, 33825, 33836, 11117, 33845, 33856, 33867, 33879, - 33889, 33898, 33908, 33913, 33917, 33925, 33936, 33946, 33952, 33957, - 33961, 33964, 33967, 33975, 33983, 33992, 34002, 34011, 34017, 34022, - 34036, 2838, 34058, 34069, 34078, 34088, 34100, 34109, 34118, 34128, - 34136, 34144, 34153, 34158, 34169, 34174, 34183, 34189, 34200, 34204, - 34207, 34217, 34226, 34234, 34244, 34254, 34262, 34271, 34278, 34284, - 34292, 34299, 34308, 34317, 34322, 34327, 34331, 34339, 34346, 34352, - 34356, 34364, 34371, 34382, 34397, 34404, 34410, 34420, 34429, 34435, - 34446, 34450, 34457, 34461, 34468, 34474, 16838, 34480, 34484, 34489, - 34495, 34502, 34506, 34510, 34518, 34526, 34532, 34541, 34548, 34555, - 34560, 34565, 34575, 28574, 34579, 34582, 34587, 34592, 34597, 34602, - 34607, 34612, 34617, 34622, 34628, 34633, 34638, 34644, 1094, 770, 34649, - 34652, 34659, 34668, 1777, 34675, 34680, 34684, 34690, 1143, 643, 34695, - 347, 34699, 34709, 34718, 34726, 34735, 34743, 34750, 34761, 34769, - 34778, 34786, 34796, 34804, 34809, 11794, 34813, 34821, 34829, 34834, - 17754, 4101, 34840, 34846, 34852, 6669, 34857, 34861, 34868, 34874, - 34880, 34884, 34893, 34899, 34904, 34911, 1336, 34917, 34923, 34928, - 34935, 34939, 1243, 6677, 34944, 34954, 34962, 34968, 34978, 34987, - 34995, 35001, 35006, 35014, 35021, 13376, 35027, 35034, 35039, 35045, - 35052, 35062, 1404, 253, 2212, 35068, 35074, 35081, 35092, 35103, 35111, - 35118, 35128, 35137, 35145, 35154, 35161, 35168, 35181, 35188, 35194, - 35205, 35224, 35229, 1148, 35233, 35238, 35246, 3984, 35250, 35255, - 35259, 35263, 1340, 29973, 35273, 35277, 35282, 35286, 35292, 3846, - 35298, 35306, 35313, 35324, 35333, 35341, 35366, 35374, 35379, 3985, 401, - 35385, 35393, 35401, 35408, 35413, 35419, 35424, 2281, 12792, 35431, - 35437, 31595, 31934, 35443, 656, 106, 35447, 35451, 35457, 595, 10679, - 35462, 35467, 35474, 35480, 35484, 35488, 1549, 35491, 35495, 18296, - 35498, 35503, 35510, 35516, 8966, 35521, 35529, 35536, 35542, 27205, - 35546, 35550, 35554, 35558, 1834, 20204, 35562, 35567, 35571, 35574, - 35582, 35590, 35595, 35604, 35612, 35615, 35622, 35629, 35641, 27284, - 35651, 35663, 35671, 35676, 35680, 35688, 35695, 35702, 35711, 35717, - 35724, 35731, 35734, 35738, 35742, 1351, 35752, 35754, 35759, 35765, - 35771, 35776, 35781, 35786, 35791, 35796, 35801, 35806, 35811, 35816, - 35821, 35826, 35831, 35836, 35841, 35847, 35853, 35859, 35865, 35870, - 35875, 35880, 35886, 35891, 35896, 35901, 35907, 35912, 35918, 35923, - 35928, 35933, 35938, 35944, 35949, 35955, 35960, 35965, 35970, 35975, - 35981, 35986, 35992, 35997, 36002, 36007, 36012, 36017, 36022, 36027, - 36032, 36037, 36043, 36049, 36055, 36060, 36065, 36070, 36075, 36081, - 36087, 36093, 36099, 36105, 36111, 36116, 36122, 36127, 36132, 36137, - 36142, 36148, 2552, 36153, 2559, 2566, 2962, 36158, 2572, 2582, 36164, - 2614, 2619, 2624, 36168, 36173, 36178, 36184, 36189, 36194, 36198, 36203, - 36209, 36214, 36219, 36224, 36230, 36235, 36239, 36243, 36248, 36253, - 36258, 36263, 36268, 36274, 36280, 36285, 36289, 36294, 36300, 36304, - 36309, 36314, 36319, 36324, 36328, 36331, 36336, 36341, 36346, 36351, - 36356, 36362, 36368, 36373, 36378, 36383, 36387, 36392, 36397, 36402, - 36407, 36412, 36417, 36421, 36426, 36431, 36436, 36440, 36444, 36448, - 36453, 36461, 36466, 36471, 36477, 36483, 36489, 36494, 36502, 36506, - 36509, 36514, 36519, 36523, 36528, 36533, 36537, 36542, 36546, 36549, - 36554, 4211, 21695, 36559, 36564, 36569, 36574, 36582, 25865, 34932, - 10318, 36587, 36592, 36596, 36601, 36605, 36609, 36614, 36618, 36621, - 36624, 36628, 36633, 36637, 36645, 36649, 36652, 36657, 36661, 36665, - 36670, 36675, 36679, 36685, 36690, 36695, 36702, 36709, 36713, 36716, - 36722, 36731, 36738, 36746, 36753, 36757, 36762, 36766, 36770, 36776, - 36781, 36787, 36791, 36797, 36802, 36807, 36811, 36818, 36824, 36830, - 36836, 36842, 36849, 36855, 36861, 36867, 36873, 36879, 36885, 36891, - 36898, 36904, 36911, 36917, 36923, 36929, 36935, 36941, 36947, 36953, - 36959, 36965, 36971, 36976, 36981, 13731, 36986, 36992, 36997, 37002, - 37007, 37012, 37015, 37021, 37026, 37034, 37039, 37043, 37048, 37054, - 37063, 37069, 37074, 37079, 37084, 37088, 37093, 37097, 37102, 37107, - 37112, 37117, 37124, 37131, 37137, 37143, 37148, 19801, 37155, 37161, - 37168, 37174, 37180, 37185, 37193, 37198, 11288, 37202, 37207, 37212, - 37218, 37223, 37228, 37232, 37237, 37242, 37248, 37253, 37258, 37263, - 37267, 37272, 37277, 37281, 37286, 37291, 37295, 37300, 37304, 37309, - 37314, 37319, 37323, 37328, 37332, 37337, 37341, 37348, 37352, 37356, - 18452, 37361, 37368, 37377, 37383, 37389, 37398, 37406, 37415, 37423, - 37428, 37432, 37439, 37445, 37453, 37457, 37460, 37465, 37469, 37478, - 37486, 37504, 37510, 1403, 37516, 37519, 37523, 27351, 27357, 37529, - 37533, 37544, 37555, 37566, 37578, 37582, 37589, 37596, 37603, 37608, - 37612, 37620, 37625, 37630, 37635, 37640, 6734, 16742, 25864, 37645, - 37650, 37654, 16733, 37659, 37665, 37670, 37676, 37681, 37687, 37692, - 37698, 37703, 37709, 37715, 37721, 37726, 37682, 37688, 37730, 37735, - 37741, 37746, 37752, 37757, 37763, 37768, 37693, 12422, 37772, 37704, - 37710, 37716, 3054, 3760, 37778, 37781, 37786, 37792, 37798, 37804, - 37811, 37817, 37823, 37829, 37835, 37841, 37847, 37853, 37859, 37865, - 37871, 37877, 37883, 37890, 37896, 37902, 37908, 37914, 37920, 37923, - 37928, 37931, 37938, 37943, 37951, 37955, 37960, 37965, 37971, 37976, - 37981, 37985, 37990, 37996, 38001, 38007, 38012, 38018, 38023, 38029, - 38035, 38039, 38044, 38049, 38054, 38059, 38063, 38068, 38073, 38078, - 38084, 38090, 38096, 38102, 38107, 38111, 38114, 38120, 38126, 38135, - 38143, 38150, 38155, 38159, 38163, 38168, 18239, 38173, 38181, 38187, - 4152, 1253, 38192, 38197, 38201, 9016, 38207, 38213, 38220, 9025, 38224, - 38230, 38236, 38243, 38249, 38258, 38266, 38278, 38287, 38291, 38298, - 38304, 38309, 38313, 38317, 38320, 38330, 38339, 38347, 37683, 38352, - 38362, 38372, 38382, 38388, 38393, 38403, 38408, 38421, 38435, 38446, - 38458, 38470, 38484, 38497, 38509, 38521, 17559, 38535, 38540, 38545, - 38549, 38553, 38557, 38561, 38567, 38572, 38577, 38582, 38587, 38592, - 38597, 1737, 32999, 38602, 38607, 38612, 37731, 38617, 38620, 38625, - 38630, 38635, 38641, 38647, 19411, 11994, 38652, 38658, 38665, 19039, - 38671, 38676, 38681, 38685, 38690, 38695, 37736, 38700, 38705, 38710, - 38716, 37742, 38721, 38724, 38731, 38739, 38745, 38751, 38757, 38768, - 38773, 38780, 38787, 38794, 38802, 38811, 38820, 38826, 38832, 38840, - 37747, 38845, 38851, 38857, 37753, 38862, 38867, 38875, 38883, 38889, - 38896, 38902, 38909, 38916, 38922, 38930, 38940, 38947, 38953, 38958, - 38964, 38969, 38974, 38981, 38990, 38998, 39003, 39009, 39016, 39024, - 39030, 39035, 39041, 39050, 39057, 33997, 39063, 39067, 39072, 39081, - 39086, 39091, 39096, 14972, 39104, 39109, 39114, 39119, 39123, 39128, - 39133, 39140, 39145, 39150, 39155, 37758, 25793, 39161, 2655, 158, 39164, - 39167, 39171, 39175, 39185, 39193, 39200, 39204, 39208, 39211, 39219, - 39226, 39233, 31888, 39242, 39245, 39252, 39258, 39263, 39267, 39274, - 39278, 39286, 39294, 39301, 39316, 39320, 39324, 39327, 39333, 39340, - 39344, 39350, 39354, 39361, 39369, 39377, 39384, 37694, 39391, 39399, - 39404, 39416, 12075, 12082, 12089, 12096, 12103, 12110, 626, 434, 39422, - 39427, 39432, 39438, 39443, 39448, 4178, 39453, 39456, 39461, 39466, - 39471, 39476, 39481, 39488, 27469, 39493, 39498, 39503, 39508, 39513, - 39519, 39524, 39530, 37934, 39536, 39541, 39547, 39553, 39563, 39568, - 39573, 39577, 39582, 39587, 39592, 39597, 39610, 39615, 27083, 20286, - 1064, 39619, 39625, 39629, 39634, 39639, 39645, 39650, 39655, 39659, - 39664, 39669, 39675, 39680, 39685, 1258, 39689, 39694, 39699, 39704, - 39708, 39713, 39718, 39723, 39729, 39735, 39740, 39744, 39748, 39753, - 39758, 39763, 39767, 39772, 39780, 39784, 39790, 39794, 39801, 39810, - 20057, 37705, 39816, 39823, 39831, 39839, 39846, 39852, 39861, 39874, - 39886, 39891, 39897, 39901, 2981, 39905, 39909, 39335, 39918, 39929, - 39940, 39945, 34065, 39950, 39955, 39959, 34185, 27362, 39964, 39971, - 39975, 39980, 37711, 25900, 39984, 39989, 39995, 40000, 40004, 40008, - 40011, 40015, 40021, 40030, 40041, 40053, 37717, 40058, 40061, 40065, - 40069, 40074, 40079, 40084, 40089, 40094, 40099, 40104, 40109, 373, - 40114, 40119, 40124, 40129, 40134, 40139, 40145, 40150, 40155, 40161, - 40166, 40172, 40177, 40183, 40188, 40193, 40198, 40203, 40208, 40213, - 40218, 40223, 40229, 40234, 40239, 40244, 40249, 40254, 40259, 40264, - 40270, 40276, 40281, 40286, 40291, 40296, 40301, 40306, 40311, 40316, - 40321, 40326, 40331, 40336, 40341, 40346, 40351, 40356, 40361, 40366, - 40376, 40386, 40392, 342, 14, 40397, 40400, 40404, 40408, 40416, 40420, - 40424, 31568, 16975, 1818, 40427, 40432, 40436, 40441, 40445, 40450, - 40454, 40459, 40463, 40466, 40468, 40472, 40477, 40481, 40492, 40495, - 40497, 40501, 40513, 40525, 40534, 40538, 40548, 40552, 40558, 40563, - 40572, 40578, 40583, 40588, 40592, 40596, 40601, 40608, 40613, 40619, - 40624, 40628, 40635, 31169, 31179, 40639, 40644, 40649, 40654, 40661, - 40665, 40672, 40679, 40685, 9171, 40689, 40698, 40706, 40721, 40735, - 40744, 40752, 40763, 40772, 40777, 40784, 40794, 8165, 40804, 40809, - 40815, 40820, 40824, 40827, 40832, 40836, 40841, 40845, 40852, 40857, - 40862, 40867, 40877, 40882, 40887, 40892, 10188, 40897, 40899, 40907, - 40910, 40913, 40921, 40936, 40944, 40954, 40956, 40959, 40963, 40969, - 40973, 40978, 40983, 41001, 41015, 41034, 41051, 41060, 41068, 41073, - 41078, 1396, 41084, 41090, 41095, 41105, 41114, 41122, 41127, 41133, - 41138, 41147, 41156, 41167, 41172, 41179, 41185, 41189, 41198, 41205, - 41213, 41220, 41233, 41241, 41245, 41255, 41261, 41266, 41270, 41278, - 41286, 41291, 41295, 41299, 41308, 41314, 41319, 41327, 41337, 41346, - 41355, 41364, 41375, 41383, 41394, 41403, 41411, 41418, 41424, 41429, - 41440, 41451, 41456, 41460, 41463, 41467, 41477, 41485, 41491, 41502, - 41513, 41524, 41535, 41546, 41557, 41568, 41579, 41591, 41603, 41615, - 41627, 41639, 41651, 41663, 41672, 41676, 41684, 41690, 41696, 41703, - 41709, 41714, 41720, 41724, 41729, 41734, 41739, 40371, 40381, 2526, - 41744, 41746, 41751, 41756, 41761, 41764, 41766, 41770, 41773, 41780, - 41784, 11644, 41788, 41794, 41801, 41807, 41817, 41822, 41828, 41832, - 41837, 41850, 31758, 41856, 41862, 41871, 41880, 21918, 41887, 41896, - 41904, 38368, 41910, 41915, 41919, 41928, 41936, 41943, 41948, 41952, - 41957, 41962, 41970, 41974, 41982, 41988, 41994, 41999, 42004, 42008, - 42011, 42016, 42029, 42045, 27953, 42062, 42074, 42091, 42103, 42117, - 27970, 27989, 42129, 42141, 2855, 42155, 42160, 42165, 42170, 42174, - 42181, 42193, 42200, 42209, 42219, 42222, 42233, 42244, 42252, 42257, - 42261, 42266, 42271, 42276, 42281, 42286, 42291, 1768, 947, 42296, 42300, - 42304, 42307, 42312, 42317, 42323, 42328, 42333, 42339, 42345, 42350, - 42354, 42359, 42364, 42369, 42373, 42376, 42382, 42387, 42392, 42397, - 42401, 42406, 42412, 42420, 32069, 42425, 42430, 42437, 42443, 42449, - 42454, 42462, 27478, 42469, 42474, 42479, 42484, 42488, 42491, 42496, - 42500, 42504, 42511, 42517, 42523, 42529, 42536, 42541, 42547, 41281, - 42551, 42555, 42560, 42573, 42578, 42584, 42592, 42599, 42607, 42617, - 42623, 42629, 42635, 42639, 42648, 42656, 42663, 42668, 42673, 12445, - 42678, 42688, 42695, 42701, 42711, 42716, 42722, 42730, 4017, 42737, - 42744, 42750, 42757, 4023, 42761, 42766, 42777, 42784, 42790, 42799, - 42803, 42806, 4609, 42813, 42820, 42826, 42832, 42840, 42850, 35414, - 42857, 42865, 42871, 42876, 42882, 42887, 42891, 31517, 42897, 42904, - 42910, 42918, 42927, 42934, 42940, 42951, 28772, 42957, 42964, 42970, - 42980, 42985, 42989, 42997, 43005, 43012, 43018, 43023, 11246, 941, - 43028, 43032, 43034, 43038, 43043, 43046, 43048, 43053, 43059, 43064, - 43069, 43076, 39484, 43082, 43087, 43091, 43096, 43100, 43109, 43113, - 43119, 43126, 43132, 43139, 43144, 43153, 43158, 43162, 43167, 43174, - 43182, 43190, 43195, 25956, 43199, 43202, 43206, 43210, 12889, 1005, - 43214, 43219, 43227, 43232, 43236, 43245, 43252, 43256, 43260, 43268, - 43275, 16260, 43285, 43289, 43293, 43301, 43309, 43315, 43320, 43324, - 43333, 16008, 43339, 43348, 43355, 43360, 43367, 43374, 43382, 43389, - 43397, 43405, 43414, 43419, 43426, 43433, 43440, 43447, 43454, 43459, - 43466, 43472, 43489, 43497, 43507, 43515, 43522, 43530, 461, 43534, - 43540, 43544, 43549, 40768, 43555, 43558, 43562, 43568, 43579, 43587, - 4028, 43595, 43601, 43607, 43617, 43623, 43632, 43641, 43651, 43658, - 43664, 43669, 4034, 4040, 43678, 43686, 43693, 43697, 14356, 43705, - 43709, 43716, 43724, 43731, 43740, 43747, 43753, 43762, 43772, 43778, - 43786, 43795, 43802, 43810, 43817, 26758, 43821, 43828, 43834, 43844, - 43853, 43861, 43872, 43876, 43886, 43893, 43898, 43903, 43909, 43916, - 43924, 43933, 43942, 43952, 43963, 43970, 43975, 43982, 3269, 43990, - 43996, 44001, 44008, 44014, 44020, 44025, 44038, 44051, 44064, 44071, - 44077, 44085, 44093, 44098, 44102, 44106, 44111, 44116, 44121, 44126, - 44131, 44136, 1365, 44141, 44145, 44149, 44153, 44157, 44161, 44165, - 44169, 44173, 44177, 44181, 44185, 44189, 44193, 44197, 44201, 44205, - 44209, 44213, 44217, 44221, 44225, 44229, 44233, 44237, 44241, 44245, - 44249, 44253, 44257, 44261, 44265, 44269, 44273, 44277, 44281, 44285, - 44289, 44293, 44297, 44301, 44305, 44309, 44313, 44317, 44321, 44325, - 44329, 44333, 44337, 44341, 44345, 44349, 44353, 44357, 44361, 44365, - 44369, 44373, 44377, 44381, 44385, 44389, 44393, 44397, 44401, 44405, - 44409, 44413, 44417, 44421, 44425, 44429, 44433, 44437, 44441, 44445, - 44449, 44453, 44457, 44461, 44465, 44469, 44473, 44477, 44481, 44485, - 44489, 44493, 44497, 44501, 44505, 44509, 44513, 44517, 44521, 44525, - 44529, 44533, 44537, 44541, 44545, 44549, 44553, 44557, 44561, 44565, - 44569, 44573, 44577, 44581, 44585, 44589, 44593, 44597, 44601, 44605, - 44609, 44613, 44617, 44621, 44625, 44629, 44633, 44637, 44641, 44645, - 44649, 44653, 44657, 44661, 44665, 44669, 44673, 44677, 44681, 44685, - 44689, 44693, 44697, 44701, 44705, 44709, 44713, 44717, 44721, 44725, - 44729, 44733, 44737, 44741, 44745, 44749, 44753, 44758, 44762, 44767, - 44771, 44776, 44780, 44785, 44789, 44795, 44800, 44804, 44809, 44813, - 44818, 44822, 44827, 44831, 44836, 44840, 44845, 44849, 44854, 44858, - 44864, 44870, 44875, 44879, 44884, 44888, 44894, 44899, 44903, 44908, - 44912, 44917, 44921, 44927, 44932, 44936, 44941, 44945, 44950, 44954, - 44959, 44963, 44969, 44974, 44978, 44983, 44987, 44993, 44998, 45002, - 45007, 45011, 45016, 45020, 45025, 45029, 45034, 45038, 45044, 45049, - 45053, 45059, 45064, 45068, 45074, 45079, 45083, 45088, 45092, 45097, - 45101, 45107, 45113, 45119, 45125, 45131, 45137, 45143, 45149, 45154, - 45158, 45163, 45167, 45173, 45178, 45182, 45187, 45191, 45196, 45200, - 45205, 45209, 45214, 45218, 45223, 45227, 45232, 45236, 45242, 45247, - 45251, 45256, 45260, 45266, 45272, 45277, 127, 63, 45281, 45283, 45287, - 45291, 45295, 45300, 45304, 45308, 45313, 11153, 45318, 45324, 1677, - 7181, 45330, 45333, 45338, 45342, 45347, 45351, 45355, 45360, 12233, - 45364, 45368, 45372, 630, 45376, 18561, 45381, 45385, 45390, 45395, - 45400, 45404, 45411, 45417, 45423, 31790, 45428, 45431, 45435, 45440, - 45446, 45450, 45453, 45461, 45467, 45472, 45476, 45479, 45483, 45489, - 45493, 45497, 3811, 3816, 15084, 45500, 45504, 45508, 45512, 45516, - 45524, 45531, 45535, 15958, 45542, 45556, 45563, 45574, 361, 45579, - 45583, 45589, 45601, 45607, 45613, 45618, 45624, 18613, 45628, 45632, - 35727, 45641, 45647, 45656, 45660, 45664, 45669, 45675, 45680, 45684, - 45689, 45693, 45697, 45704, 45710, 45715, 45726, 45741, 45756, 45771, - 45787, 45805, 12140, 45819, 45826, 45832, 45836, 45839, 45848, 45853, - 45857, 45865, 19242, 45873, 45877, 45887, 45898, 35617, 1042, 45911, - 45920, 45938, 45957, 45966, 45974, 45982, 1690, 12342, 45986, 27374, - 45989, 31556, 45994, 11478, 45999, 46005, 46010, 46016, 46021, 46027, - 46032, 46038, 46043, 46049, 46055, 46061, 46066, 46022, 46028, 46070, - 46033, 46039, 46044, 46075, 46050, 46056, 9184, 4434, 46081, 46089, - 46093, 46096, 46103, 46107, 46112, 46117, 46124, 46130, 46136, 46141, - 17850, 46145, 31573, 46149, 46153, 46157, 46164, 46170, 46174, 33931, - 46183, 10351, 46187, 10780, 46190, 46197, 46203, 46207, 14381, 46214, - 46220, 46225, 46232, 46239, 46246, 34730, 9081, 46253, 46260, 46267, - 46273, 46278, 46285, 46296, 46302, 46307, 46312, 46317, 46321, 46326, - 46333, 46023, 46337, 46347, 46356, 46367, 46373, 46381, 46388, 46393, - 46398, 46403, 46408, 46413, 46417, 46421, 46428, 46434, 46442, 2416, - 30582, 12245, 12257, 12262, 12268, 46451, 12273, 12278, 12284, 46456, - 46466, 46470, 12289, 46475, 20484, 46478, 46483, 46487, 46491, 46502, - 46510, 42204, 46518, 46523, 46530, 46537, 46541, 46544, 46552, 12153, - 46559, 46562, 46568, 46578, 6767, 46587, 46592, 46598, 46602, 46610, - 46614, 46624, 46630, 46635, 46646, 46655, 46664, 46673, 46682, 46691, - 46700, 46709, 46715, 46721, 46726, 46732, 46738, 46744, 46749, 46752, - 46759, 46765, 46769, 46774, 46781, 46788, 46792, 46795, 46805, 46818, - 46827, 46836, 46847, 46860, 46872, 46883, 46892, 46903, 46908, 46917, - 46922, 12294, 46928, 46935, 46943, 46950, 46955, 46960, 31836, 46964, - 46971, 4374, 25, 46975, 46980, 20333, 46984, 46987, 46990, 34122, 46994, - 34739, 47002, 47006, 47010, 47013, 47019, 47025, 47030, 37782, 47039, - 47047, 47053, 47060, 34105, 47064, 34342, 47068, 47077, 47081, 47089, - 47095, 47101, 47106, 47110, 34765, 47116, 47119, 47127, 47135, 47143, - 4772, 47149, 47153, 47157, 47162, 47169, 47175, 47180, 47185, 47189, - 47195, 47200, 47206, 4662, 820, 47213, 47217, 47220, 47232, 47239, 47244, - 18434, 47248, 47256, 47264, 47272, 47280, 47287, 47295, 47303, 47310, - 47318, 47326, 47334, 47342, 47350, 47358, 47366, 47374, 47382, 47390, - 47398, 47405, 47413, 47421, 47429, 47437, 47445, 47453, 47461, 47469, - 47477, 47485, 47493, 47501, 47509, 47517, 47525, 47533, 47541, 47549, - 47557, 47564, 47572, 47579, 47587, 47595, 47603, 47611, 47619, 47627, - 47635, 47643, 47654, 26794, 47659, 47662, 47669, 47673, 47679, 47683, - 47689, 47694, 47700, 47705, 47710, 47714, 47718, 47725, 47733, 47738, - 47743, 47753, 47759, 47772, 47778, 47784, 47790, 47793, 47800, 47805, - 4700, 47811, 4869, 965, 47816, 47819, 47822, 47825, 37866, 37872, 47828, - 37878, 37891, 37897, 37903, 47834, 37909, 37915, 47840, 47846, 10, 47854, - 47861, 47865, 47869, 47877, 38726, 47881, 47885, 47892, 47897, 47901, - 47906, 47912, 47917, 47923, 47928, 47932, 47936, 47940, 47945, 47949, - 47954, 47958, 47962, 47969, 47974, 47978, 47982, 47987, 47991, 47996, - 48000, 48004, 48009, 48015, 18743, 18748, 48020, 48024, 48027, 48033, - 48037, 48041, 25750, 48046, 48050, 48056, 48063, 48069, 48074, 40797, - 48084, 48089, 48097, 48101, 48104, 48108, 38741, 48116, 4738, 48121, - 48126, 48130, 48135, 48139, 48144, 16026, 48155, 48159, 48162, 48166, - 48174, 48179, 48183, 48188, 48193, 48197, 48201, 48205, 48208, 48212, - 48215, 48220, 48225, 48230, 48235, 48240, 48245, 8664, 16042, 48250, - 48253, 48259, 48264, 48270, 48275, 48281, 48286, 48292, 48297, 48303, - 48309, 48315, 48320, 48324, 48328, 48339, 48347, 48354, 48360, 48365, - 48376, 48386, 48392, 48397, 48404, 48413, 48429, 48445, 48455, 34007, - 48462, 48466, 48471, 48476, 48480, 48484, 43937, 48490, 48495, 48499, - 48506, 48511, 48516, 48520, 48523, 48527, 48533, 32802, 48537, 26108, - 48542, 48549, 48557, 48563, 48569, 48576, 48584, 48590, 48594, 48599, - 48605, 48613, 48618, 48622, 48631, 11134, 48639, 48643, 48651, 48658, - 48663, 48668, 48673, 48677, 48680, 48686, 48690, 48693, 48697, 48704, - 48709, 48716, 48720, 48726, 48730, 48736, 48741, 48746, 5107, 5114, - 48751, 48760, 48768, 48773, 48779, 48791, 48804, 48818, 48825, 48831, - 48837, 48842, 48850, 48853, 48855, 48866, 48878, 48889, 48904, 48921, - 48941, 48963, 48970, 48977, 48984, 48990, 48994, 8663, 48997, 49001, - 49005, 49010, 49014, 49018, 49021, 49025, 49039, 28019, 49058, 49071, - 49084, 49097, 28037, 49112, 2808, 49127, 49133, 49137, 49147, 49151, - 49155, 49160, 49164, 49171, 49176, 49180, 49187, 49193, 49198, 49204, - 49214, 49226, 49237, 49242, 49249, 49253, 49257, 49260, 49268, 19263, - 4141, 49273, 18782, 49286, 49293, 49300, 49306, 49310, 49314, 49319, - 49325, 49330, 49336, 49340, 49344, 49347, 49352, 49356, 49361, 49366, - 49371, 49376, 49381, 49386, 49391, 49396, 49401, 8727, 18793, 49406, - 49410, 49416, 49425, 49430, 49439, 49446, 43768, 49452, 49457, 49461, - 49468, 49473, 49480, 49488, 49494, 49498, 49501, 49505, 49510, 2886, - 49517, 49524, 49528, 49531, 49536, 49541, 49547, 49552, 49557, 49561, - 49566, 49576, 49581, 49587, 49592, 49599, 47234, 49605, 49611, 49619, - 49629, 49634, 49639, 49643, 49648, 49653, 8167, 8179, 49658, 49661, - 49668, 49674, 49683, 10268, 41421, 49691, 49695, 49699, 38789, 49707, - 49718, 49726, 43985, 49733, 49738, 49743, 49754, 49761, 49772, 38813, - 26125, 49780, 4652, 49785, 16459, 49791, 34096, 49797, 49802, 49812, - 49821, 49828, 49834, 49838, 49841, 49848, 49854, 49861, 49867, 49877, - 49885, 49891, 49897, 49902, 49906, 49913, 49918, 49924, 49931, 49937, - 49006, 49942, 49946, 16501, 16510, 16519, 16528, 16537, 16566, 622, - 16575, 49952, 49957, 49960, 49966, 49974, 1275, 49979, 49983, 49988, - 49993, 49997, 50002, 50009, 50015, 50019, 50024, 50030, 50034, 37939, - 50039, 50044, 50053, 50060, 50070, 50076, 34140, 50093, 50102, 50110, - 50116, 50121, 50128, 50134, 50142, 50151, 50159, 50167, 50173, 50177, - 50182, 50190, 35288, 38822, 50196, 50215, 19166, 50229, 50245, 50259, - 50265, 50270, 50275, 50280, 50286, 38828, 50291, 50294, 50301, 50308, - 50317, 50322, 50326, 423, 3176, 50333, 50338, 50343, 33196, 50131, 50347, - 50355, 50360, 50368, 50372, 50375, 50380, 50386, 50392, 50397, 50401, - 34213, 50404, 50409, 50413, 50416, 50421, 50425, 50430, 50435, 50439, - 50444, 50448, 50455, 50459, 50463, 25746, 25757, 50468, 50473, 50479, - 50484, 50490, 50496, 32758, 50501, 50505, 50508, 50514, 50519, 50524, - 50529, 50534, 50539, 50544, 50549, 50554, 50560, 50566, 14569, 19473, - 50571, 50576, 50581, 50586, 50591, 50596, 50601, 50606, 452, 68, 37956, - 37961, 37966, 37972, 37977, 37982, 50611, 37986, 50615, 50619, 50623, - 37991, 37997, 50637, 38008, 38013, 50645, 50650, 38019, 50655, 50660, - 50669, 50674, 50679, 50688, 50694, 50700, 50706, 38036, 50719, 50728, - 50734, 38040, 50738, 38045, 50743, 38050, 38055, 50746, 50751, 50755, - 50761, 16267, 50768, 16277, 50775, 50780, 38060, 50784, 50789, 50794, - 50799, 50804, 50808, 50813, 50818, 50824, 50829, 50834, 50840, 50846, - 50851, 50855, 50860, 50865, 50870, 50874, 50879, 50884, 50889, 50895, - 50901, 50907, 50912, 50916, 50921, 50925, 38064, 38069, 38074, 50929, - 50933, 50938, 50942, 50954, 38079, 38085, 38091, 38103, 50960, 31616, - 50964, 50969, 50973, 50978, 50985, 50990, 50995, 51000, 51004, 51008, - 51018, 51023, 51028, 51032, 51042, 51046, 51049, 51057, 51062, 38151, - 51066, 1375, 51072, 51077, 51083, 51091, 51095, 51104, 51112, 51116, - 51120, 51128, 51134, 51142, 51158, 51163, 51167, 51171, 51175, 51180, - 51186, 51201, 38188, 1685, 14601, 51205, 1254, 1269, 51217, 51225, 51232, - 51237, 9230, 51244, 51249, 10765, 978, 2641, 12321, 51256, 10658, 51261, - 51264, 51273, 1162, 51278, 49177, 51285, 51294, 51299, 51303, 51311, - 51318, 27424, 2697, 51326, 12842, 51336, 51342, 2434, 2444, 51351, 51360, - 51370, 51381, 3584, 41818, 51386, 4341, 4352, 9258, 1167, 51390, 51398, - 51405, 51410, 51414, 51418, 51423, 29054, 49512, 12412, 51431, 51440, - 51449, 51457, 51470, 51477, 51488, 51493, 51506, 51519, 51531, 51543, - 51555, 51566, 51579, 51590, 51601, 51611, 51619, 51627, 51639, 51651, - 51662, 51671, 51679, 51686, 51698, 51705, 51711, 51720, 51726, 51733, - 51746, 51751, 51761, 51766, 51772, 51777, 32098, 51781, 48682, 51788, - 51795, 51803, 51810, 2654, 51817, 51828, 51838, 51847, 51855, 51865, - 51873, 51882, 51892, 51901, 51906, 51912, 51918, 4190, 51929, 51939, - 51948, 51957, 51965, 51975, 51983, 51992, 51997, 52002, 52007, 1604, 47, - 52015, 52023, 52034, 52045, 19877, 52055, 52059, 52066, 52072, 52077, - 52081, 52092, 52102, 52111, 52122, 52127, 20306, 20311, 52134, 52143, - 52148, 52158, 52163, 52171, 52179, 52186, 52192, 1566, 271, 52196, 52201, - 52207, 46085, 52212, 52215, 2182, 2663, 52223, 52227, 52230, 1420, 52236, - 16787, 1172, 52241, 52254, 2797, 2818, 52268, 52280, 52292, 2832, 2849, - 2864, 2880, 2897, 52306, 52318, 2912, 52332, 1178, 1184, 1190, 12713, - 52337, 52342, 52347, 52351, 52366, 52381, 52396, 52411, 52426, 52441, - 52456, 52471, 52486, 52501, 52516, 52531, 52546, 52561, 52576, 52591, - 52606, 52621, 52636, 52651, 52666, 52681, 52696, 52711, 52726, 52741, - 52756, 52771, 52786, 52801, 52816, 52831, 52846, 52861, 52876, 52891, - 52906, 52921, 52936, 52951, 52966, 52981, 52996, 53011, 53026, 53041, - 53056, 53071, 53086, 53101, 53116, 53131, 53146, 53161, 53176, 53191, - 53206, 53221, 53236, 53251, 53266, 53281, 53296, 53311, 53326, 53341, - 53356, 53371, 53386, 53401, 53416, 53431, 53446, 53461, 53476, 53491, - 53506, 53521, 53536, 53551, 53566, 53581, 53596, 53611, 53626, 53641, - 53656, 53671, 53686, 53701, 53716, 53731, 53746, 53761, 53776, 53791, - 53806, 53821, 53836, 53851, 53866, 53881, 53896, 53911, 53926, 53941, - 53956, 53971, 53986, 54001, 54016, 54031, 54046, 54061, 54076, 54091, - 54106, 54121, 54136, 54151, 54166, 54181, 54196, 54211, 54226, 54241, - 54256, 54271, 54286, 54301, 54316, 54331, 54346, 54361, 54376, 54391, - 54406, 54421, 54436, 54451, 54466, 54481, 54496, 54511, 54526, 54541, - 54556, 54571, 54586, 54601, 54616, 54631, 54646, 54661, 54676, 54691, - 54706, 54721, 54736, 54751, 54766, 54781, 54796, 54811, 54826, 54841, - 54856, 54871, 54886, 54901, 54916, 54931, 54946, 54961, 54976, 54991, - 55006, 55021, 55036, 55051, 55066, 55081, 55096, 55111, 55126, 55141, - 55156, 55171, 55186, 55201, 55216, 55231, 55246, 55261, 55276, 55291, - 55306, 55321, 55336, 55351, 55366, 55381, 55396, 55411, 55426, 55441, - 55456, 55471, 55486, 55501, 55516, 55531, 55546, 55561, 55576, 55591, - 55606, 55621, 55636, 55651, 55666, 55681, 55696, 55711, 55726, 55741, - 55756, 55771, 55786, 55801, 55816, 55831, 55846, 55861, 55876, 55891, - 55906, 55921, 55936, 55951, 55966, 55981, 55996, 56011, 56026, 56041, - 56056, 56071, 56086, 56101, 56116, 56131, 56146, 56161, 56176, 56191, - 56206, 56221, 56236, 56251, 56266, 56281, 56296, 56311, 56326, 56341, - 56356, 56371, 56386, 56401, 56416, 56431, 56446, 56461, 56476, 56491, - 56506, 56521, 56536, 56551, 56566, 56581, 56596, 56611, 56626, 56641, - 56656, 56671, 56686, 56701, 56716, 56731, 56746, 56761, 56776, 56791, - 56806, 56821, 56836, 56851, 56866, 56881, 56896, 56911, 56926, 56941, - 56956, 56971, 56986, 57001, 57016, 57031, 57046, 57061, 57076, 57091, - 57106, 57121, 57136, 57151, 57166, 57181, 57196, 57211, 57226, 57241, - 57256, 57271, 57286, 57301, 57316, 57331, 57346, 57361, 57376, 57391, - 57406, 57421, 57436, 57451, 57466, 57481, 57496, 57511, 57526, 57541, - 57556, 57571, 57586, 57601, 57616, 57631, 57646, 57661, 57676, 57691, - 57706, 57721, 57736, 57751, 57766, 57781, 57796, 57811, 57826, 57841, - 57856, 57871, 57886, 57901, 57916, 57931, 57946, 57961, 57976, 57991, - 58006, 58021, 58036, 58051, 58066, 58081, 58096, 58111, 58126, 58141, - 58156, 58171, 58186, 58201, 58216, 58231, 58246, 58261, 58276, 58291, - 58306, 58321, 58336, 58351, 58366, 58381, 58396, 58411, 58426, 58441, - 58456, 58471, 58486, 58501, 58516, 58531, 58546, 58561, 58576, 58591, - 58606, 58621, 58636, 58651, 58666, 58681, 58696, 58711, 58726, 58741, - 58756, 58771, 58786, 58801, 58816, 58831, 58846, 58861, 58876, 58891, - 58906, 58921, 58936, 58951, 58966, 58981, 58996, 59011, 59026, 59041, - 59056, 59071, 59086, 59101, 59116, 59131, 59146, 59161, 59176, 59191, - 59206, 59221, 59236, 59251, 59266, 59281, 59296, 59311, 59326, 59341, - 59356, 59371, 59386, 59401, 59416, 59431, 59446, 59461, 59476, 59491, - 59506, 59521, 59536, 59551, 59566, 59581, 59596, 59611, 59626, 59641, - 59656, 59671, 59686, 59701, 59716, 59731, 59746, 59761, 59776, 59791, - 59806, 59821, 59836, 59851, 59866, 59881, 59896, 59911, 59926, 59941, - 59956, 59971, 59986, 60001, 60016, 60031, 60046, 60061, 60076, 60091, - 60106, 60121, 60136, 60151, 60166, 60182, 60198, 60214, 60230, 60246, - 60262, 60278, 60294, 60310, 60326, 60342, 60358, 60374, 60390, 60406, - 60422, 60438, 60454, 60470, 60486, 60502, 60518, 60534, 60550, 60566, - 60582, 60598, 60614, 60630, 60646, 60662, 60678, 60694, 60710, 60726, - 60742, 60758, 60774, 60790, 60806, 60822, 60838, 60854, 60870, 60886, - 60902, 60918, 60934, 60950, 60966, 60982, 60998, 61014, 61030, 61046, - 61062, 61078, 61094, 61110, 61126, 61142, 61158, 61174, 61190, 61206, - 61222, 61238, 61254, 61270, 61286, 61302, 61318, 61334, 61350, 61366, - 61382, 61398, 61414, 61430, 61446, 61462, 61478, 61494, 61510, 61526, - 61542, 61558, 61574, 61590, 61606, 61622, 61638, 61654, 61670, 61686, - 61702, 61718, 61734, 61750, 61766, 61782, 61798, 61814, 61830, 61846, - 61862, 61878, 61894, 61910, 61926, 61942, 61958, 61974, 61990, 62006, - 62022, 62038, 62054, 62070, 62086, 62102, 62118, 62134, 62150, 62166, - 62182, 62198, 62214, 62230, 62246, 62262, 62278, 62294, 62310, 62326, - 62342, 62358, 62374, 62390, 62406, 62422, 62438, 62454, 62470, 62486, - 62502, 62518, 62534, 62550, 62566, 62582, 62598, 62614, 62630, 62646, - 62662, 62678, 62694, 62710, 62726, 62742, 62758, 62774, 62790, 62806, - 62822, 62838, 62854, 62870, 62886, 62902, 62918, 62934, 62950, 62966, - 62982, 62998, 63014, 63030, 63046, 63062, 63078, 63094, 63110, 63126, - 63142, 63158, 63174, 63190, 63206, 63222, 63238, 63254, 63270, 63286, - 63302, 63318, 63334, 63350, 63366, 63382, 63398, 63414, 63430, 63446, - 63462, 63478, 63494, 63510, 63526, 63542, 63558, 63574, 63590, 63606, - 63622, 63638, 63654, 63670, 63686, 63702, 63718, 63734, 63750, 63766, - 63782, 63798, 63814, 63830, 63846, 63862, 63878, 63894, 63910, 63926, - 63942, 63958, 63974, 63990, 64006, 64022, 64038, 64054, 64070, 64086, - 64102, 64118, 64134, 64150, 64166, 64182, 64198, 64214, 64230, 64246, - 64262, 64278, 64294, 64310, 64326, 64342, 64358, 64374, 64390, 64406, - 64422, 64438, 64454, 64470, 64486, 64502, 64518, 64534, 64550, 64566, - 64582, 64598, 64614, 64630, 64646, 64662, 64678, 64694, 64710, 64726, - 64742, 64758, 64774, 64790, 64806, 64822, 64838, 64854, 64870, 64886, - 64902, 64918, 64934, 64950, 64966, 64982, 64998, 65014, 65030, 65046, - 65062, 65078, 65094, 65110, 65126, 65142, 65158, 65174, 65190, 65206, - 65222, 65238, 65254, 65270, 65286, 65302, 65318, 65334, 65350, 65366, - 65382, 65398, 65414, 65430, 65446, 65462, 65478, 65494, 65510, 65526, - 65542, 65558, 65574, 65590, 65606, 65622, 65638, 65654, 65670, 65686, - 65702, 65718, 65734, 65750, 65766, 65782, 65798, 65814, 65830, 65846, - 65862, 65878, 65894, 65910, 65926, 65942, 65958, 65974, 65990, 66006, - 66022, 66038, 66054, 66070, 66086, 66102, 66118, 66134, 66150, 66166, - 66182, 66198, 66214, 66230, 66246, 66262, 66278, 66294, 66310, 66326, - 66342, 66358, 66374, 66390, 66406, 66422, 66438, 66454, 66470, 66486, - 66502, 66518, 66534, 66550, 66566, 66582, 66598, 66614, 66630, 66646, - 66662, 66678, 66694, 66710, 66726, 66742, 66758, 66774, 66790, 66806, - 66822, 66838, 66854, 66870, 66886, 66902, 66918, 66934, 66950, 66966, - 66982, 66998, 67014, 67030, 67046, 67062, 67078, 67094, 67110, 67126, - 67142, 67158, 67174, 67190, 67206, 67222, 67238, 67254, 67270, 67286, - 67302, 67318, 67334, 67350, 67366, 67382, 67398, 67414, 67430, 67446, - 67462, 67478, 67494, 67510, 67526, 67542, 67558, 67574, 67590, 67606, - 67622, 67638, 67654, 67670, 67686, 67702, 67718, 67734, 67750, 67766, - 67782, 67798, 67814, 67830, 67846, 67862, 67878, 67894, 67910, 67926, - 67942, 67958, 67974, 67990, 68006, 68022, 68038, 68054, 68070, 68086, - 68102, 68118, 68134, 68150, 68166, 68182, 68198, 68214, 68230, 68246, - 68262, 68278, 68294, 68310, 68326, 68342, 68358, 68374, 68390, 68406, - 68422, 68438, 68454, 68470, 68486, 68502, 68518, 68534, 68550, 68566, - 68582, 68598, 68614, 68630, 68646, 68662, 68678, 68694, 68710, 68726, - 68742, 68758, 68774, 68790, 68806, 68822, 68838, 68847, 68862, 68876, - 68885, 17689, 68889, 68894, 68900, 68906, 68916, 68924, 17946, 18677, - 9277, 68937, 1428, 1432, 68945, 4270, 33321, 8104, 68951, 68956, 68961, - 68966, 68971, 68977, 68982, 68988, 68993, 68999, 69004, 69009, 69014, - 69019, 69025, 69030, 69035, 69040, 69045, 69050, 69055, 69060, 69066, - 69071, 69077, 69084, 2701, 69089, 69095, 9652, 69099, 69104, 69111, - 69119, 4281, 4286, 4291, 4296, 65, 69123, 69129, 69134, 69139, 69143, - 69148, 69152, 69156, 12785, 69160, 69170, 69183, 69194, 69207, 69214, - 69220, 69228, 69235, 12246, 69244, 69249, 69255, 69261, 69267, 69272, - 69277, 69282, 69287, 69291, 69296, 69301, 69306, 69312, 69318, 69324, - 69329, 69333, 69338, 69343, 69347, 69352, 69357, 69362, 69366, 12801, - 12812, 12817, 1471, 69370, 69376, 1476, 19711, 69381, 19720, 1486, 69386, - 69392, 69397, 1507, 69403, 1513, 1519, 12847, 69408, 69417, 69425, 69433, - 69440, 69444, 69448, 69454, 69459, 37599, 69464, 69471, 69479, 69486, - 69491, 69495, 69499, 69508, 69513, 69518, 69523, 1524, 280, 69528, 69533, - 69537, 19846, 987, 69541, 69548, 69553, 69557, 19904, 1528, 46361, 69560, - 69565, 69575, 69584, 69589, 69593, 69599, 1533, 49458, 69604, 69613, - 69619, 69624, 69629, 13086, 13092, 69635, 69648, 69660, 69677, 69694, - 69711, 69728, 69745, 69762, 69779, 69796, 69813, 69830, 69847, 69864, - 69881, 69898, 69915, 69932, 69949, 69966, 69983, 70000, 70017, 70034, - 70051, 70068, 70085, 70102, 70119, 70136, 70153, 70170, 70187, 70204, - 70221, 70238, 70255, 70272, 70289, 70306, 70323, 70340, 70357, 70374, - 70391, 70408, 70425, 70442, 70459, 70476, 70493, 70504, 70514, 70519, - 1538, 70523, 70528, 70534, 70539, 70544, 70551, 10677, 1543, 70557, - 70566, 33713, 70571, 70582, 13108, 70592, 70597, 70603, 70608, 70615, - 70621, 70626, 1548, 20198, 70631, 70637, 13118, 70643, 70648, 70653, - 70658, 70663, 70668, 70673, 70678, 1553, 4761, 70683, 70688, 70694, - 70699, 70704, 70709, 70714, 70719, 70724, 70729, 70734, 70740, 70746, - 70752, 70757, 70761, 70766, 70771, 70775, 70780, 70785, 70790, 70795, - 70799, 70804, 70810, 70815, 70820, 70824, 70829, 70834, 70840, 70845, - 70850, 70856, 70862, 70867, 70871, 70876, 70881, 70886, 70890, 70895, - 70900, 70905, 70911, 70917, 70922, 70926, 70930, 70935, 70940, 70945, - 35492, 70949, 70954, 70959, 70965, 70970, 70975, 70979, 70984, 70989, - 70995, 71000, 71005, 71011, 71017, 71022, 71026, 71031, 71036, 71040, - 71045, 71050, 71055, 71061, 71067, 71072, 71076, 71081, 71086, 71090, - 71095, 71100, 71105, 71110, 71114, 71117, 71120, 71125, 71130, 38335, - 71137, 71145, 50085, 71151, 3928, 33656, 71164, 71171, 71177, 71183, - 4107, 71188, 13260, 71194, 71204, 71219, 71227, 13265, 71238, 71243, - 71254, 71266, 71278, 71290, 2903, 71302, 71307, 31699, 71319, 71325, - 71331, 71336, 71345, 71352, 71357, 71362, 71367, 71372, 71377, 71382, - 1570, 19338, 71387, 71392, 71397, 71402, 71408, 71413, 71419, 71424, - 71429, 71435, 71440, 71445, 49532, 71449, 71453, 71458, 71462, 20346, - 71467, 71470, 71475, 71483, 71491, 1574, 13301, 13307, 1579, 71499, - 71506, 71511, 71520, 71530, 71537, 71542, 71547, 1584, 71554, 71559, - 20466, 71563, 71568, 71575, 71581, 71585, 71598, 71604, 71615, 71625, - 71632, 20488, 10571, 10578, 4355, 4361, 71639, 1589, 71644, 71653, 71659, - 71667, 71674, 71680, 71687, 71699, 71705, 71710, 71717, 71729, 71740, - 71750, 71759, 71769, 71779, 4249, 71787, 37393, 37402, 20528, 71800, - 71805, 71810, 71815, 71820, 71825, 71830, 1594, 1598, 71835, 71839, - 71842, 71853, 71858, 20554, 1608, 71866, 71871, 71876, 71888, 20587, - 71895, 71898, 71904, 71910, 71915, 71923, 1613, 71928, 71933, 71941, - 71949, 71956, 71965, 71973, 71982, 71986, 1618, 71995, 1623, 25931, - 72000, 72007, 72013, 20674, 72021, 72031, 72037, 72042, 72050, 72057, - 72066, 72074, 72084, 72093, 72103, 72112, 72123, 72133, 72143, 72152, - 72162, 72176, 72189, 72198, 72206, 72216, 72225, 72237, 72248, 72259, - 72269, 19966, 72274, 13453, 72283, 72289, 72294, 72301, 72307, 72314, - 72320, 19555, 72330, 72336, 72341, 72352, 72359, 72366, 72371, 72379, - 13470, 13475, 72387, 72393, 72397, 4339, 4350, 20750, 49635, 72405, - 72411, 72416, 72424, 72431, 14582, 72436, 72442, 72448, 1634, 72453, - 72456, 72462, 72467, 72472, 72477, 72482, 72487, 72492, 72497, 72502, - 72508, 72514, 1333, 72519, 72524, 72529, 72535, 72540, 72545, 72550, - 72555, 72560, 72565, 1643, 18, 72571, 72575, 72580, 72584, 72588, 72592, - 38621, 72597, 28238, 72602, 72607, 72611, 72614, 72618, 72622, 72627, - 72631, 72636, 72640, 72643, 72649, 42308, 42313, 42318, 72652, 72659, - 72665, 72673, 49230, 72683, 72689, 42324, 38885, 38636, 38642, 42340, - 38648, 72694, 72699, 72703, 38918, 72710, 72713, 72717, 72725, 72732, - 72737, 72740, 72745, 72750, 72754, 72758, 72761, 72771, 72783, 72790, - 72796, 38653, 72803, 40604, 72806, 9669, 13815, 72809, 72813, 72818, - 4159, 72822, 72825, 16320, 72832, 72839, 72852, 72867, 72881, 72897, - 72912, 72921, 72929, 72937, 72946, 72950, 72959, 72965, 72970, 72980, - 72993, 73005, 73012, 73017, 73026, 73039, 44032, 73057, 73062, 73069, - 73075, 73080, 895, 73085, 73093, 73100, 73107, 33137, 914, 73113, 73119, - 73124, 73134, 73142, 73148, 73153, 38672, 6858, 38686, 73157, 73167, - 73172, 73180, 73190, 73205, 73211, 73217, 73224, 38696, 73229, 73235, - 37737, 73239, 73243, 73248, 73257, 73264, 73269, 73273, 73278, 73286, - 20531, 73293, 73298, 73302, 6899, 38722, 73306, 73312, 341, 73322, 73329, - 73336, 73342, 73349, 73354, 73363, 15941, 69569, 69579, 73369, 73377, - 73381, 73385, 73389, 73393, 73398, 73402, 73408, 73416, 73421, 73426, - 73433, 73438, 73442, 73447, 73451, 73455, 73461, 73467, 73478, 73484, - 73489, 73493, 73498, 73502, 38846, 73506, 38852, 38858, 73511, 73517, - 73524, 73529, 73533, 37754, 20185, 73536, 73540, 73545, 73552, 73558, - 73562, 73567, 48699, 73573, 73577, 73584, 73588, 73593, 73599, 73605, - 73611, 73623, 73632, 73642, 73648, 73655, 73660, 73665, 73669, 73672, - 73678, 73685, 73690, 73695, 73702, 73709, 73716, 73722, 73727, 73732, - 73740, 38863, 2531, 73745, 73750, 73756, 73761, 73767, 73772, 73777, - 73782, 73788, 38884, 73793, 73799, 73805, 73811, 38954, 73816, 73821, - 73826, 38965, 73831, 73836, 73841, 73847, 73853, 38970, 73858, 73863, - 73868, 39025, 39031, 73873, 73878, 39036, 39058, 33998, 39064, 39068, - 73883, 14258, 73887, 73895, 73901, 73909, 73916, 73922, 73932, 73938, - 73945, 12685, 39082, 73951, 73964, 73973, 73979, 73988, 73994, 74000, - 74007, 28581, 74015, 74022, 74032, 74040, 74043, 39026, 74048, 74055, - 74060, 74064, 74068, 74073, 74077, 4478, 74082, 74087, 74092, 42402, - 42407, 74096, 42421, 74101, 42426, 74106, 74112, 42438, 42444, 42450, - 74117, 74123, 27479, 74134, 74137, 74149, 74157, 39105, 74161, 74170, - 74180, 74189, 39115, 74194, 74201, 74210, 74216, 74224, 74231, 74238, - 6950, 5174, 74243, 39037, 74249, 74252, 74258, 74265, 74270, 74275, - 28485, 74279, 74285, 74291, 74296, 74301, 74305, 74311, 74317, 40488, - 74322, 43626, 45463, 45469, 39146, 39151, 74326, 74330, 74334, 74337, - 74350, 74356, 74360, 74363, 74368, 40870, 74372, 37759, 25872, 74378, - 6879, 6887, 10377, 74381, 74386, 74391, 74396, 74401, 74406, 74411, - 74416, 74421, 74426, 74432, 74437, 74442, 74448, 74453, 74458, 74463, - 74468, 74473, 74478, 74484, 74489, 74495, 74500, 74505, 74510, 74515, - 74520, 74525, 74530, 74535, 74540, 74545, 74551, 74556, 74561, 74566, - 74571, 74576, 74581, 74587, 74592, 74597, 74602, 74607, 74612, 74617, - 74622, 74627, 74632, 74638, 74643, 74648, 74653, 74658, 74664, 74670, - 74675, 74681, 74686, 74691, 74696, 74701, 74706, 1421, 159, 74711, 74715, - 74719, 74723, 30435, 74727, 74731, 74736, 74740, 74745, 74749, 74754, - 74759, 74764, 74769, 74773, 74777, 74782, 74786, 16020, 74791, 74795, - 74802, 74812, 18315, 74821, 74830, 74839, 74843, 74848, 74853, 74857, - 74861, 30215, 3259, 74865, 74871, 21763, 74875, 74884, 74892, 74898, - 74903, 74915, 74927, 74932, 74936, 74941, 74945, 74951, 74957, 74962, - 74972, 74982, 74988, 74996, 75001, 75005, 75011, 75016, 75023, 75029, - 75034, 75041, 75050, 75059, 75067, 75071, 18871, 75074, 75083, 75091, - 75103, 75114, 75125, 75134, 75138, 75147, 75155, 75165, 75173, 75180, - 75190, 75196, 75201, 75209, 75216, 75225, 75231, 75236, 75243, 75249, - 75260, 60, 37536, 75266, 31986, 31996, 75272, 75280, 75287, 75293, 75297, - 75307, 75318, 75326, 75335, 75340, 75345, 75350, 75354, 75358, 75366, - 21710, 75373, 75377, 75383, 75393, 75400, 75407, 75413, 75419, 42501, - 75423, 75425, 75428, 75434, 75438, 75449, 75459, 75465, 75472, 75479, - 15957, 75487, 75493, 75502, 75511, 75517, 11579, 75523, 75529, 75534, - 75539, 75546, 75551, 75558, 75564, 75569, 75577, 75590, 75599, 75608, - 72138, 72148, 75618, 75624, 75633, 75639, 75645, 75652, 75659, 75666, - 75673, 75680, 75685, 75689, 75693, 75696, 75706, 75710, 75722, 75731, - 10038, 75740, 75751, 75756, 75760, 72157, 75766, 75773, 75782, 75790, - 51037, 75798, 75802, 75807, 75812, 75822, 75830, 75842, 75847, 75851, - 75855, 75861, 75869, 75876, 75888, 75896, 75907, 75914, 75920, 75930, - 75936, 75940, 75949, 75958, 75965, 75971, 75976, 75980, 75984, 75988, - 75997, 76006, 76015, 76022, 76028, 76034, 76040, 76045, 76052, 76058, - 76066, 76073, 76079, 15046, 76084, 76090, 76094, 17172, 76098, 76103, - 76113, 76118, 76127, 76133, 76139, 76147, 76154, 76158, 76162, 76169, - 76175, 76183, 76190, 76196, 76207, 76211, 76215, 76219, 76222, 76228, - 76233, 76238, 76242, 76246, 76255, 76263, 76270, 76276, 76283, 29245, - 48840, 76288, 76296, 76300, 76304, 76307, 76315, 76322, 76328, 76337, - 76345, 76351, 76356, 76360, 76365, 76370, 76374, 76378, 76382, 76387, - 76396, 76400, 76407, 45567, 76411, 76417, 76425, 76429, 76435, 76443, - 76449, 76454, 76465, 76473, 76479, 76488, 27626, 76496, 76503, 76510, - 76517, 76524, 76531, 52526, 15772, 76538, 76545, 76550, 42537, 4721, - 76556, 76561, 76566, 76572, 76578, 76584, 76589, 76594, 76599, 76604, - 76610, 76615, 76621, 76626, 76632, 76637, 76642, 76647, 76652, 76657, - 76662, 76667, 76673, 76678, 76684, 76689, 76694, 76699, 76704, 76709, - 76714, 76720, 76725, 76730, 76735, 76740, 76745, 76750, 76755, 76760, - 76765, 76770, 76776, 76781, 76786, 76791, 76796, 76801, 76806, 76811, - 76816, 76822, 76827, 76832, 76837, 76842, 76847, 76852, 76857, 76862, - 76867, 76872, 76877, 76882, 76888, 1883, 305, 76893, 46479, 46484, 76897, - 76902, 9293, 76906, 3628, 76911, 76916, 76920, 76929, 76940, 76957, - 76975, 76983, 75794, 76990, 76993, 77003, 77010, 77019, 77035, 77044, - 77054, 77059, 77072, 77082, 77091, 77099, 77113, 77121, 77130, 77134, - 77137, 77144, 77150, 77161, 77168, 77180, 77191, 77202, 77211, 77218, - 1173, 812, 77228, 2744, 77232, 77237, 77246, 997, 9059, 25308, 77254, - 77262, 77276, 77289, 77293, 77298, 77303, 77308, 77314, 77320, 77325, - 9661, 18358, 77330, 77334, 77338, 77346, 10098, 77351, 77357, 77366, - 77374, 1657, 13314, 1179, 4393, 77378, 77382, 77391, 77401, 2482, 32836, - 77410, 77416, 20438, 32851, 77422, 4558, 13696, 77428, 77435, 71848, - 77439, 77443, 77449, 77454, 77459, 3861, 163, 3887, 77464, 77476, 77480, - 77484, 77490, 77495, 33733, 77499, 13684, 2938, 4, 77504, 77514, 77525, - 77536, 77546, 77552, 77563, 77570, 77576, 77582, 2306, 77587, 77595, - 77602, 77608, 77618, 77628, 77638, 77647, 28568, 1185, 77652, 77656, - 77660, 77666, 77670, 2961, 2967, 9658, 2337, 77674, 77678, 77687, 77695, - 77706, 77714, 77722, 77728, 77733, 77744, 77755, 77763, 77769, 77774, - 11356, 77784, 77792, 77796, 77800, 77805, 77809, 77821, 34196, 18257, - 77828, 77838, 77844, 77850, 7977, 11490, 77860, 77871, 77882, 77892, - 77901, 77905, 77912, 999, 2731, 77922, 77927, 77935, 71564, 77943, 77948, - 77959, 77966, 77980, 16968, 529, 77990, 77997, 78001, 78005, 78013, - 78022, 4433, 78030, 78036, 20483, 78041, 78055, 78062, 78068, 78076, - 78085, 78094, 78101, 78113, 78123, 78131, 78138, 78146, 78153, 4357, 116, - 78161, 78172, 78176, 78188, 78194, 1804, 227, 78199, 10709, 78204, 3006, - 78208, 78215, 78221, 78232, 78242, 78250, 78257, 10049, 78264, 78273, - 78281, 4438, 78294, 4455, 78298, 78303, 78309, 78314, 78319, 78324, 3011, - 573, 78330, 78343, 78347, 78352, 78357, 3016, 1882, 763, 78361, 4459, - 78369, 78375, 78379, 799, 78389, 78398, 78403, 3878, 78407, 78411, 17989, - 17996, 9317, 78419, 4490, 4367, 15644, 78427, 78434, 78439, 28632, 78443, - 78450, 78456, 13952, 78461, 14017, 204, 78466, 78478, 78484, 78492, 3028, - 1699, 78500, 78502, 78507, 78512, 78517, 78523, 78528, 78533, 78538, - 78543, 78548, 78553, 78559, 78564, 78569, 78574, 78579, 78584, 78589, - 78594, 78599, 78605, 78610, 78615, 78620, 78626, 78631, 78637, 78642, - 78647, 78652, 78657, 78662, 78667, 78672, 78678, 78683, 78689, 78694, - 78699, 78704, 78709, 78714, 78719, 78724, 78729, 9730, 9743, 4506, 4511, - 4516, 4521, 26, 78735, 78741, 78746, 78751, 78756, 78762, 78767, 78771, - 78775, 78780, 78786, 78790, 78796, 78801, 78806, 78812, 78817, 78821, - 78826, 78831, 78835, 78838, 78840, 78844, 78847, 78854, 78859, 78863, - 78868, 78872, 78876, 78880, 78886, 78897, 78917, 78936, 78957, 78970, - 78982, 78991, 78995, 78998, 39423, 79001, 39428, 79008, 79013, 39433, - 79022, 79031, 39439, 79036, 39444, 79045, 79050, 13941, 79054, 79059, - 79064, 39449, 79068, 79077, 50696, 79081, 79084, 79088, 9325, 79094, - 79097, 79102, 79107, 79112, 79116, 4179, 39454, 79119, 79123, 79126, - 79137, 79142, 79146, 79152, 79160, 79173, 79177, 79185, 79194, 79200, - 79205, 79211, 79215, 79221, 79227, 79235, 79240, 79244, 79251, 79257, - 79265, 79274, 79282, 39457, 79289, 79299, 79308, 79316, 79327, 79340, - 79345, 79350, 79354, 79363, 79369, 79376, 79389, 79401, 79412, 79424, - 79431, 79440, 79449, 79458, 79465, 79471, 79478, 79486, 79493, 79501, - 79510, 79518, 79525, 79533, 79542, 79550, 79559, 79569, 79578, 79586, - 79593, 79601, 79610, 79618, 79627, 79637, 79646, 79654, 79663, 79673, - 79682, 79692, 79703, 79713, 79722, 79730, 79737, 79745, 79754, 79762, - 79771, 79781, 79790, 79798, 79807, 79817, 79826, 79836, 79847, 79857, - 79866, 79874, 79883, 79893, 79902, 79912, 79923, 79933, 79942, 79952, - 79963, 79973, 79984, 79996, 80007, 80017, 80026, 80034, 80041, 80049, - 80058, 80066, 80075, 80085, 80094, 80102, 80111, 80121, 80130, 80140, - 80151, 80161, 80170, 80178, 80187, 80197, 80206, 80216, 80227, 80237, - 80246, 80256, 80267, 80277, 80288, 80300, 80311, 80321, 80330, 80338, - 80347, 80357, 80366, 80376, 80387, 80397, 80406, 80416, 80427, 80437, - 80448, 80460, 80471, 80481, 80490, 80500, 80511, 80521, 80532, 80544, - 80555, 80565, 80576, 80588, 80599, 80611, 80624, 80636, 80647, 80657, - 80666, 80674, 80681, 80689, 80698, 80706, 80715, 80725, 80734, 80742, - 80751, 80761, 80770, 80780, 80791, 80801, 80810, 80818, 80827, 80837, - 80846, 80856, 80867, 80877, 80886, 80896, 80907, 80917, 80928, 80940, - 80951, 80961, 80970, 80978, 80987, 80997, 81006, 81016, 81027, 81037, - 81046, 81056, 81067, 81077, 81088, 81100, 81111, 81121, 81130, 81140, - 81151, 81161, 81172, 81184, 81195, 81205, 81216, 81228, 81239, 81251, - 81264, 81276, 81287, 81297, 81306, 81314, 81323, 81333, 81342, 81352, - 81363, 81373, 81382, 81392, 81403, 81413, 81424, 81436, 81447, 81457, - 81466, 81476, 81487, 81497, 81508, 81520, 81531, 81541, 81552, 81564, - 81575, 81587, 81600, 81612, 81623, 81633, 81642, 81652, 81663, 81673, - 81684, 81696, 81707, 81717, 81728, 81740, 81751, 81763, 81776, 81788, - 81799, 81809, 81820, 81832, 81843, 81855, 81868, 81880, 81891, 81903, - 81916, 81928, 81941, 81955, 81968, 81980, 81991, 82001, 82010, 82018, - 82025, 82030, 9090, 82037, 82042, 39467, 82048, 82053, 39472, 82059, - 82066, 25430, 31434, 82071, 82077, 82083, 82091, 82097, 82103, 82110, - 82117, 82122, 82127, 82131, 82136, 82140, 82143, 82147, 82152, 82161, - 82170, 82178, 82184, 82196, 82207, 82211, 3321, 9065, 82216, 82219, - 82222, 82224, 82228, 82232, 82236, 82242, 82247, 31497, 82252, 82256, - 82259, 82264, 82268, 82275, 82281, 82285, 7060, 82289, 82294, 39494, - 82298, 82305, 82314, 82322, 82328, 82339, 82347, 82356, 82364, 82371, - 82378, 82384, 82389, 82400, 39499, 82405, 82416, 82428, 82436, 82447, - 82456, 82464, 82475, 82480, 82488, 2696, 82493, 82502, 41891, 82515, - 82519, 82531, 82539, 82544, 82552, 82563, 21928, 82572, 82578, 82585, - 82593, 82599, 39509, 82604, 4484, 68920, 82611, 82614, 82622, 82635, - 82648, 82661, 82674, 82681, 82692, 82701, 82706, 52343, 52348, 82710, - 82714, 82722, 82729, 82738, 82746, 82752, 82761, 82769, 82776, 82784, - 82788, 82797, 82806, 82816, 82829, 82842, 82852, 39514, 82858, 82865, - 82871, 82877, 39520, 82882, 82885, 82889, 82897, 82906, 52114, 82914, - 82923, 82931, 82938, 82946, 82956, 82965, 82974, 41043, 82983, 82994, - 83009, 83019, 10747, 26246, 83028, 83033, 83038, 83042, 19547, 83047, - 83052, 83058, 83063, 83068, 83074, 83079, 83084, 26206, 83089, 83096, - 83104, 83112, 83120, 83125, 83132, 83139, 83144, 1717, 83148, 83152, - 83160, 83168, 39537, 83174, 83180, 83192, 83198, 83205, 83209, 83216, - 83221, 83228, 83234, 83241, 83252, 83262, 83272, 83284, 83290, 83298, - 83307, 83313, 83323, 83333, 39564, 83342, 83351, 83357, 83369, 83380, - 83387, 83392, 83396, 83404, 83415, 83421, 83426, 83431, 83438, 83446, - 83458, 83468, 83477, 83486, 83494, 83501, 41705, 29006, 83507, 83512, - 83516, 83520, 83525, 83533, 83539, 83550, 83563, 83568, 83575, 39569, - 83580, 83592, 83601, 83609, 83619, 83630, 83643, 83650, 83659, 83668, - 83676, 83681, 83687, 83691, 1410, 83696, 83701, 83706, 83711, 83717, - 83722, 83727, 83733, 83739, 83744, 83748, 83753, 83758, 83763, 69504, - 83768, 83773, 83778, 83783, 83789, 83795, 83800, 83804, 83809, 19546, - 83814, 83820, 83825, 83831, 83836, 83841, 83846, 83851, 83855, 83861, - 83866, 83875, 83880, 83885, 83890, 83895, 83899, 83906, 83912, 4836, - 20800, 3286, 83917, 83921, 83926, 83930, 83934, 83938, 56143, 83942, - 83867, 83944, 83954, 39578, 83957, 83962, 83971, 83977, 7019, 39583, - 83981, 83987, 83992, 83998, 84003, 84007, 84014, 84019, 84029, 84038, - 84042, 84048, 84054, 84060, 84064, 84072, 84079, 84087, 84095, 39588, - 84102, 84105, 84116, 84123, 84129, 84134, 84138, 84144, 84152, 84159, - 84164, 84168, 84177, 84185, 84191, 84196, 84203, 84211, 39593, 84218, - 28458, 84230, 84236, 84241, 84247, 84254, 84260, 25894, 33344, 84266, - 84271, 84277, 84281, 84293, 83900, 83907, 26138, 84303, 84308, 84315, - 84321, 84328, 84334, 84345, 84350, 84358, 10447, 84363, 84366, 84372, - 84376, 84380, 84383, 84389, 84395, 39282, 4837, 1425, 16069, 84402, - 84408, 84414, 84420, 84426, 84432, 84438, 84444, 84450, 84455, 84460, - 84465, 84470, 84475, 84480, 84485, 84490, 84495, 84500, 84505, 84510, - 84515, 84521, 84526, 84531, 84537, 84542, 84547, 84553, 84559, 84565, - 84571, 84577, 84583, 84589, 84595, 84601, 84606, 84611, 84617, 84622, - 84627, 84633, 84638, 84643, 84648, 84653, 84658, 84663, 84668, 84673, - 84678, 84683, 84688, 84693, 84699, 84704, 84709, 84714, 84720, 84725, - 84730, 84735, 84740, 84746, 84751, 84756, 84761, 84766, 84771, 84776, - 84781, 84786, 84791, 84796, 84801, 84806, 84811, 84816, 84821, 84826, - 84831, 84836, 84841, 84847, 84852, 84857, 84862, 84867, 84872, 84877, - 84882, 1065, 148, 84887, 84891, 84895, 84900, 84908, 84912, 84924, 84931, - 84939, 84943, 84956, 84964, 84969, 84974, 32049, 84978, 84983, 84987, - 84992, 84996, 85004, 85008, 25438, 85013, 85017, 72401, 85021, 85024, - 85032, 85040, 85048, 85053, 85058, 85065, 85072, 85078, 85084, 85089, - 85096, 85101, 85109, 77281, 85116, 85121, 72167, 85128, 85134, 85139, - 85143, 85150, 85156, 85163, 72194, 14031, 85171, 85176, 85181, 85185, - 85188, 85199, 85208, 85214, 85219, 85223, 85233, 85242, 50487, 85246, - 85250, 85257, 85270, 85276, 85284, 85291, 85300, 85311, 85322, 85333, - 85344, 85353, 85359, 85368, 85376, 85386, 85399, 85407, 85414, 85425, - 85434, 85440, 85445, 85450, 85456, 85466, 85472, 85482, 85490, 85497, - 85507, 85516, 83582, 85524, 85530, 85538, 85544, 75834, 85551, 85556, - 85559, 85563, 85569, 85573, 85576, 85584, 85590, 85596, 85604, 85616, - 85628, 85635, 85640, 85644, 85655, 85663, 85670, 85682, 85690, 85697, - 85705, 85712, 85718, 85723, 85729, 85739, 85748, 85756, 85761, 85771, - 85780, 51375, 85787, 85791, 85796, 85804, 85811, 85817, 85821, 85831, - 85842, 85850, 85857, 85869, 85881, 85890, 82505, 85897, 85907, 85919, - 85930, 85944, 85952, 85962, 85969, 85977, 85990, 86002, 86011, 86019, - 86029, 86040, 86052, 86061, 86071, 86081, 86091, 86100, 86107, 86116, - 86131, 86139, 86149, 86158, 86166, 86179, 68890, 86194, 86204, 86213, - 86225, 86235, 86247, 86258, 86272, 86286, 86300, 86314, 86328, 86342, - 86356, 86370, 86384, 86398, 86412, 86426, 86440, 86454, 86468, 86482, - 86496, 86510, 86524, 86538, 86552, 86566, 86580, 86594, 86608, 86622, - 86636, 86650, 86664, 86678, 86692, 86706, 86720, 86734, 86748, 86762, - 86776, 86790, 86804, 86818, 86832, 86846, 86860, 86874, 86888, 86902, - 86916, 86930, 86944, 86958, 86972, 86986, 87000, 87014, 87028, 87042, - 87056, 87070, 87084, 87098, 87112, 87126, 87140, 87154, 87168, 87182, - 87196, 87210, 87224, 87238, 87252, 87266, 87280, 87294, 87308, 87322, - 87336, 87350, 87364, 87378, 87392, 87406, 87420, 87434, 87448, 87462, - 87476, 87490, 87504, 87518, 87532, 87546, 87560, 87574, 87588, 87602, - 87616, 87630, 87644, 87658, 87672, 87686, 87700, 87714, 87728, 87742, - 87756, 87770, 87784, 87798, 87812, 87826, 87840, 87854, 87868, 87882, - 87896, 87910, 87924, 87938, 87952, 87966, 87980, 87994, 88008, 88022, - 88036, 88050, 88064, 88078, 88092, 88106, 88120, 88134, 88148, 88162, - 88176, 88190, 88204, 88218, 88232, 88246, 88260, 88274, 88288, 88302, - 88316, 88330, 88344, 88358, 88372, 88386, 88400, 88414, 88428, 88442, - 88456, 88470, 88484, 88498, 88512, 88526, 88540, 88554, 88568, 88582, - 88596, 88610, 88624, 88638, 88652, 88666, 88680, 88694, 88708, 88722, - 88736, 88750, 88764, 88778, 88792, 88806, 88820, 88834, 88848, 88862, - 88876, 88890, 88904, 88918, 88932, 88946, 88960, 88974, 88988, 89002, - 89016, 89030, 89044, 89058, 89072, 89086, 89100, 89114, 89128, 89142, - 89156, 89170, 89184, 89198, 89212, 89226, 89240, 89254, 89268, 89282, - 89296, 89310, 89324, 89338, 89352, 89366, 89380, 89394, 89408, 89422, - 89436, 89450, 89464, 89478, 89492, 89506, 89520, 89534, 89548, 89562, - 89576, 89590, 89604, 89618, 89632, 89646, 89660, 89674, 89688, 89702, - 89716, 89730, 89744, 89758, 89772, 89786, 89800, 89814, 89828, 89842, - 89856, 89870, 89884, 89898, 89912, 89926, 89940, 89954, 89968, 89982, - 89996, 90010, 90024, 90038, 90052, 90066, 90080, 90094, 90108, 90122, - 90136, 90150, 90164, 90178, 90192, 90206, 90220, 90234, 90248, 90262, - 90276, 90290, 90304, 90318, 90332, 90346, 90360, 90374, 90388, 90402, - 90416, 90430, 90444, 90458, 90472, 90486, 90500, 90514, 90528, 90542, - 90556, 90570, 90584, 90598, 90612, 90626, 90640, 90654, 90668, 90682, - 90696, 90710, 90724, 90738, 90752, 90766, 90780, 90794, 90808, 90822, - 90836, 90850, 90864, 90878, 90892, 90906, 90920, 90934, 90948, 90962, - 90976, 90990, 91004, 91018, 91032, 91046, 91060, 91074, 91088, 91102, - 91116, 91130, 91144, 91158, 91172, 91186, 91200, 91214, 91228, 91242, - 91256, 91270, 91284, 91298, 91312, 91326, 91340, 91354, 91368, 91382, - 91396, 91410, 91424, 91438, 91452, 91466, 91480, 91494, 91508, 91522, - 91536, 91550, 91564, 91578, 91592, 91606, 91620, 91634, 91648, 91662, - 91676, 91690, 91704, 91718, 91732, 91746, 91760, 91774, 91788, 91802, - 91816, 91830, 91844, 91858, 91872, 91886, 91900, 91914, 91928, 91942, - 91956, 91970, 91984, 91998, 92012, 92026, 92040, 92054, 92068, 92082, - 92096, 92110, 92124, 92138, 92152, 92166, 92180, 92194, 92208, 92222, - 92236, 92250, 92264, 92278, 92292, 92306, 92320, 92334, 92348, 92362, - 92376, 92390, 92404, 92418, 92432, 92446, 92460, 92474, 92488, 92502, - 92516, 92530, 92544, 92558, 92572, 92586, 92600, 92614, 92628, 92642, - 92656, 92670, 92684, 92698, 92712, 92726, 92740, 92754, 92768, 92782, - 92796, 92810, 92824, 92838, 92852, 92866, 92880, 92894, 92908, 92922, - 92936, 92950, 92964, 92978, 92992, 93006, 93020, 93034, 93048, 93062, - 93076, 93090, 93104, 93118, 93132, 93146, 93160, 93174, 93188, 93202, - 93216, 93230, 93244, 93258, 93272, 93286, 93300, 93314, 93328, 93342, - 93356, 93370, 93384, 93398, 93412, 93426, 93440, 93454, 93468, 93482, - 93496, 93510, 93524, 93538, 93552, 93566, 93580, 93594, 93608, 93622, - 93636, 93650, 93664, 93678, 93692, 93706, 93720, 93734, 93748, 93762, - 93776, 93790, 93804, 93818, 93832, 93846, 93860, 93874, 93888, 93902, - 93916, 93930, 93944, 93958, 93972, 93986, 94000, 94014, 94028, 94042, - 94056, 94070, 94084, 94098, 94112, 94126, 94140, 94154, 94168, 94182, - 94196, 94210, 94224, 94238, 94252, 94266, 94280, 94294, 94308, 94322, - 94336, 94350, 94364, 94378, 94392, 94406, 94420, 94434, 94448, 94462, - 94476, 94490, 94504, 94518, 94532, 94546, 94560, 94574, 94588, 94602, - 94616, 94630, 94644, 94658, 94672, 94686, 94700, 94714, 94728, 94742, - 94756, 94770, 94784, 94798, 94812, 94826, 94840, 94854, 94868, 94882, - 94896, 94910, 94924, 94938, 94952, 94966, 94980, 94994, 95008, 95022, - 95036, 95050, 95064, 95078, 95092, 95106, 95120, 95134, 95148, 95162, - 95176, 95190, 95204, 95218, 95232, 95246, 95260, 95274, 95288, 95302, - 95316, 95330, 95344, 95358, 95372, 95386, 95400, 95414, 95428, 95442, - 95456, 95470, 95484, 95498, 95512, 95526, 95540, 95554, 95568, 95582, - 95596, 95610, 95624, 95638, 95652, 95666, 95680, 95694, 95708, 95722, - 95736, 95750, 95764, 95778, 95792, 95806, 95820, 95834, 95848, 95862, - 95876, 95890, 95904, 95918, 95932, 95946, 95960, 95974, 95988, 96002, - 96016, 96030, 96044, 96058, 96072, 96086, 96100, 96114, 96128, 96142, - 96156, 96170, 96184, 96198, 96212, 96226, 96240, 96254, 96268, 96282, - 96296, 96310, 96324, 96338, 96352, 96366, 96380, 96394, 96408, 96422, - 96436, 96450, 96464, 96478, 96492, 96506, 96520, 96534, 96548, 96562, - 96576, 96590, 96604, 96618, 96632, 96646, 96660, 96674, 96688, 96702, - 96716, 96730, 96744, 96758, 96772, 96786, 96800, 96814, 96828, 96842, - 96856, 96870, 96884, 96898, 96912, 96926, 96940, 96954, 96968, 96982, - 96996, 97010, 97019, 97030, 97041, 97051, 97062, 97070, 97078, 97084, - 97094, 97102, 97108, 35368, 97113, 97119, 97128, 97140, 97145, 97152, - 11370, 21948, 97158, 97167, 97172, 97176, 97181, 97188, 97194, 97199, - 97204, 97212, 97220, 97230, 97235, 97243, 14513, 97247, 97253, 97259, - 97265, 97271, 97277, 97283, 97289, 97295, 97301, 97307, 97313, 97319, - 97325, 97331, 97337, 97343, 97349, 97355, 97361, 97367, 97373, 97379, - 97385, 97391, 97397, 97403, 97409, 97415, 97421, 97427, 97433, 97439, - 97445, 97451, 97457, 97463, 97470, 97476, 97482, 97488, 97494, 97500, - 97506, 97512, 97518, 97524, 97530, 97536, 97542, 97548, 97554, 97560, - 97566, 97572, 97578, 97584, 97590, 97596, 97602, 97608, 97614, 97620, - 97626, 97632, 97638, 97644, 97650, 97656, 97662, 97668, 97674, 97680, - 97686, 97692, 97698, 97704, 97710, 97716, 97722, 97728, 97734, 97740, - 97746, 97752, 97758, 97764, 97770, 97777, 97783, 97789, 97795, 97801, - 97807, 97813, 97819, 97825, 97831, 97837, 97843, 97846, 97848, 97863, - 97876, 97883, 97889, 97900, 97905, 97909, 97914, 97921, 97927, 97932, - 97940, 77884, 77894, 97946, 97953, 97963, 12672, 97970, 97975, 35616, - 97984, 97989, 97996, 98006, 98014, 98022, 98031, 98040, 98046, 98052, - 98057, 98064, 98071, 98076, 98080, 98088, 72211, 98093, 98102, 98110, - 98117, 98122, 98126, 98135, 98141, 98144, 98148, 98157, 98167, 84951, - 98176, 98180, 98188, 98192, 98198, 98209, 98219, 21957, 98230, 98239, - 98247, 98255, 98262, 72230, 9895, 98270, 98274, 98283, 98290, 98293, - 98297, 33215, 98300, 98304, 98309, 98326, 98338, 12630, 98350, 98355, - 98360, 98365, 25545, 98369, 98374, 98379, 98385, 98390, 6640, 98395, - 25549, 98400, 98405, 98411, 98418, 98423, 98428, 98434, 98440, 98446, - 98451, 98457, 98461, 98475, 98483, 98491, 98497, 98502, 98509, 98519, - 98528, 98533, 98538, 98543, 98551, 98561, 98572, 98577, 98583, 98588, - 98597, 70639, 4760, 98602, 98620, 98639, 98652, 98666, 98682, 98689, - 98696, 98705, 98712, 98718, 98725, 98730, 98736, 98741, 98747, 98755, - 98761, 98766, 98771, 98787, 12643, 98801, 98808, 98816, 98822, 98826, - 98829, 98835, 98840, 98845, 98853, 98860, 98865, 98874, 98880, 98885, - 98891, 98897, 98906, 98915, 43462, 98920, 98931, 98938, 98946, 98955, - 14104, 98964, 98970, 98978, 98984, 98990, 98996, 99001, 99008, 99014, - 14115, 99019, 99022, 99027, 39620, 99037, 99046, 99051, 99059, 99066, - 99072, 99077, 99085, 99092, 99103, 99119, 99135, 99151, 99167, 99183, - 99199, 99215, 99231, 99247, 99263, 99279, 99295, 99311, 99327, 99343, - 99359, 99375, 99391, 99407, 99423, 99439, 99455, 99471, 99487, 99503, - 99519, 99535, 99551, 99567, 99583, 99599, 99615, 99631, 99647, 99663, - 99679, 99695, 99711, 99727, 99743, 99759, 99775, 99791, 99807, 99823, - 99839, 99855, 99871, 99887, 99903, 99919, 99935, 99951, 99967, 99983, - 99999, 100015, 100031, 100047, 100063, 100079, 100095, 100111, 100127, - 100143, 100159, 100175, 100191, 100207, 100223, 100239, 100255, 100271, - 100287, 100303, 100319, 100335, 100351, 100367, 100383, 100399, 100415, - 100431, 100447, 100463, 100479, 100495, 100511, 100527, 100543, 100559, - 100575, 100591, 100607, 100623, 100639, 100655, 100671, 100687, 100703, - 100719, 100735, 100751, 100767, 100783, 100799, 100815, 100831, 100847, - 100863, 100879, 100895, 100911, 100927, 100943, 100959, 100975, 100991, - 101007, 101023, 101039, 101055, 101071, 101087, 101103, 101119, 101135, - 101151, 101167, 101183, 101199, 101215, 101231, 101247, 101263, 101279, - 101295, 101311, 101327, 101343, 101359, 101375, 101391, 101407, 101423, - 101439, 101455, 101471, 101487, 101503, 101519, 101535, 101551, 101567, - 101583, 101599, 101615, 101631, 101647, 101663, 101679, 101695, 101711, - 101727, 101743, 101759, 101775, 101791, 101807, 101823, 101839, 101855, - 101871, 101887, 101903, 101919, 101935, 101951, 101967, 101983, 101999, - 102015, 102031, 102047, 102063, 102079, 102095, 102111, 102127, 102143, - 102159, 102175, 102191, 102207, 102223, 102239, 102255, 102271, 102287, - 102303, 102319, 102335, 102351, 102367, 102383, 102399, 102415, 102431, - 102447, 102463, 102479, 102495, 102511, 102527, 102543, 102559, 102575, - 102591, 102607, 102623, 102639, 102655, 102671, 102687, 102703, 102719, - 102735, 102751, 102767, 102783, 102799, 102815, 102831, 102847, 102863, - 102879, 102895, 102911, 102927, 102943, 102959, 102975, 102991, 103007, - 103023, 103039, 103055, 103071, 103087, 103103, 103119, 103135, 103151, - 103167, 103183, 103199, 103215, 103231, 103247, 103263, 103279, 103295, - 103311, 103327, 103343, 103359, 103375, 103391, 103407, 103423, 103439, - 103455, 103471, 103487, 103503, 103519, 103535, 103551, 103567, 103583, - 103599, 103615, 103631, 103647, 103663, 103679, 103695, 103711, 103727, - 103743, 103759, 103775, 103791, 103807, 103823, 103839, 103855, 103871, - 103887, 103903, 103919, 103935, 103951, 103967, 103983, 103999, 104015, - 104031, 104047, 104063, 104079, 104095, 104111, 104127, 104143, 104159, - 104175, 104191, 104207, 104223, 104239, 104255, 104271, 104287, 104303, - 104319, 104335, 104351, 104367, 104383, 104399, 104415, 104431, 104447, - 104463, 104479, 104495, 104511, 104527, 104543, 104559, 104575, 104591, - 104607, 104623, 104639, 104655, 104671, 104687, 104703, 104719, 104735, - 104751, 104767, 104783, 104799, 104815, 104831, 104847, 104863, 104879, - 104895, 104911, 104927, 104943, 104959, 104975, 104991, 105007, 105023, - 105039, 105055, 105071, 105087, 105103, 105119, 105135, 105151, 105167, - 105183, 105199, 105215, 105231, 105247, 105263, 105279, 105295, 105311, - 105327, 105343, 105359, 105375, 105391, 105407, 105423, 105439, 105455, - 105471, 105487, 105503, 105519, 105535, 105551, 105567, 105583, 105599, - 105615, 105631, 105647, 105663, 105679, 105695, 105711, 105727, 105743, - 105759, 105775, 105791, 105807, 105823, 105839, 105855, 105871, 105887, - 105903, 105919, 105935, 105951, 105967, 105983, 105999, 106015, 106031, - 106047, 106063, 106079, 106095, 106111, 106127, 106143, 106159, 106175, - 106191, 106207, 106223, 106239, 106255, 106271, 106287, 106303, 106319, - 106335, 106351, 106367, 106383, 106399, 106415, 106431, 106447, 106463, - 106479, 106495, 106511, 106527, 106543, 106559, 106575, 106591, 106607, - 106623, 106639, 106655, 106671, 106687, 106703, 106719, 106735, 106751, - 106767, 106783, 106799, 106815, 106831, 106847, 106863, 106879, 106895, - 106911, 106927, 106943, 106959, 106975, 106991, 107007, 107023, 107039, - 107055, 107071, 107087, 107103, 107119, 107135, 107151, 107167, 107183, - 107199, 107215, 107231, 107247, 107263, 107279, 107295, 107311, 107327, - 107343, 107359, 107375, 107391, 107407, 107423, 107439, 107455, 107471, - 107487, 107503, 107519, 107535, 107551, 107567, 107583, 107599, 107615, - 107631, 107647, 107663, 107679, 107695, 107711, 107727, 107743, 107759, - 107775, 107791, 107807, 107823, 107839, 107855, 107871, 107887, 107903, - 107919, 107935, 107951, 107967, 107983, 107999, 108015, 108031, 108047, - 108063, 108079, 108095, 108111, 108127, 108143, 108159, 108175, 108191, - 108207, 108223, 108239, 108255, 108271, 108287, 108303, 108319, 108335, - 108351, 108367, 108383, 108399, 108415, 108431, 108447, 108463, 108479, - 108495, 108511, 108527, 108543, 108559, 108575, 108591, 108607, 108623, - 108639, 108655, 108671, 108687, 108703, 108719, 108735, 108751, 108767, - 108783, 108799, 108815, 108831, 108847, 108863, 108879, 108895, 108911, - 108927, 108943, 108959, 108975, 108991, 109007, 109023, 109039, 109055, - 109071, 109087, 109103, 109119, 109135, 109151, 109167, 109183, 109199, - 109215, 109231, 109247, 109263, 109279, 109295, 109311, 109327, 109343, - 109359, 109375, 109391, 109407, 109423, 109439, 109455, 109471, 109487, - 109503, 109519, 109535, 109551, 109567, 109583, 109599, 109615, 109631, - 109647, 109663, 109679, 109695, 109711, 109727, 109743, 109759, 109775, - 109791, 109807, 109823, 109839, 109855, 109871, 109887, 109903, 109919, - 109935, 109951, 109967, 109983, 109999, 110015, 110031, 110047, 110063, - 110079, 110095, 110111, 110127, 110143, 110159, 110175, 110191, 110207, - 110223, 110239, 110255, 110271, 110287, 110303, 110319, 110335, 110351, - 110367, 110383, 110399, 110415, 110431, 110447, 110463, 110479, 110495, - 110511, 110527, 110543, 110559, 110575, 110591, 110607, 110623, 110639, - 110655, 110671, 110687, 110703, 110719, 110735, 110751, 110767, 110783, - 110799, 110815, 110831, 110847, 110863, 110879, 110895, 110911, 110927, - 110943, 110959, 110975, 110991, 111007, 111023, 111039, 111055, 111071, - 111087, 111103, 111119, 111135, 111151, 111167, 111183, 111199, 111215, - 111231, 111247, 111263, 111279, 111295, 111311, 111327, 111343, 111359, - 111375, 111391, 111407, 111423, 111439, 111455, 111471, 111487, 111503, - 111519, 111535, 111551, 111567, 111583, 111599, 111615, 111631, 111647, - 111663, 111679, 111695, 111711, 111727, 111743, 111759, 111775, 111791, - 111807, 111823, 111839, 111855, 111871, 111887, 111903, 111919, 111935, - 111951, 111967, 111983, 111999, 112015, 112031, 112047, 112063, 112079, - 112095, 112111, 112127, 112143, 112159, 112175, 112191, 112207, 112223, - 112239, 112255, 112271, 112287, 112303, 112319, 112335, 112351, 112367, - 112383, 112399, 112415, 112431, 112447, 112463, 112479, 112495, 112511, - 112527, 112543, 112559, 112575, 112591, 112607, 112623, 112639, 112655, - 112671, 112687, 112703, 112719, 112735, 112751, 112767, 112783, 112799, - 112815, 112831, 112847, 112863, 112879, 112895, 112911, 112927, 112943, - 112959, 112969, 112978, 112983, 112991, 77204, 112996, 113002, 113007, - 113014, 113023, 113031, 113035, 4338, 113041, 113048, 113054, 113058, - 20549, 46595, 3295, 113063, 113067, 113071, 113078, 113084, 113093, - 113099, 113106, 113110, 113131, 113153, 113169, 113186, 113205, 113214, - 113224, 113232, 113239, 113246, 113252, 33070, 113266, 113270, 113276, - 113284, 113296, 113302, 113310, 113317, 113322, 113327, 113331, 113339, - 113346, 113350, 113356, 113362, 113367, 3972, 52543, 113373, 113377, - 113381, 113385, 113390, 113395, 113400, 113406, 113412, 113418, 113425, - 113431, 113438, 113444, 113450, 113455, 113461, 113466, 113470, 105563, - 113475, 105627, 52558, 113480, 113485, 113493, 113497, 113502, 113509, - 113518, 113525, 113531, 113540, 113544, 113551, 113555, 113558, 113565, - 113571, 113580, 113590, 113600, 113605, 113609, 113616, 113624, 113633, - 113637, 113645, 113651, 113656, 113661, 113667, 113673, 113678, 113682, - 31947, 113688, 113692, 113696, 113699, 113704, 113712, 113722, 113728, - 113733, 113743, 49664, 113751, 113763, 113769, 113776, 113782, 113786, - 113791, 113797, 113809, 113820, 113827, 113833, 113840, 113847, 113859, - 113866, 113872, 25629, 113876, 113884, 113890, 113897, 113903, 113909, - 113915, 113920, 113925, 113930, 113934, 113943, 113951, 113962, 7934, - 113967, 19985, 113973, 113977, 113981, 113985, 113993, 114002, 114006, - 114013, 114022, 114030, 114043, 114049, 106139, 36551, 114054, 114056, - 114061, 114066, 114071, 114076, 114081, 114086, 114091, 114096, 114101, - 114106, 114111, 114116, 114121, 114126, 114132, 114137, 114142, 114147, - 114152, 114157, 114162, 114167, 114172, 114178, 114184, 114190, 114195, - 114200, 114212, 114217, 1935, 54, 114222, 114227, 39630, 114231, 39635, - 39640, 39646, 39651, 114235, 39656, 26815, 114257, 114261, 114265, - 114270, 114274, 39660, 114278, 114286, 114293, 114299, 114309, 39665, - 114316, 114319, 114324, 114328, 114337, 11168, 114345, 39670, 26659, - 114348, 114352, 114360, 1307, 114365, 39681, 114368, 114373, 114378, - 31188, 31198, 43060, 114383, 114388, 114393, 114398, 114404, 114409, - 114418, 114423, 114432, 114440, 114447, 114453, 114458, 114463, 114468, - 114478, 114487, 114495, 114500, 114508, 114512, 114520, 114524, 114531, - 114538, 114546, 114553, 39485, 46310, 114559, 114565, 114570, 114575, - 14548, 11961, 114580, 114585, 114590, 114596, 114603, 114609, 114618, - 114623, 114631, 114641, 114648, 114658, 114664, 114669, 114675, 114679, - 21979, 114686, 44045, 114699, 114704, 114711, 114717, 114732, 37615, - 75612, 114745, 114749, 114758, 114767, 114774, 114780, 114788, 114794, - 114802, 114811, 114819, 114826, 46430, 114832, 114835, 114839, 114843, - 114847, 11982, 114853, 114860, 114866, 114874, 114879, 114883, 29180, - 114889, 114892, 114900, 114907, 114915, 114928, 114942, 114949, 114955, - 114962, 114968, 39695, 114972, 114978, 114986, 114993, 115001, 115009, - 115015, 39700, 115023, 115029, 115034, 115044, 115050, 115059, 37410, - 42408, 115067, 115072, 115077, 115081, 115086, 115090, 115098, 115103, - 17981, 18806, 49686, 115107, 115112, 39705, 18138, 115116, 115128, - 115133, 115137, 115144, 115153, 115157, 115165, 115171, 115176, 115184, - 115192, 115200, 115208, 115216, 115224, 115235, 115241, 9132, 115246, - 115252, 115257, 115262, 115273, 115282, 115294, 115309, 40017, 115315, - 20104, 39709, 115319, 115326, 115332, 115336, 29317, 115343, 115349, - 115356, 48811, 115365, 115371, 115380, 115386, 115391, 115399, 115405, - 115410, 39719, 115415, 115424, 115433, 113815, 115442, 115449, 115455, - 115461, 115470, 115480, 115486, 115494, 115501, 115505, 39724, 115508, - 39730, 1346, 115513, 115521, 115529, 115539, 115548, 115556, 115563, - 115573, 39741, 115577, 115579, 115583, 115588, 115592, 115596, 115602, - 115607, 115611, 115622, 115627, 115633, 115638, 115647, 115652, 3300, - 115656, 115663, 115667, 115676, 115684, 115692, 115699, 115704, 115709, - 74113, 115713, 115716, 115722, 115730, 115736, 115740, 115745, 115752, - 115757, 115762, 115766, 115773, 115779, 115784, 42439, 115788, 115791, - 115796, 115800, 115805, 115812, 115817, 115821, 47780, 115829, 31207, - 31216, 115835, 115841, 115847, 115852, 115856, 115859, 115869, 115878, - 115883, 115889, 115896, 115902, 115906, 115914, 115919, 42445, 85210, - 115923, 115931, 115938, 115944, 115951, 115956, 115963, 115968, 115972, - 115978, 115983, 69106, 115989, 115995, 10386, 116000, 116005, 116009, - 116014, 116019, 116024, 116028, 116033, 116038, 116044, 116049, 116054, - 116060, 116066, 116071, 116075, 116080, 116085, 116090, 116094, 29316, - 116099, 116104, 116110, 116116, 116122, 116127, 116131, 116136, 116141, - 109915, 116146, 116151, 116156, 116161, 109979, 52813, 116166, 39749, - 116174, 116178, 116186, 116194, 116205, 116210, 116214, 27294, 82608, - 116219, 116225, 116230, 4649, 116240, 116247, 116252, 116260, 116269, - 116274, 116278, 116283, 116287, 116295, 116303, 116310, 77470, 116316, - 116324, 116331, 116342, 116348, 116354, 39759, 116357, 116364, 116372, - 116377, 116381, 33589, 71792, 116387, 116392, 116399, 116404, 10275, - 116408, 116416, 116423, 116430, 116439, 116446, 116452, 116466, 116474, - 6724, 116236, 116480, 116485, 116491, 116495, 116498, 116506, 116513, - 116518, 116531, 116538, 116544, 116548, 116556, 116561, 116568, 116574, - 116579, 72070, 116584, 116587, 116596, 116603, 110187, 116609, 116612, - 116620, 116626, 116635, 116645, 116655, 116664, 116675, 116683, 116694, - 116699, 116703, 116708, 116712, 43191, 116720, 18771, 43200, 116725, - 101706, 101722, 101738, 101754, 101770, 116730, 101802, 101818, 101834, - 101850, 101962, 101978, 116734, 102010, 102026, 116738, 116742, 116746, - 116750, 102266, 102298, 116754, 102330, 116758, 116762, 102474, 102490, - 102506, 102522, 116766, 102586, 102602, 116770, 102730, 102746, 102762, - 102778, 102794, 102810, 102826, 102842, 102858, 102874, 102986, 103002, - 103018, 103034, 103050, 103066, 103082, 103098, 103114, 103130, 116774, - 104922, 105034, 105098, 105114, 105130, 105146, 105162, 105178, 105290, - 105306, 105322, 116778, 105370, 116782, 105402, 105418, 105434, 116786, - 116791, 116796, 116801, 116806, 116811, 116816, 116820, 116824, 116829, - 116834, 116838, 116843, 116848, 116852, 116857, 116862, 116867, 116872, - 116876, 116881, 116886, 116890, 116895, 116899, 116903, 116907, 116911, - 116916, 116920, 116924, 116928, 116932, 116936, 116940, 116944, 116948, - 116952, 116957, 116962, 116967, 116972, 116977, 116982, 116987, 116992, - 116997, 117002, 117006, 117010, 117014, 117018, 117022, 117026, 117031, - 117035, 117040, 117044, 117049, 117054, 117058, 117062, 117067, 117071, - 117075, 117079, 117083, 117087, 117091, 117095, 117099, 117103, 117107, - 117111, 117115, 117119, 117123, 117128, 117133, 117137, 117141, 117145, - 117149, 117153, 117157, 117162, 117166, 117170, 117174, 117178, 117182, - 117186, 117191, 117195, 117200, 117204, 117208, 117212, 117216, 117220, - 117224, 117228, 117232, 117236, 117240, 117244, 117249, 117253, 117257, - 117261, 117265, 117269, 117273, 117277, 117281, 117285, 117289, 117293, - 117298, 117302, 117306, 117311, 117316, 117320, 117324, 117328, 117332, - 117336, 117340, 117344, 117348, 117353, 117357, 117362, 117366, 117371, - 117375, 117380, 117384, 117390, 117395, 117399, 117404, 117408, 117413, - 117417, 117422, 117426, 117431, 1429, 117435, 117439, 3042, 1705, 28453, - 1602, 31143, 117443, 3051, 117447, 1276, 117452, 1218, 117456, 117460, - 117464, 117468, 117472, 117476, 3075, 117480, 117488, 117495, 117502, - 117516, 3079, 8044, 117525, 117533, 117540, 117551, 117560, 117564, - 117571, 117583, 117596, 117609, 117620, 117625, 117632, 117644, 117648, - 3083, 14185, 117658, 117663, 117672, 117682, 117687, 117696, 3087, - 117704, 117708, 117713, 117720, 117726, 117731, 117740, 117748, 117760, - 117770, 1223, 15645, 117783, 117787, 117793, 117807, 117819, 117831, - 117839, 117849, 117858, 117867, 117876, 117884, 117895, 117903, 4657, - 117913, 117924, 117933, 117939, 117954, 117961, 117967, 117972, 43334, - 117977, 3111, 15649, 117981, 117986, 117993, 10206, 118002, 118008, 4695, - 118018, 3116, 39121, 118027, 71682, 118034, 118038, 118044, 118055, - 118061, 118066, 118073, 118079, 118087, 118094, 118100, 118111, 118127, - 118137, 118146, 118157, 118166, 118173, 118179, 118189, 118197, 118203, - 118218, 118224, 118229, 118233, 118240, 118248, 118252, 118255, 118261, - 118268, 118274, 118282, 118291, 118299, 118305, 118314, 52116, 118328, - 118333, 118339, 17732, 118344, 118357, 118369, 118378, 118386, 118393, - 118397, 118401, 118404, 118411, 118418, 118426, 118434, 118443, 118451, - 17631, 118459, 118464, 118468, 118480, 118487, 118494, 118503, 954, - 118513, 118522, 118533, 3137, 118537, 118541, 118547, 118560, 118572, - 118582, 118591, 118603, 32105, 118614, 118622, 118631, 118642, 118653, - 118663, 118673, 118681, 118690, 118698, 13604, 118705, 118709, 118712, - 118717, 118722, 118726, 118732, 1228, 118739, 118743, 14281, 118747, - 118751, 118762, 118771, 118779, 118788, 118796, 118812, 118823, 118832, - 118840, 118852, 118863, 118879, 118889, 118910, 118924, 118937, 118945, - 118952, 8090, 118965, 118970, 118976, 6733, 118982, 118985, 118992, - 119002, 9266, 119009, 119014, 119019, 119026, 119034, 119042, 119048, - 119053, 119059, 119063, 119071, 119080, 119088, 119093, 119102, 119109, - 11418, 11427, 119115, 119126, 119132, 119137, 119143, 3153, 3158, 119149, - 1063, 119155, 119162, 119169, 119182, 119192, 119197, 2324, 87, 119205, - 119212, 119217, 119225, 119235, 119244, 119250, 119259, 119267, 119277, - 119281, 119285, 119290, 119294, 119306, 3181, 119314, 119322, 119327, - 119338, 119349, 119361, 119372, 119382, 119391, 26013, 119396, 119402, - 119407, 119417, 119427, 119432, 34323, 119438, 119443, 119452, 26035, - 119456, 26046, 119461, 4783, 8, 119468, 119477, 119484, 119491, 119497, - 119502, 119506, 119512, 34353, 119517, 119522, 72367, 119527, 119532, - 119538, 119544, 119552, 119557, 119565, 119573, 119582, 119589, 119595, - 119602, 119608, 119615, 119620, 47649, 52010, 119626, 119636, 1822, 32, - 119643, 119648, 119661, 119666, 119674, 119679, 119685, 3207, 30884, - 3221, 119690, 119698, 119705, 119710, 119715, 119724, 4340, 4351, 73711, - 119732, 119736, 1629, 1862, 119741, 119746, 119753, 34774, 1866, 331, - 119760, 119766, 119771, 3229, 119775, 119780, 119787, 1870, 119792, - 119798, 119803, 119815, 6978, 119825, 119832, 1877, 119838, 119843, - 119850, 119857, 119872, 119879, 119890, 119895, 119903, 2772, 119907, - 119919, 119924, 119928, 119934, 34195, 2329, 119938, 119949, 119953, - 119957, 119963, 119967, 119976, 119980, 119991, 119995, 2375, 38938, - 119999, 120009, 120017, 3320, 120023, 120032, 120040, 10752, 120045, - 120053, 120058, 120062, 120071, 120078, 120084, 3290, 17796, 120088, - 120101, 44058, 120119, 120124, 120132, 120140, 120150, 11759, 15773, - 120162, 120175, 120182, 120192, 120206, 120213, 120229, 120236, 120242, - 26093, 14980, 120249, 120256, 120266, 120275, 52812, 120287, 120295, - 52947, 120302, 120305, 120311, 120317, 120323, 120329, 120335, 120342, - 120349, 120355, 120361, 120367, 120373, 120379, 120385, 120391, 120397, - 120403, 120409, 120415, 120421, 120427, 120433, 120439, 120445, 120451, - 120457, 120463, 120469, 120475, 120481, 120487, 120493, 120499, 120505, - 120511, 120517, 120523, 120529, 120535, 120541, 120547, 120553, 120559, - 120565, 120571, 120577, 120583, 120589, 120595, 120601, 120607, 120613, - 120619, 120625, 120631, 120637, 120643, 120649, 120655, 120662, 120668, - 120675, 120682, 120688, 120695, 120702, 120708, 120714, 120720, 120726, - 120732, 120738, 120744, 120750, 120756, 120762, 120768, 120774, 120780, - 120786, 120792, 3304, 10720, 120798, 120808, 120814, 120822, 120826, - 117716, 3308, 120830, 114044, 25758, 4701, 4265, 120834, 3314, 120838, - 120848, 120854, 120860, 120866, 120872, 120878, 120884, 120890, 120896, - 120902, 120908, 120914, 120920, 120926, 120932, 120938, 120944, 120950, - 120956, 120962, 120968, 120974, 120980, 120986, 120992, 120998, 121005, - 121012, 121018, 121024, 121030, 121036, 121042, 121048, 1233, 121054, - 121059, 121064, 121069, 121074, 121079, 121084, 121089, 121094, 121098, - 121102, 121106, 121110, 121114, 121118, 121122, 121126, 121130, 121136, - 121142, 121148, 121154, 121158, 121162, 121166, 121170, 121174, 121178, - 121182, 121186, 121190, 121195, 121200, 121205, 121210, 121215, 121220, - 121225, 121230, 121235, 121240, 121245, 121250, 121255, 121260, 121265, - 121270, 121275, 121280, 121285, 121290, 121295, 121300, 121305, 121310, - 121315, 121320, 121325, 121330, 121335, 121340, 121345, 121350, 121355, - 121360, 121365, 121370, 121375, 121380, 121385, 121390, 121395, 121400, - 121405, 121410, 121415, 121420, 121425, 121430, 121435, 121440, 121445, - 121450, 121455, 121460, 121465, 121470, 121475, 121480, 121485, 121490, - 121495, 121500, 121505, 121510, 121515, 121520, 121525, 121530, 121535, - 121540, 121545, 121550, 121555, 121560, 121565, 121570, 121575, 121580, - 121585, 121590, 121595, 121600, 121605, 121610, 121615, 121620, 121625, - 121630, 121635, 121640, 121645, 121650, 121655, 121660, 121665, 121670, - 121675, 121680, 121685, 121690, 121695, 121700, 121705, 121710, 121715, - 121720, 121725, 121730, 121735, 121740, 121745, 121750, 121755, 121760, - 121765, 121770, 121775, 121780, 121785, 121790, 121795, 121800, 121805, - 121810, 121815, 121820, 121825, 121830, 121835, 121840, 121845, 121850, - 121855, 121860, 121865, 121870, 121875, 121880, 121885, 121890, 121895, - 121900, 121905, 121910, 121915, 121920, 121925, 121930, 121935, 121940, - 121945, 121950, 121955, 121960, 121965, 121970, 121975, 121980, 121985, - 121990, 121995, 122000, 122005, 122010, 122015, 122020, 122025, 122030, - 122035, 122040, 122045, 122050, 122055, 122060, 122065, 122070, 122075, - 122080, 122086, 122091, 122096, 122101, 122106, 122111, 122116, 122121, - 122127, 122132, 122137, 122142, 122147, 122152, 122157, 122162, 122167, - 122172, 122177, 122182, 122187, 122192, 122197, 122202, 122207, 122212, - 122217, 122222, 122227, 122232, 122237, 122242, 122247, 122252, 122257, - 122262, 122267, 122272, 122277, 122282, 122287, 122296, 122301, 122310, - 122315, 122324, 122329, 122338, 122343, 122352, 122357, 122366, 122371, - 122380, 122385, 122394, 122399, 122404, 122413, 122417, 122426, 122431, - 122440, 122445, 122454, 122459, 122468, 122473, 122482, 122487, 122496, - 122501, 122510, 122515, 122524, 122529, 122538, 122543, 122552, 122557, - 122562, 122567, 122572, 122577, 122582, 122587, 122591, 122596, 122601, - 122606, 122611, 122616, 122621, 122627, 122632, 122637, 122642, 122648, - 122652, 122657, 122663, 122668, 122673, 122678, 122683, 122688, 122693, - 122698, 122703, 122708, 122713, 122719, 122724, 122729, 122734, 122740, - 122745, 122750, 122755, 122760, 122766, 122771, 122776, 122781, 122786, - 122791, 122797, 122802, 122807, 122812, 122817, 122822, 122827, 122832, - 122837, 122842, 122847, 122852, 122857, 122862, 122867, 122872, 122877, - 122882, 122887, 122892, 122897, 122902, 122907, 122912, 122918, 122924, - 122930, 122935, 122940, 122945, 122950, 122956, 122962, 122968, 122973, - 122978, 122983, 122989, 122994, 122999, 123004, 123009, 123014, 123019, - 123024, 123029, 123034, 123039, 123044, 123049, 123054, 123059, 123064, - 123069, 123075, 123081, 123087, 123092, 123097, 123102, 123107, 123113, - 123119, 123125, 123130, 123135, 123140, 123145, 123150, 123155, 123160, - 123165, 123170, 19463, 123175, 123181, 123186, 123191, 123196, 123201, - 123206, 123212, 123217, 123222, 123227, 123232, 123237, 123243, 123248, - 123253, 123258, 123263, 123268, 123273, 123278, 123283, 123288, 123293, - 123298, 123303, 123308, 123313, 123318, 123323, 123328, 123333, 123338, - 123343, 123348, 123353, 123359, 123364, 123369, 123374, 123379, 123384, - 123389, 123394, 123399, 123404, 123409, 123414, 123419, 123424, 123429, - 123434, 123439, 123444, 123449, 123454, 123459, 123464, 123469, 123474, - 123479, 123484, 123489, 123494, 123499, 123504, 123509, 123514, 123519, - 123524, 123529, 123534, 123539, 123544, 123549, 123554, 123559, 123565, - 123570, 123575, 123580, 123585, 123590, 123595, 123600, 123605, 123610, - 123615, 123620, 123626, 123631, 123637, 123642, 123647, 123652, 123657, - 123662, 123667, 123673, 123678, 123683, 123689, 123694, 123699, 123704, - 123709, 123714, 123720, 123726, 123731, 123736, 14614, 123741, 123746, - 123751, 123756, 123761, 123766, 123771, 123776, 123781, 123786, 123791, - 123796, 123801, 123806, 123811, 123816, 123821, 123826, 123831, 123836, - 123841, 123846, 123851, 123856, 123861, 123866, 123871, 123876, 123881, - 123886, 123891, 123896, 123901, 123906, 123911, 123916, 123921, 123926, - 123931, 123936, 123941, 123946, 123951, 123956, 123961, 123966, 123971, - 123976, 123981, 123986, 123991, 123996, 124001, 124006, 124011, 124016, - 124021, 124026, 124031, 124036, 124041, 124046, 124051, 124056, 124061, - 124067, 124072, 124077, 124082, 124087, 124093, 124098, 124103, 124108, - 124113, 124118, 124123, 124129, 124134, 124139, 124144, 124149, 124154, - 124160, 124165, 124170, 124175, 124180, 124185, 124191, 124196, 124201, - 124206, 124211, 124216, 124222, 124228, 124233, 124238, 124243, 124249, - 124255, 124261, 124266, 124271, 124277, 124283, 124288, 124294, 124300, - 124306, 124311, 124316, 124322, 124327, 124333, 124338, 124344, 124353, - 124358, 124363, 124369, 124374, 124380, 124385, 124390, 124395, 124400, - 124405, 124410, 124415, 124420, 124425, 124430, 124435, 124440, 124445, - 124450, 124455, 124460, 124465, 124470, 124475, 124480, 124485, 124490, - 124495, 124500, 124505, 124510, 124515, 124520, 124525, 124530, 124535, - 124541, 124547, 124553, 124558, 124563, 124568, 124573, 124578, 124583, - 124588, 124593, 124598, 124603, 124608, 124613, 124618, 124623, 124628, - 124633, 124638, 124643, 124648, 124653, 124659, 124665, 124670, 124676, - 124681, 124686, 124692, 124697, 124703, 124708, 124714, 124719, 124725, - 124730, 124736, 124741, 124746, 124751, 124756, 124761, 124766, 124771, - 120849, 120855, 120861, 120867, 124777, 120873, 120879, 124783, 120885, - 120891, 120897, 120903, 120909, 120915, 120921, 120927, 120933, 124789, - 120939, 120945, 120951, 124795, 120957, 120963, 120969, 120975, 124801, - 120981, 120987, 120993, 121013, 124807, 124813, 121019, 124819, 121025, - 121031, 121037, 121043, 121049, 124825, 3331, 3336, 124830, 3351, 3356, - 3361, 124835, 124838, 124844, 124850, 124857, 124862, 124867, 2380, +/* name->code dictionary */ +static const unsigned char packed_name_dawg[] = { + 228, 174, 4, 250, 2, 65, 206, 254, 2, 66, 222, 254, 2, 67, 198, 245, 4, + 68, 222, 134, 1, 69, 250, 151, 1, 70, 206, 52, 71, 186, 154, 1, 72, 242, + 223, 1, 73, 146, 65, 74, 138, 23, 75, 230, 134, 1, 76, 146, 130, 3, 77, + 162, 200, 3, 78, 162, 107, 79, 226, 124, 80, 128, 159, 1, 2, 81, 85, 194, + 7, 82, 182, 169, 1, 83, 166, 175, 4, 84, 170, 203, 2, 85, 222, 90, 86, + 182, 80, 87, 182, 111, 88, 254, 4, 89, 179, 48, 90, 182, 40, 222, 2, 67, + 238, 1, 68, 182, 10, 69, 172, 5, 4, 72, 79, 77, 32, 244, 6, 7, 73, 82, + 80, 76, 65, 78, 69, 82, 76, 210, 32, 77, 198, 1, 78, 142, 26, 80, 142, + 20, 82, 158, 136, 2, 83, 210, 2, 84, 70, 85, 214, 1, 86, 172, 213, 11, 4, + 70, 71, 72, 65, 206, 192, 9, 66, 220, 219, 2, 9, 75, 84, 73, 69, 83, 69, + 76, 83, 75, 164, 187, 2, 2, 81, 85, 199, 135, 10, 88, 18, 132, 1, 2, 67, + 79, 46, 75, 20, 5, 85, 84, 69, 32, 65, 140, 230, 16, 6, 84, 73, 86, 65, + 84, 69, 225, 150, 22, 5, 32, 67, 85, 82, 82, 4, 162, 185, 25, 85, 237, + 182, 13, 2, 82, 68, 5, 147, 175, 33, 78, 4, 178, 207, 34, 67, 167, 207, + 3, 78, 188, 1, 232, 1, 4, 76, 65, 77, 32, 242, 7, 77, 216, 141, 13, 7, + 72, 69, 83, 73, 86, 69, 32, 168, 151, 4, 19, 68, 82, 69, 83, 83, 69, 68, + 32, 84, 79, 32, 84, 72, 69, 32, 83, 85, 66, 74, 234, 178, 13, 85, 161, + 186, 1, 6, 73, 32, 83, 72, 65, 75, 176, 1, 218, 1, 67, 44, 4, 83, 77, 65, + 76, 168, 4, 7, 71, 69, 77, 73, 78, 65, 84, 116, 8, 73, 78, 73, 84, 73, + 65, 76, 32, 38, 78, 178, 209, 2, 72, 220, 244, 22, 4, 65, 76, 73, 70, 0, + 5, 86, 79, 87, 69, 76, 131, 130, 12, 68, 70, 40, 5, 65, 80, 73, 84, 65, + 215, 4, 79, 68, 45, 9, 76, 32, 76, 69, 84, 84, 69, 82, 32, 68, 142, 2, + 68, 38, 71, 34, 74, 2, 77, 22, 75, 46, 78, 42, 83, 210, 158, 29, 81, 190, + 205, 4, 76, 130, 40, 67, 202, 154, 4, 90, 212, 7, 2, 65, 76, 170, 2, 66, + 2, 89, 146, 1, 87, 182, 89, 84, 150, 14, 80, 158, 20, 70, 2, 72, 2, 82, + 2, 86, 186, 2, 69, 2, 73, 2, 79, 3, 85, 4, 250, 186, 5, 65, 247, 251, 33, + 72, 4, 174, 162, 39, 66, 215, 22, 65, 2, 171, 182, 38, 73, 6, 194, 183, + 38, 65, 154, 98, 80, 191, 28, 72, 6, 206, 232, 38, 85, 158, 77, 72, 3, + 89, 4, 188, 181, 2, 6, 73, 78, 78, 89, 73, 73, 135, 128, 37, 72, 4, 40, + 4, 69, 32, 67, 79, 151, 206, 38, 73, 2, 173, 174, 38, 13, 78, 83, 79, 78, + 65, 78, 84, 32, 77, 79, 68, 73, 70, 4, 218, 222, 32, 69, 191, 141, 4, 81, + 4, 166, 151, 25, 65, 199, 185, 10, 85, 4, 182, 215, 26, 69, 185, 202, 11, + 12, 73, 83, 83, 73, 79, 78, 32, 84, 73, 67, 75, 69, 116, 80, 5, 71, 69, + 65, 78, 32, 249, 144, 33, 9, 82, 73, 65, 76, 32, 84, 82, 65, 77, 114, + 136, 1, 3, 68, 82, 89, 0, 6, 76, 73, 81, 85, 73, 68, 60, 8, 77, 69, 65, + 83, 85, 82, 69, 32, 26, 87, 130, 185, 26, 78, 147, 185, 11, 67, 2, 153, + 2, 11, 32, 77, 69, 65, 83, 85, 82, 69, 32, 70, 73, 4, 246, 1, 83, 31, 84, + 14, 100, 6, 69, 73, 71, 72, 84, 32, 241, 1, 14, 79, 82, 68, 32, 83, 69, + 80, 65, 82, 65, 84, 79, 82, 32, 10, 54, 70, 66, 83, 30, 84, 65, 5, 66, + 65, 83, 69, 32, 4, 38, 73, 89, 5, 79, 85, 82, 84, 72, 2, 85, 3, 82, 83, + 84, 2, 49, 4, 69, 67, 79, 78, 2, 21, 3, 72, 73, 82, 2, 11, 68, 2, 25, 4, + 32, 83, 85, 66, 2, 133, 148, 39, 2, 85, 78, 4, 130, 151, 38, 76, 247, 72, + 68, 130, 1, 140, 2, 22, 67, 79, 78, 83, 79, 78, 65, 78, 84, 32, 83, 73, + 71, 78, 32, 77, 69, 68, 73, 65, 76, 32, 88, 7, 76, 69, 84, 84, 69, 82, + 32, 242, 1, 83, 168, 1, 11, 86, 79, 87, 69, 76, 32, 83, 73, 71, 78, 32, + 140, 234, 31, 8, 78, 85, 77, 66, 69, 82, 32, 84, 219, 209, 5, 68, 6, 26, + 76, 159, 171, 39, 82, 4, 132, 227, 38, 7, 73, 71, 65, 84, 73, 78, 71, + 207, 74, 65, 68, 154, 1, 65, 210, 195, 35, 68, 46, 84, 222, 225, 1, 76, + 246, 189, 1, 78, 126, 66, 2, 67, 2, 71, 2, 74, 2, 75, 2, 80, 254, 68, 72, + 2, 77, 2, 82, 3, 83, 9, 45, 9, 76, 84, 69, 82, 78, 65, 84, 69, 32, 6, + 146, 169, 39, 66, 2, 71, 3, 84, 10, 60, 4, 73, 71, 78, 32, 241, 193, 22, + 5, 89, 77, 66, 79, 76, 8, 50, 83, 182, 130, 25, 75, 145, 233, 9, 2, 82, + 85, 4, 148, 183, 36, 4, 77, 65, 76, 76, 207, 162, 2, 69, 22, 66, 65, 162, + 218, 35, 85, 210, 200, 1, 73, 206, 134, 2, 69, 3, 79, 11, 186, 169, 39, + 65, 2, 73, 2, 77, 3, 87, 7, 11, 32, 4, 252, 190, 34, 3, 68, 69, 80, 141, + 153, 4, 5, 65, 82, 82, 73, 86, 130, 2, 232, 1, 20, 67, 72, 69, 77, 73, + 67, 65, 76, 32, 83, 89, 77, 66, 79, 76, 32, 70, 79, 82, 32, 166, 28, 69, + 60, 2, 76, 32, 82, 77, 108, 6, 84, 69, 82, 78, 65, 84, 208, 179, 28, 7, + 73, 69, 78, 32, 77, 79, 78, 225, 230, 6, 3, 65, 82, 77, 232, 1, 158, 2, + 65, 246, 2, 66, 210, 1, 67, 138, 3, 68, 98, 71, 38, 72, 132, 1, 4, 73, + 82, 79, 78, 82, 76, 74, 77, 144, 1, 2, 78, 73, 34, 80, 176, 2, 3, 81, 85, + 73, 74, 82, 146, 2, 83, 210, 5, 84, 166, 1, 86, 200, 1, 2, 87, 65, 214, + 245, 33, 85, 190, 206, 1, 69, 202, 153, 1, 79, 195, 27, 70, 30, 194, 1, + 76, 72, 3, 81, 85, 65, 204, 8, 7, 78, 84, 73, 77, 79, 78, 89, 148, 137, + 3, 3, 77, 65, 76, 176, 222, 8, 5, 85, 82, 73, 80, 73, 188, 129, 12, 3, + 82, 83, 69, 234, 156, 14, 83, 159, 91, 73, 8, 224, 24, 2, 69, 77, 252, + 209, 25, 4, 75, 65, 76, 73, 179, 167, 13, 85, 10, 38, 32, 149, 139, 24, + 3, 70, 79, 82, 8, 216, 7, 4, 86, 73, 84, 65, 225, 194, 22, 4, 82, 69, 71, + 73, 16, 148, 1, 7, 65, 84, 72, 32, 79, 70, 32, 204, 6, 6, 73, 83, 77, 85, + 84, 72, 144, 1, 4, 79, 82, 65, 88, 164, 1, 4, 76, 65, 67, 75, 203, 232, + 37, 82, 4, 230, 182, 16, 77, 253, 218, 21, 5, 86, 65, 80, 79, 85, 28, 82, + 65, 92, 6, 79, 80, 80, 69, 82, 32, 34, 82, 217, 206, 36, 4, 73, 78, 78, + 65, 6, 216, 218, 5, 2, 68, 85, 196, 156, 32, 9, 80, 85, 84, 32, 77, 79, + 82, 84, 85, 235, 27, 76, 4, 230, 13, 65, 179, 240, 37, 79, 16, 72, 8, 79, + 67, 85, 83, 32, 79, 70, 32, 53, 6, 85, 67, 73, 66, 76, 69, 6, 228, 16, 5, + 67, 79, 80, 80, 69, 219, 232, 37, 73, 11, 11, 45, 8, 138, 157, 39, 50, 2, + 51, 2, 52, 3, 53, 8, 44, 2, 73, 83, 185, 133, 5, 3, 65, 89, 45, 6, 144, + 2, 4, 83, 79, 76, 86, 203, 169, 36, 84, 4, 234, 182, 29, 79, 191, 212, 9, + 85, 8, 32, 4, 65, 76, 70, 32, 47, 79, 4, 240, 191, 34, 2, 79, 85, 255, + 161, 3, 68, 4, 132, 245, 2, 4, 82, 83, 69, 32, 183, 237, 35, 85, 6, 56, + 3, 32, 79, 82, 73, 7, 45, 67, 79, 80, 80, 69, 82, 4, 147, 226, 25, 69, 4, + 48, 3, 69, 65, 68, 221, 158, 13, 3, 79, 68, 69, 2, 135, 225, 34, 32, 10, + 120, 16, 69, 82, 67, 85, 82, 89, 32, 83, 85, 66, 76, 73, 77, 65, 84, 69, + 176, 133, 16, 4, 65, 82, 67, 65, 135, 148, 21, 79, 7, 207, 151, 39, 45, + 4, 142, 248, 37, 84, 235, 117, 71, 14, 108, 11, 72, 73, 76, 79, 83, 79, + 80, 72, 69, 82, 83, 34, 79, 98, 85, 181, 155, 29, 6, 82, 69, 67, 73, 80, + 73, 2, 209, 9, 4, 32, 83, 85, 76, 6, 52, 4, 87, 68, 69, 82, 161, 145, 35, + 3, 84, 32, 65, 5, 237, 231, 37, 5, 69, 68, 32, 66, 82, 4, 180, 143, 33, + 4, 84, 82, 69, 70, 161, 245, 5, 3, 82, 73, 70, 4, 132, 185, 34, 5, 78, + 84, 69, 83, 83, 249, 196, 3, 4, 67, 75, 32, 76, 24, 58, 69, 213, 220, 25, + 8, 79, 67, 75, 32, 83, 65, 76, 84, 20, 68, 5, 71, 85, 76, 85, 83, 164, 7, + 3, 65, 76, 71, 179, 172, 25, 84, 15, 32, 4, 32, 79, 70, 32, 71, 45, 6, + 228, 219, 25, 8, 65, 78, 84, 73, 77, 79, 78, 89, 255, 147, 12, 73, 6, + 170, 147, 39, 50, 2, 51, 3, 52, 34, 164, 1, 2, 65, 76, 194, 1, 84, 142, + 1, 85, 184, 139, 17, 2, 80, 73, 200, 255, 11, 2, 73, 76, 194, 243, 8, 79, + 133, 20, 11, 67, 69, 80, 84, 69, 82, 32, 79, 70, 32, 74, 8, 58, 84, 197, + 234, 37, 8, 45, 65, 77, 77, 79, 78, 73, 65, 7, 25, 4, 32, 79, 70, 32, 4, + 52, 8, 67, 79, 80, 80, 69, 82, 32, 65, 231, 5, 65, 2, 237, 149, 29, 7, + 78, 84, 73, 77, 79, 78, 73, 6, 236, 3, 8, 65, 82, 82, 69, 68, 32, 84, 82, + 169, 212, 25, 19, 82, 65, 84, 85, 77, 32, 83, 85, 80, 69, 82, 32, 83, 84, + 82, 65, 84, 85, 77, 12, 44, 6, 66, 76, 73, 77, 65, 84, 155, 1, 76, 10, + 44, 5, 69, 32, 79, 70, 32, 215, 190, 38, 73, 8, 68, 8, 83, 65, 76, 84, + 32, 79, 70, 32, 130, 3, 65, 175, 209, 26, 67, 4, 254, 2, 65, 175, 209, + 26, 67, 2, 135, 149, 38, 70, 12, 68, 3, 65, 82, 84, 32, 2, 73, 78, 34, + 82, 189, 162, 37, 2, 85, 84, 4, 11, 65, 4, 219, 212, 25, 82, 4, 222, 162, + 34, 67, 167, 49, 32, 2, 145, 201, 38, 2, 73, 68, 14, 50, 73, 245, 238, + 36, 6, 69, 82, 68, 73, 71, 82, 12, 64, 5, 78, 69, 71, 65, 82, 149, 211, + 25, 5, 84, 82, 73, 79, 76, 9, 44, 5, 32, 79, 70, 32, 65, 251, 137, 39, + 45, 2, 221, 188, 23, 3, 78, 84, 73, 4, 234, 204, 38, 84, 227, 61, 88, 6, + 38, 77, 246, 246, 37, 70, 231, 118, 82, 2, 151, 227, 37, 66, 4, 134, 227, + 32, 69, 233, 136, 4, 11, 65, 82, 79, 85, 78, 68, 45, 80, 82, 79, 70, 9, + 49, 10, 79, 83, 84, 32, 69, 81, 85, 65, 76, 32, 6, 32, 2, 84, 79, 235, + 176, 31, 79, 5, 147, 205, 6, 32, 4, 240, 192, 10, 3, 73, 86, 69, 253, + 159, 27, 5, 69, 32, 79, 78, 69, 10, 162, 1, 80, 180, 194, 28, 6, 69, 82, + 73, 67, 65, 78, 200, 232, 5, 3, 66, 85, 76, 209, 204, 3, 16, 65, 76, 71, + 65, 77, 65, 84, 73, 79, 78, 32, 79, 82, 32, 67, 79, 4, 158, 205, 35, 69, + 171, 78, 72, 192, 9, 92, 3, 65, 84, 79, 174, 20, 71, 174, 1, 84, 150, + 167, 24, 67, 182, 203, 11, 68, 155, 252, 2, 75, 144, 9, 104, 17, 76, 73, + 65, 78, 32, 72, 73, 69, 82, 79, 71, 76, 89, 80, 72, 32, 65, 133, 241, 12, + 3, 77, 73, 67, 142, 9, 70, 48, 138, 4, 49, 198, 2, 50, 162, 3, 51, 174, + 5, 52, 163, 3, 53, 222, 1, 106, 50, 102, 52, 110, 54, 102, 57, 182, 7, + 51, 234, 190, 11, 49, 202, 174, 22, 48, 242, 1, 53, 2, 55, 3, 56, 22, + 238, 193, 33, 54, 174, 193, 5, 48, 2, 49, 2, 50, 2, 51, 2, 52, 2, 53, 2, + 55, 2, 56, 3, 57, 28, 250, 135, 12, 54, 146, 185, 21, 49, 2, 53, 174, + 193, 5, 48, 2, 50, 2, 51, 2, 52, 2, 55, 2, 56, 3, 57, 26, 210, 238, 11, + 54, 250, 146, 27, 48, 2, 49, 2, 50, 2, 51, 2, 52, 2, 53, 2, 55, 2, 56, 3, + 57, 24, 186, 191, 33, 55, 2, 56, 174, 193, 5, 48, 2, 49, 2, 50, 2, 51, 2, + 52, 2, 53, 2, 54, 3, 57, 232, 1, 98, 48, 114, 49, 254, 242, 11, 50, 2, + 51, 158, 129, 22, 52, 2, 53, 2, 54, 2, 55, 2, 56, 3, 57, 42, 162, 236, + 11, 52, 2, 55, 190, 24, 53, 146, 185, 21, 48, 2, 49, 2, 50, 174, 193, 5, + 51, 2, 54, 2, 56, 3, 57, 26, 238, 131, 12, 48, 146, 185, 21, 53, 174, + 193, 5, 49, 2, 50, 2, 51, 2, 52, 2, 54, 2, 55, 2, 56, 3, 57, 222, 1, 102, + 48, 110, 49, 102, 57, 210, 1, 56, 170, 225, 11, 50, 2, 54, 250, 141, 22, + 51, 2, 52, 2, 53, 3, 55, 28, 150, 130, 12, 50, 146, 185, 21, 55, 2, 57, + 174, 193, 5, 48, 2, 49, 2, 51, 2, 52, 2, 53, 2, 54, 3, 56, 24, 186, 186, + 33, 53, 2, 54, 174, 193, 5, 48, 2, 49, 2, 50, 2, 51, 2, 52, 2, 55, 2, 56, + 3, 57, 24, 214, 185, 33, 52, 2, 57, 174, 193, 5, 48, 2, 49, 2, 50, 2, 51, + 2, 53, 2, 54, 2, 55, 3, 56, 228, 1, 102, 48, 2, 50, 2, 53, 102, 51, 110, + 54, 102, 56, 162, 1, 57, 174, 201, 11, 55, 162, 162, 22, 49, 3, 52, 22, + 134, 184, 33, 57, 174, 193, 5, 48, 2, 49, 2, 50, 2, 51, 2, 52, 2, 53, 2, + 54, 2, 55, 3, 56, 30, 214, 229, 11, 54, 242, 150, 8, 50, 138, 252, 18, + 48, 2, 49, 2, 51, 2, 52, 2, 53, 2, 55, 2, 56, 3, 57, 24, 182, 182, 33, + 52, 2, 56, 174, 193, 5, 48, 2, 49, 2, 50, 2, 51, 2, 53, 2, 54, 2, 55, 3, + 57, 26, 98, 51, 242, 180, 33, 49, 2, 54, 174, 193, 5, 48, 2, 50, 2, 52, + 2, 53, 2, 55, 2, 56, 3, 57, 4, 144, 173, 20, 6, 32, 82, 65, 32, 79, 82, + 139, 201, 18, 65, 20, 140, 203, 38, 3, 51, 32, 69, 210, 42, 48, 2, 49, 2, + 50, 2, 52, 2, 53, 2, 54, 2, 55, 2, 56, 3, 57, 202, 1, 102, 49, 210, 1, + 53, 130, 132, 20, 57, 166, 228, 13, 48, 2, 50, 2, 51, 2, 52, 2, 54, 2, + 55, 3, 56, 22, 90, 48, 174, 243, 38, 49, 2, 50, 2, 51, 2, 52, 2, 53, 2, + 54, 2, 55, 2, 56, 3, 57, 4, 60, 6, 32, 66, 69, 71, 73, 78, 1, 5, 65, 32, + 69, 78, 68, 2, 129, 248, 15, 8, 32, 76, 79, 71, 79, 71, 82, 65, 24, 138, + 177, 33, 48, 2, 55, 174, 193, 5, 49, 2, 50, 2, 51, 2, 52, 2, 53, 2, 54, + 2, 56, 3, 57, 60, 218, 142, 32, 51, 246, 214, 1, 48, 242, 1, 49, 3, 50, + 14, 96, 2, 76, 69, 250, 161, 2, 85, 208, 173, 31, 2, 83, 84, 230, 192, 3, + 69, 249, 162, 1, 2, 82, 89, 7, 33, 6, 32, 87, 73, 84, 72, 32, 4, 254, + 133, 31, 83, 191, 161, 4, 85, 29, 104, 11, 73, 67, 76, 79, 67, 75, 87, + 73, 83, 69, 32, 233, 219, 35, 9, 69, 78, 78, 65, 32, 87, 73, 84, 72, 24, + 90, 84, 254, 220, 6, 67, 58, 68, 122, 71, 138, 4, 79, 253, 173, 27, 5, + 73, 78, 84, 69, 71, 12, 84, 15, 82, 73, 65, 78, 71, 76, 69, 45, 72, 69, + 65, 68, 69, 68, 32, 187, 225, 6, 79, 10, 112, 3, 76, 69, 70, 0, 4, 82, + 73, 71, 72, 12, 6, 66, 79, 84, 84, 79, 77, 0, 3, 84, 79, 80, 223, 224, 6, + 79, 2, 11, 84, 2, 169, 152, 36, 7, 32, 85, 45, 83, 72, 65, 80, 158, 1, + 128, 1, 20, 76, 32, 70, 85, 78, 67, 84, 73, 79, 78, 65, 76, 32, 83, 89, + 77, 66, 79, 76, 32, 210, 15, 79, 38, 80, 167, 219, 38, 67, 140, 1, 222, + 2, 67, 186, 1, 68, 190, 2, 73, 44, 4, 65, 76, 80, 72, 0, 4, 79, 77, 69, + 71, 32, 4, 74, 79, 84, 32, 36, 4, 76, 69, 70, 84, 68, 2, 81, 85, 222, 3, + 82, 54, 83, 92, 4, 69, 80, 83, 73, 32, 6, 66, 65, 67, 75, 83, 76, 76, 2, + 85, 80, 208, 216, 15, 12, 71, 82, 69, 65, 84, 69, 82, 45, 84, 72, 65, 78, + 0, 5, 84, 73, 76, 68, 69, 191, 195, 19, 90, 14, 64, 6, 73, 82, 67, 76, + 69, 32, 165, 152, 36, 4, 79, 77, 77, 65, 12, 80, 2, 83, 84, 202, 138, 19, + 68, 170, 246, 5, 66, 214, 157, 10, 85, 175, 248, 2, 74, 4, 246, 197, 37, + 73, 215, 104, 65, 22, 76, 2, 69, 76, 120, 3, 79, 87, 78, 253, 140, 31, 6, + 73, 65, 77, 79, 78, 68, 10, 30, 32, 53, 3, 84, 65, 32, 6, 182, 137, 19, + 68, 174, 155, 16, 84, 159, 163, 1, 83, 4, 254, 156, 35, 85, 207, 170, 1, + 83, 10, 22, 32, 171, 9, 87, 8, 52, 5, 84, 65, 67, 75, 32, 182, 1, 83, + 231, 6, 67, 4, 138, 156, 35, 85, 175, 248, 2, 74, 6, 40, 2, 79, 84, 173, + 155, 31, 2, 45, 66, 4, 11, 65, 5, 219, 139, 31, 32, 4, 158, 135, 19, 68, + 255, 147, 16, 85, 4, 28, 2, 32, 83, 191, 7, 87, 2, 149, 197, 36, 4, 72, + 79, 69, 32, 46, 44, 2, 65, 68, 137, 3, 4, 79, 84, 69, 32, 43, 11, 32, 40, + 178, 1, 67, 34, 68, 92, 2, 85, 80, 44, 2, 76, 69, 186, 158, 6, 81, 200, + 170, 13, 3, 78, 79, 84, 22, 69, 182, 176, 5, 66, 198, 133, 7, 83, 234, + 209, 4, 71, 162, 111, 82, 183, 79, 74, 4, 158, 146, 37, 73, 147, 127, 79, + 12, 54, 73, 36, 3, 79, 87, 78, 197, 188, 35, 2, 69, 76, 4, 218, 246, 30, + 86, 219, 174, 6, 65, 4, 152, 167, 10, 2, 32, 67, 215, 153, 27, 87, 4, + 174, 209, 36, 83, 255, 110, 70, 4, 242, 248, 11, 81, 139, 158, 23, 85, 4, + 184, 3, 5, 73, 71, 72, 84, 87, 131, 189, 38, 72, 10, 88, 5, 69, 77, 73, + 67, 79, 34, 76, 34, 84, 129, 247, 11, 7, 81, 85, 73, 83, 72, 32, 81, 2, + 229, 133, 31, 3, 76, 79, 78, 2, 177, 142, 36, 3, 65, 83, 72, 4, 248, 216, + 15, 2, 65, 82, 239, 133, 7, 73, 12, 22, 32, 171, 1, 87, 10, 78, 67, 36, + 5, 84, 65, 67, 75, 32, 253, 139, 38, 6, 83, 72, 79, 69, 32, 74, 2, 229, + 221, 22, 4, 65, 82, 69, 84, 6, 210, 255, 18, 68, 162, 195, 16, 79, 139, + 201, 2, 74, 2, 169, 207, 35, 6, 65, 82, 68, 83, 32, 86, 4, 242, 237, 32, + 83, 235, 157, 5, 76, 12, 92, 2, 82, 79, 153, 200, 25, 15, 76, 73, 67, 65, + 84, 73, 79, 78, 32, 80, 82, 79, 71, 82, 65, 10, 112, 9, 88, 73, 77, 65, + 84, 69, 76, 89, 32, 153, 189, 38, 13, 65, 67, 72, 69, 83, 32, 84, 72, 69, + 32, 76, 73, 77, 8, 76, 6, 69, 81, 85, 65, 76, 32, 201, 161, 24, 7, 66, + 85, 84, 32, 78, 79, 84, 6, 32, 2, 84, 79, 255, 128, 31, 79, 5, 181, 201, + 25, 13, 32, 79, 82, 32, 84, 72, 69, 32, 73, 77, 65, 71, 69, 230, 22, 148, + 1, 4, 65, 66, 73, 67, 208, 245, 1, 7, 77, 69, 78, 73, 65, 78, 32, 224, + 12, 3, 82, 79, 87, 236, 3, 2, 84, 73, 254, 188, 35, 73, 227, 147, 1, 67, + 148, 21, 54, 32, 141, 244, 1, 7, 45, 73, 78, 68, 73, 67, 32, 248, 20, + 178, 3, 67, 158, 1, 68, 242, 2, 69, 198, 1, 70, 212, 1, 2, 72, 65, 104, + 5, 75, 65, 83, 82, 65, 86, 76, 248, 167, 1, 2, 77, 65, 220, 18, 7, 78, + 85, 77, 66, 69, 82, 32, 36, 5, 79, 80, 69, 78, 32, 82, 80, 214, 1, 82, + 156, 2, 8, 66, 65, 83, 69, 76, 73, 78, 69, 52, 6, 73, 78, 86, 69, 82, 84, + 98, 83, 154, 33, 84, 202, 4, 86, 188, 245, 16, 9, 87, 65, 86, 89, 32, 72, + 65, 77, 90, 138, 164, 17, 81, 201, 190, 1, 6, 90, 87, 65, 82, 65, 75, 14, + 44, 5, 85, 82, 76, 89, 32, 191, 135, 36, 79, 12, 72, 4, 68, 65, 77, 77, + 0, 4, 70, 65, 84, 72, 1, 4, 75, 65, 83, 82, 4, 11, 65, 5, 199, 138, 37, + 84, 24, 154, 1, 65, 108, 5, 79, 85, 66, 76, 69, 152, 2, 16, 73, 83, 80, + 85, 84, 69, 68, 32, 69, 78, 68, 32, 79, 70, 32, 65, 137, 253, 22, 5, 69, + 67, 73, 77, 65, 14, 36, 3, 77, 77, 65, 171, 189, 32, 84, 13, 22, 32, 211, + 5, 84, 6, 158, 226, 1, 73, 58, 77, 167, 202, 35, 87, 6, 202, 4, 68, 157, + 193, 1, 18, 32, 82, 73, 71, 72, 84, 32, 65, 82, 82, 79, 87, 72, 69, 65, + 68, 32, 65, 8, 88, 12, 77, 80, 84, 89, 32, 67, 69, 78, 84, 82, 69, 32, + 57, 6, 78, 68, 32, 79, 70, 32, 4, 184, 131, 36, 4, 72, 73, 71, 72, 1, 3, + 76, 79, 87, 4, 26, 65, 139, 249, 28, 84, 2, 255, 148, 31, 89, 22, 84, 4, + 65, 84, 72, 65, 230, 209, 1, 79, 164, 196, 4, 3, 73, 86, 69, 223, 235, + 29, 85, 17, 22, 32, 139, 2, 84, 10, 52, 5, 87, 73, 84, 72, 32, 162, 222, + 1, 73, 59, 77, 6, 170, 254, 36, 84, 174, 77, 68, 191, 47, 82, 6, 72, 13, + 76, 70, 32, 77, 65, 68, 68, 65, 32, 79, 86, 69, 82, 231, 16, 77, 2, 181, + 157, 17, 2, 32, 77, 13, 18, 32, 43, 84, 6, 230, 72, 87, 146, 148, 1, 73, + 59, 77, 4, 161, 82, 2, 65, 78, 224, 15, 84, 5, 65, 82, 71, 69, 32, 146, + 1, 69, 149, 90, 8, 73, 71, 65, 84, 85, 82, 69, 32, 8, 64, 10, 82, 79, 85, + 78, 68, 32, 68, 79, 84, 32, 251, 218, 10, 67, 6, 220, 218, 10, 6, 73, 78, + 83, 73, 68, 69, 238, 213, 25, 66, 223, 155, 1, 65, 252, 7, 80, 5, 84, 84, + 69, 82, 32, 157, 251, 6, 9, 70, 84, 32, 65, 82, 82, 79, 87, 72, 248, 7, + 206, 2, 65, 240, 10, 2, 66, 69, 150, 4, 68, 214, 5, 70, 246, 4, 71, 226, + 2, 72, 156, 9, 2, 74, 69, 122, 75, 246, 5, 76, 222, 2, 77, 154, 1, 78, + 140, 3, 3, 80, 69, 72, 176, 1, 3, 81, 65, 70, 214, 1, 82, 230, 3, 83, + 158, 9, 84, 186, 7, 85, 148, 2, 2, 86, 69, 28, 3, 87, 65, 87, 202, 1, 89, + 246, 3, 79, 248, 2, 2, 90, 65, 31, 69, 112, 92, 7, 70, 82, 73, 67, 65, + 78, 32, 92, 2, 73, 78, 144, 2, 3, 76, 69, 70, 195, 193, 38, 69, 8, 52, 3, + 81, 65, 70, 214, 144, 32, 70, 243, 161, 3, 78, 5, 221, 64, 5, 32, 87, 73, + 84, 72, 21, 11, 32, 18, 72, 6, 87, 73, 84, 72, 32, 84, 154, 160, 1, 70, + 230, 43, 73, 203, 9, 77, 10, 60, 10, 72, 82, 69, 69, 32, 68, 79, 84, 83, + 32, 131, 55, 87, 6, 216, 204, 14, 17, 80, 79, 73, 78, 84, 73, 78, 71, 32, + 68, 79, 87, 78, 87, 65, 82, 68, 166, 221, 21, 66, 223, 155, 1, 65, 83, + 11, 32, 80, 70, 87, 196, 45, 6, 77, 65, 75, 83, 85, 82, 202, 112, 70, + 247, 52, 73, 70, 48, 4, 73, 84, 72, 32, 145, 45, 3, 65, 83, 76, 64, 192, + 2, 9, 65, 84, 84, 65, 67, 72, 69, 68, 32, 220, 1, 19, 82, 73, 71, 72, 84, + 32, 77, 73, 68, 68, 76, 69, 32, 83, 84, 82, 79, 75, 69, 188, 1, 6, 72, + 65, 77, 90, 65, 32, 44, 8, 87, 65, 86, 89, 32, 72, 65, 77, 254, 69, 69, + 204, 1, 4, 77, 65, 68, 68, 196, 139, 35, 9, 76, 69, 70, 84, 32, 77, 73, + 68, 68, 243, 230, 1, 68, 28, 204, 1, 17, 66, 79, 84, 84, 79, 77, 32, 82, + 73, 71, 72, 84, 32, 75, 65, 83, 82, 0, 14, 84, 79, 80, 32, 82, 73, 71, + 72, 84, 32, 70, 65, 84, 72, 94, 82, 56, 3, 76, 69, 70, 186, 201, 1, 75, + 223, 160, 31, 70, 6, 11, 65, 7, 29, 5, 32, 65, 78, 68, 32, 4, 196, 231, + 18, 3, 76, 69, 70, 255, 211, 18, 68, 8, 52, 3, 73, 71, 72, 253, 214, 1, + 4, 79, 85, 78, 68, 4, 17, 2, 84, 32, 4, 162, 176, 1, 82, 227, 37, 72, 12, + 146, 72, 65, 37, 5, 66, 69, 76, 79, 87, 4, 211, 143, 36, 90, 50, 22, 72, + 219, 63, 69, 41, 22, 32, 195, 63, 69, 28, 68, 5, 87, 73, 84, 72, 32, 198, + 150, 1, 70, 230, 43, 73, 203, 9, 77, 20, 116, 6, 83, 77, 65, 76, 76, 32, + 34, 84, 154, 19, 73, 200, 33, 10, 68, 79, 84, 32, 66, 69, 76, 79, 87, 32, + 215, 19, 72, 6, 226, 39, 77, 175, 232, 22, 86, 8, 88, 10, 72, 82, 69, 69, + 32, 68, 79, 84, 83, 32, 177, 49, 7, 87, 79, 32, 68, 79, 84, 83, 6, 144, + 1, 22, 80, 79, 73, 78, 84, 73, 78, 71, 32, 85, 80, 87, 65, 82, 68, 83, + 32, 66, 69, 76, 79, 87, 133, 29, 8, 72, 79, 82, 73, 90, 79, 78, 84, 5, + 227, 191, 14, 32, 76, 90, 65, 164, 4, 2, 68, 65, 40, 7, 79, 84, 76, 69, + 83, 83, 32, 190, 28, 89, 255, 24, 85, 42, 34, 76, 154, 4, 72, 187, 46, + 68, 25, 11, 32, 22, 56, 5, 87, 73, 84, 72, 32, 226, 145, 1, 70, 247, 52, + 73, 18, 132, 1, 9, 68, 79, 84, 32, 66, 69, 76, 79, 87, 16, 9, 73, 78, 86, + 69, 82, 84, 69, 68, 32, 34, 84, 202, 215, 11, 70, 203, 138, 26, 82, 5, + 243, 1, 32, 4, 226, 14, 83, 199, 164, 38, 86, 6, 160, 1, 10, 72, 82, 69, + 69, 32, 68, 79, 84, 83, 32, 33, 25, 87, 79, 32, 68, 79, 84, 83, 32, 86, + 69, 82, 84, 73, 67, 65, 76, 76, 89, 32, 66, 69, 76, 79, 87, 32, 4, 234, + 53, 65, 195, 227, 35, 66, 2, 253, 235, 14, 10, 65, 78, 68, 32, 83, 77, + 65, 76, 76, 32, 12, 22, 72, 207, 62, 76, 6, 199, 53, 65, 6, 190, 253, 31, + 66, 2, 70, 139, 178, 5, 81, 44, 60, 8, 65, 82, 83, 73, 32, 89, 69, 72, + 169, 2, 2, 69, 72, 23, 11, 32, 20, 68, 5, 87, 73, 84, 72, 32, 194, 140, + 1, 70, 230, 43, 73, 203, 9, 77, 12, 144, 1, 28, 69, 88, 84, 69, 78, 68, + 69, 68, 32, 65, 82, 65, 66, 73, 67, 45, 73, 78, 68, 73, 67, 32, 68, 73, + 71, 73, 84, 32, 30, 84, 163, 40, 73, 6, 250, 8, 70, 219, 49, 84, 4, 226, + 245, 6, 72, 131, 194, 7, 87, 23, 11, 32, 20, 68, 5, 87, 73, 84, 72, 32, + 154, 138, 1, 70, 230, 43, 73, 203, 9, 77, 12, 32, 4, 68, 79, 84, 32, 51, + 84, 6, 254, 40, 66, 249, 142, 15, 4, 77, 79, 86, 69, 6, 64, 10, 72, 82, + 69, 69, 32, 68, 79, 84, 83, 32, 203, 132, 36, 87, 4, 198, 17, 80, 227, + 129, 36, 66, 44, 72, 2, 65, 70, 160, 1, 4, 72, 65, 73, 78, 178, 21, 85, + 143, 147, 37, 82, 19, 11, 32, 16, 68, 5, 87, 73, 84, 72, 32, 194, 135, 1, + 70, 230, 43, 73, 203, 9, 77, 8, 162, 24, 84, 134, 193, 37, 82, 229, 32, + 8, 73, 78, 86, 69, 82, 84, 69, 68, 15, 11, 32, 12, 68, 5, 87, 73, 84, 72, + 32, 162, 134, 1, 70, 230, 43, 73, 203, 9, 77, 4, 254, 37, 84, 171, 140, + 26, 68, 82, 78, 65, 236, 5, 2, 69, 72, 161, 2, 9, 73, 71, 72, 32, 72, 65, + 77, 90, 65, 34, 34, 72, 213, 47, 3, 77, 90, 65, 31, 11, 32, 28, 68, 5, + 87, 73, 84, 72, 32, 186, 132, 1, 70, 230, 43, 73, 203, 9, 77, 20, 132, 2, + 29, 69, 88, 84, 69, 78, 68, 69, 68, 32, 65, 82, 65, 66, 73, 67, 45, 73, + 78, 68, 73, 67, 32, 68, 73, 71, 73, 84, 32, 70, 30, 73, 92, 24, 83, 77, + 65, 76, 76, 32, 65, 82, 65, 66, 73, 67, 32, 76, 69, 84, 84, 69, 82, 32, + 84, 65, 72, 32, 62, 84, 135, 52, 72, 2, 145, 186, 1, 2, 79, 85, 2, 45, 9, + 78, 86, 69, 82, 84, 69, 68, 32, 83, 2, 221, 253, 35, 6, 77, 65, 76, 76, + 32, 86, 6, 26, 65, 199, 139, 36, 66, 4, 174, 31, 78, 255, 135, 37, 66, 8, + 88, 10, 72, 82, 69, 69, 32, 68, 79, 84, 83, 32, 33, 8, 87, 79, 32, 68, + 79, 84, 83, 32, 4, 230, 8, 80, 191, 157, 37, 65, 4, 232, 165, 37, 8, 86, + 69, 82, 84, 73, 67, 65, 76, 27, 65, 41, 11, 32, 38, 144, 1, 4, 71, 79, + 65, 76, 88, 5, 87, 73, 84, 72, 32, 220, 46, 10, 68, 79, 65, 67, 72, 65, + 83, 72, 77, 69, 242, 78, 70, 230, 43, 73, 203, 9, 77, 13, 11, 32, 10, + 156, 49, 6, 87, 73, 84, 72, 32, 72, 250, 76, 70, 230, 43, 73, 203, 9, 77, + 8, 218, 26, 73, 245, 18, 3, 89, 69, 72, 9, 11, 32, 6, 166, 254, 22, 65, + 178, 238, 8, 89, 135, 181, 5, 87, 22, 28, 2, 69, 77, 131, 45, 72, 17, 11, + 32, 14, 140, 31, 6, 87, 73, 84, 72, 32, 84, 170, 93, 70, 230, 43, 73, + 203, 9, 77, 68, 98, 65, 208, 1, 4, 69, 72, 69, 72, 160, 3, 7, 73, 82, 71, + 72, 73, 90, 32, 205, 30, 2, 72, 65, 22, 46, 70, 177, 162, 1, 5, 83, 72, + 77, 73, 82, 21, 11, 32, 18, 64, 5, 87, 73, 84, 72, 32, 138, 122, 70, 230, + 43, 73, 203, 9, 77, 10, 42, 84, 130, 174, 34, 68, 199, 157, 3, 82, 4, + 174, 166, 14, 87, 207, 206, 21, 72, 25, 11, 32, 22, 64, 5, 87, 73, 84, + 72, 32, 234, 120, 70, 230, 43, 73, 203, 9, 77, 14, 38, 84, 226, 41, 83, + 143, 241, 36, 68, 10, 88, 10, 72, 82, 69, 69, 32, 68, 79, 84, 83, 32, + 121, 8, 87, 79, 32, 68, 79, 84, 83, 32, 6, 42, 80, 226, 129, 36, 66, 223, + 155, 1, 65, 2, 165, 243, 35, 14, 79, 73, 78, 84, 73, 78, 71, 32, 85, 80, + 87, 65, 82, 68, 4, 48, 6, 86, 69, 82, 84, 73, 67, 191, 156, 37, 65, 2, + 145, 188, 11, 3, 65, 76, 76, 12, 198, 38, 79, 13, 2, 89, 85, 26, 40, 2, + 65, 77, 245, 169, 1, 2, 79, 87, 25, 11, 32, 22, 64, 5, 87, 73, 84, 72, + 32, 254, 116, 70, 230, 43, 73, 203, 9, 77, 14, 88, 2, 68, 79, 36, 6, 83, + 77, 65, 76, 76, 32, 216, 162, 32, 2, 84, 72, 223, 209, 4, 66, 4, 166, + 161, 17, 85, 231, 248, 19, 84, 4, 204, 26, 16, 65, 82, 65, 66, 73, 67, + 32, 76, 69, 84, 84, 69, 82, 32, 84, 65, 143, 252, 37, 86, 18, 36, 3, 69, + 69, 77, 195, 212, 37, 65, 17, 11, 32, 14, 64, 5, 87, 73, 84, 72, 32, 166, + 114, 70, 230, 43, 73, 203, 9, 77, 6, 130, 18, 84, 199, 148, 34, 68, 60, + 38, 71, 26, 89, 17, 3, 79, 79, 78, 21, 22, 79, 255, 108, 32, 10, 247, 25, + 69, 31, 11, 32, 28, 92, 5, 71, 72, 85, 78, 78, 16, 5, 87, 73, 84, 72, 32, + 186, 112, 70, 230, 43, 73, 203, 9, 77, 6, 131, 33, 65, 14, 116, 6, 83, + 77, 65, 76, 76, 32, 38, 84, 184, 23, 8, 73, 78, 86, 69, 82, 84, 69, 68, + 238, 131, 26, 68, 227, 165, 11, 82, 4, 214, 217, 30, 84, 203, 184, 7, 86, + 4, 238, 217, 6, 72, 247, 144, 29, 87, 25, 22, 32, 151, 23, 69, 12, 88, + 11, 87, 73, 84, 72, 32, 83, 77, 65, 76, 76, 32, 134, 110, 70, 230, 43, + 73, 203, 9, 77, 4, 26, 77, 203, 144, 38, 86, 2, 209, 147, 37, 3, 69, 69, + 77, 19, 11, 32, 16, 64, 5, 87, 73, 84, 72, 32, 250, 108, 70, 230, 43, 73, + 203, 9, 77, 8, 36, 4, 68, 79, 84, 32, 179, 12, 84, 6, 44, 5, 66, 69, 76, + 79, 87, 167, 146, 37, 65, 5, 241, 152, 14, 6, 32, 65, 78, 68, 32, 78, 52, + 108, 2, 69, 72, 192, 27, 3, 82, 69, 72, 136, 3, 4, 78, 79, 79, 78, 197, + 118, 7, 79, 72, 73, 78, 71, 89, 65, 35, 11, 32, 32, 52, 5, 87, 73, 84, + 72, 32, 194, 106, 70, 247, 52, 73, 28, 134, 1, 83, 96, 2, 84, 87, 234, 5, + 73, 250, 21, 72, 154, 148, 11, 70, 148, 226, 6, 5, 68, 79, 84, 32, 66, + 234, 39, 76, 207, 128, 19, 82, 10, 44, 5, 77, 65, 76, 76, 32, 251, 219, + 37, 84, 8, 194, 6, 65, 182, 198, 6, 78, 215, 150, 16, 86, 4, 37, 7, 79, + 32, 68, 79, 84, 83, 32, 4, 162, 8, 86, 147, 134, 37, 65, 60, 184, 1, 2, + 65, 68, 120, 3, 69, 69, 78, 132, 6, 4, 72, 69, 69, 78, 220, 147, 1, 4, + 85, 80, 69, 82, 156, 145, 4, 7, 84, 82, 65, 73, 71, 72, 84, 169, 220, 31, + 6, 87, 65, 83, 72, 32, 75, 17, 11, 32, 14, 68, 6, 87, 73, 84, 72, 32, 84, + 130, 102, 70, 230, 43, 73, 203, 9, 77, 6, 218, 148, 32, 72, 239, 204, 3, + 87, 27, 11, 32, 24, 64, 5, 87, 73, 84, 72, 32, 142, 101, 70, 230, 43, 73, + 203, 9, 77, 16, 232, 1, 3, 68, 79, 84, 50, 73, 44, 7, 83, 77, 65, 76, 76, + 32, 65, 110, 84, 250, 168, 11, 70, 177, 137, 5, 31, 69, 88, 84, 69, 78, + 68, 69, 68, 32, 65, 82, 65, 66, 73, 67, 45, 73, 78, 68, 73, 67, 32, 68, + 73, 71, 73, 84, 32, 70, 79, 85, 2, 249, 140, 18, 7, 32, 66, 69, 76, 79, + 87, 32, 2, 169, 20, 7, 78, 86, 69, 82, 84, 69, 68, 2, 85, 19, 82, 65, 66, + 73, 67, 32, 76, 69, 84, 84, 69, 82, 32, 84, 65, 72, 32, 65, 78, 2, 159, + 167, 22, 68, 6, 96, 11, 72, 82, 69, 69, 32, 68, 79, 84, 83, 32, 66, 105, + 9, 87, 79, 32, 68, 79, 84, 83, 32, 86, 4, 25, 4, 69, 76, 79, 87, 5, 11, + 32, 2, 21, 3, 65, 78, 68, 2, 17, 2, 32, 84, 2, 243, 202, 6, 72, 2, 209, + 165, 11, 8, 69, 82, 84, 73, 67, 65, 76, 76, 13, 11, 32, 10, 46, 87, 158, + 95, 70, 230, 43, 73, 203, 9, 77, 2, 161, 139, 26, 5, 73, 84, 72, 32, 68, + 118, 92, 2, 65, 72, 144, 1, 4, 67, 72, 69, 72, 124, 2, 69, 72, 150, 3, + 72, 61, 3, 84, 69, 72, 19, 11, 32, 16, 64, 5, 87, 73, 84, 72, 32, 198, + 93, 70, 230, 43, 73, 203, 9, 77, 8, 26, 84, 179, 137, 26, 68, 6, 250, + 137, 14, 87, 139, 130, 18, 72, 25, 22, 32, 163, 5, 69, 12, 64, 5, 87, 73, + 84, 72, 32, 170, 92, 70, 230, 43, 73, 203, 9, 77, 4, 198, 13, 83, 143, + 241, 36, 68, 37, 22, 32, 167, 4, 69, 24, 62, 77, 116, 5, 87, 73, 84, 72, + 32, 190, 90, 70, 231, 43, 73, 10, 48, 6, 65, 82, 66, 85, 84, 65, 183, + 144, 1, 69, 9, 11, 32, 6, 238, 90, 70, 246, 52, 73, 197, 228, 35, 2, 71, + 79, 8, 104, 6, 83, 77, 65, 76, 76, 32, 56, 12, 84, 72, 82, 69, 69, 32, + 68, 79, 84, 83, 32, 65, 131, 171, 37, 82, 4, 32, 2, 84, 69, 143, 252, 37, + 86, 2, 151, 255, 36, 72, 2, 237, 135, 27, 4, 66, 79, 86, 69, 18, 42, 65, + 126, 69, 213, 129, 1, 2, 73, 78, 6, 131, 9, 76, 23, 18, 32, 91, 69, 10, + 60, 4, 87, 73, 84, 72, 230, 87, 70, 230, 43, 73, 203, 9, 77, 2, 129, 9, + 2, 32, 83, 10, 143, 11, 72, 15, 158, 1, 32, 181, 80, 33, 73, 71, 72, 85, + 82, 32, 75, 65, 90, 65, 75, 72, 32, 75, 73, 82, 71, 72, 73, 90, 32, 65, + 76, 69, 70, 32, 77, 65, 75, 83, 85, 82, 65, 8, 96, 16, 87, 73, 84, 72, + 32, 72, 65, 77, 90, 65, 32, 65, 66, 79, 86, 69, 186, 85, 70, 247, 52, 73, + 5, 155, 75, 32, 17, 234, 8, 72, 167, 76, 32, 25, 11, 32, 22, 52, 5, 87, + 73, 84, 72, 32, 202, 84, 70, 247, 52, 73, 18, 80, 4, 68, 79, 84, 32, 162, + 2, 69, 182, 1, 72, 234, 252, 13, 84, 163, 165, 23, 82, 4, 192, 178, 30, + 3, 87, 73, 84, 183, 199, 6, 65, 54, 28, 2, 69, 72, 227, 3, 85, 49, 11, + 32, 46, 100, 6, 66, 65, 82, 82, 69, 69, 252, 2, 5, 87, 73, 84, 72, 32, + 182, 79, 70, 230, 43, 73, 203, 9, 77, 17, 11, 32, 14, 52, 5, 87, 73, 84, + 72, 32, 238, 81, 70, 247, 52, 73, 10, 22, 69, 183, 1, 72, 4, 121, 28, 88, + 84, 69, 78, 68, 69, 68, 32, 65, 82, 65, 66, 73, 67, 45, 73, 78, 68, 73, + 67, 32, 68, 73, 71, 73, 84, 32, 84, 4, 160, 229, 34, 3, 72, 82, 69, 161, + 145, 2, 2, 87, 79, 6, 21, 3, 65, 77, 90, 6, 11, 65, 6, 17, 2, 32, 65, 6, + 21, 3, 66, 79, 86, 6, 11, 69, 7, 171, 79, 32, 22, 64, 10, 72, 65, 77, 90, + 65, 32, 65, 66, 79, 86, 18, 83, 51, 84, 10, 179, 2, 69, 2, 25, 4, 77, 65, + 76, 76, 2, 255, 150, 31, 32, 10, 108, 18, 87, 79, 32, 68, 79, 84, 83, 32, + 66, 69, 76, 79, 87, 32, 65, 78, 68, 32, 174, 195, 35, 65, 183, 5, 72, 6, + 70, 72, 232, 176, 6, 7, 83, 77, 65, 76, 76, 32, 78, 191, 190, 30, 68, 2, + 205, 248, 32, 3, 65, 77, 90, 18, 26, 72, 17, 2, 73, 78, 11, 243, 71, 32, + 9, 11, 32, 6, 158, 76, 70, 246, 52, 73, 161, 11, 13, 87, 73, 84, 72, 32, + 73, 78, 86, 69, 82, 84, 69, 68, 220, 7, 230, 5, 65, 158, 5, 66, 176, 2, + 9, 68, 65, 68, 32, 87, 73, 84, 72, 32, 80, 9, 70, 69, 72, 32, 87, 73, 84, + 72, 32, 72, 11, 71, 72, 65, 73, 78, 32, 87, 73, 84, 72, 32, 154, 1, 72, + 134, 3, 74, 190, 2, 75, 252, 1, 9, 76, 65, 77, 32, 87, 73, 84, 72, 32, + 226, 4, 77, 152, 4, 10, 78, 79, 79, 78, 32, 87, 73, 84, 72, 32, 182, 2, + 81, 190, 2, 82, 178, 2, 83, 146, 16, 84, 196, 9, 7, 87, 65, 83, 65, 76, + 76, 65, 40, 9, 89, 69, 72, 32, 87, 73, 84, 72, 32, 216, 3, 53, 85, 73, + 71, 72, 85, 82, 32, 75, 73, 82, 71, 72, 73, 90, 32, 89, 69, 72, 32, 87, + 73, 84, 72, 32, 72, 65, 77, 90, 65, 32, 65, 66, 79, 86, 69, 32, 87, 73, + 84, 72, 32, 65, 76, 69, 70, 32, 77, 65, 75, 83, 85, 82, 65, 205, 6, 14, + 90, 65, 72, 32, 87, 73, 84, 72, 32, 77, 69, 69, 77, 32, 54, 128, 1, 8, + 73, 78, 32, 87, 73, 84, 72, 32, 70, 76, 232, 57, 4, 75, 66, 65, 82, 205, + 168, 35, 8, 90, 90, 65, 32, 87, 65, 32, 74, 28, 152, 19, 4, 77, 69, 69, + 77, 150, 16, 74, 238, 23, 65, 255, 8, 89, 22, 56, 3, 65, 89, 72, 216, 1, + 3, 69, 70, 32, 207, 13, 76, 12, 30, 73, 122, 65, 151, 56, 69, 8, 52, 9, + 32, 65, 83, 45, 83, 65, 76, 65, 65, 47, 77, 4, 80, 4, 84, 85, 32, 87, + 139, 229, 37, 77, 4, 18, 65, 23, 32, 2, 17, 2, 65, 32, 2, 149, 153, 32, + 6, 65, 83, 45, 83, 65, 76, 8, 212, 65, 29, 77, 65, 75, 83, 85, 82, 65, + 32, 87, 73, 84, 72, 32, 83, 85, 80, 69, 82, 83, 67, 82, 73, 80, 84, 32, + 65, 76, 69, 70, 1, 13, 87, 73, 84, 72, 32, 70, 65, 84, 72, 65, 84, 65, + 78, 44, 160, 1, 8, 69, 72, 32, 87, 73, 84, 72, 32, 141, 135, 25, 25, 73, + 83, 77, 73, 76, 76, 65, 72, 32, 65, 82, 45, 82, 65, 72, 77, 65, 78, 32, + 65, 82, 45, 82, 65, 72, 42, 98, 72, 24, 3, 75, 72, 65, 230, 52, 65, 250, + 3, 74, 78, 77, 86, 78, 78, 90, 242, 2, 82, 43, 89, 10, 22, 65, 171, 56, + 69, 6, 131, 59, 72, 36, 222, 6, 72, 158, 7, 75, 218, 38, 65, 250, 3, 74, + 2, 77, 134, 5, 82, 3, 89, 30, 170, 13, 75, 218, 38, 65, 250, 3, 74, 146, + 2, 77, 110, 72, 139, 2, 89, 22, 64, 5, 77, 69, 69, 77, 32, 250, 50, 65, + 250, 3, 74, 135, 5, 89, 10, 40, 5, 87, 73, 84, 72, 32, 235, 103, 73, 6, + 174, 21, 77, 170, 25, 65, 203, 12, 89, 40, 80, 8, 65, 72, 32, 87, 73, 84, + 72, 32, 69, 8, 69, 72, 32, 87, 73, 84, 72, 32, 22, 236, 3, 4, 77, 69, 69, + 77, 226, 45, 65, 138, 6, 74, 247, 2, 89, 18, 164, 1, 5, 77, 69, 69, 77, + 32, 196, 11, 6, 65, 76, 69, 70, 32, 77, 150, 2, 89, 134, 38, 74, 53, 16, + 83, 85, 80, 69, 82, 83, 67, 82, 73, 80, 84, 32, 65, 76, 69, 70, 8, 40, 5, + 87, 73, 84, 72, 32, 215, 100, 73, 4, 254, 43, 74, 3, 77, 30, 104, 9, 69, + 69, 77, 32, 87, 73, 84, 72, 32, 173, 230, 3, 11, 65, 76, 76, 65, 74, 65, + 76, 65, 76, 79, 85, 28, 62, 72, 60, 5, 77, 69, 69, 77, 32, 186, 45, 65, + 255, 8, 89, 8, 17, 2, 65, 72, 8, 11, 32, 8, 178, 29, 87, 191, 69, 73, 12, + 40, 5, 87, 73, 84, 72, 32, 171, 98, 73, 8, 166, 37, 72, 242, 3, 65, 203, + 12, 89, 64, 84, 8, 65, 70, 32, 87, 73, 84, 72, 32, 93, 9, 72, 65, 72, 32, + 87, 73, 84, 72, 32, 46, 168, 46, 2, 65, 76, 218, 1, 74, 96, 2, 76, 65, + 146, 2, 75, 14, 72, 30, 77, 239, 1, 89, 18, 54, 72, 250, 42, 65, 250, 3, + 74, 2, 77, 135, 5, 89, 2, 247, 8, 65, 74, 116, 5, 65, 76, 69, 70, 32, + 210, 1, 72, 124, 5, 74, 69, 69, 77, 32, 78, 75, 28, 5, 77, 69, 69, 77, + 32, 187, 47, 89, 20, 64, 5, 87, 73, 84, 72, 32, 138, 44, 77, 222, 6, 70, + 247, 52, 73, 12, 68, 6, 72, 65, 77, 90, 65, 32, 41, 7, 77, 65, 68, 68, + 65, 32, 65, 8, 38, 65, 249, 45, 4, 66, 69, 76, 79, 4, 229, 45, 3, 66, 79, + 86, 14, 28, 2, 65, 72, 163, 44, 69, 12, 11, 32, 12, 40, 5, 87, 73, 84, + 72, 32, 231, 92, 73, 8, 210, 35, 65, 130, 12, 77, 75, 89, 14, 40, 5, 87, + 73, 84, 72, 32, 151, 92, 73, 10, 130, 47, 74, 2, 77, 75, 89, 8, 129, 15, + 3, 72, 65, 72, 14, 150, 14, 87, 222, 33, 70, 230, 43, 73, 203, 9, 77, 48, + 84, 9, 69, 69, 77, 32, 87, 73, 84, 72, 32, 193, 36, 7, 79, 72, 65, 77, + 77, 65, 68, 46, 116, 5, 65, 76, 69, 70, 32, 66, 72, 0, 2, 75, 72, 104, 5, + 74, 69, 69, 77, 32, 92, 5, 77, 69, 69, 77, 32, 43, 89, 4, 22, 77, 219, + 45, 70, 2, 173, 35, 6, 65, 75, 83, 85, 82, 65, 10, 21, 3, 65, 72, 32, 10, + 40, 5, 87, 73, 84, 72, 32, 211, 88, 73, 6, 250, 31, 74, 2, 77, 143, 12, + 89, 12, 40, 5, 87, 73, 84, 72, 32, 131, 88, 73, 8, 170, 31, 77, 194, 7, + 75, 14, 72, 195, 4, 89, 8, 246, 40, 87, 246, 2, 70, 231, 43, 73, 2, 11, + 69, 2, 143, 33, 72, 60, 134, 1, 72, 28, 5, 74, 69, 69, 77, 32, 92, 5, 77, + 69, 69, 77, 32, 242, 31, 65, 154, 5, 78, 78, 90, 134, 1, 75, 238, 1, 82, + 43, 89, 14, 146, 27, 65, 155, 9, 69, 16, 40, 5, 87, 73, 84, 72, 32, 191, + 85, 73, 12, 186, 24, 72, 242, 3, 65, 130, 12, 77, 75, 89, 12, 206, 15, + 87, 218, 25, 70, 230, 43, 73, 203, 9, 77, 28, 70, 65, 197, 146, 30, 11, + 85, 68, 68, 73, 83, 65, 32, 83, 73, 82, 82, 26, 64, 7, 70, 32, 87, 73, + 84, 72, 32, 193, 8, 4, 76, 65, 32, 85, 24, 64, 5, 77, 69, 69, 77, 32, + 238, 29, 65, 246, 6, 72, 139, 2, 89, 12, 40, 5, 87, 73, 84, 72, 32, 223, + 82, 73, 8, 34, 77, 186, 21, 72, 187, 16, 89, 2, 129, 38, 3, 69, 69, 77, + 18, 30, 65, 129, 26, 2, 69, 72, 16, 128, 1, 14, 68, 73, 32, 65, 76, 76, + 65, 65, 72, 85, 32, 65, 78, 72, 76, 6, 72, 73, 77, 65, 72, 85, 161, 26, + 4, 83, 79, 85, 76, 11, 26, 85, 163, 197, 37, 65, 6, 26, 77, 251, 140, 36, + 78, 5, 131, 197, 37, 65, 4, 26, 32, 1, 2, 77, 32, 2, 193, 142, 30, 4, 65, + 76, 76, 65, 190, 1, 138, 1, 65, 192, 6, 9, 69, 69, 78, 32, 87, 73, 84, + 72, 32, 250, 3, 72, 233, 5, 13, 85, 66, 72, 65, 65, 78, 65, 72, 85, 32, + 87, 65, 32, 46, 48, 7, 68, 32, 87, 73, 84, 72, 32, 251, 1, 76, 32, 76, 4, + 72, 65, 72, 32, 82, 77, 238, 23, 65, 138, 4, 75, 246, 4, 82, 3, 89, 10, + 22, 87, 195, 77, 73, 6, 25, 4, 73, 84, 72, 32, 6, 162, 16, 72, 187, 16, + 89, 8, 21, 3, 69, 69, 77, 8, 11, 32, 8, 208, 31, 6, 87, 73, 84, 72, 32, + 77, 147, 45, 73, 14, 26, 65, 77, 2, 76, 65, 4, 134, 22, 77, 193, 189, 35, + 11, 65, 77, 85, 72, 85, 32, 65, 76, 65, 89, 78, 10, 34, 32, 133, 1, 3, + 76, 76, 65, 4, 22, 85, 159, 84, 73, 2, 217, 8, 23, 83, 69, 68, 32, 65, + 83, 32, 75, 79, 82, 65, 78, 73, 67, 32, 83, 84, 79, 80, 32, 83, 73, 71, + 6, 98, 72, 169, 191, 37, 18, 65, 72, 85, 32, 65, 76, 65, 89, 72, 73, 32, + 87, 65, 45, 65, 65, 76, 73, 4, 220, 63, 12, 79, 85, 32, 65, 76, 65, 89, + 72, 69, 32, 87, 65, 1, 22, 85, 32, 65, 76, 65, 89, 72, 73, 32, 87, 65, + 65, 65, 76, 73, 72, 69, 69, 32, 87, 65, 45, 60, 130, 1, 72, 100, 5, 74, + 69, 69, 77, 32, 84, 5, 75, 72, 65, 72, 32, 92, 5, 77, 69, 69, 77, 32, + 234, 15, 65, 254, 8, 82, 3, 89, 12, 32, 3, 65, 72, 32, 159, 21, 69, 8, + 156, 14, 6, 87, 73, 84, 72, 32, 74, 214, 56, 73, 203, 9, 77, 10, 52, 5, + 87, 73, 84, 72, 32, 254, 69, 73, 203, 9, 77, 4, 234, 12, 65, 139, 8, 72, + 10, 34, 87, 190, 69, 73, 203, 9, 77, 4, 25, 4, 73, 84, 72, 32, 4, 142, + 12, 65, 203, 12, 89, 16, 52, 5, 87, 73, 84, 72, 32, 206, 68, 73, 203, 9, + 77, 10, 202, 7, 72, 174, 4, 74, 199, 11, 77, 82, 96, 10, 65, 68, 68, 65, + 32, 87, 73, 84, 72, 32, 161, 1, 9, 69, 69, 78, 32, 87, 73, 84, 72, 32, + 18, 96, 4, 68, 65, 77, 77, 0, 4, 75, 65, 83, 82, 138, 11, 83, 237, 41, 6, + 70, 65, 84, 72, 65, 32, 6, 11, 65, 6, 28, 2, 84, 65, 203, 52, 32, 2, 163, + 12, 78, 64, 130, 1, 72, 36, 5, 74, 69, 69, 77, 32, 52, 5, 77, 69, 69, 77, + 32, 170, 11, 65, 228, 4, 4, 75, 72, 65, 72, 154, 4, 82, 3, 89, 18, 194, + 15, 69, 229, 3, 2, 65, 72, 10, 158, 18, 87, 246, 2, 70, 230, 43, 73, 203, + 9, 77, 16, 64, 5, 87, 73, 84, 72, 32, 158, 20, 70, 230, 43, 73, 203, 9, + 77, 8, 252, 2, 2, 75, 72, 243, 15, 77, 122, 66, 65, 176, 2, 8, 69, 72, + 32, 87, 73, 84, 72, 32, 179, 4, 72, 28, 88, 11, 66, 65, 65, 82, 65, 75, + 65, 32, 87, 65, 45, 29, 7, 72, 32, 87, 73, 84, 72, 32, 2, 177, 163, 27, + 2, 84, 65, 26, 64, 5, 77, 69, 69, 77, 32, 194, 8, 65, 246, 6, 72, 139, 2, + 89, 14, 52, 5, 87, 73, 84, 72, 32, 166, 61, 73, 203, 9, 77, 8, 34, 72, + 174, 4, 77, 143, 12, 89, 4, 133, 16, 2, 65, 72, 66, 138, 1, 72, 108, 3, + 75, 72, 65, 12, 4, 74, 69, 69, 77, 92, 5, 77, 69, 69, 77, 32, 238, 4, 65, + 154, 5, 78, 78, 90, 242, 2, 82, 43, 89, 14, 32, 3, 65, 72, 32, 227, 9, + 69, 10, 40, 5, 87, 73, 84, 72, 32, 143, 59, 73, 6, 182, 2, 77, 199, 11, + 74, 10, 11, 72, 10, 11, 32, 10, 40, 5, 87, 73, 84, 72, 32, 175, 58, 73, + 6, 154, 1, 65, 62, 77, 143, 12, 89, 18, 64, 5, 87, 73, 84, 72, 32, 226, + 13, 70, 230, 43, 73, 203, 9, 77, 10, 50, 65, 62, 74, 194, 7, 75, 14, 72, + 195, 4, 89, 2, 217, 12, 11, 76, 69, 70, 32, 77, 65, 75, 83, 85, 82, 65, + 2, 225, 7, 3, 69, 69, 77, 28, 56, 2, 65, 76, 117, 8, 69, 72, 32, 87, 73, + 84, 72, 32, 2, 37, 7, 32, 87, 73, 84, 72, 32, 83, 2, 197, 1, 15, 85, 80, + 69, 82, 83, 67, 82, 73, 80, 84, 32, 65, 76, 69, 70, 26, 108, 3, 74, 69, + 69, 126, 65, 198, 4, 77, 86, 78, 78, 90, 242, 2, 82, 42, 89, 233, 53, 5, + 72, 69, 72, 32, 77, 2, 11, 77, 2, 11, 32, 2, 143, 63, 73, 114, 82, 65, + 38, 72, 246, 4, 78, 78, 90, 38, 74, 98, 75, 42, 77, 198, 1, 82, 43, 89, + 4, 217, 2, 5, 76, 69, 70, 32, 77, 76, 22, 65, 139, 3, 69, 72, 80, 15, 77, + 90, 65, 32, 65, 66, 79, 86, 69, 32, 87, 73, 84, 72, 32, 147, 5, 72, 66, + 118, 65, 126, 69, 42, 72, 78, 74, 18, 75, 62, 77, 86, 78, 22, 79, 16, 2, + 87, 65, 18, 89, 26, 90, 242, 2, 82, 67, 85, 12, 22, 76, 247, 6, 69, 8, + 21, 3, 69, 70, 32, 8, 34, 77, 222, 6, 70, 247, 52, 73, 4, 181, 6, 6, 65, + 75, 83, 85, 82, 65, 6, 11, 32, 6, 166, 6, 70, 231, 43, 73, 8, 22, 69, + 191, 3, 65, 4, 11, 72, 4, 11, 32, 4, 230, 4, 73, 163, 54, 77, 4, 251, 48, + 69, 2, 11, 72, 2, 11, 65, 2, 11, 72, 2, 149, 4, 2, 32, 73, 8, 17, 2, 69, + 69, 8, 11, 77, 8, 11, 32, 8, 198, 4, 70, 230, 43, 73, 203, 9, 77, 2, 93, + 2, 79, 79, 4, 231, 3, 69, 4, 215, 3, 87, 8, 186, 3, 69, 15, 85, 2, 17, 2, + 65, 73, 2, 239, 2, 78, 6, 21, 3, 69, 69, 77, 6, 11, 32, 6, 22, 87, 219, + 46, 73, 2, 141, 2, 5, 73, 84, 72, 32, 89, 4, 11, 72, 4, 11, 65, 4, 135, + 46, 72, 14, 21, 3, 69, 69, 77, 14, 11, 32, 14, 64, 5, 87, 73, 84, 72, 32, + 194, 1, 70, 230, 43, 73, 203, 9, 77, 6, 18, 77, 75, 89, 4, 21, 3, 69, 69, + 77, 4, 11, 32, 4, 18, 73, 119, 70, 2, 239, 44, 78, 2, 17, 2, 69, 72, 2, + 77, 2, 32, 70, 4, 11, 69, 4, 11, 72, 4, 11, 32, 4, 22, 70, 247, 52, 73, + 2, 205, 53, 2, 73, 78, 6, 202, 43, 73, 203, 9, 77, 166, 2, 92, 3, 68, 68, + 65, 52, 3, 82, 75, 32, 109, 11, 84, 72, 69, 77, 65, 84, 73, 67, 65, 76, + 32, 4, 148, 231, 35, 5, 32, 87, 65, 65, 74, 191, 61, 72, 4, 58, 78, 1, + 10, 83, 73, 68, 69, 87, 65, 89, 83, 32, 78, 2, 221, 254, 33, 7, 79, 79, + 78, 32, 71, 72, 85, 158, 2, 178, 2, 68, 144, 3, 8, 73, 78, 73, 84, 73, + 65, 76, 32, 222, 1, 76, 132, 2, 9, 79, 80, 69, 82, 65, 84, 79, 82, 32, + 166, 1, 83, 146, 3, 84, 158, 205, 23, 65, 102, 75, 110, 90, 246, 104, 74, + 2, 77, 166, 162, 5, 72, 170, 133, 1, 66, 2, 70, 2, 82, 2, 89, 174, 57, + 71, 198, 232, 2, 78, 154, 144, 2, 81, 255, 2, 87, 62, 26, 79, 187, 155, + 36, 65, 58, 88, 6, 84, 76, 69, 83, 83, 32, 61, 12, 85, 66, 76, 69, 45, + 83, 84, 82, 85, 67, 75, 32, 8, 214, 233, 30, 66, 2, 70, 242, 161, 3, 78, + 155, 144, 2, 81, 50, 190, 12, 83, 186, 20, 75, 158, 183, 23, 84, 74, 90, + 246, 104, 74, 2, 77, 166, 162, 5, 72, 170, 133, 1, 66, 2, 70, 2, 82, 2, + 89, 174, 57, 71, 198, 232, 2, 78, 246, 215, 1, 76, 150, 55, 68, 146, 1, + 81, 222, 1, 65, 163, 1, 87, 40, 182, 1, 84, 174, 9, 83, 150, 203, 23, 72, + 30, 75, 226, 105, 74, 2, 77, 206, 167, 6, 66, 2, 70, 2, 89, 174, 57, 71, + 198, 232, 2, 78, 246, 215, 1, 76, 166, 56, 81, 222, 1, 65, 159, 57, 68, + 4, 134, 230, 30, 72, 147, 178, 6, 69, 56, 48, 6, 79, 79, 80, 69, 68, 32, + 251, 135, 37, 65, 54, 210, 8, 83, 186, 20, 75, 150, 182, 23, 65, 74, 72, + 66, 84, 74, 90, 246, 104, 74, 2, 77, 206, 167, 6, 66, 2, 70, 2, 82, 2, + 89, 174, 57, 71, 198, 232, 2, 78, 246, 215, 1, 76, 150, 55, 68, 146, 1, + 81, 255, 2, 87, 4, 160, 154, 28, 23, 77, 69, 69, 77, 32, 87, 73, 84, 72, + 32, 72, 65, 72, 32, 87, 73, 84, 72, 32, 84, 65, 84, 87, 177, 233, 7, 9, + 72, 65, 72, 32, 87, 73, 84, 72, 32, 52, 84, 9, 84, 82, 69, 84, 67, 72, + 69, 68, 32, 134, 196, 35, 72, 14, 69, 227, 138, 1, 65, 46, 182, 1, 68, + 86, 84, 254, 2, 83, 150, 203, 23, 72, 30, 75, 226, 105, 74, 2, 77, 166, + 162, 5, 90, 170, 133, 1, 66, 2, 70, 2, 89, 174, 57, 71, 198, 232, 2, 78, + 154, 144, 2, 81, 223, 1, 65, 6, 52, 7, 79, 84, 76, 69, 83, 83, 32, 131, + 205, 36, 65, 4, 242, 223, 30, 66, 3, 70, 6, 214, 223, 30, 72, 146, 178, + 6, 65, 3, 69, 38, 42, 65, 158, 206, 23, 72, 247, 194, 13, 69, 32, 44, 5, + 73, 76, 69, 68, 32, 243, 145, 37, 72, 30, 150, 1, 68, 94, 83, 186, 20, + 75, 218, 160, 24, 74, 166, 162, 5, 72, 170, 133, 1, 89, 174, 57, 71, 198, + 232, 2, 78, 246, 215, 1, 76, 166, 56, 81, 223, 1, 65, 6, 52, 7, 79, 84, + 76, 69, 83, 83, 32, 143, 202, 36, 65, 4, 238, 254, 33, 78, 155, 144, 2, + 81, 6, 250, 190, 35, 72, 14, 69, 227, 138, 1, 65, 4, 238, 252, 17, 77, + 147, 140, 18, 83, 6, 128, 149, 24, 3, 75, 65, 83, 12, 4, 68, 65, 77, 77, + 1, 4, 70, 65, 84, 72, 10, 130, 1, 79, 212, 156, 12, 11, 76, 65, 67, 69, + 32, 79, 70, 32, 83, 65, 74, 144, 222, 5, 6, 73, 65, 83, 84, 82, 69, 175, + 173, 13, 69, 4, 148, 141, 12, 8, 69, 84, 73, 67, 32, 86, 69, 82, 205, + 237, 5, 3, 85, 78, 68, 14, 238, 1, 65, 96, 5, 69, 86, 69, 82, 83, 36, 15, + 73, 71, 72, 84, 32, 65, 82, 82, 79, 87, 72, 69, 65, 68, 32, 201, 206, 22, + 28, 79, 85, 78, 68, 69, 68, 32, 72, 73, 71, 72, 32, 83, 84, 79, 80, 32, + 87, 73, 84, 72, 32, 70, 73, 76, 76, 69, 68, 4, 40, 4, 73, 83, 69, 68, + 239, 138, 37, 89, 2, 17, 2, 32, 82, 2, 165, 193, 35, 3, 79, 85, 78, 2, + 133, 135, 21, 4, 69, 68, 32, 68, 6, 26, 65, 195, 241, 34, 66, 4, 193, + 230, 35, 3, 66, 79, 86, 202, 1, 238, 1, 69, 244, 2, 5, 72, 65, 68, 68, + 65, 36, 4, 73, 71, 78, 32, 240, 4, 5, 77, 65, 76, 76, 32, 246, 15, 85, + 244, 2, 6, 89, 77, 66, 79, 76, 32, 209, 178, 35, 18, 84, 65, 82, 84, 32, + 79, 70, 32, 82, 85, 66, 32, 69, 76, 32, 72, 73, 90, 20, 52, 7, 81, 85, + 69, 78, 67, 69, 32, 223, 209, 33, 77, 18, 184, 1, 26, 89, 69, 72, 32, 87, + 73, 84, 72, 32, 72, 65, 77, 90, 65, 32, 65, 66, 79, 86, 69, 32, 87, 73, + 84, 72, 32, 209, 210, 30, 13, 78, 79, 79, 78, 32, 87, 73, 84, 72, 32, 75, + 69, 72, 16, 70, 65, 142, 135, 36, 87, 182, 89, 89, 150, 14, 79, 214, 22, + 69, 3, 85, 6, 36, 3, 76, 69, 70, 131, 133, 37, 69, 5, 159, 13, 32, 7, 11, + 32, 4, 246, 22, 73, 59, 77, 22, 132, 1, 2, 82, 65, 158, 1, 83, 188, 1, 7, + 65, 76, 65, 89, 72, 69, 32, 160, 15, 2, 77, 73, 209, 148, 33, 6, 84, 65, + 75, 72, 65, 76, 4, 132, 1, 13, 72, 77, 65, 84, 85, 76, 76, 65, 72, 32, + 65, 76, 65, 213, 192, 32, 13, 68, 73, 32, 65, 76, 76, 65, 72, 79, 85, 32, + 65, 78, 2, 175, 213, 36, 89, 12, 46, 65, 193, 1, 6, 73, 78, 68, 72, 73, + 32, 8, 136, 1, 18, 76, 76, 65, 76, 76, 65, 72, 79, 85, 32, 65, 76, 65, + 89, 72, 69, 32, 87, 166, 200, 29, 78, 142, 193, 5, 70, 237, 99, 2, 77, + 86, 2, 17, 2, 65, 83, 2, 229, 173, 15, 3, 83, 65, 76, 4, 140, 249, 19, + 12, 80, 79, 83, 84, 80, 79, 83, 73, 84, 73, 79, 78, 233, 205, 13, 2, 65, + 77, 106, 132, 1, 2, 70, 65, 32, 5, 72, 73, 71, 72, 32, 240, 11, 4, 76, + 79, 87, 32, 110, 75, 170, 238, 20, 68, 146, 208, 9, 89, 135, 181, 5, 87, + 4, 190, 3, 82, 219, 131, 35, 84, 74, 236, 2, 17, 68, 79, 84, 76, 69, 83, + 83, 32, 72, 69, 65, 68, 32, 79, 70, 32, 75, 22, 70, 102, 76, 142, 3, 77, + 116, 4, 78, 79, 79, 78, 18, 83, 78, 84, 38, 87, 196, 2, 3, 89, 69, 72, + 228, 128, 14, 18, 85, 80, 82, 73, 71, 72, 84, 32, 82, 69, 67, 84, 65, 78, + 71, 85, 76, 65, 196, 180, 8, 7, 82, 79, 85, 78, 68, 69, 68, 130, 122, 90, + 246, 104, 74, 214, 217, 11, 81, 223, 1, 65, 2, 251, 194, 29, 72, 4, 24, + 2, 65, 82, 31, 79, 2, 11, 83, 2, 175, 2, 73, 2, 181, 220, 25, 6, 79, 84, + 78, 79, 84, 69, 10, 60, 8, 73, 71, 65, 84, 85, 82, 69, 32, 213, 11, 2, + 65, 77, 8, 88, 10, 65, 76, 69, 70, 32, 87, 73, 84, 72, 32, 116, 3, 81, + 65, 70, 1, 3, 83, 65, 68, 4, 84, 8, 76, 65, 77, 32, 87, 73, 84, 72, 153, + 140, 35, 7, 89, 69, 72, 32, 66, 65, 82, 2, 181, 197, 30, 2, 32, 89, 2, + 89, 20, 32, 87, 73, 84, 72, 32, 76, 65, 77, 32, 87, 73, 84, 72, 32, 65, + 76, 69, 70, 32, 2, 225, 193, 21, 3, 77, 65, 75, 6, 26, 69, 215, 201, 15, + 65, 4, 17, 2, 69, 77, 4, 17, 2, 32, 73, 4, 22, 78, 135, 9, 83, 2, 197, 9, + 2, 73, 84, 5, 207, 4, 32, 6, 252, 254, 34, 7, 73, 71, 78, 32, 83, 65, 70, + 202, 38, 69, 227, 138, 1, 65, 4, 194, 243, 22, 72, 159, 129, 14, 65, 20, + 40, 4, 79, 82, 68, 32, 147, 247, 35, 65, 18, 74, 65, 172, 1, 2, 83, 65, + 200, 214, 24, 3, 87, 65, 81, 143, 155, 11, 81, 10, 228, 225, 6, 3, 76, + 45, 74, 236, 253, 17, 3, 82, 45, 82, 132, 196, 6, 7, 84, 72, 45, 84, 72, + 65, 76, 240, 207, 4, 5, 78, 45, 78, 73, 83, 137, 92, 5, 83, 45, 83, 65, + 74, 4, 218, 206, 36, 75, 207, 36, 72, 5, 149, 150, 10, 12, 32, 66, 65, + 82, 82, 69, 69, 32, 87, 73, 84, 72, 20, 68, 5, 78, 79, 79, 78, 32, 70, + 87, 206, 150, 24, 77, 239, 137, 11, 83, 2, 33, 6, 87, 73, 84, 72, 32, 75, + 2, 11, 65, 2, 151, 173, 36, 83, 14, 40, 4, 79, 82, 68, 32, 255, 242, 35, + 65, 12, 106, 73, 198, 194, 15, 77, 204, 135, 9, 3, 84, 65, 83, 212, 192, + 8, 2, 83, 65, 237, 172, 3, 3, 81, 65, 83, 4, 252, 230, 12, 2, 77, 65, + 177, 189, 18, 3, 83, 72, 77, 12, 138, 1, 66, 64, 3, 75, 85, 78, 177, 152, + 24, 22, 80, 69, 82, 83, 67, 82, 73, 80, 84, 32, 65, 76, 69, 70, 32, 77, + 79, 75, 72, 65, 83, 83, 2, 33, 6, 83, 67, 82, 73, 80, 84, 2, 229, 204, + 21, 2, 32, 65, 9, 11, 32, 6, 34, 73, 58, 77, 255, 212, 34, 66, 2, 11, 83, + 2, 141, 239, 35, 6, 79, 76, 65, 84, 69, 68, 2, 11, 69, 2, 11, 68, 2, 11, + 73, 2, 189, 238, 35, 2, 65, 76, 34, 152, 1, 2, 68, 79, 114, 84, 224, 145, + 5, 8, 83, 77, 65, 76, 76, 32, 84, 65, 156, 229, 25, 4, 70, 79, 85, 82, + 228, 124, 4, 87, 65, 83, 76, 147, 166, 4, 82, 6, 88, 16, 85, 66, 76, 69, + 32, 86, 69, 82, 84, 73, 67, 65, 76, 32, 66, 65, 159, 210, 34, 84, 2, 151, + 196, 34, 82, 16, 88, 10, 72, 82, 69, 69, 32, 68, 79, 84, 83, 32, 121, 8, + 87, 79, 32, 68, 79, 84, 83, 32, 8, 184, 246, 30, 17, 80, 79, 73, 78, 84, + 73, 78, 71, 32, 68, 79, 87, 78, 87, 65, 82, 68, 154, 219, 3, 66, 223, + 155, 1, 65, 8, 176, 208, 34, 10, 86, 69, 82, 84, 73, 67, 65, 76, 76, 89, + 42, 66, 223, 155, 1, 65, 30, 202, 1, 65, 152, 2, 4, 79, 78, 69, 32, 244, + 209, 10, 12, 82, 73, 80, 76, 69, 32, 68, 79, 84, 32, 80, 85, 152, 164, 6, + 8, 85, 82, 78, 69, 68, 32, 68, 65, 149, 222, 13, 8, 72, 79, 85, 83, 65, + 78, 68, 83, 12, 68, 5, 84, 87, 69, 69, 76, 157, 180, 9, 6, 73, 76, 32, + 70, 82, 65, 11, 33, 6, 32, 87, 73, 84, 72, 32, 8, 112, 11, 79, 86, 69, + 82, 83, 84, 82, 85, 67, 75, 32, 184, 166, 5, 7, 70, 65, 84, 72, 65, 84, + 65, 131, 226, 4, 84, 4, 26, 72, 223, 230, 35, 87, 2, 197, 254, 28, 2, 65, + 77, 12, 68, 3, 79, 78, 69, 234, 159, 29, 84, 205, 171, 5, 4, 76, 79, 79, + 80, 4, 213, 245, 32, 2, 32, 68, 8, 64, 10, 79, 87, 69, 76, 32, 83, 73, + 71, 78, 32, 243, 178, 23, 69, 6, 72, 10, 73, 78, 86, 69, 82, 84, 69, 68, + 32, 83, 2, 83, 147, 236, 24, 68, 2, 25, 4, 77, 65, 76, 76, 2, 213, 229, + 35, 2, 32, 86, 28, 104, 4, 80, 69, 82, 32, 136, 214, 5, 3, 67, 85, 66, + 208, 128, 5, 5, 70, 79, 85, 82, 84, 211, 156, 24, 68, 4, 250, 182, 24, + 77, 31, 84, 188, 1, 222, 1, 65, 34, 67, 138, 3, 69, 60, 7, 83, 77, 65, + 76, 76, 32, 76, 240, 176, 20, 17, 77, 79, 68, 73, 70, 73, 69, 82, 32, 76, + 69, 84, 84, 69, 82, 32, 76, 222, 225, 8, 72, 184, 168, 2, 3, 68, 82, 65, + 218, 213, 2, 70, 83, 81, 4, 214, 215, 30, 66, 135, 26, 80, 78, 80, 14, + 65, 80, 73, 84, 65, 76, 32, 76, 69, 84, 84, 69, 82, 32, 187, 147, 34, 79, + 76, 250, 1, 84, 36, 2, 89, 73, 150, 3, 67, 38, 82, 34, 69, 42, 71, 34, + 74, 38, 75, 22, 80, 38, 83, 106, 65, 22, 86, 158, 1, 76, 254, 161, 30, + 70, 2, 88, 170, 227, 1, 73, 134, 255, 2, 66, 2, 77, 234, 54, 78, 226, 26, + 90, 186, 96, 72, 190, 28, 68, 171, 1, 79, 4, 178, 139, 35, 73, 163, 209, + 1, 79, 5, 219, 140, 36, 87, 4, 216, 135, 25, 6, 77, 80, 72, 65, 83, 73, + 191, 233, 5, 88, 92, 76, 6, 69, 84, 84, 69, 82, 32, 157, 5, 8, 73, 71, + 65, 84, 85, 82, 69, 32, 80, 242, 1, 67, 38, 82, 34, 69, 42, 71, 34, 74, + 38, 75, 22, 80, 38, 83, 34, 84, 74, 65, 22, 86, 32, 2, 89, 73, 126, 76, + 254, 161, 30, 70, 2, 88, 170, 227, 1, 73, 134, 255, 2, 66, 2, 77, 234, + 54, 78, 226, 26, 90, 186, 96, 72, 190, 28, 68, 171, 1, 79, 8, 34, 72, + 250, 216, 36, 65, 3, 79, 4, 230, 215, 36, 69, 147, 1, 65, 6, 198, 215, + 36, 67, 146, 1, 72, 3, 84, 4, 142, 146, 36, 72, 203, 53, 73, 4, 238, 164, + 30, 72, 163, 179, 6, 65, 4, 207, 225, 32, 69, 4, 166, 217, 3, 73, 163, + 253, 32, 69, 4, 250, 212, 36, 72, 171, 1, 69, 6, 68, 7, 85, 82, 78, 69, + 68, 32, 65, 174, 133, 35, 73, 163, 209, 1, 79, 2, 167, 156, 35, 89, 4, + 166, 216, 35, 69, 147, 126, 79, 7, 222, 216, 20, 32, 231, 173, 15, 87, + 12, 84, 5, 69, 67, 72, 32, 89, 20, 4, 77, 69, 78, 32, 133, 136, 29, 4, + 86, 69, 87, 32, 2, 251, 131, 35, 73, 8, 230, 161, 30, 88, 170, 227, 1, + 73, 238, 181, 3, 78, 231, 119, 69, 14, 116, 10, 32, 80, 79, 73, 78, 84, + 73, 78, 71, 32, 177, 151, 35, 13, 72, 69, 65, 68, 45, 83, 72, 65, 80, 69, + 68, 32, 80, 12, 156, 2, 24, 82, 73, 71, 72, 84, 87, 65, 82, 68, 83, 32, + 84, 72, 69, 78, 32, 67, 85, 82, 86, 73, 78, 71, 32, 48, 16, 85, 80, 87, + 65, 82, 68, 83, 32, 84, 72, 69, 78, 32, 78, 79, 82, 201, 248, 33, 22, 68, + 79, 87, 78, 87, 65, 82, 68, 83, 32, 84, 72, 69, 78, 32, 67, 85, 82, 86, + 73, 78, 71, 6, 44, 3, 83, 79, 85, 210, 239, 25, 68, 35, 85, 2, 173, 173, + 28, 4, 84, 72, 32, 87, 4, 144, 135, 30, 10, 67, 85, 76, 65, 84, 69, 68, + 32, 76, 79, 137, 133, 5, 6, 83, 84, 32, 80, 65, 76, 20, 58, 67, 38, 84, + 146, 200, 22, 89, 241, 156, 9, 2, 83, 69, 4, 222, 141, 8, 69, 175, 128, + 11, 73, 12, 48, 4, 69, 82, 73, 83, 36, 2, 79, 78, 31, 82, 6, 238, 192, 2, + 75, 247, 141, 34, 77, 2, 209, 199, 13, 2, 73, 83, 4, 226, 254, 29, 65, + 189, 204, 4, 22, 79, 78, 79, 77, 73, 67, 65, 76, 32, 83, 89, 77, 66, 79, + 76, 32, 70, 79, 82, 32, 85, 82, 4, 216, 219, 18, 6, 72, 76, 69, 84, 73, + 67, 189, 222, 16, 2, 79, 77, 10, 68, 2, 84, 79, 240, 142, 21, 2, 83, 84, + 185, 162, 2, 3, 66, 69, 82, 6, 54, 77, 201, 205, 35, 7, 32, 82, 73, 67, + 75, 83, 72, 4, 218, 176, 23, 79, 153, 182, 5, 12, 65, 84, 69, 68, 32, 84, + 69, 76, 76, 69, 82, 32, 112, 56, 6, 69, 83, 84, 65, 78, 32, 133, 196, 4, + 2, 79, 67, 110, 52, 7, 76, 69, 84, 84, 69, 82, 32, 167, 194, 30, 65, 108, + 234, 1, 65, 58, 71, 42, 72, 34, 78, 50, 88, 42, 83, 42, 89, 34, 84, 246, + 246, 32, 85, 158, 144, 1, 79, 182, 56, 73, 198, 134, 1, 66, 2, 68, 2, 90, + 246, 63, 69, 194, 41, 67, 2, 70, 2, 74, 2, 75, 2, 76, 2, 77, 2, 80, 2, + 82, 3, 86, 17, 254, 130, 34, 65, 158, 133, 2, 69, 150, 64, 78, 3, 79, 6, + 162, 177, 36, 71, 2, 72, 215, 22, 69, 4, 250, 176, 36, 77, 215, 22, 69, + 12, 46, 71, 174, 176, 36, 78, 2, 89, 215, 22, 69, 6, 170, 176, 36, 86, 2, + 89, 215, 22, 69, 8, 38, 72, 166, 153, 36, 83, 143, 45, 69, 4, 218, 175, + 36, 89, 215, 22, 69, 6, 186, 175, 36, 72, 2, 84, 215, 22, 69, 134, 37, + 178, 1, 65, 182, 169, 1, 69, 132, 16, 9, 72, 65, 73, 75, 83, 85, 75, 73, + 32, 198, 6, 73, 130, 3, 76, 186, 34, 79, 130, 55, 82, 138, 19, 85, 138, + 8, 89, 222, 139, 34, 80, 147, 1, 83, 182, 14, 132, 1, 2, 66, 89, 94, 67, + 206, 2, 68, 146, 1, 71, 106, 76, 140, 28, 4, 77, 85, 77, 32, 230, 114, + 78, 178, 1, 82, 98, 83, 223, 6, 84, 11, 11, 32, 8, 238, 188, 12, 67, 134, + 212, 5, 66, 204, 209, 13, 3, 65, 78, 71, 227, 205, 3, 83, 16, 62, 75, + 172, 223, 8, 5, 84, 82, 73, 65, 78, 139, 147, 27, 79, 12, 42, 32, 46, 83, + 229, 186, 10, 2, 45, 84, 4, 178, 220, 9, 87, 161, 145, 20, 2, 79, 70, 6, + 132, 1, 26, 76, 65, 78, 84, 69, 68, 32, 83, 79, 85, 84, 72, 32, 65, 82, + 82, 79, 87, 32, 87, 73, 84, 72, 32, 72, 79, 175, 131, 36, 80, 4, 150, + 215, 28, 82, 245, 130, 5, 2, 79, 75, 4, 188, 215, 33, 27, 77, 73, 78, 84, + 79, 78, 32, 82, 65, 67, 81, 85, 69, 84, 32, 65, 78, 68, 32, 83, 72, 85, + 84, 84, 76, 69, 67, 223, 170, 2, 71, 6, 228, 247, 29, 6, 85, 69, 84, 84, + 69, 32, 234, 189, 5, 69, 229, 6, 8, 71, 65, 71, 69, 32, 67, 76, 65, 150, + 2, 44, 6, 73, 78, 69, 83, 69, 32, 131, 24, 76, 248, 1, 188, 2, 6, 67, 65, + 82, 73, 75, 32, 104, 7, 76, 69, 84, 84, 69, 82, 32, 224, 8, 15, 77, 85, + 83, 73, 67, 65, 76, 32, 83, 89, 77, 66, 79, 76, 32, 196, 6, 2, 80, 65, + 120, 5, 83, 73, 71, 78, 32, 180, 1, 11, 86, 79, 87, 69, 76, 32, 83, 73, + 71, 78, 32, 192, 246, 13, 5, 65, 68, 69, 71, 32, 162, 204, 18, 87, 219, + 247, 1, 68, 6, 32, 2, 80, 65, 255, 230, 2, 83, 4, 156, 130, 29, 5, 77, + 85, 78, 71, 75, 213, 231, 5, 3, 82, 69, 82, 110, 166, 2, 65, 112, 2, 66, + 65, 32, 2, 67, 65, 32, 2, 68, 65, 110, 69, 32, 2, 71, 65, 30, 73, 2, 79, + 2, 85, 36, 2, 74, 65, 30, 75, 68, 2, 76, 65, 18, 78, 72, 2, 80, 65, 36, + 2, 82, 65, 16, 2, 83, 65, 54, 84, 128, 1, 2, 86, 69, 0, 3, 90, 65, 76, + 170, 175, 36, 72, 2, 77, 2, 87, 3, 89, 10, 226, 2, 75, 184, 3, 5, 83, 89, + 85, 82, 65, 172, 243, 14, 8, 82, 67, 72, 65, 73, 67, 32, 74, 243, 217, 3, + 73, 5, 213, 165, 18, 3, 32, 75, 69, 5, 221, 192, 22, 3, 32, 76, 65, 9, + 17, 2, 32, 77, 6, 44, 5, 85, 82, 68, 65, 32, 175, 208, 32, 65, 4, 166, + 129, 14, 77, 25, 3, 65, 76, 80, 4, 254, 3, 70, 163, 237, 35, 75, 5, 185, + 202, 33, 2, 32, 71, 4, 11, 75, 4, 229, 14, 2, 65, 82, 5, 133, 169, 34, 2, + 32, 74, 8, 34, 65, 225, 2, 3, 72, 79, 84, 7, 222, 2, 70, 247, 252, 13, + 32, 7, 199, 12, 32, 8, 34, 65, 182, 177, 36, 71, 3, 89, 5, 221, 154, 26, + 4, 32, 82, 65, 77, 5, 157, 170, 35, 4, 32, 75, 65, 80, 7, 235, 11, 32, 7, + 21, 3, 32, 83, 65, 4, 194, 176, 36, 71, 3, 80, 10, 30, 65, 97, 3, 90, 73, + 82, 9, 11, 32, 6, 196, 253, 13, 6, 77, 85, 82, 68, 65, 32, 208, 7, 3, 76, + 65, 84, 151, 232, 17, 84, 2, 229, 249, 13, 2, 32, 83, 56, 168, 1, 10, 67, + 79, 77, 66, 73, 78, 73, 78, 71, 32, 246, 1, 68, 172, 1, 10, 76, 69, 70, + 84, 45, 72, 65, 78, 68, 32, 117, 11, 82, 73, 71, 72, 84, 45, 72, 65, 78, + 68, 32, 18, 132, 1, 4, 75, 69, 77, 80, 78, 74, 180, 181, 19, 2, 66, 69, + 136, 159, 7, 3, 69, 78, 68, 232, 166, 3, 3, 84, 69, 71, 195, 246, 3, 71, + 8, 32, 2, 76, 73, 1, 2, 85, 76, 5, 37, 7, 32, 87, 73, 84, 72, 32, 74, 2, + 225, 243, 13, 3, 69, 71, 79, 20, 50, 65, 90, 69, 174, 220, 35, 73, 2, 79, + 3, 85, 10, 40, 2, 78, 71, 218, 220, 35, 69, 3, 73, 7, 11, 32, 4, 158, 4, + 83, 227, 203, 10, 71, 4, 170, 220, 35, 85, 155, 80, 78, 10, 76, 6, 79, + 80, 69, 78, 32, 80, 113, 9, 67, 76, 79, 83, 69, 68, 32, 80, 76, 6, 186, + 219, 35, 65, 2, 73, 3, 85, 8, 72, 8, 67, 76, 79, 83, 69, 68, 32, 84, 29, + 6, 79, 80, 69, 78, 32, 68, 4, 158, 168, 36, 65, 3, 85, 4, 198, 170, 36, + 65, 3, 85, 10, 30, 77, 49, 3, 78, 84, 73, 6, 44, 3, 65, 68, 65, 129, 238, + 33, 2, 69, 78, 5, 233, 209, 35, 5, 32, 76, 65, 78, 84, 12, 110, 83, 20, + 4, 85, 76, 85, 32, 188, 240, 28, 3, 66, 73, 83, 150, 134, 1, 67, 153, + 248, 1, 4, 82, 69, 82, 69, 2, 247, 146, 24, 85, 4, 130, 245, 19, 67, 213, + 161, 16, 3, 82, 73, 67, 30, 120, 3, 76, 65, 32, 32, 3, 82, 65, 32, 12, 4, + 83, 85, 75, 85, 34, 84, 104, 5, 80, 69, 80, 69, 84, 53, 3, 85, 76, 85, 4, + 165, 1, 4, 76, 69, 78, 71, 4, 115, 82, 5, 233, 173, 35, 3, 32, 73, 76, + 10, 36, 5, 65, 76, 73, 78, 71, 99, 69, 9, 11, 32, 6, 18, 82, 55, 84, 4, + 17, 2, 69, 80, 4, 11, 65, 5, 17, 2, 32, 84, 2, 11, 69, 2, 131, 245, 29, + 68, 5, 133, 157, 29, 3, 32, 83, 65, 30, 86, 79, 164, 196, 22, 5, 32, 79, + 70, 32, 89, 245, 204, 12, 6, 69, 84, 32, 83, 72, 79, 26, 32, 2, 79, 78, + 21, 2, 84, 32, 5, 199, 147, 34, 45, 22, 44, 2, 66, 79, 246, 1, 83, 159, + 162, 36, 88, 18, 38, 88, 205, 1, 4, 76, 68, 32, 83, 17, 33, 6, 32, 87, + 73, 84, 72, 32, 14, 82, 66, 86, 83, 140, 167, 12, 4, 76, 73, 71, 72, 210, + 145, 10, 67, 195, 233, 13, 88, 6, 52, 4, 79, 76, 68, 32, 141, 210, 35, 3, + 65, 76, 76, 4, 26, 83, 223, 184, 22, 67, 2, 137, 167, 12, 4, 67, 82, 73, + 80, 162, 10, 120, 2, 67, 79, 180, 1, 7, 76, 69, 84, 84, 69, 82, 32, 248, + 91, 3, 78, 74, 65, 186, 234, 27, 83, 146, 142, 5, 70, 83, 81, 8, 26, 77, + 255, 208, 35, 76, 6, 72, 12, 66, 73, 78, 73, 78, 71, 32, 77, 65, 82, 75, + 32, 219, 157, 36, 77, 4, 168, 137, 21, 6, 84, 85, 75, 87, 69, 78, 241, + 165, 3, 4, 75, 79, 81, 78, 146, 10, 170, 1, 70, 58, 75, 170, 1, 76, 66, + 77, 102, 78, 234, 1, 80, 206, 103, 82, 102, 83, 134, 1, 84, 54, 89, 202, + 193, 2, 87, 166, 215, 32, 69, 214, 22, 65, 2, 73, 2, 79, 3, 85, 8, 226, + 79, 65, 222, 183, 35, 69, 254, 5, 79, 219, 16, 85, 22, 78, 69, 46, 79, + 174, 176, 34, 89, 254, 233, 1, 80, 186, 2, 65, 2, 73, 3, 85, 6, 254, 144, + 35, 85, 142, 140, 1, 78, 3, 84, 7, 218, 173, 34, 86, 161, 222, 1, 2, 71, + 72, 10, 194, 102, 69, 190, 162, 25, 79, 182, 147, 10, 65, 2, 73, 3, 85, + 19, 62, 69, 166, 101, 66, 146, 182, 35, 65, 2, 73, 2, 79, 3, 85, 4, 254, + 174, 34, 69, 183, 236, 1, 78, 30, 102, 71, 50, 74, 50, 84, 150, 101, 85, + 250, 188, 33, 83, 246, 7, 68, 242, 219, 1, 89, 218, 19, 65, 3, 73, 6, + 178, 223, 31, 75, 190, 184, 4, 71, 187, 2, 65, 6, 222, 236, 25, 85, 198, + 150, 10, 69, 171, 4, 65, 4, 222, 244, 35, 85, 151, 14, 69, 254, 8, 76, 5, + 72, 65, 83, 69, 45, 210, 100, 69, 138, 2, 85, 254, 177, 35, 65, 3, 73, + 242, 8, 116, 2, 65, 32, 160, 18, 2, 66, 32, 136, 13, 2, 67, 32, 160, 20, + 2, 68, 32, 172, 18, 2, 69, 32, 137, 25, 2, 70, 32, 174, 1, 158, 1, 71, + 106, 75, 130, 1, 76, 102, 77, 190, 3, 78, 210, 4, 80, 146, 2, 83, 190, 2, + 84, 154, 1, 85, 144, 253, 28, 2, 70, 73, 182, 156, 5, 86, 211, 219, 1, + 82, 6, 60, 5, 72, 69, 85, 65, 69, 173, 46, 5, 66, 73, 69, 69, 32, 4, 168, + 27, 2, 71, 72, 179, 205, 25, 82, 12, 38, 65, 34, 69, 142, 67, 80, 3, 85, + 4, 234, 146, 36, 70, 187, 2, 81, 4, 132, 192, 26, 5, 85, 75, 69, 85, 84, + 255, 212, 9, 84, 10, 78, 85, 222, 65, 79, 224, 190, 25, 2, 65, 80, 129, + 154, 9, 4, 69, 84, 32, 75, 5, 243, 185, 26, 65, 34, 142, 1, 65, 168, 1, + 2, 66, 65, 38, 79, 76, 6, 86, 69, 85, 65, 69, 78, 244, 70, 8, 69, 85, 78, + 74, 79, 77, 78, 68, 157, 152, 33, 2, 71, 66, 18, 62, 69, 164, 49, 2, 78, + 83, 149, 253, 30, 4, 80, 32, 80, 73, 14, 58, 77, 242, 254, 11, 75, 246, + 134, 7, 78, 163, 248, 16, 83, 9, 178, 24, 66, 206, 44, 86, 183, 248, 26, + 75, 4, 182, 133, 19, 78, 251, 139, 17, 81, 6, 36, 2, 79, 77, 237, 1, 2, + 78, 32, 4, 250, 207, 12, 80, 171, 199, 22, 69, 2, 131, 215, 34, 71, 48, + 122, 65, 32, 2, 68, 65, 54, 71, 98, 75, 32, 2, 83, 72, 38, 84, 102, 89, + 74, 90, 210, 210, 34, 74, 234, 105, 69, 239, 70, 73, 4, 250, 8, 65, 183, + 134, 36, 81, 4, 22, 65, 159, 22, 32, 2, 153, 44, 3, 78, 71, 71, 8, 52, 3, + 75, 85, 69, 222, 202, 31, 65, 215, 242, 2, 71, 4, 250, 7, 32, 181, 239, + 11, 2, 78, 90, 4, 246, 25, 65, 147, 253, 18, 73, 4, 166, 161, 34, 73, + 183, 236, 1, 65, 8, 40, 2, 65, 80, 229, 184, 27, 2, 79, 81, 7, 11, 32, 4, + 180, 157, 34, 2, 77, 70, 1, 2, 78, 84, 6, 26, 73, 143, 240, 35, 69, 5, + 193, 13, 7, 84, 32, 77, 79, 78, 71, 75, 4, 214, 5, 65, 245, 243, 11, 4, + 85, 78, 32, 77, 22, 58, 65, 80, 3, 79, 78, 32, 166, 238, 35, 69, 163, 28, + 85, 10, 42, 65, 154, 18, 32, 250, 17, 77, 15, 83, 4, 218, 221, 25, 82, + 155, 173, 10, 77, 8, 56, 4, 77, 70, 79, 78, 1, 6, 80, 65, 32, 78, 74, 73, + 4, 37, 7, 32, 80, 73, 80, 65, 69, 77, 4, 206, 16, 71, 231, 246, 35, 66, + 22, 70, 72, 194, 1, 79, 192, 66, 2, 69, 85, 158, 160, 35, 85, 167, 34, + 73, 10, 74, 73, 70, 85, 129, 224, 34, 10, 79, 81, 32, 78, 83, 72, 85, 84, + 32, 89, 4, 158, 219, 25, 82, 233, 194, 6, 8, 78, 68, 65, 32, 80, 65, 32, + 78, 4, 188, 11, 4, 69, 78, 83, 72, 183, 252, 35, 77, 6, 132, 206, 34, 2, + 78, 74, 190, 185, 1, 81, 3, 84, 10, 44, 2, 69, 85, 44, 3, 73, 84, 65, 31, + 85, 4, 234, 181, 34, 65, 1, 4, 84, 69, 85, 87, 2, 11, 32, 2, 223, 30, 77, + 4, 186, 26, 32, 215, 145, 26, 65, 4, 228, 3, 5, 32, 89, 85, 81, 32, 145, + 130, 27, 3, 78, 75, 78, 112, 164, 1, 7, 71, 72, 69, 85, 71, 72, 69, 34, + 75, 126, 76, 122, 77, 154, 3, 78, 234, 2, 80, 90, 83, 178, 1, 84, 106, + 89, 190, 22, 87, 204, 46, 2, 70, 69, 147, 157, 11, 86, 4, 198, 56, 85, + 203, 203, 35, 78, 12, 40, 2, 69, 85, 50, 73, 191, 242, 35, 65, 6, 230, + 54, 89, 246, 139, 12, 80, 191, 174, 23, 65, 4, 230, 240, 35, 69, 175, 18, + 81, 8, 46, 65, 240, 69, 2, 79, 77, 171, 160, 35, 69, 4, 50, 65, 129, 61, + 7, 77, 32, 78, 83, 72, 85, 84, 2, 247, 212, 25, 78, 26, 70, 65, 74, 66, + 140, 1, 2, 69, 85, 58, 70, 145, 23, 3, 79, 78, 84, 7, 21, 3, 32, 78, 74, + 4, 194, 134, 18, 85, 137, 192, 16, 3, 69, 85, 65, 10, 90, 65, 154, 46, + 85, 144, 201, 28, 2, 69, 85, 173, 182, 6, 7, 73, 84, 32, 77, 66, 65, 65, + 4, 150, 12, 65, 245, 242, 18, 4, 32, 77, 65, 69, 4, 252, 155, 31, 5, 84, + 32, 78, 71, 71, 227, 227, 4, 81, 4, 48, 4, 79, 78, 32, 84, 181, 235, 25, + 2, 73, 89, 2, 163, 65, 69, 24, 110, 71, 166, 1, 83, 50, 89, 152, 23, 8, + 84, 73, 69, 69, 32, 83, 72, 69, 193, 245, 33, 5, 68, 85, 32, 78, 74, 12, + 70, 71, 168, 132, 35, 8, 75, 73, 78, 68, 73, 32, 77, 86, 175, 104, 79, 8, + 60, 3, 85, 79, 81, 216, 133, 19, 2, 69, 85, 219, 189, 15, 65, 5, 137, + 208, 27, 2, 32, 76, 4, 26, 72, 227, 172, 35, 69, 2, 167, 199, 35, 85, 4, + 248, 45, 2, 65, 69, 211, 17, 73, 8, 152, 155, 10, 2, 69, 69, 210, 130, + 12, 65, 160, 146, 8, 3, 85, 78, 71, 199, 175, 5, 73, 12, 88, 2, 65, 75, + 16, 2, 72, 69, 160, 236, 18, 2, 69, 84, 230, 161, 15, 73, 227, 213, 1, + 85, 2, 211, 25, 69, 4, 244, 230, 25, 4, 84, 32, 78, 74, 129, 239, 4, 4, + 85, 65, 69, 81, 6, 32, 2, 85, 32, 151, 192, 34, 65, 4, 36, 4, 77, 65, 69, + 77, 139, 7, 78, 2, 11, 71, 2, 135, 7, 66, 4, 44, 4, 65, 70, 85, 32, 229, + 4, 2, 69, 85, 2, 221, 179, 31, 6, 76, 69, 69, 82, 65, 69, 196, 1, 170, 1, + 71, 82, 75, 206, 2, 76, 50, 77, 250, 3, 78, 238, 6, 80, 78, 83, 118, 84, + 176, 1, 3, 86, 69, 85, 46, 87, 62, 89, 250, 179, 29, 66, 166, 208, 2, 70, + 247, 187, 3, 82, 6, 40, 2, 72, 65, 221, 234, 18, 2, 66, 65, 4, 186, 201, + 25, 82, 155, 173, 10, 80, 22, 66, 69, 182, 1, 85, 248, 224, 25, 3, 80, + 65, 82, 139, 145, 10, 65, 14, 40, 2, 78, 32, 54, 85, 143, 245, 35, 84, 4, + 212, 148, 32, 4, 70, 65, 84, 73, 207, 226, 2, 76, 8, 42, 83, 162, 225, + 25, 75, 195, 147, 10, 77, 4, 232, 14, 3, 72, 69, 85, 239, 53, 69, 4, 48, + 6, 79, 80, 32, 78, 75, 65, 135, 244, 35, 84, 2, 11, 65, 2, 223, 198, 25, + 82, 8, 202, 47, 65, 230, 176, 25, 73, 183, 147, 10, 85, 38, 82, 65, 130, + 1, 66, 202, 196, 25, 85, 216, 25, 4, 71, 66, 65, 83, 143, 167, 8, 73, 8, + 18, 32, 79, 69, 4, 42, 78, 209, 159, 17, 4, 75, 69, 85, 65, 2, 11, 83, 2, + 223, 133, 34, 73, 4, 214, 196, 35, 77, 211, 25, 83, 24, 34, 65, 114, 69, + 82, 73, 35, 85, 6, 32, 2, 65, 32, 163, 229, 18, 78, 4, 204, 219, 30, 8, + 67, 65, 66, 66, 65, 71, 69, 45, 129, 195, 4, 2, 80, 73, 8, 50, 85, 130, + 195, 25, 82, 185, 201, 5, 2, 69, 75, 4, 150, 240, 35, 77, 3, 88, 7, 226, + 7, 82, 155, 232, 35, 84, 4, 174, 221, 35, 65, 175, 18, 69, 72, 130, 1, + 65, 54, 68, 110, 71, 222, 1, 74, 102, 83, 130, 1, 84, 102, 90, 237, 7, + 12, 89, 73, 82, 32, 77, 75, 80, 65, 82, 65, 81, 32, 4, 244, 218, 25, 4, + 78, 83, 65, 78, 195, 147, 10, 81, 12, 60, 2, 69, 85, 174, 41, 65, 146, + 205, 18, 79, 135, 210, 16, 73, 4, 128, 129, 34, 2, 65, 69, 195, 236, 1, + 84, 20, 50, 71, 98, 75, 210, 216, 25, 65, 223, 130, 10, 79, 12, 26, 85, + 247, 156, 35, 69, 11, 180, 39, 3, 65, 69, 78, 190, 245, 34, 79, 202, 26, + 69, 143, 53, 77, 4, 36, 3, 85, 69, 32, 171, 216, 25, 65, 2, 145, 230, 18, + 3, 77, 65, 69, 10, 34, 65, 34, 69, 255, 169, 12, 85, 4, 190, 218, 35, 69, + 219, 16, 77, 4, 194, 254, 33, 69, 171, 96, 85, 12, 78, 85, 202, 214, 25, + 72, 216, 216, 5, 2, 69, 85, 146, 170, 4, 79, 219, 16, 65, 4, 212, 214, + 35, 4, 79, 84, 32, 78, 179, 19, 78, 8, 54, 69, 232, 204, 35, 4, 85, 32, + 77, 66, 131, 26, 65, 4, 204, 225, 18, 2, 85, 78, 211, 135, 17, 78, 4, + 254, 192, 34, 69, 247, 167, 1, 65, 6, 26, 73, 227, 152, 35, 69, 4, 26, + 82, 155, 232, 35, 78, 2, 151, 151, 34, 73, 10, 30, 69, 50, 72, 255, 6, + 85, 4, 26, 84, 191, 219, 34, 85, 2, 231, 151, 35, 70, 4, 182, 166, 12, + 85, 203, 173, 13, 73, 10, 40, 2, 65, 65, 34, 69, 41, 2, 73, 84, 2, 11, + 83, 2, 191, 185, 25, 72, 4, 228, 25, 2, 85, 84, 223, 204, 35, 84, 4, 38, + 85, 153, 133, 32, 3, 65, 32, 89, 2, 235, 139, 26, 65, 4, 180, 145, 27, 2, + 65, 69, 171, 212, 8, 88, 4, 40, 4, 65, 78, 71, 75, 255, 228, 35, 85, 2, + 143, 19, 85, 10, 42, 85, 230, 163, 12, 69, 179, 190, 23, 65, 6, 210, 18, + 87, 212, 3, 4, 32, 77, 85, 79, 167, 206, 35, 77, 234, 1, 134, 1, 70, 68, + 2, 71, 72, 34, 75, 254, 1, 76, 142, 1, 77, 130, 3, 78, 130, 5, 80, 122, + 82, 90, 83, 190, 1, 84, 158, 1, 87, 39, 89, 4, 36, 3, 69, 85, 70, 167, + 224, 35, 65, 2, 11, 69, 2, 151, 2, 85, 4, 202, 1, 69, 191, 222, 35, 65, + 22, 46, 69, 146, 1, 85, 42, 87, 135, 244, 33, 89, 10, 26, 85, 215, 225, + 35, 84, 8, 72, 3, 65, 69, 84, 20, 5, 79, 84, 32, 77, 66, 246, 224, 35, + 77, 3, 80, 2, 251, 205, 11, 77, 2, 219, 179, 25, 85, 9, 134, 208, 35, 79, + 218, 16, 78, 3, 81, 2, 171, 171, 35, 65, 14, 58, 69, 182, 204, 25, 79, + 130, 167, 8, 73, 223, 219, 1, 85, 8, 42, 85, 138, 243, 33, 69, 183, 236, + 1, 84, 4, 178, 133, 26, 65, 139, 218, 9, 77, 41, 94, 65, 58, 66, 66, 69, + 38, 70, 80, 2, 71, 66, 214, 140, 31, 79, 246, 214, 3, 86, 135, 121, 85, + 4, 228, 139, 17, 2, 76, 69, 197, 157, 18, 3, 69, 78, 74, 6, 32, 2, 65, + 65, 235, 190, 35, 85, 5, 237, 130, 28, 2, 32, 83, 6, 250, 226, 17, 85, + 147, 142, 16, 69, 10, 44, 2, 69, 85, 238, 228, 33, 79, 207, 11, 73, 4, + 150, 198, 35, 65, 215, 22, 84, 6, 150, 240, 33, 73, 192, 68, 2, 79, 70, + 223, 39, 69, 72, 78, 68, 46, 71, 226, 1, 74, 98, 83, 110, 84, 34, 89, + 210, 215, 35, 73, 3, 85, 8, 194, 39, 69, 178, 228, 34, 79, 255, 62, 65, + 24, 18, 71, 99, 75, 12, 54, 65, 202, 42, 69, 162, 245, 30, 87, 135, 170, + 4, 85, 6, 152, 38, 2, 65, 77, 183, 180, 35, 80, 12, 68, 2, 69, 85, 174, + 237, 33, 73, 2, 89, 226, 156, 1, 85, 203, 79, 65, 4, 226, 152, 12, 65, + 167, 173, 23, 82, 12, 60, 2, 69, 85, 230, 15, 73, 158, 136, 12, 85, 243, + 192, 23, 65, 4, 206, 198, 35, 65, 175, 18, 84, 10, 46, 72, 32, 3, 73, 69, + 69, 183, 199, 35, 85, 4, 254, 187, 35, 85, 219, 5, 69, 4, 138, 216, 35, + 80, 3, 84, 6, 130, 14, 69, 135, 165, 35, 85, 8, 162, 187, 35, 69, 218, 5, + 85, 254, 5, 65, 219, 16, 73, 12, 42, 69, 46, 85, 182, 214, 35, 65, 3, 73, + 4, 208, 169, 25, 2, 85, 84, 155, 173, 10, 69, 4, 146, 186, 35, 85, 175, + 28, 81, 8, 48, 3, 69, 78, 32, 150, 194, 35, 73, 175, 1, 65, 4, 214, 240, + 25, 79, 227, 194, 9, 77, 26, 58, 72, 90, 85, 186, 16, 65, 174, 6, 69, + 167, 161, 35, 79, 12, 54, 69, 162, 193, 25, 79, 222, 255, 9, 73, 219, 19, + 85, 6, 214, 7, 85, 255, 204, 35, 69, 6, 222, 189, 35, 65, 214, 22, 69, 3, + 85, 18, 62, 69, 74, 85, 210, 191, 25, 79, 226, 252, 9, 65, 215, 22, 73, + 8, 26, 85, 255, 230, 33, 69, 6, 186, 130, 34, 65, 246, 208, 1, 78, 3, 84, + 5, 215, 182, 35, 79, 4, 134, 152, 31, 85, 223, 186, 4, 65, 10, 40, 2, 65, + 69, 18, 85, 191, 130, 35, 69, 2, 251, 3, 77, 6, 22, 87, 227, 13, 79, 2, + 195, 190, 25, 79, 186, 2, 178, 1, 70, 154, 1, 71, 202, 1, 75, 170, 1, 76, + 158, 1, 77, 134, 2, 78, 190, 7, 80, 166, 2, 82, 78, 83, 166, 1, 84, 246, + 1, 86, 66, 87, 34, 89, 226, 186, 35, 65, 2, 73, 3, 79, 18, 54, 85, 218, + 172, 22, 65, 202, 140, 13, 69, 255, 5, 79, 10, 26, 32, 231, 154, 30, 69, + 6, 148, 143, 23, 4, 82, 69, 77, 69, 134, 188, 10, 67, 191, 132, 2, 73, + 16, 24, 2, 66, 69, 39, 72, 4, 234, 194, 34, 85, 143, 140, 1, 84, 12, 34, + 65, 34, 69, 187, 189, 35, 79, 2, 11, 65, 2, 139, 161, 25, 77, 8, 26, 85, + 247, 205, 35, 84, 6, 158, 183, 35, 65, 214, 22, 78, 3, 88, 18, 50, 69, + 62, 80, 18, 85, 206, 204, 35, 73, 3, 79, 6, 26, 85, 255, 204, 35, 84, 4, + 166, 182, 35, 65, 215, 22, 88, 2, 211, 28, 69, 6, 158, 176, 35, 69, 162, + 28, 79, 15, 84, 18, 50, 65, 40, 2, 69, 85, 22, 79, 183, 203, 35, 85, 6, + 150, 187, 35, 65, 218, 16, 80, 3, 81, 2, 155, 185, 35, 65, 8, 238, 208, + 17, 79, 198, 250, 17, 77, 3, 81, 32, 110, 65, 44, 2, 66, 69, 34, 70, 20, + 2, 71, 66, 34, 73, 130, 156, 25, 85, 198, 221, 9, 69, 2, 79, 255, 59, 86, + 11, 234, 164, 17, 69, 174, 165, 18, 80, 3, 81, 4, 146, 185, 35, 85, 219, + 16, 69, 2, 227, 136, 12, 69, 4, 226, 249, 34, 69, 215, 79, 65, 5, 195, + 178, 35, 69, 80, 114, 68, 170, 1, 71, 138, 3, 74, 112, 2, 83, 72, 58, 84, + 32, 3, 89, 73, 32, 54, 90, 210, 129, 35, 65, 179, 47, 75, 12, 34, 65, 98, + 73, 187, 247, 34, 85, 6, 32, 2, 65, 32, 203, 199, 35, 80, 4, 128, 215, + 17, 3, 77, 89, 32, 249, 140, 13, 3, 83, 79, 70, 4, 214, 179, 25, 65, 183, + 147, 10, 81, 36, 78, 71, 50, 85, 122, 75, 118, 79, 188, 177, 11, 3, 69, + 85, 82, 195, 146, 24, 65, 12, 18, 69, 51, 85, 6, 26, 85, 183, 217, 33, + 69, 4, 199, 187, 23, 65, 6, 64, 6, 65, 69, 83, 72, 65, 69, 250, 151, 25, + 82, 155, 173, 10, 80, 2, 11, 32, 2, 203, 231, 22, 78, 12, 34, 65, 20, 2, + 69, 85, 35, 85, 5, 231, 176, 35, 65, 4, 138, 178, 35, 65, 175, 18, 88, 4, + 150, 196, 35, 77, 3, 80, 4, 250, 195, 35, 80, 3, 81, 8, 18, 65, 31, 69, + 2, 201, 244, 30, 2, 69, 77, 6, 26, 69, 139, 183, 34, 85, 5, 233, 160, 35, + 4, 32, 69, 80, 79, 6, 26, 85, 163, 214, 33, 73, 4, 198, 194, 35, 79, 15, + 69, 4, 222, 177, 35, 85, 207, 16, 65, 4, 128, 190, 25, 4, 67, 76, 69, 65, + 247, 240, 1, 66, 4, 174, 174, 25, 65, 3, 85, 34, 42, 65, 90, 69, 58, 73, + 50, 79, 23, 85, 8, 32, 2, 32, 80, 207, 155, 17, 65, 4, 152, 176, 27, 2, + 69, 79, 169, 135, 7, 2, 76, 85, 6, 26, 85, 211, 175, 35, 69, 4, 166, 192, + 35, 84, 3, 88, 7, 11, 69, 4, 202, 172, 25, 69, 183, 147, 10, 84, 5, 135, + 240, 34, 79, 11, 82, 65, 246, 190, 35, 69, 3, 77, 8, 46, 65, 238, 14, 69, + 185, 168, 18, 2, 73, 77, 4, 242, 190, 35, 69, 3, 81, 18, 62, 69, 30, 72, + 150, 131, 31, 85, 146, 170, 4, 79, 163, 14, 65, 4, 150, 190, 35, 69, 3, + 84, 8, 42, 69, 182, 154, 22, 79, 235, 143, 3, 73, 2, 209, 252, 11, 2, 85, + 65, 28, 34, 65, 94, 69, 50, 79, 39, 85, 10, 56, 2, 69, 78, 186, 153, 22, + 65, 158, 163, 13, 77, 3, 81, 2, 221, 165, 11, 3, 32, 78, 84, 6, 26, 85, + 155, 188, 35, 78, 5, 155, 251, 11, 65, 6, 130, 196, 33, 79, 131, 248, 1, + 81, 6, 170, 7, 77, 227, 157, 35, 65, 6, 26, 69, 207, 170, 35, 79, 4, 138, + 142, 25, 85, 155, 173, 10, 69, 6, 246, 10, 69, 255, 203, 31, 85, 26, 68, + 2, 69, 85, 46, 73, 32, 3, 79, 81, 32, 54, 85, 143, 185, 35, 65, 8, 246, + 175, 23, 65, 162, 138, 12, 77, 3, 88, 4, 150, 163, 35, 69, 215, 22, 84, + 4, 248, 150, 12, 4, 83, 87, 73, 77, 223, 162, 9, 67, 8, 226, 165, 25, 69, + 194, 194, 8, 65, 246, 208, 1, 78, 3, 81, 108, 162, 1, 75, 82, 76, 46, 77, + 98, 78, 190, 1, 80, 66, 82, 50, 83, 110, 84, 38, 89, 170, 196, 2, 87, + 252, 172, 9, 2, 86, 85, 170, 170, 23, 69, 242, 5, 70, 231, 16, 85, 14, + 242, 188, 17, 69, 146, 142, 16, 89, 254, 233, 1, 80, 186, 2, 65, 2, 79, + 3, 85, 6, 178, 163, 25, 79, 182, 147, 10, 65, 3, 73, 13, 42, 66, 34, 69, + 242, 181, 35, 65, 3, 79, 4, 186, 230, 34, 69, 159, 77, 65, 2, 187, 201, + 33, 69, 22, 94, 71, 38, 74, 38, 85, 250, 188, 33, 83, 246, 7, 68, 150, 3, + 84, 222, 216, 1, 89, 219, 19, 73, 4, 134, 250, 30, 75, 191, 184, 4, 71, + 4, 190, 135, 25, 85, 239, 154, 10, 65, 5, 223, 157, 35, 65, 6, 26, 69, + 239, 134, 25, 85, 4, 246, 167, 34, 85, 143, 140, 1, 69, 12, 186, 2, 69, + 154, 231, 8, 73, 143, 202, 26, 85, 14, 66, 72, 230, 2, 69, 194, 170, 18, + 65, 226, 224, 16, 85, 235, 36, 73, 6, 146, 159, 35, 73, 218, 19, 79, 3, + 85, 6, 186, 190, 20, 65, 223, 215, 14, 69, 4, 234, 158, 25, 79, 183, 147, + 10, 65, 4, 166, 155, 35, 65, 215, 22, 69, 14, 54, 69, 154, 231, 8, 73, + 186, 179, 26, 65, 215, 22, 85, 6, 150, 165, 34, 85, 142, 140, 1, 69, 3, + 78, 16, 62, 72, 50, 69, 194, 170, 18, 65, 226, 224, 16, 85, 235, 36, 73, + 8, 46, 69, 178, 156, 35, 73, 218, 19, 79, 3, 85, 2, 251, 163, 34, 85, 10, + 174, 181, 17, 69, 190, 134, 3, 65, 139, 244, 14, 73, 6, 138, 156, 25, 79, + 2, 85, 183, 147, 10, 65, 14, 42, 75, 166, 244, 33, 65, 211, 155, 1, 74, + 11, 49, 10, 78, 79, 84, 69, 32, 87, 73, 84, 72, 32, 8, 224, 173, 9, 2, + 80, 79, 190, 1, 89, 188, 131, 12, 2, 69, 85, 147, 156, 6, 68, 6, 38, 32, + 237, 172, 16, 3, 66, 69, 82, 4, 170, 226, 28, 67, 189, 186, 5, 5, 79, 70, + 32, 83, 79, 78, 72, 3, 75, 69, 84, 60, 7, 83, 65, 32, 86, 65, 72, 32, + 183, 167, 33, 69, 5, 241, 218, 15, 10, 66, 65, 76, 76, 32, 65, 78, 68, + 32, 72, 72, 104, 10, 67, 79, 77, 66, 73, 78, 73, 78, 71, 32, 164, 1, 7, + 76, 69, 84, 84, 69, 82, 32, 235, 222, 32, 70, 10, 52, 4, 72, 73, 71, 72, + 44, 3, 76, 79, 87, 39, 77, 4, 172, 140, 21, 2, 45, 76, 251, 207, 10, 32, + 4, 32, 2, 45, 77, 219, 219, 31, 32, 2, 201, 219, 31, 2, 73, 68, 60, 238, + 1, 68, 38, 69, 38, 71, 34, 75, 38, 85, 20, 2, 87, 65, 22, 89, 128, 238, + 27, 2, 72, 87, 154, 196, 2, 77, 178, 181, 2, 79, 154, 154, 2, 86, 246, 5, + 74, 2, 84, 2, 90, 162, 8, 67, 2, 83, 158, 20, 66, 2, 70, 2, 80, 186, 2, + 65, 3, 73, 4, 222, 235, 32, 72, 159, 188, 2, 79, 7, 222, 215, 30, 78, + 251, 207, 4, 69, 4, 202, 130, 35, 66, 219, 35, 65, 4, 202, 238, 27, 80, + 203, 184, 7, 65, 5, 135, 130, 35, 87, 5, 215, 129, 35, 68, 4, 138, 167, + 34, 69, 235, 104, 73, 121, 48, 3, 65, 75, 32, 230, 10, 72, 179, 218, 21, + 84, 112, 196, 1, 15, 67, 79, 78, 83, 79, 78, 65, 78, 84, 32, 83, 73, 71, + 78, 32, 28, 7, 76, 69, 84, 84, 69, 82, 32, 248, 4, 3, 80, 65, 78, 50, 83, + 141, 2, 11, 86, 79, 87, 69, 76, 32, 83, 73, 71, 78, 32, 4, 214, 163, 35, + 78, 87, 72, 76, 194, 1, 77, 114, 78, 68, 2, 80, 65, 38, 83, 232, 144, 18, + 4, 75, 65, 82, 79, 214, 141, 17, 66, 2, 67, 2, 68, 2, 71, 2, 72, 2, 74, + 2, 76, 2, 82, 2, 87, 2, 89, 186, 2, 65, 2, 73, 3, 85, 10, 26, 65, 251, + 159, 35, 66, 9, 45, 9, 78, 68, 65, 73, 76, 73, 78, 71, 32, 6, 198, 159, + 35, 72, 2, 78, 3, 83, 10, 152, 2, 2, 79, 82, 138, 157, 35, 68, 2, 71, 2, + 89, 187, 2, 65, 5, 189, 165, 20, 4, 75, 80, 65, 75, 24, 80, 10, 73, 77, + 65, 76, 85, 78, 71, 85, 78, 32, 96, 2, 79, 85, 195, 159, 35, 65, 20, 230, + 157, 35, 71, 2, 72, 2, 76, 2, 77, 2, 80, 2, 82, 2, 83, 2, 87, 2, 89, 187, + 2, 65, 2, 145, 145, 18, 5, 84, 72, 69, 82, 78, 4, 166, 2, 71, 161, 145, + 18, 4, 79, 78, 71, 79, 10, 96, 12, 89, 77, 66, 79, 76, 32, 66, 73, 78, + 68, 85, 32, 193, 140, 10, 6, 73, 71, 78, 32, 84, 79, 8, 78, 80, 152, 243, + 10, 3, 74, 85, 68, 249, 166, 24, 6, 78, 65, 32, 77, 69, 84, 4, 64, 3, 65, + 78, 71, 133, 199, 22, 7, 73, 78, 65, 82, 66, 79, 82, 2, 139, 131, 25, 79, + 18, 122, 85, 228, 173, 25, 6, 80, 65, 75, 80, 65, 75, 180, 248, 2, 5, 75, + 65, 82, 79, 32, 182, 181, 6, 69, 150, 64, 73, 3, 79, 5, 177, 200, 29, 15, + 32, 70, 79, 82, 32, 83, 73, 77, 65, 76, 85, 78, 71, 85, 78, 5, 143, 134, + 23, 84, 254, 1, 134, 1, 65, 230, 2, 69, 50, 76, 130, 1, 78, 198, 10, 84, + 144, 220, 31, 2, 67, 65, 204, 162, 2, 5, 86, 69, 82, 65, 71, 191, 140, 1, + 68, 20, 136, 1, 4, 77, 69, 68, 32, 170, 1, 82, 164, 143, 3, 10, 67, 72, + 32, 87, 73, 84, 72, 32, 85, 77, 210, 144, 7, 84, 234, 185, 24, 86, 19, + 78, 8, 86, 65, 0, 2, 68, 69, 52, 4, 69, 73, 71, 72, 1, 7, 83, 73, 88, 84, + 69, 69, 78, 2, 201, 214, 19, 8, 83, 67, 69, 78, 68, 73, 78, 71, 2, 193, + 214, 19, 2, 84, 72, 4, 128, 196, 28, 3, 68, 69, 68, 179, 150, 6, 32, 4, + 176, 166, 8, 3, 82, 32, 77, 183, 207, 25, 84, 13, 11, 76, 11, 38, 32, + 217, 187, 24, 3, 72, 79, 80, 6, 162, 140, 12, 80, 212, 232, 15, 6, 87, + 73, 84, 72, 32, 67, 187, 142, 6, 83, 208, 1, 84, 5, 71, 65, 76, 73, 32, + 162, 9, 84, 37, 9, 90, 69, 78, 69, 32, 82, 73, 78, 71, 200, 1, 210, 1, + 65, 44, 9, 67, 85, 82, 82, 69, 78, 67, 89, 32, 148, 2, 7, 76, 69, 84, 84, + 69, 82, 32, 204, 3, 6, 82, 85, 80, 69, 69, 32, 34, 83, 242, 128, 22, 73, + 130, 4, 86, 242, 153, 11, 68, 141, 105, 3, 71, 65, 78, 6, 190, 147, 30, + 85, 138, 149, 1, 66, 51, 78, 12, 120, 10, 78, 85, 77, 69, 82, 65, 84, 79, + 82, 32, 221, 212, 22, 14, 68, 69, 78, 79, 77, 73, 78, 65, 84, 79, 82, 32, + 83, 73, 10, 52, 3, 79, 78, 69, 214, 170, 30, 70, 155, 250, 2, 84, 5, 165, + 201, 28, 19, 32, 76, 69, 83, 83, 32, 84, 72, 65, 78, 32, 84, 72, 69, 32, + 68, 69, 78, 79, 108, 226, 1, 75, 90, 82, 226, 232, 20, 86, 234, 239, 7, + 89, 150, 205, 2, 65, 38, 68, 46, 84, 230, 24, 85, 210, 200, 1, 73, 158, + 190, 1, 78, 46, 83, 82, 66, 2, 67, 2, 71, 2, 74, 2, 80, 254, 68, 72, 2, + 76, 2, 77, 186, 2, 69, 3, 79, 8, 26, 72, 235, 142, 35, 65, 6, 26, 65, + 155, 208, 13, 73, 5, 157, 128, 18, 3, 78, 68, 65, 10, 34, 65, 210, 139, + 35, 72, 3, 82, 7, 33, 6, 32, 87, 73, 84, 72, 32, 4, 244, 179, 24, 5, 76, + 79, 87, 69, 82, 1, 6, 77, 73, 68, 68, 76, 69, 4, 202, 134, 34, 83, 179, + 69, 77, 20, 116, 19, 69, 81, 85, 69, 78, 67, 69, 32, 70, 79, 82, 32, 76, + 69, 84, 84, 69, 82, 32, 154, 154, 25, 65, 187, 138, 6, 73, 6, 150, 131, + 22, 82, 147, 134, 13, 89, 4, 182, 173, 25, 32, 251, 209, 8, 79, 5, 137, + 247, 31, 4, 32, 87, 73, 84, 4, 150, 186, 33, 87, 255, 61, 32, 194, 1, + 180, 2, 7, 76, 69, 84, 84, 69, 82, 32, 244, 1, 7, 78, 85, 77, 66, 69, 82, + 32, 72, 5, 83, 73, 71, 78, 32, 44, 11, 86, 79, 87, 69, 76, 32, 83, 73, + 71, 78, 32, 250, 143, 25, 68, 130, 229, 3, 87, 136, 97, 10, 71, 65, 80, + 32, 70, 73, 76, 76, 69, 82, 153, 229, 4, 12, 72, 85, 78, 68, 82, 69, 68, + 83, 32, 85, 78, 73, 92, 210, 1, 86, 154, 158, 31, 65, 38, 68, 46, 84, + 230, 24, 85, 210, 200, 1, 73, 158, 190, 1, 78, 46, 83, 82, 66, 2, 67, 2, + 71, 2, 74, 2, 75, 2, 80, 254, 68, 72, 2, 76, 2, 77, 2, 82, 2, 89, 186, 2, + 69, 3, 79, 8, 234, 1, 79, 255, 132, 35, 65, 36, 138, 100, 69, 38, 70, 66, + 78, 26, 83, 250, 241, 20, 84, 183, 150, 12, 79, 10, 142, 159, 31, 65, 74, + 67, 171, 163, 3, 86, 24, 84, 2, 86, 79, 166, 160, 31, 65, 190, 21, 85, + 210, 200, 1, 73, 206, 134, 2, 69, 3, 79, 6, 33, 6, 67, 65, 76, 73, 67, + 32, 6, 178, 161, 31, 82, 167, 227, 3, 76, 26, 148, 1, 4, 67, 89, 67, 76, + 36, 2, 71, 32, 28, 2, 76, 76, 46, 82, 66, 84, 212, 216, 18, 4, 79, 72, + 65, 90, 164, 217, 11, 2, 75, 73, 155, 128, 4, 83, 4, 210, 187, 31, 73, + 203, 199, 3, 69, 4, 186, 240, 32, 82, 67, 83, 4, 164, 175, 9, 2, 69, 68, + 219, 251, 22, 73, 4, 176, 188, 31, 7, 84, 72, 68, 65, 89, 32, 67, 255, + 197, 3, 68, 4, 160, 165, 13, 2, 67, 79, 149, 219, 21, 4, 73, 78, 71, 32, + 230, 3, 42, 65, 222, 29, 79, 249, 3, 2, 85, 69, 228, 2, 32, 2, 67, 75, + 135, 159, 17, 78, 226, 2, 22, 32, 143, 28, 45, 210, 2, 214, 1, 67, 254, + 4, 68, 174, 2, 70, 102, 72, 82, 76, 170, 2, 77, 250, 2, 80, 46, 82, 202, + 3, 83, 210, 3, 84, 82, 85, 248, 2, 3, 86, 69, 82, 198, 215, 11, 79, 208, + 240, 19, 3, 66, 79, 87, 154, 227, 1, 78, 179, 1, 81, 98, 196, 1, 5, 73, + 82, 67, 76, 69, 200, 1, 6, 85, 82, 86, 69, 68, 32, 192, 150, 25, 12, 82, + 79, 83, 83, 32, 79, 78, 32, 83, 72, 73, 69, 240, 155, 3, 5, 69, 78, 84, + 82, 69, 178, 238, 4, 72, 203, 13, 76, 11, 11, 32, 8, 72, 5, 87, 73, 84, + 72, 32, 145, 164, 16, 7, 70, 79, 82, 32, 82, 69, 67, 6, 224, 51, 8, 87, + 72, 73, 84, 69, 32, 68, 79, 238, 181, 18, 68, 221, 144, 2, 8, 84, 87, 79, + 32, 87, 72, 73, 84, 16, 84, 4, 68, 79, 87, 78, 0, 2, 85, 80, 56, 3, 76, + 69, 70, 1, 4, 82, 73, 71, 72, 4, 141, 139, 31, 9, 87, 65, 82, 68, 83, 32, + 65, 78, 68, 4, 53, 11, 84, 87, 65, 82, 68, 83, 32, 65, 78, 68, 32, 4, + 178, 164, 10, 85, 179, 237, 21, 68, 30, 64, 6, 73, 65, 77, 79, 78, 68, + 152, 1, 3, 79, 87, 78, 43, 82, 13, 11, 32, 10, 210, 15, 67, 152, 208, 12, + 10, 77, 73, 78, 85, 83, 32, 87, 72, 73, 84, 184, 134, 6, 6, 87, 73, 84, + 72, 32, 68, 242, 212, 14, 79, 131, 11, 83, 12, 142, 16, 32, 62, 45, 175, + 185, 30, 87, 6, 196, 155, 33, 2, 79, 80, 175, 20, 65, 8, 18, 76, 39, 79, + 4, 150, 134, 27, 79, 191, 240, 7, 65, 4, 172, 192, 2, 2, 85, 82, 231, + 146, 30, 76, 12, 38, 69, 146, 179, 33, 65, 239, 2, 79, 6, 216, 180, 33, + 2, 65, 82, 215, 10, 88, 32, 60, 3, 69, 70, 84, 202, 1, 79, 161, 228, 32, + 3, 65, 82, 71, 22, 96, 10, 45, 80, 79, 73, 78, 84, 73, 78, 71, 32, 64, 6, + 87, 65, 82, 68, 83, 32, 155, 183, 33, 32, 12, 162, 6, 68, 246, 7, 73, + 174, 170, 33, 80, 166, 24, 83, 51, 84, 4, 226, 142, 32, 69, 143, 137, 1, + 66, 6, 230, 13, 87, 143, 178, 33, 90, 30, 76, 6, 69, 68, 73, 85, 77, 32, + 197, 145, 21, 7, 79, 79, 78, 32, 76, 73, 76, 28, 66, 68, 42, 76, 36, 4, + 82, 73, 71, 72, 12, 2, 85, 80, 111, 83, 6, 84, 3, 79, 87, 78, 219, 182, + 33, 73, 6, 32, 2, 69, 70, 235, 189, 33, 79, 4, 11, 84, 4, 81, 18, 45, 80, + 79, 73, 78, 84, 73, 78, 71, 32, 84, 82, 73, 65, 78, 71, 76, 69, 5, 217, + 7, 2, 32, 67, 8, 130, 12, 77, 207, 196, 33, 81, 8, 142, 169, 24, 85, 222, + 141, 9, 65, 87, 69, 32, 52, 4, 73, 71, 72, 84, 178, 228, 32, 79, 251, + 105, 69, 28, 100, 10, 45, 80, 79, 73, 78, 84, 73, 78, 71, 32, 244, 1, 6, + 87, 65, 82, 68, 83, 32, 159, 199, 33, 32, 16, 90, 68, 88, 8, 84, 82, 73, + 65, 78, 71, 76, 69, 158, 7, 73, 162, 175, 33, 80, 179, 19, 83, 4, 65, 14, + 79, 85, 66, 76, 69, 32, 84, 82, 73, 65, 78, 71, 76, 69, 5, 247, 146, 12, + 32, 5, 197, 153, 20, 11, 32, 87, 73, 84, 72, 32, 68, 79, 85, 66, 76, 8, + 226, 211, 18, 65, 134, 180, 13, 69, 143, 137, 1, 66, 38, 150, 2, 77, 84, + 5, 81, 85, 65, 82, 69, 172, 156, 25, 3, 85, 78, 32, 196, 223, 1, 5, 75, + 85, 76, 76, 32, 208, 164, 3, 3, 78, 79, 87, 208, 195, 1, 5, 65, 70, 69, + 84, 89, 164, 118, 13, 76, 73, 71, 72, 84, 76, 89, 32, 83, 77, 65, 76, 76, + 146, 90, 67, 50, 72, 226, 1, 80, 143, 17, 84, 10, 40, 4, 65, 76, 76, 32, + 239, 182, 33, 73, 8, 134, 175, 33, 68, 134, 7, 76, 71, 83, 9, 11, 32, 6, + 54, 67, 228, 158, 32, 3, 70, 79, 82, 243, 152, 1, 66, 2, 245, 137, 30, 3, + 69, 78, 84, 14, 180, 4, 3, 73, 78, 89, 134, 221, 22, 82, 226, 221, 10, + 79, 54, 69, 135, 2, 87, 18, 38, 80, 133, 208, 31, 3, 78, 73, 86, 16, 46, + 32, 62, 45, 170, 1, 80, 135, 184, 30, 87, 2, 185, 194, 33, 10, 80, 79, + 73, 78, 84, 73, 78, 71, 32, 66, 8, 45, 9, 80, 79, 73, 78, 84, 73, 78, 71, + 32, 8, 66, 73, 236, 190, 33, 5, 68, 79, 85, 66, 76, 230, 3, 83, 51, 84, + 2, 129, 199, 32, 8, 83, 79, 83, 67, 69, 76, 69, 83, 4, 21, 3, 69, 82, 32, + 4, 190, 222, 23, 76, 143, 232, 8, 82, 10, 56, 6, 84, 73, 67, 65, 76, 32, + 29, 4, 89, 32, 83, 77, 4, 134, 195, 33, 69, 51, 82, 6, 21, 3, 65, 76, 76, + 6, 11, 32, 6, 182, 169, 33, 68, 134, 7, 76, 227, 19, 83, 16, 84, 15, 76, + 69, 84, 84, 69, 82, 32, 67, 65, 80, 73, 84, 65, 76, 32, 155, 234, 10, 70, + 10, 218, 227, 34, 67, 2, 72, 2, 73, 2, 82, 3, 90, 124, 84, 11, 67, 75, + 32, 83, 69, 88, 84, 65, 78, 84, 45, 238, 128, 2, 83, 135, 181, 10, 87, + 120, 62, 49, 214, 1, 50, 46, 51, 38, 52, 42, 53, 199, 223, 34, 54, 61, + 50, 50, 118, 51, 126, 52, 42, 53, 199, 223, 34, 54, 31, 46, 51, 194, 1, + 52, 42, 53, 199, 223, 34, 54, 15, 38, 52, 194, 1, 53, 199, 223, 34, 54, + 7, 130, 225, 34, 53, 3, 54, 15, 122, 52, 190, 248, 27, 53, 179, 231, 6, + 54, 31, 42, 51, 66, 52, 14, 53, 199, 223, 34, 54, 17, 34, 52, 42, 53, + 199, 223, 34, 54, 9, 38, 53, 199, 223, 34, 54, 7, 11, 53, 5, 195, 223, + 34, 54, 6, 178, 207, 21, 32, 241, 166, 8, 4, 66, 69, 82, 82, 144, 4, 200, + 1, 3, 76, 68, 32, 78, 79, 104, 7, 80, 79, 77, 79, 70, 79, 32, 188, 6, 2, + 84, 84, 140, 3, 5, 85, 81, 85, 69, 84, 54, 87, 198, 1, 88, 210, 204, 5, + 77, 194, 153, 3, 89, 218, 177, 25, 65, 255, 33, 78, 14, 246, 169, 8, 83, + 210, 164, 7, 69, 134, 252, 16, 70, 234, 2, 87, 207, 10, 71, 10, 26, 75, + 155, 198, 22, 77, 9, 40, 4, 77, 65, 82, 75, 155, 220, 34, 83, 5, 197, + 224, 22, 3, 32, 84, 65, 150, 1, 96, 13, 70, 73, 78, 65, 76, 32, 76, 69, + 84, 84, 69, 82, 32, 53, 7, 76, 69, 84, 84, 69, 82, 32, 10, 142, 219, 34, + 71, 2, 72, 2, 75, 2, 80, 3, 84, 140, 1, 234, 1, 65, 54, 85, 22, 69, 82, + 71, 46, 73, 70, 78, 38, 79, 98, 90, 226, 138, 7, 75, 162, 215, 23, 67, 2, + 76, 2, 83, 198, 36, 66, 210, 200, 1, 74, 206, 134, 2, 68, 2, 70, 2, 72, + 2, 77, 2, 80, 2, 81, 2, 82, 2, 84, 2, 86, 3, 88, 21, 50, 73, 2, 85, 74, + 78, 242, 215, 34, 72, 3, 77, 5, 227, 136, 34, 78, 17, 50, 78, 242, 215, + 34, 69, 2, 72, 2, 73, 3, 82, 7, 238, 215, 34, 71, 3, 78, 11, 210, 215, + 34, 72, 2, 78, 2, 85, 3, 87, 15, 164, 223, 32, 2, 78, 78, 130, 248, 1, + 72, 2, 77, 2, 82, 3, 85, 9, 206, 222, 32, 71, 151, 248, 1, 78, 17, 66, + 78, 146, 213, 33, 32, 238, 128, 1, 69, 2, 77, 2, 79, 3, 85, 4, 250, 213, + 34, 71, 3, 78, 9, 222, 213, 34, 72, 2, 73, 3, 89, 34, 104, 3, 79, 77, 32, + 197, 238, 20, 17, 76, 69, 32, 87, 73, 84, 72, 32, 80, 79, 80, 80, 73, 78, + 71, 32, 67, 32, 168, 1, 5, 72, 65, 76, 70, 32, 52, 14, 83, 81, 85, 65, + 82, 69, 32, 66, 82, 65, 67, 75, 69, 84, 134, 157, 15, 65, 166, 217, 15, + 67, 134, 2, 80, 126, 76, 22, 82, 175, 1, 84, 8, 226, 247, 30, 66, 46, 76, + 26, 82, 255, 214, 1, 73, 5, 193, 250, 30, 11, 32, 79, 86, 69, 82, 32, 84, + 79, 80, 32, 83, 5, 229, 195, 33, 8, 32, 79, 70, 32, 70, 76, 79, 87, 14, + 58, 76, 116, 3, 84, 73, 69, 181, 252, 31, 3, 32, 65, 78, 6, 26, 32, 187, + 128, 34, 73, 4, 160, 158, 9, 7, 79, 70, 32, 72, 89, 71, 73, 197, 161, 22, + 6, 87, 73, 84, 72, 32, 83, 7, 235, 196, 31, 32, 162, 2, 88, 10, 32, 68, + 82, 65, 87, 73, 78, 71, 83, 32, 137, 211, 33, 6, 73, 78, 71, 32, 71, 76, + 160, 2, 176, 1, 2, 68, 79, 148, 4, 6, 72, 69, 65, 86, 89, 32, 194, 2, 76, + 156, 17, 6, 82, 73, 71, 72, 84, 32, 144, 4, 3, 85, 80, 32, 245, 3, 9, 86, + 69, 82, 84, 73, 67, 65, 76, 32, 58, 48, 5, 85, 66, 76, 69, 32, 89, 3, 87, + 78, 32, 22, 68, 4, 68, 79, 87, 78, 0, 2, 85, 80, 250, 21, 86, 155, 177, + 28, 72, 6, 171, 22, 32, 36, 128, 1, 10, 72, 69, 65, 86, 89, 32, 65, 78, + 68, 32, 132, 1, 10, 76, 73, 71, 72, 84, 32, 65, 78, 68, 32, 230, 29, 68, + 131, 4, 83, 12, 76, 3, 76, 69, 70, 0, 4, 82, 73, 71, 72, 248, 26, 2, 85, + 80, 151, 5, 72, 4, 17, 2, 84, 32, 4, 250, 23, 85, 227, 136, 34, 76, 12, + 76, 3, 76, 69, 70, 0, 4, 82, 73, 71, 72, 176, 27, 2, 85, 80, 235, 4, 72, + 4, 17, 2, 84, 32, 4, 218, 23, 85, 135, 9, 72, 46, 120, 4, 76, 69, 70, 84, + 68, 2, 85, 80, 176, 14, 2, 68, 79, 106, 81, 34, 84, 234, 1, 86, 154, 177, + 28, 72, 199, 219, 5, 82, 5, 45, 9, 32, 65, 78, 68, 32, 76, 73, 71, 72, 2, + 207, 250, 32, 84, 11, 29, 5, 32, 65, 78, 68, 32, 8, 42, 76, 238, 193, 28, + 72, 199, 219, 5, 82, 4, 204, 223, 23, 4, 73, 71, 72, 84, 211, 189, 10, + 69, 108, 56, 4, 69, 70, 84, 32, 169, 2, 5, 73, 71, 72, 84, 32, 16, 244, + 18, 19, 68, 79, 87, 78, 32, 72, 69, 65, 86, 89, 32, 65, 78, 68, 32, 82, + 73, 71, 72, 24, 14, 72, 69, 65, 86, 89, 32, 65, 78, 68, 32, 82, 73, 71, + 72, 100, 14, 76, 73, 71, 72, 84, 32, 65, 78, 68, 32, 82, 73, 71, 72, 97, + 17, 85, 80, 32, 72, 69, 65, 86, 89, 32, 65, 78, 68, 32, 82, 73, 71, 72, + 92, 172, 1, 4, 65, 82, 67, 32, 30, 68, 172, 9, 4, 76, 69, 70, 84, 62, 81, + 34, 84, 112, 2, 85, 80, 122, 86, 176, 134, 34, 10, 72, 79, 82, 73, 90, + 79, 78, 84, 65, 76, 175, 6, 82, 8, 158, 143, 17, 68, 67, 85, 48, 52, 8, + 73, 65, 71, 79, 78, 65, 76, 32, 203, 8, 79, 36, 100, 7, 77, 73, 68, 68, + 76, 69, 32, 216, 2, 6, 85, 80, 80, 69, 82, 32, 194, 129, 33, 67, 191, 2, + 68, 12, 88, 8, 76, 69, 70, 84, 32, 84, 79, 32, 161, 1, 9, 82, 73, 71, 72, + 84, 32, 84, 79, 32, 8, 136, 1, 28, 85, 80, 80, 69, 82, 32, 67, 69, 78, + 84, 82, 69, 32, 84, 79, 32, 77, 73, 68, 68, 76, 69, 32, 82, 73, 71, 72, + 84, 195, 3, 76, 5, 143, 132, 20, 32, 4, 232, 4, 15, 85, 80, 80, 69, 82, + 32, 67, 69, 78, 84, 82, 69, 32, 84, 79, 175, 255, 19, 76, 20, 196, 1, 17, + 67, 69, 78, 84, 82, 69, 32, 84, 79, 32, 77, 73, 68, 68, 76, 69, 32, 228, + 239, 22, 7, 76, 69, 70, 84, 32, 84, 79, 193, 155, 11, 14, 82, 73, 71, 72, + 84, 32, 84, 79, 32, 76, 79, 87, 69, 82, 16, 56, 4, 76, 69, 70, 84, 165, + 1, 5, 82, 73, 71, 72, 84, 9, 11, 32, 6, 60, 4, 84, 79, 32, 76, 137, 128, + 20, 5, 65, 78, 68, 32, 77, 4, 53, 11, 79, 87, 69, 82, 32, 67, 69, 78, 84, + 82, 69, 5, 169, 198, 31, 3, 32, 84, 79, 9, 11, 32, 6, 88, 3, 65, 78, 68, + 65, 15, 84, 79, 32, 76, 79, 87, 69, 82, 32, 67, 69, 78, 84, 82, 69, 2, + 249, 254, 19, 11, 32, 77, 73, 68, 68, 76, 69, 32, 76, 69, 70, 5, 165, + 187, 10, 9, 32, 84, 79, 32, 77, 73, 68, 68, 76, 12, 164, 1, 2, 85, 66, + 241, 1, 2, 87, 78, 5, 221, 235, 32, 10, 32, 65, 78, 68, 32, 72, 69, 65, + 86, 89, 4, 49, 5, 85, 65, 68, 82, 85, 4, 17, 2, 82, 73, 4, 11, 80, 4, 41, + 8, 76, 69, 32, 68, 65, 83, 72, 32, 4, 230, 130, 16, 86, 207, 175, 12, 72, + 11, 29, 5, 32, 65, 78, 68, 32, 8, 34, 72, 246, 140, 34, 76, 31, 82, 4, + 172, 207, 23, 4, 69, 65, 86, 89, 171, 226, 4, 79, 8, 37, 7, 69, 82, 84, + 73, 67, 65, 76, 9, 11, 32, 6, 25, 4, 65, 78, 68, 32, 6, 198, 176, 28, 72, + 170, 219, 5, 76, 31, 82, 16, 148, 2, 18, 68, 79, 87, 78, 32, 72, 69, 65, + 86, 89, 32, 65, 78, 68, 32, 76, 69, 70, 24, 13, 72, 69, 65, 86, 89, 32, + 65, 78, 68, 32, 76, 69, 70, 100, 13, 76, 73, 71, 72, 84, 32, 65, 78, 68, + 32, 76, 69, 70, 97, 16, 85, 80, 32, 72, 69, 65, 86, 89, 32, 65, 78, 68, + 32, 76, 69, 70, 2, 101, 3, 84, 32, 85, 6, 17, 2, 84, 32, 6, 58, 85, 178, + 3, 68, 245, 4, 6, 86, 69, 82, 84, 73, 67, 2, 227, 157, 32, 80, 6, 17, 2, + 84, 32, 6, 58, 85, 134, 4, 68, 205, 4, 6, 86, 69, 82, 84, 73, 67, 2, 239, + 8, 80, 2, 185, 2, 3, 84, 32, 68, 36, 128, 1, 10, 72, 69, 65, 86, 89, 32, + 65, 78, 68, 32, 188, 1, 10, 76, 73, 71, 72, 84, 32, 65, 78, 68, 32, 186, + 2, 68, 131, 4, 83, 12, 80, 4, 68, 79, 87, 78, 24, 3, 76, 69, 70, 0, 4, + 82, 73, 71, 72, 255, 4, 72, 2, 145, 5, 2, 32, 72, 4, 17, 2, 84, 32, 4, + 26, 68, 179, 133, 34, 76, 2, 177, 154, 32, 3, 79, 87, 78, 12, 80, 4, 68, + 79, 87, 78, 24, 3, 76, 69, 70, 0, 4, 82, 73, 71, 72, 211, 4, 72, 2, 229, + 4, 2, 32, 72, 4, 17, 2, 84, 32, 4, 22, 68, 131, 5, 72, 2, 233, 4, 3, 79, + 87, 78, 24, 130, 1, 68, 188, 1, 10, 72, 69, 65, 86, 89, 32, 65, 78, 68, + 32, 144, 1, 10, 76, 73, 71, 72, 84, 32, 65, 78, 68, 32, 183, 1, 83, 6, + 49, 10, 79, 85, 66, 76, 69, 32, 65, 78, 68, 32, 6, 92, 3, 76, 69, 70, 0, + 4, 82, 73, 71, 72, 13, 10, 72, 79, 82, 73, 90, 79, 78, 84, 65, 76, 2, 11, + 84, 2, 189, 157, 26, 2, 32, 83, 6, 54, 72, 68, 3, 76, 69, 70, 1, 4, 82, + 73, 71, 72, 2, 37, 7, 79, 82, 73, 90, 79, 78, 84, 2, 189, 149, 32, 2, 65, + 76, 2, 163, 149, 32, 84, 6, 54, 72, 60, 3, 76, 69, 70, 1, 4, 82, 73, 71, + 72, 2, 37, 7, 79, 82, 73, 90, 79, 78, 84, 2, 29, 2, 65, 76, 2, 11, 84, 2, + 17, 2, 32, 72, 2, 253, 151, 34, 3, 69, 65, 86, 6, 49, 10, 73, 78, 71, 76, + 69, 32, 65, 78, 68, 32, 6, 96, 3, 76, 69, 70, 0, 4, 82, 73, 71, 72, 165, + 225, 25, 9, 72, 79, 82, 73, 90, 79, 78, 84, 65, 2, 175, 225, 25, 84, 134, + 6, 46, 65, 186, 14, 69, 150, 1, 73, 191, 1, 79, 232, 5, 36, 4, 72, 77, + 73, 32, 255, 9, 73, 230, 1, 192, 1, 7, 76, 69, 84, 84, 69, 82, 32, 196, + 2, 7, 78, 85, 77, 66, 69, 82, 32, 144, 2, 12, 80, 85, 78, 67, 84, 85, 65, + 84, 73, 79, 78, 32, 84, 5, 83, 73, 71, 78, 32, 126, 86, 215, 169, 24, 68, + 108, 210, 1, 79, 178, 187, 30, 65, 38, 68, 46, 84, 46, 86, 186, 24, 85, + 210, 200, 1, 73, 42, 76, 246, 189, 1, 78, 46, 83, 82, 66, 2, 67, 2, 71, + 2, 74, 2, 75, 2, 80, 254, 68, 72, 2, 77, 2, 82, 2, 89, 187, 2, 69, 15, + 45, 9, 76, 68, 32, 84, 65, 77, 73, 76, 32, 12, 226, 165, 28, 76, 186, + 153, 2, 83, 190, 66, 78, 199, 221, 2, 82, 42, 82, 69, 38, 70, 66, 78, 26, + 83, 250, 241, 20, 84, 174, 213, 5, 79, 155, 156, 7, 74, 4, 193, 175, 30, + 4, 73, 71, 72, 84, 8, 26, 79, 135, 218, 20, 73, 4, 134, 184, 32, 82, 167, + 177, 1, 85, 4, 65, 3, 73, 78, 69, 8, 40, 4, 69, 86, 69, 78, 1, 2, 73, 88, + 5, 203, 143, 34, 84, 10, 46, 76, 170, 188, 12, 68, 169, 16, 2, 67, 82, 4, + 178, 138, 19, 79, 139, 253, 13, 73, 12, 204, 155, 16, 9, 79, 76, 68, 32, + 84, 65, 77, 73, 76, 182, 158, 14, 67, 198, 180, 1, 74, 158, 2, 86, 122, + 85, 231, 233, 1, 65, 34, 64, 10, 79, 87, 69, 76, 32, 83, 73, 71, 78, 32, + 247, 236, 31, 73, 32, 142, 1, 79, 140, 213, 28, 11, 66, 72, 65, 84, 84, + 73, 80, 82, 79, 76, 85, 250, 227, 1, 65, 106, 86, 214, 20, 85, 210, 200, + 1, 73, 207, 134, 2, 69, 7, 165, 185, 30, 10, 76, 68, 32, 84, 65, 77, 73, + 76, 32, 83, 130, 4, 72, 12, 76, 76, 69, 32, 80, 65, 84, 84, 69, 82, 78, + 32, 211, 156, 34, 78, 128, 4, 44, 5, 68, 79, 84, 83, 45, 215, 243, 6, 66, + 254, 3, 74, 49, 74, 50, 66, 51, 54, 52, 46, 53, 38, 54, 30, 55, 167, 153, + 34, 56, 129, 2, 66, 50, 66, 51, 54, 52, 46, 53, 38, 54, 30, 55, 167, 153, + 34, 56, 129, 1, 58, 51, 54, 52, 46, 53, 38, 54, 30, 55, 167, 153, 34, 56, + 65, 50, 52, 46, 53, 38, 54, 30, 55, 167, 153, 34, 56, 33, 42, 53, 38, 54, + 30, 55, 167, 153, 34, 56, 17, 34, 54, 30, 55, 167, 153, 34, 56, 9, 26, + 55, 167, 153, 34, 56, 5, 163, 153, 34, 56, 8, 26, 65, 163, 130, 34, 86, + 6, 212, 131, 20, 11, 75, 32, 80, 69, 82, 77, 73, 84, 84, 69, 68, 196, + 135, 8, 6, 83, 84, 45, 70, 69, 69, 219, 141, 6, 68, 10, 42, 68, 108, 2, + 69, 70, 207, 147, 34, 67, 4, 84, 6, 71, 69, 32, 65, 84, 32, 133, 234, 31, + 9, 69, 32, 87, 73, 84, 72, 32, 86, 69, 2, 167, 236, 33, 78, 4, 190, 134, + 31, 67, 167, 144, 3, 83, 12, 84, 4, 75, 69, 78, 32, 232, 177, 8, 2, 67, + 67, 220, 220, 24, 2, 87, 78, 207, 118, 79, 6, 140, 227, 26, 17, 67, 73, + 82, 67, 76, 69, 32, 87, 73, 84, 72, 32, 78, 79, 82, 84, 72, 178, 144, 6, + 66, 155, 27, 72, 134, 1, 208, 1, 4, 66, 66, 76, 69, 46, 71, 156, 4, 4, + 72, 73, 68, 32, 36, 2, 76, 76, 122, 83, 56, 4, 84, 84, 69, 82, 220, 230, + 10, 10, 73, 76, 68, 73, 78, 71, 32, 67, 79, 78, 208, 154, 16, 2, 82, 82, + 155, 185, 6, 67, 4, 216, 195, 27, 2, 32, 84, 195, 207, 6, 83, 63, 33, 6, + 73, 78, 69, 83, 69, 32, 60, 144, 1, 7, 76, 69, 84, 84, 69, 82, 32, 172, + 2, 11, 86, 79, 87, 69, 76, 32, 83, 73, 71, 78, 32, 154, 252, 15, 69, 237, + 205, 13, 4, 80, 65, 76, 76, 46, 154, 1, 77, 34, 78, 198, 141, 34, 66, 2, + 67, 2, 68, 2, 71, 2, 72, 2, 74, 2, 75, 2, 76, 2, 80, 2, 82, 2, 83, 2, 84, + 2, 86, 2, 89, 187, 2, 65, 4, 226, 141, 34, 80, 187, 2, 65, 12, 46, 71, + 34, 89, 246, 140, 34, 82, 187, 2, 65, 4, 146, 141, 34, 75, 187, 2, 65, 4, + 242, 140, 34, 67, 187, 2, 65, 10, 182, 248, 33, 65, 214, 22, 69, 2, 73, + 2, 79, 3, 85, 40, 134, 134, 10, 76, 183, 169, 18, 86, 10, 56, 2, 69, 84, + 20, 4, 72, 79, 82, 78, 151, 149, 9, 83, 5, 211, 227, 30, 32, 5, 221, 237, + 26, 5, 32, 87, 73, 84, 72, 9, 26, 84, 203, 194, 31, 32, 4, 214, 237, 26, + 83, 15, 32, 5, 207, 233, 33, 70, 240, 3, 140, 1, 23, 90, 65, 78, 84, 73, + 78, 69, 32, 77, 85, 83, 73, 67, 65, 76, 32, 83, 89, 77, 66, 79, 76, 32, + 173, 254, 19, 5, 84, 69, 32, 79, 82, 238, 3, 154, 2, 65, 128, 7, 2, 67, + 72, 170, 1, 68, 158, 5, 69, 206, 2, 70, 166, 8, 71, 202, 3, 73, 162, 2, + 75, 142, 5, 76, 190, 2, 77, 250, 4, 79, 114, 80, 174, 4, 82, 42, 83, 194, + 5, 84, 196, 5, 2, 86, 65, 250, 1, 89, 238, 162, 31, 78, 149, 136, 2, 9, + 88, 73, 82, 79, 78, 32, 75, 76, 65, 62, 60, 5, 71, 79, 71, 73, 32, 222, + 1, 78, 118, 80, 199, 2, 82, 16, 70, 65, 0, 2, 71, 79, 64, 2, 77, 69, 37, + 5, 80, 79, 76, 73, 32, 4, 17, 2, 82, 71, 4, 200, 181, 15, 2, 79, 84, 211, + 210, 18, 73, 4, 134, 138, 9, 84, 147, 234, 24, 83, 4, 26, 65, 1, 2, 71, + 79, 2, 223, 150, 17, 82, 6, 72, 6, 84, 73, 75, 69, 78, 79, 169, 229, 33, + 6, 65, 84, 82, 73, 67, 72, 4, 168, 32, 2, 75, 89, 239, 227, 33, 77, 22, + 52, 5, 69, 83, 79, 32, 69, 38, 79, 247, 241, 33, 76, 4, 204, 1, 2, 88, + 79, 147, 55, 75, 16, 80, 6, 83, 84, 82, 79, 70, 79, 188, 40, 3, 68, 69, + 82, 181, 128, 1, 2, 84, 72, 10, 24, 2, 73, 32, 79, 83, 4, 56, 9, 83, 89, + 78, 68, 69, 83, 77, 79, 83, 195, 24, 84, 2, 143, 44, 32, 7, 11, 32, 4, + 214, 60, 68, 251, 213, 21, 78, 18, 48, 2, 71, 79, 33, 6, 75, 84, 73, 75, + 79, 32, 4, 170, 21, 83, 135, 238, 33, 78, 14, 194, 242, 26, 86, 218, 241, + 6, 90, 162, 8, 75, 254, 2, 68, 2, 78, 162, 17, 71, 3, 80, 14, 80, 4, 82, + 79, 65, 32, 168, 37, 4, 79, 82, 69, 86, 221, 2, 4, 65, 77, 73, 76, 6, + 204, 161, 19, 2, 83, 80, 152, 184, 3, 3, 90, 89, 71, 161, 246, 9, 3, 75, + 76, 73, 42, 50, 73, 220, 205, 8, 2, 65, 83, 143, 148, 25, 89, 38, 122, + 65, 200, 1, 5, 69, 83, 73, 83, 32, 70, 71, 208, 1, 3, 80, 76, 73, 185, + 235, 26, 8, 70, 84, 79, 71, 71, 79, 83, 32, 10, 48, 6, 83, 84, 79, 76, + 73, 32, 187, 200, 32, 82, 8, 80, 6, 65, 80, 76, 73, 32, 77, 174, 55, 68, + 177, 159, 22, 5, 84, 72, 69, 83, 69, 4, 40, 2, 69, 71, 197, 245, 26, 2, + 73, 75, 2, 171, 175, 29, 65, 12, 38, 84, 246, 50, 65, 42, 68, 63, 77, 6, + 194, 10, 69, 239, 41, 82, 10, 72, 5, 79, 82, 71, 79, 78, 181, 252, 33, 7, + 82, 65, 77, 77, 65, 32, 71, 9, 69, 15, 32, 80, 65, 82, 69, 83, 84, 73, + 71, 77, 69, 78, 79, 78, 32, 6, 222, 38, 68, 137, 10, 8, 65, 82, 73, 83, + 84, 69, 82, 65, 5, 175, 47, 32, 16, 166, 1, 78, 116, 6, 84, 69, 82, 79, + 78, 32, 188, 44, 4, 88, 79, 32, 69, 252, 236, 31, 4, 80, 69, 71, 69, 196, + 46, 6, 75, 83, 84, 82, 69, 80, 209, 13, 3, 76, 65, 70, 4, 224, 22, 3, 68, + 79, 70, 157, 211, 26, 18, 65, 82, 88, 73, 83, 32, 75, 65, 73, 32, 70, 84, + 72, 79, 82, 65, 32, 86, 4, 208, 11, 5, 65, 82, 71, 79, 83, 151, 20, 80, + 44, 180, 1, 9, 65, 78, 69, 82, 79, 83, 73, 83, 32, 52, 6, 84, 72, 79, 82, + 65, 32, 165, 6, 22, 72, 84, 79, 82, 65, 32, 83, 75, 76, 73, 82, 79, 78, + 32, 67, 72, 82, 79, 77, 65, 32, 86, 6, 246, 4, 68, 14, 77, 25, 5, 84, 69, + 84, 82, 65, 36, 220, 2, 8, 65, 82, 67, 72, 65, 73, 79, 78, 80, 10, 68, + 73, 65, 84, 79, 78, 73, 75, 73, 32, 96, 11, 73, 32, 89, 70, 69, 83, 73, + 83, 32, 84, 69, 32, 15, 77, 65, 76, 65, 75, 79, 78, 32, 67, 72, 82, 79, + 77, 65, 32, 74, 78, 40, 8, 83, 75, 76, 73, 82, 79, 78, 32, 133, 157, 18, + 18, 69, 78, 65, 82, 77, 79, 78, 73, 79, 83, 32, 65, 78, 84, 73, 70, 79, + 78, 5, 57, 12, 32, 68, 69, 89, 84, 69, 82, 79, 85, 32, 73, 67, 2, 211, + 227, 26, 72, 14, 62, 78, 218, 212, 33, 90, 162, 8, 75, 254, 2, 68, 163, + 17, 80, 6, 242, 39, 73, 151, 145, 32, 65, 2, 237, 42, 4, 84, 65, 82, 84, + 4, 18, 68, 15, 77, 2, 35, 73, 2, 21, 3, 79, 78, 79, 2, 151, 19, 70, 4, + 166, 19, 65, 193, 218, 31, 2, 69, 78, 6, 84, 7, 67, 72, 82, 79, 77, 65, + 32, 205, 225, 16, 8, 68, 73, 65, 84, 79, 78, 79, 78, 4, 42, 86, 181, 229, + 16, 4, 83, 89, 78, 65, 2, 159, 212, 31, 65, 22, 80, 6, 69, 78, 73, 75, + 73, 32, 44, 2, 79, 82, 185, 26, 5, 82, 79, 78, 84, 72, 4, 140, 150, 30, + 2, 68, 73, 1, 2, 89, 70, 16, 68, 2, 71, 79, 225, 1, 10, 84, 72, 77, 73, + 75, 79, 78, 32, 78, 32, 12, 28, 2, 78, 32, 155, 1, 83, 10, 96, 14, 80, + 65, 82, 69, 83, 84, 73, 71, 77, 69, 78, 79, 78, 32, 242, 33, 65, 113, 3, + 78, 69, 79, 4, 214, 24, 68, 233, 201, 31, 5, 65, 82, 73, 83, 84, 2, 165, + 188, 32, 5, 89, 78, 84, 72, 69, 4, 142, 28, 65, 1, 2, 68, 73, 16, 56, 2, + 77, 73, 114, 83, 213, 236, 32, 4, 67, 72, 65, 68, 8, 34, 70, 169, 28, 3, + 68, 73, 65, 6, 40, 4, 84, 72, 79, 82, 183, 226, 32, 79, 4, 218, 156, 33, + 79, 215, 79, 65, 6, 44, 6, 65, 75, 73, 65, 32, 84, 231, 13, 79, 2, 145, + 141, 21, 12, 69, 76, 79, 85, 83, 32, 73, 67, 72, 73, 77, 65, 54, 108, 2, + 65, 84, 96, 6, 69, 78, 84, 73, 77, 65, 140, 1, 5, 76, 65, 83, 77, 65, 18, + 79, 98, 82, 175, 1, 89, 6, 40, 3, 65, 86, 65, 201, 3, 2, 72, 73, 4, 140, + 29, 5, 32, 84, 82, 79, 77, 227, 171, 33, 83, 18, 24, 2, 84, 65, 15, 32, + 11, 11, 32, 8, 36, 4, 78, 69, 79, 32, 183, 28, 65, 6, 220, 144, 25, 2, + 77, 69, 166, 247, 4, 75, 235, 183, 3, 65, 7, 243, 28, 32, 8, 64, 6, 78, + 84, 69, 86, 77, 65, 250, 198, 8, 82, 195, 255, 24, 85, 5, 165, 254, 13, + 2, 32, 65, 14, 44, 4, 65, 84, 73, 77, 105, 3, 69, 77, 65, 12, 18, 65, 35, + 79, 8, 182, 23, 32, 159, 205, 33, 84, 4, 134, 12, 75, 181, 201, 30, 5, + 89, 80, 79, 82, 82, 2, 187, 194, 26, 83, 2, 251, 196, 33, 76, 14, 22, 69, + 147, 22, 89, 12, 44, 5, 73, 77, 77, 65, 32, 167, 163, 29, 77, 10, 72, 2, + 69, 78, 0, 5, 73, 77, 73, 83, 69, 54, 84, 69, 3, 68, 89, 79, 2, 173, 212, + 26, 8, 79, 83, 32, 67, 72, 82, 79, 78, 4, 44, 5, 69, 83, 83, 65, 82, 1, + 2, 82, 73, 2, 17, 2, 79, 78, 2, 25, 4, 32, 67, 72, 82, 2, 235, 217, 32, + 79, 28, 84, 8, 65, 82, 84, 89, 82, 73, 65, 32, 241, 143, 27, 7, 73, 75, + 82, 79, 78, 32, 73, 26, 72, 5, 65, 76, 76, 73, 32, 38, 68, 38, 80, 134, + 1, 86, 30, 84, 87, 76, 4, 34, 68, 177, 2, 3, 80, 82, 79, 2, 237, 2, 5, + 69, 89, 84, 69, 82, 8, 60, 7, 76, 65, 71, 73, 79, 83, 32, 45, 4, 82, 79, + 84, 79, 4, 200, 1, 5, 84, 69, 84, 65, 82, 111, 73, 4, 22, 86, 227, 1, 83, + 2, 209, 1, 3, 65, 82, 89, 8, 56, 8, 69, 84, 65, 82, 84, 79, 83, 32, 61, + 2, 82, 73, 4, 22, 76, 135, 1, 73, 2, 21, 3, 69, 71, 69, 2, 63, 84, 4, 18, + 70, 35, 84, 2, 205, 137, 21, 3, 79, 78, 73, 2, 11, 79, 2, 11, 83, 2, 17, + 2, 32, 73, 2, 195, 178, 22, 67, 18, 92, 4, 76, 73, 71, 79, 180, 1, 5, 89, + 82, 65, 78, 73, 210, 14, 88, 141, 254, 32, 2, 77, 65, 4, 211, 1, 78, 42, + 60, 2, 65, 82, 100, 2, 73, 65, 90, 69, 169, 1, 2, 83, 73, 12, 40, 2, 65, + 75, 201, 246, 16, 2, 73, 67, 10, 52, 3, 65, 76, 69, 45, 6, 76, 73, 84, + 73, 75, 73, 4, 11, 83, 4, 17, 2, 77, 65, 4, 23, 32, 7, 11, 32, 4, 198, + 15, 65, 151, 219, 21, 78, 12, 72, 3, 84, 65, 83, 136, 3, 6, 76, 65, 83, + 84, 79, 78, 239, 202, 8, 82, 6, 26, 84, 211, 216, 33, 77, 4, 32, 2, 79, + 75, 231, 218, 33, 73, 2, 173, 185, 33, 2, 79, 85, 14, 36, 5, 70, 73, 83, + 84, 79, 67, 76, 10, 46, 80, 214, 1, 78, 170, 8, 76, 187, 1, 83, 2, 135, + 11, 65, 4, 138, 138, 33, 79, 215, 79, 73, 4, 178, 5, 69, 229, 178, 33, 2, + 65, 80, 42, 120, 5, 69, 73, 83, 77, 65, 32, 8, 73, 77, 65, 78, 83, 73, + 83, 32, 182, 1, 84, 154, 1, 89, 249, 240, 1, 3, 65, 88, 73, 5, 11, 32, 2, + 219, 230, 21, 78, 16, 36, 2, 65, 82, 1, 3, 84, 72, 69, 8, 25, 4, 83, 69, + 79, 83, 9, 11, 32, 6, 18, 84, 39, 68, 4, 34, 82, 13, 4, 69, 84, 82, 65, + 2, 11, 73, 2, 153, 198, 26, 3, 83, 73, 77, 8, 68, 5, 65, 86, 82, 79, 83, + 52, 4, 82, 65, 71, 71, 175, 147, 16, 73, 5, 29, 5, 32, 65, 80, 79, 68, 2, + 175, 206, 8, 69, 2, 145, 241, 1, 2, 73, 83, 12, 34, 78, 149, 1, 3, 82, + 77, 65, 8, 36, 5, 65, 71, 77, 65, 32, 91, 69, 6, 154, 8, 65, 150, 219, + 21, 78, 233, 224, 4, 10, 77, 69, 84, 65, 32, 83, 84, 65, 86, 82, 2, 251, + 178, 33, 86, 5, 11, 84, 2, 255, 193, 16, 73, 40, 42, 69, 70, 72, 218, 1, + 82, 227, 2, 73, 6, 136, 12, 3, 84, 82, 65, 162, 148, 8, 76, 137, 167, 23, + 2, 83, 83, 12, 26, 69, 131, 174, 33, 73, 10, 64, 2, 77, 65, 133, 190, 32, + 8, 83, 32, 75, 65, 73, 32, 65, 80, 9, 56, 2, 32, 65, 33, 8, 84, 73, 83, + 77, 79, 83, 32, 69, 2, 177, 209, 32, 3, 80, 76, 79, 4, 182, 178, 33, 83, + 3, 88, 20, 38, 73, 73, 5, 79, 77, 73, 75, 79, 6, 48, 2, 71, 79, 182, 129, + 29, 80, 131, 207, 4, 65, 2, 191, 153, 32, 82, 14, 42, 76, 32, 2, 78, 32, + 62, 80, 95, 83, 2, 11, 89, 2, 191, 174, 33, 71, 6, 26, 65, 135, 222, 21, + 78, 4, 250, 2, 82, 239, 169, 33, 76, 4, 46, 65, 141, 157, 32, 5, 83, 73, + 70, 73, 83, 2, 201, 173, 33, 6, 82, 65, 75, 65, 76, 69, 2, 11, 89, 2, + 141, 140, 16, 2, 78, 65, 10, 26, 82, 183, 172, 33, 84, 8, 21, 3, 69, 73, + 65, 8, 26, 32, 113, 2, 73, 32, 6, 38, 69, 242, 5, 68, 251, 213, 21, 78, + 2, 11, 75, 2, 29, 5, 70, 79, 78, 73, 84, 2, 141, 253, 32, 2, 73, 75, 2, + 11, 65, 2, 11, 82, 2, 129, 252, 32, 3, 67, 72, 65, 22, 28, 2, 70, 69, + 231, 3, 80, 14, 34, 78, 49, 4, 83, 73, 83, 32, 4, 11, 32, 4, 210, 234, + 29, 75, 235, 183, 3, 65, 10, 42, 65, 42, 68, 62, 77, 89, 2, 84, 82, 2, + 133, 2, 6, 80, 76, 73, 32, 68, 89, 2, 233, 1, 11, 73, 71, 82, 65, 77, 77, + 79, 83, 32, 69, 88, 2, 173, 1, 18, 79, 78, 79, 71, 82, 65, 77, 77, 79, + 83, 32, 84, 69, 83, 83, 69, 82, 65, 4, 11, 73, 4, 60, 11, 71, 82, 65, 77, + 77, 79, 83, 32, 79, 75, 84, 59, 84, 2, 11, 79, 2, 189, 174, 2, 6, 32, 68, + 79, 68, 69, 75, 2, 129, 248, 32, 4, 73, 77, 79, 82, 8, 26, 79, 243, 248, + 28, 83, 6, 56, 6, 75, 82, 73, 83, 73, 83, 157, 133, 29, 2, 82, 82, 5, 17, + 2, 32, 68, 2, 11, 73, 2, 159, 248, 28, 80, 162, 82, 182, 1, 65, 134, 72, + 69, 230, 1, 72, 154, 31, 73, 240, 41, 3, 74, 75, 32, 238, 25, 76, 186, + 18, 79, 194, 113, 82, 162, 8, 85, 130, 128, 2, 89, 166, 221, 18, 71, 226, + 155, 10, 83, 203, 18, 67, 198, 13, 110, 68, 66, 76, 50, 77, 90, 78, 174, + 51, 80, 62, 82, 198, 7, 84, 138, 1, 85, 198, 240, 17, 67, 139, 181, 6, + 83, 4, 34, 85, 221, 189, 26, 2, 65, 32, 2, 201, 193, 31, 2, 67, 69, 4, + 144, 189, 9, 3, 76, 32, 77, 131, 130, 19, 69, 6, 36, 3, 69, 82, 65, 207, + 242, 32, 80, 5, 217, 226, 26, 7, 32, 87, 73, 84, 72, 32, 70, 193, 11, + 148, 1, 16, 65, 68, 73, 65, 78, 32, 83, 89, 76, 76, 65, 66, 73, 67, 83, + 32, 148, 49, 2, 67, 69, 94, 68, 172, 152, 23, 3, 78, 69, 68, 139, 225, 9, + 79, 172, 11, 226, 1, 65, 190, 1, 66, 162, 2, 67, 242, 8, 69, 50, 70, 198, + 4, 72, 38, 73, 30, 75, 134, 1, 76, 82, 77, 174, 1, 78, 202, 4, 81, 178, + 1, 79, 194, 1, 80, 70, 82, 142, 1, 83, 194, 4, 84, 246, 3, 87, 254, 5, + 89, 223, 152, 17, 71, 21, 90, 65, 30, 73, 40, 10, 84, 72, 65, 80, 65, 83, + 67, 65, 78, 32, 242, 190, 33, 78, 3, 89, 7, 178, 191, 33, 73, 3, 89, 5, + 133, 150, 23, 5, 86, 73, 76, 73, 75, 4, 238, 190, 33, 77, 3, 83, 42, 156, + 1, 9, 76, 65, 67, 75, 70, 79, 79, 84, 32, 172, 226, 18, 9, 73, 66, 76, + 69, 45, 67, 82, 69, 69, 253, 180, 7, 10, 69, 65, 86, 69, 82, 32, 68, 69, + 78, 69, 36, 82, 87, 158, 208, 11, 75, 2, 78, 198, 236, 21, 65, 2, 69, 2, + 73, 2, 79, 3, 83, 11, 222, 188, 33, 65, 2, 69, 2, 73, 3, 79, 141, 3, 82, + 65, 186, 42, 87, 206, 155, 8, 72, 218, 182, 22, 79, 182, 56, 73, 207, + 134, 2, 69, 241, 2, 48, 6, 82, 82, 73, 69, 82, 32, 219, 180, 31, 65, 234, + 2, 170, 1, 68, 122, 71, 94, 72, 46, 73, 46, 74, 82, 75, 30, 78, 66, 83, + 66, 80, 2, 90, 58, 84, 38, 76, 132, 1, 2, 67, 72, 2, 77, 2, 82, 2, 87, 2, + 89, 171, 157, 33, 69, 32, 46, 69, 202, 5, 76, 2, 90, 255, 179, 33, 73, 6, + 26, 78, 171, 185, 33, 69, 4, 166, 210, 16, 69, 181, 191, 6, 2, 84, 65, + 30, 254, 4, 72, 174, 234, 20, 87, 166, 136, 7, 65, 154, 129, 5, 69, 150, + 64, 73, 2, 79, 3, 85, 19, 162, 4, 87, 170, 157, 33, 69, 215, 22, 73, 5, + 209, 223, 13, 6, 78, 73, 84, 73, 65, 76, 26, 202, 3, 74, 234, 243, 32, + 69, 222, 61, 87, 186, 2, 65, 2, 73, 2, 79, 3, 85, 26, 154, 1, 75, 227, 1, + 72, 14, 198, 246, 32, 69, 150, 64, 65, 2, 71, 2, 73, 2, 79, 3, 85, 26, + 62, 72, 202, 245, 32, 69, 150, 64, 65, 2, 73, 2, 79, 3, 85, 15, 198, 245, + 32, 69, 150, 64, 65, 2, 73, 2, 79, 3, 85, 72, 34, 76, 70, 84, 66, 72, 3, + 83, 24, 130, 1, 72, 234, 243, 32, 69, 150, 64, 65, 2, 73, 2, 79, 3, 85, + 24, 62, 83, 234, 243, 32, 69, 150, 64, 65, 2, 73, 2, 79, 3, 85, 12, 230, + 243, 32, 69, 150, 64, 65, 2, 73, 2, 79, 3, 85, 7, 236, 29, 4, 65, 83, 84, + 69, 215, 149, 33, 78, 51, 74, 65, 22, 73, 190, 231, 30, 85, 250, 11, 79, + 186, 79, 87, 203, 239, 1, 69, 7, 251, 171, 31, 65, 33, 40, 4, 78, 65, 76, + 32, 139, 178, 33, 73, 28, 160, 1, 2, 68, 79, 134, 1, 82, 78, 83, 150, + 221, 13, 71, 186, 2, 65, 132, 165, 3, 6, 66, 79, 84, 84, 79, 77, 0, 3, + 84, 79, 80, 202, 205, 12, 80, 211, 203, 2, 77, 6, 44, 5, 85, 66, 76, 69, + 32, 195, 212, 23, 87, 4, 232, 193, 6, 12, 83, 72, 79, 82, 84, 32, 86, 69, + 82, 84, 73, 67, 131, 159, 7, 65, 6, 38, 73, 253, 229, 31, 3, 65, 73, 83, + 4, 218, 132, 17, 71, 139, 170, 16, 78, 4, 184, 199, 24, 4, 77, 65, 76, + 76, 129, 202, 6, 4, 72, 79, 82, 84, 4, 198, 229, 25, 89, 139, 201, 7, 75, + 7, 170, 174, 33, 73, 3, 78, 39, 66, 87, 234, 27, 65, 230, 210, 30, 79, + 182, 56, 73, 207, 134, 2, 69, 19, 182, 250, 11, 65, 150, 244, 18, 79, + 182, 56, 73, 207, 134, 2, 69, 49, 142, 7, 72, 154, 20, 65, 66, 87, 166, + 210, 30, 79, 182, 56, 73, 207, 134, 2, 69, 43, 70, 69, 38, 79, 238, 25, + 65, 66, 87, 218, 138, 31, 73, 207, 134, 2, 72, 7, 229, 133, 26, 4, 68, + 73, 65, 76, 7, 11, 79, 5, 161, 233, 31, 8, 83, 69, 45, 67, 82, 69, 69, + 32, 149, 1, 164, 1, 8, 45, 67, 82, 69, 69, 32, 84, 72, 38, 65, 250, 2, + 71, 76, 2, 78, 71, 48, 4, 85, 78, 65, 86, 142, 20, 79, 30, 87, 218, 138, + 31, 73, 206, 134, 2, 69, 3, 72, 6, 150, 163, 31, 73, 207, 134, 2, 69, 63, + 104, 6, 83, 75, 65, 80, 73, 32, 188, 1, 7, 84, 84, 73, 76, 73, 75, 32, + 206, 160, 31, 65, 207, 134, 2, 89, 30, 70, 83, 86, 87, 210, 17, 67, 2, + 75, 2, 77, 2, 78, 2, 84, 3, 89, 14, 220, 230, 27, 2, 75, 87, 178, 124, + 67, 2, 80, 2, 84, 182, 213, 2, 87, 187, 113, 45, 4, 194, 136, 33, 79, + 191, 28, 65, 24, 30, 72, 1, 3, 83, 72, 82, 12, 202, 229, 27, 65, 174, + 130, 3, 79, 183, 56, 73, 19, 38, 65, 162, 231, 30, 79, 183, 56, 73, 9, + 210, 159, 31, 65, 207, 134, 2, 73, 15, 206, 228, 27, 65, 174, 130, 3, 79, + 183, 56, 73, 18, 224, 9, 3, 73, 75, 32, 149, 243, 22, 2, 85, 84, 33, 68, + 7, 74, 73, 66, 87, 65, 89, 32, 210, 164, 33, 78, 2, 79, 3, 89, 24, 74, + 78, 166, 176, 29, 83, 226, 243, 3, 67, 2, 75, 2, 77, 2, 80, 3, 84, 11, + 11, 87, 8, 246, 228, 30, 79, 183, 56, 73, 39, 206, 4, 87, 166, 13, 65, + 38, 79, 246, 138, 31, 73, 207, 134, 2, 69, 39, 104, 7, 45, 67, 82, 69, + 69, 32, 82, 146, 14, 87, 182, 2, 65, 230, 210, 30, 79, 182, 56, 73, 207, + 134, 2, 69, 4, 210, 139, 33, 87, 215, 22, 69, 125, 94, 65, 218, 1, 72, + 138, 1, 79, 238, 2, 87, 154, 175, 11, 80, 250, 229, 19, 73, 207, 134, 2, + 69, 43, 26, 89, 195, 154, 31, 65, 37, 25, 4, 73, 83, 73, 32, 34, 70, 72, + 54, 74, 218, 4, 83, 198, 135, 33, 89, 202, 18, 84, 147, 1, 77, 10, 166, + 225, 30, 79, 130, 191, 2, 65, 2, 69, 3, 73, 6, 214, 208, 29, 85, 159, + 207, 3, 73, 37, 70, 87, 202, 13, 79, 174, 222, 11, 65, 202, 172, 19, 73, + 207, 134, 2, 69, 16, 198, 13, 79, 150, 208, 27, 65, 226, 186, 3, 73, 207, + 134, 2, 69, 15, 80, 12, 85, 84, 72, 45, 83, 76, 65, 86, 69, 89, 32, 75, + 246, 157, 33, 79, 3, 89, 8, 226, 156, 33, 65, 2, 69, 2, 73, 3, 79, 117, + 110, 72, 190, 1, 76, 78, 84, 238, 8, 65, 66, 87, 226, 164, 11, 89, 198, + 173, 19, 79, 182, 56, 73, 207, 134, 2, 69, 39, 108, 7, 45, 67, 82, 69, + 69, 32, 84, 226, 4, 87, 222, 213, 27, 65, 174, 130, 3, 79, 182, 56, 73, + 207, 134, 2, 69, 16, 11, 72, 17, 174, 218, 27, 65, 174, 130, 3, 79, 182, + 56, 73, 207, 134, 2, 69, 12, 11, 72, 12, 142, 220, 30, 79, 174, 168, 2, + 87, 214, 22, 65, 2, 69, 3, 73, 24, 50, 72, 158, 154, 33, 65, 2, 69, 2, + 73, 3, 79, 17, 238, 216, 27, 65, 174, 130, 3, 79, 174, 168, 2, 87, 214, + 22, 69, 3, 73, 224, 1, 54, 69, 218, 3, 79, 174, 226, 11, 65, 203, 172, + 19, 73, 185, 1, 17, 2, 83, 84, 182, 1, 44, 6, 45, 67, 82, 69, 69, 32, + 251, 2, 69, 180, 1, 110, 76, 66, 77, 2, 80, 2, 89, 16, 2, 78, 87, 38, 82, + 62, 83, 26, 67, 2, 75, 18, 84, 26, 70, 199, 4, 87, 27, 178, 6, 87, 250, + 207, 27, 65, 174, 130, 3, 79, 131, 191, 2, 69, 17, 243, 5, 87, 6, 218, + 213, 27, 65, 175, 193, 5, 69, 13, 154, 167, 31, 87, 202, 239, 1, 65, 2, + 69, 2, 73, 3, 79, 28, 22, 72, 239, 4, 87, 14, 235, 4, 87, 16, 22, 72, + 199, 4, 87, 2, 159, 166, 31, 87, 2, 135, 240, 22, 82, 31, 11, 79, 29, 41, + 8, 68, 83, 45, 67, 82, 69, 69, 32, 26, 56, 2, 84, 72, 201, 149, 31, 6, + 70, 73, 78, 65, 76, 32, 25, 50, 87, 154, 148, 33, 65, 2, 69, 2, 73, 3, + 79, 14, 234, 210, 27, 65, 174, 130, 3, 79, 182, 56, 73, 251, 239, 1, 69, + 61, 92, 6, 45, 67, 82, 69, 69, 32, 150, 1, 65, 38, 79, 30, 87, 218, 138, + 31, 73, 207, 134, 2, 69, 24, 110, 80, 194, 209, 30, 67, 2, 75, 2, 76, 2, + 77, 2, 78, 2, 83, 2, 84, 2, 89, 214, 161, 2, 79, 247, 30, 87, 4, 190, + 162, 31, 87, 215, 208, 1, 79, 9, 150, 139, 31, 65, 207, 134, 2, 89, 7, + 190, 145, 33, 79, 3, 89, 14, 246, 207, 27, 65, 174, 130, 3, 79, 182, 56, + 73, 207, 134, 2, 69, 10, 26, 76, 203, 144, 33, 82, 9, 26, 32, 239, 162, + 9, 76, 4, 222, 217, 21, 67, 207, 208, 9, 84, 4, 178, 249, 32, 76, 215, + 22, 89, 4, 180, 247, 14, 3, 73, 84, 85, 253, 241, 7, 3, 82, 73, 67, 124, + 140, 1, 2, 68, 32, 102, 69, 72, 11, 73, 65, 78, 32, 76, 69, 84, 84, 69, + 82, 32, 210, 3, 79, 62, 80, 90, 82, 181, 250, 26, 4, 32, 83, 76, 73, 6, + 52, 5, 73, 78, 68, 69, 88, 157, 129, 32, 2, 70, 73, 5, 153, 255, 31, 6, + 32, 68, 73, 86, 73, 68, 6, 26, 84, 147, 131, 21, 32, 5, 209, 136, 10, 6, + 32, 73, 78, 83, 69, 82, 98, 196, 1, 2, 67, 45, 38, 76, 22, 77, 50, 78, + 38, 83, 46, 84, 22, 85, 230, 213, 3, 65, 2, 68, 2, 69, 2, 71, 2, 75, 2, + 80, 214, 208, 25, 82, 218, 220, 1, 73, 206, 134, 2, 66, 2, 79, 2, 81, 3, + 88, 4, 226, 163, 26, 49, 159, 148, 3, 51, 7, 139, 215, 3, 68, 11, 11, 66, + 9, 226, 138, 33, 50, 2, 51, 3, 52, 9, 190, 138, 33, 68, 2, 71, 3, 78, 13, + 162, 214, 3, 72, 2, 84, 251, 179, 29, 83, 7, 247, 213, 3, 84, 13, 11, 85, + 11, 11, 85, 9, 194, 137, 33, 50, 2, 51, 3, 85, 4, 148, 128, 32, 6, 85, + 83, 69, 76, 32, 72, 139, 137, 1, 78, 4, 152, 230, 26, 6, 32, 83, 84, 82, + 69, 65, 173, 164, 5, 7, 69, 78, 84, 82, 89, 32, 83, 4, 198, 240, 26, 73, + 155, 251, 5, 79, 9, 29, 5, 32, 70, 65, 67, 69, 7, 33, 6, 32, 87, 73, 84, + 72, 32, 4, 132, 229, 6, 2, 84, 69, 157, 132, 24, 6, 87, 82, 89, 32, 83, + 77, 108, 88, 16, 67, 65, 83, 73, 65, 78, 32, 65, 76, 66, 65, 78, 73, 65, + 78, 32, 159, 172, 29, 84, 106, 60, 7, 76, 69, 84, 84, 69, 82, 32, 189, + 160, 27, 2, 67, 73, 104, 174, 2, 65, 34, 67, 146, 1, 68, 78, 69, 34, 71, + 46, 73, 46, 74, 34, 75, 34, 76, 34, 80, 34, 83, 74, 84, 62, 89, 46, 90, + 140, 189, 16, 2, 81, 65, 166, 173, 6, 77, 208, 156, 6, 3, 86, 69, 89, + 182, 189, 2, 70, 220, 18, 3, 78, 79, 87, 146, 19, 82, 234, 21, 88, 150, + 46, 79, 202, 26, 66, 225, 24, 3, 72, 69, 89, 4, 194, 202, 32, 79, 167, + 28, 76, 16, 34, 65, 34, 72, 49, 2, 89, 65, 4, 250, 178, 32, 89, 215, 79, + 82, 8, 186, 205, 27, 65, 174, 163, 5, 79, 203, 17, 73, 4, 254, 129, 33, + 87, 3, 89, 8, 42, 90, 134, 186, 31, 89, 139, 171, 1, 65, 4, 202, 245, 31, + 89, 167, 122, 65, 4, 194, 177, 32, 89, 215, 79, 66, 4, 136, 214, 31, 2, + 72, 69, 151, 154, 1, 73, 6, 166, 198, 31, 82, 210, 106, 87, 251, 76, 78, + 4, 134, 244, 31, 72, 191, 14, 65, 4, 238, 129, 32, 73, 195, 69, 65, 4, + 138, 176, 32, 65, 159, 51, 89, 4, 142, 1, 73, 223, 174, 32, 69, 8, 34, + 72, 229, 251, 32, 2, 69, 89, 6, 142, 220, 19, 65, 167, 145, 13, 79, 6, + 38, 73, 198, 242, 31, 89, 159, 78, 65, 2, 223, 197, 32, 87, 4, 132, 184, + 32, 2, 65, 89, 1, 2, 79, 87, 6, 142, 223, 15, 72, 199, 177, 4, 65, 16, + 72, 2, 68, 73, 32, 2, 78, 84, 180, 155, 31, 3, 76, 84, 73, 207, 77, 82, + 4, 162, 246, 31, 32, 199, 100, 76, 8, 32, 2, 82, 69, 227, 245, 31, 32, 6, + 44, 5, 76, 73, 78, 69, 32, 207, 226, 4, 32, 4, 174, 154, 21, 76, 255, + 252, 9, 79, 252, 5, 102, 65, 170, 17, 69, 134, 8, 73, 150, 1, 79, 140, + 152, 4, 6, 82, 73, 83, 84, 77, 65, 195, 222, 18, 85, 198, 2, 66, 73, 32, + 4, 75, 77, 65, 32, 148, 6, 2, 77, 32, 131, 8, 82, 4, 226, 188, 32, 78, + 211, 61, 82, 142, 1, 156, 1, 7, 76, 69, 84, 84, 69, 82, 32, 142, 3, 83, + 98, 86, 170, 255, 22, 68, 170, 171, 7, 81, 236, 90, 5, 77, 65, 65, 89, + 89, 144, 174, 1, 2, 65, 85, 3, 79, 76, 202, 1, 68, 54, 78, 54, 84, 54, + 89, 142, 162, 28, 66, 2, 67, 2, 71, 2, 74, 2, 75, 2, 76, 2, 80, 182, 228, + 2, 72, 2, 77, 2, 82, 2, 83, 2, 86, 2, 87, 146, 237, 1, 65, 186, 2, 69, 2, + 73, 3, 85, 8, 166, 163, 28, 68, 182, 228, 2, 72, 147, 237, 1, 65, 8, 166, + 135, 31, 71, 2, 78, 2, 89, 147, 237, 1, 65, 8, 190, 162, 28, 84, 182, + 228, 2, 72, 147, 237, 1, 65, 4, 190, 134, 31, 89, 147, 237, 1, 65, 8, 40, + 4, 73, 71, 78, 32, 195, 188, 21, 69, 6, 142, 143, 29, 67, 226, 182, 1, + 86, 223, 234, 1, 65, 26, 64, 10, 79, 87, 69, 76, 32, 83, 73, 71, 78, 32, + 203, 194, 30, 73, 24, 238, 139, 29, 65, 182, 25, 85, 210, 200, 1, 69, 2, + 73, 3, 79, 166, 1, 236, 1, 15, 67, 79, 78, 83, 79, 78, 65, 78, 84, 32, + 83, 73, 71, 78, 32, 112, 7, 76, 69, 84, 84, 69, 82, 32, 152, 4, 12, 80, + 85, 78, 67, 84, 85, 65, 84, 73, 79, 78, 32, 60, 11, 86, 79, 87, 69, 76, + 32, 83, 73, 71, 78, 32, 175, 254, 30, 68, 14, 72, 6, 70, 73, 78, 65, 76, + 32, 138, 239, 32, 76, 2, 82, 2, 87, 3, 89, 6, 234, 240, 32, 78, 86, 72, + 3, 77, 104, 132, 2, 6, 70, 73, 78, 65, 76, 32, 110, 78, 50, 77, 78, 80, + 146, 195, 11, 66, 198, 231, 5, 68, 234, 191, 2, 83, 166, 252, 10, 65, + 152, 191, 1, 2, 67, 72, 2, 71, 2, 74, 2, 75, 2, 84, 254, 68, 72, 2, 76, + 2, 82, 2, 86, 2, 89, 186, 2, 69, 2, 73, 2, 79, 3, 85, 22, 254, 246, 30, + 78, 198, 186, 1, 83, 194, 60, 67, 146, 1, 71, 2, 75, 2, 76, 2, 80, 2, 82, + 2, 84, 3, 89, 14, 46, 71, 34, 72, 134, 215, 32, 85, 215, 22, 65, 4, 162, + 215, 32, 85, 215, 22, 65, 6, 130, 215, 32, 85, 158, 20, 74, 187, 2, 65, + 6, 242, 234, 32, 72, 2, 80, 187, 2, 65, 8, 190, 136, 11, 83, 246, 142, + 12, 68, 45, 4, 84, 82, 73, 80, 20, 238, 135, 29, 65, 142, 222, 1, 73, + 186, 198, 1, 79, 2, 85, 191, 44, 69, 14, 72, 7, 65, 67, 84, 69, 82, 32, + 84, 49, 7, 84, 32, 87, 73, 84, 72, 32, 8, 140, 223, 9, 3, 65, 66, 85, + 211, 245, 22, 73, 6, 128, 1, 13, 85, 80, 87, 65, 82, 68, 83, 32, 84, 82, + 69, 78, 68, 149, 214, 24, 12, 68, 79, 87, 78, 87, 65, 82, 68, 83, 32, 84, + 82, 5, 233, 234, 6, 6, 32, 65, 78, 68, 32, 89, 234, 2, 80, 2, 67, 75, 82, + 69, 90, 82, 224, 247, 4, 2, 83, 84, 241, 219, 14, 2, 81, 85, 6, 56, 8, + 69, 82, 32, 66, 79, 65, 82, 68, 151, 167, 32, 32, 5, 223, 247, 29, 32, 4, + 184, 215, 26, 4, 83, 69, 32, 87, 177, 231, 4, 9, 82, 73, 78, 71, 32, 77, + 69, 71, 65, 220, 2, 40, 5, 79, 75, 69, 69, 32, 143, 5, 82, 216, 2, 46, + 76, 1, 7, 83, 77, 65, 76, 76, 32, 76, 172, 1, 33, 6, 69, 84, 84, 69, 82, + 32, 172, 1, 170, 1, 68, 74, 72, 74, 78, 70, 83, 62, 84, 54, 71, 2, 76, 2, + 77, 0, 2, 81, 85, 2, 87, 2, 89, 158, 224, 32, 75, 186, 2, 65, 2, 69, 2, + 73, 2, 79, 2, 85, 3, 86, 14, 222, 226, 32, 76, 186, 2, 65, 2, 69, 2, 73, + 2, 79, 2, 85, 3, 86, 14, 150, 226, 32, 78, 186, 2, 65, 2, 69, 2, 73, 2, + 79, 2, 85, 3, 86, 14, 166, 240, 28, 65, 226, 243, 3, 69, 2, 73, 2, 79, 2, + 85, 3, 86, 15, 194, 227, 32, 65, 2, 69, 2, 73, 2, 79, 2, 85, 3, 86, 30, + 50, 76, 2, 83, 214, 226, 32, 65, 2, 69, 3, 73, 12, 210, 226, 32, 65, 2, + 69, 2, 73, 2, 79, 2, 85, 3, 86, 4, 48, 6, 89, 32, 66, 76, 79, 83, 135, + 206, 31, 73, 2, 255, 208, 32, 83, 12, 96, 2, 76, 68, 174, 222, 7, 32, + 232, 239, 2, 2, 80, 77, 228, 193, 20, 2, 67, 75, 151, 129, 1, 82, 5, 213, + 128, 28, 7, 82, 69, 78, 32, 67, 82, 79, 60, 92, 8, 82, 65, 83, 77, 73, + 65, 78, 32, 222, 253, 4, 80, 249, 203, 11, 5, 67, 79, 76, 65, 84, 56, 52, + 7, 76, 69, 84, 84, 69, 82, 32, 243, 134, 21, 78, 42, 224, 1, 6, 67, 85, + 82, 76, 69, 68, 30, 83, 202, 131, 21, 68, 34, 76, 254, 194, 1, 82, 134, + 212, 2, 65, 50, 71, 90, 90, 98, 89, 154, 193, 1, 72, 234, 5, 75, 130, 76, + 66, 190, 173, 4, 78, 254, 1, 84, 2, 87, 202, 103, 80, 171, 4, 77, 2, 161, + 223, 31, 2, 32, 87, 6, 176, 131, 21, 6, 77, 65, 76, 76, 32, 65, 172, 210, + 5, 2, 65, 77, 139, 136, 5, 72, 232, 4, 66, 78, 20, 2, 82, 67, 233, 40, 7, + 84, 89, 83, 67, 65, 80, 69, 2, 247, 186, 32, 69, 226, 4, 28, 2, 76, 69, + 239, 39, 85, 220, 4, 30, 32, 181, 6, 2, 68, 32, 24, 244, 1, 5, 87, 73, + 84, 72, 32, 161, 133, 18, 49, 68, 73, 86, 73, 68, 69, 68, 32, 66, 89, 32, + 72, 79, 82, 73, 90, 79, 78, 84, 65, 76, 32, 66, 65, 82, 32, 65, 78, 68, + 32, 84, 79, 80, 32, 72, 65, 76, 70, 32, 68, 73, 86, 73, 68, 69, 68, 32, + 66, 89, 22, 142, 2, 76, 46, 83, 108, 22, 84, 87, 79, 32, 72, 79, 82, 73, + 90, 79, 78, 84, 65, 76, 32, 83, 84, 82, 79, 75, 69, 83, 44, 6, 85, 80, + 80, 69, 82, 32, 44, 17, 65, 76, 76, 32, 66, 85, 84, 32, 85, 80, 80, 69, + 82, 32, 76, 69, 70, 238, 230, 25, 86, 190, 227, 3, 82, 231, 58, 72, 4, + 138, 204, 29, 69, 49, 4, 79, 87, 69, 82, 4, 104, 11, 77, 65, 76, 76, 32, + 67, 73, 82, 67, 76, 69, 221, 5, 10, 85, 80, 69, 82, 73, 77, 80, 79, 83, + 69, 2, 173, 225, 29, 6, 32, 84, 79, 32, 84, 72, 4, 40, 4, 82, 73, 71, 72, + 227, 202, 29, 72, 2, 245, 202, 29, 10, 84, 32, 81, 85, 65, 68, 82, 65, + 78, 84, 196, 4, 230, 2, 65, 186, 1, 66, 58, 67, 230, 1, 68, 246, 1, 72, + 250, 2, 73, 210, 10, 75, 190, 2, 76, 38, 77, 136, 1, 7, 78, 85, 77, 66, + 69, 82, 32, 192, 4, 17, 79, 80, 69, 78, 32, 67, 69, 78, 84, 82, 69, 32, + 69, 73, 71, 72, 84, 54, 80, 114, 82, 50, 84, 78, 87, 224, 228, 9, 4, 90, + 69, 82, 79, 222, 253, 15, 69, 250, 129, 4, 86, 130, 65, 71, 190, 110, 83, + 199, 160, 1, 88, 6, 100, 12, 78, 84, 73, 67, 76, 79, 67, 75, 87, 73, 83, + 69, 249, 166, 29, 7, 83, 84, 69, 82, 73, 83, 75, 4, 160, 220, 8, 11, 45, + 82, 79, 84, 65, 84, 69, 68, 32, 68, 73, 211, 218, 22, 32, 4, 32, 2, 79, + 76, 139, 244, 30, 85, 2, 175, 225, 13, 68, 16, 60, 4, 82, 79, 83, 83, + 210, 2, 32, 142, 205, 32, 67, 3, 68, 10, 26, 32, 219, 193, 1, 73, 8, 64, + 6, 70, 79, 82, 77, 69, 69, 201, 226, 30, 4, 80, 79, 77, 77, 7, 33, 6, 32, + 87, 73, 84, 72, 32, 4, 254, 177, 30, 70, 251, 78, 84, 30, 34, 73, 70, 79, + 183, 232, 30, 65, 24, 152, 188, 4, 8, 86, 73, 83, 73, 79, 78, 32, 83, + 247, 163, 26, 71, 4, 64, 10, 76, 76, 65, 82, 32, 83, 73, 71, 78, 32, 227, + 162, 29, 84, 2, 197, 230, 18, 13, 87, 73, 84, 72, 32, 79, 86, 69, 82, 76, + 65, 73, 68, 64, 212, 1, 6, 65, 78, 71, 85, 76, 32, 184, 151, 12, 20, 79, + 82, 73, 90, 79, 78, 84, 65, 76, 32, 66, 65, 82, 32, 87, 73, 84, 72, 32, + 78, 152, 181, 9, 4, 69, 65, 86, 89, 189, 158, 6, 8, 85, 77, 65, 78, 32, + 70, 73, 71, 58, 110, 67, 160, 128, 20, 5, 73, 69, 85, 78, 71, 42, 72, 30, + 75, 66, 77, 34, 78, 34, 80, 62, 82, 30, 83, 27, 84, 8, 254, 255, 19, 72, + 157, 3, 4, 73, 69, 85, 67, 116, 220, 1, 9, 68, 69, 79, 71, 82, 65, 80, + 72, 32, 212, 8, 27, 84, 65, 76, 73, 67, 32, 76, 65, 84, 73, 78, 32, 67, + 65, 80, 73, 84, 65, 76, 32, 76, 69, 84, 84, 69, 82, 32, 165, 176, 26, 9, + 78, 70, 79, 82, 77, 65, 84, 73, 79, 110, 178, 1, 65, 110, 67, 90, 69, 86, + 70, 62, 72, 38, 75, 70, 76, 50, 77, 86, 78, 62, 81, 30, 82, 74, 83, 246, + 128, 20, 84, 50, 87, 146, 204, 1, 73, 172, 24, 2, 80, 82, 231, 193, 9, + 79, 8, 130, 129, 20, 76, 180, 132, 1, 3, 67, 67, 69, 196, 212, 6, 3, 84, + 84, 69, 245, 17, 5, 68, 86, 65, 78, 84, 8, 26, 79, 159, 208, 29, 69, 6, + 168, 180, 10, 2, 82, 82, 146, 204, 9, 78, 175, 179, 12, 80, 8, 206, 128, + 20, 78, 246, 253, 8, 65, 148, 131, 3, 5, 88, 67, 69, 76, 76, 219, 24, 73, + 10, 218, 128, 20, 73, 128, 169, 5, 2, 69, 77, 131, 162, 6, 79, 4, 214, + 203, 28, 73, 203, 251, 2, 65, 4, 240, 141, 7, 8, 73, 78, 68, 69, 82, 71, + 65, 82, 199, 233, 21, 79, 6, 234, 255, 19, 65, 130, 197, 11, 79, 179, 83, + 69, 8, 38, 69, 130, 161, 31, 65, 199, 81, 79, 4, 128, 169, 31, 3, 68, 73, + 67, 251, 15, 84, 6, 26, 73, 139, 170, 31, 65, 4, 162, 151, 32, 71, 231, + 19, 78, 2, 237, 218, 27, 2, 85, 69, 8, 26, 69, 195, 150, 32, 73, 6, 242, + 254, 19, 83, 205, 225, 7, 2, 76, 73, 22, 90, 69, 38, 85, 164, 230, 13, 2, + 67, 72, 166, 152, 6, 79, 22, 80, 34, 84, 211, 180, 11, 73, 4, 178, 132, + 10, 67, 215, 234, 20, 86, 6, 198, 255, 19, 80, 180, 177, 4, 3, 73, 84, + 65, 223, 142, 8, 78, 4, 150, 191, 32, 67, 3, 82, 98, 116, 8, 65, 84, 65, + 75, 65, 78, 65, 32, 133, 1, 16, 79, 82, 69, 65, 78, 32, 67, 72, 65, 82, + 65, 67, 84, 69, 82, 32, 94, 194, 208, 10, 72, 2, 75, 2, 77, 2, 78, 2, 82, + 2, 83, 2, 84, 126, 87, 46, 89, 154, 236, 21, 65, 2, 69, 2, 73, 2, 79, 3, + 85, 4, 216, 214, 15, 3, 74, 85, 69, 165, 199, 16, 4, 67, 72, 65, 77, 106, + 166, 211, 26, 65, 203, 218, 3, 69, 4, 100, 19, 85, 76, 84, 73, 80, 76, + 73, 67, 65, 84, 73, 79, 78, 32, 83, 73, 71, 78, 32, 191, 184, 30, 73, 2, + 129, 84, 4, 87, 73, 84, 72, 98, 50, 69, 46, 70, 98, 83, 94, 84, 151, 251, + 19, 78, 6, 180, 1, 3, 73, 71, 72, 191, 222, 24, 76, 30, 28, 3, 73, 70, + 84, 35, 79, 6, 214, 1, 89, 203, 231, 30, 69, 24, 142, 2, 82, 255, 250, + 19, 85, 8, 40, 4, 69, 86, 69, 78, 1, 2, 73, 88, 4, 11, 84, 4, 104, 2, 89, + 32, 191, 231, 30, 69, 52, 56, 2, 69, 78, 32, 4, 72, 73, 82, 84, 29, 2, + 87, 69, 5, 11, 32, 2, 135, 252, 24, 79, 24, 74, 89, 223, 230, 30, 69, 24, + 26, 78, 163, 187, 31, 76, 22, 17, 2, 84, 89, 23, 11, 32, 20, 72, 2, 79, + 78, 218, 201, 30, 70, 30, 83, 42, 84, 190, 83, 78, 211, 110, 69, 4, 226, + 250, 24, 32, 151, 188, 7, 69, 2, 213, 163, 30, 8, 32, 80, 79, 73, 78, 84, + 69, 68, 8, 184, 146, 17, 3, 79, 83, 84, 246, 223, 6, 65, 188, 189, 2, 8, + 69, 82, 80, 69, 78, 68, 73, 67, 203, 131, 4, 76, 4, 128, 139, 29, 3, 73, + 78, 71, 255, 151, 1, 69, 6, 52, 7, 82, 73, 65, 78, 71, 76, 69, 151, 224, + 25, 73, 5, 163, 204, 21, 32, 6, 44, 5, 72, 73, 84, 69, 32, 135, 180, 32, + 90, 4, 206, 215, 30, 66, 211, 24, 83, 6, 226, 198, 26, 77, 252, 138, 4, + 6, 76, 65, 84, 73, 79, 78, 233, 158, 1, 3, 83, 32, 84, 5, 233, 240, 30, + 6, 32, 65, 84, 32, 68, 85, 154, 18, 192, 1, 24, 67, 79, 77, 80, 65, 84, + 73, 66, 73, 76, 73, 84, 89, 32, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, + 144, 3, 8, 82, 65, 68, 73, 67, 65, 76, 32, 245, 17, 7, 83, 84, 82, 79, + 75, 69, 32, 236, 15, 24, 2, 50, 70, 75, 70, 188, 8, 34, 65, 194, 225, 10, + 56, 3, 57, 60, 202, 1, 49, 143, 182, 18, 48, 176, 7, 26, 65, 131, 225, + 10, 57, 176, 3, 134, 1, 54, 142, 182, 18, 48, 2, 49, 2, 50, 2, 51, 2, 52, + 2, 53, 2, 55, 2, 56, 2, 57, 2, 65, 2, 66, 2, 67, 231, 238, 8, 68, 28, + 130, 175, 32, 48, 2, 49, 2, 50, 2, 51, 2, 52, 2, 53, 2, 54, 2, 55, 2, 56, + 2, 57, 2, 65, 2, 66, 2, 67, 3, 68, 230, 1, 210, 1, 66, 126, 67, 226, 4, + 68, 62, 69, 50, 70, 34, 71, 50, 72, 86, 74, 154, 1, 76, 62, 77, 130, 1, + 80, 46, 82, 78, 83, 182, 3, 84, 82, 87, 200, 197, 10, 2, 78, 69, 252, 16, + 4, 75, 78, 73, 70, 159, 225, 11, 79, 14, 74, 79, 192, 229, 10, 4, 82, 85, + 83, 72, 154, 218, 4, 65, 179, 139, 13, 76, 6, 230, 140, 10, 76, 170, 136, + 22, 78, 215, 22, 88, 56, 104, 12, 45, 83, 73, 77, 80, 76, 73, 70, 73, 69, + 68, 32, 162, 3, 73, 50, 76, 234, 168, 31, 79, 175, 78, 72, 44, 114, 69, + 38, 70, 50, 71, 38, 76, 34, 83, 94, 84, 214, 146, 14, 87, 42, 68, 246, + 149, 16, 66, 234, 117, 72, 135, 2, 67, 4, 222, 216, 30, 86, 203, 180, 1, + 65, 6, 146, 196, 30, 73, 214, 211, 1, 76, 235, 16, 82, 4, 234, 195, 22, + 79, 235, 160, 8, 65, 4, 194, 167, 31, 69, 175, 48, 79, 10, 174, 204, 6, + 73, 242, 253, 16, 65, 142, 194, 1, 72, 232, 249, 6, 3, 80, 69, 69, 215, + 11, 69, 6, 214, 10, 85, 176, 155, 10, 2, 65, 78, 143, 255, 3, 79, 4, 156, + 150, 20, 3, 86, 73, 76, 195, 255, 11, 84, 4, 214, 161, 17, 73, 171, 241, + 13, 79, 6, 220, 201, 23, 2, 73, 86, 194, 226, 2, 69, 227, 249, 5, 79, 10, + 196, 6, 2, 65, 84, 254, 136, 32, 87, 3, 89, 4, 198, 133, 31, 73, 247, 79, + 79, 8, 244, 5, 4, 82, 65, 83, 83, 255, 215, 28, 72, 10, 48, 2, 69, 65, + 218, 198, 27, 79, 175, 208, 3, 65, 6, 186, 8, 82, 171, 156, 32, 68, 10, + 72, 12, 45, 83, 73, 77, 80, 76, 73, 70, 73, 69, 68, 32, 135, 151, 30, 65, + 8, 42, 84, 234, 142, 14, 68, 251, 167, 16, 69, 4, 194, 6, 85, 191, 154, + 14, 79, 12, 132, 221, 10, 3, 79, 78, 71, 197, 176, 15, 3, 65, 77, 69, 14, + 18, 69, 35, 79, 4, 174, 134, 32, 65, 159, 27, 83, 10, 148, 220, 10, 3, + 85, 78, 68, 158, 236, 12, 84, 166, 150, 7, 82, 147, 116, 79, 6, 200, 219, + 10, 2, 65, 87, 143, 243, 14, 69, 8, 34, 65, 233, 252, 27, 2, 69, 80, 6, + 202, 209, 31, 73, 214, 79, 77, 3, 80, 38, 122, 69, 90, 73, 186, 1, 78, + 196, 1, 4, 80, 73, 82, 73, 132, 214, 10, 4, 77, 65, 76, 76, 250, 222, 11, + 72, 219, 151, 9, 85, 8, 40, 4, 67, 79, 78, 68, 183, 150, 31, 65, 6, 11, + 32, 6, 230, 178, 30, 84, 203, 83, 79, 12, 60, 9, 77, 80, 76, 73, 70, 73, + 69, 68, 32, 207, 155, 32, 76, 10, 34, 72, 50, 87, 159, 161, 10, 89, 4, + 184, 139, 10, 3, 65, 76, 70, 251, 180, 17, 79, 4, 130, 194, 6, 65, 215, + 183, 21, 72, 6, 192, 1, 2, 79, 85, 211, 236, 31, 65, 8, 58, 85, 174, 142, + 24, 65, 230, 199, 1, 72, 135, 143, 3, 73, 2, 243, 187, 23, 82, 12, 26, + 65, 49, 2, 69, 83, 8, 176, 214, 10, 2, 76, 75, 1, 3, 84, 69, 82, 4, 131, + 214, 10, 84, 72, 110, 72, 162, 1, 80, 38, 83, 226, 161, 30, 84, 172, 247, + 1, 2, 66, 88, 2, 87, 2, 88, 86, 68, 2, 78, 3, 81, 29, 50, 80, 22, 90, + 136, 154, 32, 2, 88, 87, 87, 71, 5, 155, 154, 32, 87, 19, 50, 90, 150, + 162, 30, 87, 150, 248, 1, 71, 3, 84, 9, 146, 162, 30, 90, 151, 248, 1, + 80, 9, 130, 154, 32, 68, 2, 71, 3, 90, 21, 50, 87, 30, 90, 146, 153, 32, + 71, 2, 80, 3, 84, 7, 170, 153, 32, 71, 3, 90, 7, 186, 152, 32, 87, 87, + 90, 124, 62, 65, 194, 1, 73, 114, 79, 173, 181, 20, 4, 69, 65, 82, 32, 8, + 132, 1, 2, 80, 80, 252, 177, 18, 6, 83, 83, 73, 67, 65, 76, 241, 187, 12, + 14, 77, 83, 72, 69, 76, 76, 32, 77, 79, 66, 73, 76, 69, 32, 4, 144, 130, + 19, 5, 73, 78, 71, 32, 72, 199, 226, 1, 69, 6, 48, 6, 78, 75, 73, 78, 71, + 32, 207, 255, 30, 80, 4, 234, 198, 24, 71, 229, 169, 3, 6, 66, 69, 69, + 82, 32, 77, 108, 72, 2, 67, 75, 140, 10, 2, 83, 69, 236, 3, 2, 85, 68, + 227, 154, 29, 87, 70, 64, 6, 32, 70, 65, 67, 69, 32, 237, 2, 5, 87, 73, + 83, 69, 32, 48, 58, 69, 46, 70, 36, 2, 78, 73, 2, 79, 18, 83, 51, 84, 8, + 120, 2, 76, 69, 125, 4, 73, 71, 72, 84, 8, 178, 1, 73, 25, 3, 79, 85, 82, + 4, 155, 1, 78, 8, 26, 69, 125, 2, 73, 88, 4, 57, 2, 86, 69, 16, 38, 69, + 14, 87, 41, 3, 72, 82, 69, 4, 63, 78, 8, 24, 2, 69, 76, 27, 79, 4, 11, + 86, 4, 11, 69, 4, 196, 164, 28, 2, 32, 79, 213, 131, 2, 3, 45, 84, 72, + 22, 90, 67, 58, 68, 122, 71, 48, 5, 82, 73, 71, 72, 84, 226, 2, 84, 122, + 79, 247, 135, 30, 73, 4, 196, 1, 3, 76, 79, 83, 141, 99, 4, 79, 78, 84, + 79, 2, 141, 3, 26, 79, 87, 78, 87, 65, 82, 68, 83, 32, 65, 78, 68, 32, + 85, 80, 87, 65, 82, 68, 83, 32, 79, 80, 69, 78, 32, 2, 21, 3, 65, 80, 80, + 2, 133, 4, 2, 69, 68, 6, 228, 1, 14, 32, 65, 78, 68, 32, 76, 69, 70, 84, + 32, 83, 69, 77, 73, 45, 38, 87, 65, 82, 68, 83, 32, 65, 78, 68, 32, 76, + 69, 70, 84, 87, 65, 82, 68, 83, 32, 79, 80, 69, 78, 32, 67, 73, 82, 67, + 76, 69, 32, 65, 82, 82, 79, 87, 83, 2, 129, 184, 29, 6, 67, 73, 82, 67, + 76, 69, 5, 161, 83, 15, 32, 87, 73, 84, 72, 32, 67, 73, 82, 67, 76, 69, + 68, 32, 79, 4, 82, 79, 37, 16, 82, 73, 65, 78, 71, 76, 69, 45, 72, 69, + 65, 68, 69, 68, 32, 79, 2, 69, 6, 80, 32, 83, 69, 77, 73, 2, 21, 3, 80, + 69, 78, 2, 11, 32, 2, 161, 182, 29, 4, 67, 73, 82, 67, 26, 32, 2, 68, 32, + 167, 149, 31, 32, 24, 216, 1, 2, 83, 85, 66, 85, 254, 243, 18, 77, 180, + 3, 9, 76, 79, 67, 75, 32, 87, 73, 84, 72, 222, 192, 11, 66, 145, 147, 1, + 23, 73, 78, 84, 69, 82, 83, 69, 67, 84, 73, 79, 78, 32, 87, 73, 84, 72, + 32, 83, 69, 82, 73, 70, 8, 30, 66, 1, 3, 80, 69, 82, 4, 145, 177, 24, 3, + 83, 69, 84, 6, 82, 77, 33, 16, 78, 73, 79, 78, 32, 87, 73, 84, 72, 32, + 83, 69, 82, 73, 70, 83, 2, 197, 148, 24, 3, 66, 82, 69, 5, 221, 248, 30, + 9, 32, 65, 78, 68, 32, 83, 77, 65, 83, 11, 33, 6, 32, 87, 73, 84, 72, 32, + 8, 72, 4, 84, 79, 82, 78, 190, 162, 5, 76, 146, 151, 19, 83, 215, 161, 6, + 82, 2, 155, 140, 25, 65, 226, 9, 158, 1, 67, 82, 76, 98, 77, 162, 82, 78, + 220, 5, 2, 79, 75, 58, 80, 154, 19, 82, 138, 1, 85, 186, 165, 27, 87, + 160, 242, 2, 2, 70, 70, 234, 47, 73, 171, 51, 65, 6, 26, 75, 139, 149, 4, + 79, 4, 186, 214, 8, 82, 129, 151, 22, 4, 84, 65, 73, 76, 8, 44, 2, 79, + 78, 209, 187, 24, 3, 76, 73, 83, 7, 11, 32, 4, 146, 178, 25, 69, 171, + 203, 5, 83, 158, 6, 72, 7, 66, 73, 78, 73, 78, 71, 32, 166, 80, 77, 94, + 80, 239, 149, 31, 69, 142, 6, 214, 2, 65, 174, 2, 66, 134, 1, 67, 246, + 12, 68, 174, 9, 69, 146, 2, 70, 54, 71, 140, 9, 2, 72, 79, 82, 73, 216, + 1, 2, 75, 65, 162, 1, 76, 230, 13, 77, 250, 1, 78, 78, 79, 138, 2, 80, + 174, 1, 82, 244, 4, 5, 90, 73, 71, 90, 65, 166, 2, 83, 242, 3, 84, 238, + 2, 85, 148, 1, 9, 86, 69, 82, 84, 73, 67, 65, 76, 32, 36, 2, 87, 73, 183, + 1, 88, 24, 148, 1, 4, 67, 85, 84, 69, 86, 78, 168, 185, 24, 6, 83, 84, + 69, 82, 73, 83, 201, 172, 5, 14, 76, 77, 79, 83, 84, 32, 69, 81, 85, 65, + 76, 32, 84, 79, 10, 22, 45, 167, 33, 32, 4, 180, 164, 12, 6, 71, 82, 65, + 86, 69, 45, 195, 193, 3, 77, 6, 244, 2, 4, 84, 73, 67, 76, 177, 180, 3, + 4, 78, 85, 73, 84, 12, 42, 82, 129, 215, 29, 4, 73, 78, 68, 85, 10, 48, + 3, 69, 86, 69, 197, 228, 29, 3, 73, 68, 71, 7, 162, 252, 11, 45, 183, + 218, 17, 32, 142, 1, 142, 1, 65, 34, 76, 98, 79, 116, 8, 89, 82, 73, 76, + 76, 73, 67, 32, 184, 28, 11, 73, 82, 67, 85, 77, 70, 76, 69, 88, 32, 65, + 175, 238, 11, 69, 6, 162, 18, 82, 199, 131, 28, 78, 4, 41, 8, 79, 67, 75, + 87, 73, 83, 69, 32, 4, 184, 131, 12, 4, 82, 73, 78, 71, 239, 160, 16, 65, + 10, 76, 4, 77, 77, 65, 32, 189, 16, 10, 78, 74, 79, 73, 78, 73, 78, 71, + 32, 77, 6, 250, 229, 12, 65, 247, 251, 16, 66, 116, 252, 1, 8, 72, 85, + 78, 68, 82, 69, 68, 32, 32, 7, 76, 69, 84, 84, 69, 82, 32, 166, 5, 80, + 116, 5, 68, 65, 83, 73, 65, 38, 84, 106, 77, 206, 243, 2, 75, 132, 214, + 12, 15, 83, 77, 65, 76, 76, 32, 76, 69, 84, 84, 69, 82, 32, 66, 89, 217, + 241, 15, 2, 86, 90, 4, 194, 7, 77, 215, 158, 3, 84, 84, 238, 1, 66, 38, + 68, 50, 69, 82, 73, 106, 79, 22, 83, 66, 85, 30, 89, 214, 137, 3, 76, + 140, 5, 5, 77, 79, 78, 79, 71, 142, 18, 72, 202, 174, 12, 84, 190, 163, + 15, 90, 254, 82, 67, 2, 71, 182, 8, 70, 134, 14, 80, 2, 86, 158, 20, 75, + 187, 2, 65, 4, 174, 147, 6, 73, 199, 226, 25, 69, 4, 168, 155, 25, 3, 74, + 69, 82, 167, 218, 6, 69, 14, 58, 83, 230, 244, 31, 70, 2, 76, 2, 77, 2, + 78, 3, 82, 5, 183, 176, 30, 45, 11, 56, 8, 79, 84, 73, 70, 73, 69, 68, + 32, 151, 244, 31, 69, 6, 194, 145, 6, 66, 210, 226, 25, 65, 3, 69, 5, + 239, 243, 24, 77, 6, 26, 72, 155, 209, 15, 79, 4, 250, 251, 29, 67, 191, + 247, 1, 65, 5, 193, 153, 3, 2, 75, 82, 8, 142, 230, 27, 69, 190, 240, 3, + 65, 174, 28, 73, 3, 85, 8, 66, 65, 48, 4, 83, 73, 76, 73, 133, 212, 28, + 4, 79, 75, 82, 89, 4, 170, 246, 2, 89, 241, 175, 12, 3, 76, 65, 84, 2, + 145, 13, 5, 32, 80, 78, 69, 85, 10, 80, 2, 69, 78, 0, 7, 72, 79, 85, 83, + 65, 78, 68, 177, 8, 4, 73, 84, 76, 79, 2, 17, 2, 32, 77, 2, 169, 164, 21, + 5, 73, 76, 76, 73, 79, 110, 62, 69, 244, 1, 8, 73, 65, 69, 82, 69, 83, + 73, 83, 39, 79, 38, 68, 9, 86, 65, 78, 65, 71, 65, 82, 73, 32, 249, 133, + 31, 2, 76, 69, 36, 92, 7, 76, 69, 84, 84, 69, 82, 32, 240, 179, 25, 6, + 83, 73, 71, 78, 32, 65, 167, 204, 4, 68, 14, 214, 218, 31, 86, 162, 17, + 75, 2, 78, 2, 80, 2, 82, 186, 2, 65, 3, 85, 7, 246, 140, 27, 45, 151, + 186, 2, 32, 66, 58, 84, 128, 1, 4, 85, 66, 76, 69, 241, 4, 2, 87, 78, 14, + 38, 32, 149, 215, 15, 3, 84, 69, 68, 10, 64, 5, 65, 66, 79, 86, 69, 241, + 165, 6, 5, 66, 69, 76, 79, 87, 7, 151, 193, 31, 32, 48, 22, 32, 191, 4, + 68, 46, 230, 1, 66, 0, 10, 73, 78, 86, 69, 82, 84, 69, 68, 32, 66, 26, + 77, 54, 79, 34, 80, 68, 2, 82, 73, 48, 5, 84, 73, 76, 68, 69, 80, 9, 86, + 69, 82, 84, 73, 67, 65, 76, 32, 174, 210, 15, 65, 42, 71, 166, 179, 4, + 76, 187, 228, 10, 67, 4, 229, 16, 2, 82, 69, 4, 21, 3, 65, 67, 82, 4, + 181, 193, 16, 2, 79, 78, 4, 230, 35, 80, 255, 224, 29, 86, 6, 238, 36, + 76, 205, 206, 7, 9, 65, 82, 69, 78, 84, 72, 69, 83, 69, 4, 156, 51, 4, + 71, 72, 84, 87, 139, 228, 9, 78, 7, 11, 32, 4, 44, 3, 76, 69, 70, 1, 4, + 82, 73, 71, 72, 2, 199, 205, 29, 84, 6, 178, 239, 11, 83, 211, 255, 13, + 76, 2, 141, 205, 15, 2, 32, 67, 4, 128, 41, 2, 32, 84, 227, 158, 30, 87, + 16, 76, 9, 78, 67, 76, 79, 83, 73, 78, 71, 32, 129, 193, 25, 4, 81, 85, + 65, 76, 14, 132, 1, 6, 67, 73, 82, 67, 76, 69, 22, 83, 216, 145, 6, 3, + 75, 69, 89, 160, 241, 1, 7, 85, 80, 87, 65, 82, 68, 32, 227, 166, 22, 68, + 5, 219, 254, 17, 32, 4, 134, 138, 25, 67, 195, 186, 5, 81, 4, 32, 2, 69, + 82, 135, 137, 5, 79, 2, 143, 74, 77, 126, 88, 17, 76, 65, 71, 79, 76, 73, + 84, 73, 67, 32, 76, 69, 84, 84, 69, 82, 32, 143, 3, 82, 76, 238, 1, 68, + 30, 73, 46, 83, 50, 84, 182, 250, 5, 65, 22, 66, 94, 67, 134, 1, 70, 38, + 71, 238, 2, 77, 32, 2, 76, 74, 34, 78, 88, 2, 80, 79, 30, 82, 194, 2, 86, + 22, 89, 90, 90, 182, 199, 18, 72, 142, 243, 1, 85, 154, 253, 4, 79, 235, + 5, 75, 4, 238, 252, 5, 74, 31, 79, 11, 250, 253, 5, 78, 54, 79, 135, 182, + 25, 90, 8, 218, 254, 5, 77, 130, 4, 76, 243, 204, 20, 72, 4, 142, 131, 6, + 86, 255, 201, 25, 83, 50, 38, 65, 173, 3, 4, 69, 69, 75, 32, 36, 84, 5, + 78, 84, 72, 65, 32, 196, 1, 2, 86, 69, 153, 228, 27, 5, 80, 72, 69, 77, + 69, 24, 68, 6, 68, 73, 71, 73, 84, 32, 65, 7, 76, 69, 84, 84, 69, 82, 32, + 14, 202, 177, 16, 83, 142, 192, 13, 70, 70, 84, 62, 90, 143, 83, 79, 10, + 222, 202, 31, 86, 162, 17, 75, 2, 78, 2, 80, 187, 2, 65, 10, 18, 32, 67, + 45, 6, 26, 65, 215, 242, 15, 84, 4, 245, 143, 4, 4, 67, 67, 69, 78, 4, + 208, 220, 11, 6, 65, 67, 85, 84, 69, 45, 195, 231, 3, 77, 14, 148, 1, 8, + 77, 85, 83, 73, 67, 65, 76, 32, 150, 151, 4, 75, 250, 182, 2, 80, 174, 4, + 89, 249, 227, 3, 11, 68, 73, 65, 76, 89, 84, 73, 75, 65, 32, 84, 6, 26, + 84, 131, 135, 15, 80, 4, 218, 135, 15, 69, 35, 82, 6, 206, 200, 12, 79, + 216, 149, 18, 8, 77, 79, 84, 72, 69, 84, 73, 67, 163, 45, 82, 14, 26, 78, + 207, 179, 29, 83, 12, 52, 7, 86, 69, 82, 84, 69, 68, 32, 143, 222, 27, + 70, 10, 64, 2, 66, 82, 45, 10, 68, 79, 85, 66, 76, 69, 32, 65, 82, 67, 6, + 22, 69, 235, 37, 73, 4, 211, 181, 11, 86, 4, 167, 192, 29, 72, 8, 128, 1, + 16, 84, 65, 75, 65, 78, 65, 45, 72, 73, 82, 65, 71, 65, 78, 65, 32, 153, + 180, 17, 9, 86, 89, 75, 65, 32, 65, 66, 79, 86, 4, 146, 237, 9, 83, 35, + 86, 158, 1, 80, 5, 65, 84, 73, 78, 32, 156, 8, 3, 69, 70, 84, 184, 3, 2, + 73, 71, 83, 79, 106, 156, 1, 21, 76, 69, 84, 84, 69, 82, 32, 83, 77, 65, + 76, 76, 32, 67, 65, 80, 73, 84, 65, 76, 32, 53, 13, 83, 77, 65, 76, 76, + 32, 76, 69, 84, 84, 69, 82, 32, 10, 218, 213, 31, 71, 2, 76, 2, 77, 2, + 78, 3, 82, 96, 226, 1, 65, 70, 67, 34, 69, 30, 70, 78, 73, 86, 76, 106, + 79, 2, 85, 134, 1, 82, 50, 84, 206, 131, 12, 83, 194, 134, 2, 66, 226, + 156, 2, 87, 158, 168, 15, 68, 2, 71, 2, 72, 2, 75, 2, 77, 2, 78, 2, 80, + 2, 86, 2, 88, 3, 90, 13, 142, 244, 2, 32, 146, 235, 12, 76, 166, 244, 15, + 69, 2, 79, 3, 86, 5, 221, 227, 11, 3, 32, 67, 69, 7, 206, 209, 31, 83, 3, + 84, 5, 185, 219, 26, 14, 76, 65, 84, 84, 69, 78, 69, 68, 32, 79, 80, 69, + 78, 32, 11, 37, 7, 78, 83, 85, 76, 65, 82, 32, 8, 206, 209, 31, 68, 2, + 71, 2, 82, 3, 84, 7, 136, 210, 15, 14, 32, 87, 73, 84, 72, 32, 68, 79, + 85, 66, 76, 69, 32, 77, 165, 172, 12, 3, 79, 78, 71, 7, 33, 6, 32, 87, + 73, 84, 72, 32, 4, 194, 243, 11, 68, 201, 187, 12, 15, 76, 73, 71, 72, + 84, 32, 67, 69, 78, 84, 82, 65, 76, 73, 90, 7, 11, 32, 4, 146, 210, 11, + 82, 227, 228, 17, 66, 5, 129, 26, 6, 85, 82, 78, 69, 68, 32, 32, 46, 32, + 213, 2, 6, 87, 65, 82, 68, 83, 32, 28, 154, 1, 65, 112, 12, 80, 65, 82, + 69, 78, 84, 72, 69, 83, 73, 83, 32, 226, 12, 72, 182, 1, 84, 177, 165, + 29, 11, 82, 73, 71, 72, 84, 32, 65, 82, 82, 79, 87, 12, 48, 4, 82, 82, + 79, 87, 233, 179, 29, 2, 78, 71, 8, 26, 72, 243, 179, 29, 32, 4, 225, + 179, 29, 3, 69, 65, 68, 4, 244, 204, 7, 4, 65, 66, 79, 86, 245, 204, 23, + 5, 66, 69, 76, 79, 87, 4, 230, 13, 72, 133, 198, 11, 5, 65, 82, 82, 79, + 87, 10, 52, 6, 65, 84, 85, 82, 69, 32, 169, 17, 2, 72, 84, 8, 238, 1, 76, + 23, 82, 10, 36, 3, 78, 71, 32, 251, 176, 30, 87, 8, 172, 7, 7, 68, 79, + 85, 66, 76, 69, 32, 246, 7, 83, 71, 86, 20, 52, 5, 65, 67, 82, 79, 78, + 145, 164, 25, 2, 73, 78, 19, 18, 32, 127, 45, 10, 34, 76, 22, 82, 183, + 176, 29, 66, 4, 41, 2, 69, 70, 4, 21, 3, 73, 71, 72, 4, 181, 160, 16, 6, + 84, 32, 72, 65, 76, 70, 6, 166, 246, 11, 71, 186, 2, 65, 139, 157, 3, 66, + 4, 152, 9, 9, 85, 77, 66, 69, 82, 32, 83, 73, 71, 177, 173, 11, 2, 79, + 84, 18, 136, 1, 17, 76, 68, 32, 80, 69, 82, 77, 73, 67, 32, 76, 69, 84, + 84, 69, 82, 32, 82, 80, 248, 243, 11, 4, 71, 79, 78, 69, 135, 237, 17, + 86, 10, 246, 43, 90, 206, 218, 17, 78, 186, 253, 8, 68, 138, 134, 2, 83, + 203, 236, 1, 65, 2, 213, 128, 24, 6, 69, 78, 32, 77, 65, 82, 12, 18, 65, + 107, 76, 8, 236, 7, 9, 82, 69, 78, 84, 72, 69, 83, 69, 83, 141, 248, 23, + 9, 76, 65, 84, 65, 76, 73, 90, 69, 68, 4, 197, 171, 29, 7, 85, 83, 32, + 83, 73, 71, 78, 38, 18, 69, 127, 73, 6, 72, 5, 86, 69, 82, 83, 69, 133, + 254, 23, 7, 84, 82, 79, 70, 76, 69, 88, 4, 22, 32, 227, 12, 68, 2, 141, + 8, 2, 83, 79, 32, 40, 3, 71, 72, 84, 157, 5, 2, 78, 71, 26, 50, 32, 149, + 4, 7, 87, 65, 82, 68, 83, 32, 72, 24, 104, 5, 65, 82, 82, 79, 87, 218, 1, + 72, 124, 12, 80, 65, 82, 69, 78, 84, 72, 69, 83, 73, 83, 32, 59, 84, 12, + 44, 5, 72, 69, 65, 68, 32, 155, 168, 29, 32, 8, 26, 65, 155, 168, 29, 66, + 6, 36, 3, 78, 68, 32, 219, 195, 30, 66, 4, 40, 4, 68, 79, 87, 78, 1, 2, + 85, 80, 2, 157, 203, 8, 9, 32, 65, 82, 82, 79, 87, 72, 69, 65, 6, 11, 65, + 6, 48, 6, 76, 70, 32, 82, 73, 78, 21, 2, 82, 80, 4, 163, 166, 29, 71, 2, + 17, 2, 79, 79, 2, 231, 193, 30, 78, 4, 174, 198, 9, 65, 137, 170, 20, 5, + 66, 69, 76, 79, 87, 2, 149, 249, 23, 2, 65, 67, 2, 233, 201, 20, 16, 65, + 82, 80, 79, 79, 78, 32, 87, 73, 84, 72, 32, 66, 65, 82, 66, 6, 11, 32, 6, + 182, 197, 11, 79, 166, 223, 17, 66, 223, 155, 1, 65, 18, 188, 1, 5, 72, + 79, 82, 84, 32, 160, 1, 7, 81, 85, 65, 82, 69, 32, 66, 56, 5, 84, 82, 79, + 78, 71, 232, 193, 3, 2, 85, 83, 148, 179, 20, 2, 78, 65, 233, 157, 5, 6, + 69, 65, 71, 85, 76, 76, 6, 18, 83, 71, 86, 4, 26, 79, 223, 194, 11, 84, + 2, 253, 194, 11, 5, 76, 73, 68, 85, 83, 2, 49, 10, 69, 82, 84, 73, 67, + 65, 76, 32, 76, 73, 2, 151, 194, 11, 78, 4, 148, 196, 7, 5, 82, 65, 67, + 75, 69, 191, 221, 21, 69, 2, 225, 244, 23, 17, 32, 67, 69, 78, 84, 82, + 65, 76, 73, 90, 65, 84, 73, 79, 78, 32, 83, 20, 98, 72, 32, 4, 73, 76, + 68, 69, 136, 1, 6, 82, 73, 80, 76, 69, 32, 69, 5, 85, 82, 78, 69, 68, 2, + 137, 194, 7, 3, 82, 69, 69, 11, 11, 32, 8, 76, 3, 76, 69, 70, 0, 4, 82, + 73, 71, 72, 182, 191, 11, 79, 167, 223, 17, 66, 2, 169, 144, 29, 6, 84, + 32, 72, 65, 76, 70, 6, 186, 161, 15, 65, 184, 132, 15, 5, 85, 78, 68, 69, + 82, 199, 64, 68, 2, 145, 252, 14, 2, 32, 67, 10, 34, 80, 238, 184, 30, + 82, 3, 83, 6, 42, 87, 141, 240, 23, 4, 32, 84, 65, 67, 2, 45, 9, 65, 82, + 68, 83, 32, 65, 82, 82, 79, 2, 159, 142, 29, 87, 6, 158, 188, 25, 76, + 171, 183, 2, 84, 6, 52, 3, 68, 69, 32, 133, 189, 11, 4, 71, 71, 76, 89, + 4, 92, 12, 73, 78, 86, 69, 82, 84, 69, 68, 32, 66, 82, 73, 161, 165, 28, + 5, 66, 82, 73, 68, 71, 2, 241, 238, 23, 2, 68, 71, 6, 178, 196, 11, 45, + 147, 214, 17, 32, 6, 52, 7, 69, 82, 67, 73, 65, 76, 32, 191, 178, 31, 65, + 4, 206, 152, 28, 77, 195, 253, 2, 65, 8, 178, 140, 8, 82, 144, 221, 15, + 3, 79, 83, 73, 246, 225, 2, 76, 171, 208, 3, 65, 38, 214, 1, 70, 84, 10, + 83, 84, 82, 85, 67, 84, 73, 79, 78, 32, 46, 84, 172, 236, 2, 8, 86, 69, + 78, 73, 69, 78, 67, 69, 172, 237, 17, 6, 73, 67, 65, 76, 32, 84, 170, + 243, 8, 74, 133, 97, 7, 71, 82, 85, 69, 78, 84, 32, 6, 168, 187, 26, 4, + 69, 84, 84, 73, 162, 214, 1, 85, 229, 141, 2, 4, 79, 85, 78, 68, 4, 240, + 144, 20, 2, 87, 79, 219, 151, 10, 83, 20, 80, 5, 65, 73, 78, 83, 32, 198, + 1, 79, 28, 4, 82, 79, 76, 32, 199, 146, 3, 73, 12, 48, 3, 65, 83, 32, 93, + 5, 87, 73, 84, 72, 32, 6, 242, 205, 23, 77, 253, 7, 15, 78, 79, 82, 77, + 65, 76, 32, 83, 85, 66, 71, 82, 79, 85, 80, 6, 162, 190, 4, 76, 218, 144, + 19, 86, 223, 196, 4, 79, 2, 193, 168, 29, 2, 85, 82, 4, 232, 176, 19, 3, + 75, 78, 79, 173, 242, 3, 8, 83, 69, 81, 85, 69, 78, 67, 69, 6, 26, 73, + 175, 158, 2, 69, 4, 250, 170, 31, 78, 87, 69, 206, 2, 36, 4, 84, 73, 67, + 32, 175, 18, 89, 202, 2, 186, 1, 67, 204, 1, 6, 69, 80, 65, 67, 84, 32, + 86, 70, 36, 11, 79, 76, 68, 32, 78, 85, 66, 73, 65, 78, 32, 110, 83, 129, + 133, 28, 13, 77, 79, 82, 80, 72, 79, 76, 79, 71, 73, 67, 65, 76, 126, 76, + 9, 79, 77, 66, 73, 78, 73, 78, 71, 32, 161, 3, 5, 65, 80, 73, 84, 65, 6, + 68, 9, 83, 80, 73, 82, 73, 84, 85, 83, 32, 189, 171, 30, 2, 78, 73, 4, + 196, 135, 6, 2, 76, 69, 161, 198, 16, 2, 65, 83, 56, 184, 211, 19, 8, 84, + 72, 79, 85, 83, 65, 78, 68, 166, 146, 1, 78, 195, 190, 2, 68, 4, 230, + 241, 17, 82, 203, 234, 10, 85, 8, 58, 68, 0, 3, 73, 78, 68, 146, 15, 86, + 183, 204, 28, 70, 2, 145, 220, 28, 7, 73, 82, 69, 67, 84, 32, 81, 134, 1, + 56, 3, 77, 65, 76, 197, 11, 6, 89, 77, 66, 79, 76, 32, 120, 45, 9, 76, + 32, 76, 69, 84, 84, 69, 82, 32, 120, 138, 2, 65, 48, 6, 66, 79, 72, 65, + 73, 82, 32, 2, 67, 82, 170, 1, 68, 160, 1, 2, 71, 65, 34, 72, 38, 75, 46, + 70, 34, 76, 66, 79, 138, 3, 83, 90, 84, 46, 90, 146, 197, 5, 86, 210, 55, + 80, 206, 203, 3, 73, 138, 179, 21, 82, 198, 3, 69, 218, 7, 77, 2, 78, + 163, 17, 85, 4, 44, 5, 75, 72, 77, 73, 77, 143, 134, 19, 76, 2, 177, 1, + 4, 73, 67, 32, 75, 10, 92, 12, 89, 80, 84, 79, 71, 82, 65, 77, 77, 73, + 67, 32, 53, 7, 79, 83, 83, 69, 68, 32, 83, 8, 50, 83, 226, 4, 71, 170, + 129, 31, 69, 219, 7, 78, 2, 215, 144, 24, 72, 12, 80, 9, 73, 65, 76, 69, + 67, 84, 45, 80, 32, 204, 251, 30, 2, 65, 76, 175, 17, 69, 8, 222, 137, 8, + 72, 162, 245, 7, 65, 240, 252, 11, 2, 75, 65, 139, 145, 3, 78, 4, 190, 3, + 78, 183, 251, 30, 77, 4, 250, 150, 24, 79, 191, 196, 5, 65, 8, 42, 72, + 182, 250, 27, 65, 139, 145, 3, 83, 4, 186, 139, 31, 69, 219, 19, 73, 4, + 224, 131, 19, 7, 45, 83, 72, 65, 80, 69, 68, 207, 212, 7, 65, 35, 36, 3, + 76, 68, 32, 167, 249, 30, 79, 30, 76, 7, 67, 79, 80, 84, 73, 67, 32, 193, + 1, 7, 78, 85, 66, 73, 65, 78, 32, 22, 98, 71, 42, 72, 188, 1, 2, 83, 72, + 238, 169, 14, 68, 190, 224, 9, 79, 178, 171, 5, 69, 227, 101, 65, 2, 17, + 2, 65, 78, 2, 171, 199, 15, 71, 8, 198, 147, 24, 79, 246, 211, 1, 65, + 159, 161, 5, 69, 8, 50, 78, 176, 253, 15, 2, 83, 72, 163, 139, 5, 87, 4, + 238, 135, 31, 71, 3, 89, 10, 54, 72, 178, 137, 6, 65, 222, 236, 24, 79, + 219, 3, 73, 4, 226, 249, 30, 73, 187, 13, 69, 4, 196, 237, 30, 3, 72, 69, + 84, 167, 8, 65, 2, 219, 245, 30, 65, 14, 62, 75, 30, 77, 2, 80, 22, 83, + 253, 146, 27, 3, 84, 65, 85, 4, 26, 72, 227, 133, 31, 65, 2, 143, 147, + 27, 73, 4, 136, 251, 15, 6, 72, 73, 77, 65, 32, 83, 145, 246, 3, 3, 84, + 65, 85, 4, 220, 252, 23, 3, 76, 69, 70, 157, 133, 2, 4, 82, 73, 71, 72, + 6, 96, 6, 78, 73, 83, 72, 32, 86, 252, 240, 24, 8, 82, 69, 83, 80, 79, + 78, 68, 83, 163, 157, 5, 65, 2, 157, 246, 27, 4, 69, 82, 83, 69, 44, 104, + 2, 78, 84, 208, 132, 3, 6, 67, 72, 32, 65, 78, 68, 181, 138, 27, 8, 80, + 76, 69, 32, 87, 73, 84, 72, 40, 56, 2, 69, 82, 33, 8, 73, 78, 71, 32, 82, + 79, 68, 32, 4, 158, 221, 26, 66, 235, 121, 83, 36, 48, 4, 84, 69, 78, 83, + 1, 4, 85, 78, 73, 84, 18, 185, 145, 23, 2, 32, 68, 51, 82, 69, 76, 5, 73, + 67, 75, 69, 84, 34, 79, 254, 5, 85, 50, 89, 239, 210, 29, 65, 4, 220, + 148, 8, 3, 68, 73, 84, 153, 238, 19, 7, 83, 67, 69, 78, 84, 32, 77, 5, + 237, 158, 26, 3, 32, 66, 65, 28, 84, 2, 83, 83, 228, 244, 28, 3, 67, 79, + 68, 188, 148, 1, 3, 73, 83, 83, 243, 57, 87, 22, 46, 32, 240, 2, 3, 69, + 68, 32, 223, 1, 73, 14, 44, 3, 79, 70, 32, 82, 80, 151, 208, 30, 77, 4, + 236, 202, 27, 6, 74, 69, 82, 85, 83, 65, 245, 173, 2, 5, 76, 79, 82, 82, + 65, 8, 76, 10, 65, 84, 84, 89, 32, 87, 73, 84, 72, 32, 97, 5, 79, 77, 77, + 69, 69, 4, 44, 3, 76, 69, 70, 1, 4, 82, 73, 71, 72, 2, 241, 192, 28, 7, + 84, 32, 67, 82, 79, 83, 83, 5, 233, 161, 3, 11, 32, 87, 73, 84, 72, 32, + 72, 65, 76, 70, 45, 6, 196, 181, 24, 37, 78, 69, 71, 65, 84, 73, 86, 69, + 32, 83, 81, 85, 65, 82, 69, 68, 32, 76, 65, 84, 73, 78, 32, 67, 65, 80, + 73, 84, 65, 76, 32, 76, 69, 84, 84, 69, 82, 160, 212, 2, 2, 70, 76, 137, + 169, 2, 3, 83, 87, 79, 2, 141, 160, 23, 5, 78, 71, 32, 76, 65, 4, 228, + 145, 17, 3, 90, 69, 73, 179, 217, 13, 84, 6, 194, 159, 19, 73, 137, 249, + 6, 4, 83, 84, 65, 76, 204, 19, 154, 1, 66, 20, 8, 78, 69, 73, 70, 79, 82, + 77, 32, 138, 250, 1, 80, 114, 82, 172, 3, 2, 83, 84, 254, 165, 15, 67, + 209, 194, 9, 6, 84, 32, 79, 70, 32, 77, 2, 207, 160, 5, 69, 168, 19, 176, + 1, 13, 78, 85, 77, 69, 82, 73, 67, 32, 83, 73, 71, 78, 32, 184, 20, 17, + 80, 85, 78, 67, 84, 85, 65, 84, 73, 79, 78, 32, 83, 73, 71, 78, 32, 233, + 1, 5, 83, 73, 71, 78, 32, 222, 1, 78, 69, 166, 2, 70, 152, 3, 2, 78, 73, + 154, 2, 79, 130, 3, 83, 151, 4, 84, 24, 68, 5, 73, 71, 72, 84, 32, 153, + 1, 7, 76, 65, 77, 73, 84, 69, 32, 16, 142, 14, 83, 214, 113, 85, 238, 50, + 71, 136, 56, 17, 86, 65, 82, 73, 65, 78, 84, 32, 70, 79, 82, 77, 32, 85, + 83, 83, 85, 186, 223, 25, 68, 171, 217, 1, 65, 8, 136, 197, 20, 5, 79, + 78, 69, 32, 84, 250, 214, 8, 70, 175, 14, 84, 58, 48, 4, 73, 86, 69, 32, + 125, 4, 79, 85, 82, 32, 26, 70, 83, 206, 1, 66, 250, 12, 65, 82, 71, 250, + 109, 85, 175, 202, 26, 68, 6, 182, 15, 72, 165, 212, 18, 5, 73, 88, 84, + 72, 83, 32, 150, 1, 66, 44, 18, 86, 65, 82, 73, 65, 78, 84, 32, 70, 79, + 82, 77, 32, 76, 73, 77, 77, 85, 206, 12, 65, 82, 71, 26, 83, 226, 109, + 85, 175, 202, 26, 68, 6, 188, 123, 3, 65, 78, 50, 139, 252, 25, 85, 9, + 194, 156, 12, 32, 195, 231, 18, 52, 24, 44, 4, 71, 73, 68, 65, 33, 3, 78, + 69, 32, 4, 146, 158, 29, 69, 227, 101, 77, 20, 156, 1, 19, 86, 65, 82, + 73, 65, 78, 84, 32, 70, 79, 82, 77, 32, 73, 76, 73, 77, 77, 85, 174, 7, + 83, 214, 113, 85, 238, 50, 71, 194, 151, 26, 68, 171, 217, 1, 65, 9, 182, + 255, 30, 32, 186, 2, 51, 3, 52, 28, 92, 16, 76, 68, 32, 65, 83, 83, 89, + 82, 73, 65, 78, 32, 79, 78, 69, 32, 37, 3, 78, 69, 32, 4, 170, 134, 18, + 83, 203, 250, 10, 81, 24, 166, 1, 69, 52, 8, 81, 85, 65, 82, 84, 69, 82, + 32, 206, 7, 66, 54, 71, 84, 5, 84, 72, 73, 82, 68, 224, 244, 23, 2, 83, + 72, 241, 136, 6, 6, 72, 65, 76, 70, 32, 71, 4, 158, 8, 83, 189, 164, 1, + 5, 73, 71, 72, 84, 72, 4, 202, 153, 29, 65, 219, 108, 71, 38, 144, 1, 5, + 69, 86, 69, 78, 32, 188, 1, 20, 72, 65, 82, 50, 32, 84, 73, 77, 69, 83, + 32, 71, 65, 76, 32, 80, 76, 85, 83, 32, 37, 3, 73, 88, 32, 18, 148, 1, + 17, 86, 65, 82, 73, 65, 78, 84, 32, 70, 79, 82, 77, 32, 73, 77, 73, 78, + 218, 1, 83, 214, 113, 85, 238, 50, 71, 194, 151, 26, 68, 171, 217, 1, 65, + 6, 218, 148, 12, 32, 195, 231, 18, 51, 4, 178, 189, 27, 68, 139, 191, 2, + 77, 16, 142, 1, 83, 142, 3, 65, 202, 110, 85, 238, 50, 71, 220, 130, 26, + 16, 86, 65, 82, 73, 65, 78, 84, 32, 70, 79, 82, 77, 32, 65, 83, 72, 231, + 20, 68, 2, 227, 61, 72, 50, 52, 5, 72, 82, 69, 69, 32, 241, 1, 3, 87, 79, + 32, 28, 142, 1, 66, 40, 4, 83, 72, 65, 82, 24, 16, 86, 65, 82, 73, 65, + 78, 84, 32, 70, 79, 82, 77, 32, 69, 83, 72, 118, 65, 82, 71, 167, 184, + 27, 68, 6, 248, 111, 3, 85, 82, 85, 199, 10, 65, 8, 210, 111, 50, 3, 85, + 4, 250, 144, 24, 49, 203, 3, 50, 22, 82, 65, 30, 66, 32, 2, 69, 83, 22, + 71, 26, 83, 61, 6, 84, 72, 73, 82, 68, 83, 4, 209, 184, 1, 2, 83, 72, 4, + 238, 120, 65, 199, 241, 25, 85, 2, 239, 147, 24, 72, 4, 53, 3, 69, 83, + 72, 4, 11, 72, 4, 17, 2, 65, 82, 4, 174, 246, 30, 50, 3, 85, 4, 11, 32, + 4, 128, 226, 26, 12, 86, 65, 82, 73, 65, 78, 84, 32, 70, 79, 82, 77, 195, + 85, 68, 10, 160, 1, 9, 68, 73, 65, 71, 79, 78, 65, 76, 32, 188, 241, 24, + 6, 86, 69, 82, 84, 73, 67, 169, 225, 2, 14, 79, 76, 68, 32, 65, 83, 83, + 89, 82, 73, 65, 78, 32, 87, 6, 192, 190, 27, 2, 84, 82, 204, 229, 2, 4, + 81, 85, 65, 68, 15, 67, 192, 17, 202, 1, 65, 186, 15, 66, 170, 5, 68, + 190, 15, 69, 202, 10, 71, 182, 30, 72, 238, 3, 73, 238, 4, 75, 138, 20, + 76, 134, 37, 77, 134, 6, 78, 226, 17, 80, 210, 3, 82, 42, 83, 238, 19, + 84, 186, 8, 85, 207, 20, 90, 141, 1, 160, 1, 7, 32, 84, 73, 77, 69, 83, + 32, 142, 1, 66, 250, 3, 68, 38, 75, 90, 76, 212, 1, 3, 77, 65, 82, 78, + 78, 134, 2, 82, 42, 83, 210, 230, 29, 80, 191, 127, 50, 16, 128, 173, 1, + 5, 76, 65, 71, 65, 82, 226, 23, 71, 166, 187, 12, 73, 198, 144, 13, 77, + 142, 250, 1, 83, 226, 159, 1, 66, 234, 67, 72, 187, 2, 65, 45, 22, 32, + 219, 2, 50, 28, 48, 6, 84, 73, 77, 69, 83, 32, 251, 202, 1, 71, 26, 180, + 1, 2, 71, 65, 38, 73, 36, 2, 83, 72, 240, 112, 8, 85, 32, 80, 76, 85, 83, + 32, 85, 188, 56, 4, 68, 85, 78, 51, 166, 2, 65, 204, 2, 3, 78, 85, 78, + 242, 27, 76, 191, 160, 29, 72, 4, 178, 210, 1, 78, 151, 155, 29, 76, 4, + 194, 169, 1, 71, 167, 196, 28, 77, 4, 170, 137, 24, 85, 187, 254, 4, 69, + 15, 37, 7, 32, 84, 73, 77, 69, 83, 32, 12, 190, 133, 1, 77, 130, 59, 71, + 194, 9, 83, 234, 10, 84, 192, 177, 27, 2, 66, 65, 143, 230, 1, 65, 5, + 249, 51, 5, 32, 84, 73, 77, 69, 7, 37, 7, 32, 84, 73, 77, 69, 83, 32, 4, + 252, 27, 5, 83, 72, 73, 84, 65, 199, 80, 69, 23, 68, 7, 32, 84, 73, 77, + 69, 83, 32, 202, 240, 24, 69, 247, 169, 5, 65, 16, 102, 75, 140, 173, 1, + 2, 68, 73, 218, 253, 25, 71, 170, 217, 1, 85, 130, 92, 65, 146, 92, 83, + 215, 42, 72, 4, 242, 157, 1, 65, 183, 203, 29, 73, 7, 37, 7, 32, 84, 73, + 77, 69, 83, 32, 4, 130, 248, 3, 75, 207, 195, 26, 83, 13, 26, 32, 147, + 187, 30, 83, 8, 128, 1, 10, 80, 76, 85, 83, 32, 78, 65, 71, 65, 32, 148, + 164, 8, 7, 84, 72, 82, 69, 69, 32, 84, 245, 220, 5, 4, 79, 86, 69, 82, 4, + 128, 140, 1, 16, 79, 80, 80, 79, 83, 73, 78, 71, 32, 65, 78, 32, 80, 76, + 85, 83, 163, 226, 22, 83, 6, 200, 49, 2, 65, 68, 175, 219, 17, 75, 18, + 26, 72, 239, 245, 11, 65, 17, 42, 32, 138, 140, 18, 71, 191, 217, 12, 50, + 10, 68, 9, 79, 86, 69, 82, 32, 65, 83, 72, 32, 158, 97, 90, 135, 112, 75, + 6, 176, 1, 8, 79, 86, 69, 82, 32, 65, 83, 72, 141, 143, 1, 29, 84, 85, + 71, 50, 32, 79, 86, 69, 82, 32, 84, 85, 71, 50, 32, 84, 85, 71, 50, 32, + 79, 86, 69, 82, 32, 84, 85, 71, 50, 5, 133, 145, 1, 27, 32, 67, 82, 79, + 83, 83, 73, 78, 71, 32, 65, 83, 72, 32, 79, 86, 69, 82, 32, 65, 83, 72, + 32, 79, 86, 69, 82, 52, 30, 65, 158, 2, 73, 95, 85, 27, 66, 68, 44, 4, + 72, 65, 82, 50, 90, 76, 66, 82, 183, 140, 27, 71, 5, 129, 208, 1, 6, 32, + 84, 73, 77, 69, 83, 9, 37, 7, 32, 84, 73, 77, 69, 83, 32, 6, 222, 164, 1, + 65, 218, 168, 29, 78, 163, 17, 90, 7, 180, 215, 29, 7, 32, 79, 86, 69, + 82, 32, 66, 215, 136, 1, 65, 5, 203, 252, 23, 65, 9, 37, 7, 32, 84, 73, + 77, 69, 83, 32, 6, 246, 155, 1, 73, 198, 161, 28, 71, 171, 162, 1, 65, + 19, 50, 32, 168, 1, 3, 76, 85, 71, 223, 169, 1, 82, 8, 88, 8, 79, 86, 69, + 82, 32, 66, 85, 32, 217, 222, 26, 8, 67, 82, 79, 83, 83, 73, 78, 71, 6, + 144, 152, 12, 7, 84, 73, 77, 69, 83, 32, 78, 234, 139, 17, 65, 211, 106, + 85, 5, 237, 236, 3, 8, 32, 79, 86, 69, 82, 32, 66, 85, 180, 1, 34, 65, + 222, 5, 73, 195, 2, 85, 67, 50, 71, 150, 5, 82, 146, 49, 32, 163, 166, + 30, 77, 55, 26, 32, 171, 220, 30, 51, 50, 76, 13, 75, 73, 83, 73, 77, 53, + 32, 84, 73, 77, 69, 83, 32, 211, 198, 1, 84, 48, 146, 1, 65, 30, 66, 38, + 71, 112, 2, 73, 82, 42, 76, 94, 85, 166, 131, 1, 80, 162, 61, 84, 234, + 232, 26, 75, 146, 152, 2, 78, 254, 2, 83, 163, 17, 72, 4, 110, 32, 175, + 183, 29, 77, 4, 154, 244, 28, 65, 143, 230, 1, 73, 10, 34, 65, 58, 73, + 151, 147, 30, 85, 5, 11, 32, 2, 169, 244, 28, 6, 80, 76, 85, 83, 32, 77, + 5, 211, 245, 23, 82, 5, 181, 203, 13, 5, 32, 80, 76, 85, 83, 8, 26, 85, + 211, 216, 30, 65, 7, 144, 151, 1, 7, 32, 80, 76, 85, 83, 32, 77, 191, + 193, 29, 77, 6, 52, 7, 50, 32, 80, 76, 85, 83, 32, 203, 214, 30, 83, 4, + 128, 27, 2, 71, 73, 175, 215, 28, 77, 7, 171, 147, 12, 65, 25, 54, 77, + 150, 1, 78, 76, 2, 83, 72, 135, 213, 30, 66, 13, 44, 7, 32, 84, 73, 77, + 69, 83, 32, 59, 50, 6, 220, 69, 2, 85, 32, 134, 160, 13, 73, 199, 195, + 16, 83, 5, 153, 228, 12, 6, 32, 84, 73, 77, 69, 83, 5, 173, 179, 18, 14, + 32, 75, 65, 83, 75, 65, 76, 32, 85, 32, 71, 85, 78, 85, 5, 229, 157, 1, + 5, 32, 80, 76, 85, 83, 91, 70, 32, 66, 66, 94, 71, 234, 4, 78, 190, 234, + 23, 82, 215, 227, 6, 72, 6, 138, 176, 1, 71, 170, 3, 83, 249, 144, 12, 4, + 79, 86, 69, 82, 9, 52, 7, 32, 84, 73, 77, 69, 83, 32, 159, 211, 30, 50, + 4, 234, 145, 1, 69, 167, 148, 29, 83, 61, 52, 7, 32, 84, 73, 77, 69, 83, + 32, 175, 140, 30, 85, 56, 122, 65, 58, 68, 30, 71, 74, 75, 90, 76, 110, + 77, 50, 83, 242, 79, 69, 218, 58, 73, 250, 139, 16, 72, 158, 164, 13, 78, + 3, 80, 6, 32, 2, 83, 72, 139, 164, 30, 78, 5, 143, 154, 14, 32, 4, 182, + 129, 30, 73, 3, 85, 8, 26, 73, 215, 208, 30, 65, 7, 252, 140, 1, 2, 82, + 50, 199, 194, 29, 83, 8, 26, 85, 195, 185, 1, 65, 6, 40, 4, 83, 72, 85, + 50, 227, 207, 30, 82, 5, 175, 26, 32, 8, 26, 65, 45, 2, 85, 72, 6, 202, + 26, 77, 197, 207, 23, 3, 75, 45, 48, 2, 225, 57, 5, 32, 80, 76, 85, 83, + 6, 198, 233, 28, 65, 206, 167, 1, 69, 211, 61, 73, 4, 222, 138, 1, 73, + 131, 173, 29, 72, 11, 26, 51, 247, 205, 30, 52, 7, 143, 9, 32, 117, 130, + 1, 32, 90, 50, 210, 1, 78, 202, 1, 82, 60, 3, 83, 72, 50, 52, 3, 90, 69, + 78, 230, 164, 18, 71, 226, 163, 11, 68, 191, 127, 76, 4, 168, 25, 11, 79, + 86, 69, 82, 32, 69, 32, 78, 85, 78, 32, 237, 94, 4, 84, 73, 77, 69, 19, + 37, 7, 32, 84, 73, 77, 69, 83, 32, 16, 134, 1, 83, 128, 168, 1, 10, 65, + 32, 80, 76, 85, 83, 32, 72, 65, 32, 178, 128, 28, 71, 214, 17, 80, 146, + 24, 75, 238, 100, 77, 219, 19, 85, 4, 186, 193, 29, 65, 203, 114, 72, 15, + 11, 32, 12, 96, 4, 67, 82, 79, 83, 0, 4, 79, 80, 80, 79, 36, 6, 84, 73, + 77, 69, 83, 32, 179, 208, 23, 83, 2, 189, 222, 13, 4, 83, 73, 78, 71, 6, + 188, 138, 1, 4, 71, 65, 78, 50, 147, 168, 29, 77, 6, 36, 3, 73, 78, 50, + 247, 248, 29, 69, 5, 187, 188, 29, 32, 5, 229, 16, 9, 32, 67, 82, 79, 83, + 83, 73, 78, 71, 63, 11, 32, 60, 96, 14, 83, 72, 69, 83, 72, 73, 71, 32, + 84, 73, 77, 69, 83, 32, 97, 6, 84, 73, 77, 69, 83, 32, 16, 162, 131, 1, + 73, 130, 219, 2, 77, 210, 131, 25, 65, 128, 105, 2, 76, 65, 182, 87, 83, + 147, 17, 72, 44, 134, 1, 65, 68, 5, 68, 85, 78, 51, 32, 26, 75, 58, 76, + 62, 83, 34, 85, 206, 127, 73, 204, 31, 2, 72, 65, 226, 249, 27, 71, 163, + 100, 66, 9, 228, 86, 9, 32, 80, 76, 85, 83, 32, 76, 65, 76, 195, 238, 29, + 78, 4, 217, 32, 2, 71, 85, 6, 192, 203, 23, 5, 65, 83, 75, 65, 76, 159, + 165, 3, 85, 8, 34, 65, 242, 195, 30, 73, 3, 85, 5, 185, 85, 2, 76, 32, 4, + 130, 173, 30, 72, 215, 22, 85, 4, 182, 195, 30, 50, 3, 68, 160, 2, 42, + 65, 166, 19, 69, 122, 73, 135, 5, 85, 191, 1, 114, 50, 144, 16, 2, 66, + 65, 94, 68, 22, 76, 38, 78, 190, 140, 1, 32, 154, 6, 82, 218, 143, 27, + 83, 167, 142, 2, 77, 153, 1, 11, 32, 150, 1, 68, 6, 84, 73, 77, 69, 83, + 32, 137, 128, 1, 5, 79, 86, 69, 82, 32, 148, 1, 202, 1, 65, 162, 2, 66, + 154, 1, 68, 178, 1, 69, 58, 71, 178, 1, 72, 230, 1, 73, 70, 75, 194, 1, + 76, 62, 77, 50, 78, 130, 1, 83, 142, 1, 85, 206, 154, 1, 84, 248, 179, + 22, 3, 90, 73, 90, 159, 225, 6, 80, 18, 132, 1, 6, 32, 80, 76, 85, 83, + 32, 50, 78, 52, 2, 83, 72, 161, 228, 17, 14, 66, 50, 32, 84, 69, 78, 85, + 32, 80, 76, 85, 83, 32, 84, 6, 186, 58, 68, 182, 147, 13, 73, 155, 238, + 16, 72, 5, 169, 61, 9, 32, 80, 76, 85, 83, 32, 75, 65, 75, 7, 11, 50, 5, + 245, 89, 6, 32, 80, 76, 85, 83, 32, 10, 26, 65, 77, 2, 85, 82, 6, 42, 72, + 44, 2, 82, 32, 183, 188, 30, 68, 2, 11, 65, 2, 255, 216, 23, 82, 5, 11, + 32, 2, 229, 241, 29, 4, 80, 76, 85, 83, 14, 34, 73, 54, 85, 187, 187, 30, + 65, 7, 17, 2, 77, 32, 4, 146, 22, 84, 191, 129, 1, 71, 6, 56, 8, 71, 32, + 84, 73, 77, 69, 83, 32, 255, 186, 30, 66, 4, 142, 119, 73, 151, 45, 75, + 10, 38, 78, 254, 2, 76, 203, 230, 28, 82, 5, 243, 28, 32, 18, 18, 65, 99, + 73, 11, 26, 82, 231, 158, 1, 78, 7, 33, 6, 32, 80, 76, 85, 83, 32, 4, + 254, 162, 30, 78, 255, 2, 68, 9, 158, 122, 52, 193, 176, 12, 7, 82, 50, + 32, 80, 76, 85, 83, 12, 62, 65, 138, 124, 85, 173, 174, 12, 6, 73, 32, + 80, 76, 85, 83, 8, 40, 6, 32, 80, 76, 85, 83, 32, 83, 76, 4, 48, 6, 76, + 85, 32, 80, 76, 85, 219, 183, 30, 65, 2, 11, 83, 2, 199, 97, 32, 5, 201, + 169, 13, 5, 32, 80, 76, 85, 83, 4, 160, 100, 10, 83, 72, 32, 80, 76, 85, + 83, 32, 72, 85, 147, 15, 71, 12, 34, 65, 36, 2, 73, 68, 27, 85, 4, 218, + 252, 23, 83, 211, 185, 6, 75, 5, 209, 77, 2, 32, 80, 4, 60, 5, 83, 72, + 85, 50, 32, 181, 127, 5, 51, 32, 80, 76, 85, 2, 189, 158, 1, 3, 80, 76, + 85, 8, 26, 65, 231, 179, 30, 85, 7, 11, 77, 5, 211, 159, 1, 32, 6, 234, + 77, 69, 206, 129, 28, 85, 159, 229, 1, 73, 10, 26, 69, 73, 2, 85, 78, 7, + 33, 6, 32, 80, 76, 85, 83, 32, 4, 142, 208, 23, 69, 255, 207, 6, 71, 5, + 11, 32, 2, 171, 101, 79, 14, 42, 72, 250, 140, 23, 65, 171, 149, 7, 85, + 8, 18, 69, 51, 73, 5, 157, 186, 29, 7, 32, 80, 76, 85, 83, 32, 84, 4, + 178, 178, 30, 68, 3, 77, 7, 11, 68, 5, 161, 162, 13, 5, 32, 80, 76, 85, + 83, 7, 11, 32, 4, 170, 216, 28, 82, 133, 172, 1, 11, 67, 82, 79, 83, 83, + 73, 78, 71, 32, 71, 65, 5, 175, 131, 1, 32, 7, 246, 130, 1, 32, 167, 157, + 29, 65, 11, 11, 50, 9, 11, 32, 6, 80, 8, 67, 82, 79, 83, 83, 73, 78, 71, + 0, 4, 79, 86, 69, 82, 255, 221, 25, 84, 2, 181, 49, 3, 32, 71, 65, 8, 44, + 5, 83, 72, 84, 73, 78, 199, 203, 23, 50, 7, 37, 7, 32, 84, 73, 77, 69, + 83, 32, 4, 170, 182, 29, 75, 199, 120, 85, 49, 70, 32, 94, 52, 114, 82, + 190, 1, 83, 202, 168, 29, 68, 187, 130, 1, 71, 6, 172, 232, 8, 6, 84, 73, + 77, 69, 83, 32, 253, 212, 4, 8, 67, 82, 79, 83, 83, 73, 78, 71, 7, 11, + 32, 4, 64, 8, 67, 82, 79, 83, 83, 73, 78, 71, 1, 4, 79, 86, 69, 82, 2, + 225, 199, 23, 3, 32, 71, 73, 16, 26, 51, 131, 136, 1, 50, 13, 37, 7, 32, + 84, 73, 77, 69, 83, 32, 10, 70, 65, 0, 2, 76, 85, 190, 127, 71, 166, 187, + 12, 73, 155, 238, 16, 80, 2, 221, 186, 13, 7, 32, 80, 76, 85, 83, 32, 73, + 14, 26, 72, 203, 161, 29, 65, 13, 11, 32, 10, 22, 84, 247, 20, 67, 8, 44, + 5, 73, 77, 69, 83, 32, 159, 133, 30, 69, 6, 192, 20, 6, 71, 73, 83, 72, + 32, 67, 130, 126, 84, 175, 209, 28, 66, 43, 110, 50, 174, 1, 68, 218, 1, + 77, 54, 82, 176, 183, 13, 9, 32, 67, 82, 79, 83, 83, 73, 78, 71, 247, + 237, 16, 76, 15, 11, 32, 12, 48, 6, 84, 73, 77, 69, 83, 32, 151, 132, 1, + 71, 10, 252, 24, 3, 75, 65, 75, 178, 75, 73, 152, 20, 10, 83, 65, 76, 32, + 80, 76, 85, 83, 32, 84, 191, 175, 28, 78, 11, 11, 32, 8, 128, 1, 10, 80, + 76, 85, 83, 32, 71, 73, 83, 72, 32, 16, 6, 84, 73, 77, 69, 83, 32, 161, + 66, 8, 79, 86, 69, 82, 32, 71, 85, 68, 2, 247, 120, 84, 4, 156, 145, 1, + 5, 65, 32, 80, 76, 85, 175, 156, 28, 75, 5, 17, 2, 32, 84, 2, 225, 42, 4, + 73, 77, 69, 83, 9, 26, 85, 139, 165, 30, 55, 4, 246, 163, 30, 83, 147, 1, + 78, 50, 30, 65, 82, 73, 215, 1, 85, 11, 26, 32, 175, 164, 30, 76, 6, 32, + 2, 84, 69, 131, 128, 1, 71, 4, 219, 127, 78, 23, 37, 7, 32, 84, 73, 77, + 69, 83, 32, 20, 104, 3, 65, 83, 72, 162, 228, 26, 68, 174, 190, 2, 78, + 94, 75, 158, 57, 66, 2, 71, 150, 25, 83, 143, 45, 85, 7, 208, 55, 8, 32, + 79, 86, 69, 82, 32, 72, 73, 147, 235, 29, 50, 19, 48, 2, 66, 50, 158, + 190, 23, 76, 199, 226, 6, 83, 13, 37, 7, 32, 84, 73, 77, 69, 83, 32, 10, + 238, 138, 1, 75, 150, 216, 25, 76, 158, 181, 2, 72, 214, 57, 65, 195, 9, + 85, 49, 104, 3, 68, 73, 77, 94, 71, 214, 1, 76, 62, 77, 238, 154, 30, 32, + 170, 1, 83, 146, 1, 66, 2, 78, 3, 82, 7, 53, 11, 32, 79, 86, 69, 82, 32, + 73, 68, 73, 77, 32, 4, 226, 166, 23, 83, 179, 128, 6, 66, 13, 11, 73, 11, + 11, 32, 8, 146, 123, 71, 168, 178, 11, 31, 79, 86, 69, 82, 32, 73, 71, + 73, 32, 83, 72, 73, 82, 32, 79, 86, 69, 82, 32, 83, 72, 73, 82, 32, 85, + 68, 32, 79, 86, 69, 82, 178, 183, 16, 68, 219, 166, 1, 82, 7, 26, 32, + 199, 157, 30, 50, 2, 153, 72, 4, 84, 73, 77, 69, 13, 26, 32, 183, 205, + 29, 73, 8, 76, 4, 67, 82, 79, 83, 0, 4, 79, 80, 80, 79, 146, 111, 84, + 183, 180, 22, 83, 2, 253, 153, 29, 5, 83, 73, 78, 71, 32, 222, 1, 78, 65, + 130, 15, 73, 242, 1, 85, 158, 73, 69, 237, 217, 22, 4, 87, 85, 51, 49, + 175, 1, 164, 1, 7, 32, 84, 73, 77, 69, 83, 32, 210, 9, 50, 66, 68, 102, + 75, 50, 76, 82, 77, 28, 4, 83, 75, 65, 76, 152, 140, 15, 6, 80, 32, 69, + 76, 65, 77, 235, 129, 15, 66, 134, 1, 170, 1, 65, 94, 66, 82, 69, 30, 71, + 182, 2, 73, 34, 75, 34, 76, 38, 77, 170, 1, 83, 118, 84, 34, 85, 198, 8, + 72, 246, 51, 78, 154, 157, 16, 80, 142, 147, 13, 82, 147, 17, 90, 13, 46, + 68, 154, 235, 29, 78, 165, 44, 2, 83, 72, 5, 213, 50, 7, 32, 80, 76, 85, + 83, 32, 75, 10, 34, 65, 226, 151, 30, 73, 3, 85, 6, 222, 177, 28, 76, + 130, 230, 1, 68, 3, 82, 4, 250, 24, 82, 151, 61, 83, 26, 30, 65, 98, 73, + 147, 1, 85, 11, 38, 82, 190, 123, 78, 151, 155, 29, 76, 5, 233, 21, 10, + 32, 80, 76, 85, 83, 32, 83, 72, 65, 51, 11, 32, 2, 83, 72, 163, 178, 23, + 82, 7, 11, 32, 4, 26, 67, 239, 130, 1, 80, 2, 37, 7, 82, 79, 83, 83, 73, + 78, 71, 2, 221, 214, 26, 2, 32, 71, 7, 242, 193, 26, 82, 151, 211, 3, 68, + 4, 138, 129, 30, 71, 219, 19, 77, 8, 234, 8, 73, 239, 232, 16, 65, 6, + 246, 238, 11, 85, 175, 165, 18, 73, 12, 18, 69, 83, 73, 9, 33, 6, 32, 80, + 76, 85, 83, 32, 6, 222, 238, 29, 68, 150, 14, 84, 255, 2, 71, 5, 45, 9, + 32, 80, 76, 85, 83, 32, 78, 85, 78, 2, 251, 155, 26, 85, 18, 62, 72, 246, + 174, 26, 65, 224, 234, 2, 2, 85, 72, 243, 119, 73, 10, 250, 149, 29, 85, + 138, 54, 73, 150, 70, 65, 3, 69, 4, 146, 217, 29, 65, 211, 56, 85, 17, + 110, 32, 222, 92, 82, 156, 182, 25, 9, 77, 85, 77, 32, 84, 73, 77, 69, + 83, 206, 252, 3, 83, 146, 1, 50, 3, 68, 2, 207, 190, 20, 85, 5, 177, 202, + 11, 11, 32, 67, 82, 79, 83, 83, 73, 78, 71, 32, 75, 10, 42, 53, 214, 143, + 30, 50, 2, 51, 3, 52, 5, 249, 169, 23, 9, 32, 79, 86, 69, 82, 32, 75, 65, + 68, 5, 173, 75, 8, 32, 84, 73, 77, 69, 83, 32, 73, 7, 11, 32, 4, 166, + 105, 84, 233, 235, 22, 9, 67, 82, 79, 83, 83, 73, 78, 71, 32, 4, 154, + 142, 30, 50, 3, 52, 7, 11, 32, 4, 70, 76, 1, 13, 79, 86, 69, 82, 32, 75, + 65, 83, 75, 65, 76, 32, 76, 2, 173, 116, 24, 65, 71, 65, 66, 32, 84, 73, + 77, 69, 83, 32, 85, 32, 79, 86, 69, 82, 32, 76, 65, 71, 65, 66, 32, 21, + 68, 7, 32, 84, 73, 77, 69, 83, 32, 50, 83, 198, 139, 30, 68, 3, 78, 6, + 26, 85, 187, 197, 29, 66, 5, 215, 139, 30, 68, 8, 52, 3, 73, 77, 53, 242, + 129, 29, 65, 159, 137, 1, 72, 5, 177, 165, 23, 11, 32, 79, 86, 69, 82, + 32, 75, 73, 83, 73, 77, 25, 200, 1, 29, 32, 79, 86, 69, 82, 32, 72, 73, + 32, 84, 73, 77, 69, 83, 32, 65, 83, 72, 50, 32, 75, 85, 32, 79, 86, 69, + 82, 32, 72, 18, 52, 54, 82, 186, 98, 83, 230, 1, 76, 162, 164, 29, 51, 2, + 55, 3, 78, 2, 155, 71, 73, 5, 157, 138, 29, 8, 32, 86, 65, 82, 73, 65, + 78, 84, 5, 213, 115, 9, 32, 79, 80, 80, 79, 83, 73, 78, 71, 240, 2, 30, + 65, 174, 26, 73, 59, 85, 141, 2, 68, 2, 71, 65, 252, 12, 2, 75, 45, 222, + 11, 76, 46, 77, 135, 55, 72, 118, 22, 66, 131, 11, 82, 109, 11, 32, 106, + 48, 6, 84, 73, 77, 69, 83, 32, 207, 141, 23, 83, 104, 190, 1, 65, 186, 1, + 66, 34, 71, 70, 72, 66, 73, 94, 75, 118, 76, 46, 77, 46, 83, 138, 2, 84, + 126, 85, 200, 150, 4, 8, 90, 85, 32, 79, 86, 69, 82, 32, 138, 196, 24, + 68, 214, 82, 69, 131, 57, 78, 15, 80, 6, 32, 80, 76, 85, 83, 32, 76, 4, + 83, 72, 32, 90, 226, 131, 30, 76, 3, 78, 6, 38, 68, 222, 225, 28, 71, + 131, 25, 76, 2, 201, 62, 5, 65, 32, 80, 76, 85, 2, 149, 112, 2, 73, 68, + 4, 178, 189, 29, 65, 151, 70, 73, 10, 48, 2, 85, 68, 210, 159, 26, 65, + 167, 227, 3, 73, 5, 191, 105, 32, 6, 244, 177, 17, 7, 73, 32, 84, 73, 77, + 69, 83, 211, 212, 11, 65, 8, 22, 77, 175, 62, 71, 7, 33, 6, 32, 80, 76, + 85, 83, 32, 4, 254, 220, 29, 76, 179, 34, 72, 10, 26, 85, 175, 137, 28, + 73, 6, 26, 76, 147, 129, 30, 51, 5, 41, 8, 32, 80, 76, 85, 83, 32, 72, + 73, 2, 219, 65, 32, 8, 198, 100, 65, 242, 182, 27, 73, 131, 105, 85, 6, + 26, 69, 243, 154, 28, 85, 5, 175, 25, 32, 12, 26, 72, 139, 239, 29, 85, + 10, 100, 14, 73, 84, 65, 32, 80, 76, 85, 83, 32, 71, 73, 83, 72, 32, 96, + 2, 85, 50, 217, 3, 2, 69, 32, 4, 48, 6, 80, 76, 85, 83, 32, 69, 223, 172, + 25, 84, 2, 11, 82, 2, 11, 73, 2, 215, 154, 23, 78, 5, 189, 73, 5, 32, 80, + 76, 85, 83, 6, 86, 65, 189, 30, 16, 69, 32, 80, 76, 85, 83, 32, 65, 32, + 80, 76, 85, 83, 32, 83, 85, 4, 162, 152, 23, 75, 251, 228, 6, 71, 13, 72, + 6, 32, 80, 76, 85, 83, 32, 190, 41, 50, 226, 209, 29, 83, 147, 1, 68, 4, + 26, 85, 147, 252, 29, 65, 2, 255, 40, 32, 11, 11, 32, 8, 68, 4, 71, 85, + 78, 85, 97, 9, 84, 73, 77, 69, 83, 32, 83, 72, 69, 5, 73, 16, 32, 79, 86, + 69, 82, 32, 76, 65, 71, 65, 82, 32, 71, 85, 78, 85, 2, 199, 205, 29, 32, + 5, 11, 32, 2, 229, 143, 14, 4, 80, 76, 85, 83, 136, 1, 82, 48, 146, 2, + 49, 30, 50, 114, 51, 82, 52, 222, 2, 54, 154, 4, 55, 243, 24, 53, 22, + 158, 1, 50, 30, 56, 180, 52, 15, 55, 57, 32, 79, 86, 69, 82, 32, 76, 65, + 75, 45, 48, 55, 57, 242, 199, 10, 53, 146, 152, 12, 54, 2, 57, 94, 51, + 143, 143, 3, 48, 4, 162, 248, 29, 49, 3, 53, 4, 144, 148, 23, 12, 49, 32, + 79, 86, 69, 82, 32, 76, 65, 75, 45, 48, 247, 227, 6, 48, 4, 222, 147, 23, + 52, 95, 51, 16, 46, 50, 38, 54, 230, 140, 23, 49, 159, 2, 51, 6, 230, + 246, 29, 48, 2, 53, 3, 56, 4, 194, 246, 29, 53, 3, 54, 12, 42, 52, 250, + 177, 11, 56, 143, 225, 11, 57, 6, 250, 245, 29, 51, 2, 55, 3, 56, 30, 62, + 52, 214, 1, 53, 30, 57, 178, 144, 23, 55, 143, 143, 3, 56, 14, 26, 57, + 255, 244, 29, 49, 13, 37, 7, 32, 84, 73, 77, 69, 83, 32, 10, 116, 9, 80, + 65, 80, 32, 80, 76, 85, 83, 32, 208, 227, 12, 7, 85, 50, 32, 80, 76, 85, + 83, 190, 31, 73, 235, 203, 16, 71, 4, 210, 13, 80, 51, 76, 4, 194, 243, + 29, 48, 3, 55, 8, 166, 243, 29, 48, 2, 50, 2, 51, 3, 53, 46, 60, 2, 49, + 55, 240, 1, 2, 52, 56, 138, 137, 23, 48, 23, 51, 23, 37, 7, 32, 84, 73, + 77, 69, 83, 32, 20, 122, 84, 34, 85, 162, 11, 75, 132, 34, 9, 68, 85, 78, + 51, 32, 71, 85, 78, 85, 186, 222, 27, 65, 254, 158, 1, 66, 235, 67, 76, + 4, 198, 184, 29, 65, 211, 56, 69, 6, 250, 146, 14, 82, 254, 221, 15, 50, + 3, 68, 21, 37, 7, 32, 84, 73, 77, 69, 83, 32, 18, 154, 1, 85, 220, 8, 4, + 80, 65, 80, 32, 146, 45, 73, 164, 167, 12, 10, 83, 72, 69, 83, 72, 32, + 80, 76, 85, 83, 250, 252, 4, 68, 170, 129, 12, 78, 163, 17, 71, 4, 138, + 145, 14, 82, 255, 221, 15, 68, 4, 234, 137, 23, 50, 211, 145, 3, 52, 5, + 11, 32, 2, 145, 6, 4, 84, 73, 77, 69, 7, 49, 10, 32, 84, 73, 77, 69, 83, + 32, 75, 85, 82, 5, 221, 160, 11, 5, 32, 80, 76, 85, 83, 9, 200, 160, 11, + 2, 77, 77, 222, 203, 18, 83, 147, 1, 76, 93, 90, 50, 212, 7, 3, 71, 65, + 76, 142, 1, 77, 130, 62, 32, 198, 165, 29, 51, 2, 72, 3, 76, 69, 11, 32, + 66, 88, 4, 67, 82, 79, 83, 0, 4, 79, 80, 80, 79, 44, 4, 71, 85, 78, 85, + 38, 83, 35, 84, 2, 205, 158, 11, 6, 83, 73, 78, 71, 32, 76, 2, 193, 24, + 5, 32, 84, 73, 77, 69, 6, 250, 68, 72, 139, 173, 22, 81, 54, 44, 5, 73, + 77, 69, 83, 32, 171, 197, 29, 69, 52, 188, 1, 4, 69, 83, 72, 50, 94, 72, + 42, 75, 68, 2, 76, 65, 34, 77, 60, 3, 80, 65, 80, 118, 83, 90, 84, 250, + 56, 71, 158, 230, 7, 78, 150, 135, 18, 68, 170, 181, 2, 65, 254, 66, 66, + 203, 53, 73, 7, 11, 32, 4, 26, 80, 207, 150, 25, 84, 2, 17, 2, 76, 85, 2, + 245, 222, 28, 3, 83, 32, 76, 4, 184, 66, 2, 73, 32, 171, 156, 28, 65, 8, + 32, 2, 65, 68, 183, 231, 29, 73, 6, 226, 19, 51, 211, 211, 29, 50, 4, + 174, 20, 32, 171, 249, 16, 71, 2, 11, 69, 2, 11, 32, 2, 209, 251, 12, 4, + 80, 76, 85, 83, 5, 11, 32, 2, 33, 6, 80, 76, 85, 83, 32, 80, 2, 45, 9, + 65, 80, 32, 80, 76, 85, 83, 32, 76, 2, 235, 145, 26, 85, 6, 26, 73, 195, + 192, 29, 72, 4, 194, 18, 32, 157, 211, 25, 7, 75, 50, 32, 80, 76, 85, 83, + 4, 162, 53, 85, 139, 24, 65, 9, 11, 32, 6, 22, 79, 207, 67, 83, 4, 56, 7, + 80, 80, 79, 83, 73, 78, 71, 1, 3, 86, 69, 82, 2, 21, 3, 32, 76, 85, 2, + 175, 218, 28, 71, 7, 45, 9, 32, 79, 86, 69, 82, 32, 76, 85, 77, 5, 187, + 59, 32, 70, 34, 65, 70, 69, 22, 73, 71, 85, 17, 170, 45, 32, 188, 1, 2, + 83, 72, 250, 179, 29, 50, 2, 72, 3, 82, 7, 187, 238, 25, 83, 7, 240, 142, + 26, 8, 32, 80, 76, 85, 83, 32, 90, 65, 151, 211, 3, 78, 43, 104, 2, 83, + 72, 186, 60, 71, 140, 215, 10, 5, 32, 79, 86, 69, 82, 40, 2, 82, 71, 237, + 183, 6, 2, 78, 83, 31, 22, 32, 183, 2, 51, 16, 136, 1, 9, 79, 86, 69, 82, + 32, 77, 85, 83, 72, 124, 6, 84, 73, 77, 69, 83, 32, 173, 254, 25, 10, 67, + 82, 79, 83, 83, 73, 78, 71, 32, 77, 9, 37, 7, 32, 84, 73, 77, 69, 83, 32, + 6, 42, 65, 254, 175, 27, 75, 175, 172, 2, 71, 2, 237, 142, 11, 5, 32, 80, + 76, 85, 83, 6, 242, 229, 28, 75, 142, 118, 90, 187, 2, 65, 13, 11, 32, + 10, 44, 6, 84, 73, 77, 69, 83, 32, 203, 57, 71, 8, 38, 65, 210, 201, 29, + 68, 163, 17, 90, 5, 173, 205, 12, 5, 32, 80, 76, 85, 83, 158, 1, 42, 65, + 134, 2, 69, 94, 73, 199, 7, 85, 23, 52, 2, 71, 65, 166, 1, 77, 246, 218, + 29, 50, 3, 52, 11, 26, 32, 255, 219, 29, 82, 6, 100, 8, 79, 80, 80, 79, + 83, 73, 78, 71, 146, 59, 73, 197, 14, 9, 84, 73, 77, 69, 83, 32, 83, 72, + 85, 2, 217, 152, 29, 3, 32, 78, 65, 7, 204, 21, 2, 32, 78, 167, 197, 29, + 50, 9, 11, 32, 6, 44, 6, 84, 73, 77, 69, 83, 32, 179, 57, 83, 4, 250, + 147, 29, 85, 151, 70, 65, 73, 90, 77, 78, 78, 204, 234, 19, 6, 32, 84, + 73, 77, 69, 83, 254, 135, 8, 83, 131, 230, 1, 50, 7, 45, 9, 32, 84, 73, + 77, 69, 83, 32, 71, 65, 4, 158, 3, 82, 179, 58, 78, 59, 36, 3, 68, 65, + 50, 163, 216, 29, 57, 55, 37, 7, 32, 84, 73, 77, 69, 83, 32, 52, 162, 1, + 65, 34, 71, 50, 75, 16, 5, 76, 65, 75, 45, 48, 22, 77, 86, 78, 34, 80, + 76, 3, 83, 72, 69, 94, 85, 240, 15, 3, 68, 73, 77, 174, 186, 28, 66, 211, + 117, 72, 6, 246, 2, 83, 223, 211, 29, 78, 8, 26, 73, 255, 211, 28, 85, 5, + 135, 213, 29, 83, 2, 211, 20, 69, 2, 251, 242, 22, 53, 4, 26, 69, 171, + 240, 27, 65, 2, 25, 4, 32, 80, 76, 85, 2, 177, 41, 3, 83, 32, 71, 4, 182, + 133, 29, 85, 215, 79, 69, 2, 33, 6, 65, 80, 32, 80, 76, 85, 2, 11, 83, 2, + 229, 195, 28, 2, 32, 80, 9, 37, 7, 32, 80, 76, 85, 83, 32, 65, 6, 26, 83, + 171, 140, 28, 32, 4, 11, 72, 5, 107, 32, 11, 50, 32, 34, 50, 246, 244, + 13, 82, 239, 220, 15, 83, 2, 233, 217, 13, 3, 80, 76, 85, 2, 11, 32, 2, + 21, 3, 80, 76, 85, 2, 11, 83, 2, 151, 237, 27, 32, 57, 24, 2, 49, 49, 99, + 78, 9, 11, 32, 6, 200, 25, 9, 79, 86, 69, 82, 32, 78, 85, 49, 49, 210, + 230, 24, 84, 191, 248, 2, 82, 47, 30, 32, 169, 3, 2, 85, 90, 18, 144, 1, + 12, 67, 82, 79, 83, 83, 73, 78, 71, 32, 78, 85, 78, 72, 12, 76, 65, 71, + 65, 82, 32, 84, 73, 77, 69, 83, 32, 174, 1, 79, 163, 252, 24, 84, 5, 209, + 40, 14, 32, 76, 65, 71, 65, 82, 32, 79, 86, 69, 82, 32, 76, 65, 10, 56, + 3, 83, 65, 76, 210, 233, 27, 77, 14, 85, 247, 66, 71, 5, 205, 197, 28, + 23, 32, 79, 86, 69, 82, 32, 78, 85, 78, 32, 76, 65, 71, 65, 82, 32, 84, + 73, 77, 69, 83, 32, 83, 2, 153, 253, 16, 3, 86, 69, 82, 27, 11, 32, 24, + 120, 10, 65, 66, 50, 32, 84, 73, 77, 69, 83, 32, 205, 37, 15, 75, 73, 83, + 73, 77, 53, 32, 84, 73, 77, 69, 83, 32, 66, 73, 20, 168, 1, 2, 75, 65, + 202, 7, 73, 212, 39, 2, 65, 83, 194, 171, 2, 68, 164, 166, 8, 3, 83, 73, + 76, 226, 230, 11, 85, 150, 185, 5, 71, 238, 147, 1, 78, 254, 2, 66, 163, + 17, 76, 2, 199, 247, 25, 68, 46, 42, 65, 36, 4, 69, 83, 72, 50, 23, 73, + 9, 242, 202, 29, 68, 2, 78, 3, 80, 5, 135, 186, 27, 32, 35, 22, 32, 151, + 1, 82, 20, 80, 6, 84, 73, 77, 69, 83, 32, 205, 199, 17, 8, 67, 82, 79, + 83, 83, 73, 78, 71, 18, 214, 21, 85, 146, 48, 65, 2, 73, 190, 195, 28, + 66, 175, 64, 69, 12, 32, 2, 73, 71, 239, 200, 29, 50, 11, 11, 32, 8, 96, + 6, 84, 73, 77, 69, 83, 32, 173, 193, 25, 12, 79, 80, 80, 79, 83, 73, 78, + 71, 32, 80, 73, 82, 6, 210, 190, 28, 75, 150, 67, 85, 223, 67, 90, 8, + 230, 67, 65, 234, 131, 29, 73, 3, 85, 202, 1, 46, 65, 250, 5, 72, 150, + 11, 73, 163, 1, 85, 63, 46, 71, 190, 4, 76, 122, 78, 147, 193, 29, 82, + 53, 11, 32, 50, 92, 4, 71, 85, 78, 85, 54, 78, 32, 6, 84, 73, 77, 69, 83, + 32, 241, 21, 4, 79, 86, 69, 82, 5, 29, 5, 32, 84, 73, 77, 69, 2, 167, + 170, 17, 83, 2, 177, 203, 24, 3, 85, 84, 73, 42, 150, 1, 73, 42, 75, 34, + 83, 64, 2, 84, 65, 38, 85, 216, 62, 2, 68, 85, 246, 219, 27, 76, 222, 39, + 78, 198, 48, 69, 254, 59, 77, 162, 17, 72, 187, 2, 65, 2, 11, 71, 2, 11, + 73, 2, 191, 31, 32, 4, 242, 138, 29, 85, 187, 53, 65, 6, 26, 72, 239, + 185, 28, 65, 4, 234, 139, 13, 69, 139, 241, 15, 73, 4, 234, 221, 22, 75, + 251, 228, 6, 66, 10, 174, 193, 29, 83, 146, 1, 50, 2, 66, 2, 77, 3, 82, + 5, 33, 6, 32, 76, 65, 71, 65, 66, 2, 37, 7, 32, 84, 73, 77, 69, 83, 32, + 2, 11, 65, 2, 11, 83, 2, 207, 221, 22, 72, 2, 131, 251, 10, 71, 106, 46, + 65, 250, 1, 69, 242, 2, 73, 239, 3, 85, 29, 50, 51, 182, 1, 54, 182, 215, + 22, 66, 223, 3, 82, 19, 37, 7, 32, 84, 73, 77, 69, 83, 32, 16, 90, 85, + 146, 25, 83, 194, 231, 25, 71, 130, 198, 2, 84, 166, 50, 66, 206, 47, 78, + 215, 22, 65, 5, 11, 32, 2, 129, 171, 25, 4, 80, 76, 85, 83, 5, 175, 45, + 32, 27, 62, 32, 140, 2, 2, 83, 72, 226, 232, 25, 71, 171, 211, 3, 78, 14, + 84, 8, 79, 86, 69, 82, 32, 83, 72, 69, 88, 5, 80, 76, 85, 83, 32, 255, + 151, 29, 72, 7, 11, 32, 4, 190, 15, 71, 141, 6, 12, 84, 65, 66, 32, 79, + 86, 69, 82, 32, 84, 65, 66, 6, 48, 2, 72, 85, 20, 2, 78, 65, 247, 153, + 28, 83, 2, 219, 216, 22, 66, 2, 199, 216, 22, 77, 7, 202, 130, 28, 76, + 191, 185, 1, 50, 40, 62, 68, 74, 77, 218, 1, 82, 182, 178, 25, 78, 155, + 132, 4, 84, 7, 37, 7, 32, 84, 73, 77, 69, 83, 32, 4, 162, 170, 29, 73, + 219, 16, 65, 25, 37, 7, 32, 84, 73, 77, 69, 83, 32, 22, 114, 66, 38, 73, + 130, 19, 75, 198, 181, 2, 77, 190, 198, 2, 76, 246, 135, 23, 71, 130, 25, + 83, 238, 9, 68, 191, 127, 65, 4, 218, 200, 2, 85, 203, 231, 25, 65, 4, + 249, 20, 2, 71, 73, 7, 11, 32, 4, 60, 9, 79, 86, 69, 82, 32, 83, 72, 73, + 82, 211, 230, 24, 84, 2, 241, 191, 28, 11, 32, 66, 85, 82, 32, 79, 86, + 69, 82, 32, 66, 13, 88, 14, 32, 79, 86, 69, 82, 32, 73, 78, 86, 69, 82, + 84, 69, 68, 34, 50, 187, 190, 28, 66, 2, 11, 32, 2, 167, 245, 24, 83, 7, + 33, 6, 32, 80, 76, 85, 83, 32, 4, 88, 7, 69, 50, 32, 84, 73, 77, 69, 173, + 234, 10, 9, 68, 85, 71, 32, 84, 73, 77, 69, 83, 2, 235, 207, 12, 83, 17, + 50, 32, 30, 71, 230, 234, 10, 76, 227, 230, 11, 75, 4, 138, 8, 84, 163, + 9, 71, 7, 11, 52, 5, 49, 10, 32, 79, 86, 69, 82, 32, 83, 73, 71, 52, 2, + 199, 14, 32, 19, 78, 68, 22, 77, 22, 82, 252, 164, 12, 5, 32, 79, 86, 69, + 82, 147, 150, 16, 72, 5, 247, 179, 29, 50, 5, 199, 206, 27, 65, 5, 207, + 179, 29, 57, 72, 46, 65, 150, 4, 73, 250, 1, 85, 227, 8, 69, 37, 66, 32, + 94, 66, 166, 1, 71, 148, 1, 2, 75, 52, 183, 175, 29, 82, 8, 60, 6, 84, + 73, 77, 69, 83, 32, 130, 14, 71, 207, 147, 27, 65, 4, 174, 158, 29, 72, + 3, 77, 7, 11, 32, 4, 188, 143, 17, 29, 79, 86, 69, 82, 32, 84, 65, 66, + 32, 78, 73, 32, 79, 86, 69, 82, 32, 78, 73, 32, 68, 73, 83, 72, 32, 79, + 86, 69, 82, 175, 169, 5, 83, 15, 37, 7, 32, 84, 73, 77, 69, 83, 32, 12, + 74, 84, 252, 233, 7, 2, 83, 72, 154, 155, 20, 71, 174, 100, 85, 191, 50, + 66, 2, 11, 85, 2, 243, 203, 22, 71, 5, 29, 5, 32, 80, 76, 85, 83, 2, 145, + 201, 27, 2, 32, 83, 17, 46, 82, 150, 29, 32, 182, 145, 29, 50, 3, 76, 9, + 11, 32, 6, 48, 8, 79, 86, 69, 82, 32, 84, 73, 82, 99, 84, 5, 11, 32, 2, + 11, 71, 2, 21, 3, 65, 68, 32, 2, 241, 5, 8, 79, 86, 69, 82, 32, 71, 65, + 68, 2, 217, 21, 6, 73, 77, 69, 83, 32, 84, 17, 50, 77, 114, 82, 138, 200, + 22, 71, 215, 227, 6, 75, 7, 37, 7, 32, 84, 73, 77, 69, 83, 32, 4, 46, 71, + 213, 137, 17, 5, 84, 72, 82, 69, 69, 2, 221, 16, 2, 65, 78, 5, 137, 221, + 10, 17, 32, 79, 86, 69, 82, 32, 84, 85, 82, 32, 90, 65, 32, 79, 86, 69, + 82, 179, 1, 138, 1, 32, 246, 2, 68, 226, 2, 78, 46, 77, 158, 2, 82, 128, + 9, 2, 83, 72, 174, 1, 90, 192, 133, 12, 2, 84, 85, 238, 145, 17, 50, 3, + 66, 12, 64, 7, 79, 86, 69, 82, 32, 85, 32, 158, 2, 85, 215, 252, 27, 71, + 6, 200, 1, 10, 80, 65, 32, 79, 86, 69, 82, 32, 80, 65, 168, 247, 8, 19, + 85, 32, 82, 69, 86, 69, 82, 83, 69, 68, 32, 79, 86, 69, 82, 32, 85, 32, + 82, 249, 183, 19, 10, 83, 85, 82, 32, 79, 86, 69, 82, 32, 83, 2, 11, 32, + 2, 45, 9, 71, 65, 82, 32, 79, 86, 69, 82, 32, 2, 255, 132, 28, 71, 5, + 171, 130, 29, 32, 21, 26, 32, 147, 166, 29, 85, 16, 70, 75, 44, 2, 83, + 72, 100, 6, 84, 73, 77, 69, 83, 32, 135, 1, 71, 2, 11, 85, 2, 11, 83, 2, + 151, 217, 10, 72, 4, 29, 5, 69, 83, 72, 73, 71, 5, 11, 32, 2, 11, 84, 2, + 149, 223, 28, 6, 73, 77, 69, 83, 32, 66, 8, 92, 14, 85, 32, 80, 76, 85, + 83, 32, 85, 32, 80, 76, 85, 83, 32, 142, 222, 28, 66, 203, 50, 77, 4, 11, + 85, 5, 11, 32, 2, 11, 71, 2, 147, 255, 28, 85, 21, 72, 7, 32, 84, 73, 77, + 69, 83, 32, 136, 1, 2, 85, 77, 231, 162, 28, 66, 10, 50, 76, 16, 2, 77, + 69, 50, 83, 183, 162, 29, 85, 2, 231, 6, 65, 5, 11, 32, 2, 177, 153, 25, + 4, 80, 76, 85, 83, 2, 255, 215, 10, 72, 7, 37, 7, 32, 84, 73, 77, 69, 83, + 32, 4, 158, 11, 75, 163, 148, 29, 80, 93, 54, 32, 102, 50, 194, 2, 73, + 22, 85, 235, 157, 29, 52, 4, 62, 83, 157, 168, 28, 9, 67, 82, 79, 83, 83, + 73, 78, 71, 32, 2, 141, 154, 25, 4, 72, 69, 83, 72, 23, 11, 32, 20, 42, + 73, 37, 6, 84, 73, 77, 69, 83, 32, 2, 165, 168, 23, 4, 78, 86, 69, 82, + 18, 46, 65, 82, 85, 202, 158, 28, 78, 227, 125, 72, 6, 48, 6, 32, 80, 76, + 85, 83, 32, 255, 158, 29, 76, 4, 194, 156, 29, 72, 3, 78, 8, 26, 50, 199, + 158, 29, 68, 7, 33, 6, 32, 80, 76, 85, 83, 32, 4, 130, 185, 27, 65, 199, + 209, 1, 66, 5, 251, 157, 29, 51, 59, 56, 7, 32, 84, 73, 77, 69, 83, 32, + 165, 4, 2, 68, 65, 52, 134, 1, 65, 46, 68, 38, 71, 82, 73, 46, 76, 78, + 83, 46, 85, 186, 247, 27, 66, 238, 34, 77, 214, 90, 84, 146, 17, 75, 162, + 17, 72, 3, 80, 5, 11, 83, 2, 11, 72, 2, 207, 194, 16, 71, 4, 186, 208, + 10, 65, 235, 251, 17, 85, 10, 26, 65, 187, 155, 29, 85, 9, 34, 78, 150, + 155, 29, 76, 3, 82, 2, 211, 9, 50, 6, 170, 135, 29, 71, 202, 18, 83, 147, + 1, 77, 6, 46, 85, 229, 178, 22, 5, 65, 75, 45, 54, 54, 4, 166, 154, 29, + 51, 3, 77, 4, 144, 181, 22, 2, 73, 71, 167, 206, 6, 72, 6, 42, 32, 186, + 187, 13, 82, 255, 221, 15, 68, 2, 241, 238, 27, 6, 80, 76, 85, 83, 32, + 71, 5, 11, 32, 2, 213, 159, 13, 4, 84, 73, 77, 69, 17, 84, 7, 32, 84, 73, + 77, 69, 83, 32, 244, 139, 28, 2, 85, 77, 142, 140, 1, 50, 3, 88, 8, 50, + 84, 168, 180, 25, 2, 75, 85, 167, 227, 3, 65, 2, 11, 65, 2, 199, 178, 22, + 75, 6, 26, 51, 147, 151, 29, 85, 5, 29, 5, 32, 84, 73, 77, 69, 2, 21, 3, + 83, 32, 75, 2, 11, 65, 2, 251, 220, 22, 83, 42, 50, 65, 190, 1, 73, 146, + 1, 85, 231, 175, 22, 69, 13, 50, 32, 198, 137, 28, 77, 142, 140, 1, 55, + 3, 71, 4, 56, 8, 83, 81, 85, 65, 82, 69, 68, 32, 175, 195, 24, 84, 2, 11, + 84, 2, 21, 3, 73, 77, 69, 2, 11, 83, 2, 157, 156, 28, 2, 32, 75, 15, 86, + 66, 132, 152, 22, 6, 32, 79, 86, 69, 82, 32, 154, 24, 90, 214, 227, 6, + 51, 3, 71, 5, 17, 2, 32, 75, 2, 17, 2, 65, 66, 2, 135, 2, 65, 15, 84, 10, + 32, 79, 86, 69, 82, 32, 90, 85, 32, 80, 42, 53, 246, 153, 28, 66, 199, + 120, 77, 2, 181, 240, 27, 5, 76, 85, 83, 32, 83, 7, 37, 7, 32, 84, 73, + 77, 69, 83, 32, 4, 44, 5, 84, 72, 82, 69, 69, 227, 145, 29, 65, 2, 29, 5, + 32, 68, 73, 83, 72, 2, 11, 32, 2, 203, 191, 24, 84, 8, 42, 32, 194, 150, + 22, 73, 187, 180, 3, 67, 4, 202, 212, 21, 79, 141, 190, 6, 8, 87, 73, 84, + 72, 32, 83, 84, 82, 18, 134, 1, 76, 154, 1, 82, 189, 202, 28, 23, 86, 69, + 68, 32, 83, 84, 69, 77, 32, 80, 65, 82, 65, 71, 82, 65, 80, 72, 32, 83, + 73, 71, 78, 10, 48, 2, 89, 32, 253, 147, 3, 4, 73, 78, 71, 32, 8, 60, 2, + 76, 79, 177, 128, 6, 7, 66, 82, 65, 67, 75, 69, 84, 6, 210, 226, 25, 71, + 215, 171, 3, 79, 6, 52, 5, 69, 78, 67, 89, 32, 53, 4, 89, 32, 65, 78, 4, + 248, 158, 24, 4, 69, 88, 67, 72, 143, 232, 3, 83, 2, 133, 160, 19, 3, 68, + 32, 82, 4, 174, 246, 27, 65, 133, 89, 2, 79, 77, 236, 8, 128, 1, 2, 80, + 82, 140, 9, 7, 82, 73, 76, 76, 73, 67, 32, 244, 134, 25, 7, 76, 73, 78, + 68, 82, 73, 67, 173, 210, 2, 2, 67, 76, 180, 2, 140, 1, 13, 73, 79, 84, + 32, 83, 89, 76, 76, 65, 66, 76, 69, 32, 169, 1, 16, 79, 45, 77, 73, 78, + 79, 65, 78, 32, 83, 73, 71, 78, 32, 67, 77, 110, 254, 156, 7, 75, 2, 76, + 2, 77, 2, 78, 2, 80, 2, 82, 2, 83, 2, 84, 126, 87, 254, 41, 74, 2, 90, + 194, 206, 6, 88, 138, 244, 14, 65, 2, 69, 2, 73, 2, 79, 3, 85, 198, 1, + 46, 48, 146, 5, 49, 141, 212, 23, 2, 51, 48, 170, 1, 102, 48, 78, 49, 74, + 50, 78, 51, 78, 52, 62, 53, 86, 55, 190, 140, 10, 57, 190, 3, 54, 179, + 234, 13, 56, 16, 246, 135, 29, 49, 2, 50, 2, 52, 2, 53, 2, 54, 2, 55, 2, + 56, 3, 57, 16, 194, 3, 50, 234, 131, 29, 48, 2, 49, 2, 51, 2, 53, 2, 55, + 3, 57, 16, 226, 134, 29, 49, 2, 51, 2, 52, 2, 53, 2, 54, 2, 55, 2, 56, 3, + 57, 16, 150, 134, 29, 48, 2, 51, 2, 52, 2, 53, 2, 54, 2, 55, 2, 56, 3, + 57, 12, 202, 133, 29, 48, 2, 49, 2, 52, 2, 54, 2, 55, 3, 57, 18, 142, + 133, 29, 48, 2, 49, 2, 50, 2, 51, 2, 52, 2, 53, 2, 54, 2, 56, 3, 57, 20, + 82, 53, 234, 131, 29, 48, 2, 49, 2, 50, 2, 51, 2, 52, 2, 54, 2, 56, 3, + 57, 5, 231, 131, 29, 66, 24, 18, 48, 87, 49, 18, 190, 131, 29, 48, 2, 49, + 2, 50, 2, 51, 2, 52, 2, 53, 2, 55, 2, 56, 3, 57, 6, 234, 130, 29, 48, 2, + 50, 3, 52, 180, 6, 140, 1, 9, 67, 65, 80, 73, 84, 65, 76, 32, 76, 194, 4, + 75, 32, 7, 76, 69, 84, 84, 69, 82, 32, 132, 1, 3, 80, 65, 89, 30, 83, + 203, 41, 84, 240, 2, 44, 6, 69, 84, 84, 69, 82, 32, 159, 43, 73, 234, 2, + 150, 2, 76, 46, 78, 34, 80, 34, 82, 58, 84, 54, 85, 190, 5, 65, 214, 1, + 66, 242, 1, 67, 150, 1, 68, 254, 1, 69, 206, 2, 71, 130, 1, 72, 134, 1, + 73, 230, 3, 75, 226, 3, 77, 218, 1, 79, 226, 2, 83, 210, 7, 89, 166, 1, + 90, 230, 178, 28, 70, 134, 14, 74, 2, 86, 2, 87, 159, 20, 81, 6, 214, 25, + 73, 186, 206, 28, 74, 159, 20, 72, 4, 254, 26, 69, 231, 204, 28, 74, 8, + 246, 33, 69, 203, 200, 28, 83, 12, 212, 9, 3, 79, 85, 78, 226, 18, 69, + 139, 223, 28, 72, 18, 158, 33, 69, 106, 83, 174, 174, 28, 67, 187, 22, + 87, 13, 190, 34, 32, 115, 75, 2, 137, 244, 28, 3, 65, 86, 89, 6, 248, 10, + 5, 77, 85, 76, 84, 73, 156, 205, 12, 2, 80, 65, 229, 195, 11, 14, 83, 77, + 65, 76, 76, 32, 67, 65, 80, 73, 84, 65, 76, 32, 2, 237, 209, 28, 2, 69, + 82, 184, 3, 136, 1, 6, 77, 65, 76, 76, 32, 76, 193, 37, 22, 85, 66, 83, + 67, 82, 73, 80, 84, 32, 83, 77, 65, 76, 76, 32, 76, 69, 84, 84, 69, 82, + 32, 132, 3, 44, 6, 69, 84, 84, 69, 82, 32, 143, 36, 73, 254, 2, 154, 2, + 65, 214, 1, 66, 242, 1, 67, 150, 1, 68, 254, 1, 69, 206, 2, 71, 130, 1, + 72, 134, 1, 73, 230, 3, 75, 222, 2, 76, 134, 1, 77, 114, 78, 106, 79, + 110, 80, 50, 82, 198, 1, 83, 218, 2, 84, 210, 2, 85, 246, 1, 87, 54, 89, + 166, 1, 90, 230, 178, 28, 70, 134, 14, 74, 2, 86, 159, 20, 81, 17, 108, + 6, 32, 87, 73, 84, 72, 32, 36, 9, 66, 75, 72, 65, 83, 73, 65, 78, 32, + 229, 228, 11, 4, 76, 69, 85, 84, 4, 138, 154, 9, 68, 151, 170, 3, 66, 8, + 128, 209, 12, 3, 67, 72, 69, 250, 189, 6, 68, 139, 229, 9, 72, 18, 110, + 65, 78, 73, 32, 3, 82, 79, 65, 128, 146, 3, 6, 76, 69, 78, 68, 69, 68, + 178, 187, 9, 89, 243, 166, 16, 69, 6, 200, 21, 6, 82, 82, 69, 68, 32, 79, + 233, 205, 11, 5, 83, 72, 75, 73, 82, 4, 230, 2, 78, 187, 143, 3, 71, 2, + 179, 133, 10, 68, 14, 76, 2, 72, 69, 246, 9, 76, 164, 222, 12, 4, 82, 79, + 83, 83, 155, 222, 15, 67, 9, 33, 6, 32, 87, 73, 84, 72, 32, 6, 142, 29, + 68, 195, 165, 28, 86, 26, 96, 2, 74, 69, 20, 6, 79, 85, 66, 76, 69, 32, + 66, 90, 182, 196, 28, 67, 186, 22, 87, 215, 22, 69, 5, 239, 151, 22, 82, + 4, 36, 3, 77, 79, 78, 219, 241, 28, 79, 2, 153, 13, 2, 79, 67, 12, 46, + 69, 138, 241, 27, 90, 182, 105, 72, 3, 87, 5, 155, 210, 28, 76, 41, 86, + 76, 98, 78, 110, 82, 166, 15, 32, 254, 185, 12, 83, 250, 247, 13, 77, + 195, 173, 2, 70, 11, 33, 6, 32, 87, 73, 84, 72, 32, 8, 158, 20, 77, 222, + 182, 12, 68, 134, 248, 13, 84, 163, 92, 72, 13, 33, 6, 32, 87, 73, 84, + 72, 32, 10, 190, 19, 77, 222, 182, 12, 68, 202, 52, 76, 190, 195, 13, 84, + 163, 92, 72, 5, 229, 191, 27, 5, 32, 87, 73, 84, 72, 14, 32, 2, 72, 69, + 187, 215, 28, 74, 13, 33, 6, 32, 87, 73, 84, 72, 32, 10, 134, 18, 77, + 146, 15, 85, 206, 167, 12, 68, 143, 31, 83, 12, 26, 65, 195, 214, 28, 87, + 11, 48, 6, 32, 87, 73, 84, 72, 32, 143, 135, 27, 82, 6, 218, 199, 12, 68, + 166, 212, 14, 72, 231, 160, 1, 83, 35, 84, 6, 32, 87, 73, 84, 72, 32, 50, + 69, 74, 79, 201, 1, 6, 90, 72, 73, 84, 83, 65, 6, 254, 142, 9, 68, 214, + 10, 71, 239, 184, 3, 77, 7, 33, 6, 32, 87, 73, 84, 72, 32, 4, 254, 152, + 9, 71, 195, 159, 3, 66, 17, 11, 84, 14, 48, 6, 73, 70, 73, 69, 68, 32, + 159, 234, 28, 65, 12, 80, 2, 67, 76, 38, 76, 214, 134, 3, 66, 130, 207, + 24, 89, 210, 147, 1, 65, 3, 69, 2, 33, 6, 79, 83, 69, 68, 32, 76, 2, 151, + 4, 73, 5, 145, 212, 12, 14, 32, 87, 73, 84, 72, 32, 68, 79, 85, 66, 76, + 69, 32, 71, 34, 102, 65, 98, 79, 244, 185, 28, 11, 72, 65, 75, 65, 83, + 83, 73, 65, 78, 32, 67, 186, 22, 74, 255, 2, 83, 11, 33, 6, 32, 87, 73, + 84, 72, 32, 8, 182, 194, 12, 68, 166, 212, 14, 72, 154, 160, 1, 86, 79, + 83, 18, 36, 3, 77, 73, 32, 251, 193, 25, 80, 16, 58, 68, 198, 236, 11, + 76, 2, 78, 2, 83, 2, 84, 3, 90, 6, 194, 236, 11, 90, 134, 227, 16, 74, + 215, 22, 69, 8, 94, 73, 236, 154, 10, 10, 79, 78, 71, 45, 76, 69, 71, 71, + 69, 68, 206, 179, 18, 74, 159, 20, 72, 2, 233, 130, 3, 4, 84, 84, 76, 69, + 4, 21, 3, 79, 78, 79, 4, 18, 67, 39, 71, 2, 205, 188, 18, 4, 85, 76, 65, + 82, 2, 237, 10, 4, 82, 65, 80, 72, 6, 62, 69, 204, 187, 18, 5, 65, 82, + 82, 79, 87, 155, 145, 10, 74, 2, 249, 192, 12, 5, 85, 84, 82, 65, 76, 11, + 52, 4, 77, 69, 71, 65, 166, 3, 32, 183, 223, 28, 84, 5, 233, 185, 28, 8, + 32, 87, 73, 84, 72, 32, 84, 73, 10, 130, 6, 69, 230, 183, 12, 65, 231, + 144, 16, 83, 14, 50, 69, 100, 4, 79, 85, 78, 68, 167, 222, 28, 72, 8, 37, + 7, 86, 69, 82, 83, 69, 68, 32, 8, 214, 249, 18, 68, 206, 222, 8, 84, 142, + 100, 89, 151, 14, 90, 4, 250, 241, 9, 32, 241, 237, 1, 2, 69, 68, 34, + 108, 4, 67, 72, 87, 65, 34, 72, 132, 1, 4, 79, 70, 84, 32, 170, 186, 12, + 84, 213, 1, 5, 69, 77, 73, 83, 79, 5, 11, 32, 2, 183, 218, 5, 87, 16, 92, + 4, 79, 82, 84, 32, 136, 185, 12, 2, 72, 65, 254, 173, 14, 67, 234, 224, + 1, 87, 215, 22, 65, 6, 254, 176, 26, 73, 195, 173, 2, 85, 8, 38, 69, 166, + 215, 27, 83, 255, 111, 68, 4, 242, 221, 28, 76, 3, 77, 26, 132, 1, 4, 65, + 76, 76, 32, 50, 69, 106, 83, 212, 211, 11, 11, 72, 82, 69, 69, 45, 76, + 69, 71, 71, 69, 68, 218, 218, 16, 67, 187, 22, 87, 6, 178, 179, 12, 72, + 206, 149, 15, 89, 255, 124, 84, 7, 33, 6, 32, 87, 73, 84, 72, 32, 4, 26, + 77, 223, 182, 12, 68, 2, 185, 169, 21, 5, 73, 68, 68, 76, 69, 8, 226, + 196, 28, 72, 2, 83, 2, 87, 215, 22, 69, 15, 58, 32, 114, 75, 53, 8, 78, + 66, 76, 69, 78, 68, 69, 68, 6, 29, 5, 87, 73, 84, 72, 32, 6, 26, 68, 255, + 192, 12, 77, 4, 172, 255, 8, 5, 79, 85, 66, 76, 69, 187, 8, 73, 5, 11, + 82, 2, 213, 4, 6, 65, 73, 78, 73, 65, 78, 2, 159, 144, 24, 32, 4, 176, + 197, 27, 4, 73, 68, 69, 32, 227, 147, 1, 69, 18, 62, 65, 28, 3, 69, 82, + 85, 134, 216, 28, 73, 2, 78, 3, 85, 7, 158, 216, 28, 69, 3, 84, 7, 33, 6, + 32, 87, 73, 84, 72, 32, 4, 138, 251, 8, 68, 131, 186, 3, 66, 18, 18, 69, + 71, 72, 9, 156, 1, 7, 32, 87, 73, 84, 72, 32, 68, 173, 211, 28, 2, 77, + 76, 10, 26, 69, 247, 191, 28, 87, 9, 33, 6, 32, 87, 73, 84, 72, 32, 6, + 26, 68, 203, 163, 12, 66, 4, 222, 131, 9, 73, 179, 173, 3, 69, 6, 37, 7, + 71, 65, 84, 85, 82, 69, 32, 6, 66, 65, 176, 140, 15, 2, 84, 69, 189, 155, + 13, 4, 69, 78, 32, 71, 2, 199, 185, 28, 32, 52, 198, 1, 66, 38, 68, 38, + 69, 36, 3, 71, 72, 69, 38, 72, 246, 188, 21, 89, 222, 157, 5, 83, 202, + 110, 84, 238, 8, 90, 246, 63, 73, 138, 19, 67, 186, 22, 80, 2, 86, 158, + 20, 75, 186, 2, 65, 2, 79, 3, 85, 4, 170, 172, 12, 89, 243, 166, 16, 69, + 6, 238, 210, 27, 90, 139, 128, 1, 69, 6, 210, 210, 28, 70, 2, 76, 3, 83, + 5, 201, 5, 5, 32, 87, 73, 84, 72, 4, 11, 65, 5, 171, 236, 26, 82, 2, 209, + 188, 15, 4, 72, 79, 85, 83, 184, 15, 178, 1, 65, 138, 4, 67, 54, 69, 198, + 35, 73, 250, 22, 79, 142, 44, 82, 174, 3, 85, 180, 180, 12, 13, 78, 65, + 32, 68, 79, 85, 66, 76, 69, 32, 72, 69, 76, 154, 231, 14, 86, 195, 47, + 76, 30, 116, 4, 71, 71, 69, 82, 146, 1, 78, 32, 4, 82, 75, 32, 83, 36, 2, + 83, 72, 200, 177, 21, 2, 76, 69, 155, 133, 1, 84, 9, 11, 32, 6, 44, 5, + 87, 73, 84, 72, 32, 143, 190, 6, 75, 4, 44, 3, 76, 69, 70, 1, 4, 82, 73, + 71, 72, 2, 201, 183, 27, 4, 84, 32, 71, 85, 4, 166, 144, 28, 67, 239, 30, + 71, 4, 254, 253, 20, 85, 175, 224, 4, 72, 10, 30, 32, 105, 3, 69, 68, 32, + 4, 60, 9, 87, 73, 84, 72, 32, 76, 69, 70, 84, 239, 185, 27, 83, 2, 17, 2, + 32, 85, 2, 175, 181, 22, 80, 6, 170, 215, 4, 84, 182, 147, 12, 76, 255, + 252, 9, 79, 10, 134, 204, 28, 49, 2, 50, 2, 51, 2, 52, 3, 83, 176, 4, + 182, 2, 67, 132, 2, 5, 71, 82, 69, 69, 32, 98, 76, 80, 21, 78, 84, 73, + 83, 84, 82, 89, 32, 83, 89, 77, 66, 79, 76, 32, 76, 73, 71, 72, 84, 32, + 160, 3, 8, 80, 65, 82, 84, 77, 69, 78, 84, 34, 83, 174, 6, 86, 188, 214, + 14, 11, 82, 69, 76, 73, 67, 84, 32, 72, 79, 85, 83, 132, 146, 7, 2, 65, + 70, 235, 154, 6, 69, 8, 50, 73, 217, 229, 5, 6, 82, 69, 65, 83, 69, 32, + 6, 48, 4, 68, 85, 79, 85, 21, 4, 77, 65, 76, 32, 2, 219, 178, 23, 83, 4, + 88, 9, 83, 69, 80, 65, 82, 65, 84, 79, 82, 197, 171, 21, 7, 69, 88, 80, + 79, 78, 69, 78, 2, 21, 3, 32, 75, 69, 2, 151, 180, 27, 89, 6, 200, 242, + 21, 4, 67, 69, 76, 83, 250, 205, 5, 83, 153, 106, 8, 70, 65, 72, 82, 69, + 78, 72, 69, 9, 176, 190, 16, 5, 73, 86, 69, 82, 89, 128, 225, 5, 2, 84, + 65, 215, 226, 4, 69, 30, 88, 4, 68, 79, 87, 78, 0, 2, 85, 80, 153, 1, 9, + 86, 69, 82, 84, 73, 67, 65, 76, 32, 8, 69, 15, 32, 65, 78, 68, 32, 72, + 79, 82, 73, 90, 79, 78, 84, 65, 76, 9, 33, 6, 32, 87, 73, 84, 72, 32, 6, + 234, 219, 26, 87, 170, 25, 67, 191, 43, 84, 14, 52, 4, 65, 78, 68, 32, + 85, 5, 87, 73, 84, 72, 32, 10, 200, 158, 17, 2, 84, 79, 190, 188, 9, 87, + 165, 189, 1, 6, 66, 79, 84, 84, 79, 77, 4, 218, 243, 26, 67, 191, 43, 84, + 2, 245, 137, 24, 3, 32, 83, 84, 170, 1, 64, 2, 67, 69, 48, 2, 69, 82, + 129, 5, 5, 75, 84, 79, 80, 32, 2, 217, 180, 26, 7, 78, 68, 73, 78, 71, + 32, 78, 164, 1, 32, 3, 69, 84, 32, 183, 4, 84, 160, 1, 56, 6, 67, 65, 80, + 73, 84, 65, 1, 4, 83, 77, 65, 76, 80, 45, 9, 76, 32, 76, 69, 84, 84, 69, + 82, 32, 80, 218, 1, 69, 96, 4, 76, 79, 78, 71, 0, 5, 83, 72, 79, 82, 84, + 74, 79, 30, 84, 2, 90, 246, 178, 11, 67, 206, 157, 15, 66, 2, 68, 2, 74, + 2, 80, 2, 86, 2, 89, 202, 96, 71, 2, 75, 134, 103, 87, 162, 19, 65, 203, + 17, 72, 20, 214, 202, 24, 83, 206, 251, 1, 78, 134, 247, 1, 84, 146, 1, + 70, 2, 76, 2, 77, 2, 82, 3, 87, 12, 11, 32, 12, 234, 201, 24, 65, 226, + 180, 1, 79, 130, 191, 2, 69, 3, 73, 4, 142, 189, 28, 73, 3, 87, 4, 190, + 208, 26, 72, 227, 213, 1, 69, 5, 225, 174, 27, 4, 32, 73, 83, 76, 4, 186, + 153, 16, 67, 229, 136, 11, 4, 87, 73, 78, 68, 202, 2, 100, 8, 65, 78, 65, + 71, 65, 82, 73, 32, 185, 18, 12, 73, 67, 69, 32, 67, 79, 78, 84, 82, 79, + 76, 32, 192, 2, 222, 1, 65, 38, 67, 22, 71, 36, 4, 72, 69, 65, 68, 96, 7, + 76, 69, 84, 84, 69, 82, 32, 198, 5, 83, 176, 7, 11, 86, 79, 87, 69, 76, + 32, 83, 73, 71, 78, 32, 158, 181, 18, 68, 148, 245, 5, 4, 74, 65, 73, 78, + 243, 239, 3, 79, 4, 138, 164, 12, 67, 191, 170, 12, 66, 2, 187, 253, 5, + 65, 4, 250, 163, 12, 82, 215, 236, 1, 65, 6, 44, 5, 32, 77, 65, 82, 75, + 163, 136, 28, 83, 5, 209, 195, 18, 7, 32, 87, 73, 84, 72, 32, 72, 158, 1, + 158, 2, 65, 54, 67, 62, 68, 50, 71, 62, 72, 52, 2, 77, 65, 46, 83, 154, + 10, 79, 218, 254, 6, 66, 82, 74, 218, 220, 4, 75, 238, 194, 3, 82, 166, + 212, 6, 89, 170, 109, 85, 238, 30, 78, 230, 46, 76, 238, 146, 1, 84, 46, + 86, 138, 225, 1, 73, 154, 191, 1, 80, 2, 90, 254, 68, 70, 2, 81, 187, 2, + 69, 13, 198, 181, 28, 65, 2, 73, 2, 85, 2, 87, 3, 89, 10, 26, 65, 195, + 178, 28, 72, 9, 185, 2, 4, 78, 68, 82, 65, 12, 170, 204, 24, 68, 246, + 229, 3, 72, 187, 2, 65, 10, 182, 185, 12, 76, 190, 179, 15, 72, 254, 68, + 71, 187, 2, 65, 4, 232, 150, 16, 4, 69, 65, 86, 89, 131, 157, 12, 65, 5, + 229, 133, 7, 6, 82, 87, 65, 82, 73, 32, 12, 38, 72, 174, 176, 28, 83, + 187, 2, 65, 8, 36, 3, 79, 82, 84, 191, 178, 28, 65, 6, 163, 212, 11, 32, + 68, 168, 1, 19, 69, 81, 85, 69, 78, 67, 69, 32, 70, 79, 82, 32, 76, 69, + 84, 84, 69, 82, 32, 104, 4, 73, 71, 78, 32, 141, 128, 26, 10, 84, 82, 69, + 83, 83, 32, 83, 73, 71, 78, 16, 226, 202, 3, 71, 2, 75, 220, 238, 22, 3, + 68, 68, 68, 2, 82, 226, 244, 1, 89, 38, 70, 2, 81, 3, 90, 48, 210, 3, 66, + 0, 10, 69, 88, 84, 69, 78, 68, 69, 68, 32, 66, 36, 11, 67, 65, 78, 68, + 82, 65, 66, 73, 78, 68, 85, 60, 8, 87, 69, 83, 84, 69, 82, 78, 32, 32, + 10, 82, 69, 86, 69, 82, 83, 69, 68, 32, 78, 148, 231, 4, 5, 80, 85, 83, + 72, 80, 182, 204, 1, 83, 156, 243, 3, 18, 68, 79, 85, 66, 76, 69, 32, 67, + 65, 78, 68, 82, 65, 66, 73, 78, 68, 85, 182, 148, 8, 73, 186, 137, 6, 65, + 126, 77, 46, 78, 204, 212, 2, 12, 72, 73, 71, 72, 32, 83, 80, 65, 67, 73, + 78, 71, 255, 77, 86, 4, 133, 170, 12, 4, 72, 65, 76, 69, 11, 11, 32, 8, + 206, 241, 21, 65, 210, 89, 86, 151, 244, 3, 84, 4, 30, 78, 21, 3, 70, 73, + 86, 2, 17, 2, 73, 78, 2, 217, 144, 21, 8, 69, 45, 76, 73, 75, 69, 32, 66, + 50, 146, 1, 65, 52, 7, 67, 65, 78, 68, 82, 65, 32, 62, 79, 190, 186, 18, + 80, 254, 165, 4, 85, 138, 228, 1, 83, 70, 86, 166, 221, 1, 73, 207, 134, + 2, 69, 10, 226, 169, 28, 65, 2, 73, 2, 85, 2, 87, 3, 89, 6, 176, 187, 18, + 4, 76, 79, 78, 71, 254, 237, 9, 69, 3, 79, 7, 158, 146, 28, 79, 215, 22, + 69, 10, 222, 193, 23, 70, 136, 6, 2, 83, 84, 146, 244, 2, 84, 203, 83, + 79, 228, 2, 182, 2, 65, 134, 2, 69, 74, 71, 224, 4, 6, 78, 71, 66, 65, + 84, 32, 248, 1, 5, 82, 69, 67, 84, 32, 98, 83, 178, 2, 86, 200, 7, 2, 89, + 65, 32, 4, 90, 90, 89, 32, 192, 152, 5, 2, 84, 84, 216, 229, 14, 10, 70, + 70, 69, 82, 69, 78, 67, 69, 32, 66, 229, 147, 7, 12, 77, 69, 78, 83, 73, + 79, 78, 32, 79, 82, 73, 71, 18, 26, 77, 167, 211, 8, 69, 16, 40, 4, 79, + 78, 68, 32, 195, 138, 3, 69, 14, 128, 1, 5, 87, 73, 84, 72, 32, 218, 220, + 17, 84, 128, 221, 2, 12, 83, 72, 65, 80, 69, 32, 87, 73, 84, 72, 32, 65, + 159, 192, 4, 79, 8, 202, 177, 21, 66, 162, 2, 84, 250, 228, 3, 76, 27, + 82, 14, 164, 240, 4, 5, 32, 70, 65, 67, 69, 225, 229, 16, 4, 83, 69, 76, + 32, 78, 64, 3, 73, 84, 32, 149, 2, 8, 82, 65, 77, 32, 70, 79, 82, 32, 60, + 98, 70, 44, 2, 78, 73, 2, 79, 14, 83, 46, 84, 44, 3, 90, 69, 82, 13, 5, + 69, 73, 71, 72, 84, 12, 128, 1, 2, 73, 86, 25, 3, 79, 85, 82, 6, 87, 78, + 12, 96, 4, 69, 86, 69, 78, 1, 2, 73, 88, 12, 28, 3, 72, 82, 69, 15, 87, + 6, 23, 69, 6, 11, 79, 7, 207, 186, 16, 32, 18, 88, 5, 69, 65, 82, 84, 72, + 64, 5, 71, 82, 69, 65, 84, 0, 4, 76, 69, 83, 83, 39, 72, 7, 25, 4, 76, + 89, 32, 72, 4, 238, 213, 23, 85, 187, 131, 1, 69, 4, 229, 207, 12, 4, 69, + 82, 32, 89, 4, 172, 129, 5, 7, 69, 65, 86, 69, 78, 76, 89, 1, 4, 85, 77, + 65, 78, 64, 120, 17, 78, 69, 71, 65, 84, 73, 86, 69, 32, 67, 73, 82, 67, + 76, 69, 68, 32, 41, 9, 67, 73, 82, 67, 76, 69, 68, 32, 83, 42, 38, 83, + 162, 32, 78, 139, 249, 19, 68, 22, 49, 10, 65, 78, 83, 45, 83, 69, 82, + 73, 70, 32, 22, 234, 31, 78, 203, 142, 26, 68, 4, 140, 143, 22, 15, 67, + 85, 82, 82, 69, 78, 84, 32, 83, 89, 77, 66, 79, 76, 32, 235, 240, 5, 72, + 10, 70, 65, 144, 1, 5, 67, 79, 78, 84, 73, 213, 251, 24, 3, 71, 85, 73, + 6, 76, 9, 80, 80, 79, 73, 78, 84, 69, 68, 32, 217, 255, 14, 4, 66, 76, + 69, 68, 4, 232, 226, 16, 7, 66, 85, 84, 32, 82, 69, 76, 211, 250, 10, 70, + 2, 53, 11, 78, 85, 79, 85, 83, 32, 85, 78, 68, 69, 82, 2, 213, 197, 16, + 3, 76, 73, 78, 156, 1, 80, 9, 69, 83, 32, 65, 75, 85, 82, 85, 32, 238, 5, + 73, 233, 190, 16, 2, 79, 82, 144, 1, 142, 2, 68, 36, 7, 76, 69, 84, 84, + 69, 82, 32, 236, 1, 5, 83, 73, 71, 78, 32, 58, 86, 252, 243, 8, 6, 77, + 69, 68, 73, 65, 76, 198, 247, 4, 71, 198, 211, 4, 69, 172, 189, 4, 12, + 80, 82, 69, 70, 73, 88, 69, 68, 32, 78, 65, 83, 241, 204, 4, 7, 73, 78, + 73, 84, 73, 65, 76, 22, 246, 192, 18, 79, 175, 231, 7, 73, 84, 186, 142, + 10, 84, 242, 209, 11, 89, 186, 116, 65, 130, 217, 1, 68, 146, 25, 85, + 210, 200, 1, 73, 42, 76, 246, 189, 1, 78, 46, 83, 82, 66, 2, 67, 2, 71, + 2, 75, 2, 80, 254, 68, 72, 2, 74, 2, 77, 2, 82, 2, 86, 2, 90, 186, 2, 69, + 3, 79, 8, 234, 128, 24, 72, 146, 45, 67, 98, 78, 223, 160, 3, 65, 18, 64, + 10, 79, 87, 69, 76, 32, 83, 73, 71, 78, 32, 179, 225, 25, 73, 16, 178, + 219, 14, 65, 218, 232, 9, 85, 210, 200, 1, 73, 206, 134, 2, 69, 3, 79, + 10, 68, 5, 83, 73, 79, 78, 32, 204, 234, 1, 2, 78, 71, 235, 147, 25, 68, + 6, 26, 83, 247, 206, 5, 84, 4, 206, 172, 26, 76, 231, 94, 73, 2, 173, + 184, 18, 3, 32, 76, 65, 4, 190, 254, 26, 83, 255, 85, 70, 190, 5, 188, 2, + 6, 67, 85, 77, 69, 78, 84, 124, 7, 69, 83, 32, 78, 79, 84, 32, 194, 3, + 71, 210, 3, 76, 36, 10, 77, 73, 78, 79, 32, 84, 73, 76, 69, 32, 226, 1, + 78, 38, 84, 246, 2, 85, 204, 17, 2, 87, 78, 220, 128, 16, 8, 32, 78, 79, + 84, 32, 76, 73, 84, 136, 178, 11, 8, 86, 69, 32, 79, 70, 32, 80, 69, 174, + 4, 79, 223, 25, 68, 9, 33, 6, 32, 87, 73, 84, 72, 32, 6, 40, 4, 84, 69, + 88, 84, 191, 133, 2, 80, 5, 185, 133, 2, 6, 32, 65, 78, 68, 32, 80, 22, + 164, 1, 11, 67, 79, 78, 84, 65, 73, 78, 32, 65, 83, 32, 92, 6, 68, 73, + 86, 73, 68, 69, 112, 2, 80, 82, 48, 7, 83, 85, 67, 67, 69, 69, 68, 233, + 251, 21, 2, 70, 79, 6, 248, 1, 15, 78, 79, 82, 77, 65, 76, 32, 83, 85, + 66, 71, 82, 79, 85, 80, 195, 170, 20, 77, 5, 209, 170, 21, 23, 32, 87, + 73, 84, 72, 32, 82, 69, 86, 69, 82, 83, 69, 68, 32, 78, 69, 71, 65, 84, + 73, 79, 78, 6, 44, 5, 69, 67, 69, 68, 69, 243, 141, 27, 79, 5, 217, 240, + 8, 2, 32, 79, 125, 36, 3, 82, 65, 32, 235, 204, 27, 32, 120, 120, 7, 76, + 69, 84, 84, 69, 82, 32, 212, 1, 11, 86, 79, 87, 69, 76, 32, 83, 73, 71, + 78, 32, 158, 199, 22, 65, 191, 2, 83, 88, 214, 232, 23, 82, 206, 55, 65, + 38, 68, 46, 84, 230, 24, 85, 210, 200, 1, 73, 158, 190, 1, 78, 46, 83, + 82, 66, 2, 67, 2, 71, 2, 74, 2, 75, 2, 80, 254, 68, 72, 2, 76, 2, 77, 2, + 86, 2, 89, 186, 2, 69, 3, 79, 22, 162, 193, 18, 86, 166, 225, 5, 65, 190, + 21, 85, 210, 200, 1, 73, 206, 134, 2, 69, 3, 79, 4, 182, 194, 20, 80, + 243, 173, 2, 76, 200, 1, 72, 8, 72, 79, 82, 73, 90, 79, 78, 84, 1, 6, 86, + 69, 82, 84, 73, 67, 100, 17, 2, 65, 76, 100, 32, 2, 45, 48, 191, 162, 23, + 32, 98, 58, 48, 2, 49, 2, 50, 2, 51, 2, 52, 2, 53, 3, 54, 14, 197, 219, + 19, 2, 45, 48, 4, 254, 237, 25, 75, 223, 143, 1, 71, 26, 34, 32, 57, 4, + 84, 69, 68, 32, 8, 254, 166, 24, 80, 34, 77, 202, 50, 79, 187, 173, 2, + 65, 18, 214, 1, 67, 34, 83, 144, 213, 15, 3, 76, 73, 78, 192, 132, 1, 4, + 79, 66, 69, 76, 160, 9, 9, 84, 82, 65, 78, 83, 80, 79, 83, 73, 134, 194, + 6, 70, 141, 41, 14, 82, 73, 71, 72, 84, 45, 80, 79, 73, 78, 84, 73, 78, + 71, 4, 238, 178, 26, 73, 167, 17, 82, 4, 182, 241, 25, 79, 223, 111, 81, + 162, 1, 40, 3, 66, 76, 69, 137, 17, 2, 71, 72, 160, 1, 42, 32, 190, 10, + 45, 241, 5, 2, 68, 32, 106, 226, 2, 67, 174, 1, 68, 38, 72, 32, 4, 73, + 78, 84, 69, 38, 76, 144, 1, 7, 78, 69, 83, 84, 69, 68, 32, 74, 80, 66, + 83, 130, 2, 85, 36, 9, 86, 69, 82, 84, 73, 67, 65, 76, 32, 132, 140, 6, + 6, 79, 66, 76, 73, 81, 85, 172, 167, 2, 9, 82, 73, 71, 72, 84, 32, 65, + 82, 67, 194, 174, 3, 65, 186, 189, 9, 69, 190, 141, 4, 81, 213, 101, 6, + 87, 65, 86, 89, 32, 79, 24, 100, 7, 73, 82, 67, 76, 69, 68, 32, 252, 166, + 7, 4, 85, 82, 76, 89, 145, 191, 1, 4, 79, 76, 79, 78, 20, 26, 78, 139, + 249, 19, 68, 2, 137, 199, 2, 5, 85, 77, 66, 69, 82, 4, 186, 160, 18, 79, + 131, 164, 6, 65, 4, 186, 243, 19, 73, 215, 63, 89, 4, 230, 136, 25, 82, + 223, 233, 1, 71, 12, 54, 79, 141, 222, 16, 7, 69, 70, 84, 32, 65, 82, 67, + 10, 26, 87, 163, 207, 24, 71, 6, 26, 45, 187, 225, 26, 32, 4, 162, 242, + 19, 82, 211, 1, 57, 6, 196, 204, 16, 9, 76, 69, 83, 83, 45, 84, 72, 65, + 78, 255, 158, 9, 71, 8, 26, 82, 247, 246, 25, 76, 6, 154, 152, 1, 69, + 139, 180, 15, 73, 18, 80, 6, 81, 85, 65, 82, 69, 32, 30, 84, 50, 85, 185, + 161, 13, 4, 79, 76, 73, 68, 4, 238, 221, 24, 73, 55, 85, 4, 252, 138, 12, + 3, 65, 67, 75, 187, 192, 4, 82, 8, 58, 83, 186, 150, 1, 67, 170, 182, 20, + 80, 191, 194, 4, 66, 2, 209, 142, 27, 4, 80, 69, 78, 83, 4, 210, 155, 18, + 80, 179, 139, 9, 78, 10, 36, 3, 66, 65, 82, 211, 221, 26, 76, 9, 11, 32, + 6, 52, 7, 68, 79, 85, 66, 76, 69, 32, 163, 215, 25, 76, 4, 158, 215, 25, + 76, 51, 82, 48, 112, 5, 76, 73, 78, 69, 32, 220, 1, 7, 83, 84, 82, 85, + 67, 75, 32, 189, 182, 8, 7, 69, 78, 68, 69, 68, 32, 77, 12, 48, 8, 83, + 76, 65, 78, 84, 69, 68, 32, 75, 69, 8, 70, 69, 56, 7, 71, 82, 69, 65, 84, + 69, 82, 1, 4, 76, 69, 83, 83, 4, 177, 232, 19, 9, 81, 85, 65, 76, 32, 84, + 79, 32, 79, 2, 193, 239, 13, 5, 45, 84, 72, 65, 78, 34, 160, 1, 8, 67, + 65, 80, 73, 84, 65, 76, 32, 92, 7, 73, 84, 65, 76, 73, 67, 32, 124, 6, + 83, 77, 65, 76, 76, 32, 153, 155, 13, 8, 78, 45, 65, 82, 89, 32, 83, 85, + 18, 234, 238, 11, 71, 230, 252, 13, 80, 206, 134, 2, 67, 2, 72, 2, 78, 2, + 81, 2, 82, 3, 90, 10, 76, 6, 83, 77, 65, 76, 76, 32, 185, 151, 21, 7, 67, + 65, 80, 73, 84, 65, 76, 8, 238, 240, 27, 68, 2, 69, 2, 73, 3, 74, 4, 146, + 237, 11, 71, 219, 239, 15, 80, 6, 146, 237, 9, 70, 26, 77, 255, 239, 16, + 83, 2, 179, 246, 26, 78, 144, 1, 86, 32, 156, 1, 10, 45, 80, 79, 73, 78, + 84, 73, 78, 71, 32, 65, 4, 87, 65, 82, 68, 10, 60, 4, 84, 65, 67, 75, + 250, 222, 24, 70, 30, 82, 251, 64, 65, 5, 29, 5, 32, 87, 73, 84, 72, 2, + 11, 32, 2, 11, 67, 2, 201, 169, 20, 4, 73, 82, 67, 76, 8, 178, 225, 24, + 82, 0, 7, 83, 77, 65, 76, 76, 32, 82, 35, 84, 126, 56, 8, 32, 70, 65, 67, + 73, 78, 71, 32, 89, 2, 83, 32, 8, 54, 72, 1, 9, 78, 79, 84, 67, 72, 69, + 68, 32, 72, 4, 137, 201, 26, 3, 79, 79, 75, 118, 158, 1, 65, 202, 2, 84, + 168, 192, 8, 2, 87, 72, 186, 138, 8, 90, 198, 184, 8, 66, 154, 1, 68, 50, + 70, 82, 72, 146, 4, 67, 46, 81, 42, 82, 22, 83, 243, 7, 80, 34, 40, 4, + 82, 82, 79, 87, 187, 255, 24, 78, 33, 11, 32, 30, 144, 1, 5, 87, 73, 84, + 72, 32, 208, 147, 3, 14, 76, 69, 70, 84, 87, 65, 82, 68, 83, 32, 79, 70, + 32, 85, 254, 235, 21, 65, 170, 10, 70, 175, 5, 84, 22, 180, 163, 5, 6, + 67, 79, 82, 78, 69, 82, 182, 222, 19, 68, 58, 76, 42, 77, 38, 78, 58, 83, + 66, 69, 246, 12, 84, 139, 59, 72, 36, 36, 2, 82, 73, 161, 2, 2, 87, 79, + 32, 44, 5, 65, 78, 71, 76, 69, 171, 146, 25, 80, 30, 56, 8, 45, 72, 69, + 65, 68, 69, 68, 32, 215, 152, 25, 32, 28, 68, 5, 65, 82, 82, 79, 87, 134, + 201, 16, 90, 162, 199, 8, 68, 39, 80, 23, 11, 32, 20, 216, 139, 25, 15, + 76, 69, 70, 84, 87, 65, 82, 68, 83, 32, 79, 70, 32, 85, 80, 98, 84, 19, + 87, 4, 162, 145, 25, 32, 105, 15, 45, 72, 69, 65, 68, 69, 68, 32, 65, 82, + 82, 79, 87, 32, 87, 22, 138, 1, 65, 106, 79, 152, 1, 12, 85, 77, 32, 87, + 73, 84, 72, 32, 68, 82, 85, 77, 152, 182, 16, 6, 73, 86, 69, 32, 83, 76, + 179, 149, 10, 69, 8, 238, 189, 2, 67, 236, 243, 5, 10, 70, 84, 73, 78, + 71, 32, 80, 79, 73, 78, 201, 192, 15, 3, 71, 79, 78, 8, 56, 6, 77, 69, + 68, 65, 82, 89, 34, 80, 251, 174, 26, 79, 2, 217, 160, 20, 3, 32, 67, 65, + 4, 240, 234, 17, 6, 32, 79, 70, 32, 66, 76, 191, 194, 9, 76, 2, 217, 165, + 12, 3, 83, 84, 73, 162, 2, 76, 7, 80, 76, 79, 89, 65, 78, 32, 128, 187, + 19, 2, 77, 80, 247, 162, 8, 67, 158, 2, 212, 2, 6, 65, 70, 70, 73, 88, + 32, 152, 7, 7, 76, 69, 84, 84, 69, 82, 32, 208, 188, 1, 16, 84, 72, 73, + 67, 75, 32, 76, 69, 84, 84, 69, 82, 32, 83, 69, 76, 236, 160, 3, 4, 68, + 79, 85, 66, 204, 172, 16, 19, 80, 85, 78, 67, 84, 85, 65, 84, 73, 79, 78, + 32, 67, 72, 73, 78, 79, 79, 75, 153, 143, 5, 11, 83, 73, 71, 78, 32, 79, + 32, 87, 73, 84, 72, 64, 140, 1, 9, 65, 84, 84, 65, 67, 72, 69, 68, 32, + 184, 1, 5, 72, 73, 71, 72, 32, 102, 76, 40, 4, 82, 73, 71, 72, 169, 2, 4, + 77, 73, 68, 32, 14, 112, 2, 84, 65, 224, 4, 13, 76, 69, 70, 84, 45, 84, + 79, 45, 82, 73, 71, 72, 84, 26, 83, 146, 165, 20, 69, 3, 73, 6, 44, 5, + 78, 71, 69, 78, 84, 227, 210, 26, 73, 5, 227, 169, 20, 32, 20, 166, 2, + 76, 50, 84, 38, 86, 238, 134, 8, 71, 186, 2, 65, 154, 231, 17, 87, 170, + 25, 67, 223, 126, 68, 24, 36, 2, 69, 70, 29, 3, 79, 87, 32, 2, 209, 2, 3, + 84, 32, 72, 22, 90, 65, 38, 76, 50, 84, 38, 86, 238, 134, 8, 71, 210, + 233, 17, 87, 170, 25, 67, 223, 126, 68, 4, 202, 150, 21, 67, 131, 169, 5, + 82, 4, 220, 216, 7, 3, 79, 78, 71, 207, 231, 18, 73, 2, 173, 254, 7, 4, + 73, 71, 72, 84, 4, 37, 7, 69, 82, 84, 73, 67, 65, 76, 5, 131, 1, 32, 4, + 42, 72, 41, 6, 86, 69, 82, 84, 73, 67, 2, 37, 7, 79, 82, 73, 90, 79, 78, + 84, 2, 17, 2, 65, 76, 2, 11, 32, 2, 11, 83, 2, 237, 205, 26, 2, 69, 67, + 214, 1, 222, 1, 65, 22, 68, 34, 69, 30, 70, 22, 71, 22, 74, 162, 1, 75, + 66, 76, 50, 77, 62, 78, 134, 1, 79, 50, 80, 86, 82, 74, 83, 210, 2, 84, + 66, 85, 42, 86, 38, 87, 70, 88, 230, 206, 26, 72, 138, 60, 73, 194, 41, + 89, 215, 22, 66, 5, 203, 176, 27, 79, 7, 206, 151, 27, 32, 211, 61, 72, + 7, 254, 212, 27, 69, 3, 85, 5, 143, 133, 27, 32, 5, 207, 129, 24, 32, 19, + 11, 32, 16, 76, 8, 87, 73, 84, 72, 32, 68, 79, 84, 230, 5, 77, 2, 78, + 215, 170, 26, 83, 5, 233, 214, 26, 12, 83, 32, 73, 78, 83, 73, 68, 69, + 32, 65, 78, 68, 9, 26, 32, 131, 211, 27, 75, 4, 138, 128, 24, 82, 247, + 210, 3, 77, 9, 248, 243, 21, 3, 79, 78, 71, 227, 222, 5, 72, 11, 11, 32, + 8, 162, 4, 78, 238, 170, 26, 87, 147, 163, 1, 83, 19, 38, 32, 49, 5, 65, + 83, 65, 76, 32, 8, 202, 3, 77, 238, 170, 26, 87, 147, 163, 1, 83, 8, 150, + 209, 27, 65, 2, 73, 2, 79, 3, 85, 11, 218, 207, 27, 79, 146, 1, 65, 2, + 85, 3, 87, 9, 52, 7, 69, 82, 78, 73, 78, 32, 65, 179, 128, 27, 32, 4, + 130, 208, 27, 77, 3, 78, 11, 248, 240, 21, 6, 79, 77, 65, 78, 73, 65, + 158, 161, 5, 32, 211, 61, 72, 49, 58, 32, 164, 1, 5, 76, 79, 65, 78, 32, + 195, 158, 6, 72, 26, 102, 74, 22, 75, 2, 80, 2, 84, 20, 7, 87, 73, 84, + 72, 32, 68, 79, 214, 205, 27, 77, 2, 78, 3, 83, 5, 171, 144, 27, 32, 5, + 151, 149, 27, 32, 4, 183, 165, 12, 84, 18, 74, 69, 138, 176, 5, 79, 154, + 205, 21, 65, 198, 78, 68, 146, 1, 74, 3, 85, 6, 242, 204, 27, 69, 2, 72, + 3, 78, 9, 26, 32, 183, 204, 27, 72, 4, 190, 249, 23, 82, 247, 210, 3, 83, + 9, 186, 252, 26, 32, 214, 79, 72, 3, 73, 5, 217, 237, 6, 4, 79, 67, 65, + 76, 17, 66, 79, 178, 146, 27, 32, 250, 36, 69, 218, 19, 65, 2, 72, 3, 73, + 5, 255, 202, 27, 87, 250, 28, 234, 2, 65, 188, 3, 10, 68, 73, 84, 79, 82, + 73, 65, 76, 32, 67, 22, 71, 240, 75, 4, 73, 71, 72, 84, 198, 1, 76, 194, + 9, 77, 214, 5, 78, 246, 3, 79, 36, 2, 81, 85, 182, 8, 82, 222, 1, 83, + 118, 84, 242, 31, 85, 198, 1, 88, 252, 3, 2, 89, 69, 152, 72, 4, 45, 77, + 65, 73, 132, 207, 18, 3, 74, 69, 67, 168, 134, 2, 8, 86, 69, 82, 71, 82, + 69, 69, 78, 159, 147, 5, 80, 22, 38, 82, 130, 230, 25, 83, 179, 64, 71, + 19, 30, 32, 137, 1, 2, 84, 72, 6, 88, 3, 79, 70, 32, 221, 210, 4, 13, 87, + 73, 84, 72, 32, 72, 69, 65, 82, 73, 78, 71, 32, 4, 216, 138, 11, 2, 77, + 65, 227, 206, 6, 82, 11, 17, 2, 32, 71, 8, 44, 5, 76, 79, 66, 69, 32, + 239, 165, 24, 82, 6, 70, 65, 149, 207, 13, 11, 69, 85, 82, 79, 80, 69, + 45, 65, 70, 82, 73, 4, 128, 214, 9, 4, 77, 69, 82, 73, 133, 154, 2, 11, + 83, 73, 65, 45, 65, 85, 83, 84, 82, 65, 76, 2, 191, 163, 2, 79, 174, 17, + 96, 18, 89, 80, 84, 73, 65, 78, 32, 72, 73, 69, 82, 79, 71, 76, 89, 80, + 72, 32, 199, 195, 27, 71, 172, 17, 146, 3, 65, 178, 4, 66, 52, 2, 67, 48, + 224, 1, 2, 68, 48, 170, 4, 69, 198, 3, 70, 164, 4, 2, 71, 48, 210, 3, 72, + 222, 1, 73, 238, 2, 76, 122, 77, 134, 9, 78, 210, 5, 79, 140, 5, 2, 80, + 48, 120, 2, 82, 48, 232, 1, 2, 83, 48, 190, 3, 84, 220, 2, 2, 85, 48, + 250, 2, 86, 134, 5, 87, 236, 2, 3, 88, 48, 48, 88, 3, 89, 48, 48, 84, 2, + 90, 48, 224, 196, 3, 3, 75, 48, 48, 177, 218, 14, 3, 81, 48, 48, 228, 1, + 30, 48, 133, 3, 2, 65, 48, 160, 1, 86, 48, 98, 49, 102, 52, 234, 55, 51, + 138, 163, 20, 55, 230, 216, 1, 50, 2, 53, 3, 54, 24, 238, 68, 54, 146, + 185, 21, 53, 174, 193, 5, 49, 2, 50, 2, 51, 2, 52, 2, 55, 2, 56, 3, 57, + 24, 158, 253, 21, 52, 2, 55, 174, 193, 5, 48, 2, 49, 2, 50, 2, 51, 2, 53, + 2, 54, 2, 56, 3, 57, 28, 186, 252, 21, 48, 2, 50, 2, 51, 2, 53, 174, 193, + 5, 49, 2, 52, 2, 54, 2, 55, 2, 56, 3, 57, 68, 46, 48, 186, 55, 51, 138, + 251, 21, 49, 3, 50, 22, 150, 66, 55, 190, 250, 26, 49, 2, 50, 2, 51, 2, + 52, 2, 53, 2, 54, 2, 56, 3, 57, 26, 148, 9, 4, 69, 71, 73, 78, 253, 25, + 2, 48, 48, 56, 34, 48, 90, 49, 207, 199, 8, 50, 24, 170, 40, 50, 250, + 146, 27, 49, 2, 51, 2, 52, 2, 53, 2, 54, 2, 55, 2, 56, 3, 57, 22, 158, + 249, 21, 48, 174, 193, 5, 49, 2, 50, 2, 51, 2, 52, 2, 53, 2, 54, 2, 55, + 2, 56, 3, 57, 184, 1, 70, 48, 94, 51, 102, 52, 102, 53, 106, 54, 134, 30, + 50, 251, 141, 22, 49, 20, 238, 247, 21, 56, 174, 193, 5, 49, 2, 50, 2, + 51, 2, 52, 2, 53, 2, 54, 2, 55, 3, 57, 24, 146, 247, 21, 49, 2, 52, 174, + 193, 5, 48, 2, 50, 2, 51, 2, 53, 2, 54, 2, 55, 2, 56, 3, 57, 24, 174, + 246, 21, 54, 2, 56, 174, 193, 5, 48, 2, 49, 2, 50, 2, 51, 2, 52, 2, 53, + 2, 55, 3, 57, 42, 154, 61, 48, 178, 184, 21, 50, 2, 52, 174, 193, 5, 49, + 2, 51, 2, 53, 2, 54, 2, 55, 2, 56, 3, 57, 32, 134, 61, 55, 138, 249, 26, + 48, 2, 49, 2, 50, 2, 51, 2, 52, 2, 53, 3, 54, 94, 30, 48, 189, 2, 2, 78, + 68, 88, 38, 48, 94, 50, 102, 51, 235, 7, 49, 22, 202, 243, 21, 56, 2, 57, + 174, 193, 5, 49, 2, 50, 2, 51, 2, 52, 2, 53, 2, 54, 3, 55, 24, 238, 242, + 21, 48, 2, 56, 174, 193, 5, 49, 2, 50, 2, 51, 2, 52, 2, 53, 2, 54, 2, 55, + 3, 57, 18, 138, 242, 21, 52, 174, 193, 5, 48, 2, 49, 2, 50, 2, 51, 2, 54, + 2, 55, 3, 56, 6, 11, 32, 6, 68, 2, 83, 69, 136, 160, 5, 6, 87, 65, 76, + 76, 69, 68, 191, 19, 69, 2, 231, 238, 26, 71, 132, 1, 42, 48, 133, 9, 5, + 85, 76, 76, 32, 66, 130, 1, 54, 48, 94, 49, 102, 51, 102, 52, 102, 53, + 215, 1, 50, 20, 226, 239, 21, 49, 174, 193, 5, 50, 2, 51, 2, 52, 2, 53, + 2, 54, 2, 55, 2, 56, 3, 57, 22, 134, 239, 21, 51, 174, 193, 5, 48, 2, 49, + 2, 50, 2, 52, 2, 53, 2, 54, 2, 55, 2, 56, 3, 57, 26, 162, 238, 21, 49, 2, + 55, 2, 56, 174, 193, 5, 48, 2, 50, 2, 51, 2, 52, 2, 53, 2, 54, 3, 57, 26, + 190, 237, 21, 53, 2, 54, 2, 55, 174, 193, 5, 48, 2, 49, 2, 50, 2, 51, 2, + 52, 2, 56, 3, 57, 14, 142, 27, 49, 250, 146, 27, 48, 2, 50, 3, 51, 128, + 1, 62, 48, 98, 49, 102, 51, 102, 52, 130, 28, 50, 239, 155, 8, 53, 24, + 214, 50, 55, 146, 185, 21, 54, 174, 193, 5, 49, 2, 50, 2, 51, 2, 52, 2, + 53, 2, 56, 3, 57, 22, 134, 235, 21, 49, 174, 193, 5, 48, 2, 50, 2, 51, 2, + 52, 2, 53, 2, 54, 2, 55, 2, 56, 3, 57, 24, 162, 234, 21, 54, 2, 55, 174, + 193, 5, 48, 2, 49, 2, 50, 2, 51, 2, 52, 2, 53, 2, 56, 3, 57, 24, 190, + 233, 21, 51, 2, 53, 174, 193, 5, 48, 2, 49, 2, 50, 2, 52, 2, 54, 2, 55, + 2, 56, 3, 57, 24, 80, 2, 48, 48, 84, 4, 65, 76, 70, 32, 209, 40, 7, 79, + 82, 73, 90, 79, 78, 84, 18, 134, 232, 21, 54, 174, 193, 5, 49, 2, 50, 2, + 51, 2, 52, 2, 53, 2, 55, 3, 56, 4, 22, 66, 175, 43, 76, 2, 237, 233, 23, + 2, 76, 65, 52, 58, 48, 181, 1, 9, 78, 83, 69, 82, 84, 32, 65, 84, 32, 38, + 18, 48, 95, 49, 22, 174, 230, 21, 53, 2, 57, 174, 193, 5, 49, 2, 50, 2, + 51, 2, 52, 2, 54, 2, 55, 3, 56, 16, 210, 229, 21, 48, 2, 49, 174, 193, 5, + 50, 2, 51, 2, 52, 3, 53, 14, 68, 6, 66, 79, 84, 84, 79, 77, 0, 3, 84, 79, + 80, 239, 138, 19, 77, 7, 11, 32, 4, 134, 152, 26, 69, 221, 6, 2, 83, 84, + 22, 32, 2, 48, 48, 215, 162, 15, 79, 20, 238, 227, 21, 50, 2, 54, 174, + 193, 5, 49, 2, 51, 2, 52, 2, 53, 2, 55, 3, 56, 164, 1, 158, 1, 48, 128, + 4, 15, 79, 68, 73, 70, 73, 69, 82, 32, 68, 65, 77, 65, 71, 69, 68, 189, + 239, 23, 14, 73, 82, 82, 79, 82, 32, 72, 79, 82, 73, 90, 79, 78, 84, 132, + 1, 42, 48, 98, 49, 106, 50, 102, 51, 107, 52, 24, 182, 40, 49, 146, 185, + 21, 51, 174, 193, 5, 50, 2, 52, 2, 53, 2, 54, 2, 55, 2, 56, 3, 57, 44, + 138, 41, 50, 222, 183, 21, 48, 2, 53, 2, 54, 2, 55, 174, 193, 5, 49, 2, + 51, 2, 52, 2, 56, 3, 57, 26, 254, 223, 21, 50, 2, 52, 2, 56, 174, 193, 5, + 48, 2, 49, 2, 51, 2, 53, 2, 54, 2, 55, 3, 57, 26, 138, 38, 51, 146, 185, + 21, 49, 174, 193, 5, 48, 2, 50, 2, 52, 2, 53, 2, 54, 2, 55, 2, 56, 3, 57, + 12, 178, 222, 21, 48, 174, 193, 5, 49, 2, 50, 2, 51, 3, 52, 31, 25, 4, + 32, 65, 84, 32, 28, 96, 6, 66, 79, 84, 84, 79, 77, 120, 5, 83, 84, 65, + 82, 84, 68, 3, 84, 79, 80, 139, 143, 26, 69, 11, 11, 32, 8, 56, 5, 83, + 84, 65, 82, 84, 186, 1, 65, 199, 142, 26, 69, 5, 129, 2, 8, 32, 65, 78, + 68, 32, 84, 79, 80, 7, 29, 5, 32, 65, 78, 68, 32, 4, 146, 212, 23, 66, + 247, 207, 2, 84, 11, 11, 32, 8, 54, 65, 20, 5, 83, 84, 65, 82, 84, 179, + 142, 26, 69, 2, 73, 2, 78, 68, 5, 53, 11, 32, 65, 78, 68, 32, 66, 79, 84, + 84, 79, 77, 2, 235, 135, 19, 32, 194, 1, 50, 48, 128, 2, 2, 76, 48, 229, + 1, 2, 85, 48, 98, 58, 49, 98, 51, 194, 14, 50, 150, 6, 52, 155, 249, 21, + 48, 24, 146, 32, 56, 190, 250, 26, 48, 2, 49, 2, 50, 2, 51, 2, 52, 2, 53, + 2, 54, 2, 55, 3, 57, 28, 194, 216, 21, 51, 2, 52, 2, 53, 2, 55, 174, 193, + 5, 48, 2, 49, 2, 50, 2, 54, 2, 56, 3, 57, 44, 34, 48, 94, 49, 151, 181, + 20, 50, 20, 186, 215, 21, 53, 174, 193, 5, 49, 2, 50, 2, 51, 2, 52, 2, + 54, 2, 55, 2, 56, 3, 57, 22, 222, 214, 21, 55, 174, 193, 5, 48, 2, 49, 2, + 50, 2, 51, 2, 52, 2, 53, 2, 54, 2, 56, 3, 57, 52, 34, 49, 102, 50, 159, + 138, 22, 48, 26, 214, 213, 21, 48, 2, 49, 2, 56, 174, 193, 5, 50, 2, 51, + 2, 52, 2, 53, 2, 54, 2, 55, 3, 57, 8, 242, 212, 21, 50, 174, 193, 5, 48, + 3, 49, 152, 1, 50, 48, 229, 172, 18, 6, 86, 69, 82, 76, 65, 89, 150, 1, + 66, 48, 154, 1, 49, 138, 1, 50, 102, 51, 106, 53, 247, 134, 22, 52, 34, + 90, 54, 238, 210, 21, 49, 2, 53, 174, 193, 5, 50, 2, 51, 2, 52, 2, 55, 2, + 56, 3, 57, 15, 150, 148, 27, 65, 2, 66, 2, 67, 2, 68, 2, 69, 3, 70, 28, + 98, 48, 206, 209, 21, 57, 174, 193, 5, 49, 2, 50, 2, 51, 2, 52, 2, 53, 2, + 54, 2, 55, 3, 56, 9, 246, 146, 27, 65, 2, 66, 3, 67, 28, 166, 209, 21, + 48, 2, 52, 2, 53, 2, 57, 174, 193, 5, 49, 2, 50, 2, 51, 2, 54, 2, 55, 3, + 56, 32, 134, 23, 54, 190, 185, 21, 48, 2, 51, 174, 193, 5, 49, 2, 50, 2, + 52, 2, 53, 2, 55, 2, 56, 3, 57, 8, 202, 22, 48, 191, 250, 26, 49, 26, 26, + 48, 235, 148, 8, 49, 22, 158, 207, 21, 49, 2, 51, 174, 193, 5, 50, 2, 52, + 2, 53, 2, 54, 2, 55, 2, 56, 3, 57, 68, 34, 48, 98, 49, 219, 132, 22, 50, + 24, 142, 21, 51, 146, 185, 21, 50, 174, 193, 5, 49, 2, 52, 2, 53, 2, 54, + 2, 55, 2, 56, 3, 57, 24, 190, 205, 21, 48, 2, 54, 174, 193, 5, 49, 2, 50, + 2, 51, 2, 52, 2, 53, 2, 55, 2, 56, 3, 57, 108, 50, 48, 94, 49, 106, 50, + 98, 51, 155, 226, 18, 52, 22, 166, 204, 21, 50, 2, 54, 174, 193, 5, 49, + 2, 51, 2, 52, 2, 53, 2, 55, 2, 56, 3, 57, 26, 186, 18, 52, 146, 185, 21, + 55, 174, 193, 5, 48, 2, 49, 2, 50, 2, 51, 2, 53, 2, 54, 2, 56, 3, 57, 24, + 210, 17, 54, 190, 250, 26, 48, 2, 49, 2, 50, 2, 51, 2, 52, 2, 53, 2, 55, + 2, 56, 3, 57, 22, 130, 202, 21, 53, 174, 193, 5, 48, 2, 49, 2, 50, 2, 51, + 2, 52, 2, 54, 2, 55, 2, 56, 3, 57, 90, 34, 48, 249, 12, 3, 65, 76, 76, + 88, 42, 48, 94, 49, 102, 51, 171, 254, 21, 50, 26, 206, 200, 21, 51, 2, + 55, 2, 56, 2, 57, 174, 193, 5, 49, 2, 50, 2, 52, 2, 53, 3, 54, 24, 242, + 199, 21, 49, 2, 54, 174, 193, 5, 48, 2, 50, 2, 51, 2, 52, 2, 53, 2, 55, + 2, 56, 3, 57, 18, 142, 199, 21, 50, 2, 51, 174, 193, 5, 48, 2, 49, 2, 52, + 2, 53, 3, 54, 94, 50, 48, 90, 50, 102, 51, 102, 52, 139, 251, 21, 49, 22, + 254, 12, 54, 190, 250, 26, 49, 2, 50, 2, 51, 2, 52, 2, 53, 2, 55, 2, 56, + 3, 57, 24, 182, 197, 21, 51, 2, 57, 174, 193, 5, 48, 2, 49, 2, 50, 2, 52, + 2, 53, 2, 54, 2, 55, 3, 56, 22, 210, 196, 21, 50, 174, 193, 5, 48, 2, 49, + 2, 51, 2, 52, 2, 53, 2, 54, 2, 55, 2, 56, 3, 57, 6, 154, 133, 27, 48, 2, + 49, 3, 50, 158, 1, 42, 48, 185, 4, 5, 69, 82, 84, 73, 67, 156, 1, 62, 48, + 98, 49, 98, 50, 210, 1, 51, 201, 191, 21, 2, 52, 48, 42, 198, 9, 55, 98, + 49, 178, 184, 21, 50, 174, 193, 5, 51, 2, 52, 2, 53, 2, 54, 2, 56, 3, 57, + 32, 186, 8, 49, 46, 50, 190, 250, 26, 48, 2, 51, 2, 52, 2, 53, 2, 54, 2, + 55, 2, 56, 3, 57, 50, 98, 48, 182, 192, 21, 51, 2, 56, 2, 57, 174, 193, + 5, 49, 2, 50, 2, 52, 2, 53, 2, 54, 3, 55, 27, 222, 129, 27, 65, 2, 66, 2, + 67, 2, 68, 2, 69, 2, 70, 2, 71, 2, 72, 2, 73, 2, 74, 2, 75, 3, 76, 28, + 198, 191, 21, 48, 2, 49, 2, 51, 2, 55, 174, 193, 5, 50, 2, 52, 2, 53, 2, + 54, 2, 56, 3, 57, 2, 169, 134, 23, 2, 65, 76, 66, 34, 48, 161, 2, 3, 73, + 68, 69, 64, 26, 48, 94, 49, 103, 50, 22, 134, 190, 21, 51, 2, 57, 174, + 193, 5, 49, 2, 50, 2, 52, 2, 53, 2, 54, 2, 55, 3, 56, 28, 170, 189, 21, + 48, 2, 52, 2, 55, 2, 56, 174, 193, 5, 49, 2, 50, 2, 51, 2, 53, 2, 54, 3, + 57, 14, 198, 188, 21, 52, 174, 193, 5, 48, 2, 49, 2, 50, 2, 51, 3, 53, 2, + 17, 2, 32, 76, 2, 211, 250, 14, 79, 24, 202, 2, 52, 146, 185, 21, 54, 2, + 56, 174, 193, 5, 49, 2, 50, 2, 51, 2, 53, 3, 55, 18, 130, 187, 21, 49, + 174, 193, 5, 50, 2, 51, 2, 52, 2, 53, 2, 54, 2, 55, 3, 56, 82, 22, 48, + 167, 1, 49, 34, 90, 50, 46, 51, 146, 185, 21, 52, 2, 53, 174, 193, 5, 49, + 2, 54, 2, 55, 2, 56, 3, 57, 11, 230, 250, 26, 65, 2, 66, 2, 67, 3, 68, 7, + 186, 250, 26, 65, 3, 66, 48, 66, 53, 86, 54, 138, 249, 26, 48, 2, 49, 2, + 50, 2, 51, 3, 52, 21, 218, 249, 26, 65, 2, 66, 2, 67, 2, 68, 2, 69, 2, + 70, 2, 71, 2, 72, 3, 73, 19, 134, 249, 26, 65, 2, 66, 2, 67, 2, 68, 2, + 69, 2, 70, 2, 71, 3, 72, 14, 26, 32, 159, 171, 15, 72, 12, 42, 80, 242, + 133, 3, 84, 135, 225, 21, 83, 8, 242, 132, 3, 79, 213, 129, 16, 22, 69, + 84, 65, 76, 76, 69, 68, 32, 79, 85, 84, 76, 73, 78, 69, 68, 32, 66, 76, + 65, 67, 75, 160, 1, 132, 1, 13, 66, 65, 83, 65, 78, 32, 76, 69, 84, 84, + 69, 82, 32, 166, 3, 69, 176, 4, 7, 89, 77, 65, 73, 67, 32, 76, 155, 238, + 26, 70, 80, 230, 1, 71, 78, 76, 34, 78, 50, 82, 158, 236, 24, 69, 198, + 134, 1, 67, 2, 68, 2, 75, 2, 83, 2, 84, 2, 90, 182, 105, 66, 2, 70, 2, + 72, 2, 74, 2, 77, 2, 80, 2, 81, 2, 86, 2, 88, 214, 22, 65, 2, 73, 2, 79, + 2, 85, 3, 89, 8, 38, 72, 138, 221, 26, 74, 215, 22, 69, 4, 194, 168, 24, + 65, 155, 203, 2, 69, 4, 226, 220, 26, 76, 215, 22, 69, 8, 194, 220, 26, + 68, 2, 74, 214, 22, 65, 3, 69, 4, 146, 220, 26, 82, 215, 22, 69, 32, 96, + 5, 67, 84, 82, 73, 67, 160, 1, 7, 77, 69, 78, 84, 32, 79, 70, 246, 230, + 25, 80, 223, 80, 86, 10, 26, 32, 215, 165, 23, 65, 8, 98, 80, 244, 134, + 17, 2, 84, 79, 204, 175, 8, 9, 76, 73, 71, 72, 84, 32, 66, 85, 76, 131, + 32, 65, 2, 11, 76, 2, 131, 240, 26, 85, 19, 11, 32, 16, 72, 5, 87, 73, + 84, 72, 32, 157, 142, 16, 7, 79, 80, 69, 78, 73, 78, 71, 12, 130, 1, 76, + 32, 12, 84, 87, 79, 32, 72, 79, 82, 73, 90, 79, 78, 84, 186, 144, 19, 86, + 186, 149, 4, 85, 166, 47, 79, 131, 153, 2, 68, 2, 141, 209, 24, 3, 79, + 78, 71, 2, 233, 158, 14, 7, 65, 76, 32, 83, 84, 82, 79, 46, 170, 154, 4, + 69, 153, 147, 15, 15, 73, 71, 65, 84, 85, 82, 69, 32, 90, 65, 89, 73, 78, + 45, 89, 53, 48, 4, 79, 74, 73, 32, 218, 2, 80, 163, 3, 32, 18, 164, 1, + 10, 67, 79, 77, 80, 79, 78, 69, 78, 84, 32, 109, 26, 77, 79, 68, 73, 70, + 73, 69, 82, 32, 70, 73, 84, 90, 80, 65, 84, 82, 73, 67, 75, 32, 84, 89, + 80, 69, 45, 8, 140, 200, 14, 2, 82, 69, 12, 5, 67, 85, 82, 76, 89, 0, 5, + 87, 72, 73, 84, 69, 173, 190, 2, 2, 66, 65, 10, 152, 135, 20, 2, 49, 45, + 214, 227, 6, 51, 2, 52, 2, 53, 3, 54, 26, 44, 3, 84, 89, 32, 225, 229, 3, + 2, 72, 65, 24, 82, 78, 60, 3, 80, 65, 71, 20, 3, 83, 69, 84, 177, 165, + 26, 4, 68, 79, 67, 85, 8, 36, 3, 79, 84, 69, 187, 161, 23, 69, 7, 131, + 232, 12, 32, 4, 139, 229, 24, 69, 11, 33, 6, 32, 87, 73, 84, 72, 32, 8, + 234, 203, 13, 82, 24, 3, 76, 69, 70, 176, 166, 1, 2, 83, 77, 207, 220, 8, + 79, 38, 86, 32, 64, 2, 68, 32, 214, 1, 81, 20, 6, 86, 69, 76, 79, 80, 69, + 235, 164, 15, 84, 6, 42, 81, 186, 129, 25, 68, 139, 167, 1, 83, 2, 191, + 160, 26, 85, 20, 32, 3, 79, 70, 32, 131, 1, 87, 18, 88, 3, 80, 82, 79, + 146, 149, 20, 71, 56, 2, 83, 69, 194, 59, 77, 30, 84, 139, 251, 4, 76, 4, + 210, 149, 20, 84, 239, 206, 5, 79, 2, 241, 169, 19, 7, 73, 84, 72, 32, + 76, 69, 70, 5, 167, 209, 20, 85, 7, 33, 6, 32, 87, 73, 84, 72, 32, 4, 42, + 76, 221, 140, 23, 4, 68, 79, 87, 78, 2, 209, 248, 21, 4, 73, 71, 72, 84, + 6, 238, 227, 26, 76, 2, 77, 3, 84, 44, 28, 2, 65, 76, 231, 6, 73, 38, 30, + 32, 133, 2, 2, 83, 32, 12, 56, 3, 84, 79, 32, 237, 220, 12, 5, 65, 78, + 68, 32, 80, 10, 68, 3, 79, 82, 32, 217, 144, 26, 8, 66, 89, 32, 68, 69, + 70, 73, 78, 8, 64, 3, 80, 82, 69, 28, 3, 83, 85, 67, 170, 210, 24, 71, + 39, 76, 2, 133, 230, 14, 2, 67, 69, 2, 221, 132, 25, 3, 67, 69, 69, 26, + 72, 4, 83, 73, 71, 78, 232, 207, 24, 4, 87, 73, 84, 72, 223, 192, 1, 67, + 23, 11, 32, 20, 42, 65, 201, 1, 5, 87, 73, 84, 72, 32, 12, 112, 5, 66, + 79, 86, 69, 32, 65, 19, 78, 68, 32, 83, 76, 65, 78, 84, 69, 68, 32, 80, + 65, 82, 65, 76, 76, 69, 76, 8, 158, 178, 20, 80, 154, 5, 84, 150, 184, 2, + 76, 231, 207, 2, 82, 5, 135, 205, 6, 32, 8, 160, 1, 4, 66, 85, 77, 80, + 20, 7, 73, 78, 70, 73, 78, 73, 84, 20, 18, 84, 87, 79, 32, 68, 79, 84, + 83, 32, 65, 66, 79, 86, 69, 32, 65, 78, 68, 155, 230, 14, 68, 2, 163, + 224, 25, 89, 2, 159, 182, 24, 89, 2, 17, 2, 32, 84, 2, 195, 181, 24, 87, + 6, 80, 7, 86, 65, 76, 69, 78, 84, 32, 185, 181, 20, 7, 65, 78, 71, 85, + 76, 65, 82, 4, 48, 6, 87, 73, 84, 72, 32, 70, 207, 188, 26, 84, 2, 11, + 79, 2, 177, 229, 2, 2, 85, 82, 20, 152, 1, 11, 82, 79, 82, 45, 66, 65, + 82, 82, 69, 68, 32, 216, 147, 5, 7, 73, 83, 32, 70, 79, 82, 77, 205, 162, + 7, 9, 65, 83, 69, 32, 84, 79, 32, 84, 72, 12, 240, 200, 5, 4, 87, 72, 73, + 84, 13, 5, 66, 76, 65, 67, 75, 10, 58, 67, 20, 6, 84, 73, 77, 65, 84, 69, + 239, 216, 26, 65, 5, 143, 148, 25, 65, 4, 218, 197, 25, 68, 147, 147, 1, + 83, 154, 8, 60, 7, 72, 73, 79, 80, 73, 67, 32, 134, 216, 26, 66, 3, 88, + 150, 8, 204, 1, 2, 67, 79, 232, 1, 7, 78, 85, 77, 66, 69, 82, 32, 114, + 80, 54, 83, 156, 24, 11, 84, 79, 78, 65, 76, 32, 77, 65, 82, 75, 32, 174, + 183, 18, 68, 218, 184, 5, 70, 82, 81, 137, 140, 2, 4, 87, 79, 82, 68, 10, + 26, 77, 183, 134, 26, 76, 8, 52, 7, 66, 73, 78, 73, 78, 71, 32, 167, 211, + 26, 77, 6, 60, 11, 71, 69, 77, 73, 78, 65, 84, 73, 79, 78, 32, 51, 86, 4, + 44, 5, 65, 78, 68, 32, 86, 207, 147, 26, 77, 2, 129, 213, 21, 4, 79, 87, + 69, 76, 22, 66, 84, 226, 171, 21, 72, 210, 188, 3, 69, 30, 70, 42, 78, + 39, 83, 8, 130, 134, 16, 69, 222, 227, 8, 72, 27, 87, 4, 242, 103, 65, + 201, 155, 25, 5, 82, 69, 70, 65, 67, 198, 7, 50, 69, 37, 8, 89, 76, 76, + 65, 66, 76, 69, 32, 4, 154, 157, 23, 77, 187, 204, 2, 67, 194, 7, 210, 1, + 66, 90, 67, 246, 1, 68, 186, 1, 70, 90, 71, 214, 2, 72, 162, 1, 75, 102, + 77, 90, 78, 90, 80, 138, 2, 81, 174, 1, 82, 86, 83, 210, 1, 84, 122, 74, + 2, 76, 138, 1, 87, 2, 89, 66, 88, 134, 1, 90, 95, 86, 38, 194, 12, 87, + 230, 8, 66, 158, 250, 20, 65, 2, 79, 154, 129, 5, 69, 150, 64, 73, 3, 85, + 78, 94, 67, 254, 15, 72, 146, 254, 20, 65, 2, 79, 154, 129, 5, 69, 222, + 61, 87, 186, 2, 73, 3, 85, 42, 70, 72, 198, 141, 21, 65, 154, 129, 5, 69, + 150, 64, 73, 2, 79, 3, 85, 28, 166, 19, 72, 158, 250, 20, 65, 154, 129, + 5, 69, 150, 64, 73, 2, 79, 3, 85, 60, 94, 68, 214, 14, 90, 198, 253, 20, + 65, 2, 79, 154, 129, 5, 69, 222, 61, 87, 186, 2, 73, 3, 85, 30, 210, 14, + 72, 198, 253, 20, 65, 2, 79, 154, 129, 5, 69, 222, 61, 87, 186, 2, 73, 3, + 85, 24, 190, 8, 87, 130, 131, 21, 65, 154, 129, 5, 69, 222, 61, 89, 186, + 2, 73, 2, 79, 3, 85, 118, 142, 1, 85, 226, 7, 71, 232, 3, 7, 76, 79, 84, + 84, 65, 76, 32, 158, 2, 87, 218, 1, 89, 158, 250, 20, 65, 2, 79, 154, + 129, 5, 69, 151, 64, 73, 39, 29, 5, 82, 65, 71, 69, 32, 36, 74, 66, 2, + 70, 2, 77, 2, 80, 46, 71, 2, 75, 2, 81, 191, 210, 11, 72, 4, 11, 87, 4, + 182, 179, 26, 69, 215, 22, 73, 6, 11, 87, 6, 202, 137, 26, 69, 151, 64, + 73, 52, 70, 72, 206, 135, 21, 65, 2, 79, 154, 129, 5, 69, 150, 64, 73, 3, + 85, 36, 202, 4, 87, 230, 8, 89, 158, 250, 20, 65, 154, 129, 5, 69, 150, + 64, 73, 2, 79, 3, 85, 64, 250, 4, 88, 134, 6, 87, 218, 1, 89, 158, 250, + 20, 65, 2, 79, 154, 129, 5, 69, 150, 64, 73, 3, 85, 26, 142, 3, 87, 130, + 131, 21, 65, 2, 79, 154, 129, 5, 69, 222, 61, 89, 186, 2, 73, 3, 85, 36, + 166, 7, 89, 146, 254, 20, 65, 2, 79, 154, 129, 5, 69, 222, 61, 87, 186, + 2, 73, 3, 85, 56, 82, 72, 142, 1, 87, 130, 131, 21, 65, 2, 79, 154, 129, + 5, 69, 150, 64, 73, 3, 85, 32, 74, 65, 194, 131, 21, 79, 154, 129, 5, 69, + 222, 61, 87, 186, 2, 73, 3, 85, 19, 160, 9, 8, 82, 89, 78, 71, 69, 65, + 76, 32, 203, 187, 26, 65, 8, 150, 132, 26, 69, 150, 64, 65, 3, 73, 64, + 94, 72, 134, 6, 87, 218, 1, 89, 158, 250, 20, 65, 2, 79, 154, 129, 5, 69, + 150, 64, 73, 3, 85, 24, 130, 6, 87, 246, 251, 20, 65, 154, 129, 5, 69, + 150, 64, 73, 2, 79, 3, 85, 20, 170, 129, 21, 65, 2, 79, 154, 129, 5, 69, + 222, 61, 87, 2, 89, 186, 2, 73, 3, 85, 74, 102, 69, 226, 1, 72, 170, 3, + 90, 78, 83, 158, 250, 20, 65, 2, 79, 246, 190, 5, 87, 186, 2, 73, 3, 85, + 13, 56, 8, 66, 65, 84, 66, 69, 73, 84, 32, 227, 192, 26, 69, 8, 226, 251, + 21, 66, 2, 70, 2, 77, 3, 80, 80, 118, 72, 76, 2, 84, 72, 62, 90, 162, 2, + 83, 234, 250, 20, 65, 2, 79, 154, 129, 5, 69, 222, 61, 87, 186, 2, 73, 3, + 85, 18, 142, 254, 20, 65, 2, 79, 154, 129, 5, 69, 222, 61, 87, 186, 2, + 73, 3, 85, 12, 218, 254, 25, 69, 222, 61, 65, 186, 2, 73, 2, 79, 3, 85, + 16, 134, 253, 20, 65, 2, 79, 154, 129, 5, 69, 150, 64, 73, 3, 85, 40, 82, + 87, 218, 1, 89, 158, 250, 20, 65, 2, 79, 154, 129, 5, 69, 150, 64, 73, 3, + 85, 10, 242, 251, 20, 65, 154, 129, 5, 69, 151, 64, 73, 48, 90, 72, 78, + 90, 158, 250, 20, 65, 2, 79, 154, 129, 5, 69, 222, 61, 87, 186, 2, 73, 3, + 85, 16, 230, 250, 20, 65, 154, 129, 5, 69, 222, 61, 87, 186, 2, 73, 2, + 79, 3, 85, 14, 154, 250, 20, 65, 154, 129, 5, 69, 150, 64, 73, 2, 79, 3, + 85, 20, 130, 1, 68, 74, 72, 30, 75, 42, 82, 0, 7, 83, 72, 79, 82, 84, 32, + 82, 176, 253, 3, 3, 67, 72, 73, 189, 134, 22, 3, 89, 73, 90, 6, 48, 4, + 69, 82, 69, 84, 129, 166, 25, 2, 73, 70, 5, 17, 2, 45, 72, 2, 173, 132, + 26, 2, 73, 68, 4, 204, 165, 25, 2, 69, 78, 219, 12, 85, 2, 217, 139, 4, + 3, 73, 75, 82, 10, 68, 2, 82, 79, 205, 174, 25, 9, 76, 69, 82, 32, 67, + 79, 78, 83, 84, 8, 92, 5, 80, 69, 65, 78, 32, 172, 153, 23, 8, 45, 67, + 85, 82, 82, 69, 78, 67, 171, 151, 2, 32, 4, 186, 248, 3, 67, 19, 80, 42, + 82, 67, 102, 84, 201, 248, 25, 12, 80, 82, 69, 83, 83, 73, 79, 78, 76, + 69, 83, 83, 6, 60, 9, 76, 65, 77, 65, 84, 73, 79, 78, 32, 203, 159, 25, + 69, 4, 202, 235, 23, 81, 151, 137, 2, 77, 34, 98, 82, 217, 223, 20, 18, + 69, 78, 68, 69, 68, 32, 65, 82, 65, 66, 73, 67, 45, 73, 78, 68, 73, 67, + 14, 140, 1, 12, 69, 77, 69, 76, 89, 32, 72, 69, 65, 86, 89, 32, 245, 226, + 24, 16, 65, 84, 69, 82, 82, 69, 83, 84, 82, 73, 65, 76, 32, 65, 76, 73, + 12, 50, 83, 214, 160, 24, 70, 234, 2, 87, 207, 10, 71, 4, 230, 161, 24, + 65, 43, 73, 7, 194, 227, 18, 71, 215, 207, 7, 83, 130, 4, 142, 1, 65, + 206, 18, 69, 194, 1, 73, 186, 7, 76, 214, 4, 79, 238, 6, 82, 142, 5, 85, + 136, 232, 19, 2, 86, 83, 254, 150, 4, 83, 207, 134, 2, 70, 90, 122, 67, + 254, 14, 76, 176, 2, 2, 88, 32, 230, 129, 3, 77, 252, 213, 5, 2, 82, 83, + 168, 250, 1, 2, 84, 72, 255, 192, 9, 73, 68, 72, 2, 69, 32, 236, 235, 15, + 4, 83, 73, 77, 73, 249, 183, 4, 2, 84, 79, 64, 226, 1, 83, 160, 1, 4, 87, + 73, 84, 72, 168, 203, 12, 2, 80, 65, 176, 130, 2, 2, 77, 65, 132, 201, + 10, 13, 84, 72, 82, 79, 87, 73, 78, 71, 32, 65, 32, 75, 73, 201, 1, 14, + 72, 79, 76, 68, 73, 78, 71, 32, 66, 65, 67, 75, 32, 84, 4, 212, 182, 16, + 18, 65, 86, 79, 85, 82, 73, 78, 71, 32, 68, 69, 76, 73, 67, 73, 79, 85, + 83, 161, 243, 4, 13, 67, 82, 69, 65, 77, 73, 78, 71, 32, 73, 78, 32, 70, + 52, 38, 32, 221, 190, 21, 3, 79, 85, 84, 50, 144, 4, 2, 67, 79, 44, 5, + 72, 69, 65, 68, 45, 38, 77, 98, 79, 92, 7, 78, 79, 32, 71, 79, 79, 68, + 238, 1, 80, 164, 1, 16, 83, 84, 85, 67, 75, 45, 79, 85, 84, 32, 84, 79, + 78, 71, 85, 69, 110, 84, 168, 140, 18, 22, 70, 73, 78, 71, 69, 82, 32, + 67, 79, 86, 69, 82, 73, 78, 71, 32, 67, 76, 79, 83, 69, 68, 172, 67, 3, + 82, 79, 76, 180, 217, 1, 13, 76, 79, 79, 75, 32, 79, 70, 32, 84, 82, 73, + 85, 77, 184, 139, 1, 8, 68, 73, 65, 71, 79, 78, 65, 76, 1, 20, 85, 78, + 69, 86, 69, 78, 32, 69, 89, 69, 83, 32, 65, 78, 68, 32, 87, 65, 86, 89, + 4, 252, 4, 3, 87, 66, 79, 163, 208, 18, 76, 2, 225, 205, 21, 4, 66, 65, + 78, 68, 4, 60, 6, 69, 68, 73, 67, 65, 76, 217, 216, 24, 3, 79, 78, 79, 2, + 165, 229, 24, 3, 32, 77, 65, 12, 90, 75, 36, 4, 80, 69, 78, 32, 165, 218, + 19, 10, 78, 69, 32, 69, 89, 69, 66, 82, 79, 87, 2, 217, 188, 21, 4, 32, + 71, 69, 83, 8, 116, 5, 77, 79, 85, 84, 72, 161, 183, 21, 18, 69, 89, 69, + 83, 32, 65, 78, 68, 32, 72, 65, 78, 68, 32, 79, 86, 69, 82, 7, 11, 32, 4, + 228, 206, 9, 3, 86, 79, 77, 241, 130, 9, 5, 65, 78, 68, 32, 67, 6, 132, + 1, 18, 65, 82, 84, 89, 32, 72, 79, 82, 78, 32, 65, 78, 68, 32, 80, 65, + 82, 84, 100, 2, 69, 69, 133, 208, 18, 4, 76, 69, 65, 68, 2, 213, 230, 21, + 2, 89, 32, 7, 29, 5, 32, 65, 78, 68, 32, 4, 36, 3, 87, 73, 78, 159, 208, + 18, 84, 2, 153, 170, 1, 4, 75, 73, 78, 71, 4, 50, 69, 149, 234, 21, 6, + 72, 69, 82, 77, 79, 77, 2, 197, 144, 26, 8, 65, 82, 83, 32, 79, 70, 32, + 74, 10, 34, 76, 237, 192, 21, 2, 65, 70, 8, 84, 13, 73, 78, 71, 32, 68, + 73, 65, 71, 79, 78, 65, 76, 32, 197, 236, 22, 2, 69, 78, 6, 128, 1, 9, + 67, 82, 79, 83, 83, 73, 78, 71, 32, 181, 227, 18, 16, 73, 78, 32, 87, 72, + 73, 84, 69, 32, 67, 73, 82, 67, 76, 69, 32, 4, 224, 197, 15, 3, 82, 73, + 83, 135, 165, 3, 78, 4, 166, 191, 14, 73, 175, 251, 3, 77, 14, 50, 65, + 54, 77, 44, 2, 82, 82, 147, 149, 18, 78, 4, 214, 196, 17, 84, 245, 156, + 8, 4, 82, 70, 85, 76, 4, 144, 188, 8, 2, 73, 78, 239, 157, 7, 65, 4, 168, + 199, 7, 2, 73, 83, 215, 214, 18, 89, 54, 200, 1, 5, 71, 85, 82, 69, 32, + 38, 76, 186, 1, 82, 182, 2, 83, 208, 12, 4, 86, 69, 32, 68, 172, 233, 4, + 10, 69, 76, 68, 32, 72, 79, 67, 75, 69, 89, 233, 157, 19, 9, 78, 73, 84, + 69, 32, 80, 65, 82, 84, 4, 222, 182, 24, 68, 139, 167, 1, 83, 10, 32, 2, + 69, 32, 65, 2, 77, 32, 6, 174, 133, 15, 70, 172, 59, 4, 67, 65, 66, 73, + 247, 193, 7, 83, 4, 52, 4, 80, 82, 79, 74, 149, 198, 19, 3, 70, 82, 65, + 2, 221, 225, 25, 2, 69, 67, 22, 34, 69, 189, 1, 3, 83, 84, 32, 13, 56, 2, + 32, 69, 68, 4, 87, 79, 82, 75, 207, 244, 14, 67, 4, 214, 254, 12, 78, + 237, 192, 4, 8, 88, 84, 73, 78, 71, 85, 73, 83, 4, 220, 209, 22, 6, 32, + 83, 80, 65, 82, 75, 171, 199, 3, 83, 10, 222, 137, 5, 81, 168, 146, 10, + 8, 83, 84, 82, 79, 78, 71, 32, 73, 219, 197, 6, 80, 10, 38, 72, 177, 224, + 22, 3, 84, 69, 68, 9, 236, 234, 3, 13, 73, 78, 71, 32, 80, 79, 76, 69, + 32, 65, 78, 68, 32, 182, 171, 5, 69, 209, 250, 15, 19, 32, 67, 65, 75, + 69, 32, 87, 73, 84, 72, 32, 83, 87, 73, 82, 76, 32, 68, 69, 36, 50, 65, + 134, 1, 69, 98, 79, 194, 1, 85, 39, 89, 10, 78, 84, 220, 148, 7, 6, 71, + 32, 73, 78, 32, 72, 229, 246, 16, 3, 77, 73, 78, 6, 214, 163, 8, 32, 202, + 170, 11, 66, 183, 176, 5, 78, 4, 132, 245, 22, 8, 88, 69, 68, 32, 66, 73, + 67, 69, 241, 130, 1, 7, 85, 82, 45, 68, 69, 45, 76, 10, 46, 82, 28, 3, + 87, 69, 82, 231, 208, 24, 80, 2, 173, 140, 25, 2, 65, 76, 7, 17, 2, 32, + 80, 4, 58, 85, 141, 187, 23, 8, 76, 65, 89, 73, 78, 71, 32, 67, 2, 193, + 169, 25, 4, 78, 67, 84, 85, 4, 214, 139, 3, 83, 155, 240, 22, 84, 9, 25, + 4, 73, 78, 71, 32, 6, 242, 213, 9, 68, 148, 179, 8, 2, 83, 65, 139, 181, + 1, 69, 54, 102, 71, 20, 2, 76, 68, 68, 2, 79, 84, 22, 82, 238, 1, 85, + 172, 173, 22, 2, 78, 68, 203, 163, 3, 88, 5, 151, 255, 25, 71, 4, 196, + 148, 9, 8, 73, 78, 71, 32, 72, 65, 78, 68, 183, 195, 16, 69, 5, 147, 224, + 13, 80, 16, 102, 75, 218, 252, 19, 77, 250, 141, 4, 32, 222, 112, 67, + 177, 120, 9, 84, 85, 78, 69, 32, 67, 79, 79, 75, 8, 80, 10, 32, 65, 78, + 68, 32, 75, 78, 73, 70, 69, 218, 225, 14, 69, 247, 219, 10, 73, 5, 133, + 146, 15, 7, 32, 87, 73, 84, 72, 32, 80, 22, 26, 82, 159, 200, 22, 78, 20, + 38, 32, 218, 2, 84, 255, 154, 18, 45, 16, 110, 67, 174, 1, 68, 234, 154, + 2, 66, 204, 240, 9, 7, 76, 69, 65, 70, 32, 67, 76, 242, 105, 84, 171, + 130, 11, 80, 4, 244, 246, 12, 3, 76, 85, 66, 229, 85, 32, 79, 82, 78, 69, + 82, 32, 65, 82, 82, 79, 87, 83, 32, 67, 73, 82, 67, 76, 73, 78, 71, 32, + 65, 78, 84, 73, 67, 76, 79, 67, 75, 87, 4, 21, 3, 79, 84, 32, 4, 186, + 222, 22, 80, 183, 235, 2, 77, 2, 255, 31, 72, 28, 78, 65, 226, 1, 69, 98, + 79, 165, 174, 16, 8, 73, 69, 68, 32, 83, 72, 82, 73, 10, 72, 6, 67, 84, + 73, 79, 78, 32, 69, 8, 77, 69, 32, 87, 73, 84, 72, 32, 4, 214, 168, 19, + 83, 177, 6, 9, 78, 85, 77, 69, 82, 65, 84, 79, 82, 6, 50, 80, 166, 155, + 2, 65, 213, 196, 20, 2, 84, 73, 2, 213, 158, 21, 2, 73, 67, 6, 48, 6, 78, + 67, 72, 32, 70, 82, 171, 185, 18, 69, 4, 150, 244, 24, 73, 249, 12, 3, + 65, 78, 67, 10, 52, 3, 78, 84, 45, 116, 2, 87, 78, 143, 201, 25, 71, 4, + 70, 84, 145, 128, 2, 11, 70, 65, 67, 73, 78, 71, 32, 66, 65, 66, 89, 2, + 253, 132, 12, 6, 73, 76, 84, 69, 68, 32, 5, 181, 176, 18, 15, 73, 78, 71, + 32, 70, 65, 67, 69, 32, 87, 73, 84, 72, 32, 79, 224, 1, 80, 2, 76, 76, + 250, 5, 78, 216, 165, 16, 5, 69, 76, 32, 80, 85, 215, 194, 9, 83, 216, 1, + 42, 32, 73, 6, 87, 73, 68, 84, 72, 32, 10, 158, 210, 11, 77, 160, 159, 3, + 2, 79, 85, 194, 170, 8, 66, 131, 30, 83, 206, 1, 238, 1, 67, 42, 76, 78, + 78, 30, 80, 66, 82, 134, 1, 83, 38, 89, 130, 230, 9, 77, 130, 171, 10, + 65, 158, 2, 68, 58, 69, 98, 71, 118, 72, 190, 4, 81, 214, 139, 2, 87, + 182, 24, 84, 220, 113, 6, 66, 82, 79, 75, 69, 78, 202, 4, 70, 159, 177, + 1, 86, 10, 238, 148, 20, 73, 62, 79, 227, 75, 69, 116, 42, 69, 162, 152, + 20, 65, 171, 132, 4, 79, 10, 162, 1, 70, 139, 154, 20, 83, 4, 182, 234, + 20, 79, 35, 85, 6, 42, 79, 138, 155, 20, 69, 247, 203, 2, 76, 2, 239, + 154, 24, 85, 10, 36, 3, 73, 71, 72, 231, 237, 23, 69, 8, 17, 2, 84, 32, + 8, 182, 163, 22, 67, 240, 1, 5, 87, 72, 73, 84, 69, 22, 80, 155, 2, 83, + 4, 218, 201, 22, 69, 203, 165, 1, 79, 2, 247, 136, 24, 69, 4, 236, 146, + 11, 8, 67, 84, 73, 79, 78, 32, 65, 80, 253, 212, 8, 5, 69, 82, 65, 76, + 32, 228, 18, 110, 65, 62, 69, 198, 17, 73, 162, 1, 76, 134, 15, 79, 194, + 6, 82, 158, 93, 85, 226, 175, 21, 72, 215, 199, 3, 83, 4, 196, 214, 24, + 2, 82, 76, 189, 139, 1, 4, 77, 69, 32, 68, 242, 2, 112, 2, 65, 82, 110, + 77, 50, 79, 224, 220, 22, 9, 82, 77, 65, 78, 32, 80, 69, 78, 78, 130, + 153, 2, 84, 215, 105, 78, 7, 29, 5, 32, 87, 73, 84, 72, 4, 220, 230, 13, + 5, 79, 85, 84, 32, 72, 177, 236, 8, 5, 32, 72, 65, 78, 68, 4, 26, 32, + 131, 171, 21, 73, 2, 199, 172, 22, 83, 226, 2, 64, 6, 77, 69, 84, 82, 73, + 67, 73, 6, 82, 71, 73, 65, 78, 32, 6, 236, 185, 19, 4, 65, 76, 76, 89, + 137, 214, 1, 5, 32, 80, 82, 79, 80, 220, 2, 228, 1, 6, 67, 65, 80, 73, + 84, 65, 0, 4, 83, 77, 65, 76, 172, 3, 7, 76, 69, 84, 84, 69, 82, 32, 180, + 2, 24, 77, 84, 65, 86, 82, 85, 76, 73, 32, 67, 65, 80, 73, 84, 65, 76, + 32, 76, 69, 84, 84, 69, 82, 32, 165, 6, 2, 80, 65, 80, 45, 9, 76, 32, 76, + 69, 84, 84, 69, 82, 32, 80, 142, 2, 65, 34, 72, 166, 5, 67, 118, 71, 130, + 1, 74, 34, 75, 82, 80, 34, 83, 94, 90, 176, 155, 5, 2, 84, 65, 234, 250, + 7, 76, 214, 168, 2, 82, 230, 229, 8, 66, 2, 77, 2, 88, 142, 37, 78, 2, + 81, 238, 34, 86, 222, 47, 68, 14, 69, 2, 73, 2, 79, 2, 85, 2, 89, 131, + 57, 87, 4, 210, 165, 25, 69, 215, 79, 78, 10, 46, 65, 134, 222, 25, 73, + 2, 79, 215, 22, 69, 4, 214, 244, 25, 69, 3, 82, 94, 254, 1, 85, 178, 2, + 65, 42, 67, 74, 69, 46, 71, 34, 72, 98, 74, 34, 75, 34, 76, 50, 80, 34, + 83, 34, 84, 62, 90, 238, 190, 15, 82, 230, 229, 8, 66, 2, 77, 2, 88, 142, + 37, 78, 2, 81, 238, 34, 86, 222, 47, 68, 14, 73, 2, 79, 2, 89, 130, 57, + 87, 255, 2, 70, 4, 252, 174, 21, 4, 45, 66, 82, 74, 191, 195, 4, 78, 92, + 250, 1, 65, 42, 67, 74, 69, 46, 71, 34, 72, 98, 74, 34, 75, 34, 76, 50, + 80, 34, 83, 34, 84, 62, 90, 238, 190, 15, 82, 230, 229, 8, 66, 2, 77, 2, + 88, 142, 37, 78, 2, 81, 238, 34, 86, 222, 47, 68, 14, 73, 2, 79, 2, 85, + 2, 89, 130, 57, 87, 255, 2, 70, 6, 182, 160, 25, 69, 2, 73, 215, 79, 78, + 8, 38, 72, 162, 230, 24, 73, 203, 57, 65, 4, 230, 159, 25, 73, 135, 23, + 65, 4, 180, 227, 8, 2, 76, 73, 231, 139, 17, 78, 4, 186, 167, 24, 72, + 227, 119, 65, 12, 46, 65, 206, 215, 25, 73, 2, 79, 215, 22, 69, 6, 26, + 82, 135, 238, 25, 69, 5, 155, 231, 24, 68, 4, 186, 166, 24, 72, 155, 62, + 73, 4, 166, 203, 24, 72, 215, 82, 65, 4, 11, 65, 4, 134, 154, 15, 66, + 159, 211, 10, 83, 4, 214, 202, 24, 72, 219, 105, 65, 4, 162, 237, 24, 72, + 235, 47, 65, 6, 220, 177, 3, 6, 85, 82, 78, 69, 68, 32, 143, 234, 1, 65, + 4, 218, 201, 24, 72, 215, 82, 69, 2, 165, 219, 19, 7, 82, 65, 71, 82, 65, + 80, 72, 10, 48, 2, 77, 69, 20, 4, 78, 71, 69, 82, 31, 82, 2, 239, 215, + 24, 76, 2, 141, 252, 17, 2, 32, 82, 6, 38, 76, 237, 189, 13, 3, 65, 70, + 70, 5, 151, 215, 24, 83, 202, 1, 66, 65, 214, 13, 79, 217, 154, 25, 7, + 69, 73, 67, 72, 32, 83, 84, 194, 1, 84, 8, 71, 79, 76, 73, 84, 73, 67, + 32, 229, 12, 8, 83, 83, 32, 79, 70, 32, 77, 73, 192, 1, 56, 6, 67, 65, + 80, 73, 84, 65, 1, 4, 83, 77, 65, 76, 96, 45, 9, 76, 32, 76, 69, 84, 84, + 69, 82, 32, 96, 206, 1, 65, 22, 66, 42, 67, 94, 68, 94, 70, 38, 71, 46, + 73, 138, 2, 76, 58, 77, 66, 78, 34, 79, 30, 80, 58, 82, 30, 83, 186, 1, + 84, 110, 86, 22, 89, 90, 90, 182, 199, 18, 72, 142, 243, 1, 85, 131, 131, + 5, 75, 2, 199, 193, 25, 90, 4, 214, 3, 73, 253, 208, 25, 2, 85, 75, 4, + 48, 8, 65, 85, 68, 65, 84, 69, 32, 67, 15, 72, 2, 11, 72, 2, 197, 252, 8, + 2, 82, 73, 6, 42, 74, 30, 79, 129, 194, 25, 2, 90, 69, 2, 253, 251, 8, 2, + 69, 82, 2, 187, 248, 23, 66, 4, 238, 191, 20, 82, 131, 128, 5, 73, 2, 21, + 3, 76, 65, 71, 2, 255, 148, 21, 79, 13, 38, 78, 54, 79, 141, 1, 2, 90, + 72, 2, 181, 182, 25, 8, 73, 84, 73, 65, 76, 32, 73, 90, 4, 33, 6, 84, 65, + 84, 69, 68, 32, 4, 26, 66, 25, 2, 83, 77, 2, 11, 73, 2, 35, 71, 2, 21, 3, + 65, 76, 76, 2, 177, 223, 23, 2, 32, 89, 4, 178, 223, 25, 73, 211, 2, 69, + 4, 52, 9, 65, 84, 73, 78, 65, 84, 69, 32, 77, 35, 74, 2, 193, 223, 10, 3, + 89, 83, 76, 2, 177, 231, 8, 3, 85, 68, 73, 2, 11, 65, 2, 239, 188, 20, + 83, 4, 226, 187, 25, 78, 3, 84, 4, 26, 79, 151, 224, 25, 69, 2, 225, 245, + 21, 2, 75, 79, 2, 225, 161, 21, 2, 73, 84, 14, 106, 72, 58, 76, 168, 195, + 13, 6, 80, 73, 68, 69, 82, 89, 209, 237, 9, 8, 77, 65, 76, 76, 32, 89, + 85, 83, 6, 32, 2, 84, 65, 207, 222, 25, 65, 5, 223, 183, 24, 80, 2, 251, + 218, 8, 79, 6, 78, 86, 208, 201, 21, 9, 82, 79, 75, 85, 84, 65, 83, 84, + 73, 175, 128, 4, 83, 2, 157, 227, 18, 2, 82, 73, 2, 195, 208, 23, 69, 12, + 50, 69, 246, 184, 18, 65, 254, 163, 7, 79, 3, 85, 6, 174, 184, 20, 83, + 151, 228, 4, 82, 4, 192, 235, 8, 3, 69, 77, 76, 221, 172, 15, 4, 72, 73, + 86, 69, 2, 243, 216, 25, 76, 6, 212, 199, 11, 13, 66, 69, 32, 87, 73, 84, + 72, 32, 77, 69, 82, 73, 68, 146, 177, 4, 87, 179, 207, 8, 86, 68, 162, 1, + 65, 44, 12, 84, 72, 73, 67, 32, 76, 69, 84, 84, 69, 82, 32, 178, 174, 17, + 71, 182, 55, 82, 252, 182, 5, 3, 78, 71, 71, 238, 179, 1, 79, 149, 75, 2, + 76, 70, 4, 132, 255, 14, 2, 76, 32, 231, 218, 10, 84, 54, 202, 2, 65, 50, + 72, 46, 73, 46, 78, 46, 80, 2, 81, 40, 2, 82, 65, 22, 84, 240, 227, 8, 2, + 87, 73, 142, 233, 11, 85, 160, 70, 3, 70, 65, 73, 204, 7, 4, 66, 65, 73, + 82, 248, 21, 2, 79, 84, 202, 30, 68, 218, 99, 77, 144, 117, 3, 83, 65, + 85, 138, 16, 69, 128, 26, 3, 76, 65, 71, 142, 197, 1, 74, 184, 16, 2, 71, + 73, 141, 12, 2, 75, 85, 4, 132, 212, 23, 3, 73, 72, 86, 171, 128, 2, 72, + 4, 154, 179, 13, 87, 141, 154, 11, 2, 65, 71, 4, 142, 229, 8, 85, 201, + 155, 14, 2, 71, 71, 6, 194, 149, 15, 73, 137, 195, 8, 2, 65, 85, 2, 137, + 145, 25, 5, 65, 73, 82, 84, 72, 2, 147, 176, 25, 73, 4, 136, 231, 20, 2, + 72, 73, 185, 152, 2, 2, 69, 73, 234, 9, 46, 65, 190, 6, 69, 206, 82, 73, + 139, 3, 79, 152, 1, 96, 7, 68, 85, 65, 84, 73, 79, 78, 32, 5, 78, 84, 72, + 65, 32, 226, 232, 19, 86, 215, 214, 4, 80, 2, 11, 32, 2, 211, 194, 24, + 67, 146, 1, 156, 1, 7, 76, 69, 84, 84, 69, 82, 32, 212, 2, 5, 83, 73, 71, + 78, 32, 104, 11, 86, 79, 87, 69, 76, 32, 83, 73, 71, 78, 32, 234, 191, 7, + 65, 247, 253, 17, 79, 100, 214, 1, 86, 202, 231, 21, 65, 38, 68, 46, 84, + 230, 24, 85, 210, 200, 1, 73, 42, 76, 246, 189, 1, 78, 46, 83, 82, 66, 2, + 67, 2, 71, 2, 74, 2, 75, 2, 80, 194, 40, 79, 162, 8, 69, 158, 20, 72, 2, + 77, 2, 82, 3, 89, 14, 60, 5, 69, 68, 73, 67, 32, 246, 235, 21, 79, 231, + 227, 3, 65, 4, 212, 160, 23, 6, 68, 79, 85, 66, 76, 69, 151, 234, 1, 65, + 16, 66, 67, 162, 191, 21, 80, 202, 40, 65, 170, 1, 78, 203, 162, 3, 86, + 4, 238, 200, 7, 79, 207, 159, 14, 65, 26, 218, 233, 21, 65, 106, 86, 214, + 20, 85, 210, 200, 1, 73, 218, 231, 1, 79, 163, 8, 69, 192, 8, 76, 10, 65, + 84, 69, 82, 45, 84, 72, 65, 78, 32, 206, 7, 69, 159, 190, 24, 89, 56, + 134, 1, 65, 150, 3, 66, 62, 79, 216, 2, 11, 69, 81, 85, 65, 76, 32, 84, + 79, 32, 79, 82, 218, 173, 6, 67, 138, 4, 87, 175, 141, 18, 83, 16, 44, 5, + 66, 79, 86, 69, 32, 183, 178, 6, 78, 12, 150, 1, 83, 180, 1, 19, 68, 79, + 85, 66, 76, 69, 45, 76, 73, 78, 69, 32, 69, 81, 85, 65, 76, 32, 65, 220, + 172, 6, 4, 76, 69, 83, 83, 207, 252, 17, 82, 6, 148, 1, 7, 73, 77, 73, + 76, 65, 82, 32, 221, 175, 6, 23, 76, 65, 78, 84, 69, 68, 32, 69, 81, 85, + 65, 76, 32, 65, 66, 79, 86, 69, 32, 76, 69, 83, 83, 4, 26, 65, 179, 175, + 6, 79, 2, 65, 3, 66, 79, 86, 6, 40, 4, 69, 83, 73, 68, 155, 176, 6, 85, + 2, 231, 2, 69, 20, 40, 2, 82, 32, 245, 1, 3, 86, 69, 82, 16, 120, 16, 83, + 76, 65, 78, 84, 69, 68, 32, 69, 81, 85, 65, 76, 32, 84, 79, 226, 177, 6, + 65, 150, 213, 12, 69, 191, 177, 4, 76, 9, 49, 10, 32, 87, 73, 84, 72, 32, + 68, 79, 84, 32, 6, 44, 5, 65, 66, 79, 86, 69, 171, 220, 17, 73, 5, 251, + 147, 25, 32, 4, 52, 7, 76, 65, 80, 80, 73, 78, 71, 235, 158, 19, 32, 2, + 253, 182, 23, 2, 32, 76, 134, 8, 36, 2, 75, 32, 185, 73, 2, 78, 32, 254, + 7, 130, 3, 65, 216, 15, 8, 67, 65, 80, 73, 84, 65, 76, 32, 182, 11, 68, + 134, 1, 70, 68, 2, 73, 78, 222, 3, 75, 138, 1, 76, 174, 3, 78, 66, 77, + 84, 3, 88, 69, 83, 22, 79, 202, 1, 80, 90, 82, 182, 1, 83, 130, 22, 84, + 200, 2, 13, 85, 80, 83, 73, 76, 79, 78, 32, 87, 73, 84, 72, 32, 150, 1, + 86, 142, 2, 89, 254, 186, 7, 66, 164, 174, 3, 4, 71, 82, 65, 77, 204, 23, + 2, 90, 69, 167, 177, 11, 81, 112, 92, 10, 67, 82, 79, 80, 72, 79, 78, 73, + 67, 32, 172, 14, 6, 78, 79, 32, 84, 69, 76, 23, 82, 106, 188, 2, 6, 65, + 84, 84, 73, 67, 32, 222, 5, 67, 92, 3, 78, 65, 88, 32, 12, 68, 69, 76, + 80, 72, 73, 67, 32, 70, 73, 86, 69, 0, 14, 83, 84, 82, 65, 84, 73, 65, + 78, 32, 70, 73, 70, 84, 89, 40, 11, 69, 80, 73, 68, 65, 85, 82, 69, 65, + 78, 32, 112, 3, 72, 69, 82, 164, 1, 9, 77, 69, 83, 83, 69, 78, 73, 65, + 78, 35, 84, 48, 72, 2, 70, 73, 180, 2, 4, 79, 78, 69, 32, 205, 1, 4, 84, + 69, 78, 32, 26, 36, 3, 70, 84, 89, 105, 2, 86, 69, 11, 11, 32, 8, 22, 84, + 171, 4, 83, 6, 48, 7, 72, 79, 85, 83, 65, 78, 68, 215, 3, 65, 5, 231, 3, + 32, 17, 11, 32, 14, 56, 7, 72, 85, 78, 68, 82, 69, 68, 18, 84, 143, 3, + 83, 7, 131, 2, 32, 6, 48, 7, 72, 79, 85, 83, 65, 78, 68, 187, 2, 65, 5, + 213, 1, 2, 32, 84, 14, 98, 72, 48, 7, 84, 72, 79, 85, 83, 65, 78, 230, + 186, 23, 81, 229, 222, 1, 5, 68, 82, 65, 67, 72, 6, 44, 5, 85, 78, 68, + 82, 69, 203, 186, 23, 65, 4, 17, 2, 68, 32, 4, 22, 84, 131, 1, 83, 2, 95, + 65, 8, 30, 84, 86, 83, 175, 1, 77, 4, 50, 65, 21, 8, 72, 79, 85, 83, 65, + 78, 68, 32, 2, 171, 241, 15, 76, 2, 11, 83, 2, 201, 187, 23, 2, 84, 65, + 4, 88, 5, 65, 82, 89, 83, 84, 145, 1, 12, 89, 82, 69, 78, 65, 73, 67, 32, + 84, 87, 79, 32, 2, 101, 5, 73, 65, 78, 32, 70, 2, 17, 2, 32, 77, 2, 147, + 226, 12, 78, 6, 30, 70, 29, 3, 84, 87, 79, 2, 221, 248, 14, 2, 73, 86, 5, + 11, 32, 2, 161, 234, 9, 5, 68, 82, 65, 67, 72, 8, 112, 8, 77, 73, 79, 78, + 73, 65, 78, 32, 253, 145, 24, 14, 65, 69, 85, 77, 32, 79, 78, 69, 32, 80, + 76, 69, 84, 72, 6, 150, 140, 12, 70, 254, 216, 11, 84, 227, 55, 79, 2, + 11, 32, 2, 215, 228, 23, 84, 32, 92, 8, 72, 69, 83, 80, 73, 65, 78, 32, + 129, 1, 10, 82, 79, 69, 90, 69, 78, 73, 65, 78, 32, 20, 40, 2, 70, 73, + 38, 84, 239, 217, 17, 79, 6, 222, 139, 20, 86, 219, 190, 3, 70, 8, 246, + 244, 14, 72, 190, 239, 9, 69, 227, 48, 87, 12, 36, 2, 70, 73, 209, 24, 2, + 84, 69, 8, 142, 243, 17, 86, 145, 193, 6, 3, 70, 84, 89, 2, 231, 221, 9, + 69, 4, 252, 246, 21, 2, 79, 85, 149, 164, 1, 3, 84, 65, 66, 154, 2, 66, + 76, 174, 45, 82, 66, 68, 168, 188, 7, 2, 75, 65, 135, 6, 84, 144, 2, 44, + 6, 69, 84, 84, 69, 82, 32, 239, 45, 85, 142, 2, 198, 2, 65, 190, 1, 69, + 28, 4, 73, 79, 84, 65, 128, 1, 2, 79, 77, 156, 3, 3, 82, 72, 79, 46, 83, + 48, 7, 85, 80, 83, 73, 76, 79, 78, 146, 33, 80, 170, 2, 84, 138, 157, 5, + 68, 156, 164, 2, 2, 75, 65, 146, 192, 1, 71, 194, 223, 10, 67, 166, 255, + 1, 66, 2, 72, 2, 90, 166, 1, 76, 254, 210, 2, 89, 198, 43, 77, 2, 78, + 147, 17, 88, 48, 68, 4, 76, 80, 72, 65, 213, 28, 8, 82, 67, 72, 65, 73, + 67, 32, 83, 47, 33, 6, 32, 87, 73, 84, 72, 32, 44, 242, 2, 68, 30, 80, + 226, 29, 86, 226, 5, 79, 142, 226, 3, 84, 147, 140, 5, 77, 62, 186, 1, + 84, 131, 27, 80, 31, 33, 6, 32, 87, 73, 84, 72, 32, 28, 186, 5, 68, 136, + 25, 2, 80, 83, 158, 1, 86, 226, 5, 79, 142, 226, 3, 84, 147, 140, 5, 77, + 62, 28, 2, 69, 71, 235, 34, 73, 42, 11, 65, 43, 33, 6, 32, 87, 73, 84, + 72, 32, 40, 54, 68, 30, 80, 194, 35, 79, 22, 86, 251, 225, 3, 84, 16, 65, + 4, 65, 83, 73, 65, 18, 36, 4, 83, 73, 76, 73, 211, 16, 82, 17, 29, 5, 32, + 65, 78, 68, 32, 14, 44, 2, 79, 88, 0, 3, 86, 65, 82, 23, 80, 4, 81, 2, + 73, 65, 6, 60, 10, 69, 82, 73, 83, 80, 79, 77, 69, 78, 73, 175, 15, 82, + 5, 169, 15, 7, 32, 65, 78, 68, 32, 80, 82, 5, 161, 35, 7, 32, 87, 73, 84, + 72, 32, 68, 6, 170, 230, 7, 73, 206, 242, 16, 65, 227, 48, 72, 23, 33, 6, + 32, 87, 73, 84, 72, 32, 20, 66, 68, 166, 26, 86, 226, 5, 79, 142, 226, 3, + 84, 147, 140, 5, 77, 10, 130, 24, 65, 133, 203, 1, 5, 73, 65, 76, 89, 84, + 18, 76, 9, 73, 65, 76, 89, 84, 73, 75, 65, 32, 32, 3, 82, 65, 67, 227, + 22, 65, 8, 174, 24, 65, 223, 232, 3, 84, 2, 235, 146, 11, 72, 4, 40, 3, + 73, 86, 69, 1, 3, 79, 85, 82, 2, 205, 37, 2, 32, 79, 76, 144, 1, 27, 83, + 84, 82, 85, 77, 69, 78, 84, 65, 76, 32, 78, 79, 84, 65, 84, 73, 79, 78, + 32, 83, 89, 77, 66, 79, 76, 45, 165, 202, 21, 2, 68, 73, 74, 70, 49, 70, + 50, 62, 51, 62, 52, 170, 37, 53, 250, 252, 24, 55, 3, 56, 17, 218, 163, + 25, 49, 2, 50, 2, 51, 2, 52, 2, 55, 2, 56, 3, 57, 15, 150, 163, 25, 51, + 2, 52, 2, 53, 2, 54, 2, 55, 3, 57, 12, 218, 162, 25, 48, 2, 50, 2, 54, 2, + 55, 2, 56, 3, 57, 17, 158, 162, 25, 48, 2, 50, 2, 51, 2, 53, 2, 55, 2, + 56, 3, 57, 8, 54, 65, 38, 79, 169, 32, 6, 89, 65, 84, 72, 79, 83, 4, 210, + 216, 7, 80, 195, 181, 16, 73, 2, 11, 82, 2, 11, 79, 2, 251, 131, 23, 78, + 32, 128, 1, 6, 69, 84, 84, 69, 82, 32, 168, 2, 6, 79, 87, 69, 82, 32, 78, + 32, 6, 85, 78, 65, 84, 69, 32, 157, 225, 21, 2, 73, 84, 24, 94, 83, 140, + 13, 9, 65, 82, 67, 72, 65, 73, 67, 32, 75, 2, 75, 182, 11, 68, 135, 182, + 24, 89, 16, 88, 13, 77, 65, 76, 76, 32, 67, 65, 80, 73, 84, 65, 76, 32, + 210, 12, 65, 195, 205, 7, 84, 12, 74, 80, 154, 154, 9, 71, 174, 131, 9, + 79, 238, 195, 2, 82, 243, 152, 1, 76, 4, 238, 137, 25, 83, 219, 19, 73, + 2, 249, 223, 9, 3, 85, 77, 69, 4, 222, 25, 83, 163, 186, 7, 69, 4, 80, 4, + 69, 84, 82, 69, 253, 208, 22, 10, 85, 83, 73, 67, 65, 76, 32, 76, 69, 73, + 2, 139, 206, 2, 84, 12, 88, 3, 78, 69, 32, 142, 198, 9, 88, 200, 136, 5, + 3, 85, 78, 75, 161, 181, 5, 2, 66, 79, 6, 64, 8, 72, 65, 76, 70, 32, 83, + 73, 71, 21, 4, 81, 85, 65, 82, 4, 207, 155, 24, 78, 2, 159, 132, 20, 84, + 16, 62, 82, 206, 11, 83, 114, 69, 230, 197, 7, 72, 203, 180, 16, 73, 2, + 217, 29, 2, 79, 83, 6, 100, 3, 72, 79, 32, 241, 207, 7, 16, 69, 86, 69, + 82, 83, 69, 68, 32, 76, 85, 78, 65, 84, 69, 32, 69, 4, 140, 197, 13, 10, + 87, 73, 84, 72, 32, 83, 84, 82, 79, 75, 243, 192, 10, 83, 226, 2, 220, 1, + 5, 77, 65, 76, 76, 32, 192, 19, 22, 85, 66, 83, 67, 82, 73, 80, 84, 32, + 83, 77, 65, 76, 76, 32, 76, 69, 84, 84, 69, 82, 32, 72, 10, 89, 77, 66, + 79, 76, 32, 84, 65, 85, 32, 237, 156, 23, 6, 73, 78, 85, 83, 79, 73, 212, + 2, 56, 7, 76, 69, 84, 84, 69, 82, 32, 202, 17, 82, 67, 68, 206, 2, 178, + 2, 65, 162, 2, 68, 38, 69, 52, 4, 73, 79, 84, 65, 0, 7, 85, 80, 83, 73, + 76, 79, 78, 254, 3, 75, 28, 2, 79, 77, 182, 5, 80, 112, 3, 82, 72, 79, + 94, 83, 94, 84, 192, 192, 7, 2, 70, 73, 246, 192, 1, 71, 194, 223, 10, + 67, 166, 255, 1, 66, 2, 72, 2, 90, 166, 1, 76, 194, 254, 2, 77, 2, 78, + 147, 17, 88, 58, 64, 4, 76, 80, 72, 65, 149, 1, 7, 82, 67, 72, 65, 73, + 67, 32, 55, 33, 6, 32, 87, 73, 84, 72, 32, 52, 82, 86, 226, 6, 68, 30, + 80, 114, 79, 142, 1, 89, 250, 227, 3, 84, 147, 140, 5, 77, 6, 154, 5, 82, + 155, 3, 65, 4, 18, 75, 23, 83, 2, 163, 206, 7, 79, 2, 11, 65, 2, 203, + 143, 13, 77, 4, 214, 184, 7, 73, 191, 180, 14, 69, 70, 22, 80, 215, 4, + 84, 20, 249, 7, 3, 83, 73, 76, 41, 33, 6, 32, 87, 73, 84, 72, 32, 38, 78, + 68, 166, 1, 80, 178, 1, 86, 226, 5, 79, 142, 226, 3, 84, 147, 140, 5, 77, + 18, 50, 65, 29, 8, 73, 65, 76, 89, 84, 73, 75, 65, 8, 153, 1, 3, 83, 73, + 65, 11, 29, 5, 32, 65, 78, 68, 32, 8, 170, 1, 80, 154, 6, 79, 22, 86, + 251, 225, 3, 84, 10, 18, 83, 115, 69, 8, 21, 3, 73, 76, 73, 9, 17, 2, 32, + 65, 6, 21, 3, 78, 68, 32, 6, 30, 80, 154, 6, 79, 23, 86, 2, 11, 69, 2, + 11, 82, 2, 181, 17, 4, 73, 83, 80, 79, 4, 22, 82, 147, 15, 65, 2, 177, + 235, 24, 2, 65, 67, 4, 154, 201, 7, 65, 3, 79, 70, 28, 2, 69, 71, 151, 3, + 73, 50, 11, 65, 51, 33, 6, 32, 87, 73, 84, 72, 32, 48, 58, 68, 30, 80, + 114, 79, 62, 86, 82, 89, 251, 227, 3, 84, 16, 61, 4, 65, 83, 73, 65, 20, + 32, 4, 83, 73, 76, 73, 91, 69, 17, 29, 5, 32, 65, 78, 68, 32, 14, 42, 79, + 12, 2, 80, 69, 50, 86, 83, 89, 4, 83, 88, 4, 89, 9, 82, 73, 83, 80, 79, + 77, 69, 78, 73, 4, 11, 65, 4, 11, 82, 4, 17, 2, 73, 65, 5, 33, 6, 32, 65, + 78, 68, 32, 89, 2, 243, 12, 80, 20, 17, 2, 67, 82, 20, 17, 2, 79, 78, 21, + 33, 6, 32, 87, 73, 84, 72, 32, 18, 88, 5, 68, 65, 83, 73, 65, 0, 5, 80, + 83, 73, 76, 73, 54, 79, 22, 86, 251, 225, 3, 84, 7, 29, 5, 32, 65, 78, + 68, 32, 4, 18, 79, 23, 86, 2, 151, 178, 9, 88, 2, 179, 9, 65, 8, 88, 11, + 65, 77, 80, 72, 89, 76, 73, 65, 78, 32, 68, 218, 242, 24, 72, 2, 83, 219, + 19, 73, 2, 215, 173, 7, 73, 7, 33, 6, 32, 87, 73, 84, 72, 32, 4, 34, 68, + 201, 182, 20, 2, 80, 83, 2, 215, 159, 8, 65, 10, 54, 65, 134, 193, 7, 84, + 230, 1, 73, 175, 163, 17, 72, 4, 142, 131, 13, 77, 251, 129, 12, 78, 4, + 150, 224, 21, 72, 231, 255, 2, 65, 4, 41, 8, 69, 86, 69, 82, 83, 69, 68, + 32, 4, 18, 68, 43, 76, 2, 37, 7, 79, 84, 84, 69, 68, 32, 76, 2, 11, 85, + 2, 33, 6, 78, 65, 84, 69, 32, 83, 2, 245, 193, 7, 3, 73, 71, 77, 10, 214, + 255, 8, 71, 194, 223, 10, 67, 2, 80, 218, 103, 82, 207, 151, 1, 66, 2, + 167, 198, 20, 82, 16, 106, 72, 104, 7, 82, 89, 66, 76, 73, 79, 78, 44, 3, + 87, 79, 32, 150, 219, 3, 79, 141, 132, 16, 2, 65, 76, 6, 40, 4, 82, 69, + 69, 32, 219, 191, 7, 69, 4, 146, 1, 79, 185, 230, 21, 7, 81, 85, 65, 82, + 84, 69, 82, 2, 21, 3, 32, 66, 65, 2, 231, 232, 22, 83, 4, 42, 79, 253, + 234, 11, 4, 84, 72, 73, 82, 2, 229, 148, 19, 2, 66, 79, 6, 80, 5, 65, 67, + 85, 84, 69, 0, 9, 68, 73, 65, 69, 82, 69, 83, 73, 83, 39, 72, 2, 33, 6, + 32, 65, 78, 68, 32, 72, 2, 145, 157, 7, 2, 79, 79, 60, 102, 65, 21, 21, + 79, 67, 65, 76, 32, 78, 79, 84, 65, 84, 73, 79, 78, 32, 83, 89, 77, 66, + 79, 76, 45, 2, 207, 168, 9, 82, 58, 90, 50, 2, 53, 166, 195, 22, 49, 214, + 185, 2, 51, 2, 52, 2, 54, 2, 55, 2, 56, 3, 57, 13, 246, 252, 24, 48, 2, + 49, 2, 50, 2, 51, 3, 52, 4, 26, 80, 139, 230, 19, 69, 2, 11, 79, 2, 33, + 6, 71, 69, 71, 82, 65, 77, 2, 253, 171, 20, 2, 77, 69, 8, 238, 189, 13, + 65, 142, 237, 9, 66, 210, 73, 72, 241, 64, 3, 83, 65, 76, 12, 60, 6, 78, + 78, 73, 78, 71, 32, 205, 242, 23, 3, 77, 65, 67, 10, 100, 4, 70, 65, 67, + 69, 217, 166, 17, 15, 67, 65, 84, 32, 70, 65, 67, 69, 32, 87, 73, 84, 72, + 32, 83, 9, 33, 6, 32, 87, 73, 84, 72, 32, 6, 108, 23, 79, 78, 69, 32, 76, + 65, 82, 71, 69, 32, 65, 78, 68, 32, 79, 78, 69, 32, 83, 77, 65, 76, 76, + 35, 83, 2, 11, 32, 2, 159, 247, 7, 69, 4, 174, 165, 17, 77, 145, 1, 3, + 84, 65, 82, 6, 28, 3, 85, 80, 32, 39, 87, 4, 250, 222, 21, 83, 211, 215, + 2, 77, 2, 251, 211, 17, 73, 232, 3, 164, 1, 2, 65, 82, 70, 73, 52, 7, 74, + 65, 82, 65, 84, 73, 32, 212, 6, 12, 78, 74, 65, 76, 65, 32, 71, 79, 78, + 68, 73, 32, 137, 3, 7, 82, 77, 85, 75, 72, 73, 32, 4, 34, 65, 157, 172, + 20, 2, 68, 83, 2, 11, 78, 2, 239, 238, 23, 73, 4, 154, 211, 23, 84, 201, + 161, 1, 4, 68, 69, 32, 68, 182, 1, 168, 1, 7, 76, 69, 84, 84, 69, 82, 32, + 220, 1, 5, 83, 73, 71, 78, 32, 160, 2, 6, 86, 79, 87, 69, 76, 32, 226, + 175, 19, 65, 210, 24, 82, 154, 185, 3, 68, 199, 221, 1, 79, 98, 142, 139, + 21, 65, 38, 68, 46, 84, 46, 86, 186, 24, 85, 210, 200, 1, 73, 42, 76, + 234, 14, 90, 142, 175, 1, 78, 46, 83, 82, 66, 2, 67, 2, 71, 2, 74, 2, 75, + 2, 80, 254, 68, 72, 2, 77, 2, 82, 2, 89, 186, 2, 69, 3, 79, 24, 98, 67, + 28, 3, 77, 65, 68, 22, 84, 250, 194, 3, 83, 138, 199, 17, 65, 170, 1, 78, + 203, 162, 3, 86, 4, 118, 73, 143, 138, 21, 65, 2, 187, 184, 17, 68, 4, + 68, 5, 87, 79, 45, 67, 73, 29, 8, 72, 82, 69, 69, 45, 68, 79, 84, 2, 25, + 4, 82, 67, 76, 69, 2, 129, 249, 19, 5, 32, 78, 85, 75, 84, 34, 36, 5, 83, + 73, 71, 78, 32, 91, 67, 30, 86, 67, 142, 138, 21, 65, 106, 86, 214, 20, + 85, 210, 200, 1, 73, 206, 134, 2, 69, 3, 79, 4, 201, 138, 21, 5, 65, 78, + 68, 82, 65, 126, 108, 7, 76, 69, 84, 84, 69, 82, 32, 212, 1, 5, 83, 73, + 71, 78, 32, 38, 86, 186, 253, 22, 68, 199, 221, 1, 79, 80, 250, 132, 21, + 65, 38, 68, 46, 84, 230, 24, 85, 22, 78, 190, 200, 1, 73, 42, 76, 242, + 190, 1, 66, 2, 67, 2, 71, 2, 74, 2, 75, 2, 80, 194, 40, 79, 162, 8, 69, + 158, 20, 72, 2, 77, 2, 82, 2, 83, 2, 86, 3, 89, 4, 174, 188, 22, 86, 223, + 234, 1, 65, 20, 230, 6, 79, 247, 178, 22, 73, 172, 1, 194, 1, 65, 44, 7, + 76, 69, 84, 84, 69, 82, 32, 242, 1, 83, 228, 2, 2, 86, 79, 244, 226, 12, + 3, 84, 73, 80, 146, 249, 4, 73, 172, 130, 3, 5, 69, 75, 32, 79, 78, 162, + 152, 2, 68, 235, 169, 1, 85, 4, 138, 255, 20, 66, 253, 187, 1, 2, 68, 68, + 96, 202, 156, 8, 71, 2, 75, 218, 172, 12, 82, 206, 55, 65, 38, 68, 46, + 84, 230, 24, 85, 210, 200, 1, 73, 42, 76, 246, 189, 1, 78, 126, 66, 2, + 67, 2, 74, 2, 80, 2, 83, 194, 40, 79, 162, 8, 69, 158, 20, 70, 2, 72, 2, + 77, 2, 86, 2, 89, 3, 90, 26, 108, 19, 69, 81, 85, 69, 78, 67, 69, 32, 70, + 79, 82, 32, 76, 69, 84, 84, 69, 82, 32, 93, 4, 73, 71, 78, 32, 12, 70, + 71, 2, 75, 222, 238, 22, 83, 166, 213, 1, 76, 226, 31, 70, 3, 90, 2, 219, + 238, 22, 72, 14, 128, 1, 6, 65, 68, 65, 75, 32, 66, 2, 66, 164, 211, 14, + 2, 85, 68, 150, 172, 6, 78, 160, 128, 2, 3, 89, 65, 75, 171, 162, 1, 86, + 2, 139, 238, 7, 73, 18, 45, 9, 87, 69, 76, 32, 83, 73, 71, 78, 32, 18, + 226, 255, 20, 65, 190, 21, 85, 210, 200, 1, 73, 218, 231, 1, 79, 163, 8, + 69, 142, 23, 110, 65, 162, 95, 69, 206, 103, 73, 146, 9, 79, 142, 11, 84, + 30, 85, 130, 1, 89, 137, 186, 12, 4, 82, 89, 86, 78, 136, 11, 248, 1, 2, + 73, 82, 60, 8, 76, 70, 87, 73, 68, 84, 72, 32, 254, 10, 77, 210, 1, 78, + 236, 76, 21, 80, 80, 89, 32, 80, 69, 82, 83, 79, 78, 32, 82, 65, 73, 83, + 73, 78, 71, 32, 79, 78, 22, 84, 180, 183, 17, 2, 85, 77, 128, 141, 5, 2, + 82, 68, 227, 46, 68, 6, 26, 32, 163, 231, 23, 67, 4, 134, 178, 23, 80, + 187, 112, 83, 244, 1, 132, 2, 7, 72, 65, 78, 71, 85, 76, 32, 216, 4, 8, + 75, 65, 84, 65, 75, 65, 78, 65, 204, 3, 3, 76, 69, 70, 0, 4, 82, 73, 71, + 72, 58, 85, 228, 159, 6, 11, 70, 79, 82, 77, 83, 32, 76, 73, 71, 72, 84, + 194, 207, 6, 73, 174, 170, 4, 66, 190, 185, 4, 87, 167, 26, 68, 104, 52, + 7, 76, 69, 84, 84, 69, 82, 32, 255, 181, 10, 70, 102, 206, 1, 75, 28, 5, + 78, 73, 69, 85, 78, 42, 80, 24, 5, 82, 73, 69, 85, 76, 86, 83, 98, 89, + 222, 61, 67, 54, 69, 30, 73, 242, 4, 77, 138, 1, 84, 206, 3, 87, 198, 1, + 72, 214, 208, 23, 65, 2, 79, 151, 64, 85, 6, 242, 65, 72, 155, 3, 73, 7, + 11, 45, 4, 154, 72, 67, 131, 3, 72, 6, 166, 69, 72, 35, 73, 17, 11, 45, + 14, 226, 49, 84, 226, 14, 80, 130, 4, 77, 194, 3, 75, 218, 2, 72, 99, 83, + 12, 40, 4, 83, 65, 78, 71, 215, 178, 13, 73, 10, 230, 70, 67, 42, 75, 74, + 80, 34, 84, 211, 2, 83, 14, 154, 155, 22, 69, 238, 254, 1, 65, 150, 64, + 73, 2, 79, 3, 85, 118, 70, 32, 149, 238, 2, 11, 45, 72, 73, 82, 65, 71, + 65, 78, 65, 32, 80, 116, 76, 7, 76, 69, 84, 84, 69, 82, 32, 234, 237, 2, + 83, 34, 86, 147, 217, 20, 77, 110, 146, 1, 83, 222, 231, 2, 78, 150, 2, + 72, 2, 75, 2, 77, 2, 82, 2, 84, 170, 1, 89, 210, 41, 87, 202, 194, 21, + 65, 2, 69, 2, 73, 2, 79, 3, 85, 28, 76, 5, 77, 65, 76, 76, 32, 226, 214, + 24, 65, 2, 69, 2, 73, 2, 79, 3, 85, 18, 198, 234, 2, 89, 178, 199, 21, + 84, 234, 36, 65, 2, 69, 2, 73, 2, 79, 3, 85, 4, 11, 84, 4, 236, 243, 12, + 2, 32, 67, 231, 194, 10, 87, 2, 155, 182, 23, 80, 14, 56, 3, 77, 69, 82, + 106, 83, 173, 156, 21, 3, 66, 85, 82, 9, 29, 5, 32, 65, 78, 68, 32, 6, + 172, 128, 12, 3, 87, 82, 69, 180, 213, 3, 2, 83, 73, 175, 208, 7, 80, 4, + 136, 151, 24, 3, 84, 69, 82, 151, 61, 65, 194, 8, 118, 68, 202, 2, 71, + 128, 66, 13, 73, 70, 73, 32, 82, 79, 72, 73, 78, 71, 89, 65, 32, 165, 5, + 5, 85, 78, 79, 79, 32, 10, 100, 12, 32, 87, 73, 84, 72, 32, 73, 78, 68, + 69, 88, 32, 188, 1, 2, 66, 65, 217, 138, 21, 2, 83, 72, 4, 156, 1, 18, + 65, 78, 68, 32, 77, 73, 68, 68, 76, 69, 32, 70, 73, 78, 71, 69, 82, 83, + 1, 16, 70, 73, 78, 71, 69, 82, 32, 65, 78, 68, 32, 84, 72, 85, 77, 66, 2, + 145, 206, 15, 2, 32, 67, 4, 182, 199, 23, 76, 159, 137, 1, 71, 170, 7, + 84, 3, 85, 76, 32, 217, 64, 13, 90, 72, 79, 85, 32, 78, 85, 77, 69, 82, + 65, 76, 32, 146, 7, 164, 1, 9, 67, 72, 79, 83, 69, 79, 78, 71, 32, 244, + 15, 4, 68, 79, 85, 66, 0, 4, 83, 73, 78, 71, 46, 74, 180, 31, 7, 76, 69, + 84, 84, 69, 82, 32, 215, 246, 9, 70, 250, 1, 246, 1, 67, 172, 2, 5, 73, + 69, 85, 78, 71, 146, 1, 75, 132, 1, 5, 77, 73, 69, 85, 77, 56, 5, 78, 73, + 69, 85, 78, 74, 80, 172, 2, 5, 82, 73, 69, 85, 76, 210, 1, 83, 166, 3, + 84, 124, 2, 89, 69, 200, 40, 5, 72, 73, 69, 85, 72, 139, 238, 9, 70, 30, + 76, 2, 72, 73, 84, 7, 69, 79, 78, 71, 67, 72, 73, 121, 4, 73, 69, 85, 67, + 16, 40, 4, 69, 85, 67, 72, 41, 2, 84, 85, 7, 11, 45, 4, 202, 31, 75, 243, + 26, 72, 10, 21, 3, 69, 85, 77, 10, 22, 83, 155, 46, 67, 6, 40, 4, 83, 65, + 78, 71, 179, 162, 13, 73, 4, 194, 54, 67, 227, 3, 83, 5, 215, 30, 45, 27, + 11, 45, 24, 90, 80, 234, 30, 82, 242, 13, 67, 194, 5, 77, 138, 1, 84, + 186, 2, 75, 218, 2, 72, 99, 83, 6, 214, 50, 72, 214, 3, 73, 207, 2, 65, + 16, 80, 7, 65, 80, 89, 69, 79, 85, 78, 228, 20, 5, 73, 89, 69, 79, 75, + 131, 25, 72, 10, 234, 29, 82, 178, 15, 80, 30, 83, 231, 3, 77, 11, 11, + 45, 8, 158, 52, 75, 74, 80, 34, 84, 211, 2, 83, 15, 11, 45, 12, 190, 51, + 67, 42, 75, 74, 80, 34, 84, 242, 1, 72, 99, 83, 42, 68, 6, 72, 73, 69, + 85, 80, 72, 40, 4, 73, 69, 85, 80, 223, 53, 65, 7, 11, 45, 4, 158, 51, + 80, 147, 2, 72, 35, 11, 45, 32, 82, 83, 234, 20, 80, 214, 7, 75, 162, 12, + 67, 202, 6, 84, 226, 2, 78, 179, 2, 72, 14, 32, 3, 73, 79, 83, 251, 3, + 83, 13, 11, 45, 10, 242, 46, 84, 146, 2, 67, 42, 75, 75, 80, 29, 11, 45, + 26, 78, 75, 42, 83, 190, 44, 77, 154, 3, 67, 82, 78, 34, 80, 34, 84, 243, + 1, 72, 6, 170, 22, 65, 130, 19, 72, 135, 7, 73, 8, 40, 4, 83, 65, 78, 71, + 151, 155, 13, 73, 6, 206, 47, 75, 74, 80, 35, 84, 58, 48, 3, 73, 79, 83, + 217, 1, 4, 83, 65, 78, 71, 33, 11, 45, 30, 130, 1, 80, 44, 2, 83, 83, + 210, 22, 82, 210, 1, 75, 162, 12, 67, 194, 5, 77, 138, 1, 84, 226, 2, 78, + 178, 2, 72, 223, 223, 17, 73, 6, 184, 23, 4, 73, 69, 85, 80, 179, 19, 72, + 2, 233, 48, 3, 65, 78, 71, 26, 236, 17, 5, 67, 73, 69, 85, 67, 172, 3, 4, + 83, 73, 79, 83, 154, 1, 82, 186, 20, 84, 54, 89, 134, 2, 75, 42, 78, 34, + 80, 146, 2, 72, 223, 223, 17, 73, 16, 40, 5, 73, 75, 69, 85, 84, 195, 41, + 72, 15, 11, 45, 12, 226, 20, 82, 178, 19, 77, 154, 3, 67, 42, 75, 74, 80, + 243, 2, 83, 4, 150, 19, 83, 139, 22, 79, 2, 165, 211, 8, 6, 76, 69, 32, + 68, 79, 84, 216, 3, 92, 9, 79, 78, 71, 83, 69, 79, 78, 71, 32, 165, 21, + 9, 85, 78, 71, 83, 69, 79, 78, 71, 32, 154, 2, 226, 1, 67, 80, 5, 72, 73, + 69, 85, 72, 60, 5, 73, 69, 85, 78, 71, 46, 75, 220, 1, 5, 77, 73, 69, 85, + 77, 188, 1, 5, 78, 73, 69, 85, 78, 94, 80, 240, 2, 5, 82, 73, 69, 85, 76, + 190, 4, 83, 194, 3, 84, 213, 1, 2, 89, 69, 8, 36, 4, 73, 69, 85, 67, 239, + 30, 72, 7, 11, 45, 4, 162, 32, 83, 239, 7, 80, 11, 11, 45, 8, 174, 16, + 82, 178, 19, 77, 234, 3, 78, 35, 80, 9, 11, 45, 6, 194, 17, 75, 57, 2, + 83, 83, 28, 76, 7, 65, 80, 89, 69, 79, 85, 78, 40, 5, 73, 89, 69, 79, 75, + 215, 30, 72, 8, 130, 15, 82, 178, 15, 80, 131, 4, 77, 19, 11, 45, 16, + 166, 13, 75, 170, 1, 82, 42, 83, 224, 13, 2, 67, 72, 146, 9, 78, 34, 80, + 147, 2, 72, 27, 11, 45, 24, 74, 80, 30, 83, 134, 13, 82, 242, 13, 67, + 130, 9, 75, 42, 78, 179, 2, 72, 6, 174, 33, 73, 131, 6, 65, 6, 40, 4, 83, + 65, 78, 71, 143, 143, 13, 73, 4, 238, 35, 78, 147, 3, 83, 21, 11, 45, 18, + 174, 12, 82, 242, 13, 67, 202, 6, 84, 186, 2, 75, 218, 2, 72, 62, 80, 39, + 83, 36, 88, 6, 65, 78, 83, 73, 79, 83, 48, 6, 72, 73, 69, 85, 80, 72, 53, + 4, 73, 69, 85, 80, 7, 11, 45, 4, 236, 7, 2, 75, 65, 195, 26, 80, 9, 11, + 45, 6, 150, 11, 84, 234, 22, 80, 243, 2, 83, 23, 11, 45, 20, 112, 5, 82, + 73, 69, 85, 76, 24, 4, 83, 73, 79, 83, 134, 3, 80, 246, 19, 67, 194, 5, + 77, 170, 4, 84, 243, 1, 72, 5, 153, 3, 2, 45, 80, 5, 221, 32, 2, 45, 84, + 57, 11, 45, 54, 102, 75, 92, 5, 77, 73, 69, 85, 77, 50, 80, 126, 83, 74, + 84, 44, 2, 89, 69, 154, 28, 78, 179, 2, 72, 10, 52, 5, 73, 89, 69, 79, + 75, 190, 4, 65, 131, 19, 72, 7, 11, 45, 4, 254, 32, 72, 99, 83, 9, 11, + 45, 6, 130, 30, 75, 218, 2, 72, 99, 83, 14, 48, 4, 73, 69, 85, 80, 174, + 26, 72, 163, 6, 65, 11, 11, 45, 8, 42, 80, 222, 29, 84, 242, 1, 72, 99, + 83, 2, 243, 25, 72, 6, 40, 4, 83, 65, 78, 71, 255, 135, 13, 73, 4, 182, + 28, 75, 187, 3, 83, 6, 100, 5, 73, 75, 69, 85, 84, 151, 25, 72, 6, 56, 9, + 79, 82, 73, 78, 72, 73, 69, 85, 72, 191, 3, 83, 5, 255, 29, 45, 52, 48, + 3, 73, 79, 83, 161, 1, 4, 83, 65, 78, 71, 25, 11, 45, 22, 82, 75, 162, 3, + 82, 242, 13, 67, 198, 2, 80, 254, 2, 77, 138, 1, 84, 147, 5, 72, 4, 22, + 65, 135, 26, 73, 2, 237, 18, 6, 80, 89, 69, 79, 85, 78, 28, 160, 1, 5, + 82, 73, 69, 85, 76, 36, 6, 84, 73, 75, 69, 85, 84, 16, 3, 89, 69, 83, + 138, 19, 83, 178, 1, 77, 154, 3, 67, 42, 75, 42, 78, 34, 80, 239, 225, + 17, 73, 5, 17, 2, 45, 75, 2, 159, 17, 72, 5, 255, 16, 45, 2, 171, 250, + 17, 73, 20, 40, 5, 73, 75, 69, 85, 84, 155, 21, 72, 19, 11, 45, 16, 58, + 82, 42, 83, 42, 84, 162, 13, 67, 130, 9, 75, 75, 80, 2, 17, 2, 73, 69, 2, + 255, 160, 23, 85, 4, 21, 3, 73, 79, 83, 5, 223, 1, 45, 2, 255, 19, 72, + 18, 44, 6, 83, 73, 69, 85, 78, 71, 243, 19, 79, 17, 11, 45, 14, 50, 75, + 30, 83, 198, 17, 77, 154, 6, 72, 63, 80, 4, 166, 14, 72, 135, 7, 73, 4, + 26, 83, 175, 128, 13, 73, 2, 21, 3, 65, 78, 71, 2, 207, 20, 75, 190, 1, + 122, 65, 118, 69, 134, 1, 73, 92, 7, 83, 83, 65, 78, 71, 65, 82, 106, 79, + 138, 1, 85, 102, 89, 174, 15, 87, 175, 234, 9, 70, 23, 48, 4, 82, 65, 69, + 65, 98, 45, 239, 165, 24, 69, 13, 11, 45, 10, 190, 231, 21, 69, 130, 191, + 2, 65, 2, 73, 3, 85, 25, 18, 79, 55, 85, 9, 11, 45, 6, 130, 129, 24, 69, + 234, 36, 79, 3, 85, 15, 11, 45, 12, 170, 9, 69, 142, 156, 24, 65, 2, 79, + 3, 85, 31, 11, 45, 28, 66, 65, 34, 89, 166, 1, 79, 142, 254, 23, 69, 234, + 36, 73, 3, 85, 5, 11, 82, 2, 235, 212, 17, 65, 14, 50, 65, 230, 228, 21, + 69, 130, 191, 2, 79, 3, 85, 7, 238, 132, 24, 45, 247, 30, 69, 23, 26, 45, + 171, 163, 24, 69, 18, 50, 79, 22, 89, 226, 227, 21, 69, 131, 191, 2, 85, + 5, 155, 143, 24, 45, 8, 222, 227, 21, 69, 239, 254, 1, 65, 17, 11, 45, + 14, 158, 19, 89, 234, 136, 5, 73, 192, 170, 4, 3, 69, 79, 45, 214, 155, + 14, 65, 151, 64, 85, 62, 42, 65, 70, 69, 66, 73, 22, 79, 107, 85, 11, 26, + 45, 147, 161, 24, 69, 6, 154, 130, 24, 89, 246, 30, 79, 3, 85, 11, 11, + 79, 9, 11, 45, 6, 150, 158, 24, 89, 186, 2, 79, 3, 85, 5, 191, 251, 23, + 45, 19, 11, 45, 16, 58, 89, 186, 223, 23, 65, 162, 33, 69, 246, 30, 73, + 3, 79, 6, 182, 223, 23, 65, 163, 33, 69, 21, 11, 45, 18, 142, 16, 89, + 146, 208, 21, 69, 238, 254, 1, 65, 150, 64, 73, 2, 79, 3, 85, 186, 1, + 226, 1, 65, 46, 67, 54, 69, 30, 73, 22, 75, 188, 1, 5, 77, 73, 69, 85, + 77, 64, 5, 78, 73, 69, 85, 78, 70, 80, 168, 1, 5, 82, 73, 69, 85, 76, + 254, 1, 84, 90, 83, 246, 2, 87, 50, 89, 150, 1, 72, 214, 208, 23, 79, + 151, 64, 85, 9, 156, 13, 3, 82, 65, 69, 207, 143, 24, 69, 4, 22, 72, 207, + 8, 73, 2, 241, 249, 23, 2, 73, 69, 7, 138, 156, 24, 79, 3, 85, 5, 239, + 234, 17, 69, 14, 56, 7, 65, 80, 89, 69, 79, 85, 78, 106, 72, 155, 3, 73, + 8, 30, 80, 30, 83, 231, 3, 77, 4, 190, 4, 72, 215, 3, 73, 2, 25, 4, 83, + 65, 78, 71, 2, 207, 7, 80, 2, 253, 59, 2, 73, 69, 9, 11, 45, 6, 22, 80, + 247, 9, 83, 4, 142, 7, 73, 207, 2, 65, 13, 11, 45, 10, 234, 5, 67, 146, + 1, 84, 242, 1, 72, 62, 80, 39, 83, 20, 48, 4, 73, 69, 85, 80, 170, 2, 72, + 163, 6, 65, 17, 11, 45, 14, 42, 83, 186, 2, 84, 146, 2, 67, 43, 75, 6, + 21, 3, 73, 79, 83, 7, 11, 45, 4, 202, 4, 75, 107, 84, 27, 11, 45, 24, 68, + 2, 75, 73, 34, 77, 34, 80, 106, 84, 54, 89, 222, 4, 72, 99, 83, 4, 149, + 1, 4, 89, 69, 79, 75, 2, 11, 73, 2, 255, 238, 22, 69, 8, 30, 72, 34, 73, + 131, 6, 65, 2, 245, 156, 18, 3, 73, 69, 85, 4, 21, 3, 69, 85, 80, 5, 243, + 5, 45, 4, 22, 72, 151, 3, 73, 2, 229, 167, 19, 2, 73, 69, 2, 17, 2, 69, + 79, 2, 167, 4, 82, 28, 44, 3, 73, 79, 83, 57, 4, 83, 65, 78, 71, 13, 11, + 45, 10, 122, 67, 42, 75, 42, 78, 34, 80, 35, 84, 16, 78, 67, 42, 75, 42, + 78, 34, 80, 34, 84, 242, 1, 72, 98, 83, 255, 222, 17, 73, 2, 11, 73, 2, + 249, 236, 22, 2, 69, 85, 2, 11, 73, 2, 209, 233, 23, 2, 89, 69, 2, 11, + 73, 2, 243, 146, 23, 69, 2, 11, 73, 2, 135, 157, 23, 69, 2, 11, 73, 2, + 11, 75, 2, 255, 152, 23, 69, 10, 170, 211, 21, 69, 238, 254, 1, 65, 151, + 64, 73, 34, 58, 69, 206, 1, 79, 62, 85, 166, 207, 23, 65, 151, 64, 73, + 13, 42, 79, 73, 6, 83, 73, 69, 85, 78, 71, 5, 11, 82, 2, 17, 2, 73, 78, + 2, 11, 72, 2, 157, 200, 9, 2, 73, 69, 7, 11, 45, 4, 18, 80, 39, 83, 2, + 11, 65, 2, 11, 78, 2, 11, 83, 2, 139, 232, 12, 73, 9, 11, 45, 6, 26, 89, + 207, 143, 24, 73, 4, 183, 207, 23, 65, 9, 11, 45, 6, 26, 89, 147, 143, + 24, 73, 4, 143, 208, 21, 69, 24, 178, 223, 10, 84, 170, 194, 11, 70, 30, + 83, 230, 83, 78, 14, 79, 199, 110, 69, 100, 156, 1, 7, 76, 69, 84, 84, + 69, 82, 32, 196, 2, 5, 77, 65, 82, 75, 32, 72, 5, 83, 73, 71, 78, 32, + 196, 156, 2, 6, 86, 79, 87, 69, 76, 32, 167, 255, 19, 68, 58, 202, 1, 68, + 34, 75, 222, 249, 18, 84, 174, 113, 82, 246, 168, 2, 78, 246, 175, 1, 83, + 254, 68, 66, 2, 67, 2, 70, 2, 71, 2, 72, 2, 74, 2, 76, 2, 77, 2, 80, 2, + 86, 2, 87, 2, 89, 2, 90, 187, 2, 65, 4, 138, 137, 24, 68, 187, 2, 65, 8, + 56, 5, 73, 78, 78, 65, 32, 178, 136, 24, 72, 187, 2, 65, 4, 174, 136, 24, + 87, 3, 89, 4, 208, 232, 20, 6, 78, 65, 32, 75, 72, 79, 189, 162, 2, 3, + 83, 65, 75, 8, 52, 2, 84, 65, 209, 255, 21, 5, 72, 65, 82, 66, 65, 6, 42, + 72, 142, 203, 19, 83, 223, 187, 4, 78, 2, 135, 231, 23, 65, 42, 62, 76, + 172, 167, 18, 6, 83, 73, 71, 78, 32, 80, 139, 2, 86, 36, 33, 6, 69, 84, + 84, 69, 82, 32, 36, 158, 185, 20, 78, 210, 204, 3, 66, 2, 68, 2, 71, 2, + 72, 2, 75, 2, 76, 2, 77, 2, 80, 2, 82, 2, 83, 2, 84, 2, 87, 2, 89, 186, + 2, 65, 2, 73, 3, 85, 2, 135, 249, 22, 69, 54, 52, 5, 67, 72, 73, 78, 71, + 41, 4, 82, 65, 78, 32, 2, 17, 2, 32, 67, 2, 207, 215, 22, 72, 52, 52, 7, + 76, 69, 84, 84, 69, 82, 32, 211, 145, 6, 78, 42, 218, 1, 65, 226, 132, + 11, 90, 210, 46, 84, 150, 119, 76, 50, 81, 60, 6, 68, 65, 76, 69, 84, 72, + 198, 150, 4, 71, 122, 83, 66, 89, 154, 193, 1, 72, 234, 5, 75, 130, 76, + 66, 190, 173, 4, 78, 254, 1, 87, 202, 103, 80, 171, 4, 77, 4, 222, 193, + 16, 76, 207, 242, 6, 89, 170, 9, 230, 1, 65, 184, 32, 5, 66, 82, 69, 87, + 32, 230, 32, 76, 200, 1, 16, 78, 84, 65, 73, 71, 65, 78, 65, 32, 76, 69, + 84, 84, 69, 82, 32, 174, 12, 82, 120, 11, 88, 65, 71, 82, 65, 77, 32, 70, + 79, 82, 32, 137, 177, 23, 4, 68, 71, 69, 72, 212, 1, 42, 68, 98, 82, 201, + 1, 3, 86, 89, 32, 6, 44, 5, 83, 84, 79, 78, 69, 223, 215, 22, 80, 5, 205, + 219, 2, 7, 32, 71, 82, 65, 86, 69, 89, 12, 32, 2, 84, 32, 143, 222, 16, + 45, 10, 60, 5, 87, 73, 84, 72, 32, 210, 250, 11, 68, 139, 220, 8, 72, 6, + 76, 9, 84, 73, 80, 32, 79, 78, 32, 84, 72, 130, 200, 12, 82, 139, 157, + 10, 65, 2, 243, 204, 23, 69, 194, 1, 134, 2, 65, 202, 1, 66, 230, 2, 67, + 154, 3, 68, 162, 1, 69, 186, 3, 70, 94, 72, 62, 76, 222, 1, 77, 110, 79, + 162, 1, 82, 142, 2, 83, 228, 1, 3, 78, 79, 82, 198, 1, 84, 128, 2, 2, 85, + 80, 174, 1, 87, 146, 215, 13, 73, 146, 223, 3, 80, 242, 220, 3, 86, 215, + 74, 71, 12, 108, 17, 82, 82, 79, 87, 32, 83, 72, 65, 70, 84, 32, 87, 73, + 68, 84, 72, 32, 154, 217, 17, 77, 215, 146, 4, 83, 8, 36, 3, 79, 78, 69, + 235, 158, 22, 84, 7, 11, 32, 4, 182, 185, 13, 84, 151, 194, 8, 72, 14, + 48, 4, 65, 76, 76, 79, 21, 4, 76, 65, 67, 75, 2, 143, 140, 5, 84, 12, 30, + 32, 153, 1, 2, 45, 70, 6, 52, 7, 67, 85, 82, 86, 69, 68, 32, 151, 243, + 22, 72, 4, 40, 4, 68, 79, 87, 78, 1, 2, 85, 80, 2, 245, 217, 22, 8, 87, + 65, 82, 68, 83, 32, 65, 78, 6, 45, 9, 69, 65, 84, 72, 69, 82, 69, 68, 32, + 6, 194, 159, 13, 83, 210, 164, 3, 78, 163, 149, 6, 82, 14, 116, 2, 72, + 69, 52, 5, 73, 82, 67, 76, 69, 245, 159, 17, 14, 79, 78, 67, 65, 86, 69, + 45, 80, 79, 73, 78, 84, 69, 68, 4, 156, 134, 20, 4, 86, 82, 79, 78, 247, + 176, 2, 67, 9, 64, 6, 32, 87, 73, 84, 72, 32, 165, 229, 21, 4, 68, 32, + 83, 65, 4, 52, 7, 83, 84, 82, 79, 75, 69, 32, 159, 227, 4, 67, 2, 29, 5, + 65, 78, 68, 32, 84, 2, 11, 87, 2, 11, 79, 2, 21, 3, 32, 68, 79, 2, 11, + 84, 2, 231, 248, 22, 83, 14, 52, 7, 65, 83, 72, 69, 68, 32, 84, 18, 73, + 31, 79, 2, 175, 16, 82, 2, 157, 201, 18, 2, 86, 73, 10, 192, 16, 3, 87, + 78, 87, 206, 214, 13, 85, 135, 162, 4, 76, 16, 120, 5, 73, 71, 72, 84, + 32, 156, 2, 16, 88, 67, 76, 65, 77, 65, 84, 73, 79, 78, 32, 77, 65, 82, + 75, 32, 231, 133, 18, 81, 10, 40, 2, 80, 79, 126, 84, 135, 225, 21, 83, + 6, 33, 6, 73, 78, 84, 69, 68, 32, 6, 174, 130, 16, 80, 128, 221, 5, 11, + 82, 69, 67, 84, 73, 76, 73, 78, 69, 65, 82, 23, 66, 2, 173, 225, 21, 24, + 69, 65, 82, 68, 82, 79, 80, 45, 83, 80, 79, 75, 69, 68, 32, 80, 82, 79, + 80, 69, 76, 76, 69, 82, 4, 150, 222, 22, 83, 187, 79, 79, 6, 44, 5, 79, + 85, 82, 32, 66, 227, 226, 4, 73, 2, 225, 218, 10, 6, 65, 76, 76, 79, 79, + 78, 4, 210, 254, 16, 79, 157, 170, 5, 6, 69, 65, 82, 84, 32, 69, 20, 74, + 65, 44, 3, 69, 70, 84, 28, 2, 79, 87, 237, 221, 4, 3, 73, 71, 65, 4, 212, + 236, 20, 2, 82, 71, 167, 196, 1, 84, 8, 254, 3, 45, 195, 6, 87, 6, 26, + 32, 179, 236, 9, 69, 4, 162, 225, 13, 68, 25, 4, 83, 73, 78, 71, 4, 56, + 8, 85, 76, 84, 73, 80, 76, 73, 67, 227, 211, 20, 73, 2, 25, 4, 65, 84, + 73, 79, 2, 163, 254, 4, 78, 6, 172, 234, 5, 9, 80, 69, 78, 32, 67, 69, + 78, 84, 82, 204, 152, 10, 13, 86, 65, 76, 32, 87, 73, 84, 72, 32, 79, 86, + 65, 76, 213, 214, 5, 5, 85, 84, 76, 73, 78, 12, 76, 4, 73, 71, 72, 84, + 149, 203, 22, 9, 79, 85, 78, 68, 45, 84, 73, 80, 80, 10, 62, 45, 109, 11, + 87, 65, 82, 68, 83, 32, 65, 82, 82, 79, 87, 4, 69, 15, 80, 79, 73, 78, + 84, 73, 78, 71, 32, 65, 78, 71, 76, 69, 32, 4, 130, 196, 6, 66, 247, 153, + 7, 81, 7, 139, 6, 32, 26, 106, 65, 78, 73, 44, 2, 79, 85, 168, 229, 13, + 7, 67, 82, 73, 80, 84, 32, 76, 225, 131, 1, 3, 80, 65, 82, 4, 244, 220, + 13, 10, 78, 83, 45, 83, 69, 82, 73, 70, 32, 73, 195, 250, 7, 76, 8, 224, + 218, 13, 2, 78, 71, 203, 249, 7, 88, 10, 21, 3, 84, 72, 32, 10, 60, 5, + 69, 65, 83, 84, 32, 29, 6, 87, 69, 83, 84, 32, 80, 6, 26, 80, 235, 204, + 22, 65, 4, 41, 8, 79, 73, 78, 84, 73, 78, 71, 32, 4, 178, 181, 16, 86, + 239, 134, 6, 66, 12, 88, 9, 69, 65, 82, 68, 82, 79, 80, 45, 83, 130, 1, + 82, 169, 192, 6, 4, 87, 69, 76, 86, 6, 64, 6, 80, 79, 75, 69, 68, 32, + 145, 197, 22, 4, 72, 65, 78, 75, 4, 196, 212, 21, 8, 80, 73, 78, 87, 72, + 69, 69, 76, 27, 65, 2, 137, 3, 5, 73, 65, 78, 71, 76, 6, 26, 87, 159, + 226, 9, 80, 4, 53, 11, 65, 82, 68, 83, 32, 65, 82, 82, 79, 87, 32, 4, 29, + 5, 87, 73, 84, 72, 32, 4, 204, 181, 19, 5, 76, 65, 82, 71, 69, 187, 200, + 1, 69, 10, 72, 5, 72, 73, 84, 69, 32, 112, 2, 73, 68, 177, 254, 21, 3, + 69, 68, 71, 6, 56, 5, 68, 79, 87, 78, 45, 130, 147, 22, 67, 199, 46, 83, + 2, 165, 190, 22, 8, 80, 79, 73, 78, 84, 73, 78, 71, 2, 145, 153, 20, 2, + 69, 45, 140, 2, 112, 7, 65, 67, 67, 69, 78, 84, 32, 146, 8, 76, 164, 14, + 5, 77, 65, 82, 75, 32, 114, 80, 245, 188, 20, 2, 89, 79, 60, 132, 2, 9, + 65, 84, 78, 65, 72, 32, 72, 65, 70, 22, 68, 36, 3, 71, 69, 82, 74, 77, + 128, 1, 2, 80, 65, 28, 4, 69, 84, 78, 65, 20, 2, 81, 65, 58, 83, 58, 84, + 156, 1, 2, 89, 69, 78, 90, 152, 132, 8, 3, 82, 69, 86, 246, 179, 14, 79, + 221, 143, 1, 3, 73, 76, 85, 2, 255, 214, 17, 85, 4, 178, 186, 18, 69, + 175, 225, 4, 65, 6, 32, 3, 69, 83, 72, 195, 28, 83, 5, 237, 187, 6, 4, + 32, 77, 85, 81, 8, 88, 5, 69, 82, 75, 72, 65, 148, 164, 16, 2, 85, 78, + 145, 177, 1, 5, 65, 72, 65, 80, 65, 5, 149, 150, 19, 4, 32, 75, 69, 70, + 4, 26, 83, 191, 158, 23, 90, 2, 207, 183, 23, 72, 4, 196, 151, 23, 6, 82, + 78, 69, 89, 32, 80, 179, 35, 68, 4, 194, 24, 69, 241, 230, 21, 6, 72, 65, + 76, 83, 72, 69, 8, 38, 69, 181, 227, 21, 3, 73, 80, 69, 6, 48, 6, 76, 73, + 83, 72, 65, 32, 163, 183, 11, 86, 4, 136, 177, 21, 3, 81, 69, 84, 153, + 135, 2, 4, 71, 69, 68, 79, 4, 176, 171, 8, 10, 82, 65, 72, 32, 66, 69, + 78, 32, 89, 79, 167, 214, 2, 84, 8, 34, 65, 177, 160, 23, 2, 73, 78, 6, + 40, 4, 81, 69, 70, 32, 139, 222, 5, 82, 4, 194, 222, 10, 81, 197, 231, + 11, 3, 71, 65, 68, 150, 1, 76, 6, 69, 84, 84, 69, 82, 32, 201, 11, 8, 73, + 71, 65, 84, 85, 82, 69, 32, 140, 1, 134, 3, 65, 204, 1, 3, 66, 69, 84, 0, + 3, 75, 65, 70, 0, 2, 80, 69, 68, 6, 70, 73, 78, 65, 76, 32, 92, 2, 81, + 79, 16, 2, 72, 69, 52, 2, 78, 85, 0, 4, 90, 65, 89, 73, 18, 83, 48, 3, + 82, 69, 83, 170, 1, 84, 52, 4, 68, 65, 76, 69, 12, 5, 71, 73, 77, 69, 76, + 0, 5, 76, 65, 77, 69, 68, 0, 3, 77, 69, 77, 48, 3, 86, 65, 86, 80, 5, 87, + 73, 68, 69, 32, 153, 1, 3, 89, 79, 68, 14, 26, 76, 251, 212, 22, 89, 12, + 64, 2, 69, 70, 73, 10, 84, 69, 82, 78, 65, 84, 73, 86, 69, 32, 9, 33, 6, + 32, 87, 73, 84, 72, 32, 6, 250, 12, 77, 130, 1, 80, 35, 81, 4, 254, 145, + 16, 65, 187, 148, 1, 80, 7, 33, 6, 32, 87, 73, 84, 72, 32, 4, 154, 15, + 82, 243, 172, 13, 68, 14, 88, 2, 75, 65, 236, 2, 2, 80, 69, 136, 152, 1, + 2, 84, 83, 218, 182, 21, 78, 239, 109, 77, 4, 235, 2, 70, 7, 236, 10, 5, + 32, 87, 73, 84, 72, 231, 198, 23, 84, 4, 167, 2, 78, 16, 44, 4, 65, 77, + 69, 75, 17, 3, 72, 73, 78, 4, 231, 1, 72, 13, 33, 6, 32, 87, 73, 84, 72, + 32, 10, 40, 6, 68, 65, 71, 69, 83, 72, 39, 83, 7, 33, 6, 32, 65, 78, 68, + 32, 83, 4, 210, 221, 5, 72, 167, 192, 2, 73, 12, 50, 69, 12, 2, 65, 86, + 1, 4, 83, 65, 68, 73, 4, 11, 84, 5, 161, 184, 13, 7, 32, 87, 73, 84, 72, + 32, 68, 7, 33, 6, 32, 87, 73, 84, 72, 32, 4, 176, 251, 1, 2, 72, 79, 159, + 188, 11, 68, 16, 174, 2, 76, 250, 169, 8, 65, 246, 188, 2, 84, 158, 206, + 2, 82, 164, 186, 8, 2, 68, 65, 134, 91, 75, 198, 106, 72, 169, 4, 7, 70, + 73, 78, 65, 76, 32, 77, 7, 33, 6, 32, 87, 73, 84, 72, 32, 4, 168, 7, 2, + 72, 73, 191, 174, 13, 68, 10, 72, 6, 65, 76, 69, 70, 32, 76, 29, 8, 89, + 73, 68, 68, 73, 83, 72, 32, 2, 133, 236, 18, 2, 65, 77, 8, 120, 7, 68, + 79, 85, 66, 76, 69, 32, 224, 4, 9, 89, 79, 68, 32, 89, 79, 68, 32, 80, + 237, 163, 20, 5, 86, 65, 86, 32, 89, 4, 210, 229, 10, 86, 251, 194, 9, + 89, 6, 80, 3, 76, 79, 87, 0, 3, 85, 80, 80, 153, 250, 21, 6, 77, 65, 83, + 79, 82, 65, 2, 185, 184, 22, 2, 69, 82, 50, 84, 5, 79, 73, 78, 84, 32, + 241, 5, 11, 85, 78, 67, 84, 85, 65, 84, 73, 79, 78, 32, 38, 220, 1, 9, + 68, 65, 71, 69, 83, 72, 32, 79, 82, 46, 72, 106, 80, 164, 1, 17, 74, 85, + 68, 69, 79, 45, 83, 80, 65, 78, 73, 83, 72, 32, 86, 65, 82, 22, 81, 86, + 82, 22, 83, 168, 174, 9, 2, 84, 83, 173, 207, 13, 3, 77, 69, 84, 2, 17, + 2, 32, 77, 2, 201, 1, 2, 65, 80, 12, 60, 5, 65, 84, 65, 70, 32, 106, 73, + 33, 4, 79, 76, 65, 77, 6, 38, 80, 34, 81, 165, 2, 2, 83, 69, 2, 11, 65, + 2, 251, 140, 16, 84, 2, 153, 177, 22, 3, 65, 77, 65, 2, 11, 82, 2, 207, + 177, 13, 73, 5, 145, 224, 10, 12, 32, 72, 65, 83, 69, 82, 32, 70, 79, 82, + 32, 86, 2, 195, 187, 23, 73, 6, 52, 5, 65, 77, 65, 84, 83, 133, 150, 11, + 2, 85, 66, 5, 193, 201, 10, 2, 32, 81, 2, 243, 191, 6, 65, 8, 34, 69, 22, + 72, 151, 145, 8, 73, 2, 179, 176, 22, 71, 4, 146, 145, 8, 73, 171, 187, + 7, 69, 12, 152, 1, 3, 71, 69, 82, 60, 3, 80, 65, 83, 20, 7, 83, 79, 70, + 32, 80, 65, 83, 224, 142, 21, 7, 78, 85, 78, 32, 72, 65, 70, 241, 176, 1, + 3, 77, 65, 81, 4, 26, 83, 131, 220, 21, 69, 2, 225, 190, 22, 3, 72, 65, + 89, 2, 199, 173, 13, 69, 2, 179, 173, 13, 85, 8, 114, 77, 248, 235, 11, + 15, 76, 83, 67, 72, 82, 69, 73, 66, 69, 82, 32, 80, 65, 85, 83, 221, 193, + 5, 3, 73, 67, 79, 4, 252, 188, 5, 12, 69, 84, 32, 87, 73, 84, 72, 32, 87, + 72, 73, 84, 223, 239, 16, 32, 188, 4, 164, 1, 2, 65, 45, 50, 72, 70, 75, + 230, 1, 77, 114, 78, 146, 2, 82, 66, 83, 154, 1, 84, 226, 1, 87, 62, 89, + 110, 69, 186, 206, 8, 85, 250, 148, 5, 79, 167, 178, 3, 73, 8, 234, 158, + 23, 87, 246, 30, 49, 2, 50, 3, 51, 72, 166, 6, 79, 182, 157, 8, 65, 222, + 201, 5, 85, 162, 115, 69, 3, 73, 74, 72, 2, 65, 45, 104, 2, 79, 45, 178, + 4, 73, 226, 3, 69, 211, 214, 14, 85, 24, 210, 193, 11, 49, 250, 227, 11, + 75, 214, 22, 50, 2, 51, 2, 52, 2, 53, 2, 54, 2, 55, 2, 56, 3, 57, 8, 222, + 167, 23, 75, 218, 19, 49, 2, 50, 3, 51, 54, 68, 2, 69, 45, 154, 7, 79, + 210, 214, 14, 65, 2, 73, 135, 191, 2, 85, 6, 134, 184, 23, 77, 186, 2, + 49, 3, 50, 68, 116, 2, 69, 45, 72, 2, 73, 45, 246, 2, 65, 246, 208, 8, + 79, 250, 148, 5, 85, 165, 160, 4, 6, 45, 77, 85, 45, 77, 79, 14, 170, + 154, 23, 75, 246, 30, 49, 2, 50, 2, 51, 2, 52, 2, 53, 3, 54, 16, 130, + 162, 23, 84, 214, 22, 49, 2, 50, 2, 51, 2, 52, 2, 53, 2, 54, 3, 55, 54, + 222, 4, 79, 2, 85, 210, 214, 14, 73, 134, 191, 2, 65, 3, 69, 68, 62, 65, + 2, 85, 226, 3, 73, 186, 206, 8, 69, 155, 136, 6, 79, 16, 11, 45, 16, 250, + 182, 23, 49, 2, 50, 2, 51, 2, 52, 2, 53, 2, 54, 2, 55, 3, 56, 64, 74, 69, + 20, 2, 79, 45, 72, 2, 85, 45, 178, 216, 14, 73, 135, 191, 2, 65, 18, 223, + 169, 18, 45, 14, 150, 179, 23, 82, 186, 2, 49, 2, 50, 2, 51, 2, 52, 2, + 53, 3, 54, 10, 146, 150, 23, 84, 246, 30, 49, 2, 50, 2, 51, 3, 52, 42, + 222, 207, 8, 65, 2, 73, 154, 136, 6, 79, 135, 191, 2, 69, 32, 40, 2, 65, + 45, 66, 79, 215, 149, 17, 85, 12, 242, 148, 23, 89, 246, 30, 49, 2, 50, + 2, 51, 2, 52, 3, 53, 12, 11, 45, 12, 154, 179, 23, 49, 2, 50, 2, 51, 2, + 52, 2, 53, 3, 54, 4, 176, 133, 8, 21, 77, 73, 84, 73, 65, 78, 32, 67, 79, + 78, 74, 85, 71, 65, 84, 69, 32, 77, 65, 84, 82, 175, 173, 15, 66, 128, 1, + 210, 2, 65, 110, 66, 144, 1, 2, 67, 79, 94, 68, 198, 2, 70, 66, 71, 40, + 4, 72, 79, 76, 68, 164, 1, 2, 73, 78, 112, 2, 77, 79, 58, 79, 122, 80, + 100, 2, 82, 69, 62, 83, 238, 1, 84, 210, 5, 87, 216, 227, 14, 4, 76, 73, + 77, 73, 184, 137, 5, 11, 89, 79, 85, 84, 72, 70, 85, 76, 32, 70, 79, 133, + 159, 3, 9, 69, 78, 84, 72, 85, 83, 73, 65, 83, 6, 76, 3, 80, 80, 82, 124, + 4, 70, 84, 69, 82, 245, 209, 18, 4, 66, 85, 78, 68, 2, 149, 140, 23, 2, + 79, 65, 6, 92, 5, 69, 70, 79, 82, 69, 192, 193, 3, 6, 73, 84, 73, 78, 71, + 32, 1, 4, 82, 69, 65, 75, 2, 253, 220, 22, 7, 32, 67, 79, 77, 80, 76, 69, + 6, 26, 78, 239, 200, 18, 77, 4, 196, 236, 19, 4, 84, 69, 77, 80, 217, + 177, 2, 3, 70, 76, 73, 14, 110, 69, 78, 73, 134, 205, 18, 85, 173, 200, + 2, 15, 65, 82, 75, 69, 78, 73, 78, 71, 32, 79, 70, 32, 84, 72, 69, 6, + 150, 201, 18, 67, 192, 6, 2, 76, 73, 201, 152, 4, 5, 86, 69, 76, 79, 80, + 4, 184, 191, 18, 21, 70, 70, 73, 67, 85, 76, 84, 89, 32, 65, 84, 32, 84, + 72, 69, 32, 66, 69, 71, 73, 78, 137, 210, 2, 4, 83, 80, 69, 82, 4, 148, + 196, 18, 2, 79, 76, 221, 144, 4, 5, 69, 76, 76, 79, 87, 12, 36, 5, 65, + 84, 72, 69, 82, 35, 82, 2, 213, 206, 14, 3, 73, 78, 71, 10, 40, 4, 69, + 65, 84, 32, 211, 235, 22, 65, 8, 22, 80, 207, 5, 84, 6, 22, 79, 143, 5, + 82, 4, 168, 2, 2, 83, 83, 135, 232, 22, 87, 8, 50, 78, 134, 197, 18, 67, + 217, 5, 3, 70, 76, 85, 4, 184, 185, 18, 5, 69, 82, 32, 84, 82, 161, 17, + 2, 79, 67, 4, 128, 189, 21, 3, 68, 69, 83, 221, 59, 3, 85, 84, 72, 6, 26, + 66, 37, 2, 80, 80, 2, 209, 213, 22, 4, 83, 84, 82, 85, 4, 26, 82, 171, + 212, 22, 79, 2, 169, 140, 21, 2, 69, 83, 6, 200, 211, 14, 9, 85, 83, 72, + 73, 78, 71, 32, 85, 80, 168, 134, 2, 3, 82, 79, 71, 219, 142, 6, 69, 6, + 26, 84, 235, 180, 18, 86, 4, 186, 198, 18, 85, 215, 57, 82, 8, 132, 1, 5, + 77, 65, 76, 76, 32, 204, 178, 20, 6, 84, 65, 78, 68, 83, 84, 209, 233, 1, + 11, 80, 76, 73, 84, 84, 73, 78, 71, 32, 65, 80, 4, 24, 2, 80, 82, 43, 84, + 2, 157, 199, 18, 5, 69, 80, 79, 78, 68, 2, 11, 65, 2, 215, 209, 22, 77, + 30, 36, 3, 72, 69, 32, 171, 148, 17, 82, 28, 186, 2, 65, 130, 1, 67, 132, + 1, 3, 70, 65, 77, 20, 9, 82, 69, 67, 69, 80, 84, 73, 86, 69, 30, 87, 156, + 21, 12, 77, 65, 82, 82, 89, 73, 78, 71, 32, 77, 65, 73, 232, 242, 4, 6, + 71, 69, 78, 84, 76, 69, 204, 199, 10, 13, 75, 69, 69, 80, 73, 78, 71, 32, + 83, 84, 73, 76, 76, 177, 220, 3, 7, 74, 79, 89, 79, 85, 83, 32, 6, 58, + 82, 141, 140, 11, 8, 66, 89, 83, 77, 65, 76, 32, 87, 4, 220, 217, 19, 8, + 79, 85, 83, 73, 78, 71, 32, 84, 247, 179, 3, 77, 6, 160, 129, 1, 2, 65, + 85, 152, 215, 18, 9, 82, 69, 65, 84, 73, 86, 69, 32, 72, 233, 180, 1, 9, + 76, 73, 78, 71, 73, 78, 71, 32, 70, 2, 163, 250, 22, 73, 2, 129, 215, 19, + 2, 32, 69, 4, 242, 152, 21, 69, 209, 198, 1, 5, 65, 78, 68, 69, 82, 4, + 174, 198, 6, 65, 217, 146, 6, 14, 79, 82, 75, 32, 79, 78, 32, 84, 72, 69, + 32, 68, 69, 67, 222, 1, 236, 1, 2, 71, 72, 180, 2, 7, 82, 65, 71, 65, 78, + 65, 32, 212, 4, 7, 83, 84, 79, 82, 73, 67, 32, 184, 130, 15, 7, 78, 68, + 85, 32, 84, 69, 77, 236, 33, 4, 75, 73, 78, 71, 150, 235, 1, 66, 241, + 128, 4, 8, 80, 80, 79, 80, 79, 84, 65, 77, 12, 18, 32, 119, 45, 6, 144, + 234, 4, 2, 66, 82, 156, 152, 16, 6, 86, 79, 76, 84, 65, 71, 149, 47, 9, + 79, 67, 84, 69, 84, 32, 80, 82, 69, 6, 92, 11, 83, 80, 69, 69, 68, 32, + 84, 82, 65, 73, 78, 233, 166, 5, 6, 72, 69, 69, 76, 69, 68, 5, 133, 145, + 11, 14, 32, 87, 73, 84, 72, 32, 66, 85, 76, 76, 69, 84, 32, 78, 200, 1, + 112, 9, 68, 73, 71, 82, 65, 80, 72, 32, 89, 20, 7, 76, 69, 84, 84, 69, + 82, 32, 234, 170, 1, 86, 215, 207, 19, 73, 2, 135, 142, 16, 79, 194, 1, + 194, 1, 65, 74, 83, 218, 161, 1, 66, 162, 3, 78, 150, 2, 68, 2, 71, 2, + 72, 2, 75, 2, 77, 2, 80, 2, 82, 2, 84, 2, 90, 126, 87, 46, 89, 178, 199, + 21, 86, 234, 36, 69, 2, 73, 2, 79, 3, 85, 7, 37, 7, 82, 67, 72, 65, 73, + 67, 32, 4, 130, 240, 22, 87, 151, 14, 89, 42, 76, 5, 77, 65, 76, 76, 32, + 254, 147, 23, 65, 2, 69, 2, 73, 2, 79, 3, 85, 32, 182, 167, 1, 87, 46, + 89, 130, 142, 5, 75, 178, 185, 16, 84, 234, 36, 65, 2, 69, 2, 73, 2, 79, + 3, 85, 2, 171, 145, 8, 83, 92, 166, 1, 76, 52, 3, 78, 69, 89, 46, 82, + 130, 6, 84, 138, 1, 85, 210, 130, 16, 83, 138, 203, 2, 67, 172, 149, 3, + 6, 77, 79, 84, 72, 69, 84, 214, 163, 1, 79, 155, 3, 80, 6, 180, 212, 15, + 4, 76, 79, 87, 32, 163, 189, 7, 69, 4, 238, 164, 21, 66, 137, 156, 1, 2, + 32, 80, 50, 60, 8, 73, 90, 79, 78, 84, 65, 76, 32, 137, 5, 2, 83, 69, 44, + 198, 1, 66, 108, 4, 76, 73, 78, 69, 28, 17, 79, 78, 69, 32, 69, 73, 71, + 72, 84, 72, 32, 66, 76, 79, 67, 75, 45, 88, 10, 83, 67, 65, 78, 32, 76, + 73, 78, 69, 45, 46, 84, 210, 239, 20, 69, 251, 4, 77, 6, 44, 5, 76, 65, + 67, 75, 32, 243, 213, 22, 65, 4, 38, 79, 153, 215, 21, 3, 72, 69, 88, 2, + 139, 215, 21, 67, 2, 173, 244, 20, 2, 32, 69, 14, 160, 166, 16, 3, 49, + 51, 53, 198, 231, 6, 50, 2, 51, 2, 52, 2, 53, 2, 54, 3, 55, 8, 142, 141, + 23, 49, 2, 51, 2, 55, 3, 57, 10, 32, 2, 65, 66, 215, 246, 20, 82, 8, 26, + 85, 215, 245, 20, 32, 6, 33, 6, 76, 65, 84, 73, 79, 78, 7, 11, 32, 4, + 208, 163, 9, 8, 87, 73, 84, 72, 32, 74, 85, 83, 151, 179, 13, 83, 7, 11, + 32, 4, 140, 159, 7, 2, 82, 65, 155, 175, 15, 70, 10, 26, 32, 195, 129, + 22, 69, 8, 86, 80, 188, 175, 18, 5, 66, 69, 86, 69, 82, 204, 80, 3, 83, + 80, 82, 159, 137, 4, 68, 2, 175, 175, 14, 69, 12, 48, 6, 82, 71, 76, 65, + 83, 83, 77, 2, 83, 69, 5, 153, 208, 19, 14, 32, 87, 73, 84, 72, 32, 70, + 76, 79, 87, 73, 78, 71, 32, 9, 11, 32, 6, 88, 8, 87, 73, 84, 72, 32, 71, + 65, 82, 169, 132, 21, 8, 66, 85, 73, 76, 68, 73, 78, 71, 2, 147, 183, 21, + 68, 7, 242, 135, 23, 74, 3, 83, 8, 106, 83, 208, 243, 21, 11, 78, 68, 82, + 69, 68, 32, 80, 79, 73, 78, 84, 148, 11, 2, 71, 71, 139, 136, 1, 84, 2, + 171, 246, 21, 72, 18, 90, 80, 224, 1, 5, 83, 84, 69, 82, 69, 220, 180, + 16, 2, 71, 73, 193, 207, 4, 2, 65, 67, 12, 60, 3, 72, 69, 78, 129, 133, + 4, 6, 79, 68, 73, 65, 83, 84, 11, 34, 32, 82, 65, 227, 167, 19, 45, 4, + 26, 87, 203, 168, 21, 66, 2, 21, 3, 73, 84, 72, 2, 141, 168, 3, 2, 32, + 68, 2, 193, 169, 12, 6, 84, 73, 79, 78, 32, 80, 2, 253, 240, 21, 2, 83, + 73, 202, 5, 160, 1, 3, 67, 69, 32, 152, 1, 2, 68, 69, 222, 24, 77, 214, + 2, 78, 132, 37, 7, 90, 65, 75, 65, 89, 65, 32, 237, 137, 19, 9, 32, 76, + 79, 86, 69, 32, 89, 79, 85, 8, 114, 67, 252, 249, 10, 18, 72, 79, 67, 75, + 69, 89, 32, 83, 84, 73, 67, 75, 32, 65, 78, 68, 32, 80, 155, 179, 1, 83, + 4, 250, 184, 15, 82, 187, 212, 2, 85, 246, 1, 68, 3, 78, 84, 73, 201, 1, + 9, 79, 71, 82, 65, 80, 72, 73, 67, 32, 8, 64, 4, 67, 65, 76, 32, 105, 8, + 70, 73, 67, 65, 84, 73, 79, 78, 6, 32, 2, 84, 79, 175, 255, 21, 87, 5, + 129, 188, 14, 12, 32, 65, 78, 68, 32, 83, 76, 65, 78, 84, 69, 68, 2, 229, + 232, 21, 2, 32, 67, 238, 1, 208, 2, 11, 65, 78, 78, 79, 84, 65, 84, 73, + 79, 78, 32, 242, 3, 67, 72, 2, 68, 69, 248, 5, 5, 78, 85, 77, 66, 69, 22, + 84, 220, 204, 5, 8, 72, 65, 76, 70, 32, 70, 73, 76, 144, 186, 1, 5, 69, + 78, 84, 69, 82, 0, 3, 82, 73, 83, 24, 5, 76, 69, 86, 69, 76, 236, 240, 8, + 5, 86, 65, 82, 73, 65, 158, 175, 4, 70, 230, 46, 73, 131, 222, 1, 83, 32, + 232, 1, 5, 66, 79, 84, 84, 79, 22, 70, 82, 77, 62, 84, 140, 1, 4, 76, 73, + 78, 75, 188, 142, 1, 4, 83, 69, 67, 79, 150, 255, 5, 79, 228, 238, 5, 6, + 82, 69, 86, 69, 82, 83, 148, 147, 9, 5, 72, 69, 65, 86, 69, 165, 39, 3, + 69, 65, 82, 2, 175, 185, 22, 77, 6, 48, 3, 79, 85, 82, 229, 175, 22, 3, + 73, 82, 83, 4, 218, 184, 22, 84, 27, 32, 4, 36, 3, 73, 68, 68, 235, 144, + 22, 65, 2, 211, 253, 12, 76, 8, 34, 72, 46, 87, 131, 226, 7, 79, 4, 222, + 236, 8, 82, 181, 192, 13, 2, 73, 82, 2, 191, 183, 22, 79, 4, 36, 3, 76, + 79, 83, 167, 173, 20, 79, 2, 129, 183, 22, 3, 73, 78, 71, 36, 104, 20, + 83, 67, 82, 73, 80, 84, 73, 79, 78, 32, 67, 72, 65, 82, 65, 67, 84, 69, + 82, 32, 247, 139, 7, 80, 34, 144, 2, 9, 65, 66, 79, 86, 69, 32, 84, 79, + 32, 84, 8, 76, 69, 70, 84, 32, 84, 79, 32, 76, 5, 79, 86, 69, 82, 76, 20, + 2, 83, 85, 202, 186, 14, 82, 152, 153, 5, 8, 70, 85, 76, 76, 32, 83, 85, + 82, 173, 207, 2, 15, 72, 79, 82, 73, 90, 79, 78, 84, 65, 76, 32, 82, 69, + 70, 76, 4, 60, 9, 77, 73, 68, 68, 76, 69, 32, 65, 78, 167, 220, 20, 66, + 2, 247, 205, 20, 68, 4, 180, 166, 21, 10, 77, 73, 68, 68, 76, 69, 32, 65, + 78, 68, 195, 163, 1, 82, 2, 231, 162, 16, 65, 18, 72, 12, 82, 82, 79, 85, + 78, 68, 32, 70, 82, 79, 77, 32, 163, 236, 16, 66, 16, 82, 76, 200, 163, + 11, 3, 85, 80, 80, 202, 182, 9, 66, 222, 155, 1, 65, 143, 82, 82, 6, 186, + 163, 11, 79, 175, 164, 11, 69, 2, 195, 180, 8, 82, 148, 1, 92, 10, 65, + 76, 76, 89, 32, 77, 65, 82, 75, 32, 41, 9, 69, 76, 69, 71, 82, 65, 80, + 72, 32, 10, 138, 132, 21, 70, 70, 84, 203, 83, 79, 138, 1, 140, 1, 11, + 83, 89, 77, 66, 79, 76, 32, 70, 79, 82, 32, 205, 179, 12, 17, 76, 73, 78, + 69, 32, 70, 69, 69, 68, 32, 83, 69, 80, 65, 82, 65, 84, 136, 1, 182, 1, + 65, 58, 68, 200, 2, 5, 72, 79, 85, 82, 32, 214, 1, 74, 28, 4, 70, 69, 66, + 82, 64, 2, 77, 65, 144, 137, 15, 3, 78, 79, 86, 0, 4, 83, 69, 80, 84, 25, + 4, 79, 67, 84, 79, 4, 232, 166, 19, 3, 85, 71, 85, 213, 154, 1, 2, 80, + 82, 64, 44, 3, 65, 89, 32, 217, 141, 15, 2, 69, 67, 62, 66, 84, 130, 177, + 5, 69, 66, 70, 70, 78, 26, 83, 219, 161, 16, 79, 34, 34, 72, 90, 87, 187, + 156, 22, 69, 8, 36, 3, 73, 82, 84, 139, 128, 21, 82, 6, 26, 89, 175, 155, + 21, 69, 5, 247, 194, 21, 45, 24, 26, 69, 243, 235, 22, 79, 22, 36, 3, 78, + 84, 89, 135, 239, 21, 76, 21, 147, 232, 14, 45, 50, 78, 84, 222, 174, 5, + 69, 66, 70, 70, 78, 26, 83, 206, 206, 15, 90, 143, 83, 79, 20, 42, 87, + 186, 176, 5, 72, 175, 234, 16, 69, 14, 26, 69, 159, 234, 22, 79, 12, 36, + 3, 78, 84, 89, 179, 237, 21, 76, 11, 159, 212, 16, 45, 6, 24, 2, 65, 78, + 35, 85, 2, 11, 85, 2, 131, 221, 16, 65, 4, 206, 210, 22, 78, 143, 5, 76, + 4, 218, 198, 22, 82, 171, 34, 89, 68, 40, 6, 65, 71, 69, 32, 79, 70, 83, + 80, 5, 233, 225, 8, 15, 32, 79, 82, 32, 65, 80, 80, 82, 79, 88, 73, 77, + 65, 84, 69, 65, 65, 14, 69, 82, 73, 65, 76, 32, 65, 82, 65, 77, 65, 73, + 67, 32, 62, 64, 7, 78, 85, 77, 66, 69, 82, 32, 234, 18, 76, 239, 249, 18, + 83, 16, 26, 84, 171, 140, 15, 79, 10, 138, 143, 11, 87, 186, 137, 1, 69, + 195, 225, 8, 72, 132, 3, 202, 1, 67, 234, 1, 68, 218, 6, 70, 132, 2, 5, + 72, 73, 66, 73, 84, 156, 1, 15, 80, 85, 84, 32, 83, 89, 77, 66, 79, 76, + 32, 70, 79, 82, 32, 206, 1, 83, 236, 5, 2, 84, 69, 206, 8, 86, 175, 211, + 9, 66, 10, 32, 2, 79, 77, 69, 2, 82, 69, 4, 144, 144, 16, 3, 73, 78, 71, + 129, 216, 2, 5, 80, 76, 69, 84, 69, 6, 36, 3, 65, 83, 69, 151, 160, 22, + 77, 4, 34, 32, 161, 141, 10, 2, 83, 32, 2, 161, 143, 11, 8, 70, 79, 78, + 84, 32, 83, 73, 90, 145, 1, 24, 2, 69, 88, 103, 73, 5, 205, 201, 21, 20, + 32, 80, 79, 73, 78, 84, 73, 78, 71, 32, 65, 84, 32, 84, 72, 69, 32, 86, + 73, 69, 138, 1, 72, 8, 67, 32, 83, 73, 89, 65, 81, 32, 209, 185, 17, 4, + 65, 78, 32, 82, 136, 1, 200, 1, 11, 65, 76, 84, 69, 82, 78, 65, 84, 69, + 32, 76, 2, 76, 28, 9, 70, 82, 65, 67, 84, 73, 79, 78, 32, 100, 7, 78, 85, + 77, 66, 69, 82, 32, 222, 209, 8, 82, 201, 246, 2, 6, 80, 76, 65, 67, 69, + 72, 2, 237, 157, 22, 2, 65, 75, 6, 68, 4, 79, 78, 69, 32, 217, 224, 20, + 7, 84, 72, 82, 69, 69, 32, 81, 4, 178, 222, 20, 72, 43, 81, 122, 212, 1, + 10, 65, 76, 84, 69, 82, 78, 65, 84, 69, 32, 72, 5, 75, 65, 82, 79, 82, 0, + 4, 76, 65, 75, 72, 250, 226, 9, 69, 66, 70, 94, 78, 26, 83, 78, 84, 220, + 243, 4, 8, 80, 82, 69, 70, 73, 88, 69, 68, 167, 41, 79, 6, 26, 84, 175, + 195, 21, 79, 4, 236, 128, 6, 2, 69, 78, 223, 188, 16, 87, 5, 191, 140, + 22, 65, 16, 72, 5, 73, 78, 73, 84, 89, 85, 9, 79, 82, 77, 65, 84, 73, 79, + 78, 32, 5, 45, 9, 32, 78, 69, 71, 65, 84, 69, 68, 32, 2, 237, 134, 8, 4, + 87, 73, 84, 72, 12, 42, 83, 253, 134, 16, 4, 68, 69, 83, 75, 10, 156, + 245, 6, 5, 69, 80, 65, 82, 65, 191, 214, 9, 79, 4, 11, 32, 4, 232, 136, + 22, 15, 65, 82, 65, 66, 73, 67, 32, 70, 79, 82, 77, 32, 83, 72, 65, 1, + 14, 83, 89, 77, 77, 69, 84, 82, 73, 67, 32, 83, 87, 65, 80, 10, 80, 6, + 76, 65, 84, 73, 78, 32, 234, 185, 14, 83, 221, 143, 7, 4, 78, 85, 77, 66, + 6, 64, 6, 67, 65, 80, 73, 84, 65, 0, 4, 83, 77, 65, 76, 27, 76, 2, 21, 3, + 76, 32, 76, 2, 205, 217, 20, 2, 69, 84, 116, 84, 13, 67, 82, 73, 80, 84, + 73, 79, 78, 65, 76, 32, 80, 65, 233, 141, 15, 2, 69, 82, 114, 72, 6, 72, + 76, 65, 86, 73, 32, 225, 1, 7, 82, 84, 72, 73, 65, 78, 32, 54, 48, 7, 76, + 69, 84, 84, 69, 82, 32, 191, 3, 78, 38, 234, 132, 10, 84, 226, 118, 65, + 22, 68, 34, 76, 22, 77, 50, 87, 238, 150, 4, 71, 90, 90, 34, 83, 66, 89, + 154, 193, 1, 72, 234, 5, 75, 130, 76, 66, 190, 173, 4, 78, 199, 105, 80, + 60, 22, 76, 251, 1, 78, 44, 11, 69, 44, 29, 5, 84, 84, 69, 82, 32, 44, + 250, 130, 10, 84, 246, 118, 68, 34, 76, 50, 81, 206, 194, 1, 82, 134, + 212, 2, 65, 50, 71, 90, 90, 34, 83, 66, 89, 154, 193, 1, 72, 234, 5, 75, + 130, 76, 66, 190, 173, 4, 78, 254, 1, 87, 202, 103, 80, 171, 4, 77, 16, + 33, 6, 85, 77, 66, 69, 82, 32, 16, 246, 249, 10, 84, 202, 253, 3, 79, + 171, 243, 2, 70, 50, 36, 4, 71, 82, 65, 76, 179, 3, 82, 23, 11, 32, 20, + 58, 65, 140, 1, 5, 87, 73, 84, 72, 32, 219, 181, 20, 69, 4, 96, 6, 86, + 69, 82, 65, 71, 69, 173, 237, 15, 12, 82, 79, 85, 78, 68, 32, 65, 32, 80, + 79, 73, 78, 2, 209, 238, 15, 5, 32, 87, 73, 84, 72, 14, 160, 1, 3, 84, + 73, 77, 20, 2, 85, 78, 200, 203, 6, 16, 76, 69, 70, 84, 87, 65, 82, 68, + 83, 32, 65, 82, 82, 79, 87, 32, 182, 231, 12, 73, 198, 1, 79, 251, 49, + 68, 2, 191, 180, 19, 69, 4, 202, 180, 19, 68, 203, 201, 2, 73, 28, 94, + 76, 232, 1, 7, 83, 69, 67, 84, 73, 79, 78, 202, 6, 82, 144, 200, 11, 2, + 67, 65, 43, 73, 8, 164, 1, 17, 73, 78, 69, 65, 82, 32, 65, 78, 78, 79, + 84, 65, 84, 73, 79, 78, 32, 201, 200, 4, 17, 79, 67, 75, 69, 68, 32, 70, + 69, 77, 65, 76, 69, 32, 65, 78, 68, 32, 6, 232, 130, 8, 3, 65, 78, 67, + 170, 128, 8, 84, 199, 175, 3, 83, 15, 11, 32, 12, 168, 1, 6, 65, 66, 79, + 86, 69, 32, 64, 5, 87, 73, 84, 72, 32, 133, 174, 19, 22, 66, 69, 83, 73, + 68, 69, 32, 65, 78, 68, 32, 74, 79, 73, 78, 69, 68, 32, 87, 73, 84, 72, + 4, 244, 174, 19, 9, 66, 65, 82, 32, 65, 66, 79, 86, 69, 23, 85, 6, 158, + 143, 4, 76, 190, 160, 15, 79, 139, 201, 2, 68, 36, 56, 2, 69, 82, 245, 4, + 7, 73, 83, 73, 66, 76, 69, 32, 30, 48, 3, 83, 69, 32, 153, 2, 4, 84, 69, + 68, 32, 12, 180, 1, 5, 67, 72, 69, 67, 75, 68, 24, 68, 79, 87, 78, 87, + 65, 82, 68, 83, 32, 65, 82, 82, 79, 87, 32, 87, 73, 84, 72, 32, 84, 73, + 80, 166, 195, 19, 87, 230, 18, 77, 183, 147, 1, 66, 4, 196, 213, 19, 8, + 69, 82, 32, 66, 79, 65, 82, 68, 195, 175, 2, 32, 2, 229, 237, 19, 2, 32, + 76, 18, 144, 1, 6, 73, 78, 84, 69, 82, 82, 22, 76, 150, 195, 11, 80, 170, + 169, 4, 69, 148, 183, 1, 2, 79, 72, 136, 131, 2, 4, 85, 78, 68, 69, 163, + 83, 81, 2, 151, 179, 4, 79, 6, 60, 9, 79, 87, 32, 75, 65, 86, 89, 75, 65, + 187, 196, 6, 65, 5, 225, 204, 17, 11, 32, 87, 73, 84, 72, 32, 75, 65, 86, + 89, 75, 6, 38, 84, 138, 230, 18, 80, 143, 68, 83, 2, 207, 238, 15, 73, + 218, 1, 94, 65, 134, 21, 69, 62, 79, 42, 85, 165, 146, 11, 10, 73, 71, + 83, 65, 87, 32, 80, 85, 90, 90, 202, 1, 120, 5, 67, 75, 45, 79, 45, 32, + 7, 80, 65, 78, 69, 83, 69, 32, 184, 2, 7, 86, 65, 78, 69, 83, 69, 32, + 183, 190, 22, 82, 2, 233, 226, 17, 3, 76, 65, 78, 16, 246, 1, 67, 18, 80, + 128, 153, 1, 10, 73, 78, 68, 85, 83, 84, 82, 73, 65, 76, 140, 196, 3, 3, + 66, 65, 78, 250, 171, 3, 68, 244, 171, 12, 3, 71, 79, 66, 204, 105, 2, + 79, 71, 181, 98, 16, 83, 89, 77, 66, 79, 76, 32, 70, 79, 82, 32, 66, 69, + 71, 73, 78, 2, 199, 32, 65, 2, 197, 209, 12, 7, 79, 83, 84, 32, 79, 70, + 70, 182, 1, 172, 2, 15, 67, 79, 78, 83, 79, 78, 65, 78, 84, 32, 83, 73, + 71, 78, 32, 76, 2, 76, 69, 40, 4, 82, 73, 71, 72, 224, 6, 2, 80, 65, 176, + 3, 14, 84, 85, 82, 78, 69, 68, 32, 80, 65, 68, 65, 32, 80, 73, 88, 5, 83, + 73, 71, 78, 32, 140, 1, 11, 86, 79, 87, 69, 76, 32, 83, 73, 71, 78, 32, + 255, 192, 20, 68, 6, 52, 2, 75, 69, 228, 129, 16, 2, 80, 69, 175, 5, 67, + 2, 187, 134, 22, 82, 96, 38, 70, 65, 5, 84, 84, 69, 82, 32, 2, 41, 8, 84, + 32, 82, 69, 82, 69, 78, 71, 2, 171, 243, 20, 71, 94, 230, 1, 68, 26, 73, + 48, 2, 75, 65, 66, 78, 130, 1, 66, 2, 67, 2, 71, 16, 2, 80, 65, 56, 2, + 82, 65, 32, 2, 83, 65, 42, 84, 74, 74, 186, 174, 20, 65, 150, 132, 2, 72, + 2, 76, 2, 77, 2, 87, 2, 89, 186, 2, 69, 2, 79, 3, 85, 8, 222, 3, 68, 15, + 65, 7, 164, 167, 5, 3, 32, 75, 65, 167, 145, 17, 73, 7, 11, 32, 4, 22, + 83, 215, 2, 77, 2, 145, 137, 20, 2, 65, 83, 14, 36, 2, 71, 65, 90, 89, + 167, 1, 65, 7, 33, 6, 32, 76, 69, 76, 69, 84, 5, 29, 5, 32, 82, 65, 83, + 87, 2, 135, 192, 5, 65, 4, 163, 1, 65, 7, 11, 32, 4, 154, 1, 77, 129, + 178, 22, 3, 67, 69, 82, 5, 145, 133, 16, 3, 32, 65, 71, 7, 17, 2, 32, 77, + 4, 70, 85, 71, 65, 8, 18, 65, 55, 84, 5, 17, 2, 32, 77, 2, 11, 85, 2, + 147, 144, 22, 82, 4, 11, 65, 5, 11, 32, 2, 11, 77, 2, 11, 65, 2, 11, 72, + 2, 233, 232, 16, 2, 65, 80, 28, 40, 3, 68, 65, 32, 165, 3, 2, 78, 71, 24, + 174, 1, 65, 90, 76, 86, 80, 168, 240, 6, 10, 84, 73, 82, 84, 65, 32, 84, + 85, 77, 69, 138, 219, 11, 87, 128, 149, 2, 7, 73, 83, 69, 78, 45, 73, 83, + 153, 206, 1, 3, 77, 65, 68, 6, 44, 3, 68, 69, 71, 205, 161, 21, 2, 78, + 68, 5, 11, 32, 2, 181, 236, 21, 2, 65, 68, 6, 38, 85, 141, 175, 22, 3, + 73, 78, 71, 4, 184, 243, 17, 2, 78, 71, 211, 197, 3, 72, 4, 38, 73, 149, + 236, 17, 3, 65, 78, 71, 2, 217, 253, 15, 3, 83, 69, 76, 4, 208, 214, 12, + 5, 82, 65, 78, 71, 75, 171, 138, 9, 75, 10, 104, 5, 67, 69, 67, 65, 75, + 204, 165, 5, 5, 80, 65, 78, 89, 65, 176, 2, 3, 87, 73, 71, 239, 212, 10, + 76, 5, 233, 218, 17, 3, 32, 84, 69, 18, 116, 4, 83, 85, 75, 85, 42, 84, + 64, 4, 87, 85, 76, 85, 182, 251, 15, 80, 165, 210, 1, 7, 68, 73, 82, 71, + 65, 32, 77, 5, 221, 180, 21, 5, 32, 77, 69, 78, 68, 6, 26, 65, 243, 252, + 15, 79, 4, 218, 252, 15, 82, 139, 224, 5, 76, 5, 25, 4, 32, 77, 69, 76, + 2, 131, 170, 22, 73, 4, 36, 3, 76, 76, 89, 207, 254, 18, 65, 2, 155, 238, + 18, 70, 4, 228, 253, 20, 2, 89, 83, 147, 95, 73, 6, 148, 134, 14, 2, 71, + 71, 138, 230, 4, 80, 147, 161, 3, 78, 192, 24, 74, 65, 178, 78, 69, 202, + 1, 72, 178, 50, 73, 178, 2, 78, 50, 79, 111, 82, 198, 10, 200, 1, 5, 73, + 84, 72, 73, 32, 230, 4, 78, 168, 45, 6, 84, 65, 75, 65, 78, 65, 208, 13, + 3, 87, 73, 32, 240, 8, 7, 89, 65, 72, 32, 76, 73, 32, 252, 163, 4, 6, 75, + 84, 79, 86, 73, 75, 219, 143, 17, 65, 136, 1, 204, 1, 7, 76, 69, 84, 84, + 69, 82, 32, 174, 2, 83, 234, 115, 68, 156, 206, 3, 2, 86, 79, 168, 136, + 3, 11, 78, 85, 77, 66, 69, 82, 32, 83, 73, 71, 78, 154, 155, 9, 65, 197, + 213, 1, 6, 69, 78, 85, 77, 69, 82, 90, 210, 1, 68, 210, 189, 18, 65, 82, + 84, 230, 24, 85, 210, 200, 1, 73, 158, 190, 1, 78, 46, 83, 82, 66, 2, 67, + 2, 71, 2, 74, 2, 75, 2, 80, 2, 82, 254, 68, 72, 2, 76, 2, 77, 2, 86, 2, + 89, 186, 2, 69, 3, 79, 10, 38, 68, 194, 163, 22, 72, 187, 2, 65, 6, 186, + 174, 20, 68, 134, 245, 1, 72, 187, 2, 65, 12, 40, 4, 73, 71, 78, 32, 167, + 236, 10, 69, 10, 242, 190, 18, 67, 98, 78, 222, 160, 3, 65, 239, 1, 86, + 230, 4, 42, 71, 221, 39, 5, 78, 65, 68, 65, 32, 174, 3, 76, 11, 88, 73, + 32, 82, 65, 68, 73, 67, 65, 76, 32, 153, 227, 19, 2, 65, 82, 172, 3, 130, + 2, 65, 94, 66, 230, 2, 67, 150, 2, 68, 158, 3, 69, 198, 1, 70, 138, 2, + 71, 146, 1, 72, 210, 2, 73, 76, 2, 74, 65, 34, 75, 30, 76, 230, 1, 77, + 254, 1, 78, 62, 79, 102, 80, 110, 82, 166, 1, 83, 210, 6, 84, 226, 2, 86, + 50, 87, 210, 2, 89, 131, 244, 20, 85, 10, 56, 2, 82, 82, 238, 245, 20, + 71, 158, 101, 78, 195, 47, 88, 4, 138, 163, 21, 79, 207, 1, 73, 34, 58, + 65, 38, 73, 46, 76, 54, 79, 102, 82, 167, 215, 20, 69, 4, 190, 180, 5, + 77, 143, 180, 13, 68, 6, 206, 233, 20, 84, 186, 112, 82, 151, 70, 71, 6, + 138, 254, 18, 79, 154, 243, 1, 65, 251, 151, 1, 85, 10, 62, 76, 210, 130, + 22, 65, 218, 5, 78, 142, 5, 68, 203, 17, 87, 2, 173, 193, 3, 4, 84, 32, + 79, 70, 6, 42, 73, 246, 201, 9, 65, 159, 239, 10, 85, 2, 151, 189, 13, + 83, 28, 58, 65, 70, 76, 74, 79, 190, 135, 10, 72, 163, 171, 10, 73, 6, + 38, 85, 138, 129, 22, 82, 219, 5, 86, 2, 165, 249, 20, 2, 76, 68, 8, 42, + 65, 206, 151, 7, 73, 171, 241, 13, 79, 4, 234, 156, 22, 78, 3, 87, 10, + 214, 250, 20, 82, 204, 1, 2, 77, 80, 206, 98, 86, 134, 5, 76, 223, 56, + 87, 34, 38, 69, 38, 73, 98, 79, 195, 1, 82, 4, 214, 156, 20, 65, 183, + 198, 1, 69, 8, 38, 83, 158, 190, 13, 86, 175, 2, 80, 4, 200, 220, 18, 5, + 84, 73, 78, 71, 85, 199, 190, 3, 72, 16, 94, 84, 76, 3, 85, 66, 76, 214, + 191, 12, 87, 172, 137, 9, 2, 32, 78, 222, 23, 79, 211, 56, 71, 7, 25, 4, + 84, 69, 68, 32, 4, 184, 148, 7, 3, 67, 76, 73, 135, 194, 14, 84, 2, 171, + 170, 3, 69, 6, 162, 226, 20, 65, 158, 166, 1, 85, 219, 16, 89, 20, 106, + 65, 38, 78, 32, 3, 86, 69, 78, 216, 214, 8, 6, 77, 66, 82, 79, 73, 68, + 158, 150, 13, 73, 243, 19, 89, 6, 202, 152, 16, 82, 179, 255, 5, 84, 4, + 158, 25, 67, 219, 192, 21, 84, 5, 203, 198, 21, 73, 28, 74, 65, 50, 73, + 62, 76, 38, 82, 150, 20, 69, 138, 177, 21, 79, 223, 23, 85, 6, 206, 188, + 13, 84, 182, 195, 8, 67, 131, 22, 78, 8, 146, 177, 12, 69, 222, 186, 9, + 71, 230, 19, 82, 199, 21, 83, 4, 190, 209, 20, 85, 175, 196, 1, 89, 4, + 220, 232, 20, 2, 65, 71, 151, 172, 1, 79, 14, 58, 79, 52, 2, 82, 65, 218, + 204, 18, 72, 171, 131, 2, 65, 7, 202, 206, 21, 76, 229, 34, 5, 32, 83, + 76, 79, 87, 4, 214, 196, 21, 73, 135, 18, 83, 22, 58, 65, 142, 1, 69, 60, + 5, 73, 68, 73, 78, 71, 19, 79, 8, 38, 76, 150, 205, 21, 78, 199, 13, 73, + 4, 34, 70, 177, 252, 20, 2, 66, 69, 2, 41, 8, 32, 84, 82, 69, 69, 32, 84, + 82, 2, 255, 211, 18, 85, 6, 26, 65, 159, 146, 22, 77, 4, 250, 245, 21, + 82, 175, 28, 68, 2, 175, 19, 32, 6, 26, 82, 199, 142, 22, 79, 4, 134, + 251, 21, 83, 215, 22, 78, 6, 26, 78, 207, 250, 21, 67, 4, 26, 83, 247, + 143, 22, 67, 2, 171, 130, 21, 69, 4, 154, 250, 21, 68, 215, 22, 82, 2, + 253, 140, 5, 2, 78, 73, 22, 46, 65, 34, 69, 78, 73, 41, 3, 79, 78, 71, 4, + 174, 249, 21, 77, 191, 19, 67, 8, 38, 65, 238, 209, 21, 71, 187, 58, 69, + 4, 178, 181, 13, 84, 139, 218, 8, 70, 6, 194, 248, 21, 70, 2, 78, 215, + 22, 68, 5, 209, 146, 11, 3, 32, 83, 84, 22, 42, 69, 34, 73, 46, 79, 135, + 190, 21, 65, 4, 194, 190, 21, 76, 183, 51, 65, 4, 156, 185, 11, 2, 78, + 73, 203, 248, 8, 76, 12, 34, 82, 34, 85, 195, 189, 21, 79, 4, 138, 235, + 20, 84, 179, 81, 78, 6, 26, 78, 235, 139, 22, 84, 4, 198, 225, 20, 84, + 179, 171, 1, 68, 6, 26, 79, 143, 240, 21, 69, 4, 226, 245, 21, 83, 215, + 22, 84, 10, 40, 2, 78, 69, 22, 80, 199, 197, 21, 76, 5, 139, 247, 5, 83, + 4, 170, 132, 10, 80, 215, 173, 2, 69, 10, 54, 82, 242, 240, 20, 76, 166, + 1, 79, 151, 152, 1, 73, 4, 152, 144, 12, 2, 73, 86, 229, 218, 6, 2, 79, + 70, 18, 62, 65, 42, 73, 214, 255, 9, 79, 186, 186, 11, 85, 195, 9, 69, 6, + 178, 186, 21, 73, 214, 79, 80, 3, 84, 6, 232, 175, 12, 3, 71, 72, 84, + 150, 156, 9, 86, 143, 39, 67, 74, 170, 1, 65, 86, 67, 46, 69, 62, 72, + 166, 1, 73, 46, 76, 62, 80, 106, 84, 234, 159, 17, 87, 182, 145, 1, 78, + 190, 50, 79, 182, 155, 1, 77, 134, 100, 81, 254, 32, 75, 235, 47, 85, 6, + 192, 168, 3, 9, 67, 82, 73, 70, 73, 67, 73, 65, 76, 138, 195, 18, 76, + 175, 28, 89, 4, 150, 198, 10, 82, 229, 186, 5, 2, 72, 79, 8, 242, 203, + 20, 67, 234, 49, 65, 146, 8, 76, 143, 129, 1, 69, 10, 18, 69, 39, 79, 4, + 138, 253, 20, 76, 147, 137, 1, 69, 6, 40, 4, 82, 84, 32, 84, 175, 233, + 21, 79, 4, 222, 190, 15, 72, 137, 200, 4, 7, 65, 73, 76, 69, 68, 32, 66, + 4, 148, 162, 17, 2, 67, 75, 235, 223, 4, 76, 6, 26, 65, 227, 199, 21, 73, + 4, 250, 237, 21, 86, 199, 21, 83, 10, 50, 69, 34, 73, 178, 177, 18, 82, + 207, 130, 3, 79, 4, 170, 203, 21, 65, 171, 22, 69, 2, 163, 231, 21, 82, + 12, 34, 69, 34, 79, 167, 245, 20, 65, 4, 202, 242, 21, 65, 219, 16, 80, + 6, 26, 80, 151, 236, 21, 78, 5, 239, 177, 21, 80, 30, 82, 65, 98, 73, 34, + 79, 38, 82, 52, 2, 85, 82, 32, 2, 87, 79, 183, 176, 21, 69, 6, 38, 78, + 182, 224, 20, 66, 139, 24, 76, 2, 33, 6, 78, 69, 68, 32, 76, 69, 2, 159, + 167, 13, 65, 4, 190, 195, 21, 71, 143, 39, 76, 4, 150, 160, 18, 78, 231, + 225, 1, 79, 6, 214, 159, 16, 73, 186, 178, 4, 65, 251, 151, 1, 69, 4, + 242, 184, 20, 66, 147, 38, 84, 5, 215, 214, 18, 32, 4, 170, 157, 12, 65, + 129, 136, 5, 3, 73, 76, 76, 26, 58, 65, 110, 69, 42, 72, 32, 2, 73, 78, + 30, 79, 39, 82, 6, 32, 2, 76, 75, 135, 193, 21, 84, 5, 11, 32, 2, 11, 69, + 2, 17, 2, 78, 67, 2, 201, 158, 17, 2, 76, 79, 4, 184, 174, 21, 2, 65, 80, + 183, 51, 83, 4, 198, 185, 20, 73, 223, 48, 69, 4, 210, 253, 21, 68, 3, + 69, 4, 130, 182, 20, 77, 159, 196, 1, 82, 4, 166, 172, 21, 79, 227, 80, + 65, 2, 197, 228, 19, 2, 69, 76, 184, 1, 92, 2, 76, 69, 148, 2, 5, 83, 73, + 71, 78, 32, 238, 249, 16, 65, 174, 9, 86, 175, 136, 3, 68, 110, 44, 5, + 84, 84, 69, 82, 32, 235, 185, 21, 78, 108, 214, 128, 17, 76, 38, 78, 174, + 90, 82, 206, 55, 65, 38, 68, 46, 84, 46, 86, 186, 24, 85, 158, 144, 1, + 79, 182, 56, 73, 202, 190, 1, 83, 82, 66, 2, 67, 2, 71, 2, 74, 2, 75, 2, + 80, 162, 7, 69, 222, 61, 70, 2, 72, 2, 77, 3, 89, 22, 94, 67, 138, 1, 83, + 138, 145, 18, 65, 170, 1, 78, 230, 179, 1, 74, 150, 3, 85, 211, 235, 1, + 86, 4, 100, 19, 79, 77, 66, 73, 78, 73, 78, 71, 32, 65, 78, 85, 83, 86, + 65, 82, 65, 32, 65, 255, 145, 18, 65, 2, 185, 131, 19, 3, 66, 79, 86, 4, + 244, 135, 12, 6, 80, 65, 67, 73, 78, 71, 155, 249, 4, 73, 162, 2, 62, 32, + 173, 11, 10, 45, 72, 73, 82, 65, 71, 65, 78, 65, 32, 154, 2, 140, 1, 7, + 76, 69, 84, 84, 69, 82, 32, 242, 9, 86, 236, 159, 18, 10, 68, 73, 71, 82, + 65, 80, 72, 32, 75, 79, 234, 175, 1, 73, 247, 138, 1, 77, 146, 2, 186, 1, + 65, 178, 1, 66, 106, 77, 186, 2, 78, 54, 83, 226, 1, 68, 2, 71, 2, 72, 2, + 75, 2, 80, 2, 82, 2, 84, 2, 86, 2, 90, 126, 87, 46, 89, 154, 236, 21, 69, + 2, 73, 2, 79, 3, 85, 19, 60, 4, 73, 78, 85, 32, 45, 7, 82, 67, 72, 65, + 73, 67, 32, 8, 130, 7, 84, 142, 214, 21, 67, 215, 22, 80, 8, 38, 89, 170, + 206, 21, 87, 235, 36, 69, 4, 142, 243, 21, 69, 3, 73, 20, 50, 73, 194, + 242, 21, 65, 2, 69, 2, 79, 3, 85, 13, 253, 4, 9, 68, 65, 75, 85, 79, 78, + 32, 78, 71, 36, 50, 73, 218, 241, 21, 65, 2, 69, 2, 79, 3, 85, 29, 29, 5, + 78, 78, 65, 78, 32, 26, 96, 15, 78, 65, 83, 65, 76, 73, 90, 69, 68, 32, + 84, 79, 78, 69, 45, 69, 5, 84, 79, 78, 69, 45, 14, 210, 240, 21, 49, 2, + 50, 2, 51, 2, 52, 2, 53, 2, 55, 3, 56, 12, 142, 240, 21, 50, 2, 51, 2, + 52, 2, 53, 2, 55, 3, 56, 13, 210, 239, 21, 65, 2, 69, 2, 73, 2, 79, 3, + 85, 76, 76, 5, 77, 65, 76, 76, 32, 210, 238, 21, 65, 2, 69, 2, 73, 2, 79, + 3, 85, 66, 142, 1, 72, 2, 82, 54, 75, 46, 84, 30, 87, 46, 89, 254, 156, + 18, 78, 242, 142, 3, 83, 198, 27, 77, 234, 36, 65, 2, 69, 2, 73, 2, 79, + 3, 85, 10, 190, 237, 21, 65, 2, 69, 2, 73, 2, 79, 3, 85, 8, 138, 237, 21, + 65, 2, 69, 2, 79, 3, 85, 4, 222, 236, 21, 79, 3, 85, 8, 194, 236, 21, 65, + 2, 69, 2, 73, 3, 79, 6, 150, 236, 21, 65, 2, 79, 3, 85, 2, 189, 207, 19, + 5, 79, 73, 67, 69, 68, 8, 52, 5, 68, 79, 85, 66, 76, 22, 80, 38, 83, 35, + 86, 2, 251, 216, 7, 69, 2, 89, 6, 82, 79, 76, 79, 78, 71, 2, 29, 5, 69, + 77, 73, 45, 86, 2, 21, 3, 79, 73, 67, 2, 33, 6, 69, 68, 32, 83, 79, 85, + 2, 239, 157, 21, 78, 172, 1, 228, 1, 7, 76, 69, 84, 84, 69, 82, 32, 132, + 2, 12, 80, 85, 78, 67, 84, 85, 65, 84, 73, 79, 78, 32, 148, 3, 5, 83, 73, + 71, 78, 32, 92, 11, 86, 79, 87, 69, 76, 32, 83, 73, 71, 78, 32, 178, 236, + 11, 68, 205, 183, 9, 3, 67, 79, 78, 94, 230, 1, 65, 214, 128, 4, 74, 154, + 253, 13, 68, 46, 84, 146, 4, 86, 214, 20, 85, 210, 200, 1, 73, 158, 190, + 1, 78, 46, 83, 82, 66, 2, 67, 2, 71, 2, 75, 2, 80, 254, 68, 72, 2, 76, 2, + 77, 2, 82, 2, 87, 2, 89, 186, 2, 69, 3, 79, 7, 150, 230, 21, 65, 3, 73, + 22, 122, 67, 90, 68, 58, 70, 54, 83, 20, 12, 65, 76, 84, 69, 82, 78, 65, + 84, 69, 32, 83, 69, 149, 210, 20, 4, 84, 82, 73, 80, 4, 56, 8, 76, 79, + 83, 73, 78, 71, 32, 83, 203, 149, 20, 73, 2, 141, 219, 20, 2, 80, 73, 4, + 11, 79, 4, 132, 211, 20, 2, 85, 66, 151, 145, 1, 84, 4, 204, 148, 20, 5, + 73, 76, 76, 69, 68, 175, 54, 76, 6, 18, 69, 23, 80, 2, 203, 196, 10, 67, + 4, 156, 241, 3, 2, 65, 67, 195, 232, 16, 73, 10, 192, 238, 5, 2, 82, 69, + 166, 204, 1, 75, 218, 193, 10, 67, 226, 182, 1, 86, 223, 234, 1, 65, 20, + 66, 65, 134, 255, 3, 86, 170, 147, 14, 69, 2, 85, 211, 200, 1, 73, 6, + 244, 152, 16, 8, 76, 84, 69, 82, 78, 65, 84, 69, 210, 200, 5, 65, 3, 73, + 96, 148, 1, 7, 76, 69, 84, 84, 69, 82, 32, 204, 1, 5, 83, 73, 71, 78, 32, + 44, 5, 84, 79, 78, 69, 32, 92, 6, 86, 79, 87, 69, 76, 32, 247, 238, 19, + 68, 56, 154, 206, 16, 72, 190, 173, 1, 79, 230, 236, 1, 78, 246, 175, 1, + 75, 2, 80, 2, 83, 2, 84, 254, 68, 66, 2, 67, 2, 68, 2, 71, 2, 76, 2, 77, + 2, 82, 2, 86, 2, 87, 2, 89, 2, 90, 186, 2, 65, 3, 73, 4, 242, 204, 4, 67, + 201, 142, 17, 2, 83, 72, 6, 36, 5, 67, 65, 76, 89, 65, 23, 80, 5, 17, 2, + 32, 80, 2, 197, 155, 17, 3, 76, 79, 80, 10, 250, 156, 21, 69, 2, 85, 151, + 64, 79, 34, 24, 2, 76, 86, 23, 89, 2, 175, 230, 19, 73, 33, 52, 5, 66, + 79, 65, 82, 68, 37, 4, 67, 65, 80, 32, 5, 213, 172, 18, 4, 32, 65, 78, + 68, 26, 142, 197, 16, 78, 146, 134, 3, 65, 162, 34, 68, 171, 29, 84, 186, + 13, 202, 1, 65, 212, 9, 18, 73, 84, 65, 78, 32, 83, 77, 65, 76, 76, 32, + 83, 67, 82, 73, 80, 84, 32, 184, 3, 4, 77, 69, 82, 32, 204, 25, 5, 79, + 74, 75, 73, 32, 145, 6, 8, 85, 68, 65, 87, 65, 68, 73, 32, 138, 1, 56, 8, + 82, 79, 83, 72, 84, 72, 73, 32, 143, 180, 21, 78, 136, 1, 220, 1, 4, 68, + 73, 71, 73, 20, 7, 76, 69, 84, 84, 69, 82, 32, 144, 2, 7, 78, 85, 77, 66, + 69, 82, 32, 36, 12, 80, 85, 78, 67, 84, 85, 65, 84, 73, 79, 78, 32, 136, + 2, 5, 83, 73, 71, 78, 32, 198, 1, 86, 207, 155, 8, 70, 8, 203, 193, 15, + 84, 74, 182, 1, 75, 42, 84, 150, 229, 6, 78, 250, 135, 11, 68, 170, 160, + 3, 83, 82, 66, 2, 67, 2, 71, 2, 80, 2, 86, 254, 68, 72, 2, 74, 2, 76, 2, + 77, 2, 82, 2, 89, 2, 90, 187, 2, 65, 6, 166, 211, 21, 72, 2, 75, 187, 2, + 65, 12, 182, 237, 17, 84, 202, 229, 3, 72, 187, 2, 65, 8, 146, 149, 14, + 84, 159, 151, 2, 79, 18, 70, 67, 74, 68, 66, 76, 36, 5, 77, 65, 78, 71, + 65, 175, 131, 20, 83, 4, 26, 82, 135, 133, 20, 73, 2, 177, 132, 19, 6, + 69, 83, 67, 69, 78, 84, 6, 26, 79, 191, 254, 11, 65, 4, 134, 254, 11, 85, + 179, 213, 9, 84, 4, 246, 188, 6, 79, 199, 168, 7, 73, 2, 179, 153, 20, + 76, 12, 72, 2, 66, 65, 22, 67, 20, 2, 68, 79, 162, 162, 19, 86, 223, 234, + 1, 65, 2, 155, 213, 20, 82, 2, 255, 243, 5, 65, 4, 56, 8, 85, 66, 76, 69, + 32, 82, 73, 78, 203, 170, 19, 84, 2, 199, 170, 19, 71, 14, 44, 5, 79, 87, + 69, 76, 32, 243, 158, 19, 73, 12, 44, 5, 83, 73, 71, 78, 32, 203, 142, + 21, 76, 10, 242, 237, 3, 86, 198, 226, 17, 69, 2, 73, 2, 79, 3, 85, 174, + 7, 72, 12, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 56, 175, 167, 7, + 70, 172, 7, 22, 66, 147, 1, 67, 128, 4, 146, 214, 7, 48, 2, 49, 2, 50, 2, + 51, 2, 52, 2, 53, 2, 54, 2, 55, 2, 56, 2, 57, 2, 65, 2, 66, 2, 67, 2, 68, + 2, 69, 3, 70, 172, 3, 122, 68, 138, 212, 7, 48, 2, 49, 2, 50, 2, 51, 2, + 52, 2, 53, 2, 54, 2, 55, 2, 56, 2, 57, 2, 65, 2, 66, 3, 67, 12, 254, 204, + 21, 48, 2, 49, 2, 50, 2, 51, 2, 52, 3, 53, 246, 2, 202, 1, 67, 240, 2, + 18, 73, 78, 68, 69, 80, 69, 78, 68, 69, 78, 84, 32, 86, 79, 87, 69, 76, + 32, 220, 2, 7, 76, 69, 84, 84, 69, 82, 32, 254, 2, 83, 208, 12, 6, 86, + 79, 87, 69, 76, 32, 195, 199, 19, 68, 70, 176, 1, 20, 79, 78, 83, 79, 78, + 65, 78, 84, 32, 83, 73, 71, 78, 32, 67, 79, 69, 78, 71, 32, 233, 232, 16, + 17, 85, 82, 82, 69, 78, 67, 89, 32, 83, 89, 77, 66, 79, 76, 32, 82, 73, + 68, 138, 1, 78, 154, 4, 67, 2, 75, 90, 80, 74, 84, 54, 68, 2, 76, 198, + 250, 20, 83, 146, 41, 77, 2, 82, 2, 86, 2, 89, 190, 28, 66, 3, 72, 8, + 190, 169, 21, 71, 2, 89, 246, 30, 65, 3, 79, 42, 82, 81, 196, 1, 11, 83, + 73, 71, 78, 32, 67, 79, 69, 78, 71, 32, 50, 76, 3, 82, 26, 82, 65, 44, 6, + 79, 79, 32, 84, 89, 80, 34, 85, 198, 191, 19, 73, 207, 134, 2, 69, 8, + 218, 198, 21, 65, 2, 73, 2, 81, 3, 85, 4, 11, 69, 4, 159, 231, 9, 32, 9, + 214, 152, 7, 85, 187, 173, 14, 75, 8, 18, 81, 31, 82, 4, 214, 197, 21, + 69, 3, 85, 4, 195, 210, 17, 89, 70, 138, 1, 67, 2, 75, 42, 78, 50, 80, + 30, 83, 46, 84, 54, 68, 2, 76, 214, 163, 21, 77, 2, 82, 2, 86, 2, 89, + 190, 28, 66, 2, 72, 3, 81, 8, 210, 1, 72, 202, 194, 21, 65, 3, 79, 8, + 254, 164, 21, 71, 2, 78, 2, 89, 247, 30, 79, 6, 122, 72, 203, 194, 21, + 79, 6, 178, 164, 21, 83, 190, 28, 72, 187, 2, 65, 12, 50, 72, 0, 2, 84, + 72, 202, 194, 21, 65, 3, 79, 4, 198, 194, 21, 65, 3, 79, 130, 1, 60, 4, + 73, 71, 78, 32, 221, 6, 6, 89, 77, 66, 79, 76, 32, 46, 202, 2, 65, 104, + 10, 83, 65, 77, 89, 79, 75, 32, 83, 65, 78, 22, 66, 118, 67, 86, 75, 74, + 82, 54, 84, 244, 191, 4, 3, 76, 69, 75, 244, 10, 6, 80, 72, 78, 65, 69, + 75, 180, 204, 11, 11, 89, 85, 85, 75, 65, 76, 69, 65, 80, 73, 78, 152, + 97, 3, 78, 73, 75, 244, 251, 2, 9, 77, 85, 85, 83, 73, 75, 65, 84, 79, + 249, 13, 4, 86, 73, 82, 73, 6, 100, 9, 86, 65, 75, 82, 65, 72, 65, 83, + 65, 152, 189, 17, 4, 84, 84, 72, 65, 153, 220, 3, 2, 72, 83, 2, 215, 187, + 21, 78, 8, 38, 65, 209, 180, 20, 3, 69, 89, 89, 6, 174, 6, 84, 216, 1, 2, + 78, 84, 189, 238, 19, 6, 82, 73, 89, 79, 79, 83, 4, 224, 244, 6, 12, 65, + 77, 78, 85, 67, 32, 80, 73, 73, 32, 75, 85, 155, 140, 12, 79, 6, 188, + 163, 11, 2, 65, 75, 230, 209, 8, 72, 245, 77, 4, 79, 79, 77, 85, 4, 130, + 163, 11, 79, 133, 208, 5, 4, 69, 65, 72, 77, 4, 136, 168, 20, 8, 79, 65, + 78, 68, 65, 75, 72, 73, 253, 2, 4, 82, 73, 73, 83, 84, 128, 1, 3, 68, 65, + 80, 92, 10, 76, 69, 75, 32, 65, 84, 84, 65, 75, 32, 182, 1, 80, 72, 5, + 84, 85, 84, 69, 89, 78, 66, 47, 77, 24, 22, 45, 223, 3, 32, 20, 30, 80, + 238, 2, 66, 47, 77, 8, 138, 3, 73, 37, 3, 82, 65, 77, 20, 50, 80, 98, 66, + 130, 221, 10, 77, 187, 139, 10, 83, 12, 36, 3, 82, 65, 77, 251, 164, 21, + 73, 11, 11, 45, 8, 42, 66, 130, 221, 10, 77, 255, 158, 8, 80, 4, 182, + 232, 20, 85, 139, 60, 69, 26, 44, 2, 65, 84, 44, 3, 82, 65, 77, 91, 73, + 2, 21, 3, 72, 65, 77, 2, 223, 237, 15, 65, 20, 18, 45, 119, 32, 16, 34, + 66, 32, 2, 80, 73, 15, 77, 8, 30, 69, 37, 3, 85, 79, 78, 4, 35, 73, 4, + 21, 3, 85, 79, 89, 4, 11, 32, 4, 34, 82, 229, 128, 21, 2, 75, 79, 2, 143, + 143, 20, 79, 42, 76, 10, 73, 78, 72, 69, 82, 69, 78, 84, 32, 65, 29, 5, + 83, 73, 71, 78, 32, 4, 138, 181, 21, 65, 3, 81, 38, 102, 65, 54, 73, 30, + 79, 38, 89, 180, 228, 2, 5, 67, 79, 69, 78, 71, 250, 150, 7, 85, 235, + 183, 11, 69, 10, 218, 142, 3, 65, 174, 165, 18, 69, 2, 73, 3, 85, 7, 210, + 179, 21, 69, 3, 73, 6, 182, 179, 21, 69, 2, 77, 3, 79, 7, 146, 179, 21, + 65, 3, 89, 130, 1, 146, 1, 68, 88, 7, 76, 69, 84, 84, 69, 82, 32, 170, 2, + 83, 164, 1, 11, 86, 79, 87, 69, 76, 32, 83, 73, 71, 78, 32, 226, 156, 15, + 87, 219, 80, 65, 6, 48, 6, 79, 85, 66, 76, 69, 32, 179, 220, 11, 65, 4, + 166, 248, 9, 83, 255, 227, 1, 68, 90, 234, 1, 83, 130, 5, 66, 42, 71, + 246, 230, 5, 68, 222, 137, 4, 74, 214, 208, 7, 65, 82, 84, 222, 225, 1, + 76, 246, 189, 1, 78, 126, 67, 2, 75, 2, 80, 254, 68, 72, 2, 77, 2, 81, 2, + 82, 2, 86, 2, 89, 186, 2, 69, 2, 73, 2, 79, 3, 85, 4, 26, 72, 131, 175, + 21, 65, 2, 249, 238, 20, 3, 79, 82, 84, 12, 40, 4, 73, 71, 78, 32, 191, + 245, 9, 69, 10, 58, 83, 138, 205, 15, 86, 170, 251, 1, 78, 223, 160, 3, + 65, 4, 26, 72, 243, 222, 16, 85, 2, 11, 65, 2, 203, 136, 21, 68, 18, 246, + 202, 3, 86, 238, 253, 13, 65, 142, 222, 1, 73, 206, 134, 2, 69, 2, 79, 3, + 85, 138, 1, 100, 7, 76, 69, 84, 84, 69, 82, 32, 216, 2, 5, 83, 73, 71, + 78, 32, 170, 236, 15, 86, 227, 206, 3, 68, 94, 222, 1, 66, 42, 71, 42, + 74, 206, 230, 5, 68, 230, 162, 11, 82, 206, 55, 65, 82, 84, 230, 24, 85, + 210, 200, 1, 73, 158, 190, 1, 78, 126, 67, 2, 75, 2, 80, 2, 83, 254, 68, + 72, 2, 76, 2, 77, 2, 86, 2, 89, 186, 2, 69, 3, 79, 6, 226, 167, 21, 66, + 2, 72, 187, 2, 65, 6, 186, 167, 21, 71, 2, 72, 187, 2, 65, 6, 146, 167, + 21, 72, 2, 74, 187, 2, 65, 6, 178, 200, 15, 86, 170, 251, 1, 78, 223, + 160, 3, 65, 20, 92, 2, 83, 83, 140, 245, 19, 4, 87, 73, 70, 82, 158, 44, + 80, 216, 93, 2, 77, 79, 191, 18, 84, 13, 40, 4, 73, 78, 71, 32, 187, 230, + 20, 32, 8, 96, 4, 70, 65, 67, 69, 209, 212, 13, 14, 67, 65, 84, 32, 70, + 65, 67, 69, 32, 87, 73, 84, 72, 32, 7, 33, 6, 32, 87, 73, 84, 72, 32, 4, + 198, 211, 13, 83, 115, 67, 4, 236, 210, 14, 3, 69, 69, 76, 167, 183, 6, + 79, 4, 40, 4, 82, 69, 65, 78, 207, 131, 21, 65, 2, 33, 6, 32, 83, 84, 65, + 78, 68, 2, 129, 141, 18, 2, 65, 82, 2, 11, 79, 2, 155, 253, 9, 78, 128, + 41, 154, 1, 65, 190, 216, 1, 69, 242, 56, 73, 230, 83, 79, 146, 22, 85, + 94, 89, 182, 206, 7, 82, 168, 249, 8, 5, 32, 66, 32, 66, 65, 174, 157, 1, + 76, 227, 66, 70, 130, 22, 182, 1, 66, 44, 6, 67, 82, 79, 83, 83, 69, 46, + 68, 56, 2, 79, 32, 222, 11, 82, 208, 6, 4, 83, 84, 32, 81, 76, 4, 84, 73, + 78, 32, 161, 168, 19, 8, 78, 71, 85, 65, 71, 69, 32, 84, 4, 212, 131, 14, + 2, 32, 67, 183, 149, 6, 69, 2, 153, 173, 16, 6, 32, 83, 84, 73, 67, 75, + 4, 184, 192, 12, 5, 89, 32, 66, 69, 69, 183, 163, 8, 68, 174, 1, 200, 2, + 3, 72, 79, 32, 28, 7, 76, 69, 84, 84, 69, 82, 32, 214, 5, 83, 148, 1, 9, + 84, 79, 78, 69, 32, 77, 65, 73, 32, 84, 11, 86, 79, 87, 69, 76, 32, 83, + 73, 71, 78, 32, 128, 137, 4, 2, 75, 79, 188, 211, 12, 2, 89, 65, 162, + 157, 2, 69, 250, 46, 68, 248, 132, 1, 7, 67, 65, 78, 67, 69, 76, 76, 205, + 68, 6, 78, 73, 71, 71, 65, 72, 4, 210, 255, 20, 77, 3, 78, 94, 176, 1, 3, + 70, 79, 32, 78, 75, 96, 2, 76, 79, 50, 80, 154, 1, 83, 86, 84, 30, 72, + 206, 212, 15, 78, 214, 165, 5, 66, 2, 67, 2, 68, 2, 77, 2, 82, 2, 87, 2, + 89, 247, 30, 79, 8, 42, 70, 206, 235, 14, 83, 199, 247, 4, 84, 4, 246, + 204, 20, 79, 143, 62, 65, 10, 26, 72, 147, 156, 21, 79, 8, 32, 3, 77, 85, + 32, 231, 2, 79, 4, 182, 195, 20, 78, 195, 57, 71, 7, 17, 2, 32, 76, 4, + 202, 202, 20, 73, 67, 79, 30, 52, 4, 65, 76, 73, 32, 210, 1, 72, 151, + 153, 21, 79, 24, 190, 165, 6, 68, 34, 84, 206, 6, 78, 254, 246, 12, 66, + 2, 67, 2, 71, 2, 74, 167, 213, 1, 76, 8, 52, 9, 65, 78, 83, 75, 82, 73, + 84, 32, 83, 71, 79, 4, 146, 151, 21, 72, 3, 83, 6, 26, 72, 151, 153, 21, + 79, 4, 11, 79, 4, 11, 32, 4, 250, 231, 14, 83, 199, 247, 4, 84, 6, 112, + 14, 69, 77, 73, 86, 79, 87, 69, 76, 32, 83, 73, 71, 78, 32, 137, 147, 3, + 8, 73, 71, 78, 32, 80, 65, 76, 73, 4, 174, 191, 20, 78, 195, 57, 76, 8, + 50, 84, 252, 209, 16, 2, 67, 65, 255, 193, 4, 69, 4, 154, 248, 20, 72, + 247, 30, 73, 32, 106, 65, 44, 5, 77, 65, 73, 32, 75, 226, 162, 17, 89, + 222, 35, 85, 210, 200, 1, 69, 2, 73, 207, 134, 2, 79, 11, 130, 150, 21, + 65, 2, 73, 2, 77, 3, 89, 4, 130, 198, 20, 65, 3, 79, 56, 32, 2, 71, 69, + 179, 142, 20, 73, 54, 26, 32, 231, 188, 13, 82, 50, 254, 1, 66, 44, 4, + 71, 82, 69, 69, 22, 79, 250, 1, 84, 186, 180, 11, 68, 36, 2, 85, 80, 168, + 180, 3, 12, 76, 69, 70, 84, 32, 84, 82, 73, 65, 78, 71, 76, 224, 151, 4, + 5, 80, 85, 82, 80, 76, 12, 3, 82, 69, 68, 0, 6, 89, 69, 76, 76, 79, 87, + 207, 64, 67, 10, 40, 3, 82, 79, 87, 201, 1, 2, 76, 85, 4, 251, 130, 19, + 78, 10, 48, 3, 78, 69, 32, 129, 1, 4, 82, 65, 78, 71, 4, 200, 248, 7, 5, + 68, 79, 84, 32, 79, 173, 221, 2, 18, 82, 73, 78, 71, 32, 79, 86, 69, 82, + 32, 84, 87, 79, 32, 82, 73, 78, 71, 6, 11, 69, 6, 11, 32, 6, 230, 193, + 19, 67, 226, 19, 68, 231, 26, 83, 6, 104, 3, 87, 79, 32, 161, 229, 17, + 17, 82, 73, 80, 76, 69, 32, 86, 69, 82, 84, 73, 67, 65, 76, 32, 66, 65, + 4, 162, 162, 17, 68, 205, 64, 19, 82, 73, 78, 71, 83, 32, 79, 86, 69, 82, + 32, 79, 78, 69, 32, 82, 73, 78, 71, 6, 53, 11, 85, 65, 82, 84, 69, 82, + 32, 77, 79, 79, 78, 7, 167, 220, 6, 32, 138, 20, 150, 1, 67, 244, 45, 18, + 69, 80, 73, 71, 82, 65, 80, 72, 73, 67, 32, 76, 69, 84, 84, 69, 82, 32, + 252, 1, 7, 76, 69, 84, 84, 69, 82, 32, 183, 13, 83, 192, 7, 56, 8, 65, + 80, 73, 84, 65, 76, 32, 76, 239, 206, 19, 82, 190, 7, 76, 6, 69, 84, 84, + 69, 82, 32, 189, 44, 8, 73, 71, 65, 84, 85, 82, 69, 32, 186, 7, 154, 2, + 65, 158, 3, 66, 154, 1, 67, 254, 1, 68, 250, 1, 69, 174, 2, 70, 82, 71, + 194, 1, 72, 146, 1, 73, 154, 2, 74, 118, 75, 126, 76, 222, 2, 77, 114, + 78, 134, 2, 79, 198, 2, 80, 102, 81, 62, 82, 174, 2, 83, 254, 2, 84, 142, + 3, 85, 234, 1, 86, 146, 1, 87, 118, 88, 50, 89, 167, 1, 90, 93, 172, 1, + 6, 32, 87, 73, 84, 72, 32, 166, 1, 69, 182, 65, 78, 166, 209, 4, 76, 236, + 154, 9, 6, 70, 82, 73, 67, 65, 78, 178, 136, 4, 86, 138, 209, 2, 65, 2, + 79, 2, 85, 3, 89, 66, 182, 64, 66, 34, 68, 108, 3, 82, 73, 78, 242, 33, + 77, 254, 21, 67, 146, 49, 72, 158, 1, 79, 198, 10, 71, 186, 2, 65, 206, + 156, 3, 73, 214, 241, 12, 84, 175, 145, 3, 83, 7, 33, 6, 32, 87, 73, 84, + 72, 32, 4, 142, 183, 1, 65, 183, 182, 3, 77, 21, 60, 6, 32, 87, 73, 84, + 72, 32, 254, 67, 82, 175, 157, 20, 69, 14, 218, 66, 84, 146, 60, 70, 202, + 56, 76, 134, 224, 15, 68, 222, 157, 2, 72, 231, 160, 1, 83, 33, 108, 6, + 32, 87, 73, 84, 72, 32, 140, 70, 7, 76, 79, 83, 69, 68, 32, 73, 54, 85, + 154, 238, 19, 79, 255, 59, 72, 20, 94, 67, 134, 180, 1, 65, 222, 215, 3, + 80, 142, 167, 14, 72, 186, 46, 66, 246, 33, 68, 187, 80, 83, 8, 134, 68, + 69, 190, 112, 73, 255, 170, 18, 65, 31, 44, 6, 32, 87, 73, 84, 72, 32, + 179, 1, 90, 24, 78, 83, 182, 15, 67, 214, 47, 84, 218, 116, 76, 134, 224, + 15, 68, 223, 157, 2, 72, 8, 92, 13, 77, 65, 76, 76, 32, 76, 69, 84, 84, + 69, 82, 32, 90, 246, 136, 1, 72, 223, 200, 19, 84, 5, 177, 72, 2, 32, 87, + 91, 104, 6, 32, 87, 73, 84, 72, 32, 152, 1, 2, 90, 72, 134, 76, 71, 194, + 191, 16, 84, 210, 242, 3, 83, 63, 78, 70, 254, 73, 67, 158, 2, 68, 194, + 16, 84, 162, 23, 77, 250, 1, 86, 234, 44, 72, 158, 1, 79, 198, 10, 71, + 186, 2, 65, 206, 156, 3, 73, 62, 66, 199, 130, 16, 83, 7, 11, 32, 4, 138, + 70, 87, 211, 8, 82, 9, 33, 6, 32, 87, 73, 84, 72, 32, 6, 246, 173, 19, + 72, 174, 80, 68, 187, 80, 83, 35, 76, 6, 32, 87, 73, 84, 72, 32, 190, 81, + 76, 138, 225, 17, 65, 227, 200, 2, 72, 20, 154, 84, 67, 250, 89, 65, 138, + 157, 3, 66, 174, 25, 77, 142, 133, 4, 79, 170, 195, 10, 72, 174, 80, 68, + 187, 80, 83, 29, 76, 6, 32, 87, 73, 84, 72, 32, 138, 126, 65, 238, 218, + 7, 87, 191, 210, 11, 69, 20, 186, 82, 66, 34, 67, 46, 68, 182, 216, 18, + 72, 231, 160, 1, 83, 59, 80, 6, 32, 87, 73, 84, 72, 32, 132, 88, 2, 78, + 83, 186, 254, 19, 79, 207, 36, 83, 40, 138, 1, 68, 162, 83, 67, 242, 1, + 77, 142, 1, 84, 130, 70, 72, 158, 1, 79, 198, 10, 71, 186, 2, 65, 206, + 156, 3, 73, 62, 66, 199, 130, 16, 83, 10, 22, 79, 191, 83, 73, 6, 234, + 120, 85, 155, 232, 17, 84, 11, 33, 6, 32, 87, 73, 84, 72, 32, 8, 42, 67, + 206, 183, 17, 84, 175, 145, 3, 83, 4, 234, 169, 1, 73, 199, 205, 3, 82, + 25, 33, 6, 32, 87, 73, 84, 72, 32, 22, 182, 89, 67, 34, 68, 50, 83, 222, + 78, 65, 138, 1, 76, 186, 186, 7, 79, 171, 195, 10, 72, 37, 48, 6, 32, 87, + 73, 84, 72, 32, 163, 247, 20, 74, 32, 138, 1, 66, 36, 2, 68, 79, 52, 7, + 77, 73, 68, 68, 76, 69, 32, 38, 83, 174, 2, 67, 198, 91, 72, 226, 71, 65, + 138, 1, 76, 155, 141, 16, 84, 4, 246, 151, 12, 69, 207, 165, 8, 65, 6, + 22, 85, 135, 92, 84, 2, 205, 223, 4, 2, 66, 76, 4, 146, 180, 17, 84, 255, + 240, 2, 68, 4, 214, 2, 77, 211, 194, 20, 84, 19, 44, 6, 32, 87, 73, 84, + 72, 32, 223, 94, 73, 10, 254, 164, 1, 65, 142, 225, 15, 68, 150, 45, 84, + 203, 240, 1, 72, 33, 48, 6, 32, 87, 73, 84, 72, 32, 215, 243, 20, 74, 28, + 102, 67, 44, 2, 83, 77, 194, 96, 76, 130, 64, 71, 186, 2, 65, 102, 68, + 222, 186, 7, 79, 227, 210, 8, 84, 6, 202, 131, 1, 69, 22, 73, 131, 203, + 18, 65, 2, 249, 194, 10, 10, 65, 76, 76, 32, 76, 69, 84, 84, 69, 82, 101, + 108, 6, 32, 87, 73, 84, 72, 32, 194, 103, 76, 202, 140, 4, 80, 150, 253, + 8, 77, 250, 255, 6, 73, 2, 79, 3, 85, 84, 144, 1, 2, 76, 79, 34, 77, 242, + 96, 67, 70, 68, 154, 2, 79, 38, 83, 66, 84, 106, 86, 218, 43, 72, 242, + 12, 71, 186, 2, 65, 206, 156, 3, 73, 63, 66, 4, 174, 99, 78, 199, 140, + 20, 79, 8, 170, 99, 65, 171, 141, 4, 73, 17, 33, 6, 32, 87, 73, 84, 72, + 32, 14, 146, 104, 70, 34, 83, 162, 55, 65, 234, 254, 17, 72, 175, 80, 68, + 7, 33, 6, 32, 87, 73, 84, 72, 32, 4, 230, 104, 68, 39, 83, 41, 78, 32, + 156, 1, 8, 69, 86, 69, 82, 83, 69, 68, 32, 145, 111, 3, 85, 77, 32, 28, + 40, 5, 87, 73, 84, 72, 32, 143, 112, 82, 26, 174, 78, 67, 234, 28, 68, + 170, 2, 84, 158, 48, 65, 138, 1, 76, 198, 155, 3, 73, 246, 158, 4, 79, + 143, 228, 11, 83, 8, 146, 110, 72, 218, 138, 4, 79, 162, 246, 12, 67, + 171, 253, 2, 69, 47, 136, 1, 6, 32, 87, 73, 84, 72, 32, 132, 1, 5, 77, + 65, 76, 76, 32, 156, 115, 2, 65, 76, 234, 1, 72, 152, 2, 2, 73, 71, 235, + 248, 3, 67, 30, 82, 67, 194, 111, 65, 118, 68, 126, 83, 174, 1, 86, 178, + 227, 7, 79, 171, 195, 10, 72, 10, 154, 112, 65, 218, 10, 69, 82, 79, 203, + 31, 73, 4, 200, 188, 18, 11, 81, 32, 87, 73, 84, 72, 32, 72, 79, 79, 75, + 149, 237, 1, 7, 67, 65, 80, 73, 84, 65, 76, 59, 136, 1, 6, 32, 87, 73, + 84, 72, 32, 168, 1, 6, 85, 82, 78, 69, 68, 32, 232, 122, 2, 72, 79, 176, + 1, 2, 79, 78, 74, 82, 231, 233, 19, 90, 22, 82, 67, 50, 68, 170, 152, 1, + 76, 186, 220, 3, 82, 170, 161, 14, 72, 231, 160, 1, 83, 8, 246, 119, 69, + 22, 73, 62, 79, 199, 202, 18, 65, 6, 234, 141, 1, 73, 207, 234, 15, 79, + 18, 162, 40, 73, 146, 249, 2, 65, 146, 197, 17, 72, 2, 75, 2, 76, 2, 77, + 2, 84, 3, 86, 79, 26, 32, 179, 245, 4, 80, 74, 44, 5, 87, 73, 84, 72, 32, + 251, 194, 19, 66, 72, 210, 131, 1, 67, 74, 68, 150, 2, 72, 170, 1, 77, + 134, 1, 79, 142, 1, 84, 186, 9, 71, 186, 2, 65, 206, 156, 3, 73, 62, 66, + 186, 136, 14, 82, 143, 250, 1, 83, 23, 88, 6, 32, 87, 73, 84, 72, 32, + 222, 138, 1, 73, 66, 79, 174, 202, 18, 69, 227, 141, 1, 89, 8, 142, 138, + 1, 68, 242, 151, 16, 84, 203, 240, 1, 72, 19, 48, 6, 32, 87, 73, 84, 72, + 32, 159, 132, 7, 89, 14, 234, 143, 1, 67, 18, 68, 70, 71, 186, 2, 65, + 235, 254, 17, 72, 7, 245, 139, 1, 7, 32, 87, 73, 84, 72, 32, 68, 29, 48, + 6, 32, 87, 73, 84, 72, 32, 147, 233, 16, 79, 24, 198, 142, 1, 67, 18, 68, + 70, 71, 22, 72, 42, 76, 254, 1, 65, 182, 182, 3, 77, 238, 215, 12, 84, + 175, 145, 3, 83, 25, 33, 6, 32, 87, 73, 84, 72, 32, 22, 170, 57, 67, 150, + 87, 65, 102, 68, 38, 76, 34, 83, 182, 214, 3, 80, 143, 167, 14, 72, 4, + 250, 175, 10, 73, 231, 152, 10, 79, 12, 128, 1, 5, 65, 82, 67, 72, 65, + 30, 73, 64, 9, 82, 69, 86, 69, 82, 83, 69, 68, 32, 197, 173, 10, 7, 83, + 73, 68, 69, 87, 65, 89, 2, 213, 199, 13, 2, 73, 67, 4, 136, 107, 5, 78, + 86, 69, 82, 84, 149, 156, 14, 3, 32, 76, 79, 4, 174, 221, 20, 70, 3, 80, + 138, 1, 198, 3, 65, 36, 2, 66, 73, 152, 1, 21, 73, 78, 86, 69, 82, 84, + 69, 68, 32, 71, 76, 79, 84, 84, 65, 76, 32, 83, 84, 79, 80, 72, 2, 82, + 69, 222, 1, 83, 162, 28, 87, 132, 33, 3, 84, 87, 79, 204, 246, 3, 2, 68, + 69, 140, 5, 2, 76, 65, 206, 11, 71, 248, 174, 1, 21, 80, 72, 65, 82, 89, + 78, 71, 69, 65, 76, 32, 86, 79, 73, 67, 69, 68, 32, 70, 82, 73, 192, 181, + 13, 20, 86, 79, 73, 67, 69, 68, 32, 76, 65, 82, 89, 78, 71, 69, 65, 76, + 32, 83, 80, 73, 155, 116, 89, 4, 150, 169, 4, 76, 223, 224, 15, 73, 6, + 76, 7, 76, 65, 66, 73, 65, 76, 32, 29, 8, 68, 69, 78, 84, 65, 76, 32, 80, + 4, 26, 80, 143, 188, 4, 67, 2, 153, 208, 15, 6, 69, 82, 67, 85, 83, 83, + 7, 33, 6, 32, 87, 73, 84, 72, 32, 4, 134, 225, 4, 67, 231, 198, 15, 83, + 8, 104, 7, 86, 69, 82, 83, 69, 68, 32, 149, 225, 4, 13, 84, 82, 79, 70, + 76, 69, 88, 32, 67, 76, 73, 67, 75, 4, 80, 3, 69, 83, 72, 193, 61, 12, + 71, 76, 79, 84, 84, 65, 76, 32, 83, 84, 79, 80, 2, 189, 132, 1, 2, 32, + 76, 96, 172, 1, 13, 77, 65, 76, 76, 32, 67, 65, 80, 73, 84, 65, 76, 32, + 220, 111, 10, 84, 82, 69, 84, 67, 72, 69, 68, 32, 67, 225, 211, 18, 10, + 73, 78, 79, 76, 79, 71, 73, 67, 65, 76, 90, 230, 1, 69, 30, 73, 22, 76, + 74, 79, 42, 82, 122, 84, 186, 164, 4, 66, 202, 41, 71, 166, 194, 15, 65, + 150, 64, 67, 2, 68, 2, 70, 2, 72, 2, 74, 2, 75, 2, 77, 2, 78, 2, 80, 2, + 81, 2, 83, 2, 85, 2, 86, 2, 87, 2, 89, 3, 90, 7, 190, 209, 20, 84, 3, 90, + 5, 191, 201, 4, 78, 7, 33, 6, 32, 87, 73, 84, 72, 32, 4, 198, 199, 8, 66, + 187, 218, 11, 83, 9, 214, 94, 80, 130, 243, 19, 69, 3, 85, 11, 88, 8, 69, + 86, 69, 82, 83, 69, 68, 32, 216, 127, 5, 32, 87, 73, 84, 72, 167, 192, + 19, 85, 4, 210, 208, 20, 78, 3, 82, 13, 33, 6, 85, 82, 78, 69, 68, 32, + 10, 146, 208, 20, 69, 2, 71, 2, 75, 2, 77, 3, 82, 180, 11, 136, 1, 5, 77, + 65, 76, 76, 32, 253, 129, 1, 22, 85, 66, 83, 67, 82, 73, 80, 84, 32, 83, + 77, 65, 76, 76, 32, 76, 69, 84, 84, 69, 82, 32, 144, 11, 76, 15, 67, 65, + 80, 73, 84, 65, 76, 32, 76, 69, 84, 84, 69, 82, 32, 27, 76, 4, 182, 53, + 73, 3, 85, 140, 11, 76, 6, 69, 84, 84, 69, 82, 32, 161, 127, 8, 73, 71, + 65, 84, 85, 82, 69, 32, 250, 10, 182, 2, 65, 190, 5, 66, 198, 3, 67, 186, + 4, 68, 182, 4, 69, 174, 9, 70, 214, 1, 71, 162, 2, 72, 230, 2, 73, 166, + 7, 74, 182, 1, 75, 178, 2, 76, 210, 6, 77, 178, 2, 78, 218, 3, 79, 242, + 8, 80, 230, 1, 81, 174, 1, 82, 142, 8, 83, 234, 10, 84, 246, 13, 85, 218, + 9, 86, 130, 3, 87, 110, 88, 226, 2, 89, 171, 3, 90, 101, 118, 32, 198, 3, + 69, 82, 78, 132, 208, 4, 4, 76, 80, 72, 65, 190, 164, 13, 86, 138, 209, + 2, 65, 2, 79, 2, 85, 3, 89, 72, 88, 5, 87, 73, 84, 72, 32, 209, 209, 5, + 11, 82, 69, 86, 69, 82, 83, 69, 68, 45, 83, 67, 70, 150, 1, 66, 34, 68, + 54, 82, 170, 34, 77, 254, 21, 67, 146, 49, 72, 158, 1, 79, 198, 10, 71, + 186, 2, 65, 206, 156, 3, 73, 214, 241, 12, 84, 175, 145, 3, 83, 12, 161, + 105, 4, 82, 69, 86, 69, 12, 22, 79, 155, 57, 73, 8, 218, 57, 84, 223, 12, + 85, 10, 26, 73, 255, 212, 4, 69, 8, 26, 78, 131, 156, 4, 71, 6, 17, 2, + 71, 32, 6, 240, 58, 4, 65, 66, 79, 86, 159, 243, 17, 66, 9, 33, 6, 32, + 87, 73, 84, 72, 32, 6, 242, 115, 71, 186, 2, 65, 183, 182, 3, 77, 2, 133, + 160, 10, 7, 71, 76, 73, 67, 65, 78, 65, 41, 140, 1, 6, 32, 87, 73, 84, + 72, 32, 130, 1, 65, 108, 11, 76, 65, 67, 75, 76, 69, 84, 84, 69, 82, 32, + 38, 82, 242, 182, 4, 79, 191, 230, 15, 69, 18, 110, 84, 146, 60, 70, 202, + 56, 76, 170, 207, 3, 77, 174, 7, 80, 178, 137, 12, 68, 222, 157, 2, 72, + 231, 160, 1, 83, 2, 255, 7, 79, 8, 64, 5, 82, 82, 69, 68, 32, 161, 80, 6, + 83, 69, 76, 73, 78, 69, 6, 182, 32, 65, 142, 162, 20, 69, 3, 79, 6, 186, + 177, 4, 79, 227, 144, 16, 69, 2, 133, 148, 10, 4, 79, 75, 69, 78, 47, + 108, 6, 32, 87, 73, 84, 72, 32, 196, 1, 2, 72, 73, 92, 6, 76, 79, 83, 69, + 68, 32, 90, 85, 155, 238, 19, 79, 24, 102, 67, 182, 112, 65, 222, 215, 3, + 80, 230, 5, 82, 170, 161, 14, 72, 186, 46, 66, 246, 33, 68, 187, 80, 83, + 10, 54, 69, 190, 112, 73, 238, 225, 6, 85, 147, 201, 11, 65, 4, 249, 51, + 5, 68, 73, 76, 76, 65, 7, 49, 10, 32, 87, 73, 84, 72, 32, 76, 79, 87, 32, + 4, 162, 106, 82, 45, 4, 76, 69, 70, 84, 8, 34, 73, 18, 79, 227, 181, 4, + 82, 2, 163, 87, 78, 4, 210, 202, 4, 80, 199, 243, 8, 77, 4, 37, 7, 65, + 84, 82, 73, 76, 76, 79, 5, 153, 224, 12, 5, 32, 87, 73, 84, 72, 73, 96, + 6, 32, 87, 73, 84, 72, 32, 182, 1, 69, 34, 79, 178, 1, 90, 246, 194, 4, + 66, 235, 229, 15, 85, 32, 98, 83, 34, 84, 130, 33, 67, 206, 44, 77, 170, + 31, 76, 206, 199, 3, 72, 138, 15, 80, 179, 137, 12, 68, 4, 134, 67, 72, + 223, 200, 19, 84, 4, 26, 79, 167, 142, 18, 65, 2, 215, 235, 17, 80, 8, + 246, 77, 90, 195, 200, 19, 76, 16, 60, 6, 84, 76, 69, 83, 83, 32, 49, 5, + 85, 66, 76, 69, 32, 8, 26, 74, 139, 186, 20, 73, 7, 235, 179, 4, 32, 8, + 42, 87, 210, 183, 4, 82, 187, 219, 5, 84, 2, 163, 219, 6, 89, 11, 11, 32, + 8, 26, 87, 219, 179, 4, 68, 2, 169, 89, 5, 73, 84, 72, 32, 67, 119, 112, + 6, 32, 87, 73, 84, 72, 32, 214, 4, 71, 72, 2, 78, 71, 68, 2, 83, 72, 164, + 1, 2, 90, 72, 147, 189, 16, 84, 76, 182, 1, 67, 158, 2, 68, 110, 78, 214, + 15, 84, 162, 23, 77, 250, 1, 86, 194, 3, 70, 170, 41, 72, 158, 1, 79, + 198, 10, 71, 186, 2, 65, 206, 156, 3, 73, 62, 66, 186, 64, 82, 143, 194, + 15, 83, 24, 92, 6, 69, 68, 73, 76, 76, 65, 32, 9, 73, 82, 67, 85, 77, 70, + 76, 69, 88, 179, 145, 19, 65, 5, 129, 131, 4, 3, 32, 65, 78, 19, 11, 32, + 16, 40, 4, 65, 78, 68, 32, 207, 156, 18, 66, 14, 162, 85, 67, 130, 2, 72, + 226, 11, 71, 186, 2, 65, 182, 182, 3, 77, 190, 162, 4, 68, 179, 181, 8, + 84, 12, 22, 79, 227, 97, 73, 10, 28, 2, 84, 32, 243, 50, 85, 8, 192, 87, + 5, 65, 66, 79, 86, 69, 239, 195, 17, 66, 2, 183, 232, 13, 79, 4, 237, + 237, 6, 13, 89, 80, 84, 79, 76, 79, 71, 73, 67, 65, 76, 32, 65, 7, 33, 6, + 32, 87, 73, 84, 72, 32, 4, 226, 176, 4, 67, 231, 9, 80, 13, 33, 6, 32, + 87, 73, 84, 72, 32, 10, 88, 10, 68, 79, 85, 66, 76, 69, 32, 66, 65, 82, + 170, 185, 4, 80, 142, 1, 67, 219, 4, 82, 5, 157, 186, 4, 4, 32, 65, 78, + 68, 15, 11, 32, 12, 38, 82, 37, 5, 87, 73, 84, 72, 32, 2, 209, 228, 13, + 4, 69, 86, 69, 82, 10, 54, 67, 246, 183, 4, 80, 230, 5, 82, 139, 197, 13, + 84, 4, 194, 194, 7, 85, 147, 201, 11, 65, 17, 84, 6, 32, 87, 73, 84, 72, + 32, 73, 11, 69, 78, 71, 32, 68, 73, 71, 82, 65, 80, 72, 10, 202, 175, 4, + 77, 174, 7, 80, 142, 167, 14, 72, 174, 80, 68, 187, 80, 83, 5, 197, 189, + 17, 8, 32, 87, 73, 84, 72, 32, 84, 82, 37, 72, 6, 32, 87, 73, 84, 72, 32, + 126, 76, 138, 225, 17, 65, 227, 200, 2, 72, 22, 218, 3, 67, 250, 89, 65, + 138, 157, 3, 66, 174, 25, 77, 170, 33, 80, 230, 227, 3, 79, 170, 195, 10, + 72, 174, 80, 68, 187, 80, 83, 8, 33, 6, 79, 84, 84, 65, 76, 32, 8, 178, + 225, 17, 83, 202, 202, 2, 65, 2, 73, 3, 85, 39, 140, 1, 6, 32, 87, 73, + 84, 72, 32, 166, 44, 65, 216, 25, 12, 79, 79, 75, 69, 68, 32, 83, 67, 72, + 87, 65, 32, 242, 225, 3, 69, 207, 130, 16, 86, 24, 86, 66, 34, 67, 46, + 68, 214, 90, 76, 214, 214, 3, 80, 142, 167, 14, 72, 231, 160, 1, 83, 2, + 157, 229, 12, 3, 82, 69, 86, 6, 158, 58, 69, 154, 32, 73, 255, 170, 18, + 65, 8, 234, 86, 73, 178, 173, 3, 69, 203, 182, 12, 79, 75, 80, 6, 32, 87, + 73, 84, 72, 32, 222, 4, 78, 188, 1, 2, 79, 84, 251, 161, 20, 83, 48, 178, + 1, 67, 34, 68, 210, 1, 77, 64, 6, 79, 71, 79, 78, 69, 75, 78, 84, 130, + 70, 72, 226, 11, 71, 186, 2, 65, 206, 156, 3, 73, 62, 66, 136, 64, 6, 83, + 84, 82, 79, 75, 69, 51, 82, 4, 210, 87, 73, 255, 170, 18, 65, 14, 18, 73, + 47, 79, 4, 221, 26, 7, 65, 69, 82, 69, 83, 73, 83, 10, 28, 2, 84, 32, + 231, 36, 85, 8, 64, 10, 65, 66, 79, 86, 69, 32, 65, 78, 68, 32, 227, 140, + 18, 66, 6, 150, 83, 71, 186, 2, 65, 163, 142, 16, 84, 4, 29, 5, 65, 67, + 82, 79, 78, 5, 233, 35, 4, 32, 65, 78, 68, 7, 145, 72, 15, 32, 65, 78, + 68, 32, 68, 79, 84, 32, 65, 66, 79, 86, 69, 32, 4, 21, 3, 73, 76, 68, 4, + 171, 251, 4, 69, 16, 46, 83, 93, 7, 86, 69, 82, 84, 69, 68, 32, 12, 29, + 5, 85, 76, 65, 82, 32, 12, 226, 162, 20, 68, 2, 70, 2, 71, 2, 82, 2, 83, + 3, 84, 4, 26, 65, 187, 139, 20, 79, 2, 231, 173, 4, 76, 6, 150, 145, 4, + 65, 229, 162, 6, 5, 73, 70, 73, 69, 68, 13, 33, 6, 32, 87, 73, 84, 72, + 32, 10, 94, 67, 216, 161, 4, 13, 68, 79, 84, 32, 65, 66, 79, 86, 69, 32, + 65, 78, 68, 235, 206, 15, 83, 6, 178, 81, 73, 198, 205, 3, 82, 187, 221, + 14, 65, 29, 48, 6, 32, 87, 73, 84, 72, 32, 163, 157, 20, 82, 24, 98, 67, + 34, 68, 50, 83, 222, 78, 65, 138, 1, 76, 214, 214, 3, 80, 230, 227, 3, + 79, 171, 195, 10, 72, 4, 210, 47, 69, 151, 203, 18, 65, 6, 214, 69, 73, + 134, 180, 3, 69, 175, 174, 4, 79, 4, 29, 5, 84, 82, 79, 75, 69, 5, 177, + 24, 6, 32, 65, 78, 68, 32, 68, 77, 156, 1, 6, 32, 87, 73, 84, 72, 32, + 248, 3, 5, 65, 77, 66, 68, 65, 22, 69, 48, 5, 79, 78, 71, 32, 83, 194, + 161, 4, 83, 2, 90, 234, 229, 15, 85, 219, 16, 74, 50, 178, 1, 66, 86, 67, + 56, 2, 68, 79, 100, 3, 77, 73, 68, 242, 1, 72, 226, 71, 65, 138, 1, 76, + 218, 206, 3, 73, 162, 1, 82, 222, 2, 70, 130, 4, 80, 198, 182, 12, 84, + 175, 145, 3, 83, 6, 36, 3, 69, 76, 84, 147, 226, 19, 65, 5, 241, 162, 4, + 6, 32, 65, 78, 68, 32, 80, 8, 146, 43, 69, 22, 73, 242, 129, 7, 85, 147, + 201, 11, 65, 8, 38, 84, 25, 5, 85, 66, 76, 69, 32, 4, 137, 24, 2, 32, 66, + 4, 162, 154, 4, 77, 243, 220, 14, 66, 8, 36, 4, 68, 76, 69, 32, 187, 43, + 45, 6, 198, 215, 16, 84, 178, 240, 2, 82, 79, 68, 2, 139, 155, 4, 32, 6, + 222, 162, 4, 90, 161, 192, 12, 3, 78, 73, 83, 9, 33, 6, 32, 87, 73, 84, + 72, 32, 6, 18, 68, 35, 72, 4, 202, 62, 73, 215, 216, 18, 79, 2, 133, 154, + 4, 2, 73, 71, 27, 56, 6, 32, 87, 73, 84, 72, 32, 102, 73, 151, 133, 20, + 85, 16, 134, 71, 65, 250, 205, 3, 67, 186, 2, 77, 174, 7, 80, 178, 137, + 12, 68, 150, 45, 84, 203, 240, 1, 72, 6, 25, 4, 68, 68, 76, 69, 6, 76, 7, + 45, 87, 69, 76, 83, 72, 32, 141, 194, 16, 6, 32, 83, 67, 79, 84, 83, 4, + 226, 139, 19, 76, 159, 137, 1, 86, 49, 58, 32, 216, 2, 2, 71, 32, 242, + 128, 20, 85, 219, 16, 74, 40, 88, 5, 87, 73, 84, 72, 32, 193, 250, 5, 11, + 80, 82, 69, 67, 69, 68, 69, 68, 32, 66, 89, 38, 122, 67, 74, 76, 154, 36, + 77, 234, 27, 71, 186, 2, 65, 102, 68, 250, 214, 3, 80, 230, 5, 82, 130, + 222, 3, 79, 227, 210, 8, 84, 10, 166, 35, 69, 22, 73, 202, 237, 3, 82, + 170, 148, 3, 85, 147, 201, 11, 65, 6, 128, 65, 3, 79, 78, 71, 202, 2, 73, + 135, 222, 3, 69, 2, 25, 4, 87, 73, 84, 72, 2, 149, 131, 17, 5, 32, 84, + 73, 76, 68, 115, 116, 6, 32, 87, 73, 84, 72, 32, 186, 6, 76, 52, 4, 80, + 69, 78, 32, 170, 137, 13, 77, 250, 255, 6, 73, 2, 79, 3, 85, 86, 154, 1, + 67, 70, 68, 152, 1, 2, 76, 79, 86, 77, 46, 79, 38, 83, 66, 84, 106, 86, + 218, 43, 72, 242, 12, 71, 186, 2, 65, 206, 156, 3, 73, 62, 66, 187, 64, + 82, 14, 168, 48, 9, 73, 82, 67, 85, 77, 70, 76, 69, 88, 187, 186, 18, 65, + 14, 18, 73, 47, 79, 4, 233, 12, 7, 65, 69, 82, 69, 83, 73, 83, 10, 22, + 84, 167, 46, 85, 6, 11, 32, 6, 152, 12, 5, 65, 66, 79, 86, 69, 247, 232, + 17, 66, 6, 66, 78, 188, 162, 12, 6, 87, 32, 82, 73, 78, 71, 139, 234, 7, + 79, 2, 155, 20, 71, 6, 11, 65, 6, 189, 2, 4, 67, 82, 79, 78, 4, 229, 10, + 5, 71, 79, 78, 69, 75, 4, 25, 4, 84, 82, 79, 75, 4, 11, 69, 5, 209, 48, + 2, 32, 65, 8, 25, 4, 73, 76, 68, 69, 9, 29, 5, 32, 65, 78, 68, 32, 6, + 158, 46, 68, 142, 13, 65, 183, 182, 3, 77, 6, 81, 18, 69, 82, 84, 73, 67, + 65, 76, 32, 76, 73, 78, 69, 32, 66, 69, 76, 79, 87, 7, 217, 42, 4, 32, + 65, 78, 68, 2, 229, 225, 9, 8, 68, 32, 80, 79, 76, 73, 83, 72, 16, 26, + 79, 195, 147, 4, 69, 13, 48, 6, 32, 87, 73, 84, 72, 32, 211, 136, 20, 69, + 8, 206, 54, 71, 186, 2, 65, 194, 221, 3, 82, 143, 194, 15, 83, 23, 48, 6, + 32, 87, 73, 84, 72, 32, 139, 244, 19, 72, 18, 86, 70, 34, 83, 162, 55, + 65, 178, 208, 3, 77, 174, 7, 80, 142, 167, 14, 72, 175, 80, 68, 2, 181, + 135, 14, 3, 76, 79, 85, 6, 202, 27, 84, 185, 130, 12, 6, 81, 85, 73, 82, + 82, 69, 13, 48, 6, 32, 87, 73, 84, 72, 32, 191, 143, 4, 80, 8, 42, 68, + 16, 4, 72, 79, 79, 75, 23, 83, 2, 211, 44, 73, 5, 179, 216, 17, 32, 2, + 181, 26, 6, 84, 82, 79, 75, 69, 32, 77, 90, 32, 228, 4, 8, 69, 86, 69, + 82, 83, 69, 68, 32, 148, 2, 2, 85, 77, 231, 129, 4, 65, 46, 36, 4, 87, + 73, 84, 72, 235, 6, 82, 44, 26, 32, 219, 253, 14, 79, 42, 166, 1, 67, 50, + 68, 200, 1, 8, 70, 73, 83, 72, 72, 79, 79, 75, 66, 76, 34, 84, 254, 17, + 77, 162, 30, 65, 206, 156, 3, 73, 146, 59, 80, 230, 227, 3, 79, 143, 228, + 11, 83, 6, 154, 19, 69, 222, 237, 3, 82, 187, 221, 14, 65, 8, 11, 79, 8, + 24, 2, 84, 32, 111, 85, 6, 26, 66, 239, 132, 19, 65, 4, 25, 4, 69, 76, + 79, 87, 5, 29, 5, 32, 65, 78, 68, 32, 2, 247, 231, 3, 77, 2, 21, 3, 66, + 76, 69, 2, 11, 32, 2, 211, 46, 71, 7, 29, 5, 32, 65, 78, 68, 32, 4, 138, + 129, 4, 77, 175, 7, 80, 4, 206, 49, 73, 211, 218, 3, 79, 4, 238, 210, 17, + 65, 251, 22, 73, 22, 162, 1, 72, 40, 6, 79, 80, 69, 78, 32, 69, 140, 130, + 4, 8, 82, 32, 87, 73, 84, 72, 32, 70, 168, 2, 3, 83, 67, 82, 218, 129, + 14, 69, 198, 84, 67, 171, 163, 1, 75, 2, 11, 65, 2, 189, 213, 9, 2, 76, + 70, 7, 33, 6, 32, 87, 73, 84, 72, 32, 4, 202, 139, 4, 82, 171, 161, 14, + 72, 5, 11, 32, 2, 11, 82, 2, 153, 168, 10, 3, 79, 84, 85, 83, 180, 1, 6, + 32, 87, 73, 84, 72, 32, 202, 4, 65, 66, 67, 218, 1, 72, 34, 73, 156, 2, + 13, 81, 85, 65, 84, 32, 82, 69, 86, 69, 82, 83, 69, 68, 173, 198, 9, 6, + 84, 73, 82, 82, 85, 80, 38, 106, 65, 34, 67, 86, 68, 126, 83, 174, 1, 86, + 210, 9, 77, 254, 245, 3, 80, 230, 227, 3, 79, 171, 195, 10, 72, 4, 193, + 1, 4, 67, 85, 84, 69, 12, 58, 65, 218, 10, 69, 82, 79, 202, 31, 73, 239, + 225, 6, 85, 4, 101, 3, 82, 79, 78, 6, 21, 3, 79, 84, 32, 6, 26, 66, 211, + 252, 18, 65, 4, 25, 4, 69, 76, 79, 87, 5, 11, 32, 2, 185, 248, 18, 3, 65, + 78, 68, 4, 22, 72, 203, 42, 87, 2, 21, 3, 79, 82, 84, 2, 17, 2, 32, 83, + 2, 11, 84, 2, 21, 3, 82, 79, 75, 2, 11, 69, 2, 17, 2, 32, 79, 2, 237, + 235, 18, 4, 86, 69, 82, 76, 2, 37, 7, 69, 82, 84, 73, 67, 65, 76, 2, 205, + 40, 2, 32, 76, 4, 46, 76, 249, 226, 18, 5, 75, 72, 65, 32, 89, 2, 247, + 12, 84, 18, 48, 3, 72, 87, 65, 97, 5, 82, 73, 80, 84, 32, 11, 33, 6, 32, + 87, 73, 84, 72, 32, 8, 222, 35, 71, 186, 2, 65, 194, 221, 3, 82, 171, + 161, 14, 72, 8, 26, 82, 147, 243, 3, 71, 5, 173, 141, 11, 5, 32, 87, 73, + 84, 72, 2, 233, 161, 16, 3, 65, 82, 80, 14, 48, 7, 68, 69, 87, 65, 89, + 83, 32, 199, 1, 71, 12, 110, 79, 56, 4, 84, 85, 82, 78, 224, 160, 10, 11, + 68, 73, 65, 69, 82, 69, 83, 73, 90, 69, 68, 135, 210, 9, 85, 7, 26, 80, + 203, 245, 3, 32, 2, 145, 203, 9, 2, 69, 78, 2, 173, 220, 12, 2, 69, 68, + 2, 209, 159, 16, 4, 77, 79, 73, 68, 2, 227, 219, 9, 32, 147, 1, 188, 1, + 6, 32, 87, 73, 84, 72, 32, 192, 3, 2, 69, 83, 70, 72, 130, 2, 79, 102, + 82, 54, 85, 242, 241, 3, 67, 202, 1, 83, 136, 210, 10, 9, 65, 73, 76, 76, + 69, 83, 83, 32, 80, 243, 163, 5, 90, 34, 110, 67, 182, 1, 68, 66, 77, + 170, 31, 76, 214, 214, 3, 80, 180, 5, 4, 72, 79, 79, 75, 50, 82, 143, + 194, 15, 83, 10, 58, 69, 22, 73, 62, 79, 182, 129, 7, 85, 147, 201, 11, + 65, 2, 195, 251, 11, 68, 2, 37, 7, 82, 67, 85, 77, 70, 76, 69, 2, 255, + 199, 17, 88, 2, 17, 2, 77, 77, 2, 215, 199, 17, 65, 8, 32, 2, 73, 65, + 215, 255, 15, 79, 4, 154, 21, 71, 215, 6, 69, 4, 17, 2, 73, 68, 4, 26, + 45, 195, 238, 3, 68, 2, 229, 252, 3, 6, 72, 69, 73, 71, 72, 84, 6, 45, 9, + 72, 32, 68, 73, 71, 82, 65, 80, 72, 7, 183, 244, 3, 32, 8, 64, 12, 32, + 87, 73, 84, 72, 32, 83, 84, 82, 73, 75, 69, 43, 79, 2, 245, 243, 15, 5, + 84, 72, 82, 79, 85, 6, 17, 2, 82, 78, 7, 41, 8, 32, 87, 73, 84, 72, 32, + 83, 84, 4, 25, 4, 82, 79, 75, 69, 5, 11, 32, 2, 213, 197, 3, 6, 84, 72, + 82, 79, 85, 71, 8, 26, 78, 143, 244, 3, 80, 6, 17, 2, 69, 32, 6, 234, + 188, 4, 83, 190, 160, 9, 84, 215, 132, 1, 70, 2, 17, 2, 69, 83, 2, 11, + 73, 2, 243, 198, 19, 76, 76, 44, 5, 82, 78, 69, 68, 32, 131, 233, 19, 77, + 74, 162, 1, 68, 22, 72, 66, 73, 54, 79, 142, 1, 82, 110, 84, 22, 86, 138, + 240, 3, 65, 50, 77, 198, 2, 89, 246, 221, 15, 85, 218, 19, 69, 2, 71, 2, + 75, 2, 76, 3, 87, 2, 191, 195, 16, 69, 7, 209, 224, 3, 11, 32, 87, 73, + 84, 72, 32, 70, 73, 83, 72, 72, 5, 11, 78, 2, 149, 181, 9, 5, 83, 85, 76, + 65, 82, 12, 66, 69, 176, 213, 3, 7, 32, 79, 80, 69, 78, 45, 79, 167, 29, + 80, 7, 33, 6, 32, 87, 73, 84, 72, 32, 4, 166, 200, 17, 72, 203, 237, 1, + 83, 15, 33, 6, 32, 87, 73, 84, 72, 32, 12, 138, 230, 3, 77, 174, 7, 80, + 142, 5, 76, 226, 197, 13, 84, 163, 92, 72, 5, 203, 237, 3, 32, 7, 11, 32, + 4, 161, 5, 4, 87, 73, 84, 72, 97, 90, 32, 224, 210, 3, 6, 80, 83, 73, 76, + 79, 78, 226, 144, 16, 69, 2, 73, 2, 77, 3, 79, 82, 48, 3, 66, 65, 82, 49, + 5, 87, 73, 84, 72, 32, 5, 245, 17, 8, 32, 87, 73, 84, 72, 32, 83, 72, 78, + 142, 1, 67, 74, 68, 150, 2, 72, 170, 1, 77, 134, 1, 79, 106, 82, 38, 84, + 186, 9, 71, 82, 83, 234, 1, 65, 206, 156, 3, 73, 62, 66, 135, 66, 76, 6, + 172, 185, 4, 9, 73, 82, 67, 85, 77, 70, 76, 69, 88, 147, 132, 14, 65, 18, + 52, 8, 73, 65, 69, 82, 69, 83, 73, 83, 131, 1, 79, 13, 11, 32, 10, 40, 4, + 65, 78, 68, 32, 223, 199, 17, 66, 8, 50, 67, 226, 13, 71, 186, 2, 65, + 183, 182, 3, 77, 2, 211, 187, 18, 65, 6, 26, 85, 207, 184, 17, 84, 4, 21, + 3, 66, 76, 69, 4, 11, 32, 4, 138, 13, 71, 187, 2, 65, 14, 11, 79, 14, 28, + 2, 82, 78, 251, 75, 79, 13, 29, 5, 32, 65, 78, 68, 32, 10, 66, 72, 226, + 11, 71, 186, 2, 65, 242, 216, 7, 68, 179, 181, 8, 84, 2, 145, 75, 2, 79, + 79, 10, 29, 5, 65, 67, 82, 79, 78, 11, 29, 5, 32, 65, 78, 68, 32, 8, 50, + 68, 214, 10, 71, 186, 2, 65, 163, 142, 16, 84, 2, 171, 10, 73, 6, 29, 5, + 71, 79, 78, 69, 75, 7, 11, 32, 4, 25, 4, 65, 78, 68, 32, 4, 178, 12, 65, + 163, 142, 16, 84, 4, 222, 233, 3, 69, 131, 200, 13, 73, 6, 25, 4, 73, 76, + 68, 69, 7, 11, 32, 4, 26, 65, 191, 194, 17, 66, 2, 17, 2, 78, 68, 2, 11, + 32, 2, 139, 11, 65, 29, 84, 6, 32, 87, 73, 84, 72, 32, 162, 1, 73, 66, + 79, 174, 202, 18, 69, 227, 141, 1, 89, 14, 82, 68, 174, 225, 3, 80, 142, + 1, 67, 158, 7, 82, 158, 174, 12, 84, 203, 240, 1, 72, 4, 26, 73, 179, + 226, 7, 79, 2, 17, 2, 65, 71, 2, 189, 168, 19, 2, 79, 78, 2, 41, 8, 83, + 73, 71, 79, 84, 72, 73, 67, 2, 175, 225, 15, 32, 6, 33, 6, 76, 65, 80, + 85, 75, 32, 6, 146, 193, 19, 65, 2, 79, 3, 85, 19, 33, 6, 32, 87, 73, 84, + 72, 32, 16, 202, 4, 67, 18, 68, 70, 71, 186, 2, 65, 194, 165, 17, 82, + 171, 89, 72, 17, 33, 6, 32, 87, 73, 84, 72, 32, 14, 42, 68, 32, 2, 76, + 79, 255, 221, 3, 80, 4, 222, 3, 73, 131, 210, 18, 79, 8, 60, 11, 78, 71, + 32, 76, 69, 70, 84, 32, 76, 69, 71, 79, 87, 7, 11, 32, 4, 60, 7, 65, 78, + 68, 32, 76, 79, 87, 65, 4, 87, 73, 84, 72, 2, 17, 2, 32, 82, 2, 21, 3, + 73, 71, 72, 2, 215, 236, 10, 84, 2, 197, 210, 18, 4, 32, 83, 69, 82, 33, + 48, 6, 32, 87, 73, 84, 72, 32, 187, 219, 15, 79, 28, 110, 67, 18, 68, 70, + 71, 22, 72, 42, 76, 22, 83, 234, 1, 65, 182, 182, 3, 77, 238, 215, 12, + 84, 163, 151, 1, 82, 2, 203, 3, 73, 6, 26, 73, 251, 227, 15, 79, 2, 17, + 2, 65, 69, 2, 243, 247, 15, 82, 2, 207, 233, 17, 82, 4, 17, 2, 79, 79, 4, + 187, 246, 4, 75, 2, 191, 216, 18, 79, 4, 26, 72, 167, 161, 19, 84, 2, 21, + 3, 79, 82, 84, 2, 245, 226, 7, 6, 32, 82, 73, 71, 72, 84, 31, 33, 6, 32, + 87, 73, 84, 72, 32, 28, 98, 65, 22, 67, 82, 68, 38, 76, 34, 83, 138, 207, + 3, 77, 174, 7, 80, 230, 5, 82, 171, 161, 14, 72, 2, 175, 140, 13, 67, 6, + 42, 73, 238, 225, 6, 85, 147, 201, 11, 65, 2, 177, 158, 11, 4, 82, 67, + 85, 77, 6, 234, 169, 3, 69, 203, 182, 12, 79, 2, 11, 73, 2, 243, 137, 12, + 78, 4, 26, 87, 151, 158, 19, 84, 2, 195, 190, 16, 65, 18, 90, 70, 222, + 157, 9, 73, 172, 9, 6, 76, 79, 78, 71, 32, 83, 226, 137, 10, 83, 219, 5, + 79, 10, 34, 70, 242, 204, 19, 73, 3, 76, 7, 238, 204, 19, 73, 3, 76, 36, + 150, 1, 83, 190, 203, 19, 65, 2, 69, 2, 72, 2, 73, 2, 74, 2, 75, 2, 76, + 2, 77, 2, 78, 2, 79, 2, 80, 2, 82, 2, 84, 2, 85, 2, 86, 3, 88, 5, 139, + 212, 4, 67, 160, 5, 200, 1, 2, 65, 70, 104, 2, 70, 84, 186, 33, 79, 20, + 5, 80, 67, 72, 65, 32, 164, 8, 8, 83, 83, 45, 84, 72, 65, 78, 32, 142, + 231, 15, 68, 248, 22, 6, 86, 69, 76, 32, 83, 76, 158, 209, 2, 77, 227, + 79, 71, 4, 180, 180, 1, 14, 32, 70, 76, 85, 84, 84, 69, 82, 73, 78, 71, + 32, 73, 78, 169, 186, 11, 3, 89, 32, 71, 200, 3, 58, 32, 186, 17, 45, + 169, 1, 6, 87, 65, 82, 68, 83, 32, 218, 1, 190, 1, 65, 174, 3, 66, 202, + 1, 67, 96, 2, 68, 79, 112, 2, 72, 65, 250, 2, 76, 46, 77, 38, 79, 38, 82, + 146, 3, 83, 82, 84, 174, 1, 87, 190, 159, 8, 70, 210, 3, 78, 202, 1, 80, + 187, 11, 86, 26, 22, 78, 211, 2, 82, 20, 28, 2, 68, 32, 131, 2, 71, 14, + 72, 3, 76, 79, 87, 0, 3, 85, 80, 80, 93, 6, 82, 73, 71, 72, 84, 32, 4, + 21, 3, 69, 82, 32, 4, 132, 190, 16, 9, 65, 78, 68, 32, 82, 73, 71, 72, + 84, 175, 30, 79, 6, 50, 84, 161, 166, 17, 6, 68, 79, 85, 66, 76, 69, 4, + 138, 190, 16, 82, 131, 216, 1, 65, 6, 202, 163, 8, 69, 185, 1, 4, 76, 69, + 32, 66, 6, 26, 67, 167, 167, 8, 82, 2, 129, 167, 8, 5, 32, 76, 69, 83, + 83, 12, 40, 4, 65, 82, 66, 32, 191, 167, 8, 76, 8, 40, 4, 68, 79, 87, 78, + 1, 2, 85, 80, 4, 57, 12, 32, 82, 73, 71, 72, 84, 32, 66, 65, 82, 66, 32, + 4, 208, 176, 16, 4, 68, 79, 87, 78, 1, 2, 85, 80, 14, 130, 167, 8, 85, + 230, 21, 79, 250, 222, 2, 69, 217, 153, 2, 8, 76, 79, 83, 69, 68, 32, 69, + 78, 10, 44, 5, 85, 66, 76, 69, 32, 175, 167, 8, 84, 8, 226, 168, 8, 87, + 234, 24, 65, 198, 248, 2, 81, 151, 172, 4, 80, 26, 36, 3, 76, 70, 32, + 203, 170, 8, 78, 24, 216, 1, 6, 67, 73, 82, 67, 76, 69, 190, 167, 8, 66, + 90, 70, 34, 82, 128, 147, 8, 30, 73, 78, 86, 69, 82, 83, 69, 32, 77, 69, + 68, 73, 85, 77, 32, 83, 72, 65, 68, 69, 32, 65, 78, 68, 32, 82, 73, 71, + 72, 84, 139, 19, 77, 11, 33, 6, 32, 87, 73, 84, 72, 32, 8, 42, 84, 254, + 160, 17, 70, 175, 204, 1, 68, 4, 166, 187, 5, 72, 219, 180, 12, 87, 4, + 252, 148, 1, 2, 85, 71, 207, 147, 7, 79, 2, 161, 172, 18, 4, 85, 76, 84, + 73, 6, 214, 169, 8, 85, 215, 150, 8, 78, 30, 44, 5, 73, 71, 72, 84, 32, + 219, 170, 8, 65, 28, 152, 1, 5, 65, 82, 82, 79, 87, 132, 1, 12, 68, 79, + 85, 66, 76, 69, 32, 65, 82, 82, 79, 87, 30, 87, 218, 209, 8, 79, 234, + 215, 7, 66, 54, 83, 159, 53, 84, 11, 11, 32, 8, 72, 5, 87, 73, 84, 72, + 32, 193, 234, 17, 7, 84, 72, 82, 79, 85, 71, 72, 6, 146, 248, 15, 68, + 190, 145, 3, 86, 79, 83, 7, 197, 201, 8, 2, 32, 87, 4, 202, 220, 8, 65, + 255, 248, 7, 72, 34, 238, 168, 8, 45, 70, 69, 78, 73, 168, 1, 3, 80, 69, + 69, 26, 81, 227, 2, 85, 18, 58, 82, 246, 173, 8, 72, 178, 178, 7, 79, + 179, 169, 2, 65, 6, 40, 4, 73, 65, 78, 71, 143, 175, 8, 65, 4, 208, 227, + 4, 8, 76, 69, 32, 66, 69, 83, 73, 68, 235, 230, 11, 85, 16, 174, 177, 8, + 72, 202, 1, 73, 141, 246, 9, 2, 82, 73, 30, 90, 83, 230, 178, 8, 70, 206, + 1, 72, 130, 1, 80, 189, 3, 7, 84, 79, 45, 82, 73, 71, 72, 4, 44, 5, 73, + 68, 69, 32, 65, 171, 183, 8, 72, 2, 209, 138, 1, 2, 82, 67, 208, 1, 172, + 1, 5, 65, 82, 82, 79, 87, 134, 5, 66, 70, 72, 134, 4, 84, 178, 2, 87, + 230, 182, 8, 68, 210, 1, 70, 222, 7, 76, 26, 79, 34, 80, 50, 82, 70, 83, + 134, 136, 8, 67, 47, 81, 71, 26, 32, 247, 134, 17, 45, 66, 102, 65, 138, + 1, 84, 132, 2, 5, 87, 73, 84, 72, 32, 238, 184, 8, 70, 173, 215, 9, 4, + 79, 86, 69, 82, 12, 44, 5, 66, 79, 86, 69, 32, 219, 186, 8, 78, 10, 64, + 4, 83, 72, 79, 82, 210, 185, 8, 82, 202, 208, 4, 65, 55, 84, 2, 175, 146, + 18, 84, 12, 56, 7, 72, 82, 79, 85, 71, 72, 32, 53, 3, 79, 32, 66, 6, 242, + 135, 13, 83, 134, 155, 4, 76, 223, 142, 2, 88, 6, 32, 2, 65, 82, 199, + 187, 8, 76, 5, 221, 128, 12, 23, 32, 79, 86, 69, 82, 32, 82, 73, 71, 72, + 84, 87, 65, 82, 68, 83, 32, 65, 82, 82, 79, 87, 32, 36, 154, 188, 8, 68, + 98, 76, 38, 80, 30, 83, 38, 84, 210, 139, 8, 77, 38, 78, 122, 69, 226, + 148, 1, 72, 155, 160, 1, 86, 8, 194, 189, 8, 65, 224, 10, 5, 79, 84, 84, + 79, 77, 251, 129, 8, 76, 30, 26, 65, 163, 207, 16, 69, 26, 48, 6, 82, 80, + 79, 79, 78, 32, 243, 231, 18, 78, 24, 100, 10, 87, 73, 84, 72, 32, 66, + 65, 82, 66, 32, 213, 191, 8, 9, 79, 86, 69, 82, 32, 82, 73, 71, 72, 22, + 40, 4, 68, 79, 87, 78, 117, 2, 85, 80, 10, 26, 32, 251, 212, 16, 87, 8, + 226, 192, 8, 66, 188, 2, 7, 65, 66, 79, 86, 69, 32, 82, 130, 138, 8, 70, + 175, 5, 84, 12, 26, 32, 135, 212, 16, 87, 10, 60, 6, 65, 66, 79, 86, 69, + 32, 238, 203, 16, 70, 175, 5, 84, 6, 42, 76, 205, 192, 8, 4, 82, 73, 71, + 72, 4, 242, 190, 8, 69, 207, 201, 4, 79, 54, 44, 2, 82, 73, 194, 196, 8, + 79, 159, 5, 87, 34, 44, 5, 65, 78, 71, 76, 69, 247, 200, 8, 80, 30, 56, + 8, 45, 72, 69, 65, 68, 69, 68, 32, 243, 218, 16, 32, 28, 52, 5, 65, 82, + 82, 79, 87, 210, 210, 16, 68, 39, 80, 25, 11, 32, 22, 184, 197, 8, 9, 79, + 86, 69, 82, 32, 82, 73, 71, 72, 22, 87, 155, 137, 8, 84, 6, 26, 72, 131, + 203, 8, 65, 4, 45, 9, 73, 84, 69, 32, 65, 82, 82, 79, 87, 5, 165, 216, + 16, 2, 32, 87, 5, 215, 144, 18, 80, 148, 1, 252, 1, 15, 67, 79, 78, 83, + 79, 78, 65, 78, 84, 32, 83, 73, 71, 78, 32, 124, 7, 76, 69, 84, 84, 69, + 82, 32, 236, 1, 12, 80, 85, 78, 67, 84, 85, 65, 84, 73, 79, 78, 32, 198, + 1, 83, 172, 1, 11, 86, 79, 87, 69, 76, 32, 83, 73, 71, 78, 32, 175, 177, + 17, 68, 18, 66, 75, 22, 78, 202, 164, 19, 76, 2, 77, 2, 80, 2, 82, 3, 84, + 5, 239, 211, 18, 65, 5, 145, 170, 12, 4, 89, 73, 78, 45, 78, 194, 1, 75, + 2, 80, 198, 134, 7, 68, 250, 149, 10, 66, 2, 70, 2, 71, 2, 72, 2, 77, + 254, 14, 78, 202, 175, 1, 84, 46, 67, 2, 83, 254, 68, 74, 2, 76, 2, 82, + 2, 86, 2, 87, 2, 89, 187, 2, 65, 6, 166, 160, 19, 72, 2, 76, 187, 2, 65, + 10, 82, 84, 40, 14, 78, 89, 69, 84, 32, 84, 72, 89, 79, 79, 77, 32, 84, + 65, 43, 67, 6, 38, 65, 21, 5, 83, 72, 79, 79, 75, 2, 255, 233, 6, 45, 5, + 17, 2, 32, 67, 2, 149, 220, 14, 3, 69, 82, 45, 8, 92, 4, 73, 71, 78, 32, + 37, 15, 85, 66, 74, 79, 73, 78, 69, 68, 32, 76, 69, 84, 84, 69, 82, 4, + 202, 186, 15, 78, 151, 158, 2, 82, 4, 11, 32, 4, 170, 157, 19, 82, 3, 89, + 14, 170, 208, 15, 85, 158, 144, 1, 79, 202, 188, 2, 65, 186, 2, 69, 3, + 73, 52, 138, 1, 65, 128, 4, 11, 69, 81, 85, 65, 76, 32, 84, 79, 32, 79, + 82, 200, 1, 2, 66, 85, 42, 67, 186, 1, 79, 210, 2, 87, 175, 141, 18, 83, + 16, 40, 5, 66, 79, 86, 69, 32, 171, 4, 78, 12, 152, 1, 7, 71, 82, 69, 65, + 84, 69, 82, 110, 83, 176, 1, 19, 68, 79, 85, 66, 76, 69, 45, 76, 73, 78, + 69, 32, 69, 81, 85, 65, 76, 32, 65, 207, 170, 15, 76, 2, 181, 5, 23, 45, + 84, 72, 65, 78, 32, 65, 66, 79, 86, 69, 32, 68, 79, 85, 66, 76, 69, 45, + 76, 73, 78, 69, 6, 152, 1, 7, 73, 77, 73, 76, 65, 82, 32, 93, 26, 76, 65, + 78, 84, 69, 68, 32, 69, 81, 85, 65, 76, 32, 65, 66, 79, 86, 69, 32, 71, + 82, 69, 65, 84, 69, 82, 4, 18, 65, 59, 79, 2, 25, 4, 66, 79, 86, 69, 2, + 241, 138, 17, 2, 32, 71, 2, 227, 2, 82, 2, 145, 2, 6, 45, 84, 72, 65, 78, + 32, 4, 17, 2, 68, 32, 4, 220, 3, 5, 78, 79, 84, 32, 65, 129, 238, 12, 11, + 83, 73, 78, 71, 76, 69, 45, 76, 73, 78, 69, 4, 253, 215, 12, 5, 84, 32, + 78, 79, 84, 4, 65, 14, 76, 79, 83, 69, 68, 32, 66, 89, 32, 67, 85, 82, + 86, 69, 5, 11, 32, 2, 61, 13, 65, 66, 79, 86, 69, 32, 83, 76, 65, 78, 84, + 69, 68, 2, 17, 2, 32, 69, 2, 183, 186, 14, 81, 18, 40, 2, 82, 32, 193, + 190, 11, 2, 86, 69, 16, 114, 65, 48, 16, 83, 76, 65, 78, 84, 69, 68, 32, + 69, 81, 85, 65, 76, 32, 84, 79, 230, 212, 12, 69, 155, 177, 4, 71, 2, + 201, 154, 9, 7, 80, 80, 82, 79, 88, 73, 77, 9, 49, 10, 32, 87, 73, 84, + 72, 32, 68, 79, 84, 32, 6, 26, 65, 175, 170, 11, 73, 4, 25, 4, 66, 79, + 86, 69, 5, 139, 198, 17, 32, 6, 25, 4, 73, 84, 72, 32, 6, 66, 67, 40, 8, + 81, 85, 69, 83, 84, 73, 79, 78, 203, 194, 18, 68, 2, 133, 169, 11, 5, 73, + 82, 67, 76, 69, 2, 17, 2, 32, 77, 2, 17, 2, 65, 82, 2, 215, 149, 18, 75, + 136, 11, 190, 1, 71, 186, 5, 77, 162, 7, 78, 168, 65, 2, 80, 83, 20, 3, + 83, 85, 32, 130, 135, 15, 82, 152, 34, 11, 86, 82, 69, 32, 84, 79, 85, + 82, 78, 79, 73, 234, 44, 79, 130, 214, 1, 90, 175, 82, 66, 44, 26, 65, + 57, 2, 72, 84, 2, 165, 142, 9, 9, 84, 85, 82, 69, 32, 79, 80, 69, 78, 42, + 38, 32, 137, 4, 4, 78, 73, 78, 71, 36, 146, 1, 69, 38, 70, 126, 82, 40, + 3, 76, 69, 70, 86, 83, 42, 84, 152, 184, 7, 3, 66, 76, 85, 134, 224, 8, + 87, 134, 36, 86, 214, 74, 71, 195, 68, 67, 2, 201, 253, 16, 4, 73, 71, + 72, 84, 8, 94, 73, 201, 201, 17, 17, 79, 85, 82, 32, 80, 79, 73, 78, 84, + 69, 68, 32, 66, 76, 65, 67, 75, 4, 221, 249, 16, 2, 86, 69, 4, 36, 3, 73, + 71, 72, 171, 224, 16, 65, 2, 241, 230, 1, 16, 84, 32, 84, 79, 82, 84, 79, + 73, 83, 69, 32, 83, 72, 69, 76, 76, 6, 138, 157, 16, 72, 242, 93, 65, 43, + 73, 4, 216, 216, 15, 2, 87, 69, 21, 3, 72, 82, 69, 7, 29, 5, 32, 77, 79, + 79, 68, 5, 163, 130, 8, 32, 138, 1, 80, 3, 66, 85, 32, 229, 136, 8, 11, + 73, 84, 69, 68, 32, 76, 73, 65, 66, 73, 76, 136, 1, 128, 1, 7, 76, 69, + 84, 84, 69, 82, 32, 218, 1, 83, 200, 2, 5, 86, 79, 87, 69, 76, 206, 173, + 12, 69, 190, 141, 4, 81, 155, 92, 68, 60, 166, 1, 71, 174, 254, 5, 84, + 174, 192, 8, 89, 214, 122, 78, 134, 135, 3, 83, 82, 66, 2, 67, 2, 68, 2, + 74, 2, 75, 2, 80, 254, 68, 72, 2, 76, 2, 77, 2, 82, 3, 87, 6, 254, 192, + 17, 89, 254, 196, 1, 72, 187, 2, 65, 32, 108, 4, 73, 71, 78, 32, 128, 1, + 12, 77, 65, 76, 76, 32, 76, 69, 84, 84, 69, 82, 32, 193, 236, 6, 2, 85, + 66, 8, 72, 3, 75, 69, 77, 0, 3, 77, 85, 75, 32, 2, 83, 65, 227, 197, 16, + 76, 2, 149, 202, 16, 3, 80, 72, 82, 2, 207, 242, 18, 45, 18, 138, 183, + 15, 78, 158, 138, 3, 65, 182, 66, 75, 2, 76, 2, 77, 2, 80, 2, 82, 3, 84, + 20, 84, 6, 32, 83, 73, 71, 78, 32, 253, 82, 10, 45, 67, 65, 82, 82, 73, + 69, 82, 32, 76, 18, 142, 199, 5, 65, 214, 254, 10, 79, 238, 254, 1, 69, + 150, 64, 73, 3, 85, 226, 8, 22, 69, 199, 64, 75, 222, 8, 34, 32, 177, 3, + 3, 65, 82, 32, 14, 120, 12, 73, 78, 84, 69, 71, 82, 65, 84, 73, 79, 78, + 32, 190, 240, 12, 70, 178, 249, 2, 83, 193, 130, 1, 4, 84, 65, 66, 85, 6, + 108, 5, 87, 73, 84, 72, 32, 157, 1, 17, 78, 79, 84, 32, 73, 78, 67, 76, + 85, 68, 73, 78, 71, 32, 84, 72, 69, 4, 76, 7, 82, 69, 67, 84, 65, 78, 71, + 1, 8, 83, 69, 77, 73, 67, 73, 82, 67, 2, 73, 16, 85, 76, 65, 82, 32, 80, + 65, 84, 72, 32, 65, 82, 79, 85, 78, 68, 2, 17, 2, 32, 80, 2, 151, 223, + 17, 79, 208, 8, 60, 8, 65, 32, 83, 73, 71, 78, 32, 65, 221, 24, 2, 66, + 32, 170, 5, 122, 49, 86, 51, 202, 2, 52, 214, 1, 53, 158, 4, 54, 142, 3, + 55, 148, 4, 2, 56, 48, 78, 66, 201, 179, 17, 3, 48, 50, 56, 6, 140, 155, + 12, 5, 48, 48, 45, 49, 48, 176, 169, 5, 2, 50, 48, 197, 19, 2, 51, 49, + 150, 1, 78, 48, 90, 49, 130, 1, 55, 210, 241, 13, 50, 2, 51, 2, 52, 2, + 53, 3, 54, 22, 178, 1, 57, 138, 252, 18, 49, 2, 50, 2, 51, 2, 52, 2, 53, + 2, 54, 2, 55, 3, 56, 24, 90, 51, 138, 252, 18, 48, 2, 49, 2, 50, 2, 52, + 2, 53, 2, 54, 2, 55, 2, 56, 3, 57, 6, 134, 252, 18, 65, 2, 66, 3, 67, 4, + 226, 251, 18, 48, 3, 49, 38, 18, 48, 91, 49, 20, 162, 1, 48, 2, 49, 2, + 50, 2, 51, 2, 52, 2, 53, 2, 54, 2, 55, 2, 56, 3, 57, 18, 74, 48, 2, 49, + 2, 50, 2, 51, 2, 52, 2, 53, 2, 54, 2, 55, 3, 56, 2, 161, 164, 6, 2, 45, + 86, 160, 1, 102, 48, 78, 49, 62, 51, 86, 52, 70, 53, 86, 54, 206, 11, 50, + 250, 159, 2, 57, 190, 192, 11, 55, 3, 56, 16, 134, 249, 18, 49, 2, 50, 2, + 51, 2, 52, 2, 53, 2, 54, 2, 56, 3, 57, 12, 186, 248, 18, 48, 2, 49, 2, + 50, 2, 51, 2, 53, 3, 54, 18, 254, 247, 18, 48, 2, 49, 2, 50, 2, 52, 2, + 53, 2, 54, 2, 55, 2, 56, 3, 57, 14, 170, 247, 18, 48, 2, 49, 2, 50, 2, + 53, 2, 55, 2, 56, 3, 57, 18, 230, 246, 18, 48, 2, 49, 2, 50, 2, 51, 2, + 52, 2, 53, 2, 54, 2, 55, 3, 57, 12, 146, 246, 18, 51, 2, 52, 2, 53, 2, + 54, 2, 56, 3, 57, 104, 70, 48, 78, 50, 86, 51, 38, 52, 78, 54, 254, 230, + 13, 53, 243, 1, 49, 16, 142, 245, 18, 48, 2, 49, 2, 50, 2, 51, 2, 52, 2, + 54, 2, 56, 3, 57, 18, 194, 244, 18, 48, 2, 49, 2, 50, 2, 51, 2, 52, 2, + 54, 2, 55, 2, 56, 3, 57, 6, 238, 243, 18, 52, 2, 55, 3, 56, 16, 202, 243, + 18, 48, 2, 50, 2, 51, 2, 52, 2, 53, 2, 54, 2, 56, 3, 57, 10, 254, 242, + 18, 48, 2, 49, 2, 50, 2, 51, 3, 52, 44, 86, 48, 134, 2, 49, 140, 246, 1, + 2, 51, 50, 157, 232, 16, 6, 50, 54, 32, 69, 89, 89, 26, 110, 57, 194, + 193, 8, 55, 182, 6, 50, 62, 54, 218, 58, 52, 198, 148, 3, 51, 110, 56, + 202, 196, 2, 49, 215, 94, 53, 10, 26, 45, 207, 231, 17, 32, 8, 96, 2, 50, + 32, 212, 136, 12, 3, 54, 32, 76, 184, 2, 3, 52, 32, 76, 141, 145, 3, 3, + 51, 32, 76, 2, 175, 140, 12, 76, 14, 110, 49, 22, 51, 32, 3, 52, 32, 65, + 0, 2, 53, 32, 198, 147, 4, 50, 202, 181, 4, 48, 141, 209, 6, 2, 55, 32, + 2, 243, 226, 17, 32, 2, 11, 32, 2, 219, 238, 11, 79, 2, 167, 180, 17, 66, + 16, 182, 238, 18, 48, 2, 49, 2, 50, 2, 51, 2, 52, 2, 53, 2, 54, 3, 55, + 162, 1, 22, 48, 155, 5, 49, 140, 1, 82, 49, 54, 50, 118, 51, 62, 52, 78, + 53, 86, 54, 62, 55, 70, 56, 243, 220, 13, 48, 10, 246, 236, 18, 48, 2, + 49, 2, 51, 2, 54, 3, 55, 28, 86, 49, 2, 50, 194, 70, 51, 174, 165, 18, + 48, 2, 52, 2, 54, 2, 55, 2, 56, 3, 57, 7, 234, 235, 18, 70, 3, 77, 12, + 206, 235, 18, 48, 2, 49, 2, 52, 2, 55, 2, 56, 3, 57, 16, 146, 235, 18, + 48, 2, 49, 2, 52, 2, 53, 2, 54, 2, 55, 2, 56, 3, 57, 18, 198, 234, 18, + 48, 2, 49, 2, 51, 2, 52, 2, 53, 2, 54, 2, 55, 2, 56, 3, 57, 12, 242, 233, + 18, 48, 2, 49, 2, 53, 2, 54, 2, 55, 3, 57, 14, 182, 233, 18, 48, 2, 51, + 2, 52, 2, 54, 2, 55, 2, 56, 3, 57, 12, 242, 232, 18, 48, 2, 49, 2, 50, 2, + 53, 2, 54, 3, 55, 22, 82, 50, 36, 2, 51, 49, 30, 56, 226, 255, 11, 49, + 206, 2, 54, 146, 1, 55, 3, 57, 6, 226, 231, 18, 48, 2, 50, 3, 51, 4, 190, + 231, 18, 65, 3, 66, 4, 162, 231, 18, 48, 3, 56, 166, 3, 116, 9, 73, 68, + 69, 79, 71, 82, 65, 77, 32, 216, 17, 10, 77, 79, 78, 79, 71, 82, 65, 77, + 32, 66, 249, 1, 2, 83, 89, 234, 1, 54, 66, 249, 15, 8, 86, 69, 83, 83, + 69, 76, 32, 66, 176, 1, 22, 49, 255, 10, 50, 126, 86, 48, 210, 3, 50, + 162, 1, 51, 86, 52, 122, 53, 114, 54, 146, 1, 55, 118, 56, 71, 57, 28, + 114, 53, 98, 54, 58, 55, 78, 56, 62, 57, 148, 247, 6, 3, 50, 32, 87, 234, + 84, 48, 237, 215, 10, 4, 52, 32, 68, 69, 6, 252, 245, 6, 2, 32, 69, 188, + 205, 10, 3, 70, 32, 77, 245, 79, 7, 77, 32, 83, 84, 65, 76, 76, 4, 224, + 233, 1, 3, 70, 32, 69, 221, 191, 15, 2, 77, 32, 4, 36, 3, 70, 32, 83, 1, + 2, 77, 32, 2, 213, 195, 11, 4, 72, 69, 45, 71, 4, 228, 250, 8, 3, 77, 32, + 66, 145, 205, 8, 3, 70, 32, 83, 4, 148, 221, 16, 4, 77, 32, 66, 85, 165, + 106, 3, 70, 32, 67, 10, 236, 243, 8, 4, 51, 32, 83, 80, 224, 10, 5, 49, + 32, 66, 65, 82, 160, 218, 4, 4, 50, 32, 79, 76, 20, 6, 53, 32, 67, 89, + 80, 69, 209, 99, 4, 48, 32, 87, 72, 6, 54, 49, 192, 178, 16, 3, 48, 32, + 79, 247, 172, 2, 50, 2, 145, 198, 17, 2, 32, 87, 10, 224, 5, 3, 53, 32, + 87, 244, 241, 8, 6, 48, 32, 66, 82, 79, 78, 172, 2, 4, 49, 32, 71, 79, + 150, 229, 9, 50, 3, 54, 16, 82, 57, 150, 226, 2, 49, 186, 251, 15, 48, 2, + 50, 2, 51, 2, 52, 2, 55, 3, 56, 2, 253, 90, 3, 32, 67, 76, 20, 184, 246, + 13, 5, 51, 32, 65, 82, 77, 204, 163, 4, 5, 50, 32, 71, 65, 82, 170, 67, + 48, 2, 49, 2, 52, 2, 53, 2, 54, 2, 55, 2, 56, 3, 57, 18, 202, 198, 13, + 54, 196, 150, 3, 4, 51, 32, 77, 79, 146, 255, 1, 48, 2, 49, 2, 50, 2, 52, + 2, 55, 2, 56, 3, 57, 14, 170, 219, 18, 48, 2, 49, 2, 50, 2, 51, 2, 52, 2, + 53, 3, 57, 4, 240, 157, 2, 3, 49, 32, 72, 247, 188, 16, 48, 50, 42, 50, + 110, 51, 130, 1, 52, 227, 1, 53, 4, 84, 8, 48, 32, 70, 79, 79, 84, 83, + 84, 181, 196, 6, 7, 53, 32, 66, 65, 84, 72, 84, 2, 219, 198, 17, 79, 12, + 104, 4, 51, 32, 83, 87, 248, 211, 13, 4, 48, 32, 83, 80, 130, 234, 3, 49, + 190, 154, 1, 50, 2, 52, 3, 54, 2, 223, 193, 17, 79, 16, 168, 1, 9, 48, + 32, 87, 72, 69, 69, 76, 69, 68, 2, 49, 34, 51, 240, 202, 16, 12, 50, 32, + 67, 72, 65, 82, 73, 79, 84, 32, 70, 82, 230, 139, 2, 53, 2, 54, 2, 56, 3, + 57, 2, 133, 205, 17, 3, 32, 67, 72, 2, 183, 176, 6, 32, 18, 184, 207, 17, + 3, 52, 32, 68, 134, 135, 1, 49, 2, 50, 2, 51, 2, 53, 2, 54, 2, 55, 2, 56, + 3, 57, 58, 50, 50, 204, 239, 11, 2, 49, 53, 1, 2, 51, 48, 54, 50, 50, + 250, 241, 11, 53, 230, 216, 1, 48, 3, 49, 12, 238, 212, 18, 49, 2, 50, 2, + 54, 2, 55, 2, 56, 3, 57, 12, 46, 49, 153, 12, 6, 50, 52, 55, 32, 68, 73, + 10, 50, 50, 70, 51, 181, 11, 5, 53, 54, 32, 84, 85, 4, 252, 167, 3, 3, + 55, 32, 75, 197, 140, 15, 5, 56, 32, 75, 65, 78, 4, 56, 3, 53, 32, 77, + 241, 173, 15, 5, 51, 32, 65, 82, 69, 2, 231, 201, 11, 69, 176, 1, 84, 9, + 76, 76, 65, 66, 76, 69, 32, 66, 48, 229, 12, 7, 77, 66, 79, 76, 32, 66, + 48, 148, 1, 114, 48, 142, 1, 49, 162, 1, 50, 230, 1, 51, 174, 1, 52, 162, + 1, 53, 154, 1, 54, 186, 1, 55, 198, 1, 56, 87, 57, 18, 118, 54, 250, 191, + 1, 55, 150, 8, 52, 162, 14, 57, 138, 211, 10, 53, 186, 146, 2, 56, 226, + 10, 49, 254, 2, 50, 207, 8, 51, 2, 171, 149, 17, 32, 16, 122, 54, 18, 55, + 158, 201, 1, 49, 142, 2, 50, 158, 26, 52, 196, 186, 1, 2, 53, 32, 198, + 220, 5, 48, 177, 186, 8, 2, 51, 32, 2, 135, 84, 32, 2, 159, 232, 10, 32, + 18, 166, 1, 51, 22, 54, 20, 3, 57, 32, 80, 224, 6, 2, 53, 32, 136, 168, + 3, 2, 48, 32, 228, 253, 13, 2, 55, 32, 140, 7, 2, 52, 32, 146, 89, 56, + 173, 44, 3, 49, 32, 81, 2, 151, 250, 13, 32, 2, 151, 192, 14, 32, 2, 151, + 233, 11, 85, 16, 134, 1, 48, 20, 2, 51, 32, 254, 188, 1, 55, 254, 34, 54, + 194, 233, 4, 57, 138, 148, 2, 56, 210, 154, 4, 49, 185, 180, 5, 3, 50, + 32, 81, 2, 215, 251, 13, 32, 2, 135, 1, 82, 16, 116, 2, 51, 32, 22, 53, + 242, 184, 1, 48, 222, 1, 49, 134, 6, 50, 222, 10, 52, 146, 5, 54, 233, + 180, 12, 3, 56, 32, 78, 2, 199, 246, 14, 65, 2, 171, 189, 16, 32, 18, + 130, 1, 51, 162, 185, 1, 49, 150, 1, 56, 42, 57, 102, 55, 214, 5, 48, + 158, 140, 2, 52, 200, 210, 14, 2, 50, 32, 157, 4, 2, 53, 32, 2, 159, 192, + 11, 32, 16, 132, 1, 2, 50, 32, 20, 2, 56, 32, 204, 1, 3, 54, 32, 84, 150, + 180, 1, 55, 226, 3, 57, 146, 2, 53, 158, 228, 6, 49, 163, 221, 9, 48, 2, + 191, 131, 17, 80, 2, 129, 228, 11, 2, 82, 79, 18, 172, 1, 3, 54, 32, 82, + 182, 180, 1, 55, 158, 8, 48, 142, 16, 53, 12, 3, 49, 32, 68, 228, 145, 7, + 2, 52, 32, 214, 235, 3, 50, 152, 229, 5, 3, 56, 32, 81, 241, 2, 2, 51, + 32, 2, 183, 226, 11, 65, 8, 178, 180, 1, 49, 160, 24, 3, 55, 32, 84, 172, + 230, 6, 2, 53, 32, 211, 129, 6, 48, 4, 158, 184, 12, 49, 21, 3, 48, 32, + 68, 28, 90, 52, 30, 54, 30, 56, 186, 220, 11, 53, 158, 2, 49, 30, 51, + 166, 1, 50, 175, 144, 3, 55, 4, 158, 196, 18, 55, 3, 57, 4, 130, 196, 18, + 51, 3, 52, 8, 230, 195, 18, 50, 2, 51, 2, 54, 3, 57, 4, 156, 173, 10, 9, + 69, 68, 32, 80, 65, 80, 69, 82, 67, 155, 131, 7, 32, 5, 155, 148, 17, 84, + 98, 96, 7, 76, 69, 84, 84, 69, 82, 32, 253, 219, 6, 11, 80, 85, 78, 67, + 84, 85, 65, 84, 73, 79, 78, 94, 234, 1, 84, 186, 234, 2, 68, 226, 249, 9, + 85, 222, 140, 2, 69, 22, 78, 214, 135, 3, 67, 2, 71, 2, 72, 2, 75, 2, 80, + 2, 83, 2, 89, 2, 90, 162, 7, 65, 2, 79, 222, 61, 66, 2, 70, 2, 74, 2, 76, + 2, 77, 2, 87, 2, 88, 187, 2, 73, 20, 64, 4, 79, 78, 69, 32, 154, 248, 17, + 83, 254, 68, 72, 187, 2, 65, 12, 48, 4, 77, 89, 65, 32, 229, 185, 1, 2, + 78, 65, 10, 174, 227, 3, 74, 246, 188, 14, 66, 158, 11, 84, 254, 16, 67, + 39, 78, 208, 1, 244, 1, 2, 67, 75, 132, 1, 6, 71, 73, 67, 65, 76, 32, + 236, 3, 3, 78, 71, 32, 230, 4, 84, 116, 3, 86, 69, 32, 70, 87, 144, 8, 5, + 90, 69, 78, 71, 69, 218, 212, 7, 66, 220, 204, 9, 8, 85, 68, 76, 89, 32, + 67, 82, 89, 133, 15, 4, 76, 76, 73, 80, 9, 96, 10, 73, 78, 71, 45, 83, + 72, 73, 70, 84, 32, 149, 16, 9, 32, 87, 73, 84, 72, 32, 73, 78, 75, 4, + 210, 207, 16, 90, 143, 83, 79, 28, 36, 3, 65, 78, 68, 85, 2, 79, 82, 15, + 33, 6, 32, 87, 73, 84, 72, 32, 12, 226, 1, 68, 94, 72, 58, 77, 187, 239, + 14, 85, 15, 11, 32, 12, 88, 13, 79, 86, 69, 82, 76, 65, 80, 80, 73, 78, + 71, 32, 76, 49, 5, 87, 73, 84, 72, 32, 2, 129, 172, 17, 7, 79, 71, 73, + 67, 65, 76, 32, 10, 26, 68, 94, 72, 59, 77, 6, 11, 79, 6, 44, 5, 85, 66, + 76, 69, 32, 247, 187, 17, 84, 4, 142, 240, 14, 85, 167, 47, 79, 2, 149, + 144, 15, 9, 79, 82, 73, 90, 79, 78, 84, 65, 76, 2, 213, 196, 7, 5, 73, + 68, 68, 76, 69, 34, 66, 68, 236, 1, 4, 76, 69, 70, 84, 109, 5, 82, 73, + 71, 72, 84, 6, 172, 1, 30, 65, 83, 72, 32, 70, 82, 79, 77, 32, 76, 69, + 70, 84, 32, 77, 69, 77, 66, 69, 82, 32, 79, 70, 32, 68, 79, 85, 66, 76, + 69, 196, 180, 13, 2, 73, 86, 191, 217, 3, 82, 2, 17, 2, 32, 86, 2, 181, + 172, 17, 5, 69, 82, 84, 73, 67, 16, 18, 32, 119, 87, 6, 48, 6, 82, 73, + 71, 72, 84, 32, 215, 170, 15, 84, 4, 130, 165, 15, 68, 203, 245, 1, 65, + 12, 26, 87, 215, 216, 8, 32, 10, 29, 5, 65, 82, 68, 83, 32, 10, 82, 65, + 0, 8, 68, 79, 85, 66, 76, 69, 32, 65, 153, 205, 7, 4, 83, 81, 85, 73, 4, + 25, 4, 82, 82, 79, 87, 5, 233, 211, 15, 2, 32, 70, 6, 92, 5, 73, 79, 78, + 32, 66, 144, 153, 17, 9, 32, 79, 70, 32, 70, 79, 82, 84, 85, 199, 91, 85, + 2, 131, 209, 9, 79, 4, 38, 76, 145, 209, 13, 3, 72, 79, 84, 2, 153, 251, + 16, 2, 69, 84, 118, 34, 32, 229, 1, 3, 69, 82, 32, 14, 138, 1, 66, 140, + 169, 10, 11, 68, 79, 85, 66, 76, 69, 32, 80, 82, 73, 77, 214, 246, 5, 65, + 148, 109, 6, 75, 65, 86, 89, 75, 65, 139, 10, 76, 4, 38, 82, 149, 239, 4, + 3, 65, 84, 84, 2, 213, 156, 17, 7, 73, 71, 72, 84, 78, 69, 83, 104, 152, + 1, 5, 72, 65, 76, 70, 32, 92, 5, 76, 69, 70, 84, 32, 220, 2, 6, 82, 73, + 71, 72, 84, 32, 210, 164, 15, 66, 74, 70, 154, 9, 79, 150, 13, 83, 63, + 84, 8, 208, 137, 1, 7, 73, 78, 86, 69, 82, 83, 69, 238, 180, 14, 77, 162, + 7, 66, 195, 153, 1, 67, 40, 174, 1, 66, 60, 8, 70, 79, 85, 78, 84, 65, + 73, 78, 22, 80, 52, 12, 83, 69, 77, 73, 67, 73, 82, 67, 85, 76, 65, 82, + 202, 1, 84, 232, 166, 11, 3, 67, 82, 65, 147, 144, 4, 81, 24, 56, 8, 65, + 76, 76, 80, 79, 73, 78, 84, 227, 176, 15, 76, 2, 183, 215, 9, 32, 4, 176, + 203, 14, 5, 65, 73, 78, 84, 66, 171, 109, 69, 2, 177, 173, 7, 5, 32, 65, + 78, 84, 73, 40, 78, 83, 82, 84, 158, 168, 15, 66, 238, 3, 67, 130, 9, 68, + 206, 1, 80, 39, 81, 6, 172, 172, 7, 11, 69, 77, 73, 67, 73, 82, 67, 85, + 76, 65, 82, 131, 140, 8, 72, 4, 139, 185, 15, 82, 5, 149, 136, 17, 25, + 32, 68, 73, 86, 73, 68, 69, 68, 32, 66, 89, 32, 72, 79, 82, 73, 90, 79, + 78, 84, 65, 76, 32, 82, 85, 6, 18, 71, 23, 78, 2, 231, 205, 13, 71, 4, + 140, 134, 17, 5, 65, 82, 32, 69, 67, 191, 100, 71, 114, 104, 12, 67, 73, + 65, 78, 32, 76, 69, 84, 84, 69, 82, 32, 228, 1, 5, 68, 73, 65, 78, 32, + 159, 157, 17, 73, 58, 206, 1, 77, 194, 130, 5, 75, 142, 175, 9, 66, 50, + 84, 178, 251, 1, 65, 2, 69, 2, 78, 130, 248, 1, 68, 2, 71, 2, 72, 2, 73, + 2, 74, 2, 76, 2, 80, 2, 81, 2, 82, 2, 83, 2, 85, 2, 87, 2, 88, 3, 90, 5, + 171, 165, 18, 77, 54, 88, 7, 76, 69, 84, 84, 69, 82, 32, 253, 177, 14, 9, + 84, 82, 73, 65, 78, 71, 85, 76, 65, 52, 198, 239, 12, 84, 254, 193, 1, + 76, 154, 239, 1, 83, 226, 11, 65, 2, 69, 2, 78, 130, 248, 1, 66, 2, 67, + 2, 68, 2, 70, 2, 71, 2, 73, 2, 75, 2, 77, 2, 79, 2, 81, 2, 82, 2, 85, 2, + 86, 3, 89, 194, 53, 162, 1, 65, 242, 103, 69, 138, 103, 73, 254, 24, 79, + 136, 112, 3, 82, 79, 32, 234, 3, 85, 164, 70, 7, 89, 65, 78, 77, 65, 82, + 32, 246, 193, 14, 86, 186, 61, 77, 27, 87, 204, 23, 186, 1, 71, 62, 72, + 130, 11, 75, 234, 3, 76, 156, 14, 2, 77, 77, 22, 78, 150, 17, 80, 118, + 82, 174, 7, 83, 194, 7, 84, 196, 36, 3, 89, 65, 78, 132, 129, 1, 3, 88, + 73, 77, 243, 151, 15, 67, 6, 156, 146, 17, 4, 73, 67, 32, 87, 226, 88, + 78, 143, 53, 69, 166, 1, 84, 6, 65, 74, 65, 78, 73, 32, 133, 3, 10, 74, + 79, 78, 71, 32, 84, 73, 76, 69, 32, 78, 38, 76, 166, 2, 83, 167, 220, 12, + 65, 72, 88, 6, 69, 84, 84, 69, 82, 32, 137, 149, 11, 10, 73, 71, 65, 84, + 85, 82, 69, 32, 83, 72, 70, 202, 173, 3, 78, 138, 208, 10, 82, 242, 55, + 68, 46, 84, 206, 160, 3, 66, 2, 67, 2, 71, 2, 74, 2, 75, 2, 80, 254, 68, + 72, 2, 76, 2, 77, 2, 83, 2, 86, 186, 2, 65, 2, 69, 2, 73, 2, 79, 3, 85, + 4, 174, 227, 6, 69, 177, 211, 7, 5, 73, 71, 78, 32, 78, 88, 236, 1, 2, + 66, 65, 38, 69, 46, 70, 46, 78, 42, 79, 46, 80, 22, 83, 118, 84, 194, 1, + 87, 112, 5, 71, 82, 69, 69, 78, 0, 3, 82, 69, 68, 168, 128, 6, 3, 65, 85, + 84, 210, 21, 74, 141, 215, 10, 11, 67, 72, 82, 89, 83, 65, 78, 84, 72, + 69, 77, 4, 254, 173, 1, 77, 235, 232, 16, 67, 8, 228, 2, 4, 73, 71, 72, + 84, 195, 1, 65, 12, 172, 2, 2, 73, 86, 13, 3, 79, 85, 82, 8, 192, 1, 2, + 79, 82, 65, 2, 73, 78, 8, 218, 1, 78, 237, 197, 11, 3, 82, 67, 72, 2, + 187, 240, 16, 76, 18, 88, 2, 79, 85, 76, 4, 69, 86, 69, 78, 0, 2, 73, 88, + 162, 244, 11, 85, 235, 193, 1, 80, 2, 157, 2, 2, 84, 72, 12, 36, 3, 72, + 82, 69, 13, 2, 87, 79, 6, 11, 69, 6, 25, 4, 32, 79, 70, 32, 6, 46, 67, + 173, 238, 6, 5, 66, 65, 77, 66, 79, 4, 180, 132, 6, 2, 73, 82, 145, 148, + 10, 5, 72, 65, 82, 65, 67, 6, 50, 69, 60, 4, 72, 73, 84, 69, 163, 222, + 16, 73, 2, 17, 2, 83, 84, 2, 17, 2, 32, 87, 2, 171, 135, 17, 73, 2, 17, + 2, 32, 68, 2, 227, 221, 16, 82, 52, 52, 5, 65, 83, 65, 82, 32, 157, 206, + 14, 2, 69, 77, 50, 162, 1, 69, 40, 7, 76, 69, 84, 84, 69, 82, 32, 152, 1, + 5, 80, 65, 83, 83, 73, 32, 11, 86, 79, 87, 69, 76, 32, 83, 73, 71, 78, + 32, 173, 136, 18, 3, 65, 78, 71, 2, 213, 159, 15, 5, 78, 68, 32, 79, 70, + 36, 162, 155, 16, 78, 242, 244, 1, 66, 2, 67, 2, 68, 2, 71, 2, 74, 2, 75, + 2, 76, 2, 77, 2, 80, 2, 82, 2, 83, 2, 84, 2, 86, 2, 89, 187, 2, 65, 2, + 11, 77, 2, 227, 184, 17, 66, 8, 146, 145, 18, 69, 2, 73, 2, 79, 3, 85, + 246, 1, 80, 7, 65, 89, 65, 76, 65, 77, 32, 208, 11, 2, 69, 32, 225, 1, 3, + 84, 69, 83, 236, 1, 190, 1, 65, 22, 68, 44, 9, 70, 82, 65, 67, 84, 73, + 79, 78, 32, 240, 1, 7, 76, 69, 84, 84, 69, 82, 32, 164, 5, 7, 78, 85, 77, + 66, 69, 82, 32, 36, 5, 83, 73, 71, 78, 32, 143, 144, 13, 86, 2, 227, 142, + 13, 85, 22, 172, 146, 8, 2, 65, 84, 251, 141, 8, 73, 26, 56, 4, 79, 78, + 69, 32, 121, 6, 84, 72, 82, 69, 69, 32, 18, 82, 84, 142, 128, 5, 83, 202, + 219, 7, 70, 58, 79, 170, 176, 3, 69, 46, 72, 43, 81, 4, 254, 222, 12, 87, + 239, 174, 3, 69, 8, 166, 128, 5, 83, 174, 223, 7, 69, 110, 84, 163, 174, + 3, 81, 132, 1, 226, 1, 65, 82, 67, 158, 1, 68, 78, 84, 82, 86, 222, 221, + 12, 78, 230, 46, 76, 210, 90, 82, 130, 81, 85, 158, 144, 1, 79, 182, 56, + 73, 202, 190, 1, 83, 82, 66, 2, 71, 2, 74, 2, 75, 2, 80, 162, 7, 69, 222, + 61, 72, 2, 77, 3, 89, 11, 148, 206, 15, 7, 82, 67, 72, 65, 73, 67, 32, + 158, 188, 2, 65, 2, 73, 3, 85, 22, 26, 72, 203, 137, 18, 65, 20, 44, 5, + 73, 76, 76, 85, 32, 155, 137, 18, 65, 18, 226, 211, 12, 76, 182, 189, 3, + 78, 178, 191, 1, 82, 210, 56, 75, 2, 77, 3, 89, 10, 164, 198, 10, 4, 79, + 84, 32, 82, 238, 250, 6, 68, 254, 68, 72, 187, 2, 65, 10, 38, 84, 158, + 133, 18, 72, 187, 2, 65, 6, 154, 133, 18, 72, 2, 84, 187, 2, 65, 12, 250, + 225, 3, 69, 206, 193, 10, 79, 231, 227, 3, 65, 6, 158, 222, 12, 79, 231, + 215, 3, 84, 18, 50, 67, 114, 86, 194, 158, 14, 65, 179, 162, 3, 80, 6, + 54, 79, 120, 5, 73, 82, 67, 85, 76, 215, 158, 14, 65, 2, 185, 142, 13, 9, + 77, 66, 73, 78, 73, 78, 71, 32, 65, 6, 60, 9, 69, 82, 84, 73, 67, 65, 76, + 32, 66, 255, 193, 17, 73, 2, 17, 2, 65, 82, 2, 233, 163, 12, 2, 32, 86, + 8, 80, 12, 87, 73, 84, 72, 32, 83, 84, 82, 79, 75, 69, 32, 70, 65, 219, + 252, 16, 83, 4, 64, 10, 65, 78, 68, 32, 77, 65, 76, 69, 32, 65, 219, 252, + 16, 83, 2, 25, 4, 78, 68, 32, 70, 2, 11, 69, 2, 11, 77, 2, 199, 190, 7, + 65, 2, 231, 196, 16, 69, 2, 199, 131, 16, 79, 185, 1, 210, 1, 32, 220, 2, + 5, 68, 65, 73, 67, 32, 220, 3, 8, 73, 67, 72, 65, 69, 65, 78, 32, 222, 8, + 83, 200, 165, 2, 3, 85, 65, 76, 166, 181, 10, 65, 220, 168, 1, 8, 84, 69, + 76, 80, 73, 69, 67, 69, 147, 207, 3, 71, 12, 132, 1, 3, 73, 78, 32, 128, + 1, 5, 87, 73, 84, 72, 32, 196, 146, 2, 3, 68, 65, 78, 169, 194, 12, 8, + 65, 78, 68, 32, 87, 79, 77, 65, 4, 208, 240, 9, 19, 66, 85, 83, 73, 78, + 69, 83, 83, 32, 83, 85, 73, 84, 32, 76, 69, 86, 73, 84, 209, 148, 1, 4, + 84, 85, 88, 69, 4, 204, 195, 13, 8, 71, 85, 65, 32, 80, 73, 32, 77, 213, + 243, 2, 4, 84, 85, 82, 66, 58, 136, 1, 7, 76, 69, 84, 84, 69, 82, 32, + 230, 209, 10, 71, 176, 184, 3, 3, 86, 79, 67, 146, 70, 80, 177, 195, 2, + 6, 65, 70, 70, 82, 73, 67, 50, 82, 65, 176, 1, 2, 68, 85, 2, 85, 28, 3, + 72, 65, 76, 22, 73, 167, 180, 17, 75, 38, 154, 1, 75, 150, 198, 12, 84, + 226, 193, 1, 83, 194, 163, 3, 73, 214, 79, 66, 2, 68, 2, 71, 2, 72, 2, + 76, 2, 77, 2, 78, 2, 80, 2, 81, 2, 82, 3, 90, 5, 207, 248, 17, 83, 2, + 253, 239, 7, 2, 83, 72, 2, 159, 248, 17, 81, 4, 194, 250, 17, 78, 3, 84, + 102, 216, 1, 7, 76, 69, 84, 84, 69, 82, 32, 194, 4, 78, 80, 12, 80, 85, + 78, 67, 84, 85, 65, 84, 73, 79, 78, 32, 220, 1, 4, 83, 73, 71, 78, 185, + 172, 10, 16, 65, 66, 66, 82, 69, 86, 73, 65, 84, 73, 79, 78, 32, 77, 65, + 82, 72, 218, 1, 65, 46, 66, 38, 68, 30, 71, 30, 74, 2, 90, 30, 75, 30, + 81, 38, 83, 50, 84, 54, 88, 238, 154, 6, 76, 254, 194, 1, 82, 238, 213, + 2, 89, 154, 193, 1, 72, 166, 255, 4, 78, 254, 1, 87, 202, 103, 70, 2, 80, + 171, 4, 77, 6, 206, 180, 10, 76, 122, 65, 239, 193, 6, 89, 4, 238, 200, + 12, 72, 211, 174, 3, 69, 4, 206, 156, 6, 65, 23, 72, 4, 246, 179, 10, 72, + 15, 73, 4, 178, 180, 10, 72, 15, 65, 4, 246, 251, 11, 72, 15, 65, 4, 162, + 156, 6, 72, 199, 223, 5, 79, 8, 250, 176, 10, 83, 154, 3, 65, 191, 193, + 6, 72, 6, 158, 155, 6, 72, 186, 218, 9, 69, 247, 128, 1, 65, 4, 222, 250, + 11, 65, 3, 79, 10, 33, 6, 85, 77, 66, 69, 82, 32, 10, 186, 179, 10, 79, + 58, 84, 219, 183, 2, 70, 14, 80, 2, 68, 79, 116, 3, 76, 73, 78, 138, 159, + 5, 70, 142, 133, 11, 84, 255, 9, 83, 6, 54, 84, 13, 9, 85, 66, 76, 69, + 32, 68, 79, 84, 32, 5, 11, 32, 2, 25, 4, 87, 73, 84, 72, 2, 163, 192, 2, + 73, 2, 223, 201, 3, 69, 2, 159, 199, 16, 32, 2, 11, 32, 2, 221, 218, 17, + 2, 83, 72, 4, 92, 17, 32, 83, 89, 77, 66, 79, 76, 32, 70, 79, 82, 32, 76, + 73, 71, 72, 84, 175, 191, 10, 76, 2, 175, 193, 14, 72, 142, 1, 142, 1, + 65, 20, 5, 67, 72, 69, 78, 32, 160, 155, 6, 4, 82, 73, 65, 71, 165, 213, + 10, 13, 84, 73, 65, 76, 32, 65, 82, 84, 83, 32, 85, 78, 73, 2, 175, 153, + 5, 67, 136, 1, 152, 1, 7, 76, 69, 84, 84, 69, 82, 32, 194, 1, 83, 236, 2, + 11, 86, 79, 87, 69, 76, 32, 83, 73, 71, 78, 32, 154, 157, 17, 72, 225, 5, + 4, 77, 65, 82, 75, 60, 254, 3, 84, 146, 148, 2, 68, 178, 222, 13, 78, + 246, 175, 1, 67, 2, 75, 2, 80, 2, 83, 2, 90, 254, 68, 45, 2, 66, 2, 71, + 2, 72, 2, 74, 2, 76, 2, 77, 2, 82, 2, 87, 2, 89, 187, 2, 65, 62, 96, 4, + 73, 71, 78, 32, 37, 16, 85, 66, 74, 79, 73, 78, 69, 68, 32, 76, 69, 84, + 84, 69, 82, 32, 4, 154, 133, 14, 67, 191, 161, 3, 65, 58, 182, 1, 84, + 146, 148, 2, 68, 178, 222, 13, 78, 246, 175, 1, 67, 2, 75, 2, 80, 2, 83, + 2, 90, 254, 68, 66, 2, 71, 2, 72, 2, 74, 2, 76, 2, 77, 2, 82, 2, 87, 2, + 89, 187, 2, 65, 8, 178, 162, 17, 83, 254, 68, 72, 187, 2, 65, 10, 130, + 231, 17, 65, 186, 2, 69, 2, 73, 2, 79, 3, 85, 156, 1, 120, 11, 65, 82, + 65, 77, 32, 71, 79, 78, 68, 73, 32, 236, 5, 3, 67, 85, 76, 64, 5, 75, 32, + 87, 79, 82, 163, 160, 17, 85, 150, 1, 100, 7, 76, 69, 84, 84, 69, 82, 32, + 178, 2, 82, 56, 5, 83, 73, 71, 78, 32, 82, 86, 199, 245, 15, 68, 94, 210, + 1, 74, 42, 84, 206, 252, 13, 65, 38, 68, 146, 25, 85, 210, 200, 1, 73, + 42, 76, 210, 189, 1, 75, 38, 78, 46, 83, 82, 66, 2, 67, 2, 71, 2, 80, + 254, 68, 72, 2, 77, 2, 82, 2, 86, 2, 89, 186, 2, 69, 3, 79, 6, 230, 226, + 17, 78, 38, 72, 187, 2, 65, 10, 230, 157, 17, 84, 254, 68, 72, 2, 82, + 187, 2, 65, 4, 32, 2, 65, 45, 163, 240, 1, 69, 2, 131, 160, 17, 75, 10, + 174, 176, 1, 67, 202, 160, 12, 72, 242, 45, 78, 130, 182, 1, 86, 223, + 234, 1, 65, 22, 26, 79, 207, 177, 15, 73, 20, 45, 9, 87, 69, 76, 32, 83, + 73, 71, 78, 32, 20, 78, 86, 238, 253, 13, 65, 190, 21, 85, 210, 200, 1, + 73, 206, 134, 2, 69, 3, 79, 2, 201, 182, 7, 6, 79, 67, 65, 76, 73, 67, 2, + 253, 168, 17, 11, 73, 78, 69, 32, 79, 82, 68, 73, 78, 65, 76, 2, 199, + 206, 16, 75, 226, 15, 76, 10, 72, 69, 77, 65, 84, 73, 67, 65, 76, 32, + 129, 162, 14, 3, 69, 32, 68, 224, 15, 252, 1, 5, 66, 79, 76, 68, 32, 168, + 6, 14, 68, 79, 85, 66, 76, 69, 45, 83, 84, 82, 85, 67, 75, 32, 238, 1, + 70, 164, 2, 7, 73, 84, 65, 76, 73, 67, 32, 180, 3, 10, 77, 79, 78, 79, + 83, 80, 65, 67, 69, 32, 40, 2, 82, 73, 36, 3, 76, 69, 70, 167, 1, 83, + 160, 5, 176, 1, 8, 67, 65, 80, 73, 84, 65, 76, 32, 130, 2, 83, 210, 14, + 73, 222, 3, 69, 38, 75, 38, 78, 30, 80, 98, 82, 242, 5, 84, 56, 7, 70, + 82, 65, 75, 84, 85, 82, 131, 211, 15, 68, 104, 190, 4, 68, 174, 15, 84, + 186, 4, 65, 22, 66, 2, 90, 42, 69, 98, 71, 22, 73, 22, 75, 34, 76, 22, + 79, 50, 80, 42, 82, 22, 83, 70, 85, 250, 196, 1, 67, 214, 173, 12, 77, 2, + 78, 210, 200, 1, 88, 206, 134, 2, 70, 2, 72, 2, 74, 2, 81, 2, 86, 2, 87, + 3, 89, 208, 1, 60, 5, 77, 65, 76, 76, 32, 213, 25, 5, 67, 82, 73, 80, 84, + 104, 250, 1, 68, 230, 19, 65, 22, 66, 2, 90, 42, 69, 38, 70, 62, 71, 22, + 73, 22, 75, 34, 76, 22, 79, 50, 80, 42, 82, 22, 83, 34, 84, 38, 85, 250, + 196, 1, 67, 214, 173, 12, 77, 2, 78, 210, 200, 1, 88, 206, 134, 2, 72, 2, + 74, 2, 81, 2, 86, 2, 87, 3, 89, 7, 26, 73, 191, 180, 14, 69, 2, 167, 213, + 1, 71, 110, 68, 8, 67, 65, 80, 73, 84, 65, 76, 32, 162, 23, 83, 195, 210, + 15, 68, 38, 250, 215, 17, 65, 2, 66, 2, 68, 2, 69, 2, 70, 2, 71, 2, 73, + 2, 74, 2, 75, 2, 76, 2, 77, 2, 79, 2, 83, 2, 84, 2, 85, 2, 86, 2, 87, 2, + 88, 3, 89, 96, 52, 7, 82, 65, 75, 84, 85, 82, 32, 139, 252, 6, 65, 94, + 52, 8, 67, 65, 80, 73, 84, 65, 76, 32, 143, 21, 83, 42, 230, 213, 17, 65, + 2, 66, 2, 68, 2, 69, 2, 70, 2, 71, 2, 74, 2, 75, 2, 76, 2, 77, 2, 78, 2, + 79, 2, 80, 2, 81, 2, 83, 2, 84, 2, 85, 2, 86, 2, 87, 2, 88, 3, 89, 222, + 1, 100, 6, 83, 77, 65, 76, 76, 32, 222, 7, 67, 230, 2, 69, 38, 75, 38, + 78, 30, 80, 98, 82, 243, 5, 84, 104, 242, 1, 68, 198, 12, 65, 22, 66, 2, + 90, 42, 69, 38, 70, 62, 71, 22, 73, 22, 75, 34, 76, 22, 79, 50, 80, 42, + 82, 22, 83, 34, 84, 38, 85, 250, 196, 1, 67, 214, 173, 12, 77, 2, 78, + 210, 200, 1, 88, 206, 134, 2, 74, 2, 81, 2, 86, 2, 87, 3, 89, 9, 52, 7, + 79, 84, 76, 69, 83, 83, 32, 131, 173, 14, 69, 4, 154, 209, 17, 73, 3, 74, + 124, 130, 16, 67, 34, 83, 195, 210, 15, 68, 12, 32, 2, 71, 72, 179, 246, + 6, 83, 10, 17, 2, 84, 32, 10, 112, 6, 87, 72, 73, 84, 69, 32, 170, 236, + 5, 68, 234, 99, 65, 197, 164, 7, 9, 70, 76, 65, 84, 84, 69, 78, 69, 68, + 4, 254, 246, 13, 83, 39, 84, 130, 6, 84, 10, 65, 78, 83, 45, 83, 69, 82, + 73, 70, 32, 133, 14, 6, 67, 82, 73, 80, 84, 32, 176, 5, 96, 5, 66, 79, + 76, 68, 32, 176, 12, 6, 73, 84, 65, 76, 73, 67, 34, 67, 34, 83, 195, 210, + 15, 68, 204, 3, 98, 73, 122, 67, 230, 2, 69, 38, 75, 38, 78, 30, 80, 98, + 82, 30, 83, 214, 5, 84, 187, 211, 15, 68, 220, 1, 33, 6, 84, 65, 76, 73, + 67, 32, 220, 1, 74, 67, 230, 2, 69, 38, 75, 38, 78, 30, 80, 98, 82, 30, + 83, 215, 5, 84, 102, 37, 7, 65, 80, 73, 84, 65, 76, 32, 102, 250, 1, 84, + 186, 4, 65, 22, 66, 2, 90, 22, 68, 22, 69, 98, 71, 22, 73, 22, 75, 34, + 76, 22, 79, 50, 80, 42, 82, 22, 83, 70, 85, 250, 196, 1, 67, 214, 173, + 12, 77, 2, 78, 210, 200, 1, 88, 206, 134, 2, 70, 2, 72, 2, 74, 2, 81, 2, + 86, 2, 87, 3, 89, 9, 40, 4, 72, 69, 84, 65, 183, 164, 17, 65, 5, 151, + 182, 16, 32, 2, 185, 212, 15, 4, 80, 83, 73, 76, 2, 17, 2, 65, 80, 2, + 159, 7, 80, 2, 165, 166, 17, 2, 65, 66, 6, 74, 72, 168, 141, 5, 8, 65, + 82, 84, 73, 65, 76, 32, 68, 163, 167, 11, 73, 2, 199, 180, 16, 73, 2, + 177, 180, 16, 2, 72, 79, 102, 29, 5, 77, 65, 76, 76, 32, 102, 246, 1, 65, + 22, 66, 2, 90, 22, 68, 22, 69, 38, 70, 62, 71, 22, 73, 22, 75, 34, 76, + 22, 79, 50, 80, 42, 82, 22, 83, 34, 84, 38, 85, 250, 196, 1, 67, 214, + 173, 12, 77, 2, 78, 210, 200, 1, 88, 206, 134, 2, 72, 2, 74, 2, 81, 2, + 86, 2, 87, 3, 89, 5, 235, 208, 1, 76, 5, 175, 160, 17, 69, 5, 203, 160, + 14, 69, 7, 178, 212, 1, 80, 235, 237, 15, 84, 5, 11, 73, 2, 29, 5, 78, + 65, 76, 32, 83, 2, 227, 1, 73, 5, 219, 248, 14, 65, 5, 147, 159, 17, 79, + 5, 11, 65, 2, 223, 158, 14, 80, 5, 143, 160, 14, 65, 7, 11, 77, 4, 230, + 170, 1, 73, 239, 213, 15, 69, 9, 142, 175, 17, 72, 2, 83, 219, 19, 73, 5, + 203, 163, 17, 72, 5, 11, 73, 2, 143, 161, 17, 71, 7, 190, 157, 14, 72, + 231, 255, 2, 65, 5, 199, 209, 1, 80, 2, 11, 72, 2, 11, 69, 2, 11, 84, 2, + 159, 174, 16, 65, 104, 11, 32, 104, 18, 67, 35, 83, 52, 53, 5, 65, 80, + 73, 84, 65, 52, 21, 3, 77, 65, 76, 52, 183, 216, 11, 76, 82, 76, 8, 67, + 65, 80, 73, 84, 65, 76, 32, 157, 1, 6, 83, 77, 65, 76, 76, 32, 36, 222, + 191, 17, 65, 2, 67, 2, 68, 2, 71, 2, 74, 2, 75, 2, 78, 2, 79, 2, 80, 2, + 81, 2, 83, 2, 84, 2, 85, 2, 86, 2, 87, 2, 88, 2, 89, 3, 90, 46, 194, 190, + 17, 65, 2, 66, 2, 67, 2, 68, 2, 70, 2, 72, 2, 73, 2, 74, 2, 75, 2, 76, 2, + 77, 2, 78, 2, 80, 2, 81, 2, 82, 2, 83, 2, 84, 2, 85, 2, 86, 2, 87, 2, 88, + 2, 89, 3, 90, 40, 45, 9, 32, 78, 85, 77, 69, 82, 65, 76, 32, 40, 70, 69, + 66, 70, 70, 78, 26, 83, 66, 84, 142, 206, 15, 90, 143, 83, 79, 6, 40, 4, + 73, 71, 72, 84, 243, 224, 9, 76, 5, 231, 234, 15, 69, 8, 30, 73, 105, 3, + 79, 85, 82, 4, 202, 254, 4, 70, 139, 166, 12, 86, 4, 65, 3, 73, 78, 69, + 8, 40, 4, 69, 86, 69, 78, 1, 2, 73, 88, 5, 191, 233, 15, 84, 10, 42, 72, + 190, 224, 9, 87, 243, 137, 7, 69, 4, 150, 253, 4, 73, 183, 208, 10, 82, + 248, 8, 234, 1, 65, 192, 4, 9, 67, 72, 65, 78, 73, 67, 65, 76, 32, 34, + 68, 180, 15, 11, 69, 84, 69, 73, 32, 77, 65, 89, 69, 75, 32, 178, 11, 76, + 34, 78, 162, 50, 82, 172, 15, 8, 83, 83, 65, 71, 69, 32, 87, 65, 20, 2, + 84, 82, 183, 183, 16, 77, 26, 72, 6, 83, 85, 82, 69, 68, 32, 249, 141, + 16, 6, 84, 32, 79, 78, 32, 66, 24, 96, 5, 65, 78, 71, 76, 69, 200, 247, + 9, 9, 82, 73, 71, 72, 84, 32, 65, 78, 71, 175, 173, 7, 66, 21, 11, 32, + 18, 212, 1, 39, 87, 73, 84, 72, 32, 79, 80, 69, 78, 32, 65, 82, 77, 32, + 69, 78, 68, 73, 78, 71, 32, 73, 78, 32, 65, 82, 82, 79, 87, 32, 80, 79, + 73, 78, 84, 73, 78, 71, 32, 161, 130, 17, 7, 79, 80, 69, 78, 73, 78, 71, + 16, 62, 68, 24, 3, 76, 69, 70, 0, 4, 82, 73, 71, 72, 43, 85, 4, 73, 3, + 79, 87, 78, 4, 173, 249, 7, 5, 84, 32, 65, 78, 68, 4, 11, 80, 4, 145, + 190, 11, 3, 32, 65, 78, 4, 254, 180, 16, 65, 211, 56, 76, 250, 1, 56, 9, + 69, 70, 65, 73, 68, 82, 73, 78, 32, 159, 7, 73, 190, 1, 174, 1, 67, 52, + 6, 68, 73, 71, 73, 84, 32, 152, 1, 7, 78, 85, 77, 66, 69, 82, 32, 114, + 83, 132, 255, 6, 12, 69, 88, 67, 76, 65, 77, 65, 84, 73, 79, 78, 32, 215, + 228, 7, 70, 70, 128, 3, 5, 65, 80, 73, 84, 65, 255, 226, 14, 79, 26, 82, + 84, 48, 2, 79, 78, 194, 194, 15, 70, 30, 83, 102, 90, 130, 83, 78, 211, + 110, 69, 8, 44, 3, 72, 82, 69, 209, 176, 16, 2, 87, 79, 4, 207, 176, 16, + 69, 20, 50, 84, 226, 240, 4, 69, 46, 70, 42, 78, 31, 83, 6, 162, 242, 4, + 72, 204, 227, 4, 2, 87, 69, 215, 137, 7, 69, 70, 68, 3, 77, 65, 76, 217, + 183, 9, 8, 89, 77, 66, 79, 76, 32, 65, 73, 68, 45, 9, 76, 32, 76, 69, 84, + 84, 69, 82, 32, 68, 242, 1, 65, 38, 78, 146, 221, 3, 72, 2, 75, 162, 255, + 9, 89, 138, 143, 3, 79, 150, 64, 66, 2, 67, 2, 68, 2, 69, 2, 70, 2, 71, + 2, 73, 2, 74, 2, 76, 2, 77, 2, 80, 2, 81, 2, 82, 2, 83, 2, 84, 2, 85, 2, + 86, 2, 87, 2, 88, 3, 90, 7, 162, 237, 3, 84, 207, 190, 13, 73, 7, 202, + 171, 17, 71, 3, 89, 60, 48, 5, 69, 86, 65, 76, 32, 45, 3, 85, 77, 32, 6, + 138, 211, 10, 69, 206, 140, 4, 67, 115, 81, 54, 210, 1, 66, 46, 70, 164, + 1, 3, 76, 69, 70, 0, 4, 82, 73, 71, 72, 248, 1, 11, 77, 65, 84, 72, 69, + 77, 65, 84, 73, 67, 65, 22, 83, 104, 4, 84, 72, 82, 69, 186, 212, 14, 86, + 230, 59, 69, 166, 4, 87, 207, 10, 71, 4, 164, 4, 3, 79, 76, 68, 163, 201, + 13, 76, 10, 84, 9, 76, 65, 84, 84, 69, 78, 69, 68, 32, 204, 3, 3, 79, 85, + 82, 219, 145, 15, 73, 4, 44, 3, 76, 69, 70, 1, 4, 82, 73, 71, 72, 2, 213, + 1, 3, 84, 32, 80, 6, 11, 84, 6, 78, 32, 41, 15, 45, 80, 79, 73, 78, 84, + 73, 78, 71, 32, 65, 78, 71, 76, 69, 4, 36, 5, 67, 85, 82, 76, 89, 59, 80, + 2, 17, 2, 32, 66, 2, 237, 163, 7, 4, 82, 65, 67, 75, 2, 153, 226, 16, 10, + 65, 82, 69, 78, 84, 72, 69, 83, 73, 83, 2, 251, 230, 16, 76, 10, 72, 4, + 77, 65, 76, 76, 154, 181, 14, 72, 188, 91, 2, 73, 88, 183, 2, 65, 2, 133, + 162, 14, 2, 32, 87, 4, 11, 69, 4, 45, 9, 32, 80, 79, 73, 78, 84, 69, 68, + 32, 4, 206, 179, 9, 80, 151, 221, 5, 66, 158, 1, 146, 1, 65, 104, 6, 67, + 72, 69, 73, 75, 72, 34, 76, 144, 6, 8, 83, 89, 76, 76, 65, 66, 76, 69, 0, + 4, 87, 79, 82, 68, 50, 86, 223, 172, 15, 68, 6, 80, 8, 72, 65, 78, 71, + 32, 75, 72, 85, 164, 6, 3, 80, 85, 78, 155, 177, 13, 78, 2, 175, 232, 15, + 68, 4, 130, 210, 16, 65, 255, 59, 69, 94, 52, 6, 69, 84, 84, 69, 82, 32, + 185, 5, 2, 85, 77, 92, 250, 1, 66, 36, 2, 67, 72, 38, 68, 50, 71, 38, 74, + 34, 75, 42, 78, 62, 80, 30, 83, 42, 84, 54, 73, 0, 3, 76, 65, 73, 0, 3, + 77, 73, 84, 230, 210, 12, 72, 166, 10, 82, 2, 87, 188, 144, 2, 2, 65, 84, + 230, 213, 1, 89, 242, 8, 85, 214, 79, 69, 3, 79, 4, 198, 229, 15, 72, + 191, 185, 1, 65, 4, 194, 149, 16, 73, 159, 137, 1, 65, 8, 238, 141, 10, + 72, 178, 135, 6, 73, 235, 65, 68, 4, 190, 141, 10, 72, 183, 141, 7, 79, + 4, 170, 228, 15, 72, 163, 48, 73, 6, 216, 1, 2, 79, 75, 163, 139, 10, 72, + 12, 178, 1, 65, 0, 3, 71, 79, 85, 182, 153, 17, 78, 3, 89, 6, 118, 65, + 179, 226, 15, 72, 6, 238, 139, 17, 65, 162, 14, 72, 3, 83, 10, 48, 2, 73, + 76, 162, 139, 10, 72, 155, 201, 6, 84, 5, 157, 177, 1, 4, 32, 76, 79, 78, + 2, 161, 152, 17, 3, 32, 73, 89, 2, 141, 178, 16, 7, 32, 82, 69, 80, 69, + 84, 73, 30, 64, 10, 79, 87, 69, 76, 32, 83, 73, 71, 78, 32, 191, 232, 14, + 73, 28, 130, 1, 65, 44, 4, 67, 72, 69, 73, 2, 79, 0, 3, 83, 79, 85, 0, 2, + 89, 69, 22, 73, 38, 85, 206, 231, 10, 78, 187, 129, 4, 86, 8, 218, 136, + 16, 78, 170, 80, 65, 175, 64, 85, 2, 175, 136, 16, 78, 4, 154, 136, 16, + 78, 215, 144, 1, 73, 4, 246, 135, 16, 78, 215, 144, 1, 85, 4, 158, 144, + 16, 84, 183, 56, 79, 174, 3, 160, 1, 11, 68, 69, 32, 75, 73, 75, 65, 75, + 85, 73, 32, 244, 130, 16, 20, 79, 82, 65, 72, 32, 87, 73, 84, 72, 32, 78, + 73, 78, 69, 32, 66, 82, 65, 78, 67, 95, 83, 170, 3, 148, 1, 17, 67, 79, + 77, 66, 73, 78, 73, 78, 71, 32, 78, 85, 77, 66, 69, 82, 32, 164, 1, 10, + 83, 89, 76, 76, 65, 66, 76, 69, 32, 77, 199, 144, 9, 68, 14, 62, 84, 56, + 7, 72, 85, 78, 68, 82, 69, 68, 243, 177, 4, 77, 8, 26, 69, 187, 178, 4, + 72, 6, 26, 78, 187, 230, 13, 69, 4, 140, 178, 4, 2, 32, 84, 191, 226, 12, + 83, 138, 3, 22, 48, 167, 21, 49, 198, 1, 118, 48, 250, 1, 49, 210, 1, 50, + 138, 2, 51, 254, 1, 52, 150, 2, 53, 158, 2, 54, 238, 1, 55, 142, 2, 56, + 187, 2, 57, 18, 142, 1, 49, 34, 50, 22, 51, 22, 52, 218, 149, 2, 53, 142, + 230, 3, 56, 180, 149, 10, 3, 57, 32, 77, 92, 3, 55, 32, 77, 213, 90, 3, + 54, 32, 87, 2, 11, 32, 2, 147, 254, 16, 75, 2, 239, 136, 17, 32, 2, 183, + 239, 11, 32, 2, 11, 32, 2, 203, 253, 16, 87, 20, 130, 1, 49, 22, 54, 18, + 56, 22, 57, 200, 28, 2, 48, 32, 138, 161, 7, 53, 130, 190, 5, 52, 226, + 10, 55, 222, 9, 50, 199, 191, 3, 51, 2, 227, 226, 16, 32, 2, 143, 25, 32, + 2, 139, 170, 13, 32, 2, 191, 209, 12, 32, 20, 106, 49, 22, 50, 22, 51, + 22, 52, 22, 53, 22, 54, 22, 55, 22, 57, 158, 186, 11, 48, 253, 232, 1, 2, + 56, 32, 2, 155, 144, 10, 32, 2, 195, 234, 9, 32, 2, 223, 233, 16, 32, 2, + 215, 233, 11, 32, 2, 131, 191, 12, 32, 2, 215, 235, 16, 32, 2, 143, 185, + 12, 32, 2, 191, 28, 32, 20, 174, 1, 48, 16, 2, 49, 32, 20, 2, 52, 32, 20, + 2, 56, 32, 230, 186, 4, 57, 238, 51, 50, 22, 53, 188, 201, 7, 2, 54, 32, + 244, 211, 3, 3, 55, 32, 78, 213, 90, 3, 51, 32, 89, 2, 187, 37, 32, 2, + 159, 248, 16, 89, 2, 139, 248, 16, 70, 2, 155, 196, 15, 78, 20, 184, 1, + 2, 48, 32, 20, 2, 51, 32, 30, 53, 22, 56, 164, 8, 3, 52, 32, 75, 252, 21, + 3, 54, 32, 72, 230, 2, 55, 170, 205, 4, 49, 212, 164, 4, 3, 57, 32, 87, + 245, 181, 5, 3, 50, 32, 72, 2, 203, 157, 15, 72, 2, 177, 199, 16, 2, 78, + 71, 2, 223, 252, 10, 32, 2, 187, 234, 16, 32, 20, 178, 1, 48, 18, 53, 20, + 2, 54, 32, 20, 2, 56, 32, 22, 57, 172, 190, 9, 2, 50, 32, 236, 4, 2, 51, + 32, 166, 200, 1, 49, 164, 187, 3, 3, 52, 32, 76, 213, 137, 1, 3, 55, 32, + 78, 2, 143, 4, 32, 2, 183, 195, 15, 32, 2, 167, 218, 16, 71, 2, 227, 236, + 12, 78, 2, 177, 182, 15, 2, 32, 77, 20, 192, 1, 2, 50, 32, 22, 54, 242, + 25, 51, 164, 2, 3, 55, 32, 78, 52, 3, 49, 32, 87, 156, 215, 1, 2, 52, 32, + 206, 143, 3, 56, 156, 255, 4, 3, 48, 32, 78, 174, 92, 57, 137, 186, 4, 3, + 53, 32, 75, 2, 159, 216, 16, 77, 2, 195, 254, 9, 32, 20, 184, 1, 3, 52, + 32, 75, 20, 2, 53, 32, 20, 2, 55, 32, 22, 57, 178, 9, 51, 234, 11, 50, + 144, 2, 3, 49, 32, 71, 40, 3, 48, 32, 71, 144, 171, 14, 3, 54, 32, 75, + 149, 84, 3, 56, 32, 70, 2, 251, 222, 16, 80, 2, 251, 236, 16, 70, 2, 199, + 228, 16, 86, 2, 139, 171, 8, 32, 20, 228, 1, 2, 48, 32, 20, 2, 49, 32, + 20, 2, 52, 32, 22, 53, 248, 13, 6, 54, 32, 76, 79, 78, 71, 152, 12, 2, + 57, 32, 160, 167, 3, 3, 51, 32, 72, 132, 252, 8, 4, 50, 32, 78, 71, 164, + 195, 3, 3, 55, 32, 72, 165, 97, 3, 56, 32, 70, 2, 215, 234, 16, 89, 2, + 227, 148, 15, 80, 2, 207, 148, 15, 76, 2, 171, 132, 16, 32, 20, 230, 1, + 53, 164, 14, 4, 48, 32, 78, 71, 172, 8, 3, 51, 32, 71, 244, 243, 11, 2, + 55, 32, 214, 118, 57, 252, 88, 3, 50, 32, 75, 172, 184, 1, 3, 49, 32, 84, + 192, 27, 4, 56, 32, 78, 89, 148, 129, 1, 3, 52, 32, 77, 213, 34, 2, 54, + 32, 2, 155, 207, 16, 32, 196, 1, 118, 48, 154, 2, 49, 210, 2, 50, 170, 2, + 51, 222, 1, 52, 162, 2, 53, 214, 2, 54, 166, 2, 55, 238, 2, 56, 231, 2, + 57, 20, 222, 1, 49, 30, 52, 172, 11, 6, 54, 32, 76, 79, 78, 71, 164, 4, + 6, 53, 32, 76, 79, 78, 71, 24, 2, 51, 32, 162, 229, 4, 50, 230, 152, 2, + 48, 204, 249, 4, 3, 55, 32, 71, 252, 135, 3, 3, 57, 32, 89, 197, 39, 3, + 56, 32, 75, 2, 205, 180, 15, 2, 32, 70, 2, 157, 187, 14, 2, 32, 84, 20, + 208, 1, 6, 48, 32, 76, 79, 78, 71, 22, 51, 34, 54, 22, 56, 32, 2, 57, 32, + 156, 18, 4, 53, 32, 78, 71, 224, 206, 2, 2, 55, 32, 192, 145, 2, 3, 50, + 32, 75, 140, 198, 9, 3, 52, 32, 87, 145, 254, 1, 2, 49, 32, 2, 211, 216, + 15, 32, 2, 11, 32, 2, 131, 227, 16, 74, 2, 207, 240, 15, 32, 2, 11, 32, + 2, 207, 226, 16, 87, 2, 155, 236, 14, 78, 20, 230, 1, 50, 32, 2, 51, 32, + 232, 3, 3, 52, 32, 71, 182, 10, 48, 220, 147, 7, 2, 57, 32, 176, 196, 2, + 4, 56, 32, 72, 79, 248, 207, 2, 5, 55, 32, 78, 71, 71, 236, 90, 2, 53, + 32, 180, 249, 1, 3, 54, 32, 87, 129, 148, 1, 2, 49, 32, 2, 11, 32, 2, + 203, 247, 12, 77, 2, 11, 78, 2, 143, 227, 16, 68, 20, 172, 8, 3, 52, 32, + 78, 204, 2, 2, 56, 32, 224, 233, 4, 3, 50, 32, 75, 194, 195, 2, 49, 2, + 53, 216, 173, 2, 2, 55, 32, 152, 208, 4, 3, 51, 32, 70, 0, 3, 54, 32, 83, + 164, 50, 2, 48, 32, 225, 145, 1, 3, 57, 32, 87, 20, 232, 1, 3, 53, 32, + 77, 22, 54, 224, 2, 3, 57, 32, 78, 172, 4, 6, 50, 32, 76, 79, 78, 71, + 130, 196, 6, 55, 140, 151, 3, 3, 51, 32, 87, 200, 212, 2, 2, 48, 32, 220, + 60, 3, 56, 32, 71, 244, 190, 1, 3, 49, 32, 89, 1, 3, 52, 32, 86, 2, 179, + 223, 16, 66, 2, 129, 191, 15, 3, 32, 78, 71, 20, 192, 1, 2, 50, 32, 34, + 52, 26, 53, 34, 54, 36, 2, 55, 32, 244, 7, 2, 48, 32, 180, 225, 9, 3, 56, + 32, 75, 148, 182, 2, 2, 49, 32, 148, 225, 2, 5, 57, 32, 78, 71, 71, 249, + 204, 1, 2, 51, 32, 2, 11, 78, 2, 207, 238, 16, 74, 2, 213, 5, 2, 32, 77, + 2, 11, 32, 2, 247, 220, 16, 71, 2, 241, 175, 14, 4, 32, 78, 71, 71, 2, + 227, 131, 15, 74, 20, 220, 1, 2, 48, 32, 20, 6, 49, 32, 76, 79, 78, 71, + 30, 56, 204, 2, 2, 55, 32, 128, 170, 9, 3, 52, 32, 78, 200, 48, 4, 54, + 32, 71, 85, 152, 208, 4, 2, 53, 32, 148, 84, 3, 50, 32, 83, 0, 2, 51, 32, + 185, 98, 2, 57, 32, 2, 219, 173, 14, 74, 2, 221, 249, 11, 2, 32, 77, 2, + 183, 170, 12, 32, 20, 198, 1, 50, 46, 52, 40, 6, 53, 32, 76, 79, 78, 71, + 28, 3, 55, 32, 78, 34, 56, 152, 199, 11, 2, 54, 32, 156, 99, 3, 57, 32, + 75, 160, 212, 2, 3, 51, 32, 86, 156, 108, 4, 48, 32, 78, 89, 207, 53, 49, + 2, 11, 32, 2, 11, 77, 2, 183, 171, 14, 66, 2, 17, 2, 32, 77, 2, 227, 204, + 16, 66, 2, 205, 204, 16, 2, 32, 74, 2, 11, 71, 2, 231, 163, 15, 85, 2, + 147, 154, 15, 32, 20, 208, 1, 2, 48, 32, 22, 49, 22, 50, 32, 6, 51, 32, + 76, 79, 78, 71, 34, 56, 252, 241, 8, 2, 53, 32, 152, 126, 3, 52, 32, 78, + 188, 182, 2, 2, 54, 32, 228, 210, 2, 4, 55, 32, 77, 66, 145, 30, 4, 57, + 32, 77, 85, 2, 215, 168, 14, 68, 2, 215, 238, 9, 32, 2, 11, 32, 2, 147, + 213, 16, 86, 2, 253, 222, 14, 3, 32, 78, 71, 2, 17, 2, 32, 77, 2, 239, + 251, 14, 66, 16, 142, 1, 48, 32, 3, 49, 32, 78, 20, 3, 50, 32, 78, 20, 2, + 51, 32, 20, 3, 52, 32, 87, 22, 53, 20, 2, 54, 32, 169, 165, 12, 3, 55, + 32, 70, 2, 11, 32, 2, 191, 250, 14, 71, 2, 171, 250, 14, 68, 2, 227, 193, + 16, 74, 2, 215, 150, 16, 72, 2, 203, 210, 16, 85, 2, 219, 158, 15, 32, 2, + 227, 144, 1, 83, 248, 1, 68, 6, 79, 73, 84, 73, 67, 32, 250, 145, 10, 80, + 241, 70, 2, 67, 85, 244, 1, 104, 8, 67, 85, 82, 83, 73, 86, 69, 32, 221, + 10, 13, 72, 73, 69, 82, 79, 71, 76, 89, 80, 72, 73, 67, 32, 180, 1, 96, + 9, 70, 82, 65, 67, 84, 73, 79, 78, 32, 250, 2, 76, 133, 3, 7, 78, 85, 77, + 66, 69, 82, 32, 24, 78, 69, 50, 70, 44, 4, 79, 78, 69, 32, 46, 83, 50, + 84, 61, 3, 78, 73, 78, 4, 160, 1, 2, 76, 69, 93, 4, 73, 71, 72, 84, 4, + 192, 1, 2, 73, 86, 13, 3, 79, 85, 82, 4, 232, 225, 14, 4, 84, 87, 69, 76, + 19, 72, 4, 26, 69, 93, 2, 73, 88, 2, 65, 2, 86, 69, 6, 46, 69, 12, 3, 72, + 82, 69, 13, 2, 87, 79, 2, 23, 78, 2, 11, 69, 2, 197, 227, 14, 5, 32, 84, + 87, 69, 76, 52, 76, 6, 69, 84, 84, 69, 82, 32, 137, 2, 8, 79, 71, 79, 71, + 82, 65, 77, 32, 48, 182, 1, 65, 46, 84, 146, 234, 1, 78, 2, 83, 206, 252, + 12, 72, 138, 176, 1, 75, 254, 68, 66, 2, 68, 2, 76, 2, 77, 2, 80, 2, 81, + 2, 82, 2, 87, 2, 89, 186, 2, 69, 2, 73, 3, 79, 5, 149, 139, 11, 6, 82, + 67, 72, 65, 73, 67, 6, 150, 222, 16, 65, 2, 69, 3, 79, 4, 174, 201, 4, + 73, 153, 248, 11, 2, 82, 77, 104, 92, 5, 69, 73, 71, 72, 84, 30, 70, 92, + 4, 78, 73, 78, 69, 54, 83, 78, 84, 73, 2, 79, 78, 11, 150, 1, 89, 223, 1, + 32, 24, 18, 73, 35, 79, 12, 142, 2, 86, 139, 228, 3, 70, 12, 148, 2, 2, + 85, 82, 227, 227, 3, 82, 11, 28, 2, 84, 89, 223, 1, 32, 2, 231, 141, 6, + 32, 24, 40, 4, 69, 86, 69, 78, 1, 2, 73, 88, 13, 154, 1, 32, 227, 227, 3, + 84, 28, 34, 72, 50, 87, 159, 140, 6, 69, 12, 32, 2, 82, 69, 215, 227, 3, + 73, 8, 39, 69, 12, 26, 79, 215, 227, 3, 69, 9, 11, 32, 6, 194, 138, 6, + 72, 171, 167, 5, 84, 64, 96, 7, 76, 69, 84, 84, 69, 82, 32, 229, 160, 3, + 11, 83, 89, 77, 66, 79, 76, 32, 86, 73, 68, 74, 60, 174, 1, 66, 2, 82, + 22, 78, 30, 83, 38, 84, 174, 223, 14, 72, 138, 176, 1, 75, 254, 68, 68, + 2, 76, 2, 77, 2, 80, 2, 81, 2, 87, 2, 89, 186, 2, 65, 2, 69, 2, 73, 3, + 79, 4, 179, 159, 3, 65, 8, 158, 159, 3, 65, 3, 69, 6, 130, 159, 3, 65, + 139, 184, 13, 69, 10, 222, 158, 3, 65, 2, 69, 139, 184, 13, 79, 2, 175, + 252, 11, 73, 20, 44, 5, 73, 67, 65, 76, 32, 251, 213, 16, 79, 18, 116, + 10, 76, 79, 78, 71, 32, 79, 86, 69, 82, 32, 74, 80, 26, 84, 168, 1, 7, + 83, 72, 79, 82, 84, 32, 79, 187, 32, 66, 4, 188, 244, 2, 2, 83, 72, 185, + 180, 10, 7, 84, 87, 79, 32, 83, 72, 79, 2, 109, 3, 69, 78, 84, 8, 66, 69, + 34, 82, 41, 10, 87, 79, 32, 83, 72, 79, 82, 84, 83, 32, 2, 17, 2, 84, 82, + 2, 23, 65, 2, 11, 73, 2, 217, 187, 15, 2, 83, 69, 4, 26, 79, 179, 231, 7, + 74, 2, 137, 162, 10, 4, 86, 69, 82, 32, 224, 2, 100, 3, 65, 79, 32, 136, + 18, 2, 67, 82, 142, 1, 68, 118, 76, 130, 1, 78, 245, 2, 4, 82, 82, 79, + 82, 170, 2, 156, 1, 7, 76, 69, 84, 84, 69, 82, 32, 180, 10, 5, 83, 73, + 71, 78, 32, 212, 1, 5, 84, 79, 78, 69, 32, 69, 11, 86, 79, 87, 69, 76, + 32, 83, 73, 71, 78, 32, 178, 1, 214, 1, 65, 110, 66, 34, 68, 106, 71, 34, + 76, 50, 78, 106, 82, 170, 1, 83, 54, 84, 218, 1, 86, 32, 3, 89, 73, 32, + 118, 90, 238, 247, 12, 81, 230, 200, 1, 80, 242, 190, 1, 72, 2, 77, 254, + 68, 70, 2, 75, 2, 87, 3, 88, 10, 52, 7, 82, 67, 72, 65, 73, 67, 32, 179, + 206, 16, 72, 8, 254, 231, 8, 90, 170, 151, 4, 78, 211, 204, 3, 77, 4, + 162, 186, 16, 82, 219, 19, 65, 16, 50, 90, 154, 4, 76, 218, 198, 16, 68, + 187, 2, 65, 8, 206, 185, 16, 89, 162, 17, 72, 2, 90, 187, 2, 65, 6, 190, + 133, 16, 72, 183, 71, 65, 8, 238, 150, 10, 72, 174, 179, 6, 89, 187, 2, + 65, 18, 54, 65, 186, 132, 16, 71, 2, 78, 2, 89, 255, 68, 72, 5, 11, 83, + 2, 169, 159, 13, 4, 65, 76, 73, 90, 16, 60, 9, 69, 70, 79, 82, 77, 69, + 68, 32, 84, 171, 180, 16, 84, 14, 40, 4, 79, 78, 69, 45, 151, 211, 14, + 83, 12, 206, 202, 16, 49, 2, 50, 2, 52, 2, 53, 2, 54, 3, 56, 8, 186, 182, + 16, 89, 162, 17, 72, 2, 83, 187, 2, 65, 32, 78, 76, 20, 4, 79, 78, 69, + 45, 70, 83, 130, 198, 16, 84, 186, 2, 65, 3, 69, 4, 171, 147, 10, 72, 14, + 250, 200, 16, 50, 2, 51, 2, 52, 2, 53, 2, 54, 2, 55, 3, 56, 8, 254, 197, + 16, 72, 2, 83, 186, 2, 65, 3, 69, 4, 206, 197, 16, 70, 187, 2, 65, 16, + 70, 84, 228, 207, 14, 2, 68, 90, 250, 60, 78, 142, 184, 1, 75, 3, 80, 8, + 234, 255, 15, 83, 254, 68, 84, 187, 2, 65, 16, 50, 90, 142, 255, 15, 83, + 254, 68, 72, 187, 2, 65, 8, 218, 144, 10, 83, 174, 179, 6, 89, 187, 2, + 65, 8, 144, 1, 9, 82, 69, 70, 79, 82, 77, 69, 68, 32, 34, 65, 145, 245, + 13, 18, 67, 79, 78, 83, 79, 78, 65, 78, 84, 32, 77, 79, 68, 73, 70, 73, + 69, 82, 4, 30, 65, 189, 88, 2, 86, 79, 2, 225, 230, 11, 3, 83, 80, 73, 8, + 130, 172, 14, 66, 168, 74, 3, 84, 79, 80, 182, 81, 65, 143, 82, 82, 104, + 146, 1, 65, 78, 69, 62, 73, 78, 79, 74, 85, 74, 89, 180, 250, 6, 9, 82, + 79, 85, 78, 68, 69, 68, 32, 69, 206, 134, 7, 87, 238, 70, 78, 135, 122, + 86, 19, 206, 202, 14, 78, 130, 184, 1, 69, 134, 63, 72, 146, 1, 65, 2, + 73, 3, 85, 15, 242, 222, 12, 82, 146, 235, 1, 78, 150, 248, 1, 65, 3, 73, + 23, 186, 201, 14, 65, 54, 79, 154, 247, 1, 78, 86, 69, 2, 71, 2, 73, 3, + 85, 13, 42, 69, 230, 192, 16, 71, 2, 79, 3, 85, 4, 226, 192, 16, 82, 3, + 89, 19, 166, 200, 14, 65, 202, 228, 1, 69, 134, 19, 78, 2, 79, 86, 73, 3, + 85, 7, 166, 172, 16, 85, 219, 19, 73, 12, 18, 32, 63, 79, 4, 172, 172, + 15, 4, 79, 78, 32, 85, 13, 4, 68, 65, 83, 72, 8, 190, 189, 11, 83, 158, + 216, 3, 80, 218, 34, 32, 139, 112, 66, 6, 64, 4, 68, 76, 69, 32, 173, + 215, 4, 6, 76, 73, 78, 69, 32, 72, 4, 152, 180, 5, 3, 84, 72, 73, 203, + 185, 10, 68, 8, 76, 6, 73, 84, 65, 82, 89, 32, 172, 153, 10, 3, 75, 89, + 32, 255, 156, 5, 76, 4, 26, 72, 187, 134, 12, 77, 2, 163, 170, 4, 69, 24, + 42, 73, 76, 2, 85, 83, 235, 187, 16, 89, 6, 34, 68, 22, 77, 147, 185, 14, + 66, 2, 195, 137, 6, 73, 2, 187, 212, 6, 73, 16, 46, 32, 201, 142, 10, 5, + 45, 79, 82, 45, 80, 14, 40, 4, 83, 73, 71, 78, 231, 249, 12, 84, 13, 11, + 32, 10, 44, 5, 87, 73, 84, 72, 32, 239, 153, 6, 73, 8, 66, 67, 182, 195, + 4, 68, 206, 135, 8, 82, 21, 4, 70, 65, 76, 76, 2, 129, 195, 11, 3, 79, + 77, 77, 5, 163, 181, 14, 32, 182, 9, 184, 1, 10, 66, 73, 76, 69, 32, 80, + 72, 79, 78, 69, 166, 1, 68, 190, 76, 78, 174, 27, 79, 156, 1, 3, 83, 81, + 85, 38, 84, 250, 1, 85, 242, 140, 11, 89, 217, 178, 2, 5, 86, 73, 69, 32, + 67, 7, 11, 32, 4, 108, 21, 87, 73, 84, 72, 32, 82, 73, 71, 72, 84, 87, + 65, 82, 68, 83, 32, 65, 82, 82, 79, 87, 255, 177, 1, 79, 2, 11, 32, 2, + 213, 132, 16, 2, 65, 84, 154, 6, 58, 69, 74, 73, 149, 75, 7, 85, 76, 79, + 32, 84, 87, 79, 4, 196, 230, 15, 10, 82, 78, 32, 80, 69, 78, 84, 65, 84, + 72, 159, 18, 76, 148, 6, 42, 32, 221, 1, 5, 70, 73, 69, 82, 32, 158, 1, + 88, 5, 83, 73, 71, 78, 32, 210, 172, 3, 86, 178, 146, 3, 68, 182, 1, 76, + 167, 180, 4, 65, 10, 42, 65, 234, 189, 8, 72, 203, 179, 7, 86, 4, 44, 5, + 82, 68, 72, 65, 67, 163, 239, 15, 78, 2, 201, 239, 15, 3, 65, 78, 68, + 246, 4, 92, 12, 66, 82, 69, 86, 69, 32, 87, 73, 84, 72, 32, 73, 89, 7, + 76, 69, 84, 84, 69, 82, 32, 2, 33, 6, 78, 86, 69, 82, 84, 69, 2, 21, 3, + 68, 32, 66, 2, 249, 181, 15, 2, 82, 69, 244, 4, 198, 1, 65, 82, 66, 66, + 67, 190, 13, 68, 194, 1, 69, 182, 2, 71, 82, 72, 46, 76, 230, 4, 77, 216, + 3, 7, 79, 80, 69, 78, 32, 83, 72, 22, 80, 38, 82, 182, 4, 83, 214, 33, + 84, 114, 85, 118, 86, 63, 89, 6, 38, 76, 150, 27, 67, 183, 167, 10, 80, + 2, 237, 19, 6, 86, 69, 79, 76, 65, 82, 6, 176, 19, 5, 73, 76, 65, 66, 73, + 201, 45, 4, 69, 71, 73, 78, 160, 1, 240, 1, 7, 65, 80, 73, 84, 65, 76, + 32, 192, 2, 7, 69, 78, 84, 82, 69, 68, 32, 100, 13, 72, 73, 78, 69, 83, + 69, 32, 84, 79, 78, 69, 32, 89, 108, 8, 89, 82, 73, 76, 76, 73, 67, 32, + 166, 188, 10, 73, 244, 2, 4, 82, 79, 83, 83, 191, 154, 5, 79, 56, 206, 1, + 66, 42, 82, 250, 26, 72, 198, 193, 12, 79, 138, 143, 3, 65, 150, 64, 67, + 2, 68, 2, 69, 2, 70, 2, 71, 2, 73, 2, 74, 2, 75, 2, 76, 2, 77, 2, 78, 2, + 80, 2, 81, 2, 84, 2, 85, 2, 86, 3, 87, 5, 237, 130, 6, 5, 65, 82, 82, 69, + 68, 7, 41, 8, 69, 86, 69, 82, 83, 69, 68, 32, 4, 170, 171, 16, 69, 3, 78, + 4, 30, 76, 21, 3, 82, 73, 71, 2, 29, 2, 69, 70, 2, 11, 72, 2, 11, 84, 2, + 173, 26, 2, 32, 72, 16, 36, 3, 65, 78, 71, 1, 2, 73, 78, 8, 11, 32, 8, + 170, 226, 11, 83, 214, 246, 3, 80, 146, 44, 81, 3, 82, 78, 34, 72, 30, + 83, 175, 217, 15, 69, 2, 197, 195, 14, 2, 65, 82, 74, 40, 5, 77, 65, 76, + 76, 32, 183, 6, 79, 72, 186, 1, 66, 138, 1, 68, 38, 69, 150, 1, 80, 58, + 83, 94, 84, 34, 89, 158, 163, 15, 90, 246, 63, 73, 138, 19, 67, 2, 71, + 186, 22, 74, 2, 86, 158, 20, 72, 2, 75, 186, 2, 65, 2, 79, 3, 85, 6, 38, + 89, 186, 27, 65, 187, 139, 16, 69, 2, 221, 201, 1, 19, 69, 76, 79, 82, + 85, 83, 83, 73, 65, 78, 45, 85, 75, 82, 65, 73, 78, 73, 65, 4, 206, 190, + 6, 90, 195, 231, 9, 69, 15, 50, 83, 186, 165, 16, 70, 2, 76, 2, 77, 3, + 82, 5, 25, 4, 32, 87, 73, 84, 2, 21, 3, 72, 32, 68, 2, 11, 69, 2, 205, + 223, 12, 3, 83, 67, 69, 4, 26, 65, 191, 164, 16, 69, 2, 241, 247, 15, 2, + 76, 79, 8, 42, 84, 198, 172, 1, 67, 251, 244, 14, 72, 4, 145, 19, 8, 82, + 65, 73, 71, 72, 84, 32, 85, 4, 238, 140, 16, 83, 215, 22, 69, 6, 36, 3, + 69, 82, 85, 255, 162, 16, 85, 5, 37, 7, 32, 87, 73, 84, 72, 32, 66, 2, + 21, 3, 65, 67, 75, 2, 217, 228, 15, 2, 32, 89, 2, 191, 139, 11, 70, 16, + 18, 69, 27, 79, 2, 161, 5, 2, 78, 84, 14, 64, 2, 84, 32, 44, 5, 85, 66, + 76, 69, 32, 137, 52, 2, 87, 78, 6, 178, 192, 9, 83, 194, 144, 4, 72, 43, + 86, 4, 254, 135, 2, 65, 215, 240, 2, 80, 24, 40, 5, 88, 84, 82, 65, 45, + 139, 49, 78, 20, 52, 5, 72, 73, 71, 72, 32, 81, 4, 76, 79, 87, 32, 10, + 156, 1, 9, 69, 88, 84, 82, 65, 45, 76, 79, 87, 154, 7, 68, 70, 76, 79, + 84, 10, 76, 10, 69, 88, 84, 82, 65, 45, 72, 73, 71, 72, 154, 7, 68, 70, + 76, 79, 84, 2, 145, 8, 8, 32, 67, 79, 78, 84, 79, 85, 82, 8, 162, 9, 82, + 226, 3, 76, 237, 238, 14, 9, 69, 79, 82, 71, 73, 65, 78, 32, 78, 10, 248, + 5, 4, 73, 71, 72, 32, 135, 41, 65, 44, 46, 65, 84, 2, 79, 87, 201, 11, 2, + 69, 70, 2, 21, 3, 84, 69, 82, 2, 17, 2, 65, 76, 2, 17, 2, 32, 67, 2, 211, + 237, 14, 76, 36, 86, 32, 245, 231, 11, 15, 69, 82, 32, 82, 73, 71, 72, + 84, 32, 67, 79, 82, 78, 69, 82, 34, 158, 1, 67, 20, 2, 68, 79, 40, 4, 76, + 69, 70, 84, 82, 77, 12, 2, 82, 73, 50, 84, 178, 3, 65, 42, 71, 170, 2, + 73, 136, 196, 13, 2, 85, 80, 235, 180, 1, 86, 2, 131, 173, 10, 73, 6, + 238, 2, 84, 205, 200, 13, 2, 87, 78, 6, 28, 2, 32, 65, 247, 2, 45, 4, 25, + 4, 82, 82, 79, 87, 5, 151, 203, 13, 72, 2, 111, 65, 4, 180, 202, 13, 3, + 71, 72, 84, 255, 205, 2, 78, 4, 194, 2, 79, 155, 128, 14, 73, 18, 18, 65, + 23, 73, 2, 151, 244, 14, 67, 16, 26, 68, 163, 254, 12, 78, 14, 38, 32, + 217, 1, 4, 68, 76, 69, 32, 8, 26, 68, 70, 76, 79, 84, 4, 17, 2, 79, 84, + 4, 25, 4, 84, 69, 68, 32, 4, 18, 76, 79, 84, 2, 25, 4, 69, 70, 84, 45, 2, + 25, 4, 83, 84, 69, 77, 2, 17, 2, 32, 84, 2, 11, 79, 2, 11, 78, 2, 187, + 198, 13, 69, 6, 40, 6, 68, 79, 85, 66, 76, 69, 75, 71, 4, 11, 32, 4, 18, + 65, 43, 71, 2, 11, 67, 2, 229, 170, 10, 2, 85, 84, 2, 11, 82, 2, 179, + 170, 10, 65, 2, 207, 148, 14, 69, 4, 246, 250, 12, 76, 247, 129, 2, 82, + 26, 104, 6, 65, 73, 83, 69, 68, 32, 150, 1, 69, 216, 1, 3, 73, 71, 72, + 173, 222, 8, 5, 72, 79, 84, 73, 67, 10, 70, 68, 30, 73, 234, 186, 9, 69, + 180, 189, 5, 2, 85, 80, 199, 74, 67, 2, 129, 197, 14, 2, 79, 87, 2, 209, + 186, 9, 7, 78, 86, 69, 82, 84, 69, 68, 8, 104, 7, 86, 69, 82, 83, 69, 68, + 32, 133, 28, 14, 84, 82, 79, 70, 76, 69, 88, 32, 67, 76, 73, 67, 75, 32, + 6, 26, 71, 255, 197, 13, 67, 4, 11, 76, 4, 49, 10, 79, 84, 84, 65, 76, + 32, 83, 84, 79, 80, 5, 167, 19, 32, 6, 17, 2, 84, 32, 6, 38, 72, 250, + 133, 13, 84, 231, 59, 65, 2, 185, 168, 7, 3, 65, 76, 70, 156, 2, 138, 1, + 72, 48, 5, 77, 65, 76, 76, 32, 156, 31, 8, 84, 82, 69, 83, 83, 32, 65, + 78, 53, 11, 85, 80, 69, 82, 83, 67, 82, 73, 80, 84, 32, 4, 216, 130, 8, + 3, 79, 82, 84, 251, 139, 6, 69, 144, 2, 154, 2, 65, 46, 66, 130, 1, 67, + 238, 2, 68, 238, 2, 90, 66, 69, 46, 70, 30, 71, 110, 72, 102, 77, 34, 73, + 34, 74, 98, 76, 176, 3, 7, 78, 32, 87, 73, 84, 72, 32, 30, 79, 94, 80, + 22, 82, 146, 2, 83, 190, 1, 84, 130, 8, 85, 142, 1, 86, 134, 240, 15, 75, + 2, 81, 2, 87, 2, 88, 3, 89, 9, 238, 23, 76, 210, 164, 15, 73, 215, 79, + 69, 11, 46, 65, 50, 79, 222, 8, 32, 227, 221, 15, 69, 2, 17, 2, 82, 82, + 2, 181, 227, 5, 2, 69, 68, 2, 229, 20, 4, 84, 84, 79, 77, 41, 100, 7, 65, + 80, 73, 84, 65, 76, 32, 180, 1, 6, 76, 79, 83, 69, 68, 32, 190, 17, 32, + 187, 227, 15, 72, 30, 114, 73, 214, 6, 71, 238, 16, 76, 250, 218, 15, 79, + 158, 20, 65, 186, 2, 66, 2, 72, 2, 78, 2, 82, 2, 85, 3, 89, 7, 22, 78, + 191, 11, 32, 2, 237, 220, 5, 5, 86, 69, 82, 84, 69, 4, 26, 82, 175, 136, + 9, 79, 2, 229, 20, 9, 69, 86, 69, 82, 83, 69, 68, 32, 79, 23, 104, 6, 32, + 87, 73, 84, 72, 32, 86, 69, 32, 9, 79, 84, 76, 69, 83, 83, 32, 74, 32, + 105, 3, 90, 32, 68, 6, 26, 72, 247, 217, 13, 84, 4, 21, 3, 79, 79, 75, 5, + 201, 160, 13, 3, 32, 65, 78, 4, 238, 15, 90, 131, 210, 15, 76, 4, 33, 6, + 87, 73, 84, 72, 32, 83, 4, 29, 5, 84, 82, 79, 75, 69, 5, 177, 211, 8, 4, + 32, 65, 78, 68, 6, 33, 6, 73, 71, 82, 65, 80, 72, 7, 33, 6, 32, 87, 73, + 84, 72, 32, 4, 138, 14, 67, 219, 4, 82, 11, 190, 131, 16, 83, 2, 84, 2, + 90, 63, 78, 5, 225, 13, 3, 69, 78, 71, 11, 56, 5, 82, 69, 69, 75, 32, + 162, 1, 32, 151, 183, 13, 65, 4, 26, 71, 195, 223, 10, 80, 2, 151, 184, + 13, 65, 11, 40, 6, 32, 87, 73, 84, 72, 32, 39, 69, 4, 142, 178, 14, 72, + 231, 160, 1, 83, 4, 17, 2, 78, 71, 5, 11, 32, 2, 239, 207, 8, 87, 4, 222, + 4, 32, 239, 216, 15, 79, 5, 37, 7, 32, 87, 73, 84, 72, 32, 67, 2, 11, 82, + 2, 181, 212, 13, 6, 79, 83, 83, 69, 68, 45, 25, 116, 6, 32, 87, 73, 84, + 72, 32, 226, 9, 83, 2, 90, 112, 2, 69, 90, 241, 222, 15, 8, 73, 71, 65, + 84, 85, 82, 69, 32, 12, 54, 73, 82, 77, 82, 82, 222, 6, 80, 187, 237, 3, + 66, 2, 49, 10, 78, 86, 69, 82, 84, 69, 68, 32, 76, 65, 2, 189, 172, 12, + 2, 90, 89, 2, 11, 73, 2, 17, 2, 68, 68, 2, 17, 2, 76, 69, 2, 185, 189, + 12, 2, 32, 84, 4, 61, 13, 69, 84, 82, 79, 70, 76, 69, 88, 32, 72, 79, 79, + 75, 5, 217, 12, 4, 32, 65, 78, 68, 4, 222, 11, 82, 207, 1, 76, 9, 18, 32, + 47, 80, 2, 21, 3, 87, 73, 84, 2, 139, 205, 15, 72, 4, 241, 152, 12, 2, + 69, 78, 5, 151, 233, 15, 72, 15, 80, 6, 32, 87, 73, 84, 72, 32, 62, 65, + 41, 8, 69, 86, 69, 82, 83, 69, 68, 32, 4, 26, 70, 239, 206, 13, 84, 2, + 209, 201, 8, 3, 73, 83, 72, 2, 17, 2, 77, 83, 2, 247, 212, 5, 32, 6, 38, + 71, 182, 7, 79, 203, 243, 15, 69, 2, 11, 76, 2, 129, 176, 13, 4, 79, 84, + 84, 65, 13, 72, 6, 32, 87, 73, 84, 72, 32, 34, 67, 61, 6, 73, 68, 69, 87, + 65, 89, 4, 158, 3, 67, 131, 166, 14, 72, 4, 26, 82, 203, 180, 11, 72, 2, + 221, 199, 5, 3, 73, 80, 84, 2, 159, 167, 6, 83, 51, 106, 32, 102, 67, + 116, 2, 69, 83, 44, 2, 79, 80, 42, 83, 96, 6, 85, 82, 78, 69, 68, 32, + 207, 208, 12, 72, 4, 29, 5, 87, 73, 84, 72, 32, 4, 22, 80, 231, 5, 82, 2, + 197, 197, 8, 6, 65, 76, 65, 84, 65, 76, 2, 45, 9, 32, 68, 73, 71, 82, 65, + 80, 72, 32, 2, 25, 4, 87, 73, 84, 72, 2, 17, 2, 32, 67, 2, 195, 137, 3, + 85, 2, 11, 72, 2, 157, 241, 9, 3, 32, 68, 73, 2, 177, 206, 5, 5, 32, 72, + 65, 76, 70, 4, 37, 7, 32, 68, 73, 71, 82, 65, 80, 4, 11, 72, 5, 11, 32, + 2, 153, 3, 4, 87, 73, 84, 72, 32, 86, 65, 50, 77, 74, 79, 42, 82, 214, 1, + 89, 206, 241, 15, 72, 2, 73, 2, 86, 3, 87, 7, 26, 76, 167, 244, 15, 69, + 2, 231, 252, 13, 80, 5, 41, 8, 32, 87, 73, 84, 72, 32, 76, 79, 2, 221, + 133, 4, 2, 78, 71, 2, 11, 80, 2, 189, 133, 6, 2, 69, 78, 9, 33, 6, 32, + 87, 73, 84, 72, 32, 6, 26, 76, 131, 162, 14, 72, 4, 37, 7, 79, 78, 71, + 32, 76, 69, 71, 5, 25, 4, 32, 65, 78, 68, 2, 17, 2, 32, 82, 2, 11, 69, 2, + 213, 191, 8, 7, 84, 82, 79, 70, 76, 69, 88, 5, 29, 5, 32, 87, 73, 84, 72, + 2, 245, 230, 3, 2, 32, 66, 9, 18, 32, 95, 80, 4, 40, 4, 87, 73, 84, 72, + 171, 206, 14, 66, 2, 17, 2, 32, 76, 2, 11, 69, 2, 131, 1, 70, 2, 177, + 160, 15, 2, 83, 73, 7, 33, 6, 32, 87, 73, 84, 72, 32, 4, 26, 82, 231, + 158, 14, 72, 2, 21, 3, 73, 71, 72, 2, 135, 189, 8, 84, 4, 11, 68, 4, 11, + 32, 4, 182, 208, 1, 72, 35, 76, 4, 24, 2, 72, 65, 31, 84, 2, 25, 4, 76, + 70, 32, 84, 2, 43, 82, 4, 30, 82, 53, 3, 85, 82, 78, 2, 237, 157, 15, 8, + 73, 65, 78, 71, 85, 76, 65, 82, 2, 161, 144, 8, 2, 69, 68, 8, 70, 80, + 140, 245, 9, 7, 78, 65, 83, 80, 73, 82, 65, 223, 247, 5, 83, 4, 11, 32, + 4, 190, 226, 12, 84, 231, 59, 65, 4, 26, 79, 199, 210, 14, 69, 2, 11, 73, + 2, 155, 155, 15, 67, 4, 36, 3, 65, 78, 71, 1, 2, 73, 78, 2, 25, 4, 32, + 68, 69, 80, 2, 21, 3, 65, 82, 84, 2, 21, 3, 73, 78, 71, 2, 17, 2, 32, 84, + 2, 11, 79, 2, 227, 238, 5, 78, 2, 11, 32, 2, 215, 194, 14, 83, 234, 2, + 92, 2, 69, 89, 88, 7, 71, 79, 76, 73, 65, 78, 32, 210, 24, 79, 209, 222, + 11, 3, 75, 69, 89, 6, 26, 32, 251, 171, 15, 45, 4, 184, 223, 11, 6, 87, + 73, 84, 72, 32, 87, 255, 163, 2, 66, 214, 2, 194, 2, 68, 46, 70, 148, 1, + 14, 73, 78, 86, 69, 82, 84, 69, 68, 32, 66, 73, 82, 71, 65, 16, 7, 76, + 69, 84, 84, 69, 82, 32, 142, 16, 83, 132, 1, 7, 82, 79, 84, 65, 84, 69, + 68, 22, 66, 98, 84, 160, 2, 4, 86, 79, 87, 69, 158, 233, 3, 67, 164, 1, + 6, 77, 65, 78, 67, 72, 85, 196, 162, 7, 4, 78, 73, 82, 85, 171, 166, 2, + 69, 22, 236, 20, 3, 79, 85, 66, 183, 227, 13, 73, 12, 112, 19, 82, 69, + 69, 32, 86, 65, 82, 73, 65, 84, 73, 79, 78, 32, 83, 69, 76, 69, 67, 158, + 154, 13, 85, 175, 46, 79, 8, 177, 207, 9, 3, 84, 79, 82, 5, 231, 19, 32, + 136, 2, 130, 2, 65, 244, 4, 2, 67, 72, 88, 2, 77, 65, 174, 2, 83, 250, 1, + 84, 234, 3, 90, 190, 229, 13, 72, 150, 168, 1, 75, 2, 76, 162, 7, 69, 2, + 79, 2, 85, 222, 61, 66, 2, 68, 2, 70, 2, 71, 2, 74, 2, 78, 2, 80, 2, 81, + 2, 82, 2, 87, 2, 89, 187, 2, 73, 59, 56, 8, 76, 73, 32, 71, 65, 76, 73, + 32, 207, 225, 15, 78, 54, 174, 1, 65, 52, 6, 86, 73, 83, 65, 82, 71, 22, + 68, 76, 5, 72, 65, 76, 70, 32, 34, 73, 50, 85, 34, 78, 30, 84, 66, 66, + 222, 150, 15, 80, 2, 90, 242, 68, 83, 14, 67, 3, 75, 7, 48, 6, 78, 85, + 83, 86, 65, 82, 191, 224, 15, 72, 2, 131, 134, 9, 65, 8, 26, 65, 215, + 221, 15, 68, 7, 214, 222, 8, 77, 253, 190, 6, 3, 71, 65, 76, 4, 162, 221, + 15, 89, 187, 2, 85, 5, 45, 9, 78, 86, 69, 82, 84, 69, 68, 32, 85, 2, 169, + 156, 15, 3, 66, 65, 68, 4, 178, 220, 15, 71, 3, 78, 8, 60, 6, 72, 82, 69, + 69, 32, 66, 222, 150, 15, 84, 183, 71, 65, 2, 17, 2, 65, 76, 2, 247, 184, + 15, 85, 6, 26, 65, 207, 221, 15, 73, 5, 29, 5, 32, 87, 73, 84, 72, 2, + 201, 143, 14, 2, 32, 84, 41, 29, 5, 78, 67, 72, 85, 32, 38, 104, 9, 65, + 76, 73, 32, 71, 65, 76, 73, 32, 202, 228, 13, 90, 134, 245, 1, 70, 2, 75, + 2, 82, 187, 2, 73, 28, 122, 68, 166, 165, 9, 67, 158, 164, 1, 84, 142, + 154, 3, 66, 2, 71, 2, 74, 2, 76, 138, 176, 1, 90, 254, 4, 78, 247, 63, + 83, 4, 202, 227, 13, 68, 135, 245, 1, 72, 48, 52, 4, 73, 66, 69, 32, 246, + 215, 15, 72, 187, 2, 65, 44, 186, 215, 2, 84, 162, 243, 2, 71, 2, 72, + 218, 156, 6, 73, 190, 251, 1, 67, 2, 83, 246, 7, 82, 222, 158, 1, 65, + 186, 9, 90, 162, 7, 85, 222, 61, 68, 2, 70, 2, 74, 2, 75, 2, 80, 187, 2, + 69, 60, 52, 4, 79, 68, 79, 32, 254, 213, 15, 83, 187, 2, 65, 56, 250, 1, + 65, 98, 68, 34, 74, 34, 78, 176, 163, 1, 8, 76, 79, 78, 71, 32, 86, 79, + 87, 250, 174, 1, 84, 162, 243, 2, 71, 150, 152, 8, 67, 246, 7, 72, 182, + 175, 1, 79, 2, 85, 222, 61, 66, 2, 75, 2, 77, 2, 80, 2, 81, 2, 87, 2, 89, + 186, 2, 69, 3, 73, 6, 56, 8, 76, 73, 32, 71, 65, 76, 73, 32, 171, 213, + 15, 78, 4, 190, 222, 13, 90, 135, 245, 1, 84, 4, 158, 211, 15, 90, 187, + 2, 65, 4, 254, 210, 15, 73, 187, 2, 65, 2, 223, 210, 15, 73, 6, 170, 193, + 15, 72, 162, 17, 82, 187, 2, 65, 8, 128, 1, 4, 87, 73, 82, 76, 149, 181, + 4, 21, 73, 66, 69, 32, 83, 89, 76, 76, 65, 66, 76, 69, 32, 66, 79, 85, + 78, 68, 65, 82, 89, 6, 17, 2, 32, 66, 6, 25, 4, 73, 82, 71, 65, 7, 33, 6, + 32, 87, 73, 84, 72, 32, 4, 150, 2, 68, 171, 141, 15, 79, 6, 152, 1, 3, + 82, 73, 80, 56, 18, 85, 82, 78, 69, 68, 32, 83, 87, 73, 82, 76, 32, 66, + 73, 82, 71, 65, 32, 245, 190, 1, 8, 79, 68, 79, 32, 83, 79, 70, 84, 2, + 209, 141, 15, 9, 76, 69, 32, 66, 73, 82, 71, 65, 32, 2, 33, 6, 87, 73, + 84, 72, 32, 68, 2, 145, 141, 15, 5, 79, 85, 66, 76, 69, 2, 131, 192, 9, + 76, 10, 96, 9, 71, 82, 65, 77, 32, 70, 79, 82, 32, 224, 251, 3, 5, 83, + 84, 65, 66, 76, 235, 166, 9, 82, 6, 26, 89, 243, 136, 12, 69, 4, 190, + 254, 14, 65, 155, 1, 73, 8, 48, 2, 78, 32, 162, 197, 4, 68, 231, 242, 10, + 83, 4, 72, 12, 86, 73, 69, 87, 73, 78, 71, 32, 67, 69, 82, 69, 147, 136, + 12, 67, 2, 177, 174, 15, 2, 77, 79, 4, 230, 129, 12, 73, 139, 204, 3, 69, + 10, 26, 72, 69, 2, 79, 82, 2, 45, 9, 69, 82, 32, 67, 72, 82, 73, 83, 84, + 2, 147, 247, 2, 77, 8, 50, 32, 52, 4, 73, 90, 69, 68, 155, 192, 14, 87, + 4, 230, 173, 8, 66, 133, 232, 5, 4, 83, 67, 79, 79, 2, 205, 168, 3, 7, + 32, 87, 72, 69, 69, 76, 67, 18, 52, 2, 78, 84, 152, 1, 2, 83, 69, 247, + 200, 15, 84, 10, 48, 3, 65, 73, 78, 185, 224, 11, 3, 32, 70, 85, 9, 11, + 32, 6, 222, 166, 9, 82, 24, 5, 67, 65, 66, 76, 69, 137, 235, 1, 6, 66, + 73, 67, 89, 67, 76, 7, 11, 32, 4, 160, 185, 14, 2, 84, 82, 219, 83, 70, + 86, 52, 7, 76, 69, 84, 84, 69, 82, 32, 191, 211, 5, 68, 62, 198, 1, 75, + 62, 77, 34, 78, 34, 79, 30, 80, 34, 84, 246, 104, 68, 220, 231, 7, 2, 72, + 65, 2, 82, 158, 180, 1, 69, 190, 29, 83, 150, 90, 76, 246, 7, 67, 246, + 162, 4, 89, 190, 28, 66, 2, 87, 187, 2, 65, 6, 180, 154, 5, 2, 69, 65, + 182, 238, 5, 72, 231, 190, 4, 79, 4, 230, 180, 15, 65, 215, 1, 73, 4, + 158, 247, 14, 73, 255, 59, 71, 7, 210, 198, 15, 76, 3, 79, 4, 222, 178, + 15, 72, 219, 19, 65, 6, 214, 246, 8, 72, 170, 204, 6, 69, 155, 3, 65, + 204, 4, 44, 2, 76, 84, 238, 6, 83, 159, 175, 13, 67, 102, 36, 4, 65, 78, + 73, 32, 223, 2, 73, 76, 52, 7, 76, 69, 84, 84, 69, 82, 32, 211, 139, 4, + 83, 74, 210, 1, 68, 222, 82, 78, 158, 230, 1, 82, 230, 208, 1, 74, 166, + 209, 7, 84, 206, 160, 3, 66, 2, 67, 2, 71, 2, 75, 2, 80, 254, 68, 72, 2, + 76, 2, 77, 2, 83, 2, 86, 2, 89, 186, 2, 65, 2, 69, 2, 73, 3, 85, 10, 38, + 68, 162, 192, 15, 72, 187, 2, 65, 6, 158, 192, 15, 68, 2, 72, 187, 2, 65, + 26, 56, 2, 80, 76, 236, 2, 3, 83, 69, 84, 183, 174, 14, 77, 18, 50, 69, + 89, 8, 73, 67, 65, 84, 73, 79, 78, 32, 2, 41, 8, 32, 77, 85, 83, 73, 67, + 65, 76, 2, 21, 3, 32, 78, 79, 2, 155, 173, 14, 84, 16, 40, 4, 83, 73, 71, + 78, 191, 192, 15, 88, 15, 11, 32, 12, 48, 3, 73, 78, 32, 81, 5, 87, 73, + 84, 72, 32, 8, 166, 199, 3, 76, 22, 82, 140, 246, 8, 5, 68, 79, 85, 66, + 76, 235, 222, 1, 84, 4, 210, 246, 11, 85, 167, 200, 2, 68, 7, 11, 32, 4, + 232, 82, 5, 77, 85, 76, 84, 73, 207, 209, 11, 85, 226, 3, 32, 2, 73, 67, + 247, 152, 3, 72, 224, 3, 30, 32, 101, 3, 65, 76, 32, 6, 76, 4, 78, 65, + 84, 85, 200, 43, 2, 70, 76, 181, 229, 10, 4, 83, 72, 65, 82, 2, 239, 165, + 10, 82, 218, 3, 64, 8, 75, 69, 89, 66, 79, 65, 82, 68, 74, 83, 155, 239, + 3, 78, 5, 41, 8, 32, 87, 73, 84, 72, 32, 74, 65, 2, 209, 254, 14, 2, 67, + 75, 212, 3, 48, 6, 89, 77, 66, 79, 76, 32, 135, 131, 11, 67, 210, 3, 230, + 2, 66, 238, 1, 67, 226, 9, 68, 242, 2, 69, 162, 1, 70, 166, 2, 71, 112, + 9, 65, 82, 80, 69, 71, 71, 73, 65, 84, 168, 1, 2, 72, 65, 126, 75, 198, + 3, 76, 138, 1, 77, 190, 2, 78, 162, 1, 79, 218, 2, 80, 200, 2, 2, 81, 85, + 146, 2, 82, 190, 2, 83, 230, 5, 84, 182, 10, 86, 42, 88, 42, 87, 180, + 233, 8, 9, 73, 78, 86, 69, 82, 84, 69, 68, 32, 163, 151, 6, 90, 20, 36, + 5, 69, 71, 73, 78, 32, 59, 82, 8, 130, 15, 80, 30, 83, 182, 224, 7, 66, + 187, 173, 7, 84, 12, 24, 2, 65, 67, 35, 69, 4, 218, 130, 15, 75, 143, 53, + 69, 8, 26, 86, 223, 245, 14, 65, 6, 32, 2, 73, 83, 139, 183, 15, 69, 5, + 171, 26, 32, 84, 120, 2, 65, 69, 30, 76, 94, 79, 194, 7, 82, 234, 11, 32, + 224, 32, 7, 73, 82, 67, 76, 69, 32, 88, 145, 200, 5, 2, 85, 84, 2, 197, + 241, 14, 2, 83, 85, 8, 42, 73, 245, 23, 5, 85, 83, 84, 69, 82, 4, 26, 77, + 175, 152, 13, 86, 2, 207, 177, 9, 65, 64, 26, 77, 179, 178, 15, 68, 62, + 64, 7, 66, 73, 78, 73, 78, 71, 32, 185, 251, 5, 3, 77, 79, 78, 60, 202, + 1, 65, 80, 7, 77, 65, 82, 67, 65, 84, 79, 56, 2, 68, 79, 56, 2, 85, 80, + 28, 2, 70, 76, 40, 5, 72, 65, 82, 77, 79, 22, 83, 142, 2, 84, 202, 154, + 7, 66, 140, 180, 3, 2, 76, 79, 183, 222, 4, 82, 6, 76, 5, 67, 67, 69, 78, + 84, 37, 10, 85, 71, 77, 69, 78, 84, 65, 84, 73, 79, 5, 205, 2, 5, 45, 83, + 84, 65, 67, 2, 231, 160, 14, 78, 6, 52, 2, 87, 78, 168, 3, 2, 85, 66, + 199, 145, 15, 73, 2, 137, 151, 14, 2, 32, 66, 12, 136, 76, 2, 65, 71, + 231, 228, 14, 73, 2, 231, 137, 14, 78, 12, 132, 1, 9, 78, 65, 80, 32, 80, + 73, 90, 90, 73, 22, 84, 236, 187, 4, 11, 80, 82, 69, 67, 72, 71, 69, 83, + 65, 78, 71, 255, 238, 5, 77, 2, 191, 206, 11, 67, 6, 44, 5, 65, 67, 67, + 65, 84, 159, 158, 15, 69, 4, 40, 4, 73, 83, 83, 73, 203, 174, 15, 79, 2, + 211, 143, 15, 77, 10, 34, 82, 253, 225, 11, 2, 69, 78, 8, 28, 2, 73, 80, + 191, 6, 69, 2, 133, 205, 11, 6, 76, 69, 32, 84, 79, 78, 4, 22, 79, 191, + 2, 69, 2, 159, 161, 14, 73, 24, 98, 65, 142, 1, 69, 84, 6, 79, 85, 66, + 76, 69, 32, 213, 249, 9, 7, 82, 85, 77, 32, 67, 76, 69, 10, 96, 2, 32, + 67, 20, 2, 77, 80, 196, 29, 4, 83, 72, 69, 68, 233, 228, 14, 5, 76, 32, + 83, 69, 71, 2, 223, 164, 8, 65, 5, 255, 166, 13, 32, 4, 52, 3, 67, 82, + 69, 241, 201, 8, 4, 71, 82, 69, 69, 2, 157, 25, 3, 83, 67, 69, 6, 246, + 21, 83, 250, 6, 66, 131, 244, 4, 70, 14, 32, 3, 78, 68, 32, 155, 16, 73, + 10, 74, 80, 30, 83, 208, 13, 3, 79, 70, 32, 230, 210, 7, 66, 187, 173, 7, + 84, 2, 145, 153, 12, 2, 72, 82, 2, 215, 176, 14, 76, 34, 104, 6, 69, 82, + 77, 65, 84, 65, 22, 73, 122, 79, 102, 32, 144, 36, 3, 85, 83, 65, 157, + 221, 3, 2, 76, 65, 5, 195, 129, 13, 32, 10, 22, 78, 135, 34, 86, 8, 56, + 9, 71, 69, 82, 69, 68, 32, 84, 82, 69, 235, 20, 65, 6, 185, 215, 5, 4, + 77, 79, 76, 79, 6, 208, 25, 3, 85, 82, 45, 147, 201, 13, 82, 18, 54, 32, + 56, 7, 76, 73, 83, 83, 65, 78, 68, 23, 82, 6, 25, 4, 67, 76, 69, 70, 7, + 161, 13, 3, 32, 79, 84, 4, 163, 235, 5, 79, 8, 84, 9, 65, 67, 69, 32, 78, + 79, 84, 69, 32, 37, 8, 69, 71, 79, 82, 73, 65, 78, 32, 4, 132, 196, 8, 2, + 78, 79, 27, 83, 4, 250, 2, 67, 3, 70, 8, 44, 3, 76, 70, 32, 209, 8, 3, + 85, 80, 84, 6, 52, 3, 80, 69, 68, 246, 214, 3, 78, 163, 169, 3, 82, 2, + 135, 175, 5, 65, 24, 48, 6, 73, 69, 86, 65, 78, 32, 147, 255, 13, 79, 22, + 178, 1, 67, 46, 69, 68, 7, 81, 85, 65, 82, 84, 69, 82, 62, 70, 184, 211, + 3, 4, 72, 65, 76, 70, 0, 5, 87, 72, 79, 76, 69, 253, 208, 1, 9, 82, 69, + 67, 73, 84, 65, 84, 73, 86, 2, 11, 32, 2, 11, 67, 2, 171, 144, 5, 76, 6, + 64, 5, 73, 71, 72, 84, 72, 253, 235, 13, 5, 78, 68, 32, 79, 70, 4, 165, + 230, 5, 10, 32, 78, 79, 84, 69, 32, 83, 84, 69, 77, 4, 214, 14, 76, 225, + 196, 3, 4, 73, 78, 65, 76, 8, 44, 4, 79, 78, 71, 65, 213, 13, 2, 69, 70, + 7, 11, 32, 4, 28, 3, 73, 77, 80, 3, 80, 2, 197, 2, 7, 69, 82, 70, 69, 67, + 84, 65, 18, 104, 2, 65, 88, 20, 2, 69, 90, 20, 5, 73, 78, 73, 77, 65, 48, + 3, 79, 79, 78, 25, 4, 85, 76, 84, 73, 2, 135, 253, 14, 73, 2, 143, 255, + 14, 90, 7, 11, 32, 4, 146, 250, 6, 82, 171, 153, 5, 66, 4, 185, 17, 2, + 32, 78, 4, 60, 11, 80, 76, 69, 32, 77, 69, 65, 83, 85, 82, 69, 15, 32, 2, + 11, 32, 2, 139, 249, 6, 82, 10, 120, 4, 69, 66, 69, 78, 208, 26, 3, 85, + 76, 76, 148, 198, 5, 3, 65, 84, 85, 173, 176, 6, 7, 79, 84, 69, 72, 69, + 65, 68, 2, 245, 131, 14, 4, 83, 84, 73, 77, 32, 88, 2, 78, 69, 120, 14, + 82, 78, 65, 77, 69, 78, 84, 32, 83, 84, 82, 79, 75, 69, 107, 84, 6, 92, + 18, 32, 72, 85, 78, 68, 82, 69, 68, 32, 84, 87, 69, 78, 84, 89, 45, 69, + 73, 155, 20, 45, 4, 177, 13, 2, 71, 72, 22, 11, 45, 22, 250, 158, 3, 49, + 206, 250, 11, 50, 2, 51, 2, 52, 2, 53, 2, 54, 2, 55, 2, 56, 3, 57, 4, + 173, 4, 3, 84, 65, 86, 18, 96, 9, 65, 82, 69, 78, 84, 72, 69, 83, 73, 0, + 2, 76, 85, 18, 69, 142, 1, 79, 247, 145, 13, 73, 2, 239, 22, 83, 6, 68, + 4, 68, 65, 76, 32, 49, 9, 83, 32, 83, 85, 66, 80, 85, 78, 67, 4, 26, 85, + 219, 213, 14, 77, 2, 191, 213, 14, 80, 2, 247, 249, 12, 84, 6, 48, 2, 68, + 65, 237, 5, 5, 82, 82, 69, 67, 84, 2, 175, 147, 13, 84, 12, 76, 6, 65, + 82, 84, 69, 82, 32, 125, 9, 73, 78, 68, 73, 67, 69, 83, 73, 77, 8, 60, 5, + 84, 79, 78, 69, 32, 138, 200, 3, 78, 163, 169, 3, 82, 4, 26, 83, 251, + 250, 4, 70, 2, 205, 148, 15, 3, 72, 65, 82, 4, 17, 2, 65, 32, 4, 138, + 240, 11, 65, 217, 161, 3, 3, 66, 65, 83, 14, 22, 69, 167, 1, 73, 10, 72, + 4, 80, 69, 65, 84, 73, 10, 86, 69, 82, 83, 69, 32, 70, 73, 78, 65, 8, + 152, 195, 5, 9, 69, 68, 32, 70, 73, 71, 85, 82, 69, 191, 130, 8, 32, 2, + 211, 4, 76, 4, 48, 2, 71, 72, 57, 6, 78, 70, 79, 82, 90, 65, 2, 33, 6, + 84, 32, 82, 69, 80, 69, 2, 131, 251, 9, 65, 2, 155, 151, 8, 78, 48, 136, + 1, 6, 67, 65, 78, 68, 73, 67, 62, 69, 166, 1, 72, 54, 73, 252, 1, 6, 81, + 85, 65, 82, 69, 32, 204, 128, 8, 2, 85, 66, 239, 2, 79, 4, 17, 2, 85, 83, + 5, 173, 141, 13, 5, 32, 70, 76, 69, 88, 14, 32, 2, 77, 73, 195, 230, 14, + 71, 12, 64, 6, 66, 82, 69, 86, 73, 83, 1, 6, 77, 73, 78, 73, 77, 65, 6, + 11, 32, 6, 138, 13, 87, 166, 222, 6, 82, 171, 153, 5, 66, 6, 84, 3, 79, + 82, 84, 169, 211, 5, 3, 65, 82, 80, 14, 32, 4, 78, 71, 76, 69, 43, 88, 2, + 17, 2, 32, 66, 2, 155, 169, 13, 65, 12, 18, 45, 79, 84, 4, 242, 7, 76, + 213, 238, 13, 11, 83, 84, 82, 73, 78, 71, 32, 70, 82, 69, 84, 8, 52, 3, + 69, 69, 78, 1, 6, 89, 45, 70, 79, 85, 82, 4, 193, 12, 2, 84, 72, 6, 26, + 78, 135, 140, 15, 66, 4, 229, 9, 7, 79, 84, 69, 72, 69, 65, 68, 60, 132, + 1, 6, 69, 77, 80, 85, 83, 32, 154, 4, 72, 88, 2, 87, 79, 84, 7, 79, 82, + 67, 85, 76, 85, 83, 46, 82, 141, 3, 3, 85, 82, 78, 16, 232, 1, 27, 73, + 77, 80, 69, 82, 70, 69, 67, 84, 85, 77, 32, 67, 85, 77, 32, 80, 82, 79, + 76, 65, 84, 73, 79, 78, 69, 32, 129, 1, 25, 80, 69, 82, 70, 69, 67, 84, + 85, 77, 32, 67, 85, 77, 32, 80, 82, 79, 76, 65, 84, 73, 79, 78, 69, 32, + 10, 60, 10, 73, 77, 80, 69, 82, 70, 69, 67, 84, 65, 131, 1, 80, 9, 169, + 184, 5, 11, 32, 68, 73, 77, 73, 78, 85, 84, 73, 79, 78, 6, 60, 3, 73, 77, + 80, 41, 8, 80, 69, 82, 70, 69, 67, 84, 65, 2, 213, 226, 14, 5, 69, 82, + 70, 69, 67, 5, 145, 163, 8, 12, 32, 68, 73, 77, 73, 78, 85, 84, 73, 79, + 78, 45, 6, 72, 2, 82, 69, 249, 5, 11, 73, 82, 84, 89, 45, 83, 69, 67, 79, + 78, 68, 2, 11, 69, 2, 11, 45, 2, 11, 76, 2, 37, 7, 73, 78, 69, 32, 83, + 84, 65, 2, 147, 132, 14, 70, 5, 173, 168, 11, 6, 32, 82, 69, 83, 85, 80, + 27, 33, 6, 73, 65, 78, 71, 76, 69, 24, 128, 1, 10, 32, 78, 79, 84, 69, + 72, 69, 65, 68, 32, 61, 17, 45, 82, 79, 85, 78, 68, 32, 78, 79, 84, 69, + 72, 69, 65, 68, 32, 68, 20, 58, 68, 24, 3, 85, 80, 32, 38, 82, 25, 3, 76, + 69, 70, 4, 93, 3, 79, 87, 78, 8, 34, 82, 78, 87, 207, 247, 11, 66, 4, 21, + 3, 73, 71, 72, 4, 11, 84, 4, 11, 32, 4, 26, 87, 207, 247, 11, 66, 2, 11, + 72, 2, 187, 189, 13, 73, 7, 11, 32, 4, 222, 160, 8, 83, 223, 224, 6, 85, + 4, 36, 3, 79, 73, 68, 187, 190, 14, 73, 2, 221, 178, 12, 5, 32, 78, 79, + 84, 69, 6, 92, 4, 72, 79, 76, 69, 157, 174, 8, 13, 73, 84, 72, 32, 70, + 73, 78, 71, 69, 82, 78, 65, 73, 4, 11, 32, 4, 246, 178, 3, 78, 163, 169, + 3, 82, 192, 3, 252, 1, 15, 67, 79, 78, 83, 79, 78, 65, 78, 84, 32, 83, + 73, 71, 78, 32, 254, 1, 76, 216, 14, 16, 77, 79, 68, 73, 70, 73, 69, 82, + 32, 76, 69, 84, 84, 69, 82, 32, 122, 83, 166, 10, 84, 216, 1, 11, 86, 79, + 87, 69, 76, 32, 83, 73, 71, 78, 32, 223, 241, 12, 68, 16, 66, 77, 165, 1, + 11, 83, 72, 65, 78, 32, 77, 69, 68, 73, 65, 76, 14, 80, 6, 69, 68, 73, + 65, 76, 32, 45, 10, 79, 78, 32, 77, 69, 68, 73, 65, 76, 32, 8, 238, 249, + 14, 72, 2, 82, 2, 87, 3, 89, 6, 194, 249, 14, 76, 2, 77, 3, 78, 2, 219, + 182, 10, 32, 238, 1, 104, 6, 69, 84, 84, 69, 82, 32, 189, 13, 15, 79, 71, + 79, 71, 82, 65, 77, 32, 75, 72, 65, 77, 84, 73, 32, 232, 1, 242, 1, 65, + 50, 69, 146, 1, 71, 50, 75, 254, 1, 77, 134, 1, 78, 58, 82, 86, 83, 130, + 3, 84, 198, 1, 87, 242, 133, 11, 68, 190, 4, 86, 214, 20, 85, 210, 200, + 1, 73, 42, 76, 242, 190, 1, 66, 2, 67, 2, 74, 2, 80, 254, 68, 72, 2, 89, + 187, 2, 79, 7, 140, 174, 14, 4, 73, 84, 79, 78, 207, 74, 85, 9, 77, 17, + 65, 83, 84, 69, 82, 78, 32, 80, 87, 79, 32, 75, 65, 82, 69, 78, 32, 6, + 42, 71, 182, 178, 10, 89, 187, 138, 3, 78, 2, 179, 178, 10, 72, 6, 214, + 163, 9, 82, 142, 209, 5, 72, 187, 2, 65, 44, 32, 2, 72, 65, 203, 246, 14, + 65, 43, 25, 4, 77, 84, 73, 32, 40, 134, 1, 68, 34, 84, 162, 191, 8, 78, + 178, 238, 5, 67, 2, 72, 2, 74, 158, 37, 76, 226, 31, 70, 2, 71, 2, 82, 2, + 83, 2, 88, 3, 90, 6, 238, 173, 14, 68, 255, 68, 72, 4, 207, 173, 14, 84, + 12, 36, 3, 79, 78, 32, 203, 244, 14, 65, 10, 60, 2, 66, 66, 206, 252, 12, + 74, 134, 181, 1, 78, 187, 66, 69, 4, 134, 244, 14, 65, 3, 69, 10, 134, + 190, 8, 78, 174, 179, 6, 71, 2, 89, 187, 2, 65, 4, 196, 214, 2, 12, 85, + 77, 65, 73, 32, 80, 65, 76, 65, 85, 78, 71, 239, 156, 12, 65, 50, 90, 72, + 136, 215, 2, 9, 71, 65, 87, 32, 75, 65, 82, 69, 78, 198, 152, 12, 83, + 187, 2, 65, 44, 66, 65, 197, 1, 11, 87, 69, 32, 80, 65, 76, 65, 85, 78, + 71, 32, 41, 17, 2, 78, 32, 38, 134, 1, 78, 234, 248, 12, 74, 2, 80, 2, + 84, 138, 176, 1, 66, 2, 67, 2, 71, 2, 75, 254, 68, 68, 2, 70, 2, 72, 2, + 90, 187, 2, 65, 6, 234, 237, 14, 78, 2, 89, 187, 2, 65, 4, 190, 248, 12, + 67, 3, 83, 36, 38, 65, 134, 168, 14, 84, 255, 68, 72, 31, 41, 8, 73, 32, + 76, 65, 73, 78, 71, 32, 28, 82, 78, 142, 134, 11, 68, 250, 160, 3, 66, 2, + 71, 2, 74, 158, 37, 76, 227, 31, 70, 4, 254, 235, 14, 78, 3, 89, 6, 92, + 17, 69, 83, 84, 69, 82, 78, 32, 80, 87, 79, 32, 75, 65, 82, 69, 78, 32, + 191, 237, 14, 65, 4, 190, 168, 10, 80, 195, 205, 2, 84, 6, 170, 225, 13, + 79, 154, 60, 81, 255, 62, 72, 4, 56, 6, 75, 72, 65, 77, 84, 73, 1, 4, 83, + 72, 65, 78, 2, 29, 5, 32, 82, 69, 68, 85, 2, 133, 132, 1, 2, 80, 76, 90, + 88, 4, 73, 71, 78, 32, 232, 6, 6, 89, 77, 66, 79, 76, 32, 145, 143, 9, 3, + 72, 65, 78, 52, 202, 3, 65, 32, 12, 75, 72, 65, 77, 84, 73, 32, 84, 79, + 78, 69, 45, 30, 83, 132, 2, 15, 84, 65, 73, 32, 76, 65, 73, 78, 71, 32, + 84, 79, 78, 69, 45, 28, 22, 87, 69, 83, 84, 69, 82, 78, 32, 80, 87, 79, + 32, 75, 65, 82, 69, 78, 32, 84, 79, 78, 69, 154, 238, 2, 68, 128, 145, 5, + 19, 82, 85, 77, 65, 73, 32, 80, 65, 76, 65, 85, 78, 71, 32, 84, 79, 78, + 69, 45, 156, 151, 3, 9, 80, 65, 79, 32, 75, 65, 82, 69, 78, 160, 91, 6, + 76, 73, 84, 84, 76, 69, 159, 176, 2, 86, 4, 250, 211, 13, 83, 243, 78, + 78, 4, 170, 231, 14, 49, 3, 51, 18, 40, 4, 72, 65, 78, 32, 151, 150, 14, + 69, 16, 84, 8, 67, 79, 85, 78, 67, 73, 76, 32, 84, 5, 84, 79, 78, 69, 45, + 159, 231, 13, 83, 6, 204, 151, 11, 8, 69, 77, 80, 72, 65, 84, 73, 67, + 189, 205, 3, 4, 84, 79, 78, 69, 8, 182, 229, 14, 50, 2, 51, 2, 53, 3, 54, + 4, 138, 229, 14, 50, 3, 53, 10, 11, 45, 10, 226, 228, 14, 49, 2, 50, 2, + 51, 2, 52, 3, 53, 18, 130, 1, 65, 132, 1, 2, 76, 79, 28, 5, 83, 72, 65, + 78, 32, 232, 148, 8, 4, 71, 69, 78, 73, 201, 85, 6, 67, 79, 77, 80, 76, + 69, 8, 84, 5, 73, 84, 79, 78, 32, 217, 152, 6, 10, 70, 79, 82, 69, 77, + 69, 78, 84, 73, 79, 6, 98, 69, 130, 213, 8, 84, 223, 243, 4, 79, 2, 129, + 149, 8, 2, 67, 65, 4, 26, 69, 223, 200, 13, 79, 2, 205, 12, 4, 88, 67, + 76, 65, 24, 140, 1, 20, 79, 78, 69, 32, 77, 65, 82, 75, 32, 83, 71, 65, + 87, 32, 75, 65, 82, 69, 78, 32, 161, 139, 9, 8, 65, 73, 32, 76, 65, 73, + 78, 71, 4, 42, 72, 253, 163, 10, 4, 75, 69, 32, 80, 2, 161, 188, 9, 2, + 65, 84, 56, 154, 2, 65, 76, 9, 71, 69, 66, 65, 32, 75, 65, 82, 69, 20, 6, + 75, 65, 89, 65, 72, 32, 40, 4, 77, 79, 78, 32, 34, 83, 154, 1, 69, 40, + 18, 87, 69, 83, 84, 69, 82, 78, 32, 80, 87, 79, 32, 75, 65, 82, 69, 78, + 32, 144, 146, 9, 2, 84, 65, 246, 228, 1, 86, 214, 20, 85, 211, 200, 1, + 73, 8, 26, 73, 195, 221, 14, 65, 7, 25, 4, 84, 79, 78, 32, 4, 215, 214, + 12, 65, 2, 139, 157, 14, 78, 6, 166, 198, 14, 69, 2, 79, 215, 22, 85, 4, + 250, 200, 14, 73, 219, 19, 79, 10, 72, 10, 71, 65, 87, 32, 75, 65, 82, + 69, 78, 32, 21, 4, 72, 65, 78, 32, 2, 255, 182, 14, 69, 8, 54, 69, 20, 5, + 70, 73, 78, 65, 76, 211, 216, 14, 65, 5, 179, 222, 13, 32, 2, 191, 201, + 14, 32, 4, 138, 182, 14, 69, 151, 14, 85, 216, 17, 128, 2, 5, 45, 65, 82, + 89, 32, 214, 4, 65, 242, 16, 66, 30, 69, 206, 31, 73, 136, 1, 3, 75, 79, + 32, 154, 10, 79, 162, 24, 85, 224, 8, 22, 89, 73, 65, 75, 69, 78, 71, 32, + 80, 85, 65, 67, 72, 85, 69, 32, 72, 77, 79, 78, 71, 32, 232, 246, 13, 2, + 78, 66, 27, 76, 32, 130, 1, 67, 114, 84, 46, 83, 160, 1, 5, 85, 78, 73, + 79, 78, 108, 4, 87, 72, 73, 84, 174, 168, 11, 76, 254, 16, 73, 135, 140, + 2, 80, 8, 52, 7, 73, 82, 67, 76, 69, 68, 32, 147, 200, 13, 79, 6, 40, 2, + 80, 76, 14, 84, 167, 244, 7, 68, 2, 35, 85, 2, 21, 3, 73, 77, 69, 2, 147, + 172, 11, 83, 6, 40, 6, 81, 85, 65, 82, 69, 32, 87, 85, 4, 60, 9, 73, 78, + 84, 69, 82, 83, 69, 67, 84, 1, 2, 85, 78, 2, 255, 146, 11, 73, 2, 11, 77, + 2, 235, 168, 11, 77, 7, 69, 15, 32, 79, 80, 69, 82, 65, 84, 79, 82, 32, + 87, 73, 84, 72, 32, 4, 198, 247, 10, 80, 211, 140, 3, 68, 2, 11, 69, 2, + 145, 132, 12, 2, 32, 86, 188, 2, 170, 2, 66, 252, 4, 10, 71, 32, 77, 85, + 78, 68, 65, 82, 73, 32, 154, 4, 73, 52, 2, 78, 68, 216, 4, 7, 84, 73, 79, + 78, 65, 76, 32, 240, 206, 1, 2, 85, 83, 136, 236, 7, 5, 77, 69, 32, 66, + 65, 148, 172, 3, 7, 90, 65, 82, 32, 65, 77, 85, 196, 157, 1, 8, 82, 82, + 79, 87, 32, 78, 79, 45, 219, 62, 75, 82, 52, 7, 65, 84, 65, 69, 65, 78, + 32, 219, 206, 14, 76, 80, 160, 1, 7, 76, 69, 84, 84, 69, 82, 32, 236, 2, + 7, 78, 85, 77, 66, 69, 82, 32, 193, 207, 9, 16, 67, 82, 85, 67, 73, 70, + 79, 82, 77, 32, 78, 85, 77, 66, 69, 82, 62, 236, 1, 6, 70, 73, 78, 65, + 76, 32, 174, 253, 1, 84, 246, 118, 68, 34, 76, 50, 81, 206, 194, 1, 82, + 134, 212, 2, 65, 50, 71, 90, 90, 34, 83, 66, 89, 154, 193, 1, 72, 234, 5, + 75, 130, 76, 66, 190, 173, 4, 78, 254, 1, 87, 202, 103, 80, 171, 4, 77, + 18, 138, 244, 2, 65, 54, 76, 174, 149, 4, 83, 190, 3, 89, 130, 199, 1, + 75, 130, 76, 66, 190, 173, 4, 78, 198, 105, 72, 171, 4, 77, 16, 154, 245, + 2, 84, 186, 151, 4, 79, 143, 211, 5, 70, 84, 84, 7, 76, 69, 84, 84, 69, + 82, 32, 164, 2, 5, 83, 73, 71, 78, 32, 183, 219, 12, 68, 54, 42, 65, 50, + 69, 66, 73, 50, 79, 47, 85, 11, 254, 185, 14, 78, 202, 17, 66, 2, 72, 3, + 74, 15, 150, 211, 12, 78, 230, 110, 76, 242, 108, 84, 174, 28, 71, 3, 77, + 11, 194, 132, 14, 68, 150, 70, 72, 2, 83, 3, 84, 11, 210, 201, 14, 78, + 86, 76, 2, 80, 3, 89, 11, 250, 201, 14, 67, 2, 68, 2, 75, 3, 82, 10, 112, + 2, 77, 85, 20, 3, 83, 85, 84, 172, 165, 2, 2, 73, 75, 184, 129, 9, 2, 79, + 74, 137, 233, 2, 3, 84, 79, 89, 2, 255, 143, 14, 72, 2, 183, 199, 14, 85, + 4, 236, 137, 11, 5, 76, 32, 80, 79, 76, 231, 2, 82, 133, 1, 41, 8, 73, + 78, 65, 71, 65, 82, 73, 32, 130, 1, 140, 1, 7, 76, 69, 84, 84, 69, 82, + 32, 252, 1, 5, 83, 73, 71, 78, 32, 52, 11, 86, 79, 87, 69, 76, 32, 83, + 73, 71, 78, 32, 199, 207, 4, 72, 94, 214, 1, 86, 202, 164, 10, 82, 206, + 55, 65, 38, 68, 46, 84, 230, 24, 85, 210, 200, 1, 73, 42, 76, 246, 189, + 1, 78, 46, 83, 82, 66, 2, 67, 2, 71, 2, 74, 2, 75, 2, 80, 254, 68, 72, 2, + 77, 2, 89, 186, 2, 69, 3, 79, 6, 242, 254, 4, 79, 243, 197, 9, 65, 10, + 202, 205, 9, 83, 134, 144, 1, 65, 243, 163, 3, 86, 24, 210, 213, 4, 80, + 190, 40, 86, 166, 225, 5, 65, 190, 21, 85, 210, 200, 1, 73, 206, 134, 2, + 69, 3, 79, 4, 202, 47, 68, 191, 210, 13, 80, 4, 250, 194, 14, 83, 15, 72, + 246, 4, 216, 1, 3, 71, 65, 84, 128, 7, 6, 73, 84, 72, 69, 82, 32, 194, 3, + 83, 136, 1, 2, 85, 84, 242, 1, 87, 144, 16, 3, 88, 84, 32, 140, 150, 8, + 4, 80, 84, 85, 78, 240, 239, 2, 2, 67, 75, 150, 141, 2, 82, 183, 144, 1, + 76, 154, 1, 152, 1, 4, 73, 86, 69, 32, 245, 160, 12, 27, 69, 68, 32, 68, + 79, 85, 66, 76, 69, 32, 86, 69, 82, 84, 73, 67, 65, 76, 32, 66, 65, 82, + 32, 68, 79, 85, 66, 152, 1, 152, 1, 8, 67, 73, 82, 67, 76, 69, 68, 32, + 216, 1, 9, 68, 73, 65, 71, 79, 78, 65, 76, 32, 196, 1, 8, 83, 81, 85, 65, + 82, 69, 68, 32, 147, 170, 8, 65, 78, 104, 5, 68, 73, 71, 73, 84, 28, 7, + 78, 85, 77, 66, 69, 82, 32, 142, 3, 76, 238, 150, 13, 84, 139, 3, 83, 2, + 189, 209, 12, 2, 32, 90, 20, 50, 84, 218, 254, 1, 69, 46, 70, 42, 78, 31, + 83, 6, 154, 128, 2, 72, 47, 87, 6, 38, 77, 234, 254, 12, 67, 191, 2, 68, + 2, 49, 10, 73, 68, 68, 76, 69, 32, 82, 73, 71, 72, 2, 17, 2, 84, 32, 2, + 25, 4, 84, 79, 32, 76, 2, 25, 4, 79, 87, 69, 82, 2, 169, 198, 11, 2, 32, + 67, 66, 118, 76, 248, 229, 2, 4, 67, 82, 79, 83, 142, 138, 9, 81, 146, + 144, 1, 65, 198, 19, 73, 2, 87, 170, 164, 1, 80, 3, 83, 52, 221, 209, 8, + 6, 65, 84, 73, 78, 32, 67, 18, 158, 1, 65, 216, 1, 17, 71, 82, 69, 65, + 84, 69, 82, 45, 84, 72, 65, 78, 32, 78, 79, 82, 32, 37, 14, 76, 69, 83, + 83, 45, 84, 72, 65, 78, 32, 78, 79, 82, 32, 6, 92, 3, 32, 83, 85, 85, 16, + 80, 80, 82, 79, 88, 73, 77, 65, 84, 69, 76, 89, 32, 78, 79, 82, 4, 30, + 66, 1, 3, 80, 69, 82, 2, 253, 223, 6, 8, 83, 69, 84, 32, 79, 70, 32, 78, + 2, 213, 48, 5, 32, 65, 67, 84, 85, 6, 250, 246, 7, 69, 191, 177, 4, 76, + 6, 214, 246, 7, 69, 155, 177, 4, 71, 6, 26, 84, 199, 179, 12, 83, 4, 76, + 5, 73, 78, 71, 32, 68, 145, 176, 10, 8, 32, 87, 73, 84, 72, 32, 69, 71, + 2, 133, 228, 7, 2, 79, 76, 64, 40, 4, 82, 65, 76, 32, 203, 252, 13, 69, + 62, 48, 6, 67, 72, 69, 83, 83, 32, 235, 247, 13, 70, 60, 74, 75, 134, + 218, 12, 66, 38, 69, 130, 5, 80, 22, 81, 38, 82, 131, 2, 84, 20, 44, 5, + 78, 73, 71, 72, 84, 151, 219, 12, 73, 15, 195, 219, 12, 32, 246, 2, 70, + 32, 184, 8, 2, 65, 32, 248, 6, 3, 76, 73, 78, 183, 206, 3, 83, 174, 1, + 90, 77, 64, 4, 83, 72, 69, 81, 20, 8, 84, 65, 73, 32, 76, 85, 69, 32, + 183, 152, 13, 76, 4, 25, 4, 79, 79, 78, 32, 4, 234, 244, 7, 87, 171, 170, + 5, 83, 2, 183, 154, 9, 69, 166, 1, 160, 1, 7, 76, 69, 84, 84, 69, 82, 32, + 244, 2, 8, 83, 73, 71, 78, 32, 76, 65, 69, 22, 84, 76, 11, 86, 79, 87, + 69, 76, 32, 83, 73, 71, 78, 32, 191, 190, 12, 68, 102, 76, 6, 70, 73, 78, + 65, 76, 32, 68, 4, 72, 73, 71, 72, 1, 3, 76, 79, 87, 14, 198, 183, 12, + 78, 150, 248, 1, 66, 2, 68, 2, 75, 2, 77, 3, 86, 44, 11, 32, 44, 146, 1, + 75, 2, 88, 34, 83, 210, 222, 10, 78, 134, 135, 3, 84, 82, 80, 254, 68, + 66, 2, 68, 2, 70, 2, 72, 2, 76, 2, 77, 2, 81, 2, 86, 3, 89, 4, 190, 171, + 14, 86, 187, 2, 65, 4, 158, 171, 14, 85, 187, 2, 65, 5, 183, 173, 14, 86, + 6, 224, 133, 7, 3, 79, 78, 69, 253, 76, 8, 72, 65, 77, 32, 68, 73, 71, + 73, 34, 110, 65, 46, 73, 30, 79, 38, 85, 216, 231, 11, 11, 86, 79, 87, + 69, 76, 32, 83, 72, 79, 82, 84, 167, 195, 2, 69, 8, 238, 184, 10, 65, + 250, 242, 3, 69, 3, 89, 4, 186, 171, 14, 73, 3, 89, 9, 166, 184, 10, 65, + 251, 242, 3, 89, 11, 130, 184, 10, 69, 250, 242, 3, 85, 3, 89, 194, 1, + 182, 1, 68, 106, 71, 72, 7, 76, 69, 84, 84, 69, 82, 32, 214, 2, 83, 190, + 23, 80, 202, 133, 1, 86, 138, 200, 7, 65, 144, 230, 1, 5, 73, 78, 83, 69, + 82, 210, 142, 1, 67, 207, 186, 2, 79, 26, 64, 6, 79, 85, 66, 76, 69, 32, + 214, 211, 4, 65, 239, 230, 7, 73, 4, 198, 211, 4, 68, 231, 137, 7, 67, 2, + 11, 65, 2, 11, 80, 2, 17, 2, 32, 70, 2, 213, 224, 10, 2, 73, 76, 108, + 218, 1, 78, 62, 86, 254, 188, 10, 65, 38, 68, 46, 84, 230, 24, 85, 210, + 200, 1, 73, 202, 190, 1, 83, 82, 66, 2, 67, 2, 71, 2, 74, 2, 75, 2, 76, + 2, 77, 2, 80, 2, 82, 254, 68, 72, 2, 87, 2, 89, 186, 2, 69, 3, 79, 14, + 210, 222, 13, 71, 2, 89, 254, 68, 72, 2, 78, 187, 2, 65, 10, 26, 69, 207, + 193, 10, 79, 2, 173, 246, 11, 3, 68, 73, 67, 22, 26, 73, 139, 179, 4, 65, + 20, 44, 3, 71, 78, 32, 213, 128, 9, 2, 68, 68, 18, 210, 189, 10, 65, 74, + 67, 98, 78, 230, 179, 1, 74, 228, 2, 5, 70, 73, 78, 65, 76, 50, 85, 211, + 235, 1, 86, 4, 203, 248, 13, 69, 4, 250, 200, 9, 80, 171, 193, 3, 76, 6, + 70, 78, 245, 141, 13, 11, 71, 72, 84, 32, 87, 73, 84, 72, 32, 83, 84, 4, + 156, 217, 7, 7, 69, 32, 80, 79, 73, 78, 84, 131, 199, 6, 74, 124, 152, 1, + 3, 67, 79, 77, 242, 2, 68, 78, 76, 156, 4, 4, 72, 73, 71, 72, 72, 7, 83, + 89, 77, 66, 79, 76, 32, 238, 192, 7, 69, 133, 178, 1, 3, 84, 65, 77, 20, + 52, 7, 66, 73, 78, 73, 78, 71, 32, 143, 158, 14, 77, 18, 116, 5, 76, 79, + 78, 71, 32, 76, 2, 78, 65, 20, 6, 83, 72, 79, 82, 84, 32, 165, 158, 13, + 6, 68, 79, 85, 66, 76, 69, 8, 130, 1, 72, 34, 76, 194, 207, 10, 82, 21, + 7, 68, 69, 83, 67, 69, 78, 68, 2, 155, 172, 10, 83, 6, 34, 72, 34, 76, + 195, 207, 10, 82, 2, 137, 208, 10, 3, 73, 71, 72, 2, 233, 207, 10, 2, 79, + 87, 24, 152, 1, 4, 65, 78, 84, 65, 152, 133, 12, 4, 79, 82, 79, 77, 203, + 41, 73, 70, 76, 4, 65, 74, 65, 78, 32, 6, 69, 84, 84, 69, 82, 32, 173, 3, + 2, 79, 87, 2, 185, 213, 12, 3, 89, 65, 76, 66, 228, 1, 2, 68, 65, 42, 74, + 90, 78, 206, 249, 9, 82, 158, 225, 1, 79, 198, 71, 67, 170, 183, 1, 69, + 238, 18, 71, 242, 42, 66, 2, 70, 2, 72, 2, 75, 2, 76, 2, 77, 2, 80, 2, + 83, 2, 84, 2, 87, 2, 89, 186, 2, 65, 2, 73, 3, 85, 5, 237, 248, 10, 5, + 71, 66, 65, 83, 73, 8, 40, 4, 79, 78, 65, 32, 151, 154, 14, 65, 6, 214, + 162, 12, 67, 134, 245, 1, 74, 3, 82, 11, 26, 65, 1, 2, 89, 65, 5, 173, + 193, 5, 5, 32, 87, 79, 76, 79, 2, 29, 5, 32, 84, 79, 78, 69, 2, 17, 2, + 32, 65, 2, 135, 171, 8, 80, 4, 68, 7, 71, 66, 65, 75, 85, 82, 85, 1, 6, + 79, 79, 32, 68, 69, 78, 2, 159, 199, 12, 78, 180, 1, 90, 32, 156, 3, 2, + 77, 73, 118, 78, 150, 1, 82, 238, 7, 84, 186, 203, 13, 45, 135, 40, 83, + 18, 202, 1, 66, 96, 5, 69, 78, 84, 82, 89, 22, 80, 160, 180, 2, 15, 79, + 78, 69, 32, 85, 78, 68, 69, 82, 32, 69, 73, 71, 72, 84, 220, 242, 3, 9, + 77, 79, 66, 73, 76, 69, 32, 80, 72, 181, 30, 3, 83, 77, 79, 4, 52, 4, 82, + 69, 65, 75, 173, 131, 2, 3, 73, 67, 89, 2, 17, 2, 32, 72, 2, 231, 244, + 12, 69, 5, 151, 142, 13, 32, 4, 60, 6, 69, 68, 69, 83, 84, 82, 161, 167, + 9, 3, 73, 82, 65, 2, 137, 230, 10, 2, 73, 65, 4, 36, 5, 78, 65, 76, 32, + 68, 59, 83, 2, 249, 255, 12, 9, 73, 71, 73, 84, 32, 83, 72, 65, 80, 2, + 195, 215, 10, 77, 6, 38, 45, 185, 183, 9, 3, 70, 79, 82, 4, 76, 8, 66, + 82, 69, 65, 75, 73, 78, 71, 245, 162, 2, 5, 80, 79, 84, 65, 66, 2, 129, + 201, 6, 2, 32, 72, 93, 56, 2, 84, 72, 146, 11, 77, 173, 185, 10, 3, 68, + 73, 67, 84, 78, 32, 213, 131, 11, 13, 69, 65, 83, 84, 45, 80, 79, 73, 78, + 84, 73, 78, 71, 82, 96, 5, 69, 65, 83, 84, 32, 132, 2, 6, 73, 78, 68, 73, + 67, 32, 217, 1, 5, 87, 69, 83, 84, 32, 30, 82, 65, 182, 221, 6, 80, 130, + 1, 84, 246, 160, 4, 66, 38, 68, 18, 83, 203, 43, 87, 12, 40, 4, 82, 82, + 79, 87, 175, 217, 6, 78, 11, 11, 32, 8, 80, 9, 67, 82, 79, 83, 83, 73, + 78, 71, 32, 244, 2, 2, 65, 78, 255, 216, 6, 87, 4, 218, 180, 3, 83, 207, + 166, 3, 78, 20, 50, 80, 60, 3, 81, 85, 65, 66, 82, 215, 126, 70, 2, 37, + 7, 76, 65, 67, 69, 72, 79, 76, 2, 135, 158, 4, 68, 4, 240, 157, 4, 2, 82, + 84, 237, 173, 9, 5, 78, 84, 73, 84, 89, 2, 17, 2, 85, 80, 2, 187, 144, 4, + 69, 32, 82, 65, 218, 217, 6, 80, 130, 1, 84, 246, 160, 4, 66, 38, 68, 18, + 83, 203, 43, 87, 14, 34, 78, 33, 4, 82, 82, 79, 87, 2, 229, 177, 3, 3, + 68, 32, 83, 13, 11, 32, 10, 68, 3, 84, 79, 32, 138, 213, 6, 67, 40, 3, + 65, 78, 68, 219, 2, 87, 4, 146, 214, 6, 67, 229, 228, 4, 4, 76, 79, 78, + 71, 56, 54, 32, 236, 5, 5, 67, 72, 69, 68, 32, 207, 2, 69, 38, 162, 1, + 65, 132, 2, 4, 78, 79, 82, 77, 78, 80, 46, 83, 170, 1, 84, 250, 195, 7, + 69, 196, 25, 7, 73, 68, 69, 78, 84, 73, 67, 214, 151, 4, 71, 38, 76, 243, + 77, 67, 10, 88, 3, 32, 83, 85, 52, 7, 78, 32, 69, 76, 69, 77, 69, 28, 2, + 83, 89, 139, 223, 7, 76, 4, 30, 66, 1, 3, 80, 69, 82, 2, 29, 2, 83, 69, + 2, 11, 78, 2, 243, 119, 84, 2, 37, 7, 77, 80, 84, 79, 84, 73, 67, 2, 17, + 2, 65, 76, 2, 201, 223, 7, 2, 76, 89, 4, 181, 174, 6, 14, 65, 76, 32, 83, + 85, 66, 71, 82, 79, 85, 80, 32, 79, 70, 2, 153, 223, 7, 6, 65, 82, 65, + 76, 76, 69, 6, 48, 6, 81, 85, 65, 82, 69, 32, 195, 254, 12, 73, 4, 68, 5, + 73, 77, 65, 71, 69, 1, 8, 79, 82, 73, 71, 73, 78, 65, 76, 2, 21, 3, 32, + 79, 70, 2, 183, 172, 6, 32, 4, 178, 163, 10, 82, 227, 202, 1, 73, 8, 58, + 76, 40, 4, 82, 73, 71, 72, 133, 1, 3, 85, 80, 80, 4, 36, 2, 69, 70, 133, + 1, 2, 79, 87, 2, 89, 20, 84, 32, 83, 69, 77, 73, 67, 73, 82, 67, 76, 69, + 32, 87, 73, 84, 72, 32, 84, 72, 2, 17, 2, 82, 69, 2, 207, 180, 12, 69, 2, + 11, 69, 2, 41, 8, 82, 32, 82, 73, 71, 72, 84, 45, 2, 153, 131, 3, 6, 83, + 72, 65, 68, 79, 87, 11, 34, 32, 53, 4, 66, 79, 79, 75, 4, 17, 2, 80, 65, + 4, 146, 234, 13, 71, 215, 22, 68, 5, 81, 18, 32, 87, 73, 84, 72, 32, 68, + 69, 67, 79, 82, 65, 84, 73, 86, 69, 32, 67, 2, 223, 251, 3, 79, 186, 6, + 102, 77, 176, 3, 4, 83, 72, 85, 32, 168, 157, 5, 8, 84, 32, 65, 78, 68, + 32, 66, 79, 131, 226, 7, 76, 26, 36, 4, 66, 69, 82, 32, 247, 2, 69, 24, + 58, 69, 50, 70, 42, 83, 66, 84, 57, 4, 78, 73, 78, 69, 4, 204, 1, 3, 73, + 71, 72, 21, 3, 76, 69, 86, 4, 144, 1, 2, 79, 85, 13, 2, 73, 70, 6, 34, + 73, 85, 4, 69, 86, 69, 78, 4, 82, 88, 239, 172, 13, 71, 8, 40, 2, 72, 73, + 46, 69, 21, 2, 87, 69, 2, 11, 82, 2, 17, 2, 84, 69, 2, 11, 69, 2, 143, + 175, 7, 78, 4, 248, 174, 7, 3, 76, 86, 69, 1, 3, 78, 84, 89, 2, 155, 221, + 6, 82, 154, 6, 72, 12, 67, 72, 65, 82, 65, 67, 84, 69, 82, 45, 49, 66, + 215, 222, 11, 73, 152, 6, 18, 49, 87, 50, 160, 2, 222, 1, 55, 2, 56, 2, + 57, 2, 65, 2, 66, 2, 67, 2, 68, 2, 69, 3, 70, 248, 3, 138, 1, 48, 2, 49, + 2, 50, 2, 51, 2, 52, 2, 53, 2, 54, 2, 55, 2, 56, 2, 57, 2, 65, 2, 66, 2, + 67, 2, 68, 2, 69, 143, 1, 70, 32, 246, 248, 13, 48, 2, 49, 2, 50, 2, 51, + 2, 52, 2, 53, 2, 54, 2, 55, 2, 56, 2, 57, 2, 65, 2, 66, 2, 67, 2, 68, 2, + 69, 3, 70, 24, 234, 247, 13, 48, 2, 49, 2, 50, 2, 51, 2, 52, 2, 53, 2, + 54, 2, 55, 2, 56, 2, 57, 2, 65, 3, 66, 142, 1, 108, 8, 67, 73, 82, 67, + 76, 69, 68, 32, 22, 76, 226, 3, 83, 160, 2, 5, 84, 79, 78, 69, 45, 223, + 129, 12, 68, 2, 211, 243, 13, 67, 92, 88, 6, 69, 84, 84, 69, 82, 32, 141, + 157, 1, 10, 79, 71, 79, 71, 82, 65, 77, 32, 78, 89, 90, 130, 2, 78, 90, + 84, 222, 188, 7, 88, 186, 116, 65, 146, 161, 1, 82, 188, 44, 2, 72, 65, + 226, 180, 1, 79, 222, 56, 68, 2, 77, 2, 80, 146, 198, 1, 69, 222, 61, 67, + 2, 70, 2, 71, 2, 75, 2, 76, 2, 81, 2, 83, 2, 86, 2, 89, 2, 90, 186, 2, + 73, 2, 85, 3, 87, 22, 86, 84, 158, 236, 11, 80, 238, 131, 2, 67, 2, 75, + 2, 81, 2, 82, 2, 89, 187, 2, 65, 6, 134, 240, 13, 83, 2, 88, 187, 2, 65, + 14, 64, 4, 73, 71, 78, 32, 185, 1, 7, 89, 76, 76, 65, 66, 76, 69, 12, 56, + 4, 70, 79, 82, 32, 137, 243, 12, 4, 88, 87, 32, 88, 10, 152, 9, 2, 76, + 79, 190, 147, 3, 84, 132, 89, 8, 73, 78, 86, 69, 82, 84, 69, 66, 154, + 168, 3, 80, 237, 86, 3, 65, 78, 73, 2, 221, 172, 11, 4, 32, 76, 69, 78, + 14, 246, 239, 13, 66, 2, 68, 2, 71, 2, 74, 2, 77, 2, 83, 3, 86, 214, 13, + 178, 2, 66, 226, 1, 67, 224, 5, 4, 70, 70, 73, 67, 54, 71, 248, 6, 4, 73, + 76, 32, 68, 22, 76, 222, 63, 78, 166, 5, 80, 214, 7, 82, 190, 10, 83, + 212, 8, 2, 84, 84, 154, 8, 85, 180, 1, 3, 86, 69, 82, 234, 159, 2, 89, + 138, 180, 5, 72, 190, 233, 1, 75, 174, 230, 1, 68, 230, 61, 77, 246, 9, + 87, 159, 137, 1, 88, 10, 132, 1, 6, 76, 73, 81, 85, 69, 32, 140, 152, 2, + 9, 83, 69, 82, 86, 69, 82, 32, 69, 89, 221, 28, 8, 74, 69, 67, 84, 32, + 82, 69, 80, 6, 160, 177, 4, 13, 65, 78, 71, 76, 69, 32, 79, 80, 69, 78, + 73, 78, 71, 191, 241, 1, 72, 28, 56, 2, 82, 32, 234, 4, 84, 229, 172, 5, + 3, 67, 85, 76, 22, 156, 1, 11, 65, 77, 79, 85, 78, 84, 32, 79, 70, 32, + 67, 22, 66, 198, 1, 67, 118, 68, 106, 70, 0, 10, 73, 78, 86, 69, 82, 84, + 69, 68, 32, 70, 175, 149, 12, 72, 2, 207, 158, 5, 72, 6, 136, 1, 15, 82, + 65, 78, 67, 72, 32, 66, 65, 78, 75, 32, 73, 68, 69, 78, 144, 233, 4, 5, + 69, 76, 84, 32, 66, 201, 225, 5, 3, 79, 87, 32, 2, 21, 3, 84, 73, 70, 2, + 11, 73, 2, 199, 187, 10, 67, 4, 92, 17, 85, 83, 84, 79, 77, 69, 82, 32, + 65, 67, 67, 79, 85, 78, 84, 32, 78, 227, 195, 1, 72, 2, 159, 135, 6, 85, + 4, 44, 5, 79, 85, 66, 76, 69, 171, 129, 12, 65, 2, 11, 32, 2, 11, 66, 2, + 181, 133, 7, 3, 65, 67, 75, 2, 247, 164, 13, 79, 4, 184, 206, 8, 4, 65, + 71, 79, 78, 209, 148, 3, 2, 79, 80, 2, 11, 69, 2, 213, 215, 7, 5, 32, 66, + 85, 73, 76, 60, 48, 4, 72, 65, 77, 32, 177, 225, 13, 2, 79, 78, 58, 122, + 70, 0, 10, 82, 69, 86, 69, 82, 83, 69, 68, 32, 70, 36, 7, 76, 69, 84, 84, + 69, 82, 32, 161, 231, 3, 3, 83, 80, 65, 2, 177, 244, 3, 4, 69, 65, 84, + 72, 52, 196, 1, 2, 65, 73, 22, 66, 2, 80, 34, 67, 36, 2, 69, 65, 64, 2, + 70, 69, 22, 71, 22, 73, 58, 76, 2, 82, 22, 78, 46, 79, 34, 83, 50, 85, + 150, 178, 1, 77, 170, 9, 68, 149, 138, 11, 3, 84, 73, 78, 2, 147, 209, + 13, 76, 2, 11, 69, 2, 199, 226, 11, 73, 4, 138, 239, 7, 69, 255, 237, 3, + 79, 6, 138, 1, 66, 2, 68, 201, 247, 3, 6, 77, 72, 65, 78, 67, 72, 2, 199, + 130, 9, 65, 2, 199, 217, 12, 79, 4, 32, 2, 79, 68, 207, 224, 12, 70, 2, + 235, 224, 7, 72, 2, 135, 195, 11, 85, 4, 176, 204, 12, 3, 71, 69, 65, + 207, 67, 73, 4, 222, 143, 13, 78, 215, 79, 82, 4, 158, 178, 11, 65, 161, + 171, 1, 3, 84, 82, 65, 6, 60, 5, 73, 76, 76, 69, 65, 162, 223, 11, 65, + 135, 255, 1, 82, 2, 207, 142, 13, 78, 2, 155, 182, 12, 82, 220, 7, 64, 7, + 32, 67, 72, 73, 75, 73, 32, 206, 6, 68, 167, 218, 12, 73, 96, 132, 1, 7, + 76, 69, 84, 84, 69, 82, 32, 148, 3, 2, 77, 85, 62, 71, 74, 80, 164, 198, + 3, 2, 82, 69, 214, 163, 8, 68, 243, 167, 1, 65, 60, 50, 65, 98, 69, 54, + 73, 50, 76, 62, 79, 51, 85, 16, 50, 65, 242, 218, 13, 78, 86, 71, 2, 76, + 3, 84, 8, 194, 219, 13, 74, 2, 75, 2, 77, 3, 87, 8, 130, 149, 13, 68, + 198, 13, 82, 210, 56, 78, 3, 80, 8, 154, 201, 13, 78, 202, 17, 72, 2, 82, + 3, 83, 12, 134, 153, 8, 65, 174, 193, 5, 69, 2, 73, 2, 79, 3, 85, 8, 202, + 189, 13, 84, 174, 28, 66, 2, 72, 3, 86, 8, 242, 137, 13, 78, 214, 79, 67, + 2, 68, 3, 89, 4, 56, 2, 45, 71, 221, 242, 11, 6, 32, 84, 84, 85, 68, 68, + 2, 217, 242, 11, 13, 65, 65, 72, 76, 65, 65, 32, 84, 84, 85, 68, 68, 65, + 6, 84, 11, 85, 78, 67, 84, 85, 65, 84, 73, 79, 78, 32, 137, 197, 6, 4, + 72, 65, 65, 82, 4, 48, 8, 68, 79, 85, 66, 76, 69, 32, 77, 3, 77, 2, 229, + 144, 13, 3, 85, 67, 65, 250, 6, 34, 32, 225, 55, 3, 69, 82, 32, 244, 6, + 240, 2, 8, 67, 72, 73, 78, 69, 83, 69, 32, 44, 10, 72, 85, 78, 71, 65, + 82, 73, 65, 78, 32, 244, 6, 7, 73, 84, 65, 76, 73, 67, 32, 212, 4, 14, + 78, 79, 82, 84, 72, 32, 65, 82, 65, 66, 73, 65, 78, 32, 196, 4, 3, 80, + 69, 82, 164, 12, 2, 83, 79, 144, 13, 14, 84, 85, 82, 75, 73, 67, 32, 76, + 69, 84, 84, 69, 82, 32, 132, 7, 7, 85, 89, 71, 72, 85, 82, 32, 151, 140, + 11, 75, 4, 166, 183, 11, 73, 205, 91, 3, 72, 79, 79, 216, 1, 96, 6, 67, + 65, 80, 73, 84, 65, 0, 4, 83, 77, 65, 76, 221, 5, 7, 78, 85, 77, 66, 69, + 82, 32, 102, 45, 9, 76, 32, 76, 69, 84, 84, 69, 82, 32, 102, 226, 1, 65, + 54, 69, 164, 2, 10, 78, 73, 75, 79, 76, 83, 66, 85, 82, 71, 0, 9, 82, 85, + 68, 73, 77, 69, 78, 84, 65, 42, 79, 34, 85, 132, 223, 3, 5, 67, 76, 79, + 83, 69, 178, 231, 7, 73, 237, 200, 1, 6, 83, 72, 79, 82, 84, 32, 11, 250, + 149, 12, 77, 146, 116, 78, 150, 70, 65, 3, 75, 63, 174, 1, 77, 22, 78, + 78, 83, 146, 218, 9, 67, 86, 71, 2, 76, 2, 84, 154, 239, 1, 90, 226, 131, + 2, 66, 2, 68, 2, 69, 2, 70, 2, 72, 2, 74, 2, 75, 2, 80, 2, 82, 3, 86, 5, + 187, 206, 13, 80, 11, 34, 84, 134, 206, 13, 67, 3, 89, 5, 165, 145, 2, 5, + 45, 83, 72, 65, 80, 5, 219, 205, 13, 90, 4, 11, 32, 4, 230, 182, 13, 79, + 3, 85, 7, 202, 182, 13, 69, 215, 22, 79, 9, 230, 201, 13, 78, 154, 3, 83, + 3, 85, 12, 210, 4, 70, 234, 237, 5, 79, 171, 137, 6, 84, 78, 80, 7, 76, + 69, 84, 84, 69, 82, 32, 169, 3, 8, 78, 85, 77, 69, 82, 65, 76, 32, 70, + 190, 1, 69, 90, 75, 50, 83, 36, 3, 78, 79, 82, 206, 249, 9, 85, 210, 200, + 1, 73, 198, 134, 1, 80, 2, 84, 254, 82, 67, 186, 22, 66, 2, 68, 2, 72, 2, + 86, 2, 89, 2, 90, 214, 22, 65, 3, 79, 23, 198, 214, 9, 83, 238, 239, 1, + 82, 146, 198, 1, 75, 210, 61, 70, 2, 76, 2, 77, 3, 78, 8, 230, 178, 13, + 72, 214, 22, 65, 2, 69, 3, 85, 4, 32, 2, 79, 85, 151, 178, 13, 72, 2, 29, + 5, 84, 72, 69, 82, 78, 2, 209, 191, 12, 2, 32, 84, 8, 38, 70, 146, 247, + 11, 84, 227, 55, 79, 4, 11, 73, 4, 130, 222, 11, 70, 163, 211, 1, 86, 64, + 76, 7, 76, 69, 84, 84, 69, 82, 32, 209, 3, 7, 78, 85, 77, 66, 69, 82, 32, + 58, 210, 1, 65, 38, 71, 38, 72, 30, 75, 38, 84, 74, 90, 246, 104, 77, + 244, 138, 3, 2, 69, 83, 218, 156, 3, 66, 2, 70, 2, 82, 2, 89, 242, 161, + 3, 78, 246, 215, 1, 76, 150, 55, 68, 146, 1, 81, 254, 2, 87, 255, 55, 83, + 4, 138, 180, 3, 76, 211, 193, 9, 73, 4, 218, 153, 12, 72, 135, 153, 1, + 69, 4, 214, 195, 13, 65, 3, 69, 4, 130, 140, 6, 72, 191, 183, 6, 65, 8, + 34, 72, 246, 194, 13, 65, 3, 69, 4, 230, 186, 12, 65, 143, 136, 1, 69, 4, + 11, 65, 4, 254, 243, 12, 73, 215, 79, 72, 6, 190, 131, 6, 84, 227, 166, + 6, 79, 178, 1, 64, 11, 77, 73, 67, 32, 76, 69, 84, 84, 69, 82, 32, 183, + 5, 83, 76, 228, 1, 2, 67, 72, 22, 68, 66, 69, 22, 73, 30, 77, 2, 78, 30, + 80, 22, 83, 70, 84, 50, 86, 38, 89, 94, 90, 218, 172, 6, 76, 2, 82, 254, + 209, 2, 71, 230, 255, 1, 79, 190, 198, 1, 66, 242, 40, 65, 242, 31, 75, + 174, 45, 72, 187, 2, 85, 2, 171, 180, 7, 69, 6, 26, 90, 219, 172, 13, 79, + 4, 138, 254, 8, 72, 219, 157, 4, 73, 5, 139, 192, 13, 70, 7, 246, 191, + 13, 65, 3, 69, 2, 249, 168, 13, 2, 69, 78, 2, 223, 174, 6, 69, 6, 26, 72, + 187, 171, 13, 73, 4, 232, 252, 8, 3, 67, 72, 79, 3, 79, 4, 26, 83, 247, + 170, 13, 65, 2, 227, 153, 13, 73, 4, 146, 252, 8, 79, 215, 137, 4, 69, + 14, 60, 2, 69, 82, 226, 136, 8, 65, 174, 163, 5, 82, 203, 17, 85, 7, 210, + 189, 13, 73, 3, 85, 4, 146, 251, 8, 72, 219, 157, 4, 65, 102, 52, 4, 73, + 65, 78, 32, 213, 153, 1, 3, 79, 78, 65, 100, 80, 7, 78, 85, 77, 66, 69, + 82, 32, 80, 5, 83, 73, 71, 78, 32, 139, 154, 10, 87, 10, 42, 84, 186, + 147, 8, 72, 147, 143, 4, 79, 6, 162, 228, 1, 87, 231, 135, 11, 69, 88, + 210, 1, 65, 86, 66, 62, 68, 98, 74, 2, 86, 30, 84, 42, 88, 226, 109, 71, + 2, 75, 2, 78, 2, 82, 250, 228, 8, 77, 214, 156, 3, 83, 206, 69, 67, 2, + 70, 2, 72, 2, 76, 2, 80, 2, 89, 2, 90, 186, 2, 73, 3, 85, 9, 45, 9, 85, + 82, 65, 77, 65, 90, 68, 65, 65, 7, 222, 213, 6, 45, 159, 225, 6, 72, 6, + 38, 65, 165, 250, 9, 3, 85, 85, 77, 5, 175, 182, 13, 71, 10, 34, 65, 178, + 184, 13, 73, 3, 85, 7, 37, 7, 72, 89, 65, 65, 85, 83, 72, 5, 179, 212, 6, + 45, 4, 242, 183, 13, 65, 3, 73, 6, 158, 181, 13, 72, 186, 2, 65, 3, 85, + 4, 132, 137, 11, 8, 83, 72, 65, 65, 89, 65, 84, 72, 171, 174, 2, 65, 144, + 1, 92, 6, 71, 68, 73, 65, 78, 32, 141, 7, 12, 85, 84, 72, 32, 65, 82, 65, + 66, 73, 65, 78, 32, 80, 58, 70, 74, 76, 145, 5, 7, 78, 85, 77, 66, 69, + 82, 32, 2, 11, 82, 2, 157, 155, 11, 10, 65, 67, 84, 73, 79, 78, 32, 79, + 78, 69, 60, 76, 6, 69, 84, 84, 69, 82, 32, 149, 4, 8, 73, 71, 65, 84, 85, + 82, 69, 32, 58, 234, 1, 65, 96, 6, 70, 73, 78, 65, 76, 32, 200, 1, 5, 82, + 69, 83, 72, 45, 230, 214, 1, 76, 178, 151, 4, 71, 90, 90, 34, 83, 66, 89, + 154, 193, 1, 72, 234, 5, 75, 130, 76, 66, 190, 173, 4, 78, 254, 1, 84, 2, + 87, 202, 103, 80, 171, 4, 77, 6, 26, 76, 243, 178, 12, 89, 4, 244, 240, + 5, 8, 84, 69, 82, 78, 65, 84, 69, 32, 239, 199, 1, 69, 18, 116, 3, 78, + 85, 78, 0, 5, 83, 65, 68, 72, 69, 0, 3, 84, 65, 87, 130, 215, 1, 65, 158, + 172, 6, 66, 131, 151, 5, 72, 5, 41, 8, 32, 87, 73, 84, 72, 32, 86, 69, 2, + 209, 199, 5, 4, 82, 84, 73, 67, 2, 193, 214, 1, 6, 65, 89, 73, 78, 45, + 68, 18, 42, 84, 158, 239, 5, 79, 143, 211, 5, 70, 10, 42, 72, 230, 215, + 1, 87, 231, 135, 11, 69, 4, 230, 194, 11, 82, 159, 2, 73, 64, 60, 7, 76, + 69, 84, 84, 69, 82, 32, 245, 3, 3, 78, 85, 77, 58, 202, 1, 65, 38, 68, + 74, 71, 34, 75, 34, 83, 78, 84, 218, 43, 90, 230, 165, 1, 76, 50, 81, + 206, 194, 1, 82, 238, 213, 2, 89, 154, 193, 1, 72, 234, 81, 66, 190, 173, + 4, 78, 254, 1, 87, 202, 103, 70, 171, 4, 77, 4, 202, 155, 3, 76, 211, + 193, 9, 89, 6, 32, 2, 72, 65, 219, 210, 1, 65, 4, 210, 254, 7, 76, 203, + 128, 5, 68, 4, 226, 44, 72, 163, 189, 5, 73, 4, 154, 178, 7, 65, 247, 75, + 72, 8, 26, 65, 239, 171, 12, 72, 6, 226, 163, 7, 77, 186, 218, 5, 68, + 143, 45, 84, 8, 166, 90, 72, 206, 209, 10, 69, 247, 128, 1, 65, 6, 56, 4, + 66, 69, 82, 32, 245, 240, 12, 4, 69, 82, 73, 67, 4, 26, 70, 223, 144, 12, + 79, 2, 207, 190, 11, 73, 146, 1, 80, 7, 79, 82, 75, 72, 79, 78, 32, 197, + 3, 8, 89, 69, 78, 73, 83, 69, 73, 32, 84, 54, 65, 202, 1, 69, 122, 73, + 30, 79, 203, 192, 11, 66, 45, 106, 69, 130, 180, 9, 83, 226, 243, 3, 66, + 2, 68, 2, 71, 2, 76, 2, 78, 2, 81, 2, 82, 2, 84, 3, 89, 20, 222, 167, 13, + 66, 2, 68, 2, 71, 2, 75, 2, 76, 2, 78, 2, 82, 2, 83, 2, 84, 3, 89, 20, + 74, 78, 142, 138, 13, 76, 158, 27, 83, 146, 1, 67, 2, 77, 2, 80, 3, 90, + 8, 182, 166, 13, 67, 2, 71, 2, 84, 3, 89, 7, 138, 166, 13, 67, 3, 81, 13, + 130, 3, 69, 238, 162, 13, 80, 2, 81, 3, 84, 62, 38, 65, 170, 1, 69, 86, + 73, 23, 79, 39, 98, 69, 166, 163, 13, 83, 62, 78, 86, 66, 2, 68, 2, 71, + 2, 76, 2, 81, 2, 82, 2, 84, 3, 89, 17, 158, 172, 11, 78, 150, 248, 1, 66, + 2, 71, 2, 75, 2, 84, 3, 89, 15, 46, 78, 178, 162, 13, 83, 146, 1, 67, 3, + 90, 6, 190, 163, 13, 67, 2, 84, 3, 89, 5, 155, 163, 13, 81, 6, 26, 69, + 239, 162, 13, 81, 5, 235, 162, 13, 75, 52, 148, 1, 10, 67, 79, 77, 66, + 73, 78, 73, 78, 71, 32, 36, 7, 76, 69, 84, 84, 69, 82, 32, 233, 1, 12, + 80, 85, 78, 67, 84, 85, 65, 84, 73, 79, 78, 32, 8, 146, 221, 5, 84, 243, + 213, 3, 68, 36, 170, 199, 1, 65, 178, 195, 1, 82, 214, 212, 2, 76, 58, + 90, 34, 83, 66, 89, 252, 195, 1, 6, 70, 73, 78, 65, 76, 32, 0, 6, 71, 73, + 77, 69, 76, 45, 134, 3, 75, 130, 76, 66, 190, 173, 4, 78, 254, 1, 84, 2, + 87, 202, 103, 80, 171, 4, 77, 8, 52, 4, 84, 87, 79, 32, 166, 130, 11, 70, + 179, 122, 66, 4, 150, 138, 12, 66, 71, 68, 6, 170, 180, 1, 87, 152, 140, + 3, 3, 65, 68, 85, 235, 150, 7, 77, 22, 212, 1, 34, 32, 87, 73, 84, 72, + 32, 69, 88, 67, 76, 65, 77, 65, 84, 73, 79, 78, 32, 77, 65, 82, 75, 32, + 87, 73, 84, 72, 32, 76, 69, 70, 84, 32, 82, 44, 7, 67, 79, 77, 73, 78, + 71, 32, 210, 1, 69, 239, 202, 12, 73, 2, 21, 3, 73, 71, 72, 2, 151, 197, + 9, 84, 10, 144, 1, 6, 65, 85, 84, 79, 77, 79, 20, 7, 70, 73, 82, 69, 32, + 69, 78, 20, 6, 80, 79, 76, 73, 67, 69, 184, 212, 2, 2, 84, 65, 191, 195, + 8, 66, 2, 135, 253, 10, 66, 2, 211, 129, 12, 71, 2, 135, 206, 9, 32, 8, + 70, 32, 245, 230, 11, 11, 45, 80, 73, 69, 67, 69, 32, 83, 87, 73, 77, 6, + 40, 4, 68, 79, 84, 32, 147, 234, 9, 66, 4, 26, 79, 235, 235, 9, 76, 2, + 169, 221, 2, 11, 86, 69, 82, 32, 84, 87, 79, 32, 68, 79, 84, 46, 82, 69, + 168, 6, 2, 84, 73, 148, 143, 11, 5, 72, 73, 85, 67, 72, 167, 177, 1, 80, + 36, 70, 78, 181, 5, 12, 82, 65, 84, 73, 78, 71, 32, 83, 89, 83, 84, 69, + 34, 22, 32, 247, 3, 45, 28, 108, 2, 66, 79, 32, 7, 67, 69, 78, 84, 82, + 69, 32, 114, 70, 50, 72, 42, 77, 202, 233, 6, 83, 239, 194, 3, 76, 4, + 190, 147, 13, 79, 155, 3, 88, 8, 50, 84, 238, 130, 11, 66, 222, 2, 65, + 219, 82, 67, 2, 37, 7, 69, 65, 82, 68, 82, 79, 80, 2, 207, 132, 11, 45, + 4, 180, 255, 1, 5, 73, 76, 69, 32, 70, 15, 79, 2, 17, 2, 65, 78, 2, 187, + 251, 9, 68, 4, 57, 12, 65, 73, 76, 66, 79, 88, 32, 87, 73, 84, 72, 32, 4, + 44, 3, 76, 79, 87, 21, 4, 82, 65, 73, 83, 2, 17, 2, 69, 82, 2, 205, 173, + 11, 2, 69, 68, 6, 108, 15, 67, 73, 82, 67, 85, 73, 84, 45, 79, 85, 84, + 80, 85, 84, 32, 217, 242, 11, 6, 79, 85, 84, 76, 73, 78, 4, 18, 72, 3, + 76, 2, 229, 190, 1, 4, 45, 84, 89, 80, 2, 189, 132, 12, 6, 77, 32, 67, + 79, 77, 77, 6, 64, 2, 79, 78, 153, 177, 1, 8, 67, 65, 76, 32, 68, 73, 83, + 67, 2, 235, 250, 10, 32, 204, 1, 132, 1, 3, 65, 78, 71, 66, 73, 212, 8, + 5, 78, 65, 84, 69, 32, 192, 225, 3, 5, 84, 72, 79, 68, 79, 254, 186, 1, + 32, 227, 231, 5, 67, 6, 28, 2, 69, 32, 239, 21, 85, 4, 154, 191, 11, 66, + 211, 73, 72, 188, 1, 48, 5, 71, 73, 78, 65, 76, 21, 3, 89, 65, 32, 2, + 151, 133, 1, 32, 186, 1, 106, 65, 30, 70, 250, 1, 73, 32, 7, 76, 69, 84, + 84, 69, 82, 32, 142, 2, 83, 214, 1, 86, 243, 153, 11, 68, 4, 182, 142, 8, + 73, 3, 85, 12, 41, 8, 82, 65, 67, 84, 73, 79, 78, 32, 12, 56, 4, 79, 78, + 69, 32, 81, 6, 84, 72, 82, 69, 69, 32, 8, 42, 83, 170, 140, 11, 69, 46, + 72, 43, 81, 2, 177, 141, 11, 4, 73, 88, 84, 69, 4, 26, 83, 187, 142, 11, + 81, 2, 249, 223, 7, 4, 73, 88, 84, 69, 2, 225, 233, 11, 3, 83, 83, 72, + 104, 226, 1, 82, 166, 212, 6, 89, 150, 205, 2, 65, 38, 68, 46, 84, 46, + 86, 186, 24, 85, 210, 200, 1, 73, 42, 76, 246, 189, 1, 78, 46, 83, 82, + 66, 2, 67, 2, 71, 2, 74, 2, 75, 2, 80, 254, 68, 72, 2, 77, 2, 87, 186, 2, + 69, 3, 79, 6, 206, 135, 13, 72, 2, 82, 187, 2, 65, 18, 112, 20, 69, 81, + 85, 69, 78, 67, 69, 32, 70, 79, 82, 32, 76, 69, 84, 84, 69, 82, 32, 82, + 29, 4, 73, 71, 78, 32, 4, 178, 134, 13, 72, 3, 82, 14, 222, 161, 9, 65, + 74, 67, 98, 78, 234, 128, 2, 79, 227, 161, 1, 86, 26, 49, 10, 79, 87, 69, + 76, 32, 83, 73, 71, 78, 32, 26, 254, 162, 9, 65, 106, 86, 214, 20, 85, + 210, 200, 1, 73, 206, 134, 2, 69, 3, 79, 4, 242, 171, 9, 76, 27, 82, 226, + 1, 76, 4, 65, 71, 69, 32, 164, 4, 6, 77, 65, 78, 89, 65, 32, 247, 129, + 13, 67, 144, 1, 56, 6, 67, 65, 80, 73, 84, 65, 1, 4, 83, 77, 65, 76, 72, + 45, 9, 76, 32, 76, 69, 84, 84, 69, 82, 32, 72, 194, 1, 65, 38, 69, 114, + 75, 42, 79, 22, 84, 178, 204, 6, 72, 170, 190, 4, 67, 2, 68, 2, 71, 138, + 176, 1, 83, 2, 90, 130, 3, 66, 254, 65, 76, 2, 77, 2, 78, 2, 80, 2, 87, + 186, 2, 73, 3, 85, 9, 226, 139, 11, 73, 131, 248, 1, 72, 15, 26, 72, 211, + 179, 12, 73, 10, 50, 84, 182, 139, 11, 67, 134, 245, 1, 75, 3, 80, 4, + 182, 128, 13, 83, 187, 2, 65, 6, 150, 128, 13, 72, 2, 89, 187, 2, 65, 5, + 211, 178, 12, 73, 6, 222, 186, 12, 83, 183, 71, 65, 80, 52, 7, 76, 69, + 84, 84, 69, 82, 32, 163, 147, 11, 68, 60, 246, 1, 65, 38, 67, 22, 68, 38, + 75, 34, 83, 30, 77, 130, 229, 2, 81, 174, 218, 7, 79, 204, 119, 2, 76, + 65, 156, 71, 2, 78, 85, 254, 1, 87, 138, 62, 69, 222, 61, 66, 2, 70, 2, + 71, 2, 72, 2, 74, 2, 82, 2, 84, 2, 88, 2, 89, 186, 2, 73, 3, 85, 7, 158, + 238, 2, 76, 167, 145, 10, 65, 2, 195, 129, 12, 65, 4, 178, 158, 8, 69, + 163, 222, 4, 72, 4, 206, 253, 11, 65, 227, 126, 72, 4, 26, 72, 175, 254, + 12, 65, 2, 239, 254, 11, 73, 124, 68, 11, 79, 77, 65, 78, 32, 83, 73, 89, + 65, 81, 32, 131, 197, 12, 69, 122, 172, 1, 17, 65, 76, 84, 69, 82, 78, + 65, 84, 69, 32, 78, 85, 77, 66, 69, 82, 32, 200, 1, 13, 70, 82, 65, 67, + 84, 73, 79, 78, 32, 79, 78, 69, 32, 48, 3, 77, 65, 82, 47, 78, 26, 54, + 70, 50, 83, 46, 84, 238, 225, 11, 78, 211, 110, 69, 6, 208, 187, 5, 3, + 79, 85, 82, 211, 195, 6, 73, 6, 160, 187, 5, 2, 73, 88, 171, 211, 5, 69, + 10, 138, 173, 2, 69, 12, 2, 87, 79, 183, 225, 8, 72, 4, 26, 83, 163, 250, + 10, 72, 2, 139, 251, 10, 73, 2, 11, 82, 2, 11, 65, 2, 219, 178, 11, 84, + 90, 33, 6, 85, 77, 66, 69, 82, 32, 90, 58, 69, 66, 70, 94, 78, 26, 83, + 78, 84, 131, 157, 5, 79, 10, 25, 4, 73, 71, 72, 84, 11, 138, 171, 2, 89, + 191, 165, 5, 32, 20, 18, 73, 35, 79, 10, 166, 2, 70, 147, 156, 5, 86, 10, + 134, 2, 82, 157, 156, 5, 2, 85, 82, 10, 65, 3, 73, 78, 69, 20, 40, 4, 69, + 86, 69, 78, 1, 2, 73, 88, 11, 166, 1, 84, 223, 205, 7, 32, 24, 34, 72, + 50, 87, 203, 168, 2, 69, 10, 34, 73, 197, 156, 5, 2, 82, 69, 4, 51, 82, + 10, 26, 69, 171, 156, 5, 79, 4, 11, 78, 4, 11, 84, 4, 159, 168, 2, 89, + 12, 34, 84, 133, 222, 10, 2, 78, 67, 10, 42, 66, 37, 6, 76, 73, 78, 69, + 68, 32, 2, 181, 233, 11, 4, 79, 88, 32, 84, 8, 254, 252, 2, 76, 254, 174, + 3, 87, 250, 181, 4, 66, 239, 13, 71, 12, 18, 72, 35, 76, 2, 245, 227, 11, + 3, 69, 65, 84, 10, 32, 2, 65, 80, 227, 218, 11, 73, 9, 29, 5, 80, 73, 78, + 71, 32, 6, 40, 6, 87, 72, 73, 84, 69, 32, 51, 66, 4, 44, 5, 65, 78, 68, + 32, 66, 247, 199, 9, 83, 2, 221, 199, 9, 4, 76, 65, 67, 75, 144, 13, 194, + 1, 65, 174, 65, 68, 30, 69, 194, 13, 72, 134, 25, 73, 206, 4, 76, 150, + 15, 79, 234, 8, 82, 208, 15, 15, 83, 65, 76, 84, 69, 82, 32, 80, 65, 72, + 76, 65, 86, 73, 32, 214, 5, 85, 151, 215, 11, 77, 154, 6, 134, 2, 68, 38, + 71, 212, 1, 11, 72, 65, 87, 72, 32, 72, 77, 79, 78, 71, 32, 138, 23, 76, + 130, 6, 78, 58, 82, 156, 22, 2, 83, 83, 132, 2, 10, 85, 32, 67, 73, 78, + 32, 72, 65, 85, 32, 180, 7, 3, 87, 32, 80, 172, 213, 7, 2, 67, 75, 145, + 217, 4, 4, 80, 69, 82, 67, 5, 157, 184, 1, 4, 68, 73, 78, 71, 14, 26, 69, + 191, 201, 12, 79, 13, 34, 32, 158, 238, 12, 82, 3, 83, 6, 72, 6, 87, 73, + 84, 72, 32, 67, 149, 139, 4, 6, 70, 65, 67, 73, 78, 71, 4, 50, 85, 181, + 197, 7, 6, 73, 82, 67, 76, 69, 68, 2, 255, 227, 11, 82, 254, 1, 190, 1, + 67, 160, 6, 9, 77, 65, 82, 75, 32, 67, 73, 77, 32, 160, 1, 7, 78, 85, 77, + 66, 69, 82, 32, 244, 1, 5, 83, 73, 71, 78, 32, 148, 10, 7, 86, 79, 87, + 69, 76, 32, 75, 227, 233, 10, 68, 78, 92, 9, 76, 65, 78, 32, 83, 73, 71, + 78, 32, 137, 3, 9, 79, 78, 83, 79, 78, 65, 78, 84, 32, 38, 132, 1, 2, 72, + 65, 38, 75, 46, 76, 34, 84, 82, 86, 30, 89, 148, 9, 2, 88, 89, 176, 5, 2, + 80, 72, 174, 1, 70, 165, 2, 2, 77, 85, 4, 162, 186, 2, 87, 187, 175, 10, + 77, 6, 250, 15, 72, 202, 186, 12, 79, 159, 14, 87, 4, 214, 12, 65, 231, + 158, 12, 73, 8, 22, 83, 247, 9, 72, 6, 152, 185, 2, 3, 72, 69, 69, 150, + 245, 8, 65, 3, 87, 4, 226, 184, 2, 65, 3, 87, 4, 198, 184, 2, 65, 223, + 233, 9, 69, 40, 122, 67, 38, 72, 46, 78, 60, 2, 80, 76, 2, 81, 222, 210, + 2, 76, 2, 77, 2, 82, 2, 86, 2, 88, 2, 89, 147, 238, 9, 65, 4, 230, 211, + 2, 72, 147, 238, 9, 65, 6, 194, 211, 2, 76, 2, 78, 147, 238, 9, 65, 12, + 58, 67, 22, 84, 202, 210, 2, 75, 2, 76, 147, 238, 9, 65, 2, 219, 210, 2, + 72, 4, 198, 210, 2, 72, 3, 83, 14, 42, 75, 50, 83, 38, 84, 195, 211, 12, + 72, 4, 26, 72, 143, 167, 12, 69, 2, 183, 138, 6, 65, 4, 138, 171, 11, 85, + 191, 185, 1, 79, 4, 254, 169, 11, 85, 179, 18, 65, 14, 52, 7, 72, 85, 78, + 68, 82, 69, 68, 38, 84, 79, 77, 4, 108, 2, 32, 77, 223, 226, 12, 83, 8, + 24, 2, 69, 78, 51, 82, 6, 26, 32, 243, 226, 12, 83, 4, 18, 66, 35, 84, 2, + 145, 194, 4, 3, 73, 76, 76, 2, 11, 72, 2, 137, 185, 9, 3, 79, 85, 83, 72, + 188, 1, 4, 67, 73, 77, 32, 250, 2, 72, 32, 3, 73, 66, 32, 22, 77, 86, 78, + 50, 84, 124, 4, 86, 79, 83, 32, 198, 1, 88, 208, 1, 6, 90, 87, 74, 32, + 84, 72, 150, 176, 1, 76, 219, 205, 4, 65, 16, 174, 1, 67, 84, 5, 78, 82, + 69, 83, 32, 22, 84, 148, 164, 11, 7, 80, 85, 66, 32, 68, 65, 87, 197, + 185, 1, 16, 72, 65, 73, 83, 32, 76, 85, 83, 32, 78, 84, 79, 71, 32, 78, + 84, 4, 48, 7, 85, 65, 77, 32, 84, 83, 72, 131, 4, 72, 2, 11, 79, 2, 167, + 175, 2, 79, 2, 207, 182, 1, 84, 6, 56, 3, 88, 87, 86, 157, 221, 12, 5, + 83, 79, 86, 32, 82, 5, 213, 131, 6, 4, 32, 67, 72, 87, 4, 214, 72, 78, + 171, 129, 12, 76, 2, 251, 163, 11, 89, 6, 40, 4, 69, 69, 74, 32, 171, + 159, 12, 85, 4, 128, 3, 2, 84, 83, 57, 2, 83, 85, 4, 26, 84, 231, 213, 8, + 81, 2, 251, 172, 2, 85, 6, 196, 1, 7, 88, 72, 69, 69, 74, 32, 67, 216, + 139, 8, 12, 72, 73, 82, 68, 45, 83, 84, 65, 71, 69, 32, 72, 155, 170, 4, + 65, 14, 54, 70, 22, 83, 30, 84, 190, 69, 76, 163, 212, 7, 78, 2, 191, + 200, 12, 69, 2, 177, 128, 6, 2, 69, 69, 6, 42, 72, 29, 6, 83, 72, 65, 66, + 32, 67, 4, 82, 73, 231, 200, 12, 79, 2, 223, 188, 5, 69, 14, 34, 73, 22, + 89, 191, 214, 10, 65, 2, 151, 159, 11, 65, 10, 40, 4, 69, 69, 77, 32, + 139, 186, 12, 79, 8, 84, 3, 78, 84, 88, 128, 254, 5, 2, 84, 79, 142, 158, + 2, 82, 233, 129, 3, 2, 70, 65, 2, 255, 253, 5, 73, 2, 215, 168, 2, 65, + 56, 50, 65, 66, 69, 38, 73, 2, 85, 38, 79, 39, 87, 20, 170, 1, 65, 2, 73, + 2, 85, 2, 87, 158, 214, 12, 66, 3, 86, 8, 106, 69, 158, 214, 12, 66, 3, + 86, 8, 70, 65, 158, 214, 12, 66, 3, 86, 8, 34, 79, 158, 214, 12, 66, 3, + 86, 4, 154, 214, 12, 66, 3, 86, 76, 18, 76, 23, 77, 2, 155, 152, 12, 65, + 74, 74, 32, 104, 6, 89, 82, 69, 78, 69, 32, 241, 249, 3, 4, 83, 32, 85, + 80, 8, 80, 3, 66, 82, 65, 250, 231, 10, 84, 192, 94, 4, 68, 79, 87, 78, + 1, 2, 85, 80, 2, 143, 178, 12, 78, 64, 80, 2, 76, 69, 40, 4, 82, 73, 71, + 72, 253, 2, 7, 78, 85, 77, 66, 69, 82, 32, 48, 38, 70, 89, 5, 84, 84, 69, + 82, 32, 2, 57, 12, 84, 45, 80, 79, 73, 78, 84, 73, 78, 71, 32, 70, 2, + 137, 209, 5, 2, 76, 69, 46, 224, 1, 5, 70, 73, 78, 65, 76, 30, 84, 246, + 118, 68, 34, 76, 50, 81, 206, 194, 1, 82, 134, 212, 2, 65, 50, 71, 90, + 90, 34, 83, 66, 89, 154, 193, 1, 72, 234, 5, 75, 130, 76, 66, 190, 173, + 4, 78, 254, 1, 87, 202, 103, 80, 171, 4, 77, 2, 209, 208, 11, 2, 32, 78, + 4, 202, 209, 10, 69, 247, 128, 1, 65, 14, 198, 120, 84, 198, 234, 9, 70, + 143, 84, 79, 4, 32, 2, 67, 65, 183, 144, 12, 68, 2, 251, 187, 11, 75, + 184, 2, 94, 65, 216, 1, 11, 69, 78, 84, 72, 69, 83, 73, 90, 69, 68, 32, + 242, 16, 84, 243, 235, 11, 82, 14, 80, 5, 71, 82, 65, 80, 72, 48, 5, 76, + 76, 69, 76, 32, 201, 138, 6, 2, 67, 72, 6, 206, 121, 85, 198, 187, 8, 32, + 175, 219, 2, 79, 6, 44, 5, 87, 73, 84, 72, 32, 191, 174, 12, 84, 4, 214, + 165, 6, 84, 151, 138, 4, 72, 150, 2, 252, 1, 7, 72, 65, 78, 71, 85, 76, + 32, 188, 4, 10, 73, 68, 69, 79, 71, 82, 65, 80, 72, 32, 188, 7, 18, 75, + 79, 82, 69, 65, 78, 32, 67, 72, 65, 82, 65, 67, 84, 69, 82, 32, 79, 44, + 7, 78, 85, 77, 66, 69, 82, 32, 138, 187, 4, 68, 197, 154, 2, 2, 76, 65, + 58, 102, 67, 110, 72, 30, 75, 66, 77, 34, 78, 34, 80, 62, 82, 30, 83, 26, + 84, 73, 5, 73, 69, 85, 78, 71, 10, 34, 72, 33, 4, 73, 69, 85, 67, 4, 141, + 3, 4, 73, 69, 85, 67, 7, 11, 32, 4, 206, 201, 12, 65, 3, 85, 4, 197, 2, + 3, 73, 69, 85, 8, 168, 2, 5, 72, 73, 69, 85, 75, 13, 5, 73, 89, 69, 79, + 75, 4, 245, 1, 4, 73, 69, 85, 77, 4, 213, 1, 4, 73, 69, 85, 78, 8, 168, + 1, 5, 72, 73, 69, 85, 80, 13, 4, 73, 69, 85, 80, 4, 121, 4, 73, 69, 85, + 76, 4, 93, 3, 73, 79, 83, 8, 56, 5, 72, 73, 69, 85, 84, 13, 5, 73, 75, + 69, 85, 84, 4, 11, 72, 5, 167, 196, 12, 32, 72, 148, 1, 2, 65, 76, 30, + 67, 74, 69, 82, 70, 112, 2, 76, 65, 22, 77, 38, 78, 32, 2, 82, 69, 78, + 83, 138, 2, 84, 50, 87, 134, 215, 10, 72, 159, 79, 79, 2, 225, 233, 7, 2, + 76, 73, 4, 32, 2, 79, 78, 199, 192, 10, 65, 2, 137, 212, 7, 4, 71, 82, + 65, 84, 6, 42, 78, 246, 253, 8, 65, 239, 155, 3, 73, 2, 169, 4, 5, 84, + 69, 82, 80, 82, 10, 58, 73, 156, 186, 11, 5, 69, 83, 84, 73, 86, 231, 16, + 79, 6, 208, 2, 3, 78, 65, 78, 158, 170, 12, 82, 3, 86, 2, 179, 138, 12, + 66, 4, 174, 245, 9, 69, 239, 253, 1, 79, 4, 194, 169, 11, 73, 195, 1, 65, + 8, 38, 83, 170, 178, 11, 80, 195, 109, 65, 4, 182, 179, 6, 79, 219, 142, + 6, 84, 18, 58, 69, 34, 79, 22, 80, 34, 84, 50, 85, 163, 180, 11, 73, 4, + 186, 240, 10, 86, 235, 79, 76, 2, 231, 212, 7, 67, 2, 11, 69, 2, 247, + 161, 4, 67, 4, 26, 85, 247, 145, 11, 79, 2, 247, 174, 12, 68, 4, 26, 80, + 147, 192, 12, 78, 2, 21, 3, 69, 82, 86, 2, 131, 183, 11, 73, 6, 162, 211, + 10, 72, 238, 156, 1, 69, 227, 48, 87, 4, 206, 157, 9, 79, 155, 235, 1, + 65, 4, 166, 253, 7, 32, 137, 242, 3, 2, 74, 69, 22, 42, 69, 46, 70, 42, + 78, 30, 83, 51, 84, 4, 216, 1, 3, 73, 71, 72, 243, 225, 4, 76, 4, 160, 1, + 2, 79, 85, 13, 2, 73, 70, 2, 133, 1, 3, 73, 78, 69, 4, 34, 73, 73, 4, 69, + 86, 69, 78, 2, 71, 88, 8, 34, 72, 46, 87, 247, 236, 11, 69, 2, 11, 73, 2, + 11, 82, 2, 219, 235, 10, 84, 4, 11, 69, 4, 198, 210, 10, 78, 179, 109, + 76, 18, 128, 1, 3, 73, 65, 76, 216, 1, 3, 89, 32, 80, 144, 141, 8, 6, 78, + 69, 82, 83, 72, 73, 189, 167, 3, 6, 32, 65, 76, 84, 69, 82, 12, 62, 32, + 189, 122, 10, 76, 89, 45, 82, 69, 67, 89, 67, 76, 69, 10, 38, 68, 41, 5, + 76, 73, 78, 69, 32, 2, 157, 155, 4, 5, 73, 70, 70, 69, 82, 8, 134, 186, + 3, 68, 242, 45, 70, 20, 4, 66, 65, 67, 75, 243, 209, 8, 85, 2, 235, 222, + 3, 79, 10, 98, 69, 52, 9, 73, 86, 69, 45, 80, 85, 76, 76, 45, 89, 9, 80, + 79, 82, 84, 32, 67, 79, 78, 84, 4, 182, 165, 11, 68, 145, 62, 5, 78, 71, + 69, 82, 32, 4, 40, 4, 68, 79, 87, 78, 1, 2, 85, 80, 2, 233, 155, 5, 6, + 45, 79, 85, 84, 80, 85, 2, 227, 164, 11, 82, 114, 192, 1, 12, 71, 76, 79, + 84, 84, 65, 76, 32, 83, 84, 79, 80, 62, 76, 160, 3, 3, 82, 73, 83, 36, + 14, 77, 73, 68, 45, 76, 69, 86, 69, 76, 32, 84, 79, 78, 69, 57, 7, 83, + 65, 78, 68, 72, 73, 32, 7, 11, 32, 4, 206, 5, 70, 197, 166, 11, 4, 86, + 65, 82, 73, 82, 72, 6, 69, 84, 84, 69, 82, 32, 213, 2, 7, 79, 87, 45, 70, + 65, 76, 76, 74, 206, 1, 70, 226, 241, 6, 73, 2, 85, 166, 242, 1, 78, 214, + 135, 3, 67, 2, 75, 2, 80, 2, 84, 254, 68, 66, 2, 68, 2, 71, 2, 72, 2, 76, + 2, 77, 2, 82, 2, 83, 2, 86, 2, 90, 186, 2, 65, 2, 69, 3, 79, 20, 44, 5, + 73, 78, 65, 76, 32, 223, 178, 12, 65, 18, 198, 186, 10, 78, 150, 248, 1, + 75, 2, 76, 2, 77, 2, 80, 2, 84, 2, 87, 3, 89, 8, 157, 1, 5, 73, 78, 71, + 32, 84, 7, 11, 32, 4, 192, 1, 5, 76, 79, 78, 71, 32, 15, 70, 12, 66, 84, + 73, 12, 71, 76, 79, 84, 84, 65, 76, 32, 83, 84, 79, 80, 8, 21, 3, 79, 78, + 69, 9, 11, 32, 6, 32, 4, 76, 79, 78, 71, 27, 70, 5, 11, 32, 2, 11, 70, 2, + 135, 181, 3, 73, 2, 223, 161, 4, 82, 4, 222, 175, 12, 70, 3, 73, 80, 130, + 1, 65, 122, 78, 162, 1, 82, 222, 9, 83, 44, 3, 84, 82, 73, 254, 16, 68, + 173, 192, 11, 9, 79, 80, 76, 69, 32, 72, 85, 71, 71, 12, 50, 67, 50, 78, + 218, 204, 6, 32, 135, 225, 5, 82, 6, 190, 255, 10, 79, 190, 27, 69, 147, + 147, 1, 72, 2, 199, 153, 11, 85, 10, 118, 71, 20, 3, 83, 73, 86, 190, + 171, 1, 84, 224, 172, 4, 10, 32, 79, 86, 69, 82, 32, 83, 84, 65, 77, 175, + 167, 4, 67, 2, 147, 173, 11, 85, 2, 167, 239, 11, 69, 48, 186, 1, 32, + 116, 10, 80, 69, 78, 68, 73, 67, 85, 76, 65, 82, 42, 83, 198, 136, 7, 67, + 224, 10, 10, 77, 65, 78, 69, 78, 84, 32, 80, 65, 80, 153, 234, 1, 8, 70, + 79, 82, 77, 73, 78, 71, 32, 6, 34, 77, 30, 84, 223, 163, 11, 83, 2, 153, + 230, 1, 2, 73, 76, 2, 189, 196, 10, 8, 69, 78, 32, 84, 72, 79, 85, 83, 5, + 129, 215, 8, 5, 32, 87, 73, 84, 72, 32, 60, 2, 79, 78, 182, 75, 80, 213, + 213, 10, 4, 69, 86, 69, 82, 28, 22, 32, 243, 5, 65, 26, 216, 2, 10, 68, + 79, 73, 78, 71, 32, 67, 65, 82, 84, 32, 3, 73, 78, 32, 108, 5, 87, 73, + 84, 72, 32, 208, 185, 7, 4, 70, 82, 79, 87, 200, 13, 27, 82, 65, 73, 83, + 73, 78, 71, 32, 66, 79, 84, 72, 32, 72, 65, 78, 68, 83, 32, 73, 78, 32, + 67, 69, 76, 69, 66, 128, 141, 4, 5, 67, 76, 73, 77, 66, 201, 45, 11, 66, + 79, 87, 73, 78, 71, 32, 68, 69, 69, 80, 2, 11, 87, 2, 179, 169, 3, 72, 4, + 76, 7, 83, 84, 69, 65, 77, 89, 32, 217, 211, 11, 6, 76, 79, 84, 85, 83, + 32, 2, 197, 148, 12, 2, 82, 79, 12, 154, 1, 66, 212, 134, 2, 3, 80, 79, + 85, 160, 157, 1, 2, 67, 82, 196, 214, 5, 6, 70, 79, 76, 68, 69, 68, 177, + 168, 2, 8, 72, 69, 65, 68, 83, 67, 65, 82, 4, 36, 3, 76, 79, 78, 159, + 159, 10, 65, 2, 11, 68, 2, 11, 32, 2, 11, 72, 2, 11, 65, 2, 203, 234, 11, + 73, 2, 21, 3, 76, 32, 67, 2, 161, 236, 10, 4, 79, 77, 80, 85, 4, 232, + 230, 8, 2, 69, 84, 251, 180, 2, 79, 2, 217, 227, 8, 2, 32, 68, 140, 2, + 66, 65, 180, 19, 9, 73, 76, 73, 80, 80, 73, 78, 69, 32, 47, 79, 204, 1, + 108, 6, 71, 83, 45, 80, 65, 32, 189, 7, 16, 73, 83, 84, 79, 83, 32, 68, + 73, 83, 67, 32, 83, 73, 71, 78, 32, 112, 100, 7, 76, 69, 84, 84, 69, 82, + 32, 248, 4, 5, 77, 65, 82, 75, 32, 30, 83, 33, 4, 68, 79, 85, 66, 96, + 138, 2, 65, 138, 1, 67, 50, 68, 42, 83, 64, 5, 86, 79, 73, 67, 69, 174, + 204, 8, 71, 218, 134, 3, 78, 82, 84, 46, 75, 2, 80, 2, 90, 162, 7, 69, + 222, 61, 66, 2, 70, 2, 72, 2, 74, 2, 76, 2, 77, 2, 81, 2, 82, 2, 87, 2, + 88, 2, 89, 186, 2, 73, 2, 79, 3, 85, 7, 80, 8, 76, 84, 69, 82, 78, 65, + 84, 69, 21, 8, 83, 80, 73, 82, 65, 84, 69, 68, 2, 163, 154, 12, 32, 2, + 11, 32, 2, 167, 154, 12, 70, 6, 26, 65, 251, 153, 12, 72, 5, 159, 182, 8, + 78, 6, 226, 153, 12, 68, 2, 90, 187, 2, 65, 6, 236, 135, 8, 4, 77, 65, + 76, 76, 206, 145, 4, 72, 187, 2, 65, 4, 34, 68, 21, 4, 76, 69, 83, 83, 2, + 211, 163, 10, 32, 2, 243, 247, 8, 32, 4, 130, 212, 11, 68, 59, 83, 10, + 28, 3, 73, 78, 71, 31, 85, 2, 241, 205, 11, 2, 76, 69, 8, 58, 66, 225, + 206, 11, 8, 80, 69, 82, 70, 73, 88, 69, 68, 6, 229, 150, 8, 13, 74, 79, + 73, 78, 69, 68, 32, 76, 69, 84, 84, 69, 82, 92, 238, 1, 66, 146, 1, 67, + 172, 2, 2, 68, 79, 38, 71, 66, 72, 64, 2, 76, 73, 32, 2, 77, 65, 66, 80, + 162, 1, 82, 38, 83, 150, 1, 84, 70, 87, 168, 203, 5, 2, 70, 76, 172, 224, + 1, 2, 79, 88, 188, 193, 3, 2, 69, 65, 142, 7, 65, 135, 1, 86, 10, 52, 2, + 69, 69, 22, 79, 205, 40, 4, 85, 76, 76, 83, 5, 199, 142, 7, 72, 4, 32, 2, + 79, 77, 175, 150, 12, 87, 2, 11, 69, 2, 219, 189, 11, 82, 16, 34, 65, 86, + 72, 22, 76, 23, 79, 6, 194, 200, 5, 80, 200, 192, 3, 8, 82, 80, 69, 78, + 84, 82, 89, 32, 223, 140, 3, 84, 2, 255, 175, 2, 73, 2, 219, 218, 10, 85, + 6, 26, 76, 33, 2, 77, 66, 2, 11, 85, 2, 239, 196, 11, 77, 5, 37, 7, 73, + 78, 73, 78, 71, 32, 79, 2, 237, 172, 9, 5, 66, 76, 73, 81, 85, 4, 222, + 235, 10, 76, 175, 145, 1, 86, 4, 42, 82, 245, 182, 10, 4, 65, 85, 78, 84, + 2, 195, 220, 10, 65, 6, 42, 69, 198, 180, 7, 79, 155, 209, 2, 73, 2, 183, + 221, 11, 76, 4, 242, 128, 12, 76, 203, 17, 68, 4, 40, 2, 78, 65, 181, + 169, 9, 2, 84, 84, 2, 159, 233, 8, 67, 8, 52, 2, 69, 68, 50, 76, 237, + 136, 7, 3, 65, 80, 89, 2, 25, 4, 69, 83, 84, 82, 2, 211, 201, 10, 73, 4, + 184, 167, 4, 2, 85, 77, 229, 211, 2, 3, 65, 78, 69, 4, 230, 132, 10, 79, + 255, 250, 1, 65, 12, 108, 2, 72, 73, 154, 145, 11, 65, 154, 45, 76, 128, + 19, 3, 84, 82, 65, 165, 39, 7, 77, 65, 76, 76, 32, 65, 88, 4, 146, 170, + 2, 69, 151, 229, 9, 80, 6, 200, 165, 4, 5, 65, 84, 84, 79, 79, 250, 164, + 7, 73, 195, 36, 85, 4, 246, 196, 7, 79, 221, 187, 3, 5, 65, 86, 89, 32, + 66, 4, 218, 232, 1, 83, 25, 4, 68, 79, 85, 66, 60, 56, 8, 69, 78, 73, 67, + 73, 65, 78, 32, 183, 138, 10, 76, 58, 92, 7, 76, 69, 84, 84, 69, 82, 32, + 160, 3, 7, 78, 85, 77, 66, 69, 82, 32, 199, 248, 5, 87, 44, 234, 1, 65, + 34, 68, 22, 72, 22, 81, 22, 83, 58, 84, 202, 246, 1, 87, 150, 212, 5, 90, + 130, 157, 1, 89, 200, 188, 1, 2, 82, 79, 128, 92, 3, 71, 65, 77, 134, 8, + 75, 130, 1, 78, 132, 58, 3, 76, 65, 77, 138, 17, 66, 186, 30, 80, 171, 4, + 77, 4, 198, 137, 11, 76, 187, 49, 73, 2, 151, 172, 3, 69, 4, 171, 213, 6, + 69, 2, 255, 136, 11, 79, 6, 130, 253, 9, 65, 186, 141, 1, 72, 165, 124, + 2, 69, 77, 4, 214, 228, 11, 65, 191, 8, 69, 12, 186, 49, 84, 187, 151, 4, + 79, 40, 104, 2, 67, 75, 66, 71, 62, 76, 90, 78, 178, 1, 83, 32, 7, 84, + 67, 72, 70, 79, 82, 75, 243, 132, 12, 69, 5, 17, 2, 85, 80, 2, 21, 3, 32, + 84, 82, 2, 155, 217, 10, 85, 7, 11, 32, 4, 26, 78, 179, 202, 11, 70, 2, + 183, 254, 10, 79, 6, 52, 4, 69, 32, 79, 70, 238, 90, 67, 247, 171, 11, + 76, 2, 11, 32, 2, 139, 198, 9, 80, 14, 68, 2, 67, 72, 46, 69, 186, 149, + 4, 87, 242, 232, 6, 75, 219, 98, 65, 4, 144, 140, 3, 2, 69, 68, 211, 235, + 7, 73, 4, 28, 2, 32, 68, 195, 71, 65, 2, 185, 241, 4, 2, 69, 67, 4, 174, + 241, 10, 67, 139, 1, 84, 5, 165, 186, 9, 10, 32, 87, 73, 84, 72, 32, 84, + 69, 69, 32, 218, 1, 38, 65, 218, 9, 85, 179, 250, 11, 68, 176, 1, 78, 67, + 128, 1, 12, 78, 67, 75, 32, 67, 79, 78, 83, 84, 65, 78, 84, 83, 89, 6, + 44, 5, 69, 32, 79, 70, 32, 179, 236, 10, 65, 4, 56, 6, 73, 78, 84, 69, + 82, 69, 189, 173, 11, 2, 87, 79, 2, 231, 235, 6, 83, 5, 45, 9, 32, 79, + 86, 69, 82, 32, 84, 87, 79, 2, 11, 32, 2, 159, 238, 11, 80, 166, 1, 96, + 9, 73, 78, 71, 32, 67, 65, 82, 68, 32, 149, 151, 4, 9, 71, 82, 79, 85, + 78, 68, 32, 83, 76, 164, 1, 182, 1, 66, 44, 3, 82, 69, 68, 0, 5, 87, 72, + 73, 84, 69, 42, 70, 74, 75, 38, 69, 34, 83, 36, 3, 81, 85, 69, 14, 84, + 92, 2, 65, 67, 0, 3, 78, 73, 78, 13, 4, 74, 65, 67, 75, 4, 40, 4, 76, 65, + 67, 75, 203, 208, 10, 65, 2, 17, 2, 32, 74, 2, 203, 225, 1, 79, 18, 30, + 79, 249, 1, 2, 73, 86, 10, 128, 2, 2, 85, 82, 175, 243, 10, 79, 16, 34, + 78, 185, 1, 3, 73, 78, 71, 8, 181, 1, 4, 73, 71, 72, 84, 16, 32, 2, 69, + 86, 117, 2, 73, 88, 8, 91, 69, 66, 78, 69, 12, 3, 72, 82, 69, 12, 2, 87, + 79, 161, 1, 5, 82, 85, 77, 80, 45, 8, 23, 78, 8, 11, 69, 8, 25, 4, 32, + 79, 70, 32, 8, 88, 3, 67, 76, 85, 20, 3, 83, 80, 65, 158, 207, 8, 72, + 137, 3, 5, 68, 73, 65, 77, 79, 2, 255, 189, 11, 66, 2, 219, 231, 10, 68, + 42, 90, 50, 250, 192, 9, 49, 214, 185, 2, 51, 2, 52, 2, 53, 2, 54, 2, 55, + 2, 56, 3, 57, 7, 202, 250, 11, 48, 3, 49, 41, 46, 83, 160, 4, 2, 84, 79, + 239, 189, 8, 78, 26, 52, 5, 32, 83, 73, 71, 78, 221, 223, 8, 2, 45, 77, + 25, 11, 32, 22, 64, 3, 73, 78, 32, 124, 5, 87, 73, 84, 72, 32, 219, 235, + 3, 65, 6, 34, 76, 22, 82, 247, 212, 10, 84, 2, 41, 2, 69, 70, 2, 21, 3, + 73, 71, 72, 2, 133, 169, 10, 6, 84, 32, 72, 65, 76, 70, 14, 162, 1, 68, + 34, 83, 204, 221, 9, 4, 84, 73, 76, 68, 140, 117, 5, 66, 76, 65, 67, 75, + 185, 35, 16, 67, 73, 82, 67, 85, 77, 70, 76, 69, 88, 32, 65, 67, 67, 69, + 78, 2, 11, 79, 2, 231, 207, 9, 84, 4, 54, 77, 165, 157, 5, 7, 85, 66, 83, + 67, 82, 73, 80, 2, 197, 231, 8, 3, 65, 76, 76, 11, 33, 6, 32, 70, 79, 82, + 77, 32, 8, 154, 136, 10, 70, 71, 84, 58, 232, 1, 5, 76, 73, 67, 69, 32, + 122, 80, 136, 1, 11, 82, 84, 65, 66, 76, 69, 32, 83, 84, 69, 82, 22, 83, + 158, 1, 84, 146, 1, 85, 196, 1, 4, 87, 69, 82, 32, 202, 231, 6, 79, 245, + 204, 4, 11, 67, 75, 69, 84, 32, 67, 65, 76, 67, 85, 76, 6, 52, 3, 67, 65, + 82, 141, 234, 3, 4, 79, 70, 70, 73, 5, 173, 221, 9, 11, 83, 32, 82, 69, + 86, 79, 76, 86, 73, 78, 71, 6, 76, 13, 32, 68, 73, 82, 69, 67, 84, 73, + 79, 78, 65, 76, 32, 187, 203, 1, 67, 4, 166, 117, 73, 185, 162, 6, 6, 70, + 79, 82, 77, 65, 84, 2, 191, 210, 11, 69, 12, 40, 2, 69, 73, 22, 84, 195, + 246, 4, 73, 2, 147, 161, 11, 68, 8, 36, 3, 65, 76, 32, 163, 228, 10, 66, + 6, 130, 202, 1, 72, 217, 180, 6, 4, 77, 65, 82, 75, 8, 66, 65, 210, 247, + 1, 32, 173, 238, 8, 6, 84, 69, 68, 32, 80, 76, 4, 26, 66, 179, 208, 11, + 84, 2, 29, 5, 76, 69, 32, 87, 65, 2, 135, 47, 84, 12, 108, 4, 76, 84, 82, + 89, 28, 7, 82, 73, 78, 71, 32, 76, 73, 28, 2, 84, 73, 250, 135, 10, 78, + 199, 228, 1, 67, 2, 165, 168, 11, 2, 32, 76, 2, 209, 156, 5, 2, 81, 85, + 4, 197, 137, 10, 2, 78, 71, 8, 24, 2, 79, 78, 47, 83, 4, 128, 218, 10, 4, + 45, 79, 70, 70, 15, 32, 4, 160, 213, 8, 3, 76, 69, 69, 219, 132, 2, 89, + 140, 1, 74, 69, 162, 10, 73, 234, 2, 79, 237, 139, 9, 6, 65, 89, 69, 82, + 32, 66, 102, 132, 1, 6, 71, 78, 65, 78, 84, 32, 66, 83, 156, 167, 5, 4, + 67, 69, 68, 69, 144, 193, 1, 5, 86, 73, 79, 85, 83, 157, 33, 2, 84, 90, + 6, 42, 87, 146, 151, 5, 80, 243, 139, 5, 77, 2, 235, 160, 7, 79, 70, 176, + 1, 27, 69, 78, 84, 65, 84, 73, 79, 78, 32, 70, 79, 82, 77, 32, 70, 79, + 82, 32, 86, 69, 82, 84, 73, 67, 65, 76, 32, 241, 162, 8, 10, 67, 82, 73, + 80, 84, 73, 79, 78, 32, 84, 68, 198, 1, 67, 22, 69, 46, 72, 50, 73, 94, + 76, 188, 1, 6, 82, 73, 71, 72, 84, 32, 192, 2, 6, 87, 65, 86, 89, 32, 76, + 202, 136, 4, 83, 192, 171, 4, 9, 84, 87, 79, 32, 68, 79, 84, 32, 76, 163, + 99, 81, 4, 203, 170, 2, 79, 6, 138, 252, 5, 88, 214, 194, 2, 77, 3, 78, + 2, 233, 215, 8, 7, 79, 82, 73, 90, 79, 78, 84, 4, 49, 10, 68, 69, 79, 71, + 82, 65, 80, 72, 73, 67, 4, 11, 32, 4, 206, 154, 9, 67, 35, 70, 22, 40, 4, + 69, 70, 84, 32, 191, 128, 10, 79, 20, 112, 6, 87, 72, 73, 84, 69, 32, + 142, 1, 66, 42, 68, 218, 93, 67, 146, 6, 65, 218, 164, 7, 80, 154, 2, 83, + 39, 84, 4, 162, 2, 67, 159, 93, 76, 22, 110, 66, 42, 68, 36, 6, 87, 72, + 73, 84, 69, 32, 182, 93, 67, 146, 6, 65, 218, 164, 7, 80, 154, 2, 83, 39, + 84, 2, 177, 94, 6, 76, 65, 67, 75, 32, 76, 2, 209, 99, 5, 79, 85, 66, 76, + 69, 6, 74, 67, 17, 14, 76, 69, 78, 84, 73, 67, 85, 76, 65, 82, 32, 66, + 82, 65, 2, 131, 93, 79, 4, 198, 143, 11, 67, 177, 29, 2, 75, 67, 2, 235, + 252, 9, 79, 22, 46, 78, 156, 1, 2, 86, 65, 171, 201, 11, 77, 10, 34, 84, + 173, 171, 6, 2, 67, 69, 6, 26, 32, 53, 2, 69, 82, 2, 21, 3, 83, 67, 82, + 2, 253, 235, 9, 2, 69, 69, 5, 17, 2, 32, 73, 2, 175, 144, 11, 67, 10, 60, + 5, 67, 89, 32, 77, 69, 29, 6, 84, 69, 32, 85, 83, 69, 2, 241, 132, 7, 2, + 83, 83, 8, 26, 32, 191, 175, 6, 45, 4, 146, 210, 5, 84, 223, 243, 4, 79, + 14, 130, 1, 74, 30, 80, 228, 32, 5, 72, 73, 66, 73, 84, 148, 176, 8, 6, + 66, 73, 78, 71, 32, 67, 133, 210, 1, 5, 83, 69, 82, 80, 73, 2, 181, 144, + 5, 2, 69, 67, 6, 64, 6, 79, 82, 84, 73, 79, 78, 197, 195, 10, 4, 69, 82, + 84, 89, 5, 179, 182, 5, 65, 58, 172, 1, 15, 70, 79, 85, 82, 32, 68, 79, + 84, 83, 32, 87, 73, 84, 72, 32, 32, 7, 76, 69, 84, 84, 69, 82, 32, 230, + 2, 78, 178, 31, 83, 1, 8, 84, 85, 82, 78, 69, 68, 32, 83, 4, 210, 157, + 10, 67, 187, 109, 68, 36, 166, 1, 65, 22, 68, 34, 76, 22, 77, 50, 87, + 238, 150, 4, 71, 90, 90, 34, 83, 66, 89, 154, 193, 1, 72, 234, 5, 75, + 130, 76, 66, 190, 173, 4, 78, 254, 1, 84, 203, 103, 80, 2, 207, 151, 4, + 76, 2, 11, 65, 2, 251, 171, 6, 76, 2, 235, 151, 4, 65, 2, 25, 4, 69, 77, + 45, 81, 2, 195, 223, 5, 79, 2, 37, 7, 65, 87, 45, 65, 89, 73, 78, 2, 141, + 194, 1, 2, 45, 82, 14, 33, 6, 85, 77, 66, 69, 82, 32, 14, 42, 84, 186, + 151, 4, 79, 187, 217, 2, 70, 8, 42, 87, 250, 234, 9, 72, 239, 156, 1, 69, + 4, 182, 237, 9, 69, 131, 234, 1, 79, 18, 252, 1, 4, 78, 67, 84, 85, 106, + 82, 56, 19, 84, 32, 76, 73, 84, 84, 69, 82, 32, 73, 78, 32, 73, 84, 83, + 32, 80, 76, 65, 170, 140, 1, 83, 140, 42, 20, 66, 76, 73, 67, 32, 65, 68, + 68, 82, 69, 83, 83, 32, 76, 79, 85, 68, 83, 80, 69, 194, 157, 10, 49, 3, + 50, 4, 80, 9, 83, 32, 69, 76, 69, 86, 65, 84, 85, 137, 150, 11, 5, 65, + 84, 73, 79, 78, 2, 135, 147, 11, 83, 4, 32, 2, 80, 76, 183, 189, 11, 83, + 2, 227, 204, 10, 69, 2, 11, 67, 2, 215, 192, 10, 69, 40, 98, 65, 148, 6, + 6, 69, 83, 84, 73, 79, 78, 214, 231, 5, 79, 253, 216, 4, 5, 73, 78, 67, + 85, 78, 30, 104, 2, 68, 82, 208, 4, 9, 84, 69, 82, 78, 73, 79, 78, 32, + 73, 48, 4, 82, 84, 69, 82, 223, 170, 10, 79, 24, 56, 4, 65, 78, 84, 32, + 253, 3, 5, 85, 80, 76, 69, 32, 20, 44, 6, 85, 80, 80, 69, 82, 32, 131, 2, + 76, 16, 56, 4, 76, 69, 70, 84, 249, 1, 5, 82, 73, 71, 72, 84, 11, 29, 5, + 32, 65, 78, 68, 32, 8, 108, 6, 76, 79, 87, 69, 82, 32, 53, 17, 85, 80, + 80, 69, 82, 32, 82, 73, 71, 72, 84, 32, 65, 78, 68, 32, 76, 4, 184, 1, 5, + 76, 69, 70, 84, 32, 195, 163, 11, 82, 4, 11, 79, 4, 11, 87, 4, 241, 163, + 11, 2, 69, 82, 7, 69, 15, 32, 65, 78, 68, 32, 76, 79, 87, 69, 82, 32, 76, + 69, 70, 84, 5, 11, 32, 2, 21, 3, 65, 78, 68, 2, 229, 255, 9, 6, 32, 76, + 79, 87, 69, 82, 4, 22, 73, 155, 37, 80, 2, 133, 163, 8, 7, 78, 84, 69, + 71, 82, 65, 76, 2, 17, 2, 32, 78, 2, 195, 136, 10, 79, 6, 34, 32, 185, + 165, 5, 2, 69, 68, 4, 198, 244, 4, 69, 211, 150, 6, 77, 152, 9, 114, 65, + 182, 7, 69, 224, 27, 6, 72, 73, 78, 79, 67, 69, 34, 73, 182, 78, 76, 46, + 79, 246, 18, 85, 151, 198, 10, 83, 60, 110, 67, 104, 2, 68, 73, 130, 1, + 73, 202, 4, 84, 160, 210, 7, 4, 66, 66, 73, 84, 130, 185, 3, 90, 223, 56, + 77, 6, 40, 4, 73, 78, 71, 32, 211, 184, 8, 67, 4, 140, 251, 9, 7, 77, 79, + 84, 79, 82, 67, 89, 203, 44, 67, 8, 66, 79, 245, 255, 7, 10, 67, 65, 76, + 32, 83, 89, 77, 66, 79, 76, 7, 200, 145, 6, 4, 65, 67, 84, 73, 197, 133, + 4, 2, 32, 66, 34, 60, 5, 76, 87, 65, 89, 32, 46, 78, 21, 4, 83, 69, 68, + 32, 4, 228, 189, 8, 2, 84, 82, 247, 231, 1, 67, 5, 203, 173, 10, 66, 26, + 156, 1, 3, 68, 79, 84, 34, 73, 48, 4, 72, 65, 78, 68, 182, 1, 77, 198, + 139, 7, 70, 186, 237, 1, 67, 226, 170, 1, 83, 197, 18, 7, 66, 65, 67, 75, + 32, 79, 70, 5, 29, 5, 84, 69, 68, 32, 73, 2, 165, 39, 8, 78, 84, 69, 82, + 80, 79, 76, 65, 7, 33, 6, 32, 87, 73, 84, 72, 32, 4, 130, 27, 70, 201, + 176, 2, 28, 80, 65, 82, 84, 32, 66, 69, 84, 87, 69, 69, 78, 32, 77, 73, + 68, 68, 76, 69, 32, 65, 78, 68, 32, 82, 73, 78, 71, 6, 182, 189, 10, 67, + 2, 68, 3, 82, 5, 135, 165, 11, 73, 248, 1, 226, 1, 67, 232, 3, 2, 68, 32, + 64, 2, 71, 73, 144, 1, 5, 74, 65, 78, 71, 32, 254, 4, 76, 32, 8, 77, 73, + 78, 68, 69, 82, 32, 82, 34, 80, 106, 83, 136, 1, 5, 84, 85, 82, 78, 32, + 42, 86, 225, 184, 1, 5, 70, 69, 82, 69, 78, 24, 114, 69, 32, 3, 89, 67, + 76, 158, 176, 5, 79, 181, 237, 3, 13, 82, 69, 65, 84, 73, 79, 78, 65, 76, + 32, 86, 69, 72, 2, 11, 73, 2, 211, 164, 11, 80, 18, 78, 69, 53, 15, 73, + 78, 71, 32, 83, 89, 77, 66, 79, 76, 32, 70, 79, 82, 32, 2, 29, 5, 68, 32, + 80, 65, 80, 2, 239, 223, 9, 69, 16, 100, 5, 84, 89, 80, 69, 45, 157, 237, + 4, 14, 71, 69, 78, 69, 82, 73, 67, 32, 77, 65, 84, 69, 82, 73, 14, 58, + 49, 2, 50, 2, 51, 2, 52, 2, 53, 2, 54, 3, 55, 2, 229, 177, 5, 6, 32, 80, + 76, 65, 83, 84, 4, 42, 65, 229, 233, 4, 4, 71, 73, 70, 84, 2, 143, 173, + 3, 80, 54, 120, 4, 83, 84, 69, 82, 165, 212, 5, 20, 79, 78, 65, 76, 32, + 73, 78, 68, 73, 67, 65, 84, 79, 82, 32, 83, 89, 77, 66, 79, 2, 135, 215, + 9, 69, 74, 128, 1, 15, 67, 79, 78, 83, 79, 78, 65, 78, 84, 32, 83, 73, + 71, 78, 32, 44, 7, 76, 69, 84, 84, 69, 82, 32, 150, 2, 83, 35, 86, 8, + 174, 195, 9, 78, 150, 248, 1, 72, 3, 82, 46, 154, 1, 77, 34, 78, 166, + 183, 11, 66, 2, 67, 2, 68, 2, 71, 2, 72, 2, 74, 2, 75, 2, 76, 2, 80, 2, + 82, 2, 83, 2, 84, 2, 87, 2, 89, 187, 2, 65, 4, 194, 183, 11, 66, 187, 2, + 65, 12, 54, 89, 158, 234, 7, 71, 210, 204, 3, 68, 187, 2, 65, 4, 234, + 182, 11, 74, 187, 2, 65, 2, 11, 69, 2, 223, 207, 10, 67, 18, 64, 10, 79, + 87, 69, 76, 32, 83, 73, 71, 78, 32, 171, 134, 9, 73, 16, 54, 69, 190, + 247, 10, 65, 174, 64, 73, 2, 79, 3, 85, 7, 230, 183, 11, 65, 3, 85, 2, + 137, 167, 10, 3, 73, 69, 86, 2, 201, 231, 10, 3, 73, 66, 66, 2, 41, 8, + 76, 65, 67, 69, 77, 69, 78, 84, 2, 17, 2, 32, 67, 2, 253, 255, 9, 5, 72, + 65, 82, 65, 67, 8, 32, 2, 84, 82, 187, 217, 6, 80, 6, 168, 134, 6, 16, + 73, 67, 84, 69, 68, 32, 76, 69, 70, 84, 32, 69, 78, 84, 82, 89, 243, 158, + 5, 79, 6, 162, 162, 10, 83, 142, 104, 76, 31, 82, 70, 64, 4, 69, 82, 83, + 69, 173, 228, 3, 6, 79, 76, 86, 73, 78, 71, 68, 30, 32, 169, 3, 2, 68, + 32, 20, 184, 1, 6, 67, 72, 69, 67, 75, 69, 28, 2, 76, 73, 108, 7, 83, 79, + 76, 73, 68, 85, 83, 196, 193, 7, 16, 84, 73, 76, 68, 69, 32, 79, 80, 69, + 82, 65, 84, 79, 82, 32, 65, 147, 203, 2, 73, 2, 221, 155, 10, 2, 82, 32, + 4, 136, 194, 3, 18, 71, 72, 84, 32, 70, 79, 85, 82, 32, 80, 79, 73, 78, + 84, 69, 68, 32, 80, 239, 221, 1, 78, 9, 11, 32, 6, 200, 135, 5, 9, 80, + 82, 69, 67, 69, 68, 73, 78, 71, 226, 255, 2, 79, 167, 140, 1, 87, 48, + 232, 2, 5, 65, 78, 71, 76, 69, 20, 7, 68, 79, 85, 66, 76, 69, 32, 118, + 78, 20, 5, 70, 79, 82, 75, 69, 70, 80, 82, 82, 214, 1, 83, 102, 84, 212, + 201, 6, 30, 72, 65, 78, 68, 32, 87, 73, 84, 72, 32, 77, 73, 68, 68, 76, + 69, 32, 70, 73, 78, 71, 69, 82, 32, 69, 88, 84, 69, 78, 68, 158, 148, 2, + 67, 114, 81, 212, 61, 3, 86, 73, 67, 157, 36, 6, 69, 77, 80, 84, 89, 32, + 5, 159, 213, 3, 32, 6, 40, 3, 80, 82, 73, 41, 3, 83, 84, 82, 4, 17, 2, + 77, 69, 5, 195, 166, 3, 32, 2, 29, 5, 79, 75, 69, 32, 78, 2, 147, 150, 6, + 79, 2, 49, 10, 68, 32, 80, 65, 82, 65, 71, 82, 65, 80, 2, 175, 4, 72, 4, + 36, 3, 73, 76, 67, 151, 148, 10, 82, 2, 11, 82, 2, 253, 164, 10, 2, 79, + 87, 6, 156, 1, 17, 65, 73, 83, 69, 68, 32, 72, 65, 78, 68, 32, 87, 73, + 84, 72, 32, 70, 252, 96, 8, 79, 84, 65, 84, 69, 68, 32, 70, 229, 149, 6, + 4, 73, 71, 72, 84, 2, 185, 102, 9, 73, 78, 71, 69, 82, 83, 32, 83, 80, 4, + 132, 124, 17, 65, 78, 83, 45, 83, 69, 82, 73, 70, 32, 67, 65, 80, 73, 84, + 65, 76, 151, 248, 6, 69, 10, 88, 4, 73, 76, 68, 69, 28, 7, 82, 73, 80, + 76, 69, 32, 80, 173, 251, 6, 3, 72, 85, 77, 5, 189, 214, 4, 2, 32, 69, 2, + 187, 144, 10, 82, 2, 11, 82, 2, 171, 234, 10, 79, 213, 3, 228, 1, 4, 66, + 66, 79, 78, 164, 1, 3, 67, 69, 32, 60, 3, 71, 72, 84, 236, 71, 2, 78, 71, + 252, 1, 23, 83, 73, 78, 71, 32, 68, 73, 65, 71, 79, 78, 65, 76, 32, 67, + 82, 79, 83, 83, 73, 78, 71, 32, 134, 195, 5, 65, 143, 246, 3, 70, 19, 37, + 7, 32, 65, 82, 82, 79, 87, 32, 16, 80, 3, 76, 69, 70, 0, 4, 82, 73, 71, + 72, 22, 85, 213, 249, 10, 3, 68, 79, 87, 4, 175, 234, 1, 84, 4, 223, 249, + 10, 80, 4, 26, 67, 131, 160, 9, 66, 2, 133, 135, 1, 3, 82, 65, 67, 162, + 3, 110, 32, 158, 31, 45, 132, 8, 11, 72, 65, 78, 68, 32, 73, 78, 84, 69, + 82, 73, 29, 6, 87, 65, 82, 68, 83, 32, 176, 1, 198, 1, 65, 132, 6, 2, 66, + 76, 62, 67, 184, 1, 2, 68, 79, 242, 1, 70, 60, 2, 72, 65, 212, 2, 2, 76, + 79, 66, 78, 82, 79, 122, 80, 168, 1, 2, 82, 65, 58, 83, 154, 6, 84, 194, + 3, 86, 143, 1, 87, 28, 22, 78, 163, 4, 82, 22, 24, 2, 68, 32, 39, 71, 4, + 214, 41, 76, 21, 3, 85, 80, 80, 18, 26, 69, 17, 2, 76, 69, 2, 175, 23, + 82, 17, 11, 32, 14, 154, 1, 66, 44, 8, 68, 79, 84, 84, 69, 68, 32, 83, 2, + 83, 112, 5, 87, 73, 84, 72, 32, 189, 253, 9, 12, 86, 65, 82, 73, 65, 78, + 84, 32, 87, 73, 84, 72, 4, 133, 252, 9, 6, 82, 65, 67, 75, 69, 84, 2, 37, + 7, 85, 66, 83, 84, 73, 84, 85, 2, 25, 4, 84, 73, 79, 78, 2, 21, 3, 32, + 77, 65, 2, 243, 128, 1, 82, 4, 68, 11, 68, 79, 87, 78, 87, 65, 82, 68, + 83, 32, 90, 203, 171, 8, 65, 2, 141, 131, 10, 5, 73, 71, 90, 65, 71, 6, + 18, 67, 79, 82, 2, 41, 8, 32, 71, 82, 69, 65, 84, 69, 82, 2, 189, 20, 4, + 45, 84, 72, 65, 4, 41, 8, 79, 87, 32, 87, 73, 84, 72, 32, 4, 132, 191, 7, + 7, 67, 73, 82, 67, 76, 69, 68, 207, 141, 2, 83, 4, 25, 4, 65, 67, 75, 32, + 4, 194, 22, 76, 243, 172, 7, 84, 12, 38, 85, 230, 21, 79, 251, 222, 2, + 69, 8, 53, 11, 82, 76, 89, 32, 66, 82, 65, 67, 75, 69, 84, 9, 11, 32, 6, + 44, 4, 77, 73, 68, 68, 138, 8, 76, 23, 85, 2, 129, 229, 9, 2, 76, 69, 12, + 38, 84, 41, 5, 85, 66, 76, 69, 32, 2, 173, 14, 6, 84, 69, 68, 32, 83, 85, + 10, 50, 65, 94, 87, 174, 145, 3, 81, 151, 172, 4, 80, 4, 206, 25, 78, + 217, 149, 3, 15, 82, 82, 79, 87, 32, 87, 73, 84, 72, 32, 82, 79, 85, 78, + 68, 2, 203, 19, 73, 6, 26, 73, 227, 241, 2, 76, 4, 146, 146, 8, 86, 163, + 88, 83, 14, 32, 3, 76, 70, 32, 223, 1, 78, 12, 42, 66, 90, 70, 34, 82, + 139, 166, 8, 77, 6, 11, 76, 6, 40, 4, 65, 67, 75, 32, 231, 231, 9, 79, 4, + 166, 199, 9, 67, 167, 11, 83, 2, 11, 79, 2, 147, 242, 8, 76, 2, 33, 6, + 85, 78, 78, 73, 78, 71, 2, 131, 204, 6, 32, 2, 149, 145, 1, 16, 68, 32, + 84, 69, 76, 69, 80, 72, 79, 78, 69, 32, 82, 69, 67, 69, 2, 241, 193, 10, + 11, 87, 32, 80, 65, 82, 65, 80, 72, 82, 65, 83, 2, 197, 4, 16, 79, 82, + 77, 65, 76, 32, 70, 65, 67, 84, 79, 82, 32, 83, 69, 77, 8, 74, 85, 214, + 150, 8, 78, 237, 178, 1, 8, 80, 69, 78, 32, 83, 81, 85, 65, 2, 201, 147, + 10, 6, 84, 69, 82, 32, 74, 79, 8, 49, 10, 65, 82, 69, 78, 84, 72, 69, 83, + 73, 83, 9, 11, 32, 6, 34, 76, 22, 85, 147, 248, 8, 69, 2, 37, 2, 79, 87, + 2, 17, 2, 80, 80, 2, 169, 223, 3, 2, 69, 82, 2, 249, 8, 10, 73, 83, 69, + 68, 32, 79, 77, 73, 83, 83, 40, 62, 45, 70, 69, 78, 73, 68, 2, 80, 69, + 126, 81, 227, 2, 85, 2, 153, 208, 7, 12, 83, 72, 65, 80, 69, 68, 32, 66, + 65, 71, 32, 68, 4, 26, 77, 199, 160, 8, 86, 2, 205, 128, 10, 7, 73, 68, + 73, 82, 69, 67, 84, 4, 134, 136, 3, 78, 193, 180, 7, 8, 68, 69, 87, 65, + 89, 83, 32, 85, 8, 32, 4, 65, 75, 69, 82, 67, 69, 7, 33, 6, 32, 87, 73, + 84, 72, 32, 4, 186, 237, 3, 79, 75, 84, 2, 201, 4, 2, 67, 72, 20, 57, 12, + 85, 65, 82, 69, 32, 66, 82, 65, 67, 75, 69, 84, 21, 11, 32, 18, 84, 3, + 76, 79, 87, 0, 3, 85, 80, 80, 28, 5, 87, 73, 84, 72, 32, 223, 242, 8, 69, + 2, 133, 216, 3, 2, 69, 82, 12, 96, 8, 84, 73, 67, 75, 32, 73, 78, 32, + 162, 5, 81, 214, 189, 7, 85, 158, 97, 68, 195, 183, 2, 83, 4, 132, 215, + 3, 6, 66, 79, 84, 84, 79, 77, 1, 3, 84, 79, 80, 2, 197, 2, 6, 66, 83, 84, + 73, 84, 85, 20, 54, 72, 162, 1, 82, 146, 177, 7, 79, 179, 169, 2, 65, 8, + 54, 73, 60, 5, 79, 85, 71, 72, 84, 131, 155, 8, 82, 2, 201, 197, 1, 10, + 82, 68, 32, 87, 72, 73, 84, 69, 32, 82, 2, 11, 32, 2, 205, 250, 2, 3, 66, + 85, 66, 8, 34, 65, 89, 4, 73, 65, 78, 71, 2, 33, 6, 78, 83, 80, 79, 83, + 73, 2, 11, 84, 2, 17, 2, 73, 79, 2, 191, 181, 10, 78, 6, 32, 2, 76, 69, + 183, 154, 8, 85, 5, 41, 8, 32, 65, 66, 79, 86, 69, 32, 76, 2, 161, 232, + 8, 2, 69, 70, 4, 45, 9, 69, 82, 84, 73, 67, 65, 76, 32, 66, 4, 68, 9, 65, + 82, 32, 87, 73, 84, 72, 32, 81, 245, 236, 9, 2, 79, 88, 2, 215, 149, 8, + 85, 14, 22, 72, 203, 1, 73, 12, 25, 4, 73, 84, 69, 32, 12, 54, 67, 54, + 76, 182, 170, 7, 80, 154, 2, 83, 39, 84, 4, 26, 79, 215, 168, 7, 85, 2, + 65, 3, 82, 78, 69, 2, 41, 8, 69, 78, 84, 73, 67, 85, 76, 65, 2, 231, 177, + 10, 82, 2, 221, 167, 6, 6, 71, 71, 76, 89, 32, 70, 30, 82, 70, 206, 1, + 72, 130, 1, 80, 250, 1, 83, 197, 1, 6, 84, 79, 45, 76, 69, 70, 8, 33, 6, + 65, 67, 73, 78, 71, 32, 8, 144, 1, 14, 65, 82, 77, 69, 78, 73, 65, 78, + 32, 69, 84, 69, 82, 78, 144, 196, 3, 11, 83, 86, 65, 83, 84, 73, 32, 83, + 73, 71, 78, 151, 133, 3, 70, 2, 239, 227, 7, 73, 2, 81, 18, 65, 78, 68, + 69, 68, 32, 73, 78, 84, 69, 82, 76, 65, 67, 69, 68, 32, 80, 2, 21, 3, 69, + 78, 84, 2, 171, 199, 9, 65, 8, 41, 8, 79, 73, 78, 84, 73, 78, 71, 32, 8, + 140, 1, 6, 67, 85, 82, 86, 69, 68, 22, 65, 224, 247, 2, 6, 68, 79, 85, + 66, 76, 69, 253, 239, 6, 10, 77, 65, 71, 78, 73, 70, 89, 73, 78, 71, 2, + 17, 2, 32, 65, 2, 11, 78, 2, 157, 172, 10, 2, 71, 76, 4, 46, 72, 85, 7, + 73, 68, 69, 32, 65, 82, 67, 2, 17, 2, 65, 68, 2, 17, 2, 69, 68, 2, 165, + 222, 9, 6, 32, 87, 72, 73, 84, 69, 2, 11, 32, 2, 193, 168, 8, 8, 67, 76, + 79, 67, 75, 87, 73, 83, 8, 17, 2, 84, 32, 8, 86, 73, 40, 4, 79, 86, 69, + 82, 196, 238, 4, 5, 69, 77, 66, 69, 68, 187, 204, 5, 77, 2, 17, 2, 83, + 79, 2, 207, 129, 1, 76, 2, 179, 146, 3, 82, 2, 249, 236, 9, 2, 79, 82, + 210, 1, 160, 1, 5, 65, 82, 82, 79, 87, 182, 8, 66, 86, 68, 210, 1, 70, + 122, 72, 230, 6, 76, 26, 79, 34, 80, 50, 82, 70, 83, 94, 84, 202, 8, 87, + 226, 254, 7, 67, 47, 81, 71, 26, 32, 159, 205, 8, 45, 66, 94, 65, 170, 2, + 70, 82, 84, 184, 1, 5, 87, 73, 84, 72, 32, 149, 152, 1, 4, 79, 86, 69, + 82, 12, 40, 5, 66, 79, 86, 69, 32, 143, 1, 78, 10, 70, 82, 208, 155, 1, + 5, 83, 72, 79, 82, 84, 250, 180, 3, 65, 55, 84, 4, 37, 7, 69, 86, 69, 82, + 83, 69, 32, 4, 158, 208, 4, 65, 55, 84, 2, 61, 13, 68, 32, 85, 80, 80, + 69, 82, 32, 65, 78, 68, 32, 76, 2, 17, 2, 79, 87, 2, 137, 142, 8, 2, 69, + 82, 4, 37, 7, 82, 79, 77, 32, 66, 65, 82, 5, 189, 1, 6, 32, 84, 79, 32, + 66, 76, 10, 56, 7, 72, 82, 79, 85, 71, 72, 32, 65, 3, 79, 32, 66, 6, 144, + 203, 4, 3, 83, 85, 80, 130, 156, 4, 71, 131, 143, 2, 88, 4, 26, 76, 235, + 188, 10, 65, 2, 213, 171, 9, 3, 65, 67, 75, 38, 140, 1, 6, 67, 79, 82, + 78, 69, 82, 26, 68, 98, 76, 38, 80, 30, 83, 38, 84, 210, 139, 8, 77, 38, + 78, 122, 69, 226, 148, 1, 72, 155, 160, 1, 86, 2, 213, 18, 2, 32, 68, 4, + 11, 79, 4, 40, 4, 84, 84, 69, 68, 203, 177, 7, 85, 2, 17, 2, 32, 83, 2, + 247, 224, 10, 84, 4, 150, 140, 8, 65, 247, 237, 1, 79, 2, 249, 203, 8, 2, + 76, 85, 6, 218, 140, 8, 77, 135, 182, 2, 84, 10, 206, 16, 73, 171, 3, 65, + 8, 58, 65, 128, 12, 5, 79, 84, 84, 79, 77, 219, 128, 8, 76, 2, 145, 2, 2, + 67, 75, 14, 48, 6, 79, 85, 66, 76, 69, 32, 235, 154, 8, 65, 12, 40, 5, + 65, 82, 82, 79, 87, 135, 19, 68, 11, 26, 32, 183, 195, 8, 45, 6, 26, 87, + 243, 144, 8, 70, 4, 25, 4, 73, 84, 72, 32, 4, 190, 191, 10, 86, 79, 83, + 4, 40, 4, 82, 79, 78, 84, 143, 140, 8, 73, 2, 141, 139, 8, 14, 45, 84, + 73, 76, 84, 69, 68, 32, 83, 72, 65, 68, 79, 87, 30, 26, 65, 195, 143, 8, + 69, 26, 48, 6, 82, 80, 79, 79, 78, 32, 147, 168, 10, 78, 24, 88, 8, 79, + 86, 69, 82, 32, 76, 69, 70, 45, 10, 87, 73, 84, 72, 32, 66, 65, 82, 66, + 32, 2, 237, 219, 7, 6, 84, 87, 65, 82, 68, 83, 22, 44, 4, 68, 79, 87, 78, + 173, 1, 2, 85, 80, 10, 26, 32, 247, 148, 8, 87, 8, 76, 8, 65, 66, 79, 86, + 69, 32, 76, 69, 18, 66, 190, 140, 8, 70, 175, 5, 84, 2, 227, 2, 70, 2, + 185, 201, 4, 7, 69, 76, 79, 87, 32, 76, 79, 12, 26, 32, 203, 147, 8, 87, + 10, 60, 6, 65, 66, 79, 86, 69, 32, 178, 139, 8, 70, 175, 5, 84, 6, 22, + 76, 155, 1, 82, 4, 32, 2, 69, 70, 247, 199, 4, 79, 2, 233, 135, 2, 24, + 84, 87, 65, 82, 68, 83, 32, 72, 65, 82, 80, 79, 79, 78, 32, 87, 73, 84, + 72, 32, 66, 65, 82, 66, 2, 21, 3, 73, 71, 72, 2, 105, 24, 84, 87, 65, 82, + 68, 83, 32, 72, 65, 82, 80, 79, 79, 78, 32, 87, 73, 84, 72, 32, 66, 65, + 82, 66, 2, 11, 32, 2, 163, 232, 1, 68, 2, 141, 1, 2, 69, 70, 2, 221, 141, + 8, 3, 80, 69, 78, 4, 218, 145, 8, 65, 221, 199, 1, 3, 85, 83, 72, 4, 36, + 3, 73, 71, 72, 187, 148, 10, 79, 2, 11, 84, 2, 171, 1, 45, 6, 32, 2, 81, + 85, 235, 136, 8, 65, 4, 26, 73, 131, 137, 8, 65, 2, 245, 144, 8, 2, 71, + 71, 54, 38, 79, 60, 2, 82, 73, 227, 4, 87, 2, 11, 80, 2, 11, 32, 2, 149, + 129, 8, 4, 83, 72, 65, 68, 34, 40, 5, 65, 78, 71, 76, 69, 255, 3, 80, 30, + 56, 8, 45, 72, 69, 65, 68, 69, 68, 32, 251, 149, 8, 32, 28, 52, 5, 65, + 82, 82, 79, 87, 218, 141, 8, 68, 39, 80, 25, 11, 32, 22, 64, 8, 79, 86, + 69, 82, 32, 76, 69, 70, 22, 87, 155, 137, 8, 84, 2, 203, 136, 8, 84, 18, + 25, 4, 73, 84, 72, 32, 18, 128, 1, 7, 68, 79, 85, 66, 76, 69, 32, 36, 7, + 76, 79, 78, 71, 32, 84, 73, 246, 136, 8, 66, 158, 1, 77, 34, 78, 34, 86, + 35, 72, 4, 186, 196, 8, 72, 255, 236, 1, 86, 4, 11, 80, 4, 11, 32, 4, 18, + 68, 35, 85, 2, 197, 137, 8, 3, 79, 87, 78, 2, 167, 137, 8, 80, 4, 21, 3, + 76, 69, 32, 4, 138, 3, 68, 183, 195, 9, 65, 18, 11, 79, 18, 56, 8, 45, + 72, 69, 65, 68, 69, 68, 32, 191, 139, 8, 32, 16, 76, 6, 65, 82, 82, 79, + 87, 32, 213, 1, 8, 84, 82, 73, 80, 76, 69, 32, 68, 14, 44, 5, 87, 73, 84, + 72, 32, 203, 255, 7, 70, 12, 42, 84, 206, 156, 7, 68, 191, 145, 3, 86, 8, + 26, 65, 131, 139, 8, 82, 6, 17, 2, 73, 76, 7, 33, 6, 32, 87, 73, 84, 72, + 32, 4, 246, 155, 7, 68, 191, 145, 3, 86, 2, 153, 127, 2, 65, 83, 8, 58, + 65, 21, 10, 72, 73, 84, 69, 32, 65, 82, 82, 79, 87, 2, 227, 135, 8, 86, + 7, 11, 32, 4, 164, 185, 2, 4, 70, 82, 79, 77, 147, 212, 5, 87, 19, 66, + 32, 136, 1, 6, 69, 68, 32, 80, 76, 65, 21, 3, 73, 78, 71, 12, 82, 66, 22, + 80, 132, 180, 4, 2, 73, 78, 26, 69, 214, 252, 2, 79, 187, 173, 2, 65, 2, + 195, 201, 10, 85, 2, 11, 79, 2, 231, 151, 10, 73, 2, 215, 165, 10, 78, 2, + 189, 190, 3, 2, 32, 66, 4, 24, 2, 70, 65, 75, 83, 2, 17, 2, 76, 76, 2, + 21, 3, 73, 78, 71, 2, 205, 222, 1, 2, 32, 68, 2, 225, 164, 3, 2, 79, 85, + 8, 178, 217, 10, 69, 2, 73, 2, 77, 3, 79, 124, 136, 2, 2, 67, 75, 20, 2, + 76, 76, 134, 2, 79, 56, 4, 77, 65, 78, 32, 192, 8, 2, 83, 69, 20, 6, 84, + 65, 84, 69, 68, 32, 152, 3, 3, 85, 78, 68, 230, 169, 3, 87, 228, 189, 3, + 15, 65, 83, 84, 69, 68, 32, 83, 87, 69, 69, 84, 32, 80, 79, 84, 165, 253, + 1, 2, 66, 79, 5, 207, 186, 10, 69, 10, 130, 1, 69, 64, 4, 32, 79, 70, 32, + 101, 21, 73, 78, 71, 32, 79, 78, 32, 84, 72, 69, 32, 70, 76, 79, 79, 82, + 32, 76, 65, 85, 71, 6, 60, 9, 68, 45, 85, 80, 32, 78, 69, 87, 83, 33, 2, + 82, 32, 2, 11, 80, 2, 207, 250, 1, 65, 4, 28, 3, 67, 79, 65, 23, 83, 2, + 151, 158, 9, 83, 2, 239, 89, 75, 2, 199, 131, 10, 72, 72, 140, 1, 6, 67, + 69, 78, 84, 85, 82, 22, 68, 100, 3, 81, 85, 73, 28, 8, 78, 85, 77, 69, + 82, 65, 76, 32, 182, 4, 83, 114, 85, 159, 179, 7, 65, 2, 223, 187, 5, 73, + 6, 98, 69, 232, 5, 5, 85, 80, 79, 78, 68, 61, 12, 73, 77, 73, 68, 73, 65, + 32, 83, 69, 88, 84, 85, 2, 229, 5, 3, 78, 65, 82, 48, 142, 1, 70, 136, 1, + 3, 79, 78, 69, 134, 1, 83, 66, 84, 152, 14, 10, 82, 69, 86, 69, 82, 83, + 69, 68, 32, 79, 142, 229, 2, 69, 235, 193, 6, 78, 14, 26, 73, 155, 216, + 9, 79, 12, 36, 3, 70, 84, 89, 167, 246, 2, 86, 7, 11, 32, 4, 158, 168, 5, + 84, 185, 169, 4, 5, 69, 65, 82, 76, 89, 11, 11, 32, 8, 50, 72, 41, 8, 84, + 72, 79, 85, 83, 65, 78, 68, 4, 185, 1, 6, 85, 78, 68, 82, 69, 68, 5, 205, + 245, 3, 2, 32, 67, 6, 32, 2, 73, 88, 223, 225, 8, 69, 5, 221, 207, 9, 2, + 32, 76, 10, 42, 69, 190, 244, 2, 87, 135, 237, 5, 72, 4, 11, 78, 5, 11, + 32, 2, 223, 165, 5, 84, 10, 46, 69, 197, 145, 7, 5, 73, 76, 73, 81, 85, + 8, 60, 2, 77, 85, 40, 5, 83, 84, 69, 82, 84, 21, 2, 88, 84, 2, 17, 2, 78, + 67, 2, 239, 144, 7, 73, 2, 231, 178, 7, 73, 4, 18, 65, 23, 85, 2, 203, + 178, 7, 78, 2, 159, 144, 7, 76, 5, 191, 135, 9, 84, 10, 166, 2, 70, 32, + 11, 72, 69, 65, 86, 89, 32, 66, 76, 65, 67, 75, 52, 24, 76, 73, 71, 72, + 84, 32, 70, 79, 85, 82, 32, 80, 79, 73, 78, 84, 69, 68, 32, 66, 76, 65, + 67, 75, 0, 18, 87, 72, 73, 84, 69, 32, 70, 79, 85, 82, 32, 80, 79, 73, + 78, 84, 69, 68, 169, 53, 8, 67, 65, 80, 73, 84, 65, 76, 32, 2, 29, 5, 76, + 79, 82, 65, 76, 2, 217, 236, 8, 8, 32, 72, 69, 65, 82, 84, 32, 66, 2, + 225, 132, 9, 2, 32, 67, 16, 74, 32, 89, 14, 69, 68, 32, 83, 89, 77, 66, + 79, 76, 32, 70, 79, 82, 32, 4, 24, 2, 80, 85, 43, 84, 2, 11, 83, 2, 141, + 200, 9, 2, 72, 80, 2, 175, 210, 3, 65, 12, 68, 2, 83, 72, 242, 135, 6, + 67, 254, 153, 4, 70, 2, 76, 147, 17, 88, 4, 40, 4, 85, 65, 78, 71, 195, + 161, 10, 79, 2, 207, 178, 10, 88, 136, 2, 226, 1, 66, 20, 3, 71, 66, 89, + 40, 5, 76, 69, 45, 68, 69, 40, 3, 77, 73, 32, 154, 5, 78, 156, 26, 26, + 83, 83, 73, 65, 78, 32, 65, 83, 84, 82, 79, 76, 79, 71, 73, 67, 65, 76, + 32, 83, 89, 77, 66, 79, 76, 32, 247, 252, 4, 80, 2, 211, 172, 8, 76, 2, + 205, 191, 8, 5, 32, 70, 79, 79, 84, 2, 11, 76, 2, 161, 228, 5, 2, 65, 89, + 62, 68, 9, 70, 82, 65, 67, 84, 73, 79, 78, 32, 102, 78, 195, 190, 2, 68, + 8, 40, 4, 79, 78, 69, 32, 203, 229, 8, 84, 6, 34, 84, 150, 194, 8, 72, + 43, 81, 2, 191, 195, 8, 72, 36, 33, 6, 85, 77, 66, 69, 82, 32, 36, 76, 5, + 69, 73, 71, 72, 84, 38, 70, 92, 2, 78, 73, 22, 79, 18, 83, 83, 84, 4, + 158, 129, 3, 32, 139, 192, 7, 89, 8, 18, 73, 35, 79, 4, 130, 2, 86, 251, + 212, 8, 70, 4, 136, 2, 2, 85, 82, 211, 212, 8, 82, 4, 77, 2, 78, 69, 2, + 167, 1, 78, 8, 40, 4, 69, 86, 69, 78, 1, 2, 73, 88, 4, 206, 255, 2, 32, + 195, 174, 7, 84, 10, 34, 72, 50, 87, 143, 239, 9, 69, 4, 32, 2, 82, 69, + 215, 212, 8, 73, 2, 39, 69, 4, 26, 79, 199, 212, 8, 69, 2, 187, 254, 2, + 32, 182, 1, 32, 3, 73, 67, 32, 147, 25, 78, 178, 1, 220, 1, 6, 66, 69, + 76, 71, 84, 72, 20, 4, 67, 82, 79, 83, 20, 7, 76, 69, 84, 84, 69, 82, 32, + 210, 22, 83, 24, 6, 77, 85, 76, 84, 73, 80, 188, 141, 7, 5, 65, 82, 76, + 65, 85, 205, 183, 1, 7, 84, 86, 73, 77, 65, 68, 85, 2, 151, 220, 8, 79, + 2, 167, 143, 7, 83, 166, 1, 202, 4, 65, 110, 67, 98, 68, 126, 69, 82, 70, + 222, 1, 71, 104, 2, 72, 65, 50, 73, 220, 1, 5, 74, 69, 82, 65, 78, 34, + 75, 58, 76, 234, 1, 79, 128, 1, 13, 82, 65, 73, 68, 79, 32, 82, 65, 68, + 32, 82, 69, 73, 34, 83, 176, 2, 16, 66, 69, 82, 75, 65, 78, 65, 78, 32, + 66, 69, 79, 82, 67, 32, 66, 144, 1, 12, 78, 65, 85, 68, 73, 90, 32, 78, + 89, 68, 32, 78, 110, 84, 194, 1, 87, 244, 83, 7, 85, 82, 85, 90, 32, 85, + 82, 208, 187, 2, 10, 77, 65, 78, 78, 65, 90, 32, 77, 65, 78, 184, 60, 13, + 80, 69, 82, 84, 72, 79, 32, 80, 69, 79, 82, 84, 72, 218, 246, 2, 89, 166, + 227, 3, 81, 2, 86, 2, 88, 3, 90, 8, 222, 4, 69, 202, 158, 6, 67, 0, 4, + 78, 83, 85, 90, 249, 135, 3, 9, 76, 71, 73, 90, 32, 69, 79, 76, 72, 11, + 46, 69, 30, 65, 197, 239, 6, 3, 87, 69, 79, 4, 26, 65, 247, 181, 10, 78, + 2, 147, 143, 9, 76, 11, 84, 6, 79, 84, 84, 69, 68, 45, 209, 219, 3, 9, + 65, 71, 65, 90, 32, 68, 65, 69, 71, 6, 134, 181, 10, 76, 2, 78, 3, 80, + 11, 228, 70, 7, 72, 87, 65, 90, 32, 69, 72, 174, 181, 9, 65, 194, 55, 84, + 63, 78, 12, 120, 13, 82, 65, 78, 75, 83, 32, 67, 65, 83, 75, 69, 84, 32, + 233, 253, 6, 11, 69, 72, 85, 32, 70, 69, 79, 72, 32, 70, 69, 10, 46, 65, + 154, 245, 9, 73, 2, 79, 195, 60, 69, 4, 26, 69, 207, 178, 10, 67, 2, 235, + 139, 9, 83, 9, 26, 69, 207, 249, 9, 65, 4, 52, 7, 66, 79, 32, 71, 89, 70, + 85, 231, 177, 10, 82, 2, 143, 177, 10, 32, 4, 236, 8, 2, 69, 71, 13, 4, + 71, 76, 65, 90, 12, 156, 1, 2, 78, 71, 20, 9, 83, 65, 90, 32, 73, 83, 32, + 73, 83, 20, 5, 87, 65, 90, 32, 69, 136, 247, 9, 10, 67, 69, 76, 65, 78, + 68, 73, 67, 45, 89, 3, 79, 5, 131, 185, 6, 87, 2, 231, 239, 9, 83, 2, + 199, 174, 10, 79, 2, 11, 32, 2, 183, 175, 10, 74, 7, 21, 3, 65, 85, 78, + 4, 242, 171, 10, 32, 155, 3, 65, 12, 120, 15, 65, 85, 75, 65, 90, 32, 76, + 65, 71, 85, 32, 76, 79, 71, 82, 21, 11, 79, 78, 71, 45, 66, 82, 65, 78, + 67, 72, 45, 2, 211, 164, 9, 32, 10, 64, 3, 65, 82, 32, 158, 4, 72, 62, + 77, 66, 79, 179, 239, 9, 89, 2, 195, 150, 10, 65, 15, 150, 5, 83, 0, 12, + 84, 72, 65, 76, 65, 78, 32, 69, 84, 72, 69, 76, 224, 167, 10, 4, 80, 69, + 78, 45, 14, 69, 2, 78, 3, 79, 2, 11, 68, 2, 167, 243, 9, 32, 26, 150, 1, + 72, 244, 2, 18, 73, 71, 69, 76, 32, 76, 79, 78, 71, 45, 66, 82, 65, 78, + 67, 72, 45, 83, 228, 212, 6, 5, 79, 87, 73, 76, 79, 195, 139, 2, 84, 21, + 45, 9, 79, 82, 84, 45, 84, 87, 73, 71, 45, 18, 102, 66, 58, 72, 62, 77, + 30, 78, 38, 79, 42, 83, 186, 1, 84, 156, 146, 6, 2, 65, 82, 183, 219, 3, + 89, 2, 33, 6, 74, 65, 82, 75, 65, 78, 2, 235, 238, 8, 32, 2, 25, 4, 65, + 71, 65, 76, 2, 11, 76, 2, 195, 167, 10, 32, 2, 253, 145, 3, 2, 65, 68, 2, + 205, 216, 9, 4, 65, 85, 68, 32, 2, 17, 2, 83, 83, 2, 247, 136, 10, 32, 2, + 11, 79, 2, 215, 212, 6, 76, 4, 116, 15, 72, 85, 82, 73, 83, 65, 90, 32, + 84, 72, 85, 82, 83, 32, 84, 33, 10, 73, 87, 65, 90, 32, 84, 73, 82, 32, + 84, 2, 11, 72, 2, 167, 200, 5, 79, 2, 17, 2, 89, 82, 2, 223, 137, 10, 32, + 5, 41, 8, 85, 78, 74, 79, 32, 87, 89, 78, 2, 11, 78, 2, 175, 167, 9, 32, + 2, 21, 3, 73, 78, 71, 2, 169, 248, 6, 2, 76, 69, 4, 204, 191, 8, 16, 73, + 78, 71, 32, 83, 72, 73, 82, 84, 32, 87, 73, 84, 72, 32, 83, 219, 172, 1, + 69, 12, 120, 3, 66, 73, 78, 2, 78, 28, 2, 81, 85, 0, 3, 86, 73, 71, 134, + 234, 6, 83, 249, 154, 1, 6, 84, 82, 69, 68, 69, 67, 2, 149, 133, 8, 2, + 79, 86, 2, 237, 132, 8, 2, 73, 78, 214, 37, 244, 1, 2, 32, 73, 22, 65, + 238, 25, 67, 138, 5, 69, 146, 7, 72, 186, 33, 73, 186, 233, 1, 75, 154, + 2, 76, 130, 9, 77, 170, 21, 78, 174, 2, 79, 142, 39, 80, 180, 11, 2, 81, + 85, 158, 67, 83, 38, 84, 142, 16, 85, 150, 35, 87, 186, 1, 89, 187, 251, + 4, 71, 2, 131, 253, 8, 78, 196, 2, 140, 2, 5, 70, 69, 84, 89, 32, 36, 4, + 71, 73, 84, 84, 30, 76, 112, 8, 77, 65, 82, 73, 84, 65, 78, 32, 142, 14, + 78, 190, 3, 84, 100, 2, 85, 82, 132, 236, 2, 2, 73, 76, 198, 87, 88, 180, + 209, 5, 15, 75, 69, 32, 66, 79, 84, 84, 76, 69, 32, 65, 78, 68, 32, 67, + 143, 98, 82, 4, 234, 250, 1, 86, 151, 164, 7, 80, 2, 205, 201, 3, 2, 65, + 82, 6, 18, 84, 75, 85, 4, 36, 3, 32, 83, 72, 163, 253, 8, 73, 2, 11, 65, + 2, 211, 223, 9, 75, 2, 151, 149, 9, 84, 122, 184, 1, 7, 76, 69, 84, 84, + 69, 82, 32, 198, 3, 77, 248, 2, 12, 80, 85, 78, 67, 84, 85, 65, 84, 73, + 79, 78, 32, 132, 4, 11, 86, 79, 87, 69, 76, 32, 83, 73, 71, 78, 32, 155, + 137, 4, 65, 44, 202, 1, 66, 32, 2, 68, 65, 22, 73, 38, 75, 22, 76, 34, + 83, 46, 84, 182, 2, 65, 208, 204, 5, 2, 71, 65, 134, 139, 1, 82, 210, + 237, 1, 90, 190, 78, 77, 172, 1, 2, 81, 85, 118, 78, 218, 6, 89, 235, + 101, 70, 4, 214, 253, 9, 73, 247, 25, 65, 2, 147, 134, 9, 76, 6, 206, + 153, 10, 78, 2, 84, 3, 89, 2, 147, 152, 9, 65, 2, 11, 65, 2, 187, 133, 9, + 66, 4, 152, 7, 3, 73, 78, 71, 171, 202, 8, 72, 6, 178, 151, 9, 65, 238, + 100, 73, 229, 10, 5, 83, 65, 65, 68, 73, 18, 96, 4, 65, 82, 75, 32, 165, + 1, 15, 79, 68, 73, 70, 73, 69, 82, 32, 76, 69, 84, 84, 69, 82, 32, 12, + 82, 68, 40, 2, 73, 78, 90, 69, 242, 2, 78, 173, 249, 7, 5, 79, 67, 67, + 76, 85, 2, 17, 2, 65, 71, 2, 163, 177, 8, 69, 5, 17, 2, 45, 65, 2, 255, + 148, 9, 76, 6, 46, 69, 180, 6, 2, 83, 72, 163, 143, 10, 73, 2, 145, 156, + 9, 11, 80, 69, 78, 84, 72, 69, 84, 73, 67, 32, 89, 28, 130, 1, 65, 154, + 1, 66, 22, 78, 30, 83, 130, 1, 90, 238, 155, 3, 84, 200, 208, 6, 9, 77, + 69, 76, 79, 68, 73, 67, 32, 81, 3, 81, 10, 76, 3, 70, 83, 65, 34, 78, 28, + 2, 84, 77, 145, 238, 9, 4, 82, 75, 65, 65, 2, 11, 65, 2, 179, 147, 10, + 81, 4, 26, 78, 199, 179, 5, 71, 2, 11, 65, 2, 143, 238, 9, 65, 2, 177, + 132, 3, 2, 69, 81, 4, 64, 4, 72, 73, 89, 89, 41, 8, 79, 70, 32, 77, 65, + 83, 72, 70, 2, 17, 2, 65, 65, 2, 167, 162, 8, 76, 2, 139, 254, 8, 65, 4, + 34, 65, 221, 161, 8, 2, 73, 81, 2, 151, 144, 9, 69, 30, 92, 5, 76, 79, + 78, 71, 32, 54, 79, 66, 83, 146, 206, 4, 65, 174, 193, 5, 69, 2, 73, 3, + 85, 10, 130, 207, 4, 65, 174, 193, 5, 69, 2, 73, 3, 85, 7, 41, 8, 86, 69, + 82, 76, 79, 78, 71, 32, 4, 163, 206, 4, 65, 4, 26, 72, 183, 192, 5, 85, + 2, 153, 251, 5, 3, 79, 82, 84, 10, 68, 8, 83, 45, 83, 69, 82, 73, 70, 32, + 145, 236, 9, 3, 68, 87, 73, 8, 44, 6, 72, 69, 65, 86, 89, 32, 139, 2, 73, + 6, 48, 3, 68, 79, 85, 81, 5, 76, 79, 87, 32, 68, 4, 11, 66, 4, 21, 3, 76, + 69, 32, 4, 84, 6, 84, 85, 82, 78, 69, 68, 23, 67, 2, 21, 3, 79, 85, 66, + 2, 17, 2, 76, 69, 2, 17, 2, 32, 67, 2, 33, 6, 79, 77, 77, 65, 32, 81, 2, + 153, 197, 8, 3, 85, 79, 84, 2, 169, 200, 9, 10, 78, 84, 69, 82, 82, 79, + 66, 65, 78, 71, 6, 48, 6, 69, 76, 76, 73, 84, 69, 135, 173, 5, 85, 5, 25, + 4, 32, 65, 78, 84, 2, 251, 232, 6, 69, 166, 1, 52, 7, 65, 83, 72, 84, 82, + 65, 32, 163, 169, 4, 79, 164, 1, 180, 1, 7, 76, 69, 84, 84, 69, 82, 32, + 212, 1, 5, 83, 73, 71, 78, 32, 186, 17, 68, 156, 244, 2, 16, 67, 79, 78, + 83, 79, 78, 65, 78, 84, 32, 83, 73, 71, 78, 32, 72, 251, 138, 2, 86, 100, + 150, 160, 6, 65, 38, 68, 46, 84, 46, 86, 186, 24, 85, 158, 144, 1, 79, + 182, 56, 73, 42, 76, 246, 189, 1, 78, 46, 83, 82, 66, 2, 67, 2, 71, 2, + 74, 2, 75, 2, 80, 162, 7, 69, 222, 61, 72, 2, 77, 2, 82, 3, 89, 8, 234, + 160, 6, 67, 190, 161, 3, 65, 239, 1, 86, 52, 66, 65, 32, 4, 72, 79, 79, + 76, 46, 79, 74, 82, 143, 133, 10, 73, 4, 190, 242, 8, 76, 215, 18, 82, 5, + 165, 165, 5, 6, 32, 83, 65, 84, 67, 72, 6, 36, 3, 82, 80, 73, 227, 206, + 8, 79, 4, 214, 181, 9, 79, 135, 18, 85, 36, 66, 69, 72, 4, 73, 80, 84, + 32, 166, 243, 1, 85, 175, 140, 6, 79, 4, 36, 3, 87, 68, 82, 207, 180, 9, + 69, 2, 11, 73, 2, 179, 198, 9, 86, 28, 80, 8, 67, 65, 80, 73, 84, 65, 76, + 32, 86, 76, 81, 6, 83, 77, 65, 76, 76, 32, 18, 170, 131, 10, 66, 2, 69, + 2, 70, 2, 72, 2, 73, 2, 76, 2, 77, 2, 80, 3, 82, 2, 37, 7, 73, 71, 65, + 84, 85, 82, 69, 2, 11, 32, 2, 205, 190, 9, 2, 69, 84, 8, 134, 130, 10, + 69, 2, 71, 2, 76, 3, 79, 64, 250, 1, 65, 30, 67, 74, 69, 36, 5, 71, 77, + 69, 78, 84, 28, 2, 77, 73, 174, 1, 82, 158, 1, 83, 68, 2, 84, 32, 200, + 245, 4, 8, 87, 73, 78, 71, 32, 78, 69, 69, 172, 237, 1, 6, 80, 65, 82, + 65, 84, 69, 178, 122, 88, 202, 99, 68, 149, 159, 1, 2, 76, 70, 4, 222, + 255, 9, 76, 3, 84, 6, 34, 84, 157, 200, 5, 2, 79, 78, 4, 194, 165, 6, 73, + 143, 161, 3, 79, 4, 238, 216, 1, 68, 223, 131, 1, 45, 23, 181, 169, 4, 2, + 69, 68, 6, 128, 77, 28, 68, 73, 82, 69, 67, 84, 32, 80, 82, 79, 68, 85, + 67, 84, 32, 87, 73, 84, 72, 32, 66, 79, 84, 84, 79, 77, 32, 67, 172, 147, + 7, 3, 83, 69, 88, 151, 206, 1, 67, 4, 120, 2, 86, 73, 217, 171, 2, 22, + 73, 79, 85, 83, 32, 70, 65, 67, 69, 32, 87, 73, 84, 72, 32, 83, 89, 77, + 66, 79, 76, 83, 2, 11, 67, 2, 207, 186, 9, 69, 4, 52, 7, 81, 85, 73, 81, + 85, 65, 68, 155, 198, 8, 65, 2, 91, 82, 4, 64, 10, 84, 82, 65, 78, 83, + 77, 73, 84, 32, 83, 147, 158, 6, 77, 2, 11, 84, 2, 179, 182, 8, 65, 240, + 2, 102, 65, 254, 19, 73, 102, 79, 250, 10, 69, 70, 82, 184, 202, 8, 5, + 85, 70, 70, 76, 69, 143, 143, 1, 89, 176, 2, 164, 1, 12, 68, 79, 87, 69, + 68, 32, 87, 72, 73, 84, 69, 32, 68, 9, 76, 76, 79, 87, 32, 80, 65, 78, + 32, 62, 82, 206, 9, 86, 172, 133, 7, 2, 77, 82, 183, 224, 1, 75, 6, 38, + 76, 134, 169, 8, 67, 167, 11, 83, 2, 249, 185, 8, 2, 65, 84, 2, 17, 2, + 79, 70, 2, 17, 2, 32, 70, 2, 227, 213, 6, 79, 194, 1, 40, 4, 65, 68, 65, + 32, 135, 247, 9, 75, 192, 1, 162, 1, 68, 42, 69, 110, 72, 34, 76, 246, 1, + 83, 208, 2, 6, 86, 79, 87, 69, 76, 32, 226, 175, 4, 65, 196, 213, 1, 7, + 67, 79, 78, 84, 73, 78, 85, 235, 217, 3, 79, 24, 158, 32, 79, 66, 65, + 239, 230, 7, 73, 4, 84, 15, 88, 84, 82, 65, 32, 83, 72, 79, 82, 84, 32, + 86, 79, 87, 69, 163, 187, 8, 75, 2, 163, 179, 9, 76, 2, 189, 196, 9, 3, + 69, 65, 68, 96, 33, 6, 69, 84, 84, 69, 82, 32, 96, 178, 139, 6, 65, 38, + 68, 46, 84, 46, 86, 186, 24, 85, 210, 200, 1, 73, 42, 76, 246, 189, 1, + 78, 46, 83, 82, 66, 2, 67, 2, 71, 2, 74, 2, 75, 2, 80, 254, 68, 72, 2, + 77, 2, 82, 2, 89, 186, 2, 69, 3, 79, 30, 70, 65, 38, 69, 56, 4, 73, 71, + 78, 32, 141, 236, 8, 3, 85, 84, 82, 2, 177, 176, 9, 4, 78, 68, 72, 73, 6, + 132, 202, 2, 5, 67, 84, 73, 79, 78, 231, 142, 4, 80, 20, 102, 73, 182, + 249, 4, 83, 134, 144, 1, 65, 74, 67, 98, 78, 230, 179, 1, 74, 150, 3, 85, + 211, 235, 1, 86, 2, 37, 7, 78, 86, 69, 82, 84, 69, 68, 2, 213, 137, 6, 2, + 32, 67, 30, 60, 6, 77, 79, 68, 73, 70, 73, 21, 5, 83, 73, 71, 78, 32, 2, + 227, 252, 5, 69, 28, 86, 80, 226, 137, 6, 65, 106, 86, 214, 20, 85, 210, + 200, 1, 73, 206, 134, 2, 69, 3, 79, 2, 57, 12, 82, 73, 83, 72, 84, 72, + 65, 77, 65, 84, 82, 65, 2, 167, 215, 9, 32, 98, 72, 3, 69, 68, 32, 21, + 11, 73, 65, 78, 32, 76, 69, 84, 84, 69, 82, 32, 2, 171, 176, 9, 73, 96, + 158, 2, 65, 120, 3, 67, 72, 85, 22, 69, 70, 72, 46, 73, 46, 76, 22, 77, + 38, 79, 94, 80, 18, 82, 22, 83, 38, 84, 64, 2, 87, 79, 36, 2, 89, 69, + 208, 221, 4, 2, 74, 85, 162, 186, 2, 68, 202, 13, 90, 150, 84, 70, 182, + 6, 71, 210, 43, 66, 218, 11, 75, 206, 20, 86, 246, 25, 78, 143, 128, 1, + 85, 16, 82, 82, 198, 177, 9, 73, 222, 25, 68, 162, 8, 71, 2, 87, 198, 21, + 83, 147, 1, 72, 4, 166, 222, 8, 82, 239, 139, 1, 69, 2, 199, 199, 9, 82, + 8, 38, 65, 230, 176, 9, 82, 255, 55, 71, 4, 178, 233, 9, 82, 3, 84, 4, + 216, 241, 7, 2, 65, 45, 211, 166, 1, 85, 6, 150, 153, 9, 65, 130, 57, 67, + 215, 22, 70, 2, 143, 228, 7, 79, 4, 178, 136, 5, 69, 167, 200, 3, 73, 12, + 70, 79, 166, 222, 8, 73, 242, 108, 85, 150, 25, 65, 154, 3, 78, 3, 82, 2, + 235, 208, 9, 90, 2, 163, 13, 69, 2, 243, 196, 8, 79, 4, 230, 198, 8, 85, + 163, 160, 1, 79, 6, 26, 72, 159, 202, 9, 79, 4, 186, 238, 5, 73, 199, + 230, 3, 69, 4, 134, 221, 8, 79, 159, 137, 1, 69, 4, 254, 229, 9, 65, 3, + 87, 10, 78, 69, 222, 214, 3, 70, 192, 121, 6, 78, 84, 79, 32, 83, 72, + 251, 148, 5, 80, 2, 255, 158, 9, 76, 44, 236, 1, 2, 79, 84, 32, 6, 80, + 80, 73, 78, 71, 32, 72, 2, 82, 84, 180, 8, 7, 85, 76, 68, 69, 82, 69, 68, + 208, 240, 1, 24, 67, 75, 69, 68, 32, 70, 65, 67, 69, 32, 87, 73, 84, 72, + 32, 69, 88, 80, 76, 79, 68, 73, 78, 71, 199, 171, 7, 87, 2, 145, 208, 7, + 3, 73, 78, 71, 4, 36, 3, 84, 82, 79, 239, 220, 5, 66, 2, 11, 76, 2, 247, + 203, 7, 76, 32, 102, 32, 248, 5, 12, 72, 65, 78, 68, 32, 70, 79, 82, 77, + 65, 84, 32, 206, 149, 6, 67, 255, 197, 3, 83, 20, 154, 2, 66, 92, 11, 83, + 76, 65, 78, 84, 69, 68, 32, 78, 79, 82, 196, 1, 22, 82, 73, 71, 72, 84, + 87, 65, 82, 68, 83, 32, 65, 82, 82, 79, 87, 32, 65, 66, 79, 86, 69, 28, + 7, 85, 80, 32, 84, 65, 67, 75, 128, 1, 4, 76, 69, 70, 84, 133, 160, 2, 9, + 68, 79, 87, 78, 32, 84, 65, 67, 75, 4, 88, 14, 65, 67, 75, 83, 76, 65, + 78, 84, 69, 68, 32, 83, 79, 85, 33, 4, 69, 78, 84, 32, 2, 11, 84, 2, 255, + 195, 8, 72, 2, 213, 37, 37, 65, 82, 82, 79, 87, 32, 80, 79, 73, 78, 84, + 73, 78, 71, 32, 68, 79, 87, 78, 87, 65, 82, 68, 83, 32, 84, 72, 69, 78, + 32, 78, 79, 82, 84, 72, 32, 69, 2, 189, 237, 5, 2, 32, 76, 7, 11, 32, 4, + 76, 13, 65, 66, 79, 86, 69, 32, 83, 72, 79, 82, 84, 32, 68, 191, 131, 2, + 87, 2, 11, 79, 2, 11, 87, 2, 11, 78, 2, 11, 32, 2, 191, 209, 6, 84, 8, + 120, 10, 67, 79, 78, 84, 73, 78, 85, 73, 78, 71, 0, 6, 76, 69, 84, 84, + 69, 82, 44, 4, 68, 79, 87, 78, 1, 2, 85, 80, 2, 245, 201, 8, 6, 32, 79, + 86, 69, 82, 76, 2, 21, 3, 32, 83, 84, 2, 251, 217, 9, 69, 2, 25, 4, 32, + 79, 80, 69, 2, 167, 205, 8, 78, 4, 26, 73, 215, 216, 9, 85, 2, 155, 217, + 9, 77, 159, 14, 174, 1, 68, 132, 20, 2, 71, 78, 232, 181, 1, 6, 77, 73, + 76, 65, 82, 32, 158, 2, 78, 198, 24, 88, 225, 171, 6, 15, 76, 72, 79, 85, + 69, 84, 84, 69, 32, 79, 70, 32, 74, 65, 80, 200, 1, 64, 5, 68, 72, 65, + 77, 32, 225, 17, 6, 69, 87, 65, 89, 83, 32, 184, 1, 194, 1, 68, 106, 69, + 68, 7, 76, 69, 84, 84, 69, 82, 32, 172, 4, 15, 82, 69, 80, 69, 84, 73, + 84, 73, 79, 78, 32, 77, 65, 82, 75, 50, 83, 165, 8, 11, 86, 79, 87, 69, + 76, 32, 83, 73, 71, 78, 32, 4, 18, 79, 67, 65, 2, 11, 85, 2, 11, 66, 2, + 25, 4, 76, 69, 32, 68, 2, 11, 65, 2, 247, 175, 9, 78, 2, 37, 7, 78, 68, + 32, 79, 70, 32, 84, 2, 129, 138, 9, 2, 69, 88, 102, 210, 1, 65, 98, 84, + 198, 233, 5, 68, 90, 86, 186, 24, 85, 210, 200, 1, 73, 158, 190, 1, 78, + 46, 83, 82, 66, 2, 67, 2, 71, 2, 74, 2, 75, 2, 80, 254, 68, 72, 2, 76, 2, + 77, 2, 82, 2, 89, 186, 2, 69, 3, 79, 11, 72, 8, 76, 84, 69, 82, 78, 65, + 84, 69, 134, 210, 9, 65, 2, 73, 3, 85, 2, 155, 173, 9, 32, 14, 134, 1, + 72, 196, 212, 5, 19, 87, 79, 45, 67, 73, 82, 67, 76, 69, 32, 65, 76, 84, + 69, 82, 78, 65, 84, 69, 242, 180, 3, 84, 183, 71, 65, 4, 224, 144, 9, 20, + 82, 69, 69, 45, 67, 73, 82, 67, 76, 69, 32, 65, 76, 84, 69, 82, 78, 65, + 84, 69, 135, 64, 65, 6, 11, 45, 6, 234, 207, 9, 49, 2, 50, 3, 51, 44, 38, + 69, 181, 7, 4, 73, 71, 78, 32, 32, 96, 11, 67, 84, 73, 79, 78, 32, 77, + 65, 82, 75, 32, 177, 6, 8, 80, 65, 82, 65, 84, 79, 82, 32, 28, 80, 11, + 68, 79, 85, 66, 76, 69, 32, 82, 73, 78, 71, 57, 5, 87, 73, 84, 72, 32, 5, + 11, 32, 2, 225, 162, 8, 6, 87, 73, 84, 72, 32, 82, 24, 212, 1, 12, 67, + 73, 82, 67, 76, 69, 83, 32, 65, 78, 68, 32, 116, 5, 81, 85, 65, 68, 82, + 0, 4, 83, 69, 80, 84, 12, 16, 82, 65, 89, 83, 32, 65, 78, 68, 32, 68, 79, + 84, 84, 69, 68, 32, 46, 68, 45, 3, 84, 82, 73, 6, 60, 4, 70, 79, 85, 82, + 0, 3, 84, 87, 79, 163, 160, 8, 82, 2, 169, 160, 6, 8, 32, 69, 78, 67, 76, + 79, 83, 85, 2, 83, 85, 6, 42, 68, 28, 3, 84, 82, 73, 215, 1, 67, 2, 197, + 1, 3, 79, 85, 66, 2, 171, 1, 80, 6, 52, 9, 68, 69, 78, 84, 32, 65, 78, + 68, 32, 103, 80, 4, 116, 6, 68, 79, 84, 84, 69, 68, 49, 14, 85, 45, 83, + 72, 65, 80, 69, 68, 32, 79, 82, 78, 65, 77, 2, 17, 2, 76, 69, 2, 17, 2, + 32, 67, 2, 25, 4, 82, 69, 83, 67, 2, 151, 186, 1, 69, 4, 226, 165, 8, 66, + 255, 81, 68, 12, 246, 208, 4, 83, 206, 144, 1, 67, 98, 78, 222, 160, 3, + 65, 239, 1, 86, 26, 74, 65, 94, 86, 226, 246, 5, 85, 210, 200, 1, 73, + 206, 134, 2, 69, 3, 79, 10, 184, 247, 5, 10, 76, 84, 69, 82, 78, 65, 84, + 69, 32, 85, 158, 207, 3, 65, 2, 73, 3, 85, 4, 11, 79, 4, 33, 6, 67, 65, + 76, 73, 67, 32, 4, 167, 226, 5, 82, 16, 56, 5, 66, 76, 65, 67, 75, 1, 5, + 87, 72, 73, 84, 69, 8, 11, 32, 8, 70, 82, 24, 3, 76, 69, 70, 12, 4, 68, + 79, 87, 78, 1, 2, 85, 80, 2, 21, 3, 73, 71, 72, 2, 11, 84, 2, 225, 92, 6, + 32, 80, 79, 73, 78, 84, 194, 10, 96, 8, 87, 82, 73, 84, 73, 78, 71, 32, + 217, 238, 1, 10, 32, 79, 70, 32, 84, 72, 69, 32, 72, 79, 192, 10, 136, 3, + 4, 65, 73, 82, 32, 192, 1, 2, 66, 82, 102, 67, 138, 1, 68, 218, 4, 69, + 242, 6, 70, 244, 3, 4, 87, 65, 76, 76, 138, 1, 72, 238, 77, 76, 224, 6, + 2, 77, 79, 222, 42, 78, 230, 1, 82, 202, 7, 83, 162, 5, 84, 180, 10, 5, + 71, 82, 65, 83, 80, 184, 5, 30, 85, 80, 80, 69, 82, 32, 66, 79, 68, 89, + 32, 84, 73, 76, 84, 73, 78, 71, 32, 70, 82, 79, 77, 32, 72, 73, 80, 32, + 74, 79, 211, 179, 4, 80, 8, 48, 4, 66, 76, 79, 87, 29, 4, 83, 85, 67, 75, + 4, 58, 32, 195, 207, 4, 73, 4, 30, 32, 61, 3, 73, 78, 71, 2, 157, 158, 1, + 10, 83, 77, 65, 76, 76, 32, 82, 79, 84, 65, 2, 251, 190, 8, 32, 10, 52, + 5, 69, 65, 84, 72, 32, 149, 170, 1, 2, 85, 83, 4, 152, 163, 2, 2, 69, 88, + 1, 2, 73, 78, 10, 40, 6, 72, 69, 69, 75, 83, 32, 63, 79, 6, 170, 107, 83, + 146, 38, 78, 153, 204, 3, 4, 80, 85, 70, 70, 4, 246, 236, 8, 76, 211, 46, + 77, 28, 108, 15, 82, 69, 65, 77, 89, 32, 69, 89, 69, 66, 82, 79, 87, 83, + 32, 165, 1, 7, 89, 78, 65, 77, 73, 67, 32, 8, 64, 4, 68, 79, 87, 78, 0, + 2, 85, 80, 29, 4, 78, 69, 85, 84, 2, 169, 143, 1, 2, 32, 78, 4, 21, 3, + 82, 65, 76, 4, 11, 32, 4, 194, 58, 68, 247, 255, 8, 85, 20, 180, 1, 11, + 69, 86, 69, 82, 89, 32, 79, 84, 72, 69, 82, 30, 70, 22, 83, 144, 122, 9, + 65, 82, 82, 79, 87, 72, 69, 65, 68, 138, 39, 82, 232, 186, 3, 2, 84, 69, + 21, 4, 71, 82, 65, 68, 2, 137, 161, 8, 2, 32, 84, 2, 135, 241, 5, 65, 6, + 68, 11, 73, 77, 85, 76, 84, 65, 78, 69, 79, 85, 83, 235, 157, 8, 76, 5, + 251, 151, 1, 32, 54, 64, 2, 89, 69, 188, 208, 4, 4, 88, 67, 73, 84, 167, + 216, 3, 65, 50, 166, 1, 32, 56, 15, 66, 82, 79, 87, 83, 32, 83, 84, 82, + 65, 73, 71, 72, 84, 32, 44, 5, 71, 65, 90, 69, 45, 140, 2, 7, 76, 65, 83, + 72, 69, 83, 32, 65, 2, 83, 32, 6, 140, 151, 1, 5, 66, 76, 73, 78, 75, + 131, 224, 4, 87, 6, 186, 53, 68, 170, 84, 78, 207, 171, 8, 85, 18, 100, + 11, 70, 76, 79, 79, 82, 80, 76, 65, 78, 69, 32, 25, 10, 87, 65, 76, 76, + 80, 76, 65, 78, 69, 32, 8, 82, 83, 207, 45, 67, 10, 18, 67, 43, 83, 4, + 254, 45, 85, 241, 95, 3, 73, 82, 67, 6, 37, 7, 84, 82, 65, 73, 71, 72, + 84, 7, 11, 32, 4, 250, 163, 1, 65, 55, 68, 6, 130, 51, 68, 196, 154, 4, + 4, 70, 76, 85, 84, 179, 229, 4, 85, 14, 112, 5, 72, 65, 76, 70, 32, 26, + 67, 28, 4, 87, 73, 68, 69, 246, 92, 79, 233, 244, 3, 6, 83, 81, 85, 69, + 69, 90, 4, 22, 67, 147, 93, 79, 2, 205, 229, 2, 2, 76, 79, 4, 162, 67, + 32, 233, 61, 4, 78, 73, 78, 71, 38, 204, 1, 28, 65, 67, 69, 32, 68, 73, + 82, 69, 67, 84, 73, 79, 78, 32, 80, 79, 83, 73, 84, 73, 79, 78, 32, 78, + 79, 83, 69, 32, 138, 1, 73, 82, 76, 176, 1, 8, 79, 82, 69, 72, 69, 65, + 68, 32, 163, 225, 6, 85, 6, 88, 10, 85, 80, 32, 79, 82, 32, 68, 79, 87, + 78, 13, 8, 70, 79, 82, 87, 65, 82, 68, 32, 5, 11, 32, 2, 169, 212, 4, 3, + 84, 73, 76, 12, 248, 210, 3, 11, 76, 76, 32, 77, 79, 68, 73, 70, 73, 69, + 82, 171, 163, 2, 78, 12, 44, 4, 73, 67, 75, 32, 29, 3, 79, 79, 82, 10, + 174, 141, 1, 76, 35, 83, 2, 169, 176, 8, 20, 80, 76, 65, 78, 69, 32, 83, + 72, 79, 85, 76, 68, 69, 82, 32, 72, 73, 80, 32, 77, 6, 182, 89, 87, 222, + 38, 67, 47, 78, 156, 4, 34, 65, 137, 75, 3, 69, 65, 68, 140, 4, 36, 3, + 78, 68, 45, 211, 242, 8, 73, 138, 4, 92, 5, 65, 78, 71, 76, 69, 138, 5, + 67, 150, 10, 70, 186, 42, 72, 241, 12, 4, 79, 86, 65, 76, 37, 11, 32, 34, + 188, 1, 5, 73, 78, 68, 69, 88, 176, 1, 7, 76, 73, 84, 84, 76, 69, 32, + 136, 1, 5, 82, 73, 78, 71, 32, 173, 66, 18, 77, 73, 68, 68, 76, 69, 32, + 82, 73, 78, 71, 32, 76, 73, 84, 84, 76, 69, 17, 11, 32, 14, 128, 1, 7, + 77, 73, 68, 68, 76, 69, 32, 228, 24, 11, 82, 73, 78, 71, 32, 76, 73, 84, + 84, 76, 69, 241, 42, 5, 84, 72, 85, 77, 66, 4, 178, 70, 76, 183, 144, 8, + 82, 8, 44, 5, 73, 78, 68, 69, 88, 135, 167, 9, 85, 7, 145, 24, 18, 32, + 84, 72, 85, 77, 66, 32, 73, 78, 68, 69, 88, 32, 84, 72, 85, 77, 66, 4, + 108, 22, 68, 79, 87, 78, 32, 77, 73, 68, 68, 76, 69, 32, 84, 72, 85, 77, + 66, 32, 73, 78, 68, 69, 159, 68, 76, 2, 207, 231, 7, 88, 88, 64, 5, 73, + 82, 67, 76, 69, 184, 3, 3, 76, 65, 87, 183, 2, 85, 35, 11, 32, 32, 116, + 5, 73, 78, 68, 69, 88, 200, 1, 7, 76, 73, 84, 84, 76, 69, 32, 36, 7, 77, + 73, 68, 68, 76, 69, 32, 167, 64, 82, 21, 11, 32, 18, 72, 6, 77, 73, 68, + 68, 76, 69, 198, 26, 72, 246, 38, 82, 195, 158, 8, 66, 13, 11, 32, 10, + 64, 5, 67, 82, 79, 83, 83, 194, 64, 84, 90, 76, 183, 144, 8, 82, 4, 138, + 65, 32, 167, 155, 8, 69, 4, 170, 253, 7, 73, 239, 164, 1, 85, 6, 252, 47, + 10, 82, 73, 78, 71, 32, 76, 73, 84, 84, 76, 247, 241, 8, 85, 17, 11, 32, + 14, 144, 2, 28, 77, 73, 68, 68, 76, 69, 32, 82, 73, 78, 71, 32, 76, 73, + 84, 84, 76, 69, 32, 67, 79, 78, 74, 79, 73, 78, 69, 68, 176, 49, 2, 70, + 79, 194, 11, 78, 170, 1, 84, 237, 118, 23, 73, 78, 68, 69, 88, 32, 84, + 72, 85, 77, 66, 32, 67, 85, 82, 86, 69, 32, 84, 72, 85, 77, 66, 5, 163, + 181, 1, 32, 38, 46, 80, 149, 2, 6, 82, 76, 73, 67, 85, 69, 31, 11, 32, + 28, 188, 1, 5, 73, 78, 68, 69, 88, 56, 19, 70, 73, 86, 69, 32, 70, 73, + 78, 71, 69, 82, 83, 32, 83, 80, 82, 69, 65, 68, 196, 50, 7, 77, 73, 68, + 68, 76, 69, 32, 18, 79, 214, 7, 78, 171, 1, 84, 9, 11, 32, 6, 40, 5, 84, + 72, 85, 77, 66, 247, 58, 82, 5, 215, 46, 32, 9, 11, 32, 6, 72, 5, 73, 78, + 68, 69, 88, 0, 6, 77, 73, 68, 68, 76, 69, 195, 71, 79, 2, 133, 204, 8, + 13, 32, 82, 73, 78, 71, 32, 76, 73, 84, 84, 76, 69, 32, 172, 2, 44, 3, + 73, 83, 84, 177, 33, 3, 76, 65, 84, 247, 1, 11, 32, 244, 1, 160, 2, 5, + 73, 78, 68, 69, 88, 192, 16, 7, 76, 73, 84, 84, 76, 69, 32, 196, 2, 7, + 77, 73, 68, 68, 76, 69, 32, 200, 4, 5, 82, 73, 78, 71, 32, 132, 2, 5, 84, + 72, 85, 77, 66, 138, 2, 72, 205, 9, 22, 70, 79, 85, 82, 32, 70, 73, 78, + 71, 69, 82, 83, 32, 67, 79, 78, 74, 79, 73, 78, 69, 68, 137, 1, 11, 32, + 134, 1, 232, 1, 4, 66, 69, 78, 84, 36, 6, 72, 73, 78, 71, 69, 68, 76, 6, + 77, 73, 68, 68, 76, 69, 168, 7, 2, 67, 85, 64, 6, 84, 72, 85, 77, 66, 32, + 160, 5, 16, 85, 80, 32, 77, 73, 68, 68, 76, 69, 32, 72, 73, 78, 71, 69, + 68, 151, 4, 82, 5, 217, 45, 5, 32, 79, 86, 69, 82, 9, 11, 32, 6, 252, 20, + 8, 77, 73, 68, 68, 76, 69, 32, 85, 251, 230, 7, 76, 71, 11, 32, 68, 236, + 1, 4, 66, 69, 78, 84, 42, 67, 244, 1, 10, 85, 80, 32, 83, 80, 82, 69, 65, + 68, 32, 100, 6, 72, 73, 78, 71, 69, 68, 46, 82, 80, 5, 84, 72, 85, 77, + 66, 188, 28, 14, 83, 84, 82, 65, 73, 71, 72, 84, 32, 84, 72, 85, 77, 66, + 231, 17, 76, 5, 229, 92, 6, 32, 84, 72, 85, 77, 66, 28, 68, 8, 79, 78, + 74, 79, 73, 78, 69, 68, 233, 1, 4, 82, 79, 83, 83, 23, 11, 32, 20, 144, + 1, 6, 67, 85, 80, 80, 69, 68, 28, 6, 84, 72, 85, 77, 66, 32, 68, 5, 72, + 73, 78, 71, 69, 166, 22, 73, 165, 7, 6, 77, 73, 68, 68, 76, 69, 5, 11, + 32, 2, 203, 27, 84, 8, 160, 1, 4, 83, 73, 68, 69, 235, 61, 70, 6, 22, 69, + 163, 47, 32, 4, 223, 15, 68, 5, 241, 30, 7, 32, 83, 80, 82, 69, 65, 68, + 8, 32, 3, 73, 78, 71, 247, 19, 65, 7, 11, 32, 4, 138, 36, 67, 199, 168, + 8, 66, 19, 11, 32, 16, 64, 6, 65, 78, 71, 76, 69, 68, 22, 67, 106, 72, + 231, 202, 8, 66, 5, 207, 188, 5, 32, 6, 74, 85, 230, 7, 73, 241, 25, 10, + 79, 78, 74, 79, 73, 78, 69, 68, 32, 72, 2, 217, 174, 4, 2, 80, 80, 4, + 194, 33, 73, 233, 26, 2, 79, 79, 40, 164, 1, 7, 65, 78, 71, 76, 69, 68, + 32, 46, 67, 220, 1, 14, 70, 79, 82, 87, 65, 82, 68, 32, 73, 78, 68, 69, + 88, 32, 32, 4, 72, 79, 79, 75, 53, 4, 83, 73, 68, 69, 4, 128, 1, 2, 73, + 78, 1, 3, 79, 85, 84, 12, 36, 5, 73, 82, 67, 76, 69, 15, 85, 5, 47, 68, + 8, 32, 4, 80, 80, 69, 68, 39, 82, 2, 221, 40, 5, 32, 77, 73, 68, 68, 6, + 56, 9, 86, 69, 32, 84, 72, 85, 77, 66, 32, 143, 37, 76, 4, 206, 160, 1, + 73, 219, 164, 4, 85, 4, 218, 84, 83, 183, 242, 7, 66, 7, 157, 8, 9, 69, + 68, 32, 77, 73, 68, 68, 76, 69, 15, 11, 32, 12, 92, 6, 73, 78, 68, 69, + 88, 32, 156, 13, 5, 84, 72, 85, 77, 66, 193, 8, 4, 66, 79, 84, 72, 4, 26, + 72, 183, 197, 8, 66, 2, 207, 212, 7, 73, 7, 37, 7, 32, 84, 72, 85, 77, + 66, 32, 4, 178, 28, 67, 251, 129, 1, 83, 22, 88, 4, 68, 79, 87, 78, 186, + 1, 84, 158, 6, 82, 130, 21, 73, 170, 167, 8, 66, 147, 67, 85, 9, 11, 32, + 6, 80, 9, 79, 84, 72, 69, 82, 83, 32, 67, 73, 25, 7, 82, 73, 80, 80, 76, + 69, 32, 2, 241, 51, 2, 82, 67, 4, 22, 67, 187, 80, 83, 2, 11, 85, 2, 185, + 166, 4, 2, 82, 86, 4, 192, 35, 6, 79, 85, 67, 72, 69, 83, 39, 72, 30, + 134, 1, 82, 28, 6, 84, 72, 85, 77, 66, 32, 138, 3, 85, 134, 1, 68, 214, + 30, 76, 161, 188, 7, 9, 66, 69, 78, 84, 32, 79, 86, 69, 82, 4, 238, 4, + 65, 235, 29, 73, 16, 80, 7, 65, 78, 71, 76, 69, 68, 32, 126, 67, 124, 4, + 72, 79, 79, 75, 151, 32, 76, 6, 60, 10, 79, 85, 84, 32, 73, 78, 68, 69, + 88, 32, 215, 1, 73, 4, 26, 67, 211, 130, 9, 85, 2, 241, 182, 2, 3, 82, + 79, 83, 6, 76, 12, 73, 82, 67, 76, 69, 68, 32, 73, 78, 68, 69, 88, 45, 3, + 85, 80, 80, 4, 11, 32, 4, 150, 21, 72, 191, 236, 8, 85, 2, 25, 4, 69, 68, + 32, 73, 2, 229, 30, 4, 78, 68, 69, 88, 4, 11, 80, 5, 175, 15, 32, 18, + 102, 68, 20, 6, 77, 73, 68, 68, 76, 69, 42, 82, 194, 29, 84, 90, 76, 182, + 188, 7, 73, 239, 164, 1, 85, 2, 223, 174, 7, 79, 7, 11, 32, 4, 206, 3, + 82, 179, 16, 67, 2, 11, 65, 2, 37, 7, 73, 83, 69, 68, 32, 75, 78, 2, 11, + 85, 2, 11, 67, 2, 211, 221, 7, 75, 35, 11, 32, 32, 148, 1, 8, 66, 69, 84, + 87, 69, 69, 78, 32, 102, 72, 20, 5, 79, 86, 69, 82, 32, 120, 4, 83, 73, + 68, 69, 100, 6, 85, 78, 68, 69, 82, 32, 223, 40, 70, 8, 80, 12, 73, 78, + 68, 69, 88, 32, 77, 73, 68, 68, 76, 69, 246, 20, 77, 159, 6, 82, 5, 151, + 70, 32, 2, 131, 156, 4, 69, 4, 52, 6, 70, 79, 85, 82, 32, 82, 161, 2, 2, + 84, 87, 2, 11, 65, 2, 133, 81, 9, 73, 83, 69, 68, 32, 75, 78, 85, 67, 6, + 11, 32, 6, 38, 68, 190, 15, 67, 199, 168, 8, 66, 2, 25, 4, 73, 65, 71, + 79, 2, 215, 241, 7, 78, 10, 54, 73, 34, 84, 48, 4, 70, 79, 85, 82, 255, + 22, 76, 2, 161, 7, 4, 78, 68, 69, 88, 4, 34, 87, 13, 4, 72, 82, 69, 69, + 2, 11, 79, 2, 153, 235, 7, 5, 32, 70, 73, 78, 71, 55, 11, 32, 52, 194, 1, + 70, 172, 3, 4, 72, 69, 69, 76, 192, 1, 6, 83, 80, 76, 73, 84, 32, 236, 1, + 6, 84, 72, 85, 77, 66, 32, 153, 231, 4, 16, 66, 69, 84, 87, 69, 69, 78, + 32, 80, 65, 76, 77, 32, 70, 65, 67, 24, 140, 1, 18, 73, 86, 69, 32, 70, + 73, 78, 71, 69, 82, 83, 32, 83, 80, 82, 69, 65, 68, 165, 1, 11, 79, 85, + 82, 32, 70, 73, 78, 71, 69, 82, 83, 15, 11, 32, 12, 68, 6, 72, 73, 78, + 71, 69, 68, 42, 84, 186, 2, 70, 143, 176, 8, 66, 7, 11, 32, 4, 190, 4, + 84, 151, 15, 78, 2, 205, 35, 6, 72, 85, 77, 66, 32, 70, 11, 11, 32, 8, + 72, 9, 67, 79, 78, 74, 79, 73, 78, 69, 68, 154, 8, 72, 175, 169, 8, 66, + 5, 153, 216, 8, 3, 32, 83, 80, 11, 11, 32, 8, 96, 19, 70, 73, 86, 69, 32, + 70, 73, 78, 71, 69, 82, 83, 32, 83, 80, 82, 69, 65, 68, 151, 2, 84, 7, + 11, 32, 4, 26, 70, 143, 176, 8, 66, 2, 21, 3, 79, 85, 82, 2, 167, 1, 32, + 10, 72, 6, 67, 69, 78, 84, 82, 69, 96, 5, 73, 78, 68, 69, 88, 171, 16, + 76, 7, 49, 10, 32, 84, 72, 85, 77, 66, 32, 83, 73, 68, 4, 11, 69, 5, 11, + 32, 2, 203, 174, 8, 66, 2, 11, 32, 2, 11, 84, 2, 197, 135, 1, 5, 72, 85, + 77, 66, 32, 6, 130, 31, 70, 170, 104, 83, 207, 166, 7, 66, 82, 48, 4, 73, + 78, 71, 69, 181, 9, 3, 79, 79, 75, 63, 11, 32, 60, 206, 1, 70, 172, 1, 5, + 73, 78, 68, 69, 88, 196, 2, 6, 76, 73, 84, 84, 76, 69, 80, 6, 77, 73, 68, + 68, 76, 69, 30, 79, 64, 4, 82, 73, 78, 71, 124, 6, 84, 72, 85, 77, 66, + 32, 154, 6, 78, 215, 128, 4, 83, 4, 92, 19, 73, 86, 69, 32, 70, 73, 78, + 71, 69, 82, 83, 32, 83, 80, 82, 69, 65, 68, 32, 19, 79, 2, 207, 25, 79, + 2, 249, 1, 11, 85, 82, 32, 70, 73, 78, 71, 69, 82, 83, 32, 23, 11, 32, + 20, 86, 72, 40, 7, 77, 73, 68, 68, 76, 69, 32, 104, 5, 84, 72, 85, 77, + 66, 223, 9, 82, 2, 11, 73, 2, 249, 140, 4, 2, 78, 71, 6, 36, 4, 82, 73, + 78, 71, 207, 10, 76, 5, 11, 32, 2, 11, 67, 2, 21, 3, 79, 78, 74, 2, 191, + 33, 79, 11, 11, 32, 8, 34, 83, 226, 22, 79, 203, 39, 76, 4, 146, 222, 6, + 73, 187, 8, 77, 9, 11, 32, 6, 22, 73, 195, 8, 84, 4, 25, 4, 78, 68, 69, + 88, 5, 151, 8, 32, 5, 11, 32, 2, 175, 8, 82, 8, 21, 3, 80, 69, 78, 9, 11, + 32, 6, 174, 7, 78, 171, 1, 84, 5, 97, 22, 32, 68, 79, 87, 78, 32, 73, 78, + 68, 69, 88, 32, 84, 72, 85, 77, 66, 32, 72, 79, 79, 75, 2, 205, 77, 2, + 32, 77, 6, 68, 9, 66, 69, 84, 87, 69, 69, 78, 32, 77, 53, 4, 83, 73, 68, + 69, 2, 29, 5, 73, 68, 68, 76, 69, 2, 235, 134, 4, 32, 5, 33, 6, 32, 84, + 79, 85, 67, 72, 2, 145, 194, 7, 3, 73, 78, 71, 21, 11, 32, 18, 172, 1, 4, + 67, 85, 82, 76, 28, 18, 73, 78, 68, 69, 88, 32, 82, 73, 78, 71, 32, 76, + 73, 84, 84, 76, 69, 32, 48, 7, 77, 73, 68, 68, 76, 69, 32, 221, 2, 4, 82, + 73, 78, 71, 2, 229, 132, 5, 2, 73, 67, 6, 254, 159, 5, 85, 234, 203, 2, + 79, 239, 41, 73, 8, 104, 21, 82, 73, 78, 71, 32, 76, 73, 84, 84, 76, 69, + 32, 67, 79, 78, 74, 79, 73, 78, 69, 68, 139, 2, 84, 7, 231, 213, 2, 32, + 17, 11, 32, 14, 130, 1, 76, 66, 78, 78, 82, 94, 84, 136, 154, 2, 15, 70, + 73, 86, 69, 32, 70, 73, 78, 71, 69, 82, 83, 32, 83, 80, 131, 162, 5, 73, + 2, 21, 3, 73, 84, 84, 2, 17, 2, 76, 69, 2, 215, 236, 7, 32, 2, 11, 79, 2, + 11, 32, 2, 11, 84, 2, 11, 72, 2, 209, 167, 7, 2, 85, 77, 2, 11, 73, 2, + 21, 3, 78, 71, 32, 2, 11, 76, 2, 11, 73, 2, 11, 84, 2, 239, 191, 7, 84, + 4, 29, 5, 72, 85, 77, 66, 32, 4, 206, 14, 70, 171, 104, 83, 17, 11, 32, + 14, 56, 8, 77, 79, 86, 69, 77, 69, 78, 84, 199, 221, 7, 82, 12, 26, 45, + 207, 144, 7, 32, 10, 100, 11, 70, 76, 79, 79, 82, 80, 76, 65, 78, 69, 32, + 25, 10, 87, 65, 76, 76, 80, 76, 65, 78, 69, 32, 4, 62, 67, 235, 40, 83, + 6, 38, 67, 28, 2, 84, 73, 207, 40, 83, 2, 241, 225, 7, 2, 85, 82, 2, 239, + 193, 8, 76, 38, 50, 73, 225, 3, 7, 79, 67, 65, 84, 73, 79, 78, 22, 32, 3, + 77, 66, 32, 171, 1, 80, 16, 56, 4, 67, 79, 77, 66, 29, 6, 76, 69, 78, 71, + 84, 72, 2, 189, 176, 5, 2, 73, 78, 14, 11, 45, 14, 202, 220, 8, 49, 2, + 50, 2, 51, 2, 52, 2, 53, 2, 54, 3, 55, 6, 58, 32, 153, 1, 9, 83, 32, 80, + 82, 69, 83, 83, 69, 68, 4, 116, 12, 76, 79, 87, 69, 82, 32, 79, 86, 69, + 82, 32, 85, 213, 193, 7, 11, 85, 80, 80, 69, 82, 32, 79, 86, 69, 82, 32, + 2, 11, 80, 2, 231, 156, 8, 80, 2, 29, 5, 32, 84, 79, 71, 69, 2, 11, 84, + 2, 167, 156, 8, 72, 16, 22, 32, 215, 1, 45, 12, 140, 1, 2, 72, 69, 48, 3, + 84, 79, 82, 152, 217, 6, 3, 68, 69, 80, 0, 3, 87, 73, 68, 241, 106, 10, + 76, 73, 77, 66, 83, 32, 68, 73, 71, 73, 4, 216, 13, 4, 65, 68, 32, 78, + 175, 160, 8, 73, 2, 167, 185, 8, 83, 4, 52, 5, 70, 76, 79, 79, 82, 1, 4, + 87, 65, 76, 76, 2, 149, 153, 8, 5, 80, 76, 65, 78, 69, 156, 3, 64, 4, 85, + 84, 72, 32, 161, 5, 7, 86, 69, 77, 69, 78, 84, 45, 54, 186, 1, 67, 88, 5, + 70, 82, 79, 87, 78, 0, 5, 83, 77, 73, 76, 69, 56, 4, 75, 73, 83, 83, 36, + 5, 79, 80, 69, 78, 32, 192, 1, 5, 84, 69, 78, 83, 69, 165, 29, 5, 87, 82, + 73, 78, 75, 8, 48, 6, 76, 79, 83, 69, 68, 32, 243, 166, 7, 79, 6, 222, 2, + 70, 142, 38, 67, 47, 78, 7, 11, 32, 4, 22, 79, 203, 1, 87, 2, 179, 131, + 7, 80, 7, 11, 32, 4, 166, 1, 87, 83, 70, 18, 100, 4, 79, 86, 65, 76, 0, + 9, 82, 69, 67, 84, 65, 78, 71, 76, 69, 42, 87, 82, 70, 139, 131, 7, 67, + 7, 11, 32, 4, 26, 87, 183, 129, 7, 89, 2, 25, 4, 82, 73, 78, 75, 2, 131, + 243, 3, 76, 7, 11, 32, 4, 18, 70, 43, 83, 2, 17, 2, 79, 82, 2, 155, 187, + 7, 87, 2, 17, 2, 85, 67, 2, 147, 242, 3, 75, 230, 2, 192, 1, 9, 68, 73, + 65, 71, 79, 78, 65, 76, 32, 148, 1, 11, 70, 76, 79, 79, 82, 80, 76, 65, + 78, 69, 32, 184, 14, 6, 72, 73, 78, 71, 69, 32, 189, 2, 10, 87, 65, 76, + 76, 80, 76, 65, 78, 69, 32, 32, 56, 8, 66, 69, 84, 87, 69, 69, 78, 32, + 22, 65, 31, 84, 16, 18, 65, 31, 84, 8, 229, 28, 3, 87, 65, 89, 8, 201, + 28, 6, 79, 87, 65, 82, 68, 83, 150, 1, 208, 2, 24, 65, 82, 77, 32, 67, + 73, 82, 67, 76, 69, 32, 72, 73, 84, 84, 73, 78, 71, 32, 87, 65, 76, 76, + 32, 38, 66, 34, 67, 224, 1, 8, 70, 73, 78, 71, 69, 82, 32, 67, 52, 5, 72, + 85, 77, 80, 32, 184, 3, 5, 76, 79, 79, 80, 32, 198, 1, 83, 108, 7, 84, + 82, 73, 80, 76, 69, 32, 110, 87, 206, 12, 68, 198, 2, 80, 154, 6, 90, + 159, 175, 7, 74, 12, 178, 7, 76, 154, 9, 77, 39, 83, 8, 150, 17, 79, 243, + 172, 7, 69, 28, 86, 72, 20, 5, 85, 82, 86, 69, 32, 196, 29, 5, 79, 82, + 78, 69, 82, 195, 239, 6, 82, 2, 163, 156, 7, 69, 18, 80, 4, 67, 79, 77, + 66, 158, 8, 72, 230, 15, 76, 198, 157, 2, 77, 243, 178, 1, 83, 2, 11, 73, + 2, 187, 234, 3, 78, 6, 128, 9, 6, 73, 82, 67, 76, 69, 83, 239, 20, 79, + 18, 56, 8, 72, 73, 84, 84, 73, 78, 71, 32, 167, 231, 3, 83, 16, 72, 8, + 67, 69, 73, 76, 73, 78, 71, 32, 101, 6, 70, 76, 79, 79, 82, 32, 8, 56, 5, + 76, 65, 82, 71, 69, 1, 5, 83, 77, 65, 76, 76, 4, 11, 32, 4, 238, 54, 84, + 135, 2, 68, 8, 88, 4, 83, 77, 65, 76, 12, 5, 76, 65, 82, 71, 69, 17, 7, + 84, 82, 73, 80, 76, 69, 32, 2, 11, 76, 2, 255, 18, 32, 4, 56, 5, 76, 65, + 82, 71, 69, 1, 5, 83, 77, 65, 76, 76, 2, 157, 53, 2, 32, 84, 18, 56, 8, + 72, 73, 84, 84, 73, 78, 71, 32, 239, 227, 3, 83, 16, 64, 7, 67, 69, 73, + 76, 73, 78, 71, 1, 5, 70, 76, 79, 79, 82, 8, 11, 32, 8, 22, 76, 191, 9, + 83, 4, 249, 22, 4, 65, 82, 71, 69, 12, 44, 6, 72, 65, 75, 73, 78, 71, + 243, 16, 73, 2, 21, 3, 32, 80, 65, 2, 149, 227, 3, 4, 82, 65, 76, 76, 8, + 76, 12, 65, 76, 84, 69, 82, 78, 65, 84, 73, 78, 71, 32, 138, 18, 87, 63, + 83, 4, 134, 18, 87, 159, 21, 77, 18, 80, 4, 65, 86, 69, 32, 169, 1, 11, + 82, 73, 83, 84, 32, 67, 73, 82, 67, 76, 69, 14, 30, 72, 102, 83, 171, 20, + 76, 8, 37, 7, 73, 84, 84, 73, 78, 71, 32, 8, 252, 2, 4, 67, 69, 73, 76, + 25, 5, 70, 76, 79, 79, 82, 4, 138, 251, 4, 78, 195, 193, 1, 77, 4, 209, + 5, 10, 32, 72, 73, 84, 84, 73, 78, 71, 32, 87, 14, 112, 3, 85, 80, 32, + 184, 1, 6, 68, 79, 87, 78, 32, 83, 245, 183, 5, 10, 83, 73, 68, 69, 32, + 84, 79, 32, 83, 73, 10, 40, 5, 68, 79, 87, 78, 32, 143, 1, 83, 8, 68, 8, + 65, 76, 84, 69, 82, 78, 65, 84, 230, 17, 76, 143, 203, 3, 83, 4, 21, 3, + 73, 78, 71, 4, 11, 32, 4, 190, 17, 76, 143, 203, 3, 83, 2, 219, 30, 69, + 162, 1, 148, 2, 11, 65, 82, 77, 32, 67, 73, 82, 67, 76, 69, 32, 98, 66, + 54, 67, 174, 4, 68, 100, 8, 70, 73, 78, 71, 69, 82, 32, 67, 64, 5, 72, + 85, 77, 80, 32, 60, 5, 76, 79, 79, 80, 32, 102, 80, 34, 83, 216, 1, 7, + 84, 82, 73, 80, 76, 69, 32, 218, 1, 87, 202, 2, 90, 159, 175, 7, 74, 8, + 18, 77, 39, 83, 4, 225, 13, 5, 69, 68, 73, 85, 77, 4, 11, 77, 4, 177, 13, + 3, 65, 76, 76, 12, 34, 79, 185, 13, 3, 69, 78, 68, 6, 183, 13, 88, 46, + 100, 6, 79, 82, 78, 69, 82, 32, 88, 4, 85, 82, 86, 69, 232, 11, 4, 72, + 69, 67, 75, 195, 239, 6, 82, 8, 54, 82, 194, 12, 76, 158, 152, 2, 77, + 243, 178, 1, 83, 2, 11, 79, 2, 223, 140, 5, 84, 30, 50, 32, 137, 2, 7, + 68, 32, 67, 82, 79, 83, 83, 26, 66, 72, 68, 2, 84, 72, 133, 5, 7, 81, 85, + 65, 82, 84, 69, 82, 12, 196, 5, 10, 65, 76, 70, 45, 67, 73, 82, 67, 76, + 69, 159, 14, 73, 6, 96, 2, 69, 78, 29, 18, 82, 69, 69, 45, 81, 85, 65, + 82, 84, 69, 82, 32, 67, 73, 82, 67, 76, 69, 2, 11, 32, 2, 131, 1, 83, 4, + 11, 32, 4, 242, 161, 2, 77, 243, 178, 1, 83, 8, 33, 6, 79, 85, 66, 76, + 69, 32, 8, 30, 83, 150, 4, 65, 75, 87, 2, 253, 138, 8, 3, 84, 82, 65, 6, + 32, 3, 73, 82, 67, 151, 9, 79, 4, 173, 7, 3, 76, 69, 83, 10, 142, 8, 76, + 178, 8, 72, 238, 143, 2, 77, 243, 178, 1, 83, 12, 68, 5, 83, 77, 65, 76, + 76, 142, 7, 76, 178, 8, 72, 239, 143, 2, 77, 5, 11, 32, 2, 239, 36, 68, + 6, 181, 6, 4, 69, 65, 75, 83, 12, 22, 73, 243, 36, 72, 10, 29, 5, 78, 71, + 76, 69, 32, 10, 52, 8, 83, 84, 82, 65, 73, 71, 72, 84, 207, 1, 87, 8, 11, + 32, 8, 42, 76, 198, 157, 2, 77, 243, 178, 1, 83, 4, 25, 4, 65, 82, 71, + 69, 5, 191, 149, 8, 83, 8, 26, 65, 74, 87, 63, 83, 4, 49, 10, 76, 84, 69, + 82, 78, 65, 84, 73, 78, 71, 5, 17, 2, 32, 87, 2, 29, 5, 82, 73, 83, 84, + 32, 2, 237, 139, 7, 2, 70, 76, 2, 37, 7, 84, 82, 65, 73, 71, 72, 84, 2, + 171, 20, 32, 26, 104, 4, 65, 86, 69, 32, 185, 1, 17, 82, 73, 83, 84, 32, + 67, 73, 82, 67, 76, 69, 32, 70, 82, 79, 78, 84, 22, 108, 6, 67, 85, 82, + 86, 69, 32, 140, 1, 13, 68, 73, 65, 71, 79, 78, 65, 76, 32, 80, 65, 84, + 72, 235, 8, 72, 12, 48, 4, 68, 79, 85, 66, 1, 4, 84, 82, 73, 80, 6, 85, + 2, 76, 69, 4, 11, 32, 4, 222, 30, 68, 43, 83, 6, 29, 5, 73, 71, 90, 65, + 71, 6, 11, 32, 6, 42, 76, 158, 152, 2, 77, 243, 178, 1, 83, 2, 143, 240, + 6, 65, 10, 40, 4, 79, 83, 69, 32, 215, 253, 6, 69, 8, 26, 67, 46, 78, 35, + 87, 2, 11, 79, 2, 157, 157, 7, 3, 78, 84, 65, 2, 161, 162, 7, 3, 69, 85, + 84, 4, 36, 2, 73, 71, 21, 3, 82, 73, 78, 2, 191, 130, 5, 71, 2, 171, 130, + 5, 75, 72, 56, 7, 79, 84, 65, 84, 73, 79, 78, 225, 22, 2, 85, 66, 66, 60, + 10, 32, 77, 79, 68, 73, 70, 73, 69, 82, 45, 155, 1, 45, 30, 82, 49, 154, + 169, 8, 50, 2, 51, 2, 52, 2, 53, 2, 54, 2, 55, 2, 56, 3, 57, 14, 150, + 169, 8, 48, 2, 49, 2, 50, 2, 51, 2, 52, 2, 53, 3, 54, 36, 104, 11, 70, + 76, 79, 79, 82, 80, 76, 65, 78, 69, 32, 133, 2, 10, 87, 65, 76, 76, 80, + 76, 65, 78, 69, 32, 18, 100, 4, 68, 79, 85, 66, 0, 4, 83, 73, 78, 71, 21, + 11, 65, 76, 84, 69, 82, 78, 65, 84, 73, 78, 71, 6, 17, 2, 76, 69, 7, 45, + 9, 32, 72, 73, 84, 84, 73, 78, 71, 32, 4, 32, 2, 67, 69, 33, 2, 70, 76, + 2, 11, 73, 2, 147, 213, 7, 76, 2, 155, 237, 7, 79, 18, 88, 8, 65, 76, 84, + 69, 82, 78, 65, 84, 44, 4, 68, 79, 85, 66, 1, 4, 83, 73, 78, 71, 6, 72, + 4, 73, 78, 71, 32, 191, 164, 8, 69, 6, 17, 2, 76, 69, 7, 11, 32, 4, 11, + 72, 4, 11, 73, 4, 33, 6, 84, 84, 73, 78, 71, 32, 4, 44, 2, 67, 72, 21, 5, + 70, 82, 79, 78, 84, 2, 135, 220, 4, 69, 2, 253, 158, 6, 2, 32, 87, 30, + 172, 1, 8, 72, 79, 85, 76, 68, 69, 82, 32, 196, 1, 7, 81, 85, 69, 69, 90, + 69, 32, 240, 1, 7, 85, 82, 70, 65, 67, 69, 32, 240, 10, 5, 84, 82, 73, + 75, 69, 243, 221, 4, 69, 6, 100, 4, 72, 73, 80, 32, 173, 232, 3, 15, 84, + 73, 76, 84, 73, 78, 71, 32, 70, 82, 79, 77, 32, 87, 65, 4, 48, 4, 80, 79, + 83, 73, 181, 135, 7, 2, 83, 80, 2, 11, 84, 2, 177, 242, 4, 2, 73, 79, 12, + 48, 6, 70, 76, 73, 67, 75, 32, 18, 76, 35, 83, 2, 211, 16, 65, 4, 129, 1, + 4, 65, 82, 71, 69, 6, 34, 69, 65, 4, 77, 65, 76, 76, 2, 17, 2, 81, 85, 2, + 21, 3, 69, 78, 84, 2, 207, 149, 7, 73, 4, 11, 32, 4, 214, 11, 77, 187, 4, + 83, 4, 22, 83, 135, 11, 66, 2, 201, 204, 1, 4, 89, 77, 66, 79, 82, 58, + 69, 218, 2, 79, 137, 8, 6, 82, 65, 86, 69, 76, 45, 20, 76, 3, 69, 84, 72, + 185, 1, 11, 78, 83, 69, 32, 67, 72, 69, 69, 75, 83, 32, 15, 11, 32, 12, + 56, 3, 79, 78, 32, 86, 77, 177, 5, 4, 66, 73, 84, 69, 8, 56, 4, 76, 73, + 80, 83, 1, 6, 84, 79, 78, 71, 85, 69, 5, 11, 32, 2, 11, 77, 2, 245, 180, + 3, 2, 79, 86, 6, 50, 77, 252, 162, 4, 2, 72, 73, 131, 222, 2, 76, 2, 157, + 149, 3, 2, 73, 68, 28, 76, 5, 78, 71, 85, 69, 32, 196, 4, 4, 82, 83, 79, + 45, 129, 2, 2, 85, 67, 16, 192, 2, 7, 67, 69, 78, 84, 82, 69, 32, 52, 14, + 73, 78, 83, 73, 68, 69, 32, 77, 79, 85, 84, 72, 32, 82, 36, 4, 84, 73, + 80, 32, 88, 7, 76, 73, 67, 75, 73, 78, 71, 128, 244, 6, 14, 83, 84, 73, + 67, 75, 73, 78, 71, 32, 79, 85, 84, 32, 70, 133, 159, 1, 17, 77, 79, 86, + 69, 83, 32, 65, 71, 65, 73, 78, 83, 84, 32, 67, 72, 69, 4, 214, 1, 73, + 193, 166, 3, 5, 83, 84, 73, 67, 75, 2, 225, 183, 3, 4, 69, 76, 65, 88, 4, + 84, 7, 66, 69, 84, 87, 69, 69, 78, 41, 10, 84, 79, 85, 67, 72, 73, 78, + 71, 32, 73, 2, 11, 32, 2, 189, 246, 4, 2, 76, 73, 2, 237, 167, 3, 5, 78, + 83, 73, 68, 69, 6, 120, 10, 87, 65, 76, 76, 80, 76, 65, 78, 69, 32, 169, + 186, 3, 14, 70, 76, 79, 79, 82, 80, 76, 65, 78, 69, 32, 84, 87, 73, 4, + 108, 8, 67, 85, 82, 86, 69, 68, 32, 66, 241, 200, 1, 13, 83, 84, 82, 65, + 73, 71, 72, 84, 32, 83, 84, 82, 69, 2, 139, 134, 7, 69, 6, 11, 72, 6, 11, + 32, 6, 30, 66, 34, 77, 187, 4, 83, 2, 157, 194, 6, 3, 69, 84, 87, 2, 149, + 2, 3, 85, 76, 84, 34, 100, 11, 70, 76, 79, 79, 82, 80, 76, 65, 78, 69, + 32, 29, 10, 87, 65, 76, 76, 80, 76, 65, 78, 69, 32, 14, 178, 1, 82, 151, + 2, 83, 20, 72, 11, 65, 82, 77, 32, 83, 80, 73, 82, 65, 76, 32, 78, 82, + 151, 2, 83, 6, 30, 84, 134, 2, 68, 43, 83, 2, 11, 82, 2, 11, 73, 2, 183, + 239, 6, 80, 12, 41, 8, 79, 84, 65, 84, 73, 79, 78, 45, 12, 52, 5, 70, 76, + 79, 79, 82, 1, 4, 87, 65, 76, 76, 6, 33, 6, 80, 76, 65, 78, 69, 32, 6, + 26, 65, 54, 68, 43, 83, 2, 29, 5, 76, 84, 69, 82, 78, 2, 247, 180, 3, 65, + 2, 17, 2, 79, 85, 2, 183, 237, 6, 66, 2, 139, 237, 6, 73, 2, 11, 72, 2, + 247, 178, 3, 65, 2, 11, 73, 2, 243, 249, 6, 78, 10, 100, 6, 65, 66, 79, + 86, 69, 32, 162, 1, 79, 197, 133, 2, 10, 77, 73, 78, 85, 83, 32, 83, 73, + 77, 73, 4, 60, 7, 71, 82, 69, 65, 84, 69, 82, 1, 4, 76, 69, 83, 83, 2, + 37, 7, 45, 84, 72, 65, 78, 32, 65, 2, 25, 4, 66, 79, 86, 69, 2, 157, 228, + 1, 2, 32, 69, 4, 203, 252, 5, 82, 250, 1, 64, 3, 71, 76, 69, 212, 4, 5, + 72, 65, 76, 65, 32, 135, 102, 69, 20, 50, 32, 221, 137, 8, 6, 45, 83, 72, + 73, 70, 84, 16, 138, 1, 67, 0, 9, 71, 82, 65, 80, 72, 73, 67, 32, 67, + 116, 2, 72, 73, 74, 76, 36, 4, 82, 73, 71, 72, 145, 208, 4, 4, 83, 72, + 73, 70, 2, 41, 8, 72, 65, 82, 65, 67, 84, 69, 82, 2, 37, 7, 32, 73, 78, + 84, 82, 79, 68, 2, 11, 85, 2, 143, 203, 7, 67, 2, 25, 4, 71, 72, 45, 82, + 2, 185, 1, 7, 69, 86, 69, 82, 83, 69, 68, 4, 32, 2, 69, 70, 109, 2, 79, + 87, 2, 49, 10, 84, 45, 80, 79, 73, 78, 84, 73, 78, 71, 2, 21, 3, 32, 65, + 78, 2, 17, 2, 71, 76, 2, 31, 69, 2, 17, 2, 45, 57, 2, 11, 32, 2, 11, 81, + 2, 205, 161, 2, 2, 85, 79, 228, 1, 168, 2, 8, 65, 82, 67, 72, 65, 73, 67, + 32, 224, 1, 15, 67, 79, 78, 83, 79, 78, 65, 78, 84, 32, 83, 73, 71, 78, + 32, 114, 76, 188, 8, 5, 83, 73, 71, 78, 32, 144, 1, 11, 86, 79, 87, 69, + 76, 32, 83, 73, 71, 78, 32, 229, 212, 2, 17, 80, 85, 78, 67, 84, 85, 65, + 84, 73, 79, 78, 32, 75, 85, 78, 68, 68, 40, 46, 68, 109, 7, 78, 85, 77, + 66, 69, 82, 32, 18, 25, 4, 73, 71, 73, 84, 18, 11, 32, 18, 146, 150, 6, + 70, 30, 83, 42, 84, 190, 83, 78, 14, 79, 199, 110, 69, 22, 150, 218, 2, + 79, 134, 189, 3, 69, 30, 70, 42, 78, 38, 83, 39, 84, 6, 18, 82, 63, 89, + 4, 56, 6, 65, 75, 65, 65, 82, 65, 245, 254, 7, 2, 69, 80, 2, 241, 254, 7, + 3, 65, 78, 83, 138, 1, 60, 6, 69, 84, 84, 69, 82, 32, 217, 171, 2, 3, 73, + 84, 72, 118, 246, 1, 65, 106, 69, 34, 73, 62, 85, 34, 77, 220, 1, 4, 68, + 65, 78, 84, 58, 79, 28, 8, 83, 65, 78, 89, 65, 75, 65, 32, 50, 70, 2, 72, + 2, 82, 2, 86, 2, 89, 32, 8, 84, 65, 65, 76, 85, 74, 65, 32, 29, 9, 75, + 65, 78, 84, 65, 74, 65, 32, 78, 34, 102, 69, 204, 1, 2, 76, 80, 144, 2, + 5, 77, 66, 65, 32, 66, 14, 65, 2, 73, 2, 85, 175, 216, 4, 89, 4, 230, 3, + 69, 175, 216, 4, 89, 12, 46, 76, 2, 82, 154, 3, 73, 175, 216, 4, 89, 4, + 11, 85, 4, 138, 3, 85, 175, 216, 4, 89, 28, 42, 65, 177, 1, 5, 85, 85, + 82, 68, 72, 22, 32, 2, 72, 65, 203, 218, 4, 89, 20, 41, 8, 65, 80, 82, + 65, 65, 78, 65, 32, 20, 70, 84, 138, 1, 68, 22, 66, 2, 67, 2, 71, 2, 74, + 2, 75, 3, 80, 4, 154, 1, 84, 15, 65, 6, 25, 4, 65, 74, 65, 32, 6, 102, + 76, 2, 78, 3, 83, 4, 86, 79, 175, 216, 4, 89, 8, 26, 68, 22, 71, 3, 74, + 4, 18, 68, 15, 65, 2, 11, 65, 2, 171, 216, 4, 89, 6, 26, 78, 21, 2, 83, + 65, 2, 89, 2, 65, 65, 4, 68, 11, 78, 89, 79, 79, 71, 65, 32, 78, 65, 65, + 75, 163, 215, 4, 89, 2, 185, 246, 7, 4, 83, 73, 75, 89, 8, 66, 65, 150, + 146, 4, 67, 193, 227, 3, 6, 86, 73, 83, 65, 82, 71, 4, 220, 113, 5, 76, + 45, 76, 65, 75, 245, 131, 7, 6, 78, 85, 83, 86, 65, 82, 34, 56, 5, 68, + 73, 71, 65, 32, 62, 71, 82, 75, 155, 2, 65, 12, 58, 71, 48, 4, 75, 79, + 77, 66, 118, 65, 26, 73, 19, 80, 4, 11, 65, 4, 236, 2, 3, 69, 84, 84, 67, + 89, 2, 11, 85, 2, 131, 244, 7, 86, 16, 52, 5, 69, 84, 84, 73, 32, 85, 4, + 79, 77, 66, 85, 6, 26, 65, 26, 73, 19, 80, 2, 213, 1, 2, 69, 68, 2, 203, + 1, 83, 2, 175, 1, 65, 10, 40, 2, 86, 65, 173, 198, 7, 2, 32, 68, 9, 29, + 5, 32, 72, 65, 65, 32, 6, 62, 65, 0, 6, 68, 73, 71, 65, 32, 65, 85, 3, + 71, 65, 89, 2, 17, 2, 69, 76, 2, 11, 65, 2, 17, 2, 45, 80, 2, 11, 73, 2, + 183, 209, 7, 76, 2, 193, 202, 5, 5, 65, 78, 85, 75, 73, 12, 84, 2, 32, + 80, 206, 2, 45, 137, 223, 5, 10, 84, 69, 69, 78, 32, 80, 79, 73, 78, 84, + 8, 140, 1, 23, 69, 84, 65, 76, 76, 69, 68, 32, 66, 76, 65, 67, 75, 32, + 65, 78, 68, 32, 87, 72, 73, 84, 69, 49, 7, 79, 73, 78, 84, 69, 68, 32, 2, + 25, 4, 32, 70, 76, 79, 2, 207, 172, 6, 82, 6, 78, 80, 150, 221, 5, 66, + 217, 129, 1, 9, 83, 84, 65, 82, 32, 87, 73, 84, 72, 2, 21, 3, 73, 78, 87, + 2, 149, 221, 5, 4, 72, 69, 69, 76, 2, 179, 194, 3, 80, 12, 46, 73, 102, + 85, 213, 215, 6, 3, 65, 84, 69, 4, 56, 8, 32, 65, 78, 68, 32, 83, 75, 73, + 163, 182, 7, 69, 2, 17, 2, 32, 66, 2, 175, 158, 7, 79, 6, 32, 2, 76, 76, + 143, 235, 7, 78, 5, 11, 32, 2, 49, 10, 65, 78, 68, 32, 67, 82, 79, 83, + 83, 66, 2, 11, 79, 2, 247, 217, 6, 78, 42, 46, 65, 198, 4, 69, 210, 1, + 73, 155, 1, 79, 14, 64, 5, 78, 84, 69, 68, 32, 253, 219, 5, 5, 86, 79, + 78, 73, 67, 12, 148, 1, 12, 69, 81, 85, 65, 76, 32, 84, 79, 32, 79, 82, + 32, 229, 1, 19, 78, 79, 82, 84, 72, 32, 65, 82, 82, 79, 87, 32, 87, 73, + 84, 72, 32, 72, 79, 8, 60, 7, 71, 82, 69, 65, 84, 69, 82, 1, 4, 76, 69, + 83, 83, 4, 29, 5, 45, 84, 72, 65, 78, 5, 11, 32, 2, 25, 4, 87, 73, 84, + 72, 2, 25, 4, 32, 68, 79, 84, 2, 17, 2, 32, 73, 2, 11, 78, 2, 11, 83, 2, + 243, 220, 5, 73, 4, 24, 2, 79, 75, 43, 82, 2, 17, 2, 69, 68, 2, 135, 155, + 5, 32, 2, 29, 5, 73, 90, 79, 78, 84, 2, 11, 65, 2, 203, 187, 5, 76, 12, + 80, 2, 69, 80, 180, 214, 7, 9, 85, 84, 72, 32, 79, 82, 32, 83, 80, 203, + 17, 68, 8, 40, 4, 73, 78, 71, 32, 191, 170, 7, 89, 6, 152, 187, 4, 8, 65, + 67, 67, 79, 77, 77, 79, 68, 190, 153, 2, 83, 255, 85, 70, 6, 76, 9, 67, + 69, 32, 79, 70, 32, 80, 73, 90, 21, 6, 71, 72, 84, 76, 89, 32, 2, 247, + 227, 7, 90, 4, 196, 162, 6, 2, 70, 82, 145, 16, 3, 83, 77, 73, 10, 18, + 80, 75, 84, 6, 140, 186, 4, 9, 73, 78, 71, 32, 76, 65, 82, 71, 69, 199, + 171, 3, 69, 4, 26, 32, 243, 228, 7, 72, 2, 11, 77, 2, 193, 203, 6, 3, 65, + 67, 72, 148, 1, 34, 65, 210, 12, 73, 159, 8, 79, 114, 32, 2, 76, 76, 227, + 212, 6, 83, 112, 30, 32, 193, 11, 2, 69, 82, 108, 178, 2, 65, 44, 3, 66, + 76, 85, 0, 5, 79, 82, 65, 78, 71, 20, 2, 67, 79, 158, 1, 68, 22, 69, 140, + 2, 11, 73, 68, 69, 79, 71, 82, 65, 80, 72, 73, 67, 28, 2, 76, 69, 34, 82, + 218, 3, 83, 22, 84, 36, 4, 86, 69, 69, 32, 208, 238, 1, 3, 71, 82, 69, + 34, 72, 138, 4, 80, 154, 79, 78, 202, 203, 2, 70, 83, 81, 6, 226, 167, 4, + 77, 218, 44, 73, 187, 124, 83, 2, 151, 151, 6, 69, 12, 68, 7, 78, 84, 65, + 73, 78, 83, 32, 218, 243, 1, 77, 231, 156, 5, 76, 6, 36, 4, 65, 83, 32, + 77, 175, 1, 87, 2, 11, 69, 2, 11, 77, 2, 251, 161, 7, 66, 2, 235, 243, 1, + 79, 12, 84, 9, 76, 69, 77, 69, 78, 84, 32, 79, 70, 178, 243, 1, 81, 42, + 88, 215, 194, 2, 77, 7, 17, 2, 32, 87, 4, 25, 4, 73, 84, 72, 32, 4, 26, + 86, 223, 196, 4, 79, 2, 181, 192, 5, 21, 69, 82, 84, 73, 67, 65, 76, 32, + 66, 65, 82, 32, 65, 84, 32, 69, 78, 68, 32, 79, 70, 2, 129, 146, 5, 2, + 32, 67, 8, 130, 1, 70, 255, 245, 1, 83, 40, 96, 3, 73, 71, 72, 64, 13, + 79, 77, 65, 78, 32, 78, 85, 77, 69, 82, 65, 76, 32, 155, 201, 5, 69, 6, + 17, 2, 84, 32, 6, 170, 255, 3, 67, 134, 2, 80, 191, 2, 84, 32, 62, 69, + 50, 70, 62, 79, 46, 84, 238, 236, 5, 83, 231, 83, 78, 4, 26, 76, 171, + 176, 7, 73, 2, 255, 237, 5, 69, 8, 26, 73, 251, 225, 6, 79, 6, 154, 26, + 86, 175, 214, 5, 70, 6, 11, 78, 6, 11, 69, 7, 203, 177, 2, 32, 8, 42, 87, + 134, 237, 5, 72, 239, 156, 1, 69, 4, 26, 69, 171, 217, 7, 79, 2, 227, + 220, 6, 76, 2, 183, 163, 4, 69, 4, 178, 235, 3, 87, 211, 215, 1, 73, 2, + 11, 87, 2, 21, 3, 73, 84, 72, 2, 11, 32, 2, 211, 143, 4, 85, 4, 29, 5, + 32, 84, 72, 65, 78, 5, 11, 32, 2, 11, 79, 2, 223, 176, 1, 82, 32, 34, 76, + 161, 207, 6, 2, 82, 75, 30, 40, 4, 73, 78, 71, 32, 255, 214, 7, 69, 28, + 112, 14, 67, 65, 84, 32, 70, 65, 67, 69, 32, 87, 73, 84, 72, 32, 65, 10, + 70, 65, 67, 69, 32, 87, 73, 84, 72, 32, 4, 30, 79, 157, 1, 2, 72, 69, 2, + 213, 231, 2, 3, 80, 69, 78, 24, 86, 72, 104, 10, 79, 80, 69, 78, 32, 77, + 79, 85, 84, 72, 178, 2, 83, 159, 205, 2, 84, 6, 34, 69, 50, 79, 207, 177, + 7, 65, 2, 189, 2, 8, 65, 82, 84, 45, 83, 72, 65, 80, 2, 135, 166, 4, 82, + 9, 29, 5, 32, 65, 78, 68, 32, 6, 26, 67, 58, 83, 63, 84, 2, 17, 2, 79, + 76, 2, 253, 174, 3, 4, 68, 32, 83, 87, 2, 11, 77, 2, 11, 73, 2, 11, 76, + 2, 117, 3, 73, 78, 71, 2, 37, 7, 73, 71, 72, 84, 76, 89, 45, 2, 11, 67, + 2, 21, 3, 76, 79, 83, 2, 17, 2, 69, 68, 2, 149, 190, 6, 3, 32, 69, 89, 8, + 64, 11, 77, 73, 76, 73, 78, 71, 32, 69, 89, 69, 83, 175, 1, 85, 7, 29, 5, + 32, 65, 78, 68, 32, 4, 52, 4, 72, 65, 78, 68, 57, 5, 84, 72, 82, 69, 69, + 2, 169, 226, 2, 9, 32, 67, 79, 86, 69, 82, 73, 78, 71, 2, 225, 163, 4, 2, + 32, 72, 2, 17, 2, 78, 71, 2, 241, 187, 6, 4, 76, 65, 83, 83, 2, 195, 183, + 4, 75, 16, 42, 65, 32, 2, 69, 69, 21, 2, 79, 87, 4, 210, 197, 6, 73, 203, + 114, 75, 2, 199, 198, 6, 90, 10, 100, 7, 32, 67, 65, 80, 80, 69, 68, 28, + 3, 77, 65, 78, 212, 203, 2, 3, 66, 79, 65, 195, 144, 1, 70, 2, 233, 135, + 4, 2, 32, 77, 5, 49, 10, 32, 87, 73, 84, 72, 79, 85, 84, 32, 83, 2, 247, + 178, 6, 78, 151, 3, 162, 2, 67, 48, 2, 70, 84, 228, 1, 6, 71, 68, 73, 65, + 78, 32, 244, 10, 3, 76, 73, 68, 140, 2, 12, 79, 78, 32, 87, 73, 84, 72, + 32, 82, 73, 71, 72, 20, 11, 82, 65, 32, 83, 79, 77, 80, 69, 78, 71, 32, + 238, 2, 85, 172, 8, 6, 89, 79, 77, 66, 79, 32, 162, 169, 6, 77, 234, 134, + 1, 72, 3, 83, 4, 128, 214, 2, 3, 67, 69, 82, 247, 182, 4, 75, 10, 70, 32, + 124, 9, 87, 65, 82, 69, 45, 70, 85, 78, 67, 155, 196, 5, 66, 6, 58, 72, + 44, 6, 73, 67, 69, 32, 67, 82, 231, 133, 6, 83, 2, 11, 89, 2, 11, 80, 2, + 135, 248, 5, 72, 2, 171, 143, 6, 69, 2, 11, 84, 2, 251, 211, 5, 73, 84, + 248, 1, 10, 67, 79, 77, 66, 73, 78, 73, 78, 71, 32, 168, 2, 13, 73, 78, + 68, 69, 80, 69, 78, 68, 69, 78, 84, 32, 83, 20, 7, 76, 69, 84, 84, 69, + 82, 32, 188, 3, 7, 78, 85, 77, 66, 69, 82, 32, 113, 12, 80, 85, 78, 67, + 84, 85, 65, 84, 73, 79, 78, 32, 22, 140, 1, 3, 72, 79, 79, 20, 4, 76, 79, + 78, 71, 50, 83, 58, 84, 242, 213, 3, 68, 216, 199, 1, 4, 82, 69, 83, 72, + 249, 13, 4, 67, 85, 82, 86, 4, 199, 172, 5, 75, 2, 25, 4, 32, 72, 79, 79, + 2, 147, 158, 5, 75, 2, 21, 3, 84, 82, 79, 2, 11, 75, 2, 219, 157, 5, 69, + 4, 189, 208, 1, 2, 87, 79, 2, 211, 196, 6, 72, 42, 190, 1, 65, 50, 71, + 34, 76, 56, 5, 82, 69, 83, 72, 45, 2, 90, 34, 83, 66, 89, 154, 193, 1, + 72, 234, 5, 75, 130, 76, 66, 2, 70, 190, 173, 4, 78, 254, 1, 84, 2, 87, + 202, 103, 80, 171, 4, 77, 4, 26, 76, 231, 194, 6, 89, 2, 215, 200, 1, 69, + 2, 11, 73, 2, 167, 225, 2, 77, 4, 26, 65, 183, 220, 5, 69, 2, 189, 194, + 1, 2, 77, 69, 2, 11, 65, 2, 235, 193, 6, 89, 6, 26, 65, 191, 193, 6, 72, + 4, 178, 185, 1, 77, 187, 218, 5, 68, 2, 195, 193, 1, 79, 8, 18, 79, 59, + 84, 4, 11, 78, 4, 11, 69, 5, 11, 32, 2, 227, 151, 2, 72, 4, 230, 213, 5, + 87, 187, 154, 1, 69, 10, 66, 67, 0, 6, 72, 65, 76, 70, 32, 67, 53, 4, 84, + 87, 79, 32, 2, 21, 3, 73, 82, 67, 2, 201, 193, 4, 2, 76, 69, 6, 100, 13, + 86, 69, 82, 84, 73, 67, 65, 76, 32, 66, 65, 82, 83, 13, 8, 67, 73, 82, + 67, 76, 69, 83, 32, 5, 11, 32, 2, 153, 240, 5, 4, 87, 73, 84, 72, 8, 30, + 32, 189, 1, 2, 85, 83, 4, 93, 21, 81, 85, 73, 76, 84, 32, 83, 81, 85, 65, + 82, 69, 32, 79, 82, 78, 65, 77, 69, 78, 84, 5, 11, 32, 2, 11, 73, 2, 17, + 2, 78, 32, 2, 11, 66, 2, 173, 155, 6, 4, 76, 65, 67, 75, 5, 173, 162, 4, + 7, 32, 87, 73, 84, 72, 32, 79, 2, 251, 227, 3, 84, 70, 52, 7, 76, 69, 84, + 84, 69, 82, 32, 207, 204, 5, 68, 50, 190, 1, 69, 32, 2, 77, 65, 30, 78, + 38, 66, 2, 67, 2, 68, 2, 71, 2, 72, 2, 74, 2, 75, 2, 76, 2, 80, 2, 82, 2, + 83, 2, 84, 2, 86, 2, 89, 186, 183, 7, 65, 2, 73, 2, 79, 3, 85, 4, 150, + 184, 7, 69, 147, 1, 72, 4, 134, 185, 7, 69, 3, 72, 6, 34, 71, 2, 89, 187, + 183, 7, 65, 2, 183, 183, 7, 65, 54, 104, 3, 84, 72, 32, 197, 233, 5, 17, + 78, 68, 32, 82, 69, 67, 79, 82, 68, 73, 78, 71, 32, 67, 79, 80, 89, 52, + 60, 5, 69, 65, 83, 84, 32, 237, 2, 5, 87, 69, 83, 84, 32, 28, 96, 5, 65, + 82, 82, 79, 87, 162, 4, 80, 130, 1, 84, 246, 160, 4, 66, 38, 68, 18, 83, + 203, 43, 87, 11, 11, 32, 8, 52, 2, 65, 78, 38, 67, 120, 2, 84, 79, 139, + 2, 87, 2, 237, 2, 5, 68, 32, 83, 79, 85, 2, 37, 7, 82, 79, 83, 83, 73, + 78, 71, 2, 17, 2, 32, 78, 2, 17, 2, 79, 82, 2, 221, 209, 4, 5, 84, 72, + 32, 69, 65, 2, 17, 2, 32, 67, 2, 239, 219, 3, 79, 24, 96, 5, 65, 82, 82, + 79, 87, 182, 1, 80, 130, 1, 84, 246, 160, 4, 66, 38, 68, 18, 83, 203, 43, + 87, 7, 11, 32, 4, 36, 5, 65, 78, 68, 32, 78, 75, 87, 2, 17, 2, 79, 82, 2, + 21, 3, 84, 72, 32, 2, 201, 207, 4, 2, 87, 69, 2, 21, 3, 73, 84, 72, 2, + 11, 32, 2, 183, 225, 5, 72, 6, 41, 8, 79, 73, 78, 84, 73, 78, 71, 32, 6, + 42, 86, 154, 253, 3, 76, 215, 137, 2, 66, 2, 17, 2, 73, 78, 2, 239, 252, + 3, 69, 4, 89, 20, 82, 73, 65, 78, 71, 76, 69, 45, 72, 69, 65, 68, 69, 68, + 32, 65, 82, 82, 79, 87, 5, 11, 32, 2, 147, 214, 4, 84, 166, 1, 212, 3, + 23, 67, 76, 85, 83, 84, 69, 82, 45, 73, 78, 73, 84, 73, 65, 76, 32, 76, + 69, 84, 84, 69, 82, 32, 40, 21, 70, 73, 78, 65, 76, 32, 67, 79, 78, 83, + 79, 78, 65, 78, 84, 32, 83, 73, 71, 78, 32, 114, 71, 32, 27, 72, 69, 65, + 68, 32, 77, 65, 82, 75, 32, 87, 73, 84, 72, 32, 77, 79, 79, 78, 32, 65, + 78, 68, 32, 83, 85, 78, 104, 7, 76, 69, 84, 84, 69, 82, 32, 180, 1, 5, + 77, 65, 82, 75, 32, 54, 83, 100, 8, 84, 69, 82, 77, 73, 78, 65, 76, 41, + 6, 86, 79, 87, 69, 76, 32, 8, 246, 228, 6, 83, 254, 68, 76, 3, 82, 24, + 162, 184, 3, 83, 206, 251, 1, 78, 222, 245, 1, 45, 186, 2, 66, 2, 68, 2, + 71, 2, 75, 2, 76, 2, 77, 3, 82, 2, 157, 166, 6, 3, 69, 77, 73, 7, 29, 5, + 32, 65, 78, 68, 32, 4, 50, 70, 1, 8, 84, 82, 73, 80, 76, 69, 32, 70, 2, + 187, 158, 5, 76, 82, 234, 174, 2, 68, 206, 178, 4, 75, 38, 78, 46, 83, + 38, 84, 46, 66, 2, 67, 2, 71, 2, 74, 2, 80, 2, 90, 254, 68, 45, 2, 72, 2, + 76, 2, 77, 2, 82, 2, 86, 2, 89, 187, 2, 65, 8, 158, 153, 3, 80, 214, 200, + 3, 68, 58, 83, 63, 84, 10, 40, 4, 73, 71, 78, 32, 211, 229, 6, 85, 8, + 146, 246, 4, 74, 158, 2, 86, 122, 85, 231, 233, 1, 65, 4, 233, 247, 1, 5, + 32, 77, 65, 82, 75, 22, 44, 5, 83, 73, 71, 78, 32, 251, 228, 6, 76, 20, + 88, 7, 86, 79, 67, 65, 76, 73, 67, 226, 229, 6, 65, 26, 79, 2, 85, 150, + 64, 69, 3, 73, 4, 11, 32, 4, 254, 165, 7, 76, 3, 82, 61, 166, 1, 65, 142, + 1, 69, 136, 5, 13, 72, 69, 82, 73, 67, 65, 76, 32, 65, 78, 71, 76, 69, + 82, 73, 220, 1, 12, 76, 65, 83, 72, 73, 78, 71, 32, 83, 87, 69, 65, 23, + 79, 13, 60, 4, 71, 72, 69, 84, 20, 3, 82, 75, 76, 151, 141, 7, 67, 2, + 163, 144, 7, 84, 6, 26, 73, 239, 159, 5, 69, 2, 165, 156, 6, 2, 78, 71, + 18, 52, 2, 65, 75, 250, 3, 69, 69, 4, 83, 77, 73, 76, 12, 70, 45, 64, 2, + 69, 82, 173, 2, 8, 73, 78, 71, 32, 72, 69, 65, 68, 2, 221, 139, 5, 11, + 78, 79, 45, 69, 86, 73, 76, 32, 77, 79, 78, 9, 33, 6, 32, 87, 73, 84, 72, + 32, 6, 26, 67, 78, 79, 75, 84, 2, 33, 6, 65, 78, 67, 69, 76, 76, 2, 245, + 240, 6, 5, 65, 84, 73, 79, 78, 2, 41, 8, 78, 69, 32, 83, 79, 85, 78, 68, + 2, 133, 184, 5, 2, 32, 87, 2, 25, 4, 72, 82, 69, 69, 2, 157, 140, 6, 10, + 32, 83, 79, 85, 78, 68, 32, 87, 65, 86, 2, 11, 32, 2, 245, 218, 5, 9, 73, + 78, 32, 83, 73, 76, 72, 79, 85, 4, 34, 68, 241, 232, 2, 2, 67, 72, 2, 11, + 66, 2, 255, 138, 6, 79, 2, 211, 151, 6, 79, 7, 45, 9, 32, 79, 80, 69, 78, + 73, 78, 71, 32, 4, 138, 243, 6, 76, 227, 42, 85, 10, 44, 3, 68, 69, 82, + 41, 4, 82, 65, 76, 32, 5, 17, 2, 32, 87, 2, 239, 226, 5, 69, 6, 80, 8, + 67, 65, 76, 69, 78, 68, 65, 82, 0, 4, 78, 79, 84, 69, 29, 2, 83, 72, 2, + 137, 214, 6, 2, 32, 80, 2, 223, 151, 5, 69, 2, 235, 136, 6, 84, 10, 90, + 79, 60, 7, 85, 84, 73, 78, 71, 32, 87, 128, 228, 2, 3, 82, 84, 83, 223, + 130, 3, 78, 4, 144, 84, 7, 76, 32, 79, 70, 32, 84, 72, 251, 198, 6, 78, + 2, 11, 72, 2, 159, 249, 5, 65, 206, 5, 26, 65, 255, 211, 6, 73, 204, 5, + 28, 2, 82, 69, 175, 66, 84, 202, 5, 30, 32, 129, 44, 2, 68, 32, 218, 3, + 246, 1, 65, 116, 2, 86, 32, 58, 66, 158, 1, 67, 170, 1, 68, 102, 69, 194, + 2, 70, 74, 71, 222, 1, 72, 214, 2, 73, 94, 75, 206, 4, 76, 102, 77, 210, + 5, 78, 94, 79, 178, 1, 80, 222, 3, 82, 154, 3, 83, 186, 1, 84, 74, 87, + 218, 6, 89, 175, 158, 6, 85, 14, 114, 32, 152, 71, 2, 78, 80, 236, 142, + 2, 3, 82, 85, 72, 238, 51, 65, 240, 43, 2, 80, 65, 250, 224, 3, 77, 3, + 85, 2, 21, 3, 79, 86, 69, 2, 11, 82, 2, 219, 133, 7, 32, 14, 98, 65, 36, + 4, 85, 83, 83, 89, 178, 136, 3, 73, 212, 64, 2, 79, 82, 202, 39, 69, 207, + 164, 3, 81, 4, 32, 2, 65, 82, 155, 149, 7, 82, 2, 175, 136, 3, 69, 22, + 98, 65, 30, 79, 230, 18, 77, 204, 128, 7, 7, 32, 79, 86, 69, 82, 32, 75, + 74, 85, 14, 67, 3, 68, 4, 158, 148, 7, 76, 3, 80, 5, 17, 2, 82, 80, 2, + 247, 181, 2, 79, 20, 82, 65, 234, 17, 77, 142, 195, 2, 69, 174, 49, 79, + 234, 140, 4, 66, 2, 74, 3, 76, 5, 207, 20, 65, 18, 66, 69, 22, 82, 236, + 23, 5, 83, 85, 75, 85, 85, 183, 250, 6, 86, 2, 235, 162, 5, 75, 12, 52, + 7, 65, 32, 78, 65, 77, 69, 32, 235, 145, 7, 71, 10, 132, 1, 4, 72, 69, + 73, 83, 20, 5, 84, 65, 73, 83, 89, 224, 20, 3, 77, 69, 73, 240, 182, 2, + 3, 82, 69, 73, 1, 4, 83, 89, 79, 85, 2, 135, 253, 6, 69, 2, 227, 235, 6, + 79, 6, 26, 79, 159, 144, 7, 77, 4, 128, 226, 5, 2, 85, 82, 239, 145, 1, + 79, 24, 102, 65, 46, 73, 188, 12, 5, 85, 82, 65, 77, 85, 178, 139, 3, 72, + 186, 244, 3, 80, 186, 2, 66, 3, 89, 6, 166, 191, 6, 82, 210, 46, 78, 147, + 33, 76, 6, 42, 82, 150, 210, 4, 78, 231, 185, 2, 71, 2, 229, 158, 5, 2, + 85, 68, 30, 130, 1, 65, 22, 69, 54, 79, 62, 85, 226, 202, 1, 80, 196, + 184, 5, 10, 73, 82, 65, 71, 65, 78, 65, 32, 72, 79, 234, 8, 71, 3, 90, 5, + 207, 232, 1, 73, 4, 184, 11, 3, 75, 85, 84, 129, 221, 1, 2, 82, 85, 6, + 26, 79, 175, 140, 7, 78, 4, 194, 231, 6, 82, 235, 36, 78, 6, 54, 73, 160, + 17, 4, 65, 82, 65, 68, 131, 179, 5, 82, 2, 203, 191, 3, 73, 14, 54, 78, + 228, 12, 4, 77, 65, 71, 69, 167, 254, 6, 85, 7, 190, 199, 2, 73, 243, + 175, 4, 84, 58, 230, 1, 65, 64, 2, 89, 85, 20, 3, 73, 82, 79, 78, 77, 90, + 79, 60, 2, 85, 82, 144, 8, 2, 69, 69, 202, 135, 3, 72, 202, 237, 2, 67, + 208, 120, 3, 32, 79, 72, 162, 14, 80, 186, 2, 66, 2, 71, 2, 75, 2, 76, 2, + 84, 2, 86, 3, 87, 9, 18, 73, 23, 82, 2, 143, 245, 6, 82, 4, 22, 79, 143, + 20, 65, 2, 159, 204, 4, 82, 9, 252, 16, 3, 77, 69, 69, 248, 2, 2, 87, 65, + 169, 161, 2, 3, 71, 85, 82, 9, 11, 32, 6, 22, 67, 199, 14, 83, 4, 22, 65, + 179, 6, 85, 2, 209, 185, 4, 2, 80, 73, 4, 18, 79, 23, 82, 2, 251, 231, 6, + 80, 2, 151, 204, 5, 85, 4, 176, 154, 5, 4, 85, 90, 69, 73, 239, 66, 79, + 12, 62, 79, 244, 13, 2, 69, 70, 230, 247, 6, 77, 2, 78, 3, 88, 4, 202, + 209, 5, 90, 143, 180, 1, 71, 82, 162, 1, 32, 70, 65, 122, 66, 22, 69, 54, + 73, 110, 77, 68, 2, 85, 32, 78, 86, 2, 87, 162, 137, 3, 72, 214, 237, 2, + 79, 230, 134, 1, 80, 186, 2, 71, 2, 76, 3, 83, 10, 34, 79, 242, 2, 67, + 139, 8, 83, 6, 198, 10, 86, 207, 232, 6, 72, 13, 54, 73, 44, 2, 78, 83, + 146, 82, 82, 159, 185, 4, 72, 4, 252, 150, 5, 2, 75, 85, 175, 199, 1, 82, + 2, 135, 179, 6, 89, 5, 243, 160, 2, 32, 6, 28, 2, 71, 65, 251, 10, 69, 5, + 191, 178, 6, 84, 8, 42, 75, 20, 2, 82, 73, 207, 129, 7, 76, 2, 211, 221, + 5, 85, 5, 11, 66, 2, 11, 65, 2, 203, 244, 2, 65, 7, 11, 32, 4, 22, 67, + 139, 8, 83, 2, 11, 85, 2, 175, 161, 2, 66, 16, 218, 128, 7, 65, 2, 70, 2, + 71, 2, 76, 2, 77, 2, 83, 2, 86, 3, 87, 5, 11, 32, 2, 11, 77, 2, 191, 189, + 6, 69, 16, 70, 65, 238, 10, 79, 178, 244, 6, 70, 2, 77, 2, 83, 2, 86, 3, + 87, 5, 167, 224, 6, 78, 12, 78, 78, 20, 7, 82, 73, 71, 73, 78, 65, 76, + 170, 171, 2, 79, 255, 210, 4, 86, 2, 207, 217, 6, 83, 6, 21, 3, 32, 79, + 70, 7, 25, 4, 32, 79, 82, 32, 4, 214, 86, 78, 51, 69, 46, 118, 65, 82, + 69, 94, 73, 74, 79, 150, 234, 6, 80, 218, 16, 67, 2, 70, 2, 72, 2, 77, 2, + 82, 2, 83, 2, 86, 3, 87, 9, 38, 65, 221, 220, 3, 3, 32, 65, 77, 4, 236, + 1, 2, 83, 69, 227, 213, 6, 84, 8, 34, 69, 22, 78, 231, 220, 6, 83, 2, + 147, 232, 6, 90, 4, 230, 215, 1, 73, 139, 255, 4, 83, 6, 34, 75, 233, 3, + 3, 65, 83, 85, 4, 166, 238, 2, 85, 235, 140, 4, 79, 6, 34, 73, 22, 78, + 21, 2, 83, 73, 2, 191, 174, 3, 78, 2, 191, 219, 6, 68, 2, 133, 193, 6, 4, + 84, 73, 79, 78, 22, 60, 2, 65, 68, 114, 69, 62, 73, 134, 1, 85, 227, 166, + 6, 79, 7, 21, 3, 32, 79, 86, 4, 25, 4, 69, 82, 32, 83, 5, 17, 2, 32, 83, + 2, 11, 81, 2, 153, 153, 2, 2, 85, 65, 4, 36, 3, 78, 84, 79, 191, 211, 6, + 77, 2, 175, 167, 5, 71, 6, 40, 2, 71, 72, 62, 84, 243, 244, 6, 82, 2, + 181, 205, 3, 10, 84, 32, 79, 80, 69, 78, 32, 66, 79, 88, 2, 189, 234, 2, + 2, 84, 79, 4, 172, 1, 2, 85, 66, 195, 185, 4, 80, 14, 82, 65, 72, 3, 69, + 78, 84, 128, 178, 2, 3, 73, 82, 73, 202, 195, 4, 82, 3, 86, 4, 48, 2, 73, + 75, 225, 162, 2, 4, 78, 84, 73, 73, 2, 243, 232, 2, 85, 4, 198, 245, 6, + 73, 3, 79, 6, 42, 65, 146, 254, 2, 72, 159, 167, 3, 79, 2, 241, 191, 6, + 2, 82, 71, 34, 50, 65, 20, 4, 73, 84, 72, 32, 159, 244, 6, 66, 2, 167, + 168, 3, 84, 30, 222, 1, 66, 40, 3, 68, 73, 65, 0, 5, 79, 82, 84, 72, 79, + 84, 2, 72, 79, 42, 76, 126, 84, 28, 6, 85, 80, 80, 69, 82, 32, 186, 1, + 86, 190, 227, 3, 82, 225, 241, 1, 13, 67, 79, 78, 84, 79, 85, 82, 69, 68, + 32, 79, 85, 84, 2, 209, 231, 3, 5, 79, 84, 84, 79, 77, 2, 165, 129, 4, + 16, 71, 79, 78, 65, 76, 32, 67, 82, 79, 83, 83, 72, 65, 84, 67, 72, 2, + 149, 3, 6, 82, 73, 90, 79, 78, 84, 6, 44, 5, 79, 87, 69, 82, 32, 211, + 229, 3, 69, 4, 44, 3, 76, 69, 70, 1, 4, 82, 73, 71, 72, 2, 189, 1, 3, 84, + 32, 68, 2, 177, 229, 3, 2, 79, 80, 8, 60, 5, 76, 69, 70, 84, 32, 37, 6, + 82, 73, 71, 72, 84, 32, 4, 70, 68, 253, 241, 3, 2, 84, 79, 4, 34, 68, + 205, 253, 3, 2, 84, 79, 2, 141, 228, 3, 7, 73, 65, 71, 79, 78, 65, 76, 2, + 29, 5, 69, 82, 84, 73, 67, 2, 185, 253, 3, 2, 65, 76, 6, 32, 2, 65, 65, + 183, 166, 5, 85, 4, 254, 200, 6, 82, 247, 5, 68, 240, 1, 226, 1, 67, 174, + 9, 68, 34, 70, 88, 3, 82, 73, 83, 142, 1, 72, 66, 75, 106, 76, 166, 1, + 77, 38, 78, 34, 79, 94, 80, 34, 83, 190, 2, 84, 156, 1, 5, 69, 73, 71, + 72, 84, 22, 85, 90, 86, 166, 199, 4, 65, 222, 105, 87, 207, 96, 73, 90, + 128, 1, 21, 74, 75, 32, 85, 78, 73, 70, 73, 69, 68, 32, 73, 68, 69, 79, + 71, 82, 65, 80, 72, 45, 134, 216, 5, 79, 219, 146, 1, 76, 86, 68, 2, 52, + 69, 82, 53, 206, 2, 54, 150, 2, 55, 166, 1, 56, 95, 57, 10, 50, 48, 234, + 4, 65, 154, 190, 5, 56, 207, 96, 50, 4, 222, 233, 6, 48, 3, 57, 30, 150, + 1, 50, 42, 51, 38, 52, 48, 2, 53, 66, 0, 2, 68, 69, 22, 57, 164, 4, 2, + 56, 70, 162, 143, 3, 66, 248, 172, 2, 2, 70, 56, 205, 96, 2, 49, 56, 6, + 214, 4, 55, 194, 157, 6, 49, 3, 52, 4, 150, 148, 3, 70, 143, 173, 2, 67, + 4, 26, 48, 159, 148, 3, 51, 2, 195, 231, 6, 56, 2, 175, 231, 6, 54, 4, + 242, 147, 3, 50, 243, 208, 3, 49, 24, 86, 50, 46, 51, 50, 53, 34, 54, 16, + 2, 55, 48, 28, 2, 70, 49, 129, 2, 2, 69, 56, 6, 70, 57, 238, 145, 3, 53, + 203, 153, 2, 52, 4, 26, 53, 199, 146, 3, 48, 2, 215, 229, 6, 53, 4, 202, + 2, 66, 211, 143, 3, 57, 2, 171, 2, 50, 4, 146, 229, 6, 56, 3, 57, 2, 247, + 228, 6, 52, 12, 74, 53, 38, 57, 12, 2, 49, 50, 20, 2, 68, 52, 157, 225, + 6, 2, 65, 55, 4, 170, 144, 3, 51, 227, 210, 2, 49, 2, 11, 56, 2, 231, + 227, 6, 49, 2, 211, 227, 6, 50, 6, 50, 57, 20, 2, 68, 55, 209, 143, 3, 2, + 67, 65, 2, 159, 143, 3, 69, 2, 247, 226, 6, 48, 4, 204, 156, 6, 2, 49, + 52, 221, 67, 2, 48, 52, 2, 11, 79, 2, 251, 183, 3, 84, 10, 84, 3, 65, 76, + 76, 104, 4, 79, 85, 82, 32, 240, 5, 3, 73, 86, 69, 179, 238, 4, 82, 2, + 57, 12, 73, 78, 71, 32, 68, 73, 65, 71, 79, 78, 65, 76, 2, 11, 32, 2, 11, + 83, 2, 191, 251, 4, 76, 4, 210, 179, 3, 68, 131, 173, 3, 75, 8, 192, 181, + 3, 2, 73, 45, 158, 242, 2, 68, 210, 56, 67, 3, 86, 8, 56, 8, 65, 84, 65, + 75, 65, 78, 65, 32, 239, 205, 6, 69, 6, 150, 172, 6, 75, 202, 28, 68, + 159, 20, 83, 60, 36, 5, 65, 84, 73, 78, 32, 79, 79, 54, 164, 5, 12, 83, + 77, 65, 76, 76, 32, 76, 69, 84, 84, 69, 82, 227, 112, 67, 6, 178, 178, 3, + 71, 157, 149, 2, 3, 83, 83, 76, 4, 234, 218, 4, 73, 251, 130, 2, 86, 4, + 174, 223, 5, 69, 147, 126, 71, 4, 140, 3, 15, 78, 69, 32, 72, 85, 78, 68, + 82, 69, 68, 32, 84, 87, 69, 78, 147, 218, 6, 75, 4, 158, 2, 80, 187, 215, + 4, 76, 20, 110, 69, 146, 1, 72, 20, 2, 73, 88, 198, 200, 4, 65, 150, 66, + 77, 130, 47, 81, 234, 98, 79, 210, 61, 68, 3, 83, 4, 56, 7, 67, 79, 78, + 68, 32, 83, 67, 21, 3, 86, 69, 78, 2, 247, 137, 5, 82, 2, 29, 5, 32, 80, + 79, 73, 78, 2, 11, 84, 2, 143, 177, 5, 32, 2, 163, 218, 6, 86, 2, 17, 2, + 84, 89, 2, 239, 217, 6, 32, 8, 44, 4, 72, 82, 69, 69, 22, 87, 243, 4, 73, + 2, 163, 147, 6, 32, 4, 68, 13, 69, 78, 84, 89, 45, 84, 87, 79, 32, 80, + 79, 73, 78, 19, 79, 2, 215, 75, 84, 2, 179, 213, 6, 32, 4, 48, 6, 80, 32, + 87, 73, 84, 72, 243, 145, 6, 72, 2, 17, 2, 32, 69, 2, 235, 108, 88, 4, + 202, 145, 6, 79, 151, 70, 83, 2, 201, 183, 5, 6, 32, 66, 76, 65, 67, 75, + 6, 146, 215, 6, 50, 2, 51, 3, 65, 85, 134, 1, 65, 138, 7, 69, 236, 1, 10, + 73, 67, 75, 32, 70, 73, 71, 85, 82, 69, 182, 1, 79, 90, 82, 234, 2, 85, + 130, 200, 6, 83, 3, 88, 38, 92, 6, 70, 70, 32, 79, 70, 32, 106, 77, 80, + 2, 78, 68, 90, 82, 206, 3, 84, 175, 167, 5, 68, 4, 60, 8, 65, 69, 83, 67, + 85, 76, 65, 80, 21, 3, 72, 69, 82, 2, 219, 209, 4, 73, 2, 211, 192, 5, + 77, 2, 21, 3, 80, 69, 68, 2, 17, 2, 32, 69, 2, 173, 210, 1, 4, 78, 86, + 69, 76, 2, 21, 3, 73, 78, 71, 2, 17, 2, 32, 80, 2, 11, 69, 2, 11, 82, 2, + 171, 131, 6, 83, 24, 42, 32, 205, 1, 5, 84, 32, 79, 70, 32, 12, 82, 69, + 54, 79, 240, 224, 1, 8, 65, 78, 68, 32, 67, 82, 69, 83, 131, 229, 1, 87, + 2, 17, 2, 81, 85, 2, 11, 65, 2, 135, 148, 6, 76, 4, 44, 5, 70, 32, 68, + 65, 86, 143, 167, 3, 80, 2, 255, 138, 6, 73, 12, 66, 71, 30, 83, 40, 4, + 80, 82, 79, 84, 142, 66, 72, 155, 102, 84, 2, 89, 4, 85, 65, 82, 68, 4, + 26, 69, 155, 239, 1, 84, 2, 11, 76, 2, 21, 3, 69, 67, 84, 2, 29, 5, 69, + 68, 32, 65, 82, 2, 135, 205, 6, 69, 4, 144, 229, 4, 10, 85, 69, 32, 79, + 70, 32, 76, 73, 66, 69, 187, 154, 1, 73, 8, 92, 2, 65, 77, 112, 9, 78, + 79, 71, 82, 65, 80, 72, 73, 67, 193, 203, 1, 4, 84, 72, 79, 83, 4, 54, + 32, 173, 196, 5, 7, 73, 78, 71, 32, 66, 79, 87, 2, 33, 6, 76, 79, 67, 79, + 77, 79, 2, 135, 197, 1, 84, 2, 137, 130, 4, 2, 32, 70, 11, 11, 32, 8, 60, + 5, 87, 73, 84, 72, 32, 193, 153, 2, 4, 76, 69, 65, 78, 4, 32, 4, 65, 82, + 77, 83, 51, 68, 2, 25, 4, 32, 82, 65, 73, 2, 167, 236, 1, 83, 2, 143, + 181, 5, 82, 4, 44, 4, 67, 75, 32, 67, 21, 3, 80, 87, 65, 2, 139, 196, 5, + 72, 2, 211, 168, 6, 84, 12, 66, 65, 108, 10, 69, 83, 83, 32, 79, 85, 84, + 76, 73, 78, 79, 73, 6, 44, 4, 73, 71, 72, 84, 45, 3, 87, 66, 69, 4, 188, + 130, 3, 2, 32, 82, 243, 176, 2, 78, 2, 147, 61, 82, 2, 17, 2, 69, 68, 2, + 17, 2, 32, 87, 2, 145, 182, 4, 4, 72, 73, 84, 69, 4, 52, 4, 78, 71, 32, + 84, 233, 7, 4, 67, 84, 76, 89, 2, 17, 2, 69, 82, 2, 169, 143, 6, 3, 77, + 73, 78, 6, 100, 8, 68, 73, 79, 32, 77, 73, 67, 82, 20, 9, 70, 70, 69, 68, + 32, 70, 76, 65, 84, 207, 196, 6, 80, 2, 215, 157, 5, 79, 2, 11, 66, 2, + 231, 248, 3, 82, 202, 2, 150, 1, 66, 196, 2, 5, 67, 67, 69, 69, 68, 192, + 3, 8, 77, 77, 65, 84, 73, 79, 78, 32, 70, 78, 132, 15, 3, 80, 69, 82, + 148, 11, 2, 82, 70, 47, 83, 63, 11, 83, 60, 72, 6, 67, 82, 73, 80, 84, + 32, 124, 3, 69, 84, 32, 93, 3, 84, 73, 84, 30, 222, 22, 69, 162, 1, 80, + 150, 208, 2, 77, 202, 1, 76, 26, 82, 222, 237, 1, 70, 30, 83, 42, 84, 62, + 90, 130, 83, 78, 15, 79, 28, 56, 6, 65, 66, 79, 86, 69, 32, 246, 25, 79, + 159, 3, 87, 6, 142, 24, 83, 203, 139, 5, 82, 2, 235, 254, 4, 85, 22, 11, + 83, 23, 11, 32, 20, 128, 1, 6, 65, 66, 79, 86, 69, 32, 156, 1, 7, 66, 85, + 84, 32, 78, 79, 84, 32, 2, 79, 82, 229, 255, 2, 5, 85, 78, 68, 69, 82, + 12, 100, 4, 78, 79, 84, 32, 28, 12, 83, 73, 78, 71, 76, 69, 45, 76, 73, + 78, 69, 32, 218, 24, 65, 39, 69, 4, 242, 24, 65, 167, 1, 69, 4, 250, 24, + 69, 83, 78, 2, 93, 5, 32, 69, 81, 85, 73, 4, 17, 2, 32, 69, 4, 17, 2, 81, + 85, 4, 22, 73, 167, 25, 65, 2, 173, 25, 6, 86, 65, 76, 69, 78, 84, 6, + 202, 246, 2, 66, 228, 196, 1, 4, 87, 73, 84, 72, 147, 139, 1, 84, 161, 1, + 166, 1, 32, 72, 7, 68, 65, 78, 69, 83, 69, 32, 200, 12, 4, 82, 73, 83, + 69, 200, 166, 2, 14, 83, 69, 84, 32, 79, 86, 69, 82, 32, 66, 85, 73, 76, + 68, 255, 240, 2, 70, 4, 50, 87, 197, 146, 5, 6, 66, 69, 72, 73, 78, 68, + 2, 247, 255, 5, 73, 146, 1, 198, 2, 65, 20, 17, 67, 79, 78, 83, 79, 78, + 65, 78, 84, 32, 83, 73, 71, 78, 32, 80, 65, 172, 1, 7, 76, 69, 84, 84, + 69, 82, 32, 188, 3, 18, 80, 85, 78, 67, 84, 85, 65, 84, 73, 79, 78, 32, + 66, 73, 78, 68, 85, 32, 228, 1, 5, 83, 73, 71, 78, 32, 200, 1, 13, 86, + 79, 87, 69, 76, 32, 83, 73, 71, 78, 32, 80, 65, 255, 195, 4, 68, 2, 235, + 211, 2, 86, 10, 68, 2, 77, 73, 40, 2, 78, 89, 33, 7, 83, 65, 78, 71, 65, + 78, 32, 2, 17, 2, 78, 71, 2, 167, 176, 5, 75, 4, 142, 5, 65, 163, 146, 1, + 73, 4, 226, 182, 6, 77, 3, 87, 76, 246, 1, 65, 58, 70, 78, 76, 2, 82, 34, + 83, 202, 230, 2, 69, 246, 215, 1, 78, 246, 175, 1, 66, 2, 75, 254, 68, + 67, 2, 68, 2, 71, 2, 72, 2, 74, 2, 77, 2, 80, 2, 81, 2, 84, 2, 86, 2, 87, + 2, 88, 2, 89, 2, 90, 186, 2, 73, 2, 79, 3, 85, 7, 128, 247, 5, 6, 82, 67, + 72, 65, 73, 67, 135, 64, 69, 6, 44, 5, 73, 78, 65, 76, 32, 163, 182, 6, + 65, 4, 158, 182, 6, 75, 3, 77, 4, 154, 145, 6, 69, 235, 36, 65, 4, 170, + 179, 6, 89, 187, 2, 65, 16, 90, 66, 2, 68, 2, 75, 12, 3, 76, 69, 85, 38, + 67, 34, 80, 189, 177, 6, 3, 83, 85, 82, 2, 11, 65, 2, 137, 94, 5, 32, 83, + 65, 84, 65, 2, 11, 65, 2, 247, 239, 5, 75, 4, 168, 3, 3, 65, 78, 71, 141, + 238, 5, 3, 85, 82, 78, 10, 28, 2, 80, 65, 211, 82, 86, 8, 28, 3, 77, 65, + 65, 23, 78, 2, 143, 178, 6, 69, 6, 18, 71, 71, 89, 4, 38, 76, 177, 236, + 5, 3, 87, 73, 83, 2, 165, 144, 5, 2, 65, 89, 2, 141, 175, 6, 2, 69, 67, + 12, 18, 77, 23, 78, 2, 179, 244, 2, 69, 10, 96, 3, 69, 85, 76, 34, 79, + 22, 89, 140, 220, 1, 3, 71, 72, 85, 157, 152, 2, 4, 65, 69, 76, 65, 2, + 11, 69, 2, 147, 224, 5, 85, 2, 139, 244, 3, 76, 2, 203, 142, 1, 85, 5, + 173, 130, 3, 13, 32, 79, 86, 69, 82, 32, 77, 79, 85, 78, 84, 65, 73, 72, + 54, 83, 166, 195, 4, 72, 241, 64, 4, 86, 73, 76, 76, 68, 56, 6, 67, 82, + 73, 80, 84, 32, 173, 2, 3, 69, 84, 32, 34, 118, 69, 34, 76, 130, 1, 80, + 150, 208, 2, 77, 226, 1, 82, 222, 237, 1, 70, 30, 83, 42, 84, 62, 90, + 130, 83, 78, 15, 79, 4, 226, 66, 81, 235, 192, 5, 73, 6, 96, 18, 65, 84, + 73, 78, 32, 83, 77, 65, 76, 76, 32, 76, 69, 84, 84, 69, 82, 32, 135, 210, + 2, 69, 4, 138, 173, 6, 73, 3, 78, 2, 155, 147, 3, 76, 34, 148, 1, 6, 65, + 66, 79, 86, 69, 32, 96, 7, 66, 69, 83, 73, 68, 69, 32, 162, 1, 79, 158, + 3, 87, 153, 148, 4, 9, 80, 82, 69, 67, 69, 68, 73, 78, 71, 6, 26, 83, + 231, 187, 2, 76, 4, 11, 85, 4, 26, 80, 191, 194, 4, 66, 2, 185, 194, 4, + 2, 69, 82, 4, 108, 23, 65, 78, 68, 32, 74, 79, 73, 78, 69, 68, 32, 66, + 89, 32, 68, 65, 83, 72, 32, 87, 73, 84, 72, 23, 83, 2, 17, 2, 32, 83, 2, + 153, 193, 4, 2, 85, 66, 16, 11, 70, 17, 11, 32, 14, 120, 6, 65, 66, 79, + 86, 69, 32, 132, 1, 4, 87, 73, 84, 72, 181, 166, 5, 11, 79, 82, 32, 69, + 81, 85, 65, 76, 32, 84, 79, 8, 34, 65, 38, 69, 18, 84, 67, 78, 2, 11, 76, + 2, 113, 3, 77, 79, 83, 2, 187, 60, 81, 2, 21, 3, 73, 76, 68, 2, 147, 253, + 2, 69, 2, 17, 2, 32, 78, 2, 11, 79, 2, 11, 84, 2, 11, 32, 2, 11, 69, 2, + 17, 2, 81, 85, 2, 11, 65, 2, 11, 76, 2, 179, 218, 2, 32, 6, 25, 4, 73, + 84, 72, 32, 6, 96, 2, 80, 76, 24, 14, 77, 85, 76, 84, 73, 80, 76, 73, 67, + 65, 84, 73, 79, 78, 231, 212, 5, 68, 2, 11, 85, 2, 11, 83, 2, 169, 254, + 3, 5, 32, 83, 73, 71, 78, 4, 196, 160, 4, 2, 65, 67, 211, 203, 1, 69, 4, + 60, 9, 80, 69, 78, 83, 73, 79, 78, 32, 82, 167, 144, 6, 72, 2, 21, 3, 65, + 73, 76, 2, 247, 151, 5, 87, 8, 26, 65, 98, 73, 35, 85, 4, 44, 5, 83, 72, + 32, 65, 77, 135, 163, 6, 78, 2, 173, 223, 5, 7, 80, 69, 82, 83, 65, 78, + 68, 2, 11, 77, 2, 231, 228, 5, 77, 2, 129, 250, 2, 2, 78, 71, 230, 2, 92, + 11, 76, 79, 84, 73, 32, 78, 65, 71, 82, 73, 32, 226, 5, 77, 182, 15, 78, + 97, 2, 82, 73, 90, 180, 1, 7, 76, 69, 84, 84, 69, 82, 32, 168, 2, 11, 80, + 79, 69, 84, 82, 89, 32, 77, 65, 82, 75, 56, 5, 83, 73, 71, 78, 32, 145, + 1, 11, 86, 79, 87, 69, 76, 32, 83, 73, 71, 78, 32, 64, 174, 1, 68, 46, + 82, 34, 84, 154, 89, 66, 2, 67, 2, 71, 2, 74, 2, 75, 2, 80, 246, 165, 5, + 72, 2, 76, 2, 77, 2, 78, 2, 83, 246, 30, 65, 2, 69, 2, 73, 2, 79, 3, 85, + 8, 226, 89, 68, 246, 165, 5, 72, 247, 30, 79, 4, 170, 255, 5, 82, 247, + 30, 79, 8, 150, 89, 84, 246, 165, 5, 72, 247, 30, 79, 8, 11, 45, 8, 198, + 157, 6, 49, 2, 50, 2, 51, 3, 52, 8, 46, 65, 70, 72, 213, 215, 5, 3, 68, + 86, 73, 4, 64, 10, 76, 84, 69, 82, 78, 65, 84, 69, 32, 72, 203, 215, 5, + 78, 2, 129, 137, 2, 2, 65, 83, 10, 150, 253, 5, 79, 246, 30, 65, 2, 69, + 2, 73, 3, 85, 82, 60, 8, 66, 79, 76, 32, 70, 79, 82, 32, 213, 14, 2, 77, + 69, 80, 238, 2, 66, 48, 2, 67, 65, 118, 68, 222, 1, 69, 130, 2, 70, 56, + 8, 72, 79, 82, 73, 90, 79, 78, 84, 0, 6, 86, 69, 82, 84, 73, 67, 44, 3, + 76, 73, 78, 52, 9, 77, 65, 82, 75, 83, 32, 67, 72, 65, 22, 78, 90, 65, + 68, 3, 82, 69, 67, 32, 5, 71, 82, 79, 85, 80, 0, 4, 85, 78, 73, 84, 22, + 83, 205, 3, 15, 84, 89, 80, 69, 32, 65, 32, 69, 76, 69, 67, 84, 82, 79, + 78, 4, 242, 147, 4, 69, 133, 198, 1, 3, 65, 67, 75, 4, 44, 3, 82, 82, 73, + 237, 182, 1, 2, 78, 67, 2, 33, 6, 65, 71, 69, 32, 82, 69, 2, 11, 84, 2, + 135, 185, 1, 85, 14, 24, 2, 65, 84, 55, 69, 2, 161, 3, 9, 65, 32, 76, 73, + 78, 75, 32, 69, 83, 12, 76, 12, 86, 73, 67, 69, 32, 67, 79, 78, 84, 82, + 79, 76, 157, 8, 2, 76, 69, 8, 11, 32, 8, 222, 174, 1, 70, 154, 250, 2, + 84, 203, 83, 79, 12, 22, 78, 207, 1, 83, 10, 48, 5, 68, 32, 79, 70, 32, + 137, 1, 2, 81, 85, 8, 18, 77, 31, 84, 2, 193, 236, 4, 2, 69, 68, 6, 64, + 11, 82, 65, 78, 83, 77, 73, 83, 83, 73, 79, 78, 159, 108, 69, 5, 143, + 171, 3, 32, 2, 155, 7, 73, 2, 205, 206, 4, 2, 67, 65, 4, 36, 2, 73, 76, + 73, 3, 79, 82, 77, 2, 191, 2, 69, 2, 129, 162, 1, 6, 65, 76, 32, 84, 65, + 66, 2, 11, 69, 2, 17, 2, 32, 70, 2, 223, 178, 1, 69, 2, 191, 219, 4, 80, + 6, 26, 69, 175, 141, 4, 85, 4, 56, 8, 71, 65, 84, 73, 86, 69, 32, 65, + 247, 247, 4, 87, 2, 21, 3, 67, 75, 78, 2, 21, 3, 79, 87, 76, 2, 191, 136, + 1, 69, 2, 11, 79, 2, 17, 2, 82, 68, 2, 191, 247, 2, 32, 18, 176, 1, 7, + 65, 77, 65, 82, 73, 84, 65, 60, 3, 72, 73, 70, 52, 8, 84, 65, 82, 84, 32, + 79, 70, 32, 64, 7, 85, 66, 83, 84, 73, 84, 85, 204, 1, 3, 89, 78, 67, + 255, 206, 5, 80, 2, 25, 4, 78, 32, 83, 79, 2, 11, 85, 2, 219, 209, 5, 82, + 4, 17, 2, 84, 32, 4, 226, 148, 5, 79, 239, 41, 73, 4, 22, 72, 155, 102, + 84, 2, 17, 2, 69, 65, 2, 223, 188, 5, 68, 4, 11, 84, 4, 11, 69, 5, 11, + 32, 2, 25, 4, 70, 79, 82, 77, 2, 17, 2, 32, 84, 2, 251, 237, 5, 87, 2, + 137, 207, 5, 2, 73, 67, 2, 11, 84, 2, 235, 250, 5, 82, 7, 38, 67, 145, + 171, 2, 3, 65, 71, 79, 2, 141, 134, 1, 9, 72, 82, 79, 78, 79, 85, 83, 32, + 73, 180, 1, 36, 3, 65, 67, 32, 163, 215, 4, 78, 178, 1, 150, 3, 65, 52, + 4, 66, 65, 82, 82, 32, 2, 67, 79, 80, 13, 68, 79, 84, 84, 69, 68, 32, 90, + 76, 65, 77, 65, 32, 118, 69, 90, 72, 204, 2, 7, 76, 69, 84, 84, 69, 82, + 32, 236, 9, 9, 79, 66, 76, 73, 81, 85, 69, 32, 76, 28, 4, 80, 84, 72, 65, + 0, 4, 90, 81, 65, 80, 110, 82, 88, 2, 83, 85, 174, 2, 84, 216, 205, 4, 3, + 77, 85, 83, 228, 21, 7, 70, 69, 77, 73, 78, 73, 78, 229, 136, 1, 5, 81, + 85, 83, 72, 83, 2, 11, 66, 2, 197, 158, 5, 5, 66, 82, 69, 86, 73, 2, 11, + 69, 2, 167, 134, 6, 75, 6, 38, 78, 165, 17, 4, 76, 79, 78, 32, 2, 17, 2, + 84, 82, 2, 151, 182, 5, 65, 4, 28, 3, 65, 78, 71, 35, 72, 2, 11, 85, 2, + 255, 227, 4, 76, 2, 11, 79, 2, 185, 184, 3, 5, 82, 73, 90, 79, 78, 6, 60, + 10, 78, 68, 32, 79, 70, 32, 80, 65, 82, 65, 151, 14, 83, 2, 201, 11, 2, + 71, 82, 14, 104, 8, 65, 82, 75, 76, 69, 65, 78, 32, 132, 1, 4, 66, 65, + 83, 65, 65, 7, 79, 82, 73, 90, 79, 78, 84, 6, 60, 5, 65, 83, 84, 69, 82, + 40, 4, 77, 69, 84, 79, 3, 79, 2, 17, 2, 73, 83, 2, 219, 128, 4, 67, 2, + 181, 166, 2, 2, 66, 69, 6, 164, 11, 8, 45, 69, 83, 65, 83, 65, 32, 68, + 159, 223, 3, 32, 2, 197, 178, 5, 2, 65, 76, 92, 154, 2, 68, 102, 72, 32, + 3, 76, 65, 77, 34, 77, 204, 1, 2, 80, 69, 142, 1, 82, 78, 83, 144, 1, 8, + 70, 73, 78, 65, 76, 32, 83, 69, 106, 65, 14, 75, 2, 81, 34, 84, 40, 5, + 71, 65, 77, 65, 76, 40, 4, 89, 85, 68, 72, 146, 75, 66, 166, 130, 4, 90, + 154, 43, 78, 254, 1, 87, 159, 126, 69, 4, 76, 14, 79, 84, 76, 69, 83, 83, + 32, 68, 65, 76, 65, 84, 72, 32, 139, 3, 65, 2, 139, 193, 2, 82, 4, 11, + 69, 5, 159, 254, 5, 84, 2, 11, 65, 2, 255, 253, 5, 68, 24, 60, 9, 65, 76, + 65, 89, 65, 76, 65, 77, 32, 231, 237, 5, 73, 22, 78, 76, 22, 78, 158, + 134, 4, 66, 242, 210, 1, 84, 138, 34, 83, 14, 74, 3, 82, 4, 199, 247, 3, + 76, 8, 182, 84, 78, 234, 166, 5, 71, 3, 89, 9, 33, 6, 82, 83, 73, 65, 78, + 32, 6, 50, 66, 16, 3, 68, 72, 65, 17, 3, 71, 72, 65, 2, 131, 79, 72, 2, + 147, 2, 76, 2, 143, 243, 4, 77, 4, 52, 7, 69, 86, 69, 82, 83, 69, 68, + 211, 150, 4, 73, 2, 251, 182, 4, 32, 14, 142, 1, 69, 40, 7, 79, 71, 68, + 73, 65, 78, 32, 64, 12, 85, 80, 69, 82, 83, 67, 82, 73, 80, 84, 32, 65, + 166, 250, 4, 72, 177, 82, 2, 65, 68, 2, 17, 2, 77, 75, 2, 175, 251, 3, + 65, 6, 42, 90, 32, 2, 75, 72, 131, 227, 5, 70, 2, 195, 206, 4, 72, 2, 11, + 76, 2, 11, 65, 2, 183, 248, 5, 80, 6, 36, 3, 69, 84, 72, 255, 250, 4, 65, + 5, 237, 85, 6, 32, 71, 65, 82, 83, 72, 5, 215, 203, 5, 32, 4, 225, 223, + 3, 2, 73, 78, 6, 21, 3, 72, 65, 32, 6, 42, 68, 186, 223, 3, 66, 223, 155, + 1, 65, 2, 17, 2, 79, 84, 2, 155, 152, 1, 84, 8, 58, 66, 210, 144, 2, 87, + 217, 189, 1, 4, 85, 75, 75, 65, 4, 173, 204, 3, 2, 65, 83, 14, 88, 8, 66, + 76, 73, 78, 69, 65, 82, 32, 113, 10, 80, 82, 65, 76, 73, 78, 69, 65, 82, + 32, 8, 44, 5, 67, 79, 76, 79, 78, 227, 170, 3, 70, 7, 11, 32, 4, 29, 5, + 83, 75, 69, 87, 69, 4, 171, 202, 5, 68, 6, 44, 5, 67, 79, 76, 79, 78, + 243, 169, 3, 70, 5, 185, 194, 5, 7, 32, 83, 75, 69, 87, 69, 68, 8, 62, + 72, 25, 11, 87, 79, 32, 86, 69, 82, 84, 73, 67, 65, 76, 4, 21, 3, 82, 69, + 69, 4, 25, 4, 32, 68, 79, 84, 4, 239, 218, 3, 83, 148, 41, 102, 45, 58, + 65, 166, 106, 69, 254, 45, 72, 174, 46, 73, 254, 72, 79, 182, 20, 82, + 226, 16, 85, 191, 9, 87, 4, 32, 2, 83, 72, 203, 205, 4, 82, 2, 179, 235, + 4, 73, 244, 26, 182, 1, 66, 82, 71, 192, 17, 2, 73, 32, 182, 29, 75, 152, + 5, 9, 76, 76, 89, 32, 77, 65, 82, 75, 32, 34, 77, 226, 37, 78, 156, 13, + 3, 80, 69, 32, 94, 85, 150, 233, 4, 67, 159, 11, 88, 5, 249, 123, 16, 76, + 69, 32, 84, 69, 78, 78, 73, 83, 32, 80, 65, 68, 68, 76, 69, 144, 2, 78, + 32, 224, 11, 5, 65, 76, 79, 71, 32, 253, 2, 6, 66, 65, 78, 87, 65, 32, + 190, 1, 158, 1, 65, 102, 67, 186, 1, 68, 58, 69, 98, 71, 118, 72, 46, 76, + 222, 3, 80, 54, 81, 62, 82, 106, 83, 194, 77, 78, 166, 213, 1, 84, 166, + 118, 70, 159, 177, 1, 86, 6, 42, 80, 170, 180, 2, 77, 147, 169, 1, 83, 2, + 17, 2, 79, 83, 2, 197, 192, 5, 4, 84, 82, 79, 80, 8, 18, 73, 63, 79, 2, + 25, 4, 82, 67, 85, 77, 2, 213, 2, 4, 70, 76, 69, 88, 6, 26, 77, 231, 156, + 5, 76, 4, 11, 77, 4, 228, 216, 4, 7, 69, 82, 67, 73, 65, 76, 32, 211, + 147, 1, 65, 22, 26, 79, 207, 253, 3, 73, 2, 11, 76, 2, 175, 85, 76, 4, + 18, 81, 43, 88, 2, 17, 2, 85, 65, 2, 207, 209, 2, 76, 2, 221, 129, 5, 4, + 67, 76, 65, 77, 4, 11, 82, 4, 18, 65, 55, 69, 2, 11, 86, 2, 11, 69, 2, + 209, 121, 3, 32, 65, 67, 2, 137, 4, 4, 65, 84, 69, 82, 2, 129, 141, 2, 6, + 89, 80, 72, 69, 78, 45, 114, 38, 65, 246, 2, 69, 183, 129, 4, 79, 104, + 25, 4, 84, 73, 78, 32, 104, 34, 67, 33, 4, 83, 77, 65, 76, 52, 29, 5, 65, + 80, 73, 84, 65, 52, 41, 8, 76, 32, 76, 69, 84, 84, 69, 82, 52, 11, 32, + 52, 254, 231, 5, 65, 2, 66, 2, 67, 2, 68, 2, 69, 2, 70, 2, 71, 2, 72, 2, + 73, 2, 74, 2, 75, 2, 76, 2, 77, 2, 78, 2, 79, 2, 80, 2, 81, 2, 82, 2, 83, + 2, 84, 2, 85, 2, 86, 2, 87, 2, 88, 2, 89, 3, 90, 8, 22, 83, 195, 1, 70, + 2, 11, 83, 2, 145, 64, 3, 45, 84, 72, 4, 26, 69, 247, 203, 2, 76, 2, 185, + 68, 2, 82, 67, 4, 11, 85, 4, 26, 79, 235, 154, 3, 69, 2, 227, 251, 4, 84, + 8, 36, 3, 73, 71, 72, 159, 210, 3, 69, 6, 17, 2, 84, 32, 6, 238, 135, 2, + 67, 134, 2, 80, 155, 2, 83, 6, 174, 174, 2, 69, 202, 165, 1, 79, 155, + 211, 1, 80, 46, 80, 7, 76, 69, 84, 84, 69, 82, 32, 208, 1, 5, 83, 73, 71, + 78, 32, 159, 2, 86, 38, 162, 1, 65, 218, 146, 2, 78, 210, 204, 3, 66, 2, + 68, 2, 71, 2, 72, 2, 75, 2, 76, 2, 77, 2, 80, 2, 82, 2, 83, 2, 84, 2, 87, + 2, 89, 186, 2, 73, 3, 85, 5, 145, 151, 5, 6, 82, 67, 72, 65, 73, 67, 4, + 18, 80, 51, 86, 2, 25, 4, 65, 77, 85, 68, 2, 159, 191, 2, 80, 2, 247, + 174, 3, 73, 36, 48, 7, 76, 69, 84, 84, 69, 82, 32, 147, 1, 86, 32, 158, + 145, 2, 78, 210, 204, 3, 66, 2, 68, 2, 71, 2, 75, 2, 76, 2, 77, 2, 80, 2, + 83, 2, 84, 2, 87, 2, 89, 186, 2, 65, 2, 73, 3, 85, 4, 41, 8, 79, 87, 69, + 76, 32, 83, 73, 71, 4, 11, 78, 4, 179, 158, 5, 32, 212, 3, 112, 10, 76, + 69, 32, 76, 69, 84, 84, 69, 82, 32, 248, 2, 5, 84, 72, 65, 77, 32, 193, + 18, 5, 86, 73, 69, 84, 32, 70, 186, 1, 65, 34, 69, 30, 84, 214, 140, 2, + 78, 138, 144, 1, 79, 206, 247, 1, 75, 2, 80, 162, 7, 85, 222, 61, 70, 2, + 72, 2, 76, 2, 77, 2, 81, 2, 83, 2, 86, 2, 88, 2, 89, 187, 2, 73, 7, 194, + 197, 5, 85, 215, 22, 73, 7, 246, 219, 5, 69, 3, 72, 18, 60, 3, 79, 78, + 69, 234, 147, 5, 83, 254, 68, 72, 187, 2, 65, 10, 11, 45, 10, 142, 219, + 5, 50, 2, 51, 2, 52, 2, 53, 3, 54, 254, 1, 196, 1, 2, 67, 79, 240, 3, 4, + 72, 79, 82, 65, 0, 4, 84, 72, 65, 77, 28, 7, 76, 69, 84, 84, 69, 82, 32, + 220, 4, 5, 83, 73, 71, 78, 32, 217, 5, 11, 86, 79, 87, 69, 76, 32, 83, + 73, 71, 78, 32, 20, 164, 1, 13, 78, 83, 79, 78, 65, 78, 84, 32, 83, 73, + 71, 78, 32, 237, 198, 4, 21, 77, 66, 73, 78, 73, 78, 71, 32, 67, 82, 89, + 80, 84, 79, 71, 82, 65, 77, 77, 73, 67, 18, 148, 1, 6, 70, 73, 78, 65, + 76, 32, 22, 76, 56, 16, 72, 73, 71, 72, 32, 82, 65, 84, 72, 65, 32, 79, + 82, 32, 76, 79, 22, 77, 186, 211, 5, 66, 3, 83, 2, 151, 148, 5, 78, 4, + 54, 79, 149, 151, 1, 7, 65, 32, 84, 65, 78, 71, 32, 2, 167, 216, 1, 87, + 6, 48, 6, 69, 68, 73, 65, 76, 32, 191, 213, 5, 65, 4, 130, 211, 5, 76, 3, + 82, 20, 129, 231, 3, 2, 32, 68, 106, 188, 1, 2, 71, 82, 44, 5, 72, 73, + 71, 72, 32, 94, 76, 222, 1, 82, 198, 129, 2, 85, 210, 200, 1, 73, 166, + 15, 78, 182, 216, 1, 79, 162, 8, 69, 158, 20, 66, 2, 68, 2, 77, 2, 87, + 187, 2, 65, 2, 21, 3, 69, 65, 84, 2, 231, 208, 5, 32, 32, 242, 1, 75, 42, + 82, 250, 136, 5, 83, 82, 67, 2, 80, 2, 84, 254, 68, 70, 2, 72, 3, 89, 36, + 60, 3, 79, 87, 32, 234, 145, 5, 65, 194, 41, 85, 159, 20, 76, 28, 86, 75, + 42, 82, 202, 137, 5, 67, 2, 80, 2, 84, 254, 68, 70, 2, 72, 2, 83, 3, 89, + 6, 234, 206, 5, 72, 2, 88, 187, 2, 65, 2, 189, 217, 3, 2, 65, 84, 8, 26, + 65, 243, 185, 5, 85, 7, 138, 206, 5, 78, 3, 84, 50, 182, 1, 72, 34, 75, + 176, 1, 4, 77, 65, 73, 32, 82, 82, 136, 1, 2, 83, 65, 92, 5, 87, 73, 65, + 78, 71, 152, 27, 4, 84, 79, 78, 69, 224, 100, 3, 68, 79, 75, 177, 242, 3, + 2, 67, 65, 4, 130, 254, 4, 65, 167, 63, 79, 14, 52, 4, 72, 85, 69, 78, + 134, 3, 65, 139, 177, 4, 69, 8, 80, 6, 32, 84, 79, 78, 69, 45, 145, 134, + 4, 8, 45, 76, 85, 69, 32, 75, 65, 82, 6, 194, 205, 5, 51, 2, 52, 3, 53, + 8, 56, 4, 75, 65, 78, 71, 194, 136, 1, 89, 235, 138, 3, 83, 5, 243, 141, + 1, 32, 4, 92, 3, 65, 32, 72, 21, 16, 69, 86, 69, 82, 83, 69, 68, 32, 82, + 79, 84, 65, 84, 69, 68, 32, 2, 179, 146, 4, 65, 2, 171, 162, 3, 82, 8, + 48, 3, 84, 75, 65, 226, 131, 4, 87, 139, 119, 75, 4, 17, 2, 65, 78, 5, + 251, 219, 3, 75, 5, 133, 156, 3, 2, 87, 65, 38, 90, 65, 36, 4, 77, 65, + 73, 32, 22, 79, 46, 84, 86, 85, 242, 193, 3, 73, 207, 134, 2, 69, 9, 242, + 201, 5, 65, 2, 69, 3, 73, 2, 255, 181, 4, 83, 11, 218, 176, 3, 65, 226, + 152, 2, 79, 3, 89, 4, 42, 65, 129, 138, 1, 4, 72, 65, 77, 32, 2, 17, 2, + 76, 76, 2, 135, 217, 3, 32, 9, 166, 136, 5, 85, 151, 64, 69, 144, 1, 184, + 1, 7, 76, 69, 84, 84, 69, 82, 32, 188, 2, 5, 77, 65, 73, 32, 75, 32, 7, + 83, 89, 77, 66, 79, 76, 32, 124, 9, 84, 79, 78, 69, 32, 77, 65, 73, 32, + 81, 6, 86, 79, 87, 69, 76, 32, 96, 44, 4, 72, 73, 71, 72, 1, 3, 76, 79, + 87, 48, 11, 32, 48, 154, 1, 75, 30, 67, 2, 80, 2, 84, 34, 78, 214, 165, + 5, 66, 2, 68, 2, 70, 2, 71, 2, 72, 2, 76, 2, 77, 2, 82, 2, 83, 2, 86, 2, + 89, 247, 30, 79, 6, 26, 72, 235, 196, 5, 79, 4, 242, 165, 5, 72, 247, 30, + 79, 6, 210, 165, 5, 71, 2, 89, 247, 30, 79, 4, 178, 243, 4, 65, 183, 52, + 72, 10, 72, 2, 75, 79, 110, 78, 164, 128, 1, 4, 72, 79, 32, 72, 235, 136, + 3, 83, 4, 140, 129, 1, 3, 73, 32, 75, 167, 194, 4, 78, 8, 58, 78, 178, + 134, 1, 84, 186, 255, 1, 83, 203, 185, 2, 69, 2, 151, 134, 3, 85, 26, 50, + 65, 58, 85, 30, 73, 174, 193, 5, 69, 3, 79, 10, 170, 171, 5, 85, 214, 22, + 65, 2, 77, 2, 78, 3, 89, 9, 26, 69, 175, 193, 5, 65, 5, 171, 193, 5, 65, + 138, 1, 52, 3, 82, 73, 32, 173, 180, 4, 4, 69, 79, 85, 84, 136, 1, 82, + 65, 20, 7, 76, 69, 84, 84, 69, 82, 32, 170, 2, 83, 78, 86, 227, 206, 3, + 68, 2, 163, 213, 1, 66, 88, 214, 1, 65, 254, 157, 1, 82, 242, 55, 68, 46, + 84, 230, 24, 85, 210, 200, 1, 73, 158, 190, 1, 78, 126, 66, 2, 67, 2, 71, + 2, 74, 2, 75, 2, 80, 2, 83, 254, 68, 72, 2, 76, 2, 77, 2, 86, 2, 89, 186, + 2, 69, 3, 79, 11, 176, 149, 3, 7, 82, 67, 72, 65, 73, 67, 32, 230, 168, + 2, 65, 2, 73, 3, 85, 8, 25, 4, 73, 71, 78, 32, 8, 226, 215, 1, 78, 222, + 160, 3, 65, 239, 1, 86, 18, 49, 10, 79, 87, 69, 76, 32, 83, 73, 71, 78, + 32, 18, 238, 215, 1, 65, 190, 21, 85, 210, 200, 1, 73, 206, 134, 2, 69, + 3, 79, 4, 226, 51, 70, 139, 239, 3, 79, 188, 6, 36, 3, 73, 76, 32, 147, + 154, 4, 65, 186, 6, 170, 3, 65, 102, 67, 194, 2, 68, 72, 3, 87, 69, 84, + 48, 9, 70, 82, 65, 67, 84, 73, 79, 78, 32, 136, 8, 9, 73, 78, 32, 80, 79, + 83, 83, 69, 83, 22, 76, 204, 2, 7, 78, 85, 77, 66, 69, 82, 32, 152, 1, + 18, 80, 85, 78, 67, 84, 85, 65, 84, 73, 79, 78, 32, 69, 78, 68, 32, 79, + 70, 54, 82, 42, 83, 188, 14, 11, 86, 79, 87, 69, 76, 32, 83, 73, 71, 78, + 32, 78, 84, 228, 1, 2, 89, 69, 184, 143, 4, 5, 77, 79, 78, 84, 72, 147, + 118, 79, 6, 76, 5, 83, 32, 65, 66, 79, 206, 55, 85, 149, 154, 3, 5, 78, + 68, 32, 79, 68, 2, 219, 159, 3, 86, 52, 80, 9, 79, 78, 83, 79, 78, 65, + 78, 84, 32, 192, 21, 3, 85, 82, 82, 143, 10, 82, 48, 130, 1, 75, 22, 76, + 22, 78, 46, 84, 170, 193, 1, 83, 170, 16, 82, 166, 227, 3, 67, 2, 72, 2, + 74, 2, 77, 2, 80, 2, 86, 3, 89, 5, 247, 247, 4, 83, 7, 151, 185, 4, 76, + 11, 158, 189, 3, 78, 130, 248, 1, 71, 3, 89, 5, 243, 180, 5, 84, 26, 68, + 2, 82, 89, 172, 29, 2, 69, 66, 234, 248, 1, 65, 247, 175, 1, 73, 2, 213, + 201, 1, 7, 32, 67, 85, 76, 84, 73, 86, 42, 168, 1, 4, 79, 78, 69, 32, + 252, 4, 6, 84, 72, 82, 69, 69, 32, 165, 172, 5, 22, 68, 79, 87, 78, 83, + 67, 65, 76, 73, 78, 71, 32, 70, 65, 67, 84, 79, 82, 32, 75, 73, 73, 30, + 112, 5, 69, 73, 71, 72, 84, 34, 70, 40, 3, 72, 65, 76, 18, 79, 88, 4, 83, + 73, 88, 84, 110, 84, 187, 175, 3, 81, 4, 242, 3, 73, 215, 173, 5, 72, 4, + 188, 3, 2, 79, 82, 191, 173, 3, 73, 4, 171, 1, 70, 2, 133, 3, 18, 78, 69, + 45, 72, 85, 78, 68, 82, 69, 68, 45, 65, 78, 68, 45, 83, 73, 88, 6, 64, 5, + 69, 69, 78, 84, 72, 165, 233, 1, 5, 89, 45, 70, 79, 85, 4, 11, 45, 4, + 198, 175, 5, 49, 3, 50, 8, 38, 72, 138, 1, 87, 239, 174, 3, 69, 4, 132, + 1, 18, 82, 69, 69, 45, 72, 85, 78, 68, 82, 69, 68, 45, 65, 78, 68, 45, + 84, 87, 249, 242, 3, 8, 73, 82, 84, 89, 45, 83, 69, 67, 2, 17, 2, 69, 78, + 2, 17, 2, 84, 73, 2, 207, 174, 3, 69, 10, 58, 69, 28, 4, 83, 73, 88, 84, + 82, 84, 163, 174, 3, 81, 2, 129, 1, 3, 73, 71, 72, 4, 50, 69, 149, 175, + 3, 6, 89, 45, 70, 79, 85, 82, 2, 145, 175, 3, 2, 69, 78, 2, 21, 3, 87, + 69, 78, 2, 221, 174, 3, 3, 84, 73, 69, 2, 247, 209, 1, 83, 72, 48, 6, 69, + 84, 84, 69, 82, 32, 187, 197, 3, 65, 70, 198, 1, 78, 138, 24, 84, 222, + 22, 76, 210, 90, 82, 206, 55, 65, 182, 25, 85, 158, 144, 1, 79, 182, 56, + 73, 202, 190, 1, 83, 242, 7, 69, 222, 61, 67, 2, 72, 2, 74, 2, 75, 2, 77, + 2, 80, 2, 86, 3, 89, 10, 46, 78, 234, 166, 5, 71, 2, 89, 187, 2, 65, 4, + 230, 166, 5, 78, 187, 2, 65, 8, 38, 79, 230, 215, 3, 84, 167, 74, 83, 4, + 11, 78, 4, 17, 2, 69, 32, 4, 18, 72, 31, 84, 2, 213, 72, 3, 85, 78, 68, + 2, 229, 238, 1, 3, 72, 79, 85, 2, 17, 2, 32, 84, 2, 11, 69, 2, 155, 139, + 5, 88, 2, 17, 2, 85, 80, 2, 199, 143, 3, 69, 194, 4, 152, 1, 5, 65, 76, + 84, 32, 80, 20, 4, 73, 71, 78, 32, 206, 4, 80, 28, 9, 84, 65, 82, 84, 73, + 78, 71, 32, 70, 41, 8, 89, 76, 76, 65, 66, 76, 69, 32, 2, 207, 175, 3, + 65, 40, 90, 65, 48, 3, 67, 69, 86, 34, 75, 80, 2, 77, 85, 102, 85, 14, + 80, 118, 86, 163, 65, 78, 4, 216, 2, 4, 65, 90, 72, 65, 195, 221, 4, 78, + 2, 11, 73, 2, 215, 255, 4, 84, 6, 38, 85, 157, 255, 4, 3, 65, 65, 67, 4, + 18, 90, 87, 82, 2, 151, 144, 5, 72, 6, 60, 4, 75, 75, 85, 82, 16, 2, 84, + 72, 21, 3, 85, 86, 85, 2, 163, 83, 85, 2, 203, 241, 2, 65, 2, 75, 90, 8, + 26, 65, 255, 210, 4, 79, 6, 34, 84, 230, 232, 3, 65, 15, 78, 2, 11, 72, + 2, 17, 2, 65, 75, 2, 163, 253, 4, 75, 10, 38, 65, 210, 82, 69, 143, 140, + 4, 73, 4, 176, 103, 3, 82, 65, 65, 213, 202, 2, 6, 75, 65, 73, 89, 65, + 82, 2, 11, 69, 2, 159, 10, 78, 2, 17, 2, 82, 79, 2, 243, 153, 4, 77, 148, + 4, 122, 75, 170, 1, 76, 174, 1, 78, 194, 1, 82, 90, 83, 186, 1, 84, 86, + 67, 2, 72, 2, 74, 2, 77, 2, 80, 2, 86, 3, 89, 46, 88, 2, 83, 83, 150, + 186, 1, 65, 190, 21, 85, 158, 144, 1, 79, 182, 56, 73, 187, 198, 1, 69, + 24, 154, 182, 1, 65, 182, 25, 85, 158, 144, 1, 79, 182, 56, 73, 187, 198, + 1, 69, 66, 82, 76, 246, 184, 1, 65, 190, 21, 85, 158, 144, 1, 79, 182, + 56, 73, 187, 198, 1, 69, 44, 250, 4, 76, 250, 179, 1, 65, 190, 21, 85, + 158, 144, 1, 79, 182, 56, 73, 187, 198, 1, 69, 110, 102, 78, 190, 3, 71, + 2, 89, 250, 179, 1, 65, 190, 21, 85, 158, 144, 1, 79, 182, 56, 73, 187, + 198, 1, 69, 44, 186, 3, 78, 250, 179, 1, 65, 190, 21, 85, 158, 144, 1, + 79, 182, 56, 73, 187, 198, 1, 69, 44, 226, 2, 82, 250, 179, 1, 65, 190, + 21, 85, 158, 144, 1, 79, 182, 56, 73, 187, 198, 1, 69, 68, 94, 72, 174, + 1, 83, 250, 179, 1, 65, 190, 21, 85, 158, 144, 1, 79, 182, 56, 73, 187, + 198, 1, 69, 24, 162, 181, 1, 65, 190, 21, 85, 158, 144, 1, 79, 230, 2, + 82, 210, 53, 73, 187, 198, 1, 69, 44, 82, 84, 250, 179, 1, 65, 190, 21, + 85, 158, 144, 1, 79, 182, 56, 73, 187, 198, 1, 69, 22, 246, 179, 1, 65, + 190, 21, 85, 158, 144, 1, 79, 182, 56, 73, 187, 198, 1, 69, 6, 68, 2, 79, + 84, 33, 11, 82, 65, 68, 73, 84, 73, 79, 78, 65, 76, 32, 2, 11, 65, 2, + 199, 144, 4, 76, 4, 24, 2, 67, 82, 55, 78, 2, 17, 2, 69, 68, 2, 11, 73, + 2, 247, 143, 4, 84, 2, 11, 85, 2, 17, 2, 77, 66, 2, 23, 69, 2, 11, 65, 2, + 171, 143, 4, 82, 184, 13, 36, 5, 65, 66, 65, 84, 65, 35, 71, 2, 11, 32, + 2, 135, 169, 3, 84, 182, 13, 54, 69, 20, 3, 83, 65, 32, 241, 6, 3, 85, + 84, 32, 2, 215, 251, 3, 82, 178, 1, 52, 7, 76, 69, 84, 84, 69, 82, 32, + 143, 166, 3, 68, 158, 1, 210, 1, 65, 58, 70, 54, 72, 62, 76, 58, 77, 54, + 78, 50, 83, 126, 85, 114, 69, 2, 73, 2, 79, 2, 86, 158, 198, 4, 84, 82, + 67, 2, 68, 2, 71, 2, 75, 2, 80, 254, 68, 66, 2, 82, 2, 87, 2, 88, 2, 89, + 3, 90, 16, 174, 4, 87, 162, 142, 5, 67, 2, 81, 2, 88, 3, 90, 4, 168, 193, + 4, 5, 73, 78, 65, 76, 32, 239, 80, 65, 6, 26, 84, 203, 145, 5, 65, 4, + 142, 143, 5, 84, 187, 2, 65, 4, 192, 236, 3, 5, 79, 78, 71, 32, 85, 231, + 164, 1, 65, 10, 238, 144, 5, 65, 2, 67, 2, 81, 2, 88, 3, 90, 8, 130, 142, + 5, 71, 2, 72, 2, 89, 187, 2, 65, 8, 26, 72, 243, 143, 5, 65, 6, 40, 4, + 79, 82, 84, 32, 199, 143, 5, 65, 4, 208, 152, 1, 2, 85, 69, 229, 234, 2, + 2, 65, 87, 32, 58, 73, 54, 69, 162, 142, 5, 67, 2, 81, 2, 88, 3, 90, 16, + 50, 85, 162, 142, 5, 67, 2, 81, 2, 88, 3, 90, 8, 158, 142, 5, 67, 2, 81, + 2, 88, 3, 90, 130, 12, 64, 10, 67, 79, 77, 80, 79, 78, 69, 78, 84, 45, + 143, 241, 2, 73, 128, 12, 70, 48, 178, 1, 49, 2, 50, 2, 51, 2, 52, 2, 53, + 2, 54, 95, 55, 198, 1, 86, 48, 242, 1, 49, 2, 50, 2, 51, 2, 52, 2, 53, 2, + 54, 2, 55, 2, 56, 3, 57, 18, 130, 140, 5, 49, 2, 50, 2, 51, 2, 52, 2, 53, + 2, 54, 2, 55, 2, 56, 3, 57, 200, 1, 150, 1, 48, 2, 49, 2, 50, 2, 51, 2, + 52, 2, 53, 2, 54, 2, 55, 2, 56, 3, 57, 138, 1, 58, 48, 2, 49, 2, 50, 2, + 51, 2, 52, 2, 53, 95, 54, 20, 146, 138, 5, 48, 2, 49, 2, 50, 2, 51, 2, + 52, 2, 53, 2, 54, 2, 55, 2, 56, 3, 57, 18, 182, 137, 5, 48, 2, 49, 2, 50, + 2, 51, 2, 52, 2, 53, 2, 54, 2, 55, 3, 56, 4, 48, 6, 67, 65, 82, 84, 82, + 73, 21, 2, 68, 82, 2, 187, 212, 3, 68, 2, 215, 139, 4, 73, 2, 155, 133, + 3, 82, 142, 3, 154, 1, 65, 152, 2, 5, 68, 68, 89, 32, 66, 22, 76, 234, + 14, 78, 144, 1, 5, 83, 84, 32, 84, 85, 21, 12, 84, 82, 65, 71, 82, 65, + 77, 32, 70, 79, 82, 32, 10, 68, 9, 67, 85, 80, 32, 87, 73, 84, 72, 79, + 58, 82, 171, 181, 4, 80, 2, 33, 6, 85, 84, 32, 72, 65, 78, 2, 195, 228, + 3, 68, 6, 72, 9, 45, 79, 70, 70, 32, 67, 65, 76, 69, 29, 5, 68, 82, 79, + 80, 45, 2, 221, 226, 3, 2, 78, 68, 4, 234, 243, 2, 83, 245, 112, 4, 66, + 65, 82, 66, 2, 147, 226, 3, 69, 216, 1, 38, 69, 225, 2, 4, 85, 71, 85, + 32, 16, 52, 6, 80, 72, 79, 78, 69, 32, 246, 1, 83, 35, 86, 12, 132, 1, 3, + 82, 69, 67, 252, 151, 1, 3, 76, 79, 67, 242, 227, 2, 83, 165, 116, 13, + 79, 78, 32, 84, 79, 80, 32, 79, 70, 32, 77, 79, 68, 6, 36, 5, 69, 73, 86, + 69, 82, 51, 79, 5, 29, 5, 32, 87, 73, 84, 72, 2, 159, 39, 32, 2, 243, + 221, 2, 82, 2, 11, 67, 2, 211, 188, 3, 79, 2, 247, 231, 2, 73, 200, 1, + 162, 1, 65, 40, 15, 70, 82, 65, 67, 84, 73, 79, 78, 32, 68, 73, 71, 73, + 84, 32, 164, 2, 2, 76, 69, 156, 4, 5, 83, 73, 71, 78, 32, 198, 2, 86, + 175, 136, 3, 68, 2, 11, 73, 2, 245, 189, 4, 2, 32, 76, 14, 74, 84, 40, 2, + 79, 78, 81, 10, 90, 69, 82, 79, 32, 70, 79, 82, 32, 79, 8, 36, 3, 72, 82, + 69, 13, 2, 87, 79, 4, 11, 69, 4, 29, 5, 32, 70, 79, 82, 32, 4, 34, 79, + 21, 4, 69, 86, 69, 78, 2, 17, 2, 68, 68, 2, 49, 10, 32, 80, 79, 87, 69, + 82, 83, 32, 79, 70, 2, 201, 22, 2, 32, 70, 114, 44, 5, 84, 84, 69, 82, + 32, 159, 187, 4, 78, 112, 214, 1, 68, 54, 76, 38, 78, 106, 82, 34, 84, + 242, 144, 1, 65, 126, 86, 186, 24, 85, 158, 144, 1, 79, 182, 56, 73, 202, + 190, 1, 83, 82, 66, 2, 67, 2, 71, 2, 74, 2, 75, 2, 80, 162, 7, 69, 222, + 61, 72, 2, 77, 3, 89, 10, 234, 179, 4, 68, 254, 68, 72, 2, 90, 187, 2, + 65, 6, 198, 244, 2, 76, 167, 134, 2, 65, 10, 42, 65, 230, 247, 4, 71, 2, + 78, 3, 89, 5, 41, 8, 75, 65, 65, 82, 65, 32, 80, 79, 2, 163, 37, 76, 6, + 194, 89, 82, 159, 160, 4, 65, 10, 138, 178, 4, 84, 254, 68, 72, 2, 83, + 187, 2, 65, 20, 86, 67, 194, 1, 83, 248, 35, 3, 84, 85, 85, 142, 108, 65, + 170, 1, 78, 203, 162, 3, 86, 6, 60, 9, 79, 77, 66, 73, 78, 73, 78, 71, + 32, 219, 145, 1, 65, 4, 70, 65, 185, 250, 3, 11, 67, 65, 78, 68, 82, 65, + 66, 73, 78, 68, 85, 2, 33, 6, 78, 85, 83, 86, 65, 82, 2, 147, 250, 3, 65, + 2, 11, 73, 2, 169, 189, 3, 3, 68, 68, 72, 30, 49, 10, 79, 87, 69, 76, 32, + 83, 73, 71, 78, 32, 30, 186, 145, 1, 65, 106, 86, 214, 20, 85, 158, 144, + 1, 79, 182, 56, 73, 187, 198, 1, 69, 6, 80, 10, 78, 73, 83, 32, 82, 65, + 67, 81, 85, 69, 150, 221, 2, 71, 219, 151, 2, 84, 2, 11, 84, 2, 25, 4, + 32, 65, 78, 68, 2, 251, 239, 2, 32, 2, 219, 221, 4, 66, 162, 1, 210, 2, + 65, 134, 1, 66, 174, 1, 67, 130, 3, 68, 198, 3, 69, 154, 2, 70, 182, 1, + 71, 198, 1, 72, 64, 8, 89, 79, 85, 84, 72, 70, 85, 76, 52, 2, 73, 78, 46, + 75, 98, 76, 146, 1, 77, 134, 1, 79, 62, 80, 142, 1, 82, 210, 1, 83, 224, + 1, 14, 86, 65, 83, 84, 78, 69, 83, 83, 32, 79, 82, 32, 87, 65, 12, 2, 87, + 65, 202, 94, 85, 143, 234, 3, 74, 8, 88, 4, 67, 67, 85, 77, 22, 83, 132, + 21, 2, 68, 86, 157, 175, 1, 5, 71, 71, 82, 65, 86, 2, 183, 176, 1, 85, 2, + 183, 173, 4, 67, 6, 92, 7, 79, 76, 68, 32, 82, 69, 83, 32, 5, 82, 65, 78, + 67, 72, 221, 230, 3, 3, 65, 82, 82, 2, 153, 159, 4, 3, 79, 76, 85, 2, 11, + 73, 2, 133, 157, 1, 3, 78, 71, 32, 22, 54, 72, 20, 3, 76, 79, 83, 102, + 79, 211, 248, 1, 69, 2, 219, 186, 3, 65, 6, 26, 69, 143, 206, 3, 85, 4, + 26, 68, 207, 215, 3, 78, 2, 21, 3, 32, 77, 79, 2, 243, 238, 2, 85, 12, + 28, 3, 77, 80, 76, 35, 78, 4, 242, 17, 73, 143, 139, 4, 69, 8, 32, 4, 83, + 84, 65, 78, 23, 84, 2, 183, 219, 4, 67, 6, 46, 69, 20, 3, 82, 65, 82, + 211, 221, 3, 65, 2, 247, 155, 4, 78, 2, 171, 129, 3, 73, 20, 80, 4, 65, + 82, 75, 69, 22, 69, 206, 1, 73, 74, 85, 237, 204, 4, 3, 79, 85, 66, 2, + 199, 154, 4, 78, 6, 132, 1, 19, 70, 69, 67, 84, 73, 86, 69, 78, 69, 83, + 83, 32, 79, 82, 32, 68, 73, 83, 84, 34, 80, 133, 7, 6, 67, 73, 83, 73, + 86, 69, 2, 11, 79, 2, 211, 153, 4, 82, 2, 17, 2, 65, 82, 2, 143, 10, 84, + 8, 68, 6, 70, 70, 73, 67, 85, 76, 34, 77, 161, 12, 4, 86, 69, 82, 71, 2, + 11, 84, 2, 171, 213, 3, 73, 4, 140, 1, 2, 73, 78, 243, 150, 4, 77, 14, + 100, 5, 77, 66, 69, 76, 76, 34, 78, 124, 4, 88, 72, 65, 85, 236, 106, 3, + 84, 69, 82, 239, 242, 2, 65, 2, 189, 164, 4, 3, 73, 83, 72, 6, 80, 4, 68, + 69, 65, 86, 20, 4, 76, 65, 82, 71, 129, 233, 2, 4, 67, 79, 85, 78, 2, + 175, 238, 3, 79, 2, 183, 163, 4, 69, 2, 135, 150, 4, 83, 12, 70, 79, 76, + 3, 85, 76, 76, 196, 5, 3, 65, 73, 76, 147, 181, 4, 76, 4, 18, 76, 35, 83, + 2, 225, 148, 4, 3, 76, 79, 87, 2, 205, 4, 2, 84, 69, 4, 142, 150, 3, 32, + 211, 56, 78, 10, 96, 8, 65, 84, 72, 69, 82, 73, 78, 71, 22, 79, 64, 3, + 82, 69, 65, 65, 5, 85, 65, 82, 68, 69, 5, 227, 228, 3, 32, 2, 41, 8, 73, + 78, 71, 32, 84, 79, 32, 77, 2, 211, 174, 4, 69, 2, 75, 84, 4, 48, 2, 65, + 82, 33, 6, 79, 76, 68, 73, 78, 71, 2, 11, 68, 2, 187, 204, 3, 78, 2, 11, + 32, 2, 195, 216, 1, 66, 4, 26, 67, 211, 164, 4, 78, 2, 143, 5, 82, 4, 60, + 7, 69, 69, 80, 73, 78, 71, 32, 225, 140, 4, 2, 73, 78, 2, 11, 83, 2, 151, + 221, 2, 77, 6, 18, 65, 107, 69, 4, 60, 3, 66, 79, 85, 21, 8, 87, 32, 79, + 82, 32, 77, 79, 68, 2, 243, 143, 4, 82, 2, 187, 215, 3, 69, 2, 139, 144, + 4, 71, 6, 26, 65, 30, 69, 47, 73, 2, 153, 143, 4, 2, 83, 83, 2, 11, 65, + 2, 11, 83, 2, 191, 191, 3, 85, 2, 11, 82, 2, 171, 153, 4, 69, 4, 204, + 162, 3, 7, 78, 32, 84, 72, 69, 32, 86, 139, 107, 80, 8, 54, 65, 64, 4, + 69, 78, 69, 84, 165, 98, 2, 85, 82, 4, 22, 84, 243, 2, 67, 2, 17, 2, 84, + 69, 2, 183, 142, 4, 82, 2, 195, 177, 1, 82, 12, 30, 69, 157, 1, 2, 73, + 84, 10, 34, 76, 22, 83, 231, 186, 4, 65, 2, 251, 204, 1, 69, 6, 18, 73, + 51, 80, 4, 30, 68, 137, 1, 2, 83, 84, 2, 147, 1, 69, 2, 11, 79, 2, 199, + 211, 3, 78, 2, 255, 210, 3, 85, 10, 34, 69, 64, 2, 73, 78, 23, 84, 2, 11, + 86, 2, 17, 2, 69, 82, 2, 11, 65, 2, 211, 158, 4, 78, 2, 183, 138, 4, 75, + 6, 42, 79, 237, 219, 2, 4, 82, 69, 78, 71, 4, 26, 80, 131, 196, 4, 86, 2, + 11, 80, 2, 211, 166, 3, 65, 2, 39, 83, 4, 26, 73, 231, 183, 4, 84, 2, + 147, 137, 4, 84, 224, 2, 86, 65, 180, 31, 2, 69, 82, 246, 1, 73, 206, 1, + 79, 100, 3, 82, 69, 69, 179, 8, 85, 146, 2, 44, 4, 65, 78, 65, 32, 145, + 10, 2, 73, 32, 100, 122, 65, 38, 69, 76, 7, 76, 69, 84, 84, 69, 82, 32, + 154, 7, 79, 76, 3, 73, 66, 73, 0, 3, 85, 66, 85, 45, 2, 83, 85, 4, 184, + 8, 3, 65, 66, 65, 3, 66, 6, 58, 66, 0, 3, 69, 66, 69, 245, 7, 4, 89, 66, + 69, 89, 2, 243, 7, 69, 78, 202, 1, 65, 42, 68, 82, 70, 2, 81, 14, 71, 50, + 72, 38, 75, 62, 76, 32, 3, 77, 69, 69, 20, 2, 67, 72, 2, 74, 2, 80, 18, + 78, 42, 83, 94, 84, 102, 86, 2, 87, 42, 90, 130, 225, 2, 66, 2, 82, 3, + 89, 4, 252, 1, 2, 76, 73, 191, 174, 4, 73, 6, 30, 65, 29, 3, 72, 65, 65, + 4, 218, 2, 65, 255, 1, 86, 2, 227, 175, 4, 76, 2, 123, 65, 6, 110, 65, + 86, 78, 245, 173, 4, 3, 72, 65, 73, 4, 178, 228, 2, 72, 147, 237, 1, 65, + 4, 26, 65, 247, 227, 2, 72, 2, 11, 65, 2, 199, 174, 4, 70, 4, 18, 65, 35, + 72, 2, 11, 65, 2, 147, 174, 4, 77, 2, 211, 1, 65, 4, 224, 173, 4, 2, 79, + 79, 191, 34, 65, 8, 32, 2, 65, 65, 18, 72, 23, 69, 2, 163, 16, 68, 4, 18, + 69, 87, 65, 2, 243, 172, 4, 69, 10, 62, 65, 16, 3, 72, 65, 65, 190, 225, + 2, 84, 203, 239, 1, 79, 2, 131, 1, 86, 5, 155, 172, 4, 76, 2, 17, 2, 65, + 65, 2, 243, 171, 4, 86, 6, 26, 65, 175, 208, 4, 79, 4, 26, 86, 147, 208, + 4, 65, 2, 21, 3, 73, 89, 65, 2, 159, 188, 4, 78, 6, 48, 3, 65, 66, 79, + 14, 66, 1, 3, 79, 66, 79, 2, 23, 65, 2, 11, 79, 2, 11, 70, 2, 11, 73, 2, + 167, 187, 4, 76, 2, 211, 206, 3, 75, 174, 1, 26, 67, 159, 224, 2, 68, + 154, 1, 132, 1, 9, 72, 65, 82, 65, 67, 84, 69, 82, 32, 245, 162, 4, 17, + 85, 82, 82, 69, 78, 67, 89, 32, 83, 89, 77, 66, 79, 76, 32, 66, 65, 152, + 1, 176, 2, 6, 66, 79, 32, 66, 65, 73, 16, 6, 67, 72, 79, 32, 67, 72, 56, + 3, 68, 79, 32, 44, 2, 70, 79, 76, 3, 72, 79, 32, 66, 75, 190, 1, 76, 138, + 1, 77, 252, 1, 7, 65, 78, 71, 75, 72, 65, 78, 46, 78, 158, 1, 80, 234, 1, + 82, 70, 83, 238, 2, 84, 224, 2, 3, 87, 79, 32, 34, 89, 145, 226, 3, 2, + 79, 32, 2, 143, 12, 77, 8, 204, 210, 2, 2, 65, 78, 170, 167, 1, 73, 155, + 58, 79, 4, 164, 165, 4, 3, 67, 72, 65, 227, 33, 68, 6, 32, 2, 32, 70, 21, + 2, 78, 71, 4, 219, 209, 2, 65, 2, 147, 130, 3, 77, 4, 40, 4, 78, 79, 75, + 72, 223, 199, 4, 72, 2, 239, 197, 4, 85, 14, 40, 2, 72, 79, 229, 9, 3, + 79, 32, 75, 12, 26, 32, 239, 206, 3, 77, 10, 36, 2, 75, 72, 57, 3, 82, + 65, 75, 8, 158, 9, 87, 150, 171, 3, 85, 254, 67, 79, 255, 59, 65, 2, 135, + 239, 3, 72, 8, 76, 2, 79, 32, 224, 11, 8, 65, 75, 75, 72, 65, 78, 71, 89, + 139, 187, 4, 85, 4, 32, 2, 67, 72, 207, 245, 3, 76, 2, 171, 164, 4, 85, + 16, 28, 2, 65, 73, 235, 52, 79, 14, 42, 32, 176, 1, 3, 84, 65, 73, 19, + 89, 10, 76, 4, 67, 72, 65, 84, 44, 5, 72, 65, 78, 45, 65, 22, 84, 191, + 193, 4, 69, 2, 11, 84, 2, 11, 65, 2, 195, 194, 4, 87, 2, 151, 177, 3, 75, + 4, 222, 165, 4, 72, 159, 11, 82, 2, 203, 2, 75, 2, 193, 154, 4, 2, 65, + 77, 8, 60, 3, 71, 79, 32, 32, 3, 73, 75, 72, 29, 3, 79, 32, 78, 2, 11, + 78, 2, 211, 158, 4, 71, 2, 237, 166, 4, 2, 65, 72, 4, 182, 243, 3, 69, + 215, 79, 85, 12, 68, 6, 65, 73, 89, 65, 78, 78, 22, 72, 249, 159, 4, 3, + 79, 32, 80, 2, 203, 174, 4, 79, 8, 36, 3, 73, 78, 84, 21, 2, 79, 32, 2, + 255, 156, 4, 72, 6, 44, 2, 80, 72, 161, 5, 4, 83, 65, 77, 80, 4, 182, + 240, 3, 85, 155, 1, 65, 4, 32, 2, 79, 32, 227, 192, 4, 85, 2, 11, 82, 2, + 155, 190, 4, 85, 36, 44, 4, 65, 82, 65, 32, 225, 1, 2, 79, 32, 28, 62, + 65, 130, 1, 85, 134, 184, 2, 73, 206, 134, 2, 69, 3, 79, 13, 64, 6, 73, + 32, 77, 65, 73, 77, 142, 191, 4, 65, 2, 69, 3, 77, 4, 26, 65, 191, 247, + 2, 85, 2, 11, 76, 2, 139, 171, 4, 65, 9, 186, 254, 3, 69, 151, 64, 85, 8, + 24, 2, 82, 85, 23, 83, 2, 187, 170, 4, 83, 6, 230, 155, 4, 65, 226, 31, + 85, 187, 2, 79, 18, 30, 72, 133, 2, 2, 79, 32, 14, 48, 6, 65, 78, 84, 72, + 65, 75, 21, 2, 79, 32, 2, 175, 169, 3, 72, 12, 80, 8, 78, 65, 78, 71, 77, + 79, 78, 84, 20, 4, 80, 72, 85, 84, 13, 2, 84, 72, 2, 163, 157, 4, 72, 2, + 123, 72, 8, 34, 65, 234, 234, 3, 79, 3, 85, 4, 158, 244, 2, 72, 183, 199, + 1, 78, 4, 38, 84, 165, 140, 2, 3, 80, 65, 84, 2, 147, 156, 4, 65, 2, 11, + 87, 2, 243, 233, 2, 65, 6, 30, 65, 45, 3, 79, 32, 89, 2, 21, 3, 77, 65, + 75, 2, 231, 242, 2, 75, 4, 154, 233, 3, 73, 215, 77, 65, 10, 30, 69, 145, + 1, 2, 77, 79, 6, 18, 32, 107, 70, 4, 84, 11, 68, 79, 69, 83, 32, 78, 79, + 84, 32, 69, 88, 201, 164, 3, 4, 69, 88, 73, 83, 2, 147, 113, 73, 2, 171, + 152, 3, 79, 4, 46, 77, 157, 145, 3, 5, 68, 89, 78, 65, 77, 2, 187, 129, + 3, 69, 10, 18, 78, 95, 82, 8, 26, 32, 191, 175, 3, 75, 6, 26, 83, 255, + 177, 2, 71, 4, 218, 165, 2, 65, 211, 212, 1, 80, 2, 21, 3, 68, 32, 80, 2, + 25, 4, 76, 65, 67, 69, 2, 17, 2, 32, 77, 2, 143, 163, 3, 69, 4, 56, 4, + 85, 71, 72, 84, 173, 162, 3, 4, 78, 71, 32, 83, 2, 185, 164, 1, 5, 32, + 66, 65, 76, 76, 46, 22, 32, 199, 3, 45, 30, 154, 1, 68, 90, 76, 114, 82, + 130, 131, 1, 66, 86, 67, 242, 5, 83, 170, 149, 1, 80, 253, 21, 15, 78, + 69, 84, 87, 79, 82, 75, 69, 68, 32, 67, 79, 77, 80, 85, 4, 64, 10, 73, + 77, 69, 78, 83, 73, 79, 78, 65, 76, 219, 134, 1, 79, 2, 131, 146, 3, 32, + 6, 76, 12, 73, 78, 69, 83, 32, 67, 79, 78, 86, 69, 82, 71, 237, 127, 2, + 69, 70, 4, 217, 135, 4, 3, 73, 78, 71, 10, 36, 4, 65, 89, 83, 32, 147, + 127, 73, 8, 230, 153, 2, 66, 222, 155, 1, 65, 242, 81, 76, 31, 82, 16, + 44, 2, 68, 32, 254, 3, 80, 131, 133, 1, 69, 12, 196, 2, 12, 84, 79, 80, + 45, 76, 73, 71, 72, 84, 69, 68, 32, 80, 17, 76, 69, 70, 84, 45, 76, 73, + 71, 72, 84, 69, 68, 32, 68, 79, 87, 78, 0, 16, 82, 73, 71, 72, 84, 45, + 76, 73, 71, 72, 84, 69, 68, 32, 85, 80, 209, 223, 1, 25, 66, 79, 84, 84, + 79, 77, 45, 76, 73, 71, 72, 84, 69, 68, 32, 82, 73, 71, 72, 84, 87, 65, + 82, 68, 83, 6, 76, 4, 76, 69, 70, 84, 69, 11, 82, 73, 71, 72, 84, 87, 65, + 82, 68, 83, 32, 2, 11, 87, 2, 25, 4, 65, 82, 68, 83, 2, 181, 200, 1, 2, + 32, 69, 4, 154, 200, 1, 69, 139, 23, 65, 2, 129, 239, 3, 5, 69, 82, 45, + 69, 77, 8, 34, 77, 85, 4, 78, 68, 69, 82, 4, 21, 3, 66, 83, 32, 4, 38, + 85, 149, 182, 2, 3, 68, 79, 87, 2, 199, 165, 3, 80, 4, 212, 128, 3, 10, + 32, 67, 76, 79, 85, 68, 32, 65, 78, 68, 141, 45, 2, 83, 84, 230, 5, 204, + 1, 6, 66, 69, 84, 65, 78, 32, 240, 45, 6, 69, 32, 79, 86, 69, 82, 72, 7, + 70, 73, 78, 65, 71, 72, 32, 150, 9, 71, 152, 1, 3, 76, 68, 69, 248, 2, 2, + 77, 69, 56, 2, 78, 89, 78, 82, 223, 154, 3, 67, 160, 3, 228, 2, 18, 65, + 83, 84, 82, 79, 76, 79, 71, 73, 67, 65, 76, 32, 83, 73, 71, 78, 32, 172, + 1, 18, 67, 65, 78, 84, 73, 76, 76, 65, 84, 73, 79, 78, 32, 83, 73, 71, + 78, 32, 208, 1, 6, 68, 73, 71, 73, 84, 32, 100, 9, 75, 85, 32, 82, 85, + 32, 75, 72, 65, 26, 76, 204, 3, 5, 77, 65, 82, 75, 32, 246, 18, 83, 181, + 15, 11, 86, 79, 87, 69, 76, 32, 83, 73, 71, 78, 32, 6, 46, 83, 129, 41, + 6, 45, 75, 72, 89, 85, 68, 4, 104, 8, 68, 79, 78, 71, 32, 84, 83, 72, + 229, 21, 13, 71, 82, 65, 32, 71, 67, 65, 78, 32, 45, 67, 72, 65, 2, 159, + 32, 85, 8, 144, 1, 5, 72, 69, 65, 86, 89, 0, 5, 76, 73, 71, 72, 84, 40, + 7, 83, 66, 85, 66, 32, 45, 67, 189, 255, 3, 8, 67, 65, 78, 71, 32, 84, + 69, 45, 2, 17, 2, 32, 66, 2, 231, 144, 3, 69, 2, 251, 154, 3, 72, 40, + 156, 182, 2, 4, 72, 65, 76, 70, 82, 70, 30, 83, 42, 84, 62, 90, 130, 83, + 78, 14, 79, 199, 110, 69, 5, 245, 10, 2, 32, 66, 92, 96, 6, 69, 84, 84, + 69, 82, 32, 181, 2, 13, 79, 71, 79, 84, 89, 80, 69, 32, 83, 73, 71, 78, + 32, 88, 226, 1, 75, 50, 82, 208, 213, 3, 10, 70, 73, 88, 69, 68, 45, 70, + 79, 82, 77, 202, 1, 68, 86, 78, 46, 83, 38, 84, 46, 66, 2, 67, 2, 71, 2, + 80, 2, 90, 254, 68, 45, 2, 72, 2, 74, 2, 76, 2, 77, 2, 87, 2, 89, 187, 2, + 65, 8, 134, 158, 4, 83, 14, 72, 2, 75, 187, 2, 65, 4, 226, 157, 4, 82, + 187, 2, 65, 4, 248, 25, 3, 76, 72, 65, 13, 4, 67, 72, 65, 68, 80, 250, 2, + 66, 176, 1, 8, 77, 78, 89, 65, 77, 32, 89, 73, 114, 67, 172, 2, 13, 89, + 73, 71, 32, 77, 71, 79, 32, 84, 83, 72, 69, 71, 190, 1, 71, 212, 2, 9, + 65, 78, 71, 32, 75, 72, 65, 78, 71, 58, 72, 48, 2, 73, 78, 246, 1, 78, + 220, 1, 2, 80, 65, 30, 82, 118, 83, 46, 84, 36, 4, 76, 69, 65, 68, 233, + 250, 1, 17, 68, 69, 76, 73, 77, 73, 84, 69, 82, 32, 84, 83, 72, 69, 71, + 32, 66, 10, 52, 9, 75, 65, 45, 32, 83, 72, 79, 71, 32, 27, 83, 4, 142, 1, + 71, 67, 89, 6, 34, 75, 229, 21, 3, 68, 85, 83, 4, 56, 6, 65, 45, 32, 83, + 72, 79, 89, 4, 85, 82, 32, 89, 2, 21, 3, 71, 32, 71, 2, 41, 8, 73, 32, + 77, 71, 79, 32, 82, 71, 2, 163, 211, 2, 89, 2, 221, 2, 2, 73, 71, 12, 84, + 5, 65, 82, 69, 84, 32, 240, 1, 2, 72, 69, 29, 7, 76, 79, 83, 73, 78, 71, + 32, 6, 112, 12, 45, 68, 90, 85, 68, 32, 82, 84, 65, 71, 83, 32, 97, 12, + 89, 73, 71, 32, 77, 71, 79, 32, 80, 72, 85, 82, 4, 42, 66, 37, 6, 77, 69, + 32, 76, 79, 78, 2, 33, 6, 90, 72, 73, 32, 77, 73, 2, 231, 22, 71, 2, 225, + 3, 3, 32, 83, 72, 2, 137, 142, 2, 2, 32, 77, 4, 68, 13, 66, 82, 68, 65, + 32, 82, 78, 89, 73, 78, 71, 32, 89, 3, 89, 2, 213, 5, 11, 73, 71, 32, 77, + 71, 79, 32, 83, 71, 65, 66, 12, 68, 4, 84, 69, 82, 32, 141, 2, 8, 85, 71, + 32, 82, 84, 65, 71, 83, 8, 56, 8, 89, 73, 71, 32, 77, 71, 79, 32, 211, + 207, 3, 84, 6, 68, 4, 45, 85, 77, 32, 117, 9, 84, 82, 85, 78, 67, 65, 84, + 69, 68, 4, 88, 7, 82, 78, 65, 77, 32, 66, 67, 245, 2, 10, 71, 84, 69, 82, + 32, 84, 83, 72, 69, 71, 2, 241, 2, 2, 65, 68, 2, 203, 145, 4, 32, 4, 21, + 3, 32, 71, 89, 4, 130, 196, 3, 79, 135, 18, 65, 2, 17, 2, 65, 76, 2, 213, + 238, 3, 2, 65, 78, 6, 92, 6, 73, 84, 73, 65, 76, 32, 165, 204, 3, 11, 84, + 69, 82, 83, 89, 76, 76, 65, 66, 73, 67, 4, 68, 13, 66, 82, 68, 65, 32, + 82, 78, 89, 73, 78, 71, 32, 89, 3, 89, 2, 53, 11, 73, 71, 32, 77, 71, 79, + 32, 77, 68, 85, 78, 2, 151, 240, 3, 32, 10, 72, 10, 71, 65, 83, 32, 66, + 90, 85, 78, 71, 32, 77, 4, 89, 73, 83, 32, 4, 56, 3, 83, 71, 79, 245, + 237, 3, 5, 78, 89, 73, 32, 90, 2, 151, 10, 82, 6, 44, 5, 84, 83, 72, 69, + 71, 163, 201, 3, 83, 5, 147, 201, 3, 32, 2, 233, 234, 3, 2, 76, 85, 4, + 212, 200, 3, 8, 71, 89, 65, 32, 71, 82, 65, 77, 1, 14, 73, 78, 32, 67, + 72, 69, 78, 32, 83, 80, 85, 78, 71, 83, 4, 224, 199, 3, 4, 66, 82, 85, + 76, 39, 72, 6, 32, 4, 82, 65, 73, 76, 55, 83, 2, 225, 7, 9, 73, 78, 71, + 32, 77, 67, 72, 65, 78, 4, 56, 5, 65, 32, 45, 80, 72, 165, 198, 3, 3, 72, + 69, 71, 2, 255, 231, 3, 82, 156, 1, 84, 4, 73, 71, 78, 32, 228, 6, 9, 85, + 66, 74, 79, 73, 78, 69, 68, 32, 143, 4, 89, 42, 176, 1, 4, 71, 82, 85, + 32, 96, 2, 76, 67, 30, 77, 36, 11, 78, 89, 73, 32, 90, 76, 65, 32, 78, + 65, 65, 22, 82, 252, 2, 2, 89, 65, 130, 4, 73, 165, 4, 5, 83, 78, 65, 32, + 76, 4, 40, 3, 67, 65, 78, 1, 3, 77, 69, 68, 2, 25, 4, 32, 82, 71, 89, 2, + 169, 4, 2, 73, 78, 4, 238, 3, 73, 179, 4, 69, 4, 136, 4, 2, 65, 82, 231, + 3, 67, 2, 159, 228, 3, 32, 20, 116, 4, 68, 69, 76, 32, 240, 1, 10, 74, + 69, 83, 32, 83, 85, 32, 78, 71, 65, 137, 192, 3, 6, 78, 65, 77, 32, 66, + 67, 16, 52, 5, 68, 75, 65, 82, 32, 53, 4, 78, 65, 71, 32, 8, 94, 71, 129, + 161, 2, 6, 82, 68, 69, 76, 32, 78, 8, 42, 71, 69, 6, 82, 68, 69, 76, 32, + 68, 6, 46, 67, 228, 233, 1, 2, 78, 89, 251, 116, 83, 2, 251, 133, 4, 73, + 2, 147, 228, 2, 75, 2, 147, 154, 2, 32, 4, 18, 78, 71, 82, 2, 11, 71, 2, + 21, 3, 32, 82, 84, 2, 11, 65, 2, 255, 199, 3, 71, 2, 17, 2, 32, 84, 2, + 187, 241, 2, 83, 94, 68, 7, 76, 69, 84, 84, 69, 82, 32, 145, 2, 5, 83, + 73, 71, 78, 32, 88, 220, 1, 10, 70, 73, 88, 69, 68, 45, 70, 79, 82, 77, + 234, 185, 3, 68, 50, 75, 38, 78, 46, 83, 38, 84, 46, 66, 2, 67, 2, 71, 2, + 80, 2, 90, 254, 68, 45, 2, 72, 2, 74, 2, 76, 2, 77, 2, 82, 2, 87, 2, 89, + 187, 2, 65, 6, 11, 32, 6, 166, 128, 4, 82, 2, 87, 3, 89, 6, 38, 73, 50, + 77, 33, 3, 76, 67, 69, 2, 45, 9, 78, 86, 69, 82, 84, 69, 68, 32, 77, 2, + 11, 67, 2, 45, 2, 72, 85, 2, 25, 4, 32, 84, 83, 65, 2, 11, 32, 2, 231, + 185, 2, 67, 20, 60, 6, 76, 76, 65, 66, 76, 69, 21, 5, 77, 66, 79, 76, 32, + 2, 227, 239, 3, 32, 18, 104, 4, 68, 82, 73, 76, 32, 6, 78, 79, 82, 32, + 66, 85, 130, 1, 80, 93, 7, 82, 68, 79, 32, 82, 74, 69, 2, 11, 32, 2, 211, + 218, 3, 66, 9, 11, 32, 6, 72, 4, 66, 90, 72, 73, 0, 4, 71, 83, 85, 77, 1, + 4, 78, 89, 73, 83, 2, 217, 209, 1, 5, 32, 45, 75, 72, 89, 4, 52, 6, 65, + 68, 77, 65, 32, 71, 21, 3, 72, 85, 82, 2, 187, 182, 2, 68, 2, 251, 88, + 32, 5, 245, 195, 2, 6, 32, 82, 71, 89, 65, 32, 30, 120, 8, 82, 69, 86, + 69, 82, 83, 69, 68, 182, 24, 86, 214, 20, 85, 158, 144, 1, 79, 182, 56, + 73, 186, 198, 1, 69, 223, 61, 65, 4, 213, 245, 1, 2, 32, 73, 2, 25, 4, + 32, 73, 78, 70, 2, 11, 73, 2, 11, 78, 2, 223, 145, 2, 73, 118, 216, 1, 9, + 67, 79, 78, 83, 79, 78, 65, 78, 84, 20, 7, 76, 69, 84, 84, 69, 82, 32, + 236, 6, 20, 77, 79, 68, 73, 70, 73, 69, 82, 32, 76, 69, 84, 84, 69, 82, + 32, 76, 65, 66, 73, 37, 8, 83, 69, 80, 65, 82, 65, 84, 79, 2, 211, 187, + 3, 32, 112, 106, 65, 108, 17, 66, 69, 82, 66, 69, 82, 32, 65, 67, 65, 68, + 69, 77, 89, 32, 89, 65, 30, 84, 223, 1, 89, 4, 84, 6, 89, 69, 82, 32, 89, + 65, 241, 246, 3, 9, 72, 65, 71, 71, 65, 82, 32, 89, 65, 2, 251, 246, 3, + 71, 4, 246, 247, 3, 72, 3, 74, 18, 92, 11, 65, 87, 69, 76, 76, 69, 77, + 69, 84, 32, 89, 33, 8, 85, 65, 82, 69, 71, 32, 89, 65, 2, 11, 65, 2, 239, + 246, 3, 90, 16, 62, 71, 190, 2, 75, 210, 242, 3, 90, 62, 78, 86, 72, 3, + 81, 4, 154, 246, 3, 72, 3, 78, 86, 54, 65, 210, 2, 69, 250, 242, 3, 73, + 2, 79, 3, 85, 77, 190, 1, 68, 30, 71, 2, 75, 14, 66, 2, 72, 22, 83, 30, + 84, 30, 90, 242, 15, 82, 150, 226, 3, 67, 146, 1, 65, 2, 70, 2, 74, 2, + 76, 2, 77, 2, 78, 2, 80, 2, 81, 2, 86, 2, 87, 3, 89, 9, 38, 68, 227, 243, + 3, 72, 7, 11, 72, 5, 223, 243, 3, 72, 7, 202, 243, 3, 72, 3, 83, 7, 174, + 243, 3, 72, 3, 84, 7, 146, 243, 3, 72, 3, 90, 5, 247, 242, 3, 89, 2, 189, + 137, 3, 4, 65, 76, 73, 90, 2, 135, 177, 3, 82, 6, 76, 2, 69, 82, 21, 13, + 72, 84, 32, 84, 82, 73, 70, 79, 76, 73, 65, 84, 69, 5, 211, 180, 3, 32, + 2, 33, 6, 32, 83, 78, 79, 87, 70, 2, 167, 43, 76, 19, 11, 32, 16, 72, 8, + 79, 80, 69, 82, 65, 84, 79, 82, 229, 1, 5, 87, 73, 84, 72, 32, 11, 11, + 32, 8, 38, 65, 97, 5, 87, 73, 84, 72, 32, 4, 25, 4, 66, 79, 86, 69, 4, + 11, 32, 4, 26, 76, 231, 207, 2, 82, 2, 249, 207, 2, 2, 69, 70, 4, 26, 82, + 219, 238, 2, 68, 2, 17, 2, 73, 83, 2, 173, 161, 2, 3, 73, 78, 71, 6, 26, + 68, 183, 196, 1, 82, 4, 11, 79, 4, 207, 213, 1, 84, 6, 22, 82, 155, 98, + 83, 2, 11, 32, 2, 175, 133, 1, 67, 5, 21, 3, 32, 84, 87, 2, 21, 3, 79, + 32, 68, 2, 249, 63, 3, 79, 84, 83, 170, 1, 100, 5, 72, 85, 84, 65, 32, + 156, 9, 11, 79, 78, 73, 65, 78, 32, 83, 73, 71, 78, 32, 223, 210, 2, 69, + 164, 1, 178, 1, 65, 88, 7, 76, 69, 84, 84, 69, 82, 32, 232, 2, 2, 83, 73, + 140, 2, 11, 86, 79, 87, 69, 76, 32, 83, 73, 71, 78, 32, 142, 247, 1, 68, + 216, 149, 1, 2, 71, 86, 239, 71, 79, 4, 18, 66, 51, 78, 2, 29, 5, 66, 82, + 69, 86, 73, 2, 203, 16, 65, 2, 215, 214, 3, 74, 94, 202, 1, 65, 38, 68, + 46, 84, 46, 86, 186, 24, 85, 210, 200, 1, 73, 158, 190, 1, 78, 46, 83, + 82, 66, 2, 67, 2, 71, 2, 74, 2, 75, 2, 80, 254, 68, 72, 2, 76, 2, 77, 2, + 82, 2, 89, 186, 2, 69, 3, 79, 9, 206, 232, 3, 65, 2, 73, 3, 85, 8, 246, + 160, 3, 68, 254, 68, 72, 187, 2, 65, 8, 202, 160, 3, 84, 254, 68, 72, + 187, 2, 65, 10, 238, 3, 79, 231, 227, 3, 65, 12, 21, 3, 71, 78, 32, 12, + 42, 65, 74, 67, 98, 78, 203, 162, 3, 86, 4, 26, 86, 247, 161, 3, 78, 2, + 21, 3, 65, 71, 82, 2, 255, 238, 1, 65, 2, 11, 65, 2, 11, 78, 2, 25, 4, + 68, 82, 65, 66, 2, 11, 73, 2, 11, 78, 2, 243, 192, 3, 68, 2, 11, 85, 2, + 239, 192, 3, 75, 30, 78, 65, 38, 83, 70, 86, 214, 20, 85, 210, 200, 1, + 73, 206, 134, 2, 69, 3, 79, 6, 214, 228, 3, 65, 2, 73, 3, 85, 4, 25, 4, + 72, 79, 82, 84, 4, 11, 32, 4, 138, 228, 3, 69, 3, 79, 8, 11, 79, 8, 33, + 6, 67, 65, 76, 73, 67, 32, 8, 26, 82, 139, 231, 2, 76, 5, 163, 227, 3, + 82, 4, 128, 174, 3, 8, 67, 65, 80, 73, 84, 65, 76, 32, 227, 24, 69, 138, + 1, 210, 1, 77, 18, 78, 34, 79, 80, 2, 80, 32, 152, 9, 23, 82, 84, 79, 73, + 83, 69, 32, 83, 72, 69, 76, 76, 32, 66, 82, 65, 67, 75, 69, 84, 69, 68, + 32, 130, 4, 84, 198, 246, 1, 73, 169, 67, 5, 75, 89, 79, 32, 84, 2, 239, + 20, 65, 2, 11, 71, 2, 135, 202, 3, 85, 6, 32, 2, 84, 72, 131, 212, 2, 76, + 5, 11, 66, 2, 11, 82, 2, 239, 250, 1, 85, 40, 140, 1, 4, 65, 82, 67, 32, + 162, 2, 67, 44, 2, 72, 65, 218, 1, 80, 126, 76, 22, 82, 138, 1, 83, 38, + 84, 81, 7, 87, 73, 84, 72, 32, 85, 80, 6, 180, 1, 19, 65, 78, 84, 73, 67, + 76, 79, 67, 75, 87, 73, 83, 69, 32, 65, 82, 82, 79, 87, 73, 21, 67, 76, + 79, 67, 75, 87, 73, 83, 69, 32, 65, 82, 82, 79, 87, 32, 87, 73, 84, 72, + 32, 5, 29, 5, 32, 87, 73, 84, 72, 2, 17, 2, 32, 80, 2, 143, 218, 1, 76, + 2, 11, 77, 2, 227, 217, 1, 73, 2, 11, 85, 2, 213, 137, 3, 3, 82, 76, 89, + 12, 36, 3, 76, 70, 32, 247, 219, 3, 84, 10, 50, 66, 46, 76, 26, 82, 114, + 83, 143, 214, 1, 73, 2, 11, 76, 2, 145, 140, 2, 3, 65, 67, 75, 2, 11, 69, + 2, 35, 70, 2, 21, 3, 73, 71, 72, 2, 11, 84, 2, 17, 2, 32, 80, 2, 33, 6, + 65, 82, 69, 78, 84, 72, 2, 167, 189, 1, 69, 2, 11, 69, 2, 11, 67, 2, 11, + 84, 2, 11, 73, 2, 191, 227, 1, 79, 6, 41, 2, 69, 70, 6, 21, 3, 73, 71, + 72, 6, 17, 2, 84, 32, 6, 42, 67, 249, 133, 3, 4, 72, 65, 76, 70, 4, 26, + 79, 191, 223, 2, 82, 2, 211, 154, 3, 82, 2, 185, 133, 3, 4, 81, 85, 65, + 82, 2, 11, 79, 2, 149, 133, 3, 12, 82, 84, 79, 73, 83, 69, 32, 83, 72, + 69, 76, 76, 2, 29, 5, 87, 65, 82, 68, 83, 2, 17, 2, 32, 65, 2, 141, 218, + 2, 4, 82, 82, 79, 87, 20, 188, 1, 22, 67, 74, 75, 32, 85, 78, 73, 70, 73, + 69, 68, 32, 73, 68, 69, 79, 71, 82, 65, 80, 72, 45, 161, 2, 19, 76, 65, + 84, 73, 78, 32, 67, 65, 80, 73, 84, 65, 76, 32, 76, 69, 84, 84, 69, 18, + 40, 2, 52, 69, 34, 53, 54, 54, 87, 55, 4, 202, 1, 48, 203, 172, 2, 56, 4, + 30, 50, 141, 1, 2, 66, 56, 2, 159, 142, 3, 68, 6, 48, 2, 50, 53, 22, 53, + 249, 172, 2, 2, 55, 50, 2, 235, 211, 3, 51, 2, 67, 53, 4, 32, 2, 48, 66, + 21, 2, 54, 68, 2, 167, 211, 3, 57, 2, 147, 211, 3, 55, 2, 11, 82, 2, 163, + 149, 3, 32, 64, 48, 6, 65, 76, 32, 82, 85, 78, 21, 2, 79, 32, 2, 235, + 216, 2, 79, 62, 72, 7, 76, 69, 84, 84, 69, 82, 32, 229, 2, 6, 83, 73, 71, + 78, 32, 82, 60, 202, 1, 66, 102, 73, 22, 78, 138, 144, 1, 69, 198, 71, + 67, 170, 183, 1, 65, 222, 61, 68, 2, 71, 2, 72, 2, 74, 2, 75, 2, 76, 2, + 77, 2, 80, 2, 82, 2, 83, 2, 84, 2, 87, 2, 89, 186, 2, 79, 3, 85, 12, 52, + 7, 82, 69, 65, 84, 72, 89, 32, 203, 207, 3, 65, 10, 42, 73, 158, 144, 1, + 69, 175, 168, 2, 65, 5, 155, 207, 3, 85, 4, 206, 204, 3, 71, 187, 2, 65, + 2, 17, 2, 73, 83, 2, 21, 3, 73, 78, 71, 2, 11, 32, 2, 135, 165, 2, 84, + 98, 46, 65, 138, 2, 73, 246, 11, 79, 195, 1, 85, 16, 66, 67, 36, 2, 68, + 69, 34, 77, 32, 2, 78, 83, 243, 252, 2, 73, 4, 222, 200, 1, 75, 239, 203, + 1, 84, 2, 153, 16, 4, 32, 77, 65, 82, 5, 11, 32, 2, 175, 170, 2, 67, 4, + 44, 2, 80, 76, 33, 5, 86, 69, 82, 83, 65, 2, 11, 85, 2, 147, 173, 3, 84, + 2, 231, 48, 76, 66, 156, 1, 3, 65, 78, 71, 176, 3, 8, 68, 69, 78, 84, 32, + 69, 77, 66, 20, 9, 71, 82, 65, 77, 32, 70, 79, 82, 32, 140, 2, 4, 80, 76, + 69, 32, 255, 244, 2, 67, 16, 48, 2, 76, 69, 245, 1, 5, 85, 76, 65, 82, + 32, 10, 44, 6, 32, 87, 73, 84, 72, 32, 163, 1, 45, 8, 80, 9, 83, 69, 82, + 73, 70, 83, 32, 65, 84, 54, 85, 150, 136, 2, 82, 147, 64, 68, 2, 17, 2, + 32, 66, 2, 145, 184, 3, 3, 79, 84, 84, 2, 173, 47, 2, 78, 68, 2, 177, + 168, 2, 4, 72, 69, 65, 68, 6, 68, 9, 70, 76, 65, 71, 32, 79, 78, 32, 80, + 34, 82, 131, 235, 1, 66, 2, 11, 79, 2, 155, 171, 3, 83, 2, 11, 85, 2, + 199, 137, 3, 76, 2, 231, 180, 3, 76, 16, 66, 69, 34, 72, 34, 76, 22, 77, + 46, 84, 42, 87, 227, 179, 1, 70, 2, 11, 65, 2, 171, 199, 1, 82, 2, 11, + 69, 2, 163, 217, 1, 65, 2, 163, 150, 3, 65, 2, 21, 3, 79, 85, 78, 2, 159, + 154, 2, 84, 2, 17, 2, 72, 85, 2, 183, 161, 1, 78, 4, 198, 142, 2, 65, + 239, 40, 73, 30, 176, 2, 3, 67, 79, 76, 24, 20, 72, 79, 82, 73, 90, 79, + 78, 84, 65, 76, 32, 66, 65, 82, 32, 87, 73, 84, 72, 32, 98, 80, 34, 84, + 20, 13, 86, 69, 82, 84, 73, 67, 65, 76, 32, 66, 65, 82, 32, 44, 9, 83, + 79, 76, 73, 68, 85, 83, 32, 66, 232, 8, 2, 68, 65, 224, 168, 1, 6, 78, + 69, 83, 84, 69, 68, 163, 11, 73, 2, 145, 24, 2, 79, 78, 4, 34, 68, 33, 4, + 84, 82, 73, 80, 2, 17, 2, 79, 85, 2, 11, 66, 2, 133, 145, 3, 2, 76, 69, + 4, 218, 190, 1, 76, 143, 107, 82, 2, 171, 171, 1, 73, 8, 42, 66, 74, 68, + 198, 161, 1, 82, 111, 87, 2, 29, 5, 73, 78, 65, 82, 89, 2, 21, 3, 32, 82, + 69, 2, 251, 19, 76, 2, 25, 4, 69, 76, 73, 77, 2, 183, 137, 2, 73, 10, 24, + 2, 76, 76, 35, 80, 5, 229, 188, 1, 3, 69, 89, 66, 6, 44, 5, 73, 67, 65, + 76, 32, 191, 173, 3, 72, 4, 18, 68, 47, 70, 2, 11, 82, 2, 11, 73, 2, 191, + 187, 3, 78, 2, 167, 217, 1, 73, 6, 18, 69, 79, 77, 5, 205, 153, 3, 14, + 32, 76, 73, 71, 72, 84, 32, 77, 79, 79, 78, 32, 65, 82, 2, 195, 136, 3, + 80, 56, 80, 3, 71, 82, 73, 22, 82, 148, 165, 2, 5, 77, 66, 76, 69, 82, + 151, 150, 1, 76, 2, 255, 181, 2, 75, 50, 50, 75, 84, 4, 78, 69, 68, 32, + 171, 154, 2, 84, 4, 48, 6, 73, 83, 72, 32, 76, 73, 167, 170, 3, 69, 2, + 11, 82, 2, 247, 180, 2, 65, 44, 238, 1, 65, 80, 6, 66, 76, 65, 67, 75, + 32, 40, 7, 87, 72, 73, 84, 69, 32, 83, 22, 67, 50, 68, 96, 2, 78, 79, 32, + 2, 79, 75, 30, 83, 185, 146, 3, 21, 71, 82, 69, 69, 75, 32, 83, 77, 65, + 76, 76, 32, 76, 69, 84, 84, 69, 82, 32, 73, 79, 4, 26, 77, 147, 152, 2, + 78, 2, 17, 2, 80, 69, 2, 11, 82, 2, 179, 171, 2, 83, 4, 18, 80, 23, 83, + 2, 223, 129, 2, 69, 2, 207, 131, 2, 72, 4, 144, 3, 5, 65, 80, 73, 84, 65, + 167, 106, 79, 6, 30, 65, 33, 3, 73, 71, 73, 2, 11, 71, 2, 147, 250, 2, + 71, 4, 129, 203, 1, 3, 84, 32, 84, 6, 162, 2, 82, 183, 174, 2, 84, 2, + 177, 209, 1, 2, 32, 72, 14, 128, 1, 18, 65, 78, 83, 45, 83, 69, 82, 73, + 70, 32, 67, 65, 80, 73, 84, 65, 76, 32, 38, 69, 32, 3, 77, 65, 76, 33, 2, + 79, 85, 6, 254, 181, 3, 71, 2, 76, 3, 89, 2, 11, 77, 2, 203, 229, 2, 73, + 2, 11, 76, 2, 163, 180, 2, 32, 4, 21, 3, 84, 72, 32, 4, 32, 2, 69, 65, 1, + 2, 87, 69, 2, 53, 11, 83, 84, 32, 80, 79, 73, 78, 84, 73, 78, 71, 2, 17, + 2, 32, 76, 2, 251, 178, 2, 69, 36, 58, 69, 52, 8, 73, 83, 84, 69, 68, 32, + 82, 73, 63, 79, 2, 17, 2, 76, 86, 2, 209, 159, 1, 3, 69, 32, 80, 2, 17, + 2, 71, 72, 2, 153, 93, 6, 84, 87, 65, 82, 68, 83, 32, 30, 32, 249, 9, 2, + 45, 69, 30, 200, 2, 24, 65, 83, 84, 69, 82, 73, 83, 75, 83, 32, 65, 76, + 73, 71, 78, 69, 68, 32, 86, 69, 82, 84, 73, 67, 34, 66, 86, 67, 116, 3, + 68, 79, 84, 226, 1, 72, 44, 14, 73, 78, 84, 69, 82, 83, 69, 67, 84, 73, + 78, 71, 32, 76, 92, 6, 74, 79, 73, 78, 69, 68, 64, 8, 76, 79, 71, 73, 67, + 65, 76, 32, 98, 77, 0, 3, 87, 79, 77, 119, 83, 2, 11, 65, 2, 171, 140, 3, + 76, 2, 29, 5, 85, 84, 84, 79, 78, 2, 17, 2, 32, 77, 2, 11, 79, 2, 147, + 166, 2, 85, 2, 93, 21, 79, 78, 83, 69, 67, 85, 84, 73, 86, 69, 32, 69, + 81, 85, 65, 76, 83, 32, 83, 73, 71, 2, 195, 240, 2, 78, 6, 18, 32, 55, + 83, 4, 22, 76, 131, 1, 80, 2, 225, 137, 1, 2, 69, 65, 2, 53, 11, 32, 79, + 86, 69, 82, 32, 79, 78, 69, 32, 68, 2, 11, 79, 2, 11, 84, 2, 17, 2, 32, + 80, 2, 29, 5, 85, 78, 67, 84, 85, 2, 239, 219, 2, 65, 2, 11, 69, 2, 11, + 65, 2, 243, 151, 2, 82, 4, 17, 2, 79, 71, 4, 25, 4, 73, 67, 65, 76, 4, + 11, 32, 4, 214, 157, 2, 65, 147, 85, 79, 2, 17, 2, 32, 83, 2, 21, 3, 81, + 85, 65, 2, 139, 151, 2, 82, 4, 30, 79, 13, 3, 65, 78, 68, 2, 11, 82, 2, + 11, 32, 2, 11, 79, 2, 11, 80, 2, 183, 17, 69, 2, 11, 69, 2, 45, 9, 78, + 32, 72, 79, 76, 68, 73, 78, 71, 2, 11, 32, 2, 11, 72, 2, 11, 65, 2, 207, + 204, 1, 78, 2, 49, 10, 80, 69, 69, 67, 72, 32, 66, 85, 66, 66, 2, 239, + 148, 2, 76, 2, 11, 77, 2, 133, 195, 1, 2, 32, 68, 140, 3, 140, 1, 8, 71, + 65, 82, 73, 84, 73, 67, 32, 148, 6, 7, 77, 66, 82, 69, 76, 76, 65, 166, + 1, 78, 154, 8, 80, 174, 148, 1, 82, 135, 131, 2, 83, 62, 48, 7, 76, 69, + 84, 84, 69, 82, 32, 159, 5, 87, 60, 206, 1, 65, 28, 2, 81, 79, 22, 66, + 22, 68, 50, 71, 44, 2, 72, 79, 22, 75, 34, 76, 32, 2, 82, 65, 22, 83, 74, + 84, 74, 89, 22, 90, 186, 161, 2, 78, 178, 91, 80, 246, 5, 87, 202, 12, + 77, 174, 18, 73, 3, 85, 4, 26, 76, 143, 213, 2, 73, 2, 167, 162, 3, 80, + 2, 255, 255, 2, 69, 4, 26, 69, 247, 154, 2, 72, 2, 207, 255, 2, 76, 4, + 214, 248, 1, 72, 153, 137, 1, 2, 65, 77, 5, 163, 161, 3, 84, 4, 186, 162, + 2, 65, 215, 126, 72, 2, 11, 65, 2, 151, 254, 2, 77, 2, 203, 171, 1, 83, + 8, 38, 65, 146, 163, 2, 72, 215, 90, 83, 4, 246, 139, 3, 68, 239, 13, 77, + 6, 38, 72, 218, 133, 3, 69, 175, 28, 79, 2, 11, 65, 2, 179, 231, 1, 78, + 2, 207, 219, 2, 79, 4, 130, 253, 2, 69, 207, 36, 85, 2, 21, 3, 79, 82, + 68, 2, 25, 4, 32, 68, 73, 86, 2, 139, 125, 73, 7, 11, 32, 4, 84, 4, 79, + 78, 32, 71, 45, 13, 87, 73, 84, 72, 32, 82, 65, 73, 78, 32, 68, 82, 79, + 2, 11, 82, 2, 11, 79, 2, 143, 146, 2, 85, 2, 139, 226, 2, 80, 32, 160, 1, + 3, 65, 77, 85, 20, 7, 67, 69, 82, 84, 65, 73, 78, 34, 68, 62, 73, 241, 5, + 18, 77, 65, 82, 82, 73, 69, 68, 32, 80, 65, 82, 84, 78, 69, 82, 83, 72, + 73, 2, 227, 141, 2, 83, 2, 11, 84, 2, 155, 151, 2, 89, 4, 26, 69, 199, + 138, 2, 79, 2, 11, 82, 2, 151, 130, 3, 84, 22, 60, 2, 79, 78, 230, 3, 84, + 106, 86, 201, 43, 3, 67, 79, 82, 15, 11, 32, 12, 160, 1, 6, 65, 66, 79, + 86, 69, 32, 108, 22, 66, 69, 83, 73, 68, 69, 32, 65, 78, 68, 32, 74, 79, + 73, 78, 69, 68, 32, 87, 73, 84, 72, 41, 5, 87, 73, 84, 72, 32, 4, 52, 9, + 66, 65, 82, 32, 65, 66, 79, 86, 69, 23, 73, 2, 17, 2, 32, 73, 2, 229, 39, + 4, 78, 84, 69, 82, 2, 17, 2, 32, 85, 2, 139, 202, 2, 78, 6, 66, 77, 58, + 79, 217, 224, 2, 8, 76, 79, 71, 73, 67, 65, 76, 32, 2, 11, 73, 2, 11, 78, + 2, 11, 85, 2, 223, 146, 2, 83, 2, 11, 86, 2, 229, 73, 2, 69, 82, 4, 18, + 32, 67, 69, 2, 11, 83, 2, 17, 2, 69, 80, 2, 11, 65, 2, 219, 223, 2, 82, + 2, 171, 133, 2, 68, 2, 57, 12, 69, 82, 83, 65, 76, 32, 82, 69, 67, 89, + 67, 76, 2, 17, 2, 73, 78, 2, 199, 132, 2, 71, 2, 179, 132, 2, 80, 164, 2, + 170, 1, 32, 128, 8, 10, 45, 80, 79, 73, 78, 84, 73, 78, 71, 32, 248, 3, + 4, 80, 69, 82, 32, 168, 29, 8, 83, 73, 68, 69, 45, 68, 79, 87, 21, 6, 87, + 65, 82, 68, 83, 32, 38, 140, 1, 5, 65, 82, 82, 79, 87, 240, 1, 5, 66, 65, + 82, 66, 32, 228, 1, 5, 68, 79, 87, 78, 32, 210, 1, 70, 30, 82, 89, 4, 84, + 65, 67, 75, 8, 60, 7, 32, 84, 72, 82, 79, 85, 71, 21, 4, 72, 69, 65, 68, + 2, 143, 197, 1, 72, 7, 11, 32, 4, 112, 22, 66, 69, 84, 87, 69, 69, 78, + 32, 84, 87, 79, 32, 72, 79, 82, 73, 90, 79, 78, 84, 65, 76, 159, 134, 2, + 73, 2, 181, 254, 1, 2, 32, 66, 8, 44, 3, 76, 69, 70, 1, 4, 82, 73, 71, + 72, 4, 57, 12, 84, 32, 68, 79, 87, 78, 32, 66, 65, 82, 66, 32, 4, 44, 3, + 76, 69, 70, 1, 4, 82, 73, 71, 72, 2, 11, 84, 2, 25, 4, 32, 72, 65, 82, 2, + 11, 80, 2, 207, 193, 2, 79, 14, 76, 5, 65, 82, 82, 79, 87, 62, 66, 38, + 68, 18, 83, 202, 43, 87, 215, 9, 84, 5, 37, 7, 32, 87, 73, 84, 72, 32, + 66, 2, 175, 135, 2, 65, 2, 209, 245, 1, 4, 76, 65, 67, 75, 2, 147, 44, + 79, 2, 131, 50, 65, 2, 11, 73, 2, 155, 98, 83, 2, 53, 11, 73, 71, 72, 84, + 32, 68, 73, 65, 71, 79, 78, 2, 225, 113, 4, 65, 76, 32, 69, 5, 29, 5, 32, + 87, 73, 84, 72, 2, 33, 6, 32, 67, 73, 82, 67, 76, 2, 159, 145, 2, 69, 14, + 96, 8, 77, 73, 76, 73, 84, 65, 82, 89, 20, 6, 83, 77, 65, 76, 76, 32, 22, + 65, 66, 82, 35, 84, 2, 37, 2, 32, 65, 4, 18, 65, 67, 82, 2, 11, 73, 2, + 11, 82, 2, 17, 2, 80, 76, 2, 179, 243, 1, 65, 2, 11, 69, 2, 199, 232, 1, + 68, 4, 37, 7, 82, 73, 65, 78, 71, 76, 69, 4, 11, 32, 4, 11, 87, 4, 25, 4, + 73, 84, 72, 32, 4, 18, 76, 27, 82, 2, 11, 69, 2, 35, 70, 2, 21, 3, 73, + 71, 72, 2, 11, 84, 2, 17, 2, 32, 72, 2, 21, 3, 65, 76, 70, 2, 17, 2, 32, + 66, 2, 11, 76, 2, 207, 219, 1, 65, 110, 172, 1, 4, 65, 78, 68, 32, 186, + 2, 66, 74, 70, 36, 5, 72, 65, 76, 70, 32, 148, 3, 5, 76, 69, 70, 84, 32, + 226, 5, 79, 60, 6, 82, 73, 71, 72, 84, 32, 218, 12, 83, 63, 84, 8, 34, + 76, 53, 4, 82, 73, 71, 72, 6, 48, 2, 69, 70, 149, 1, 5, 79, 87, 69, 82, + 32, 2, 53, 11, 84, 32, 65, 78, 68, 32, 76, 79, 87, 69, 82, 2, 217, 25, + 19, 32, 84, 82, 73, 65, 78, 71, 85, 76, 65, 82, 32, 84, 72, 82, 69, 69, + 32, 81, 4, 28, 2, 84, 82, 179, 29, 79, 2, 205, 3, 7, 73, 65, 78, 71, 85, + 76, 65, 2, 17, 2, 76, 65, 2, 17, 2, 68, 69, 2, 177, 208, 1, 3, 32, 83, + 67, 2, 17, 2, 73, 86, 2, 191, 22, 69, 12, 96, 5, 66, 76, 79, 67, 75, 108, + 8, 73, 78, 86, 69, 82, 83, 69, 32, 254, 19, 77, 227, 160, 1, 67, 5, 209, + 20, 23, 32, 65, 78, 68, 32, 76, 79, 87, 69, 82, 32, 72, 65, 76, 70, 32, + 73, 78, 86, 69, 82, 83, 69, 4, 100, 21, 77, 69, 68, 73, 85, 77, 32, 83, + 72, 65, 68, 69, 32, 65, 78, 68, 32, 76, 79, 87, 69, 51, 87, 2, 11, 82, 2, + 141, 26, 5, 32, 72, 65, 76, 70, 2, 21, 3, 72, 73, 84, 2, 147, 179, 1, 69, + 34, 106, 66, 238, 3, 67, 54, 84, 176, 9, 13, 79, 82, 32, 76, 79, 87, 69, + 82, 32, 82, 73, 71, 72, 143, 1, 81, 22, 65, 14, 76, 79, 67, 75, 32, 68, + 73, 65, 71, 79, 78, 65, 76, 32, 22, 144, 1, 6, 76, 79, 87, 69, 82, 32, + 173, 6, 24, 85, 80, 80, 69, 82, 32, 77, 73, 68, 68, 76, 69, 32, 76, 69, + 70, 84, 32, 84, 79, 32, 85, 80, 80, 18, 176, 1, 10, 67, 69, 78, 84, 82, + 69, 32, 84, 79, 32, 36, 8, 76, 69, 70, 84, 32, 84, 79, 32, 169, 8, 18, + 77, 73, 68, 68, 76, 69, 32, 76, 69, 70, 84, 32, 84, 79, 32, 85, 80, 80, + 6, 70, 76, 193, 6, 3, 85, 80, 80, 6, 34, 76, 153, 7, 3, 85, 80, 80, 2, + 217, 7, 2, 79, 87, 2, 29, 5, 79, 82, 78, 69, 82, 2, 139, 218, 1, 32, 6, + 22, 79, 187, 12, 82, 2, 129, 12, 11, 32, 76, 79, 87, 69, 82, 32, 82, 73, + 71, 72, 4, 11, 78, 4, 17, 2, 69, 32, 4, 150, 15, 81, 139, 4, 69, 40, 128, + 1, 2, 66, 76, 186, 6, 68, 100, 12, 79, 82, 32, 76, 79, 87, 69, 82, 32, + 76, 69, 70, 106, 80, 38, 81, 104, 2, 83, 72, 51, 84, 22, 61, 13, 79, 67, + 75, 32, 68, 73, 65, 71, 79, 78, 65, 76, 32, 22, 140, 1, 24, 76, 79, 87, + 69, 82, 32, 77, 73, 68, 68, 76, 69, 32, 76, 69, 70, 84, 32, 84, 79, 32, + 76, 79, 87, 57, 6, 85, 80, 80, 69, 82, 32, 4, 21, 3, 69, 82, 32, 4, 246, + 3, 67, 211, 202, 2, 82, 18, 176, 1, 10, 67, 69, 78, 84, 82, 69, 32, 84, + 79, 32, 92, 8, 76, 69, 70, 84, 32, 84, 79, 32, 141, 1, 18, 77, 73, 68, + 68, 76, 69, 32, 76, 69, 70, 84, 32, 84, 79, 32, 76, 79, 87, 6, 32, 3, 76, + 79, 87, 139, 1, 85, 4, 21, 3, 69, 82, 32, 4, 142, 2, 77, 171, 202, 2, 82, + 6, 28, 3, 76, 79, 87, 51, 85, 4, 21, 3, 69, 82, 32, 4, 142, 1, 67, 43, + 77, 2, 17, 2, 80, 80, 2, 17, 2, 69, 82, 2, 117, 2, 32, 77, 6, 21, 3, 69, + 82, 32, 6, 34, 67, 42, 77, 171, 202, 2, 82, 2, 11, 69, 2, 241, 212, 1, 2, + 78, 84, 2, 25, 4, 73, 68, 68, 76, 2, 203, 166, 1, 69, 2, 65, 14, 82, 79, + 80, 45, 83, 72, 65, 68, 79, 87, 69, 68, 32, 87, 2, 225, 181, 1, 3, 72, + 73, 84, 2, 69, 15, 84, 32, 67, 85, 82, 76, 89, 32, 66, 82, 65, 67, 75, + 69, 84, 2, 11, 32, 2, 179, 162, 2, 83, 2, 11, 69, 2, 249, 69, 2, 78, 67, + 2, 81, 18, 85, 65, 68, 82, 65, 78, 84, 32, 67, 73, 82, 67, 85, 76, 65, + 82, 32, 65, 2, 163, 203, 1, 82, 4, 245, 97, 8, 65, 68, 79, 87, 69, 68, + 32, 87, 6, 18, 79, 107, 82, 2, 49, 10, 32, 76, 79, 87, 69, 82, 32, 76, + 69, 70, 2, 11, 84, 2, 11, 32, 2, 11, 70, 2, 163, 108, 73, 4, 25, 4, 73, + 65, 78, 71, 4, 40, 4, 85, 76, 65, 82, 171, 217, 2, 76, 2, 17, 2, 32, 77, + 2, 41, 8, 69, 68, 73, 85, 77, 32, 83, 72, 2, 199, 98, 65, 2, 17, 2, 69, + 86, 2, 17, 2, 69, 78, 2, 117, 2, 32, 69, 6, 52, 2, 72, 82, 129, 1, 6, 82, + 73, 65, 78, 71, 85, 4, 21, 3, 69, 69, 32, 4, 18, 69, 35, 81, 2, 65, 5, + 73, 71, 72, 84, 72, 2, 33, 6, 85, 65, 82, 84, 69, 82, 2, 231, 4, 83, 2, + 45, 9, 76, 65, 82, 32, 79, 78, 69, 32, 81, 2, 165, 4, 6, 85, 65, 82, 84, + 69, 82, 2, 203, 175, 2, 78, 128, 1, 146, 1, 65, 174, 6, 66, 154, 1, 68, + 50, 70, 82, 72, 146, 4, 67, 46, 81, 42, 82, 22, 83, 102, 84, 142, 7, 80, + 173, 3, 6, 87, 72, 73, 84, 69, 32, 32, 34, 78, 33, 4, 82, 82, 79, 87, 2, + 11, 67, 2, 207, 166, 2, 79, 31, 11, 32, 28, 134, 1, 65, 180, 1, 14, 76, + 69, 70, 84, 87, 65, 82, 68, 83, 32, 79, 70, 32, 68, 32, 5, 87, 73, 84, + 72, 32, 214, 8, 70, 175, 5, 84, 2, 41, 8, 78, 68, 32, 82, 73, 71, 72, 84, + 2, 17, 2, 32, 79, 2, 25, 4, 78, 69, 32, 69, 2, 29, 5, 73, 71, 72, 84, 72, + 2, 11, 32, 2, 11, 66, 2, 11, 76, 2, 239, 185, 1, 79, 2, 233, 200, 1, 3, + 79, 87, 78, 20, 74, 68, 58, 76, 42, 77, 38, 78, 58, 83, 66, 69, 246, 12, + 84, 139, 59, 72, 2, 21, 3, 79, 85, 66, 2, 11, 76, 2, 131, 183, 2, 69, 2, + 11, 65, 2, 233, 23, 3, 82, 71, 69, 2, 205, 23, 5, 69, 68, 73, 85, 77, 2, + 25, 4, 79, 84, 67, 72, 2, 11, 69, 2, 247, 56, 68, 4, 11, 77, 4, 25, 4, + 65, 76, 76, 32, 4, 22, 69, 203, 22, 84, 2, 237, 22, 10, 81, 85, 73, 76, + 65, 84, 69, 82, 65, 76, 4, 11, 76, 4, 25, 4, 65, 67, 75, 32, 4, 44, 5, + 67, 73, 82, 67, 76, 143, 202, 1, 65, 2, 25, 4, 69, 68, 32, 87, 2, 11, 72, + 2, 229, 14, 2, 73, 84, 4, 22, 79, 187, 13, 65, 2, 169, 14, 2, 85, 66, 2, + 11, 73, 2, 37, 7, 78, 71, 69, 82, 45, 80, 79, 2, 205, 200, 1, 2, 83, 84, + 20, 88, 17, 65, 82, 80, 79, 79, 78, 32, 87, 73, 84, 72, 32, 66, 65, 82, + 66, 32, 255, 2, 69, 16, 56, 4, 76, 69, 70, 84, 245, 1, 5, 82, 73, 71, 72, + 84, 10, 22, 32, 231, 9, 87, 8, 60, 7, 66, 69, 83, 73, 68, 69, 32, 206, 1, + 70, 175, 5, 84, 4, 40, 4, 68, 79, 87, 78, 1, 2, 85, 80, 2, 193, 146, 1, + 23, 87, 65, 82, 68, 83, 32, 72, 65, 82, 80, 79, 79, 78, 32, 87, 73, 84, + 72, 32, 66, 65, 82, 66, 6, 22, 32, 243, 7, 87, 4, 22, 70, 175, 5, 84, 2, + 229, 15, 3, 82, 79, 77, 4, 25, 4, 65, 86, 89, 32, 4, 26, 67, 191, 196, 1, + 65, 2, 185, 10, 7, 79, 77, 80, 82, 69, 83, 83, 2, 133, 9, 6, 85, 65, 68, + 82, 85, 80, 2, 195, 139, 2, 79, 4, 30, 65, 53, 3, 81, 85, 65, 2, 153, + 195, 1, 8, 78, 83, 45, 83, 69, 82, 73, 70, 2, 255, 8, 82, 36, 36, 2, 82, + 73, 225, 7, 2, 87, 79, 30, 40, 5, 65, 78, 71, 76, 69, 151, 7, 80, 28, 52, + 8, 45, 72, 69, 65, 68, 69, 68, 32, 199, 13, 32, 26, 48, 5, 65, 82, 82, + 79, 87, 170, 5, 68, 39, 80, 23, 11, 32, 20, 92, 17, 76, 69, 70, 84, 87, + 65, 82, 68, 83, 32, 79, 70, 32, 68, 79, 87, 78, 98, 84, 19, 87, 2, 37, 7, + 87, 65, 82, 68, 83, 32, 84, 2, 37, 7, 82, 73, 65, 78, 71, 76, 69, 2, 215, + 5, 45, 2, 187, 10, 79, 16, 25, 4, 73, 84, 72, 32, 16, 114, 66, 28, 6, 76, + 79, 78, 71, 32, 84, 130, 1, 77, 34, 78, 34, 86, 34, 72, 149, 57, 6, 68, + 79, 85, 66, 76, 69, 2, 149, 2, 3, 79, 76, 68, 4, 17, 2, 73, 80, 4, 11, + 32, 4, 34, 76, 21, 4, 82, 73, 71, 72, 2, 17, 2, 69, 70, 2, 11, 84, 2, 11, + 87, 2, 135, 123, 65, 2, 121, 5, 69, 68, 73, 85, 77, 2, 89, 5, 65, 82, 82, + 79, 87, 2, 29, 5, 69, 82, 89, 32, 72, 2, 25, 4, 69, 65, 86, 89, 2, 237, + 171, 2, 4, 32, 83, 72, 65, 2, 11, 65, 2, 249, 1, 2, 83, 72, 2, 11, 65, 2, + 25, 4, 73, 82, 69, 68, 2, 29, 5, 32, 65, 82, 82, 79, 2, 239, 151, 2, 87, + 2, 11, 76, 2, 227, 186, 1, 69, 6, 74, 32, 61, 14, 45, 72, 69, 65, 68, 69, + 68, 32, 65, 82, 82, 79, 87, 32, 2, 25, 4, 72, 69, 65, 68, 2, 11, 69, 2, + 219, 185, 1, 68, 4, 42, 87, 129, 132, 1, 4, 70, 82, 79, 77, 2, 33, 6, 73, + 84, 72, 32, 84, 82, 2, 61, 13, 73, 65, 78, 71, 76, 69, 32, 65, 82, 82, + 79, 87, 72, 2, 169, 118, 2, 69, 65, 18, 88, 5, 65, 82, 82, 79, 87, 133, + 4, 12, 68, 79, 85, 66, 76, 69, 32, 65, 82, 82, 79, 87, 15, 11, 32, 12, + 104, 8, 70, 82, 79, 77, 32, 66, 65, 82, 40, 11, 79, 78, 32, 80, 69, 68, + 69, 83, 84, 65, 76, 183, 1, 87, 5, 93, 7, 32, 87, 73, 84, 72, 32, 72, 7, + 33, 6, 32, 87, 73, 84, 72, 32, 4, 18, 72, 43, 86, 2, 69, 7, 79, 82, 73, + 90, 79, 78, 84, 2, 29, 5, 69, 82, 84, 73, 67, 2, 17, 2, 65, 76, 2, 11, + 32, 2, 151, 173, 1, 66, 2, 29, 5, 73, 84, 72, 73, 78, 2, 17, 2, 32, 84, + 2, 37, 7, 82, 73, 65, 78, 71, 76, 69, 2, 11, 32, 2, 11, 65, 2, 25, 4, 82, + 82, 79, 87, 2, 11, 72, 2, 239, 135, 2, 69, 5, 45, 9, 32, 79, 78, 32, 80, + 69, 68, 69, 83, 2, 163, 196, 1, 84, 226, 15, 86, 65, 254, 16, 83, 174, 3, + 69, 162, 42, 73, 178, 8, 79, 134, 2, 84, 21, 2, 85, 76, 218, 8, 116, 2, + 73, 32, 128, 16, 17, 82, 73, 65, 84, 73, 79, 78, 32, 83, 69, 76, 69, 67, + 84, 79, 82, 45, 173, 42, 2, 77, 80, 216, 4, 54, 67, 34, 70, 82, 81, 40, + 2, 83, 89, 243, 91, 68, 2, 11, 79, 2, 135, 170, 2, 77, 2, 11, 85, 2, 11, + 76, 2, 11, 76, 2, 11, 32, 2, 11, 83, 2, 195, 209, 1, 84, 2, 17, 2, 85, + 69, 2, 135, 225, 1, 83, 190, 4, 68, 7, 76, 76, 65, 66, 76, 69, 32, 197, + 11, 5, 77, 66, 79, 76, 32, 164, 4, 214, 1, 68, 70, 66, 2, 83, 2, 84, 2, + 90, 70, 71, 122, 72, 82, 75, 134, 1, 76, 130, 1, 77, 86, 78, 134, 3, 67, + 2, 70, 2, 74, 2, 80, 2, 82, 2, 86, 2, 89, 78, 87, 50, 69, 34, 79, 158, + 70, 65, 2, 73, 3, 85, 42, 66, 72, 162, 8, 79, 238, 254, 1, 69, 150, 64, + 65, 2, 73, 3, 85, 28, 230, 7, 72, 58, 79, 238, 254, 1, 69, 150, 64, 65, + 2, 73, 3, 85, 34, 62, 66, 202, 6, 69, 86, 79, 130, 191, 2, 65, 2, 73, 3, + 85, 18, 106, 79, 222, 5, 69, 214, 191, 2, 65, 2, 73, 3, 85, 24, 50, 79, + 222, 5, 69, 214, 71, 65, 2, 73, 3, 85, 7, 174, 197, 2, 78, 3, 79, 34, 70, + 80, 206, 5, 79, 130, 71, 65, 238, 183, 1, 69, 150, 64, 73, 3, 85, 18, + 246, 4, 69, 86, 79, 130, 71, 65, 130, 248, 1, 73, 3, 85, 16, 54, 69, 218, + 4, 79, 130, 191, 2, 65, 2, 73, 3, 85, 7, 26, 78, 191, 195, 2, 69, 2, 21, + 3, 71, 84, 72, 2, 183, 133, 2, 69, 42, 214, 3, 66, 0, 2, 71, 66, 58, 79, + 238, 254, 1, 69, 150, 64, 65, 2, 73, 3, 85, 90, 90, 68, 174, 1, 71, 126, + 74, 2, 89, 58, 79, 238, 254, 1, 69, 150, 64, 65, 2, 73, 3, 85, 24, 54, + 79, 150, 129, 2, 69, 150, 64, 65, 2, 73, 3, 85, 15, 36, 3, 76, 69, 32, + 131, 193, 2, 79, 10, 54, 83, 214, 161, 2, 68, 190, 28, 70, 2, 75, 3, 77, + 2, 211, 161, 2, 79, 25, 42, 71, 182, 240, 1, 65, 2, 69, 3, 79, 16, 50, + 69, 86, 79, 130, 191, 2, 65, 2, 73, 3, 85, 7, 210, 191, 2, 69, 3, 78, 14, + 54, 79, 238, 254, 1, 69, 150, 64, 65, 2, 73, 3, 85, 5, 255, 190, 2, 79, + 28, 46, 69, 34, 79, 158, 70, 65, 2, 73, 3, 85, 9, 186, 70, 69, 131, 248, + 1, 78, 9, 154, 70, 79, 131, 248, 1, 78, 26, 66, 68, 62, 70, 30, 74, 22, + 75, 50, 78, 22, 84, 199, 227, 1, 66, 6, 26, 79, 179, 236, 1, 65, 4, 174, + 236, 1, 79, 251, 49, 45, 4, 74, 69, 251, 185, 2, 65, 2, 243, 235, 1, 79, + 4, 26, 69, 199, 235, 1, 85, 2, 195, 235, 1, 69, 2, 195, 168, 2, 73, 6, + 154, 235, 1, 73, 2, 79, 183, 78, 65, 128, 4, 74, 49, 94, 50, 98, 51, 2, + 52, 2, 53, 2, 54, 2, 55, 2, 56, 3, 57, 223, 1, 182, 1, 48, 2, 49, 2, 50, + 2, 51, 2, 52, 2, 53, 2, 54, 2, 55, 2, 56, 3, 57, 137, 1, 90, 48, 2, 49, + 2, 50, 2, 51, 2, 52, 94, 53, 250, 184, 2, 54, 2, 55, 2, 56, 3, 57, 23, + 210, 185, 2, 48, 2, 49, 2, 50, 2, 51, 2, 52, 2, 53, 2, 54, 2, 55, 2, 56, + 3, 57, 17, 246, 184, 2, 48, 2, 49, 2, 50, 2, 51, 2, 52, 2, 53, 3, 54, + 180, 1, 116, 4, 68, 73, 67, 32, 222, 19, 82, 208, 148, 1, 13, 67, 84, 79, + 82, 32, 79, 82, 32, 67, 82, 79, 83, 83, 195, 106, 83, 86, 60, 5, 83, 73, + 71, 78, 32, 153, 10, 5, 84, 79, 78, 69, 32, 48, 218, 2, 65, 216, 1, 17, + 68, 79, 85, 66, 76, 69, 32, 65, 78, 85, 83, 86, 65, 82, 65, 32, 65, 98, + 74, 52, 6, 78, 73, 72, 83, 72, 86, 22, 82, 240, 1, 8, 72, 69, 88, 73, 70, + 79, 82, 77, 22, 76, 52, 4, 84, 73, 82, 89, 22, 85, 60, 8, 86, 73, 83, 65, + 82, 71, 65, 32, 237, 6, 17, 89, 65, 74, 85, 82, 86, 69, 68, 73, 67, 32, + 77, 73, 68, 76, 73, 78, 14, 76, 8, 78, 85, 83, 86, 65, 82, 65, 32, 212, + 1, 3, 84, 73, 75, 151, 2, 82, 10, 134, 1, 65, 24, 4, 66, 65, 72, 73, 24, + 9, 85, 66, 72, 65, 89, 65, 84, 79, 32, 201, 4, 10, 86, 65, 77, 65, 71, + 79, 77, 85, 75, 72, 2, 21, 3, 78, 84, 65, 2, 21, 3, 82, 71, 79, 2, 11, + 77, 2, 163, 9, 85, 2, 151, 239, 1, 82, 2, 33, 6, 73, 72, 86, 65, 77, 85, + 2, 151, 3, 76, 2, 235, 174, 2, 65, 8, 144, 1, 15, 69, 86, 69, 82, 83, 69, + 68, 32, 86, 73, 83, 65, 82, 71, 65, 36, 9, 79, 84, 65, 84, 69, 68, 32, + 65, 82, 57, 5, 84, 72, 65, 78, 71, 4, 11, 32, 4, 218, 6, 65, 23, 85, 2, + 25, 4, 68, 72, 65, 86, 2, 245, 236, 1, 2, 73, 83, 2, 17, 2, 32, 76, 2, + 21, 3, 79, 78, 71, 2, 145, 234, 1, 2, 32, 65, 2, 203, 171, 2, 65, 2, 37, + 7, 80, 65, 68, 72, 77, 65, 78, 2, 203, 171, 2, 73, 10, 40, 3, 65, 78, 85, + 2, 85, 179, 9, 83, 4, 25, 4, 68, 65, 84, 84, 4, 11, 65, 5, 25, 4, 32, 87, + 73, 84, 2, 11, 72, 2, 11, 32, 2, 11, 84, 2, 11, 65, 2, 215, 163, 1, 73, + 38, 128, 2, 5, 67, 65, 78, 68, 82, 16, 2, 68, 79, 96, 2, 75, 65, 136, 1, + 4, 80, 82, 69, 78, 16, 2, 82, 73, 106, 84, 164, 1, 11, 89, 65, 74, 85, + 82, 86, 69, 68, 73, 67, 32, 180, 1, 12, 65, 84, 72, 65, 82, 86, 65, 86, + 69, 68, 73, 67, 213, 224, 1, 2, 83, 72, 4, 251, 17, 65, 6, 40, 5, 85, 66, + 76, 69, 32, 191, 3, 84, 4, 22, 82, 211, 5, 83, 2, 11, 73, 2, 251, 1, 78, + 4, 56, 3, 82, 83, 72, 17, 7, 84, 72, 65, 75, 65, 32, 65, 2, 235, 110, 65, + 2, 17, 2, 78, 85, 2, 17, 2, 68, 65, 2, 171, 132, 2, 84, 2, 167, 49, 75, + 4, 82, 78, 237, 2, 15, 71, 86, 69, 68, 73, 67, 32, 75, 65, 83, 72, 77, + 73, 82, 73, 2, 139, 171, 1, 71, 6, 42, 72, 24, 4, 82, 73, 80, 76, 19, 87, + 2, 49, 3, 82, 69, 69, 2, 219, 2, 69, 2, 11, 79, 2, 25, 4, 32, 68, 79, 84, + 2, 11, 83, 2, 11, 32, 2, 159, 14, 66, 8, 176, 1, 10, 65, 71, 71, 82, 65, + 86, 65, 84, 69, 68, 22, 73, 105, 27, 75, 65, 84, 72, 65, 75, 65, 32, 73, + 78, 68, 69, 80, 69, 78, 68, 69, 78, 84, 32, 83, 86, 65, 82, 73, 84, 65, + 2, 17, 2, 32, 73, 2, 49, 10, 78, 68, 69, 80, 69, 78, 68, 69, 78, 84, 2, + 17, 2, 32, 83, 2, 221, 255, 1, 3, 86, 65, 82, 5, 37, 7, 32, 83, 67, 72, + 82, 79, 69, 2, 143, 230, 1, 68, 90, 62, 83, 16, 6, 84, 73, 67, 65, 76, + 32, 221, 13, 2, 89, 32, 2, 171, 84, 73, 62, 208, 2, 4, 66, 65, 82, 32, + 166, 3, 69, 62, 70, 36, 11, 73, 68, 69, 79, 71, 82, 65, 80, 72, 73, 67, + 48, 12, 75, 65, 78, 65, 32, 82, 69, 80, 69, 65, 84, 32, 252, 1, 4, 76, + 73, 78, 69, 238, 1, 77, 88, 17, 79, 78, 69, 32, 69, 73, 71, 72, 84, 72, + 32, 66, 76, 79, 67, 75, 45, 62, 84, 192, 73, 3, 83, 73, 88, 241, 32, 5, + 90, 73, 71, 90, 65, 8, 108, 6, 66, 69, 83, 73, 68, 69, 60, 8, 68, 79, 85, + 66, 76, 69, 32, 76, 20, 4, 84, 82, 73, 80, 139, 1, 87, 2, 17, 2, 32, 82, + 2, 21, 3, 73, 71, 72, 2, 187, 123, 84, 2, 69, 2, 69, 70, 2, 25, 4, 76, + 69, 32, 82, 2, 21, 3, 73, 71, 72, 2, 11, 84, 2, 29, 5, 32, 84, 85, 82, + 78, 2, 11, 83, 2, 11, 84, 2, 219, 124, 73, 2, 21, 3, 73, 84, 72, 2, 17, + 2, 32, 72, 2, 153, 237, 1, 7, 79, 82, 73, 90, 79, 78, 84, 2, 25, 4, 76, + 76, 73, 80, 2, 11, 83, 2, 155, 223, 1, 73, 2, 11, 79, 2, 129, 79, 2, 85, + 82, 2, 17, 2, 32, 73, 2, 237, 178, 1, 2, 84, 69, 10, 120, 4, 77, 65, 82, + 75, 45, 22, 87, 73, 84, 72, 32, 86, 79, 73, 67, 69, 68, 32, 83, 79, 85, + 78, 68, 32, 77, 65, 82, 75, 7, 11, 32, 4, 50, 85, 21, 3, 76, 79, 87, 5, + 17, 2, 32, 85, 2, 17, 2, 80, 80, 2, 17, 2, 69, 82, 2, 129, 26, 2, 32, 72, + 11, 11, 32, 8, 38, 69, 49, 5, 87, 73, 84, 72, 32, 2, 25, 4, 88, 84, 69, + 78, 2, 255, 200, 1, 83, 6, 40, 4, 67, 73, 82, 67, 207, 135, 1, 77, 4, 11, + 76, 4, 11, 69, 4, 11, 32, 4, 26, 66, 223, 155, 1, 65, 2, 11, 69, 2, 159, + 126, 76, 2, 65, 14, 65, 76, 69, 32, 87, 73, 84, 72, 32, 83, 84, 82, 79, + 75, 2, 239, 144, 1, 69, 12, 194, 151, 2, 50, 2, 51, 2, 52, 2, 53, 2, 54, + 3, 55, 10, 32, 2, 65, 66, 106, 73, 19, 82, 6, 18, 32, 35, 85, 2, 11, 75, + 2, 251, 132, 2, 69, 4, 33, 6, 76, 65, 84, 73, 79, 78, 5, 199, 45, 32, 2, + 135, 9, 76, 2, 29, 5, 65, 70, 70, 73, 67, 2, 249, 234, 1, 2, 32, 76, 26, + 80, 6, 72, 69, 65, 86, 89, 32, 176, 5, 3, 77, 85, 67, 233, 9, 3, 66, 79, + 76, 20, 62, 69, 190, 1, 70, 38, 82, 82, 83, 246, 1, 87, 207, 10, 71, 4, + 25, 4, 73, 71, 72, 84, 4, 11, 32, 4, 22, 80, 223, 2, 83, 2, 25, 4, 79, + 73, 78, 84, 2, 17, 2, 69, 68, 2, 17, 2, 32, 66, 2, 25, 4, 76, 65, 67, 75, + 2, 11, 32, 2, 139, 79, 83, 2, 11, 73, 2, 185, 1, 2, 86, 69, 2, 11, 69, 2, + 29, 5, 86, 69, 82, 83, 69, 2, 17, 2, 32, 83, 2, 231, 1, 79, 6, 30, 65, + 42, 73, 147, 1, 79, 2, 11, 76, 2, 11, 84, 2, 147, 113, 73, 2, 11, 88, 2, + 11, 32, 2, 11, 83, 2, 21, 3, 80, 79, 75, 2, 17, 2, 69, 68, 2, 11, 32, 2, + 11, 65, 2, 11, 83, 2, 129, 78, 3, 84, 69, 82, 2, 165, 13, 3, 76, 73, 68, + 4, 21, 3, 72, 73, 84, 4, 11, 69, 4, 11, 32, 4, 190, 64, 67, 199, 46, 83, + 4, 11, 72, 4, 11, 32, 4, 18, 71, 39, 76, 2, 69, 6, 82, 69, 65, 84, 69, + 82, 2, 11, 69, 2, 11, 83, 2, 11, 83, 2, 17, 2, 45, 84, 2, 239, 70, 72, + 160, 1, 140, 1, 9, 66, 82, 65, 84, 73, 79, 78, 32, 77, 34, 67, 32, 3, 68, + 69, 79, 126, 69, 218, 1, 79, 22, 82, 21, 7, 84, 72, 75, 85, 81, 73, 32, + 2, 11, 79, 2, 159, 246, 1, 68, 2, 221, 126, 4, 84, 79, 82, 89, 6, 30, 32, + 77, 3, 67, 65, 83, 4, 18, 67, 43, 71, 2, 17, 2, 65, 77, 2, 195, 199, 1, + 69, 2, 143, 116, 65, 2, 147, 71, 83, 6, 168, 1, 31, 84, 78, 65, 77, 69, + 83, 69, 32, 65, 76, 84, 69, 82, 78, 65, 84, 69, 32, 82, 69, 65, 68, 73, + 78, 71, 32, 77, 65, 82, 75, 32, 193, 105, 5, 87, 68, 65, 84, 65, 4, 26, + 78, 199, 135, 2, 67, 2, 143, 126, 72, 2, 175, 138, 1, 76, 2, 227, 234, 1, + 71, 140, 1, 56, 6, 67, 65, 80, 73, 84, 65, 1, 4, 83, 77, 65, 76, 70, 45, + 9, 76, 32, 76, 69, 84, 84, 69, 82, 32, 70, 230, 1, 66, 34, 69, 22, 73, + 22, 76, 34, 78, 254, 133, 1, 67, 2, 68, 2, 83, 2, 84, 214, 56, 72, 226, + 48, 70, 2, 74, 2, 77, 2, 80, 2, 82, 2, 86, 2, 88, 2, 90, 158, 20, 71, 2, + 75, 2, 81, 186, 2, 65, 2, 79, 2, 85, 3, 89, 4, 150, 240, 1, 66, 215, 22, + 69, 5, 203, 134, 2, 73, 5, 227, 239, 1, 74, 4, 234, 131, 2, 76, 187, 2, + 65, 4, 174, 239, 1, 74, 215, 22, 69, 8, 28, 3, 73, 68, 69, 59, 76, 2, 21, + 3, 68, 32, 71, 2, 177, 71, 4, 82, 69, 69, 75, 6, 46, 67, 20, 3, 76, 69, + 89, 41, 2, 85, 77, 2, 203, 219, 1, 65, 2, 11, 66, 2, 11, 65, 2, 147, 123, + 76, 2, 11, 69, 2, 17, 2, 32, 73, 2, 201, 122, 4, 78, 84, 69, 71, 5, 223, + 131, 2, 83, 40, 70, 67, 45, 13, 71, 65, 82, 32, 70, 82, 65, 67, 84, 73, + 79, 78, 32, 2, 11, 65, 2, 11, 78, 2, 155, 197, 1, 85, 38, 106, 70, 96, 4, + 79, 78, 69, 32, 174, 2, 84, 80, 7, 83, 69, 86, 69, 78, 32, 69, 145, 33, + 3, 90, 69, 82, 6, 56, 4, 73, 86, 69, 32, 249, 3, 5, 79, 85, 82, 32, 70, + 4, 158, 3, 69, 113, 3, 83, 73, 88, 18, 66, 69, 28, 2, 70, 73, 18, 72, 30, + 78, 14, 81, 30, 83, 55, 84, 2, 193, 1, 3, 73, 71, 72, 2, 167, 1, 70, 2, + 11, 65, 2, 131, 127, 76, 2, 111, 73, 2, 165, 73, 3, 85, 65, 82, 4, 24, 2, + 69, 86, 15, 73, 2, 43, 69, 2, 43, 88, 4, 18, 69, 35, 72, 2, 11, 78, 2, + 243, 253, 1, 84, 2, 155, 104, 73, 10, 48, 5, 72, 82, 69, 69, 32, 93, 3, + 87, 79, 32, 6, 26, 69, 26, 81, 67, 70, 2, 109, 3, 73, 71, 72, 2, 21, 3, + 85, 65, 82, 2, 151, 111, 84, 4, 22, 70, 211, 32, 84, 2, 11, 73, 2, 11, + 70, 2, 205, 191, 1, 2, 84, 72, 156, 6, 86, 65, 242, 23, 69, 158, 3, 72, + 142, 66, 73, 234, 8, 79, 134, 6, 82, 167, 144, 1, 74, 204, 2, 122, 78, + 220, 5, 2, 88, 73, 158, 1, 82, 210, 10, 84, 194, 1, 86, 252, 70, 2, 70, + 70, 233, 78, 6, 83, 84, 69, 66, 65, 83, 122, 36, 4, 67, 72, 79, 32, 183, + 5, 73, 118, 100, 7, 76, 69, 84, 84, 69, 82, 32, 252, 3, 3, 78, 71, 85, + 16, 5, 84, 79, 78, 69, 32, 243, 7, 68, 88, 210, 1, 65, 38, 79, 34, 69, + 22, 73, 22, 76, 50, 78, 42, 84, 50, 85, 22, 89, 138, 175, 1, 75, 2, 80, + 2, 83, 254, 68, 66, 2, 67, 2, 68, 2, 70, 2, 71, 2, 72, 2, 74, 2, 77, 2, + 82, 2, 86, 2, 87, 3, 90, 13, 34, 65, 206, 247, 1, 78, 87, 85, 7, 11, 78, + 5, 147, 248, 1, 71, 5, 255, 247, 1, 78, 5, 151, 247, 1, 78, 4, 26, 76, + 191, 247, 1, 65, 2, 131, 245, 1, 72, 6, 238, 244, 1, 71, 2, 89, 187, 2, + 65, 8, 198, 244, 1, 72, 2, 82, 2, 83, 187, 2, 65, 5, 251, 166, 1, 69, 4, + 170, 245, 1, 73, 147, 1, 65, 2, 179, 111, 78, 8, 40, 3, 75, 79, 73, 1, 3, + 84, 85, 80, 5, 135, 226, 1, 78, 4, 21, 3, 78, 71, 32, 4, 76, 8, 67, 82, + 69, 83, 67, 69, 78, 84, 1, 7, 71, 73, 66, 66, 79, 85, 83, 2, 21, 3, 32, + 77, 79, 2, 11, 79, 2, 175, 97, 78, 170, 1, 72, 9, 65, 78, 71, 32, 67, 73, + 84, 73, 32, 249, 108, 4, 78, 73, 78, 71, 168, 1, 128, 1, 6, 67, 65, 80, + 73, 84, 65, 0, 4, 83, 77, 65, 76, 190, 4, 68, 156, 2, 7, 78, 85, 77, 66, + 69, 82, 32, 171, 219, 1, 79, 64, 45, 9, 76, 32, 76, 69, 84, 84, 69, 82, + 32, 64, 174, 1, 65, 38, 69, 42, 72, 74, 78, 50, 79, 22, 83, 50, 85, 30, + 89, 170, 42, 84, 248, 107, 2, 86, 73, 206, 51, 66, 2, 80, 246, 5, 75, + 158, 11, 73, 2, 87, 162, 17, 68, 3, 71, 9, 162, 240, 1, 78, 86, 77, 3, + 84, 7, 11, 78, 4, 198, 240, 1, 78, 3, 89, 8, 38, 79, 210, 151, 1, 73, + 231, 31, 65, 4, 178, 183, 1, 82, 223, 25, 76, 4, 26, 71, 223, 158, 1, 85, + 2, 143, 237, 1, 65, 5, 159, 169, 1, 68, 4, 26, 83, 175, 219, 1, 73, 2, + 155, 202, 1, 85, 4, 238, 238, 1, 67, 3, 85, 8, 34, 85, 178, 238, 1, 65, + 3, 79, 5, 175, 238, 1, 74, 20, 11, 73, 20, 11, 71, 20, 17, 2, 73, 84, 20, + 11, 32, 20, 66, 70, 30, 83, 42, 84, 62, 90, 130, 83, 78, 14, 79, 199, + 110, 69, 4, 218, 112, 73, 131, 4, 79, 4, 22, 69, 227, 96, 73, 2, 247, 27, + 86, 4, 26, 72, 207, 205, 1, 87, 2, 11, 82, 2, 223, 213, 1, 69, 2, 11, 69, + 2, 159, 205, 1, 82, 18, 42, 69, 30, 70, 42, 78, 38, 83, 39, 84, 2, 221, + 1, 3, 73, 71, 72, 4, 22, 73, 139, 1, 79, 2, 171, 1, 70, 2, 17, 2, 73, 78, + 2, 135, 1, 69, 4, 92, 2, 69, 86, 25, 2, 73, 88, 6, 34, 72, 26, 87, 187, + 154, 1, 69, 2, 11, 73, 2, 35, 82, 2, 11, 69, 2, 11, 78, 2, 171, 216, 1, + 84, 12, 32, 2, 69, 82, 175, 232, 1, 67, 10, 34, 32, 173, 153, 1, 2, 77, + 69, 8, 80, 3, 67, 76, 79, 22, 87, 224, 197, 1, 5, 66, 85, 70, 70, 65, 1, + 2, 80, 79, 2, 183, 179, 1, 83, 2, 235, 107, 65, 20, 60, 2, 69, 32, 124, + 4, 73, 78, 71, 32, 161, 1, 2, 89, 32, 6, 182, 2, 68, 157, 186, 1, 23, 65, + 82, 82, 79, 87, 32, 80, 79, 73, 78, 84, 73, 78, 71, 32, 68, 73, 82, 69, + 67, 84, 76, 89, 6, 64, 5, 66, 76, 65, 67, 75, 0, 5, 87, 72, 73, 84, 69, + 55, 72, 2, 17, 2, 32, 70, 2, 11, 76, 2, 171, 229, 1, 65, 2, 11, 65, 2, + 11, 78, 2, 235, 94, 68, 8, 26, 68, 34, 76, 43, 79, 2, 11, 65, 2, 139, + 228, 1, 83, 4, 22, 79, 223, 75, 73, 2, 183, 75, 87, 2, 11, 86, 2, 11, 69, + 2, 155, 75, 82, 14, 48, 3, 65, 82, 89, 70, 68, 70, 73, 171, 1, 83, 4, 11, + 32, 4, 32, 2, 67, 65, 219, 166, 1, 70, 2, 191, 166, 1, 84, 4, 26, 71, + 175, 146, 1, 68, 2, 149, 67, 6, 69, 45, 84, 65, 73, 76, 4, 116, 17, 69, + 82, 83, 84, 82, 65, 83, 83, 32, 69, 76, 76, 73, 80, 84, 73, 67, 185, 43, + 7, 71, 72, 84, 32, 76, 73, 70, 2, 17, 2, 32, 70, 2, 157, 145, 1, 2, 85, + 78, 2, 37, 7, 84, 32, 83, 89, 82, 73, 65, 2, 179, 35, 67, 180, 2, 52, 3, + 69, 69, 76, 100, 3, 73, 84, 69, 219, 62, 65, 7, 60, 7, 32, 79, 70, 32, + 68, 72, 65, 21, 4, 67, 72, 65, 73, 2, 143, 191, 1, 82, 2, 251, 76, 82, + 172, 2, 54, 32, 181, 63, 8, 45, 70, 69, 65, 84, 72, 69, 82, 170, 2, 148, + 2, 18, 65, 82, 82, 79, 87, 32, 83, 72, 65, 70, 84, 32, 87, 73, 68, 84, + 72, 32, 114, 66, 46, 67, 194, 15, 68, 166, 5, 69, 50, 70, 178, 3, 72, + 222, 3, 76, 218, 3, 77, 226, 1, 78, 34, 80, 146, 1, 81, 78, 82, 250, 1, + 83, 142, 12, 84, 228, 3, 2, 85, 80, 217, 3, 3, 86, 69, 82, 4, 22, 84, + 251, 67, 79, 2, 11, 87, 2, 21, 3, 79, 32, 84, 2, 17, 2, 72, 73, 2, 11, + 82, 2, 247, 158, 1, 68, 2, 11, 85, 2, 11, 76, 2, 143, 167, 1, 76, 92, + 146, 1, 72, 168, 10, 5, 73, 82, 67, 76, 69, 162, 3, 76, 25, 20, 79, 78, + 67, 65, 86, 69, 45, 83, 73, 68, 69, 68, 32, 68, 73, 65, 77, 79, 78, 68, + 66, 25, 4, 69, 83, 83, 32, 66, 66, 66, 38, 69, 118, 75, 142, 4, 80, 22, + 81, 38, 82, 131, 2, 84, 6, 241, 5, 5, 73, 83, 72, 79, 80, 4, 45, 9, 81, + 85, 73, 72, 79, 80, 80, 69, 82, 5, 17, 2, 32, 82, 2, 129, 6, 8, 79, 84, + 65, 84, 69, 68, 32, 78, 26, 38, 73, 25, 5, 78, 73, 71, 72, 84, 6, 177, 4, + 2, 78, 71, 21, 22, 32, 151, 3, 45, 12, 41, 8, 82, 79, 84, 65, 84, 69, 68, + 32, 12, 104, 2, 70, 79, 0, 15, 79, 78, 69, 32, 72, 85, 78, 68, 82, 69, + 68, 32, 84, 72, 73, 18, 84, 215, 3, 78, 2, 207, 1, 82, 6, 148, 1, 11, 87, + 79, 32, 72, 85, 78, 68, 82, 69, 68, 32, 133, 3, 20, 72, 82, 69, 69, 32, + 72, 85, 78, 68, 82, 69, 68, 32, 70, 73, 70, 84, 69, 69, 78, 4, 36, 4, 84, + 87, 69, 78, 175, 2, 83, 2, 217, 2, 7, 84, 89, 45, 70, 73, 86, 69, 6, 166, + 3, 66, 94, 81, 47, 82, 6, 41, 2, 65, 87, 6, 21, 3, 85, 69, 69, 6, 35, 78, + 6, 21, 3, 79, 79, 75, 7, 45, 9, 32, 82, 79, 84, 65, 84, 69, 68, 32, 4, + 70, 78, 25, 13, 84, 87, 79, 32, 72, 85, 78, 68, 82, 69, 68, 32, 83, 2, + 49, 3, 73, 78, 69, 2, 25, 4, 69, 86, 69, 78, 2, 17, 2, 84, 89, 2, 253, + 62, 6, 32, 68, 69, 71, 82, 69, 12, 33, 6, 85, 82, 78, 69, 68, 32, 12, 42, + 66, 30, 75, 34, 80, 34, 81, 47, 82, 2, 225, 88, 3, 73, 83, 72, 4, 222, + 128, 1, 73, 159, 38, 78, 2, 11, 65, 2, 203, 129, 1, 87, 2, 11, 85, 2, 11, + 69, 2, 159, 129, 1, 69, 2, 255, 166, 1, 79, 19, 11, 32, 16, 100, 16, 67, + 79, 78, 84, 65, 73, 78, 73, 78, 71, 32, 66, 76, 65, 67, 75, 121, 5, 87, + 73, 84, 72, 32, 2, 17, 2, 32, 83, 2, 11, 77, 2, 21, 3, 65, 76, 76, 2, 11, + 32, 2, 11, 67, 2, 11, 73, 2, 11, 82, 2, 203, 45, 67, 14, 56, 2, 68, 79, + 70, 84, 148, 30, 2, 76, 79, 231, 1, 85, 4, 18, 84, 35, 87, 2, 11, 32, 2, + 179, 163, 1, 82, 2, 179, 51, 78, 2, 11, 87, 2, 11, 79, 2, 11, 32, 2, 155, + 57, 68, 2, 141, 26, 2, 85, 66, 7, 33, 6, 32, 87, 73, 84, 72, 32, 4, 148, + 29, 2, 76, 69, 49, 2, 82, 73, 28, 76, 6, 73, 65, 77, 79, 78, 68, 216, 2, + 3, 79, 87, 78, 177, 1, 2, 82, 65, 15, 11, 32, 12, 160, 1, 17, 67, 79, 78, + 84, 65, 73, 78, 73, 78, 71, 32, 66, 76, 65, 67, 75, 32, 128, 1, 9, 87, + 73, 84, 72, 32, 67, 69, 78, 84, 198, 22, 83, 173, 18, 2, 73, 78, 6, 74, + 83, 0, 6, 86, 69, 82, 89, 32, 83, 29, 6, 77, 69, 68, 73, 85, 77, 2, 25, + 4, 77, 65, 76, 76, 2, 181, 14, 2, 32, 68, 2, 11, 82, 2, 11, 69, 2, 179, + 56, 68, 10, 96, 10, 32, 80, 79, 73, 78, 84, 73, 78, 71, 32, 53, 10, 45, + 80, 79, 73, 78, 84, 73, 78, 71, 32, 6, 250, 34, 66, 24, 5, 76, 69, 70, + 84, 32, 51, 73, 4, 138, 36, 83, 51, 84, 4, 33, 6, 85, 71, 72, 84, 83, 32, + 4, 22, 77, 191, 118, 75, 2, 223, 119, 65, 2, 29, 5, 88, 67, 76, 65, 77, + 2, 155, 14, 65, 14, 74, 76, 144, 2, 11, 79, 85, 82, 32, 80, 79, 73, 78, + 84, 69, 68, 71, 82, 8, 28, 2, 65, 71, 175, 1, 79, 5, 149, 1, 34, 32, 87, + 73, 84, 72, 32, 72, 79, 82, 73, 90, 79, 78, 84, 65, 76, 32, 77, 73, 68, + 68, 76, 69, 32, 66, 76, 65, 67, 75, 32, 83, 84, 82, 73, 2, 155, 174, 1, + 80, 4, 26, 82, 227, 134, 1, 87, 2, 17, 2, 69, 84, 2, 215, 173, 1, 84, 4, + 11, 32, 4, 18, 67, 23, 83, 2, 223, 195, 1, 85, 2, 187, 33, 84, 2, 183, + 59, 79, 16, 34, 65, 150, 1, 69, 219, 1, 79, 2, 25, 4, 82, 68, 32, 83, 2, + 45, 9, 72, 69, 76, 76, 32, 70, 76, 79, 80, 2, 17, 2, 80, 89, 2, 17, 2, + 32, 68, 2, 11, 73, 2, 135, 191, 1, 83, 10, 22, 65, 247, 10, 88, 8, 30, + 82, 29, 3, 86, 89, 32, 4, 11, 84, 5, 183, 14, 32, 4, 74, 67, 41, 14, 83, + 65, 76, 84, 73, 82, 69, 32, 87, 73, 84, 72, 32, 82, 2, 21, 3, 72, 69, 67, + 2, 155, 127, 75, 2, 139, 18, 79, 4, 152, 30, 10, 82, 73, 90, 79, 78, 84, + 65, 76, 32, 69, 229, 10, 2, 85, 82, 18, 170, 1, 65, 116, 3, 69, 70, 84, + 165, 9, 31, 79, 90, 69, 78, 71, 69, 32, 67, 79, 78, 84, 65, 73, 78, 73, + 78, 71, 32, 66, 76, 65, 67, 75, 32, 83, 77, 65, 76, 76, 32, 76, 4, 24, 2, + 82, 71, 19, 84, 2, 199, 29, 69, 2, 11, 73, 2, 11, 78, 2, 17, 2, 32, 67, + 2, 11, 82, 2, 159, 39, 79, 12, 58, 32, 77, 10, 45, 80, 79, 73, 78, 84, + 73, 78, 71, 32, 6, 44, 6, 76, 65, 78, 69, 32, 77, 223, 22, 80, 2, 11, 69, + 2, 219, 8, 82, 6, 30, 80, 166, 24, 83, 51, 84, 2, 187, 5, 79, 12, 68, 6, + 69, 68, 73, 85, 77, 32, 121, 7, 79, 79, 78, 32, 83, 69, 76, 10, 30, 68, + 54, 83, 211, 6, 76, 2, 11, 73, 2, 11, 65, 2, 11, 77, 2, 163, 45, 79, 6, + 202, 24, 84, 186, 1, 77, 59, 81, 2, 11, 69, 2, 139, 184, 1, 78, 2, 11, + 73, 2, 163, 186, 1, 66, 6, 18, 65, 87, 69, 2, 37, 7, 82, 65, 76, 76, 69, + 76, 79, 2, 11, 71, 2, 11, 82, 2, 227, 168, 1, 65, 4, 11, 78, 4, 154, 2, + 84, 191, 45, 78, 2, 21, 3, 85, 69, 83, 2, 145, 117, 9, 84, 73, 79, 78, + 32, 77, 65, 82, 75, 14, 36, 4, 73, 71, 72, 84, 179, 22, 69, 12, 60, 10, + 45, 80, 79, 73, 78, 84, 73, 78, 71, 32, 195, 17, 32, 8, 30, 80, 178, 19, + 83, 51, 84, 4, 18, 69, 55, 79, 2, 11, 78, 2, 11, 84, 2, 11, 65, 2, 147, + 103, 71, 2, 11, 73, 2, 11, 78, 2, 235, 120, 84, 56, 118, 67, 32, 3, 69, + 83, 65, 18, 72, 58, 77, 170, 1, 80, 68, 5, 81, 85, 65, 82, 69, 168, 6, 2, + 85, 78, 163, 10, 84, 2, 133, 39, 4, 73, 83, 83, 79, 2, 155, 36, 77, 2, + 21, 3, 79, 71, 73, 2, 137, 120, 4, 32, 80, 73, 69, 8, 32, 4, 65, 76, 76, + 32, 119, 73, 6, 18, 76, 71, 83, 2, 11, 79, 2, 11, 90, 2, 11, 69, 2, 11, + 78, 2, 159, 157, 1, 71, 4, 182, 17, 84, 243, 1, 81, 2, 187, 43, 76, 2, + 21, 3, 65, 68, 69, 2, 11, 32, 2, 11, 83, 2, 203, 150, 1, 85, 29, 11, 32, + 26, 114, 66, 36, 17, 67, 79, 78, 84, 65, 73, 78, 73, 78, 71, 32, 66, 76, + 65, 67, 75, 32, 73, 5, 87, 73, 84, 72, 32, 2, 17, 2, 85, 84, 2, 251, 97, + 84, 6, 184, 16, 4, 86, 69, 82, 89, 22, 83, 37, 6, 77, 69, 68, 73, 85, 77, + 18, 150, 1, 76, 50, 82, 214, 1, 85, 144, 1, 17, 86, 69, 82, 84, 73, 67, + 65, 76, 32, 66, 73, 83, 69, 67, 84, 73, 78, 221, 18, 6, 67, 69, 78, 84, + 82, 69, 6, 18, 69, 15, 79, 2, 67, 70, 4, 247, 1, 87, 4, 18, 73, 115, 79, + 2, 17, 2, 71, 72, 2, 33, 6, 84, 87, 65, 82, 68, 83, 2, 11, 32, 2, 11, 84, + 2, 11, 73, 2, 179, 171, 1, 67, 2, 29, 5, 85, 78, 68, 69, 68, 2, 21, 3, + 32, 67, 79, 2, 181, 31, 2, 82, 78, 4, 17, 2, 80, 80, 4, 21, 3, 69, 82, + 32, 4, 44, 3, 76, 69, 70, 1, 4, 82, 73, 71, 72, 2, 33, 6, 84, 32, 81, 85, + 65, 68, 2, 163, 35, 82, 2, 159, 19, 71, 11, 11, 32, 8, 84, 12, 66, 69, + 72, 73, 78, 68, 32, 67, 76, 79, 85, 68, 69, 5, 87, 73, 84, 72, 32, 5, 29, + 5, 32, 87, 73, 84, 72, 2, 17, 2, 32, 82, 2, 243, 43, 65, 4, 38, 82, 29, + 5, 83, 77, 65, 76, 76, 2, 11, 65, 2, 155, 109, 89, 2, 25, 4, 32, 67, 76, + 79, 2, 171, 100, 85, 10, 38, 79, 54, 69, 62, 82, 203, 1, 87, 2, 49, 10, + 85, 67, 72, 84, 79, 78, 69, 32, 84, 69, 2, 17, 2, 76, 69, 2, 11, 80, 2, + 11, 72, 2, 147, 16, 79, 4, 148, 1, 4, 65, 80, 69, 90, 33, 28, 73, 65, 78, + 71, 76, 69, 32, 67, 79, 78, 84, 65, 73, 78, 73, 78, 71, 32, 83, 77, 65, + 76, 76, 32, 87, 72, 73, 84, 2, 11, 73, 2, 155, 151, 1, 85, 2, 255, 3, 69, + 2, 11, 79, 2, 85, 19, 45, 87, 65, 89, 32, 76, 69, 70, 84, 32, 87, 65, 89, + 32, 84, 82, 65, 70, 70, 2, 11, 73, 2, 223, 166, 1, 67, 12, 62, 32, 185, + 1, 10, 45, 80, 79, 73, 78, 84, 73, 78, 71, 32, 4, 11, 80, 4, 41, 8, 79, + 73, 78, 84, 73, 78, 71, 32, 4, 18, 66, 75, 73, 2, 21, 3, 65, 67, 75, 2, + 25, 4, 72, 65, 78, 68, 2, 17, 2, 32, 73, 2, 17, 2, 78, 68, 2, 215, 24, + 69, 8, 68, 4, 67, 72, 69, 86, 18, 83, 73, 7, 84, 82, 73, 65, 78, 71, 76, + 2, 171, 84, 82, 2, 25, 4, 77, 65, 76, 76, 2, 17, 2, 32, 84, 2, 129, 2, 2, + 82, 73, 4, 11, 69, 5, 11, 32, 2, 11, 87, 2, 145, 18, 3, 73, 84, 72, 8, + 44, 6, 84, 73, 67, 65, 76, 32, 183, 1, 89, 6, 26, 66, 18, 69, 51, 82, 2, + 215, 105, 65, 2, 11, 76, 2, 17, 2, 76, 73, 2, 131, 25, 80, 2, 11, 69, 2, + 17, 2, 67, 84, 2, 11, 65, 2, 11, 78, 2, 11, 71, 2, 207, 138, 1, 76, 2, + 17, 2, 32, 83, 2, 11, 77, 2, 21, 3, 65, 76, 76, 2, 17, 2, 32, 83, 2, 11, + 81, 2, 11, 85, 2, 11, 65, 2, 203, 137, 1, 82, 2, 11, 69, 2, 11, 68, 2, + 17, 2, 32, 82, 2, 21, 3, 73, 71, 72, 2, 11, 84, 2, 11, 87, 2, 241, 4, 4, + 65, 82, 68, 83, 100, 140, 1, 10, 68, 69, 45, 72, 69, 65, 68, 69, 68, 32, + 132, 4, 4, 71, 71, 76, 89, 124, 6, 76, 84, 69, 68, 32, 70, 42, 78, 189, + 1, 2, 82, 69, 80, 128, 1, 3, 76, 69, 70, 0, 4, 82, 73, 71, 72, 12, 4, 68, + 79, 87, 78, 0, 2, 85, 80, 32, 3, 78, 79, 82, 1, 3, 83, 79, 85, 10, 11, + 84, 10, 109, 5, 87, 65, 82, 68, 83, 20, 21, 3, 84, 72, 32, 20, 32, 2, 69, + 65, 1, 2, 87, 69, 10, 17, 2, 83, 84, 10, 11, 32, 10, 110, 72, 0, 6, 86, + 69, 82, 89, 32, 72, 28, 5, 76, 73, 71, 72, 84, 0, 6, 77, 69, 68, 73, 85, + 77, 23, 66, 2, 25, 4, 69, 65, 86, 89, 2, 17, 2, 32, 66, 2, 21, 3, 65, 82, + 66, 2, 11, 32, 2, 11, 65, 2, 11, 82, 2, 11, 82, 2, 251, 27, 79, 2, 17, 2, + 32, 86, 2, 11, 69, 2, 33, 6, 82, 84, 73, 67, 65, 76, 2, 11, 32, 2, 11, + 76, 2, 11, 73, 2, 191, 130, 1, 78, 2, 11, 76, 2, 11, 79, 2, 135, 91, 87, + 12, 46, 68, 106, 69, 186, 15, 75, 139, 136, 1, 71, 6, 22, 32, 131, 26, + 79, 4, 44, 2, 67, 72, 217, 15, 4, 66, 76, 79, 87, 2, 11, 73, 2, 255, 128, + 1, 77, 2, 11, 32, 2, 121, 3, 71, 76, 65, 4, 36, 5, 68, 32, 75, 69, 89, + 51, 76, 2, 17, 2, 66, 79, 2, 11, 65, 2, 191, 80, 82, 2, 11, 69, 2, 231, + 88, 83, 30, 66, 77, 158, 3, 82, 226, 11, 78, 214, 64, 79, 129, 9, 2, 76, + 70, 14, 36, 2, 65, 78, 161, 2, 2, 69, 78, 13, 72, 12, 32, 87, 73, 84, 72, + 32, 66, 85, 78, 78, 89, 32, 29, 2, 83, 32, 2, 11, 69, 2, 167, 6, 65, 8, + 48, 2, 66, 79, 28, 2, 67, 76, 54, 72, 19, 83, 2, 11, 79, 2, 195, 86, 84, + 2, 11, 79, 2, 11, 84, 2, 11, 72, 2, 143, 86, 69, 2, 163, 119, 65, 2, 17, + 2, 65, 78, 2, 131, 10, 68, 2, 11, 83, 2, 11, 32, 2, 11, 83, 2, 11, 89, 2, + 17, 2, 77, 66, 2, 187, 9, 79, 10, 72, 2, 68, 32, 156, 1, 3, 76, 68, 32, + 32, 2, 82, 73, 195, 144, 1, 77, 4, 56, 9, 83, 69, 80, 65, 82, 65, 84, 79, + 82, 191, 83, 74, 2, 17, 2, 32, 77, 2, 21, 3, 73, 68, 68, 2, 11, 76, 2, + 11, 69, 2, 11, 32, 2, 195, 64, 68, 2, 11, 77, 2, 199, 144, 1, 65, 2, 11, + 69, 2, 159, 83, 68, 10, 56, 7, 65, 80, 80, 69, 68, 32, 80, 30, 69, 163, + 1, 73, 2, 201, 76, 3, 82, 69, 83, 6, 48, 2, 65, 84, 80, 3, 83, 84, 76, + 163, 108, 78, 2, 11, 72, 2, 11, 32, 2, 11, 80, 2, 25, 4, 82, 79, 68, 85, + 2, 171, 114, 67, 2, 11, 69, 2, 235, 80, 82, 2, 11, 84, 2, 11, 73, 2, 17, + 2, 78, 71, 2, 17, 2, 32, 72, 2, 11, 65, 2, 203, 71, 78, 34, 76, 2, 32, + 73, 138, 1, 45, 28, 7, 73, 65, 78, 71, 81, 73, 32, 143, 83, 79, 2, 53, + 11, 78, 32, 65, 32, 82, 69, 67, 84, 65, 78, 71, 2, 11, 76, 2, 11, 69, 2, + 11, 32, 2, 11, 66, 2, 11, 79, 2, 139, 140, 1, 88, 2, 11, 82, 2, 163, 122, + 65, 28, 48, 5, 66, 76, 65, 67, 75, 1, 3, 82, 69, 68, 14, 11, 32, 14, 130, + 1, 67, 72, 4, 69, 76, 69, 80, 28, 4, 71, 69, 78, 69, 46, 72, 36, 4, 83, + 79, 76, 68, 169, 9, 6, 77, 65, 78, 68, 65, 82, 4, 24, 2, 65, 78, 19, 72, + 2, 155, 58, 78, 2, 189, 57, 3, 65, 82, 73, 2, 11, 72, 2, 179, 70, 65, 2, + 11, 82, 2, 11, 65, 2, 155, 137, 1, 76, 2, 17, 2, 79, 82, 2, 159, 114, 83, + 2, 131, 75, 73, 242, 19, 50, 65, 58, 69, 218, 11, 73, 217, 35, 2, 79, 45, + 2, 17, 2, 87, 78, 2, 11, 73, 2, 229, 74, 2, 78, 71, 98, 60, 4, 76, 76, + 79, 87, 62, 78, 53, 5, 90, 73, 68, 73, 32, 2, 17, 2, 32, 72, 2, 11, 69, + 2, 11, 65, 2, 203, 106, 82, 2, 11, 32, 2, 11, 83, 2, 11, 73, 2, 239, 54, + 71, 94, 112, 10, 67, 79, 77, 66, 73, 78, 73, 78, 71, 32, 76, 5, 72, 89, + 80, 72, 69, 17, 7, 76, 69, 84, 84, 69, 82, 32, 4, 44, 3, 77, 65, 68, 13, + 4, 72, 65, 77, 90, 2, 11, 68, 2, 203, 67, 65, 2, 207, 27, 78, 88, 250, 1, + 67, 50, 77, 18, 68, 42, 69, 58, 72, 30, 75, 22, 71, 2, 81, 32, 3, 76, 65, + 77, 98, 78, 18, 80, 30, 83, 66, 84, 28, 2, 86, 65, 118, 87, 14, 79, 18, + 88, 52, 3, 89, 79, 84, 154, 1, 90, 130, 53, 82, 226, 48, 66, 254, 5, 85, + 162, 14, 70, 3, 74, 6, 22, 72, 251, 113, 73, 4, 22, 72, 227, 113, 73, 2, + 223, 113, 73, 4, 11, 65, 4, 154, 130, 1, 68, 3, 76, 8, 42, 76, 130, 50, + 89, 214, 79, 84, 3, 87, 2, 71, 73, 4, 254, 111, 65, 147, 15, 72, 4, 18, + 72, 15, 65, 2, 11, 65, 2, 139, 129, 1, 70, 5, 11, 32, 2, 11, 87, 2, 21, + 3, 73, 84, 72, 2, 17, 2, 32, 68, 2, 11, 79, 2, 179, 3, 84, 2, 195, 48, + 85, 4, 178, 105, 72, 215, 22, 69, 8, 46, 72, 234, 47, 73, 194, 9, 65, + 151, 70, 69, 2, 231, 47, 73, 4, 214, 104, 72, 215, 22, 65, 5, 37, 7, 32, + 65, 76, 84, 69, 82, 78, 2, 21, 3, 65, 84, 69, 2, 11, 32, 2, 11, 70, 2, + 11, 79, 2, 211, 109, 82, 2, 11, 65, 2, 143, 126, 87, 4, 22, 72, 235, 125, + 65, 2, 11, 69, 2, 135, 46, 89, 5, 37, 7, 32, 87, 73, 84, 72, 32, 67, 2, + 45, 9, 73, 82, 67, 85, 77, 70, 76, 69, 88, 2, 11, 32, 2, 11, 65, 2, 11, + 66, 2, 11, 79, 2, 239, 101, 86, 6, 22, 65, 159, 124, 69, 5, 155, 124, 76, + 140, 19, 34, 32, 161, 35, 3, 78, 32, 89, 138, 19, 88, 8, 82, 65, 68, 73, + 67, 65, 76, 32, 181, 7, 9, 83, 89, 76, 76, 65, 66, 76, 69, 32, 110, 170, + 1, 66, 42, 67, 86, 68, 42, 71, 74, 72, 66, 74, 66, 75, 30, 76, 30, 77, + 26, 78, 74, 80, 26, 83, 74, 84, 30, 86, 30, 89, 30, 90, 246, 35, 81, 186, + 49, 87, 235, 30, 79, 4, 22, 66, 243, 64, 85, 2, 147, 93, 85, 12, 42, 85, + 18, 89, 162, 98, 72, 203, 22, 73, 2, 247, 120, 79, 7, 242, 120, 80, 3, + 84, 4, 22, 68, 199, 120, 85, 2, 243, 63, 85, 10, 42, 71, 222, 91, 79, + 162, 28, 69, 15, 65, 4, 146, 89, 85, 235, 30, 79, 8, 22, 88, 227, 88, 77, + 6, 222, 88, 85, 202, 2, 73, 163, 28, 79, 8, 22, 74, 151, 119, 79, 6, 230, + 90, 85, 218, 5, 73, 215, 22, 89, 4, 190, 90, 73, 175, 28, 69, 6, 186, 54, + 73, 199, 7, 89, 4, 166, 118, 79, 15, 73, 8, 30, 89, 26, 90, 183, 90, 66, + 4, 238, 117, 73, 3, 79, 2, 215, 117, 85, 4, 166, 89, 85, 3, 89, 10, 22, + 72, 207, 97, 83, 8, 210, 60, 85, 166, 28, 65, 162, 28, 79, 15, 89, 4, + 198, 88, 65, 175, 28, 85, 4, 134, 60, 85, 199, 56, 69, 4, 142, 88, 73, + 175, 28, 79, 10, 54, 85, 220, 62, 2, 90, 73, 226, 24, 79, 175, 28, 65, 4, + 230, 115, 80, 3, 82, 156, 18, 134, 2, 66, 134, 1, 67, 162, 1, 68, 110, + 70, 50, 71, 150, 1, 72, 138, 3, 73, 134, 1, 74, 98, 75, 54, 76, 62, 77, + 134, 1, 78, 234, 4, 80, 54, 81, 2, 89, 46, 82, 162, 1, 83, 134, 1, 84, + 102, 86, 82, 87, 58, 88, 50, 90, 140, 2, 2, 85, 79, 66, 65, 2, 79, 107, + 69, 132, 1, 66, 66, 238, 21, 85, 150, 1, 69, 26, 73, 42, 65, 2, 79, 67, + 89, 64, 234, 21, 85, 150, 1, 69, 26, 73, 42, 65, 2, 79, 3, 89, 122, 66, + 72, 238, 20, 85, 150, 1, 69, 26, 73, 42, 65, 2, 79, 67, 89, 54, 46, 85, + 146, 22, 65, 2, 69, 2, 79, 67, 89, 19, 142, 22, 79, 106, 82, 214, 88, 80, + 3, 88, 106, 58, 68, 138, 15, 85, 134, 5, 73, 94, 69, 66, 65, 3, 79, 54, + 210, 19, 85, 58, 73, 94, 69, 66, 65, 3, 79, 42, 182, 20, 79, 66, 65, 2, + 73, 2, 89, 67, 85, 116, 58, 71, 214, 15, 85, 146, 4, 73, 42, 65, 2, 69, + 3, 79, 56, 50, 73, 162, 15, 85, 186, 4, 65, 2, 69, 3, 79, 13, 150, 19, + 69, 254, 89, 84, 3, 88, 246, 1, 78, 73, 30, 76, 58, 77, 54, 78, 110, 88, + 50, 85, 254, 15, 69, 66, 65, 3, 79, 6, 198, 19, 69, 215, 88, 84, 64, 238, + 16, 85, 58, 73, 94, 69, 2, 79, 66, 65, 67, 89, 58, 182, 16, 85, 58, 73, + 158, 1, 65, 2, 79, 35, 89, 42, 46, 79, 34, 85, 202, 16, 69, 26, 73, 43, + 65, 6, 226, 106, 80, 2, 84, 3, 88, 6, 238, 17, 79, 215, 88, 84, 46, 46, + 85, 254, 15, 69, 26, 73, 42, 65, 3, 79, 8, 187, 16, 79, 19, 42, 84, 130, + 16, 69, 190, 89, 80, 3, 88, 5, 11, 69, 2, 11, 82, 2, 11, 65, 2, 11, 84, + 2, 11, 73, 2, 11, 79, 2, 187, 39, 78, 106, 50, 74, 190, 10, 85, 146, 4, + 73, 42, 79, 67, 89, 50, 158, 13, 85, 174, 1, 73, 42, 79, 3, 89, 56, 242, + 12, 85, 58, 73, 158, 1, 65, 2, 69, 3, 79, 70, 218, 9, 85, 250, 3, 69, 26, + 73, 42, 65, 2, 79, 67, 89, 106, 70, 71, 218, 8, 85, 158, 3, 73, 158, 1, + 65, 2, 79, 2, 89, 107, 69, 44, 186, 11, 85, 150, 1, 69, 66, 65, 2, 79, + 105, 2, 73, 69, 248, 2, 102, 66, 54, 68, 94, 71, 90, 74, 46, 82, 50, 89, + 78, 90, 134, 7, 85, 58, 73, 94, 65, 2, 69, 67, 79, 54, 202, 10, 73, 158, + 1, 65, 2, 79, 66, 85, 3, 89, 46, 46, 73, 198, 10, 69, 66, 65, 2, 79, 67, + 85, 13, 234, 11, 69, 214, 88, 80, 2, 84, 3, 88, 34, 60, 2, 85, 79, 218, + 9, 69, 0, 2, 73, 69, 66, 65, 3, 79, 7, 210, 99, 84, 3, 88, 50, 230, 1, + 85, 242, 7, 73, 42, 79, 67, 89, 46, 146, 9, 79, 66, 65, 2, 69, 66, 85, 3, + 89, 38, 30, 85, 222, 8, 73, 43, 79, 15, 194, 8, 79, 254, 89, 80, 2, 84, + 3, 88, 56, 62, 85, 206, 4, 79, 178, 2, 73, 158, 1, 65, 66, 89, 43, 69, + 15, 254, 8, 79, 2, 82, 214, 88, 80, 3, 88, 60, 150, 6, 85, 58, 73, 158, + 1, 65, 2, 79, 67, 89, 56, 254, 2, 85, 146, 4, 73, 42, 79, 67, 89, 100, + 58, 82, 254, 4, 85, 150, 1, 69, 66, 65, 2, 79, 67, 89, 48, 46, 85, 162, + 6, 69, 2, 79, 66, 89, 43, 65, 17, 134, 7, 79, 2, 82, 214, 88, 80, 2, 84, + 3, 88, 176, 1, 70, 83, 158, 3, 72, 50, 85, 58, 73, 94, 69, 66, 65, 2, 79, + 67, 89, 56, 130, 4, 73, 94, 69, 66, 65, 2, 79, 2, 85, 67, 89, 56, 46, 85, + 158, 3, 73, 94, 69, 66, 65, 3, 79, 21, 182, 4, 79, 106, 82, 214, 88, 80, + 2, 84, 3, 88, 60, 54, 69, 166, 3, 73, 42, 65, 2, 79, 66, 85, 3, 89, 4, + 134, 93, 80, 3, 88, 28, 38, 85, 206, 2, 69, 2, 79, 67, 65, 9, 203, 2, 79, + 40, 210, 2, 73, 42, 79, 66, 89, 41, 2, 85, 79, 178, 1, 66, 72, 50, 85, + 58, 73, 42, 90, 54, 69, 66, 65, 2, 79, 67, 89, 54, 46, 85, 214, 1, 65, 2, + 69, 2, 79, 67, 89, 19, 146, 1, 79, 170, 1, 82, 214, 88, 80, 2, 84, 3, 88, + 15, 90, 69, 254, 89, 80, 2, 84, 3, 88, 58, 50, 69, 2, 79, 26, 73, 42, 65, + 34, 85, 35, 89, 7, 250, 89, 80, 3, 88, 17, 38, 69, 190, 89, 80, 2, 84, 3, + 88, 9, 186, 89, 80, 2, 84, 3, 88, 11, 70, 82, 214, 88, 80, 3, 88, 13, 38, + 82, 214, 88, 80, 2, 84, 3, 88, 5, 211, 88, 88, 2, 215, 7, 65, 2, 191, 57, + 89, 180, 4, 252, 1, 10, 32, 78, 79, 84, 65, 84, 73, 79, 78, 32, 220, 6, + 16, 65, 78, 65, 66, 65, 90, 65, 82, 32, 83, 81, 85, 65, 82, 69, 32, 210, + 15, 69, 180, 2, 6, 73, 80, 80, 69, 82, 45, 96, 8, 78, 65, 77, 69, 78, 78, + 89, 32, 176, 33, 3, 79, 77, 66, 235, 26, 87, 26, 144, 1, 9, 66, 65, 71, + 32, 77, 69, 77, 66, 69, 38, 82, 104, 6, 68, 79, 77, 65, 73, 78, 60, 3, + 76, 69, 70, 154, 1, 83, 145, 2, 3, 84, 89, 80, 2, 11, 82, 2, 209, 83, 2, + 83, 72, 8, 100, 4, 65, 78, 71, 69, 60, 3, 73, 71, 72, 221, 1, 11, 69, 76, + 65, 84, 73, 79, 78, 65, 76, 32, 67, 2, 173, 3, 11, 32, 65, 78, 84, 73, + 82, 69, 83, 84, 82, 73, 4, 17, 2, 84, 32, 4, 60, 4, 73, 77, 65, 71, 13, + 7, 66, 73, 78, 68, 73, 78, 71, 2, 11, 69, 2, 25, 4, 32, 66, 82, 65, 2, + 11, 67, 2, 175, 29, 75, 8, 44, 6, 67, 72, 69, 77, 65, 32, 211, 1, 80, 6, + 18, 67, 71, 80, 2, 17, 2, 79, 77, 2, 11, 80, 2, 11, 79, 2, 11, 83, 2, + 107, 73, 4, 30, 73, 41, 3, 82, 79, 74, 2, 11, 80, 2, 11, 73, 2, 151, 80, + 78, 2, 11, 69, 2, 11, 67, 2, 11, 84, 2, 87, 73, 2, 255, 51, 79, 2, 11, + 69, 2, 11, 32, 2, 11, 67, 2, 11, 79, 2, 11, 76, 2, 11, 79, 2, 211, 79, + 78, 144, 1, 240, 1, 2, 67, 76, 68, 7, 73, 78, 73, 84, 73, 65, 76, 204, 2, + 14, 70, 73, 78, 65, 76, 32, 67, 79, 78, 83, 79, 78, 65, 78, 16, 7, 76, + 69, 84, 84, 69, 82, 32, 148, 3, 5, 77, 65, 82, 75, 32, 206, 1, 83, 181, + 3, 6, 86, 79, 87, 69, 76, 32, 14, 64, 5, 79, 83, 73, 78, 71, 137, 1, 6, + 85, 83, 84, 69, 82, 45, 4, 11, 32, 4, 64, 12, 68, 79, 85, 66, 76, 69, 45, + 76, 73, 78, 69, 68, 23, 72, 2, 17, 2, 32, 72, 2, 17, 2, 69, 65, 2, 215, + 10, 68, 10, 96, 13, 70, 73, 78, 65, 76, 32, 76, 69, 84, 84, 69, 82, 32, + 41, 7, 73, 78, 73, 84, 73, 65, 76, 8, 226, 72, 76, 2, 82, 2, 86, 3, 89, + 2, 37, 7, 32, 76, 69, 84, 84, 69, 82, 2, 151, 6, 32, 2, 131, 9, 84, 82, + 166, 1, 68, 50, 75, 38, 78, 46, 83, 38, 84, 46, 66, 2, 67, 2, 71, 2, 80, + 2, 90, 254, 68, 45, 2, 72, 2, 74, 2, 76, 2, 77, 2, 82, 2, 86, 2, 89, 187, + 2, 65, 12, 206, 1, 68, 2, 90, 254, 68, 72, 187, 2, 65, 6, 142, 70, 83, + 14, 72, 187, 2, 65, 8, 246, 69, 71, 2, 78, 2, 89, 187, 2, 65, 6, 202, 69, + 72, 2, 83, 187, 2, 65, 12, 42, 83, 2, 84, 254, 68, 72, 187, 2, 65, 4, + 250, 68, 72, 187, 2, 65, 8, 50, 68, 58, 83, 40, 4, 76, 79, 78, 71, 23, + 84, 2, 29, 5, 79, 85, 66, 76, 69, 2, 11, 32, 2, 11, 83, 2, 11, 72, 2, 11, + 65, 2, 147, 70, 68, 2, 17, 2, 32, 84, 2, 17, 2, 83, 72, 2, 135, 69, 69, + 14, 36, 4, 73, 71, 78, 32, 255, 2, 85, 12, 54, 65, 72, 6, 67, 65, 78, 68, + 82, 65, 167, 1, 86, 2, 11, 78, 2, 11, 85, 2, 17, 2, 83, 86, 2, 11, 65, 2, + 251, 65, 82, 6, 36, 5, 66, 73, 78, 68, 85, 15, 32, 5, 11, 32, 2, 25, 4, + 87, 73, 84, 72, 2, 17, 2, 32, 79, 2, 21, 3, 82, 78, 65, 2, 11, 77, 2, 11, + 69, 2, 227, 38, 78, 4, 11, 73, 4, 18, 82, 19, 83, 2, 207, 33, 65, 2, 11, + 65, 2, 11, 82, 2, 255, 63, 71, 2, 151, 4, 66, 20, 38, 76, 109, 5, 83, 73, + 71, 78, 32, 2, 17, 2, 69, 78, 2, 11, 71, 2, 11, 84, 2, 11, 72, 2, 11, 32, + 2, 11, 77, 2, 11, 65, 2, 251, 61, 82, 18, 86, 65, 26, 79, 2, 85, 16, 8, + 82, 69, 86, 69, 82, 83, 69, 68, 134, 64, 69, 3, 73, 4, 170, 64, 73, 3, + 85, 5, 147, 64, 69, 2, 171, 44, 32, 12, 72, 2, 66, 82, 16, 9, 82, 79, 32, + 87, 73, 68, 84, 72, 32, 203, 1, 85, 2, 147, 2, 65, 8, 32, 2, 78, 79, 86, + 83, 31, 74, 4, 26, 45, 73, 2, 78, 45, 2, 29, 5, 66, 82, 69, 65, 75, 2, + 11, 32, 2, 11, 83, 2, 163, 1, 80, 2, 11, 74, 2, 11, 79, 2, 11, 73, 2, 11, + 78, 2, 143, 5, 69, 2, 207, 61, 83, 2, 21, 3, 77, 79, 85, 2, 17, 2, 84, + 72, 2, 11, 32, 2, 11, 70, 2, 11, 65, 2, 155, 38, 67, 242, 2, 168, 1, 10, + 67, 79, 77, 66, 73, 78, 73, 78, 71, 32, 212, 18, 6, 78, 69, 85, 77, 69, + 32, 181, 38, 17, 80, 82, 73, 90, 78, 65, 75, 32, 77, 79, 68, 73, 70, 73, + 69, 82, 32, 128, 1, 144, 2, 17, 76, 79, 87, 69, 82, 32, 84, 79, 78, 65, + 76, 32, 82, 65, 78, 71, 69, 88, 5, 77, 65, 82, 75, 32, 148, 3, 18, 65, + 84, 84, 65, 67, 72, 73, 78, 71, 32, 86, 69, 82, 84, 73, 67, 65, 76, 221, + 11, 17, 84, 79, 78, 65, 76, 32, 82, 65, 78, 71, 69, 32, 77, 65, 82, 75, + 32, 2, 33, 6, 32, 73, 78, 68, 73, 67, 2, 11, 65, 2, 11, 84, 2, 11, 79, 2, + 207, 56, 82, 118, 182, 2, 67, 142, 1, 68, 104, 8, 71, 79, 82, 65, 90, 68, + 79, 32, 34, 78, 106, 75, 114, 79, 72, 2, 80, 79, 140, 2, 8, 77, 65, 76, + 79, 32, 80, 79, 86, 100, 2, 82, 65, 50, 83, 186, 1, 84, 108, 7, 86, 89, + 83, 79, 75, 79, 32, 234, 1, 90, 224, 10, 2, 76, 79, 224, 22, 4, 85, 68, + 65, 82, 129, 6, 4, 66, 79, 82, 90, 6, 60, 6, 72, 65, 83, 72, 75, 65, 29, + 5, 85, 82, 86, 69, 68, 5, 185, 47, 3, 32, 80, 79, 2, 17, 2, 32, 79, 2, + 11, 77, 2, 223, 24, 69, 4, 228, 10, 13, 69, 77, 69, 83, 84, 86, 69, 78, + 78, 89, 32, 90, 65, 217, 14, 6, 86, 79, 69, 84, 79, 67, 10, 30, 78, 89, + 3, 86, 89, 83, 8, 29, 5, 73, 90, 75, 79, 32, 8, 152, 8, 8, 83, 32, 75, + 82, 89, 90, 72, 69, 35, 79, 2, 155, 20, 79, 8, 56, 4, 82, 89, 90, 72, + 138, 6, 65, 233, 39, 2, 85, 80, 5, 21, 3, 32, 79, 78, 2, 11, 32, 2, 191, + 7, 76, 6, 208, 5, 3, 84, 83, 69, 200, 13, 5, 66, 76, 65, 67, 72, 131, 31, + 78, 18, 22, 68, 247, 1, 86, 6, 60, 7, 67, 72, 65, 83, 72, 73, 69, 189, + 22, 3, 86, 69, 82, 5, 29, 5, 32, 87, 73, 84, 72, 2, 17, 2, 32, 86, 2, 29, + 5, 69, 82, 84, 73, 67, 2, 17, 2, 65, 76, 2, 11, 32, 2, 11, 83, 2, 11, 84, + 2, 11, 82, 2, 11, 79, 2, 131, 25, 75, 12, 29, 5, 89, 83, 72, 69, 32, 12, + 22, 83, 251, 3, 79, 8, 154, 3, 32, 229, 2, 4, 84, 82, 65, 78, 4, 28, 2, + 90, 83, 183, 5, 86, 2, 219, 37, 69, 10, 136, 1, 2, 75, 79, 16, 16, 84, + 82, 65, 78, 78, 79, 32, 77, 65, 76, 79, 32, 80, 79, 86, 89, 236, 1, 5, + 82, 69, 68, 78, 69, 231, 26, 79, 2, 239, 42, 66, 2, 11, 83, 2, 183, 22, + 72, 10, 50, 79, 16, 5, 83, 65, 84, 65, 32, 139, 36, 73, 2, 187, 28, 67, + 6, 158, 1, 79, 201, 24, 3, 83, 32, 75, 10, 24, 2, 83, 32, 95, 79, 6, 11, + 75, 6, 44, 6, 72, 79, 75, 72, 76, 79, 247, 24, 82, 4, 11, 77, 4, 17, 2, + 32, 79, 4, 11, 78, 4, 11, 32, 4, 18, 76, 31, 82, 2, 11, 69, 2, 179, 14, + 70, 2, 11, 73, 2, 11, 71, 2, 139, 14, 72, 6, 18, 65, 31, 69, 2, 249, 25, + 3, 68, 69, 82, 4, 22, 86, 239, 10, 76, 2, 199, 38, 79, 6, 60, 5, 77, 82, + 65, 67, 72, 18, 83, 1, 4, 84, 82, 69, 83, 2, 155, 10, 78, 2, 17, 2, 86, + 69, 2, 155, 6, 84, 232, 1, 128, 2, 2, 67, 72, 38, 68, 218, 1, 70, 28, 10, + 71, 79, 76, 85, 66, 67, 72, 73, 75, 32, 158, 1, 75, 160, 2, 6, 77, 69, + 67, 72, 73, 75, 184, 1, 2, 78, 69, 18, 79, 138, 2, 80, 146, 2, 82, 114, + 83, 180, 20, 9, 86, 82, 65, 75, 72, 73, 89, 65, 32, 151, 2, 90, 4, 246, + 11, 69, 209, 10, 2, 65, 83, 10, 74, 69, 98, 85, 16, 9, 86, 65, 32, 86, + 32, 67, 72, 69, 76, 187, 27, 79, 4, 76, 2, 82, 66, 213, 2, 12, 77, 69, + 83, 84, 86, 69, 78, 78, 89, 32, 75, 76, 2, 195, 34, 73, 2, 203, 34, 68, + 2, 11, 78, 2, 231, 36, 85, 2, 11, 73, 2, 147, 34, 84, 10, 78, 84, 38, 83, + 240, 3, 5, 77, 82, 65, 67, 72, 145, 14, 4, 66, 79, 82, 90, 4, 32, 3, 82, + 69, 83, 251, 1, 73, 2, 21, 3, 86, 69, 84, 2, 231, 17, 76, 14, 76, 4, 72, + 65, 77, 73, 18, 76, 40, 3, 79, 66, 89, 16, 2, 82, 89, 87, 85, 2, 219, 3, + 76, 2, 11, 89, 2, 11, 85, 2, 151, 33, 67, 2, 223, 31, 76, 6, 28, 2, 85, + 75, 219, 32, 90, 5, 21, 3, 32, 84, 73, 2, 11, 75, 2, 251, 15, 72, 2, 11, + 70, 2, 11, 73, 2, 11, 83, 2, 215, 30, 77, 11, 11, 32, 8, 44, 7, 75, 76, + 89, 85, 67, 72, 69, 83, 80, 6, 64, 9, 78, 69, 80, 79, 83, 84, 79, 89, 65, + 14, 80, 163, 14, 86, 2, 39, 78, 2, 25, 4, 79, 86, 79, 68, 2, 143, 14, 78, + 2, 223, 22, 77, 14, 40, 2, 66, 76, 41, 4, 83, 79, 75, 65, 2, 11, 65, 2, + 11, 75, 2, 243, 30, 79, 13, 11, 32, 10, 30, 75, 142, 26, 84, 39, 83, 6, + 104, 11, 76, 89, 85, 67, 72, 69, 86, 65, 89, 65, 32, 185, 25, 10, 82, 89, + 85, 75, 79, 86, 65, 89, 65, 32, 4, 202, 16, 78, 251, 8, 83, 14, 58, 65, + 88, 8, 69, 82, 69, 86, 79, 68, 75, 65, 27, 79, 6, 44, 3, 82, 65, 75, 222, + 19, 76, 211, 5, 85, 2, 11, 76, 2, 11, 73, 2, 171, 28, 84, 5, 153, 15, 2, + 32, 78, 4, 68, 5, 68, 67, 72, 65, 83, 245, 9, 7, 76, 75, 85, 76, 73, 90, + 77, 2, 11, 72, 2, 219, 4, 73, 4, 64, 11, 69, 86, 69, 82, 83, 69, 68, 32, + 67, 72, 69, 139, 26, 79, 2, 25, 4, 76, 89, 85, 83, 2, 215, 17, 84, 126, + 96, 9, 75, 65, 77, 69, 89, 84, 83, 65, 32, 148, 2, 8, 76, 79, 90, 72, 73, + 84, 73, 69, 119, 84, 22, 128, 1, 13, 68, 86, 79, 69, 67, 72, 69, 76, 78, + 65, 89, 65, 32, 44, 7, 75, 76, 89, 85, 67, 72, 69, 74, 84, 218, 18, 77, + 119, 83, 8, 218, 10, 75, 110, 78, 178, 8, 80, 75, 83, 6, 40, 5, 86, 65, + 89, 65, 32, 243, 10, 78, 4, 178, 15, 84, 183, 4, 83, 4, 162, 15, 73, 147, + 4, 82, 9, 11, 32, 6, 48, 2, 83, 32, 25, 6, 90, 65, 75, 82, 89, 84, 4, + 166, 4, 75, 95, 90, 2, 11, 79, 2, 211, 22, 69, 96, 92, 4, 65, 84, 89, 65, + 172, 4, 6, 79, 80, 73, 84, 83, 65, 189, 1, 5, 82, 69, 76, 65, 32, 23, 11, + 32, 20, 76, 2, 83, 32, 236, 2, 9, 90, 65, 75, 82, 89, 84, 65, 89, 65, + 159, 5, 78, 14, 160, 1, 14, 68, 86, 85, 77, 89, 65, 32, 90, 65, 80, 89, + 65, 84, 89, 28, 7, 75, 82, 89, 90, 72, 69, 77, 24, 2, 82, 79, 17, 8, 90, + 65, 80, 89, 65, 84, 79, 89, 2, 11, 77, 2, 215, 19, 73, 5, 189, 1, 2, 32, + 73, 2, 203, 2, 71, 7, 21, 3, 32, 73, 32, 4, 54, 75, 37, 9, 80, 79, 68, + 67, 72, 65, 83, 72, 73, 2, 11, 82, 2, 21, 3, 89, 90, 72, 2, 211, 1, 69, + 5, 17, 2, 32, 83, 2, 17, 2, 32, 90, 2, 29, 5, 65, 80, 89, 65, 84, 2, 11, + 79, 2, 199, 17, 89, 7, 11, 32, 4, 68, 6, 83, 32, 79, 67, 72, 75, 29, 7, + 87, 73, 84, 72, 32, 83, 79, 2, 11, 79, 2, 215, 16, 77, 2, 45, 9, 82, 79, + 67, 72, 89, 65, 32, 78, 79, 2, 11, 90, 2, 163, 7, 72, 68, 140, 1, 9, 68, + 86, 79, 69, 67, 72, 69, 76, 78, 162, 1, 75, 78, 78, 174, 1, 71, 152, 3, + 8, 77, 82, 65, 67, 72, 78, 79, 84, 42, 80, 75, 84, 10, 18, 79, 71, 65, 6, + 64, 7, 80, 79, 86, 79, 68, 78, 65, 189, 5, 4, 75, 82, 89, 90, 4, 17, 2, + 89, 65, 5, 17, 2, 32, 75, 2, 145, 5, 4, 76, 89, 85, 67, 26, 48, 6, 76, + 89, 85, 67, 72, 69, 77, 2, 82, 89, 4, 22, 78, 203, 6, 80, 2, 157, 8, 9, + 69, 80, 79, 83, 84, 79, 89, 65, 78, 22, 48, 7, 85, 75, 79, 86, 65, 89, + 65, 195, 3, 90, 21, 11, 32, 18, 54, 71, 236, 2, 5, 84, 82, 89, 65, 83, + 179, 2, 80, 14, 21, 3, 82, 79, 77, 14, 32, 4, 78, 65, 89, 65, 47, 79, 5, + 237, 1, 7, 32, 87, 73, 84, 72, 32, 83, 10, 92, 10, 75, 82, 89, 90, 72, + 69, 86, 65, 89, 65, 17, 9, 80, 79, 86, 79, 68, 78, 65, 89, 65, 5, 175, 2, + 32, 7, 33, 6, 32, 87, 73, 84, 72, 32, 4, 24, 2, 68, 79, 23, 83, 2, 41, 2, + 85, 66, 2, 21, 3, 73, 78, 71, 2, 133, 6, 6, 76, 69, 32, 90, 65, 80, 2, + 175, 6, 75, 2, 237, 5, 3, 72, 69, 86, 2, 11, 73, 2, 11, 75, 2, 187, 5, + 72, 6, 22, 79, 187, 3, 82, 4, 28, 2, 76, 85, 187, 1, 86, 2, 163, 1, 80, + 8, 80, 5, 82, 89, 65, 83, 79, 153, 2, 10, 73, 75, 72, 65, 89, 65, 32, 80, + 85, 84, 6, 62, 80, 44, 4, 83, 84, 82, 69, 173, 1, 4, 71, 76, 65, 83, 2, + 17, 2, 79, 86, 2, 193, 1, 2, 79, 68, 2, 171, 1, 76, 16, 88, 12, 75, 76, + 89, 85, 67, 72, 69, 86, 65, 89, 65, 32, 38, 77, 46, 80, 38, 84, 39, 83, + 8, 34, 77, 46, 80, 38, 84, 39, 83, 2, 25, 4, 82, 65, 67, 72, 2, 247, 1, + 78, 2, 11, 82, 2, 205, 1, 2, 79, 83, 2, 11, 82, 2, 11, 69, 2, 11, 83, 2, + 157, 1, 4, 86, 69, 84, 76, 6, 30, 65, 121, 3, 77, 69, 89, 4, 32, 4, 78, + 79, 90, 72, 31, 80, 2, 11, 69, 2, 151, 3, 75, 2, 17, 2, 89, 65, 2, 11, + 84, 2, 11, 65, 2, 35, 89, 2, 11, 84, 2, 11, 83, 2, 183, 2, 65, 10, 108, + 11, 68, 73, 82, 69, 67, 84, 73, 79, 78, 32, 70, 28, 3, 75, 82, 89, 28, 5, + 76, 69, 86, 69, 76, 35, 82, 2, 11, 76, 2, 159, 1, 73, 2, 11, 90, 2, 143, + 1, 72, 4, 11, 45, 4, 114, 50, 3, 51, 2, 11, 79, 2, 83, 71, 8, 26, 78, 34, + 83, 15, 74, 4, 18, 66, 27, 74, 2, 11, 83, 2, 11, 80, 3, 0, }; -/* code->name phrasebook */ -#define phrasebook_shift 7 -#define phrasebook_short 190 -static const unsigned char phrasebook[] = { - 0, 201, 247, 233, 216, 77, 207, 252, 77, 31, 56, 236, 155, 56, 210, 13, - 56, 251, 137, 251, 49, 45, 210, 113, 50, 210, 113, 250, 193, 108, 56, - 242, 74, 228, 87, 232, 80, 201, 63, 202, 23, 17, 191, 77, 17, 107, 17, - 109, 17, 138, 17, 134, 17, 149, 17, 169, 17, 175, 17, 171, 17, 178, 242, - 83, 204, 25, 219, 180, 56, 234, 43, 56, 230, 204, 56, 208, 13, 77, 242, - 72, 250, 182, 8, 6, 1, 65, 8, 6, 1, 250, 120, 8, 6, 1, 247, 193, 8, 6, 1, - 238, 127, 8, 6, 1, 71, 8, 6, 1, 233, 175, 8, 6, 1, 232, 51, 8, 6, 1, 230, - 116, 8, 6, 1, 68, 8, 6, 1, 223, 35, 8, 6, 1, 222, 152, 8, 6, 1, 172, 8, - 6, 1, 218, 168, 8, 6, 1, 215, 61, 8, 6, 1, 74, 8, 6, 1, 210, 236, 8, 6, - 1, 208, 104, 8, 6, 1, 146, 8, 6, 1, 206, 8, 8, 6, 1, 200, 43, 8, 6, 1, - 66, 8, 6, 1, 196, 12, 8, 6, 1, 193, 224, 8, 6, 1, 192, 235, 8, 6, 1, 192, - 159, 8, 6, 1, 191, 166, 45, 51, 248, 53, 207, 19, 202, 23, 50, 51, 248, - 53, 243, 2, 252, 60, 130, 219, 112, 230, 211, 252, 60, 8, 2, 1, 65, 8, 2, - 1, 250, 120, 8, 2, 1, 247, 193, 8, 2, 1, 238, 127, 8, 2, 1, 71, 8, 2, 1, - 233, 175, 8, 2, 1, 232, 51, 8, 2, 1, 230, 116, 8, 2, 1, 68, 8, 2, 1, 223, - 35, 8, 2, 1, 222, 152, 8, 2, 1, 172, 8, 2, 1, 218, 168, 8, 2, 1, 215, 61, - 8, 2, 1, 74, 8, 2, 1, 210, 236, 8, 2, 1, 208, 104, 8, 2, 1, 146, 8, 2, 1, - 206, 8, 8, 2, 1, 200, 43, 8, 2, 1, 66, 8, 2, 1, 196, 12, 8, 2, 1, 193, - 224, 8, 2, 1, 192, 235, 8, 2, 1, 192, 159, 8, 2, 1, 191, 166, 45, 238, - 171, 248, 53, 81, 219, 112, 50, 238, 171, 248, 53, 198, 152, 213, 37, - 201, 247, 223, 93, 233, 216, 77, 247, 24, 56, 209, 8, 56, 238, 170, 56, - 192, 71, 56, 248, 22, 164, 205, 54, 56, 237, 42, 239, 6, 56, 233, 40, - 211, 50, 223, 144, 219, 219, 55, 251, 116, 207, 252, 77, 213, 12, 56, - 202, 32, 228, 88, 207, 78, 56, 217, 146, 237, 125, 56, 209, 80, 56, 200, - 182, 109, 200, 182, 138, 252, 47, 252, 60, 216, 91, 56, 209, 142, 56, 82, - 236, 140, 247, 35, 200, 182, 107, 217, 40, 211, 50, 223, 144, 206, 203, - 55, 251, 116, 207, 252, 77, 193, 246, 232, 118, 91, 208, 22, 193, 246, - 232, 118, 91, 230, 70, 193, 246, 232, 118, 115, 208, 20, 223, 93, 208, - 13, 77, 8, 6, 1, 42, 4, 230, 210, 8, 6, 1, 42, 4, 252, 46, 8, 6, 1, 42, - 4, 243, 1, 8, 6, 1, 42, 4, 198, 152, 8, 6, 1, 42, 4, 237, 42, 8, 6, 1, - 42, 4, 206, 189, 58, 8, 6, 1, 252, 25, 8, 6, 1, 247, 194, 4, 247, 35, 8, - 6, 1, 235, 15, 4, 230, 210, 8, 6, 1, 235, 15, 4, 252, 46, 8, 6, 1, 235, - 15, 4, 243, 1, 8, 6, 1, 235, 15, 4, 237, 42, 8, 6, 1, 228, 74, 4, 230, - 210, 8, 6, 1, 228, 74, 4, 252, 46, 8, 6, 1, 228, 74, 4, 243, 1, 8, 6, 1, - 228, 74, 4, 237, 42, 8, 6, 1, 233, 248, 8, 6, 1, 215, 62, 4, 198, 152, 8, - 6, 1, 187, 4, 230, 210, 8, 6, 1, 187, 4, 252, 46, 8, 6, 1, 187, 4, 243, - 1, 8, 6, 1, 187, 4, 198, 152, 8, 6, 1, 187, 4, 237, 42, 215, 127, 56, 8, - 6, 1, 187, 4, 106, 8, 6, 1, 126, 4, 230, 210, 8, 6, 1, 126, 4, 252, 46, - 8, 6, 1, 126, 4, 243, 1, 8, 6, 1, 126, 4, 237, 42, 8, 6, 1, 192, 160, 4, - 252, 46, 8, 6, 1, 198, 233, 8, 2, 1, 203, 127, 206, 8, 8, 2, 1, 42, 4, - 230, 210, 8, 2, 1, 42, 4, 252, 46, 8, 2, 1, 42, 4, 243, 1, 8, 2, 1, 42, - 4, 198, 152, 8, 2, 1, 42, 4, 237, 42, 8, 2, 1, 42, 4, 206, 189, 58, 8, 2, - 1, 252, 25, 8, 2, 1, 247, 194, 4, 247, 35, 8, 2, 1, 235, 15, 4, 230, 210, - 8, 2, 1, 235, 15, 4, 252, 46, 8, 2, 1, 235, 15, 4, 243, 1, 8, 2, 1, 235, - 15, 4, 237, 42, 8, 2, 1, 228, 74, 4, 230, 210, 8, 2, 1, 228, 74, 4, 252, - 46, 8, 2, 1, 228, 74, 4, 243, 1, 8, 2, 1, 228, 74, 4, 237, 42, 8, 2, 1, - 233, 248, 8, 2, 1, 215, 62, 4, 198, 152, 8, 2, 1, 187, 4, 230, 210, 8, 2, - 1, 187, 4, 252, 46, 8, 2, 1, 187, 4, 243, 1, 8, 2, 1, 187, 4, 198, 152, - 8, 2, 1, 187, 4, 237, 42, 236, 200, 56, 8, 2, 1, 187, 4, 106, 8, 2, 1, - 126, 4, 230, 210, 8, 2, 1, 126, 4, 252, 46, 8, 2, 1, 126, 4, 243, 1, 8, - 2, 1, 126, 4, 237, 42, 8, 2, 1, 192, 160, 4, 252, 46, 8, 2, 1, 198, 233, - 8, 2, 1, 192, 160, 4, 237, 42, 8, 6, 1, 42, 4, 217, 146, 8, 2, 1, 42, 4, - 217, 146, 8, 6, 1, 42, 4, 248, 36, 8, 2, 1, 42, 4, 248, 36, 8, 6, 1, 42, - 4, 211, 138, 8, 2, 1, 42, 4, 211, 138, 8, 6, 1, 247, 194, 4, 252, 46, 8, - 2, 1, 247, 194, 4, 252, 46, 8, 6, 1, 247, 194, 4, 243, 1, 8, 2, 1, 247, - 194, 4, 243, 1, 8, 6, 1, 247, 194, 4, 75, 58, 8, 2, 1, 247, 194, 4, 75, - 58, 8, 6, 1, 247, 194, 4, 247, 92, 8, 2, 1, 247, 194, 4, 247, 92, 8, 6, - 1, 238, 128, 4, 247, 92, 8, 2, 1, 238, 128, 4, 247, 92, 8, 6, 1, 238, - 128, 4, 106, 8, 2, 1, 238, 128, 4, 106, 8, 6, 1, 235, 15, 4, 217, 146, 8, - 2, 1, 235, 15, 4, 217, 146, 8, 6, 1, 235, 15, 4, 248, 36, 8, 2, 1, 235, - 15, 4, 248, 36, 8, 6, 1, 235, 15, 4, 75, 58, 8, 2, 1, 235, 15, 4, 75, 58, - 8, 6, 1, 235, 15, 4, 211, 138, 8, 2, 1, 235, 15, 4, 211, 138, 8, 6, 1, - 235, 15, 4, 247, 92, 8, 2, 1, 235, 15, 4, 247, 92, 8, 6, 1, 232, 52, 4, - 243, 1, 8, 2, 1, 232, 52, 4, 243, 1, 8, 6, 1, 232, 52, 4, 248, 36, 8, 2, - 1, 232, 52, 4, 248, 36, 8, 6, 1, 232, 52, 4, 75, 58, 8, 2, 1, 232, 52, 4, - 75, 58, 8, 6, 1, 232, 52, 4, 247, 35, 8, 2, 1, 232, 52, 4, 247, 35, 8, 6, - 1, 230, 117, 4, 243, 1, 8, 2, 1, 230, 117, 4, 243, 1, 8, 6, 1, 230, 117, - 4, 106, 8, 2, 1, 230, 117, 4, 106, 8, 6, 1, 228, 74, 4, 198, 152, 8, 2, - 1, 228, 74, 4, 198, 152, 8, 6, 1, 228, 74, 4, 217, 146, 8, 2, 1, 228, 74, - 4, 217, 146, 8, 6, 1, 228, 74, 4, 248, 36, 8, 2, 1, 228, 74, 4, 248, 36, - 8, 6, 1, 228, 74, 4, 211, 138, 8, 2, 1, 228, 74, 4, 211, 138, 8, 6, 1, - 228, 74, 4, 75, 58, 8, 2, 1, 236, 139, 68, 8, 6, 34, 223, 197, 8, 2, 34, - 223, 197, 8, 6, 1, 223, 36, 4, 243, 1, 8, 2, 1, 223, 36, 4, 243, 1, 8, 6, - 1, 222, 153, 4, 247, 35, 8, 2, 1, 222, 153, 4, 247, 35, 8, 2, 1, 221, 8, - 8, 6, 1, 220, 143, 4, 252, 46, 8, 2, 1, 220, 143, 4, 252, 46, 8, 6, 1, - 220, 143, 4, 247, 35, 8, 2, 1, 220, 143, 4, 247, 35, 8, 6, 1, 220, 143, - 4, 247, 92, 8, 2, 1, 220, 143, 4, 247, 92, 8, 6, 1, 220, 143, 4, 82, 236, - 140, 8, 2, 1, 220, 143, 4, 82, 236, 140, 8, 6, 1, 220, 143, 4, 106, 8, 2, - 1, 220, 143, 4, 106, 8, 6, 1, 215, 62, 4, 252, 46, 8, 2, 1, 215, 62, 4, - 252, 46, 8, 6, 1, 215, 62, 4, 247, 35, 8, 2, 1, 215, 62, 4, 247, 35, 8, - 6, 1, 215, 62, 4, 247, 92, 8, 2, 1, 215, 62, 4, 247, 92, 8, 2, 1, 215, - 62, 208, 233, 247, 205, 251, 49, 8, 6, 1, 234, 88, 8, 2, 1, 234, 88, 8, - 6, 1, 187, 4, 217, 146, 8, 2, 1, 187, 4, 217, 146, 8, 6, 1, 187, 4, 248, - 36, 8, 2, 1, 187, 4, 248, 36, 8, 6, 1, 187, 4, 55, 252, 46, 8, 2, 1, 187, - 4, 55, 252, 46, 8, 6, 34, 211, 151, 8, 2, 34, 211, 151, 8, 6, 1, 207, - 222, 4, 252, 46, 8, 2, 1, 207, 222, 4, 252, 46, 8, 6, 1, 207, 222, 4, - 247, 35, 8, 2, 1, 207, 222, 4, 247, 35, 8, 6, 1, 207, 222, 4, 247, 92, 8, - 2, 1, 207, 222, 4, 247, 92, 8, 6, 1, 206, 9, 4, 252, 46, 8, 2, 1, 206, 9, - 4, 252, 46, 8, 6, 1, 206, 9, 4, 243, 1, 8, 2, 1, 206, 9, 4, 243, 1, 8, 6, - 1, 206, 9, 4, 247, 35, 8, 2, 1, 206, 9, 4, 247, 35, 8, 6, 1, 206, 9, 4, - 247, 92, 8, 2, 1, 206, 9, 4, 247, 92, 8, 6, 1, 200, 44, 4, 247, 35, 8, 2, - 1, 200, 44, 4, 247, 35, 8, 6, 1, 200, 44, 4, 247, 92, 8, 2, 1, 200, 44, - 4, 247, 92, 8, 6, 1, 200, 44, 4, 106, 8, 2, 1, 200, 44, 4, 106, 8, 6, 1, - 126, 4, 198, 152, 8, 2, 1, 126, 4, 198, 152, 8, 6, 1, 126, 4, 217, 146, - 8, 2, 1, 126, 4, 217, 146, 8, 6, 1, 126, 4, 248, 36, 8, 2, 1, 126, 4, - 248, 36, 8, 6, 1, 126, 4, 206, 189, 58, 8, 2, 1, 126, 4, 206, 189, 58, 8, - 6, 1, 126, 4, 55, 252, 46, 8, 2, 1, 126, 4, 55, 252, 46, 8, 6, 1, 126, 4, - 211, 138, 8, 2, 1, 126, 4, 211, 138, 8, 6, 1, 193, 225, 4, 243, 1, 8, 2, - 1, 193, 225, 4, 243, 1, 8, 6, 1, 192, 160, 4, 243, 1, 8, 2, 1, 192, 160, - 4, 243, 1, 8, 6, 1, 192, 160, 4, 237, 42, 8, 6, 1, 191, 167, 4, 252, 46, - 8, 2, 1, 191, 167, 4, 252, 46, 8, 6, 1, 191, 167, 4, 75, 58, 8, 2, 1, - 191, 167, 4, 75, 58, 8, 6, 1, 191, 167, 4, 247, 92, 8, 2, 1, 191, 167, 4, - 247, 92, 8, 2, 1, 179, 206, 8, 8, 2, 1, 78, 4, 106, 8, 6, 1, 78, 4, 102, - 8, 6, 1, 78, 4, 198, 51, 8, 2, 1, 78, 4, 198, 51, 8, 6, 1, 163, 169, 8, - 2, 1, 163, 169, 8, 6, 1, 211, 77, 74, 8, 6, 1, 247, 194, 4, 102, 8, 2, 1, - 247, 194, 4, 102, 8, 6, 1, 252, 0, 238, 127, 8, 6, 1, 238, 128, 4, 102, - 8, 6, 1, 238, 128, 4, 198, 51, 8, 2, 1, 238, 128, 4, 198, 51, 8, 2, 1, - 153, 237, 106, 8, 6, 1, 207, 18, 71, 8, 6, 1, 205, 86, 8, 6, 1, 211, 77, - 71, 8, 6, 1, 233, 176, 4, 102, 8, 2, 1, 233, 176, 4, 102, 8, 6, 1, 232, - 52, 4, 102, 8, 6, 1, 231, 211, 8, 2, 1, 228, 126, 8, 6, 1, 223, 83, 8, 6, - 1, 228, 74, 4, 106, 8, 6, 1, 222, 153, 4, 102, 8, 2, 1, 222, 153, 4, 102, - 8, 2, 1, 220, 143, 4, 164, 8, 2, 1, 220, 33, 4, 106, 8, 6, 1, 153, 218, - 168, 8, 6, 1, 215, 62, 4, 45, 102, 8, 2, 1, 215, 62, 4, 179, 50, 219, - 212, 8, 6, 1, 187, 4, 82, 198, 152, 8, 6, 1, 187, 4, 228, 187, 8, 2, 1, - 187, 4, 228, 187, 8, 6, 1, 211, 133, 8, 2, 1, 211, 133, 8, 6, 1, 210, - 237, 4, 102, 8, 2, 1, 210, 237, 4, 102, 8, 1, 191, 228, 8, 6, 1, 163, - 109, 8, 2, 1, 163, 109, 8, 6, 1, 234, 12, 8, 1, 207, 18, 234, 13, 219, 4, - 8, 2, 1, 200, 44, 4, 210, 192, 102, 8, 6, 1, 200, 44, 4, 102, 8, 2, 1, - 200, 44, 4, 102, 8, 6, 1, 200, 44, 4, 207, 24, 102, 8, 6, 1, 126, 4, 228, - 187, 8, 2, 1, 126, 4, 228, 187, 8, 6, 1, 196, 70, 8, 6, 1, 196, 13, 4, - 102, 8, 6, 1, 192, 160, 4, 102, 8, 2, 1, 192, 160, 4, 102, 8, 6, 1, 191, - 167, 4, 106, 8, 2, 1, 191, 167, 4, 106, 8, 6, 1, 233, 178, 8, 6, 1, 233, - 179, 207, 17, 8, 2, 1, 233, 179, 207, 17, 8, 2, 1, 233, 179, 4, 199, 215, - 8, 1, 105, 4, 106, 8, 6, 1, 163, 149, 8, 2, 1, 163, 149, 8, 1, 223, 93, - 231, 11, 201, 64, 4, 106, 8, 1, 192, 238, 8, 1, 237, 98, 242, 231, 8, 1, - 220, 3, 242, 231, 8, 1, 251, 150, 242, 231, 8, 1, 207, 24, 242, 231, 8, - 6, 1, 235, 37, 4, 247, 92, 8, 6, 1, 238, 128, 4, 2, 1, 191, 167, 4, 247, - 92, 8, 2, 1, 235, 37, 4, 247, 92, 8, 6, 1, 219, 77, 8, 6, 1, 220, 143, 4, - 2, 1, 223, 35, 8, 2, 1, 219, 77, 8, 6, 1, 213, 158, 8, 6, 1, 215, 62, 4, - 2, 1, 223, 35, 8, 2, 1, 213, 158, 8, 6, 1, 42, 4, 247, 92, 8, 2, 1, 42, - 4, 247, 92, 8, 6, 1, 228, 74, 4, 247, 92, 8, 2, 1, 228, 74, 4, 247, 92, - 8, 6, 1, 187, 4, 247, 92, 8, 2, 1, 187, 4, 247, 92, 8, 6, 1, 126, 4, 247, - 92, 8, 2, 1, 126, 4, 247, 92, 8, 6, 1, 126, 4, 237, 43, 23, 217, 146, 8, - 2, 1, 126, 4, 237, 43, 23, 217, 146, 8, 6, 1, 126, 4, 237, 43, 23, 252, - 46, 8, 2, 1, 126, 4, 237, 43, 23, 252, 46, 8, 6, 1, 126, 4, 237, 43, 23, - 247, 92, 8, 2, 1, 126, 4, 237, 43, 23, 247, 92, 8, 6, 1, 126, 4, 237, 43, - 23, 230, 210, 8, 2, 1, 126, 4, 237, 43, 23, 230, 210, 8, 2, 1, 153, 71, - 8, 6, 1, 42, 4, 237, 43, 23, 217, 146, 8, 2, 1, 42, 4, 237, 43, 23, 217, - 146, 8, 6, 1, 42, 4, 75, 93, 23, 217, 146, 8, 2, 1, 42, 4, 75, 93, 23, - 217, 146, 8, 6, 1, 252, 26, 4, 217, 146, 8, 2, 1, 252, 26, 4, 217, 146, - 8, 6, 1, 232, 52, 4, 106, 8, 2, 1, 232, 52, 4, 106, 8, 6, 1, 232, 52, 4, - 247, 92, 8, 2, 1, 232, 52, 4, 247, 92, 8, 6, 1, 222, 153, 4, 247, 92, 8, - 2, 1, 222, 153, 4, 247, 92, 8, 6, 1, 187, 4, 211, 138, 8, 2, 1, 187, 4, - 211, 138, 8, 6, 1, 187, 4, 211, 139, 23, 217, 146, 8, 2, 1, 187, 4, 211, - 139, 23, 217, 146, 8, 6, 1, 233, 179, 4, 247, 92, 8, 2, 1, 233, 179, 4, - 247, 92, 8, 2, 1, 223, 36, 4, 247, 92, 8, 6, 1, 235, 36, 8, 6, 1, 238, - 128, 4, 2, 1, 191, 166, 8, 2, 1, 235, 36, 8, 6, 1, 232, 52, 4, 252, 46, - 8, 2, 1, 232, 52, 4, 252, 46, 8, 6, 1, 228, 123, 8, 6, 1, 192, 238, 8, 6, - 1, 215, 62, 4, 230, 210, 8, 2, 1, 215, 62, 4, 230, 210, 8, 6, 1, 42, 4, - 206, 189, 93, 23, 252, 46, 8, 2, 1, 42, 4, 206, 189, 93, 23, 252, 46, 8, - 6, 1, 252, 26, 4, 252, 46, 8, 2, 1, 252, 26, 4, 252, 46, 8, 6, 1, 187, 4, - 201, 28, 23, 252, 46, 8, 2, 1, 187, 4, 201, 28, 23, 252, 46, 8, 6, 1, 42, - 4, 55, 230, 210, 8, 2, 1, 42, 4, 55, 230, 210, 8, 6, 1, 42, 4, 223, 93, - 248, 36, 8, 2, 1, 42, 4, 223, 93, 248, 36, 8, 6, 1, 235, 15, 4, 55, 230, - 210, 8, 2, 1, 235, 15, 4, 55, 230, 210, 8, 6, 1, 235, 15, 4, 223, 93, - 248, 36, 8, 2, 1, 235, 15, 4, 223, 93, 248, 36, 8, 6, 1, 228, 74, 4, 55, - 230, 210, 8, 2, 1, 228, 74, 4, 55, 230, 210, 8, 6, 1, 228, 74, 4, 223, - 93, 248, 36, 8, 2, 1, 228, 74, 4, 223, 93, 248, 36, 8, 6, 1, 187, 4, 55, - 230, 210, 8, 2, 1, 187, 4, 55, 230, 210, 8, 6, 1, 187, 4, 223, 93, 248, - 36, 8, 2, 1, 187, 4, 223, 93, 248, 36, 8, 6, 1, 207, 222, 4, 55, 230, - 210, 8, 2, 1, 207, 222, 4, 55, 230, 210, 8, 6, 1, 207, 222, 4, 223, 93, - 248, 36, 8, 2, 1, 207, 222, 4, 223, 93, 248, 36, 8, 6, 1, 126, 4, 55, - 230, 210, 8, 2, 1, 126, 4, 55, 230, 210, 8, 6, 1, 126, 4, 223, 93, 248, - 36, 8, 2, 1, 126, 4, 223, 93, 248, 36, 8, 6, 1, 206, 9, 4, 242, 75, 60, - 8, 2, 1, 206, 9, 4, 242, 75, 60, 8, 6, 1, 200, 44, 4, 242, 75, 60, 8, 2, - 1, 200, 44, 4, 242, 75, 60, 8, 6, 1, 191, 248, 8, 2, 1, 191, 248, 8, 6, - 1, 230, 117, 4, 247, 92, 8, 2, 1, 230, 117, 4, 247, 92, 8, 6, 1, 215, 62, - 4, 179, 50, 219, 212, 8, 2, 1, 238, 128, 4, 238, 175, 8, 6, 1, 211, 19, - 8, 2, 1, 211, 19, 8, 6, 1, 191, 167, 4, 102, 8, 2, 1, 191, 167, 4, 102, - 8, 6, 1, 42, 4, 75, 58, 8, 2, 1, 42, 4, 75, 58, 8, 6, 1, 235, 15, 4, 247, - 35, 8, 2, 1, 235, 15, 4, 247, 35, 8, 6, 1, 187, 4, 237, 43, 23, 217, 146, - 8, 2, 1, 187, 4, 237, 43, 23, 217, 146, 8, 6, 1, 187, 4, 198, 153, 23, - 217, 146, 8, 2, 1, 187, 4, 198, 153, 23, 217, 146, 8, 6, 1, 187, 4, 75, - 58, 8, 2, 1, 187, 4, 75, 58, 8, 6, 1, 187, 4, 75, 93, 23, 217, 146, 8, 2, - 1, 187, 4, 75, 93, 23, 217, 146, 8, 6, 1, 192, 160, 4, 217, 146, 8, 2, 1, - 192, 160, 4, 217, 146, 8, 2, 1, 220, 143, 4, 238, 175, 8, 2, 1, 215, 62, - 4, 238, 175, 8, 2, 1, 200, 44, 4, 238, 175, 8, 2, 1, 236, 139, 223, 35, - 8, 2, 1, 237, 201, 237, 2, 8, 2, 1, 208, 34, 237, 2, 8, 6, 1, 42, 4, 106, - 8, 6, 1, 247, 194, 4, 106, 8, 2, 1, 247, 194, 4, 106, 8, 6, 1, 220, 143, - 4, 164, 8, 6, 1, 200, 44, 4, 237, 39, 106, 8, 2, 1, 206, 9, 4, 200, 146, - 199, 215, 8, 2, 1, 191, 167, 4, 200, 146, 199, 215, 8, 6, 1, 231, 11, - 201, 63, 8, 2, 1, 231, 11, 201, 63, 8, 6, 1, 78, 4, 106, 8, 6, 1, 126, - 164, 8, 6, 1, 153, 196, 12, 8, 6, 1, 235, 15, 4, 106, 8, 2, 1, 235, 15, - 4, 106, 8, 6, 1, 223, 36, 4, 106, 8, 2, 1, 223, 36, 4, 106, 8, 6, 1, 2, - 208, 105, 4, 228, 251, 199, 215, 8, 2, 1, 208, 105, 4, 228, 251, 199, - 215, 8, 6, 1, 207, 222, 4, 106, 8, 2, 1, 207, 222, 4, 106, 8, 6, 1, 192, - 160, 4, 106, 8, 2, 1, 192, 160, 4, 106, 8, 2, 1, 153, 65, 8, 2, 1, 251, - 160, 8, 2, 1, 153, 251, 160, 8, 2, 1, 78, 4, 102, 8, 2, 1, 211, 77, 74, - 8, 2, 1, 247, 194, 4, 238, 175, 8, 2, 1, 238, 128, 4, 199, 215, 8, 2, 1, - 238, 128, 4, 102, 8, 2, 1, 207, 18, 71, 8, 2, 1, 205, 86, 8, 2, 1, 205, - 87, 4, 102, 8, 2, 1, 211, 77, 71, 8, 2, 1, 207, 18, 211, 77, 71, 8, 2, 1, - 207, 18, 211, 77, 235, 15, 4, 102, 8, 2, 1, 242, 219, 207, 18, 211, 77, - 71, 8, 2, 1, 236, 139, 223, 36, 4, 106, 8, 2, 1, 232, 52, 4, 102, 8, 2, - 1, 27, 232, 51, 8, 1, 2, 6, 232, 51, 8, 2, 1, 231, 211, 8, 2, 1, 207, - 140, 228, 187, 8, 2, 1, 153, 230, 116, 8, 2, 1, 230, 117, 4, 102, 8, 2, - 1, 229, 197, 4, 102, 8, 2, 1, 228, 74, 4, 106, 8, 2, 1, 223, 83, 8, 1, 2, - 6, 68, 8, 2, 1, 220, 143, 4, 82, 198, 152, 8, 2, 1, 220, 143, 4, 248, - 231, 8, 2, 1, 220, 143, 4, 207, 24, 102, 8, 2, 1, 219, 162, 8, 2, 1, 153, - 218, 168, 8, 2, 1, 153, 218, 169, 4, 179, 219, 212, 8, 2, 1, 218, 169, 4, - 102, 8, 2, 1, 215, 62, 4, 45, 102, 8, 2, 1, 215, 62, 4, 207, 24, 102, 8, - 1, 2, 6, 215, 61, 8, 2, 1, 249, 82, 74, 8, 1, 2, 6, 211, 151, 8, 2, 1, - 242, 219, 211, 110, 8, 2, 1, 209, 211, 8, 2, 1, 153, 146, 8, 2, 1, 153, - 207, 222, 4, 179, 219, 212, 8, 2, 1, 153, 207, 222, 4, 102, 8, 2, 1, 207, - 222, 4, 179, 219, 212, 8, 2, 1, 207, 222, 4, 199, 215, 8, 2, 1, 207, 222, - 4, 232, 233, 8, 2, 1, 207, 18, 207, 222, 4, 232, 233, 8, 1, 2, 6, 146, 8, - 1, 2, 6, 223, 93, 146, 8, 2, 1, 206, 9, 4, 102, 8, 2, 1, 234, 12, 8, 2, - 1, 236, 139, 223, 36, 4, 201, 28, 23, 102, 8, 2, 1, 201, 187, 207, 18, - 234, 12, 8, 2, 1, 234, 13, 4, 238, 175, 8, 2, 1, 153, 200, 43, 8, 2, 1, - 200, 44, 4, 207, 24, 102, 8, 2, 1, 126, 164, 8, 2, 1, 196, 70, 8, 2, 1, - 196, 13, 4, 102, 8, 2, 1, 153, 196, 12, 8, 2, 1, 153, 193, 224, 8, 2, 1, - 153, 192, 159, 8, 1, 2, 6, 192, 159, 8, 2, 1, 191, 167, 4, 207, 24, 102, - 8, 2, 1, 191, 167, 4, 238, 175, 8, 2, 1, 233, 178, 8, 2, 1, 233, 179, 4, - 238, 175, 8, 1, 231, 11, 201, 63, 8, 1, 209, 219, 195, 20, 232, 104, 8, - 1, 223, 93, 231, 11, 201, 63, 8, 1, 201, 36, 247, 193, 8, 1, 248, 172, - 242, 231, 8, 1, 2, 6, 250, 120, 8, 2, 1, 242, 219, 211, 77, 71, 8, 1, 2, - 6, 232, 52, 4, 102, 8, 1, 2, 6, 230, 116, 8, 2, 1, 223, 36, 4, 238, 212, - 8, 2, 1, 153, 222, 152, 8, 1, 2, 6, 172, 8, 2, 1, 208, 105, 4, 102, 8, 1, - 231, 11, 201, 64, 4, 106, 8, 1, 207, 18, 231, 11, 201, 64, 4, 106, 8, 2, - 1, 235, 37, 237, 2, 8, 2, 1, 237, 70, 237, 2, 8, 2, 1, 235, 37, 237, 3, - 4, 238, 175, 8, 2, 1, 197, 170, 237, 2, 8, 2, 1, 199, 79, 237, 2, 8, 2, - 1, 199, 152, 237, 3, 4, 238, 175, 8, 2, 1, 233, 37, 237, 2, 8, 2, 1, 218, - 227, 237, 2, 8, 2, 1, 218, 170, 237, 2, 8, 1, 248, 172, 210, 12, 8, 1, - 248, 180, 210, 12, 8, 2, 1, 153, 230, 117, 4, 232, 233, 8, 2, 1, 153, - 230, 117, 4, 232, 234, 23, 199, 215, 52, 1, 2, 230, 116, 52, 1, 2, 230, - 117, 4, 102, 52, 1, 2, 223, 35, 52, 1, 2, 146, 52, 1, 2, 153, 146, 52, 1, - 2, 153, 207, 222, 4, 102, 52, 1, 2, 6, 223, 93, 146, 52, 1, 2, 193, 224, - 52, 1, 2, 192, 159, 52, 1, 208, 215, 52, 1, 55, 208, 215, 52, 1, 153, - 242, 74, 52, 1, 251, 49, 52, 1, 207, 18, 242, 74, 52, 1, 50, 132, 206, - 188, 52, 1, 45, 132, 206, 188, 52, 1, 231, 11, 201, 63, 52, 1, 207, 18, - 231, 11, 201, 63, 52, 1, 45, 250, 235, 52, 1, 50, 250, 235, 52, 1, 133, - 250, 235, 52, 1, 144, 250, 235, 52, 1, 243, 2, 252, 60, 247, 92, 52, 1, - 81, 219, 112, 52, 1, 217, 146, 52, 1, 252, 47, 252, 60, 52, 1, 230, 211, - 252, 60, 52, 1, 130, 81, 219, 112, 52, 1, 130, 217, 146, 52, 1, 130, 230, - 211, 252, 60, 52, 1, 130, 252, 47, 252, 60, 52, 1, 197, 238, 242, 83, 52, - 1, 132, 197, 238, 242, 83, 52, 1, 247, 20, 50, 132, 206, 188, 52, 1, 247, - 20, 45, 132, 206, 188, 52, 1, 133, 199, 228, 52, 1, 144, 199, 228, 52, 1, - 108, 56, 52, 1, 216, 35, 56, 248, 36, 75, 58, 206, 189, 58, 211, 138, 2, - 198, 152, 55, 252, 47, 252, 60, 52, 1, 207, 2, 102, 52, 1, 238, 218, 252, - 60, 52, 1, 2, 231, 211, 52, 1, 2, 172, 52, 1, 2, 206, 8, 52, 1, 2, 192, - 235, 52, 1, 2, 207, 18, 231, 11, 201, 63, 52, 1, 233, 200, 163, 164, 52, - 1, 137, 163, 164, 52, 1, 216, 87, 163, 164, 52, 1, 130, 163, 164, 52, 1, - 233, 199, 163, 164, 52, 1, 192, 22, 237, 95, 163, 77, 52, 1, 192, 107, - 237, 95, 163, 77, 52, 1, 195, 18, 52, 1, 196, 109, 52, 1, 55, 251, 49, - 52, 1, 130, 144, 250, 235, 52, 1, 130, 133, 250, 235, 52, 1, 130, 45, - 250, 235, 52, 1, 130, 50, 250, 235, 52, 1, 130, 206, 188, 52, 1, 82, 230, - 211, 252, 60, 52, 1, 82, 55, 230, 211, 252, 60, 52, 1, 82, 55, 252, 47, - 252, 60, 52, 1, 130, 198, 152, 52, 1, 207, 147, 242, 83, 52, 1, 248, 249, - 137, 198, 79, 52, 1, 234, 95, 137, 198, 79, 52, 1, 248, 249, 130, 198, - 79, 52, 1, 234, 95, 130, 198, 79, 52, 1, 203, 104, 52, 1, 211, 77, 203, - 104, 52, 1, 130, 45, 57, 33, 230, 211, 252, 60, 33, 252, 47, 252, 60, 33, - 243, 2, 252, 60, 33, 198, 152, 33, 217, 146, 33, 210, 254, 33, 248, 36, - 33, 75, 58, 33, 237, 42, 33, 228, 251, 58, 33, 206, 189, 58, 33, 55, 252, - 47, 252, 60, 33, 247, 92, 33, 81, 219, 113, 58, 33, 55, 81, 219, 113, 58, - 33, 55, 230, 211, 252, 60, 33, 247, 119, 33, 223, 93, 248, 36, 33, 153, - 242, 75, 58, 33, 242, 75, 58, 33, 207, 18, 242, 75, 58, 33, 242, 75, 93, - 183, 33, 230, 211, 252, 61, 60, 33, 252, 47, 252, 61, 60, 33, 45, 199, - 229, 60, 33, 50, 199, 229, 60, 33, 45, 251, 116, 58, 33, 228, 187, 33, - 45, 132, 206, 189, 60, 33, 133, 199, 229, 60, 33, 144, 199, 229, 60, 33, - 108, 3, 60, 33, 216, 35, 3, 60, 33, 210, 190, 228, 251, 60, 33, 207, 24, - 228, 251, 60, 33, 75, 60, 33, 237, 43, 60, 33, 206, 189, 60, 33, 242, 75, - 60, 33, 247, 35, 33, 211, 138, 33, 81, 219, 113, 60, 33, 248, 29, 60, 33, - 223, 93, 55, 251, 15, 60, 33, 247, 93, 60, 33, 243, 2, 252, 61, 60, 33, - 248, 37, 60, 33, 223, 93, 248, 37, 60, 33, 198, 153, 60, 33, 217, 147, - 60, 33, 130, 219, 112, 33, 55, 130, 219, 112, 33, 198, 153, 210, 255, 33, - 203, 40, 201, 28, 210, 255, 33, 179, 201, 28, 210, 255, 33, 203, 40, 202, - 24, 210, 255, 33, 179, 202, 24, 210, 255, 33, 50, 132, 206, 189, 60, 33, - 223, 93, 248, 29, 60, 33, 51, 60, 33, 205, 62, 60, 33, 192, 236, 58, 33, - 81, 198, 152, 33, 55, 210, 254, 33, 230, 211, 163, 77, 33, 252, 47, 163, - 77, 33, 35, 210, 4, 33, 35, 221, 30, 33, 35, 237, 36, 198, 60, 33, 35, - 191, 233, 33, 248, 29, 58, 33, 234, 43, 3, 60, 33, 55, 81, 219, 113, 60, - 33, 45, 251, 116, 60, 33, 213, 12, 198, 153, 58, 33, 229, 1, 58, 33, 251, - 165, 234, 45, 119, 58, 33, 45, 50, 64, 60, 33, 196, 66, 64, 60, 33, 230, - 217, 222, 196, 33, 50, 250, 236, 58, 33, 45, 132, 206, 189, 58, 33, 233, - 34, 33, 192, 236, 60, 33, 45, 250, 236, 60, 33, 50, 250, 236, 60, 33, 50, - 250, 236, 23, 133, 250, 236, 60, 33, 50, 132, 206, 189, 58, 33, 75, 93, - 183, 33, 250, 194, 60, 33, 55, 206, 189, 60, 33, 191, 21, 58, 33, 55, - 248, 37, 60, 33, 55, 248, 36, 33, 55, 217, 146, 33, 55, 217, 147, 60, 33, - 55, 198, 152, 33, 55, 223, 93, 248, 36, 33, 55, 96, 64, 60, 33, 8, 2, 1, - 65, 33, 8, 2, 1, 71, 33, 8, 2, 1, 68, 33, 8, 2, 1, 74, 33, 8, 2, 1, 66, - 33, 8, 2, 1, 247, 193, 33, 8, 2, 1, 238, 127, 33, 8, 2, 1, 230, 116, 33, - 8, 2, 1, 218, 168, 33, 8, 2, 1, 146, 33, 8, 2, 1, 200, 43, 33, 8, 2, 1, - 196, 12, 33, 8, 2, 1, 192, 235, 35, 6, 1, 229, 185, 35, 2, 1, 229, 185, - 35, 6, 1, 251, 14, 205, 145, 35, 2, 1, 251, 14, 205, 145, 35, 212, 134, - 56, 35, 110, 212, 134, 56, 35, 6, 1, 210, 171, 237, 10, 35, 2, 1, 210, - 171, 237, 10, 35, 191, 233, 35, 2, 207, 18, 218, 206, 202, 197, 113, 35, - 2, 235, 138, 218, 206, 202, 197, 113, 35, 2, 207, 18, 235, 138, 218, 206, - 202, 197, 113, 35, 208, 13, 77, 35, 6, 1, 191, 240, 35, 198, 60, 35, 237, - 36, 198, 60, 35, 6, 1, 251, 161, 4, 198, 60, 35, 251, 94, 199, 108, 35, - 6, 1, 234, 48, 4, 198, 60, 35, 6, 1, 233, 254, 4, 198, 60, 35, 6, 1, 223, - 84, 4, 198, 60, 35, 6, 1, 211, 108, 4, 198, 60, 35, 6, 1, 196, 71, 4, - 198, 60, 35, 6, 1, 211, 111, 4, 198, 60, 35, 2, 1, 223, 84, 4, 237, 36, - 23, 198, 60, 35, 6, 1, 251, 160, 35, 6, 1, 248, 212, 35, 6, 1, 231, 211, - 35, 6, 1, 237, 106, 35, 6, 1, 234, 47, 35, 6, 1, 191, 76, 35, 6, 1, 233, - 253, 35, 6, 1, 199, 15, 35, 6, 1, 223, 83, 35, 6, 1, 222, 72, 35, 6, 1, - 220, 31, 35, 6, 1, 215, 155, 35, 6, 1, 212, 178, 35, 6, 1, 192, 207, 35, - 6, 1, 211, 107, 35, 6, 1, 209, 185, 35, 6, 1, 207, 3, 35, 6, 1, 202, 196, - 35, 6, 1, 199, 166, 35, 6, 1, 196, 70, 35, 6, 1, 209, 211, 35, 6, 1, 243, - 95, 35, 6, 1, 208, 176, 35, 6, 1, 211, 110, 35, 6, 1, 223, 84, 4, 237, - 35, 35, 6, 1, 196, 71, 4, 237, 35, 35, 2, 1, 251, 161, 4, 198, 60, 35, 2, - 1, 234, 48, 4, 198, 60, 35, 2, 1, 233, 254, 4, 198, 60, 35, 2, 1, 223, - 84, 4, 198, 60, 35, 2, 1, 196, 71, 4, 237, 36, 23, 198, 60, 35, 2, 1, - 251, 160, 35, 2, 1, 248, 212, 35, 2, 1, 231, 211, 35, 2, 1, 237, 106, 35, - 2, 1, 234, 47, 35, 2, 1, 191, 76, 35, 2, 1, 233, 253, 35, 2, 1, 199, 15, - 35, 2, 1, 223, 83, 35, 2, 1, 222, 72, 35, 2, 1, 220, 31, 35, 2, 1, 215, - 155, 35, 2, 1, 212, 178, 35, 2, 1, 192, 207, 35, 2, 1, 211, 107, 35, 2, - 1, 209, 185, 35, 2, 1, 207, 3, 35, 2, 1, 53, 202, 196, 35, 2, 1, 202, - 196, 35, 2, 1, 199, 166, 35, 2, 1, 196, 70, 35, 2, 1, 209, 211, 35, 2, 1, - 243, 95, 35, 2, 1, 208, 176, 35, 2, 1, 211, 110, 35, 2, 1, 223, 84, 4, - 237, 35, 35, 2, 1, 196, 71, 4, 237, 35, 35, 2, 1, 211, 108, 4, 198, 60, - 35, 2, 1, 196, 71, 4, 198, 60, 35, 2, 1, 211, 111, 4, 198, 60, 35, 6, - 222, 103, 113, 35, 248, 213, 113, 35, 199, 16, 113, 35, 196, 71, 4, 228, - 251, 113, 35, 196, 71, 4, 252, 47, 23, 228, 251, 113, 35, 196, 71, 4, - 237, 43, 23, 228, 251, 113, 35, 209, 212, 113, 35, 209, 186, 113, 35, - 222, 103, 113, 35, 1, 251, 14, 221, 35, 35, 2, 1, 251, 14, 221, 35, 35, - 1, 201, 73, 35, 2, 1, 201, 73, 35, 1, 237, 10, 35, 2, 1, 237, 10, 35, 1, - 221, 35, 35, 2, 1, 221, 35, 35, 1, 205, 145, 35, 2, 1, 205, 145, 94, 6, - 1, 203, 105, 94, 2, 1, 203, 105, 94, 6, 1, 233, 44, 94, 2, 1, 233, 44, - 94, 6, 1, 221, 195, 94, 2, 1, 221, 195, 94, 6, 1, 228, 242, 94, 2, 1, - 228, 242, 94, 6, 1, 231, 206, 94, 2, 1, 231, 206, 94, 6, 1, 203, 71, 94, - 2, 1, 203, 71, 94, 6, 1, 237, 122, 94, 2, 1, 237, 122, 35, 222, 73, 113, - 35, 207, 4, 113, 35, 218, 206, 202, 197, 113, 35, 1, 191, 240, 35, 6, - 199, 16, 113, 35, 218, 206, 234, 48, 113, 35, 207, 18, 218, 206, 234, 48, - 113, 35, 6, 1, 203, 56, 35, 2, 1, 203, 56, 35, 6, 218, 206, 202, 197, - 113, 35, 6, 1, 205, 142, 35, 2, 1, 205, 142, 35, 207, 4, 4, 201, 28, 113, - 35, 6, 207, 18, 218, 206, 202, 197, 113, 35, 6, 235, 138, 218, 206, 202, - 197, 113, 35, 6, 207, 18, 235, 138, 218, 206, 202, 197, 113, 38, 6, 1, - 223, 227, 4, 230, 210, 38, 6, 1, 223, 88, 38, 6, 1, 236, 192, 38, 6, 1, - 231, 20, 38, 6, 1, 196, 125, 223, 226, 38, 6, 1, 235, 32, 38, 6, 1, 247, - 203, 68, 38, 6, 1, 192, 33, 38, 6, 1, 223, 10, 38, 6, 1, 219, 76, 38, 6, - 1, 213, 150, 38, 6, 1, 197, 155, 38, 6, 1, 221, 103, 38, 6, 1, 228, 74, - 4, 230, 210, 38, 6, 1, 203, 40, 66, 38, 6, 1, 235, 28, 38, 6, 1, 65, 38, - 6, 1, 249, 17, 38, 6, 1, 195, 153, 38, 6, 1, 231, 77, 38, 6, 1, 237, 146, - 38, 6, 1, 223, 226, 38, 6, 1, 191, 62, 38, 6, 1, 191, 87, 38, 6, 1, 68, - 38, 6, 1, 203, 40, 68, 38, 6, 1, 155, 38, 6, 1, 234, 140, 38, 6, 1, 234, - 114, 38, 6, 1, 234, 103, 38, 6, 1, 74, 38, 6, 1, 210, 63, 38, 6, 1, 234, - 34, 38, 6, 1, 234, 22, 38, 6, 1, 199, 145, 38, 6, 1, 66, 38, 6, 1, 234, - 181, 38, 6, 1, 140, 38, 6, 1, 197, 161, 38, 6, 1, 243, 127, 38, 6, 1, - 203, 165, 38, 6, 1, 203, 116, 38, 6, 1, 230, 17, 56, 38, 6, 1, 192, 58, - 38, 6, 1, 202, 32, 56, 38, 6, 1, 71, 38, 6, 1, 191, 225, 38, 6, 1, 170, - 38, 2, 1, 65, 38, 2, 1, 249, 17, 38, 2, 1, 195, 153, 38, 2, 1, 231, 77, - 38, 2, 1, 237, 146, 38, 2, 1, 223, 226, 38, 2, 1, 191, 62, 38, 2, 1, 191, - 87, 38, 2, 1, 68, 38, 2, 1, 203, 40, 68, 38, 2, 1, 155, 38, 2, 1, 234, - 140, 38, 2, 1, 234, 114, 38, 2, 1, 234, 103, 38, 2, 1, 74, 38, 2, 1, 210, - 63, 38, 2, 1, 234, 34, 38, 2, 1, 234, 22, 38, 2, 1, 199, 145, 38, 2, 1, - 66, 38, 2, 1, 234, 181, 38, 2, 1, 140, 38, 2, 1, 197, 161, 38, 2, 1, 243, - 127, 38, 2, 1, 203, 165, 38, 2, 1, 203, 116, 38, 2, 1, 230, 17, 56, 38, - 2, 1, 192, 58, 38, 2, 1, 202, 32, 56, 38, 2, 1, 71, 38, 2, 1, 191, 225, - 38, 2, 1, 170, 38, 2, 1, 223, 227, 4, 230, 210, 38, 2, 1, 223, 88, 38, 2, - 1, 236, 192, 38, 2, 1, 231, 20, 38, 2, 1, 196, 125, 223, 226, 38, 2, 1, - 235, 32, 38, 2, 1, 247, 203, 68, 38, 2, 1, 192, 33, 38, 2, 1, 223, 10, - 38, 2, 1, 219, 76, 38, 2, 1, 213, 150, 38, 2, 1, 197, 155, 38, 2, 1, 221, - 103, 38, 2, 1, 228, 74, 4, 230, 210, 38, 2, 1, 203, 40, 66, 38, 2, 1, - 235, 28, 38, 6, 1, 211, 110, 38, 2, 1, 211, 110, 38, 6, 1, 192, 95, 38, - 2, 1, 192, 95, 38, 6, 1, 223, 81, 71, 38, 2, 1, 223, 81, 71, 38, 6, 1, - 219, 83, 191, 190, 38, 2, 1, 219, 83, 191, 190, 38, 6, 1, 223, 81, 219, - 83, 191, 190, 38, 2, 1, 223, 81, 219, 83, 191, 190, 38, 6, 1, 248, 175, - 191, 190, 38, 2, 1, 248, 175, 191, 190, 38, 6, 1, 223, 81, 248, 175, 191, - 190, 38, 2, 1, 223, 81, 248, 175, 191, 190, 38, 6, 1, 220, 248, 38, 2, 1, - 220, 248, 38, 6, 1, 208, 176, 38, 2, 1, 208, 176, 38, 6, 1, 232, 228, 38, - 2, 1, 232, 228, 38, 6, 1, 223, 37, 38, 2, 1, 223, 37, 38, 6, 1, 223, 38, - 4, 55, 230, 211, 252, 60, 38, 2, 1, 223, 38, 4, 55, 230, 211, 252, 60, - 38, 6, 1, 196, 128, 38, 2, 1, 196, 128, 38, 6, 1, 206, 115, 211, 110, 38, - 2, 1, 206, 115, 211, 110, 38, 6, 1, 211, 111, 4, 198, 122, 38, 2, 1, 211, - 111, 4, 198, 122, 38, 6, 1, 211, 30, 38, 2, 1, 211, 30, 38, 6, 1, 221, - 35, 38, 2, 1, 221, 35, 38, 198, 229, 56, 33, 38, 198, 122, 33, 38, 210, - 191, 33, 38, 237, 213, 209, 75, 33, 38, 208, 170, 209, 75, 33, 38, 209, - 54, 33, 38, 228, 141, 198, 229, 56, 33, 38, 216, 48, 56, 38, 6, 1, 203, - 40, 228, 74, 4, 199, 215, 38, 2, 1, 203, 40, 228, 74, 4, 199, 215, 38, 6, - 1, 204, 21, 56, 38, 2, 1, 204, 21, 56, 38, 6, 1, 234, 35, 4, 198, 182, - 38, 2, 1, 234, 35, 4, 198, 182, 38, 6, 1, 231, 78, 4, 196, 69, 38, 2, 1, - 231, 78, 4, 196, 69, 38, 6, 1, 231, 78, 4, 106, 38, 2, 1, 231, 78, 4, - 106, 38, 6, 1, 231, 78, 4, 82, 102, 38, 2, 1, 231, 78, 4, 82, 102, 38, 6, - 1, 191, 63, 4, 237, 87, 38, 2, 1, 191, 63, 4, 237, 87, 38, 6, 1, 191, 88, - 4, 237, 87, 38, 2, 1, 191, 88, 4, 237, 87, 38, 6, 1, 222, 142, 4, 237, - 87, 38, 2, 1, 222, 142, 4, 237, 87, 38, 6, 1, 222, 142, 4, 81, 106, 38, - 2, 1, 222, 142, 4, 81, 106, 38, 6, 1, 222, 142, 4, 106, 38, 2, 1, 222, - 142, 4, 106, 38, 6, 1, 249, 70, 155, 38, 2, 1, 249, 70, 155, 38, 6, 1, - 234, 104, 4, 237, 87, 38, 2, 1, 234, 104, 4, 237, 87, 38, 6, 34, 234, - 104, 231, 77, 38, 2, 34, 234, 104, 231, 77, 38, 6, 1, 210, 64, 4, 82, - 102, 38, 2, 1, 210, 64, 4, 82, 102, 38, 6, 1, 252, 67, 140, 38, 2, 1, - 252, 67, 140, 38, 6, 1, 234, 23, 4, 237, 87, 38, 2, 1, 234, 23, 4, 237, - 87, 38, 6, 1, 199, 146, 4, 237, 87, 38, 2, 1, 199, 146, 4, 237, 87, 38, - 6, 1, 201, 53, 66, 38, 2, 1, 201, 53, 66, 38, 6, 1, 201, 53, 126, 4, 106, - 38, 2, 1, 201, 53, 126, 4, 106, 38, 6, 1, 230, 105, 4, 237, 87, 38, 2, 1, - 230, 105, 4, 237, 87, 38, 6, 34, 199, 146, 197, 161, 38, 2, 34, 199, 146, - 197, 161, 38, 6, 1, 243, 128, 4, 237, 87, 38, 2, 1, 243, 128, 4, 237, 87, - 38, 6, 1, 243, 128, 4, 81, 106, 38, 2, 1, 243, 128, 4, 81, 106, 38, 6, 1, - 203, 82, 38, 2, 1, 203, 82, 38, 6, 1, 252, 67, 243, 127, 38, 2, 1, 252, - 67, 243, 127, 38, 6, 1, 252, 67, 243, 128, 4, 237, 87, 38, 2, 1, 252, 67, - 243, 128, 4, 237, 87, 38, 1, 210, 179, 38, 6, 1, 191, 63, 4, 248, 36, 38, - 2, 1, 191, 63, 4, 248, 36, 38, 6, 1, 222, 142, 4, 102, 38, 2, 1, 222, - 142, 4, 102, 38, 6, 1, 234, 141, 4, 199, 215, 38, 2, 1, 234, 141, 4, 199, - 215, 38, 6, 1, 234, 104, 4, 102, 38, 2, 1, 234, 104, 4, 102, 38, 6, 1, - 234, 104, 4, 199, 215, 38, 2, 1, 234, 104, 4, 199, 215, 38, 6, 1, 221, - 208, 243, 127, 38, 2, 1, 221, 208, 243, 127, 38, 6, 1, 234, 115, 4, 199, - 215, 38, 2, 1, 234, 115, 4, 199, 215, 38, 2, 1, 210, 179, 38, 6, 1, 42, - 4, 248, 36, 38, 2, 1, 42, 4, 248, 36, 38, 6, 1, 42, 4, 237, 42, 38, 2, 1, - 42, 4, 237, 42, 38, 6, 34, 42, 223, 226, 38, 2, 34, 42, 223, 226, 38, 6, - 1, 223, 227, 4, 248, 36, 38, 2, 1, 223, 227, 4, 248, 36, 38, 6, 1, 205, - 86, 38, 2, 1, 205, 86, 38, 6, 1, 205, 87, 4, 237, 42, 38, 2, 1, 205, 87, - 4, 237, 42, 38, 6, 1, 191, 63, 4, 237, 42, 38, 2, 1, 191, 63, 4, 237, 42, - 38, 6, 1, 191, 88, 4, 237, 42, 38, 2, 1, 191, 88, 4, 237, 42, 38, 6, 1, - 252, 67, 235, 32, 38, 2, 1, 252, 67, 235, 32, 38, 6, 1, 228, 74, 4, 217, - 146, 38, 2, 1, 228, 74, 4, 217, 146, 38, 6, 1, 228, 74, 4, 237, 42, 38, - 2, 1, 228, 74, 4, 237, 42, 38, 6, 1, 187, 4, 237, 42, 38, 2, 1, 187, 4, - 237, 42, 38, 6, 1, 249, 82, 74, 38, 2, 1, 249, 82, 74, 38, 6, 1, 249, 82, - 187, 4, 237, 42, 38, 2, 1, 249, 82, 187, 4, 237, 42, 38, 6, 1, 235, 15, - 4, 237, 42, 38, 2, 1, 235, 15, 4, 237, 42, 38, 6, 1, 126, 4, 217, 146, - 38, 2, 1, 126, 4, 217, 146, 38, 6, 1, 126, 4, 237, 42, 38, 2, 1, 126, 4, - 237, 42, 38, 6, 1, 126, 4, 55, 252, 46, 38, 2, 1, 126, 4, 55, 252, 46, - 38, 6, 1, 243, 128, 4, 237, 42, 38, 2, 1, 243, 128, 4, 237, 42, 38, 6, 1, - 231, 78, 4, 237, 87, 38, 2, 1, 231, 78, 4, 237, 87, 38, 6, 1, 192, 59, 4, - 237, 42, 38, 2, 1, 192, 59, 4, 237, 42, 38, 6, 1, 231, 78, 4, 201, 28, - 23, 102, 38, 2, 1, 231, 78, 4, 201, 28, 23, 102, 38, 6, 1, 230, 105, 4, - 102, 38, 2, 1, 230, 105, 4, 102, 38, 6, 1, 230, 105, 4, 106, 38, 2, 1, - 230, 105, 4, 106, 38, 6, 1, 221, 45, 237, 146, 38, 2, 1, 221, 45, 237, - 146, 38, 6, 1, 221, 45, 236, 192, 38, 2, 1, 221, 45, 236, 192, 38, 6, 1, - 221, 45, 191, 12, 38, 2, 1, 221, 45, 191, 12, 38, 6, 1, 221, 45, 235, 24, - 38, 2, 1, 221, 45, 235, 24, 38, 6, 1, 221, 45, 219, 76, 38, 2, 1, 221, - 45, 219, 76, 38, 6, 1, 221, 45, 213, 150, 38, 2, 1, 221, 45, 213, 150, - 38, 6, 1, 221, 45, 202, 115, 38, 2, 1, 221, 45, 202, 115, 38, 6, 1, 221, - 45, 198, 116, 38, 2, 1, 221, 45, 198, 116, 38, 6, 1, 207, 18, 191, 87, - 38, 2, 1, 207, 18, 191, 87, 38, 6, 1, 234, 141, 4, 102, 38, 2, 1, 234, - 141, 4, 102, 38, 6, 1, 219, 159, 38, 2, 1, 219, 159, 38, 6, 1, 207, 6, - 38, 2, 1, 207, 6, 38, 6, 1, 192, 129, 38, 2, 1, 192, 129, 38, 6, 1, 208, - 96, 38, 2, 1, 208, 96, 38, 6, 1, 193, 125, 38, 2, 1, 193, 125, 38, 6, 1, - 251, 188, 155, 38, 2, 1, 251, 188, 155, 38, 6, 1, 234, 141, 4, 82, 102, - 38, 2, 1, 234, 141, 4, 82, 102, 38, 6, 1, 234, 104, 4, 82, 102, 38, 2, 1, - 234, 104, 4, 82, 102, 38, 6, 1, 210, 64, 4, 237, 87, 38, 2, 1, 210, 64, - 4, 237, 87, 38, 6, 1, 203, 83, 4, 237, 87, 38, 2, 1, 203, 83, 4, 237, 87, - 38, 6, 1, 234, 104, 4, 45, 102, 38, 2, 1, 234, 104, 4, 45, 102, 38, 6, 1, - 235, 16, 38, 2, 1, 235, 16, 38, 6, 1, 237, 195, 38, 2, 1, 237, 195, 38, - 6, 1, 234, 141, 4, 237, 87, 38, 2, 1, 234, 141, 4, 237, 87, 250, 249, 6, - 1, 250, 128, 250, 249, 6, 1, 248, 229, 250, 249, 6, 1, 231, 40, 250, 249, - 6, 1, 238, 32, 250, 249, 6, 1, 234, 195, 250, 249, 6, 1, 191, 123, 250, - 249, 6, 1, 234, 173, 250, 249, 6, 1, 233, 255, 250, 249, 6, 1, 159, 250, - 249, 6, 1, 191, 62, 250, 249, 6, 1, 223, 131, 250, 249, 6, 1, 219, 80, - 250, 249, 6, 1, 192, 212, 250, 249, 6, 1, 247, 160, 250, 249, 6, 1, 221, - 251, 250, 249, 6, 1, 229, 23, 250, 249, 6, 1, 223, 32, 250, 249, 6, 1, - 231, 88, 250, 249, 6, 1, 243, 117, 250, 249, 6, 1, 216, 186, 250, 249, 6, - 1, 192, 33, 250, 249, 6, 1, 212, 253, 250, 249, 6, 1, 203, 165, 250, 249, - 6, 1, 195, 24, 250, 249, 6, 1, 247, 1, 250, 249, 6, 1, 210, 41, 250, 249, - 6, 1, 222, 247, 250, 249, 6, 1, 165, 250, 249, 6, 1, 205, 39, 250, 249, - 6, 1, 195, 74, 250, 249, 6, 1, 198, 119, 250, 249, 6, 1, 207, 71, 250, - 249, 6, 1, 242, 99, 250, 249, 6, 1, 192, 17, 250, 249, 6, 1, 209, 114, - 250, 249, 6, 1, 222, 6, 250, 249, 6, 1, 211, 136, 250, 249, 6, 1, 233, - 46, 250, 249, 52, 1, 45, 132, 206, 188, 250, 249, 251, 49, 250, 249, 234, - 107, 77, 250, 249, 233, 216, 77, 250, 249, 242, 74, 250, 249, 208, 13, - 77, 250, 249, 252, 68, 77, 250, 249, 2, 1, 153, 250, 128, 250, 249, 2, 1, - 250, 128, 250, 249, 2, 1, 248, 229, 250, 249, 2, 1, 231, 40, 250, 249, 2, - 1, 238, 32, 250, 249, 2, 1, 234, 195, 250, 249, 2, 1, 191, 123, 250, 249, - 2, 1, 234, 173, 250, 249, 2, 1, 233, 255, 250, 249, 2, 1, 159, 250, 249, - 2, 1, 191, 62, 250, 249, 2, 1, 223, 131, 250, 249, 2, 1, 219, 80, 250, - 249, 2, 1, 192, 212, 250, 249, 2, 1, 247, 160, 250, 249, 2, 1, 221, 251, - 250, 249, 2, 1, 229, 23, 250, 249, 2, 1, 223, 32, 250, 249, 2, 1, 231, - 88, 250, 249, 2, 1, 243, 117, 250, 249, 2, 1, 216, 186, 250, 249, 2, 1, - 192, 33, 250, 249, 2, 1, 212, 253, 250, 249, 2, 1, 203, 165, 250, 249, 2, - 1, 195, 24, 250, 249, 2, 1, 247, 1, 250, 249, 2, 1, 210, 41, 250, 249, 2, - 1, 222, 247, 250, 249, 2, 1, 165, 250, 249, 2, 1, 205, 39, 250, 249, 2, - 1, 195, 74, 250, 249, 2, 1, 198, 119, 250, 249, 2, 1, 207, 71, 250, 249, - 2, 1, 242, 99, 250, 249, 2, 1, 192, 17, 250, 249, 2, 1, 209, 114, 250, - 249, 2, 1, 222, 6, 250, 249, 2, 1, 211, 136, 250, 249, 2, 1, 233, 46, - 250, 249, 2, 34, 234, 196, 192, 17, 250, 249, 2, 1, 11, 4, 106, 250, 249, - 232, 80, 201, 63, 250, 249, 228, 88, 206, 207, 250, 249, 233, 251, 56, - 219, 223, 250, 249, 233, 251, 56, 250, 249, 235, 110, 56, 136, 252, 61, - 233, 246, 136, 252, 61, 205, 40, 136, 252, 61, 203, 141, 136, 252, 61, - 191, 99, 208, 78, 136, 252, 61, 191, 99, 231, 230, 136, 252, 61, 198, - 134, 136, 252, 61, 207, 15, 136, 252, 61, 191, 97, 136, 252, 61, 210, 97, - 136, 252, 61, 192, 48, 136, 252, 61, 199, 56, 136, 252, 61, 231, 139, - 136, 252, 61, 231, 140, 215, 110, 136, 252, 61, 231, 137, 136, 252, 61, - 208, 80, 210, 130, 136, 252, 61, 199, 103, 231, 158, 136, 252, 61, 210, - 69, 136, 252, 61, 250, 173, 230, 85, 136, 252, 61, 215, 121, 136, 252, - 61, 217, 117, 136, 252, 61, 216, 175, 136, 252, 61, 216, 176, 222, 7, - 136, 252, 61, 237, 222, 136, 252, 61, 208, 91, 136, 252, 61, 199, 103, - 208, 73, 136, 252, 61, 192, 61, 248, 230, 191, 247, 136, 252, 61, 211, - 117, 136, 252, 61, 223, 183, 136, 252, 61, 237, 123, 136, 252, 61, 191, - 19, 136, 87, 217, 34, 243, 10, 136, 209, 62, 203, 85, 136, 209, 62, 230, - 8, 205, 40, 136, 209, 62, 230, 8, 210, 88, 136, 209, 62, 230, 8, 208, 84, - 136, 209, 62, 229, 119, 136, 209, 62, 197, 158, 136, 209, 62, 205, 40, - 136, 209, 62, 210, 88, 136, 209, 62, 208, 84, 136, 209, 62, 229, 7, 136, - 209, 62, 229, 8, 230, 10, 40, 195, 158, 136, 209, 62, 208, 18, 136, 209, - 62, 238, 17, 211, 57, 217, 70, 136, 209, 62, 216, 164, 136, 208, 152, - 217, 67, 136, 209, 62, 207, 161, 136, 208, 152, 210, 99, 136, 209, 62, - 203, 70, 236, 140, 136, 209, 62, 202, 175, 236, 140, 136, 208, 152, 202, - 33, 210, 90, 136, 87, 116, 236, 140, 136, 87, 110, 236, 140, 136, 208, - 152, 212, 131, 230, 84, 136, 209, 62, 208, 85, 208, 78, 136, 1, 251, 192, - 136, 1, 248, 214, 136, 1, 231, 38, 136, 1, 237, 253, 136, 1, 229, 245, - 136, 1, 195, 158, 136, 1, 191, 91, 136, 1, 229, 186, 136, 1, 199, 73, - 136, 1, 191, 250, 136, 1, 53, 222, 106, 136, 1, 222, 106, 136, 1, 220, - 27, 136, 1, 53, 216, 193, 136, 1, 216, 193, 136, 1, 53, 212, 130, 136, 1, - 212, 130, 136, 1, 205, 148, 136, 1, 250, 126, 136, 1, 53, 210, 63, 136, - 1, 210, 63, 136, 1, 53, 197, 163, 136, 1, 197, 163, 136, 1, 208, 42, 136, - 1, 207, 38, 136, 1, 203, 69, 136, 1, 199, 162, 136, 191, 251, 197, 241, - 136, 34, 192, 31, 55, 195, 158, 136, 34, 192, 31, 195, 159, 191, 250, - 136, 34, 192, 31, 55, 191, 250, 136, 208, 152, 231, 139, 136, 208, 152, - 231, 137, 9, 31, 56, 9, 3, 205, 141, 9, 232, 157, 217, 51, 9, 3, 205, - 187, 9, 3, 205, 144, 9, 31, 87, 58, 251, 28, 238, 191, 206, 128, 251, 28, - 232, 121, 206, 128, 9, 207, 122, 251, 28, 210, 14, 216, 50, 56, 251, 28, - 210, 14, 199, 96, 198, 230, 56, 252, 2, 56, 9, 242, 74, 9, 237, 209, 204, - 10, 9, 209, 64, 195, 137, 56, 9, 3, 216, 25, 9, 3, 205, 161, 251, 199, - 193, 149, 9, 3, 251, 199, 250, 198, 9, 3, 207, 157, 251, 198, 9, 3, 207, - 167, 251, 170, 251, 105, 9, 3, 199, 206, 9, 2, 137, 199, 219, 9, 2, 137, - 34, 131, 4, 220, 36, 4, 192, 75, 9, 2, 137, 191, 113, 9, 2, 233, 70, 9, - 2, 237, 245, 9, 2, 222, 52, 9, 204, 25, 9, 1, 77, 9, 234, 95, 79, 199, - 54, 77, 9, 197, 225, 75, 208, 152, 77, 9, 208, 13, 77, 9, 1, 222, 56, - 192, 75, 9, 1, 230, 57, 9, 1, 131, 4, 217, 142, 58, 9, 1, 131, 4, 230, - 58, 58, 9, 1, 193, 134, 4, 230, 58, 58, 9, 1, 131, 4, 230, 58, 60, 9, 1, - 99, 4, 230, 58, 58, 9, 1, 251, 192, 9, 1, 248, 245, 9, 1, 199, 115, 217, - 62, 9, 1, 199, 114, 9, 1, 199, 29, 9, 1, 223, 6, 9, 1, 230, 81, 9, 1, - 221, 210, 9, 1, 238, 3, 9, 1, 199, 41, 9, 1, 207, 71, 9, 1, 191, 113, 9, - 1, 205, 46, 9, 1, 203, 109, 9, 1, 205, 192, 9, 1, 238, 26, 9, 1, 199, - 219, 9, 1, 191, 116, 9, 1, 251, 230, 9, 1, 231, 86, 9, 1, 222, 5, 4, 105, - 185, 58, 9, 1, 222, 5, 4, 115, 185, 60, 9, 1, 233, 74, 99, 4, 223, 93, - 196, 12, 9, 1, 233, 74, 99, 4, 105, 185, 58, 9, 1, 233, 74, 99, 4, 115, - 185, 58, 9, 199, 168, 9, 1, 233, 46, 9, 1, 208, 89, 9, 1, 222, 106, 9, 1, - 220, 35, 9, 1, 216, 208, 9, 1, 213, 24, 9, 1, 229, 210, 9, 1, 193, 133, - 9, 1, 131, 217, 99, 9, 1, 192, 75, 9, 233, 68, 9, 237, 243, 9, 222, 50, - 9, 233, 70, 9, 237, 245, 9, 222, 52, 9, 203, 155, 9, 200, 206, 9, 217, - 140, 58, 9, 230, 58, 58, 9, 230, 58, 60, 9, 200, 230, 251, 192, 9, 223, - 93, 237, 245, 9, 87, 213, 25, 231, 57, 9, 190, 237, 9, 18, 3, 2, 196, 13, - 58, 9, 18, 3, 223, 93, 2, 196, 13, 58, 9, 18, 3, 75, 60, 9, 207, 18, 237, - 245, 9, 233, 71, 4, 105, 236, 138, 9, 193, 135, 230, 58, 60, 251, 28, 17, - 191, 77, 251, 28, 17, 107, 251, 28, 17, 109, 251, 28, 17, 138, 251, 28, - 17, 134, 251, 28, 17, 149, 251, 28, 17, 169, 251, 28, 17, 175, 251, 28, - 17, 171, 251, 28, 17, 178, 9, 210, 13, 56, 9, 237, 138, 204, 10, 9, 198, - 229, 204, 10, 9, 232, 226, 209, 60, 201, 102, 9, 1, 236, 139, 248, 245, - 9, 1, 236, 139, 208, 89, 9, 1, 200, 182, 251, 192, 9, 1, 131, 193, 150, - 9, 1, 131, 4, 193, 135, 230, 58, 58, 9, 1, 131, 4, 193, 135, 230, 58, 60, - 9, 1, 137, 230, 57, 9, 1, 137, 230, 58, 251, 192, 9, 1, 137, 230, 58, - 193, 133, 9, 1, 126, 4, 230, 58, 58, 9, 1, 137, 230, 58, 192, 75, 9, 1, - 197, 124, 9, 1, 197, 122, 9, 1, 248, 255, 9, 1, 199, 115, 4, 206, 188, 9, - 1, 199, 115, 4, 115, 185, 93, 235, 118, 9, 1, 210, 41, 9, 1, 199, 112, 9, - 1, 248, 243, 9, 1, 182, 4, 230, 58, 58, 9, 1, 182, 4, 105, 185, 81, 58, - 9, 1, 212, 87, 9, 1, 235, 41, 9, 1, 182, 4, 115, 185, 58, 9, 1, 199, 149, - 9, 1, 199, 147, 9, 1, 237, 186, 9, 1, 238, 4, 4, 206, 188, 9, 1, 238, 4, - 4, 75, 60, 9, 1, 238, 4, 4, 75, 248, 233, 23, 2, 199, 219, 9, 1, 238, 10, - 9, 1, 237, 188, 9, 1, 235, 78, 9, 1, 238, 4, 4, 115, 185, 93, 235, 118, - 9, 1, 238, 4, 4, 232, 128, 185, 58, 9, 1, 206, 101, 9, 1, 207, 72, 4, 2, - 196, 12, 9, 1, 207, 72, 4, 206, 188, 9, 1, 207, 72, 4, 75, 60, 9, 1, 207, - 72, 4, 2, 196, 13, 60, 9, 1, 207, 72, 4, 75, 248, 233, 23, 75, 58, 9, 1, - 207, 72, 4, 105, 185, 58, 9, 1, 223, 3, 9, 1, 207, 72, 4, 232, 128, 185, - 58, 9, 1, 205, 47, 4, 75, 248, 233, 23, 75, 58, 9, 1, 205, 47, 4, 115, - 185, 60, 9, 1, 205, 47, 4, 115, 185, 248, 233, 23, 115, 185, 58, 9, 1, - 205, 193, 4, 105, 185, 60, 9, 1, 205, 193, 4, 115, 185, 58, 9, 1, 199, - 220, 4, 115, 185, 58, 9, 1, 251, 231, 4, 115, 185, 58, 9, 1, 236, 139, - 233, 46, 9, 1, 233, 47, 4, 75, 215, 177, 60, 9, 1, 233, 47, 4, 75, 60, 9, - 1, 195, 146, 9, 1, 233, 47, 4, 115, 185, 60, 9, 1, 210, 39, 9, 1, 208, - 90, 4, 75, 58, 9, 1, 208, 90, 4, 115, 185, 58, 9, 1, 222, 4, 9, 1, 200, - 146, 222, 106, 9, 1, 222, 107, 4, 206, 188, 9, 1, 222, 107, 4, 75, 58, 9, - 1, 214, 70, 9, 1, 222, 107, 4, 115, 185, 60, 9, 1, 231, 227, 9, 1, 231, - 228, 4, 206, 188, 9, 1, 213, 247, 9, 1, 231, 228, 4, 105, 185, 60, 9, 1, - 230, 166, 9, 1, 231, 228, 4, 115, 185, 58, 9, 1, 220, 36, 4, 2, 196, 12, - 9, 1, 220, 36, 4, 75, 58, 9, 1, 220, 36, 4, 115, 185, 58, 9, 1, 220, 36, - 4, 115, 185, 60, 9, 1, 213, 25, 4, 75, 60, 9, 1, 213, 25, 231, 57, 9, 1, - 206, 165, 9, 1, 213, 25, 4, 206, 188, 9, 1, 213, 25, 4, 115, 185, 58, 9, - 1, 229, 211, 236, 170, 9, 1, 199, 150, 4, 75, 58, 9, 1, 229, 211, 4, 99, - 58, 9, 1, 229, 211, 231, 0, 9, 1, 229, 211, 231, 1, 4, 230, 58, 58, 9, 1, - 199, 115, 217, 63, 231, 0, 9, 1, 193, 134, 4, 206, 188, 9, 1, 221, 132, - 211, 151, 9, 1, 211, 151, 9, 1, 66, 9, 1, 191, 225, 9, 1, 221, 132, 191, - 225, 9, 1, 193, 134, 4, 105, 185, 58, 9, 1, 195, 153, 9, 1, 233, 74, 192, - 75, 9, 1, 99, 4, 199, 215, 9, 1, 99, 4, 2, 196, 12, 9, 1, 193, 134, 4, - 75, 58, 9, 1, 71, 9, 1, 99, 4, 115, 185, 60, 9, 1, 99, 249, 80, 9, 1, 99, - 249, 81, 4, 230, 58, 58, 9, 232, 80, 201, 63, 9, 1, 252, 25, 9, 2, 137, - 34, 205, 193, 4, 220, 36, 4, 131, 217, 99, 9, 2, 137, 34, 208, 90, 4, - 220, 36, 4, 131, 217, 99, 9, 2, 137, 92, 89, 20, 9, 2, 137, 220, 36, 251, - 192, 9, 2, 137, 223, 6, 9, 2, 137, 115, 236, 138, 9, 2, 137, 205, 46, 9, - 234, 95, 79, 250, 130, 9, 201, 98, 79, 206, 60, 234, 141, 229, 114, 9, 2, - 137, 206, 113, 191, 77, 9, 2, 137, 196, 73, 207, 91, 191, 77, 9, 2, 137, - 236, 139, 229, 236, 79, 221, 210, 9, 2, 137, 92, 76, 20, 9, 2, 130, 205, - 46, 9, 2, 137, 217, 141, 9, 2, 193, 133, 9, 2, 192, 75, 9, 2, 137, 192, - 75, 9, 2, 137, 213, 24, 9, 209, 108, 79, 205, 177, 9, 234, 105, 247, 22, - 130, 201, 63, 9, 234, 105, 247, 22, 137, 201, 63, 9, 206, 113, 137, 201, - 64, 4, 233, 4, 247, 21, 9, 2, 130, 216, 208, 9, 1, 238, 4, 4, 223, 93, - 196, 12, 9, 1, 207, 72, 4, 223, 93, 196, 12, 233, 205, 251, 28, 17, 191, - 77, 233, 205, 251, 28, 17, 107, 233, 205, 251, 28, 17, 109, 233, 205, - 251, 28, 17, 138, 233, 205, 251, 28, 17, 134, 233, 205, 251, 28, 17, 149, - 233, 205, 251, 28, 17, 169, 233, 205, 251, 28, 17, 175, 233, 205, 251, - 28, 17, 171, 233, 205, 251, 28, 17, 178, 9, 1, 203, 110, 4, 75, 60, 9, 1, - 238, 27, 4, 75, 60, 9, 1, 231, 87, 4, 75, 60, 9, 3, 202, 173, 251, 137, - 9, 3, 202, 173, 209, 16, 216, 186, 9, 1, 229, 211, 4, 223, 93, 196, 12, - 200, 63, 234, 95, 79, 210, 127, 200, 63, 200, 177, 232, 80, 201, 63, 200, - 63, 200, 232, 232, 80, 201, 63, 200, 63, 200, 177, 242, 83, 200, 63, 200, - 232, 242, 83, 200, 63, 228, 241, 242, 83, 200, 63, 242, 84, 202, 110, - 219, 224, 200, 63, 242, 84, 202, 110, 183, 200, 63, 200, 177, 242, 84, - 202, 110, 219, 224, 200, 63, 200, 232, 242, 84, 202, 110, 183, 200, 63, - 239, 24, 200, 63, 230, 15, 211, 176, 200, 63, 230, 15, 216, 162, 200, 63, - 230, 15, 250, 195, 200, 63, 252, 68, 77, 200, 63, 1, 251, 202, 200, 63, - 1, 200, 182, 251, 202, 200, 63, 1, 248, 211, 200, 63, 1, 231, 217, 200, - 63, 1, 231, 218, 231, 194, 200, 63, 1, 238, 0, 200, 63, 1, 236, 139, 238, - 1, 206, 181, 200, 63, 1, 229, 245, 200, 63, 1, 193, 133, 200, 63, 1, 191, - 113, 200, 63, 1, 229, 184, 200, 63, 1, 199, 69, 200, 63, 1, 199, 70, 231, - 194, 200, 63, 1, 191, 208, 200, 63, 1, 191, 209, 229, 245, 200, 63, 1, - 222, 75, 200, 63, 1, 220, 34, 200, 63, 1, 216, 46, 200, 63, 1, 212, 130, - 200, 63, 1, 204, 18, 200, 63, 1, 53, 204, 18, 200, 63, 1, 71, 200, 63, 1, - 210, 63, 200, 63, 1, 207, 18, 210, 63, 200, 63, 1, 205, 189, 200, 63, 1, - 208, 83, 200, 63, 1, 206, 181, 200, 63, 1, 203, 69, 200, 63, 1, 199, 159, - 200, 63, 1, 209, 252, 248, 194, 200, 63, 1, 209, 252, 231, 84, 200, 63, - 1, 209, 252, 237, 63, 200, 63, 208, 166, 58, 200, 63, 208, 166, 60, 200, - 63, 208, 166, 235, 137, 200, 63, 191, 0, 58, 200, 63, 191, 0, 60, 200, - 63, 191, 0, 235, 137, 200, 63, 207, 116, 58, 200, 63, 207, 116, 60, 200, - 63, 235, 138, 191, 9, 228, 240, 200, 63, 235, 138, 191, 9, 251, 108, 200, - 63, 229, 250, 58, 200, 63, 229, 250, 60, 200, 63, 229, 249, 235, 137, - 200, 63, 234, 16, 58, 200, 63, 234, 16, 60, 200, 63, 206, 24, 200, 63, - 233, 40, 236, 140, 200, 63, 207, 246, 200, 63, 206, 54, 200, 63, 105, 81, - 185, 58, 200, 63, 105, 81, 185, 60, 200, 63, 115, 185, 58, 200, 63, 115, - 185, 60, 200, 63, 211, 172, 219, 113, 58, 200, 63, 211, 172, 219, 113, - 60, 200, 63, 215, 96, 200, 63, 249, 79, 200, 63, 1, 202, 28, 191, 69, - 200, 63, 1, 202, 28, 221, 201, 200, 63, 1, 202, 28, 233, 59, 9, 1, 248, - 246, 4, 115, 185, 228, 190, 60, 9, 1, 248, 246, 4, 75, 248, 233, 23, 115, - 185, 58, 9, 1, 248, 246, 4, 115, 185, 209, 58, 196, 66, 60, 9, 1, 248, - 246, 4, 115, 185, 209, 58, 196, 66, 248, 233, 23, 105, 185, 58, 9, 1, - 248, 246, 4, 105, 185, 248, 233, 23, 75, 58, 9, 1, 248, 246, 4, 223, 93, - 2, 196, 13, 60, 9, 1, 248, 246, 4, 2, 196, 12, 9, 1, 182, 4, 105, 185, - 58, 9, 1, 182, 4, 115, 185, 209, 58, 196, 66, 60, 9, 1, 238, 4, 4, 105, - 185, 195, 85, 248, 233, 23, 2, 199, 219, 9, 1, 238, 4, 4, 223, 93, 2, - 196, 13, 60, 9, 1, 207, 72, 4, 106, 9, 1, 205, 47, 4, 232, 128, 185, 58, - 9, 1, 251, 231, 4, 105, 185, 58, 9, 1, 251, 231, 4, 115, 185, 209, 58, - 235, 119, 58, 9, 1, 251, 231, 4, 105, 185, 195, 85, 58, 9, 1, 233, 47, 4, - 105, 185, 60, 9, 1, 233, 47, 4, 115, 185, 209, 58, 196, 66, 60, 9, 1, - 222, 5, 4, 75, 58, 9, 1, 222, 5, 4, 115, 185, 58, 9, 1, 222, 5, 4, 115, - 185, 209, 58, 196, 66, 60, 9, 1, 92, 4, 75, 58, 9, 1, 92, 4, 75, 60, 9, - 1, 213, 25, 4, 105, 185, 60, 9, 1, 213, 25, 4, 2, 199, 219, 9, 1, 213, - 25, 4, 2, 196, 12, 9, 1, 220, 36, 4, 164, 9, 1, 207, 72, 4, 105, 185, - 195, 85, 58, 9, 1, 207, 72, 4, 230, 58, 58, 9, 1, 205, 47, 4, 105, 185, - 195, 85, 58, 9, 1, 182, 4, 2, 9, 1, 199, 220, 60, 9, 1, 182, 4, 2, 9, 1, - 199, 220, 23, 105, 236, 138, 9, 1, 205, 47, 4, 2, 9, 1, 199, 220, 23, - 105, 236, 138, 9, 1, 207, 72, 4, 2, 9, 1, 199, 220, 23, 105, 236, 138, 9, - 1, 182, 4, 2, 9, 1, 199, 220, 58, 9, 1, 131, 4, 233, 205, 251, 28, 17, - 105, 58, 9, 1, 131, 4, 233, 205, 251, 28, 17, 115, 58, 9, 1, 233, 74, 99, - 4, 233, 205, 251, 28, 17, 105, 58, 9, 1, 233, 74, 99, 4, 233, 205, 251, - 28, 17, 115, 58, 9, 1, 233, 74, 99, 4, 233, 205, 251, 28, 17, 232, 128, - 60, 9, 1, 193, 134, 4, 233, 205, 251, 28, 17, 105, 58, 9, 1, 193, 134, 4, - 233, 205, 251, 28, 17, 115, 58, 9, 1, 99, 249, 81, 4, 233, 205, 251, 28, - 17, 105, 58, 9, 1, 99, 249, 81, 4, 233, 205, 251, 28, 17, 115, 58, 9, 1, - 182, 4, 233, 205, 251, 28, 17, 232, 128, 60, 9, 1, 205, 47, 4, 233, 205, - 251, 28, 17, 232, 128, 58, 9, 1, 205, 47, 4, 223, 93, 196, 12, 9, 1, 222, - 107, 4, 105, 185, 58, 199, 46, 1, 230, 91, 199, 46, 1, 203, 119, 199, 46, - 1, 213, 23, 199, 46, 1, 207, 178, 199, 46, 1, 249, 151, 199, 46, 1, 219, - 156, 199, 46, 1, 222, 122, 199, 46, 1, 251, 179, 199, 46, 1, 195, 186, - 199, 46, 1, 216, 207, 199, 46, 1, 233, 107, 199, 46, 1, 237, 66, 199, 46, - 1, 199, 48, 199, 46, 1, 220, 122, 199, 46, 1, 231, 236, 199, 46, 1, 231, - 6, 199, 46, 1, 205, 45, 199, 46, 1, 237, 207, 199, 46, 1, 191, 94, 199, - 46, 1, 199, 161, 199, 46, 1, 192, 140, 199, 46, 1, 210, 77, 199, 46, 1, - 223, 15, 199, 46, 1, 243, 130, 199, 46, 1, 197, 131, 199, 46, 1, 229, - 176, 199, 46, 1, 221, 214, 199, 46, 1, 199, 47, 199, 46, 1, 191, 121, - 199, 46, 1, 203, 108, 199, 46, 1, 205, 196, 199, 46, 1, 238, 30, 199, 46, - 1, 159, 199, 46, 1, 191, 7, 199, 46, 1, 251, 227, 199, 46, 1, 231, 85, - 199, 46, 1, 208, 93, 199, 46, 1, 193, 178, 199, 46, 252, 70, 199, 46, - 252, 171, 199, 46, 228, 29, 199, 46, 234, 187, 199, 46, 196, 161, 199, - 46, 211, 86, 199, 46, 234, 198, 199, 46, 233, 195, 199, 46, 211, 171, - 199, 46, 211, 181, 199, 46, 200, 206, 199, 46, 1, 214, 250, 213, 107, 17, - 191, 77, 213, 107, 17, 107, 213, 107, 17, 109, 213, 107, 17, 138, 213, - 107, 17, 134, 213, 107, 17, 149, 213, 107, 17, 169, 213, 107, 17, 175, - 213, 107, 17, 171, 213, 107, 17, 178, 213, 107, 1, 65, 213, 107, 1, 234, - 188, 213, 107, 1, 68, 213, 107, 1, 71, 213, 107, 1, 66, 213, 107, 1, 211, - 87, 213, 107, 1, 74, 213, 107, 1, 238, 18, 213, 107, 1, 215, 61, 213, - 107, 1, 249, 153, 213, 107, 1, 168, 213, 107, 1, 190, 190, 213, 107, 1, - 223, 32, 213, 107, 1, 247, 1, 213, 107, 1, 238, 32, 213, 107, 1, 165, - 213, 107, 1, 206, 109, 213, 107, 1, 188, 213, 107, 1, 231, 182, 213, 107, - 1, 233, 109, 213, 107, 1, 155, 213, 107, 1, 173, 213, 107, 1, 215, 7, - 193, 37, 213, 107, 1, 174, 213, 107, 1, 212, 101, 213, 107, 1, 180, 213, - 107, 1, 140, 213, 107, 1, 193, 190, 213, 107, 1, 170, 213, 107, 1, 212, - 102, 193, 37, 213, 107, 1, 222, 193, 223, 32, 213, 107, 1, 222, 193, 247, - 1, 213, 107, 1, 222, 193, 165, 213, 107, 33, 203, 40, 137, 198, 79, 213, - 107, 33, 203, 40, 130, 198, 79, 213, 107, 33, 203, 40, 206, 180, 198, 79, - 213, 107, 33, 179, 237, 86, 198, 79, 213, 107, 33, 179, 137, 198, 79, - 213, 107, 33, 179, 130, 198, 79, 213, 107, 33, 179, 206, 180, 198, 79, - 213, 107, 33, 214, 213, 77, 213, 107, 33, 55, 75, 58, 213, 107, 137, 163, - 251, 49, 213, 107, 130, 163, 251, 49, 213, 107, 16, 211, 88, 237, 101, - 213, 107, 16, 231, 181, 213, 107, 242, 74, 213, 107, 233, 216, 77, 213, - 107, 220, 94, 213, 107, 237, 233, 213, 107, 236, 142, 56, 213, 107, 199, - 195, 56, 205, 151, 1, 251, 204, 205, 151, 1, 248, 148, 205, 151, 1, 231, - 216, 205, 151, 1, 238, 2, 205, 151, 1, 223, 44, 205, 151, 1, 249, 151, - 205, 151, 1, 191, 80, 205, 151, 1, 223, 53, 205, 151, 1, 198, 125, 205, - 151, 1, 191, 189, 205, 151, 1, 222, 123, 205, 151, 1, 220, 118, 205, 151, - 1, 216, 46, 205, 151, 1, 212, 130, 205, 151, 1, 202, 171, 205, 151, 1, - 223, 162, 205, 151, 1, 233, 23, 205, 151, 1, 197, 166, 205, 151, 1, 208, - 10, 205, 151, 1, 206, 181, 205, 151, 1, 203, 138, 205, 151, 1, 199, 243, - 205, 151, 87, 223, 162, 205, 151, 87, 223, 161, 205, 151, 87, 211, 165, - 205, 151, 87, 238, 16, 205, 151, 52, 1, 234, 52, 191, 189, 205, 151, 87, - 234, 52, 191, 189, 205, 151, 18, 3, 179, 71, 205, 151, 18, 3, 71, 205, - 151, 18, 3, 210, 253, 252, 206, 205, 151, 18, 3, 179, 252, 206, 205, 151, - 18, 3, 252, 206, 205, 151, 18, 3, 210, 253, 65, 205, 151, 18, 3, 179, 65, - 205, 151, 18, 3, 65, 205, 151, 52, 1, 203, 40, 65, 205, 151, 18, 3, 203, - 40, 65, 205, 151, 18, 3, 179, 66, 205, 151, 18, 3, 66, 205, 151, 52, 1, - 68, 205, 151, 18, 3, 179, 68, 205, 151, 18, 3, 68, 205, 151, 18, 3, 74, - 205, 151, 18, 3, 200, 206, 205, 151, 87, 214, 93, 205, 151, 208, 152, - 214, 93, 205, 151, 208, 152, 251, 255, 205, 151, 208, 152, 251, 121, 205, - 151, 208, 152, 249, 57, 205, 151, 208, 152, 250, 174, 205, 151, 208, 152, - 203, 57, 205, 151, 252, 68, 77, 205, 151, 208, 152, 216, 197, 208, 48, - 205, 151, 208, 152, 191, 16, 205, 151, 208, 152, 208, 48, 205, 151, 208, - 152, 191, 119, 205, 151, 208, 152, 197, 54, 205, 151, 208, 152, 250, 255, - 205, 151, 208, 152, 202, 33, 217, 37, 205, 151, 208, 152, 251, 97, 217, - 86, 1, 230, 65, 217, 86, 1, 252, 155, 217, 86, 1, 251, 253, 217, 86, 1, - 252, 42, 217, 86, 1, 251, 245, 217, 86, 1, 196, 36, 217, 86, 1, 250, 123, - 217, 86, 1, 223, 53, 217, 86, 1, 250, 171, 217, 86, 1, 251, 211, 217, 86, - 1, 251, 216, 217, 86, 1, 251, 207, 217, 86, 1, 251, 149, 217, 86, 1, 251, - 132, 217, 86, 1, 250, 219, 217, 86, 1, 223, 162, 217, 86, 1, 251, 65, - 217, 86, 1, 250, 184, 217, 86, 1, 251, 37, 217, 86, 1, 251, 33, 217, 86, - 1, 250, 209, 217, 86, 1, 250, 182, 217, 86, 1, 235, 62, 217, 86, 1, 222, - 114, 217, 86, 1, 251, 230, 217, 86, 252, 3, 77, 217, 86, 195, 22, 77, - 217, 86, 231, 153, 77, 217, 86, 208, 151, 200, 63, 1, 142, 214, 68, 200, - 63, 1, 142, 223, 32, 200, 63, 1, 142, 212, 101, 200, 63, 1, 142, 197, - 132, 200, 63, 1, 142, 213, 79, 200, 63, 1, 142, 213, 61, 200, 63, 1, 142, - 248, 203, 200, 63, 1, 142, 165, 200, 63, 1, 142, 219, 73, 200, 63, 1, - 142, 219, 62, 200, 63, 1, 142, 201, 175, 9, 1, 131, 4, 250, 170, 233, 70, - 9, 1, 131, 4, 250, 170, 198, 54, 50, 233, 70, 9, 1, 131, 4, 50, 82, 106, - 9, 1, 131, 4, 45, 82, 106, 9, 1, 131, 4, 250, 170, 222, 52, 9, 1, 131, 4, - 250, 170, 248, 77, 50, 222, 52, 9, 1, 131, 4, 250, 170, 206, 115, 75, 58, - 9, 1, 131, 4, 250, 170, 50, 206, 115, 236, 140, 9, 1, 131, 4, 250, 170, - 45, 206, 115, 236, 140, 9, 1, 131, 4, 250, 170, 206, 115, 75, 60, 9, 1, - 131, 4, 75, 58, 9, 1, 131, 4, 250, 170, 198, 54, 50, 233, 71, 23, 75, 58, - 9, 1, 131, 4, 50, 82, 201, 28, 23, 75, 58, 9, 1, 131, 4, 250, 170, 248, - 77, 50, 222, 53, 23, 75, 58, 9, 1, 131, 4, 250, 170, 198, 54, 50, 233, - 71, 23, 45, 206, 188, 9, 1, 131, 4, 50, 82, 201, 28, 23, 45, 206, 188, 9, - 1, 131, 4, 250, 170, 248, 77, 50, 222, 53, 23, 45, 206, 188, 9, 1, 131, - 4, 250, 170, 50, 230, 57, 9, 1, 131, 4, 250, 170, 45, 230, 57, 9, 199, - 169, 4, 210, 251, 230, 57, 9, 199, 169, 4, 210, 251, 193, 133, 9, 199, - 169, 4, 105, 185, 60, 9, 1, 199, 4, 192, 75, 9, 249, 72, 206, 115, 236, - 140, 9, 207, 147, 206, 115, 236, 140, 9, 1, 213, 25, 4, 223, 93, 2, 196, - 12, 9, 1, 182, 4, 223, 93, 2, 196, 13, 60, 9, 1, 199, 220, 4, 75, 60, 9, - 1, 199, 220, 4, 115, 185, 60, 9, 1, 222, 5, 4, 105, 185, 195, 85, 60, 9, - 81, 199, 215, 9, 209, 8, 87, 58, 9, 209, 182, 87, 58, 9, 2, 137, 193, 23, - 251, 206, 9, 2, 130, 193, 23, 223, 61, 9, 2, 130, 193, 23, 223, 179, 9, - 2, 130, 193, 23, 199, 173, 9, 217, 142, 193, 179, 9, 200, 182, 131, 215, - 234, 9, 235, 128, 217, 141, 9, 132, 217, 142, 139, 217, 141, 9, 1, 248, - 246, 4, 2, 196, 13, 60, 9, 1, 248, 246, 4, 230, 58, 58, 9, 1, 223, 7, 4, - 105, 185, 58, 9, 1, 199, 220, 4, 105, 185, 58, 9, 1, 233, 47, 4, 75, 248, - 233, 23, 115, 185, 58, 9, 1, 208, 90, 4, 75, 60, 9, 1, 220, 36, 4, 55, - 164, 9, 1, 92, 4, 115, 185, 58, 9, 1, 99, 4, 105, 185, 248, 233, 23, 230, - 58, 58, 9, 1, 99, 4, 105, 185, 248, 233, 23, 75, 58, 9, 1, 207, 72, 4, - 219, 4, 9, 1, 193, 134, 4, 75, 193, 52, 9, 1, 206, 142, 192, 75, 9, 1, - 130, 251, 192, 9, 1, 238, 4, 4, 115, 185, 60, 9, 1, 205, 193, 4, 115, - 185, 60, 9, 1, 231, 228, 4, 223, 93, 106, 9, 1, 201, 53, 193, 133, 9, 1, - 191, 114, 4, 223, 93, 196, 13, 58, 9, 1, 251, 231, 4, 115, 185, 60, 9, 1, - 222, 107, 4, 75, 60, 9, 1, 208, 90, 4, 75, 248, 233, 23, 213, 44, 185, - 58, 9, 1, 248, 246, 4, 2, 92, 58, 9, 1, 210, 42, 4, 2, 92, 58, 9, 1, 199, - 115, 4, 2, 199, 115, 58, 9, 1, 207, 72, 4, 2, 213, 25, 58, 9, 1, 99, 4, - 105, 185, 248, 233, 23, 2, 213, 25, 58, 9, 1, 252, 0, 233, 46, 9, 1, 252, - 0, 208, 89, 9, 1, 252, 0, 213, 24, 9, 1, 210, 42, 4, 2, 196, 12, 9, 1, - 199, 115, 4, 2, 196, 12, 9, 1, 197, 125, 4, 2, 196, 12, 9, 1, 199, 150, - 4, 2, 196, 12, 9, 1, 222, 5, 4, 2, 196, 12, 9, 1, 231, 87, 4, 115, 185, - 58, 9, 1, 252, 0, 208, 90, 4, 115, 185, 58, 9, 1, 223, 7, 4, 115, 185, - 58, 9, 1, 223, 7, 4, 115, 185, 60, 9, 1, 220, 36, 4, 2, 9, 1, 199, 220, - 58, 9, 1, 230, 224, 9, 2, 233, 74, 192, 75, 9, 2, 137, 233, 74, 192, 75, - 9, 2, 137, 99, 249, 81, 4, 105, 185, 60, 9, 2, 137, 193, 23, 205, 182, 9, - 2, 137, 191, 116, 9, 220, 13, 206, 115, 75, 58, 9, 220, 13, 206, 115, 75, - 60, 9, 200, 207, 60, 9, 220, 13, 243, 11, 60, 9, 220, 13, 206, 115, 75, - 223, 118, 243, 11, 60, 9, 2, 130, 193, 133, 9, 2, 137, 193, 23, 251, 30, - 9, 2, 137, 205, 192, 9, 2, 137, 251, 230, 9, 2, 137, 208, 89, 9, 2, 137, - 213, 25, 4, 222, 52, 9, 2, 130, 213, 25, 4, 222, 52, 9, 2, 137, 193, 23, - 250, 181, 9, 2, 137, 193, 23, 250, 218, 9, 2, 137, 193, 23, 251, 131, 9, - 2, 137, 193, 23, 205, 171, 9, 2, 137, 193, 23, 208, 52, 9, 2, 137, 193, - 23, 193, 157, 9, 2, 137, 232, 157, 217, 51, 9, 2, 137, 3, 205, 187, 9, - 236, 218, 234, 95, 79, 250, 130, 9, 153, 237, 246, 60, 9, 238, 171, 233, - 70, 9, 238, 171, 237, 245, 9, 238, 171, 222, 52, 9, 238, 171, 233, 68, 9, - 238, 171, 237, 243, 9, 238, 171, 222, 50, 9, 163, 91, 75, 58, 9, 163, - 105, 185, 58, 9, 163, 219, 5, 58, 9, 163, 91, 75, 60, 9, 163, 105, 185, - 60, 9, 163, 219, 5, 60, 9, 211, 77, 233, 68, 9, 211, 77, 237, 243, 9, - 211, 77, 222, 50, 9, 2, 137, 193, 133, 9, 233, 71, 4, 206, 188, 9, 233, - 71, 4, 75, 58, 9, 222, 53, 4, 75, 60, 9, 45, 250, 236, 58, 9, 50, 250, - 236, 58, 9, 45, 250, 236, 60, 9, 50, 250, 236, 60, 9, 55, 50, 250, 236, - 58, 9, 55, 50, 250, 236, 93, 4, 236, 140, 9, 50, 250, 236, 93, 4, 236, - 140, 9, 237, 246, 4, 236, 140, 9, 87, 202, 206, 213, 25, 231, 57, 100, 3, - 223, 93, 247, 119, 100, 3, 247, 119, 100, 3, 251, 71, 100, 3, 195, 35, - 100, 1, 203, 40, 65, 100, 1, 65, 100, 1, 252, 206, 100, 1, 68, 100, 1, - 223, 199, 100, 1, 66, 100, 1, 196, 30, 100, 1, 117, 146, 100, 1, 117, - 172, 100, 1, 247, 122, 71, 100, 1, 203, 40, 71, 100, 1, 71, 100, 1, 251, - 236, 100, 1, 247, 122, 74, 100, 1, 203, 40, 74, 100, 1, 74, 100, 1, 250, - 163, 100, 1, 155, 100, 1, 221, 215, 100, 1, 231, 240, 100, 1, 231, 91, - 100, 1, 214, 68, 100, 1, 247, 160, 100, 1, 247, 1, 100, 1, 223, 32, 100, - 1, 222, 252, 100, 1, 212, 101, 100, 1, 197, 132, 100, 1, 197, 120, 100, - 1, 237, 191, 100, 1, 237, 175, 100, 1, 213, 79, 100, 1, 190, 190, 100, 1, - 199, 49, 100, 1, 238, 32, 100, 1, 237, 68, 100, 1, 180, 100, 1, 213, 61, - 100, 1, 168, 100, 1, 209, 228, 100, 1, 249, 153, 100, 1, 248, 203, 100, - 1, 174, 100, 1, 170, 100, 1, 165, 100, 1, 206, 109, 100, 1, 173, 100, 1, - 219, 73, 100, 1, 219, 62, 100, 1, 195, 188, 100, 1, 203, 165, 100, 1, - 201, 175, 100, 1, 188, 100, 1, 140, 100, 18, 3, 211, 151, 100, 18, 3, - 211, 85, 100, 3, 212, 141, 100, 3, 250, 145, 100, 18, 3, 252, 206, 100, - 18, 3, 68, 100, 18, 3, 223, 199, 100, 18, 3, 66, 100, 18, 3, 196, 30, - 100, 18, 3, 117, 146, 100, 18, 3, 117, 206, 110, 100, 18, 3, 247, 122, - 71, 100, 18, 3, 203, 40, 71, 100, 18, 3, 71, 100, 18, 3, 251, 236, 100, - 18, 3, 247, 122, 74, 100, 18, 3, 203, 40, 74, 100, 18, 3, 74, 100, 18, 3, - 250, 163, 100, 3, 195, 40, 100, 18, 3, 208, 207, 71, 100, 18, 3, 250, - 140, 100, 211, 113, 100, 201, 38, 3, 196, 154, 100, 201, 38, 3, 251, 73, - 100, 230, 211, 252, 60, 100, 252, 47, 252, 60, 100, 18, 3, 247, 122, 179, - 71, 100, 18, 3, 196, 152, 100, 18, 3, 196, 29, 100, 1, 208, 96, 100, 1, - 221, 193, 100, 1, 231, 66, 100, 1, 191, 123, 100, 1, 237, 180, 100, 1, - 207, 6, 100, 1, 233, 109, 100, 1, 191, 175, 100, 1, 117, 206, 110, 100, - 1, 117, 219, 74, 100, 18, 3, 117, 172, 100, 18, 3, 117, 219, 74, 100, - 237, 238, 100, 55, 237, 238, 100, 17, 191, 77, 100, 17, 107, 100, 17, - 109, 100, 17, 138, 100, 17, 134, 100, 17, 149, 100, 17, 169, 100, 17, - 175, 100, 17, 171, 100, 17, 178, 100, 252, 68, 56, 100, 3, 137, 201, 246, - 236, 140, 100, 1, 247, 122, 65, 100, 1, 211, 151, 100, 1, 211, 85, 100, - 1, 250, 140, 100, 1, 196, 152, 100, 1, 196, 29, 100, 1, 217, 43, 237, - 191, 100, 1, 191, 71, 100, 1, 88, 170, 100, 1, 231, 127, 100, 1, 222, - 230, 100, 1, 231, 11, 201, 63, 100, 1, 237, 181, 100, 1, 249, 53, 248, - 225, 251, 100, 248, 225, 3, 247, 119, 248, 225, 3, 251, 71, 248, 225, 3, - 195, 35, 248, 225, 1, 65, 248, 225, 1, 252, 206, 248, 225, 1, 68, 248, - 225, 1, 223, 199, 248, 225, 1, 66, 248, 225, 1, 196, 30, 248, 225, 1, - 117, 146, 248, 225, 1, 117, 172, 248, 225, 1, 71, 248, 225, 1, 251, 236, - 248, 225, 1, 74, 248, 225, 1, 250, 163, 248, 225, 1, 155, 248, 225, 1, - 221, 215, 248, 225, 1, 231, 240, 248, 225, 1, 231, 91, 248, 225, 1, 214, - 68, 248, 225, 1, 247, 160, 248, 225, 1, 247, 1, 248, 225, 1, 223, 32, - 248, 225, 1, 222, 252, 248, 225, 1, 212, 101, 248, 225, 1, 197, 132, 248, - 225, 1, 197, 120, 248, 225, 1, 237, 191, 248, 225, 1, 237, 175, 248, 225, - 1, 213, 79, 248, 225, 1, 190, 190, 248, 225, 1, 199, 49, 248, 225, 1, - 238, 32, 248, 225, 1, 237, 68, 248, 225, 1, 180, 248, 225, 1, 168, 248, - 225, 1, 209, 228, 248, 225, 1, 249, 153, 248, 225, 1, 248, 203, 248, 225, - 1, 174, 248, 225, 1, 170, 248, 225, 1, 165, 248, 225, 1, 173, 248, 225, - 1, 203, 165, 248, 225, 1, 201, 175, 248, 225, 1, 188, 248, 225, 1, 140, - 248, 225, 3, 212, 141, 248, 225, 3, 250, 145, 248, 225, 18, 3, 252, 206, - 248, 225, 18, 3, 68, 248, 225, 18, 3, 223, 199, 248, 225, 18, 3, 66, 248, - 225, 18, 3, 196, 30, 248, 225, 18, 3, 117, 146, 248, 225, 18, 3, 117, - 206, 110, 248, 225, 18, 3, 71, 248, 225, 18, 3, 251, 236, 248, 225, 18, - 3, 74, 248, 225, 18, 3, 250, 163, 248, 225, 3, 195, 40, 248, 225, 1, 221, - 204, 190, 190, 248, 225, 250, 164, 219, 198, 77, 248, 225, 1, 206, 109, - 248, 225, 1, 207, 6, 248, 225, 1, 191, 175, 248, 225, 1, 117, 206, 110, - 248, 225, 1, 117, 219, 74, 248, 225, 18, 3, 117, 172, 248, 225, 18, 3, - 117, 219, 74, 248, 225, 17, 191, 77, 248, 225, 17, 107, 248, 225, 17, - 109, 248, 225, 17, 138, 248, 225, 17, 134, 248, 225, 17, 149, 248, 225, - 17, 169, 248, 225, 17, 175, 248, 225, 17, 171, 248, 225, 17, 178, 248, - 225, 1, 207, 186, 4, 82, 237, 38, 248, 225, 1, 207, 186, 4, 110, 237, 38, - 248, 225, 206, 36, 77, 248, 225, 206, 36, 56, 248, 225, 238, 170, 212, - 133, 107, 248, 225, 238, 170, 212, 133, 109, 248, 225, 238, 170, 212, - 133, 138, 248, 225, 238, 170, 212, 133, 134, 248, 225, 238, 170, 212, - 133, 91, 219, 181, 199, 39, 199, 34, 237, 99, 248, 225, 238, 170, 237, - 100, 202, 130, 248, 225, 223, 54, 248, 225, 231, 207, 77, 248, 225, 1, - 195, 150, 251, 71, 248, 225, 252, 68, 56, 248, 225, 205, 138, 77, 230, - 144, 3, 252, 41, 248, 167, 230, 144, 3, 248, 167, 230, 144, 3, 195, 35, - 230, 144, 1, 65, 230, 144, 1, 252, 206, 230, 144, 1, 68, 230, 144, 1, - 223, 199, 230, 144, 1, 66, 230, 144, 1, 196, 30, 230, 144, 1, 234, 188, - 230, 144, 1, 251, 236, 230, 144, 1, 211, 87, 230, 144, 1, 250, 163, 230, - 144, 1, 155, 230, 144, 1, 221, 215, 230, 144, 1, 231, 240, 230, 144, 1, - 231, 91, 230, 144, 1, 214, 68, 230, 144, 1, 247, 160, 230, 144, 1, 247, - 1, 230, 144, 1, 223, 32, 230, 144, 1, 222, 252, 230, 144, 1, 212, 101, - 230, 144, 1, 197, 132, 230, 144, 1, 197, 120, 230, 144, 1, 237, 191, 230, - 144, 1, 237, 175, 230, 144, 1, 213, 79, 230, 144, 1, 190, 190, 230, 144, - 1, 199, 49, 230, 144, 1, 238, 32, 230, 144, 1, 237, 68, 230, 144, 1, 180, - 230, 144, 1, 168, 230, 144, 1, 209, 228, 230, 144, 1, 249, 153, 230, 144, - 1, 248, 203, 230, 144, 1, 174, 230, 144, 1, 170, 230, 144, 1, 165, 230, - 144, 1, 173, 230, 144, 1, 219, 73, 230, 144, 1, 195, 188, 230, 144, 1, - 203, 165, 230, 144, 1, 188, 230, 144, 1, 140, 230, 144, 3, 212, 141, 230, - 144, 18, 3, 252, 206, 230, 144, 18, 3, 68, 230, 144, 18, 3, 223, 199, - 230, 144, 18, 3, 66, 230, 144, 18, 3, 196, 30, 230, 144, 18, 3, 234, 188, - 230, 144, 18, 3, 251, 236, 230, 144, 18, 3, 211, 87, 230, 144, 18, 3, - 250, 163, 230, 144, 3, 195, 40, 230, 144, 3, 196, 157, 230, 144, 1, 221, - 193, 230, 144, 1, 231, 66, 230, 144, 1, 191, 123, 230, 144, 1, 206, 109, - 230, 144, 1, 233, 109, 230, 144, 17, 191, 77, 230, 144, 17, 107, 230, - 144, 17, 109, 230, 144, 17, 138, 230, 144, 17, 134, 230, 144, 17, 149, - 230, 144, 17, 169, 230, 144, 17, 175, 230, 144, 17, 171, 230, 144, 17, - 178, 230, 144, 198, 133, 230, 144, 252, 40, 230, 144, 223, 75, 230, 144, - 196, 58, 230, 144, 234, 148, 211, 92, 230, 144, 3, 192, 115, 230, 144, - 252, 68, 56, 230, 161, 3, 247, 119, 230, 161, 3, 251, 71, 230, 161, 3, - 195, 35, 230, 161, 1, 65, 230, 161, 1, 252, 206, 230, 161, 1, 68, 230, - 161, 1, 223, 199, 230, 161, 1, 66, 230, 161, 1, 196, 30, 230, 161, 1, - 117, 146, 230, 161, 1, 117, 172, 230, 161, 18, 247, 122, 71, 230, 161, 1, - 71, 230, 161, 1, 251, 236, 230, 161, 18, 247, 122, 74, 230, 161, 1, 74, - 230, 161, 1, 250, 163, 230, 161, 1, 155, 230, 161, 1, 221, 215, 230, 161, - 1, 231, 240, 230, 161, 1, 231, 91, 230, 161, 1, 214, 68, 230, 161, 1, - 247, 160, 230, 161, 1, 247, 1, 230, 161, 1, 223, 32, 230, 161, 1, 222, - 252, 230, 161, 1, 212, 101, 230, 161, 1, 197, 132, 230, 161, 1, 197, 120, - 230, 161, 1, 237, 191, 230, 161, 1, 237, 175, 230, 161, 1, 213, 79, 230, - 161, 1, 190, 190, 230, 161, 1, 199, 49, 230, 161, 1, 238, 32, 230, 161, - 1, 237, 68, 230, 161, 1, 180, 230, 161, 1, 168, 230, 161, 1, 209, 228, - 230, 161, 1, 249, 153, 230, 161, 1, 248, 203, 230, 161, 1, 174, 230, 161, - 1, 170, 230, 161, 1, 165, 230, 161, 1, 173, 230, 161, 1, 219, 73, 230, - 161, 1, 195, 188, 230, 161, 1, 203, 165, 230, 161, 1, 201, 175, 230, 161, - 1, 188, 230, 161, 1, 140, 230, 161, 3, 212, 141, 230, 161, 3, 250, 145, - 230, 161, 18, 3, 252, 206, 230, 161, 18, 3, 68, 230, 161, 18, 3, 223, - 199, 230, 161, 18, 3, 66, 230, 161, 18, 3, 196, 30, 230, 161, 18, 3, 117, - 146, 230, 161, 18, 3, 117, 206, 110, 230, 161, 18, 3, 247, 122, 71, 230, - 161, 18, 3, 71, 230, 161, 18, 3, 251, 236, 230, 161, 18, 3, 247, 122, 74, - 230, 161, 18, 3, 74, 230, 161, 18, 3, 250, 163, 230, 161, 3, 195, 40, - 230, 161, 211, 113, 230, 161, 1, 117, 206, 110, 230, 161, 1, 117, 219, - 74, 230, 161, 18, 3, 117, 172, 230, 161, 18, 3, 117, 219, 74, 230, 161, - 17, 191, 77, 230, 161, 17, 107, 230, 161, 17, 109, 230, 161, 17, 138, - 230, 161, 17, 134, 230, 161, 17, 149, 230, 161, 17, 169, 230, 161, 17, - 175, 230, 161, 17, 171, 230, 161, 17, 178, 230, 161, 252, 68, 56, 230, - 161, 206, 36, 56, 230, 161, 1, 191, 71, 230, 161, 3, 200, 206, 230, 161, - 3, 203, 155, 230, 161, 3, 217, 139, 230, 161, 3, 198, 224, 212, 142, 58, - 230, 161, 3, 243, 11, 212, 142, 58, 230, 161, 3, 197, 15, 212, 142, 58, - 211, 45, 3, 247, 119, 211, 45, 3, 251, 71, 211, 45, 3, 195, 35, 211, 45, - 1, 65, 211, 45, 1, 252, 206, 211, 45, 1, 68, 211, 45, 1, 223, 199, 211, - 45, 1, 66, 211, 45, 1, 196, 30, 211, 45, 1, 117, 146, 211, 45, 1, 117, - 172, 211, 45, 1, 71, 211, 45, 1, 251, 236, 211, 45, 1, 74, 211, 45, 1, - 250, 163, 211, 45, 1, 155, 211, 45, 1, 221, 215, 211, 45, 1, 231, 240, - 211, 45, 1, 231, 91, 211, 45, 1, 214, 68, 211, 45, 1, 247, 160, 211, 45, - 1, 247, 1, 211, 45, 1, 223, 32, 211, 45, 1, 222, 252, 211, 45, 1, 212, - 101, 211, 45, 1, 197, 132, 211, 45, 1, 197, 120, 211, 45, 1, 237, 191, - 211, 45, 1, 237, 175, 211, 45, 1, 213, 79, 211, 45, 1, 190, 190, 211, 45, - 1, 199, 49, 211, 45, 1, 238, 32, 211, 45, 1, 237, 68, 211, 45, 1, 180, - 211, 45, 1, 168, 211, 45, 1, 209, 228, 211, 45, 1, 249, 153, 211, 45, 1, - 248, 203, 211, 45, 1, 174, 211, 45, 1, 170, 211, 45, 1, 165, 211, 45, 1, - 173, 211, 45, 1, 219, 73, 211, 45, 1, 195, 188, 211, 45, 1, 203, 165, - 211, 45, 1, 201, 175, 211, 45, 1, 188, 211, 45, 1, 140, 211, 45, 3, 212, - 141, 211, 45, 3, 250, 145, 211, 45, 18, 3, 252, 206, 211, 45, 18, 3, 68, - 211, 45, 18, 3, 223, 199, 211, 45, 18, 3, 66, 211, 45, 18, 3, 196, 30, - 211, 45, 18, 3, 117, 146, 211, 45, 18, 3, 117, 206, 110, 211, 45, 18, 3, - 71, 211, 45, 18, 3, 251, 236, 211, 45, 18, 3, 74, 211, 45, 18, 3, 250, - 163, 211, 45, 3, 195, 40, 211, 45, 3, 210, 254, 211, 45, 251, 237, 219, - 198, 77, 211, 45, 250, 164, 219, 198, 77, 211, 45, 1, 206, 109, 211, 45, - 1, 207, 6, 211, 45, 1, 191, 175, 211, 45, 1, 117, 206, 110, 211, 45, 1, - 117, 219, 74, 211, 45, 18, 3, 117, 172, 211, 45, 18, 3, 117, 219, 74, - 211, 45, 17, 191, 77, 211, 45, 17, 107, 211, 45, 17, 109, 211, 45, 17, - 138, 211, 45, 17, 134, 211, 45, 17, 149, 211, 45, 17, 169, 211, 45, 17, - 175, 211, 45, 17, 171, 211, 45, 17, 178, 211, 45, 223, 54, 211, 45, 1, - 193, 190, 211, 45, 232, 118, 91, 208, 22, 211, 45, 232, 118, 91, 230, 70, - 211, 45, 232, 118, 115, 208, 20, 211, 45, 232, 118, 91, 202, 128, 211, - 45, 232, 118, 91, 234, 159, 211, 45, 232, 118, 115, 202, 125, 44, 3, 251, - 71, 44, 3, 195, 35, 44, 1, 65, 44, 1, 252, 206, 44, 1, 68, 44, 1, 223, - 199, 44, 1, 66, 44, 1, 196, 30, 44, 1, 71, 44, 1, 234, 188, 44, 1, 251, - 236, 44, 1, 74, 44, 1, 211, 87, 44, 1, 250, 163, 44, 1, 155, 44, 1, 214, - 68, 44, 1, 247, 160, 44, 1, 223, 32, 44, 1, 212, 101, 44, 1, 197, 132, - 44, 1, 213, 79, 44, 1, 190, 190, 44, 1, 180, 44, 1, 213, 61, 44, 1, 168, - 44, 1, 174, 44, 1, 170, 44, 1, 165, 44, 1, 206, 109, 44, 1, 173, 44, 1, - 219, 73, 44, 1, 219, 62, 44, 1, 195, 188, 44, 1, 203, 165, 44, 1, 201, - 175, 44, 1, 188, 44, 1, 140, 44, 18, 3, 252, 206, 44, 18, 3, 68, 44, 18, - 3, 223, 199, 44, 18, 3, 66, 44, 18, 3, 196, 30, 44, 18, 3, 71, 44, 18, 3, - 234, 188, 44, 18, 3, 251, 236, 44, 18, 3, 74, 44, 18, 3, 211, 87, 44, 18, - 3, 250, 163, 44, 3, 195, 40, 44, 211, 113, 44, 250, 164, 219, 198, 77, - 44, 17, 191, 77, 44, 17, 107, 44, 17, 109, 44, 17, 138, 44, 17, 134, 44, - 17, 149, 44, 17, 169, 44, 17, 175, 44, 17, 171, 44, 17, 178, 44, 31, 199, - 95, 44, 31, 91, 228, 140, 44, 31, 91, 189, 44, 237, 204, 56, 44, 215, - 214, 56, 44, 192, 78, 56, 44, 237, 142, 56, 44, 238, 230, 56, 44, 250, - 220, 93, 56, 44, 206, 36, 56, 44, 31, 56, 199, 99, 3, 33, 247, 120, 58, - 199, 99, 3, 247, 119, 199, 99, 3, 251, 71, 199, 99, 3, 195, 35, 199, 99, - 3, 33, 251, 72, 58, 199, 99, 1, 65, 199, 99, 1, 252, 206, 199, 99, 1, 68, - 199, 99, 1, 223, 199, 199, 99, 1, 66, 199, 99, 1, 196, 30, 199, 99, 1, - 117, 146, 199, 99, 1, 117, 172, 199, 99, 1, 71, 199, 99, 1, 234, 188, - 199, 99, 1, 251, 236, 199, 99, 1, 74, 199, 99, 1, 211, 87, 199, 99, 1, - 250, 163, 199, 99, 1, 155, 199, 99, 1, 221, 215, 199, 99, 1, 231, 240, - 199, 99, 1, 231, 91, 199, 99, 1, 214, 68, 199, 99, 1, 247, 160, 199, 99, - 1, 247, 1, 199, 99, 1, 223, 32, 199, 99, 1, 222, 252, 199, 99, 1, 212, - 101, 199, 99, 1, 197, 132, 199, 99, 1, 197, 120, 199, 99, 1, 237, 191, - 199, 99, 1, 237, 175, 199, 99, 1, 213, 79, 199, 99, 1, 190, 190, 199, 99, - 1, 199, 49, 199, 99, 1, 238, 32, 199, 99, 1, 237, 68, 199, 99, 1, 180, - 199, 99, 1, 168, 199, 99, 1, 209, 228, 199, 99, 1, 249, 153, 199, 99, 1, - 248, 203, 199, 99, 1, 174, 199, 99, 1, 170, 199, 99, 1, 165, 199, 99, 1, - 206, 109, 199, 99, 1, 173, 199, 99, 1, 219, 73, 199, 99, 1, 219, 62, 199, - 99, 1, 195, 188, 199, 99, 1, 203, 165, 199, 99, 1, 201, 175, 199, 99, 1, - 188, 199, 99, 1, 140, 199, 99, 3, 212, 141, 199, 99, 3, 250, 145, 199, - 99, 18, 3, 252, 206, 199, 99, 18, 3, 68, 199, 99, 18, 3, 223, 199, 199, - 99, 18, 3, 66, 199, 99, 18, 3, 196, 30, 199, 99, 18, 3, 117, 146, 199, - 99, 18, 3, 117, 206, 110, 199, 99, 18, 3, 71, 199, 99, 18, 3, 234, 188, - 199, 99, 18, 3, 251, 236, 199, 99, 18, 3, 74, 199, 99, 18, 3, 211, 87, - 199, 99, 18, 3, 250, 163, 199, 99, 3, 195, 40, 199, 99, 219, 198, 77, - 199, 99, 251, 237, 219, 198, 77, 199, 99, 1, 197, 168, 199, 99, 1, 235, - 35, 199, 99, 1, 206, 90, 199, 99, 1, 214, 232, 209, 46, 199, 99, 1, 117, - 206, 110, 199, 99, 1, 117, 219, 74, 199, 99, 18, 3, 117, 172, 199, 99, - 18, 3, 117, 219, 74, 199, 99, 17, 191, 77, 199, 99, 17, 107, 199, 99, 17, - 109, 199, 99, 17, 138, 199, 99, 17, 134, 199, 99, 17, 149, 199, 99, 17, - 169, 199, 99, 17, 175, 199, 99, 17, 171, 199, 99, 17, 178, 199, 99, 3, - 202, 210, 199, 99, 232, 118, 17, 191, 78, 40, 211, 155, 208, 253, 79, - 134, 199, 99, 232, 118, 17, 91, 40, 211, 155, 208, 253, 79, 134, 199, 99, - 232, 118, 17, 105, 40, 211, 155, 208, 253, 79, 134, 199, 99, 232, 118, - 17, 115, 40, 211, 155, 208, 253, 79, 134, 199, 99, 232, 118, 17, 91, 40, - 233, 229, 208, 253, 79, 134, 199, 99, 232, 118, 17, 105, 40, 233, 229, - 208, 253, 79, 134, 199, 99, 232, 118, 17, 115, 40, 233, 229, 208, 253, - 79, 134, 199, 99, 3, 197, 48, 222, 81, 3, 201, 246, 247, 119, 222, 81, 3, - 247, 119, 222, 81, 3, 251, 71, 222, 81, 3, 195, 35, 222, 81, 3, 202, 210, - 222, 81, 1, 65, 222, 81, 1, 252, 206, 222, 81, 1, 68, 222, 81, 1, 223, - 199, 222, 81, 1, 66, 222, 81, 1, 196, 30, 222, 81, 1, 117, 146, 222, 81, - 1, 117, 172, 222, 81, 1, 71, 222, 81, 1, 234, 188, 222, 81, 1, 251, 236, - 222, 81, 1, 74, 222, 81, 1, 211, 87, 222, 81, 1, 250, 163, 222, 81, 1, - 155, 222, 81, 1, 221, 215, 222, 81, 1, 231, 240, 222, 81, 1, 231, 91, - 222, 81, 1, 214, 68, 222, 81, 1, 247, 160, 222, 81, 1, 247, 1, 222, 81, - 1, 223, 32, 222, 81, 1, 222, 252, 222, 81, 1, 212, 101, 222, 81, 1, 197, - 132, 222, 81, 1, 197, 120, 222, 81, 1, 237, 191, 222, 81, 1, 237, 175, - 222, 81, 1, 213, 79, 222, 81, 1, 190, 190, 222, 81, 1, 199, 49, 222, 81, - 1, 238, 32, 222, 81, 1, 237, 68, 222, 81, 1, 180, 222, 81, 1, 168, 222, - 81, 1, 209, 228, 222, 81, 1, 249, 153, 222, 81, 1, 248, 203, 222, 81, 1, - 174, 222, 81, 1, 170, 222, 81, 1, 165, 222, 81, 1, 206, 109, 222, 81, 1, - 173, 222, 81, 1, 219, 73, 222, 81, 1, 195, 188, 222, 81, 1, 203, 165, - 222, 81, 1, 201, 175, 222, 81, 1, 188, 222, 81, 1, 140, 222, 81, 3, 212, - 141, 222, 81, 3, 250, 145, 222, 81, 18, 3, 252, 206, 222, 81, 18, 3, 68, - 222, 81, 18, 3, 223, 199, 222, 81, 18, 3, 66, 222, 81, 18, 3, 196, 30, - 222, 81, 18, 3, 117, 146, 222, 81, 18, 3, 117, 206, 110, 222, 81, 18, 3, - 71, 222, 81, 18, 3, 234, 188, 222, 81, 18, 3, 251, 236, 222, 81, 18, 3, - 74, 222, 81, 18, 3, 211, 87, 222, 81, 18, 3, 250, 163, 222, 81, 3, 195, - 40, 222, 81, 219, 198, 77, 222, 81, 251, 237, 219, 198, 77, 222, 81, 1, - 214, 232, 209, 46, 222, 81, 1, 233, 109, 222, 81, 1, 117, 206, 110, 222, - 81, 1, 117, 219, 74, 222, 81, 18, 3, 117, 172, 222, 81, 18, 3, 117, 219, - 74, 222, 81, 17, 191, 77, 222, 81, 17, 107, 222, 81, 17, 109, 222, 81, - 17, 138, 222, 81, 17, 134, 222, 81, 17, 149, 222, 81, 17, 169, 222, 81, - 17, 175, 222, 81, 17, 171, 222, 81, 17, 178, 222, 81, 3, 222, 237, 222, - 81, 3, 196, 75, 222, 81, 3, 33, 251, 72, 93, 183, 142, 3, 33, 251, 72, - 58, 142, 3, 247, 119, 142, 3, 251, 71, 142, 3, 195, 35, 142, 1, 195, 150, - 251, 71, 142, 1, 65, 142, 1, 252, 206, 142, 1, 68, 142, 1, 223, 199, 142, - 1, 66, 142, 1, 196, 30, 142, 1, 117, 146, 142, 1, 117, 172, 142, 1, 71, - 142, 1, 234, 188, 142, 1, 251, 236, 142, 1, 74, 142, 1, 211, 87, 142, 1, - 250, 163, 142, 1, 155, 142, 1, 221, 215, 142, 1, 231, 240, 142, 1, 231, - 91, 142, 1, 214, 68, 142, 1, 247, 160, 142, 1, 247, 1, 142, 1, 223, 32, - 142, 1, 222, 252, 142, 1, 212, 101, 142, 1, 197, 132, 142, 1, 197, 120, - 142, 1, 237, 191, 142, 1, 237, 175, 142, 1, 213, 79, 142, 1, 190, 190, - 142, 1, 199, 49, 142, 1, 238, 32, 142, 1, 237, 68, 142, 1, 180, 142, 1, - 213, 61, 142, 1, 168, 142, 1, 209, 228, 142, 1, 249, 153, 142, 1, 248, - 203, 142, 1, 174, 142, 1, 170, 142, 1, 165, 142, 1, 206, 109, 142, 1, - 173, 142, 1, 219, 73, 142, 1, 219, 62, 142, 1, 195, 188, 142, 1, 203, - 165, 142, 1, 201, 175, 142, 1, 188, 142, 1, 140, 142, 1, 197, 101, 142, - 3, 81, 249, 88, 195, 40, 142, 3, 243, 4, 195, 40, 142, 3, 250, 145, 142, - 18, 3, 252, 206, 142, 18, 3, 68, 142, 18, 3, 223, 199, 142, 18, 3, 66, - 142, 18, 3, 196, 30, 142, 18, 3, 117, 146, 142, 18, 3, 117, 206, 110, - 142, 18, 3, 71, 142, 18, 3, 234, 188, 142, 18, 3, 251, 236, 142, 18, 3, - 74, 142, 18, 3, 211, 87, 142, 18, 3, 250, 163, 142, 3, 195, 40, 142, 1, - 75, 207, 45, 142, 3, 210, 130, 142, 1, 243, 84, 218, 168, 142, 1, 243, - 84, 192, 159, 142, 1, 243, 84, 219, 63, 142, 250, 164, 219, 198, 77, 142, - 232, 118, 91, 211, 100, 142, 232, 118, 91, 232, 139, 142, 232, 118, 115, - 234, 155, 142, 232, 118, 91, 197, 35, 142, 232, 118, 91, 199, 86, 142, - 232, 118, 115, 197, 34, 142, 232, 118, 91, 233, 18, 142, 1, 251, 14, 223, - 199, 142, 1, 117, 206, 110, 142, 1, 117, 219, 74, 142, 18, 3, 117, 172, - 142, 18, 3, 117, 219, 74, 142, 17, 191, 77, 142, 17, 107, 142, 17, 109, - 142, 17, 138, 142, 17, 134, 142, 17, 149, 142, 17, 169, 142, 17, 175, - 142, 17, 171, 142, 17, 178, 142, 31, 199, 95, 142, 31, 91, 228, 140, 142, - 31, 91, 189, 142, 232, 118, 91, 208, 22, 142, 232, 118, 91, 230, 70, 142, - 232, 118, 115, 208, 20, 142, 232, 118, 91, 202, 128, 142, 232, 118, 91, - 234, 159, 142, 232, 118, 115, 202, 125, 142, 237, 209, 77, 142, 1, 243, - 84, 213, 80, 142, 1, 243, 84, 215, 61, 142, 1, 243, 84, 206, 110, 142, 1, - 243, 84, 172, 142, 1, 243, 84, 219, 74, 142, 1, 243, 84, 222, 152, 166, - 3, 247, 119, 166, 3, 251, 70, 166, 3, 195, 34, 166, 1, 250, 129, 166, 1, - 252, 159, 166, 1, 252, 5, 166, 1, 252, 20, 166, 1, 223, 43, 166, 1, 223, - 198, 166, 1, 196, 20, 166, 1, 196, 24, 166, 1, 223, 70, 166, 1, 223, 71, - 166, 1, 223, 182, 166, 1, 223, 184, 166, 1, 233, 196, 166, 1, 234, 183, - 166, 1, 251, 219, 166, 1, 210, 241, 166, 1, 211, 80, 166, 1, 250, 148, - 166, 1, 251, 163, 222, 27, 166, 1, 217, 119, 222, 27, 166, 1, 251, 163, - 231, 185, 166, 1, 217, 119, 231, 185, 166, 1, 222, 80, 214, 247, 166, 1, - 205, 132, 231, 185, 166, 1, 251, 163, 247, 68, 166, 1, 217, 119, 247, 68, - 166, 1, 251, 163, 223, 13, 166, 1, 217, 119, 223, 13, 166, 1, 199, 241, - 214, 247, 166, 1, 199, 241, 205, 131, 214, 248, 166, 1, 205, 132, 223, - 13, 166, 1, 251, 163, 197, 128, 166, 1, 217, 119, 197, 128, 166, 1, 251, - 163, 237, 182, 166, 1, 217, 119, 237, 182, 166, 1, 215, 92, 214, 197, - 166, 1, 205, 132, 237, 182, 166, 1, 251, 163, 199, 153, 166, 1, 217, 119, - 199, 153, 166, 1, 251, 163, 237, 202, 166, 1, 217, 119, 237, 202, 166, 1, - 237, 234, 214, 197, 166, 1, 205, 132, 237, 202, 166, 1, 251, 163, 210, - 71, 166, 1, 217, 119, 210, 71, 166, 1, 251, 163, 249, 55, 166, 1, 217, - 119, 249, 55, 166, 1, 217, 19, 166, 1, 251, 143, 249, 55, 166, 1, 192, - 85, 166, 1, 207, 121, 166, 1, 237, 234, 219, 247, 166, 1, 195, 156, 166, - 1, 199, 241, 205, 102, 166, 1, 215, 92, 205, 102, 166, 1, 237, 234, 205, - 102, 166, 1, 229, 251, 166, 1, 215, 92, 219, 247, 166, 1, 233, 61, 166, - 3, 251, 205, 166, 18, 3, 252, 15, 166, 18, 3, 221, 240, 252, 22, 166, 18, - 3, 237, 11, 252, 22, 166, 18, 3, 221, 240, 223, 67, 166, 18, 3, 237, 11, - 223, 67, 166, 18, 3, 221, 240, 210, 219, 166, 18, 3, 237, 11, 210, 219, - 166, 18, 3, 231, 229, 166, 18, 3, 221, 46, 166, 18, 3, 237, 11, 221, 46, - 166, 18, 3, 221, 48, 237, 120, 166, 18, 3, 221, 47, 230, 92, 252, 15, - 166, 18, 3, 221, 47, 230, 92, 237, 11, 252, 15, 166, 18, 3, 221, 47, 230, - 92, 231, 184, 166, 18, 3, 231, 184, 166, 219, 86, 17, 191, 77, 166, 219, - 86, 17, 107, 166, 219, 86, 17, 109, 166, 219, 86, 17, 138, 166, 219, 86, - 17, 134, 166, 219, 86, 17, 149, 166, 219, 86, 17, 169, 166, 219, 86, 17, - 175, 166, 219, 86, 17, 171, 166, 219, 86, 17, 178, 166, 18, 3, 237, 11, - 231, 229, 166, 18, 3, 237, 11, 231, 184, 166, 208, 152, 220, 209, 199, - 44, 246, 240, 221, 68, 222, 102, 199, 44, 246, 240, 221, 184, 221, 209, - 199, 44, 246, 240, 221, 184, 221, 174, 199, 44, 246, 240, 221, 184, 221, - 169, 199, 44, 246, 240, 221, 184, 221, 179, 199, 44, 246, 240, 221, 184, - 207, 143, 199, 44, 246, 240, 213, 250, 213, 237, 199, 44, 246, 240, 243, - 69, 246, 246, 199, 44, 246, 240, 243, 69, 243, 79, 199, 44, 246, 240, - 243, 69, 246, 245, 199, 44, 246, 240, 202, 47, 202, 46, 199, 44, 246, - 240, 243, 69, 243, 65, 199, 44, 246, 240, 192, 13, 192, 20, 199, 44, 246, - 240, 236, 175, 246, 254, 199, 44, 246, 240, 119, 210, 87, 199, 44, 246, - 240, 198, 242, 199, 38, 199, 44, 246, 240, 198, 242, 214, 222, 199, 44, - 246, 240, 198, 242, 209, 188, 199, 44, 246, 240, 213, 44, 214, 102, 199, - 44, 246, 240, 236, 175, 237, 121, 199, 44, 246, 240, 119, 199, 184, 199, - 44, 246, 240, 198, 242, 198, 207, 199, 44, 246, 240, 198, 242, 199, 45, - 199, 44, 246, 240, 198, 242, 198, 236, 199, 44, 246, 240, 213, 44, 212, - 178, 199, 44, 246, 240, 248, 112, 249, 118, 199, 44, 246, 240, 209, 74, - 209, 110, 199, 44, 246, 240, 209, 200, 209, 190, 199, 44, 246, 240, 232, - 176, 233, 109, 199, 44, 246, 240, 209, 200, 209, 221, 199, 44, 246, 240, - 232, 176, 233, 80, 199, 44, 246, 240, 209, 200, 205, 146, 199, 44, 246, - 240, 216, 13, 174, 199, 44, 246, 240, 192, 13, 192, 116, 199, 44, 246, - 240, 206, 163, 206, 61, 199, 44, 246, 240, 206, 68, 199, 44, 246, 240, - 219, 44, 219, 105, 199, 44, 246, 240, 218, 225, 199, 44, 246, 240, 193, - 49, 193, 175, 199, 44, 246, 240, 202, 47, 205, 167, 199, 44, 246, 240, - 202, 47, 206, 32, 199, 44, 246, 240, 202, 47, 200, 251, 199, 44, 246, - 240, 229, 24, 229, 122, 199, 44, 246, 240, 219, 44, 243, 47, 199, 44, - 246, 240, 187, 251, 122, 199, 44, 246, 240, 229, 24, 213, 34, 199, 44, - 246, 240, 210, 194, 199, 44, 246, 240, 205, 126, 65, 199, 44, 246, 240, - 217, 113, 230, 55, 199, 44, 246, 240, 205, 126, 252, 206, 199, 44, 246, - 240, 205, 126, 251, 149, 199, 44, 246, 240, 205, 126, 68, 199, 44, 246, - 240, 205, 126, 223, 199, 199, 44, 246, 240, 205, 126, 196, 152, 199, 44, - 246, 240, 205, 126, 196, 149, 199, 44, 246, 240, 205, 126, 66, 199, 44, - 246, 240, 205, 126, 196, 30, 199, 44, 246, 240, 209, 202, 199, 44, 238, - 170, 16, 249, 119, 199, 44, 246, 240, 205, 126, 71, 199, 44, 246, 240, - 205, 126, 252, 25, 199, 44, 246, 240, 205, 126, 74, 199, 44, 246, 240, - 205, 126, 251, 237, 217, 107, 199, 44, 246, 240, 205, 126, 251, 237, 217, - 108, 199, 44, 246, 240, 220, 39, 199, 44, 246, 240, 217, 104, 199, 44, - 246, 240, 217, 105, 199, 44, 246, 240, 217, 113, 234, 147, 199, 44, 246, - 240, 217, 113, 198, 241, 199, 44, 246, 240, 217, 113, 197, 244, 199, 44, - 246, 240, 217, 113, 243, 132, 199, 44, 246, 240, 199, 36, 199, 44, 246, - 240, 213, 183, 199, 44, 246, 240, 192, 110, 199, 44, 246, 240, 232, 164, - 199, 44, 17, 191, 77, 199, 44, 17, 107, 199, 44, 17, 109, 199, 44, 17, - 138, 199, 44, 17, 134, 199, 44, 17, 149, 199, 44, 17, 169, 199, 44, 17, - 175, 199, 44, 17, 171, 199, 44, 17, 178, 199, 44, 246, 240, 251, 117, - 199, 44, 246, 240, 221, 180, 220, 17, 1, 221, 67, 220, 17, 1, 221, 184, - 200, 195, 220, 17, 1, 221, 184, 199, 197, 220, 17, 1, 210, 187, 231, 91, - 220, 17, 1, 213, 249, 220, 17, 1, 242, 99, 220, 17, 1, 210, 187, 247, 1, - 220, 17, 1, 202, 47, 199, 197, 220, 17, 1, 210, 187, 222, 252, 220, 17, - 1, 212, 65, 220, 17, 1, 210, 187, 212, 101, 220, 17, 1, 210, 187, 197, - 132, 220, 17, 1, 210, 187, 197, 120, 220, 17, 1, 210, 187, 237, 191, 220, - 17, 1, 210, 187, 237, 175, 220, 17, 1, 210, 187, 213, 79, 220, 17, 1, - 236, 174, 220, 17, 1, 159, 220, 17, 1, 198, 242, 200, 195, 220, 17, 1, - 198, 242, 199, 197, 220, 17, 1, 210, 187, 237, 68, 220, 17, 1, 213, 43, - 220, 17, 1, 248, 111, 220, 17, 1, 209, 73, 220, 17, 1, 209, 200, 200, - 195, 220, 17, 1, 232, 176, 199, 197, 220, 17, 1, 209, 200, 199, 197, 220, - 17, 1, 232, 176, 200, 195, 220, 17, 1, 210, 187, 248, 203, 220, 17, 1, - 216, 12, 220, 17, 1, 192, 12, 220, 17, 1, 219, 44, 219, 105, 220, 17, 1, - 219, 44, 219, 2, 220, 17, 1, 193, 48, 220, 17, 1, 205, 134, 203, 165, - 220, 17, 1, 205, 134, 201, 175, 220, 17, 1, 202, 47, 200, 195, 220, 17, - 1, 229, 24, 200, 195, 220, 17, 1, 210, 187, 219, 73, 220, 17, 1, 74, 220, - 17, 1, 229, 24, 199, 197, 220, 17, 234, 120, 220, 17, 18, 3, 65, 220, 17, - 18, 3, 217, 113, 222, 87, 220, 17, 18, 3, 252, 206, 220, 17, 18, 3, 251, - 149, 220, 17, 18, 3, 68, 220, 17, 18, 3, 223, 199, 220, 17, 18, 3, 192, - 159, 220, 17, 18, 3, 191, 176, 220, 17, 18, 3, 66, 220, 17, 18, 3, 196, - 30, 220, 17, 3, 210, 187, 195, 40, 220, 17, 18, 3, 217, 113, 221, 44, - 220, 17, 204, 20, 3, 219, 43, 220, 17, 204, 20, 3, 212, 65, 220, 17, 18, - 3, 71, 220, 17, 18, 3, 234, 166, 220, 17, 18, 3, 74, 220, 17, 18, 3, 250, - 131, 220, 17, 18, 3, 251, 236, 220, 17, 221, 68, 173, 220, 17, 163, 217, - 113, 234, 147, 220, 17, 163, 217, 113, 198, 241, 220, 17, 163, 217, 113, - 198, 193, 220, 17, 163, 217, 113, 247, 77, 220, 17, 247, 125, 77, 220, - 17, 213, 192, 220, 17, 192, 110, 220, 17, 17, 191, 77, 220, 17, 17, 107, - 220, 17, 17, 109, 220, 17, 17, 138, 220, 17, 17, 134, 220, 17, 17, 149, - 220, 17, 17, 169, 220, 17, 17, 175, 220, 17, 17, 171, 220, 17, 17, 178, - 220, 17, 229, 24, 213, 43, 220, 17, 229, 24, 216, 12, 220, 17, 1, 221, - 185, 231, 3, 220, 17, 1, 221, 185, 212, 65, 86, 5, 211, 113, 86, 87, 230, - 181, 192, 25, 216, 118, 197, 178, 65, 86, 87, 230, 181, 192, 25, 216, - 118, 255, 207, 206, 167, 249, 19, 174, 86, 87, 230, 181, 192, 25, 216, - 118, 255, 207, 230, 181, 197, 153, 174, 86, 87, 89, 192, 25, 216, 118, - 216, 234, 174, 86, 87, 242, 215, 192, 25, 216, 118, 203, 172, 174, 86, - 87, 247, 97, 192, 25, 216, 118, 209, 189, 203, 158, 174, 86, 87, 192, 25, - 216, 118, 197, 153, 203, 158, 174, 86, 87, 205, 100, 203, 157, 86, 87, - 248, 13, 192, 25, 216, 117, 86, 87, 248, 141, 203, 50, 192, 25, 216, 117, - 86, 87, 223, 98, 197, 152, 86, 87, 237, 113, 197, 153, 248, 12, 86, 87, - 203, 157, 86, 87, 212, 70, 203, 157, 86, 87, 197, 153, 203, 157, 86, 87, - 212, 70, 197, 153, 203, 157, 86, 87, 206, 191, 243, 111, 201, 193, 203, - 157, 86, 87, 207, 10, 230, 222, 203, 157, 86, 87, 247, 97, 255, 211, 206, - 73, 216, 233, 179, 247, 128, 86, 87, 230, 181, 197, 152, 86, 219, 27, 3, - 246, 255, 206, 72, 86, 219, 27, 3, 219, 157, 206, 72, 86, 250, 188, 3, - 203, 168, 231, 168, 255, 212, 206, 72, 86, 250, 188, 3, 255, 209, 168, - 86, 250, 188, 3, 205, 69, 197, 147, 86, 3, 207, 115, 236, 189, 231, 167, - 86, 3, 207, 115, 236, 189, 231, 5, 86, 3, 207, 115, 236, 189, 230, 182, - 86, 3, 207, 115, 214, 243, 231, 167, 86, 3, 207, 115, 214, 243, 231, 5, - 86, 3, 207, 115, 236, 189, 207, 115, 214, 242, 86, 17, 191, 77, 86, 17, - 107, 86, 17, 109, 86, 17, 138, 86, 17, 134, 86, 17, 149, 86, 17, 169, 86, - 17, 175, 86, 17, 171, 86, 17, 178, 86, 17, 132, 107, 86, 17, 132, 109, - 86, 17, 132, 138, 86, 17, 132, 134, 86, 17, 132, 149, 86, 17, 132, 169, - 86, 17, 132, 175, 86, 17, 132, 171, 86, 17, 132, 178, 86, 17, 132, 191, - 77, 86, 87, 248, 15, 206, 72, 86, 87, 214, 59, 247, 195, 212, 82, 191, - 10, 86, 87, 247, 97, 255, 211, 206, 73, 247, 196, 216, 62, 247, 128, 86, - 87, 214, 59, 247, 195, 203, 169, 206, 72, 86, 87, 243, 128, 216, 117, 86, - 87, 197, 169, 255, 208, 86, 87, 230, 164, 206, 73, 230, 119, 86, 87, 230, - 164, 206, 73, 230, 125, 86, 87, 251, 123, 221, 202, 230, 119, 86, 87, - 251, 123, 221, 202, 230, 125, 86, 3, 192, 102, 197, 151, 86, 3, 217, 66, - 197, 151, 86, 1, 155, 86, 1, 221, 215, 86, 1, 231, 240, 86, 1, 231, 91, - 86, 1, 214, 68, 86, 1, 247, 160, 86, 1, 247, 1, 86, 1, 223, 32, 86, 1, - 212, 101, 86, 1, 197, 132, 86, 1, 197, 120, 86, 1, 237, 191, 86, 1, 237, - 175, 86, 1, 213, 79, 86, 1, 190, 190, 86, 1, 199, 49, 86, 1, 238, 32, 86, - 1, 237, 68, 86, 1, 180, 86, 1, 168, 86, 1, 209, 228, 86, 1, 249, 153, 86, - 1, 248, 203, 86, 1, 174, 86, 1, 197, 168, 86, 1, 197, 157, 86, 1, 235, - 35, 86, 1, 235, 29, 86, 1, 193, 190, 86, 1, 191, 71, 86, 1, 191, 123, 86, - 1, 255, 214, 86, 1, 170, 86, 1, 165, 86, 1, 173, 86, 1, 203, 165, 86, 1, - 201, 175, 86, 1, 188, 86, 1, 140, 86, 1, 65, 86, 1, 220, 246, 86, 1, 232, - 221, 165, 86, 1, 221, 101, 86, 1, 206, 109, 86, 18, 3, 252, 206, 86, 18, - 3, 68, 86, 18, 3, 223, 199, 86, 18, 3, 66, 86, 18, 3, 196, 30, 86, 18, 3, - 117, 146, 86, 18, 3, 117, 206, 110, 86, 18, 3, 117, 172, 86, 18, 3, 117, - 219, 74, 86, 18, 3, 71, 86, 18, 3, 234, 188, 86, 18, 3, 74, 86, 18, 3, - 211, 87, 86, 3, 206, 173, 201, 5, 214, 69, 206, 162, 86, 3, 206, 167, - 249, 18, 86, 18, 3, 207, 18, 68, 86, 18, 3, 207, 18, 223, 199, 86, 3, - 212, 82, 191, 11, 214, 251, 238, 32, 86, 3, 202, 61, 219, 240, 86, 87, - 230, 72, 86, 87, 210, 178, 86, 3, 219, 243, 206, 72, 86, 3, 192, 107, - 206, 72, 86, 3, 219, 244, 197, 169, 247, 128, 86, 3, 216, 236, 247, 128, - 86, 3, 230, 185, 247, 129, 207, 8, 86, 3, 230, 185, 216, 220, 207, 8, 86, - 3, 223, 93, 216, 236, 247, 128, 86, 200, 239, 3, 219, 244, 197, 169, 247, - 128, 86, 200, 239, 3, 216, 236, 247, 128, 86, 200, 239, 3, 223, 93, 216, - 236, 247, 128, 86, 200, 239, 1, 155, 86, 200, 239, 1, 221, 215, 86, 200, - 239, 1, 231, 240, 86, 200, 239, 1, 231, 91, 86, 200, 239, 1, 214, 68, 86, - 200, 239, 1, 247, 160, 86, 200, 239, 1, 247, 1, 86, 200, 239, 1, 223, 32, - 86, 200, 239, 1, 212, 101, 86, 200, 239, 1, 197, 132, 86, 200, 239, 1, - 197, 120, 86, 200, 239, 1, 237, 191, 86, 200, 239, 1, 237, 175, 86, 200, - 239, 1, 213, 79, 86, 200, 239, 1, 190, 190, 86, 200, 239, 1, 199, 49, 86, - 200, 239, 1, 238, 32, 86, 200, 239, 1, 237, 68, 86, 200, 239, 1, 180, 86, - 200, 239, 1, 168, 86, 200, 239, 1, 209, 228, 86, 200, 239, 1, 249, 153, - 86, 200, 239, 1, 248, 203, 86, 200, 239, 1, 174, 86, 200, 239, 1, 197, - 168, 86, 200, 239, 1, 197, 157, 86, 200, 239, 1, 235, 35, 86, 200, 239, - 1, 235, 29, 86, 200, 239, 1, 193, 190, 86, 200, 239, 1, 191, 71, 86, 200, - 239, 1, 191, 123, 86, 200, 239, 1, 255, 214, 86, 200, 239, 1, 170, 86, - 200, 239, 1, 165, 86, 200, 239, 1, 173, 86, 200, 239, 1, 203, 165, 86, - 200, 239, 1, 201, 175, 86, 200, 239, 1, 188, 86, 200, 239, 1, 140, 86, - 200, 239, 1, 65, 86, 200, 239, 1, 220, 246, 86, 200, 239, 1, 232, 221, - 193, 190, 86, 200, 239, 1, 232, 221, 170, 86, 200, 239, 1, 232, 221, 165, - 86, 220, 233, 206, 69, 221, 215, 86, 220, 233, 206, 69, 221, 216, 247, - 196, 216, 62, 247, 128, 86, 247, 112, 3, 88, 249, 7, 86, 247, 112, 3, - 156, 249, 7, 86, 247, 112, 3, 247, 116, 199, 135, 86, 247, 112, 3, 205, - 99, 255, 213, 86, 16, 235, 105, 248, 10, 86, 16, 207, 114, 206, 174, 86, - 16, 210, 206, 231, 166, 86, 16, 207, 114, 206, 175, 207, 10, 230, 221, - 86, 16, 209, 189, 168, 86, 16, 213, 21, 248, 10, 86, 16, 213, 21, 248, - 11, 212, 70, 255, 210, 86, 16, 213, 21, 248, 11, 230, 183, 255, 210, 86, - 16, 213, 21, 248, 11, 247, 196, 255, 210, 86, 3, 207, 115, 214, 243, 207, - 115, 236, 188, 86, 3, 207, 115, 214, 243, 230, 182, 86, 87, 248, 14, 203, - 50, 231, 54, 216, 118, 207, 9, 86, 87, 216, 14, 192, 25, 231, 54, 216, - 118, 207, 9, 86, 87, 212, 70, 197, 152, 86, 87, 89, 248, 44, 206, 164, - 192, 25, 216, 118, 216, 234, 174, 86, 87, 242, 215, 248, 44, 206, 164, - 192, 25, 216, 118, 203, 172, 174, 206, 207, 200, 155, 56, 219, 223, 200, - 155, 56, 206, 207, 200, 155, 3, 4, 236, 138, 219, 223, 200, 155, 3, 4, - 236, 138, 86, 87, 219, 235, 216, 237, 206, 72, 86, 87, 198, 18, 216, 237, - 206, 72, 80, 1, 155, 80, 1, 221, 215, 80, 1, 231, 240, 80, 1, 231, 91, - 80, 1, 214, 68, 80, 1, 247, 160, 80, 1, 247, 1, 80, 1, 223, 32, 80, 1, - 222, 252, 80, 1, 212, 101, 80, 1, 213, 45, 80, 1, 197, 132, 80, 1, 197, - 120, 80, 1, 237, 191, 80, 1, 237, 175, 80, 1, 213, 79, 80, 1, 190, 190, - 80, 1, 199, 49, 80, 1, 238, 32, 80, 1, 237, 68, 80, 1, 180, 80, 1, 168, - 80, 1, 209, 228, 80, 1, 249, 153, 80, 1, 248, 203, 80, 1, 174, 80, 1, - 170, 80, 1, 165, 80, 1, 173, 80, 1, 193, 190, 80, 1, 188, 80, 1, 140, 80, - 1, 219, 73, 80, 1, 65, 80, 1, 203, 139, 65, 80, 1, 68, 80, 1, 223, 199, - 80, 1, 66, 80, 1, 196, 30, 80, 1, 71, 80, 1, 215, 232, 71, 80, 1, 74, 80, - 1, 250, 163, 80, 18, 3, 199, 200, 252, 206, 80, 18, 3, 252, 206, 80, 18, - 3, 68, 80, 18, 3, 223, 199, 80, 18, 3, 66, 80, 18, 3, 196, 30, 80, 18, 3, - 71, 80, 18, 3, 251, 236, 80, 18, 3, 215, 232, 223, 199, 80, 18, 3, 215, - 232, 74, 80, 18, 3, 235, 15, 58, 80, 3, 251, 71, 80, 3, 75, 60, 80, 3, - 195, 35, 80, 3, 195, 40, 80, 3, 250, 214, 80, 120, 3, 216, 217, 170, 80, - 120, 3, 216, 217, 165, 80, 120, 3, 216, 217, 193, 190, 80, 120, 3, 216, - 217, 140, 80, 1, 230, 206, 188, 80, 17, 191, 77, 80, 17, 107, 80, 17, - 109, 80, 17, 138, 80, 17, 134, 80, 17, 149, 80, 17, 169, 80, 17, 175, 80, - 17, 171, 80, 17, 178, 80, 3, 219, 83, 205, 53, 80, 3, 205, 53, 80, 16, - 219, 36, 80, 16, 242, 67, 80, 16, 252, 1, 80, 16, 231, 146, 80, 1, 203, - 165, 80, 1, 201, 175, 80, 1, 117, 146, 80, 1, 117, 206, 110, 80, 1, 117, - 172, 80, 1, 117, 219, 74, 80, 18, 3, 117, 146, 80, 18, 3, 117, 206, 110, - 80, 18, 3, 117, 172, 80, 18, 3, 117, 219, 74, 80, 1, 215, 232, 214, 68, - 80, 1, 215, 232, 222, 252, 80, 1, 215, 232, 249, 53, 80, 1, 215, 232, - 249, 48, 80, 120, 3, 215, 232, 216, 217, 180, 80, 120, 3, 215, 232, 216, - 217, 174, 80, 120, 3, 215, 232, 216, 217, 173, 80, 1, 203, 171, 222, 62, - 203, 165, 80, 18, 3, 203, 171, 222, 62, 233, 242, 80, 163, 87, 203, 171, - 222, 62, 230, 5, 80, 163, 87, 203, 171, 222, 62, 222, 23, 209, 199, 80, - 1, 193, 102, 208, 116, 222, 62, 199, 49, 80, 1, 193, 102, 208, 116, 222, - 62, 208, 122, 80, 18, 3, 193, 102, 208, 116, 222, 62, 233, 242, 80, 18, - 3, 193, 102, 208, 116, 222, 62, 196, 152, 80, 3, 193, 102, 208, 116, 222, - 62, 198, 78, 80, 3, 193, 102, 208, 116, 222, 62, 198, 77, 80, 3, 193, - 102, 208, 116, 222, 62, 198, 76, 80, 3, 193, 102, 208, 116, 222, 62, 198, - 75, 80, 3, 193, 102, 208, 116, 222, 62, 198, 74, 80, 1, 234, 202, 208, - 116, 222, 62, 213, 79, 80, 1, 234, 202, 208, 116, 222, 62, 191, 183, 80, - 1, 234, 202, 208, 116, 222, 62, 231, 56, 80, 18, 3, 231, 161, 222, 62, - 68, 80, 18, 3, 222, 28, 211, 151, 80, 18, 3, 222, 28, 66, 80, 18, 3, 222, - 28, 234, 188, 80, 1, 203, 139, 155, 80, 1, 203, 139, 221, 215, 80, 1, - 203, 139, 231, 240, 80, 1, 203, 139, 247, 160, 80, 1, 203, 139, 191, 123, - 80, 1, 203, 139, 212, 101, 80, 1, 203, 139, 238, 32, 80, 1, 203, 139, - 180, 80, 1, 203, 139, 209, 228, 80, 1, 203, 139, 233, 109, 80, 1, 203, - 139, 249, 153, 80, 1, 203, 139, 199, 49, 80, 1, 203, 139, 140, 80, 120, - 3, 203, 139, 216, 217, 193, 190, 80, 18, 3, 203, 139, 252, 206, 80, 18, - 3, 203, 139, 71, 80, 18, 3, 203, 139, 235, 15, 58, 80, 18, 3, 203, 139, - 53, 192, 159, 80, 3, 203, 139, 198, 77, 80, 3, 203, 139, 198, 76, 80, 3, - 203, 139, 198, 74, 80, 3, 203, 139, 198, 73, 80, 3, 203, 139, 238, 247, - 198, 77, 80, 3, 203, 139, 238, 247, 198, 76, 80, 3, 203, 139, 238, 247, - 234, 106, 198, 79, 80, 1, 206, 47, 210, 189, 233, 109, 80, 3, 206, 47, - 210, 189, 198, 74, 80, 203, 139, 17, 191, 77, 80, 203, 139, 17, 107, 80, - 203, 139, 17, 109, 80, 203, 139, 17, 138, 80, 203, 139, 17, 134, 80, 203, - 139, 17, 149, 80, 203, 139, 17, 169, 80, 203, 139, 17, 175, 80, 203, 139, - 17, 171, 80, 203, 139, 17, 178, 80, 3, 221, 206, 198, 78, 80, 3, 221, - 206, 198, 76, 80, 18, 3, 251, 222, 65, 80, 18, 3, 251, 222, 251, 236, 80, - 16, 203, 139, 107, 80, 16, 203, 139, 233, 215, 101, 6, 1, 251, 132, 101, - 6, 1, 249, 101, 101, 6, 1, 231, 210, 101, 6, 1, 236, 150, 101, 6, 1, 234, - 103, 101, 6, 1, 195, 49, 101, 6, 1, 191, 80, 101, 6, 1, 199, 193, 101, 6, - 1, 223, 162, 101, 6, 1, 222, 87, 101, 6, 1, 220, 7, 101, 6, 1, 217, 90, - 101, 6, 1, 214, 216, 101, 6, 1, 211, 104, 101, 6, 1, 210, 131, 101, 6, 1, - 191, 67, 101, 6, 1, 207, 163, 101, 6, 1, 205, 142, 101, 6, 1, 199, 179, - 101, 6, 1, 196, 113, 101, 6, 1, 209, 220, 101, 6, 1, 221, 200, 101, 6, 1, - 231, 82, 101, 6, 1, 208, 81, 101, 6, 1, 203, 69, 101, 6, 1, 243, 81, 101, - 6, 1, 247, 128, 101, 6, 1, 222, 234, 101, 6, 1, 243, 18, 101, 6, 1, 246, - 241, 101, 6, 1, 192, 218, 101, 6, 1, 222, 249, 101, 6, 1, 230, 87, 101, - 6, 1, 229, 245, 101, 6, 1, 229, 145, 101, 6, 1, 193, 125, 101, 6, 1, 230, - 19, 101, 6, 1, 229, 11, 101, 6, 1, 192, 14, 101, 6, 1, 252, 14, 101, 1, - 251, 132, 101, 1, 249, 101, 101, 1, 231, 210, 101, 1, 236, 150, 101, 1, - 234, 103, 101, 1, 195, 49, 101, 1, 191, 80, 101, 1, 199, 193, 101, 1, - 223, 162, 101, 1, 222, 87, 101, 1, 220, 7, 101, 1, 217, 90, 101, 1, 214, - 216, 101, 1, 211, 104, 101, 1, 210, 131, 101, 1, 191, 67, 101, 1, 207, - 163, 101, 1, 205, 142, 101, 1, 199, 179, 101, 1, 196, 113, 101, 1, 209, - 220, 101, 1, 221, 200, 101, 1, 231, 82, 101, 1, 208, 81, 101, 1, 203, 69, - 101, 1, 243, 81, 101, 1, 247, 128, 101, 1, 222, 234, 101, 1, 243, 18, - 101, 1, 246, 241, 101, 1, 192, 218, 101, 1, 222, 249, 101, 1, 230, 87, - 101, 1, 229, 245, 101, 1, 229, 145, 101, 1, 193, 125, 101, 1, 230, 19, - 101, 1, 229, 11, 101, 1, 233, 23, 101, 1, 192, 14, 101, 1, 234, 123, 101, - 1, 153, 231, 210, 101, 1, 251, 230, 101, 210, 128, 204, 10, 52, 1, 101, - 214, 216, 101, 1, 252, 14, 101, 1, 230, 17, 56, 101, 1, 220, 116, 56, 30, - 147, 221, 113, 30, 147, 201, 167, 30, 147, 213, 204, 30, 147, 198, 168, - 30, 147, 201, 156, 30, 147, 206, 239, 30, 147, 216, 77, 30, 147, 209, - 169, 30, 147, 201, 164, 30, 147, 202, 160, 30, 147, 201, 161, 30, 147, - 223, 222, 30, 147, 243, 24, 30, 147, 201, 171, 30, 147, 243, 91, 30, 147, - 221, 188, 30, 147, 199, 7, 30, 147, 209, 209, 30, 147, 229, 142, 30, 147, - 213, 200, 30, 147, 201, 165, 30, 147, 213, 194, 30, 147, 213, 198, 30, - 147, 198, 165, 30, 147, 206, 227, 30, 147, 201, 163, 30, 147, 206, 237, - 30, 147, 222, 68, 30, 147, 216, 70, 30, 147, 222, 71, 30, 147, 209, 164, - 30, 147, 209, 162, 30, 147, 209, 150, 30, 147, 209, 158, 30, 147, 209, - 156, 30, 147, 209, 153, 30, 147, 209, 155, 30, 147, 209, 152, 30, 147, - 209, 157, 30, 147, 209, 167, 30, 147, 209, 168, 30, 147, 209, 151, 30, - 147, 209, 161, 30, 147, 222, 69, 30, 147, 222, 67, 30, 147, 202, 153, 30, - 147, 202, 151, 30, 147, 202, 143, 30, 147, 202, 146, 30, 147, 202, 152, - 30, 147, 202, 148, 30, 147, 202, 147, 30, 147, 202, 145, 30, 147, 202, - 156, 30, 147, 202, 158, 30, 147, 202, 159, 30, 147, 202, 154, 30, 147, - 202, 144, 30, 147, 202, 149, 30, 147, 202, 157, 30, 147, 243, 72, 30, - 147, 243, 70, 30, 147, 247, 14, 30, 147, 247, 12, 30, 147, 210, 149, 30, - 147, 223, 217, 30, 147, 223, 208, 30, 147, 223, 216, 30, 147, 223, 213, - 30, 147, 223, 211, 30, 147, 223, 215, 30, 147, 201, 168, 30, 147, 223, - 220, 30, 147, 223, 221, 30, 147, 223, 209, 30, 147, 223, 214, 30, 147, - 192, 57, 30, 147, 243, 23, 30, 147, 243, 73, 30, 147, 243, 71, 30, 147, - 247, 15, 30, 147, 247, 13, 30, 147, 243, 89, 30, 147, 243, 90, 30, 147, - 243, 74, 30, 147, 247, 16, 30, 147, 209, 207, 30, 147, 222, 70, 30, 147, - 201, 169, 30, 147, 192, 63, 30, 147, 221, 104, 30, 147, 213, 196, 30, - 147, 213, 202, 30, 147, 213, 201, 30, 147, 198, 162, 30, 147, 233, 3, 30, - 222, 174, 233, 3, 30, 222, 174, 65, 30, 222, 174, 252, 25, 30, 222, 174, - 170, 30, 222, 174, 192, 129, 30, 222, 174, 234, 65, 30, 222, 174, 71, 30, - 222, 174, 192, 67, 30, 222, 174, 192, 80, 30, 222, 174, 74, 30, 222, 174, - 193, 190, 30, 222, 174, 193, 176, 30, 222, 174, 211, 151, 30, 222, 174, - 192, 12, 30, 222, 174, 66, 30, 222, 174, 193, 107, 30, 222, 174, 193, - 125, 30, 222, 174, 193, 86, 30, 222, 174, 191, 225, 30, 222, 174, 233, - 242, 30, 222, 174, 192, 33, 30, 222, 174, 68, 30, 222, 174, 255, 202, 30, - 222, 174, 255, 201, 30, 222, 174, 192, 143, 30, 222, 174, 192, 141, 30, - 222, 174, 234, 63, 30, 222, 174, 234, 62, 30, 222, 174, 234, 64, 30, 222, - 174, 192, 66, 30, 222, 174, 192, 65, 30, 222, 174, 212, 10, 30, 222, 174, - 212, 11, 30, 222, 174, 212, 4, 30, 222, 174, 212, 9, 30, 222, 174, 212, - 7, 30, 222, 174, 192, 0, 30, 222, 174, 191, 255, 30, 222, 174, 191, 254, - 30, 222, 174, 192, 1, 30, 222, 174, 192, 2, 30, 222, 174, 196, 226, 30, - 222, 174, 196, 225, 30, 222, 174, 196, 223, 30, 222, 174, 196, 219, 30, - 222, 174, 196, 220, 30, 222, 174, 191, 220, 30, 222, 174, 191, 217, 30, - 222, 174, 191, 218, 30, 222, 174, 191, 212, 30, 222, 174, 191, 213, 30, - 222, 174, 191, 214, 30, 222, 174, 191, 216, 30, 222, 174, 233, 236, 30, - 222, 174, 233, 238, 30, 222, 174, 192, 32, 30, 222, 174, 228, 69, 30, - 222, 174, 228, 61, 30, 222, 174, 228, 64, 30, 222, 174, 228, 62, 30, 222, - 174, 228, 66, 30, 222, 174, 228, 68, 30, 222, 174, 251, 25, 30, 222, 174, - 251, 22, 30, 222, 174, 251, 20, 30, 222, 174, 251, 21, 30, 222, 174, 201, - 172, 30, 222, 174, 255, 203, 30, 222, 174, 192, 142, 30, 222, 174, 192, - 64, 30, 222, 174, 212, 6, 30, 222, 174, 212, 5, 30, 125, 221, 113, 30, - 125, 201, 167, 30, 125, 221, 106, 30, 125, 213, 204, 30, 125, 213, 202, - 30, 125, 213, 201, 30, 125, 198, 168, 30, 125, 206, 239, 30, 125, 206, - 234, 30, 125, 206, 231, 30, 125, 206, 224, 30, 125, 206, 219, 30, 125, - 206, 214, 30, 125, 206, 225, 30, 125, 206, 237, 30, 125, 216, 77, 30, - 125, 209, 169, 30, 125, 209, 158, 30, 125, 202, 160, 30, 125, 201, 161, - 30, 125, 223, 222, 30, 125, 243, 24, 30, 125, 243, 91, 30, 125, 221, 188, - 30, 125, 199, 7, 30, 125, 209, 209, 30, 125, 229, 142, 30, 125, 221, 107, - 30, 125, 221, 105, 30, 125, 213, 200, 30, 125, 213, 194, 30, 125, 213, - 196, 30, 125, 213, 199, 30, 125, 213, 195, 30, 125, 198, 165, 30, 125, - 198, 162, 30, 125, 206, 232, 30, 125, 206, 227, 30, 125, 206, 213, 30, - 125, 206, 212, 30, 125, 201, 163, 30, 125, 206, 229, 30, 125, 206, 228, - 30, 125, 206, 221, 30, 125, 206, 223, 30, 125, 206, 236, 30, 125, 206, - 216, 30, 125, 206, 226, 30, 125, 206, 235, 30, 125, 206, 211, 30, 125, - 216, 73, 30, 125, 216, 68, 30, 125, 216, 70, 30, 125, 216, 67, 30, 125, - 216, 65, 30, 125, 216, 71, 30, 125, 216, 76, 30, 125, 216, 74, 30, 125, - 222, 71, 30, 125, 209, 160, 30, 125, 209, 161, 30, 125, 209, 166, 30, - 125, 222, 69, 30, 125, 202, 153, 30, 125, 202, 143, 30, 125, 202, 146, - 30, 125, 202, 148, 30, 125, 210, 149, 30, 125, 223, 217, 30, 125, 223, - 210, 30, 125, 201, 168, 30, 125, 223, 218, 30, 125, 192, 57, 30, 125, - 192, 51, 30, 125, 192, 52, 30, 125, 209, 207, 30, 125, 222, 70, 30, 125, - 229, 140, 30, 125, 229, 138, 30, 125, 229, 141, 30, 125, 229, 139, 30, - 125, 192, 63, 30, 125, 221, 109, 30, 125, 221, 108, 30, 125, 221, 112, - 30, 125, 221, 110, 30, 125, 221, 111, 30, 125, 201, 165, 36, 5, 140, 36, - 5, 228, 159, 36, 5, 229, 158, 36, 5, 230, 91, 36, 5, 229, 215, 36, 5, - 229, 245, 36, 5, 229, 23, 36, 5, 229, 14, 36, 5, 173, 36, 5, 218, 225, - 36, 5, 219, 146, 36, 5, 220, 125, 36, 5, 219, 228, 36, 5, 219, 238, 36, - 5, 219, 43, 36, 5, 218, 191, 36, 5, 229, 177, 36, 5, 229, 171, 36, 5, - 229, 173, 36, 5, 229, 176, 36, 5, 229, 174, 36, 5, 229, 175, 36, 5, 229, - 172, 36, 5, 229, 170, 36, 5, 174, 36, 5, 215, 155, 36, 5, 216, 100, 36, - 5, 217, 151, 36, 5, 216, 211, 36, 5, 216, 232, 36, 5, 216, 12, 36, 5, - 215, 80, 36, 5, 200, 54, 36, 5, 200, 48, 36, 5, 200, 50, 36, 5, 200, 53, - 36, 5, 200, 51, 36, 5, 200, 52, 36, 5, 200, 49, 36, 5, 200, 47, 36, 5, - 165, 36, 5, 206, 68, 36, 5, 207, 1, 36, 5, 207, 178, 36, 5, 207, 84, 36, - 5, 207, 113, 36, 5, 206, 162, 36, 5, 206, 26, 36, 5, 188, 36, 5, 201, 4, - 36, 5, 202, 222, 36, 5, 205, 197, 36, 5, 205, 50, 36, 5, 205, 68, 36, 5, - 202, 46, 36, 5, 200, 150, 36, 5, 203, 165, 36, 5, 203, 5, 36, 5, 203, 81, - 36, 5, 203, 160, 36, 5, 203, 111, 36, 5, 203, 113, 36, 5, 203, 56, 36, 5, - 202, 240, 36, 5, 208, 96, 36, 5, 208, 33, 36, 5, 208, 57, 36, 5, 208, 95, - 36, 5, 208, 74, 36, 5, 208, 75, 36, 5, 208, 45, 36, 5, 208, 44, 36, 5, - 207, 240, 36, 5, 207, 236, 36, 5, 207, 239, 36, 5, 207, 237, 36, 5, 207, - 238, 36, 5, 208, 71, 36, 5, 208, 63, 36, 5, 208, 66, 36, 5, 208, 70, 36, - 5, 208, 67, 36, 5, 208, 68, 36, 5, 208, 65, 36, 5, 208, 62, 36, 5, 208, - 58, 36, 5, 208, 61, 36, 5, 208, 59, 36, 5, 208, 60, 36, 5, 249, 153, 36, - 5, 248, 10, 36, 5, 248, 188, 36, 5, 249, 151, 36, 5, 249, 1, 36, 5, 249, - 17, 36, 5, 248, 111, 36, 5, 247, 210, 36, 5, 195, 188, 36, 5, 193, 249, - 36, 5, 195, 69, 36, 5, 195, 187, 36, 5, 195, 148, 36, 5, 195, 153, 36, 5, - 195, 24, 36, 5, 193, 238, 36, 5, 190, 190, 36, 5, 197, 94, 36, 5, 198, - 193, 36, 5, 199, 245, 36, 5, 199, 121, 36, 5, 199, 145, 36, 5, 159, 36, - 5, 197, 43, 36, 5, 247, 160, 36, 5, 238, 195, 36, 5, 243, 29, 36, 5, 247, - 159, 36, 5, 247, 34, 36, 5, 247, 42, 36, 5, 242, 99, 36, 5, 238, 151, 36, - 5, 192, 220, 36, 5, 192, 188, 36, 5, 192, 207, 36, 5, 192, 219, 36, 5, - 192, 213, 36, 5, 192, 214, 36, 5, 192, 196, 36, 5, 192, 195, 36, 5, 192, - 181, 36, 5, 192, 177, 36, 5, 192, 180, 36, 5, 192, 178, 36, 5, 192, 179, - 36, 5, 180, 36, 5, 212, 178, 36, 5, 213, 219, 36, 5, 214, 250, 36, 5, - 214, 110, 36, 5, 214, 121, 36, 5, 213, 43, 36, 5, 212, 110, 36, 5, 212, - 101, 36, 5, 212, 58, 36, 5, 212, 81, 36, 5, 212, 100, 36, 5, 212, 89, 36, - 5, 212, 90, 36, 5, 212, 65, 36, 5, 212, 48, 36, 5, 231, 11, 65, 36, 5, - 231, 11, 66, 36, 5, 231, 11, 68, 36, 5, 231, 11, 252, 206, 36, 5, 231, - 11, 234, 188, 36, 5, 231, 11, 71, 36, 5, 231, 11, 74, 36, 5, 231, 11, - 193, 190, 36, 5, 155, 36, 5, 220, 232, 36, 5, 221, 166, 36, 5, 222, 127, - 36, 5, 222, 13, 36, 5, 222, 22, 36, 5, 221, 67, 36, 5, 221, 62, 36, 5, - 220, 179, 36, 5, 220, 172, 36, 5, 220, 178, 36, 5, 220, 173, 36, 5, 220, - 174, 36, 5, 220, 165, 36, 5, 220, 159, 36, 5, 220, 161, 36, 5, 220, 164, - 36, 5, 220, 162, 36, 5, 220, 163, 36, 5, 220, 160, 36, 5, 220, 158, 36, - 5, 220, 154, 36, 5, 220, 157, 36, 5, 220, 155, 36, 5, 220, 156, 36, 5, - 193, 190, 36, 5, 193, 0, 36, 5, 193, 86, 36, 5, 193, 181, 36, 5, 193, - 114, 36, 5, 193, 125, 36, 5, 193, 48, 36, 5, 193, 40, 36, 5, 209, 219, - 65, 36, 5, 209, 219, 66, 36, 5, 209, 219, 68, 36, 5, 209, 219, 252, 206, - 36, 5, 209, 219, 234, 188, 36, 5, 209, 219, 71, 36, 5, 209, 219, 74, 36, - 5, 191, 123, 36, 5, 190, 251, 36, 5, 191, 30, 36, 5, 191, 121, 36, 5, - 191, 84, 36, 5, 191, 87, 36, 5, 191, 7, 36, 5, 190, 238, 36, 5, 191, 71, - 36, 5, 191, 48, 36, 5, 191, 57, 36, 5, 191, 70, 36, 5, 191, 61, 36, 5, - 191, 62, 36, 5, 191, 54, 36, 5, 191, 39, 36, 5, 170, 36, 5, 191, 225, 36, - 5, 192, 33, 36, 5, 192, 140, 36, 5, 192, 77, 36, 5, 192, 80, 36, 5, 192, - 12, 36, 5, 191, 252, 36, 5, 238, 32, 36, 5, 235, 89, 36, 5, 237, 44, 36, - 5, 238, 31, 36, 5, 237, 131, 36, 5, 237, 146, 36, 5, 236, 174, 36, 5, - 235, 46, 36, 5, 237, 191, 36, 5, 237, 156, 36, 5, 237, 168, 36, 5, 237, - 190, 36, 5, 237, 178, 36, 5, 237, 179, 36, 5, 237, 161, 36, 5, 237, 147, - 36, 5, 223, 32, 36, 5, 222, 182, 36, 5, 222, 244, 36, 5, 223, 31, 36, 5, - 223, 8, 36, 5, 223, 10, 36, 5, 222, 201, 36, 5, 222, 160, 36, 5, 231, - 240, 36, 5, 230, 179, 36, 5, 231, 53, 36, 5, 231, 237, 36, 5, 231, 157, - 36, 5, 231, 165, 36, 5, 231, 3, 36, 5, 231, 2, 36, 5, 230, 135, 36, 5, - 230, 131, 36, 5, 230, 134, 36, 5, 230, 132, 36, 5, 230, 133, 36, 5, 231, - 127, 36, 5, 231, 107, 36, 5, 231, 117, 36, 5, 231, 126, 36, 5, 231, 121, - 36, 5, 231, 122, 36, 5, 231, 111, 36, 5, 231, 96, 36, 5, 199, 49, 36, 5, - 198, 213, 36, 5, 199, 11, 36, 5, 199, 48, 36, 5, 199, 31, 36, 5, 199, 33, - 36, 5, 198, 241, 36, 5, 198, 204, 36, 5, 247, 1, 36, 5, 243, 48, 36, 5, - 243, 95, 36, 5, 247, 0, 36, 5, 243, 123, 36, 5, 243, 127, 36, 5, 243, 68, - 36, 5, 243, 37, 36, 5, 209, 228, 36, 5, 209, 191, 36, 5, 209, 211, 36, 5, - 209, 227, 36, 5, 209, 213, 36, 5, 209, 214, 36, 5, 209, 199, 36, 5, 209, - 187, 36, 5, 197, 168, 36, 5, 197, 140, 36, 5, 197, 146, 36, 5, 197, 167, - 36, 5, 197, 160, 36, 5, 197, 161, 36, 5, 197, 144, 36, 5, 197, 138, 36, - 5, 196, 240, 36, 5, 196, 232, 36, 5, 196, 236, 36, 5, 196, 239, 36, 5, - 196, 237, 36, 5, 196, 238, 36, 5, 196, 234, 36, 5, 196, 233, 36, 5, 233, - 109, 36, 5, 232, 86, 36, 5, 233, 23, 36, 5, 233, 108, 36, 5, 233, 52, 36, - 5, 233, 59, 36, 5, 232, 175, 36, 5, 232, 62, 36, 5, 168, 36, 5, 208, 165, - 36, 5, 209, 185, 36, 5, 210, 220, 36, 5, 210, 49, 36, 5, 210, 63, 36, 5, - 209, 73, 36, 5, 208, 122, 36, 5, 206, 16, 36, 5, 215, 68, 36, 5, 232, 56, - 36, 33, 231, 153, 23, 18, 219, 198, 77, 36, 33, 18, 219, 198, 77, 36, 33, - 231, 153, 77, 36, 205, 54, 77, 36, 193, 22, 36, 232, 80, 201, 63, 36, - 242, 74, 36, 204, 25, 36, 242, 83, 36, 208, 228, 242, 83, 36, 208, 13, - 77, 36, 210, 128, 204, 10, 36, 17, 107, 36, 17, 109, 36, 17, 138, 36, 17, - 134, 36, 17, 149, 36, 17, 169, 36, 17, 175, 36, 17, 171, 36, 17, 178, 36, - 31, 199, 95, 36, 31, 197, 32, 36, 31, 198, 249, 36, 31, 232, 135, 36, 31, - 233, 15, 36, 31, 202, 120, 36, 31, 203, 241, 36, 31, 234, 153, 36, 31, - 213, 169, 36, 31, 228, 140, 36, 31, 199, 96, 189, 36, 5, 205, 59, 215, - 80, 36, 5, 215, 76, 36, 5, 215, 77, 36, 5, 215, 78, 36, 5, 205, 59, 247, - 210, 36, 5, 247, 207, 36, 5, 247, 208, 36, 5, 247, 209, 36, 5, 205, 59, - 232, 62, 36, 5, 232, 58, 36, 5, 232, 59, 36, 5, 232, 60, 36, 5, 205, 59, - 208, 122, 36, 5, 208, 118, 36, 5, 208, 119, 36, 5, 208, 120, 36, 198, 80, - 87, 192, 15, 36, 198, 80, 87, 237, 89, 36, 198, 80, 87, 206, 194, 36, - 198, 80, 87, 203, 40, 206, 194, 36, 198, 80, 87, 237, 18, 36, 198, 80, - 87, 221, 250, 36, 198, 80, 87, 243, 76, 36, 198, 80, 87, 229, 147, 36, - 198, 80, 87, 237, 88, 36, 198, 80, 87, 220, 195, 103, 1, 65, 103, 1, 71, - 103, 1, 68, 103, 1, 74, 103, 1, 66, 103, 1, 196, 12, 103, 1, 231, 240, - 103, 1, 155, 103, 1, 231, 165, 103, 1, 231, 53, 103, 1, 231, 3, 103, 1, - 230, 179, 103, 1, 230, 138, 103, 1, 140, 103, 1, 229, 245, 103, 1, 229, - 158, 103, 1, 229, 23, 103, 1, 228, 159, 103, 1, 228, 126, 103, 1, 173, - 103, 1, 219, 238, 103, 1, 219, 146, 103, 1, 219, 43, 103, 1, 218, 225, - 103, 1, 218, 192, 103, 1, 174, 103, 1, 216, 232, 103, 1, 216, 100, 103, - 1, 216, 12, 103, 1, 215, 155, 103, 1, 180, 103, 1, 229, 47, 103, 1, 214, - 237, 103, 1, 214, 121, 103, 1, 213, 219, 103, 1, 213, 43, 103, 1, 212, - 178, 103, 1, 212, 112, 103, 1, 208, 32, 103, 1, 208, 16, 103, 1, 208, 9, - 103, 1, 207, 255, 103, 1, 207, 244, 103, 1, 207, 242, 103, 1, 188, 103, - 1, 206, 8, 103, 1, 205, 68, 103, 1, 202, 222, 103, 1, 202, 46, 103, 1, - 201, 4, 103, 1, 200, 158, 103, 1, 238, 32, 103, 1, 190, 190, 103, 1, 237, - 146, 103, 1, 199, 145, 103, 1, 237, 44, 103, 1, 198, 193, 103, 1, 236, - 174, 103, 1, 235, 89, 103, 1, 235, 57, 103, 1, 236, 186, 103, 1, 198, - 115, 103, 1, 198, 114, 103, 1, 198, 103, 103, 1, 198, 102, 103, 1, 198, - 101, 103, 1, 198, 100, 103, 1, 197, 168, 103, 1, 197, 161, 103, 1, 197, - 146, 103, 1, 197, 144, 103, 1, 197, 140, 103, 1, 197, 139, 103, 1, 193, - 190, 103, 1, 193, 125, 103, 1, 193, 86, 103, 1, 193, 48, 103, 1, 193, 0, - 103, 1, 192, 243, 103, 1, 170, 103, 1, 192, 80, 103, 1, 192, 33, 103, 1, - 192, 12, 103, 1, 191, 225, 103, 1, 191, 184, 103, 1, 215, 87, 103, 2, 1, - 192, 80, 103, 2, 1, 192, 33, 103, 2, 1, 192, 12, 103, 2, 1, 191, 225, - 103, 2, 1, 191, 184, 103, 2, 1, 215, 87, 21, 22, 228, 88, 21, 22, 71, 21, - 22, 252, 170, 21, 22, 68, 21, 22, 223, 199, 21, 22, 74, 21, 22, 211, 87, - 21, 22, 192, 158, 211, 87, 21, 22, 98, 234, 188, 21, 22, 98, 68, 21, 22, - 65, 21, 22, 252, 206, 21, 22, 193, 125, 21, 22, 193, 103, 193, 125, 21, - 22, 193, 86, 21, 22, 193, 103, 193, 86, 21, 22, 193, 70, 21, 22, 193, - 103, 193, 70, 21, 22, 193, 48, 21, 22, 193, 103, 193, 48, 21, 22, 193, - 29, 21, 22, 193, 103, 193, 29, 21, 22, 214, 209, 193, 29, 21, 22, 193, - 190, 21, 22, 193, 103, 193, 190, 21, 22, 193, 181, 21, 22, 193, 103, 193, - 181, 21, 22, 214, 209, 193, 181, 21, 22, 251, 236, 21, 22, 192, 158, 193, - 224, 21, 22, 231, 11, 201, 63, 21, 22, 53, 252, 46, 21, 22, 53, 230, 210, - 21, 22, 53, 248, 77, 132, 206, 188, 21, 22, 53, 198, 54, 132, 206, 188, - 21, 22, 53, 50, 132, 206, 188, 21, 22, 53, 206, 188, 21, 22, 53, 55, 252, - 46, 21, 22, 53, 55, 203, 40, 81, 201, 15, 21, 22, 53, 82, 236, 140, 21, - 22, 53, 203, 40, 228, 241, 106, 21, 22, 53, 209, 81, 21, 22, 53, 144, - 199, 228, 21, 22, 234, 103, 21, 22, 223, 162, 21, 22, 211, 104, 21, 22, - 251, 132, 21, 22, 210, 63, 21, 22, 210, 218, 21, 22, 209, 185, 21, 22, - 209, 145, 21, 22, 209, 73, 21, 22, 209, 37, 21, 22, 192, 158, 209, 37, - 21, 22, 98, 229, 215, 21, 22, 98, 229, 158, 21, 22, 168, 21, 22, 210, - 220, 21, 22, 208, 120, 21, 22, 193, 103, 208, 120, 21, 22, 208, 118, 21, - 22, 193, 103, 208, 118, 21, 22, 208, 117, 21, 22, 193, 103, 208, 117, 21, - 22, 208, 115, 21, 22, 193, 103, 208, 115, 21, 22, 208, 114, 21, 22, 193, - 103, 208, 114, 21, 22, 208, 122, 21, 22, 193, 103, 208, 122, 21, 22, 208, - 121, 21, 22, 193, 103, 208, 121, 21, 22, 192, 158, 208, 121, 21, 22, 210, - 236, 21, 22, 193, 103, 210, 236, 21, 22, 98, 230, 116, 21, 22, 199, 145, - 21, 22, 199, 242, 21, 22, 198, 193, 21, 22, 198, 170, 21, 22, 159, 21, - 22, 198, 59, 21, 22, 192, 158, 198, 59, 21, 22, 98, 237, 131, 21, 22, 98, - 237, 44, 21, 22, 190, 190, 21, 22, 199, 245, 21, 22, 197, 41, 21, 22, - 193, 103, 197, 41, 21, 22, 197, 19, 21, 22, 193, 103, 197, 19, 21, 22, - 197, 18, 21, 22, 193, 103, 197, 18, 21, 22, 109, 21, 22, 193, 103, 109, - 21, 22, 197, 9, 21, 22, 193, 103, 197, 9, 21, 22, 197, 43, 21, 22, 193, - 103, 197, 43, 21, 22, 197, 42, 21, 22, 193, 103, 197, 42, 21, 22, 214, - 209, 197, 42, 21, 22, 200, 43, 21, 22, 197, 127, 21, 22, 197, 111, 21, - 22, 197, 109, 21, 22, 197, 132, 21, 22, 222, 22, 21, 22, 222, 121, 21, - 22, 221, 166, 21, 22, 221, 145, 21, 22, 221, 67, 21, 22, 221, 41, 21, 22, - 192, 158, 221, 41, 21, 22, 155, 21, 22, 222, 127, 21, 22, 220, 174, 21, - 22, 193, 103, 220, 174, 21, 22, 220, 172, 21, 22, 193, 103, 220, 172, 21, - 22, 220, 171, 21, 22, 193, 103, 220, 171, 21, 22, 220, 169, 21, 22, 193, - 103, 220, 169, 21, 22, 220, 168, 21, 22, 193, 103, 220, 168, 21, 22, 220, - 179, 21, 22, 193, 103, 220, 179, 21, 22, 220, 178, 21, 22, 193, 103, 220, - 178, 21, 22, 214, 209, 220, 178, 21, 22, 222, 152, 21, 22, 220, 180, 21, - 22, 202, 1, 222, 6, 21, 22, 202, 1, 221, 146, 21, 22, 202, 1, 221, 56, - 21, 22, 202, 1, 222, 104, 21, 22, 247, 42, 21, 22, 247, 158, 21, 22, 243, - 29, 21, 22, 243, 19, 21, 22, 242, 99, 21, 22, 239, 18, 21, 22, 192, 158, - 239, 18, 21, 22, 247, 160, 21, 22, 247, 159, 21, 22, 238, 149, 21, 22, - 193, 103, 238, 149, 21, 22, 238, 147, 21, 22, 193, 103, 238, 147, 21, 22, - 238, 146, 21, 22, 193, 103, 238, 146, 21, 22, 238, 145, 21, 22, 193, 103, - 238, 145, 21, 22, 238, 144, 21, 22, 193, 103, 238, 144, 21, 22, 238, 151, - 21, 22, 193, 103, 238, 151, 21, 22, 238, 150, 21, 22, 193, 103, 238, 150, - 21, 22, 214, 209, 238, 150, 21, 22, 247, 193, 21, 22, 205, 101, 199, 51, - 21, 22, 216, 232, 21, 22, 217, 150, 21, 22, 216, 100, 21, 22, 216, 61, - 21, 22, 216, 12, 21, 22, 215, 211, 21, 22, 192, 158, 215, 211, 21, 22, - 174, 21, 22, 217, 151, 21, 22, 215, 78, 21, 22, 193, 103, 215, 78, 21, - 22, 215, 76, 21, 22, 193, 103, 215, 76, 21, 22, 215, 75, 21, 22, 193, - 103, 215, 75, 21, 22, 215, 74, 21, 22, 193, 103, 215, 74, 21, 22, 215, - 73, 21, 22, 193, 103, 215, 73, 21, 22, 215, 80, 21, 22, 193, 103, 215, - 80, 21, 22, 215, 79, 21, 22, 193, 103, 215, 79, 21, 22, 214, 209, 215, - 79, 21, 22, 218, 168, 21, 22, 193, 103, 218, 168, 21, 22, 216, 104, 21, - 22, 250, 180, 218, 168, 21, 22, 205, 101, 218, 168, 21, 22, 214, 121, 21, - 22, 214, 249, 21, 22, 213, 219, 21, 22, 213, 186, 21, 22, 213, 43, 21, - 22, 213, 26, 21, 22, 192, 158, 213, 26, 21, 22, 180, 21, 22, 214, 250, - 21, 22, 212, 108, 21, 22, 193, 103, 212, 108, 21, 22, 212, 110, 21, 22, - 193, 103, 212, 110, 21, 22, 212, 109, 21, 22, 193, 103, 212, 109, 21, 22, - 214, 209, 212, 109, 21, 22, 215, 61, 21, 22, 98, 214, 70, 21, 22, 213, - 225, 21, 22, 219, 238, 21, 22, 220, 124, 21, 22, 219, 146, 21, 22, 219, - 128, 21, 22, 219, 43, 21, 22, 219, 8, 21, 22, 192, 158, 219, 8, 21, 22, - 173, 21, 22, 220, 125, 21, 22, 218, 189, 21, 22, 193, 103, 218, 189, 21, - 22, 218, 188, 21, 22, 193, 103, 218, 188, 21, 22, 218, 187, 21, 22, 193, - 103, 218, 187, 21, 22, 218, 186, 21, 22, 193, 103, 218, 186, 21, 22, 218, - 185, 21, 22, 193, 103, 218, 185, 21, 22, 218, 191, 21, 22, 193, 103, 218, - 191, 21, 22, 218, 190, 21, 22, 193, 103, 218, 190, 21, 22, 172, 21, 22, - 193, 103, 172, 21, 22, 216, 217, 172, 21, 22, 205, 68, 21, 22, 205, 195, - 21, 22, 202, 222, 21, 22, 202, 193, 21, 22, 202, 46, 21, 22, 202, 16, 21, - 22, 192, 158, 202, 16, 21, 22, 188, 21, 22, 205, 197, 21, 22, 200, 145, - 21, 22, 193, 103, 200, 145, 21, 22, 200, 139, 21, 22, 193, 103, 200, 139, - 21, 22, 200, 138, 21, 22, 193, 103, 200, 138, 21, 22, 200, 133, 21, 22, - 193, 103, 200, 133, 21, 22, 200, 132, 21, 22, 193, 103, 200, 132, 21, 22, - 200, 150, 21, 22, 193, 103, 200, 150, 21, 22, 200, 149, 21, 22, 193, 103, - 200, 149, 21, 22, 214, 209, 200, 149, 21, 22, 206, 8, 21, 22, 250, 180, - 206, 8, 21, 22, 200, 151, 21, 22, 248, 136, 206, 8, 21, 22, 215, 203, - 202, 114, 21, 22, 214, 209, 202, 101, 21, 22, 214, 209, 206, 6, 21, 22, - 214, 209, 201, 192, 21, 22, 214, 209, 201, 7, 21, 22, 214, 209, 202, 100, - 21, 22, 214, 209, 205, 71, 21, 22, 203, 113, 21, 22, 203, 81, 21, 22, - 203, 76, 21, 22, 203, 56, 21, 22, 203, 48, 21, 22, 203, 165, 21, 22, 203, - 160, 21, 22, 202, 237, 21, 22, 193, 103, 202, 237, 21, 22, 202, 236, 21, - 22, 193, 103, 202, 236, 21, 22, 202, 235, 21, 22, 193, 103, 202, 235, 21, - 22, 202, 234, 21, 22, 193, 103, 202, 234, 21, 22, 202, 233, 21, 22, 193, - 103, 202, 233, 21, 22, 202, 240, 21, 22, 193, 103, 202, 240, 21, 22, 202, - 239, 21, 22, 193, 103, 202, 239, 21, 22, 203, 167, 21, 22, 192, 80, 21, - 22, 192, 138, 21, 22, 192, 33, 21, 22, 192, 23, 21, 22, 192, 12, 21, 22, - 191, 246, 21, 22, 192, 158, 191, 246, 21, 22, 170, 21, 22, 192, 140, 21, - 22, 191, 181, 21, 22, 193, 103, 191, 181, 21, 22, 191, 180, 21, 22, 193, - 103, 191, 180, 21, 22, 191, 179, 21, 22, 193, 103, 191, 179, 21, 22, 191, - 178, 21, 22, 193, 103, 191, 178, 21, 22, 191, 177, 21, 22, 193, 103, 191, - 177, 21, 22, 191, 183, 21, 22, 193, 103, 191, 183, 21, 22, 191, 182, 21, - 22, 193, 103, 191, 182, 21, 22, 214, 209, 191, 182, 21, 22, 192, 159, 21, - 22, 248, 186, 192, 159, 21, 22, 193, 103, 192, 159, 21, 22, 205, 101, - 192, 33, 21, 22, 207, 113, 21, 22, 207, 221, 207, 113, 21, 22, 193, 103, - 219, 238, 21, 22, 207, 177, 21, 22, 207, 1, 21, 22, 206, 195, 21, 22, - 206, 162, 21, 22, 206, 134, 21, 22, 193, 103, 219, 43, 21, 22, 165, 21, - 22, 207, 178, 21, 22, 193, 103, 173, 21, 22, 206, 25, 21, 22, 193, 103, - 206, 25, 21, 22, 146, 21, 22, 193, 103, 146, 21, 22, 216, 217, 146, 21, - 22, 233, 59, 21, 22, 233, 106, 21, 22, 233, 23, 21, 22, 233, 8, 21, 22, - 232, 175, 21, 22, 232, 162, 21, 22, 233, 109, 21, 22, 233, 108, 21, 22, - 232, 61, 21, 22, 193, 103, 232, 61, 21, 22, 233, 175, 21, 22, 199, 33, - 21, 22, 215, 59, 199, 33, 21, 22, 199, 11, 21, 22, 215, 59, 199, 11, 21, - 22, 199, 5, 21, 22, 215, 59, 199, 5, 21, 22, 198, 241, 21, 22, 198, 235, - 21, 22, 199, 49, 21, 22, 199, 48, 21, 22, 198, 203, 21, 22, 193, 103, - 198, 203, 21, 22, 199, 51, 21, 22, 197, 118, 21, 22, 197, 116, 21, 22, - 197, 115, 21, 22, 197, 120, 21, 22, 197, 121, 21, 22, 197, 2, 21, 22, - 197, 1, 21, 22, 197, 0, 21, 22, 197, 4, 21, 22, 212, 129, 229, 245, 21, - 22, 212, 129, 229, 158, 21, 22, 212, 129, 229, 130, 21, 22, 212, 129, - 229, 23, 21, 22, 212, 129, 228, 252, 21, 22, 212, 129, 140, 21, 22, 212, - 129, 230, 91, 21, 22, 212, 129, 230, 116, 21, 22, 212, 128, 230, 116, 21, - 22, 229, 113, 21, 22, 208, 92, 21, 22, 208, 57, 21, 22, 208, 51, 21, 22, - 208, 45, 21, 22, 208, 40, 21, 22, 208, 96, 21, 22, 208, 95, 21, 22, 208, - 104, 21, 22, 198, 111, 21, 22, 198, 109, 21, 22, 198, 108, 21, 22, 198, - 112, 21, 22, 193, 103, 207, 113, 21, 22, 193, 103, 207, 1, 21, 22, 193, - 103, 206, 162, 21, 22, 193, 103, 165, 21, 22, 214, 66, 21, 22, 214, 16, - 21, 22, 214, 12, 21, 22, 213, 249, 21, 22, 213, 244, 21, 22, 214, 68, 21, - 22, 214, 67, 21, 22, 214, 70, 21, 22, 213, 72, 21, 22, 205, 101, 203, - 113, 21, 22, 205, 101, 203, 81, 21, 22, 205, 101, 203, 56, 21, 22, 205, - 101, 203, 165, 21, 22, 193, 27, 199, 33, 21, 22, 193, 27, 199, 11, 21, - 22, 193, 27, 198, 241, 21, 22, 193, 27, 199, 49, 21, 22, 193, 27, 199, - 51, 21, 22, 219, 153, 21, 22, 219, 152, 21, 22, 219, 151, 21, 22, 219, - 150, 21, 22, 219, 159, 21, 22, 219, 158, 21, 22, 219, 160, 21, 22, 199, - 50, 199, 33, 21, 22, 199, 50, 199, 11, 21, 22, 199, 50, 199, 5, 21, 22, - 199, 50, 198, 241, 21, 22, 199, 50, 198, 235, 21, 22, 199, 50, 199, 49, - 21, 22, 199, 50, 199, 48, 21, 22, 199, 50, 199, 51, 21, 22, 251, 220, - 250, 120, 21, 22, 248, 136, 71, 21, 22, 248, 136, 68, 21, 22, 248, 136, - 74, 21, 22, 248, 136, 65, 21, 22, 248, 136, 193, 125, 21, 22, 248, 136, - 193, 86, 21, 22, 248, 136, 193, 48, 21, 22, 248, 136, 193, 190, 21, 22, - 248, 136, 214, 121, 21, 22, 248, 136, 213, 219, 21, 22, 248, 136, 213, - 43, 21, 22, 248, 136, 180, 21, 22, 248, 136, 222, 22, 21, 22, 248, 136, - 221, 166, 21, 22, 248, 136, 221, 67, 21, 22, 248, 136, 155, 21, 22, 205, - 101, 229, 245, 21, 22, 205, 101, 229, 158, 21, 22, 205, 101, 229, 23, 21, - 22, 205, 101, 140, 21, 22, 98, 231, 59, 21, 22, 98, 231, 63, 21, 22, 98, - 231, 77, 21, 22, 98, 231, 76, 21, 22, 98, 231, 65, 21, 22, 98, 231, 91, - 21, 22, 98, 206, 68, 21, 22, 98, 206, 162, 21, 22, 98, 207, 113, 21, 22, - 98, 207, 84, 21, 22, 98, 207, 1, 21, 22, 98, 165, 21, 22, 98, 193, 0, 21, - 22, 98, 193, 48, 21, 22, 98, 193, 125, 21, 22, 98, 193, 114, 21, 22, 98, - 193, 86, 21, 22, 98, 193, 190, 21, 22, 98, 228, 118, 21, 22, 98, 228, - 119, 21, 22, 98, 228, 122, 21, 22, 98, 228, 121, 21, 22, 98, 228, 120, - 21, 22, 98, 228, 125, 21, 22, 98, 198, 213, 21, 22, 98, 198, 241, 21, 22, - 98, 199, 33, 21, 22, 98, 199, 31, 21, 22, 98, 199, 11, 21, 22, 98, 199, - 49, 21, 22, 98, 197, 99, 21, 22, 98, 197, 109, 21, 22, 98, 197, 127, 21, - 22, 98, 197, 126, 21, 22, 98, 197, 111, 21, 22, 98, 197, 132, 21, 22, 98, - 208, 165, 21, 22, 98, 209, 73, 21, 22, 98, 210, 63, 21, 22, 98, 210, 49, - 21, 22, 98, 209, 185, 21, 22, 98, 168, 21, 22, 98, 210, 236, 21, 22, 98, - 230, 179, 21, 22, 98, 231, 3, 21, 22, 98, 231, 165, 21, 22, 98, 231, 157, - 21, 22, 98, 231, 53, 21, 22, 98, 231, 240, 21, 22, 98, 221, 175, 21, 22, - 98, 221, 183, 21, 22, 98, 221, 197, 21, 22, 98, 221, 196, 21, 22, 98, - 221, 190, 21, 22, 98, 221, 215, 21, 22, 98, 221, 96, 21, 22, 98, 221, 97, - 21, 22, 98, 221, 100, 21, 22, 98, 221, 99, 21, 22, 98, 221, 98, 21, 22, - 98, 221, 101, 21, 22, 98, 221, 102, 21, 22, 98, 212, 178, 21, 22, 98, - 213, 43, 21, 22, 98, 214, 121, 21, 22, 98, 214, 110, 21, 22, 98, 213, - 219, 21, 22, 98, 180, 21, 22, 98, 215, 155, 21, 22, 98, 216, 12, 21, 22, - 98, 216, 232, 21, 22, 98, 216, 211, 21, 22, 98, 216, 100, 21, 22, 98, - 174, 21, 22, 98, 191, 225, 21, 22, 98, 192, 12, 21, 22, 98, 192, 80, 21, - 22, 98, 192, 77, 21, 22, 98, 192, 33, 21, 22, 98, 170, 21, 22, 98, 222, - 182, 21, 22, 205, 101, 222, 182, 21, 22, 98, 222, 201, 21, 22, 98, 223, - 10, 21, 22, 98, 223, 8, 21, 22, 98, 222, 244, 21, 22, 205, 101, 222, 244, - 21, 22, 98, 223, 32, 21, 22, 98, 222, 215, 21, 22, 98, 222, 219, 21, 22, - 98, 222, 229, 21, 22, 98, 222, 228, 21, 22, 98, 222, 227, 21, 22, 98, - 222, 230, 21, 22, 98, 218, 225, 21, 22, 98, 219, 43, 21, 22, 98, 219, - 238, 21, 22, 98, 219, 228, 21, 22, 98, 219, 146, 21, 22, 98, 173, 21, 22, - 98, 236, 179, 21, 22, 98, 236, 180, 21, 22, 98, 236, 185, 21, 22, 98, - 236, 184, 21, 22, 98, 236, 181, 21, 22, 98, 236, 186, 21, 22, 98, 219, - 149, 21, 22, 98, 219, 151, 21, 22, 98, 219, 155, 21, 22, 98, 219, 154, - 21, 22, 98, 219, 153, 21, 22, 98, 219, 159, 21, 22, 98, 198, 106, 21, 22, - 98, 198, 108, 21, 22, 98, 198, 111, 21, 22, 98, 198, 110, 21, 22, 98, - 198, 109, 21, 22, 98, 198, 112, 21, 22, 98, 198, 101, 21, 22, 98, 198, - 102, 21, 22, 98, 198, 114, 21, 22, 98, 198, 113, 21, 22, 98, 198, 103, - 21, 22, 98, 198, 115, 21, 22, 98, 190, 251, 21, 22, 98, 191, 7, 21, 22, - 98, 191, 87, 21, 22, 98, 191, 84, 21, 22, 98, 191, 30, 21, 22, 98, 191, - 123, 21, 22, 98, 191, 166, 21, 22, 98, 89, 191, 166, 21, 22, 98, 235, 22, - 21, 22, 98, 235, 23, 21, 22, 98, 235, 32, 21, 22, 98, 235, 31, 21, 22, - 98, 235, 26, 21, 22, 98, 235, 35, 21, 22, 98, 201, 4, 21, 22, 98, 202, - 46, 21, 22, 98, 205, 68, 21, 22, 98, 205, 50, 21, 22, 98, 202, 222, 21, - 22, 98, 188, 21, 22, 98, 203, 5, 21, 22, 98, 203, 56, 21, 22, 98, 203, - 113, 21, 22, 98, 203, 111, 21, 22, 98, 203, 81, 21, 22, 98, 203, 165, 21, - 22, 98, 203, 167, 21, 22, 98, 197, 140, 21, 22, 98, 197, 144, 21, 22, 98, - 197, 161, 21, 22, 98, 197, 160, 21, 22, 98, 197, 146, 21, 22, 98, 197, - 168, 21, 22, 98, 243, 48, 21, 22, 98, 243, 68, 21, 22, 98, 243, 127, 21, - 22, 98, 243, 123, 21, 22, 98, 243, 95, 21, 22, 98, 247, 1, 21, 22, 98, - 197, 102, 21, 22, 98, 197, 103, 21, 22, 98, 197, 106, 21, 22, 98, 197, - 105, 21, 22, 98, 197, 104, 21, 22, 98, 197, 107, 21, 22, 243, 96, 56, 21, - 22, 232, 80, 201, 63, 21, 22, 208, 88, 21, 22, 214, 64, 21, 22, 213, 69, - 21, 22, 213, 68, 21, 22, 213, 67, 21, 22, 213, 66, 21, 22, 213, 71, 21, - 22, 213, 70, 21, 22, 193, 27, 198, 201, 21, 22, 193, 27, 198, 200, 21, - 22, 193, 27, 198, 199, 21, 22, 193, 27, 198, 198, 21, 22, 193, 27, 198, - 197, 21, 22, 193, 27, 198, 204, 21, 22, 193, 27, 198, 203, 21, 22, 193, - 27, 53, 199, 51, 21, 22, 248, 136, 193, 224, 211, 140, 201, 248, 77, 211, - 140, 1, 248, 239, 211, 140, 1, 218, 211, 211, 140, 1, 233, 56, 211, 140, - 1, 205, 179, 211, 140, 1, 213, 166, 211, 140, 1, 196, 165, 211, 140, 1, - 238, 5, 211, 140, 1, 198, 139, 211, 140, 1, 242, 86, 211, 140, 1, 247, - 29, 211, 140, 1, 215, 137, 211, 140, 1, 230, 234, 211, 140, 1, 214, 54, - 211, 140, 1, 201, 54, 211, 140, 1, 206, 55, 211, 140, 1, 251, 232, 211, - 140, 1, 211, 91, 211, 140, 1, 196, 62, 211, 140, 1, 234, 215, 211, 140, - 1, 223, 87, 211, 140, 1, 234, 216, 211, 140, 1, 211, 56, 211, 140, 1, - 196, 136, 211, 140, 1, 223, 205, 211, 140, 1, 234, 213, 211, 140, 1, 210, - 38, 211, 140, 233, 55, 77, 211, 140, 207, 18, 233, 55, 77, 206, 44, 1, - 233, 45, 233, 36, 233, 60, 233, 175, 206, 44, 1, 196, 12, 206, 44, 1, - 196, 47, 196, 63, 66, 206, 44, 1, 191, 228, 206, 44, 1, 192, 159, 206, - 44, 1, 193, 224, 206, 44, 1, 198, 206, 198, 205, 198, 233, 206, 44, 1, - 233, 248, 206, 44, 1, 251, 90, 65, 206, 44, 1, 211, 37, 74, 206, 44, 1, - 252, 64, 65, 206, 44, 1, 252, 9, 206, 44, 1, 219, 15, 74, 206, 44, 1, - 203, 33, 74, 206, 44, 1, 74, 206, 44, 1, 211, 151, 206, 44, 1, 211, 104, - 206, 44, 1, 207, 154, 207, 169, 207, 69, 146, 206, 44, 1, 222, 39, 206, - 44, 1, 247, 25, 206, 44, 1, 222, 40, 222, 152, 206, 44, 1, 232, 51, 206, - 44, 1, 234, 88, 206, 44, 1, 231, 160, 230, 122, 232, 51, 206, 44, 1, 231, - 200, 206, 44, 1, 192, 248, 192, 239, 193, 224, 206, 44, 1, 230, 82, 230, - 116, 206, 44, 1, 230, 86, 230, 116, 206, 44, 1, 219, 17, 230, 116, 206, - 44, 1, 203, 36, 230, 116, 206, 44, 1, 214, 203, 212, 91, 214, 204, 215, - 61, 206, 44, 1, 203, 34, 215, 61, 206, 44, 1, 235, 135, 206, 44, 1, 223, - 65, 223, 69, 223, 55, 68, 206, 44, 1, 71, 206, 44, 1, 222, 255, 223, 35, - 206, 44, 1, 231, 141, 206, 44, 1, 219, 18, 252, 25, 206, 44, 1, 203, 38, - 65, 206, 44, 1, 223, 47, 234, 61, 206, 44, 1, 209, 247, 210, 18, 210, - 236, 206, 44, 1, 251, 185, 234, 59, 206, 44, 1, 201, 254, 206, 8, 206, - 44, 1, 202, 198, 219, 14, 206, 8, 206, 44, 1, 203, 32, 206, 8, 206, 44, - 1, 247, 193, 206, 44, 1, 191, 166, 206, 44, 1, 198, 120, 198, 132, 196, - 242, 200, 43, 206, 44, 1, 203, 31, 200, 43, 206, 44, 1, 238, 127, 206, - 44, 1, 248, 217, 248, 220, 248, 142, 250, 120, 206, 44, 1, 203, 37, 250, - 120, 206, 44, 1, 235, 134, 206, 44, 1, 211, 70, 206, 44, 1, 234, 167, - 234, 174, 71, 206, 44, 1, 217, 79, 217, 91, 218, 168, 206, 44, 1, 219, - 16, 218, 168, 206, 44, 1, 203, 35, 218, 168, 206, 44, 1, 219, 253, 220, - 101, 219, 26, 172, 206, 44, 1, 235, 136, 206, 44, 1, 223, 135, 206, 44, - 1, 223, 136, 206, 44, 1, 238, 19, 238, 25, 238, 127, 206, 44, 1, 211, 28, - 233, 247, 74, 206, 44, 1, 234, 211, 206, 44, 1, 223, 85, 206, 44, 1, 238, - 148, 206, 44, 1, 247, 143, 206, 44, 1, 247, 41, 206, 44, 1, 201, 108, - 206, 44, 1, 219, 13, 206, 44, 1, 203, 30, 206, 44, 1, 228, 25, 206, 44, - 1, 208, 104, 206, 44, 1, 192, 235, 206, 44, 202, 170, 208, 151, 206, 44, - 215, 129, 208, 151, 206, 44, 238, 218, 208, 151, 206, 44, 250, 252, 113, - 206, 44, 197, 45, 113, 206, 44, 248, 237, 113, 206, 44, 1, 222, 152, 206, - 44, 1, 203, 167, 206, 44, 1, 211, 87, 206, 44, 1, 232, 110, 247, 81, 211, - 36, 206, 44, 1, 232, 110, 247, 81, 223, 68, 206, 44, 1, 232, 110, 247, - 81, 234, 173, 206, 44, 1, 232, 110, 247, 81, 252, 63, 206, 44, 1, 232, - 110, 247, 81, 252, 9, 199, 222, 1, 65, 199, 222, 1, 68, 199, 222, 1, 66, - 199, 222, 1, 155, 199, 222, 1, 231, 240, 199, 222, 1, 214, 68, 199, 222, - 1, 190, 190, 199, 222, 1, 238, 32, 199, 222, 1, 180, 199, 222, 1, 168, - 199, 222, 1, 249, 153, 199, 222, 1, 174, 199, 222, 1, 170, 199, 222, 1, - 165, 199, 222, 1, 173, 199, 222, 1, 193, 190, 199, 222, 1, 188, 199, 222, - 1, 140, 199, 222, 18, 3, 68, 199, 222, 18, 3, 66, 199, 222, 3, 195, 40, - 199, 222, 3, 210, 169, 199, 222, 1, 251, 14, 165, 230, 23, 1, 65, 230, - 23, 1, 68, 230, 23, 1, 66, 230, 23, 1, 155, 230, 23, 1, 231, 240, 230, - 23, 1, 214, 68, 230, 23, 1, 190, 190, 230, 23, 1, 238, 32, 230, 23, 1, - 180, 230, 23, 1, 168, 230, 23, 1, 249, 153, 230, 23, 1, 174, 230, 23, 1, - 170, 230, 23, 1, 165, 230, 23, 1, 173, 230, 23, 1, 193, 190, 230, 23, 1, - 188, 230, 23, 1, 140, 230, 23, 18, 3, 68, 230, 23, 18, 3, 66, 230, 23, 3, - 210, 169, 209, 204, 202, 170, 208, 151, 209, 204, 55, 208, 151, 248, 0, - 1, 65, 248, 0, 1, 68, 248, 0, 1, 66, 248, 0, 1, 155, 248, 0, 1, 231, 240, - 248, 0, 1, 214, 68, 248, 0, 1, 190, 190, 248, 0, 1, 238, 32, 248, 0, 1, - 180, 248, 0, 1, 168, 248, 0, 1, 249, 153, 248, 0, 1, 174, 248, 0, 1, 170, - 248, 0, 1, 165, 248, 0, 1, 173, 248, 0, 1, 193, 190, 248, 0, 1, 188, 248, - 0, 1, 140, 248, 0, 18, 3, 68, 248, 0, 18, 3, 66, 199, 221, 1, 65, 199, - 221, 1, 68, 199, 221, 1, 66, 199, 221, 1, 155, 199, 221, 1, 231, 240, - 199, 221, 1, 214, 68, 199, 221, 1, 190, 190, 199, 221, 1, 238, 32, 199, - 221, 1, 180, 199, 221, 1, 168, 199, 221, 1, 249, 153, 199, 221, 1, 174, - 199, 221, 1, 170, 199, 221, 1, 173, 199, 221, 1, 193, 190, 199, 221, 1, - 188, 199, 221, 18, 3, 68, 199, 221, 18, 3, 66, 95, 1, 155, 95, 1, 221, - 215, 95, 1, 221, 67, 95, 1, 221, 183, 95, 1, 213, 249, 95, 1, 247, 160, - 95, 1, 247, 1, 95, 1, 242, 99, 95, 1, 243, 68, 95, 1, 212, 65, 95, 1, - 238, 32, 95, 1, 197, 120, 95, 1, 236, 174, 95, 1, 197, 115, 95, 1, 213, - 49, 95, 1, 190, 190, 95, 1, 199, 49, 95, 1, 159, 95, 1, 198, 241, 95, 1, - 213, 43, 95, 1, 249, 153, 95, 1, 209, 228, 95, 1, 209, 73, 95, 1, 209, - 199, 95, 1, 216, 12, 95, 1, 192, 12, 95, 1, 206, 162, 95, 1, 219, 43, 95, - 1, 195, 24, 95, 1, 203, 165, 95, 1, 201, 134, 95, 1, 188, 95, 1, 140, 95, - 1, 173, 95, 1, 208, 96, 95, 223, 149, 18, 208, 82, 95, 223, 149, 18, 208, - 95, 95, 223, 149, 18, 208, 57, 95, 223, 149, 18, 208, 51, 95, 223, 149, - 18, 208, 33, 95, 223, 149, 18, 208, 0, 95, 223, 149, 18, 207, 244, 95, - 223, 149, 18, 207, 243, 95, 223, 149, 18, 206, 17, 95, 223, 149, 18, 206, - 10, 95, 223, 149, 18, 218, 183, 95, 223, 149, 18, 218, 171, 95, 223, 149, - 18, 208, 75, 95, 223, 149, 18, 208, 88, 95, 223, 149, 18, 208, 41, 196, - 255, 107, 95, 223, 149, 18, 208, 41, 196, 255, 109, 95, 223, 149, 18, - 208, 77, 95, 18, 223, 133, 251, 37, 95, 18, 223, 133, 252, 206, 95, 18, - 3, 252, 206, 95, 18, 3, 68, 95, 18, 3, 223, 199, 95, 18, 3, 192, 159, 95, - 18, 3, 191, 176, 95, 18, 3, 66, 95, 18, 3, 196, 30, 95, 18, 3, 196, 168, - 95, 18, 3, 211, 151, 95, 18, 3, 170, 95, 18, 3, 223, 226, 95, 18, 3, 71, - 95, 18, 3, 252, 25, 95, 18, 3, 251, 236, 95, 18, 3, 211, 87, 95, 18, 3, - 250, 163, 95, 3, 213, 184, 95, 3, 207, 106, 95, 3, 191, 187, 95, 3, 215, - 91, 95, 3, 197, 229, 95, 3, 249, 90, 95, 3, 206, 151, 95, 3, 198, 90, 95, - 3, 222, 95, 95, 3, 251, 238, 95, 3, 205, 143, 205, 135, 95, 3, 195, 37, - 95, 3, 242, 90, 95, 3, 249, 60, 95, 3, 221, 205, 95, 3, 249, 85, 95, 3, - 247, 131, 209, 146, 220, 186, 95, 3, 219, 205, 198, 59, 95, 3, 248, 205, - 95, 3, 209, 201, 215, 148, 95, 3, 221, 39, 95, 238, 170, 16, 206, 241, - 95, 3, 250, 144, 95, 3, 250, 166, 95, 17, 191, 77, 95, 17, 107, 95, 17, - 109, 95, 17, 138, 95, 17, 134, 95, 17, 149, 95, 17, 169, 95, 17, 175, 95, - 17, 171, 95, 17, 178, 95, 16, 219, 205, 250, 168, 202, 19, 95, 16, 219, - 205, 250, 168, 215, 112, 95, 16, 219, 205, 250, 168, 209, 145, 95, 16, - 219, 205, 250, 168, 248, 240, 95, 16, 219, 205, 250, 168, 247, 236, 95, - 16, 219, 205, 250, 168, 208, 245, 95, 16, 219, 205, 250, 168, 208, 239, - 95, 16, 219, 205, 250, 168, 208, 237, 95, 16, 219, 205, 250, 168, 208, - 243, 95, 16, 219, 205, 250, 168, 208, 241, 104, 248, 158, 104, 234, 120, - 104, 242, 74, 104, 232, 80, 201, 63, 104, 242, 83, 104, 232, 128, 236, - 138, 104, 198, 88, 202, 32, 228, 88, 104, 202, 214, 5, 248, 73, 217, 51, - 104, 217, 87, 242, 74, 104, 217, 87, 232, 80, 201, 63, 104, 213, 164, - 104, 232, 109, 67, 205, 35, 107, 104, 232, 109, 67, 205, 35, 109, 104, - 232, 109, 67, 205, 35, 138, 104, 18, 204, 10, 104, 232, 109, 67, 205, 35, - 134, 104, 17, 191, 77, 104, 17, 107, 104, 17, 109, 104, 17, 138, 104, 17, - 134, 104, 17, 149, 104, 17, 169, 104, 17, 175, 104, 17, 171, 104, 17, - 178, 104, 1, 65, 104, 1, 71, 104, 1, 68, 104, 1, 74, 104, 1, 66, 104, 1, - 211, 151, 104, 1, 196, 152, 104, 1, 234, 188, 104, 1, 180, 104, 1, 251, - 122, 104, 1, 249, 153, 104, 1, 168, 104, 1, 208, 96, 104, 1, 231, 240, - 104, 1, 174, 104, 1, 173, 104, 1, 188, 104, 1, 203, 165, 104, 1, 190, - 190, 104, 1, 238, 32, 104, 1, 247, 1, 104, 1, 223, 32, 104, 1, 170, 104, - 1, 165, 104, 1, 193, 190, 104, 1, 233, 109, 104, 1, 155, 104, 1, 221, - 215, 104, 1, 197, 168, 104, 1, 191, 123, 104, 1, 230, 91, 104, 1, 190, - 255, 104, 1, 219, 159, 104, 1, 191, 57, 104, 1, 243, 95, 104, 1, 198, 88, - 179, 18, 56, 104, 1, 198, 88, 71, 104, 1, 198, 88, 68, 104, 1, 198, 88, - 74, 104, 1, 198, 88, 66, 104, 1, 198, 88, 211, 151, 104, 1, 198, 88, 196, - 152, 104, 1, 198, 88, 251, 122, 104, 1, 198, 88, 249, 153, 104, 1, 198, - 88, 168, 104, 1, 198, 88, 208, 96, 104, 1, 198, 88, 231, 240, 104, 1, - 198, 88, 174, 104, 1, 198, 88, 190, 190, 104, 1, 198, 88, 238, 32, 104, - 1, 198, 88, 247, 1, 104, 1, 198, 88, 223, 32, 104, 1, 198, 88, 197, 168, - 104, 1, 198, 88, 170, 104, 1, 198, 88, 193, 190, 104, 1, 198, 88, 155, - 104, 1, 198, 88, 231, 237, 104, 1, 198, 88, 230, 91, 104, 1, 198, 88, - 222, 243, 104, 1, 198, 88, 213, 209, 104, 1, 198, 88, 235, 35, 104, 1, - 202, 214, 71, 104, 1, 202, 214, 68, 104, 1, 202, 214, 223, 44, 104, 1, - 202, 214, 196, 152, 104, 1, 202, 214, 66, 104, 1, 202, 214, 251, 122, - 104, 1, 202, 214, 155, 104, 1, 202, 214, 231, 240, 104, 1, 202, 214, 140, - 104, 1, 202, 214, 168, 104, 1, 202, 214, 203, 165, 104, 1, 202, 214, 190, - 190, 104, 1, 202, 214, 238, 32, 104, 1, 202, 214, 223, 32, 104, 1, 202, - 214, 233, 109, 104, 1, 202, 214, 231, 237, 104, 1, 202, 214, 230, 91, - 104, 1, 202, 214, 197, 168, 104, 1, 202, 214, 191, 123, 104, 1, 202, 214, - 207, 178, 104, 1, 202, 214, 247, 1, 104, 1, 202, 214, 191, 71, 104, 1, - 217, 87, 68, 104, 1, 217, 87, 155, 104, 1, 217, 87, 165, 104, 1, 217, 87, - 233, 109, 104, 1, 217, 87, 191, 71, 104, 1, 247, 2, 4, 105, 236, 138, - 104, 1, 251, 184, 231, 220, 251, 72, 107, 104, 1, 251, 184, 231, 220, - 195, 36, 107, 104, 1, 251, 184, 231, 220, 237, 247, 104, 1, 251, 184, - 231, 220, 196, 163, 104, 1, 251, 184, 231, 220, 223, 93, 196, 163, 104, - 1, 251, 184, 231, 220, 249, 104, 104, 1, 251, 184, 231, 220, 115, 249, - 104, 104, 1, 251, 184, 231, 220, 65, 104, 1, 251, 184, 231, 220, 68, 104, - 1, 251, 184, 231, 220, 155, 104, 1, 251, 184, 231, 220, 214, 68, 104, 1, - 251, 184, 231, 220, 247, 160, 104, 1, 251, 184, 231, 220, 197, 132, 104, - 1, 251, 184, 231, 220, 197, 120, 104, 1, 251, 184, 231, 220, 237, 191, - 104, 1, 251, 184, 231, 220, 213, 79, 104, 1, 251, 184, 231, 220, 190, - 190, 104, 1, 251, 184, 231, 220, 238, 32, 104, 1, 251, 184, 231, 220, - 168, 104, 1, 251, 184, 231, 220, 209, 228, 104, 1, 251, 184, 231, 220, - 201, 175, 104, 1, 251, 184, 231, 220, 191, 71, 104, 1, 251, 184, 231, - 220, 191, 123, 104, 1, 251, 184, 231, 220, 251, 245, 104, 1, 198, 88, - 251, 184, 231, 220, 190, 190, 104, 1, 198, 88, 251, 184, 231, 220, 191, - 71, 104, 1, 217, 87, 251, 184, 231, 220, 231, 91, 104, 1, 217, 87, 251, - 184, 231, 220, 214, 68, 104, 1, 217, 87, 251, 184, 231, 220, 247, 160, - 104, 1, 217, 87, 251, 184, 231, 220, 222, 252, 104, 1, 217, 87, 251, 184, - 231, 220, 197, 132, 104, 1, 217, 87, 251, 184, 231, 220, 237, 175, 104, - 1, 217, 87, 251, 184, 231, 220, 190, 190, 104, 1, 217, 87, 251, 184, 231, - 220, 237, 68, 104, 1, 217, 87, 251, 184, 231, 220, 201, 175, 104, 1, 217, - 87, 251, 184, 231, 220, 238, 142, 104, 1, 217, 87, 251, 184, 231, 220, - 191, 71, 104, 1, 217, 87, 251, 184, 231, 220, 191, 123, 104, 1, 251, 184, - 231, 220, 132, 66, 104, 1, 251, 184, 231, 220, 132, 170, 104, 1, 217, 87, - 251, 184, 231, 220, 248, 203, 104, 1, 251, 184, 231, 220, 238, 20, 104, - 1, 217, 87, 251, 184, 231, 220, 219, 159, 21, 22, 210, 242, 21, 22, 250, - 131, 21, 22, 252, 160, 21, 22, 193, 128, 21, 22, 208, 251, 21, 22, 210, - 72, 21, 22, 208, 113, 21, 22, 199, 154, 21, 22, 222, 29, 21, 22, 220, - 176, 21, 22, 217, 21, 21, 22, 212, 250, 21, 22, 214, 198, 21, 22, 219, - 248, 21, 22, 201, 252, 21, 22, 205, 103, 21, 22, 203, 18, 21, 22, 203, - 117, 21, 22, 202, 232, 21, 22, 191, 234, 21, 22, 192, 86, 21, 22, 207, - 122, 21, 22, 212, 107, 21, 22, 211, 128, 212, 107, 21, 22, 212, 106, 21, - 22, 211, 128, 212, 106, 21, 22, 212, 105, 21, 22, 211, 128, 212, 105, 21, - 22, 212, 104, 21, 22, 211, 128, 212, 104, 21, 22, 206, 22, 21, 22, 206, - 21, 21, 22, 206, 20, 21, 22, 206, 19, 21, 22, 206, 18, 21, 22, 206, 26, - 21, 22, 211, 128, 210, 236, 21, 22, 211, 128, 200, 43, 21, 22, 211, 128, - 222, 152, 21, 22, 211, 128, 247, 193, 21, 22, 211, 128, 218, 168, 21, 22, - 211, 128, 215, 61, 21, 22, 211, 128, 206, 8, 21, 22, 211, 128, 203, 167, - 21, 22, 234, 202, 193, 224, 21, 22, 193, 102, 193, 224, 21, 22, 53, 2, - 206, 188, 21, 22, 53, 207, 147, 236, 140, 21, 22, 207, 221, 206, 23, 21, - 22, 193, 103, 219, 8, 21, 22, 193, 103, 220, 125, 21, 22, 198, 202, 21, - 22, 198, 204, 21, 22, 197, 112, 21, 22, 197, 114, 21, 22, 197, 119, 21, - 22, 198, 105, 21, 22, 198, 107, 21, 22, 205, 101, 202, 237, 21, 22, 205, - 101, 203, 48, 21, 22, 205, 101, 228, 252, 21, 22, 98, 230, 130, 21, 22, - 98, 237, 103, 231, 157, 21, 22, 98, 231, 237, 21, 22, 98, 230, 135, 21, - 22, 205, 101, 222, 162, 21, 22, 98, 222, 160, 21, 22, 249, 5, 237, 103, - 172, 21, 22, 249, 5, 237, 103, 146, 21, 22, 98, 237, 98, 206, 8, 219, - 122, 195, 1, 219, 175, 219, 122, 1, 155, 219, 122, 1, 221, 215, 219, 122, - 1, 231, 240, 219, 122, 1, 231, 91, 219, 122, 1, 214, 68, 219, 122, 1, - 247, 160, 219, 122, 1, 247, 1, 219, 122, 1, 223, 32, 219, 122, 1, 222, - 252, 219, 122, 1, 192, 108, 219, 122, 1, 190, 190, 219, 122, 1, 199, 49, - 219, 122, 1, 238, 32, 219, 122, 1, 237, 68, 219, 122, 1, 180, 219, 122, - 1, 168, 219, 122, 1, 209, 228, 219, 122, 1, 249, 153, 219, 122, 1, 248, - 203, 219, 122, 1, 174, 219, 122, 1, 170, 219, 122, 1, 165, 219, 122, 1, - 173, 219, 122, 1, 193, 190, 219, 122, 1, 203, 165, 219, 122, 1, 201, 175, - 219, 122, 1, 188, 219, 122, 1, 140, 219, 122, 1, 230, 126, 219, 122, 1, - 198, 26, 219, 122, 18, 3, 65, 219, 122, 18, 3, 68, 219, 122, 18, 3, 66, - 219, 122, 18, 3, 234, 188, 219, 122, 18, 3, 251, 236, 219, 122, 18, 3, - 211, 87, 219, 122, 18, 3, 250, 163, 219, 122, 18, 3, 71, 219, 122, 18, 3, - 74, 219, 122, 200, 239, 1, 170, 219, 122, 200, 239, 1, 165, 219, 122, - 200, 239, 1, 193, 190, 219, 122, 2, 1, 155, 219, 122, 2, 1, 214, 68, 219, - 122, 2, 1, 251, 71, 219, 122, 2, 1, 190, 190, 219, 122, 2, 1, 180, 219, - 122, 2, 1, 168, 219, 122, 2, 1, 174, 219, 122, 2, 1, 165, 219, 122, 2, 1, - 173, 219, 122, 3, 215, 134, 219, 122, 3, 222, 1, 219, 122, 3, 205, 198, - 219, 122, 3, 219, 8, 219, 122, 233, 216, 77, 219, 122, 208, 13, 77, 219, - 122, 17, 191, 77, 219, 122, 17, 107, 219, 122, 17, 109, 219, 122, 17, - 138, 219, 122, 17, 134, 219, 122, 17, 149, 219, 122, 17, 169, 219, 122, - 17, 175, 219, 122, 17, 171, 219, 122, 17, 178, 54, 219, 239, 1, 155, 54, - 219, 239, 1, 192, 220, 54, 219, 239, 1, 214, 68, 54, 219, 239, 1, 197, - 168, 54, 219, 239, 1, 188, 54, 219, 239, 1, 170, 54, 219, 239, 1, 190, - 190, 54, 219, 239, 1, 199, 49, 54, 219, 239, 1, 173, 54, 219, 239, 1, - 168, 54, 219, 239, 1, 209, 228, 54, 219, 239, 1, 174, 54, 219, 239, 1, - 233, 109, 54, 219, 239, 1, 195, 188, 54, 219, 239, 1, 140, 54, 219, 239, - 1, 208, 96, 54, 219, 239, 1, 221, 215, 54, 219, 239, 1, 197, 157, 54, - 219, 239, 1, 180, 54, 219, 239, 1, 65, 54, 219, 239, 1, 68, 54, 219, 239, - 1, 234, 188, 54, 219, 239, 1, 234, 173, 54, 219, 239, 1, 66, 54, 219, - 239, 1, 211, 87, 54, 219, 239, 1, 74, 54, 219, 239, 1, 196, 152, 54, 219, - 239, 1, 71, 54, 219, 239, 1, 250, 161, 54, 219, 239, 1, 251, 236, 54, - 219, 239, 1, 198, 77, 54, 219, 239, 1, 198, 76, 54, 219, 239, 1, 198, 75, - 54, 219, 239, 1, 198, 74, 54, 219, 239, 1, 198, 73, 214, 80, 54, 218, - 219, 1, 137, 208, 96, 214, 80, 54, 218, 219, 1, 130, 208, 96, 214, 80, - 54, 218, 219, 1, 137, 155, 214, 80, 54, 218, 219, 1, 137, 192, 220, 214, - 80, 54, 218, 219, 1, 137, 214, 68, 214, 80, 54, 218, 219, 1, 130, 155, - 214, 80, 54, 218, 219, 1, 130, 192, 220, 214, 80, 54, 218, 219, 1, 130, - 214, 68, 214, 80, 54, 218, 219, 1, 137, 197, 168, 214, 80, 54, 218, 219, - 1, 137, 188, 214, 80, 54, 218, 219, 1, 137, 170, 214, 80, 54, 218, 219, - 1, 130, 197, 168, 214, 80, 54, 218, 219, 1, 130, 188, 214, 80, 54, 218, - 219, 1, 130, 170, 214, 80, 54, 218, 219, 1, 137, 190, 190, 214, 80, 54, - 218, 219, 1, 137, 199, 49, 214, 80, 54, 218, 219, 1, 137, 180, 214, 80, - 54, 218, 219, 1, 130, 190, 190, 214, 80, 54, 218, 219, 1, 130, 199, 49, - 214, 80, 54, 218, 219, 1, 130, 180, 214, 80, 54, 218, 219, 1, 137, 168, - 214, 80, 54, 218, 219, 1, 137, 209, 228, 214, 80, 54, 218, 219, 1, 137, - 174, 214, 80, 54, 218, 219, 1, 130, 168, 214, 80, 54, 218, 219, 1, 130, - 209, 228, 214, 80, 54, 218, 219, 1, 130, 174, 214, 80, 54, 218, 219, 1, - 137, 233, 109, 214, 80, 54, 218, 219, 1, 137, 195, 188, 214, 80, 54, 218, - 219, 1, 137, 173, 214, 80, 54, 218, 219, 1, 130, 233, 109, 214, 80, 54, - 218, 219, 1, 130, 195, 188, 214, 80, 54, 218, 219, 1, 130, 173, 214, 80, - 54, 218, 219, 1, 137, 140, 214, 80, 54, 218, 219, 1, 137, 238, 32, 214, - 80, 54, 218, 219, 1, 137, 249, 153, 214, 80, 54, 218, 219, 1, 130, 140, - 214, 80, 54, 218, 219, 1, 130, 238, 32, 214, 80, 54, 218, 219, 1, 130, - 249, 153, 214, 80, 54, 218, 219, 1, 137, 220, 181, 214, 80, 54, 218, 219, - 1, 137, 192, 185, 214, 80, 54, 218, 219, 1, 130, 220, 181, 214, 80, 54, - 218, 219, 1, 130, 192, 185, 214, 80, 54, 218, 219, 1, 137, 200, 251, 214, - 80, 54, 218, 219, 1, 130, 200, 251, 214, 80, 54, 218, 219, 18, 3, 18, - 203, 28, 214, 80, 54, 218, 219, 18, 3, 252, 206, 214, 80, 54, 218, 219, - 18, 3, 223, 199, 214, 80, 54, 218, 219, 18, 3, 66, 214, 80, 54, 218, 219, - 18, 3, 196, 30, 214, 80, 54, 218, 219, 18, 3, 71, 214, 80, 54, 218, 219, - 18, 3, 252, 25, 214, 80, 54, 218, 219, 18, 3, 74, 214, 80, 54, 218, 219, - 18, 3, 211, 182, 214, 80, 54, 218, 219, 18, 3, 196, 152, 214, 80, 54, - 218, 219, 18, 3, 250, 131, 214, 80, 54, 218, 219, 18, 3, 252, 160, 214, - 80, 54, 218, 219, 18, 3, 196, 21, 214, 80, 54, 218, 219, 18, 3, 210, 242, - 214, 80, 54, 218, 219, 18, 3, 211, 179, 214, 80, 54, 218, 219, 18, 3, - 196, 144, 214, 80, 54, 218, 219, 18, 3, 223, 44, 214, 80, 54, 218, 219, - 1, 53, 196, 12, 214, 80, 54, 218, 219, 1, 53, 214, 70, 214, 80, 54, 218, - 219, 1, 53, 215, 61, 214, 80, 54, 218, 219, 1, 53, 218, 168, 214, 80, 54, - 218, 219, 1, 53, 222, 152, 214, 80, 54, 218, 219, 1, 53, 238, 127, 214, - 80, 54, 218, 219, 1, 53, 250, 120, 214, 80, 54, 218, 219, 163, 217, 55, - 214, 80, 54, 218, 219, 163, 217, 54, 214, 80, 54, 218, 219, 17, 191, 77, - 214, 80, 54, 218, 219, 17, 107, 214, 80, 54, 218, 219, 17, 109, 214, 80, - 54, 218, 219, 17, 138, 214, 80, 54, 218, 219, 17, 134, 214, 80, 54, 218, - 219, 17, 149, 214, 80, 54, 218, 219, 17, 169, 214, 80, 54, 218, 219, 17, - 175, 214, 80, 54, 218, 219, 17, 171, 214, 80, 54, 218, 219, 17, 178, 214, - 80, 54, 218, 219, 128, 17, 107, 214, 80, 54, 218, 219, 3, 220, 107, 214, - 80, 54, 218, 219, 3, 220, 106, 95, 16, 210, 84, 95, 16, 215, 113, 221, - 58, 95, 16, 209, 146, 221, 58, 95, 16, 248, 241, 221, 58, 95, 16, 247, - 237, 221, 58, 95, 16, 208, 246, 221, 58, 95, 16, 208, 240, 221, 58, 95, - 16, 208, 238, 221, 58, 95, 16, 208, 244, 221, 58, 95, 16, 208, 242, 221, - 58, 95, 16, 237, 232, 221, 58, 95, 16, 237, 228, 221, 58, 95, 16, 237, - 227, 221, 58, 95, 16, 237, 230, 221, 58, 95, 16, 237, 229, 221, 58, 95, - 16, 237, 226, 221, 58, 95, 16, 197, 51, 95, 16, 215, 113, 206, 149, 95, - 16, 209, 146, 206, 149, 95, 16, 248, 241, 206, 149, 95, 16, 247, 237, - 206, 149, 95, 16, 208, 246, 206, 149, 95, 16, 208, 240, 206, 149, 95, 16, - 208, 238, 206, 149, 95, 16, 208, 244, 206, 149, 95, 16, 208, 242, 206, - 149, 95, 16, 237, 232, 206, 149, 95, 16, 237, 228, 206, 149, 95, 16, 237, - 227, 206, 149, 95, 16, 237, 230, 206, 149, 95, 16, 237, 229, 206, 149, - 95, 16, 237, 226, 206, 149, 248, 1, 1, 155, 248, 1, 1, 231, 240, 248, 1, - 1, 214, 68, 248, 1, 1, 214, 11, 248, 1, 1, 168, 248, 1, 1, 249, 153, 248, - 1, 1, 174, 248, 1, 1, 215, 166, 248, 1, 1, 190, 190, 248, 1, 1, 238, 32, - 248, 1, 1, 180, 248, 1, 1, 212, 244, 248, 1, 1, 247, 160, 248, 1, 1, 223, - 32, 248, 1, 1, 212, 101, 248, 1, 1, 212, 92, 248, 1, 1, 170, 248, 1, 1, - 165, 248, 1, 1, 173, 248, 1, 1, 195, 188, 248, 1, 1, 188, 248, 1, 1, 65, - 248, 1, 1, 140, 248, 1, 18, 3, 68, 248, 1, 18, 3, 66, 248, 1, 18, 3, 71, - 248, 1, 18, 3, 74, 248, 1, 18, 3, 252, 25, 248, 1, 210, 184, 248, 1, 234, - 95, 79, 205, 53, 54, 128, 1, 137, 155, 54, 128, 1, 137, 221, 215, 54, - 128, 1, 137, 220, 165, 54, 128, 1, 130, 155, 54, 128, 1, 130, 220, 165, - 54, 128, 1, 130, 221, 215, 54, 128, 1, 214, 68, 54, 128, 1, 137, 247, - 160, 54, 128, 1, 137, 247, 1, 54, 128, 1, 130, 247, 160, 54, 128, 1, 130, - 188, 54, 128, 1, 130, 247, 1, 54, 128, 1, 212, 101, 54, 128, 1, 207, 129, - 54, 128, 1, 137, 207, 127, 54, 128, 1, 238, 32, 54, 128, 1, 130, 207, - 127, 54, 128, 1, 207, 138, 54, 128, 1, 137, 190, 190, 54, 128, 1, 137, - 199, 49, 54, 128, 1, 130, 190, 190, 54, 128, 1, 130, 199, 49, 54, 128, 1, - 180, 54, 128, 1, 249, 153, 54, 128, 1, 137, 168, 54, 128, 1, 137, 209, - 228, 54, 128, 1, 137, 233, 109, 54, 128, 1, 130, 168, 54, 128, 1, 130, - 233, 109, 54, 128, 1, 130, 209, 228, 54, 128, 1, 174, 54, 128, 1, 130, - 170, 54, 128, 1, 137, 170, 54, 128, 1, 165, 54, 128, 1, 206, 57, 54, 128, - 1, 173, 54, 128, 1, 218, 218, 54, 128, 1, 193, 190, 54, 128, 1, 137, 203, - 165, 54, 128, 1, 137, 201, 175, 54, 128, 1, 137, 188, 54, 128, 1, 137, - 140, 54, 128, 1, 219, 73, 54, 128, 1, 65, 54, 128, 1, 130, 140, 54, 128, - 1, 68, 54, 128, 1, 223, 199, 54, 128, 1, 66, 54, 128, 1, 196, 30, 54, - 128, 1, 234, 188, 54, 128, 1, 211, 87, 54, 128, 1, 220, 107, 54, 128, 1, - 230, 206, 188, 54, 128, 120, 3, 216, 217, 165, 54, 128, 120, 3, 216, 217, - 173, 54, 128, 120, 3, 220, 126, 199, 190, 220, 96, 54, 128, 3, 217, 113, - 222, 84, 220, 96, 54, 128, 120, 3, 53, 214, 68, 54, 128, 120, 3, 130, - 168, 54, 128, 120, 3, 137, 207, 128, 211, 57, 130, 168, 54, 128, 120, 3, - 174, 54, 128, 120, 3, 249, 153, 54, 128, 120, 3, 188, 54, 128, 3, 205, - 172, 54, 128, 18, 3, 65, 54, 128, 18, 3, 217, 113, 205, 122, 54, 128, 18, - 3, 252, 206, 54, 128, 18, 3, 199, 200, 252, 206, 54, 128, 18, 3, 68, 54, - 128, 18, 3, 223, 199, 54, 128, 18, 3, 196, 152, 54, 128, 18, 3, 196, 29, - 54, 128, 18, 3, 66, 54, 128, 18, 3, 196, 30, 54, 128, 18, 3, 74, 54, 128, - 18, 3, 211, 183, 60, 54, 128, 18, 3, 210, 242, 54, 128, 18, 3, 71, 54, - 128, 18, 3, 252, 25, 54, 128, 18, 3, 211, 87, 54, 128, 18, 3, 251, 236, - 54, 128, 18, 3, 128, 251, 236, 54, 128, 18, 3, 211, 183, 58, 54, 128, 3, - 217, 113, 222, 83, 54, 128, 3, 198, 78, 54, 128, 3, 198, 77, 54, 128, 3, - 221, 171, 198, 76, 54, 128, 3, 221, 171, 198, 75, 54, 128, 3, 221, 171, - 198, 74, 54, 128, 3, 207, 186, 230, 90, 54, 128, 3, 217, 113, 205, 152, - 54, 128, 3, 221, 170, 222, 64, 54, 128, 33, 238, 198, 236, 140, 54, 128, - 228, 243, 17, 191, 77, 54, 128, 228, 243, 17, 107, 54, 128, 228, 243, 17, - 109, 54, 128, 228, 243, 17, 138, 54, 128, 228, 243, 17, 134, 54, 128, - 228, 243, 17, 149, 54, 128, 228, 243, 17, 169, 54, 128, 228, 243, 17, - 175, 54, 128, 228, 243, 17, 171, 54, 128, 228, 243, 17, 178, 54, 128, - 128, 17, 191, 77, 54, 128, 128, 17, 107, 54, 128, 128, 17, 109, 54, 128, - 128, 17, 138, 54, 128, 128, 17, 134, 54, 128, 128, 17, 149, 54, 128, 128, - 17, 169, 54, 128, 128, 17, 175, 54, 128, 128, 17, 171, 54, 128, 128, 17, - 178, 54, 128, 3, 193, 80, 54, 128, 3, 193, 79, 54, 128, 3, 205, 107, 54, - 128, 3, 221, 246, 54, 128, 3, 228, 170, 54, 128, 3, 236, 157, 54, 128, 3, - 207, 18, 206, 122, 207, 138, 54, 128, 3, 217, 113, 192, 109, 54, 128, 3, - 222, 120, 54, 128, 3, 222, 119, 54, 128, 3, 205, 117, 54, 128, 3, 205, - 116, 54, 128, 3, 230, 26, 54, 128, 3, 247, 157, 33, 235, 128, 243, 2, - 252, 60, 33, 237, 41, 33, 223, 139, 33, 235, 119, 57, 33, 197, 225, 236, - 140, 33, 192, 233, 60, 33, 193, 72, 219, 113, 60, 33, 211, 77, 87, 60, - 33, 55, 211, 77, 87, 60, 33, 156, 247, 23, 201, 28, 60, 33, 201, 14, 247, - 23, 201, 28, 60, 33, 210, 115, 58, 33, 55, 210, 115, 58, 33, 210, 115, - 60, 33, 210, 115, 210, 255, 33, 8, 2, 1, 193, 225, 60, 33, 8, 2, 1, 153, - 193, 225, 60, 33, 45, 210, 114, 93, 219, 224, 33, 50, 210, 114, 93, 183, - 33, 45, 210, 114, 248, 233, 219, 224, 33, 50, 210, 114, 248, 233, 183, - 33, 51, 248, 51, 58, 33, 31, 3, 58, 33, 223, 93, 55, 251, 15, 58, 33, - 108, 3, 58, 33, 55, 108, 3, 58, 33, 55, 108, 3, 60, 33, 197, 225, 252, - 47, 252, 60, 33, 8, 2, 1, 223, 115, 232, 51, 33, 8, 2, 1, 223, 115, 146, - 33, 8, 2, 1, 223, 115, 200, 43, 148, 3, 196, 123, 206, 244, 148, 3, 196, - 123, 247, 121, 148, 3, 247, 38, 148, 3, 200, 173, 148, 3, 248, 155, 148, - 1, 251, 214, 148, 1, 251, 215, 199, 123, 148, 1, 223, 194, 148, 1, 223, - 195, 199, 123, 148, 1, 196, 126, 148, 1, 196, 127, 199, 123, 148, 1, 207, - 186, 207, 51, 148, 1, 207, 186, 207, 52, 199, 123, 148, 1, 220, 126, 219, - 199, 148, 1, 220, 126, 219, 200, 199, 123, 148, 1, 234, 145, 148, 1, 251, - 233, 148, 1, 211, 123, 148, 1, 211, 124, 199, 123, 148, 1, 155, 148, 1, - 222, 142, 217, 116, 148, 1, 231, 240, 148, 1, 231, 241, 230, 241, 148, 1, - 214, 68, 148, 1, 247, 160, 148, 1, 247, 161, 220, 112, 148, 1, 223, 32, - 148, 1, 223, 33, 223, 0, 148, 1, 212, 101, 148, 1, 199, 252, 220, 2, 148, - 1, 199, 252, 215, 108, 217, 116, 148, 1, 238, 33, 215, 108, 251, 162, - 148, 1, 238, 33, 215, 108, 217, 116, 148, 1, 215, 7, 207, 141, 148, 1, - 190, 190, 148, 1, 199, 252, 199, 158, 148, 1, 238, 32, 148, 1, 238, 33, - 217, 138, 148, 1, 180, 148, 1, 168, 148, 1, 210, 221, 222, 76, 148, 1, - 249, 153, 148, 1, 249, 154, 222, 2, 148, 1, 174, 148, 1, 170, 148, 1, - 165, 148, 1, 173, 148, 1, 193, 190, 148, 1, 205, 207, 205, 184, 148, 1, - 205, 207, 205, 129, 148, 1, 188, 148, 1, 140, 148, 3, 207, 41, 148, 18, - 3, 199, 123, 148, 18, 3, 196, 122, 148, 18, 3, 196, 123, 205, 125, 148, - 18, 3, 200, 208, 148, 18, 3, 200, 209, 223, 185, 148, 18, 3, 207, 186, - 207, 51, 148, 18, 3, 207, 186, 207, 52, 199, 123, 148, 18, 3, 220, 126, - 219, 199, 148, 18, 3, 220, 126, 219, 200, 199, 123, 148, 18, 3, 199, 201, - 148, 18, 3, 199, 202, 207, 51, 148, 18, 3, 199, 202, 199, 123, 148, 18, - 3, 199, 202, 207, 52, 199, 123, 148, 18, 3, 210, 16, 148, 18, 3, 210, 17, - 199, 123, 148, 252, 37, 252, 36, 148, 1, 222, 107, 205, 124, 148, 1, 221, - 177, 205, 124, 148, 1, 196, 235, 205, 124, 148, 1, 234, 182, 205, 124, - 148, 1, 195, 154, 205, 124, 148, 1, 191, 109, 205, 124, 148, 1, 250, 185, - 205, 124, 148, 1, 251, 14, 222, 202, 148, 17, 191, 77, 148, 17, 107, 148, - 17, 109, 148, 17, 138, 148, 17, 134, 148, 17, 149, 148, 17, 169, 148, 17, - 175, 148, 17, 171, 148, 17, 178, 148, 210, 145, 148, 210, 175, 148, 193, - 64, 148, 247, 94, 210, 168, 148, 247, 94, 202, 190, 148, 247, 94, 210, - 112, 148, 210, 174, 148, 37, 16, 236, 148, 148, 37, 16, 237, 102, 148, - 37, 16, 235, 71, 148, 37, 16, 237, 236, 148, 37, 16, 237, 237, 200, 173, - 148, 37, 16, 236, 242, 148, 37, 16, 238, 24, 148, 37, 16, 237, 77, 148, - 37, 16, 238, 6, 148, 37, 16, 237, 237, 231, 159, 148, 37, 16, 33, 199, - 116, 148, 37, 16, 33, 234, 92, 148, 37, 16, 33, 221, 253, 148, 37, 16, - 33, 221, 255, 148, 37, 16, 33, 223, 5, 148, 37, 16, 33, 221, 254, 4, 223, - 5, 148, 37, 16, 33, 222, 0, 4, 223, 5, 148, 37, 16, 33, 248, 226, 148, - 37, 16, 33, 230, 247, 148, 37, 16, 206, 206, 211, 77, 235, 82, 148, 37, - 16, 206, 206, 211, 77, 238, 22, 148, 37, 16, 206, 206, 242, 219, 197, 80, - 148, 37, 16, 206, 206, 242, 219, 199, 211, 148, 37, 16, 219, 222, 211, - 77, 210, 160, 148, 37, 16, 219, 222, 211, 77, 208, 149, 148, 37, 16, 219, - 222, 242, 219, 209, 104, 148, 37, 16, 219, 222, 242, 219, 209, 86, 148, - 37, 16, 219, 222, 211, 77, 209, 132, 148, 210, 146, 220, 19, 148, 210, - 176, 220, 19, 200, 197, 3, 210, 142, 200, 197, 3, 210, 156, 200, 197, 3, - 210, 152, 200, 197, 1, 65, 200, 197, 1, 68, 200, 197, 1, 66, 200, 197, 1, - 252, 25, 200, 197, 1, 74, 200, 197, 1, 71, 200, 197, 1, 233, 242, 200, - 197, 1, 155, 200, 197, 1, 208, 96, 200, 197, 1, 231, 240, 200, 197, 1, - 214, 68, 200, 197, 1, 247, 160, 200, 197, 1, 223, 32, 200, 197, 1, 191, - 123, 200, 197, 1, 212, 101, 200, 197, 1, 190, 190, 200, 197, 1, 238, 32, - 200, 197, 1, 180, 200, 197, 1, 168, 200, 197, 1, 233, 109, 200, 197, 1, - 195, 188, 200, 197, 1, 249, 153, 200, 197, 1, 174, 200, 197, 1, 170, 200, - 197, 1, 165, 200, 197, 1, 173, 200, 197, 1, 193, 190, 200, 197, 1, 188, - 200, 197, 1, 192, 220, 200, 197, 1, 140, 200, 197, 120, 3, 210, 172, 200, - 197, 120, 3, 210, 144, 200, 197, 120, 3, 210, 141, 200, 197, 18, 3, 210, - 159, 200, 197, 18, 3, 210, 140, 200, 197, 18, 3, 210, 165, 200, 197, 18, - 3, 210, 151, 200, 197, 18, 3, 210, 173, 200, 197, 18, 3, 210, 161, 200, - 197, 3, 210, 177, 200, 197, 3, 195, 40, 200, 197, 120, 3, 210, 100, 174, - 200, 197, 120, 3, 210, 100, 193, 190, 200, 197, 1, 221, 215, 200, 197, 1, - 200, 126, 200, 197, 17, 191, 77, 200, 197, 17, 107, 200, 197, 17, 109, - 200, 197, 17, 138, 200, 197, 17, 134, 200, 197, 17, 149, 200, 197, 17, - 169, 200, 197, 17, 175, 200, 197, 17, 171, 200, 197, 17, 178, 200, 197, - 250, 145, 200, 197, 1, 207, 21, 200, 197, 1, 219, 172, 200, 197, 1, 248, - 203, 200, 197, 1, 53, 222, 152, 200, 197, 1, 53, 218, 168, 249, 63, 1, - 65, 249, 63, 1, 202, 182, 65, 249, 63, 1, 140, 249, 63, 1, 202, 182, 140, - 249, 63, 1, 217, 85, 140, 249, 63, 1, 249, 153, 249, 63, 1, 222, 61, 249, - 153, 249, 63, 1, 168, 249, 63, 1, 202, 182, 168, 249, 63, 1, 180, 249, - 63, 1, 217, 85, 180, 249, 63, 1, 193, 190, 249, 63, 1, 202, 182, 193, - 190, 249, 63, 1, 210, 193, 193, 190, 249, 63, 1, 231, 240, 249, 63, 1, - 202, 182, 231, 240, 249, 63, 1, 223, 32, 249, 63, 1, 238, 32, 249, 63, 1, - 165, 249, 63, 1, 202, 182, 165, 249, 63, 1, 174, 249, 63, 1, 202, 182, - 174, 249, 63, 1, 202, 0, 190, 190, 249, 63, 1, 213, 16, 190, 190, 249, - 63, 1, 188, 249, 63, 1, 202, 182, 188, 249, 63, 1, 217, 85, 188, 249, 63, - 1, 170, 249, 63, 1, 202, 182, 170, 249, 63, 1, 214, 68, 249, 63, 1, 173, - 249, 63, 1, 202, 182, 173, 249, 63, 1, 212, 101, 249, 63, 1, 247, 160, - 249, 63, 1, 214, 162, 249, 63, 1, 217, 11, 249, 63, 1, 68, 249, 63, 1, - 66, 249, 63, 3, 198, 82, 249, 63, 18, 3, 71, 249, 63, 18, 3, 210, 193, - 71, 249, 63, 18, 3, 234, 188, 249, 63, 18, 3, 68, 249, 63, 18, 3, 222, - 61, 68, 249, 63, 18, 3, 74, 249, 63, 18, 3, 222, 61, 74, 249, 63, 18, 3, - 66, 249, 63, 18, 3, 126, 40, 202, 182, 188, 249, 63, 120, 3, 214, 70, - 249, 63, 120, 3, 230, 116, 249, 63, 210, 154, 249, 63, 210, 150, 249, 63, - 16, 248, 165, 215, 7, 216, 163, 249, 63, 16, 248, 165, 209, 138, 249, 63, - 16, 248, 165, 222, 179, 249, 63, 16, 248, 165, 210, 154, 219, 183, 1, - 155, 219, 183, 1, 221, 94, 219, 183, 1, 221, 215, 219, 183, 1, 231, 240, - 219, 183, 1, 231, 19, 219, 183, 1, 214, 68, 219, 183, 1, 247, 160, 219, - 183, 1, 247, 1, 219, 183, 1, 223, 32, 219, 183, 1, 212, 101, 219, 183, 1, - 190, 190, 219, 183, 1, 199, 49, 219, 183, 1, 238, 32, 219, 183, 1, 180, - 219, 183, 1, 168, 219, 183, 1, 209, 110, 219, 183, 1, 209, 228, 219, 183, - 1, 233, 109, 219, 183, 1, 232, 219, 219, 183, 1, 249, 153, 219, 183, 1, - 248, 140, 219, 183, 1, 174, 219, 183, 1, 216, 19, 219, 183, 1, 197, 168, - 219, 183, 1, 197, 157, 219, 183, 1, 235, 35, 219, 183, 1, 170, 219, 183, - 1, 165, 219, 183, 1, 173, 219, 183, 1, 140, 219, 183, 1, 229, 111, 219, - 183, 1, 195, 188, 219, 183, 1, 188, 219, 183, 1, 203, 165, 219, 183, 1, - 193, 190, 219, 183, 1, 65, 219, 183, 200, 239, 1, 170, 219, 183, 200, - 239, 1, 165, 219, 183, 18, 3, 252, 206, 219, 183, 18, 3, 68, 219, 183, - 18, 3, 74, 219, 183, 18, 3, 211, 87, 219, 183, 18, 3, 66, 219, 183, 18, - 3, 196, 30, 219, 183, 18, 3, 71, 219, 183, 120, 3, 222, 152, 219, 183, - 120, 3, 218, 168, 219, 183, 120, 3, 172, 219, 183, 120, 3, 215, 61, 219, - 183, 120, 3, 210, 236, 219, 183, 120, 3, 146, 219, 183, 120, 3, 200, 43, - 219, 183, 120, 3, 212, 73, 219, 183, 120, 3, 222, 83, 219, 183, 3, 207, - 139, 219, 183, 3, 212, 141, 219, 183, 208, 152, 199, 247, 219, 183, 208, - 152, 212, 85, 198, 196, 199, 247, 219, 183, 208, 152, 247, 10, 219, 183, - 208, 152, 197, 149, 247, 10, 219, 183, 208, 152, 197, 148, 219, 183, 17, - 191, 77, 219, 183, 17, 107, 219, 183, 17, 109, 219, 183, 17, 138, 219, - 183, 17, 134, 219, 183, 17, 149, 219, 183, 17, 169, 219, 183, 17, 175, - 219, 183, 17, 171, 219, 183, 17, 178, 219, 183, 1, 197, 132, 219, 183, 1, - 197, 120, 219, 183, 1, 237, 191, 211, 121, 243, 88, 17, 191, 77, 211, - 121, 243, 88, 17, 107, 211, 121, 243, 88, 17, 109, 211, 121, 243, 88, 17, - 138, 211, 121, 243, 88, 17, 134, 211, 121, 243, 88, 17, 149, 211, 121, - 243, 88, 17, 169, 211, 121, 243, 88, 17, 175, 211, 121, 243, 88, 17, 171, - 211, 121, 243, 88, 17, 178, 211, 121, 243, 88, 1, 173, 211, 121, 243, 88, - 1, 250, 182, 211, 121, 243, 88, 1, 251, 253, 211, 121, 243, 88, 1, 251, - 122, 211, 121, 243, 88, 1, 251, 207, 211, 121, 243, 88, 1, 220, 125, 211, - 121, 243, 88, 1, 252, 168, 211, 121, 243, 88, 1, 252, 169, 211, 121, 243, - 88, 1, 252, 167, 211, 121, 243, 88, 1, 252, 161, 211, 121, 243, 88, 1, - 219, 146, 211, 121, 243, 88, 1, 223, 68, 211, 121, 243, 88, 1, 223, 200, - 211, 121, 243, 88, 1, 223, 90, 211, 121, 243, 88, 1, 223, 77, 211, 121, - 243, 88, 1, 218, 225, 211, 121, 243, 88, 1, 196, 160, 211, 121, 243, 88, - 1, 196, 158, 211, 121, 243, 88, 1, 196, 83, 211, 121, 243, 88, 1, 196, - 21, 211, 121, 243, 88, 1, 219, 238, 211, 121, 243, 88, 1, 234, 56, 211, - 121, 243, 88, 1, 234, 191, 211, 121, 243, 88, 1, 234, 103, 211, 121, 243, - 88, 1, 234, 26, 211, 121, 243, 88, 1, 219, 43, 211, 121, 243, 88, 1, 211, - 24, 211, 121, 243, 88, 1, 211, 178, 211, 121, 243, 88, 1, 211, 9, 211, - 121, 243, 88, 1, 211, 136, 211, 121, 243, 88, 215, 156, 197, 97, 211, - 121, 243, 88, 231, 235, 197, 98, 211, 121, 243, 88, 215, 150, 197, 98, - 211, 121, 243, 88, 207, 66, 211, 121, 243, 88, 209, 226, 211, 121, 243, - 88, 251, 244, 211, 121, 243, 88, 208, 152, 215, 146, 211, 121, 243, 88, - 208, 152, 55, 215, 146, 38, 2, 1, 206, 113, 195, 153, 38, 2, 1, 219, 12, - 237, 146, 38, 2, 1, 214, 215, 74, 38, 2, 1, 193, 78, 234, 22, 38, 2, 1, - 199, 200, 199, 145, 38, 2, 1, 198, 221, 199, 145, 38, 2, 1, 199, 200, - 230, 17, 56, 38, 2, 1, 199, 200, 192, 95, 38, 2, 1, 196, 108, 196, 128, - 101, 215, 157, 6, 1, 251, 132, 101, 215, 157, 6, 1, 249, 101, 101, 215, - 157, 6, 1, 231, 210, 101, 215, 157, 6, 1, 236, 150, 101, 215, 157, 6, 1, - 234, 103, 101, 215, 157, 6, 1, 195, 49, 101, 215, 157, 6, 1, 191, 80, - 101, 215, 157, 6, 1, 199, 193, 101, 215, 157, 6, 1, 223, 162, 101, 215, - 157, 6, 1, 222, 87, 101, 215, 157, 6, 1, 220, 7, 101, 215, 157, 6, 1, - 217, 90, 101, 215, 157, 6, 1, 214, 216, 101, 215, 157, 6, 1, 211, 104, - 101, 215, 157, 6, 1, 210, 131, 101, 215, 157, 6, 1, 191, 67, 101, 215, - 157, 6, 1, 207, 163, 101, 215, 157, 6, 1, 205, 142, 101, 215, 157, 6, 1, - 199, 179, 101, 215, 157, 6, 1, 196, 113, 101, 215, 157, 6, 1, 209, 220, - 101, 215, 157, 6, 1, 221, 200, 101, 215, 157, 6, 1, 231, 82, 101, 215, - 157, 6, 1, 208, 81, 101, 215, 157, 6, 1, 203, 69, 101, 215, 157, 6, 1, - 243, 81, 101, 215, 157, 6, 1, 247, 128, 101, 215, 157, 6, 1, 222, 234, - 101, 215, 157, 6, 1, 243, 18, 101, 215, 157, 6, 1, 246, 241, 101, 215, - 157, 6, 1, 192, 218, 101, 215, 157, 6, 1, 222, 249, 101, 215, 157, 6, 1, - 230, 87, 101, 215, 157, 6, 1, 229, 245, 101, 215, 157, 6, 1, 229, 145, - 101, 215, 157, 6, 1, 193, 125, 101, 215, 157, 6, 1, 230, 19, 101, 215, - 157, 6, 1, 229, 11, 101, 215, 157, 6, 1, 233, 23, 101, 215, 157, 6, 1, - 192, 14, 101, 215, 157, 6, 1, 234, 123, 101, 215, 157, 6, 1, 153, 231, - 210, 101, 215, 157, 6, 1, 251, 230, 101, 215, 157, 6, 1, 252, 14, 101, - 215, 157, 6, 1, 230, 17, 56, 101, 215, 157, 6, 1, 220, 116, 56, 200, 197, - 208, 152, 248, 165, 200, 166, 200, 197, 208, 152, 248, 165, 210, 155, - 200, 197, 208, 152, 248, 165, 208, 139, 200, 197, 208, 152, 248, 165, - 247, 145, 200, 197, 208, 152, 248, 165, 219, 173, 205, 121, 200, 197, - 208, 152, 248, 165, 222, 142, 205, 121, 200, 197, 208, 152, 248, 165, - 238, 33, 205, 121, 200, 197, 208, 152, 248, 165, 249, 154, 205, 121, 195, - 150, 163, 222, 57, 195, 150, 163, 203, 130, 195, 150, 163, 208, 225, 195, - 150, 3, 213, 187, 195, 150, 3, 192, 117, 216, 82, 200, 156, 195, 150, - 163, 192, 117, 251, 249, 223, 149, 200, 156, 195, 150, 163, 192, 117, - 223, 149, 200, 156, 195, 150, 163, 192, 117, 222, 45, 223, 149, 200, 156, - 195, 150, 163, 247, 122, 60, 195, 150, 163, 192, 117, 222, 45, 223, 149, - 200, 157, 205, 88, 195, 150, 163, 55, 200, 156, 195, 150, 163, 197, 225, - 200, 156, 195, 150, 163, 222, 45, 251, 73, 195, 150, 163, 75, 60, 195, - 150, 163, 105, 185, 60, 195, 150, 163, 115, 185, 60, 195, 150, 163, 206, - 196, 222, 56, 223, 149, 200, 156, 195, 150, 163, 250, 179, 223, 149, 200, - 156, 195, 150, 3, 195, 36, 200, 156, 195, 150, 3, 195, 36, 196, 154, 195, - 150, 3, 207, 18, 195, 36, 196, 154, 195, 150, 3, 195, 36, 251, 73, 195, - 150, 3, 207, 18, 195, 36, 251, 73, 195, 150, 3, 195, 36, 196, 155, 4, - 199, 215, 195, 150, 3, 195, 36, 251, 74, 4, 199, 215, 195, 150, 3, 251, - 72, 251, 88, 195, 150, 3, 251, 72, 249, 120, 195, 150, 3, 251, 72, 195, - 178, 195, 150, 3, 251, 72, 195, 179, 4, 199, 215, 195, 150, 3, 198, 126, - 195, 150, 3, 229, 180, 179, 251, 71, 195, 150, 3, 179, 251, 71, 195, 150, - 3, 206, 70, 179, 251, 71, 195, 150, 3, 251, 72, 196, 162, 215, 136, 195, - 150, 3, 251, 10, 195, 150, 3, 206, 122, 251, 10, 195, 150, 163, 247, 122, - 58, 195, 150, 3, 222, 237, 195, 150, 3, 196, 75, 195, 150, 3, 250, 177, - 195, 150, 163, 206, 189, 58, 195, 150, 163, 55, 206, 189, 58, 195, 150, - 3, 55, 251, 72, 251, 88, 8, 1, 2, 6, 65, 8, 1, 2, 6, 252, 25, 8, 2, 1, - 153, 252, 25, 8, 1, 2, 6, 249, 82, 250, 120, 8, 1, 2, 6, 247, 193, 8, 1, - 2, 6, 238, 127, 8, 1, 2, 6, 233, 248, 8, 1, 2, 6, 71, 8, 2, 1, 153, 211, - 77, 71, 8, 2, 1, 153, 68, 8, 1, 2, 6, 223, 35, 8, 1, 2, 6, 222, 152, 8, - 1, 2, 6, 220, 143, 4, 106, 8, 1, 2, 6, 218, 168, 8, 1, 2, 6, 207, 18, - 215, 61, 8, 1, 2, 6, 74, 8, 1, 2, 6, 211, 77, 74, 8, 2, 1, 202, 206, 74, - 8, 2, 1, 202, 206, 211, 77, 74, 8, 2, 1, 202, 206, 187, 4, 106, 8, 2, 1, - 153, 211, 151, 8, 1, 2, 6, 211, 19, 8, 2, 1, 198, 54, 132, 74, 8, 2, 1, - 248, 77, 132, 74, 8, 1, 2, 6, 210, 236, 8, 1, 2, 6, 207, 18, 146, 8, 1, - 2, 6, 153, 146, 8, 1, 2, 6, 200, 43, 8, 1, 2, 6, 66, 8, 2, 1, 202, 206, - 66, 8, 2, 1, 202, 206, 237, 40, 66, 8, 2, 1, 202, 206, 153, 218, 168, 8, - 1, 2, 6, 196, 12, 8, 1, 2, 6, 193, 224, 8, 1, 2, 6, 191, 166, 8, 1, 2, 6, - 233, 178, 8, 1, 195, 20, 220, 8, 201, 216, 8, 1, 251, 230, 35, 1, 2, 6, - 231, 211, 35, 1, 2, 6, 220, 31, 35, 1, 2, 6, 209, 185, 35, 1, 2, 6, 207, - 3, 35, 1, 2, 6, 208, 176, 38, 1, 2, 6, 234, 140, 52, 1, 6, 65, 52, 1, 6, - 252, 25, 52, 1, 6, 250, 120, 52, 1, 6, 249, 82, 250, 120, 52, 1, 6, 238, - 127, 52, 1, 6, 71, 52, 1, 6, 207, 18, 71, 52, 1, 6, 232, 51, 52, 1, 6, - 230, 116, 52, 1, 6, 68, 52, 1, 6, 223, 35, 52, 1, 6, 222, 152, 52, 1, 6, - 172, 52, 1, 6, 218, 168, 52, 1, 6, 215, 61, 52, 1, 6, 207, 18, 215, 61, - 52, 1, 6, 74, 52, 1, 6, 211, 19, 52, 1, 6, 210, 236, 52, 1, 6, 146, 52, - 1, 6, 200, 43, 52, 1, 6, 66, 52, 1, 6, 193, 224, 52, 1, 2, 65, 52, 1, 2, - 153, 65, 52, 1, 2, 251, 160, 52, 1, 2, 153, 252, 25, 52, 1, 2, 250, 120, - 52, 1, 2, 238, 127, 52, 1, 2, 71, 52, 1, 2, 205, 86, 52, 1, 2, 211, 77, - 71, 52, 1, 2, 153, 211, 77, 71, 52, 1, 2, 232, 51, 52, 1, 2, 153, 68, 52, - 1, 2, 222, 152, 52, 1, 2, 218, 168, 52, 1, 2, 234, 88, 52, 1, 2, 74, 52, - 1, 2, 211, 77, 74, 52, 1, 2, 198, 54, 132, 74, 52, 1, 2, 248, 77, 132, - 74, 52, 1, 2, 210, 236, 52, 1, 2, 200, 43, 52, 1, 2, 66, 52, 1, 2, 202, - 206, 66, 52, 1, 2, 153, 218, 168, 52, 1, 2, 196, 12, 52, 1, 2, 251, 230, - 52, 1, 2, 248, 212, 52, 1, 2, 35, 231, 211, 52, 1, 2, 237, 106, 52, 1, 2, - 35, 209, 211, 52, 1, 2, 243, 95, 8, 200, 230, 2, 1, 68, 8, 200, 230, 2, - 1, 146, 8, 200, 230, 2, 1, 66, 8, 200, 230, 2, 1, 196, 12, 35, 200, 230, - 2, 1, 248, 212, 35, 200, 230, 2, 1, 231, 211, 35, 200, 230, 2, 1, 207, 3, - 35, 200, 230, 2, 1, 209, 211, 35, 200, 230, 2, 1, 243, 95, 8, 2, 1, 196, - 152, 8, 2, 1, 78, 4, 82, 198, 152, 8, 2, 1, 238, 128, 4, 82, 198, 152, 8, - 2, 1, 233, 176, 4, 82, 198, 152, 8, 2, 1, 218, 169, 4, 82, 198, 152, 8, - 2, 1, 215, 62, 4, 82, 198, 152, 8, 2, 1, 210, 237, 4, 82, 198, 152, 8, 2, - 1, 207, 222, 4, 82, 198, 152, 8, 2, 1, 207, 222, 4, 232, 234, 23, 82, - 198, 152, 8, 2, 1, 206, 9, 4, 82, 198, 152, 8, 2, 1, 200, 44, 4, 82, 198, - 152, 8, 2, 1, 191, 167, 4, 82, 198, 152, 8, 2, 1, 153, 232, 51, 52, 1, - 38, 234, 103, 8, 2, 1, 223, 115, 232, 51, 8, 2, 1, 199, 52, 4, 201, 32, - 8, 2, 6, 1, 228, 74, 4, 106, 8, 2, 1, 223, 84, 4, 106, 8, 2, 1, 210, 237, - 4, 106, 8, 2, 6, 1, 126, 4, 106, 8, 2, 1, 196, 71, 4, 106, 8, 2, 1, 78, - 4, 210, 192, 102, 8, 2, 1, 238, 128, 4, 210, 192, 102, 8, 2, 1, 233, 176, - 4, 210, 192, 102, 8, 2, 1, 232, 52, 4, 210, 192, 102, 8, 2, 1, 222, 153, - 4, 210, 192, 102, 8, 2, 1, 220, 143, 4, 210, 192, 102, 8, 2, 1, 218, 169, - 4, 210, 192, 102, 8, 2, 1, 215, 62, 4, 210, 192, 102, 8, 2, 1, 210, 237, - 4, 210, 192, 102, 8, 2, 1, 207, 222, 4, 210, 192, 102, 8, 2, 1, 206, 9, - 4, 210, 192, 102, 8, 2, 1, 234, 13, 4, 210, 192, 102, 8, 2, 1, 196, 13, - 4, 210, 192, 102, 8, 2, 1, 192, 236, 4, 210, 192, 102, 8, 2, 1, 191, 167, - 4, 210, 192, 102, 8, 2, 1, 42, 4, 207, 24, 102, 8, 2, 1, 251, 161, 4, - 207, 24, 102, 8, 2, 1, 238, 128, 4, 228, 251, 23, 199, 215, 8, 2, 1, 235, - 15, 4, 207, 24, 102, 8, 2, 1, 211, 77, 235, 15, 4, 207, 24, 102, 8, 2, 1, - 207, 18, 211, 77, 235, 15, 4, 207, 24, 102, 8, 2, 1, 205, 87, 4, 207, 24, - 102, 8, 2, 1, 228, 74, 4, 207, 24, 102, 8, 2, 1, 211, 77, 187, 4, 207, - 24, 102, 8, 2, 1, 234, 13, 4, 207, 24, 102, 8, 2, 1, 126, 4, 207, 24, - 102, 8, 2, 1, 233, 179, 4, 207, 24, 102, 52, 1, 2, 153, 251, 160, 52, 1, - 2, 247, 193, 52, 1, 2, 247, 194, 4, 238, 175, 52, 1, 2, 233, 248, 52, 1, - 2, 207, 18, 211, 77, 71, 52, 1, 2, 233, 175, 52, 1, 2, 236, 139, 223, 36, - 4, 106, 52, 1, 2, 27, 232, 51, 52, 1, 2, 153, 230, 116, 52, 1, 2, 228, - 74, 4, 106, 52, 1, 2, 223, 83, 52, 1, 2, 6, 68, 52, 1, 2, 6, 228, 74, 4, - 106, 52, 1, 2, 223, 36, 4, 238, 212, 52, 1, 2, 220, 143, 4, 207, 24, 102, - 52, 1, 2, 220, 143, 4, 210, 192, 102, 52, 1, 2, 6, 172, 52, 1, 2, 218, - 169, 4, 102, 52, 1, 2, 153, 218, 169, 4, 179, 219, 212, 52, 1, 2, 215, - 62, 4, 45, 102, 52, 1, 2, 215, 62, 4, 207, 24, 102, 52, 1, 2, 6, 215, 61, - 52, 1, 2, 249, 82, 74, 52, 1, 2, 209, 211, 52, 1, 2, 206, 9, 4, 102, 52, - 1, 2, 234, 12, 52, 1, 2, 200, 44, 4, 210, 192, 102, 52, 1, 2, 126, 164, - 52, 1, 2, 196, 70, 52, 1, 2, 6, 66, 52, 1, 2, 196, 13, 4, 102, 52, 1, 2, - 153, 196, 12, 52, 1, 2, 191, 166, 52, 1, 2, 191, 167, 4, 207, 24, 102, - 52, 1, 2, 191, 167, 4, 238, 175, 52, 1, 2, 233, 178, 52, 1, 2, 199, 15, - 33, 235, 138, 230, 211, 252, 60, 33, 235, 138, 252, 47, 252, 60, 33, 202, - 59, 60, 33, 200, 164, 77, 33, 217, 145, 33, 230, 208, 33, 217, 143, 33, - 252, 44, 33, 230, 209, 33, 252, 45, 33, 8, 2, 1, 207, 222, 60, 33, 248, - 35, 33, 217, 144, 33, 55, 243, 2, 58, 33, 211, 139, 58, 33, 191, 21, 60, - 33, 223, 69, 60, 33, 196, 63, 58, 33, 196, 46, 58, 33, 8, 2, 1, 232, 203, - 211, 77, 42, 58, 33, 8, 2, 1, 252, 25, 33, 8, 2, 1, 251, 68, 33, 8, 2, 1, - 250, 146, 33, 8, 2, 1, 247, 194, 247, 35, 33, 8, 2, 1, 223, 115, 238, - 127, 33, 8, 2, 1, 233, 248, 33, 8, 2, 1, 232, 51, 33, 8, 1, 2, 6, 232, - 51, 33, 8, 2, 1, 222, 152, 33, 8, 2, 1, 172, 33, 8, 1, 2, 6, 172, 33, 8, - 1, 2, 6, 218, 168, 33, 8, 2, 1, 215, 61, 33, 8, 1, 2, 6, 215, 61, 33, 8, - 1, 2, 6, 146, 33, 8, 2, 1, 207, 222, 206, 116, 33, 8, 2, 1, 206, 8, 33, - 8, 2, 1, 179, 206, 8, 33, 8, 2, 1, 191, 166, 33, 8, 2, 1, 251, 160, 33, - 8, 2, 1, 250, 120, 33, 8, 2, 1, 248, 212, 33, 8, 2, 1, 205, 86, 33, 8, 2, - 1, 233, 175, 33, 8, 2, 1, 220, 143, 4, 55, 82, 198, 152, 33, 8, 2, 1, - 187, 4, 156, 247, 23, 106, 33, 8, 2, 1, 210, 236, 33, 8, 2, 1, 234, 12, - 33, 8, 2, 1, 126, 4, 156, 247, 23, 106, 33, 8, 2, 1, 193, 224, 33, 8, 2, - 1, 42, 4, 237, 42, 33, 8, 2, 1, 187, 4, 237, 42, 33, 8, 2, 1, 126, 4, - 237, 42, 33, 133, 199, 229, 58, 33, 222, 36, 93, 183, 33, 222, 36, 93, - 219, 224, 33, 75, 93, 219, 224, 33, 193, 78, 223, 93, 248, 29, 60, 33, - 75, 248, 233, 219, 224, 33, 237, 115, 77, 33, 55, 223, 93, 248, 37, 60, - 33, 251, 165, 234, 45, 119, 60, 33, 45, 250, 236, 58, 33, 50, 250, 236, - 23, 144, 250, 236, 60, 8, 6, 1, 42, 4, 206, 189, 60, 8, 2, 1, 42, 4, 206, - 189, 60, 8, 6, 1, 78, 4, 75, 58, 8, 2, 1, 78, 4, 75, 58, 8, 6, 1, 78, 4, - 75, 60, 8, 2, 1, 78, 4, 75, 60, 8, 6, 1, 78, 4, 219, 113, 60, 8, 2, 1, - 78, 4, 219, 113, 60, 8, 6, 1, 247, 194, 4, 247, 36, 23, 252, 46, 8, 2, 1, - 247, 194, 4, 247, 36, 23, 252, 46, 8, 6, 1, 238, 128, 4, 75, 58, 8, 2, 1, - 238, 128, 4, 75, 58, 8, 6, 1, 238, 128, 4, 75, 60, 8, 2, 1, 238, 128, 4, - 75, 60, 8, 6, 1, 238, 128, 4, 219, 113, 60, 8, 2, 1, 238, 128, 4, 219, - 113, 60, 8, 6, 1, 238, 128, 4, 247, 35, 8, 2, 1, 238, 128, 4, 247, 35, 8, - 6, 1, 238, 128, 4, 243, 2, 60, 8, 2, 1, 238, 128, 4, 243, 2, 60, 8, 6, 1, - 235, 15, 4, 217, 147, 23, 230, 210, 8, 2, 1, 235, 15, 4, 217, 147, 23, - 230, 210, 8, 6, 1, 235, 15, 4, 217, 147, 23, 252, 46, 8, 2, 1, 235, 15, - 4, 217, 147, 23, 252, 46, 8, 6, 1, 235, 15, 4, 243, 2, 60, 8, 2, 1, 235, - 15, 4, 243, 2, 60, 8, 6, 1, 235, 15, 4, 198, 153, 60, 8, 2, 1, 235, 15, - 4, 198, 153, 60, 8, 6, 1, 235, 15, 4, 247, 36, 23, 248, 36, 8, 2, 1, 235, - 15, 4, 247, 36, 23, 248, 36, 8, 6, 1, 233, 176, 4, 75, 58, 8, 2, 1, 233, - 176, 4, 75, 58, 8, 6, 1, 232, 52, 4, 217, 146, 8, 2, 1, 232, 52, 4, 217, - 146, 8, 6, 1, 230, 117, 4, 75, 58, 8, 2, 1, 230, 117, 4, 75, 58, 8, 6, 1, - 230, 117, 4, 75, 60, 8, 2, 1, 230, 117, 4, 75, 60, 8, 6, 1, 230, 117, 4, - 237, 42, 8, 2, 1, 230, 117, 4, 237, 42, 8, 6, 1, 230, 117, 4, 247, 35, 8, - 2, 1, 230, 117, 4, 247, 35, 8, 6, 1, 230, 117, 4, 248, 37, 60, 8, 2, 1, - 230, 117, 4, 248, 37, 60, 8, 6, 1, 228, 74, 4, 198, 153, 60, 8, 2, 1, - 228, 74, 4, 198, 153, 60, 8, 6, 1, 228, 74, 4, 237, 43, 23, 252, 46, 8, - 2, 1, 228, 74, 4, 237, 43, 23, 252, 46, 8, 6, 1, 222, 153, 4, 252, 46, 8, - 2, 1, 222, 153, 4, 252, 46, 8, 6, 1, 222, 153, 4, 75, 60, 8, 2, 1, 222, - 153, 4, 75, 60, 8, 6, 1, 222, 153, 4, 219, 113, 60, 8, 2, 1, 222, 153, 4, - 219, 113, 60, 8, 6, 1, 220, 143, 4, 75, 60, 8, 2, 1, 220, 143, 4, 75, 60, - 8, 6, 1, 220, 143, 4, 75, 248, 233, 23, 217, 146, 8, 2, 1, 220, 143, 4, - 75, 248, 233, 23, 217, 146, 8, 6, 1, 220, 143, 4, 219, 113, 60, 8, 2, 1, - 220, 143, 4, 219, 113, 60, 8, 6, 1, 220, 143, 4, 243, 2, 60, 8, 2, 1, - 220, 143, 4, 243, 2, 60, 8, 6, 1, 218, 169, 4, 252, 46, 8, 2, 1, 218, - 169, 4, 252, 46, 8, 6, 1, 218, 169, 4, 75, 58, 8, 2, 1, 218, 169, 4, 75, - 58, 8, 6, 1, 218, 169, 4, 75, 60, 8, 2, 1, 218, 169, 4, 75, 60, 8, 6, 1, - 215, 62, 4, 75, 58, 8, 2, 1, 215, 62, 4, 75, 58, 8, 6, 1, 215, 62, 4, 75, - 60, 8, 2, 1, 215, 62, 4, 75, 60, 8, 6, 1, 215, 62, 4, 219, 113, 60, 8, 2, - 1, 215, 62, 4, 219, 113, 60, 8, 6, 1, 215, 62, 4, 243, 2, 60, 8, 2, 1, - 215, 62, 4, 243, 2, 60, 8, 6, 1, 187, 4, 198, 153, 23, 252, 46, 8, 2, 1, - 187, 4, 198, 153, 23, 252, 46, 8, 6, 1, 187, 4, 198, 153, 23, 237, 42, 8, - 2, 1, 187, 4, 198, 153, 23, 237, 42, 8, 6, 1, 187, 4, 217, 147, 23, 230, - 210, 8, 2, 1, 187, 4, 217, 147, 23, 230, 210, 8, 6, 1, 187, 4, 217, 147, - 23, 252, 46, 8, 2, 1, 187, 4, 217, 147, 23, 252, 46, 8, 6, 1, 210, 237, - 4, 252, 46, 8, 2, 1, 210, 237, 4, 252, 46, 8, 6, 1, 210, 237, 4, 75, 58, - 8, 2, 1, 210, 237, 4, 75, 58, 8, 6, 1, 207, 222, 4, 75, 58, 8, 2, 1, 207, - 222, 4, 75, 58, 8, 6, 1, 207, 222, 4, 75, 60, 8, 2, 1, 207, 222, 4, 75, - 60, 8, 6, 1, 207, 222, 4, 75, 248, 233, 23, 217, 146, 8, 2, 1, 207, 222, - 4, 75, 248, 233, 23, 217, 146, 8, 6, 1, 207, 222, 4, 219, 113, 60, 8, 2, - 1, 207, 222, 4, 219, 113, 60, 8, 6, 1, 206, 9, 4, 75, 58, 8, 2, 1, 206, - 9, 4, 75, 58, 8, 6, 1, 206, 9, 4, 75, 60, 8, 2, 1, 206, 9, 4, 75, 60, 8, - 6, 1, 206, 9, 4, 252, 47, 23, 75, 58, 8, 2, 1, 206, 9, 4, 252, 47, 23, - 75, 58, 8, 6, 1, 206, 9, 4, 247, 93, 23, 75, 58, 8, 2, 1, 206, 9, 4, 247, - 93, 23, 75, 58, 8, 6, 1, 206, 9, 4, 75, 248, 233, 23, 75, 58, 8, 2, 1, - 206, 9, 4, 75, 248, 233, 23, 75, 58, 8, 6, 1, 200, 44, 4, 75, 58, 8, 2, - 1, 200, 44, 4, 75, 58, 8, 6, 1, 200, 44, 4, 75, 60, 8, 2, 1, 200, 44, 4, - 75, 60, 8, 6, 1, 200, 44, 4, 219, 113, 60, 8, 2, 1, 200, 44, 4, 219, 113, - 60, 8, 6, 1, 200, 44, 4, 243, 2, 60, 8, 2, 1, 200, 44, 4, 243, 2, 60, 8, - 6, 1, 126, 4, 237, 43, 60, 8, 2, 1, 126, 4, 237, 43, 60, 8, 6, 1, 126, 4, - 198, 153, 60, 8, 2, 1, 126, 4, 198, 153, 60, 8, 6, 1, 126, 4, 243, 2, 60, - 8, 2, 1, 126, 4, 243, 2, 60, 8, 6, 1, 126, 4, 198, 153, 23, 252, 46, 8, - 2, 1, 126, 4, 198, 153, 23, 252, 46, 8, 6, 1, 126, 4, 217, 147, 23, 237, - 42, 8, 2, 1, 126, 4, 217, 147, 23, 237, 42, 8, 6, 1, 196, 13, 4, 198, - 152, 8, 2, 1, 196, 13, 4, 198, 152, 8, 6, 1, 196, 13, 4, 75, 60, 8, 2, 1, - 196, 13, 4, 75, 60, 8, 6, 1, 193, 225, 4, 230, 210, 8, 2, 1, 193, 225, 4, - 230, 210, 8, 6, 1, 193, 225, 4, 252, 46, 8, 2, 1, 193, 225, 4, 252, 46, - 8, 6, 1, 193, 225, 4, 237, 42, 8, 2, 1, 193, 225, 4, 237, 42, 8, 6, 1, - 193, 225, 4, 75, 58, 8, 2, 1, 193, 225, 4, 75, 58, 8, 6, 1, 193, 225, 4, - 75, 60, 8, 2, 1, 193, 225, 4, 75, 60, 8, 6, 1, 192, 236, 4, 75, 58, 8, 2, - 1, 192, 236, 4, 75, 58, 8, 6, 1, 192, 236, 4, 237, 42, 8, 2, 1, 192, 236, - 4, 237, 42, 8, 6, 1, 192, 160, 4, 75, 58, 8, 2, 1, 192, 160, 4, 75, 58, - 8, 6, 1, 191, 167, 4, 243, 1, 8, 2, 1, 191, 167, 4, 243, 1, 8, 6, 1, 191, - 167, 4, 75, 60, 8, 2, 1, 191, 167, 4, 75, 60, 8, 6, 1, 191, 167, 4, 219, - 113, 60, 8, 2, 1, 191, 167, 4, 219, 113, 60, 8, 2, 1, 230, 117, 4, 219, - 113, 60, 8, 2, 1, 200, 44, 4, 237, 42, 8, 2, 1, 193, 225, 4, 206, 189, - 58, 8, 2, 1, 192, 160, 4, 206, 189, 58, 8, 2, 1, 42, 4, 50, 132, 206, - 188, 8, 2, 1, 179, 206, 9, 4, 75, 58, 8, 2, 1, 179, 206, 9, 4, 237, 39, - 106, 8, 2, 1, 179, 206, 9, 4, 137, 106, 8, 6, 1, 203, 127, 206, 8, 8, 2, - 1, 237, 106, 8, 6, 1, 42, 4, 75, 60, 8, 2, 1, 42, 4, 75, 60, 8, 6, 1, 42, - 4, 228, 251, 58, 8, 2, 1, 42, 4, 228, 251, 58, 8, 6, 1, 42, 4, 243, 2, - 23, 252, 46, 8, 2, 1, 42, 4, 243, 2, 23, 252, 46, 8, 6, 1, 42, 4, 243, 2, - 23, 230, 210, 8, 2, 1, 42, 4, 243, 2, 23, 230, 210, 8, 6, 1, 42, 4, 243, - 2, 23, 228, 251, 58, 8, 2, 1, 42, 4, 243, 2, 23, 228, 251, 58, 8, 6, 1, - 42, 4, 243, 2, 23, 198, 152, 8, 2, 1, 42, 4, 243, 2, 23, 198, 152, 8, 6, - 1, 42, 4, 243, 2, 23, 75, 60, 8, 2, 1, 42, 4, 243, 2, 23, 75, 60, 8, 6, - 1, 42, 4, 248, 37, 23, 252, 46, 8, 2, 1, 42, 4, 248, 37, 23, 252, 46, 8, - 6, 1, 42, 4, 248, 37, 23, 230, 210, 8, 2, 1, 42, 4, 248, 37, 23, 230, - 210, 8, 6, 1, 42, 4, 248, 37, 23, 228, 251, 58, 8, 2, 1, 42, 4, 248, 37, - 23, 228, 251, 58, 8, 6, 1, 42, 4, 248, 37, 23, 198, 152, 8, 2, 1, 42, 4, - 248, 37, 23, 198, 152, 8, 6, 1, 42, 4, 248, 37, 23, 75, 60, 8, 2, 1, 42, - 4, 248, 37, 23, 75, 60, 8, 6, 1, 235, 15, 4, 75, 60, 8, 2, 1, 235, 15, 4, - 75, 60, 8, 6, 1, 235, 15, 4, 228, 251, 58, 8, 2, 1, 235, 15, 4, 228, 251, - 58, 8, 6, 1, 235, 15, 4, 198, 152, 8, 2, 1, 235, 15, 4, 198, 152, 8, 6, - 1, 235, 15, 4, 243, 2, 23, 252, 46, 8, 2, 1, 235, 15, 4, 243, 2, 23, 252, - 46, 8, 6, 1, 235, 15, 4, 243, 2, 23, 230, 210, 8, 2, 1, 235, 15, 4, 243, - 2, 23, 230, 210, 8, 6, 1, 235, 15, 4, 243, 2, 23, 228, 251, 58, 8, 2, 1, - 235, 15, 4, 243, 2, 23, 228, 251, 58, 8, 6, 1, 235, 15, 4, 243, 2, 23, - 198, 152, 8, 2, 1, 235, 15, 4, 243, 2, 23, 198, 152, 8, 6, 1, 235, 15, 4, - 243, 2, 23, 75, 60, 8, 2, 1, 235, 15, 4, 243, 2, 23, 75, 60, 8, 6, 1, - 228, 74, 4, 228, 251, 58, 8, 2, 1, 228, 74, 4, 228, 251, 58, 8, 6, 1, - 228, 74, 4, 75, 60, 8, 2, 1, 228, 74, 4, 75, 60, 8, 6, 1, 187, 4, 75, 60, - 8, 2, 1, 187, 4, 75, 60, 8, 6, 1, 187, 4, 228, 251, 58, 8, 2, 1, 187, 4, - 228, 251, 58, 8, 6, 1, 187, 4, 243, 2, 23, 252, 46, 8, 2, 1, 187, 4, 243, - 2, 23, 252, 46, 8, 6, 1, 187, 4, 243, 2, 23, 230, 210, 8, 2, 1, 187, 4, - 243, 2, 23, 230, 210, 8, 6, 1, 187, 4, 243, 2, 23, 228, 251, 58, 8, 2, 1, - 187, 4, 243, 2, 23, 228, 251, 58, 8, 6, 1, 187, 4, 243, 2, 23, 198, 152, - 8, 2, 1, 187, 4, 243, 2, 23, 198, 152, 8, 6, 1, 187, 4, 243, 2, 23, 75, - 60, 8, 2, 1, 187, 4, 243, 2, 23, 75, 60, 8, 6, 1, 187, 4, 228, 188, 23, - 252, 46, 8, 2, 1, 187, 4, 228, 188, 23, 252, 46, 8, 6, 1, 187, 4, 228, - 188, 23, 230, 210, 8, 2, 1, 187, 4, 228, 188, 23, 230, 210, 8, 6, 1, 187, - 4, 228, 188, 23, 228, 251, 58, 8, 2, 1, 187, 4, 228, 188, 23, 228, 251, - 58, 8, 6, 1, 187, 4, 228, 188, 23, 198, 152, 8, 2, 1, 187, 4, 228, 188, - 23, 198, 152, 8, 6, 1, 187, 4, 228, 188, 23, 75, 60, 8, 2, 1, 187, 4, - 228, 188, 23, 75, 60, 8, 6, 1, 126, 4, 75, 60, 8, 2, 1, 126, 4, 75, 60, - 8, 6, 1, 126, 4, 228, 251, 58, 8, 2, 1, 126, 4, 228, 251, 58, 8, 6, 1, - 126, 4, 228, 188, 23, 252, 46, 8, 2, 1, 126, 4, 228, 188, 23, 252, 46, 8, - 6, 1, 126, 4, 228, 188, 23, 230, 210, 8, 2, 1, 126, 4, 228, 188, 23, 230, - 210, 8, 6, 1, 126, 4, 228, 188, 23, 228, 251, 58, 8, 2, 1, 126, 4, 228, - 188, 23, 228, 251, 58, 8, 6, 1, 126, 4, 228, 188, 23, 198, 152, 8, 2, 1, - 126, 4, 228, 188, 23, 198, 152, 8, 6, 1, 126, 4, 228, 188, 23, 75, 60, 8, - 2, 1, 126, 4, 228, 188, 23, 75, 60, 8, 6, 1, 192, 160, 4, 230, 210, 8, 2, - 1, 192, 160, 4, 230, 210, 8, 6, 1, 192, 160, 4, 75, 60, 8, 2, 1, 192, - 160, 4, 75, 60, 8, 6, 1, 192, 160, 4, 228, 251, 58, 8, 2, 1, 192, 160, 4, - 228, 251, 58, 8, 6, 1, 192, 160, 4, 198, 152, 8, 2, 1, 192, 160, 4, 198, - 152, 8, 6, 1, 216, 83, 219, 74, 8, 2, 1, 216, 83, 219, 74, 8, 6, 1, 216, - 83, 196, 12, 8, 2, 1, 216, 83, 196, 12, 8, 6, 1, 192, 160, 4, 219, 4, 8, - 2, 1, 192, 160, 4, 219, 4, 35, 2, 1, 251, 161, 4, 208, 169, 35, 2, 1, - 251, 161, 4, 237, 212, 35, 2, 1, 251, 161, 4, 208, 170, 23, 195, 169, 35, - 2, 1, 251, 161, 4, 237, 213, 23, 195, 169, 35, 2, 1, 251, 161, 4, 208, - 170, 23, 210, 243, 35, 2, 1, 251, 161, 4, 237, 213, 23, 210, 243, 35, 2, - 1, 251, 161, 4, 208, 170, 23, 210, 4, 35, 2, 1, 251, 161, 4, 237, 213, - 23, 210, 4, 35, 6, 1, 251, 161, 4, 208, 169, 35, 6, 1, 251, 161, 4, 237, - 212, 35, 6, 1, 251, 161, 4, 208, 170, 23, 195, 169, 35, 6, 1, 251, 161, - 4, 237, 213, 23, 195, 169, 35, 6, 1, 251, 161, 4, 208, 170, 23, 210, 243, - 35, 6, 1, 251, 161, 4, 237, 213, 23, 210, 243, 35, 6, 1, 251, 161, 4, - 208, 170, 23, 210, 4, 35, 6, 1, 251, 161, 4, 237, 213, 23, 210, 4, 35, 2, - 1, 234, 48, 4, 208, 169, 35, 2, 1, 234, 48, 4, 237, 212, 35, 2, 1, 234, - 48, 4, 208, 170, 23, 195, 169, 35, 2, 1, 234, 48, 4, 237, 213, 23, 195, - 169, 35, 2, 1, 234, 48, 4, 208, 170, 23, 210, 243, 35, 2, 1, 234, 48, 4, - 237, 213, 23, 210, 243, 35, 6, 1, 234, 48, 4, 208, 169, 35, 6, 1, 234, - 48, 4, 237, 212, 35, 6, 1, 234, 48, 4, 208, 170, 23, 195, 169, 35, 6, 1, - 234, 48, 4, 237, 213, 23, 195, 169, 35, 6, 1, 234, 48, 4, 208, 170, 23, - 210, 243, 35, 6, 1, 234, 48, 4, 237, 213, 23, 210, 243, 35, 2, 1, 233, - 254, 4, 208, 169, 35, 2, 1, 233, 254, 4, 237, 212, 35, 2, 1, 233, 254, 4, - 208, 170, 23, 195, 169, 35, 2, 1, 233, 254, 4, 237, 213, 23, 195, 169, - 35, 2, 1, 233, 254, 4, 208, 170, 23, 210, 243, 35, 2, 1, 233, 254, 4, - 237, 213, 23, 210, 243, 35, 2, 1, 233, 254, 4, 208, 170, 23, 210, 4, 35, - 2, 1, 233, 254, 4, 237, 213, 23, 210, 4, 35, 6, 1, 233, 254, 4, 208, 169, - 35, 6, 1, 233, 254, 4, 237, 212, 35, 6, 1, 233, 254, 4, 208, 170, 23, - 195, 169, 35, 6, 1, 233, 254, 4, 237, 213, 23, 195, 169, 35, 6, 1, 233, - 254, 4, 208, 170, 23, 210, 243, 35, 6, 1, 233, 254, 4, 237, 213, 23, 210, - 243, 35, 6, 1, 233, 254, 4, 208, 170, 23, 210, 4, 35, 6, 1, 233, 254, 4, - 237, 213, 23, 210, 4, 35, 2, 1, 223, 84, 4, 208, 169, 35, 2, 1, 223, 84, - 4, 237, 212, 35, 2, 1, 223, 84, 4, 208, 170, 23, 195, 169, 35, 2, 1, 223, - 84, 4, 237, 213, 23, 195, 169, 35, 2, 1, 223, 84, 4, 208, 170, 23, 210, - 243, 35, 2, 1, 223, 84, 4, 237, 213, 23, 210, 243, 35, 2, 1, 223, 84, 4, - 208, 170, 23, 210, 4, 35, 2, 1, 223, 84, 4, 237, 213, 23, 210, 4, 35, 6, - 1, 223, 84, 4, 208, 169, 35, 6, 1, 223, 84, 4, 237, 212, 35, 6, 1, 223, - 84, 4, 208, 170, 23, 195, 169, 35, 6, 1, 223, 84, 4, 237, 213, 23, 195, - 169, 35, 6, 1, 223, 84, 4, 208, 170, 23, 210, 243, 35, 6, 1, 223, 84, 4, - 237, 213, 23, 210, 243, 35, 6, 1, 223, 84, 4, 208, 170, 23, 210, 4, 35, - 6, 1, 223, 84, 4, 237, 213, 23, 210, 4, 35, 2, 1, 211, 108, 4, 208, 169, - 35, 2, 1, 211, 108, 4, 237, 212, 35, 2, 1, 211, 108, 4, 208, 170, 23, - 195, 169, 35, 2, 1, 211, 108, 4, 237, 213, 23, 195, 169, 35, 2, 1, 211, - 108, 4, 208, 170, 23, 210, 243, 35, 2, 1, 211, 108, 4, 237, 213, 23, 210, - 243, 35, 6, 1, 211, 108, 4, 208, 169, 35, 6, 1, 211, 108, 4, 237, 212, - 35, 6, 1, 211, 108, 4, 208, 170, 23, 195, 169, 35, 6, 1, 211, 108, 4, - 237, 213, 23, 195, 169, 35, 6, 1, 211, 108, 4, 208, 170, 23, 210, 243, - 35, 6, 1, 211, 108, 4, 237, 213, 23, 210, 243, 35, 2, 1, 196, 71, 4, 208, - 169, 35, 2, 1, 196, 71, 4, 237, 212, 35, 2, 1, 196, 71, 4, 208, 170, 23, - 195, 169, 35, 2, 1, 196, 71, 4, 237, 213, 23, 195, 169, 35, 2, 1, 196, - 71, 4, 208, 170, 23, 210, 243, 35, 2, 1, 196, 71, 4, 237, 213, 23, 210, - 243, 35, 2, 1, 196, 71, 4, 208, 170, 23, 210, 4, 35, 2, 1, 196, 71, 4, - 237, 213, 23, 210, 4, 35, 6, 1, 196, 71, 4, 237, 212, 35, 6, 1, 196, 71, - 4, 237, 213, 23, 195, 169, 35, 6, 1, 196, 71, 4, 237, 213, 23, 210, 243, - 35, 6, 1, 196, 71, 4, 237, 213, 23, 210, 4, 35, 2, 1, 211, 111, 4, 208, - 169, 35, 2, 1, 211, 111, 4, 237, 212, 35, 2, 1, 211, 111, 4, 208, 170, - 23, 195, 169, 35, 2, 1, 211, 111, 4, 237, 213, 23, 195, 169, 35, 2, 1, - 211, 111, 4, 208, 170, 23, 210, 243, 35, 2, 1, 211, 111, 4, 237, 213, 23, - 210, 243, 35, 2, 1, 211, 111, 4, 208, 170, 23, 210, 4, 35, 2, 1, 211, - 111, 4, 237, 213, 23, 210, 4, 35, 6, 1, 211, 111, 4, 208, 169, 35, 6, 1, - 211, 111, 4, 237, 212, 35, 6, 1, 211, 111, 4, 208, 170, 23, 195, 169, 35, - 6, 1, 211, 111, 4, 237, 213, 23, 195, 169, 35, 6, 1, 211, 111, 4, 208, - 170, 23, 210, 243, 35, 6, 1, 211, 111, 4, 237, 213, 23, 210, 243, 35, 6, - 1, 211, 111, 4, 208, 170, 23, 210, 4, 35, 6, 1, 211, 111, 4, 237, 213, - 23, 210, 4, 35, 2, 1, 251, 161, 4, 195, 169, 35, 2, 1, 251, 161, 4, 210, - 243, 35, 2, 1, 234, 48, 4, 195, 169, 35, 2, 1, 234, 48, 4, 210, 243, 35, - 2, 1, 233, 254, 4, 195, 169, 35, 2, 1, 233, 254, 4, 210, 243, 35, 2, 1, - 223, 84, 4, 195, 169, 35, 2, 1, 223, 84, 4, 210, 243, 35, 2, 1, 211, 108, - 4, 195, 169, 35, 2, 1, 211, 108, 4, 210, 243, 35, 2, 1, 196, 71, 4, 195, - 169, 35, 2, 1, 196, 71, 4, 210, 243, 35, 2, 1, 211, 111, 4, 195, 169, 35, - 2, 1, 211, 111, 4, 210, 243, 35, 2, 1, 251, 161, 4, 208, 170, 23, 191, - 233, 35, 2, 1, 251, 161, 4, 237, 213, 23, 191, 233, 35, 2, 1, 251, 161, - 4, 208, 170, 23, 195, 170, 23, 191, 233, 35, 2, 1, 251, 161, 4, 237, 213, - 23, 195, 170, 23, 191, 233, 35, 2, 1, 251, 161, 4, 208, 170, 23, 210, - 244, 23, 191, 233, 35, 2, 1, 251, 161, 4, 237, 213, 23, 210, 244, 23, - 191, 233, 35, 2, 1, 251, 161, 4, 208, 170, 23, 210, 5, 23, 191, 233, 35, - 2, 1, 251, 161, 4, 237, 213, 23, 210, 5, 23, 191, 233, 35, 6, 1, 251, - 161, 4, 208, 170, 23, 208, 184, 35, 6, 1, 251, 161, 4, 237, 213, 23, 208, - 184, 35, 6, 1, 251, 161, 4, 208, 170, 23, 195, 170, 23, 208, 184, 35, 6, - 1, 251, 161, 4, 237, 213, 23, 195, 170, 23, 208, 184, 35, 6, 1, 251, 161, - 4, 208, 170, 23, 210, 244, 23, 208, 184, 35, 6, 1, 251, 161, 4, 237, 213, - 23, 210, 244, 23, 208, 184, 35, 6, 1, 251, 161, 4, 208, 170, 23, 210, 5, - 23, 208, 184, 35, 6, 1, 251, 161, 4, 237, 213, 23, 210, 5, 23, 208, 184, - 35, 2, 1, 233, 254, 4, 208, 170, 23, 191, 233, 35, 2, 1, 233, 254, 4, - 237, 213, 23, 191, 233, 35, 2, 1, 233, 254, 4, 208, 170, 23, 195, 170, - 23, 191, 233, 35, 2, 1, 233, 254, 4, 237, 213, 23, 195, 170, 23, 191, - 233, 35, 2, 1, 233, 254, 4, 208, 170, 23, 210, 244, 23, 191, 233, 35, 2, - 1, 233, 254, 4, 237, 213, 23, 210, 244, 23, 191, 233, 35, 2, 1, 233, 254, - 4, 208, 170, 23, 210, 5, 23, 191, 233, 35, 2, 1, 233, 254, 4, 237, 213, - 23, 210, 5, 23, 191, 233, 35, 6, 1, 233, 254, 4, 208, 170, 23, 208, 184, - 35, 6, 1, 233, 254, 4, 237, 213, 23, 208, 184, 35, 6, 1, 233, 254, 4, - 208, 170, 23, 195, 170, 23, 208, 184, 35, 6, 1, 233, 254, 4, 237, 213, - 23, 195, 170, 23, 208, 184, 35, 6, 1, 233, 254, 4, 208, 170, 23, 210, - 244, 23, 208, 184, 35, 6, 1, 233, 254, 4, 237, 213, 23, 210, 244, 23, - 208, 184, 35, 6, 1, 233, 254, 4, 208, 170, 23, 210, 5, 23, 208, 184, 35, - 6, 1, 233, 254, 4, 237, 213, 23, 210, 5, 23, 208, 184, 35, 2, 1, 211, - 111, 4, 208, 170, 23, 191, 233, 35, 2, 1, 211, 111, 4, 237, 213, 23, 191, - 233, 35, 2, 1, 211, 111, 4, 208, 170, 23, 195, 170, 23, 191, 233, 35, 2, - 1, 211, 111, 4, 237, 213, 23, 195, 170, 23, 191, 233, 35, 2, 1, 211, 111, - 4, 208, 170, 23, 210, 244, 23, 191, 233, 35, 2, 1, 211, 111, 4, 237, 213, - 23, 210, 244, 23, 191, 233, 35, 2, 1, 211, 111, 4, 208, 170, 23, 210, 5, - 23, 191, 233, 35, 2, 1, 211, 111, 4, 237, 213, 23, 210, 5, 23, 191, 233, - 35, 6, 1, 211, 111, 4, 208, 170, 23, 208, 184, 35, 6, 1, 211, 111, 4, - 237, 213, 23, 208, 184, 35, 6, 1, 211, 111, 4, 208, 170, 23, 195, 170, - 23, 208, 184, 35, 6, 1, 211, 111, 4, 237, 213, 23, 195, 170, 23, 208, - 184, 35, 6, 1, 211, 111, 4, 208, 170, 23, 210, 244, 23, 208, 184, 35, 6, - 1, 211, 111, 4, 237, 213, 23, 210, 244, 23, 208, 184, 35, 6, 1, 211, 111, - 4, 208, 170, 23, 210, 5, 23, 208, 184, 35, 6, 1, 211, 111, 4, 237, 213, - 23, 210, 5, 23, 208, 184, 35, 2, 1, 251, 161, 4, 194, 254, 35, 2, 1, 251, - 161, 4, 217, 146, 35, 2, 1, 251, 161, 4, 195, 170, 23, 191, 233, 35, 2, - 1, 251, 161, 4, 191, 233, 35, 2, 1, 251, 161, 4, 210, 244, 23, 191, 233, - 35, 2, 1, 251, 161, 4, 210, 4, 35, 2, 1, 251, 161, 4, 210, 5, 23, 191, - 233, 35, 6, 1, 251, 161, 4, 194, 254, 35, 6, 1, 251, 161, 4, 217, 146, - 35, 6, 1, 251, 161, 4, 195, 169, 35, 6, 1, 251, 161, 4, 210, 243, 35, 6, - 1, 251, 161, 4, 208, 184, 35, 221, 30, 35, 208, 184, 35, 208, 169, 35, - 210, 4, 35, 237, 36, 23, 210, 4, 35, 2, 1, 233, 254, 4, 195, 170, 23, - 191, 233, 35, 2, 1, 233, 254, 4, 191, 233, 35, 2, 1, 233, 254, 4, 210, - 244, 23, 191, 233, 35, 2, 1, 233, 254, 4, 210, 4, 35, 2, 1, 233, 254, 4, - 210, 5, 23, 191, 233, 35, 6, 1, 234, 48, 4, 195, 169, 35, 6, 1, 234, 48, - 4, 210, 243, 35, 6, 1, 233, 254, 4, 195, 169, 35, 6, 1, 233, 254, 4, 210, - 243, 35, 6, 1, 233, 254, 4, 208, 184, 35, 208, 170, 23, 195, 169, 35, - 208, 170, 23, 210, 243, 35, 208, 170, 23, 210, 4, 35, 2, 1, 223, 84, 4, - 194, 254, 35, 2, 1, 223, 84, 4, 217, 146, 35, 2, 1, 223, 84, 4, 237, 36, - 23, 195, 169, 35, 2, 1, 223, 84, 4, 237, 36, 23, 210, 243, 35, 2, 1, 223, - 84, 4, 210, 4, 35, 2, 1, 223, 84, 4, 237, 36, 23, 210, 4, 35, 6, 1, 223, - 84, 4, 194, 254, 35, 6, 1, 223, 84, 4, 217, 146, 35, 6, 1, 223, 84, 4, - 195, 169, 35, 6, 1, 223, 84, 4, 210, 243, 35, 237, 213, 23, 195, 169, 35, - 237, 213, 23, 210, 243, 35, 237, 213, 23, 210, 4, 35, 2, 1, 196, 71, 4, - 194, 254, 35, 2, 1, 196, 71, 4, 217, 146, 35, 2, 1, 196, 71, 4, 237, 36, - 23, 195, 169, 35, 2, 1, 196, 71, 4, 237, 36, 23, 210, 243, 35, 2, 1, 207, - 4, 4, 208, 169, 35, 2, 1, 207, 4, 4, 237, 212, 35, 2, 1, 196, 71, 4, 210, - 4, 35, 2, 1, 196, 71, 4, 237, 36, 23, 210, 4, 35, 6, 1, 196, 71, 4, 194, - 254, 35, 6, 1, 196, 71, 4, 217, 146, 35, 6, 1, 196, 71, 4, 195, 169, 35, - 6, 1, 196, 71, 4, 210, 243, 35, 6, 1, 207, 4, 4, 237, 212, 35, 237, 36, - 23, 195, 169, 35, 237, 36, 23, 210, 243, 35, 195, 169, 35, 2, 1, 211, - 111, 4, 195, 170, 23, 191, 233, 35, 2, 1, 211, 111, 4, 191, 233, 35, 2, - 1, 211, 111, 4, 210, 244, 23, 191, 233, 35, 2, 1, 211, 111, 4, 210, 4, - 35, 2, 1, 211, 111, 4, 210, 5, 23, 191, 233, 35, 6, 1, 211, 108, 4, 195, - 169, 35, 6, 1, 211, 108, 4, 210, 243, 35, 6, 1, 211, 111, 4, 195, 169, - 35, 6, 1, 211, 111, 4, 210, 243, 35, 6, 1, 211, 111, 4, 208, 184, 35, - 210, 243, 35, 237, 212, 234, 104, 208, 30, 234, 115, 208, 30, 234, 104, - 201, 247, 234, 115, 201, 247, 198, 219, 201, 247, 232, 126, 201, 247, - 202, 134, 201, 247, 233, 13, 201, 247, 208, 152, 201, 247, 199, 4, 201, - 247, 230, 79, 201, 247, 191, 78, 193, 75, 201, 247, 191, 78, 193, 75, - 213, 29, 191, 78, 193, 75, 222, 196, 219, 215, 77, 206, 199, 77, 228, 88, - 213, 30, 228, 88, 233, 13, 237, 215, 234, 104, 237, 215, 234, 115, 237, - 215, 228, 241, 164, 55, 81, 219, 112, 55, 130, 219, 112, 45, 202, 170, - 207, 252, 77, 50, 202, 170, 207, 252, 77, 202, 170, 218, 240, 207, 252, - 77, 202, 170, 229, 132, 207, 252, 77, 45, 55, 207, 252, 77, 50, 55, 207, - 252, 77, 55, 218, 240, 207, 252, 77, 55, 229, 132, 207, 252, 77, 238, 14, - 55, 238, 14, 247, 248, 197, 238, 247, 248, 91, 75, 219, 236, 105, 75, - 219, 236, 228, 241, 234, 120, 228, 86, 209, 61, 219, 113, 204, 10, 210, - 128, 204, 10, 219, 215, 234, 113, 206, 199, 234, 113, 209, 34, 236, 232, - 232, 144, 219, 215, 210, 252, 206, 199, 210, 252, 214, 215, 213, 37, 201, - 247, 210, 14, 216, 50, 56, 210, 14, 199, 96, 198, 230, 56, 208, 215, 55, - 208, 215, 197, 225, 208, 215, 207, 18, 208, 215, 207, 18, 55, 208, 215, - 207, 18, 197, 225, 208, 215, 247, 96, 202, 170, 219, 219, 251, 116, 207, - 252, 77, 202, 170, 206, 203, 251, 116, 207, 252, 77, 207, 83, 77, 55, - 233, 216, 77, 223, 102, 210, 254, 196, 100, 246, 240, 198, 178, 247, 97, - 223, 119, 209, 61, 250, 191, 228, 89, 247, 248, 232, 118, 202, 97, 45, - 51, 248, 54, 4, 208, 7, 50, 51, 248, 54, 4, 208, 7, 55, 208, 13, 77, 208, - 13, 233, 216, 77, 233, 216, 208, 13, 77, 198, 128, 3, 233, 255, 207, 18, - 209, 142, 56, 62, 118, 247, 248, 62, 96, 247, 248, 130, 250, 193, 207, - 18, 204, 25, 242, 220, 196, 77, 105, 250, 192, 251, 178, 195, 84, 242, - 72, 216, 35, 56, 200, 129, 237, 215, 223, 93, 196, 100, 232, 187, 208, - 152, 77, 115, 75, 208, 151, 208, 26, 208, 215, 232, 128, 75, 208, 151, - 232, 226, 75, 208, 151, 105, 75, 208, 151, 232, 128, 75, 77, 235, 138, - 238, 217, 197, 237, 81, 232, 128, 236, 138, 216, 213, 13, 201, 247, 193, - 23, 222, 196, 232, 77, 251, 44, 223, 91, 198, 144, 223, 91, 204, 10, 223, - 91, 209, 81, 219, 215, 223, 59, 206, 199, 223, 59, 232, 238, 201, 14, - 223, 59, 209, 34, 236, 232, 223, 59, 223, 132, 200, 75, 200, 147, 252, - 49, 200, 75, 200, 147, 223, 132, 9, 232, 146, 203, 133, 252, 49, 9, 232, - 146, 203, 133, 214, 208, 17, 203, 134, 213, 33, 17, 203, 134, 200, 182, - 191, 77, 200, 182, 8, 2, 1, 68, 200, 182, 134, 200, 182, 149, 200, 182, - 169, 200, 182, 175, 200, 182, 171, 200, 182, 178, 200, 182, 108, 56, 200, - 182, 216, 34, 200, 182, 234, 43, 56, 200, 182, 45, 210, 113, 200, 182, - 50, 210, 113, 200, 182, 8, 2, 1, 215, 61, 200, 230, 191, 77, 200, 230, - 107, 200, 230, 109, 200, 230, 138, 200, 230, 134, 200, 230, 149, 200, - 230, 169, 200, 230, 175, 200, 230, 171, 200, 230, 178, 200, 230, 108, 56, - 200, 230, 216, 34, 200, 230, 234, 43, 56, 200, 230, 45, 210, 113, 200, - 230, 50, 210, 113, 8, 200, 230, 2, 1, 65, 8, 200, 230, 2, 1, 71, 8, 200, - 230, 2, 1, 74, 8, 200, 230, 2, 1, 192, 235, 8, 200, 230, 2, 1, 205, 86, - 8, 200, 230, 2, 1, 230, 116, 8, 200, 230, 2, 1, 222, 152, 8, 200, 230, 2, - 1, 172, 8, 200, 230, 2, 1, 218, 168, 8, 200, 230, 2, 1, 215, 61, 8, 200, - 230, 2, 1, 210, 236, 8, 200, 230, 2, 1, 206, 8, 8, 200, 230, 2, 1, 200, - 43, 233, 233, 56, 242, 84, 56, 238, 200, 56, 232, 106, 232, 111, 56, 219, - 91, 56, 216, 51, 56, 214, 234, 56, 209, 245, 56, 206, 36, 56, 193, 31, - 56, 214, 80, 203, 99, 56, 236, 149, 56, 233, 234, 56, 221, 135, 56, 197, - 81, 56, 235, 116, 56, 231, 138, 210, 27, 56, 209, 242, 56, 230, 174, 56, - 250, 153, 56, 228, 166, 56, 247, 37, 56, 219, 81, 198, 33, 56, 201, 226, - 56, 199, 93, 56, 223, 147, 206, 36, 56, 197, 60, 219, 91, 56, 213, 19, - 87, 56, 217, 88, 56, 206, 59, 56, 220, 9, 56, 248, 147, 56, 202, 22, 56, - 33, 45, 230, 13, 58, 33, 50, 230, 13, 58, 33, 179, 81, 219, 113, 210, - 255, 33, 203, 40, 81, 219, 113, 210, 255, 33, 251, 85, 64, 58, 33, 242, - 221, 64, 58, 33, 45, 64, 58, 33, 50, 64, 58, 33, 206, 189, 210, 255, 33, - 242, 221, 206, 189, 210, 255, 33, 251, 85, 206, 189, 210, 255, 33, 115, - 185, 58, 33, 232, 128, 185, 58, 33, 234, 99, 243, 10, 33, 234, 99, 201, - 190, 33, 234, 99, 237, 32, 33, 234, 99, 243, 11, 249, 141, 33, 45, 50, - 64, 58, 33, 234, 99, 205, 76, 33, 234, 99, 221, 218, 33, 234, 99, 196, - 68, 209, 58, 197, 241, 33, 207, 19, 202, 24, 210, 255, 33, 55, 81, 201, - 28, 210, 255, 33, 251, 95, 113, 33, 197, 225, 196, 102, 33, 193, 78, 248, - 29, 58, 33, 118, 64, 210, 255, 33, 179, 55, 202, 24, 210, 255, 33, 96, - 230, 13, 4, 181, 235, 118, 33, 118, 230, 13, 4, 181, 235, 118, 33, 45, - 64, 60, 33, 50, 64, 60, 33, 250, 194, 58, 252, 55, 211, 146, 252, 38, - 119, 199, 34, 200, 240, 235, 129, 6, 247, 193, 237, 125, 247, 27, 247, - 22, 219, 113, 113, 247, 98, 211, 146, 247, 152, 196, 112, 233, 235, 239, - 38, 205, 72, 237, 125, 233, 91, 27, 2, 232, 51, 27, 6, 230, 116, 248, - 137, 6, 230, 116, 235, 129, 6, 230, 116, 209, 103, 239, 38, 209, 103, - 239, 39, 139, 105, 209, 185, 27, 6, 68, 248, 137, 6, 68, 27, 6, 172, 27, - 2, 172, 220, 143, 78, 249, 88, 113, 235, 129, 6, 215, 61, 212, 132, 56, - 202, 5, 207, 95, 239, 5, 27, 6, 210, 236, 235, 129, 6, 210, 236, 235, - 129, 6, 208, 104, 27, 6, 146, 248, 137, 6, 146, 235, 129, 6, 146, 208, - 223, 199, 208, 207, 31, 204, 1, 77, 199, 107, 56, 198, 22, 87, 56, 195, - 136, 235, 129, 6, 191, 166, 211, 18, 56, 211, 135, 56, 223, 93, 211, 135, - 56, 248, 137, 6, 191, 166, 153, 35, 2, 1, 223, 83, 222, 3, 56, 251, 110, - 56, 27, 6, 250, 120, 248, 137, 6, 247, 193, 234, 4, 113, 27, 2, 71, 27, - 6, 71, 27, 6, 233, 175, 153, 6, 233, 175, 27, 6, 218, 168, 27, 2, 74, - 131, 113, 248, 215, 113, 231, 39, 113, 237, 254, 113, 223, 137, 202, 3, - 206, 122, 6, 208, 104, 233, 94, 56, 235, 129, 2, 209, 185, 235, 129, 2, - 231, 211, 235, 129, 6, 231, 211, 235, 129, 6, 209, 185, 235, 129, 215, - 60, 200, 201, 153, 49, 6, 232, 51, 153, 49, 6, 172, 207, 18, 49, 6, 172, - 153, 49, 6, 192, 159, 235, 129, 43, 6, 238, 127, 235, 129, 43, 2, 238, - 127, 235, 129, 43, 2, 71, 235, 129, 43, 2, 68, 235, 129, 43, 2, 223, 35, - 208, 188, 219, 112, 153, 251, 137, 210, 14, 56, 251, 210, 153, 2, 233, - 175, 16, 40, 205, 151, 202, 3, 193, 246, 232, 118, 91, 203, 243, 193, - 246, 232, 118, 91, 213, 167, 193, 246, 232, 118, 91, 199, 86, 193, 246, - 232, 118, 91, 199, 0, 193, 246, 232, 118, 105, 198, 253, 193, 246, 232, - 118, 91, 233, 18, 193, 246, 232, 118, 105, 233, 17, 193, 246, 232, 118, - 115, 233, 17, 193, 246, 232, 118, 232, 128, 233, 17, 193, 246, 232, 118, - 91, 202, 124, 193, 246, 232, 118, 232, 226, 202, 122, 193, 246, 232, 118, - 91, 234, 159, 193, 246, 232, 118, 115, 234, 157, 193, 246, 232, 118, 232, - 226, 234, 157, 193, 246, 232, 118, 203, 247, 234, 157, 232, 118, 212, - 133, 107, 206, 136, 212, 134, 107, 206, 136, 212, 134, 109, 206, 136, - 212, 134, 138, 206, 136, 212, 134, 134, 206, 136, 212, 134, 149, 206, - 136, 212, 134, 169, 206, 136, 212, 134, 175, 206, 136, 212, 134, 171, - 206, 136, 212, 134, 178, 206, 136, 212, 134, 199, 95, 206, 136, 212, 134, - 234, 127, 206, 136, 212, 134, 197, 37, 206, 136, 212, 134, 233, 15, 206, - 136, 212, 134, 91, 228, 140, 206, 136, 212, 134, 232, 226, 228, 140, 206, - 136, 212, 134, 91, 189, 2, 206, 136, 212, 134, 107, 2, 206, 136, 212, - 134, 109, 2, 206, 136, 212, 134, 138, 2, 206, 136, 212, 134, 134, 2, 206, - 136, 212, 134, 149, 2, 206, 136, 212, 134, 169, 2, 206, 136, 212, 134, - 175, 2, 206, 136, 212, 134, 171, 2, 206, 136, 212, 134, 178, 2, 206, 136, - 212, 134, 199, 95, 2, 206, 136, 212, 134, 234, 127, 2, 206, 136, 212, - 134, 197, 37, 2, 206, 136, 212, 134, 233, 15, 2, 206, 136, 212, 134, 91, - 228, 140, 2, 206, 136, 212, 134, 232, 226, 228, 140, 2, 206, 136, 212, - 134, 91, 189, 206, 136, 212, 134, 91, 198, 230, 247, 194, 238, 127, 206, - 136, 212, 134, 232, 226, 189, 206, 136, 212, 134, 199, 96, 189, 206, 136, - 212, 134, 207, 18, 91, 228, 140, 8, 2, 1, 207, 18, 247, 193, 206, 136, - 212, 134, 202, 136, 220, 4, 20, 206, 136, 212, 134, 233, 16, 234, 210, - 20, 206, 136, 212, 134, 233, 16, 189, 206, 136, 212, 134, 91, 228, 141, - 189, 193, 246, 232, 118, 191, 78, 198, 253, 153, 17, 109, 153, 17, 138, - 118, 57, 196, 66, 57, 96, 57, 235, 119, 57, 45, 50, 57, 133, 144, 57, - 186, 193, 105, 57, 186, 234, 204, 57, 202, 2, 234, 204, 57, 202, 2, 193, - 105, 57, 118, 64, 4, 106, 96, 64, 4, 106, 118, 193, 139, 57, 96, 193, - 139, 57, 118, 105, 229, 233, 57, 196, 66, 105, 229, 233, 57, 96, 105, - 229, 233, 57, 235, 119, 105, 229, 233, 57, 118, 64, 4, 199, 215, 96, 64, - 4, 199, 215, 118, 64, 232, 98, 164, 196, 66, 64, 232, 98, 164, 96, 64, - 232, 98, 164, 235, 119, 64, 232, 98, 164, 133, 144, 64, 4, 249, 74, 118, - 64, 4, 102, 96, 64, 4, 102, 118, 64, 4, 219, 4, 96, 64, 4, 219, 4, 45, - 50, 193, 139, 57, 45, 50, 64, 4, 106, 235, 119, 191, 21, 57, 196, 66, 64, - 4, 198, 136, 219, 214, 196, 66, 64, 4, 198, 136, 206, 197, 235, 119, 64, - 4, 198, 136, 219, 214, 235, 119, 64, 4, 198, 136, 206, 197, 96, 64, 4, - 239, 2, 235, 118, 235, 119, 64, 4, 239, 2, 219, 214, 251, 85, 198, 54, - 204, 28, 57, 242, 221, 198, 54, 204, 28, 57, 186, 193, 105, 64, 119, 179, - 164, 118, 64, 119, 249, 88, 139, 96, 64, 119, 164, 251, 85, 211, 77, 243, - 11, 57, 242, 221, 211, 77, 243, 11, 57, 118, 230, 13, 4, 181, 196, 65, - 118, 230, 13, 4, 181, 235, 118, 196, 66, 230, 13, 4, 181, 206, 197, 196, - 66, 230, 13, 4, 181, 219, 214, 96, 230, 13, 4, 181, 196, 65, 96, 230, 13, - 4, 181, 235, 118, 235, 119, 230, 13, 4, 181, 206, 197, 235, 119, 230, 13, - 4, 181, 219, 214, 96, 64, 139, 118, 57, 196, 66, 64, 118, 79, 235, 119, - 57, 118, 64, 139, 96, 57, 118, 210, 196, 250, 231, 196, 66, 210, 196, - 250, 231, 96, 210, 196, 250, 231, 235, 119, 210, 196, 250, 231, 118, 230, - 13, 139, 96, 230, 12, 96, 230, 13, 139, 118, 230, 12, 118, 55, 64, 4, - 106, 45, 50, 55, 64, 4, 106, 96, 55, 64, 4, 106, 118, 55, 57, 196, 66, - 55, 57, 96, 55, 57, 235, 119, 55, 57, 45, 50, 55, 57, 133, 144, 55, 57, - 186, 193, 105, 55, 57, 186, 234, 204, 55, 57, 202, 2, 234, 204, 55, 57, - 202, 2, 193, 105, 55, 57, 118, 197, 225, 57, 96, 197, 225, 57, 118, 201, - 183, 57, 96, 201, 183, 57, 196, 66, 64, 4, 55, 106, 235, 119, 64, 4, 55, - 106, 118, 237, 214, 57, 196, 66, 237, 214, 57, 96, 237, 214, 57, 235, - 119, 237, 214, 57, 118, 64, 119, 164, 96, 64, 119, 164, 118, 63, 57, 196, - 66, 63, 57, 96, 63, 57, 235, 119, 63, 57, 196, 66, 63, 64, 232, 98, 164, - 196, 66, 63, 64, 211, 105, 210, 52, 196, 66, 63, 64, 211, 105, 210, 53, - 4, 228, 241, 164, 196, 66, 63, 64, 211, 105, 210, 53, 4, 81, 164, 196, - 66, 63, 55, 57, 196, 66, 63, 55, 64, 211, 105, 210, 52, 96, 63, 64, 232, - 98, 193, 167, 186, 193, 105, 64, 119, 239, 1, 202, 2, 234, 204, 64, 119, - 239, 1, 133, 144, 63, 57, 50, 64, 4, 2, 243, 10, 235, 119, 64, 118, 79, - 196, 66, 57, 115, 96, 250, 231, 118, 64, 4, 81, 106, 96, 64, 4, 81, 106, - 45, 50, 64, 4, 81, 106, 118, 64, 4, 55, 81, 106, 96, 64, 4, 55, 81, 106, - 45, 50, 64, 4, 55, 81, 106, 118, 211, 74, 57, 96, 211, 74, 57, 45, 50, - 211, 74, 57, 40, 251, 174, 242, 68, 210, 105, 237, 16, 199, 24, 233, 211, - 199, 24, 236, 164, 213, 12, 233, 212, 234, 105, 203, 252, 223, 151, 214, - 245, 234, 132, 211, 146, 213, 12, 251, 133, 234, 132, 211, 146, 2, 234, - 132, 211, 146, 239, 32, 250, 220, 216, 190, 236, 164, 213, 12, 239, 34, - 250, 220, 216, 190, 2, 239, 32, 250, 220, 216, 190, 234, 95, 79, 208, - 190, 215, 60, 208, 200, 215, 60, 239, 9, 215, 60, 200, 201, 216, 35, 56, - 216, 33, 56, 75, 209, 81, 236, 200, 202, 97, 203, 253, 216, 34, 250, 194, - 211, 66, 206, 189, 211, 66, 247, 249, 211, 66, 51, 206, 128, 238, 191, - 206, 128, 232, 121, 206, 128, 208, 186, 159, 223, 139, 50, 251, 115, 251, - 115, 216, 226, 251, 115, 201, 225, 251, 115, 236, 203, 236, 164, 213, 12, - 236, 207, 210, 119, 159, 213, 12, 210, 119, 159, 219, 29, 251, 125, 219, - 29, 211, 56, 223, 99, 196, 92, 223, 113, 55, 223, 113, 197, 225, 223, - 113, 239, 26, 223, 113, 200, 171, 223, 113, 195, 11, 223, 113, 242, 221, - 223, 113, 242, 221, 239, 26, 223, 113, 251, 85, 239, 26, 223, 113, 199, - 23, 249, 3, 207, 126, 208, 187, 75, 216, 34, 233, 219, 231, 144, 208, - 187, 229, 0, 198, 153, 211, 66, 207, 18, 198, 152, 223, 93, 219, 245, - 206, 8, 202, 172, 193, 138, 193, 10, 208, 200, 213, 12, 198, 152, 216, - 35, 198, 152, 250, 186, 234, 45, 159, 213, 12, 250, 186, 234, 45, 159, - 251, 40, 234, 45, 159, 251, 40, 247, 218, 213, 12, 252, 48, 234, 45, 159, - 214, 105, 251, 40, 213, 21, 252, 48, 234, 45, 159, 251, 165, 234, 45, - 159, 213, 12, 251, 165, 234, 45, 159, 251, 165, 234, 45, 211, 57, 234, - 45, 159, 197, 225, 198, 152, 251, 175, 234, 45, 159, 234, 36, 159, 231, - 143, 234, 36, 159, 237, 17, 248, 209, 251, 42, 199, 34, 219, 120, 231, - 143, 234, 45, 159, 251, 40, 234, 45, 119, 211, 57, 199, 34, 223, 178, - 211, 146, 223, 178, 79, 211, 57, 251, 40, 234, 45, 159, 242, 84, 234, 42, - 234, 43, 242, 83, 206, 189, 223, 163, 234, 45, 159, 206, 189, 234, 45, - 159, 238, 250, 159, 234, 3, 234, 41, 159, 201, 103, 234, 42, 237, 107, - 234, 45, 159, 234, 45, 119, 247, 205, 237, 126, 216, 226, 247, 204, 208, - 11, 234, 45, 159, 213, 12, 234, 45, 159, 228, 17, 159, 213, 12, 228, 17, - 159, 201, 35, 234, 36, 159, 219, 180, 211, 57, 234, 45, 159, 230, 204, - 211, 57, 234, 45, 159, 219, 180, 139, 234, 45, 159, 230, 204, 139, 234, - 45, 159, 219, 180, 247, 218, 213, 12, 234, 45, 159, 230, 204, 247, 218, - 213, 12, 234, 45, 159, 215, 145, 219, 179, 215, 145, 230, 203, 248, 209, - 213, 12, 234, 36, 159, 213, 12, 219, 179, 213, 12, 230, 203, 214, 105, - 219, 180, 213, 21, 234, 45, 159, 214, 105, 230, 204, 213, 21, 234, 45, - 159, 219, 180, 211, 57, 234, 36, 159, 230, 204, 211, 57, 234, 36, 159, - 214, 105, 219, 180, 213, 21, 234, 36, 159, 214, 105, 230, 204, 213, 21, - 234, 36, 159, 219, 180, 211, 57, 230, 203, 230, 204, 211, 57, 219, 179, - 214, 105, 219, 180, 213, 21, 230, 203, 214, 105, 230, 204, 213, 21, 219, - 179, 208, 231, 200, 220, 208, 232, 211, 57, 234, 45, 159, 200, 221, 211, - 57, 234, 45, 159, 208, 232, 211, 57, 234, 36, 159, 200, 221, 211, 57, - 234, 36, 159, 236, 164, 213, 12, 208, 234, 236, 164, 213, 12, 200, 222, - 200, 229, 211, 146, 200, 181, 211, 146, 213, 12, 42, 200, 229, 211, 146, - 213, 12, 42, 200, 181, 211, 146, 200, 229, 79, 211, 57, 234, 45, 159, - 200, 181, 79, 211, 57, 234, 45, 159, 214, 105, 42, 200, 229, 79, 213, 21, - 234, 45, 159, 214, 105, 42, 200, 181, 79, 213, 21, 234, 45, 159, 200, - 229, 79, 4, 213, 12, 234, 45, 159, 200, 181, 79, 4, 213, 12, 234, 45, - 159, 215, 124, 215, 125, 215, 126, 215, 125, 196, 92, 51, 223, 178, 211, - 146, 51, 211, 46, 211, 146, 51, 223, 178, 79, 211, 57, 234, 45, 159, 51, - 211, 46, 79, 211, 57, 234, 45, 159, 51, 247, 111, 51, 238, 181, 47, 209, - 81, 47, 216, 34, 47, 198, 144, 47, 236, 200, 202, 97, 47, 75, 211, 66, - 47, 206, 189, 211, 66, 47, 250, 194, 211, 66, 47, 234, 42, 47, 237, 215, - 112, 209, 81, 112, 216, 34, 112, 198, 144, 112, 75, 211, 66, 50, 199, - 228, 45, 199, 228, 144, 199, 228, 133, 199, 228, 250, 197, 216, 1, 197, - 201, 232, 152, 197, 225, 81, 249, 88, 50, 197, 57, 55, 81, 249, 88, 55, - 50, 197, 57, 236, 164, 213, 12, 208, 179, 213, 12, 197, 201, 236, 164, - 213, 12, 232, 153, 214, 108, 55, 81, 249, 88, 55, 50, 197, 57, 208, 232, - 196, 105, 207, 65, 200, 221, 196, 105, 207, 65, 213, 18, 200, 244, 211, - 146, 239, 32, 250, 220, 213, 18, 200, 243, 213, 18, 200, 244, 79, 211, - 57, 234, 45, 159, 239, 32, 250, 220, 213, 18, 200, 244, 211, 57, 234, 45, - 159, 211, 46, 211, 146, 223, 178, 211, 146, 215, 131, 229, 189, 239, 43, - 217, 27, 223, 110, 192, 192, 214, 224, 213, 20, 50, 251, 116, 4, 251, 16, - 50, 197, 241, 215, 60, 219, 29, 251, 125, 215, 60, 219, 29, 211, 56, 215, - 60, 223, 99, 215, 60, 196, 92, 237, 33, 211, 66, 75, 211, 66, 201, 103, - 211, 66, 236, 200, 198, 144, 248, 63, 45, 213, 18, 233, 93, 204, 24, 208, - 200, 50, 213, 18, 233, 93, 204, 24, 208, 200, 45, 204, 24, 208, 200, 50, - 204, 24, 208, 200, 207, 18, 198, 153, 234, 42, 238, 171, 219, 29, 211, - 56, 238, 171, 219, 29, 251, 125, 55, 200, 228, 55, 200, 180, 55, 223, 99, - 55, 196, 92, 209, 115, 234, 45, 23, 210, 119, 159, 219, 180, 4, 236, 140, - 230, 204, 4, 236, 140, 195, 83, 215, 145, 219, 179, 195, 83, 215, 145, - 230, 203, 219, 180, 234, 45, 119, 211, 57, 230, 203, 230, 204, 234, 45, - 119, 211, 57, 219, 179, 234, 45, 119, 211, 57, 219, 179, 234, 45, 119, - 211, 57, 230, 203, 234, 45, 119, 211, 57, 208, 231, 234, 45, 119, 211, - 57, 200, 220, 236, 164, 213, 12, 208, 235, 211, 57, 234, 44, 236, 164, - 213, 12, 200, 223, 211, 57, 234, 44, 213, 12, 51, 223, 178, 79, 211, 57, - 234, 45, 159, 213, 12, 51, 211, 46, 79, 211, 57, 234, 45, 159, 51, 223, - 178, 79, 211, 57, 213, 12, 234, 45, 159, 51, 211, 46, 79, 211, 57, 213, - 12, 234, 45, 159, 219, 180, 247, 218, 213, 12, 234, 36, 159, 230, 204, - 247, 218, 213, 12, 234, 36, 159, 208, 232, 247, 218, 213, 12, 234, 36, - 159, 200, 221, 247, 218, 213, 12, 234, 36, 159, 213, 12, 213, 18, 200, - 244, 211, 146, 236, 164, 213, 12, 239, 34, 250, 220, 213, 18, 200, 243, - 213, 12, 213, 18, 200, 244, 79, 211, 57, 234, 45, 159, 236, 164, 213, 12, - 239, 34, 250, 220, 213, 18, 200, 244, 211, 57, 234, 44, 81, 234, 120, - 216, 82, 228, 241, 234, 120, 133, 50, 237, 39, 234, 120, 144, 50, 237, - 39, 234, 120, 234, 132, 79, 4, 179, 228, 241, 106, 234, 132, 79, 4, 81, - 249, 88, 250, 183, 234, 95, 79, 228, 241, 106, 2, 234, 132, 79, 4, 81, - 249, 88, 250, 183, 234, 95, 79, 228, 241, 106, 234, 132, 79, 4, 75, 58, - 234, 132, 79, 4, 211, 6, 2, 234, 132, 79, 4, 211, 6, 234, 132, 79, 4, - 196, 103, 234, 132, 79, 4, 105, 228, 241, 201, 15, 239, 32, 4, 179, 228, - 241, 106, 239, 32, 4, 81, 249, 88, 250, 183, 234, 95, 79, 228, 241, 106, - 2, 239, 32, 4, 81, 249, 88, 250, 183, 234, 95, 79, 228, 241, 106, 239, - 32, 4, 211, 6, 2, 239, 32, 4, 211, 6, 191, 167, 213, 10, 249, 131, 216, - 189, 237, 34, 56, 234, 135, 57, 228, 172, 133, 250, 235, 144, 250, 235, - 208, 194, 209, 248, 193, 135, 219, 112, 45, 247, 30, 50, 247, 30, 45, - 232, 193, 50, 232, 193, 248, 77, 50, 238, 219, 248, 77, 45, 238, 219, - 198, 54, 50, 238, 219, 198, 54, 45, 238, 219, 207, 18, 213, 12, 56, 51, - 218, 232, 251, 16, 205, 43, 205, 52, 199, 107, 207, 96, 209, 25, 223, - 144, 195, 56, 201, 190, 209, 108, 79, 223, 109, 56, 153, 213, 12, 56, - 193, 145, 228, 174, 198, 54, 45, 239, 1, 198, 54, 50, 239, 1, 248, 77, - 45, 239, 1, 248, 77, 50, 239, 1, 198, 54, 132, 223, 113, 248, 77, 132, - 223, 113, 232, 93, 202, 65, 133, 250, 236, 248, 210, 105, 228, 241, 249, - 76, 211, 59, 221, 222, 234, 32, 119, 199, 34, 183, 192, 236, 223, 163, - 42, 207, 93, 248, 62, 221, 220, 219, 219, 251, 116, 248, 53, 206, 203, - 251, 116, 248, 53, 234, 32, 119, 199, 34, 219, 224, 248, 221, 206, 188, - 238, 138, 251, 175, 250, 244, 200, 74, 198, 39, 206, 41, 236, 252, 211, - 47, 239, 48, 199, 181, 202, 81, 238, 246, 238, 245, 251, 59, 232, 75, 16, - 228, 67, 251, 59, 232, 75, 16, 201, 181, 208, 30, 251, 59, 232, 75, 16, - 208, 31, 234, 44, 251, 59, 232, 75, 16, 208, 31, 236, 207, 251, 59, 232, - 75, 16, 208, 31, 237, 32, 251, 59, 232, 75, 16, 208, 31, 222, 188, 251, - 59, 232, 75, 16, 208, 31, 243, 10, 251, 59, 232, 75, 16, 243, 11, 201, - 71, 251, 59, 232, 75, 16, 243, 11, 222, 188, 251, 59, 232, 75, 16, 202, - 98, 164, 251, 59, 232, 75, 16, 249, 142, 164, 251, 59, 232, 75, 16, 208, - 31, 202, 97, 251, 59, 232, 75, 16, 208, 31, 249, 141, 251, 59, 232, 75, - 16, 208, 31, 219, 179, 251, 59, 232, 75, 16, 208, 31, 230, 203, 251, 59, - 232, 75, 16, 118, 195, 176, 251, 59, 232, 75, 16, 96, 195, 176, 251, 59, - 232, 75, 16, 208, 31, 118, 57, 251, 59, 232, 75, 16, 208, 31, 96, 57, - 251, 59, 232, 75, 16, 243, 11, 249, 141, 251, 59, 232, 75, 16, 144, 199, - 229, 196, 103, 251, 59, 232, 75, 16, 237, 107, 201, 71, 251, 59, 232, 75, - 16, 208, 31, 144, 247, 96, 251, 59, 232, 75, 16, 208, 31, 237, 106, 251, - 59, 232, 75, 16, 144, 199, 229, 222, 188, 251, 59, 232, 75, 16, 196, 66, - 195, 176, 251, 59, 232, 75, 16, 208, 31, 196, 66, 57, 251, 59, 232, 75, - 16, 133, 199, 229, 211, 6, 251, 59, 232, 75, 16, 237, 119, 201, 71, 251, - 59, 232, 75, 16, 208, 31, 133, 247, 96, 251, 59, 232, 75, 16, 208, 31, - 237, 118, 251, 59, 232, 75, 16, 133, 199, 229, 222, 188, 251, 59, 232, - 75, 16, 235, 119, 195, 176, 251, 59, 232, 75, 16, 208, 31, 235, 119, 57, - 251, 59, 232, 75, 16, 207, 251, 196, 103, 251, 59, 232, 75, 16, 237, 107, - 196, 103, 251, 59, 232, 75, 16, 237, 33, 196, 103, 251, 59, 232, 75, 16, - 222, 189, 196, 103, 251, 59, 232, 75, 16, 243, 11, 196, 103, 251, 59, - 232, 75, 16, 133, 203, 53, 222, 188, 251, 59, 232, 75, 16, 207, 251, 208, - 30, 251, 59, 232, 75, 16, 243, 11, 201, 102, 251, 59, 232, 75, 16, 208, - 31, 242, 83, 251, 59, 232, 75, 16, 133, 199, 229, 237, 42, 251, 59, 232, - 75, 16, 237, 119, 237, 42, 251, 59, 232, 75, 16, 201, 103, 237, 42, 251, - 59, 232, 75, 16, 222, 189, 237, 42, 251, 59, 232, 75, 16, 243, 11, 237, - 42, 251, 59, 232, 75, 16, 144, 203, 53, 201, 71, 251, 59, 232, 75, 16, - 45, 203, 53, 201, 71, 251, 59, 232, 75, 16, 198, 153, 237, 42, 251, 59, - 232, 75, 16, 230, 204, 237, 42, 251, 59, 232, 75, 16, 242, 75, 164, 251, - 59, 232, 75, 16, 237, 119, 198, 152, 251, 59, 232, 75, 16, 191, 20, 251, - 59, 232, 75, 16, 201, 72, 198, 152, 251, 59, 232, 75, 16, 204, 26, 196, - 103, 251, 59, 232, 75, 16, 208, 31, 213, 12, 234, 44, 251, 59, 232, 75, - 16, 208, 31, 208, 12, 251, 59, 232, 75, 16, 144, 247, 97, 198, 152, 251, - 59, 232, 75, 16, 133, 247, 97, 198, 152, 251, 59, 232, 75, 16, 223, 83, - 251, 59, 232, 75, 16, 207, 3, 251, 59, 232, 75, 16, 211, 110, 251, 59, - 232, 75, 16, 251, 161, 196, 103, 251, 59, 232, 75, 16, 234, 48, 196, 103, - 251, 59, 232, 75, 16, 223, 84, 196, 103, 251, 59, 232, 75, 16, 211, 111, - 196, 103, 251, 59, 232, 75, 16, 251, 160, 213, 12, 243, 126, 77, 50, 251, - 116, 4, 235, 119, 191, 21, 57, 203, 21, 211, 77, 248, 62, 248, 236, 113, - 81, 219, 113, 4, 82, 236, 140, 223, 119, 113, 239, 27, 196, 101, 113, - 236, 225, 196, 101, 113, 234, 107, 113, 239, 63, 113, 63, 51, 4, 247, 22, - 81, 219, 112, 234, 78, 113, 251, 152, 221, 223, 113, 229, 202, 113, 47, - 228, 241, 249, 88, 4, 213, 9, 47, 197, 242, 235, 123, 248, 22, 243, 11, - 4, 213, 15, 57, 196, 99, 113, 215, 216, 113, 228, 84, 113, 211, 75, 230, - 115, 113, 211, 75, 220, 141, 113, 210, 93, 113, 210, 92, 113, 236, 234, - 238, 169, 16, 232, 146, 109, 202, 29, 113, 251, 59, 232, 75, 16, 208, 30, - 237, 138, 204, 11, 221, 223, 113, 208, 217, 210, 204, 214, 73, 210, 204, - 208, 212, 205, 77, 113, 242, 238, 205, 77, 113, 45, 210, 114, 116, 102, - 45, 210, 114, 233, 203, 45, 210, 114, 110, 102, 50, 210, 114, 116, 102, - 50, 210, 114, 233, 203, 50, 210, 114, 110, 102, 45, 51, 248, 54, 116, - 239, 1, 45, 51, 248, 54, 233, 203, 45, 51, 248, 54, 110, 239, 1, 50, 51, - 248, 54, 116, 239, 1, 50, 51, 248, 54, 233, 203, 50, 51, 248, 54, 110, - 239, 1, 45, 238, 171, 248, 54, 116, 102, 45, 238, 171, 248, 54, 82, 209, - 175, 45, 238, 171, 248, 54, 110, 102, 238, 171, 248, 54, 233, 203, 50, - 238, 171, 248, 54, 116, 102, 50, 238, 171, 248, 54, 82, 209, 175, 50, - 238, 171, 248, 54, 110, 102, 223, 114, 233, 203, 228, 241, 219, 113, 233, - 203, 116, 45, 211, 57, 110, 50, 238, 171, 248, 54, 205, 53, 116, 50, 211, - 57, 110, 45, 238, 171, 248, 54, 205, 53, 200, 202, 198, 53, 200, 202, - 248, 76, 198, 54, 51, 248, 53, 248, 77, 51, 248, 53, 248, 77, 51, 248, - 54, 139, 198, 54, 51, 248, 53, 48, 16, 248, 76, 45, 81, 111, 219, 112, - 50, 81, 111, 219, 112, 228, 241, 205, 97, 219, 111, 228, 241, 205, 97, - 219, 110, 228, 241, 205, 97, 219, 109, 228, 241, 205, 97, 219, 108, 237, - 97, 16, 156, 81, 23, 198, 54, 183, 237, 97, 16, 156, 81, 23, 248, 77, - 183, 237, 97, 16, 156, 81, 4, 243, 10, 237, 97, 16, 156, 144, 23, 228, - 241, 4, 243, 10, 237, 97, 16, 156, 133, 23, 228, 241, 4, 243, 10, 237, - 97, 16, 156, 81, 4, 197, 241, 237, 97, 16, 156, 144, 23, 228, 241, 4, - 197, 241, 237, 97, 16, 156, 133, 23, 228, 241, 4, 197, 241, 237, 97, 16, - 156, 81, 23, 193, 138, 237, 97, 16, 156, 144, 23, 228, 241, 4, 193, 138, - 237, 97, 16, 156, 133, 23, 228, 241, 4, 193, 138, 237, 97, 16, 156, 144, - 23, 228, 240, 237, 97, 16, 156, 133, 23, 228, 240, 237, 97, 16, 156, 81, - 23, 198, 54, 219, 224, 237, 97, 16, 156, 81, 23, 248, 77, 219, 224, 51, - 232, 159, 207, 23, 113, 234, 149, 113, 81, 219, 113, 233, 203, 216, 159, - 248, 36, 216, 159, 179, 139, 203, 39, 216, 159, 203, 40, 139, 219, 19, - 216, 159, 179, 139, 105, 203, 25, 216, 159, 105, 203, 26, 139, 219, 19, - 216, 159, 105, 203, 26, 222, 197, 216, 159, 197, 221, 216, 159, 199, 65, - 216, 159, 210, 22, 234, 208, 230, 188, 232, 69, 198, 54, 210, 113, 248, - 77, 210, 113, 198, 54, 238, 171, 248, 53, 248, 77, 238, 171, 248, 53, - 198, 54, 198, 42, 203, 103, 248, 53, 248, 77, 198, 42, 203, 103, 248, 53, - 63, 198, 5, 248, 221, 206, 189, 4, 243, 10, 201, 51, 232, 204, 252, 64, - 238, 168, 234, 134, 223, 99, 237, 138, 233, 207, 113, 62, 206, 203, 55, - 197, 241, 62, 219, 219, 55, 197, 241, 62, 196, 76, 55, 197, 241, 62, 235, - 122, 55, 197, 241, 62, 206, 203, 55, 197, 242, 4, 81, 164, 62, 219, 219, - 55, 197, 242, 4, 81, 164, 62, 206, 203, 197, 242, 4, 55, 81, 164, 251, - 201, 242, 222, 201, 58, 198, 145, 242, 222, 228, 175, 4, 232, 184, 205, - 140, 62, 216, 213, 219, 219, 197, 241, 62, 216, 213, 206, 203, 197, 241, - 62, 216, 213, 196, 76, 197, 241, 62, 216, 213, 235, 122, 197, 241, 55, - 81, 164, 62, 51, 40, 201, 63, 62, 243, 11, 40, 207, 97, 208, 255, 113, - 208, 255, 211, 103, 113, 208, 255, 211, 105, 113, 208, 255, 202, 93, 113, - 211, 168, 233, 194, 113, 16, 40, 212, 138, 16, 40, 201, 98, 79, 229, 232, - 16, 40, 201, 98, 79, 199, 53, 16, 40, 234, 95, 79, 199, 53, 16, 40, 234, - 95, 79, 198, 11, 16, 40, 234, 81, 16, 40, 252, 51, 16, 40, 248, 235, 16, - 40, 249, 140, 16, 40, 228, 241, 199, 230, 16, 40, 219, 113, 233, 50, 16, - 40, 81, 199, 230, 16, 40, 232, 146, 233, 50, 16, 40, 247, 88, 207, 22, - 16, 40, 203, 77, 211, 14, 16, 40, 203, 77, 223, 162, 16, 40, 237, 210, - 219, 103, 234, 14, 16, 40, 237, 75, 239, 22, 107, 16, 40, 237, 75, 239, - 22, 109, 16, 40, 237, 75, 239, 22, 138, 16, 40, 237, 75, 239, 22, 134, - 16, 40, 214, 106, 252, 51, 16, 40, 200, 69, 223, 228, 16, 40, 234, 95, - 79, 198, 12, 248, 129, 16, 40, 247, 126, 16, 40, 234, 95, 79, 216, 212, - 16, 40, 200, 226, 16, 40, 234, 14, 16, 40, 233, 7, 204, 10, 16, 40, 230, - 187, 204, 10, 16, 40, 207, 98, 204, 10, 16, 40, 196, 91, 204, 10, 16, 40, - 201, 247, 16, 40, 237, 116, 248, 133, 113, 211, 77, 248, 62, 16, 40, 214, - 76, 16, 40, 237, 117, 232, 146, 109, 16, 40, 200, 227, 232, 146, 109, - 211, 161, 102, 211, 161, 246, 252, 211, 161, 232, 149, 211, 161, 223, 93, - 232, 149, 211, 161, 248, 232, 248, 5, 211, 161, 248, 70, 198, 178, 211, - 161, 248, 48, 249, 93, 228, 15, 211, 161, 251, 139, 79, 243, 125, 211, - 161, 237, 215, 211, 161, 238, 157, 252, 55, 212, 136, 211, 161, 55, 249, - 141, 47, 17, 107, 47, 17, 109, 47, 17, 138, 47, 17, 134, 47, 17, 149, 47, - 17, 169, 47, 17, 175, 47, 17, 171, 47, 17, 178, 47, 31, 199, 95, 47, 31, - 234, 127, 47, 31, 197, 37, 47, 31, 198, 251, 47, 31, 232, 122, 47, 31, - 233, 19, 47, 31, 202, 130, 47, 31, 203, 244, 47, 31, 234, 161, 47, 31, - 213, 171, 47, 31, 197, 32, 127, 17, 107, 127, 17, 109, 127, 17, 138, 127, - 17, 134, 127, 17, 149, 127, 17, 169, 127, 17, 175, 127, 17, 171, 127, 17, - 178, 127, 31, 199, 95, 127, 31, 234, 127, 127, 31, 197, 37, 127, 31, 198, - 251, 127, 31, 232, 122, 127, 31, 233, 19, 127, 31, 202, 130, 127, 31, - 203, 244, 127, 31, 234, 161, 127, 31, 213, 171, 127, 31, 197, 32, 17, 91, - 232, 80, 201, 63, 17, 105, 232, 80, 201, 63, 17, 115, 232, 80, 201, 63, - 17, 232, 128, 232, 80, 201, 63, 17, 232, 226, 232, 80, 201, 63, 17, 202, - 136, 232, 80, 201, 63, 17, 203, 247, 232, 80, 201, 63, 17, 234, 164, 232, - 80, 201, 63, 17, 213, 175, 232, 80, 201, 63, 31, 199, 96, 232, 80, 201, - 63, 31, 234, 128, 232, 80, 201, 63, 31, 197, 38, 232, 80, 201, 63, 31, - 198, 252, 232, 80, 201, 63, 31, 232, 123, 232, 80, 201, 63, 31, 233, 20, - 232, 80, 201, 63, 31, 202, 131, 232, 80, 201, 63, 31, 203, 245, 232, 80, - 201, 63, 31, 234, 162, 232, 80, 201, 63, 31, 213, 172, 232, 80, 201, 63, - 31, 197, 33, 232, 80, 201, 63, 127, 8, 2, 1, 65, 127, 8, 2, 1, 250, 120, - 127, 8, 2, 1, 247, 193, 127, 8, 2, 1, 238, 127, 127, 8, 2, 1, 71, 127, 8, - 2, 1, 233, 175, 127, 8, 2, 1, 232, 51, 127, 8, 2, 1, 230, 116, 127, 8, 2, - 1, 68, 127, 8, 2, 1, 223, 35, 127, 8, 2, 1, 222, 152, 127, 8, 2, 1, 172, - 127, 8, 2, 1, 218, 168, 127, 8, 2, 1, 215, 61, 127, 8, 2, 1, 74, 127, 8, - 2, 1, 210, 236, 127, 8, 2, 1, 208, 104, 127, 8, 2, 1, 146, 127, 8, 2, 1, - 206, 8, 127, 8, 2, 1, 200, 43, 127, 8, 2, 1, 66, 127, 8, 2, 1, 196, 12, - 127, 8, 2, 1, 193, 224, 127, 8, 2, 1, 192, 235, 127, 8, 2, 1, 192, 159, - 127, 8, 2, 1, 191, 166, 47, 8, 6, 1, 65, 47, 8, 6, 1, 250, 120, 47, 8, 6, - 1, 247, 193, 47, 8, 6, 1, 238, 127, 47, 8, 6, 1, 71, 47, 8, 6, 1, 233, - 175, 47, 8, 6, 1, 232, 51, 47, 8, 6, 1, 230, 116, 47, 8, 6, 1, 68, 47, 8, - 6, 1, 223, 35, 47, 8, 6, 1, 222, 152, 47, 8, 6, 1, 172, 47, 8, 6, 1, 218, - 168, 47, 8, 6, 1, 215, 61, 47, 8, 6, 1, 74, 47, 8, 6, 1, 210, 236, 47, 8, - 6, 1, 208, 104, 47, 8, 6, 1, 146, 47, 8, 6, 1, 206, 8, 47, 8, 6, 1, 200, - 43, 47, 8, 6, 1, 66, 47, 8, 6, 1, 196, 12, 47, 8, 6, 1, 193, 224, 47, 8, - 6, 1, 192, 235, 47, 8, 6, 1, 192, 159, 47, 8, 6, 1, 191, 166, 47, 8, 2, - 1, 65, 47, 8, 2, 1, 250, 120, 47, 8, 2, 1, 247, 193, 47, 8, 2, 1, 238, - 127, 47, 8, 2, 1, 71, 47, 8, 2, 1, 233, 175, 47, 8, 2, 1, 232, 51, 47, 8, - 2, 1, 230, 116, 47, 8, 2, 1, 68, 47, 8, 2, 1, 223, 35, 47, 8, 2, 1, 222, - 152, 47, 8, 2, 1, 172, 47, 8, 2, 1, 218, 168, 47, 8, 2, 1, 215, 61, 47, - 8, 2, 1, 74, 47, 8, 2, 1, 210, 236, 47, 8, 2, 1, 208, 104, 47, 8, 2, 1, - 146, 47, 8, 2, 1, 206, 8, 47, 8, 2, 1, 200, 43, 47, 8, 2, 1, 66, 47, 8, - 2, 1, 196, 12, 47, 8, 2, 1, 193, 224, 47, 8, 2, 1, 192, 235, 47, 8, 2, 1, - 192, 159, 47, 8, 2, 1, 191, 166, 47, 17, 191, 77, 214, 106, 47, 31, 234, - 127, 214, 106, 47, 31, 197, 37, 214, 106, 47, 31, 198, 251, 214, 106, 47, - 31, 232, 122, 214, 106, 47, 31, 233, 19, 214, 106, 47, 31, 202, 130, 214, - 106, 47, 31, 203, 244, 214, 106, 47, 31, 234, 161, 214, 106, 47, 31, 213, - 171, 214, 106, 47, 31, 197, 32, 55, 47, 17, 107, 55, 47, 17, 109, 55, 47, - 17, 138, 55, 47, 17, 134, 55, 47, 17, 149, 55, 47, 17, 169, 55, 47, 17, - 175, 55, 47, 17, 171, 55, 47, 17, 178, 55, 47, 31, 199, 95, 214, 106, 47, - 17, 191, 77, 111, 122, 156, 228, 240, 111, 122, 88, 228, 240, 111, 122, - 156, 195, 135, 111, 122, 88, 195, 135, 111, 122, 156, 197, 225, 237, 216, - 228, 240, 111, 122, 88, 197, 225, 237, 216, 228, 240, 111, 122, 156, 197, - 225, 237, 216, 195, 135, 111, 122, 88, 197, 225, 237, 216, 195, 135, 111, - 122, 156, 208, 26, 237, 216, 228, 240, 111, 122, 88, 208, 26, 237, 216, - 228, 240, 111, 122, 156, 208, 26, 237, 216, 195, 135, 111, 122, 88, 208, - 26, 237, 216, 195, 135, 111, 122, 156, 144, 23, 183, 111, 122, 144, 156, - 23, 50, 229, 217, 111, 122, 144, 88, 23, 50, 219, 132, 111, 122, 88, 144, - 23, 183, 111, 122, 156, 144, 23, 219, 224, 111, 122, 144, 156, 23, 45, - 229, 217, 111, 122, 144, 88, 23, 45, 219, 132, 111, 122, 88, 144, 23, - 219, 224, 111, 122, 156, 133, 23, 183, 111, 122, 133, 156, 23, 50, 229, - 217, 111, 122, 133, 88, 23, 50, 219, 132, 111, 122, 88, 133, 23, 183, - 111, 122, 156, 133, 23, 219, 224, 111, 122, 133, 156, 23, 45, 229, 217, - 111, 122, 133, 88, 23, 45, 219, 132, 111, 122, 88, 133, 23, 219, 224, - 111, 122, 156, 81, 23, 183, 111, 122, 81, 156, 23, 50, 229, 217, 111, - 122, 133, 88, 23, 50, 144, 219, 132, 111, 122, 144, 88, 23, 50, 133, 219, - 132, 111, 122, 81, 88, 23, 50, 219, 132, 111, 122, 144, 156, 23, 50, 133, - 229, 217, 111, 122, 133, 156, 23, 50, 144, 229, 217, 111, 122, 88, 81, - 23, 183, 111, 122, 156, 81, 23, 219, 224, 111, 122, 81, 156, 23, 45, 229, - 217, 111, 122, 133, 88, 23, 45, 144, 219, 132, 111, 122, 144, 88, 23, 45, - 133, 219, 132, 111, 122, 81, 88, 23, 45, 219, 132, 111, 122, 144, 156, - 23, 45, 133, 229, 217, 111, 122, 133, 156, 23, 45, 144, 229, 217, 111, - 122, 88, 81, 23, 219, 224, 111, 122, 156, 144, 23, 228, 240, 111, 122, - 45, 88, 23, 50, 144, 219, 132, 111, 122, 50, 88, 23, 45, 144, 219, 132, - 111, 122, 144, 156, 23, 228, 241, 229, 217, 111, 122, 144, 88, 23, 228, - 241, 219, 132, 111, 122, 50, 156, 23, 45, 144, 229, 217, 111, 122, 45, - 156, 23, 50, 144, 229, 217, 111, 122, 88, 144, 23, 228, 240, 111, 122, - 156, 133, 23, 228, 240, 111, 122, 45, 88, 23, 50, 133, 219, 132, 111, - 122, 50, 88, 23, 45, 133, 219, 132, 111, 122, 133, 156, 23, 228, 241, - 229, 217, 111, 122, 133, 88, 23, 228, 241, 219, 132, 111, 122, 50, 156, - 23, 45, 133, 229, 217, 111, 122, 45, 156, 23, 50, 133, 229, 217, 111, - 122, 88, 133, 23, 228, 240, 111, 122, 156, 81, 23, 228, 240, 111, 122, - 45, 88, 23, 50, 81, 219, 132, 111, 122, 50, 88, 23, 45, 81, 219, 132, - 111, 122, 81, 156, 23, 228, 241, 229, 217, 111, 122, 133, 88, 23, 144, - 228, 241, 219, 132, 111, 122, 144, 88, 23, 133, 228, 241, 219, 132, 111, - 122, 81, 88, 23, 228, 241, 219, 132, 111, 122, 45, 133, 88, 23, 50, 144, - 219, 132, 111, 122, 50, 133, 88, 23, 45, 144, 219, 132, 111, 122, 45, - 144, 88, 23, 50, 133, 219, 132, 111, 122, 50, 144, 88, 23, 45, 133, 219, - 132, 111, 122, 144, 156, 23, 133, 228, 241, 229, 217, 111, 122, 133, 156, - 23, 144, 228, 241, 229, 217, 111, 122, 50, 156, 23, 45, 81, 229, 217, - 111, 122, 45, 156, 23, 50, 81, 229, 217, 111, 122, 88, 81, 23, 228, 240, - 111, 122, 156, 55, 237, 216, 228, 240, 111, 122, 88, 55, 237, 216, 228, - 240, 111, 122, 156, 55, 237, 216, 195, 135, 111, 122, 88, 55, 237, 216, - 195, 135, 111, 122, 55, 228, 240, 111, 122, 55, 195, 135, 111, 122, 144, - 202, 170, 23, 50, 235, 133, 111, 122, 144, 55, 23, 50, 202, 169, 111, - 122, 55, 144, 23, 183, 111, 122, 144, 202, 170, 23, 45, 235, 133, 111, - 122, 144, 55, 23, 45, 202, 169, 111, 122, 55, 144, 23, 219, 224, 111, - 122, 133, 202, 170, 23, 50, 235, 133, 111, 122, 133, 55, 23, 50, 202, - 169, 111, 122, 55, 133, 23, 183, 111, 122, 133, 202, 170, 23, 45, 235, - 133, 111, 122, 133, 55, 23, 45, 202, 169, 111, 122, 55, 133, 23, 219, - 224, 111, 122, 81, 202, 170, 23, 50, 235, 133, 111, 122, 81, 55, 23, 50, - 202, 169, 111, 122, 55, 81, 23, 183, 111, 122, 81, 202, 170, 23, 45, 235, - 133, 111, 122, 81, 55, 23, 45, 202, 169, 111, 122, 55, 81, 23, 219, 224, - 111, 122, 144, 202, 170, 23, 228, 241, 235, 133, 111, 122, 144, 55, 23, - 228, 241, 202, 169, 111, 122, 55, 144, 23, 228, 240, 111, 122, 133, 202, - 170, 23, 228, 241, 235, 133, 111, 122, 133, 55, 23, 228, 241, 202, 169, - 111, 122, 55, 133, 23, 228, 240, 111, 122, 81, 202, 170, 23, 228, 241, - 235, 133, 111, 122, 81, 55, 23, 228, 241, 202, 169, 111, 122, 55, 81, 23, - 228, 240, 111, 122, 156, 251, 17, 144, 23, 183, 111, 122, 156, 251, 17, - 144, 23, 219, 224, 111, 122, 156, 251, 17, 133, 23, 219, 224, 111, 122, - 156, 251, 17, 133, 23, 183, 111, 122, 156, 237, 39, 116, 50, 119, 110, - 219, 224, 111, 122, 156, 237, 39, 116, 45, 119, 110, 183, 111, 122, 156, - 237, 39, 238, 217, 111, 122, 156, 219, 224, 111, 122, 156, 196, 77, 111, - 122, 156, 183, 111, 122, 156, 235, 123, 111, 122, 88, 219, 224, 111, 122, - 88, 196, 77, 111, 122, 88, 183, 111, 122, 88, 235, 123, 111, 122, 156, - 45, 23, 88, 183, 111, 122, 156, 133, 23, 88, 235, 123, 111, 122, 88, 45, - 23, 156, 183, 111, 122, 88, 133, 23, 156, 235, 123, 116, 132, 248, 129, - 110, 91, 234, 160, 248, 129, 110, 91, 208, 23, 248, 129, 110, 115, 234, - 158, 248, 129, 110, 132, 248, 129, 110, 232, 226, 234, 158, 248, 129, - 110, 115, 208, 21, 248, 129, 110, 203, 247, 234, 158, 248, 129, 232, 80, - 248, 129, 45, 203, 247, 234, 158, 248, 129, 45, 115, 208, 21, 248, 129, - 45, 232, 226, 234, 158, 248, 129, 45, 132, 248, 129, 45, 115, 234, 158, - 248, 129, 45, 91, 208, 23, 248, 129, 45, 91, 234, 160, 248, 129, 50, 132, - 248, 129, 156, 203, 153, 216, 213, 203, 153, 237, 221, 203, 153, 116, 91, - 234, 160, 248, 129, 50, 91, 234, 160, 248, 129, 208, 28, 110, 219, 224, - 208, 28, 110, 183, 208, 28, 116, 219, 224, 208, 28, 116, 45, 23, 110, 45, - 23, 110, 183, 208, 28, 116, 45, 23, 110, 183, 208, 28, 116, 45, 23, 116, - 50, 23, 110, 219, 224, 208, 28, 116, 45, 23, 116, 50, 23, 110, 183, 208, - 28, 116, 183, 208, 28, 116, 50, 23, 110, 219, 224, 208, 28, 116, 50, 23, - 110, 45, 23, 110, 183, 62, 201, 190, 63, 201, 190, 63, 51, 4, 206, 113, - 239, 0, 63, 51, 239, 33, 62, 2, 201, 190, 51, 4, 228, 241, 233, 5, 51, 4, - 81, 233, 5, 51, 4, 211, 38, 238, 211, 233, 5, 51, 4, 116, 45, 119, 110, - 50, 233, 5, 51, 4, 116, 50, 119, 110, 45, 233, 5, 51, 4, 237, 39, 238, - 211, 233, 5, 62, 2, 201, 190, 63, 2, 201, 190, 62, 207, 92, 63, 207, 92, - 62, 81, 207, 92, 63, 81, 207, 92, 62, 210, 117, 63, 210, 117, 62, 196, - 76, 197, 241, 63, 196, 76, 197, 241, 62, 196, 76, 2, 197, 241, 63, 196, - 76, 2, 197, 241, 62, 206, 203, 197, 241, 63, 206, 203, 197, 241, 62, 206, - 203, 2, 197, 241, 63, 206, 203, 2, 197, 241, 62, 206, 203, 209, 59, 63, - 206, 203, 209, 59, 62, 235, 122, 197, 241, 63, 235, 122, 197, 241, 62, - 235, 122, 2, 197, 241, 63, 235, 122, 2, 197, 241, 62, 219, 219, 197, 241, - 63, 219, 219, 197, 241, 62, 219, 219, 2, 197, 241, 63, 219, 219, 2, 197, - 241, 62, 219, 219, 209, 59, 63, 219, 219, 209, 59, 62, 237, 32, 63, 237, - 32, 63, 237, 33, 239, 33, 62, 2, 237, 32, 232, 235, 218, 232, 63, 243, - 10, 235, 138, 243, 10, 243, 11, 4, 81, 233, 5, 247, 244, 62, 243, 10, - 243, 11, 4, 45, 132, 248, 139, 243, 11, 4, 50, 132, 248, 139, 243, 11, 4, - 110, 132, 248, 139, 243, 11, 4, 116, 132, 248, 139, 243, 11, 4, 116, 50, - 208, 28, 248, 139, 243, 11, 4, 251, 175, 247, 218, 116, 45, 208, 28, 248, - 139, 45, 132, 62, 243, 10, 50, 132, 62, 243, 10, 223, 95, 247, 248, 223, - 95, 63, 243, 10, 116, 132, 223, 95, 63, 243, 10, 110, 132, 223, 95, 63, - 243, 10, 116, 45, 208, 28, 243, 4, 251, 16, 116, 50, 208, 28, 243, 4, - 251, 16, 110, 50, 208, 28, 243, 4, 251, 16, 110, 45, 208, 28, 243, 4, - 251, 16, 116, 132, 243, 10, 110, 132, 243, 10, 62, 110, 50, 197, 241, 62, - 110, 45, 197, 241, 62, 116, 45, 197, 241, 62, 116, 50, 197, 241, 63, 247, - 248, 51, 4, 45, 132, 248, 139, 51, 4, 50, 132, 248, 139, 51, 4, 116, 45, - 237, 39, 132, 248, 139, 51, 4, 110, 50, 237, 39, 132, 248, 139, 63, 51, - 4, 81, 248, 154, 219, 112, 63, 196, 76, 197, 242, 4, 236, 140, 196, 76, - 197, 242, 4, 45, 132, 248, 139, 196, 76, 197, 242, 4, 50, 132, 248, 139, - 220, 13, 243, 10, 63, 51, 4, 116, 45, 208, 27, 63, 51, 4, 110, 45, 208, - 27, 63, 51, 4, 110, 50, 208, 27, 63, 51, 4, 116, 50, 208, 27, 63, 243, - 11, 4, 116, 45, 208, 27, 63, 243, 11, 4, 110, 45, 208, 27, 63, 243, 11, - 4, 110, 50, 208, 27, 63, 243, 11, 4, 116, 50, 208, 27, 116, 45, 197, 241, - 116, 50, 197, 241, 110, 45, 197, 241, 63, 216, 213, 201, 190, 62, 216, - 213, 201, 190, 63, 216, 213, 2, 201, 190, 62, 216, 213, 2, 201, 190, 110, - 50, 197, 241, 62, 200, 199, 4, 207, 119, 242, 210, 196, 117, 202, 48, - 242, 77, 62, 201, 102, 63, 201, 102, 219, 129, 198, 208, 200, 198, 250, - 213, 213, 35, 237, 86, 213, 35, 239, 42, 211, 62, 62, 199, 106, 63, 199, - 106, 249, 107, 248, 62, 249, 107, 111, 4, 243, 125, 249, 107, 111, 4, - 192, 235, 205, 154, 196, 118, 4, 207, 150, 235, 96, 228, 181, 248, 207, - 63, 203, 49, 209, 175, 62, 203, 49, 209, 175, 203, 140, 207, 18, 206, - 122, 232, 190, 229, 224, 247, 248, 62, 45, 209, 58, 223, 148, 62, 50, - 209, 58, 223, 148, 63, 45, 209, 58, 223, 148, 63, 133, 209, 58, 223, 148, - 63, 50, 209, 58, 223, 148, 63, 144, 209, 58, 223, 148, 202, 104, 23, 238, - 215, 247, 71, 56, 207, 164, 56, 248, 162, 56, 247, 151, 251, 99, 211, 39, - 238, 217, 243, 96, 207, 3, 238, 218, 79, 218, 255, 238, 218, 79, 222, - 254, 201, 103, 23, 238, 227, 233, 74, 113, 252, 34, 203, 143, 230, 62, - 23, 202, 213, 210, 61, 113, 192, 22, 192, 106, 197, 231, 40, 229, 219, - 197, 231, 40, 220, 43, 197, 231, 40, 232, 243, 197, 231, 40, 198, 209, - 197, 231, 40, 193, 66, 197, 231, 40, 193, 143, 197, 231, 40, 215, 184, - 197, 231, 40, 234, 207, 193, 94, 79, 237, 60, 63, 232, 92, 233, 103, 63, - 202, 64, 233, 103, 62, 202, 64, 233, 103, 63, 200, 199, 4, 207, 119, 232, - 238, 208, 23, 215, 205, 220, 6, 208, 23, 215, 205, 216, 180, 233, 42, 56, - 234, 207, 217, 97, 56, 222, 167, 205, 115, 196, 57, 214, 94, 209, 77, - 251, 2, 199, 164, 231, 152, 247, 124, 219, 186, 195, 38, 219, 143, 205, - 80, 205, 183, 247, 106, 251, 34, 209, 120, 63, 243, 105, 221, 138, 63, - 243, 105, 208, 14, 63, 243, 105, 206, 131, 63, 243, 105, 248, 152, 63, - 243, 105, 221, 76, 63, 243, 105, 210, 74, 62, 243, 105, 221, 138, 62, - 243, 105, 208, 14, 62, 243, 105, 206, 131, 62, 243, 105, 248, 152, 62, - 243, 105, 221, 76, 62, 243, 105, 210, 74, 62, 201, 245, 200, 211, 63, - 229, 224, 200, 211, 63, 237, 33, 200, 211, 62, 242, 207, 200, 211, 63, - 201, 245, 200, 211, 62, 229, 224, 200, 211, 62, 237, 33, 200, 211, 63, - 242, 207, 200, 211, 228, 181, 201, 195, 208, 23, 213, 6, 234, 160, 213, - 6, 249, 13, 234, 160, 213, 1, 249, 13, 202, 129, 213, 1, 215, 97, 232, - 207, 56, 215, 97, 214, 206, 56, 215, 97, 203, 127, 56, 193, 105, 200, 63, - 238, 217, 234, 204, 200, 63, 238, 217, 196, 87, 207, 88, 113, 207, 88, - 16, 40, 196, 254, 209, 98, 207, 88, 16, 40, 196, 252, 209, 98, 207, 88, - 16, 40, 196, 251, 209, 98, 207, 88, 16, 40, 196, 249, 209, 98, 207, 88, - 16, 40, 196, 247, 209, 98, 207, 88, 16, 40, 196, 245, 209, 98, 207, 88, - 16, 40, 196, 243, 209, 98, 207, 88, 16, 40, 231, 149, 217, 28, 62, 196, - 87, 207, 88, 113, 207, 89, 210, 136, 113, 210, 104, 210, 136, 113, 210, - 3, 210, 136, 56, 193, 92, 113, 237, 25, 233, 102, 237, 25, 233, 101, 237, - 25, 233, 100, 237, 25, 233, 99, 237, 25, 233, 98, 237, 25, 233, 97, 63, - 243, 11, 4, 75, 183, 63, 243, 11, 4, 105, 236, 138, 62, 243, 11, 4, 63, - 75, 183, 62, 243, 11, 4, 105, 63, 236, 138, 215, 221, 40, 192, 106, 215, - 221, 40, 192, 21, 237, 6, 40, 230, 205, 192, 106, 237, 6, 40, 219, 178, - 192, 21, 237, 6, 40, 219, 178, 192, 106, 237, 6, 40, 230, 205, 192, 21, - 63, 232, 217, 62, 232, 217, 230, 62, 23, 209, 180, 251, 127, 238, 214, - 200, 130, 201, 112, 79, 252, 8, 205, 98, 251, 191, 232, 186, 231, 162, - 201, 112, 79, 229, 191, 250, 172, 113, 232, 202, 211, 10, 63, 201, 102, - 115, 219, 107, 239, 19, 183, 115, 219, 107, 239, 19, 219, 224, 193, 155, - 56, 137, 195, 12, 56, 235, 128, 233, 42, 56, 235, 128, 217, 97, 56, 223, - 105, 233, 42, 23, 217, 97, 56, 217, 97, 23, 233, 42, 56, 217, 97, 4, 201, - 28, 56, 217, 97, 4, 201, 28, 23, 217, 97, 23, 233, 42, 56, 81, 217, 97, - 4, 201, 28, 56, 228, 241, 217, 97, 4, 201, 28, 56, 216, 213, 63, 243, 10, - 216, 213, 62, 243, 10, 216, 213, 2, 63, 243, 10, 217, 48, 113, 236, 198, - 113, 196, 84, 210, 103, 113, 242, 89, 232, 74, 196, 53, 214, 83, 247, 7, - 210, 185, 222, 173, 195, 80, 243, 75, 62, 215, 206, 219, 126, 203, 176, - 204, 22, 208, 4, 203, 255, 202, 36, 249, 111, 249, 73, 112, 221, 222, 63, - 235, 108, 217, 90, 63, 235, 108, 221, 138, 62, 235, 108, 217, 90, 62, - 235, 108, 221, 138, 202, 49, 193, 51, 202, 52, 200, 199, 248, 242, 242, - 210, 207, 149, 62, 202, 48, 198, 210, 242, 211, 23, 207, 149, 153, 63, - 203, 49, 209, 175, 153, 62, 203, 49, 209, 175, 63, 237, 33, 223, 163, - 201, 190, 238, 210, 220, 21, 236, 229, 247, 102, 211, 65, 209, 180, 247, - 103, 202, 85, 229, 201, 4, 63, 238, 217, 47, 238, 210, 220, 21, 246, 253, - 213, 44, 234, 72, 251, 157, 211, 96, 45, 193, 129, 198, 19, 62, 197, 10, - 45, 193, 129, 198, 19, 63, 197, 10, 45, 193, 129, 198, 19, 62, 45, 220, - 22, 216, 179, 63, 45, 220, 22, 216, 179, 235, 103, 202, 76, 56, 88, 63, - 235, 122, 197, 241, 45, 242, 219, 234, 72, 112, 205, 154, 233, 83, 237, - 39, 223, 163, 63, 243, 11, 223, 163, 62, 201, 190, 62, 197, 203, 207, 29, - 45, 234, 71, 207, 29, 45, 234, 70, 250, 187, 16, 40, 196, 57, 88, 243, - 11, 4, 201, 28, 23, 105, 185, 58, 210, 23, 206, 205, 223, 107, 210, 23, - 219, 221, 223, 107, 210, 23, 223, 93, 210, 23, 62, 238, 218, 211, 105, - 203, 78, 203, 66, 203, 12, 243, 40, 247, 80, 229, 118, 202, 137, 231, - 163, 193, 51, 228, 153, 231, 163, 4, 230, 30, 217, 72, 16, 40, 219, 131, - 215, 184, 196, 118, 211, 105, 230, 188, 232, 129, 232, 218, 223, 163, - 229, 5, 233, 32, 205, 178, 51, 232, 128, 239, 0, 202, 108, 228, 27, 202, - 112, 209, 251, 4, 249, 111, 199, 87, 223, 19, 249, 93, 113, 229, 229, - 230, 207, 113, 232, 83, 208, 153, 238, 182, 211, 105, 62, 201, 190, 63, - 232, 218, 4, 228, 241, 82, 62, 201, 29, 62, 205, 188, 205, 84, 116, 248, - 134, 205, 84, 62, 205, 84, 110, 248, 134, 205, 84, 63, 205, 84, 63, 88, - 243, 126, 77, 199, 107, 219, 40, 56, 199, 182, 235, 102, 251, 223, 234, - 67, 207, 147, 232, 231, 207, 147, 230, 53, 195, 67, 230, 53, 193, 3, 230, - 53, 110, 50, 210, 33, 210, 33, 116, 50, 210, 33, 63, 213, 208, 62, 213, - 208, 243, 126, 77, 88, 243, 126, 77, 215, 127, 192, 235, 88, 215, 127, - 192, 235, 249, 107, 192, 235, 88, 249, 107, 192, 235, 211, 10, 35, 238, - 217, 88, 35, 238, 217, 211, 77, 247, 22, 238, 217, 88, 211, 77, 247, 22, - 238, 217, 8, 238, 217, 203, 151, 63, 8, 238, 217, 211, 10, 8, 238, 217, - 217, 93, 238, 217, 201, 103, 79, 237, 208, 232, 128, 199, 127, 250, 193, - 232, 128, 249, 108, 250, 193, 88, 232, 128, 249, 108, 250, 193, 232, 128, - 242, 205, 250, 193, 62, 232, 128, 209, 60, 201, 102, 63, 232, 128, 209, - 60, 201, 102, 201, 240, 201, 38, 211, 10, 63, 201, 102, 47, 63, 201, 102, - 211, 77, 247, 22, 62, 201, 102, 62, 247, 22, 63, 201, 102, 211, 10, 62, - 201, 102, 88, 211, 10, 62, 201, 102, 209, 130, 201, 102, 203, 151, 63, - 201, 102, 88, 250, 193, 211, 77, 247, 22, 250, 193, 234, 164, 201, 206, - 250, 193, 234, 164, 209, 60, 62, 201, 102, 234, 164, 209, 60, 209, 130, - 201, 102, 202, 136, 209, 60, 62, 201, 102, 234, 164, 209, 60, 207, 90, - 62, 201, 102, 88, 234, 164, 209, 60, 207, 90, 62, 201, 102, 197, 38, 209, - 60, 62, 201, 102, 202, 131, 209, 60, 250, 193, 199, 127, 250, 193, 211, - 77, 247, 22, 199, 127, 250, 193, 88, 199, 127, 250, 193, 202, 136, 209, - 239, 62, 23, 63, 232, 189, 62, 232, 189, 63, 232, 189, 234, 164, 209, - 239, 211, 10, 62, 232, 189, 47, 211, 77, 247, 22, 234, 164, 209, 60, 201, - 102, 88, 199, 127, 209, 130, 250, 193, 202, 50, 198, 172, 197, 234, 202, - 50, 88, 243, 101, 202, 50, 201, 242, 88, 201, 242, 249, 108, 250, 193, - 234, 164, 199, 127, 208, 189, 250, 193, 88, 234, 164, 199, 127, 208, 189, - 250, 193, 238, 218, 77, 203, 151, 63, 243, 10, 214, 106, 112, 238, 218, - 77, 110, 50, 235, 98, 63, 201, 190, 116, 50, 235, 98, 63, 201, 190, 110, - 50, 203, 151, 63, 201, 190, 116, 50, 203, 151, 63, 201, 190, 62, 208, 13, - 87, 211, 42, 63, 208, 13, 87, 211, 42, 63, 233, 216, 87, 211, 42, 62, - 237, 33, 216, 35, 63, 192, 235, 88, 233, 216, 87, 113, 156, 81, 164, 216, - 213, 81, 164, 88, 81, 164, 88, 202, 170, 153, 242, 75, 207, 252, 87, 211, - 42, 88, 202, 170, 242, 75, 207, 252, 87, 211, 42, 88, 55, 153, 242, 75, - 207, 252, 87, 211, 42, 88, 55, 242, 75, 207, 252, 87, 211, 42, 88, 130, - 202, 170, 242, 75, 207, 252, 87, 211, 42, 88, 130, 55, 242, 75, 207, 252, - 87, 211, 42, 238, 163, 201, 81, 210, 128, 3, 211, 42, 88, 233, 216, 87, - 211, 42, 88, 229, 224, 233, 216, 87, 211, 42, 88, 62, 229, 223, 206, 122, - 88, 62, 229, 224, 247, 248, 232, 190, 229, 223, 206, 122, 232, 190, 229, - 224, 247, 248, 216, 213, 45, 210, 114, 211, 42, 216, 213, 50, 210, 114, - 211, 42, 216, 213, 232, 203, 45, 210, 114, 211, 42, 216, 213, 232, 203, - 50, 210, 114, 211, 42, 216, 213, 219, 219, 251, 116, 248, 54, 211, 42, - 216, 213, 206, 203, 251, 116, 248, 54, 211, 42, 88, 219, 219, 251, 116, - 207, 252, 87, 211, 42, 88, 206, 203, 251, 116, 207, 252, 87, 211, 42, 88, - 219, 219, 251, 116, 248, 54, 211, 42, 88, 206, 203, 251, 116, 248, 54, - 211, 42, 156, 45, 198, 42, 203, 103, 248, 54, 211, 42, 156, 50, 198, 42, - 203, 103, 248, 54, 211, 42, 216, 213, 45, 238, 171, 248, 54, 211, 42, - 216, 213, 50, 238, 171, 248, 54, 211, 42, 236, 241, 214, 106, 47, 17, - 107, 236, 241, 214, 106, 47, 17, 109, 236, 241, 214, 106, 47, 17, 138, - 236, 241, 214, 106, 47, 17, 134, 236, 241, 214, 106, 47, 17, 149, 236, - 241, 214, 106, 47, 17, 169, 236, 241, 214, 106, 47, 17, 175, 236, 241, - 214, 106, 47, 17, 171, 236, 241, 214, 106, 47, 17, 178, 236, 241, 214, - 106, 47, 31, 199, 95, 236, 241, 47, 49, 17, 107, 236, 241, 47, 49, 17, - 109, 236, 241, 47, 49, 17, 138, 236, 241, 47, 49, 17, 134, 236, 241, 47, - 49, 17, 149, 236, 241, 47, 49, 17, 169, 236, 241, 47, 49, 17, 175, 236, - 241, 47, 49, 17, 171, 236, 241, 47, 49, 17, 178, 236, 241, 47, 49, 31, - 199, 95, 236, 241, 214, 106, 47, 49, 17, 107, 236, 241, 214, 106, 47, 49, - 17, 109, 236, 241, 214, 106, 47, 49, 17, 138, 236, 241, 214, 106, 47, 49, - 17, 134, 236, 241, 214, 106, 47, 49, 17, 149, 236, 241, 214, 106, 47, 49, - 17, 169, 236, 241, 214, 106, 47, 49, 17, 175, 236, 241, 214, 106, 47, 49, - 17, 171, 236, 241, 214, 106, 47, 49, 17, 178, 236, 241, 214, 106, 47, 49, - 31, 199, 95, 88, 193, 77, 96, 57, 88, 108, 56, 88, 216, 35, 56, 88, 236, - 200, 56, 88, 202, 2, 234, 204, 57, 88, 96, 57, 88, 186, 234, 204, 57, - 235, 113, 209, 62, 96, 57, 88, 206, 114, 96, 57, 197, 240, 96, 57, 88, - 197, 240, 96, 57, 237, 214, 197, 240, 96, 57, 88, 237, 214, 197, 240, 96, - 57, 62, 96, 57, 198, 225, 198, 52, 96, 250, 235, 198, 225, 248, 75, 96, - 250, 235, 62, 96, 250, 235, 88, 62, 238, 163, 235, 119, 23, 96, 57, 88, - 62, 238, 163, 196, 66, 23, 96, 57, 201, 187, 62, 96, 57, 88, 239, 56, 62, - 96, 57, 206, 202, 63, 96, 57, 219, 218, 63, 96, 57, 249, 145, 203, 151, - 63, 96, 57, 232, 95, 203, 151, 63, 96, 57, 88, 110, 206, 201, 63, 96, 57, - 88, 116, 206, 201, 63, 96, 57, 213, 8, 110, 206, 201, 63, 96, 57, 238, - 171, 219, 4, 213, 8, 116, 206, 201, 63, 96, 57, 47, 88, 63, 96, 57, 193, - 88, 96, 57, 248, 138, 202, 2, 234, 204, 57, 248, 138, 96, 57, 248, 138, - 186, 234, 204, 57, 88, 248, 138, 202, 2, 234, 204, 57, 88, 248, 138, 96, - 57, 88, 248, 138, 186, 234, 204, 57, 199, 129, 96, 57, 88, 199, 128, 96, - 57, 193, 115, 96, 57, 88, 193, 115, 96, 57, 211, 71, 96, 57, 55, 238, - 171, 219, 4, 115, 236, 251, 251, 115, 63, 197, 242, 239, 33, 2, 63, 197, - 241, 209, 254, 211, 77, 200, 228, 211, 77, 200, 180, 45, 206, 7, 249, - 131, 237, 112, 50, 206, 7, 249, 131, 237, 112, 211, 57, 4, 75, 223, 117, - 207, 19, 202, 24, 208, 230, 200, 228, 200, 181, 208, 230, 202, 23, 81, - 249, 88, 4, 228, 241, 106, 13, 206, 180, 237, 38, 179, 236, 199, 13, 233, - 83, 237, 38, 112, 219, 29, 251, 125, 112, 219, 29, 211, 56, 63, 237, 33, - 4, 247, 20, 236, 140, 23, 4, 236, 140, 234, 132, 79, 211, 69, 196, 65, - 110, 50, 239, 2, 4, 236, 140, 116, 45, 239, 2, 4, 236, 140, 45, 211, 12, - 222, 199, 50, 211, 12, 222, 199, 232, 80, 211, 12, 222, 199, 220, 13, - 133, 199, 228, 220, 13, 144, 199, 228, 45, 23, 50, 55, 197, 57, 45, 23, - 50, 199, 228, 45, 215, 131, 179, 50, 199, 228, 179, 45, 199, 228, 133, - 199, 229, 4, 243, 11, 58, 218, 233, 236, 206, 247, 205, 228, 241, 206, - 52, 63, 239, 55, 237, 32, 63, 239, 55, 237, 33, 4, 118, 198, 182, 63, - 239, 55, 237, 33, 4, 96, 198, 182, 63, 51, 4, 118, 198, 182, 63, 51, 4, - 96, 198, 182, 13, 45, 63, 51, 248, 53, 13, 50, 63, 51, 248, 53, 13, 45, - 251, 116, 248, 53, 13, 50, 251, 116, 248, 53, 13, 45, 55, 251, 116, 248, - 53, 13, 50, 55, 251, 116, 248, 53, 13, 45, 63, 198, 42, 203, 103, 248, - 53, 13, 50, 63, 198, 42, 203, 103, 248, 53, 13, 45, 232, 203, 210, 113, - 13, 50, 232, 203, 210, 113, 196, 66, 208, 26, 57, 235, 119, 208, 26, 57, - 251, 85, 231, 202, 243, 11, 57, 242, 221, 231, 202, 243, 11, 57, 50, 64, - 4, 47, 209, 81, 179, 118, 57, 179, 96, 57, 179, 45, 50, 57, 179, 118, 55, - 57, 179, 96, 55, 57, 179, 45, 50, 55, 57, 179, 118, 64, 232, 98, 164, - 179, 96, 64, 232, 98, 164, 179, 118, 55, 64, 232, 98, 164, 179, 96, 55, - 64, 232, 98, 164, 179, 96, 201, 183, 57, 69, 70, 248, 132, 69, 70, 236, - 137, 69, 70, 236, 9, 69, 70, 236, 136, 69, 70, 235, 201, 69, 70, 236, 72, - 69, 70, 236, 8, 69, 70, 236, 135, 69, 70, 235, 169, 69, 70, 236, 40, 69, - 70, 235, 232, 69, 70, 236, 103, 69, 70, 235, 200, 69, 70, 236, 71, 69, - 70, 236, 7, 69, 70, 236, 134, 69, 70, 235, 153, 69, 70, 236, 24, 69, 70, - 235, 216, 69, 70, 236, 87, 69, 70, 235, 184, 69, 70, 236, 55, 69, 70, - 235, 247, 69, 70, 236, 118, 69, 70, 235, 168, 69, 70, 236, 39, 69, 70, - 235, 231, 69, 70, 236, 102, 69, 70, 235, 199, 69, 70, 236, 70, 69, 70, - 236, 6, 69, 70, 236, 133, 69, 70, 235, 145, 69, 70, 236, 16, 69, 70, 235, - 208, 69, 70, 236, 79, 69, 70, 235, 176, 69, 70, 236, 47, 69, 70, 235, - 239, 69, 70, 236, 110, 69, 70, 235, 160, 69, 70, 236, 31, 69, 70, 235, - 223, 69, 70, 236, 94, 69, 70, 235, 191, 69, 70, 236, 62, 69, 70, 235, - 254, 69, 70, 236, 125, 69, 70, 235, 152, 69, 70, 236, 23, 69, 70, 235, - 215, 69, 70, 236, 86, 69, 70, 235, 183, 69, 70, 236, 54, 69, 70, 235, - 246, 69, 70, 236, 117, 69, 70, 235, 167, 69, 70, 236, 38, 69, 70, 235, - 230, 69, 70, 236, 101, 69, 70, 235, 198, 69, 70, 236, 69, 69, 70, 236, 5, - 69, 70, 236, 132, 69, 70, 235, 141, 69, 70, 236, 12, 69, 70, 235, 204, - 69, 70, 236, 75, 69, 70, 235, 172, 69, 70, 236, 43, 69, 70, 235, 235, 69, - 70, 236, 106, 69, 70, 235, 156, 69, 70, 236, 27, 69, 70, 235, 219, 69, - 70, 236, 90, 69, 70, 235, 187, 69, 70, 236, 58, 69, 70, 235, 250, 69, 70, - 236, 121, 69, 70, 235, 148, 69, 70, 236, 19, 69, 70, 235, 211, 69, 70, - 236, 82, 69, 70, 235, 179, 69, 70, 236, 50, 69, 70, 235, 242, 69, 70, - 236, 113, 69, 70, 235, 163, 69, 70, 236, 34, 69, 70, 235, 226, 69, 70, - 236, 97, 69, 70, 235, 194, 69, 70, 236, 65, 69, 70, 236, 1, 69, 70, 236, - 128, 69, 70, 235, 144, 69, 70, 236, 15, 69, 70, 235, 207, 69, 70, 236, - 78, 69, 70, 235, 175, 69, 70, 236, 46, 69, 70, 235, 238, 69, 70, 236, - 109, 69, 70, 235, 159, 69, 70, 236, 30, 69, 70, 235, 222, 69, 70, 236, - 93, 69, 70, 235, 190, 69, 70, 236, 61, 69, 70, 235, 253, 69, 70, 236, - 124, 69, 70, 235, 151, 69, 70, 236, 22, 69, 70, 235, 214, 69, 70, 236, - 85, 69, 70, 235, 182, 69, 70, 236, 53, 69, 70, 235, 245, 69, 70, 236, - 116, 69, 70, 235, 166, 69, 70, 236, 37, 69, 70, 235, 229, 69, 70, 236, - 100, 69, 70, 235, 197, 69, 70, 236, 68, 69, 70, 236, 4, 69, 70, 236, 131, - 69, 70, 235, 139, 69, 70, 236, 10, 69, 70, 235, 202, 69, 70, 236, 73, 69, - 70, 235, 170, 69, 70, 236, 41, 69, 70, 235, 233, 69, 70, 236, 104, 69, - 70, 235, 154, 69, 70, 236, 25, 69, 70, 235, 217, 69, 70, 236, 88, 69, 70, - 235, 185, 69, 70, 236, 56, 69, 70, 235, 248, 69, 70, 236, 119, 69, 70, - 235, 146, 69, 70, 236, 17, 69, 70, 235, 209, 69, 70, 236, 80, 69, 70, - 235, 177, 69, 70, 236, 48, 69, 70, 235, 240, 69, 70, 236, 111, 69, 70, - 235, 161, 69, 70, 236, 32, 69, 70, 235, 224, 69, 70, 236, 95, 69, 70, - 235, 192, 69, 70, 236, 63, 69, 70, 235, 255, 69, 70, 236, 126, 69, 70, - 235, 142, 69, 70, 236, 13, 69, 70, 235, 205, 69, 70, 236, 76, 69, 70, - 235, 173, 69, 70, 236, 44, 69, 70, 235, 236, 69, 70, 236, 107, 69, 70, - 235, 157, 69, 70, 236, 28, 69, 70, 235, 220, 69, 70, 236, 91, 69, 70, - 235, 188, 69, 70, 236, 59, 69, 70, 235, 251, 69, 70, 236, 122, 69, 70, - 235, 149, 69, 70, 236, 20, 69, 70, 235, 212, 69, 70, 236, 83, 69, 70, - 235, 180, 69, 70, 236, 51, 69, 70, 235, 243, 69, 70, 236, 114, 69, 70, - 235, 164, 69, 70, 236, 35, 69, 70, 235, 227, 69, 70, 236, 98, 69, 70, - 235, 195, 69, 70, 236, 66, 69, 70, 236, 2, 69, 70, 236, 129, 69, 70, 235, - 140, 69, 70, 236, 11, 69, 70, 235, 203, 69, 70, 236, 74, 69, 70, 235, - 171, 69, 70, 236, 42, 69, 70, 235, 234, 69, 70, 236, 105, 69, 70, 235, - 155, 69, 70, 236, 26, 69, 70, 235, 218, 69, 70, 236, 89, 69, 70, 235, - 186, 69, 70, 236, 57, 69, 70, 235, 249, 69, 70, 236, 120, 69, 70, 235, - 147, 69, 70, 236, 18, 69, 70, 235, 210, 69, 70, 236, 81, 69, 70, 235, - 178, 69, 70, 236, 49, 69, 70, 235, 241, 69, 70, 236, 112, 69, 70, 235, - 162, 69, 70, 236, 33, 69, 70, 235, 225, 69, 70, 236, 96, 69, 70, 235, - 193, 69, 70, 236, 64, 69, 70, 236, 0, 69, 70, 236, 127, 69, 70, 235, 143, - 69, 70, 236, 14, 69, 70, 235, 206, 69, 70, 236, 77, 69, 70, 235, 174, 69, - 70, 236, 45, 69, 70, 235, 237, 69, 70, 236, 108, 69, 70, 235, 158, 69, - 70, 236, 29, 69, 70, 235, 221, 69, 70, 236, 92, 69, 70, 235, 189, 69, 70, - 236, 60, 69, 70, 235, 252, 69, 70, 236, 123, 69, 70, 235, 150, 69, 70, - 236, 21, 69, 70, 235, 213, 69, 70, 236, 84, 69, 70, 235, 181, 69, 70, - 236, 52, 69, 70, 235, 244, 69, 70, 236, 115, 69, 70, 235, 165, 69, 70, - 236, 36, 69, 70, 235, 228, 69, 70, 236, 99, 69, 70, 235, 196, 69, 70, - 236, 67, 69, 70, 236, 3, 69, 70, 236, 130, 96, 197, 13, 64, 4, 81, 106, - 96, 197, 13, 64, 4, 55, 81, 106, 118, 55, 64, 4, 81, 106, 96, 55, 64, 4, - 81, 106, 45, 50, 55, 64, 4, 81, 106, 96, 197, 13, 64, 232, 98, 164, 118, - 55, 64, 232, 98, 164, 96, 55, 64, 232, 98, 164, 235, 119, 64, 4, 228, - 241, 106, 196, 66, 64, 4, 228, 241, 106, 196, 66, 197, 225, 57, 235, 119, - 197, 225, 57, 118, 55, 237, 216, 57, 96, 55, 237, 216, 57, 118, 197, 225, - 237, 216, 57, 96, 197, 225, 237, 216, 57, 96, 197, 13, 197, 225, 237, - 216, 57, 96, 64, 4, 235, 138, 201, 80, 196, 66, 64, 119, 164, 235, 119, - 64, 119, 164, 96, 64, 4, 199, 216, 4, 81, 106, 96, 64, 4, 199, 216, 4, - 55, 81, 106, 96, 197, 13, 64, 4, 199, 215, 96, 197, 13, 64, 4, 199, 216, - 4, 81, 106, 96, 197, 13, 64, 4, 199, 216, 4, 55, 81, 106, 118, 250, 237, - 96, 250, 237, 118, 55, 250, 237, 96, 55, 250, 237, 118, 64, 119, 62, 237, - 32, 96, 64, 119, 62, 237, 32, 118, 64, 232, 98, 249, 88, 119, 62, 237, - 32, 96, 64, 232, 98, 249, 88, 119, 62, 237, 32, 186, 193, 105, 23, 202, - 2, 234, 204, 57, 186, 234, 204, 23, 202, 2, 193, 105, 57, 186, 193, 105, - 64, 4, 102, 186, 234, 204, 64, 4, 102, 202, 2, 234, 204, 64, 4, 102, 202, - 2, 193, 105, 64, 4, 102, 186, 193, 105, 64, 23, 186, 234, 204, 57, 186, - 234, 204, 64, 23, 202, 2, 234, 204, 57, 202, 2, 234, 204, 64, 23, 202, 2, - 193, 105, 57, 202, 2, 193, 105, 64, 23, 186, 193, 105, 57, 206, 180, 237, - 39, 238, 210, 233, 83, 237, 38, 233, 83, 237, 39, 238, 210, 206, 180, - 237, 38, 202, 2, 234, 204, 64, 238, 210, 186, 234, 204, 57, 186, 234, - 204, 64, 238, 210, 202, 2, 234, 204, 57, 233, 83, 237, 39, 238, 210, 186, - 234, 204, 57, 206, 180, 237, 39, 238, 210, 202, 2, 234, 204, 57, 186, - 234, 204, 64, 238, 210, 186, 193, 105, 57, 186, 193, 105, 64, 238, 210, - 186, 234, 204, 57, 193, 139, 64, 209, 58, 236, 231, 183, 64, 209, 58, 96, - 199, 25, 238, 161, 196, 65, 64, 209, 58, 96, 199, 25, 238, 161, 235, 118, - 64, 209, 58, 235, 119, 199, 25, 238, 161, 219, 214, 64, 209, 58, 235, - 119, 199, 25, 238, 161, 206, 197, 206, 200, 251, 17, 242, 221, 57, 219, - 217, 251, 17, 251, 85, 57, 198, 54, 251, 17, 251, 85, 57, 248, 77, 251, - 17, 251, 85, 57, 198, 54, 251, 17, 242, 221, 64, 4, 216, 34, 198, 54, - 251, 17, 251, 85, 64, 4, 209, 81, 110, 50, 204, 27, 242, 221, 57, 110, - 45, 204, 27, 251, 85, 57, 251, 85, 242, 219, 243, 11, 57, 242, 221, 242, - 219, 243, 11, 57, 96, 64, 93, 203, 40, 118, 57, 118, 64, 93, 203, 40, 96, - 57, 203, 40, 96, 64, 93, 118, 57, 96, 64, 4, 108, 60, 118, 64, 4, 108, - 60, 96, 64, 198, 216, 192, 235, 45, 50, 64, 198, 216, 2, 243, 10, 196, - 66, 197, 13, 64, 232, 98, 2, 243, 10, 45, 181, 133, 50, 181, 144, 230, - 12, 45, 181, 144, 50, 181, 133, 230, 12, 133, 181, 50, 144, 181, 45, 230, - 12, 133, 181, 45, 144, 181, 50, 230, 12, 45, 181, 133, 50, 181, 133, 230, - 12, 133, 181, 50, 144, 181, 50, 230, 12, 45, 181, 144, 50, 181, 144, 230, - 12, 133, 181, 45, 144, 181, 45, 230, 12, 118, 230, 13, 4, 181, 133, 119, - 164, 96, 230, 13, 4, 181, 133, 119, 164, 196, 66, 230, 13, 4, 181, 50, - 119, 164, 235, 119, 230, 13, 4, 181, 50, 119, 164, 118, 230, 13, 4, 181, - 144, 119, 164, 96, 230, 13, 4, 181, 144, 119, 164, 196, 66, 230, 13, 4, - 181, 45, 119, 164, 235, 119, 230, 13, 4, 181, 45, 119, 164, 118, 230, 13, - 4, 181, 133, 232, 98, 164, 96, 230, 13, 4, 181, 133, 232, 98, 164, 196, - 66, 230, 13, 4, 181, 50, 232, 98, 164, 235, 119, 230, 13, 4, 181, 50, - 232, 98, 164, 118, 230, 13, 4, 181, 144, 232, 98, 164, 96, 230, 13, 4, - 181, 144, 232, 98, 164, 196, 66, 230, 13, 4, 181, 45, 232, 98, 164, 235, - 119, 230, 13, 4, 181, 45, 232, 98, 164, 118, 230, 13, 4, 181, 133, 93, - 118, 230, 13, 4, 181, 235, 123, 196, 66, 230, 13, 4, 181, 45, 248, 216, - 196, 66, 230, 13, 4, 181, 183, 96, 230, 13, 4, 181, 133, 93, 96, 230, 13, - 4, 181, 235, 123, 235, 119, 230, 13, 4, 181, 45, 248, 216, 235, 119, 230, - 13, 4, 181, 183, 118, 230, 13, 4, 181, 133, 93, 96, 230, 13, 4, 181, 196, - 77, 118, 230, 13, 4, 181, 144, 93, 96, 230, 13, 4, 181, 235, 123, 96, - 230, 13, 4, 181, 133, 93, 118, 230, 13, 4, 181, 196, 77, 96, 230, 13, 4, - 181, 144, 93, 118, 230, 13, 4, 181, 235, 123, 118, 230, 13, 4, 181, 133, - 93, 179, 237, 215, 118, 230, 13, 4, 181, 144, 248, 233, 179, 237, 215, - 96, 230, 13, 4, 181, 133, 93, 179, 237, 215, 96, 230, 13, 4, 181, 144, - 248, 233, 179, 237, 215, 196, 66, 230, 13, 4, 181, 45, 248, 216, 235, - 119, 230, 13, 4, 181, 183, 235, 119, 230, 13, 4, 181, 45, 248, 216, 196, - 66, 230, 13, 4, 181, 183, 50, 55, 64, 4, 206, 113, 229, 235, 234, 43, 3, - 93, 96, 57, 198, 153, 211, 67, 93, 96, 57, 118, 64, 93, 198, 153, 211, - 66, 96, 64, 93, 198, 153, 211, 66, 96, 64, 93, 251, 165, 234, 45, 159, - 219, 180, 93, 118, 57, 118, 64, 198, 216, 219, 179, 230, 204, 93, 96, 57, - 200, 229, 93, 96, 57, 118, 64, 198, 216, 200, 228, 200, 181, 93, 118, 57, - 45, 232, 237, 199, 215, 50, 232, 237, 199, 215, 133, 232, 237, 199, 215, - 144, 232, 237, 199, 215, 197, 225, 81, 249, 88, 237, 112, 191, 167, 213, - 10, 201, 201, 191, 167, 213, 10, 196, 255, 242, 83, 45, 63, 238, 171, - 248, 53, 50, 63, 238, 171, 248, 53, 45, 63, 210, 113, 50, 63, 210, 113, - 191, 167, 213, 10, 45, 223, 178, 248, 53, 191, 167, 213, 10, 50, 223, - 178, 248, 53, 191, 167, 213, 10, 45, 248, 166, 248, 53, 191, 167, 213, - 10, 50, 248, 166, 248, 53, 45, 51, 248, 54, 4, 196, 103, 50, 51, 248, 54, - 4, 196, 103, 45, 51, 248, 54, 4, 198, 183, 223, 163, 198, 54, 239, 1, 50, - 51, 248, 54, 4, 198, 183, 223, 163, 248, 77, 239, 1, 45, 51, 248, 54, 4, - 198, 183, 223, 163, 248, 77, 239, 1, 50, 51, 248, 54, 4, 198, 183, 223, - 163, 198, 54, 239, 1, 45, 251, 116, 248, 54, 4, 236, 140, 50, 251, 116, - 248, 54, 4, 236, 140, 45, 251, 17, 219, 180, 248, 53, 50, 251, 17, 230, - 204, 248, 53, 55, 45, 251, 17, 230, 204, 248, 53, 55, 50, 251, 17, 219, - 180, 248, 53, 45, 62, 198, 42, 203, 103, 248, 53, 50, 62, 198, 42, 203, - 103, 248, 53, 235, 138, 233, 39, 81, 191, 21, 219, 112, 216, 226, 251, - 116, 211, 69, 219, 224, 50, 251, 116, 195, 168, 4, 201, 190, 216, 226, - 50, 251, 116, 4, 236, 140, 251, 116, 4, 206, 9, 223, 117, 252, 47, 251, - 115, 201, 225, 251, 116, 211, 69, 219, 224, 201, 225, 251, 116, 211, 69, - 196, 77, 153, 251, 115, 207, 18, 251, 115, 251, 116, 4, 196, 103, 207, - 18, 251, 116, 4, 196, 103, 211, 172, 251, 116, 211, 69, 196, 77, 211, - 172, 251, 116, 211, 69, 235, 123, 216, 226, 251, 116, 4, 211, 77, 250, - 251, 234, 91, 223, 163, 64, 209, 58, 133, 23, 183, 216, 226, 251, 116, 4, - 211, 77, 250, 251, 234, 91, 223, 163, 64, 209, 58, 133, 23, 219, 224, - 216, 226, 251, 116, 4, 211, 77, 250, 251, 234, 91, 223, 163, 64, 209, 58, - 144, 23, 183, 216, 226, 251, 116, 4, 211, 77, 250, 251, 234, 91, 223, - 163, 64, 209, 58, 144, 23, 219, 224, 216, 226, 251, 116, 4, 211, 77, 250, - 251, 234, 91, 223, 163, 64, 209, 58, 50, 23, 196, 77, 216, 226, 251, 116, - 4, 211, 77, 250, 251, 234, 91, 223, 163, 64, 209, 58, 45, 23, 196, 77, - 216, 226, 251, 116, 4, 211, 77, 250, 251, 234, 91, 223, 163, 64, 209, 58, - 50, 23, 235, 123, 216, 226, 251, 116, 4, 211, 77, 250, 251, 234, 91, 223, - 163, 64, 209, 58, 45, 23, 235, 123, 207, 18, 234, 105, 203, 252, 234, - 105, 203, 253, 4, 211, 6, 234, 105, 203, 253, 4, 2, 243, 11, 58, 234, - 105, 203, 253, 4, 50, 64, 58, 234, 105, 203, 253, 4, 45, 64, 58, 243, 11, - 4, 228, 241, 164, 47, 81, 164, 47, 210, 118, 47, 207, 19, 202, 23, 47, - 209, 254, 243, 11, 236, 206, 247, 205, 228, 241, 249, 88, 23, 198, 54, - 132, 236, 206, 247, 205, 81, 164, 243, 11, 4, 200, 183, 192, 235, 47, - 251, 83, 236, 200, 56, 133, 64, 198, 216, 243, 10, 47, 63, 247, 248, 47, - 247, 248, 47, 219, 179, 47, 230, 203, 243, 11, 4, 2, 243, 11, 119, 199, - 34, 183, 243, 11, 4, 105, 228, 241, 201, 16, 119, 199, 34, 183, 112, 206, - 180, 237, 39, 202, 97, 112, 233, 83, 237, 39, 202, 97, 112, 250, 193, - 112, 2, 243, 10, 112, 201, 190, 105, 222, 198, 201, 188, 197, 242, 4, 75, - 58, 197, 242, 4, 196, 103, 206, 9, 223, 163, 197, 241, 197, 242, 4, 204, - 4, 250, 183, 248, 76, 50, 197, 242, 93, 45, 197, 241, 45, 197, 242, 248, - 216, 81, 164, 81, 249, 88, 248, 216, 50, 197, 241, 248, 64, 4, 45, 132, - 248, 139, 248, 64, 4, 50, 132, 248, 139, 62, 248, 63, 25, 4, 45, 132, - 248, 139, 25, 4, 50, 132, 248, 139, 63, 228, 174, 62, 228, 174, 45, 193, - 72, 233, 39, 50, 193, 72, 233, 39, 45, 55, 193, 72, 233, 39, 50, 55, 193, - 72, 233, 39, 223, 155, 223, 139, 198, 179, 139, 223, 139, 223, 140, 214, - 108, 4, 81, 164, 235, 132, 215, 131, 51, 4, 239, 25, 211, 11, 223, 152, - 250, 219, 202, 254, 208, 200, 234, 43, 3, 23, 202, 99, 210, 118, 234, 43, - 3, 23, 202, 99, 210, 119, 4, 198, 153, 58, 228, 17, 119, 23, 202, 99, - 210, 118, 231, 14, 201, 101, 199, 22, 235, 122, 197, 242, 4, 45, 132, - 248, 139, 235, 122, 197, 242, 4, 50, 132, 248, 139, 62, 237, 33, 4, 144, - 57, 62, 218, 232, 63, 243, 11, 4, 144, 57, 62, 243, 11, 4, 144, 57, 234, - 25, 63, 201, 190, 234, 25, 62, 201, 190, 234, 25, 63, 237, 32, 234, 25, - 62, 237, 32, 234, 25, 63, 243, 10, 234, 25, 62, 243, 10, 206, 51, 207, - 19, 202, 24, 211, 66, 202, 24, 4, 211, 6, 207, 19, 202, 24, 4, 228, 241, - 106, 248, 175, 202, 23, 248, 175, 207, 19, 202, 23, 55, 209, 81, 197, - 225, 209, 81, 219, 219, 238, 163, 251, 116, 248, 53, 206, 203, 238, 163, - 251, 116, 248, 53, 198, 137, 216, 32, 215, 60, 47, 75, 211, 66, 215, 60, - 47, 108, 211, 66, 215, 60, 47, 25, 211, 66, 215, 60, 196, 93, 211, 67, 4, - 236, 140, 215, 60, 196, 93, 211, 67, 4, 209, 81, 215, 60, 51, 223, 100, - 211, 66, 215, 60, 51, 196, 93, 211, 66, 105, 219, 29, 23, 211, 66, 105, - 219, 29, 211, 57, 211, 66, 215, 60, 25, 211, 66, 215, 236, 105, 200, 204, - 200, 202, 4, 223, 113, 208, 26, 223, 114, 211, 66, 232, 246, 210, 107, - 223, 113, 223, 114, 4, 55, 106, 223, 114, 250, 143, 4, 202, 97, 243, 3, - 232, 76, 251, 85, 223, 111, 219, 113, 223, 112, 4, 207, 91, 210, 86, 250, - 245, 209, 52, 219, 113, 223, 112, 4, 204, 27, 210, 86, 250, 245, 209, 52, - 219, 113, 223, 112, 213, 12, 223, 157, 199, 34, 209, 52, 223, 114, 250, - 245, 42, 209, 62, 211, 66, 208, 19, 223, 114, 211, 66, 223, 114, 4, 118, - 64, 4, 102, 223, 114, 4, 25, 56, 223, 114, 4, 223, 99, 223, 114, 4, 196, - 92, 223, 114, 4, 211, 6, 223, 114, 4, 196, 103, 222, 199, 220, 13, 45, - 197, 242, 211, 66, 191, 167, 213, 10, 205, 92, 239, 62, 191, 167, 213, - 10, 205, 92, 209, 126, 191, 167, 213, 10, 205, 92, 208, 195, 108, 3, 4, - 2, 243, 11, 58, 108, 3, 4, 243, 2, 252, 61, 58, 108, 3, 4, 198, 153, 58, - 108, 3, 4, 75, 60, 108, 3, 4, 198, 153, 60, 108, 3, 4, 200, 230, 109, - 108, 3, 4, 62, 197, 241, 216, 35, 3, 4, 242, 75, 58, 216, 35, 3, 4, 75, - 60, 216, 35, 3, 4, 233, 83, 236, 138, 216, 35, 3, 4, 206, 180, 236, 138, - 108, 3, 223, 163, 45, 132, 243, 10, 108, 3, 223, 163, 50, 132, 243, 10, - 195, 152, 211, 57, 238, 218, 208, 200, 215, 127, 3, 4, 75, 58, 215, 127, - 3, 4, 196, 103, 204, 24, 208, 201, 4, 248, 77, 242, 218, 202, 68, 208, - 200, 215, 127, 3, 223, 163, 45, 132, 243, 10, 215, 127, 3, 223, 163, 50, - 132, 243, 10, 47, 215, 127, 3, 4, 243, 2, 252, 60, 215, 127, 3, 223, 163, - 55, 243, 10, 47, 236, 200, 56, 108, 3, 223, 163, 197, 241, 216, 35, 3, - 223, 163, 197, 241, 215, 127, 3, 223, 163, 197, 241, 223, 108, 208, 200, - 206, 198, 223, 108, 208, 200, 191, 167, 213, 10, 207, 64, 239, 62, 251, - 147, 211, 57, 239, 9, 223, 100, 4, 236, 140, 196, 93, 4, 216, 35, 56, - 196, 93, 4, 211, 6, 223, 100, 4, 211, 6, 223, 100, 4, 219, 29, 251, 125, - 196, 93, 4, 219, 29, 211, 56, 196, 93, 93, 223, 99, 223, 100, 93, 196, - 92, 196, 93, 93, 249, 88, 93, 223, 99, 223, 100, 93, 249, 88, 93, 196, - 92, 196, 93, 248, 216, 23, 222, 198, 4, 196, 92, 223, 100, 248, 216, 23, - 222, 198, 4, 223, 99, 242, 219, 196, 93, 4, 204, 3, 242, 219, 223, 100, - 4, 204, 3, 55, 51, 223, 99, 55, 51, 196, 92, 242, 219, 196, 93, 4, 204, - 4, 23, 202, 68, 208, 200, 219, 29, 23, 4, 75, 58, 219, 29, 211, 57, 4, - 75, 58, 55, 219, 29, 251, 125, 55, 219, 29, 211, 56, 105, 223, 101, 219, - 29, 251, 125, 105, 223, 101, 219, 29, 211, 56, 202, 80, 220, 13, 211, 56, - 202, 80, 220, 13, 251, 125, 219, 29, 211, 57, 211, 1, 219, 29, 251, 125, - 219, 29, 23, 4, 82, 201, 80, 219, 29, 211, 57, 4, 82, 201, 80, 219, 29, - 23, 4, 228, 241, 237, 215, 219, 29, 211, 57, 4, 228, 241, 237, 215, 219, - 29, 23, 4, 55, 211, 6, 219, 29, 23, 4, 196, 103, 219, 29, 23, 4, 55, 196, - 103, 2, 195, 149, 4, 196, 103, 219, 29, 211, 57, 4, 55, 211, 6, 219, 29, - 211, 57, 4, 55, 196, 103, 191, 167, 213, 10, 236, 152, 251, 75, 191, 167, - 213, 10, 207, 137, 251, 75, 234, 43, 3, 4, 75, 60, 228, 17, 4, 75, 58, - 197, 225, 228, 241, 249, 88, 4, 55, 81, 106, 197, 225, 228, 241, 249, 88, - 4, 197, 225, 81, 106, 198, 153, 211, 67, 4, 75, 58, 198, 153, 211, 67, 4, - 206, 180, 236, 138, 202, 180, 216, 35, 202, 179, 239, 49, 4, 75, 58, 234, - 43, 4, 250, 193, 251, 165, 234, 45, 119, 4, 243, 2, 252, 60, 251, 40, - 234, 45, 211, 57, 234, 45, 159, 234, 43, 3, 93, 108, 56, 108, 3, 93, 234, - 43, 56, 234, 43, 3, 93, 198, 153, 211, 66, 55, 242, 84, 234, 44, 105, - 239, 41, 234, 43, 202, 194, 115, 239, 41, 234, 43, 202, 194, 234, 43, 3, - 4, 105, 185, 93, 23, 105, 185, 60, 234, 36, 4, 232, 128, 185, 58, 219, - 180, 4, 243, 11, 223, 117, 230, 204, 4, 243, 11, 223, 117, 219, 180, 4, - 208, 13, 87, 58, 230, 204, 4, 208, 13, 87, 58, 219, 180, 211, 57, 202, - 99, 234, 45, 159, 230, 204, 211, 57, 202, 99, 234, 45, 159, 219, 180, - 211, 57, 202, 99, 234, 45, 119, 4, 75, 223, 117, 230, 204, 211, 57, 202, - 99, 234, 45, 119, 4, 75, 223, 117, 219, 180, 211, 57, 202, 99, 234, 45, - 119, 4, 75, 58, 230, 204, 211, 57, 202, 99, 234, 45, 119, 4, 75, 58, 219, - 180, 211, 57, 202, 99, 234, 45, 119, 4, 75, 93, 183, 230, 204, 211, 57, - 202, 99, 234, 45, 119, 4, 75, 93, 219, 224, 219, 180, 211, 57, 251, 41, - 230, 204, 211, 57, 251, 41, 219, 180, 23, 202, 168, 213, 12, 234, 45, - 159, 230, 204, 23, 202, 168, 213, 12, 234, 45, 159, 219, 180, 23, 213, - 12, 251, 41, 230, 204, 23, 213, 12, 251, 41, 219, 180, 93, 235, 131, 234, - 45, 93, 230, 203, 230, 204, 93, 235, 131, 234, 45, 93, 219, 179, 219, - 180, 93, 202, 180, 211, 57, 234, 44, 230, 204, 93, 202, 180, 211, 57, - 234, 44, 219, 180, 93, 202, 180, 93, 230, 203, 230, 204, 93, 202, 180, - 93, 219, 179, 219, 180, 93, 230, 204, 93, 235, 131, 234, 44, 230, 204, - 93, 219, 180, 93, 235, 131, 234, 44, 219, 180, 93, 202, 99, 234, 45, 93, - 230, 204, 93, 202, 99, 234, 44, 230, 204, 93, 202, 99, 234, 45, 93, 219, - 180, 93, 202, 99, 234, 44, 202, 99, 234, 45, 119, 211, 57, 219, 179, 202, - 99, 234, 45, 119, 211, 57, 230, 203, 202, 99, 234, 45, 119, 211, 57, 219, - 180, 4, 75, 223, 117, 202, 99, 234, 45, 119, 211, 57, 230, 204, 4, 75, - 223, 117, 235, 131, 234, 45, 119, 211, 57, 219, 179, 235, 131, 234, 45, - 119, 211, 57, 230, 203, 235, 131, 202, 99, 234, 45, 119, 211, 57, 219, - 179, 235, 131, 202, 99, 234, 45, 119, 211, 57, 230, 203, 202, 180, 211, - 57, 219, 179, 202, 180, 211, 57, 230, 203, 202, 180, 93, 219, 180, 93, - 234, 43, 56, 202, 180, 93, 230, 204, 93, 234, 43, 56, 55, 214, 88, 219, - 179, 55, 214, 88, 230, 203, 55, 214, 88, 219, 180, 4, 196, 103, 230, 204, - 211, 1, 219, 179, 230, 204, 248, 216, 219, 179, 219, 180, 242, 219, 247, - 205, 238, 164, 230, 204, 242, 219, 247, 205, 238, 164, 219, 180, 242, - 219, 247, 205, 238, 165, 93, 202, 99, 234, 44, 230, 204, 242, 219, 247, - 205, 238, 165, 93, 202, 99, 234, 44, 202, 69, 199, 38, 220, 11, 199, 38, - 202, 69, 199, 39, 211, 57, 234, 45, 159, 220, 11, 199, 39, 211, 57, 234, - 45, 159, 234, 43, 3, 4, 247, 241, 58, 208, 232, 93, 202, 168, 234, 43, - 56, 200, 221, 93, 202, 168, 234, 43, 56, 208, 232, 93, 202, 168, 213, 12, - 234, 45, 159, 200, 221, 93, 202, 168, 213, 12, 234, 45, 159, 208, 232, - 93, 234, 43, 56, 200, 221, 93, 234, 43, 56, 208, 232, 93, 213, 12, 234, - 45, 159, 200, 221, 93, 213, 12, 234, 45, 159, 208, 232, 93, 251, 165, - 234, 45, 159, 200, 221, 93, 251, 165, 234, 45, 159, 208, 232, 93, 213, - 12, 251, 165, 234, 45, 159, 200, 221, 93, 213, 12, 251, 165, 234, 45, - 159, 55, 208, 231, 55, 200, 220, 200, 229, 4, 236, 140, 200, 181, 4, 236, - 140, 200, 229, 4, 108, 3, 60, 200, 181, 4, 108, 3, 60, 200, 229, 4, 215, - 127, 3, 60, 200, 181, 4, 215, 127, 3, 60, 200, 229, 79, 211, 57, 234, 45, - 119, 4, 75, 58, 200, 181, 79, 211, 57, 234, 45, 119, 4, 75, 58, 200, 229, - 79, 93, 234, 43, 56, 200, 181, 79, 93, 234, 43, 56, 200, 229, 79, 93, - 198, 153, 211, 66, 200, 181, 79, 93, 198, 153, 211, 66, 200, 229, 79, 93, - 251, 165, 234, 45, 159, 200, 181, 79, 93, 251, 165, 234, 45, 159, 200, - 229, 79, 93, 213, 12, 234, 45, 159, 200, 181, 79, 93, 213, 12, 234, 45, - 159, 51, 45, 211, 77, 111, 211, 66, 51, 50, 211, 77, 111, 211, 66, 242, - 219, 200, 228, 242, 219, 200, 180, 242, 219, 200, 229, 211, 57, 234, 45, - 159, 242, 219, 200, 181, 211, 57, 234, 45, 159, 200, 229, 93, 200, 180, - 200, 181, 93, 200, 228, 200, 229, 93, 200, 228, 200, 181, 93, 200, 180, - 200, 181, 248, 216, 200, 228, 200, 181, 248, 216, 23, 222, 198, 247, 205, - 237, 216, 4, 200, 228, 234, 132, 79, 211, 69, 235, 118, 209, 116, 4, 199, - 122, 198, 53, 198, 7, 223, 99, 232, 147, 213, 27, 203, 40, 45, 199, 228, - 203, 40, 144, 199, 228, 203, 40, 133, 199, 228, 209, 255, 4, 206, 8, 81, - 249, 88, 197, 225, 50, 197, 57, 55, 81, 249, 88, 45, 197, 57, 81, 249, - 88, 55, 45, 197, 57, 55, 81, 249, 88, 55, 45, 197, 57, 179, 237, 216, - 232, 98, 45, 216, 191, 79, 55, 195, 135, 203, 40, 144, 199, 229, 4, 211, - 6, 203, 40, 133, 199, 229, 4, 196, 103, 203, 40, 133, 199, 229, 93, 203, - 40, 144, 199, 228, 55, 144, 199, 228, 55, 133, 199, 228, 55, 201, 28, - 213, 12, 56, 207, 18, 55, 201, 28, 213, 12, 56, 236, 164, 213, 12, 236, - 208, 4, 207, 18, 214, 107, 202, 97, 81, 219, 113, 4, 243, 11, 58, 81, - 219, 113, 4, 243, 11, 60, 144, 199, 229, 4, 243, 11, 60, 210, 119, 4, - 228, 241, 106, 210, 119, 4, 198, 153, 211, 66, 197, 225, 81, 249, 88, - 248, 168, 207, 65, 197, 225, 81, 249, 88, 4, 228, 241, 106, 197, 225, - 242, 84, 211, 66, 197, 225, 214, 88, 219, 179, 197, 225, 214, 88, 230, - 203, 235, 131, 202, 99, 219, 180, 211, 57, 234, 45, 159, 235, 131, 202, - 99, 230, 204, 211, 57, 234, 45, 159, 197, 225, 202, 24, 248, 168, 207, - 65, 220, 13, 197, 225, 81, 249, 88, 211, 66, 55, 202, 24, 211, 66, 63, - 81, 164, 215, 60, 63, 81, 164, 186, 234, 204, 63, 57, 186, 193, 105, 63, - 57, 202, 2, 234, 204, 63, 57, 202, 2, 193, 105, 63, 57, 45, 50, 63, 57, - 118, 62, 57, 196, 66, 62, 57, 235, 119, 62, 57, 186, 234, 204, 62, 57, - 186, 193, 105, 62, 57, 202, 2, 234, 204, 62, 57, 202, 2, 193, 105, 62, - 57, 45, 50, 62, 57, 133, 144, 62, 57, 96, 64, 4, 198, 136, 235, 118, 96, - 64, 4, 198, 136, 196, 65, 118, 64, 4, 198, 136, 235, 118, 118, 64, 4, - 198, 136, 196, 65, 51, 4, 198, 54, 132, 248, 139, 51, 4, 248, 77, 132, - 248, 139, 51, 4, 116, 50, 237, 39, 132, 248, 139, 51, 4, 110, 45, 237, - 39, 132, 248, 139, 237, 33, 4, 45, 132, 248, 139, 237, 33, 4, 50, 132, - 248, 139, 237, 33, 4, 198, 54, 132, 248, 139, 237, 33, 4, 248, 77, 132, - 248, 139, 235, 138, 201, 190, 62, 220, 13, 201, 190, 63, 220, 13, 201, - 190, 62, 195, 83, 2, 201, 190, 63, 195, 83, 2, 201, 190, 62, 210, 24, 63, - 210, 24, 63, 229, 182, 62, 229, 182, 228, 241, 62, 229, 182, 62, 220, 13, - 243, 10, 62, 216, 213, 237, 32, 63, 216, 213, 237, 32, 62, 216, 213, 218, - 232, 63, 216, 213, 218, 232, 62, 2, 237, 32, 62, 2, 218, 232, 63, 2, 218, - 232, 62, 228, 241, 234, 121, 63, 228, 241, 234, 121, 62, 81, 234, 121, - 63, 81, 234, 121, 45, 64, 4, 2, 243, 10, 115, 118, 250, 231, 45, 64, 4, - 47, 209, 81, 179, 118, 201, 183, 57, 118, 197, 13, 64, 4, 81, 106, 118, - 197, 13, 64, 4, 55, 81, 106, 118, 197, 13, 64, 232, 98, 164, 118, 197, - 13, 197, 225, 237, 216, 57, 118, 64, 4, 235, 138, 201, 80, 118, 64, 4, - 199, 216, 4, 81, 106, 118, 64, 4, 199, 216, 4, 55, 81, 106, 118, 197, 13, - 64, 4, 199, 215, 118, 197, 13, 64, 4, 199, 216, 4, 81, 106, 118, 197, 13, - 64, 4, 199, 216, 4, 55, 81, 106, 118, 64, 198, 216, 192, 235, 193, 139, - 64, 209, 58, 236, 231, 219, 224, 234, 43, 3, 93, 118, 57, 207, 19, 198, - 153, 211, 67, 93, 118, 57, 118, 64, 93, 207, 19, 251, 165, 234, 45, 159, - 96, 64, 198, 216, 230, 203, 96, 64, 198, 216, 200, 180, 118, 208, 26, 57, - 96, 208, 26, 57, 207, 19, 198, 153, 211, 67, 93, 96, 57, 96, 64, 93, 207, - 19, 251, 165, 234, 45, 159, 198, 153, 211, 67, 93, 118, 57, 118, 64, 93, - 251, 165, 234, 45, 159, 118, 64, 93, 207, 19, 198, 153, 211, 66, 96, 64, - 93, 207, 19, 198, 153, 211, 66, 235, 119, 197, 240, 191, 21, 57, 203, 40, - 202, 99, 186, 57, 203, 40, 249, 143, 202, 2, 57, 63, 216, 213, 201, 102, - 62, 2, 201, 102, 63, 2, 201, 102, 62, 206, 203, 210, 24, 63, 206, 203, - 210, 24, 88, 220, 13, 243, 10, 88, 211, 8, 4, 211, 8, 223, 117, 88, 243, - 11, 4, 243, 11, 223, 117, 88, 243, 10, 88, 47, 205, 154, 202, 99, 186, - 64, 4, 228, 250, 229, 235, 249, 143, 202, 2, 64, 4, 228, 250, 199, 215, - 202, 99, 186, 64, 4, 228, 241, 199, 215, 249, 143, 202, 2, 64, 4, 228, - 241, 199, 215, 248, 224, 64, 209, 58, 235, 119, 199, 25, 186, 234, 203, - 203, 40, 248, 224, 64, 209, 58, 235, 119, 199, 25, 186, 234, 203, 118, - 197, 240, 57, 196, 66, 197, 240, 57, 96, 197, 240, 57, 235, 119, 197, - 240, 57, 45, 50, 197, 240, 57, 133, 144, 197, 240, 57, 186, 193, 105, - 197, 240, 57, 186, 234, 204, 197, 240, 57, 202, 2, 234, 204, 197, 240, - 57, 202, 2, 193, 105, 197, 240, 57, 118, 197, 240, 237, 214, 57, 196, 66, - 197, 240, 237, 214, 57, 96, 197, 240, 237, 214, 57, 235, 119, 197, 240, - 237, 214, 57, 242, 221, 197, 240, 211, 77, 243, 11, 57, 251, 85, 197, - 240, 211, 77, 243, 11, 57, 118, 197, 240, 64, 119, 164, 196, 66, 197, - 240, 64, 119, 164, 96, 197, 240, 64, 119, 164, 235, 119, 197, 240, 64, - 119, 164, 186, 193, 105, 197, 240, 64, 119, 164, 186, 234, 204, 197, 240, - 64, 119, 164, 202, 2, 234, 204, 197, 240, 64, 119, 164, 202, 2, 193, 105, - 197, 240, 64, 119, 164, 118, 197, 240, 64, 4, 55, 228, 241, 106, 196, 66, - 197, 240, 64, 4, 55, 228, 241, 106, 96, 197, 240, 64, 4, 55, 228, 241, - 106, 235, 119, 197, 240, 64, 4, 55, 228, 241, 106, 228, 241, 199, 237, - 221, 222, 81, 199, 237, 221, 222, 118, 197, 240, 64, 139, 96, 197, 240, - 57, 196, 66, 197, 240, 64, 118, 79, 235, 119, 197, 240, 57, 96, 197, 240, - 64, 139, 118, 197, 240, 57, 235, 119, 197, 240, 64, 118, 79, 196, 66, - 197, 240, 57, 118, 197, 240, 210, 196, 250, 231, 196, 66, 197, 240, 210, - 196, 250, 231, 96, 197, 240, 210, 196, 250, 231, 235, 119, 197, 240, 210, - 196, 250, 231, 118, 62, 47, 63, 57, 196, 66, 62, 47, 63, 57, 96, 62, 47, - 63, 57, 235, 119, 62, 47, 63, 57, 251, 85, 197, 240, 50, 196, 221, 57, - 251, 85, 197, 240, 248, 77, 196, 221, 57, 251, 85, 197, 240, 45, 196, - 221, 57, 251, 85, 197, 240, 198, 54, 196, 221, 57, 207, 23, 219, 224, - 207, 23, 183, 214, 77, 219, 224, 214, 77, 183, 232, 128, 239, 2, 250, - 232, 243, 6, 251, 84, 96, 62, 57, 16, 40, 196, 255, 42, 234, 133, 198, - 225, 198, 52, 118, 234, 37, 250, 235, 198, 225, 206, 204, 196, 66, 234, - 37, 250, 235, 198, 225, 198, 52, 96, 234, 37, 250, 235, 198, 225, 219, - 220, 235, 119, 234, 37, 250, 235, 62, 118, 234, 37, 250, 235, 62, 196, - 66, 234, 37, 250, 235, 62, 96, 234, 37, 250, 235, 62, 235, 119, 234, 37, - 250, 235, 235, 119, 197, 240, 64, 4, 179, 198, 136, 219, 214, 235, 119, - 197, 240, 64, 4, 179, 198, 136, 206, 197, 196, 66, 197, 240, 64, 4, 179, - 198, 136, 219, 214, 196, 66, 197, 240, 64, 4, 179, 198, 136, 206, 197, - 118, 197, 240, 64, 4, 179, 198, 136, 196, 65, 96, 197, 240, 64, 4, 179, - 198, 136, 196, 65, 118, 197, 240, 64, 4, 179, 198, 136, 235, 118, 96, - 197, 240, 64, 4, 179, 198, 136, 235, 118, 62, 238, 163, 235, 119, 23, - 118, 57, 62, 238, 163, 235, 119, 23, 96, 57, 62, 238, 163, 196, 66, 23, - 118, 57, 62, 238, 163, 196, 66, 23, 96, 57, 62, 238, 163, 118, 23, 196, - 66, 57, 62, 238, 163, 96, 23, 196, 66, 57, 62, 238, 163, 118, 23, 235, - 119, 57, 62, 238, 163, 96, 23, 235, 119, 57, 206, 248, 64, 144, 219, 224, - 206, 248, 64, 144, 183, 206, 248, 64, 133, 219, 224, 206, 248, 64, 133, - 183, 206, 248, 64, 45, 196, 77, 206, 248, 64, 50, 196, 77, 206, 248, 64, - 45, 235, 123, 206, 248, 64, 50, 235, 123, 196, 66, 63, 64, 232, 98, 249, - 88, 4, 228, 241, 164, 133, 250, 236, 223, 163, 42, 207, 93, 248, 62, 211, - 1, 63, 201, 188, 211, 1, 63, 23, 62, 201, 188, 211, 1, 62, 201, 188, 249, - 107, 111, 4, 156, 192, 235, 47, 192, 235, 47, 28, 192, 235, 62, 51, 247, - 19, 62, 237, 33, 247, 19, 153, 62, 210, 24, 228, 241, 62, 211, 160, 62, - 211, 160, 62, 216, 213, 196, 76, 197, 242, 247, 19, 62, 216, 213, 235, - 122, 197, 242, 247, 19, 62, 216, 213, 219, 219, 197, 242, 247, 19, 62, - 216, 213, 206, 203, 197, 242, 247, 19, 214, 95, 232, 146, 109, 198, 54, - 132, 62, 243, 10, 248, 77, 132, 62, 243, 10, 156, 232, 128, 209, 60, 62, - 238, 159, 206, 122, 156, 232, 128, 209, 60, 62, 238, 159, 63, 232, 128, - 209, 60, 238, 159, 206, 122, 63, 232, 128, 209, 60, 238, 159, 51, 209, - 25, 223, 144, 196, 107, 56, 230, 187, 77, 209, 78, 232, 146, 109, 209, - 78, 232, 146, 138, 209, 78, 232, 146, 134, 209, 78, 232, 146, 149, 198, - 9, 208, 185, 250, 189, 228, 91, 209, 196, 214, 91, 63, 215, 206, 204, 33, - 62, 237, 33, 211, 105, 238, 217, 197, 202, 156, 215, 206, 250, 227, 238, - 179, 230, 88, 191, 75, 221, 2, 251, 53, 252, 32, 193, 247, 209, 26, 45, - 132, 62, 201, 102, 50, 132, 62, 201, 102, 201, 103, 4, 45, 132, 248, 139, - 201, 103, 4, 50, 132, 248, 139, 118, 197, 13, 64, 4, 197, 242, 250, 233, - 196, 66, 197, 13, 64, 4, 197, 242, 250, 233, 96, 197, 13, 64, 4, 197, - 242, 250, 233, 235, 119, 197, 13, 64, 4, 197, 242, 250, 233, 234, 27, - 232, 146, 107, 234, 27, 232, 146, 109, 205, 51, 206, 31, 250, 188, 16, - 195, 52, 206, 31, 250, 188, 16, 212, 254, 206, 31, 250, 188, 16, 208, 1, - 206, 31, 250, 188, 16, 248, 163, 206, 31, 250, 188, 16, 204, 16, 206, 31, - 250, 188, 16, 198, 0, 234, 43, 3, 4, 223, 140, 60, 196, 89, 113, 204, 12, - 113, 235, 128, 113, 210, 96, 113, 207, 18, 50, 251, 115, 229, 203, 210, - 78, 113, 135, 6, 1, 250, 122, 135, 6, 1, 247, 252, 135, 6, 1, 195, 151, - 135, 6, 1, 231, 18, 135, 6, 1, 236, 169, 135, 6, 1, 192, 49, 135, 6, 1, - 191, 55, 135, 6, 1, 235, 30, 135, 6, 1, 191, 82, 135, 6, 1, 223, 39, 135, - 6, 1, 89, 223, 39, 135, 6, 1, 68, 135, 6, 1, 236, 190, 135, 6, 1, 222, - 94, 135, 6, 1, 219, 75, 135, 6, 1, 215, 66, 135, 6, 1, 214, 210, 135, 6, - 1, 211, 89, 135, 6, 1, 209, 55, 135, 6, 1, 206, 179, 135, 6, 1, 202, 77, - 135, 6, 1, 197, 44, 135, 6, 1, 196, 124, 135, 6, 1, 232, 101, 135, 6, 1, - 229, 188, 135, 6, 1, 211, 20, 135, 6, 1, 210, 63, 135, 6, 1, 203, 8, 135, - 6, 1, 197, 146, 135, 6, 1, 243, 54, 135, 6, 1, 203, 165, 135, 6, 1, 192, - 58, 135, 6, 1, 192, 60, 135, 6, 1, 192, 93, 135, 6, 1, 201, 220, 140, - 135, 6, 1, 191, 225, 135, 6, 1, 2, 191, 190, 135, 6, 1, 2, 191, 191, 4, - 199, 215, 135, 6, 1, 192, 12, 135, 6, 1, 223, 82, 2, 191, 190, 135, 6, 1, - 248, 175, 191, 190, 135, 6, 1, 223, 82, 248, 175, 191, 190, 135, 6, 1, - 232, 228, 135, 6, 1, 223, 37, 135, 6, 1, 203, 7, 135, 6, 1, 197, 215, 65, - 135, 6, 1, 220, 1, 215, 66, 135, 6, 1, 247, 73, 243, 54, 135, 2, 1, 250, - 122, 135, 2, 1, 247, 252, 135, 2, 1, 195, 151, 135, 2, 1, 231, 18, 135, - 2, 1, 236, 169, 135, 2, 1, 192, 49, 135, 2, 1, 191, 55, 135, 2, 1, 235, - 30, 135, 2, 1, 191, 82, 135, 2, 1, 223, 39, 135, 2, 1, 89, 223, 39, 135, - 2, 1, 68, 135, 2, 1, 236, 190, 135, 2, 1, 222, 94, 135, 2, 1, 219, 75, - 135, 2, 1, 215, 66, 135, 2, 1, 214, 210, 135, 2, 1, 211, 89, 135, 2, 1, - 209, 55, 135, 2, 1, 206, 179, 135, 2, 1, 202, 77, 135, 2, 1, 197, 44, - 135, 2, 1, 196, 124, 135, 2, 1, 232, 101, 135, 2, 1, 229, 188, 135, 2, 1, - 211, 20, 135, 2, 1, 210, 63, 135, 2, 1, 203, 8, 135, 2, 1, 197, 146, 135, - 2, 1, 243, 54, 135, 2, 1, 203, 165, 135, 2, 1, 192, 58, 135, 2, 1, 192, - 60, 135, 2, 1, 192, 93, 135, 2, 1, 201, 220, 140, 135, 2, 1, 191, 225, - 135, 2, 1, 2, 191, 190, 135, 2, 1, 2, 191, 191, 4, 199, 215, 135, 2, 1, - 192, 12, 135, 2, 1, 223, 82, 2, 191, 190, 135, 2, 1, 248, 175, 191, 190, - 135, 2, 1, 223, 82, 248, 175, 191, 190, 135, 2, 1, 232, 228, 135, 2, 1, - 223, 37, 135, 2, 1, 203, 7, 135, 2, 1, 197, 215, 65, 135, 2, 1, 220, 1, - 215, 66, 135, 2, 1, 247, 73, 243, 54, 8, 6, 1, 220, 143, 4, 55, 164, 8, - 2, 1, 220, 143, 4, 55, 164, 8, 6, 1, 220, 143, 4, 82, 198, 152, 8, 6, 1, - 210, 237, 4, 106, 8, 6, 1, 207, 222, 4, 199, 215, 8, 2, 1, 42, 4, 106, 8, - 2, 1, 200, 44, 4, 237, 39, 106, 8, 6, 1, 230, 117, 4, 237, 87, 8, 2, 1, - 230, 117, 4, 237, 87, 8, 6, 1, 222, 153, 4, 237, 87, 8, 2, 1, 222, 153, - 4, 237, 87, 8, 6, 1, 191, 167, 4, 237, 87, 8, 2, 1, 191, 167, 4, 237, 87, - 8, 6, 1, 251, 160, 8, 6, 1, 218, 169, 4, 102, 8, 6, 1, 153, 65, 8, 6, 1, - 153, 251, 160, 8, 2, 1, 196, 13, 4, 50, 102, 8, 6, 1, 193, 225, 4, 102, - 8, 2, 1, 193, 225, 4, 102, 8, 2, 1, 196, 13, 4, 238, 175, 8, 6, 1, 132, - 230, 116, 8, 2, 1, 132, 230, 116, 8, 2, 1, 199, 213, 209, 211, 8, 2, 1, - 235, 15, 4, 213, 9, 8, 2, 1, 153, 207, 222, 4, 199, 215, 8, 2, 1, 187, 4, - 130, 206, 189, 223, 117, 8, 1, 2, 6, 153, 71, 8, 200, 230, 2, 1, 223, 35, - 52, 1, 6, 196, 12, 8, 6, 1, 206, 9, 4, 200, 146, 199, 215, 8, 6, 1, 191, - 167, 4, 200, 146, 199, 215, 94, 6, 1, 251, 186, 94, 2, 1, 251, 186, 94, - 6, 1, 195, 66, 94, 2, 1, 195, 66, 94, 6, 1, 231, 211, 94, 2, 1, 231, 211, - 94, 6, 1, 237, 255, 94, 2, 1, 237, 255, 94, 6, 1, 234, 165, 94, 2, 1, - 234, 165, 94, 6, 1, 202, 7, 94, 2, 1, 202, 7, 94, 6, 1, 191, 95, 94, 2, - 1, 191, 95, 94, 6, 1, 230, 6, 94, 2, 1, 230, 6, 94, 6, 1, 199, 13, 94, 2, - 1, 199, 13, 94, 6, 1, 228, 32, 94, 2, 1, 228, 32, 94, 6, 1, 222, 77, 94, - 2, 1, 222, 77, 94, 6, 1, 219, 252, 94, 2, 1, 219, 252, 94, 6, 1, 216, - 100, 94, 2, 1, 216, 100, 94, 6, 1, 213, 219, 94, 2, 1, 213, 219, 94, 6, - 1, 220, 248, 94, 2, 1, 220, 248, 94, 6, 1, 74, 94, 2, 1, 74, 94, 6, 1, - 209, 185, 94, 2, 1, 209, 185, 94, 6, 1, 206, 162, 94, 2, 1, 206, 162, 94, - 6, 1, 202, 183, 94, 2, 1, 202, 183, 94, 6, 1, 199, 166, 94, 2, 1, 199, - 166, 94, 6, 1, 196, 168, 94, 2, 1, 196, 168, 94, 6, 1, 233, 23, 94, 2, 1, - 233, 23, 94, 6, 1, 221, 190, 94, 2, 1, 221, 190, 94, 6, 1, 208, 176, 94, - 2, 1, 208, 176, 94, 6, 1, 211, 81, 94, 2, 1, 211, 81, 94, 6, 1, 237, 37, - 251, 192, 94, 2, 1, 237, 37, 251, 192, 94, 6, 1, 39, 94, 251, 230, 94, 2, - 1, 39, 94, 251, 230, 94, 6, 1, 238, 198, 234, 165, 94, 2, 1, 238, 198, - 234, 165, 94, 6, 1, 237, 37, 222, 77, 94, 2, 1, 237, 37, 222, 77, 94, 6, - 1, 237, 37, 213, 219, 94, 2, 1, 237, 37, 213, 219, 94, 6, 1, 238, 198, - 213, 219, 94, 2, 1, 238, 198, 213, 219, 94, 6, 1, 39, 94, 211, 81, 94, 2, - 1, 39, 94, 211, 81, 94, 6, 1, 205, 145, 94, 2, 1, 205, 145, 94, 6, 1, - 238, 214, 203, 105, 94, 2, 1, 238, 214, 203, 105, 94, 6, 1, 39, 94, 203, - 105, 94, 2, 1, 39, 94, 203, 105, 94, 6, 1, 39, 94, 234, 12, 94, 2, 1, 39, - 94, 234, 12, 94, 6, 1, 251, 212, 221, 195, 94, 2, 1, 251, 212, 221, 195, - 94, 6, 1, 237, 37, 228, 242, 94, 2, 1, 237, 37, 228, 242, 94, 6, 1, 39, - 94, 228, 242, 94, 2, 1, 39, 94, 228, 242, 94, 6, 1, 39, 94, 140, 94, 2, - 1, 39, 94, 140, 94, 6, 1, 220, 142, 140, 94, 2, 1, 220, 142, 140, 94, 6, - 1, 39, 94, 229, 209, 94, 2, 1, 39, 94, 229, 209, 94, 6, 1, 39, 94, 230, - 9, 94, 2, 1, 39, 94, 230, 9, 94, 6, 1, 39, 94, 231, 206, 94, 2, 1, 39, - 94, 231, 206, 94, 6, 1, 39, 94, 236, 193, 94, 2, 1, 39, 94, 236, 193, 94, - 6, 1, 39, 94, 203, 71, 94, 2, 1, 39, 94, 203, 71, 94, 6, 1, 39, 212, 145, - 203, 71, 94, 2, 1, 39, 212, 145, 203, 71, 94, 6, 1, 39, 212, 145, 214, - 16, 94, 2, 1, 39, 212, 145, 214, 16, 94, 6, 1, 39, 212, 145, 212, 81, 94, - 2, 1, 39, 212, 145, 212, 81, 94, 6, 1, 39, 212, 145, 193, 140, 94, 2, 1, - 39, 212, 145, 193, 140, 94, 16, 222, 102, 94, 16, 216, 101, 206, 162, 94, - 16, 209, 186, 206, 162, 94, 16, 201, 89, 94, 16, 199, 167, 206, 162, 94, - 16, 221, 191, 206, 162, 94, 16, 203, 72, 202, 183, 94, 6, 1, 238, 198, - 203, 105, 94, 2, 1, 238, 198, 203, 105, 94, 6, 1, 238, 198, 231, 206, 94, - 2, 1, 238, 198, 231, 206, 94, 33, 213, 220, 58, 94, 33, 201, 213, 250, - 201, 94, 33, 201, 213, 219, 188, 94, 6, 1, 248, 103, 221, 195, 94, 2, 1, - 248, 103, 221, 195, 94, 39, 212, 145, 232, 80, 201, 63, 94, 39, 212, 145, - 236, 234, 208, 13, 77, 94, 39, 212, 145, 223, 142, 208, 13, 77, 94, 39, - 212, 145, 195, 137, 236, 205, 94, 232, 118, 91, 230, 70, 94, 232, 80, - 201, 63, 94, 215, 200, 236, 205, 101, 2, 1, 251, 132, 101, 2, 1, 249, - 101, 101, 2, 1, 231, 210, 101, 2, 1, 236, 150, 101, 2, 1, 234, 103, 101, - 2, 1, 195, 49, 101, 2, 1, 191, 80, 101, 2, 1, 199, 193, 101, 2, 1, 223, - 162, 101, 2, 1, 222, 87, 101, 2, 1, 220, 7, 101, 2, 1, 217, 90, 101, 2, - 1, 214, 216, 101, 2, 1, 211, 104, 101, 2, 1, 210, 131, 101, 2, 1, 191, - 67, 101, 2, 1, 207, 163, 101, 2, 1, 205, 142, 101, 2, 1, 199, 179, 101, - 2, 1, 196, 113, 101, 2, 1, 209, 220, 101, 2, 1, 221, 200, 101, 2, 1, 231, - 82, 101, 2, 1, 208, 81, 101, 2, 1, 203, 69, 101, 2, 1, 243, 81, 101, 2, - 1, 247, 128, 101, 2, 1, 222, 234, 101, 2, 1, 243, 18, 101, 2, 1, 246, - 241, 101, 2, 1, 192, 218, 101, 2, 1, 222, 249, 101, 2, 1, 230, 87, 101, - 2, 1, 229, 245, 101, 2, 1, 229, 145, 101, 2, 1, 193, 125, 101, 2, 1, 230, - 19, 101, 2, 1, 229, 11, 101, 2, 1, 192, 14, 101, 2, 1, 252, 14, 198, 175, - 1, 170, 198, 175, 1, 192, 136, 198, 175, 1, 192, 135, 198, 175, 1, 192, - 125, 198, 175, 1, 192, 123, 198, 175, 1, 248, 218, 252, 62, 192, 118, - 198, 175, 1, 192, 118, 198, 175, 1, 192, 133, 198, 175, 1, 192, 130, 198, - 175, 1, 192, 132, 198, 175, 1, 192, 131, 198, 175, 1, 192, 40, 198, 175, - 1, 192, 127, 198, 175, 1, 192, 116, 198, 175, 1, 197, 86, 192, 116, 198, - 175, 1, 192, 113, 198, 175, 1, 192, 121, 198, 175, 1, 248, 218, 252, 62, - 192, 121, 198, 175, 1, 197, 86, 192, 121, 198, 175, 1, 192, 120, 198, - 175, 1, 192, 140, 198, 175, 1, 192, 114, 198, 175, 1, 197, 86, 192, 114, - 198, 175, 1, 192, 103, 198, 175, 1, 197, 86, 192, 103, 198, 175, 1, 192, - 33, 198, 175, 1, 192, 82, 198, 175, 1, 251, 243, 192, 82, 198, 175, 1, - 197, 86, 192, 82, 198, 175, 1, 192, 112, 198, 175, 1, 192, 111, 198, 175, - 1, 192, 108, 198, 175, 1, 197, 86, 192, 122, 198, 175, 1, 197, 86, 192, - 106, 198, 175, 1, 192, 104, 198, 175, 1, 191, 225, 198, 175, 1, 192, 101, - 198, 175, 1, 192, 99, 198, 175, 1, 192, 124, 198, 175, 1, 197, 86, 192, - 124, 198, 175, 1, 250, 127, 192, 124, 198, 175, 1, 192, 98, 198, 175, 1, - 192, 96, 198, 175, 1, 192, 97, 198, 175, 1, 192, 95, 198, 175, 1, 192, - 94, 198, 175, 1, 192, 134, 198, 175, 1, 192, 92, 198, 175, 1, 192, 90, - 198, 175, 1, 192, 89, 198, 175, 1, 192, 86, 198, 175, 1, 192, 83, 198, - 175, 1, 199, 157, 192, 83, 198, 175, 1, 192, 81, 198, 175, 1, 192, 80, - 198, 175, 1, 192, 12, 198, 175, 52, 1, 220, 115, 77, 198, 175, 204, 11, - 77, 198, 175, 120, 222, 196, 36, 5, 219, 42, 36, 5, 216, 5, 36, 5, 206, - 154, 36, 5, 202, 38, 36, 5, 203, 55, 36, 5, 248, 110, 36, 5, 198, 91, 36, - 5, 242, 98, 36, 5, 213, 36, 36, 5, 212, 64, 36, 5, 231, 11, 211, 182, 36, - 5, 191, 6, 36, 5, 236, 172, 36, 5, 237, 160, 36, 5, 222, 200, 36, 5, 198, - 240, 36, 5, 243, 67, 36, 5, 209, 198, 36, 5, 209, 72, 36, 5, 231, 97, 36, - 5, 231, 93, 36, 5, 231, 94, 36, 5, 231, 95, 36, 5, 201, 175, 36, 5, 201, - 129, 36, 5, 201, 142, 36, 5, 201, 174, 36, 5, 201, 147, 36, 5, 201, 148, - 36, 5, 201, 134, 36, 5, 247, 65, 36, 5, 247, 44, 36, 5, 247, 46, 36, 5, - 247, 64, 36, 5, 247, 62, 36, 5, 247, 63, 36, 5, 247, 45, 36, 5, 190, 224, - 36, 5, 190, 202, 36, 5, 190, 215, 36, 5, 190, 223, 36, 5, 190, 218, 36, - 5, 190, 219, 36, 5, 190, 207, 36, 5, 247, 60, 36, 5, 247, 47, 36, 5, 247, - 49, 36, 5, 247, 59, 36, 5, 247, 57, 36, 5, 247, 58, 36, 5, 247, 48, 36, - 5, 207, 234, 36, 5, 207, 224, 36, 5, 207, 230, 36, 5, 207, 233, 36, 5, - 207, 231, 36, 5, 207, 232, 36, 5, 207, 229, 36, 5, 220, 153, 36, 5, 220, - 145, 36, 5, 220, 148, 36, 5, 220, 152, 36, 5, 220, 149, 36, 5, 220, 150, - 36, 5, 220, 146, 36, 5, 192, 175, 36, 5, 192, 162, 36, 5, 192, 170, 36, - 5, 192, 174, 36, 5, 192, 172, 36, 5, 192, 173, 36, 5, 192, 169, 36, 5, - 230, 128, 36, 5, 230, 118, 36, 5, 230, 121, 36, 5, 230, 127, 36, 5, 230, - 123, 36, 5, 230, 124, 36, 5, 230, 120, 33, 38, 1, 249, 17, 33, 38, 1, - 195, 153, 33, 38, 1, 231, 77, 33, 38, 1, 237, 146, 33, 38, 1, 191, 62, - 33, 38, 1, 191, 87, 33, 38, 1, 155, 33, 38, 1, 234, 140, 33, 38, 1, 234, - 114, 33, 38, 1, 234, 103, 33, 38, 1, 74, 33, 38, 1, 210, 63, 33, 38, 1, - 234, 34, 33, 38, 1, 234, 22, 33, 38, 1, 199, 145, 33, 38, 1, 140, 33, 38, - 1, 197, 161, 33, 38, 1, 243, 127, 33, 38, 1, 203, 165, 33, 38, 1, 203, - 116, 33, 38, 1, 232, 228, 33, 38, 1, 234, 18, 33, 38, 1, 65, 33, 38, 1, - 223, 226, 33, 38, 1, 236, 191, 33, 38, 1, 215, 219, 196, 128, 33, 38, 1, - 192, 95, 33, 38, 1, 191, 225, 33, 38, 1, 223, 81, 65, 33, 38, 1, 219, 83, - 191, 190, 33, 38, 1, 248, 175, 191, 190, 33, 38, 1, 223, 81, 248, 175, - 191, 190, 50, 251, 116, 200, 225, 217, 51, 50, 251, 116, 235, 138, 200, - 225, 217, 51, 45, 200, 225, 248, 53, 50, 200, 225, 248, 53, 45, 235, 138, - 200, 225, 248, 53, 50, 235, 138, 200, 225, 248, 53, 207, 147, 223, 104, - 217, 51, 207, 147, 235, 138, 223, 104, 217, 51, 235, 138, 198, 8, 217, - 51, 45, 198, 8, 248, 53, 50, 198, 8, 248, 53, 207, 147, 201, 190, 45, - 207, 147, 211, 106, 248, 53, 50, 207, 147, 211, 106, 248, 53, 234, 189, - 238, 254, 210, 126, 232, 148, 210, 126, 207, 18, 232, 148, 210, 126, 228, - 85, 235, 138, 211, 177, 235, 119, 251, 126, 196, 66, 251, 126, 235, 138, - 206, 203, 251, 115, 55, 211, 172, 228, 88, 223, 93, 223, 102, 210, 183, - 248, 47, 228, 89, 4, 237, 42, 198, 153, 4, 206, 189, 58, 45, 130, 210, - 116, 248, 53, 50, 130, 210, 116, 248, 53, 198, 153, 4, 75, 58, 198, 153, - 4, 75, 60, 45, 81, 249, 88, 4, 208, 7, 50, 81, 249, 88, 4, 208, 7, 198, - 54, 45, 132, 248, 53, 198, 54, 50, 132, 248, 53, 248, 77, 45, 132, 248, - 53, 248, 77, 50, 132, 248, 53, 45, 202, 206, 126, 248, 53, 50, 202, 206, - 126, 248, 53, 45, 55, 210, 113, 50, 55, 210, 113, 105, 185, 139, 91, 75, - 208, 151, 91, 75, 139, 105, 185, 208, 151, 112, 232, 128, 75, 208, 151, - 232, 226, 75, 77, 207, 18, 208, 13, 77, 81, 198, 152, 206, 189, 209, 61, - 193, 23, 204, 11, 82, 236, 140, 153, 242, 74, 207, 147, 236, 140, 207, - 147, 242, 74, 153, 204, 25, 238, 15, 4, 45, 230, 173, 238, 15, 4, 50, - 230, 173, 153, 238, 14, 198, 54, 132, 205, 54, 56, 197, 14, 237, 215, - 198, 223, 237, 215, 201, 79, 232, 80, 201, 63, 81, 202, 136, 236, 138, - 193, 72, 81, 219, 112, 247, 109, 55, 228, 88, 207, 18, 242, 74, 55, 218, - 237, 207, 252, 77, 237, 216, 4, 45, 196, 69, 55, 200, 164, 77, 223, 93, - 130, 222, 35, 223, 93, 130, 222, 36, 4, 222, 36, 58, 130, 222, 35, 130, - 222, 36, 4, 236, 140, 55, 201, 114, 242, 74, 235, 138, 202, 23, 197, 225, - 238, 14, 216, 214, 242, 74, 210, 125, 77, 208, 150, 234, 129, 77, 238, - 255, 195, 137, 236, 205, 238, 218, 210, 82, 4, 50, 238, 216, 238, 218, - 210, 82, 4, 45, 238, 216, 198, 128, 3, 6, 233, 255, 216, 214, 233, 216, - 77, 216, 214, 208, 13, 77, 45, 51, 248, 54, 4, 106, 50, 51, 248, 54, 4, - 106, 45, 51, 248, 54, 4, 55, 106, 50, 51, 248, 54, 4, 55, 106, 198, 54, - 132, 45, 210, 113, 198, 54, 132, 50, 210, 113, 248, 77, 132, 45, 210, - 113, 248, 77, 132, 50, 210, 113, 211, 172, 228, 88, 12, 48, 207, 48, 12, - 48, 242, 230, 12, 48, 205, 57, 107, 12, 48, 205, 57, 109, 12, 48, 205, - 57, 138, 12, 48, 209, 250, 12, 48, 248, 62, 12, 48, 199, 233, 12, 48, - 221, 79, 107, 12, 48, 221, 79, 109, 12, 48, 236, 202, 12, 48, 205, 61, - 12, 48, 2, 107, 12, 48, 2, 109, 12, 48, 220, 30, 107, 12, 48, 220, 30, - 109, 12, 48, 220, 30, 138, 12, 48, 220, 30, 134, 12, 48, 202, 58, 12, 48, - 198, 227, 12, 48, 202, 55, 107, 12, 48, 202, 55, 109, 12, 48, 229, 224, - 107, 12, 48, 229, 224, 109, 12, 48, 230, 53, 12, 48, 207, 136, 12, 48, - 243, 64, 12, 48, 200, 198, 12, 48, 215, 205, 12, 48, 237, 143, 12, 48, - 215, 193, 12, 48, 242, 249, 12, 48, 193, 144, 107, 12, 48, 193, 144, 109, - 12, 48, 232, 243, 12, 48, 210, 76, 107, 12, 48, 210, 76, 109, 12, 48, - 202, 178, 132, 197, 255, 197, 177, 12, 48, 238, 239, 12, 48, 236, 162, - 12, 48, 223, 27, 12, 48, 248, 102, 79, 242, 213, 12, 48, 233, 193, 12, - 48, 201, 215, 107, 12, 48, 201, 215, 109, 12, 48, 249, 103, 12, 48, 202, - 185, 12, 48, 247, 190, 202, 185, 12, 48, 214, 86, 107, 12, 48, 214, 86, - 109, 12, 48, 214, 86, 138, 12, 48, 214, 86, 134, 12, 48, 216, 172, 12, - 48, 203, 107, 12, 48, 207, 142, 12, 48, 233, 223, 12, 48, 211, 119, 12, - 48, 248, 18, 107, 12, 48, 248, 18, 109, 12, 48, 216, 224, 12, 48, 215, - 199, 12, 48, 230, 214, 107, 12, 48, 230, 214, 109, 12, 48, 230, 214, 138, - 12, 48, 198, 173, 12, 48, 242, 212, 12, 48, 193, 105, 107, 12, 48, 193, - 105, 109, 12, 48, 247, 190, 205, 50, 12, 48, 202, 178, 228, 187, 12, 48, - 228, 187, 12, 48, 247, 190, 201, 229, 12, 48, 247, 190, 203, 102, 12, 48, - 232, 159, 12, 48, 247, 190, 247, 85, 12, 48, 202, 178, 193, 169, 12, 48, - 193, 170, 107, 12, 48, 193, 170, 109, 12, 48, 242, 252, 12, 48, 247, 190, - 230, 250, 12, 48, 179, 107, 12, 48, 179, 109, 12, 48, 247, 190, 219, 19, - 12, 48, 247, 190, 231, 191, 12, 48, 215, 188, 107, 12, 48, 215, 188, 109, - 12, 48, 207, 149, 12, 48, 248, 114, 12, 48, 247, 190, 199, 185, 219, 230, - 12, 48, 247, 190, 219, 233, 12, 48, 247, 190, 193, 66, 12, 48, 247, 190, - 232, 179, 12, 48, 234, 201, 107, 12, 48, 234, 201, 109, 12, 48, 234, 201, - 138, 12, 48, 247, 190, 234, 200, 12, 48, 229, 235, 12, 48, 247, 190, 228, - 183, 12, 48, 248, 98, 12, 48, 231, 61, 12, 48, 247, 190, 232, 236, 12, - 48, 247, 190, 248, 160, 12, 48, 247, 190, 205, 158, 12, 48, 202, 178, - 193, 95, 12, 48, 202, 178, 192, 72, 12, 48, 247, 190, 232, 99, 12, 48, - 223, 34, 233, 228, 12, 48, 247, 190, 233, 228, 12, 48, 223, 34, 198, 56, - 12, 48, 247, 190, 198, 56, 12, 48, 223, 34, 235, 111, 12, 48, 247, 190, - 235, 111, 12, 48, 197, 55, 12, 48, 223, 34, 197, 55, 12, 48, 247, 190, - 197, 55, 83, 48, 107, 83, 48, 219, 112, 83, 48, 236, 140, 83, 48, 202, - 97, 83, 48, 205, 56, 83, 48, 102, 83, 48, 109, 83, 48, 219, 141, 83, 48, - 217, 90, 83, 48, 219, 209, 83, 48, 234, 77, 83, 48, 171, 83, 48, 144, - 248, 62, 83, 48, 238, 242, 83, 48, 228, 26, 83, 48, 199, 233, 83, 48, - 211, 77, 248, 62, 83, 48, 221, 78, 83, 48, 208, 254, 83, 48, 193, 12, 83, - 48, 201, 203, 83, 48, 50, 211, 77, 248, 62, 83, 48, 229, 146, 234, 98, - 83, 48, 199, 95, 83, 48, 236, 202, 83, 48, 205, 61, 83, 48, 242, 230, 83, - 48, 208, 204, 83, 48, 251, 252, 83, 48, 215, 179, 83, 48, 234, 98, 83, - 48, 234, 207, 83, 48, 205, 91, 83, 48, 231, 3, 83, 48, 231, 4, 202, 74, - 83, 48, 233, 227, 83, 48, 248, 174, 83, 48, 193, 35, 83, 48, 243, 86, 83, - 48, 206, 133, 83, 48, 223, 158, 83, 48, 202, 70, 83, 48, 220, 29, 83, 48, - 238, 252, 83, 48, 201, 194, 83, 48, 215, 184, 83, 48, 206, 176, 83, 48, - 193, 20, 83, 48, 211, 95, 83, 48, 197, 63, 83, 48, 235, 91, 83, 48, 203, - 40, 198, 227, 83, 48, 235, 138, 242, 230, 83, 48, 179, 201, 34, 83, 48, - 105, 230, 28, 83, 48, 203, 46, 83, 48, 248, 69, 83, 48, 202, 54, 83, 48, - 248, 25, 83, 48, 201, 78, 83, 48, 229, 223, 83, 48, 230, 71, 83, 48, 236, - 144, 83, 48, 230, 53, 83, 48, 248, 47, 83, 48, 207, 136, 83, 48, 205, 74, - 83, 48, 236, 236, 83, 48, 250, 132, 83, 48, 201, 190, 83, 48, 213, 11, - 83, 48, 200, 198, 83, 48, 205, 103, 83, 48, 215, 205, 83, 48, 197, 254, - 83, 48, 220, 111, 83, 48, 201, 63, 83, 48, 237, 143, 83, 48, 193, 120, - 83, 48, 236, 175, 213, 11, 83, 48, 242, 70, 83, 48, 232, 72, 83, 48, 242, - 243, 83, 48, 201, 84, 83, 48, 193, 143, 83, 48, 232, 243, 83, 48, 242, - 239, 83, 48, 233, 66, 83, 48, 55, 192, 235, 83, 48, 132, 197, 255, 197, - 177, 83, 48, 202, 88, 83, 48, 233, 78, 83, 48, 238, 239, 83, 48, 236, - 162, 83, 48, 208, 199, 83, 48, 223, 27, 83, 48, 216, 196, 83, 48, 198, - 151, 83, 48, 200, 141, 83, 48, 219, 135, 83, 48, 196, 43, 83, 48, 233, - 21, 83, 48, 248, 102, 79, 242, 213, 83, 48, 202, 212, 83, 48, 235, 138, - 199, 87, 83, 48, 193, 89, 83, 48, 202, 107, 83, 48, 236, 222, 83, 48, - 233, 193, 83, 48, 201, 232, 83, 48, 57, 83, 48, 201, 65, 83, 48, 201, - 214, 83, 48, 198, 25, 83, 48, 230, 223, 83, 48, 247, 70, 83, 48, 201, - 107, 83, 48, 249, 103, 83, 48, 206, 245, 83, 48, 202, 185, 83, 48, 223, - 18, 83, 48, 214, 85, 83, 48, 203, 107, 83, 48, 233, 54, 83, 48, 211, 119, - 83, 48, 251, 125, 83, 48, 209, 89, 83, 48, 234, 211, 83, 48, 248, 17, 83, - 48, 216, 224, 83, 48, 216, 37, 83, 48, 204, 32, 83, 48, 250, 239, 83, 48, - 215, 199, 83, 48, 198, 61, 83, 48, 211, 64, 83, 48, 248, 106, 83, 48, - 201, 59, 83, 48, 242, 82, 83, 48, 230, 213, 83, 48, 198, 173, 83, 48, - 223, 121, 83, 48, 248, 120, 83, 48, 193, 170, 234, 98, 83, 48, 242, 212, - 83, 48, 193, 104, 83, 48, 205, 50, 83, 48, 228, 187, 83, 48, 201, 229, - 83, 48, 195, 180, 83, 48, 249, 12, 83, 48, 209, 147, 83, 48, 249, 133, - 83, 48, 203, 102, 83, 48, 207, 86, 83, 48, 206, 45, 83, 48, 232, 159, 83, - 48, 248, 104, 83, 48, 247, 85, 83, 48, 248, 144, 83, 48, 215, 201, 83, - 48, 193, 169, 83, 48, 242, 252, 83, 48, 193, 62, 83, 48, 236, 214, 83, - 48, 195, 50, 83, 48, 230, 250, 83, 48, 219, 19, 83, 48, 231, 191, 83, 48, - 215, 187, 83, 48, 202, 96, 83, 48, 203, 40, 199, 214, 248, 160, 83, 48, - 207, 149, 83, 48, 248, 114, 83, 48, 193, 2, 83, 48, 233, 103, 83, 48, - 219, 230, 83, 48, 199, 185, 219, 230, 83, 48, 219, 226, 83, 48, 202, 4, - 83, 48, 219, 233, 83, 48, 193, 66, 83, 48, 232, 179, 83, 48, 234, 200, - 83, 48, 229, 235, 83, 48, 232, 116, 83, 48, 228, 183, 83, 48, 248, 98, - 83, 48, 199, 199, 83, 48, 230, 78, 83, 48, 233, 14, 83, 48, 205, 194, - 193, 62, 83, 48, 247, 72, 83, 48, 231, 61, 83, 48, 232, 236, 83, 48, 248, - 160, 83, 48, 205, 158, 83, 48, 237, 128, 83, 48, 193, 95, 83, 48, 229, - 199, 83, 48, 192, 72, 83, 48, 216, 49, 83, 48, 248, 139, 83, 48, 234, - 110, 83, 48, 232, 99, 83, 48, 197, 222, 83, 48, 235, 94, 83, 48, 207, - 130, 83, 48, 213, 13, 83, 48, 233, 228, 83, 48, 198, 56, 83, 48, 235, - 111, 83, 48, 197, 55, 83, 48, 232, 182, 154, 237, 85, 246, 240, 45, 119, - 183, 154, 237, 85, 246, 240, 93, 119, 60, 154, 237, 85, 246, 240, 45, - 119, 82, 23, 183, 154, 237, 85, 246, 240, 93, 119, 82, 23, 60, 154, 237, - 85, 246, 240, 232, 80, 200, 168, 154, 237, 85, 246, 240, 200, 169, 232, - 98, 58, 154, 237, 85, 246, 240, 200, 169, 232, 98, 60, 154, 237, 85, 246, - 240, 200, 169, 232, 98, 219, 224, 154, 237, 85, 246, 240, 200, 169, 232, - 98, 116, 219, 224, 154, 237, 85, 246, 240, 200, 169, 232, 98, 116, 183, - 154, 237, 85, 246, 240, 200, 169, 232, 98, 110, 219, 224, 154, 237, 85, - 246, 240, 211, 3, 154, 201, 247, 154, 242, 74, 154, 232, 80, 201, 63, - 236, 211, 77, 223, 19, 223, 141, 201, 106, 113, 154, 223, 51, 77, 154, - 242, 215, 77, 154, 31, 191, 77, 45, 251, 116, 248, 53, 50, 251, 116, 248, - 53, 45, 55, 251, 116, 248, 53, 50, 55, 251, 116, 248, 53, 45, 239, 2, - 248, 53, 50, 239, 2, 248, 53, 45, 63, 239, 2, 248, 53, 50, 63, 239, 2, - 248, 53, 45, 62, 219, 187, 248, 53, 50, 62, 219, 187, 248, 53, 209, 18, - 77, 231, 130, 77, 45, 198, 42, 203, 103, 248, 53, 50, 198, 42, 203, 103, - 248, 53, 45, 63, 219, 187, 248, 53, 50, 63, 219, 187, 248, 53, 45, 63, - 198, 42, 203, 103, 248, 53, 50, 63, 198, 42, 203, 103, 248, 53, 45, 63, - 51, 248, 53, 50, 63, 51, 248, 53, 193, 139, 237, 215, 207, 18, 55, 208, - 216, 207, 252, 77, 55, 208, 216, 207, 252, 77, 130, 55, 208, 216, 207, - 252, 77, 209, 18, 87, 233, 103, 230, 25, 212, 134, 107, 230, 25, 212, - 134, 109, 230, 25, 212, 134, 138, 230, 25, 212, 134, 134, 230, 25, 212, - 134, 149, 230, 25, 212, 134, 169, 230, 25, 212, 134, 175, 230, 25, 212, - 134, 171, 230, 25, 212, 134, 178, 154, 219, 168, 163, 77, 154, 206, 180, - 163, 77, 154, 237, 95, 163, 77, 154, 234, 76, 163, 77, 30, 202, 170, 75, - 163, 77, 30, 55, 75, 163, 77, 193, 135, 237, 215, 81, 222, 86, 207, 49, - 77, 81, 222, 86, 207, 49, 4, 195, 20, 202, 5, 77, 81, 222, 86, 207, 49, - 87, 116, 230, 70, 81, 222, 86, 207, 49, 4, 195, 20, 202, 5, 87, 116, 230, - 70, 81, 222, 86, 207, 49, 87, 110, 230, 70, 47, 209, 18, 77, 154, 199, - 109, 219, 113, 233, 51, 204, 11, 113, 230, 25, 212, 134, 199, 95, 230, - 25, 212, 134, 197, 32, 230, 25, 212, 134, 198, 249, 81, 154, 223, 51, 77, - 217, 31, 77, 210, 107, 251, 153, 77, 154, 67, 223, 144, 154, 132, 233, 6, - 201, 247, 229, 120, 1, 2, 65, 229, 120, 1, 65, 229, 120, 1, 2, 68, 229, - 120, 1, 68, 229, 120, 1, 2, 66, 229, 120, 1, 66, 229, 120, 1, 2, 71, 229, - 120, 1, 71, 229, 120, 1, 2, 74, 229, 120, 1, 74, 229, 120, 1, 155, 229, - 120, 1, 231, 240, 229, 120, 1, 221, 166, 229, 120, 1, 231, 53, 229, 120, - 1, 220, 232, 229, 120, 1, 230, 179, 229, 120, 1, 222, 22, 229, 120, 1, - 231, 165, 229, 120, 1, 221, 67, 229, 120, 1, 231, 3, 229, 120, 1, 188, - 229, 120, 1, 191, 123, 229, 120, 1, 202, 222, 229, 120, 1, 191, 30, 229, - 120, 1, 201, 4, 229, 120, 1, 190, 251, 229, 120, 1, 205, 68, 229, 120, 1, - 191, 87, 229, 120, 1, 202, 46, 229, 120, 1, 191, 7, 229, 120, 1, 190, - 190, 229, 120, 1, 238, 32, 229, 120, 1, 198, 193, 229, 120, 1, 237, 44, - 229, 120, 1, 2, 197, 94, 229, 120, 1, 197, 94, 229, 120, 1, 235, 89, 229, - 120, 1, 199, 145, 229, 120, 1, 237, 146, 229, 120, 1, 159, 229, 120, 1, - 236, 174, 229, 120, 1, 180, 229, 120, 1, 213, 219, 229, 120, 1, 212, 178, - 229, 120, 1, 214, 121, 229, 120, 1, 213, 43, 229, 120, 1, 140, 229, 120, - 1, 249, 153, 229, 120, 1, 168, 229, 120, 1, 229, 158, 229, 120, 1, 248, - 188, 229, 120, 1, 209, 185, 229, 120, 1, 228, 159, 229, 120, 1, 248, 10, - 229, 120, 1, 208, 165, 229, 120, 1, 229, 245, 229, 120, 1, 249, 17, 229, - 120, 1, 210, 63, 229, 120, 1, 229, 23, 229, 120, 1, 248, 111, 229, 120, - 1, 209, 73, 229, 120, 1, 174, 229, 120, 1, 216, 100, 229, 120, 1, 215, - 155, 229, 120, 1, 216, 232, 229, 120, 1, 216, 12, 229, 120, 1, 2, 170, - 229, 120, 1, 170, 229, 120, 1, 2, 191, 225, 229, 120, 1, 191, 225, 229, - 120, 1, 2, 192, 12, 229, 120, 1, 192, 12, 229, 120, 1, 165, 229, 120, 1, - 207, 1, 229, 120, 1, 206, 68, 229, 120, 1, 207, 113, 229, 120, 1, 206, - 162, 229, 120, 1, 2, 193, 190, 229, 120, 1, 193, 190, 229, 120, 1, 193, - 86, 229, 120, 1, 193, 125, 229, 120, 1, 193, 48, 229, 120, 1, 215, 61, - 229, 120, 1, 193, 249, 229, 120, 1, 2, 155, 229, 120, 1, 2, 222, 22, 33, - 222, 48, 195, 20, 202, 5, 77, 33, 222, 48, 204, 30, 202, 5, 77, 222, 48, - 195, 20, 202, 5, 77, 222, 48, 204, 30, 202, 5, 77, 229, 120, 223, 51, 77, - 229, 120, 195, 20, 223, 51, 77, 229, 120, 237, 3, 191, 242, 222, 48, 55, - 228, 88, 72, 1, 2, 65, 72, 1, 65, 72, 1, 2, 68, 72, 1, 68, 72, 1, 2, 66, - 72, 1, 66, 72, 1, 2, 71, 72, 1, 71, 72, 1, 2, 74, 72, 1, 74, 72, 1, 155, - 72, 1, 231, 240, 72, 1, 221, 166, 72, 1, 231, 53, 72, 1, 220, 232, 72, 1, - 230, 179, 72, 1, 222, 22, 72, 1, 231, 165, 72, 1, 221, 67, 72, 1, 231, 3, - 72, 1, 188, 72, 1, 191, 123, 72, 1, 202, 222, 72, 1, 191, 30, 72, 1, 201, - 4, 72, 1, 190, 251, 72, 1, 205, 68, 72, 1, 191, 87, 72, 1, 202, 46, 72, - 1, 191, 7, 72, 1, 190, 190, 72, 1, 238, 32, 72, 1, 198, 193, 72, 1, 237, - 44, 72, 1, 2, 197, 94, 72, 1, 197, 94, 72, 1, 235, 89, 72, 1, 199, 145, - 72, 1, 237, 146, 72, 1, 159, 72, 1, 236, 174, 72, 1, 180, 72, 1, 213, - 219, 72, 1, 212, 178, 72, 1, 214, 121, 72, 1, 213, 43, 72, 1, 140, 72, 1, - 249, 153, 72, 1, 168, 72, 1, 229, 158, 72, 1, 248, 188, 72, 1, 209, 185, - 72, 1, 228, 159, 72, 1, 248, 10, 72, 1, 208, 165, 72, 1, 229, 245, 72, 1, - 249, 17, 72, 1, 210, 63, 72, 1, 229, 23, 72, 1, 248, 111, 72, 1, 209, 73, - 72, 1, 174, 72, 1, 216, 100, 72, 1, 215, 155, 72, 1, 216, 232, 72, 1, - 216, 12, 72, 1, 2, 170, 72, 1, 170, 72, 1, 2, 191, 225, 72, 1, 191, 225, - 72, 1, 2, 192, 12, 72, 1, 192, 12, 72, 1, 165, 72, 1, 207, 1, 72, 1, 206, - 68, 72, 1, 207, 113, 72, 1, 206, 162, 72, 1, 2, 193, 190, 72, 1, 193, - 190, 72, 1, 193, 86, 72, 1, 193, 125, 72, 1, 193, 48, 72, 1, 215, 61, 72, - 1, 193, 249, 72, 1, 2, 155, 72, 1, 2, 222, 22, 72, 1, 195, 188, 72, 1, - 195, 69, 72, 1, 195, 153, 72, 1, 195, 24, 72, 82, 236, 140, 222, 48, 208, - 191, 202, 5, 77, 72, 223, 51, 77, 72, 195, 20, 223, 51, 77, 72, 237, 3, - 221, 27, 248, 88, 1, 250, 120, 248, 88, 1, 210, 236, 248, 88, 1, 218, - 168, 248, 88, 1, 233, 175, 248, 88, 1, 238, 127, 248, 88, 1, 200, 43, - 248, 88, 1, 215, 61, 248, 88, 1, 172, 248, 88, 1, 232, 51, 248, 88, 1, - 222, 152, 248, 88, 1, 230, 116, 248, 88, 1, 223, 35, 248, 88, 1, 208, - 104, 248, 88, 1, 192, 235, 248, 88, 1, 191, 72, 248, 88, 1, 247, 3, 248, - 88, 1, 203, 167, 248, 88, 1, 146, 248, 88, 1, 191, 166, 248, 88, 1, 247, - 193, 248, 88, 1, 206, 8, 248, 88, 1, 65, 248, 88, 1, 74, 248, 88, 1, 71, - 248, 88, 1, 234, 173, 248, 88, 1, 251, 236, 248, 88, 1, 234, 166, 248, - 88, 1, 250, 163, 248, 88, 1, 211, 19, 248, 88, 1, 251, 132, 248, 88, 1, - 234, 103, 248, 88, 1, 251, 122, 248, 88, 1, 234, 88, 248, 88, 1, 234, 34, - 248, 88, 1, 68, 248, 88, 1, 66, 248, 88, 1, 223, 49, 248, 88, 1, 196, 12, - 248, 88, 1, 214, 70, 248, 88, 1, 231, 7, 248, 88, 1, 223, 200, 248, 88, - 1, 187, 4, 75, 58, 248, 88, 1, 213, 80, 30, 1, 221, 113, 30, 1, 201, 167, - 30, 1, 221, 106, 30, 1, 213, 204, 30, 1, 213, 202, 30, 1, 213, 201, 30, - 1, 198, 168, 30, 1, 201, 156, 30, 1, 206, 239, 30, 1, 206, 234, 30, 1, - 206, 231, 30, 1, 206, 224, 30, 1, 206, 219, 30, 1, 206, 214, 30, 1, 206, - 225, 30, 1, 206, 237, 30, 1, 216, 77, 30, 1, 209, 169, 30, 1, 201, 164, - 30, 1, 209, 158, 30, 1, 202, 160, 30, 1, 201, 161, 30, 1, 223, 222, 30, - 1, 243, 24, 30, 1, 201, 171, 30, 1, 243, 91, 30, 1, 221, 188, 30, 1, 199, - 7, 30, 1, 209, 209, 30, 1, 229, 142, 30, 1, 65, 30, 1, 252, 25, 30, 1, - 170, 30, 1, 192, 129, 30, 1, 234, 65, 30, 1, 71, 30, 1, 192, 67, 30, 1, - 192, 80, 30, 1, 74, 30, 1, 193, 190, 30, 1, 193, 176, 30, 1, 211, 151, - 30, 1, 192, 12, 30, 1, 66, 30, 1, 193, 107, 30, 1, 193, 125, 30, 1, 193, - 86, 30, 1, 191, 225, 30, 1, 233, 242, 30, 1, 192, 33, 30, 1, 68, 30, 233, - 3, 30, 1, 201, 165, 30, 1, 213, 194, 30, 1, 213, 196, 30, 1, 213, 199, - 30, 1, 206, 232, 30, 1, 206, 213, 30, 1, 206, 221, 30, 1, 206, 226, 30, - 1, 206, 211, 30, 1, 216, 70, 30, 1, 216, 67, 30, 1, 216, 71, 30, 1, 222, - 71, 30, 1, 209, 164, 30, 1, 209, 150, 30, 1, 209, 156, 30, 1, 209, 153, - 30, 1, 209, 167, 30, 1, 209, 151, 30, 1, 222, 69, 30, 1, 222, 67, 30, 1, - 202, 153, 30, 1, 202, 151, 30, 1, 202, 143, 30, 1, 202, 148, 30, 1, 202, - 158, 30, 1, 210, 149, 30, 1, 201, 168, 30, 1, 192, 57, 30, 1, 192, 51, - 30, 1, 192, 52, 30, 1, 222, 70, 30, 1, 201, 169, 30, 1, 192, 63, 30, 1, - 192, 0, 30, 1, 191, 255, 30, 1, 192, 2, 30, 1, 191, 212, 30, 1, 191, 213, - 30, 1, 191, 216, 30, 1, 251, 25, 30, 1, 251, 19, 154, 251, 96, 219, 101, - 77, 154, 251, 96, 207, 19, 77, 154, 251, 96, 91, 77, 154, 251, 96, 105, - 77, 154, 251, 96, 115, 77, 154, 251, 96, 232, 128, 77, 154, 251, 96, 198, - 54, 77, 154, 251, 96, 82, 77, 154, 251, 96, 248, 77, 77, 154, 251, 96, - 232, 238, 77, 154, 251, 96, 205, 57, 77, 154, 251, 96, 199, 1, 77, 154, - 251, 96, 232, 121, 77, 154, 251, 96, 229, 220, 77, 154, 251, 96, 234, - 208, 77, 154, 251, 96, 217, 91, 77, 248, 88, 1, 248, 10, 248, 88, 1, 191, - 30, 248, 88, 1, 222, 244, 248, 88, 1, 230, 179, 248, 88, 1, 234, 188, - 248, 88, 1, 234, 85, 248, 88, 1, 211, 87, 248, 88, 1, 211, 91, 248, 88, - 1, 223, 77, 248, 88, 1, 251, 98, 248, 88, 1, 223, 128, 248, 88, 1, 196, - 83, 248, 88, 1, 223, 180, 248, 88, 1, 214, 48, 248, 88, 1, 251, 229, 248, - 88, 1, 250, 158, 248, 88, 1, 251, 149, 248, 88, 1, 211, 113, 248, 88, 1, - 211, 94, 248, 88, 1, 223, 125, 248, 88, 53, 1, 210, 236, 248, 88, 53, 1, - 200, 43, 248, 88, 53, 1, 222, 152, 248, 88, 53, 1, 230, 116, 248, 88, 1, - 231, 92, 248, 88, 1, 219, 160, 248, 88, 1, 190, 231, 248, 88, 53, 1, 232, - 51, 248, 88, 1, 230, 136, 248, 88, 1, 220, 180, 248, 88, 1, 211, 151, - 248, 88, 1, 251, 245, 12, 201, 28, 200, 43, 12, 201, 28, 193, 98, 12, - 201, 28, 192, 209, 12, 201, 28, 247, 206, 12, 201, 28, 200, 151, 12, 201, - 28, 228, 78, 12, 201, 28, 228, 82, 12, 201, 28, 228, 169, 12, 201, 28, - 228, 79, 12, 201, 28, 200, 46, 12, 201, 28, 228, 81, 12, 201, 28, 228, - 77, 12, 201, 28, 228, 167, 12, 201, 28, 228, 80, 12, 201, 28, 228, 76, - 12, 201, 28, 215, 61, 12, 201, 28, 230, 116, 12, 201, 28, 206, 8, 12, - 201, 28, 210, 236, 12, 201, 28, 201, 250, 12, 201, 28, 238, 127, 12, 201, - 28, 228, 83, 12, 201, 28, 229, 178, 12, 201, 28, 200, 55, 12, 201, 28, - 200, 128, 12, 201, 28, 201, 118, 12, 201, 28, 203, 173, 12, 201, 28, 210, - 67, 12, 201, 28, 208, 106, 12, 201, 28, 198, 99, 12, 201, 28, 200, 45, - 12, 201, 28, 200, 140, 12, 201, 28, 228, 94, 12, 201, 28, 228, 75, 12, - 201, 28, 209, 230, 12, 201, 28, 208, 104, 72, 1, 2, 220, 232, 72, 1, 2, - 202, 222, 72, 1, 2, 201, 4, 72, 1, 2, 159, 72, 1, 2, 212, 178, 72, 1, 2, - 140, 72, 1, 2, 229, 158, 72, 1, 2, 228, 159, 72, 1, 2, 229, 245, 72, 1, - 2, 229, 23, 72, 1, 2, 215, 155, 72, 1, 2, 165, 72, 1, 2, 207, 1, 72, 1, - 2, 206, 68, 72, 1, 2, 207, 113, 72, 1, 2, 206, 162, 127, 30, 221, 113, - 127, 30, 213, 204, 127, 30, 198, 168, 127, 30, 206, 239, 127, 30, 216, - 77, 127, 30, 209, 169, 127, 30, 202, 160, 127, 30, 223, 222, 127, 30, - 243, 24, 127, 30, 243, 91, 127, 30, 221, 188, 127, 30, 199, 7, 127, 30, - 209, 209, 127, 30, 229, 142, 127, 30, 221, 114, 65, 127, 30, 213, 205, - 65, 127, 30, 198, 169, 65, 127, 30, 206, 240, 65, 127, 30, 216, 78, 65, - 127, 30, 209, 170, 65, 127, 30, 202, 161, 65, 127, 30, 223, 223, 65, 127, - 30, 243, 25, 65, 127, 30, 243, 92, 65, 127, 30, 221, 189, 65, 127, 30, - 199, 8, 65, 127, 30, 209, 210, 65, 127, 30, 229, 143, 65, 127, 30, 243, - 25, 66, 127, 221, 32, 246, 240, 211, 129, 127, 221, 32, 246, 240, 187, - 228, 159, 127, 228, 14, 107, 127, 228, 14, 109, 127, 228, 14, 138, 127, - 228, 14, 134, 127, 228, 14, 149, 127, 228, 14, 169, 127, 228, 14, 175, - 127, 228, 14, 171, 127, 228, 14, 178, 127, 228, 14, 199, 95, 127, 228, - 14, 215, 205, 127, 228, 14, 232, 243, 127, 228, 14, 193, 143, 127, 228, - 14, 193, 28, 127, 228, 14, 216, 165, 127, 228, 14, 234, 207, 127, 228, - 14, 200, 198, 127, 228, 14, 201, 66, 127, 228, 14, 229, 255, 127, 228, - 14, 202, 35, 127, 228, 14, 214, 227, 127, 228, 14, 201, 231, 127, 228, - 14, 232, 254, 127, 228, 14, 239, 50, 127, 228, 14, 220, 114, 127, 228, - 14, 207, 42, 127, 228, 14, 247, 138, 127, 228, 14, 201, 10, 127, 228, 14, - 200, 178, 127, 228, 14, 234, 75, 127, 228, 14, 207, 32, 127, 228, 14, - 251, 168, 127, 228, 14, 233, 31, 127, 228, 14, 207, 30, 127, 228, 14, - 204, 32, 127, 228, 14, 207, 108, 47, 228, 14, 208, 12, 47, 228, 14, 221, - 140, 47, 228, 14, 205, 89, 47, 228, 14, 221, 27, 47, 31, 199, 96, 211, - 105, 62, 201, 190, 47, 31, 197, 33, 211, 105, 62, 201, 190, 47, 31, 198, - 250, 211, 105, 62, 201, 190, 47, 31, 232, 136, 211, 105, 62, 201, 190, - 47, 31, 233, 16, 211, 105, 62, 201, 190, 47, 31, 202, 121, 211, 105, 62, - 201, 190, 47, 31, 203, 242, 211, 105, 62, 201, 190, 47, 31, 234, 154, - 211, 105, 62, 201, 190, 210, 103, 56, 47, 31, 197, 33, 107, 47, 31, 197, - 33, 109, 47, 31, 197, 33, 138, 47, 31, 197, 33, 134, 47, 31, 197, 33, - 149, 47, 31, 197, 33, 169, 47, 31, 197, 33, 175, 47, 31, 197, 33, 171, - 47, 31, 197, 33, 178, 47, 31, 198, 249, 47, 31, 198, 250, 107, 47, 31, - 198, 250, 109, 47, 31, 198, 250, 138, 47, 31, 198, 250, 134, 47, 31, 198, - 250, 149, 47, 30, 221, 113, 47, 30, 213, 204, 47, 30, 198, 168, 47, 30, - 206, 239, 47, 30, 216, 77, 47, 30, 209, 169, 47, 30, 202, 160, 47, 30, - 223, 222, 47, 30, 243, 24, 47, 30, 243, 91, 47, 30, 221, 188, 47, 30, - 199, 7, 47, 30, 209, 209, 47, 30, 229, 142, 47, 30, 221, 114, 65, 47, 30, - 213, 205, 65, 47, 30, 198, 169, 65, 47, 30, 206, 240, 65, 47, 30, 216, - 78, 65, 47, 30, 209, 170, 65, 47, 30, 202, 161, 65, 47, 30, 223, 223, 65, - 47, 30, 243, 25, 65, 47, 30, 243, 92, 65, 47, 30, 221, 189, 65, 47, 30, - 199, 8, 65, 47, 30, 209, 210, 65, 47, 30, 229, 143, 65, 47, 221, 32, 246, - 240, 246, 247, 47, 221, 32, 246, 240, 222, 178, 47, 30, 223, 223, 66, - 221, 32, 201, 106, 113, 47, 228, 14, 107, 47, 228, 14, 109, 47, 228, 14, - 138, 47, 228, 14, 134, 47, 228, 14, 149, 47, 228, 14, 169, 47, 228, 14, - 175, 47, 228, 14, 171, 47, 228, 14, 178, 47, 228, 14, 199, 95, 47, 228, - 14, 215, 205, 47, 228, 14, 232, 243, 47, 228, 14, 193, 143, 47, 228, 14, - 193, 28, 47, 228, 14, 216, 165, 47, 228, 14, 234, 207, 47, 228, 14, 200, - 198, 47, 228, 14, 201, 66, 47, 228, 14, 229, 255, 47, 228, 14, 202, 35, - 47, 228, 14, 214, 227, 47, 228, 14, 201, 231, 47, 228, 14, 232, 254, 47, - 228, 14, 239, 50, 47, 228, 14, 220, 114, 47, 228, 14, 205, 55, 47, 228, - 14, 217, 96, 47, 228, 14, 233, 41, 47, 228, 14, 200, 210, 47, 228, 14, - 233, 220, 47, 228, 14, 208, 211, 47, 228, 14, 250, 167, 47, 228, 14, 223, - 52, 47, 228, 14, 207, 30, 47, 228, 14, 239, 8, 47, 228, 14, 238, 251, 47, - 228, 14, 229, 135, 47, 228, 14, 247, 21, 47, 228, 14, 218, 241, 47, 228, - 14, 219, 224, 47, 228, 14, 183, 47, 228, 14, 216, 215, 47, 228, 14, 207, - 60, 47, 228, 14, 201, 10, 47, 228, 14, 200, 178, 47, 228, 14, 234, 75, - 47, 228, 14, 207, 32, 47, 228, 14, 251, 168, 47, 228, 14, 213, 190, 47, - 31, 198, 250, 169, 47, 31, 198, 250, 175, 47, 31, 198, 250, 171, 47, 31, - 198, 250, 178, 47, 31, 232, 135, 47, 31, 232, 136, 107, 47, 31, 232, 136, - 109, 47, 31, 232, 136, 138, 47, 31, 232, 136, 134, 47, 31, 232, 136, 149, - 47, 31, 232, 136, 169, 47, 31, 232, 136, 175, 47, 31, 232, 136, 171, 47, - 31, 232, 136, 178, 47, 31, 233, 15, 154, 199, 109, 16, 40, 223, 21, 154, - 199, 109, 16, 40, 233, 53, 154, 199, 109, 16, 40, 217, 58, 154, 199, 109, - 16, 40, 251, 39, 154, 199, 109, 16, 40, 217, 21, 154, 199, 109, 16, 40, - 222, 175, 154, 199, 109, 16, 40, 222, 176, 154, 199, 109, 16, 40, 250, - 159, 154, 199, 109, 16, 40, 204, 9, 154, 199, 109, 16, 40, 211, 157, 154, - 199, 109, 16, 40, 212, 255, 154, 199, 109, 16, 40, 237, 140, 51, 229, - 178, 51, 234, 30, 51, 233, 230, 219, 118, 219, 145, 56, 47, 72, 65, 47, - 72, 68, 47, 72, 66, 47, 72, 71, 47, 72, 74, 47, 72, 155, 47, 72, 221, - 166, 47, 72, 220, 232, 47, 72, 222, 22, 47, 72, 221, 67, 47, 72, 188, 47, - 72, 202, 222, 47, 72, 201, 4, 47, 72, 205, 68, 47, 72, 202, 46, 47, 72, - 190, 190, 47, 72, 198, 193, 47, 72, 197, 94, 47, 72, 199, 145, 47, 72, - 159, 47, 72, 180, 47, 72, 213, 219, 47, 72, 212, 178, 47, 72, 214, 121, - 47, 72, 213, 43, 47, 72, 140, 47, 72, 229, 158, 47, 72, 228, 159, 47, 72, - 229, 245, 47, 72, 229, 23, 47, 72, 174, 47, 72, 216, 100, 47, 72, 215, - 155, 47, 72, 216, 232, 47, 72, 216, 12, 47, 72, 170, 47, 72, 191, 225, - 47, 72, 192, 12, 47, 72, 165, 47, 72, 207, 1, 47, 72, 206, 68, 47, 72, - 207, 113, 47, 72, 206, 162, 47, 72, 193, 190, 47, 72, 193, 86, 47, 72, - 193, 125, 47, 72, 193, 48, 51, 234, 33, 214, 228, 207, 68, 51, 251, 64, - 51, 250, 221, 51, 251, 92, 51, 252, 163, 51, 223, 130, 51, 223, 97, 51, - 196, 80, 51, 234, 2, 51, 234, 185, 51, 211, 90, 51, 211, 83, 51, 222, - 100, 51, 222, 63, 51, 222, 58, 51, 231, 195, 51, 231, 205, 51, 231, 41, - 51, 231, 35, 51, 220, 144, 51, 231, 26, 51, 221, 131, 51, 221, 130, 51, - 221, 129, 51, 221, 128, 51, 230, 146, 51, 230, 145, 51, 220, 193, 51, - 220, 196, 51, 222, 9, 51, 221, 29, 51, 221, 38, 51, 205, 180, 51, 205, - 133, 51, 202, 141, 51, 204, 15, 51, 204, 14, 51, 238, 28, 51, 237, 81, - 51, 236, 141, 51, 198, 81, 51, 214, 221, 51, 213, 0, 51, 230, 75, 51, - 210, 214, 51, 210, 213, 51, 249, 150, 51, 209, 181, 51, 209, 143, 51, - 209, 144, 51, 248, 156, 51, 228, 154, 51, 228, 148, 51, 247, 221, 51, - 228, 132, 51, 229, 206, 51, 209, 241, 51, 210, 29, 51, 229, 187, 51, 210, - 25, 51, 210, 43, 51, 248, 252, 51, 209, 57, 51, 248, 84, 51, 228, 255, - 51, 209, 38, 51, 228, 246, 51, 228, 248, 51, 217, 110, 51, 217, 106, 51, - 217, 115, 51, 217, 44, 51, 217, 76, 51, 216, 56, 51, 216, 29, 51, 216, - 28, 51, 216, 203, 51, 216, 200, 51, 216, 204, 51, 192, 139, 51, 192, 137, - 51, 191, 210, 51, 206, 178, 51, 206, 182, 51, 206, 35, 51, 206, 28, 51, - 207, 57, 51, 207, 54, 51, 193, 141, 154, 199, 109, 16, 40, 228, 177, 191, - 77, 154, 199, 109, 16, 40, 228, 177, 107, 154, 199, 109, 16, 40, 228, - 177, 109, 154, 199, 109, 16, 40, 228, 177, 138, 154, 199, 109, 16, 40, - 228, 177, 134, 154, 199, 109, 16, 40, 228, 177, 149, 154, 199, 109, 16, - 40, 228, 177, 169, 154, 199, 109, 16, 40, 228, 177, 175, 154, 199, 109, - 16, 40, 228, 177, 171, 154, 199, 109, 16, 40, 228, 177, 178, 154, 199, - 109, 16, 40, 228, 177, 199, 95, 154, 199, 109, 16, 40, 228, 177, 234, - 127, 154, 199, 109, 16, 40, 228, 177, 197, 37, 154, 199, 109, 16, 40, - 228, 177, 198, 251, 154, 199, 109, 16, 40, 228, 177, 232, 122, 154, 199, - 109, 16, 40, 228, 177, 233, 19, 154, 199, 109, 16, 40, 228, 177, 202, - 130, 154, 199, 109, 16, 40, 228, 177, 203, 244, 154, 199, 109, 16, 40, - 228, 177, 234, 161, 154, 199, 109, 16, 40, 228, 177, 213, 171, 154, 199, - 109, 16, 40, 228, 177, 197, 32, 154, 199, 109, 16, 40, 228, 177, 197, 25, - 154, 199, 109, 16, 40, 228, 177, 197, 20, 154, 199, 109, 16, 40, 228, - 177, 197, 22, 154, 199, 109, 16, 40, 228, 177, 197, 27, 51, 228, 168, 51, - 238, 32, 51, 250, 163, 51, 164, 51, 211, 9, 51, 210, 68, 51, 236, 177, - 51, 236, 178, 201, 189, 51, 236, 178, 238, 189, 51, 223, 49, 51, 234, 33, - 214, 228, 229, 207, 51, 234, 33, 214, 228, 200, 66, 51, 234, 33, 214, - 228, 199, 212, 51, 234, 33, 214, 228, 216, 199, 51, 238, 253, 51, 210, - 221, 251, 135, 51, 180, 51, 215, 156, 65, 51, 174, 51, 155, 51, 222, 25, - 51, 217, 16, 51, 231, 183, 51, 247, 144, 51, 222, 24, 51, 209, 231, 51, - 214, 72, 51, 215, 156, 233, 175, 51, 215, 156, 232, 51, 51, 216, 141, 51, - 221, 217, 51, 228, 83, 51, 221, 168, 51, 216, 102, 51, 231, 55, 51, 198, - 195, 51, 215, 156, 172, 51, 216, 20, 51, 236, 187, 51, 221, 95, 51, 232, - 177, 51, 213, 81, 51, 215, 156, 218, 168, 51, 216, 17, 51, 242, 199, 51, - 221, 81, 51, 216, 18, 201, 189, 51, 242, 200, 201, 189, 51, 218, 169, - 201, 189, 51, 221, 82, 201, 189, 51, 216, 18, 238, 189, 51, 242, 200, - 238, 189, 51, 218, 169, 238, 189, 51, 221, 82, 238, 189, 51, 218, 169, - 139, 206, 8, 51, 218, 169, 139, 206, 9, 201, 189, 51, 168, 51, 221, 21, - 51, 215, 166, 51, 230, 229, 51, 207, 168, 51, 207, 169, 139, 206, 8, 51, - 207, 169, 139, 206, 9, 201, 189, 51, 208, 178, 51, 212, 219, 51, 215, - 156, 206, 8, 51, 215, 158, 51, 208, 124, 51, 212, 112, 51, 215, 156, 196, - 12, 51, 215, 87, 51, 220, 182, 51, 215, 88, 216, 203, 51, 208, 123, 51, - 212, 111, 51, 215, 156, 193, 224, 51, 215, 81, 51, 220, 180, 51, 215, 82, - 216, 203, 51, 222, 153, 211, 134, 51, 218, 169, 211, 134, 51, 251, 149, - 51, 248, 57, 51, 247, 66, 51, 247, 43, 51, 247, 194, 139, 221, 217, 51, - 242, 99, 51, 237, 200, 51, 230, 129, 51, 140, 51, 228, 169, 51, 223, 162, - 51, 221, 102, 51, 221, 82, 247, 110, 51, 220, 234, 51, 219, 46, 51, 219, - 45, 51, 219, 30, 51, 218, 184, 51, 217, 17, 202, 70, 51, 216, 55, 51, - 215, 233, 51, 209, 229, 51, 209, 76, 51, 208, 249, 51, 208, 247, 51, 201, - 180, 51, 200, 158, 51, 193, 127, 51, 196, 13, 139, 218, 168, 51, 42, 139, - 218, 168, 154, 199, 109, 16, 40, 237, 204, 107, 154, 199, 109, 16, 40, - 237, 204, 109, 154, 199, 109, 16, 40, 237, 204, 138, 154, 199, 109, 16, - 40, 237, 204, 134, 154, 199, 109, 16, 40, 237, 204, 149, 154, 199, 109, - 16, 40, 237, 204, 169, 154, 199, 109, 16, 40, 237, 204, 175, 154, 199, - 109, 16, 40, 237, 204, 171, 154, 199, 109, 16, 40, 237, 204, 178, 154, - 199, 109, 16, 40, 237, 204, 199, 95, 154, 199, 109, 16, 40, 237, 204, - 234, 127, 154, 199, 109, 16, 40, 237, 204, 197, 37, 154, 199, 109, 16, - 40, 237, 204, 198, 251, 154, 199, 109, 16, 40, 237, 204, 232, 122, 154, - 199, 109, 16, 40, 237, 204, 233, 19, 154, 199, 109, 16, 40, 237, 204, - 202, 130, 154, 199, 109, 16, 40, 237, 204, 203, 244, 154, 199, 109, 16, - 40, 237, 204, 234, 161, 154, 199, 109, 16, 40, 237, 204, 213, 171, 154, - 199, 109, 16, 40, 237, 204, 197, 32, 154, 199, 109, 16, 40, 237, 204, - 197, 25, 154, 199, 109, 16, 40, 237, 204, 197, 20, 154, 199, 109, 16, 40, - 237, 204, 197, 22, 154, 199, 109, 16, 40, 237, 204, 197, 27, 154, 199, - 109, 16, 40, 237, 204, 197, 28, 154, 199, 109, 16, 40, 237, 204, 197, 23, - 154, 199, 109, 16, 40, 237, 204, 197, 24, 154, 199, 109, 16, 40, 237, - 204, 197, 31, 154, 199, 109, 16, 40, 237, 204, 197, 26, 154, 199, 109, - 16, 40, 237, 204, 198, 249, 154, 199, 109, 16, 40, 237, 204, 198, 247, - 51, 231, 222, 229, 181, 40, 199, 34, 238, 231, 229, 219, 229, 181, 40, - 199, 34, 207, 100, 234, 207, 229, 181, 40, 237, 14, 250, 183, 199, 34, - 248, 247, 229, 181, 40, 191, 238, 232, 168, 229, 181, 40, 193, 171, 229, - 181, 40, 239, 53, 229, 181, 40, 199, 34, 250, 246, 229, 181, 40, 229, 6, - 198, 87, 229, 181, 40, 2, 199, 194, 229, 181, 40, 198, 1, 229, 181, 40, - 210, 60, 229, 181, 40, 201, 104, 229, 181, 40, 233, 43, 229, 181, 40, - 230, 206, 209, 21, 229, 181, 40, 215, 254, 229, 181, 40, 234, 74, 229, - 181, 40, 232, 169, 229, 181, 40, 193, 21, 211, 105, 199, 34, 237, 141, - 229, 181, 40, 251, 43, 229, 181, 40, 239, 31, 229, 181, 40, 248, 145, - 198, 215, 229, 181, 40, 230, 227, 229, 181, 40, 201, 208, 251, 63, 229, - 181, 40, 207, 22, 229, 181, 40, 223, 124, 229, 181, 40, 230, 206, 199, - 194, 229, 181, 40, 215, 180, 239, 0, 229, 181, 40, 230, 206, 208, 224, - 229, 181, 40, 199, 34, 252, 65, 193, 143, 229, 181, 40, 199, 34, 242, - 227, 232, 243, 229, 181, 40, 223, 138, 229, 181, 40, 235, 64, 229, 181, - 40, 207, 25, 229, 181, 40, 230, 206, 208, 254, 229, 181, 40, 208, 197, - 229, 181, 40, 237, 220, 79, 199, 34, 219, 132, 229, 181, 40, 199, 34, - 233, 81, 229, 181, 40, 211, 62, 229, 181, 40, 211, 167, 229, 181, 40, - 237, 111, 229, 181, 40, 237, 133, 229, 181, 40, 223, 153, 229, 181, 40, - 248, 41, 229, 181, 40, 242, 76, 119, 216, 206, 229, 181, 40, 231, 190, - 198, 87, 229, 181, 40, 208, 135, 196, 67, 229, 181, 40, 211, 61, 229, - 181, 40, 199, 34, 193, 109, 229, 181, 40, 207, 13, 229, 181, 40, 199, 34, - 247, 72, 229, 181, 40, 199, 34, 250, 242, 198, 209, 229, 181, 40, 199, - 34, 222, 10, 201, 70, 215, 184, 229, 181, 40, 237, 76, 229, 181, 40, 199, - 34, 217, 47, 217, 111, 229, 181, 40, 252, 66, 229, 181, 40, 199, 34, 193, - 161, 229, 181, 40, 199, 34, 231, 145, 193, 66, 229, 181, 40, 199, 34, - 222, 184, 220, 43, 229, 181, 40, 236, 219, 229, 181, 40, 219, 119, 229, - 181, 40, 223, 127, 197, 176, 229, 181, 40, 2, 208, 224, 229, 181, 40, - 251, 254, 242, 66, 229, 181, 40, 248, 250, 242, 66, 11, 5, 223, 53, 11, - 5, 223, 45, 11, 5, 68, 11, 5, 223, 80, 11, 5, 223, 224, 11, 5, 223, 207, - 11, 5, 223, 226, 11, 5, 223, 225, 11, 5, 250, 182, 11, 5, 250, 133, 11, - 5, 65, 11, 5, 251, 65, 11, 5, 196, 78, 11, 5, 196, 82, 11, 5, 196, 79, - 11, 5, 211, 30, 11, 5, 210, 247, 11, 5, 74, 11, 5, 211, 78, 11, 5, 233, - 221, 11, 5, 71, 11, 5, 193, 0, 11, 5, 248, 148, 11, 5, 248, 143, 11, 5, - 248, 188, 11, 5, 248, 161, 11, 5, 248, 177, 11, 5, 248, 176, 11, 5, 248, - 179, 11, 5, 248, 178, 11, 5, 249, 64, 11, 5, 249, 56, 11, 5, 249, 153, - 11, 5, 249, 89, 11, 5, 247, 234, 11, 5, 247, 238, 11, 5, 247, 235, 11, 5, - 248, 81, 11, 5, 248, 62, 11, 5, 248, 111, 11, 5, 248, 89, 11, 5, 248, - 206, 11, 5, 249, 17, 11, 5, 248, 219, 11, 5, 247, 217, 11, 5, 247, 211, - 11, 5, 248, 10, 11, 5, 247, 232, 11, 5, 247, 225, 11, 5, 247, 230, 11, 5, - 247, 199, 11, 5, 247, 197, 11, 5, 247, 204, 11, 5, 247, 202, 11, 5, 247, - 200, 11, 5, 247, 201, 11, 5, 209, 117, 11, 5, 209, 113, 11, 5, 209, 185, - 11, 5, 209, 129, 11, 5, 209, 149, 11, 5, 209, 176, 11, 5, 209, 172, 11, - 5, 210, 89, 11, 5, 210, 73, 11, 5, 168, 11, 5, 210, 137, 11, 5, 208, 145, - 11, 5, 208, 147, 11, 5, 208, 146, 11, 5, 209, 14, 11, 5, 208, 252, 11, 5, - 209, 73, 11, 5, 209, 33, 11, 5, 208, 131, 11, 5, 208, 126, 11, 5, 208, - 165, 11, 5, 208, 144, 11, 5, 208, 136, 11, 5, 208, 142, 11, 5, 208, 108, - 11, 5, 208, 107, 11, 5, 208, 112, 11, 5, 208, 111, 11, 5, 208, 109, 11, - 5, 208, 110, 11, 5, 249, 38, 11, 5, 249, 37, 11, 5, 249, 44, 11, 5, 249, - 39, 11, 5, 249, 41, 11, 5, 249, 40, 11, 5, 249, 43, 11, 5, 249, 42, 11, - 5, 249, 50, 11, 5, 249, 49, 11, 5, 249, 53, 11, 5, 249, 51, 11, 5, 249, - 29, 11, 5, 249, 31, 11, 5, 249, 30, 11, 5, 249, 34, 11, 5, 249, 33, 11, - 5, 249, 36, 11, 5, 249, 35, 11, 5, 249, 45, 11, 5, 249, 48, 11, 5, 249, - 46, 11, 5, 249, 25, 11, 5, 249, 24, 11, 5, 249, 32, 11, 5, 249, 28, 11, - 5, 249, 26, 11, 5, 249, 27, 11, 5, 249, 21, 11, 5, 249, 20, 11, 5, 249, - 23, 11, 5, 249, 22, 11, 5, 214, 185, 11, 5, 214, 184, 11, 5, 214, 190, - 11, 5, 214, 186, 11, 5, 214, 187, 11, 5, 214, 189, 11, 5, 214, 188, 11, - 5, 214, 193, 11, 5, 214, 192, 11, 5, 214, 195, 11, 5, 214, 194, 11, 5, - 214, 181, 11, 5, 214, 180, 11, 5, 214, 183, 11, 5, 214, 182, 11, 5, 214, - 174, 11, 5, 214, 173, 11, 5, 214, 178, 11, 5, 214, 177, 11, 5, 214, 175, - 11, 5, 214, 176, 11, 5, 214, 168, 11, 5, 214, 167, 11, 5, 214, 172, 11, - 5, 214, 171, 11, 5, 214, 169, 11, 5, 214, 170, 11, 5, 229, 67, 11, 5, - 229, 66, 11, 5, 229, 72, 11, 5, 229, 68, 11, 5, 229, 69, 11, 5, 229, 71, - 11, 5, 229, 70, 11, 5, 229, 75, 11, 5, 229, 74, 11, 5, 229, 77, 11, 5, - 229, 76, 11, 5, 229, 58, 11, 5, 229, 60, 11, 5, 229, 59, 11, 5, 229, 63, - 11, 5, 229, 62, 11, 5, 229, 65, 11, 5, 229, 64, 11, 5, 229, 54, 11, 5, - 229, 53, 11, 5, 229, 61, 11, 5, 229, 57, 11, 5, 229, 55, 11, 5, 229, 56, - 11, 5, 229, 48, 11, 5, 229, 52, 11, 5, 229, 51, 11, 5, 229, 49, 11, 5, - 229, 50, 11, 5, 216, 23, 11, 5, 216, 22, 11, 5, 216, 100, 11, 5, 216, 31, - 11, 5, 216, 63, 11, 5, 216, 81, 11, 5, 216, 79, 11, 5, 217, 30, 11, 5, - 217, 24, 11, 5, 174, 11, 5, 217, 71, 11, 5, 215, 115, 11, 5, 215, 114, - 11, 5, 215, 118, 11, 5, 215, 116, 11, 5, 215, 195, 11, 5, 215, 168, 11, - 5, 216, 12, 11, 5, 215, 202, 11, 5, 216, 152, 11, 5, 216, 232, 11, 5, - 215, 95, 11, 5, 215, 89, 11, 5, 215, 155, 11, 5, 215, 111, 11, 5, 215, - 104, 11, 5, 215, 109, 11, 5, 215, 65, 11, 5, 215, 64, 11, 5, 215, 70, 11, - 5, 215, 67, 11, 5, 232, 229, 11, 5, 232, 222, 11, 5, 233, 23, 11, 5, 232, - 245, 11, 5, 233, 72, 11, 5, 233, 63, 11, 5, 233, 109, 11, 5, 233, 77, 11, - 5, 232, 119, 11, 5, 232, 175, 11, 5, 232, 154, 11, 5, 232, 68, 11, 5, - 232, 67, 11, 5, 232, 86, 11, 5, 232, 73, 11, 5, 232, 71, 11, 5, 232, 72, - 11, 5, 232, 54, 11, 5, 232, 53, 11, 5, 232, 57, 11, 5, 232, 55, 11, 5, - 195, 32, 11, 5, 195, 26, 11, 5, 195, 69, 11, 5, 195, 41, 11, 5, 195, 58, - 11, 5, 195, 53, 11, 5, 195, 61, 11, 5, 195, 60, 11, 5, 195, 162, 11, 5, - 195, 157, 11, 5, 195, 188, 11, 5, 195, 175, 11, 5, 195, 4, 11, 5, 195, 0, - 11, 5, 195, 24, 11, 5, 195, 6, 11, 5, 195, 73, 11, 5, 195, 141, 11, 5, - 193, 242, 11, 5, 193, 240, 11, 5, 193, 249, 11, 5, 193, 245, 11, 5, 193, - 243, 11, 5, 193, 244, 11, 5, 193, 229, 11, 5, 193, 228, 11, 5, 193, 235, - 11, 5, 193, 234, 11, 5, 193, 232, 11, 5, 193, 233, 11, 5, 236, 212, 11, - 5, 236, 197, 11, 5, 237, 44, 11, 5, 236, 240, 11, 5, 237, 19, 11, 5, 237, - 24, 11, 5, 237, 23, 11, 5, 237, 211, 11, 5, 237, 205, 11, 5, 238, 32, 11, - 5, 237, 231, 11, 5, 235, 69, 11, 5, 235, 70, 11, 5, 236, 140, 11, 5, 235, - 117, 11, 5, 236, 174, 11, 5, 236, 143, 11, 5, 237, 74, 11, 5, 237, 146, - 11, 5, 237, 96, 11, 5, 235, 60, 11, 5, 235, 58, 11, 5, 235, 89, 11, 5, - 235, 68, 11, 5, 235, 63, 11, 5, 235, 66, 11, 5, 198, 125, 11, 5, 198, - 117, 11, 5, 198, 193, 11, 5, 198, 135, 11, 5, 198, 176, 11, 5, 198, 178, - 11, 5, 198, 177, 11, 5, 199, 171, 11, 5, 199, 156, 11, 5, 190, 190, 11, - 5, 199, 183, 11, 5, 197, 69, 11, 5, 197, 68, 11, 5, 197, 71, 11, 5, 197, - 70, 11, 5, 198, 40, 11, 5, 198, 29, 11, 5, 159, 11, 5, 198, 53, 11, 5, - 199, 55, 11, 5, 199, 145, 11, 5, 199, 82, 11, 5, 197, 52, 11, 5, 197, 47, - 11, 5, 197, 94, 11, 5, 197, 67, 11, 5, 197, 53, 11, 5, 197, 64, 11, 5, - 237, 163, 11, 5, 237, 162, 11, 5, 237, 168, 11, 5, 237, 164, 11, 5, 237, - 165, 11, 5, 237, 167, 11, 5, 237, 166, 11, 5, 237, 184, 11, 5, 237, 183, - 11, 5, 237, 191, 11, 5, 237, 185, 11, 5, 237, 153, 11, 5, 237, 155, 11, - 5, 237, 154, 11, 5, 237, 158, 11, 5, 237, 157, 11, 5, 237, 161, 11, 5, - 237, 159, 11, 5, 237, 176, 11, 5, 237, 179, 11, 5, 237, 177, 11, 5, 237, - 149, 11, 5, 237, 148, 11, 5, 237, 156, 11, 5, 237, 152, 11, 5, 237, 150, - 11, 5, 237, 151, 11, 5, 214, 140, 11, 5, 214, 139, 11, 5, 214, 147, 11, - 5, 214, 142, 11, 5, 214, 143, 11, 5, 214, 144, 11, 5, 214, 156, 11, 5, - 214, 155, 11, 5, 214, 162, 11, 5, 214, 157, 11, 5, 214, 132, 11, 5, 214, - 131, 11, 5, 214, 138, 11, 5, 214, 133, 11, 5, 214, 148, 11, 5, 214, 154, - 11, 5, 214, 152, 11, 5, 214, 124, 11, 5, 214, 123, 11, 5, 214, 129, 11, - 5, 214, 127, 11, 5, 214, 125, 11, 5, 214, 126, 11, 5, 229, 33, 11, 5, - 229, 32, 11, 5, 229, 39, 11, 5, 229, 34, 11, 5, 229, 36, 11, 5, 229, 35, - 11, 5, 229, 38, 11, 5, 229, 37, 11, 5, 229, 45, 11, 5, 229, 43, 11, 5, - 229, 47, 11, 5, 229, 46, 11, 5, 229, 26, 11, 5, 229, 27, 11, 5, 229, 30, - 11, 5, 229, 29, 11, 5, 229, 31, 11, 5, 229, 40, 11, 5, 229, 42, 11, 5, - 229, 41, 11, 5, 229, 25, 11, 5, 213, 162, 11, 5, 213, 160, 11, 5, 213, - 219, 11, 5, 213, 165, 11, 5, 213, 193, 11, 5, 213, 207, 11, 5, 213, 206, - 11, 5, 214, 200, 11, 5, 180, 11, 5, 214, 218, 11, 5, 212, 122, 11, 5, - 212, 124, 11, 5, 212, 123, 11, 5, 213, 11, 11, 5, 212, 251, 11, 5, 213, - 43, 11, 5, 213, 22, 11, 5, 214, 74, 11, 5, 214, 121, 11, 5, 214, 97, 11, - 5, 212, 117, 11, 5, 212, 113, 11, 5, 212, 178, 11, 5, 212, 121, 11, 5, - 212, 119, 11, 5, 212, 120, 11, 5, 229, 98, 11, 5, 229, 97, 11, 5, 229, - 103, 11, 5, 229, 99, 11, 5, 229, 100, 11, 5, 229, 102, 11, 5, 229, 101, - 11, 5, 229, 109, 11, 5, 229, 107, 11, 5, 229, 111, 11, 5, 229, 110, 11, - 5, 229, 90, 11, 5, 229, 92, 11, 5, 229, 91, 11, 5, 229, 94, 11, 5, 229, - 96, 11, 5, 229, 95, 11, 5, 229, 104, 11, 5, 229, 106, 11, 5, 229, 105, - 11, 5, 229, 86, 11, 5, 229, 85, 11, 5, 229, 93, 11, 5, 229, 89, 11, 5, - 229, 87, 11, 5, 229, 88, 11, 5, 229, 80, 11, 5, 229, 79, 11, 5, 229, 84, - 11, 5, 229, 83, 11, 5, 229, 81, 11, 5, 229, 82, 11, 5, 219, 87, 11, 5, - 219, 79, 11, 5, 219, 146, 11, 5, 219, 98, 11, 5, 219, 137, 11, 5, 219, - 136, 11, 5, 219, 140, 11, 5, 219, 138, 11, 5, 220, 5, 11, 5, 219, 249, - 11, 5, 173, 11, 5, 220, 16, 11, 5, 218, 201, 11, 5, 218, 200, 11, 5, 218, - 203, 11, 5, 218, 202, 11, 5, 218, 249, 11, 5, 218, 234, 11, 5, 219, 43, - 11, 5, 219, 1, 11, 5, 219, 164, 11, 5, 219, 238, 11, 5, 219, 184, 11, 5, - 218, 195, 11, 5, 218, 193, 11, 5, 218, 225, 11, 5, 218, 199, 11, 5, 218, - 197, 11, 5, 218, 198, 11, 5, 218, 173, 11, 5, 218, 172, 11, 5, 218, 183, - 11, 5, 218, 176, 11, 5, 218, 174, 11, 5, 218, 175, 11, 5, 231, 22, 11, 5, - 231, 21, 11, 5, 231, 53, 11, 5, 231, 34, 11, 5, 231, 45, 11, 5, 231, 44, - 11, 5, 231, 47, 11, 5, 231, 46, 11, 5, 231, 192, 11, 5, 231, 187, 11, 5, - 231, 240, 11, 5, 231, 203, 11, 5, 230, 152, 11, 5, 230, 151, 11, 5, 230, - 154, 11, 5, 230, 153, 11, 5, 230, 232, 11, 5, 230, 230, 11, 5, 231, 3, - 11, 5, 230, 242, 11, 5, 231, 131, 11, 5, 231, 129, 11, 5, 231, 165, 11, - 5, 231, 142, 11, 5, 230, 140, 11, 5, 230, 139, 11, 5, 230, 179, 11, 5, - 230, 150, 11, 5, 230, 141, 11, 5, 230, 149, 11, 5, 221, 120, 11, 5, 221, - 115, 11, 5, 221, 166, 11, 5, 221, 134, 11, 5, 221, 147, 11, 5, 221, 151, - 11, 5, 221, 149, 11, 5, 222, 49, 11, 5, 222, 30, 11, 5, 155, 11, 5, 222, - 78, 11, 5, 220, 202, 11, 5, 220, 207, 11, 5, 220, 204, 11, 5, 221, 28, - 11, 5, 221, 23, 11, 5, 221, 67, 11, 5, 221, 36, 11, 5, 221, 241, 11, 5, - 221, 224, 11, 5, 222, 22, 11, 5, 221, 245, 11, 5, 220, 188, 11, 5, 220, - 184, 11, 5, 220, 232, 11, 5, 220, 201, 11, 5, 220, 192, 11, 5, 220, 197, - 11, 5, 231, 113, 11, 5, 231, 112, 11, 5, 231, 117, 11, 5, 231, 114, 11, - 5, 231, 116, 11, 5, 231, 115, 11, 5, 231, 124, 11, 5, 231, 123, 11, 5, - 231, 127, 11, 5, 231, 125, 11, 5, 231, 104, 11, 5, 231, 103, 11, 5, 231, - 106, 11, 5, 231, 105, 11, 5, 231, 109, 11, 5, 231, 108, 11, 5, 231, 111, - 11, 5, 231, 110, 11, 5, 231, 119, 11, 5, 231, 118, 11, 5, 231, 122, 11, - 5, 231, 120, 11, 5, 231, 99, 11, 5, 231, 98, 11, 5, 231, 107, 11, 5, 231, - 102, 11, 5, 231, 100, 11, 5, 231, 101, 11, 5, 216, 119, 11, 5, 216, 120, - 11, 5, 216, 138, 11, 5, 216, 137, 11, 5, 216, 140, 11, 5, 216, 139, 11, - 5, 216, 110, 11, 5, 216, 112, 11, 5, 216, 111, 11, 5, 216, 115, 11, 5, - 216, 114, 11, 5, 216, 117, 11, 5, 216, 116, 11, 5, 216, 121, 11, 5, 216, - 123, 11, 5, 216, 122, 11, 5, 216, 106, 11, 5, 216, 105, 11, 5, 216, 113, - 11, 5, 216, 109, 11, 5, 216, 107, 11, 5, 216, 108, 11, 5, 228, 104, 11, - 5, 228, 103, 11, 5, 228, 110, 11, 5, 228, 105, 11, 5, 228, 107, 11, 5, - 228, 106, 11, 5, 228, 109, 11, 5, 228, 108, 11, 5, 228, 115, 11, 5, 228, - 114, 11, 5, 228, 117, 11, 5, 228, 116, 11, 5, 228, 96, 11, 5, 228, 95, - 11, 5, 228, 98, 11, 5, 228, 97, 11, 5, 228, 100, 11, 5, 228, 99, 11, 5, - 228, 102, 11, 5, 228, 101, 11, 5, 228, 111, 11, 5, 228, 113, 11, 5, 228, - 112, 11, 5, 214, 13, 11, 5, 214, 15, 11, 5, 214, 14, 11, 5, 214, 58, 11, - 5, 214, 56, 11, 5, 214, 68, 11, 5, 214, 61, 11, 5, 213, 230, 11, 5, 213, - 229, 11, 5, 213, 231, 11, 5, 213, 241, 11, 5, 213, 238, 11, 5, 213, 249, - 11, 5, 213, 243, 11, 5, 214, 49, 11, 5, 214, 55, 11, 5, 214, 51, 11, 5, - 229, 117, 11, 5, 229, 136, 11, 5, 229, 145, 11, 5, 230, 9, 11, 5, 229, - 253, 11, 5, 140, 11, 5, 230, 21, 11, 5, 228, 134, 11, 5, 228, 133, 11, 5, - 228, 136, 11, 5, 228, 135, 11, 5, 228, 180, 11, 5, 228, 171, 11, 5, 229, - 23, 11, 5, 228, 244, 11, 5, 229, 183, 11, 5, 229, 245, 11, 5, 229, 195, - 11, 5, 193, 146, 11, 5, 193, 131, 11, 5, 193, 190, 11, 5, 193, 158, 11, - 5, 192, 245, 11, 5, 192, 247, 11, 5, 192, 246, 11, 5, 193, 13, 11, 5, - 193, 48, 11, 5, 193, 24, 11, 5, 193, 99, 11, 5, 193, 125, 11, 5, 193, - 106, 11, 5, 191, 15, 11, 5, 191, 14, 11, 5, 191, 30, 11, 5, 191, 18, 11, - 5, 191, 23, 11, 5, 191, 25, 11, 5, 191, 24, 11, 5, 191, 96, 11, 5, 191, - 93, 11, 5, 191, 123, 11, 5, 191, 104, 11, 5, 190, 244, 11, 5, 190, 246, - 11, 5, 190, 245, 11, 5, 191, 2, 11, 5, 191, 1, 11, 5, 191, 7, 11, 5, 191, - 3, 11, 5, 191, 73, 11, 5, 191, 87, 11, 5, 191, 79, 11, 5, 190, 240, 11, - 5, 190, 239, 11, 5, 190, 251, 11, 5, 190, 243, 11, 5, 190, 241, 11, 5, - 190, 242, 11, 5, 190, 226, 11, 5, 190, 225, 11, 5, 190, 231, 11, 5, 190, - 229, 11, 5, 190, 227, 11, 5, 190, 228, 11, 5, 242, 255, 11, 5, 242, 248, - 11, 5, 243, 29, 11, 5, 243, 12, 11, 5, 243, 26, 11, 5, 243, 20, 11, 5, - 243, 28, 11, 5, 243, 27, 11, 5, 247, 78, 11, 5, 247, 69, 11, 5, 247, 160, - 11, 5, 247, 111, 11, 5, 238, 183, 11, 5, 238, 185, 11, 5, 238, 184, 11, - 5, 238, 249, 11, 5, 238, 237, 11, 5, 242, 99, 11, 5, 239, 13, 11, 5, 247, - 5, 11, 5, 247, 42, 11, 5, 247, 11, 11, 5, 238, 154, 11, 5, 238, 152, 11, - 5, 238, 195, 11, 5, 238, 181, 11, 5, 238, 160, 11, 5, 238, 176, 11, 5, - 238, 130, 11, 5, 238, 129, 11, 5, 238, 143, 11, 5, 238, 137, 11, 5, 238, - 131, 11, 5, 238, 133, 11, 5, 190, 209, 11, 5, 190, 208, 11, 5, 190, 215, - 11, 5, 190, 210, 11, 5, 190, 212, 11, 5, 190, 211, 11, 5, 190, 214, 11, - 5, 190, 213, 11, 5, 190, 221, 11, 5, 190, 220, 11, 5, 190, 224, 11, 5, - 190, 222, 11, 5, 190, 205, 11, 5, 190, 207, 11, 5, 190, 206, 11, 5, 190, - 216, 11, 5, 190, 219, 11, 5, 190, 217, 11, 5, 190, 198, 11, 5, 190, 202, - 11, 5, 190, 201, 11, 5, 190, 199, 11, 5, 190, 200, 11, 5, 190, 192, 11, - 5, 190, 191, 11, 5, 190, 197, 11, 5, 190, 195, 11, 5, 190, 193, 11, 5, - 190, 194, 11, 5, 212, 33, 11, 5, 212, 32, 11, 5, 212, 38, 11, 5, 212, 34, - 11, 5, 212, 35, 11, 5, 212, 37, 11, 5, 212, 36, 11, 5, 212, 43, 11, 5, - 212, 42, 11, 5, 212, 46, 11, 5, 212, 45, 11, 5, 212, 26, 11, 5, 212, 27, - 11, 5, 212, 30, 11, 5, 212, 31, 11, 5, 212, 39, 11, 5, 212, 41, 11, 5, - 212, 21, 11, 5, 212, 29, 11, 5, 212, 25, 11, 5, 212, 22, 11, 5, 212, 23, - 11, 5, 212, 16, 11, 5, 212, 15, 11, 5, 212, 20, 11, 5, 212, 19, 11, 5, - 212, 17, 11, 5, 212, 18, 11, 5, 202, 138, 11, 5, 169, 11, 5, 202, 222, - 11, 5, 202, 142, 11, 5, 202, 202, 11, 5, 202, 205, 11, 5, 202, 203, 11, - 5, 205, 122, 11, 5, 205, 106, 11, 5, 188, 11, 5, 205, 130, 11, 5, 200, - 188, 11, 5, 200, 190, 11, 5, 200, 189, 11, 5, 202, 8, 11, 5, 201, 253, - 11, 5, 202, 46, 11, 5, 202, 14, 11, 5, 203, 238, 11, 5, 205, 68, 11, 5, - 204, 13, 11, 5, 200, 163, 11, 5, 200, 159, 11, 5, 201, 4, 11, 5, 200, - 187, 11, 5, 200, 167, 11, 5, 200, 175, 11, 5, 200, 57, 11, 5, 200, 56, - 11, 5, 200, 127, 11, 5, 200, 65, 11, 5, 200, 59, 11, 5, 200, 64, 11, 5, - 201, 136, 11, 5, 201, 135, 11, 5, 201, 142, 11, 5, 201, 137, 11, 5, 201, - 139, 11, 5, 201, 141, 11, 5, 201, 140, 11, 5, 201, 151, 11, 5, 201, 149, - 11, 5, 201, 175, 11, 5, 201, 152, 11, 5, 201, 131, 11, 5, 201, 130, 11, - 5, 201, 134, 11, 5, 201, 132, 11, 5, 201, 145, 11, 5, 201, 148, 11, 5, - 201, 146, 11, 5, 201, 127, 11, 5, 201, 125, 11, 5, 201, 129, 11, 5, 201, - 128, 11, 5, 201, 120, 11, 5, 201, 119, 11, 5, 201, 124, 11, 5, 201, 123, - 11, 5, 201, 121, 11, 5, 201, 122, 11, 5, 191, 66, 11, 5, 191, 65, 11, 5, - 191, 71, 11, 5, 191, 68, 11, 5, 191, 45, 11, 5, 191, 47, 11, 5, 191, 46, - 11, 5, 191, 50, 11, 5, 191, 49, 11, 5, 191, 54, 11, 5, 191, 51, 11, 5, - 191, 59, 11, 5, 191, 58, 11, 5, 191, 62, 11, 5, 191, 60, 11, 5, 191, 41, - 11, 5, 191, 40, 11, 5, 191, 48, 11, 5, 191, 44, 11, 5, 191, 42, 11, 5, - 191, 43, 11, 5, 191, 33, 11, 5, 191, 32, 11, 5, 191, 37, 11, 5, 191, 36, - 11, 5, 191, 34, 11, 5, 191, 35, 11, 5, 243, 133, 11, 5, 243, 129, 11, 5, - 247, 1, 11, 5, 246, 243, 11, 5, 243, 44, 11, 5, 243, 43, 11, 5, 243, 46, - 11, 5, 243, 45, 11, 5, 243, 59, 11, 5, 243, 58, 11, 5, 243, 68, 11, 5, - 243, 63, 11, 5, 243, 102, 11, 5, 243, 99, 11, 5, 243, 127, 11, 5, 243, - 110, 11, 5, 243, 38, 11, 5, 243, 48, 11, 5, 243, 42, 11, 5, 243, 39, 11, - 5, 243, 41, 11, 5, 243, 31, 11, 5, 243, 30, 11, 5, 243, 35, 11, 5, 243, - 34, 11, 5, 243, 32, 11, 5, 243, 33, 11, 5, 206, 105, 11, 5, 206, 109, 11, - 5, 206, 87, 11, 5, 206, 88, 11, 5, 206, 92, 11, 5, 206, 91, 11, 5, 206, - 95, 11, 5, 206, 93, 11, 5, 206, 99, 11, 5, 206, 98, 11, 5, 206, 104, 11, - 5, 206, 100, 11, 5, 206, 83, 11, 5, 206, 81, 11, 5, 206, 89, 11, 5, 206, - 86, 11, 5, 206, 84, 11, 5, 206, 85, 11, 5, 206, 76, 11, 5, 206, 75, 11, - 5, 206, 80, 11, 5, 206, 79, 11, 5, 206, 77, 11, 5, 206, 78, 11, 5, 212, - 242, 11, 5, 212, 241, 11, 5, 212, 244, 11, 5, 212, 243, 11, 5, 212, 233, - 11, 5, 212, 235, 11, 5, 212, 234, 11, 5, 212, 237, 11, 5, 212, 236, 11, - 5, 212, 240, 11, 5, 212, 239, 11, 5, 212, 227, 11, 5, 212, 226, 11, 5, - 212, 232, 11, 5, 212, 230, 11, 5, 212, 228, 11, 5, 212, 229, 11, 5, 212, - 221, 11, 5, 212, 220, 11, 5, 212, 225, 11, 5, 212, 224, 11, 5, 212, 222, - 11, 5, 212, 223, 11, 5, 203, 123, 11, 5, 203, 118, 11, 5, 203, 165, 11, - 5, 203, 136, 11, 5, 202, 249, 11, 5, 202, 251, 11, 5, 202, 250, 11, 5, - 203, 24, 11, 5, 203, 19, 11, 5, 203, 56, 11, 5, 203, 44, 11, 5, 203, 91, - 11, 5, 203, 84, 11, 5, 203, 113, 11, 5, 203, 100, 11, 5, 202, 245, 11, 5, - 202, 242, 11, 5, 203, 5, 11, 5, 202, 248, 11, 5, 202, 246, 11, 5, 202, - 247, 11, 5, 202, 225, 11, 5, 202, 224, 11, 5, 202, 231, 11, 5, 202, 228, - 11, 5, 202, 226, 11, 5, 202, 227, 11, 5, 207, 130, 11, 5, 207, 123, 11, - 5, 165, 11, 5, 207, 136, 11, 5, 206, 38, 11, 5, 206, 40, 11, 5, 206, 39, - 11, 5, 206, 123, 11, 5, 206, 111, 11, 5, 206, 162, 11, 5, 206, 127, 11, - 5, 207, 11, 11, 5, 207, 113, 11, 5, 207, 53, 11, 5, 206, 30, 11, 5, 206, - 27, 11, 5, 206, 68, 11, 5, 206, 37, 11, 5, 206, 33, 11, 5, 206, 34, 11, - 5, 206, 12, 11, 5, 206, 11, 11, 5, 206, 17, 11, 5, 206, 15, 11, 5, 206, - 13, 11, 5, 206, 14, 11, 5, 222, 232, 11, 5, 222, 231, 11, 5, 222, 244, - 11, 5, 222, 233, 11, 5, 222, 240, 11, 5, 222, 239, 11, 5, 222, 242, 11, - 5, 222, 241, 11, 5, 222, 170, 11, 5, 222, 169, 11, 5, 222, 172, 11, 5, - 222, 171, 11, 5, 222, 188, 11, 5, 222, 186, 11, 5, 222, 201, 11, 5, 222, - 190, 11, 5, 222, 163, 11, 5, 222, 161, 11, 5, 222, 182, 11, 5, 222, 168, - 11, 5, 222, 165, 11, 5, 222, 166, 11, 5, 222, 155, 11, 5, 222, 154, 11, - 5, 222, 159, 11, 5, 222, 158, 11, 5, 222, 156, 11, 5, 222, 157, 11, 5, - 208, 49, 11, 5, 208, 47, 11, 5, 208, 57, 11, 5, 208, 50, 11, 5, 208, 54, - 11, 5, 208, 53, 11, 5, 208, 56, 11, 5, 208, 55, 11, 5, 207, 253, 11, 5, - 207, 250, 11, 5, 207, 255, 11, 5, 207, 254, 11, 5, 208, 36, 11, 5, 208, - 35, 11, 5, 208, 45, 11, 5, 208, 39, 11, 5, 207, 245, 11, 5, 207, 241, 11, - 5, 208, 33, 11, 5, 207, 249, 11, 5, 207, 247, 11, 5, 207, 248, 11, 5, - 207, 225, 11, 5, 207, 223, 11, 5, 207, 235, 11, 5, 207, 228, 11, 5, 207, - 226, 11, 5, 207, 227, 11, 5, 222, 221, 11, 5, 222, 220, 11, 5, 222, 227, - 11, 5, 222, 222, 11, 5, 222, 224, 11, 5, 222, 223, 11, 5, 222, 226, 11, - 5, 222, 225, 11, 5, 222, 212, 11, 5, 222, 214, 11, 5, 222, 213, 11, 5, - 222, 217, 11, 5, 222, 216, 11, 5, 222, 219, 11, 5, 222, 218, 11, 5, 222, - 208, 11, 5, 222, 207, 11, 5, 222, 215, 11, 5, 222, 211, 11, 5, 222, 209, - 11, 5, 222, 210, 11, 5, 222, 204, 11, 5, 222, 203, 11, 5, 222, 206, 11, - 5, 222, 205, 11, 5, 213, 134, 11, 5, 213, 133, 11, 5, 213, 141, 11, 5, - 213, 135, 11, 5, 213, 137, 11, 5, 213, 136, 11, 5, 213, 140, 11, 5, 213, - 138, 11, 5, 213, 123, 11, 5, 213, 124, 11, 5, 213, 129, 11, 5, 213, 128, - 11, 5, 213, 132, 11, 5, 213, 130, 11, 5, 213, 118, 11, 5, 213, 127, 11, - 5, 213, 122, 11, 5, 213, 119, 11, 5, 213, 120, 11, 5, 213, 113, 11, 5, - 213, 112, 11, 5, 213, 117, 11, 5, 213, 116, 11, 5, 213, 114, 11, 5, 213, - 115, 11, 5, 212, 68, 11, 5, 212, 67, 11, 5, 212, 81, 11, 5, 212, 72, 11, - 5, 212, 77, 11, 5, 212, 76, 11, 5, 212, 79, 11, 5, 212, 78, 11, 5, 212, - 53, 11, 5, 212, 55, 11, 5, 212, 54, 11, 5, 212, 60, 11, 5, 212, 59, 11, - 5, 212, 65, 11, 5, 212, 61, 11, 5, 212, 51, 11, 5, 212, 49, 11, 5, 212, - 58, 11, 5, 212, 52, 11, 5, 192, 198, 11, 5, 192, 197, 11, 5, 192, 207, - 11, 5, 192, 200, 11, 5, 192, 202, 11, 5, 192, 201, 11, 5, 192, 204, 11, - 5, 192, 203, 11, 5, 192, 186, 11, 5, 192, 187, 11, 5, 192, 191, 11, 5, - 192, 190, 11, 5, 192, 196, 11, 5, 192, 194, 11, 5, 192, 163, 11, 5, 192, - 161, 11, 5, 192, 176, 11, 5, 192, 166, 11, 5, 192, 164, 11, 5, 192, 165, - 11, 5, 192, 18, 11, 5, 192, 16, 11, 5, 192, 33, 11, 5, 192, 19, 11, 5, - 192, 27, 11, 5, 192, 26, 11, 5, 192, 30, 11, 5, 192, 28, 11, 5, 191, 198, - 11, 5, 191, 197, 11, 5, 191, 201, 11, 5, 191, 199, 11, 5, 191, 240, 11, - 5, 191, 235, 11, 5, 192, 12, 11, 5, 191, 245, 11, 5, 191, 189, 11, 5, - 191, 185, 11, 5, 191, 225, 11, 5, 191, 196, 11, 5, 191, 192, 11, 5, 191, - 193, 11, 5, 191, 169, 11, 5, 191, 168, 11, 5, 191, 176, 11, 5, 191, 172, - 11, 5, 191, 170, 11, 5, 191, 171, 11, 48, 208, 36, 11, 48, 219, 146, 11, - 48, 221, 120, 11, 48, 212, 72, 11, 48, 238, 137, 11, 48, 201, 142, 11, - 48, 231, 110, 11, 48, 231, 142, 11, 48, 216, 100, 11, 48, 228, 104, 11, - 48, 218, 175, 11, 48, 249, 25, 11, 48, 215, 202, 11, 48, 192, 12, 11, 48, - 208, 131, 11, 48, 228, 98, 11, 48, 199, 171, 11, 48, 231, 240, 11, 48, - 190, 243, 11, 48, 238, 130, 11, 48, 237, 151, 11, 48, 247, 230, 11, 48, - 231, 106, 11, 48, 212, 61, 11, 48, 197, 94, 11, 48, 211, 78, 11, 48, 222, - 208, 11, 48, 191, 2, 11, 48, 208, 108, 11, 48, 229, 65, 11, 48, 192, 18, - 11, 48, 193, 244, 11, 48, 202, 231, 11, 48, 195, 141, 11, 48, 191, 123, - 11, 48, 222, 201, 11, 48, 212, 25, 11, 48, 222, 206, 11, 48, 230, 232, - 11, 48, 222, 226, 11, 48, 193, 48, 11, 48, 235, 89, 11, 48, 202, 247, 11, - 48, 219, 140, 11, 48, 238, 143, 11, 48, 238, 184, 11, 48, 243, 12, 11, - 48, 228, 101, 11, 48, 203, 123, 11, 48, 190, 242, 11, 48, 203, 44, 11, - 48, 243, 127, 11, 48, 190, 212, 11, 48, 214, 189, 11, 48, 222, 22, 219, - 88, 1, 249, 153, 219, 88, 1, 168, 219, 88, 1, 209, 228, 219, 88, 1, 238, - 32, 219, 88, 1, 190, 190, 219, 88, 1, 199, 49, 219, 88, 1, 231, 240, 219, - 88, 1, 155, 219, 88, 1, 221, 215, 219, 88, 1, 223, 32, 219, 88, 1, 247, - 160, 219, 88, 1, 247, 1, 219, 88, 1, 235, 35, 219, 88, 1, 197, 168, 219, - 88, 1, 197, 157, 219, 88, 1, 174, 219, 88, 1, 180, 219, 88, 1, 173, 219, - 88, 1, 188, 219, 88, 1, 191, 71, 219, 88, 1, 191, 123, 219, 88, 1, 214, - 68, 219, 88, 1, 140, 219, 88, 1, 192, 220, 219, 88, 1, 229, 177, 219, 88, - 1, 233, 109, 219, 88, 1, 193, 190, 219, 88, 1, 203, 165, 219, 88, 1, 170, - 219, 88, 1, 231, 91, 219, 88, 1, 65, 219, 88, 1, 252, 25, 219, 88, 1, 71, - 219, 88, 1, 233, 242, 219, 88, 1, 68, 219, 88, 1, 74, 219, 88, 1, 66, - 219, 88, 1, 196, 152, 219, 88, 1, 196, 141, 219, 88, 1, 211, 151, 219, - 88, 1, 163, 215, 69, 198, 193, 219, 88, 1, 163, 215, 7, 209, 73, 219, 88, - 1, 163, 215, 69, 238, 142, 219, 88, 1, 163, 215, 69, 248, 111, 219, 88, - 1, 163, 215, 69, 180, 219, 88, 1, 163, 215, 69, 222, 253, 219, 88, 208, - 152, 242, 74, 219, 88, 208, 152, 232, 80, 201, 63, 59, 5, 234, 188, 59, - 5, 234, 184, 59, 5, 229, 215, 59, 5, 193, 114, 59, 5, 193, 113, 59, 5, - 210, 49, 59, 5, 248, 195, 59, 5, 249, 1, 59, 5, 217, 3, 59, 5, 221, 16, - 59, 5, 216, 132, 59, 5, 231, 178, 59, 5, 233, 52, 59, 5, 195, 148, 59, 5, - 199, 121, 59, 5, 199, 31, 59, 5, 237, 58, 59, 5, 237, 55, 59, 5, 219, - 228, 59, 5, 207, 84, 59, 5, 237, 131, 59, 5, 214, 153, 59, 5, 205, 50, - 59, 5, 203, 111, 59, 5, 191, 84, 59, 5, 191, 61, 59, 5, 247, 34, 59, 5, - 223, 8, 59, 5, 213, 148, 59, 5, 192, 77, 59, 5, 222, 13, 59, 5, 214, 41, - 59, 5, 231, 157, 59, 5, 216, 211, 59, 5, 214, 110, 59, 5, 212, 89, 59, 5, - 68, 59, 5, 223, 162, 59, 5, 229, 158, 59, 5, 229, 128, 59, 5, 193, 86, - 59, 5, 193, 68, 59, 5, 209, 185, 59, 5, 248, 193, 59, 5, 248, 188, 59, 5, - 216, 252, 59, 5, 221, 13, 59, 5, 216, 129, 59, 5, 231, 174, 59, 5, 233, - 23, 59, 5, 195, 69, 59, 5, 198, 193, 59, 5, 199, 11, 59, 5, 237, 50, 59, - 5, 237, 54, 59, 5, 219, 146, 59, 5, 207, 1, 59, 5, 237, 44, 59, 5, 214, - 147, 59, 5, 202, 222, 59, 5, 203, 81, 59, 5, 191, 30, 59, 5, 191, 57, 59, - 5, 243, 29, 59, 5, 222, 244, 59, 5, 213, 141, 59, 5, 192, 33, 59, 5, 221, - 166, 59, 5, 214, 33, 59, 5, 231, 53, 59, 5, 216, 100, 59, 5, 213, 219, - 59, 5, 212, 81, 59, 5, 65, 59, 5, 251, 132, 59, 5, 214, 63, 59, 5, 140, - 59, 5, 230, 56, 59, 5, 193, 190, 59, 5, 193, 164, 59, 5, 168, 59, 5, 248, - 203, 59, 5, 249, 153, 59, 5, 217, 11, 59, 5, 221, 21, 59, 5, 221, 19, 59, - 5, 216, 136, 59, 5, 231, 182, 59, 5, 233, 109, 59, 5, 195, 188, 59, 5, - 190, 190, 59, 5, 199, 49, 59, 5, 237, 68, 59, 5, 237, 57, 59, 5, 173, 59, - 5, 165, 59, 5, 238, 32, 59, 5, 214, 162, 59, 5, 188, 59, 5, 203, 165, 59, - 5, 191, 123, 59, 5, 191, 71, 59, 5, 247, 160, 59, 5, 223, 32, 59, 5, 213, - 157, 59, 5, 170, 59, 5, 155, 59, 5, 222, 87, 59, 5, 214, 47, 59, 5, 231, - 240, 59, 5, 174, 59, 5, 180, 59, 5, 212, 101, 59, 5, 211, 87, 59, 5, 211, - 82, 59, 5, 228, 252, 59, 5, 193, 29, 59, 5, 193, 25, 59, 5, 209, 37, 59, - 5, 248, 191, 59, 5, 248, 97, 59, 5, 216, 247, 59, 5, 221, 11, 59, 5, 216, - 125, 59, 5, 231, 170, 59, 5, 232, 162, 59, 5, 195, 8, 59, 5, 198, 59, 59, - 5, 198, 235, 59, 5, 237, 47, 59, 5, 237, 52, 59, 5, 219, 8, 59, 5, 206, - 134, 59, 5, 236, 146, 59, 5, 214, 134, 59, 5, 202, 16, 59, 5, 203, 48, - 59, 5, 191, 4, 59, 5, 191, 52, 59, 5, 239, 18, 59, 5, 222, 191, 59, 5, - 213, 131, 59, 5, 191, 246, 59, 5, 221, 41, 59, 5, 214, 31, 59, 5, 230, - 245, 59, 5, 215, 211, 59, 5, 213, 26, 59, 5, 212, 62, 59, 5, 66, 59, 5, - 196, 113, 59, 5, 228, 159, 59, 5, 228, 142, 59, 5, 193, 0, 59, 5, 192, - 249, 59, 5, 208, 165, 59, 5, 248, 190, 59, 5, 248, 10, 59, 5, 216, 246, - 59, 5, 221, 9, 59, 5, 216, 124, 59, 5, 231, 169, 59, 5, 232, 86, 59, 5, - 193, 249, 59, 5, 197, 94, 59, 5, 198, 213, 59, 5, 237, 45, 59, 5, 237, - 51, 59, 5, 218, 225, 59, 5, 206, 68, 59, 5, 235, 89, 59, 5, 214, 129, 59, - 5, 201, 4, 59, 5, 203, 5, 59, 5, 190, 251, 59, 5, 191, 48, 59, 5, 238, - 195, 59, 5, 222, 182, 59, 5, 213, 127, 59, 5, 191, 225, 59, 5, 220, 232, - 59, 5, 214, 30, 59, 5, 230, 179, 59, 5, 215, 155, 59, 5, 212, 178, 59, 5, - 212, 58, 59, 5, 74, 59, 5, 211, 104, 59, 5, 213, 245, 59, 5, 229, 23, 59, - 5, 228, 255, 59, 5, 193, 48, 59, 5, 193, 30, 59, 5, 209, 73, 59, 5, 248, - 192, 59, 5, 248, 111, 59, 5, 216, 248, 59, 5, 221, 12, 59, 5, 216, 127, - 59, 5, 231, 172, 59, 5, 231, 171, 59, 5, 232, 175, 59, 5, 195, 24, 59, 5, - 159, 59, 5, 198, 241, 59, 5, 237, 48, 59, 5, 237, 53, 59, 5, 219, 43, 59, - 5, 206, 162, 59, 5, 236, 174, 59, 5, 214, 138, 59, 5, 202, 46, 59, 5, - 203, 56, 59, 5, 191, 7, 59, 5, 191, 54, 59, 5, 242, 99, 59, 5, 222, 201, - 59, 5, 213, 132, 59, 5, 192, 12, 59, 5, 221, 67, 59, 5, 214, 32, 59, 5, - 231, 3, 59, 5, 216, 12, 59, 5, 213, 43, 59, 5, 212, 65, 59, 5, 71, 59, 5, - 234, 103, 59, 5, 214, 52, 59, 5, 229, 245, 59, 5, 229, 198, 59, 5, 193, - 125, 59, 5, 193, 108, 59, 5, 210, 63, 59, 5, 248, 196, 59, 5, 249, 17, - 59, 5, 217, 4, 59, 5, 221, 17, 59, 5, 221, 15, 59, 5, 216, 133, 59, 5, - 231, 179, 59, 5, 231, 177, 59, 5, 233, 59, 59, 5, 195, 153, 59, 5, 199, - 145, 59, 5, 199, 33, 59, 5, 237, 59, 59, 5, 237, 56, 59, 5, 219, 238, 59, - 5, 207, 113, 59, 5, 237, 146, 59, 5, 214, 154, 59, 5, 205, 68, 59, 5, - 203, 113, 59, 5, 191, 87, 59, 5, 191, 62, 59, 5, 247, 42, 59, 5, 223, 10, - 59, 5, 213, 150, 59, 5, 192, 80, 59, 5, 222, 22, 59, 5, 214, 42, 59, 5, - 214, 38, 59, 5, 231, 165, 59, 5, 231, 151, 59, 5, 216, 232, 59, 5, 214, - 121, 59, 5, 212, 90, 59, 5, 214, 70, 59, 5, 219, 190, 59, 242, 74, 59, - 232, 80, 201, 63, 59, 208, 13, 77, 59, 5, 214, 137, 233, 109, 59, 5, 214, - 137, 155, 59, 5, 214, 137, 202, 16, 59, 16, 233, 48, 59, 16, 222, 11, 59, - 16, 198, 140, 59, 16, 213, 186, 59, 16, 249, 95, 59, 16, 233, 108, 59, - 16, 199, 245, 59, 16, 237, 236, 59, 16, 236, 145, 59, 16, 220, 208, 59, - 16, 198, 63, 59, 16, 236, 173, 59, 16, 222, 192, 59, 17, 191, 77, 59, 17, - 107, 59, 17, 109, 59, 17, 138, 59, 17, 134, 59, 17, 149, 59, 17, 169, 59, - 17, 175, 59, 17, 171, 59, 17, 178, 59, 5, 214, 137, 174, 59, 5, 214, 137, - 236, 174, 38, 6, 1, 191, 81, 38, 2, 1, 191, 81, 38, 6, 1, 235, 30, 38, 2, - 1, 235, 30, 38, 6, 1, 207, 18, 235, 32, 38, 2, 1, 207, 18, 235, 32, 38, - 6, 1, 223, 83, 38, 2, 1, 223, 83, 38, 6, 1, 236, 191, 38, 2, 1, 236, 191, - 38, 6, 1, 215, 219, 196, 128, 38, 2, 1, 215, 219, 196, 128, 38, 6, 1, - 248, 24, 211, 110, 38, 2, 1, 248, 24, 211, 110, 38, 6, 1, 214, 82, 192, - 62, 38, 2, 1, 214, 82, 192, 62, 38, 6, 1, 192, 59, 4, 249, 147, 192, 62, - 38, 2, 1, 192, 59, 4, 249, 147, 192, 62, 38, 6, 1, 223, 81, 192, 95, 38, - 2, 1, 223, 81, 192, 95, 38, 6, 1, 207, 18, 191, 225, 38, 2, 1, 207, 18, - 191, 225, 38, 6, 1, 223, 81, 65, 38, 2, 1, 223, 81, 65, 38, 6, 1, 242, - 219, 219, 83, 191, 190, 38, 2, 1, 242, 219, 219, 83, 191, 190, 38, 6, 1, - 248, 131, 191, 190, 38, 2, 1, 248, 131, 191, 190, 38, 6, 1, 223, 81, 242, - 219, 219, 83, 191, 190, 38, 2, 1, 223, 81, 242, 219, 219, 83, 191, 190, - 38, 6, 1, 192, 14, 38, 2, 1, 192, 14, 38, 6, 1, 207, 18, 197, 161, 38, 2, - 1, 207, 18, 197, 161, 38, 6, 1, 202, 32, 237, 146, 38, 2, 1, 202, 32, - 237, 146, 38, 6, 1, 202, 32, 234, 140, 38, 2, 1, 202, 32, 234, 140, 38, - 6, 1, 202, 32, 234, 114, 38, 2, 1, 202, 32, 234, 114, 38, 6, 1, 215, 223, - 74, 38, 2, 1, 215, 223, 74, 38, 6, 1, 248, 164, 74, 38, 2, 1, 248, 164, - 74, 38, 6, 1, 55, 215, 223, 74, 38, 2, 1, 55, 215, 223, 74, 38, 1, 215, - 130, 74, 33, 38, 193, 226, 33, 38, 199, 96, 216, 48, 56, 33, 38, 228, - 141, 216, 48, 56, 33, 38, 198, 230, 216, 48, 56, 202, 95, 250, 193, 33, - 38, 1, 196, 125, 223, 226, 33, 38, 1, 68, 33, 38, 1, 192, 33, 33, 38, 1, - 66, 33, 38, 1, 230, 17, 56, 33, 38, 1, 192, 58, 33, 38, 1, 202, 32, 56, - 33, 38, 1, 211, 110, 33, 38, 222, 35, 33, 38, 210, 70, 38, 222, 35, 38, - 210, 70, 38, 6, 1, 235, 45, 38, 2, 1, 235, 45, 38, 6, 1, 235, 21, 38, 2, - 1, 235, 21, 38, 6, 1, 191, 38, 38, 2, 1, 191, 38, 38, 6, 1, 247, 58, 38, - 2, 1, 247, 58, 38, 6, 1, 235, 17, 38, 2, 1, 235, 17, 38, 6, 1, 199, 146, - 4, 82, 102, 38, 2, 1, 199, 146, 4, 82, 102, 38, 6, 1, 197, 41, 38, 2, 1, - 197, 41, 38, 6, 1, 197, 136, 38, 2, 1, 197, 136, 38, 6, 1, 197, 141, 38, - 2, 1, 197, 141, 38, 6, 1, 199, 151, 38, 2, 1, 199, 151, 38, 6, 1, 228, - 122, 38, 2, 1, 228, 122, 38, 6, 1, 202, 237, 38, 2, 1, 202, 237, 38, 6, - 1, 55, 74, 38, 2, 1, 55, 74, 38, 6, 1, 238, 214, 74, 38, 2, 1, 238, 214, - 74, 52, 1, 38, 230, 17, 56, 52, 1, 38, 202, 32, 56, 33, 38, 1, 234, 181, - 33, 38, 1, 223, 81, 71, 26, 1, 65, 26, 1, 155, 26, 1, 66, 26, 1, 220, - 232, 26, 1, 234, 188, 26, 1, 207, 84, 26, 1, 199, 226, 26, 1, 74, 26, 1, - 212, 81, 26, 1, 68, 26, 1, 173, 26, 1, 168, 26, 1, 206, 195, 26, 1, 206, - 242, 26, 1, 219, 227, 26, 1, 216, 210, 26, 1, 199, 245, 26, 1, 214, 160, - 26, 1, 213, 155, 26, 1, 218, 168, 26, 1, 200, 160, 26, 1, 215, 155, 26, - 1, 203, 76, 26, 1, 202, 222, 26, 1, 203, 86, 26, 1, 203, 248, 26, 1, 220, - 149, 26, 1, 221, 241, 26, 1, 212, 146, 26, 1, 212, 178, 26, 1, 213, 126, - 26, 1, 191, 243, 26, 1, 203, 5, 26, 1, 191, 194, 26, 1, 170, 26, 1, 212, - 215, 26, 1, 221, 227, 26, 1, 209, 232, 26, 1, 213, 148, 26, 1, 212, 195, - 26, 1, 208, 156, 26, 1, 192, 253, 26, 1, 210, 49, 26, 1, 233, 52, 26, 1, - 206, 68, 26, 1, 218, 225, 26, 1, 216, 100, 26, 1, 213, 219, 26, 1, 207, - 20, 26, 1, 207, 163, 26, 1, 221, 251, 26, 1, 213, 252, 26, 1, 214, 47, - 26, 1, 214, 68, 26, 1, 203, 56, 26, 1, 208, 161, 26, 1, 232, 86, 26, 1, - 232, 167, 26, 1, 193, 190, 26, 1, 180, 26, 1, 219, 146, 26, 1, 209, 185, - 26, 1, 219, 0, 26, 1, 221, 67, 26, 1, 217, 1, 26, 1, 207, 55, 26, 1, 216, - 186, 26, 1, 174, 26, 1, 198, 193, 26, 1, 221, 166, 26, 1, 216, 12, 26, 1, - 217, 9, 26, 1, 199, 73, 26, 1, 221, 21, 26, 1, 199, 95, 26, 1, 212, 181, - 26, 1, 205, 150, 26, 1, 233, 105, 26, 1, 221, 24, 26, 1, 221, 57, 26, 33, - 87, 221, 34, 26, 33, 87, 197, 79, 26, 213, 154, 26, 232, 80, 201, 63, 26, - 242, 83, 26, 242, 74, 26, 204, 25, 26, 208, 13, 77, 52, 1, 243, 80, 163, - 192, 22, 209, 132, 52, 1, 243, 80, 163, 192, 107, 209, 132, 52, 1, 243, - 80, 163, 192, 22, 203, 137, 52, 1, 243, 80, 163, 192, 107, 203, 137, 52, - 1, 243, 80, 163, 192, 22, 208, 33, 52, 1, 243, 80, 163, 192, 107, 208, - 33, 52, 1, 243, 80, 163, 192, 22, 206, 68, 52, 1, 243, 80, 163, 192, 107, - 206, 68, 52, 1, 233, 200, 235, 138, 163, 164, 52, 1, 137, 235, 138, 163, - 164, 52, 1, 216, 87, 235, 138, 163, 164, 52, 1, 130, 235, 138, 163, 164, - 52, 1, 233, 199, 235, 138, 163, 164, 52, 1, 233, 200, 235, 138, 219, 216, - 163, 164, 52, 1, 137, 235, 138, 219, 216, 163, 164, 52, 1, 216, 87, 235, - 138, 219, 216, 163, 164, 52, 1, 130, 235, 138, 219, 216, 163, 164, 52, 1, - 233, 199, 235, 138, 219, 216, 163, 164, 52, 1, 233, 200, 219, 216, 163, - 164, 52, 1, 137, 219, 216, 163, 164, 52, 1, 216, 87, 219, 216, 163, 164, - 52, 1, 130, 219, 216, 163, 164, 52, 1, 233, 199, 219, 216, 163, 164, 52, - 1, 75, 81, 164, 52, 1, 75, 202, 97, 52, 1, 75, 228, 241, 164, 52, 1, 110, - 50, 239, 2, 251, 115, 52, 1, 207, 147, 133, 57, 52, 1, 207, 147, 144, 57, - 52, 1, 207, 147, 233, 216, 77, 52, 1, 207, 147, 223, 93, 233, 216, 77, - 52, 1, 130, 223, 93, 233, 216, 77, 52, 1, 201, 38, 23, 137, 198, 79, 52, - 1, 201, 38, 23, 130, 198, 79, 8, 6, 1, 234, 175, 251, 192, 8, 2, 1, 234, - 175, 251, 192, 8, 6, 1, 234, 175, 251, 230, 8, 2, 1, 234, 175, 251, 230, - 8, 6, 1, 229, 196, 8, 2, 1, 229, 196, 8, 6, 1, 196, 241, 8, 2, 1, 196, - 241, 8, 6, 1, 197, 248, 8, 2, 1, 197, 248, 8, 6, 1, 238, 192, 8, 2, 1, - 238, 192, 8, 6, 1, 238, 193, 4, 242, 74, 8, 2, 1, 238, 193, 4, 242, 74, - 8, 1, 2, 6, 233, 175, 8, 1, 2, 6, 206, 8, 8, 6, 1, 252, 206, 8, 2, 1, - 252, 206, 8, 6, 1, 251, 68, 8, 2, 1, 251, 68, 8, 6, 1, 250, 163, 8, 2, 1, - 250, 163, 8, 6, 1, 250, 146, 8, 2, 1, 250, 146, 8, 6, 1, 250, 147, 4, - 228, 241, 164, 8, 2, 1, 250, 147, 4, 228, 241, 164, 8, 6, 1, 250, 131, 8, - 2, 1, 250, 131, 8, 6, 1, 207, 18, 247, 194, 4, 236, 140, 8, 2, 1, 207, - 18, 247, 194, 4, 236, 140, 8, 6, 1, 222, 153, 4, 106, 8, 2, 1, 222, 153, - 4, 106, 8, 6, 1, 222, 153, 4, 237, 39, 106, 8, 2, 1, 222, 153, 4, 237, - 39, 106, 8, 6, 1, 222, 153, 4, 201, 28, 23, 237, 39, 106, 8, 2, 1, 222, - 153, 4, 201, 28, 23, 237, 39, 106, 8, 6, 1, 248, 22, 172, 8, 2, 1, 248, - 22, 172, 8, 6, 1, 220, 143, 4, 137, 106, 8, 2, 1, 220, 143, 4, 137, 106, - 8, 6, 1, 187, 4, 179, 201, 28, 210, 255, 8, 2, 1, 187, 4, 179, 201, 28, - 210, 255, 8, 6, 1, 187, 4, 219, 4, 8, 2, 1, 187, 4, 219, 4, 8, 6, 1, 211, - 87, 8, 2, 1, 211, 87, 8, 6, 1, 210, 237, 4, 201, 28, 198, 216, 237, 87, - 8, 2, 1, 210, 237, 4, 201, 28, 198, 216, 237, 87, 8, 6, 1, 210, 237, 4, - 232, 188, 8, 2, 1, 210, 237, 4, 232, 188, 8, 6, 1, 210, 237, 4, 201, 182, - 199, 215, 8, 2, 1, 210, 237, 4, 201, 182, 199, 215, 8, 6, 1, 208, 105, 4, - 201, 28, 198, 216, 237, 87, 8, 2, 1, 208, 105, 4, 201, 28, 198, 216, 237, - 87, 8, 6, 1, 208, 105, 4, 237, 39, 106, 8, 2, 1, 208, 105, 4, 237, 39, - 106, 8, 6, 1, 207, 222, 206, 116, 8, 2, 1, 207, 222, 206, 116, 8, 6, 1, - 206, 49, 206, 116, 8, 2, 1, 206, 49, 206, 116, 8, 6, 1, 196, 13, 4, 237, - 39, 106, 8, 2, 1, 196, 13, 4, 237, 39, 106, 8, 6, 1, 193, 235, 8, 2, 1, - 193, 235, 8, 6, 1, 195, 33, 191, 166, 8, 2, 1, 195, 33, 191, 166, 8, 6, - 1, 198, 234, 4, 106, 8, 2, 1, 198, 234, 4, 106, 8, 6, 1, 198, 234, 4, - 201, 28, 198, 216, 237, 87, 8, 2, 1, 198, 234, 4, 201, 28, 198, 216, 237, - 87, 8, 6, 1, 195, 142, 8, 2, 1, 195, 142, 8, 6, 1, 233, 255, 8, 2, 1, - 233, 255, 8, 6, 1, 223, 68, 8, 2, 1, 223, 68, 8, 6, 1, 239, 57, 8, 2, 1, - 239, 57, 52, 1, 196, 45, 8, 2, 1, 235, 77, 8, 2, 1, 218, 208, 8, 2, 1, - 215, 123, 8, 2, 1, 212, 137, 8, 2, 1, 206, 48, 8, 1, 2, 6, 206, 48, 8, 2, - 1, 197, 76, 8, 2, 1, 196, 120, 8, 6, 1, 223, 115, 238, 127, 8, 2, 1, 223, - 115, 238, 127, 8, 6, 1, 223, 115, 233, 175, 8, 2, 1, 223, 115, 233, 175, - 8, 6, 1, 223, 115, 232, 51, 8, 6, 1, 153, 223, 115, 232, 51, 8, 2, 1, - 153, 223, 115, 232, 51, 8, 6, 1, 153, 172, 8, 2, 1, 153, 172, 8, 6, 1, - 223, 115, 146, 8, 2, 1, 223, 115, 146, 8, 6, 1, 223, 115, 206, 8, 8, 2, - 1, 223, 115, 206, 8, 8, 6, 1, 223, 115, 200, 43, 8, 2, 1, 223, 115, 200, - 43, 52, 1, 130, 243, 2, 252, 60, 52, 1, 242, 83, 52, 1, 203, 40, 234, 43, - 56, 8, 6, 1, 205, 156, 8, 2, 1, 205, 156, 8, 6, 1, 153, 230, 116, 8, 2, - 1, 220, 143, 4, 207, 24, 228, 251, 23, 248, 231, 8, 1, 202, 163, 236, - 140, 8, 6, 1, 215, 62, 4, 237, 87, 8, 2, 1, 215, 62, 4, 237, 87, 8, 6, 1, - 247, 194, 4, 164, 8, 2, 1, 247, 194, 4, 164, 8, 2, 1, 247, 194, 4, 210, - 192, 102, 8, 2, 1, 230, 117, 4, 210, 192, 102, 8, 6, 1, 78, 4, 232, 188, - 8, 2, 1, 78, 4, 232, 188, 8, 6, 1, 233, 176, 4, 106, 8, 2, 1, 233, 176, - 4, 106, 8, 6, 1, 195, 15, 252, 25, 8, 2, 1, 195, 15, 252, 25, 8, 6, 1, - 195, 15, 211, 151, 8, 2, 1, 195, 15, 211, 151, 8, 6, 1, 195, 15, 196, - 152, 8, 2, 1, 195, 15, 196, 152, 8, 6, 1, 232, 52, 4, 211, 172, 106, 8, - 2, 1, 232, 52, 4, 211, 172, 106, 8, 6, 1, 222, 153, 4, 211, 172, 106, 8, - 2, 1, 222, 153, 4, 211, 172, 106, 8, 6, 1, 215, 62, 4, 211, 172, 106, 8, - 2, 1, 215, 62, 4, 211, 172, 106, 8, 6, 1, 207, 222, 4, 211, 172, 106, 8, - 2, 1, 207, 222, 4, 211, 172, 106, 8, 6, 1, 206, 9, 4, 211, 172, 106, 8, - 2, 1, 206, 9, 4, 211, 172, 106, 8, 6, 1, 230, 117, 4, 102, 8, 6, 1, 207, - 18, 211, 77, 71, 8, 6, 1, 27, 232, 51, 8, 6, 1, 220, 143, 4, 248, 231, 8, - 6, 1, 2, 6, 68, 8, 1, 2, 6, 208, 104, 8, 6, 1, 153, 222, 152, 8, 6, 1, - 153, 200, 43, 8, 6, 1, 223, 36, 4, 238, 212, 8, 6, 1, 243, 95, 8, 6, 1, - 248, 212, 8, 2, 1, 248, 212, 8, 6, 1, 211, 110, 8, 2, 1, 211, 110, 8, 6, - 1, 126, 4, 106, 8, 2, 1, 126, 4, 106, 8, 6, 1, 231, 11, 65, 8, 2, 1, 231, - 11, 65, 8, 6, 1, 231, 11, 68, 8, 2, 1, 231, 11, 68, 8, 6, 1, 231, 11, 66, - 8, 2, 1, 231, 11, 66, 8, 6, 1, 39, 209, 49, 74, 8, 2, 1, 39, 209, 49, 74, - 8, 6, 1, 251, 112, 193, 224, 8, 2, 1, 251, 112, 193, 224, 8, 6, 1, 247, - 194, 4, 210, 192, 102, 8, 6, 1, 206, 9, 4, 102, 8, 6, 1, 191, 167, 4, - 210, 192, 102, 8, 6, 1, 238, 128, 4, 203, 40, 201, 28, 210, 255, 8, 2, 1, - 238, 128, 4, 203, 40, 201, 28, 210, 255, 8, 6, 1, 206, 9, 4, 203, 40, - 201, 28, 210, 255, 8, 2, 1, 206, 9, 4, 203, 40, 201, 28, 210, 255, 8, 6, - 1, 242, 219, 223, 115, 232, 51, 8, 2, 1, 242, 219, 223, 115, 232, 51, 8, - 2, 1, 55, 198, 233, 8, 2, 1, 55, 192, 238, 8, 6, 1, 82, 205, 79, 206, 8, - 8, 2, 1, 82, 205, 79, 206, 8, 8, 6, 1, 202, 195, 206, 8, 8, 2, 1, 202, - 195, 206, 8, 52, 1, 6, 247, 193, 52, 1, 6, 233, 175, 52, 1, 6, 208, 104, - 8, 6, 1, 207, 18, 132, 230, 116, 8, 2, 1, 207, 18, 132, 230, 116, 8, 234, - 50, 1, 202, 206, 68, 52, 1, 6, 230, 117, 4, 106, 52, 1, 2, 34, 211, 151, - 8, 1, 2, 6, 153, 218, 168, 8, 234, 50, 1, 207, 18, 233, 175, 8, 234, 50, - 1, 207, 18, 210, 236, 8, 234, 50, 1, 223, 93, 218, 168, 8, 234, 50, 1, - 228, 74, 219, 10, 8, 234, 50, 1, 251, 14, 218, 168, 200, 124, 214, 238, - 1, 65, 200, 124, 214, 238, 1, 68, 200, 124, 214, 238, 3, 235, 54, 200, - 124, 214, 238, 1, 66, 200, 124, 214, 238, 1, 71, 200, 124, 214, 238, 1, - 74, 200, 124, 214, 238, 3, 230, 11, 200, 124, 214, 238, 1, 221, 67, 200, - 124, 214, 238, 1, 221, 183, 200, 124, 214, 238, 1, 231, 3, 200, 124, 214, - 238, 1, 231, 63, 200, 124, 214, 238, 3, 251, 71, 200, 124, 214, 238, 1, - 242, 99, 200, 124, 214, 238, 1, 243, 68, 200, 124, 214, 238, 1, 222, 201, - 200, 124, 214, 238, 1, 222, 246, 200, 124, 214, 238, 1, 197, 109, 200, - 124, 214, 238, 1, 197, 115, 200, 124, 214, 238, 1, 237, 161, 200, 124, - 214, 238, 1, 237, 170, 200, 124, 214, 238, 1, 159, 200, 124, 214, 238, 1, - 198, 241, 200, 124, 214, 238, 1, 236, 174, 200, 124, 214, 238, 1, 237, - 48, 200, 124, 214, 238, 1, 213, 43, 200, 124, 214, 238, 1, 209, 73, 200, - 124, 214, 238, 1, 209, 199, 200, 124, 214, 238, 1, 248, 111, 200, 124, - 214, 238, 1, 248, 192, 200, 124, 214, 238, 1, 216, 12, 200, 124, 214, - 238, 1, 206, 162, 200, 124, 214, 238, 1, 219, 43, 200, 124, 214, 238, 1, - 206, 95, 200, 124, 214, 238, 1, 202, 46, 200, 124, 214, 238, 1, 229, 23, - 200, 124, 214, 238, 18, 3, 65, 200, 124, 214, 238, 18, 3, 68, 200, 124, - 214, 238, 18, 3, 66, 200, 124, 214, 238, 18, 3, 71, 200, 124, 214, 238, - 18, 3, 211, 87, 200, 124, 214, 238, 209, 63, 217, 55, 200, 124, 214, 238, - 209, 63, 217, 54, 200, 124, 214, 238, 209, 63, 217, 53, 200, 124, 214, - 238, 209, 63, 217, 52, 200, 124, 214, 238, 3, 251, 157, 230, 11, 186, - 223, 146, 232, 118, 91, 208, 22, 186, 223, 146, 232, 118, 91, 230, 70, - 186, 223, 146, 232, 118, 115, 208, 20, 186, 223, 146, 232, 118, 91, 202, - 128, 186, 223, 146, 232, 118, 91, 234, 159, 186, 223, 146, 232, 118, 115, - 202, 125, 186, 223, 146, 208, 23, 77, 186, 223, 146, 209, 107, 77, 186, - 223, 146, 206, 36, 77, 186, 223, 146, 208, 25, 77, 209, 224, 1, 155, 209, - 224, 1, 221, 215, 209, 224, 1, 231, 240, 209, 224, 1, 214, 68, 209, 224, - 1, 247, 160, 209, 224, 1, 247, 1, 209, 224, 1, 223, 32, 209, 224, 1, 212, - 101, 209, 224, 1, 190, 190, 209, 224, 1, 199, 49, 209, 224, 1, 238, 32, - 209, 224, 1, 180, 209, 224, 1, 168, 209, 224, 1, 209, 228, 209, 224, 1, - 249, 153, 209, 224, 1, 174, 209, 224, 1, 197, 168, 209, 224, 1, 197, 157, - 209, 224, 1, 235, 35, 209, 224, 1, 193, 190, 209, 224, 1, 191, 71, 209, - 224, 1, 191, 123, 209, 224, 1, 2, 65, 209, 224, 1, 170, 209, 224, 1, 165, - 209, 224, 1, 173, 209, 224, 1, 203, 165, 209, 224, 1, 188, 209, 224, 1, - 140, 209, 224, 1, 65, 209, 224, 1, 68, 209, 224, 1, 66, 209, 224, 1, 71, - 209, 224, 1, 74, 209, 224, 1, 208, 96, 209, 224, 1, 192, 220, 209, 224, - 1, 233, 109, 209, 224, 1, 231, 127, 209, 224, 1, 234, 188, 209, 224, 200, - 239, 1, 193, 190, 209, 224, 200, 239, 1, 170, 209, 224, 1, 197, 132, 209, - 224, 1, 197, 120, 209, 224, 1, 237, 191, 209, 224, 1, 213, 79, 209, 224, - 1, 251, 157, 170, 209, 224, 1, 195, 19, 203, 165, 209, 224, 1, 195, 20, - 140, 209, 224, 1, 250, 200, 233, 109, 209, 224, 200, 239, 1, 165, 209, - 224, 200, 185, 1, 165, 209, 224, 1, 247, 119, 209, 224, 202, 170, 229, - 236, 77, 209, 224, 55, 229, 236, 77, 209, 224, 87, 203, 157, 209, 224, - 87, 55, 203, 157, 205, 111, 3, 251, 71, 205, 111, 3, 195, 35, 205, 111, - 1, 65, 205, 111, 1, 252, 206, 205, 111, 1, 68, 205, 111, 1, 223, 199, - 205, 111, 1, 66, 205, 111, 1, 196, 30, 205, 111, 1, 117, 146, 205, 111, - 1, 117, 206, 110, 205, 111, 1, 117, 172, 205, 111, 1, 117, 219, 74, 205, - 111, 1, 71, 205, 111, 1, 234, 188, 205, 111, 1, 251, 236, 205, 111, 1, - 74, 205, 111, 1, 211, 87, 205, 111, 1, 250, 163, 205, 111, 1, 155, 205, - 111, 1, 221, 215, 205, 111, 1, 231, 240, 205, 111, 1, 231, 91, 205, 111, - 1, 214, 68, 205, 111, 1, 247, 160, 205, 111, 1, 247, 1, 205, 111, 1, 223, - 32, 205, 111, 1, 222, 252, 205, 111, 1, 212, 101, 205, 111, 1, 197, 132, - 205, 111, 1, 197, 120, 205, 111, 1, 237, 191, 205, 111, 1, 237, 175, 205, - 111, 1, 213, 79, 205, 111, 1, 190, 190, 205, 111, 1, 199, 49, 205, 111, - 1, 238, 32, 205, 111, 1, 237, 68, 205, 111, 1, 180, 205, 111, 1, 168, - 205, 111, 1, 209, 228, 205, 111, 1, 249, 153, 205, 111, 1, 248, 203, 205, - 111, 1, 174, 205, 111, 1, 170, 205, 111, 1, 165, 205, 111, 1, 173, 205, - 111, 1, 195, 188, 205, 111, 1, 203, 165, 205, 111, 1, 201, 175, 205, 111, - 1, 188, 205, 111, 1, 140, 205, 111, 1, 219, 73, 205, 111, 120, 3, 230, - 89, 205, 111, 18, 3, 252, 206, 205, 111, 18, 3, 68, 205, 111, 18, 3, 223, - 199, 205, 111, 18, 3, 66, 205, 111, 18, 3, 196, 30, 205, 111, 18, 3, 117, - 146, 205, 111, 18, 3, 117, 206, 110, 205, 111, 18, 3, 117, 172, 205, 111, - 18, 3, 117, 219, 74, 205, 111, 18, 3, 71, 205, 111, 18, 3, 234, 188, 205, - 111, 18, 3, 251, 236, 205, 111, 18, 3, 74, 205, 111, 18, 3, 211, 87, 205, - 111, 18, 3, 250, 163, 205, 111, 3, 195, 40, 205, 111, 3, 247, 119, 205, - 111, 237, 238, 205, 111, 55, 237, 238, 205, 111, 17, 191, 77, 205, 111, - 17, 107, 205, 111, 17, 109, 205, 111, 17, 138, 205, 111, 17, 134, 205, - 111, 17, 149, 205, 111, 17, 169, 205, 111, 17, 175, 205, 111, 17, 171, - 205, 111, 17, 178, 33, 100, 17, 191, 77, 33, 100, 17, 107, 33, 100, 17, - 109, 33, 100, 17, 138, 33, 100, 17, 134, 33, 100, 17, 149, 33, 100, 17, - 169, 33, 100, 17, 175, 33, 100, 17, 171, 33, 100, 17, 178, 33, 100, 1, - 65, 33, 100, 1, 66, 33, 100, 1, 155, 33, 100, 1, 180, 33, 100, 1, 168, - 33, 100, 1, 165, 33, 100, 1, 195, 69, 33, 100, 3, 250, 145, 100, 3, 201, - 246, 247, 119, 100, 3, 247, 120, 195, 40, 100, 3, 55, 247, 120, 195, 40, - 100, 3, 247, 120, 109, 100, 3, 247, 120, 138, 100, 3, 247, 120, 250, 145, - 100, 3, 208, 134, 100, 231, 204, 233, 3, 100, 247, 96, 100, 229, 227, - 100, 3, 202, 210, 100, 223, 24, 211, 113, 100, 1, 250, 131, 100, 18, 3, - 250, 131, 222, 28, 219, 147, 17, 191, 77, 222, 28, 219, 147, 17, 107, - 222, 28, 219, 147, 17, 109, 222, 28, 219, 147, 17, 138, 222, 28, 219, - 147, 17, 134, 222, 28, 219, 147, 17, 149, 222, 28, 219, 147, 17, 169, - 222, 28, 219, 147, 17, 175, 222, 28, 219, 147, 17, 171, 222, 28, 219, - 147, 17, 178, 222, 28, 219, 147, 1, 155, 222, 28, 219, 147, 1, 221, 215, - 222, 28, 219, 147, 1, 231, 240, 222, 28, 219, 147, 1, 214, 68, 222, 28, - 219, 147, 1, 188, 222, 28, 219, 147, 1, 203, 165, 222, 28, 219, 147, 1, - 191, 123, 222, 28, 219, 147, 1, 212, 101, 222, 28, 219, 147, 1, 190, 190, - 222, 28, 219, 147, 1, 228, 164, 222, 28, 219, 147, 1, 180, 222, 28, 219, - 147, 1, 168, 222, 28, 219, 147, 1, 209, 228, 222, 28, 219, 147, 1, 174, - 222, 28, 219, 147, 1, 238, 32, 222, 28, 219, 147, 1, 249, 153, 222, 28, - 219, 147, 1, 165, 222, 28, 219, 147, 1, 170, 222, 28, 219, 147, 1, 173, - 222, 28, 219, 147, 1, 193, 190, 222, 28, 219, 147, 1, 199, 49, 222, 28, - 219, 147, 1, 140, 222, 28, 219, 147, 1, 195, 188, 222, 28, 219, 147, 1, - 247, 160, 222, 28, 219, 147, 1, 65, 222, 28, 219, 147, 1, 211, 151, 222, - 28, 219, 147, 1, 68, 222, 28, 219, 147, 1, 211, 87, 222, 28, 219, 147, - 18, 196, 152, 222, 28, 219, 147, 18, 71, 222, 28, 219, 147, 18, 66, 222, - 28, 219, 147, 18, 234, 188, 222, 28, 219, 147, 18, 74, 222, 28, 219, 147, - 163, 209, 90, 222, 28, 219, 147, 163, 247, 135, 222, 28, 219, 147, 163, - 247, 136, 209, 90, 222, 28, 219, 147, 3, 238, 147, 222, 28, 219, 147, 3, - 202, 230, 207, 67, 1, 155, 207, 67, 1, 231, 240, 207, 67, 1, 214, 68, - 207, 67, 1, 190, 190, 207, 67, 1, 238, 32, 207, 67, 1, 180, 207, 67, 1, - 168, 207, 67, 1, 249, 153, 207, 67, 1, 174, 207, 67, 1, 247, 160, 207, - 67, 1, 223, 32, 207, 67, 1, 212, 101, 207, 67, 1, 188, 207, 67, 1, 165, - 207, 67, 1, 173, 207, 67, 1, 170, 207, 67, 1, 193, 190, 207, 67, 1, 140, - 207, 67, 1, 217, 11, 207, 67, 1, 214, 47, 207, 67, 1, 214, 162, 207, 67, - 1, 212, 66, 207, 67, 1, 65, 207, 67, 18, 3, 68, 207, 67, 18, 3, 66, 207, - 67, 18, 3, 71, 207, 67, 18, 3, 251, 236, 207, 67, 18, 3, 74, 207, 67, 18, - 3, 250, 163, 207, 67, 18, 3, 233, 242, 207, 67, 18, 3, 234, 217, 207, 67, - 120, 3, 214, 70, 207, 67, 120, 3, 215, 61, 207, 67, 120, 3, 146, 207, 67, - 120, 3, 230, 116, 207, 67, 195, 40, 207, 67, 205, 54, 77, 30, 147, 198, - 164, 30, 147, 198, 163, 30, 147, 198, 161, 30, 147, 198, 166, 30, 147, - 206, 234, 30, 147, 206, 218, 30, 147, 206, 213, 30, 147, 206, 215, 30, - 147, 206, 231, 30, 147, 206, 224, 30, 147, 206, 217, 30, 147, 206, 236, - 30, 147, 206, 219, 30, 147, 206, 238, 30, 147, 206, 235, 30, 147, 216, - 73, 30, 147, 216, 64, 30, 147, 216, 67, 30, 147, 209, 154, 30, 147, 209, - 165, 30, 147, 209, 166, 30, 147, 201, 159, 30, 147, 223, 212, 30, 147, - 223, 219, 30, 147, 201, 170, 30, 147, 201, 157, 30, 147, 209, 208, 30, - 147, 229, 137, 30, 147, 201, 154, 223, 16, 3, 210, 143, 223, 16, 3, 247, - 39, 223, 16, 3, 219, 246, 223, 16, 3, 193, 71, 223, 16, 1, 65, 223, 16, - 1, 228, 74, 222, 32, 223, 16, 1, 68, 223, 16, 1, 223, 199, 223, 16, 1, - 66, 223, 16, 1, 210, 221, 247, 9, 223, 16, 1, 214, 69, 219, 203, 223, 16, - 1, 214, 69, 219, 204, 207, 131, 223, 16, 1, 71, 223, 16, 1, 251, 236, - 223, 16, 1, 74, 223, 16, 1, 155, 223, 16, 1, 222, 142, 205, 124, 223, 16, - 1, 222, 142, 215, 107, 223, 16, 1, 231, 240, 223, 16, 1, 231, 241, 215, - 107, 223, 16, 1, 214, 68, 223, 16, 1, 247, 160, 223, 16, 1, 247, 161, - 215, 107, 223, 16, 1, 223, 32, 223, 16, 1, 212, 102, 215, 107, 223, 16, - 1, 223, 33, 217, 116, 223, 16, 1, 212, 101, 223, 16, 1, 197, 132, 223, - 16, 1, 197, 133, 217, 116, 223, 16, 1, 237, 191, 223, 16, 1, 237, 192, - 217, 116, 223, 16, 1, 215, 7, 215, 107, 223, 16, 1, 190, 190, 223, 16, 1, - 199, 252, 215, 107, 223, 16, 1, 238, 32, 223, 16, 1, 238, 33, 217, 116, - 223, 16, 1, 180, 223, 16, 1, 168, 223, 16, 1, 210, 221, 215, 107, 223, - 16, 1, 249, 153, 223, 16, 1, 249, 154, 215, 107, 223, 16, 1, 174, 223, - 16, 1, 170, 223, 16, 1, 165, 223, 16, 1, 207, 186, 251, 246, 223, 16, 1, - 173, 223, 16, 1, 193, 190, 223, 16, 1, 205, 207, 215, 107, 223, 16, 1, - 205, 207, 217, 116, 223, 16, 1, 188, 223, 16, 1, 140, 223, 16, 3, 247, - 40, 199, 100, 223, 16, 18, 3, 199, 175, 223, 16, 18, 3, 198, 84, 223, 16, - 18, 3, 192, 250, 223, 16, 18, 3, 192, 251, 216, 198, 223, 16, 18, 3, 200, - 208, 223, 16, 18, 3, 200, 209, 216, 185, 223, 16, 18, 3, 199, 201, 223, - 16, 18, 3, 236, 230, 215, 106, 223, 16, 18, 3, 210, 16, 223, 16, 120, 3, - 221, 244, 223, 16, 120, 3, 210, 31, 223, 16, 120, 3, 247, 145, 223, 16, - 210, 157, 223, 16, 45, 207, 40, 223, 16, 50, 207, 40, 223, 16, 210, 209, - 251, 124, 223, 16, 210, 209, 217, 137, 223, 16, 210, 209, 218, 212, 223, - 16, 210, 209, 193, 64, 223, 16, 210, 209, 210, 158, 223, 16, 210, 209, - 219, 104, 223, 16, 210, 209, 218, 204, 223, 16, 210, 209, 252, 36, 223, - 16, 210, 209, 252, 37, 252, 36, 223, 16, 210, 209, 209, 119, 223, 16, - 153, 210, 209, 209, 119, 223, 16, 210, 153, 223, 16, 17, 191, 77, 223, - 16, 17, 107, 223, 16, 17, 109, 223, 16, 17, 138, 223, 16, 17, 134, 223, - 16, 17, 149, 223, 16, 17, 169, 223, 16, 17, 175, 223, 16, 17, 171, 223, - 16, 17, 178, 223, 16, 210, 209, 198, 127, 197, 73, 223, 16, 210, 209, - 223, 64, 80, 1, 203, 139, 231, 91, 80, 1, 203, 139, 247, 1, 80, 1, 203, - 139, 222, 252, 80, 1, 203, 139, 213, 79, 80, 1, 203, 139, 248, 203, 80, - 3, 203, 139, 205, 108, 80, 52, 1, 203, 139, 207, 85, 80, 1, 54, 220, 95, - 212, 101, 80, 1, 54, 220, 95, 233, 109, 80, 1, 54, 220, 95, 231, 240, 80, - 1, 54, 220, 95, 231, 91, 80, 1, 54, 220, 95, 223, 32, 80, 1, 54, 220, 95, - 222, 252, 80, 1, 54, 220, 95, 237, 191, 80, 1, 54, 220, 95, 237, 175, 80, - 1, 54, 220, 95, 213, 79, 80, 54, 220, 95, 17, 191, 77, 80, 54, 220, 95, - 17, 107, 80, 54, 220, 95, 17, 109, 80, 54, 220, 95, 17, 138, 80, 54, 220, - 95, 17, 134, 80, 54, 220, 95, 17, 149, 80, 54, 220, 95, 17, 169, 80, 54, - 220, 95, 17, 175, 80, 54, 220, 95, 17, 171, 80, 54, 220, 95, 17, 178, 80, - 1, 54, 220, 95, 219, 73, 80, 1, 54, 220, 95, 238, 32, 80, 1, 54, 220, 95, - 237, 68, 80, 1, 54, 220, 95, 249, 153, 80, 1, 54, 220, 95, 248, 203, 246, - 250, 1, 65, 246, 250, 1, 68, 246, 250, 1, 66, 246, 250, 1, 71, 246, 250, - 1, 251, 236, 246, 250, 1, 74, 246, 250, 1, 155, 246, 250, 1, 221, 215, - 246, 250, 1, 231, 240, 246, 250, 1, 231, 91, 246, 250, 1, 213, 233, 246, - 250, 1, 214, 68, 246, 250, 1, 247, 1, 246, 250, 1, 243, 98, 246, 250, 1, - 223, 32, 246, 250, 1, 222, 252, 246, 250, 1, 213, 221, 246, 250, 1, 213, - 224, 246, 250, 1, 213, 222, 246, 250, 1, 190, 190, 246, 250, 1, 199, 49, - 246, 250, 1, 238, 32, 246, 250, 1, 237, 68, 246, 250, 1, 212, 144, 246, - 250, 1, 180, 246, 250, 1, 237, 191, 246, 250, 1, 168, 246, 250, 1, 208, - 250, 246, 250, 1, 209, 228, 246, 250, 1, 249, 153, 246, 250, 1, 248, 203, - 246, 250, 1, 215, 143, 246, 250, 1, 174, 246, 250, 1, 249, 53, 246, 250, - 1, 170, 246, 250, 1, 165, 246, 250, 1, 173, 246, 250, 1, 195, 188, 246, - 250, 1, 201, 175, 246, 250, 1, 188, 246, 250, 1, 140, 246, 250, 18, 3, - 252, 206, 246, 250, 18, 3, 68, 246, 250, 18, 3, 223, 199, 246, 250, 18, - 3, 234, 166, 246, 250, 18, 3, 66, 246, 250, 18, 3, 211, 151, 246, 250, - 18, 3, 74, 246, 250, 18, 3, 251, 236, 246, 250, 18, 3, 250, 163, 246, - 250, 18, 3, 196, 152, 246, 250, 120, 3, 170, 246, 250, 120, 3, 165, 246, - 250, 120, 3, 173, 246, 250, 120, 3, 193, 190, 246, 250, 1, 53, 222, 152, - 246, 250, 1, 53, 232, 51, 246, 250, 1, 53, 214, 70, 246, 250, 120, 3, 53, - 214, 70, 246, 250, 1, 53, 247, 3, 246, 250, 1, 53, 200, 43, 246, 250, 1, - 53, 215, 61, 246, 250, 1, 53, 210, 236, 246, 250, 1, 53, 192, 159, 246, - 250, 1, 53, 146, 246, 250, 1, 53, 172, 246, 250, 1, 53, 201, 178, 246, - 250, 120, 3, 53, 218, 168, 246, 250, 120, 3, 53, 230, 116, 246, 250, 17, - 191, 77, 246, 250, 17, 107, 246, 250, 17, 109, 246, 250, 17, 138, 246, - 250, 17, 134, 246, 250, 17, 149, 246, 250, 17, 169, 246, 250, 17, 175, - 246, 250, 17, 171, 246, 250, 17, 178, 246, 250, 208, 152, 201, 217, 246, - 250, 208, 152, 237, 238, 246, 250, 208, 152, 55, 237, 238, 246, 250, 208, - 152, 197, 225, 237, 238, 80, 1, 221, 206, 231, 240, 80, 1, 221, 206, 247, - 160, 80, 1, 221, 206, 247, 1, 80, 1, 221, 206, 223, 32, 80, 1, 221, 206, - 222, 252, 80, 1, 221, 206, 212, 101, 80, 1, 221, 206, 197, 132, 80, 1, - 221, 206, 197, 120, 80, 1, 221, 206, 237, 191, 80, 1, 221, 206, 237, 175, - 80, 1, 221, 206, 237, 68, 80, 1, 221, 206, 180, 80, 1, 221, 206, 188, 80, - 1, 221, 206, 140, 80, 1, 221, 206, 229, 177, 80, 1, 221, 206, 233, 109, - 80, 52, 1, 221, 206, 207, 85, 80, 1, 221, 206, 192, 220, 80, 1, 221, 206, - 191, 123, 80, 1, 221, 206, 165, 80, 219, 28, 221, 206, 211, 179, 80, 219, - 28, 221, 206, 208, 46, 80, 219, 28, 221, 206, 229, 78, 80, 16, 251, 222, - 233, 215, 80, 16, 251, 222, 107, 80, 16, 251, 222, 109, 80, 1, 251, 222, - 165, 80, 3, 210, 139, 222, 62, 198, 79, 80, 3, 54, 220, 95, 198, 77, 80, - 3, 54, 220, 95, 198, 74, 80, 1, 202, 238, 210, 189, 247, 1, 80, 1, 202, - 238, 210, 189, 203, 165, 54, 195, 59, 1, 130, 221, 67, 54, 195, 59, 1, - 137, 221, 67, 54, 195, 59, 1, 130, 221, 183, 54, 195, 59, 1, 137, 221, - 183, 54, 195, 59, 1, 130, 221, 192, 54, 195, 59, 1, 137, 221, 192, 54, - 195, 59, 1, 130, 231, 3, 54, 195, 59, 1, 137, 231, 3, 54, 195, 59, 1, - 130, 213, 249, 54, 195, 59, 1, 137, 213, 249, 54, 195, 59, 1, 130, 242, - 99, 54, 195, 59, 1, 137, 242, 99, 54, 195, 59, 1, 130, 243, 68, 54, 195, - 59, 1, 137, 243, 68, 54, 195, 59, 1, 130, 202, 46, 54, 195, 59, 1, 137, - 202, 46, 54, 195, 59, 1, 130, 212, 65, 54, 195, 59, 1, 137, 212, 65, 54, - 195, 59, 1, 130, 236, 174, 54, 195, 59, 1, 137, 236, 174, 54, 195, 59, 1, - 130, 159, 54, 195, 59, 1, 137, 159, 54, 195, 59, 1, 130, 198, 241, 54, - 195, 59, 1, 137, 198, 241, 54, 195, 59, 1, 130, 213, 43, 54, 195, 59, 1, - 137, 213, 43, 54, 195, 59, 1, 130, 248, 111, 54, 195, 59, 1, 137, 248, - 111, 54, 195, 59, 1, 130, 209, 73, 54, 195, 59, 1, 137, 209, 73, 54, 195, - 59, 1, 130, 209, 199, 54, 195, 59, 1, 137, 209, 199, 54, 195, 59, 1, 130, - 232, 175, 54, 195, 59, 1, 137, 232, 175, 54, 195, 59, 1, 130, 216, 12, - 54, 195, 59, 1, 137, 216, 12, 54, 195, 59, 1, 130, 192, 12, 54, 195, 59, - 1, 137, 192, 12, 54, 195, 59, 1, 130, 206, 162, 54, 195, 59, 1, 137, 206, - 162, 54, 195, 59, 1, 130, 219, 43, 54, 195, 59, 1, 137, 219, 43, 54, 195, - 59, 1, 130, 195, 24, 54, 195, 59, 1, 137, 195, 24, 54, 195, 59, 1, 130, - 229, 23, 54, 195, 59, 1, 137, 229, 23, 54, 195, 59, 1, 130, 74, 54, 195, - 59, 1, 137, 74, 54, 195, 59, 217, 113, 222, 83, 54, 195, 59, 18, 252, - 206, 54, 195, 59, 18, 68, 54, 195, 59, 18, 196, 152, 54, 195, 59, 18, 66, - 54, 195, 59, 18, 71, 54, 195, 59, 18, 74, 54, 195, 59, 217, 113, 221, - 186, 54, 195, 59, 18, 228, 35, 54, 195, 59, 18, 196, 151, 54, 195, 59, - 18, 196, 168, 54, 195, 59, 18, 250, 161, 54, 195, 59, 18, 250, 131, 54, - 195, 59, 18, 251, 132, 54, 195, 59, 18, 251, 149, 54, 195, 59, 163, 217, - 113, 234, 147, 54, 195, 59, 163, 217, 113, 212, 143, 54, 195, 59, 163, - 217, 113, 198, 241, 54, 195, 59, 163, 217, 113, 202, 18, 54, 195, 59, 16, - 221, 44, 54, 195, 59, 16, 212, 143, 54, 195, 59, 16, 205, 152, 54, 195, - 59, 16, 229, 24, 229, 10, 54, 195, 59, 16, 221, 55, 221, 54, 216, 205, - 217, 18, 1, 71, 216, 205, 217, 18, 1, 74, 216, 205, 217, 18, 1, 247, 1, - 216, 205, 217, 18, 1, 212, 101, 216, 205, 217, 18, 1, 197, 132, 216, 205, - 217, 18, 1, 197, 120, 216, 205, 217, 18, 1, 237, 191, 216, 205, 217, 18, - 1, 237, 175, 216, 205, 217, 18, 1, 213, 79, 216, 205, 217, 18, 1, 203, - 165, 216, 205, 217, 18, 1, 201, 175, 216, 205, 217, 18, 18, 3, 223, 199, - 216, 205, 217, 18, 18, 3, 196, 30, 216, 205, 217, 18, 18, 3, 252, 170, - 216, 205, 217, 18, 18, 3, 250, 163, 216, 205, 217, 18, 18, 3, 252, 162, - 216, 205, 217, 18, 243, 116, 216, 205, 217, 18, 251, 242, 221, 173, 216, - 205, 217, 18, 251, 100, 216, 205, 217, 18, 5, 207, 46, 77, 216, 205, 217, - 18, 193, 23, 207, 46, 77, 216, 205, 217, 18, 18, 3, 195, 35, 216, 205, - 217, 18, 195, 40, 36, 5, 197, 113, 36, 5, 197, 116, 36, 5, 197, 119, 36, - 5, 197, 117, 36, 5, 197, 118, 36, 5, 197, 115, 36, 5, 237, 169, 36, 5, - 237, 171, 36, 5, 237, 174, 36, 5, 237, 172, 36, 5, 237, 173, 36, 5, 237, - 170, 36, 5, 235, 22, 36, 5, 235, 26, 36, 5, 235, 34, 36, 5, 235, 31, 36, - 5, 235, 32, 36, 5, 235, 23, 36, 5, 247, 56, 36, 5, 247, 50, 36, 5, 247, - 52, 36, 5, 247, 55, 36, 5, 247, 53, 36, 5, 247, 54, 36, 5, 247, 51, 36, - 5, 249, 53, 36, 5, 249, 32, 36, 5, 249, 44, 36, 5, 249, 52, 36, 5, 249, - 47, 36, 5, 249, 48, 36, 5, 249, 36, 8, 2, 1, 249, 82, 251, 160, 8, 2, 1, - 42, 207, 16, 8, 2, 1, 248, 135, 71, 8, 2, 1, 249, 82, 71, 8, 2, 1, 235, - 15, 4, 232, 188, 8, 2, 1, 219, 189, 233, 175, 8, 2, 1, 27, 232, 52, 4, - 238, 212, 8, 2, 1, 220, 143, 4, 223, 93, 219, 245, 206, 8, 8, 2, 1, 220, - 143, 4, 55, 82, 198, 152, 8, 2, 1, 220, 143, 4, 82, 206, 188, 8, 2, 1, - 218, 169, 4, 238, 212, 8, 2, 1, 215, 62, 4, 238, 212, 8, 2, 1, 234, 89, - 4, 238, 212, 8, 2, 1, 248, 135, 74, 8, 2, 1, 248, 135, 187, 4, 106, 8, 2, - 1, 211, 77, 187, 4, 106, 8, 2, 1, 223, 93, 211, 151, 8, 2, 1, 153, 211, - 152, 4, 106, 8, 2, 1, 153, 211, 152, 4, 228, 241, 106, 8, 2, 1, 153, 187, - 211, 72, 8, 2, 1, 153, 187, 211, 73, 4, 106, 8, 2, 1, 201, 68, 146, 8, 1, - 2, 6, 207, 222, 4, 50, 219, 212, 8, 2, 1, 207, 222, 193, 51, 230, 31, 8, - 2, 1, 55, 146, 8, 2, 1, 207, 222, 4, 238, 212, 8, 2, 1, 55, 207, 222, 4, - 238, 212, 8, 2, 1, 27, 146, 8, 2, 1, 27, 207, 222, 4, 206, 188, 8, 2, 1, - 249, 72, 234, 12, 8, 2, 1, 126, 4, 203, 40, 50, 219, 212, 8, 2, 1, 126, - 249, 88, 4, 203, 40, 50, 219, 212, 8, 2, 1, 196, 139, 8, 2, 1, 153, 196, - 139, 8, 2, 1, 126, 4, 45, 102, 8, 2, 1, 243, 95, 8, 2, 1, 243, 96, 4, - 130, 50, 206, 188, 8, 2, 1, 243, 96, 4, 130, 45, 204, 5, 8, 2, 1, 192, - 236, 4, 130, 50, 206, 188, 8, 2, 1, 192, 236, 4, 179, 45, 219, 212, 8, 2, - 1, 192, 236, 4, 179, 45, 219, 213, 23, 130, 50, 206, 188, 8, 2, 1, 192, - 236, 4, 179, 45, 219, 213, 4, 204, 5, 8, 2, 1, 192, 160, 4, 203, 40, 50, - 219, 212, 52, 248, 37, 4, 223, 93, 248, 36, 52, 1, 2, 229, 196, 52, 1, 2, - 220, 143, 4, 223, 93, 219, 245, 206, 8, 52, 1, 2, 220, 143, 4, 82, 198, - 152, 52, 1, 2, 126, 4, 45, 102, 8, 2, 1, 205, 174, 192, 95, 8, 2, 1, 223, - 81, 71, 8, 2, 1, 211, 77, 211, 151, 8, 2, 1, 196, 82, 8, 2, 1, 223, 93, - 251, 160, 35, 1, 2, 6, 211, 110, 8, 2, 1, 235, 37, 237, 3, 4, 207, 24, - 102, 8, 2, 1, 197, 170, 237, 3, 4, 207, 24, 102, 8, 2, 1, 153, 207, 222, - 4, 82, 198, 152, 52, 1, 2, 153, 193, 224, 52, 1, 45, 199, 228, 52, 1, 50, - 199, 228, 103, 2, 1, 65, 103, 2, 1, 71, 103, 2, 1, 68, 103, 2, 1, 74, - 103, 2, 1, 66, 103, 2, 1, 196, 12, 103, 2, 1, 231, 240, 103, 2, 1, 155, - 103, 2, 1, 231, 165, 103, 2, 1, 231, 53, 103, 2, 1, 231, 3, 103, 2, 1, - 230, 179, 103, 2, 1, 230, 138, 103, 2, 1, 140, 103, 2, 1, 229, 245, 103, - 2, 1, 229, 158, 103, 2, 1, 229, 23, 103, 2, 1, 228, 159, 103, 2, 1, 228, - 126, 103, 2, 1, 173, 103, 2, 1, 219, 238, 103, 2, 1, 219, 146, 103, 2, 1, - 219, 43, 103, 2, 1, 218, 225, 103, 2, 1, 218, 192, 103, 2, 1, 174, 103, - 2, 1, 216, 232, 103, 2, 1, 216, 100, 103, 2, 1, 216, 12, 103, 2, 1, 215, - 155, 103, 2, 1, 180, 103, 2, 1, 229, 47, 103, 2, 1, 214, 237, 103, 2, 1, - 214, 121, 103, 2, 1, 213, 219, 103, 2, 1, 213, 43, 103, 2, 1, 212, 178, - 103, 2, 1, 212, 112, 103, 2, 1, 208, 32, 103, 2, 1, 208, 16, 103, 2, 1, - 208, 9, 103, 2, 1, 207, 255, 103, 2, 1, 207, 244, 103, 2, 1, 207, 242, - 103, 2, 1, 188, 103, 2, 1, 206, 8, 103, 2, 1, 205, 68, 103, 2, 1, 202, - 222, 103, 2, 1, 202, 46, 103, 2, 1, 201, 4, 103, 2, 1, 200, 158, 103, 2, - 1, 238, 32, 103, 2, 1, 190, 190, 103, 2, 1, 237, 146, 103, 2, 1, 199, - 145, 103, 2, 1, 237, 44, 103, 2, 1, 198, 193, 103, 2, 1, 236, 174, 103, - 2, 1, 235, 89, 103, 2, 1, 235, 57, 103, 2, 1, 236, 186, 103, 2, 1, 198, - 115, 103, 2, 1, 198, 114, 103, 2, 1, 198, 103, 103, 2, 1, 198, 102, 103, - 2, 1, 198, 101, 103, 2, 1, 198, 100, 103, 2, 1, 197, 168, 103, 2, 1, 197, - 161, 103, 2, 1, 197, 146, 103, 2, 1, 197, 144, 103, 2, 1, 197, 140, 103, - 2, 1, 197, 139, 103, 2, 1, 193, 190, 103, 2, 1, 193, 125, 103, 2, 1, 193, - 86, 103, 2, 1, 193, 48, 103, 2, 1, 193, 0, 103, 2, 1, 192, 243, 103, 2, - 1, 170, 216, 205, 217, 18, 1, 221, 51, 216, 205, 217, 18, 1, 205, 152, - 216, 205, 217, 18, 1, 220, 96, 216, 205, 217, 18, 1, 216, 23, 216, 205, - 217, 18, 1, 168, 216, 205, 217, 18, 1, 180, 216, 205, 217, 18, 1, 243, - 87, 216, 205, 217, 18, 1, 198, 154, 216, 205, 217, 18, 1, 221, 176, 216, - 205, 217, 18, 1, 213, 239, 216, 205, 217, 18, 1, 198, 232, 216, 205, 217, - 18, 1, 193, 173, 216, 205, 217, 18, 1, 192, 106, 216, 205, 217, 18, 1, - 228, 147, 216, 205, 217, 18, 1, 196, 113, 216, 205, 217, 18, 1, 68, 216, - 205, 217, 18, 1, 209, 222, 216, 205, 217, 18, 1, 250, 175, 216, 205, 217, - 18, 1, 230, 251, 216, 205, 217, 18, 1, 222, 250, 216, 205, 217, 18, 1, - 207, 156, 216, 205, 217, 18, 1, 249, 153, 216, 205, 217, 18, 1, 222, 234, - 216, 205, 217, 18, 1, 237, 1, 216, 205, 217, 18, 1, 231, 60, 216, 205, - 217, 18, 1, 237, 46, 216, 205, 217, 18, 1, 248, 198, 216, 205, 217, 18, - 1, 221, 52, 219, 9, 216, 205, 217, 18, 1, 220, 97, 219, 9, 216, 205, 217, - 18, 1, 216, 24, 219, 9, 216, 205, 217, 18, 1, 210, 221, 219, 9, 216, 205, - 217, 18, 1, 215, 7, 219, 9, 216, 205, 217, 18, 1, 198, 155, 219, 9, 216, - 205, 217, 18, 1, 213, 240, 219, 9, 216, 205, 217, 18, 1, 228, 74, 219, 9, - 216, 205, 217, 18, 18, 3, 211, 102, 216, 205, 217, 18, 18, 3, 223, 160, - 216, 205, 217, 18, 18, 3, 251, 130, 216, 205, 217, 18, 18, 3, 192, 69, - 216, 205, 217, 18, 18, 3, 202, 6, 216, 205, 217, 18, 18, 3, 196, 110, - 216, 205, 217, 18, 18, 3, 243, 114, 216, 205, 217, 18, 18, 3, 212, 127, - 216, 205, 217, 18, 243, 115, 216, 205, 217, 18, 218, 209, 223, 42, 216, - 205, 217, 18, 251, 38, 223, 42, 216, 205, 217, 18, 17, 191, 77, 216, 205, - 217, 18, 17, 107, 216, 205, 217, 18, 17, 109, 216, 205, 217, 18, 17, 138, - 216, 205, 217, 18, 17, 134, 216, 205, 217, 18, 17, 149, 216, 205, 217, - 18, 17, 169, 216, 205, 217, 18, 17, 175, 216, 205, 217, 18, 17, 171, 216, - 205, 217, 18, 17, 178, 30, 222, 174, 212, 3, 30, 222, 174, 212, 8, 30, - 222, 174, 192, 5, 30, 222, 174, 192, 4, 30, 222, 174, 192, 3, 30, 222, - 174, 196, 218, 30, 222, 174, 196, 222, 30, 222, 174, 191, 219, 30, 222, - 174, 191, 215, 30, 222, 174, 233, 241, 30, 222, 174, 233, 239, 30, 222, - 174, 233, 240, 30, 222, 174, 233, 237, 30, 222, 174, 228, 60, 30, 222, - 174, 228, 59, 30, 222, 174, 228, 57, 30, 222, 174, 228, 58, 30, 222, 174, - 228, 63, 30, 222, 174, 228, 56, 30, 222, 174, 228, 55, 30, 222, 174, 228, - 65, 30, 222, 174, 251, 24, 30, 222, 174, 251, 23, 30, 125, 213, 197, 30, - 125, 213, 203, 30, 125, 201, 156, 30, 125, 201, 155, 30, 125, 198, 163, - 30, 125, 198, 161, 30, 125, 198, 160, 30, 125, 198, 166, 30, 125, 198, - 167, 30, 125, 198, 159, 30, 125, 206, 218, 30, 125, 206, 233, 30, 125, - 201, 162, 30, 125, 206, 230, 30, 125, 206, 220, 30, 125, 206, 222, 30, - 125, 206, 209, 30, 125, 206, 210, 30, 125, 222, 68, 30, 125, 216, 72, 30, - 125, 216, 66, 30, 125, 201, 166, 30, 125, 216, 69, 30, 125, 216, 75, 30, - 125, 209, 150, 30, 125, 209, 159, 30, 125, 209, 163, 30, 125, 201, 164, - 30, 125, 209, 153, 30, 125, 209, 167, 30, 125, 209, 168, 30, 125, 202, - 152, 30, 125, 202, 155, 30, 125, 201, 160, 30, 125, 201, 158, 30, 125, - 202, 150, 30, 125, 202, 158, 30, 125, 202, 159, 30, 125, 202, 144, 30, - 125, 202, 157, 30, 125, 210, 147, 30, 125, 210, 148, 30, 125, 192, 53, - 30, 125, 192, 56, 30, 125, 243, 22, 30, 125, 243, 21, 30, 125, 201, 171, - 30, 125, 209, 206, 30, 125, 209, 205, 12, 15, 225, 190, 12, 15, 225, 189, - 12, 15, 225, 188, 12, 15, 225, 187, 12, 15, 225, 186, 12, 15, 225, 185, - 12, 15, 225, 184, 12, 15, 225, 183, 12, 15, 225, 182, 12, 15, 225, 181, - 12, 15, 225, 180, 12, 15, 225, 179, 12, 15, 225, 178, 12, 15, 225, 177, - 12, 15, 225, 176, 12, 15, 225, 175, 12, 15, 225, 174, 12, 15, 225, 173, - 12, 15, 225, 172, 12, 15, 225, 171, 12, 15, 225, 170, 12, 15, 225, 169, - 12, 15, 225, 168, 12, 15, 225, 167, 12, 15, 225, 166, 12, 15, 225, 165, - 12, 15, 225, 164, 12, 15, 225, 163, 12, 15, 225, 162, 12, 15, 225, 161, - 12, 15, 225, 160, 12, 15, 225, 159, 12, 15, 225, 158, 12, 15, 225, 157, - 12, 15, 225, 156, 12, 15, 225, 155, 12, 15, 225, 154, 12, 15, 225, 153, - 12, 15, 225, 152, 12, 15, 225, 151, 12, 15, 225, 150, 12, 15, 225, 149, - 12, 15, 225, 148, 12, 15, 225, 147, 12, 15, 225, 146, 12, 15, 225, 145, - 12, 15, 225, 144, 12, 15, 225, 143, 12, 15, 225, 142, 12, 15, 225, 141, - 12, 15, 225, 140, 12, 15, 225, 139, 12, 15, 225, 138, 12, 15, 225, 137, - 12, 15, 225, 136, 12, 15, 225, 135, 12, 15, 225, 134, 12, 15, 225, 133, - 12, 15, 225, 132, 12, 15, 225, 131, 12, 15, 225, 130, 12, 15, 225, 129, - 12, 15, 225, 128, 12, 15, 225, 127, 12, 15, 225, 126, 12, 15, 225, 125, - 12, 15, 225, 124, 12, 15, 225, 123, 12, 15, 225, 122, 12, 15, 225, 121, - 12, 15, 225, 120, 12, 15, 225, 119, 12, 15, 225, 118, 12, 15, 225, 117, - 12, 15, 225, 116, 12, 15, 225, 115, 12, 15, 225, 114, 12, 15, 225, 113, - 12, 15, 225, 112, 12, 15, 225, 111, 12, 15, 225, 110, 12, 15, 225, 109, - 12, 15, 225, 108, 12, 15, 225, 107, 12, 15, 225, 106, 12, 15, 225, 105, - 12, 15, 225, 104, 12, 15, 225, 103, 12, 15, 225, 102, 12, 15, 225, 101, - 12, 15, 225, 100, 12, 15, 225, 99, 12, 15, 225, 98, 12, 15, 225, 97, 12, - 15, 225, 96, 12, 15, 225, 95, 12, 15, 225, 94, 12, 15, 225, 93, 12, 15, - 225, 92, 12, 15, 225, 91, 12, 15, 225, 90, 12, 15, 225, 89, 12, 15, 225, - 88, 12, 15, 225, 87, 12, 15, 225, 86, 12, 15, 225, 85, 12, 15, 225, 84, - 12, 15, 225, 83, 12, 15, 225, 82, 12, 15, 225, 81, 12, 15, 225, 80, 12, - 15, 225, 79, 12, 15, 225, 78, 12, 15, 225, 77, 12, 15, 225, 76, 12, 15, - 225, 75, 12, 15, 225, 74, 12, 15, 225, 73, 12, 15, 225, 72, 12, 15, 225, - 71, 12, 15, 225, 70, 12, 15, 225, 69, 12, 15, 225, 68, 12, 15, 225, 67, - 12, 15, 225, 66, 12, 15, 225, 65, 12, 15, 225, 64, 12, 15, 225, 63, 12, - 15, 225, 62, 12, 15, 225, 61, 12, 15, 225, 60, 12, 15, 225, 59, 12, 15, - 225, 58, 12, 15, 225, 57, 12, 15, 225, 56, 12, 15, 225, 55, 12, 15, 225, - 54, 12, 15, 225, 53, 12, 15, 225, 52, 12, 15, 225, 51, 12, 15, 225, 50, - 12, 15, 225, 49, 12, 15, 225, 48, 12, 15, 225, 47, 12, 15, 225, 46, 12, - 15, 225, 45, 12, 15, 225, 44, 12, 15, 225, 43, 12, 15, 225, 42, 12, 15, - 225, 41, 12, 15, 225, 40, 12, 15, 225, 39, 12, 15, 225, 38, 12, 15, 225, - 37, 12, 15, 225, 36, 12, 15, 225, 35, 12, 15, 225, 34, 12, 15, 225, 33, - 12, 15, 225, 32, 12, 15, 225, 31, 12, 15, 225, 30, 12, 15, 225, 29, 12, - 15, 225, 28, 12, 15, 225, 27, 12, 15, 225, 26, 12, 15, 225, 25, 12, 15, - 225, 24, 12, 15, 225, 23, 12, 15, 225, 22, 12, 15, 225, 21, 12, 15, 225, - 20, 12, 15, 225, 19, 12, 15, 225, 18, 12, 15, 225, 17, 12, 15, 225, 16, - 12, 15, 225, 15, 12, 15, 225, 14, 12, 15, 225, 13, 12, 15, 225, 12, 12, - 15, 225, 11, 12, 15, 225, 10, 12, 15, 225, 9, 12, 15, 225, 8, 12, 15, - 225, 7, 12, 15, 225, 6, 12, 15, 225, 5, 12, 15, 225, 4, 12, 15, 225, 3, - 12, 15, 225, 2, 12, 15, 225, 1, 12, 15, 225, 0, 12, 15, 224, 255, 12, 15, - 224, 254, 12, 15, 224, 253, 12, 15, 224, 252, 12, 15, 224, 251, 12, 15, - 224, 250, 12, 15, 224, 249, 12, 15, 224, 248, 12, 15, 224, 247, 12, 15, - 224, 246, 12, 15, 224, 245, 12, 15, 224, 244, 12, 15, 224, 243, 12, 15, - 224, 242, 12, 15, 224, 241, 12, 15, 224, 240, 12, 15, 224, 239, 12, 15, - 224, 238, 12, 15, 224, 237, 12, 15, 224, 236, 12, 15, 224, 235, 12, 15, - 224, 234, 12, 15, 224, 233, 12, 15, 224, 232, 12, 15, 224, 231, 12, 15, - 224, 230, 12, 15, 224, 229, 12, 15, 224, 228, 12, 15, 224, 227, 12, 15, - 224, 226, 12, 15, 224, 225, 12, 15, 224, 224, 12, 15, 224, 223, 12, 15, - 224, 222, 12, 15, 224, 221, 12, 15, 224, 220, 12, 15, 224, 219, 12, 15, - 224, 218, 12, 15, 224, 217, 12, 15, 224, 216, 12, 15, 224, 215, 12, 15, - 224, 214, 12, 15, 224, 213, 12, 15, 224, 212, 12, 15, 224, 211, 12, 15, - 224, 210, 12, 15, 224, 209, 12, 15, 224, 208, 12, 15, 224, 207, 12, 15, - 224, 206, 12, 15, 224, 205, 12, 15, 224, 204, 12, 15, 224, 203, 12, 15, - 224, 202, 12, 15, 224, 201, 12, 15, 224, 200, 12, 15, 224, 199, 12, 15, - 224, 198, 12, 15, 224, 197, 12, 15, 224, 196, 12, 15, 224, 195, 12, 15, - 224, 194, 12, 15, 224, 193, 12, 15, 224, 192, 12, 15, 224, 191, 12, 15, - 224, 190, 12, 15, 224, 189, 12, 15, 224, 188, 12, 15, 224, 187, 12, 15, - 224, 186, 12, 15, 224, 185, 12, 15, 224, 184, 12, 15, 224, 183, 12, 15, - 224, 182, 12, 15, 224, 181, 12, 15, 224, 180, 12, 15, 224, 179, 12, 15, - 224, 178, 12, 15, 224, 177, 12, 15, 224, 176, 12, 15, 224, 175, 12, 15, - 224, 174, 12, 15, 224, 173, 12, 15, 224, 172, 12, 15, 224, 171, 12, 15, - 224, 170, 12, 15, 224, 169, 12, 15, 224, 168, 12, 15, 224, 167, 12, 15, - 224, 166, 12, 15, 224, 165, 12, 15, 224, 164, 12, 15, 224, 163, 12, 15, - 224, 162, 12, 15, 224, 161, 12, 15, 224, 160, 12, 15, 224, 159, 12, 15, - 224, 158, 12, 15, 224, 157, 12, 15, 224, 156, 12, 15, 224, 155, 12, 15, - 224, 154, 12, 15, 224, 153, 12, 15, 224, 152, 12, 15, 224, 151, 12, 15, - 224, 150, 12, 15, 224, 149, 12, 15, 224, 148, 12, 15, 224, 147, 12, 15, - 224, 146, 12, 15, 224, 145, 12, 15, 224, 144, 12, 15, 224, 143, 12, 15, - 224, 142, 12, 15, 224, 141, 12, 15, 224, 140, 12, 15, 224, 139, 12, 15, - 224, 138, 12, 15, 224, 137, 12, 15, 224, 136, 12, 15, 224, 135, 12, 15, - 224, 134, 12, 15, 224, 133, 12, 15, 224, 132, 12, 15, 224, 131, 12, 15, - 224, 130, 12, 15, 224, 129, 12, 15, 224, 128, 12, 15, 224, 127, 12, 15, - 224, 126, 12, 15, 224, 125, 12, 15, 224, 124, 12, 15, 224, 123, 12, 15, - 224, 122, 12, 15, 224, 121, 12, 15, 224, 120, 12, 15, 224, 119, 12, 15, - 224, 118, 12, 15, 224, 117, 12, 15, 224, 116, 12, 15, 224, 115, 12, 15, - 224, 114, 12, 15, 224, 113, 12, 15, 224, 112, 12, 15, 224, 111, 12, 15, - 224, 110, 12, 15, 224, 109, 12, 15, 224, 108, 12, 15, 224, 107, 12, 15, - 224, 106, 12, 15, 224, 105, 12, 15, 224, 104, 12, 15, 224, 103, 12, 15, - 224, 102, 12, 15, 224, 101, 12, 15, 224, 100, 12, 15, 224, 99, 12, 15, - 224, 98, 12, 15, 224, 97, 12, 15, 224, 96, 12, 15, 224, 95, 12, 15, 224, - 94, 12, 15, 224, 93, 12, 15, 224, 92, 12, 15, 224, 91, 12, 15, 224, 90, - 12, 15, 224, 89, 12, 15, 224, 88, 12, 15, 224, 87, 12, 15, 224, 86, 12, - 15, 224, 85, 12, 15, 224, 84, 12, 15, 224, 83, 12, 15, 224, 82, 12, 15, - 224, 81, 12, 15, 224, 80, 12, 15, 224, 79, 12, 15, 224, 78, 12, 15, 224, - 77, 12, 15, 224, 76, 12, 15, 224, 75, 12, 15, 224, 74, 12, 15, 224, 73, - 12, 15, 224, 72, 12, 15, 224, 71, 12, 15, 224, 70, 12, 15, 224, 69, 12, - 15, 224, 68, 12, 15, 224, 67, 12, 15, 224, 66, 12, 15, 224, 65, 12, 15, - 224, 64, 12, 15, 224, 63, 12, 15, 224, 62, 12, 15, 224, 61, 12, 15, 224, - 60, 12, 15, 224, 59, 12, 15, 224, 58, 12, 15, 224, 57, 12, 15, 224, 56, - 12, 15, 224, 55, 12, 15, 224, 54, 12, 15, 224, 53, 12, 15, 224, 52, 12, - 15, 224, 51, 12, 15, 224, 50, 12, 15, 224, 49, 12, 15, 224, 48, 12, 15, - 224, 47, 12, 15, 224, 46, 12, 15, 224, 45, 12, 15, 224, 44, 12, 15, 224, - 43, 12, 15, 224, 42, 12, 15, 224, 41, 12, 15, 224, 40, 12, 15, 224, 39, - 12, 15, 224, 38, 12, 15, 224, 37, 12, 15, 224, 36, 12, 15, 224, 35, 12, - 15, 224, 34, 12, 15, 224, 33, 12, 15, 224, 32, 12, 15, 224, 31, 12, 15, - 224, 30, 12, 15, 224, 29, 12, 15, 224, 28, 12, 15, 224, 27, 12, 15, 224, - 26, 12, 15, 224, 25, 12, 15, 224, 24, 12, 15, 224, 23, 12, 15, 224, 22, - 12, 15, 224, 21, 12, 15, 224, 20, 12, 15, 224, 19, 12, 15, 224, 18, 12, - 15, 224, 17, 12, 15, 224, 16, 12, 15, 224, 15, 12, 15, 224, 14, 12, 15, - 224, 13, 12, 15, 224, 12, 12, 15, 224, 11, 12, 15, 224, 10, 12, 15, 224, - 9, 12, 15, 224, 8, 12, 15, 224, 7, 12, 15, 224, 6, 12, 15, 224, 5, 12, - 15, 224, 4, 12, 15, 224, 3, 12, 15, 224, 2, 12, 15, 224, 1, 12, 15, 224, - 0, 12, 15, 223, 255, 12, 15, 223, 254, 12, 15, 223, 253, 12, 15, 223, - 252, 12, 15, 223, 251, 12, 15, 223, 250, 12, 15, 223, 249, 12, 15, 223, - 248, 12, 15, 223, 247, 12, 15, 223, 246, 12, 15, 223, 245, 12, 15, 223, - 244, 12, 15, 223, 243, 12, 15, 223, 242, 12, 15, 223, 241, 12, 15, 223, - 240, 12, 15, 223, 239, 12, 15, 223, 238, 12, 15, 223, 237, 12, 15, 223, - 236, 12, 15, 223, 235, 12, 15, 223, 234, 12, 15, 223, 233, 12, 15, 223, - 232, 12, 15, 223, 231, 8, 2, 34, 233, 27, 8, 2, 34, 233, 23, 8, 2, 34, - 232, 220, 8, 2, 34, 233, 26, 8, 2, 34, 233, 25, 8, 2, 34, 179, 206, 9, - 200, 43, 8, 2, 34, 201, 118, 250, 249, 2, 34, 216, 187, 212, 253, 250, - 249, 2, 34, 216, 187, 234, 195, 250, 249, 2, 34, 216, 187, 223, 131, 250, - 249, 2, 34, 195, 75, 212, 253, 250, 249, 2, 34, 216, 187, 192, 212, 136, - 1, 191, 251, 4, 229, 119, 136, 209, 62, 222, 181, 195, 166, 136, 34, 192, - 31, 191, 251, 191, 251, 210, 88, 136, 1, 251, 152, 250, 126, 136, 1, 193, - 78, 251, 192, 136, 1, 193, 78, 237, 253, 136, 1, 193, 78, 229, 245, 136, - 1, 193, 78, 222, 106, 136, 1, 193, 78, 220, 27, 136, 1, 193, 78, 53, 216, - 193, 136, 1, 193, 78, 207, 38, 136, 1, 193, 78, 199, 162, 136, 1, 251, - 152, 108, 56, 136, 1, 203, 70, 4, 203, 70, 236, 140, 136, 1, 203, 70, 4, - 202, 175, 236, 140, 136, 1, 203, 70, 4, 238, 17, 23, 203, 70, 236, 140, - 136, 1, 203, 70, 4, 238, 17, 23, 202, 175, 236, 140, 136, 1, 131, 4, 210, - 88, 136, 1, 131, 4, 208, 84, 136, 1, 131, 4, 217, 70, 136, 1, 248, 215, - 4, 238, 16, 136, 1, 231, 39, 4, 238, 16, 136, 1, 237, 254, 4, 238, 16, - 136, 1, 229, 246, 4, 217, 70, 136, 1, 195, 159, 4, 238, 16, 136, 1, 191, - 92, 4, 238, 16, 136, 1, 199, 74, 4, 238, 16, 136, 1, 191, 251, 4, 238, - 16, 136, 1, 53, 222, 107, 4, 238, 16, 136, 1, 222, 107, 4, 238, 16, 136, - 1, 220, 28, 4, 238, 16, 136, 1, 216, 194, 4, 238, 16, 136, 1, 212, 131, - 4, 238, 16, 136, 1, 205, 149, 4, 238, 16, 136, 1, 53, 210, 64, 4, 238, - 16, 136, 1, 210, 64, 4, 238, 16, 136, 1, 197, 164, 4, 238, 16, 136, 1, - 208, 43, 4, 238, 16, 136, 1, 207, 39, 4, 238, 16, 136, 1, 203, 70, 4, - 238, 16, 136, 1, 199, 163, 4, 238, 16, 136, 1, 195, 159, 4, 229, 7, 136, - 1, 248, 215, 4, 207, 161, 136, 1, 222, 107, 4, 207, 161, 136, 1, 210, 64, - 4, 207, 161, 136, 34, 131, 220, 27, 9, 1, 131, 193, 151, 76, 20, 9, 1, - 131, 193, 151, 53, 20, 9, 1, 249, 0, 76, 20, 9, 1, 249, 0, 53, 20, 9, 1, - 249, 0, 89, 20, 9, 1, 249, 0, 216, 217, 20, 9, 1, 210, 42, 76, 20, 9, 1, - 210, 42, 53, 20, 9, 1, 210, 42, 89, 20, 9, 1, 210, 42, 216, 217, 20, 9, - 1, 248, 244, 76, 20, 9, 1, 248, 244, 53, 20, 9, 1, 248, 244, 89, 20, 9, - 1, 248, 244, 216, 217, 20, 9, 1, 197, 123, 76, 20, 9, 1, 197, 123, 53, - 20, 9, 1, 197, 123, 89, 20, 9, 1, 197, 123, 216, 217, 20, 9, 1, 199, 113, - 76, 20, 9, 1, 199, 113, 53, 20, 9, 1, 199, 113, 89, 20, 9, 1, 199, 113, - 216, 217, 20, 9, 1, 197, 125, 76, 20, 9, 1, 197, 125, 53, 20, 9, 1, 197, - 125, 89, 20, 9, 1, 197, 125, 216, 217, 20, 9, 1, 195, 147, 76, 20, 9, 1, - 195, 147, 53, 20, 9, 1, 195, 147, 89, 20, 9, 1, 195, 147, 216, 217, 20, - 9, 1, 210, 40, 76, 20, 9, 1, 210, 40, 53, 20, 9, 1, 210, 40, 89, 20, 9, - 1, 210, 40, 216, 217, 20, 9, 1, 235, 42, 76, 20, 9, 1, 235, 42, 53, 20, - 9, 1, 235, 42, 89, 20, 9, 1, 235, 42, 216, 217, 20, 9, 1, 212, 88, 76, - 20, 9, 1, 212, 88, 53, 20, 9, 1, 212, 88, 89, 20, 9, 1, 212, 88, 216, - 217, 20, 9, 1, 199, 150, 76, 20, 9, 1, 199, 150, 53, 20, 9, 1, 199, 150, - 89, 20, 9, 1, 199, 150, 216, 217, 20, 9, 1, 199, 148, 76, 20, 9, 1, 199, - 148, 53, 20, 9, 1, 199, 148, 89, 20, 9, 1, 199, 148, 216, 217, 20, 9, 1, - 237, 189, 76, 20, 9, 1, 237, 189, 53, 20, 9, 1, 238, 11, 76, 20, 9, 1, - 238, 11, 53, 20, 9, 1, 235, 79, 76, 20, 9, 1, 235, 79, 53, 20, 9, 1, 237, - 187, 76, 20, 9, 1, 237, 187, 53, 20, 9, 1, 223, 4, 76, 20, 9, 1, 223, 4, - 53, 20, 9, 1, 206, 102, 76, 20, 9, 1, 206, 102, 53, 20, 9, 1, 222, 5, 76, - 20, 9, 1, 222, 5, 53, 20, 9, 1, 222, 5, 89, 20, 9, 1, 222, 5, 216, 217, - 20, 9, 1, 231, 228, 76, 20, 9, 1, 231, 228, 53, 20, 9, 1, 231, 228, 89, - 20, 9, 1, 231, 228, 216, 217, 20, 9, 1, 230, 167, 76, 20, 9, 1, 230, 167, - 53, 20, 9, 1, 230, 167, 89, 20, 9, 1, 230, 167, 216, 217, 20, 9, 1, 213, - 248, 76, 20, 9, 1, 213, 248, 53, 20, 9, 1, 213, 248, 89, 20, 9, 1, 213, - 248, 216, 217, 20, 9, 1, 213, 25, 231, 58, 76, 20, 9, 1, 213, 25, 231, - 58, 53, 20, 9, 1, 206, 166, 76, 20, 9, 1, 206, 166, 53, 20, 9, 1, 206, - 166, 89, 20, 9, 1, 206, 166, 216, 217, 20, 9, 1, 229, 211, 4, 99, 93, 76, - 20, 9, 1, 229, 211, 4, 99, 93, 53, 20, 9, 1, 229, 211, 231, 1, 76, 20, 9, - 1, 229, 211, 231, 1, 53, 20, 9, 1, 229, 211, 231, 1, 89, 20, 9, 1, 229, - 211, 231, 1, 216, 217, 20, 9, 1, 229, 211, 236, 171, 76, 20, 9, 1, 229, - 211, 236, 171, 53, 20, 9, 1, 229, 211, 236, 171, 89, 20, 9, 1, 229, 211, - 236, 171, 216, 217, 20, 9, 1, 99, 249, 81, 76, 20, 9, 1, 99, 249, 81, 53, - 20, 9, 1, 99, 249, 81, 4, 230, 58, 93, 76, 20, 9, 1, 99, 249, 81, 4, 230, - 58, 93, 53, 20, 9, 16, 75, 58, 9, 16, 75, 60, 9, 16, 105, 185, 58, 9, 16, - 105, 185, 60, 9, 16, 115, 185, 58, 9, 16, 115, 185, 60, 9, 16, 115, 185, - 209, 58, 235, 119, 58, 9, 16, 115, 185, 209, 58, 235, 119, 60, 9, 16, - 232, 128, 185, 58, 9, 16, 232, 128, 185, 60, 9, 16, 55, 81, 249, 88, 60, - 9, 16, 105, 185, 195, 85, 58, 9, 16, 105, 185, 195, 85, 60, 9, 16, 206, - 188, 9, 16, 2, 199, 220, 58, 9, 16, 2, 199, 220, 60, 9, 16, 193, 151, 58, - 9, 1, 214, 71, 76, 20, 9, 1, 214, 71, 53, 20, 9, 1, 214, 71, 89, 20, 9, - 1, 214, 71, 216, 217, 20, 9, 1, 126, 76, 20, 9, 1, 126, 53, 20, 9, 1, - 211, 152, 76, 20, 9, 1, 211, 152, 53, 20, 9, 1, 191, 226, 76, 20, 9, 1, - 191, 226, 53, 20, 9, 1, 126, 4, 230, 58, 93, 76, 20, 9, 1, 195, 154, 76, - 20, 9, 1, 195, 154, 53, 20, 9, 1, 221, 132, 211, 152, 76, 20, 9, 1, 221, - 132, 211, 152, 53, 20, 9, 1, 221, 132, 191, 226, 76, 20, 9, 1, 221, 132, - 191, 226, 53, 20, 9, 1, 235, 15, 76, 20, 9, 1, 235, 15, 53, 20, 9, 1, - 235, 15, 89, 20, 9, 1, 235, 15, 216, 217, 20, 9, 1, 196, 137, 222, 26, - 221, 132, 131, 217, 100, 89, 20, 9, 1, 196, 137, 222, 26, 221, 132, 131, - 217, 100, 216, 217, 20, 9, 34, 99, 4, 230, 58, 93, 4, 131, 76, 20, 9, 34, - 99, 4, 230, 58, 93, 4, 131, 53, 20, 9, 34, 99, 4, 230, 58, 93, 4, 252, - 26, 76, 20, 9, 34, 99, 4, 230, 58, 93, 4, 252, 26, 53, 20, 9, 34, 99, 4, - 230, 58, 93, 4, 193, 134, 76, 20, 9, 34, 99, 4, 230, 58, 93, 4, 193, 134, - 53, 20, 9, 34, 99, 4, 230, 58, 93, 4, 126, 76, 20, 9, 34, 99, 4, 230, 58, - 93, 4, 126, 53, 20, 9, 34, 99, 4, 230, 58, 93, 4, 211, 152, 76, 20, 9, - 34, 99, 4, 230, 58, 93, 4, 211, 152, 53, 20, 9, 34, 99, 4, 230, 58, 93, - 4, 191, 226, 76, 20, 9, 34, 99, 4, 230, 58, 93, 4, 191, 226, 53, 20, 9, - 34, 99, 4, 230, 58, 93, 4, 235, 15, 76, 20, 9, 34, 99, 4, 230, 58, 93, 4, - 235, 15, 53, 20, 9, 34, 99, 4, 230, 58, 93, 4, 235, 15, 89, 20, 9, 34, - 196, 137, 221, 132, 99, 4, 230, 58, 93, 4, 131, 217, 100, 76, 20, 9, 34, - 196, 137, 221, 132, 99, 4, 230, 58, 93, 4, 131, 217, 100, 53, 20, 9, 34, - 196, 137, 221, 132, 99, 4, 230, 58, 93, 4, 131, 217, 100, 89, 20, 9, 1, - 233, 74, 99, 76, 20, 9, 1, 233, 74, 99, 53, 20, 9, 1, 233, 74, 99, 89, - 20, 9, 1, 233, 74, 99, 216, 217, 20, 9, 34, 99, 4, 230, 58, 93, 4, 223, - 7, 76, 20, 9, 34, 99, 4, 230, 58, 93, 4, 182, 76, 20, 9, 34, 99, 4, 230, - 58, 93, 4, 92, 76, 20, 9, 34, 99, 4, 230, 58, 93, 4, 131, 217, 100, 76, - 20, 9, 34, 99, 4, 230, 58, 93, 4, 99, 76, 20, 9, 34, 248, 246, 4, 223, 7, - 76, 20, 9, 34, 248, 246, 4, 182, 76, 20, 9, 34, 248, 246, 4, 221, 211, - 76, 20, 9, 34, 248, 246, 4, 92, 76, 20, 9, 34, 248, 246, 4, 131, 217, - 100, 76, 20, 9, 34, 248, 246, 4, 99, 76, 20, 9, 34, 199, 115, 4, 223, 7, - 76, 20, 9, 34, 199, 115, 4, 182, 76, 20, 9, 34, 199, 115, 4, 221, 211, - 76, 20, 9, 34, 199, 115, 4, 92, 76, 20, 9, 34, 199, 115, 4, 131, 217, - 100, 76, 20, 9, 34, 199, 115, 4, 99, 76, 20, 9, 34, 199, 30, 4, 223, 7, - 76, 20, 9, 34, 199, 30, 4, 92, 76, 20, 9, 34, 199, 30, 4, 131, 217, 100, - 76, 20, 9, 34, 199, 30, 4, 99, 76, 20, 9, 34, 223, 7, 4, 182, 76, 20, 9, - 34, 223, 7, 4, 92, 76, 20, 9, 34, 182, 4, 223, 7, 76, 20, 9, 34, 182, 4, - 92, 76, 20, 9, 34, 221, 211, 4, 223, 7, 76, 20, 9, 34, 221, 211, 4, 182, - 76, 20, 9, 34, 221, 211, 4, 92, 76, 20, 9, 34, 205, 47, 4, 223, 7, 76, - 20, 9, 34, 205, 47, 4, 182, 76, 20, 9, 34, 205, 47, 4, 221, 211, 76, 20, - 9, 34, 205, 47, 4, 92, 76, 20, 9, 34, 205, 193, 4, 182, 76, 20, 9, 34, - 205, 193, 4, 92, 76, 20, 9, 34, 238, 27, 4, 223, 7, 76, 20, 9, 34, 238, - 27, 4, 182, 76, 20, 9, 34, 238, 27, 4, 221, 211, 76, 20, 9, 34, 238, 27, - 4, 92, 76, 20, 9, 34, 199, 220, 4, 182, 76, 20, 9, 34, 199, 220, 4, 92, - 76, 20, 9, 34, 191, 117, 4, 92, 76, 20, 9, 34, 251, 231, 4, 223, 7, 76, - 20, 9, 34, 251, 231, 4, 92, 76, 20, 9, 34, 231, 87, 4, 223, 7, 76, 20, 9, - 34, 231, 87, 4, 92, 76, 20, 9, 34, 233, 47, 4, 223, 7, 76, 20, 9, 34, - 233, 47, 4, 182, 76, 20, 9, 34, 233, 47, 4, 221, 211, 76, 20, 9, 34, 233, - 47, 4, 92, 76, 20, 9, 34, 233, 47, 4, 131, 217, 100, 76, 20, 9, 34, 233, - 47, 4, 99, 76, 20, 9, 34, 208, 90, 4, 182, 76, 20, 9, 34, 208, 90, 4, 92, - 76, 20, 9, 34, 208, 90, 4, 131, 217, 100, 76, 20, 9, 34, 208, 90, 4, 99, - 76, 20, 9, 34, 222, 107, 4, 131, 76, 20, 9, 34, 222, 107, 4, 223, 7, 76, - 20, 9, 34, 222, 107, 4, 182, 76, 20, 9, 34, 222, 107, 4, 221, 211, 76, - 20, 9, 34, 222, 107, 4, 220, 36, 76, 20, 9, 34, 222, 107, 4, 92, 76, 20, - 9, 34, 222, 107, 4, 131, 217, 100, 76, 20, 9, 34, 222, 107, 4, 99, 76, - 20, 9, 34, 220, 36, 4, 223, 7, 76, 20, 9, 34, 220, 36, 4, 182, 76, 20, 9, - 34, 220, 36, 4, 221, 211, 76, 20, 9, 34, 220, 36, 4, 92, 76, 20, 9, 34, - 220, 36, 4, 131, 217, 100, 76, 20, 9, 34, 220, 36, 4, 99, 76, 20, 9, 34, - 92, 4, 223, 7, 76, 20, 9, 34, 92, 4, 182, 76, 20, 9, 34, 92, 4, 221, 211, - 76, 20, 9, 34, 92, 4, 92, 76, 20, 9, 34, 92, 4, 131, 217, 100, 76, 20, 9, - 34, 92, 4, 99, 76, 20, 9, 34, 213, 25, 4, 223, 7, 76, 20, 9, 34, 213, 25, - 4, 182, 76, 20, 9, 34, 213, 25, 4, 221, 211, 76, 20, 9, 34, 213, 25, 4, - 92, 76, 20, 9, 34, 213, 25, 4, 131, 217, 100, 76, 20, 9, 34, 213, 25, 4, - 99, 76, 20, 9, 34, 229, 211, 4, 223, 7, 76, 20, 9, 34, 229, 211, 4, 92, - 76, 20, 9, 34, 229, 211, 4, 131, 217, 100, 76, 20, 9, 34, 229, 211, 4, - 99, 76, 20, 9, 34, 99, 4, 223, 7, 76, 20, 9, 34, 99, 4, 182, 76, 20, 9, - 34, 99, 4, 221, 211, 76, 20, 9, 34, 99, 4, 92, 76, 20, 9, 34, 99, 4, 131, - 217, 100, 76, 20, 9, 34, 99, 4, 99, 76, 20, 9, 34, 199, 42, 4, 200, 182, - 131, 76, 20, 9, 34, 207, 72, 4, 200, 182, 131, 76, 20, 9, 34, 131, 217, - 100, 4, 200, 182, 131, 76, 20, 9, 34, 203, 156, 4, 237, 244, 76, 20, 9, - 34, 203, 156, 4, 222, 51, 76, 20, 9, 34, 203, 156, 4, 233, 71, 76, 20, 9, - 34, 203, 156, 4, 237, 246, 76, 20, 9, 34, 203, 156, 4, 222, 53, 76, 20, - 9, 34, 203, 156, 4, 200, 182, 131, 76, 20, 9, 34, 99, 4, 230, 58, 93, 4, - 207, 72, 53, 20, 9, 34, 99, 4, 230, 58, 93, 4, 191, 114, 53, 20, 9, 34, - 99, 4, 230, 58, 93, 4, 92, 53, 20, 9, 34, 99, 4, 230, 58, 93, 4, 213, 25, - 53, 20, 9, 34, 99, 4, 230, 58, 93, 4, 131, 217, 100, 53, 20, 9, 34, 99, - 4, 230, 58, 93, 4, 99, 53, 20, 9, 34, 248, 246, 4, 207, 72, 53, 20, 9, - 34, 248, 246, 4, 191, 114, 53, 20, 9, 34, 248, 246, 4, 92, 53, 20, 9, 34, - 248, 246, 4, 213, 25, 53, 20, 9, 34, 248, 246, 4, 131, 217, 100, 53, 20, - 9, 34, 248, 246, 4, 99, 53, 20, 9, 34, 199, 115, 4, 207, 72, 53, 20, 9, - 34, 199, 115, 4, 191, 114, 53, 20, 9, 34, 199, 115, 4, 92, 53, 20, 9, 34, - 199, 115, 4, 213, 25, 53, 20, 9, 34, 199, 115, 4, 131, 217, 100, 53, 20, - 9, 34, 199, 115, 4, 99, 53, 20, 9, 34, 199, 30, 4, 207, 72, 53, 20, 9, - 34, 199, 30, 4, 191, 114, 53, 20, 9, 34, 199, 30, 4, 92, 53, 20, 9, 34, - 199, 30, 4, 213, 25, 53, 20, 9, 34, 199, 30, 4, 131, 217, 100, 53, 20, 9, - 34, 199, 30, 4, 99, 53, 20, 9, 34, 233, 47, 4, 131, 217, 100, 53, 20, 9, - 34, 233, 47, 4, 99, 53, 20, 9, 34, 208, 90, 4, 131, 217, 100, 53, 20, 9, - 34, 208, 90, 4, 99, 53, 20, 9, 34, 222, 107, 4, 131, 53, 20, 9, 34, 222, - 107, 4, 220, 36, 53, 20, 9, 34, 222, 107, 4, 92, 53, 20, 9, 34, 222, 107, - 4, 131, 217, 100, 53, 20, 9, 34, 222, 107, 4, 99, 53, 20, 9, 34, 220, 36, - 4, 92, 53, 20, 9, 34, 220, 36, 4, 131, 217, 100, 53, 20, 9, 34, 220, 36, - 4, 99, 53, 20, 9, 34, 92, 4, 131, 53, 20, 9, 34, 92, 4, 92, 53, 20, 9, - 34, 213, 25, 4, 207, 72, 53, 20, 9, 34, 213, 25, 4, 191, 114, 53, 20, 9, - 34, 213, 25, 4, 92, 53, 20, 9, 34, 213, 25, 4, 213, 25, 53, 20, 9, 34, - 213, 25, 4, 131, 217, 100, 53, 20, 9, 34, 213, 25, 4, 99, 53, 20, 9, 34, - 131, 217, 100, 4, 200, 182, 131, 53, 20, 9, 34, 99, 4, 207, 72, 53, 20, - 9, 34, 99, 4, 191, 114, 53, 20, 9, 34, 99, 4, 92, 53, 20, 9, 34, 99, 4, - 213, 25, 53, 20, 9, 34, 99, 4, 131, 217, 100, 53, 20, 9, 34, 99, 4, 99, - 53, 20, 9, 34, 99, 4, 230, 58, 93, 4, 223, 7, 89, 20, 9, 34, 99, 4, 230, - 58, 93, 4, 182, 89, 20, 9, 34, 99, 4, 230, 58, 93, 4, 221, 211, 89, 20, - 9, 34, 99, 4, 230, 58, 93, 4, 92, 89, 20, 9, 34, 99, 4, 230, 58, 93, 4, - 229, 211, 89, 20, 9, 34, 248, 246, 4, 223, 7, 89, 20, 9, 34, 248, 246, 4, - 182, 89, 20, 9, 34, 248, 246, 4, 221, 211, 89, 20, 9, 34, 248, 246, 4, - 92, 89, 20, 9, 34, 248, 246, 4, 229, 211, 89, 20, 9, 34, 199, 115, 4, - 223, 7, 89, 20, 9, 34, 199, 115, 4, 182, 89, 20, 9, 34, 199, 115, 4, 221, - 211, 89, 20, 9, 34, 199, 115, 4, 92, 89, 20, 9, 34, 199, 115, 4, 229, - 211, 89, 20, 9, 34, 199, 30, 4, 92, 89, 20, 9, 34, 223, 7, 4, 182, 89, - 20, 9, 34, 223, 7, 4, 92, 89, 20, 9, 34, 182, 4, 223, 7, 89, 20, 9, 34, - 182, 4, 92, 89, 20, 9, 34, 221, 211, 4, 223, 7, 89, 20, 9, 34, 221, 211, - 4, 92, 89, 20, 9, 34, 205, 47, 4, 223, 7, 89, 20, 9, 34, 205, 47, 4, 182, - 89, 20, 9, 34, 205, 47, 4, 221, 211, 89, 20, 9, 34, 205, 47, 4, 92, 89, - 20, 9, 34, 205, 193, 4, 182, 89, 20, 9, 34, 205, 193, 4, 221, 211, 89, - 20, 9, 34, 205, 193, 4, 92, 89, 20, 9, 34, 238, 27, 4, 223, 7, 89, 20, 9, - 34, 238, 27, 4, 182, 89, 20, 9, 34, 238, 27, 4, 221, 211, 89, 20, 9, 34, - 238, 27, 4, 92, 89, 20, 9, 34, 199, 220, 4, 182, 89, 20, 9, 34, 191, 117, - 4, 92, 89, 20, 9, 34, 251, 231, 4, 223, 7, 89, 20, 9, 34, 251, 231, 4, - 92, 89, 20, 9, 34, 231, 87, 4, 223, 7, 89, 20, 9, 34, 231, 87, 4, 92, 89, - 20, 9, 34, 233, 47, 4, 223, 7, 89, 20, 9, 34, 233, 47, 4, 182, 89, 20, 9, - 34, 233, 47, 4, 221, 211, 89, 20, 9, 34, 233, 47, 4, 92, 89, 20, 9, 34, - 208, 90, 4, 182, 89, 20, 9, 34, 208, 90, 4, 92, 89, 20, 9, 34, 222, 107, - 4, 223, 7, 89, 20, 9, 34, 222, 107, 4, 182, 89, 20, 9, 34, 222, 107, 4, - 221, 211, 89, 20, 9, 34, 222, 107, 4, 220, 36, 89, 20, 9, 34, 222, 107, - 4, 92, 89, 20, 9, 34, 220, 36, 4, 223, 7, 89, 20, 9, 34, 220, 36, 4, 182, - 89, 20, 9, 34, 220, 36, 4, 221, 211, 89, 20, 9, 34, 220, 36, 4, 92, 89, - 20, 9, 34, 220, 36, 4, 229, 211, 89, 20, 9, 34, 92, 4, 223, 7, 89, 20, 9, - 34, 92, 4, 182, 89, 20, 9, 34, 92, 4, 221, 211, 89, 20, 9, 34, 92, 4, 92, - 89, 20, 9, 34, 213, 25, 4, 223, 7, 89, 20, 9, 34, 213, 25, 4, 182, 89, - 20, 9, 34, 213, 25, 4, 221, 211, 89, 20, 9, 34, 213, 25, 4, 92, 89, 20, - 9, 34, 213, 25, 4, 229, 211, 89, 20, 9, 34, 229, 211, 4, 223, 7, 89, 20, - 9, 34, 229, 211, 4, 92, 89, 20, 9, 34, 229, 211, 4, 200, 182, 131, 89, - 20, 9, 34, 99, 4, 223, 7, 89, 20, 9, 34, 99, 4, 182, 89, 20, 9, 34, 99, - 4, 221, 211, 89, 20, 9, 34, 99, 4, 92, 89, 20, 9, 34, 99, 4, 229, 211, - 89, 20, 9, 34, 99, 4, 230, 58, 93, 4, 92, 216, 217, 20, 9, 34, 99, 4, - 230, 58, 93, 4, 229, 211, 216, 217, 20, 9, 34, 248, 246, 4, 92, 216, 217, - 20, 9, 34, 248, 246, 4, 229, 211, 216, 217, 20, 9, 34, 199, 115, 4, 92, - 216, 217, 20, 9, 34, 199, 115, 4, 229, 211, 216, 217, 20, 9, 34, 199, 30, - 4, 92, 216, 217, 20, 9, 34, 199, 30, 4, 229, 211, 216, 217, 20, 9, 34, - 205, 47, 4, 92, 216, 217, 20, 9, 34, 205, 47, 4, 229, 211, 216, 217, 20, - 9, 34, 203, 110, 4, 92, 216, 217, 20, 9, 34, 203, 110, 4, 229, 211, 216, - 217, 20, 9, 34, 222, 107, 4, 220, 36, 216, 217, 20, 9, 34, 222, 107, 4, - 92, 216, 217, 20, 9, 34, 220, 36, 4, 92, 216, 217, 20, 9, 34, 213, 25, 4, - 92, 216, 217, 20, 9, 34, 213, 25, 4, 229, 211, 216, 217, 20, 9, 34, 99, - 4, 92, 216, 217, 20, 9, 34, 99, 4, 229, 211, 216, 217, 20, 9, 34, 203, - 156, 4, 233, 71, 216, 217, 20, 9, 34, 203, 156, 4, 237, 246, 216, 217, - 20, 9, 34, 203, 156, 4, 222, 53, 216, 217, 20, 9, 34, 199, 220, 4, 131, - 217, 100, 76, 20, 9, 34, 199, 220, 4, 99, 76, 20, 9, 34, 251, 231, 4, - 131, 217, 100, 76, 20, 9, 34, 251, 231, 4, 99, 76, 20, 9, 34, 231, 87, 4, - 131, 217, 100, 76, 20, 9, 34, 231, 87, 4, 99, 76, 20, 9, 34, 205, 47, 4, - 131, 217, 100, 76, 20, 9, 34, 205, 47, 4, 99, 76, 20, 9, 34, 203, 110, 4, - 131, 217, 100, 76, 20, 9, 34, 203, 110, 4, 99, 76, 20, 9, 34, 182, 4, - 131, 217, 100, 76, 20, 9, 34, 182, 4, 99, 76, 20, 9, 34, 223, 7, 4, 131, - 217, 100, 76, 20, 9, 34, 223, 7, 4, 99, 76, 20, 9, 34, 221, 211, 4, 131, - 217, 100, 76, 20, 9, 34, 221, 211, 4, 99, 76, 20, 9, 34, 205, 193, 4, - 131, 217, 100, 76, 20, 9, 34, 205, 193, 4, 99, 76, 20, 9, 34, 238, 27, 4, - 131, 217, 100, 76, 20, 9, 34, 238, 27, 4, 99, 76, 20, 9, 34, 203, 110, 4, - 223, 7, 76, 20, 9, 34, 203, 110, 4, 182, 76, 20, 9, 34, 203, 110, 4, 221, - 211, 76, 20, 9, 34, 203, 110, 4, 92, 76, 20, 9, 34, 203, 110, 4, 207, 72, - 76, 20, 9, 34, 205, 47, 4, 207, 72, 76, 20, 9, 34, 205, 193, 4, 207, 72, - 76, 20, 9, 34, 238, 27, 4, 207, 72, 76, 20, 9, 34, 199, 220, 4, 131, 217, - 100, 53, 20, 9, 34, 199, 220, 4, 99, 53, 20, 9, 34, 251, 231, 4, 131, - 217, 100, 53, 20, 9, 34, 251, 231, 4, 99, 53, 20, 9, 34, 231, 87, 4, 131, - 217, 100, 53, 20, 9, 34, 231, 87, 4, 99, 53, 20, 9, 34, 205, 47, 4, 131, - 217, 100, 53, 20, 9, 34, 205, 47, 4, 99, 53, 20, 9, 34, 203, 110, 4, 131, - 217, 100, 53, 20, 9, 34, 203, 110, 4, 99, 53, 20, 9, 34, 182, 4, 131, - 217, 100, 53, 20, 9, 34, 182, 4, 99, 53, 20, 9, 34, 223, 7, 4, 131, 217, - 100, 53, 20, 9, 34, 223, 7, 4, 99, 53, 20, 9, 34, 221, 211, 4, 131, 217, - 100, 53, 20, 9, 34, 221, 211, 4, 99, 53, 20, 9, 34, 205, 193, 4, 131, - 217, 100, 53, 20, 9, 34, 205, 193, 4, 99, 53, 20, 9, 34, 238, 27, 4, 131, - 217, 100, 53, 20, 9, 34, 238, 27, 4, 99, 53, 20, 9, 34, 203, 110, 4, 223, - 7, 53, 20, 9, 34, 203, 110, 4, 182, 53, 20, 9, 34, 203, 110, 4, 221, 211, - 53, 20, 9, 34, 203, 110, 4, 92, 53, 20, 9, 34, 203, 110, 4, 207, 72, 53, - 20, 9, 34, 205, 47, 4, 207, 72, 53, 20, 9, 34, 205, 193, 4, 207, 72, 53, - 20, 9, 34, 238, 27, 4, 207, 72, 53, 20, 9, 34, 203, 110, 4, 223, 7, 89, - 20, 9, 34, 203, 110, 4, 182, 89, 20, 9, 34, 203, 110, 4, 221, 211, 89, - 20, 9, 34, 203, 110, 4, 92, 89, 20, 9, 34, 205, 47, 4, 229, 211, 89, 20, - 9, 34, 203, 110, 4, 229, 211, 89, 20, 9, 34, 199, 220, 4, 92, 89, 20, 9, - 34, 205, 47, 4, 223, 7, 216, 217, 20, 9, 34, 205, 47, 4, 182, 216, 217, - 20, 9, 34, 205, 47, 4, 221, 211, 216, 217, 20, 9, 34, 203, 110, 4, 223, - 7, 216, 217, 20, 9, 34, 203, 110, 4, 182, 216, 217, 20, 9, 34, 203, 110, - 4, 221, 211, 216, 217, 20, 9, 34, 199, 220, 4, 92, 216, 217, 20, 9, 34, - 191, 117, 4, 92, 216, 217, 20, 9, 34, 131, 4, 233, 69, 53, 20, 9, 34, - 131, 4, 233, 69, 76, 20, 211, 40, 45, 210, 113, 211, 40, 50, 210, 113, 9, - 34, 207, 159, 251, 173, 9, 34, 207, 167, 251, 172, 251, 107, 9, 34, 207, - 167, 251, 172, 251, 106, 9, 34, 207, 167, 251, 172, 251, 104, 9, 34, 207, - 167, 251, 172, 251, 103, 9, 34, 207, 167, 251, 172, 251, 102, 9, 34, 205, - 162, 251, 197, 193, 184, 9, 34, 251, 197, 250, 217, 9, 34, 251, 196, 250, - 217, 9, 34, 251, 195, 250, 217, 9, 34, 251, 197, 250, 216, 193, 154, 9, - 34, 208, 17, 202, 140, 9, 34, 205, 160, 251, 197, 193, 180, 193, 183, 9, - 34, 251, 200, 250, 217, 9, 34, 199, 235, 193, 182, 9, 34, 207, 158, 251, - 173, 9, 34, 199, 115, 4, 223, 7, 4, 92, 89, 20, 9, 34, 199, 115, 4, 182, - 4, 223, 7, 53, 20, 9, 34, 199, 115, 4, 182, 4, 223, 7, 89, 20, 9, 34, - 199, 115, 4, 182, 4, 92, 89, 20, 9, 34, 199, 115, 4, 221, 211, 4, 92, 89, - 20, 9, 34, 199, 115, 4, 92, 4, 223, 7, 89, 20, 9, 34, 199, 115, 4, 92, 4, - 182, 89, 20, 9, 34, 199, 115, 4, 92, 4, 221, 211, 89, 20, 9, 34, 223, 7, - 4, 92, 4, 182, 53, 20, 9, 34, 223, 7, 4, 92, 4, 182, 89, 20, 9, 34, 182, - 4, 92, 4, 99, 53, 20, 9, 34, 182, 4, 92, 4, 131, 217, 100, 53, 20, 9, 34, - 205, 47, 4, 182, 4, 223, 7, 89, 20, 9, 34, 205, 47, 4, 223, 7, 4, 182, - 89, 20, 9, 34, 205, 47, 4, 223, 7, 4, 131, 217, 100, 53, 20, 9, 34, 205, - 47, 4, 92, 4, 182, 53, 20, 9, 34, 205, 47, 4, 92, 4, 182, 89, 20, 9, 34, - 205, 47, 4, 92, 4, 223, 7, 89, 20, 9, 34, 205, 47, 4, 92, 4, 92, 53, 20, - 9, 34, 205, 47, 4, 92, 4, 92, 89, 20, 9, 34, 205, 193, 4, 182, 4, 182, - 53, 20, 9, 34, 205, 193, 4, 182, 4, 182, 89, 20, 9, 34, 205, 193, 4, 92, - 4, 92, 53, 20, 9, 34, 203, 110, 4, 182, 4, 92, 53, 20, 9, 34, 203, 110, - 4, 182, 4, 92, 89, 20, 9, 34, 203, 110, 4, 223, 7, 4, 99, 53, 20, 9, 34, - 203, 110, 4, 92, 4, 221, 211, 53, 20, 9, 34, 203, 110, 4, 92, 4, 221, - 211, 89, 20, 9, 34, 203, 110, 4, 92, 4, 92, 53, 20, 9, 34, 203, 110, 4, - 92, 4, 92, 89, 20, 9, 34, 238, 27, 4, 182, 4, 131, 217, 100, 53, 20, 9, - 34, 238, 27, 4, 221, 211, 4, 92, 53, 20, 9, 34, 238, 27, 4, 221, 211, 4, - 92, 89, 20, 9, 34, 199, 220, 4, 92, 4, 182, 53, 20, 9, 34, 199, 220, 4, - 92, 4, 182, 89, 20, 9, 34, 199, 220, 4, 92, 4, 92, 89, 20, 9, 34, 199, - 220, 4, 92, 4, 99, 53, 20, 9, 34, 251, 231, 4, 223, 7, 4, 92, 53, 20, 9, - 34, 251, 231, 4, 92, 4, 92, 53, 20, 9, 34, 251, 231, 4, 92, 4, 92, 89, - 20, 9, 34, 251, 231, 4, 92, 4, 131, 217, 100, 53, 20, 9, 34, 231, 87, 4, - 92, 4, 92, 53, 20, 9, 34, 231, 87, 4, 92, 4, 99, 53, 20, 9, 34, 231, 87, - 4, 92, 4, 131, 217, 100, 53, 20, 9, 34, 233, 47, 4, 221, 211, 4, 92, 53, - 20, 9, 34, 233, 47, 4, 221, 211, 4, 92, 89, 20, 9, 34, 208, 90, 4, 92, 4, - 182, 53, 20, 9, 34, 208, 90, 4, 92, 4, 92, 53, 20, 9, 34, 220, 36, 4, - 182, 4, 92, 53, 20, 9, 34, 220, 36, 4, 182, 4, 99, 53, 20, 9, 34, 220, - 36, 4, 182, 4, 131, 217, 100, 53, 20, 9, 34, 220, 36, 4, 223, 7, 4, 223, - 7, 89, 20, 9, 34, 220, 36, 4, 223, 7, 4, 223, 7, 53, 20, 9, 34, 220, 36, - 4, 221, 211, 4, 92, 53, 20, 9, 34, 220, 36, 4, 221, 211, 4, 92, 89, 20, - 9, 34, 220, 36, 4, 92, 4, 182, 53, 20, 9, 34, 220, 36, 4, 92, 4, 182, 89, - 20, 9, 34, 92, 4, 182, 4, 223, 7, 89, 20, 9, 34, 92, 4, 182, 4, 92, 89, - 20, 9, 34, 92, 4, 182, 4, 99, 53, 20, 9, 34, 92, 4, 223, 7, 4, 182, 89, - 20, 9, 34, 92, 4, 223, 7, 4, 92, 89, 20, 9, 34, 92, 4, 221, 211, 4, 223, - 7, 89, 20, 9, 34, 92, 4, 221, 211, 4, 92, 89, 20, 9, 34, 92, 4, 223, 7, - 4, 221, 211, 89, 20, 9, 34, 229, 211, 4, 92, 4, 223, 7, 89, 20, 9, 34, - 229, 211, 4, 92, 4, 92, 89, 20, 9, 34, 213, 25, 4, 182, 4, 92, 89, 20, 9, - 34, 213, 25, 4, 182, 4, 131, 217, 100, 53, 20, 9, 34, 213, 25, 4, 223, 7, - 4, 92, 53, 20, 9, 34, 213, 25, 4, 223, 7, 4, 92, 89, 20, 9, 34, 213, 25, - 4, 223, 7, 4, 131, 217, 100, 53, 20, 9, 34, 213, 25, 4, 92, 4, 99, 53, - 20, 9, 34, 213, 25, 4, 92, 4, 131, 217, 100, 53, 20, 9, 34, 99, 4, 92, 4, - 92, 53, 20, 9, 34, 99, 4, 92, 4, 92, 89, 20, 9, 34, 248, 246, 4, 221, - 211, 4, 99, 53, 20, 9, 34, 199, 115, 4, 223, 7, 4, 99, 53, 20, 9, 34, - 199, 115, 4, 223, 7, 4, 131, 217, 100, 53, 20, 9, 34, 199, 115, 4, 221, - 211, 4, 99, 53, 20, 9, 34, 199, 115, 4, 221, 211, 4, 131, 217, 100, 53, - 20, 9, 34, 199, 115, 4, 92, 4, 99, 53, 20, 9, 34, 199, 115, 4, 92, 4, - 131, 217, 100, 53, 20, 9, 34, 223, 7, 4, 92, 4, 99, 53, 20, 9, 34, 223, - 7, 4, 182, 4, 131, 217, 100, 53, 20, 9, 34, 223, 7, 4, 92, 4, 131, 217, - 100, 53, 20, 9, 34, 205, 47, 4, 221, 211, 4, 131, 217, 100, 53, 20, 9, - 34, 205, 193, 4, 182, 4, 99, 53, 20, 9, 34, 203, 110, 4, 182, 4, 99, 53, - 20, 9, 34, 238, 27, 4, 182, 4, 99, 53, 20, 9, 34, 220, 36, 4, 223, 7, 4, - 99, 53, 20, 9, 34, 220, 36, 4, 92, 4, 99, 53, 20, 9, 34, 99, 4, 182, 4, - 99, 53, 20, 9, 34, 99, 4, 223, 7, 4, 99, 53, 20, 9, 34, 99, 4, 92, 4, 99, - 53, 20, 9, 34, 92, 4, 92, 4, 99, 53, 20, 9, 34, 208, 90, 4, 92, 4, 99, - 53, 20, 9, 34, 213, 25, 4, 182, 4, 99, 53, 20, 9, 34, 208, 90, 4, 92, 4, - 182, 89, 20, 9, 34, 220, 36, 4, 182, 4, 92, 89, 20, 9, 34, 251, 231, 4, - 92, 4, 99, 53, 20, 9, 34, 222, 107, 4, 92, 4, 99, 53, 20, 9, 34, 213, 25, - 4, 223, 7, 4, 182, 89, 20, 9, 34, 92, 4, 221, 211, 4, 99, 53, 20, 9, 34, - 220, 36, 4, 223, 7, 4, 92, 89, 20, 9, 34, 222, 107, 4, 92, 4, 92, 53, 20, - 9, 34, 220, 36, 4, 223, 7, 4, 92, 53, 20, 9, 34, 213, 25, 4, 223, 7, 4, - 182, 53, 20, 9, 34, 223, 7, 4, 182, 4, 99, 53, 20, 9, 34, 182, 4, 223, 7, - 4, 99, 53, 20, 9, 34, 92, 4, 223, 7, 4, 99, 53, 20, 9, 34, 233, 47, 4, - 92, 4, 99, 53, 20, 9, 34, 248, 246, 4, 182, 4, 99, 53, 20, 9, 34, 222, - 107, 4, 92, 4, 92, 89, 20, 9, 34, 251, 231, 4, 223, 7, 4, 92, 89, 20, 9, - 34, 205, 193, 4, 92, 4, 92, 89, 20, 9, 34, 205, 47, 4, 221, 211, 4, 99, - 53, 20, 9, 34, 213, 25, 4, 223, 7, 4, 99, 53, 20, 9, 34, 205, 166, 251, - 194, 9, 34, 205, 163, 196, 40, 250, 220, 221, 33, 201, 64, 3, 76, 20, 9, - 34, 208, 86, 196, 40, 250, 220, 221, 33, 201, 64, 3, 76, 20, 9, 34, 251, - 171, 76, 20, 9, 34, 251, 213, 76, 20, 9, 34, 215, 235, 76, 20, 9, 34, - 205, 164, 76, 20, 9, 34, 207, 132, 76, 20, 9, 34, 251, 199, 76, 20, 9, - 34, 193, 153, 76, 20, 9, 34, 205, 163, 76, 20, 9, 34, 205, 161, 251, 199, - 193, 152, 9, 34, 223, 22, 206, 249, 56, 9, 34, 248, 151, 251, 31, 251, - 32, 9, 34, 200, 242, 193, 191, 199, 244, 9, 34, 250, 121, 193, 191, 223, - 23, 67, 205, 33, 67, 204, 178, 67, 204, 110, 67, 204, 99, 67, 204, 88, - 67, 204, 77, 67, 204, 66, 67, 204, 55, 67, 204, 44, 67, 205, 32, 67, 205, - 21, 67, 205, 10, 67, 204, 255, 67, 204, 244, 67, 204, 233, 67, 204, 222, - 208, 221, 232, 146, 40, 81, 242, 74, 208, 221, 232, 146, 40, 81, 154, - 242, 74, 208, 221, 232, 146, 40, 81, 154, 232, 80, 201, 63, 208, 221, - 232, 146, 40, 81, 242, 83, 208, 221, 232, 146, 40, 81, 204, 25, 208, 221, - 232, 146, 40, 81, 233, 216, 77, 208, 221, 232, 146, 40, 81, 208, 13, 77, - 208, 221, 232, 146, 40, 81, 45, 63, 219, 187, 248, 53, 208, 221, 232, - 146, 40, 81, 50, 63, 219, 187, 248, 49, 208, 221, 232, 146, 40, 81, 228, - 241, 234, 120, 33, 34, 45, 230, 70, 33, 34, 50, 230, 70, 33, 55, 198, - 153, 45, 230, 70, 33, 55, 198, 153, 50, 230, 70, 33, 217, 147, 45, 230, - 70, 33, 217, 147, 50, 230, 70, 33, 239, 44, 217, 146, 33, 34, 45, 132, - 60, 33, 34, 50, 132, 60, 33, 198, 153, 45, 132, 60, 33, 198, 153, 50, - 132, 60, 33, 217, 147, 45, 132, 60, 33, 217, 147, 50, 132, 60, 33, 239, - 44, 217, 147, 60, 33, 38, 198, 123, 45, 230, 70, 33, 38, 198, 123, 50, - 230, 70, 208, 221, 232, 146, 40, 81, 105, 75, 219, 236, 208, 221, 232, - 146, 40, 81, 234, 115, 237, 215, 208, 221, 232, 146, 40, 81, 234, 104, - 237, 215, 208, 221, 232, 146, 40, 81, 130, 219, 112, 208, 221, 232, 146, - 40, 81, 193, 135, 130, 219, 112, 208, 221, 232, 146, 40, 81, 45, 210, - 113, 208, 221, 232, 146, 40, 81, 50, 210, 113, 208, 221, 232, 146, 40, - 81, 45, 238, 171, 248, 53, 208, 221, 232, 146, 40, 81, 50, 238, 171, 248, - 53, 208, 221, 232, 146, 40, 81, 45, 198, 42, 203, 103, 248, 53, 208, 221, - 232, 146, 40, 81, 50, 198, 42, 203, 103, 248, 53, 208, 221, 232, 146, 40, - 81, 45, 62, 219, 187, 248, 53, 208, 221, 232, 146, 40, 81, 50, 62, 219, - 187, 248, 53, 208, 221, 232, 146, 40, 81, 45, 55, 251, 116, 248, 53, 208, - 221, 232, 146, 40, 81, 50, 55, 251, 116, 248, 53, 208, 221, 232, 146, 40, - 81, 45, 251, 116, 248, 53, 208, 221, 232, 146, 40, 81, 50, 251, 116, 248, - 53, 208, 221, 232, 146, 40, 81, 45, 239, 2, 248, 53, 208, 221, 232, 146, - 40, 81, 50, 239, 2, 248, 53, 208, 221, 232, 146, 40, 81, 45, 63, 239, 2, - 248, 53, 208, 221, 232, 146, 40, 81, 50, 63, 239, 2, 248, 53, 204, 0, - 236, 140, 63, 204, 0, 236, 140, 208, 221, 232, 146, 40, 81, 45, 51, 248, - 53, 208, 221, 232, 146, 40, 81, 50, 51, 248, 53, 237, 214, 210, 254, 247, - 18, 210, 254, 193, 135, 210, 254, 55, 193, 135, 210, 254, 237, 214, 130, - 219, 112, 247, 18, 130, 219, 112, 193, 135, 130, 219, 112, 2, 242, 74, 2, - 154, 242, 74, 2, 232, 80, 201, 63, 2, 204, 25, 2, 242, 83, 2, 208, 13, - 77, 2, 233, 216, 77, 2, 234, 115, 237, 215, 2, 45, 210, 113, 2, 50, 210, - 113, 2, 45, 238, 171, 248, 53, 2, 50, 238, 171, 248, 53, 2, 45, 198, 42, - 203, 103, 248, 53, 2, 50, 198, 42, 203, 103, 248, 53, 2, 31, 56, 2, 251, - 137, 2, 250, 193, 2, 108, 56, 2, 228, 87, 2, 219, 180, 56, 2, 230, 204, - 56, 2, 234, 43, 56, 2, 207, 19, 202, 23, 2, 236, 155, 56, 2, 210, 13, 56, - 2, 242, 72, 250, 182, 9, 233, 69, 76, 20, 9, 199, 169, 4, 233, 69, 58, 9, - 237, 244, 76, 20, 9, 199, 216, 232, 117, 9, 222, 51, 76, 20, 9, 233, 71, - 76, 20, 9, 233, 71, 216, 217, 20, 9, 237, 246, 76, 20, 9, 237, 246, 216, - 217, 20, 9, 222, 53, 76, 20, 9, 222, 53, 216, 217, 20, 9, 203, 156, 76, - 20, 9, 203, 156, 216, 217, 20, 9, 200, 207, 76, 20, 9, 200, 207, 216, - 217, 20, 9, 1, 230, 58, 76, 20, 9, 1, 131, 4, 217, 142, 93, 76, 20, 9, 1, - 131, 4, 217, 142, 93, 53, 20, 9, 1, 131, 4, 230, 58, 93, 76, 20, 9, 1, - 131, 4, 230, 58, 93, 53, 20, 9, 1, 193, 134, 4, 230, 58, 93, 76, 20, 9, - 1, 193, 134, 4, 230, 58, 93, 53, 20, 9, 1, 131, 4, 230, 58, 248, 233, 76, - 20, 9, 1, 131, 4, 230, 58, 248, 233, 53, 20, 9, 1, 99, 4, 230, 58, 93, - 76, 20, 9, 1, 99, 4, 230, 58, 93, 53, 20, 9, 1, 99, 4, 230, 58, 93, 89, - 20, 9, 1, 99, 4, 230, 58, 93, 216, 217, 20, 9, 1, 131, 76, 20, 9, 1, 131, - 53, 20, 9, 1, 248, 246, 76, 20, 9, 1, 248, 246, 53, 20, 9, 1, 248, 246, - 89, 20, 9, 1, 248, 246, 216, 217, 20, 9, 1, 199, 115, 217, 63, 76, 20, 9, - 1, 199, 115, 217, 63, 53, 20, 9, 1, 199, 115, 76, 20, 9, 1, 199, 115, 53, - 20, 9, 1, 199, 115, 89, 20, 9, 1, 199, 115, 216, 217, 20, 9, 1, 199, 30, - 76, 20, 9, 1, 199, 30, 53, 20, 9, 1, 199, 30, 89, 20, 9, 1, 199, 30, 216, - 217, 20, 9, 1, 223, 7, 76, 20, 9, 1, 223, 7, 53, 20, 9, 1, 223, 7, 89, - 20, 9, 1, 223, 7, 216, 217, 20, 9, 1, 182, 76, 20, 9, 1, 182, 53, 20, 9, - 1, 182, 89, 20, 9, 1, 182, 216, 217, 20, 9, 1, 221, 211, 76, 20, 9, 1, - 221, 211, 53, 20, 9, 1, 221, 211, 89, 20, 9, 1, 221, 211, 216, 217, 20, - 9, 1, 238, 4, 76, 20, 9, 1, 238, 4, 53, 20, 9, 1, 199, 42, 76, 20, 9, 1, - 199, 42, 53, 20, 9, 1, 207, 72, 76, 20, 9, 1, 207, 72, 53, 20, 9, 1, 191, - 114, 76, 20, 9, 1, 191, 114, 53, 20, 9, 1, 205, 47, 76, 20, 9, 1, 205, - 47, 53, 20, 9, 1, 205, 47, 89, 20, 9, 1, 205, 47, 216, 217, 20, 9, 1, - 203, 110, 76, 20, 9, 1, 203, 110, 53, 20, 9, 1, 203, 110, 89, 20, 9, 1, - 203, 110, 216, 217, 20, 9, 1, 205, 193, 76, 20, 9, 1, 205, 193, 53, 20, - 9, 1, 205, 193, 89, 20, 9, 1, 205, 193, 216, 217, 20, 9, 1, 238, 27, 76, - 20, 9, 1, 238, 27, 53, 20, 9, 1, 238, 27, 89, 20, 9, 1, 238, 27, 216, - 217, 20, 9, 1, 199, 220, 76, 20, 9, 1, 199, 220, 53, 20, 9, 1, 199, 220, - 89, 20, 9, 1, 199, 220, 216, 217, 20, 9, 1, 191, 117, 76, 20, 9, 1, 191, - 117, 53, 20, 9, 1, 191, 117, 89, 20, 9, 1, 191, 117, 216, 217, 20, 9, 1, - 251, 231, 76, 20, 9, 1, 251, 231, 53, 20, 9, 1, 251, 231, 89, 20, 9, 1, - 251, 231, 216, 217, 20, 9, 1, 231, 87, 76, 20, 9, 1, 231, 87, 53, 20, 9, - 1, 231, 87, 89, 20, 9, 1, 231, 87, 216, 217, 20, 9, 1, 233, 47, 76, 20, - 9, 1, 233, 47, 53, 20, 9, 1, 233, 47, 89, 20, 9, 1, 233, 47, 216, 217, - 20, 9, 1, 208, 90, 76, 20, 9, 1, 208, 90, 53, 20, 9, 1, 208, 90, 89, 20, - 9, 1, 208, 90, 216, 217, 20, 9, 1, 222, 107, 76, 20, 9, 1, 222, 107, 53, - 20, 9, 1, 222, 107, 89, 20, 9, 1, 222, 107, 216, 217, 20, 9, 1, 220, 36, - 76, 20, 9, 1, 220, 36, 53, 20, 9, 1, 220, 36, 89, 20, 9, 1, 220, 36, 216, - 217, 20, 9, 1, 92, 76, 20, 9, 1, 92, 53, 20, 9, 1, 92, 89, 20, 9, 1, 92, - 216, 217, 20, 9, 1, 213, 25, 76, 20, 9, 1, 213, 25, 53, 20, 9, 1, 213, - 25, 89, 20, 9, 1, 213, 25, 216, 217, 20, 9, 1, 229, 211, 76, 20, 9, 1, - 229, 211, 53, 20, 9, 1, 229, 211, 89, 20, 9, 1, 229, 211, 216, 217, 20, - 9, 1, 193, 134, 76, 20, 9, 1, 193, 134, 53, 20, 9, 1, 131, 217, 100, 76, - 20, 9, 1, 131, 217, 100, 53, 20, 9, 1, 99, 76, 20, 9, 1, 99, 53, 20, 9, - 1, 99, 89, 20, 9, 1, 99, 216, 217, 20, 9, 34, 220, 36, 4, 131, 4, 217, - 142, 93, 76, 20, 9, 34, 220, 36, 4, 131, 4, 217, 142, 93, 53, 20, 9, 34, - 220, 36, 4, 131, 4, 230, 58, 93, 76, 20, 9, 34, 220, 36, 4, 131, 4, 230, - 58, 93, 53, 20, 9, 34, 220, 36, 4, 131, 4, 230, 58, 248, 233, 76, 20, 9, - 34, 220, 36, 4, 131, 4, 230, 58, 248, 233, 53, 20, 9, 34, 220, 36, 4, - 131, 76, 20, 9, 34, 220, 36, 4, 131, 53, 20, 191, 78, 193, 75, 213, 37, - 201, 247, 232, 78, 233, 216, 77, 232, 78, 207, 252, 77, 232, 78, 31, 56, - 232, 78, 236, 155, 56, 232, 78, 210, 13, 56, 232, 78, 251, 137, 232, 78, - 251, 49, 232, 78, 45, 210, 113, 232, 78, 50, 210, 113, 232, 78, 250, 193, - 232, 78, 108, 56, 232, 78, 242, 74, 232, 78, 228, 87, 232, 78, 232, 80, - 201, 63, 232, 78, 202, 23, 232, 78, 17, 191, 77, 232, 78, 17, 107, 232, - 78, 17, 109, 232, 78, 17, 138, 232, 78, 17, 134, 232, 78, 17, 149, 232, - 78, 17, 169, 232, 78, 17, 175, 232, 78, 17, 171, 232, 78, 17, 178, 232, - 78, 242, 83, 232, 78, 204, 25, 232, 78, 219, 180, 56, 232, 78, 234, 43, - 56, 232, 78, 230, 204, 56, 232, 78, 208, 13, 77, 232, 78, 242, 72, 250, - 182, 232, 78, 8, 6, 1, 65, 232, 78, 8, 6, 1, 250, 120, 232, 78, 8, 6, 1, - 247, 193, 232, 78, 8, 6, 1, 238, 127, 232, 78, 8, 6, 1, 71, 232, 78, 8, - 6, 1, 233, 175, 232, 78, 8, 6, 1, 232, 51, 232, 78, 8, 6, 1, 230, 116, - 232, 78, 8, 6, 1, 68, 232, 78, 8, 6, 1, 223, 35, 232, 78, 8, 6, 1, 222, - 152, 232, 78, 8, 6, 1, 172, 232, 78, 8, 6, 1, 218, 168, 232, 78, 8, 6, 1, - 215, 61, 232, 78, 8, 6, 1, 74, 232, 78, 8, 6, 1, 210, 236, 232, 78, 8, 6, - 1, 208, 104, 232, 78, 8, 6, 1, 146, 232, 78, 8, 6, 1, 206, 8, 232, 78, 8, - 6, 1, 200, 43, 232, 78, 8, 6, 1, 66, 232, 78, 8, 6, 1, 196, 12, 232, 78, - 8, 6, 1, 193, 224, 232, 78, 8, 6, 1, 192, 235, 232, 78, 8, 6, 1, 192, - 159, 232, 78, 8, 6, 1, 191, 166, 232, 78, 45, 51, 248, 53, 232, 78, 207, - 19, 202, 23, 232, 78, 50, 51, 248, 53, 232, 78, 243, 2, 252, 60, 232, 78, - 130, 219, 112, 232, 78, 230, 211, 252, 60, 232, 78, 8, 2, 1, 65, 232, 78, - 8, 2, 1, 250, 120, 232, 78, 8, 2, 1, 247, 193, 232, 78, 8, 2, 1, 238, - 127, 232, 78, 8, 2, 1, 71, 232, 78, 8, 2, 1, 233, 175, 232, 78, 8, 2, 1, - 232, 51, 232, 78, 8, 2, 1, 230, 116, 232, 78, 8, 2, 1, 68, 232, 78, 8, 2, - 1, 223, 35, 232, 78, 8, 2, 1, 222, 152, 232, 78, 8, 2, 1, 172, 232, 78, - 8, 2, 1, 218, 168, 232, 78, 8, 2, 1, 215, 61, 232, 78, 8, 2, 1, 74, 232, - 78, 8, 2, 1, 210, 236, 232, 78, 8, 2, 1, 208, 104, 232, 78, 8, 2, 1, 146, - 232, 78, 8, 2, 1, 206, 8, 232, 78, 8, 2, 1, 200, 43, 232, 78, 8, 2, 1, - 66, 232, 78, 8, 2, 1, 196, 12, 232, 78, 8, 2, 1, 193, 224, 232, 78, 8, 2, - 1, 192, 235, 232, 78, 8, 2, 1, 192, 159, 232, 78, 8, 2, 1, 191, 166, 232, - 78, 45, 238, 171, 248, 53, 232, 78, 81, 219, 112, 232, 78, 50, 238, 171, - 248, 53, 232, 78, 198, 152, 232, 78, 45, 63, 210, 113, 232, 78, 50, 63, - 210, 113, 150, 154, 232, 80, 201, 63, 150, 45, 239, 2, 248, 53, 150, 50, - 239, 2, 248, 53, 150, 154, 242, 74, 150, 72, 82, 236, 140, 150, 72, 1, - 193, 48, 150, 72, 1, 2, 65, 150, 72, 1, 2, 68, 150, 72, 1, 2, 66, 150, - 72, 1, 2, 71, 150, 72, 1, 2, 74, 150, 72, 1, 2, 170, 150, 72, 1, 2, 191, - 225, 150, 72, 1, 2, 192, 12, 150, 72, 1, 2, 197, 94, 150, 222, 48, 208, - 191, 202, 5, 77, 150, 72, 1, 65, 150, 72, 1, 68, 150, 72, 1, 66, 150, 72, - 1, 71, 150, 72, 1, 74, 150, 72, 1, 155, 150, 72, 1, 221, 166, 150, 72, 1, - 220, 232, 150, 72, 1, 222, 22, 150, 72, 1, 221, 67, 150, 72, 1, 188, 150, - 72, 1, 202, 222, 150, 72, 1, 201, 4, 150, 72, 1, 205, 68, 150, 72, 1, - 202, 46, 150, 72, 1, 190, 190, 150, 72, 1, 198, 193, 150, 72, 1, 197, 94, - 150, 72, 1, 199, 145, 150, 72, 1, 159, 150, 72, 1, 180, 150, 72, 1, 213, - 219, 150, 72, 1, 212, 178, 150, 72, 1, 214, 121, 150, 72, 1, 213, 43, - 150, 72, 1, 140, 150, 72, 1, 229, 158, 150, 72, 1, 228, 159, 150, 72, 1, - 229, 245, 150, 72, 1, 229, 23, 150, 72, 1, 174, 150, 72, 1, 216, 100, - 150, 72, 1, 215, 155, 150, 72, 1, 216, 232, 150, 72, 1, 216, 12, 150, 72, - 1, 170, 150, 72, 1, 191, 225, 150, 72, 1, 192, 12, 150, 72, 1, 165, 150, - 72, 1, 207, 1, 150, 72, 1, 206, 68, 150, 72, 1, 207, 113, 150, 72, 1, - 206, 162, 150, 72, 1, 193, 190, 150, 72, 1, 215, 61, 150, 72, 195, 20, - 202, 5, 77, 150, 72, 204, 30, 202, 5, 77, 150, 30, 233, 3, 150, 30, 1, - 221, 113, 150, 30, 1, 201, 167, 150, 30, 1, 221, 106, 150, 30, 1, 213, - 204, 150, 30, 1, 213, 202, 150, 30, 1, 213, 201, 150, 30, 1, 198, 168, - 150, 30, 1, 201, 156, 150, 30, 1, 206, 239, 150, 30, 1, 206, 234, 150, - 30, 1, 206, 231, 150, 30, 1, 206, 224, 150, 30, 1, 206, 219, 150, 30, 1, - 206, 214, 150, 30, 1, 206, 225, 150, 30, 1, 206, 237, 150, 30, 1, 216, - 77, 150, 30, 1, 209, 169, 150, 30, 1, 201, 164, 150, 30, 1, 209, 158, - 150, 30, 1, 202, 160, 150, 30, 1, 201, 161, 150, 30, 1, 223, 222, 150, - 30, 1, 243, 24, 150, 30, 1, 201, 171, 150, 30, 1, 243, 91, 150, 30, 1, - 221, 188, 150, 30, 1, 199, 7, 150, 30, 1, 209, 209, 150, 30, 1, 229, 142, - 150, 30, 1, 65, 150, 30, 1, 252, 25, 150, 30, 1, 170, 150, 30, 1, 192, - 129, 150, 30, 1, 234, 65, 150, 30, 1, 71, 150, 30, 1, 192, 67, 150, 30, - 1, 192, 80, 150, 30, 1, 74, 150, 30, 1, 193, 190, 150, 30, 1, 193, 176, - 150, 30, 1, 211, 151, 150, 30, 1, 192, 12, 150, 30, 1, 66, 150, 30, 1, - 193, 107, 150, 30, 1, 193, 125, 150, 30, 1, 193, 86, 150, 30, 1, 191, - 225, 150, 30, 1, 233, 242, 150, 30, 1, 192, 33, 150, 30, 1, 68, 232, 78, - 247, 24, 56, 232, 78, 209, 8, 56, 232, 78, 213, 12, 56, 232, 78, 217, - 146, 232, 78, 248, 22, 164, 232, 78, 192, 71, 56, 232, 78, 193, 31, 56, - 150, 232, 141, 156, 195, 135, 150, 118, 57, 150, 196, 66, 57, 150, 96, - 57, 150, 235, 119, 57, 150, 62, 201, 190, 150, 63, 243, 10, 223, 106, - 251, 96, 251, 127, 223, 106, 251, 96, 204, 10, 223, 106, 251, 96, 199, - 80, 211, 175, 207, 43, 246, 239, 207, 43, 246, 239, 32, 78, 5, 250, 104, - 65, 32, 78, 5, 250, 73, 71, 32, 78, 5, 250, 82, 68, 32, 78, 5, 250, 50, - 74, 32, 78, 5, 250, 100, 66, 32, 78, 5, 250, 119, 238, 32, 32, 78, 5, - 250, 66, 237, 146, 32, 78, 5, 250, 106, 237, 44, 32, 78, 5, 250, 96, 236, - 174, 32, 78, 5, 250, 60, 235, 89, 32, 78, 5, 250, 54, 223, 32, 32, 78, 5, - 250, 65, 223, 10, 32, 78, 5, 250, 75, 222, 201, 32, 78, 5, 250, 46, 222, - 182, 32, 78, 5, 250, 34, 155, 32, 78, 5, 250, 67, 222, 22, 32, 78, 5, - 250, 44, 221, 166, 32, 78, 5, 250, 41, 221, 67, 32, 78, 5, 250, 30, 220, - 232, 32, 78, 5, 250, 31, 174, 32, 78, 5, 250, 97, 216, 232, 32, 78, 5, - 250, 38, 216, 100, 32, 78, 5, 250, 95, 216, 12, 32, 78, 5, 250, 87, 215, - 155, 32, 78, 5, 250, 108, 180, 32, 78, 5, 250, 86, 214, 121, 32, 78, 5, - 250, 80, 213, 219, 32, 78, 5, 250, 59, 213, 43, 32, 78, 5, 250, 56, 212, - 178, 32, 78, 5, 250, 115, 168, 32, 78, 5, 250, 39, 210, 63, 32, 78, 5, - 250, 72, 209, 185, 32, 78, 5, 250, 99, 209, 73, 32, 78, 5, 250, 61, 208, - 165, 32, 78, 5, 250, 94, 208, 96, 32, 78, 5, 250, 33, 208, 75, 32, 78, 5, - 250, 89, 208, 57, 32, 78, 5, 250, 78, 208, 45, 32, 78, 5, 250, 51, 165, - 32, 78, 5, 250, 83, 207, 113, 32, 78, 5, 250, 58, 207, 1, 32, 78, 5, 250, - 117, 206, 162, 32, 78, 5, 250, 84, 206, 68, 32, 78, 5, 250, 79, 188, 32, - 78, 5, 250, 102, 205, 68, 32, 78, 5, 250, 70, 202, 222, 32, 78, 5, 250, - 98, 202, 46, 32, 78, 5, 250, 53, 201, 4, 32, 78, 5, 250, 52, 190, 190, - 32, 78, 5, 250, 113, 199, 145, 32, 78, 5, 250, 74, 198, 193, 32, 78, 5, - 250, 111, 159, 32, 78, 5, 250, 42, 197, 94, 32, 78, 5, 250, 57, 193, 190, - 32, 78, 5, 250, 36, 193, 125, 32, 78, 5, 250, 71, 193, 86, 32, 78, 5, - 250, 69, 193, 48, 32, 78, 5, 250, 93, 191, 123, 32, 78, 5, 250, 37, 191, - 87, 32, 78, 5, 250, 90, 191, 7, 32, 78, 5, 250, 85, 254, 215, 32, 78, 5, - 250, 68, 254, 103, 32, 78, 5, 250, 27, 250, 163, 32, 78, 5, 250, 40, 235, - 45, 32, 78, 5, 250, 23, 235, 44, 32, 78, 5, 250, 63, 212, 110, 32, 78, 5, - 250, 81, 208, 163, 32, 78, 5, 250, 49, 208, 167, 32, 78, 5, 250, 35, 207, - 180, 32, 78, 5, 250, 77, 207, 179, 32, 78, 5, 250, 43, 206, 155, 32, 78, - 5, 250, 45, 199, 246, 32, 78, 5, 250, 25, 197, 41, 32, 78, 5, 250, 22, - 109, 32, 78, 16, 250, 92, 32, 78, 16, 250, 91, 32, 78, 16, 250, 88, 32, - 78, 16, 250, 76, 32, 78, 16, 250, 64, 32, 78, 16, 250, 62, 32, 78, 16, - 250, 55, 32, 78, 16, 250, 48, 32, 78, 16, 250, 47, 32, 78, 16, 250, 32, - 32, 78, 16, 250, 29, 32, 78, 16, 250, 28, 32, 78, 16, 250, 26, 32, 78, - 16, 250, 24, 32, 78, 157, 250, 21, 217, 90, 32, 78, 157, 250, 20, 193, - 35, 32, 78, 157, 250, 19, 237, 128, 32, 78, 157, 250, 18, 234, 40, 32, - 78, 157, 250, 17, 217, 56, 32, 78, 157, 250, 16, 201, 110, 32, 78, 157, - 250, 15, 233, 223, 32, 78, 157, 250, 14, 207, 142, 32, 78, 157, 250, 13, - 203, 112, 32, 78, 157, 250, 12, 229, 237, 32, 78, 157, 250, 11, 201, 255, - 32, 78, 157, 250, 10, 248, 109, 32, 78, 157, 250, 9, 238, 239, 32, 78, - 157, 250, 8, 247, 250, 32, 78, 157, 250, 7, 193, 95, 32, 78, 157, 250, 6, - 249, 84, 32, 78, 157, 250, 5, 211, 115, 32, 78, 157, 250, 4, 201, 223, - 32, 78, 157, 250, 3, 238, 136, 32, 78, 215, 221, 250, 2, 222, 74, 32, 78, - 215, 221, 250, 1, 222, 85, 32, 78, 157, 250, 0, 211, 131, 32, 78, 157, - 249, 255, 193, 62, 32, 78, 157, 249, 254, 32, 78, 215, 221, 249, 253, - 251, 7, 32, 78, 215, 221, 249, 252, 216, 178, 32, 78, 157, 249, 251, 248, - 21, 32, 78, 157, 249, 250, 230, 250, 32, 78, 157, 249, 249, 32, 78, 157, - 249, 248, 193, 26, 32, 78, 157, 249, 247, 32, 78, 157, 249, 246, 32, 78, - 157, 249, 245, 228, 187, 32, 78, 157, 249, 244, 32, 78, 157, 249, 243, - 32, 78, 157, 249, 242, 32, 78, 215, 221, 249, 240, 197, 56, 32, 78, 157, - 249, 239, 32, 78, 157, 249, 238, 32, 78, 157, 249, 237, 242, 213, 32, 78, - 157, 249, 236, 32, 78, 157, 249, 235, 32, 78, 157, 249, 234, 231, 196, - 32, 78, 157, 249, 233, 250, 248, 32, 78, 157, 249, 232, 32, 78, 157, 249, - 231, 32, 78, 157, 249, 230, 32, 78, 157, 249, 229, 32, 78, 157, 249, 228, - 32, 78, 157, 249, 227, 32, 78, 157, 249, 226, 32, 78, 157, 249, 225, 32, - 78, 157, 249, 224, 32, 78, 157, 249, 223, 215, 213, 32, 78, 157, 249, - 222, 32, 78, 157, 249, 221, 197, 254, 32, 78, 157, 249, 220, 32, 78, 157, - 249, 219, 32, 78, 157, 249, 218, 32, 78, 157, 249, 217, 32, 78, 157, 249, - 216, 32, 78, 157, 249, 215, 32, 78, 157, 249, 214, 32, 78, 157, 249, 213, - 32, 78, 157, 249, 212, 32, 78, 157, 249, 211, 32, 78, 157, 249, 210, 32, - 78, 157, 249, 209, 229, 200, 32, 78, 157, 249, 188, 232, 155, 32, 78, - 157, 249, 185, 249, 59, 32, 78, 157, 249, 180, 201, 232, 32, 78, 157, - 249, 179, 57, 32, 78, 157, 249, 178, 32, 78, 157, 249, 177, 200, 131, 32, - 78, 157, 249, 176, 32, 78, 157, 249, 175, 32, 78, 157, 249, 174, 193, 90, - 243, 138, 32, 78, 157, 249, 173, 243, 138, 32, 78, 157, 249, 172, 243, - 139, 232, 113, 32, 78, 157, 249, 171, 193, 93, 32, 78, 157, 249, 170, 32, - 78, 157, 249, 169, 32, 78, 215, 221, 249, 168, 236, 235, 32, 78, 157, - 249, 167, 32, 78, 157, 249, 166, 32, 78, 157, 249, 164, 32, 78, 157, 249, - 163, 32, 78, 157, 249, 162, 32, 78, 157, 249, 161, 237, 218, 32, 78, 157, - 249, 160, 32, 78, 157, 249, 159, 32, 78, 157, 249, 158, 32, 78, 157, 249, - 157, 32, 78, 157, 249, 156, 32, 78, 157, 195, 82, 249, 241, 32, 78, 157, - 195, 82, 249, 208, 32, 78, 157, 195, 82, 249, 207, 32, 78, 157, 195, 82, - 249, 206, 32, 78, 157, 195, 82, 249, 205, 32, 78, 157, 195, 82, 249, 204, - 32, 78, 157, 195, 82, 249, 203, 32, 78, 157, 195, 82, 249, 202, 32, 78, - 157, 195, 82, 249, 201, 32, 78, 157, 195, 82, 249, 200, 32, 78, 157, 195, - 82, 249, 199, 32, 78, 157, 195, 82, 249, 198, 32, 78, 157, 195, 82, 249, - 197, 32, 78, 157, 195, 82, 249, 196, 32, 78, 157, 195, 82, 249, 195, 32, - 78, 157, 195, 82, 249, 194, 32, 78, 157, 195, 82, 249, 193, 32, 78, 157, - 195, 82, 249, 192, 32, 78, 157, 195, 82, 249, 191, 32, 78, 157, 195, 82, - 249, 190, 32, 78, 157, 195, 82, 249, 189, 32, 78, 157, 195, 82, 249, 187, - 32, 78, 157, 195, 82, 249, 186, 32, 78, 157, 195, 82, 249, 184, 32, 78, - 157, 195, 82, 249, 183, 32, 78, 157, 195, 82, 249, 182, 32, 78, 157, 195, - 82, 249, 181, 32, 78, 157, 195, 82, 249, 165, 32, 78, 157, 195, 82, 249, - 155, 252, 18, 193, 23, 204, 11, 219, 112, 252, 18, 193, 23, 204, 11, 236, - 140, 252, 18, 243, 126, 77, 252, 18, 31, 107, 252, 18, 31, 109, 252, 18, - 31, 138, 252, 18, 31, 134, 252, 18, 31, 149, 252, 18, 31, 169, 252, 18, - 31, 175, 252, 18, 31, 171, 252, 18, 31, 178, 252, 18, 31, 199, 95, 252, - 18, 31, 197, 32, 252, 18, 31, 198, 249, 252, 18, 31, 232, 135, 252, 18, - 31, 233, 15, 252, 18, 31, 202, 120, 252, 18, 31, 203, 241, 252, 18, 31, - 234, 153, 252, 18, 31, 213, 169, 252, 18, 31, 91, 228, 140, 252, 18, 31, - 105, 228, 140, 252, 18, 31, 115, 228, 140, 252, 18, 31, 232, 128, 228, - 140, 252, 18, 31, 232, 226, 228, 140, 252, 18, 31, 202, 136, 228, 140, - 252, 18, 31, 203, 247, 228, 140, 252, 18, 31, 234, 164, 228, 140, 252, - 18, 31, 213, 175, 228, 140, 252, 18, 31, 91, 189, 252, 18, 31, 105, 189, - 252, 18, 31, 115, 189, 252, 18, 31, 232, 128, 189, 252, 18, 31, 232, 226, - 189, 252, 18, 31, 202, 136, 189, 252, 18, 31, 203, 247, 189, 252, 18, 31, - 234, 164, 189, 252, 18, 31, 213, 175, 189, 252, 18, 31, 199, 96, 189, - 252, 18, 31, 197, 33, 189, 252, 18, 31, 198, 250, 189, 252, 18, 31, 232, - 136, 189, 252, 18, 31, 233, 16, 189, 252, 18, 31, 202, 121, 189, 252, 18, - 31, 203, 242, 189, 252, 18, 31, 234, 154, 189, 252, 18, 31, 213, 170, - 189, 252, 18, 193, 110, 249, 75, 196, 90, 252, 18, 193, 110, 232, 238, - 200, 224, 252, 18, 193, 110, 205, 57, 200, 224, 252, 18, 193, 110, 199, - 1, 200, 224, 252, 18, 193, 110, 232, 121, 200, 224, 252, 18, 235, 92, - 216, 228, 232, 238, 200, 224, 252, 18, 219, 93, 216, 228, 232, 238, 200, - 224, 252, 18, 216, 228, 205, 57, 200, 224, 252, 18, 216, 228, 199, 1, - 200, 224, 35, 252, 50, 250, 165, 91, 208, 22, 35, 252, 50, 250, 165, 91, - 230, 70, 35, 252, 50, 250, 165, 91, 235, 115, 35, 252, 50, 250, 165, 149, - 35, 252, 50, 250, 165, 233, 15, 35, 252, 50, 250, 165, 232, 226, 228, - 140, 35, 252, 50, 250, 165, 232, 226, 189, 35, 252, 50, 250, 165, 233, - 16, 189, 35, 252, 50, 250, 165, 232, 226, 199, 203, 35, 252, 50, 250, - 165, 199, 96, 199, 203, 35, 252, 50, 250, 165, 233, 16, 199, 203, 35, - 252, 50, 250, 165, 91, 228, 141, 199, 203, 35, 252, 50, 250, 165, 232, - 226, 228, 141, 199, 203, 35, 252, 50, 250, 165, 91, 198, 230, 199, 203, - 35, 252, 50, 250, 165, 232, 226, 198, 230, 199, 203, 35, 252, 50, 250, - 165, 232, 226, 201, 94, 35, 252, 50, 250, 165, 199, 96, 201, 94, 35, 252, - 50, 250, 165, 233, 16, 201, 94, 35, 252, 50, 250, 165, 91, 228, 141, 201, - 94, 35, 252, 50, 250, 165, 232, 226, 228, 141, 201, 94, 35, 252, 50, 250, - 165, 91, 198, 230, 201, 94, 35, 252, 50, 250, 165, 199, 96, 198, 230, - 201, 94, 35, 252, 50, 250, 165, 233, 16, 198, 230, 201, 94, 35, 252, 50, - 250, 165, 199, 96, 216, 15, 35, 252, 50, 229, 194, 91, 209, 92, 35, 252, - 50, 199, 17, 107, 35, 252, 50, 229, 190, 107, 35, 252, 50, 234, 51, 109, - 35, 252, 50, 199, 17, 109, 35, 252, 50, 238, 132, 105, 235, 114, 35, 252, - 50, 234, 51, 105, 235, 114, 35, 252, 50, 197, 216, 149, 35, 252, 50, 197, - 216, 199, 95, 35, 252, 50, 197, 216, 199, 96, 251, 157, 20, 35, 252, 50, - 229, 190, 199, 95, 35, 252, 50, 216, 167, 199, 95, 35, 252, 50, 199, 17, - 199, 95, 35, 252, 50, 199, 17, 198, 249, 35, 252, 50, 197, 216, 233, 15, - 35, 252, 50, 197, 216, 233, 16, 251, 157, 20, 35, 252, 50, 229, 190, 233, - 15, 35, 252, 50, 199, 17, 233, 15, 35, 252, 50, 199, 17, 91, 228, 140, - 35, 252, 50, 199, 17, 115, 228, 140, 35, 252, 50, 234, 51, 232, 226, 228, - 140, 35, 252, 50, 197, 216, 232, 226, 228, 140, 35, 252, 50, 199, 17, - 232, 226, 228, 140, 35, 252, 50, 247, 82, 232, 226, 228, 140, 35, 252, - 50, 214, 199, 232, 226, 228, 140, 35, 252, 50, 199, 17, 91, 189, 35, 252, - 50, 199, 17, 232, 226, 189, 35, 252, 50, 237, 109, 232, 226, 216, 15, 35, - 252, 50, 201, 47, 233, 16, 216, 15, 35, 91, 132, 56, 35, 91, 132, 3, 251, - 157, 20, 35, 105, 198, 254, 56, 35, 115, 208, 21, 56, 35, 192, 78, 56, - 35, 199, 204, 56, 35, 235, 116, 56, 35, 211, 170, 56, 35, 105, 211, 169, - 56, 35, 115, 211, 169, 56, 35, 232, 128, 211, 169, 56, 35, 232, 226, 211, - 169, 56, 35, 216, 161, 56, 35, 220, 151, 249, 75, 56, 35, 219, 85, 56, - 35, 211, 16, 56, 35, 192, 211, 56, 35, 250, 226, 56, 35, 250, 243, 56, - 35, 230, 220, 56, 35, 197, 171, 249, 75, 56, 35, 191, 78, 56, 35, 91, - 208, 23, 56, 35, 202, 162, 56, 35, 223, 143, 56, 213, 32, 56, 206, 136, - 203, 237, 56, 206, 136, 196, 106, 56, 206, 136, 204, 17, 56, 206, 136, - 203, 175, 56, 206, 136, 236, 250, 203, 175, 56, 206, 136, 202, 186, 56, - 206, 136, 237, 104, 56, 206, 136, 208, 5, 56, 206, 136, 203, 254, 56, - 206, 136, 235, 67, 56, 206, 136, 250, 220, 56, 206, 136, 247, 17, 56, - 250, 211, 113, 35, 16, 199, 167, 207, 3, 209, 223, 236, 227, 3, 210, 51, - 209, 223, 236, 227, 3, 209, 84, 229, 235, 209, 223, 236, 227, 3, 199, - 170, 229, 235, 209, 223, 236, 227, 3, 247, 105, 209, 223, 236, 227, 3, - 243, 86, 209, 223, 236, 227, 3, 193, 35, 209, 223, 236, 227, 3, 229, 200, - 209, 223, 236, 227, 3, 231, 188, 209, 223, 236, 227, 3, 198, 184, 209, - 223, 236, 227, 3, 57, 209, 223, 236, 227, 3, 248, 69, 209, 223, 236, 227, - 3, 203, 78, 209, 223, 236, 227, 3, 242, 206, 209, 223, 236, 227, 3, 217, - 89, 209, 223, 236, 227, 3, 217, 26, 209, 223, 236, 227, 3, 205, 108, 209, - 223, 236, 227, 3, 219, 141, 209, 223, 236, 227, 3, 248, 92, 209, 223, - 236, 227, 3, 247, 89, 209, 101, 209, 223, 236, 227, 3, 236, 156, 209, - 223, 236, 227, 3, 242, 80, 209, 223, 236, 227, 3, 202, 83, 209, 223, 236, - 227, 3, 242, 81, 209, 223, 236, 227, 3, 248, 254, 209, 223, 236, 227, 3, - 203, 65, 209, 223, 236, 227, 3, 228, 187, 209, 223, 236, 227, 3, 229, - 148, 209, 223, 236, 227, 3, 247, 245, 219, 212, 209, 223, 236, 227, 3, - 247, 78, 209, 223, 236, 227, 3, 207, 142, 209, 223, 236, 227, 3, 234, - 214, 209, 223, 236, 227, 3, 235, 124, 209, 223, 236, 227, 3, 197, 72, - 209, 223, 236, 227, 3, 249, 1, 209, 223, 236, 227, 3, 209, 102, 197, 254, - 209, 223, 236, 227, 3, 195, 47, 209, 223, 236, 227, 3, 210, 132, 209, - 223, 236, 227, 3, 206, 125, 209, 223, 236, 227, 3, 219, 125, 209, 223, - 236, 227, 3, 210, 248, 249, 146, 209, 223, 236, 227, 3, 232, 182, 209, - 223, 236, 227, 3, 230, 212, 209, 223, 236, 227, 3, 201, 50, 209, 223, - 236, 227, 3, 2, 250, 132, 209, 223, 236, 227, 3, 193, 135, 249, 97, 209, - 223, 236, 227, 3, 33, 211, 172, 106, 218, 181, 1, 65, 218, 181, 1, 71, - 218, 181, 1, 250, 120, 218, 181, 1, 248, 204, 218, 181, 1, 232, 51, 218, - 181, 1, 238, 127, 218, 181, 1, 68, 218, 181, 1, 193, 224, 218, 181, 1, - 191, 166, 218, 181, 1, 199, 51, 218, 181, 1, 223, 35, 218, 181, 1, 222, - 152, 218, 181, 1, 208, 104, 218, 181, 1, 172, 218, 181, 1, 218, 168, 218, - 181, 1, 215, 61, 218, 181, 1, 216, 17, 218, 181, 1, 213, 80, 218, 181, 1, - 66, 218, 181, 1, 210, 236, 218, 181, 1, 221, 102, 218, 181, 1, 146, 218, - 181, 1, 206, 8, 218, 181, 1, 200, 43, 218, 181, 1, 197, 135, 218, 181, 1, - 251, 132, 218, 181, 1, 234, 103, 218, 181, 1, 230, 116, 218, 181, 1, 192, - 235, 247, 95, 1, 65, 247, 95, 1, 210, 222, 247, 95, 1, 238, 127, 247, 95, - 1, 172, 247, 95, 1, 196, 28, 247, 95, 1, 146, 247, 95, 1, 219, 242, 247, - 95, 1, 254, 215, 247, 95, 1, 208, 104, 247, 95, 1, 250, 120, 247, 95, 1, - 218, 168, 247, 95, 1, 74, 247, 95, 1, 238, 34, 247, 95, 1, 200, 43, 247, - 95, 1, 203, 167, 247, 95, 1, 203, 166, 247, 95, 1, 206, 8, 247, 95, 1, - 247, 192, 247, 95, 1, 66, 247, 95, 1, 213, 80, 247, 95, 1, 192, 235, 247, - 95, 1, 215, 61, 247, 95, 1, 197, 134, 247, 95, 1, 210, 236, 247, 95, 1, - 201, 178, 247, 95, 1, 68, 247, 95, 1, 71, 247, 95, 1, 196, 25, 247, 95, - 1, 222, 152, 247, 95, 1, 222, 143, 247, 95, 1, 214, 164, 247, 95, 1, 196, - 30, 247, 95, 1, 232, 51, 247, 95, 1, 231, 242, 247, 95, 1, 201, 118, 247, - 95, 1, 201, 117, 247, 95, 1, 214, 70, 247, 95, 1, 223, 199, 247, 95, 1, - 247, 191, 247, 95, 1, 197, 135, 247, 95, 1, 196, 27, 247, 95, 1, 206, - 110, 247, 95, 1, 217, 16, 247, 95, 1, 217, 15, 247, 95, 1, 217, 14, 247, - 95, 1, 217, 13, 247, 95, 1, 219, 241, 247, 95, 1, 234, 218, 247, 95, 1, - 196, 26, 94, 234, 54, 198, 229, 77, 94, 234, 54, 17, 107, 94, 234, 54, - 17, 109, 94, 234, 54, 17, 138, 94, 234, 54, 17, 134, 94, 234, 54, 17, - 149, 94, 234, 54, 17, 169, 94, 234, 54, 17, 175, 94, 234, 54, 17, 171, - 94, 234, 54, 17, 178, 94, 234, 54, 31, 199, 95, 94, 234, 54, 31, 197, 32, - 94, 234, 54, 31, 198, 249, 94, 234, 54, 31, 232, 135, 94, 234, 54, 31, - 233, 15, 94, 234, 54, 31, 202, 120, 94, 234, 54, 31, 203, 241, 94, 234, - 54, 31, 234, 153, 94, 234, 54, 31, 213, 169, 94, 234, 54, 31, 91, 228, - 140, 94, 234, 54, 31, 105, 228, 140, 94, 234, 54, 31, 115, 228, 140, 94, - 234, 54, 31, 232, 128, 228, 140, 94, 234, 54, 31, 232, 226, 228, 140, 94, - 234, 54, 31, 202, 136, 228, 140, 94, 234, 54, 31, 203, 247, 228, 140, 94, - 234, 54, 31, 234, 164, 228, 140, 94, 234, 54, 31, 213, 175, 228, 140, 39, - 43, 1, 65, 39, 43, 1, 249, 17, 39, 43, 1, 222, 22, 39, 43, 1, 237, 146, - 39, 43, 1, 71, 39, 43, 1, 195, 153, 39, 43, 1, 191, 87, 39, 43, 1, 229, - 245, 39, 43, 1, 199, 33, 39, 43, 1, 68, 39, 43, 1, 155, 39, 43, 1, 234, - 140, 39, 43, 1, 234, 114, 39, 43, 1, 234, 103, 39, 43, 1, 234, 12, 39, - 43, 1, 74, 39, 43, 1, 210, 63, 39, 43, 1, 203, 113, 39, 43, 1, 220, 232, - 39, 43, 1, 234, 34, 39, 43, 1, 234, 22, 39, 43, 1, 199, 145, 39, 43, 1, - 66, 39, 43, 1, 234, 143, 39, 43, 1, 209, 214, 39, 43, 1, 221, 197, 39, - 43, 1, 234, 181, 39, 43, 1, 234, 24, 39, 43, 1, 243, 127, 39, 43, 1, 223, - 199, 39, 43, 1, 196, 30, 39, 43, 1, 234, 5, 39, 43, 212, 134, 107, 39, - 43, 212, 134, 149, 39, 43, 212, 134, 199, 95, 39, 43, 212, 134, 233, 15, - 39, 43, 1, 192, 80, 39, 43, 1, 213, 16, 197, 161, 39, 43, 1, 202, 0, 197, - 161, 230, 231, 1, 251, 239, 230, 231, 1, 249, 117, 230, 231, 1, 231, 50, - 230, 231, 1, 238, 13, 230, 231, 1, 251, 234, 230, 231, 1, 208, 87, 230, - 231, 1, 223, 48, 230, 231, 1, 230, 83, 230, 231, 1, 198, 243, 230, 231, - 1, 234, 151, 230, 231, 1, 220, 189, 230, 231, 1, 220, 100, 230, 231, 1, - 217, 80, 230, 231, 1, 214, 201, 230, 231, 1, 223, 1, 230, 231, 1, 196, - 48, 230, 231, 1, 210, 195, 230, 231, 1, 213, 169, 230, 231, 1, 207, 155, - 230, 231, 1, 205, 112, 230, 231, 1, 199, 111, 230, 231, 1, 193, 59, 230, - 231, 1, 233, 89, 230, 231, 1, 223, 203, 230, 231, 1, 228, 123, 230, 231, - 1, 211, 29, 230, 231, 1, 213, 175, 228, 140, 39, 210, 2, 1, 251, 132, 39, - 210, 2, 1, 247, 230, 39, 210, 2, 1, 231, 224, 39, 210, 2, 1, 236, 160, - 39, 210, 2, 1, 71, 39, 210, 2, 1, 191, 53, 39, 210, 2, 1, 235, 27, 39, - 210, 2, 1, 191, 95, 39, 210, 2, 1, 235, 25, 39, 210, 2, 1, 68, 39, 210, - 2, 1, 221, 50, 39, 210, 2, 1, 219, 208, 39, 210, 2, 1, 216, 184, 39, 210, - 2, 1, 214, 100, 39, 210, 2, 1, 195, 7, 39, 210, 2, 1, 210, 48, 39, 210, - 2, 1, 207, 70, 39, 210, 2, 1, 202, 193, 39, 210, 2, 1, 199, 217, 39, 210, - 2, 1, 66, 39, 210, 2, 1, 243, 106, 39, 210, 2, 1, 203, 47, 39, 210, 2, 1, - 203, 115, 39, 210, 2, 1, 191, 227, 39, 210, 2, 1, 192, 58, 39, 210, 2, 1, - 74, 39, 210, 2, 1, 211, 87, 39, 210, 2, 1, 234, 181, 39, 210, 2, 1, 140, - 39, 210, 2, 1, 197, 145, 39, 210, 2, 1, 195, 140, 39, 210, 2, 1, 192, 62, - 39, 210, 2, 1, 192, 60, 39, 210, 2, 1, 192, 95, 39, 210, 2, 1, 223, 226, - 39, 210, 2, 1, 191, 225, 39, 210, 2, 1, 170, 39, 210, 2, 1, 228, 35, 33, - 39, 210, 2, 1, 251, 132, 33, 39, 210, 2, 1, 236, 160, 33, 39, 210, 2, 1, - 191, 95, 33, 39, 210, 2, 1, 214, 100, 33, 39, 210, 2, 1, 202, 193, 196, - 142, 1, 251, 164, 196, 142, 1, 248, 212, 196, 142, 1, 231, 212, 196, 142, - 1, 221, 215, 196, 142, 1, 237, 106, 196, 142, 1, 229, 23, 196, 142, 1, - 193, 48, 196, 142, 1, 191, 76, 196, 142, 1, 228, 179, 196, 142, 1, 199, - 73, 196, 142, 1, 191, 250, 196, 142, 1, 222, 106, 196, 142, 1, 203, 69, - 196, 142, 1, 220, 31, 196, 142, 1, 216, 193, 196, 142, 1, 237, 64, 196, - 142, 1, 212, 130, 196, 142, 1, 190, 251, 196, 142, 1, 205, 147, 196, 142, - 1, 251, 230, 196, 142, 1, 208, 165, 196, 142, 1, 205, 191, 196, 142, 1, - 208, 38, 196, 142, 1, 207, 133, 196, 142, 1, 199, 37, 196, 142, 1, 231, - 86, 196, 142, 1, 159, 196, 142, 1, 68, 196, 142, 1, 66, 196, 142, 1, 201, - 129, 196, 142, 193, 23, 236, 205, 39, 209, 252, 3, 65, 39, 209, 252, 3, - 68, 39, 209, 252, 3, 66, 39, 209, 252, 3, 155, 39, 209, 252, 3, 220, 232, - 39, 209, 252, 3, 231, 240, 39, 209, 252, 3, 230, 179, 39, 209, 252, 3, - 192, 220, 39, 209, 252, 3, 247, 160, 39, 209, 252, 3, 223, 32, 39, 209, - 252, 3, 222, 244, 39, 209, 252, 3, 190, 190, 39, 209, 252, 3, 197, 94, - 39, 209, 252, 3, 238, 32, 39, 209, 252, 3, 237, 44, 39, 209, 252, 3, 235, - 89, 39, 209, 252, 3, 199, 49, 39, 209, 252, 3, 168, 39, 209, 252, 3, 249, - 153, 39, 209, 252, 3, 233, 109, 39, 209, 252, 3, 180, 39, 209, 252, 3, - 212, 178, 39, 209, 252, 3, 174, 39, 209, 252, 3, 216, 100, 39, 209, 252, - 3, 215, 155, 39, 209, 252, 3, 170, 39, 209, 252, 3, 195, 188, 39, 209, - 252, 3, 195, 69, 39, 209, 252, 3, 165, 39, 209, 252, 3, 206, 68, 39, 209, - 252, 3, 173, 39, 209, 252, 3, 188, 39, 209, 252, 3, 191, 123, 39, 209, - 252, 3, 203, 165, 39, 209, 252, 3, 201, 175, 39, 209, 252, 3, 140, 39, - 209, 252, 3, 250, 157, 39, 209, 252, 3, 250, 156, 39, 209, 252, 3, 250, - 155, 39, 209, 252, 3, 192, 189, 39, 209, 252, 3, 238, 9, 39, 209, 252, 3, - 238, 8, 39, 209, 252, 3, 249, 128, 39, 209, 252, 3, 247, 212, 39, 209, - 252, 193, 23, 236, 205, 39, 209, 252, 31, 107, 39, 209, 252, 31, 109, 39, - 209, 252, 31, 199, 95, 39, 209, 252, 31, 197, 32, 39, 209, 252, 31, 228, - 140, 237, 84, 6, 1, 179, 68, 237, 84, 6, 1, 179, 71, 237, 84, 6, 1, 179, - 65, 237, 84, 6, 1, 179, 251, 245, 237, 84, 6, 1, 179, 74, 237, 84, 6, 1, - 179, 211, 87, 237, 84, 6, 1, 203, 40, 68, 237, 84, 6, 1, 203, 40, 71, - 237, 84, 6, 1, 203, 40, 65, 237, 84, 6, 1, 203, 40, 251, 245, 237, 84, 6, - 1, 203, 40, 74, 237, 84, 6, 1, 203, 40, 211, 87, 237, 84, 6, 1, 250, 131, - 237, 84, 6, 1, 210, 250, 237, 84, 6, 1, 193, 0, 237, 84, 6, 1, 192, 77, - 237, 84, 6, 1, 230, 116, 237, 84, 6, 1, 210, 49, 237, 84, 6, 1, 249, 1, - 237, 84, 6, 1, 199, 121, 237, 84, 6, 1, 237, 131, 237, 84, 6, 1, 243, - 123, 237, 84, 6, 1, 223, 8, 237, 84, 6, 1, 222, 29, 237, 84, 6, 1, 231, - 186, 237, 84, 6, 1, 234, 181, 237, 84, 6, 1, 195, 148, 237, 84, 6, 1, - 233, 248, 237, 84, 6, 1, 199, 31, 237, 84, 6, 1, 234, 22, 237, 84, 6, 1, - 191, 84, 237, 84, 6, 1, 234, 12, 237, 84, 6, 1, 191, 61, 237, 84, 6, 1, - 234, 34, 237, 84, 6, 1, 234, 140, 237, 84, 6, 1, 234, 114, 237, 84, 6, 1, - 234, 103, 237, 84, 6, 1, 234, 88, 237, 84, 6, 1, 211, 133, 237, 84, 6, 1, - 233, 224, 237, 84, 2, 1, 179, 68, 237, 84, 2, 1, 179, 71, 237, 84, 2, 1, - 179, 65, 237, 84, 2, 1, 179, 251, 245, 237, 84, 2, 1, 179, 74, 237, 84, - 2, 1, 179, 211, 87, 237, 84, 2, 1, 203, 40, 68, 237, 84, 2, 1, 203, 40, - 71, 237, 84, 2, 1, 203, 40, 65, 237, 84, 2, 1, 203, 40, 251, 245, 237, - 84, 2, 1, 203, 40, 74, 237, 84, 2, 1, 203, 40, 211, 87, 237, 84, 2, 1, - 250, 131, 237, 84, 2, 1, 210, 250, 237, 84, 2, 1, 193, 0, 237, 84, 2, 1, - 192, 77, 237, 84, 2, 1, 230, 116, 237, 84, 2, 1, 210, 49, 237, 84, 2, 1, - 249, 1, 237, 84, 2, 1, 199, 121, 237, 84, 2, 1, 237, 131, 237, 84, 2, 1, - 243, 123, 237, 84, 2, 1, 223, 8, 237, 84, 2, 1, 222, 29, 237, 84, 2, 1, - 231, 186, 237, 84, 2, 1, 234, 181, 237, 84, 2, 1, 195, 148, 237, 84, 2, - 1, 233, 248, 237, 84, 2, 1, 199, 31, 237, 84, 2, 1, 234, 22, 237, 84, 2, - 1, 191, 84, 237, 84, 2, 1, 234, 12, 237, 84, 2, 1, 191, 61, 237, 84, 2, - 1, 234, 34, 237, 84, 2, 1, 234, 140, 237, 84, 2, 1, 234, 114, 237, 84, 2, - 1, 234, 103, 237, 84, 2, 1, 234, 88, 237, 84, 2, 1, 211, 133, 237, 84, 2, - 1, 233, 224, 203, 120, 1, 210, 45, 203, 120, 1, 198, 40, 203, 120, 1, - 221, 154, 203, 120, 1, 233, 52, 203, 120, 1, 199, 6, 203, 120, 1, 202, - 46, 203, 120, 1, 200, 172, 203, 120, 1, 243, 40, 203, 120, 1, 192, 79, - 203, 120, 1, 228, 137, 203, 120, 1, 248, 187, 203, 120, 1, 237, 145, 203, - 120, 1, 231, 226, 203, 120, 1, 195, 2, 203, 120, 1, 199, 12, 203, 120, 1, - 191, 4, 203, 120, 1, 216, 227, 203, 120, 1, 222, 180, 203, 120, 1, 193, - 39, 203, 120, 1, 230, 93, 203, 120, 1, 219, 25, 203, 120, 1, 216, 45, - 203, 120, 1, 223, 206, 203, 120, 1, 234, 179, 203, 120, 1, 250, 209, 203, - 120, 1, 252, 30, 203, 120, 1, 211, 104, 203, 120, 1, 193, 26, 203, 120, - 1, 211, 14, 203, 120, 1, 251, 245, 203, 120, 1, 206, 153, 203, 120, 1, - 212, 130, 203, 120, 1, 234, 200, 203, 120, 1, 251, 250, 203, 120, 1, 228, - 26, 203, 120, 1, 196, 77, 203, 120, 1, 211, 180, 203, 120, 1, 211, 79, - 203, 120, 1, 211, 131, 203, 120, 1, 250, 137, 203, 120, 1, 251, 9, 203, - 120, 1, 211, 56, 203, 120, 1, 251, 225, 203, 120, 1, 234, 26, 203, 120, - 1, 250, 240, 203, 120, 1, 234, 211, 203, 120, 1, 228, 34, 203, 120, 1, - 192, 41, 211, 33, 1, 251, 192, 211, 33, 1, 249, 153, 211, 33, 1, 190, - 190, 211, 33, 1, 223, 32, 211, 33, 1, 192, 220, 211, 33, 1, 221, 215, - 211, 33, 1, 237, 130, 211, 33, 1, 165, 211, 33, 1, 188, 211, 33, 1, 203, - 75, 211, 33, 1, 237, 68, 211, 33, 1, 247, 67, 211, 33, 1, 231, 240, 211, - 33, 1, 233, 109, 211, 33, 1, 208, 94, 211, 33, 1, 222, 123, 211, 33, 1, - 220, 121, 211, 33, 1, 216, 59, 211, 33, 1, 212, 114, 211, 33, 1, 193, - 133, 211, 33, 1, 140, 211, 33, 1, 170, 211, 33, 1, 65, 211, 33, 1, 71, - 211, 33, 1, 68, 211, 33, 1, 74, 211, 33, 1, 66, 211, 33, 1, 252, 206, - 211, 33, 1, 234, 188, 211, 33, 1, 211, 87, 211, 33, 17, 191, 77, 211, 33, - 17, 107, 211, 33, 17, 109, 211, 33, 17, 138, 211, 33, 17, 134, 211, 33, - 17, 149, 211, 33, 17, 169, 211, 33, 17, 175, 211, 33, 17, 171, 211, 33, - 17, 178, 211, 35, 6, 1, 65, 211, 35, 6, 1, 251, 236, 211, 35, 6, 1, 251, - 230, 211, 35, 6, 1, 251, 245, 211, 35, 6, 1, 248, 56, 211, 35, 6, 1, 247, - 1, 211, 35, 6, 1, 234, 172, 211, 35, 6, 1, 71, 211, 35, 6, 1, 234, 152, - 211, 35, 6, 1, 140, 211, 35, 6, 1, 228, 93, 211, 35, 6, 1, 68, 211, 35, - 6, 1, 155, 211, 35, 6, 1, 234, 171, 211, 35, 6, 1, 220, 153, 211, 35, 6, - 1, 173, 211, 35, 6, 1, 174, 211, 35, 6, 1, 180, 211, 35, 6, 1, 74, 211, - 35, 6, 1, 211, 130, 211, 35, 6, 1, 168, 211, 35, 6, 1, 234, 170, 211, 35, - 6, 1, 188, 211, 35, 6, 1, 203, 165, 211, 35, 6, 1, 190, 190, 211, 35, 6, - 1, 234, 169, 211, 35, 6, 1, 197, 168, 211, 35, 6, 1, 234, 168, 211, 35, - 6, 1, 197, 157, 211, 35, 6, 1, 237, 68, 211, 35, 6, 1, 66, 211, 35, 6, 1, - 193, 190, 211, 35, 6, 1, 221, 215, 211, 35, 6, 1, 231, 91, 211, 35, 6, 1, - 191, 123, 211, 35, 6, 1, 191, 71, 211, 35, 2, 1, 65, 211, 35, 2, 1, 251, - 236, 211, 35, 2, 1, 251, 230, 211, 35, 2, 1, 251, 245, 211, 35, 2, 1, - 248, 56, 211, 35, 2, 1, 247, 1, 211, 35, 2, 1, 234, 172, 211, 35, 2, 1, - 71, 211, 35, 2, 1, 234, 152, 211, 35, 2, 1, 140, 211, 35, 2, 1, 228, 93, - 211, 35, 2, 1, 68, 211, 35, 2, 1, 155, 211, 35, 2, 1, 234, 171, 211, 35, - 2, 1, 220, 153, 211, 35, 2, 1, 173, 211, 35, 2, 1, 174, 211, 35, 2, 1, - 180, 211, 35, 2, 1, 74, 211, 35, 2, 1, 211, 130, 211, 35, 2, 1, 168, 211, - 35, 2, 1, 234, 170, 211, 35, 2, 1, 188, 211, 35, 2, 1, 203, 165, 211, 35, - 2, 1, 190, 190, 211, 35, 2, 1, 234, 169, 211, 35, 2, 1, 197, 168, 211, - 35, 2, 1, 234, 168, 211, 35, 2, 1, 197, 157, 211, 35, 2, 1, 237, 68, 211, - 35, 2, 1, 66, 211, 35, 2, 1, 193, 190, 211, 35, 2, 1, 221, 215, 211, 35, - 2, 1, 231, 91, 211, 35, 2, 1, 191, 123, 211, 35, 2, 1, 191, 71, 234, 136, - 1, 65, 234, 136, 1, 249, 17, 234, 136, 1, 247, 42, 234, 136, 1, 243, 127, - 234, 136, 1, 237, 146, 234, 136, 1, 214, 154, 234, 136, 1, 237, 59, 234, - 136, 1, 234, 166, 234, 136, 1, 71, 234, 136, 1, 233, 59, 234, 136, 1, - 231, 165, 234, 136, 1, 231, 20, 234, 136, 1, 229, 245, 234, 136, 1, 68, - 234, 136, 1, 223, 10, 234, 136, 1, 222, 22, 234, 136, 1, 219, 238, 234, - 136, 1, 219, 68, 234, 136, 1, 216, 232, 234, 136, 1, 214, 121, 234, 136, - 1, 180, 234, 136, 1, 213, 150, 234, 136, 1, 74, 234, 136, 1, 210, 63, - 234, 136, 1, 208, 75, 234, 136, 1, 207, 113, 234, 136, 1, 206, 104, 234, - 136, 1, 205, 68, 234, 136, 1, 203, 113, 234, 136, 1, 199, 145, 234, 136, - 1, 199, 33, 234, 136, 1, 66, 234, 136, 1, 195, 153, 234, 136, 1, 192, - 214, 234, 136, 1, 192, 159, 234, 136, 1, 191, 87, 234, 136, 1, 191, 62, - 234, 136, 1, 231, 77, 234, 136, 1, 231, 83, 234, 136, 1, 221, 197, 247, - 75, 251, 193, 1, 251, 159, 247, 75, 251, 193, 1, 248, 214, 247, 75, 251, - 193, 1, 231, 40, 247, 75, 251, 193, 1, 237, 211, 247, 75, 251, 193, 1, - 234, 199, 247, 75, 251, 193, 1, 191, 98, 247, 75, 251, 193, 1, 233, 184, - 247, 75, 251, 193, 1, 191, 56, 247, 75, 251, 193, 1, 199, 174, 247, 75, - 251, 193, 1, 247, 1, 247, 75, 251, 193, 1, 191, 236, 247, 75, 251, 193, - 1, 191, 71, 247, 75, 251, 193, 1, 223, 76, 247, 75, 251, 193, 1, 203, - 165, 247, 75, 251, 193, 1, 220, 24, 247, 75, 251, 193, 1, 223, 89, 247, - 75, 251, 193, 1, 192, 210, 247, 75, 251, 193, 1, 235, 43, 247, 75, 251, - 193, 1, 247, 102, 247, 75, 251, 193, 1, 222, 245, 247, 75, 251, 193, 1, - 222, 65, 247, 75, 251, 193, 1, 218, 177, 247, 75, 251, 193, 1, 229, 179, - 247, 75, 251, 193, 1, 208, 76, 247, 75, 251, 193, 1, 251, 67, 247, 75, - 251, 193, 1, 243, 57, 247, 75, 251, 193, 1, 243, 95, 247, 75, 251, 193, - 1, 238, 140, 247, 75, 251, 193, 1, 217, 68, 247, 75, 251, 193, 1, 208, - 81, 247, 75, 251, 193, 1, 212, 252, 247, 75, 251, 193, 1, 235, 20, 247, - 75, 251, 193, 1, 203, 147, 247, 75, 251, 193, 1, 223, 11, 247, 75, 251, - 193, 1, 211, 104, 247, 75, 251, 193, 1, 197, 3, 247, 75, 251, 193, 1, - 233, 82, 247, 75, 251, 193, 1, 235, 33, 247, 75, 251, 193, 1, 243, 133, - 247, 75, 251, 193, 1, 210, 34, 247, 75, 251, 193, 1, 231, 67, 247, 75, - 251, 193, 1, 207, 130, 247, 75, 251, 193, 1, 203, 174, 247, 75, 251, 193, - 1, 195, 72, 247, 75, 251, 193, 1, 198, 118, 247, 75, 251, 193, 1, 203, - 18, 247, 75, 251, 193, 1, 223, 46, 247, 75, 251, 193, 1, 238, 141, 247, - 75, 251, 193, 1, 247, 67, 247, 75, 251, 193, 1, 192, 84, 247, 75, 251, - 193, 1, 209, 114, 247, 75, 251, 193, 1, 221, 117, 247, 75, 251, 193, 242, - 254, 77, 195, 29, 6, 1, 65, 195, 29, 6, 1, 249, 48, 195, 29, 6, 1, 249, - 17, 195, 29, 6, 1, 247, 42, 195, 29, 6, 1, 243, 127, 195, 29, 6, 1, 237, - 146, 195, 29, 6, 1, 237, 59, 195, 29, 6, 1, 234, 166, 195, 29, 6, 1, 71, - 195, 29, 6, 1, 233, 59, 195, 29, 6, 1, 231, 240, 195, 29, 6, 1, 140, 195, - 29, 6, 1, 229, 177, 195, 29, 6, 1, 68, 195, 29, 6, 1, 223, 196, 195, 29, - 6, 1, 223, 10, 195, 29, 6, 1, 155, 195, 29, 6, 1, 173, 195, 29, 6, 1, - 219, 73, 195, 29, 6, 1, 216, 232, 195, 29, 6, 1, 214, 121, 195, 29, 6, 1, - 213, 150, 195, 29, 6, 1, 74, 195, 29, 6, 1, 210, 63, 195, 29, 6, 1, 208, - 96, 195, 29, 6, 1, 207, 113, 195, 29, 6, 1, 205, 68, 195, 29, 6, 1, 203, - 113, 195, 29, 6, 1, 199, 145, 195, 29, 6, 1, 199, 33, 195, 29, 6, 1, 66, - 195, 29, 6, 1, 195, 153, 195, 29, 6, 1, 192, 214, 195, 29, 6, 1, 192, - 159, 195, 29, 6, 1, 191, 87, 195, 29, 2, 1, 65, 195, 29, 2, 1, 249, 48, - 195, 29, 2, 1, 249, 17, 195, 29, 2, 1, 247, 42, 195, 29, 2, 1, 243, 127, - 195, 29, 2, 1, 237, 146, 195, 29, 2, 1, 237, 59, 195, 29, 2, 1, 234, 166, - 195, 29, 2, 1, 71, 195, 29, 2, 1, 233, 59, 195, 29, 2, 1, 231, 240, 195, - 29, 2, 1, 140, 195, 29, 2, 1, 229, 177, 195, 29, 2, 1, 68, 195, 29, 2, 1, - 223, 196, 195, 29, 2, 1, 223, 10, 195, 29, 2, 1, 155, 195, 29, 2, 1, 173, - 195, 29, 2, 1, 219, 73, 195, 29, 2, 1, 216, 232, 195, 29, 2, 1, 214, 121, - 195, 29, 2, 1, 213, 150, 195, 29, 2, 1, 74, 195, 29, 2, 1, 210, 63, 195, - 29, 2, 1, 208, 96, 195, 29, 2, 1, 207, 113, 195, 29, 2, 1, 205, 68, 195, - 29, 2, 1, 203, 113, 195, 29, 2, 1, 199, 145, 195, 29, 2, 1, 199, 33, 195, - 29, 2, 1, 66, 195, 29, 2, 1, 195, 153, 195, 29, 2, 1, 192, 214, 195, 29, - 2, 1, 192, 159, 195, 29, 2, 1, 191, 87, 32, 42, 3, 252, 154, 32, 42, 3, - 252, 153, 32, 42, 3, 252, 152, 32, 42, 3, 252, 151, 32, 42, 3, 252, 150, - 32, 42, 3, 252, 149, 32, 42, 3, 252, 148, 32, 42, 3, 252, 147, 32, 42, 3, - 252, 146, 32, 42, 3, 252, 145, 32, 42, 3, 252, 144, 32, 42, 3, 252, 143, - 32, 42, 3, 252, 142, 32, 42, 3, 252, 141, 32, 42, 3, 252, 140, 32, 42, 3, - 252, 139, 32, 42, 3, 252, 138, 32, 42, 3, 252, 137, 32, 42, 3, 252, 136, - 32, 42, 3, 252, 135, 32, 42, 3, 252, 134, 32, 42, 3, 252, 133, 32, 42, 3, - 252, 132, 32, 42, 3, 252, 131, 32, 42, 3, 252, 130, 32, 42, 3, 252, 129, - 32, 42, 3, 252, 128, 32, 42, 3, 255, 164, 32, 42, 3, 252, 127, 32, 42, 3, - 252, 126, 32, 42, 3, 252, 125, 32, 42, 3, 252, 124, 32, 42, 3, 252, 123, - 32, 42, 3, 252, 122, 32, 42, 3, 252, 121, 32, 42, 3, 252, 120, 32, 42, 3, - 252, 119, 32, 42, 3, 252, 118, 32, 42, 3, 252, 117, 32, 42, 3, 252, 116, - 32, 42, 3, 252, 115, 32, 42, 3, 252, 114, 32, 42, 3, 252, 113, 32, 42, 3, - 252, 112, 32, 42, 3, 252, 111, 32, 42, 3, 252, 110, 32, 42, 3, 252, 109, - 32, 42, 3, 252, 108, 32, 42, 3, 252, 107, 32, 42, 3, 252, 106, 32, 42, 3, - 252, 105, 32, 42, 3, 252, 104, 32, 42, 3, 252, 103, 32, 42, 3, 252, 102, - 32, 42, 3, 252, 101, 32, 42, 3, 252, 100, 32, 42, 3, 252, 99, 32, 42, 3, - 252, 98, 32, 42, 3, 252, 97, 32, 42, 3, 252, 96, 32, 42, 3, 252, 95, 32, - 42, 3, 252, 94, 32, 42, 3, 252, 93, 32, 42, 3, 252, 92, 32, 42, 3, 252, - 91, 32, 42, 3, 252, 90, 32, 42, 3, 252, 89, 32, 42, 3, 252, 88, 32, 42, - 3, 252, 87, 32, 42, 3, 252, 86, 32, 42, 3, 252, 85, 32, 42, 3, 255, 77, - 32, 42, 3, 252, 84, 32, 42, 3, 252, 83, 32, 42, 3, 255, 42, 32, 42, 3, - 252, 82, 32, 42, 3, 252, 81, 32, 42, 3, 252, 80, 32, 42, 3, 252, 79, 32, - 42, 3, 255, 29, 32, 42, 3, 252, 78, 32, 42, 3, 252, 77, 32, 42, 3, 252, - 76, 32, 42, 3, 252, 75, 32, 42, 3, 252, 74, 32, 42, 3, 254, 101, 32, 42, - 3, 254, 100, 32, 42, 3, 254, 99, 32, 42, 3, 254, 98, 32, 42, 3, 254, 97, - 32, 42, 3, 254, 96, 32, 42, 3, 254, 95, 32, 42, 3, 254, 94, 32, 42, 3, - 254, 92, 32, 42, 3, 254, 91, 32, 42, 3, 254, 90, 32, 42, 3, 254, 89, 32, - 42, 3, 254, 88, 32, 42, 3, 254, 87, 32, 42, 3, 254, 85, 32, 42, 3, 254, - 84, 32, 42, 3, 254, 83, 32, 42, 3, 254, 82, 32, 42, 3, 254, 81, 32, 42, - 3, 254, 80, 32, 42, 3, 254, 79, 32, 42, 3, 254, 78, 32, 42, 3, 254, 77, - 32, 42, 3, 254, 76, 32, 42, 3, 254, 75, 32, 42, 3, 254, 74, 32, 42, 3, - 254, 73, 32, 42, 3, 254, 72, 32, 42, 3, 254, 71, 32, 42, 3, 254, 70, 32, - 42, 3, 254, 69, 32, 42, 3, 254, 68, 32, 42, 3, 254, 67, 32, 42, 3, 254, - 65, 32, 42, 3, 254, 64, 32, 42, 3, 254, 63, 32, 42, 3, 254, 59, 32, 42, - 3, 254, 58, 32, 42, 3, 254, 57, 32, 42, 3, 254, 56, 32, 42, 3, 254, 52, - 32, 42, 3, 254, 51, 32, 42, 3, 254, 50, 32, 42, 3, 254, 49, 32, 42, 3, - 254, 48, 32, 42, 3, 254, 47, 32, 42, 3, 254, 46, 32, 42, 3, 254, 45, 32, - 42, 3, 254, 44, 32, 42, 3, 254, 43, 32, 42, 3, 254, 42, 32, 42, 3, 254, - 41, 32, 42, 3, 254, 40, 32, 42, 3, 254, 39, 32, 42, 3, 254, 38, 32, 42, - 3, 254, 37, 32, 42, 3, 254, 36, 32, 42, 3, 254, 35, 32, 42, 3, 254, 34, - 32, 42, 3, 254, 33, 32, 42, 3, 254, 32, 32, 42, 3, 254, 31, 32, 42, 3, - 254, 30, 32, 42, 3, 254, 28, 32, 42, 3, 254, 27, 32, 42, 3, 254, 26, 32, - 42, 3, 254, 25, 32, 42, 3, 254, 24, 32, 42, 3, 254, 22, 32, 42, 3, 254, - 21, 32, 42, 3, 254, 20, 32, 42, 3, 254, 19, 32, 42, 3, 254, 17, 32, 42, - 3, 254, 16, 32, 42, 3, 254, 15, 32, 42, 3, 253, 237, 32, 42, 3, 253, 235, - 32, 42, 3, 253, 233, 32, 42, 3, 253, 231, 32, 42, 3, 253, 229, 32, 42, 3, - 253, 227, 32, 42, 3, 253, 225, 32, 42, 3, 253, 223, 32, 42, 3, 253, 221, - 32, 42, 3, 253, 219, 32, 42, 3, 253, 217, 32, 42, 3, 253, 214, 32, 42, 3, - 253, 212, 32, 42, 3, 253, 210, 32, 42, 3, 253, 208, 32, 42, 3, 253, 206, - 32, 42, 3, 253, 204, 32, 42, 3, 253, 202, 32, 42, 3, 253, 200, 32, 42, 3, - 253, 118, 32, 42, 3, 253, 117, 32, 42, 3, 253, 116, 32, 42, 3, 253, 115, - 32, 42, 3, 253, 114, 32, 42, 3, 253, 113, 32, 42, 3, 253, 111, 32, 42, 3, - 253, 110, 32, 42, 3, 253, 109, 32, 42, 3, 253, 108, 32, 42, 3, 253, 107, - 32, 42, 3, 253, 106, 32, 42, 3, 253, 104, 32, 42, 3, 253, 103, 32, 42, 3, - 253, 99, 32, 42, 3, 253, 98, 32, 42, 3, 253, 96, 32, 42, 3, 253, 95, 32, - 42, 3, 253, 94, 32, 42, 3, 253, 93, 32, 42, 3, 253, 92, 32, 42, 3, 253, - 91, 32, 42, 3, 253, 90, 32, 42, 3, 253, 89, 32, 42, 3, 253, 88, 32, 42, - 3, 253, 87, 32, 42, 3, 253, 86, 32, 42, 3, 253, 85, 32, 42, 3, 253, 84, - 32, 42, 3, 253, 83, 32, 42, 3, 253, 82, 32, 42, 3, 253, 81, 32, 42, 3, - 253, 80, 32, 42, 3, 253, 79, 32, 42, 3, 253, 78, 32, 42, 3, 253, 77, 32, - 42, 3, 253, 76, 32, 42, 3, 253, 75, 32, 42, 3, 253, 74, 32, 42, 3, 253, - 73, 32, 42, 3, 253, 72, 32, 42, 3, 253, 71, 32, 42, 3, 253, 70, 32, 42, - 3, 253, 69, 32, 42, 3, 253, 68, 32, 42, 3, 253, 67, 32, 42, 3, 253, 66, - 32, 42, 3, 253, 65, 32, 42, 3, 253, 64, 32, 42, 3, 253, 63, 32, 42, 3, - 253, 62, 32, 42, 3, 253, 61, 32, 42, 3, 253, 60, 32, 42, 3, 253, 59, 32, - 42, 3, 253, 58, 32, 42, 3, 253, 57, 32, 42, 3, 253, 56, 32, 42, 3, 253, - 55, 32, 42, 3, 253, 54, 32, 42, 3, 253, 53, 32, 42, 3, 253, 52, 32, 42, - 3, 253, 51, 32, 42, 3, 253, 50, 32, 42, 3, 253, 49, 32, 42, 3, 253, 48, - 32, 42, 3, 253, 47, 32, 42, 3, 253, 46, 32, 42, 3, 253, 45, 32, 42, 3, - 253, 44, 32, 42, 3, 253, 43, 32, 42, 3, 253, 42, 32, 42, 3, 253, 41, 32, - 42, 3, 253, 40, 32, 42, 3, 253, 39, 32, 42, 3, 253, 38, 32, 42, 3, 253, - 37, 32, 42, 3, 253, 36, 32, 42, 3, 253, 35, 32, 42, 3, 253, 34, 32, 42, - 3, 253, 33, 32, 42, 3, 253, 32, 32, 42, 3, 253, 31, 32, 42, 3, 253, 30, - 32, 42, 3, 253, 29, 32, 42, 3, 253, 28, 32, 42, 3, 253, 27, 32, 42, 3, - 253, 26, 32, 42, 3, 253, 25, 32, 42, 3, 253, 24, 32, 42, 3, 253, 23, 32, - 42, 3, 253, 22, 32, 42, 3, 253, 21, 32, 42, 3, 253, 20, 32, 42, 3, 253, - 19, 32, 42, 3, 253, 18, 32, 42, 3, 253, 17, 32, 42, 3, 253, 16, 32, 42, - 3, 253, 15, 32, 42, 3, 253, 14, 32, 42, 3, 253, 13, 32, 42, 3, 253, 12, - 32, 42, 3, 253, 11, 32, 42, 3, 253, 10, 32, 42, 3, 253, 9, 32, 42, 3, - 253, 8, 32, 42, 3, 253, 7, 32, 42, 3, 253, 6, 32, 42, 3, 253, 5, 32, 42, - 3, 253, 4, 32, 42, 3, 253, 3, 32, 42, 3, 253, 2, 32, 42, 3, 253, 1, 32, - 42, 3, 253, 0, 32, 42, 3, 252, 255, 32, 42, 3, 252, 254, 32, 42, 3, 252, - 253, 32, 42, 3, 252, 252, 32, 42, 3, 252, 251, 32, 42, 3, 252, 250, 32, - 42, 3, 252, 249, 32, 42, 3, 252, 248, 32, 42, 3, 252, 247, 32, 42, 3, - 252, 246, 32, 42, 3, 252, 245, 32, 42, 3, 252, 244, 32, 42, 3, 252, 243, - 32, 42, 3, 252, 242, 32, 42, 3, 252, 241, 32, 42, 3, 252, 240, 32, 42, 3, - 252, 239, 32, 42, 3, 252, 238, 32, 42, 3, 252, 237, 32, 42, 3, 252, 236, - 65, 32, 42, 3, 252, 235, 250, 120, 32, 42, 3, 252, 234, 238, 127, 32, 42, - 3, 252, 233, 71, 32, 42, 3, 252, 232, 233, 175, 32, 42, 3, 252, 231, 230, - 116, 32, 42, 3, 252, 230, 223, 35, 32, 42, 3, 252, 229, 222, 152, 32, 42, - 3, 252, 228, 172, 32, 42, 3, 252, 227, 220, 130, 32, 42, 3, 252, 226, - 220, 129, 32, 42, 3, 252, 225, 220, 128, 32, 42, 3, 252, 224, 220, 127, - 32, 42, 3, 252, 223, 193, 224, 32, 42, 3, 252, 222, 192, 235, 32, 42, 3, - 252, 221, 192, 159, 32, 42, 3, 252, 220, 211, 110, 32, 42, 3, 252, 219, - 252, 69, 32, 42, 3, 252, 218, 249, 54, 32, 42, 3, 252, 217, 237, 193, 32, - 42, 3, 252, 216, 233, 183, 32, 42, 3, 252, 215, 223, 10, 32, 42, 3, 252, - 214, 32, 42, 3, 252, 213, 32, 42, 3, 252, 212, 32, 42, 3, 252, 211, 32, - 42, 3, 252, 210, 32, 42, 3, 252, 209, 32, 42, 3, 252, 208, 32, 42, 3, - 252, 207, 52, 1, 2, 6, 252, 206, 52, 1, 200, 182, 197, 238, 242, 83, 52, - 1, 200, 182, 132, 197, 238, 242, 83, 52, 1, 2, 252, 25, 52, 1, 2, 6, 250, - 120, 52, 1, 2, 78, 4, 102, 52, 1, 2, 235, 37, 237, 2, 52, 1, 2, 235, 37, - 237, 3, 4, 207, 24, 102, 52, 1, 2, 235, 37, 237, 3, 4, 238, 175, 52, 1, - 2, 237, 70, 237, 2, 52, 1, 2, 238, 128, 4, 199, 215, 52, 1, 2, 238, 128, - 4, 102, 52, 1, 2, 238, 128, 4, 228, 251, 23, 199, 215, 52, 1, 2, 207, 18, - 71, 52, 1, 2, 242, 219, 207, 18, 211, 77, 71, 52, 1, 2, 233, 37, 237, 2, - 52, 1, 2, 207, 140, 228, 187, 52, 1, 2, 6, 232, 51, 52, 1, 2, 232, 52, 4, - 102, 52, 1, 2, 6, 232, 52, 4, 102, 52, 1, 2, 230, 117, 4, 106, 52, 1, 2, - 6, 230, 116, 52, 1, 2, 229, 197, 4, 102, 52, 1, 2, 236, 139, 223, 36, 4, - 201, 28, 23, 102, 52, 1, 2, 218, 227, 237, 2, 52, 1, 2, 218, 170, 237, 2, - 52, 1, 2, 220, 143, 4, 248, 231, 52, 1, 2, 6, 220, 143, 4, 248, 231, 52, - 1, 2, 220, 143, 4, 207, 24, 228, 251, 23, 248, 231, 52, 1, 2, 219, 162, - 52, 1, 2, 219, 163, 4, 207, 24, 102, 52, 1, 2, 153, 192, 159, 52, 1, 2, - 153, 192, 160, 4, 248, 231, 52, 1, 2, 187, 4, 106, 52, 1, 2, 6, 211, 151, - 52, 1, 2, 242, 219, 211, 110, 52, 1, 2, 208, 104, 52, 1, 2, 153, 207, - 222, 4, 179, 219, 212, 52, 1, 2, 153, 207, 222, 4, 179, 219, 213, 23, - 207, 24, 102, 52, 1, 2, 207, 222, 4, 199, 215, 52, 1, 2, 207, 222, 4, - 232, 233, 52, 1, 2, 6, 146, 52, 1, 2, 199, 152, 237, 3, 4, 238, 175, 52, - 1, 2, 197, 170, 237, 2, 52, 1, 2, 197, 170, 237, 3, 4, 207, 24, 102, 52, - 1, 2, 199, 79, 237, 2, 52, 1, 2, 200, 44, 4, 207, 24, 102, 52, 1, 2, 196, - 13, 4, 50, 102, 52, 1, 2, 6, 192, 159, 52, 1, 231, 11, 201, 64, 4, 106, - 52, 1, 207, 18, 231, 11, 201, 64, 4, 106, 52, 1, 248, 172, 242, 231, 52, - 1, 237, 98, 242, 231, 52, 1, 220, 3, 242, 231, 52, 1, 251, 150, 242, 231, - 52, 1, 207, 24, 242, 232, 4, 207, 24, 102, 52, 1, 2, 206, 9, 4, 238, 175, - 238, 135, 5, 65, 238, 135, 5, 71, 238, 135, 5, 68, 238, 135, 5, 74, 238, - 135, 5, 66, 238, 135, 5, 223, 32, 238, 135, 5, 222, 201, 238, 135, 5, - 155, 238, 135, 5, 222, 22, 238, 135, 5, 221, 166, 238, 135, 5, 221, 67, - 238, 135, 5, 220, 232, 238, 135, 5, 173, 238, 135, 5, 219, 238, 238, 135, - 5, 219, 146, 238, 135, 5, 219, 43, 238, 135, 5, 218, 225, 238, 135, 5, - 174, 238, 135, 5, 216, 232, 238, 135, 5, 216, 100, 238, 135, 5, 216, 12, - 238, 135, 5, 215, 155, 238, 135, 5, 180, 238, 135, 5, 214, 121, 238, 135, - 5, 213, 219, 238, 135, 5, 213, 43, 238, 135, 5, 212, 178, 238, 135, 5, - 168, 238, 135, 5, 210, 63, 238, 135, 5, 209, 185, 238, 135, 5, 209, 73, - 238, 135, 5, 208, 165, 238, 135, 5, 165, 238, 135, 5, 207, 113, 238, 135, - 5, 207, 1, 238, 135, 5, 206, 162, 238, 135, 5, 206, 68, 238, 135, 5, 188, - 238, 135, 5, 205, 68, 238, 135, 5, 202, 222, 238, 135, 5, 202, 46, 238, - 135, 5, 201, 4, 238, 135, 5, 190, 190, 238, 135, 5, 199, 145, 238, 135, - 5, 198, 193, 238, 135, 5, 159, 238, 135, 5, 197, 94, 238, 135, 5, 193, - 190, 238, 135, 5, 193, 125, 238, 135, 5, 193, 86, 238, 135, 5, 193, 48, - 238, 135, 5, 192, 220, 238, 135, 5, 192, 214, 238, 135, 5, 191, 123, 238, - 135, 5, 191, 7, 223, 164, 251, 18, 1, 251, 190, 223, 164, 251, 18, 1, - 248, 211, 223, 164, 251, 18, 1, 231, 38, 223, 164, 251, 18, 1, 237, 252, - 223, 164, 251, 18, 1, 229, 245, 223, 164, 251, 18, 1, 193, 133, 223, 164, - 251, 18, 1, 191, 91, 223, 164, 251, 18, 1, 229, 184, 223, 164, 251, 18, - 1, 199, 69, 223, 164, 251, 18, 1, 191, 249, 223, 164, 251, 18, 1, 222, - 75, 223, 164, 251, 18, 1, 220, 26, 223, 164, 251, 18, 1, 216, 193, 223, - 164, 251, 18, 1, 212, 130, 223, 164, 251, 18, 1, 205, 148, 223, 164, 251, - 18, 1, 250, 126, 223, 164, 251, 18, 1, 210, 63, 223, 164, 251, 18, 1, - 205, 189, 223, 164, 251, 18, 1, 208, 37, 223, 164, 251, 18, 1, 207, 38, - 223, 164, 251, 18, 1, 203, 69, 223, 164, 251, 18, 1, 199, 159, 223, 164, - 251, 18, 205, 54, 56, 223, 164, 251, 18, 31, 107, 223, 164, 251, 18, 31, - 109, 223, 164, 251, 18, 31, 138, 223, 164, 251, 18, 31, 199, 95, 223, - 164, 251, 18, 31, 197, 32, 223, 164, 251, 18, 31, 91, 228, 140, 223, 164, - 251, 18, 31, 91, 189, 223, 164, 251, 18, 31, 199, 96, 189, 210, 180, 1, - 251, 190, 210, 180, 1, 248, 211, 210, 180, 1, 231, 38, 210, 180, 1, 237, - 252, 210, 180, 1, 229, 245, 210, 180, 1, 193, 133, 210, 180, 1, 191, 91, - 210, 180, 1, 229, 184, 210, 180, 1, 199, 69, 210, 180, 1, 191, 249, 210, - 180, 1, 222, 75, 210, 180, 1, 220, 26, 210, 180, 1, 216, 193, 210, 180, - 1, 53, 212, 130, 210, 180, 1, 212, 130, 210, 180, 1, 205, 148, 210, 180, - 1, 250, 126, 210, 180, 1, 210, 63, 210, 180, 1, 205, 189, 210, 180, 1, - 208, 37, 210, 180, 1, 207, 38, 210, 180, 1, 203, 69, 210, 180, 1, 199, - 159, 210, 180, 219, 219, 232, 201, 210, 180, 206, 203, 232, 201, 210, - 180, 31, 107, 210, 180, 31, 109, 210, 180, 31, 138, 210, 180, 31, 134, - 210, 180, 31, 149, 210, 180, 31, 199, 95, 210, 180, 31, 197, 32, 214, - 246, 1, 53, 251, 190, 214, 246, 1, 251, 190, 214, 246, 1, 53, 248, 211, - 214, 246, 1, 248, 211, 214, 246, 1, 231, 38, 214, 246, 1, 237, 252, 214, - 246, 1, 53, 229, 245, 214, 246, 1, 229, 245, 214, 246, 1, 193, 133, 214, - 246, 1, 191, 91, 214, 246, 1, 229, 184, 214, 246, 1, 199, 69, 214, 246, - 1, 53, 191, 249, 214, 246, 1, 191, 249, 214, 246, 1, 53, 222, 75, 214, - 246, 1, 222, 75, 214, 246, 1, 53, 220, 26, 214, 246, 1, 220, 26, 214, - 246, 1, 53, 216, 193, 214, 246, 1, 216, 193, 214, 246, 1, 53, 212, 130, - 214, 246, 1, 212, 130, 214, 246, 1, 205, 148, 214, 246, 1, 250, 126, 214, - 246, 1, 210, 63, 214, 246, 1, 205, 189, 214, 246, 1, 208, 37, 214, 246, - 1, 207, 38, 214, 246, 1, 53, 203, 69, 214, 246, 1, 203, 69, 214, 246, 1, - 199, 159, 214, 246, 31, 107, 214, 246, 31, 109, 214, 246, 31, 138, 214, - 246, 31, 134, 214, 246, 238, 202, 31, 134, 214, 246, 31, 149, 214, 246, - 31, 199, 95, 214, 246, 31, 197, 32, 214, 246, 31, 91, 228, 140, 230, 4, - 1, 251, 190, 230, 4, 1, 248, 211, 230, 4, 1, 231, 38, 230, 4, 1, 237, - 251, 230, 4, 1, 229, 245, 230, 4, 1, 193, 133, 230, 4, 1, 191, 89, 230, - 4, 1, 229, 184, 230, 4, 1, 199, 69, 230, 4, 1, 191, 249, 230, 4, 1, 222, - 75, 230, 4, 1, 220, 26, 230, 4, 1, 216, 193, 230, 4, 1, 212, 130, 230, 4, - 1, 205, 148, 230, 4, 1, 250, 124, 230, 4, 1, 210, 63, 230, 4, 1, 205, - 189, 230, 4, 1, 208, 37, 230, 4, 1, 203, 69, 230, 4, 1, 199, 159, 230, 4, - 31, 107, 230, 4, 31, 149, 230, 4, 31, 199, 95, 230, 4, 31, 197, 32, 230, - 4, 31, 91, 228, 140, 209, 197, 1, 251, 187, 209, 197, 1, 248, 214, 209, - 197, 1, 231, 213, 209, 197, 1, 237, 108, 209, 197, 1, 229, 245, 209, 197, - 1, 193, 140, 209, 197, 1, 191, 115, 209, 197, 1, 229, 186, 209, 197, 1, - 199, 73, 209, 197, 1, 191, 250, 209, 197, 1, 222, 106, 209, 197, 1, 220, - 32, 209, 197, 1, 216, 193, 209, 197, 1, 212, 130, 209, 197, 1, 204, 19, - 209, 197, 1, 251, 230, 209, 197, 1, 210, 63, 209, 197, 1, 205, 191, 209, - 197, 1, 208, 42, 209, 197, 1, 206, 124, 209, 197, 1, 203, 69, 209, 197, - 1, 199, 166, 209, 197, 31, 107, 209, 197, 31, 199, 95, 209, 197, 31, 197, - 32, 209, 197, 31, 91, 228, 140, 209, 197, 31, 109, 209, 197, 31, 138, - 209, 197, 193, 23, 204, 10, 218, 180, 1, 65, 218, 180, 1, 250, 120, 218, - 180, 1, 232, 51, 218, 180, 1, 238, 127, 218, 180, 1, 71, 218, 180, 1, - 196, 12, 218, 180, 1, 68, 218, 180, 1, 192, 159, 218, 180, 1, 222, 152, - 218, 180, 1, 172, 218, 180, 1, 218, 168, 218, 180, 1, 215, 61, 218, 180, - 1, 74, 218, 180, 1, 146, 218, 180, 1, 201, 178, 218, 180, 1, 200, 43, - 218, 180, 1, 66, 218, 180, 1, 233, 175, 218, 180, 1, 208, 104, 218, 180, - 1, 206, 8, 218, 180, 1, 197, 135, 218, 180, 1, 251, 132, 218, 180, 1, - 234, 103, 218, 180, 1, 218, 183, 218, 180, 1, 213, 80, 218, 180, 1, 247, - 193, 218, 180, 197, 238, 77, 152, 229, 144, 1, 65, 152, 229, 144, 1, 71, - 152, 229, 144, 1, 68, 152, 229, 144, 1, 74, 152, 229, 144, 1, 170, 152, - 229, 144, 1, 193, 190, 152, 229, 144, 1, 249, 153, 152, 229, 144, 1, 249, - 152, 152, 229, 144, 1, 168, 152, 229, 144, 1, 174, 152, 229, 144, 1, 180, - 152, 229, 144, 1, 215, 5, 152, 229, 144, 1, 214, 121, 152, 229, 144, 1, - 214, 119, 152, 229, 144, 1, 165, 152, 229, 144, 1, 207, 184, 152, 229, - 144, 1, 173, 152, 229, 144, 1, 221, 215, 152, 229, 144, 1, 229, 177, 152, - 229, 144, 1, 188, 152, 229, 144, 1, 205, 205, 152, 229, 144, 1, 205, 68, - 152, 229, 144, 1, 155, 152, 229, 144, 1, 208, 96, 152, 229, 144, 1, 190, - 190, 152, 229, 144, 1, 199, 250, 152, 229, 144, 1, 199, 145, 152, 229, - 144, 1, 199, 143, 152, 229, 144, 1, 159, 152, 229, 144, 1, 238, 32, 152, - 229, 144, 16, 195, 63, 152, 229, 144, 16, 195, 62, 152, 238, 166, 1, 65, - 152, 238, 166, 1, 71, 152, 238, 166, 1, 68, 152, 238, 166, 1, 74, 152, - 238, 166, 1, 170, 152, 238, 166, 1, 193, 190, 152, 238, 166, 1, 249, 153, - 152, 238, 166, 1, 168, 152, 238, 166, 1, 174, 152, 238, 166, 1, 180, 152, - 238, 166, 1, 214, 121, 152, 238, 166, 1, 165, 152, 238, 166, 1, 173, 152, - 238, 166, 1, 221, 215, 152, 238, 166, 1, 229, 177, 152, 238, 166, 1, 188, - 152, 238, 166, 1, 251, 14, 188, 152, 238, 166, 1, 205, 68, 152, 238, 166, - 1, 155, 152, 238, 166, 1, 208, 96, 152, 238, 166, 1, 190, 190, 152, 238, - 166, 1, 199, 145, 152, 238, 166, 1, 159, 152, 238, 166, 1, 238, 32, 152, - 238, 166, 232, 118, 234, 128, 197, 39, 152, 238, 166, 232, 118, 91, 230, - 70, 152, 238, 166, 219, 28, 206, 168, 152, 238, 166, 219, 28, 223, 169, - 152, 238, 166, 31, 107, 152, 238, 166, 31, 109, 152, 238, 166, 31, 138, - 152, 238, 166, 31, 134, 152, 238, 166, 31, 149, 152, 238, 166, 31, 169, - 152, 238, 166, 31, 175, 152, 238, 166, 31, 171, 152, 238, 166, 31, 178, - 152, 238, 166, 31, 199, 95, 152, 238, 166, 31, 197, 32, 152, 238, 166, - 31, 198, 249, 152, 238, 166, 31, 232, 135, 152, 238, 166, 31, 233, 15, - 152, 238, 166, 31, 202, 120, 152, 238, 166, 31, 203, 241, 152, 238, 166, - 31, 91, 228, 140, 152, 238, 166, 31, 105, 228, 140, 152, 238, 166, 31, - 115, 228, 140, 152, 238, 166, 31, 232, 128, 228, 140, 152, 238, 166, 31, - 232, 226, 228, 140, 152, 238, 166, 31, 202, 136, 228, 140, 152, 238, 166, - 31, 203, 247, 228, 140, 152, 238, 166, 31, 234, 164, 228, 140, 152, 238, - 166, 31, 213, 175, 228, 140, 152, 238, 166, 31, 91, 189, 152, 238, 166, - 31, 105, 189, 152, 238, 166, 31, 115, 189, 152, 238, 166, 31, 232, 128, - 189, 152, 238, 166, 31, 232, 226, 189, 152, 238, 166, 31, 202, 136, 189, - 152, 238, 166, 31, 203, 247, 189, 152, 238, 166, 31, 234, 164, 189, 152, - 238, 166, 31, 213, 175, 189, 152, 238, 166, 31, 199, 96, 189, 152, 238, - 166, 31, 197, 33, 189, 152, 238, 166, 31, 198, 250, 189, 152, 238, 166, - 31, 232, 136, 189, 152, 238, 166, 31, 233, 16, 189, 152, 238, 166, 31, - 202, 121, 189, 152, 238, 166, 31, 203, 242, 189, 152, 238, 166, 31, 234, - 154, 189, 152, 238, 166, 31, 213, 170, 189, 152, 238, 166, 31, 91, 228, - 141, 189, 152, 238, 166, 31, 105, 228, 141, 189, 152, 238, 166, 31, 115, - 228, 141, 189, 152, 238, 166, 31, 232, 128, 228, 141, 189, 152, 238, 166, - 31, 232, 226, 228, 141, 189, 152, 238, 166, 31, 202, 136, 228, 141, 189, - 152, 238, 166, 31, 203, 247, 228, 141, 189, 152, 238, 166, 31, 234, 164, - 228, 141, 189, 152, 238, 166, 31, 213, 175, 228, 141, 189, 152, 238, 166, - 232, 118, 91, 197, 40, 152, 238, 166, 232, 118, 105, 197, 39, 152, 238, - 166, 232, 118, 115, 197, 39, 152, 238, 166, 232, 118, 232, 128, 197, 39, - 152, 238, 166, 232, 118, 232, 226, 197, 39, 152, 238, 166, 232, 118, 202, - 136, 197, 39, 152, 238, 166, 232, 118, 203, 247, 197, 39, 152, 238, 166, - 232, 118, 234, 164, 197, 39, 152, 238, 166, 232, 118, 213, 175, 197, 39, - 152, 238, 166, 232, 118, 199, 96, 197, 39, 221, 199, 1, 65, 221, 199, 18, - 3, 68, 221, 199, 18, 3, 66, 221, 199, 18, 3, 117, 146, 221, 199, 18, 3, - 71, 221, 199, 18, 3, 74, 221, 199, 18, 219, 198, 77, 221, 199, 3, 55, - 206, 189, 60, 221, 199, 3, 251, 71, 221, 199, 3, 195, 35, 221, 199, 1, - 155, 221, 199, 1, 221, 215, 221, 199, 1, 231, 240, 221, 199, 1, 231, 91, - 221, 199, 1, 247, 160, 221, 199, 1, 247, 1, 221, 199, 1, 223, 32, 221, - 199, 1, 212, 101, 221, 199, 1, 197, 132, 221, 199, 1, 197, 120, 221, 199, - 1, 237, 191, 221, 199, 1, 237, 175, 221, 199, 1, 213, 79, 221, 199, 1, - 190, 190, 221, 199, 1, 199, 49, 221, 199, 1, 238, 32, 221, 199, 1, 237, - 68, 221, 199, 1, 180, 221, 199, 1, 168, 221, 199, 1, 209, 228, 221, 199, - 1, 249, 153, 221, 199, 1, 248, 203, 221, 199, 1, 174, 221, 199, 1, 170, - 221, 199, 1, 165, 221, 199, 1, 173, 221, 199, 1, 195, 188, 221, 199, 1, - 203, 165, 221, 199, 1, 201, 175, 221, 199, 1, 188, 221, 199, 1, 191, 123, - 221, 199, 1, 140, 221, 199, 1, 221, 101, 221, 199, 1, 197, 100, 221, 199, - 1, 197, 101, 221, 199, 1, 195, 70, 221, 199, 3, 249, 88, 58, 221, 199, 3, - 247, 74, 221, 199, 3, 75, 60, 221, 199, 195, 40, 221, 199, 17, 107, 221, - 199, 17, 109, 221, 199, 17, 138, 221, 199, 17, 134, 221, 199, 31, 199, - 95, 221, 199, 31, 197, 32, 221, 199, 31, 91, 228, 140, 221, 199, 31, 91, - 189, 221, 199, 232, 118, 91, 230, 70, 221, 199, 208, 152, 236, 140, 221, - 199, 208, 152, 2, 243, 10, 221, 199, 208, 152, 243, 10, 221, 199, 208, - 152, 238, 228, 164, 221, 199, 208, 152, 217, 83, 221, 199, 208, 152, 218, - 246, 221, 199, 208, 152, 237, 238, 221, 199, 208, 152, 55, 237, 238, 221, - 199, 208, 152, 219, 106, 39, 202, 2, 251, 29, 1, 229, 245, 39, 202, 2, - 251, 29, 1, 220, 26, 39, 202, 2, 251, 29, 1, 229, 184, 39, 202, 2, 251, - 29, 1, 216, 193, 39, 202, 2, 251, 29, 1, 208, 37, 39, 202, 2, 251, 29, 1, - 193, 133, 39, 202, 2, 251, 29, 1, 203, 69, 39, 202, 2, 251, 29, 1, 207, - 38, 39, 202, 2, 251, 29, 1, 248, 211, 39, 202, 2, 251, 29, 1, 199, 159, - 39, 202, 2, 251, 29, 1, 205, 122, 39, 202, 2, 251, 29, 1, 222, 75, 39, - 202, 2, 251, 29, 1, 212, 130, 39, 202, 2, 251, 29, 1, 221, 194, 39, 202, - 2, 251, 29, 1, 205, 189, 39, 202, 2, 251, 29, 1, 205, 148, 39, 202, 2, - 251, 29, 1, 233, 59, 39, 202, 2, 251, 29, 1, 251, 192, 39, 202, 2, 251, - 29, 1, 250, 124, 39, 202, 2, 251, 29, 1, 237, 65, 39, 202, 2, 251, 29, 1, - 231, 38, 39, 202, 2, 251, 29, 1, 237, 252, 39, 202, 2, 251, 29, 1, 231, - 79, 39, 202, 2, 251, 29, 1, 199, 69, 39, 202, 2, 251, 29, 1, 191, 89, 39, - 202, 2, 251, 29, 1, 237, 62, 39, 202, 2, 251, 29, 1, 191, 249, 39, 202, - 2, 251, 29, 1, 199, 35, 39, 202, 2, 251, 29, 1, 199, 14, 39, 202, 2, 251, - 29, 31, 107, 39, 202, 2, 251, 29, 31, 233, 15, 39, 202, 2, 251, 29, 167, - 223, 144, 39, 186, 251, 29, 1, 229, 210, 39, 186, 251, 29, 1, 220, 35, - 39, 186, 251, 29, 1, 230, 81, 39, 186, 251, 29, 1, 216, 208, 39, 186, - 251, 29, 1, 208, 89, 39, 186, 251, 29, 1, 193, 133, 39, 186, 251, 29, 1, - 234, 20, 39, 186, 251, 29, 1, 207, 71, 39, 186, 251, 29, 1, 248, 245, 39, - 186, 251, 29, 1, 199, 114, 39, 186, 251, 29, 1, 234, 21, 39, 186, 251, - 29, 1, 222, 106, 39, 186, 251, 29, 1, 213, 24, 39, 186, 251, 29, 1, 221, - 210, 39, 186, 251, 29, 1, 205, 192, 39, 186, 251, 29, 1, 234, 19, 39, - 186, 251, 29, 1, 233, 46, 39, 186, 251, 29, 1, 251, 192, 39, 186, 251, - 29, 1, 251, 230, 39, 186, 251, 29, 1, 238, 26, 39, 186, 251, 29, 1, 231, - 156, 39, 186, 251, 29, 1, 238, 3, 39, 186, 251, 29, 1, 231, 86, 39, 186, - 251, 29, 1, 199, 219, 39, 186, 251, 29, 1, 191, 113, 39, 186, 251, 29, 1, - 199, 41, 39, 186, 251, 29, 1, 192, 75, 39, 186, 251, 29, 1, 199, 29, 39, - 186, 251, 29, 1, 191, 116, 39, 186, 251, 29, 31, 107, 39, 186, 251, 29, - 31, 199, 95, 39, 186, 251, 29, 31, 197, 32, 217, 81, 1, 251, 190, 217, - 81, 1, 248, 211, 217, 81, 1, 248, 194, 217, 81, 1, 231, 38, 217, 81, 1, - 231, 64, 217, 81, 1, 237, 252, 217, 81, 1, 229, 245, 217, 81, 1, 193, - 133, 217, 81, 3, 196, 158, 217, 81, 1, 191, 91, 217, 81, 1, 191, 64, 217, - 81, 1, 223, 12, 217, 81, 1, 222, 248, 217, 81, 1, 229, 184, 217, 81, 1, - 199, 69, 217, 81, 1, 191, 249, 217, 81, 1, 222, 75, 217, 81, 1, 192, 217, - 217, 81, 1, 221, 201, 217, 81, 1, 220, 26, 217, 81, 1, 237, 61, 217, 81, - 1, 199, 40, 217, 81, 1, 216, 193, 217, 81, 1, 212, 130, 217, 81, 1, 205, - 148, 217, 81, 1, 250, 126, 217, 81, 1, 252, 158, 217, 81, 1, 210, 63, - 217, 81, 1, 233, 59, 217, 81, 1, 205, 189, 217, 81, 1, 208, 37, 217, 81, - 1, 192, 193, 217, 81, 1, 208, 64, 217, 81, 1, 207, 38, 217, 81, 1, 203, - 69, 217, 81, 1, 201, 143, 217, 81, 1, 199, 159, 217, 81, 252, 68, 87, 58, - 217, 81, 252, 68, 87, 60, 217, 81, 31, 107, 217, 81, 31, 149, 217, 81, - 31, 199, 95, 217, 81, 31, 197, 32, 217, 81, 31, 91, 228, 140, 217, 81, - 208, 152, 201, 102, 217, 81, 208, 152, 232, 201, 217, 81, 208, 152, 55, - 75, 193, 53, 236, 140, 217, 81, 208, 152, 75, 193, 53, 236, 140, 217, 81, - 208, 152, 236, 140, 217, 81, 208, 152, 105, 236, 138, 217, 81, 208, 152, - 219, 113, 233, 3, 250, 142, 1, 65, 250, 142, 1, 252, 206, 250, 142, 1, - 251, 68, 250, 142, 1, 252, 164, 250, 142, 1, 251, 132, 250, 142, 1, 252, - 166, 250, 142, 1, 252, 25, 250, 142, 1, 252, 21, 250, 142, 1, 71, 250, - 142, 1, 234, 188, 250, 142, 1, 74, 250, 142, 1, 211, 87, 250, 142, 1, 68, - 250, 142, 1, 223, 199, 250, 142, 1, 66, 250, 142, 1, 196, 30, 250, 142, - 1, 222, 22, 250, 142, 1, 192, 214, 250, 142, 1, 192, 173, 250, 142, 1, - 192, 184, 250, 142, 1, 231, 165, 250, 142, 1, 231, 122, 250, 142, 1, 231, - 77, 250, 142, 1, 247, 42, 250, 142, 1, 223, 10, 250, 142, 1, 199, 145, - 250, 142, 1, 199, 33, 250, 142, 1, 237, 146, 250, 142, 1, 237, 59, 250, - 142, 1, 197, 127, 250, 142, 1, 210, 63, 250, 142, 1, 233, 59, 250, 142, - 1, 249, 17, 250, 142, 1, 248, 196, 250, 142, 1, 214, 55, 250, 142, 1, - 213, 226, 250, 142, 1, 213, 227, 250, 142, 1, 214, 121, 250, 142, 1, 212, - 90, 250, 142, 1, 213, 74, 250, 142, 1, 216, 232, 250, 142, 1, 229, 73, - 250, 142, 1, 191, 173, 250, 142, 1, 192, 80, 250, 142, 1, 195, 153, 250, - 142, 1, 207, 113, 250, 142, 1, 219, 238, 250, 142, 1, 205, 68, 250, 142, - 1, 191, 87, 250, 142, 1, 203, 113, 250, 142, 1, 191, 62, 250, 142, 1, - 202, 229, 250, 142, 1, 201, 144, 250, 142, 1, 229, 245, 250, 142, 252, - 68, 77, 198, 138, 105, 185, 139, 91, 75, 208, 151, 2, 105, 185, 139, 91, - 75, 208, 151, 220, 13, 105, 185, 139, 91, 75, 208, 151, 220, 13, 91, 75, - 139, 105, 185, 208, 151, 220, 13, 105, 206, 185, 139, 91, 206, 189, 208, - 151, 220, 13, 91, 206, 189, 139, 105, 206, 185, 208, 151, 223, 122, 210, - 106, 1, 251, 190, 223, 122, 210, 106, 1, 248, 211, 223, 122, 210, 106, 1, - 231, 38, 223, 122, 210, 106, 1, 237, 252, 223, 122, 210, 106, 1, 229, - 245, 223, 122, 210, 106, 1, 193, 133, 223, 122, 210, 106, 1, 191, 91, - 223, 122, 210, 106, 1, 229, 184, 223, 122, 210, 106, 1, 199, 69, 223, - 122, 210, 106, 1, 191, 249, 223, 122, 210, 106, 1, 222, 75, 223, 122, - 210, 106, 1, 220, 26, 223, 122, 210, 106, 1, 216, 193, 223, 122, 210, - 106, 1, 212, 130, 223, 122, 210, 106, 1, 205, 148, 223, 122, 210, 106, 1, - 250, 126, 223, 122, 210, 106, 1, 210, 63, 223, 122, 210, 106, 1, 205, - 189, 223, 122, 210, 106, 1, 208, 37, 223, 122, 210, 106, 1, 207, 38, 223, - 122, 210, 106, 1, 203, 69, 223, 122, 210, 106, 1, 199, 159, 223, 122, - 210, 106, 31, 107, 223, 122, 210, 106, 31, 109, 223, 122, 210, 106, 31, - 138, 223, 122, 210, 106, 31, 134, 223, 122, 210, 106, 31, 199, 95, 223, - 122, 210, 106, 31, 197, 32, 223, 122, 210, 106, 31, 91, 228, 140, 223, - 122, 210, 106, 31, 91, 189, 223, 122, 210, 199, 1, 251, 190, 223, 122, - 210, 199, 1, 248, 211, 223, 122, 210, 199, 1, 231, 38, 223, 122, 210, - 199, 1, 237, 252, 223, 122, 210, 199, 1, 229, 245, 223, 122, 210, 199, 1, - 193, 132, 223, 122, 210, 199, 1, 191, 91, 223, 122, 210, 199, 1, 229, - 184, 223, 122, 210, 199, 1, 199, 69, 223, 122, 210, 199, 1, 191, 249, - 223, 122, 210, 199, 1, 222, 75, 223, 122, 210, 199, 1, 220, 26, 223, 122, - 210, 199, 1, 216, 192, 223, 122, 210, 199, 1, 212, 130, 223, 122, 210, - 199, 1, 205, 148, 223, 122, 210, 199, 1, 210, 63, 223, 122, 210, 199, 1, - 205, 189, 223, 122, 210, 199, 1, 203, 69, 223, 122, 210, 199, 1, 199, - 159, 223, 122, 210, 199, 31, 107, 223, 122, 210, 199, 31, 109, 223, 122, - 210, 199, 31, 138, 223, 122, 210, 199, 31, 134, 223, 122, 210, 199, 31, - 199, 95, 223, 122, 210, 199, 31, 197, 32, 223, 122, 210, 199, 31, 91, - 228, 140, 223, 122, 210, 199, 31, 91, 189, 208, 177, 210, 199, 1, 251, - 190, 208, 177, 210, 199, 1, 248, 211, 208, 177, 210, 199, 1, 231, 38, - 208, 177, 210, 199, 1, 237, 252, 208, 177, 210, 199, 1, 229, 245, 208, - 177, 210, 199, 1, 193, 132, 208, 177, 210, 199, 1, 191, 91, 208, 177, - 210, 199, 1, 229, 184, 208, 177, 210, 199, 1, 191, 249, 208, 177, 210, - 199, 1, 222, 75, 208, 177, 210, 199, 1, 220, 26, 208, 177, 210, 199, 1, - 216, 192, 208, 177, 210, 199, 1, 212, 130, 208, 177, 210, 199, 1, 205, - 148, 208, 177, 210, 199, 1, 210, 63, 208, 177, 210, 199, 1, 205, 189, - 208, 177, 210, 199, 1, 203, 69, 208, 177, 210, 199, 1, 199, 159, 208, - 177, 210, 199, 205, 54, 77, 208, 177, 210, 199, 153, 205, 54, 77, 208, - 177, 210, 199, 232, 128, 185, 4, 238, 217, 208, 177, 210, 199, 232, 128, - 185, 4, 236, 140, 208, 177, 210, 199, 31, 107, 208, 177, 210, 199, 31, - 109, 208, 177, 210, 199, 31, 138, 208, 177, 210, 199, 31, 134, 208, 177, - 210, 199, 31, 199, 95, 208, 177, 210, 199, 31, 197, 32, 208, 177, 210, - 199, 31, 91, 228, 140, 39, 197, 61, 1, 211, 44, 65, 39, 197, 61, 1, 192, - 68, 65, 39, 197, 61, 1, 192, 68, 252, 25, 39, 197, 61, 1, 211, 44, 68, - 39, 197, 61, 1, 192, 68, 68, 39, 197, 61, 1, 192, 68, 71, 39, 197, 61, 1, - 211, 44, 74, 39, 197, 61, 1, 211, 44, 211, 151, 39, 197, 61, 1, 192, 68, - 211, 151, 39, 197, 61, 1, 211, 44, 252, 155, 39, 197, 61, 1, 192, 68, - 252, 155, 39, 197, 61, 1, 211, 44, 252, 24, 39, 197, 61, 1, 192, 68, 252, - 24, 39, 197, 61, 1, 211, 44, 251, 253, 39, 197, 61, 1, 192, 68, 251, 253, - 39, 197, 61, 1, 211, 44, 252, 19, 39, 197, 61, 1, 192, 68, 252, 19, 39, - 197, 61, 1, 211, 44, 252, 42, 39, 197, 61, 1, 192, 68, 252, 42, 39, 197, - 61, 1, 211, 44, 252, 23, 39, 197, 61, 1, 211, 44, 233, 182, 39, 197, 61, - 1, 192, 68, 233, 182, 39, 197, 61, 1, 211, 44, 250, 131, 39, 197, 61, 1, - 192, 68, 250, 131, 39, 197, 61, 1, 211, 44, 252, 6, 39, 197, 61, 1, 192, - 68, 252, 6, 39, 197, 61, 1, 211, 44, 252, 17, 39, 197, 61, 1, 192, 68, - 252, 17, 39, 197, 61, 1, 211, 44, 211, 149, 39, 197, 61, 1, 192, 68, 211, - 149, 39, 197, 61, 1, 211, 44, 251, 207, 39, 197, 61, 1, 192, 68, 251, - 207, 39, 197, 61, 1, 211, 44, 252, 16, 39, 197, 61, 1, 211, 44, 234, 118, - 39, 197, 61, 1, 211, 44, 234, 114, 39, 197, 61, 1, 211, 44, 251, 132, 39, - 197, 61, 1, 211, 44, 252, 14, 39, 197, 61, 1, 192, 68, 252, 14, 39, 197, - 61, 1, 211, 44, 234, 80, 39, 197, 61, 1, 192, 68, 234, 80, 39, 197, 61, - 1, 211, 44, 234, 100, 39, 197, 61, 1, 192, 68, 234, 100, 39, 197, 61, 1, - 211, 44, 234, 66, 39, 197, 61, 1, 192, 68, 234, 66, 39, 197, 61, 1, 192, - 68, 251, 122, 39, 197, 61, 1, 211, 44, 234, 88, 39, 197, 61, 1, 192, 68, - 252, 13, 39, 197, 61, 1, 211, 44, 234, 56, 39, 197, 61, 1, 211, 44, 211, - 78, 39, 197, 61, 1, 211, 44, 228, 28, 39, 197, 61, 1, 211, 44, 234, 197, - 39, 197, 61, 1, 192, 68, 234, 197, 39, 197, 61, 1, 211, 44, 251, 37, 39, - 197, 61, 1, 192, 68, 251, 37, 39, 197, 61, 1, 211, 44, 223, 79, 39, 197, - 61, 1, 192, 68, 223, 79, 39, 197, 61, 1, 211, 44, 211, 58, 39, 197, 61, - 1, 192, 68, 211, 58, 39, 197, 61, 1, 211, 44, 251, 33, 39, 197, 61, 1, - 192, 68, 251, 33, 39, 197, 61, 1, 211, 44, 252, 12, 39, 197, 61, 1, 211, - 44, 250, 219, 39, 197, 61, 1, 211, 44, 252, 10, 39, 197, 61, 1, 211, 44, - 250, 209, 39, 197, 61, 1, 192, 68, 250, 209, 39, 197, 61, 1, 211, 44, - 234, 12, 39, 197, 61, 1, 192, 68, 234, 12, 39, 197, 61, 1, 211, 44, 250, - 182, 39, 197, 61, 1, 192, 68, 250, 182, 39, 197, 61, 1, 211, 44, 252, 7, - 39, 197, 61, 1, 192, 68, 252, 7, 39, 197, 61, 1, 211, 44, 211, 30, 39, - 197, 61, 1, 211, 44, 249, 71, 39, 177, 6, 1, 65, 39, 177, 6, 1, 252, 206, - 39, 177, 6, 1, 234, 199, 39, 177, 6, 1, 251, 144, 39, 177, 6, 1, 234, - 197, 39, 177, 6, 1, 234, 100, 39, 177, 6, 1, 234, 193, 39, 177, 6, 1, - 234, 192, 39, 177, 6, 1, 251, 125, 39, 177, 6, 1, 71, 39, 177, 6, 1, 242, - 220, 71, 39, 177, 6, 1, 234, 188, 39, 177, 6, 1, 234, 181, 39, 177, 6, 1, - 234, 180, 39, 177, 6, 1, 234, 176, 39, 177, 6, 1, 234, 173, 39, 177, 6, - 1, 68, 39, 177, 6, 1, 223, 199, 39, 177, 6, 1, 234, 150, 39, 177, 6, 1, - 234, 147, 39, 177, 6, 1, 251, 216, 39, 177, 6, 1, 196, 86, 39, 177, 6, 1, - 234, 140, 39, 177, 6, 1, 234, 117, 39, 177, 6, 1, 234, 114, 39, 177, 6, - 1, 234, 103, 39, 177, 6, 1, 234, 66, 39, 177, 6, 1, 74, 39, 177, 6, 1, - 211, 87, 39, 177, 6, 1, 213, 182, 211, 151, 39, 177, 6, 1, 206, 58, 211, - 151, 39, 177, 6, 1, 211, 150, 39, 177, 6, 1, 234, 56, 39, 177, 6, 1, 234, - 108, 39, 177, 6, 1, 234, 34, 39, 177, 6, 1, 203, 40, 234, 34, 39, 177, 6, - 1, 234, 22, 39, 177, 6, 1, 234, 1, 39, 177, 6, 1, 233, 255, 39, 177, 6, - 1, 234, 80, 39, 177, 6, 1, 233, 243, 39, 177, 6, 1, 234, 195, 39, 177, 6, - 1, 66, 39, 177, 6, 1, 196, 30, 39, 177, 6, 1, 213, 182, 196, 152, 39, - 177, 6, 1, 206, 58, 196, 152, 39, 177, 6, 1, 233, 230, 39, 177, 6, 1, - 233, 182, 39, 177, 6, 1, 233, 177, 39, 177, 6, 1, 234, 79, 56, 39, 177, - 6, 1, 196, 45, 39, 177, 2, 1, 65, 39, 177, 2, 1, 252, 206, 39, 177, 2, 1, - 234, 199, 39, 177, 2, 1, 251, 144, 39, 177, 2, 1, 234, 197, 39, 177, 2, - 1, 234, 100, 39, 177, 2, 1, 234, 193, 39, 177, 2, 1, 234, 192, 39, 177, - 2, 1, 251, 125, 39, 177, 2, 1, 71, 39, 177, 2, 1, 242, 220, 71, 39, 177, - 2, 1, 234, 188, 39, 177, 2, 1, 234, 181, 39, 177, 2, 1, 234, 180, 39, - 177, 2, 1, 234, 176, 39, 177, 2, 1, 234, 173, 39, 177, 2, 1, 68, 39, 177, - 2, 1, 223, 199, 39, 177, 2, 1, 234, 150, 39, 177, 2, 1, 234, 147, 39, - 177, 2, 1, 251, 216, 39, 177, 2, 1, 196, 86, 39, 177, 2, 1, 234, 140, 39, - 177, 2, 1, 234, 117, 39, 177, 2, 1, 234, 114, 39, 177, 2, 1, 234, 103, - 39, 177, 2, 1, 234, 66, 39, 177, 2, 1, 74, 39, 177, 2, 1, 211, 87, 39, - 177, 2, 1, 213, 182, 211, 151, 39, 177, 2, 1, 206, 58, 211, 151, 39, 177, - 2, 1, 211, 150, 39, 177, 2, 1, 234, 56, 39, 177, 2, 1, 234, 108, 39, 177, - 2, 1, 234, 34, 39, 177, 2, 1, 203, 40, 234, 34, 39, 177, 2, 1, 234, 22, - 39, 177, 2, 1, 234, 1, 39, 177, 2, 1, 233, 255, 39, 177, 2, 1, 234, 80, - 39, 177, 2, 1, 233, 243, 39, 177, 2, 1, 234, 195, 39, 177, 2, 1, 66, 39, - 177, 2, 1, 196, 30, 39, 177, 2, 1, 213, 182, 196, 152, 39, 177, 2, 1, - 206, 58, 196, 152, 39, 177, 2, 1, 233, 230, 39, 177, 2, 1, 233, 182, 39, - 177, 2, 1, 233, 177, 39, 177, 2, 1, 234, 79, 56, 39, 177, 2, 1, 196, 45, - 39, 177, 31, 107, 39, 177, 31, 149, 39, 177, 31, 199, 95, 39, 177, 31, - 233, 15, 39, 177, 31, 91, 228, 140, 39, 177, 31, 91, 189, 230, 24, 206, - 142, 1, 65, 230, 24, 206, 142, 1, 249, 153, 230, 24, 206, 142, 1, 168, - 230, 24, 206, 142, 1, 190, 190, 230, 24, 206, 142, 1, 197, 132, 230, 24, - 206, 142, 1, 223, 32, 230, 24, 206, 142, 1, 247, 160, 230, 24, 206, 142, - 1, 140, 230, 24, 206, 142, 1, 221, 215, 230, 24, 206, 142, 1, 233, 109, - 230, 24, 206, 142, 1, 238, 32, 230, 24, 206, 142, 1, 237, 191, 230, 24, - 206, 142, 1, 165, 230, 24, 206, 142, 1, 206, 109, 230, 24, 206, 142, 1, - 191, 123, 230, 24, 206, 142, 1, 188, 230, 24, 206, 142, 1, 203, 165, 230, - 24, 206, 142, 1, 155, 230, 24, 206, 142, 1, 231, 240, 230, 24, 206, 142, - 1, 173, 230, 24, 206, 142, 1, 174, 230, 24, 206, 142, 1, 180, 230, 24, - 206, 142, 1, 193, 190, 230, 24, 206, 142, 1, 221, 137, 193, 190, 230, 24, - 206, 142, 1, 170, 230, 24, 206, 142, 1, 221, 137, 170, 230, 24, 206, 142, - 1, 214, 68, 230, 24, 206, 142, 1, 212, 101, 230, 24, 206, 142, 1, 195, - 188, 230, 24, 206, 142, 18, 65, 230, 24, 206, 142, 18, 68, 230, 24, 206, - 142, 18, 66, 230, 24, 206, 142, 18, 71, 230, 24, 206, 142, 18, 74, 230, - 24, 206, 142, 87, 205, 173, 230, 24, 206, 142, 87, 215, 7, 221, 178, 230, - 24, 206, 142, 3, 230, 18, 230, 24, 206, 142, 3, 199, 218, 230, 24, 206, - 142, 3, 199, 192, 230, 24, 206, 142, 3, 199, 172, 230, 24, 206, 142, 17, - 191, 77, 230, 24, 206, 142, 17, 107, 230, 24, 206, 142, 17, 109, 230, 24, - 206, 142, 17, 138, 230, 24, 206, 142, 17, 134, 230, 24, 206, 142, 17, - 149, 230, 24, 206, 142, 17, 169, 230, 24, 206, 142, 17, 175, 230, 24, - 206, 142, 17, 171, 230, 24, 206, 142, 17, 178, 206, 46, 17, 107, 206, 46, - 17, 109, 206, 46, 17, 138, 206, 46, 17, 134, 206, 46, 17, 149, 206, 46, - 17, 169, 206, 46, 17, 175, 206, 46, 17, 171, 206, 46, 17, 178, 206, 46, - 31, 199, 95, 206, 46, 31, 197, 32, 206, 46, 31, 198, 249, 206, 46, 31, - 232, 135, 206, 46, 31, 233, 15, 206, 46, 31, 202, 120, 206, 46, 31, 203, - 241, 206, 46, 31, 234, 153, 206, 46, 31, 213, 169, 206, 46, 31, 91, 228, - 140, 206, 46, 31, 105, 228, 140, 206, 46, 31, 115, 228, 140, 206, 46, 31, - 232, 128, 228, 140, 206, 46, 31, 232, 226, 228, 140, 206, 46, 31, 202, - 136, 228, 140, 206, 46, 31, 203, 247, 228, 140, 206, 46, 31, 234, 164, - 228, 140, 206, 46, 31, 213, 175, 228, 140, 206, 46, 232, 118, 91, 230, - 70, 206, 46, 232, 118, 91, 208, 22, 206, 46, 232, 118, 91, 199, 0, 206, - 46, 232, 118, 105, 198, 253, 192, 39, 1, 234, 124, 192, 39, 1, 249, 17, - 192, 39, 1, 210, 63, 192, 39, 1, 209, 214, 192, 39, 1, 199, 33, 192, 39, - 1, 205, 68, 192, 39, 1, 243, 16, 192, 39, 1, 243, 83, 192, 39, 1, 243, - 97, 192, 39, 1, 229, 177, 192, 39, 1, 192, 220, 192, 39, 1, 238, 3, 192, - 39, 1, 191, 108, 192, 39, 1, 165, 192, 39, 1, 207, 6, 192, 39, 1, 191, - 123, 192, 39, 1, 223, 32, 192, 39, 1, 202, 174, 192, 39, 1, 203, 69, 192, - 39, 1, 205, 192, 192, 39, 1, 238, 26, 192, 39, 1, 190, 190, 192, 39, 1, - 191, 87, 192, 39, 1, 233, 184, 192, 39, 1, 192, 208, 192, 39, 1, 233, - 109, 192, 39, 1, 195, 188, 192, 39, 1, 195, 189, 251, 157, 20, 192, 39, - 1, 208, 89, 192, 39, 1, 222, 106, 192, 39, 1, 221, 212, 192, 39, 1, 231, - 227, 192, 39, 1, 220, 35, 192, 39, 1, 216, 46, 192, 39, 1, 212, 130, 192, - 39, 1, 196, 120, 192, 39, 1, 193, 133, 192, 39, 1, 210, 250, 192, 39, 1, - 233, 224, 192, 39, 1, 229, 252, 192, 39, 1, 191, 240, 192, 39, 1, 233, - 255, 192, 39, 33, 230, 58, 77, 192, 39, 33, 217, 142, 77, 192, 39, 228, - 86, 77, 192, 39, 1, 220, 36, 4, 75, 58, 192, 39, 1, 191, 241, 4, 243, 2, - 58, 9, 2, 130, 193, 23, 205, 171, 9, 2, 130, 193, 23, 208, 79, 9, 2, 130, - 193, 23, 217, 141, 39, 202, 28, 1, 251, 190, 39, 202, 28, 1, 53, 251, - 190, 39, 202, 28, 1, 248, 211, 39, 202, 28, 1, 53, 248, 211, 39, 202, 28, - 1, 231, 38, 39, 202, 28, 1, 229, 245, 39, 202, 28, 1, 53, 229, 245, 39, - 202, 28, 1, 193, 133, 39, 202, 28, 1, 191, 91, 39, 202, 28, 1, 229, 184, - 39, 202, 28, 1, 191, 249, 39, 202, 28, 1, 222, 75, 39, 202, 28, 1, 220, - 26, 39, 202, 28, 1, 216, 193, 39, 202, 28, 1, 212, 130, 39, 202, 28, 1, - 53, 212, 130, 39, 202, 28, 1, 53, 212, 131, 4, 81, 199, 215, 39, 202, 28, - 1, 205, 148, 39, 202, 28, 1, 250, 126, 39, 202, 28, 1, 251, 157, 250, - 126, 39, 202, 28, 1, 210, 63, 39, 202, 28, 1, 205, 189, 39, 202, 28, 1, - 53, 205, 189, 39, 202, 28, 1, 53, 205, 190, 4, 81, 199, 215, 39, 202, 28, - 1, 207, 36, 39, 202, 28, 1, 203, 69, 39, 202, 28, 1, 199, 159, 39, 202, - 28, 1, 53, 199, 159, 39, 202, 28, 1, 53, 199, 160, 4, 81, 199, 215, 39, - 202, 28, 31, 107, 39, 202, 28, 31, 109, 39, 202, 28, 31, 138, 39, 202, - 28, 31, 134, 39, 202, 28, 31, 149, 39, 202, 28, 31, 199, 95, 39, 202, 28, - 31, 197, 32, 39, 202, 28, 31, 198, 249, 39, 202, 28, 31, 91, 228, 140, - 39, 202, 28, 232, 118, 91, 230, 70, 39, 202, 28, 34, 250, 125, 202, 28, - 1, 251, 190, 202, 28, 1, 248, 211, 202, 28, 1, 231, 38, 202, 28, 1, 229, - 245, 202, 28, 1, 193, 133, 202, 28, 1, 191, 91, 202, 28, 1, 229, 184, - 202, 28, 1, 191, 249, 202, 28, 1, 222, 75, 202, 28, 1, 220, 26, 202, 28, - 1, 216, 193, 202, 28, 1, 212, 130, 202, 28, 1, 205, 148, 202, 28, 1, 250, - 126, 202, 28, 1, 210, 63, 202, 28, 1, 205, 189, 202, 28, 1, 207, 37, 202, - 28, 1, 203, 69, 202, 28, 1, 199, 159, 202, 28, 1, 233, 30, 202, 28, 1, - 219, 182, 202, 28, 223, 149, 203, 69, 202, 28, 33, 75, 60, 202, 28, 33, - 105, 185, 60, 202, 28, 33, 75, 58, 202, 28, 33, 105, 185, 58, 202, 28, - 33, 238, 165, 58, 202, 28, 33, 238, 165, 60, 202, 28, 33, 228, 251, 58, - 202, 28, 33, 228, 251, 60, 202, 28, 33, 179, 228, 251, 60, 202, 28, 33, - 207, 39, 60, 202, 28, 33, 201, 28, 60, 202, 28, 31, 107, 202, 28, 31, - 199, 95, 202, 28, 31, 197, 32, 202, 28, 31, 91, 228, 140, 202, 28, 208, - 152, 105, 81, 249, 76, 202, 28, 208, 152, 105, 81, 249, 77, 4, 236, 138, - 202, 28, 208, 152, 243, 11, 4, 236, 140, 202, 28, 208, 152, 105, 243, 8, - 4, 236, 138, 202, 28, 208, 152, 132, 243, 11, 4, 236, 140, 39, 196, 19, - 1, 251, 190, 39, 196, 19, 1, 248, 211, 39, 196, 19, 1, 231, 37, 39, 196, - 19, 1, 193, 133, 39, 196, 19, 1, 191, 91, 39, 196, 19, 1, 53, 229, 184, - 39, 196, 19, 1, 191, 249, 39, 196, 19, 1, 222, 75, 39, 196, 19, 1, 220, - 26, 39, 196, 19, 1, 216, 193, 39, 196, 19, 1, 212, 130, 39, 196, 19, 1, - 205, 148, 39, 196, 19, 1, 210, 63, 39, 196, 19, 1, 205, 189, 39, 196, 19, - 1, 207, 38, 39, 196, 19, 1, 203, 69, 39, 196, 19, 1, 199, 159, 39, 196, - 19, 1, 219, 182, 39, 196, 19, 33, 75, 58, 39, 196, 19, 33, 75, 60, 39, - 196, 19, 33, 105, 185, 58, 39, 196, 19, 33, 105, 185, 60, 39, 196, 19, - 208, 152, 164, 39, 196, 19, 208, 152, 105, 249, 76, 39, 196, 19, 208, - 152, 105, 236, 138, 39, 196, 19, 208, 152, 232, 128, 236, 138, 243, 61, - 1, 251, 190, 243, 61, 1, 2, 251, 190, 243, 61, 1, 248, 211, 243, 61, 1, - 231, 38, 243, 61, 1, 237, 252, 243, 61, 1, 229, 245, 243, 61, 1, 193, - 133, 243, 61, 1, 238, 174, 193, 133, 243, 61, 1, 191, 91, 243, 61, 1, - 229, 184, 243, 61, 1, 191, 249, 243, 61, 1, 222, 75, 243, 61, 1, 220, 26, - 243, 61, 1, 216, 193, 243, 61, 1, 212, 130, 243, 61, 1, 205, 148, 243, - 61, 1, 250, 126, 243, 61, 1, 210, 63, 243, 61, 1, 207, 38, 243, 61, 1, - 203, 69, 243, 61, 1, 199, 159, 243, 61, 31, 107, 243, 61, 31, 109, 243, - 61, 31, 138, 243, 61, 31, 134, 243, 61, 31, 199, 95, 243, 61, 31, 197, - 32, 243, 61, 31, 91, 228, 140, 234, 116, 1, 251, 190, 234, 116, 1, 248, - 211, 234, 116, 1, 231, 38, 234, 116, 1, 237, 252, 234, 116, 1, 229, 245, - 234, 116, 1, 193, 133, 234, 116, 1, 191, 91, 234, 116, 1, 229, 184, 234, - 116, 1, 199, 69, 234, 116, 1, 191, 249, 234, 116, 1, 222, 75, 234, 116, - 1, 220, 26, 234, 116, 1, 216, 193, 234, 116, 1, 212, 130, 234, 116, 1, - 205, 148, 234, 116, 1, 250, 126, 234, 116, 1, 210, 63, 234, 116, 1, 205, - 189, 234, 116, 1, 208, 37, 234, 116, 1, 207, 38, 234, 116, 1, 203, 69, - 234, 116, 1, 199, 159, 234, 116, 34, 191, 90, 162, 3, 247, 119, 162, 3, - 251, 71, 162, 3, 195, 35, 162, 3, 222, 237, 162, 3, 196, 75, 162, 1, 65, - 162, 1, 252, 206, 162, 1, 68, 162, 1, 223, 199, 162, 1, 66, 162, 1, 196, - 30, 162, 1, 117, 146, 162, 1, 117, 206, 110, 162, 1, 117, 172, 162, 1, - 117, 219, 74, 162, 1, 71, 162, 1, 251, 236, 162, 1, 74, 162, 1, 250, 163, - 162, 1, 155, 162, 1, 221, 215, 162, 1, 231, 240, 162, 1, 231, 91, 162, 1, - 214, 68, 162, 1, 247, 160, 162, 1, 247, 1, 162, 1, 223, 32, 162, 1, 222, - 252, 162, 1, 212, 101, 162, 1, 197, 132, 162, 1, 197, 120, 162, 1, 237, - 191, 162, 1, 237, 175, 162, 1, 213, 79, 162, 1, 190, 190, 162, 1, 199, - 49, 162, 1, 238, 32, 162, 1, 237, 68, 162, 1, 180, 162, 1, 168, 162, 1, - 209, 228, 162, 1, 249, 153, 162, 1, 248, 203, 162, 1, 174, 162, 1, 170, - 162, 1, 165, 162, 1, 173, 162, 1, 195, 188, 162, 1, 203, 165, 162, 1, - 201, 175, 162, 1, 188, 162, 1, 140, 162, 1, 219, 73, 162, 1, 39, 44, 219, - 62, 162, 1, 39, 44, 206, 109, 162, 1, 39, 44, 213, 61, 162, 18, 3, 252, - 206, 162, 18, 3, 248, 197, 252, 206, 162, 18, 3, 68, 162, 18, 3, 223, - 199, 162, 18, 3, 66, 162, 18, 3, 196, 30, 162, 18, 3, 117, 146, 162, 18, - 3, 117, 206, 110, 162, 18, 3, 117, 172, 162, 18, 3, 117, 219, 74, 162, - 18, 3, 71, 162, 18, 3, 251, 236, 162, 18, 3, 74, 162, 18, 3, 250, 163, - 162, 195, 40, 162, 237, 238, 162, 55, 237, 238, 162, 208, 152, 236, 140, - 162, 208, 152, 55, 236, 140, 162, 208, 152, 219, 112, 162, 208, 152, 238, - 228, 164, 162, 208, 152, 218, 246, 162, 31, 107, 162, 31, 109, 162, 31, - 138, 162, 31, 134, 162, 31, 149, 162, 31, 169, 162, 31, 175, 162, 31, - 171, 162, 31, 178, 162, 31, 199, 95, 162, 31, 197, 32, 162, 31, 198, 249, - 162, 31, 232, 135, 162, 31, 233, 15, 162, 31, 202, 120, 162, 31, 203, - 241, 162, 31, 234, 153, 162, 31, 213, 169, 162, 31, 91, 228, 140, 162, - 31, 91, 189, 162, 17, 191, 77, 162, 17, 107, 162, 17, 109, 162, 17, 138, - 162, 17, 134, 162, 17, 149, 162, 17, 169, 162, 17, 175, 162, 17, 171, - 162, 17, 178, 162, 3, 39, 44, 195, 40, 162, 1, 39, 44, 203, 40, 71, 162, - 1, 39, 44, 203, 40, 74, 162, 18, 3, 39, 44, 203, 40, 71, 162, 18, 3, 39, - 44, 203, 40, 74, 162, 1, 39, 44, 219, 73, 162, 31, 222, 196, 222, 99, 3, - 247, 119, 222, 99, 3, 251, 71, 222, 99, 3, 195, 35, 222, 99, 1, 65, 222, - 99, 1, 252, 206, 222, 99, 1, 68, 222, 99, 1, 223, 199, 222, 99, 1, 66, - 222, 99, 1, 196, 30, 222, 99, 1, 71, 222, 99, 1, 251, 236, 222, 99, 1, - 74, 222, 99, 1, 250, 163, 222, 99, 1, 155, 222, 99, 1, 221, 215, 222, 99, - 1, 231, 240, 222, 99, 1, 231, 91, 222, 99, 1, 214, 68, 222, 99, 1, 247, - 160, 222, 99, 1, 247, 1, 222, 99, 1, 223, 32, 222, 99, 1, 222, 252, 222, - 99, 1, 212, 101, 222, 99, 1, 197, 132, 222, 99, 1, 197, 120, 222, 99, 1, - 237, 191, 222, 99, 1, 237, 180, 222, 99, 1, 237, 175, 222, 99, 1, 207, 6, - 222, 99, 1, 213, 79, 222, 99, 1, 190, 190, 222, 99, 1, 199, 49, 222, 99, - 1, 238, 32, 222, 99, 1, 237, 68, 222, 99, 1, 180, 222, 99, 1, 168, 222, - 99, 1, 209, 228, 222, 99, 1, 249, 153, 222, 99, 1, 248, 203, 222, 99, 1, - 174, 222, 99, 1, 170, 222, 99, 1, 165, 222, 99, 1, 173, 222, 99, 1, 195, - 188, 222, 99, 1, 203, 165, 222, 99, 1, 201, 175, 222, 99, 1, 188, 222, - 99, 1, 140, 222, 99, 18, 3, 252, 206, 222, 99, 18, 3, 68, 222, 99, 18, 3, - 223, 199, 222, 99, 18, 3, 66, 222, 99, 18, 3, 196, 30, 222, 99, 18, 3, - 71, 222, 99, 18, 3, 251, 236, 222, 99, 18, 3, 74, 222, 99, 18, 3, 250, - 163, 222, 99, 3, 195, 40, 222, 99, 3, 212, 141, 222, 99, 252, 68, 56, - 222, 99, 234, 69, 56, 222, 99, 31, 56, 222, 99, 205, 54, 77, 222, 99, 55, - 205, 54, 77, 222, 99, 237, 238, 222, 99, 55, 237, 238, 222, 99, 18, 3, - 117, 146, 222, 99, 31, 3, 58, 202, 12, 202, 20, 1, 205, 182, 202, 12, - 202, 20, 1, 199, 219, 202, 12, 202, 20, 1, 249, 123, 202, 12, 202, 20, 1, - 247, 149, 202, 12, 202, 20, 1, 238, 12, 202, 12, 202, 20, 1, 231, 225, - 202, 12, 202, 20, 1, 217, 120, 202, 12, 202, 20, 1, 214, 65, 202, 12, - 202, 20, 1, 220, 99, 202, 12, 202, 20, 1, 214, 237, 202, 12, 202, 20, 1, - 195, 184, 202, 12, 202, 20, 1, 210, 200, 202, 12, 202, 20, 1, 192, 121, - 202, 12, 202, 20, 1, 207, 160, 202, 12, 202, 20, 1, 230, 81, 202, 12, - 202, 20, 1, 222, 104, 202, 12, 202, 20, 1, 223, 26, 202, 12, 202, 20, 1, - 212, 98, 202, 12, 202, 20, 1, 251, 245, 202, 12, 202, 20, 1, 234, 186, - 202, 12, 202, 20, 1, 223, 200, 202, 12, 202, 20, 1, 196, 141, 202, 12, - 202, 20, 1, 211, 136, 202, 12, 202, 20, 1, 234, 173, 202, 12, 202, 20, 1, - 217, 136, 202, 12, 202, 20, 17, 191, 77, 202, 12, 202, 20, 17, 107, 202, - 12, 202, 20, 17, 109, 202, 12, 202, 20, 17, 138, 202, 12, 202, 20, 17, - 134, 202, 12, 202, 20, 17, 149, 202, 12, 202, 20, 17, 169, 202, 12, 202, - 20, 17, 175, 202, 12, 202, 20, 17, 171, 202, 12, 202, 20, 17, 178, 246, - 251, 3, 247, 119, 246, 251, 3, 251, 71, 246, 251, 3, 195, 35, 246, 251, - 1, 252, 206, 246, 251, 1, 68, 246, 251, 1, 66, 246, 251, 1, 71, 246, 251, - 1, 222, 127, 246, 251, 1, 221, 214, 246, 251, 1, 231, 237, 246, 251, 1, - 231, 90, 246, 251, 1, 214, 67, 246, 251, 1, 247, 159, 246, 251, 1, 247, - 0, 246, 251, 1, 223, 31, 246, 251, 1, 222, 251, 246, 251, 1, 212, 100, - 246, 251, 1, 197, 131, 246, 251, 1, 197, 119, 246, 251, 1, 237, 190, 246, - 251, 1, 237, 174, 246, 251, 1, 213, 78, 246, 251, 1, 199, 245, 246, 251, - 1, 199, 48, 246, 251, 1, 238, 31, 246, 251, 1, 237, 67, 246, 251, 1, 214, - 250, 246, 251, 1, 210, 220, 246, 251, 1, 209, 227, 246, 251, 1, 249, 151, - 246, 251, 1, 248, 202, 246, 251, 1, 217, 151, 246, 251, 1, 191, 174, 246, - 251, 1, 192, 140, 246, 251, 1, 207, 178, 246, 251, 1, 220, 125, 246, 251, - 1, 193, 181, 246, 251, 1, 205, 197, 246, 251, 1, 230, 91, 246, 251, 18, - 3, 65, 246, 251, 18, 3, 68, 246, 251, 18, 3, 223, 199, 246, 251, 18, 3, - 66, 246, 251, 18, 3, 196, 30, 246, 251, 18, 3, 71, 246, 251, 18, 3, 251, - 236, 246, 251, 18, 3, 74, 246, 251, 18, 3, 250, 163, 246, 251, 18, 3, - 211, 133, 246, 251, 187, 77, 246, 251, 250, 164, 77, 246, 251, 195, 40, - 246, 251, 217, 149, 246, 251, 17, 191, 77, 246, 251, 17, 107, 246, 251, - 17, 109, 246, 251, 17, 138, 246, 251, 17, 134, 246, 251, 17, 149, 246, - 251, 17, 169, 246, 251, 17, 175, 246, 251, 17, 171, 246, 251, 17, 178, - 246, 251, 205, 54, 77, 246, 251, 237, 238, 246, 251, 55, 237, 238, 246, - 251, 208, 13, 77, 246, 251, 1, 219, 158, 246, 251, 18, 3, 252, 206, 246, - 251, 18, 3, 234, 166, 246, 251, 1, 195, 187, 217, 118, 1, 65, 217, 118, - 1, 68, 217, 118, 1, 66, 217, 118, 1, 71, 217, 118, 1, 74, 217, 118, 1, - 155, 217, 118, 1, 221, 215, 217, 118, 1, 231, 240, 217, 118, 1, 231, 91, - 217, 118, 1, 247, 160, 217, 118, 1, 247, 1, 217, 118, 1, 223, 32, 217, - 118, 1, 222, 252, 217, 118, 1, 212, 101, 217, 118, 1, 197, 132, 217, 118, - 1, 197, 120, 217, 118, 1, 237, 191, 217, 118, 1, 237, 175, 217, 118, 1, - 213, 79, 217, 118, 1, 190, 190, 217, 118, 1, 199, 49, 217, 118, 1, 238, - 32, 217, 118, 1, 237, 68, 217, 118, 1, 180, 217, 118, 1, 168, 217, 118, - 1, 209, 228, 217, 118, 1, 249, 153, 217, 118, 1, 248, 203, 217, 118, 1, - 174, 217, 118, 1, 165, 217, 118, 1, 173, 217, 118, 1, 195, 188, 217, 118, - 1, 188, 217, 118, 1, 140, 217, 118, 1, 206, 109, 217, 118, 3, 212, 141, - 217, 118, 252, 68, 56, 217, 118, 205, 54, 77, 217, 118, 34, 203, 15, 203, - 129, 3, 247, 119, 203, 129, 3, 251, 71, 203, 129, 3, 195, 35, 203, 129, - 1, 65, 203, 129, 1, 252, 206, 203, 129, 1, 68, 203, 129, 1, 223, 199, - 203, 129, 1, 66, 203, 129, 1, 196, 30, 203, 129, 1, 117, 146, 203, 129, - 1, 117, 206, 110, 203, 129, 1, 117, 172, 203, 129, 1, 117, 219, 74, 203, - 129, 1, 71, 203, 129, 1, 251, 236, 203, 129, 1, 74, 203, 129, 1, 250, - 163, 203, 129, 1, 155, 203, 129, 1, 221, 215, 203, 129, 1, 231, 240, 203, - 129, 1, 231, 91, 203, 129, 1, 214, 68, 203, 129, 1, 247, 160, 203, 129, - 1, 247, 1, 203, 129, 1, 223, 32, 203, 129, 1, 222, 252, 203, 129, 1, 212, - 101, 203, 129, 1, 197, 132, 203, 129, 1, 197, 120, 203, 129, 1, 237, 191, - 203, 129, 1, 237, 175, 203, 129, 1, 213, 79, 203, 129, 1, 190, 190, 203, - 129, 1, 199, 49, 203, 129, 1, 238, 32, 203, 129, 1, 237, 68, 203, 129, 1, - 180, 203, 129, 1, 168, 203, 129, 1, 209, 228, 203, 129, 1, 249, 153, 203, - 129, 1, 248, 203, 203, 129, 1, 174, 203, 129, 1, 170, 203, 129, 1, 165, - 203, 129, 1, 173, 203, 129, 1, 219, 73, 203, 129, 1, 195, 188, 203, 129, - 1, 203, 165, 203, 129, 1, 201, 175, 203, 129, 1, 188, 203, 129, 1, 140, - 203, 129, 18, 3, 252, 206, 203, 129, 18, 3, 68, 203, 129, 18, 3, 223, - 199, 203, 129, 18, 3, 66, 203, 129, 18, 3, 196, 30, 203, 129, 18, 3, 117, - 146, 203, 129, 18, 3, 117, 206, 110, 203, 129, 18, 3, 117, 172, 203, 129, - 18, 3, 117, 219, 74, 203, 129, 18, 3, 71, 203, 129, 18, 3, 251, 236, 203, - 129, 18, 3, 74, 203, 129, 18, 3, 250, 163, 203, 129, 3, 195, 40, 203, - 129, 3, 250, 145, 203, 129, 3, 222, 237, 203, 129, 3, 196, 75, 203, 129, - 211, 113, 203, 129, 237, 238, 203, 129, 55, 237, 238, 203, 129, 252, 68, - 56, 203, 129, 204, 10, 203, 129, 205, 138, 77, 203, 129, 3, 212, 141, - 203, 129, 18, 52, 77, 203, 129, 233, 201, 203, 40, 18, 77, 203, 129, 200, - 162, 77, 203, 129, 18, 3, 208, 207, 71, 203, 129, 3, 223, 93, 247, 119, - 203, 129, 17, 191, 77, 203, 129, 17, 107, 203, 129, 17, 109, 203, 129, - 17, 138, 203, 129, 17, 134, 203, 129, 17, 149, 203, 129, 17, 169, 203, - 129, 17, 175, 203, 129, 17, 171, 203, 129, 17, 178, 203, 129, 234, 146, - 203, 129, 3, 202, 210, 203, 129, 229, 227, 203, 129, 239, 29, 56, 203, - 129, 205, 54, 217, 55, 203, 129, 205, 54, 217, 54, 166, 251, 14, 17, 107, - 166, 251, 14, 17, 109, 166, 251, 14, 17, 138, 166, 251, 14, 17, 134, 166, - 251, 14, 17, 149, 166, 251, 14, 17, 169, 166, 251, 14, 17, 175, 166, 251, - 14, 17, 171, 166, 251, 14, 17, 178, 166, 251, 14, 31, 199, 95, 166, 251, - 14, 31, 197, 32, 166, 251, 14, 31, 198, 249, 166, 251, 14, 31, 232, 135, - 166, 251, 14, 31, 233, 15, 166, 251, 14, 31, 202, 120, 166, 251, 14, 31, - 203, 241, 166, 251, 14, 31, 234, 153, 166, 251, 14, 31, 213, 169, 166, - 251, 14, 31, 91, 228, 140, 166, 251, 14, 31, 91, 189, 221, 182, 1, 65, - 221, 182, 1, 252, 206, 221, 182, 1, 68, 221, 182, 1, 66, 221, 182, 1, 71, - 221, 182, 1, 251, 236, 221, 182, 1, 74, 221, 182, 1, 250, 163, 221, 182, - 1, 155, 221, 182, 1, 221, 215, 221, 182, 1, 231, 240, 221, 182, 1, 231, - 127, 221, 182, 1, 231, 91, 221, 182, 1, 214, 68, 221, 182, 1, 247, 160, - 221, 182, 1, 247, 1, 221, 182, 1, 223, 32, 221, 182, 1, 222, 230, 221, - 182, 1, 212, 101, 221, 182, 1, 197, 132, 221, 182, 1, 197, 120, 221, 182, - 1, 237, 191, 221, 182, 1, 237, 175, 221, 182, 1, 213, 79, 221, 182, 1, - 190, 190, 221, 182, 1, 199, 49, 221, 182, 1, 238, 32, 221, 182, 1, 237, - 181, 221, 182, 1, 237, 68, 221, 182, 1, 180, 221, 182, 1, 168, 221, 182, - 1, 209, 228, 221, 182, 1, 249, 153, 221, 182, 1, 249, 53, 221, 182, 1, - 248, 203, 221, 182, 1, 174, 221, 182, 1, 170, 221, 182, 1, 165, 221, 182, - 1, 173, 221, 182, 1, 195, 188, 221, 182, 1, 188, 221, 182, 1, 140, 221, - 182, 1, 219, 73, 221, 182, 18, 3, 252, 206, 221, 182, 18, 3, 68, 221, - 182, 18, 3, 223, 199, 221, 182, 18, 3, 66, 221, 182, 18, 3, 71, 221, 182, - 18, 3, 251, 236, 221, 182, 18, 3, 74, 221, 182, 18, 3, 250, 163, 221, - 182, 3, 251, 71, 221, 182, 3, 195, 40, 221, 182, 3, 212, 141, 221, 182, - 3, 203, 155, 221, 182, 237, 238, 221, 182, 55, 237, 238, 221, 182, 193, - 23, 204, 10, 221, 182, 205, 54, 77, 221, 182, 55, 205, 54, 77, 221, 182, - 252, 68, 56, 221, 182, 3, 200, 206, 221, 182, 1, 208, 96, 221, 182, 1, - 203, 40, 68, 221, 182, 18, 3, 117, 146, 215, 133, 1, 65, 215, 133, 1, 68, - 215, 133, 1, 66, 215, 133, 1, 71, 215, 133, 1, 155, 215, 133, 1, 221, - 215, 215, 133, 1, 231, 240, 215, 133, 1, 231, 91, 215, 133, 1, 247, 160, - 215, 133, 1, 247, 1, 215, 133, 1, 223, 32, 215, 133, 1, 222, 230, 215, - 133, 1, 212, 101, 215, 133, 1, 197, 132, 215, 133, 1, 197, 120, 215, 133, - 1, 237, 191, 215, 133, 1, 237, 181, 215, 133, 1, 237, 175, 215, 133, 1, - 213, 79, 215, 133, 1, 190, 190, 215, 133, 1, 199, 49, 215, 133, 1, 238, - 32, 215, 133, 1, 237, 68, 215, 133, 1, 180, 215, 133, 1, 168, 215, 133, - 1, 209, 228, 215, 133, 1, 249, 153, 215, 133, 1, 248, 203, 215, 133, 1, - 174, 215, 133, 1, 170, 215, 133, 1, 165, 215, 133, 1, 173, 215, 133, 1, - 195, 188, 215, 133, 1, 188, 215, 133, 1, 140, 215, 133, 1, 206, 109, 215, - 133, 1, 207, 6, 215, 133, 205, 54, 77, 221, 172, 1, 65, 221, 172, 1, 252, - 206, 221, 172, 1, 68, 221, 172, 1, 223, 199, 221, 172, 1, 66, 221, 172, - 1, 196, 30, 221, 172, 1, 71, 221, 172, 1, 251, 236, 221, 172, 1, 74, 221, - 172, 1, 250, 163, 221, 172, 1, 155, 221, 172, 1, 221, 215, 221, 172, 1, - 231, 240, 221, 172, 1, 231, 127, 221, 172, 1, 231, 91, 221, 172, 1, 214, - 68, 221, 172, 1, 247, 160, 221, 172, 1, 247, 1, 221, 172, 1, 223, 32, - 221, 172, 1, 222, 230, 221, 172, 1, 222, 252, 221, 172, 1, 212, 101, 221, - 172, 1, 197, 132, 221, 172, 1, 197, 120, 221, 172, 1, 237, 191, 221, 172, - 1, 237, 181, 221, 172, 1, 206, 109, 221, 172, 1, 237, 175, 221, 172, 1, - 213, 79, 221, 172, 1, 190, 190, 221, 172, 1, 199, 49, 221, 172, 1, 238, - 32, 221, 172, 1, 237, 68, 221, 172, 1, 180, 221, 172, 1, 168, 221, 172, - 1, 209, 228, 221, 172, 1, 249, 153, 221, 172, 1, 249, 53, 221, 172, 1, - 248, 203, 221, 172, 1, 174, 221, 172, 1, 170, 221, 172, 1, 165, 221, 172, - 1, 173, 221, 172, 1, 195, 188, 221, 172, 1, 203, 165, 221, 172, 1, 188, - 221, 172, 1, 140, 221, 172, 3, 251, 71, 221, 172, 18, 3, 252, 206, 221, - 172, 18, 3, 68, 221, 172, 18, 3, 223, 199, 221, 172, 18, 3, 66, 221, 172, - 18, 3, 196, 30, 221, 172, 18, 3, 71, 221, 172, 18, 3, 251, 236, 221, 172, - 18, 3, 74, 221, 172, 18, 3, 250, 163, 221, 172, 3, 212, 141, 221, 172, 3, - 195, 40, 221, 172, 17, 191, 77, 221, 172, 17, 107, 221, 172, 17, 109, - 221, 172, 17, 138, 221, 172, 17, 134, 221, 172, 17, 149, 221, 172, 17, - 169, 221, 172, 17, 175, 221, 172, 17, 171, 221, 172, 17, 178, 230, 219, - 3, 33, 251, 72, 58, 230, 219, 3, 247, 119, 230, 219, 3, 251, 71, 230, - 219, 3, 195, 35, 230, 219, 1, 65, 230, 219, 1, 252, 206, 230, 219, 1, 68, - 230, 219, 1, 223, 199, 230, 219, 1, 66, 230, 219, 1, 196, 30, 230, 219, - 1, 117, 146, 230, 219, 1, 117, 172, 230, 219, 1, 234, 188, 230, 219, 1, - 251, 236, 230, 219, 1, 211, 87, 230, 219, 1, 250, 163, 230, 219, 1, 155, - 230, 219, 1, 221, 215, 230, 219, 1, 231, 240, 230, 219, 1, 231, 91, 230, - 219, 1, 214, 68, 230, 219, 1, 247, 160, 230, 219, 1, 247, 1, 230, 219, 1, - 223, 32, 230, 219, 1, 222, 252, 230, 219, 1, 212, 101, 230, 219, 1, 197, - 132, 230, 219, 1, 197, 120, 230, 219, 1, 237, 191, 230, 219, 1, 237, 175, - 230, 219, 1, 213, 79, 230, 219, 1, 190, 190, 230, 219, 1, 199, 49, 230, - 219, 1, 238, 32, 230, 219, 1, 237, 68, 230, 219, 1, 180, 230, 219, 1, - 168, 230, 219, 1, 209, 228, 230, 219, 1, 249, 153, 230, 219, 1, 248, 203, - 230, 219, 1, 174, 230, 219, 1, 170, 230, 219, 1, 165, 230, 219, 1, 173, - 230, 219, 1, 219, 73, 230, 219, 1, 195, 188, 230, 219, 1, 203, 165, 230, - 219, 1, 201, 175, 230, 219, 1, 188, 230, 219, 1, 140, 33, 248, 165, 60, - 230, 219, 3, 212, 141, 230, 219, 3, 250, 145, 230, 219, 18, 3, 252, 206, - 230, 219, 18, 3, 68, 230, 219, 18, 3, 223, 199, 230, 219, 18, 3, 66, 230, - 219, 18, 3, 196, 30, 230, 219, 18, 3, 117, 146, 230, 219, 18, 3, 117, - 206, 110, 230, 219, 18, 3, 234, 188, 230, 219, 18, 3, 251, 236, 230, 219, - 18, 3, 211, 87, 230, 219, 18, 3, 250, 163, 230, 219, 3, 195, 40, 230, - 219, 211, 113, 230, 219, 250, 164, 219, 198, 77, 230, 219, 3, 209, 79, - 230, 219, 1, 195, 150, 251, 71, 230, 219, 1, 195, 150, 55, 251, 71, 230, - 219, 1, 117, 206, 110, 230, 219, 1, 117, 219, 74, 230, 219, 18, 3, 117, - 172, 230, 219, 18, 3, 117, 219, 74, 33, 230, 219, 17, 191, 77, 33, 230, - 219, 17, 107, 33, 230, 219, 17, 109, 33, 230, 219, 17, 138, 33, 230, 219, - 17, 134, 33, 230, 219, 17, 149, 33, 230, 219, 17, 169, 33, 230, 219, 1, - 65, 33, 230, 219, 1, 155, 33, 230, 219, 1, 180, 33, 230, 219, 1, 195, 69, - 33, 230, 219, 1, 168, 214, 78, 1, 65, 214, 78, 1, 252, 206, 214, 78, 1, - 68, 214, 78, 1, 223, 199, 214, 78, 1, 66, 214, 78, 1, 196, 30, 214, 78, - 1, 117, 146, 214, 78, 1, 117, 206, 110, 214, 78, 1, 117, 172, 214, 78, 1, - 117, 219, 74, 214, 78, 1, 71, 214, 78, 1, 251, 236, 214, 78, 1, 74, 214, - 78, 1, 250, 163, 214, 78, 1, 155, 214, 78, 1, 221, 215, 214, 78, 1, 231, - 240, 214, 78, 1, 231, 91, 214, 78, 1, 214, 68, 214, 78, 1, 214, 17, 214, - 78, 1, 247, 160, 214, 78, 1, 247, 1, 214, 78, 1, 223, 32, 214, 78, 1, - 222, 252, 214, 78, 1, 212, 101, 214, 78, 1, 212, 83, 214, 78, 1, 197, - 132, 214, 78, 1, 197, 120, 214, 78, 1, 237, 191, 214, 78, 1, 237, 175, - 214, 78, 1, 213, 79, 214, 78, 1, 190, 190, 214, 78, 1, 199, 49, 214, 78, - 1, 238, 32, 214, 78, 1, 237, 68, 214, 78, 1, 180, 214, 78, 1, 213, 224, - 214, 78, 1, 168, 214, 78, 1, 209, 228, 214, 78, 1, 249, 153, 214, 78, 1, - 248, 203, 214, 78, 1, 174, 214, 78, 1, 216, 103, 214, 78, 1, 170, 214, - 78, 1, 165, 214, 78, 1, 207, 6, 214, 78, 1, 173, 214, 78, 1, 219, 159, - 214, 78, 1, 193, 190, 214, 78, 1, 203, 165, 214, 78, 1, 201, 175, 214, - 78, 1, 188, 214, 78, 1, 140, 214, 78, 18, 3, 252, 206, 214, 78, 18, 3, - 68, 214, 78, 18, 3, 223, 199, 214, 78, 18, 3, 66, 214, 78, 18, 3, 196, - 30, 214, 78, 18, 3, 117, 146, 214, 78, 18, 3, 117, 206, 110, 214, 78, 18, - 3, 117, 172, 214, 78, 18, 3, 117, 219, 74, 214, 78, 18, 3, 71, 214, 78, - 18, 3, 251, 236, 214, 78, 18, 3, 74, 214, 78, 18, 3, 250, 163, 214, 78, - 3, 195, 40, 214, 78, 3, 247, 119, 214, 78, 3, 251, 71, 214, 78, 3, 195, - 35, 214, 78, 3, 212, 141, 214, 78, 3, 250, 145, 214, 78, 3, 53, 251, 71, - 214, 78, 211, 113, 214, 78, 202, 209, 214, 78, 237, 238, 214, 78, 55, - 237, 238, 214, 78, 242, 74, 214, 78, 231, 204, 233, 3, 214, 78, 252, 68, - 56, 214, 78, 17, 191, 77, 214, 78, 17, 107, 214, 78, 17, 109, 214, 78, - 17, 138, 214, 78, 17, 134, 214, 78, 17, 149, 214, 78, 17, 169, 214, 78, - 17, 175, 214, 78, 17, 171, 214, 78, 17, 178, 214, 78, 55, 242, 74, 214, - 78, 209, 107, 77, 214, 78, 223, 119, 56, 214, 78, 205, 138, 77, 214, 78, - 1, 195, 150, 251, 71, 214, 78, 3, 222, 237, 214, 78, 3, 196, 75, 198, - 129, 251, 100, 198, 129, 1, 65, 198, 129, 1, 252, 206, 198, 129, 1, 68, - 198, 129, 1, 223, 199, 198, 129, 1, 66, 198, 129, 1, 196, 30, 198, 129, - 1, 117, 146, 198, 129, 1, 117, 206, 110, 198, 129, 1, 117, 172, 198, 129, - 1, 117, 219, 74, 198, 129, 1, 71, 198, 129, 1, 251, 236, 198, 129, 1, 74, - 198, 129, 1, 250, 163, 198, 129, 1, 155, 198, 129, 1, 221, 215, 198, 129, - 1, 231, 240, 198, 129, 1, 231, 91, 198, 129, 1, 214, 68, 198, 129, 1, - 247, 160, 198, 129, 1, 247, 1, 198, 129, 1, 223, 32, 198, 129, 1, 222, - 252, 198, 129, 1, 212, 101, 198, 129, 1, 197, 132, 198, 129, 1, 197, 120, - 198, 129, 1, 237, 191, 198, 129, 1, 237, 175, 198, 129, 1, 213, 79, 198, - 129, 1, 190, 190, 198, 129, 1, 199, 49, 198, 129, 1, 238, 32, 198, 129, - 1, 237, 68, 198, 129, 1, 180, 198, 129, 1, 168, 198, 129, 1, 209, 228, - 198, 129, 1, 249, 153, 198, 129, 1, 248, 203, 198, 129, 1, 174, 198, 129, - 1, 170, 198, 129, 1, 165, 198, 129, 1, 173, 198, 129, 1, 195, 188, 198, - 129, 1, 203, 165, 198, 129, 1, 201, 175, 198, 129, 1, 188, 198, 129, 1, - 140, 198, 129, 18, 3, 252, 206, 198, 129, 18, 3, 68, 198, 129, 18, 3, - 223, 199, 198, 129, 18, 3, 66, 198, 129, 18, 3, 196, 30, 198, 129, 18, 3, - 117, 146, 198, 129, 18, 3, 117, 206, 110, 198, 129, 18, 3, 117, 172, 198, - 129, 18, 3, 117, 219, 74, 198, 129, 18, 3, 71, 198, 129, 18, 3, 203, 40, - 71, 198, 129, 18, 3, 251, 236, 198, 129, 18, 3, 74, 198, 129, 18, 3, 203, - 40, 74, 198, 129, 18, 3, 250, 163, 198, 129, 3, 247, 119, 198, 129, 3, - 251, 71, 198, 129, 3, 195, 35, 198, 129, 3, 195, 40, 198, 129, 3, 212, - 141, 198, 129, 3, 250, 145, 198, 129, 230, 137, 198, 129, 252, 68, 56, - 198, 129, 211, 113, 198, 129, 17, 191, 77, 198, 129, 17, 107, 198, 129, - 17, 109, 198, 129, 17, 138, 198, 129, 17, 134, 198, 129, 17, 149, 198, - 129, 17, 169, 198, 129, 17, 175, 198, 129, 17, 171, 198, 129, 17, 178, - 202, 211, 1, 65, 202, 211, 1, 252, 206, 202, 211, 1, 68, 202, 211, 1, - 223, 199, 202, 211, 1, 66, 202, 211, 1, 196, 30, 202, 211, 1, 117, 146, - 202, 211, 1, 117, 206, 110, 202, 211, 1, 117, 172, 202, 211, 1, 117, 219, - 74, 202, 211, 1, 71, 202, 211, 1, 251, 236, 202, 211, 1, 74, 202, 211, 1, - 250, 163, 202, 211, 1, 155, 202, 211, 1, 221, 215, 202, 211, 1, 231, 240, - 202, 211, 1, 231, 91, 202, 211, 1, 214, 68, 202, 211, 1, 247, 160, 202, - 211, 1, 247, 1, 202, 211, 1, 223, 32, 202, 211, 1, 222, 252, 202, 211, 1, - 212, 101, 202, 211, 1, 197, 132, 202, 211, 1, 197, 120, 202, 211, 1, 237, - 191, 202, 211, 1, 237, 175, 202, 211, 1, 213, 79, 202, 211, 1, 190, 190, - 202, 211, 1, 199, 49, 202, 211, 1, 238, 32, 202, 211, 1, 237, 68, 202, - 211, 1, 180, 202, 211, 1, 168, 202, 211, 1, 209, 228, 202, 211, 1, 249, - 153, 202, 211, 1, 248, 203, 202, 211, 1, 174, 202, 211, 1, 170, 202, 211, - 1, 165, 202, 211, 1, 173, 202, 211, 1, 195, 188, 202, 211, 1, 203, 165, - 202, 211, 1, 201, 175, 202, 211, 1, 188, 202, 211, 1, 140, 202, 211, 18, - 3, 252, 206, 202, 211, 18, 3, 68, 202, 211, 18, 3, 223, 199, 202, 211, - 18, 3, 66, 202, 211, 18, 3, 196, 30, 202, 211, 18, 3, 117, 146, 202, 211, - 18, 3, 117, 206, 110, 202, 211, 18, 3, 71, 202, 211, 18, 3, 251, 236, - 202, 211, 18, 3, 74, 202, 211, 18, 3, 250, 163, 202, 211, 3, 247, 119, - 202, 211, 3, 251, 71, 202, 211, 3, 195, 35, 202, 211, 3, 195, 40, 202, - 211, 3, 212, 141, 202, 211, 3, 202, 210, 202, 211, 237, 238, 202, 211, - 55, 237, 238, 202, 211, 204, 11, 236, 140, 202, 211, 204, 11, 164, 202, - 211, 207, 46, 217, 55, 202, 211, 207, 46, 217, 54, 202, 211, 207, 46, - 217, 53, 202, 211, 234, 95, 79, 199, 54, 77, 202, 211, 205, 54, 87, 4, - 197, 236, 23, 196, 221, 211, 41, 202, 211, 205, 54, 87, 4, 197, 236, 23, - 235, 138, 238, 226, 202, 211, 205, 54, 87, 4, 207, 120, 23, 235, 138, - 238, 226, 202, 211, 205, 54, 87, 4, 207, 120, 23, 235, 138, 55, 238, 226, - 202, 211, 205, 54, 87, 4, 207, 120, 23, 235, 138, 197, 225, 238, 226, - 202, 211, 205, 54, 87, 55, 206, 188, 202, 211, 205, 54, 87, 55, 206, 189, - 4, 207, 119, 202, 211, 205, 54, 87, 4, 55, 238, 226, 202, 211, 205, 54, - 87, 4, 197, 225, 238, 226, 202, 211, 205, 54, 87, 4, 208, 26, 238, 226, - 202, 211, 205, 54, 87, 4, 204, 8, 238, 226, 202, 211, 205, 54, 87, 4, - 243, 8, 23, 207, 119, 202, 211, 205, 54, 87, 4, 243, 8, 23, 105, 234, 97, - 202, 211, 205, 54, 87, 4, 243, 8, 23, 232, 128, 234, 97, 202, 211, 1, - 198, 226, 251, 157, 68, 202, 211, 1, 197, 15, 251, 157, 68, 202, 211, 1, - 197, 15, 251, 157, 223, 199, 202, 211, 1, 251, 157, 66, 202, 211, 18, 3, - 251, 157, 66, 202, 211, 18, 3, 251, 157, 196, 30, 215, 253, 1, 65, 215, - 253, 1, 252, 206, 215, 253, 1, 68, 215, 253, 1, 223, 199, 215, 253, 1, - 66, 215, 253, 1, 196, 30, 215, 253, 1, 117, 146, 215, 253, 1, 117, 206, - 110, 215, 253, 1, 117, 172, 215, 253, 1, 117, 219, 74, 215, 253, 1, 71, - 215, 253, 1, 251, 236, 215, 253, 1, 74, 215, 253, 1, 250, 163, 215, 253, - 1, 155, 215, 253, 1, 221, 215, 215, 253, 1, 231, 240, 215, 253, 1, 231, - 91, 215, 253, 1, 214, 68, 215, 253, 1, 247, 160, 215, 253, 1, 247, 1, - 215, 253, 1, 223, 32, 215, 253, 1, 222, 252, 215, 253, 1, 212, 101, 215, - 253, 1, 197, 132, 215, 253, 1, 197, 120, 215, 253, 1, 237, 191, 215, 253, - 1, 237, 175, 215, 253, 1, 213, 79, 215, 253, 1, 190, 190, 215, 253, 1, - 199, 49, 215, 253, 1, 238, 32, 215, 253, 1, 237, 68, 215, 253, 1, 180, - 215, 253, 1, 168, 215, 253, 1, 209, 228, 215, 253, 1, 249, 153, 215, 253, - 1, 248, 203, 215, 253, 1, 174, 215, 253, 1, 170, 215, 253, 1, 165, 215, - 253, 1, 173, 215, 253, 1, 195, 188, 215, 253, 1, 203, 165, 215, 253, 1, - 201, 175, 215, 253, 1, 188, 215, 253, 1, 140, 215, 253, 1, 219, 73, 215, - 253, 18, 3, 252, 206, 215, 253, 18, 3, 68, 215, 253, 18, 3, 223, 199, - 215, 253, 18, 3, 66, 215, 253, 18, 3, 196, 30, 215, 253, 18, 3, 117, 146, - 215, 253, 18, 3, 117, 206, 110, 215, 253, 18, 3, 117, 172, 215, 253, 18, - 3, 117, 219, 74, 215, 253, 18, 3, 71, 215, 253, 18, 3, 251, 236, 215, - 253, 18, 3, 74, 215, 253, 18, 3, 250, 163, 215, 253, 3, 251, 71, 215, - 253, 3, 195, 35, 215, 253, 3, 195, 40, 215, 253, 3, 251, 11, 215, 253, - 237, 238, 215, 253, 55, 237, 238, 215, 253, 252, 68, 56, 215, 253, 3, - 228, 127, 215, 253, 17, 191, 77, 215, 253, 17, 107, 215, 253, 17, 109, - 215, 253, 17, 138, 215, 253, 17, 134, 215, 253, 17, 149, 215, 253, 17, - 169, 215, 253, 17, 175, 215, 253, 17, 171, 215, 253, 17, 178, 104, 248, - 159, 4, 211, 42, 104, 206, 122, 248, 158, 104, 55, 248, 159, 4, 211, 42, - 104, 197, 225, 248, 159, 4, 211, 42, 104, 248, 159, 4, 55, 211, 42, 104, - 206, 122, 248, 159, 4, 211, 42, 104, 206, 122, 248, 159, 4, 55, 211, 42, - 104, 223, 93, 248, 158, 104, 223, 93, 248, 159, 4, 55, 211, 42, 104, 200, - 134, 248, 158, 104, 200, 134, 248, 159, 4, 211, 42, 104, 200, 134, 248, - 159, 4, 55, 211, 42, 104, 153, 200, 134, 248, 159, 4, 55, 211, 42, 199, - 205, 1, 65, 199, 205, 1, 252, 206, 199, 205, 1, 68, 199, 205, 1, 223, - 199, 199, 205, 1, 66, 199, 205, 1, 196, 30, 199, 205, 1, 71, 199, 205, 1, - 251, 236, 199, 205, 1, 74, 199, 205, 1, 250, 163, 199, 205, 1, 155, 199, - 205, 1, 221, 215, 199, 205, 1, 231, 240, 199, 205, 1, 231, 91, 199, 205, - 1, 214, 68, 199, 205, 1, 247, 160, 199, 205, 1, 247, 1, 199, 205, 1, 223, - 32, 199, 205, 1, 222, 252, 199, 205, 1, 212, 101, 199, 205, 1, 197, 132, - 199, 205, 1, 197, 120, 199, 205, 1, 237, 191, 199, 205, 1, 237, 175, 199, - 205, 1, 213, 79, 199, 205, 1, 190, 190, 199, 205, 1, 199, 49, 199, 205, - 1, 238, 32, 199, 205, 1, 237, 68, 199, 205, 1, 180, 199, 205, 1, 168, - 199, 205, 1, 209, 228, 199, 205, 1, 249, 153, 199, 205, 1, 248, 203, 199, - 205, 1, 174, 199, 205, 1, 170, 199, 205, 1, 165, 199, 205, 1, 173, 199, - 205, 1, 195, 188, 199, 205, 1, 203, 165, 199, 205, 1, 188, 199, 205, 1, - 140, 199, 205, 1, 206, 109, 199, 205, 3, 251, 71, 199, 205, 3, 195, 35, - 199, 205, 18, 3, 252, 206, 199, 205, 18, 3, 68, 199, 205, 18, 3, 223, - 199, 199, 205, 18, 3, 66, 199, 205, 18, 3, 196, 30, 199, 205, 18, 3, 71, - 199, 205, 18, 3, 251, 236, 199, 205, 18, 3, 74, 199, 205, 18, 3, 250, - 163, 199, 205, 3, 195, 40, 199, 205, 3, 212, 141, 199, 205, 1, 251, 14, - 221, 215, 199, 205, 252, 68, 56, 199, 205, 17, 191, 77, 199, 205, 17, - 107, 199, 205, 17, 109, 199, 205, 17, 138, 199, 205, 17, 134, 199, 205, - 17, 149, 199, 205, 17, 169, 199, 205, 17, 175, 199, 205, 17, 171, 199, - 205, 17, 178, 251, 240, 1, 155, 251, 240, 1, 221, 215, 251, 240, 1, 214, - 68, 251, 240, 1, 180, 251, 240, 1, 190, 190, 251, 240, 1, 251, 157, 190, - 190, 251, 240, 1, 168, 251, 240, 1, 209, 228, 251, 240, 1, 249, 153, 251, - 240, 1, 174, 251, 240, 1, 223, 32, 251, 240, 1, 247, 1, 251, 240, 1, 199, - 49, 251, 240, 1, 165, 251, 240, 1, 173, 251, 240, 1, 188, 251, 240, 1, - 212, 101, 251, 240, 1, 140, 251, 240, 1, 65, 251, 240, 1, 238, 32, 251, - 240, 1, 237, 68, 251, 240, 1, 231, 240, 251, 240, 1, 251, 157, 231, 240, - 251, 240, 1, 231, 91, 251, 240, 1, 248, 203, 251, 240, 1, 222, 252, 251, - 240, 1, 251, 157, 249, 153, 251, 240, 120, 3, 216, 217, 173, 251, 240, - 120, 3, 216, 217, 165, 251, 240, 120, 3, 216, 217, 219, 133, 165, 251, - 240, 18, 3, 65, 251, 240, 18, 3, 252, 206, 251, 240, 18, 3, 68, 251, 240, - 18, 3, 223, 199, 251, 240, 18, 3, 66, 251, 240, 18, 3, 196, 30, 251, 240, - 18, 3, 71, 251, 240, 18, 3, 250, 140, 251, 240, 18, 3, 74, 251, 240, 18, - 3, 251, 236, 251, 240, 18, 3, 251, 149, 251, 240, 3, 221, 143, 251, 240, - 17, 191, 77, 251, 240, 17, 107, 251, 240, 17, 109, 251, 240, 17, 138, - 251, 240, 17, 134, 251, 240, 17, 149, 251, 240, 17, 169, 251, 240, 17, - 175, 251, 240, 17, 171, 251, 240, 17, 178, 251, 240, 31, 199, 95, 251, - 240, 31, 197, 32, 251, 240, 3, 2, 205, 53, 251, 240, 3, 205, 53, 251, - 240, 3, 206, 53, 251, 240, 16, 195, 69, 251, 240, 1, 247, 160, 251, 240, - 1, 197, 132, 251, 240, 1, 197, 120, 251, 240, 1, 237, 191, 251, 240, 1, - 237, 175, 251, 240, 1, 213, 79, 251, 240, 1, 219, 73, 236, 161, 1, 65, - 236, 161, 1, 252, 206, 236, 161, 1, 68, 236, 161, 1, 223, 199, 236, 161, - 1, 66, 236, 161, 1, 196, 30, 236, 161, 1, 71, 236, 161, 1, 251, 236, 236, - 161, 1, 74, 236, 161, 1, 250, 163, 236, 161, 1, 155, 236, 161, 1, 221, - 215, 236, 161, 1, 231, 240, 236, 161, 1, 231, 91, 236, 161, 1, 214, 68, - 236, 161, 1, 247, 160, 236, 161, 1, 247, 1, 236, 161, 1, 223, 32, 236, - 161, 1, 222, 252, 236, 161, 1, 212, 101, 236, 161, 1, 197, 132, 236, 161, - 1, 197, 120, 236, 161, 1, 237, 191, 236, 161, 1, 237, 175, 236, 161, 1, - 213, 79, 236, 161, 1, 190, 190, 236, 161, 1, 199, 49, 236, 161, 1, 238, - 32, 236, 161, 1, 237, 68, 236, 161, 1, 180, 236, 161, 1, 168, 236, 161, - 1, 209, 228, 236, 161, 1, 249, 153, 236, 161, 1, 248, 203, 236, 161, 1, - 174, 236, 161, 1, 170, 236, 161, 1, 165, 236, 161, 1, 173, 236, 161, 1, - 195, 188, 236, 161, 1, 203, 165, 236, 161, 1, 201, 175, 236, 161, 1, 188, - 236, 161, 1, 140, 236, 161, 1, 206, 109, 236, 161, 18, 3, 252, 206, 236, - 161, 18, 3, 68, 236, 161, 18, 3, 223, 199, 236, 161, 18, 3, 66, 236, 161, - 18, 3, 196, 30, 236, 161, 18, 3, 117, 146, 236, 161, 18, 3, 117, 206, - 110, 236, 161, 18, 3, 71, 236, 161, 18, 3, 251, 236, 236, 161, 18, 3, 74, - 236, 161, 18, 3, 250, 163, 236, 161, 3, 251, 71, 236, 161, 3, 195, 35, - 236, 161, 3, 195, 40, 236, 161, 3, 212, 141, 236, 161, 252, 68, 56, 193, - 156, 242, 253, 6, 1, 214, 67, 193, 156, 242, 253, 6, 1, 65, 193, 156, - 242, 253, 6, 1, 193, 86, 193, 156, 242, 253, 6, 1, 191, 225, 193, 156, - 242, 253, 6, 1, 170, 193, 156, 242, 253, 6, 1, 192, 12, 193, 156, 242, - 253, 6, 1, 223, 199, 193, 156, 242, 253, 6, 1, 196, 30, 193, 156, 242, - 253, 6, 1, 71, 193, 156, 242, 253, 6, 1, 74, 193, 156, 242, 253, 6, 1, - 251, 122, 193, 156, 242, 253, 6, 1, 231, 240, 193, 156, 242, 253, 6, 1, - 221, 67, 193, 156, 242, 253, 6, 1, 234, 66, 193, 156, 242, 253, 6, 1, - 191, 204, 193, 156, 242, 253, 6, 1, 196, 160, 193, 156, 242, 253, 6, 1, - 234, 85, 193, 156, 242, 253, 6, 1, 211, 154, 193, 156, 242, 253, 6, 1, - 197, 127, 193, 156, 242, 253, 6, 1, 212, 127, 193, 156, 242, 253, 6, 1, - 238, 32, 193, 156, 242, 253, 6, 1, 250, 182, 193, 156, 242, 253, 6, 1, - 251, 149, 193, 156, 242, 253, 6, 1, 248, 10, 193, 156, 242, 253, 6, 1, - 208, 165, 193, 156, 242, 253, 6, 1, 229, 115, 193, 156, 242, 253, 6, 1, - 229, 3, 193, 156, 242, 253, 6, 1, 228, 185, 193, 156, 242, 253, 6, 1, - 230, 19, 193, 156, 242, 253, 6, 1, 201, 126, 193, 156, 242, 253, 6, 1, - 202, 193, 193, 156, 242, 253, 6, 1, 195, 25, 193, 156, 242, 253, 2, 1, - 214, 67, 193, 156, 242, 253, 2, 1, 65, 193, 156, 242, 253, 2, 1, 193, 86, - 193, 156, 242, 253, 2, 1, 191, 225, 193, 156, 242, 253, 2, 1, 170, 193, - 156, 242, 253, 2, 1, 192, 12, 193, 156, 242, 253, 2, 1, 223, 199, 193, - 156, 242, 253, 2, 1, 196, 30, 193, 156, 242, 253, 2, 1, 71, 193, 156, - 242, 253, 2, 1, 74, 193, 156, 242, 253, 2, 1, 251, 122, 193, 156, 242, - 253, 2, 1, 231, 240, 193, 156, 242, 253, 2, 1, 221, 67, 193, 156, 242, - 253, 2, 1, 234, 66, 193, 156, 242, 253, 2, 1, 191, 204, 193, 156, 242, - 253, 2, 1, 196, 160, 193, 156, 242, 253, 2, 1, 234, 85, 193, 156, 242, - 253, 2, 1, 211, 154, 193, 156, 242, 253, 2, 1, 197, 127, 193, 156, 242, - 253, 2, 1, 212, 127, 193, 156, 242, 253, 2, 1, 238, 32, 193, 156, 242, - 253, 2, 1, 250, 182, 193, 156, 242, 253, 2, 1, 251, 149, 193, 156, 242, - 253, 2, 1, 248, 10, 193, 156, 242, 253, 2, 1, 208, 165, 193, 156, 242, - 253, 2, 1, 229, 115, 193, 156, 242, 253, 2, 1, 229, 3, 193, 156, 242, - 253, 2, 1, 228, 185, 193, 156, 242, 253, 2, 1, 230, 19, 193, 156, 242, - 253, 2, 1, 201, 126, 193, 156, 242, 253, 2, 1, 202, 193, 193, 156, 242, - 253, 2, 1, 195, 25, 193, 156, 242, 253, 17, 191, 77, 193, 156, 242, 253, - 17, 107, 193, 156, 242, 253, 17, 109, 193, 156, 242, 253, 17, 138, 193, - 156, 242, 253, 17, 134, 193, 156, 242, 253, 17, 149, 193, 156, 242, 253, - 17, 169, 193, 156, 242, 253, 17, 175, 193, 156, 242, 253, 17, 171, 193, - 156, 242, 253, 17, 178, 193, 156, 242, 253, 31, 199, 95, 193, 156, 242, - 253, 31, 197, 32, 193, 156, 242, 253, 31, 198, 249, 193, 156, 242, 253, - 31, 232, 135, 193, 156, 242, 253, 31, 233, 15, 193, 156, 242, 253, 31, - 202, 120, 193, 156, 242, 253, 31, 203, 241, 193, 156, 242, 253, 31, 234, - 153, 193, 156, 242, 253, 31, 213, 169, 193, 156, 242, 253, 211, 113, 236, - 209, 251, 209, 1, 65, 236, 209, 251, 209, 1, 252, 206, 236, 209, 251, - 209, 1, 68, 236, 209, 251, 209, 1, 223, 199, 236, 209, 251, 209, 1, 66, - 236, 209, 251, 209, 1, 196, 30, 236, 209, 251, 209, 1, 71, 236, 209, 251, - 209, 1, 74, 236, 209, 251, 209, 1, 155, 236, 209, 251, 209, 1, 221, 215, - 236, 209, 251, 209, 1, 231, 240, 236, 209, 251, 209, 1, 231, 91, 236, - 209, 251, 209, 1, 214, 68, 236, 209, 251, 209, 1, 247, 160, 236, 209, - 251, 209, 1, 247, 1, 236, 209, 251, 209, 1, 223, 32, 236, 209, 251, 209, - 1, 212, 101, 236, 209, 251, 209, 1, 197, 132, 236, 209, 251, 209, 1, 237, - 191, 236, 209, 251, 209, 1, 237, 175, 236, 209, 251, 209, 1, 213, 79, - 236, 209, 251, 209, 1, 190, 190, 236, 209, 251, 209, 1, 199, 49, 236, - 209, 251, 209, 1, 238, 32, 236, 209, 251, 209, 1, 237, 68, 236, 209, 251, - 209, 1, 180, 236, 209, 251, 209, 1, 168, 236, 209, 251, 209, 1, 209, 228, - 236, 209, 251, 209, 1, 249, 153, 236, 209, 251, 209, 1, 248, 203, 236, - 209, 251, 209, 1, 174, 236, 209, 251, 209, 1, 170, 236, 209, 251, 209, 1, - 191, 175, 236, 209, 251, 209, 1, 165, 236, 209, 251, 209, 1, 173, 236, - 209, 251, 209, 1, 195, 188, 236, 209, 251, 209, 1, 203, 165, 236, 209, - 251, 209, 1, 201, 175, 236, 209, 251, 209, 1, 188, 236, 209, 251, 209, 1, - 140, 236, 209, 251, 209, 1, 219, 73, 236, 209, 251, 209, 1, 191, 123, - 236, 209, 251, 209, 18, 3, 252, 206, 236, 209, 251, 209, 18, 3, 68, 236, - 209, 251, 209, 18, 3, 223, 199, 236, 209, 251, 209, 18, 3, 66, 236, 209, - 251, 209, 18, 3, 196, 30, 236, 209, 251, 209, 18, 3, 71, 236, 209, 251, - 209, 18, 3, 251, 236, 236, 209, 251, 209, 18, 3, 74, 236, 209, 251, 209, - 3, 251, 71, 236, 209, 251, 209, 3, 247, 119, 236, 209, 251, 209, 3, 230, - 72, 236, 209, 251, 209, 195, 40, 236, 209, 251, 209, 208, 227, 214, 214, - 56, 236, 209, 251, 209, 216, 217, 170, 236, 209, 251, 209, 89, 165, 236, - 209, 251, 209, 216, 217, 165, 236, 209, 251, 209, 3, 212, 141, 236, 209, - 251, 209, 55, 237, 238, 236, 209, 251, 209, 231, 204, 233, 3, 236, 209, - 251, 209, 234, 95, 79, 199, 54, 77, 236, 209, 251, 209, 17, 191, 77, 236, - 209, 251, 209, 17, 107, 236, 209, 251, 209, 17, 109, 236, 209, 251, 209, - 17, 138, 236, 209, 251, 209, 17, 134, 236, 209, 251, 209, 17, 149, 236, - 209, 251, 209, 17, 169, 236, 209, 251, 209, 17, 175, 236, 209, 251, 209, - 17, 171, 236, 209, 251, 209, 17, 178, 214, 223, 1, 65, 214, 223, 1, 252, - 206, 214, 223, 1, 68, 214, 223, 1, 223, 199, 214, 223, 1, 66, 214, 223, - 1, 196, 30, 214, 223, 1, 117, 146, 214, 223, 1, 117, 206, 110, 214, 223, - 1, 71, 214, 223, 1, 251, 236, 214, 223, 1, 74, 214, 223, 1, 250, 163, - 214, 223, 1, 155, 214, 223, 1, 221, 215, 214, 223, 1, 231, 240, 214, 223, - 1, 231, 91, 214, 223, 1, 214, 68, 214, 223, 1, 247, 160, 214, 223, 1, - 247, 1, 214, 223, 1, 223, 32, 214, 223, 1, 222, 252, 214, 223, 1, 212, - 101, 214, 223, 1, 197, 132, 214, 223, 1, 197, 120, 214, 223, 1, 237, 191, - 214, 223, 1, 237, 175, 214, 223, 1, 213, 79, 214, 223, 1, 190, 190, 214, - 223, 1, 199, 49, 214, 223, 1, 238, 32, 214, 223, 1, 237, 68, 214, 223, 1, - 180, 214, 223, 1, 168, 214, 223, 1, 209, 228, 214, 223, 1, 249, 153, 214, - 223, 1, 248, 203, 214, 223, 1, 174, 214, 223, 1, 170, 214, 223, 1, 165, - 214, 223, 1, 173, 214, 223, 1, 195, 188, 214, 223, 1, 203, 165, 214, 223, - 1, 201, 175, 214, 223, 1, 188, 214, 223, 1, 140, 214, 223, 1, 219, 73, - 214, 223, 1, 206, 109, 214, 223, 18, 3, 252, 206, 214, 223, 18, 3, 68, - 214, 223, 18, 3, 223, 199, 214, 223, 18, 3, 66, 214, 223, 18, 3, 196, 30, - 214, 223, 18, 3, 117, 146, 214, 223, 18, 3, 117, 206, 110, 214, 223, 18, - 3, 71, 214, 223, 18, 3, 251, 236, 214, 223, 18, 3, 74, 214, 223, 18, 3, - 250, 163, 214, 223, 3, 251, 71, 214, 223, 3, 195, 35, 214, 223, 3, 195, - 40, 214, 223, 3, 250, 145, 214, 223, 3, 202, 210, 214, 223, 229, 227, - 214, 223, 18, 3, 208, 207, 71, 191, 106, 51, 1, 65, 191, 106, 51, 18, 3, - 68, 191, 106, 51, 18, 3, 196, 152, 191, 106, 51, 18, 3, 66, 191, 106, 51, - 18, 3, 71, 191, 106, 51, 18, 3, 211, 151, 191, 106, 51, 18, 3, 74, 191, - 106, 51, 18, 3, 251, 236, 191, 106, 51, 18, 3, 250, 163, 191, 106, 51, - 18, 3, 207, 18, 68, 191, 106, 51, 18, 219, 198, 77, 191, 106, 51, 1, 155, - 191, 106, 51, 1, 221, 215, 191, 106, 51, 1, 231, 240, 191, 106, 51, 1, - 231, 91, 191, 106, 51, 1, 214, 68, 191, 106, 51, 1, 247, 160, 191, 106, - 51, 1, 247, 1, 191, 106, 51, 1, 223, 32, 191, 106, 51, 1, 212, 101, 191, - 106, 51, 1, 197, 132, 191, 106, 51, 1, 197, 120, 191, 106, 51, 1, 237, - 191, 191, 106, 51, 1, 237, 175, 191, 106, 51, 1, 213, 79, 191, 106, 51, - 1, 190, 190, 191, 106, 51, 1, 199, 49, 191, 106, 51, 1, 238, 32, 191, - 106, 51, 1, 237, 68, 191, 106, 51, 1, 180, 191, 106, 51, 1, 168, 191, - 106, 51, 1, 209, 228, 191, 106, 51, 1, 249, 153, 191, 106, 51, 1, 248, - 203, 191, 106, 51, 1, 174, 191, 106, 51, 1, 197, 168, 191, 106, 51, 1, - 197, 157, 191, 106, 51, 1, 235, 35, 191, 106, 51, 1, 235, 29, 191, 106, - 51, 1, 191, 71, 191, 106, 51, 1, 191, 123, 191, 106, 51, 1, 255, 214, - 191, 106, 51, 1, 170, 191, 106, 51, 1, 165, 191, 106, 51, 1, 173, 191, - 106, 51, 1, 195, 188, 191, 106, 51, 1, 203, 165, 191, 106, 51, 1, 201, - 175, 191, 106, 51, 1, 188, 191, 106, 51, 1, 140, 191, 106, 51, 1, 220, - 246, 191, 106, 51, 53, 120, 77, 191, 106, 51, 3, 195, 40, 191, 106, 51, - 3, 247, 119, 191, 106, 51, 3, 247, 120, 4, 211, 42, 191, 106, 51, 3, 247, - 122, 4, 211, 42, 191, 106, 51, 3, 251, 71, 191, 106, 51, 3, 195, 35, 191, - 106, 51, 242, 201, 1, 165, 191, 106, 51, 242, 202, 1, 170, 191, 106, 51, - 242, 202, 1, 165, 191, 106, 51, 242, 202, 1, 173, 191, 106, 51, 242, 202, - 1, 195, 188, 191, 106, 51, 89, 229, 236, 77, 191, 106, 51, 242, 215, 229, - 236, 77, 191, 106, 51, 87, 197, 152, 191, 106, 51, 87, 203, 157, 191, - 106, 51, 87, 55, 203, 157, 191, 106, 51, 87, 179, 197, 152, 191, 106, 51, - 89, 235, 130, 229, 236, 77, 191, 106, 51, 242, 215, 235, 130, 229, 236, - 77, 191, 106, 51, 200, 238, 201, 251, 1, 65, 201, 251, 18, 3, 68, 201, - 251, 18, 3, 196, 152, 201, 251, 18, 3, 66, 201, 251, 18, 3, 71, 201, 251, - 18, 3, 74, 201, 251, 18, 3, 211, 151, 201, 251, 18, 3, 251, 236, 201, - 251, 18, 3, 250, 163, 201, 251, 18, 3, 117, 146, 201, 251, 18, 3, 117, - 172, 201, 251, 18, 219, 198, 77, 201, 251, 1, 155, 201, 251, 1, 221, 215, - 201, 251, 1, 231, 240, 201, 251, 1, 231, 91, 201, 251, 1, 214, 68, 201, - 251, 1, 247, 160, 201, 251, 1, 247, 1, 201, 251, 1, 223, 32, 201, 251, 1, - 222, 252, 201, 251, 1, 212, 101, 201, 251, 1, 197, 132, 201, 251, 1, 197, - 120, 201, 251, 1, 237, 191, 201, 251, 1, 237, 175, 201, 251, 1, 213, 79, - 201, 251, 1, 190, 190, 201, 251, 1, 199, 49, 201, 251, 1, 238, 32, 201, - 251, 1, 237, 68, 201, 251, 1, 180, 201, 251, 1, 168, 201, 251, 1, 209, - 228, 201, 251, 1, 249, 153, 201, 251, 1, 248, 203, 201, 251, 1, 174, 201, - 251, 1, 197, 168, 201, 251, 1, 197, 157, 201, 251, 1, 235, 35, 201, 251, - 1, 191, 71, 201, 251, 1, 191, 123, 201, 251, 1, 255, 214, 201, 251, 1, - 170, 201, 251, 1, 165, 201, 251, 1, 173, 201, 251, 1, 195, 188, 201, 251, - 1, 203, 165, 201, 251, 1, 201, 175, 201, 251, 1, 188, 201, 251, 1, 140, - 201, 251, 1, 220, 246, 201, 251, 3, 222, 237, 201, 251, 3, 196, 75, 201, - 251, 242, 201, 1, 165, 201, 251, 242, 201, 1, 173, 201, 251, 242, 201, 1, - 203, 165, 201, 251, 242, 201, 1, 188, 201, 251, 53, 120, 3, 232, 51, 201, - 251, 53, 120, 3, 222, 152, 201, 251, 53, 120, 3, 214, 70, 201, 251, 53, - 120, 3, 238, 127, 201, 251, 53, 120, 3, 215, 61, 201, 251, 53, 120, 3, - 250, 120, 201, 251, 53, 120, 3, 218, 168, 201, 251, 53, 120, 3, 146, 201, - 251, 53, 120, 3, 172, 201, 251, 53, 120, 3, 203, 167, 201, 251, 53, 120, - 3, 206, 8, 201, 251, 53, 120, 3, 255, 214, 201, 251, 3, 251, 71, 201, - 251, 3, 195, 35, 201, 251, 231, 153, 77, 201, 251, 200, 238, 201, 251, - 87, 197, 152, 201, 251, 87, 203, 157, 201, 251, 87, 55, 203, 157, 201, - 251, 87, 209, 79, 201, 251, 229, 236, 87, 4, 215, 206, 23, 200, 199, 23, - 197, 225, 232, 210, 201, 251, 229, 236, 87, 4, 215, 206, 23, 200, 199, - 23, 232, 210, 201, 251, 229, 236, 87, 4, 215, 206, 23, 200, 198, 201, - 251, 199, 81, 217, 55, 201, 251, 199, 81, 217, 54, 21, 22, 214, 207, 229, - 158, 21, 22, 214, 207, 229, 130, 21, 22, 214, 207, 229, 23, 21, 22, 214, - 207, 228, 252, 21, 22, 214, 207, 140, 21, 22, 214, 207, 230, 91, 21, 22, - 214, 207, 203, 15, 21, 22, 214, 207, 203, 14, 21, 22, 214, 207, 203, 11, - 21, 22, 214, 207, 203, 10, 21, 22, 214, 207, 203, 17, 21, 22, 214, 207, - 203, 16, 21, 22, 201, 237, 21, 22, 201, 224, 21, 22, 201, 207, 21, 22, - 201, 249, 210, 81, 243, 15, 230, 3, 1, 168, 210, 81, 243, 15, 230, 3, 1, - 155, 210, 81, 243, 15, 230, 3, 1, 173, 210, 81, 243, 15, 230, 3, 1, 174, - 210, 81, 243, 15, 230, 3, 1, 238, 32, 210, 81, 243, 15, 230, 3, 1, 191, - 123, 210, 81, 243, 15, 230, 3, 1, 195, 188, 210, 81, 243, 15, 230, 3, 1, - 214, 68, 210, 81, 243, 15, 230, 3, 1, 140, 210, 81, 243, 15, 230, 3, 1, - 231, 240, 210, 81, 243, 15, 230, 3, 1, 221, 215, 210, 81, 243, 15, 230, - 3, 1, 188, 210, 81, 243, 15, 230, 3, 1, 249, 153, 210, 81, 243, 15, 230, - 3, 1, 247, 160, 210, 81, 243, 15, 230, 3, 1, 190, 190, 210, 81, 243, 15, - 230, 3, 1, 199, 49, 210, 81, 243, 15, 230, 3, 1, 180, 210, 81, 243, 15, - 230, 3, 1, 209, 228, 210, 81, 243, 15, 230, 3, 1, 165, 210, 81, 243, 15, - 230, 3, 1, 233, 109, 210, 81, 243, 15, 230, 3, 1, 247, 1, 210, 81, 243, - 15, 230, 3, 1, 65, 210, 81, 243, 15, 230, 3, 1, 71, 210, 81, 243, 15, - 230, 3, 1, 68, 210, 81, 243, 15, 230, 3, 1, 74, 210, 81, 243, 15, 230, 3, - 1, 66, 210, 81, 243, 15, 230, 3, 1, 196, 168, 210, 81, 243, 15, 230, 3, - 1, 228, 35, 210, 81, 243, 15, 230, 3, 1, 53, 210, 236, 210, 81, 243, 15, - 230, 3, 1, 53, 222, 152, 210, 81, 243, 15, 230, 3, 1, 53, 200, 43, 210, - 81, 243, 15, 230, 3, 1, 53, 218, 168, 210, 81, 243, 15, 230, 3, 1, 53, - 215, 61, 210, 81, 243, 15, 230, 3, 1, 53, 172, 210, 81, 243, 15, 230, 3, - 1, 53, 193, 224, 210, 81, 243, 15, 230, 3, 1, 53, 214, 70, 210, 81, 243, - 15, 230, 3, 1, 53, 192, 159, 210, 81, 243, 15, 230, 3, 206, 180, 163, - 219, 19, 210, 81, 243, 15, 230, 3, 206, 180, 198, 79, 210, 81, 243, 15, - 230, 3, 205, 138, 231, 11, 201, 63, 210, 81, 243, 15, 230, 3, 206, 180, - 163, 179, 232, 255, 210, 81, 243, 15, 230, 3, 206, 180, 163, 232, 255, - 210, 81, 243, 15, 230, 3, 205, 138, 231, 11, 201, 64, 232, 255, 210, 81, - 243, 15, 230, 3, 205, 138, 163, 219, 19, 210, 81, 243, 15, 230, 3, 205, - 138, 198, 79, 210, 81, 243, 15, 230, 3, 205, 138, 163, 179, 232, 255, - 210, 81, 243, 15, 230, 3, 205, 138, 163, 232, 255, 210, 81, 243, 15, 230, - 3, 216, 85, 198, 79, 210, 81, 243, 15, 230, 3, 231, 11, 201, 64, 195, - 167, 210, 81, 243, 15, 230, 3, 216, 85, 163, 179, 232, 255, 210, 81, 243, - 15, 230, 3, 216, 85, 163, 232, 255, 210, 81, 243, 15, 230, 3, 218, 239, - 163, 219, 19, 210, 81, 243, 15, 230, 3, 218, 239, 198, 79, 210, 81, 243, - 15, 230, 3, 231, 11, 201, 63, 210, 81, 243, 15, 230, 3, 218, 239, 163, - 179, 232, 255, 210, 81, 243, 15, 230, 3, 218, 239, 163, 232, 255, 210, - 81, 243, 15, 230, 3, 231, 11, 201, 64, 232, 255, 100, 229, 236, 77, 100, - 229, 236, 87, 4, 229, 227, 100, 3, 248, 199, 100, 3, 248, 200, 4, 102, - 100, 3, 233, 205, 248, 199, 100, 3, 233, 205, 248, 200, 4, 102, 100, 3, - 193, 102, 232, 225, 248, 199, 100, 3, 193, 102, 213, 174, 248, 199, 100, - 3, 207, 18, 213, 174, 248, 199, 100, 3, 216, 43, 248, 201, 1, 65, 248, - 201, 1, 252, 206, 248, 201, 1, 68, 248, 201, 1, 223, 199, 248, 201, 1, - 66, 248, 201, 1, 196, 30, 248, 201, 1, 117, 146, 248, 201, 1, 117, 206, - 110, 248, 201, 1, 117, 172, 248, 201, 1, 71, 248, 201, 1, 251, 236, 248, - 201, 1, 74, 248, 201, 1, 250, 163, 248, 201, 1, 155, 248, 201, 1, 221, - 215, 248, 201, 1, 231, 240, 248, 201, 1, 231, 91, 248, 201, 1, 214, 68, - 248, 201, 1, 247, 160, 248, 201, 1, 247, 1, 248, 201, 1, 223, 32, 248, - 201, 1, 222, 252, 248, 201, 1, 212, 101, 248, 201, 1, 197, 132, 248, 201, - 1, 197, 120, 248, 201, 1, 237, 191, 248, 201, 1, 237, 175, 248, 201, 1, - 213, 79, 248, 201, 1, 190, 190, 248, 201, 1, 199, 49, 248, 201, 1, 238, - 32, 248, 201, 1, 237, 68, 248, 201, 1, 180, 248, 201, 1, 168, 248, 201, - 1, 209, 228, 248, 201, 1, 249, 153, 248, 201, 1, 248, 203, 248, 201, 1, - 174, 248, 201, 1, 170, 248, 201, 1, 165, 248, 201, 1, 173, 248, 201, 1, - 195, 188, 248, 201, 1, 203, 165, 248, 201, 1, 201, 175, 248, 201, 1, 188, - 248, 201, 1, 140, 248, 201, 18, 3, 252, 206, 248, 201, 18, 3, 68, 248, - 201, 18, 3, 223, 199, 248, 201, 18, 3, 66, 248, 201, 18, 3, 196, 30, 248, - 201, 18, 3, 117, 146, 248, 201, 18, 3, 117, 206, 110, 248, 201, 18, 3, - 117, 172, 248, 201, 18, 3, 71, 248, 201, 18, 3, 251, 236, 248, 201, 18, - 3, 74, 248, 201, 18, 3, 250, 163, 248, 201, 3, 247, 119, 248, 201, 3, - 251, 71, 248, 201, 3, 195, 35, 248, 201, 3, 195, 40, 248, 201, 3, 250, - 145, 248, 201, 237, 238, 248, 201, 55, 237, 238, 248, 201, 193, 23, 204, - 10, 248, 201, 231, 204, 233, 2, 248, 201, 231, 204, 233, 1, 248, 201, 17, - 191, 77, 248, 201, 17, 107, 248, 201, 17, 109, 248, 201, 17, 138, 248, - 201, 17, 134, 248, 201, 17, 149, 248, 201, 17, 169, 248, 201, 17, 175, - 248, 201, 17, 171, 248, 201, 17, 178, 248, 201, 31, 107, 248, 201, 31, - 109, 248, 201, 31, 138, 248, 201, 31, 134, 248, 201, 31, 149, 248, 201, - 31, 169, 248, 201, 31, 175, 248, 201, 31, 171, 248, 201, 31, 178, 248, - 201, 31, 199, 95, 248, 201, 31, 197, 32, 248, 201, 31, 198, 249, 248, - 201, 31, 232, 135, 248, 201, 31, 233, 15, 248, 201, 31, 202, 120, 248, - 201, 31, 203, 241, 248, 201, 31, 234, 153, 248, 201, 31, 213, 169, 248, - 201, 228, 139, 196, 91, 77, 217, 57, 229, 236, 77, 217, 57, 87, 203, 157, - 217, 57, 1, 155, 217, 57, 1, 221, 215, 217, 57, 1, 231, 240, 217, 57, 1, - 214, 68, 217, 57, 1, 247, 160, 217, 57, 1, 247, 1, 217, 57, 1, 223, 32, - 217, 57, 1, 212, 101, 217, 57, 1, 190, 190, 217, 57, 1, 199, 49, 217, 57, - 1, 238, 32, 217, 57, 1, 180, 217, 57, 1, 168, 217, 57, 1, 209, 228, 217, - 57, 1, 249, 153, 217, 57, 1, 174, 217, 57, 1, 197, 168, 217, 57, 1, 197, - 157, 217, 57, 1, 235, 35, 217, 57, 1, 193, 190, 217, 57, 1, 191, 71, 217, - 57, 1, 191, 123, 217, 57, 1, 255, 214, 217, 57, 1, 170, 217, 57, 1, 165, - 217, 57, 1, 173, 217, 57, 1, 203, 165, 217, 57, 1, 188, 217, 57, 1, 140, - 217, 57, 1, 65, 217, 57, 200, 239, 1, 155, 217, 57, 200, 239, 1, 221, - 215, 217, 57, 200, 239, 1, 231, 240, 217, 57, 200, 239, 1, 214, 68, 217, - 57, 200, 239, 1, 247, 160, 217, 57, 200, 239, 1, 247, 1, 217, 57, 200, - 239, 1, 223, 32, 217, 57, 200, 239, 1, 212, 101, 217, 57, 200, 239, 1, - 190, 190, 217, 57, 200, 239, 1, 199, 49, 217, 57, 200, 239, 1, 238, 32, - 217, 57, 200, 239, 1, 180, 217, 57, 200, 239, 1, 168, 217, 57, 200, 239, - 1, 209, 228, 217, 57, 200, 239, 1, 249, 153, 217, 57, 200, 239, 1, 174, - 217, 57, 200, 239, 1, 197, 168, 217, 57, 200, 239, 1, 197, 157, 217, 57, - 200, 239, 1, 235, 35, 217, 57, 200, 239, 1, 193, 190, 217, 57, 200, 239, - 1, 191, 71, 217, 57, 200, 239, 1, 191, 123, 217, 57, 200, 239, 1, 170, - 217, 57, 200, 239, 1, 165, 217, 57, 200, 239, 1, 173, 217, 57, 200, 239, - 1, 203, 165, 217, 57, 200, 239, 1, 188, 217, 57, 200, 239, 1, 140, 217, - 57, 200, 239, 1, 65, 217, 57, 18, 3, 252, 206, 217, 57, 18, 3, 68, 217, - 57, 18, 3, 66, 217, 57, 18, 3, 71, 217, 57, 18, 3, 74, 217, 57, 3, 251, - 71, 217, 57, 3, 247, 119, 217, 41, 129, 1, 65, 217, 41, 129, 1, 252, 206, - 217, 41, 129, 1, 68, 217, 41, 129, 1, 223, 199, 217, 41, 129, 1, 66, 217, - 41, 129, 1, 196, 30, 217, 41, 129, 1, 71, 217, 41, 129, 1, 251, 236, 217, - 41, 129, 1, 74, 217, 41, 129, 1, 250, 163, 217, 41, 129, 1, 155, 217, 41, - 129, 1, 221, 215, 217, 41, 129, 1, 231, 240, 217, 41, 129, 1, 231, 91, - 217, 41, 129, 1, 214, 68, 217, 41, 129, 1, 247, 160, 217, 41, 129, 1, - 247, 1, 217, 41, 129, 1, 223, 32, 217, 41, 129, 1, 222, 252, 217, 41, - 129, 1, 212, 101, 217, 41, 129, 1, 197, 132, 217, 41, 129, 1, 197, 120, - 217, 41, 129, 1, 237, 191, 217, 41, 129, 1, 237, 175, 217, 41, 129, 1, - 213, 79, 217, 41, 129, 1, 190, 190, 217, 41, 129, 1, 199, 49, 217, 41, - 129, 1, 238, 32, 217, 41, 129, 1, 237, 68, 217, 41, 129, 1, 180, 217, 41, - 129, 1, 168, 217, 41, 129, 1, 209, 228, 217, 41, 129, 1, 249, 153, 217, - 41, 129, 1, 248, 203, 217, 41, 129, 1, 174, 217, 41, 129, 1, 170, 217, - 41, 129, 1, 165, 217, 41, 129, 1, 173, 217, 41, 129, 1, 195, 188, 217, - 41, 129, 1, 203, 165, 217, 41, 129, 1, 201, 175, 217, 41, 129, 1, 188, - 217, 41, 129, 1, 140, 217, 41, 129, 1, 219, 73, 217, 41, 129, 1, 220, - 246, 217, 41, 129, 1, 222, 202, 217, 41, 129, 1, 198, 26, 217, 41, 129, - 18, 3, 252, 206, 217, 41, 129, 18, 3, 68, 217, 41, 129, 18, 3, 223, 199, - 217, 41, 129, 18, 3, 66, 217, 41, 129, 18, 3, 196, 30, 217, 41, 129, 18, - 3, 117, 146, 217, 41, 129, 18, 3, 71, 217, 41, 129, 18, 3, 251, 236, 217, - 41, 129, 18, 3, 74, 217, 41, 129, 18, 3, 250, 163, 217, 41, 129, 3, 251, - 71, 217, 41, 129, 3, 195, 35, 217, 41, 129, 3, 212, 141, 217, 41, 129, 3, - 247, 121, 217, 41, 129, 3, 230, 72, 217, 41, 129, 195, 40, 217, 41, 129, - 207, 44, 217, 41, 129, 207, 181, 217, 41, 129, 17, 191, 77, 217, 41, 129, - 17, 107, 217, 41, 129, 17, 109, 217, 41, 129, 17, 138, 217, 41, 129, 17, - 134, 217, 41, 129, 17, 149, 217, 41, 129, 17, 169, 217, 41, 129, 17, 175, - 217, 41, 129, 17, 171, 217, 41, 129, 17, 178, 230, 157, 129, 1, 65, 230, - 157, 129, 1, 252, 206, 230, 157, 129, 1, 68, 230, 157, 129, 1, 223, 199, - 230, 157, 129, 1, 66, 230, 157, 129, 1, 196, 30, 230, 157, 129, 1, 234, - 188, 230, 157, 129, 1, 251, 236, 230, 157, 129, 1, 211, 87, 230, 157, - 129, 1, 250, 163, 230, 157, 129, 1, 170, 230, 157, 129, 1, 195, 188, 230, - 157, 129, 1, 249, 153, 230, 157, 129, 1, 248, 203, 230, 157, 129, 1, 174, - 230, 157, 129, 1, 155, 230, 157, 129, 1, 221, 215, 230, 157, 129, 1, 190, - 190, 230, 157, 129, 1, 199, 49, 230, 157, 129, 1, 173, 230, 157, 129, 1, - 231, 240, 230, 157, 129, 1, 231, 91, 230, 157, 129, 1, 238, 32, 230, 157, - 129, 1, 237, 68, 230, 157, 129, 1, 180, 230, 157, 129, 1, 247, 160, 230, - 157, 129, 1, 247, 1, 230, 157, 129, 1, 197, 132, 230, 157, 129, 1, 197, - 120, 230, 157, 129, 1, 219, 73, 230, 157, 129, 1, 223, 32, 230, 157, 129, - 1, 222, 252, 230, 157, 129, 1, 237, 191, 230, 157, 129, 1, 237, 175, 230, - 157, 129, 1, 214, 68, 230, 157, 129, 1, 168, 230, 157, 129, 1, 209, 228, - 230, 157, 129, 1, 140, 230, 157, 129, 1, 165, 230, 157, 129, 1, 188, 230, - 157, 129, 18, 3, 252, 206, 230, 157, 129, 18, 3, 68, 230, 157, 129, 18, - 3, 223, 199, 230, 157, 129, 18, 3, 66, 230, 157, 129, 18, 3, 196, 30, - 230, 157, 129, 18, 3, 234, 188, 230, 157, 129, 18, 3, 251, 236, 230, 157, - 129, 18, 3, 211, 87, 230, 157, 129, 18, 3, 250, 163, 230, 157, 129, 3, - 251, 71, 230, 157, 129, 3, 195, 35, 230, 157, 129, 195, 40, 230, 157, - 129, 211, 113, 230, 157, 129, 17, 191, 77, 230, 157, 129, 17, 107, 230, - 157, 129, 17, 109, 230, 157, 129, 17, 138, 230, 157, 129, 17, 134, 230, - 157, 129, 17, 149, 230, 157, 129, 17, 169, 230, 157, 129, 17, 175, 230, - 157, 129, 17, 171, 230, 157, 129, 17, 178, 217, 102, 1, 155, 217, 102, 1, - 231, 240, 217, 102, 1, 214, 68, 217, 102, 1, 168, 217, 102, 1, 249, 153, - 217, 102, 1, 174, 217, 102, 1, 190, 190, 217, 102, 1, 238, 32, 217, 102, - 1, 180, 217, 102, 1, 247, 160, 217, 102, 1, 223, 32, 217, 102, 1, 212, - 101, 217, 102, 1, 170, 217, 102, 1, 165, 217, 102, 1, 173, 217, 102, 1, - 195, 188, 217, 102, 1, 188, 217, 102, 1, 65, 217, 102, 251, 118, 217, - 102, 18, 3, 68, 217, 102, 18, 3, 66, 217, 102, 18, 3, 71, 217, 102, 18, - 3, 74, 217, 102, 210, 94, 217, 102, 234, 95, 79, 205, 53, 222, 33, 3, - 247, 119, 222, 33, 3, 251, 71, 222, 33, 3, 207, 44, 222, 33, 3, 195, 35, - 222, 33, 1, 65, 222, 33, 1, 252, 206, 222, 33, 1, 68, 222, 33, 1, 223, - 199, 222, 33, 1, 66, 222, 33, 1, 196, 30, 222, 33, 1, 117, 146, 222, 33, - 1, 117, 206, 110, 222, 33, 1, 117, 172, 222, 33, 1, 117, 219, 74, 222, - 33, 1, 71, 222, 33, 1, 251, 236, 222, 33, 1, 74, 222, 33, 1, 155, 222, - 33, 1, 221, 215, 222, 33, 1, 231, 240, 222, 33, 1, 231, 91, 222, 33, 1, - 214, 68, 222, 33, 1, 247, 160, 222, 33, 1, 247, 1, 222, 33, 1, 223, 32, - 222, 33, 1, 222, 252, 222, 33, 1, 212, 101, 222, 33, 1, 197, 132, 222, - 33, 1, 197, 120, 222, 33, 1, 237, 191, 222, 33, 1, 237, 175, 222, 33, 1, - 213, 79, 222, 33, 1, 190, 190, 222, 33, 1, 199, 49, 222, 33, 1, 238, 32, - 222, 33, 1, 237, 68, 222, 33, 1, 180, 222, 33, 1, 168, 222, 33, 1, 209, - 228, 222, 33, 1, 249, 153, 222, 33, 1, 248, 203, 222, 33, 1, 174, 222, - 33, 1, 170, 222, 33, 1, 165, 222, 33, 1, 173, 222, 33, 1, 193, 190, 222, - 33, 1, 203, 165, 222, 33, 1, 201, 175, 222, 33, 1, 188, 222, 33, 1, 140, - 222, 33, 1, 222, 202, 222, 33, 18, 3, 252, 206, 222, 33, 18, 3, 251, 157, - 252, 206, 222, 33, 18, 3, 68, 222, 33, 18, 3, 223, 199, 222, 33, 18, 3, - 66, 222, 33, 18, 3, 196, 30, 222, 33, 18, 3, 117, 146, 222, 33, 18, 3, - 71, 222, 33, 18, 3, 251, 236, 222, 33, 18, 3, 233, 242, 222, 33, 3, 221, - 143, 222, 33, 239, 45, 222, 33, 237, 238, 222, 33, 55, 237, 238, 222, 33, - 208, 152, 205, 54, 217, 51, 222, 33, 208, 152, 251, 157, 205, 54, 217, - 51, 222, 33, 208, 152, 232, 186, 222, 33, 208, 152, 201, 248, 233, 3, - 222, 33, 208, 152, 236, 140, 222, 33, 208, 152, 55, 236, 140, 222, 33, - 208, 152, 197, 225, 236, 140, 222, 33, 208, 152, 243, 10, 222, 33, 208, - 152, 233, 4, 243, 10, 222, 33, 208, 152, 201, 217, 222, 33, 208, 152, - 242, 215, 201, 217, 222, 33, 17, 191, 77, 222, 33, 17, 107, 222, 33, 17, - 109, 222, 33, 17, 138, 222, 33, 17, 134, 222, 33, 17, 149, 222, 33, 17, - 169, 222, 33, 17, 175, 222, 33, 17, 171, 222, 33, 17, 178, 219, 88, 1, - 192, 35, 44, 232, 118, 91, 198, 222, 44, 232, 118, 91, 211, 100, 44, 232, - 118, 91, 234, 156, 44, 232, 118, 91, 202, 118, 44, 232, 118, 91, 232, - 139, 44, 232, 118, 91, 198, 245, 44, 232, 118, 115, 234, 155, 44, 232, - 118, 115, 202, 117, 44, 232, 118, 91, 197, 35, 44, 232, 118, 91, 202, - 127, 44, 232, 118, 91, 202, 126, 44, 232, 118, 91, 199, 86, 44, 232, 118, - 91, 234, 159, 44, 232, 118, 115, 197, 34, 44, 232, 118, 115, 202, 125, - 44, 232, 118, 91, 233, 18, 44, 232, 118, 91, 208, 22, 44, 232, 118, 91, - 230, 69, 44, 232, 118, 91, 230, 68, 44, 232, 118, 115, 208, 20, 44, 232, - 118, 235, 121, 233, 93, 221, 144, 44, 3, 214, 104, 44, 3, 247, 6, 44, 3, - 252, 157, 44, 3, 196, 15, 44, 3, 215, 90, 44, 3, 220, 194, 44, 3, 210, - 85, 44, 3, 215, 135, 44, 3, 222, 124, 44, 3, 210, 164, 44, 3, 209, 39, - 44, 3, 195, 173, 44, 3, 210, 215, 44, 3, 220, 183, 44, 3, 195, 143, 44, - 193, 101, 238, 187, 56, 44, 235, 92, 238, 187, 56, 44, 220, 23, 56, 44, - 205, 159, 210, 167, 56, 44, 198, 21, 238, 230, 56, 44, 198, 21, 31, 56, - 44, 238, 169, 56, 44, 23, 211, 155, 56, 44, 201, 227, 56, 44, 198, 39, - 56, 44, 223, 163, 209, 22, 56, 44, 201, 96, 232, 98, 56, 44, 3, 215, 94, - 44, 3, 195, 181, 44, 208, 152, 234, 95, 79, 199, 53, 10, 3, 65, 10, 3, - 42, 25, 65, 10, 3, 42, 25, 249, 135, 10, 3, 42, 25, 231, 209, 199, 84, - 10, 3, 42, 25, 140, 10, 3, 42, 25, 223, 201, 10, 3, 42, 25, 220, 103, - 230, 155, 10, 3, 42, 25, 215, 101, 10, 3, 42, 25, 205, 185, 10, 3, 254, - 215, 10, 3, 252, 155, 10, 3, 252, 156, 25, 250, 207, 10, 3, 252, 156, 25, - 235, 74, 230, 155, 10, 3, 252, 156, 25, 231, 222, 10, 3, 252, 156, 25, - 231, 209, 199, 84, 10, 3, 252, 156, 25, 140, 10, 3, 252, 156, 25, 223, - 202, 230, 155, 10, 3, 252, 156, 25, 223, 172, 10, 3, 252, 156, 25, 220, - 104, 10, 3, 252, 156, 25, 203, 97, 10, 3, 252, 156, 25, 126, 108, 126, - 108, 66, 10, 3, 252, 156, 230, 155, 10, 3, 252, 72, 10, 3, 252, 73, 25, - 249, 114, 10, 3, 252, 73, 25, 231, 209, 199, 84, 10, 3, 252, 73, 25, 216, - 233, 108, 234, 103, 10, 3, 252, 73, 25, 203, 163, 10, 3, 252, 73, 25, - 199, 209, 10, 3, 252, 42, 10, 3, 251, 216, 10, 3, 251, 217, 25, 234, 28, - 10, 3, 251, 217, 25, 203, 59, 108, 231, 23, 10, 3, 251, 207, 10, 3, 251, - 208, 25, 251, 207, 10, 3, 251, 208, 25, 236, 253, 10, 3, 251, 208, 25, - 231, 23, 10, 3, 251, 208, 25, 140, 10, 3, 251, 208, 25, 222, 111, 10, 3, - 251, 208, 25, 221, 166, 10, 3, 251, 208, 25, 203, 113, 10, 3, 251, 208, - 25, 196, 38, 10, 3, 251, 203, 10, 3, 251, 190, 10, 3, 251, 145, 10, 3, - 251, 146, 25, 203, 113, 10, 3, 251, 132, 10, 3, 251, 133, 139, 251, 132, - 10, 3, 251, 133, 115, 198, 144, 10, 3, 251, 133, 108, 214, 241, 211, 63, - 251, 133, 108, 214, 240, 10, 3, 251, 133, 108, 214, 241, 201, 189, 10, 3, - 251, 91, 10, 3, 251, 60, 10, 3, 251, 26, 10, 3, 251, 27, 25, 220, 197, - 10, 3, 250, 254, 10, 3, 250, 215, 10, 3, 250, 209, 10, 3, 250, 210, 191, - 26, 199, 84, 10, 3, 250, 210, 222, 116, 199, 84, 10, 3, 250, 210, 139, - 250, 210, 197, 83, 139, 197, 83, 197, 83, 139, 197, 83, 210, 137, 10, 3, - 250, 210, 139, 250, 210, 139, 250, 209, 10, 3, 250, 210, 139, 250, 210, - 139, 250, 210, 238, 210, 250, 210, 139, 250, 210, 139, 250, 209, 10, 3, - 250, 207, 10, 3, 250, 203, 10, 3, 249, 153, 10, 3, 249, 135, 10, 3, 249, - 129, 10, 3, 249, 121, 10, 3, 249, 115, 10, 3, 249, 116, 139, 249, 115, - 10, 3, 249, 114, 10, 3, 164, 10, 3, 249, 87, 10, 3, 248, 188, 10, 3, 248, - 189, 25, 65, 10, 3, 248, 189, 25, 231, 200, 10, 3, 248, 189, 25, 223, - 202, 230, 155, 10, 3, 248, 10, 10, 3, 248, 11, 139, 248, 11, 252, 155, - 10, 3, 248, 11, 139, 248, 11, 196, 113, 10, 3, 248, 11, 238, 210, 248, - 10, 10, 3, 247, 242, 10, 3, 247, 243, 139, 247, 242, 10, 3, 247, 230, 10, - 3, 247, 229, 10, 3, 238, 32, 10, 3, 238, 22, 10, 3, 238, 23, 221, 125, - 25, 42, 108, 217, 39, 10, 3, 238, 23, 221, 125, 25, 251, 145, 10, 3, 238, - 23, 221, 125, 25, 249, 114, 10, 3, 238, 23, 221, 125, 25, 248, 188, 10, - 3, 238, 23, 221, 125, 25, 231, 240, 10, 3, 238, 23, 221, 125, 25, 231, - 241, 108, 217, 39, 10, 3, 238, 23, 221, 125, 25, 231, 53, 10, 3, 238, 23, - 221, 125, 25, 231, 32, 10, 3, 238, 23, 221, 125, 25, 230, 168, 10, 3, - 238, 23, 221, 125, 25, 140, 10, 3, 238, 23, 221, 125, 25, 223, 77, 10, 3, - 238, 23, 221, 125, 25, 223, 78, 108, 218, 225, 10, 3, 238, 23, 221, 125, - 25, 222, 96, 10, 3, 238, 23, 221, 125, 25, 173, 10, 3, 238, 23, 221, 125, - 25, 218, 225, 10, 3, 238, 23, 221, 125, 25, 218, 226, 108, 217, 38, 10, - 3, 238, 23, 221, 125, 25, 218, 208, 10, 3, 238, 23, 221, 125, 25, 214, - 121, 10, 3, 238, 23, 221, 125, 25, 210, 138, 108, 210, 137, 10, 3, 238, - 23, 221, 125, 25, 202, 222, 10, 3, 238, 23, 221, 125, 25, 199, 209, 10, - 3, 238, 23, 221, 125, 25, 196, 170, 108, 231, 32, 10, 3, 238, 23, 221, - 125, 25, 196, 38, 10, 3, 237, 250, 10, 3, 237, 225, 10, 3, 237, 224, 10, - 3, 237, 223, 10, 3, 237, 44, 10, 3, 237, 26, 10, 3, 236, 255, 10, 3, 237, - 0, 25, 203, 113, 10, 3, 236, 253, 10, 3, 236, 243, 10, 3, 236, 244, 222, - 55, 126, 230, 156, 236, 222, 10, 3, 236, 222, 10, 3, 235, 89, 10, 3, 235, - 90, 139, 235, 89, 10, 3, 235, 90, 230, 155, 10, 3, 235, 90, 203, 94, 10, - 3, 235, 87, 10, 3, 235, 88, 25, 234, 9, 10, 3, 235, 86, 10, 3, 235, 82, - 10, 3, 235, 81, 10, 3, 235, 80, 10, 3, 235, 75, 10, 3, 235, 73, 10, 3, - 235, 74, 230, 155, 10, 3, 235, 74, 230, 156, 230, 155, 10, 3, 235, 72, - 10, 3, 235, 65, 10, 3, 71, 10, 3, 235, 15, 25, 210, 137, 10, 3, 235, 15, - 139, 235, 15, 212, 131, 139, 212, 130, 10, 3, 234, 218, 10, 3, 234, 219, - 25, 42, 108, 230, 105, 108, 238, 32, 10, 3, 234, 219, 25, 231, 200, 10, - 3, 234, 219, 25, 216, 100, 10, 3, 234, 219, 25, 205, 169, 10, 3, 234, - 219, 25, 203, 113, 10, 3, 234, 219, 25, 66, 10, 3, 234, 190, 10, 3, 234, - 177, 10, 3, 234, 140, 10, 3, 234, 103, 10, 3, 234, 104, 25, 231, 208, 10, - 3, 234, 104, 25, 231, 209, 199, 84, 10, 3, 234, 104, 25, 216, 232, 10, 3, - 234, 104, 238, 210, 234, 103, 10, 3, 234, 104, 211, 63, 234, 103, 10, 3, - 234, 104, 201, 189, 10, 3, 234, 31, 10, 3, 234, 28, 10, 3, 234, 9, 10, 3, - 233, 180, 10, 3, 233, 181, 25, 65, 10, 3, 233, 181, 25, 42, 108, 220, 37, - 10, 3, 233, 181, 25, 42, 108, 220, 38, 25, 220, 37, 10, 3, 233, 181, 25, - 251, 132, 10, 3, 233, 181, 25, 249, 135, 10, 3, 233, 181, 25, 235, 74, - 230, 155, 10, 3, 233, 181, 25, 235, 74, 230, 156, 230, 155, 10, 3, 233, - 181, 25, 140, 10, 3, 233, 181, 25, 230, 105, 230, 155, 10, 3, 233, 181, - 25, 223, 202, 230, 155, 10, 3, 233, 181, 25, 222, 54, 10, 3, 233, 181, - 25, 222, 55, 201, 189, 10, 3, 233, 181, 25, 220, 223, 10, 3, 233, 181, - 25, 173, 10, 3, 233, 181, 25, 220, 38, 25, 220, 37, 10, 3, 233, 181, 25, - 219, 146, 10, 3, 233, 181, 25, 218, 225, 10, 3, 233, 181, 25, 196, 169, - 10, 3, 233, 181, 25, 196, 158, 10, 3, 231, 240, 10, 3, 231, 241, 230, - 155, 10, 3, 231, 238, 10, 3, 231, 239, 25, 42, 108, 238, 33, 108, 140, - 10, 3, 231, 239, 25, 42, 108, 140, 10, 3, 231, 239, 25, 42, 108, 223, - 201, 10, 3, 231, 239, 25, 252, 73, 199, 85, 108, 199, 236, 10, 3, 231, - 239, 25, 251, 132, 10, 3, 231, 239, 25, 250, 209, 10, 3, 231, 239, 25, - 250, 208, 108, 231, 222, 10, 3, 231, 239, 25, 249, 135, 10, 3, 231, 239, - 25, 249, 88, 108, 165, 10, 3, 231, 239, 25, 247, 230, 10, 3, 231, 239, - 25, 247, 231, 108, 165, 10, 3, 231, 239, 25, 238, 32, 10, 3, 231, 239, - 25, 237, 44, 10, 3, 231, 239, 25, 237, 0, 25, 203, 113, 10, 3, 231, 239, - 25, 235, 87, 10, 3, 231, 239, 25, 234, 140, 10, 3, 231, 239, 25, 234, - 141, 108, 173, 10, 3, 231, 239, 25, 234, 103, 10, 3, 231, 239, 25, 234, - 104, 25, 231, 209, 199, 84, 10, 3, 231, 239, 25, 231, 209, 199, 84, 10, - 3, 231, 239, 25, 231, 200, 10, 3, 231, 239, 25, 231, 53, 10, 3, 231, 239, - 25, 231, 51, 10, 3, 231, 239, 25, 231, 52, 108, 65, 10, 3, 231, 239, 25, - 231, 33, 108, 201, 4, 10, 3, 231, 239, 25, 230, 105, 108, 218, 226, 108, - 234, 9, 10, 3, 231, 239, 25, 230, 73, 10, 3, 231, 239, 25, 230, 74, 108, - 173, 10, 3, 231, 239, 25, 229, 159, 108, 219, 146, 10, 3, 231, 239, 25, - 228, 151, 10, 3, 231, 239, 25, 223, 202, 230, 155, 10, 3, 231, 239, 25, - 223, 63, 108, 228, 160, 108, 250, 209, 10, 3, 231, 239, 25, 222, 96, 10, - 3, 231, 239, 25, 222, 54, 10, 3, 231, 239, 25, 221, 152, 10, 3, 231, 239, - 25, 221, 153, 108, 220, 37, 10, 3, 231, 239, 25, 220, 224, 108, 251, 132, - 10, 3, 231, 239, 25, 173, 10, 3, 231, 239, 25, 216, 233, 108, 234, 103, - 10, 3, 231, 239, 25, 216, 100, 10, 3, 231, 239, 25, 212, 130, 10, 3, 231, - 239, 25, 212, 131, 139, 212, 130, 10, 3, 231, 239, 25, 168, 10, 3, 231, - 239, 25, 205, 169, 10, 3, 231, 239, 25, 205, 127, 10, 3, 231, 239, 25, - 203, 113, 10, 3, 231, 239, 25, 203, 114, 108, 197, 64, 10, 3, 231, 239, - 25, 203, 79, 10, 3, 231, 239, 25, 200, 204, 10, 3, 231, 239, 25, 199, - 209, 10, 3, 231, 239, 25, 66, 10, 3, 231, 239, 25, 196, 158, 10, 3, 231, - 239, 25, 196, 159, 108, 235, 89, 10, 3, 231, 239, 139, 231, 238, 10, 3, - 231, 233, 10, 3, 231, 234, 238, 210, 231, 233, 10, 3, 231, 231, 10, 3, - 231, 232, 139, 231, 232, 231, 201, 139, 231, 200, 10, 3, 231, 222, 10, 3, - 231, 223, 231, 232, 139, 231, 232, 231, 201, 139, 231, 200, 10, 3, 231, - 221, 10, 3, 231, 219, 10, 3, 231, 210, 10, 3, 231, 208, 10, 3, 231, 209, - 199, 84, 10, 3, 231, 209, 139, 231, 208, 10, 3, 231, 209, 238, 210, 231, - 208, 10, 3, 231, 200, 10, 3, 231, 199, 10, 3, 231, 193, 10, 3, 231, 134, - 10, 3, 231, 135, 25, 220, 197, 10, 3, 231, 53, 10, 3, 231, 54, 25, 71, - 10, 3, 231, 54, 25, 66, 10, 3, 231, 54, 238, 210, 231, 53, 10, 3, 231, - 51, 10, 3, 231, 52, 139, 231, 51, 10, 3, 231, 52, 238, 210, 231, 51, 10, - 3, 231, 48, 10, 3, 231, 32, 10, 3, 231, 33, 230, 155, 10, 3, 231, 30, 10, - 3, 231, 31, 25, 42, 108, 223, 201, 10, 3, 231, 31, 25, 231, 209, 199, 84, - 10, 3, 231, 31, 25, 223, 201, 10, 3, 231, 31, 25, 218, 226, 108, 223, - 201, 10, 3, 231, 31, 25, 168, 10, 3, 231, 25, 10, 3, 231, 23, 10, 3, 231, - 24, 238, 210, 231, 23, 10, 3, 231, 24, 25, 249, 135, 10, 3, 231, 24, 25, - 199, 209, 10, 3, 231, 24, 199, 84, 10, 3, 230, 179, 10, 3, 230, 180, 238, - 210, 230, 179, 10, 3, 230, 177, 10, 3, 230, 178, 25, 222, 96, 10, 3, 230, - 178, 25, 222, 97, 25, 223, 202, 230, 155, 10, 3, 230, 178, 25, 212, 130, - 10, 3, 230, 178, 25, 205, 170, 108, 197, 82, 10, 3, 230, 178, 230, 155, - 10, 3, 230, 168, 10, 3, 230, 169, 25, 42, 108, 220, 197, 10, 3, 230, 169, - 25, 220, 197, 10, 3, 230, 169, 139, 230, 169, 218, 216, 10, 3, 230, 160, - 10, 3, 230, 158, 10, 3, 230, 159, 25, 203, 113, 10, 3, 230, 149, 10, 3, - 230, 148, 10, 3, 230, 143, 10, 3, 230, 142, 10, 3, 140, 10, 3, 230, 105, - 199, 84, 10, 3, 230, 105, 230, 155, 10, 3, 230, 73, 10, 3, 229, 158, 10, - 3, 229, 159, 25, 250, 209, 10, 3, 229, 159, 25, 250, 207, 10, 3, 229, - 159, 25, 249, 135, 10, 3, 229, 159, 25, 236, 222, 10, 3, 229, 159, 25, - 231, 231, 10, 3, 229, 159, 25, 221, 141, 10, 3, 229, 159, 25, 212, 130, - 10, 3, 229, 159, 25, 203, 113, 10, 3, 229, 159, 25, 66, 10, 3, 228, 159, - 10, 3, 228, 151, 10, 3, 228, 152, 25, 251, 132, 10, 3, 228, 152, 25, 230, - 73, 10, 3, 228, 152, 25, 222, 54, 10, 3, 228, 152, 25, 219, 89, 10, 3, - 228, 152, 25, 196, 158, 10, 3, 228, 146, 10, 3, 68, 10, 3, 228, 74, 65, - 10, 3, 228, 30, 10, 3, 223, 229, 10, 3, 223, 230, 139, 223, 230, 247, - 230, 10, 3, 223, 230, 139, 223, 230, 201, 189, 10, 3, 223, 204, 10, 3, - 223, 201, 10, 3, 223, 202, 237, 26, 10, 3, 223, 202, 207, 1, 10, 3, 223, - 202, 139, 223, 202, 203, 63, 139, 203, 63, 196, 159, 139, 196, 158, 10, - 3, 223, 202, 230, 155, 10, 3, 223, 191, 10, 3, 223, 192, 25, 231, 209, - 199, 84, 10, 3, 223, 190, 10, 3, 223, 180, 10, 3, 223, 181, 25, 199, 209, - 10, 3, 223, 181, 238, 210, 223, 180, 10, 3, 223, 181, 211, 63, 223, 180, - 10, 3, 223, 181, 201, 189, 10, 3, 223, 172, 10, 3, 223, 162, 10, 3, 223, - 77, 10, 3, 223, 62, 10, 3, 155, 10, 3, 222, 142, 25, 65, 10, 3, 222, 142, - 25, 252, 42, 10, 3, 222, 142, 25, 252, 43, 108, 220, 223, 10, 3, 222, - 142, 25, 250, 207, 10, 3, 222, 142, 25, 249, 135, 10, 3, 222, 142, 25, - 249, 114, 10, 3, 222, 142, 25, 164, 10, 3, 222, 142, 25, 248, 188, 10, 3, - 222, 142, 25, 234, 28, 10, 3, 222, 142, 25, 234, 9, 10, 3, 222, 142, 25, - 231, 240, 10, 3, 222, 142, 25, 231, 222, 10, 3, 222, 142, 25, 231, 209, - 199, 84, 10, 3, 222, 142, 25, 231, 200, 10, 3, 222, 142, 25, 231, 201, - 108, 203, 164, 108, 65, 10, 3, 222, 142, 25, 231, 53, 10, 3, 222, 142, - 25, 231, 32, 10, 3, 222, 142, 25, 231, 24, 108, 205, 127, 10, 3, 222, - 142, 25, 231, 24, 238, 210, 231, 23, 10, 3, 222, 142, 25, 230, 179, 10, - 3, 222, 142, 25, 230, 148, 10, 3, 222, 142, 25, 223, 201, 10, 3, 222, - 142, 25, 223, 180, 10, 3, 222, 142, 25, 222, 96, 10, 3, 222, 142, 25, - 221, 166, 10, 3, 222, 142, 25, 221, 152, 10, 3, 222, 142, 25, 219, 146, - 10, 3, 222, 142, 25, 218, 225, 10, 3, 222, 142, 25, 216, 232, 10, 3, 222, - 142, 25, 216, 233, 108, 235, 89, 10, 3, 222, 142, 25, 216, 233, 108, 231, - 53, 10, 3, 222, 142, 25, 216, 233, 108, 199, 145, 10, 3, 222, 142, 25, - 216, 100, 10, 3, 222, 142, 25, 216, 101, 108, 212, 125, 10, 3, 222, 142, - 25, 214, 121, 10, 3, 222, 142, 25, 212, 130, 10, 3, 222, 142, 25, 209, - 185, 10, 3, 222, 142, 25, 206, 68, 10, 3, 222, 142, 25, 188, 10, 3, 222, - 142, 25, 205, 127, 10, 3, 222, 142, 25, 203, 165, 10, 3, 222, 142, 25, - 203, 113, 10, 3, 222, 142, 25, 203, 79, 10, 3, 222, 142, 25, 203, 5, 10, - 3, 222, 142, 25, 202, 201, 10, 3, 222, 142, 25, 200, 213, 10, 3, 222, - 142, 25, 199, 179, 10, 3, 222, 142, 25, 66, 10, 3, 222, 142, 25, 196, - 169, 10, 3, 222, 142, 25, 196, 158, 10, 3, 222, 142, 25, 196, 116, 25, - 168, 10, 3, 222, 142, 25, 196, 38, 10, 3, 222, 142, 25, 191, 30, 10, 3, - 222, 128, 10, 3, 222, 129, 238, 210, 222, 128, 10, 3, 222, 117, 10, 3, - 222, 113, 10, 3, 222, 111, 10, 3, 222, 110, 10, 3, 222, 108, 10, 3, 222, - 109, 139, 222, 108, 10, 3, 222, 96, 10, 3, 222, 97, 25, 223, 202, 230, - 155, 10, 3, 222, 91, 10, 3, 222, 92, 25, 249, 135, 10, 3, 222, 92, 238, - 210, 222, 91, 10, 3, 222, 89, 10, 3, 222, 88, 10, 3, 222, 54, 10, 3, 222, - 55, 220, 105, 25, 126, 139, 220, 105, 25, 66, 10, 3, 222, 55, 139, 222, - 55, 220, 105, 25, 126, 139, 220, 105, 25, 66, 10, 3, 221, 242, 10, 3, - 221, 166, 10, 3, 221, 167, 25, 249, 135, 10, 3, 221, 167, 25, 66, 10, 3, - 221, 167, 25, 196, 158, 10, 3, 221, 152, 10, 3, 221, 141, 10, 3, 221, - 127, 10, 3, 221, 126, 10, 3, 221, 124, 10, 3, 221, 125, 139, 221, 124, - 10, 3, 220, 232, 10, 3, 220, 233, 139, 229, 159, 25, 250, 208, 220, 233, - 139, 229, 159, 25, 250, 207, 10, 3, 220, 223, 10, 3, 220, 221, 10, 3, - 220, 222, 195, 168, 20, 10, 3, 220, 220, 10, 3, 220, 211, 10, 3, 220, - 212, 230, 155, 10, 3, 220, 210, 10, 3, 220, 197, 10, 3, 220, 198, 211, - 63, 220, 197, 10, 3, 220, 190, 10, 3, 220, 167, 10, 3, 173, 10, 3, 220, - 104, 10, 3, 220, 105, 25, 65, 10, 3, 220, 105, 25, 42, 108, 238, 33, 108, - 140, 10, 3, 220, 105, 25, 42, 108, 231, 200, 10, 3, 220, 105, 25, 42, - 108, 220, 37, 10, 3, 220, 105, 25, 251, 207, 10, 3, 220, 105, 25, 251, - 132, 10, 3, 220, 105, 25, 250, 210, 191, 26, 199, 84, 10, 3, 220, 105, - 25, 249, 135, 10, 3, 220, 105, 25, 248, 188, 10, 3, 220, 105, 25, 237, - 225, 10, 3, 220, 105, 25, 234, 103, 10, 3, 220, 105, 25, 231, 240, 10, 3, - 220, 105, 25, 231, 200, 10, 3, 220, 105, 25, 230, 168, 10, 3, 220, 105, - 25, 230, 169, 108, 230, 168, 10, 3, 220, 105, 25, 140, 10, 3, 220, 105, - 25, 230, 73, 10, 3, 220, 105, 25, 229, 159, 25, 212, 130, 10, 3, 220, - 105, 25, 223, 202, 230, 155, 10, 3, 220, 105, 25, 223, 180, 10, 3, 220, - 105, 25, 223, 181, 108, 140, 10, 3, 220, 105, 25, 223, 181, 108, 218, - 225, 10, 3, 220, 105, 25, 221, 166, 10, 3, 220, 105, 25, 221, 141, 10, 3, - 220, 105, 25, 220, 223, 10, 3, 220, 105, 25, 220, 211, 10, 3, 220, 105, - 25, 220, 212, 108, 229, 159, 108, 65, 10, 3, 220, 105, 25, 220, 104, 10, - 3, 220, 105, 25, 219, 89, 10, 3, 220, 105, 25, 218, 225, 10, 3, 220, 105, - 25, 218, 210, 10, 3, 220, 105, 25, 216, 232, 10, 3, 220, 105, 25, 216, - 233, 108, 234, 103, 10, 3, 220, 105, 25, 215, 101, 10, 3, 220, 105, 25, - 214, 121, 10, 3, 220, 105, 25, 203, 114, 108, 200, 204, 10, 3, 220, 105, - 25, 203, 59, 108, 231, 24, 108, 234, 28, 10, 3, 220, 105, 25, 203, 59, - 108, 231, 24, 199, 84, 10, 3, 220, 105, 25, 203, 3, 10, 3, 220, 105, 25, - 203, 4, 108, 203, 3, 10, 3, 220, 105, 25, 200, 204, 10, 3, 220, 105, 25, - 199, 223, 10, 3, 220, 105, 25, 199, 209, 10, 3, 220, 105, 25, 199, 146, - 108, 42, 108, 201, 5, 108, 180, 10, 3, 220, 105, 25, 66, 10, 3, 220, 105, - 25, 126, 108, 65, 10, 3, 220, 105, 25, 126, 108, 126, 108, 66, 10, 3, - 220, 105, 25, 196, 170, 108, 250, 209, 10, 3, 220, 105, 25, 196, 158, 10, - 3, 220, 105, 25, 196, 38, 10, 3, 220, 105, 201, 189, 10, 3, 220, 102, 10, - 3, 220, 103, 25, 203, 113, 10, 3, 220, 103, 25, 203, 114, 108, 200, 204, - 10, 3, 220, 103, 230, 155, 10, 3, 220, 103, 230, 156, 139, 220, 103, 230, - 156, 203, 113, 10, 3, 220, 98, 10, 3, 220, 37, 10, 3, 220, 38, 25, 220, - 37, 10, 3, 220, 35, 10, 3, 220, 36, 25, 220, 197, 10, 3, 220, 36, 25, - 220, 198, 108, 206, 68, 10, 3, 219, 146, 10, 3, 219, 127, 10, 3, 219, - 115, 10, 3, 219, 89, 10, 3, 218, 225, 10, 3, 218, 226, 25, 249, 135, 10, - 3, 218, 223, 10, 3, 218, 224, 25, 251, 207, 10, 3, 218, 224, 25, 249, - 135, 10, 3, 218, 224, 25, 234, 9, 10, 3, 218, 224, 25, 234, 10, 199, 84, - 10, 3, 218, 224, 25, 231, 209, 199, 84, 10, 3, 218, 224, 25, 229, 159, - 25, 249, 135, 10, 3, 218, 224, 25, 223, 180, 10, 3, 218, 224, 25, 222, - 113, 10, 3, 218, 224, 25, 222, 111, 10, 3, 218, 224, 25, 222, 112, 108, - 250, 209, 10, 3, 218, 224, 25, 221, 166, 10, 3, 218, 224, 25, 220, 126, - 108, 250, 209, 10, 3, 218, 224, 25, 220, 104, 10, 3, 218, 224, 25, 216, - 233, 108, 234, 103, 10, 3, 218, 224, 25, 214, 121, 10, 3, 218, 224, 25, - 212, 178, 10, 3, 218, 224, 25, 202, 223, 108, 250, 209, 10, 3, 218, 224, - 25, 202, 192, 108, 248, 10, 10, 3, 218, 224, 25, 197, 82, 10, 3, 218, - 224, 199, 84, 10, 3, 218, 224, 238, 210, 218, 223, 10, 3, 218, 224, 211, - 63, 218, 223, 10, 3, 218, 224, 201, 189, 10, 3, 218, 224, 203, 94, 10, 3, - 218, 222, 10, 3, 218, 216, 10, 3, 218, 217, 139, 218, 216, 10, 3, 218, - 217, 211, 63, 218, 216, 10, 3, 218, 217, 203, 94, 10, 3, 218, 213, 10, 3, - 218, 210, 10, 3, 218, 208, 10, 3, 218, 209, 139, 218, 208, 10, 3, 218, - 209, 139, 218, 209, 231, 201, 139, 231, 200, 10, 3, 174, 10, 3, 217, 160, - 25, 199, 209, 10, 3, 217, 160, 230, 155, 10, 3, 217, 152, 10, 3, 217, - 120, 10, 3, 217, 65, 10, 3, 217, 39, 10, 3, 217, 38, 10, 3, 216, 232, 10, - 3, 216, 173, 10, 3, 216, 100, 10, 3, 216, 44, 10, 3, 215, 155, 10, 3, - 215, 156, 139, 215, 155, 10, 3, 215, 140, 10, 3, 215, 141, 230, 155, 10, - 3, 215, 119, 10, 3, 215, 105, 10, 3, 215, 101, 10, 3, 215, 102, 25, 65, - 10, 3, 215, 102, 25, 220, 197, 10, 3, 215, 102, 25, 191, 123, 10, 3, 215, - 102, 139, 215, 101, 10, 3, 215, 102, 139, 215, 102, 25, 42, 108, 180, 10, - 3, 215, 102, 238, 210, 215, 101, 10, 3, 215, 99, 10, 3, 215, 100, 25, 65, - 10, 3, 215, 100, 25, 42, 108, 237, 44, 10, 3, 215, 100, 25, 237, 44, 10, - 3, 215, 100, 230, 155, 10, 3, 180, 10, 3, 214, 253, 10, 3, 214, 240, 10, - 3, 214, 241, 223, 92, 10, 3, 214, 241, 25, 203, 6, 199, 84, 10, 3, 214, - 241, 211, 63, 214, 240, 10, 3, 214, 239, 10, 3, 214, 231, 212, 116, 10, - 3, 214, 230, 10, 3, 214, 229, 10, 3, 214, 121, 10, 3, 214, 122, 25, 65, - 10, 3, 214, 122, 25, 196, 158, 10, 3, 214, 122, 203, 94, 10, 3, 213, 219, - 10, 3, 213, 220, 25, 71, 10, 3, 213, 210, 10, 3, 213, 180, 10, 3, 213, - 181, 25, 231, 209, 199, 84, 10, 3, 213, 181, 25, 231, 201, 108, 231, 209, - 199, 84, 10, 3, 213, 176, 10, 3, 213, 177, 25, 251, 132, 10, 3, 213, 177, - 25, 250, 209, 10, 3, 213, 177, 25, 250, 210, 108, 250, 209, 10, 3, 213, - 177, 25, 230, 168, 10, 3, 213, 177, 25, 216, 233, 108, 231, 209, 199, 84, - 10, 3, 213, 177, 25, 214, 121, 10, 3, 213, 177, 25, 212, 130, 10, 3, 213, - 177, 25, 203, 113, 10, 3, 213, 177, 25, 203, 114, 108, 42, 251, 132, 10, - 3, 213, 177, 25, 203, 114, 108, 250, 209, 10, 3, 213, 177, 25, 203, 114, - 108, 250, 210, 108, 250, 209, 10, 3, 213, 177, 25, 196, 170, 108, 250, - 209, 10, 3, 213, 177, 25, 196, 38, 10, 3, 213, 163, 10, 3, 212, 178, 10, - 3, 212, 147, 10, 3, 212, 130, 10, 3, 212, 131, 220, 103, 25, 231, 200, - 10, 3, 212, 131, 220, 103, 25, 217, 39, 10, 3, 212, 131, 220, 103, 25, - 205, 169, 10, 3, 212, 131, 220, 103, 25, 205, 170, 139, 212, 131, 220, - 103, 25, 205, 169, 10, 3, 212, 131, 220, 103, 25, 196, 38, 10, 3, 212, - 131, 199, 84, 10, 3, 212, 131, 139, 212, 130, 10, 3, 212, 131, 238, 210, - 212, 130, 10, 3, 212, 131, 238, 210, 212, 131, 220, 103, 139, 220, 102, - 10, 3, 212, 125, 10, 3, 212, 126, 252, 73, 25, 250, 203, 10, 3, 212, 126, - 252, 73, 25, 248, 188, 10, 3, 212, 126, 252, 73, 25, 235, 82, 10, 3, 212, - 126, 252, 73, 25, 230, 168, 10, 3, 212, 126, 252, 73, 25, 223, 202, 230, - 155, 10, 3, 212, 126, 252, 73, 25, 222, 111, 10, 3, 212, 126, 252, 73, - 25, 173, 10, 3, 212, 126, 252, 73, 25, 214, 121, 10, 3, 212, 126, 252, - 73, 25, 202, 189, 10, 3, 212, 126, 252, 73, 25, 196, 169, 10, 3, 212, - 126, 221, 125, 25, 248, 188, 10, 3, 212, 126, 221, 125, 25, 248, 189, 66, - 10, 3, 168, 10, 3, 210, 210, 10, 3, 210, 166, 10, 3, 210, 137, 10, 3, - 209, 243, 10, 3, 209, 185, 10, 3, 209, 186, 25, 65, 10, 3, 209, 186, 25, - 252, 155, 10, 3, 209, 186, 25, 248, 188, 10, 3, 209, 186, 25, 248, 10, - 10, 3, 209, 186, 25, 71, 10, 3, 209, 186, 25, 68, 10, 3, 209, 186, 25, - 228, 30, 10, 3, 209, 186, 25, 66, 10, 3, 209, 186, 25, 196, 169, 10, 3, - 209, 186, 238, 210, 209, 185, 10, 3, 209, 121, 10, 3, 209, 122, 25, 222, - 91, 10, 3, 209, 122, 25, 196, 158, 10, 3, 209, 122, 25, 191, 123, 10, 3, - 209, 122, 211, 63, 209, 121, 10, 3, 165, 10, 3, 207, 176, 10, 3, 207, 1, - 10, 3, 206, 68, 10, 3, 188, 10, 3, 205, 186, 212, 116, 10, 3, 205, 185, - 10, 3, 205, 186, 25, 65, 10, 3, 205, 186, 25, 235, 89, 10, 3, 205, 186, - 25, 235, 87, 10, 3, 205, 186, 25, 140, 10, 3, 205, 186, 25, 222, 96, 10, - 3, 205, 186, 25, 220, 197, 10, 3, 205, 186, 25, 218, 208, 10, 3, 205, - 186, 25, 216, 100, 10, 3, 205, 186, 25, 212, 130, 10, 3, 205, 186, 25, - 205, 169, 10, 3, 205, 186, 25, 203, 79, 10, 3, 205, 186, 25, 199, 236, - 10, 3, 205, 186, 25, 196, 169, 10, 3, 205, 186, 25, 196, 164, 10, 3, 205, - 186, 25, 196, 120, 10, 3, 205, 186, 25, 196, 62, 10, 3, 205, 186, 25, - 196, 38, 10, 3, 205, 186, 139, 205, 185, 10, 3, 205, 186, 230, 155, 10, - 3, 205, 169, 10, 3, 205, 170, 220, 105, 25, 250, 207, 10, 3, 205, 136, - 10, 3, 205, 127, 10, 3, 203, 165, 10, 3, 203, 163, 10, 3, 203, 164, 25, - 65, 10, 3, 203, 164, 25, 249, 135, 10, 3, 203, 164, 25, 231, 23, 10, 3, - 203, 164, 25, 214, 121, 10, 3, 203, 164, 25, 203, 3, 10, 3, 203, 164, 25, - 197, 64, 10, 3, 203, 164, 25, 66, 10, 3, 203, 164, 25, 126, 108, 65, 10, - 3, 203, 161, 10, 3, 203, 159, 10, 3, 203, 131, 10, 3, 203, 113, 10, 3, - 203, 114, 228, 159, 10, 3, 203, 114, 139, 203, 114, 231, 232, 139, 231, - 232, 231, 201, 139, 231, 200, 10, 3, 203, 114, 139, 203, 114, 199, 237, - 139, 199, 237, 231, 201, 139, 231, 200, 10, 3, 203, 106, 10, 3, 203, 101, - 10, 3, 203, 97, 10, 3, 203, 96, 10, 3, 203, 93, 10, 3, 203, 79, 10, 3, - 203, 80, 25, 65, 10, 3, 203, 80, 25, 223, 180, 10, 3, 203, 73, 10, 3, - 203, 74, 25, 65, 10, 3, 203, 74, 25, 249, 115, 10, 3, 203, 74, 25, 247, - 242, 10, 3, 203, 74, 25, 236, 243, 10, 3, 203, 74, 25, 231, 200, 10, 3, - 203, 74, 25, 223, 201, 10, 3, 203, 74, 25, 223, 202, 230, 155, 10, 3, - 203, 74, 25, 220, 190, 10, 3, 203, 74, 25, 218, 210, 10, 3, 203, 74, 25, - 215, 140, 10, 3, 203, 74, 25, 205, 169, 10, 3, 203, 67, 10, 3, 203, 62, - 10, 3, 203, 63, 199, 84, 10, 3, 203, 63, 139, 203, 63, 247, 231, 139, - 247, 230, 10, 3, 203, 58, 10, 3, 203, 5, 10, 3, 203, 6, 139, 223, 93, - 203, 5, 10, 3, 203, 3, 10, 3, 203, 1, 10, 3, 202, 222, 10, 3, 202, 223, - 230, 155, 10, 3, 202, 201, 10, 3, 202, 199, 10, 3, 202, 200, 139, 202, - 200, 203, 3, 10, 3, 202, 191, 10, 3, 202, 189, 10, 3, 201, 4, 10, 3, 201, - 5, 139, 201, 4, 10, 3, 200, 216, 10, 3, 200, 215, 10, 3, 200, 213, 10, 3, - 200, 204, 10, 3, 200, 203, 10, 3, 200, 175, 10, 3, 200, 174, 10, 3, 190, - 190, 10, 3, 199, 252, 250, 193, 10, 3, 199, 252, 25, 229, 158, 10, 3, - 199, 252, 25, 216, 100, 10, 3, 199, 252, 230, 155, 10, 3, 199, 236, 10, - 3, 199, 237, 139, 199, 237, 213, 220, 139, 213, 220, 236, 223, 139, 236, - 222, 10, 3, 199, 237, 201, 189, 10, 3, 199, 223, 10, 3, 199, 224, 25, - 248, 188, 10, 3, 199, 224, 25, 230, 168, 10, 3, 199, 224, 25, 203, 113, - 10, 3, 199, 224, 25, 203, 5, 10, 3, 199, 224, 25, 197, 82, 10, 3, 199, - 224, 25, 196, 158, 10, 3, 199, 209, 10, 3, 199, 179, 10, 3, 199, 145, 10, - 3, 199, 146, 230, 155, 10, 3, 198, 193, 10, 3, 198, 194, 199, 84, 10, 3, - 198, 154, 10, 3, 198, 131, 10, 3, 198, 132, 25, 199, 209, 10, 3, 198, - 132, 139, 198, 131, 10, 3, 198, 132, 139, 198, 132, 231, 232, 139, 231, - 232, 231, 201, 139, 231, 200, 10, 3, 197, 94, 10, 3, 197, 82, 10, 3, 197, - 80, 10, 3, 197, 76, 10, 3, 197, 64, 10, 3, 197, 65, 139, 197, 65, 191, - 124, 139, 191, 123, 10, 3, 66, 10, 3, 126, 230, 168, 10, 3, 126, 126, 66, - 10, 3, 126, 139, 126, 210, 221, 139, 210, 221, 231, 201, 139, 231, 200, - 10, 3, 126, 139, 126, 200, 176, 139, 200, 175, 10, 3, 126, 139, 126, 126, - 207, 18, 139, 126, 207, 17, 10, 3, 196, 169, 10, 3, 196, 164, 10, 3, 196, - 158, 10, 3, 196, 159, 220, 190, 10, 3, 196, 159, 25, 249, 135, 10, 3, - 196, 159, 25, 216, 100, 10, 3, 196, 159, 25, 126, 108, 126, 108, 66, 10, - 3, 196, 159, 25, 126, 108, 126, 108, 126, 230, 155, 10, 3, 196, 159, 230, - 155, 10, 3, 196, 159, 203, 94, 10, 3, 196, 159, 203, 95, 25, 249, 135, - 10, 3, 196, 153, 10, 3, 196, 120, 10, 3, 196, 121, 25, 220, 104, 10, 3, - 196, 121, 25, 216, 233, 108, 238, 32, 10, 3, 196, 121, 25, 203, 163, 10, - 3, 196, 121, 25, 66, 10, 3, 196, 119, 10, 3, 196, 115, 10, 3, 196, 116, - 25, 222, 54, 10, 3, 196, 116, 25, 168, 10, 3, 196, 113, 10, 3, 196, 114, - 230, 155, 10, 3, 196, 62, 10, 3, 196, 63, 238, 210, 196, 62, 10, 3, 196, - 63, 203, 94, 10, 3, 196, 60, 10, 3, 196, 61, 25, 42, 108, 140, 10, 3, - 196, 61, 25, 42, 108, 180, 10, 3, 196, 61, 25, 251, 207, 10, 3, 196, 61, - 25, 140, 10, 3, 196, 61, 25, 212, 130, 10, 3, 196, 61, 25, 196, 169, 10, - 3, 196, 61, 25, 196, 170, 108, 250, 209, 10, 3, 196, 61, 25, 196, 170, - 108, 248, 188, 10, 3, 196, 59, 10, 3, 196, 56, 10, 3, 196, 55, 10, 3, - 196, 51, 10, 3, 196, 52, 25, 65, 10, 3, 196, 52, 25, 250, 203, 10, 3, - 196, 52, 25, 164, 10, 3, 196, 52, 25, 235, 75, 10, 3, 196, 52, 25, 231, - 240, 10, 3, 196, 52, 25, 231, 222, 10, 3, 196, 52, 25, 231, 209, 199, 84, - 10, 3, 196, 52, 25, 231, 200, 10, 3, 196, 52, 25, 230, 179, 10, 3, 196, - 52, 25, 140, 10, 3, 196, 52, 25, 223, 201, 10, 3, 196, 52, 25, 223, 180, - 10, 3, 196, 52, 25, 223, 62, 10, 3, 196, 52, 25, 221, 166, 10, 3, 196, - 52, 25, 218, 208, 10, 3, 196, 52, 25, 216, 44, 10, 3, 196, 52, 25, 168, - 10, 3, 196, 52, 25, 203, 113, 10, 3, 196, 52, 25, 202, 199, 10, 3, 196, - 52, 25, 197, 94, 10, 3, 196, 52, 25, 126, 108, 230, 168, 10, 3, 196, 52, - 25, 196, 158, 10, 3, 196, 52, 25, 196, 49, 10, 3, 196, 49, 10, 3, 196, - 50, 25, 66, 10, 3, 196, 38, 10, 3, 196, 39, 25, 65, 10, 3, 196, 39, 25, - 220, 232, 10, 3, 196, 39, 25, 220, 197, 10, 3, 196, 39, 25, 199, 209, 10, - 3, 196, 34, 10, 3, 196, 37, 10, 3, 196, 35, 10, 3, 196, 31, 10, 3, 196, - 16, 10, 3, 196, 17, 25, 222, 54, 10, 3, 196, 14, 10, 3, 191, 123, 10, 3, - 191, 124, 199, 84, 10, 3, 191, 124, 112, 25, 220, 197, 10, 3, 191, 118, - 10, 3, 191, 107, 10, 3, 191, 86, 10, 3, 191, 30, 10, 3, 191, 31, 139, - 191, 30, 10, 3, 191, 29, 10, 3, 191, 27, 10, 3, 191, 28, 222, 116, 199, - 84, 10, 3, 191, 22, 10, 3, 191, 13, 10, 3, 190, 251, 10, 3, 190, 249, 10, - 3, 190, 250, 25, 65, 10, 3, 190, 248, 10, 3, 190, 247, 10, 3, 222, 79, - 234, 137, 10, 3, 252, 156, 25, 212, 130, 10, 3, 252, 73, 25, 65, 10, 3, - 251, 146, 25, 220, 213, 10, 3, 238, 23, 221, 125, 25, 196, 170, 108, 217, - 39, 10, 3, 238, 21, 10, 3, 236, 223, 108, 203, 5, 10, 3, 235, 88, 25, - 203, 113, 10, 3, 233, 181, 25, 230, 168, 10, 3, 233, 181, 25, 203, 113, - 10, 3, 231, 239, 25, 251, 133, 108, 222, 97, 108, 65, 10, 3, 231, 239, - 25, 250, 207, 10, 3, 231, 164, 10, 3, 231, 42, 10, 3, 228, 131, 10, 3, - 222, 142, 25, 251, 91, 10, 3, 222, 142, 25, 250, 206, 10, 3, 222, 142, - 25, 231, 23, 10, 3, 222, 142, 25, 230, 168, 10, 3, 222, 142, 25, 229, - 159, 25, 250, 207, 10, 3, 222, 142, 25, 218, 208, 10, 3, 222, 142, 25, - 168, 10, 3, 222, 142, 25, 202, 253, 10, 3, 222, 142, 25, 197, 94, 10, 3, - 222, 142, 25, 196, 60, 10, 3, 220, 105, 25, 231, 53, 10, 3, 218, 224, - 203, 95, 25, 249, 135, 10, 3, 218, 224, 25, 234, 10, 108, 220, 37, 10, 3, - 218, 224, 25, 203, 5, 10, 3, 216, 172, 10, 3, 215, 100, 25, 191, 123, 10, - 3, 214, 252, 10, 3, 213, 179, 10, 3, 213, 178, 10, 3, 213, 177, 25, 249, - 115, 10, 3, 213, 177, 25, 231, 53, 10, 3, 212, 148, 206, 122, 213, 170, - 237, 124, 10, 3, 209, 244, 250, 193, 10, 3, 209, 125, 10, 3, 205, 186, - 25, 223, 202, 230, 155, 10, 3, 198, 185, 10, 3, 196, 121, 25, 216, 232, - 10, 3, 126, 66, 10, 167, 3, 105, 250, 209, 10, 167, 3, 115, 250, 209, 10, - 167, 3, 232, 128, 250, 209, 10, 167, 3, 232, 226, 250, 209, 10, 167, 3, - 202, 136, 250, 209, 10, 167, 3, 203, 247, 250, 209, 10, 167, 3, 234, 164, - 250, 209, 10, 167, 3, 213, 175, 250, 209, 10, 167, 3, 115, 236, 222, 10, - 167, 3, 232, 128, 236, 222, 10, 167, 3, 232, 226, 236, 222, 10, 167, 3, - 202, 136, 236, 222, 10, 167, 3, 203, 247, 236, 222, 10, 167, 3, 234, 164, - 236, 222, 10, 167, 3, 213, 175, 236, 222, 10, 167, 3, 232, 128, 66, 10, - 167, 3, 232, 226, 66, 10, 167, 3, 202, 136, 66, 10, 167, 3, 203, 247, 66, - 10, 167, 3, 234, 164, 66, 10, 167, 3, 213, 175, 66, 10, 167, 3, 91, 231, - 136, 10, 167, 3, 105, 231, 136, 10, 167, 3, 115, 231, 136, 10, 167, 3, - 232, 128, 231, 136, 10, 167, 3, 232, 226, 231, 136, 10, 167, 3, 202, 136, - 231, 136, 10, 167, 3, 203, 247, 231, 136, 10, 167, 3, 234, 164, 231, 136, - 10, 167, 3, 213, 175, 231, 136, 10, 167, 3, 91, 231, 133, 10, 167, 3, - 105, 231, 133, 10, 167, 3, 115, 231, 133, 10, 167, 3, 232, 128, 231, 133, - 10, 167, 3, 232, 226, 231, 133, 10, 167, 3, 105, 203, 131, 10, 167, 3, - 115, 203, 131, 10, 167, 3, 115, 203, 132, 195, 168, 20, 10, 167, 3, 232, - 128, 203, 131, 10, 167, 3, 232, 226, 203, 131, 10, 167, 3, 202, 136, 203, - 131, 10, 167, 3, 203, 247, 203, 131, 10, 167, 3, 234, 164, 203, 131, 10, - 167, 3, 213, 175, 203, 131, 10, 167, 3, 91, 203, 124, 10, 167, 3, 105, - 203, 124, 10, 167, 3, 115, 203, 124, 10, 167, 3, 115, 203, 125, 195, 168, - 20, 10, 167, 3, 232, 128, 203, 124, 10, 167, 3, 232, 226, 203, 124, 10, - 167, 3, 203, 132, 25, 231, 223, 108, 236, 222, 10, 167, 3, 203, 132, 25, - 231, 223, 108, 216, 44, 10, 167, 3, 91, 247, 226, 10, 167, 3, 105, 247, - 226, 10, 167, 3, 115, 247, 226, 10, 167, 3, 115, 247, 227, 195, 168, 20, - 10, 167, 3, 232, 128, 247, 226, 10, 167, 3, 232, 226, 247, 226, 10, 167, - 3, 115, 195, 168, 232, 146, 234, 11, 10, 167, 3, 115, 195, 168, 232, 146, - 234, 8, 10, 167, 3, 232, 128, 195, 168, 232, 146, 219, 116, 10, 167, 3, - 232, 128, 195, 168, 232, 146, 219, 114, 10, 167, 3, 232, 128, 195, 168, - 232, 146, 219, 117, 65, 10, 167, 3, 232, 128, 195, 168, 232, 146, 219, - 117, 250, 120, 10, 167, 3, 202, 136, 195, 168, 232, 146, 250, 205, 10, - 167, 3, 203, 247, 195, 168, 232, 146, 223, 171, 10, 167, 3, 203, 247, - 195, 168, 232, 146, 223, 173, 65, 10, 167, 3, 203, 247, 195, 168, 232, - 146, 223, 173, 250, 120, 10, 167, 3, 234, 164, 195, 168, 232, 146, 196, - 33, 10, 167, 3, 234, 164, 195, 168, 232, 146, 196, 32, 10, 167, 3, 213, - 175, 195, 168, 232, 146, 223, 188, 10, 167, 3, 213, 175, 195, 168, 232, - 146, 223, 187, 10, 167, 3, 213, 175, 195, 168, 232, 146, 223, 186, 10, - 167, 3, 213, 175, 195, 168, 232, 146, 223, 189, 65, 10, 167, 3, 105, 250, - 210, 199, 84, 10, 167, 3, 115, 250, 210, 199, 84, 10, 167, 3, 232, 128, - 250, 210, 199, 84, 10, 167, 3, 232, 226, 250, 210, 199, 84, 10, 167, 3, - 202, 136, 250, 210, 199, 84, 10, 167, 3, 91, 249, 99, 10, 167, 3, 105, - 249, 99, 10, 167, 3, 115, 249, 99, 10, 167, 3, 232, 128, 249, 99, 10, - 167, 3, 232, 128, 249, 100, 195, 168, 20, 10, 167, 3, 232, 226, 249, 99, - 10, 167, 3, 232, 226, 249, 100, 195, 168, 20, 10, 167, 3, 213, 188, 10, - 167, 3, 213, 189, 10, 167, 3, 91, 234, 7, 10, 167, 3, 105, 234, 7, 10, - 167, 3, 91, 199, 1, 236, 222, 10, 167, 3, 105, 198, 254, 236, 222, 10, - 167, 3, 232, 226, 202, 123, 236, 222, 10, 167, 3, 91, 199, 1, 195, 168, - 232, 146, 65, 10, 167, 3, 105, 198, 254, 195, 168, 232, 146, 65, 10, 167, - 3, 91, 234, 160, 250, 209, 10, 167, 3, 91, 208, 23, 250, 209, 10, 167, 3, - 39, 250, 196, 91, 202, 124, 10, 167, 3, 39, 250, 196, 91, 208, 22, 10, - 167, 3, 91, 208, 23, 230, 149, 10, 167, 3, 91, 132, 230, 149, 10, 167, 3, - 234, 138, 91, 199, 0, 10, 167, 3, 234, 138, 105, 198, 253, 10, 167, 3, - 234, 138, 232, 135, 10, 167, 3, 234, 138, 233, 15, 10, 167, 3, 232, 128, - 126, 195, 168, 20, 10, 167, 3, 232, 226, 126, 195, 168, 20, 10, 167, 3, - 202, 136, 126, 195, 168, 20, 10, 167, 3, 203, 247, 126, 195, 168, 20, 10, - 167, 3, 234, 164, 126, 195, 168, 20, 10, 167, 3, 213, 175, 126, 195, 168, - 20, 10, 208, 152, 3, 39, 250, 196, 193, 23, 236, 205, 10, 208, 152, 3, - 81, 242, 83, 10, 208, 152, 3, 237, 39, 242, 83, 10, 208, 152, 3, 237, 39, - 197, 237, 10, 208, 152, 3, 237, 39, 208, 29, 10, 3, 252, 156, 25, 212, - 131, 199, 84, 10, 3, 252, 156, 25, 203, 3, 10, 3, 252, 43, 25, 234, 9, - 10, 3, 249, 136, 25, 236, 223, 199, 84, 10, 3, 249, 122, 25, 252, 72, 10, - 3, 249, 122, 25, 213, 219, 10, 3, 249, 122, 25, 191, 123, 10, 3, 248, 11, - 139, 248, 11, 25, 214, 253, 10, 3, 238, 33, 25, 199, 209, 10, 3, 238, 23, - 25, 220, 197, 10, 3, 237, 0, 25, 223, 201, 10, 3, 237, 0, 25, 126, 126, - 66, 10, 3, 236, 254, 25, 196, 158, 10, 3, 235, 83, 25, 251, 91, 10, 3, - 235, 83, 25, 250, 209, 10, 3, 235, 83, 25, 250, 210, 250, 183, 219, 224, - 10, 3, 235, 83, 25, 236, 243, 10, 3, 235, 83, 25, 235, 75, 10, 3, 235, - 83, 25, 234, 28, 10, 3, 235, 83, 25, 231, 240, 10, 3, 235, 83, 25, 231, - 53, 10, 3, 235, 83, 25, 231, 33, 230, 155, 10, 3, 235, 83, 25, 231, 23, - 10, 3, 235, 83, 25, 140, 10, 3, 235, 83, 25, 229, 158, 10, 3, 235, 83, - 25, 223, 202, 230, 155, 10, 3, 235, 83, 25, 222, 54, 10, 3, 235, 83, 25, - 220, 197, 10, 3, 235, 83, 25, 220, 190, 10, 3, 235, 83, 25, 220, 191, - 108, 222, 54, 10, 3, 235, 83, 25, 220, 92, 10, 3, 235, 83, 25, 220, 35, - 10, 3, 235, 83, 25, 220, 36, 25, 220, 197, 10, 3, 235, 83, 25, 218, 214, - 108, 231, 23, 10, 3, 235, 83, 25, 217, 39, 10, 3, 235, 83, 25, 216, 173, - 10, 3, 235, 83, 25, 216, 100, 10, 3, 235, 83, 25, 213, 219, 10, 3, 235, - 83, 25, 209, 185, 10, 3, 235, 83, 25, 203, 113, 10, 3, 235, 83, 25, 202, - 223, 230, 155, 10, 3, 234, 219, 25, 220, 197, 10, 3, 234, 219, 25, 210, - 137, 10, 3, 234, 29, 192, 235, 10, 3, 234, 10, 238, 210, 234, 9, 10, 3, - 233, 181, 203, 95, 25, 250, 209, 10, 3, 233, 181, 203, 95, 25, 229, 158, - 10, 3, 233, 181, 203, 95, 25, 223, 202, 230, 155, 10, 3, 233, 181, 203, - 95, 25, 173, 10, 3, 233, 181, 203, 95, 25, 220, 37, 10, 3, 233, 181, 203, - 95, 25, 216, 232, 10, 3, 233, 181, 203, 95, 25, 216, 173, 10, 3, 233, - 181, 203, 95, 25, 201, 4, 10, 3, 233, 181, 25, 201, 4, 10, 3, 231, 239, - 25, 249, 121, 10, 3, 231, 239, 25, 237, 0, 230, 155, 10, 3, 231, 239, 25, - 235, 83, 25, 223, 202, 230, 155, 10, 3, 231, 239, 25, 235, 83, 25, 222, - 54, 10, 3, 231, 239, 25, 234, 31, 10, 3, 231, 239, 25, 231, 240, 10, 3, - 231, 239, 25, 231, 201, 108, 237, 44, 10, 3, 231, 239, 25, 231, 201, 108, - 214, 121, 10, 3, 231, 239, 25, 230, 105, 108, 65, 10, 3, 231, 239, 25, - 220, 191, 108, 222, 54, 10, 3, 231, 239, 25, 220, 35, 10, 3, 231, 239, - 25, 220, 36, 25, 220, 197, 10, 3, 231, 239, 25, 218, 213, 10, 3, 231, - 239, 25, 215, 101, 10, 3, 231, 239, 25, 214, 121, 10, 3, 231, 239, 25, - 214, 122, 108, 234, 218, 10, 3, 231, 239, 25, 214, 122, 108, 231, 53, 10, - 3, 231, 239, 25, 203, 73, 10, 3, 231, 239, 25, 191, 13, 10, 3, 231, 234, - 206, 122, 213, 170, 237, 124, 10, 3, 231, 135, 25, 66, 10, 3, 231, 24, - 25, 231, 24, 238, 210, 231, 23, 10, 3, 230, 178, 25, 223, 202, 230, 155, - 10, 3, 230, 169, 108, 231, 24, 25, 199, 209, 10, 3, 230, 105, 199, 85, - 230, 155, 10, 3, 229, 159, 25, 250, 210, 139, 229, 159, 25, 250, 209, 10, - 3, 222, 142, 25, 248, 10, 10, 3, 222, 142, 25, 155, 10, 3, 222, 142, 25, - 126, 126, 66, 10, 3, 222, 142, 25, 196, 62, 10, 3, 220, 105, 25, 190, - 252, 139, 190, 251, 10, 3, 220, 93, 10, 3, 220, 91, 10, 3, 220, 90, 10, - 3, 220, 89, 10, 3, 220, 88, 10, 3, 220, 87, 10, 3, 220, 86, 10, 3, 220, - 85, 139, 220, 85, 230, 155, 10, 3, 220, 84, 10, 3, 220, 83, 139, 220, 82, - 10, 3, 220, 81, 10, 3, 220, 80, 10, 3, 220, 79, 10, 3, 220, 78, 10, 3, - 220, 77, 10, 3, 220, 76, 10, 3, 220, 75, 10, 3, 220, 74, 10, 3, 220, 73, - 10, 3, 220, 72, 10, 3, 220, 71, 10, 3, 220, 70, 10, 3, 220, 69, 10, 3, - 220, 68, 10, 3, 220, 67, 10, 3, 220, 66, 10, 3, 220, 65, 10, 3, 220, 64, - 10, 3, 220, 62, 10, 3, 220, 63, 25, 230, 179, 10, 3, 220, 63, 25, 223, - 201, 10, 3, 220, 63, 25, 210, 138, 108, 218, 222, 10, 3, 220, 63, 25, - 210, 138, 108, 210, 138, 108, 218, 222, 10, 3, 220, 63, 25, 196, 170, - 108, 249, 153, 10, 3, 220, 61, 10, 3, 220, 60, 10, 3, 220, 59, 10, 3, - 220, 58, 10, 3, 220, 57, 10, 3, 220, 56, 10, 3, 220, 55, 10, 3, 220, 54, - 10, 3, 220, 53, 10, 3, 220, 52, 10, 3, 220, 50, 10, 3, 220, 51, 25, 250, - 209, 10, 3, 220, 51, 25, 249, 135, 10, 3, 220, 51, 25, 235, 74, 230, 156, - 230, 155, 10, 3, 220, 51, 25, 220, 223, 10, 3, 220, 51, 25, 173, 10, 3, - 220, 51, 25, 199, 179, 10, 3, 220, 51, 25, 199, 145, 10, 3, 220, 51, 25, - 196, 169, 10, 3, 220, 51, 25, 196, 158, 10, 3, 220, 51, 25, 196, 49, 10, - 3, 220, 49, 10, 3, 220, 47, 10, 3, 220, 48, 25, 235, 87, 10, 3, 220, 48, - 25, 231, 240, 10, 3, 220, 48, 25, 223, 201, 10, 3, 220, 48, 25, 223, 202, - 230, 155, 10, 3, 220, 48, 25, 213, 219, 10, 3, 220, 48, 25, 210, 138, - 108, 210, 138, 108, 218, 222, 10, 3, 220, 48, 25, 203, 98, 108, 221, 166, - 10, 3, 220, 48, 25, 196, 158, 10, 3, 220, 48, 25, 196, 49, 10, 3, 220, - 45, 10, 3, 220, 44, 10, 3, 218, 224, 230, 156, 25, 250, 209, 10, 3, 218, - 224, 25, 236, 222, 10, 3, 218, 224, 25, 230, 73, 10, 3, 218, 224, 25, - 210, 137, 10, 3, 218, 224, 25, 210, 138, 108, 210, 138, 108, 218, 222, - 10, 3, 218, 224, 25, 199, 209, 10, 3, 216, 101, 108, 191, 122, 10, 3, - 215, 102, 139, 215, 102, 25, 231, 240, 10, 3, 215, 102, 139, 215, 102, - 25, 222, 96, 10, 3, 213, 177, 25, 237, 0, 230, 155, 10, 3, 213, 177, 25, - 231, 23, 10, 3, 213, 177, 25, 230, 160, 10, 3, 213, 177, 25, 229, 158, - 10, 3, 213, 177, 25, 221, 242, 10, 3, 213, 177, 25, 220, 88, 10, 3, 213, - 177, 25, 217, 39, 10, 3, 213, 177, 25, 210, 138, 108, 210, 137, 10, 3, - 213, 177, 25, 66, 10, 3, 213, 177, 25, 126, 108, 66, 10, 3, 213, 177, 25, - 196, 49, 10, 3, 205, 186, 230, 156, 25, 140, 10, 3, 205, 186, 25, 234, - 103, 10, 3, 205, 186, 25, 203, 114, 250, 183, 219, 224, 10, 3, 205, 186, - 25, 199, 209, 10, 3, 203, 162, 199, 84, 10, 3, 203, 114, 139, 203, 113, - 10, 3, 203, 114, 108, 228, 151, 10, 3, 203, 114, 108, 214, 229, 10, 3, - 203, 114, 108, 205, 127, 10, 3, 203, 4, 108, 235, 83, 25, 213, 219, 10, - 3, 203, 4, 108, 234, 219, 25, 251, 132, 10, 3, 202, 223, 25, 199, 209, - 10, 3, 199, 210, 108, 205, 185, 10, 3, 197, 77, 25, 231, 209, 199, 84, - 10, 3, 197, 77, 25, 115, 236, 222, 10, 3, 196, 61, 223, 92, 10, 3, 196, - 61, 25, 196, 158, 10, 3, 196, 52, 25, 237, 224, 10, 3, 196, 52, 25, 220, - 46, 10, 3, 196, 52, 25, 218, 222, 10, 3, 191, 122, 10, 3, 190, 252, 139, - 190, 252, 108, 205, 127, 10, 3, 190, 250, 25, 115, 236, 223, 199, 84, - 238, 134, 3, 242, 198, 238, 134, 3, 242, 197, 238, 134, 3, 242, 196, 238, - 134, 3, 242, 195, 238, 134, 3, 242, 194, 238, 134, 3, 242, 193, 238, 134, - 3, 242, 192, 238, 134, 3, 242, 191, 238, 134, 3, 242, 190, 238, 134, 3, - 242, 189, 238, 134, 3, 242, 188, 238, 134, 3, 242, 187, 238, 134, 3, 242, - 186, 238, 134, 3, 242, 185, 238, 134, 3, 242, 184, 238, 134, 3, 242, 183, - 238, 134, 3, 242, 182, 238, 134, 3, 242, 181, 238, 134, 3, 242, 180, 238, - 134, 3, 242, 179, 238, 134, 3, 242, 178, 238, 134, 3, 242, 177, 238, 134, - 3, 242, 176, 238, 134, 3, 242, 175, 238, 134, 3, 242, 174, 238, 134, 3, - 242, 173, 238, 134, 3, 242, 172, 238, 134, 3, 242, 171, 238, 134, 3, 242, - 170, 238, 134, 3, 242, 169, 238, 134, 3, 242, 168, 238, 134, 3, 242, 167, - 238, 134, 3, 242, 166, 238, 134, 3, 242, 165, 238, 134, 3, 242, 164, 238, - 134, 3, 242, 163, 238, 134, 3, 242, 162, 238, 134, 3, 242, 161, 238, 134, - 3, 242, 160, 238, 134, 3, 242, 159, 238, 134, 3, 242, 158, 238, 134, 3, - 242, 157, 238, 134, 3, 242, 156, 238, 134, 3, 242, 155, 238, 134, 3, 242, - 154, 238, 134, 3, 242, 153, 238, 134, 3, 242, 152, 238, 134, 3, 242, 151, - 238, 134, 3, 242, 150, 238, 134, 3, 242, 149, 238, 134, 3, 242, 148, 238, - 134, 3, 242, 147, 238, 134, 3, 242, 146, 238, 134, 3, 242, 145, 238, 134, - 3, 242, 144, 238, 134, 3, 242, 143, 238, 134, 3, 242, 142, 238, 134, 3, - 242, 141, 238, 134, 3, 242, 140, 238, 134, 3, 242, 139, 238, 134, 3, 242, - 138, 238, 134, 3, 242, 137, 238, 134, 3, 242, 136, 238, 134, 3, 242, 135, - 238, 134, 3, 242, 134, 238, 134, 3, 242, 133, 238, 134, 3, 242, 132, 238, - 134, 3, 242, 131, 238, 134, 3, 242, 130, 238, 134, 3, 242, 129, 238, 134, - 3, 242, 128, 238, 134, 3, 242, 127, 238, 134, 3, 242, 126, 238, 134, 3, - 242, 125, 238, 134, 3, 242, 124, 238, 134, 3, 242, 123, 238, 134, 3, 242, - 122, 238, 134, 3, 242, 121, 238, 134, 3, 242, 120, 238, 134, 3, 242, 119, - 238, 134, 3, 242, 118, 238, 134, 3, 242, 117, 238, 134, 3, 242, 116, 238, - 134, 3, 242, 115, 238, 134, 3, 242, 114, 238, 134, 3, 242, 113, 238, 134, - 3, 242, 112, 238, 134, 3, 242, 111, 238, 134, 3, 242, 110, 238, 134, 3, - 242, 109, 238, 134, 3, 242, 108, 238, 134, 3, 242, 107, 238, 134, 3, 242, - 106, 238, 134, 3, 242, 105, 238, 134, 3, 242, 104, 238, 134, 3, 242, 103, - 238, 134, 3, 242, 102, 238, 134, 3, 242, 101, 238, 134, 3, 242, 100, 14, - 7, 255, 199, 14, 7, 255, 198, 14, 7, 255, 197, 14, 7, 255, 196, 14, 7, - 255, 195, 14, 7, 255, 194, 14, 7, 255, 193, 14, 7, 255, 192, 14, 7, 255, - 191, 14, 7, 255, 190, 14, 7, 255, 189, 14, 7, 255, 188, 14, 7, 255, 187, - 14, 7, 255, 185, 14, 7, 255, 184, 14, 7, 255, 183, 14, 7, 255, 182, 14, - 7, 255, 181, 14, 7, 255, 180, 14, 7, 255, 179, 14, 7, 255, 178, 14, 7, - 255, 177, 14, 7, 255, 176, 14, 7, 255, 175, 14, 7, 255, 174, 14, 7, 255, - 173, 14, 7, 255, 172, 14, 7, 255, 171, 14, 7, 255, 170, 14, 7, 255, 169, - 14, 7, 255, 168, 14, 7, 255, 166, 14, 7, 255, 165, 14, 7, 255, 163, 14, - 7, 255, 162, 14, 7, 255, 161, 14, 7, 255, 160, 14, 7, 255, 159, 14, 7, - 255, 158, 14, 7, 255, 157, 14, 7, 255, 156, 14, 7, 255, 155, 14, 7, 255, - 154, 14, 7, 255, 153, 14, 7, 255, 152, 14, 7, 255, 150, 14, 7, 255, 149, - 14, 7, 255, 148, 14, 7, 255, 146, 14, 7, 255, 145, 14, 7, 255, 144, 14, - 7, 255, 143, 14, 7, 255, 142, 14, 7, 255, 141, 14, 7, 255, 140, 14, 7, - 255, 139, 14, 7, 255, 136, 14, 7, 255, 135, 14, 7, 255, 134, 14, 7, 255, - 133, 14, 7, 255, 132, 14, 7, 255, 131, 14, 7, 255, 130, 14, 7, 255, 129, - 14, 7, 255, 128, 14, 7, 255, 127, 14, 7, 255, 126, 14, 7, 255, 125, 14, - 7, 255, 124, 14, 7, 255, 123, 14, 7, 255, 122, 14, 7, 255, 121, 14, 7, - 255, 120, 14, 7, 255, 119, 14, 7, 255, 118, 14, 7, 255, 117, 14, 7, 255, - 113, 14, 7, 255, 112, 14, 7, 255, 111, 14, 7, 255, 110, 14, 7, 250, 118, - 14, 7, 250, 116, 14, 7, 250, 114, 14, 7, 250, 112, 14, 7, 250, 110, 14, - 7, 250, 109, 14, 7, 250, 107, 14, 7, 250, 105, 14, 7, 250, 103, 14, 7, - 250, 101, 14, 7, 247, 189, 14, 7, 247, 188, 14, 7, 247, 187, 14, 7, 247, - 186, 14, 7, 247, 185, 14, 7, 247, 184, 14, 7, 247, 183, 14, 7, 247, 182, - 14, 7, 247, 181, 14, 7, 247, 180, 14, 7, 247, 179, 14, 7, 247, 178, 14, - 7, 247, 177, 14, 7, 247, 176, 14, 7, 247, 175, 14, 7, 247, 174, 14, 7, - 247, 173, 14, 7, 247, 172, 14, 7, 247, 171, 14, 7, 247, 170, 14, 7, 247, - 169, 14, 7, 247, 168, 14, 7, 247, 167, 14, 7, 247, 166, 14, 7, 247, 165, - 14, 7, 247, 164, 14, 7, 247, 163, 14, 7, 247, 162, 14, 7, 238, 126, 14, - 7, 238, 125, 14, 7, 238, 124, 14, 7, 238, 123, 14, 7, 238, 122, 14, 7, - 238, 121, 14, 7, 238, 120, 14, 7, 238, 119, 14, 7, 238, 118, 14, 7, 238, - 117, 14, 7, 238, 116, 14, 7, 238, 115, 14, 7, 238, 114, 14, 7, 238, 113, - 14, 7, 238, 112, 14, 7, 238, 111, 14, 7, 238, 110, 14, 7, 238, 109, 14, - 7, 238, 108, 14, 7, 238, 107, 14, 7, 238, 106, 14, 7, 238, 105, 14, 7, - 238, 104, 14, 7, 238, 103, 14, 7, 238, 102, 14, 7, 238, 101, 14, 7, 238, - 100, 14, 7, 238, 99, 14, 7, 238, 98, 14, 7, 238, 97, 14, 7, 238, 96, 14, - 7, 238, 95, 14, 7, 238, 94, 14, 7, 238, 93, 14, 7, 238, 92, 14, 7, 238, - 91, 14, 7, 238, 90, 14, 7, 238, 89, 14, 7, 238, 88, 14, 7, 238, 87, 14, - 7, 238, 86, 14, 7, 238, 85, 14, 7, 238, 84, 14, 7, 238, 83, 14, 7, 238, - 82, 14, 7, 238, 81, 14, 7, 238, 80, 14, 7, 238, 79, 14, 7, 238, 78, 14, - 7, 238, 77, 14, 7, 238, 76, 14, 7, 238, 75, 14, 7, 238, 74, 14, 7, 238, - 73, 14, 7, 238, 72, 14, 7, 238, 71, 14, 7, 238, 70, 14, 7, 238, 69, 14, - 7, 238, 68, 14, 7, 238, 67, 14, 7, 238, 66, 14, 7, 238, 65, 14, 7, 238, - 64, 14, 7, 238, 63, 14, 7, 238, 62, 14, 7, 238, 61, 14, 7, 238, 60, 14, - 7, 238, 59, 14, 7, 238, 58, 14, 7, 238, 57, 14, 7, 238, 56, 14, 7, 238, - 55, 14, 7, 238, 54, 14, 7, 238, 53, 14, 7, 238, 52, 14, 7, 238, 51, 14, - 7, 238, 50, 14, 7, 238, 49, 14, 7, 238, 48, 14, 7, 238, 47, 14, 7, 238, - 46, 14, 7, 238, 45, 14, 7, 238, 44, 14, 7, 238, 43, 14, 7, 238, 42, 14, - 7, 238, 41, 14, 7, 238, 40, 14, 7, 238, 39, 14, 7, 238, 38, 14, 7, 238, - 37, 14, 7, 238, 36, 14, 7, 238, 35, 14, 7, 235, 7, 14, 7, 235, 6, 14, 7, - 235, 5, 14, 7, 235, 4, 14, 7, 235, 3, 14, 7, 235, 2, 14, 7, 235, 1, 14, - 7, 235, 0, 14, 7, 234, 255, 14, 7, 234, 254, 14, 7, 234, 253, 14, 7, 234, - 252, 14, 7, 234, 251, 14, 7, 234, 250, 14, 7, 234, 249, 14, 7, 234, 248, - 14, 7, 234, 247, 14, 7, 234, 246, 14, 7, 234, 245, 14, 7, 234, 244, 14, - 7, 234, 243, 14, 7, 234, 242, 14, 7, 234, 241, 14, 7, 234, 240, 14, 7, - 234, 239, 14, 7, 234, 238, 14, 7, 234, 237, 14, 7, 234, 236, 14, 7, 234, - 235, 14, 7, 234, 234, 14, 7, 234, 233, 14, 7, 234, 232, 14, 7, 234, 231, - 14, 7, 234, 230, 14, 7, 234, 229, 14, 7, 234, 228, 14, 7, 234, 227, 14, - 7, 234, 226, 14, 7, 234, 225, 14, 7, 234, 224, 14, 7, 234, 223, 14, 7, - 234, 222, 14, 7, 234, 221, 14, 7, 234, 220, 14, 7, 233, 174, 14, 7, 233, - 173, 14, 7, 233, 172, 14, 7, 233, 171, 14, 7, 233, 170, 14, 7, 233, 169, - 14, 7, 233, 168, 14, 7, 233, 167, 14, 7, 233, 166, 14, 7, 233, 165, 14, - 7, 233, 164, 14, 7, 233, 163, 14, 7, 233, 162, 14, 7, 233, 161, 14, 7, - 233, 160, 14, 7, 233, 159, 14, 7, 233, 158, 14, 7, 233, 157, 14, 7, 233, - 156, 14, 7, 233, 155, 14, 7, 233, 154, 14, 7, 233, 153, 14, 7, 233, 152, - 14, 7, 233, 151, 14, 7, 233, 150, 14, 7, 233, 149, 14, 7, 233, 148, 14, - 7, 233, 147, 14, 7, 233, 146, 14, 7, 233, 145, 14, 7, 233, 144, 14, 7, - 233, 143, 14, 7, 233, 142, 14, 7, 233, 141, 14, 7, 233, 140, 14, 7, 233, - 139, 14, 7, 233, 138, 14, 7, 233, 137, 14, 7, 233, 136, 14, 7, 233, 135, - 14, 7, 233, 134, 14, 7, 233, 133, 14, 7, 233, 132, 14, 7, 233, 131, 14, - 7, 233, 130, 14, 7, 233, 129, 14, 7, 233, 128, 14, 7, 233, 127, 14, 7, - 233, 126, 14, 7, 233, 125, 14, 7, 233, 124, 14, 7, 233, 123, 14, 7, 233, - 122, 14, 7, 233, 121, 14, 7, 233, 120, 14, 7, 233, 119, 14, 7, 233, 118, - 14, 7, 233, 117, 14, 7, 233, 116, 14, 7, 233, 115, 14, 7, 233, 114, 14, - 7, 233, 113, 14, 7, 233, 112, 14, 7, 233, 111, 14, 7, 233, 110, 14, 7, - 232, 50, 14, 7, 232, 49, 14, 7, 232, 48, 14, 7, 232, 47, 14, 7, 232, 46, - 14, 7, 232, 45, 14, 7, 232, 44, 14, 7, 232, 43, 14, 7, 232, 42, 14, 7, - 232, 41, 14, 7, 232, 40, 14, 7, 232, 39, 14, 7, 232, 38, 14, 7, 232, 37, - 14, 7, 232, 36, 14, 7, 232, 35, 14, 7, 232, 34, 14, 7, 232, 33, 14, 7, - 232, 32, 14, 7, 232, 31, 14, 7, 232, 30, 14, 7, 232, 29, 14, 7, 232, 28, - 14, 7, 232, 27, 14, 7, 232, 26, 14, 7, 232, 25, 14, 7, 232, 24, 14, 7, - 232, 23, 14, 7, 232, 22, 14, 7, 232, 21, 14, 7, 232, 20, 14, 7, 232, 19, - 14, 7, 232, 18, 14, 7, 232, 17, 14, 7, 232, 16, 14, 7, 232, 15, 14, 7, - 232, 14, 14, 7, 232, 13, 14, 7, 232, 12, 14, 7, 232, 11, 14, 7, 232, 10, - 14, 7, 232, 9, 14, 7, 232, 8, 14, 7, 232, 7, 14, 7, 232, 6, 14, 7, 232, - 5, 14, 7, 232, 4, 14, 7, 232, 3, 14, 7, 232, 2, 14, 7, 232, 1, 14, 7, - 232, 0, 14, 7, 231, 255, 14, 7, 231, 254, 14, 7, 231, 253, 14, 7, 231, - 252, 14, 7, 231, 251, 14, 7, 231, 250, 14, 7, 231, 249, 14, 7, 231, 248, - 14, 7, 231, 247, 14, 7, 231, 246, 14, 7, 231, 245, 14, 7, 231, 244, 14, - 7, 231, 243, 14, 7, 230, 114, 14, 7, 230, 113, 14, 7, 230, 112, 14, 7, - 230, 111, 14, 7, 230, 110, 14, 7, 230, 109, 14, 7, 230, 108, 14, 7, 230, - 107, 14, 7, 230, 106, 14, 7, 228, 54, 14, 7, 228, 53, 14, 7, 228, 52, 14, - 7, 228, 51, 14, 7, 228, 50, 14, 7, 228, 49, 14, 7, 228, 48, 14, 7, 228, - 47, 14, 7, 228, 46, 14, 7, 228, 45, 14, 7, 228, 44, 14, 7, 228, 43, 14, - 7, 228, 42, 14, 7, 228, 41, 14, 7, 228, 40, 14, 7, 228, 39, 14, 7, 228, - 38, 14, 7, 228, 37, 14, 7, 228, 36, 14, 7, 222, 151, 14, 7, 222, 150, 14, - 7, 222, 149, 14, 7, 222, 148, 14, 7, 222, 147, 14, 7, 222, 146, 14, 7, - 222, 145, 14, 7, 222, 144, 14, 7, 220, 140, 14, 7, 220, 139, 14, 7, 220, - 138, 14, 7, 220, 137, 14, 7, 220, 136, 14, 7, 220, 135, 14, 7, 220, 134, - 14, 7, 220, 133, 14, 7, 220, 132, 14, 7, 220, 131, 14, 7, 218, 166, 14, - 7, 218, 165, 14, 7, 218, 164, 14, 7, 218, 162, 14, 7, 218, 160, 14, 7, - 218, 159, 14, 7, 218, 157, 14, 7, 218, 155, 14, 7, 218, 153, 14, 7, 218, - 151, 14, 7, 218, 149, 14, 7, 218, 147, 14, 7, 218, 145, 14, 7, 218, 144, - 14, 7, 218, 142, 14, 7, 218, 140, 14, 7, 218, 139, 14, 7, 218, 138, 14, - 7, 218, 137, 14, 7, 218, 136, 14, 7, 218, 135, 14, 7, 218, 134, 14, 7, - 218, 133, 14, 7, 218, 132, 14, 7, 218, 130, 14, 7, 218, 128, 14, 7, 218, - 126, 14, 7, 218, 125, 14, 7, 218, 123, 14, 7, 218, 122, 14, 7, 218, 120, - 14, 7, 218, 119, 14, 7, 218, 117, 14, 7, 218, 115, 14, 7, 218, 113, 14, - 7, 218, 111, 14, 7, 218, 109, 14, 7, 218, 108, 14, 7, 218, 106, 14, 7, - 218, 104, 14, 7, 218, 103, 14, 7, 218, 101, 14, 7, 218, 99, 14, 7, 218, - 97, 14, 7, 218, 95, 14, 7, 218, 94, 14, 7, 218, 92, 14, 7, 218, 90, 14, - 7, 218, 88, 14, 7, 218, 87, 14, 7, 218, 85, 14, 7, 218, 83, 14, 7, 218, - 82, 14, 7, 218, 81, 14, 7, 218, 79, 14, 7, 218, 77, 14, 7, 218, 75, 14, - 7, 218, 73, 14, 7, 218, 71, 14, 7, 218, 69, 14, 7, 218, 67, 14, 7, 218, - 66, 14, 7, 218, 64, 14, 7, 218, 62, 14, 7, 218, 60, 14, 7, 218, 58, 14, - 7, 215, 56, 14, 7, 215, 55, 14, 7, 215, 54, 14, 7, 215, 53, 14, 7, 215, - 52, 14, 7, 215, 51, 14, 7, 215, 50, 14, 7, 215, 49, 14, 7, 215, 48, 14, - 7, 215, 47, 14, 7, 215, 46, 14, 7, 215, 45, 14, 7, 215, 44, 14, 7, 215, - 43, 14, 7, 215, 42, 14, 7, 215, 41, 14, 7, 215, 40, 14, 7, 215, 39, 14, - 7, 215, 38, 14, 7, 215, 37, 14, 7, 215, 36, 14, 7, 215, 35, 14, 7, 215, - 34, 14, 7, 215, 33, 14, 7, 215, 32, 14, 7, 215, 31, 14, 7, 215, 30, 14, - 7, 215, 29, 14, 7, 215, 28, 14, 7, 215, 27, 14, 7, 215, 26, 14, 7, 215, - 25, 14, 7, 215, 24, 14, 7, 215, 23, 14, 7, 215, 22, 14, 7, 215, 21, 14, - 7, 215, 20, 14, 7, 215, 19, 14, 7, 215, 18, 14, 7, 215, 17, 14, 7, 215, - 16, 14, 7, 215, 15, 14, 7, 215, 14, 14, 7, 215, 13, 14, 7, 215, 12, 14, - 7, 215, 11, 14, 7, 215, 10, 14, 7, 215, 9, 14, 7, 215, 8, 14, 7, 213, - 104, 14, 7, 213, 103, 14, 7, 213, 102, 14, 7, 213, 101, 14, 7, 213, 100, - 14, 7, 213, 99, 14, 7, 213, 98, 14, 7, 213, 97, 14, 7, 213, 96, 14, 7, - 213, 95, 14, 7, 213, 94, 14, 7, 213, 93, 14, 7, 213, 92, 14, 7, 213, 91, - 14, 7, 213, 90, 14, 7, 213, 89, 14, 7, 213, 88, 14, 7, 213, 87, 14, 7, - 213, 86, 14, 7, 213, 85, 14, 7, 213, 84, 14, 7, 213, 83, 14, 7, 212, 174, - 14, 7, 212, 173, 14, 7, 212, 172, 14, 7, 212, 171, 14, 7, 212, 170, 14, - 7, 212, 169, 14, 7, 212, 168, 14, 7, 212, 167, 14, 7, 212, 166, 14, 7, - 212, 165, 14, 7, 212, 164, 14, 7, 212, 163, 14, 7, 212, 162, 14, 7, 212, - 161, 14, 7, 212, 160, 14, 7, 212, 159, 14, 7, 212, 158, 14, 7, 212, 157, - 14, 7, 212, 156, 14, 7, 212, 155, 14, 7, 212, 154, 14, 7, 212, 153, 14, - 7, 212, 152, 14, 7, 212, 151, 14, 7, 212, 150, 14, 7, 212, 149, 14, 7, - 212, 2, 14, 7, 212, 1, 14, 7, 212, 0, 14, 7, 211, 255, 14, 7, 211, 254, - 14, 7, 211, 253, 14, 7, 211, 252, 14, 7, 211, 251, 14, 7, 211, 250, 14, - 7, 211, 249, 14, 7, 211, 248, 14, 7, 211, 247, 14, 7, 211, 246, 14, 7, - 211, 245, 14, 7, 211, 244, 14, 7, 211, 243, 14, 7, 211, 242, 14, 7, 211, - 241, 14, 7, 211, 240, 14, 7, 211, 239, 14, 7, 211, 238, 14, 7, 211, 237, - 14, 7, 211, 236, 14, 7, 211, 235, 14, 7, 211, 234, 14, 7, 211, 233, 14, - 7, 211, 232, 14, 7, 211, 231, 14, 7, 211, 230, 14, 7, 211, 229, 14, 7, - 211, 228, 14, 7, 211, 227, 14, 7, 211, 226, 14, 7, 211, 225, 14, 7, 211, - 224, 14, 7, 211, 223, 14, 7, 211, 222, 14, 7, 211, 221, 14, 7, 211, 220, - 14, 7, 211, 219, 14, 7, 211, 218, 14, 7, 211, 217, 14, 7, 211, 216, 14, - 7, 211, 215, 14, 7, 211, 214, 14, 7, 211, 213, 14, 7, 211, 212, 14, 7, - 211, 211, 14, 7, 211, 210, 14, 7, 211, 209, 14, 7, 211, 208, 14, 7, 211, - 207, 14, 7, 211, 206, 14, 7, 211, 205, 14, 7, 211, 204, 14, 7, 211, 203, - 14, 7, 211, 202, 14, 7, 211, 201, 14, 7, 211, 200, 14, 7, 211, 199, 14, - 7, 211, 198, 14, 7, 211, 197, 14, 7, 211, 196, 14, 7, 211, 195, 14, 7, - 211, 194, 14, 7, 211, 193, 14, 7, 211, 192, 14, 7, 211, 191, 14, 7, 211, - 190, 14, 7, 211, 189, 14, 7, 211, 188, 14, 7, 211, 187, 14, 7, 211, 186, - 14, 7, 211, 185, 14, 7, 211, 184, 14, 7, 210, 235, 14, 7, 210, 234, 14, - 7, 210, 233, 14, 7, 210, 232, 14, 7, 210, 231, 14, 7, 210, 230, 14, 7, - 210, 229, 14, 7, 210, 228, 14, 7, 210, 227, 14, 7, 210, 226, 14, 7, 210, - 225, 14, 7, 210, 224, 14, 7, 210, 223, 14, 7, 208, 103, 14, 7, 208, 102, - 14, 7, 208, 101, 14, 7, 208, 100, 14, 7, 208, 99, 14, 7, 208, 98, 14, 7, - 208, 97, 14, 7, 207, 220, 14, 7, 207, 219, 14, 7, 207, 218, 14, 7, 207, - 217, 14, 7, 207, 216, 14, 7, 207, 215, 14, 7, 207, 214, 14, 7, 207, 213, - 14, 7, 207, 212, 14, 7, 207, 211, 14, 7, 207, 210, 14, 7, 207, 209, 14, - 7, 207, 208, 14, 7, 207, 207, 14, 7, 207, 206, 14, 7, 207, 205, 14, 7, - 207, 204, 14, 7, 207, 203, 14, 7, 207, 202, 14, 7, 207, 201, 14, 7, 207, - 200, 14, 7, 207, 199, 14, 7, 207, 198, 14, 7, 207, 197, 14, 7, 207, 196, - 14, 7, 207, 195, 14, 7, 207, 194, 14, 7, 207, 193, 14, 7, 207, 192, 14, - 7, 207, 191, 14, 7, 207, 190, 14, 7, 207, 189, 14, 7, 207, 188, 14, 7, - 207, 187, 14, 7, 206, 5, 14, 7, 206, 4, 14, 7, 206, 3, 14, 7, 206, 2, 14, - 7, 206, 1, 14, 7, 206, 0, 14, 7, 205, 255, 14, 7, 205, 254, 14, 7, 205, - 253, 14, 7, 205, 252, 14, 7, 205, 251, 14, 7, 205, 250, 14, 7, 205, 249, - 14, 7, 205, 248, 14, 7, 205, 247, 14, 7, 205, 246, 14, 7, 205, 245, 14, - 7, 205, 244, 14, 7, 205, 243, 14, 7, 205, 242, 14, 7, 205, 241, 14, 7, - 205, 240, 14, 7, 205, 239, 14, 7, 205, 238, 14, 7, 205, 237, 14, 7, 205, - 236, 14, 7, 205, 235, 14, 7, 205, 234, 14, 7, 205, 233, 14, 7, 205, 232, - 14, 7, 205, 231, 14, 7, 205, 230, 14, 7, 205, 229, 14, 7, 205, 228, 14, - 7, 205, 227, 14, 7, 205, 226, 14, 7, 205, 225, 14, 7, 205, 224, 14, 7, - 205, 223, 14, 7, 205, 222, 14, 7, 205, 221, 14, 7, 205, 220, 14, 7, 205, - 219, 14, 7, 205, 218, 14, 7, 205, 217, 14, 7, 205, 216, 14, 7, 205, 215, - 14, 7, 205, 214, 14, 7, 205, 213, 14, 7, 205, 212, 14, 7, 205, 211, 14, - 7, 205, 210, 14, 7, 205, 209, 14, 7, 205, 208, 14, 7, 200, 40, 14, 7, - 200, 39, 14, 7, 200, 38, 14, 7, 200, 37, 14, 7, 200, 36, 14, 7, 200, 35, - 14, 7, 200, 34, 14, 7, 200, 33, 14, 7, 200, 32, 14, 7, 200, 31, 14, 7, - 200, 30, 14, 7, 200, 29, 14, 7, 200, 28, 14, 7, 200, 27, 14, 7, 200, 26, - 14, 7, 200, 25, 14, 7, 200, 24, 14, 7, 200, 23, 14, 7, 200, 22, 14, 7, - 200, 21, 14, 7, 200, 20, 14, 7, 200, 19, 14, 7, 200, 18, 14, 7, 200, 17, - 14, 7, 200, 16, 14, 7, 200, 15, 14, 7, 200, 14, 14, 7, 200, 13, 14, 7, - 200, 12, 14, 7, 200, 11, 14, 7, 200, 10, 14, 7, 200, 9, 14, 7, 200, 8, - 14, 7, 200, 7, 14, 7, 200, 6, 14, 7, 200, 5, 14, 7, 200, 4, 14, 7, 200, - 3, 14, 7, 200, 2, 14, 7, 200, 1, 14, 7, 200, 0, 14, 7, 199, 255, 14, 7, - 199, 254, 14, 7, 199, 253, 14, 7, 196, 217, 14, 7, 196, 216, 14, 7, 196, - 215, 14, 7, 196, 214, 14, 7, 196, 213, 14, 7, 196, 212, 14, 7, 196, 211, - 14, 7, 196, 210, 14, 7, 196, 209, 14, 7, 196, 208, 14, 7, 196, 207, 14, - 7, 196, 206, 14, 7, 196, 205, 14, 7, 196, 204, 14, 7, 196, 203, 14, 7, - 196, 202, 14, 7, 196, 201, 14, 7, 196, 200, 14, 7, 196, 199, 14, 7, 196, - 198, 14, 7, 196, 197, 14, 7, 196, 196, 14, 7, 196, 195, 14, 7, 196, 194, - 14, 7, 196, 193, 14, 7, 196, 192, 14, 7, 196, 191, 14, 7, 196, 190, 14, - 7, 196, 189, 14, 7, 196, 188, 14, 7, 196, 187, 14, 7, 196, 186, 14, 7, - 196, 185, 14, 7, 196, 184, 14, 7, 196, 183, 14, 7, 196, 182, 14, 7, 196, - 181, 14, 7, 196, 180, 14, 7, 196, 179, 14, 7, 196, 178, 14, 7, 196, 177, - 14, 7, 196, 176, 14, 7, 196, 175, 14, 7, 196, 174, 14, 7, 196, 173, 14, - 7, 196, 172, 14, 7, 196, 171, 14, 7, 196, 11, 14, 7, 196, 10, 14, 7, 196, - 9, 14, 7, 196, 8, 14, 7, 196, 7, 14, 7, 196, 6, 14, 7, 196, 5, 14, 7, - 196, 4, 14, 7, 196, 3, 14, 7, 196, 2, 14, 7, 196, 1, 14, 7, 196, 0, 14, - 7, 195, 255, 14, 7, 195, 254, 14, 7, 195, 253, 14, 7, 195, 252, 14, 7, - 195, 251, 14, 7, 195, 250, 14, 7, 195, 249, 14, 7, 195, 248, 14, 7, 195, - 247, 14, 7, 195, 246, 14, 7, 195, 245, 14, 7, 195, 244, 14, 7, 195, 243, - 14, 7, 195, 242, 14, 7, 195, 240, 14, 7, 195, 239, 14, 7, 195, 238, 14, - 7, 195, 237, 14, 7, 195, 236, 14, 7, 195, 235, 14, 7, 195, 234, 14, 7, - 195, 233, 14, 7, 195, 232, 14, 7, 195, 231, 14, 7, 195, 230, 14, 7, 195, - 229, 14, 7, 195, 228, 14, 7, 195, 227, 14, 7, 195, 226, 14, 7, 195, 225, - 14, 7, 195, 224, 14, 7, 195, 223, 14, 7, 195, 222, 14, 7, 195, 221, 14, - 7, 195, 220, 14, 7, 195, 219, 14, 7, 195, 218, 14, 7, 195, 217, 14, 7, - 195, 216, 14, 7, 195, 215, 14, 7, 195, 214, 14, 7, 195, 213, 14, 7, 195, - 212, 14, 7, 195, 211, 14, 7, 195, 210, 14, 7, 195, 209, 14, 7, 195, 208, - 14, 7, 195, 207, 14, 7, 195, 206, 14, 7, 195, 205, 14, 7, 195, 204, 14, - 7, 195, 203, 14, 7, 195, 202, 14, 7, 195, 201, 14, 7, 195, 200, 14, 7, - 195, 199, 14, 7, 195, 198, 14, 7, 195, 197, 14, 7, 195, 196, 14, 7, 195, - 195, 14, 7, 195, 194, 14, 7, 195, 193, 14, 7, 195, 192, 14, 7, 195, 191, - 14, 7, 195, 190, 14, 7, 193, 223, 14, 7, 193, 222, 14, 7, 193, 221, 14, - 7, 193, 220, 14, 7, 193, 219, 14, 7, 193, 218, 14, 7, 193, 217, 14, 7, - 193, 216, 14, 7, 193, 215, 14, 7, 193, 214, 14, 7, 193, 213, 14, 7, 193, - 212, 14, 7, 193, 211, 14, 7, 193, 210, 14, 7, 193, 209, 14, 7, 193, 208, - 14, 7, 193, 207, 14, 7, 193, 206, 14, 7, 193, 205, 14, 7, 193, 204, 14, - 7, 193, 203, 14, 7, 193, 202, 14, 7, 193, 201, 14, 7, 193, 200, 14, 7, - 193, 199, 14, 7, 193, 198, 14, 7, 193, 197, 14, 7, 193, 196, 14, 7, 193, - 195, 14, 7, 193, 194, 14, 7, 193, 193, 14, 7, 193, 192, 14, 7, 192, 232, - 14, 7, 192, 231, 14, 7, 192, 230, 14, 7, 192, 229, 14, 7, 192, 228, 14, - 7, 192, 227, 14, 7, 192, 226, 14, 7, 192, 225, 14, 7, 192, 224, 14, 7, - 192, 223, 14, 7, 192, 222, 14, 7, 192, 221, 14, 7, 192, 157, 14, 7, 192, - 156, 14, 7, 192, 155, 14, 7, 192, 154, 14, 7, 192, 153, 14, 7, 192, 152, - 14, 7, 192, 151, 14, 7, 192, 150, 14, 7, 192, 149, 14, 7, 191, 165, 14, - 7, 191, 164, 14, 7, 191, 163, 14, 7, 191, 162, 14, 7, 191, 161, 14, 7, - 191, 160, 14, 7, 191, 159, 14, 7, 191, 158, 14, 7, 191, 157, 14, 7, 191, - 156, 14, 7, 191, 155, 14, 7, 191, 154, 14, 7, 191, 153, 14, 7, 191, 152, - 14, 7, 191, 151, 14, 7, 191, 150, 14, 7, 191, 149, 14, 7, 191, 148, 14, - 7, 191, 147, 14, 7, 191, 146, 14, 7, 191, 145, 14, 7, 191, 144, 14, 7, - 191, 143, 14, 7, 191, 142, 14, 7, 191, 141, 14, 7, 191, 140, 14, 7, 191, - 139, 14, 7, 191, 138, 14, 7, 191, 137, 14, 7, 191, 136, 14, 7, 191, 135, - 14, 7, 191, 134, 14, 7, 191, 133, 14, 7, 191, 132, 14, 7, 191, 131, 14, - 7, 191, 130, 14, 7, 191, 129, 14, 7, 191, 128, 14, 7, 191, 127, 14, 7, - 191, 126, 14, 7, 191, 125, 14, 7, 252, 205, 14, 7, 252, 204, 14, 7, 252, - 203, 14, 7, 252, 202, 14, 7, 252, 201, 14, 7, 252, 200, 14, 7, 252, 199, - 14, 7, 252, 198, 14, 7, 252, 197, 14, 7, 252, 196, 14, 7, 252, 195, 14, - 7, 252, 194, 14, 7, 252, 193, 14, 7, 252, 192, 14, 7, 252, 191, 14, 7, - 252, 190, 14, 7, 252, 189, 14, 7, 252, 188, 14, 7, 252, 187, 14, 7, 252, - 186, 14, 7, 252, 185, 14, 7, 252, 184, 14, 7, 252, 183, 14, 7, 252, 182, - 14, 7, 252, 181, 14, 7, 252, 180, 14, 7, 252, 179, 14, 7, 252, 178, 14, - 7, 252, 177, 14, 7, 252, 176, 14, 7, 252, 175, 14, 7, 252, 174, 14, 7, - 252, 173, 14, 7, 252, 172, 14, 7, 195, 241, 14, 7, 81, 222, 196, 14, 7, - 228, 241, 222, 196, 14, 7, 223, 120, 250, 183, 198, 54, 201, 97, 14, 7, - 223, 120, 250, 183, 248, 77, 201, 97, 14, 7, 223, 120, 250, 183, 198, 54, - 234, 94, 14, 7, 223, 120, 250, 183, 248, 77, 234, 94, 14, 7, 211, 0, 216, - 84, 14, 7, 248, 249, 205, 43, 14, 7, 234, 95, 205, 43, 14, 7, 223, 120, - 250, 183, 216, 84, 14, 7, 223, 120, 250, 183, 198, 53, 14, 7, 223, 120, - 250, 183, 248, 76, 14, 7, 248, 249, 234, 98, 14, 7, 234, 95, 234, 98, 14, - 7, 248, 249, 193, 166, 234, 98, 14, 7, 234, 95, 193, 166, 234, 98, 14, 7, - 216, 27, 228, 189, 14, 7, 232, 80, 248, 132, 14, 7, 132, 248, 132, 14, 7, - 218, 251, 56, 14, 7, 132, 218, 251, 56, 14, 7, 199, 200, 218, 251, 56, - 14, 7, 193, 78, 218, 251, 56, 14, 7, 52, 237, 249, 250, 183, 198, 54, - 201, 97, 14, 7, 52, 237, 249, 250, 183, 248, 77, 201, 97, 14, 7, 52, 237, - 249, 250, 183, 201, 97, 14, 7, 52, 237, 249, 250, 183, 198, 54, 234, 94, - 14, 7, 52, 237, 249, 250, 183, 198, 53, 14, 7, 52, 237, 249, 250, 183, - 248, 77, 201, 98, 23, 198, 54, 234, 94, 14, 7, 52, 237, 249, 250, 183, - 201, 98, 23, 198, 53, 14, 7, 52, 237, 249, 250, 183, 248, 77, 234, 94, - 14, 7, 52, 237, 249, 250, 183, 198, 54, 201, 98, 23, 248, 77, 234, 94, - 14, 7, 52, 237, 249, 250, 183, 248, 76, 14, 7, 52, 237, 249, 250, 183, - 201, 98, 23, 248, 76, 14, 7, 52, 237, 249, 250, 183, 234, 94, 14, 7, 52, - 237, 249, 250, 183, 198, 54, 23, 234, 94, 14, 7, 52, 237, 249, 250, 183, - 248, 77, 23, 234, 94, 14, 7, 52, 237, 248, 29, 7, 255, 199, 29, 7, 255, - 198, 29, 7, 255, 197, 29, 7, 255, 196, 29, 7, 255, 195, 29, 7, 255, 193, - 29, 7, 255, 190, 29, 7, 255, 189, 29, 7, 255, 188, 29, 7, 255, 187, 29, - 7, 255, 186, 29, 7, 255, 185, 29, 7, 255, 184, 29, 7, 255, 183, 29, 7, - 255, 182, 29, 7, 255, 180, 29, 7, 255, 179, 29, 7, 255, 178, 29, 7, 255, - 176, 29, 7, 255, 175, 29, 7, 255, 174, 29, 7, 255, 173, 29, 7, 255, 172, - 29, 7, 255, 171, 29, 7, 255, 170, 29, 7, 255, 169, 29, 7, 255, 168, 29, - 7, 255, 167, 29, 7, 255, 166, 29, 7, 255, 165, 29, 7, 255, 163, 29, 7, - 255, 162, 29, 7, 255, 161, 29, 7, 255, 160, 29, 7, 255, 158, 29, 7, 255, - 157, 29, 7, 255, 156, 29, 7, 255, 155, 29, 7, 255, 154, 29, 7, 255, 153, - 29, 7, 255, 152, 29, 7, 255, 151, 29, 7, 255, 150, 29, 7, 255, 148, 29, - 7, 255, 147, 29, 7, 255, 146, 29, 7, 255, 144, 29, 7, 255, 142, 29, 7, - 255, 141, 29, 7, 255, 140, 29, 7, 255, 139, 29, 7, 255, 138, 29, 7, 255, - 137, 29, 7, 255, 136, 29, 7, 255, 135, 29, 7, 255, 134, 29, 7, 255, 133, - 29, 7, 255, 132, 29, 7, 255, 131, 29, 7, 255, 130, 29, 7, 255, 129, 29, - 7, 255, 128, 29, 7, 255, 127, 29, 7, 255, 126, 29, 7, 255, 125, 29, 7, - 255, 124, 29, 7, 255, 123, 29, 7, 255, 122, 29, 7, 255, 121, 29, 7, 255, - 120, 29, 7, 255, 119, 29, 7, 255, 118, 29, 7, 255, 117, 29, 7, 255, 116, - 29, 7, 255, 115, 29, 7, 255, 114, 29, 7, 255, 113, 29, 7, 255, 112, 29, - 7, 255, 111, 29, 7, 255, 110, 29, 7, 255, 109, 29, 7, 255, 108, 29, 7, - 255, 107, 29, 7, 255, 106, 29, 7, 255, 105, 29, 7, 255, 104, 29, 7, 255, - 103, 29, 7, 255, 102, 29, 7, 255, 101, 29, 7, 255, 100, 29, 7, 255, 99, - 29, 7, 255, 98, 29, 7, 255, 97, 29, 7, 255, 96, 29, 7, 255, 95, 29, 7, - 255, 94, 29, 7, 255, 93, 29, 7, 255, 92, 29, 7, 255, 91, 29, 7, 255, 90, - 29, 7, 255, 89, 29, 7, 255, 88, 29, 7, 255, 87, 29, 7, 255, 86, 29, 7, - 255, 85, 29, 7, 255, 84, 29, 7, 255, 83, 29, 7, 255, 82, 29, 7, 255, 81, - 29, 7, 255, 80, 29, 7, 255, 79, 29, 7, 255, 78, 29, 7, 255, 76, 29, 7, - 255, 75, 29, 7, 255, 74, 29, 7, 255, 73, 29, 7, 255, 72, 29, 7, 255, 71, - 29, 7, 255, 70, 29, 7, 255, 69, 29, 7, 255, 68, 29, 7, 255, 67, 29, 7, - 255, 66, 29, 7, 255, 65, 29, 7, 255, 64, 29, 7, 255, 63, 29, 7, 255, 62, - 29, 7, 255, 61, 29, 7, 255, 60, 29, 7, 255, 59, 29, 7, 255, 58, 29, 7, - 255, 57, 29, 7, 255, 56, 29, 7, 255, 55, 29, 7, 255, 54, 29, 7, 255, 53, - 29, 7, 255, 52, 29, 7, 255, 51, 29, 7, 255, 50, 29, 7, 255, 49, 29, 7, - 255, 48, 29, 7, 255, 47, 29, 7, 255, 46, 29, 7, 255, 45, 29, 7, 255, 44, - 29, 7, 255, 43, 29, 7, 255, 41, 29, 7, 255, 40, 29, 7, 255, 39, 29, 7, - 255, 38, 29, 7, 255, 37, 29, 7, 255, 36, 29, 7, 255, 35, 29, 7, 255, 34, - 29, 7, 255, 33, 29, 7, 255, 32, 29, 7, 255, 31, 29, 7, 255, 30, 29, 7, - 255, 28, 29, 7, 255, 27, 29, 7, 255, 26, 29, 7, 255, 25, 29, 7, 255, 24, - 29, 7, 255, 23, 29, 7, 255, 22, 29, 7, 255, 21, 29, 7, 255, 20, 29, 7, - 255, 19, 29, 7, 255, 18, 29, 7, 255, 17, 29, 7, 255, 16, 29, 7, 255, 15, - 29, 7, 255, 14, 29, 7, 255, 13, 29, 7, 255, 12, 29, 7, 255, 11, 29, 7, - 255, 10, 29, 7, 255, 9, 29, 7, 255, 8, 29, 7, 255, 7, 29, 7, 255, 6, 29, - 7, 255, 5, 29, 7, 255, 4, 29, 7, 255, 3, 29, 7, 255, 2, 29, 7, 255, 1, - 29, 7, 255, 0, 29, 7, 254, 255, 29, 7, 254, 254, 29, 7, 254, 253, 29, 7, - 254, 252, 29, 7, 254, 251, 29, 7, 254, 250, 29, 7, 254, 249, 29, 7, 254, - 248, 29, 7, 254, 247, 29, 7, 254, 246, 29, 7, 254, 245, 29, 7, 254, 244, - 29, 7, 254, 243, 29, 7, 254, 242, 29, 7, 254, 241, 29, 7, 254, 240, 29, - 7, 254, 239, 29, 7, 254, 238, 29, 7, 254, 237, 29, 7, 254, 236, 29, 7, - 254, 235, 29, 7, 254, 234, 29, 7, 254, 233, 29, 7, 254, 232, 29, 7, 254, - 231, 29, 7, 254, 230, 29, 7, 254, 229, 29, 7, 254, 228, 29, 7, 254, 227, - 29, 7, 254, 226, 29, 7, 254, 225, 29, 7, 254, 224, 29, 7, 254, 223, 29, - 7, 254, 222, 29, 7, 254, 221, 29, 7, 254, 220, 29, 7, 254, 219, 29, 7, - 254, 218, 29, 7, 254, 217, 29, 7, 254, 216, 29, 7, 254, 214, 29, 7, 254, - 213, 29, 7, 254, 212, 29, 7, 254, 211, 29, 7, 254, 210, 29, 7, 254, 209, - 29, 7, 254, 208, 29, 7, 254, 207, 29, 7, 254, 206, 29, 7, 254, 205, 29, - 7, 254, 204, 29, 7, 254, 203, 29, 7, 254, 202, 29, 7, 254, 201, 29, 7, - 254, 200, 29, 7, 254, 199, 29, 7, 254, 198, 29, 7, 254, 197, 29, 7, 254, - 196, 29, 7, 254, 195, 29, 7, 254, 194, 29, 7, 254, 193, 29, 7, 254, 192, - 29, 7, 254, 191, 29, 7, 254, 190, 29, 7, 254, 189, 29, 7, 254, 188, 29, - 7, 254, 187, 29, 7, 254, 186, 29, 7, 254, 185, 29, 7, 254, 184, 29, 7, - 254, 183, 29, 7, 254, 182, 29, 7, 254, 181, 29, 7, 254, 180, 29, 7, 254, - 179, 29, 7, 254, 178, 29, 7, 254, 177, 29, 7, 254, 176, 29, 7, 254, 175, - 29, 7, 254, 174, 29, 7, 254, 173, 29, 7, 254, 172, 29, 7, 254, 171, 29, - 7, 254, 170, 29, 7, 254, 169, 29, 7, 254, 168, 29, 7, 254, 167, 29, 7, - 254, 166, 29, 7, 254, 165, 29, 7, 254, 164, 29, 7, 254, 163, 29, 7, 254, - 162, 29, 7, 254, 161, 29, 7, 254, 160, 29, 7, 254, 159, 29, 7, 254, 158, - 29, 7, 254, 157, 29, 7, 254, 156, 29, 7, 254, 155, 29, 7, 254, 154, 29, - 7, 254, 153, 29, 7, 254, 152, 29, 7, 254, 151, 29, 7, 254, 150, 29, 7, - 254, 149, 29, 7, 254, 148, 29, 7, 254, 147, 29, 7, 254, 146, 29, 7, 254, - 145, 29, 7, 254, 144, 29, 7, 254, 143, 29, 7, 254, 142, 29, 7, 254, 141, - 29, 7, 254, 140, 29, 7, 254, 139, 29, 7, 254, 138, 29, 7, 254, 137, 29, - 7, 254, 136, 29, 7, 254, 135, 29, 7, 254, 134, 29, 7, 254, 133, 29, 7, - 254, 132, 29, 7, 254, 131, 29, 7, 254, 130, 29, 7, 254, 129, 29, 7, 254, - 128, 29, 7, 254, 127, 29, 7, 254, 126, 29, 7, 254, 125, 29, 7, 254, 124, - 29, 7, 254, 123, 29, 7, 254, 122, 29, 7, 254, 121, 29, 7, 254, 120, 29, - 7, 254, 119, 29, 7, 254, 118, 29, 7, 254, 117, 29, 7, 254, 116, 29, 7, - 254, 115, 29, 7, 254, 114, 29, 7, 254, 113, 29, 7, 254, 112, 29, 7, 254, - 111, 29, 7, 254, 110, 29, 7, 254, 109, 29, 7, 254, 108, 29, 7, 254, 107, - 29, 7, 254, 106, 29, 7, 254, 105, 29, 7, 254, 104, 29, 7, 254, 102, 29, - 7, 254, 101, 29, 7, 254, 100, 29, 7, 254, 99, 29, 7, 254, 98, 29, 7, 254, - 97, 29, 7, 254, 96, 29, 7, 254, 95, 29, 7, 254, 94, 29, 7, 254, 93, 29, - 7, 254, 92, 29, 7, 254, 89, 29, 7, 254, 88, 29, 7, 254, 87, 29, 7, 254, - 86, 29, 7, 254, 82, 29, 7, 254, 81, 29, 7, 254, 80, 29, 7, 254, 79, 29, - 7, 254, 78, 29, 7, 254, 77, 29, 7, 254, 76, 29, 7, 254, 75, 29, 7, 254, - 74, 29, 7, 254, 73, 29, 7, 254, 72, 29, 7, 254, 71, 29, 7, 254, 70, 29, - 7, 254, 69, 29, 7, 254, 68, 29, 7, 254, 67, 29, 7, 254, 66, 29, 7, 254, - 65, 29, 7, 254, 64, 29, 7, 254, 62, 29, 7, 254, 61, 29, 7, 254, 60, 29, - 7, 254, 59, 29, 7, 254, 58, 29, 7, 254, 57, 29, 7, 254, 56, 29, 7, 254, - 55, 29, 7, 254, 54, 29, 7, 254, 53, 29, 7, 254, 52, 29, 7, 254, 51, 29, - 7, 254, 50, 29, 7, 254, 49, 29, 7, 254, 48, 29, 7, 254, 47, 29, 7, 254, - 46, 29, 7, 254, 45, 29, 7, 254, 44, 29, 7, 254, 43, 29, 7, 254, 42, 29, - 7, 254, 41, 29, 7, 254, 40, 29, 7, 254, 39, 29, 7, 254, 38, 29, 7, 254, - 37, 29, 7, 254, 36, 29, 7, 254, 35, 29, 7, 254, 34, 29, 7, 254, 33, 29, - 7, 254, 32, 29, 7, 254, 31, 29, 7, 254, 30, 29, 7, 254, 29, 29, 7, 254, - 28, 29, 7, 254, 27, 29, 7, 254, 26, 29, 7, 254, 25, 29, 7, 254, 24, 29, - 7, 254, 23, 29, 7, 254, 22, 29, 7, 254, 21, 29, 7, 254, 20, 29, 7, 254, - 19, 29, 7, 254, 18, 29, 7, 254, 17, 29, 7, 254, 16, 29, 7, 254, 15, 29, - 7, 254, 14, 29, 7, 254, 13, 29, 7, 254, 12, 29, 7, 254, 11, 29, 7, 254, - 10, 29, 7, 254, 9, 29, 7, 254, 8, 29, 7, 254, 7, 29, 7, 254, 6, 29, 7, - 254, 5, 29, 7, 254, 4, 29, 7, 254, 3, 29, 7, 254, 2, 29, 7, 254, 1, 207, - 186, 211, 57, 207, 1, 29, 7, 254, 0, 29, 7, 253, 255, 29, 7, 253, 254, - 29, 7, 253, 253, 29, 7, 253, 252, 29, 7, 253, 251, 29, 7, 253, 250, 29, - 7, 253, 249, 29, 7, 253, 248, 29, 7, 253, 247, 29, 7, 253, 246, 29, 7, - 253, 245, 171, 29, 7, 253, 244, 29, 7, 253, 243, 29, 7, 253, 242, 29, 7, - 253, 241, 29, 7, 253, 240, 29, 7, 253, 239, 29, 7, 253, 238, 29, 7, 253, - 236, 29, 7, 253, 234, 29, 7, 253, 232, 29, 7, 253, 230, 29, 7, 253, 228, - 29, 7, 253, 226, 29, 7, 253, 224, 29, 7, 253, 222, 29, 7, 253, 220, 29, - 7, 253, 218, 248, 249, 219, 28, 77, 29, 7, 253, 216, 234, 95, 219, 28, - 77, 29, 7, 253, 215, 29, 7, 253, 213, 29, 7, 253, 211, 29, 7, 253, 209, - 29, 7, 253, 207, 29, 7, 253, 205, 29, 7, 253, 203, 29, 7, 253, 201, 29, - 7, 253, 199, 29, 7, 253, 198, 29, 7, 253, 197, 29, 7, 253, 196, 29, 7, - 253, 195, 29, 7, 253, 194, 29, 7, 253, 193, 29, 7, 253, 192, 29, 7, 253, - 191, 29, 7, 253, 190, 29, 7, 253, 189, 29, 7, 253, 188, 29, 7, 253, 187, - 29, 7, 253, 186, 29, 7, 253, 185, 29, 7, 253, 184, 29, 7, 253, 183, 29, - 7, 253, 182, 29, 7, 253, 181, 29, 7, 253, 180, 29, 7, 253, 179, 29, 7, - 253, 178, 29, 7, 253, 177, 29, 7, 253, 176, 29, 7, 253, 175, 29, 7, 253, - 174, 29, 7, 253, 173, 29, 7, 253, 172, 29, 7, 253, 171, 29, 7, 253, 170, - 29, 7, 253, 169, 29, 7, 253, 168, 29, 7, 253, 167, 29, 7, 253, 166, 29, - 7, 253, 165, 29, 7, 253, 164, 29, 7, 253, 163, 29, 7, 253, 162, 29, 7, - 253, 161, 29, 7, 253, 160, 29, 7, 253, 159, 29, 7, 253, 158, 29, 7, 253, - 157, 29, 7, 253, 156, 29, 7, 253, 155, 29, 7, 253, 154, 29, 7, 253, 153, - 29, 7, 253, 152, 29, 7, 253, 151, 29, 7, 253, 150, 29, 7, 253, 149, 29, - 7, 253, 148, 29, 7, 253, 147, 29, 7, 253, 146, 29, 7, 253, 145, 29, 7, - 253, 144, 29, 7, 253, 143, 29, 7, 253, 142, 29, 7, 253, 141, 29, 7, 253, - 140, 29, 7, 253, 139, 29, 7, 253, 138, 29, 7, 253, 137, 29, 7, 253, 136, - 29, 7, 253, 135, 29, 7, 253, 134, 29, 7, 253, 133, 29, 7, 253, 132, 29, - 7, 253, 131, 29, 7, 253, 130, 29, 7, 253, 129, 29, 7, 253, 128, 29, 7, - 253, 127, 29, 7, 253, 126, 29, 7, 253, 125, 29, 7, 253, 124, 29, 7, 253, - 123, 29, 7, 253, 122, 29, 7, 253, 121, 29, 7, 253, 120, 29, 7, 253, 119, - 29, 7, 253, 118, 29, 7, 253, 117, 29, 7, 253, 116, 29, 7, 253, 115, 29, - 7, 253, 114, 29, 7, 253, 113, 29, 7, 253, 112, 29, 7, 253, 111, 29, 7, - 253, 110, 29, 7, 253, 109, 29, 7, 253, 108, 29, 7, 253, 107, 29, 7, 253, - 106, 29, 7, 253, 105, 29, 7, 253, 104, 29, 7, 253, 103, 29, 7, 253, 102, - 29, 7, 253, 101, 29, 7, 253, 100, 29, 7, 253, 99, 29, 7, 253, 98, 29, 7, - 253, 97, 29, 7, 253, 96, 29, 7, 253, 95, 29, 7, 253, 94, 29, 7, 253, 93, - 29, 7, 253, 92, 29, 7, 253, 91, 29, 7, 253, 90, 29, 7, 253, 89, 26, 1, - 209, 218, 214, 1, 216, 142, 26, 1, 209, 218, 231, 173, 232, 166, 26, 1, - 209, 218, 209, 40, 216, 143, 209, 127, 26, 1, 209, 218, 209, 40, 216, - 143, 209, 128, 26, 1, 209, 218, 214, 251, 216, 142, 26, 1, 209, 218, 203, - 0, 26, 1, 209, 218, 198, 124, 216, 142, 26, 1, 209, 218, 212, 47, 216, - 142, 26, 1, 209, 218, 203, 68, 210, 221, 213, 141, 26, 1, 209, 218, 209, - 40, 210, 221, 213, 142, 209, 127, 26, 1, 209, 218, 209, 40, 210, 221, - 213, 142, 209, 128, 26, 1, 209, 218, 217, 131, 26, 1, 209, 218, 197, 95, - 217, 132, 26, 1, 209, 218, 214, 62, 26, 1, 209, 218, 217, 128, 26, 1, - 209, 218, 217, 77, 26, 1, 209, 218, 215, 86, 26, 1, 209, 218, 203, 249, - 26, 1, 209, 218, 212, 187, 26, 1, 209, 218, 221, 234, 26, 1, 209, 218, - 213, 108, 26, 1, 209, 218, 200, 160, 26, 1, 209, 218, 214, 0, 26, 1, 209, - 218, 220, 15, 26, 1, 209, 218, 219, 177, 220, 188, 26, 1, 209, 218, 212, - 197, 216, 150, 26, 1, 209, 218, 217, 135, 26, 1, 209, 218, 210, 98, 26, - 1, 209, 218, 231, 72, 26, 1, 209, 218, 210, 170, 26, 1, 209, 218, 215, - 232, 214, 35, 26, 1, 209, 218, 212, 28, 216, 153, 26, 1, 209, 218, 126, - 191, 195, 214, 244, 26, 1, 209, 218, 231, 73, 26, 1, 209, 218, 212, 197, - 212, 198, 26, 1, 209, 218, 202, 139, 26, 1, 209, 218, 216, 135, 26, 1, - 209, 218, 216, 156, 26, 1, 209, 218, 215, 207, 26, 1, 209, 218, 222, 105, - 26, 1, 209, 218, 210, 221, 219, 225, 26, 1, 209, 218, 214, 163, 219, 225, - 26, 1, 209, 218, 209, 240, 26, 1, 209, 218, 217, 129, 26, 1, 209, 218, - 213, 185, 26, 1, 209, 218, 208, 144, 26, 1, 209, 218, 197, 87, 26, 1, - 209, 218, 218, 221, 26, 1, 209, 218, 202, 17, 26, 1, 209, 218, 199, 58, - 26, 1, 209, 218, 217, 126, 26, 1, 209, 218, 221, 241, 26, 1, 209, 218, - 214, 159, 26, 1, 209, 218, 220, 203, 26, 1, 209, 218, 215, 208, 26, 1, - 209, 218, 202, 252, 26, 1, 209, 218, 219, 20, 26, 1, 209, 218, 232, 239, - 26, 1, 209, 218, 206, 137, 26, 1, 209, 218, 221, 10, 26, 1, 209, 218, - 202, 13, 26, 1, 209, 218, 217, 72, 209, 173, 26, 1, 209, 218, 203, 61, - 26, 1, 209, 218, 212, 196, 26, 1, 209, 218, 203, 42, 212, 208, 191, 203, - 26, 1, 209, 218, 212, 69, 215, 228, 26, 1, 209, 218, 210, 216, 26, 1, - 209, 218, 213, 110, 26, 1, 209, 218, 196, 85, 26, 1, 209, 218, 214, 38, - 26, 1, 209, 218, 217, 125, 26, 1, 209, 218, 213, 153, 26, 1, 209, 218, - 217, 6, 26, 1, 209, 218, 212, 84, 26, 1, 209, 218, 199, 62, 26, 1, 209, - 218, 202, 8, 26, 1, 209, 218, 210, 217, 26, 1, 209, 218, 212, 212, 26, 1, - 209, 218, 217, 133, 26, 1, 209, 218, 212, 81, 26, 1, 209, 218, 222, 66, - 26, 1, 209, 218, 212, 215, 26, 1, 209, 218, 195, 148, 26, 1, 209, 218, - 218, 225, 26, 1, 209, 218, 214, 102, 26, 1, 209, 218, 214, 217, 26, 1, - 209, 218, 217, 5, 26, 1, 209, 217, 212, 210, 26, 1, 209, 217, 197, 95, - 217, 130, 26, 1, 209, 217, 202, 204, 26, 1, 209, 217, 203, 253, 197, 94, - 26, 1, 209, 217, 219, 23, 212, 193, 26, 1, 209, 217, 217, 12, 217, 134, - 26, 1, 209, 217, 221, 150, 26, 1, 209, 217, 192, 43, 26, 1, 209, 217, - 217, 7, 26, 1, 209, 217, 222, 90, 26, 1, 209, 217, 210, 44, 26, 1, 209, - 217, 192, 126, 219, 225, 26, 1, 209, 217, 220, 36, 212, 208, 212, 95, 26, - 1, 209, 217, 212, 190, 203, 87, 26, 1, 209, 217, 214, 130, 213, 156, 26, - 1, 209, 217, 231, 70, 26, 1, 209, 217, 209, 117, 26, 1, 209, 217, 197, - 95, 212, 206, 26, 1, 209, 217, 203, 92, 213, 151, 26, 1, 209, 217, 203, - 88, 26, 1, 209, 217, 216, 143, 199, 61, 26, 1, 209, 217, 216, 250, 217, - 8, 26, 1, 209, 217, 212, 82, 212, 193, 26, 1, 209, 217, 221, 230, 26, 1, - 209, 217, 231, 71, 26, 1, 209, 217, 221, 226, 26, 1, 209, 217, 220, 120, - 26, 1, 209, 217, 210, 101, 26, 1, 209, 217, 195, 77, 26, 1, 209, 217, - 214, 2, 215, 84, 26, 1, 209, 217, 214, 37, 216, 246, 26, 1, 209, 217, - 192, 254, 26, 1, 209, 217, 205, 175, 26, 1, 209, 217, 199, 240, 26, 1, - 209, 217, 216, 155, 26, 1, 209, 217, 214, 21, 26, 1, 209, 217, 214, 22, - 220, 12, 26, 1, 209, 217, 216, 145, 26, 1, 209, 217, 200, 214, 26, 1, - 209, 217, 216, 254, 26, 1, 209, 217, 215, 212, 26, 1, 209, 217, 212, 99, - 26, 1, 209, 217, 208, 148, 26, 1, 209, 217, 216, 154, 214, 39, 26, 1, - 209, 217, 233, 28, 26, 1, 209, 217, 216, 241, 26, 1, 209, 217, 233, 52, - 26, 1, 209, 217, 221, 238, 26, 1, 209, 217, 217, 160, 213, 145, 26, 1, - 209, 217, 217, 160, 213, 121, 26, 1, 209, 217, 219, 176, 26, 1, 209, 217, - 214, 45, 26, 1, 209, 217, 212, 217, 26, 1, 209, 217, 174, 26, 1, 209, - 217, 221, 133, 26, 1, 209, 217, 213, 246, 26, 1, 209, 216, 214, 1, 217, - 132, 26, 1, 209, 216, 212, 46, 26, 1, 209, 216, 191, 203, 26, 1, 209, - 216, 193, 160, 26, 1, 209, 216, 214, 38, 26, 1, 209, 216, 214, 151, 26, - 1, 209, 216, 214, 8, 26, 1, 209, 216, 231, 80, 26, 1, 209, 216, 217, 2, - 26, 1, 209, 216, 231, 180, 26, 1, 209, 216, 212, 71, 216, 21, 216, 157, - 26, 1, 209, 216, 212, 184, 216, 249, 26, 1, 209, 216, 216, 255, 26, 1, - 209, 216, 209, 123, 26, 1, 209, 216, 214, 136, 26, 1, 209, 216, 217, 10, - 247, 156, 26, 1, 209, 216, 221, 228, 26, 1, 209, 216, 231, 81, 26, 1, - 209, 216, 221, 235, 26, 1, 209, 216, 191, 226, 215, 117, 26, 1, 209, 216, - 212, 40, 26, 1, 209, 216, 216, 243, 26, 1, 209, 216, 212, 216, 26, 1, - 209, 216, 216, 249, 26, 1, 209, 216, 192, 44, 26, 1, 209, 216, 221, 18, - 26, 1, 209, 216, 222, 127, 26, 1, 209, 216, 203, 248, 26, 1, 209, 216, - 214, 145, 26, 1, 209, 216, 199, 238, 26, 1, 209, 216, 213, 125, 26, 1, - 209, 216, 198, 124, 191, 207, 26, 1, 209, 216, 200, 247, 26, 1, 209, 216, - 214, 28, 212, 95, 26, 1, 209, 216, 195, 76, 26, 1, 209, 216, 214, 220, - 26, 1, 209, 216, 217, 160, 221, 237, 26, 1, 209, 216, 212, 198, 26, 1, - 209, 216, 214, 23, 26, 1, 209, 216, 220, 16, 26, 1, 209, 216, 216, 251, - 26, 1, 209, 216, 216, 134, 26, 1, 209, 216, 212, 192, 26, 1, 209, 216, - 199, 57, 26, 1, 209, 216, 214, 25, 26, 1, 209, 216, 232, 84, 26, 1, 209, - 216, 214, 150, 26, 1, 209, 216, 212, 218, 26, 1, 209, 216, 212, 214, 26, - 1, 209, 216, 247, 240, 26, 1, 209, 216, 195, 78, 26, 1, 209, 216, 217, 0, - 26, 1, 209, 216, 206, 68, 26, 1, 209, 216, 213, 155, 26, 1, 209, 216, - 220, 35, 26, 1, 209, 216, 198, 121, 26, 1, 209, 216, 212, 200, 213, 246, - 26, 1, 209, 216, 213, 147, 26, 1, 209, 216, 221, 241, 26, 1, 209, 216, - 214, 30, 26, 1, 209, 216, 217, 125, 26, 1, 209, 216, 216, 244, 26, 1, - 209, 216, 218, 225, 26, 1, 209, 216, 220, 188, 26, 1, 209, 216, 213, 153, - 26, 1, 209, 216, 213, 246, 26, 1, 209, 216, 192, 244, 26, 1, 209, 216, - 214, 26, 26, 1, 209, 216, 212, 203, 26, 1, 209, 216, 212, 194, 26, 1, - 209, 216, 220, 205, 213, 110, 26, 1, 209, 216, 212, 201, 26, 1, 209, 216, - 214, 158, 26, 1, 209, 216, 217, 160, 212, 206, 26, 1, 209, 216, 192, 140, - 26, 1, 209, 216, 214, 157, 26, 1, 209, 216, 202, 255, 26, 1, 209, 216, - 203, 251, 26, 1, 209, 216, 216, 252, 26, 1, 209, 216, 217, 132, 26, 1, - 209, 216, 217, 6, 26, 1, 209, 216, 221, 229, 26, 1, 209, 216, 216, 253, - 26, 1, 209, 216, 221, 233, 26, 1, 209, 216, 217, 10, 209, 179, 26, 1, - 209, 216, 191, 186, 26, 1, 209, 216, 213, 143, 26, 1, 209, 216, 216, 80, - 26, 1, 209, 216, 215, 149, 26, 1, 209, 216, 203, 64, 26, 1, 209, 216, - 221, 252, 219, 250, 26, 1, 209, 216, 221, 252, 233, 65, 26, 1, 209, 216, - 214, 60, 26, 1, 209, 216, 214, 217, 26, 1, 209, 216, 219, 94, 26, 1, 209, - 216, 209, 139, 26, 1, 209, 216, 210, 34, 26, 1, 209, 216, 199, 73, 26, 1, - 158, 216, 242, 26, 1, 158, 193, 158, 26, 1, 158, 213, 141, 26, 1, 158, - 216, 142, 26, 1, 158, 213, 139, 26, 1, 158, 219, 139, 26, 1, 158, 213, - 144, 26, 1, 158, 212, 213, 26, 1, 158, 214, 44, 26, 1, 158, 212, 95, 26, - 1, 158, 192, 255, 26, 1, 158, 213, 254, 26, 1, 158, 203, 111, 26, 1, 158, - 214, 9, 26, 1, 158, 221, 236, 26, 1, 158, 199, 59, 26, 1, 158, 203, 90, - 26, 1, 158, 213, 152, 26, 1, 158, 200, 214, 26, 1, 158, 221, 241, 26, 1, - 158, 192, 128, 26, 1, 158, 220, 206, 26, 1, 158, 205, 130, 26, 1, 158, - 216, 147, 26, 1, 158, 214, 149, 26, 1, 158, 217, 95, 26, 1, 158, 216, - 153, 26, 1, 158, 203, 250, 26, 1, 158, 192, 70, 26, 1, 158, 213, 146, 26, - 1, 158, 221, 232, 216, 245, 26, 1, 158, 214, 5, 26, 1, 158, 197, 94, 26, - 1, 158, 231, 90, 26, 1, 158, 213, 251, 26, 1, 158, 233, 29, 26, 1, 158, - 214, 153, 26, 1, 158, 216, 126, 26, 1, 158, 219, 170, 26, 1, 158, 214, - 135, 26, 1, 158, 215, 227, 26, 1, 158, 216, 130, 26, 1, 158, 208, 127, - 26, 1, 158, 216, 128, 26, 1, 158, 216, 144, 26, 1, 158, 218, 208, 26, 1, - 158, 212, 205, 26, 1, 158, 217, 9, 26, 1, 158, 220, 177, 26, 1, 158, 212, - 84, 26, 1, 158, 199, 62, 26, 1, 158, 202, 8, 26, 1, 158, 191, 186, 26, 1, - 158, 221, 233, 26, 1, 158, 207, 162, 26, 1, 158, 199, 120, 26, 1, 158, - 214, 6, 26, 1, 158, 216, 149, 26, 1, 158, 212, 204, 26, 1, 158, 221, 231, - 26, 1, 158, 209, 129, 26, 1, 158, 209, 233, 26, 1, 158, 212, 57, 26, 1, - 158, 219, 176, 26, 1, 158, 214, 45, 26, 1, 158, 216, 146, 26, 1, 158, - 214, 18, 26, 1, 158, 191, 200, 26, 1, 158, 210, 137, 26, 1, 158, 191, - 199, 26, 1, 158, 214, 158, 26, 1, 158, 212, 193, 26, 1, 158, 200, 249, - 26, 1, 158, 220, 210, 26, 1, 158, 214, 34, 26, 1, 158, 214, 3, 26, 1, - 158, 197, 69, 26, 1, 158, 216, 157, 26, 1, 158, 220, 199, 26, 1, 158, - 212, 202, 26, 1, 158, 199, 60, 26, 1, 158, 217, 127, 26, 1, 158, 214, 43, - 26, 1, 158, 219, 169, 26, 1, 158, 214, 24, 26, 1, 158, 212, 207, 26, 1, - 158, 213, 125, 26, 1, 158, 231, 74, 26, 1, 158, 220, 232, 26, 1, 158, - 207, 56, 211, 119, 26, 1, 158, 199, 226, 26, 1, 158, 198, 50, 26, 1, 158, - 212, 81, 26, 1, 158, 206, 195, 26, 1, 158, 219, 227, 26, 1, 158, 216, - 210, 26, 1, 158, 218, 168, 26, 1, 158, 200, 160, 26, 1, 158, 215, 155, - 26, 1, 158, 203, 76, 26, 1, 158, 203, 86, 26, 1, 158, 220, 149, 26, 1, - 158, 212, 178, 26, 1, 158, 203, 5, 26, 1, 158, 212, 195, 26, 1, 158, 210, - 49, 26, 1, 158, 213, 219, 26, 1, 158, 203, 41, 26, 1, 158, 208, 143, 26, - 1, 158, 215, 84, 26, 1, 158, 219, 0, 26, 1, 158, 207, 56, 215, 144, 26, - 1, 158, 198, 193, 26, 1, 158, 212, 181, 26, 1, 158, 217, 10, 175, 26, 1, - 158, 205, 128, 26, 1, 158, 233, 108, 26, 1, 114, 214, 157, 26, 1, 114, - 198, 57, 26, 1, 114, 216, 255, 26, 1, 114, 220, 16, 26, 1, 114, 195, 10, - 26, 1, 114, 219, 6, 26, 1, 114, 210, 220, 26, 1, 114, 202, 21, 26, 1, - 114, 207, 134, 26, 1, 114, 212, 209, 26, 1, 114, 214, 128, 26, 1, 114, - 208, 161, 26, 1, 114, 199, 197, 26, 1, 114, 214, 11, 26, 1, 114, 221, 14, - 26, 1, 114, 192, 247, 26, 1, 114, 205, 50, 26, 1, 114, 214, 35, 26, 1, - 114, 210, 217, 26, 1, 114, 198, 59, 26, 1, 114, 220, 204, 26, 1, 114, - 219, 22, 26, 1, 114, 212, 212, 26, 1, 114, 213, 243, 26, 1, 114, 217, - 133, 26, 1, 114, 214, 4, 26, 1, 114, 213, 242, 26, 1, 114, 212, 211, 26, - 1, 114, 206, 192, 26, 1, 114, 213, 143, 26, 1, 114, 210, 46, 26, 1, 114, - 205, 197, 26, 1, 114, 214, 19, 26, 1, 114, 216, 136, 26, 1, 114, 231, 68, - 26, 1, 114, 214, 7, 26, 1, 114, 213, 154, 26, 1, 114, 217, 71, 26, 1, - 114, 219, 2, 26, 1, 114, 214, 40, 26, 1, 114, 214, 141, 26, 1, 114, 199, - 225, 212, 193, 26, 1, 114, 203, 252, 26, 1, 114, 208, 154, 26, 1, 114, - 214, 161, 202, 30, 26, 1, 114, 214, 27, 212, 95, 26, 1, 114, 192, 29, 26, - 1, 114, 231, 69, 26, 1, 114, 197, 88, 26, 1, 114, 192, 47, 26, 1, 114, - 209, 73, 26, 1, 114, 197, 75, 26, 1, 114, 221, 239, 26, 1, 114, 200, 248, - 26, 1, 114, 199, 61, 26, 1, 114, 195, 79, 26, 1, 114, 193, 100, 26, 1, - 114, 220, 123, 26, 1, 114, 208, 165, 26, 1, 114, 199, 239, 26, 1, 114, - 231, 89, 26, 1, 114, 214, 50, 26, 1, 114, 203, 89, 26, 1, 114, 216, 131, - 26, 1, 114, 217, 3, 26, 1, 114, 212, 44, 26, 1, 114, 213, 106, 26, 1, - 114, 231, 176, 26, 1, 114, 197, 76, 26, 1, 114, 220, 215, 26, 1, 114, - 192, 104, 26, 1, 114, 212, 82, 242, 237, 26, 1, 114, 192, 18, 26, 1, 114, - 216, 148, 26, 1, 114, 214, 146, 26, 1, 114, 209, 174, 26, 1, 114, 191, - 206, 26, 1, 114, 219, 171, 26, 1, 114, 232, 84, 26, 1, 114, 231, 175, 26, - 1, 114, 213, 253, 26, 1, 114, 221, 241, 26, 1, 114, 217, 136, 26, 1, 114, - 214, 10, 26, 1, 114, 231, 75, 26, 1, 114, 233, 109, 26, 1, 114, 212, 182, - 26, 1, 114, 209, 234, 26, 1, 114, 192, 45, 26, 1, 114, 214, 36, 26, 1, - 114, 212, 82, 248, 209, 26, 1, 114, 212, 24, 26, 1, 114, 209, 35, 26, 1, - 114, 216, 80, 26, 1, 114, 232, 82, 26, 1, 114, 214, 244, 26, 1, 114, 215, - 149, 26, 1, 114, 231, 74, 26, 1, 114, 232, 87, 68, 26, 1, 114, 215, 85, - 26, 1, 114, 208, 160, 26, 1, 114, 213, 255, 26, 1, 114, 220, 188, 26, 1, - 114, 209, 171, 26, 1, 114, 212, 196, 26, 1, 114, 192, 46, 26, 1, 114, - 214, 20, 26, 1, 114, 210, 221, 210, 19, 26, 1, 114, 232, 87, 247, 138, - 26, 1, 114, 232, 167, 26, 1, 114, 213, 148, 26, 1, 114, 65, 26, 1, 114, - 198, 50, 26, 1, 114, 74, 26, 1, 114, 68, 26, 1, 114, 220, 14, 26, 1, 114, - 210, 221, 209, 82, 26, 1, 114, 199, 245, 26, 1, 114, 199, 180, 26, 1, - 114, 214, 161, 215, 71, 228, 172, 26, 1, 114, 203, 64, 26, 1, 114, 192, - 42, 26, 1, 114, 213, 236, 26, 1, 114, 191, 211, 26, 1, 114, 191, 244, - 200, 136, 26, 1, 114, 191, 244, 238, 242, 26, 1, 114, 191, 194, 26, 1, - 114, 191, 202, 26, 1, 114, 221, 227, 26, 1, 114, 209, 232, 26, 1, 114, - 213, 149, 234, 49, 26, 1, 114, 208, 156, 26, 1, 114, 192, 253, 26, 1, - 114, 233, 52, 26, 1, 114, 195, 148, 26, 1, 114, 218, 225, 26, 1, 114, - 216, 100, 26, 1, 114, 207, 20, 26, 1, 114, 207, 163, 26, 1, 114, 213, - 235, 26, 1, 114, 214, 68, 26, 1, 114, 203, 56, 26, 1, 114, 203, 41, 26, - 1, 114, 232, 87, 207, 59, 26, 1, 114, 180, 26, 1, 114, 209, 185, 26, 1, - 114, 219, 0, 26, 1, 114, 221, 67, 26, 1, 114, 216, 186, 26, 1, 114, 174, - 26, 1, 114, 217, 68, 26, 1, 114, 199, 63, 26, 1, 114, 221, 166, 26, 1, - 114, 215, 231, 26, 1, 114, 199, 95, 26, 1, 114, 233, 76, 26, 1, 114, 231, - 62, 26, 1, 209, 215, 155, 26, 1, 209, 215, 66, 26, 1, 209, 215, 220, 232, - 26, 1, 209, 215, 234, 188, 26, 1, 209, 215, 207, 84, 26, 1, 209, 215, - 199, 226, 26, 1, 209, 215, 212, 81, 26, 1, 209, 215, 173, 26, 1, 209, - 215, 206, 195, 26, 1, 209, 215, 206, 242, 26, 1, 209, 215, 216, 210, 26, - 1, 209, 215, 199, 245, 26, 1, 209, 215, 214, 160, 26, 1, 209, 215, 213, - 155, 26, 1, 209, 215, 218, 168, 26, 1, 209, 215, 200, 160, 26, 1, 209, - 215, 203, 76, 26, 1, 209, 215, 202, 222, 26, 1, 209, 215, 203, 248, 26, - 1, 209, 215, 220, 149, 26, 1, 209, 215, 221, 241, 26, 1, 209, 215, 212, - 146, 26, 1, 209, 215, 212, 178, 26, 1, 209, 215, 213, 126, 26, 1, 209, - 215, 191, 243, 26, 1, 209, 215, 203, 5, 26, 1, 209, 215, 170, 26, 1, 209, - 215, 212, 215, 26, 1, 209, 215, 209, 232, 26, 1, 209, 215, 212, 195, 26, - 1, 209, 215, 192, 253, 26, 1, 209, 215, 210, 49, 26, 1, 209, 215, 206, - 68, 26, 1, 209, 215, 213, 219, 26, 1, 209, 215, 207, 20, 26, 1, 209, 215, - 221, 251, 26, 1, 209, 215, 213, 252, 26, 1, 209, 215, 214, 47, 26, 1, - 209, 215, 203, 56, 26, 1, 209, 215, 208, 161, 26, 1, 209, 215, 232, 167, - 26, 1, 209, 215, 193, 190, 26, 1, 209, 215, 219, 146, 26, 1, 209, 215, - 219, 0, 26, 1, 209, 215, 221, 67, 26, 1, 209, 215, 217, 1, 26, 1, 209, - 215, 207, 55, 26, 1, 209, 215, 174, 26, 1, 209, 215, 216, 12, 26, 1, 209, - 215, 217, 9, 26, 1, 209, 215, 199, 73, 26, 1, 209, 215, 221, 21, 26, 1, - 209, 215, 205, 150, 26, 1, 209, 215, 193, 248, 215, 159, 1, 190, 190, - 215, 159, 1, 214, 16, 215, 159, 1, 192, 12, 215, 159, 1, 216, 46, 215, - 159, 1, 249, 153, 215, 159, 1, 238, 32, 215, 159, 1, 65, 215, 159, 1, - 209, 211, 215, 159, 1, 221, 209, 215, 159, 1, 230, 22, 215, 159, 1, 238, - 7, 215, 159, 1, 243, 48, 215, 159, 1, 222, 15, 215, 159, 1, 211, 120, - 215, 159, 1, 217, 133, 215, 159, 1, 213, 179, 215, 159, 1, 168, 215, 159, - 1, 211, 87, 215, 159, 1, 74, 215, 159, 1, 206, 162, 215, 159, 1, 203, 81, - 215, 159, 1, 199, 32, 215, 159, 1, 234, 217, 215, 159, 1, 193, 190, 215, - 159, 1, 71, 215, 159, 1, 221, 67, 215, 159, 1, 220, 24, 215, 159, 1, 173, - 215, 159, 1, 230, 80, 215, 159, 1, 207, 1, 215, 159, 1, 199, 110, 215, - 159, 17, 191, 77, 215, 159, 17, 107, 215, 159, 17, 109, 215, 159, 17, - 138, 215, 159, 17, 134, 215, 159, 17, 149, 215, 159, 17, 169, 215, 159, - 17, 175, 215, 159, 17, 171, 215, 159, 17, 178, 215, 159, 237, 238, 215, - 159, 55, 237, 238, 199, 186, 1, 210, 238, 199, 186, 1, 211, 166, 199, - 186, 1, 211, 58, 199, 186, 1, 210, 247, 199, 186, 1, 250, 123, 199, 186, - 1, 252, 63, 199, 186, 1, 251, 37, 199, 186, 1, 250, 133, 199, 186, 1, - 193, 227, 199, 186, 1, 195, 155, 199, 186, 1, 194, 255, 199, 186, 1, 193, - 236, 199, 186, 1, 233, 182, 199, 186, 1, 234, 197, 199, 186, 1, 234, 46, - 199, 186, 1, 233, 221, 199, 186, 1, 223, 41, 199, 186, 1, 228, 28, 199, - 186, 1, 223, 79, 199, 186, 1, 223, 45, 199, 186, 1, 196, 18, 199, 186, 1, - 196, 160, 199, 186, 1, 196, 64, 199, 186, 1, 196, 22, 199, 186, 1, 250, - 134, 199, 186, 1, 250, 138, 199, 186, 1, 250, 136, 199, 186, 1, 250, 135, - 199, 186, 1, 196, 129, 199, 186, 1, 196, 138, 199, 186, 1, 196, 135, 199, - 186, 1, 196, 130, 199, 186, 1, 53, 214, 70, 199, 186, 1, 179, 196, 145, - 199, 186, 1, 203, 40, 196, 143, 199, 186, 1, 203, 40, 250, 135, 199, 186, - 1, 196, 150, 199, 186, 1, 196, 143, 199, 186, 1, 196, 146, 199, 186, 1, - 196, 145, 199, 186, 1, 196, 131, 199, 186, 1, 196, 134, 199, 186, 1, 196, - 133, 199, 186, 1, 196, 132, 199, 186, 1, 215, 63, 199, 186, 1, 216, 238, - 199, 186, 1, 215, 165, 199, 186, 1, 215, 72, 199, 186, 1, 155, 199, 186, - 1, 221, 215, 199, 186, 1, 231, 240, 199, 186, 1, 214, 68, 199, 186, 1, - 188, 199, 186, 1, 170, 199, 186, 1, 193, 190, 199, 186, 1, 168, 199, 186, - 1, 212, 101, 199, 186, 1, 209, 228, 199, 186, 1, 249, 153, 199, 186, 1, - 174, 199, 186, 1, 180, 199, 186, 1, 140, 199, 186, 1, 173, 199, 186, 1, - 228, 164, 199, 186, 1, 190, 190, 199, 186, 1, 238, 32, 199, 186, 1, 165, - 199, 186, 1, 213, 224, 199, 186, 1, 203, 165, 199, 186, 1, 247, 160, 199, - 186, 1, 197, 168, 199, 186, 1, 231, 91, 199, 186, 1, 228, 161, 199, 186, - 1, 199, 49, 199, 186, 1, 192, 220, 199, 186, 1, 233, 109, 199, 186, 1, - 237, 68, 199, 186, 1, 247, 1, 199, 186, 1, 191, 123, 199, 186, 17, 191, - 77, 199, 186, 17, 107, 199, 186, 17, 109, 199, 186, 17, 138, 199, 186, - 17, 134, 199, 186, 17, 149, 199, 186, 17, 169, 199, 186, 17, 175, 199, - 186, 17, 171, 199, 186, 17, 178, 249, 67, 195, 185, 1, 234, 84, 249, 67, - 195, 185, 1, 155, 249, 67, 195, 185, 1, 205, 68, 249, 67, 195, 185, 1, - 233, 109, 249, 67, 195, 185, 1, 217, 4, 249, 67, 195, 185, 1, 192, 30, - 249, 67, 195, 185, 1, 231, 225, 249, 67, 195, 185, 1, 237, 49, 249, 67, - 195, 185, 1, 221, 20, 249, 67, 195, 185, 1, 222, 201, 249, 67, 195, 185, - 1, 228, 124, 249, 67, 195, 185, 1, 193, 190, 249, 67, 195, 185, 1, 191, - 7, 249, 67, 195, 185, 1, 231, 169, 249, 67, 195, 185, 1, 236, 174, 249, - 67, 195, 185, 1, 247, 42, 249, 67, 195, 185, 1, 196, 23, 249, 67, 195, - 185, 1, 159, 249, 67, 195, 185, 1, 249, 153, 249, 67, 195, 185, 1, 193, - 249, 249, 67, 195, 185, 1, 192, 74, 249, 67, 195, 185, 1, 168, 249, 67, - 195, 185, 1, 193, 177, 249, 67, 195, 185, 1, 65, 249, 67, 195, 185, 1, - 74, 249, 67, 195, 185, 1, 211, 87, 249, 67, 195, 185, 1, 66, 249, 67, - 195, 185, 1, 234, 188, 249, 67, 195, 185, 1, 71, 249, 67, 195, 185, 1, - 68, 249, 67, 195, 185, 33, 137, 198, 79, 249, 67, 195, 185, 33, 130, 198, - 79, 249, 67, 195, 185, 33, 216, 87, 198, 79, 249, 67, 195, 185, 33, 218, - 238, 198, 79, 249, 67, 195, 185, 33, 229, 133, 198, 79, 249, 67, 195, - 185, 232, 80, 201, 63, 145, 90, 18, 222, 12, 145, 90, 18, 222, 8, 145, - 90, 18, 221, 155, 145, 90, 18, 221, 118, 145, 90, 18, 222, 41, 145, 90, - 18, 222, 38, 145, 90, 18, 220, 216, 145, 90, 18, 220, 185, 145, 90, 18, - 222, 14, 145, 90, 18, 221, 225, 145, 90, 18, 222, 101, 145, 90, 18, 222, - 98, 145, 90, 18, 221, 40, 145, 90, 18, 221, 37, 145, 90, 18, 222, 34, - 145, 90, 18, 222, 31, 145, 90, 18, 220, 218, 145, 90, 18, 220, 217, 145, - 90, 18, 221, 60, 145, 90, 18, 221, 25, 145, 90, 18, 221, 157, 145, 90, - 18, 221, 156, 145, 90, 18, 222, 117, 145, 90, 18, 222, 37, 145, 90, 18, - 220, 175, 145, 90, 18, 220, 166, 145, 90, 18, 222, 126, 145, 90, 18, 222, - 118, 145, 90, 120, 195, 160, 145, 90, 120, 212, 185, 145, 90, 120, 220, - 0, 145, 90, 120, 230, 2, 145, 90, 120, 213, 82, 145, 90, 120, 207, 125, - 145, 90, 120, 213, 109, 145, 90, 120, 208, 69, 145, 90, 120, 192, 91, - 145, 90, 120, 229, 108, 145, 90, 120, 217, 25, 145, 90, 120, 243, 131, - 145, 90, 120, 214, 165, 145, 90, 120, 229, 44, 145, 90, 120, 209, 91, - 145, 90, 120, 212, 191, 145, 90, 120, 214, 205, 145, 90, 120, 250, 163, - 145, 90, 120, 192, 216, 145, 90, 120, 247, 76, 145, 90, 87, 243, 17, 197, - 85, 145, 90, 87, 243, 17, 202, 46, 145, 90, 87, 243, 17, 221, 243, 145, - 90, 87, 243, 17, 221, 198, 145, 90, 87, 243, 17, 200, 246, 145, 90, 87, - 243, 17, 229, 2, 145, 90, 87, 243, 17, 199, 165, 145, 90, 3, 195, 5, 198, - 238, 145, 90, 3, 195, 5, 197, 156, 247, 33, 145, 90, 3, 243, 17, 243, - 120, 145, 90, 3, 195, 5, 199, 10, 145, 90, 3, 195, 5, 233, 49, 145, 90, - 3, 192, 171, 212, 179, 145, 90, 3, 192, 171, 207, 3, 145, 90, 3, 192, - 171, 198, 32, 145, 90, 3, 192, 171, 233, 90, 145, 90, 3, 195, 5, 205, 44, - 145, 90, 3, 216, 209, 200, 250, 145, 90, 3, 195, 5, 212, 231, 145, 90, 3, - 228, 31, 192, 111, 145, 90, 3, 192, 215, 145, 90, 3, 243, 17, 197, 143, - 206, 144, 145, 90, 17, 191, 77, 145, 90, 17, 107, 145, 90, 17, 109, 145, - 90, 17, 138, 145, 90, 17, 134, 145, 90, 17, 149, 145, 90, 17, 169, 145, - 90, 17, 175, 145, 90, 17, 171, 145, 90, 17, 178, 145, 90, 31, 199, 90, - 145, 90, 31, 228, 138, 145, 90, 31, 199, 96, 198, 228, 145, 90, 31, 216, - 47, 145, 90, 31, 228, 141, 216, 47, 145, 90, 31, 199, 96, 248, 169, 145, - 90, 31, 197, 227, 145, 90, 3, 195, 5, 218, 220, 145, 90, 3, 192, 168, - 145, 90, 3, 229, 103, 145, 90, 3, 198, 255, 229, 103, 145, 90, 3, 190, - 236, 199, 43, 145, 90, 3, 229, 28, 145, 90, 3, 212, 245, 145, 90, 3, 192, - 206, 145, 90, 3, 212, 183, 145, 90, 3, 250, 146, 145, 90, 3, 197, 7, 247, - 32, 145, 90, 3, 216, 209, 197, 159, 145, 90, 3, 199, 166, 145, 90, 3, - 218, 253, 145, 90, 3, 215, 103, 145, 90, 3, 243, 17, 230, 76, 218, 196, - 212, 189, 212, 188, 145, 90, 3, 243, 17, 238, 194, 197, 150, 145, 90, 3, - 243, 17, 197, 5, 145, 90, 3, 243, 17, 197, 6, 243, 36, 145, 90, 3, 243, - 17, 208, 159, 237, 206, 145, 90, 3, 243, 17, 212, 238, 198, 41, 145, 90, - 242, 244, 3, 197, 154, 145, 90, 242, 244, 3, 192, 76, 145, 90, 242, 244, - 3, 219, 90, 145, 90, 242, 244, 3, 219, 254, 145, 90, 242, 244, 3, 192, - 167, 145, 90, 242, 244, 3, 221, 41, 145, 90, 242, 244, 3, 229, 254, 145, - 90, 242, 244, 3, 215, 147, 145, 90, 242, 244, 3, 198, 239, 145, 90, 242, - 244, 3, 197, 165, 145, 90, 242, 244, 3, 209, 225, 145, 90, 242, 244, 3, - 221, 213, 145, 90, 242, 244, 3, 230, 64, 145, 90, 242, 244, 3, 195, 182, - 145, 90, 242, 244, 3, 233, 86, 145, 90, 242, 244, 3, 192, 118, 145, 90, - 242, 244, 3, 197, 137, 145, 90, 242, 244, 3, 220, 170, 145, 90, 242, 244, - 3, 193, 237, 216, 218, 6, 1, 218, 168, 216, 218, 6, 1, 206, 8, 216, 218, - 6, 1, 196, 12, 216, 218, 6, 1, 193, 224, 216, 218, 6, 1, 250, 176, 216, - 218, 6, 1, 191, 166, 216, 218, 6, 1, 221, 22, 216, 218, 6, 1, 210, 236, - 216, 218, 6, 1, 200, 43, 216, 218, 6, 1, 232, 51, 216, 218, 6, 1, 233, - 175, 216, 218, 6, 1, 68, 216, 218, 6, 1, 222, 152, 216, 218, 6, 1, 65, - 216, 218, 6, 1, 223, 35, 216, 218, 6, 1, 71, 216, 218, 6, 1, 250, 120, - 216, 218, 6, 1, 247, 193, 216, 218, 6, 1, 66, 216, 218, 6, 1, 191, 225, - 216, 218, 6, 1, 172, 216, 218, 6, 1, 208, 104, 216, 218, 6, 1, 228, 169, - 216, 218, 6, 1, 212, 103, 216, 218, 6, 1, 192, 235, 216, 218, 6, 1, 238, - 127, 216, 218, 6, 1, 211, 151, 216, 218, 6, 1, 215, 61, 216, 218, 6, 1, - 146, 216, 218, 6, 1, 74, 216, 218, 6, 1, 251, 236, 216, 218, 6, 1, 192, - 159, 216, 218, 2, 1, 218, 168, 216, 218, 2, 1, 206, 8, 216, 218, 2, 1, - 196, 12, 216, 218, 2, 1, 193, 224, 216, 218, 2, 1, 250, 176, 216, 218, 2, - 1, 191, 166, 216, 218, 2, 1, 221, 22, 216, 218, 2, 1, 210, 236, 216, 218, - 2, 1, 200, 43, 216, 218, 2, 1, 232, 51, 216, 218, 2, 1, 233, 175, 216, - 218, 2, 1, 68, 216, 218, 2, 1, 222, 152, 216, 218, 2, 1, 65, 216, 218, 2, - 1, 223, 35, 216, 218, 2, 1, 71, 216, 218, 2, 1, 250, 120, 216, 218, 2, 1, - 247, 193, 216, 218, 2, 1, 66, 216, 218, 2, 1, 191, 225, 216, 218, 2, 1, - 172, 216, 218, 2, 1, 208, 104, 216, 218, 2, 1, 228, 169, 216, 218, 2, 1, - 212, 103, 216, 218, 2, 1, 192, 235, 216, 218, 2, 1, 238, 127, 216, 218, - 2, 1, 211, 151, 216, 218, 2, 1, 215, 61, 216, 218, 2, 1, 146, 216, 218, - 2, 1, 74, 216, 218, 2, 1, 251, 236, 216, 218, 2, 1, 192, 159, 216, 218, - 17, 191, 77, 216, 218, 17, 107, 216, 218, 17, 109, 216, 218, 17, 138, - 216, 218, 17, 134, 216, 218, 17, 149, 216, 218, 17, 169, 216, 218, 17, - 175, 216, 218, 17, 171, 216, 218, 17, 178, 216, 218, 31, 199, 95, 216, - 218, 31, 234, 127, 216, 218, 31, 197, 37, 216, 218, 31, 198, 251, 216, - 218, 31, 232, 122, 216, 218, 31, 233, 19, 216, 218, 31, 202, 130, 216, - 218, 31, 203, 244, 216, 218, 31, 234, 161, 216, 218, 31, 213, 171, 216, - 218, 17, 91, 251, 157, 20, 216, 218, 17, 105, 251, 157, 20, 216, 218, 17, - 115, 251, 157, 20, 216, 218, 242, 74, 216, 218, 232, 80, 201, 63, 216, - 218, 16, 251, 221, 216, 218, 233, 216, 211, 136, 121, 1, 168, 121, 1, - 249, 153, 121, 1, 11, 168, 121, 1, 209, 110, 121, 1, 174, 121, 1, 216, - 103, 121, 1, 251, 14, 174, 121, 1, 233, 109, 121, 1, 195, 188, 121, 1, - 195, 71, 121, 1, 190, 190, 121, 1, 238, 32, 121, 1, 11, 197, 132, 121, 1, - 11, 190, 190, 121, 1, 197, 132, 121, 1, 237, 191, 121, 1, 180, 121, 1, - 213, 224, 121, 1, 11, 213, 79, 121, 1, 251, 14, 180, 121, 1, 213, 79, - 121, 1, 213, 65, 121, 1, 173, 121, 1, 218, 182, 121, 1, 219, 159, 121, 1, - 219, 148, 121, 1, 198, 112, 121, 1, 236, 183, 121, 1, 198, 104, 121, 1, - 236, 182, 121, 1, 155, 121, 1, 231, 240, 121, 1, 11, 155, 121, 1, 208, - 96, 121, 1, 208, 72, 121, 1, 214, 68, 121, 1, 214, 17, 121, 1, 251, 14, - 214, 68, 121, 1, 140, 121, 1, 192, 220, 121, 1, 231, 91, 121, 1, 231, 66, - 121, 1, 197, 142, 121, 1, 235, 18, 121, 1, 212, 101, 121, 1, 212, 83, - 121, 1, 197, 157, 121, 1, 235, 29, 121, 1, 11, 197, 157, 121, 1, 11, 235, - 29, 121, 1, 207, 82, 197, 157, 121, 1, 203, 165, 121, 1, 201, 175, 121, - 1, 191, 71, 121, 1, 190, 253, 121, 1, 197, 168, 121, 1, 235, 35, 121, 1, - 11, 197, 168, 121, 1, 188, 121, 1, 191, 123, 121, 1, 190, 254, 121, 1, - 190, 224, 121, 1, 190, 204, 121, 1, 251, 14, 190, 224, 121, 1, 190, 196, - 121, 1, 190, 203, 121, 1, 193, 190, 121, 1, 251, 245, 121, 1, 229, 177, - 121, 1, 248, 32, 121, 1, 200, 125, 121, 1, 235, 19, 121, 1, 199, 145, - 121, 1, 197, 161, 121, 1, 206, 71, 121, 3, 120, 52, 164, 121, 1, 214, - 212, 121, 3, 250, 199, 121, 3, 207, 82, 195, 18, 121, 3, 207, 82, 250, - 199, 121, 18, 3, 65, 121, 18, 3, 252, 206, 121, 18, 3, 251, 241, 121, 18, - 3, 251, 132, 121, 18, 3, 251, 122, 121, 18, 3, 74, 121, 18, 3, 211, 87, - 121, 18, 3, 193, 48, 121, 18, 3, 193, 224, 121, 18, 3, 71, 121, 18, 3, - 234, 103, 121, 18, 3, 234, 88, 121, 18, 3, 211, 147, 121, 18, 3, 68, 121, - 18, 3, 228, 35, 121, 18, 3, 228, 34, 121, 18, 3, 228, 33, 121, 18, 3, - 223, 88, 121, 18, 3, 223, 226, 121, 18, 3, 223, 199, 121, 18, 3, 223, 49, - 121, 18, 3, 223, 136, 121, 18, 3, 66, 121, 18, 3, 196, 168, 121, 18, 3, - 196, 167, 121, 18, 3, 196, 166, 121, 18, 3, 196, 30, 121, 18, 3, 196, - 148, 121, 18, 3, 196, 97, 121, 18, 3, 192, 159, 121, 18, 3, 192, 33, 121, - 18, 3, 252, 25, 121, 18, 3, 252, 21, 121, 18, 3, 234, 26, 121, 18, 3, - 206, 113, 234, 26, 121, 18, 3, 234, 34, 121, 18, 3, 206, 113, 234, 34, - 121, 18, 3, 251, 236, 121, 18, 3, 234, 166, 121, 18, 3, 250, 163, 121, - 18, 3, 211, 19, 121, 18, 3, 215, 61, 121, 18, 3, 214, 70, 121, 18, 3, - 196, 81, 121, 18, 3, 191, 205, 121, 18, 3, 211, 141, 121, 18, 3, 211, - 148, 121, 18, 3, 193, 239, 121, 18, 3, 223, 204, 121, 18, 3, 234, 217, - 121, 18, 3, 223, 86, 121, 18, 3, 196, 139, 121, 163, 183, 121, 163, 198, - 54, 183, 121, 163, 58, 121, 163, 60, 121, 1, 198, 77, 121, 1, 198, 76, - 121, 1, 198, 75, 121, 1, 198, 74, 121, 1, 198, 73, 121, 1, 198, 72, 121, - 1, 198, 71, 121, 1, 207, 82, 198, 78, 121, 1, 207, 82, 198, 77, 121, 1, - 207, 82, 198, 75, 121, 1, 207, 82, 198, 74, 121, 1, 207, 82, 198, 73, - 121, 1, 207, 82, 198, 71, 19, 223, 51, 77, 46, 223, 51, 77, 39, 243, 80, - 228, 251, 77, 39, 243, 80, 223, 51, 77, 41, 2, 27, 233, 3, 195, 57, 251, - 157, 207, 107, 87, 247, 160, 195, 57, 251, 157, 207, 107, 87, 213, 223, - 19, 242, 63, 19, 242, 62, 19, 242, 61, 19, 242, 60, 19, 242, 59, 19, 242, - 58, 19, 242, 57, 19, 242, 56, 19, 242, 55, 19, 242, 54, 19, 242, 53, 19, - 242, 52, 19, 242, 51, 19, 242, 50, 19, 242, 49, 19, 242, 48, 19, 242, 47, - 19, 242, 46, 19, 242, 45, 19, 242, 44, 19, 242, 43, 19, 242, 42, 19, 242, - 41, 19, 242, 40, 19, 242, 39, 19, 242, 38, 19, 242, 37, 19, 242, 36, 19, - 242, 35, 19, 242, 34, 19, 242, 33, 19, 242, 32, 19, 242, 31, 19, 242, 30, - 19, 242, 29, 19, 242, 28, 19, 242, 27, 19, 242, 26, 19, 242, 25, 19, 242, - 24, 19, 242, 23, 19, 242, 22, 19, 242, 21, 19, 242, 20, 19, 242, 19, 19, - 242, 18, 19, 242, 17, 19, 242, 16, 19, 242, 15, 19, 242, 14, 19, 242, 13, - 19, 242, 12, 19, 242, 11, 19, 242, 10, 19, 242, 9, 19, 242, 8, 19, 242, - 7, 19, 242, 6, 19, 242, 5, 19, 242, 4, 19, 242, 3, 19, 242, 2, 19, 242, - 1, 19, 242, 0, 19, 241, 255, 19, 241, 254, 19, 241, 253, 19, 241, 252, - 19, 241, 251, 19, 241, 250, 19, 241, 249, 19, 241, 248, 19, 241, 247, 19, - 241, 246, 19, 241, 245, 19, 241, 244, 19, 241, 243, 19, 241, 242, 19, - 241, 241, 19, 241, 240, 19, 241, 239, 19, 241, 238, 19, 241, 237, 19, - 241, 236, 19, 241, 235, 19, 241, 234, 19, 241, 233, 19, 241, 232, 19, - 241, 231, 19, 241, 230, 19, 241, 229, 19, 241, 228, 19, 241, 227, 19, - 241, 226, 19, 241, 225, 19, 241, 224, 19, 241, 223, 19, 241, 222, 19, - 241, 221, 19, 241, 220, 19, 241, 219, 19, 241, 218, 19, 241, 217, 19, - 241, 216, 19, 241, 215, 19, 241, 214, 19, 241, 213, 19, 241, 212, 19, - 241, 211, 19, 241, 210, 19, 241, 209, 19, 241, 208, 19, 241, 207, 19, - 241, 206, 19, 241, 205, 19, 241, 204, 19, 241, 203, 19, 241, 202, 19, - 241, 201, 19, 241, 200, 19, 241, 199, 19, 241, 198, 19, 241, 197, 19, - 241, 196, 19, 241, 195, 19, 241, 194, 19, 241, 193, 19, 241, 192, 19, - 241, 191, 19, 241, 190, 19, 241, 189, 19, 241, 188, 19, 241, 187, 19, - 241, 186, 19, 241, 185, 19, 241, 184, 19, 241, 183, 19, 241, 182, 19, - 241, 181, 19, 241, 180, 19, 241, 179, 19, 241, 178, 19, 241, 177, 19, - 241, 176, 19, 241, 175, 19, 241, 174, 19, 241, 173, 19, 241, 172, 19, - 241, 171, 19, 241, 170, 19, 241, 169, 19, 241, 168, 19, 241, 167, 19, - 241, 166, 19, 241, 165, 19, 241, 164, 19, 241, 163, 19, 241, 162, 19, - 241, 161, 19, 241, 160, 19, 241, 159, 19, 241, 158, 19, 241, 157, 19, - 241, 156, 19, 241, 155, 19, 241, 154, 19, 241, 153, 19, 241, 152, 19, - 241, 151, 19, 241, 150, 19, 241, 149, 19, 241, 148, 19, 241, 147, 19, - 241, 146, 19, 241, 145, 19, 241, 144, 19, 241, 143, 19, 241, 142, 19, - 241, 141, 19, 241, 140, 19, 241, 139, 19, 241, 138, 19, 241, 137, 19, - 241, 136, 19, 241, 135, 19, 241, 134, 19, 241, 133, 19, 241, 132, 19, - 241, 131, 19, 241, 130, 19, 241, 129, 19, 241, 128, 19, 241, 127, 19, - 241, 126, 19, 241, 125, 19, 241, 124, 19, 241, 123, 19, 241, 122, 19, - 241, 121, 19, 241, 120, 19, 241, 119, 19, 241, 118, 19, 241, 117, 19, - 241, 116, 19, 241, 115, 19, 241, 114, 19, 241, 113, 19, 241, 112, 19, - 241, 111, 19, 241, 110, 19, 241, 109, 19, 241, 108, 19, 241, 107, 19, - 241, 106, 19, 241, 105, 19, 241, 104, 19, 241, 103, 19, 241, 102, 19, - 241, 101, 19, 241, 100, 19, 241, 99, 19, 241, 98, 19, 241, 97, 19, 241, - 96, 19, 241, 95, 19, 241, 94, 19, 241, 93, 19, 241, 92, 19, 241, 91, 19, - 241, 90, 19, 241, 89, 19, 241, 88, 19, 241, 87, 19, 241, 86, 19, 241, 85, - 19, 241, 84, 19, 241, 83, 19, 241, 82, 19, 241, 81, 19, 241, 80, 19, 241, - 79, 19, 241, 78, 19, 241, 77, 19, 241, 76, 19, 241, 75, 19, 241, 74, 19, - 241, 73, 19, 241, 72, 19, 241, 71, 19, 241, 70, 19, 241, 69, 19, 241, 68, - 19, 241, 67, 19, 241, 66, 19, 241, 65, 19, 241, 64, 19, 241, 63, 19, 241, - 62, 19, 241, 61, 19, 241, 60, 19, 241, 59, 19, 241, 58, 19, 241, 57, 19, - 241, 56, 19, 241, 55, 19, 241, 54, 19, 241, 53, 19, 241, 52, 19, 241, 51, - 19, 241, 50, 19, 241, 49, 19, 241, 48, 19, 241, 47, 19, 241, 46, 19, 241, - 45, 19, 241, 44, 19, 241, 43, 19, 241, 42, 19, 241, 41, 19, 241, 40, 19, - 241, 39, 19, 241, 38, 19, 241, 37, 19, 241, 36, 19, 241, 35, 19, 241, 34, - 19, 241, 33, 19, 241, 32, 19, 241, 31, 19, 241, 30, 19, 241, 29, 19, 241, - 28, 19, 241, 27, 19, 241, 26, 19, 241, 25, 19, 241, 24, 19, 241, 23, 19, - 241, 22, 19, 241, 21, 19, 241, 20, 19, 241, 19, 19, 241, 18, 19, 241, 17, - 19, 241, 16, 19, 241, 15, 19, 241, 14, 19, 241, 13, 19, 241, 12, 19, 241, - 11, 19, 241, 10, 19, 241, 9, 19, 241, 8, 19, 241, 7, 19, 241, 6, 19, 241, - 5, 19, 241, 4, 19, 241, 3, 19, 241, 2, 19, 241, 1, 19, 241, 0, 19, 240, - 255, 19, 240, 254, 19, 240, 253, 19, 240, 252, 19, 240, 251, 19, 240, - 250, 19, 240, 249, 19, 240, 248, 19, 240, 247, 19, 240, 246, 19, 240, - 245, 19, 240, 244, 19, 240, 243, 19, 240, 242, 19, 240, 241, 19, 240, - 240, 19, 240, 239, 19, 240, 238, 19, 240, 237, 19, 240, 236, 19, 240, - 235, 19, 240, 234, 19, 240, 233, 19, 240, 232, 19, 240, 231, 19, 240, - 230, 19, 240, 229, 19, 240, 228, 19, 240, 227, 19, 240, 226, 19, 240, - 225, 19, 240, 224, 19, 240, 223, 19, 240, 222, 19, 240, 221, 19, 240, - 220, 19, 240, 219, 19, 240, 218, 19, 240, 217, 19, 240, 216, 19, 240, - 215, 19, 240, 214, 19, 240, 213, 19, 240, 212, 19, 240, 211, 19, 240, - 210, 19, 240, 209, 19, 240, 208, 19, 240, 207, 19, 240, 206, 19, 240, - 205, 19, 240, 204, 19, 240, 203, 19, 240, 202, 19, 240, 201, 19, 240, - 200, 19, 240, 199, 19, 240, 198, 19, 240, 197, 19, 240, 196, 19, 240, - 195, 19, 240, 194, 19, 240, 193, 19, 240, 192, 19, 240, 191, 19, 240, - 190, 19, 240, 189, 19, 240, 188, 19, 240, 187, 19, 240, 186, 19, 240, - 185, 19, 240, 184, 19, 240, 183, 19, 240, 182, 19, 240, 181, 19, 240, - 180, 19, 240, 179, 19, 240, 178, 19, 240, 177, 19, 240, 176, 19, 240, - 175, 19, 240, 174, 19, 240, 173, 19, 240, 172, 19, 240, 171, 19, 240, - 170, 19, 240, 169, 19, 240, 168, 19, 240, 167, 19, 240, 166, 19, 240, - 165, 19, 240, 164, 19, 240, 163, 19, 240, 162, 19, 240, 161, 19, 240, - 160, 19, 240, 159, 19, 240, 158, 19, 240, 157, 19, 240, 156, 19, 240, - 155, 19, 240, 154, 19, 240, 153, 19, 240, 152, 19, 240, 151, 19, 240, - 150, 19, 240, 149, 19, 240, 148, 19, 240, 147, 19, 240, 146, 19, 240, - 145, 19, 240, 144, 19, 240, 143, 19, 240, 142, 19, 240, 141, 19, 240, - 140, 19, 240, 139, 19, 240, 138, 19, 240, 137, 19, 240, 136, 19, 240, - 135, 19, 240, 134, 19, 240, 133, 19, 240, 132, 19, 240, 131, 19, 240, - 130, 19, 240, 129, 19, 240, 128, 19, 240, 127, 19, 240, 126, 19, 240, - 125, 19, 240, 124, 19, 240, 123, 19, 240, 122, 19, 240, 121, 19, 240, - 120, 19, 240, 119, 19, 240, 118, 19, 240, 117, 19, 240, 116, 19, 240, - 115, 19, 240, 114, 19, 240, 113, 19, 240, 112, 19, 240, 111, 19, 240, - 110, 19, 240, 109, 19, 240, 108, 19, 240, 107, 19, 240, 106, 19, 240, - 105, 19, 240, 104, 19, 240, 103, 19, 240, 102, 19, 240, 101, 19, 240, - 100, 19, 240, 99, 19, 240, 98, 19, 240, 97, 19, 240, 96, 19, 240, 95, 19, - 240, 94, 19, 240, 93, 19, 240, 92, 19, 240, 91, 19, 240, 90, 19, 240, 89, - 19, 240, 88, 19, 240, 87, 19, 240, 86, 19, 240, 85, 19, 240, 84, 19, 240, - 83, 19, 240, 82, 19, 240, 81, 19, 240, 80, 19, 240, 79, 19, 240, 78, 19, - 240, 77, 19, 240, 76, 19, 240, 75, 19, 240, 74, 19, 240, 73, 19, 240, 72, - 19, 240, 71, 19, 240, 70, 19, 240, 69, 19, 240, 68, 19, 240, 67, 19, 240, - 66, 19, 240, 65, 19, 240, 64, 19, 240, 63, 19, 240, 62, 19, 240, 61, 19, - 240, 60, 19, 240, 59, 19, 240, 58, 19, 240, 57, 19, 240, 56, 19, 240, 55, - 19, 240, 54, 19, 240, 53, 19, 240, 52, 19, 240, 51, 19, 240, 50, 19, 240, - 49, 19, 240, 48, 19, 240, 47, 19, 240, 46, 19, 240, 45, 19, 240, 44, 19, - 240, 43, 19, 240, 42, 19, 240, 41, 19, 240, 40, 19, 240, 39, 19, 240, 38, - 19, 240, 37, 19, 240, 36, 19, 240, 35, 19, 240, 34, 19, 240, 33, 19, 240, - 32, 19, 240, 31, 19, 240, 30, 19, 240, 29, 19, 240, 28, 19, 240, 27, 19, - 240, 26, 19, 240, 25, 19, 240, 24, 19, 240, 23, 19, 240, 22, 19, 240, 21, - 19, 240, 20, 19, 240, 19, 19, 240, 18, 19, 240, 17, 19, 240, 16, 19, 240, - 15, 19, 240, 14, 19, 240, 13, 19, 240, 12, 19, 240, 11, 19, 240, 10, 19, - 240, 9, 19, 240, 8, 19, 240, 7, 19, 240, 6, 19, 240, 5, 19, 240, 4, 19, - 240, 3, 19, 240, 2, 19, 240, 1, 19, 240, 0, 19, 239, 255, 19, 239, 254, - 19, 239, 253, 19, 239, 252, 19, 239, 251, 19, 239, 250, 19, 239, 249, 19, - 239, 248, 19, 239, 247, 19, 239, 246, 19, 239, 245, 19, 239, 244, 19, - 239, 243, 19, 239, 242, 19, 239, 241, 19, 239, 240, 19, 239, 239, 19, - 239, 238, 19, 239, 237, 19, 239, 236, 19, 239, 235, 19, 239, 234, 19, - 239, 233, 19, 239, 232, 19, 239, 231, 19, 239, 230, 19, 239, 229, 19, - 239, 228, 19, 239, 227, 19, 239, 226, 19, 239, 225, 19, 239, 224, 19, - 239, 223, 19, 239, 222, 19, 239, 221, 19, 239, 220, 19, 239, 219, 19, - 239, 218, 19, 239, 217, 19, 239, 216, 19, 239, 215, 19, 239, 214, 19, - 239, 213, 19, 239, 212, 19, 239, 211, 19, 239, 210, 19, 239, 209, 19, - 239, 208, 19, 239, 207, 19, 239, 206, 19, 239, 205, 19, 239, 204, 19, - 239, 203, 19, 239, 202, 19, 239, 201, 19, 239, 200, 19, 239, 199, 19, - 239, 198, 19, 239, 197, 19, 239, 196, 19, 239, 195, 19, 239, 194, 19, - 239, 193, 19, 239, 192, 19, 239, 191, 19, 239, 190, 19, 239, 189, 19, - 239, 188, 19, 239, 187, 19, 239, 186, 19, 239, 185, 19, 239, 184, 19, - 239, 183, 19, 239, 182, 19, 239, 181, 19, 239, 180, 19, 239, 179, 19, - 239, 178, 19, 239, 177, 19, 239, 176, 19, 239, 175, 19, 239, 174, 19, - 239, 173, 19, 239, 172, 19, 239, 171, 19, 239, 170, 19, 239, 169, 19, - 239, 168, 19, 239, 167, 19, 239, 166, 19, 239, 165, 19, 239, 164, 19, - 239, 163, 19, 239, 162, 19, 239, 161, 19, 239, 160, 19, 239, 159, 19, - 239, 158, 19, 239, 157, 19, 239, 156, 19, 239, 155, 19, 239, 154, 19, - 239, 153, 19, 239, 152, 19, 239, 151, 19, 239, 150, 19, 239, 149, 19, - 239, 148, 19, 239, 147, 19, 239, 146, 19, 239, 145, 19, 239, 144, 19, - 239, 143, 19, 239, 142, 19, 239, 141, 19, 239, 140, 19, 239, 139, 19, - 239, 138, 19, 239, 137, 19, 239, 136, 19, 239, 135, 19, 239, 134, 19, - 239, 133, 19, 239, 132, 19, 239, 131, 19, 239, 130, 19, 239, 129, 19, - 239, 128, 19, 239, 127, 19, 239, 126, 19, 239, 125, 19, 239, 124, 19, - 239, 123, 19, 239, 122, 19, 239, 121, 19, 239, 120, 19, 239, 119, 19, - 239, 118, 19, 239, 117, 19, 239, 116, 19, 239, 115, 19, 239, 114, 19, - 239, 113, 19, 239, 112, 19, 239, 111, 19, 239, 110, 19, 239, 109, 19, - 239, 108, 19, 239, 107, 19, 239, 106, 19, 239, 105, 19, 239, 104, 19, - 239, 103, 19, 239, 102, 19, 239, 101, 19, 239, 100, 19, 239, 99, 19, 239, - 98, 19, 239, 97, 19, 239, 96, 19, 239, 95, 19, 239, 94, 19, 239, 93, 19, - 239, 92, 19, 239, 91, 19, 239, 90, 19, 239, 89, 19, 239, 88, 19, 239, 87, - 19, 239, 86, 19, 239, 85, 19, 239, 84, 19, 239, 83, 19, 239, 82, 19, 239, - 81, 19, 239, 80, 19, 239, 79, 19, 239, 78, 19, 239, 77, 19, 239, 76, 19, - 239, 75, 19, 239, 74, 19, 239, 73, 19, 239, 72, 19, 239, 71, 19, 239, 70, - 19, 239, 69, 19, 239, 68, 19, 239, 67, 19, 239, 66, 19, 239, 65, 19, 239, - 64, 41, 2, 27, 246, 238, 41, 2, 27, 246, 237, 41, 2, 27, 246, 236, 41, 2, - 27, 246, 235, 41, 2, 27, 246, 234, 41, 2, 27, 246, 233, 41, 2, 27, 246, - 232, 41, 2, 27, 246, 231, 41, 2, 27, 246, 230, 41, 2, 27, 246, 229, 41, - 2, 27, 246, 228, 41, 2, 27, 246, 227, 41, 2, 27, 246, 226, 41, 2, 27, - 246, 225, 41, 2, 27, 246, 224, 41, 2, 27, 246, 223, 41, 2, 27, 246, 222, - 41, 2, 27, 246, 221, 41, 2, 27, 246, 220, 41, 2, 27, 246, 219, 41, 2, 27, - 246, 218, 41, 2, 27, 246, 217, 41, 2, 27, 246, 216, 41, 2, 27, 246, 215, - 41, 2, 27, 246, 214, 41, 2, 27, 246, 213, 41, 2, 27, 246, 212, 41, 2, 27, - 246, 211, 41, 2, 27, 246, 210, 41, 2, 27, 246, 209, 41, 2, 27, 246, 208, - 41, 2, 27, 246, 207, 41, 2, 27, 246, 206, 41, 2, 27, 246, 205, 41, 2, 27, - 246, 204, 41, 2, 27, 246, 203, 41, 2, 27, 246, 202, 41, 2, 27, 246, 201, - 41, 2, 27, 246, 200, 41, 2, 27, 246, 199, 41, 2, 27, 246, 198, 41, 2, 27, - 246, 197, 41, 2, 27, 246, 196, 41, 2, 27, 246, 195, 41, 2, 27, 246, 194, - 41, 2, 27, 246, 193, 41, 2, 27, 246, 192, 41, 2, 27, 246, 191, 41, 2, 27, - 246, 190, 41, 2, 27, 246, 189, 41, 2, 27, 246, 188, 41, 2, 27, 246, 187, - 41, 2, 27, 246, 186, 41, 2, 27, 246, 185, 41, 2, 27, 246, 184, 41, 2, 27, - 246, 183, 41, 2, 27, 246, 182, 41, 2, 27, 246, 181, 41, 2, 27, 246, 180, - 41, 2, 27, 246, 179, 41, 2, 27, 246, 178, 41, 2, 27, 246, 177, 41, 2, 27, - 246, 176, 41, 2, 27, 246, 175, 41, 2, 27, 246, 174, 41, 2, 27, 246, 173, - 41, 2, 27, 246, 172, 41, 2, 27, 246, 171, 41, 2, 27, 246, 170, 41, 2, 27, - 246, 169, 41, 2, 27, 246, 168, 41, 2, 27, 246, 167, 41, 2, 27, 246, 166, - 41, 2, 27, 246, 165, 41, 2, 27, 246, 164, 41, 2, 27, 246, 163, 41, 2, 27, - 246, 162, 41, 2, 27, 246, 161, 41, 2, 27, 246, 160, 41, 2, 27, 246, 159, - 41, 2, 27, 246, 158, 41, 2, 27, 246, 157, 41, 2, 27, 246, 156, 41, 2, 27, - 246, 155, 41, 2, 27, 246, 154, 41, 2, 27, 246, 153, 41, 2, 27, 246, 152, - 41, 2, 27, 246, 151, 41, 2, 27, 246, 150, 41, 2, 27, 246, 149, 41, 2, 27, - 246, 148, 41, 2, 27, 246, 147, 41, 2, 27, 246, 146, 41, 2, 27, 246, 145, - 41, 2, 27, 246, 144, 41, 2, 27, 246, 143, 41, 2, 27, 246, 142, 41, 2, 27, - 246, 141, 41, 2, 27, 246, 140, 41, 2, 27, 246, 139, 41, 2, 27, 246, 138, - 41, 2, 27, 246, 137, 41, 2, 27, 246, 136, 41, 2, 27, 246, 135, 41, 2, 27, - 246, 134, 41, 2, 27, 246, 133, 41, 2, 27, 246, 132, 41, 2, 27, 246, 131, - 41, 2, 27, 246, 130, 41, 2, 27, 246, 129, 41, 2, 27, 246, 128, 41, 2, 27, - 246, 127, 41, 2, 27, 246, 126, 41, 2, 27, 246, 125, 41, 2, 27, 246, 124, - 41, 2, 27, 246, 123, 41, 2, 27, 246, 122, 41, 2, 27, 246, 121, 41, 2, 27, - 246, 120, 41, 2, 27, 246, 119, 41, 2, 27, 246, 118, 41, 2, 27, 246, 117, - 41, 2, 27, 246, 116, 41, 2, 27, 246, 115, 41, 2, 27, 246, 114, 41, 2, 27, - 246, 113, 41, 2, 27, 246, 112, 41, 2, 27, 246, 111, 41, 2, 27, 246, 110, - 41, 2, 27, 246, 109, 41, 2, 27, 246, 108, 41, 2, 27, 246, 107, 41, 2, 27, - 246, 106, 41, 2, 27, 246, 105, 41, 2, 27, 246, 104, 41, 2, 27, 246, 103, - 41, 2, 27, 246, 102, 41, 2, 27, 246, 101, 41, 2, 27, 246, 100, 41, 2, 27, - 246, 99, 41, 2, 27, 246, 98, 41, 2, 27, 246, 97, 41, 2, 27, 246, 96, 41, - 2, 27, 246, 95, 41, 2, 27, 246, 94, 41, 2, 27, 246, 93, 41, 2, 27, 246, - 92, 41, 2, 27, 246, 91, 41, 2, 27, 246, 90, 41, 2, 27, 246, 89, 41, 2, - 27, 246, 88, 41, 2, 27, 246, 87, 41, 2, 27, 246, 86, 41, 2, 27, 246, 85, - 41, 2, 27, 246, 84, 41, 2, 27, 246, 83, 41, 2, 27, 246, 82, 41, 2, 27, - 246, 81, 41, 2, 27, 246, 80, 41, 2, 27, 246, 79, 41, 2, 27, 246, 78, 41, - 2, 27, 246, 77, 41, 2, 27, 246, 76, 41, 2, 27, 246, 75, 41, 2, 27, 246, - 74, 41, 2, 27, 246, 73, 41, 2, 27, 246, 72, 41, 2, 27, 246, 71, 41, 2, - 27, 246, 70, 41, 2, 27, 246, 69, 41, 2, 27, 246, 68, 41, 2, 27, 246, 67, - 41, 2, 27, 246, 66, 41, 2, 27, 246, 65, 41, 2, 27, 246, 64, 41, 2, 27, - 246, 63, 41, 2, 27, 246, 62, 41, 2, 27, 246, 61, 41, 2, 27, 246, 60, 41, - 2, 27, 246, 59, 41, 2, 27, 246, 58, 41, 2, 27, 246, 57, 41, 2, 27, 246, - 56, 41, 2, 27, 246, 55, 41, 2, 27, 246, 54, 41, 2, 27, 246, 53, 41, 2, - 27, 246, 52, 41, 2, 27, 246, 51, 41, 2, 27, 246, 50, 41, 2, 27, 246, 49, - 41, 2, 27, 246, 48, 41, 2, 27, 246, 47, 41, 2, 27, 246, 46, 41, 2, 27, - 246, 45, 41, 2, 27, 246, 44, 41, 2, 27, 246, 43, 41, 2, 27, 246, 42, 41, - 2, 27, 246, 41, 41, 2, 27, 246, 40, 41, 2, 27, 246, 39, 41, 2, 27, 246, - 38, 41, 2, 27, 246, 37, 41, 2, 27, 246, 36, 41, 2, 27, 246, 35, 41, 2, - 27, 246, 34, 41, 2, 27, 246, 33, 41, 2, 27, 246, 32, 41, 2, 27, 246, 31, - 41, 2, 27, 246, 30, 41, 2, 27, 246, 29, 41, 2, 27, 246, 28, 41, 2, 27, - 246, 27, 41, 2, 27, 246, 26, 41, 2, 27, 246, 25, 41, 2, 27, 246, 24, 41, - 2, 27, 246, 23, 41, 2, 27, 246, 22, 41, 2, 27, 246, 21, 41, 2, 27, 246, - 20, 41, 2, 27, 246, 19, 41, 2, 27, 246, 18, 41, 2, 27, 246, 17, 41, 2, - 27, 246, 16, 41, 2, 27, 246, 15, 41, 2, 27, 246, 14, 41, 2, 27, 246, 13, - 41, 2, 27, 246, 12, 41, 2, 27, 246, 11, 41, 2, 27, 246, 10, 41, 2, 27, - 246, 9, 41, 2, 27, 246, 8, 41, 2, 27, 246, 7, 41, 2, 27, 246, 6, 41, 2, - 27, 246, 5, 41, 2, 27, 246, 4, 41, 2, 27, 246, 3, 41, 2, 27, 246, 2, 41, - 2, 27, 246, 1, 41, 2, 27, 246, 0, 41, 2, 27, 245, 255, 41, 2, 27, 245, - 254, 41, 2, 27, 245, 253, 41, 2, 27, 245, 252, 41, 2, 27, 245, 251, 41, - 2, 27, 245, 250, 41, 2, 27, 245, 249, 41, 2, 27, 245, 248, 41, 2, 27, - 245, 247, 41, 2, 27, 245, 246, 41, 2, 27, 245, 245, 41, 2, 27, 245, 244, - 41, 2, 27, 245, 243, 41, 2, 27, 245, 242, 41, 2, 27, 245, 241, 41, 2, 27, - 245, 240, 41, 2, 27, 245, 239, 41, 2, 27, 245, 238, 41, 2, 27, 245, 237, - 41, 2, 27, 245, 236, 41, 2, 27, 245, 235, 41, 2, 27, 245, 234, 41, 2, 27, - 245, 233, 41, 2, 27, 245, 232, 41, 2, 27, 245, 231, 41, 2, 27, 245, 230, - 41, 2, 27, 245, 229, 41, 2, 27, 245, 228, 41, 2, 27, 245, 227, 41, 2, 27, - 245, 226, 41, 2, 27, 245, 225, 41, 2, 27, 245, 224, 41, 2, 27, 245, 223, - 41, 2, 27, 245, 222, 41, 2, 27, 245, 221, 41, 2, 27, 245, 220, 41, 2, 27, - 245, 219, 41, 2, 27, 245, 218, 41, 2, 27, 245, 217, 41, 2, 27, 245, 216, - 41, 2, 27, 245, 215, 41, 2, 27, 245, 214, 41, 2, 27, 245, 213, 41, 2, 27, - 245, 212, 41, 2, 27, 245, 211, 41, 2, 27, 245, 210, 41, 2, 27, 245, 209, - 41, 2, 27, 245, 208, 41, 2, 27, 245, 207, 41, 2, 27, 245, 206, 41, 2, 27, - 245, 205, 41, 2, 27, 245, 204, 41, 2, 27, 245, 203, 41, 2, 27, 245, 202, - 41, 2, 27, 245, 201, 41, 2, 27, 245, 200, 41, 2, 27, 245, 199, 41, 2, 27, - 245, 198, 41, 2, 27, 245, 197, 41, 2, 27, 245, 196, 41, 2, 27, 245, 195, - 41, 2, 27, 245, 194, 41, 2, 27, 245, 193, 41, 2, 27, 245, 192, 41, 2, 27, - 245, 191, 41, 2, 27, 245, 190, 41, 2, 27, 245, 189, 41, 2, 27, 245, 188, - 41, 2, 27, 245, 187, 41, 2, 27, 245, 186, 41, 2, 27, 245, 185, 41, 2, 27, - 245, 184, 41, 2, 27, 245, 183, 41, 2, 27, 245, 182, 41, 2, 27, 245, 181, - 41, 2, 27, 245, 180, 41, 2, 27, 245, 179, 41, 2, 27, 245, 178, 41, 2, 27, - 245, 177, 41, 2, 27, 245, 176, 41, 2, 27, 245, 175, 41, 2, 27, 245, 174, - 41, 2, 27, 245, 173, 41, 2, 27, 245, 172, 41, 2, 27, 245, 171, 41, 2, 27, - 245, 170, 41, 2, 27, 245, 169, 41, 2, 27, 245, 168, 41, 2, 27, 245, 167, - 41, 2, 27, 245, 166, 41, 2, 27, 245, 165, 41, 2, 27, 245, 164, 41, 2, 27, - 245, 163, 41, 2, 27, 245, 162, 41, 2, 27, 245, 161, 41, 2, 27, 245, 160, - 41, 2, 27, 245, 159, 41, 2, 27, 245, 158, 41, 2, 27, 245, 157, 41, 2, 27, - 245, 156, 41, 2, 27, 245, 155, 41, 2, 27, 245, 154, 41, 2, 27, 245, 153, - 41, 2, 27, 245, 152, 41, 2, 27, 245, 151, 41, 2, 27, 245, 150, 41, 2, 27, - 245, 149, 41, 2, 27, 245, 148, 41, 2, 27, 245, 147, 41, 2, 27, 245, 146, - 41, 2, 27, 245, 145, 41, 2, 27, 245, 144, 41, 2, 27, 245, 143, 41, 2, 27, - 245, 142, 41, 2, 27, 245, 141, 41, 2, 27, 245, 140, 41, 2, 27, 245, 139, - 41, 2, 27, 245, 138, 41, 2, 27, 245, 137, 41, 2, 27, 245, 136, 41, 2, 27, - 245, 135, 41, 2, 27, 245, 134, 41, 2, 27, 245, 133, 41, 2, 27, 245, 132, - 41, 2, 27, 245, 131, 41, 2, 27, 245, 130, 41, 2, 27, 245, 129, 41, 2, 27, - 245, 128, 41, 2, 27, 245, 127, 41, 2, 27, 245, 126, 41, 2, 27, 245, 125, - 41, 2, 27, 245, 124, 41, 2, 27, 245, 123, 41, 2, 27, 245, 122, 41, 2, 27, - 245, 121, 41, 2, 27, 245, 120, 41, 2, 27, 245, 119, 41, 2, 27, 245, 118, - 41, 2, 27, 245, 117, 41, 2, 27, 245, 116, 41, 2, 27, 245, 115, 41, 2, 27, - 245, 114, 41, 2, 27, 245, 113, 41, 2, 27, 245, 112, 41, 2, 27, 245, 111, - 41, 2, 27, 245, 110, 41, 2, 27, 245, 109, 41, 2, 27, 245, 108, 41, 2, 27, - 245, 107, 41, 2, 27, 245, 106, 41, 2, 27, 245, 105, 41, 2, 27, 245, 104, - 41, 2, 27, 245, 103, 41, 2, 27, 245, 102, 41, 2, 27, 245, 101, 41, 2, 27, - 245, 100, 41, 2, 27, 245, 99, 41, 2, 27, 245, 98, 41, 2, 27, 245, 97, 41, - 2, 27, 245, 96, 41, 2, 27, 245, 95, 41, 2, 27, 245, 94, 41, 2, 27, 245, - 93, 41, 2, 27, 245, 92, 41, 2, 27, 245, 91, 41, 2, 27, 245, 90, 41, 2, - 27, 245, 89, 41, 2, 27, 245, 88, 41, 2, 27, 245, 87, 41, 2, 27, 245, 86, - 41, 2, 27, 245, 85, 41, 2, 27, 245, 84, 41, 2, 27, 245, 83, 41, 2, 27, - 245, 82, 41, 2, 27, 245, 81, 41, 2, 27, 245, 80, 41, 2, 27, 245, 79, 41, - 2, 27, 245, 78, 41, 2, 27, 245, 77, 41, 2, 27, 245, 76, 41, 2, 27, 245, - 75, 41, 2, 27, 245, 74, 41, 2, 27, 245, 73, 41, 2, 27, 245, 72, 41, 2, - 27, 245, 71, 41, 2, 27, 245, 70, 41, 2, 27, 245, 69, 41, 2, 27, 245, 68, - 41, 2, 27, 245, 67, 41, 2, 27, 245, 66, 41, 2, 27, 245, 65, 41, 2, 27, - 245, 64, 41, 2, 27, 245, 63, 41, 2, 27, 245, 62, 41, 2, 27, 245, 61, 41, - 2, 27, 245, 60, 41, 2, 27, 245, 59, 41, 2, 27, 245, 58, 41, 2, 27, 245, - 57, 41, 2, 27, 245, 56, 41, 2, 27, 245, 55, 41, 2, 27, 245, 54, 41, 2, - 27, 245, 53, 41, 2, 27, 245, 52, 41, 2, 27, 245, 51, 41, 2, 27, 245, 50, - 41, 2, 27, 245, 49, 41, 2, 27, 245, 48, 41, 2, 27, 245, 47, 41, 2, 27, - 245, 46, 41, 2, 27, 245, 45, 41, 2, 27, 245, 44, 41, 2, 27, 245, 43, 41, - 2, 27, 245, 42, 41, 2, 27, 245, 41, 41, 2, 27, 245, 40, 41, 2, 27, 245, - 39, 41, 2, 27, 245, 38, 41, 2, 27, 245, 37, 41, 2, 27, 245, 36, 41, 2, - 27, 245, 35, 41, 2, 27, 245, 34, 41, 2, 27, 245, 33, 41, 2, 27, 245, 32, - 41, 2, 27, 245, 31, 41, 2, 27, 245, 30, 41, 2, 27, 245, 29, 41, 2, 27, - 245, 28, 41, 2, 27, 245, 27, 41, 2, 27, 245, 26, 41, 2, 27, 245, 25, 72, - 1, 216, 36, 198, 77, 72, 1, 216, 36, 198, 76, 72, 1, 216, 36, 198, 75, - 72, 1, 216, 36, 198, 74, 72, 1, 216, 36, 198, 72, 72, 1, 216, 36, 198, - 71, 72, 1, 216, 36, 214, 211, 198, 78, 72, 1, 216, 36, 214, 211, 198, 77, - 72, 1, 216, 36, 214, 211, 198, 76, 72, 1, 216, 36, 214, 211, 198, 75, 72, - 1, 216, 36, 214, 211, 198, 74, 72, 1, 216, 36, 214, 211, 198, 72, 72, 1, - 216, 36, 214, 211, 198, 71, 72, 1, 251, 14, 71, 229, 120, 1, 251, 14, - 192, 80, 61, 1, 255, 206, 61, 1, 255, 205, 61, 1, 255, 204, 61, 1, 255, - 200, 61, 1, 228, 73, 61, 1, 228, 72, 61, 1, 228, 71, 61, 1, 228, 70, 61, - 1, 196, 231, 61, 1, 196, 230, 61, 1, 196, 229, 61, 1, 196, 228, 61, 1, - 196, 227, 61, 1, 235, 13, 61, 1, 235, 12, 61, 1, 235, 11, 61, 1, 235, 10, - 61, 1, 235, 9, 61, 1, 212, 14, 61, 1, 212, 13, 61, 1, 212, 12, 61, 1, - 222, 141, 61, 1, 222, 138, 61, 1, 222, 137, 61, 1, 222, 136, 61, 1, 222, - 135, 61, 1, 222, 134, 61, 1, 222, 133, 61, 1, 222, 132, 61, 1, 222, 131, - 61, 1, 222, 140, 61, 1, 222, 139, 61, 1, 222, 130, 61, 1, 221, 165, 61, - 1, 221, 164, 61, 1, 221, 163, 61, 1, 221, 162, 61, 1, 221, 161, 61, 1, - 221, 160, 61, 1, 221, 159, 61, 1, 221, 158, 61, 1, 220, 231, 61, 1, 220, - 230, 61, 1, 220, 229, 61, 1, 220, 228, 61, 1, 220, 227, 61, 1, 220, 226, - 61, 1, 220, 225, 61, 1, 222, 21, 61, 1, 222, 20, 61, 1, 222, 19, 61, 1, - 222, 18, 61, 1, 222, 17, 61, 1, 222, 16, 61, 1, 221, 66, 61, 1, 221, 65, - 61, 1, 221, 64, 61, 1, 221, 63, 61, 1, 205, 206, 61, 1, 205, 205, 61, 1, - 205, 204, 61, 1, 205, 203, 61, 1, 205, 202, 61, 1, 205, 201, 61, 1, 205, - 200, 61, 1, 205, 199, 61, 1, 202, 221, 61, 1, 202, 220, 61, 1, 202, 219, - 61, 1, 202, 218, 61, 1, 202, 217, 61, 1, 202, 216, 61, 1, 201, 3, 61, 1, - 201, 2, 61, 1, 201, 1, 61, 1, 201, 0, 61, 1, 200, 255, 61, 1, 200, 254, - 61, 1, 200, 253, 61, 1, 200, 252, 61, 1, 205, 67, 61, 1, 205, 66, 61, 1, - 205, 65, 61, 1, 205, 64, 61, 1, 205, 63, 61, 1, 202, 45, 61, 1, 202, 44, - 61, 1, 202, 43, 61, 1, 202, 42, 61, 1, 202, 41, 61, 1, 202, 40, 61, 1, - 202, 39, 61, 1, 199, 251, 61, 1, 199, 250, 61, 1, 199, 249, 61, 1, 199, - 248, 61, 1, 198, 192, 61, 1, 198, 191, 61, 1, 198, 190, 61, 1, 198, 189, - 61, 1, 198, 188, 61, 1, 198, 187, 61, 1, 198, 186, 61, 1, 197, 93, 61, 1, - 197, 92, 61, 1, 197, 91, 61, 1, 197, 90, 61, 1, 197, 89, 61, 1, 199, 144, - 61, 1, 199, 143, 61, 1, 199, 142, 61, 1, 199, 141, 61, 1, 199, 140, 61, - 1, 199, 139, 61, 1, 199, 138, 61, 1, 199, 137, 61, 1, 199, 136, 61, 1, - 198, 98, 61, 1, 198, 97, 61, 1, 198, 96, 61, 1, 198, 95, 61, 1, 198, 94, - 61, 1, 198, 93, 61, 1, 198, 92, 61, 1, 215, 6, 61, 1, 215, 5, 61, 1, 215, - 4, 61, 1, 215, 3, 61, 1, 215, 2, 61, 1, 215, 1, 61, 1, 215, 0, 61, 1, - 214, 255, 61, 1, 214, 254, 61, 1, 213, 218, 61, 1, 213, 217, 61, 1, 213, - 216, 61, 1, 213, 215, 61, 1, 213, 214, 61, 1, 213, 213, 61, 1, 213, 212, - 61, 1, 213, 211, 61, 1, 212, 177, 61, 1, 212, 176, 61, 1, 212, 175, 61, - 1, 214, 120, 61, 1, 214, 119, 61, 1, 214, 118, 61, 1, 214, 117, 61, 1, - 214, 116, 61, 1, 214, 115, 61, 1, 214, 114, 61, 1, 213, 42, 61, 1, 213, - 41, 61, 1, 213, 40, 61, 1, 213, 39, 61, 1, 213, 38, 61, 1, 230, 104, 61, - 1, 230, 101, 61, 1, 230, 100, 61, 1, 230, 99, 61, 1, 230, 98, 61, 1, 230, - 97, 61, 1, 230, 96, 61, 1, 230, 95, 61, 1, 230, 94, 61, 1, 230, 103, 61, - 1, 230, 102, 61, 1, 229, 157, 61, 1, 229, 156, 61, 1, 229, 155, 61, 1, - 229, 154, 61, 1, 229, 153, 61, 1, 229, 152, 61, 1, 229, 151, 61, 1, 228, - 158, 61, 1, 228, 157, 61, 1, 228, 156, 61, 1, 229, 244, 61, 1, 229, 243, - 61, 1, 229, 242, 61, 1, 229, 241, 61, 1, 229, 240, 61, 1, 229, 239, 61, - 1, 229, 238, 61, 1, 229, 22, 61, 1, 229, 21, 61, 1, 229, 20, 61, 1, 229, - 19, 61, 1, 229, 18, 61, 1, 229, 17, 61, 1, 229, 16, 61, 1, 229, 15, 61, - 1, 217, 159, 61, 1, 217, 158, 61, 1, 217, 157, 61, 1, 217, 156, 61, 1, - 217, 155, 61, 1, 217, 154, 61, 1, 217, 153, 61, 1, 216, 99, 61, 1, 216, - 98, 61, 1, 216, 97, 61, 1, 216, 96, 61, 1, 216, 95, 61, 1, 216, 94, 61, - 1, 216, 93, 61, 1, 215, 154, 61, 1, 215, 153, 61, 1, 215, 152, 61, 1, - 215, 151, 61, 1, 216, 231, 61, 1, 216, 230, 61, 1, 216, 229, 61, 1, 216, - 11, 61, 1, 216, 10, 61, 1, 216, 9, 61, 1, 216, 8, 61, 1, 216, 7, 61, 1, - 216, 6, 61, 1, 192, 148, 61, 1, 192, 147, 61, 1, 192, 146, 61, 1, 192, - 145, 61, 1, 192, 144, 61, 1, 192, 141, 61, 1, 191, 224, 61, 1, 191, 223, - 61, 1, 191, 222, 61, 1, 191, 221, 61, 1, 192, 11, 61, 1, 192, 10, 61, 1, - 192, 9, 61, 1, 192, 8, 61, 1, 192, 7, 61, 1, 192, 6, 61, 1, 207, 185, 61, - 1, 207, 184, 61, 1, 207, 183, 61, 1, 207, 182, 61, 1, 207, 0, 61, 1, 206, - 255, 61, 1, 206, 254, 61, 1, 206, 253, 61, 1, 206, 252, 61, 1, 206, 251, - 61, 1, 206, 250, 61, 1, 206, 67, 61, 1, 206, 66, 61, 1, 206, 65, 61, 1, - 206, 64, 61, 1, 206, 63, 61, 1, 206, 62, 61, 1, 207, 112, 61, 1, 207, - 111, 61, 1, 207, 110, 61, 1, 207, 109, 61, 1, 206, 161, 61, 1, 206, 160, - 61, 1, 206, 159, 61, 1, 206, 158, 61, 1, 206, 157, 61, 1, 206, 156, 61, - 1, 193, 189, 61, 1, 193, 188, 61, 1, 193, 187, 61, 1, 193, 186, 61, 1, - 193, 185, 61, 1, 193, 85, 61, 1, 193, 84, 61, 1, 193, 83, 61, 1, 193, 82, - 61, 1, 193, 81, 61, 1, 193, 124, 61, 1, 193, 123, 61, 1, 193, 122, 61, 1, - 193, 121, 61, 1, 193, 47, 61, 1, 193, 46, 61, 1, 193, 45, 61, 1, 193, 44, - 61, 1, 193, 43, 61, 1, 193, 42, 61, 1, 193, 41, 61, 1, 215, 58, 61, 1, - 215, 57, 229, 120, 1, 251, 14, 193, 0, 72, 1, 251, 14, 192, 33, 72, 1, - 251, 14, 192, 80, 72, 1, 251, 14, 193, 0, 229, 120, 1, 2, 221, 67, 229, - 120, 1, 2, 193, 86, 229, 120, 1, 2, 193, 125, 229, 120, 1, 2, 193, 48, - 72, 1, 2, 221, 67, 72, 1, 2, 193, 86, 72, 1, 2, 193, 125, 72, 1, 2, 193, - 48, 72, 1, 2, 215, 61, 46, 245, 24, 46, 245, 23, 46, 245, 22, 46, 245, - 21, 46, 245, 20, 46, 245, 19, 46, 245, 18, 46, 245, 17, 46, 245, 16, 46, - 245, 15, 46, 245, 14, 46, 245, 13, 46, 245, 12, 46, 245, 11, 46, 245, 10, - 46, 245, 9, 46, 245, 8, 46, 245, 7, 46, 245, 6, 46, 245, 5, 46, 245, 4, - 46, 245, 3, 46, 245, 2, 46, 245, 1, 46, 245, 0, 46, 244, 255, 46, 244, - 254, 46, 244, 253, 46, 244, 252, 46, 244, 251, 46, 244, 250, 46, 244, - 249, 46, 244, 248, 46, 244, 247, 46, 244, 246, 46, 244, 245, 46, 244, - 244, 46, 244, 243, 46, 244, 242, 46, 244, 241, 46, 244, 240, 46, 244, - 239, 46, 244, 238, 46, 244, 237, 46, 244, 236, 46, 244, 235, 46, 244, - 234, 46, 244, 233, 46, 244, 232, 46, 244, 231, 46, 244, 230, 46, 244, - 229, 46, 244, 228, 46, 244, 227, 46, 244, 226, 46, 244, 225, 46, 244, - 224, 46, 244, 223, 46, 244, 222, 46, 244, 221, 46, 244, 220, 46, 244, - 219, 46, 244, 218, 46, 244, 217, 46, 244, 216, 46, 244, 215, 46, 244, - 214, 46, 244, 213, 46, 244, 212, 46, 244, 211, 46, 244, 210, 46, 244, - 209, 46, 244, 208, 46, 244, 207, 46, 244, 206, 46, 244, 205, 46, 244, - 204, 46, 244, 203, 46, 244, 202, 46, 244, 201, 46, 244, 200, 46, 244, - 199, 46, 244, 198, 46, 244, 197, 46, 244, 196, 46, 244, 195, 46, 244, - 194, 46, 244, 193, 46, 244, 192, 46, 244, 191, 46, 244, 190, 46, 244, - 189, 46, 244, 188, 46, 244, 187, 46, 244, 186, 46, 244, 185, 46, 244, - 184, 46, 244, 183, 46, 244, 182, 46, 244, 181, 46, 244, 180, 46, 244, - 179, 46, 244, 178, 46, 244, 177, 46, 244, 176, 46, 244, 175, 46, 244, - 174, 46, 244, 173, 46, 244, 172, 46, 244, 171, 46, 244, 170, 46, 244, - 169, 46, 244, 168, 46, 244, 167, 46, 244, 166, 46, 244, 165, 46, 244, - 164, 46, 244, 163, 46, 244, 162, 46, 244, 161, 46, 244, 160, 46, 244, - 159, 46, 244, 158, 46, 244, 157, 46, 244, 156, 46, 244, 155, 46, 244, - 154, 46, 244, 153, 46, 244, 152, 46, 244, 151, 46, 244, 150, 46, 244, - 149, 46, 244, 148, 46, 244, 147, 46, 244, 146, 46, 244, 145, 46, 244, - 144, 46, 244, 143, 46, 244, 142, 46, 244, 141, 46, 244, 140, 46, 244, - 139, 46, 244, 138, 46, 244, 137, 46, 244, 136, 46, 244, 135, 46, 244, - 134, 46, 244, 133, 46, 244, 132, 46, 244, 131, 46, 244, 130, 46, 244, - 129, 46, 244, 128, 46, 244, 127, 46, 244, 126, 46, 244, 125, 46, 244, - 124, 46, 244, 123, 46, 244, 122, 46, 244, 121, 46, 244, 120, 46, 244, - 119, 46, 244, 118, 46, 244, 117, 46, 244, 116, 46, 244, 115, 46, 244, - 114, 46, 244, 113, 46, 244, 112, 46, 244, 111, 46, 244, 110, 46, 244, - 109, 46, 244, 108, 46, 244, 107, 46, 244, 106, 46, 244, 105, 46, 244, - 104, 46, 244, 103, 46, 244, 102, 46, 244, 101, 46, 244, 100, 46, 244, 99, - 46, 244, 98, 46, 244, 97, 46, 244, 96, 46, 244, 95, 46, 244, 94, 46, 244, - 93, 46, 244, 92, 46, 244, 91, 46, 244, 90, 46, 244, 89, 46, 244, 88, 46, - 244, 87, 46, 244, 86, 46, 244, 85, 46, 244, 84, 46, 244, 83, 46, 244, 82, - 46, 244, 81, 46, 244, 80, 46, 244, 79, 46, 244, 78, 46, 244, 77, 46, 244, - 76, 46, 244, 75, 46, 244, 74, 46, 244, 73, 46, 244, 72, 46, 244, 71, 46, - 244, 70, 46, 244, 69, 46, 244, 68, 46, 244, 67, 46, 244, 66, 46, 244, 65, - 46, 244, 64, 46, 244, 63, 46, 244, 62, 46, 244, 61, 46, 244, 60, 46, 244, - 59, 46, 244, 58, 46, 244, 57, 46, 244, 56, 46, 244, 55, 46, 244, 54, 46, - 244, 53, 46, 244, 52, 46, 244, 51, 46, 244, 50, 46, 244, 49, 46, 244, 48, - 46, 244, 47, 46, 244, 46, 46, 244, 45, 46, 244, 44, 46, 244, 43, 46, 244, - 42, 46, 244, 41, 46, 244, 40, 46, 244, 39, 46, 244, 38, 46, 244, 37, 46, - 244, 36, 46, 244, 35, 46, 244, 34, 46, 244, 33, 46, 244, 32, 46, 244, 31, - 46, 244, 30, 46, 244, 29, 46, 244, 28, 46, 244, 27, 46, 244, 26, 46, 244, - 25, 46, 244, 24, 46, 244, 23, 46, 244, 22, 46, 244, 21, 46, 244, 20, 46, - 244, 19, 46, 244, 18, 46, 244, 17, 46, 244, 16, 46, 244, 15, 46, 244, 14, - 46, 244, 13, 46, 244, 12, 46, 244, 11, 46, 244, 10, 46, 244, 9, 46, 244, - 8, 46, 244, 7, 46, 244, 6, 46, 244, 5, 46, 244, 4, 46, 244, 3, 46, 244, - 2, 46, 244, 1, 46, 244, 0, 46, 243, 255, 46, 243, 254, 46, 243, 253, 46, - 243, 252, 46, 243, 251, 46, 243, 250, 46, 243, 249, 46, 243, 248, 46, - 243, 247, 46, 243, 246, 46, 243, 245, 46, 243, 244, 46, 243, 243, 46, - 243, 242, 46, 243, 241, 46, 243, 240, 46, 243, 239, 46, 243, 238, 46, - 243, 237, 46, 243, 236, 46, 243, 235, 46, 243, 234, 46, 243, 233, 46, - 243, 232, 46, 243, 231, 46, 243, 230, 46, 243, 229, 46, 243, 228, 46, - 243, 227, 46, 243, 226, 46, 243, 225, 46, 243, 224, 46, 243, 223, 46, - 243, 222, 46, 243, 221, 46, 243, 220, 46, 243, 219, 46, 243, 218, 46, - 243, 217, 46, 243, 216, 46, 243, 215, 46, 243, 214, 46, 243, 213, 46, - 243, 212, 46, 243, 211, 46, 243, 210, 46, 243, 209, 46, 243, 208, 46, - 243, 207, 46, 243, 206, 46, 243, 205, 46, 243, 204, 46, 243, 203, 46, - 243, 202, 46, 243, 201, 46, 243, 200, 46, 243, 199, 46, 243, 198, 46, - 243, 197, 46, 243, 196, 46, 243, 195, 46, 243, 194, 46, 243, 193, 46, - 243, 192, 46, 243, 191, 46, 243, 190, 46, 243, 189, 46, 243, 188, 46, - 243, 187, 46, 243, 186, 46, 243, 185, 46, 243, 184, 46, 243, 183, 46, - 243, 182, 46, 243, 181, 46, 243, 180, 46, 243, 179, 46, 243, 178, 46, - 243, 177, 46, 243, 176, 46, 243, 175, 46, 243, 174, 46, 243, 173, 46, - 243, 172, 46, 243, 171, 46, 243, 170, 46, 243, 169, 46, 243, 168, 46, - 243, 167, 46, 243, 166, 46, 243, 165, 46, 243, 164, 46, 243, 163, 46, - 243, 162, 46, 243, 161, 46, 243, 160, 46, 243, 159, 46, 243, 158, 46, - 243, 157, 46, 243, 156, 46, 243, 155, 46, 243, 154, 46, 243, 153, 46, - 243, 152, 46, 243, 151, 46, 243, 150, 46, 243, 149, 46, 243, 148, 46, - 243, 147, 46, 243, 146, 46, 243, 145, 46, 243, 144, 46, 243, 143, 46, - 243, 142, 46, 243, 141, 124, 1, 230, 116, 124, 1, 192, 235, 124, 1, 210, - 236, 124, 1, 200, 43, 124, 1, 233, 175, 124, 1, 222, 152, 124, 1, 172, - 124, 1, 250, 120, 124, 1, 238, 127, 124, 1, 196, 12, 124, 1, 232, 51, - 124, 1, 146, 124, 1, 210, 237, 215, 61, 124, 1, 238, 128, 206, 8, 124, 1, - 233, 176, 215, 61, 124, 1, 222, 153, 218, 168, 124, 1, 207, 222, 206, 8, - 124, 1, 199, 51, 124, 1, 202, 82, 237, 69, 124, 1, 237, 69, 124, 1, 221, - 102, 124, 1, 202, 82, 223, 35, 124, 1, 229, 112, 124, 1, 219, 160, 124, - 1, 207, 7, 124, 1, 218, 168, 124, 1, 215, 61, 124, 1, 223, 35, 124, 1, - 206, 8, 124, 1, 218, 169, 215, 61, 124, 1, 215, 62, 218, 168, 124, 1, - 223, 36, 218, 168, 124, 1, 206, 9, 223, 35, 124, 1, 218, 169, 4, 236, - 140, 124, 1, 215, 62, 4, 236, 140, 124, 1, 223, 36, 4, 236, 140, 124, 1, - 223, 36, 4, 185, 223, 118, 23, 58, 124, 1, 206, 9, 4, 236, 140, 124, 1, - 206, 9, 4, 75, 60, 124, 1, 218, 169, 206, 8, 124, 1, 215, 62, 206, 8, - 124, 1, 223, 36, 206, 8, 124, 1, 206, 9, 206, 8, 124, 1, 218, 169, 215, - 62, 206, 8, 124, 1, 215, 62, 218, 169, 206, 8, 124, 1, 223, 36, 218, 169, - 206, 8, 124, 1, 206, 9, 223, 36, 206, 8, 124, 1, 223, 36, 206, 9, 4, 236, - 140, 124, 1, 223, 36, 215, 61, 124, 1, 223, 36, 215, 62, 206, 8, 124, 1, - 206, 9, 200, 43, 124, 1, 206, 9, 200, 44, 146, 124, 1, 206, 9, 210, 236, - 124, 1, 206, 9, 210, 237, 146, 124, 1, 200, 44, 206, 8, 124, 1, 200, 44, - 207, 222, 206, 8, 124, 1, 193, 224, 124, 1, 193, 97, 124, 1, 193, 225, - 146, 124, 1, 206, 9, 215, 61, 124, 1, 206, 9, 218, 168, 124, 1, 222, 153, - 207, 222, 206, 8, 124, 1, 232, 52, 207, 222, 206, 8, 124, 1, 206, 9, 222, - 152, 124, 1, 206, 9, 222, 153, 146, 124, 1, 65, 124, 1, 202, 82, 210, - 250, 124, 1, 211, 182, 124, 1, 74, 124, 1, 251, 66, 124, 1, 68, 124, 1, - 71, 124, 1, 223, 226, 124, 1, 203, 40, 68, 124, 1, 196, 139, 124, 1, 234, - 188, 124, 1, 202, 82, 234, 173, 124, 1, 206, 135, 68, 124, 1, 202, 82, - 234, 188, 124, 1, 179, 68, 124, 1, 192, 80, 124, 1, 66, 124, 1, 233, 242, - 124, 1, 192, 182, 124, 1, 126, 215, 61, 124, 1, 179, 66, 124, 1, 206, - 135, 66, 124, 1, 196, 141, 124, 1, 202, 82, 66, 124, 1, 211, 84, 124, 1, - 210, 250, 124, 1, 211, 19, 124, 1, 193, 190, 124, 1, 193, 48, 124, 1, - 193, 86, 124, 1, 193, 112, 124, 1, 193, 14, 124, 1, 214, 214, 66, 124, 1, - 214, 214, 74, 124, 1, 214, 214, 68, 124, 1, 214, 214, 65, 124, 1, 210, 0, - 251, 132, 124, 1, 210, 0, 251, 149, 124, 1, 202, 82, 234, 103, 124, 1, - 202, 82, 251, 132, 124, 1, 202, 82, 211, 104, 124, 1, 117, 218, 168, 124, - 252, 4, 45, 228, 241, 205, 58, 124, 252, 4, 216, 87, 228, 241, 205, 58, - 124, 252, 4, 50, 228, 241, 205, 58, 124, 252, 4, 130, 81, 205, 58, 124, - 252, 4, 216, 87, 81, 205, 58, 124, 252, 4, 137, 81, 205, 58, 124, 252, 4, - 250, 170, 205, 58, 124, 252, 4, 250, 170, 219, 215, 205, 58, 124, 252, 4, - 250, 170, 199, 188, 124, 252, 4, 250, 170, 199, 215, 124, 252, 4, 250, - 170, 235, 15, 102, 124, 252, 4, 250, 170, 228, 74, 102, 124, 252, 4, 250, - 170, 199, 189, 102, 124, 252, 4, 137, 252, 46, 124, 252, 4, 137, 198, - 172, 252, 46, 124, 252, 4, 137, 230, 210, 124, 252, 4, 137, 179, 230, - 210, 124, 252, 4, 137, 236, 140, 124, 252, 4, 137, 243, 10, 124, 252, 4, - 137, 219, 112, 124, 252, 4, 137, 193, 138, 124, 252, 4, 137, 195, 135, - 124, 252, 4, 130, 252, 46, 124, 252, 4, 130, 198, 172, 252, 46, 124, 252, - 4, 130, 230, 210, 124, 252, 4, 130, 179, 230, 210, 124, 252, 4, 130, 236, - 140, 124, 252, 4, 130, 243, 10, 124, 252, 4, 130, 219, 112, 124, 252, 4, - 130, 193, 138, 124, 252, 4, 130, 195, 135, 124, 252, 4, 130, 57, 124, 3, - 187, 4, 238, 217, 124, 199, 9, 1, 205, 34, 124, 55, 77, 124, 208, 152, - 243, 78, 232, 80, 201, 63, 203, 27, 232, 145, 1, 211, 2, 203, 27, 232, - 145, 239, 28, 211, 2, 203, 27, 232, 145, 144, 201, 78, 203, 27, 232, 145, - 133, 201, 78, 97, 33, 87, 230, 240, 213, 159, 206, 9, 220, 251, 211, 105, - 219, 224, 97, 33, 87, 213, 159, 206, 9, 220, 251, 211, 105, 219, 224, 97, - 33, 87, 197, 162, 211, 105, 219, 224, 97, 33, 87, 230, 240, 213, 159, - 211, 105, 219, 224, 97, 33, 87, 213, 159, 211, 105, 219, 224, 97, 33, 87, - 201, 179, 211, 105, 219, 224, 97, 33, 87, 217, 94, 209, 3, 211, 105, 219, - 224, 97, 33, 87, 209, 3, 211, 105, 219, 224, 97, 33, 87, 193, 231, 211, - 105, 219, 224, 97, 33, 87, 217, 94, 209, 3, 206, 9, 221, 181, 211, 105, - 219, 224, 97, 33, 87, 209, 3, 206, 9, 221, 181, 211, 105, 219, 224, 97, - 33, 87, 193, 231, 206, 9, 221, 181, 211, 105, 219, 224, 97, 33, 87, 230, - 240, 213, 159, 206, 9, 220, 251, 211, 105, 183, 97, 33, 87, 213, 159, - 206, 9, 220, 251, 211, 105, 183, 97, 33, 87, 197, 162, 211, 105, 183, 97, - 33, 87, 230, 240, 213, 159, 211, 105, 183, 97, 33, 87, 213, 159, 211, - 105, 183, 97, 33, 87, 201, 179, 211, 105, 183, 97, 33, 87, 217, 94, 209, - 3, 211, 105, 183, 97, 33, 87, 209, 3, 211, 105, 183, 97, 33, 87, 193, - 231, 211, 105, 183, 97, 33, 87, 217, 94, 209, 3, 206, 9, 221, 181, 211, - 105, 183, 97, 33, 87, 209, 3, 206, 9, 221, 181, 211, 105, 183, 97, 33, - 87, 193, 231, 206, 9, 221, 181, 211, 105, 183, 97, 33, 87, 197, 162, 206, - 9, 220, 250, 97, 33, 87, 217, 94, 209, 3, 206, 9, 220, 250, 97, 33, 87, - 201, 49, 217, 94, 209, 2, 97, 33, 87, 209, 3, 206, 9, 220, 250, 97, 33, - 87, 209, 3, 201, 48, 97, 33, 87, 193, 231, 206, 9, 220, 250, 97, 33, 87, - 217, 94, 209, 3, 201, 48, 97, 33, 87, 230, 240, 193, 230, 97, 33, 87, - 191, 83, 97, 33, 87, 211, 104, 97, 33, 87, 207, 124, 97, 33, 87, 198, - 157, 97, 33, 87, 248, 83, 97, 33, 87, 196, 156, 97, 33, 87, 209, 65, 97, - 33, 87, 219, 21, 97, 33, 87, 220, 200, 97, 33, 87, 222, 115, 97, 33, 87, - 191, 74, 97, 33, 87, 202, 105, 97, 33, 87, 207, 117, 97, 33, 87, 220, - 253, 211, 105, 219, 224, 97, 33, 198, 80, 207, 137, 87, 215, 162, 97, 33, - 198, 80, 207, 137, 87, 200, 153, 97, 33, 198, 80, 207, 137, 87, 197, 246, - 97, 33, 87, 191, 120, 97, 33, 87, 237, 105, 191, 120, 97, 33, 87, 211, - 25, 97, 33, 87, 209, 67, 97, 33, 87, 209, 68, 4, 81, 106, 97, 33, 87, - 243, 134, 97, 33, 87, 243, 135, 209, 45, 97, 33, 87, 211, 174, 97, 33, - 87, 202, 10, 212, 249, 97, 33, 87, 198, 89, 97, 33, 87, 235, 48, 97, 33, - 250, 169, 81, 211, 109, 97, 33, 87, 238, 163, 211, 109, 97, 33, 87, 220, - 252, 97, 33, 110, 198, 80, 207, 137, 223, 144, 97, 208, 203, 52, 219, - 167, 97, 208, 203, 52, 219, 166, 97, 208, 203, 52, 236, 233, 232, 195, - 97, 208, 203, 52, 220, 252, 97, 208, 203, 52, 206, 144, 97, 161, 221, 0, - 97, 161, 221, 1, 198, 156, 97, 161, 210, 122, 97, 161, 235, 56, 196, 13, - 243, 113, 97, 161, 221, 90, 97, 161, 191, 105, 97, 161, 201, 61, 97, 161, - 201, 62, 206, 9, 211, 163, 97, 161, 210, 10, 97, 161, 210, 11, 214, 96, - 97, 161, 201, 62, 4, 202, 10, 212, 249, 97, 161, 243, 112, 97, 161, 210, - 186, 97, 161, 191, 103, 97, 161, 230, 248, 248, 82, 97, 161, 230, 248, - 198, 156, 97, 161, 230, 248, 215, 160, 97, 161, 230, 248, 200, 152, 97, - 161, 230, 248, 197, 245, 97, 161, 194, 253, 208, 183, 97, 161, 194, 253, - 215, 163, 97, 161, 194, 253, 200, 154, 97, 161, 194, 253, 197, 247, 97, - 161, 194, 253, 221, 85, 208, 183, 97, 161, 194, 253, 221, 85, 215, 163, - 97, 161, 194, 253, 221, 85, 200, 154, 97, 161, 194, 253, 221, 85, 197, - 247, 97, 161, 55, 191, 103, 97, 161, 207, 18, 243, 112, 97, 161, 237, 91, - 97, 161, 221, 207, 97, 161, 243, 134, 97, 161, 209, 67, 97, 161, 202, - 113, 215, 163, 97, 161, 202, 113, 200, 154, 97, 161, 202, 113, 197, 247, - 97, 161, 202, 113, 198, 157, 97, 161, 237, 105, 221, 90, 97, 161, 202, - 113, 221, 85, 200, 154, 97, 161, 202, 113, 221, 89, 97, 161, 202, 113, - 221, 85, 198, 157, 97, 161, 202, 113, 235, 53, 208, 183, 97, 161, 202, - 113, 235, 53, 200, 154, 97, 161, 202, 113, 235, 53, 214, 96, 97, 161, - 202, 113, 235, 53, 221, 84, 97, 161, 202, 72, 97, 161, 202, 73, 206, 9, - 191, 101, 97, 161, 202, 73, 191, 110, 97, 161, 202, 73, 206, 9, 220, 250, - 97, 161, 220, 252, 97, 161, 206, 144, 97, 161, 232, 228, 97, 161, 221, - 59, 97, 161, 191, 8, 97, 161, 201, 90, 97, 161, 201, 91, 206, 9, 191, - 101, 97, 161, 201, 91, 206, 9, 220, 250, 97, 161, 201, 91, 206, 9, 191, - 102, 228, 74, 220, 250, 97, 161, 201, 91, 206, 9, 220, 251, 228, 74, 191, - 101, 97, 161, 201, 91, 191, 111, 97, 161, 201, 91, 191, 112, 206, 9, 191, - 101, 97, 161, 201, 91, 206, 9, 206, 143, 97, 161, 201, 91, 206, 9, 235, - 47, 191, 100, 97, 161, 201, 91, 206, 9, 191, 102, 228, 74, 209, 66, 97, - 161, 209, 47, 97, 161, 201, 91, 214, 96, 97, 161, 201, 40, 208, 183, 97, - 161, 201, 40, 215, 161, 97, 161, 201, 40, 220, 249, 97, 161, 201, 40, - 209, 43, 97, 161, 201, 40, 209, 5, 97, 161, 201, 40, 214, 96, 97, 161, - 201, 40, 221, 87, 97, 161, 201, 40, 221, 89, 97, 161, 201, 40, 198, 158, - 208, 130, 97, 161, 201, 40, 235, 52, 97, 161, 201, 40, 235, 51, 97, 161, - 201, 40, 235, 49, 97, 161, 201, 40, 235, 53, 221, 84, 97, 161, 201, 40, - 235, 50, 221, 84, 97, 161, 201, 40, 230, 195, 4, 202, 170, 191, 103, 97, - 161, 201, 40, 230, 191, 4, 202, 170, 191, 103, 97, 161, 201, 40, 230, - 194, 97, 161, 201, 40, 230, 190, 97, 161, 201, 40, 230, 191, 4, 55, 191, - 103, 97, 161, 201, 40, 230, 192, 97, 161, 201, 40, 230, 193, 209, 5, 97, - 161, 216, 221, 97, 161, 216, 222, 209, 4, 97, 161, 216, 222, 221, 83, 97, - 161, 216, 222, 221, 86, 97, 161, 216, 222, 221, 88, 97, 161, 201, 40, - 197, 174, 97, 161, 201, 40, 197, 173, 97, 161, 201, 40, 197, 172, 97, - 161, 211, 31, 97, 161, 211, 32, 200, 154, 97, 161, 211, 32, 197, 247, 97, - 161, 211, 32, 220, 255, 200, 154, 97, 161, 211, 32, 221, 85, 200, 154, - 97, 161, 211, 32, 221, 85, 214, 96, 97, 161, 201, 40, 220, 254, 97, 161, - 201, 40, 220, 255, 209, 5, 97, 161, 201, 40, 220, 255, 230, 195, 4, 202, - 170, 191, 103, 97, 161, 201, 40, 220, 255, 230, 191, 4, 202, 170, 191, - 103, 97, 161, 201, 40, 220, 255, 230, 194, 97, 161, 201, 40, 220, 255, - 230, 190, 97, 161, 201, 40, 220, 255, 230, 191, 4, 55, 191, 103, 97, 161, - 201, 40, 220, 255, 230, 192, 97, 161, 201, 40, 220, 255, 230, 193, 209, - 5, 97, 161, 201, 40, 220, 255, 197, 175, 97, 161, 220, 214, 97, 161, 211, - 173, 97, 161, 235, 84, 97, 161, 214, 103, 97, 161, 210, 79, 73, 37, 16, - 208, 169, 73, 37, 16, 237, 217, 73, 37, 16, 210, 4, 73, 37, 16, 210, 246, - 234, 144, 73, 37, 16, 210, 246, 236, 238, 73, 37, 16, 195, 172, 234, 144, - 73, 37, 16, 195, 172, 236, 238, 73, 37, 16, 222, 44, 73, 37, 16, 200, 60, - 73, 37, 16, 210, 120, 73, 37, 16, 191, 231, 73, 37, 16, 191, 232, 236, - 238, 73, 37, 16, 221, 3, 73, 37, 16, 251, 61, 234, 144, 73, 37, 16, 233, - 210, 234, 144, 73, 37, 16, 199, 108, 73, 37, 16, 221, 247, 73, 37, 16, - 251, 50, 73, 37, 16, 251, 51, 236, 238, 73, 37, 16, 200, 67, 73, 37, 16, - 198, 244, 73, 37, 16, 211, 116, 251, 12, 73, 37, 16, 230, 238, 251, 12, - 73, 37, 16, 208, 168, 73, 37, 16, 246, 248, 73, 37, 16, 195, 161, 73, 37, - 16, 223, 58, 251, 12, 73, 37, 16, 221, 249, 251, 12, 73, 37, 16, 221, - 248, 251, 12, 73, 37, 16, 205, 105, 73, 37, 16, 210, 110, 73, 37, 16, - 201, 88, 251, 54, 73, 37, 16, 210, 245, 251, 12, 73, 37, 16, 195, 171, - 251, 12, 73, 37, 16, 251, 55, 251, 12, 73, 37, 16, 251, 48, 73, 37, 16, - 221, 92, 73, 37, 16, 207, 14, 73, 37, 16, 209, 183, 251, 12, 73, 37, 16, - 198, 142, 73, 37, 16, 251, 128, 73, 37, 16, 205, 37, 73, 37, 16, 200, 71, - 251, 12, 73, 37, 16, 200, 71, 216, 166, 201, 86, 73, 37, 16, 210, 240, - 251, 12, 73, 37, 16, 199, 27, 73, 37, 16, 219, 202, 73, 37, 16, 235, 38, - 73, 37, 16, 197, 243, 73, 37, 16, 199, 76, 73, 37, 16, 221, 6, 73, 37, - 16, 251, 61, 233, 210, 214, 98, 73, 37, 16, 232, 88, 251, 12, 73, 37, 16, - 223, 175, 73, 37, 16, 197, 210, 251, 12, 73, 37, 16, 222, 47, 197, 209, - 73, 37, 16, 210, 36, 73, 37, 16, 208, 173, 73, 37, 16, 221, 42, 73, 37, - 16, 243, 60, 251, 12, 73, 37, 16, 207, 135, 73, 37, 16, 210, 124, 251, - 12, 73, 37, 16, 210, 121, 251, 12, 73, 37, 16, 228, 24, 73, 37, 16, 214, - 225, 73, 37, 16, 209, 238, 73, 37, 16, 221, 43, 251, 167, 73, 37, 16, - 197, 210, 251, 167, 73, 37, 16, 201, 55, 73, 37, 16, 230, 189, 73, 37, - 16, 223, 58, 214, 98, 73, 37, 16, 211, 116, 214, 98, 73, 37, 16, 210, - 246, 214, 98, 73, 37, 16, 209, 237, 73, 37, 16, 221, 26, 73, 37, 16, 209, - 236, 73, 37, 16, 221, 5, 73, 37, 16, 210, 37, 214, 98, 73, 37, 16, 221, - 248, 214, 99, 251, 93, 73, 37, 16, 221, 249, 214, 99, 251, 93, 73, 37, - 16, 191, 229, 73, 37, 16, 251, 51, 214, 98, 73, 37, 16, 251, 52, 200, 68, - 214, 98, 73, 37, 16, 191, 230, 73, 37, 16, 221, 4, 73, 37, 16, 234, 139, - 73, 37, 16, 246, 249, 73, 37, 16, 216, 57, 223, 57, 73, 37, 16, 195, 172, - 214, 98, 73, 37, 16, 209, 183, 214, 98, 73, 37, 16, 208, 174, 214, 98, - 73, 37, 16, 211, 112, 73, 37, 16, 251, 80, 73, 37, 16, 218, 179, 73, 37, - 16, 210, 121, 214, 98, 73, 37, 16, 210, 124, 214, 98, 73, 37, 16, 233, - 249, 210, 123, 73, 37, 16, 220, 147, 73, 37, 16, 251, 81, 73, 37, 16, - 197, 210, 214, 98, 73, 37, 16, 234, 142, 73, 37, 16, 200, 71, 214, 98, - 73, 37, 16, 200, 61, 73, 37, 16, 243, 60, 214, 98, 73, 37, 16, 234, 53, - 73, 37, 16, 205, 38, 214, 98, 73, 37, 16, 192, 199, 221, 92, 73, 37, 16, - 197, 207, 73, 37, 16, 208, 175, 73, 37, 16, 197, 211, 73, 37, 16, 197, - 208, 73, 37, 16, 208, 172, 73, 37, 16, 197, 206, 73, 37, 16, 208, 171, - 73, 37, 16, 230, 237, 73, 37, 16, 251, 4, 73, 37, 16, 233, 249, 251, 4, - 73, 37, 16, 210, 240, 214, 98, 73, 37, 16, 199, 26, 234, 6, 73, 37, 16, - 199, 26, 233, 209, 73, 37, 16, 199, 28, 251, 56, 73, 37, 16, 199, 20, - 222, 103, 251, 47, 73, 37, 16, 222, 46, 73, 37, 16, 234, 90, 73, 37, 16, - 192, 38, 222, 43, 73, 37, 16, 192, 38, 251, 93, 73, 37, 16, 201, 87, 73, - 37, 16, 221, 93, 251, 93, 73, 37, 16, 236, 239, 251, 12, 73, 37, 16, 221, - 7, 251, 12, 73, 37, 16, 221, 7, 251, 167, 73, 37, 16, 221, 7, 214, 98, - 73, 37, 16, 251, 55, 214, 98, 73, 37, 16, 251, 57, 73, 37, 16, 236, 238, - 73, 37, 16, 197, 223, 73, 37, 16, 199, 66, 73, 37, 16, 221, 30, 73, 37, - 16, 219, 207, 234, 83, 243, 50, 73, 37, 16, 219, 207, 235, 39, 243, 51, - 73, 37, 16, 219, 207, 197, 226, 243, 51, 73, 37, 16, 219, 207, 199, 78, - 243, 51, 73, 37, 16, 219, 207, 223, 170, 243, 50, 73, 37, 16, 230, 238, - 214, 99, 251, 93, 73, 37, 16, 230, 238, 210, 111, 251, 0, 73, 37, 16, - 230, 238, 210, 111, 237, 73, 73, 37, 16, 237, 7, 73, 37, 16, 237, 8, 210, - 111, 251, 1, 222, 43, 73, 37, 16, 237, 8, 210, 111, 251, 1, 251, 93, 73, - 37, 16, 237, 8, 210, 111, 237, 73, 73, 37, 16, 197, 232, 73, 37, 16, 251, - 5, 73, 37, 16, 223, 177, 73, 37, 16, 237, 30, 73, 37, 16, 251, 247, 209, - 51, 251, 6, 73, 37, 16, 251, 247, 251, 3, 73, 37, 16, 251, 247, 251, 6, - 73, 37, 16, 251, 247, 216, 160, 73, 37, 16, 251, 247, 216, 171, 73, 37, - 16, 251, 247, 230, 239, 73, 37, 16, 251, 247, 230, 236, 73, 37, 16, 251, - 247, 209, 51, 230, 239, 73, 37, 16, 217, 45, 208, 181, 228, 22, 73, 37, - 16, 217, 45, 251, 169, 208, 181, 228, 22, 73, 37, 16, 217, 45, 237, 72, - 228, 22, 73, 37, 16, 217, 45, 251, 169, 237, 72, 228, 22, 73, 37, 16, - 217, 45, 197, 218, 228, 22, 73, 37, 16, 217, 45, 197, 233, 73, 37, 16, - 217, 45, 199, 71, 228, 22, 73, 37, 16, 217, 45, 199, 71, 219, 211, 228, - 22, 73, 37, 16, 217, 45, 219, 211, 228, 22, 73, 37, 16, 217, 45, 209, - 105, 228, 22, 73, 37, 16, 223, 66, 199, 101, 228, 23, 73, 37, 16, 251, - 52, 199, 101, 228, 23, 73, 37, 16, 233, 79, 199, 68, 73, 37, 16, 233, 79, - 215, 222, 73, 37, 16, 233, 79, 237, 13, 73, 37, 16, 217, 45, 195, 165, - 228, 22, 73, 37, 16, 217, 45, 208, 180, 228, 22, 73, 37, 16, 217, 45, - 209, 105, 199, 71, 228, 22, 73, 37, 16, 230, 233, 215, 62, 251, 56, 73, - 37, 16, 230, 233, 215, 62, 236, 237, 73, 37, 16, 234, 101, 222, 103, 232, - 88, 195, 3, 73, 37, 16, 223, 176, 73, 37, 16, 223, 174, 73, 37, 16, 232, - 88, 251, 13, 237, 71, 228, 21, 73, 37, 16, 232, 88, 237, 28, 168, 73, 37, - 16, 232, 88, 237, 28, 214, 225, 73, 37, 16, 232, 88, 214, 219, 228, 22, - 73, 37, 16, 232, 88, 237, 28, 237, 44, 73, 37, 16, 232, 88, 202, 106, - 237, 27, 237, 44, 73, 37, 16, 232, 88, 237, 28, 222, 22, 73, 37, 16, 232, - 88, 237, 28, 191, 7, 73, 37, 16, 232, 88, 237, 28, 213, 220, 222, 43, 73, - 37, 16, 232, 88, 237, 28, 213, 220, 251, 93, 73, 37, 16, 232, 88, 217, - 98, 243, 52, 237, 13, 73, 37, 16, 232, 88, 217, 98, 243, 52, 215, 222, - 73, 37, 16, 233, 24, 202, 106, 243, 52, 195, 164, 73, 37, 16, 232, 88, - 202, 106, 243, 52, 200, 72, 73, 37, 16, 232, 88, 214, 101, 73, 37, 16, - 243, 53, 190, 230, 73, 37, 16, 243, 53, 221, 91, 73, 37, 16, 243, 53, - 201, 238, 73, 37, 16, 232, 88, 228, 74, 192, 37, 199, 72, 73, 37, 16, - 232, 88, 234, 102, 251, 82, 73, 37, 16, 192, 37, 197, 219, 73, 37, 16, - 237, 21, 197, 219, 73, 37, 16, 237, 21, 199, 72, 73, 37, 16, 237, 21, - 251, 58, 235, 39, 236, 166, 73, 37, 16, 237, 21, 215, 220, 199, 77, 236, - 166, 73, 37, 16, 237, 21, 237, 4, 233, 222, 236, 166, 73, 37, 16, 237, - 21, 197, 230, 211, 122, 236, 166, 73, 37, 16, 192, 37, 251, 58, 235, 39, - 236, 166, 73, 37, 16, 192, 37, 215, 220, 199, 77, 236, 166, 73, 37, 16, - 192, 37, 237, 4, 233, 222, 236, 166, 73, 37, 16, 192, 37, 197, 230, 211, - 122, 236, 166, 73, 37, 16, 231, 147, 237, 20, 73, 37, 16, 231, 147, 192, - 36, 73, 37, 16, 237, 29, 251, 58, 216, 58, 73, 37, 16, 237, 29, 251, 58, - 216, 202, 73, 37, 16, 237, 29, 236, 238, 73, 37, 16, 237, 29, 199, 18, - 73, 37, 16, 202, 181, 199, 18, 73, 37, 16, 202, 181, 199, 19, 236, 221, - 73, 37, 16, 202, 181, 199, 19, 197, 220, 73, 37, 16, 202, 181, 199, 19, - 199, 64, 73, 37, 16, 202, 181, 250, 228, 73, 37, 16, 202, 181, 250, 229, - 236, 221, 73, 37, 16, 202, 181, 250, 229, 197, 220, 73, 37, 16, 202, 181, - 250, 229, 199, 64, 73, 37, 16, 237, 5, 231, 128, 73, 37, 16, 237, 12, - 211, 19, 73, 37, 16, 201, 73, 73, 37, 16, 250, 253, 168, 73, 37, 16, 250, - 253, 195, 3, 73, 37, 16, 250, 253, 231, 240, 73, 37, 16, 250, 253, 237, - 44, 73, 37, 16, 250, 253, 222, 22, 73, 37, 16, 250, 253, 191, 7, 73, 37, - 16, 250, 253, 213, 219, 73, 37, 16, 221, 248, 214, 99, 216, 170, 73, 37, - 16, 221, 249, 214, 99, 216, 170, 73, 37, 16, 221, 248, 214, 99, 222, 43, - 73, 37, 16, 221, 249, 214, 99, 222, 43, 73, 37, 16, 221, 93, 222, 43, 73, - 37, 16, 230, 238, 214, 99, 222, 43, 37, 16, 202, 170, 249, 83, 37, 16, - 55, 249, 83, 37, 16, 53, 249, 83, 37, 16, 207, 19, 53, 249, 83, 37, 16, - 237, 214, 249, 83, 37, 16, 203, 40, 249, 83, 37, 16, 45, 207, 49, 56, 37, - 16, 50, 207, 49, 56, 37, 16, 207, 49, 236, 138, 37, 16, 238, 4, 205, 41, - 37, 16, 238, 33, 247, 108, 37, 16, 205, 41, 37, 16, 242, 92, 37, 16, 207, - 47, 233, 11, 37, 16, 207, 47, 233, 10, 37, 16, 207, 47, 233, 9, 37, 16, - 233, 34, 37, 16, 233, 35, 60, 37, 16, 248, 39, 77, 37, 16, 247, 150, 37, - 16, 248, 55, 37, 16, 248, 53, 37, 16, 211, 99, 201, 111, 37, 16, 197, 12, - 201, 111, 37, 16, 198, 220, 201, 111, 37, 16, 232, 127, 201, 111, 37, 16, - 232, 224, 201, 111, 37, 16, 202, 135, 201, 111, 37, 16, 202, 133, 232, - 105, 37, 16, 232, 125, 232, 105, 37, 16, 232, 52, 242, 235, 37, 16, 232, - 52, 242, 236, 211, 23, 251, 158, 37, 16, 232, 52, 242, 236, 211, 23, 249, - 66, 37, 16, 247, 194, 242, 235, 37, 16, 233, 176, 242, 235, 37, 16, 233, - 176, 242, 236, 211, 23, 251, 158, 37, 16, 233, 176, 242, 236, 211, 23, - 249, 66, 37, 16, 235, 95, 242, 234, 37, 16, 235, 95, 242, 233, 37, 16, - 215, 129, 216, 228, 207, 30, 37, 16, 55, 203, 126, 37, 16, 55, 232, 206, - 37, 16, 232, 207, 196, 77, 37, 16, 232, 207, 235, 123, 37, 16, 214, 206, - 196, 77, 37, 16, 214, 206, 235, 123, 37, 16, 203, 127, 196, 77, 37, 16, - 203, 127, 235, 123, 37, 16, 208, 23, 163, 203, 126, 37, 16, 208, 23, 163, - 232, 206, 37, 16, 242, 71, 198, 146, 37, 16, 238, 155, 198, 146, 37, 16, - 211, 23, 251, 158, 37, 16, 211, 23, 249, 66, 37, 16, 208, 3, 251, 158, - 37, 16, 208, 3, 249, 66, 37, 16, 215, 132, 207, 30, 37, 16, 193, 87, 207, - 30, 37, 16, 132, 207, 30, 37, 16, 208, 23, 207, 30, 37, 16, 234, 160, - 207, 30, 37, 16, 202, 129, 207, 30, 37, 16, 198, 246, 207, 30, 37, 16, - 202, 119, 207, 30, 37, 16, 91, 228, 141, 197, 30, 207, 30, 37, 16, 192, - 236, 213, 2, 37, 16, 108, 213, 2, 37, 16, 243, 11, 192, 236, 213, 2, 37, - 16, 51, 213, 3, 193, 89, 37, 16, 51, 213, 3, 248, 139, 37, 16, 197, 242, - 213, 3, 133, 193, 89, 37, 16, 197, 242, 213, 3, 133, 248, 139, 37, 16, - 197, 242, 213, 3, 45, 193, 89, 37, 16, 197, 242, 213, 3, 45, 248, 139, - 37, 16, 197, 242, 213, 3, 50, 193, 89, 37, 16, 197, 242, 213, 3, 50, 248, - 139, 37, 16, 197, 242, 213, 3, 144, 193, 89, 37, 16, 197, 242, 213, 3, - 144, 248, 139, 37, 16, 197, 242, 213, 3, 133, 50, 193, 89, 37, 16, 197, - 242, 213, 3, 133, 50, 248, 139, 37, 16, 215, 206, 213, 3, 193, 89, 37, - 16, 215, 206, 213, 3, 248, 139, 37, 16, 197, 239, 213, 3, 144, 193, 89, - 37, 16, 197, 239, 213, 3, 144, 248, 139, 37, 16, 210, 114, 213, 2, 37, - 16, 195, 17, 213, 2, 37, 16, 213, 3, 248, 139, 37, 16, 212, 139, 213, 2, - 37, 16, 242, 203, 213, 3, 193, 89, 37, 16, 242, 203, 213, 3, 248, 139, - 37, 16, 248, 36, 37, 16, 193, 87, 213, 6, 37, 16, 132, 213, 6, 37, 16, - 208, 23, 213, 6, 37, 16, 234, 160, 213, 6, 37, 16, 202, 129, 213, 6, 37, - 16, 198, 246, 213, 6, 37, 16, 202, 119, 213, 6, 37, 16, 91, 228, 141, - 197, 30, 213, 6, 37, 16, 33, 201, 80, 37, 16, 33, 201, 197, 201, 80, 37, - 16, 33, 197, 253, 37, 16, 33, 197, 252, 37, 16, 33, 197, 251, 37, 16, - 232, 250, 197, 253, 37, 16, 232, 250, 197, 252, 37, 16, 232, 250, 197, - 251, 37, 16, 33, 250, 160, 236, 140, 37, 16, 33, 232, 216, 37, 16, 33, - 232, 215, 37, 16, 33, 232, 214, 37, 16, 33, 232, 213, 37, 16, 33, 232, - 212, 37, 16, 248, 249, 249, 14, 37, 16, 234, 95, 249, 14, 37, 16, 248, - 249, 198, 178, 37, 16, 234, 95, 198, 178, 37, 16, 248, 249, 202, 71, 37, - 16, 234, 95, 202, 71, 37, 16, 248, 249, 209, 192, 37, 16, 234, 95, 209, - 192, 37, 16, 33, 252, 60, 37, 16, 33, 201, 115, 37, 16, 33, 199, 83, 37, - 16, 33, 201, 116, 37, 16, 33, 217, 60, 37, 16, 33, 217, 59, 37, 16, 33, - 252, 59, 37, 16, 33, 218, 243, 37, 16, 250, 241, 196, 77, 37, 16, 250, - 241, 235, 123, 37, 16, 33, 236, 158, 37, 16, 33, 206, 184, 37, 16, 33, - 232, 195, 37, 16, 33, 202, 67, 37, 16, 33, 248, 227, 37, 16, 33, 55, 198, - 61, 37, 16, 33, 197, 225, 198, 61, 37, 16, 206, 190, 37, 16, 200, 241, - 37, 16, 191, 166, 37, 16, 209, 184, 37, 16, 216, 151, 37, 16, 232, 140, - 37, 16, 238, 229, 37, 16, 237, 132, 37, 16, 230, 228, 213, 7, 202, 97, - 37, 16, 230, 228, 213, 7, 213, 44, 202, 97, 37, 16, 198, 27, 37, 16, 197, - 58, 37, 16, 223, 93, 197, 58, 37, 16, 197, 59, 202, 97, 37, 16, 197, 59, - 196, 77, 37, 16, 211, 43, 201, 27, 37, 16, 211, 43, 201, 24, 37, 16, 211, - 43, 201, 23, 37, 16, 211, 43, 201, 22, 37, 16, 211, 43, 201, 21, 37, 16, - 211, 43, 201, 20, 37, 16, 211, 43, 201, 19, 37, 16, 211, 43, 201, 18, 37, - 16, 211, 43, 201, 17, 37, 16, 211, 43, 201, 26, 37, 16, 211, 43, 201, 25, - 37, 16, 230, 0, 37, 16, 214, 113, 37, 16, 234, 95, 79, 201, 69, 37, 16, - 237, 125, 202, 97, 37, 16, 33, 144, 248, 69, 37, 16, 33, 133, 248, 69, - 37, 16, 33, 230, 14, 37, 16, 33, 202, 57, 209, 111, 37, 16, 210, 54, 77, - 37, 16, 210, 54, 133, 77, 37, 16, 132, 210, 54, 77, 37, 16, 231, 13, 196, - 77, 37, 16, 231, 13, 235, 123, 37, 16, 4, 232, 249, 37, 16, 237, 241, 37, - 16, 237, 242, 251, 174, 37, 16, 217, 23, 37, 16, 219, 10, 37, 16, 248, - 33, 37, 16, 204, 29, 193, 89, 37, 16, 204, 29, 248, 139, 37, 16, 216, 39, - 37, 16, 216, 40, 248, 139, 37, 16, 204, 23, 193, 89, 37, 16, 204, 23, - 248, 139, 37, 16, 232, 70, 193, 89, 37, 16, 232, 70, 248, 139, 37, 16, - 219, 11, 210, 9, 207, 30, 37, 16, 219, 11, 223, 167, 207, 30, 37, 16, - 248, 34, 207, 30, 37, 16, 204, 29, 207, 30, 37, 16, 216, 40, 207, 30, 37, - 16, 204, 23, 207, 30, 37, 16, 199, 97, 210, 7, 238, 186, 208, 192, 210, - 8, 37, 16, 199, 97, 210, 7, 238, 186, 208, 192, 223, 166, 37, 16, 199, - 97, 210, 7, 238, 186, 208, 192, 210, 9, 236, 248, 37, 16, 199, 97, 223, - 165, 238, 186, 208, 192, 210, 8, 37, 16, 199, 97, 223, 165, 238, 186, - 208, 192, 223, 166, 37, 16, 199, 97, 223, 165, 238, 186, 208, 192, 223, - 167, 236, 248, 37, 16, 199, 97, 223, 165, 238, 186, 208, 192, 223, 167, - 236, 247, 37, 16, 199, 97, 223, 165, 238, 186, 208, 192, 223, 167, 236, - 246, 37, 16, 238, 220, 37, 16, 230, 199, 247, 194, 242, 235, 37, 16, 230, - 199, 233, 176, 242, 235, 37, 16, 51, 250, 120, 37, 16, 195, 39, 37, 16, - 209, 69, 37, 16, 242, 224, 37, 16, 205, 95, 37, 16, 242, 229, 37, 16, - 198, 47, 37, 16, 209, 28, 37, 16, 209, 29, 232, 198, 37, 16, 205, 96, - 232, 198, 37, 16, 198, 48, 207, 27, 37, 16, 209, 246, 200, 231, 37, 16, - 221, 148, 247, 194, 242, 235, 37, 16, 221, 148, 234, 95, 79, 209, 175, - 37, 16, 221, 148, 53, 213, 6, 37, 16, 221, 148, 207, 99, 77, 37, 16, 221, - 148, 193, 87, 213, 6, 37, 16, 221, 148, 132, 213, 6, 37, 16, 221, 148, - 208, 23, 213, 7, 201, 81, 235, 123, 37, 16, 221, 148, 208, 23, 213, 7, - 201, 81, 196, 77, 37, 16, 221, 148, 234, 160, 213, 7, 201, 81, 235, 123, - 37, 16, 221, 148, 234, 160, 213, 7, 201, 81, 196, 77, 37, 16, 221, 148, - 232, 207, 56, 37, 16, 202, 11, 37, 16, 221, 31, 35, 195, 23, 213, 10, - 200, 123, 35, 195, 23, 213, 10, 200, 112, 35, 195, 23, 213, 10, 200, 102, - 35, 195, 23, 213, 10, 200, 95, 35, 195, 23, 213, 10, 200, 87, 35, 195, - 23, 213, 10, 200, 81, 35, 195, 23, 213, 10, 200, 80, 35, 195, 23, 213, - 10, 200, 79, 35, 195, 23, 213, 10, 200, 78, 35, 195, 23, 213, 10, 200, - 122, 35, 195, 23, 213, 10, 200, 121, 35, 195, 23, 213, 10, 200, 120, 35, - 195, 23, 213, 10, 200, 119, 35, 195, 23, 213, 10, 200, 118, 35, 195, 23, - 213, 10, 200, 117, 35, 195, 23, 213, 10, 200, 116, 35, 195, 23, 213, 10, - 200, 115, 35, 195, 23, 213, 10, 200, 114, 35, 195, 23, 213, 10, 200, 113, - 35, 195, 23, 213, 10, 200, 111, 35, 195, 23, 213, 10, 200, 110, 35, 195, - 23, 213, 10, 200, 109, 35, 195, 23, 213, 10, 200, 108, 35, 195, 23, 213, - 10, 200, 107, 35, 195, 23, 213, 10, 200, 86, 35, 195, 23, 213, 10, 200, - 85, 35, 195, 23, 213, 10, 200, 84, 35, 195, 23, 213, 10, 200, 83, 35, - 195, 23, 213, 10, 200, 82, 35, 223, 116, 213, 10, 200, 123, 35, 223, 116, - 213, 10, 200, 112, 35, 223, 116, 213, 10, 200, 95, 35, 223, 116, 213, 10, - 200, 87, 35, 223, 116, 213, 10, 200, 80, 35, 223, 116, 213, 10, 200, 79, - 35, 223, 116, 213, 10, 200, 121, 35, 223, 116, 213, 10, 200, 120, 35, - 223, 116, 213, 10, 200, 119, 35, 223, 116, 213, 10, 200, 118, 35, 223, - 116, 213, 10, 200, 115, 35, 223, 116, 213, 10, 200, 114, 35, 223, 116, - 213, 10, 200, 113, 35, 223, 116, 213, 10, 200, 108, 35, 223, 116, 213, - 10, 200, 107, 35, 223, 116, 213, 10, 200, 106, 35, 223, 116, 213, 10, - 200, 105, 35, 223, 116, 213, 10, 200, 104, 35, 223, 116, 213, 10, 200, - 103, 35, 223, 116, 213, 10, 200, 101, 35, 223, 116, 213, 10, 200, 100, - 35, 223, 116, 213, 10, 200, 99, 35, 223, 116, 213, 10, 200, 98, 35, 223, - 116, 213, 10, 200, 97, 35, 223, 116, 213, 10, 200, 96, 35, 223, 116, 213, - 10, 200, 94, 35, 223, 116, 213, 10, 200, 93, 35, 223, 116, 213, 10, 200, - 92, 35, 223, 116, 213, 10, 200, 91, 35, 223, 116, 213, 10, 200, 90, 35, - 223, 116, 213, 10, 200, 89, 35, 223, 116, 213, 10, 200, 88, 35, 223, 116, - 213, 10, 200, 86, 35, 223, 116, 213, 10, 200, 85, 35, 223, 116, 213, 10, - 200, 84, 35, 223, 116, 213, 10, 200, 83, 35, 223, 116, 213, 10, 200, 82, - 33, 35, 37, 197, 221, 33, 35, 37, 199, 65, 33, 35, 37, 210, 22, 35, 37, - 219, 206, 222, 93, 212, 134, 191, 77, 222, 93, 212, 134, 107, 222, 93, - 212, 134, 109, 222, 93, 212, 134, 138, 222, 93, 212, 134, 134, 222, 93, - 212, 134, 149, 222, 93, 212, 134, 169, 222, 93, 212, 134, 175, 222, 93, - 212, 134, 171, 222, 93, 212, 134, 178, 222, 93, 212, 134, 199, 95, 222, - 93, 212, 134, 234, 127, 222, 93, 212, 134, 197, 37, 222, 93, 212, 134, - 198, 251, 222, 93, 212, 134, 232, 122, 222, 93, 212, 134, 233, 19, 222, - 93, 212, 134, 202, 130, 222, 93, 212, 134, 203, 244, 222, 93, 212, 134, - 234, 161, 222, 93, 212, 134, 213, 171, 217, 20, 212, 134, 191, 77, 217, - 20, 212, 134, 107, 217, 20, 212, 134, 109, 217, 20, 212, 134, 138, 217, - 20, 212, 134, 134, 217, 20, 212, 134, 149, 217, 20, 212, 134, 169, 217, - 20, 212, 134, 175, 217, 20, 212, 134, 171, 217, 20, 212, 134, 178, 217, - 20, 212, 134, 199, 95, 217, 20, 212, 134, 234, 127, 217, 20, 212, 134, - 197, 37, 217, 20, 212, 134, 198, 251, 217, 20, 212, 134, 232, 122, 217, - 20, 212, 134, 233, 19, 217, 20, 212, 134, 202, 130, 217, 20, 212, 134, - 203, 244, 217, 20, 212, 134, 234, 161, 217, 20, 212, 134, 213, 171, 215, - 221, 40, 234, 207, 237, 6, 40, 229, 218, 234, 207, 237, 6, 40, 228, 145, - 234, 207, 237, 6, 40, 234, 206, 229, 219, 237, 6, 40, 234, 206, 228, 144, - 237, 6, 40, 234, 207, 199, 67, 40, 247, 21, 199, 67, 40, 232, 80, 243, - 10, 199, 67, 40, 216, 30, 199, 67, 40, 249, 78, 199, 67, 40, 222, 10, - 202, 70, 199, 67, 40, 239, 23, 199, 67, 40, 250, 212, 199, 67, 40, 211, - 62, 199, 67, 40, 248, 45, 211, 14, 199, 67, 40, 237, 127, 211, 57, 236, - 213, 199, 67, 40, 236, 210, 199, 67, 40, 191, 237, 199, 67, 40, 223, 153, - 199, 67, 40, 210, 32, 199, 67, 40, 207, 108, 199, 67, 40, 239, 35, 199, - 67, 40, 229, 6, 249, 146, 199, 67, 40, 193, 171, 199, 67, 40, 232, 169, - 199, 67, 40, 252, 28, 199, 67, 40, 207, 62, 199, 67, 40, 207, 34, 199, - 67, 40, 234, 205, 199, 67, 40, 222, 185, 199, 67, 40, 239, 30, 199, 67, - 40, 234, 93, 199, 67, 40, 235, 59, 199, 67, 40, 246, 244, 199, 67, 40, - 237, 137, 199, 67, 40, 28, 207, 33, 199, 67, 40, 210, 211, 199, 67, 40, - 219, 210, 199, 67, 40, 242, 217, 199, 67, 40, 221, 136, 199, 67, 40, 231, - 189, 199, 67, 40, 201, 39, 199, 67, 40, 208, 140, 199, 67, 40, 232, 79, - 199, 67, 40, 207, 35, 199, 67, 40, 219, 251, 211, 57, 216, 2, 199, 67, - 40, 207, 31, 199, 67, 40, 230, 252, 119, 216, 206, 199, 67, 40, 234, 96, - 199, 67, 40, 201, 56, 199, 67, 40, 230, 202, 199, 67, 40, 234, 86, 199, - 67, 40, 210, 83, 199, 67, 40, 206, 177, 199, 67, 40, 232, 196, 199, 67, - 40, 195, 163, 211, 57, 193, 147, 199, 67, 40, 239, 40, 199, 67, 40, 216, - 227, 199, 67, 40, 233, 250, 199, 67, 40, 196, 88, 199, 67, 40, 236, 249, - 199, 67, 40, 242, 219, 215, 179, 199, 67, 40, 230, 171, 199, 67, 40, 231, - 190, 223, 162, 199, 67, 40, 217, 32, 199, 67, 40, 252, 54, 199, 67, 40, - 234, 112, 199, 67, 40, 235, 127, 199, 67, 40, 193, 145, 199, 67, 40, 202, - 165, 199, 67, 40, 223, 126, 199, 67, 40, 237, 93, 199, 67, 40, 237, 219, - 199, 67, 40, 236, 245, 199, 67, 40, 233, 213, 199, 67, 40, 203, 240, 199, - 67, 40, 201, 60, 199, 67, 40, 230, 16, 199, 67, 40, 242, 66, 199, 67, 40, - 242, 214, 199, 67, 40, 233, 88, 199, 67, 40, 251, 248, 199, 67, 40, 242, - 65, 199, 67, 40, 211, 105, 199, 34, 195, 138, 199, 67, 40, 237, 15, 199, - 67, 40, 220, 113, 199, 67, 40, 232, 131, 238, 244, 206, 145, 196, 91, 17, - 107, 238, 244, 206, 145, 196, 91, 17, 109, 238, 244, 206, 145, 196, 91, - 17, 138, 238, 244, 206, 145, 196, 91, 17, 134, 238, 244, 206, 145, 196, - 91, 17, 149, 238, 244, 206, 145, 196, 91, 17, 169, 238, 244, 206, 145, - 196, 91, 17, 175, 238, 244, 206, 145, 196, 91, 17, 171, 238, 244, 206, - 145, 196, 91, 17, 178, 238, 244, 206, 145, 199, 91, 17, 107, 238, 244, - 206, 145, 199, 91, 17, 109, 238, 244, 206, 145, 199, 91, 17, 138, 238, - 244, 206, 145, 199, 91, 17, 134, 238, 244, 206, 145, 199, 91, 17, 149, - 238, 244, 206, 145, 199, 91, 17, 169, 238, 244, 206, 145, 199, 91, 17, - 175, 238, 244, 206, 145, 199, 91, 17, 171, 238, 244, 206, 145, 199, 91, - 17, 178, 154, 199, 198, 87, 107, 154, 199, 198, 87, 109, 154, 199, 198, - 87, 138, 154, 199, 198, 87, 134, 154, 199, 198, 87, 149, 199, 198, 87, - 107, 199, 198, 87, 149, 13, 28, 6, 65, 13, 28, 6, 250, 120, 13, 28, 6, - 247, 193, 13, 28, 6, 238, 127, 13, 28, 6, 71, 13, 28, 6, 233, 175, 13, - 28, 6, 232, 51, 13, 28, 6, 230, 116, 13, 28, 6, 68, 13, 28, 6, 223, 35, - 13, 28, 6, 222, 152, 13, 28, 6, 172, 13, 28, 6, 218, 168, 13, 28, 6, 215, - 61, 13, 28, 6, 74, 13, 28, 6, 210, 236, 13, 28, 6, 208, 104, 13, 28, 6, - 146, 13, 28, 6, 206, 8, 13, 28, 6, 200, 43, 13, 28, 6, 66, 13, 28, 6, - 196, 12, 13, 28, 6, 193, 224, 13, 28, 6, 192, 235, 13, 28, 6, 192, 159, - 13, 28, 6, 191, 166, 13, 28, 2, 65, 13, 28, 2, 250, 120, 13, 28, 2, 247, - 193, 13, 28, 2, 238, 127, 13, 28, 2, 71, 13, 28, 2, 233, 175, 13, 28, 2, - 232, 51, 13, 28, 2, 230, 116, 13, 28, 2, 68, 13, 28, 2, 223, 35, 13, 28, - 2, 222, 152, 13, 28, 2, 172, 13, 28, 2, 218, 168, 13, 28, 2, 215, 61, 13, - 28, 2, 74, 13, 28, 2, 210, 236, 13, 28, 2, 208, 104, 13, 28, 2, 146, 13, - 28, 2, 206, 8, 13, 28, 2, 200, 43, 13, 28, 2, 66, 13, 28, 2, 196, 12, 13, - 28, 2, 193, 224, 13, 28, 2, 192, 235, 13, 28, 2, 192, 159, 13, 28, 2, - 191, 166, 13, 43, 6, 65, 13, 43, 6, 250, 120, 13, 43, 6, 247, 193, 13, - 43, 6, 238, 127, 13, 43, 6, 71, 13, 43, 6, 233, 175, 13, 43, 6, 232, 51, - 13, 43, 6, 230, 116, 13, 43, 6, 68, 13, 43, 6, 223, 35, 13, 43, 6, 222, - 152, 13, 43, 6, 172, 13, 43, 6, 218, 168, 13, 43, 6, 215, 61, 13, 43, 6, - 74, 13, 43, 6, 210, 236, 13, 43, 6, 208, 104, 13, 43, 6, 146, 13, 43, 6, - 206, 8, 13, 43, 6, 200, 43, 13, 43, 6, 66, 13, 43, 6, 196, 12, 13, 43, 6, - 193, 224, 13, 43, 6, 192, 235, 13, 43, 6, 192, 159, 13, 43, 6, 191, 166, - 13, 43, 2, 65, 13, 43, 2, 250, 120, 13, 43, 2, 247, 193, 13, 43, 2, 238, - 127, 13, 43, 2, 71, 13, 43, 2, 233, 175, 13, 43, 2, 232, 51, 13, 43, 2, - 68, 13, 43, 2, 223, 35, 13, 43, 2, 222, 152, 13, 43, 2, 172, 13, 43, 2, - 218, 168, 13, 43, 2, 215, 61, 13, 43, 2, 74, 13, 43, 2, 210, 236, 13, 43, - 2, 208, 104, 13, 43, 2, 146, 13, 43, 2, 206, 8, 13, 43, 2, 200, 43, 13, - 43, 2, 66, 13, 43, 2, 196, 12, 13, 43, 2, 193, 224, 13, 43, 2, 192, 235, - 13, 43, 2, 192, 159, 13, 43, 2, 191, 166, 13, 28, 43, 6, 65, 13, 28, 43, - 6, 250, 120, 13, 28, 43, 6, 247, 193, 13, 28, 43, 6, 238, 127, 13, 28, - 43, 6, 71, 13, 28, 43, 6, 233, 175, 13, 28, 43, 6, 232, 51, 13, 28, 43, - 6, 230, 116, 13, 28, 43, 6, 68, 13, 28, 43, 6, 223, 35, 13, 28, 43, 6, - 222, 152, 13, 28, 43, 6, 172, 13, 28, 43, 6, 218, 168, 13, 28, 43, 6, - 215, 61, 13, 28, 43, 6, 74, 13, 28, 43, 6, 210, 236, 13, 28, 43, 6, 208, - 104, 13, 28, 43, 6, 146, 13, 28, 43, 6, 206, 8, 13, 28, 43, 6, 200, 43, - 13, 28, 43, 6, 66, 13, 28, 43, 6, 196, 12, 13, 28, 43, 6, 193, 224, 13, - 28, 43, 6, 192, 235, 13, 28, 43, 6, 192, 159, 13, 28, 43, 6, 191, 166, - 13, 28, 43, 2, 65, 13, 28, 43, 2, 250, 120, 13, 28, 43, 2, 247, 193, 13, - 28, 43, 2, 238, 127, 13, 28, 43, 2, 71, 13, 28, 43, 2, 233, 175, 13, 28, - 43, 2, 232, 51, 13, 28, 43, 2, 230, 116, 13, 28, 43, 2, 68, 13, 28, 43, - 2, 223, 35, 13, 28, 43, 2, 222, 152, 13, 28, 43, 2, 172, 13, 28, 43, 2, - 218, 168, 13, 28, 43, 2, 215, 61, 13, 28, 43, 2, 74, 13, 28, 43, 2, 210, - 236, 13, 28, 43, 2, 208, 104, 13, 28, 43, 2, 146, 13, 28, 43, 2, 206, 8, - 13, 28, 43, 2, 200, 43, 13, 28, 43, 2, 66, 13, 28, 43, 2, 196, 12, 13, - 28, 43, 2, 193, 224, 13, 28, 43, 2, 192, 235, 13, 28, 43, 2, 192, 159, - 13, 28, 43, 2, 191, 166, 13, 27, 6, 65, 13, 27, 6, 247, 193, 13, 27, 6, - 238, 127, 13, 27, 6, 232, 51, 13, 27, 6, 223, 35, 13, 27, 6, 222, 152, - 13, 27, 6, 215, 61, 13, 27, 6, 74, 13, 27, 6, 210, 236, 13, 27, 6, 208, - 104, 13, 27, 6, 206, 8, 13, 27, 6, 200, 43, 13, 27, 6, 66, 13, 27, 6, - 196, 12, 13, 27, 6, 193, 224, 13, 27, 6, 192, 235, 13, 27, 6, 192, 159, - 13, 27, 6, 191, 166, 13, 27, 2, 65, 13, 27, 2, 250, 120, 13, 27, 2, 247, - 193, 13, 27, 2, 238, 127, 13, 27, 2, 233, 175, 13, 27, 2, 230, 116, 13, - 27, 2, 68, 13, 27, 2, 223, 35, 13, 27, 2, 222, 152, 13, 27, 2, 172, 13, - 27, 2, 218, 168, 13, 27, 2, 215, 61, 13, 27, 2, 210, 236, 13, 27, 2, 208, - 104, 13, 27, 2, 146, 13, 27, 2, 206, 8, 13, 27, 2, 200, 43, 13, 27, 2, - 66, 13, 27, 2, 196, 12, 13, 27, 2, 193, 224, 13, 27, 2, 192, 235, 13, 27, - 2, 192, 159, 13, 27, 2, 191, 166, 13, 28, 27, 6, 65, 13, 28, 27, 6, 250, - 120, 13, 28, 27, 6, 247, 193, 13, 28, 27, 6, 238, 127, 13, 28, 27, 6, 71, - 13, 28, 27, 6, 233, 175, 13, 28, 27, 6, 232, 51, 13, 28, 27, 6, 230, 116, - 13, 28, 27, 6, 68, 13, 28, 27, 6, 223, 35, 13, 28, 27, 6, 222, 152, 13, - 28, 27, 6, 172, 13, 28, 27, 6, 218, 168, 13, 28, 27, 6, 215, 61, 13, 28, - 27, 6, 74, 13, 28, 27, 6, 210, 236, 13, 28, 27, 6, 208, 104, 13, 28, 27, - 6, 146, 13, 28, 27, 6, 206, 8, 13, 28, 27, 6, 200, 43, 13, 28, 27, 6, 66, - 13, 28, 27, 6, 196, 12, 13, 28, 27, 6, 193, 224, 13, 28, 27, 6, 192, 235, - 13, 28, 27, 6, 192, 159, 13, 28, 27, 6, 191, 166, 13, 28, 27, 2, 65, 13, - 28, 27, 2, 250, 120, 13, 28, 27, 2, 247, 193, 13, 28, 27, 2, 238, 127, - 13, 28, 27, 2, 71, 13, 28, 27, 2, 233, 175, 13, 28, 27, 2, 232, 51, 13, - 28, 27, 2, 230, 116, 13, 28, 27, 2, 68, 13, 28, 27, 2, 223, 35, 13, 28, - 27, 2, 222, 152, 13, 28, 27, 2, 172, 13, 28, 27, 2, 218, 168, 13, 28, 27, - 2, 215, 61, 13, 28, 27, 2, 74, 13, 28, 27, 2, 210, 236, 13, 28, 27, 2, - 208, 104, 13, 28, 27, 2, 146, 13, 28, 27, 2, 206, 8, 13, 28, 27, 2, 200, - 43, 13, 28, 27, 2, 66, 13, 28, 27, 2, 196, 12, 13, 28, 27, 2, 193, 224, - 13, 28, 27, 2, 192, 235, 13, 28, 27, 2, 192, 159, 13, 28, 27, 2, 191, - 166, 13, 232, 115, 6, 65, 13, 232, 115, 6, 250, 120, 13, 232, 115, 6, - 238, 127, 13, 232, 115, 6, 71, 13, 232, 115, 6, 233, 175, 13, 232, 115, - 6, 232, 51, 13, 232, 115, 6, 223, 35, 13, 232, 115, 6, 222, 152, 13, 232, - 115, 6, 172, 13, 232, 115, 6, 218, 168, 13, 232, 115, 6, 215, 61, 13, - 232, 115, 6, 74, 13, 232, 115, 6, 210, 236, 13, 232, 115, 6, 208, 104, - 13, 232, 115, 6, 206, 8, 13, 232, 115, 6, 200, 43, 13, 232, 115, 6, 66, - 13, 232, 115, 6, 196, 12, 13, 232, 115, 6, 193, 224, 13, 232, 115, 6, - 192, 235, 13, 232, 115, 6, 192, 159, 13, 232, 115, 2, 65, 13, 232, 115, - 2, 250, 120, 13, 232, 115, 2, 247, 193, 13, 232, 115, 2, 238, 127, 13, - 232, 115, 2, 71, 13, 232, 115, 2, 233, 175, 13, 232, 115, 2, 232, 51, 13, - 232, 115, 2, 230, 116, 13, 232, 115, 2, 68, 13, 232, 115, 2, 223, 35, 13, - 232, 115, 2, 222, 152, 13, 232, 115, 2, 172, 13, 232, 115, 2, 218, 168, - 13, 232, 115, 2, 215, 61, 13, 232, 115, 2, 74, 13, 232, 115, 2, 210, 236, - 13, 232, 115, 2, 208, 104, 13, 232, 115, 2, 146, 13, 232, 115, 2, 206, 8, - 13, 232, 115, 2, 200, 43, 13, 232, 115, 2, 66, 13, 232, 115, 2, 196, 12, - 13, 232, 115, 2, 193, 224, 13, 232, 115, 2, 192, 235, 13, 232, 115, 2, - 192, 159, 13, 232, 115, 2, 191, 166, 13, 235, 129, 6, 65, 13, 235, 129, - 6, 250, 120, 13, 235, 129, 6, 238, 127, 13, 235, 129, 6, 71, 13, 235, - 129, 6, 233, 175, 13, 235, 129, 6, 232, 51, 13, 235, 129, 6, 68, 13, 235, - 129, 6, 223, 35, 13, 235, 129, 6, 222, 152, 13, 235, 129, 6, 172, 13, - 235, 129, 6, 218, 168, 13, 235, 129, 6, 74, 13, 235, 129, 6, 206, 8, 13, - 235, 129, 6, 200, 43, 13, 235, 129, 6, 66, 13, 235, 129, 6, 196, 12, 13, - 235, 129, 6, 193, 224, 13, 235, 129, 6, 192, 235, 13, 235, 129, 6, 192, - 159, 13, 235, 129, 2, 65, 13, 235, 129, 2, 250, 120, 13, 235, 129, 2, - 247, 193, 13, 235, 129, 2, 238, 127, 13, 235, 129, 2, 71, 13, 235, 129, - 2, 233, 175, 13, 235, 129, 2, 232, 51, 13, 235, 129, 2, 230, 116, 13, - 235, 129, 2, 68, 13, 235, 129, 2, 223, 35, 13, 235, 129, 2, 222, 152, 13, - 235, 129, 2, 172, 13, 235, 129, 2, 218, 168, 13, 235, 129, 2, 215, 61, - 13, 235, 129, 2, 74, 13, 235, 129, 2, 210, 236, 13, 235, 129, 2, 208, - 104, 13, 235, 129, 2, 146, 13, 235, 129, 2, 206, 8, 13, 235, 129, 2, 200, - 43, 13, 235, 129, 2, 66, 13, 235, 129, 2, 196, 12, 13, 235, 129, 2, 193, - 224, 13, 235, 129, 2, 192, 235, 13, 235, 129, 2, 192, 159, 13, 235, 129, - 2, 191, 166, 13, 28, 232, 115, 6, 65, 13, 28, 232, 115, 6, 250, 120, 13, - 28, 232, 115, 6, 247, 193, 13, 28, 232, 115, 6, 238, 127, 13, 28, 232, - 115, 6, 71, 13, 28, 232, 115, 6, 233, 175, 13, 28, 232, 115, 6, 232, 51, - 13, 28, 232, 115, 6, 230, 116, 13, 28, 232, 115, 6, 68, 13, 28, 232, 115, - 6, 223, 35, 13, 28, 232, 115, 6, 222, 152, 13, 28, 232, 115, 6, 172, 13, - 28, 232, 115, 6, 218, 168, 13, 28, 232, 115, 6, 215, 61, 13, 28, 232, - 115, 6, 74, 13, 28, 232, 115, 6, 210, 236, 13, 28, 232, 115, 6, 208, 104, - 13, 28, 232, 115, 6, 146, 13, 28, 232, 115, 6, 206, 8, 13, 28, 232, 115, - 6, 200, 43, 13, 28, 232, 115, 6, 66, 13, 28, 232, 115, 6, 196, 12, 13, - 28, 232, 115, 6, 193, 224, 13, 28, 232, 115, 6, 192, 235, 13, 28, 232, - 115, 6, 192, 159, 13, 28, 232, 115, 6, 191, 166, 13, 28, 232, 115, 2, 65, - 13, 28, 232, 115, 2, 250, 120, 13, 28, 232, 115, 2, 247, 193, 13, 28, - 232, 115, 2, 238, 127, 13, 28, 232, 115, 2, 71, 13, 28, 232, 115, 2, 233, - 175, 13, 28, 232, 115, 2, 232, 51, 13, 28, 232, 115, 2, 230, 116, 13, 28, - 232, 115, 2, 68, 13, 28, 232, 115, 2, 223, 35, 13, 28, 232, 115, 2, 222, - 152, 13, 28, 232, 115, 2, 172, 13, 28, 232, 115, 2, 218, 168, 13, 28, - 232, 115, 2, 215, 61, 13, 28, 232, 115, 2, 74, 13, 28, 232, 115, 2, 210, - 236, 13, 28, 232, 115, 2, 208, 104, 13, 28, 232, 115, 2, 146, 13, 28, - 232, 115, 2, 206, 8, 13, 28, 232, 115, 2, 200, 43, 13, 28, 232, 115, 2, - 66, 13, 28, 232, 115, 2, 196, 12, 13, 28, 232, 115, 2, 193, 224, 13, 28, - 232, 115, 2, 192, 235, 13, 28, 232, 115, 2, 192, 159, 13, 28, 232, 115, - 2, 191, 166, 13, 49, 6, 65, 13, 49, 6, 250, 120, 13, 49, 6, 247, 193, 13, - 49, 6, 238, 127, 13, 49, 6, 71, 13, 49, 6, 233, 175, 13, 49, 6, 232, 51, - 13, 49, 6, 230, 116, 13, 49, 6, 68, 13, 49, 6, 223, 35, 13, 49, 6, 222, - 152, 13, 49, 6, 172, 13, 49, 6, 218, 168, 13, 49, 6, 215, 61, 13, 49, 6, - 74, 13, 49, 6, 210, 236, 13, 49, 6, 208, 104, 13, 49, 6, 146, 13, 49, 6, - 206, 8, 13, 49, 6, 200, 43, 13, 49, 6, 66, 13, 49, 6, 196, 12, 13, 49, 6, - 193, 224, 13, 49, 6, 192, 235, 13, 49, 6, 192, 159, 13, 49, 6, 191, 166, - 13, 49, 2, 65, 13, 49, 2, 250, 120, 13, 49, 2, 247, 193, 13, 49, 2, 238, - 127, 13, 49, 2, 71, 13, 49, 2, 233, 175, 13, 49, 2, 232, 51, 13, 49, 2, - 230, 116, 13, 49, 2, 68, 13, 49, 2, 223, 35, 13, 49, 2, 222, 152, 13, 49, - 2, 172, 13, 49, 2, 218, 168, 13, 49, 2, 215, 61, 13, 49, 2, 74, 13, 49, - 2, 210, 236, 13, 49, 2, 208, 104, 13, 49, 2, 146, 13, 49, 2, 206, 8, 13, - 49, 2, 200, 43, 13, 49, 2, 66, 13, 49, 2, 196, 12, 13, 49, 2, 193, 224, - 13, 49, 2, 192, 235, 13, 49, 2, 192, 159, 13, 49, 2, 191, 166, 13, 49, - 28, 6, 65, 13, 49, 28, 6, 250, 120, 13, 49, 28, 6, 247, 193, 13, 49, 28, - 6, 238, 127, 13, 49, 28, 6, 71, 13, 49, 28, 6, 233, 175, 13, 49, 28, 6, - 232, 51, 13, 49, 28, 6, 230, 116, 13, 49, 28, 6, 68, 13, 49, 28, 6, 223, - 35, 13, 49, 28, 6, 222, 152, 13, 49, 28, 6, 172, 13, 49, 28, 6, 218, 168, - 13, 49, 28, 6, 215, 61, 13, 49, 28, 6, 74, 13, 49, 28, 6, 210, 236, 13, - 49, 28, 6, 208, 104, 13, 49, 28, 6, 146, 13, 49, 28, 6, 206, 8, 13, 49, - 28, 6, 200, 43, 13, 49, 28, 6, 66, 13, 49, 28, 6, 196, 12, 13, 49, 28, 6, - 193, 224, 13, 49, 28, 6, 192, 235, 13, 49, 28, 6, 192, 159, 13, 49, 28, - 6, 191, 166, 13, 49, 28, 2, 65, 13, 49, 28, 2, 250, 120, 13, 49, 28, 2, - 247, 193, 13, 49, 28, 2, 238, 127, 13, 49, 28, 2, 71, 13, 49, 28, 2, 233, - 175, 13, 49, 28, 2, 232, 51, 13, 49, 28, 2, 230, 116, 13, 49, 28, 2, 68, - 13, 49, 28, 2, 223, 35, 13, 49, 28, 2, 222, 152, 13, 49, 28, 2, 172, 13, - 49, 28, 2, 218, 168, 13, 49, 28, 2, 215, 61, 13, 49, 28, 2, 74, 13, 49, - 28, 2, 210, 236, 13, 49, 28, 2, 208, 104, 13, 49, 28, 2, 146, 13, 49, 28, - 2, 206, 8, 13, 49, 28, 2, 200, 43, 13, 49, 28, 2, 66, 13, 49, 28, 2, 196, - 12, 13, 49, 28, 2, 193, 224, 13, 49, 28, 2, 192, 235, 13, 49, 28, 2, 192, - 159, 13, 49, 28, 2, 191, 166, 13, 49, 43, 6, 65, 13, 49, 43, 6, 250, 120, - 13, 49, 43, 6, 247, 193, 13, 49, 43, 6, 238, 127, 13, 49, 43, 6, 71, 13, - 49, 43, 6, 233, 175, 13, 49, 43, 6, 232, 51, 13, 49, 43, 6, 230, 116, 13, - 49, 43, 6, 68, 13, 49, 43, 6, 223, 35, 13, 49, 43, 6, 222, 152, 13, 49, - 43, 6, 172, 13, 49, 43, 6, 218, 168, 13, 49, 43, 6, 215, 61, 13, 49, 43, - 6, 74, 13, 49, 43, 6, 210, 236, 13, 49, 43, 6, 208, 104, 13, 49, 43, 6, - 146, 13, 49, 43, 6, 206, 8, 13, 49, 43, 6, 200, 43, 13, 49, 43, 6, 66, - 13, 49, 43, 6, 196, 12, 13, 49, 43, 6, 193, 224, 13, 49, 43, 6, 192, 235, - 13, 49, 43, 6, 192, 159, 13, 49, 43, 6, 191, 166, 13, 49, 43, 2, 65, 13, - 49, 43, 2, 250, 120, 13, 49, 43, 2, 247, 193, 13, 49, 43, 2, 238, 127, - 13, 49, 43, 2, 71, 13, 49, 43, 2, 233, 175, 13, 49, 43, 2, 232, 51, 13, - 49, 43, 2, 230, 116, 13, 49, 43, 2, 68, 13, 49, 43, 2, 223, 35, 13, 49, - 43, 2, 222, 152, 13, 49, 43, 2, 172, 13, 49, 43, 2, 218, 168, 13, 49, 43, - 2, 215, 61, 13, 49, 43, 2, 74, 13, 49, 43, 2, 210, 236, 13, 49, 43, 2, - 208, 104, 13, 49, 43, 2, 146, 13, 49, 43, 2, 206, 8, 13, 49, 43, 2, 200, - 43, 13, 49, 43, 2, 66, 13, 49, 43, 2, 196, 12, 13, 49, 43, 2, 193, 224, - 13, 49, 43, 2, 192, 235, 13, 49, 43, 2, 192, 159, 13, 49, 43, 2, 191, - 166, 13, 49, 28, 43, 6, 65, 13, 49, 28, 43, 6, 250, 120, 13, 49, 28, 43, - 6, 247, 193, 13, 49, 28, 43, 6, 238, 127, 13, 49, 28, 43, 6, 71, 13, 49, - 28, 43, 6, 233, 175, 13, 49, 28, 43, 6, 232, 51, 13, 49, 28, 43, 6, 230, - 116, 13, 49, 28, 43, 6, 68, 13, 49, 28, 43, 6, 223, 35, 13, 49, 28, 43, - 6, 222, 152, 13, 49, 28, 43, 6, 172, 13, 49, 28, 43, 6, 218, 168, 13, 49, - 28, 43, 6, 215, 61, 13, 49, 28, 43, 6, 74, 13, 49, 28, 43, 6, 210, 236, - 13, 49, 28, 43, 6, 208, 104, 13, 49, 28, 43, 6, 146, 13, 49, 28, 43, 6, - 206, 8, 13, 49, 28, 43, 6, 200, 43, 13, 49, 28, 43, 6, 66, 13, 49, 28, - 43, 6, 196, 12, 13, 49, 28, 43, 6, 193, 224, 13, 49, 28, 43, 6, 192, 235, - 13, 49, 28, 43, 6, 192, 159, 13, 49, 28, 43, 6, 191, 166, 13, 49, 28, 43, - 2, 65, 13, 49, 28, 43, 2, 250, 120, 13, 49, 28, 43, 2, 247, 193, 13, 49, - 28, 43, 2, 238, 127, 13, 49, 28, 43, 2, 71, 13, 49, 28, 43, 2, 233, 175, - 13, 49, 28, 43, 2, 232, 51, 13, 49, 28, 43, 2, 230, 116, 13, 49, 28, 43, - 2, 68, 13, 49, 28, 43, 2, 223, 35, 13, 49, 28, 43, 2, 222, 152, 13, 49, - 28, 43, 2, 172, 13, 49, 28, 43, 2, 218, 168, 13, 49, 28, 43, 2, 215, 61, - 13, 49, 28, 43, 2, 74, 13, 49, 28, 43, 2, 210, 236, 13, 49, 28, 43, 2, - 208, 104, 13, 49, 28, 43, 2, 146, 13, 49, 28, 43, 2, 206, 8, 13, 49, 28, - 43, 2, 200, 43, 13, 49, 28, 43, 2, 66, 13, 49, 28, 43, 2, 196, 12, 13, - 49, 28, 43, 2, 193, 224, 13, 49, 28, 43, 2, 192, 235, 13, 49, 28, 43, 2, - 192, 159, 13, 49, 28, 43, 2, 191, 166, 13, 215, 217, 6, 65, 13, 215, 217, - 6, 250, 120, 13, 215, 217, 6, 247, 193, 13, 215, 217, 6, 238, 127, 13, - 215, 217, 6, 71, 13, 215, 217, 6, 233, 175, 13, 215, 217, 6, 232, 51, 13, - 215, 217, 6, 230, 116, 13, 215, 217, 6, 68, 13, 215, 217, 6, 223, 35, 13, - 215, 217, 6, 222, 152, 13, 215, 217, 6, 172, 13, 215, 217, 6, 218, 168, - 13, 215, 217, 6, 215, 61, 13, 215, 217, 6, 74, 13, 215, 217, 6, 210, 236, - 13, 215, 217, 6, 208, 104, 13, 215, 217, 6, 146, 13, 215, 217, 6, 206, 8, - 13, 215, 217, 6, 200, 43, 13, 215, 217, 6, 66, 13, 215, 217, 6, 196, 12, - 13, 215, 217, 6, 193, 224, 13, 215, 217, 6, 192, 235, 13, 215, 217, 6, - 192, 159, 13, 215, 217, 6, 191, 166, 13, 215, 217, 2, 65, 13, 215, 217, - 2, 250, 120, 13, 215, 217, 2, 247, 193, 13, 215, 217, 2, 238, 127, 13, - 215, 217, 2, 71, 13, 215, 217, 2, 233, 175, 13, 215, 217, 2, 232, 51, 13, - 215, 217, 2, 230, 116, 13, 215, 217, 2, 68, 13, 215, 217, 2, 223, 35, 13, - 215, 217, 2, 222, 152, 13, 215, 217, 2, 172, 13, 215, 217, 2, 218, 168, - 13, 215, 217, 2, 215, 61, 13, 215, 217, 2, 74, 13, 215, 217, 2, 210, 236, - 13, 215, 217, 2, 208, 104, 13, 215, 217, 2, 146, 13, 215, 217, 2, 206, 8, - 13, 215, 217, 2, 200, 43, 13, 215, 217, 2, 66, 13, 215, 217, 2, 196, 12, - 13, 215, 217, 2, 193, 224, 13, 215, 217, 2, 192, 235, 13, 215, 217, 2, - 192, 159, 13, 215, 217, 2, 191, 166, 13, 43, 2, 236, 139, 68, 13, 43, 2, - 236, 139, 223, 35, 13, 28, 6, 251, 160, 13, 28, 6, 248, 212, 13, 28, 6, - 231, 211, 13, 28, 6, 237, 106, 13, 28, 6, 234, 47, 13, 28, 6, 191, 76, - 13, 28, 6, 233, 253, 13, 28, 6, 199, 15, 13, 28, 6, 223, 83, 13, 28, 6, - 222, 72, 13, 28, 6, 220, 31, 13, 28, 6, 215, 155, 13, 28, 6, 212, 178, - 13, 28, 6, 192, 207, 13, 28, 6, 211, 107, 13, 28, 6, 209, 185, 13, 28, 6, - 207, 3, 13, 28, 6, 199, 16, 113, 13, 28, 6, 202, 196, 13, 28, 6, 199, - 166, 13, 28, 6, 196, 70, 13, 28, 6, 209, 211, 13, 28, 6, 243, 95, 13, 28, - 6, 208, 176, 13, 28, 6, 211, 110, 13, 28, 214, 245, 13, 28, 2, 251, 160, - 13, 28, 2, 248, 212, 13, 28, 2, 231, 211, 13, 28, 2, 237, 106, 13, 28, 2, - 234, 47, 13, 28, 2, 191, 76, 13, 28, 2, 233, 253, 13, 28, 2, 199, 15, 13, - 28, 2, 223, 83, 13, 28, 2, 222, 72, 13, 28, 2, 220, 31, 13, 28, 2, 215, - 155, 13, 28, 2, 212, 178, 13, 28, 2, 192, 207, 13, 28, 2, 211, 107, 13, - 28, 2, 209, 185, 13, 28, 2, 207, 3, 13, 28, 2, 53, 202, 196, 13, 28, 2, - 202, 196, 13, 28, 2, 199, 166, 13, 28, 2, 196, 70, 13, 28, 2, 209, 211, - 13, 28, 2, 243, 95, 13, 28, 2, 208, 176, 13, 28, 2, 211, 110, 13, 28, - 210, 105, 237, 16, 13, 28, 234, 48, 113, 13, 28, 199, 16, 113, 13, 28, - 222, 73, 113, 13, 28, 209, 212, 113, 13, 28, 207, 4, 113, 13, 28, 209, - 186, 113, 13, 43, 6, 251, 160, 13, 43, 6, 248, 212, 13, 43, 6, 231, 211, - 13, 43, 6, 237, 106, 13, 43, 6, 234, 47, 13, 43, 6, 191, 76, 13, 43, 6, - 233, 253, 13, 43, 6, 199, 15, 13, 43, 6, 223, 83, 13, 43, 6, 222, 72, 13, - 43, 6, 220, 31, 13, 43, 6, 215, 155, 13, 43, 6, 212, 178, 13, 43, 6, 192, - 207, 13, 43, 6, 211, 107, 13, 43, 6, 209, 185, 13, 43, 6, 207, 3, 13, 43, - 6, 199, 16, 113, 13, 43, 6, 202, 196, 13, 43, 6, 199, 166, 13, 43, 6, - 196, 70, 13, 43, 6, 209, 211, 13, 43, 6, 243, 95, 13, 43, 6, 208, 176, - 13, 43, 6, 211, 110, 13, 43, 214, 245, 13, 43, 2, 251, 160, 13, 43, 2, - 248, 212, 13, 43, 2, 231, 211, 13, 43, 2, 237, 106, 13, 43, 2, 234, 47, - 13, 43, 2, 191, 76, 13, 43, 2, 233, 253, 13, 43, 2, 199, 15, 13, 43, 2, - 223, 83, 13, 43, 2, 222, 72, 13, 43, 2, 220, 31, 13, 43, 2, 215, 155, 13, - 43, 2, 212, 178, 13, 43, 2, 192, 207, 13, 43, 2, 211, 107, 13, 43, 2, - 209, 185, 13, 43, 2, 207, 3, 13, 43, 2, 53, 202, 196, 13, 43, 2, 202, - 196, 13, 43, 2, 199, 166, 13, 43, 2, 196, 70, 13, 43, 2, 209, 211, 13, - 43, 2, 243, 95, 13, 43, 2, 208, 176, 13, 43, 2, 211, 110, 13, 43, 210, - 105, 237, 16, 13, 43, 234, 48, 113, 13, 43, 199, 16, 113, 13, 43, 222, - 73, 113, 13, 43, 209, 212, 113, 13, 43, 207, 4, 113, 13, 43, 209, 186, - 113, 13, 28, 43, 6, 251, 160, 13, 28, 43, 6, 248, 212, 13, 28, 43, 6, - 231, 211, 13, 28, 43, 6, 237, 106, 13, 28, 43, 6, 234, 47, 13, 28, 43, 6, - 191, 76, 13, 28, 43, 6, 233, 253, 13, 28, 43, 6, 199, 15, 13, 28, 43, 6, - 223, 83, 13, 28, 43, 6, 222, 72, 13, 28, 43, 6, 220, 31, 13, 28, 43, 6, - 215, 155, 13, 28, 43, 6, 212, 178, 13, 28, 43, 6, 192, 207, 13, 28, 43, - 6, 211, 107, 13, 28, 43, 6, 209, 185, 13, 28, 43, 6, 207, 3, 13, 28, 43, - 6, 199, 16, 113, 13, 28, 43, 6, 202, 196, 13, 28, 43, 6, 199, 166, 13, - 28, 43, 6, 196, 70, 13, 28, 43, 6, 209, 211, 13, 28, 43, 6, 243, 95, 13, - 28, 43, 6, 208, 176, 13, 28, 43, 6, 211, 110, 13, 28, 43, 214, 245, 13, - 28, 43, 2, 251, 160, 13, 28, 43, 2, 248, 212, 13, 28, 43, 2, 231, 211, - 13, 28, 43, 2, 237, 106, 13, 28, 43, 2, 234, 47, 13, 28, 43, 2, 191, 76, - 13, 28, 43, 2, 233, 253, 13, 28, 43, 2, 199, 15, 13, 28, 43, 2, 223, 83, - 13, 28, 43, 2, 222, 72, 13, 28, 43, 2, 220, 31, 13, 28, 43, 2, 215, 155, - 13, 28, 43, 2, 212, 178, 13, 28, 43, 2, 192, 207, 13, 28, 43, 2, 211, - 107, 13, 28, 43, 2, 209, 185, 13, 28, 43, 2, 207, 3, 13, 28, 43, 2, 53, - 202, 196, 13, 28, 43, 2, 202, 196, 13, 28, 43, 2, 199, 166, 13, 28, 43, - 2, 196, 70, 13, 28, 43, 2, 209, 211, 13, 28, 43, 2, 243, 95, 13, 28, 43, - 2, 208, 176, 13, 28, 43, 2, 211, 110, 13, 28, 43, 210, 105, 237, 16, 13, - 28, 43, 234, 48, 113, 13, 28, 43, 199, 16, 113, 13, 28, 43, 222, 73, 113, - 13, 28, 43, 209, 212, 113, 13, 28, 43, 207, 4, 113, 13, 28, 43, 209, 186, - 113, 13, 49, 28, 6, 251, 160, 13, 49, 28, 6, 248, 212, 13, 49, 28, 6, - 231, 211, 13, 49, 28, 6, 237, 106, 13, 49, 28, 6, 234, 47, 13, 49, 28, 6, - 191, 76, 13, 49, 28, 6, 233, 253, 13, 49, 28, 6, 199, 15, 13, 49, 28, 6, - 223, 83, 13, 49, 28, 6, 222, 72, 13, 49, 28, 6, 220, 31, 13, 49, 28, 6, - 215, 155, 13, 49, 28, 6, 212, 178, 13, 49, 28, 6, 192, 207, 13, 49, 28, - 6, 211, 107, 13, 49, 28, 6, 209, 185, 13, 49, 28, 6, 207, 3, 13, 49, 28, - 6, 199, 16, 113, 13, 49, 28, 6, 202, 196, 13, 49, 28, 6, 199, 166, 13, - 49, 28, 6, 196, 70, 13, 49, 28, 6, 209, 211, 13, 49, 28, 6, 243, 95, 13, - 49, 28, 6, 208, 176, 13, 49, 28, 6, 211, 110, 13, 49, 28, 214, 245, 13, - 49, 28, 2, 251, 160, 13, 49, 28, 2, 248, 212, 13, 49, 28, 2, 231, 211, - 13, 49, 28, 2, 237, 106, 13, 49, 28, 2, 234, 47, 13, 49, 28, 2, 191, 76, - 13, 49, 28, 2, 233, 253, 13, 49, 28, 2, 199, 15, 13, 49, 28, 2, 223, 83, - 13, 49, 28, 2, 222, 72, 13, 49, 28, 2, 220, 31, 13, 49, 28, 2, 215, 155, - 13, 49, 28, 2, 212, 178, 13, 49, 28, 2, 192, 207, 13, 49, 28, 2, 211, - 107, 13, 49, 28, 2, 209, 185, 13, 49, 28, 2, 207, 3, 13, 49, 28, 2, 53, - 202, 196, 13, 49, 28, 2, 202, 196, 13, 49, 28, 2, 199, 166, 13, 49, 28, - 2, 196, 70, 13, 49, 28, 2, 209, 211, 13, 49, 28, 2, 243, 95, 13, 49, 28, - 2, 208, 176, 13, 49, 28, 2, 211, 110, 13, 49, 28, 210, 105, 237, 16, 13, - 49, 28, 234, 48, 113, 13, 49, 28, 199, 16, 113, 13, 49, 28, 222, 73, 113, - 13, 49, 28, 209, 212, 113, 13, 49, 28, 207, 4, 113, 13, 49, 28, 209, 186, - 113, 13, 49, 28, 43, 6, 251, 160, 13, 49, 28, 43, 6, 248, 212, 13, 49, - 28, 43, 6, 231, 211, 13, 49, 28, 43, 6, 237, 106, 13, 49, 28, 43, 6, 234, - 47, 13, 49, 28, 43, 6, 191, 76, 13, 49, 28, 43, 6, 233, 253, 13, 49, 28, - 43, 6, 199, 15, 13, 49, 28, 43, 6, 223, 83, 13, 49, 28, 43, 6, 222, 72, - 13, 49, 28, 43, 6, 220, 31, 13, 49, 28, 43, 6, 215, 155, 13, 49, 28, 43, - 6, 212, 178, 13, 49, 28, 43, 6, 192, 207, 13, 49, 28, 43, 6, 211, 107, - 13, 49, 28, 43, 6, 209, 185, 13, 49, 28, 43, 6, 207, 3, 13, 49, 28, 43, - 6, 199, 16, 113, 13, 49, 28, 43, 6, 202, 196, 13, 49, 28, 43, 6, 199, - 166, 13, 49, 28, 43, 6, 196, 70, 13, 49, 28, 43, 6, 209, 211, 13, 49, 28, - 43, 6, 243, 95, 13, 49, 28, 43, 6, 208, 176, 13, 49, 28, 43, 6, 211, 110, - 13, 49, 28, 43, 214, 245, 13, 49, 28, 43, 2, 251, 160, 13, 49, 28, 43, 2, - 248, 212, 13, 49, 28, 43, 2, 231, 211, 13, 49, 28, 43, 2, 237, 106, 13, - 49, 28, 43, 2, 234, 47, 13, 49, 28, 43, 2, 191, 76, 13, 49, 28, 43, 2, - 233, 253, 13, 49, 28, 43, 2, 199, 15, 13, 49, 28, 43, 2, 223, 83, 13, 49, - 28, 43, 2, 222, 72, 13, 49, 28, 43, 2, 220, 31, 13, 49, 28, 43, 2, 215, - 155, 13, 49, 28, 43, 2, 212, 178, 13, 49, 28, 43, 2, 192, 207, 13, 49, - 28, 43, 2, 211, 107, 13, 49, 28, 43, 2, 209, 185, 13, 49, 28, 43, 2, 207, - 3, 13, 49, 28, 43, 2, 53, 202, 196, 13, 49, 28, 43, 2, 202, 196, 13, 49, - 28, 43, 2, 199, 166, 13, 49, 28, 43, 2, 196, 70, 13, 49, 28, 43, 2, 209, - 211, 13, 49, 28, 43, 2, 243, 95, 13, 49, 28, 43, 2, 208, 176, 13, 49, 28, - 43, 2, 211, 110, 13, 49, 28, 43, 210, 105, 237, 16, 13, 49, 28, 43, 234, - 48, 113, 13, 49, 28, 43, 199, 16, 113, 13, 49, 28, 43, 222, 73, 113, 13, - 49, 28, 43, 209, 212, 113, 13, 49, 28, 43, 207, 4, 113, 13, 49, 28, 43, - 209, 186, 113, 13, 28, 6, 237, 10, 13, 28, 2, 237, 10, 13, 28, 17, 191, - 77, 13, 28, 17, 107, 13, 28, 17, 109, 13, 28, 17, 138, 13, 28, 17, 134, - 13, 28, 17, 149, 13, 28, 17, 169, 13, 28, 17, 175, 13, 28, 17, 171, 13, - 28, 17, 178, 13, 235, 129, 17, 191, 77, 13, 235, 129, 17, 107, 13, 235, - 129, 17, 109, 13, 235, 129, 17, 138, 13, 235, 129, 17, 134, 13, 235, 129, - 17, 149, 13, 235, 129, 17, 169, 13, 235, 129, 17, 175, 13, 235, 129, 17, - 171, 13, 235, 129, 17, 178, 13, 49, 17, 191, 77, 13, 49, 17, 107, 13, 49, - 17, 109, 13, 49, 17, 138, 13, 49, 17, 134, 13, 49, 17, 149, 13, 49, 17, - 169, 13, 49, 17, 175, 13, 49, 17, 171, 13, 49, 17, 178, 13, 49, 28, 17, - 191, 77, 13, 49, 28, 17, 107, 13, 49, 28, 17, 109, 13, 49, 28, 17, 138, - 13, 49, 28, 17, 134, 13, 49, 28, 17, 149, 13, 49, 28, 17, 169, 13, 49, - 28, 17, 175, 13, 49, 28, 17, 171, 13, 49, 28, 17, 178, 13, 215, 217, 17, - 191, 77, 13, 215, 217, 17, 107, 13, 215, 217, 17, 109, 13, 215, 217, 17, - 138, 13, 215, 217, 17, 134, 13, 215, 217, 17, 149, 13, 215, 217, 17, 169, - 13, 215, 217, 17, 175, 13, 215, 217, 17, 171, 13, 215, 217, 17, 178, 24, - 151, 223, 148, 24, 230, 50, 223, 148, 24, 230, 46, 223, 148, 24, 230, 35, - 223, 148, 24, 230, 39, 223, 148, 24, 230, 52, 223, 148, 24, 151, 141, - 248, 223, 24, 230, 50, 141, 248, 223, 24, 151, 176, 196, 105, 141, 248, - 223, 24, 151, 141, 207, 147, 221, 70, 24, 151, 141, 238, 177, 24, 151, - 141, 229, 124, 24, 151, 141, 229, 125, 218, 241, 24, 230, 50, 141, 229, - 126, 24, 151, 141, 216, 84, 24, 230, 50, 141, 216, 84, 24, 151, 141, 82, - 248, 223, 24, 151, 141, 82, 207, 147, 221, 69, 24, 151, 141, 82, 229, - 124, 24, 151, 141, 133, 82, 229, 124, 24, 151, 141, 229, 125, 82, 196, - 77, 24, 151, 141, 82, 239, 46, 24, 151, 141, 82, 239, 47, 141, 248, 223, - 24, 151, 141, 82, 239, 47, 82, 248, 223, 24, 151, 141, 82, 239, 47, 238, - 177, 24, 151, 141, 82, 239, 47, 229, 124, 24, 151, 141, 82, 238, 213, 24, - 230, 50, 141, 82, 238, 213, 24, 151, 82, 248, 224, 139, 223, 148, 24, - 151, 141, 248, 224, 139, 216, 84, 24, 151, 141, 82, 198, 212, 24, 230, - 50, 141, 82, 198, 212, 24, 151, 141, 82, 201, 53, 176, 248, 223, 24, 151, - 141, 82, 248, 224, 176, 201, 52, 24, 151, 141, 82, 176, 248, 223, 24, - 151, 141, 82, 229, 125, 201, 199, 176, 202, 207, 24, 151, 141, 133, 82, - 229, 125, 176, 202, 207, 24, 151, 141, 133, 82, 229, 125, 176, 239, 46, - 24, 151, 141, 229, 125, 82, 133, 176, 202, 207, 24, 151, 141, 82, 133, - 201, 199, 176, 232, 132, 24, 151, 141, 82, 176, 238, 177, 24, 151, 141, - 82, 176, 243, 9, 24, 151, 141, 82, 176, 228, 249, 24, 151, 141, 82, 176, - 229, 124, 24, 151, 176, 248, 210, 141, 82, 201, 52, 24, 151, 141, 82, - 239, 47, 176, 202, 207, 24, 151, 141, 82, 239, 47, 176, 202, 208, 239, - 46, 24, 151, 141, 82, 239, 47, 176, 202, 208, 248, 223, 24, 151, 82, 176, - 228, 250, 141, 196, 77, 24, 151, 141, 176, 228, 250, 82, 196, 77, 24, - 151, 141, 82, 239, 47, 229, 125, 176, 202, 207, 24, 151, 141, 82, 238, - 214, 176, 202, 207, 24, 151, 141, 82, 239, 47, 176, 232, 132, 24, 151, - 141, 82, 239, 47, 238, 178, 176, 232, 132, 24, 151, 82, 176, 238, 178, - 141, 196, 77, 24, 151, 141, 176, 238, 178, 82, 196, 77, 24, 151, 82, 176, - 47, 141, 196, 77, 24, 151, 82, 176, 47, 141, 229, 124, 24, 151, 141, 176, - 251, 114, 211, 15, 82, 196, 77, 24, 151, 141, 176, 251, 114, 223, 163, - 82, 196, 77, 24, 151, 141, 176, 47, 82, 196, 77, 24, 151, 141, 82, 176, - 239, 47, 229, 124, 24, 151, 141, 82, 176, 251, 114, 211, 14, 24, 151, - 141, 82, 176, 251, 113, 24, 151, 82, 176, 251, 114, 211, 15, 141, 196, - 77, 24, 151, 82, 176, 251, 114, 211, 15, 141, 238, 213, 24, 151, 82, 176, - 251, 114, 141, 196, 77, 24, 151, 141, 176, 228, 250, 82, 229, 124, 24, - 230, 41, 232, 128, 232, 247, 24, 230, 41, 232, 128, 232, 248, 248, 223, - 24, 230, 41, 232, 128, 232, 248, 229, 124, 24, 230, 41, 232, 128, 232, - 248, 239, 46, 24, 230, 41, 232, 128, 232, 248, 239, 47, 201, 209, 24, - 230, 48, 232, 128, 232, 248, 239, 46, 24, 151, 232, 128, 232, 248, 239, - 47, 248, 223, 24, 230, 39, 232, 128, 232, 248, 239, 46, 24, 230, 41, 232, - 226, 232, 248, 201, 198, 24, 230, 41, 229, 213, 232, 226, 232, 248, 201, - 198, 24, 230, 41, 232, 226, 232, 248, 201, 199, 232, 128, 248, 223, 24, - 230, 41, 229, 213, 232, 226, 232, 248, 201, 199, 232, 128, 248, 223, 24, - 230, 41, 232, 226, 232, 248, 201, 199, 248, 223, 24, 230, 41, 229, 213, - 232, 226, 232, 248, 201, 199, 248, 223, 24, 230, 41, 232, 226, 232, 248, - 201, 199, 176, 232, 132, 24, 230, 46, 232, 226, 232, 248, 201, 198, 24, - 230, 46, 232, 226, 232, 248, 201, 199, 211, 76, 24, 230, 39, 232, 226, - 232, 248, 201, 199, 211, 76, 24, 230, 35, 232, 226, 232, 248, 201, 198, - 24, 230, 41, 232, 226, 232, 248, 201, 199, 229, 124, 24, 230, 41, 232, - 226, 232, 248, 201, 199, 229, 125, 176, 202, 207, 24, 230, 41, 232, 226, - 232, 248, 201, 199, 229, 125, 213, 44, 198, 212, 24, 230, 40, 24, 230, - 41, 248, 210, 210, 183, 233, 95, 24, 230, 41, 229, 212, 24, 230, 41, 176, - 202, 207, 24, 230, 41, 229, 213, 176, 202, 207, 24, 230, 41, 176, 248, - 223, 24, 230, 41, 176, 232, 132, 24, 230, 41, 201, 210, 141, 176, 202, - 207, 24, 230, 41, 201, 210, 247, 21, 24, 230, 41, 201, 210, 247, 22, 176, - 202, 207, 24, 230, 41, 201, 210, 247, 22, 176, 202, 208, 248, 223, 24, - 230, 41, 201, 210, 219, 82, 24, 230, 47, 24, 230, 48, 176, 202, 207, 24, - 230, 48, 213, 44, 198, 212, 24, 230, 48, 176, 232, 132, 24, 230, 37, 238, - 173, 24, 230, 36, 24, 230, 46, 211, 76, 24, 230, 45, 24, 230, 46, 211, - 77, 176, 202, 207, 24, 230, 46, 176, 202, 207, 24, 230, 46, 211, 77, 213, - 44, 198, 212, 24, 230, 46, 213, 44, 198, 212, 24, 230, 46, 211, 77, 176, - 232, 132, 24, 230, 46, 176, 232, 132, 24, 230, 44, 211, 76, 24, 230, 43, - 24, 230, 49, 24, 230, 34, 24, 230, 35, 176, 202, 207, 24, 230, 35, 213, - 44, 198, 212, 24, 230, 35, 176, 232, 132, 24, 230, 39, 211, 76, 24, 230, - 39, 211, 77, 176, 232, 132, 24, 230, 38, 24, 230, 39, 202, 70, 24, 230, - 39, 211, 77, 176, 202, 207, 24, 230, 39, 176, 202, 207, 24, 230, 39, 211, - 77, 213, 44, 198, 212, 24, 230, 39, 213, 44, 198, 212, 24, 230, 39, 176, - 202, 208, 198, 35, 223, 148, 24, 230, 39, 176, 248, 210, 82, 206, 188, - 24, 230, 51, 24, 151, 141, 82, 206, 188, 24, 230, 50, 141, 82, 206, 188, - 24, 230, 39, 141, 82, 206, 188, 24, 230, 52, 141, 82, 206, 188, 24, 230, - 39, 219, 82, 24, 151, 141, 82, 206, 189, 248, 223, 24, 151, 141, 82, 206, - 189, 239, 46, 24, 230, 39, 141, 82, 206, 189, 239, 46, 24, 151, 219, 83, - 235, 123, 24, 151, 219, 83, 144, 206, 183, 201, 52, 24, 151, 219, 83, - 144, 206, 183, 238, 162, 24, 151, 219, 83, 144, 211, 26, 243, 9, 24, 151, - 219, 83, 196, 77, 24, 151, 176, 196, 105, 219, 83, 196, 77, 24, 230, 50, - 219, 83, 196, 77, 24, 230, 35, 219, 83, 196, 77, 24, 230, 52, 219, 83, - 196, 77, 24, 151, 219, 83, 207, 147, 221, 70, 24, 151, 219, 83, 248, 223, - 24, 151, 219, 83, 198, 36, 198, 212, 24, 151, 219, 83, 198, 212, 24, 230, - 39, 219, 83, 198, 212, 24, 151, 219, 83, 141, 198, 212, 24, 230, 39, 219, - 83, 141, 198, 212, 24, 230, 52, 219, 83, 141, 176, 141, 176, 211, 14, 24, - 230, 52, 219, 83, 141, 176, 141, 198, 212, 24, 151, 219, 83, 223, 148, - 24, 230, 50, 219, 83, 223, 148, 24, 230, 39, 219, 83, 223, 148, 24, 230, - 52, 219, 83, 223, 148, 24, 151, 141, 82, 219, 82, 24, 230, 50, 141, 82, - 219, 82, 24, 230, 39, 141, 82, 219, 82, 24, 230, 39, 206, 188, 24, 230, - 52, 141, 82, 219, 82, 24, 151, 141, 82, 238, 218, 219, 82, 24, 230, 50, - 141, 82, 238, 218, 219, 82, 24, 151, 206, 189, 235, 123, 24, 230, 39, - 206, 189, 144, 141, 176, 228, 251, 216, 84, 24, 230, 52, 206, 189, 144, - 82, 176, 141, 238, 217, 24, 151, 206, 189, 196, 77, 24, 151, 206, 189, - 207, 147, 221, 70, 24, 151, 206, 189, 219, 82, 24, 230, 50, 206, 189, - 219, 82, 24, 230, 35, 206, 189, 219, 82, 24, 230, 52, 206, 189, 219, 82, - 24, 151, 206, 189, 216, 84, 24, 151, 206, 189, 82, 239, 46, 24, 151, 206, - 189, 82, 207, 147, 221, 69, 24, 151, 206, 189, 223, 148, 24, 151, 206, - 189, 198, 212, 24, 230, 37, 206, 189, 198, 212, 24, 151, 141, 206, 189, - 219, 82, 24, 230, 50, 141, 206, 189, 219, 82, 24, 230, 44, 141, 206, 189, - 219, 83, 211, 104, 24, 230, 37, 141, 206, 189, 219, 83, 211, 14, 24, 230, - 37, 141, 206, 189, 219, 83, 223, 162, 24, 230, 37, 141, 206, 189, 219, - 83, 196, 104, 24, 230, 46, 141, 206, 189, 219, 82, 24, 230, 39, 141, 206, - 189, 219, 82, 24, 230, 52, 141, 206, 189, 219, 83, 211, 14, 24, 230, 52, - 141, 206, 189, 219, 82, 24, 151, 82, 235, 123, 24, 230, 39, 216, 84, 24, - 151, 82, 196, 77, 24, 230, 50, 82, 196, 77, 24, 151, 82, 207, 147, 221, - 70, 24, 151, 82, 133, 176, 202, 207, 24, 230, 37, 82, 198, 212, 24, 151, - 82, 176, 219, 82, 24, 151, 82, 219, 82, 24, 151, 82, 206, 189, 219, 82, - 24, 230, 50, 82, 206, 189, 219, 82, 24, 230, 44, 82, 206, 189, 219, 83, - 211, 104, 24, 230, 46, 82, 206, 189, 219, 82, 24, 230, 39, 82, 206, 189, - 219, 82, 24, 230, 52, 82, 206, 189, 219, 83, 211, 14, 24, 230, 52, 82, - 206, 189, 219, 83, 223, 162, 24, 230, 52, 82, 206, 189, 219, 82, 24, 230, - 50, 82, 206, 189, 219, 83, 248, 223, 24, 230, 48, 82, 206, 189, 219, 83, - 239, 46, 24, 230, 48, 82, 206, 189, 219, 83, 239, 47, 202, 207, 24, 230, - 37, 82, 206, 189, 219, 83, 239, 47, 211, 14, 24, 230, 37, 82, 206, 189, - 219, 83, 239, 47, 223, 162, 24, 230, 37, 82, 206, 189, 219, 83, 239, 46, - 24, 230, 39, 141, 229, 124, 24, 151, 141, 176, 202, 207, 24, 230, 39, - 141, 176, 202, 207, 24, 151, 141, 176, 202, 208, 176, 237, 38, 24, 151, - 141, 176, 202, 208, 176, 239, 46, 24, 151, 141, 176, 202, 208, 176, 248, - 223, 24, 151, 141, 176, 202, 208, 141, 248, 223, 24, 151, 141, 176, 202, - 208, 248, 80, 248, 223, 24, 151, 141, 176, 202, 208, 141, 229, 126, 24, - 151, 141, 176, 232, 133, 141, 201, 52, 24, 151, 141, 176, 232, 133, 141, - 248, 223, 24, 151, 141, 176, 102, 24, 151, 141, 176, 238, 173, 24, 151, - 141, 176, 238, 165, 176, 223, 117, 24, 230, 48, 141, 176, 238, 165, 176, - 223, 117, 24, 151, 141, 176, 238, 165, 176, 196, 104, 24, 151, 141, 176, - 243, 10, 24, 230, 46, 141, 198, 212, 24, 230, 46, 141, 176, 211, 76, 24, - 230, 39, 141, 176, 211, 76, 24, 230, 39, 141, 176, 220, 12, 24, 230, 39, - 141, 198, 212, 24, 230, 39, 141, 176, 202, 70, 24, 230, 52, 141, 176, - 211, 14, 24, 230, 52, 141, 176, 223, 162, 24, 230, 52, 141, 198, 212, 24, - 151, 198, 212, 24, 151, 176, 229, 212, 24, 151, 176, 202, 208, 237, 38, - 24, 151, 176, 202, 208, 239, 46, 24, 151, 176, 202, 208, 248, 223, 24, - 151, 176, 232, 132, 24, 151, 176, 248, 210, 141, 216, 84, 24, 151, 176, - 248, 210, 82, 206, 188, 24, 151, 176, 248, 210, 206, 189, 219, 82, 24, - 151, 176, 196, 105, 105, 232, 247, 24, 151, 176, 139, 105, 232, 247, 24, - 151, 176, 196, 105, 115, 232, 247, 24, 151, 176, 196, 105, 232, 128, 232, - 247, 24, 151, 176, 139, 232, 128, 207, 147, 221, 69, 24, 230, 42, 24, - 151, 229, 212, 24, 198, 37, 202, 169, 24, 198, 37, 215, 128, 24, 198, 37, - 248, 209, 24, 230, 215, 202, 169, 24, 230, 215, 215, 128, 24, 230, 215, - 248, 209, 24, 201, 33, 202, 169, 24, 201, 33, 215, 128, 24, 201, 33, 248, - 209, 24, 248, 18, 202, 169, 24, 248, 18, 215, 128, 24, 248, 18, 248, 209, - 24, 206, 60, 202, 169, 24, 206, 60, 215, 128, 24, 206, 60, 248, 209, 24, - 200, 171, 200, 76, 24, 200, 171, 248, 209, 24, 201, 186, 220, 13, 202, - 169, 24, 201, 186, 2, 202, 169, 24, 201, 186, 220, 13, 215, 128, 24, 201, - 186, 2, 215, 128, 24, 201, 186, 204, 6, 24, 232, 197, 220, 13, 202, 169, - 24, 232, 197, 2, 202, 169, 24, 232, 197, 220, 13, 215, 128, 24, 232, 197, - 2, 215, 128, 24, 232, 197, 204, 6, 24, 201, 186, 232, 197, 251, 154, 24, - 215, 172, 133, 144, 220, 12, 24, 215, 172, 133, 144, 202, 70, 24, 215, - 172, 133, 204, 6, 24, 215, 172, 144, 204, 6, 24, 215, 172, 133, 144, 251, - 155, 220, 12, 24, 215, 172, 133, 144, 251, 155, 202, 70, 24, 215, 172, - 202, 208, 119, 202, 208, 205, 84, 24, 215, 171, 232, 253, 239, 35, 24, - 215, 173, 232, 253, 239, 35, 24, 215, 171, 202, 170, 201, 53, 202, 70, - 24, 215, 171, 202, 170, 201, 53, 216, 212, 24, 215, 171, 202, 170, 201, - 53, 220, 12, 24, 215, 171, 202, 170, 201, 53, 220, 10, 24, 215, 171, 202, - 170, 193, 4, 232, 200, 24, 215, 171, 55, 201, 52, 24, 215, 171, 55, 193, - 4, 232, 200, 24, 215, 171, 55, 251, 154, 24, 215, 171, 55, 251, 155, 193, - 4, 232, 200, 24, 215, 171, 238, 217, 24, 215, 171, 197, 225, 201, 53, - 215, 175, 24, 215, 171, 197, 225, 193, 4, 232, 200, 24, 215, 171, 197, - 225, 251, 154, 24, 215, 171, 197, 225, 251, 155, 193, 4, 232, 200, 24, - 215, 171, 248, 228, 202, 70, 24, 215, 171, 248, 228, 216, 212, 24, 215, - 171, 248, 228, 220, 12, 24, 215, 171, 239, 2, 202, 70, 24, 215, 171, 239, - 2, 216, 212, 24, 215, 171, 239, 2, 220, 12, 24, 215, 171, 239, 2, 206, - 120, 24, 215, 171, 243, 126, 202, 70, 24, 215, 171, 243, 126, 216, 212, - 24, 215, 171, 243, 126, 220, 12, 24, 215, 171, 111, 202, 70, 24, 215, - 171, 111, 216, 212, 24, 215, 171, 111, 220, 12, 24, 215, 171, 191, 21, - 202, 70, 24, 215, 171, 191, 21, 216, 212, 24, 215, 171, 191, 21, 220, 12, - 24, 215, 171, 210, 57, 202, 70, 24, 215, 171, 210, 57, 216, 212, 24, 215, - 171, 210, 57, 220, 12, 24, 198, 3, 206, 118, 202, 169, 24, 198, 3, 206, - 118, 235, 133, 24, 198, 3, 206, 118, 251, 154, 24, 198, 3, 206, 119, 202, - 169, 24, 198, 3, 206, 119, 235, 133, 24, 198, 3, 206, 119, 251, 154, 24, - 198, 3, 203, 144, 24, 198, 3, 250, 251, 201, 218, 202, 169, 24, 198, 3, - 250, 251, 201, 218, 235, 133, 24, 198, 3, 250, 251, 201, 218, 197, 224, - 24, 215, 174, 250, 139, 202, 70, 24, 215, 174, 250, 139, 216, 212, 24, - 215, 174, 250, 139, 220, 12, 24, 215, 174, 250, 139, 220, 10, 24, 215, - 174, 198, 31, 202, 70, 24, 215, 174, 198, 31, 216, 212, 24, 215, 174, - 198, 31, 220, 12, 24, 215, 174, 198, 31, 220, 10, 24, 215, 174, 248, 210, - 250, 139, 202, 70, 24, 215, 174, 248, 210, 250, 139, 216, 212, 24, 215, - 174, 248, 210, 250, 139, 220, 12, 24, 215, 174, 248, 210, 250, 139, 220, - 10, 24, 215, 174, 248, 210, 198, 31, 202, 70, 24, 215, 174, 248, 210, - 198, 31, 216, 212, 24, 215, 174, 248, 210, 198, 31, 220, 12, 24, 215, - 174, 248, 210, 198, 31, 220, 10, 24, 215, 173, 202, 170, 201, 53, 202, - 70, 24, 215, 173, 202, 170, 201, 53, 216, 212, 24, 215, 173, 202, 170, - 201, 53, 220, 12, 24, 215, 173, 202, 170, 201, 53, 220, 10, 24, 215, 173, - 202, 170, 193, 4, 232, 200, 24, 215, 173, 55, 201, 52, 24, 215, 173, 55, - 193, 4, 232, 200, 24, 215, 173, 55, 251, 154, 24, 215, 173, 55, 251, 155, - 193, 4, 232, 200, 24, 215, 173, 238, 217, 24, 215, 173, 197, 225, 201, - 53, 215, 175, 24, 215, 173, 197, 225, 193, 4, 232, 200, 24, 215, 173, - 197, 225, 251, 155, 215, 175, 24, 215, 173, 197, 225, 251, 155, 193, 4, - 232, 200, 24, 215, 173, 248, 227, 24, 215, 173, 239, 2, 202, 70, 24, 215, - 173, 239, 2, 216, 212, 24, 215, 173, 239, 2, 220, 12, 24, 215, 173, 243, - 125, 24, 215, 173, 111, 202, 70, 24, 215, 173, 111, 216, 212, 24, 215, - 173, 111, 220, 12, 24, 215, 173, 191, 21, 202, 70, 24, 215, 173, 191, 21, - 216, 212, 24, 215, 173, 191, 21, 220, 12, 24, 215, 173, 210, 57, 202, 70, - 24, 215, 173, 210, 57, 216, 212, 24, 215, 173, 210, 57, 220, 12, 24, 198, - 4, 206, 119, 202, 169, 24, 198, 4, 206, 119, 235, 133, 24, 198, 4, 206, - 119, 251, 154, 24, 198, 4, 206, 118, 202, 169, 24, 198, 4, 206, 118, 235, - 133, 24, 198, 4, 206, 118, 251, 154, 24, 198, 4, 203, 144, 24, 215, 171, - 238, 165, 208, 23, 202, 70, 24, 215, 171, 238, 165, 208, 23, 216, 212, - 24, 215, 171, 238, 165, 208, 23, 220, 12, 24, 215, 171, 238, 165, 208, - 23, 220, 10, 24, 215, 171, 238, 165, 230, 67, 202, 70, 24, 215, 171, 238, - 165, 230, 67, 216, 212, 24, 215, 171, 238, 165, 230, 67, 220, 12, 24, - 215, 171, 238, 165, 230, 67, 220, 10, 24, 215, 171, 238, 165, 198, 218, - 243, 11, 202, 70, 24, 215, 171, 238, 165, 198, 218, 243, 11, 216, 212, - 24, 215, 171, 228, 143, 202, 70, 24, 215, 171, 228, 143, 216, 212, 24, - 215, 171, 228, 143, 220, 12, 24, 215, 171, 219, 5, 202, 70, 24, 215, 171, - 219, 5, 216, 212, 24, 215, 171, 219, 5, 220, 12, 24, 215, 171, 219, 5, 2, - 235, 133, 24, 215, 171, 193, 139, 238, 165, 55, 202, 70, 24, 215, 171, - 193, 139, 238, 165, 55, 216, 212, 24, 215, 171, 193, 139, 238, 165, 55, - 220, 12, 24, 215, 171, 193, 139, 238, 165, 197, 225, 202, 70, 24, 215, - 171, 193, 139, 238, 165, 197, 225, 216, 212, 24, 215, 171, 193, 139, 238, - 165, 197, 225, 220, 12, 24, 215, 171, 238, 165, 199, 25, 201, 52, 24, - 215, 171, 238, 163, 238, 218, 202, 70, 24, 215, 171, 238, 163, 238, 218, - 216, 212, 24, 206, 118, 202, 169, 24, 206, 118, 235, 133, 24, 206, 118, - 251, 156, 24, 215, 171, 203, 144, 24, 215, 171, 238, 165, 229, 116, 232, - 97, 193, 167, 24, 215, 171, 228, 143, 229, 116, 232, 97, 193, 167, 24, - 215, 171, 219, 5, 229, 116, 232, 97, 193, 167, 24, 215, 171, 193, 139, - 229, 116, 232, 97, 193, 167, 24, 206, 118, 202, 170, 229, 116, 232, 97, - 193, 167, 24, 206, 118, 55, 229, 116, 232, 97, 193, 167, 24, 206, 118, - 251, 155, 229, 116, 232, 97, 193, 167, 24, 215, 171, 238, 165, 229, 116, - 243, 104, 24, 215, 171, 228, 143, 229, 116, 243, 104, 24, 215, 171, 219, - 5, 229, 116, 243, 104, 24, 215, 171, 193, 139, 229, 116, 243, 104, 24, - 206, 118, 202, 170, 229, 116, 243, 104, 24, 206, 118, 55, 229, 116, 243, - 104, 24, 206, 118, 251, 155, 229, 116, 243, 104, 24, 215, 171, 193, 139, - 237, 39, 210, 86, 202, 70, 24, 215, 171, 193, 139, 237, 39, 210, 86, 216, - 212, 24, 215, 171, 193, 139, 237, 39, 210, 86, 220, 12, 24, 215, 173, - 238, 165, 229, 116, 247, 31, 202, 70, 24, 215, 173, 238, 165, 229, 116, - 247, 31, 220, 12, 24, 215, 173, 228, 143, 229, 116, 247, 31, 2, 235, 133, - 24, 215, 173, 228, 143, 229, 116, 247, 31, 220, 13, 235, 133, 24, 215, - 173, 228, 143, 229, 116, 247, 31, 2, 197, 224, 24, 215, 173, 228, 143, - 229, 116, 247, 31, 220, 13, 197, 224, 24, 215, 173, 219, 5, 229, 116, - 247, 31, 2, 202, 169, 24, 215, 173, 219, 5, 229, 116, 247, 31, 220, 13, - 202, 169, 24, 215, 173, 219, 5, 229, 116, 247, 31, 2, 235, 133, 24, 215, - 173, 219, 5, 229, 116, 247, 31, 220, 13, 235, 133, 24, 215, 173, 193, - 139, 229, 116, 247, 31, 202, 70, 24, 215, 173, 193, 139, 229, 116, 247, - 31, 220, 12, 24, 206, 119, 202, 170, 229, 116, 247, 30, 24, 206, 119, 55, - 229, 116, 247, 30, 24, 206, 119, 251, 155, 229, 116, 247, 30, 24, 215, - 173, 238, 165, 229, 116, 232, 194, 202, 70, 24, 215, 173, 238, 165, 229, - 116, 232, 194, 220, 12, 24, 215, 173, 228, 143, 229, 116, 232, 194, 2, - 235, 133, 24, 215, 173, 228, 143, 229, 116, 232, 194, 220, 13, 235, 133, - 24, 215, 173, 228, 143, 229, 116, 232, 194, 197, 225, 2, 197, 224, 24, - 215, 173, 228, 143, 229, 116, 232, 194, 197, 225, 220, 13, 197, 224, 24, - 215, 173, 219, 5, 229, 116, 232, 194, 2, 202, 169, 24, 215, 173, 219, 5, - 229, 116, 232, 194, 220, 13, 202, 169, 24, 215, 173, 219, 5, 229, 116, - 232, 194, 2, 235, 133, 24, 215, 173, 219, 5, 229, 116, 232, 194, 220, 13, - 235, 133, 24, 215, 173, 193, 139, 229, 116, 232, 194, 202, 70, 24, 215, - 173, 193, 139, 229, 116, 232, 194, 220, 12, 24, 206, 119, 202, 170, 229, - 116, 232, 193, 24, 206, 119, 55, 229, 116, 232, 193, 24, 206, 119, 251, - 155, 229, 116, 232, 193, 24, 215, 173, 238, 165, 202, 70, 24, 215, 173, - 238, 165, 216, 212, 24, 215, 173, 238, 165, 220, 12, 24, 215, 173, 238, - 165, 220, 10, 24, 215, 173, 238, 165, 242, 78, 24, 215, 173, 228, 143, - 202, 70, 24, 215, 173, 219, 5, 202, 70, 24, 215, 173, 193, 139, 202, 58, - 24, 215, 173, 193, 139, 202, 70, 24, 215, 173, 193, 139, 220, 12, 24, - 206, 119, 202, 169, 24, 206, 119, 235, 133, 24, 206, 119, 251, 154, 24, - 215, 173, 203, 145, 210, 118, 24, 215, 171, 250, 251, 243, 11, 2, 202, - 169, 24, 215, 171, 250, 251, 243, 11, 216, 213, 202, 169, 24, 215, 171, - 250, 251, 243, 11, 2, 235, 133, 24, 215, 171, 250, 251, 243, 11, 216, - 213, 235, 133, 24, 215, 173, 250, 251, 243, 11, 229, 116, 193, 168, 2, - 202, 169, 24, 215, 173, 250, 251, 243, 11, 229, 116, 193, 168, 216, 213, - 202, 169, 24, 215, 173, 250, 251, 243, 11, 229, 116, 193, 168, 220, 13, - 202, 169, 24, 215, 173, 250, 251, 243, 11, 229, 116, 193, 168, 2, 235, - 133, 24, 215, 173, 250, 251, 243, 11, 229, 116, 193, 168, 216, 213, 235, - 133, 24, 215, 173, 250, 251, 243, 11, 229, 116, 193, 168, 220, 13, 235, - 133, 24, 215, 171, 193, 4, 243, 11, 232, 97, 202, 169, 24, 215, 171, 193, - 4, 243, 11, 232, 97, 235, 133, 24, 215, 173, 193, 4, 243, 11, 229, 116, - 193, 168, 202, 169, 24, 215, 173, 193, 4, 243, 11, 229, 116, 193, 168, - 235, 133, 24, 215, 171, 232, 253, 243, 8, 202, 169, 24, 215, 171, 232, - 253, 243, 8, 235, 133, 24, 215, 173, 232, 253, 243, 8, 229, 116, 193, - 168, 202, 169, 24, 215, 173, 232, 253, 243, 8, 229, 116, 193, 168, 235, - 133, 24, 235, 40, 250, 236, 202, 70, 24, 235, 40, 250, 236, 220, 12, 24, - 235, 40, 233, 73, 24, 235, 40, 202, 75, 24, 235, 40, 199, 88, 24, 235, - 40, 207, 63, 24, 235, 40, 202, 176, 24, 235, 40, 202, 177, 251, 154, 24, - 235, 40, 233, 225, 211, 27, 198, 146, 24, 235, 40, 230, 226, 24, 229, - 235, 24, 229, 236, 206, 193, 24, 229, 236, 215, 171, 201, 52, 24, 229, - 236, 215, 171, 198, 149, 24, 229, 236, 215, 173, 201, 52, 24, 229, 236, - 215, 171, 238, 164, 24, 229, 236, 215, 173, 238, 164, 24, 229, 236, 215, - 176, 243, 10, 24, 233, 104, 236, 233, 209, 25, 213, 14, 232, 133, 198, - 147, 24, 233, 104, 236, 233, 209, 25, 213, 14, 133, 211, 57, 235, 123, - 24, 233, 104, 236, 233, 209, 25, 213, 14, 133, 211, 57, 144, 198, 147, - 24, 233, 191, 201, 53, 196, 77, 24, 233, 191, 201, 53, 214, 81, 24, 233, - 191, 201, 53, 235, 123, 24, 235, 107, 233, 191, 214, 82, 235, 123, 24, - 235, 107, 233, 191, 144, 214, 81, 24, 235, 107, 233, 191, 133, 214, 81, - 24, 235, 107, 233, 191, 214, 82, 196, 77, 24, 232, 151, 214, 81, 24, 232, - 151, 239, 35, 24, 232, 151, 193, 7, 24, 233, 186, 211, 76, 24, 233, 186, - 201, 185, 24, 233, 186, 242, 218, 24, 233, 194, 248, 130, 202, 169, 24, - 233, 194, 248, 130, 215, 128, 24, 233, 186, 132, 211, 76, 24, 233, 186, - 193, 78, 211, 76, 24, 233, 186, 132, 242, 218, 24, 233, 186, 193, 76, - 215, 175, 24, 233, 194, 193, 58, 24, 233, 187, 196, 77, 24, 233, 187, - 235, 123, 24, 233, 187, 232, 180, 24, 233, 189, 201, 52, 24, 233, 189, - 201, 53, 235, 133, 24, 233, 189, 201, 53, 251, 154, 24, 233, 190, 201, - 52, 24, 233, 190, 201, 53, 235, 133, 24, 233, 190, 201, 53, 251, 154, 24, - 233, 189, 238, 162, 24, 233, 190, 238, 162, 24, 233, 189, 243, 5, 24, - 243, 121, 208, 155, 24, 243, 121, 214, 81, 24, 243, 121, 200, 218, 24, - 199, 89, 243, 121, 229, 135, 24, 199, 89, 243, 121, 216, 84, 24, 199, 89, - 243, 121, 218, 241, 24, 234, 209, 24, 213, 14, 214, 81, 24, 213, 14, 239, - 35, 24, 213, 14, 193, 5, 24, 213, 14, 193, 73, 24, 251, 226, 248, 116, - 211, 14, 24, 251, 226, 200, 217, 223, 162, 24, 251, 226, 248, 118, 2, - 206, 117, 24, 251, 226, 200, 219, 2, 206, 117, 24, 248, 39, 223, 134, 24, - 248, 39, 233, 214, 24, 215, 180, 242, 219, 214, 81, 24, 215, 180, 242, - 219, 232, 132, 24, 215, 180, 242, 219, 239, 35, 24, 215, 180, 202, 65, - 24, 215, 180, 202, 66, 193, 7, 24, 215, 180, 202, 66, 211, 76, 24, 215, - 180, 232, 93, 24, 215, 180, 232, 94, 193, 7, 24, 215, 180, 232, 94, 211, - 76, 24, 215, 180, 211, 77, 243, 10, 24, 215, 180, 211, 77, 232, 132, 24, - 215, 180, 211, 77, 193, 7, 24, 215, 180, 211, 77, 211, 7, 24, 215, 180, - 211, 77, 211, 8, 193, 7, 24, 215, 180, 211, 77, 211, 8, 192, 88, 24, 215, - 180, 211, 77, 207, 92, 24, 215, 180, 211, 77, 207, 93, 193, 7, 24, 215, - 180, 211, 77, 207, 93, 192, 88, 24, 215, 180, 221, 122, 24, 215, 180, - 221, 123, 232, 132, 24, 215, 180, 221, 123, 193, 7, 24, 215, 180, 199, - 88, 24, 215, 180, 199, 89, 232, 132, 24, 215, 180, 199, 89, 200, 218, 24, - 219, 97, 208, 219, 198, 87, 24, 219, 99, 110, 139, 196, 74, 24, 219, 99, - 116, 139, 218, 236, 24, 215, 180, 239, 0, 24, 215, 180, 193, 6, 202, 169, - 24, 215, 180, 193, 6, 235, 133, 24, 198, 62, 201, 74, 211, 15, 233, 75, - 24, 198, 62, 219, 142, 219, 96, 24, 198, 62, 198, 136, 248, 210, 219, 96, - 24, 198, 62, 198, 136, 198, 35, 223, 118, 215, 179, 24, 198, 62, 223, - 118, 215, 180, 207, 63, 24, 198, 62, 215, 170, 251, 251, 243, 122, 24, - 198, 62, 247, 22, 201, 74, 211, 14, 24, 198, 62, 247, 22, 223, 118, 215, - 179, 24, 199, 117, 24, 199, 118, 215, 175, 24, 199, 118, 211, 105, 198, - 61, 24, 199, 118, 211, 105, 198, 62, 215, 175, 24, 199, 118, 211, 105, - 219, 96, 24, 199, 118, 211, 105, 219, 97, 215, 175, 24, 199, 118, 248, - 146, 219, 96, 24, 215, 171, 223, 14, 24, 215, 173, 223, 14, 24, 214, 112, - 24, 230, 78, 24, 233, 217, 24, 203, 22, 229, 123, 201, 219, 24, 203, 22, - 229, 123, 209, 23, 24, 193, 165, 203, 22, 229, 123, 215, 178, 24, 232, - 192, 203, 22, 229, 123, 215, 178, 24, 203, 22, 198, 148, 232, 98, 193, - 172, 24, 198, 43, 201, 53, 201, 37, 24, 198, 43, 238, 163, 248, 227, 24, - 198, 44, 197, 16, 24, 116, 248, 105, 198, 148, 232, 98, 229, 123, 222, - 195, 24, 219, 124, 242, 79, 24, 219, 124, 219, 197, 24, 219, 124, 219, - 196, 24, 219, 124, 219, 195, 24, 219, 124, 219, 194, 24, 219, 124, 219, - 193, 24, 219, 124, 219, 192, 24, 219, 124, 219, 191, 24, 232, 252, 24, - 219, 37, 201, 247, 24, 219, 38, 201, 247, 24, 219, 40, 229, 208, 24, 219, - 40, 193, 74, 24, 219, 40, 237, 92, 24, 219, 40, 229, 236, 214, 112, 24, - 219, 40, 198, 45, 24, 219, 40, 219, 123, 237, 9, 24, 242, 74, 24, 232, - 80, 201, 63, 24, 204, 25, 24, 242, 83, 24, 210, 113, 24, 233, 6, 215, - 244, 24, 233, 6, 215, 243, 24, 233, 6, 215, 242, 24, 233, 6, 215, 241, - 24, 233, 6, 215, 240, 24, 206, 121, 215, 244, 24, 206, 121, 215, 243, 24, - 206, 121, 215, 242, 24, 206, 121, 215, 241, 24, 206, 121, 215, 240, 24, - 206, 121, 215, 239, 24, 206, 121, 215, 238, 24, 206, 121, 215, 237, 24, - 206, 121, 215, 251, 24, 206, 121, 215, 250, 24, 206, 121, 215, 249, 24, - 206, 121, 215, 248, 24, 206, 121, 215, 247, 24, 206, 121, 215, 246, 24, - 206, 121, 215, 245, 8, 2, 1, 233, 37, 237, 3, 4, 197, 228, 8, 2, 1, 207, - 18, 27, 232, 51, 8, 1, 2, 6, 153, 232, 51, 8, 2, 1, 207, 18, 222, 152, 8, - 1, 2, 6, 220, 143, 4, 248, 231, 8, 2, 1, 219, 163, 4, 207, 24, 102, 8, 2, - 1, 153, 192, 160, 4, 248, 231, 8, 2, 1, 207, 18, 234, 88, 8, 2, 1, 153, - 207, 222, 4, 179, 219, 213, 23, 207, 24, 102, 8, 2, 1, 200, 44, 4, 228, - 251, 23, 207, 24, 102, 8, 1, 207, 24, 242, 232, 4, 207, 24, 102, 8, 2, 1, - 234, 13, 4, 55, 164, 8, 2, 1, 234, 13, 4, 55, 249, 88, 23, 238, 175, 8, - 2, 1, 153, 200, 44, 4, 238, 175, 8, 1, 223, 93, 231, 11, 201, 64, 4, 238, - 175, 8, 1, 201, 36, 247, 194, 4, 238, 175, 8, 1, 2, 6, 153, 222, 152, 8, - 2, 1, 220, 143, 4, 232, 233, 8, 2, 1, 237, 70, 237, 3, 4, 210, 192, 102, - 8, 2, 1, 220, 143, 4, 248, 232, 23, 210, 192, 102, 8, 2, 1, 234, 89, 4, - 210, 192, 102, 8, 2, 1, 153, 207, 222, 4, 210, 192, 102, 8, 2, 1, 207, - 222, 4, 232, 234, 23, 210, 192, 102, 8, 2, 1, 199, 79, 237, 3, 4, 210, - 192, 102, 8, 2, 1, 233, 179, 4, 210, 192, 102, 8, 2, 1, 237, 70, 237, 3, - 4, 207, 24, 102, 8, 2, 1, 228, 74, 4, 201, 28, 23, 207, 24, 102, 8, 2, 1, - 187, 4, 207, 24, 102, 8, 2, 1, 199, 79, 237, 3, 4, 207, 24, 102, 8, 2, 1, - 247, 194, 4, 207, 24, 102, 8, 2, 1, 206, 9, 4, 238, 175, 8, 2, 1, 238, - 128, 4, 216, 86, 45, 102, 8, 2, 1, 220, 143, 4, 216, 86, 45, 102, 8, 2, - 1, 215, 62, 4, 216, 86, 45, 102, 8, 2, 1, 207, 222, 4, 216, 86, 45, 102, - 8, 2, 1, 206, 9, 4, 216, 86, 45, 102, 8, 2, 1, 200, 44, 4, 216, 86, 45, - 102, 33, 135, 1, 250, 122, 33, 135, 1, 247, 252, 33, 135, 1, 195, 151, - 33, 135, 1, 231, 18, 33, 135, 1, 236, 169, 33, 135, 1, 192, 49, 33, 135, - 1, 191, 55, 33, 135, 1, 191, 82, 33, 135, 1, 223, 39, 33, 135, 1, 89, - 223, 39, 33, 135, 1, 68, 33, 135, 1, 236, 190, 33, 135, 1, 222, 94, 33, - 135, 1, 219, 75, 33, 135, 1, 215, 66, 33, 135, 1, 214, 210, 33, 135, 1, - 211, 89, 33, 135, 1, 209, 55, 33, 135, 1, 206, 179, 33, 135, 1, 202, 77, - 33, 135, 1, 197, 44, 33, 135, 1, 196, 124, 33, 135, 1, 232, 101, 33, 135, - 1, 229, 188, 33, 135, 1, 203, 8, 33, 135, 1, 197, 146, 33, 135, 1, 243, - 54, 33, 135, 1, 203, 165, 33, 135, 1, 192, 58, 33, 135, 1, 192, 60, 33, - 135, 1, 192, 93, 33, 135, 1, 191, 225, 33, 135, 1, 2, 191, 190, 33, 135, - 1, 192, 12, 33, 135, 1, 223, 82, 2, 191, 190, 33, 135, 1, 248, 175, 191, - 190, 33, 135, 1, 223, 82, 248, 175, 191, 190, 33, 135, 1, 232, 228, 52, - 1, 38, 2, 65, 52, 1, 38, 2, 249, 17, 52, 1, 38, 2, 195, 153, 52, 1, 38, - 2, 231, 77, 52, 1, 38, 2, 237, 146, 52, 1, 38, 2, 223, 226, 52, 1, 38, 2, - 191, 62, 52, 1, 38, 2, 191, 87, 52, 1, 38, 2, 68, 52, 1, 38, 2, 155, 52, - 1, 38, 2, 234, 140, 52, 1, 38, 2, 234, 114, 52, 1, 38, 2, 74, 52, 1, 38, - 2, 210, 63, 52, 1, 38, 2, 234, 34, 52, 1, 38, 2, 234, 22, 52, 1, 38, 2, - 199, 145, 52, 1, 38, 2, 66, 52, 1, 38, 2, 234, 181, 52, 1, 38, 2, 140, - 52, 1, 38, 2, 197, 161, 52, 1, 38, 2, 243, 127, 52, 1, 38, 2, 203, 165, - 52, 1, 38, 2, 192, 58, 52, 1, 38, 2, 71, 52, 1, 38, 2, 191, 225, 52, 1, - 38, 2, 235, 17, 52, 1, 38, 2, 205, 86, 52, 1, 38, 2, 247, 203, 68, 52, 1, - 38, 2, 223, 10, 52, 1, 38, 2, 249, 82, 74, 52, 1, 38, 2, 201, 53, 66, 52, - 1, 38, 2, 210, 179, 38, 200, 230, 2, 1, 65, 38, 200, 230, 2, 1, 249, 17, - 38, 200, 230, 2, 1, 195, 153, 38, 200, 230, 2, 1, 231, 77, 38, 200, 230, - 2, 1, 237, 146, 38, 200, 230, 2, 1, 223, 226, 38, 200, 230, 2, 1, 191, - 62, 38, 200, 230, 2, 1, 191, 87, 38, 200, 230, 2, 1, 68, 38, 200, 230, 2, - 1, 155, 38, 200, 230, 2, 1, 234, 140, 38, 200, 230, 2, 1, 74, 38, 200, - 230, 2, 1, 210, 63, 38, 200, 230, 2, 1, 234, 22, 38, 200, 230, 2, 1, 66, - 38, 200, 230, 2, 1, 234, 181, 38, 200, 230, 2, 1, 140, 38, 200, 230, 2, - 1, 197, 161, 38, 200, 230, 2, 1, 243, 127, 38, 200, 230, 2, 1, 203, 165, - 38, 200, 230, 2, 1, 230, 17, 56, 38, 200, 230, 2, 1, 192, 58, 38, 200, - 230, 2, 1, 231, 78, 4, 196, 69, 38, 200, 230, 2, 1, 247, 203, 68, 38, - 200, 230, 2, 1, 235, 32, 38, 200, 230, 2, 1, 235, 28, 52, 1, 38, 2, 234, - 23, 4, 237, 87, 52, 1, 38, 2, 192, 59, 4, 249, 147, 192, 62, 52, 1, 38, - 2, 201, 53, 126, 4, 106, 33, 38, 2, 1, 247, 203, 68, 212, 80, 208, 162, - 90, 1, 174, 212, 80, 208, 162, 90, 1, 197, 168, 212, 80, 208, 162, 90, 1, - 212, 199, 212, 80, 208, 162, 90, 1, 190, 190, 212, 80, 208, 162, 90, 1, - 140, 212, 80, 208, 162, 90, 1, 180, 212, 80, 208, 162, 90, 1, 192, 220, - 212, 80, 208, 162, 90, 1, 213, 111, 212, 80, 208, 162, 90, 1, 247, 160, - 212, 80, 208, 162, 90, 1, 173, 212, 80, 208, 162, 90, 1, 188, 212, 80, - 208, 162, 90, 1, 191, 123, 212, 80, 208, 162, 90, 1, 214, 166, 212, 80, - 208, 162, 90, 1, 212, 186, 212, 80, 208, 162, 90, 1, 155, 212, 80, 208, - 162, 90, 1, 238, 32, 212, 80, 208, 162, 90, 1, 212, 101, 212, 80, 208, - 162, 90, 1, 212, 244, 212, 80, 208, 162, 90, 1, 195, 188, 212, 80, 208, - 162, 90, 1, 212, 180, 212, 80, 208, 162, 90, 1, 197, 8, 212, 80, 208, - 162, 90, 1, 233, 109, 212, 80, 208, 162, 90, 1, 165, 212, 80, 208, 162, - 90, 1, 208, 96, 212, 80, 208, 162, 90, 1, 170, 212, 80, 208, 162, 90, 1, - 212, 246, 212, 80, 208, 162, 90, 1, 168, 212, 80, 208, 162, 90, 1, 192, - 175, 212, 80, 208, 162, 90, 1, 212, 248, 212, 80, 208, 162, 90, 1, 236, - 186, 212, 80, 208, 162, 90, 1, 212, 247, 212, 80, 208, 162, 90, 1, 230, - 81, 212, 80, 208, 162, 90, 1, 216, 19, 212, 80, 208, 162, 90, 1, 209, - 110, 212, 80, 208, 162, 90, 1, 231, 240, 212, 80, 208, 162, 90, 1, 206, - 109, 212, 80, 208, 162, 90, 1, 65, 212, 80, 208, 162, 90, 1, 252, 206, - 212, 80, 208, 162, 90, 1, 68, 212, 80, 208, 162, 90, 1, 66, 212, 80, 208, - 162, 90, 1, 74, 212, 80, 208, 162, 90, 1, 211, 87, 212, 80, 208, 162, 90, - 1, 71, 212, 80, 208, 162, 90, 1, 234, 188, 212, 80, 208, 162, 90, 1, 193, - 224, 212, 80, 208, 162, 90, 198, 70, 212, 80, 208, 162, 90, 198, 66, 212, - 80, 208, 162, 90, 198, 67, 212, 80, 208, 162, 90, 198, 64, 212, 80, 208, - 162, 90, 198, 65, 212, 80, 208, 162, 90, 198, 68, 212, 80, 208, 162, 90, - 198, 69, 212, 80, 208, 162, 90, 3, 40, 209, 250, 212, 80, 208, 162, 90, - 3, 40, 199, 3, 212, 80, 208, 162, 90, 3, 40, 219, 39, 212, 80, 208, 162, - 90, 3, 40, 251, 101, 212, 80, 208, 162, 90, 3, 40, 223, 94, 212, 80, 208, - 162, 90, 3, 192, 183, 192, 182, 212, 80, 208, 162, 90, 5, 219, 190, 212, - 80, 208, 162, 90, 17, 191, 77, 212, 80, 208, 162, 90, 17, 107, 212, 80, - 208, 162, 90, 17, 109, 212, 80, 208, 162, 90, 17, 138, 212, 80, 208, 162, - 90, 17, 134, 212, 80, 208, 162, 90, 17, 149, 212, 80, 208, 162, 90, 17, - 169, 212, 80, 208, 162, 90, 17, 175, 212, 80, 208, 162, 90, 17, 171, 212, - 80, 208, 162, 90, 17, 178, 212, 80, 208, 162, 90, 219, 28, 212, 96, 212, - 80, 208, 162, 90, 47, 247, 160, 198, 38, 1, 168, 198, 38, 1, 249, 153, - 198, 38, 1, 190, 190, 198, 38, 1, 238, 32, 198, 38, 1, 155, 198, 38, 1, - 231, 240, 198, 38, 1, 174, 198, 38, 1, 180, 198, 38, 1, 214, 68, 198, 38, - 1, 188, 198, 38, 1, 247, 1, 198, 38, 1, 170, 198, 38, 1, 193, 190, 198, - 38, 1, 223, 32, 198, 38, 1, 140, 198, 38, 1, 165, 198, 38, 1, 173, 198, - 38, 1, 68, 198, 38, 1, 248, 38, 68, 198, 38, 1, 223, 49, 198, 38, 1, 248, - 38, 223, 49, 198, 38, 1, 66, 198, 38, 1, 71, 198, 38, 1, 248, 38, 71, - 198, 38, 1, 234, 65, 198, 38, 1, 248, 38, 234, 65, 198, 38, 1, 74, 198, - 38, 1, 252, 25, 198, 38, 1, 248, 38, 252, 25, 198, 38, 1, 65, 198, 38, 3, - 206, 180, 198, 79, 193, 163, 1, 252, 206, 193, 163, 1, 65, 193, 163, 1, - 249, 153, 193, 163, 1, 247, 160, 193, 163, 1, 238, 32, 193, 163, 1, 231, - 240, 193, 163, 1, 170, 193, 163, 1, 209, 228, 193, 163, 1, 173, 193, 163, - 1, 180, 193, 163, 1, 168, 193, 163, 1, 190, 190, 193, 163, 1, 199, 49, - 193, 163, 1, 233, 109, 193, 163, 1, 188, 193, 163, 1, 203, 165, 193, 163, - 1, 223, 32, 193, 163, 1, 191, 123, 193, 163, 1, 193, 190, 193, 163, 1, - 195, 188, 193, 163, 1, 155, 193, 163, 1, 74, 193, 163, 1, 250, 163, 193, - 163, 1, 165, 193, 163, 1, 174, 193, 163, 1, 221, 215, 193, 163, 1, 140, - 193, 163, 1, 71, 193, 163, 1, 68, 193, 163, 1, 214, 68, 193, 163, 1, 66, - 193, 163, 1, 219, 66, 193, 163, 1, 197, 168, 193, 163, 1, 198, 26, 193, - 163, 1, 211, 94, 193, 163, 1, 252, 165, 193, 163, 1, 251, 122, 193, 163, - 1, 223, 136, 193, 163, 1, 211, 104, 193, 163, 1, 234, 103, 193, 163, 1, - 252, 166, 193, 163, 1, 212, 101, 193, 163, 1, 196, 147, 193, 163, 1, 192, - 24, 193, 163, 163, 197, 67, 193, 163, 163, 197, 66, 193, 163, 163, 221, - 54, 193, 163, 163, 221, 53, 193, 163, 17, 191, 77, 193, 163, 17, 107, - 193, 163, 17, 109, 193, 163, 17, 138, 193, 163, 17, 134, 193, 163, 17, - 149, 193, 163, 17, 169, 193, 163, 17, 175, 193, 163, 17, 171, 193, 163, - 17, 178, 193, 163, 213, 232, 56, 214, 243, 215, 120, 1, 74, 214, 243, - 215, 120, 1, 211, 78, 214, 243, 215, 120, 1, 211, 120, 214, 243, 215, - 120, 1, 210, 242, 214, 243, 215, 120, 1, 211, 94, 214, 243, 215, 120, 1, - 65, 214, 243, 215, 120, 1, 251, 218, 214, 243, 215, 120, 1, 252, 155, - 214, 243, 215, 120, 1, 251, 69, 214, 243, 215, 120, 1, 251, 245, 214, - 243, 215, 120, 1, 68, 214, 243, 215, 120, 1, 223, 68, 214, 243, 215, 120, - 1, 228, 18, 214, 243, 215, 120, 1, 223, 53, 214, 243, 215, 120, 1, 223, - 200, 214, 243, 215, 120, 1, 66, 214, 243, 215, 120, 1, 196, 160, 214, - 243, 215, 120, 1, 196, 158, 214, 243, 215, 120, 1, 196, 128, 214, 243, - 215, 120, 1, 196, 62, 214, 243, 215, 120, 1, 71, 214, 243, 215, 120, 1, - 234, 85, 214, 243, 215, 120, 1, 234, 180, 214, 243, 215, 120, 1, 234, - 114, 214, 243, 215, 120, 1, 234, 103, 214, 243, 215, 120, 1, 233, 245, - 214, 243, 215, 120, 1, 234, 122, 214, 243, 215, 120, 3, 211, 127, 214, - 243, 215, 120, 3, 215, 138, 214, 243, 215, 120, 3, 198, 28, 214, 243, - 215, 120, 3, 223, 193, 214, 243, 215, 120, 3, 200, 161, 214, 243, 215, - 120, 17, 191, 77, 214, 243, 215, 120, 17, 107, 214, 243, 215, 120, 17, - 109, 214, 243, 215, 120, 17, 138, 214, 243, 215, 120, 17, 134, 214, 243, - 215, 120, 17, 149, 214, 243, 215, 120, 17, 169, 214, 243, 215, 120, 17, - 175, 214, 243, 215, 120, 17, 171, 214, 243, 215, 120, 17, 178, 36, 5, - 229, 166, 36, 5, 229, 160, 36, 5, 229, 162, 36, 5, 229, 165, 36, 5, 229, - 163, 36, 5, 229, 164, 36, 5, 229, 161, 36, 5, 230, 147, 229, 170, 36, 5, - 229, 167, 36, 5, 229, 168, 36, 5, 229, 169, 36, 5, 230, 147, 215, 76, 36, - 5, 230, 147, 215, 77, 36, 5, 230, 147, 207, 236, 36, 5, 230, 147, 207, - 237, 36, 5, 230, 147, 207, 238, 36, 5, 230, 147, 247, 207, 36, 5, 230, - 147, 247, 208, 36, 5, 230, 147, 220, 172, 36, 5, 230, 147, 220, 173, 36, - 5, 230, 147, 220, 174, 36, 5, 230, 147, 230, 131, 36, 5, 230, 147, 230, - 132, 36, 5, 230, 147, 230, 133, 36, 5, 230, 147, 232, 58, 36, 5, 230, - 147, 232, 59, 36, 5, 230, 147, 208, 118, 36, 5, 230, 147, 208, 119, 85, - 84, 5, 218, 167, 221, 166, 85, 84, 5, 218, 163, 155, 85, 84, 5, 218, 161, - 220, 232, 85, 84, 5, 218, 37, 222, 13, 85, 84, 5, 218, 7, 222, 22, 85, - 84, 5, 218, 26, 221, 41, 85, 84, 5, 218, 54, 221, 67, 85, 84, 5, 217, - 179, 220, 219, 85, 84, 5, 218, 158, 193, 86, 85, 84, 5, 218, 156, 193, - 190, 85, 84, 5, 218, 154, 193, 0, 85, 84, 5, 217, 232, 193, 114, 85, 84, - 5, 217, 240, 193, 125, 85, 84, 5, 217, 244, 193, 29, 85, 84, 5, 218, 57, - 193, 48, 85, 84, 5, 217, 164, 192, 252, 85, 84, 5, 217, 215, 193, 112, - 85, 84, 5, 218, 41, 192, 240, 85, 84, 5, 218, 53, 192, 242, 85, 84, 5, - 217, 219, 192, 241, 85, 84, 5, 218, 152, 216, 44, 85, 84, 5, 218, 150, - 217, 90, 85, 84, 5, 218, 148, 215, 122, 85, 84, 5, 218, 43, 216, 186, 85, - 84, 5, 218, 8, 215, 231, 85, 84, 5, 217, 204, 215, 148, 85, 84, 5, 217, - 169, 215, 142, 85, 84, 5, 218, 146, 248, 188, 85, 84, 5, 218, 143, 249, - 153, 85, 84, 5, 218, 141, 248, 10, 85, 84, 5, 217, 208, 249, 1, 85, 84, - 5, 218, 5, 249, 17, 85, 84, 5, 217, 255, 248, 97, 85, 84, 5, 217, 220, - 248, 111, 85, 84, 5, 218, 131, 68, 85, 84, 5, 218, 129, 65, 85, 84, 5, - 218, 127, 66, 85, 84, 5, 217, 195, 234, 188, 85, 84, 5, 218, 2, 71, 85, - 84, 5, 217, 193, 211, 87, 85, 84, 5, 217, 211, 74, 85, 84, 5, 217, 221, - 234, 166, 85, 84, 5, 217, 227, 223, 162, 85, 84, 5, 217, 223, 223, 162, - 85, 84, 5, 217, 163, 251, 132, 85, 84, 5, 217, 180, 234, 103, 85, 84, 5, - 218, 116, 202, 222, 85, 84, 5, 218, 114, 188, 85, 84, 5, 218, 112, 201, - 4, 85, 84, 5, 217, 196, 205, 50, 85, 84, 5, 217, 242, 205, 68, 85, 84, 5, - 217, 222, 202, 16, 85, 84, 5, 218, 23, 202, 46, 85, 84, 5, 217, 162, 202, - 215, 85, 84, 5, 218, 102, 219, 146, 85, 84, 5, 218, 100, 173, 85, 84, 5, - 218, 98, 218, 225, 85, 84, 5, 218, 18, 219, 228, 85, 84, 5, 218, 29, 219, - 238, 85, 84, 5, 218, 48, 219, 8, 85, 84, 5, 217, 205, 219, 43, 85, 84, 5, - 217, 248, 179, 219, 238, 85, 84, 5, 218, 124, 237, 44, 85, 84, 5, 218, - 121, 238, 32, 85, 84, 5, 218, 118, 235, 89, 85, 84, 5, 218, 13, 237, 131, - 85, 84, 5, 217, 178, 236, 146, 85, 84, 5, 217, 177, 236, 174, 85, 84, 5, - 218, 110, 198, 193, 85, 84, 5, 218, 107, 190, 190, 85, 84, 5, 218, 105, - 197, 94, 85, 84, 5, 218, 11, 199, 121, 85, 84, 5, 218, 47, 199, 145, 85, - 84, 5, 217, 254, 198, 59, 85, 84, 5, 218, 33, 159, 85, 84, 5, 218, 96, - 222, 244, 85, 84, 5, 218, 93, 223, 32, 85, 84, 5, 218, 91, 222, 182, 85, - 84, 5, 217, 201, 223, 8, 85, 84, 5, 217, 245, 223, 10, 85, 84, 5, 217, - 198, 222, 191, 85, 84, 5, 218, 39, 222, 201, 85, 84, 5, 217, 183, 179, - 222, 201, 85, 84, 5, 218, 89, 192, 33, 85, 84, 5, 218, 86, 170, 85, 84, - 5, 218, 84, 191, 225, 85, 84, 5, 217, 249, 192, 77, 85, 84, 5, 218, 22, - 192, 80, 85, 84, 5, 217, 217, 191, 246, 85, 84, 5, 217, 237, 192, 12, 85, - 84, 5, 218, 80, 233, 23, 85, 84, 5, 218, 78, 233, 109, 85, 84, 5, 218, - 76, 232, 86, 85, 84, 5, 218, 24, 233, 52, 85, 84, 5, 218, 27, 233, 59, - 85, 84, 5, 217, 225, 232, 162, 85, 84, 5, 218, 14, 232, 175, 85, 84, 5, - 217, 161, 232, 85, 85, 84, 5, 218, 1, 233, 80, 85, 84, 5, 218, 74, 213, - 179, 85, 84, 5, 218, 72, 214, 226, 85, 84, 5, 218, 70, 212, 130, 85, 84, - 5, 217, 241, 214, 102, 85, 84, 5, 217, 189, 213, 31, 85, 84, 5, 217, 182, - 229, 158, 85, 84, 5, 218, 65, 140, 85, 84, 5, 217, 172, 228, 159, 85, 84, - 5, 218, 68, 229, 215, 85, 84, 5, 218, 6, 229, 245, 85, 84, 5, 218, 63, - 228, 252, 85, 84, 5, 217, 218, 229, 23, 85, 84, 5, 218, 19, 229, 214, 85, - 84, 5, 217, 230, 228, 245, 85, 84, 5, 218, 49, 229, 128, 85, 84, 5, 217, - 228, 230, 56, 85, 84, 5, 218, 15, 228, 142, 85, 84, 5, 218, 50, 229, 198, - 85, 84, 5, 217, 165, 228, 255, 85, 84, 5, 218, 56, 228, 155, 85, 84, 5, - 218, 12, 214, 33, 85, 84, 5, 218, 61, 214, 47, 85, 84, 5, 218, 20, 214, - 30, 85, 84, 5, 217, 243, 214, 41, 85, 84, 5, 217, 212, 214, 42, 85, 84, - 5, 217, 202, 214, 31, 85, 84, 5, 217, 238, 214, 32, 85, 84, 5, 217, 199, - 214, 46, 85, 84, 5, 217, 231, 214, 29, 85, 84, 5, 218, 16, 179, 214, 42, - 85, 84, 5, 217, 252, 179, 214, 31, 85, 84, 5, 217, 175, 179, 214, 32, 85, - 84, 5, 217, 203, 231, 53, 85, 84, 5, 217, 247, 231, 240, 85, 84, 5, 217, - 190, 230, 179, 85, 84, 5, 217, 168, 231, 157, 85, 84, 5, 217, 192, 230, - 165, 85, 84, 5, 217, 191, 230, 175, 85, 84, 5, 217, 174, 214, 52, 85, 84, - 5, 218, 45, 213, 245, 85, 84, 5, 217, 181, 213, 234, 85, 84, 5, 218, 34, - 209, 185, 85, 84, 5, 218, 3, 168, 85, 84, 5, 218, 52, 208, 165, 85, 84, - 5, 218, 21, 210, 49, 85, 84, 5, 218, 51, 210, 63, 85, 84, 5, 218, 0, 209, - 37, 85, 84, 5, 218, 36, 209, 73, 85, 84, 5, 217, 213, 216, 252, 85, 84, - 5, 218, 40, 217, 11, 85, 84, 5, 217, 236, 216, 246, 85, 84, 5, 218, 55, - 217, 3, 85, 84, 5, 217, 170, 217, 3, 85, 84, 5, 218, 30, 217, 4, 85, 84, - 5, 217, 186, 216, 247, 85, 84, 5, 217, 184, 216, 248, 85, 84, 5, 217, - 171, 216, 240, 85, 84, 5, 217, 197, 179, 217, 4, 85, 84, 5, 217, 253, - 179, 216, 247, 85, 84, 5, 217, 216, 179, 216, 248, 85, 84, 5, 217, 226, - 221, 13, 85, 84, 5, 218, 10, 221, 21, 85, 84, 5, 218, 28, 221, 9, 85, 84, - 5, 218, 59, 221, 16, 85, 84, 5, 217, 250, 221, 17, 85, 84, 5, 217, 246, - 221, 11, 85, 84, 5, 217, 200, 221, 12, 85, 84, 5, 217, 234, 231, 174, 85, - 84, 5, 218, 46, 231, 182, 85, 84, 5, 217, 210, 231, 169, 85, 84, 5, 218, - 9, 231, 178, 85, 84, 5, 217, 251, 231, 179, 85, 84, 5, 218, 31, 231, 170, - 85, 84, 5, 218, 32, 231, 172, 85, 84, 5, 217, 187, 165, 85, 84, 5, 217, - 235, 214, 147, 85, 84, 5, 217, 229, 214, 162, 85, 84, 5, 217, 233, 214, - 129, 85, 84, 5, 217, 167, 214, 153, 85, 84, 5, 217, 239, 214, 154, 85, - 84, 5, 218, 35, 214, 134, 85, 84, 5, 218, 38, 214, 138, 85, 84, 5, 217, - 206, 213, 157, 85, 84, 5, 217, 166, 213, 127, 85, 84, 5, 217, 209, 213, - 148, 85, 84, 5, 217, 224, 213, 131, 85, 84, 5, 217, 176, 195, 69, 85, 84, - 5, 217, 173, 195, 188, 85, 84, 5, 217, 207, 193, 249, 85, 84, 5, 217, - 185, 195, 148, 85, 84, 5, 218, 17, 195, 153, 85, 84, 5, 217, 214, 195, 8, - 85, 84, 5, 218, 25, 195, 24, 85, 84, 5, 217, 194, 212, 74, 85, 84, 5, - 218, 44, 212, 94, 85, 84, 5, 217, 188, 212, 56, 85, 84, 5, 218, 4, 212, - 86, 85, 84, 5, 218, 42, 212, 63, 85, 84, 17, 107, 85, 84, 17, 109, 85, - 84, 17, 138, 85, 84, 17, 134, 85, 84, 17, 149, 85, 84, 17, 169, 85, 84, - 17, 175, 85, 84, 17, 171, 85, 84, 17, 178, 85, 84, 33, 31, 199, 119, 85, - 84, 33, 31, 199, 90, 85, 84, 33, 31, 228, 138, 85, 84, 33, 31, 198, 228, - 85, 84, 33, 31, 199, 96, 198, 228, 85, 84, 33, 31, 228, 141, 198, 228, - 85, 84, 33, 31, 216, 47, 252, 33, 6, 1, 251, 180, 252, 33, 6, 1, 238, 29, - 252, 33, 6, 1, 220, 123, 252, 33, 6, 1, 216, 60, 252, 33, 6, 1, 249, 153, - 252, 33, 6, 1, 202, 164, 252, 33, 6, 1, 210, 63, 252, 33, 6, 1, 248, 196, - 252, 33, 6, 1, 165, 252, 33, 6, 1, 71, 252, 33, 6, 1, 233, 109, 252, 33, - 6, 1, 68, 252, 33, 6, 1, 74, 252, 33, 6, 1, 237, 68, 252, 33, 6, 1, 192, - 34, 252, 33, 6, 1, 193, 133, 252, 33, 6, 1, 212, 130, 252, 33, 6, 1, 222, - 106, 252, 33, 6, 1, 170, 252, 33, 6, 1, 66, 252, 33, 6, 1, 222, 235, 252, - 33, 6, 1, 243, 95, 252, 33, 6, 1, 140, 252, 33, 6, 1, 208, 94, 252, 33, - 6, 1, 231, 240, 252, 33, 6, 1, 212, 101, 252, 33, 6, 1, 197, 94, 252, 33, - 6, 1, 213, 224, 252, 33, 6, 1, 195, 188, 252, 33, 6, 1, 221, 215, 252, - 33, 6, 1, 231, 179, 252, 33, 6, 1, 191, 108, 252, 33, 6, 1, 221, 12, 252, - 33, 6, 1, 203, 165, 252, 33, 2, 1, 251, 180, 252, 33, 2, 1, 238, 29, 252, - 33, 2, 1, 220, 123, 252, 33, 2, 1, 216, 60, 252, 33, 2, 1, 249, 153, 252, - 33, 2, 1, 202, 164, 252, 33, 2, 1, 210, 63, 252, 33, 2, 1, 248, 196, 252, - 33, 2, 1, 165, 252, 33, 2, 1, 71, 252, 33, 2, 1, 233, 109, 252, 33, 2, 1, - 68, 252, 33, 2, 1, 74, 252, 33, 2, 1, 237, 68, 252, 33, 2, 1, 192, 34, - 252, 33, 2, 1, 193, 133, 252, 33, 2, 1, 212, 130, 252, 33, 2, 1, 222, - 106, 252, 33, 2, 1, 170, 252, 33, 2, 1, 66, 252, 33, 2, 1, 222, 235, 252, - 33, 2, 1, 243, 95, 252, 33, 2, 1, 140, 252, 33, 2, 1, 208, 94, 252, 33, - 2, 1, 231, 240, 252, 33, 2, 1, 212, 101, 252, 33, 2, 1, 197, 94, 252, 33, - 2, 1, 213, 224, 252, 33, 2, 1, 195, 188, 252, 33, 2, 1, 221, 215, 252, - 33, 2, 1, 231, 179, 252, 33, 2, 1, 191, 108, 252, 33, 2, 1, 221, 12, 252, - 33, 2, 1, 203, 165, 252, 33, 251, 181, 219, 190, 252, 33, 18, 219, 190, - 252, 33, 231, 153, 77, 252, 33, 230, 57, 252, 33, 120, 215, 252, 252, 33, - 231, 154, 120, 215, 252, 252, 33, 212, 141, 252, 33, 214, 213, 77, 252, - 33, 17, 191, 77, 252, 33, 17, 107, 252, 33, 17, 109, 252, 33, 17, 138, - 252, 33, 17, 134, 252, 33, 17, 149, 252, 33, 17, 169, 252, 33, 17, 175, - 252, 33, 17, 171, 252, 33, 17, 178, 252, 33, 89, 233, 216, 77, 252, 33, - 89, 208, 13, 77, 223, 146, 143, 31, 107, 223, 146, 143, 31, 109, 223, - 146, 143, 31, 138, 223, 146, 143, 31, 134, 223, 146, 143, 31, 149, 223, - 146, 143, 31, 169, 223, 146, 143, 31, 175, 223, 146, 143, 31, 171, 223, - 146, 143, 31, 178, 223, 146, 143, 31, 199, 95, 223, 146, 143, 31, 197, - 32, 223, 146, 143, 31, 198, 249, 223, 146, 143, 31, 232, 135, 223, 146, - 143, 31, 233, 15, 223, 146, 143, 31, 202, 120, 223, 146, 143, 31, 203, - 241, 223, 146, 143, 31, 234, 153, 223, 146, 143, 31, 213, 169, 223, 146, - 143, 31, 91, 228, 140, 223, 146, 143, 31, 105, 228, 140, 223, 146, 143, - 31, 115, 228, 140, 223, 146, 143, 31, 232, 128, 228, 140, 223, 146, 143, - 31, 232, 226, 228, 140, 223, 146, 143, 31, 202, 136, 228, 140, 223, 146, - 143, 31, 203, 247, 228, 140, 223, 146, 143, 31, 234, 164, 228, 140, 223, - 146, 143, 31, 213, 175, 228, 140, 223, 146, 143, 31, 91, 189, 223, 146, - 143, 31, 105, 189, 223, 146, 143, 31, 115, 189, 223, 146, 143, 31, 232, - 128, 189, 223, 146, 143, 31, 232, 226, 189, 223, 146, 143, 31, 202, 136, - 189, 223, 146, 143, 31, 203, 247, 189, 223, 146, 143, 31, 234, 164, 189, - 223, 146, 143, 31, 213, 175, 189, 223, 146, 143, 31, 199, 96, 189, 223, - 146, 143, 31, 197, 33, 189, 223, 146, 143, 31, 198, 250, 189, 223, 146, - 143, 31, 232, 136, 189, 223, 146, 143, 31, 233, 16, 189, 223, 146, 143, - 31, 202, 121, 189, 223, 146, 143, 31, 203, 242, 189, 223, 146, 143, 31, - 234, 154, 189, 223, 146, 143, 31, 213, 170, 189, 223, 146, 143, 31, 220, - 41, 223, 146, 143, 31, 220, 40, 223, 146, 143, 220, 42, 77, 223, 146, - 143, 31, 222, 60, 223, 146, 143, 31, 222, 59, 223, 146, 143, 31, 208, - 227, 107, 223, 146, 143, 31, 208, 227, 109, 223, 146, 143, 31, 208, 227, - 138, 223, 146, 143, 31, 208, 227, 134, 223, 146, 143, 31, 208, 227, 149, - 223, 146, 143, 31, 208, 227, 169, 223, 146, 143, 31, 208, 227, 175, 223, - 146, 143, 31, 208, 227, 171, 223, 146, 143, 31, 208, 227, 178, 223, 146, - 143, 209, 106, 223, 146, 143, 232, 118, 91, 208, 22, 223, 146, 143, 232, - 118, 91, 230, 70, 223, 146, 143, 232, 118, 115, 208, 20, 223, 146, 143, - 206, 36, 77, 223, 146, 143, 31, 251, 157, 107, 223, 146, 143, 31, 251, - 157, 109, 223, 146, 143, 31, 251, 157, 199, 96, 189, 223, 146, 143, 251, - 157, 220, 42, 77, 211, 21, 143, 31, 107, 211, 21, 143, 31, 109, 211, 21, - 143, 31, 138, 211, 21, 143, 31, 134, 211, 21, 143, 31, 149, 211, 21, 143, - 31, 169, 211, 21, 143, 31, 175, 211, 21, 143, 31, 171, 211, 21, 143, 31, - 178, 211, 21, 143, 31, 199, 95, 211, 21, 143, 31, 197, 32, 211, 21, 143, - 31, 198, 249, 211, 21, 143, 31, 232, 135, 211, 21, 143, 31, 233, 15, 211, - 21, 143, 31, 202, 120, 211, 21, 143, 31, 203, 241, 211, 21, 143, 31, 234, - 153, 211, 21, 143, 31, 213, 169, 211, 21, 143, 31, 91, 228, 140, 211, 21, - 143, 31, 105, 228, 140, 211, 21, 143, 31, 115, 228, 140, 211, 21, 143, - 31, 232, 128, 228, 140, 211, 21, 143, 31, 232, 226, 228, 140, 211, 21, - 143, 31, 202, 136, 228, 140, 211, 21, 143, 31, 203, 247, 228, 140, 211, - 21, 143, 31, 234, 164, 228, 140, 211, 21, 143, 31, 213, 175, 228, 140, - 211, 21, 143, 31, 91, 189, 211, 21, 143, 31, 105, 189, 211, 21, 143, 31, - 115, 189, 211, 21, 143, 31, 232, 128, 189, 211, 21, 143, 31, 232, 226, - 189, 211, 21, 143, 31, 202, 136, 189, 211, 21, 143, 31, 203, 247, 189, - 211, 21, 143, 31, 234, 164, 189, 211, 21, 143, 31, 213, 175, 189, 211, - 21, 143, 31, 199, 96, 189, 211, 21, 143, 31, 197, 33, 189, 211, 21, 143, - 31, 198, 250, 189, 211, 21, 143, 31, 232, 136, 189, 211, 21, 143, 31, - 233, 16, 189, 211, 21, 143, 31, 202, 121, 189, 211, 21, 143, 31, 203, - 242, 189, 211, 21, 143, 31, 234, 154, 189, 211, 21, 143, 31, 213, 170, - 189, 211, 21, 143, 217, 49, 211, 21, 143, 251, 157, 31, 109, 211, 21, - 143, 251, 157, 31, 138, 211, 21, 143, 251, 157, 31, 134, 211, 21, 143, - 251, 157, 31, 149, 211, 21, 143, 251, 157, 31, 169, 211, 21, 143, 251, - 157, 31, 175, 211, 21, 143, 251, 157, 31, 171, 211, 21, 143, 251, 157, - 31, 178, 211, 21, 143, 251, 157, 31, 199, 95, 211, 21, 143, 251, 157, 31, - 232, 128, 228, 140, 211, 21, 143, 251, 157, 31, 202, 136, 228, 140, 211, - 21, 143, 251, 157, 31, 105, 189, 211, 21, 143, 251, 157, 31, 199, 96, - 189, 211, 21, 143, 232, 118, 91, 230, 70, 211, 21, 143, 232, 118, 91, - 202, 124, 9, 13, 251, 192, 9, 13, 248, 245, 9, 13, 223, 6, 9, 13, 238, 3, - 9, 13, 193, 133, 9, 13, 191, 113, 9, 13, 230, 81, 9, 13, 199, 219, 9, 13, - 192, 75, 9, 13, 222, 106, 9, 13, 220, 35, 9, 13, 216, 208, 9, 13, 213, - 24, 9, 13, 205, 46, 9, 13, 251, 230, 9, 13, 233, 46, 9, 13, 205, 192, 9, - 13, 208, 89, 9, 13, 207, 71, 9, 13, 203, 109, 9, 13, 199, 114, 9, 13, - 199, 29, 9, 13, 221, 210, 9, 13, 199, 41, 9, 13, 238, 26, 9, 13, 191, - 116, 9, 13, 231, 86, 9, 13, 236, 139, 248, 245, 9, 13, 236, 139, 213, 24, - 9, 13, 236, 139, 233, 46, 9, 13, 236, 139, 208, 89, 9, 13, 89, 248, 245, - 9, 13, 89, 223, 6, 9, 13, 89, 229, 210, 9, 13, 89, 230, 81, 9, 13, 89, - 192, 75, 9, 13, 89, 222, 106, 9, 13, 89, 220, 35, 9, 13, 89, 216, 208, 9, - 13, 89, 213, 24, 9, 13, 89, 205, 46, 9, 13, 89, 251, 230, 9, 13, 89, 233, - 46, 9, 13, 89, 205, 192, 9, 13, 89, 208, 89, 9, 13, 89, 203, 109, 9, 13, - 89, 199, 114, 9, 13, 89, 199, 29, 9, 13, 89, 221, 210, 9, 13, 89, 238, - 26, 9, 13, 89, 231, 86, 9, 13, 199, 214, 223, 6, 9, 13, 199, 214, 230, - 81, 9, 13, 199, 214, 192, 75, 9, 13, 199, 214, 220, 35, 9, 13, 199, 214, - 213, 24, 9, 13, 199, 214, 205, 46, 9, 13, 199, 214, 251, 230, 9, 13, 199, - 214, 205, 192, 9, 13, 199, 214, 208, 89, 9, 13, 199, 214, 203, 109, 9, - 13, 199, 214, 221, 210, 9, 13, 199, 214, 238, 26, 9, 13, 199, 214, 231, - 86, 9, 13, 199, 214, 236, 139, 213, 24, 9, 13, 199, 214, 236, 139, 208, - 89, 9, 13, 201, 36, 248, 245, 9, 13, 201, 36, 223, 6, 9, 13, 201, 36, - 229, 210, 9, 13, 201, 36, 230, 81, 9, 13, 201, 36, 199, 219, 9, 13, 201, - 36, 192, 75, 9, 13, 201, 36, 222, 106, 9, 13, 201, 36, 216, 208, 9, 13, - 201, 36, 213, 24, 9, 13, 201, 36, 205, 46, 9, 13, 201, 36, 251, 230, 9, - 13, 201, 36, 233, 46, 9, 13, 201, 36, 205, 192, 9, 13, 201, 36, 208, 89, - 9, 13, 201, 36, 203, 109, 9, 13, 201, 36, 199, 114, 9, 13, 201, 36, 199, - 29, 9, 13, 201, 36, 221, 210, 9, 13, 201, 36, 238, 26, 9, 13, 201, 36, - 191, 116, 9, 13, 201, 36, 231, 86, 9, 13, 201, 36, 236, 139, 248, 245, 9, - 13, 201, 36, 236, 139, 233, 46, 9, 13, 219, 3, 251, 192, 9, 13, 219, 3, - 248, 245, 9, 13, 219, 3, 223, 6, 9, 13, 219, 3, 238, 3, 9, 13, 219, 3, - 229, 210, 9, 13, 219, 3, 193, 133, 9, 13, 219, 3, 191, 113, 9, 13, 219, - 3, 230, 81, 9, 13, 219, 3, 199, 219, 9, 13, 219, 3, 192, 75, 9, 13, 219, - 3, 220, 35, 9, 13, 219, 3, 216, 208, 9, 13, 219, 3, 213, 24, 9, 13, 219, - 3, 205, 46, 9, 13, 219, 3, 251, 230, 9, 13, 219, 3, 233, 46, 9, 13, 219, - 3, 205, 192, 9, 13, 219, 3, 208, 89, 9, 13, 219, 3, 207, 71, 9, 13, 219, - 3, 203, 109, 9, 13, 219, 3, 199, 114, 9, 13, 219, 3, 199, 29, 9, 13, 219, - 3, 221, 210, 9, 13, 219, 3, 199, 41, 9, 13, 219, 3, 238, 26, 9, 13, 219, - 3, 191, 116, 9, 13, 219, 3, 231, 86, 9, 13, 235, 129, 248, 245, 9, 13, - 235, 129, 223, 6, 9, 13, 235, 129, 238, 3, 9, 13, 235, 129, 193, 133, 9, - 13, 235, 129, 191, 113, 9, 13, 235, 129, 230, 81, 9, 13, 235, 129, 199, - 219, 9, 13, 235, 129, 192, 75, 9, 13, 235, 129, 220, 35, 9, 13, 235, 129, - 216, 208, 9, 13, 235, 129, 213, 24, 9, 13, 235, 129, 205, 46, 9, 13, 235, - 129, 251, 230, 9, 13, 235, 129, 233, 46, 9, 13, 235, 129, 205, 192, 9, - 13, 235, 129, 208, 89, 9, 13, 235, 129, 207, 71, 9, 13, 235, 129, 203, - 109, 9, 13, 235, 129, 199, 114, 9, 13, 235, 129, 199, 29, 9, 13, 235, - 129, 221, 210, 9, 13, 235, 129, 199, 41, 9, 13, 235, 129, 238, 26, 9, 13, - 235, 129, 191, 116, 9, 13, 235, 129, 231, 86, 9, 13, 211, 67, 92, 4, 182, - 4, 199, 168, 9, 13, 211, 67, 182, 4, 238, 3, 217, 114, 123, 234, 204, - 193, 66, 217, 114, 123, 202, 2, 193, 66, 217, 114, 123, 193, 105, 193, - 66, 217, 114, 123, 186, 193, 66, 217, 114, 123, 207, 87, 235, 111, 217, - 114, 123, 230, 201, 235, 111, 217, 114, 123, 63, 235, 111, 217, 114, 123, - 91, 79, 243, 140, 217, 114, 123, 105, 79, 243, 140, 217, 114, 123, 115, - 79, 243, 140, 217, 114, 123, 232, 128, 79, 243, 140, 217, 114, 123, 232, - 226, 79, 243, 140, 217, 114, 123, 202, 136, 79, 243, 140, 217, 114, 123, - 203, 247, 79, 243, 140, 217, 114, 123, 234, 164, 79, 243, 140, 217, 114, - 123, 213, 175, 79, 243, 140, 217, 114, 123, 91, 79, 249, 102, 217, 114, - 123, 105, 79, 249, 102, 217, 114, 123, 115, 79, 249, 102, 217, 114, 123, - 232, 128, 79, 249, 102, 217, 114, 123, 232, 226, 79, 249, 102, 217, 114, - 123, 202, 136, 79, 249, 102, 217, 114, 123, 203, 247, 79, 249, 102, 217, - 114, 123, 234, 164, 79, 249, 102, 217, 114, 123, 213, 175, 79, 249, 102, - 217, 114, 123, 91, 79, 243, 7, 217, 114, 123, 105, 79, 243, 7, 217, 114, - 123, 115, 79, 243, 7, 217, 114, 123, 232, 128, 79, 243, 7, 217, 114, 123, - 232, 226, 79, 243, 7, 217, 114, 123, 202, 136, 79, 243, 7, 217, 114, 123, - 203, 247, 79, 243, 7, 217, 114, 123, 234, 164, 79, 243, 7, 217, 114, 123, - 213, 175, 79, 243, 7, 217, 114, 123, 209, 85, 217, 114, 123, 211, 53, - 217, 114, 123, 249, 103, 217, 114, 123, 243, 49, 217, 114, 123, 201, 196, - 217, 114, 123, 200, 200, 217, 114, 123, 250, 149, 217, 114, 123, 193, 56, - 217, 114, 123, 222, 194, 217, 114, 123, 249, 146, 236, 151, 123, 228, - 241, 249, 146, 236, 151, 123, 228, 239, 236, 151, 123, 228, 238, 236, - 151, 123, 228, 237, 236, 151, 123, 228, 236, 236, 151, 123, 228, 235, - 236, 151, 123, 228, 234, 236, 151, 123, 228, 233, 236, 151, 123, 228, - 232, 236, 151, 123, 228, 231, 236, 151, 123, 228, 230, 236, 151, 123, - 228, 229, 236, 151, 123, 228, 228, 236, 151, 123, 228, 227, 236, 151, - 123, 228, 226, 236, 151, 123, 228, 225, 236, 151, 123, 228, 224, 236, - 151, 123, 228, 223, 236, 151, 123, 228, 222, 236, 151, 123, 228, 221, - 236, 151, 123, 228, 220, 236, 151, 123, 228, 219, 236, 151, 123, 228, - 218, 236, 151, 123, 228, 217, 236, 151, 123, 228, 216, 236, 151, 123, - 228, 215, 236, 151, 123, 228, 214, 236, 151, 123, 228, 213, 236, 151, - 123, 228, 212, 236, 151, 123, 228, 211, 236, 151, 123, 228, 210, 236, - 151, 123, 228, 209, 236, 151, 123, 228, 208, 236, 151, 123, 228, 207, - 236, 151, 123, 228, 206, 236, 151, 123, 228, 205, 236, 151, 123, 228, - 204, 236, 151, 123, 228, 203, 236, 151, 123, 228, 202, 236, 151, 123, - 228, 201, 236, 151, 123, 228, 200, 236, 151, 123, 228, 199, 236, 151, - 123, 228, 198, 236, 151, 123, 228, 197, 236, 151, 123, 228, 196, 236, - 151, 123, 228, 195, 236, 151, 123, 228, 194, 236, 151, 123, 228, 193, - 236, 151, 123, 228, 192, 236, 151, 123, 228, 191, 236, 151, 123, 81, 249, - 146, 236, 151, 123, 195, 134, 236, 151, 123, 195, 133, 236, 151, 123, - 195, 132, 236, 151, 123, 195, 131, 236, 151, 123, 195, 130, 236, 151, - 123, 195, 129, 236, 151, 123, 195, 128, 236, 151, 123, 195, 127, 236, - 151, 123, 195, 126, 236, 151, 123, 195, 125, 236, 151, 123, 195, 124, - 236, 151, 123, 195, 123, 236, 151, 123, 195, 122, 236, 151, 123, 195, - 121, 236, 151, 123, 195, 120, 236, 151, 123, 195, 119, 236, 151, 123, - 195, 118, 236, 151, 123, 195, 117, 236, 151, 123, 195, 116, 236, 151, - 123, 195, 115, 236, 151, 123, 195, 114, 236, 151, 123, 195, 113, 236, - 151, 123, 195, 112, 236, 151, 123, 195, 111, 236, 151, 123, 195, 110, - 236, 151, 123, 195, 109, 236, 151, 123, 195, 108, 236, 151, 123, 195, - 107, 236, 151, 123, 195, 106, 236, 151, 123, 195, 105, 236, 151, 123, - 195, 104, 236, 151, 123, 195, 103, 236, 151, 123, 195, 102, 236, 151, - 123, 195, 101, 236, 151, 123, 195, 100, 236, 151, 123, 195, 99, 236, 151, - 123, 195, 98, 236, 151, 123, 195, 97, 236, 151, 123, 195, 96, 236, 151, - 123, 195, 95, 236, 151, 123, 195, 94, 236, 151, 123, 195, 93, 236, 151, - 123, 195, 92, 236, 151, 123, 195, 91, 236, 151, 123, 195, 90, 236, 151, - 123, 195, 89, 236, 151, 123, 195, 88, 236, 151, 123, 195, 87, 236, 151, - 123, 195, 86, 209, 95, 247, 101, 249, 146, 209, 95, 247, 101, 252, 53, - 79, 201, 244, 209, 95, 247, 101, 105, 79, 201, 244, 209, 95, 247, 101, - 115, 79, 201, 244, 209, 95, 247, 101, 232, 128, 79, 201, 244, 209, 95, - 247, 101, 232, 226, 79, 201, 244, 209, 95, 247, 101, 202, 136, 79, 201, - 244, 209, 95, 247, 101, 203, 247, 79, 201, 244, 209, 95, 247, 101, 234, - 164, 79, 201, 244, 209, 95, 247, 101, 213, 175, 79, 201, 244, 209, 95, - 247, 101, 199, 96, 79, 201, 244, 209, 95, 247, 101, 223, 30, 79, 201, - 244, 209, 95, 247, 101, 221, 77, 79, 201, 244, 209, 95, 247, 101, 208, - 15, 79, 201, 244, 209, 95, 247, 101, 221, 139, 79, 201, 244, 209, 95, - 247, 101, 252, 53, 79, 229, 221, 209, 95, 247, 101, 105, 79, 229, 221, - 209, 95, 247, 101, 115, 79, 229, 221, 209, 95, 247, 101, 232, 128, 79, - 229, 221, 209, 95, 247, 101, 232, 226, 79, 229, 221, 209, 95, 247, 101, - 202, 136, 79, 229, 221, 209, 95, 247, 101, 203, 247, 79, 229, 221, 209, - 95, 247, 101, 234, 164, 79, 229, 221, 209, 95, 247, 101, 213, 175, 79, - 229, 221, 209, 95, 247, 101, 199, 96, 79, 229, 221, 209, 95, 247, 101, - 223, 30, 79, 229, 221, 209, 95, 247, 101, 221, 77, 79, 229, 221, 209, 95, - 247, 101, 208, 15, 79, 229, 221, 209, 95, 247, 101, 221, 139, 79, 229, - 221, 209, 95, 247, 101, 207, 87, 222, 194, 209, 95, 247, 101, 252, 53, - 79, 237, 31, 209, 95, 247, 101, 105, 79, 237, 31, 209, 95, 247, 101, 115, - 79, 237, 31, 209, 95, 247, 101, 232, 128, 79, 237, 31, 209, 95, 247, 101, - 232, 226, 79, 237, 31, 209, 95, 247, 101, 202, 136, 79, 237, 31, 209, 95, - 247, 101, 203, 247, 79, 237, 31, 209, 95, 247, 101, 234, 164, 79, 237, - 31, 209, 95, 247, 101, 213, 175, 79, 237, 31, 209, 95, 247, 101, 199, 96, - 79, 237, 31, 209, 95, 247, 101, 223, 30, 79, 237, 31, 209, 95, 247, 101, - 221, 77, 79, 237, 31, 209, 95, 247, 101, 208, 15, 79, 237, 31, 209, 95, - 247, 101, 221, 139, 79, 237, 31, 209, 95, 247, 101, 62, 222, 194, 209, - 95, 247, 101, 252, 53, 79, 242, 204, 209, 95, 247, 101, 105, 79, 242, - 204, 209, 95, 247, 101, 115, 79, 242, 204, 209, 95, 247, 101, 232, 128, - 79, 242, 204, 209, 95, 247, 101, 232, 226, 79, 242, 204, 209, 95, 247, - 101, 202, 136, 79, 242, 204, 209, 95, 247, 101, 203, 247, 79, 242, 204, - 209, 95, 247, 101, 234, 164, 79, 242, 204, 209, 95, 247, 101, 213, 175, - 79, 242, 204, 209, 95, 247, 101, 199, 96, 79, 242, 204, 209, 95, 247, - 101, 223, 30, 79, 242, 204, 209, 95, 247, 101, 221, 77, 79, 242, 204, - 209, 95, 247, 101, 208, 15, 79, 242, 204, 209, 95, 247, 101, 221, 139, - 79, 242, 204, 209, 95, 247, 101, 63, 222, 194, 209, 95, 247, 101, 232, - 160, 209, 95, 247, 101, 197, 200, 209, 95, 247, 101, 197, 189, 209, 95, - 247, 101, 197, 186, 209, 95, 247, 101, 197, 185, 209, 95, 247, 101, 197, - 184, 209, 95, 247, 101, 197, 183, 209, 95, 247, 101, 197, 182, 209, 95, - 247, 101, 197, 181, 209, 95, 247, 101, 197, 180, 209, 95, 247, 101, 197, - 199, 209, 95, 247, 101, 197, 198, 209, 95, 247, 101, 197, 197, 209, 95, - 247, 101, 197, 196, 209, 95, 247, 101, 197, 195, 209, 95, 247, 101, 197, - 194, 209, 95, 247, 101, 197, 193, 209, 95, 247, 101, 197, 192, 209, 95, - 247, 101, 197, 191, 209, 95, 247, 101, 197, 190, 209, 95, 247, 101, 197, - 188, 209, 95, 247, 101, 197, 187, 17, 191, 78, 232, 80, 201, 63, 17, 191, - 78, 242, 74, 17, 91, 242, 74, 17, 105, 242, 74, 17, 115, 242, 74, 17, - 232, 128, 242, 74, 17, 232, 226, 242, 74, 17, 202, 136, 242, 74, 17, 203, - 247, 242, 74, 17, 234, 164, 242, 74, 17, 213, 175, 242, 74, 236, 241, 47, - 49, 17, 191, 77, 236, 241, 214, 106, 47, 49, 17, 191, 77, 47, 191, 78, 4, - 202, 97, 47, 251, 85, 57, 47, 236, 155, 3, 4, 211, 4, 249, 141, 127, 8, - 6, 1, 65, 127, 8, 6, 1, 250, 120, 127, 8, 6, 1, 247, 193, 127, 8, 6, 1, - 238, 127, 127, 8, 6, 1, 71, 127, 8, 6, 1, 233, 175, 127, 8, 6, 1, 232, - 51, 127, 8, 6, 1, 230, 116, 127, 8, 6, 1, 68, 127, 8, 6, 1, 223, 35, 127, - 8, 6, 1, 222, 152, 127, 8, 6, 1, 172, 127, 8, 6, 1, 218, 168, 127, 8, 6, - 1, 215, 61, 127, 8, 6, 1, 74, 127, 8, 6, 1, 210, 236, 127, 8, 6, 1, 208, - 104, 127, 8, 6, 1, 146, 127, 8, 6, 1, 206, 8, 127, 8, 6, 1, 200, 43, 127, - 8, 6, 1, 66, 127, 8, 6, 1, 196, 12, 127, 8, 6, 1, 193, 224, 127, 8, 6, 1, - 192, 235, 127, 8, 6, 1, 192, 159, 127, 8, 6, 1, 191, 166, 198, 42, 203, - 103, 248, 52, 8, 6, 1, 206, 8, 47, 43, 8, 6, 1, 247, 193, 47, 43, 8, 6, - 1, 146, 47, 247, 43, 47, 192, 237, 239, 7, 113, 112, 8, 6, 1, 65, 112, 8, - 6, 1, 250, 120, 112, 8, 6, 1, 247, 193, 112, 8, 6, 1, 238, 127, 112, 8, - 6, 1, 71, 112, 8, 6, 1, 233, 175, 112, 8, 6, 1, 232, 51, 112, 8, 6, 1, - 230, 116, 112, 8, 6, 1, 68, 112, 8, 6, 1, 223, 35, 112, 8, 6, 1, 222, - 152, 112, 8, 6, 1, 172, 112, 8, 6, 1, 218, 168, 112, 8, 6, 1, 215, 61, - 112, 8, 6, 1, 74, 112, 8, 6, 1, 210, 236, 112, 8, 6, 1, 208, 104, 112, 8, - 6, 1, 146, 112, 8, 6, 1, 206, 8, 112, 8, 6, 1, 200, 43, 112, 8, 6, 1, 66, - 112, 8, 6, 1, 196, 12, 112, 8, 6, 1, 193, 224, 112, 8, 6, 1, 192, 235, - 112, 8, 6, 1, 192, 159, 112, 8, 6, 1, 191, 166, 112, 228, 126, 112, 215, - 87, 112, 205, 70, 112, 201, 178, 112, 208, 248, 112, 193, 126, 214, 106, - 47, 8, 6, 1, 65, 214, 106, 47, 8, 6, 1, 250, 120, 214, 106, 47, 8, 6, 1, - 247, 193, 214, 106, 47, 8, 6, 1, 238, 127, 214, 106, 47, 8, 6, 1, 71, - 214, 106, 47, 8, 6, 1, 233, 175, 214, 106, 47, 8, 6, 1, 232, 51, 214, - 106, 47, 8, 6, 1, 230, 116, 214, 106, 47, 8, 6, 1, 68, 214, 106, 47, 8, - 6, 1, 223, 35, 214, 106, 47, 8, 6, 1, 222, 152, 214, 106, 47, 8, 6, 1, - 172, 214, 106, 47, 8, 6, 1, 218, 168, 214, 106, 47, 8, 6, 1, 215, 61, - 214, 106, 47, 8, 6, 1, 74, 214, 106, 47, 8, 6, 1, 210, 236, 214, 106, 47, - 8, 6, 1, 208, 104, 214, 106, 47, 8, 6, 1, 146, 214, 106, 47, 8, 6, 1, - 206, 8, 214, 106, 47, 8, 6, 1, 200, 43, 214, 106, 47, 8, 6, 1, 66, 214, - 106, 47, 8, 6, 1, 196, 12, 214, 106, 47, 8, 6, 1, 193, 224, 214, 106, 47, - 8, 6, 1, 192, 235, 214, 106, 47, 8, 6, 1, 192, 159, 214, 106, 47, 8, 6, - 1, 191, 166, 207, 147, 216, 239, 56, 207, 147, 216, 235, 56, 207, 147, - 215, 164, 56, 47, 247, 66, 47, 247, 194, 4, 211, 4, 249, 141, 47, 228, - 145, 233, 12, 214, 106, 112, 8, 6, 1, 65, 214, 106, 112, 8, 6, 1, 250, - 120, 214, 106, 112, 8, 6, 1, 247, 193, 214, 106, 112, 8, 6, 1, 238, 127, - 214, 106, 112, 8, 6, 1, 71, 214, 106, 112, 8, 6, 1, 233, 175, 214, 106, - 112, 8, 6, 1, 232, 51, 214, 106, 112, 8, 6, 1, 230, 116, 214, 106, 112, - 8, 6, 1, 68, 214, 106, 112, 8, 6, 1, 223, 35, 214, 106, 112, 8, 6, 1, - 222, 152, 214, 106, 112, 8, 6, 1, 172, 214, 106, 112, 8, 6, 1, 218, 168, - 214, 106, 112, 8, 6, 1, 215, 61, 214, 106, 112, 8, 6, 1, 74, 214, 106, - 112, 8, 6, 1, 210, 236, 214, 106, 112, 8, 6, 1, 208, 104, 214, 106, 112, - 8, 6, 1, 146, 214, 106, 112, 8, 6, 1, 206, 8, 214, 106, 112, 8, 6, 1, - 200, 43, 214, 106, 112, 8, 6, 1, 66, 214, 106, 112, 8, 6, 1, 196, 12, - 214, 106, 112, 8, 6, 1, 193, 224, 214, 106, 112, 8, 6, 1, 192, 235, 214, - 106, 112, 8, 6, 1, 192, 159, 214, 106, 112, 8, 6, 1, 191, 166, 238, 214, - 214, 106, 112, 8, 6, 1, 210, 236, 214, 106, 112, 228, 28, 214, 106, 112, - 168, 214, 106, 112, 188, 214, 106, 112, 252, 155, 214, 106, 112, 193, - 126, 51, 236, 194, 112, 242, 247, 112, 239, 14, 112, 232, 108, 112, 228, - 19, 112, 214, 79, 112, 214, 70, 112, 211, 125, 112, 202, 9, 112, 133, 4, - 233, 216, 77, 112, 194, 252, 112, 115, 238, 127, 112, 205, 57, 205, 76, - 112, 105, 222, 152, 112, 232, 128, 222, 152, 112, 234, 164, 222, 152, - 112, 232, 226, 209, 62, 107, 112, 203, 247, 209, 62, 107, 112, 197, 21, - 209, 62, 109, 112, 202, 121, 210, 236, 112, 91, 228, 141, 197, 33, 210, - 236, 112, 8, 2, 1, 238, 127, 112, 229, 248, 112, 229, 247, 112, 229, 150, - 112, 218, 252, 112, 202, 241, 112, 196, 140, 112, 195, 21, 217, 36, 193, - 21, 113, 207, 79, 223, 145, 16, 1, 65, 207, 79, 223, 145, 16, 1, 250, - 120, 207, 79, 223, 145, 16, 1, 247, 193, 207, 79, 223, 145, 16, 1, 238, - 127, 207, 79, 223, 145, 16, 1, 71, 207, 79, 223, 145, 16, 1, 233, 175, - 207, 79, 223, 145, 16, 1, 232, 51, 207, 79, 223, 145, 16, 1, 230, 116, - 207, 79, 223, 145, 16, 1, 68, 207, 79, 223, 145, 16, 1, 223, 35, 207, 79, - 223, 145, 16, 1, 222, 152, 207, 79, 223, 145, 16, 1, 172, 207, 79, 223, - 145, 16, 1, 218, 168, 207, 79, 223, 145, 16, 1, 215, 61, 207, 79, 223, - 145, 16, 1, 74, 207, 79, 223, 145, 16, 1, 210, 236, 207, 79, 223, 145, - 16, 1, 208, 104, 207, 79, 223, 145, 16, 1, 146, 207, 79, 223, 145, 16, 1, - 206, 8, 207, 79, 223, 145, 16, 1, 200, 43, 207, 79, 223, 145, 16, 1, 66, - 207, 79, 223, 145, 16, 1, 196, 12, 207, 79, 223, 145, 16, 1, 193, 224, - 207, 79, 223, 145, 16, 1, 192, 235, 207, 79, 223, 145, 16, 1, 192, 159, - 207, 79, 223, 145, 16, 1, 191, 166, 51, 229, 120, 229, 9, 112, 72, 221, - 49, 112, 72, 188, 112, 12, 196, 95, 225, 217, 112, 12, 196, 95, 225, 221, - 112, 12, 196, 95, 225, 229, 112, 72, 237, 146, 112, 12, 196, 95, 225, - 236, 112, 12, 196, 95, 225, 223, 112, 12, 196, 95, 225, 195, 112, 12, - 196, 95, 225, 222, 112, 12, 196, 95, 225, 235, 112, 12, 196, 95, 225, - 209, 112, 12, 196, 95, 225, 202, 112, 12, 196, 95, 225, 211, 112, 12, - 196, 95, 225, 232, 112, 12, 196, 95, 225, 218, 112, 12, 196, 95, 225, - 234, 112, 12, 196, 95, 225, 210, 112, 12, 196, 95, 225, 233, 112, 12, - 196, 95, 225, 196, 112, 12, 196, 95, 225, 201, 112, 12, 196, 95, 225, - 194, 112, 12, 196, 95, 225, 224, 112, 12, 196, 95, 225, 226, 112, 12, - 196, 95, 225, 204, 112, 12, 196, 95, 225, 215, 112, 12, 196, 95, 225, - 213, 112, 12, 196, 95, 225, 239, 112, 12, 196, 95, 225, 238, 112, 12, - 196, 95, 225, 192, 112, 12, 196, 95, 225, 219, 112, 12, 196, 95, 225, - 237, 112, 12, 196, 95, 225, 228, 112, 12, 196, 95, 225, 214, 112, 12, - 196, 95, 225, 193, 112, 12, 196, 95, 225, 216, 112, 12, 196, 95, 225, - 198, 112, 12, 196, 95, 225, 197, 112, 12, 196, 95, 225, 227, 112, 12, - 196, 95, 225, 205, 112, 12, 196, 95, 225, 207, 112, 12, 196, 95, 225, - 208, 112, 12, 196, 95, 225, 200, 112, 12, 196, 95, 225, 231, 112, 12, - 196, 95, 225, 225, 112, 12, 196, 95, 225, 191, 198, 42, 203, 103, 248, - 52, 12, 196, 95, 225, 206, 198, 42, 203, 103, 248, 52, 12, 196, 95, 225, - 238, 198, 42, 203, 103, 248, 52, 12, 196, 95, 225, 236, 198, 42, 203, - 103, 248, 52, 12, 196, 95, 225, 220, 198, 42, 203, 103, 248, 52, 12, 196, - 95, 225, 203, 198, 42, 203, 103, 248, 52, 12, 196, 95, 225, 216, 198, 42, - 203, 103, 248, 52, 12, 196, 95, 225, 199, 198, 42, 203, 103, 248, 52, 12, - 196, 95, 225, 230, 198, 42, 203, 103, 248, 52, 12, 196, 95, 225, 212, 47, - 228, 14, 252, 27, 47, 228, 14, 252, 58, 206, 113, 16, 40, 232, 86, 206, - 113, 16, 40, 218, 225, 206, 113, 16, 40, 203, 23, 206, 113, 16, 40, 192, - 207, 206, 113, 16, 40, 203, 2, 206, 113, 16, 40, 247, 148, 238, 139, 232, - 173, 242, 219, 196, 117, 213, 191, 4, 201, 99, 200, 193, 139, 215, 183, - 200, 192, 242, 251, 250, 183, 235, 61, 200, 191, 139, 247, 253, 207, 148, - 248, 29, 250, 183, 213, 190, 193, 144, 193, 138, 195, 14, 216, 52, 193, - 128, 234, 208, 231, 12, 233, 232, 234, 208, 231, 12, 251, 140, 234, 208, - 231, 12, 250, 202, 231, 12, 4, 216, 177, 214, 80, 215, 206, 113, 193, - 130, 238, 228, 215, 206, 113, 232, 238, 208, 23, 215, 206, 113, 193, 130, - 231, 49, 215, 206, 113, 232, 80, 215, 206, 113, 193, 159, 231, 49, 215, - 206, 113, 220, 6, 208, 23, 215, 206, 113, 193, 159, 238, 228, 215, 206, - 113, 238, 228, 215, 205, 214, 80, 215, 206, 4, 233, 103, 232, 238, 208, - 23, 215, 206, 4, 233, 103, 220, 6, 208, 23, 215, 206, 4, 233, 103, 232, - 80, 215, 206, 4, 233, 103, 200, 199, 4, 233, 103, 231, 8, 201, 102, 203, - 45, 201, 102, 199, 21, 62, 235, 97, 63, 200, 198, 63, 200, 199, 4, 2, - 242, 210, 63, 200, 199, 248, 242, 242, 210, 63, 200, 199, 248, 242, 242, - 211, 4, 207, 149, 242, 211, 4, 207, 149, 242, 211, 4, 202, 52, 242, 211, - 4, 219, 129, 242, 211, 4, 198, 46, 232, 174, 193, 67, 248, 116, 233, 103, - 228, 181, 236, 162, 199, 227, 247, 228, 243, 103, 205, 48, 233, 226, 197, - 254, 237, 139, 197, 254, 210, 183, 197, 254, 247, 153, 228, 181, 210, 15, - 197, 78, 243, 107, 248, 119, 206, 126, 229, 149, 200, 196, 248, 119, 234, - 212, 79, 217, 103, 234, 212, 79, 206, 245, 229, 193, 232, 128, 219, 234, - 242, 209, 217, 69, 219, 233, 233, 84, 219, 233, 219, 234, 232, 181, 223, - 163, 193, 66, 215, 98, 198, 83, 250, 162, 230, 218, 216, 196, 193, 142, - 199, 187, 219, 201, 249, 98, 209, 133, 207, 87, 251, 46, 230, 201, 251, - 46, 210, 55, 210, 59, 243, 108, 201, 42, 230, 63, 202, 89, 79, 209, 112, - 216, 225, 211, 105, 248, 98, 209, 9, 219, 212, 206, 246, 238, 234, 206, - 246, 249, 111, 239, 17, 206, 245, 238, 167, 23, 206, 245, 201, 83, 248, - 66, 201, 243, 248, 43, 232, 106, 232, 102, 206, 152, 200, 142, 209, 12, - 237, 235, 211, 153, 200, 165, 232, 103, 203, 13, 232, 237, 247, 147, 4, - 200, 134, 237, 80, 202, 32, 228, 27, 238, 232, 203, 121, 228, 26, 228, - 27, 238, 232, 235, 126, 239, 16, 243, 66, 164, 247, 118, 219, 24, 238, - 158, 228, 254, 209, 14, 203, 29, 248, 222, 248, 62, 209, 15, 79, 232, - 161, 239, 15, 232, 150, 23, 221, 78, 199, 133, 193, 51, 230, 31, 205, - 176, 248, 79, 23, 238, 181, 193, 63, 231, 16, 242, 94, 231, 16, 197, 204, - 235, 104, 248, 253, 215, 140, 242, 226, 248, 253, 215, 139, 249, 149, - 248, 78, 232, 150, 23, 221, 79, 4, 209, 97, 248, 79, 4, 209, 30, 239, 3, - 209, 32, 206, 247, 193, 11, 208, 222, 248, 157, 247, 146, 223, 29, 243, - 56, 197, 254, 233, 67, 243, 55, 232, 240, 232, 241, 201, 241, 249, 109, - 210, 102, 209, 31, 239, 54, 249, 111, 199, 191, 197, 254, 238, 214, 232, - 211, 209, 134, 237, 136, 223, 19, 236, 154, 247, 90, 201, 41, 193, 67, - 243, 82, 215, 206, 195, 54, 247, 8, 205, 90, 205, 120, 230, 225, 247, - 111, 229, 224, 4, 198, 136, 211, 105, 199, 34, 219, 224, 248, 72, 79, - 232, 185, 216, 54, 216, 219, 207, 58, 206, 247, 37, 221, 221, 4, 223, 28, - 201, 11, 216, 89, 219, 168, 202, 86, 239, 22, 221, 72, 249, 13, 250, 213, - 37, 213, 1, 249, 13, 237, 86, 37, 213, 1, 233, 0, 232, 112, 252, 31, 198, - 180, 247, 91, 228, 183, 233, 33, 193, 93, 206, 139, 242, 97, 232, 232, - 209, 53, 23, 232, 236, 216, 89, 215, 169, 247, 132, 243, 14, 229, 231, - 250, 224, 210, 188, 198, 54, 230, 9, 243, 0, 199, 87, 198, 181, 242, 242, - 248, 107, 210, 6, 250, 222, 195, 65, 231, 214, 236, 234, 229, 117, 202, - 79, 217, 148, 248, 170, 231, 215, 237, 24, 248, 65, 232, 187, 209, 95, - 247, 99, 37, 213, 6, 215, 129, 37, 213, 1, 205, 104, 230, 162, 37, 221, - 220, 197, 179, 195, 42, 37, 205, 82, 206, 42, 203, 60, 4, 205, 123, 199, - 92, 207, 170, 23, 249, 111, 202, 109, 23, 202, 109, 248, 91, 249, 68, 23, - 228, 247, 243, 109, 232, 217, 202, 51, 206, 43, 200, 170, 201, 202, 216, - 219, 197, 205, 228, 184, 207, 171, 251, 141, 232, 158, 206, 56, 232, 158, - 200, 137, 193, 110, 219, 134, 230, 249, 207, 172, 215, 191, 207, 172, - 247, 102, 238, 225, 249, 65, 23, 249, 111, 195, 13, 233, 22, 229, 12, - 201, 75, 23, 249, 111, 228, 27, 229, 12, 201, 75, 23, 208, 157, 199, 234, - 199, 92, 210, 207, 23, 249, 111, 202, 53, 247, 107, 215, 184, 247, 130, - 249, 16, 4, 196, 117, 247, 255, 239, 36, 228, 173, 247, 253, 242, 250, - 237, 90, 228, 173, 247, 254, 242, 240, 247, 254, 237, 82, 237, 83, 223, - 60, 214, 208, 210, 109, 201, 113, 228, 173, 247, 254, 228, 173, 4, 231, - 198, 211, 144, 247, 254, 223, 19, 209, 20, 211, 143, 233, 231, 209, 20, - 211, 143, 228, 182, 249, 92, 250, 151, 199, 102, 217, 148, 228, 178, 218, - 242, 228, 178, 239, 20, 201, 57, 205, 89, 237, 94, 201, 57, 233, 92, 223, - 40, 220, 18, 223, 19, 247, 80, 233, 231, 247, 80, 63, 210, 28, 62, 210, - 28, 193, 136, 63, 232, 217, 193, 136, 62, 232, 217, 206, 125, 62, 206, - 125, 220, 117, 249, 132, 207, 170, 23, 202, 244, 248, 70, 23, 57, 251, - 136, 234, 109, 52, 232, 227, 196, 253, 234, 109, 52, 232, 227, 196, 250, - 234, 109, 52, 232, 227, 196, 248, 234, 109, 52, 232, 227, 196, 246, 234, - 109, 52, 232, 227, 196, 244, 207, 130, 215, 181, 210, 247, 193, 144, 248, - 3, 238, 239, 198, 173, 219, 185, 207, 174, 247, 78, 235, 111, 238, 223, - 193, 96, 202, 60, 202, 58, 228, 183, 207, 142, 230, 255, 203, 107, 215, - 225, 206, 129, 243, 93, 236, 162, 209, 147, 248, 109, 234, 131, 211, 156, - 201, 218, 203, 102, 248, 2, 251, 89, 228, 253, 220, 108, 248, 251, 232, - 236, 197, 204, 232, 236, 248, 117, 197, 55, 230, 7, 243, 94, 249, 149, - 243, 94, 232, 96, 249, 149, 243, 94, 248, 160, 210, 30, 221, 61, 209, 36, - 235, 101, 247, 134, 249, 137, 247, 134, 236, 153, 215, 182, 233, 103, - 238, 240, 233, 103, 198, 174, 233, 103, 207, 175, 233, 103, 247, 79, 233, - 103, 235, 112, 233, 103, 201, 200, 193, 96, 228, 184, 233, 103, 215, 226, - 233, 103, 236, 163, 233, 103, 209, 148, 233, 103, 232, 100, 233, 103, - 230, 59, 233, 103, 193, 38, 233, 103, 249, 10, 233, 103, 210, 162, 233, - 103, 209, 148, 213, 13, 210, 76, 208, 208, 243, 77, 233, 185, 233, 193, - 234, 211, 213, 13, 215, 179, 198, 61, 63, 133, 209, 58, 249, 144, 223, - 148, 63, 144, 209, 58, 249, 144, 223, 148, 63, 45, 209, 58, 249, 144, - 223, 148, 63, 50, 209, 58, 249, 144, 223, 148, 232, 230, 230, 54, 56, - 193, 136, 230, 54, 56, 211, 126, 230, 54, 56, 198, 211, 133, 56, 198, - 211, 144, 56, 242, 241, 230, 29, 56, 211, 77, 230, 29, 56, 238, 208, 193, - 34, 230, 9, 233, 188, 214, 111, 200, 41, 223, 9, 235, 106, 221, 142, 248, - 173, 193, 34, 242, 212, 208, 137, 230, 33, 209, 10, 217, 78, 203, 52, - 250, 178, 203, 52, 229, 134, 203, 52, 193, 34, 205, 139, 193, 34, 248, - 90, 232, 156, 247, 220, 223, 163, 202, 187, 247, 219, 223, 163, 202, 187, - 248, 60, 231, 28, 217, 90, 193, 35, 233, 81, 217, 91, 23, 193, 36, 229, - 6, 230, 28, 105, 216, 187, 229, 6, 230, 28, 105, 193, 33, 229, 6, 230, - 28, 209, 50, 211, 142, 193, 36, 4, 247, 239, 234, 209, 248, 30, 4, 195, - 144, 209, 251, 4, 248, 121, 230, 78, 217, 91, 4, 230, 176, 209, 186, 217, - 73, 217, 91, 4, 197, 63, 211, 118, 217, 90, 211, 118, 193, 35, 249, 148, - 239, 37, 193, 19, 208, 213, 223, 19, 211, 137, 223, 19, 230, 254, 231, - 61, 249, 149, 251, 120, 233, 198, 251, 182, 251, 183, 215, 215, 223, 168, - 202, 103, 223, 137, 237, 79, 209, 250, 230, 170, 237, 240, 219, 95, 214, - 235, 209, 48, 233, 104, 217, 33, 230, 77, 249, 86, 209, 52, 200, 62, 209, - 140, 221, 123, 77, 218, 242, 219, 175, 206, 188, 231, 155, 201, 65, 221, - 122, 248, 71, 238, 243, 4, 229, 223, 193, 117, 249, 6, 229, 223, 248, 22, - 229, 223, 105, 229, 221, 201, 239, 229, 223, 230, 186, 229, 223, 229, - 224, 4, 57, 248, 115, 229, 223, 230, 201, 229, 223, 192, 73, 229, 223, - 208, 138, 229, 223, 229, 224, 4, 206, 247, 207, 12, 229, 221, 229, 224, - 237, 136, 237, 33, 203, 135, 4, 42, 75, 223, 117, 234, 135, 156, 247, - 251, 251, 119, 113, 248, 99, 202, 92, 113, 242, 85, 113, 201, 212, 200, - 144, 113, 235, 97, 237, 216, 113, 209, 141, 79, 209, 37, 232, 199, 248, - 185, 236, 195, 113, 201, 230, 249, 109, 198, 231, 249, 109, 63, 232, 186, - 228, 141, 209, 56, 113, 215, 230, 249, 130, 238, 170, 233, 218, 88, 236, - 155, 56, 238, 230, 247, 100, 249, 91, 4, 192, 71, 56, 249, 91, 4, 236, - 155, 56, 249, 91, 4, 233, 234, 56, 249, 91, 4, 209, 8, 56, 215, 230, 4, - 193, 60, 243, 137, 4, 196, 66, 197, 250, 23, 192, 71, 56, 205, 60, 209, - 249, 239, 59, 248, 28, 216, 41, 232, 191, 236, 220, 211, 60, 236, 226, - 235, 55, 233, 7, 232, 171, 211, 77, 233, 7, 232, 171, 210, 205, 4, 238, - 175, 210, 205, 233, 96, 196, 77, 247, 140, 199, 130, 247, 140, 247, 101, - 223, 148, 243, 137, 4, 196, 66, 197, 249, 243, 137, 4, 235, 119, 197, - 249, 249, 88, 243, 136, 242, 225, 208, 133, 206, 115, 208, 133, 210, 134, - 201, 53, 206, 50, 197, 238, 206, 50, 248, 95, 199, 232, 219, 229, 213, 4, - 213, 5, 4, 237, 135, 238, 242, 242, 219, 248, 96, 211, 77, 248, 96, 230, - 201, 248, 96, 248, 115, 248, 96, 211, 55, 248, 96, 248, 93, 214, 228, - 249, 134, 205, 73, 216, 188, 199, 107, 207, 101, 210, 203, 233, 64, 217, - 148, 205, 119, 251, 86, 208, 158, 252, 39, 218, 244, 243, 119, 216, 201, - 211, 13, 198, 2, 223, 159, 198, 2, 210, 212, 235, 8, 113, 223, 156, 234, - 67, 234, 68, 4, 235, 119, 64, 58, 242, 219, 217, 109, 4, 218, 235, 232, - 217, 242, 219, 217, 109, 4, 207, 147, 232, 217, 211, 77, 217, 109, 4, - 207, 147, 232, 217, 211, 77, 217, 109, 4, 218, 235, 232, 217, 209, 17, - 209, 18, 228, 187, 214, 75, 216, 4, 209, 194, 216, 4, 209, 195, 4, 96, - 64, 250, 183, 219, 224, 195, 68, 216, 3, 216, 4, 209, 195, 211, 145, 213, - 44, 216, 4, 209, 193, 251, 87, 4, 249, 76, 247, 132, 247, 133, 4, 232, - 208, 195, 65, 247, 132, 199, 104, 207, 165, 195, 64, 233, 0, 208, 193, - 209, 27, 201, 77, 208, 236, 249, 15, 197, 17, 96, 250, 231, 242, 221, 96, - 23, 118, 211, 77, 243, 11, 250, 231, 242, 221, 96, 23, 118, 211, 77, 243, - 11, 250, 232, 4, 47, 91, 210, 255, 242, 221, 235, 119, 23, 196, 66, 211, - 77, 243, 11, 250, 231, 251, 85, 235, 119, 23, 196, 66, 211, 77, 243, 11, - 250, 231, 130, 248, 26, 113, 137, 248, 26, 113, 201, 235, 4, 247, 125, - 106, 201, 234, 201, 235, 4, 91, 202, 5, 193, 138, 201, 235, 4, 115, 202, - 5, 193, 137, 249, 58, 234, 135, 209, 87, 219, 219, 217, 121, 231, 16, - 206, 203, 217, 121, 231, 16, 219, 35, 4, 223, 129, 210, 34, 242, 219, - 219, 35, 4, 221, 222, 221, 222, 219, 34, 211, 77, 219, 34, 248, 235, 248, - 236, 4, 247, 125, 106, 248, 94, 219, 103, 113, 207, 166, 247, 213, 249, - 147, 4, 118, 64, 58, 234, 95, 4, 118, 64, 58, 211, 105, 4, 233, 216, 87, - 4, 45, 50, 64, 58, 202, 15, 4, 96, 64, 58, 198, 54, 4, 196, 66, 64, 58, - 213, 44, 91, 196, 105, 234, 162, 113, 221, 219, 199, 95, 223, 123, 16, - 40, 8, 6, 219, 174, 223, 123, 16, 40, 8, 2, 219, 174, 223, 123, 16, 40, - 212, 135, 223, 123, 16, 40, 200, 76, 223, 123, 16, 40, 8, 219, 174, 232, - 243, 234, 135, 198, 49, 193, 9, 230, 61, 212, 118, 23, 248, 101, 229, 13, - 209, 118, 216, 88, 199, 105, 238, 197, 249, 111, 202, 136, 209, 60, 201, - 103, 4, 82, 236, 140, 223, 19, 16, 40, 248, 248, 197, 236, 234, 111, 62, - 51, 247, 213, 63, 51, 247, 213, 220, 13, 207, 87, 243, 10, 220, 13, 248, - 115, 243, 10, 220, 13, 211, 55, 237, 32, 220, 13, 248, 115, 237, 32, 2, - 211, 55, 237, 32, 2, 248, 115, 237, 32, 196, 76, 207, 87, 197, 241, 235, - 122, 207, 87, 197, 241, 196, 76, 2, 207, 87, 197, 241, 235, 122, 2, 207, - 87, 197, 241, 110, 50, 203, 151, 63, 243, 10, 116, 50, 203, 151, 63, 243, - 10, 47, 238, 218, 209, 41, 238, 218, 209, 42, 4, 230, 67, 60, 238, 218, - 209, 41, 213, 8, 45, 204, 28, 4, 115, 236, 138, 213, 8, 50, 204, 28, 4, - 115, 236, 138, 16, 40, 217, 50, 246, 242, 63, 8, 238, 217, 88, 8, 238, - 217, 247, 26, 238, 217, 211, 114, 113, 235, 125, 79, 210, 60, 222, 125, - 215, 197, 200, 70, 216, 183, 4, 213, 175, 248, 46, 248, 67, 79, 228, 90, - 242, 223, 233, 104, 91, 211, 162, 242, 223, 233, 104, 105, 211, 162, 242, - 223, 233, 104, 115, 211, 162, 242, 223, 233, 104, 232, 128, 211, 162, - 242, 223, 233, 104, 232, 226, 211, 162, 242, 223, 233, 104, 202, 136, - 211, 162, 242, 223, 233, 104, 203, 247, 211, 162, 242, 223, 233, 104, - 234, 164, 211, 162, 242, 223, 233, 104, 213, 175, 211, 162, 242, 223, - 233, 104, 199, 96, 211, 162, 242, 223, 233, 104, 234, 128, 211, 162, 242, - 223, 233, 104, 197, 38, 211, 162, 242, 223, 233, 104, 211, 97, 242, 223, - 233, 104, 197, 11, 242, 223, 233, 104, 198, 217, 242, 223, 233, 104, 232, - 124, 242, 223, 233, 104, 232, 223, 242, 223, 233, 104, 202, 132, 242, - 223, 233, 104, 203, 246, 242, 223, 233, 104, 234, 163, 242, 223, 233, - 104, 213, 173, 242, 223, 233, 104, 199, 94, 242, 223, 233, 104, 234, 126, - 242, 223, 233, 104, 197, 36, 50, 201, 234, 50, 201, 235, 4, 91, 202, 5, - 193, 138, 50, 201, 235, 4, 115, 202, 5, 193, 137, 247, 246, 247, 247, 4, - 202, 5, 193, 137, 206, 186, 248, 235, 248, 96, 247, 123, 217, 75, 242, - 222, 62, 202, 104, 23, 238, 215, 213, 44, 209, 124, 229, 5, 217, 91, 223, - 163, 247, 222, 200, 212, 219, 165, 202, 90, 211, 57, 201, 191, 237, 221, - 200, 194, 201, 221, 201, 222, 193, 118, 222, 183, 217, 91, 237, 239, 45, - 230, 54, 199, 107, 207, 101, 199, 107, 207, 102, 4, 210, 204, 50, 230, - 54, 199, 107, 207, 101, 63, 198, 34, 199, 106, 62, 198, 34, 199, 106, - 199, 107, 211, 105, 198, 54, 79, 216, 0, 242, 245, 216, 4, 209, 194, 249, - 147, 79, 234, 67, 201, 109, 234, 67, 234, 68, 4, 219, 129, 232, 178, 234, - 67, 210, 35, 139, 201, 109, 234, 67, 219, 102, 210, 133, 62, 208, 133, - 110, 45, 210, 33, 110, 45, 249, 105, 210, 34, 110, 45, 232, 130, 210, 34, - 110, 45, 210, 197, 110, 45, 238, 233, 45, 193, 3, 230, 53, 153, 211, 126, - 230, 54, 56, 207, 147, 230, 54, 4, 232, 248, 201, 211, 207, 18, 207, 147, - 230, 54, 4, 232, 248, 201, 211, 207, 18, 198, 211, 133, 56, 207, 18, 198, - 211, 144, 56, 207, 18, 195, 67, 230, 53, 207, 18, 230, 54, 4, 82, 232, - 253, 233, 204, 207, 147, 230, 54, 4, 210, 107, 248, 210, 82, 23, 206, - 189, 232, 247, 63, 144, 209, 58, 45, 230, 54, 223, 148, 202, 206, 63, 45, - 209, 58, 223, 148, 202, 206, 63, 50, 209, 58, 223, 148, 202, 206, 62, 45, - 209, 58, 223, 148, 202, 206, 62, 50, 209, 58, 223, 148, 62, 45, 209, 58, - 249, 144, 223, 148, 62, 50, 209, 58, 249, 144, 223, 148, 202, 206, 63, - 133, 209, 58, 223, 148, 202, 206, 63, 144, 209, 58, 223, 148, 202, 206, - 62, 133, 209, 58, 223, 148, 202, 206, 62, 144, 209, 58, 223, 148, 62, - 133, 209, 58, 249, 144, 223, 148, 62, 144, 209, 58, 249, 144, 223, 148, - 62, 229, 223, 237, 78, 239, 59, 221, 221, 23, 215, 181, 115, 214, 84, - 239, 58, 208, 209, 209, 71, 247, 142, 62, 230, 17, 203, 103, 232, 191, - 236, 220, 63, 230, 17, 203, 103, 232, 191, 236, 220, 202, 32, 203, 103, - 232, 191, 236, 220, 199, 182, 247, 84, 193, 55, 221, 220, 91, 247, 214, - 215, 181, 105, 247, 214, 215, 181, 115, 247, 214, 215, 181, 198, 24, 39, - 209, 249, 239, 59, 230, 17, 236, 220, 205, 76, 208, 210, 228, 20, 233, - 64, 228, 20, 211, 60, 236, 227, 228, 20, 236, 168, 4, 199, 53, 236, 168, - 4, 199, 54, 23, 209, 177, 236, 168, 4, 209, 177, 232, 114, 4, 209, 177, - 232, 114, 4, 198, 150, 232, 114, 4, 251, 133, 192, 235, 62, 232, 171, - 232, 171, 211, 77, 232, 171, 247, 101, 141, 236, 204, 247, 101, 233, 7, - 248, 62, 233, 7, 247, 155, 234, 105, 213, 6, 234, 105, 213, 7, 210, 204, - 234, 105, 213, 7, 210, 210, 213, 6, 213, 7, 210, 204, 213, 7, 210, 210, - 234, 105, 236, 167, 234, 105, 210, 204, 234, 105, 210, 202, 236, 167, - 210, 204, 210, 202, 193, 148, 201, 218, 213, 7, 210, 210, 201, 218, 247, - 141, 210, 210, 237, 78, 193, 65, 216, 38, 217, 22, 211, 2, 242, 221, 50, - 23, 45, 204, 28, 250, 231, 247, 125, 192, 235, 223, 154, 232, 163, 202, - 116, 113, 237, 134, 232, 163, 202, 116, 113, 239, 60, 39, 221, 222, 206, - 140, 214, 75, 210, 205, 4, 47, 199, 53, 201, 67, 243, 136, 238, 15, 221, - 78, 219, 96, 201, 233, 229, 236, 223, 163, 202, 187, 115, 207, 120, 58, - 115, 207, 120, 60, 115, 207, 120, 219, 224, 115, 207, 120, 183, 45, 201, - 230, 248, 8, 50, 201, 230, 248, 8, 105, 201, 230, 248, 7, 115, 201, 230, - 248, 7, 45, 198, 231, 248, 8, 50, 198, 231, 248, 8, 45, 251, 119, 248, 8, - 50, 251, 119, 248, 8, 215, 210, 248, 8, 219, 130, 215, 210, 248, 8, 219, - 130, 215, 209, 249, 107, 111, 4, 249, 106, 249, 107, 27, 192, 235, 249, - 107, 111, 4, 27, 192, 235, 249, 107, 28, 27, 192, 235, 249, 107, 111, 4, - 28, 27, 192, 235, 156, 243, 126, 77, 249, 107, 111, 4, 28, 243, 125, 193, - 18, 217, 71, 215, 186, 232, 81, 198, 85, 198, 30, 201, 92, 79, 219, 144, - 202, 188, 79, 223, 20, 215, 167, 230, 196, 233, 103, 230, 196, 233, 104, - 4, 202, 64, 233, 185, 233, 104, 4, 199, 126, 79, 222, 185, 202, 64, 233, - 104, 4, 211, 77, 215, 179, 202, 64, 233, 104, 4, 211, 77, 215, 180, 23, - 202, 64, 233, 185, 202, 64, 233, 104, 4, 211, 77, 215, 180, 23, 242, 87, - 200, 143, 202, 64, 233, 104, 4, 211, 77, 215, 180, 23, 198, 171, 233, - 185, 202, 64, 233, 104, 4, 230, 66, 202, 64, 233, 104, 4, 228, 186, 193, - 57, 233, 103, 202, 64, 233, 104, 4, 202, 64, 233, 185, 233, 104, 205, - 109, 237, 114, 232, 161, 207, 61, 233, 103, 202, 64, 233, 104, 4, 229, - 222, 233, 185, 202, 64, 233, 104, 4, 200, 194, 202, 63, 233, 103, 214, - 82, 233, 103, 233, 206, 233, 103, 196, 111, 233, 103, 233, 104, 4, 242, - 87, 200, 143, 210, 26, 233, 103, 239, 51, 233, 103, 239, 52, 233, 103, - 221, 121, 233, 103, 233, 104, 198, 214, 42, 221, 122, 221, 121, 233, 104, - 4, 202, 64, 233, 185, 221, 121, 233, 104, 4, 242, 219, 233, 185, 233, - 104, 4, 201, 12, 198, 61, 233, 104, 4, 201, 12, 198, 62, 23, 193, 57, - 233, 193, 233, 104, 4, 201, 12, 198, 62, 23, 198, 171, 233, 185, 236, - 228, 233, 103, 193, 16, 233, 103, 251, 111, 233, 103, 209, 6, 233, 103, - 238, 199, 233, 103, 209, 253, 233, 103, 233, 104, 4, 219, 7, 79, 197, - 217, 236, 228, 247, 218, 207, 61, 233, 103, 232, 92, 233, 104, 4, 211, - 77, 215, 179, 251, 109, 233, 103, 233, 57, 233, 103, 193, 119, 233, 103, - 202, 91, 233, 103, 198, 130, 233, 103, 230, 197, 233, 103, 218, 245, 238, - 199, 233, 103, 233, 104, 4, 211, 77, 215, 179, 228, 130, 233, 103, 233, - 104, 4, 211, 77, 215, 180, 23, 242, 87, 200, 143, 233, 104, 205, 78, 223, - 163, 233, 58, 250, 190, 233, 103, 232, 183, 233, 103, 202, 92, 233, 103, - 236, 195, 233, 103, 233, 104, 193, 51, 215, 179, 233, 104, 4, 216, 216, - 217, 35, 230, 196, 247, 79, 233, 104, 4, 202, 64, 233, 185, 247, 79, 233, - 104, 4, 199, 126, 79, 222, 185, 202, 64, 247, 79, 233, 104, 4, 211, 77, - 215, 179, 202, 64, 247, 79, 233, 104, 4, 229, 222, 233, 185, 247, 79, - 233, 104, 4, 193, 1, 202, 65, 221, 121, 247, 79, 233, 104, 4, 242, 219, - 233, 185, 209, 6, 247, 79, 233, 103, 238, 199, 247, 79, 233, 103, 193, - 119, 247, 79, 233, 103, 202, 84, 232, 92, 233, 103, 202, 84, 202, 64, - 233, 103, 196, 72, 233, 103, 233, 104, 4, 206, 138, 233, 185, 233, 104, - 4, 213, 44, 230, 244, 231, 132, 233, 104, 4, 211, 126, 231, 132, 209, - 251, 248, 68, 237, 129, 205, 49, 215, 225, 229, 226, 215, 225, 201, 236, - 215, 225, 230, 20, 209, 251, 207, 145, 91, 230, 53, 209, 251, 207, 145, - 248, 80, 230, 29, 223, 163, 247, 28, 209, 251, 232, 91, 209, 251, 4, 209, - 6, 233, 103, 209, 251, 4, 232, 172, 230, 28, 186, 193, 105, 209, 58, 219, - 233, 202, 2, 193, 105, 209, 58, 219, 233, 186, 234, 204, 209, 58, 219, - 233, 202, 2, 234, 204, 209, 58, 219, 233, 153, 186, 193, 105, 209, 58, - 219, 233, 153, 202, 2, 193, 105, 209, 58, 219, 233, 153, 186, 234, 204, - 209, 58, 219, 233, 153, 202, 2, 234, 204, 209, 58, 219, 233, 186, 193, - 105, 209, 58, 195, 48, 219, 233, 202, 2, 193, 105, 209, 58, 195, 48, 219, - 233, 186, 234, 204, 209, 58, 195, 48, 219, 233, 202, 2, 234, 204, 209, - 58, 195, 48, 219, 233, 88, 186, 193, 105, 209, 58, 195, 48, 219, 233, 88, - 202, 2, 193, 105, 209, 58, 195, 48, 219, 233, 88, 186, 234, 204, 209, 58, - 195, 48, 219, 233, 88, 202, 2, 234, 204, 209, 58, 195, 48, 219, 233, 186, - 193, 105, 209, 58, 248, 4, 202, 2, 193, 105, 209, 58, 248, 4, 186, 234, - 204, 209, 58, 248, 4, 202, 2, 234, 204, 209, 58, 248, 4, 88, 186, 193, - 105, 209, 58, 248, 4, 88, 202, 2, 193, 105, 209, 58, 248, 4, 88, 186, - 234, 204, 209, 58, 248, 4, 88, 202, 2, 234, 204, 209, 58, 248, 4, 229, 4, - 208, 6, 51, 211, 42, 229, 4, 208, 6, 51, 211, 43, 223, 163, 62, 201, 190, - 202, 25, 208, 6, 51, 211, 42, 202, 25, 208, 6, 51, 211, 43, 223, 163, 62, - 201, 190, 118, 206, 146, 196, 66, 206, 146, 96, 206, 146, 235, 119, 206, - 146, 27, 34, 234, 0, 211, 42, 88, 27, 34, 234, 0, 211, 42, 34, 211, 77, - 234, 0, 211, 42, 88, 34, 211, 77, 234, 0, 211, 42, 88, 251, 138, 211, 42, - 200, 146, 251, 138, 211, 42, 49, 88, 55, 153, 242, 75, 207, 252, 87, 211, - 42, 49, 88, 55, 242, 75, 207, 252, 87, 211, 42, 49, 88, 130, 55, 242, 75, - 207, 252, 87, 211, 42, 88, 223, 103, 211, 42, 49, 223, 103, 211, 42, 88, - 49, 223, 103, 211, 42, 195, 83, 88, 202, 23, 195, 83, 88, 207, 19, 202, - 23, 243, 124, 248, 107, 207, 19, 243, 124, 248, 107, 206, 146, 229, 205, - 201, 85, 219, 32, 207, 152, 247, 102, 229, 131, 198, 16, 229, 131, 198, - 17, 4, 247, 249, 213, 13, 198, 16, 216, 158, 156, 207, 153, 201, 93, 198, - 14, 198, 15, 247, 102, 247, 223, 211, 101, 247, 223, 197, 212, 247, 224, - 201, 63, 216, 42, 251, 142, 232, 244, 234, 87, 209, 50, 247, 102, 211, - 101, 209, 50, 247, 102, 199, 155, 211, 101, 199, 155, 250, 150, 211, 101, - 250, 150, 207, 94, 195, 145, 237, 110, 197, 203, 250, 225, 218, 254, 198, - 23, 215, 218, 215, 185, 207, 151, 200, 164, 207, 151, 215, 185, 247, 154, - 252, 11, 198, 13, 203, 65, 206, 112, 201, 228, 228, 241, 198, 20, 219, - 132, 81, 198, 20, 219, 132, 239, 37, 56, 209, 50, 247, 86, 207, 12, 219, - 132, 197, 238, 232, 218, 211, 105, 209, 19, 236, 144, 213, 44, 234, 73, - 56, 202, 62, 113, 213, 44, 202, 62, 113, 208, 132, 219, 84, 223, 163, - 223, 50, 209, 108, 113, 236, 175, 213, 12, 219, 84, 113, 209, 13, 193, - 144, 113, 213, 28, 193, 144, 113, 248, 184, 213, 44, 248, 183, 248, 182, - 215, 185, 248, 182, 210, 51, 213, 44, 210, 50, 243, 85, 238, 209, 216, - 182, 113, 193, 32, 113, 207, 28, 249, 149, 113, 198, 86, 193, 144, 242, - 216, 203, 20, 249, 61, 249, 59, 210, 91, 239, 21, 238, 156, 249, 126, - 242, 246, 45, 218, 215, 197, 242, 4, 206, 113, 239, 0, 208, 196, 56, 47, - 223, 137, 202, 3, 248, 59, 113, 231, 27, 113, 238, 248, 23, 220, 25, 202, - 92, 252, 57, 203, 43, 249, 125, 248, 234, 248, 235, 249, 2, 209, 108, 79, - 193, 15, 211, 159, 56, 203, 43, 197, 213, 201, 8, 210, 201, 229, 127, - 199, 98, 228, 129, 234, 130, 193, 54, 209, 96, 202, 87, 193, 93, 206, - 189, 247, 233, 230, 62, 23, 193, 9, 203, 78, 211, 132, 235, 94, 215, 189, - 207, 152, 198, 25, 215, 192, 248, 106, 196, 76, 216, 54, 251, 223, 196, - 76, 251, 223, 196, 76, 2, 251, 223, 2, 251, 223, 213, 17, 251, 223, 251, - 224, 237, 93, 251, 224, 250, 238, 205, 118, 211, 101, 232, 244, 234, 87, - 237, 22, 219, 32, 210, 95, 203, 65, 205, 83, 215, 192, 205, 83, 247, 113, - 202, 94, 232, 178, 205, 113, 202, 111, 250, 152, 206, 243, 209, 178, 197, - 203, 206, 139, 202, 112, 160, 16, 40, 208, 2, 160, 16, 40, 251, 225, 160, - 16, 40, 232, 243, 160, 16, 40, 234, 207, 160, 16, 40, 193, 143, 160, 16, - 40, 251, 35, 160, 16, 40, 251, 36, 207, 81, 160, 16, 40, 251, 36, 207, - 80, 160, 16, 40, 251, 36, 195, 31, 160, 16, 40, 251, 36, 195, 30, 160, - 16, 40, 195, 45, 160, 16, 40, 195, 44, 160, 16, 40, 195, 43, 160, 16, 40, - 200, 205, 160, 16, 40, 209, 203, 200, 205, 160, 16, 40, 62, 200, 205, - 160, 16, 40, 216, 181, 200, 236, 160, 16, 40, 216, 181, 200, 235, 160, - 16, 40, 216, 181, 200, 234, 160, 16, 40, 243, 13, 160, 16, 40, 205, 158, - 160, 16, 40, 213, 161, 160, 16, 40, 195, 28, 160, 16, 40, 195, 27, 160, - 16, 40, 206, 148, 205, 158, 160, 16, 40, 206, 148, 205, 157, 160, 16, 40, - 230, 250, 160, 16, 40, 202, 184, 160, 16, 40, 223, 74, 211, 49, 160, 16, - 40, 223, 74, 211, 48, 160, 16, 40, 238, 222, 79, 223, 73, 160, 16, 40, - 207, 77, 79, 223, 73, 160, 16, 40, 239, 12, 211, 49, 160, 16, 40, 223, - 72, 211, 49, 160, 16, 40, 200, 237, 79, 239, 11, 160, 16, 40, 238, 222, - 79, 239, 11, 160, 16, 40, 238, 222, 79, 239, 10, 160, 16, 40, 239, 12, - 251, 79, 160, 16, 40, 205, 159, 79, 239, 12, 251, 79, 160, 16, 40, 200, - 237, 79, 205, 159, 79, 239, 11, 160, 16, 40, 195, 139, 160, 16, 40, 198, - 143, 211, 49, 160, 16, 40, 219, 237, 211, 49, 160, 16, 40, 251, 78, 211, - 49, 160, 16, 40, 200, 237, 79, 251, 77, 160, 16, 40, 205, 159, 79, 251, - 77, 160, 16, 40, 200, 237, 79, 205, 159, 79, 251, 77, 160, 16, 40, 195, - 46, 79, 251, 77, 160, 16, 40, 207, 77, 79, 251, 77, 160, 16, 40, 207, 77, - 79, 251, 76, 160, 16, 40, 207, 76, 160, 16, 40, 207, 75, 160, 16, 40, - 207, 74, 160, 16, 40, 207, 73, 160, 16, 40, 251, 177, 160, 16, 40, 251, - 176, 160, 16, 40, 217, 61, 160, 16, 40, 205, 168, 160, 16, 40, 250, 230, - 160, 16, 40, 207, 105, 160, 16, 40, 207, 104, 160, 16, 40, 250, 154, 160, - 16, 40, 248, 150, 211, 49, 160, 16, 40, 199, 177, 160, 16, 40, 199, 176, - 160, 16, 40, 208, 8, 219, 121, 160, 16, 40, 248, 87, 160, 16, 40, 248, - 86, 160, 16, 40, 248, 85, 160, 16, 40, 251, 151, 160, 16, 40, 211, 131, - 160, 16, 40, 201, 214, 160, 16, 40, 198, 141, 160, 16, 40, 230, 158, 160, - 16, 40, 193, 131, 160, 16, 40, 209, 1, 160, 16, 40, 247, 137, 160, 16, - 40, 197, 50, 160, 16, 40, 247, 104, 215, 198, 160, 16, 40, 205, 93, 79, - 222, 187, 160, 16, 40, 247, 151, 160, 16, 40, 197, 235, 160, 16, 40, 201, - 100, 197, 235, 160, 16, 40, 219, 31, 160, 16, 40, 202, 37, 160, 16, 40, - 196, 54, 160, 16, 40, 228, 184, 235, 71, 160, 16, 40, 250, 204, 160, 16, - 40, 209, 15, 250, 204, 160, 16, 40, 248, 31, 160, 16, 40, 209, 0, 248, - 31, 160, 16, 40, 251, 148, 160, 16, 40, 201, 46, 200, 186, 201, 45, 160, - 16, 40, 201, 46, 200, 186, 201, 44, 160, 16, 40, 200, 233, 160, 16, 40, - 208, 229, 160, 16, 40, 236, 215, 160, 16, 40, 236, 217, 160, 16, 40, 236, - 216, 160, 16, 40, 208, 141, 160, 16, 40, 208, 129, 160, 16, 40, 238, 207, - 160, 16, 40, 238, 206, 160, 16, 40, 238, 205, 160, 16, 40, 238, 204, 160, - 16, 40, 238, 203, 160, 16, 40, 251, 191, 160, 16, 40, 249, 62, 79, 217, - 42, 160, 16, 40, 249, 62, 79, 195, 174, 160, 16, 40, 207, 26, 160, 16, - 40, 228, 176, 160, 16, 40, 213, 190, 160, 16, 40, 237, 203, 160, 16, 40, - 215, 213, 160, 16, 40, 132, 235, 109, 160, 16, 40, 132, 211, 17, 218, - 250, 79, 232, 137, 211, 164, 218, 207, 234, 194, 230, 1, 217, 101, 230, - 246, 208, 24, 211, 52, 62, 219, 219, 223, 56, 50, 197, 241, 62, 196, 76, - 223, 56, 50, 197, 241, 62, 206, 203, 223, 56, 50, 197, 241, 62, 235, 122, - 223, 56, 50, 197, 241, 62, 202, 84, 2, 243, 10, 216, 213, 28, 63, 243, - 10, 28, 63, 243, 10, 88, 63, 243, 10, 195, 83, 88, 63, 243, 10, 233, 197, - 88, 63, 243, 10, 63, 243, 11, 239, 33, 62, 2, 243, 10, 206, 115, 199, - 178, 62, 198, 138, 201, 190, 62, 202, 84, 2, 201, 190, 156, 63, 201, 190, - 216, 213, 63, 201, 190, 28, 63, 201, 190, 88, 63, 201, 190, 195, 83, 88, - 63, 201, 190, 233, 197, 88, 63, 201, 190, 63, 51, 239, 33, 62, 195, 83, - 2, 201, 190, 63, 51, 239, 33, 62, 216, 213, 201, 190, 51, 199, 178, 62, - 198, 138, 237, 32, 62, 195, 83, 2, 237, 32, 62, 216, 213, 2, 237, 32, 63, - 237, 33, 239, 33, 62, 195, 83, 2, 237, 32, 63, 237, 33, 239, 33, 62, 216, - 213, 237, 32, 237, 33, 199, 178, 62, 198, 138, 218, 232, 62, 195, 83, 2, - 218, 232, 62, 216, 213, 2, 218, 232, 63, 218, 233, 239, 33, 62, 2, 218, - 232, 199, 4, 35, 238, 217, 156, 35, 238, 217, 216, 213, 35, 238, 217, 28, - 35, 238, 217, 195, 83, 28, 35, 238, 217, 195, 83, 88, 35, 238, 217, 233, - 197, 88, 35, 238, 217, 199, 4, 205, 154, 156, 205, 154, 216, 213, 205, - 154, 28, 205, 154, 88, 205, 154, 195, 83, 88, 205, 154, 233, 197, 88, - 205, 154, 156, 232, 226, 201, 206, 250, 193, 216, 213, 232, 226, 201, - 206, 250, 193, 28, 232, 226, 201, 206, 250, 193, 88, 232, 226, 201, 206, - 250, 193, 195, 83, 88, 232, 226, 201, 206, 250, 193, 233, 197, 88, 232, - 226, 201, 206, 250, 193, 156, 202, 136, 201, 206, 250, 193, 216, 213, - 202, 136, 201, 206, 250, 193, 28, 202, 136, 201, 206, 250, 193, 88, 202, - 136, 201, 206, 250, 193, 195, 83, 88, 202, 136, 201, 206, 250, 193, 233, - 197, 88, 202, 136, 201, 206, 250, 193, 156, 234, 164, 201, 206, 250, 193, - 216, 213, 234, 164, 201, 206, 250, 193, 28, 234, 164, 201, 206, 250, 193, - 88, 234, 164, 201, 206, 250, 193, 195, 83, 88, 234, 164, 201, 206, 250, - 193, 156, 115, 209, 60, 62, 201, 102, 216, 213, 115, 209, 60, 62, 201, - 102, 115, 209, 60, 62, 201, 102, 216, 213, 115, 209, 60, 209, 130, 201, - 102, 156, 232, 128, 209, 60, 62, 201, 102, 216, 213, 232, 128, 209, 60, - 62, 201, 102, 232, 128, 209, 60, 62, 201, 102, 216, 213, 232, 128, 209, - 60, 209, 130, 201, 102, 207, 19, 156, 232, 128, 209, 60, 209, 130, 201, - 102, 156, 232, 226, 209, 60, 62, 201, 102, 88, 232, 226, 209, 60, 62, - 201, 102, 216, 213, 202, 136, 209, 60, 62, 201, 102, 88, 202, 136, 209, - 60, 62, 201, 102, 202, 136, 209, 60, 209, 130, 201, 102, 216, 213, 234, - 164, 209, 60, 62, 201, 102, 88, 234, 164, 209, 60, 62, 201, 102, 195, 83, - 88, 234, 164, 209, 60, 62, 201, 102, 88, 234, 164, 209, 60, 209, 130, - 201, 102, 156, 197, 38, 209, 60, 62, 201, 102, 88, 197, 38, 209, 60, 62, - 201, 102, 88, 197, 38, 209, 60, 209, 130, 201, 102, 47, 197, 241, 214, - 106, 47, 197, 241, 47, 201, 190, 214, 106, 47, 201, 190, 213, 175, 209, - 60, 63, 201, 102, 220, 13, 211, 55, 243, 10, 220, 13, 192, 73, 243, 10, - 220, 13, 230, 201, 243, 10, 220, 13, 208, 138, 243, 10, 220, 13, 248, 19, - 243, 10, 220, 13, 207, 87, 201, 190, 220, 13, 248, 115, 201, 190, 220, - 13, 211, 55, 201, 190, 220, 13, 192, 73, 201, 190, 220, 13, 230, 201, - 201, 190, 220, 13, 208, 138, 201, 190, 220, 13, 248, 19, 201, 190, 88, - 234, 43, 56, 118, 64, 4, 2, 197, 242, 250, 235, 196, 66, 64, 4, 2, 197, - 242, 250, 235, 96, 64, 4, 2, 197, 242, 250, 235, 235, 119, 64, 4, 2, 197, - 242, 250, 235, 118, 64, 4, 216, 213, 197, 242, 250, 235, 196, 66, 64, 4, - 216, 213, 197, 242, 250, 235, 96, 64, 4, 216, 213, 197, 242, 250, 235, - 235, 119, 64, 4, 216, 213, 197, 242, 250, 235, 118, 64, 4, 220, 13, 197, - 242, 250, 235, 196, 66, 64, 4, 220, 13, 197, 242, 250, 235, 96, 64, 4, - 220, 13, 197, 242, 250, 235, 235, 119, 64, 4, 220, 13, 197, 242, 250, - 235, 118, 64, 4, 2, 234, 37, 250, 235, 196, 66, 64, 4, 2, 234, 37, 250, - 235, 96, 64, 4, 2, 234, 37, 250, 235, 235, 119, 64, 4, 2, 234, 37, 250, - 235, 118, 64, 4, 234, 37, 250, 235, 196, 66, 64, 4, 234, 37, 250, 235, - 96, 64, 4, 234, 37, 250, 235, 235, 119, 64, 4, 234, 37, 250, 235, 88, - 118, 64, 4, 234, 37, 250, 235, 88, 196, 66, 64, 4, 234, 37, 250, 235, 88, - 96, 64, 4, 234, 37, 250, 235, 88, 235, 119, 64, 4, 234, 37, 250, 235, 88, - 118, 64, 4, 220, 13, 234, 37, 250, 235, 88, 196, 66, 64, 4, 220, 13, 234, - 37, 250, 235, 88, 96, 64, 4, 220, 13, 234, 37, 250, 235, 88, 235, 119, - 64, 4, 220, 13, 234, 37, 250, 235, 118, 197, 240, 64, 4, 214, 215, 203, - 149, 196, 66, 197, 240, 64, 4, 214, 215, 203, 149, 96, 197, 240, 64, 4, - 214, 215, 203, 149, 235, 119, 197, 240, 64, 4, 214, 215, 203, 149, 118, - 197, 240, 64, 4, 216, 213, 203, 149, 196, 66, 197, 240, 64, 4, 216, 213, - 203, 149, 96, 197, 240, 64, 4, 216, 213, 203, 149, 235, 119, 197, 240, - 64, 4, 216, 213, 203, 149, 118, 197, 240, 64, 4, 28, 203, 149, 196, 66, - 197, 240, 64, 4, 28, 203, 149, 96, 197, 240, 64, 4, 28, 203, 149, 235, - 119, 197, 240, 64, 4, 28, 203, 149, 118, 197, 240, 64, 4, 88, 203, 149, - 196, 66, 197, 240, 64, 4, 88, 203, 149, 96, 197, 240, 64, 4, 88, 203, - 149, 235, 119, 197, 240, 64, 4, 88, 203, 149, 118, 197, 240, 64, 4, 195, - 83, 88, 203, 149, 196, 66, 197, 240, 64, 4, 195, 83, 88, 203, 149, 96, - 197, 240, 64, 4, 195, 83, 88, 203, 149, 235, 119, 197, 240, 64, 4, 195, - 83, 88, 203, 149, 118, 232, 251, 57, 196, 66, 232, 251, 57, 96, 232, 251, - 57, 235, 119, 232, 251, 57, 118, 112, 57, 196, 66, 112, 57, 96, 112, 57, - 235, 119, 112, 57, 118, 239, 61, 57, 196, 66, 239, 61, 57, 96, 239, 61, - 57, 235, 119, 239, 61, 57, 118, 88, 239, 61, 57, 196, 66, 88, 239, 61, - 57, 96, 88, 239, 61, 57, 235, 119, 88, 239, 61, 57, 118, 88, 57, 196, 66, - 88, 57, 96, 88, 57, 235, 119, 88, 57, 118, 49, 57, 196, 66, 49, 57, 96, - 49, 57, 235, 119, 49, 57, 186, 193, 105, 49, 57, 186, 234, 204, 49, 57, - 202, 2, 234, 204, 49, 57, 202, 2, 193, 105, 49, 57, 45, 50, 49, 57, 133, - 144, 49, 57, 193, 77, 118, 156, 181, 57, 193, 77, 196, 66, 156, 181, 57, - 193, 77, 96, 156, 181, 57, 193, 77, 235, 119, 156, 181, 57, 193, 77, 186, - 193, 105, 156, 181, 57, 193, 77, 186, 234, 204, 156, 181, 57, 193, 77, - 202, 2, 234, 204, 156, 181, 57, 193, 77, 202, 2, 193, 105, 156, 181, 57, - 193, 77, 118, 181, 57, 193, 77, 196, 66, 181, 57, 193, 77, 96, 181, 57, - 193, 77, 235, 119, 181, 57, 193, 77, 186, 193, 105, 181, 57, 193, 77, - 186, 234, 204, 181, 57, 193, 77, 202, 2, 234, 204, 181, 57, 193, 77, 202, - 2, 193, 105, 181, 57, 193, 77, 118, 216, 213, 181, 57, 193, 77, 196, 66, - 216, 213, 181, 57, 193, 77, 96, 216, 213, 181, 57, 193, 77, 235, 119, - 216, 213, 181, 57, 193, 77, 186, 193, 105, 216, 213, 181, 57, 193, 77, - 186, 234, 204, 216, 213, 181, 57, 193, 77, 202, 2, 234, 204, 216, 213, - 181, 57, 193, 77, 202, 2, 193, 105, 216, 213, 181, 57, 193, 77, 118, 88, - 181, 57, 193, 77, 196, 66, 88, 181, 57, 193, 77, 96, 88, 181, 57, 193, - 77, 235, 119, 88, 181, 57, 193, 77, 186, 193, 105, 88, 181, 57, 193, 77, - 186, 234, 204, 88, 181, 57, 193, 77, 202, 2, 234, 204, 88, 181, 57, 193, - 77, 202, 2, 193, 105, 88, 181, 57, 193, 77, 118, 195, 83, 88, 181, 57, - 193, 77, 196, 66, 195, 83, 88, 181, 57, 193, 77, 96, 195, 83, 88, 181, - 57, 193, 77, 235, 119, 195, 83, 88, 181, 57, 193, 77, 186, 193, 105, 195, - 83, 88, 181, 57, 193, 77, 186, 234, 204, 195, 83, 88, 181, 57, 193, 77, - 202, 2, 234, 204, 195, 83, 88, 181, 57, 193, 77, 202, 2, 193, 105, 195, - 83, 88, 181, 57, 118, 197, 242, 250, 235, 196, 66, 197, 242, 250, 235, - 96, 197, 242, 250, 235, 235, 119, 197, 242, 250, 235, 118, 63, 64, 193, - 53, 197, 242, 250, 235, 196, 66, 63, 64, 193, 53, 197, 242, 250, 235, 96, - 63, 64, 193, 53, 197, 242, 250, 235, 235, 119, 63, 64, 193, 53, 197, 242, - 250, 235, 118, 64, 4, 213, 8, 199, 215, 196, 66, 64, 4, 213, 8, 199, 215, - 96, 64, 4, 213, 8, 199, 215, 235, 119, 64, 4, 213, 8, 199, 215, 88, 64, - 203, 150, 193, 75, 107, 88, 64, 203, 150, 193, 75, 105, 198, 253, 88, 64, - 203, 150, 193, 75, 91, 230, 70, 88, 64, 203, 150, 193, 75, 91, 199, 0, - 118, 248, 74, 63, 57, 96, 248, 77, 203, 152, 63, 57, 118, 198, 54, 203, - 152, 63, 57, 96, 198, 54, 203, 152, 63, 57, 118, 219, 218, 63, 57, 96, - 206, 202, 63, 57, 118, 206, 202, 63, 57, 96, 219, 218, 63, 57, 118, 249, - 145, 203, 151, 63, 57, 96, 249, 145, 203, 151, 63, 57, 118, 232, 95, 203, - 151, 63, 57, 96, 232, 95, 203, 151, 63, 57, 63, 64, 203, 150, 193, 75, - 107, 63, 64, 203, 150, 193, 75, 105, 198, 253, 64, 209, 58, 196, 66, 199, - 25, 186, 193, 104, 64, 209, 58, 96, 199, 25, 238, 161, 202, 2, 193, 104, - 47, 238, 218, 232, 143, 4, 232, 128, 236, 138, 47, 238, 218, 232, 143, 4, - 105, 236, 138, 47, 238, 218, 232, 142, 45, 132, 243, 11, 4, 232, 128, - 236, 138, 45, 132, 243, 11, 4, 115, 236, 138, 45, 132, 243, 11, 4, 105, - 236, 138, 45, 132, 243, 11, 4, 236, 140, 45, 132, 243, 10, 235, 120, 233, - 96, 102, 235, 120, 233, 96, 213, 8, 102, 235, 120, 233, 96, 228, 251, 4, - 236, 140, 235, 120, 233, 96, 213, 8, 228, 251, 4, 236, 140, 209, 136, - 232, 247, 63, 229, 223, 248, 19, 229, 223, 209, 135, 230, 53, 191, 17, - 233, 103, 215, 229, 233, 103, 233, 104, 4, 199, 21, 214, 92, 233, 103, - 199, 2, 233, 103, 233, 104, 4, 229, 234, 206, 150, 233, 103, 228, 150, - 233, 103, 3, 79, 199, 34, 228, 186, 247, 139, 216, 233, 230, 53, 207, - 147, 249, 147, 79, 230, 53, 219, 223, 232, 231, 206, 207, 232, 231, 230, - 27, 230, 54, 4, 141, 23, 82, 232, 248, 238, 213, 228, 74, 218, 242, 191, - 239, 230, 54, 56, 233, 104, 4, 238, 238, 230, 9, 242, 208, 233, 103, 214, - 202, 233, 103, 206, 138, 211, 105, 199, 34, 232, 194, 219, 255, 235, 100, - 233, 103, 218, 178, 233, 103, 233, 104, 210, 182, 202, 56, 233, 103, 233, - 104, 4, 91, 233, 192, 207, 146, 230, 196, 233, 104, 4, 201, 103, 233, - 185, 230, 196, 233, 104, 4, 91, 220, 13, 23, 91, 2, 233, 193, 233, 104, - 4, 232, 253, 238, 241, 242, 219, 219, 96, 204, 2, 233, 104, 4, 200, 77, - 238, 241, 215, 179, 202, 64, 233, 104, 4, 202, 64, 233, 186, 23, 230, 54, - 238, 241, 215, 179, 233, 104, 4, 211, 77, 215, 180, 195, 9, 203, 54, 233, - 104, 4, 233, 208, 229, 235, 208, 226, 193, 35, 248, 40, 210, 181, 133, - 198, 87, 204, 31, 208, 214, 217, 91, 223, 163, 197, 46, 215, 194, 243, - 55, 203, 9, 209, 251, 236, 159, 247, 83, 222, 177, 233, 38, 215, 255, - 210, 21, 193, 8, 193, 144, 209, 44, 230, 32, 236, 201, 217, 35, 193, 69, - 232, 186, 235, 95, 4, 235, 93, 242, 226, 231, 15, 197, 74, 231, 16, 201, - 203, 231, 1, 214, 85, 206, 208, 232, 238, 209, 108, 216, 219, 205, 57, - 209, 108, 216, 219, 199, 1, 209, 108, 216, 219, 248, 61, 231, 10, 217, - 46, 250, 223, 196, 94, 238, 172, 201, 65, 220, 110, 201, 75, 23, 249, - 111, 202, 31, 232, 178, 236, 226, 238, 221, 250, 141, 238, 188, 249, 138, - 209, 12, 247, 87, 249, 124, 248, 43, 230, 201, 205, 165, 203, 142, 210, - 167, 79, 232, 161, 201, 9, 232, 205, 234, 179, 231, 17, 79, 216, 53, 210, - 56, 221, 116, 210, 163, 235, 76, 232, 138, 239, 16, 199, 207, 248, 62, - 243, 62, 248, 67, 4, 201, 203, 238, 182, 4, 201, 43, 242, 93, 248, 23, - 209, 176, 208, 218, 238, 155, 79, 216, 224, 205, 137, 247, 115, 232, 161, - 219, 232, 230, 200, 217, 82, 215, 206, 247, 146, 249, 127, 202, 64, 233, - 104, 4, 202, 64, 233, 186, 23, 115, 229, 221, 192, 87, 233, 103, 202, 64, - 233, 104, 4, 199, 131, 233, 104, 4, 210, 102, 228, 188, 23, 210, 102, - 230, 9, 233, 104, 4, 196, 98, 233, 186, 23, 193, 135, 215, 179, 211, 5, - 233, 103, 232, 107, 233, 103, 213, 168, 236, 224, 233, 103, 233, 104, - 229, 6, 249, 147, 199, 125, 233, 104, 4, 209, 93, 233, 185, 205, 125, - 220, 119, 242, 96, 230, 253, 229, 129, 248, 91, 232, 207, 203, 52, 238, - 235, 219, 100, 233, 103, 205, 81, 197, 62, 196, 96, 233, 103, 234, 214, - 235, 85, 249, 64, 203, 128, 210, 249, 232, 120, 233, 103, 247, 215, 237, - 128, 230, 235, 219, 78, 207, 5, 203, 13, 201, 184, 231, 29, 233, 103, - 191, 85, 233, 103, 229, 216, 205, 110, 200, 42, 238, 224, 222, 82, 219, - 70, 210, 58, 229, 121, 210, 108, 207, 173, 219, 41, 215, 196, 216, 90, - 249, 133, 200, 148, 217, 92, 236, 165, 202, 78, 211, 22, 211, 54, 202, - 102, 232, 209, 210, 239, 249, 4, 248, 149, 205, 61, 230, 163, 236, 162, - 208, 202, 247, 117, 234, 109, 242, 64, 207, 87, 230, 78, 234, 109, 242, - 64, 238, 171, 230, 78, 234, 109, 242, 64, 249, 113, 234, 109, 242, 64, - 63, 230, 78, 248, 98, 219, 212, 232, 159, 198, 56, 200, 184, 200, 179, - 205, 188, 195, 81, 234, 212, 4, 229, 225, 251, 235, 215, 190, 193, 91, - 217, 74, 193, 91, 216, 223, 250, 250, 216, 223, 219, 212, 243, 118, 193, - 116, 238, 180, 205, 159, 203, 146, 248, 208, 248, 62, 231, 197, 211, 93, - 233, 85, 193, 174, 247, 216, 217, 29, 235, 104, 228, 27, 238, 190, 248, - 9, 199, 134, 197, 214, 201, 105, 209, 250, 221, 80, 209, 250, 237, 144, - 209, 250, 233, 104, 4, 215, 224, 252, 29, 243, 86, 211, 118, 252, 29, - 249, 8, 209, 250, 209, 251, 4, 229, 230, 209, 251, 223, 163, 201, 82, - 206, 130, 209, 251, 242, 228, 209, 251, 223, 163, 218, 247, 209, 24, 217, - 124, 233, 87, 195, 177, 216, 174, 234, 125, 231, 148, 191, 5, 248, 50, - 211, 55, 229, 223, 248, 171, 247, 111, 205, 94, 231, 9, 242, 96, 202, 34, - 207, 87, 231, 43, 234, 67, 232, 242, 222, 238, 208, 125, 209, 175, 199, - 75, 197, 84, 209, 235, 236, 222, 236, 176, 55, 229, 204, 242, 69, 252, - 71, 232, 244, 233, 202, 198, 58, 248, 31, 217, 122, 218, 215, 218, 248, - 248, 78, 201, 204, 79, 198, 227, 249, 112, 79, 192, 100, 205, 188, 209, - 139, 199, 124, 249, 9, 248, 20, 249, 69, 206, 141, 79, 210, 135, 249, 88, - 79, 202, 37, 201, 205, 207, 103, 214, 196, 251, 134, 214, 82, 243, 105, - 221, 138, 214, 82, 243, 105, 208, 14, 214, 82, 243, 105, 206, 131, 214, - 82, 243, 105, 248, 152, 214, 82, 243, 105, 221, 76, 214, 82, 243, 105, - 210, 74, 63, 243, 105, 221, 77, 206, 122, 232, 134, 237, 124, 62, 243, - 105, 221, 77, 206, 122, 232, 134, 237, 124, 214, 82, 243, 105, 221, 77, - 206, 122, 232, 134, 237, 124, 63, 243, 105, 221, 139, 206, 122, 213, 170, - 237, 124, 63, 243, 105, 208, 15, 206, 122, 213, 170, 237, 124, 63, 243, - 105, 206, 132, 206, 122, 213, 170, 237, 124, 63, 243, 105, 248, 153, 206, - 122, 213, 170, 237, 124, 63, 243, 105, 221, 77, 206, 122, 213, 170, 237, - 124, 63, 243, 105, 210, 75, 206, 122, 213, 170, 237, 124, 62, 243, 105, - 221, 139, 206, 122, 213, 170, 237, 124, 62, 243, 105, 208, 15, 206, 122, - 213, 170, 237, 124, 62, 243, 105, 206, 132, 206, 122, 213, 170, 237, 124, - 62, 243, 105, 248, 153, 206, 122, 213, 170, 237, 124, 62, 243, 105, 221, - 77, 206, 122, 213, 170, 237, 124, 62, 243, 105, 210, 75, 206, 122, 213, - 170, 237, 124, 214, 82, 243, 105, 221, 139, 206, 122, 213, 170, 237, 124, - 214, 82, 243, 105, 208, 15, 206, 122, 213, 170, 237, 124, 214, 82, 243, - 105, 206, 132, 206, 122, 213, 170, 237, 124, 214, 82, 243, 105, 248, 153, - 206, 122, 213, 170, 237, 124, 214, 82, 243, 105, 221, 77, 206, 122, 213, - 170, 237, 124, 214, 82, 243, 105, 210, 75, 206, 122, 213, 170, 237, 124, - 63, 243, 105, 221, 77, 206, 122, 91, 228, 141, 198, 248, 237, 124, 62, - 243, 105, 221, 77, 206, 122, 91, 228, 141, 198, 248, 237, 124, 214, 82, - 243, 105, 221, 77, 206, 122, 91, 228, 141, 198, 248, 237, 124, 63, 243, - 105, 153, 221, 138, 63, 243, 105, 153, 208, 14, 63, 243, 105, 153, 206, - 131, 63, 243, 105, 153, 248, 152, 63, 243, 105, 153, 221, 76, 63, 243, - 105, 153, 210, 74, 62, 243, 105, 153, 221, 138, 62, 243, 105, 153, 208, - 14, 62, 243, 105, 153, 206, 131, 62, 243, 105, 153, 248, 152, 62, 243, - 105, 153, 221, 76, 62, 243, 105, 153, 210, 74, 214, 82, 243, 105, 153, - 221, 138, 214, 82, 243, 105, 153, 208, 14, 214, 82, 243, 105, 153, 206, - 131, 214, 82, 243, 105, 153, 248, 152, 214, 82, 243, 105, 153, 221, 76, - 214, 82, 243, 105, 153, 210, 74, 63, 243, 105, 221, 77, 206, 122, 105, - 228, 141, 197, 29, 237, 124, 62, 243, 105, 221, 77, 206, 122, 105, 228, - 141, 197, 29, 237, 124, 214, 82, 243, 105, 221, 77, 206, 122, 105, 228, - 141, 197, 29, 237, 124, 63, 243, 105, 221, 139, 206, 122, 105, 228, 141, - 203, 242, 237, 124, 63, 243, 105, 208, 15, 206, 122, 105, 228, 141, 203, - 242, 237, 124, 63, 243, 105, 206, 132, 206, 122, 105, 228, 141, 203, 242, - 237, 124, 63, 243, 105, 248, 153, 206, 122, 105, 228, 141, 203, 242, 237, - 124, 63, 243, 105, 221, 77, 206, 122, 105, 228, 141, 203, 242, 237, 124, - 63, 243, 105, 210, 75, 206, 122, 105, 228, 141, 203, 242, 237, 124, 62, - 243, 105, 221, 139, 206, 122, 105, 228, 141, 203, 242, 237, 124, 62, 243, - 105, 208, 15, 206, 122, 105, 228, 141, 203, 242, 237, 124, 62, 243, 105, - 206, 132, 206, 122, 105, 228, 141, 203, 242, 237, 124, 62, 243, 105, 248, - 153, 206, 122, 105, 228, 141, 203, 242, 237, 124, 62, 243, 105, 221, 77, - 206, 122, 105, 228, 141, 203, 242, 237, 124, 62, 243, 105, 210, 75, 206, - 122, 105, 228, 141, 203, 242, 237, 124, 214, 82, 243, 105, 221, 139, 206, - 122, 105, 228, 141, 203, 242, 237, 124, 214, 82, 243, 105, 208, 15, 206, - 122, 105, 228, 141, 203, 242, 237, 124, 214, 82, 243, 105, 206, 132, 206, - 122, 105, 228, 141, 203, 242, 237, 124, 214, 82, 243, 105, 248, 153, 206, - 122, 105, 228, 141, 203, 242, 237, 124, 214, 82, 243, 105, 221, 77, 206, - 122, 105, 228, 141, 203, 242, 237, 124, 214, 82, 243, 105, 210, 75, 206, - 122, 105, 228, 141, 203, 242, 237, 124, 63, 243, 105, 221, 77, 206, 122, - 115, 228, 141, 233, 20, 237, 124, 62, 243, 105, 221, 77, 206, 122, 115, - 228, 141, 233, 20, 237, 124, 214, 82, 243, 105, 221, 77, 206, 122, 115, - 228, 141, 233, 20, 237, 124, 63, 243, 105, 234, 38, 62, 243, 105, 234, - 38, 214, 82, 243, 105, 234, 38, 63, 243, 105, 234, 39, 206, 122, 213, - 170, 237, 124, 62, 243, 105, 234, 39, 206, 122, 213, 170, 237, 124, 214, - 82, 243, 105, 234, 39, 206, 122, 213, 170, 237, 124, 63, 243, 105, 221, - 74, 63, 243, 105, 221, 73, 63, 243, 105, 221, 75, 62, 243, 105, 221, 74, - 62, 243, 105, 221, 73, 62, 243, 105, 221, 75, 192, 205, 207, 87, 231, - 150, 192, 205, 207, 87, 217, 84, 192, 205, 207, 87, 234, 131, 192, 205, - 207, 87, 228, 183, 192, 205, 207, 87, 243, 138, 192, 205, 207, 87, 247, - 114, 192, 205, 207, 87, 202, 26, 192, 205, 62, 231, 150, 192, 205, 62, - 217, 84, 192, 205, 62, 234, 131, 192, 205, 62, 228, 183, 192, 205, 62, - 243, 138, 192, 205, 62, 247, 114, 192, 205, 62, 202, 26, 249, 110, 203, - 51, 211, 98, 200, 135, 248, 27, 203, 25, 198, 237, 205, 139, 156, 248, - 115, 229, 223, 230, 198, 229, 223, 209, 131, 229, 223, 235, 99, 79, 248, - 120, 252, 35, 249, 96, 201, 76, 192, 234, 238, 201, 191, 253, 221, 119, - 210, 129, 248, 92, 217, 123, 193, 162, 209, 137, 214, 87, 236, 154, 217, - 64, 232, 182, 206, 187, 209, 100, 246, 252, 207, 118, 250, 132, 236, 196, - 220, 25, 249, 94, 216, 54, 229, 200, 252, 56, 179, 235, 94, 242, 88, 247, - 89, 205, 108, 205, 75, 220, 109, 102, 216, 26, 193, 65, 209, 83, 203, - 239, 214, 109, 221, 71, 248, 6, 215, 182, 198, 6, 198, 55, 229, 228, 209, - 109, 206, 147, 216, 27, 249, 111, 228, 16, 247, 100, 130, 249, 58, 230, - 60, 232, 170, 230, 54, 233, 80, 230, 79, 209, 180, 221, 203, 232, 179, - 193, 17, 248, 251, 242, 95, 209, 11, 209, 99, 193, 28, 233, 54, 218, 246, - 239, 4, 234, 105, 214, 89, 214, 90, 4, 234, 178, 228, 92, 223, 2, 193, - 61, 230, 243, 251, 129, 229, 223, 218, 205, 210, 20, 228, 149, 208, 226, - 217, 90, 208, 226, 209, 250, 209, 251, 4, 238, 208, 215, 204, 236, 147, - 248, 113, 248, 236, 210, 15, 211, 115, 232, 205, 199, 196, 232, 165, 199, - 132, 209, 7, 219, 92, 249, 11, 223, 18, 231, 36, 206, 128, 210, 62, 209, - 70, 216, 195, 233, 103, 205, 153, 233, 103, 233, 104, 4, 211, 77, 233, - 186, 23, 230, 54, 139, 215, 179, 233, 104, 4, 210, 47, 233, 193, 233, - 104, 4, 237, 39, 215, 179, 235, 138, 219, 113, 233, 103, 248, 145, 219, - 98, 248, 7, 203, 145, 233, 103, 230, 54, 4, 141, 232, 253, 23, 176, 238, - 213, 96, 230, 53, 118, 230, 53, 210, 183, 144, 230, 53, 210, 183, 133, - 230, 53, 141, 209, 58, 250, 183, 199, 34, 195, 55, 229, 224, 230, 28, - 118, 208, 135, 230, 53, 96, 208, 135, 230, 53, 184, 203, 236, 184, 203, - 206, 184, 203, 235, 184, 203, 191, 184, 203, 220, 184, 203, 205, 184, - 203, 234, 184, 203, 183, 184, 203, 213, 184, 203, 197, 184, 203, 227, - 184, 203, 190, 184, 203, 219, 184, 203, 204, 184, 203, 233, 184, 203, - 179, 184, 203, 209, 184, 203, 194, 184, 203, 223, 184, 203, 186, 184, - 203, 200, 184, 203, 230, 184, 203, 182, 184, 203, 212, 184, 203, 196, - 184, 203, 226, 184, 203, 189, 184, 203, 218, 184, 203, 203, 184, 203, - 232, 184, 203, 177, 184, 203, 207, 184, 203, 192, 184, 203, 221, 184, - 203, 184, 184, 203, 214, 184, 203, 198, 184, 203, 228, 184, 203, 180, - 184, 203, 210, 184, 203, 224, 184, 203, 187, 184, 203, 216, 184, 203, - 201, 184, 203, 231, 184, 203, 178, 184, 203, 208, 184, 203, 193, 184, - 203, 222, 184, 203, 185, 184, 203, 215, 184, 203, 199, 184, 203, 229, - 184, 203, 181, 184, 203, 211, 184, 203, 195, 184, 203, 225, 184, 203, - 188, 184, 203, 217, 184, 203, 202, 110, 45, 184, 237, 39, 110, 82, 45, - 119, 110, 247, 21, 110, 45, 184, 237, 39, 110, 82, 45, 119, 110, 183, - 110, 45, 184, 237, 39, 116, 82, 45, 119, 110, 247, 21, 110, 45, 184, 237, - 39, 116, 82, 45, 119, 110, 183, 110, 45, 184, 237, 39, 116, 45, 119, 110, - 247, 21, 110, 50, 184, 237, 39, 116, 82, 45, 119, 116, 247, 21, 110, 50, - 184, 237, 39, 116, 82, 45, 119, 116, 183, 110, 50, 184, 237, 39, 110, 82, - 45, 119, 116, 247, 21, 110, 50, 184, 237, 39, 110, 82, 45, 119, 116, 183, - 110, 50, 184, 237, 39, 110, 45, 119, 116, 247, 21, 110, 50, 184, 237, 39, - 110, 82, 45, 119, 116, 82, 183, 110, 50, 184, 237, 39, 110, 247, 22, 119, - 110, 82, 183, 110, 50, 184, 237, 39, 110, 45, 119, 110, 82, 183, 110, 50, - 184, 237, 39, 110, 247, 22, 119, 116, 82, 183, 110, 50, 184, 237, 39, - 110, 45, 119, 116, 82, 183, 110, 50, 184, 237, 39, 110, 247, 22, 119, - 116, 183, 110, 45, 184, 237, 39, 116, 247, 22, 119, 116, 82, 183, 110, - 45, 184, 237, 39, 116, 45, 119, 116, 82, 183, 110, 45, 184, 237, 39, 116, - 247, 22, 119, 110, 82, 183, 110, 45, 184, 237, 39, 116, 45, 119, 110, 82, - 183, 110, 45, 184, 237, 39, 116, 247, 22, 119, 110, 183, 110, 45, 184, - 237, 39, 116, 82, 45, 119, 110, 82, 183, 116, 50, 184, 237, 39, 110, 82, - 45, 119, 110, 247, 21, 116, 50, 184, 237, 39, 110, 82, 45, 119, 110, 183, - 116, 50, 184, 237, 39, 116, 82, 45, 119, 110, 247, 21, 116, 50, 184, 237, - 39, 116, 82, 45, 119, 110, 183, 116, 50, 184, 237, 39, 116, 45, 119, 110, - 247, 21, 116, 45, 184, 237, 39, 116, 82, 45, 119, 116, 247, 21, 116, 45, - 184, 237, 39, 116, 82, 45, 119, 116, 183, 116, 45, 184, 237, 39, 110, 82, - 45, 119, 116, 247, 21, 116, 45, 184, 237, 39, 110, 82, 45, 119, 116, 183, - 116, 45, 184, 237, 39, 110, 45, 119, 116, 247, 21, 116, 45, 184, 237, 39, - 110, 82, 45, 119, 116, 82, 183, 116, 45, 184, 237, 39, 110, 247, 22, 119, - 110, 82, 183, 116, 45, 184, 237, 39, 110, 45, 119, 110, 82, 183, 116, 45, - 184, 237, 39, 110, 247, 22, 119, 116, 82, 183, 116, 45, 184, 237, 39, - 110, 45, 119, 116, 82, 183, 116, 45, 184, 237, 39, 110, 247, 22, 119, - 116, 183, 116, 50, 184, 237, 39, 116, 247, 22, 119, 116, 82, 183, 116, - 50, 184, 237, 39, 116, 45, 119, 116, 82, 183, 116, 50, 184, 237, 39, 116, - 247, 22, 119, 110, 82, 183, 116, 50, 184, 237, 39, 116, 45, 119, 110, 82, - 183, 116, 50, 184, 237, 39, 116, 247, 22, 119, 110, 183, 116, 50, 184, - 237, 39, 116, 82, 45, 119, 110, 82, 183, 116, 23, 50, 23, 110, 197, 238, - 115, 208, 21, 248, 129, 45, 23, 110, 23, 50, 197, 238, 115, 208, 21, 248, - 129, 116, 23, 45, 23, 110, 197, 238, 115, 208, 21, 248, 129, 45, 23, 116, - 23, 50, 197, 238, 115, 208, 21, 248, 129, 45, 197, 238, 91, 208, 23, 248, - 129, 116, 197, 238, 91, 208, 23, 248, 129, 50, 197, 238, 91, 208, 23, - 248, 129, 110, 197, 238, 91, 208, 23, 248, 129, 81, 91, 234, 160, 248, - 127, 81, 91, 234, 160, 248, 126, 81, 91, 234, 160, 248, 125, 81, 91, 234, - 160, 248, 124, 81, 91, 234, 160, 248, 123, 81, 91, 234, 160, 248, 122, - 228, 241, 91, 234, 160, 248, 127, 228, 241, 91, 234, 160, 248, 126, 228, - 241, 91, 234, 160, 248, 125, 228, 241, 91, 234, 160, 248, 124, 228, 241, - 91, 234, 160, 248, 123, 228, 241, 91, 234, 160, 248, 122, 45, 23, 110, - 91, 234, 160, 248, 129, 45, 23, 116, 91, 234, 160, 248, 129, 50, 23, 116, - 91, 234, 160, 248, 129, 50, 23, 110, 91, 234, 160, 248, 129, 116, 23, - 110, 91, 234, 160, 248, 129, 228, 241, 91, 234, 160, 248, 128, 116, 91, - 208, 23, 248, 129, 116, 115, 234, 158, 248, 129, 116, 232, 226, 234, 158, - 248, 129, 116, 115, 208, 21, 248, 129, 116, 203, 247, 234, 158, 248, 129, - 50, 91, 208, 23, 248, 129, 50, 115, 234, 158, 248, 129, 50, 232, 226, - 234, 158, 248, 129, 50, 115, 208, 21, 248, 129, 50, 203, 247, 234, 158, - 248, 129, 45, 132, 216, 213, 203, 153, 50, 132, 216, 213, 203, 153, 116, - 132, 216, 213, 203, 153, 110, 132, 216, 213, 203, 153, 223, 95, 216, 213, - 203, 153, 116, 132, 184, 23, 110, 132, 223, 95, 216, 213, 203, 153, 116, - 132, 223, 95, 216, 213, 203, 154, 23, 110, 132, 248, 129, 45, 132, 223, - 95, 216, 213, 203, 154, 23, 50, 132, 248, 129, 243, 124, 248, 108, 233, - 5, 223, 95, 243, 124, 248, 108, 233, 5, 88, 228, 241, 233, 5, 116, 45, - 119, 110, 50, 233, 5, 116, 50, 119, 110, 45, 233, 5, 116, 23, 110, 197, - 238, 132, 248, 129, 45, 23, 50, 197, 238, 132, 248, 129, 116, 45, 197, - 238, 216, 213, 203, 153, 116, 50, 197, 238, 216, 213, 203, 153, 110, 50, - 197, 238, 216, 213, 203, 153, 110, 45, 197, 238, 216, 213, 203, 153, 111, - 122, 156, 237, 39, 116, 247, 22, 119, 82, 219, 224, 111, 122, 156, 237, - 39, 116, 247, 22, 119, 82, 183, 111, 122, 156, 237, 39, 82, 45, 119, 110, - 247, 21, 111, 122, 156, 237, 39, 82, 50, 119, 110, 247, 21, 111, 122, - 156, 237, 39, 116, 247, 22, 119, 82, 45, 119, 110, 247, 21, 111, 122, - 156, 237, 39, 116, 247, 22, 119, 82, 50, 119, 110, 247, 21, 111, 122, - 156, 237, 39, 82, 45, 119, 110, 247, 22, 119, 82, 183, 111, 122, 156, - 237, 39, 82, 45, 119, 116, 247, 22, 119, 82, 183, 111, 122, 156, 237, 39, - 116, 247, 22, 119, 82, 45, 23, 82, 50, 119, 110, 247, 21, 111, 122, 156, - 237, 39, 116, 247, 22, 119, 82, 50, 23, 82, 45, 119, 110, 247, 21, 111, - 122, 156, 237, 39, 116, 247, 22, 119, 82, 50, 119, 110, 247, 22, 119, 82, - 219, 224, 111, 122, 156, 237, 39, 116, 247, 22, 119, 82, 45, 119, 110, - 247, 22, 119, 82, 183, 111, 122, 156, 237, 39, 82, 45, 119, 116, 247, 22, - 119, 82, 50, 119, 110, 247, 21, 111, 122, 156, 237, 39, 82, 50, 119, 116, - 247, 22, 119, 82, 45, 119, 110, 247, 21, 111, 122, 156, 237, 39, 237, 32, - 111, 122, 156, 228, 241, 4, 81, 106, 250, 234, 209, 59, 223, 95, 243, - 126, 77, 45, 132, 206, 42, 217, 90, 50, 132, 206, 42, 217, 90, 223, 95, - 235, 119, 64, 4, 198, 136, 219, 214, 118, 64, 23, 116, 23, 110, 91, 234, - 160, 248, 129, 96, 64, 23, 116, 23, 110, 91, 234, 160, 248, 129, 235, - 119, 64, 23, 50, 91, 234, 160, 248, 129, 196, 66, 64, 23, 50, 91, 234, - 160, 248, 129, 45, 132, 232, 171, 50, 132, 232, 171, 195, 16, 35, 238, - 217, 50, 211, 77, 112, 236, 140, 214, 106, 237, 39, 238, 217, 214, 106, - 237, 39, 82, 50, 119, 110, 247, 21, 214, 106, 237, 39, 237, 32, 63, 88, - 205, 155, 4, 206, 113, 239, 0, 45, 199, 1, 63, 50, 209, 58, 223, 148, 82, - 199, 1, 63, 50, 209, 58, 223, 148, 50, 199, 1, 63, 50, 209, 58, 223, 148, - 214, 106, 112, 208, 13, 77, 201, 75, 233, 12, 201, 75, 233, 13, 4, 250, - 247, 207, 146, 201, 75, 233, 13, 219, 231, 219, 224, 201, 75, 233, 13, - 219, 231, 183, 201, 75, 233, 13, 4, 235, 106, 63, 196, 76, 243, 100, 205, - 42, 17, 191, 77, 205, 42, 17, 107, 205, 42, 17, 109, 205, 42, 17, 138, - 205, 42, 17, 134, 205, 42, 17, 149, 205, 42, 17, 169, 205, 42, 17, 175, - 205, 42, 17, 171, 205, 42, 17, 178, 12, 15, 228, 13, 12, 15, 228, 12, 12, - 15, 228, 11, 12, 15, 228, 10, 12, 15, 228, 9, 12, 15, 228, 8, 12, 15, - 228, 7, 12, 15, 228, 6, 12, 15, 228, 5, 12, 15, 228, 4, 12, 15, 228, 3, - 12, 15, 228, 2, 12, 15, 228, 1, 12, 15, 228, 0, 12, 15, 227, 255, 12, 15, - 227, 254, 12, 15, 227, 253, 12, 15, 227, 252, 12, 15, 227, 251, 12, 15, - 227, 250, 12, 15, 227, 249, 12, 15, 227, 248, 12, 15, 227, 247, 12, 15, - 227, 246, 12, 15, 227, 245, 12, 15, 227, 244, 12, 15, 227, 243, 12, 15, - 227, 242, 12, 15, 227, 241, 12, 15, 227, 240, 12, 15, 227, 239, 12, 15, - 227, 238, 12, 15, 227, 237, 12, 15, 227, 236, 12, 15, 227, 235, 12, 15, - 227, 234, 12, 15, 227, 233, 12, 15, 227, 232, 12, 15, 227, 231, 12, 15, - 227, 230, 12, 15, 227, 229, 12, 15, 227, 228, 12, 15, 227, 227, 12, 15, - 227, 226, 12, 15, 227, 225, 12, 15, 227, 224, 12, 15, 227, 223, 12, 15, - 227, 222, 12, 15, 227, 221, 12, 15, 227, 220, 12, 15, 227, 219, 12, 15, - 227, 218, 12, 15, 227, 217, 12, 15, 227, 216, 12, 15, 227, 215, 12, 15, - 227, 214, 12, 15, 227, 213, 12, 15, 227, 212, 12, 15, 227, 211, 12, 15, - 227, 210, 12, 15, 227, 209, 12, 15, 227, 208, 12, 15, 227, 207, 12, 15, - 227, 206, 12, 15, 227, 205, 12, 15, 227, 204, 12, 15, 227, 203, 12, 15, - 227, 202, 12, 15, 227, 201, 12, 15, 227, 200, 12, 15, 227, 199, 12, 15, - 227, 198, 12, 15, 227, 197, 12, 15, 227, 196, 12, 15, 227, 195, 12, 15, - 227, 194, 12, 15, 227, 193, 12, 15, 227, 192, 12, 15, 227, 191, 12, 15, - 227, 190, 12, 15, 227, 189, 12, 15, 227, 188, 12, 15, 227, 187, 12, 15, - 227, 186, 12, 15, 227, 185, 12, 15, 227, 184, 12, 15, 227, 183, 12, 15, - 227, 182, 12, 15, 227, 181, 12, 15, 227, 180, 12, 15, 227, 179, 12, 15, - 227, 178, 12, 15, 227, 177, 12, 15, 227, 176, 12, 15, 227, 175, 12, 15, - 227, 174, 12, 15, 227, 173, 12, 15, 227, 172, 12, 15, 227, 171, 12, 15, - 227, 170, 12, 15, 227, 169, 12, 15, 227, 168, 12, 15, 227, 167, 12, 15, - 227, 166, 12, 15, 227, 165, 12, 15, 227, 164, 12, 15, 227, 163, 12, 15, - 227, 162, 12, 15, 227, 161, 12, 15, 227, 160, 12, 15, 227, 159, 12, 15, - 227, 158, 12, 15, 227, 157, 12, 15, 227, 156, 12, 15, 227, 155, 12, 15, - 227, 154, 12, 15, 227, 153, 12, 15, 227, 152, 12, 15, 227, 151, 12, 15, - 227, 150, 12, 15, 227, 149, 12, 15, 227, 148, 12, 15, 227, 147, 12, 15, - 227, 146, 12, 15, 227, 145, 12, 15, 227, 144, 12, 15, 227, 143, 12, 15, - 227, 142, 12, 15, 227, 141, 12, 15, 227, 140, 12, 15, 227, 139, 12, 15, - 227, 138, 12, 15, 227, 137, 12, 15, 227, 136, 12, 15, 227, 135, 12, 15, - 227, 134, 12, 15, 227, 133, 12, 15, 227, 132, 12, 15, 227, 131, 12, 15, - 227, 130, 12, 15, 227, 129, 12, 15, 227, 128, 12, 15, 227, 127, 12, 15, - 227, 126, 12, 15, 227, 125, 12, 15, 227, 124, 12, 15, 227, 123, 12, 15, - 227, 122, 12, 15, 227, 121, 12, 15, 227, 120, 12, 15, 227, 119, 12, 15, - 227, 118, 12, 15, 227, 117, 12, 15, 227, 116, 12, 15, 227, 115, 12, 15, - 227, 114, 12, 15, 227, 113, 12, 15, 227, 112, 12, 15, 227, 111, 12, 15, - 227, 110, 12, 15, 227, 109, 12, 15, 227, 108, 12, 15, 227, 107, 12, 15, - 227, 106, 12, 15, 227, 105, 12, 15, 227, 104, 12, 15, 227, 103, 12, 15, - 227, 102, 12, 15, 227, 101, 12, 15, 227, 100, 12, 15, 227, 99, 12, 15, - 227, 98, 12, 15, 227, 97, 12, 15, 227, 96, 12, 15, 227, 95, 12, 15, 227, - 94, 12, 15, 227, 93, 12, 15, 227, 92, 12, 15, 227, 91, 12, 15, 227, 90, - 12, 15, 227, 89, 12, 15, 227, 88, 12, 15, 227, 87, 12, 15, 227, 86, 12, - 15, 227, 85, 12, 15, 227, 84, 12, 15, 227, 83, 12, 15, 227, 82, 12, 15, - 227, 81, 12, 15, 227, 80, 12, 15, 227, 79, 12, 15, 227, 78, 12, 15, 227, - 77, 12, 15, 227, 76, 12, 15, 227, 75, 12, 15, 227, 74, 12, 15, 227, 73, - 12, 15, 227, 72, 12, 15, 227, 71, 12, 15, 227, 70, 12, 15, 227, 69, 12, - 15, 227, 68, 12, 15, 227, 67, 12, 15, 227, 66, 12, 15, 227, 65, 12, 15, - 227, 64, 12, 15, 227, 63, 12, 15, 227, 62, 12, 15, 227, 61, 12, 15, 227, - 60, 12, 15, 227, 59, 12, 15, 227, 58, 12, 15, 227, 57, 12, 15, 227, 56, - 12, 15, 227, 55, 12, 15, 227, 54, 12, 15, 227, 53, 12, 15, 227, 52, 12, - 15, 227, 51, 12, 15, 227, 50, 12, 15, 227, 49, 12, 15, 227, 48, 12, 15, - 227, 47, 12, 15, 227, 46, 12, 15, 227, 45, 12, 15, 227, 44, 12, 15, 227, - 43, 12, 15, 227, 42, 12, 15, 227, 41, 12, 15, 227, 40, 12, 15, 227, 39, - 12, 15, 227, 38, 12, 15, 227, 37, 12, 15, 227, 36, 12, 15, 227, 35, 12, - 15, 227, 34, 12, 15, 227, 33, 12, 15, 227, 32, 12, 15, 227, 31, 12, 15, - 227, 30, 12, 15, 227, 29, 12, 15, 227, 28, 12, 15, 227, 27, 12, 15, 227, - 26, 12, 15, 227, 25, 12, 15, 227, 24, 12, 15, 227, 23, 12, 15, 227, 22, - 12, 15, 227, 21, 12, 15, 227, 20, 12, 15, 227, 19, 12, 15, 227, 18, 12, - 15, 227, 17, 12, 15, 227, 16, 12, 15, 227, 15, 12, 15, 227, 14, 12, 15, - 227, 13, 12, 15, 227, 12, 12, 15, 227, 11, 12, 15, 227, 10, 12, 15, 227, - 9, 12, 15, 227, 8, 12, 15, 227, 7, 12, 15, 227, 6, 12, 15, 227, 5, 12, - 15, 227, 4, 12, 15, 227, 3, 12, 15, 227, 2, 12, 15, 227, 1, 12, 15, 227, - 0, 12, 15, 226, 255, 12, 15, 226, 254, 12, 15, 226, 253, 12, 15, 226, - 252, 12, 15, 226, 251, 12, 15, 226, 250, 12, 15, 226, 249, 12, 15, 226, - 248, 12, 15, 226, 247, 12, 15, 226, 246, 12, 15, 226, 245, 12, 15, 226, - 244, 12, 15, 226, 243, 12, 15, 226, 242, 12, 15, 226, 241, 12, 15, 226, - 240, 12, 15, 226, 239, 12, 15, 226, 238, 12, 15, 226, 237, 12, 15, 226, - 236, 12, 15, 226, 235, 12, 15, 226, 234, 12, 15, 226, 233, 12, 15, 226, - 232, 12, 15, 226, 231, 12, 15, 226, 230, 12, 15, 226, 229, 12, 15, 226, - 228, 12, 15, 226, 227, 12, 15, 226, 226, 12, 15, 226, 225, 12, 15, 226, - 224, 12, 15, 226, 223, 12, 15, 226, 222, 12, 15, 226, 221, 12, 15, 226, - 220, 12, 15, 226, 219, 12, 15, 226, 218, 12, 15, 226, 217, 12, 15, 226, - 216, 12, 15, 226, 215, 12, 15, 226, 214, 12, 15, 226, 213, 12, 15, 226, - 212, 12, 15, 226, 211, 12, 15, 226, 210, 12, 15, 226, 209, 12, 15, 226, - 208, 12, 15, 226, 207, 12, 15, 226, 206, 12, 15, 226, 205, 12, 15, 226, - 204, 12, 15, 226, 203, 12, 15, 226, 202, 12, 15, 226, 201, 12, 15, 226, - 200, 12, 15, 226, 199, 12, 15, 226, 198, 12, 15, 226, 197, 12, 15, 226, - 196, 12, 15, 226, 195, 12, 15, 226, 194, 12, 15, 226, 193, 12, 15, 226, - 192, 12, 15, 226, 191, 12, 15, 226, 190, 12, 15, 226, 189, 12, 15, 226, - 188, 12, 15, 226, 187, 12, 15, 226, 186, 12, 15, 226, 185, 12, 15, 226, - 184, 12, 15, 226, 183, 12, 15, 226, 182, 12, 15, 226, 181, 12, 15, 226, - 180, 12, 15, 226, 179, 12, 15, 226, 178, 12, 15, 226, 177, 12, 15, 226, - 176, 12, 15, 226, 175, 12, 15, 226, 174, 12, 15, 226, 173, 12, 15, 226, - 172, 12, 15, 226, 171, 12, 15, 226, 170, 12, 15, 226, 169, 12, 15, 226, - 168, 12, 15, 226, 167, 12, 15, 226, 166, 12, 15, 226, 165, 12, 15, 226, - 164, 12, 15, 226, 163, 12, 15, 226, 162, 12, 15, 226, 161, 12, 15, 226, - 160, 12, 15, 226, 159, 12, 15, 226, 158, 12, 15, 226, 157, 12, 15, 226, - 156, 12, 15, 226, 155, 12, 15, 226, 154, 12, 15, 226, 153, 12, 15, 226, - 152, 12, 15, 226, 151, 12, 15, 226, 150, 12, 15, 226, 149, 12, 15, 226, - 148, 12, 15, 226, 147, 12, 15, 226, 146, 12, 15, 226, 145, 12, 15, 226, - 144, 12, 15, 226, 143, 12, 15, 226, 142, 12, 15, 226, 141, 12, 15, 226, - 140, 12, 15, 226, 139, 12, 15, 226, 138, 12, 15, 226, 137, 12, 15, 226, - 136, 12, 15, 226, 135, 12, 15, 226, 134, 12, 15, 226, 133, 12, 15, 226, - 132, 12, 15, 226, 131, 12, 15, 226, 130, 12, 15, 226, 129, 12, 15, 226, - 128, 12, 15, 226, 127, 12, 15, 226, 126, 12, 15, 226, 125, 12, 15, 226, - 124, 12, 15, 226, 123, 12, 15, 226, 122, 12, 15, 226, 121, 12, 15, 226, - 120, 12, 15, 226, 119, 12, 15, 226, 118, 12, 15, 226, 117, 12, 15, 226, - 116, 12, 15, 226, 115, 12, 15, 226, 114, 12, 15, 226, 113, 12, 15, 226, - 112, 12, 15, 226, 111, 12, 15, 226, 110, 12, 15, 226, 109, 12, 15, 226, - 108, 12, 15, 226, 107, 12, 15, 226, 106, 12, 15, 226, 105, 12, 15, 226, - 104, 12, 15, 226, 103, 12, 15, 226, 102, 12, 15, 226, 101, 12, 15, 226, - 100, 12, 15, 226, 99, 12, 15, 226, 98, 12, 15, 226, 97, 12, 15, 226, 96, - 12, 15, 226, 95, 12, 15, 226, 94, 12, 15, 226, 93, 12, 15, 226, 92, 12, - 15, 226, 91, 12, 15, 226, 90, 12, 15, 226, 89, 12, 15, 226, 88, 12, 15, - 226, 87, 12, 15, 226, 86, 12, 15, 226, 85, 12, 15, 226, 84, 12, 15, 226, - 83, 12, 15, 226, 82, 12, 15, 226, 81, 12, 15, 226, 80, 12, 15, 226, 79, - 12, 15, 226, 78, 12, 15, 226, 77, 12, 15, 226, 76, 12, 15, 226, 75, 12, - 15, 226, 74, 12, 15, 226, 73, 12, 15, 226, 72, 12, 15, 226, 71, 12, 15, - 226, 70, 12, 15, 226, 69, 12, 15, 226, 68, 12, 15, 226, 67, 12, 15, 226, - 66, 12, 15, 226, 65, 12, 15, 226, 64, 12, 15, 226, 63, 12, 15, 226, 62, - 12, 15, 226, 61, 12, 15, 226, 60, 12, 15, 226, 59, 12, 15, 226, 58, 12, - 15, 226, 57, 12, 15, 226, 56, 12, 15, 226, 55, 12, 15, 226, 54, 12, 15, - 226, 53, 12, 15, 226, 52, 12, 15, 226, 51, 12, 15, 226, 50, 12, 15, 226, - 49, 12, 15, 226, 48, 12, 15, 226, 47, 12, 15, 226, 46, 12, 15, 226, 45, - 12, 15, 226, 44, 12, 15, 226, 43, 12, 15, 226, 42, 12, 15, 226, 41, 12, - 15, 226, 40, 12, 15, 226, 39, 12, 15, 226, 38, 12, 15, 226, 37, 12, 15, - 226, 36, 12, 15, 226, 35, 12, 15, 226, 34, 12, 15, 226, 33, 12, 15, 226, - 32, 12, 15, 226, 31, 12, 15, 226, 30, 12, 15, 226, 29, 12, 15, 226, 28, - 12, 15, 226, 27, 12, 15, 226, 26, 12, 15, 226, 25, 12, 15, 226, 24, 12, - 15, 226, 23, 12, 15, 226, 22, 12, 15, 226, 21, 12, 15, 226, 20, 12, 15, - 226, 19, 12, 15, 226, 18, 12, 15, 226, 17, 12, 15, 226, 16, 12, 15, 226, - 15, 12, 15, 226, 14, 12, 15, 226, 13, 12, 15, 226, 12, 12, 15, 226, 11, - 12, 15, 226, 10, 12, 15, 226, 9, 12, 15, 226, 8, 12, 15, 226, 7, 12, 15, - 226, 6, 12, 15, 226, 5, 12, 15, 226, 4, 12, 15, 226, 3, 12, 15, 226, 2, - 12, 15, 226, 1, 12, 15, 226, 0, 12, 15, 225, 255, 12, 15, 225, 254, 12, - 15, 225, 253, 12, 15, 225, 252, 12, 15, 225, 251, 12, 15, 225, 250, 12, - 15, 225, 249, 12, 15, 225, 248, 12, 15, 225, 247, 12, 15, 225, 246, 12, - 15, 225, 245, 12, 15, 225, 244, 12, 15, 225, 243, 12, 15, 225, 242, 12, - 15, 225, 241, 12, 15, 225, 240, 220, 20, 199, 223, 199, 224, 201, 247, - 199, 224, 233, 216, 77, 199, 224, 207, 252, 77, 199, 224, 31, 56, 199, - 224, 236, 155, 56, 199, 224, 210, 13, 56, 199, 224, 251, 137, 199, 224, - 251, 49, 199, 224, 45, 210, 113, 199, 224, 50, 210, 113, 199, 224, 250, - 193, 199, 224, 108, 56, 199, 224, 242, 74, 199, 224, 228, 87, 199, 224, - 232, 80, 201, 63, 199, 224, 202, 23, 199, 224, 17, 191, 77, 199, 224, 17, - 107, 199, 224, 17, 109, 199, 224, 17, 138, 199, 224, 17, 134, 199, 224, - 17, 149, 199, 224, 17, 169, 199, 224, 17, 175, 199, 224, 17, 171, 199, - 224, 17, 178, 199, 224, 242, 83, 199, 224, 204, 25, 199, 224, 219, 180, - 56, 199, 224, 234, 43, 56, 199, 224, 230, 204, 56, 199, 224, 208, 13, 77, - 199, 224, 242, 72, 250, 182, 199, 224, 8, 6, 1, 65, 199, 224, 8, 6, 1, - 250, 120, 199, 224, 8, 6, 1, 247, 193, 199, 224, 8, 6, 1, 238, 127, 199, - 224, 8, 6, 1, 71, 199, 224, 8, 6, 1, 233, 175, 199, 224, 8, 6, 1, 232, - 51, 199, 224, 8, 6, 1, 230, 116, 199, 224, 8, 6, 1, 68, 199, 224, 8, 6, - 1, 223, 35, 199, 224, 8, 6, 1, 222, 152, 199, 224, 8, 6, 1, 172, 199, - 224, 8, 6, 1, 218, 168, 199, 224, 8, 6, 1, 215, 61, 199, 224, 8, 6, 1, - 74, 199, 224, 8, 6, 1, 210, 236, 199, 224, 8, 6, 1, 208, 104, 199, 224, - 8, 6, 1, 146, 199, 224, 8, 6, 1, 206, 8, 199, 224, 8, 6, 1, 200, 43, 199, - 224, 8, 6, 1, 66, 199, 224, 8, 6, 1, 196, 12, 199, 224, 8, 6, 1, 193, - 224, 199, 224, 8, 6, 1, 192, 235, 199, 224, 8, 6, 1, 192, 159, 199, 224, - 8, 6, 1, 191, 166, 199, 224, 45, 51, 248, 53, 199, 224, 207, 19, 202, 23, - 199, 224, 50, 51, 248, 53, 199, 224, 243, 2, 252, 60, 199, 224, 130, 219, - 112, 199, 224, 230, 211, 252, 60, 199, 224, 8, 2, 1, 65, 199, 224, 8, 2, - 1, 250, 120, 199, 224, 8, 2, 1, 247, 193, 199, 224, 8, 2, 1, 238, 127, - 199, 224, 8, 2, 1, 71, 199, 224, 8, 2, 1, 233, 175, 199, 224, 8, 2, 1, - 232, 51, 199, 224, 8, 2, 1, 230, 116, 199, 224, 8, 2, 1, 68, 199, 224, 8, - 2, 1, 223, 35, 199, 224, 8, 2, 1, 222, 152, 199, 224, 8, 2, 1, 172, 199, - 224, 8, 2, 1, 218, 168, 199, 224, 8, 2, 1, 215, 61, 199, 224, 8, 2, 1, - 74, 199, 224, 8, 2, 1, 210, 236, 199, 224, 8, 2, 1, 208, 104, 199, 224, - 8, 2, 1, 146, 199, 224, 8, 2, 1, 206, 8, 199, 224, 8, 2, 1, 200, 43, 199, - 224, 8, 2, 1, 66, 199, 224, 8, 2, 1, 196, 12, 199, 224, 8, 2, 1, 193, - 224, 199, 224, 8, 2, 1, 192, 235, 199, 224, 8, 2, 1, 192, 159, 199, 224, - 8, 2, 1, 191, 166, 199, 224, 45, 238, 171, 248, 53, 199, 224, 81, 219, - 112, 199, 224, 50, 238, 171, 248, 53, 199, 224, 198, 152, 247, 127, 199, - 223, 67, 204, 211, 67, 204, 200, 67, 204, 189, 67, 204, 177, 67, 204, - 166, 67, 204, 155, 67, 204, 144, 67, 204, 133, 67, 204, 122, 67, 204, - 114, 67, 204, 113, 67, 204, 112, 67, 204, 111, 67, 204, 109, 67, 204, - 108, 67, 204, 107, 67, 204, 106, 67, 204, 105, 67, 204, 104, 67, 204, - 103, 67, 204, 102, 67, 204, 101, 67, 204, 100, 67, 204, 98, 67, 204, 97, - 67, 204, 96, 67, 204, 95, 67, 204, 94, 67, 204, 93, 67, 204, 92, 67, 204, - 91, 67, 204, 90, 67, 204, 89, 67, 204, 87, 67, 204, 86, 67, 204, 85, 67, - 204, 84, 67, 204, 83, 67, 204, 82, 67, 204, 81, 67, 204, 80, 67, 204, 79, - 67, 204, 78, 67, 204, 76, 67, 204, 75, 67, 204, 74, 67, 204, 73, 67, 204, - 72, 67, 204, 71, 67, 204, 70, 67, 204, 69, 67, 204, 68, 67, 204, 67, 67, - 204, 65, 67, 204, 64, 67, 204, 63, 67, 204, 62, 67, 204, 61, 67, 204, 60, - 67, 204, 59, 67, 204, 58, 67, 204, 57, 67, 204, 56, 67, 204, 54, 67, 204, - 53, 67, 204, 52, 67, 204, 51, 67, 204, 50, 67, 204, 49, 67, 204, 48, 67, - 204, 47, 67, 204, 46, 67, 204, 45, 67, 204, 43, 67, 204, 42, 67, 204, 41, - 67, 204, 40, 67, 204, 39, 67, 204, 38, 67, 204, 37, 67, 204, 36, 67, 204, - 35, 67, 204, 34, 67, 205, 31, 67, 205, 30, 67, 205, 29, 67, 205, 28, 67, - 205, 27, 67, 205, 26, 67, 205, 25, 67, 205, 24, 67, 205, 23, 67, 205, 22, - 67, 205, 20, 67, 205, 19, 67, 205, 18, 67, 205, 17, 67, 205, 16, 67, 205, - 15, 67, 205, 14, 67, 205, 13, 67, 205, 12, 67, 205, 11, 67, 205, 9, 67, - 205, 8, 67, 205, 7, 67, 205, 6, 67, 205, 5, 67, 205, 4, 67, 205, 3, 67, - 205, 2, 67, 205, 1, 67, 205, 0, 67, 204, 254, 67, 204, 253, 67, 204, 252, - 67, 204, 251, 67, 204, 250, 67, 204, 249, 67, 204, 248, 67, 204, 247, 67, - 204, 246, 67, 204, 245, 67, 204, 243, 67, 204, 242, 67, 204, 241, 67, - 204, 240, 67, 204, 239, 67, 204, 238, 67, 204, 237, 67, 204, 236, 67, - 204, 235, 67, 204, 234, 67, 204, 232, 67, 204, 231, 67, 204, 230, 67, - 204, 229, 67, 204, 228, 67, 204, 227, 67, 204, 226, 67, 204, 225, 67, - 204, 224, 67, 204, 223, 67, 204, 221, 67, 204, 220, 67, 204, 219, 67, - 204, 218, 67, 204, 217, 67, 204, 216, 67, 204, 215, 67, 204, 214, 67, - 204, 213, 67, 204, 212, 67, 204, 210, 67, 204, 209, 67, 204, 208, 67, - 204, 207, 67, 204, 206, 67, 204, 205, 67, 204, 204, 67, 204, 203, 67, - 204, 202, 67, 204, 201, 67, 204, 199, 67, 204, 198, 67, 204, 197, 67, - 204, 196, 67, 204, 195, 67, 204, 194, 67, 204, 193, 67, 204, 192, 67, - 204, 191, 67, 204, 190, 67, 204, 188, 67, 204, 187, 67, 204, 186, 67, - 204, 185, 67, 204, 184, 67, 204, 183, 67, 204, 182, 67, 204, 181, 67, - 204, 180, 67, 204, 179, 67, 204, 176, 67, 204, 175, 67, 204, 174, 67, - 204, 173, 67, 204, 172, 67, 204, 171, 67, 204, 170, 67, 204, 169, 67, - 204, 168, 67, 204, 167, 67, 204, 165, 67, 204, 164, 67, 204, 163, 67, - 204, 162, 67, 204, 161, 67, 204, 160, 67, 204, 159, 67, 204, 158, 67, - 204, 157, 67, 204, 156, 67, 204, 154, 67, 204, 153, 67, 204, 152, 67, - 204, 151, 67, 204, 150, 67, 204, 149, 67, 204, 148, 67, 204, 147, 67, - 204, 146, 67, 204, 145, 67, 204, 143, 67, 204, 142, 67, 204, 141, 67, - 204, 140, 67, 204, 139, 67, 204, 138, 67, 204, 137, 67, 204, 136, 67, - 204, 135, 67, 204, 134, 67, 204, 132, 67, 204, 131, 67, 204, 130, 67, - 204, 129, 67, 204, 128, 67, 204, 127, 67, 204, 126, 67, 204, 125, 67, - 204, 124, 67, 204, 123, 67, 204, 121, 67, 204, 120, 67, 204, 119, 67, - 204, 118, 67, 204, 117, 67, 204, 116, 67, 204, 115, 212, 138, 212, 140, - 201, 98, 79, 229, 232, 202, 27, 201, 98, 79, 199, 53, 201, 6, 234, 95, - 79, 199, 53, 233, 244, 234, 95, 79, 198, 11, 234, 57, 234, 81, 234, 82, - 252, 51, 252, 52, 251, 189, 248, 238, 249, 140, 248, 16, 246, 240, 199, - 230, 228, 241, 199, 230, 228, 165, 199, 236, 219, 113, 233, 50, 214, 80, - 219, 112, 234, 95, 79, 219, 112, 219, 161, 213, 105, 234, 60, 219, 113, - 199, 230, 81, 199, 230, 193, 251, 232, 146, 233, 50, 233, 27, 247, 88, - 207, 22, 238, 236, 203, 77, 211, 14, 219, 33, 107, 202, 46, 203, 77, 223, - 162, 219, 33, 191, 77, 202, 222, 237, 210, 219, 103, 234, 14, 236, 185, - 237, 75, 239, 22, 107, 237, 199, 237, 75, 239, 22, 109, 237, 198, 237, - 75, 239, 22, 138, 237, 197, 237, 75, 239, 22, 134, 237, 196, 214, 106, - 252, 51, 214, 233, 200, 69, 223, 228, 200, 73, 234, 95, 79, 198, 12, 248, - 129, 233, 252, 247, 126, 247, 128, 234, 95, 79, 216, 212, 234, 58, 234, - 114, 200, 226, 200, 245, 234, 14, 234, 15, 223, 137, 204, 11, 134, 233, - 7, 204, 10, 232, 90, 223, 137, 204, 11, 138, 230, 187, 204, 10, 230, 184, - 223, 137, 204, 11, 109, 207, 98, 204, 10, 206, 74, 223, 137, 204, 11, - 107, 196, 91, 204, 10, 196, 45, 201, 250, 237, 116, 237, 118, 210, 208, - 246, 239, 210, 210, 137, 211, 158, 208, 220, 228, 244, 248, 42, 210, 1, - 229, 192, 248, 58, 213, 44, 248, 42, 229, 192, 214, 191, 223, 148, 223, - 150, 214, 73, 219, 112, 214, 104, 201, 98, 79, 205, 36, 251, 8, 201, 175, - 234, 95, 79, 205, 36, 251, 8, 234, 17, 246, 240, 199, 231, 203, 252, 228, - 241, 199, 231, 203, 252, 228, 162, 246, 240, 199, 231, 4, 222, 164, 228, - 241, 199, 231, 4, 222, 164, 228, 163, 219, 113, 199, 231, 203, 252, 81, - 199, 231, 203, 252, 193, 250, 210, 105, 219, 113, 232, 132, 210, 105, - 219, 113, 235, 123, 209, 94, 210, 105, 219, 113, 249, 139, 210, 105, 219, - 113, 196, 77, 209, 88, 207, 19, 219, 113, 233, 50, 207, 19, 223, 148, - 207, 1, 202, 170, 203, 77, 109, 202, 167, 201, 177, 202, 170, 203, 77, - 138, 202, 166, 201, 176, 237, 75, 239, 22, 201, 30, 237, 194, 208, 205, - 196, 44, 107, 208, 205, 196, 42, 208, 164, 208, 205, 196, 44, 109, 208, - 205, 196, 41, 208, 163, 203, 253, 198, 10, 201, 95, 201, 13, 247, 127, - 246, 239, 247, 61, 216, 169, 193, 171, 215, 81, 201, 98, 79, 230, 172, - 251, 8, 201, 98, 79, 208, 182, 251, 8, 201, 249, 234, 95, 79, 230, 172, - 251, 8, 234, 95, 79, 208, 182, 251, 8, 234, 55, 201, 98, 79, 201, 30, - 202, 9, 202, 170, 230, 216, 246, 240, 223, 96, 203, 170, 202, 170, 246, - 240, 223, 96, 205, 85, 239, 22, 204, 7, 223, 96, 238, 196, 201, 31, 199, - 80, 201, 118, 211, 68, 200, 58, 242, 73, 211, 34, 208, 206, 216, 168, - 209, 76, 251, 45, 208, 198, 242, 73, 251, 62, 214, 179, 202, 231, 8, 6, - 1, 231, 91, 8, 2, 1, 231, 91, 247, 4, 9, 2, 137, 34, 131, 4, 99, 249, 80, - 251, 166, 200, 63, 200, 232, 242, 84, 202, 110, 219, 224, 222, 81, 1, - 219, 62, 220, 17, 1, 232, 176, 232, 166, 220, 17, 1, 232, 176, 233, 62, - 220, 17, 1, 206, 162, 220, 17, 1, 219, 43, 86, 87, 248, 141, 203, 50, - 231, 54, 216, 118, 207, 9, 30, 125, 192, 54, 30, 125, 192, 50, 30, 125, - 201, 153, 30, 125, 192, 55, 232, 66, 232, 65, 232, 64, 215, 83, 232, 63, - 200, 197, 1, 251, 14, 68, 190, 232, 190, 233, 190, 235, 218, 229, 206, - 170, 218, 231, 206, 172, 210, 66, 218, 228, 206, 169, 213, 75, 216, 16, - 193, 50, 218, 230, 206, 171, 232, 89, 210, 65, 193, 111, 234, 119, 232, - 76, 216, 92, 211, 105, 196, 46, 113, 216, 92, 237, 216, 113, 118, 197, - 240, 64, 4, 55, 81, 106, 96, 197, 240, 64, 4, 55, 81, 106, 11, 5, 223, - 51, 77, 80, 1, 221, 206, 219, 73, 194, 251, 194, 140, 194, 72, 194, 61, - 194, 50, 194, 39, 194, 28, 194, 17, 194, 6, 194, 250, 194, 239, 194, 228, - 194, 217, 194, 206, 194, 195, 194, 184, 208, 221, 232, 146, 40, 81, 50, - 63, 219, 187, 248, 53, 247, 198, 211, 51, 77, 248, 100, 190, 234, 10, 3, - 212, 148, 199, 84, 10, 3, 212, 148, 139, 212, 148, 247, 231, 139, 247, - 230, 216, 218, 6, 1, 230, 116, 216, 218, 6, 1, 214, 70, 216, 218, 2, 1, - 230, 116, 216, 218, 2, 1, 214, 70, 61, 1, 235, 14, 73, 37, 16, 232, 88, - 202, 106, 243, 52, 195, 164, 194, 173, 194, 162, 194, 151, 194, 139, 194, - 128, 194, 117, 194, 106, 194, 95, 194, 84, 194, 76, 194, 75, 194, 74, - 194, 73, 194, 71, 194, 70, 194, 69, 194, 68, 194, 67, 194, 66, 194, 65, - 194, 64, 194, 63, 194, 62, 194, 60, 194, 59, 194, 58, 194, 57, 194, 56, - 194, 55, 194, 54, 194, 53, 194, 52, 194, 51, 194, 49, 194, 48, 194, 47, - 194, 46, 194, 45, 194, 44, 194, 43, 194, 42, 194, 41, 194, 40, 194, 38, - 194, 37, 194, 36, 194, 35, 194, 34, 194, 33, 194, 32, 194, 31, 194, 30, - 194, 29, 194, 27, 194, 26, 194, 25, 194, 24, 194, 23, 194, 22, 194, 21, - 194, 20, 194, 19, 194, 18, 194, 16, 194, 15, 194, 14, 194, 13, 194, 12, - 194, 11, 194, 10, 194, 9, 194, 8, 194, 7, 194, 5, 194, 4, 194, 3, 194, 2, - 194, 1, 194, 0, 193, 255, 193, 254, 193, 253, 193, 252, 194, 249, 194, - 248, 194, 247, 194, 246, 194, 245, 194, 244, 194, 243, 194, 242, 194, - 241, 194, 240, 194, 238, 194, 237, 194, 236, 194, 235, 194, 234, 194, - 233, 194, 232, 194, 231, 194, 230, 194, 229, 194, 227, 194, 226, 194, - 225, 194, 224, 194, 223, 194, 222, 194, 221, 194, 220, 194, 219, 194, - 218, 194, 216, 194, 215, 194, 214, 194, 213, 194, 212, 194, 211, 194, - 210, 194, 209, 194, 208, 194, 207, 194, 205, 194, 204, 194, 203, 194, - 202, 194, 201, 194, 200, 194, 199, 194, 198, 194, 197, 194, 196, 194, - 194, 194, 193, 194, 192, 194, 191, 194, 190, 194, 189, 194, 188, 194, - 187, 194, 186, 194, 185, 194, 183, 194, 182, 194, 181, 194, 180, 194, - 179, 194, 178, 194, 177, 194, 176, 194, 175, 194, 174, 194, 172, 194, - 171, 194, 170, 194, 169, 194, 168, 194, 167, 194, 166, 194, 165, 194, - 164, 194, 163, 194, 161, 194, 160, 194, 159, 194, 158, 194, 157, 194, - 156, 194, 155, 194, 154, 194, 153, 194, 152, 194, 150, 194, 149, 194, - 148, 194, 147, 194, 146, 194, 145, 194, 144, 194, 143, 194, 142, 194, - 141, 194, 138, 194, 137, 194, 136, 194, 135, 194, 134, 194, 133, 194, - 132, 194, 131, 194, 130, 194, 129, 194, 127, 194, 126, 194, 125, 194, - 124, 194, 123, 194, 122, 194, 121, 194, 120, 194, 119, 194, 118, 194, - 116, 194, 115, 194, 114, 194, 113, 194, 112, 194, 111, 194, 110, 194, - 109, 194, 108, 194, 107, 194, 105, 194, 104, 194, 103, 194, 102, 194, - 101, 194, 100, 194, 99, 194, 98, 194, 97, 194, 96, 194, 94, 194, 93, 194, - 92, 194, 91, 194, 90, 194, 89, 194, 88, 194, 87, 194, 86, 194, 85, 194, - 83, 194, 82, 194, 81, 194, 80, 194, 79, 194, 78, 194, 77, 221, 219, 31, - 56, 221, 219, 250, 193, 221, 219, 17, 191, 77, 221, 219, 17, 107, 221, - 219, 17, 109, 221, 219, 17, 138, 221, 219, 17, 134, 221, 219, 17, 149, - 221, 219, 17, 169, 221, 219, 17, 175, 221, 219, 17, 171, 221, 219, 17, - 178, 8, 6, 1, 42, 4, 217, 147, 23, 230, 210, 8, 2, 1, 42, 4, 217, 147, - 23, 230, 210, 8, 6, 1, 228, 74, 4, 217, 147, 23, 230, 210, 8, 2, 1, 228, - 74, 4, 217, 147, 23, 230, 210, 8, 6, 1, 126, 4, 217, 147, 23, 230, 210, - 8, 2, 1, 126, 4, 217, 147, 23, 230, 210, 8, 6, 1, 235, 15, 4, 81, 219, - 113, 60, 8, 2, 1, 235, 15, 4, 81, 219, 113, 60, 8, 6, 1, 235, 15, 4, 81, - 219, 113, 248, 233, 23, 230, 210, 8, 2, 1, 235, 15, 4, 81, 219, 113, 248, - 233, 23, 230, 210, 8, 6, 1, 235, 15, 4, 81, 219, 113, 248, 233, 23, 252, - 46, 8, 2, 1, 235, 15, 4, 81, 219, 113, 248, 233, 23, 252, 46, 8, 6, 1, - 187, 4, 81, 219, 113, 60, 8, 2, 1, 187, 4, 81, 219, 113, 60, 8, 6, 1, - 187, 4, 81, 219, 113, 248, 233, 23, 230, 210, 8, 2, 1, 187, 4, 81, 219, - 113, 248, 233, 23, 230, 210, 8, 6, 1, 187, 4, 81, 219, 113, 248, 233, 23, - 252, 46, 8, 2, 1, 187, 4, 81, 219, 113, 248, 233, 23, 252, 46, 8, 6, 1, - 206, 9, 4, 81, 219, 113, 60, 8, 2, 1, 206, 9, 4, 81, 219, 113, 60, 8, 6, - 1, 235, 15, 4, 243, 2, 23, 217, 146, 8, 2, 1, 235, 15, 4, 243, 2, 23, - 217, 146, 8, 6, 1, 235, 15, 4, 243, 2, 23, 247, 92, 8, 2, 1, 235, 15, 4, - 243, 2, 23, 247, 92, 8, 2, 1, 228, 74, 4, 75, 93, 23, 252, 46, 8, 2, 1, - 214, 71, 4, 198, 153, 58, 8, 6, 1, 42, 4, 211, 139, 23, 252, 46, 8, 2, 1, - 42, 4, 211, 139, 23, 252, 46, 8, 6, 1, 42, 4, 211, 139, 23, 198, 152, 8, - 2, 1, 42, 4, 211, 139, 23, 198, 152, 8, 6, 1, 235, 15, 4, 211, 139, 23, - 252, 46, 8, 2, 1, 235, 15, 4, 211, 139, 23, 252, 46, 8, 6, 1, 235, 15, 4, - 211, 139, 23, 198, 152, 8, 2, 1, 235, 15, 4, 211, 139, 23, 198, 152, 8, - 6, 1, 235, 15, 4, 75, 93, 23, 252, 46, 8, 2, 1, 235, 15, 4, 75, 93, 23, - 252, 46, 8, 6, 1, 235, 15, 4, 75, 93, 23, 198, 152, 8, 2, 1, 235, 15, 4, - 75, 93, 23, 198, 152, 8, 2, 1, 228, 74, 4, 75, 93, 23, 230, 210, 8, 2, 1, - 228, 74, 4, 75, 93, 23, 198, 152, 8, 6, 1, 228, 74, 4, 211, 139, 23, 252, - 46, 8, 2, 1, 228, 74, 4, 211, 139, 23, 75, 93, 23, 252, 46, 8, 6, 1, 228, - 74, 4, 211, 139, 23, 198, 152, 8, 2, 1, 228, 74, 4, 211, 139, 23, 75, 93, - 23, 198, 152, 8, 6, 1, 223, 36, 4, 198, 152, 8, 2, 1, 223, 36, 4, 75, 93, - 23, 198, 152, 8, 6, 1, 220, 143, 4, 198, 152, 8, 2, 1, 220, 143, 4, 198, - 152, 8, 6, 1, 218, 169, 4, 198, 152, 8, 2, 1, 218, 169, 4, 198, 152, 8, - 6, 1, 207, 222, 4, 198, 152, 8, 2, 1, 207, 222, 4, 198, 152, 8, 6, 1, - 126, 4, 211, 139, 23, 252, 46, 8, 2, 1, 126, 4, 211, 139, 23, 252, 46, 8, - 6, 1, 126, 4, 211, 139, 23, 198, 152, 8, 2, 1, 126, 4, 211, 139, 23, 198, - 152, 8, 6, 1, 126, 4, 217, 147, 23, 252, 46, 8, 2, 1, 126, 4, 217, 147, - 23, 252, 46, 8, 6, 1, 126, 4, 217, 147, 23, 198, 152, 8, 2, 1, 126, 4, - 217, 147, 23, 198, 152, 8, 2, 1, 252, 26, 4, 230, 210, 8, 2, 1, 211, 77, - 187, 4, 230, 210, 8, 2, 1, 211, 77, 187, 4, 252, 46, 8, 2, 1, 153, 196, - 13, 4, 230, 210, 8, 2, 1, 153, 196, 13, 4, 252, 46, 8, 2, 1, 205, 87, 4, - 230, 210, 8, 2, 1, 205, 87, 4, 252, 46, 8, 2, 1, 228, 250, 205, 87, 4, - 230, 210, 8, 2, 1, 228, 250, 205, 87, 4, 252, 46, 9, 204, 7, 99, 4, 230, - 58, 93, 4, 251, 192, 9, 204, 7, 99, 4, 230, 58, 93, 4, 193, 133, 9, 204, - 7, 99, 4, 230, 58, 93, 4, 131, 217, 99, 9, 204, 7, 99, 4, 230, 58, 93, 4, - 211, 151, 9, 204, 7, 99, 4, 230, 58, 93, 4, 66, 9, 204, 7, 99, 4, 230, - 58, 93, 4, 191, 225, 9, 204, 7, 99, 4, 230, 58, 93, 4, 71, 9, 204, 7, 99, - 4, 230, 58, 93, 4, 252, 25, 9, 204, 7, 213, 25, 4, 222, 4, 100, 204, 7, - 40, 1, 208, 96, 100, 204, 7, 40, 1, 221, 193, 100, 204, 7, 40, 1, 231, - 66, 100, 204, 7, 40, 1, 191, 123, 100, 204, 7, 40, 1, 237, 180, 100, 204, - 7, 40, 1, 207, 6, 100, 204, 7, 40, 1, 233, 109, 100, 204, 7, 40, 1, 191, - 175, 248, 225, 204, 7, 40, 1, 206, 109, 248, 225, 204, 7, 40, 1, 207, 6, - 248, 225, 204, 7, 40, 1, 191, 175, 230, 144, 204, 7, 40, 1, 219, 73, 230, - 144, 204, 7, 40, 1, 203, 165, 230, 144, 204, 7, 40, 1, 221, 193, 230, - 144, 204, 7, 40, 1, 231, 66, 230, 144, 204, 7, 40, 1, 191, 123, 230, 144, - 204, 7, 40, 1, 233, 109, 211, 45, 204, 7, 40, 1, 206, 109, 211, 45, 204, - 7, 40, 1, 207, 6, 248, 225, 1, 221, 187, 44, 120, 222, 152, 44, 120, 214, - 70, 44, 120, 247, 193, 44, 120, 212, 103, 44, 120, 197, 135, 44, 120, - 213, 80, 44, 120, 200, 43, 44, 120, 215, 61, 44, 120, 210, 236, 44, 120, - 218, 168, 44, 120, 192, 159, 44, 120, 146, 44, 120, 172, 44, 120, 196, - 12, 44, 120, 219, 63, 44, 120, 219, 74, 44, 120, 206, 110, 44, 120, 213, - 62, 44, 120, 223, 35, 44, 120, 203, 167, 44, 120, 201, 178, 44, 120, 206, - 8, 44, 120, 230, 116, 44, 120, 220, 247, 44, 5, 222, 127, 44, 5, 221, - 166, 44, 5, 221, 145, 44, 5, 220, 232, 44, 5, 220, 187, 44, 5, 222, 22, - 44, 5, 222, 13, 44, 5, 222, 102, 44, 5, 221, 67, 44, 5, 221, 41, 44, 5, - 222, 42, 44, 5, 214, 67, 44, 5, 214, 16, 44, 5, 214, 12, 44, 5, 213, 237, - 44, 5, 213, 228, 44, 5, 214, 55, 44, 5, 214, 53, 44, 5, 214, 64, 44, 5, - 213, 249, 44, 5, 213, 244, 44, 5, 214, 57, 44, 5, 247, 159, 44, 5, 243, - 29, 44, 5, 243, 19, 44, 5, 238, 195, 44, 5, 238, 153, 44, 5, 247, 42, 44, - 5, 247, 34, 44, 5, 247, 148, 44, 5, 242, 99, 44, 5, 239, 18, 44, 5, 247, - 76, 44, 5, 212, 100, 44, 5, 212, 81, 44, 5, 212, 75, 44, 5, 212, 58, 44, - 5, 212, 50, 44, 5, 212, 90, 44, 5, 212, 89, 44, 5, 212, 97, 44, 5, 212, - 65, 44, 5, 212, 62, 44, 5, 212, 93, 44, 5, 197, 131, 44, 5, 197, 111, 44, - 5, 197, 110, 44, 5, 197, 99, 44, 5, 197, 96, 44, 5, 197, 127, 44, 5, 197, - 126, 44, 5, 197, 130, 44, 5, 197, 109, 44, 5, 197, 108, 44, 5, 197, 129, - 44, 5, 213, 78, 44, 5, 213, 64, 44, 5, 213, 63, 44, 5, 213, 47, 44, 5, - 213, 46, 44, 5, 213, 74, 44, 5, 213, 73, 44, 5, 213, 77, 44, 5, 213, 49, - 44, 5, 213, 48, 44, 5, 213, 76, 44, 5, 199, 245, 44, 5, 198, 193, 44, 5, - 198, 170, 44, 5, 197, 94, 44, 5, 197, 49, 44, 5, 199, 145, 44, 5, 199, - 121, 44, 5, 199, 217, 44, 5, 159, 44, 5, 198, 59, 44, 5, 199, 166, 44, 5, - 214, 250, 44, 5, 213, 219, 44, 5, 213, 186, 44, 5, 212, 178, 44, 5, 212, - 115, 44, 5, 214, 121, 44, 5, 214, 110, 44, 5, 214, 236, 44, 5, 213, 43, - 44, 5, 213, 26, 44, 5, 214, 205, 44, 5, 210, 220, 44, 5, 209, 185, 44, 5, - 209, 145, 44, 5, 208, 165, 44, 5, 208, 128, 44, 5, 210, 63, 44, 5, 210, - 49, 44, 5, 210, 198, 44, 5, 209, 73, 44, 5, 209, 37, 44, 5, 210, 80, 44, - 5, 217, 151, 44, 5, 216, 100, 44, 5, 216, 61, 44, 5, 215, 155, 44, 5, - 215, 93, 44, 5, 216, 232, 44, 5, 216, 211, 44, 5, 217, 112, 44, 5, 216, - 12, 44, 5, 215, 211, 44, 5, 217, 25, 44, 5, 192, 140, 44, 5, 192, 33, 44, - 5, 192, 23, 44, 5, 191, 225, 44, 5, 191, 188, 44, 5, 192, 80, 44, 5, 192, - 77, 44, 5, 192, 119, 44, 5, 192, 12, 44, 5, 191, 246, 44, 5, 192, 91, 44, - 5, 207, 178, 44, 5, 207, 1, 44, 5, 206, 195, 44, 5, 206, 68, 44, 5, 206, - 29, 44, 5, 207, 113, 44, 5, 207, 84, 44, 5, 207, 156, 44, 5, 206, 162, - 44, 5, 206, 134, 44, 5, 207, 125, 44, 5, 220, 125, 44, 5, 219, 146, 44, - 5, 219, 128, 44, 5, 218, 225, 44, 5, 218, 194, 44, 5, 219, 238, 44, 5, - 219, 228, 44, 5, 220, 96, 44, 5, 219, 43, 44, 5, 219, 8, 44, 5, 220, 0, - 44, 5, 195, 187, 44, 5, 195, 69, 44, 5, 195, 51, 44, 5, 193, 249, 44, 5, - 193, 241, 44, 5, 195, 153, 44, 5, 195, 148, 44, 5, 195, 183, 44, 5, 195, - 24, 44, 5, 195, 8, 44, 5, 195, 160, 44, 5, 219, 61, 44, 5, 219, 56, 44, - 5, 219, 55, 44, 5, 219, 52, 44, 5, 219, 51, 44, 5, 219, 58, 44, 5, 219, - 57, 44, 5, 219, 60, 44, 5, 219, 54, 44, 5, 219, 53, 44, 5, 219, 59, 44, - 5, 219, 72, 44, 5, 219, 65, 44, 5, 219, 64, 44, 5, 219, 48, 44, 5, 219, - 47, 44, 5, 219, 68, 44, 5, 219, 67, 44, 5, 219, 71, 44, 5, 219, 50, 44, - 5, 219, 49, 44, 5, 219, 69, 44, 5, 206, 108, 44, 5, 206, 97, 44, 5, 206, - 96, 44, 5, 206, 89, 44, 5, 206, 82, 44, 5, 206, 104, 44, 5, 206, 103, 44, - 5, 206, 107, 44, 5, 206, 95, 44, 5, 206, 94, 44, 5, 206, 106, 44, 5, 213, - 60, 44, 5, 213, 55, 44, 5, 213, 54, 44, 5, 213, 51, 44, 5, 213, 50, 44, - 5, 213, 57, 44, 5, 213, 56, 44, 5, 213, 59, 44, 5, 213, 53, 44, 5, 213, - 52, 44, 5, 213, 58, 44, 5, 223, 31, 44, 5, 222, 244, 44, 5, 222, 236, 44, - 5, 222, 182, 44, 5, 222, 162, 44, 5, 223, 10, 44, 5, 223, 8, 44, 5, 223, - 25, 44, 5, 222, 201, 44, 5, 222, 191, 44, 5, 223, 17, 44, 5, 203, 160, - 44, 5, 203, 81, 44, 5, 203, 76, 44, 5, 203, 5, 44, 5, 202, 243, 44, 5, - 203, 113, 44, 5, 203, 111, 44, 5, 203, 148, 44, 5, 203, 56, 44, 5, 203, - 48, 44, 5, 203, 122, 44, 5, 201, 174, 44, 5, 201, 142, 44, 5, 201, 138, - 44, 5, 201, 129, 44, 5, 201, 126, 44, 5, 201, 148, 44, 5, 201, 147, 44, - 5, 201, 173, 44, 5, 201, 134, 44, 5, 201, 133, 44, 5, 201, 150, 44, 5, - 205, 197, 44, 5, 202, 222, 44, 5, 202, 193, 44, 5, 201, 4, 44, 5, 200, - 160, 44, 5, 205, 68, 44, 5, 205, 50, 44, 5, 205, 181, 44, 5, 202, 46, 44, - 5, 202, 16, 44, 5, 205, 114, 44, 5, 230, 91, 44, 5, 229, 158, 44, 5, 229, - 130, 44, 5, 228, 159, 44, 5, 228, 128, 44, 5, 229, 245, 44, 5, 229, 215, - 44, 5, 230, 80, 44, 5, 229, 23, 44, 5, 228, 252, 44, 5, 230, 2, 44, 5, - 220, 246, 44, 5, 220, 245, 44, 5, 220, 240, 44, 5, 220, 239, 44, 5, 220, - 236, 44, 5, 220, 235, 44, 5, 220, 242, 44, 5, 220, 241, 44, 5, 220, 244, - 44, 5, 220, 238, 44, 5, 220, 237, 44, 5, 220, 243, 44, 5, 203, 14, 166, - 120, 3, 192, 105, 166, 120, 3, 207, 144, 166, 120, 3, 207, 50, 101, 1, - 196, 224, 95, 120, 3, 242, 91, 155, 95, 120, 3, 242, 91, 221, 215, 95, - 120, 3, 242, 91, 221, 67, 95, 120, 3, 242, 91, 221, 183, 95, 120, 3, 242, - 91, 213, 249, 95, 120, 3, 242, 91, 247, 160, 95, 120, 3, 242, 91, 247, 1, - 95, 120, 3, 242, 91, 242, 99, 95, 120, 3, 242, 91, 243, 68, 95, 120, 3, - 242, 91, 212, 65, 95, 120, 3, 242, 91, 238, 32, 95, 120, 3, 242, 91, 197, - 120, 95, 120, 3, 242, 91, 236, 174, 95, 120, 3, 242, 91, 197, 115, 95, - 120, 3, 242, 91, 180, 95, 120, 3, 242, 91, 190, 190, 95, 120, 3, 242, 91, - 199, 49, 95, 120, 3, 242, 91, 159, 95, 120, 3, 242, 91, 198, 241, 95, - 120, 3, 242, 91, 213, 43, 95, 120, 3, 242, 91, 249, 153, 95, 120, 3, 242, - 91, 209, 228, 95, 120, 3, 242, 91, 209, 73, 95, 120, 3, 242, 91, 209, - 199, 95, 120, 3, 242, 91, 216, 12, 95, 120, 3, 242, 91, 192, 12, 95, 120, - 3, 242, 91, 206, 162, 95, 120, 3, 242, 91, 219, 43, 95, 120, 3, 242, 91, - 195, 24, 95, 120, 3, 242, 91, 203, 165, 95, 120, 3, 242, 91, 201, 175, - 95, 120, 3, 242, 91, 188, 95, 120, 3, 242, 91, 140, 95, 120, 3, 242, 91, - 173, 95, 18, 3, 242, 91, 208, 96, 95, 223, 149, 18, 3, 242, 91, 208, 33, - 95, 223, 149, 18, 3, 242, 91, 206, 17, 95, 223, 149, 18, 3, 242, 91, 206, - 10, 95, 223, 149, 18, 3, 242, 91, 208, 75, 95, 18, 3, 211, 113, 95, 18, - 3, 252, 167, 229, 120, 1, 248, 181, 214, 68, 229, 120, 1, 248, 181, 214, - 16, 229, 120, 1, 248, 181, 213, 237, 229, 120, 1, 248, 181, 214, 55, 229, - 120, 1, 248, 181, 213, 249, 72, 1, 248, 181, 214, 68, 72, 1, 248, 181, - 214, 16, 72, 1, 248, 181, 213, 237, 72, 1, 248, 181, 214, 55, 72, 1, 248, - 181, 213, 249, 72, 1, 251, 228, 247, 42, 72, 1, 251, 228, 197, 94, 72, 1, - 251, 228, 159, 72, 1, 251, 228, 210, 236, 52, 1, 233, 200, 233, 199, 239, - 26, 163, 164, 52, 1, 233, 199, 233, 200, 239, 26, 163, 164, +static const unsigned int dawg_pos_to_codepoint[] = { + 8448, 129687, 983053, 983052, 180, 10655, 8301, 8299, 9190, 125185, + 125197, 125214, 125208, 125204, 125187, 125201, 125216, 125213, 125200, + 125211, 125209, 125189, 125217, 125207, 125186, 125205, 125215, 125184, + 125191, 125188, 125198, 125202, 125199, 125210, 125190, 125194, 125206, + 125192, 125212, 125193, 125195, 125196, 125203, 125256, 125219, 125231, + 125248, 125242, 125238, 125221, 125235, 125250, 125247, 125234, 125245, + 125243, 125223, 125251, 125241, 125220, 125239, 125249, 125218, 125225, + 125222, 125232, 125236, 125233, 125244, 125224, 125228, 125240, 125226, + 125246, 125227, 125229, 125230, 125237, 125257, 125254, 125278, 125279, + 125259, 125258, 125255, 125252, 125253, 125269, 125268, 125271, 125270, + 125267, 125266, 125264, 125273, 125265, 125272, 11237, 127903, 129657, + 8449, 129489, 9772, 65852, 65853, 65854, 65855, 65848, 65851, 65849, + 65850, 65847, 65792, 65793, 65806, 65815, 65842, 65824, 65833, 65812, + 65839, 65803, 65821, 65830, 65811, 65838, 65802, 65820, 65829, 65807, + 65816, 65843, 65825, 65834, 65805, 65814, 65841, 65823, 65832, 65804, + 65813, 65840, 65822, 65831, 65810, 65837, 65801, 65819, 65828, 65809, + 65836, 65800, 65818, 65827, 65808, 65835, 65799, 65817, 65826, 65794, + 128673, 71455, 71453, 71454, 71442, 71450, 71446, 71429, 71492, 71491, + 71444, 71443, 71490, 71489, 71436, 71428, 71494, 71438, 71426, 71493, + 71440, 71427, 71448, 71432, 71435, 71488, 71447, 71445, 71449, 71434, + 71425, 71424, 71431, 71430, 71441, 71433, 71437, 71439, 71484, 71485, + 71467, 71486, 71487, 71456, 71457, 71465, 71466, 71463, 71460, 71461, + 71458, 71459, 71462, 71464, 71483, 71482, 71477, 71476, 71479, 71478, + 71475, 71474, 71472, 71481, 71473, 71480, 9992, 128747, 128748, 128874, + 128822, 128823, 128837, 128776, 128777, 128774, 128775, 128773, 128811, + 128859, 128829, 128826, 128855, 128769, 128875, 128876, 128830, 128834, + 128835, 128836, 128783, 128857, 128848, 128846, 128844, 128805, 128800, + 128803, 128804, 128798, 128869, 128870, 128871, 128872, 128873, 128787, + 128865, 128866, 128864, 128880, 128794, 128841, 128883, 128882, 128854, + 128878, 128796, 128797, 128801, 128810, 128851, 128784, 128785, 128786, + 128824, 128881, 128789, 128879, 128782, 128843, 128858, 128856, 128868, + 128867, 128863, 128768, 128833, 128818, 128816, 128817, 128799, 128819, + 128820, 128821, 128827, 128828, 128877, 128792, 128793, 128788, 128806, + 128813, 128825, 128850, 128860, 128861, 128814, 128807, 128812, 128802, + 128862, 128781, 128839, 128795, 128852, 128847, 128831, 128832, 128840, + 128809, 128849, 128845, 128778, 128815, 128779, 128780, 128790, 128791, + 128808, 128772, 128842, 128853, 128771, 128838, 128770, 9879, 8501, + 983054, 8780, 9006, 983203, 8776, 10863, 8778, 9095, 9941, 128126, 9200, + 38, 127994, 127944, 128657, 10815, 82970, 82971, 82964, 82965, 82966, + 82967, 82968, 82969, 82972, 82973, 82974, 82994, 82995, 82996, 82987, + 82988, 82992, 82993, 82986, 82989, 82990, 82991, 82997, 82998, 82999, + 83016, 83017, 83018, 83019, 83010, 83011, 83012, 83013, 83014, 83015, + 83020, 83021, 83022, 83050, 83051, 83052, 83053, 83043, 83044, 83045, + 83046, 83047, 83048, 83049, 83054, 82984, 82985, 82975, 82976, 82977, + 82978, 82979, 82980, 82981, 82982, 82983, 82953, 82954, 82955, 82956, + 82957, 82958, 82959, 82960, 82961, 82962, 82963, 82944, 82945, 82946, + 82947, 82948, 82949, 82950, 82951, 82952, 83000, 83001, 83002, 83003, + 83004, 83005, 83006, 83007, 83008, 83009, 83023, 83024, 83025, 83026, + 83027, 83028, 83029, 83030, 83031, 83032, 83033, 83034, 83035, 83036, + 83037, 83038, 83039, 83040, 83041, 83042, 83062, 83063, 83064, 83065, + 83070, 83071, 83072, 83073, 83066, 83067, 83068, 83055, 83056, 83057, + 83058, 83059, 83060, 83061, 83069, 83074, 83075, 83076, 83077, 83078, + 83083, 83084, 83079, 83080, 83081, 83082, 83085, 83086, 83087, 83088, + 83094, 83095, 83089, 83090, 83091, 83092, 83093, 83096, 83097, 83098, + 83099, 83105, 83106, 83100, 83101, 83102, 83103, 83104, 83107, 83108, + 83109, 83110, 83111, 83112, 83113, 83114, 83115, 83116, 83117, 83118, + 83119, 83120, 83121, 83122, 83123, 83124, 83125, 83126, 83127, 83128, + 83129, 83130, 83131, 83132, 83133, 83134, 83135, 83136, 83137, 83138, + 83139, 83140, 83141, 83142, 83143, 83144, 83145, 83146, 83147, 83148, + 83149, 83150, 83151, 83152, 83153, 83154, 83155, 83156, 83157, 83158, + 83159, 83160, 83161, 83162, 83163, 83164, 83165, 83166, 83167, 83168, + 83169, 83170, 83173, 83174, 83175, 83180, 83181, 83183, 83184, 83171, + 83172, 83176, 83177, 83178, 83179, 83182, 83190, 83191, 83192, 83193, + 83185, 83186, 83187, 83188, 83189, 83194, 83195, 83196, 83274, 83275, + 83280, 83281, 83270, 83271, 83272, 83273, 83276, 83277, 83278, 83279, + 83268, 83269, 83259, 83260, 83261, 83262, 83263, 83264, 83265, 83266, + 83267, 83204, 83205, 83197, 83198, 83199, 83200, 83201, 83202, 83203, + 83206, 83207, 83245, 83246, 83238, 83239, 83240, 83241, 83242, 83243, + 83244, 83247, 83248, 83208, 83209, 83210, 83211, 83212, 83213, 83214, + 83215, 83216, 83217, 83218, 83219, 83220, 83221, 83222, 83223, 83224, + 83225, 83226, 83227, 83228, 83229, 83230, 83231, 83232, 83233, 83234, + 83235, 83236, 83237, 83249, 83250, 83251, 83252, 83253, 83254, 83255, + 83256, 83257, 83258, 83291, 83292, 83282, 83283, 83284, 83285, 83286, + 83287, 83288, 83289, 83290, 83312, 83313, 83303, 83304, 83305, 83306, + 83307, 83308, 83309, 83310, 83311, 83348, 83349, 83339, 83340, 83341, + 83342, 83343, 83344, 83345, 83346, 83347, 83322, 83323, 83324, 83325, + 83316, 83317, 83318, 83314, 83315, 83319, 83320, 83321, 83326, 83327, + 83328, 83354, 83355, 83359, 83360, 83350, 83351, 83352, 83353, 83356, + 83357, 83358, 83361, 83377, 83378, 83374, 83375, 83381, 83382, 83373, + 83376, 83379, 83380, 83383, 83384, 83385, 83389, 83386, 83387, 83388, + 83390, 83391, 83392, 83393, 83394, 83395, 83363, 83364, 83362, 83365, + 83366, 83367, 83368, 83369, 83370, 83371, 83372, 83293, 83294, 83295, + 83296, 83297, 83298, 83299, 83300, 83301, 83302, 83329, 83330, 83331, + 83332, 83333, 83334, 83335, 83336, 83337, 83338, 83406, 83407, 83408, + 83409, 83410, 83411, 83412, 83413, 83414, 83415, 83416, 83447, 83448, + 83455, 83456, 83449, 83450, 83451, 83452, 83453, 83454, 83457, 83458, + 83489, 83490, 83491, 83492, 83493, 83494, 83495, 83496, 83396, 83397, + 83398, 83399, 83400, 83401, 83402, 83403, 83404, 83405, 83417, 83418, + 83419, 83420, 83421, 83422, 83423, 83424, 83425, 83426, 83427, 83428, + 83429, 83430, 83431, 83432, 83433, 83434, 83435, 83436, 83437, 83438, + 83439, 83440, 83441, 83442, 83443, 83444, 83445, 83446, 83459, 83460, + 83461, 83462, 83463, 83464, 83465, 83466, 83467, 83468, 83469, 83470, + 83471, 83472, 83473, 83474, 83475, 83476, 83477, 83478, 83479, 83480, + 83481, 83482, 83483, 83484, 83485, 83486, 83487, 83488, 83526, 83497, + 83498, 83499, 83500, 83501, 83502, 83503, 83504, 83505, 83506, 83507, + 83508, 83509, 83510, 83511, 83512, 83513, 83514, 83515, 83516, 83517, + 83518, 83519, 83520, 83521, 83522, 83523, 83524, 83525, 129728, 8736, + 10654, 10660, 128551, 8491, 128162, 128544, 128028, 11150, 11148, 11149, + 11151, 11119, 8630, 10560, 8755, 128260, 10226, 8634, 10769, 128246, + 9875, 10193, 9765, 9021, 9055, 9061, 9033, 9052, 9022, 9066, 9058, 9067, + 9042, 9049, 9035, 9034, 9038, 9062, 9073, 9046, 9050, 9075, 9080, 9014, + 9082, 9078, 9077, 9081, 9060, 9051, 9063, 9029, 9109, 9020, 9056, 9017, + 9018, 9036, 9047, 9044, 9037, 9043, 9040, 9027, 9031, 9072, 9071, 9016, + 9026, 9025, 9028, 9032, 9019, 9054, 9048, 9030, 9076, 9070, 9023, 9059, + 9069, 9015, 9079, 9024, 9074, 9057, 9041, 9045, 9053, 9039, 9065, 9064, + 9068, 39, 11236, 8773, 8786, 10864, 8774, 8784, 983195, 983196, 2277, + 2280, 2276, 2279, 2278, 2281, 1548, 1615, 65144, 65145, 2302, 1612, + 65138, 1549, 2206, 2299, 2300, 2274, 1643, 1771, 1770, 1757, 1565, 1614, + 1630, 2293, 2292, 65142, 65143, 1611, 65136, 1538, 1645, 1748, 2207, + 1621, 1620, 1616, 2294, 65146, 65147, 1613, 65140, 2258, 2255, 2254, + 2257, 2236, 2244, 2235, 2237, 1593, 1886, 2227, 1696, 1887, 1885, 65226, + 65227, 65225, 65228, 1575, 2165, 2176, 2173, 2161, 2174, 2171, 2167, + 2177, 2169, 2166, 2168, 2178, 2164, 2160, 2162, 2175, 2172, 1571, 65156, + 65155, 1573, 65160, 65159, 1651, 1650, 1908, 1907, 1570, 65154, 65153, + 2163, 2170, 1649, 64337, 64336, 1609, 65264, 65263, 65166, 65165, 1749, + 1576, 2230, 1878, 2208, 1874, 1875, 1872, 1876, 1877, 1873, 2209, 65168, + 65169, 65167, 65170, 1664, 64347, 64348, 64346, 64349, 1659, 64339, + 64340, 64338, 64341, 1583, 1674, 1675, 1882, 1774, 1679, 2222, 1881, + 1680, 1673, 65194, 65193, 1676, 64389, 64388, 1590, 1787, 65214, 65215, + 65213, 65216, 1677, 64387, 64386, 1672, 64393, 64392, 1646, 1697, 1647, + 1668, 64371, 64372, 64370, 64373, 1678, 64391, 64390, 1740, 1911, 1910, + 1909, 1599, 1598, 1597, 64509, 64510, 64508, 64511, 1601, 1699, 2212, + 1698, 1889, 1701, 1888, 65234, 65235, 65233, 65236, 1711, 1716, 1714, + 1712, 2224, 64403, 64404, 64402, 64405, 1594, 2243, 1788, 65230, 65231, + 65229, 65232, 1715, 64407, 64408, 64406, 64409, 2248, 1581, 1916, 2186, + 1903, 1906, 1902, 1880, 1669, 1666, 1879, 1665, 65186, 65187, 65185, + 65188, 1569, 65152, 1607, 1729, 1730, 64423, 64424, 64422, 64425, 1791, + 1728, 64421, 64420, 1726, 64427, 64428, 64426, 64429, 65258, 65259, + 65257, 65260, 1652, 1653, 1656, 1654, 1580, 2210, 2246, 2245, 65182, + 65183, 65181, 65184, 1688, 64395, 64394, 1603, 1919, 1710, 2228, 1708, + 1707, 65242, 65243, 65241, 65244, 1568, 1705, 1892, 1596, 1891, 2189, + 1595, 2242, 1890, 64399, 64400, 64398, 64401, 1733, 64481, 64480, 1737, + 64483, 64482, 1582, 65190, 65191, 65189, 65192, 1604, 2214, 1718, 2247, + 1717, 1720, 1719, 1898, 65246, 65247, 65245, 65248, 2221, 1605, 2215, + 1894, 1893, 65250, 65251, 65249, 65252, 1564, 1709, 1713, 64411, 64412, + 64410, 64413, 64468, 64469, 64467, 64470, 1667, 64375, 64376, 64374, + 64377, 1606, 1722, 64415, 64414, 1896, 1897, 1725, 1895, 2185, 1721, + 1724, 65254, 65255, 65253, 65256, 1662, 2231, 2238, 64343, 64344, 64342, + 64345, 1702, 64367, 64368, 64366, 64369, 1602, 2213, 2229, 1703, 1704, + 65238, 65239, 65237, 65240, 1585, 1905, 2233, 1682, 1685, 1883, 1899, + 1687, 1775, 1900, 1689, 1684, 1686, 2218, 1683, 65198, 65197, 1681, + 64397, 64396, 1723, 64417, 64418, 64416, 64419, 2220, 1589, 2223, 1694, + 1693, 65210, 65211, 65209, 65212, 1587, 1690, 1918, 1904, 1691, 1692, + 1901, 1884, 1917, 65202, 65203, 65201, 65204, 1588, 1786, 65206, 65207, + 65205, 65208, 1648, 2225, 1706, 1591, 2211, 2188, 1695, 2187, 65218, + 65219, 65217, 65220, 1670, 2241, 1727, 64379, 64380, 64378, 64381, 1671, + 64383, 64384, 64382, 64385, 1578, 1577, 65172, 65171, 1731, 65176, 2232, + 2239, 1661, 1660, 65174, 65175, 65173, 1663, 64355, 64356, 64354, 64357, + 1584, 65196, 65195, 1579, 65178, 65179, 65177, 65180, 2182, 1657, 2240, + 64359, 64360, 64358, 64361, 1658, 64351, 64352, 64350, 64353, 1735, 1655, + 64477, 64472, 64471, 64488, 64489, 1739, 1700, 64363, 64364, 64362, + 64365, 64479, 64478, 1608, 2219, 1743, 1913, 1912, 1572, 65158, 65157, + 1738, 1732, 65262, 65261, 1610, 1746, 1915, 1914, 1747, 64433, 64432, + 64431, 64430, 1574, 65162, 65163, 65161, 65164, 1742, 2216, 2234, 2217, + 1741, 1745, 65266, 65267, 65265, 65268, 1736, 64476, 64475, 1734, 64474, + 64473, 1592, 65222, 65223, 65221, 65224, 1586, 65200, 65199, 2226, 1744, + 64485, 64486, 64484, 64487, 2297, 2295, 64888, 64887, 64886, 64950, + 64699, 64554, 64964, 64885, 64698, 64553, 64787, 64759, 64788, 64760, + 64842, 64839, 64841, 64840, 64845, 65015, 64656, 64605, 64828, 64829, + 65010, 65011, 65023, 64962, 64669, 64518, 64672, 64738, 64926, 64670, + 64519, 64622, 64521, 64668, 64517, 64620, 64671, 64520, 64737, 64621, + 64619, 64618, 64623, 64522, 65021, 64878, 64939, 64693, 64547, 64880, + 64879, 64694, 64548, 64803, 64775, 64692, 64546, 64695, 64549, 64812, + 64784, 64804, 64776, 64893, 64892, 64704, 64559, 64636, 64561, 64702, + 64557, 64961, 64705, 64560, 64703, 64558, 64637, 64562, 64889, 64891, + 64890, 64701, 64556, 64789, 64761, 64700, 64555, 64790, 64762, 64859, + 64858, 64682, 64536, 64795, 64767, 64959, 64681, 64535, 64796, 64768, + 64915, 64916, 64728, 64594, 64595, 64596, 64727, 64593, 64729, 64934, + 64958, 64679, 64533, 64857, 64856, 64935, 64933, 64680, 64534, 64797, + 64769, 64798, 64770, 65019, 64643, 64573, 64640, 64567, 64708, 64568, + 64641, 64711, 64571, 64747, 64710, 64570, 64709, 64569, 64963, 64955, + 64951, 64642, 64712, 64572, 64748, 64644, 64574, 64538, 64799, 64771, + 64683, 64537, 64684, 64539, 64800, 64772, 65272, 65271, 65274, 65273, + 65270, 65269, 64646, 64579, 65276, 65275, 64898, 64949, 64896, 64897, + 64714, 64576, 64717, 64899, 64900, 64954, 64956, 64940, 64713, 64575, + 64902, 64901, 64715, 64577, 64904, 64903, 64941, 64645, 64716, 64578, + 64749, 64647, 64580, 64585, 64648, 64905, 64906, 64907, 64719, 64582, + 64910, 64911, 64953, 64720, 64583, 64909, 64914, 64908, 64960, 64718, + 64581, 64945, 64649, 64721, 64584, 64586, 65012, 64918, 64917, 64947, + 64723, 64588, 64726, 64751, 64952, 64957, 64921, 64920, 64919, 64967, + 64722, 64587, 64923, 64922, 64652, 64725, 64590, 64750, 64654, 64591, + 64653, 64651, 64724, 64589, 64650, 64655, 64592, 64895, 64948, 64894, + 64946, 64707, 64564, 64638, 64565, 64706, 64563, 64639, 64566, 65009, + 64843, 64833, 64835, 64836, 64837, 64834, 64832, 64847, 65014, 64604, + 64869, 64868, 64937, 64689, 64544, 64965, 64870, 64691, 64545, 64801, + 64773, 64690, 64811, 64783, 64802, 64774, 65013, 64975, 65008, 65017, + 65018, 64844, 64838, 64860, 64686, 64541, 64821, 64817, 64744, 64862, + 64861, 64685, 64540, 64820, 64936, 64966, 64687, 64542, 64822, 64864, + 64863, 64865, 64867, 64866, 64688, 64543, 64743, 64791, 64763, 64810, + 64782, 64792, 64764, 64606, 64609, 64755, 64607, 64610, 64756, 64611, + 64608, 64754, 64818, 64746, 64872, 64871, 64938, 64806, 64814, 64778, + 64824, 64873, 64805, 64813, 64777, 64823, 64875, 64874, 64877, 64876, + 64808, 64816, 64780, 64745, 64793, 64765, 64807, 64815, 64779, 64825, + 64809, 64781, 64794, 64766, 65022, 64846, 64882, 64881, 64883, 64884, + 64819, 64551, 64826, 64785, 64757, 64696, 64550, 64786, 64758, 64851, + 64850, 64849, 64674, 64524, 64677, 64740, 64930, 64852, 64929, 64675, + 64525, 64928, 64848, 64927, 64673, 64523, 64932, 64853, 64855, 64854, + 64931, 64626, 64676, 64526, 64739, 64628, 64527, 64627, 64625, 64624, + 64629, 64528, 64603, 64529, 64634, 64531, 64632, 64678, 64530, 64741, + 64633, 64631, 64630, 64635, 64532, 64742, 65016, 64661, 64601, 64616, + 64515, 64491, 64490, 64493, 64492, 64503, 64504, 64502, 64667, 64736, + 64664, 64513, 64663, 64512, 64665, 64614, 64666, 64514, 64735, 64615, + 64499, 64498, 64495, 64494, 64617, 64516, 64501, 64500, 64613, 64612, + 64497, 64496, 64942, 64731, 64598, 64734, 64753, 64660, 64658, 64943, + 64730, 64597, 64732, 64599, 64925, 64924, 64944, 64659, 64733, 64600, + 64752, 64657, 64662, 64602, 64506, 64507, 64505, 64697, 64552, 64827, + 2204, 1619, 1624, 2303, 126492, 126494, 126493, 126495, 126644, 126638, + 126641, 126647, 126648, 126646, 126632, 126645, 126630, 126650, 126626, + 126636, 126631, 126625, 126640, 126643, 126633, 126651, 126637, 126635, + 126649, 126627, 126642, 126639, 126629, 126489, 126467, 126518, 126517, + 126516, 126510, 126513, 126503, 126500, 126519, 126506, 126498, 126508, + 126497, 126512, 126505, 126523, 126509, 126507, 126514, 126511, 126521, + 126612, 126606, 126609, 126615, 126592, 126607, 126599, 126596, 126616, + 126614, 126600, 126613, 126598, 126618, 126594, 126604, 126593, 126608, + 126611, 126601, 126619, 126605, 126603, 126617, 126595, 126610, 126597, + 126475, 126704, 126705, 126588, 126590, 126585, 126582, 126568, 126581, + 126580, 126574, 126577, 126567, 126564, 126583, 126570, 126562, 126572, + 126586, 126561, 126576, 126569, 126587, 126573, 126578, 126575, 126484, + 126478, 126481, 126557, 126559, 126553, 126548, 126542, 126545, 126551, + 126530, 126535, 126537, 126555, 126541, 126539, 126546, 126543, 126472, + 126488, 126486, 126485, 126464, 126479, 126487, 126474, 126470, 126490, + 126466, 126476, 126471, 126465, 126480, 126483, 126473, 126491, 126477, + 126482, 126469, 1541, 1536, 2290, 2289, 2288, 1550, 2192, 1769, 2193, + 1642, 2184, 1544, 1629, 2296, 2301, 2298, 1772, 2183, 1623, 983633, + 983635, 983640, 983634, 983638, 983636, 983639, 983637, 983641, 1563, + 1617, 65148, 65149, 1554, 1555, 1552, 1537, 1539, 1540, 1790, 1789, 1553, + 1551, 1556, 2249, 1560, 1761, 2250, 2272, 1558, 983202, 1751, 1750, 1753, + 1752, 1762, 1764, 1768, 2264, 2273, 1756, 2261, 1755, 1557, 2200, 2260, + 2266, 2268, 2267, 2269, 2252, 2271, 2270, 2291, 1767, 2251, 1760, 1759, + 1559, 2253, 1754, 2263, 2262, 2265, 2202, 2201, 69375, 2203, 69373, + 69374, 2259, 1773, 1763, 1562, 1561, 1766, 1765, 1622, 1618, 65150, + 65151, 2256, 2205, 64444, 64435, 64434, 64441, 64440, 64439, 64438, + 64446, 64445, 64437, 64436, 64449, 64448, 64443, 64442, 64450, 64447, + 1758, 1600, 2179, 2180, 65137, 2181, 65139, 2285, 2282, 2286, 2283, 2287, + 2284, 1566, 2275, 1644, 1627, 1626, 1628, 2190, 1631, 1567, 1625, 1545, + 1546, 1542, 1543, 1637, 1636, 1639, 1638, 1635, 1634, 1632, 1641, 1633, + 1640, 1375, 1370, 1359, 1337, 1349, 1362, 1347, 1353, 1342, 1361, 1360, + 1356, 1333, 1335, 1336, 1346, 1331, 1355, 1345, 1364, 1343, 1363, 1354, + 1351, 1357, 1329, 1358, 1352, 1340, 1366, 1341, 1339, 1330, 1348, 1350, + 1338, 1334, 1344, 1332, 1365, 1373, 1371, 1372, 1395, 1401, 1390, 1409, + 1408, 1404, 1381, 1383, 1384, 1394, 1379, 1403, 1393, 1412, 1391, 1411, + 1402, 1399, 1405, 1376, 1407, 1385, 1377, 1406, 1400, 1397, 1416, 1410, + 1388, 1414, 1389, 1387, 1378, 1396, 1398, 1386, 1382, 1392, 1380, 1413, + 1415, 64279, 64277, 64275, 64276, 64278, 1369, 1418, 1423, 1417, 1374, + 129201, 10549, 10548, 129200, 10550, 10551, 129968, 128667, 127912, 9800, + 8978, 9738, 65948, 42, 8727, 8258, 128562, 11225, 9954, 8771, 8870, + 128095, 9883, 128663, 127975, 128762, 8371, 127814, 68352, 68353, 68357, + 68355, 68358, 68359, 68356, 68354, 68373, 68374, 68372, 68393, 68405, + 68388, 68387, 68386, 68391, 68390, 68389, 68371, 68370, 68369, 68403, + 68401, 68404, 68399, 68394, 68395, 68378, 68381, 68377, 68366, 68367, + 68362, 68363, 68364, 68365, 68385, 68384, 68380, 68379, 68402, 68400, + 68360, 68361, 68375, 68383, 68376, 68368, 68398, 68392, 68382, 68397, + 68396, 68409, 129361, 1547, 129518, 8525, 9810, 129683, 128118, 128036, + 127868, 128124, 128700, 128281, 128386, 11101, 11099, 983056, 10155, + 128043, 129363, 127992, 129441, 129366, 129391, 128708, 7005, 7007, 7006, + 6917, 6918, 6987, 6988, 6928, 6953, 6954, 6936, 6937, 6948, 6944, 6943, + 6949, 6984, 6927, 6933, 6934, 6919, 6920, 6929, 6930, 6921, 6922, 6938, + 6939, 6931, 6981, 6932, 6982, 6958, 6925, 6926, 6950, 6945, 6935, 6940, + 6951, 6952, 6957, 6923, 6924, 6962, 6960, 6961, 6946, 6942, 6941, 6947, + 6983, 6985, 6986, 6963, 6955, 6959, 6956, 7022, 7025, 7021, 7024, 7023, + 7026, 7020, 7019, 7027, 7012, 7013, 7018, 7015, 7017, 7016, 7010, 7014, + 7009, 7011, 7032, 7036, 7033, 7034, 7035, 7031, 7030, 7029, 7028, 7003, + 7038, 7008, 7002, 7037, 6915, 6913, 6912, 6916, 6914, 6964, 6972, 6973, + 6970, 6971, 6968, 6969, 6974, 6975, 6977, 6976, 6965, 6978, 6979, 6966, + 6967, 6980, 7004, 6997, 6996, 6999, 6998, 6995, 6994, 6992, 7001, 6993, + 7000, 127880, 10057, 9744, 128503, 128505, 128499, 128501, 11197, 9745, + 9746, 128502, 128500, 10007, 129526, 129648, 42737, 42736, 42741, 42740, + 42733, 42699, 42713, 42712, 42692, 42706, 42683, 42719, 42734, 42735, + 42682, 42729, 42657, 42725, 42659, 42670, 42718, 42666, 42716, 42701, + 42675, 42671, 42722, 42720, 42727, 42723, 42702, 42726, 42677, 42707, + 42708, 42709, 42686, 42694, 42674, 42731, 42695, 42685, 42684, 42691, + 42673, 42664, 42715, 42703, 92193, 92188, 92161, 92199, 92240, 92179, + 92211, 92219, 92213, 92243, 92207, 92216, 92183, 92184, 92238, 92171, + 92174, 92203, 92186, 92210, 92230, 92175, 92221, 92232, 92246, 92198, + 92214, 92190, 92176, 92197, 92196, 92164, 92245, 92212, 92201, 92160, + 92182, 92173, 92229, 92227, 92180, 92237, 92241, 92223, 92185, 92194, + 92178, 92239, 92225, 92233, 92167, 92191, 92231, 92244, 92204, 92226, + 92236, 92200, 92189, 92187, 92162, 92163, 92169, 92170, 92202, 92205, + 92222, 92168, 92165, 92215, 92224, 92208, 92220, 92235, 92177, 92181, + 92195, 92234, 92209, 92166, 92172, 92206, 92192, 92228, 92217, 92242, + 92218, 92262, 92271, 92272, 92270, 92294, 92253, 92301, 92256, 92273, + 92259, 92251, 92297, 92300, 92296, 92295, 92255, 92252, 92292, 92286, + 92268, 92290, 92281, 92267, 92284, 92287, 92282, 92283, 92277, 92298, + 92276, 92302, 92247, 92299, 92288, 92269, 92260, 92261, 92257, 92274, + 92289, 92263, 92279, 92265, 92266, 92250, 92249, 92285, 92248, 92264, + 92280, 92258, 92254, 92278, 92291, 92293, 92275, 92310, 92320, 92312, + 92394, 92393, 92319, 92384, 92321, 92386, 92361, 92373, 92366, 92328, + 92329, 92357, 92342, 92397, 92365, 92376, 92339, 92382, 92363, 92318, + 92387, 92383, 92315, 92385, 92354, 92311, 92381, 92343, 92326, 92364, + 92324, 92391, 92344, 92390, 92338, 92396, 92308, 92349, 92375, 92378, + 92317, 92331, 92362, 92336, 92341, 92370, 92347, 92307, 92303, 92309, + 92395, 92368, 92356, 92367, 92360, 92389, 92333, 92359, 92374, 92351, + 92325, 92371, 92350, 92345, 92372, 92314, 92340, 92323, 92304, 92313, + 92316, 92398, 92399, 92380, 92330, 92379, 92392, 92335, 92332, 92346, + 92400, 92358, 92334, 92353, 92337, 92306, 92369, 92388, 92322, 92305, + 92327, 92377, 92352, 92348, 92355, 92436, 92517, 92488, 92434, 92415, + 92431, 92454, 92460, 92420, 92489, 92422, 92474, 92479, 92449, 92502, + 92439, 92484, 92495, 92464, 92511, 92406, 92446, 92497, 92426, 92482, + 92448, 92515, 92401, 92478, 92427, 92496, 92458, 92424, 92445, 92404, + 92466, 92444, 92438, 92442, 92441, 92510, 92499, 92425, 92437, 92440, + 92471, 92465, 92409, 92483, 92475, 92467, 92485, 92457, 92432, 92476, + 92435, 92412, 92414, 92430, 92407, 92403, 92405, 92487, 92418, 92486, + 92408, 92447, 92459, 92480, 92472, 92505, 92514, 92450, 92463, 92410, + 92493, 92507, 92503, 92462, 92506, 92443, 92509, 92469, 92461, 92490, + 92512, 92494, 92455, 92417, 92501, 92413, 92508, 92500, 92504, 92473, + 92419, 92498, 92423, 92516, 92428, 92452, 92451, 92481, 92416, 92456, + 92433, 92477, 92492, 92491, 92513, 92411, 92402, 92421, 92453, 92468, + 92470, 92429, 92661, 92626, 92616, 92596, 92612, 92603, 92673, 92651, + 92627, 92597, 92585, 92578, 92615, 92565, 92552, 92602, 92674, 92570, + 92646, 92599, 92532, 92587, 92538, 92620, 92670, 92665, 92575, 92521, + 92633, 92595, 92523, 92556, 92539, 92664, 92653, 92667, 92600, 92542, + 92555, 92668, 92520, 92582, 92591, 92581, 92551, 92654, 92611, 92614, + 92666, 92671, 92617, 92637, 92562, 92518, 92592, 92558, 92528, 92607, + 92535, 92557, 92563, 92550, 92624, 92640, 92657, 92531, 92601, 92553, + 92543, 92619, 92598, 92541, 92544, 92579, 92658, 92554, 92628, 92648, + 92547, 92527, 92545, 92540, 92604, 92622, 92589, 92608, 92583, 92609, + 92662, 92613, 92584, 92625, 92634, 92524, 92536, 92605, 92647, 92548, + 92663, 92593, 92621, 92568, 92610, 92576, 92529, 92618, 92649, 92561, + 92656, 92526, 92655, 92546, 92534, 92560, 92580, 92659, 92660, 92638, + 92571, 92525, 92549, 92559, 92635, 92577, 92530, 92636, 92669, 92572, + 92672, 92537, 92519, 92630, 92586, 92569, 92566, 92573, 92652, 92522, + 92574, 92650, 92533, 92567, 92623, 92606, 92639, 92564, 92590, 92642, + 92643, 92594, 92641, 92645, 92644, 92588, 92629, 92632, 92631, 92710, + 92695, 92694, 92726, 92675, 92719, 92677, 92718, 92682, 92717, 92689, + 92720, 92724, 92685, 92722, 92723, 92711, 92712, 92698, 92688, 92697, + 92696, 92702, 92687, 92704, 92681, 92708, 92703, 92706, 92714, 92709, + 92679, 92721, 92684, 92683, 92707, 92691, 92713, 92700, 92693, 92727, + 92690, 92692, 92686, 92680, 92725, 92699, 92701, 92705, 92716, 92728, + 92678, 92715, 92676, 42693, 42698, 42711, 42696, 42667, 42717, 42704, + 42661, 42721, 42669, 42668, 42705, 42700, 42680, 42678, 42710, 42688, + 42681, 42732, 42676, 42679, 42730, 42728, 42672, 42662, 42724, 42687, + 42689, 42690, 42697, 42714, 42660, 42656, 42665, 42663, 42658, 42738, + 42742, 42739, 42743, 127974, 128183, 128180, 128182, 128181, 127820, + 129685, 128202, 129532, 128136, 129530, 127936, 92916, 92912, 92915, + 92913, 92914, 92887, 92894, 92908, 92880, 92907, 92893, 92886, 92888, + 92881, 92906, 92896, 92891, 92902, 92900, 92885, 92890, 92884, 92904, + 92905, 92899, 92889, 92897, 92892, 92895, 92882, 92898, 92883, 92901, + 92903, 92909, 92917, 9918, 129415, 7152, 7153, 7124, 7108, 7114, 7130, + 7139, 7127, 7138, 7133, 7136, 7113, 7111, 7117, 7119, 7107, 7135, 7125, + 7112, 7123, 7129, 7116, 7132, 7105, 7126, 7128, 7110, 7109, 7137, 7121, + 7118, 7106, 7120, 7134, 7122, 7115, 7131, 7104, 7140, 7141, 7154, 7155, + 7167, 7165, 7166, 7164, 7142, 7150, 7151, 7144, 7147, 7149, 7143, 7145, + 7146, 7148, 128704, 128705, 128267, 127900, 127901, 9835, 9836, 129492, + 128059, 127958, 128147, 129451, 129752, 127866, 129714, 983055, 128276, + 129745, 128277, 9086, 128718, 2519, 2557, 2432, 2548, 2552, 2551, 2550, + 2549, 2553, 2454, 2510, 983661, 2453, 2480, 2545, 2544, 2525, 2524, 2556, + 2443, 2528, 2444, 2529, 2527, 2479, 2437, 2438, 2448, 2452, 2466, 2465, + 2471, 2470, 2464, 2463, 2469, 2468, 2441, 2442, 2439, 2440, 2457, 2467, + 2462, 2472, 2486, 2487, 2488, 2477, 2476, 2459, 2458, 2456, 2455, 2461, + 2460, 2475, 2474, 2489, 2482, 2478, 2447, 2451, 2547, 2546, 983651, + 983650, 983652, 2558, 2493, 2434, 2433, 2492, 2509, 2435, 2554, 2494, + 2504, 2508, 2499, 2500, 2530, 2531, 2497, 2498, 2495, 2496, 2503, 2507, + 2539, 2538, 2541, 2540, 2537, 2536, 2534, 2543, 2535, 2542, 2555, 11102, + 127857, 9004, 9187, 8812, 8502, 8757, 129475, 128719, 72710, 72711, + 72712, 72746, 72704, 72705, 72715, 72717, 72731, 72730, 72736, 72735, + 72729, 72728, 72734, 72733, 72708, 72709, 72706, 72707, 72722, 72732, + 72727, 72737, 72747, 72748, 72749, 72741, 72740, 72724, 72723, 72721, + 72720, 72726, 72725, 72719, 72718, 72739, 72738, 72750, 72745, 72742, + 72744, 72743, 72714, 72716, 72801, 72810, 72806, 72797, 72807, 72798, + 72802, 72811, 72800, 72809, 72799, 72808, 72796, 72805, 72804, 72795, + 72803, 72794, 72768, 72765, 72764, 72767, 72766, 72756, 72757, 72758, + 72751, 72761, 72763, 72754, 72755, 72752, 72753, 72760, 72762, 72770, + 72769, 72789, 72788, 72791, 72790, 72787, 72786, 72784, 72793, 72785, + 72792, 72771, 72772, 72773, 72812, 128692, 128690, 10745, 10744, 129506, + 127921, 127874, 128038, 8383, 129766, 9763, 128089, 129452, 9679, 9864, + 10733, 9865, 9210, 11176, 11177, 11178, 11179, 11180, 11182, 11181, + 11183, 9960, 10028, 9821, 129554, 129596, 129609, 129612, 9818, 129551, + 129593, 9822, 129543, 129564, 129585, 129597, 129606, 129555, 129619, + 129617, 129618, 9823, 129556, 129598, 9819, 129552, 129594, 9820, 129553, + 129595, 129575, 129572, 129576, 129577, 129573, 129574, 9827, 9670, + 11201, 10070, 10730, 11230, 9830, 128419, 128899, 9196, 9662, 9660, + 11167, 127778, 9922, 9923, 10047, 9873, 10022, 128447, 128420, 9829, + 11042, 128426, 11052, 10711, 9194, 9198, 128896, 9668, 9666, 9664, 11164, + 8268, 9944, 128412, 9754, 9699, 9698, 10731, 11044, 11035, 9207, 11206, + 11045, 9204, 11207, 11047, 9205, 11208, 9206, 11205, 128921, 128927, + 9726, 9724, 9912, 128392, 9648, 11039, 127986, 9193, 9197, 9654, 9199, + 128898, 11091, 9658, 9656, 10145, 10148, 11166, 8269, 128413, 9755, + 127990, 9644, 11049, 11050, 11089, 9642, 9787, 9632, 11200, 9209, 128306, + 9728, 128369, 9927, 9984, 128900, 128909, 9986, 9751, 9824, 9733, 128919, + 128925, 128908, 9951, 128383, 9742, 9942, 128418, 128897, 9195, 9652, + 9650, 9700, 9701, 11165, 9851, 11054, 9646, 128920, 128926, 11037, 11204, + 10707, 10002, 10067, 8493, 8460, 8465, 8476, 8488, 10164, 10166, 10165, + 9250, 129792, 129794, 129798, 129806, 129821, 129836, 129813, 129844, + 129829, 129802, 129817, 129848, 129832, 129810, 129840, 129825, 129796, + 129804, 129819, 129850, 129834, 129842, 129827, 129800, 129815, 129846, + 129831, 129808, 129838, 129823, 129793, 129797, 129805, 129820, 129851, + 129835, 129812, 129843, 129828, 129801, 129816, 129847, 129809, 129839, + 129824, 129795, 129803, 129818, 129849, 129833, 129811, 129841, 129826, + 129799, 129814, 129845, 129830, 129807, 129837, 129822, 127804, 128033, + 128216, 128153, 129744, 128939, 128951, 128957, 128945, 128902, 128912, + 128932, 128366, 128278, 128209, 128218, 129667, 12731, 12727, 12726, + 12724, 12725, 12570, 12574, 12718, 12576, 12719, 12578, 12580, 12713, + 12735, 12720, 12584, 12715, 12572, 12579, 12581, 12709, 12708, 12573, + 12575, 12582, 12557, 12728, 12588, 12707, 12732, 12583, 12714, 12723, + 12589, 12716, 12712, 12585, 12555, 12587, 12717, 12591, 12571, 12722, + 12711, 12590, 12734, 12721, 12710, 12577, 12567, 12563, 12705, 12730, + 12558, 12733, 12568, 12564, 12556, 12729, 12569, 12565, 12549, 12704, + 12560, 12706, 12553, 12552, 12559, 12551, 12550, 12561, 12566, 12554, + 12586, 12562, 11211, 11867, 11868, 8993, 9141, 9142, 10555, 9183, 9181, + 8990, 8973, 11812, 8991, 8972, 11813, 9185, 127870, 128144, 127893, + 128335, 129379, 127923, 8904, 10705, 10706, 127993, 9574, 9559, 9556, + 9577, 9565, 9562, 9553, 9580, 9571, 9568, 9552, 9511, 9490, 9503, 9486, + 9537, 9520, 9513, 9489, 9505, 9485, 9543, 9519, 9558, 9555, 9573, 9557, + 9554, 9572, 9592, 9598, 9593, 9599, 9499, 9531, 9495, 9551, 9549, 9595, + 9523, 9491, 9487, 9483, 9481, 9479, 9477, 9475, 9547, 9515, 9507, 9473, + 9594, 9541, 9525, 9517, 9533, 9530, 9522, 9546, 9539, 9582, 9581, 9583, + 9584, 129959, 129964, 129954, 129958, 129965, 129955, 129952, 129956, + 129963, 129960, 129953, 129961, 129957, 129962, 9586, 9585, 9587, 129966, + 9550, 9548, 9591, 9516, 9488, 9484, 9588, 9596, 9482, 9480, 9478, 9476, + 9589, 9597, 9524, 9496, 9492, 9474, 9532, 9508, 9500, 9472, 129967, 9590, + 9542, 9526, 9518, 9534, 9529, 9521, 9545, 9540, 9536, 9510, 9498, 9502, + 9494, 9528, 9544, 9514, 9497, 9506, 9493, 9527, 9564, 9561, 9576, 9563, + 9560, 9575, 9570, 9567, 9579, 9538, 9512, 9504, 9535, 9509, 9501, 9569, + 9566, 9578, 129354, 983263, 128163, 128102, 128713, 128023, 129460, + 69649, 69685, 69749, 69745, 69746, 69687, 69686, 69637, 69638, 69648, + 69650, 69664, 69663, 69669, 69668, 69662, 69661, 69667, 69666, 69643, + 69644, 69645, 69646, 69679, 69641, 69642, 69639, 69640, 69684, 69678, + 69655, 69665, 69660, 69670, 69680, 69681, 69682, 69674, 69673, 69657, + 69656, 69654, 69653, 69659, 69658, 69652, 69651, 69672, 69671, 69683, + 69675, 69677, 69676, 69647, 69721, 69730, 69726, 69717, 69727, 69718, + 69722, 69731, 69720, 69729, 69719, 69728, 69716, 69725, 69724, 69715, + 69723, 69714, 69732, 69733, 69759, 69709, 69707, 69706, 69705, 69708, + 69744, 69632, 69635, 69634, 69636, 69633, 69700, 69747, 69748, 69689, + 69688, 69699, 69701, 69694, 69695, 69696, 69697, 69692, 69693, 69690, + 69691, 69698, 69702, 69704, 69703, 69739, 69738, 69741, 69740, 69737, + 69736, 69734, 69743, 69735, 69742, 10241, 10243, 10247, 10255, 10271, + 10303, 10367, 10495, 10431, 10335, 10463, 10399, 10287, 10351, 10479, + 10415, 10319, 10447, 10383, 10263, 10295, 10359, 10487, 10423, 10327, + 10455, 10391, 10279, 10343, 10471, 10407, 10311, 10439, 10375, 10251, + 10267, 10299, 10363, 10491, 10427, 10331, 10459, 10395, 10283, 10347, + 10475, 10411, 10315, 10443, 10379, 10259, 10291, 10355, 10483, 10419, + 10323, 10451, 10387, 10275, 10339, 10467, 10403, 10307, 10435, 10371, + 10245, 10253, 10269, 10301, 10365, 10493, 10429, 10333, 10461, 10397, + 10285, 10349, 10477, 10413, 10317, 10445, 10381, 10261, 10293, 10357, + 10485, 10421, 10325, 10453, 10389, 10277, 10341, 10469, 10405, 10309, + 10437, 10373, 10249, 10265, 10297, 10361, 10489, 10425, 10329, 10457, + 10393, 10281, 10345, 10473, 10409, 10313, 10441, 10377, 10257, 10289, + 10353, 10481, 10417, 10321, 10449, 10385, 10273, 10337, 10465, 10401, + 10305, 10433, 10369, 10242, 10246, 10254, 10270, 10302, 10366, 10494, + 10430, 10334, 10462, 10398, 10286, 10350, 10478, 10414, 10318, 10446, + 10382, 10262, 10294, 10358, 10486, 10422, 10326, 10454, 10390, 10278, + 10342, 10470, 10406, 10310, 10438, 10374, 10250, 10266, 10298, 10362, + 10490, 10426, 10330, 10458, 10394, 10282, 10346, 10474, 10410, 10314, + 10442, 10378, 10258, 10290, 10354, 10482, 10418, 10322, 10450, 10386, + 10274, 10338, 10466, 10402, 10306, 10434, 10370, 10244, 10252, 10268, + 10300, 10364, 10492, 10428, 10332, 10460, 10396, 10284, 10348, 10476, + 10412, 10316, 10444, 10380, 10260, 10292, 10356, 10484, 10420, 10324, + 10452, 10388, 10276, 10340, 10468, 10404, 10308, 10436, 10372, 10248, + 10264, 10296, 10360, 10488, 10424, 10328, 10456, 10392, 10280, 10344, + 10472, 10408, 10312, 10440, 10376, 10256, 10288, 10352, 10480, 10416, + 10320, 10448, 10384, 10272, 10336, 10464, 10400, 10304, 10432, 10368, + 10240, 129504, 983125, 129329, 127838, 728, 127753, 128112, 128188, + 129650, 129521, 9099, 166, 128148, 129382, 129294, 129529, 129483, + 129767, 128027, 6663, 6662, 6659, 6658, 6671, 6670, 6667, 6666, 6661, + 6668, 6665, 6657, 6678, 6669, 6656, 6674, 6660, 6673, 6676, 6664, 6675, + 6672, 6677, 6683, 6681, 6679, 6682, 6680, 6687, 6686, 5957, 5960, 5962, + 5959, 5956, 5969, 5955, 5966, 5963, 5961, 5965, 5968, 5958, 5967, 5964, + 5952, 5953, 5954, 5970, 5971, 8226, 8729, 128363, 128364, 9678, 128652, + 128101, 128100, 128655, 129480, 129419, 127959, 127791, 129699, 118939, + 118940, 118944, 118943, 118941, 118942, 118938, 118945, 118882, 118876, + 118824, 118835, 118797, 118866, 118957, 118801, 118802, 118865, 118818, + 118916, 118819, 118917, 118899, 118935, 119018, 119022, 119021, 119020, + 119023, 119019, 119017, 118986, 118984, 118985, 118843, 118887, 118808, + 118870, 119003, 119002, 119004, 119005, 118937, 118991, 118995, 118990, + 118992, 118994, 118993, 118930, 118933, 118931, 118932, 119014, 118918, + 118912, 119015, 118785, 118831, 118907, 118966, 118900, 118880, 118798, + 118888, 118884, 118869, 118960, 118959, 118958, 118836, 118969, 118977, + 118978, 118971, 118976, 118975, 118973, 118970, 118987, 118979, 118980, + 118972, 118983, 983272, 118982, 118974, 118988, 118981, 119000, 119001, + 118929, 118928, 118806, 119029, 118927, 118898, 118964, 118965, 118853, + 118968, 118837, 118967, 118936, 118956, 118810, 118854, 118847, 118839, + 118906, 118791, 118800, 119024, 119026, 118862, 118812, 119025, 119027, + 118863, 118811, 118820, 119028, 118911, 118842, 118850, 118921, 118858, + 118913, 118914, 118915, 118834, 118860, 118868, 118796, 118881, 118922, + 118926, 118925, 118924, 118923, 118830, 118877, 118949, 118947, 118948, + 118963, 118955, 118962, 118946, 118961, 118953, 118952, 118951, 118950, + 118954, 118871, 118805, 118855, 118828, 118901, 118787, 118788, 118856, + 118816, 118875, 118845, 118879, 118793, 118846, 118878, 118814, 118822, + 118873, 118859, 118857, 118849, 118840, 118861, 118786, 118895, 118841, + 118874, 118892, 118897, 118807, 118784, 118821, 118844, 118825, 118889, + 119010, 119012, 119013, 119011, 119006, 119008, 119009, 119007, 118910, + 118815, 118852, 119016, 118826, 118885, 118827, 118803, 118886, 118792, + 118813, 118920, 118799, 118833, 118829, 118904, 118902, 118903, 118905, + 118804, 118934, 118919, 118832, 118893, 118838, 118851, 118883, 118894, + 118891, 118896, 118823, 118789, 118790, 118872, 118817, 118809, 118908, + 118909, 118996, 118998, 118997, 118999, 118989, 118794, 118795, 118867, + 118864, 118848, 118890, 983262, 983126, 983057, 9764, 8454, 129305, + 128197, 128247, 128248, 127957, 983098, 5130, 5131, 5122, 6322, 5148, + 5551, 5310, 5382, 5166, 6321, 5759, 5559, 5556, 5557, 5558, 5567, 5564, + 5565, 5566, 5563, 5560, 5561, 5562, 5555, 5552, 5553, 5554, 5384, 5439, + 6387, 6388, 5281, 5264, 6382, 6389, 5203, 5674, 5675, 5677, 5676, 5673, + 5672, 5706, 5707, 5709, 5708, 5705, 5704, 5204, 5574, 5575, 5577, 5576, + 5573, 5572, 6384, 6381, 5620, 6383, 5617, 5618, 5619, 5616, 5615, 5195, + 5592, 5593, 5595, 5594, 5591, 5590, 5174, 5175, 5129, 5703, 5662, 5663, + 5665, 5664, 5661, 5660, 5655, 5656, 6386, 5659, 5657, 5654, 5652, 5633, + 5629, 5630, 5632, 5631, 5628, 5627, 5623, 5624, 5626, 5625, 5622, 5621, + 5636, 5637, 5639, 5329, 5638, 5635, 5634, 5722, 5718, 5719, 5721, 5720, + 5717, 5716, 5712, 5713, 5715, 5714, 5711, 5710, 5614, 5610, 5611, 5613, + 5612, 5609, 5608, 5702, 5698, 5699, 5701, 5700, 5697, 5696, 5686, 5687, + 5689, 5688, 5685, 5684, 5692, 5693, 5695, 5694, 5691, 5690, 5737, 5738, + 5740, 5739, 5736, 5735, 5604, 5605, 5607, 5606, 5603, 5602, 5598, 5599, + 5601, 5600, 5597, 5596, 5725, 5726, 5728, 5727, 5724, 5723, 5680, 5681, + 5683, 5682, 5679, 5678, 5668, 5669, 5671, 5670, 5667, 5666, 5731, 5732, + 5734, 5733, 5730, 5729, 5642, 5643, 5645, 5644, 5641, 5640, 5580, 5581, + 5583, 5582, 5579, 5578, 5586, 5587, 5589, 5588, 5585, 5584, 5648, 5649, + 5651, 5650, 5647, 5646, 5128, 5265, 5258, 5276, 5278, 5272, 5274, 5268, + 5270, 5266, 5741, 5261, 5262, 5259, 5260, 5257, 5121, 6364, 5163, 5469, + 5465, 5466, 5460, 5461, 5158, 5157, 5162, 5155, 5156, 6367, 6366, 5160, + 5152, 5151, 5153, 5154, 5161, 5159, 5462, 5742, 5463, 5464, 5467, 5459, + 5120, 5501, 5123, 5124, 5164, 5251, 5252, 5246, 5248, 6329, 5242, 5244, + 5238, 5240, 5236, 5234, 5235, 5228, 6328, 5231, 5232, 5229, 5230, 5227, + 5354, 5542, 5540, 5541, 5538, 5539, 5536, 5537, 5338, 5339, 5332, 6333, + 5350, 5352, 5346, 5348, 5342, 5344, 5340, 5335, 5336, 5333, 5334, 5331, + 5307, 5283, 5356, 5458, 5287, 5288, 5385, 5290, 5291, 5284, 6330, 5302, + 5304, 5298, 5300, 5294, 5296, 5292, 5285, 5286, 5309, 5328, 5473, 5475, + 5471, 5319, 5386, 5390, 5391, 5388, 5389, 5380, 5387, 5142, 5147, 5280, + 5250, 5306, 5327, 5221, 5437, 72372, 72373, 72370, 72371, 72368, 72369, + 72378, 72379, 72376, 72377, 72374, 72375, 5320, 5313, 6332, 5525, 5523, + 5524, 5518, 5744, 5521, 5522, 5519, 5520, 5526, 5749, 5750, 5747, 5748, + 5745, 5746, 5499, 5497, 5498, 5495, 5496, 5493, 5494, 5492, 5500, 5316, + 5317, 6331, 5323, 5325, 6346, 6348, 6342, 6344, 5321, 5314, 5315, 5312, + 5330, 5509, 5507, 5508, 5502, 5743, 5505, 5506, 5503, 5504, 5125, 6361, + 6347, 6349, 6343, 6345, 6362, 6363, 6359, 6358, 6360, 6356, 6357, 5165, + 5126, 6320, 5193, 5184, 5186, 6326, 5188, 5190, 5180, 5182, 5178, 5176, + 5177, 5168, 6325, 5171, 5172, 6324, 5169, 5170, 5167, 5456, 6368, 5443, + 6355, 5454, 6353, 6354, 6351, 6352, 6350, 5451, 5452, 5445, 6341, 5448, + 5449, 5446, 5447, 5442, 5381, 5364, 6335, 5570, 6380, 5571, 5568, 5569, + 5653, 6385, 5658, 5529, 6379, 6378, 5530, 5527, 5528, 5441, 5282, 5311, + 5365, 5358, 5413, 5405, 5407, 6338, 5409, 5411, 5401, 5403, 5399, 5395, + 5396, 6336, 5397, 5398, 6337, 5393, 5394, 5392, 5361, 5256, 5253, 5254, + 5255, 5362, 6334, 5383, 5376, 5378, 5372, 5374, 5368, 5370, 5366, 72383, + 72380, 72381, 72382, 5359, 5360, 5357, 5222, 5482, 5550, 5548, 5549, + 5546, 5547, 5544, 5545, 5543, 6372, 5480, 6371, 5478, 5479, 5476, 5477, + 5472, 5474, 5470, 5512, 6377, 6376, 5513, 5510, 5511, 5487, 5486, 6375, + 5485, 6374, 6373, 5483, 5484, 5226, 5223, 5224, 5225, 5205, 5206, 5197, + 6327, 5217, 5219, 5213, 5215, 5209, 5211, 5207, 5491, 5488, 5489, 5490, + 5200, 5201, 5198, 5199, 5196, 5132, 5355, 5351, 5353, 5347, 5349, 5343, + 5345, 5341, 5453, 6370, 5450, 6369, 5444, 5308, 5303, 5305, 5299, 5301, + 5295, 5297, 5293, 5194, 5189, 5191, 5185, 5187, 5181, 5183, 5179, 5440, + 5434, 5436, 5430, 5432, 5426, 5428, 5424, 5324, 5326, 5322, 5457, 5455, + 5517, 5514, 5515, 5516, 5410, 5412, 5406, 5408, 5402, 5404, 5400, 5377, + 5379, 5373, 5375, 5369, 5371, 5367, 5277, 5279, 5273, 5275, 5269, 5271, + 5267, 5247, 5249, 5243, 5245, 5239, 5241, 5237, 5481, 5218, 5220, 5214, + 5216, 5210, 5212, 5208, 5468, 5144, 5146, 5139, 5141, 5135, 5137, 5133, + 6365, 5138, 5140, 5535, 5756, 5757, 5754, 5755, 5752, 5753, 5751, 5534, + 5531, 5532, 5533, 5758, 5143, 5145, 6323, 5134, 5136, 5438, 5192, 5173, + 5263, 5233, 5337, 5289, 5318, 5363, 5202, 5420, 5127, 5149, 5421, 5422, + 5415, 6340, 5418, 5419, 6339, 5433, 5435, 5429, 5431, 5425, 5427, 5423, + 5416, 5417, 5414, 5150, 983097, 983171, 917631, 128473, 9803, 128367, + 127852, 129387, 128758, 11839, 9809, 128199, 128450, 128451, 8248, 8257, + 8453, 66225, 66246, 66211, 66214, 66254, 66218, 66250, 66251, 66252, + 66253, 66229, 66238, 66244, 66227, 66224, 66222, 66223, 66242, 66243, + 66232, 66221, 66247, 66230, 66226, 66239, 66212, 66248, 66256, 66235, + 66208, 66215, 66210, 66220, 66234, 66255, 66240, 66241, 66236, 66237, + 66231, 66209, 66213, 66249, 66233, 66245, 66217, 66219, 66216, 66228, + 127904, 711, 127887, 129690, 983073, 129365, 9936, 128008, 128049, + 128569, 128572, 66888, 66864, 66912, 66882, 66873, 66902, 66889, 66890, + 66911, 66891, 66895, 66901, 66881, 66867, 66870, 66868, 66904, 66866, + 66876, 66910, 66879, 66883, 66897, 66915, 66884, 66878, 66885, 66914, + 66903, 66877, 66896, 66909, 66906, 66908, 66899, 66872, 66913, 66874, + 66871, 66875, 66869, 66893, 66887, 66892, 66907, 66900, 66894, 66905, + 66880, 66898, 66865, 66886, 66927, 9761, 127797, 9963, 8373, 184, 65102, + 65098, 8452, 162, 128328, 9907, 9939, 129681, 69908, 69907, 69913, 69912, + 69899, 69909, 69904, 69914, 69906, 69905, 69911, 69910, 69920, 69921, + 69918, 69917, 69901, 69900, 69898, 69897, 69903, 69902, 69896, 69895, + 69956, 69923, 69916, 69915, 69926, 69919, 69922, 69925, 69959, 69924, + 69891, 69894, 69892, 69893, 69888, 69890, 69889, 69952, 69927, 69957, + 69933, 69935, 69930, 69931, 69932, 69958, 69928, 69929, 69934, 69936, + 69939, 69954, 69953, 69947, 69946, 69949, 69948, 69945, 69944, 69942, + 69951, 69943, 69950, 69955, 69940, 69938, 69937, 43587, 43597, 43596, + 43573, 43572, 43574, 43571, 43590, 43586, 43595, 43588, 43585, 43584, + 43594, 43591, 43593, 43589, 43592, 43530, 43531, 43536, 43538, 43537, + 43543, 43544, 43551, 43552, 43548, 43547, 43546, 43553, 43550, 43549, + 43545, 43542, 43541, 43558, 43559, 43520, 43524, 43533, 43532, 43529, + 43528, 43535, 43534, 43527, 43526, 43540, 43539, 43560, 43556, 43555, + 43557, 43554, 43523, 43521, 43525, 43522, 43612, 43614, 43613, 43615, + 43561, 43568, 43569, 43562, 43563, 43567, 43566, 43565, 43570, 43564, + 43605, 43604, 43607, 43606, 43603, 43602, 43600, 43609, 43601, 43608, + 983058, 983140, 983137, 8256, 128200, 128185, 128201, 128638, 129941, + 10003, 129472, 128227, 5084, 5075, 5077, 5079, 5081, 5082, 5083, 5055, + 5037, 5038, 5039, 5040, 5041, 5042, 5054, 5056, 5057, 5058, 5059, 5060, + 5061, 5069, 5068, 5070, 5071, 5072, 5073, 5074, 5085, 5086, 5087, 5088, + 5089, 5090, 5091, 5092, 5093, 5094, 5095, 5096, 5076, 5078, 5080, 5030, + 5032, 5033, 5034, 5035, 5036, 5043, 5044, 5045, 5046, 5047, 5048, 5049, + 5050, 5051, 5052, 5053, 5109, 5062, 5063, 5064, 5065, 5066, 5067, 5097, + 5098, 5099, 5100, 5101, 5102, 5103, 5104, 5105, 5106, 5107, 5108, 5031, + 5024, 5025, 5026, 5027, 5028, 5029, 43948, 43939, 43941, 43943, 43945, + 43946, 43947, 43919, 43901, 43902, 43903, 43904, 43905, 43906, 43918, + 43920, 43921, 43922, 43923, 43924, 43925, 43933, 43932, 43934, 43935, + 43936, 43937, 43938, 43949, 43950, 43951, 43952, 43953, 43954, 43955, + 43956, 43957, 43958, 43959, 43960, 43940, 43942, 43944, 43894, 43896, + 43897, 43898, 43899, 43900, 43907, 43908, 43909, 43910, 43911, 43912, + 43913, 43914, 43915, 43916, 43917, 5117, 43926, 43927, 43928, 43929, + 43930, 43931, 43961, 43962, 43963, 43964, 43965, 43966, 43967, 5112, + 5113, 5114, 5115, 5116, 43895, 43888, 43889, 43890, 43891, 43892, 43893, + 127800, 127826, 127792, 127937, 129490, 128696, 9767, 128063, 128020, + 9911, 69559, 69553, 69567, 69571, 69556, 69564, 69570, 69552, 69568, + 69555, 69560, 69562, 69557, 69561, 69563, 69554, 69566, 69572, 69558, + 69569, 69565, 69578, 69574, 69575, 69577, 69573, 69579, 69576, 129378, + 127851, 127876, 9962, 127910, 9680, 9682, 10690, 10683, 10691, 9684, + 9683, 9685, 9677, 9681, 10677, 10682, 10684, 127246, 8859, 11199, 10687, + 129282, 129280, 129281, 128320, 9938, 127342, 127341, 127277, 8856, + 10808, 9316, 9315, 9318, 9317, 9314, 9313, 9450, 9320, 9312, 9319, + 127247, 8857, 8861, 12905, 12919, 12904, 12918, 12903, 12917, 12926, + 12909, 12923, 12906, 12920, 12896, 12910, 12900, 12914, 12897, 12911, + 12908, 12922, 12901, 12915, 12899, 12913, 12902, 12916, 12907, 12921, + 12898, 12912, 9097, 10162, 127343, 12975, 127569, 12959, 127568, 12963, + 12951, 12962, 12965, 12973, 12943, 12957, 12935, 12950, 12939, 12932, + 12955, 12931, 12964, 12946, 12869, 12871, 12952, 12966, 12967, 12969, + 12942, 12954, 12938, 12976, 12936, 12948, 12868, 12974, 12961, 12970, + 12968, 12953, 12934, 12972, 12956, 12944, 12870, 12947, 12949, 12971, + 12945, 12933, 12930, 12937, 12929, 12941, 12940, 12960, 12958, 12928, + 127275, 127276, 128712, 13033, 13036, 13034, 13037, 13035, 13013, 13016, + 13014, 13017, 13015, 13038, 13041, 13039, 13042, 13040, 13028, 13031, + 13029, 13032, 13030, 13046, 13049, 13047, 13050, 13048, 13018, 13021, + 13019, 13022, 13020, 13023, 13026, 13024, 13027, 13025, 13051, 13053, + 13052, 13054, 13043, 13045, 13044, 13008, 13011, 13009, 13012, 13010, + 12925, 12924, 9398, 9399, 9400, 9401, 9402, 9403, 9404, 9405, 9406, 9407, + 9408, 9409, 9410, 9411, 9412, 9413, 9414, 9415, 9416, 9417, 9418, 9419, + 9420, 9421, 9422, 9423, 9424, 9425, 9426, 9427, 9428, 9429, 9430, 9431, + 9432, 9433, 9434, 9435, 9436, 9437, 9438, 9439, 9440, 9441, 9442, 9443, + 9444, 9445, 9446, 9447, 9448, 9449, 10688, 10806, 8854, 12879, 9329, + 9322, 12991, 12876, 9326, 12981, 12875, 12982, 12986, 12985, 12988, + 12987, 12984, 12983, 12990, 12989, 9325, 12878, 9328, 12877, 9327, 9321, + 12872, 12890, 12874, 12891, 12895, 12894, 12978, 12977, 12893, 12892, + 12980, 12979, 9324, 9331, 12873, 12881, 12885, 12884, 12887, 12886, + 12883, 12882, 12889, 12888, 9323, 9330, 10050, 12342, 10679, 10681, 8853, + 8858, 10680, 128981, 9098, 8855, 10686, 10026, 127278, 127245, 8860, + 10678, 10689, 128983, 11198, 94, 10768, 127914, 127961, 127750, 195088, + 195089, 195090, 195091, 195092, 195093, 195094, 195095, 195096, 195097, + 195098, 195099, 195100, 195101, 195072, 195073, 195074, 195075, 195076, + 195077, 195078, 195079, 195080, 195081, 195082, 195083, 195084, 195085, + 195086, 195087, 194560, 194561, 194562, 194563, 194564, 194565, 194566, + 194567, 194568, 194569, 194570, 194571, 194572, 194573, 194574, 194575, + 194576, 194577, 194578, 194579, 194580, 194581, 194582, 194583, 194584, + 194585, 194586, 194587, 194588, 194589, 194590, 194591, 194592, 194593, + 194594, 194595, 194596, 194597, 194598, 194599, 194600, 194601, 194602, + 194603, 194604, 194605, 194606, 194607, 194608, 194609, 194610, 194611, + 194612, 194613, 194614, 194615, 194616, 194617, 194618, 194619, 194620, + 194621, 194622, 194623, 194624, 194625, 194626, 194627, 194628, 194629, + 194630, 194631, 194632, 194633, 194634, 194635, 194636, 194637, 194638, + 194639, 194640, 194641, 194642, 194643, 194644, 194645, 194646, 194647, + 194648, 194649, 194650, 194651, 194652, 194653, 194654, 194655, 194656, + 194657, 194658, 194659, 194660, 194661, 194662, 194663, 194664, 194665, + 194666, 194667, 194668, 194669, 194670, 194671, 194672, 194673, 194674, + 194675, 194676, 194677, 194678, 194679, 194680, 194681, 194682, 194683, + 194684, 194685, 194686, 194687, 194688, 194689, 194690, 194691, 194692, + 194693, 194694, 194695, 194696, 194697, 194698, 194699, 194700, 194701, + 194702, 194703, 194704, 194705, 194706, 194707, 194708, 194709, 194710, + 194711, 194712, 194713, 194714, 194715, 194716, 194717, 194718, 194719, + 194720, 194721, 194722, 194723, 194724, 194725, 194726, 194727, 194728, + 194729, 194730, 194731, 194732, 194733, 194734, 194735, 194736, 194737, + 194738, 194739, 194740, 194741, 194742, 194743, 194744, 194745, 194746, + 194747, 194748, 194749, 194750, 194751, 194752, 194753, 194754, 194755, + 194756, 194757, 194758, 194759, 194760, 194761, 194762, 194763, 194764, + 194765, 194766, 194767, 194768, 194769, 194770, 194771, 194772, 194773, + 194774, 194775, 194776, 194777, 194778, 194779, 194780, 194781, 194782, + 194783, 194784, 194785, 194786, 194787, 194788, 194789, 194790, 194791, + 194792, 194793, 194794, 194795, 194796, 194797, 194798, 194799, 194800, + 194801, 194802, 194803, 194804, 194805, 194806, 194807, 194808, 194809, + 194810, 194811, 194812, 194813, 194814, 194815, 194816, 194817, 194818, + 194819, 194820, 194821, 194822, 194823, 194824, 194825, 194826, 194827, + 194828, 194829, 194830, 194831, 194832, 194833, 194834, 194835, 194836, + 194837, 194838, 194839, 194840, 194841, 194842, 194843, 194844, 194845, + 194846, 194847, 194848, 194849, 194850, 194851, 194852, 194853, 194854, + 194855, 194856, 194857, 194858, 194859, 194860, 194861, 194862, 194863, + 194864, 194865, 194866, 194867, 194868, 194869, 194870, 194871, 194872, + 194873, 194874, 194875, 194876, 194877, 194878, 194879, 194880, 194881, + 194882, 194883, 194884, 194885, 194886, 194887, 194888, 194889, 194890, + 194891, 194892, 194893, 194894, 194895, 194896, 194897, 194898, 194899, + 194900, 194901, 194902, 194903, 194904, 194905, 194906, 194907, 194908, + 194909, 194910, 194911, 194912, 194913, 194914, 194915, 194916, 194917, + 194918, 194919, 194920, 194921, 194922, 194923, 194924, 194925, 194926, + 194927, 194928, 194929, 194930, 194931, 194932, 194933, 194934, 194935, + 194936, 194937, 194938, 194939, 194940, 194941, 194942, 194943, 194944, + 194945, 194946, 194947, 194948, 194949, 194950, 194951, 194952, 194953, + 194954, 194955, 194956, 194957, 194958, 194959, 194960, 194961, 194962, + 194963, 194964, 194965, 194966, 194967, 194968, 194969, 194970, 194971, + 194972, 194973, 194974, 194975, 194976, 194977, 194978, 194979, 194980, + 194981, 194982, 194983, 194984, 194985, 194986, 194987, 194988, 194989, + 194990, 194991, 194992, 194993, 194994, 194995, 194996, 194997, 194998, + 194999, 195000, 195001, 195002, 195003, 195004, 195005, 195006, 195007, + 195008, 195009, 195010, 195011, 195012, 195013, 195014, 195015, 195016, + 195017, 195018, 195019, 195020, 195021, 195022, 195023, 195024, 195025, + 195026, 195027, 195028, 195029, 195030, 195031, 195032, 195033, 195034, + 195035, 195036, 195037, 195038, 195039, 195040, 195041, 195042, 195043, + 195044, 195045, 195046, 195047, 195048, 195049, 195050, 195051, 195052, + 195053, 195054, 195055, 195056, 195057, 195058, 195059, 195060, 195061, + 195062, 195063, 195064, 195065, 195066, 195067, 195068, 195069, 195070, + 195071, 64096, 64097, 64098, 64099, 64100, 64101, 64102, 64103, 64104, + 64105, 64106, 64107, 64108, 64109, 64000, 64001, 64002, 64003, 64004, + 64005, 64006, 64007, 64008, 64009, 64010, 64011, 64012, 64013, 64014, + 64015, 64016, 64017, 64018, 64019, 64020, 64021, 64022, 64023, 64024, + 64025, 64026, 64027, 64028, 64029, 64030, 64031, 64032, 64033, 64034, + 64035, 64036, 64037, 64038, 64039, 64040, 64041, 64042, 64043, 64044, + 64045, 64046, 64047, 64048, 64049, 64050, 64051, 64052, 64053, 64054, + 64055, 64056, 64057, 64058, 64059, 64060, 64061, 64062, 64063, 64064, + 64065, 64066, 64067, 64068, 64069, 64070, 64071, 64072, 64073, 64074, + 64075, 64076, 64077, 64078, 64079, 64080, 64081, 64082, 64083, 64084, + 64085, 64086, 64087, 64088, 64089, 64090, 64091, 64092, 64093, 64094, + 64095, 64112, 64113, 64114, 64115, 64116, 64117, 64118, 64119, 64120, + 64121, 64122, 64123, 64124, 64125, 64126, 64127, 64128, 64129, 64130, + 64131, 64132, 64133, 64134, 64135, 64136, 64137, 64138, 64139, 64140, + 64141, 64142, 64143, 64144, 64145, 64146, 64147, 64148, 64149, 64150, + 64151, 64152, 64153, 64154, 64155, 64156, 64157, 64158, 64159, 64160, + 64161, 64162, 64163, 64164, 64165, 64166, 64167, 64168, 64169, 64170, + 64171, 64172, 64173, 64174, 64175, 64176, 64177, 64178, 64179, 64180, + 64181, 64182, 64183, 64184, 64185, 64186, 64187, 64188, 64189, 64190, + 64191, 64192, 64193, 64194, 64195, 64196, 64197, 64198, 64199, 64200, + 64201, 64202, 64203, 64204, 64205, 64206, 64207, 64208, 64209, 64210, + 64211, 64212, 64213, 64214, 64215, 64216, 64217, 63744, 63745, 63746, + 63747, 63748, 63749, 63750, 63751, 63752, 63753, 63754, 63755, 63756, + 63757, 63758, 63759, 63760, 63761, 63762, 63763, 63764, 63765, 63766, + 63767, 63768, 63769, 63770, 63771, 63772, 63773, 63774, 63775, 63776, + 63777, 63778, 63779, 63780, 63781, 63782, 63783, 63784, 63785, 63786, + 63787, 63788, 63789, 63790, 63791, 63792, 63793, 63794, 63795, 63796, + 63797, 63798, 63799, 63800, 63801, 63802, 63803, 63804, 63805, 63806, + 63807, 63808, 63809, 63810, 63811, 63812, 63813, 63814, 63815, 63816, + 63817, 63818, 63819, 63820, 63821, 63822, 63823, 63824, 63825, 63826, + 63827, 63828, 63829, 63830, 63831, 63832, 63833, 63834, 63835, 63836, + 63837, 63838, 63839, 63840, 63841, 63842, 63843, 63844, 63845, 63846, + 63847, 63848, 63849, 63850, 63851, 63852, 63853, 63854, 63855, 63856, + 63857, 63858, 63859, 63860, 63861, 63862, 63863, 63864, 63865, 63866, + 63867, 63868, 63869, 63870, 63871, 63872, 63873, 63874, 63875, 63876, + 63877, 63878, 63879, 63880, 63881, 63882, 63883, 63884, 63885, 63886, + 63887, 63888, 63889, 63890, 63891, 63892, 63893, 63894, 63895, 63896, + 63897, 63898, 63899, 63900, 63901, 63902, 63903, 63904, 63905, 63906, + 63907, 63908, 63909, 63910, 63911, 63912, 63913, 63914, 63915, 63916, + 63917, 63918, 63919, 63920, 63921, 63922, 63923, 63924, 63925, 63926, + 63927, 63928, 63929, 63930, 63931, 63932, 63933, 63934, 63935, 63936, + 63937, 63938, 63939, 63940, 63941, 63942, 63943, 63944, 63945, 63946, + 63947, 63948, 63949, 63950, 63951, 63952, 63953, 63954, 63955, 63956, + 63957, 63958, 63959, 63960, 63961, 63962, 63963, 63964, 63965, 63966, + 63967, 63968, 63969, 63970, 63971, 63972, 63973, 63974, 63975, 63976, + 63977, 63978, 63979, 63980, 63981, 63982, 63983, 63984, 63985, 63986, + 63987, 63988, 63989, 63990, 63991, 63992, 63993, 63994, 63995, 63996, + 63997, 63998, 63999, 11946, 12003, 11910, 11963, 11962, 11950, 11992, + 12012, 12000, 12005, 11996, 12010, 11984, 11988, 11994, 11987, 11952, + 12007, 11977, 11976, 11973, 12019, 11993, 12014, 11995, 12016, 12006, + 12002, 11979, 11936, 11983, 11905, 11970, 11943, 11931, 11914, 11934, + 11944, 11999, 11998, 11997, 11960, 11947, 11939, 11978, 11968, 11967, + 11966, 12004, 11927, 11926, 12001, 11975, 11928, 12018, 12013, 12015, + 12011, 11945, 11986, 11985, 11921, 11920, 11919, 11918, 11964, 11957, + 11990, 11989, 11935, 11965, 11933, 11941, 11940, 11909, 11991, 11959, + 11929, 11904, 11908, 11907, 11906, 11915, 11942, 11974, 11980, 12008, + 12009, 11951, 11925, 11924, 11922, 11949, 11948, 11917, 11916, 11958, + 11932, 12017, 11911, 11923, 11969, 11982, 11981, 11938, 11937, 11972, + 11971, 11956, 11955, 11954, 11953, 11913, 11912, 11961, 12752, 12743, + 12748, 12757, 12741, 12750, 12769, 12747, 12749, 12744, 12742, 12746, + 12768, 12758, 12754, 12763, 12770, 12764, 12753, 12740, 12767, 12760, + 12759, 12745, 12766, 12762, 12755, 12761, 12736, 12765, 12739, 12737, + 12738, 12756, 12751, 12771, 128079, 127916, 127963, 128385, 129346, + 127867, 128203, 128346, 128358, 128343, 128355, 128340, 128352, 128339, + 128351, 128344, 128356, 128336, 128348, 128342, 128354, 128341, 128353, + 128345, 128357, 128347, 128359, 128337, 128349, 128338, 128350, 10561, + 8754, 128259, 10227, 128472, 128257, 128258, 8631, 11118, 8635, 8753, + 10959, 10961, 10960, 10962, 127746, 10828, 10832, 128234, 128235, 128272, + 128213, 10829, 8272, 9729, 127786, 127785, 127784, 127783, 129313, 9114, + 129715, 127864, 129381, 58, 8788, 8353, 128165, 7625, 7623, 769, 791, + 833, 8410, 8404, 8423, 857, 8432, 7677, 844, 774, 7627, 814, 810, 838, + 70459, 780, 812, 784, 8409, 8405, 787, 789, 806, 65062, 65069, 42609, + 1160, 11774, 11744, 11768, 11747, 11757, 11765, 42654, 11751, 11752, + 11753, 11756, 42613, 11775, 11772, 42655, 11767, 11754, 42619, 11763, + 11762, 42618, 42615, 42612, 42617, 11770, 42614, 11771, 11773, 11769, + 11759, 42616, 11760, 11758, 11748, 11749, 11761, 11746, 11764, 11755, + 11745, 11750, 11766, 42621, 1156, 1158, 1159, 1157, 42608, 42610, 1155, + 65070, 65071, 1161, 42620, 123023, 42607, 770, 813, 807, 43248, 43244, + 43245, 43246, 43247, 43242, 43243, 43249, 43237, 43236, 43239, 43238, + 43235, 43234, 43232, 43241, 43233, 43240, 7675, 776, 6833, 804, 775, + 7672, 856, 803, 7674, 7617, 7616, 861, 860, 865, 7676, 862, 863, 6840, + 831, 6858, 6857, 6844, 866, 858, 864, 65058, 65059, 8422, 840, 782, 779, + 783, 819, 7629, 6832, 798, 6835, 8413, 8416, 8418, 8414, 8419, 8420, + 8415, 839, 850, 8412, 122892, 122884, 122891, 122890, 122921, 122919, + 122889, 122916, 122900, 122907, 122910, 122901, 122908, 122880, 122920, + 122881, 122909, 122903, 122922, 122883, 122895, 122894, 122896, 122898, + 122899, 122882, 122885, 122912, 122911, 122913, 122918, 122915, 122888, + 122886, 122904, 122902, 122897, 122893, 70508, 70507, 70506, 70505, + 70504, 70502, 70503, 70515, 70513, 70514, 70516, 70512, 768, 790, 832, + 7624, 7621, 847, 119363, 119362, 119364, 835, 834, 837, 836, 777, 843, + 795, 785, 815, 826, 811, 6855, 6834, 7632, 12442, 12441, 7671, 7670, + 7643, 7646, 7647, 7649, 7650, 867, 7666, 7655, 7636, 7637, 7638, 872, + 7639, 868, 7663, 7641, 7659, 7635, 869, 7640, 6860, 6861, 6862, 7645, + 7660, 7653, 870, 7667, 7661, 871, 7668, 7664, 876, 7651, 7626, 877, 6848, + 7652, 7658, 7656, 7657, 7665, 6847, 873, 7642, 874, 7644, 875, 7648, + 7662, 878, 879, 7654, 852, 7678, 8430, 8406, 841, 794, 6849, 6851, 796, + 849, 8400, 792, 845, 8417, 8429, 8426, 65056, 65063, 65057, 65064, 6841, + 8427, 824, 822, 8402, 818, 772, 65060, 65067, 65061, 65068, 817, 7622, + 7620, 7628, 800, 6854, 842, 66424, 66425, 66423, 66426, 66422, 6839, 808, + 7630, 773, 6846, 6845, 6843, 801, 799, 6856, 8421, 788, 802, 7679, 854, + 848, 853, 8431, 8407, 825, 855, 8401, 6850, 6852, 793, 8428, 8408, 805, + 778, 7631, 859, 823, 821, 8403, 6853, 827, 6842, 7619, 7618, 828, 8411, + 771, 65065, 65066, 820, 816, 6859, 8424, 6836, 786, 846, 797, 7669, 7633, + 7634, 809, 781, 830, 7673, 8425, 6838, 6837, 851, 829, 8274, 64, 44, + 128476, 9092, 8705, 129517, 9732, 127882, 128533, 128534, 128119, 128679, + 8715, 8883, 8885, 8954, 8955, 8957, 8750, 127899, 983187, 9089, 127978, + 9010, 9740, 10861, 127859, 127850, 127834, 11505, 11504, 11503, 11464, + 11392, 11506, 11499, 11501, 11446, 11452, 11458, 11466, 11442, 11448, + 11450, 11398, 1006, 1002, 11396, 1000, 11406, 998, 11436, 11412, 11420, + 996, 11434, 11472, 11414, 11422, 11478, 11468, 11470, 11476, 11474, + 11482, 11460, 11480, 11454, 11462, 11444, 11486, 11488, 11484, 11490, + 11440, 1004, 994, 11456, 11402, 11428, 11408, 11430, 11404, 11394, 11438, + 11424, 11410, 11426, 11400, 11416, 11418, 11432, 66272, 66298, 66289, + 66295, 66286, 66294, 66285, 66299, 66290, 66291, 66297, 66288, 66296, + 66287, 66293, 66284, 66292, 66283, 66282, 66277, 66276, 66279, 66278, + 66275, 66274, 66281, 66273, 66280, 11517, 11518, 11514, 11515, 11516, + 11513, 11465, 11393, 11507, 11500, 11502, 11447, 11453, 11459, 11467, + 11443, 11449, 11451, 11399, 1007, 1003, 11397, 1001, 11407, 999, 11437, + 11413, 11421, 997, 11435, 11473, 11415, 11423, 11479, 11469, 11471, + 11477, 11475, 11483, 11461, 11481, 11455, 11463, 11445, 11487, 11489, + 11485, 11491, 11441, 1005, 995, 11457, 11403, 11429, 11409, 11431, 11405, + 11395, 11439, 11425, 11411, 11427, 11401, 11417, 11419, 11433, 11497, + 11492, 11493, 11494, 11498, 11495, 11496, 11519, 127279, 169, 11855, + 8792, 129720, 9012, 9013, 119661, 119660, 119663, 119662, 119659, 119658, + 119665, 119657, 119664, 119652, 119651, 119654, 119653, 119650, 119649, + 119656, 119648, 119655, 128715, 128145, 128004, 128046, 9904, 129689, + 129509, 983074, 128179, 127769, 129431, 127951, 9769, 9768, 11857, 11856, + 128322, 128321, 10060, 127370, 127884, 9876, 9932, 128010, 129360, + 128081, 8354, 129660, 128575, 128546, 128302, 129408, 8731, 74794, 74771, + 74861, 74780, 74820, 74821, 74765, 74758, 74853, 74856, 74855, 74854, + 74791, 74801, 74844, 74836, 74837, 74809, 74755, 74829, 74777, 74786, + 74768, 74858, 74762, 74834, 74835, 74808, 74812, 74814, 74815, 74813, + 74754, 74828, 74776, 74785, 74790, 74800, 74767, 74857, 74761, 74839, + 74838, 74822, 74825, 74823, 74824, 74795, 74772, 74862, 74781, 74766, + 74759, 74849, 74850, 74840, 74847, 74848, 74851, 74831, 74804, 74773, + 74782, 74845, 74842, 74796, 74852, 74818, 74819, 74817, 74793, 74770, + 74860, 74779, 74764, 74757, 74802, 74803, 74792, 74756, 74830, 74769, + 74859, 74778, 74816, 74763, 74806, 74807, 74833, 74788, 74789, 74798, + 74799, 74810, 74811, 74753, 74827, 74775, 74784, 74760, 74752, 74826, + 74832, 74805, 74841, 74774, 74783, 74787, 74797, 74846, 74843, 74867, + 74868, 74866, 74865, 74864, 73728, 73734, 73731, 73733, 73735, 73736, + 73730, 73732, 73729, 73738, 73742, 73741, 73744, 73745, 74881, 73747, + 73748, 73740, 73739, 74608, 74880, 73746, 73743, 73749, 73750, 73753, + 73752, 73754, 73755, 73751, 74609, 73756, 74882, 73757, 73759, 73758, + 73760, 73765, 73766, 73762, 73763, 73768, 73761, 73767, 73764, 73770, + 73769, 73771, 74610, 73772, 73773, 73776, 73777, 73775, 73774, 73778, + 73780, 73781, 73782, 73784, 73788, 73789, 73787, 73785, 73786, 73791, + 73790, 73783, 73779, 73737, 73792, 73793, 74883, 73795, 74884, 74885, + 74886, 73796, 73797, 73798, 73799, 73800, 73794, 73801, 73804, 73803, + 73802, 73805, 74887, 73806, 73807, 73808, 73809, 73810, 73811, 73812, + 73813, 73814, 73815, 73816, 73817, 73818, 73819, 73820, 73821, 73822, + 73823, 73825, 73826, 73829, 73830, 73831, 73828, 73836, 74611, 73837, + 73833, 73835, 73827, 73832, 73834, 73824, 74889, 74612, 73839, 73840, + 73841, 74888, 73838, 73842, 73844, 74891, 74890, 73845, 73846, 74892, + 73847, 73848, 73849, 74613, 73843, 73850, 73852, 73853, 73851, 73854, + 73855, 74614, 73856, 73857, 74894, 74895, 74893, 74896, 74897, 74900, + 74901, 74902, 74899, 74908, 74909, 74907, 74906, 74911, 74912, 74910, + 74913, 74914, 74915, 74916, 74920, 74919, 74898, 74905, 74903, 74904, + 74917, 74918, 73858, 73860, 73861, 73862, 73863, 73864, 73865, 73859, + 73866, 73868, 73867, 73869, 73873, 73874, 73870, 73871, 74922, 74921, + 73872, 73875, 73879, 73883, 73884, 73880, 73881, 73882, 73885, 73887, + 74923, 73886, 73888, 74924, 73889, 74927, 74930, 74931, 74925, 74928, + 74929, 74932, 74926, 73890, 73891, 73892, 73893, 73895, 73896, 73900, + 73901, 73902, 73903, 73904, 73905, 73906, 74616, 74933, 73907, 73908, + 73899, 73897, 73898, 74615, 73894, 73877, 73876, 73878, 73909, 73911, + 73912, 73914, 73913, 73916, 74617, 73917, 74618, 73918, 73915, 74934, + 73920, 73919, 73921, 73922, 73924, 73925, 74935, 74936, 74937, 73926, + 73923, 73929, 73930, 73927, 73928, 74938, 74939, 73932, 74941, 74940, + 73931, 73933, 73934, 73935, 73936, 73937, 74942, 73938, 73939, 73941, + 73940, 73943, 73942, 73945, 73944, 73946, 73947, 74943, 73948, 73949, + 74944, 74945, 74946, 73950, 74947, 73951, 74948, 74949, 74950, 73952, + 73953, 73957, 73958, 73959, 74951, 73955, 73956, 73960, 73962, 73963, + 73964, 73961, 74952, 73954, 73965, 73966, 74953, 73967, 73968, 73969, + 73970, 73971, 73972, 73974, 73975, 73978, 73977, 73976, 73910, 73979, + 73980, 73981, 73973, 73982, 73983, 74954, 74619, 73984, 73985, 73986, + 73987, 73988, 73990, 73989, 73994, 73995, 73998, 73996, 73997, 73999, + 73992, 73993, 74001, 74955, 74004, 74003, 74005, 74002, 74000, 73991, + 74620, 74006, 74008, 74009, 74010, 74956, 74012, 74011, 74013, 74014, + 74957, 74015, 74016, 74017, 74019, 74020, 74021, 74024, 74023, 74022, + 74007, 74018, 74025, 74026, 74958, 74027, 74028, 74029, 74030, 74959, + 74031, 74033, 74036, 74035, 74032, 74034, 74037, 74038, 74039, 74040, + 74043, 74044, 74042, 74041, 74045, 74046, 74621, 74047, 74050, 74052, + 74051, 74053, 74054, 74058, 74057, 74055, 74056, 74059, 74060, 74061, + 74062, 74064, 74065, 74063, 74066, 74067, 74048, 74070, 74049, 74068, + 74069, 74071, 74072, 74073, 74074, 74622, 74075, 74623, 74077, 74076, + 74078, 74079, 74960, 74080, 74081, 74082, 74085, 74086, 74084, 74083, + 74087, 74624, 74090, 74089, 74088, 74091, 74092, 74625, 74093, 74094, + 74096, 74097, 74961, 74095, 74099, 74627, 74098, 74100, 74101, 74103, + 74102, 74104, 74105, 74115, 74629, 74114, 74112, 74113, 74110, 74111, + 74117, 74116, 74118, 74630, 74119, 74962, 74963, 74631, 74122, 74123, + 74120, 74121, 74626, 74107, 74106, 74628, 74108, 74109, 74124, 74125, + 74126, 74131, 74132, 74128, 74129, 74130, 74133, 74134, 74135, 74136, + 74137, 74138, 74139, 74140, 74141, 74142, 74607, 74127, 74144, 74146, + 74147, 74145, 74152, 74153, 74150, 74151, 74148, 74149, 74154, 74155, + 74157, 74158, 74163, 74164, 74165, 74160, 74161, 74156, 74159, 74162, + 74143, 74166, 74167, 74168, 74169, 74170, 74171, 74172, 74175, 74173, + 74174, 74176, 74177, 74182, 74183, 74180, 74181, 74632, 74186, 74184, + 74185, 74188, 74190, 74189, 74187, 74194, 74195, 74193, 74191, 74192, + 74196, 74197, 74198, 74199, 74200, 74201, 74202, 74205, 74206, 74207, + 74208, 74204, 74209, 74211, 74210, 74212, 74213, 74215, 74214, 74216, + 74218, 74217, 74964, 74178, 74179, 74203, 74219, 74220, 74223, 74224, + 74221, 74222, 74966, 74967, 74974, 74973, 74972, 74969, 74970, 74971, + 74975, 74968, 74965, 74977, 74976, 74980, 74981, 74982, 74984, 74985, + 74978, 74979, 74983, 74986, 74987, 74988, 74989, 74990, 74991, 74993, + 74997, 74996, 74998, 74995, 74994, 74992, 74999, 75000, 75003, 75004, + 75005, 75006, 75001, 75002, 75009, 75015, 75016, 75019, 75017, 75018, + 75013, 75012, 75010, 75011, 75014, 75021, 75030, 75029, 75027, 75024, + 75025, 75028, 75022, 75026, 75023, 75008, 75020, 75031, 75032, 75007, + 74226, 74227, 74228, 74229, 74230, 74225, 74231, 74233, 74234, 74232, + 74235, 74237, 74258, 74259, 75033, 74261, 74633, 74260, 74240, 74634, + 74241, 74243, 75035, 74246, 74247, 74245, 74248, 74249, 74250, 74251, + 75036, 75037, 74254, 74255, 74635, 74256, 75038, 74242, 74252, 74253, + 75034, 74238, 74239, 74244, 74257, 74263, 74265, 74264, 74266, 74269, + 74270, 74271, 74236, 74262, 74267, 74268, 74272, 74273, 74274, 74278, + 74279, 74275, 74276, 74277, 74280, 74281, 74636, 74282, 75039, 74283, + 74284, 74290, 74294, 74295, 75041, 75040, 74292, 74293, 74291, 74296, + 74297, 74298, 74299, 74300, 74637, 74301, 74286, 74287, 74285, 74289, + 74288, 74302, 74304, 74307, 74305, 74306, 74308, 74310, 74309, 74311, + 74303, 74638, 74312, 74314, 74313, 74315, 74316, 74319, 74321, 74320, + 74639, 74322, 74324, 74325, 74323, 74642, 75043, 74326, 75044, 75046, + 75047, 74327, 75048, 74329, 74328, 75049, 74330, 74332, 74333, 74331, + 75050, 75051, 74334, 75052, 74335, 75042, 74641, 75045, 74640, 74317, + 74336, 74318, 74337, 74338, 983266, 983265, 74643, 74339, 74347, 74348, + 74342, 74343, 74341, 74344, 74340, 74346, 74345, 74349, 74355, 74354, + 74350, 74352, 74358, 74359, 74353, 74357, 74351, 74356, 74360, 74361, + 74362, 74363, 74364, 74365, 74366, 74644, 74367, 74375, 74376, 74368, + 74369, 74373, 74374, 74370, 74371, 74372, 74377, 74378, 74379, 74380, + 74381, 74382, 74645, 74383, 74384, 74385, 74386, 74387, 74389, 74408, + 75053, 74388, 74646, 74395, 74394, 75055, 74400, 74399, 75056, 74401, + 74406, 74402, 74403, 74404, 74405, 74391, 74392, 74396, 74398, 75054, + 74397, 74393, 74390, 74407, 74409, 74410, 74411, 74412, 74413, 74414, + 74421, 74422, 74419, 74417, 74420, 74416, 74418, 74415, 74423, 75057, + 74424, 74425, 74426, 75058, 74428, 74429, 75059, 75060, 75061, 74427, + 74432, 74434, 74433, 74430, 74431, 74435, 74437, 74436, 74438, 74441, + 74440, 74444, 74445, 74446, 74448, 74447, 74443, 74449, 74442, 74439, + 74451, 74453, 74452, 74450, 74454, 74455, 74456, 74457, 75063, 75062, + 74458, 74459, 75064, 74460, 74461, 74462, 74463, 74465, 74464, 74466, + 74468, 74469, 74471, 74472, 74473, 74474, 74467, 74470, 74475, 74477, + 74478, 74479, 74476, 74480, 74481, 74482, 74483, 74488, 74486, 74487, + 74485, 74489, 74484, 74490, 75065, 74491, 74494, 74497, 74499, 74500, + 74498, 74495, 74647, 74496, 74501, 74504, 75066, 75067, 74505, 74506, + 74502, 74503, 74492, 74493, 74507, 74510, 74512, 74511, 74649, 74509, + 74508, 74515, 74516, 74522, 74523, 74519, 74520, 74517, 74518, 74521, + 74524, 74534, 74535, 74525, 74526, 74648, 74527, 74528, 74529, 74531, + 74532, 74533, 74530, 74536, 74538, 74537, 74539, 75068, 74540, 74541, + 74542, 74545, 74546, 74547, 75069, 74544, 74543, 74549, 74550, 74551, + 74552, 74553, 75070, 74555, 74556, 74558, 74557, 74559, 74560, 74562, + 74564, 74563, 75072, 74566, 75071, 74570, 74569, 74572, 74574, 74573, + 74554, 74567, 74571, 74565, 74561, 74568, 74575, 74576, 74548, 74577, + 74581, 74579, 74580, 74578, 74584, 74583, 74582, 74586, 74587, 74588, + 74585, 74513, 74514, 74589, 74591, 74590, 74593, 75073, 74592, 74595, + 74598, 74599, 74596, 74601, 74597, 74600, 74602, 75074, 74603, 75075, + 74604, 74605, 74606, 74594, 9982, 129380, 11232, 129473, 8911, 8910, + 10160, 9130, 129356, 128177, 164, 127835, 10081, 127854, 128707, 129362, + 129385, 67594, 67595, 67596, 67597, 67598, 67599, 67600, 67601, 67602, + 67603, 67604, 67605, 67606, 67607, 67608, 67609, 67610, 67611, 67612, + 67613, 67614, 67615, 67616, 67617, 67618, 67619, 67620, 67621, 67622, + 67623, 67624, 67625, 67626, 67627, 67628, 67629, 67630, 67631, 67632, + 67633, 67634, 67635, 67636, 67637, 67589, 67592, 67644, 67647, 67639, + 67640, 67584, 67585, 67586, 67587, 67588, 77712, 77713, 77714, 77715, + 77716, 77717, 77718, 77719, 77722, 77723, 77720, 77721, 77724, 77725, + 77726, 77727, 77728, 77729, 77730, 77731, 77732, 77733, 77734, 77735, + 77736, 77737, 77738, 77739, 77740, 77741, 77742, 77743, 77744, 77745, + 77746, 77747, 77748, 77749, 77750, 77751, 77752, 77753, 77754, 77755, + 77756, 77757, 77758, 77773, 77774, 77768, 77769, 77770, 77771, 77772, + 77775, 77776, 77777, 77788, 77789, 77790, 77791, 77792, 77793, 77794, + 77795, 77796, 77759, 77760, 77761, 77762, 77763, 77764, 77765, 77766, + 77767, 77778, 77779, 77780, 77781, 77782, 77783, 77784, 77785, 77786, + 77787, 77797, 77798, 77799, 77800, 77801, 77802, 77803, 77804, 77805, + 77806, 77807, 77808, 77809, 77810, 1126, 1033, 1300, 42574, 1034, 1055, + 1190, 1316, 1136, 1146, 42564, 42592, 42580, 1296, 1302, 1058, 42634, + 1196, 1035, 42640, 42638, 1062, 42642, 42636, 1059, 1266, 1264, 1262, + 1144, 1028, 1040, 1234, 1232, 1212, 1214, 1248, 1192, 1310, 1256, 1258, + 1184, 42602, 1130, 42572, 42586, 1030, 1041, 1063, 1268, 1206, 1208, + 42584, 42650, 42630, 1026, 42568, 42604, 42648, 1029, 42562, 1322, 42632, + 1039, 42626, 1324, 42624, 1044, 1069, 1051, 1312, 1326, 1221, 1298, 1053, + 1314, 1186, 1320, 1225, 1223, 1056, 1166, 1260, 1057, 1194, 1052, 1229, + 1060, 1043, 1172, 1168, 1270, 1170, 1274, 1027, 1061, 1202, 1276, 1278, + 1066, 42644, 1048, 1252, 1037, 1250, 1045, 1024, 1238, 1025, 42588, 1128, + 1132, 42578, 42582, 1124, 42566, 1140, 1142, 1050, 1178, 1219, 1180, + 1182, 1286, 1282, 1280, 1288, 1290, 1292, 1294, 1284, 1152, 1227, 1036, + 1134, 42600, 42570, 1054, 1120, 1148, 1254, 1150, 1240, 1242, 1049, 1162, + 1038, 1210, 1318, 1065, 42646, 1064, 42596, 42598, 1068, 42594, 1198, + 1200, 1164, 1071, 1304, 1122, 1067, 1272, 42576, 1031, 42590, 1070, 1047, + 1246, 1176, 42560, 1046, 1244, 1174, 1217, 42628, 1138, 1032, 1042, 1308, + 1306, 1236, 1204, 1188, 42622, 42606, 1216, 7467, 42623, 1072, 1235, + 1233, 1213, 1215, 1249, 1193, 1311, 1257, 1259, 1185, 42603, 1131, 42573, + 42587, 1110, 1073, 1095, 1269, 1207, 1209, 42585, 42651, 42631, 1106, + 42569, 42605, 42649, 1109, 42563, 1323, 42633, 1119, 42627, 1325, 42625, + 1076, 1101, 1083, 1313, 1327, 1222, 1299, 1085, 1315, 1187, 1321, 1226, + 1224, 1088, 1167, 1261, 1089, 1195, 1084, 1230, 1092, 1075, 1173, 1169, + 1271, 1171, 1275, 1107, 1093, 1203, 1277, 1279, 1098, 42645, 1080, 1253, + 1117, 1251, 1077, 1104, 1239, 1105, 42589, 1129, 1133, 42579, 42583, + 1125, 42567, 1141, 1143, 1082, 1179, 1220, 1181, 1183, 1287, 1283, 1281, + 1289, 1291, 1293, 1295, 1285, 1153, 1228, 1116, 1135, 1127, 7297, 1113, + 1301, 42601, 42571, 42575, 7298, 1114, 1086, 1121, 1149, 1255, 1151, + 1087, 1191, 1317, 1231, 1137, 42565, 42593, 42581, 1297, 1147, 7296, + 1303, 1241, 1243, 1081, 1163, 1118, 1211, 1319, 1097, 42647, 1096, 42597, + 42599, 1100, 42595, 1199, 1201, 1165, 7302, 7303, 7300, 1090, 42635, + 1197, 1115, 42641, 42639, 1094, 7301, 42643, 42637, 1091, 1267, 1265, + 1263, 1145, 1108, 7304, 7299, 1309, 1103, 1305, 1123, 1099, 1273, 42577, + 1111, 42591, 1102, 1079, 1247, 1177, 42561, 1078, 1245, 1175, 1218, + 42629, 1139, 1112, 1074, 1307, 1237, 1205, 1189, 122984, 122962, 122986, + 122985, 122965, 122976, 122971, 122974, 122964, 122983, 122977, 122981, + 122982, 122980, 122978, 122967, 122968, 122969, 122966, 122979, 122973, + 122963, 122970, 122961, 122972, 122975, 1154, 9005, 127744, 983201, + 983188, 983172, 8224, 11830, 11831, 128481, 128131, 127841, 128374, 9619, + 11843, 128168, 10143, 65101, 65097, 8504, 983081, 983084, 983086, 983088, + 983090, 983162, 127795, 9110, 9192, 128475, 8451, 176, 8457, 983120, + 128666, 8796, 983119, 9161, 9159, 9153, 9156, 9162, 9160, 9154, 9157, + 9163, 9150, 9158, 9164, 9151, 9152, 9155, 127980, 9739, 66589, 66591, + 66596, 66597, 66587, 66585, 66594, 66595, 66593, 66599, 66562, 66563, + 66564, 66565, 66561, 66560, 66568, 66569, 66570, 66571, 66567, 66566, + 66598, 66573, 66588, 66579, 66592, 66590, 66581, 66578, 66580, 66582, + 66577, 66586, 66575, 66584, 66583, 66574, 66572, 66576, 66629, 66631, + 66636, 66637, 66627, 66625, 66634, 66635, 66633, 66639, 66602, 66603, + 66604, 66605, 66601, 66600, 66608, 66609, 66610, 66611, 66607, 66606, + 66638, 66613, 66628, 66619, 66632, 66630, 66621, 66618, 66620, 66622, + 66617, 66626, 66615, 66624, 66623, 66614, 66612, 66616, 127964, 127965, + 128421, 128468, 2388, 2416, 43258, 2387, 43257, 72448, 72449, 43259, + 2309, 2310, 2320, 2324, 2421, 43262, 2330, 2418, 2317, 2321, 2331, 2396, + 2430, 2338, 2337, 2343, 2342, 2429, 2394, 2328, 2427, 2327, 2426, 2361, + 2350, 2424, 2308, 2318, 2322, 2358, 2359, 2360, 2323, 2420, 2419, 2431, + 2349, 2348, 2333, 2428, 2332, 2393, 2326, 2325, 2397, 2353, 2352, 2399, + 2351, 2313, 2314, 2423, 2422, 2345, 2339, 2329, 2334, 2344, 2356, 2355, + 2354, 2336, 2335, 2341, 2340, 2315, 2400, 2316, 2401, 2357, 2311, 2312, + 2347, 2346, 2425, 2395, 2398, 2392, 2319, 983644, 983643, 983646, 983647, + 983649, 983648, 983642, 983645, 72450, 72451, 72452, 72453, 2305, 43255, + 43251, 43254, 43253, 72455, 72454, 72456, 43256, 43250, 43260, 43252, + 2304, 2365, 2306, 72457, 2364, 2417, 2381, 2307, 2386, 2385, 2366, 2376, + 2380, 2383, 43263, 2389, 2373, 2377, 2379, 2363, 2362, 2382, 2369, 2370, + 2391, 2390, 2374, 2378, 2371, 2372, 2402, 2403, 2367, 2368, 2375, 2405, + 2404, 2411, 2410, 2413, 2412, 2409, 2408, 2406, 2415, 2407, 2414, 43261, + 2384, 983089, 983161, 983087, 983085, 983083, 127962, 129487, 129420, + 11033, 11032, 11030, 11031, 128924, 128160, 8900, 8960, 168, 9856, 9857, + 9858, 9859, 9860, 9861, 128754, 53, 127238, 9356, 52, 127237, 9355, 57, + 127242, 9360, 49, 127234, 9352, 55, 127240, 9358, 54, 127239, 9357, 51, + 127236, 9354, 50, 127235, 9353, 48, 127233, 127232, 56, 127241, 9359, + 119557, 119556, 119555, 9868, 9871, 9870, 9869, 119553, 119554, 10131, + 10126, 10125, 10128, 10127, 10124, 10123, 127244, 10130, 10122, 10129, + 10111, 10106, 10105, 10108, 10107, 10104, 10103, 10110, 10102, 10109, + 10121, 10116, 10115, 10118, 10117, 10114, 10113, 127243, 10120, 10112, + 10119, 9107, 127919, 128549, 128542, 9933, 9090, 129400, 72004, 72021, + 72020, 72023, 72022, 72019, 72018, 72016, 72025, 72017, 72024, 71964, + 71958, 71963, 71974, 71973, 71936, 71937, 71961, 71960, 71966, 71965, + 71940, 71941, 71938, 71939, 71982, 71976, 71952, 71962, 71957, 71967, + 71978, 71979, 71980, 71971, 71970, 71954, 71953, 71951, 71950, 71949, + 71948, 71969, 71968, 71981, 71955, 71972, 71975, 71977, 71983, 71942, + 71945, 71997, 71996, 72003, 71995, 71984, 71991, 71987, 71988, 71985, + 71986, 71989, 71992, 71998, 72002, 72000, 72005, 72006, 71999, 72001, + 8725, 247, 8903, 129343, 8739, 9902, 129684, 128171, 128565, 12291, 8783, + 9009, 128462, 128441, 128442, 128443, 8939, 8941, 8716, 8740, 10990, + 8832, 8928, 8876, 8833, 8929, 8878, 128021, 71723, 71716, 71680, 71681, + 71687, 71689, 71703, 71702, 71708, 71707, 71701, 71700, 71706, 71705, + 71684, 71685, 71682, 71683, 71694, 71704, 71699, 71709, 71719, 71720, + 71721, 71713, 71712, 71696, 71695, 71693, 71692, 71698, 71697, 71691, + 71690, 71711, 71710, 71722, 71717, 71714, 71718, 71715, 71686, 71688, + 71729, 71730, 71724, 71732, 71734, 71727, 71728, 71725, 71726, 71731, + 71733, 71739, 71738, 71735, 71737, 71736, 128054, 128044, 36, 127025, + 127026, 127027, 127028, 127029, 127030, 127031, 127032, 127033, 127034, + 127035, 127036, 127037, 127038, 127039, 127040, 127041, 127042, 127043, + 127044, 127045, 127046, 127047, 127048, 127049, 127050, 127051, 127052, + 127053, 127054, 127055, 127056, 127057, 127058, 127059, 127060, 127061, + 127062, 127063, 127064, 127065, 127066, 127067, 127068, 127069, 127070, + 127071, 127072, 127073, 127024, 127075, 127076, 127077, 127078, 127079, + 127080, 127081, 127082, 127083, 127084, 127085, 127086, 127087, 127088, + 127089, 127090, 127091, 127092, 127093, 127094, 127095, 127096, 127097, + 127098, 127099, 127100, 127101, 127102, 127103, 127104, 127105, 127106, + 127107, 127108, 127109, 127110, 127111, 127112, 127113, 127114, 127115, + 127116, 127117, 127118, 127119, 127120, 127121, 127122, 127123, 127074, + 129743, 8363, 8724, 8760, 8901, 729, 9676, 8284, 11850, 11034, 129765, + 11795, 11784, 10649, 11798, 9470, 9465, 9464, 9467, 9466, 9463, 9462, + 9469, 9461, 9468, 10175, 10868, 10986, 8225, 8223, 11840, 8914, 8748, + 11842, 8222, 8215, 10835, 10836, 10645, 10913, 10915, 10914, 10939, 8243, + 12318, 10746, 10830, 10831, 11849, 10988, 11844, 10940, 8913, 8912, + 11005, 10987, 8915, 9208, 10981, 8875, 10979, 8214, 11799, 10646, 733, + 8252, 8263, 65100, 10908, 10907, 11002, 11001, 10906, 10905, 8510, 8473, + 8511, 8450, 8461, 8469, 8474, 8477, 8484, 8518, 8519, 8520, 8521, 8517, + 8509, 8508, 8512, 10719, 9890, 9891, 11260, 127849, 8868, 10993, 10623, + 8945, 8964, 128315, 128317, 10728, 10729, 129288, 129290, 129289, 129291, + 8595, 8629, 8671, 129035, 129031, 129179, 129043, 129027, 129047, 8626, + 8627, 10504, 8693, 129975, 8615, 10515, 11796, 11107, 11139, 11123, + 129067, 11168, 11169, 129063, 129059, 129075, 129071, 11133, 11085, + 11117, 11143, 129171, 10507, 8609, 11247, 8681, 129175, 8623, 11147, + 11015, 8659, 8675, 129079, 10597, 10607, 10593, 10585, 8643, 10589, + 10581, 8642, 129091, 129095, 129087, 10225, 128623, 129107, 129083, 8650, + 128687, 128330, 128682, 129444, 8367, 10139, 128009, 128050, 128042, + 129656, 128167, 129316, 129345, 9946, 128087, 113784, 113788, 113785, + 113783, 113782, 113786, 113787, 113795, 113798, 113793, 113800, 113781, + 113794, 113792, 113799, 113797, 113796, 113776, 113808, 113817, 113811, + 113814, 113809, 113816, 113779, 113810, 113815, 113813, 113812, 113778, + 113777, 113780, 113729, 113733, 113672, 113677, 113683, 113735, 113739, + 113746, 113668, 113678, 113674, 113726, 113691, 113699, 113700, 113695, + 113709, 113712, 113713, 113705, 113711, 113669, 113725, 113679, 113684, + 113670, 113743, 113749, 113687, 113689, 113693, 113707, 113697, 113703, + 113690, 113694, 113708, 113698, 113704, 113764, 113763, 113762, 113761, + 113732, 113753, 113731, 113755, 113754, 113666, 113766, 113765, 113676, + 113675, 113741, 113750, 113680, 113688, 113692, 113696, 113710, 113727, + 113728, 113716, 113717, 113714, 113715, 113701, 113702, 113724, 113723, + 113706, 113742, 113740, 113767, 113769, 113730, 113768, 113682, 113685, + 113752, 113737, 113667, 113719, 113718, 113681, 113745, 113748, 113751, + 113738, 113673, 113770, 113720, 113757, 113760, 113722, 113759, 113756, + 113721, 113758, 113665, 113747, 113664, 113686, 113734, 113736, 113744, + 113671, 113821, 113822, 113823, 113820, 129375, 129414, 129516, 128192, + 983082, 128066, 127805, 127806, 129467, 9793, 127758, 127759, 127757, + 9178, 9841, 129413, 11790, 77830, 77831, 77832, 77828, 77829, 77824, + 77825, 77826, 77827, 77833, 77834, 77835, 77840, 77841, 77844, 77845, + 77836, 77837, 77838, 77839, 77842, 77843, 77846, 77847, 77869, 77870, + 77872, 77873, 77874, 77875, 77877, 77878, 77871, 77876, 77879, 77880, + 77881, 77882, 77860, 77861, 77858, 77859, 77862, 77863, 77864, 77865, + 77866, 77867, 77868, 77903, 77848, 77849, 77850, 77851, 77852, 77853, + 77854, 77855, 77856, 77857, 77883, 77884, 77885, 77886, 77887, 77888, + 77889, 77890, 77891, 77892, 77893, 77894, 77895, 77896, 77897, 77898, + 77899, 77900, 77901, 77902, 78867, 78868, 78869, 78861, 78862, 78863, + 78864, 78865, 78866, 78870, 78871, 78892, 78893, 78894, 78872, 78873, + 78874, 78875, 78876, 78877, 78878, 78879, 78880, 78881, 78882, 78883, + 78884, 78885, 78886, 78887, 78888, 78889, 78890, 78891, 78903, 78910, + 78908, 77908, 77909, 77904, 77905, 77906, 77907, 77910, 77911, 77912, + 77913, 77915, 77916, 77917, 77918, 77914, 77919, 77920, 77921, 77922, + 77923, 77924, 77925, 77926, 77927, 77928, 77929, 77930, 77931, 77932, + 77933, 77934, 77935, 77936, 77937, 77938, 77939, 77940, 77941, 77949, + 77950, 77942, 77943, 77944, 77945, 77946, 77947, 77948, 77951, 77974, + 77975, 77978, 77979, 77973, 77976, 77977, 77980, 77981, 77982, 77983, + 77984, 77991, 77992, 77994, 77995, 77985, 77986, 77987, 77988, 77989, + 77990, 77993, 77996, 77997, 77998, 77999, 78000, 78001, 78002, 78003, + 78004, 78005, 78006, 78008, 78009, 78011, 78012, 78007, 78010, 78013, + 78014, 78015, 78016, 78017, 78025, 78026, 78027, 78028, 78029, 78030, + 78031, 78032, 78033, 78018, 78019, 78020, 78021, 78022, 78023, 78024, + 77969, 77970, 77962, 77963, 77964, 77965, 77966, 77967, 77968, 77971, + 77972, 77952, 77953, 77954, 77955, 77956, 77957, 77958, 77959, 77960, + 77961, 78041, 78042, 78043, 78044, 78034, 78035, 78036, 78037, 78038, + 78039, 78040, 78057, 78058, 78066, 78067, 78059, 78060, 78061, 78062, + 78063, 78064, 78065, 78068, 78073, 78074, 78069, 78070, 78071, 78072, + 78075, 78076, 78077, 78051, 78052, 78053, 78054, 78045, 78046, 78047, + 78048, 78049, 78050, 78055, 78056, 78904, 78911, 78909, 78078, 78079, + 78080, 78081, 78082, 78083, 78084, 78085, 78086, 78087, 78091, 78092, + 78088, 78089, 78090, 78093, 78094, 78095, 78096, 78097, 78098, 78111, + 78112, 78118, 78119, 78120, 78121, 78110, 78113, 78114, 78115, 78116, + 78117, 78122, 78128, 78129, 78130, 78131, 78132, 78133, 78123, 78124, + 78125, 78126, 78127, 78134, 78135, 78137, 78138, 78139, 78140, 78136, + 78141, 78142, 78100, 78101, 78099, 78102, 78103, 78104, 78105, 78106, + 78107, 78108, 78109, 78913, 78150, 78151, 78152, 78148, 78149, 78143, + 78144, 78145, 78146, 78147, 78153, 78154, 78156, 78157, 78155, 78158, + 78159, 78160, 78161, 78162, 78163, 78164, 78165, 78184, 78185, 78186, + 78187, 78178, 78179, 78180, 78181, 78182, 78183, 78188, 78189, 78193, + 78194, 78196, 78197, 78190, 78191, 78192, 78195, 78198, 78199, 78200, + 78201, 78166, 78167, 78173, 78174, 78168, 78169, 78170, 78171, 78172, + 78175, 78176, 78177, 78202, 78203, 78204, 78205, 78206, 78212, 78213, + 78207, 78208, 78209, 78210, 78211, 78214, 78215, 78914, 78916, 78897, + 78220, 78221, 78225, 78226, 78216, 78217, 78218, 78219, 78222, 78223, + 78224, 78227, 78228, 78229, 78230, 78231, 78232, 78233, 78234, 78907, + 78901, 78899, 78906, 78900, 78898, 78905, 78244, 78245, 78249, 78250, + 78243, 78246, 78247, 78248, 78251, 78252, 78915, 78253, 78254, 78255, + 78257, 78258, 78256, 78259, 78260, 78261, 78262, 78263, 78264, 78268, + 78269, 78270, 78271, 78272, 78273, 78274, 78275, 78276, 78265, 78266, + 78279, 78280, 78281, 78282, 78283, 78284, 78267, 78277, 78278, 78285, + 78286, 78289, 78290, 78292, 78293, 78297, 78298, 78287, 78288, 78291, + 78294, 78295, 78296, 78299, 78304, 78305, 78306, 78301, 78302, 78300, + 78303, 78307, 78308, 78309, 78310, 78311, 78312, 78313, 78314, 78315, + 78316, 78317, 78318, 78933, 78928, 78920, 78924, 78932, 78926, 78921, + 78929, 78925, 78923, 78931, 78919, 78927, 78922, 78930, 78912, 78336, + 78337, 78338, 78328, 78329, 78330, 78331, 78332, 78333, 78334, 78335, + 78339, 78354, 78355, 78356, 78357, 78358, 78359, 78361, 78362, 78351, + 78352, 78353, 78360, 78363, 78364, 78345, 78346, 78340, 78341, 78342, + 78343, 78344, 78347, 78348, 78349, 78350, 78365, 78366, 78367, 78319, + 78320, 78321, 78322, 78323, 78324, 78325, 78326, 78327, 78372, 78373, + 78368, 78369, 78370, 78371, 78374, 78375, 78376, 78377, 78385, 78386, + 78378, 78379, 78380, 78381, 78382, 78383, 78384, 78387, 78388, 78389, + 78399, 78400, 78401, 78402, 78409, 78410, 78403, 78404, 78405, 78406, + 78407, 78408, 78411, 78414, 78415, 78412, 78413, 78390, 78391, 78392, + 78393, 78394, 78395, 78396, 78397, 78398, 78423, 78424, 78425, 78426, + 78427, 78428, 78429, 78416, 78417, 78421, 78422, 78418, 78419, 78420, + 78430, 78431, 78432, 78433, 78434, 78435, 78436, 78445, 78446, 78437, + 78438, 78439, 78440, 78441, 78442, 78443, 78444, 78447, 78448, 78452, + 78453, 78454, 78455, 78459, 78460, 78449, 78450, 78451, 78456, 78457, + 78458, 78469, 78470, 78471, 78472, 78473, 78461, 78462, 78465, 78466, + 78463, 78464, 78467, 78468, 78474, 78475, 78476, 78487, 78488, 78489, + 78490, 78477, 78478, 78479, 78480, 78481, 78482, 78483, 78484, 78485, + 78486, 78902, 78491, 78492, 78494, 78495, 78493, 78496, 78497, 78498, + 78499, 78500, 78501, 78502, 78503, 78514, 78515, 78516, 78512, 78513, + 78511, 78517, 78518, 78519, 78520, 78521, 78522, 78523, 78524, 78530, + 78531, 78525, 78526, 78527, 78528, 78529, 78532, 78533, 78534, 78535, + 78536, 78537, 78538, 78539, 78540, 78541, 78542, 78543, 78544, 78546, + 78547, 78551, 78552, 78545, 78548, 78549, 78550, 78553, 78554, 78555, + 78560, 78561, 78562, 78565, 78566, 78556, 78557, 78558, 78559, 78563, + 78564, 78567, 78568, 78575, 78576, 78577, 78569, 78570, 78571, 78572, + 78573, 78574, 78578, 78579, 78580, 78586, 78587, 78581, 78582, 78583, + 78584, 78585, 78588, 78589, 78590, 78591, 78592, 78593, 78594, 78595, + 78596, 78597, 78598, 78601, 78602, 78606, 78607, 78608, 78609, 78610, + 78611, 78599, 78600, 78603, 78604, 78605, 78613, 78614, 78619, 78620, + 78612, 78615, 78616, 78617, 78618, 78621, 78622, 78623, 78636, 78637, + 78638, 78639, 78634, 78635, 78640, 78641, 78642, 78624, 78625, 78626, + 78627, 78628, 78629, 78630, 78631, 78632, 78633, 78917, 78648, 78649, + 78650, 78643, 78644, 78645, 78646, 78647, 78651, 78652, 78653, 78667, + 78668, 78674, 78675, 78664, 78665, 78666, 78669, 78670, 78671, 78672, + 78673, 78678, 78679, 78676, 78677, 78680, 78681, 78682, 78683, 78684, + 78685, 78686, 78687, 78688, 78689, 78654, 78655, 78656, 78657, 78658, + 78659, 78660, 78661, 78662, 78663, 78706, 78707, 78708, 78690, 78691, + 78692, 78693, 78694, 78695, 78696, 78697, 78698, 78699, 78700, 78701, + 78702, 78703, 78704, 78705, 78709, 78710, 78712, 78713, 78714, 78715, + 78895, 78716, 78717, 78718, 78711, 78719, 78720, 78721, 78722, 78723, + 78724, 78725, 78726, 78727, 78728, 78729, 78730, 78731, 78732, 78733, + 78734, 78735, 78736, 78737, 78738, 78741, 78742, 78747, 78748, 78749, + 78750, 78739, 78740, 78743, 78744, 78745, 78746, 78751, 78752, 78753, + 78754, 78756, 78757, 78761, 78762, 78755, 78758, 78759, 78760, 78763, + 78764, 78765, 78766, 78896, 78769, 78770, 78776, 78777, 78767, 78768, + 78771, 78772, 78773, 78774, 78775, 78778, 78779, 78783, 78784, 78787, + 78788, 78789, 78790, 78780, 78781, 78782, 78785, 78786, 78791, 78796, + 78797, 78792, 78793, 78794, 78795, 78798, 78918, 78802, 78803, 78804, + 78806, 78807, 78809, 78810, 78799, 78800, 78801, 78805, 78808, 78811, + 78812, 78813, 78814, 78815, 78816, 78817, 78818, 78819, 78821, 78822, + 78823, 78824, 78825, 78826, 78827, 78828, 78829, 78830, 78831, 78832, + 78820, 78833, 78834, 78835, 78836, 78842, 78843, 78844, 78845, 78846, + 78847, 78848, 78849, 78850, 78851, 78852, 78853, 78854, 78855, 78856, + 78857, 78858, 78859, 78860, 78837, 78838, 78839, 78840, 78841, 78235, + 78236, 78237, 78238, 78239, 78240, 78241, 78242, 78504, 78505, 78506, + 78507, 78508, 78509, 78510, 129370, 10037, 10039, 10036, 10049, 10058, + 10035, 9834, 66854, 66853, 66827, 66826, 66833, 66832, 66821, 66837, + 66836, 66835, 66842, 66841, 66824, 66823, 66819, 66818, 66822, 66820, + 66855, 66831, 66844, 66843, 66846, 66845, 66852, 66851, 66817, 66825, + 66828, 66830, 66834, 66839, 66840, 66848, 66849, 66816, 66829, 66838, + 66847, 66850, 128268, 128294, 128161, 8961, 9191, 8712, 8946, 8953, 8947, + 8952, 8950, 8949, 10969, 10194, 128024, 128727, 69608, 69621, 69603, + 69611, 69618, 69619, 69600, 69615, 69602, 69606, 69614, 69617, 69620, + 69609, 69604, 69607, 69610, 69601, 69613, 69605, 69616, 69612, 69622, + 129501, 983101, 129456, 129457, 129459, 129458, 127995, 127996, 127997, + 127998, 127999, 128453, 128454, 128455, 129721, 128460, 128461, 8709, + 10675, 10676, 10674, 10673, 128459, 9091, 8193, 8212, 8195, 8192, 8211, + 8194, 983179, 8718, 983178, 983135, 983099, 983048, 983095, 983046, + 983064, 128282, 983051, 983050, 9993, 128388, 128233, 9094, 983067, + 983100, 983049, 8926, 8927, 8925, 8924, 8797, 8917, 61, 10865, 10867, + 11072, 10609, 10723, 10724, 10926, 11257, 10871, 10854, 10862, 8789, + 10872, 8781, 8794, 10738, 10736, 10734, 10739, 10737, 10735, 11249, + 11248, 9003, 8998, 983105, 983104, 8494, 8793, 983136, 4957, 4959, 4958, + 4963, 4965, 4978, 4988, 4980, 4979, 4987, 4985, 4982, 4981, 4986, 4984, + 4983, 4968, 4966, 4964, 4960, 4999, 4998, 4711, 4997, 43816, 43819, + 43821, 43820, 43818, 43822, 43817, 4704, 4707, 4710, 11653, 4709, 4708, + 4706, 4705, 43808, 43811, 43813, 43812, 43810, 43814, 43809, 11704, + 11707, 11709, 11708, 11706, 11710, 11705, 11688, 11691, 11693, 11692, + 11690, 11694, 11689, 4904, 4907, 4910, 11664, 4909, 4908, 4911, 4906, + 4905, 4728, 4731, 4734, 11655, 4733, 4732, 4735, 4730, 4729, 43789, + 43788, 43787, 43786, 43790, 43785, 4856, 4859, 4862, 11661, 4861, 4860, + 4863, 4858, 4857, 43797, 43796, 43795, 43794, 43798, 43793, 4848, 4851, + 4854, 11660, 4853, 4852, 4855, 4850, 4849, 5003, 5002, 4943, 5001, 4936, + 4939, 4941, 4940, 4954, 4938, 4942, 4937, 4873, 124916, 124915, 124924, + 124923, 124910, 124909, 124926, 124925, 124922, 124921, 124920, 124919, + 124918, 124917, 124914, 124913, 124912, 124904, 11667, 4895, 11670, + 11669, 11668, 4888, 4891, 4893, 4892, 4890, 4894, 4889, 4768, 4771, 4774, + 11658, 4773, 4772, 4775, 4770, 4769, 4880, 4883, 4885, 4884, 4882, 11736, + 11739, 11741, 11740, 11738, 11742, 11737, 4872, 4875, 4878, 4879, 4877, + 4876, 4874, 124907, 124906, 4631, 124905, 124896, 124899, 124901, 124900, + 124898, 124902, 124897, 4624, 4627, 4629, 4628, 4626, 4630, 4625, 4608, + 4611, 4614, 4615, 4613, 4612, 4610, 4609, 4800, 4803, 4805, 4804, 4802, + 4792, 4795, 4797, 4796, 4794, 4798, 4793, 4784, 4787, 4789, 4788, 4786, + 11720, 11723, 11725, 11724, 11722, 11726, 11721, 4776, 4779, 4782, 4783, + 4781, 4780, 4778, 4777, 4995, 4994, 4639, 4993, 4632, 4635, 4638, 11649, + 4637, 4636, 4953, 4634, 4633, 4760, 4763, 4766, 11657, 4765, 4764, 4767, + 4762, 4761, 4752, 4755, 4758, 11656, 4757, 4756, 4759, 4754, 4753, 4912, + 4816, 4819, 4821, 4820, 4818, 4822, 4817, 4915, 4918, 11665, 4917, 4916, + 4919, 4914, 4913, 5007, 5006, 4951, 5005, 4944, 4947, 4950, 11666, 4949, + 4948, 4946, 4945, 4696, 4699, 4701, 4700, 4698, 4688, 4691, 4693, 4692, + 4690, 4694, 4689, 4680, 4683, 4685, 4684, 4682, 11712, 11715, 11717, + 11716, 11714, 11718, 11713, 4672, 4675, 4678, 4679, 4677, 4676, 4674, + 4673, 4648, 4651, 4654, 11650, 4653, 4652, 4655, 4952, 4650, 4649, 4661, + 4996, 5000, 4992, 5004, 4660, 4664, 4667, 4670, 11652, 4669, 4668, 4671, + 4666, 4665, 4640, 4643, 4645, 4644, 4647, 4642, 4646, 4641, 11680, 11683, + 11685, 11684, 11682, 11686, 11681, 4656, 4659, 4662, 11651, 4663, 4658, + 4657, 4896, 4899, 4902, 11663, 4901, 4900, 4903, 4898, 4897, 43781, + 43780, 43779, 43778, 43782, 43777, 4928, 4931, 4934, 4935, 4933, 4932, + 4930, 4929, 4920, 4923, 4925, 4924, 4927, 4922, 4926, 4921, 4720, 4723, + 4726, 11654, 4725, 4724, 4727, 4722, 4721, 4864, 4867, 4870, 11662, 4869, + 4868, 4871, 4866, 4865, 4616, 4619, 4622, 11648, 4621, 4620, 4623, 4618, + 4617, 4808, 4811, 4814, 4815, 4813, 4812, 4810, 4809, 4840, 4843, 4846, + 4847, 4845, 4844, 4842, 4841, 4744, 4747, 4749, 4748, 4746, 11728, 11731, + 11733, 11732, 11730, 11734, 11729, 4736, 4739, 4742, 4743, 4741, 4740, + 4738, 4737, 4832, 4835, 4837, 4836, 4839, 4834, 4838, 4833, 11696, 11699, + 11701, 11700, 11698, 11702, 11697, 4824, 4827, 4830, 11659, 4829, 4828, + 4831, 4826, 4825, 4712, 4715, 4717, 4716, 4719, 4714, 4718, 4713, 5009, + 5016, 5012, 5015, 5013, 5017, 5010, 5011, 5014, 5008, 4973, 4972, 4975, + 4974, 4971, 4970, 4977, 4969, 4976, 4962, 4967, 4961, 983096, 983047, + 127984, 127972, 8352, 8364, 8455, 8265, 33, 8761, 128942, 128954, 128948, + 128905, 128915, 128935, 128125, 1781, 1780, 1783, 1782, 1779, 1778, 1776, + 1785, 1777, 1784, 128529, 128065, 128083, 128064, 128231, 9167, 127794, + 983180, 128523, 128561, 129312, 128531, 129301, 128567, 129488, 128582, + 128558, 129326, 128560, 129762, 129320, 128581, 129395, 129763, 129402, + 128539, 128540, 128541, 128514, 129298, 129323, 128580, 128548, 129764, + 129396, 128566, 129318, 128134, 128536, 129401, 8507, 127981, 10540, + 10543, 9950, 127810, 129478, 128439, 128224, 128106, 9771, 127877, + 129498, 129718, 128552, 170, 9792, 127905, 9972, 129338, 8210, 8199, + 128193, 128452, 983107, 128253, 127902, 128293, 128658, 129519, 127879, + 127878, 129512, 9789, 127771, 127763, 8296, 129351, 128031, 127907, 9673, + 127845, 128074, 8281, 11821, 127953, 10765, 129407, 129747, 9189, 9971, + 129449, 128170, 9884, 10086, 9880, 8277, 127924, 128190, 128563, 129672, + 129712, 129359, 128760, 128389, 127787, 127745, 129709, 128448, 129462, + 128099, 127860, 127869, 11792, 10972, 983071, 8704, 8873, 129376, 10021, + 11156, 8280, 8283, 10019, 127808, 10018, 128966, 8732, 8197, 9970, + 129749, 129418, 8260, 8543, 128444, 128446, 128445, 127839, 8355, 129398, + 10156, 128037, 8994, 128550, 128056, 127844, 127773, 127765, 10199, 9608, + 46, 65342, 65312, 65292, 65306, 65504, 65371, 65375, 65288, 65339, 65308, + 65313, 65314, 65315, 65316, 65317, 65318, 65319, 65320, 65321, 65322, + 65323, 65324, 65325, 65326, 65327, 65328, 65329, 65330, 65331, 65332, + 65333, 65334, 65335, 65336, 65337, 65338, 65345, 65346, 65347, 65348, + 65349, 65350, 65351, 65352, 65353, 65354, 65355, 65356, 65357, 65358, + 65359, 65360, 65361, 65362, 65363, 65364, 65365, 65366, 65367, 65368, + 65369, 65370, 65343, 65506, 65283, 65505, 65285, 65291, 65373, 65376, + 65289, 65341, 65340, 65307, 65295, 65509, 65507, 65287, 65286, 65290, + 65284, 65301, 65300, 65303, 65302, 65299, 65298, 65296, 65305, 65297, + 65304, 65309, 65281, 65344, 65310, 65293, 65282, 65311, 65510, 65374, + 65508, 65294, 65372, 8289, 9905, 9981, 9179, 983215, 983216, 983217, + 983219, 983108, 983236, 983072, 129476, 127922, 9881, 9965, 9966, 128142, + 9802, 8782, 8785, 8762, 4301, 4256, 4288, 4292, 4290, 4293, 4289, 4281, + 4285, 4284, 4282, 4278, 4258, 4287, 4283, 4277, 4265, 4276, 4270, 4280, + 4273, 4271, 4262, 4263, 4274, 4266, 4272, 4257, 4267, 4286, 4268, 4279, + 4261, 4259, 4260, 4264, 4269, 4275, 4295, 4291, 11565, 11520, 11552, + 11556, 11554, 11557, 11553, 11545, 11549, 11548, 11546, 11542, 11522, + 11551, 11547, 11541, 11529, 11540, 11534, 11544, 11537, 11535, 11526, + 11527, 11538, 11530, 11536, 11521, 11531, 11550, 11532, 11543, 11525, + 11523, 11524, 11528, 11533, 11539, 11559, 11555, 983955, 4323, 4349, + 4346, 4304, 4329, 4333, 4332, 4330, 4344, 4308, 4326, 4306, 4340, 4350, + 4336, 4338, 4341, 4337, 4335, 4331, 4325, 4313, 4351, 4314, 4324, 4318, + 4328, 4321, 4345, 4311, 4322, 4319, 4310, 4320, 4305, 4315, 4334, 4316, + 4327, 4309, 4307, 4312, 4317, 4343, 4339, 4342, 7357, 7354, 7312, 7337, + 7341, 7340, 7338, 7352, 7316, 7334, 7314, 7348, 7358, 7344, 7346, 7349, + 7345, 7343, 7339, 7333, 7321, 7359, 7322, 7332, 7326, 7336, 7329, 7353, + 7319, 7330, 7327, 7318, 7328, 7313, 7323, 7342, 7324, 7335, 7317, 7315, + 7320, 7325, 7331, 7351, 7347, 7350, 4347, 8368, 12307, 129502, 8503, + 129754, 128103, 128714, 129426, 11264, 11304, 11265, 11311, 11293, 11276, + 11268, 11271, 11287, 11306, 11267, 11275, 11274, 11305, 11303, 11307, + 11273, 11310, 11278, 11279, 11280, 11281, 11289, 11282, 11290, 11283, + 11291, 11308, 11294, 11284, 11298, 11300, 11301, 11285, 11309, 11292, + 11266, 11269, 11296, 11295, 11297, 11302, 11299, 11272, 11270, 11288, + 11286, 11277, 11312, 11352, 11313, 11359, 11341, 11324, 11316, 11319, + 11335, 11354, 11315, 11323, 11322, 11353, 11351, 11355, 11321, 11358, + 11326, 11327, 11328, 11329, 11337, 11330, 11338, 11331, 11339, 11356, + 11342, 11332, 11346, 11348, 11349, 11333, 11357, 11340, 11314, 11317, + 11344, 11343, 11345, 11350, 11347, 11320, 11318, 11336, 11334, 11325, + 129371, 127760, 127775, 129508, 10726, 129349, 128016, 66356, 66352, + 66376, 66359, 66358, 66375, 66378, 66369, 66365, 66368, 66357, 66370, + 66360, 66372, 66373, 66367, 66374, 66353, 66377, 66355, 66364, 66371, + 66361, 66363, 66366, 66354, 66362, 129405, 129421, 128893, 129727, + 127948, 127891, 70495, 70494, 70411, 70496, 70412, 70497, 70453, 70405, + 70406, 70416, 70420, 70434, 70433, 70439, 70438, 70432, 70431, 70437, + 70436, 70409, 70410, 70407, 70408, 70451, 70450, 70425, 70435, 70430, + 70440, 70454, 70455, 70456, 70445, 70444, 70427, 70426, 70424, 70423, + 70429, 70428, 70422, 70421, 70443, 70442, 70419, 70415, 70457, 70446, + 70448, 70447, 70400, 70401, 70493, 70461, 70402, 70460, 70477, 70403, + 70462, 70472, 70476, 70467, 70468, 70498, 70499, 70465, 70466, 70463, + 70464, 70475, 70471, 70487, 70480, 96, 127815, 10896, 10894, 10900, + 10892, 10898, 10616, 10890, 10888, 10917, 8935, 8809, 10878, 10882, + 10884, 10880, 10886, 8819, 8805, 8823, 10916, 8807, 8923, 10919, 10921, + 10874, 10876, 8919, 62, 65860, 65863, 65878, 65866, 65873, 65859, 65861, + 65868, 65875, 65862, 65870, 65864, 65871, 65867, 65874, 65857, 65869, + 65876, 65856, 65858, 65865, 65877, 65872, 65879, 65903, 65885, 65904, + 65907, 65908, 65900, 65883, 65886, 65896, 65890, 65882, 65880, 65891, + 65902, 65906, 65897, 65899, 65893, 65892, 65884, 65881, 65898, 65905, + 65887, 65901, 65894, 65895, 65888, 65889, 903, 65927, 65926, 913, 7945, + 7949, 8077, 7947, 8075, 7951, 8079, 8073, 7944, 7948, 8076, 7946, 8074, + 7950, 8078, 8072, 8124, 8120, 8122, 8123, 902, 8121, 882, 919, 7977, + 7981, 8093, 7979, 8091, 7983, 8095, 8089, 7976, 7980, 8092, 7978, 8090, + 7982, 8094, 8088, 8140, 8139, 8138, 905, 917, 7961, 7965, 7963, 7960, + 7964, 7962, 8137, 8136, 904, 921, 7993, 7999, 7997, 7995, 938, 7992, + 7998, 7996, 7994, 8152, 8154, 8155, 906, 8153, 937, 8041, 8045, 8109, + 8043, 8107, 8047, 8111, 8105, 8040, 8044, 8108, 8042, 8106, 8046, 8110, + 8104, 8188, 8187, 8186, 911, 927, 8009, 8013, 8011, 8008, 8012, 8010, + 8185, 8184, 908, 929, 8172, 931, 1018, 1015, 933, 8025, 8031, 8029, 8027, + 939, 8168, 8170, 8171, 910, 8169, 886, 934, 936, 928, 920, 932, 916, 922, + 915, 935, 914, 880, 918, 923, 895, 924, 925, 926, 1017, 1023, 1021, 1022, + 975, 1012, 8129, 8174, 8173, 901, 65915, 8190, 8159, 8158, 8157, 65920, + 65919, 119325, 119331, 119332, 119333, 119334, 119335, 119336, 119337, + 119326, 119338, 119339, 119340, 119341, 119342, 119343, 119344, 119345, + 119346, 119347, 119348, 119349, 119327, 119350, 119351, 119352, 119353, + 119354, 119355, 119356, 119328, 119357, 119358, 119359, 119360, 119361, + 119329, 119330, 65933, 1008, 983, 8125, 65922, 7466, 7464, 7462, 43877, + 7465, 7463, 992, 986, 984, 990, 988, 1011, 885, 1010, 1013, 65923, 884, + 65921, 119365, 65925, 65909, 65910, 65931, 8189, 65924, 65916, 8126, + 8127, 8143, 8142, 8141, 8128, 981, 982, 1020, 1009, 1014, 945, 8112, + 8048, 8114, 7937, 7941, 8069, 7943, 8071, 7939, 8067, 8065, 7936, 7940, + 8068, 7942, 8070, 7938, 8066, 8064, 8118, 8119, 8049, 8116, 8115, 940, + 8113, 985, 883, 989, 948, 949, 7953, 7957, 7955, 7952, 7956, 7954, 8051, + 8050, 941, 951, 7969, 7973, 8085, 7975, 8087, 7971, 8083, 8081, 7968, + 7972, 8084, 7974, 8086, 7970, 8082, 8080, 8134, 8135, 8053, 8132, 8052, + 8130, 8131, 942, 953, 7985, 7991, 7989, 7987, 970, 8151, 8147, 8146, 912, + 7984, 7990, 7988, 7986, 8150, 8144, 8054, 8055, 943, 8145, 965, 8017, + 8023, 8021, 8019, 971, 8167, 8163, 8162, 944, 8016, 8022, 8020, 8018, + 8166, 8160, 8058, 8059, 973, 8161, 954, 991, 969, 8033, 8037, 8101, 8039, + 8103, 8035, 8099, 8097, 8032, 8036, 8100, 8038, 8102, 8034, 8098, 8096, + 8182, 8183, 8061, 8180, 8060, 8178, 8179, 974, 959, 8001, 8005, 8003, + 8000, 8004, 8002, 8057, 8056, 972, 887, 966, 968, 960, 961, 8165, 8164, + 993, 1019, 987, 963, 1016, 952, 964, 962, 947, 967, 946, 881, 950, 955, + 956, 957, 958, 893, 891, 892, 7527, 7530, 7529, 7528, 7526, 65952, 65932, + 65918, 65912, 977, 65929, 65917, 65911, 900, 65914, 979, 980, 978, 8175, + 119297, 119315, 119316, 119317, 119318, 119319, 119300, 119320, 119321, + 119322, 119323, 119324, 119296, 119305, 119306, 119307, 119308, 119309, + 119310, 119311, 119312, 119313, 119314, 119298, 119299, 119301, 119302, + 119303, 119304, 890, 65913, 976, 65928, 65930, 894, 127823, 128215, + 128154, 129367, 129654, 128512, 129322, 128513, 129321, 128568, 128556, + 983110, 11218, 128151, 8370, 128130, 127928, 129454, 2693, 2694, 2704, + 2708, 2722, 2721, 2727, 2726, 2720, 2719, 2725, 2724, 2699, 2784, 2700, + 2785, 2741, 2697, 2698, 2695, 2696, 2739, 2738, 2809, 2713, 2723, 2718, + 2728, 2742, 2743, 2744, 2733, 2732, 2715, 2714, 2712, 2711, 2717, 2716, + 2710, 2709, 2731, 2730, 2745, 2734, 2736, 2735, 2703, 2707, 2814, 2689, + 2812, 2815, 2813, 2811, 2810, 2749, 2690, 2748, 2765, 2691, 2757, 2761, + 2750, 2760, 2764, 2755, 2756, 2786, 2787, 2753, 2754, 2751, 2752, 2759, + 2763, 2701, 2705, 2800, 2801, 2795, 2794, 2797, 2796, 2793, 2792, 2790, + 2799, 2791, 2798, 2768, 73056, 73057, 73064, 73067, 73091, 73090, 73081, + 73080, 73086, 73085, 73076, 73075, 73060, 73061, 73092, 73082, 73058, + 73059, 73087, 73077, 73071, 73070, 73084, 73083, 73079, 73078, 73089, + 73088, 73074, 73073, 73094, 73093, 73066, 73063, 73095, 73072, 73096, + 73097, 73069, 73068, 73110, 73109, 73098, 73105, 73108, 73101, 73102, + 73099, 73100, 73107, 73104, 73111, 73125, 73124, 73127, 73126, 73123, + 73122, 73120, 73129, 73121, 73128, 73112, 2678, 2673, 2650, 2584, 2583, + 2649, 2582, 2581, 2652, 2608, 2565, 2566, 2576, 2580, 2594, 2593, 2599, + 2598, 2592, 2591, 2597, 2596, 2569, 2570, 2567, 2568, 2611, 2610, 2585, + 2595, 2590, 2600, 2605, 2604, 2587, 2586, 2589, 2588, 2603, 2602, 2614, + 2616, 2579, 2575, 2654, 2617, 2606, 2613, 2607, 2651, 983656, 983655, + 983654, 983653, 983658, 983657, 2561, 2562, 2641, 2620, 2677, 2637, 2563, + 2622, 2632, 2636, 2625, 2626, 2623, 2624, 2635, 2631, 2672, 2674, 2676, + 2667, 2666, 2669, 2668, 2665, 2664, 2662, 2671, 2663, 2670, 2675, 128123, + 983111, 129710, 8202, 128135, 65467, 65441, 65443, 65444, 65445, 65446, + 65469, 65458, 65460, 65449, 65454, 65455, 65452, 65451, 65450, 65456, + 65453, 65465, 65442, 65459, 65448, 65462, 65461, 65483, 65482, 65476, + 65477, 65499, 65490, 65495, 65466, 65464, 65479, 65478, 65498, 65500, + 65463, 65457, 65468, 65447, 65493, 65492, 65485, 65486, 65494, 65470, + 65474, 65475, 65484, 65487, 65491, 65440, 65388, 65390, 65389, 65391, + 65383, 65386, 65384, 65387, 65385, 65403, 65406, 65404, 65407, 65405, + 65437, 65413, 65416, 65414, 65417, 65415, 65418, 65421, 65419, 65422, + 65420, 65398, 65401, 65399, 65402, 65400, 65423, 65426, 65424, 65427, + 65425, 65431, 65434, 65432, 65435, 65433, 65408, 65411, 65409, 65412, + 65410, 65428, 65430, 65429, 65436, 65382, 65393, 65396, 65394, 65397, + 65395, 65439, 65438, 65381, 65392, 65378, 65513, 65379, 65515, 65514, + 65512, 65380, 65377, 65517, 65518, 65516, 128296, 128736, 9773, 9874, + 128057, 129708, 127828, 129310, 129776, 129342, 128092, 129309, 4366, + 4434, 4435, 4431, 4413, 4412, 4436, 4430, 4433, 4415, 4414, 4437, 4432, + 4364, 4429, 4363, 4427, 4420, 4422, 43382, 4425, 4424, 4419, 4426, 4418, + 4417, 43383, 4421, 4379, 4439, 4395, 4396, 4381, 4352, 4442, 4367, 4358, + 43375, 4380, 43376, 43377, 4354, 4444, 4371, 4374, 4373, 4445, 4443, + 4369, 4438, 43386, 4359, 4385, 43378, 4387, 4390, 4386, 4388, 4389, 4394, + 43379, 4382, 4392, 4391, 4393, 4384, 4383, 43380, 4416, 4357, 43371, + 43374, 43364, 43365, 43370, 43367, 43372, 43368, 43373, 4376, 43369, + 43366, 4378, 4361, 4402, 4403, 4410, 4404, 4400, 4408, 4397, 4407, 4406, + 4401, 4409, 4399, 4398, 4411, 4405, 4365, 43384, 4362, 43381, 4377, + 43385, 4356, 43388, 4353, 4372, 4360, 4440, 4423, 4355, 4446, 43360, + 43363, 4375, 43361, 43362, 4368, 4428, 4441, 4370, 43387, 4447, 12335, + 12334, 4541, 55288, 55287, 4542, 4546, 4598, 4599, 4597, 4600, 4540, + 4591, 4588, 4589, 55261, 4596, 4582, 4578, 4520, 4605, 4547, 4522, 4548, + 4604, 4602, 4603, 4606, 4543, 4535, 4572, 55265, 4575, 55263, 4574, 4573, + 4571, 4576, 55266, 4570, 55262, 4577, 4523, 55243, 55244, 4524, 4553, + 4550, 4549, 4525, 4552, 4551, 4587, 55284, 55283, 4545, 55291, 4595, + 55290, 4536, 4579, 55268, 4537, 55271, 4580, 55273, 55272, 55269, 55267, + 4581, 4527, 4528, 55254, 4556, 4565, 4568, 4529, 4561, 55256, 4562, 4530, + 55258, 55257, 4564, 4563, 4533, 4567, 55253, 4566, 4531, 4558, 4559, + 4532, 4569, 55260, 55259, 4557, 4534, 4538, 55275, 4583, 4585, 55280, + 55279, 4586, 55278, 55274, 55281, 4584, 55282, 4560, 55255, 55245, 55246, + 983213, 4539, 55276, 55277, 55264, 55289, 4521, 4607, 55270, 4590, 4526, + 4555, 55248, 55249, 55252, 55251, 55250, 4554, 55247, 4544, 4592, 983214, + 983211, 983212, 4593, 55285, 55286, 4594, 4601, 4449, 4510, 55238, 4511, + 55237, 4513, 4512, 4515, 4470, 4471, 4450, 4454, 4453, 4476, 4474, 4475, + 4467, 55227, 55226, 4502, 55225, 55228, 4501, 4469, 4504, 4509, 4505, + 55229, 55230, 55232, 55231, 55234, 55235, 4506, 55233, 4508, 55236, 4507, + 4514, 4457, 4482, 55217, 4481, 55216, 4518, 4519, 4480, 4479, 4483, 4460, + 4462, 4492, 55221, 55222, 4491, 4489, 4490, 4493, 4451, 4473, 4472, 4516, + 4452, 4456, 4455, 4517, 4477, 4478, 4468, 4503, 4461, 4484, 4485, 4486, + 55218, 55219, 55220, 4488, 4487, 4466, 4498, 4497, 4496, 4495, 4494, + 55223, 4500, 55224, 4499, 4464, 4463, 4458, 4459, 4465, 4448, 12623, + 12685, 12686, 12624, 12618, 12616, 12628, 12627, 12641, 12643, 12615, + 12676, 12664, 12665, 12657, 12619, 12593, 12595, 12609, 12654, 12656, + 12655, 12596, 12597, 12646, 12598, 12648, 12647, 12610, 12612, 12660, + 12661, 12663, 12659, 12662, 12658, 12621, 12671, 12601, 12602, 12649, + 12603, 12607, 12604, 12651, 12652, 12606, 12650, 12653, 12608, 12605, + 12620, 12599, 12613, 12670, 12666, 12667, 12669, 12668, 12617, 12594, + 12645, 12611, 12600, 12677, 12614, 12672, 12638, 12637, 12632, 12633, + 12639, 12630, 12629, 12678, 12673, 12675, 12674, 12635, 12679, 12680, + 12681, 12640, 12683, 12682, 12684, 12625, 12626, 12642, 12622, 12631, + 12634, 12636, 12644, 12323, 12346, 12345, 12322, 12344, 12325, 12324, + 12327, 12326, 12329, 12321, 12328, 68875, 68874, 68887, 68889, 68872, + 68881, 68868, 68867, 68877, 68876, 68890, 68891, 68885, 68880, 68879, + 68865, 68870, 68873, 68882, 68871, 68869, 68883, 68884, 68866, 68892, + 68886, 68888, 68878, 68864, 68899, 68898, 68901, 68903, 68902, 68900, + 68893, 68896, 68894, 68897, 68895, 68917, 68916, 68919, 68918, 68915, + 68914, 68912, 68921, 68913, 68920, 5925, 5928, 5930, 5927, 5924, 5937, + 5923, 5934, 5931, 5929, 5933, 5936, 5926, 5935, 5932, 5920, 5921, 5922, + 5940, 5938, 5939, 128587, 128035, 67808, 67823, 67814, 67816, 67829, + 67819, 67826, 67811, 67810, 67822, 67825, 67828, 67817, 67812, 67815, + 67818, 67809, 67821, 67813, 67824, 67820, 67835, 67839, 67838, 67837, + 67836, 128891, 128436, 11233, 129702, 9980, 127911, 127892, 128157, + 128152, 128159, 129782, 128585, 129180, 129183, 129182, 129181, 128628, + 10033, 10008, 10149, 10150, 10084, 10167, 10169, 10168, 10054, 10004, + 11096, 9955, 11095, 11097, 10152, 10144, 10135, 129055, 129051, 10077, + 10078, 128178, 128977, 10040, 128975, 10059, 128958, 10071, 10082, + 129008, 10020, 128970, 128946, 129943, 10083, 11093, 128327, 10096, + 10094, 129052, 129048, 10080, 10079, 10157, 128627, 10006, 10134, 10012, + 11094, 10030, 10097, 10095, 10137, 129054, 129050, 10140, 128635, 128940, + 10075, 10076, 128972, 128952, 128607, 128615, 10136, 128605, 128613, + 128625, 10056, 128606, 128614, 10138, 128604, 128612, 10051, 10045, + 10171, 10142, 128980, 128979, 129053, 129049, 10158, 9947, 128903, + 128913, 10132, 10173, 128633, 10133, 10074, 10010, 1442, 1453, 1447, + 1436, 1437, 1438, 1445, 1446, 1443, 1444, 1433, 1441, 1425, 1439, 1448, + 1426, 1427, 1449, 1440, 1435, 1430, 1450, 1434, 1428, 1429, 1432, 1454, + 1431, 1451, 1452, 1488, 64304, 64302, 64303, 64288, 64297, 1506, 1489, + 64332, 64305, 1499, 64333, 64315, 1508, 64334, 64324, 1498, 64314, 1507, + 64323, 1509, 1503, 1501, 1511, 64327, 1492, 64308, 1495, 1504, 64320, + 1494, 64310, 1505, 64321, 1513, 64329, 64300, 64301, 64298, 64299, 1512, + 64328, 1496, 64312, 1514, 64330, 1510, 64326, 1491, 64307, 1490, 64306, + 1500, 64316, 1502, 64318, 1493, 64331, 64309, 64293, 64289, 64296, 64295, + 64290, 64292, 64291, 64294, 1497, 64285, 64313, 64335, 1520, 1522, 64287, + 1521, 1477, 1476, 1455, 1468, 1458, 1459, 1457, 1460, 1465, 1466, 1463, + 64286, 1464, 1479, 1467, 1471, 1462, 1473, 1456, 1474, 1461, 1469, 1524, + 1523, 1472, 1475, 1478, 1470, 1519, 9937, 9096, 11263, 128641, 110597, + 110594, 110595, 110596, 110778, 110779, 110780, 110781, 110782, 110783, + 110784, 110785, 110750, 110759, 110760, 110751, 110752, 110753, 110754, + 110755, 110756, 110757, 110758, 110768, 110769, 110770, 110771, 110772, + 110773, 110774, 110775, 110776, 110777, 110761, 110762, 110763, 110764, + 110765, 110766, 110767, 110615, 110624, 110625, 110626, 110616, 110617, + 110618, 110619, 110620, 110621, 110622, 110623, 110651, 110648, 110649, + 110650, 110627, 110628, 110629, 110630, 110631, 110632, 110633, 110634, + 110642, 110643, 110644, 110645, 110646, 110647, 110635, 110636, 110637, + 110638, 110639, 110640, 110641, 110806, 110804, 110805, 110807, 110808, + 110809, 110810, 110811, 110812, 110786, 110787, 110788, 110789, 110790, + 110791, 110792, 110793, 110794, 110795, 110796, 110797, 110798, 110799, + 110800, 110801, 110802, 110803, 110744, 110738, 110739, 110740, 110741, + 110742, 110743, 110734, 110727, 110728, 110729, 110730, 110731, 110732, + 110733, 110718, 110719, 110720, 110721, 110722, 110723, 110724, 110725, + 110726, 110745, 110746, 110747, 110748, 110749, 110735, 110736, 110737, + 110877, 110878, 110850, 110851, 110852, 110853, 110854, 110855, 110840, + 110841, 110842, 110843, 110844, 110845, 110833, 110834, 110835, 110836, + 110837, 110838, 110839, 110829, 110830, 110831, 110832, 110846, 110847, + 110848, 110849, 110652, 110653, 110654, 110655, 110656, 110657, 110658, + 110659, 110666, 110667, 110668, 110669, 110670, 110671, 110672, 110673, + 110660, 110661, 110662, 110663, 110664, 110665, 110674, 110675, 110676, + 110677, 110678, 110679, 110680, 110681, 110682, 110683, 110684, 110685, + 110702, 110703, 110704, 110705, 110706, 110707, 110708, 110709, 110710, + 110717, 110711, 110712, 110713, 110714, 110715, 110716, 110701, 110697, + 110698, 110699, 110700, 110690, 110691, 110692, 110693, 110694, 110695, + 110696, 110686, 110687, 110688, 110689, 110856, 110857, 110858, 110859, + 110860, 110861, 110862, 110863, 110864, 110865, 110870, 110871, 110872, + 110873, 110874, 110875, 110876, 110866, 110867, 110868, 110869, 110818, + 110813, 110814, 110815, 110816, 110817, 110823, 110824, 110825, 110826, + 110827, 110828, 110819, 110820, 110821, 110822, 983271, 110607, 110608, + 110609, 110610, 110611, 110602, 110603, 110604, 110605, 110606, 110612, + 110613, 110614, 110598, 110599, 110600, 110601, 8889, 127807, 19922, + 19966, 19958, 19967, 19924, 19946, 19923, 19909, 19947, 19944, 19943, + 19956, 19906, 19962, 19935, 19939, 19920, 19916, 19948, 19917, 19937, + 19931, 19929, 19925, 19911, 19964, 19928, 19945, 19934, 19918, 19930, + 19942, 19950, 19941, 19949, 19938, 19914, 19927, 19936, 19952, 19965, + 19912, 19915, 19926, 19954, 19910, 19932, 19953, 19904, 19933, 19940, + 19905, 19951, 19959, 19957, 19960, 19955, 19961, 19913, 19908, 19921, + 19963, 19907, 19919, 129428, 128262, 9889, 983123, 128644, 128645, + 128096, 12447, 12354, 110879, 110593, 12430, 110929, 110928, 110930, + 12419, 12423, 12421, 12437, 12438, 110898, 12387, 12353, 12359, 12355, + 12361, 12357, 12373, 12379, 12375, 12381, 12377, 12403, 983997, 984000, + 983998, 984001, 983999, 12400, 12409, 12412, 12406, 12435, 12394, 12397, + 12395, 12398, 12396, 12384, 12391, 12386, 12393, 12389, 12364, 12370, + 12366, 12372, 12368, 12399, 12408, 12402, 12411, 12405, 12363, 12369, + 12365, 12371, 12367, 12414, 12417, 12415, 12418, 12416, 12401, 12410, + 12404, 12413, 12407, 12425, 12428, 12426, 12429, 12427, 12383, 12390, + 12385, 12392, 12388, 12374, 12380, 12376, 12382, 12378, 12431, 12433, + 12432, 12434, 12420, 12424, 12422, 12436, 12360, 12356, 12362, 12358, + 12446, 12445, 9964, 128725, 129406, 127802, 129435, 128616, 128617, + 128371, 128029, 127855, 11203, 11043, 8213, 9135, 129921, 129910, 129911, + 129912, 129913, 129914, 129915, 9146, 9147, 9148, 9149, 983059, 983141, + 983138, 11134, 128677, 8230, 9897, 128014, 127943, 128052, 127798, 9749, + 9832, 127789, 127976, 8987, 9203, 8962, 127969, 127968, 127960, 127973, + 128298, 8763, 129693, 983124, 983060, 983142, 983139, 128559, 128175, + 129303, 128726, 8208, 11802, 8259, 8231, 45, 11794, 9102, 11226, 129723, + 8372, 127848, 129482, 127954, 9976, 8801, 10725, 10855, 129706, 12696, + 12700, 12693, 12697, 12695, 12703, 12692, 12699, 12691, 12694, 12688, + 12698, 12690, 12689, 12701, 12702, 12294, 12289, 12275, 12273, 12274, + 12272, 12283, 12282, 12285, 12279, 12280, 12281, 12278, 12277, 12284, + 12783, 12287, 12276, 12286, 12332, 12295, 119670, 119669, 119668, 119667, + 119666, 12999, 12995, 13309, 13310, 13292, 13282, 13299, 13304, 13303, + 13306, 13305, 13302, 13301, 13308, 13300, 13307, 13291, 13281, 13289, + 13287, 13297, 13290, 13294, 13284, 13283, 13293, 13288, 13298, 13286, + 13296, 13285, 13295, 13280, 13003, 13164, 13168, 13167, 13166, 13165, + 13156, 13146, 13157, 13147, 13154, 13152, 13162, 13155, 13159, 13149, + 13148, 13158, 13153, 13163, 13151, 13161, 13150, 13160, 13144, 13145, + 12992, 12997, 12998, 12993, 12994, 12996, 13002, 13000, 13001, 12343, + 12351, 12333, 12331, 12330, 12350, 12290, 12293, 12288, 8887, 8787, + 128127, 67676, 67673, 67675, 67679, 67674, 67672, 67677, 67678, 67656, + 67669, 67651, 67659, 67666, 67667, 67648, 67663, 67650, 67654, 67662, + 67665, 67668, 67657, 67652, 67655, 67658, 67649, 67661, 67653, 67664, + 67660, 67671, 128232, 10716, 128474, 10721, 8710, 983130, 983129, 129781, + 126132, 126112, 126126, 126125, 126127, 126131, 126130, 126129, 126113, + 126114, 126110, 126111, 126072, 126081, 126108, 126090, 126099, 126078, + 126105, 126069, 126087, 126096, 126077, 126104, 126068, 126086, 126095, + 126073, 126082, 126109, 126091, 126100, 126071, 126080, 126107, 126089, + 126098, 126070, 126079, 126106, 126088, 126097, 126076, 126103, 126067, + 126085, 126094, 126075, 126102, 126066, 126084, 126093, 126074, 126101, + 126119, 126118, 126121, 126120, 126117, 126116, 126123, 126115, 126122, + 126065, 126083, 126092, 126128, 126124, 8377, 8734, 10718, 983106, + 983109, 983112, 983115, 8505, 128129, 8300, 8298, 128288, 128289, 128292, + 128291, 128290, 68456, 68466, 68448, 68451, 68459, 68460, 68453, 68450, + 68454, 68462, 68464, 68465, 68457, 68452, 68455, 68458, 68449, 68461, + 68463, 68477, 68473, 68474, 68476, 68472, 68478, 68479, 68475, 68424, + 68437, 68419, 68427, 68434, 68435, 68416, 68431, 68418, 68422, 68430, + 68433, 68436, 68425, 68420, 68423, 68426, 68417, 68429, 68421, 68432, + 68428, 68445, 68441, 68442, 68444, 68440, 68446, 68447, 68443, 9088, + 8747, 10767, 10773, 10776, 10780, 10778, 10775, 10777, 10779, 10766, + 9134, 65529, 65531, 65530, 9892, 8745, 10825, 10823, 10820, 10819, 10816, + 10827, 8253, 8890, 10812, 129942, 129969, 129972, 9689, 129936, 9688, + 11800, 11845, 11846, 8766, 9959, 161, 8487, 8276, 191, 8290, 8292, 8291, + 128229, 127982, 129311, 127875, 127983, 127971, 12292, 9979, 127886, + 128122, 128121, 128304, 43453, 43454, 43455, 43457, 43421, 43422, 43426, + 43427, 43398, 43397, 43399, 43407, 43408, 43409, 43412, 43402, 43403, + 43418, 43416, 43428, 43423, 43431, 43432, 43413, 43414, 43410, 43411, + 43429, 43430, 43401, 43435, 43436, 43441, 43439, 43440, 43424, 43425, + 43419, 43420, 43415, 43417, 43396, 43405, 43442, 43437, 43433, 43438, + 43434, 43404, 43406, 43400, 43458, 43466, 43467, 43459, 43465, 43461, + 43464, 43468, 43463, 43486, 43462, 43487, 43460, 43471, 43456, 43469, + 43393, 43443, 43392, 43395, 43394, 43448, 43449, 43444, 43450, 43445, + 43446, 43447, 43452, 43451, 43477, 43476, 43479, 43478, 43475, 43474, + 43472, 43481, 43473, 43480, 129753, 129724, 128086, 128377, 10781, + 129337, 9795, 9909, 129513, 69786, 69787, 69785, 69793, 69792, 69763, + 69764, 69770, 69772, 69784, 69783, 69791, 69790, 69767, 69768, 69765, + 69766, 69777, 69789, 69782, 69794, 69804, 69805, 69806, 69798, 69797, + 69779, 69778, 69776, 69775, 69781, 69780, 69774, 69773, 69796, 69795, + 69788, 69801, 69807, 69802, 69799, 69803, 69800, 69769, 69771, 69760, + 69818, 69761, 69817, 69762, 69822, 69823, 69825, 69824, 69826, 69808, + 69814, 69816, 69811, 69812, 69809, 69810, 69813, 69815, 69821, 69837, + 69819, 69820, 12142, 12164, 12060, 12157, 12100, 12149, 12184, 12191, + 12227, 12068, 12174, 12234, 12205, 12134, 12168, 12219, 12189, 12088, + 12090, 12096, 12160, 12182, 12224, 12190, 12147, 12114, 12118, 12058, + 12176, 12075, 12112, 12045, 12170, 12124, 12070, 12194, 12109, 12229, + 12196, 12139, 12056, 12099, 12034, 12084, 12136, 12120, 12044, 12111, + 12094, 12125, 12243, 12238, 12082, 12159, 12063, 12215, 12062, 12042, + 12241, 12067, 12235, 12043, 12140, 12119, 12207, 12123, 12133, 12222, + 12117, 12226, 12245, 12214, 12217, 12236, 12155, 12188, 12113, 12065, + 12198, 12066, 12146, 12171, 12225, 12200, 12121, 12093, 12095, 12221, + 12092, 12216, 12231, 12054, 12218, 12179, 12037, 12173, 12072, 12046, + 12127, 12152, 12049, 12074, 12107, 12208, 12212, 12041, 12210, 12131, + 12033, 12039, 12199, 12085, 12128, 12161, 12162, 12233, 12165, 12192, + 12077, 12201, 12061, 12105, 12040, 12240, 12102, 12153, 12032, 12080, + 12167, 12048, 12156, 12059, 12126, 12158, 12050, 12183, 12204, 12097, + 12239, 12053, 12078, 12150, 12071, 12187, 12186, 12223, 12228, 12104, + 12098, 12064, 12036, 12057, 12163, 12178, 12185, 12154, 12083, 12203, + 12087, 12135, 12151, 12202, 12035, 12122, 12141, 12180, 12144, 12076, + 12052, 12115, 12091, 12108, 12169, 12143, 12148, 12130, 12089, 12211, + 12073, 12101, 12138, 12103, 12209, 12047, 12220, 12172, 12129, 12166, + 12242, 12237, 12145, 12106, 12081, 12244, 12038, 12086, 12055, 12181, + 12197, 12193, 12175, 12116, 12110, 12177, 12137, 12230, 12213, 12195, + 12069, 12079, 12206, 12051, 12232, 12132, 129432, 983205, 3251, 3250, + 3240, 3293, 3225, 3235, 3230, 3249, 3248, 3205, 3206, 3216, 3220, 3234, + 3233, 3239, 3238, 3232, 3231, 3237, 3236, 3211, 3296, 3212, 3297, 3253, + 3209, 3210, 3218, 3219, 3207, 3208, 3254, 3255, 3256, 3245, 3244, 3227, + 3226, 3224, 3223, 3229, 3228, 3222, 3221, 3243, 3242, 3214, 3215, 3294, + 3257, 3246, 3247, 3285, 3315, 3201, 3200, 3204, 3261, 3202, 3260, 3313, + 3314, 3277, 3203, 3286, 3262, 3272, 3276, 3267, 3268, 3298, 3299, 3265, + 3266, 3274, 3275, 3263, 3264, 3270, 3271, 3307, 3306, 3309, 3308, 3305, + 3304, 3302, 3311, 3303, 3310, 12450, 984009, 984008, 984007, 984010, + 110881, 110880, 110882, 110592, 12499, 984002, 984005, 984003, 984006, + 984004, 12496, 12505, 12508, 12502, 12511, 110583, 110584, 110585, + 110586, 110587, 110589, 110590, 110576, 110577, 110578, 110579, 110581, + 110582, 12510, 12513, 12514, 12512, 12531, 12490, 12493, 12491, 12494, + 12492, 12789, 12792, 12790, 12793, 12791, 12795, 12798, 12796, 12799, + 12797, 12533, 12534, 110933, 12784, 12787, 12483, 12526, 110949, 110948, + 110950, 12515, 12519, 12517, 110951, 12788, 12785, 12786, 12794, 12449, + 12455, 12451, 12457, 12453, 12469, 12475, 12471, 12477, 12473, 12480, + 12487, 12482, 12489, 12485, 12460, 12466, 12462, 12468, 12464, 12495, + 12504, 12498, 12507, 12501, 12459, 12465, 12461, 12467, 12463, 12497, + 12506, 12500, 12509, 12503, 12521, 12524, 12522, 12525, 12523, 12479, + 12486, 12481, 12488, 12484, 12535, 12537, 12536, 12538, 12532, 12470, + 12476, 12472, 12478, 12474, 12527, 12529, 12528, 12530, 12516, 12520, + 12518, 12456, 12452, 12458, 12454, 12542, 12543, 12541, 12539, 12448, + 12540, 12444, 12443, 73476, 73477, 73487, 73523, 73498, 73497, 73503, + 73502, 73508, 73507, 73501, 73500, 73506, 73505, 73482, 73483, 73484, + 73485, 73480, 73481, 73478, 73479, 73494, 73504, 73499, 73509, 73519, + 73520, 73521, 73513, 73512, 73496, 73495, 73493, 73492, 73491, 73490, + 73511, 73510, 73522, 73517, 73514, 73516, 73518, 73515, 73486, 73488, + 73551, 73548, 73546, 73545, 73549, 73543, 73541, 73544, 73550, 73542, + 73547, 73474, 73537, 73472, 73475, 73473, 73525, 73524, 73535, 73530, + 73534, 73536, 73528, 73529, 73526, 73527, 73540, 73539, 73557, 73556, + 73559, 73558, 73555, 73554, 73552, 73561, 73553, 73560, 73538, 43283, + 43295, 43299, 43301, 43277, 43281, 43284, 43275, 43274, 43286, 43285, + 43279, 43278, 43294, 43282, 43289, 43297, 43288, 43276, 43292, 43287, + 43290, 43296, 43293, 43291, 43280, 43298, 43300, 43310, 43311, 43308, + 43309, 43307, 43303, 43305, 43304, 43302, 43306, 43269, 43268, 43271, + 43270, 43267, 43266, 43264, 43273, 43265, 43272, 119496, 119506, 119499, + 119503, 119493, 119492, 119502, 119497, 119507, 119495, 119505, 119494, + 119504, 119501, 119491, 119500, 119490, 119498, 119488, 119489, 128331, + 8490, 128273, 9000, 128422, 983552, 983553, 983559, 983558, 983561, + 983560, 983557, 983556, 983554, 983563, 983555, 983562, 128287, 68163, + 68162, 68161, 68160, 68113, 68146, 68112, 68147, 68148, 68123, 68122, + 68128, 68127, 68126, 68121, 68131, 68125, 68124, 68130, 68129, 68141, + 68142, 68143, 68135, 68134, 68118, 68117, 68115, 68114, 68133, 68132, + 68149, 68140, 68145, 68119, 68139, 68136, 68138, 68137, 68144, 68096, + 68165, 68164, 68166, 68167, 68179, 68178, 68183, 68176, 68182, 68181, + 68184, 68180, 68177, 68152, 68153, 68109, 68154, 68111, 68110, 68099, + 68101, 68097, 68102, 68098, 68108, 68159, 68168, 129711, 101120, 101121, + 101122, 101123, 101124, 101125, 101126, 101127, 101128, 101129, 101130, + 101131, 101132, 101133, 101134, 101135, 101136, 101137, 101138, 101139, + 101140, 101141, 101142, 101143, 101144, 101145, 101146, 101147, 101148, + 101149, 101150, 101151, 101152, 101153, 101154, 101155, 101156, 101157, + 101158, 101159, 101160, 101161, 101162, 101163, 101164, 101165, 101166, + 101167, 101168, 101169, 101170, 101171, 101172, 101173, 101174, 101175, + 101176, 101177, 101178, 101179, 101180, 101181, 101182, 101183, 101184, + 101185, 101186, 101187, 101188, 101189, 101190, 101191, 101192, 101193, + 101194, 101195, 101196, 101197, 101198, 101199, 101200, 101201, 101202, + 101203, 101204, 101205, 101206, 101207, 101208, 101209, 101210, 101211, + 101212, 101213, 101214, 101215, 101216, 101217, 101218, 101219, 101220, + 101221, 101222, 101223, 101224, 101225, 101226, 101227, 101228, 101229, + 101230, 101231, 101232, 101233, 101234, 101235, 101236, 101237, 101238, + 101239, 101240, 101241, 101242, 101243, 101244, 101245, 101246, 101247, + 101248, 101249, 101250, 101251, 101252, 101253, 101254, 101255, 101256, + 101257, 101258, 101259, 101260, 101261, 101262, 101263, 101264, 101265, + 101266, 101267, 101268, 101269, 101270, 101271, 101272, 101273, 101274, + 101275, 101276, 101277, 101278, 101279, 101280, 101281, 101282, 101283, + 101284, 101285, 101286, 101287, 101288, 101289, 101290, 101291, 101292, + 101293, 101294, 101295, 101296, 101297, 101298, 101299, 101300, 101301, + 101302, 101303, 101304, 101305, 101306, 101307, 101308, 101309, 101310, + 101311, 101312, 101313, 101314, 101315, 101316, 101317, 101318, 101319, + 101320, 101321, 101322, 101323, 101324, 101325, 101326, 101327, 101328, + 101329, 101330, 101331, 101332, 101333, 101334, 101335, 101336, 101337, + 101338, 101339, 101340, 101341, 101342, 101343, 101344, 101345, 101346, + 101347, 101348, 101349, 101350, 101351, 101352, 101353, 101354, 101355, + 101356, 101357, 101358, 101359, 101360, 101361, 101362, 101363, 101364, + 101365, 101366, 101367, 101368, 101369, 101370, 101371, 101372, 101373, + 101374, 101375, 101584, 101585, 101586, 101587, 101588, 101589, 101376, + 101377, 101378, 101379, 101380, 101381, 101382, 101383, 101384, 101385, + 101386, 101387, 101388, 101389, 101390, 101391, 101392, 101393, 101394, + 101395, 101396, 101397, 101398, 101399, 101400, 101401, 101402, 101403, + 101404, 101405, 101406, 101407, 101408, 101409, 101410, 101411, 101412, + 101413, 101414, 101415, 101416, 101417, 101418, 101419, 101420, 101421, + 101422, 101423, 101424, 101425, 101426, 101427, 101428, 101429, 101430, + 101431, 101432, 101433, 101434, 101435, 101436, 101437, 101438, 101439, + 101440, 101441, 101442, 101443, 101444, 101445, 101446, 101447, 101448, + 101449, 101450, 101451, 101452, 101453, 101454, 101455, 101456, 101457, + 101458, 101459, 101460, 101461, 101462, 101463, 101464, 101465, 101466, + 101467, 101468, 101469, 101470, 101471, 101472, 101473, 101474, 101475, + 101476, 101477, 101478, 101479, 101480, 101481, 101482, 101483, 101484, + 101485, 101486, 101487, 101488, 101489, 101490, 101491, 101492, 101493, + 101494, 101495, 101496, 101497, 101498, 101499, 101500, 101501, 101502, + 101503, 101504, 101505, 101506, 101507, 101508, 101509, 101510, 101511, + 101512, 101513, 101514, 101515, 101516, 101517, 101518, 101519, 101520, + 101521, 101522, 101523, 101524, 101525, 101526, 101527, 101528, 101529, + 101530, 101531, 101532, 101533, 101534, 101535, 101536, 101537, 101538, + 101539, 101540, 101541, 101542, 101543, 101544, 101545, 101546, 101547, + 101548, 101549, 101550, 101551, 101552, 101553, 101554, 101555, 101556, + 101557, 101558, 101559, 101560, 101561, 101562, 101563, 101564, 101565, + 101566, 101567, 101568, 101569, 101570, 101571, 101572, 101573, 101574, + 101575, 101576, 101577, 101578, 101579, 101580, 101581, 101582, 101583, + 94180, 983960, 983965, 983970, 983975, 983962, 983964, 983961, 983963, + 983957, 983959, 983956, 983958, 983977, 983979, 983978, 983972, 983974, + 983967, 983969, 983971, 983973, 983966, 983968, 983989, 983983, 983985, + 983986, 983987, 983980, 983982, 983984, 983981, 983976, 983988, 6107, + 6052, 6064, 6051, 6067, 6066, 6065, 6055, 6057, 6058, 6056, 6053, 6054, + 6063, 983994, 983991, 983992, 983993, 6061, 6062, 6059, 6060, 6022, 6024, + 6021, 6023, 6017, 6019, 6016, 6018, 6020, 6030, 6025, 6035, 6037, 6039, + 6038, 6046, 6045, 6047, 6032, 6034, 6027, 6029, 6031, 6033, 6026, 6028, + 6049, 6043, 6040, 6042, 6044, 6041, 6036, 6048, 6050, 6108, 6109, 6095, + 6096, 6099, 6091, 6101, 6104, 6102, 6098, 6094, 6100, 6106, 6092, 6087, + 6093, 6090, 6103, 6105, 6088, 6086, 6089, 6097, 6652, 6636, 6655, 6639, + 6653, 6637, 6654, 6638, 6651, 6635, 6650, 6634, 6133, 6137, 6136, 6134, + 6135, 6130, 6132, 6131, 6129, 6128, 6624, 6648, 6632, 6649, 6633, 6647, + 6631, 6646, 6630, 6645, 6629, 6642, 6626, 6640, 6643, 6627, 6644, 6628, + 6641, 6625, 6069, 6068, 6070, 983996, 6082, 6083, 6085, 6071, 6080, 6072, + 6078, 983995, 6084, 6073, 6079, 6074, 983990, 6075, 6077, 6076, 6081, + 6117, 6116, 6119, 6118, 6115, 6114, 6112, 6121, 6113, 6120, 70204, 70201, + 70200, 70208, 70185, 70178, 70179, 70177, 70155, 70156, 70154, 70172, + 70167, 70166, 70173, 70171, 70161, 70160, 70144, 70145, 70149, 70151, + 70165, 70164, 70170, 70169, 70187, 70183, 70157, 70168, 70163, 70174, + 70159, 70158, 70153, 70152, 70176, 70175, 70186, 70180, 70207, 70182, + 70184, 70181, 70148, 70146, 70150, 70147, 70199, 70206, 70197, 70198, + 70196, 70203, 70209, 70188, 70193, 70195, 70189, 70190, 70192, 70194, + 70191, 70202, 70205, 70357, 70358, 70356, 70333, 70334, 70332, 70340, + 70339, 70338, 70345, 70347, 70344, 70352, 70351, 70346, 70361, 70320, + 70321, 70327, 70329, 70343, 70342, 70350, 70349, 70324, 70325, 70322, + 70323, 70335, 70348, 70341, 70353, 70337, 70336, 70331, 70330, 70355, + 70354, 70364, 70365, 70366, 70362, 70359, 70363, 70360, 70326, 70328, + 70378, 70377, 70367, 70368, 70374, 70376, 70371, 70372, 70369, 70370, + 70373, 70375, 70389, 70388, 70391, 70390, 70387, 70386, 70384, 70393, + 70385, 70392, 128143, 128535, 128537, 128538, 128573, 128139, 129373, + 8365, 128088, 129665, 129486, 129698, 12927, 128040, 11235, 129404, + 127991, 129357, 128030, 129692, 3805, 3804, 983206, 983207, 3743, 3741, + 3807, 3806, 3714, 3716, 3713, 983209, 3747, 3749, 3730, 3729, 3736, 3728, + 3727, 3731, 3726, 3744, 3721, 3718, 3724, 3756, 3740, 3742, 3739, 3752, + 3753, 3754, 3722, 3734, 3735, 3733, 3755, 3758, 3719, 3725, 3737, 3738, + 3720, 3732, 3745, 983208, 3751, 3746, 3757, 3773, 3772, 3770, 3785, 3786, + 3787, 3784, 3760, 3762, 3780, 3763, 3779, 3761, 3771, 3766, 3767, 3768, + 3769, 3776, 3777, 3764, 3765, 3778, 3782, 3790, 3759, 3797, 3796, 3799, + 3798, 3795, 3794, 3792, 3801, 3793, 3800, 3788, 3789, 128996, 129003, + 128309, 128311, 128998, 128994, 129001, 68413, 68415, 128992, 128310, + 128999, 68412, 68414, 11004, 10201, 10200, 10782, 128995, 129002, 128308, + 128997, 128993, 129000, 9711, 10923, 10925, 8382, 9790, 127772, 127767, + 65, 258, 7858, 7856, 7854, 7862, 7860, 550, 480, 7840, 512, 196, 478, + 197, 506, 7680, 256, 983564, 194, 7848, 7846, 7844, 7852, 7850, 461, + 7842, 260, 983590, 983592, 192, 193, 514, 195, 570, 198, 508, 482, 42946, + 11373, 393, 42808, 42810, 42802, 42804, 42806, 42812, 66, 386, 42902, + 7686, 7684, 7682, 385, 579, 42822, 42932, 67, 199, 7688, 264, 268, 262, + 42948, 391, 42898, 266, 571, 42960, 42796, 42798, 42862, 42931, 68, 498, + 453, 42951, 272, 7696, 7698, 270, 395, 7694, 7692, 7690, 394, 497, 452, + 69, 552, 7708, 202, 983586, 7874, 7872, 7870, 983584, 7878, 7876, 7704, + 282, 278, 983598, 983600, 7864, 516, 203, 7868, 7706, 274, 7700, 7702, + 983570, 983572, 983574, 7866, 280, 983594, 983596, 200, 201, 518, 276, + 582, 439, 494, 440, 42786, 42788, 42858, 208, 425, 330, 70, 401, 7710, + 42904, 71, 290, 284, 486, 500, 286, 7712, 42912, 403, 288, 484, 577, + 42938, 42940, 42942, 404, 983199, 72, 7722, 7720, 292, 542, 7718, 11367, + 7716, 7714, 42922, 294, 11381, 502, 42790, 73, 520, 7882, 304, 207, 7726, + 206, 463, 298, 983566, 296, 7724, 7880, 302, 983604, 983606, 204, 205, + 522, 300, 407, 42873, 42875, 42877, 42882, 42884, 42886, 406, 42860, 74, + 308, 42930, 983608, 584, 75, 310, 488, 42818, 11369, 7730, 42816, 42820, + 7728, 7732, 42914, 408, 76, 42925, 573, 11360, 7734, 7736, 11362, 319, + 456, 321, 315, 7740, 317, 42824, 313, 7738, 983610, 455, 77, 7742, 7746, + 7744, 983612, 11374, 7930, 7932, 42966, 78, 325, 7754, 327, 459, 544, + 7752, 413, 504, 323, 42896, 7750, 7748, 42916, 209, 458, 79, 42826, + 42828, 332, 7760, 7762, 415, 212, 7892, 7890, 7888, 7896, 7894, 465, 214, + 554, 558, 560, 7884, 524, 336, 490, 492, 216, 510, 213, 7758, 7756, 556, + 983576, 983578, 983580, 416, 7902, 7900, 7898, 7906, 7904, 7886, 210, + 211, 526, 334, 42944, 400, 390, 42934, 418, 42830, 546, 80, 42834, 11363, + 42832, 42836, 7764, 420, 7766, 81, 42840, 42838, 82, 342, 344, 7770, + 7772, 7768, 528, 11364, 983614, 340, 7774, 530, 42918, 588, 42842, 42997, + 42923, 42814, 398, 42844, 83, 352, 7782, 350, 536, 348, 346, 7780, 7778, + 7784, 7776, 42953, 11390, 983582, 42920, 42949, 586, 42926, 42891, 7838, + 42968, 42924, 399, 84, 354, 7792, 538, 356, 574, 7788, 7786, 7790, 430, + 428, 358, 42878, 11375, 11376, 42893, 42928, 42880, 412, 42929, 581, 222, + 42852, 42854, 388, 423, 444, 42794, 42792, 85, 219, 7798, 467, 220, 473, + 475, 471, 469, 7794, 532, 368, 7908, 431, 7916, 7914, 7912, 7920, 7918, + 7910, 362, 7802, 983568, 983620, 983622, 370, 983616, 983618, 360, 7800, + 7796, 217, 218, 534, 364, 366, 42936, 580, 433, 86, 42846, 7806, 7804, + 434, 42850, 42906, 42908, 42910, 42856, 42848, 87, 372, 7812, 7816, 7814, + 7808, 7810, 11378, 503, 88, 7820, 7818, 89, 374, 376, 7924, 7822, 7922, + 435, 7926, 7934, 221, 562, 7928, 590, 540, 90, 7824, 381, 377, 11371, + 7826, 379, 7828, 11391, 437, 42950, 548, 306, 338, 10013, 43007, 43005, + 43006, 43003, 43004, 42999, 450, 7461, 684, 664, 685, 662, 122638, 446, + 426, 674, 451, 122634, 7431, 7430, 7459, 618, 641, 671, 122628, 7436, + 7439, 7440, 630, 7445, 640, 7438, 7449, 43846, 42870, 7451, 11387, + 122626, 122640, 43002, 7450, 665, 7427, 610, 667, 7424, 7425, 7428, 7429, + 42800, 668, 7434, 7435, 7437, 628, 7448, 42927, 42801, 7452, 7456, 7457, + 655, 7458, 663, 122639, 42895, 447, 443, 448, 449, 660, 673, 661, 7460, + 422, 7547, 7550, 97, 259, 7859, 7857, 7855, 7863, 7861, 551, 481, 7841, + 513, 228, 479, 229, 507, 7681, 7834, 7567, 257, 983565, 226, 7849, 7847, + 7845, 7853, 7851, 462, 7843, 261, 983591, 983593, 224, 225, 515, 227, + 11365, 43825, 230, 983624, 509, 483, 42947, 593, 7568, 42809, 42811, + 42803, 42805, 42807, 42813, 98, 387, 42903, 7687, 7532, 7552, 7685, 7683, + 595, 384, 43824, 43827, 629, 43853, 43837, 43838, 43826, 42823, 7447, + 42933, 99, 231, 7689, 265, 597, 269, 263, 42900, 122653, 392, 42899, 267, + 572, 43859, 43860, 43861, 42961, 666, 631, 606, 42797, 42799, 42863, 100, + 42952, 273, 396, 598, 7697, 7699, 545, 271, 122661, 7533, 7695, 599, + 7569, 7553, 7693, 7691, 676, 122642, 122649, 7839, 567, 607, 644, 305, + 42965, 43848, 43850, 42963, 499, 454, 675, 677, 43878, 568, 42865, 101, + 553, 7709, 234, 983587, 7875, 7873, 7871, 983585, 7879, 7877, 7705, 283, + 279, 983599, 983601, 7865, 517, 235, 11384, 7869, 7707, 275, 7701, 7703, + 983571, 983573, 983575, 43828, 7867, 281, 983595, 983597, 232, 233, 519, + 277, 7570, 583, 42787, 42789, 331, 43836, 122644, 643, 122635, 122636, + 7563, 646, 7576, 658, 441, 659, 495, 122648, 7578, 442, 42859, 240, 102, + 7534, 7554, 402, 7711, 42905, 681, 122624, 103, 291, 285, 487, 501, 287, + 7713, 7555, 42913, 608, 289, 485, 578, 42939, 42941, 42943, 611, 983200, + 104, 7723, 7721, 293, 543, 7719, 11368, 7717, 7715, 7830, 42901, 614, + 295, 11382, 983631, 983632, 42791, 615, 405, 105, 238, 464, 239, 7727, + 983602, 983588, 983603, 7883, 521, 299, 983567, 303, 983605, 983607, 297, + 7725, 7881, 236, 237, 523, 301, 616, 122650, 7574, 42874, 42876, 7545, + 42883, 42885, 42887, 43876, 43840, 617, 7548, 43873, 42861, 106, 309, + 669, 496, 983609, 585, 107, 311, 489, 42819, 11370, 7731, 42817, 42821, + 7729, 7733, 7556, 42915, 409, 312, 108, 620, 122643, 410, 316, 7741, 564, + 318, 7735, 7737, 43832, 11361, 619, 43833, 320, 122662, 42825, 314, 7739, + 43831, 621, 42894, 122641, 7557, 983611, 322, 411, 622, 122629, 43829, + 383, 7836, 7835, 7837, 682, 683, 42866, 457, 109, 7743, 43834, 7535, + 7558, 7747, 7745, 983613, 625, 7931, 7933, 42967, 42867, 110, 326, 7755, + 43835, 565, 328, 414, 7753, 626, 122663, 7536, 505, 324, 42897, 7751, + 7749, 7559, 627, 42917, 241, 329, 983589, 42868, 460, 111, 244, 7893, + 7891, 7889, 7897, 7895, 466, 246, 555, 559, 561, 7885, 525, 337, 42827, + 11386, 42829, 333, 7761, 7763, 491, 493, 248, 511, 245, 7759, 7757, 557, + 983577, 983579, 983581, 417, 7903, 7901, 7899, 7907, 7905, 7887, 242, + 243, 527, 335, 122651, 42945, 596, 983625, 983626, 7575, 43839, 43874, + 603, 7571, 42935, 419, 42831, 547, 112, 42835, 7549, 42833, 42837, 7765, + 7537, 7560, 421, 7767, 632, 113, 42841, 672, 587, 42839, 569, 114, 343, + 43849, 345, 7771, 7773, 7769, 529, 638, 7539, 122646, 7775, 636, 637, + 983615, 122664, 7538, 341, 531, 7561, 42919, 589, 43847, 42843, 42998, + 604, 7572, 605, 639, 122625, 600, 122631, 8580, 42815, 122627, 42869, + 42845, 612, 115, 347, 7781, 353, 7783, 351, 537, 349, 122654, 7779, 7785, + 7777, 42954, 575, 983583, 122665, 7540, 7562, 42921, 642, 42892, 43872, + 601, 983629, 983630, 7573, 602, 43851, 43852, 609, 43830, 223, 7441, + 7442, 7443, 7455, 7454, 7453, 42969, 645, 43845, 116, 355, 7793, 539, + 566, 357, 11366, 7831, 7789, 7787, 122666, 7541, 7791, 427, 429, 122633, + 648, 359, 679, 122647, 122652, 7546, 254, 42853, 42855, 389, 424, 445, + 7446, 42795, 397, 613, 686, 687, 7433, 42879, 7444, 43842, 43841, 43843, + 43844, 7432, 633, 43880, 122645, 634, 122632, 11385, 635, 647, 122637, + 652, 983627, 983628, 592, 594, 7426, 623, 624, 654, 122630, 43857, 477, + 7543, 670, 42881, 653, 42871, 680, 678, 43879, 11383, 42793, 117, 649, + 43855, 251, 7799, 468, 252, 474, 476, 472, 470, 7795, 533, 369, 7909, + 432, 7917, 7915, 7913, 7921, 7919, 7911, 363, 7803, 983569, 983621, + 983623, 371, 983617, 983619, 7577, 367, 361, 7801, 7797, 249, 43854, + 42937, 250, 535, 365, 43858, 650, 7551, 7531, 43856, 42872, 43875, 118, + 42847, 7807, 7564, 11380, 11377, 7805, 651, 42851, 42907, 42909, 42911, + 42857, 42849, 119, 373, 7813, 7817, 7815, 7809, 7811, 7832, 11379, 120, + 7821, 7819, 43863, 43864, 43865, 43862, 7565, 121, 375, 255, 7925, 7823, + 7923, 436, 7927, 7935, 43866, 591, 253, 563, 7929, 7833, 541, 122, 378, + 7825, 657, 382, 11372, 7827, 380, 7829, 576, 438, 7542, 7566, 656, 549, + 64256, 64259, 64260, 64257, 64258, 307, 64261, 64262, 339, 8347, 8340, + 8336, 8337, 8341, 7522, 11388, 8342, 8343, 8344, 8345, 8338, 8346, 7523, + 8348, 7524, 7525, 8339, 917505, 127811, 129388, 129897, 129916, 129899, + 129917, 129947, 10203, 10202, 128494, 12296, 10641, 10643, 11058, 11056, + 10576, 10571, 10570, 10574, 12304, 10647, 123, 9128, 9129, 9127, 12300, + 8968, 9948, 10714, 12298, 8220, 11816, 11780, 129287, 129284, 129285, + 129283, 129286, 9686, 11240, 9612, 129977, 129970, 129940, 129932, + 128379, 128709, 11804, 10204, 10197, 9614, 9615, 8596, 8700, 8697, 8622, + 10568, 8660, 10500, 8654, 8621, 11012, 8703, 11020, 129112, 11108, 11788, + 10181, 8907, 9609, 8216, 11814, 128488, 91, 9123, 9121, 10639, 10637, + 8261, 10635, 11863, 11861, 9122, 11778, 10703, 129900, 11785, 129985, + 128492, 9613, 9610, 12308, 8867, 12302, 10627, 12310, 10629, 12314, + 12312, 10712, 128398, 9611, 10620, 8970, 8905, 40, 9117, 9115, 9116, + 11808, 9144, 10553, 10154, 1422, 4054, 4056, 129307, 9958, 10748, 9001, + 171, 128269, 8294, 8237, 8234, 8206, 8592, 10563, 11074, 11083, 11082, + 10611, 129973, 10618, 10615, 11070, 8676, 8633, 10525, 11064, 8698, + 129032, 8619, 10566, 129040, 129024, 8602, 11024, 11025, 8610, 11066, + 11065, 129028, 129176, 129044, 8617, 8695, 8612, 10527, 8646, 10521, + 129192, 129184, 11144, 11013, 10603, 10599, 10590, 10582, 8637, 10594, + 10602, 10598, 10586, 10578, 8636, 8651, 129778, 129088, 129092, 11104, + 11136, 11130, 983241, 11174, 11172, 129064, 129060, 129056, 129072, + 129068, 11120, 11114, 11140, 129168, 10510, 8666, 129186, 11067, 11069, + 11068, 11244, 11061, 11060, 11062, 11063, 8606, 8678, 129172, 8604, 8656, + 10498, 8653, 10502, 10523, 10508, 8672, 129194, 129076, 129188, 8701, + 8647, 129783, 129190, 128620, 8668, 129080, 129104, 129084, 11077, 9804, + 128006, 7213, 7221, 7216, 7220, 7215, 7214, 7217, 7218, 7219, 7170, 7169, + 7168, 7184, 7183, 7182, 7247, 7193, 7180, 7188, 7187, 7186, 7185, 7172, + 7171, 7198, 7197, 7190, 7189, 7173, 7177, 7181, 7192, 7191, 7246, 7245, + 7179, 7178, 7175, 7174, 7201, 7200, 7176, 7196, 7195, 7199, 7202, 7194, + 7203, 7227, 7231, 7230, 7228, 7229, 7223, 7222, 7205, 7204, 7210, 7211, + 7208, 7209, 7206, 7212, 7207, 7237, 7236, 7239, 7238, 7235, 7234, 7232, + 7241, 7233, 7240, 10897, 10895, 10893, 10899, 10891, 10614, 10889, 10887, + 8922, 8934, 8808, 10918, 10920, 10885, 10877, 10881, 10883, 10879, 8818, + 8804, 8822, 8806, 10873, 10875, 8918, 60, 128210, 127898, 127819, 129461, + 128626, 128955, 128969, 128943, 11212, 128964, 10099, 128648, 10098, + 9617, 128937, 128949, 128978, 128960, 129653, 128910, 10072, 128930, + 128504, 9735, 128498, 128497, 6429, 6404, 6403, 6412, 6430, 6411, 6421, + 6410, 6405, 6415, 6425, 6426, 6427, 6419, 6418, 6407, 6406, 6414, 6413, + 6409, 6408, 6402, 6401, 6417, 6416, 6428, 6423, 6420, 6422, 6424, 6458, + 6457, 6459, 6464, 6449, 6452, 6450, 6448, 6456, 6454, 6453, 6455, 6451, + 6442, 6443, 6441, 6432, 6436, 6438, 6440, 6437, 6439, 6435, 6433, 6434, + 6400, 6468, 6469, 6475, 6474, 6477, 6476, 6473, 6472, 6470, 6479, 6471, + 6478, 13007, 10770, 10771, 10772, 983062, 8232, 983068, 983143, 67143, + 67146, 67151, 67165, 67166, 67167, 67157, 67158, 67159, 67160, 67161, + 67162, 67163, 67164, 67171, 67172, 67173, 67168, 67169, 67170, 67174, + 67175, 67176, 67177, 67178, 67179, 67230, 67231, 67180, 67181, 67182, + 67183, 67184, 67185, 67186, 67187, 67188, 67189, 67190, 67191, 67192, + 67193, 67194, 67195, 67196, 67197, 67198, 67199, 67200, 67201, 67202, + 67203, 67204, 67205, 67206, 67207, 67208, 67209, 67210, 67211, 67212, + 67213, 67214, 67215, 67216, 67217, 67218, 67219, 67220, 67221, 67222, + 67223, 67224, 67225, 67226, 67227, 67228, 67229, 67232, 67233, 67234, + 67235, 67236, 67237, 67238, 67239, 67240, 67241, 67242, 67243, 67244, + 67245, 67246, 67247, 67248, 67249, 67250, 67251, 67252, 67253, 67254, + 67255, 67256, 67257, 67258, 67259, 67260, 67261, 67262, 67263, 67264, + 67274, 67275, 67276, 67277, 67278, 67279, 67280, 67281, 67282, 67283, + 67284, 67285, 67286, 67287, 67288, 67289, 67290, 67291, 67292, 67293, + 67294, 67295, 67296, 67297, 67298, 67299, 67300, 67301, 67302, 67303, + 67304, 67265, 67266, 67267, 67268, 67269, 67270, 67271, 67272, 67273, + 67325, 67326, 67327, 67328, 67329, 67330, 67305, 67306, 67307, 67308, + 67309, 67310, 67311, 67312, 67313, 67314, 67315, 67316, 67317, 67318, + 67319, 67320, 67321, 67322, 67323, 67324, 67331, 67332, 67333, 67334, + 67335, 67336, 67337, 67338, 67349, 67350, 67351, 67352, 67353, 67354, + 67355, 67356, 67357, 67358, 67359, 67360, 67361, 67362, 67363, 67364, + 67365, 67366, 67367, 67368, 67378, 67379, 67380, 67381, 67382, 67369, + 67370, 67371, 67372, 67373, 67374, 67375, 67376, 67377, 67339, 67340, + 67341, 67342, 67343, 67344, 67345, 67346, 67347, 67348, 67401, 67404, + 67403, 67402, 67400, 67398, 67393, 67397, 67395, 67394, 67399, 67392, + 67396, 67406, 67408, 67409, 67410, 67407, 67405, 67411, 67413, 67412, + 67424, 67425, 67426, 67427, 67428, 67429, 67430, 67431, 67081, 67082, + 67083, 67084, 67085, 67087, 67088, 67089, 67090, 67091, 67092, 67093, + 67094, 67086, 67095, 67096, 67097, 67098, 67100, 67101, 67102, 67103, + 67104, 67105, 67106, 67107, 67108, 67109, 67110, 67111, 67112, 67113, + 67114, 67115, 67116, 67117, 67118, 67119, 67120, 67121, 67122, 67123, + 67124, 67125, 67126, 67127, 67128, 67129, 67130, 67131, 67132, 67133, + 67134, 67135, 67136, 67137, 67138, 67139, 67140, 67141, 67142, 67072, + 67073, 67074, 67075, 67076, 67077, 67078, 67079, 67080, 67145, 67147, + 67148, 67149, 67150, 67154, 67155, 67144, 67152, 67153, 67156, 67099, + 65667, 65668, 65669, 65670, 65671, 65672, 65673, 65675, 65674, 65677, + 65676, 65665, 65664, 65666, 65681, 65679, 65680, 65682, 65678, 65686, + 65685, 65687, 65693, 65690, 65691, 65692, 65694, 65703, 65696, 65695, + 65697, 65698, 65699, 65701, 65702, 65707, 65706, 65704, 65705, 65708, + 65709, 65710, 65711, 65712, 65713, 65719, 65717, 65714, 65715, 65716, + 65718, 65720, 65721, 65722, 65723, 65724, 65725, 65726, 65727, 65728, + 65729, 65731, 65730, 65732, 65733, 65737, 65734, 65735, 65736, 65738, + 65739, 65740, 65741, 65743, 65742, 65744, 65745, 65747, 65748, 65752, + 65749, 65750, 65751, 65753, 65754, 65755, 65756, 65757, 65779, 65780, + 65781, 65782, 65783, 65784, 65785, 65759, 65760, 65761, 65762, 65763, + 65764, 65765, 65766, 65767, 65768, 65769, 65770, 65771, 65772, 65773, + 65774, 65775, 65776, 65777, 65778, 65758, 65786, 65683, 65684, 65689, + 65688, 65700, 65746, 65561, 65543, 65587, 65582, 65589, 65536, 65541, + 65579, 65566, 65571, 65596, 65569, 65584, 65544, 65559, 65540, 65557, + 65560, 65580, 65606, 65600, 65599, 65577, 65562, 65538, 65573, 65563, + 65609, 65588, 65549, 65568, 65537, 65581, 65574, 65601, 65542, 65593, + 65583, 65594, 65552, 65547, 65605, 65578, 65545, 65585, 65586, 65546, + 65570, 65591, 65564, 65565, 65607, 65610, 65611, 65553, 65590, 65550, + 65539, 65576, 65608, 65551, 65554, 65592, 65603, 65597, 65567, 65572, + 65558, 65555, 65612, 65602, 65556, 65613, 65604, 65620, 65621, 65623, + 65624, 65626, 65627, 65628, 65629, 65622, 65616, 65617, 65619, 65618, + 65625, 128391, 128279, 128482, 128132, 42237, 42235, 42232, 42234, 42236, + 42233, 42206, 42205, 42197, 42196, 42204, 42195, 42228, 42229, 42230, + 42224, 42225, 42213, 42208, 42203, 42202, 42221, 42198, 42216, 42214, + 42200, 42199, 42194, 42193, 42219, 42210, 73648, 42220, 42211, 42212, + 42222, 42223, 42227, 42231, 42192, 42217, 42201, 42209, 42207, 42218, + 42215, 42226, 42238, 42239, 8356, 8374, 129409, 129422, 9806, 128274, + 983079, 983076, 128271, 8743, 10848, 10846, 10833, 10844, 10842, 10847, + 8744, 10841, 10851, 10850, 10834, 10845, 10843, 10982, 10188, 129688, + 10234, 10231, 10206, 10229, 10235, 10232, 10237, 11059, 10230, 10236, + 10233, 10238, 10239, 10205, 129524, 128884, 129719, 128140, 127977, + 128261, 129707, 12319, 8270, 11847, 11848, 95, 9691, 129935, 9604, 9697, + 128394, 129852, 129853, 129870, 129872, 129868, 129856, 129871, 129869, + 129854, 129873, 129855, 128395, 128396, 128393, 10559, 129951, 9722, + 128397, 9695, 10558, 128318, 10065, 129950, 9727, 129863, 129865, 129867, + 129864, 129861, 129866, 129859, 129862, 129860, 129857, 129858, 10195, + 10063, 9998, 9694, 9987, 9605, 9602, 9601, 9607, 9603, 9606, 129903, + 9674, 10208, 129438, 128557, 127853, 129523, 128886, 129729, 66190, + 66192, 66187, 66196, 66178, 66179, 66199, 66185, 66200, 66176, 66201, + 66177, 66202, 66191, 66193, 66181, 66180, 66203, 66182, 66186, 66189, + 66195, 66188, 66197, 66198, 66194, 66183, 66204, 66184, 67887, 67892, + 67881, 67895, 67891, 67886, 67872, 67893, 67876, 67894, 67883, 67896, + 67873, 67897, 67875, 67889, 67874, 67878, 67880, 67882, 67884, 67890, + 67885, 67888, 67877, 67879, 67903, 129317, 983226, 983234, 983224, + 983229, 8468, 129433, 983065, 129668, 129522, 129497, 69986, 69981, + 69991, 70002, 69997, 69985, 69984, 69990, 69989, 69983, 69982, 69988, + 69987, 69995, 69994, 69978, 69977, 69976, 69975, 69980, 69979, 69974, + 69973, 69993, 69992, 70001, 69998, 69996, 70000, 69999, 69968, 69971, + 69969, 69972, 69970, 70006, 70005, 70003, 70004, 127012, 127019, 127008, + 126990, 126999, 126976, 127005, 126987, 126996, 127004, 126986, 126995, + 126979, 127009, 126991, 127000, 127001, 126983, 126992, 127011, 127010, + 126977, 127007, 126989, 126998, 127006, 126988, 126997, 127015, 127014, + 127003, 126985, 126994, 127002, 126984, 126993, 126978, 126982, 127017, + 126981, 126980, 127016, 127018, 127013, 73464, 73442, 73451, 73448, + 73444, 73449, 73447, 73441, 73450, 73440, 73454, 73445, 73443, 73453, + 73456, 73446, 73455, 73452, 73457, 73463, 73461, 73459, 73462, 73460, + 73458, 128892, 3415, 3449, 3435, 3434, 3437, 3436, 3433, 3432, 3430, + 3439, 3431, 3438, 3419, 3420, 3446, 3417, 3422, 3416, 3447, 3444, 3443, + 3448, 3418, 3421, 3445, 3333, 3423, 3334, 3344, 3348, 3453, 3454, 3414, + 3451, 3450, 3452, 3455, 3412, 3413, 3355, 3354, 3406, 3362, 3361, 3367, + 3366, 3360, 3386, 3359, 3365, 3364, 3332, 3339, 3424, 3340, 3425, 3381, + 3369, 3363, 3353, 3358, 3368, 3380, 3379, 3378, 3377, 3376, 3337, 3338, + 3346, 3347, 3335, 3336, 3382, 3383, 3384, 3373, 3372, 3352, 3351, 3357, + 3356, 3350, 3349, 3371, 3370, 3342, 3343, 3385, 3374, 3375, 3441, 3442, + 3440, 3328, 3388, 3329, 3387, 3405, 3331, 3389, 3330, 3407, 3390, 3400, + 3404, 3395, 3396, 3426, 3427, 3393, 3394, 3402, 3403, 3391, 3392, 3398, + 3399, 9895, 9894, 9893, 9794, 10016, 129443, 128104, 128372, 129333, + 128114, 128115, 128378, 128107, 2122, 2121, 2133, 2120, 2126, 2132, 2129, + 2136, 2113, 2115, 2114, 2116, 2123, 2124, 2125, 2128, 2130, 2131, 2118, + 2134, 2117, 2112, 2127, 2119, 2135, 2139, 2138, 2142, 2137, 68288, 68314, + 68313, 68290, 68289, 68293, 68308, 68292, 68291, 68300, 68299, 68298, + 68297, 68306, 68304, 68320, 68318, 68323, 68312, 68317, 68322, 68309, + 68302, 68324, 68305, 68319, 68307, 68321, 68303, 68294, 68301, 68311, + 68295, 68316, 68315, 68310, 68331, 68335, 68334, 68333, 68332, 68340, + 68339, 68338, 68342, 68337, 68341, 68336, 68296, 68326, 68325, 128094, + 129469, 8380, 128368, 129389, 9967, 127809, 129671, 72835, 72834, 72827, + 72826, 72836, 72828, 72821, 72825, 72829, 72823, 72822, 72819, 72818, + 72831, 72830, 72844, 72845, 72838, 72839, 72840, 72832, 72820, 72846, + 72824, 72843, 72833, 72842, 72837, 72841, 72847, 72886, 72885, 72867, + 72866, 72859, 72858, 72868, 72860, 72853, 72857, 72861, 72855, 72854, + 72851, 72850, 72863, 72862, 72876, 72877, 72870, 72871, 72864, 72852, + 72878, 72856, 72875, 72865, 72874, 72869, 72873, 72879, 72880, 72883, + 72881, 72884, 72882, 72816, 72817, 9901, 129355, 73007, 72980, 72979, + 72983, 72982, 72988, 73008, 72987, 72960, 72961, 72968, 72971, 72985, + 72984, 72990, 72989, 72964, 72965, 72962, 72963, 73005, 72999, 73006, + 72973, 72972, 72976, 72986, 72981, 72991, 73001, 73002, 73003, 72995, + 72994, 72978, 72977, 72975, 72974, 72993, 72992, 73004, 72996, 72998, + 73000, 72997, 72966, 72969, 73031, 73030, 73027, 73028, 73026, 73025, + 73024, 73014, 73009, 73020, 73023, 73012, 73013, 73010, 73011, 73018, + 73021, 73029, 73045, 73044, 73047, 73046, 73043, 73042, 73040, 73049, + 73041, 73048, 186, 127405, 12348, 119811, 120778, 120491, 119827, 120495, + 120505, 120507, 119808, 120488, 119809, 120489, 119833, 120493, 119812, + 120492, 120494, 119814, 120490, 119816, 120496, 119818, 120497, 119819, + 120498, 119822, 120502, 120512, 119823, 120509, 120511, 120503, 119825, + 120504, 119826, 120506, 119828, 120508, 119810, 120510, 119820, 120499, + 119821, 120500, 119831, 120501, 119813, 119815, 119817, 119824, 119829, + 119830, 119832, 119837, 120779, 120517, 119834, 120514, 119835, 120515, + 119859, 120519, 119838, 120518, 120520, 119839, 120531, 119840, 120516, + 119842, 120522, 119844, 120523, 119845, 120524, 119848, 120528, 120538, + 119849, 120535, 120537, 120529, 119851, 120530, 119852, 120532, 119853, + 120521, 120533, 119854, 120534, 119836, 120536, 119846, 120525, 119847, + 120526, 119857, 120527, 119841, 119843, 119850, 119855, 119856, 119858, + 120016, 120017, 120018, 120019, 120020, 120021, 120022, 120023, 120024, + 120025, 120026, 120027, 120028, 120029, 120030, 120031, 120032, 120033, + 120034, 120035, 120036, 120037, 120038, 120039, 120040, 120041, 120042, + 120043, 120044, 120045, 120046, 120047, 120048, 120049, 120050, 120051, + 120052, 120053, 120054, 120055, 120056, 120057, 120058, 120059, 120060, + 120061, 120062, 120063, 120064, 120065, 120066, 120067, 119931, 120611, + 120621, 120623, 119912, 120604, 119913, 120605, 119937, 120609, 119915, + 120607, 119916, 120608, 120610, 119918, 120606, 119920, 120612, 119922, + 120613, 119923, 120614, 119926, 120618, 120628, 119927, 120625, 120627, + 120619, 119929, 120620, 119930, 120622, 119932, 120624, 119914, 120626, + 119924, 120615, 119925, 120616, 119935, 120617, 119917, 119919, 119921, + 119928, 119933, 119934, 119936, 120656, 120658, 120629, 120659, 120655, + 120661, 120660, 119938, 120630, 119939, 120631, 119963, 120635, 119941, + 120633, 119942, 120634, 120636, 119943, 120647, 119944, 120632, 119946, + 120638, 119948, 120639, 119949, 120640, 119952, 120644, 120654, 119953, + 120651, 120653, 120645, 119955, 120646, 119956, 120648, 119957, 120637, + 120649, 119958, 120650, 119940, 120652, 119950, 120641, 119951, 120642, + 119961, 120643, 119945, 119947, 119954, 119959, 119960, 119962, 120657, + 120540, 120542, 120513, 120543, 120539, 120545, 120544, 120541, 120172, + 120173, 120174, 120175, 120176, 120177, 120178, 120179, 120180, 120181, + 120182, 120183, 120184, 120185, 120186, 120187, 120188, 120189, 120190, + 120191, 120192, 120193, 120194, 120195, 120196, 120197, 120198, 120199, + 120200, 120201, 120202, 120203, 120204, 120205, 120206, 120207, 120208, + 120209, 120210, 120211, 120212, 120213, 120214, 120215, 120216, 120217, + 120218, 120219, 120220, 120221, 120222, 120223, 120787, 120786, 120789, + 120788, 120785, 120784, 120782, 120791, 120783, 120790, 120120, 120121, + 120123, 120124, 120125, 120126, 120128, 120129, 120130, 120131, 120132, + 120134, 120138, 120139, 120140, 120141, 120142, 120143, 120144, 120146, + 120147, 120148, 120149, 120150, 120151, 120152, 120153, 120154, 120155, + 120156, 120157, 120158, 120159, 120160, 120161, 120162, 120163, 120164, + 120165, 120166, 120167, 120168, 120169, 120170, 120171, 120797, 120796, + 120799, 120798, 120795, 120794, 120792, 120801, 120793, 120800, 120068, + 120069, 120071, 120072, 120073, 120074, 120077, 120078, 120079, 120080, + 120081, 120082, 120083, 120084, 120086, 120087, 120088, 120089, 120090, + 120091, 120092, 120094, 120095, 120096, 120097, 120098, 120099, 120100, + 120101, 120102, 120103, 120104, 120105, 120106, 120107, 120108, 120109, + 120110, 120111, 120112, 120113, 120114, 120115, 120116, 120117, 120118, + 120119, 10189, 119889, 120484, 120485, 120575, 119886, 120572, 119887, + 120573, 119911, 120577, 119890, 120576, 120578, 119891, 120589, 119892, + 120574, 119894, 120580, 119896, 120581, 119897, 120582, 119900, 120586, + 120596, 119901, 120593, 120595, 120587, 119903, 120588, 119904, 120590, + 119905, 120579, 120591, 119906, 120592, 119888, 120594, 119898, 120583, + 119899, 120584, 119909, 120585, 119895, 119902, 119907, 119908, 119910, + 119879, 120553, 120563, 120565, 119860, 120546, 119861, 120547, 119885, + 120551, 119863, 120549, 119864, 120550, 120552, 119866, 120548, 119868, + 120554, 119870, 120555, 119871, 120556, 119874, 120560, 120570, 119875, + 120567, 120569, 120561, 119877, 120562, 119878, 120564, 119880, 120566, + 119862, 120568, 119872, 120557, 119873, 120558, 119883, 120559, 119865, + 119867, 119869, 119876, 119881, 119882, 119884, 120598, 120600, 120571, + 120601, 120597, 120603, 120602, 120599, 120432, 120433, 120434, 120435, + 120436, 120437, 120438, 120439, 120440, 120441, 120442, 120443, 120444, + 120445, 120446, 120447, 120448, 120449, 120450, 120451, 120452, 120453, + 120454, 120455, 120456, 120457, 120458, 120459, 120460, 120461, 120462, + 120463, 120464, 120465, 120466, 120467, 120468, 120469, 120470, 120471, + 120472, 120473, 120474, 120475, 120476, 120477, 120478, 120479, 120480, + 120481, 120482, 120483, 120827, 120826, 120829, 120828, 120825, 120824, + 120822, 120831, 120823, 120830, 10215, 10221, 10219, 10217, 10223, 10187, + 10214, 10220, 10218, 10216, 10222, 120399, 120727, 120737, 120739, + 120380, 120720, 120381, 120721, 120405, 120725, 120383, 120723, 120384, + 120724, 120726, 120386, 120722, 120388, 120728, 120390, 120729, 120391, + 120730, 120394, 120734, 120744, 120395, 120741, 120743, 120735, 120397, + 120736, 120398, 120738, 120400, 120740, 120382, 120742, 120392, 120731, + 120393, 120732, 120403, 120733, 120385, 120387, 120389, 120396, 120401, + 120402, 120404, 120772, 120774, 120745, 120775, 120771, 120777, 120776, + 120406, 120746, 120407, 120747, 120431, 120751, 120409, 120749, 120410, + 120750, 120752, 120411, 120763, 120412, 120748, 120414, 120754, 120416, + 120755, 120417, 120756, 120420, 120760, 120770, 120421, 120767, 120769, + 120761, 120423, 120762, 120424, 120764, 120425, 120753, 120765, 120426, + 120766, 120408, 120768, 120418, 120757, 120419, 120758, 120429, 120759, + 120413, 120415, 120422, 120427, 120428, 120430, 120773, 120295, 120669, + 120679, 120681, 120276, 120662, 120277, 120663, 120301, 120667, 120279, + 120665, 120280, 120666, 120668, 120282, 120664, 120284, 120670, 120286, + 120671, 120287, 120672, 120290, 120676, 120686, 120291, 120683, 120685, + 120677, 120293, 120678, 120294, 120680, 120296, 120682, 120278, 120684, + 120288, 120673, 120289, 120674, 120299, 120675, 120281, 120283, 120285, + 120292, 120297, 120298, 120300, 120714, 120716, 120687, 120717, 120713, + 120719, 120718, 120302, 120688, 120303, 120689, 120327, 120693, 120305, + 120691, 120306, 120692, 120694, 120307, 120705, 120308, 120690, 120310, + 120696, 120312, 120697, 120313, 120698, 120316, 120702, 120712, 120317, + 120709, 120711, 120703, 120319, 120704, 120320, 120706, 120321, 120695, + 120707, 120322, 120708, 120304, 120710, 120314, 120699, 120315, 120700, + 120325, 120701, 120309, 120311, 120318, 120323, 120324, 120326, 120715, + 120817, 120816, 120819, 120818, 120815, 120814, 120812, 120821, 120813, + 120820, 120328, 120329, 120330, 120331, 120332, 120333, 120334, 120335, + 120336, 120337, 120338, 120339, 120340, 120341, 120342, 120343, 120344, + 120345, 120346, 120347, 120348, 120349, 120350, 120351, 120352, 120353, + 120354, 120355, 120356, 120357, 120358, 120359, 120360, 120361, 120362, + 120363, 120364, 120365, 120366, 120367, 120368, 120369, 120370, 120371, + 120372, 120373, 120374, 120375, 120376, 120377, 120378, 120379, 120224, + 120225, 120226, 120227, 120228, 120229, 120230, 120231, 120232, 120233, + 120234, 120235, 120236, 120237, 120238, 120239, 120240, 120241, 120242, + 120243, 120244, 120245, 120246, 120247, 120248, 120249, 120250, 120251, + 120252, 120253, 120254, 120255, 120256, 120257, 120258, 120259, 120260, + 120261, 120262, 120263, 120264, 120265, 120266, 120267, 120268, 120269, + 120270, 120271, 120272, 120273, 120274, 120275, 120807, 120806, 120809, + 120808, 120805, 120804, 120802, 120811, 120803, 120810, 119964, 119966, + 119967, 119970, 119973, 119974, 119977, 119978, 119979, 119980, 119982, + 119983, 119984, 119985, 119986, 119987, 119988, 119989, 119990, 119991, + 119992, 119993, 119995, 119997, 119998, 119999, 120000, 120001, 120002, + 120003, 120005, 120006, 120007, 120008, 120009, 120010, 120011, 120012, + 120013, 120014, 120015, 129481, 119528, 119538, 119531, 119535, 119525, + 119524, 119534, 119529, 119539, 119527, 119537, 119526, 119536, 119533, + 119523, 119532, 119522, 119530, 119520, 119521, 128470, 175, 8737, 10667, + 10666, 10671, 10669, 10670, 10668, 10665, 10664, 10651, 10653, 8798, + 127830, 129470, 129471, 93773, 93764, 93790, 93787, 983268, 93783, + 983267, 93782, 93772, 93766, 93791, 93779, 93789, 93786, 93776, 93777, + 93785, 93775, 93770, 93769, 93771, 93774, 93780, 93760, 93767, 93781, + 93788, 93761, 93768, 93778, 93762, 93763, 93784, 93765, 93847, 93827, + 93846, 93826, 93845, 93825, 93844, 93829, 93828, 93831, 93830, 93824, + 93833, 93832, 93837, 93836, 93834, 93842, 93835, 93838, 93839, 93843, + 93840, 93841, 93805, 93796, 93822, 93819, 983270, 93815, 983269, 93814, + 93804, 93798, 93823, 93811, 93821, 93818, 93808, 93809, 93817, 93807, + 93802, 93801, 93803, 93806, 93812, 93792, 93799, 93813, 93820, 93793, + 93800, 93810, 93794, 93795, 93816, 93797, 93849, 93850, 93848, 11859, + 11852, 11860, 128901, 9899, 10090, 10091, 128967, 128965, 128944, 10100, + 10088, 10092, 10101, 10089, 10093, 8287, 9900, 9618, 128971, 128950, + 128938, 128963, 128961, 10073, 128974, 128956, 9898, 128911, 128931, + 43761, 44013, 43762, 43760, 44011, 43994, 43989, 43974, 43746, 43993, + 43991, 43751, 43750, 43992, 43986, 43987, 43990, 43968, 43995, 43976, + 43973, 43999, 43977, 44001, 43752, 43747, 43972, 43998, 43984, 43969, + 43753, 43754, 43975, 44000, 43978, 43749, 43748, 43983, 44002, 43970, + 43996, 43971, 43997, 43981, 43988, 43979, 43985, 43980, 43982, 43744, + 43745, 44012, 43763, 43764, 44005, 43757, 43759, 43758, 44009, 44003, + 44007, 44006, 44004, 43755, 44008, 43756, 44010, 43765, 43766, 44021, + 44020, 44023, 44022, 44019, 44018, 44016, 44025, 44017, 44024, 129760, + 127816, 125140, 125137, 125136, 125139, 125141, 125138, 125142, 124928, + 124929, 124930, 124936, 124937, 124949, 124950, 124948, 124938, 124956, + 124990, 124992, 124974, 124955, 124964, 124963, 124991, 124957, 124962, + 124976, 124996, 124997, 124998, 124982, 124983, 124984, 125004, 124975, + 125003, 125005, 125011, 125018, 125028, 125029, 125012, 125019, 125020, + 125027, 125013, 125035, 125048, 124942, 124934, 125090, 125046, 125078, + 125033, 124946, 125037, 125070, 125000, 125095, 125121, 124951, 125044, + 125041, 125072, 124987, 125066, 125076, 125074, 125009, 125107, 124945, + 125108, 125068, 125124, 125002, 124931, 125089, 125022, 125119, 124980, + 124986, 125080, 125099, 125100, 124933, 125021, 125015, 125071, 124985, + 125117, 125056, 124993, 125039, 125049, 125043, 125024, 124932, 125047, + 125097, 124959, 125069, 125088, 124999, 125123, 124952, 125036, 125026, + 125001, 125057, 125085, 124960, 125073, 124966, 125098, 125014, 125091, + 124989, 125007, 124978, 124940, 125106, 125050, 125030, 125092, 124941, + 125060, 125077, 125102, 125094, 125053, 125103, 125040, 125055, 125104, + 124939, 125017, 125112, 124961, 125087, 124970, 124971, 124969, 125023, + 124979, 125042, 124947, 125075, 125051, 125111, 125086, 124968, 124944, + 125038, 125096, 125016, 125118, 125109, 124953, 125059, 125052, 125006, + 124958, 125093, 125115, 125054, 124988, 125008, 125084, 125061, 125064, + 125120, 125063, 124967, 124977, 124965, 125031, 125081, 125082, 125010, + 125067, 124973, 125032, 124935, 125116, 125122, 125101, 124994, 124995, + 125113, 125058, 125079, 125114, 125065, 125034, 125083, 124954, 125062, + 125105, 125110, 125045, 124943, 124972, 124981, 125025, 125131, 125130, + 125133, 125132, 125129, 125128, 125135, 125127, 125134, 128334, 128697, + 68028, 68093, 68090, 68089, 68086, 68029, 68092, 68091, 68095, 68088, + 68087, 68094, 68000, 68016, 68020, 68021, 68022, 68009, 68010, 68015, + 68017, 68014, 68013, 68018, 68006, 68023, 68012, 68008, 68007, 68019, + 68011, 68005, 68004, 68001, 68002, 68003, 68031, 68030, 68039, 68075, + 68057, 68084, 68066, 68036, 68054, 68081, 68063, 68045, 68072, 68035, + 68053, 68080, 68062, 68044, 68071, 68040, 68076, 68058, 68085, 68067, + 68038, 68056, 68083, 68065, 68047, 68074, 68037, 68055, 68082, 68064, + 68046, 68073, 68034, 68052, 68079, 68061, 68043, 68070, 68033, 68051, + 68078, 68060, 68042, 68069, 68041, 68068, 68032, 68050, 68077, 68059, + 67974, 67975, 67982, 67983, 67978, 67979, 67980, 67981, 67987, 67988, + 67989, 67992, 67993, 67994, 67995, 67996, 67986, 67985, 67990, 67997, + 67984, 67977, 67976, 67991, 67973, 67972, 67968, 67969, 67970, 67971, + 67998, 67999, 129500, 9791, 983173, 9170, 9172, 9177, 9176, 9175, 9173, + 9174, 9171, 9169, 128647, 128221, 94015, 93989, 93971, 93958, 94019, + 94021, 93953, 94023, 93999, 93995, 94008, 93981, 93979, 93967, 93963, + 93993, 93992, 93983, 93977, 93976, 93975, 93974, 93968, 94032, 93988, + 93987, 93973, 93972, 93997, 93996, 93969, 94106, 94107, 94108, 94109, + 94110, 94111, 94002, 94026, 94022, 94003, 94004, 94010, 93980, 93978, + 94099, 94100, 94101, 94102, 94103, 94104, 94105, 93998, 93994, 94007, + 94025, 93966, 93962, 94024, 93961, 93960, 94000, 94009, 93964, 93965, + 94001, 93970, 93984, 93954, 94017, 94014, 94016, 94013, 94006, 94012, + 94005, 94011, 93986, 93985, 93955, 93952, 94020, 93990, 93957, 93956, + 93959, 93982, 94018, 93991, 94035, 94034, 94033, 94031, 94098, 94096, + 94097, 94095, 94036, 94039, 94040, 94067, 94068, 94038, 94037, 94073, + 94075, 94045, 94071, 94069, 94046, 94047, 94085, 94074, 94049, 94050, + 94051, 94052, 94053, 94086, 94057, 94054, 94084, 94055, 94056, 94041, + 94082, 94048, 94081, 94042, 94076, 94058, 94059, 94060, 94061, 94063, + 94064, 94079, 94087, 94062, 94065, 94080, 94066, 94072, 94070, 94044, + 94043, 94077, 94078, 94083, 983239, 983240, 128300, 127908, 181, 129440, + 129986, 183, 8943, 129686, 127894, 127756, 8357, 128189, 128469, 128656, + 8722, 10793, 10794, 10796, 10795, 10810, 8770, 8723, 10751, 129694, + 129705, 128241, 128242, 128244, 129339, 8871, 71232, 71229, 71236, 71231, + 71230, 71216, 71226, 71228, 71221, 71222, 71223, 71224, 71219, 71220, + 71217, 71218, 71225, 71227, 71234, 71233, 71253, 71252, 71255, 71254, + 71251, 71250, 71248, 71257, 71249, 71256, 71168, 71169, 71179, 71181, + 71195, 71194, 71200, 71199, 71193, 71192, 71198, 71197, 71174, 71175, + 71176, 71177, 71210, 71172, 71173, 71170, 71171, 71215, 71209, 71186, + 71196, 71191, 71201, 71211, 71212, 71213, 71205, 71204, 71188, 71187, + 71185, 71184, 71190, 71189, 71183, 71182, 71203, 71202, 71214, 71206, + 71208, 71207, 71178, 71180, 71235, 43867, 67512, 714, 700, 67509, 761, + 763, 7470, 7471, 7487, 7474, 7483, 7476, 43000, 7484, 7485, 7468, 7469, + 42994, 7472, 7473, 42995, 7475, 7477, 7478, 7479, 7480, 7481, 7482, 7486, + 42996, 7488, 7489, 11389, 7490, 723, 722, 42755, 42753, 42757, 42759, + 42754, 42752, 42756, 42758, 42652, 122956, 122958, 122929, 122954, + 122932, 122952, 122943, 122987, 122946, 122938, 122939, 122942, 122960, + 122941, 122959, 122989, 122955, 122950, 122948, 122944, 122951, 122988, + 122953, 122934, 122935, 122936, 122933, 122949, 122931, 122957, 122930, + 122947, 122937, 122928, 122940, 122945, 42653, 7544, 710, 735, 42889, + 67510, 42776, 42777, 42775, 750, 698, 725, 709, 984011, 42765, 42760, + 42770, 741, 984012, 42769, 42764, 42774, 745, 762, 764, 715, 704, 67507, + 4348, 42766, 42761, 42771, 742, 721, 67511, 42888, 42768, 42763, 751, + 767, 753, 42773, 717, 754, 755, 744, 759, 719, 718, 42783, 752, 716, + 42778, 703, 43882, 706, 713, 42767, 42762, 42772, 743, 758, 757, 756, + 727, 766, 726, 697, 42780, 42782, 42781, 42779, 760, 705, 67508, 701, + 67513, 702, 43883, 707, 734, 42890, 765, 7491, 7493, 7516, 67459, 7495, + 7601, 7509, 67461, 7517, 7580, 7590, 694, 7591, 67474, 67476, 7595, + 67484, 67491, 67456, 67460, 67478, 7600, 67498, 7608, 67506, 67471, + 67492, 7581, 7521, 7496, 67468, 67469, 67467, 67466, 7519, 7585, 67480, + 67463, 67465, 67464, 7611, 7613, 7612, 7497, 7604, 7582, 7614, 7505, + 7584, 67472, 7501, 7518, 7520, 67475, 736, 688, 689, 67477, 43868, 67479, + 7504, 7596, 7588, 7589, 690, 7592, 737, 43869, 43870, 7593, 67485, 7594, + 67483, 67481, 67482, 67486, 67487, 43001, 7599, 7598, 7506, 67490, 7499, + 7507, 7510, 7602, 691, 67497, 67496, 67473, 740, 7583, 67470, 738, 67514, + 7603, 7586, 7498, 7513, 7511, 7605, 67503, 67499, 67502, 7508, 67500, + 67501, 7492, 7579, 7494, 7514, 7597, 7500, 692, 67494, 67495, 693, 67488, + 67489, 7587, 7502, 7610, 43881, 7615, 7512, 43871, 7606, 7607, 7515, + 67504, 7609, 7503, 67493, 695, 739, 696, 42784, 42785, 67458, 67457, 720, + 699, 724, 708, 749, 42864, 748, 712, 747, 746, 10762, 128184, 128176, + 129297, 71266, 6165, 6164, 6167, 6166, 6163, 6162, 6160, 6169, 6161, + 6168, 6159, 6157, 6156, 6155, 6147, 6149, 71271, 71272, 6176, 6279, 6272, + 6295, 6273, 6289, 6274, 6313, 6286, 6311, 6310, 6280, 6276, 6275, 6282, + 6287, 6278, 6285, 6284, 6288, 6277, 6291, 6290, 6293, 6294, 6292, 6283, + 6281, 6185, 6196, 6264, 6210, 6190, 6303, 6305, 6307, 6300, 6302, 6304, + 6312, 6298, 6301, 6314, 6308, 6309, 6299, 6306, 6263, 6262, 6260, 6261, + 6259, 6254, 6248, 6244, 6252, 6245, 6253, 6238, 6239, 6257, 6247, 6256, + 6242, 6258, 6255, 6241, 6240, 6249, 6251, 6250, 6243, 6246, 6237, 6193, + 6192, 6297, 6296, 6218, 6236, 6225, 6234, 6227, 6235, 6211, 6228, 6224, + 6222, 6232, 6226, 6233, 6214, 6216, 6215, 6217, 6219, 6231, 6223, 6220, + 6221, 6230, 6229, 6212, 6213, 6204, 6194, 6209, 6207, 6205, 6206, 6203, + 6202, 6208, 6191, 6177, 6183, 6179, 6181, 6180, 6182, 6186, 6195, 6201, + 6189, 6197, 6184, 6187, 6188, 6199, 6200, 6198, 6178, 71273, 71275, + 71274, 6151, 71265, 71270, 71269, 6144, 71268, 71264, 71267, 71276, 6150, + 6158, 6148, 6146, 6152, 6153, 6154, 6145, 9866, 9867, 119552, 9101, + 128669, 128018, 128053, 127889, 129390, 128496, 129742, 129439, 128332, + 129334, 128741, 128757, 129468, 128739, 9968, 128670, 128672, 128693, + 128507, 128001, 129700, 128045, 128068, 128511, 127909, 92748, 92744, + 92761, 92750, 92739, 92751, 92737, 92754, 92749, 92753, 92743, 92752, + 92757, 92766, 92736, 92741, 92746, 92764, 92745, 92765, 92755, 92760, + 92758, 92756, 92763, 92762, 92747, 92738, 92740, 92759, 92742, 92783, + 92782, 92773, 92772, 92775, 92774, 92771, 92770, 92768, 92777, 92769, + 92776, 70291, 70292, 70290, 70297, 70296, 70293, 70287, 70298, 70312, + 70311, 70306, 70285, 70284, 70289, 70288, 70295, 70294, 70303, 70301, + 70283, 70282, 70280, 70278, 70277, 70276, 70300, 70299, 70310, 70307, + 70304, 70309, 70308, 70305, 70272, 70275, 70273, 70274, 70313, 127926, + 215, 10804, 10805, 10807, 10811, 10801, 10800, 10005, 8844, 8845, 8846, + 8888, 9838, 9837, 9839, 127929, 127896, 119161, 119159, 119155, 119157, + 119061, 119060, 119224, 119235, 119132, 119058, 119059, 119255, 119253, + 119130, 119131, 119163, 119169, 119149, 119167, 119168, 119210, 119178, + 119173, 119211, 119150, 119151, 119152, 119153, 119154, 119175, 119212, + 119213, 119166, 119164, 119141, 119142, 119176, 119179, 119143, 119144, + 119145, 119165, 119177, 119170, 119174, 119092, 119052, 119247, 119186, + 119073, 119109, 119093, 119050, 119220, 119221, 119044, 119049, 119187, + 119209, 119082, 119041, 119083, 119077, 119078, 119162, 119160, 119208, + 119156, 119158, 119136, 119102, 119056, 119057, 119146, 119147, 119148, + 119042, 119066, 119065, 119069, 119185, 119074, 119075, 119076, 119231, + 119232, 119085, 119084, 119070, 119071, 119072, 119218, 119217, 119189, + 119188, 119248, 119249, 119172, 119171, 119216, 119134, 119100, 119206, + 119262, 119270, 119271, 119263, 119268, 119269, 119272, 119264, 119267, + 119266, 119265, 119274, 119223, 119234, 119233, 119046, 119222, 119184, + 119227, 119237, 119228, 119122, 119123, 119081, 119098, 119207, 119129, + 119087, 119086, 119128, 119140, 119106, 119062, 119195, 119204, 119205, + 119196, 119197, 119198, 119199, 119200, 119201, 119202, 119203, 119094, + 119095, 119126, 119108, 119215, 119214, 119261, 119252, 119257, 119258, + 119183, 119090, 119091, 119135, 119101, 119096, 119097, 119053, 119054, + 119055, 119048, 119043, 119047, 119180, 119254, 119259, 119225, 119236, + 119226, 119229, 119238, 119230, 119051, 119045, 119089, 119088, 119040, + 119067, 119068, 119137, 119103, 119139, 119105, 119110, 119111, 119250, + 119181, 119273, 119243, 119244, 119245, 119246, 119242, 119240, 119239, + 119241, 119064, 119138, 119104, 119063, 119256, 119260, 119190, 119118, + 119119, 119120, 119121, 119112, 119113, 119116, 119117, 119114, 119115, + 119124, 119125, 119191, 119193, 119194, 119127, 119251, 119107, 119133, + 119099, 119219, 119192, 119182, 127932, 127925, 127812, 8811, 8810, 4158, + 4156, 4157, 4155, 4192, 4191, 4190, 4226, 4129, 43642, 4138, 4135, 4208, + 4207, 4206, 4159, 4099, 4098, 4097, 43625, 43624, 43626, 43623, 43622, + 43621, 43627, 43618, 43617, 43630, 43629, 43620, 43619, 983244, 43631, + 43616, 43635, 43628, 43633, 43634, 4096, 4188, 4189, 4187, 4186, 4136, + 4121, 4106, 4111, 4100, 4105, 4116, 4238, 4123, 4176, 43491, 4218, 4220, + 43490, 4221, 4224, 43492, 4223, 43489, 4216, 43488, 4215, 4214, 4213, + 4219, 4222, 4225, 4217, 4130, 43646, 43647, 4193, 4177, 4126, 4112, + 43503, 43495, 43502, 43501, 43516, 43515, 43518, 43517, 43498, 43497, + 43500, 43499, 43514, 43496, 4108, 4107, 4113, 4198, 4197, 4125, 4110, + 4109, 4115, 4114, 4178, 4179, 4180, 4181, 4133, 4134, 4131, 4132, 4128, + 4124, 4120, 4119, 4102, 4101, 4104, 4103, 4118, 4117, 4127, 4122, 4137, + 43636, 43637, 43638, 43632, 43494, 4154, 4150, 4250, 4251, 4237, 4235, + 4236, 4231, 4232, 4233, 4234, 43493, 4171, 43644, 43645, 4201, 4202, + 4203, 4204, 4205, 4151, 4239, 43643, 4170, 4153, 4152, 43639, 43641, + 43640, 4174, 4172, 4255, 4254, 4175, 4173, 4245, 4244, 4247, 4246, 4243, + 4242, 4240, 4249, 4241, 4248, 4195, 4196, 43509, 43508, 43511, 43510, + 43507, 43506, 43504, 43513, 43505, 43512, 4146, 4252, 4253, 4140, 4209, + 4212, 4210, 4211, 4147, 4148, 4194, 4228, 4229, 4230, 4227, 4145, 4149, + 4199, 4200, 4139, 4182, 4183, 4184, 4185, 4143, 4144, 4141, 4142, 4165, + 4164, 4167, 4166, 4163, 4162, 4160, 4169, 4161, 4168, 983218, 983232, + 983174, 10753, 10754, 10752, 8720, 10761, 10757, 10758, 8721, 8899, + 10756, 10755, 11007, 8896, 8897, 8898, 8719, 67712, 67728, 67740, 67724, + 67726, 67714, 67732, 67718, 67730, 67723, 67742, 67717, 67729, 67738, + 67739, 67713, 67735, 67716, 67721, 67734, 67737, 67741, 67725, 67719, + 67722, 67727, 67715, 67733, 67720, 67736, 67731, 67758, 67752, 67753, + 67757, 67751, 67759, 67756, 67754, 67755, 8711, 124117, 124120, 124119, + 124121, 124118, 124132, 124136, 124133, 124138, 124137, 124134, 124135, + 124122, 124124, 124126, 124123, 124125, 124112, 124116, 124114, 124113, + 124115, 124127, 124128, 124129, 124130, 124131, 124140, 124143, 124142, + 124139, 124141, 124149, 124148, 124151, 124150, 124147, 124146, 124144, + 124153, 124145, 124152, 128133, 8358, 8892, 72102, 72103, 72138, 72144, + 72136, 72096, 72097, 72107, 72109, 72123, 72122, 72128, 72127, 72121, + 72120, 72126, 72125, 72100, 72101, 72098, 72099, 72143, 72137, 72114, + 72124, 72119, 72129, 72139, 72140, 72141, 72133, 72132, 72116, 72115, + 72113, 72112, 72118, 72117, 72111, 72110, 72131, 72130, 72142, 72134, + 72135, 72106, 72108, 72162, 72161, 72158, 72160, 72159, 72164, 72150, + 72151, 72145, 72155, 72157, 72148, 72149, 72146, 72147, 72154, 72156, + 72163, 8302, 127966, 129314, 128219, 129535, 8239, 983092, 983197, + 983128, 9471, 9453, 9460, 9452, 9458, 9451, 9454, 9455, 9459, 9456, 9457, + 127312, 127313, 127314, 127315, 127316, 127317, 127318, 127319, 127320, + 127321, 127322, 127323, 127324, 127325, 127326, 127327, 127328, 127329, + 127330, 127331, 127332, 127333, 127334, 127335, 127336, 127337, 128982, + 128984, 129982, 129981, 129983, 127344, 127345, 127346, 127347, 127348, + 127349, 127350, 127351, 127352, 127353, 127354, 127355, 127356, 127357, + 127358, 127359, 127360, 127361, 127362, 127363, 127364, 127365, 127366, + 127367, 127368, 127369, 10062, 129988, 127374, 127371, 127375, 127372, + 127373, 983091, 8879, 8840, 8841, 8775, 8821, 8817, 8825, 8820, 8816, + 8824, 129670, 129722, 11228, 129540, 129544, 129565, 129586, 129603, + 129607, 129561, 129536, 129557, 129599, 129539, 129560, 129602, 129610, + 129613, 129541, 129562, 129604, 129537, 129558, 129600, 129538, 129559, + 129601, 129581, 129578, 129582, 129583, 129579, 129580, 128528, 9906, + 127770, 127761, 8362, 6595, 6594, 6599, 6598, 6597, 6596, 6593, 6566, + 6530, 6567, 6531, 6570, 6537, 6532, 6544, 6543, 6536, 6542, 6549, 6548, + 6562, 6561, 6554, 6560, 6556, 6550, 6528, 6555, 6538, 6568, 6533, 6569, + 6534, 6571, 6540, 6535, 6547, 6546, 6539, 6545, 6552, 6551, 6565, 6564, + 6557, 6563, 6559, 6553, 6529, 6558, 6541, 6622, 6623, 6600, 6601, 6618, + 6577, 6587, 6582, 6586, 6578, 6592, 6583, 6584, 6590, 6589, 6579, 6585, + 6591, 6580, 6588, 6576, 6581, 6613, 6612, 6615, 6614, 6611, 6610, 6608, + 6617, 6609, 6616, 983063, 70732, 70746, 70731, 70741, 70740, 70743, + 70742, 70739, 70738, 70736, 70745, 70737, 70744, 70734, 70675, 70674, + 70681, 70680, 70692, 70686, 70691, 70751, 70662, 70663, 70664, 70665, + 70656, 70657, 70667, 70669, 70685, 70684, 70690, 70689, 70683, 70682, + 70688, 70687, 70660, 70661, 70658, 70659, 70705, 70706, 70707, 70696, + 70695, 70677, 70676, 70673, 70672, 70679, 70678, 70671, 70670, 70703, + 70702, 70698, 70697, 70694, 70693, 70701, 70700, 70708, 70704, 70699, + 70666, 70668, 70727, 70724, 70723, 70726, 70752, 70728, 70753, 70722, + 70725, 70730, 70750, 70747, 70709, 70719, 70721, 70714, 70715, 70716, + 70717, 70712, 70713, 70710, 70711, 70718, 70720, 70735, 70749, 70733, + 70729, 11154, 11155, 128240, 9112, 983131, 9798, 11209, 128084, 129299, + 983132, 128985, 129399, 127747, 2031, 2032, 2033, 2030, 2034, 2027, 2028, + 2029, 2035, 2040, 2045, 2046, 1989, 1988, 1991, 1990, 1987, 1986, 1984, + 1993, 1985, 1992, 2042, 2008, 2001, 2025, 2024, 2026, 2006, 2002, 2019, + 2016, 2018, 2023, 2010, 2009, 2000, 1999, 2007, 1997, 1995, 2012, 2003, + 2013, 2020, 2014, 2015, 2017, 2004, 2011, 2005, 2021, 2022, 1994, 1996, + 1998, 2037, 2036, 2039, 2038, 2041, 2047, 983127, 128691, 9940, 128683, + 128695, 128370, 128286, 128245, 128685, 8303, 65934, 8209, 128689, 10973, + 8893, 8599, 10542, 10545, 10536, 10532, 10530, 128602, 128594, 128610, + 11111, 11127, 11016, 8663, 129109, 11008, 43063, 43062, 43065, 43064, + 43059, 43060, 43057, 43056, 43061, 43058, 10529, 8598, 8689, 8632, 10546, + 10535, 10531, 128600, 128592, 128608, 11110, 11126, 11017, 8662, 129108, + 11009, 128746, 8882, 8884, 8379, 8836, 8837, 8713, 8772, 8777, 8938, + 8940, 8742, 8930, 8931, 172, 8877, 8769, 8813, 8800, 8802, 8815, 8814, + 9083, 128323, 10159, 128324, 10161, 128456, 128457, 128458, 128211, + 128212, 160, 128067, 9369, 9362, 9365, 9366, 9367, 35, 9368, 9364, 9361, + 9363, 9371, 9370, 8470, 110960, 110961, 110962, 110963, 110964, 110965, + 110966, 110967, 110968, 110969, 110970, 110971, 110972, 110973, 110974, + 110975, 110976, 110977, 110978, 110979, 110980, 110981, 110982, 110983, + 110984, 110985, 110986, 110987, 110988, 110989, 110990, 110991, 110992, + 110993, 110994, 110995, 110996, 110997, 110998, 110999, 111000, 111001, + 111002, 111003, 111004, 111005, 111006, 111007, 111008, 111009, 111010, + 111011, 111012, 111013, 111014, 111015, 111016, 111017, 111018, 111019, + 111020, 111021, 111022, 111023, 111024, 111025, 111026, 111027, 111028, + 111029, 111030, 111031, 111032, 111033, 111034, 111035, 111036, 111037, + 111038, 111039, 111040, 111041, 111042, 111043, 111044, 111045, 111046, + 111047, 111048, 111049, 111050, 111051, 111052, 111053, 111054, 111055, + 111056, 111057, 111058, 111059, 111060, 111061, 111062, 111063, 111064, + 111065, 111066, 111067, 111068, 111069, 111070, 111071, 111072, 111073, + 111074, 111075, 111076, 111077, 111078, 111079, 111080, 111081, 111082, + 111083, 111084, 111085, 111086, 111087, 111088, 111089, 111090, 111091, + 111092, 111093, 111094, 111095, 111096, 111097, 111098, 111099, 111100, + 111101, 111102, 111103, 111104, 111105, 111106, 111107, 111108, 111109, + 111110, 111111, 111112, 111113, 111114, 111115, 111116, 111117, 111118, + 111119, 111120, 111121, 111122, 111123, 111124, 111125, 111126, 111127, + 111128, 111129, 111130, 111131, 111132, 111133, 111134, 111135, 111136, + 111137, 111138, 111139, 111140, 111141, 111142, 111143, 111144, 111145, + 111146, 111147, 111148, 111149, 111150, 111151, 111152, 111153, 111154, + 111155, 111156, 111157, 111158, 111159, 111160, 111161, 111162, 111163, + 111164, 111165, 111166, 111167, 111168, 111169, 111170, 111171, 111172, + 111173, 111174, 111175, 111176, 111177, 111178, 111179, 111180, 111181, + 111182, 111183, 111184, 111185, 111186, 111187, 111188, 111189, 111190, + 111191, 111192, 111193, 111194, 111195, 111196, 111197, 111198, 111199, + 111200, 111201, 111202, 111203, 111204, 111205, 111206, 111207, 111208, + 111209, 111210, 111211, 111212, 111213, 111214, 111215, 111216, 111217, + 111218, 111219, 111220, 111221, 111222, 111223, 111224, 111225, 111226, + 111227, 111228, 111229, 111230, 111231, 111232, 111233, 111234, 111235, + 111236, 111237, 111238, 111239, 111240, 111241, 111242, 111243, 111244, + 111245, 111246, 111247, 111248, 111249, 111250, 111251, 111252, 111253, + 111254, 111255, 111256, 111257, 111258, 111259, 111260, 111261, 111262, + 111263, 111264, 111265, 111266, 111267, 111268, 111269, 111270, 111271, + 111272, 111273, 111274, 111275, 111276, 111277, 111278, 111279, 111280, + 111281, 111282, 111283, 111284, 111285, 111286, 111287, 111288, 111289, + 111290, 111291, 111292, 111293, 111294, 111295, 111296, 111297, 111298, + 111299, 111300, 111301, 111302, 111303, 111304, 111305, 111306, 111307, + 111308, 111309, 111310, 111311, 111312, 111313, 111314, 111315, 111316, + 111317, 111318, 111319, 111320, 111321, 111322, 111323, 111324, 111325, + 111326, 111327, 111328, 111329, 111330, 111331, 111332, 111333, 111334, + 111335, 111336, 111337, 111338, 111339, 111340, 111341, 111342, 111343, + 111344, 111345, 111346, 111347, 111348, 111349, 111350, 111351, 111352, + 111353, 111354, 111355, 94177, 128297, 983041, 983040, 123215, 123149, + 123155, 123138, 123166, 123164, 123148, 123143, 123161, 123153, 123152, + 123141, 123137, 123156, 123139, 123163, 123142, 123172, 123173, 123171, + 123158, 123140, 123167, 123176, 123177, 123165, 123151, 123168, 123136, + 123169, 123162, 123178, 123179, 123144, 123157, 123170, 123150, 123145, + 123159, 123146, 123154, 123160, 123147, 123174, 123175, 123180, 123214, + 123193, 123192, 123195, 123191, 123194, 123196, 123197, 123184, 123190, + 123189, 123186, 123185, 123188, 123187, 123205, 123204, 123207, 123206, + 123203, 123202, 123200, 123209, 123201, 123208, 983231, 983066, 10663, + 10662, 11869, 9215, 65532, 9287, 9286, 9284, 9285, 9289, 9281, 9290, + 9288, 9282, 9283, 9280, 128721, 128025, 128885, 127970, 5787, 5788, 5776, + 5761, 5786, 5770, 5769, 5781, 5779, 5785, 5763, 5772, 5780, 5784, 5762, + 5775, 5773, 5765, 5777, 5782, 5764, 5774, 5783, 5766, 5778, 5771, 5767, + 5768, 5760, 731, 128738, 7265, 7264, 7266, 7267, 7261, 7260, 7262, 7259, + 7280, 7282, 7281, 7279, 7271, 7270, 7272, 7269, 7258, 7263, 7278, 7268, + 7283, 7273, 7284, 7285, 7287, 7286, 7276, 7274, 7275, 7277, 7290, 7288, + 7289, 7295, 7294, 7292, 7291, 7253, 7252, 7255, 7254, 7251, 7250, 7248, + 7257, 7249, 7256, 7293, 94179, 94178, 68736, 68739, 68744, 68737, 68756, + 68745, 68760, 68769, 68761, 68775, 68785, 68741, 68762, 68772, 68773, + 68740, 68777, 68742, 68749, 68750, 68758, 68759, 68774, 68776, 68783, + 68784, 68738, 68743, 68747, 68748, 68751, 68754, 68755, 68768, 68770, + 68782, 68765, 68780, 68766, 68781, 68763, 68767, 68764, 68778, 68757, + 68786, 68779, 68746, 68752, 68753, 68771, 68800, 68803, 68808, 68801, + 68820, 68809, 68824, 68833, 68825, 68839, 68849, 68805, 68826, 68836, + 68837, 68804, 68841, 68806, 68813, 68814, 68822, 68823, 68838, 68840, + 68847, 68848, 68802, 68807, 68811, 68812, 68815, 68818, 68819, 68832, + 68834, 68846, 68829, 68844, 68830, 68845, 68827, 68831, 68828, 68842, + 68821, 68850, 68843, 68810, 68816, 68817, 68835, 68861, 68859, 68858, + 68862, 68863, 68860, 66308, 66324, 66318, 66335, 66323, 66331, 66327, + 66330, 66315, 66316, 66317, 66329, 66314, 66306, 66322, 66351, 66321, + 66350, 66326, 66334, 66313, 66333, 66328, 66320, 66312, 66325, 66332, + 66305, 66307, 66311, 66309, 66349, 66310, 66304, 66319, 66339, 66337, + 66338, 66336, 68241, 68242, 68246, 68244, 68226, 68224, 68237, 68235, + 68249, 68251, 68247, 68233, 68248, 68252, 68227, 68234, 68230, 68239, + 68232, 68240, 68231, 68250, 68236, 68225, 68243, 68245, 68228, 68229, + 68238, 68255, 68254, 68253, 66404, 66390, 66392, 66387, 66388, 66411, + 66393, 66421, 66418, 66396, 66397, 66399, 66406, 66405, 66401, 66413, + 66402, 66398, 66414, 66415, 66416, 66408, 66420, 66417, 66407, 66419, + 66389, 66391, 66395, 66400, 66386, 66409, 66410, 66385, 66384, 66394, + 66412, 66403, 66516, 66514, 66515, 66517, 66513, 66464, 66504, 66505, + 66506, 66482, 66510, 66511, 66477, 66508, 66509, 66478, 66479, 66473, + 66474, 66490, 66491, 66480, 66475, 66476, 66507, 66471, 66469, 66470, + 66467, 66468, 66484, 66485, 66492, 66493, 66486, 66487, 66488, 66497, + 66498, 66495, 66472, 66483, 66499, 66494, 66481, 66489, 66496, 66465, + 66466, 66512, 128435, 69414, 69395, 69376, 69394, 69391, 69392, 69398, + 69399, 69403, 69404, 69377, 69379, 69382, 69400, 69388, 69380, 69384, + 69393, 69397, 69401, 69386, 69381, 69385, 69387, 69378, 69390, 69402, + 69383, 69396, 69389, 69415, 69407, 69412, 69411, 69406, 69410, 69405, + 69413, 69409, 69408, 68209, 68210, 68217, 68211, 68213, 68214, 68212, + 68203, 68205, 68207, 68206, 68202, 68198, 68220, 68219, 68215, 68201, + 68216, 68193, 68196, 68199, 68218, 68192, 68194, 68200, 68204, 68197, + 68208, 68195, 68222, 68221, 68223, 68608, 68619, 68627, 68623, 68634, + 68640, 68644, 68668, 68670, 68677, 68632, 68669, 68671, 68617, 68625, + 68621, 68638, 68643, 68660, 68666, 68675, 68630, 68648, 68653, 68646, + 68650, 68641, 68673, 68658, 68642, 68655, 68628, 68611, 68657, 68662, + 68614, 68615, 68636, 68656, 68664, 68679, 68680, 68609, 68610, 68645, + 68654, 68620, 68624, 68635, 68678, 68633, 68672, 68652, 68618, 68626, + 68622, 68639, 68661, 68667, 68676, 68631, 68613, 68649, 68647, 68651, + 68674, 68659, 68629, 68612, 68663, 68616, 68637, 68665, 69509, 69508, + 69507, 69506, 69488, 69502, 69496, 69505, 69492, 69499, 69501, 69503, + 69494, 69493, 69490, 69495, 69489, 69498, 69504, 69491, 69500, 69497, + 69511, 69512, 69513, 69510, 128477, 128117, 129491, 128116, 129746, + 128283, 128664, 128753, 128660, 128662, 128653, 11819, 8228, 128431, + 129649, 129477, 128214, 9251, 10044, 10027, 10034, 10011, 128194, 128449, + 128080, 128237, 128236, 10180, 10179, 128275, 9103, 9104, 10174, 983191, + 8997, 128191, 128440, 9934, 9741, 128217, 129505, 129447, 8886, 2902, + 2903, 2933, 2934, 2931, 2930, 2935, 2932, 2928, 2909, 2908, 2864, 2911, + 2863, 2821, 2822, 2832, 2836, 2850, 2849, 2855, 2854, 2848, 2847, 2853, + 2852, 2827, 2912, 2828, 2913, 2869, 2825, 2826, 2823, 2824, 2867, 2866, + 2841, 2851, 2846, 2856, 2870, 2871, 2872, 2861, 2860, 2843, 2842, 2840, + 2839, 2845, 2844, 2838, 2837, 2859, 2858, 2873, 2862, 2929, 2831, 2835, + 983660, 983659, 2877, 2818, 2817, 2876, 2901, 2893, 2819, 2878, 2888, + 2892, 2883, 2884, 2914, 2915, 2881, 2882, 2879, 2880, 2887, 2891, 2923, + 2922, 2925, 2924, 2921, 2920, 2918, 2927, 2919, 2926, 64830, 64831, 9766, + 10183, 128895, 66736, 66737, 66738, 66739, 66743, 66763, 66761, 66742, + 66749, 66757, 66744, 66768, 66750, 66748, 66754, 66755, 66764, 66762, + 66760, 66746, 66745, 66741, 66765, 66769, 66759, 66758, 66771, 66770, + 66740, 66751, 66752, 66753, 66756, 66767, 66747, 66766, 66776, 66777, + 66778, 66779, 66783, 66803, 66801, 66782, 66789, 66797, 66784, 66808, + 66790, 66788, 66794, 66795, 66804, 66802, 66800, 66786, 66785, 66781, + 66805, 66809, 66799, 66798, 66811, 66810, 66780, 66791, 66792, 66793, + 66796, 66807, 66787, 66806, 66710, 66688, 66715, 66699, 66694, 66698, + 66703, 66693, 66697, 66696, 66705, 66702, 66713, 66717, 66704, 66706, + 66707, 66711, 66716, 66689, 66701, 66700, 66708, 66691, 66695, 66690, + 66692, 66709, 66712, 66714, 66725, 66724, 66727, 66726, 66723, 66722, + 66720, 66729, 66721, 66728, 983192, 126257, 126264, 126258, 126259, + 126265, 126260, 126263, 126267, 126255, 126266, 126256, 126262, 126261, + 126269, 126268, 126254, 126216, 126225, 126252, 126234, 126243, 126222, + 126249, 126213, 126231, 126240, 126221, 126248, 126212, 126230, 126239, + 126217, 126226, 126253, 126235, 126244, 126215, 126224, 126251, 126233, + 126242, 126214, 126223, 126250, 126232, 126241, 126220, 126247, 126211, + 126229, 126238, 126219, 126246, 126210, 126228, 126237, 126218, 126245, + 126209, 126227, 126236, 129446, 128228, 10015, 9885, 10029, 10009, 8485, + 129397, 128471, 11195, 11194, 11196, 8254, 129450, 8486, 128076, 127842, + 128329, 129417, 128002, 983122, 983121, 128463, 128195, 128479, 128196, + 128223, 128464, 128724, 93059, 93065, 93064, 93058, 93070, 93056, 93055, + 93053, 93062, 93069, 93061, 93066, 93071, 93068, 93054, 93057, 93063, + 93067, 93060, 92967, 92975, 92965, 92969, 92959, 92968, 92971, 92957, + 92962, 92960, 92972, 92970, 92963, 92958, 92966, 92961, 92956, 92974, + 92964, 92973, 92979, 92978, 92980, 92977, 92976, 92982, 92981, 93023, + 93020, 93024, 93021, 93019, 93025, 93022, 93043, 92985, 93047, 93044, + 93045, 92997, 93046, 93042, 93032, 93029, 92995, 93038, 92993, 93041, + 93035, 93033, 93037, 93030, 93039, 92987, 92992, 92986, 92983, 92984, + 93027, 92994, 93034, 92988, 92990, 92989, 92991, 93028, 92996, 93031, + 93040, 93036, 92954, 92955, 92938, 92939, 92932, 92933, 92942, 92943, + 92950, 92951, 92928, 92929, 92936, 92937, 92948, 92949, 92930, 92931, + 92944, 92945, 92934, 92935, 92940, 92941, 92946, 92947, 92952, 92953, + 93013, 93012, 93015, 93014, 93011, 93010, 93008, 93017, 93009, 93016, + 9908, 11801, 127796, 129779, 129780, 67703, 67693, 67688, 67702, 67683, + 67691, 67699, 67700, 67680, 67696, 67682, 67686, 67695, 67698, 67701, + 67689, 67684, 67687, 67690, 67681, 67694, 67685, 67697, 67692, 67704, + 67711, 67706, 67707, 67710, 67709, 67708, 67705, 129330, 129374, 128060, + 11853, 8233, 11791, 10995, 10994, 8741, 129666, 12809, 12823, 12808, + 12822, 12828, 12813, 12827, 12810, 12824, 12800, 12814, 12804, 12818, + 12801, 12815, 12812, 12826, 12805, 12819, 12803, 12817, 12806, 12820, + 12811, 12825, 12802, 12816, 12807, 12821, 12863, 12855, 12858, 12861, + 12847, 12839, 12854, 12843, 12836, 12864, 12835, 12856, 12846, 12842, + 12840, 12852, 12862, 12865, 12857, 12867, 12838, 12866, 12851, 12853, + 12859, 12849, 12860, 12848, 12837, 12834, 12841, 12833, 12845, 12844, + 12850, 12832, 12830, 12829, 9349, 9342, 9345, 9346, 9350, 9347, 9348, + 9344, 9351, 9343, 9341, 9336, 9335, 9338, 9337, 9334, 9333, 9340, 9332, + 9339, 127248, 127249, 127250, 127251, 127252, 127253, 127254, 127255, + 127256, 127257, 127258, 127259, 127260, 127261, 127262, 127263, 127264, + 127265, 127266, 127267, 127268, 127269, 127270, 127271, 127272, 127273, + 9372, 9373, 9374, 9375, 9376, 9377, 9378, 9379, 9380, 9381, 9382, 9383, + 9384, 9385, 9386, 9387, 9388, 9389, 9390, 9391, 9392, 9393, 9394, 9395, + 9396, 9397, 8706, 983147, 983146, 983149, 983150, 9853, 127881, 12880, + 12349, 129436, 11261, 128755, 9105, 9106, 128706, 72437, 72440, 72432, + 72416, 72419, 72413, 72417, 72415, 72412, 72414, 72418, 72420, 72403, + 72407, 72411, 72409, 72410, 72391, 72400, 72404, 72397, 72394, 72385, + 72401, 72384, 72399, 72398, 72396, 72388, 72393, 72392, 72386, 72387, + 72402, 72395, 72390, 72389, 72405, 72406, 72408, 72436, 72435, 72438, + 72439, 72422, 72421, 72424, 72425, 72431, 72433, 72434, 72428, 72427, + 72429, 72430, 72423, 72426, 128062, 128230, 128206, 983228, 983237, + 129434, 9774, 127825, 129372, 129755, 127824, 128039, 128532, 9956, + 128390, 9999, 8240, 8241, 8524, 10178, 10977, 129336, 129494, 129496, + 128113, 9977, 128590, 129733, 128591, 129493, 128589, 128588, 129495, + 128583, 128187, 8966, 128547, 37, 9854, 127917, 8359, 8369, 129515, + 128694, 129730, 43101, 43117, 43120, 43076, 43123, 43077, 43115, 43090, + 43082, 43094, 43098, 43099, 43119, 43118, 43109, 43074, 43075, 43116, + 43079, 43083, 43089, 43088, 43114, 43113, 43081, 43080, 43073, 43072, + 43085, 43084, 43092, 43093, 43104, 43110, 43086, 43108, 43100, 43078, + 43097, 43087, 43106, 43096, 43091, 43107, 43095, 43102, 43105, 43103, + 43127, 43126, 43124, 43121, 43111, 43112, 43122, 43125, 66033, 66023, + 66017, 66010, 66027, 66003, 66018, 66028, 66004, 66012, 66022, 66020, + 66045, 66019, 66031, 66041, 66007, 66006, 66025, 66026, 66038, 66016, + 66013, 66014, 66000, 66001, 66034, 66036, 66037, 66029, 66011, 66024, + 66015, 66021, 66042, 66043, 66002, 66008, 66032, 66005, 66044, 66040, + 66039, 66030, 66009, 66035, 5941, 5942, 67840, 67855, 67843, 67844, + 67847, 67858, 67857, 67860, 67854, 67861, 67848, 67845, 67846, 67849, + 67859, 67842, 67850, 67853, 67851, 67841, 67856, 67852, 67864, 67866, + 67867, 67863, 67862, 67865, 67871, 11227, 9935, 128763, 128022, 128061, + 128055, 128169, 182, 128138, 129292, 129295, 127885, 127821, 10031, + 129655, 129669, 9811, 128299, 8916, 10970, 129383, 8984, 128720, 129703, + 8462, 8463, 127183, 127136, 127167, 127199, 127188, 127140, 127156, + 127172, 127200, 127189, 127141, 127157, 127173, 127196, 127148, 127164, + 127180, 127198, 127150, 127166, 127182, 127192, 127144, 127160, 127176, + 127191, 127143, 127159, 127175, 127190, 127142, 127158, 127174, 127197, + 127149, 127165, 127181, 127194, 127146, 127162, 127178, 127187, 127139, + 127155, 127171, 127186, 127138, 127154, 127170, 127202, 127220, 127221, + 127201, 127210, 127211, 127212, 127213, 127214, 127215, 127216, 127217, + 127218, 127219, 127203, 127204, 127205, 127206, 127207, 127208, 127209, + 127185, 127137, 127153, 127169, 127193, 127145, 127161, 127177, 127195, + 127147, 127163, 127179, 128733, 983151, 43, 10797, 10798, 10809, 10789, + 10786, 10791, 10790, 10788, 10792, 10787, 10866, 177, 9799, 11222, 11221, + 11220, 11219, 129696, 983148, 128659, 128680, 128110, 8297, 8236, 127871, + 128254, 11239, 128239, 12306, 12320, 128238, 8982, 128688, 129364, + 127858, 129716, 127831, 129751, 128574, 128545, 163, 128093, 9212, 9213, + 9214, 9211, 128041, 128425, 129328, 129732, 129731, 65043, 65040, 65045, + 65073, 65074, 65049, 65041, 65042, 65091, 65047, 65083, 65085, 65089, + 65079, 65087, 65077, 65095, 65081, 65075, 65084, 65086, 65092, 983261, + 65048, 65090, 65080, 65088, 65078, 65096, 65082, 65076, 65044, 65072, + 65046, 8478, 8826, 10937, 10933, 10927, 10929, 10935, 10931, 8936, 8830, + 8828, 8880, 9111, 129384, 9113, 128424, 128438, 129332, 128120, 983193, + 983166, 983163, 983164, 983167, 8242, 8965, 8759, 8733, 8522, 128711, + 129455, 11224, 128255, 68507, 68508, 68480, 68483, 68490, 68491, 68485, + 68482, 68486, 68493, 68495, 68496, 68488, 68484, 68487, 68489, 68481, + 68492, 68497, 68494, 68526, 68522, 68523, 68525, 68521, 68527, 68524, + 68505, 68506, 11854, 8200, 128156, 128091, 128686, 128204, 128226, + 983165, 983168, 983194, 9624, 9625, 9626, 9627, 9628, 9629, 9630, 9631, + 9622, 9623, 10764, 8279, 10774, 9833, 128894, 8264, 63, 8799, 34, 9915, + 127949, 127950, 129437, 128251, 9762, 128280, 9143, 128740, 128643, 9926, + 127752, 11827, 11783, 11782, 9995, 128400, 128406, 127338, 127339, + 127340, 9994, 11828, 11787, 129306, 128000, 8758, 128007, 128048, 129682, + 128015, 129534, 9852, 9843, 9844, 9845, 9846, 9847, 9848, 9849, 9850, + 983113, 128665, 127822, 129511, 174, 127462, 127463, 127464, 127465, + 127466, 127467, 127468, 127469, 127470, 127471, 127472, 127473, 127474, + 127475, 127476, 127477, 127478, 127479, 127480, 127481, 127482, 127483, + 127484, 127485, 127486, 127487, 43344, 43343, 43346, 43345, 43330, 43320, + 43333, 43323, 43331, 43314, 43332, 43317, 43319, 43321, 43316, 43313, + 43329, 43322, 43312, 43326, 43318, 43325, 43324, 43315, 43328, 43327, + 43334, 43359, 43337, 43342, 43341, 43338, 43340, 43335, 43339, 43336, + 43347, 128524, 127895, 65533, 9952, 9953, 128699, 8479, 9166, 11152, + 11153, 128639, 128968, 983152, 92, 10184, 10741, 10743, 11073, 11079, + 983153, 10659, 10661, 8246, 12317, 10989, 8976, 11793, 8267, 8245, + 128401, 9753, 11262, 8515, 8271, 8765, 8909, 8247, 128402, 128403, + 128405, 11841, 11822, 128404, 10672, 128158, 8251, 129423, 983154, + 127872, 11190, 11188, 11191, 11189, 11186, 11187, 11184, 11185, 127832, + 127833, 129919, 129918, 128495, 8735, 12297, 10642, 11777, 11776, 9084, + 8894, 10652, 10644, 10228, 8692, 12305, 10648, 125, 9132, 9133, 9131, + 12301, 8969, 11781, 12299, 10608, 10715, 8221, 11817, 129929, 10621, + 8971, 9687, 11241, 9616, 129978, 129971, 129933, 128381, 11805, 8906, + 10198, 129927, 9621, 129980, 41, 9120, 9118, 9119, 11789, 10182, 8908, + 129931, 8217, 11815, 128360, 128361, 128362, 128489, 93, 9126, 9124, + 10638, 10640, 8262, 10636, 11864, 11862, 9125, 11779, 129987, 128493, + 129928, 129930, 11786, 8895, 10702, 129902, 12309, 8866, 11809, 9145, + 12303, 10628, 12311, 10630, 12315, 12313, 10713, 1421, 4053, 4055, + 129308, 9957, 10749, 9002, 187, 128270, 10153, 10552, 8295, 8238, 8235, + 8207, 10813, 8594, 11080, 11084, 10562, 10613, 10612, 129974, 8614, + 10528, 11076, 11075, 10567, 10526, 8677, 8628, 10513, 8699, 129034, 8620, + 10565, 129042, 129026, 8603, 11022, 11023, 8611, 10517, 10516, 129030, + 129178, 129046, 8618, 8696, 8644, 10522, 129193, 129185, 11146, 11157, + 8658, 10499, 8655, 10503, 10524, 10509, 8674, 129195, 129078, 8652, + 10601, 10605, 10591, 10583, 8641, 10600, 10604, 10596, 10587, 10579, + 8640, 129777, 129090, 129094, 129191, 8702, 8649, 129784, 129189, 128622, + 8669, 129082, 129106, 129187, 11106, 11138, 11132, 983242, 11175, 11173, + 129066, 129062, 129058, 129074, 129070, 11122, 11116, 11142, 129170, + 10511, 8667, 10518, 10520, 10519, 11246, 10497, 10496, 10501, 10512, + 8608, 8605, 8680, 8688, 129174, 129086, 11078, 128141, 128735, 11824, + 8790, 8791, 8728, 730, 129680, 128365, 10539, 10544, 65020, 129350, + 983227, 983235, 983225, 983230, 129704, 128640, 128478, 127906, 128764, + 129531, 129315, 128019, 65947, 65942, 65945, 65940, 65943, 8556, 8583, + 8582, 8548, 8558, 8577, 8547, 8544, 8557, 8584, 8559, 8576, 8549, 8581, + 8550, 8553, 8578, 8555, 8545, 8546, 8579, 8554, 8551, 8552, 65938, 65944, + 65936, 65939, 65941, 65937, 65946, 127801, 127989, 10087, 10085, 11213, + 11215, 8506, 128205, 128907, 127588, 127586, 127589, 127584, 127585, + 127587, 128675, 127840, 129302, 8381, 127945, 10740, 69245, 69243, 69244, + 69246, 69241, 69232, 69238, 69229, 69237, 69228, 69242, 69233, 69234, + 69240, 69231, 69239, 69230, 69236, 69227, 69235, 69226, 69225, 69220, + 69219, 69222, 69221, 69218, 69217, 69224, 69216, 69223, 5872, 5869, 5803, + 5802, 5800, 5833, 5837, 5860, 5811, 5859, 5858, 5841, 5851, 5824, 5844, + 5854, 5826, 5846, 5856, 5799, 5814, 5880, 5879, 5877, 5876, 5878, 5792, + 5813, 5815, 5828, 5816, 5819, 5818, 5853, 5852, 5825, 5831, 5864, 5857, + 5827, 5873, 5812, 5810, 5850, 5829, 5820, 5848, 5804, 5862, 5806, 5801, + 5855, 5845, 5807, 5808, 5875, 5809, 5874, 5843, 5821, 5849, 5823, 5805, + 5836, 5840, 5830, 5863, 5835, 5834, 5861, 5842, 5822, 5798, 5839, 5797, + 5817, 5794, 5847, 5832, 5796, 5795, 5865, 5793, 5866, 5838, 5867, 5868, + 5870, 5871, 127933, 127939, 11254, 11252, 11253, 11251, 11255, 11256, + 8360, 983114, 10700, 129466, 129527, 9808, 129474, 9747, 129761, 2049, + 2053, 2051, 2063, 2055, 2052, 2058, 2059, 2062, 2068, 2069, 2056, 2065, + 2048, 2050, 2067, 2054, 2060, 2066, 2061, 2057, 2064, 2073, 2070, 2071, + 2075, 2093, 2072, 2074, 2084, 2088, 2097, 2110, 2098, 2100, 2108, 2099, + 2096, 2101, 2109, 2106, 2104, 2107, 2103, 2105, 2082, 2079, 2076, 2089, + 2086, 2091, 2081, 2078, 2085, 2092, 2083, 2080, 2077, 2090, 2087, 2102, + 128630, 128631, 128632, 128634, 129386, 128752, 128225, 9796, 43138, + 43139, 43150, 43153, 43167, 43166, 43172, 43171, 43165, 43164, 43170, + 43169, 43144, 43145, 43146, 43147, 43182, 43142, 43143, 43151, 43152, + 43140, 43141, 43187, 43181, 43158, 43168, 43163, 43173, 43183, 43184, + 43185, 43177, 43176, 43160, 43159, 43157, 43156, 43162, 43161, 43155, + 43154, 43175, 43174, 43148, 43149, 43186, 43178, 43180, 43179, 43205, + 43136, 43204, 43137, 43215, 43214, 43221, 43220, 43223, 43222, 43219, + 43218, 43216, 43225, 43217, 43224, 43188, 43189, 43200, 43203, 43194, + 43195, 43196, 43197, 43192, 43193, 43201, 43202, 43190, 43191, 43198, + 43199, 129429, 9973, 127927, 127862, 129403, 9878, 129507, 127979, + 127890, 129410, 9807, 128756, 129691, 128437, 8492, 8496, 8497, 8459, + 8464, 8466, 8499, 8472, 8475, 128624, 8495, 8458, 8467, 8500, 8456, + 128220, 983186, 129453, 128186, 167, 8980, 129352, 127793, 128584, 8979, + 130037, 130036, 130039, 130038, 130035, 130034, 130032, 130041, 130033, + 130040, 10802, 9914, 59, 8480, 129324, 9916, 65093, 983169, 8726, 129697, + 11259, 9913, 11250, 129331, 10014, 10061, 10032, 129368, 70086, 70085, + 70101, 70100, 70103, 70102, 70099, 70098, 70096, 70105, 70097, 70104, + 70092, 70106, 70108, 70019, 70020, 70030, 70032, 70046, 70045, 70051, + 70050, 70044, 70043, 70049, 70048, 70025, 70026, 70027, 70028, 70062, + 70023, 70024, 70021, 70022, 70061, 70060, 70037, 70047, 70042, 70052, + 70063, 70064, 70065, 70056, 70055, 70039, 70038, 70036, 70035, 70041, + 70040, 70034, 70033, 70054, 70053, 70066, 70057, 70059, 70058, 70029, + 70031, 70089, 70110, 70111, 70088, 70095, 70107, 70081, 70017, 70016, + 70090, 70082, 70083, 70080, 70018, 70093, 70091, 70094, 70067, 70077, + 70079, 70072, 70073, 70074, 70075, 70070, 70071, 70068, 70069, 70076, + 70078, 70087, 70109, 70084, 129416, 127847, 66684, 66680, 66682, 66665, + 66673, 66679, 66664, 66669, 66647, 66685, 66672, 66683, 66663, 66659, + 66649, 66686, 66674, 66662, 66660, 66656, 66661, 66677, 66678, 66668, + 66676, 66666, 66681, 66640, 66670, 66646, 66645, 66644, 66654, 66641, + 66667, 66658, 66648, 66687, 66657, 66651, 66655, 66643, 66652, 66650, + 66642, 66653, 66671, 66675, 9752, 129768, 128737, 983075, 983078, 9961, + 128674, 127776, 128722, 128717, 11087, 11103, 11086, 10564, 10976, 10985, + 10984, 10974, 10975, 10983, 113825, 113824, 113826, 113827, 127856, + 129651, 9085, 129327, 128703, 128017, 129424, 129335, 10722, 983198, + 983080, 71107, 71106, 71113, 71040, 71131, 71041, 71051, 71053, 71128, + 71070, 71129, 71130, 71065, 71064, 71069, 71067, 71066, 71072, 71071, + 71046, 71047, 71048, 71049, 71082, 71044, 71045, 71042, 71043, 71058, + 71068, 71063, 71073, 71083, 71084, 71085, 71077, 71076, 71060, 71059, + 71057, 71056, 71062, 71061, 71055, 71054, 71075, 71074, 71086, 71081, + 71078, 71080, 71079, 71050, 71052, 71110, 71111, 71112, 71119, 71120, + 71127, 71126, 71125, 71123, 71124, 71117, 71118, 71116, 71121, 71115, + 71114, 71122, 71109, 71108, 71105, 71100, 71104, 71101, 71103, 71102, + 71132, 71133, 71087, 71097, 71099, 71092, 71093, 71090, 71091, 71088, + 71089, 71096, 71098, 128411, 128410, 128417, 128416, 128409, 128408, + 128415, 128414, 121399, 121397, 121400, 121398, 121402, 121401, 121104, + 121103, 121102, 121388, 121387, 121386, 121482, 121479, 121358, 121359, + 121357, 121360, 121341, 121335, 121339, 121340, 121336, 121334, 121333, + 121338, 121337, 121342, 121368, 121367, 121373, 121356, 121355, 121354, + 121380, 121382, 121381, 121384, 121383, 121385, 121377, 121379, 121378, + 121375, 121376, 121374, 121371, 121369, 121366, 121370, 121372, 121364, + 121365, 121452, 121392, 121352, 121353, 121351, 121499, 121500, 121501, + 121502, 121503, 121470, 121117, 121115, 121119, 121118, 121116, 121456, + 121363, 121362, 121361, 121480, 121455, 120965, 120837, 121000, 120969, + 121027, 121026, 121076, 121074, 121075, 120995, 120991, 120990, 120982, + 121005, 121011, 121044, 121042, 121043, 120950, 120833, 120847, 121002, + 120859, 120863, 120997, 120967, 120845, 121019, 120839, 120993, 120980, + 121038, 121045, 121031, 121009, 120934, 121046, 121047, 120905, 120936, + 120937, 120935, 121065, 120941, 120834, 121068, 121069, 121024, 120915, + 120916, 121040, 120940, 120944, 120946, 120942, 120945, 120947, 120943, + 120949, 121020, 121039, 120948, 121091, 120832, 120838, 120861, 120843, + 120852, 120870, 120844, 120846, 120848, 120865, 120853, 120856, 120885, + 120877, 120878, 120879, 120884, 120857, 120882, 120854, 120855, 120858, + 120883, 121001, 120871, 120850, 120867, 120966, 120972, 120971, 120849, + 120862, 120895, 120894, 120872, 120873, 120893, 120875, 120874, 120866, + 120864, 120996, 120842, 120891, 120890, 121067, 120892, 120887, 121064, + 121066, 121063, 121060, 121061, 121062, 120899, 120881, 121052, 121059, + 121057, 121054, 121055, 121056, 121058, 120851, 120869, 120868, 120841, + 121018, 120974, 120977, 120976, 120975, 120985, 120986, 120983, 120992, + 120988, 120984, 120978, 121032, 121037, 120897, 120896, 120898, 120889, + 120888, 120886, 120880, 121035, 121030, 121033, 121028, 121036, 120860, + 121003, 121012, 121014, 121013, 121007, 121016, 121008, 121015, 121006, + 121077, 121083, 120876, 121084, 121085, 121078, 121090, 121087, 121079, + 121080, 121081, 120840, 121086, 121088, 121089, 120979, 121082, 121092, + 120906, 120922, 120908, 120919, 120920, 120921, 120914, 120910, 120912, + 120900, 120903, 120904, 120902, 120901, 120924, 120909, 120911, 120913, + 120926, 120930, 120931, 120932, 120929, 120933, 120928, 120925, 120927, + 120923, 120957, 120917, 120907, 120836, 121051, 120968, 120973, 120998, + 121072, 121053, 121073, 121070, 121071, 121025, 120970, 120994, 120989, + 120987, 121029, 121041, 120955, 120961, 120956, 120959, 120999, 121004, + 120964, 120960, 120963, 120962, 120958, 120939, 120938, 121023, 121021, + 121022, 121050, 121048, 121049, 121034, 121017, 120951, 120981, 120953, + 121010, 120954, 120952, 120918, 120835, 121451, 121343, 121349, 121347, + 121348, 121346, 121345, 121350, 121344, 121462, 121463, 121464, 121465, + 121466, 121467, 121468, 121469, 121428, 121429, 121427, 121476, 121473, + 121477, 121475, 121474, 121478, 121472, 121471, 121404, 121405, 121403, + 121430, 121409, 121411, 121410, 121406, 121408, 121407, 121421, 121423, + 121422, 121415, 121416, 121417, 121418, 121419, 121420, 121414, 121413, + 121412, 121424, 121425, 121426, 121432, 121431, 121183, 121184, 121182, + 121181, 121187, 121188, 121186, 121185, 121175, 121176, 121174, 121173, + 121179, 121180, 121178, 121177, 121324, 121321, 121323, 121320, 121322, + 121319, 121210, 121209, 121208, 121203, 121207, 121305, 121272, 121271, + 121287, 121286, 121303, 121304, 121302, 121301, 121206, 121205, 121204, + 121198, 121332, 121331, 121129, 121276, 121274, 121275, 121273, 121288, + 121289, 121291, 121290, 121306, 121280, 121278, 121279, 121277, 121295, + 121293, 121294, 121292, 121307, 121314, 121191, 121192, 121190, 121189, + 121193, 121202, 121201, 121200, 121199, 121282, 121281, 121297, 121296, + 121308, 121309, 121310, 121328, 121327, 121194, 121196, 121197, 121195, + 121216, 121215, 121214, 121213, 121212, 121211, 121449, 121125, 121126, + 121121, 121122, 121123, 121124, 121127, 121318, 121316, 121317, 121315, + 121156, 121155, 121154, 121146, 121145, 121144, 121150, 121149, 121148, + 121147, 121230, 121231, 121229, 121228, 121261, 121254, 121247, 121233, + 121232, 121226, 121227, 121225, 121224, 121249, 121248, 121153, 121152, + 121151, 121139, 121135, 121137, 121138, 121136, 121330, 121329, 121128, + 121236, 121262, 121255, 121235, 121234, 121237, 121240, 121239, 121263, + 121256, 121238, 121162, 121161, 121160, 121132, 121133, 121131, 121130, + 121134, 121253, 121142, 121143, 121141, 121140, 121243, 121242, 121241, + 121246, 121245, 121244, 121270, 121269, 121268, 121264, 121257, 121326, + 121325, 121159, 121158, 121157, 121448, 121394, 121393, 121396, 121395, + 121450, 121513, 121514, 121515, 121516, 121517, 121518, 121519, 121505, + 121506, 121507, 121508, 121509, 121510, 121511, 121512, 121312, 121284, + 121299, 121311, 121283, 121298, 121313, 121285, 121300, 121267, 121260, + 121252, 121251, 121266, 121259, 121250, 121265, 121258, 121107, 121106, + 121105, 121454, 121453, 121457, 121120, 121112, 121110, 121114, 121113, + 121111, 121108, 121109, 121101, 121100, 121099, 121481, 121441, 121445, + 121446, 121443, 121444, 121442, 121447, 121390, 121389, 121391, 121440, + 121439, 121437, 121435, 121436, 121434, 121433, 121438, 121459, 121458, + 121460, 121095, 121094, 121093, 121219, 121218, 121217, 121222, 121221, + 121220, 121223, 121172, 121171, 121170, 121168, 121167, 121166, 121165, + 121164, 121163, 121169, 121098, 121097, 121096, 121461, 121483, 129304, + 10912, 10911, 10910, 10909, 10860, 983185, 983183, 8219, 8249, 8218, + 8250, 983158, 983155, 983156, 983159, 70117, 70116, 70119, 70118, 70115, + 70114, 70121, 70113, 70120, 70131, 70132, 70129, 70126, 70125, 70130, + 70128, 70127, 70124, 70123, 70122, 983953, 983954, 983952, 3464, 3463, + 3495, 3501, 3497, 3503, 3510, 3488, 3484, 3490, 3482, 3508, 3513, 3462, + 3475, 3478, 3461, 3474, 3473, 3472, 3471, 3470, 3469, 3466, 3465, 3468, + 3467, 3496, 3502, 3498, 3504, 3511, 3489, 3485, 3491, 3483, 3509, 3512, + 3525, 3499, 3522, 3517, 3505, 3523, 3477, 3476, 3500, 3507, 3487, 3494, + 3526, 3524, 3515, 3520, 3514, 3492, 3493, 3521, 3486, 3563, 3562, 3565, + 3564, 3561, 3560, 3558, 3567, 3559, 3566, 3530, 3458, 3457, 3459, 3570, + 3571, 3546, 3537, 3539, 3542, 3544, 3551, 3536, 3538, 3540, 3545, 3548, + 3549, 3550, 3547, 3535, 3572, 8767, 10046, 128973, 10038, 128303, 8198, + 10042, 128510, 127935, 9975, 128128, 9760, 129448, 128761, 10902, 10904, + 10901, 10903, 11098, 11100, 42611, 128716, 128164, 128564, 128554, + 128373, 128759, 127829, 128577, 128578, 10840, 10839, 9011, 127920, + 129445, 65120, 128745, 65121, 128313, 128312, 8717, 8956, 8958, 65131, + 65104, 65109, 65129, 8714, 8948, 8951, 65126, 65111, 65112, 65105, 65115, + 65113, 65117, 65124, 65116, 65114, 65118, 8570, 8567, 8564, 8574, 8572, + 8563, 8560, 8573, 8575, 8571, 8561, 8562, 8569, 8566, 8565, 8568, 65128, + 65108, 68411, 732, 10849, 65125, 65123, 65130, 65122, 65119, 65106, + 65110, 10922, 10924, 10803, 128570, 128571, 128525, 128520, 128519, + 128515, 128517, 128516, 128518, 128522, 129325, 129392, 128526, 129394, + 8995, 128527, 128684, 128012, 128013, 129319, 127956, 9731, 9924, 127938, + 10052, 983077, 9917, 129510, 173, 127846, 128428, 9108, 129358, 69453, + 69452, 69454, 69456, 69447, 69449, 69446, 69448, 69455, 69451, 69450, + 69445, 69424, 69437, 69426, 69433, 69444, 69440, 69429, 69436, 69439, + 69441, 69431, 69427, 69430, 69432, 69425, 69443, 69435, 69442, 69428, + 69438, 69434, 69457, 69460, 69459, 69458, 69463, 69465, 69461, 69462, + 69464, 128618, 128619, 47, 10742, 128284, 69859, 69863, 69864, 69846, + 69847, 69857, 69849, 69842, 69843, 69844, 69845, 69854, 69856, 69855, + 69848, 69851, 69853, 69840, 69841, 69850, 69852, 69858, 69860, 69862, + 69861, 69877, 69876, 69879, 69878, 69875, 69874, 69872, 69881, 69873, + 69880, 8600, 10537, 10541, 8690, 10533, 128603, 128595, 128611, 11112, + 11128, 11018, 8664, 129110, 11010, 8601, 10538, 10534, 128601, 128593, + 128609, 11113, 11129, 11019, 8665, 129111, 11011, 8471, 72328, 72329, + 72327, 72326, 72340, 72339, 72334, 72332, 72341, 72335, 72333, 72330, + 72331, 72338, 72336, 72337, 72344, 72352, 72351, 72350, 72297, 72296, + 72302, 72311, 72301, 72323, 72285, 72284, 72288, 72298, 72293, 72303, + 72319, 72320, 72321, 72310, 72309, 72295, 72294, 72300, 72299, 72307, + 72306, 72290, 72289, 72287, 72286, 72292, 72291, 72305, 72304, 72312, + 72313, 72314, 72322, 72317, 72308, 72316, 72318, 72315, 72272, 72349, + 72348, 72347, 72346, 72324, 72343, 72325, 72342, 72345, 72353, 72354, + 72282, 72281, 72279, 72280, 72277, 72278, 72275, 72274, 72276, 72273, + 72283, 8384, 983043, 983182, 983118, 983177, 127837, 128150, 10055, + 10024, 32, 128586, 128264, 128263, 128265, 128266, 128483, 128676, + 128172, 8375, 8738, 10656, 10657, 128375, 128376, 128467, 128466, 128026, + 128166, 129525, 129348, 128051, 127941, 129533, 13279, 13058, 13057, + 13059, 13056, 13250, 13171, 13278, 13101, 13172, 13108, 13105, 13118, + 13116, 13251, 13192, 8851, 13255, 13183, 13213, 13220, 13216, 13254, + 8852, 13252, 13253, 13170, 13092, 13175, 13177, 13176, 13093, 13094, + 13256, 127376, 13207, 13064, 13179, 13181, 13182, 13055, 13180, 13005, + 13063, 13006, 9974, 9165, 13209, 13070, 13071, 13311, 13075, 13073, + 13072, 13080, 13081, 13203, 13228, 13191, 13257, 13258, 13098, 13110, + 13113, 13121, 13122, 13119, 13107, 13106, 13109, 13259, 13169, 127488, + 13004, 13200, 13260, 13060, 13061, 8847, 8932, 8849, 13178, 13188, 13067, + 13069, 13068, 13074, 13076, 13078, 13079, 13077, 13214, 13262, 13222, + 13218, 13086, 13085, 13082, 13083, 13084, 13201, 13193, 13248, 13226, + 13189, 13199, 13261, 13208, 13263, 13240, 13246, 8977, 13266, 10957, + 13264, 13265, 13267, 13223, 13224, 13249, 13221, 13217, 13187, 13123, + 13124, 13127, 13126, 13125, 13190, 13268, 13131, 13132, 13133, 13128, + 13129, 13130, 13269, 13212, 13219, 13215, 13186, 13196, 13197, 13205, + 13211, 13234, 13238, 13244, 13239, 13241, 13245, 13247, 13202, 13270, + 13227, 13198, 13206, 13235, 13185, 13096, 13097, 13195, 13210, 13233, + 13237, 13243, 13065, 8848, 8933, 8850, 13066, 13173, 13225, 13099, 13100, + 13184, 13115, 13112, 13114, 13111, 13103, 13104, 13102, 13117, 13120, + 11216, 13273, 13174, 13194, 13271, 13272, 13274, 13232, 13236, 13242, + 13229, 13230, 13231, 13142, 13141, 10958, 13137, 13138, 13140, 13139, + 8730, 13087, 13088, 13090, 13091, 13089, 13275, 13276, 128918, 13204, + 13095, 13143, 11027, 9641, 9638, 9636, 11029, 9706, 9703, 11026, 9705, + 9639, 11028, 9640, 9637, 9704, 10720, 13277, 13135, 13134, 13136, 13062, + 127529, 127530, 127512, 127508, 127533, 127545, 127520, 127516, 127534, + 127506, 127540, 127525, 127546, 127532, 127511, 127509, 127524, 127505, + 127517, 127518, 127527, 127537, 127504, 127528, 127535, 127519, 127515, + 127513, 127543, 127542, 127526, 127541, 127544, 127522, 127538, 127514, + 127521, 127539, 127510, 127536, 127523, 127547, 127531, 127378, 127377, + 8865, 10693, 11820, 127390, 127392, 127379, 10692, 127400, 127399, + 127398, 127306, 127489, 127507, 127490, 9919, 127397, 127280, 127281, + 127282, 127283, 127284, 127285, 127286, 127287, 127288, 127289, 127290, + 127291, 127292, 127293, 127294, 127295, 127296, 127297, 127298, 127299, + 127300, 127301, 127302, 127303, 127304, 127305, 10190, 10191, 127401, + 8863, 127307, 127381, 127382, 127396, 127383, 127310, 8862, 127388, + 127393, 127402, 127395, 9949, 10695, 10696, 127384, 127308, 127309, + 127387, 127394, 127389, 8864, 127391, 127385, 127403, 127404, 127386, + 10694, 127311, 127380, 10151, 129425, 983157, 983160, 983134, 983190, + 9877, 9882, 128387, 129485, 8795, 10017, 8902, 9770, 11242, 11243, + 983175, 983133, 983181, 983176, 983042, 983044, 128509, 128649, 127967, + 128642, 127836, 11836, 129658, 129989, 129990, 129993, 129991, 129992, + 128480, 9201, 128207, 9188, 127827, 10025, 983189, 8803, 127897, 129369, + 128723, 983170, 983045, 983103, 8332, 8328, 8330, 8331, 8333, 8334, 8325, + 8324, 8327, 8326, 8323, 8322, 8320, 8329, 8321, 10963, 10965, 10617, + 8834, 10953, 10949, 10951, 10955, 8842, 8838, 10947, 10943, 10945, 10941, + 983102, 8827, 10938, 10934, 10928, 10930, 10936, 10932, 8937, 8831, 8829, + 8881, 9139, 10763, 9138, 9737, 127774, 9925, 7098, 7073, 7074, 7075, + 7084, 7085, 7043, 983220, 7046, 7102, 7103, 7062, 7100, 7068, 7099, 7067, + 7087, 7070, 7048, 7049, 7053, 7057, 7060, 7101, 7064, 7086, 7050, 7054, + 7059, 7052, 7072, 7055, 7065, 7061, 7051, 7058, 7063, 7069, 7071, 7066, + 7056, 7044, 7047, 7045, 7367, 7366, 7365, 7364, 7363, 7361, 7362, 7360, + 7082, 7041, 7042, 7040, 7083, 7080, 7081, 7079, 7077, 7076, 7078, 7093, + 7092, 7095, 7094, 7091, 7090, 7088, 7097, 7089, 7096, 127749, 127748, + 127751, 127803, 8316, 8312, 8305, 8319, 8317, 8314, 8315, 8318, 8309, + 8308, 8311, 8310, 179, 178, 8304, 8313, 185, 10966, 10964, 10619, 10968, + 10967, 8835, 10954, 10950, 10952, 10956, 8843, 8839, 10948, 10944, 10946, + 10942, 10185, 129464, 129465, 8751, 127940, 128671, 127843, 128629, + 129442, 127946, 8275, 43027, 43026, 43031, 43030, 43040, 43038, 43025, + 43024, 43029, 43028, 43036, 43035, 43021, 43020, 43018, 43017, 43023, + 43022, 43016, 43015, 43034, 43033, 43042, 43039, 43037, 43032, 43041, + 43008, 43012, 43009, 43013, 43011, 43048, 43049, 43050, 43051, 43052, + 43019, 43014, 43010, 43047, 43043, 43046, 43044, 43045, 9223, 9224, 9229, + 9240, 9232, 9236, 9235, 9234, 9233, 9249, 9253, 9241, 9220, 9239, 9219, + 9221, 9243, 9244, 9228, 9225, 9227, 9226, 128325, 9237, 9252, 9216, 9222, + 9246, 9245, 9247, 8527, 9230, 9231, 9217, 9218, 9242, 9254, 9238, 9248, + 11159, 9007, 983094, 983093, 128333, 1807, 1866, 1802, 1798, 1799, 1849, + 1848, 1792, 1854, 1853, 1805, 1804, 1803, 1852, 1851, 1850, 1797, 1814, + 1813, 1815, 1818, 1824, 2153, 2152, 2149, 2148, 2144, 2146, 2150, 2147, + 2154, 2145, 2151, 1825, 1830, 1837, 1839, 1838, 1831, 1834, 1827, 1869, + 1870, 1871, 1809, 1835, 1832, 1828, 1808, 1823, 1833, 1819, 1820, 1836, + 1811, 1812, 1821, 1822, 1810, 1817, 1826, 1816, 1829, 1864, 1863, 1842, + 1841, 1840, 1845, 1844, 1843, 1847, 1846, 1855, 1858, 1796, 983204, 1801, + 1794, 1795, 1800, 1793, 1862, 1861, 1860, 1859, 1865, 1856, 1857, 128137, + 983184, 128085, 129430, 983061, 127955, 917543, 917542, 917546, 917598, + 917568, 917548, 917562, 917540, 917557, 917556, 917559, 917558, 917555, + 917554, 917552, 917561, 917553, 917560, 917565, 917537, 917600, 917566, + 917549, 917569, 917570, 917571, 917572, 917573, 917574, 917575, 917576, + 917577, 917578, 917579, 917580, 917581, 917582, 917583, 917584, 917585, + 917586, 917587, 917588, 917589, 917590, 917591, 917592, 917593, 917594, + 917601, 917602, 917603, 917604, 917605, 917606, 917607, 917608, 917609, + 917610, 917611, 917612, 917613, 917614, 917615, 917616, 917617, 917618, + 917619, 917620, 917621, 917622, 917623, 917624, 917625, 917626, 917564, + 917627, 917544, 917595, 917599, 917541, 917547, 917538, 917567, 917629, + 917545, 917597, 917596, 917563, 917551, 917536, 917539, 917630, 917550, + 917628, 5888, 5919, 5893, 5896, 5898, 5895, 5892, 5905, 5891, 5902, 5899, + 5897, 5901, 5904, 5894, 5903, 5900, 5889, 5890, 5909, 5908, 5906, 5907, + 5989, 5992, 5994, 5991, 5988, 5987, 5998, 5995, 5993, 6000, 5990, 5999, + 5996, 5984, 5985, 5986, 6002, 6003, 6499, 6508, 6509, 6507, 6501, 6502, + 6512, 6513, 6514, 6515, 6516, 6497, 6483, 6487, 6486, 6482, 6498, 6505, + 6504, 6496, 6480, 6490, 6489, 6503, 6506, 6492, 6494, 6488, 6491, 6495, + 6484, 6493, 6481, 6485, 6500, 6745, 6746, 6743, 6747, 6742, 6741, 6748, + 6749, 6750, 6783, 6789, 6788, 6791, 6790, 6787, 6786, 6784, 6793, 6785, + 6792, 6805, 6804, 6807, 6806, 6803, 6802, 6800, 6809, 6801, 6808, 6740, + 6689, 6690, 6688, 6702, 6726, 6727, 6728, 6696, 6695, 6713, 6712, 6707, + 6706, 6714, 6729, 6720, 6693, 6692, 6691, 6704, 6699, 6697, 6717, 6715, + 6709, 6708, 6716, 6732, 6698, 6719, 6723, 6739, 6724, 6730, 6721, 6705, + 6701, 6722, 6735, 6736, 6733, 6734, 6694, 6700, 6710, 6738, 6737, 6711, + 6703, 6718, 6725, 6731, 6828, 6820, 6775, 6776, 6777, 6780, 6824, 6825, + 6819, 6772, 6744, 6823, 6779, 6778, 6822, 6826, 6827, 6818, 6752, 6816, + 6817, 6773, 6774, 6821, 6829, 6753, 6755, 6767, 6769, 6754, 6763, 6764, + 6771, 6768, 6765, 6756, 6770, 6761, 6762, 6760, 6759, 6757, 6758, 6766, + 43653, 43651, 43649, 43661, 43659, 43679, 43677, 43671, 43669, 43657, + 43665, 43673, 43675, 43667, 43681, 43655, 43693, 43689, 43683, 43687, + 43663, 43691, 43685, 43695, 43652, 43650, 43648, 43660, 43658, 43678, + 43676, 43670, 43668, 43656, 43664, 43672, 43674, 43666, 43680, 43654, + 43692, 43688, 43682, 43686, 43662, 43690, 43684, 43694, 43696, 43703, + 43743, 43739, 43740, 43742, 43741, 43712, 43713, 43714, 43711, 43707, + 43697, 43710, 43709, 43708, 43700, 43699, 43705, 43706, 43698, 43704, + 43701, 43702, 71353, 71296, 71352, 71297, 71303, 71305, 71338, 71332, + 71319, 71318, 71324, 71323, 71317, 71316, 71322, 71321, 71300, 71301, + 71298, 71299, 71310, 71320, 71315, 71325, 71329, 71328, 71312, 71311, + 71309, 71308, 71314, 71313, 71307, 71306, 71327, 71326, 71335, 71336, + 71337, 71333, 71330, 71334, 71331, 71302, 71304, 71351, 71339, 71350, + 71340, 71341, 71347, 71349, 71344, 71345, 71342, 71343, 71346, 71348, + 71365, 71364, 71367, 71366, 71363, 71362, 71360, 71369, 71361, 71368, + 129377, 119672, 119671, 3064, 3031, 73707, 983662, 983685, 983674, + 983677, 983676, 983669, 983667, 983679, 983663, 983665, 983668, 983666, + 983683, 983681, 983682, 983673, 983678, 983664, 983684, 983680, 983671, + 983670, 983675, 983672, 73706, 3063, 73701, 3062, 3059, 3051, 3050, 3053, + 3052, 3049, 3048, 3046, 3055, 3047, 3054, 73700, 73666, 73676, 73668, + 73679, 73681, 73682, 73665, 73673, 73674, 73667, 73664, 73669, 73672, + 73675, 73680, 73670, 73678, 73671, 73677, 73683, 73684, 73710, 2985, + 2979, 2969, 2974, 2984, 2975, 2980, 2996, 2995, 2994, 2993, 2992, 2949, + 2950, 2960, 2964, 2953, 2954, 2962, 2963, 2951, 2952, 2998, 2999, 3000, + 2958, 2959, 2970, 3001, 2972, 2965, 2990, 2986, 2997, 2991, 73702, 3057, + 3058, 3056, 3066, 73727, 3065, 73703, 73687, 2946, 73686, 73698, 73690, + 73693, 73692, 73712, 73689, 73688, 73691, 73697, 73694, 73695, 73696, + 73713, 73699, 3021, 2947, 73685, 73708, 73711, 983939, 983940, 983947, + 983950, 983943, 983944, 983948, 983949, 983941, 983942, 983945, 983946, + 983686, 983693, 983696, 983689, 983690, 983694, 983695, 983687, 983688, + 983691, 983692, 983840, 983847, 983850, 983843, 983844, 983848, 983849, + 983841, 983842, 983845, 983846, 983851, 983858, 983861, 983854, 983855, + 983859, 983860, 983852, 983853, 983856, 983857, 983818, 983825, 983828, + 983821, 983822, 983826, 983827, 983819, 983820, 983823, 983824, 983873, + 983880, 983883, 983876, 983877, 983881, 983882, 983874, 983875, 983878, + 983879, 983741, 983748, 983751, 983744, 983745, 983749, 983750, 983742, + 983743, 983746, 983747, 983697, 983704, 983707, 983700, 983701, 983705, + 983706, 983698, 983699, 983702, 983703, 983719, 983726, 983729, 983722, + 983723, 983727, 983728, 983720, 983721, 983724, 983725, 983763, 983770, + 983773, 983766, 983767, 983771, 983772, 983764, 983765, 983768, 983769, + 983862, 983869, 983872, 983865, 983866, 983870, 983871, 983863, 983864, + 983867, 983868, 983807, 983814, 983817, 983810, 983811, 983815, 983816, + 983808, 983809, 983812, 983813, 983895, 983902, 983905, 983898, 983899, + 983903, 983904, 983951, 983896, 983897, 983900, 983901, 983906, 983913, + 983916, 983909, 983910, 983914, 983915, 983907, 983908, 983911, 983912, + 983917, 983924, 983927, 983920, 983921, 983925, 983926, 983918, 983919, + 983922, 983923, 983730, 983737, 983740, 983733, 983734, 983738, 983739, + 983731, 983732, 983735, 983736, 983752, 983759, 983762, 983755, 983756, + 983760, 983761, 983753, 983754, 983757, 983758, 983708, 983715, 983718, + 983711, 983712, 983716, 983717, 983709, 983710, 983713, 983714, 983928, + 983935, 983938, 983931, 983932, 983936, 983937, 983929, 983930, 983933, + 983934, 983884, 983891, 983894, 983887, 983888, 983892, 983893, 983885, + 983886, 983889, 983890, 983785, 983792, 983795, 983788, 983789, 983793, + 983794, 983786, 983787, 983790, 983791, 983774, 983781, 983784, 983777, + 983778, 983782, 983783, 983775, 983776, 983779, 983780, 983829, 983836, + 983839, 983832, 983833, 983837, 983838, 983830, 983831, 983834, 983835, + 983796, 983803, 983806, 983799, 983800, 983804, 983805, 983797, 983798, + 983801, 983802, 3006, 3016, 3020, 3009, 3010, 3018, 3019, 3007, 3008, + 3014, 3015, 73709, 73704, 73705, 3061, 3060, 3024, 129748, 127883, + 127818, 92809, 92810, 92811, 92808, 92789, 92790, 92791, 92788, 92816, + 92859, 92856, 92847, 92845, 92817, 92846, 92843, 92829, 92830, 92831, + 92828, 92835, 92851, 92840, 92844, 92818, 92819, 92852, 92836, 92825, + 92826, 92827, 92824, 92813, 92814, 92815, 92812, 92820, 92822, 92823, + 92821, 92805, 92806, 92807, 92804, 92797, 92798, 92799, 92796, 92801, + 92802, 92803, 92800, 92785, 92786, 92787, 92784, 92793, 92794, 92795, + 92792, 92857, 92854, 92848, 92861, 92853, 92860, 92849, 92855, 92834, + 92833, 92832, 92841, 92839, 92842, 92850, 92838, 92858, 92837, 92862, + 92869, 92868, 92871, 92870, 92867, 92866, 92864, 92873, 92865, 92872, + 100352, 100353, 100354, 100355, 100356, 100357, 100358, 100359, 100360, + 100361, 100362, 100363, 100364, 100365, 100366, 100367, 100368, 100369, + 100370, 100371, 100372, 100373, 100374, 100375, 100376, 100377, 100378, + 100379, 100380, 100381, 100382, 100383, 100384, 100385, 100386, 100387, + 100388, 100389, 100390, 100391, 100392, 100393, 100394, 100395, 100396, + 100397, 100398, 100399, 100400, 100401, 100402, 100403, 100404, 100405, + 100406, 100407, 100408, 100409, 100410, 100411, 100412, 100413, 100414, + 100415, 100416, 100417, 100418, 100419, 100420, 100421, 100422, 100423, + 100424, 100425, 100426, 100427, 100428, 100429, 100430, 100431, 100432, + 100433, 100434, 100435, 100436, 100437, 100438, 100439, 100440, 100441, + 100442, 100443, 100444, 100445, 100446, 100447, 100448, 100449, 100450, + 100451, 100452, 100453, 100454, 100455, 100456, 100457, 100458, 100459, + 100460, 100461, 100462, 100463, 100464, 100465, 100466, 100467, 100468, + 100469, 100470, 100471, 100472, 100473, 100474, 100475, 100476, 100477, + 100478, 100479, 100480, 100481, 100482, 100483, 100484, 100485, 100486, + 100487, 100488, 100489, 100490, 100491, 100492, 100493, 100494, 100495, + 100496, 100497, 100498, 100499, 100500, 100501, 100502, 100503, 100504, + 100505, 100506, 100507, 100508, 100509, 100510, 100511, 100512, 100513, + 100514, 100515, 100516, 100517, 100518, 100519, 100520, 100521, 100522, + 100523, 100524, 100525, 100526, 100527, 100528, 100529, 100530, 100531, + 100532, 100533, 100534, 100535, 100536, 100537, 100538, 100539, 100540, + 100541, 100542, 100543, 100544, 100545, 100546, 100547, 100548, 100549, + 100550, 100551, 100552, 100553, 100554, 100555, 100556, 100557, 100558, + 100559, 100560, 100561, 100562, 100563, 100564, 100565, 100566, 100567, + 100568, 100569, 100570, 100571, 100572, 100573, 100574, 100575, 100576, + 100577, 100578, 100579, 100580, 100581, 100582, 100583, 100584, 100585, + 100586, 100587, 100588, 100589, 100590, 100591, 100592, 100593, 100594, + 100595, 100596, 100597, 100598, 100599, 100600, 100601, 100602, 100603, + 100604, 100605, 100606, 100607, 100608, 100609, 100610, 100611, 100612, + 100613, 100614, 100615, 100616, 100617, 100618, 100619, 100620, 100621, + 100622, 100623, 100624, 100625, 100626, 100627, 100628, 100629, 100630, + 100631, 100632, 100633, 100634, 100635, 100636, 100637, 100638, 100639, + 100640, 100641, 100642, 100643, 100644, 100645, 100646, 100647, 100648, + 100649, 100650, 100651, 100652, 100653, 100654, 100655, 100656, 100657, + 100658, 100659, 100660, 100661, 100662, 100663, 100664, 100665, 100666, + 100667, 100668, 100669, 100670, 100671, 100672, 100673, 100674, 100675, + 100676, 100677, 100678, 100679, 100680, 100681, 100682, 100683, 100684, + 100685, 100686, 100687, 100688, 100689, 100690, 100691, 100692, 100693, + 100694, 100695, 100696, 100697, 100698, 100699, 100700, 100701, 100702, + 100703, 100704, 100705, 100706, 100707, 100708, 100709, 100710, 100711, + 100712, 100713, 100714, 100715, 100716, 100717, 100718, 100719, 100720, + 100721, 100722, 100723, 100724, 100725, 100726, 100727, 100728, 100729, + 100730, 100731, 100732, 100733, 100734, 100735, 100736, 100737, 100738, + 100739, 100740, 100741, 100742, 100743, 100744, 100745, 100746, 100747, + 100748, 100749, 100750, 100751, 100752, 100753, 100754, 100755, 100756, + 100757, 100758, 100759, 100760, 100761, 100762, 100763, 100764, 100765, + 100766, 100767, 100768, 100769, 100770, 100771, 100772, 100773, 100774, + 100775, 100776, 100777, 100778, 100779, 100780, 100781, 100782, 100783, + 100784, 100785, 100786, 100787, 100788, 100789, 100790, 100791, 100792, + 100793, 100794, 100795, 100796, 100797, 100798, 100799, 100800, 100801, + 100802, 100803, 100804, 100805, 100806, 100807, 100808, 100809, 100810, + 100811, 100812, 100813, 100814, 100815, 100816, 100817, 100818, 100819, + 100820, 100821, 100822, 100823, 100824, 100825, 100826, 100827, 100828, + 100829, 100830, 100831, 100832, 100833, 100834, 100835, 100836, 100837, + 100838, 100839, 100840, 100841, 100842, 100843, 100844, 100845, 100846, + 100847, 100848, 100849, 100850, 100851, 100852, 100853, 100854, 100855, + 100856, 100857, 100858, 100859, 100860, 100861, 100862, 100863, 100864, + 100865, 100866, 100867, 100868, 100869, 100870, 100871, 100872, 100873, + 100874, 100875, 100876, 100877, 100878, 100879, 100880, 100881, 100882, + 100883, 100884, 100885, 100886, 100887, 100888, 100889, 100890, 100891, + 100892, 100893, 100894, 100895, 100896, 100897, 100898, 100899, 100900, + 100901, 100902, 100903, 100904, 100905, 100906, 100907, 100908, 100909, + 100910, 100911, 100912, 100913, 100914, 100915, 100916, 100917, 100918, + 100919, 100920, 100921, 100922, 100923, 100924, 100925, 100926, 100927, + 100928, 100929, 100930, 100931, 100932, 100933, 100934, 100935, 100936, + 100937, 100938, 100939, 100940, 100941, 100942, 100943, 100944, 100945, + 100946, 100947, 100948, 100949, 100950, 100951, 100952, 100953, 100954, + 100955, 100956, 100957, 100958, 100959, 100960, 100961, 100962, 100963, + 100964, 100965, 100966, 100967, 100968, 100969, 100970, 100971, 100972, + 100973, 100974, 100975, 100976, 100977, 100978, 100979, 100980, 100981, + 100982, 100983, 100984, 100985, 100986, 100987, 100988, 100989, 100990, + 100991, 100992, 100993, 100994, 100995, 100996, 100997, 100998, 100999, + 101000, 101001, 101002, 101003, 101004, 101005, 101006, 101007, 101008, + 101009, 101010, 101011, 101012, 101013, 101014, 101015, 101016, 101017, + 101018, 101019, 101020, 101021, 101022, 101023, 101024, 101025, 101026, + 101027, 101028, 101029, 101030, 101031, 101032, 101033, 101034, 101035, + 101036, 101037, 101038, 101039, 101040, 101041, 101042, 101043, 101044, + 101045, 101046, 101047, 101048, 101049, 101050, 101051, 101052, 101053, + 101054, 101055, 101056, 101057, 101058, 101059, 101060, 101061, 101062, + 101063, 101064, 101065, 101066, 101067, 101068, 101069, 101070, 101071, + 101072, 101073, 101074, 101075, 101076, 101077, 101078, 101079, 101080, + 101081, 101082, 101083, 101084, 101085, 101086, 101087, 101088, 101089, + 101090, 101091, 101092, 101093, 101094, 101095, 101096, 101097, 101098, + 101099, 101100, 101101, 101102, 101103, 101104, 101105, 101106, 101107, + 101108, 101109, 101110, 101111, 101112, 101113, 101114, 101115, 101116, + 101117, 101118, 101119, 94176, 128429, 9991, 9801, 127790, 128661, + 127861, 128198, 10043, 10170, 129750, 129528, 128222, 128380, 8981, 9990, + 8481, 128384, 128301, 128250, 3158, 3195, 3198, 3194, 3197, 3193, 3196, + 3192, 3106, 3105, 3111, 3161, 3110, 3124, 3123, 3122, 3112, 3165, 3097, + 3107, 3102, 3162, 3121, 3120, 3104, 3103, 3109, 3160, 3108, 3077, 3078, + 3088, 3092, 3083, 3168, 3084, 3169, 3125, 3081, 3082, 3090, 3091, 3079, + 3080, 3126, 3127, 3128, 3117, 3116, 3099, 3098, 3096, 3095, 3101, 3100, + 3094, 3093, 3115, 3114, 3086, 3087, 3129, 3118, 3119, 3157, 3076, 3072, + 3073, 3191, 3199, 3133, 3074, 3132, 3149, 3075, 3134, 3144, 3148, 3139, + 3140, 3170, 3171, 3137, 3138, 3146, 3147, 3135, 3136, 3142, 3143, 3179, + 3178, 3181, 3180, 3177, 3176, 3174, 3183, 3175, 3182, 127934, 8376, 9978, + 129514, 119617, 119564, 119577, 119633, 119587, 119566, 119561, 119585, + 119613, 119590, 119631, 119634, 119630, 119608, 119582, 119563, 119573, + 119558, 119624, 119567, 119623, 119586, 119636, 119612, 119625, 119568, + 119584, 119619, 119618, 119583, 119603, 119600, 119626, 119610, 119580, + 119576, 119638, 119559, 119595, 119632, 119606, 119592, 119615, 119599, + 119602, 119614, 119629, 119574, 119569, 119570, 119622, 119562, 119591, + 119637, 119597, 119589, 119616, 119609, 119560, 119635, 119565, 119604, + 119588, 119571, 119594, 119578, 119596, 119579, 119598, 119572, 119605, + 119627, 119621, 119628, 119601, 119593, 119607, 119575, 119620, 119611, + 119581, 1959, 1958, 1964, 1961, 1965, 1927, 1954, 1951, 1937, 1931, 1930, + 1956, 1934, 1935, 1955, 1945, 1920, 1926, 1946, 1933, 1925, 1929, 1943, + 1942, 1941, 1922, 1969, 1950, 1949, 1921, 1936, 1939, 1932, 1947, 1944, + 1952, 1928, 1957, 1938, 1948, 1953, 1924, 1923, 1940, 1967, 1966, 1963, + 1960, 1962, 1968, 3610, 3592, 3594, 3593, 3596, 3598, 3604, 3613, 3615, + 3663, 3630, 3627, 3588, 3587, 3589, 3586, 3590, 3675, 3585, 3628, 3621, + 3653, 3622, 3659, 3633, 3657, 3658, 3656, 3655, 3654, 3617, 3674, 3591, + 3661, 3603, 3609, 3631, 3642, 3612, 3614, 3616, 3611, 3619, 3620, 3632, + 3652, 3651, 3634, 3649, 3635, 3640, 3638, 3639, 3641, 3636, 3637, 3648, + 3650, 3625, 3624, 3626, 3595, 3660, 3601, 3602, 3607, 3600, 3608, 3606, + 3605, 3599, 3623, 3662, 3597, 3618, 3629, 3647, 3669, 3668, 3671, 3670, + 3667, 3666, 3664, 3673, 3665, 3672, 8708, 8707, 8756, 127777, 10727, + 128936, 8201, 128929, 129300, 129353, 128173, 129652, 10176, 8278, 9887, + 9886, 11057, 128485, 128484, 128486, 128487, 8694, 128433, 10870, 128491, + 128962, 128423, 11160, 11162, 10146, 11163, 11161, 10147, 8196, 11835, + 128077, 128078, 9928, 9736, 3865, 3863, 3864, 4032, 4033, 4035, 4034, + 3886, 3885, 3888, 3887, 3884, 3883, 3891, 3890, 3882, 3889, 3877, 3876, + 3879, 3878, 3875, 3874, 3872, 3881, 3873, 3880, 4030, 4031, 3945, 3905, + 3947, 3904, 3948, 3938, 3946, 3917, 3916, 3932, 3931, 3922, 3921, 3908, + 3918, 3913, 3923, 3940, 3941, 3942, 3930, 3929, 3915, 3914, 3920, 3919, + 3927, 3926, 3910, 3909, 3907, 3906, 3925, 3924, 3934, 3935, 3936, 3943, + 3911, 3939, 3928, 3933, 3937, 3944, 3862, 3861, 983210, 3850, 4048, 3849, + 3892, 4049, 3894, 3859, 3846, 3896, 4052, 3845, 3847, 3842, 3843, 3841, + 3860, 3898, 3899, 3900, 3901, 3972, 4051, 3844, 3851, 3895, 3893, 4050, + 3856, 3854, 3973, 3858, 3857, 3848, 3853, 4058, 3897, 3855, 4057, 3852, + 3978, 3979, 3974, 3976, 3903, 3977, 3970, 3866, 3867, 3868, 3871, 3869, + 3870, 4047, 4046, 3966, 3967, 3975, 3902, 3980, 3971, 4028, 4026, 4027, + 3997, 3996, 4012, 4011, 4002, 4001, 4025, 3985, 3984, 3988, 3998, 3993, + 4003, 4020, 4021, 4022, 4010, 4009, 3995, 3994, 4000, 3999, 4007, 4006, + 3990, 3989, 3987, 3986, 4005, 4004, 4014, 4015, 4016, 4023, 3991, 4019, + 4008, 4018, 4013, 4017, 4024, 3983, 3982, 3981, 3840, 4036, 4041, 4044, + 4043, 4042, 4038, 4040, 4037, 4039, 3968, 3969, 3958, 3959, 3960, 3961, + 3956, 3957, 3964, 3965, 3954, 3955, 3962, 3963, 3953, 10717, 11647, + 11608, 11595, 11585, 11573, 11620, 11607, 11600, 11582, 11590, 11596, + 11601, 11586, 11592, 11568, 11575, 11577, 11578, 11576, 11571, 11606, + 11572, 11581, 11589, 11583, 11569, 11570, 11584, 11587, 11609, 11611, + 11610, 11612, 11613, 11615, 11619, 11594, 11621, 11604, 11605, 11614, + 11588, 11580, 11574, 11597, 11598, 11599, 11602, 11591, 11616, 11617, + 11618, 11622, 11579, 11593, 11623, 11603, 11631, 11632, 128005, 128047, + 10053, 126, 8764, 11081, 10610, 10859, 10858, 11807, 11806, 11803, 9202, + 10708, 10709, 10750, 68410, 70854, 70784, 70785, 70786, 70796, 70798, + 70812, 70811, 70817, 70816, 70810, 70809, 70815, 70814, 70791, 70792, + 70793, 70794, 70827, 70789, 70790, 70787, 70788, 70803, 70813, 70808, + 70818, 70828, 70829, 70830, 70822, 70821, 70805, 70804, 70802, 70801, + 70807, 70806, 70800, 70799, 70820, 70819, 70831, 70826, 70823, 70825, + 70824, 70795, 70797, 70852, 70848, 70847, 70851, 70850, 70849, 70832, + 70843, 70846, 70842, 70845, 70837, 70838, 70839, 70840, 70835, 70836, + 70833, 70834, 70841, 70844, 70869, 70868, 70871, 70870, 70867, 70866, + 70864, 70873, 70865, 70872, 70853, 70855, 11858, 8266, 128555, 127915, + 127813, 128069, 129463, 129701, 129520, 10554, 10557, 10556, 9182, 11210, + 11865, 11866, 11833, 8992, 127913, 9180, 8988, 8975, 11810, 8989, 8974, + 11811, 9140, 9184, 128285, 127553, 127554, 127559, 127555, 127557, + 127560, 127552, 127556, 127558, 127274, 9008, 123554, 123556, 123559, + 123561, 123564, 123537, 123553, 123555, 123544, 123543, 123558, 123560, + 123546, 123565, 123563, 123539, 123541, 123550, 123549, 123540, 123552, + 123542, 123536, 123551, 123545, 123538, 123548, 123547, 123562, 123557, + 123566, 128701, 128508, 128434, 128668, 8482, 128650, 128651, 11223, + 10971, 128646, 10701, 10699, 128710, 10698, 10141, 128681, 128208, 8227, + 128305, 9783, 9776, 9777, 9782, 9779, 9781, 9780, 9778, 10998, 10856, + 10857, 10747, 8244, 8779, 10996, 10624, 8874, 10997, 11003, 11851, 11000, + 10999, 8749, 8285, 129484, 128654, 127865, 128032, 127942, 8872, 11231, + 127930, 8366, 8378, 129411, 8523, 10658, 11202, 9930, 9929, 8498, 11826, + 11832, 8587, 8586, 128598, 128596, 8985, 128399, 8513, 8514, 8516, 11829, + 8526, 128599, 128597, 8489, 128034, 129347, 127799, 10041, 128256, 8273, + 128432, 10869, 8229, 8282, 11818, 128149, 10837, 10838, 10697, 10760, + 10759, 128108, 128109, 128490, 11834, 66432, 66451, 66454, 66433, 66436, + 66447, 66457, 66434, 66437, 66440, 66443, 66435, 66445, 66455, 66453, + 66450, 66444, 66461, 66456, 66441, 66458, 66442, 66439, 66449, 66448, + 66452, 66438, 66446, 66459, 66460, 66463, 9730, 9969, 9748, 128530, + 11217, 8255, 9100, 8746, 10824, 10822, 10826, 10817, 10818, 10821, + 983116, 11258, 9842, 129412, 9903, 10685, 8963, 8996, 11193, 10577, + 10573, 10572, 10575, 8597, 8616, 11021, 8661, 129113, 8691, 11109, 10622, + 8944, 8869, 10207, 128742, 128744, 128316, 128743, 128314, 9709, 9710, + 129898, 129946, 129920, 129896, 9985, 129924, 9600, 129937, 129938, 9690, + 129934, 9696, 129885, 129887, 129889, 129886, 129883, 129888, 129881, + 129884, 129882, 129879, 129880, 10196, 129944, 129948, 9720, 9136, 9692, + 129922, 9620, 129874, 129875, 129892, 129894, 129890, 129878, 129893, + 129891, 129876, 129895, 129877, 10064, 9137, 10000, 9693, 128319, 10066, + 129945, 129949, 9721, 129926, 129923, 129925, 129901, 128579, 11797, + 8593, 129976, 8645, 8670, 129033, 129029, 129177, 129041, 129025, 129045, + 8624, 8625, 10505, 8613, 10514, 11145, 11014, 8657, 8673, 129077, 10606, + 10595, 10592, 10584, 8639, 10588, 10580, 8638, 129089, 129093, 129085, + 10224, 128621, 129105, 129081, 11105, 11137, 11121, 129065, 11170, 11171, + 129061, 129057, 129073, 129069, 11131, 11115, 11141, 129169, 10506, 8607, + 11245, 10569, 8648, 8679, 8682, 11192, 8683, 8684, 8685, 129173, 8686, + 8687, 9797, 983117, 42509, 42510, 42511, 42446, 42370, 42486, 42257, + 42333, 42294, 42407, 42445, 42369, 42485, 42256, 42332, 42293, 42406, + 42449, 42373, 42489, 42260, 42336, 42297, 42410, 42434, 42359, 42473, + 42246, 42321, 42283, 42396, 42435, 42360, 42474, 42247, 42322, 42284, + 42397, 42452, 42376, 42492, 42263, 42339, 42300, 42413, 42451, 42375, + 42491, 42262, 42338, 42299, 42412, 42444, 42368, 42484, 42255, 42331, + 42292, 42405, 42443, 42367, 42483, 42254, 42330, 42291, 42404, 42454, + 42378, 42494, 42265, 42341, 42302, 42415, 42453, 42377, 42493, 42264, + 42340, 42301, 42414, 42439, 42440, 42364, 42479, 42251, 42480, 42327, + 42288, 42401, 42502, 42272, 42503, 42461, 42385, 42349, 42309, 42422, + 42429, 42430, 42355, 42468, 42242, 42469, 42316, 42317, 42278, 42279, + 42391, 42392, 42476, 42249, 42477, 42437, 42362, 42324, 42325, 42286, + 42399, 42459, 42383, 42346, 42347, 42499, 42270, 42307, 42420, 42487, + 42508, 42258, 42447, 42371, 42334, 42295, 42408, 42436, 42361, 42475, + 42248, 42323, 42285, 42398, 42438, 42363, 42478, 42250, 42326, 42287, + 42400, 42462, 42386, 42504, 42273, 42350, 42310, 42423, 42450, 42514, + 42539, 42512, 42513, 42538, 42374, 42490, 42261, 42337, 42298, 42411, + 42507, 42500, 42271, 42501, 42460, 42384, 42348, 42308, 42421, 42315, + 42467, 42428, 42457, 42381, 42497, 42268, 42344, 42305, 42418, 42464, + 42388, 42506, 42275, 42352, 42312, 42425, 42463, 42387, 42505, 42274, + 42351, 42311, 42424, 42455, 42379, 42495, 42266, 42342, 42303, 42416, + 42441, 42365, 42481, 42252, 42328, 42289, 42402, 42456, 42380, 42496, + 42267, 42343, 42304, 42417, 42433, 42358, 42472, 42245, 42320, 42282, + 42395, 42448, 42372, 42488, 42259, 42335, 42296, 42409, 42442, 42366, + 42482, 42253, 42329, 42290, 42403, 42458, 42382, 42498, 42269, 42345, + 42306, 42419, 42470, 42243, 42244, 42471, 42431, 42356, 42357, 42432, + 42318, 42319, 42280, 42281, 42393, 42394, 42465, 42240, 42241, 42466, + 42426, 42353, 42354, 42427, 42313, 42314, 42276, 42277, 42389, 42390, + 42523, 42526, 42522, 42515, 42520, 42527, 42516, 42524, 42518, 42517, + 42525, 42521, 42519, 42533, 42532, 42535, 42534, 42531, 42530, 42528, + 42537, 42529, 42536, 65024, 65033, 917843, 917844, 917845, 917846, + 917847, 917848, 917849, 917850, 917851, 917852, 65034, 917853, 917854, + 917855, 917856, 917857, 917858, 917859, 917860, 917861, 917862, 65035, + 917863, 917864, 917865, 917866, 917867, 917868, 917869, 917870, 917871, + 917872, 65036, 917873, 917874, 917875, 917876, 917877, 917878, 917879, + 917880, 917881, 917882, 65037, 917883, 917884, 917885, 917886, 917887, + 917888, 917889, 917890, 917891, 917892, 65038, 917893, 917894, 917895, + 917896, 917897, 917898, 917899, 917900, 917901, 917902, 65039, 917903, + 917904, 917905, 917906, 917907, 917908, 917909, 917910, 917911, 917912, + 917760, 917913, 917914, 917915, 917916, 917917, 917918, 917919, 917920, + 917921, 917922, 917761, 917923, 917924, 917925, 917926, 917927, 917928, + 917929, 917930, 917931, 917932, 917762, 917933, 917934, 917935, 917936, + 917937, 917938, 917939, 917940, 917941, 917942, 65025, 917763, 917943, + 917944, 917945, 917946, 917947, 917948, 917949, 917950, 917951, 917952, + 917764, 917953, 917954, 917955, 917956, 917957, 917958, 917959, 917960, + 917961, 917962, 917765, 917963, 917964, 917965, 917966, 917967, 917968, + 917969, 917970, 917971, 917972, 917766, 917973, 917974, 917975, 917976, + 917977, 917978, 917979, 917980, 917981, 917982, 917767, 917983, 917984, + 917985, 917986, 917987, 917988, 917989, 917990, 917991, 917992, 917768, + 917993, 917994, 917995, 917996, 917997, 917998, 917999, 917769, 917770, + 917771, 917772, 65026, 917773, 917774, 917775, 917776, 917777, 917778, + 917779, 917780, 917781, 917782, 65027, 917783, 917784, 917785, 917786, + 917787, 917788, 917789, 917790, 917791, 917792, 65028, 917793, 917794, + 917795, 917796, 917797, 917798, 917799, 917800, 917801, 917802, 65029, + 917803, 917804, 917805, 917806, 917807, 917808, 917809, 917810, 917811, + 917812, 65030, 917813, 917814, 917815, 917816, 917817, 917818, 917819, + 917820, 917821, 917822, 65031, 917823, 917824, 917825, 917826, 917827, + 917828, 917829, 917830, 917831, 917832, 65032, 917833, 917834, 917835, + 917836, 917837, 917838, 917839, 917840, 917841, 917842, 129499, 983245, + 983254, 983356, 983357, 983358, 983359, 983360, 983361, 983362, 983363, + 983364, 983365, 983255, 983366, 983367, 983368, 983369, 983370, 983371, + 983372, 983373, 983374, 983375, 983256, 983376, 983377, 983378, 983379, + 983380, 983381, 983382, 983383, 983384, 983385, 983257, 983386, 983387, + 983388, 983389, 983390, 983391, 983392, 983393, 983394, 983395, 983258, + 983396, 983397, 983398, 983399, 983400, 983401, 983402, 983403, 983404, + 983405, 983259, 983406, 983407, 983408, 983409, 983410, 983411, 983412, + 983413, 983414, 983415, 983260, 983416, 983417, 983418, 983419, 983420, + 983421, 983422, 983423, 983424, 983425, 983273, 983426, 983427, 983428, + 983429, 983430, 983431, 983432, 983433, 983434, 983435, 983274, 983436, + 983437, 983438, 983439, 983440, 983441, 983442, 983443, 983444, 983445, + 983275, 983446, 983447, 983448, 983449, 983450, 983451, 983452, 983453, + 983454, 983455, 983246, 983276, 983456, 983457, 983458, 983459, 983460, + 983461, 983462, 983463, 983464, 983465, 983277, 983466, 983467, 983468, + 983469, 983470, 983471, 983472, 983473, 983474, 983475, 983278, 983476, + 983477, 983478, 983479, 983480, 983481, 983482, 983483, 983484, 983485, + 983279, 983486, 983487, 983488, 983489, 983490, 983491, 983492, 983493, + 983494, 983495, 983280, 983496, 983497, 983498, 983499, 983500, 983501, + 983502, 983503, 983504, 983505, 983281, 983506, 983507, 983508, 983509, + 983510, 983511, 983512, 983282, 983283, 983284, 983285, 983247, 983286, + 983287, 983288, 983289, 983290, 983291, 983292, 983293, 983294, 983295, + 983248, 983296, 983297, 983298, 983299, 983300, 983301, 983302, 983303, + 983304, 983305, 983249, 983306, 983307, 983308, 983309, 983310, 983311, + 983312, 983313, 983314, 983315, 983250, 983316, 983317, 983318, 983319, + 983320, 983321, 983322, 983323, 983324, 983325, 983251, 983326, 983327, + 983328, 983329, 983330, 983331, 983332, 983333, 983334, 983335, 983252, + 983336, 983337, 983338, 983339, 983340, 983341, 983342, 983343, 983344, + 983345, 983253, 983346, 983347, 983348, 983349, 983350, 983351, 983352, + 983353, 983354, 983355, 7401, 7402, 7409, 7403, 7404, 7415, 7410, 7418, + 7413, 7379, 7398, 7396, 7411, 7408, 7406, 7407, 7405, 7414, 7397, 7400, + 7395, 7399, 7394, 7380, 7384, 7412, 7417, 7386, 7389, 7376, 7388, 7378, + 7416, 7392, 7391, 7387, 7390, 7381, 7382, 7383, 7385, 7393, 7377, 8483, + 10704, 10980, 10978, 10186, 8942, 8286, 12347, 12337, 12339, 12341, + 12338, 12340, 124, 9168, 10992, 10991, 9087, 9896, 129904, 129905, + 129906, 129907, 129908, 129909, 11135, 983069, 983144, 11823, 128678, + 11837, 10650, 128976, 128959, 128947, 128637, 128941, 128953, 128636, + 128904, 128914, 128934, 8921, 8920, 128933, 10799, 9910, 128243, 9996, + 128249, 127918, 128252, 94193, 94192, 8983, 127931, 9805, 66929, 66930, + 66936, 66935, 66942, 66943, 66947, 66946, 66950, 66949, 66932, 66931, + 66934, 66933, 66957, 66956, 66959, 66958, 66941, 66940, 66937, 66944, + 66948, 66952, 66954, 66961, 66962, 66965, 66938, 66945, 66953, 66928, + 66951, 66960, 66964, 66968, 66969, 66975, 66974, 66981, 66982, 66986, + 66985, 66989, 66988, 66971, 66970, 66973, 66972, 66996, 66995, 66998, + 66997, 66980, 66979, 66976, 66983, 66987, 66991, 66993, 67000, 67001, + 67004, 66977, 66984, 66992, 66967, 66990, 66999, 67003, 129979, 127755, + 127952, 8752, 983070, 983145, 11238, 8541, 8538, 8536, 8539, 8533, 189, + 8529, 188, 8528, 8537, 8530, 8531, 8540, 190, 8535, 8534, 8532, 8542, + 8585, 123585, 123584, 123624, 123619, 123620, 123606, 123605, 123622, + 123618, 123611, 123623, 123612, 123621, 123615, 123592, 123613, 123625, + 123593, 123596, 123617, 123616, 123595, 123614, 123626, 123627, 123590, + 123609, 123604, 123591, 123594, 123599, 123598, 123586, 123587, 123588, + 123597, 123589, 123610, 123600, 123608, 123607, 123603, 123602, 123601, + 123647, 123630, 123631, 123628, 123629, 123637, 123636, 123639, 123638, + 123635, 123634, 123632, 123641, 123633, 123640, 127768, 127766, 127762, + 127764, 71841, 71850, 71862, 71861, 71848, 71856, 71853, 71867, 71866, + 71865, 71868, 71840, 71859, 71849, 71857, 71869, 71870, 71855, 71847, + 71843, 71854, 71844, 71845, 71858, 71871, 71863, 71864, 71852, 71846, + 71842, 71860, 71851, 71873, 71882, 71894, 71893, 71880, 71888, 71885, + 71899, 71898, 71897, 71900, 71872, 71891, 71881, 71889, 71901, 71902, + 71887, 71879, 71875, 71886, 71876, 71877, 71890, 71903, 71895, 71896, + 71884, 71878, 71874, 71892, 71883, 71909, 71908, 71911, 71910, 71907, + 71906, 71904, 71913, 71905, 71912, 71921, 71918, 71917, 71922, 71920, + 71919, 71916, 71915, 71914, 71935, 9888, 128702, 127754, 128003, 129341, + 127817, 8986, 12316, 11071, 10547, 127988, 127987, 128075, 12336, 65103, + 8967, 65099, 129479, 128465, 128576, 128553, 10172, 128146, 983238, + 127947, 9840, 128734, 9784, 9855, 129197, 129196, 9702, 9815, 129548, + 129590, 129608, 129611, 9812, 129545, 129587, 9816, 129542, 129563, + 129584, 129591, 129605, 129549, 129616, 129614, 129615, 9817, 129550, + 129592, 9813, 129546, 129588, 9814, 129547, 129589, 129569, 129566, + 129570, 129571, 129567, 129568, 9675, 128906, 9862, 10732, 9863, 9717, + 9718, 9716, 9719, 9831, 10209, 10210, 10211, 9671, 9672, 128922, 128923, + 10192, 9826, 9931, 128071, 128407, 9759, 9663, 9661, 9920, 9921, 10069, + 9872, 9983, 10048, 128174, 11214, 10023, 9785, 128427, 129293, 9825, + 9989, 129984, 11041, 11053, 10710, 11036, 128326, 9945, 128072, 9756, + 9669, 9667, 9665, 128928, 11046, 11088, 9725, 9723, 11048, 11229, 10001, + 9649, 11040, 127985, 10068, 11092, 9659, 9657, 9655, 128073, 9758, 9645, + 9988, 65094, 9750, 11051, 11090, 9643, 9786, 9828, 9633, 128307, 128916, + 9635, 128917, 10212, 9713, 9714, 10213, 9634, 9712, 9715, 9707, 9093, + 127779, 127781, 127782, 9788, 127780, 9734, 128382, 9743, 9186, 10177, + 9943, 128070, 9757, 129994, 9653, 9651, 9708, 11006, 11055, 9647, 11038, + 10163, 128011, 129144, 129152, 129120, 129136, 129128, 129146, 129154, + 129122, 129138, 129130, 129147, 129155, 129123, 129139, 129131, 129145, + 129153, 129121, 129137, 129129, 129149, 129157, 129125, 129141, 129133, + 129148, 129156, 129124, 129140, 129132, 129150, 129158, 129126, 129142, + 129134, 129151, 129159, 129127, 129143, 129135, 11838, 129344, 127888, + 127788, 129695, 127863, 128521, 129725, 128430, 128732, 128105, 128111, + 128098, 128090, 128082, 128097, 128698, 11825, 8288, 128506, 128543, + 129713, 8361, 129717, 128058, 127873, 8768, 129340, 128295, 9997, 983233, + 8999, 129659, 129644, 129643, 129641, 129639, 129642, 129645, 129640, + 129637, 129636, 129634, 129632, 129635, 129638, 129633, 8891, 129393, + 128155, 165, 69292, 69291, 69293, 69256, 69255, 69254, 69281, 69268, + 69259, 69248, 69271, 69289, 69286, 69287, 69257, 69278, 69277, 69279, + 69276, 69280, 69296, 69282, 69251, 69250, 69266, 69265, 69267, 69253, + 69252, 69269, 69274, 69275, 69284, 69285, 69272, 69258, 69288, 69297, + 69263, 69260, 69270, 69262, 69261, 69249, 69283, 69273, 69264, 42139, + 42149, 42173, 42172, 42132, 42147, 42179, 42174, 42148, 42169, 42150, + 42134, 42166, 42135, 42145, 42143, 42137, 42175, 42157, 42154, 42167, + 42165, 42163, 42130, 42182, 42129, 42171, 42138, 42140, 42136, 42131, + 42151, 42164, 42181, 42142, 42156, 42170, 42176, 42178, 42160, 42133, + 42144, 42152, 42159, 42161, 42158, 42141, 42146, 42177, 42180, 42155, + 42162, 42128, 42168, 42153, 41070, 41059, 41060, 41058, 41073, 41072, + 41071, 41068, 41069, 41066, 41067, 41065, 41048, 41052, 41053, 41050, + 41051, 41049, 41046, 41047, 41056, 41057, 41054, 41055, 41063, 41064, + 41061, 41062, 41076, 41077, 41074, 41075, 41006, 40995, 40996, 40994, + 41009, 41008, 41007, 41004, 41005, 41002, 41003, 41001, 40984, 40988, + 40989, 40986, 40987, 40985, 40982, 40983, 40992, 40993, 40990, 40991, + 40999, 41000, 40997, 40998, 41012, 41015, 41014, 41013, 41010, 41011, + 41842, 41831, 41832, 41829, 41830, 41845, 41844, 41843, 41841, 41827, + 41828, 41825, 41826, 41839, 41840, 41837, 41838, 41835, 41836, 41833, + 41834, 41848, 41851, 41850, 41849, 41846, 41847, 41670, 41659, 41660, + 41658, 41673, 41672, 41671, 41668, 41669, 41666, 41667, 41665, 41648, + 41652, 41653, 41650, 41651, 41649, 41646, 41647, 41656, 41657, 41654, + 41655, 41663, 41664, 41661, 41662, 41676, 41679, 41678, 41677, 41674, + 41675, 41293, 41282, 41283, 41281, 41296, 41295, 41294, 41291, 41292, + 41272, 41275, 41276, 41274, 41273, 41270, 41271, 41289, 41290, 41288, + 41279, 41280, 41277, 41278, 41286, 41287, 41284, 41285, 41238, 41228, + 41227, 41241, 41240, 41239, 41236, 41237, 41218, 41221, 41222, 41220, + 41219, 41216, 41217, 41234, 41235, 41233, 41225, 41226, 41223, 41224, + 41231, 41232, 41229, 41230, 41174, 41175, 41173, 41171, 41172, 41169, + 41170, 41167, 41168, 41165, 41166, 41184, 41185, 41182, 41183, 41178, + 41181, 41180, 41179, 41176, 41177, 41494, 41496, 41497, 41495, 41492, + 41493, 41516, 41504, 41505, 41502, 41503, 41519, 41518, 41517, 41514, + 41515, 41500, 41501, 41498, 41499, 41512, 41513, 41510, 41511, 41508, + 41509, 41506, 41507, 41460, 41448, 41449, 41446, 41447, 41463, 41462, + 41461, 41458, 41459, 41436, 41440, 41441, 41438, 41439, 41437, 41434, + 41435, 41444, 41445, 41442, 41443, 41456, 41457, 41454, 41455, 41452, + 41453, 41450, 41451, 41584, 41583, 41582, 41389, 41379, 41380, 41378, + 41392, 41391, 41390, 41387, 41388, 41369, 41372, 41373, 41371, 41370, + 41367, 41368, 41385, 41386, 41384, 41382, 41383, 41381, 41376, 41377, + 41374, 41375, 41395, 41398, 41397, 41396, 41393, 41394, 41125, 41117, + 41118, 41116, 41128, 41127, 41126, 41123, 41124, 41107, 41110, 41111, + 41109, 41108, 41105, 41106, 41114, 41115, 41112, 41113, 41121, 41122, + 41119, 41120, 41130, 41133, 41132, 41131, 41129, 41336, 41334, 41335, + 41333, 41332, 41340, 41338, 41339, 41337, 41322, 41326, 41327, 41324, + 41325, 41323, 41320, 41321, 41330, 41331, 41328, 41329, 41556, 41557, + 41554, 41555, 41563, 41564, 41562, 41544, 41548, 41549, 41546, 41547, + 41545, 41542, 41543, 41552, 41553, 41550, 41551, 41560, 41561, 41558, + 41559, 41591, 41592, 41589, 41590, 41598, 41599, 41597, 41587, 41588, + 41585, 41586, 41595, 41596, 41593, 41594, 40962, 40960, 983243, 40966, + 40967, 40964, 40965, 40963, 40961, 42025, 42017, 42018, 42016, 42028, + 42027, 42026, 42023, 42024, 42010, 42014, 42015, 42012, 42013, 42011, + 42008, 42009, 42021, 42022, 42019, 42020, 42031, 42032, 42029, 42030, + 41970, 41962, 41963, 41960, 41961, 41973, 41972, 41971, 41968, 41969, + 41954, 41958, 41959, 41956, 41957, 41955, 41952, 41953, 41966, 41967, + 41964, 41965, 41976, 41979, 41978, 41977, 41974, 41975, 41488, 41476, + 41477, 41475, 41491, 41490, 41489, 41486, 41487, 41466, 41469, 41470, + 41468, 41467, 41464, 41465, 41473, 41474, 41471, 41472, 41484, 41485, + 41482, 41483, 41480, 41481, 41478, 41479, 41424, 41413, 41414, 41411, + 41412, 41427, 41426, 41425, 41422, 41423, 41420, 41421, 41419, 41401, + 41405, 41406, 41403, 41404, 41402, 41399, 41400, 41409, 41410, 41407, + 41408, 41417, 41418, 41415, 41416, 41430, 41433, 41432, 41431, 41428, + 41429, 41538, 41527, 41528, 41526, 41541, 41540, 41539, 41536, 41537, + 41534, 41535, 41533, 41524, 41525, 41522, 41523, 41531, 41532, 41529, + 41530, 41521, 41520, 41157, 41147, 41148, 41145, 41146, 41160, 41159, + 41158, 41155, 41156, 41136, 41139, 41140, 41138, 41137, 41134, 41135, + 41143, 41144, 41141, 41142, 41151, 41152, 41149, 41150, 41163, 41164, + 41161, 41162, 41154, 41153, 41080, 41083, 41084, 41082, 41081, 41078, + 41079, 41087, 41088, 41085, 41086, 41091, 41092, 41089, 41090, 41095, + 41098, 41097, 41096, 41093, 41094, 41101, 41104, 41103, 41102, 41099, + 41100, 41299, 41302, 41301, 41300, 41297, 41298, 41312, 41313, 41311, + 41305, 41306, 41303, 41304, 41309, 41310, 41307, 41308, 41316, 41319, + 41318, 41317, 41314, 41315, 41574, 41572, 41573, 41580, 41581, 41579, + 41566, 41567, 41565, 41570, 41571, 41568, 41569, 41577, 41578, 41575, + 41576, 42048, 42042, 42041, 42051, 42050, 42049, 42047, 42035, 42039, + 42040, 42037, 42038, 42036, 42033, 42034, 42045, 42046, 42043, 42044, + 42054, 42057, 42056, 42055, 42052, 42053, 41881, 41882, 41880, 41878, + 41879, 41876, 41877, 41885, 41886, 41883, 41884, 41889, 41892, 41891, + 41890, 41887, 41888, 41895, 41898, 41897, 41896, 41893, 41894, 42075, + 42067, 42068, 42066, 42076, 42073, 42074, 42060, 42064, 42065, 42062, + 42063, 42061, 42058, 42059, 42071, 42072, 42069, 42070, 41727, 41721, + 41720, 41730, 41729, 41728, 41726, 41723, 41722, 41711, 41714, 41715, + 41713, 41712, 41709, 41710, 41718, 41719, 41716, 41717, 41733, 41736, + 41735, 41734, 41731, 41732, 41725, 41724, 41363, 41352, 41353, 41351, + 41366, 41365, 41364, 41361, 41362, 41343, 41346, 41347, 41345, 41344, + 41341, 41342, 41349, 41350, 41348, 41359, 41360, 41358, 41356, 41357, + 41354, 41355, 41036, 41028, 41029, 41027, 41039, 41038, 41037, 41034, + 41035, 41018, 41021, 41022, 41020, 41019, 41016, 41017, 41025, 41026, + 41023, 41024, 41032, 41033, 41030, 41031, 41042, 41045, 41044, 41043, + 41040, 41041, 41998, 41990, 41991, 41988, 41989, 42001, 42000, 41999, + 41996, 41997, 41982, 41986, 41987, 41984, 41985, 41983, 41980, 41981, + 41994, 41995, 41992, 41993, 42004, 42007, 42006, 42005, 42002, 42003, + 42115, 42107, 42108, 42105, 42106, 42118, 42117, 42116, 42113, 42114, + 42099, 42103, 42104, 42101, 42102, 42100, 42097, 42098, 42111, 42112, + 42109, 42110, 42121, 42124, 42123, 42122, 42119, 42120, 41866, 41855, + 41854, 41869, 41868, 41867, 41864, 41865, 41862, 41863, 41860, 41861, + 41858, 41859, 41856, 41857, 41872, 41875, 41874, 41873, 41870, 41871, + 41853, 41852, 41942, 41931, 41932, 41930, 41945, 41944, 41943, 41940, + 41941, 41938, 41939, 41937, 41928, 41929, 41926, 41927, 41935, 41936, + 41933, 41934, 41948, 41951, 41950, 41949, 41946, 41947, 41772, 41775, + 41776, 41774, 41773, 41770, 41771, 41786, 41787, 41785, 41779, 41780, + 41777, 41778, 41783, 41784, 41781, 41782, 41790, 41791, 41788, 41789, + 41794, 41797, 41796, 41795, 41792, 41793, 41916, 41904, 41905, 41903, + 41919, 41918, 41917, 41914, 41915, 41901, 41902, 41899, 41900, 41912, + 41913, 41910, 41911, 41908, 41909, 41906, 41907, 41922, 41925, 41924, + 41923, 41920, 41921, 41760, 41749, 41750, 41748, 41763, 41762, 41761, + 41758, 41759, 41739, 41742, 41743, 41741, 41740, 41737, 41738, 41756, + 41757, 41755, 41746, 41747, 41744, 41745, 41753, 41754, 41751, 41752, + 41766, 41769, 41768, 41767, 41764, 41765, 41266, 41255, 41256, 41253, + 41254, 41269, 41268, 41267, 41264, 41265, 41244, 41247, 41248, 41246, + 41245, 41242, 41243, 41262, 41263, 41261, 41251, 41252, 41249, 41250, + 41259, 41260, 41257, 41258, 41203, 41202, 41188, 41192, 41193, 41190, + 41191, 41189, 41186, 41187, 41196, 41197, 41194, 41195, 41200, 41201, + 41198, 41199, 41206, 41209, 41208, 41207, 41204, 41205, 41212, 41215, + 41214, 41213, 41210, 41211, 40981, 41605, 41606, 41604, 41611, 41612, + 41610, 41608, 41609, 41607, 41602, 41603, 41600, 41601, 42079, 42083, + 42084, 42081, 42082, 42080, 42077, 42078, 42089, 42090, 42087, 42088, + 42093, 42096, 42095, 42094, 42091, 42092, 42086, 42085, 41815, 41803, + 41804, 41802, 41818, 41817, 41816, 41813, 41814, 41800, 41801, 41798, + 41799, 41811, 41812, 41809, 41810, 41807, 41808, 41805, 41806, 41821, + 41824, 41823, 41822, 41819, 41820, 41636, 41625, 41626, 41624, 41639, + 41638, 41637, 41634, 41635, 41615, 41618, 41619, 41617, 41616, 41613, + 41614, 41696, 41697, 41695, 41693, 41694, 41692, 41682, 41686, 41687, + 41684, 41685, 41683, 41680, 41681, 41690, 41691, 41688, 41689, 41699, + 41702, 41701, 41700, 41698, 41705, 41708, 41707, 41706, 41703, 41704, + 41632, 41633, 41631, 41622, 41623, 41620, 41621, 41629, 41630, 41627, + 41628, 41642, 41645, 41644, 41643, 41640, 41641, 40973, 40974, 40972, + 40970, 40971, 40968, 40969, 40977, 40978, 40975, 40976, 40980, 40979, + 9775, 129664, 8959, 10853, 10632, 10634, 10814, 10852, 10631, 10633, + 10783, 10784, 10785, 10625, 10626, 72262, 72256, 72253, 72252, 72254, + 72251, 72250, 72261, 72255, 72243, 72215, 72214, 72230, 72229, 72220, + 72219, 72242, 72204, 72203, 72207, 72216, 72211, 72221, 72238, 72239, + 72240, 72228, 72227, 72213, 72212, 72218, 72217, 72225, 72224, 72209, + 72208, 72206, 72205, 72223, 72222, 72231, 72232, 72233, 72241, 72210, + 72236, 72226, 72235, 72237, 72234, 72192, 72259, 72258, 72260, 72257, + 72248, 72245, 72246, 72247, 72244, 72249, 72263, 72202, 72199, 72200, + 72198, 72197, 72195, 72194, 72201, 72196, 72193, 129427, 65279, 8204, + 8203, 8205, 11234, 129296, 118593, 118584, 118585, 118591, 118580, + 118589, 118528, 118540, 118531, 118543, 118559, 118529, 118541, 118532, + 118544, 118592, 118573, 118569, 118568, 118581, 118586, 118561, 118582, + 118583, 118566, 118538, 118550, 118555, 118556, 118535, 118547, 118537, + 118549, 118553, 118558, 118534, 118546, 118572, 118562, 118571, 118554, + 118533, 118545, 118587, 118588, 118530, 118542, 118552, 118563, 118539, + 118551, 118557, 118536, 118548, 118579, 118570, 118560, 118567, 118565, + 118564, 118590, 118576, 118577, 118578, 118619, 118639, 118637, 118645, + 118721, 118611, 118635, 118659, 118626, 118623, 118625, 118624, 118622, + 118638, 118612, 118660, 118608, 118609, 118657, 118719, 118695, 118699, + 118698, 118697, 118696, 118722, 118720, 118703, 118708, 118707, 118706, + 118705, 118704, 118610, 118620, 118723, 118616, 118617, 118640, 118672, + 118636, 118658, 118652, 118651, 118649, 118650, 118648, 118646, 118647, + 118644, 118643, 118641, 118642, 118653, 118656, 118654, 118655, 118662, + 118670, 118664, 118666, 118669, 118663, 118665, 118671, 118667, 118668, + 118673, 118614, 118615, 118618, 118685, 118687, 118684, 118683, 118686, + 118681, 118680, 118709, 118713, 118711, 118716, 118717, 118714, 118715, + 118712, 118718, 118710, 118676, 118679, 118690, 118688, 118693, 118694, + 118691, 118692, 118689, 118675, 118677, 118678, 118674, 118701, 118702, + 118700, 118682, 118632, 118631, 118634, 118633, 118628, 118627, 118630, + 118629, 118613, 118621, 118661, 118596, 118597, 118594, 118595, 118598, + 129503, 983264, 983222, 983221, 983223, }; -static const unsigned short phrasebook_offset1[] = { +#define DAWG_CODEPOINT_TO_POS_SHIFT 8 +#define DAWG_CODEPOINT_TO_POS_NOTFOUND 35762 +static const unsigned char dawg_codepoint_to_pos_index1[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, - 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, - 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, - 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, - 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 105, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, - 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 130, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 131, 132, 133, - 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, - 148, 104, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, - 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 104, 171, 172, 173, - 174, 175, 176, 177, 178, 179, 180, 181, 104, 182, 183, 104, 184, 185, - 186, 187, 104, 188, 189, 190, 191, 192, 193, 194, 104, 195, 196, 197, - 198, 104, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, - 211, 212, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 213, 214, 215, 216, 217, 218, - 219, 220, 221, 222, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 223, 224, 225, 226, 227, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 228, 229, 230, 231, 232, - 233, 234, 235, 104, 104, 104, 104, 236, 237, 238, 239, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 250, 251, - 252, 253, 254, 255, 256, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 257, 258, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 259, 260, 261, 262, 263, 264, 265, 266, 267, - 104, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, - 281, 104, 104, 104, 104, 104, 104, 104, 104, 282, 104, 283, 284, 285, - 104, 104, 286, 104, 104, 104, 287, 104, 104, 104, 104, 104, 288, 289, - 290, 291, 104, 104, 104, 104, 104, 292, 293, 294, 104, 295, 296, 104, - 104, 297, 298, 299, 300, 301, 104, 302, 303, 304, 305, 306, 307, 308, - 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 320, 321, 322, - 323, 324, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 325, 104, 326, 327, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 328, 329, 330, - 331, 332, 333, 334, 335, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, + 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 53, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 54, 55, 56, 57, 58, + 59, 60, 61, 62, 63, 64, 65, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 66, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 67, 68, 69, 70, 71, 72, + 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, + 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, + 107, 108, 109, 110, 111, 52, 52, 52, 52, 52, 52, 52, 52, 52, 112, 113, + 114, 115, 116, 117, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 118, 119, 120, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 121, 122, 123, 124, 52, 52, 125, 126, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 127, 128, 129, 130, 131, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 132, 133, 134, 135, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 136, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 52, 52, + 52, 52, 149, 150, 151, 152, 52, 153, 52, 52, 154, 155, 156, 52, 52, 157, + 158, 159, 52, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 172, 173, 174, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 175, + 176, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 177, 178, 179, 180, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, }; -static const unsigned int phrasebook_offset2[] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1, 3, 6, 9, 11, 14, 17, 19, 21, 24, 27, 29, 31, - 33, 35, 39, 41, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 69, 72, - 75, 78, 82, 86, 91, 96, 101, 105, 110, 115, 120, 124, 129, 134, 138, 143, - 148, 152, 157, 162, 166, 171, 176, 180, 185, 190, 195, 200, 205, 209, - 213, 217, 221, 224, 228, 232, 237, 242, 247, 251, 256, 261, 266, 270, - 275, 280, 284, 289, 294, 298, 303, 308, 312, 317, 322, 326, 331, 336, - 341, 346, 351, 356, 359, 364, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 366, 370, 375, - 378, 381, 384, 387, 390, 393, 395, 398, 404, 412, 415, 419, 422, 424, - 427, 430, 433, 436, 440, 443, 446, 449, 451, 454, 460, 468, 475, 482, - 489, 494, 501, 508, 515, 522, 529, 537, 542, 550, 558, 566, 574, 582, - 590, 598, 606, 614, 619, 627, 634, 641, 648, 655, 662, 665, 671, 678, - 685, 692, 699, 707, 712, 719, 726, 733, 740, 747, 754, 762, 767, 775, - 783, 791, 799, 807, 815, 823, 831, 839, 844, 852, 859, 866, 873, 880, - 887, 890, 896, 903, 910, 917, 924, 932, 937, 945, 952, 959, 966, 973, - 980, 987, 995, 1003, 1011, 1019, 1027, 1035, 1043, 1051, 1059, 1067, - 1074, 1081, 1089, 1097, 1105, 1113, 1121, 1129, 1137, 1145, 1153, 1161, - 1169, 1177, 1185, 1193, 1201, 1209, 1217, 1225, 1233, 1241, 1248, 1255, - 1263, 1271, 1279, 1287, 1295, 1303, 1311, 1319, 1327, 1333, 1338, 1343, - 1351, 1359, 1367, 1375, 1380, 1388, 1396, 1404, 1412, 1420, 1428, 1437, - 1446, 1453, 1460, 1468, 1476, 1484, 1492, 1500, 1508, 1519, 1524, 1529, - 1536, 1543, 1550, 1557, 1565, 1573, 1578, 1583, 1591, 1599, 1607, 1615, - 1623, 1631, 1639, 1647, 1655, 1663, 1671, 1679, 1687, 1695, 1703, 1711, - 1719, 1727, 1734, 1741, 1748, 1755, 1762, 1769, 1776, 1783, 1791, 1799, - 1807, 1815, 1822, 1829, 1837, 1845, 1853, 1861, 1869, 1877, 1885, 1893, - 1901, 1909, 1917, 1923, 1929, 1935, 1942, 1949, 1954, 1959, 1965, 1972, - 1979, 1986, 1993, 2001, 2009, 2015, 2021, 2026, 2032, 2039, 2046, 2053, - 2058, 2063, 2068, 2075, 2082, 2089, 2096, 2103, 2109, 2117, 2127, 2135, - 2142, 2149, 2154, 2159, 2166, 2173, 2177, 2182, 2187, 2192, 2200, 2209, - 2216, 2223, 2232, 2239, 2246, 2251, 2258, 2265, 2272, 2279, 2286, 2291, - 2298, 2305, 2313, 2318, 2323, 2328, 2338, 2342, 2348, 2354, 2360, 2366, - 2374, 2387, 2395, 2400, 2410, 2415, 2420, 2430, 2435, 2442, 2449, 2457, - 2465, 2472, 2479, 2486, 2493, 2503, 2513, 2523, 2533, 2543, 2553, 2563, - 2573, 2578, 2588, 2598, 2608, 2618, 2626, 2634, 2641, 2648, 2656, 2664, - 2672, 2680, 2687, 2694, 2704, 2714, 2722, 2730, 2738, 2743, 2753, 2758, - 2766, 2774, 2779, 2784, 2792, 2800, 2811, 2822, 2830, 2838, 2848, 2858, - 2866, 2874, 2883, 2892, 2901, 2910, 2920, 2930, 2939, 2948, 2958, 2968, - 2976, 2984, 2993, 3002, 3011, 3020, 3030, 3040, 3048, 3056, 3065, 3074, - 3083, 3092, 3101, 3110, 3115, 3120, 3128, 3136, 3146, 3154, 3159, 3164, - 3171, 3178, 3185, 3192, 3200, 3208, 3218, 3228, 3238, 3248, 3255, 3262, - 3272, 3282, 3290, 3298, 3306, 3314, 3322, 3329, 3336, 3343, 3349, 3356, - 3363, 3370, 3379, 3389, 3399, 3406, 3413, 3419, 3424, 3430, 3437, 3444, - 3451, 3458, 3469, 3479, 3486, 3493, 3500, 3507, 3512, 3517, 3523, 3529, - 3535, 3543, 3551, 3558, 3564, 3569, 3576, 3582, 3590, 3601, 3611, 3620, - 3627, 3633, 3639, 3644, 3651, 3657, 3664, 3671, 3678, 3683, 3688, 3697, - 3705, 3714, 3719, 3725, 3735, 3742, 3750, 3759, 3765, 3771, 3777, 3784, - 3789, 3794, 3804, 3812, 3821, 3829, 3837, 3847, 3852, 3859, 3866, 3871, - 3883, 3892, 3900, 3906, 3915, 3920, 3925, 3932, 3938, 3944, 3950, 3956, - 3965, 3973, 3978, 3986, 3992, 4000, 4008, 4014, 4020, 4026, 4034, 4042, - 4048, 4056, 4062, 4067, 4074, 4082, 4092, 4099, 4106, 4116, 4123, 4130, - 4140, 4147, 4154, 4161, 4167, 4173, 4182, 4194, 4199, 4206, 4211, 4215, - 4220, 4228, 4235, 4240, 4245, 4249, 4254, 4259, 4263, 4269, 4275, 4281, - 4287, 4295, 4300, 4305, 4310, 4315, 4321, 4323, 4328, 4332, 4338, 4344, - 4350, 4355, 4362, 4369, 4375, 4382, 4390, 4398, 4403, 4408, 4412, 4417, - 4419, 4421, 4424, 4426, 4429, 4434, 4439, 4445, 4450, 4454, 4459, 4464, - 4473, 4479, 4484, 4490, 4495, 4501, 4509, 4517, 4521, 4525, 4530, 4536, - 4542, 4548, 4554, 4559, 4566, 4574, 4582, 4587, 4593, 4600, 4607, 4614, - 4621, 4625, 4631, 4636, 4641, 4646, 4651, 4654, 4657, 4660, 4663, 4666, - 4669, 4673, 4677, 4683, 4686, 4691, 4697, 4703, 4706, 4711, 4716, 4720, - 4726, 4731, 4737, 4743, 4748, 4753, 4758, 4761, 4767, 4772, 4777, 4781, - 4786, 4792, 4798, 4801, 4805, 4809, 4813, 4816, 4819, 4824, 4828, 4835, - 4839, 4845, 4849, 4855, 4859, 4863, 4867, 4872, 4877, 4884, 4890, 4897, - 4903, 4909, 4915, 4918, 4922, 4926, 4930, 4934, 4939, 4944, 4948, 4952, - 4958, 4962, 4966, 4971, 4977, 4982, 4988, 4992, 4999, 5004, 5009, 5014, - 5019, 5025, 5028, 5032, 5037, 5042, 5051, 5057, 5061, 5065, 5070, 5074, - 5079, 5083, 5087, 5092, 5096, 5102, 5107, 5112, 5117, 5122, 5127, 5132, - 5138, 5144, 5150, 5156, 5161, 5167, 5173, 5179, 5184, 5189, 5196, 5203, - 5207, 5212, 5219, 0, 0, 5226, 5229, 5238, 5247, 5258, 5262, 0, 0, 0, 0, - 5267, 5270, 5275, 5283, 5288, 5296, 5304, 0, 5312, 0, 5320, 5328, 5336, - 5347, 5352, 5357, 5362, 5367, 5372, 5377, 5382, 5387, 5392, 5397, 5402, - 5407, 5412, 5417, 5422, 5427, 0, 5432, 5437, 5442, 5447, 5452, 5457, - 5462, 5467, 5475, 5483, 5491, 5499, 5507, 5515, 5526, 5531, 5536, 5541, - 5546, 5551, 5556, 5561, 5566, 5571, 5576, 5581, 5586, 5591, 5596, 5601, - 5606, 5611, 5617, 5622, 5627, 5632, 5637, 5642, 5647, 5652, 5660, 5668, - 5676, 5684, 5692, 5697, 5701, 5705, 5712, 5722, 5732, 5736, 5740, 5744, - 5750, 5757, 5761, 5766, 5770, 5775, 5779, 5784, 5788, 5793, 5798, 5803, - 5808, 5813, 5818, 5823, 5828, 5833, 5838, 5843, 5848, 5853, 5858, 5863, - 5867, 5871, 5877, 5881, 5886, 5892, 5900, 5905, 5910, 5917, 5922, 5927, - 5934, 5943, 5952, 5963, 5971, 5976, 5981, 5986, 5993, 5998, 6004, 6009, - 6014, 6019, 6024, 6029, 6034, 6042, 6048, 6053, 6057, 6062, 6067, 6072, - 6077, 6082, 6087, 6092, 6096, 6102, 6106, 6111, 6116, 6121, 6125, 6130, - 6135, 6140, 6145, 6149, 6154, 6158, 6163, 6168, 6173, 6178, 6184, 6189, - 6195, 6199, 6204, 6208, 6212, 6217, 6222, 6227, 6232, 6237, 6242, 6247, - 6251, 6257, 6261, 6266, 6271, 6276, 6280, 6285, 6290, 6295, 6300, 6304, - 6309, 6313, 6318, 6323, 6328, 6333, 6339, 6344, 6350, 6354, 6359, 6363, - 6371, 6376, 6381, 6386, 6393, 6398, 6404, 6409, 6414, 6419, 6424, 6429, - 6434, 6442, 6448, 6453, 6458, 6463, 6468, 6473, 6479, 6485, 6492, 6499, - 6508, 6517, 6524, 6531, 6540, 6549, 6554, 6559, 6564, 6569, 6574, 6579, - 6584, 6589, 6600, 6611, 6616, 6621, 6628, 6635, 6643, 6651, 6656, 6661, - 6666, 6671, 6675, 6679, 6683, 6689, 6695, 6699, 6706, 6711, 6721, 6731, - 6737, 6743, 6751, 6759, 6767, 6775, 6782, 6789, 6797, 6805, 6813, 6821, - 6829, 6837, 6845, 6853, 6861, 6869, 6876, 6883, 6889, 6895, 6903, 6911, - 6918, 6925, 6933, 6941, 6947, 6953, 6961, 6969, 6977, 6985, 6991, 6997, - 7005, 7013, 7021, 7029, 7036, 7043, 7051, 7059, 7067, 7075, 7080, 7085, - 7092, 7099, 7109, 7119, 7123, 7131, 7139, 7146, 7153, 7161, 7169, 7176, - 7183, 7191, 7199, 7206, 7213, 7221, 7229, 7234, 7241, 7248, 7255, 7262, - 7268, 7274, 7282, 7290, 7295, 7300, 7308, 7316, 7324, 7332, 7340, 7348, - 7355, 7362, 7370, 7378, 7386, 7394, 7401, 7408, 7414, 7420, 7429, 7438, - 7446, 7454, 7461, 7468, 7475, 7482, 7490, 7498, 7506, 7514, 7522, 7530, - 7538, 7546, 7556, 7566, 7573, 7580, 7587, 7594, 7601, 7608, 7615, 7622, - 7629, 7636, 7643, 7650, 7657, 7664, 7671, 7678, 7685, 7692, 7699, 7706, - 7713, 7720, 7727, 7734, 7739, 7744, 7749, 7754, 7759, 7764, 7769, 7774, - 7779, 7784, 7790, 7796, 7804, 7812, 7820, 7828, 7836, 7844, 7852, 7860, - 7868, 7876, 7881, 7886, 7891, 7896, 7904, 0, 7912, 7918, 7924, 7930, - 7936, 7942, 7948, 7954, 7960, 7965, 7971, 7977, 7983, 7989, 7995, 8001, - 8007, 8013, 8019, 8025, 8031, 8037, 8043, 8049, 8055, 8061, 8067, 8073, - 8078, 8084, 8090, 8096, 8102, 8108, 8114, 8120, 8126, 8132, 0, 0, 8138, - 8146, 8150, 8155, 8160, 8164, 8169, 8174, 8181, 8187, 8193, 8199, 8205, - 8211, 8217, 8223, 8229, 8234, 8240, 8246, 8252, 8258, 8264, 8270, 8276, - 8282, 8288, 8294, 8300, 8306, 8312, 8318, 8324, 8330, 8336, 8342, 8347, - 8353, 8359, 8365, 8371, 8377, 8383, 8389, 8395, 8401, 8407, 8415, 8422, - 8428, 0, 0, 8432, 8439, 8446, 0, 8451, 8456, 8461, 8466, 8473, 8480, - 8485, 8490, 8495, 8500, 8505, 8510, 8515, 8522, 8527, 8534, 8541, 8546, - 8553, 8558, 8563, 8568, 8575, 8580, 8585, 8592, 8601, 8606, 8611, 8616, - 8621, 8627, 8632, 8639, 8646, 8653, 8658, 8663, 8668, 8673, 8678, 8683, - 8693, 8698, 8707, 8712, 8717, 8722, 8727, 8734, 8741, 8748, 8753, 8758, - 8765, 0, 0, 0, 0, 0, 0, 0, 0, 8772, 8776, 8780, 8784, 8788, 8792, 8796, - 8800, 8804, 8808, 8812, 8817, 8821, 8825, 8830, 8834, 8839, 8843, 8847, - 8851, 8856, 8860, 8865, 8869, 8873, 8877, 8881, 0, 0, 0, 0, 8885, 8890, - 8897, 8905, 8912, 8917, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8922, 8925, - 8929, 8934, 8938, 8942, 8946, 8952, 8958, 8961, 8968, 8977, 8980, 8983, - 8988, 8994, 8998, 9006, 9012, 9018, 9026, 9030, 9035, 9046, 9051, 9055, - 9059, 9063, 9066, 9069, 9076, 9083, 9087, 9093, 9097, 9104, 9111, 9119, - 9126, 9133, 9137, 9141, 9147, 9151, 9155, 9159, 9163, 9167, 9171, 9175, - 9179, 9183, 9187, 9191, 9195, 9199, 9203, 9207, 9211, 9215, 9223, 9231, - 9241, 9250, 9259, 9262, 9266, 9270, 9274, 9278, 9282, 9286, 9290, 9294, - 9299, 9303, 9306, 9309, 9312, 9315, 9318, 9321, 9324, 9327, 9331, 9335, - 9339, 9344, 9349, 9355, 9358, 9365, 9374, 9379, 9384, 9391, 9397, 9402, - 9406, 9410, 9414, 9418, 9422, 9426, 9430, 9434, 9438, 9442, 9447, 9452, - 9459, 9465, 9471, 9477, 9482, 9491, 9500, 9505, 9512, 9519, 9526, 9533, - 9537, 9541, 9545, 9552, 9562, 9566, 9570, 9574, 9581, 9589, 9593, 9597, - 9604, 9608, 9612, 9616, 9623, 9630, 9642, 9646, 9650, 9654, 9664, 9673, - 9677, 9685, 9692, 9699, 9708, 9719, 9727, 9731, 9740, 9751, 9759, 9772, - 9780, 9788, 9796, 9804, 9810, 9819, 9826, 9830, 9838, 9842, 9849, 9857, - 9861, 9867, 9874, 9881, 9885, 9893, 9897, 9904, 9908, 9916, 9920, 9928, - 9936, 9943, 9951, 9959, 9966, 9972, 9976, 9983, 9991, 9997, 10004, 10011, - 10017, 10027, 10035, 10042, 10048, 10052, 10055, 10059, 10065, 10073, - 10077, 10083, 10089, 10096, 10103, 10106, 10113, 10118, 10127, 10132, - 10136, 10149, 10162, 10168, 10175, 10180, 10186, 10191, 10197, 10207, - 10214, 10223, 10233, 10239, 10244, 10249, 10253, 10257, 10262, 10267, - 10273, 10281, 10289, 10300, 10305, 10314, 10323, 10330, 10336, 10342, - 10348, 10354, 10360, 10366, 10372, 10378, 10384, 10391, 10398, 10405, - 10411, 10419, 10428, 10435, 10443, 10451, 10457, 10463, 10469, 10477, - 10484, 10494, 10503, 10507, 10513, 10519, 0, 10525, 10530, 10535, 10542, - 10547, 10552, 10559, 10564, 10573, 10578, 10583, 10588, 10593, 10598, - 10605, 10610, 10617, 10622, 10627, 10632, 10637, 10642, 10648, 10652, - 10657, 10664, 10669, 10674, 10679, 10684, 10689, 10696, 10703, 10710, - 10715, 10720, 10726, 10731, 10736, 10742, 10747, 10752, 10760, 10768, - 10773, 10778, 10784, 10789, 10794, 10798, 10804, 10808, 10812, 10818, - 10824, 10829, 10834, 10841, 10848, 10852, 0, 0, 10856, 10863, 10870, - 10877, 10887, 10899, 10911, 10928, 10940, 10951, 10959, 10966, 10977, - 10992, 11003, 11009, 11018, 11026, 11038, 11048, 11056, 11068, 11075, - 11083, 11095, 11101, 11107, 11115, 11123, 11131, 11137, 11147, 11155, - 11165, 11175, 11188, 11202, 11216, 11226, 11237, 11248, 11261, 11274, - 11288, 11300, 11312, 11325, 11338, 11350, 11363, 11372, 11380, 11385, - 11390, 11395, 11400, 11405, 11410, 11415, 11420, 11425, 11430, 11435, - 11440, 11445, 11450, 11455, 11460, 11465, 11470, 11475, 11480, 11485, - 11490, 11495, 11500, 11505, 11510, 11515, 11520, 11525, 11530, 11535, - 11540, 11544, 11549, 11554, 11559, 11564, 11569, 11573, 11577, 11581, - 11585, 11589, 11593, 11597, 11601, 11605, 11609, 11613, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 11618, 11623, 11627, 11631, 11635, 11639, 11643, - 11647, 11651, 11655, 11659, 11663, 11668, 11672, 11676, 11680, 11685, - 11689, 11694, 11699, 11704, 11708, 11713, 11718, 11723, 11728, 11732, - 11737, 11741, 11746, 11751, 11755, 11759, 11766, 11770, 11775, 11779, - 11783, 11788, 11792, 11799, 11806, 11813, 11819, 11827, 11835, 11844, - 11852, 11859, 11866, 11874, 11880, 11886, 11892, 11898, 11905, 11910, - 11914, 11919, 0, 0, 11923, 11927, 11932, 11937, 11942, 11947, 11952, - 11957, 11962, 11967, 11972, 11977, 11982, 11987, 11992, 11997, 12002, - 12007, 12012, 12017, 12022, 12027, 12032, 12037, 12042, 12047, 12052, - 12057, 12062, 12067, 12075, 12082, 12088, 12093, 12101, 12108, 12114, - 12121, 12127, 12132, 12139, 12146, 12152, 12157, 12162, 12168, 12173, - 12178, 12184, 0, 0, 12189, 12195, 12201, 12207, 12213, 12219, 12225, - 12230, 12238, 12244, 12250, 12256, 12262, 12268, 12276, 0, 12282, 12287, - 12292, 12297, 12302, 12307, 12312, 12317, 12322, 12327, 12332, 12337, - 12342, 12347, 12352, 12357, 12362, 12367, 12372, 12377, 12382, 12387, - 12392, 12397, 12402, 12407, 12412, 12417, 0, 0, 12422, 0, 12426, 12432, - 12438, 12444, 12450, 12456, 12462, 12468, 12473, 12479, 12485, 0, 0, 0, - 0, 0, 12491, 12499, 12510, 12517, 12524, 12532, 12543, 12553, 12564, - 12575, 12585, 12591, 12605, 12616, 12630, 12645, 12657, 12672, 12681, - 12690, 12698, 12706, 12713, 12719, 12726, 12733, 12743, 12753, 12760, - 12768, 12778, 0, 12782, 12787, 0, 0, 0, 0, 0, 0, 12792, 12799, 12806, - 12813, 12820, 12825, 12831, 12836, 12843, 12852, 12860, 12868, 12876, - 12888, 12895, 12902, 12909, 12921, 12932, 12939, 12947, 12953, 12958, - 12966, 12974, 12982, 12988, 12998, 13006, 13013, 13026, 13034, 13042, - 13051, 13060, 13073, 13079, 13085, 13091, 13099, 13107, 13115, 13123, - 13131, 13139, 13149, 13157, 13165, 13176, 13180, 13186, 13193, 13203, - 13210, 13215, 13222, 13229, 13233, 13239, 13250, 13255, 13262, 13267, - 13272, 13277, 13285, 13293, 13300, 13307, 13314, 13321, 13328, 13335, - 13342, 13348, 13356, 13361, 13366, 13371, 13376, 13381, 13386, 13391, - 13396, 13401, 13406, 13411, 13416, 13421, 13426, 13431, 13436, 13441, - 13447, 13453, 13459, 13464, 13469, 13474, 13479, 13485, 13494, 13502, - 13508, 13516, 13522, 13526, 13530, 13534, 13539, 13542, 13546, 13549, - 13553, 13556, 13560, 13564, 13568, 13573, 13578, 13581, 13585, 13590, - 13595, 13598, 13602, 13605, 13609, 13613, 13617, 13621, 13625, 13629, - 13633, 13637, 13641, 13645, 13649, 13653, 13657, 13661, 13665, 13669, - 13673, 13677, 13680, 13684, 13687, 13691, 13695, 13699, 13702, 13705, - 13708, 13712, 13715, 13719, 13723, 13727, 13731, 13735, 13738, 13741, - 13746, 13751, 13755, 13759, 13764, 13768, 13773, 13777, 13782, 13787, - 13793, 13799, 13805, 13809, 13814, 13820, 13826, 13830, 13835, 13839, - 13845, 13850, 13853, 13859, 13865, 13870, 13875, 13882, 13887, 13892, - 13896, 13900, 13904, 13908, 13912, 13916, 13920, 13924, 13929, 13934, - 13939, 13945, 13948, 13952, 13956, 13959, 13962, 13965, 13968, 13971, - 13974, 13977, 13980, 13983, 13987, 13994, 13999, 14003, 14007, 14011, - 14015, 14019, 14025, 14029, 14033, 14037, 14041, 14047, 14051, 14055, - 14059, 14064, 14069, 0, 14074, 14078, 14083, 14087, 14092, 14096, 14101, - 14106, 0, 0, 14111, 14115, 0, 0, 14120, 14124, 14129, 14133, 14138, - 14143, 14148, 14153, 14158, 14163, 14168, 14173, 14178, 14183, 14188, - 14193, 14198, 14203, 14208, 14213, 14218, 14223, 0, 14227, 14231, 14236, - 14241, 14246, 14250, 14254, 0, 14258, 0, 0, 0, 14262, 14267, 14272, - 14276, 0, 0, 14280, 14285, 14290, 14296, 14301, 14307, 14312, 14318, - 14324, 0, 0, 14331, 14336, 0, 0, 14342, 14347, 14353, 14358, 0, 0, 0, 0, - 0, 0, 0, 0, 14365, 0, 0, 0, 0, 14372, 14377, 0, 14382, 14387, 14393, - 14399, 14405, 0, 0, 14412, 14417, 14421, 14425, 14429, 14433, 14437, - 14441, 14445, 14449, 14453, 14462, 14471, 14476, 14481, 14488, 14495, - 14502, 14509, 14524, 14532, 14536, 14541, 14548, 14553, 0, 0, 14558, - 14565, 14570, 0, 14575, 14579, 14584, 14588, 14593, 14597, 0, 0, 0, 0, - 14602, 14607, 0, 0, 14612, 14617, 14622, 14626, 14631, 14636, 14641, - 14646, 14651, 14656, 14661, 14666, 14671, 14676, 14681, 14686, 14691, - 14696, 14701, 14706, 14711, 14716, 0, 14720, 14724, 14729, 14734, 14739, - 14743, 14747, 0, 14751, 14755, 0, 14760, 14765, 0, 14770, 14774, 0, 0, - 14778, 0, 14783, 14789, 14794, 14800, 14805, 0, 0, 0, 0, 14811, 14817, 0, - 0, 14823, 14829, 14835, 0, 0, 0, 14840, 0, 0, 0, 0, 0, 0, 0, 14845, - 14850, 14855, 14860, 0, 14865, 0, 0, 0, 0, 0, 0, 0, 14870, 14875, 14879, - 14883, 14887, 14891, 14895, 14899, 14903, 14907, 14911, 14915, 14919, - 14923, 14927, 14933, 14938, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14943, 14948, - 14953, 0, 14958, 14962, 14967, 14971, 14976, 14980, 14985, 14990, 14995, - 0, 15001, 15005, 15010, 0, 15016, 15020, 15025, 15029, 15034, 15039, - 15044, 15049, 15054, 15059, 15064, 15069, 15074, 15079, 15084, 15089, - 15094, 15099, 15104, 15109, 15114, 15119, 0, 15123, 15127, 15132, 15137, - 15142, 15146, 15150, 0, 15154, 15158, 0, 15163, 15168, 15173, 15178, - 15182, 0, 0, 15186, 15191, 15196, 15202, 15207, 15213, 15218, 15224, - 15230, 15237, 0, 15244, 15249, 15255, 0, 15262, 15267, 15273, 0, 0, - 15278, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15282, 15288, 15294, - 15300, 0, 0, 15307, 15312, 15316, 15320, 15324, 15328, 15332, 15336, - 15340, 15344, 15348, 15353, 0, 0, 0, 0, 0, 0, 0, 15358, 15363, 15368, - 15373, 15378, 15386, 15394, 0, 15402, 15407, 15412, 0, 15417, 15421, - 15426, 15430, 15435, 15439, 15444, 15449, 0, 0, 15454, 15458, 0, 0, - 15463, 15467, 15472, 15476, 15481, 15486, 15491, 15496, 15501, 15506, - 15511, 15516, 15521, 15526, 15531, 15536, 15541, 15546, 15551, 15556, - 15561, 15566, 0, 15570, 15574, 15579, 15584, 15589, 15593, 15597, 0, - 15601, 15605, 0, 15610, 15615, 15620, 15625, 15629, 0, 0, 15633, 15638, - 15643, 15649, 15654, 15660, 15665, 15671, 15677, 0, 0, 15684, 15689, 0, - 0, 15695, 15700, 15706, 0, 0, 0, 0, 0, 0, 0, 15711, 15716, 15723, 0, 0, - 0, 0, 15730, 15735, 0, 15740, 15745, 15751, 15757, 15763, 0, 0, 15770, - 15775, 15779, 15783, 15787, 15791, 15795, 15799, 15803, 15807, 15811, - 15815, 15820, 15827, 15834, 15841, 15848, 15855, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 15862, 15866, 0, 15870, 15873, 15877, 15880, 15884, 15887, 0, 0, 0, - 15891, 15894, 15898, 0, 15902, 15905, 15909, 15913, 0, 0, 0, 15916, - 15920, 0, 15924, 0, 15928, 15932, 0, 0, 0, 15936, 15940, 0, 0, 0, 15944, - 15947, 15951, 0, 0, 0, 15954, 15957, 15960, 15963, 15967, 15970, 15974, - 15978, 15982, 15986, 15990, 15993, 0, 0, 0, 0, 15996, 16001, 16005, - 16010, 16014, 0, 0, 0, 16019, 16023, 16028, 0, 16033, 16037, 16042, - 16047, 0, 0, 16051, 0, 0, 0, 0, 0, 0, 16054, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 16060, 16064, 16067, 16070, 16073, 16076, 16079, 16082, - 16085, 16088, 16091, 16095, 16100, 16104, 16108, 16112, 16116, 16120, - 16124, 16129, 16133, 0, 0, 0, 0, 0, 16136, 16143, 16148, 16153, 16158, - 16165, 16169, 16174, 16178, 16183, 16187, 16192, 16197, 0, 16202, 16206, - 16211, 0, 16216, 16220, 16225, 16230, 16234, 16239, 16244, 16249, 16254, - 16259, 16264, 16269, 16274, 16279, 16284, 16289, 16294, 16299, 16304, - 16309, 16314, 16319, 16324, 0, 16328, 16332, 16337, 16342, 16347, 16351, - 16355, 16359, 16364, 16368, 16373, 16378, 16383, 16388, 16393, 16397, 0, - 0, 16401, 16406, 16411, 16417, 16422, 16428, 16433, 16439, 16445, 0, - 16452, 16457, 16463, 0, 16469, 16474, 16480, 16486, 0, 0, 0, 0, 0, 0, 0, - 16491, 16496, 0, 16503, 16508, 16513, 0, 0, 16518, 0, 0, 16525, 16531, - 16537, 16543, 0, 0, 16550, 16555, 16559, 16563, 16567, 16571, 16575, - 16579, 16583, 16587, 0, 0, 0, 0, 0, 0, 0, 16591, 16596, 16610, 16623, - 16636, 16649, 16662, 16675, 16688, 16693, 16700, 16705, 16710, 16715, - 16720, 16724, 16729, 16733, 16738, 16742, 16747, 16752, 0, 16757, 16761, - 16766, 0, 16771, 16775, 16780, 16785, 16789, 16794, 16799, 16804, 16809, - 16814, 16819, 16824, 16829, 16834, 16839, 16844, 16849, 16854, 16859, - 16864, 16869, 16874, 16879, 0, 16883, 16887, 16892, 16897, 16902, 16906, - 16910, 16914, 16919, 16923, 0, 16928, 16933, 16938, 16943, 16947, 0, 0, - 16951, 16956, 16961, 16967, 16972, 16978, 16983, 16989, 16995, 0, 17002, - 17007, 17013, 0, 17019, 17024, 17030, 17036, 0, 0, 0, 0, 0, 0, 0, 17041, - 17046, 0, 0, 0, 0, 0, 0, 17053, 17060, 0, 17065, 17071, 17077, 17083, 0, - 0, 17090, 17095, 17099, 17103, 17107, 17111, 17115, 17119, 17123, 17127, - 0, 17131, 17136, 17141, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17149, 17155, - 17159, 17163, 17167, 17173, 17176, 17180, 17183, 17187, 17190, 17194, - 17198, 0, 17202, 17205, 17209, 0, 17213, 17216, 17220, 17224, 17227, - 17231, 17235, 17239, 17243, 17247, 17251, 17255, 17259, 17263, 17267, - 17271, 17275, 17279, 17283, 17287, 17291, 17295, 17299, 17302, 17306, - 17309, 17313, 17317, 17321, 17324, 17327, 17330, 17334, 17337, 17341, - 17345, 17349, 17353, 17357, 17360, 17363, 17367, 17374, 17380, 17384, - 17389, 17393, 17398, 17402, 17407, 17412, 0, 17418, 17422, 17427, 0, - 17432, 17436, 17441, 17446, 17450, 17455, 0, 0, 0, 0, 17459, 17465, - 17471, 17477, 17483, 17489, 17495, 17501, 17507, 17513, 17519, 17525, - 17531, 17536, 17541, 17546, 0, 0, 17552, 17556, 17559, 17562, 17565, - 17568, 17571, 17574, 17577, 17580, 17583, 17587, 17592, 17596, 17602, - 17608, 17614, 17620, 17626, 17632, 17636, 17642, 17648, 17654, 17659, - 17665, 0, 17671, 17675, 17679, 0, 17683, 17687, 17691, 17695, 17699, - 17703, 17707, 17711, 17715, 17719, 17723, 17727, 17731, 17735, 17739, - 17743, 17747, 17751, 0, 0, 0, 17755, 17761, 17767, 17773, 17779, 17785, - 17791, 17797, 17803, 17809, 17815, 17821, 17829, 17835, 17841, 17847, - 17853, 17859, 17865, 17871, 17877, 17883, 17889, 17895, 0, 17901, 17907, - 17913, 17919, 17925, 17931, 17935, 17941, 17945, 0, 17949, 0, 0, 17955, - 17959, 17965, 17971, 17977, 17981, 17987, 0, 0, 0, 17991, 0, 0, 0, 0, - 17995, 18000, 18007, 18014, 18021, 18028, 0, 18035, 0, 18042, 18047, - 18052, 18059, 18066, 18075, 18086, 18095, 0, 0, 0, 0, 0, 0, 18100, 18106, - 18111, 18116, 18121, 18126, 18131, 18136, 18141, 18146, 0, 0, 18151, - 18158, 18165, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18170, 18178, 18186, - 18194, 18202, 18210, 18218, 18226, 18234, 18242, 18250, 18258, 18266, - 18274, 18282, 18289, 18297, 18305, 18313, 18321, 18329, 18336, 18344, - 18352, 18360, 18368, 18376, 18384, 18392, 18400, 18408, 18416, 18424, - 18431, 18439, 18447, 18453, 18461, 18467, 18475, 18483, 18491, 18499, - 18507, 18515, 18522, 18530, 18536, 18543, 18551, 18559, 18567, 18574, - 18582, 18590, 18598, 18605, 18613, 0, 0, 0, 0, 18619, 18626, 18633, - 18641, 18648, 18658, 18668, 18674, 18680, 18686, 18694, 18702, 18710, - 18718, 18724, 18730, 18736, 18742, 18747, 18751, 18755, 18759, 18763, - 18767, 18771, 18775, 18779, 18783, 18789, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 18795, 18800, 0, 18807, 0, 18814, 18821, 18826, 18831, 18838, 0, - 18845, 18852, 18857, 18864, 18871, 18878, 18885, 18892, 18899, 18904, - 18908, 18915, 18922, 18929, 18934, 18939, 18944, 18951, 18958, 18965, - 18972, 18979, 18984, 18989, 0, 18996, 0, 19003, 19008, 19015, 19022, - 19029, 19036, 19043, 19047, 19054, 19058, 19063, 19071, 19077, 19083, - 19088, 19094, 19100, 19106, 19111, 19117, 19124, 19132, 19139, 0, 0, - 19146, 19151, 19157, 19162, 19168, 0, 19174, 0, 19179, 19186, 19193, - 19200, 19207, 19212, 19216, 0, 19220, 19225, 19229, 19233, 19237, 19241, - 19245, 19249, 19253, 19257, 0, 0, 19261, 19267, 19273, 19280, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 19287, 19291, 19302, 19317, 19332, 19342, 19353, 19366, - 19377, 19383, 19391, 19401, 19407, 19415, 19419, 19425, 19431, 19439, - 19449, 19457, 19470, 19476, 19484, 19492, 19504, 19511, 19519, 19527, - 19535, 19543, 19551, 19559, 19569, 19573, 19576, 19579, 19582, 19585, - 19588, 19591, 19594, 19597, 19600, 19604, 19608, 19612, 19616, 19620, - 19624, 19628, 19632, 19636, 19641, 19647, 19657, 19671, 19681, 19687, - 19693, 19701, 19709, 19717, 19725, 19731, 19737, 19740, 19744, 19748, - 19752, 19756, 19760, 19764, 0, 19768, 19772, 19776, 19780, 19784, 19788, - 19792, 19796, 19800, 19804, 19808, 19811, 19814, 19818, 19822, 19826, - 19829, 19833, 19837, 19841, 19845, 19849, 19853, 19857, 19861, 19864, - 19867, 19870, 19874, 19878, 19881, 19884, 19887, 19891, 19896, 19900, 0, - 0, 0, 0, 19904, 19909, 19913, 19918, 19922, 19927, 19932, 19938, 19943, - 19949, 19953, 19958, 19962, 19967, 19977, 19983, 19989, 19996, 20006, - 20012, 20016, 20020, 20026, 20032, 20040, 20046, 20054, 20062, 20070, - 20080, 20088, 20098, 20103, 20109, 20115, 20121, 20127, 20133, 20139, 0, - 20145, 20151, 20157, 20163, 20169, 20175, 20181, 20187, 20193, 20199, - 20205, 20210, 20215, 20221, 20227, 20233, 20238, 20244, 20250, 20256, - 20262, 20268, 20274, 20280, 20286, 20291, 20296, 20301, 20307, 20313, - 20318, 20323, 20328, 20334, 20342, 20349, 0, 20356, 20363, 20376, 20383, - 20390, 20398, 20406, 20412, 20418, 20424, 20434, 20439, 20445, 20455, - 20465, 0, 20475, 20485, 20493, 20505, 20517, 20523, 20537, 20552, 20557, - 20562, 20570, 20578, 20586, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20594, - 20597, 20601, 20605, 20609, 20613, 20617, 20621, 20625, 20629, 20633, - 20637, 20641, 20645, 20649, 20653, 20657, 20661, 20665, 20669, 20673, - 20676, 20679, 20683, 20687, 20691, 20694, 20697, 20700, 20703, 20707, - 20710, 20713, 20717, 20720, 20725, 20728, 20732, 20735, 20739, 20742, - 20747, 20750, 20754, 20761, 20766, 20770, 20775, 20779, 20784, 20788, - 20793, 20800, 20806, 20812, 20816, 20820, 20824, 20828, 20832, 20838, - 20844, 20851, 20857, 20862, 20866, 20869, 20872, 20875, 20878, 20881, - 20884, 20887, 20890, 20893, 20899, 20903, 20907, 20911, 20915, 20919, - 20923, 20927, 20931, 20936, 20940, 20945, 20950, 20956, 20961, 20967, - 20973, 20979, 20985, 20991, 20999, 21007, 21015, 21023, 21032, 21041, - 21052, 21062, 21072, 21083, 21094, 21104, 21114, 21124, 21134, 21144, - 21154, 21164, 21174, 21182, 21189, 21195, 21202, 21207, 21213, 21219, - 21225, 21231, 21237, 21243, 21248, 21254, 21260, 21266, 21272, 21277, - 21286, 21293, 21299, 21307, 21315, 21321, 21327, 21333, 21339, 21347, - 21355, 21365, 21373, 21381, 21387, 21392, 21397, 21402, 21407, 21412, - 21417, 21422, 21427, 21432, 21438, 21444, 21450, 21457, 21462, 21468, - 21473, 21478, 21483, 21488, 21493, 21498, 21503, 21508, 21513, 21518, - 21523, 21528, 21533, 21538, 21543, 21548, 21553, 21558, 21563, 21568, - 21573, 21578, 21583, 21588, 21593, 21598, 21603, 21608, 21613, 21618, - 21623, 21628, 21633, 21638, 21643, 21648, 21653, 0, 21658, 0, 0, 0, 0, 0, - 21663, 0, 0, 21668, 21672, 21676, 21680, 21684, 21688, 21692, 21696, - 21700, 21704, 21708, 21712, 21716, 21720, 21724, 21728, 21732, 21736, - 21740, 21744, 21748, 21752, 21756, 21760, 21764, 21768, 21772, 21776, - 21780, 21784, 21788, 21792, 21796, 21800, 21804, 21808, 21812, 21816, - 21820, 21824, 21828, 21832, 21837, 21841, 21846, 21851, 21855, 21860, - 21865, 21869, 21873, 21877, 21881, 21885, 21889, 21893, 21897, 21901, - 21905, 21909, 21913, 21917, 21921, 21925, 21929, 21933, 21937, 21941, - 21945, 21949, 21953, 21957, 21961, 21965, 21969, 21973, 21977, 21981, - 21985, 21989, 21993, 21997, 22001, 22005, 22009, 22013, 22017, 22021, - 22025, 22029, 22033, 22037, 22041, 22045, 22049, 22053, 22057, 22061, - 22065, 22069, 22073, 22077, 22081, 22085, 22089, 22093, 22097, 22101, - 22105, 22109, 22113, 22117, 22121, 22125, 22129, 22133, 22137, 22141, - 22145, 22149, 22153, 22157, 22161, 22165, 22169, 22173, 22177, 22181, - 22185, 22189, 22193, 22197, 22201, 22205, 22209, 22213, 22217, 22221, - 22225, 22229, 22233, 22237, 22241, 22245, 22249, 22254, 22258, 22263, - 22267, 22272, 22277, 22281, 22286, 22291, 22295, 22300, 22305, 22310, - 22315, 22319, 22324, 22329, 22334, 22339, 22344, 22349, 22353, 22358, - 22363, 22368, 22373, 22378, 22383, 22388, 22393, 22398, 22403, 22408, - 22413, 22418, 22423, 22428, 22433, 22438, 22443, 22448, 22453, 22458, - 22463, 22468, 22473, 22478, 22483, 22488, 22493, 22498, 22503, 22508, - 22513, 22518, 22523, 22528, 22533, 22538, 22543, 22548, 22553, 22558, - 22563, 22568, 22573, 22578, 22583, 22588, 22593, 22598, 22603, 22607, - 22611, 22615, 22619, 22623, 22627, 22631, 22635, 22639, 22643, 22647, - 22651, 22655, 22659, 22663, 22667, 22671, 22675, 22679, 22683, 22687, - 22691, 22695, 22699, 22703, 22707, 22711, 22715, 22719, 22723, 22727, - 22731, 22735, 22739, 22743, 22747, 22751, 22755, 22759, 22763, 22767, - 22771, 22775, 22779, 22783, 22787, 22791, 22795, 22799, 22803, 22807, - 22811, 22815, 22819, 22823, 22827, 22831, 22835, 22839, 22843, 22847, - 22851, 22855, 22859, 22863, 22867, 22871, 22875, 22879, 22883, 22887, - 22891, 22895, 22899, 22903, 22907, 22911, 22915, 22919, 22923, 22927, - 22931, 22935, 22939, 22943, 22947, 22951, 22955, 22958, 22962, 22966, - 22970, 22974, 22978, 22982, 22986, 22989, 22993, 22997, 23001, 23005, - 23009, 23013, 23017, 23021, 23025, 23029, 23033, 23037, 23041, 23045, - 23049, 23052, 23056, 23060, 23064, 23068, 23072, 23076, 23080, 23084, - 23088, 23092, 23096, 23100, 23104, 23108, 23112, 23115, 23119, 23123, - 23127, 23131, 23135, 23139, 23143, 23146, 23150, 23154, 23158, 23162, - 23166, 23170, 23174, 23178, 23182, 23186, 23190, 23194, 23198, 23202, - 23206, 23210, 23214, 23218, 23222, 23226, 23230, 23234, 23238, 0, 23242, - 23246, 23250, 23254, 0, 0, 23258, 23262, 23266, 23270, 23274, 23278, - 23282, 0, 23286, 0, 23290, 23294, 23298, 23302, 0, 0, 23306, 23310, - 23314, 23318, 23322, 23326, 23330, 23334, 23338, 23342, 23346, 23350, - 23354, 23358, 23362, 23366, 23370, 23374, 23378, 23382, 23386, 23390, - 23394, 23397, 23401, 23405, 23409, 23413, 23417, 23421, 23425, 23429, - 23433, 23437, 23441, 23445, 23449, 23453, 23457, 23461, 23465, 0, 23469, - 23473, 23477, 23481, 0, 0, 23485, 23488, 23492, 23496, 23500, 23504, - 23508, 23512, 23516, 23520, 23524, 23528, 23532, 23536, 23540, 23544, - 23548, 23553, 23558, 23563, 23569, 23575, 23580, 23585, 23591, 23594, - 23598, 23602, 23606, 23610, 23614, 23618, 23622, 0, 23626, 23630, 23634, - 23638, 0, 0, 23642, 23646, 23650, 23654, 23658, 23662, 23666, 0, 23670, - 0, 23674, 23678, 23682, 23686, 0, 0, 23690, 23694, 23698, 23702, 23706, - 23710, 23714, 23718, 23722, 23727, 23732, 23737, 23743, 23749, 23754, 0, - 23759, 23763, 23767, 23771, 23775, 23779, 23783, 23787, 23791, 23795, - 23799, 23803, 23807, 23811, 23815, 23819, 23823, 23826, 23830, 23834, - 23838, 23842, 23846, 23850, 23854, 23858, 23862, 23866, 23870, 23874, - 23878, 23882, 23886, 23890, 23894, 23898, 23902, 23906, 23910, 23914, - 23918, 23922, 23926, 23930, 23934, 23938, 23942, 23946, 23950, 23954, - 23958, 23962, 23966, 23970, 23974, 23978, 23982, 0, 23986, 23990, 23994, - 23998, 0, 0, 24002, 24006, 24010, 24014, 24018, 24022, 24026, 24030, - 24034, 24038, 24042, 24046, 24050, 24054, 24058, 24062, 24066, 24070, - 24074, 24078, 24082, 24086, 24090, 24094, 24098, 24102, 24106, 24110, - 24114, 24118, 24122, 24126, 24130, 24134, 24138, 24142, 24146, 24150, - 24154, 24158, 24162, 24166, 24170, 24174, 24178, 24182, 24186, 24190, - 24194, 24198, 24202, 24206, 24210, 24214, 24218, 24222, 24226, 24229, - 24233, 24237, 24241, 24245, 24249, 24253, 24257, 24261, 24265, 0, 0, - 24269, 24278, 24284, 24289, 24293, 24296, 24301, 24304, 24307, 24310, - 24315, 24319, 24324, 24327, 24330, 24333, 24336, 24339, 24342, 24345, - 24348, 24351, 24355, 24359, 24363, 24367, 24371, 24375, 24379, 24383, - 24387, 24391, 0, 0, 0, 24396, 24402, 24406, 24410, 24414, 24420, 24424, - 24428, 24432, 24438, 24442, 24446, 24450, 24456, 24460, 24464, 24468, - 24474, 24480, 24486, 24494, 24500, 24506, 24512, 24518, 24524, 0, 0, 0, - 0, 0, 0, 24530, 24533, 24536, 24539, 24542, 24545, 24549, 24553, 24556, - 24560, 24564, 24568, 24572, 24576, 24579, 24583, 24587, 24591, 24595, - 24599, 24602, 24606, 24610, 24614, 24618, 24622, 24625, 24629, 24633, - 24637, 24641, 24644, 24648, 24652, 24656, 24660, 24664, 24668, 24672, - 24676, 24680, 24684, 24688, 24692, 24696, 24699, 24703, 24707, 24711, - 24715, 24719, 24723, 24727, 24731, 24735, 24739, 24743, 24747, 24751, - 24755, 24759, 24763, 24767, 24771, 24775, 24779, 24783, 24787, 24791, - 24795, 24799, 24803, 24807, 24811, 24815, 24819, 24823, 24827, 24831, - 24835, 24838, 24842, 24846, 24850, 24854, 24858, 0, 0, 24862, 24867, - 24872, 24877, 24882, 24887, 0, 0, 24892, 24896, 24899, 24903, 24906, - 24910, 24913, 24917, 24923, 24928, 24932, 24935, 24939, 24943, 24949, - 24953, 24959, 24963, 24969, 24973, 24979, 24983, 24989, 24995, 24999, - 25005, 25009, 25015, 25021, 25025, 25031, 25037, 25042, 25047, 25055, - 25063, 25070, 25075, 25081, 25090, 25096, 25104, 25109, 25115, 25119, - 25123, 25127, 25131, 25135, 25139, 25143, 25147, 25151, 25155, 25161, - 25166, 25171, 25174, 25178, 25182, 25188, 25192, 25198, 25202, 25208, - 25212, 25218, 25222, 25228, 25232, 25238, 25242, 25248, 25254, 25258, - 25264, 25269, 25273, 25277, 25281, 25285, 25288, 25292, 25298, 25303, - 25308, 25312, 25316, 25320, 25326, 25330, 25336, 25340, 25346, 25349, - 25354, 25358, 25364, 25368, 25374, 25378, 25384, 25390, 25394, 25398, - 25402, 25406, 25410, 25414, 25418, 25422, 25426, 25430, 25434, 25440, - 25443, 25447, 25451, 25457, 25461, 25467, 25471, 25477, 25481, 25487, - 25491, 25497, 25501, 25507, 25511, 25517, 25523, 25527, 25531, 25537, - 25543, 25549, 25555, 25559, 25563, 25567, 25571, 25575, 25579, 25585, - 25589, 25593, 25597, 25603, 25607, 25613, 25617, 25623, 25627, 25633, - 25637, 25643, 25647, 25653, 25657, 25663, 25669, 25673, 25679, 25683, - 25687, 25691, 25695, 25699, 25703, 25709, 25712, 25716, 25720, 25726, - 25730, 25736, 25740, 25746, 25750, 25756, 25760, 25766, 25770, 25776, - 25780, 25786, 25792, 25796, 25802, 25806, 25812, 25818, 25822, 25826, - 25830, 25834, 25838, 25842, 25848, 25851, 25855, 25859, 25865, 25869, - 25875, 25879, 25885, 25891, 25895, 25900, 25904, 25908, 25912, 25916, - 25920, 25924, 25928, 25934, 25937, 25941, 25945, 25951, 25955, 25961, - 25965, 25971, 25975, 25981, 25985, 25991, 25995, 26001, 26005, 26011, - 26014, 26019, 26024, 26028, 26032, 26036, 26040, 26044, 26048, 26054, - 26057, 26061, 26065, 26071, 26075, 26081, 26085, 26091, 26095, 26101, - 26105, 26111, 26115, 26121, 26125, 26131, 26137, 26141, 26147, 26151, - 26157, 26163, 26169, 26175, 26181, 26187, 26193, 26199, 26203, 26207, - 26211, 26215, 26219, 26223, 26227, 26231, 26237, 26241, 26247, 26251, - 26257, 26261, 26267, 26271, 26277, 26281, 26287, 26291, 26297, 26301, - 26305, 26309, 26313, 26317, 26321, 26325, 26331, 26334, 26338, 26342, - 26348, 26352, 26358, 26362, 26368, 26372, 26378, 26382, 26388, 26392, - 26398, 26402, 26408, 26414, 26418, 26424, 26430, 26436, 26440, 26446, - 26452, 26456, 26460, 26464, 26468, 26472, 26478, 26481, 26485, 26490, - 26494, 26500, 26503, 26508, 26513, 26517, 26521, 26525, 26529, 26533, - 26537, 26541, 26545, 26549, 26555, 26559, 26563, 26569, 26573, 26579, - 26583, 26589, 26593, 26597, 26601, 26605, 26609, 26615, 26619, 26623, - 26627, 26631, 26635, 26639, 26643, 26647, 26651, 26655, 26661, 26667, - 26673, 26679, 26685, 26690, 26696, 26702, 26708, 26712, 26716, 26720, - 26724, 26728, 26732, 26736, 26740, 26744, 26748, 26752, 26756, 26760, - 26766, 26772, 26778, 26783, 26787, 26791, 26795, 26799, 26803, 26807, - 26811, 26815, 26819, 26825, 26831, 26837, 26843, 26849, 26855, 26861, - 26867, 26873, 26877, 26881, 26885, 26889, 26893, 26897, 26901, 26907, - 26913, 26919, 26925, 26931, 26937, 26943, 26949, 26955, 26960, 26965, - 26970, 26975, 26981, 26987, 26993, 26999, 27005, 27011, 27017, 27022, - 27028, 27034, 27040, 27045, 27051, 27057, 27063, 27068, 27073, 27078, - 27083, 27088, 27093, 27098, 27103, 27108, 27113, 27118, 27123, 27127, - 27132, 27137, 27142, 27147, 27152, 27157, 27162, 27167, 27172, 27177, - 27182, 27187, 27192, 27197, 27202, 27207, 27212, 27217, 27222, 27227, - 27232, 27237, 27242, 27247, 27252, 27257, 27262, 27267, 27272, 27276, - 27281, 27286, 27291, 27296, 27301, 27306, 27311, 27316, 27321, 27326, - 27331, 27336, 27341, 27346, 27351, 27356, 27361, 27366, 27371, 27376, - 27381, 27386, 27391, 27396, 27401, 27405, 27410, 27415, 27420, 27425, - 27430, 27434, 27439, 27444, 27449, 27454, 27459, 27463, 27468, 27474, - 27479, 27484, 27489, 27494, 27500, 27505, 27510, 27515, 27520, 27525, - 27530, 27535, 27540, 27545, 27550, 27555, 27560, 27564, 27569, 27574, - 27579, 27584, 27589, 27594, 27599, 27604, 27609, 27614, 27619, 27624, - 27629, 27634, 27639, 27644, 27649, 27654, 27659, 27664, 27669, 27674, - 27679, 27684, 27689, 27694, 27699, 27704, 27709, 27714, 27719, 27725, - 27730, 27735, 27740, 27745, 27750, 27755, 27760, 27765, 27770, 27775, - 27780, 27784, 27789, 27794, 27799, 27804, 27809, 27814, 27819, 27824, - 27829, 27834, 27839, 27844, 27849, 27854, 27859, 27864, 27869, 27874, - 27879, 27884, 27889, 27894, 27899, 27904, 27909, 27914, 27920, 27924, - 27928, 27932, 27936, 27940, 27944, 27948, 27952, 27958, 27964, 27970, - 27976, 27982, 27988, 27994, 28001, 28007, 28012, 28017, 28022, 28027, - 28032, 28037, 28042, 28047, 28052, 28057, 28062, 28067, 28072, 28077, - 28082, 28087, 28092, 28097, 28102, 28107, 28112, 28117, 28122, 28127, - 28132, 28137, 28142, 28147, 0, 0, 0, 28154, 28165, 28170, 28178, 28183, - 28188, 28193, 28202, 28207, 28213, 28219, 28225, 28230, 28236, 28242, - 28246, 28251, 28256, 28266, 28271, 28276, 28283, 28288, 28293, 28302, - 28307, 28316, 28323, 28330, 28337, 28344, 28355, 28362, 28367, 28377, - 28381, 28388, 28393, 28400, 28406, 28413, 28422, 28429, 28436, 28445, - 28452, 28457, 28462, 28473, 28480, 28485, 28496, 28503, 28508, 28513, - 28521, 28530, 28537, 28544, 28554, 28559, 28564, 28569, 28578, 28586, - 28591, 28596, 28601, 28606, 28611, 28616, 28621, 28626, 28631, 28636, - 28641, 28647, 28653, 28659, 28664, 28669, 28674, 28679, 28684, 28689, - 28698, 28707, 28716, 28725, 0, 0, 0, 0, 0, 0, 0, 28734, 28738, 28742, - 28746, 28750, 28755, 28760, 28765, 28770, 28774, 28778, 28783, 28787, - 28791, 28795, 28799, 28804, 28808, 28812, 28817, 28822, 28827, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 28832, 28838, 28842, 28846, 28850, 28854, 28859, 28864, - 28869, 28874, 28878, 28882, 28887, 28891, 28895, 28899, 28903, 28908, - 28912, 28916, 28921, 28926, 28931, 28937, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 28942, 28946, 28950, 28954, 28958, 28963, 28968, 28973, 28978, 28982, - 28986, 28991, 28995, 28999, 29003, 29007, 29012, 29016, 29020, 29025, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29030, 29034, 29038, 29042, 29046, - 29051, 29056, 29061, 29066, 29070, 29074, 29079, 29083, 0, 29087, 29091, - 29096, 0, 29100, 29105, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29110, 29113, - 29117, 29121, 29125, 29129, 29133, 29137, 29141, 29145, 29149, 29153, - 29157, 29161, 29165, 29169, 29173, 29177, 29180, 29184, 29188, 29192, - 29196, 29200, 29204, 29208, 29212, 29216, 29220, 29224, 29228, 29232, - 29235, 29238, 29241, 29245, 29251, 29257, 29263, 29269, 29275, 29281, - 29287, 29293, 29299, 29305, 29311, 29317, 29323, 29329, 29338, 29347, - 29353, 29359, 29365, 29370, 29374, 29379, 29384, 29389, 29393, 29398, - 29403, 29408, 29412, 29417, 29421, 29426, 29431, 29436, 29441, 29445, - 29449, 29453, 29457, 29461, 29465, 29469, 29473, 29477, 29481, 29487, - 29491, 29495, 29499, 29503, 29507, 29515, 29521, 29525, 29531, 29535, - 29541, 29545, 0, 0, 29549, 29553, 29556, 29559, 29562, 29565, 29568, - 29571, 29574, 29577, 0, 0, 0, 0, 0, 0, 29580, 29588, 29596, 29604, 29612, - 29620, 29628, 29636, 29644, 29652, 0, 0, 0, 0, 0, 0, 29660, 29663, 29666, - 29669, 29674, 29677, 29682, 29689, 29697, 29702, 29709, 29712, 29719, - 29726, 29733, 29737, 29744, 29748, 29751, 29754, 29757, 29760, 29763, - 29766, 29769, 29772, 0, 0, 0, 0, 0, 0, 29775, 29778, 29781, 29784, 29787, - 29790, 29794, 29798, 29802, 29805, 29809, 29813, 29816, 29820, 29824, - 29827, 29830, 29833, 29837, 29841, 29845, 29849, 29853, 29856, 29859, - 29863, 29867, 29870, 29874, 29878, 29882, 29886, 29890, 29894, 29898, - 29902, 29909, 29914, 29919, 29924, 29929, 29935, 29941, 29947, 29953, - 29958, 29964, 29970, 29975, 29981, 29987, 29993, 29999, 30005, 30010, - 30016, 30021, 30027, 30033, 30039, 30045, 30051, 30056, 30061, 30067, - 30073, 30078, 30084, 30089, 30095, 30100, 30105, 30111, 30117, 30123, - 30129, 30135, 30141, 30147, 30153, 30159, 30165, 30171, 30177, 30182, - 30187, 30192, 30198, 30204, 0, 0, 0, 0, 0, 0, 0, 30212, 30221, 30230, - 30238, 30246, 30256, 30264, 30273, 30280, 30287, 30294, 30302, 30310, - 30318, 30326, 30334, 30342, 30350, 30358, 30365, 30373, 30381, 30389, - 30397, 30405, 30415, 30425, 30435, 30445, 30455, 30465, 30475, 30485, - 30495, 30505, 30515, 30525, 30535, 30545, 30553, 30561, 30571, 30579, 0, - 0, 0, 0, 0, 30589, 30593, 30597, 30601, 30605, 30609, 30613, 30617, - 30621, 30625, 30629, 30633, 30637, 30641, 30645, 30649, 30653, 30657, - 30661, 30665, 30669, 30673, 30677, 30681, 30687, 30691, 30697, 30701, - 30707, 30711, 30717, 30721, 30725, 30729, 30733, 30737, 30741, 30747, - 30753, 30759, 30765, 30771, 30777, 30783, 30789, 30795, 30801, 30807, - 30814, 30820, 30826, 30832, 30836, 30840, 30844, 30848, 30852, 30856, - 30860, 30866, 30872, 30878, 30883, 30890, 30895, 30900, 30906, 30911, - 30918, 30925, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30932, 30938, 30942, 30947, - 30952, 30957, 30962, 30967, 30972, 30977, 30982, 30987, 30992, 30997, - 31002, 31007, 31011, 31015, 31020, 31025, 31030, 31034, 31038, 31042, - 31046, 31051, 31056, 31061, 31065, 31069, 31074, 0, 31079, 31084, 31089, - 31094, 31100, 31106, 31112, 31118, 31123, 31128, 31134, 31140, 0, 0, 0, - 0, 31147, 31152, 31158, 31164, 31170, 31175, 31180, 31185, 31190, 31195, - 31200, 31205, 0, 0, 0, 0, 31210, 0, 0, 0, 31215, 31220, 31225, 31230, - 31234, 31238, 31242, 31246, 31250, 31254, 31258, 31262, 31266, 31271, - 31277, 31283, 31289, 31294, 31299, 31305, 31311, 31316, 31321, 31327, - 31332, 31338, 31344, 31349, 31355, 31361, 31367, 31372, 31377, 31382, - 31388, 31394, 31399, 31405, 31410, 31416, 31421, 31427, 0, 0, 31433, - 31439, 31445, 31451, 31457, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31463, - 31472, 31481, 31489, 31498, 31507, 31515, 31524, 31533, 31542, 31550, - 31558, 31567, 31575, 31583, 31592, 31601, 31609, 31618, 31627, 31635, - 31643, 31652, 31660, 31668, 31677, 31685, 31694, 31703, 31711, 31720, - 31729, 31737, 31745, 31754, 31763, 31771, 31780, 31789, 31798, 31807, - 31816, 31825, 31834, 0, 0, 0, 0, 31843, 31853, 31862, 31871, 31879, - 31888, 31896, 31905, 31913, 31922, 31931, 31940, 31949, 31958, 31967, - 31976, 31985, 31994, 32003, 32012, 32021, 32030, 32039, 32048, 32057, - 32065, 0, 0, 0, 0, 0, 0, 32073, 32081, 32088, 32095, 32102, 32109, 32116, - 32123, 32130, 32137, 32144, 0, 0, 0, 32152, 32160, 32168, 32172, 32178, - 32184, 32190, 32196, 32202, 32208, 32214, 32220, 32226, 32232, 32238, - 32244, 32250, 32256, 32262, 32266, 32272, 32278, 32284, 32290, 32296, - 32302, 32308, 32314, 32320, 32326, 32332, 32338, 32344, 32350, 32356, - 32360, 32365, 32370, 32375, 32379, 32384, 32388, 32393, 32398, 32403, - 32407, 32412, 32417, 32422, 32427, 32432, 32436, 32440, 32444, 32449, - 32453, 32457, 32461, 32466, 32471, 32476, 32481, 0, 0, 32487, 32491, - 32498, 32503, 32509, 32515, 32520, 32526, 32532, 32537, 32543, 32549, - 32555, 32560, 32566, 32571, 32576, 32582, 32587, 32593, 32598, 32604, - 32610, 32616, 32622, 32626, 32631, 32636, 32642, 32648, 32653, 32659, - 32665, 32669, 32674, 32679, 32683, 32688, 32692, 32697, 32702, 32708, - 32714, 32719, 32724, 32729, 32733, 32738, 32742, 32747, 32751, 32756, - 32761, 32766, 32771, 32777, 32784, 32791, 32801, 32810, 32817, 32823, - 32834, 32839, 32845, 0, 32850, 32855, 32860, 32868, 32874, 32882, 32887, - 32893, 32899, 32905, 32910, 32916, 32921, 32928, 32934, 32939, 32945, - 32951, 32957, 32964, 32971, 32978, 32983, 32988, 32995, 33002, 33009, - 33016, 33023, 0, 0, 33030, 33037, 33044, 33050, 33056, 33062, 33068, - 33074, 33080, 33086, 33092, 0, 0, 0, 0, 0, 0, 33098, 33104, 33109, 33114, - 33119, 33124, 33129, 33134, 33139, 33144, 0, 0, 0, 0, 0, 0, 33149, 33154, - 33159, 33164, 33169, 33174, 33179, 33188, 33195, 33200, 33205, 33210, - 33215, 33220, 0, 0, 33225, 33232, 33235, 33238, 33242, 33247, 33251, - 33257, 33262, 33268, 33275, 33283, 33287, 33292, 33296, 33301, 33308, - 33316, 33323, 33329, 33337, 33344, 33349, 33353, 33360, 33364, 33369, - 33374, 33381, 33389, 33396, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33404, 33410, 33416, 33420, 33424, 33428, - 33432, 33438, 33442, 33448, 33452, 33458, 33464, 33472, 33478, 33486, - 33490, 33494, 33498, 33504, 33507, 33513, 33517, 33523, 33527, 33531, - 33537, 33541, 33547, 33551, 33557, 33565, 33573, 33581, 33587, 33591, - 33597, 33601, 33607, 33610, 33613, 33619, 33623, 33629, 33632, 33635, - 33638, 33641, 33645, 33651, 33657, 33660, 33663, 33667, 33672, 33677, - 33684, 33689, 33696, 33703, 33712, 33719, 33728, 33733, 33740, 33747, - 33756, 33761, 33768, 33773, 33779, 33785, 33791, 33797, 33803, 33809, - 33815, 0, 0, 0, 33821, 33825, 33828, 33831, 33834, 33837, 33840, 33843, - 33846, 33849, 33852, 33855, 33858, 33861, 33866, 33871, 33876, 33879, - 33884, 33889, 33894, 33899, 33906, 33911, 33916, 33921, 33926, 33933, - 33939, 33945, 33951, 33957, 33963, 33972, 33981, 33987, 33993, 34002, - 34011, 34020, 34029, 34038, 34047, 34056, 34065, 34074, 34079, 0, 34084, - 34089, 34094, 34099, 34103, 34107, 34111, 34116, 34120, 34124, 34129, - 34133, 34138, 34143, 34148, 34153, 34158, 34163, 34168, 34173, 34178, - 34182, 34186, 34191, 34196, 34201, 34205, 34209, 34213, 34217, 34222, - 34226, 34231, 34235, 34241, 34247, 34253, 34259, 34265, 34271, 34277, - 34283, 34289, 34294, 34299, 34306, 34314, 34319, 34324, 34329, 34333, - 34337, 34341, 34345, 34349, 34353, 34357, 34361, 34365, 34369, 34374, - 34379, 34384, 34390, 34396, 34400, 34406, 34410, 34416, 34422, 34427, - 34434, 34438, 34444, 34448, 34454, 34459, 34466, 34473, 34478, 34485, - 34490, 34495, 34499, 34505, 34509, 34515, 34522, 34529, 34533, 34539, - 34545, 34549, 34555, 34560, 34564, 34570, 34575, 34580, 34585, 34590, - 34594, 34598, 34603, 34608, 34615, 34621, 34626, 34633, 34638, 34645, - 34650, 34659, 34665, 34671, 34675, 0, 0, 0, 0, 0, 0, 0, 0, 34679, 34688, - 34695, 34702, 34709, 34713, 34718, 34723, 34728, 34733, 34738, 34743, - 34748, 34753, 34758, 34763, 34768, 34773, 34777, 34781, 34786, 34791, - 34796, 34801, 34806, 34811, 34815, 34820, 34825, 34830, 34835, 34839, - 34843, 34847, 34851, 34856, 34861, 34865, 34870, 34875, 34879, 34885, - 34891, 34897, 34902, 34907, 34913, 34918, 34924, 34929, 34935, 34941, - 34946, 34952, 34958, 34963, 34969, 34975, 34981, 34986, 0, 0, 0, 34991, - 34997, 35007, 35013, 35021, 35027, 35032, 35036, 35040, 35044, 35048, - 35052, 35056, 35060, 35064, 0, 0, 0, 35068, 35073, 35078, 35083, 35090, - 35096, 35102, 35108, 35114, 35120, 35126, 35132, 35138, 35144, 35150, - 35157, 35164, 35171, 35178, 35185, 35192, 35199, 35206, 35213, 35220, - 35227, 35234, 35241, 35248, 35255, 35262, 35269, 35276, 35283, 35290, - 35297, 35304, 35311, 35318, 35325, 35332, 35339, 35346, 35353, 35361, - 35369, 35377, 35383, 35389, 35395, 35403, 35412, 35419, 35426, 35432, - 35439, 35446, 35453, 35461, 35468, 0, 0, 0, 0, 0, 0, 0, 35475, 35482, - 35489, 35496, 35503, 35510, 35517, 35524, 35531, 35538, 35545, 35552, - 35559, 35566, 35573, 35580, 35587, 35594, 35601, 35608, 35615, 35622, - 35629, 35636, 35643, 35650, 35657, 35664, 35671, 35678, 35685, 35692, - 35699, 35706, 35713, 35720, 35727, 35734, 35741, 35748, 35755, 35762, - 35770, 0, 0, 35777, 35784, 35792, 35800, 35808, 35816, 35824, 35832, - 35842, 35852, 35862, 0, 0, 0, 0, 0, 0, 0, 0, 35872, 35877, 35882, 35887, - 35892, 35901, 35912, 35921, 35932, 35938, 35951, 35957, 35964, 35971, - 35976, 35982, 35988, 35999, 36008, 36015, 36022, 36031, 36038, 36047, - 36057, 36067, 36074, 36081, 36088, 36098, 36103, 36111, 36117, 36125, - 36134, 36139, 36146, 36152, 36157, 36162, 36167, 36173, 36180, 0, 0, 0, - 0, 0, 36188, 36193, 36199, 36205, 36213, 36219, 36225, 36231, 36236, - 36243, 36248, 36254, 36260, 36268, 36274, 36282, 36287, 36294, 36300, - 36308, 36316, 36322, 36328, 36335, 36342, 36348, 36355, 36361, 36367, - 36372, 36378, 36386, 36394, 36400, 36406, 36412, 36418, 36426, 36430, - 36436, 36442, 36448, 36454, 36460, 36466, 36470, 36475, 36480, 36487, - 36492, 36496, 36502, 36507, 36512, 36516, 36521, 36526, 36530, 36535, - 36540, 36547, 36551, 36556, 36561, 36565, 36570, 36574, 36579, 36583, - 36588, 36593, 36599, 36604, 36609, 36613, 36618, 36624, 36631, 36636, - 36641, 36646, 36651, 36656, 36660, 36666, 36673, 36680, 36685, 36690, - 36694, 36700, 36706, 36711, 36716, 36721, 36727, 36732, 36738, 36743, - 36749, 36755, 36761, 36768, 36775, 36782, 36789, 36796, 36803, 36808, - 36816, 36825, 36834, 36843, 36852, 36861, 36870, 36882, 36891, 36900, - 36909, 36915, 36920, 36927, 36935, 36943, 36950, 36957, 36964, 36971, - 36979, 36988, 36997, 37006, 37015, 37024, 37033, 37042, 37051, 37060, - 37069, 37078, 37087, 37096, 37105, 37113, 37122, 37133, 37142, 37153, - 37166, 37175, 37184, 37194, 37203, 37211, 37220, 37226, 37231, 37239, - 37244, 37252, 37257, 37266, 37272, 37278, 37285, 37290, 37295, 37303, - 37311, 37320, 37329, 37334, 37341, 37351, 37359, 37368, 37374, 37380, - 37385, 37392, 37397, 37406, 37411, 37416, 37421, 37428, 37434, 37439, - 37448, 37456, 37461, 37466, 37473, 37480, 37484, 37488, 37491, 37494, - 37497, 37500, 37503, 37506, 37513, 37516, 37519, 37524, 37528, 37532, - 37536, 37540, 37544, 37554, 37560, 37566, 37572, 37580, 37588, 37594, - 37600, 37607, 37613, 37618, 37624, 37631, 37637, 37644, 37650, 37658, - 37664, 37671, 37677, 37683, 37689, 37695, 37701, 37707, 37718, 37728, - 37734, 37740, 37750, 37756, 37764, 37772, 37780, 37785, 37790, 37796, - 37801, 37809, 37815, 37819, 37826, 37833, 37838, 37847, 37855, 37863, - 37870, 37877, 37884, 37891, 37899, 37907, 37918, 37929, 37937, 37945, - 37953, 37961, 37970, 37979, 37987, 37995, 38004, 38013, 38024, 38035, - 38046, 38057, 38066, 38075, 38084, 38093, 38104, 38115, 38123, 38131, - 38139, 38147, 38155, 38163, 38171, 38179, 38187, 38195, 38203, 38211, - 38220, 38229, 38238, 38247, 38258, 38269, 38277, 38285, 38293, 38301, - 38310, 38319, 38327, 38335, 38347, 38359, 38368, 38377, 38386, 38395, - 38403, 38411, 38419, 38427, 38435, 38443, 38451, 38459, 38467, 38475, - 38484, 38493, 38502, 38511, 38521, 38531, 38541, 38551, 38561, 38571, - 38581, 38591, 38599, 38607, 38615, 38623, 38631, 38639, 38647, 38655, - 38667, 38679, 38688, 38697, 38705, 38713, 38721, 38729, 38740, 38751, - 38762, 38773, 38785, 38797, 38805, 38813, 38821, 38829, 38838, 38847, - 38856, 38865, 38873, 38881, 38889, 38897, 38905, 38913, 38923, 38933, - 38943, 38953, 38961, 38969, 38977, 38985, 38993, 39001, 39009, 39017, - 39025, 39033, 39041, 39049, 39057, 39065, 39073, 39081, 39089, 39097, - 39105, 39113, 39121, 39129, 39137, 39145, 39154, 39163, 39172, 39180, - 39189, 39198, 39207, 39216, 39226, 39235, 39242, 39247, 39254, 39261, - 39269, 39277, 39287, 39297, 39307, 39317, 39328, 39339, 39349, 39359, - 39369, 39379, 39389, 39399, 39409, 39419, 39430, 39441, 39451, 39461, - 39471, 39481, 39489, 39497, 39506, 39515, 39523, 39531, 39542, 39553, - 39564, 39575, 39587, 39599, 39610, 39621, 39632, 39643, 39652, 39661, - 39669, 39677, 39684, 39691, 39699, 39707, 39717, 39727, 39737, 39747, - 39758, 39769, 39779, 39789, 39799, 39809, 39819, 39829, 39839, 39849, - 39860, 39871, 39881, 39891, 39901, 39911, 39918, 39925, 39933, 39941, - 39951, 39961, 39971, 39981, 39992, 40003, 40013, 40023, 40033, 40043, - 40051, 40059, 40067, 40075, 40084, 40093, 40101, 40109, 40116, 40123, - 40130, 40137, 40145, 40153, 40161, 40169, 40180, 40191, 40202, 40213, - 40224, 40235, 40243, 40251, 40262, 40273, 40284, 40295, 40306, 40317, - 40325, 40333, 40344, 40355, 40366, 0, 0, 40377, 40385, 40393, 40404, - 40415, 40426, 0, 0, 40437, 40445, 40453, 40464, 40475, 40486, 40497, - 40508, 40519, 40527, 40535, 40546, 40557, 40568, 40579, 40590, 40601, - 40609, 40617, 40628, 40639, 40650, 40661, 40672, 40683, 40691, 40699, - 40710, 40721, 40732, 40743, 40754, 40765, 40773, 40781, 40792, 40803, - 40814, 0, 0, 40825, 40833, 40841, 40852, 40863, 40874, 0, 0, 40885, - 40893, 40901, 40912, 40923, 40934, 40945, 40956, 0, 40967, 0, 40975, 0, - 40986, 0, 40997, 41008, 41016, 41024, 41035, 41046, 41057, 41068, 41079, - 41090, 41098, 41106, 41117, 41128, 41139, 41150, 41161, 41172, 41180, - 41188, 41196, 41204, 41212, 41220, 41228, 41236, 41244, 41252, 41260, - 41268, 41276, 0, 0, 41284, 41295, 41306, 41320, 41334, 41348, 41362, - 41376, 41390, 41401, 41412, 41426, 41440, 41454, 41468, 41482, 41496, - 41507, 41518, 41532, 41546, 41560, 41574, 41588, 41602, 41613, 41624, - 41638, 41652, 41666, 41680, 41694, 41708, 41719, 41730, 41744, 41758, - 41772, 41786, 41800, 41814, 41825, 41836, 41850, 41864, 41878, 41892, - 41906, 41920, 41928, 41936, 41947, 41955, 0, 41966, 41974, 41985, 41993, - 42001, 42009, 42017, 42025, 42028, 42031, 42034, 42037, 42043, 42054, - 42062, 0, 42073, 42081, 42092, 42100, 42108, 42116, 42124, 42132, 42138, - 42144, 42150, 42158, 42166, 42177, 0, 0, 42188, 42196, 42207, 42215, - 42223, 42231, 0, 42239, 42245, 42251, 42257, 42265, 42273, 42284, 42295, - 42303, 42311, 42319, 42330, 42338, 42346, 42354, 42362, 42370, 42376, - 42382, 0, 0, 42385, 42396, 42404, 0, 42415, 42423, 42434, 42442, 42450, - 42458, 42466, 42474, 42477, 0, 42480, 42484, 42488, 42492, 42496, 42500, - 42504, 42508, 42512, 42516, 42520, 42524, 42530, 42536, 42542, 42545, - 42548, 42550, 42554, 42558, 42562, 42566, 42569, 42573, 42577, 42583, - 42589, 42596, 42603, 42608, 42613, 42619, 42625, 42627, 42630, 42632, - 42636, 42640, 42644, 42648, 42652, 42656, 42660, 42664, 42668, 42674, - 42678, 42682, 42688, 42693, 42700, 42702, 42705, 42709, 42713, 42718, - 42724, 42726, 42735, 42744, 42747, 42751, 42753, 42755, 42757, 42761, - 42767, 42769, 42773, 42777, 42784, 42791, 42795, 42800, 42805, 42810, - 42815, 42819, 42823, 42826, 42830, 42834, 42841, 42846, 42850, 42854, - 42859, 42863, 42867, 42872, 42877, 42881, 42885, 42889, 42891, 42896, - 42901, 42905, 42909, 42913, 42917, 0, 42921, 42925, 42929, 42935, 42941, - 42947, 42953, 42960, 42967, 42972, 42977, 42981, 0, 0, 42987, 42990, - 42993, 42996, 42999, 43002, 43005, 43009, 43013, 43018, 43023, 43028, - 43035, 43039, 43042, 43045, 43048, 43051, 43054, 43057, 43060, 43063, - 43066, 43070, 43074, 43079, 43084, 0, 43089, 43095, 43101, 43107, 43114, - 43121, 43128, 43135, 43141, 43148, 43155, 43162, 43169, 0, 0, 0, 43176, - 43179, 43182, 43185, 43190, 43193, 43196, 43199, 43202, 43205, 43208, - 43213, 43216, 43219, 43222, 43225, 43228, 43233, 43236, 43239, 43242, - 43245, 43248, 43253, 43256, 43259, 43264, 43269, 43273, 43276, 43279, - 43282, 43285, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43288, 43293, - 43298, 43305, 43313, 43318, 43323, 43327, 43331, 43336, 43343, 43350, - 43354, 43359, 43364, 43369, 43374, 43381, 43386, 43391, 43396, 43405, - 43412, 43419, 43423, 43428, 43434, 43439, 43446, 43454, 43462, 43466, - 43470, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43474, 43478, 43485, - 43490, 43494, 43499, 43503, 43507, 43511, 43513, 43517, 43521, 43525, - 43530, 43535, 43539, 43547, 43550, 43554, 43557, 43560, 43566, 43571, - 43574, 43580, 43584, 43589, 43594, 43597, 43601, 43605, 43609, 43611, - 43614, 43617, 43621, 43623, 43628, 43631, 43634, 43639, 43644, 43650, - 43653, 43656, 43660, 43665, 43668, 43671, 43674, 43678, 43682, 43686, - 43689, 43691, 43694, 43697, 43700, 43704, 43709, 43712, 43717, 43722, - 43727, 43732, 43738, 43743, 43747, 43752, 43757, 43763, 43769, 43774, - 43779, 43785, 43789, 43792, 43795, 43797, 43801, 43807, 43814, 43821, - 43828, 43835, 43842, 43849, 43856, 43863, 43871, 43878, 43886, 43893, - 43900, 43908, 43916, 43921, 43926, 43931, 43936, 43941, 43946, 43951, - 43956, 43961, 43966, 43972, 43978, 43984, 43990, 43997, 44005, 44011, - 44017, 44023, 44029, 44035, 44041, 44047, 44053, 44059, 44065, 44072, - 44079, 44086, 44093, 44101, 44110, 44117, 44128, 44135, 44142, 44151, - 44158, 44167, 44176, 44183, 44191, 44199, 44202, 0, 0, 0, 0, 44205, - 44207, 44210, 44212, 44215, 44218, 44221, 44225, 44229, 44234, 44239, - 44243, 44247, 44251, 44255, 44260, 44266, 44271, 44277, 44282, 44287, - 44292, 44298, 44303, 44309, 44315, 44319, 44323, 44328, 44333, 44338, - 44343, 44348, 44356, 44364, 44372, 44380, 44387, 44395, 44402, 44409, - 44416, 44426, 44433, 44440, 44447, 44454, 44462, 44470, 44477, 44484, - 44492, 44500, 44505, 44513, 44518, 44523, 44529, 44534, 44540, 44547, - 44554, 44559, 44565, 44570, 44573, 44577, 44580, 44584, 44588, 44592, - 44597, 44602, 44608, 44614, 44618, 44622, 44626, 44630, 44636, 44642, - 44646, 44651, 44655, 44660, 44664, 44668, 44671, 44675, 44678, 44682, - 44689, 44697, 44709, 44720, 44725, 44734, 44741, 44748, 44756, 44760, - 44766, 44774, 44778, 44783, 44788, 44794, 44800, 44806, 44813, 44817, - 44821, 44826, 44829, 44831, 44835, 44839, 44847, 44851, 44853, 44855, - 44859, 44867, 44872, 44878, 44888, 44895, 44900, 44904, 44908, 44912, - 44915, 44918, 44921, 44925, 44929, 44933, 44937, 44941, 44944, 44948, - 44952, 44955, 44957, 44960, 44962, 44966, 44970, 44972, 44978, 44981, - 44986, 44990, 44994, 44996, 44998, 45000, 45003, 45007, 45011, 45015, - 45019, 45023, 45029, 45035, 45037, 45039, 45041, 45043, 45046, 45048, - 45052, 45054, 45058, 45062, 45068, 45072, 45076, 45080, 45084, 45089, - 45096, 45101, 45112, 45123, 45128, 45135, 45144, 45148, 45153, 45156, - 45161, 45165, 45171, 45176, 45189, 45199, 45203, 45207, 45214, 45219, - 45222, 45224, 45227, 45231, 45236, 45243, 45247, 45252, 45257, 45260, - 45265, 45270, 45277, 45284, 45290, 45296, 45305, 45314, 45318, 45322, - 45324, 45329, 45333, 45337, 45346, 45355, 45362, 45369, 45378, 45387, - 45393, 45399, 45407, 45415, 45417, 45419, 45426, 45433, 45440, 45447, - 45453, 45459, 45463, 45467, 45474, 45481, 45489, 45497, 45508, 45519, - 45528, 45537, 45539, 45543, 45547, 45552, 45557, 45566, 45575, 45578, - 45581, 45584, 45587, 45590, 45595, 45599, 45604, 45609, 45612, 45615, - 45618, 45621, 45624, 45628, 45631, 45634, 45637, 45640, 45642, 45644, - 45646, 45648, 45656, 45664, 45670, 45674, 45680, 45690, 45696, 45702, - 45708, 45716, 45726, 45739, 45743, 45747, 45749, 45755, 45757, 45759, - 45761, 45763, 45769, 45772, 45778, 45784, 45788, 45792, 45796, 45799, - 45803, 45807, 45809, 45818, 45827, 45832, 45837, 45843, 45849, 45855, - 45858, 45861, 45864, 45867, 45869, 45875, 45880, 45885, 45891, 45897, - 45906, 45915, 45922, 45929, 45936, 45943, 45953, 45963, 45974, 45985, - 45996, 46007, 46016, 46025, 46034, 46043, 46051, 46063, 46075, 46091, - 46094, 46100, 46106, 46112, 46120, 46135, 46151, 46157, 46163, 46170, - 46176, 46185, 46192, 46206, 46221, 46226, 46232, 46240, 46243, 46246, - 46248, 46251, 46254, 46256, 46258, 46262, 46265, 46268, 46271, 46274, - 46279, 46284, 46289, 46294, 46299, 46302, 46304, 46306, 46308, 46312, - 46316, 46320, 46326, 46330, 46332, 46334, 46339, 46344, 46349, 46354, - 46359, 46364, 46366, 46368, 46378, 46382, 46388, 46397, 46399, 46405, - 46411, 46418, 46422, 46424, 46428, 46430, 46434, 46438, 46442, 46444, - 46446, 46448, 46455, 46464, 46473, 46482, 46491, 46500, 46509, 46518, - 46527, 46535, 46543, 46552, 46561, 46570, 46579, 46587, 46595, 46604, - 46613, 46622, 46632, 46641, 46651, 46660, 46670, 46679, 46689, 46699, - 46708, 46718, 46727, 46737, 46746, 46756, 46765, 46774, 46783, 46792, - 46801, 46811, 46820, 46829, 46838, 46848, 46857, 46866, 46875, 46884, - 46894, 46904, 46913, 46922, 46930, 46939, 46946, 46955, 46964, 46975, - 46984, 46994, 47004, 47011, 47018, 47025, 47034, 47043, 47052, 47061, - 47068, 47073, 47082, 47088, 47091, 47098, 47101, 47106, 47111, 47114, - 47117, 47125, 47128, 47133, 47136, 47144, 47149, 47157, 47160, 47163, - 47166, 47171, 47176, 47179, 47182, 47190, 47193, 47200, 47207, 47211, - 47215, 47220, 47225, 47230, 47235, 47240, 47245, 47250, 47255, 47262, - 47268, 47275, 47282, 47288, 47295, 47302, 47310, 47317, 47323, 47330, - 47338, 47345, 47349, 47355, 47367, 47379, 47383, 47387, 47392, 47397, - 47408, 47412, 47417, 47422, 47428, 47434, 47440, 47446, 47455, 47464, - 47472, 47483, 47494, 47502, 47513, 47524, 47532, 47543, 47554, 47562, - 47570, 47580, 47590, 47593, 47596, 47599, 47604, 47608, 47614, 47621, - 47628, 47636, 47643, 47647, 47651, 47655, 47659, 47661, 47665, 47669, - 47675, 47681, 47689, 47697, 47700, 47707, 47709, 47711, 47715, 47719, - 47724, 47730, 47736, 47742, 47748, 47757, 47766, 47775, 47779, 47781, - 47785, 47792, 47799, 47806, 47813, 47820, 47823, 47828, 47834, 47837, - 47842, 47847, 47852, 47857, 47861, 47868, 47875, 47882, 47889, 47893, - 47897, 47901, 47905, 47911, 47917, 47922, 47928, 47934, 47940, 47946, - 47954, 47961, 47968, 47975, 47982, 47988, 47994, 48003, 48007, 48014, - 48018, 48022, 48028, 48034, 48040, 48046, 48050, 48054, 48057, 48061, - 48065, 48072, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 48079, 48082, 48086, 48090, 48096, 48102, 48108, 48116, - 48123, 48127, 48135, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 48140, 48143, 48146, 48149, 48152, 48155, 48158, 48161, - 48164, 48167, 48171, 48175, 48179, 48183, 48187, 48191, 48195, 48199, - 48203, 48207, 48211, 48214, 48217, 48220, 48223, 48226, 48229, 48232, - 48235, 48238, 48242, 48246, 48250, 48254, 48258, 48262, 48266, 48270, - 48274, 48278, 48282, 48288, 48294, 48300, 48307, 48314, 48321, 48328, - 48335, 48342, 48349, 48356, 48363, 48370, 48377, 48384, 48391, 48398, - 48405, 48412, 48419, 48424, 48430, 48436, 48442, 48447, 48453, 48459, - 48465, 48470, 48476, 48482, 48487, 48493, 48499, 48504, 48510, 48516, - 48521, 48527, 48533, 48538, 48544, 48550, 48556, 48562, 48568, 48573, - 48579, 48585, 48591, 48596, 48602, 48608, 48614, 48619, 48625, 48631, - 48636, 48642, 48648, 48653, 48659, 48665, 48670, 48676, 48682, 48687, - 48693, 48699, 48705, 48711, 48717, 48722, 48728, 48734, 48740, 48745, - 48751, 48757, 48763, 48768, 48774, 48780, 48785, 48791, 48797, 48802, - 48808, 48814, 48819, 48825, 48831, 48836, 48842, 48848, 48854, 48860, - 48866, 48870, 48876, 48882, 48888, 48894, 48900, 48906, 48912, 48918, - 48924, 48930, 48934, 48938, 48942, 48946, 48950, 48954, 48958, 48962, - 48966, 48971, 48977, 48982, 48987, 48992, 48997, 49006, 49015, 49024, - 49033, 49042, 49051, 49060, 49069, 49075, 49083, 49091, 49097, 49104, - 49112, 49120, 49127, 49133, 49141, 49149, 49155, 49162, 49170, 49178, - 49185, 49191, 49199, 49208, 49217, 49225, 49234, 49243, 49249, 49256, - 49264, 49273, 49282, 49290, 49299, 49308, 49315, 49322, 49331, 49340, - 49349, 49358, 49367, 49376, 49383, 49390, 49399, 49408, 49417, 49426, - 49435, 49444, 49451, 49458, 49467, 49476, 49485, 49495, 49505, 49514, - 49524, 49534, 49544, 49554, 49564, 49574, 49583, 49592, 49599, 49607, - 49615, 49623, 49631, 49636, 49641, 49650, 49658, 49664, 49673, 49681, - 49688, 49697, 49705, 49711, 49720, 49728, 49735, 49744, 49752, 49758, - 49767, 49775, 49782, 49792, 49801, 49808, 49818, 49827, 49834, 49844, - 49853, 49860, 49868, 49877, 49886, 49894, 49905, 49915, 49922, 49927, - 49932, 49936, 49941, 49946, 49951, 49955, 49960, 49967, 49975, 49982, - 49990, 49994, 50000, 50006, 50012, 50016, 50023, 50029, 50036, 50040, - 50047, 50053, 50060, 50064, 50070, 50076, 50082, 50086, 50089, 50093, - 50097, 50103, 50109, 50114, 50118, 50123, 50133, 50140, 50151, 50161, - 50165, 50173, 50183, 50186, 50189, 50196, 50204, 50210, 50215, 50223, - 50232, 50241, 50249, 50253, 50257, 50260, 50263, 50267, 50271, 50274, - 50277, 50282, 50287, 50293, 50299, 50304, 50309, 50315, 50321, 50326, - 50331, 50336, 50341, 50347, 50353, 50358, 50363, 50369, 50375, 50380, - 50385, 50388, 50391, 50400, 50402, 50404, 50407, 50411, 50417, 50419, - 50422, 50429, 50436, 50443, 50450, 50459, 50472, 50477, 50482, 50486, - 50491, 50498, 50505, 50513, 50521, 50529, 50537, 50541, 50545, 50550, - 50555, 50560, 50565, 50568, 50574, 50580, 50589, 50598, 50606, 50614, - 50623, 50632, 50636, 50643, 50650, 50657, 50664, 50672, 50680, 50688, - 50696, 50700, 50704, 50708, 50713, 50718, 50724, 50730, 50734, 50740, - 50742, 50744, 50746, 50748, 50751, 50754, 50756, 50758, 50760, 50764, - 50768, 50770, 50772, 50775, 50778, 50782, 50788, 50794, 50796, 50803, - 50807, 50812, 50817, 50819, 50829, 50835, 50841, 50847, 50853, 50859, - 50865, 50870, 50873, 50876, 50879, 50881, 50883, 50887, 50891, 50896, - 50901, 50906, 50909, 50913, 50918, 50921, 50925, 50930, 50935, 50940, - 50945, 50950, 50955, 50960, 50965, 50970, 50975, 50980, 50985, 50991, - 50997, 51003, 51005, 51008, 51010, 51013, 51015, 51017, 51019, 51021, - 51023, 51025, 51027, 51029, 51031, 51033, 51035, 51037, 51039, 51041, - 51043, 51045, 51047, 51052, 51057, 51062, 51067, 51072, 51077, 51082, - 51087, 51092, 51097, 51102, 51107, 51112, 51117, 51122, 51127, 51132, - 51137, 51142, 51147, 51151, 51155, 51159, 51165, 51171, 51176, 51181, - 51186, 51192, 51198, 51203, 51211, 51219, 51227, 51235, 51243, 51251, - 51259, 51267, 51273, 51278, 51283, 51288, 51291, 51295, 51299, 51303, - 51307, 51311, 51315, 51321, 51328, 51335, 51343, 51348, 51353, 51360, - 51367, 51374, 51381, 51384, 51387, 51392, 51394, 51398, 51403, 51405, - 51407, 51409, 51411, 51416, 51419, 51421, 51426, 51432, 51439, 51442, - 51446, 51451, 51456, 51464, 51470, 51476, 51488, 51495, 51503, 51508, - 51513, 51519, 51522, 51525, 51530, 51532, 51536, 51538, 51540, 51542, - 51544, 51546, 51548, 51553, 51555, 51557, 51559, 51561, 51565, 51567, - 51570, 51575, 51580, 51585, 51590, 51596, 51602, 51604, 51607, 51614, - 51620, 51626, 51633, 51637, 51641, 51643, 51645, 51649, 51655, 51660, - 51662, 51666, 51675, 51683, 51691, 51697, 51703, 51708, 51714, 51719, - 51722, 51736, 51739, 51744, 51749, 51755, 51765, 51767, 51773, 51779, - 51783, 51790, 51794, 51796, 51798, 51802, 51808, 51813, 51819, 51821, - 51827, 51829, 51835, 51837, 51839, 51844, 51846, 51850, 51855, 51857, - 51862, 51867, 51871, 51878, 51888, 51893, 51898, 51901, 51906, 51909, - 51914, 51919, 51923, 51925, 51927, 51931, 51935, 51939, 51943, 51947, - 51949, 51953, 51956, 51959, 51962, 51966, 51970, 51975, 51979, 51984, - 51989, 51993, 51999, 52006, 52009, 52015, 52020, 52024, 52029, 52035, - 52041, 52048, 52054, 52061, 52068, 52070, 52077, 52081, 52088, 52094, - 52099, 52105, 52109, 52114, 52117, 52123, 52129, 52136, 52144, 52151, - 52160, 52170, 52177, 52183, 52187, 52195, 52200, 52209, 52212, 52215, - 52224, 52235, 52242, 52244, 52250, 52255, 52257, 52260, 52264, 52272, - 52281, 52284, 52289, 52295, 52302, 52309, 52316, 52323, 52329, 52335, - 52341, 52349, 52354, 52357, 52361, 52364, 52375, 52385, 52395, 52404, - 52415, 52425, 52434, 52440, 52448, 52452, 52460, 52464, 52472, 52479, - 52486, 52495, 52504, 52514, 52524, 52534, 52544, 52553, 52562, 52572, - 52582, 52591, 52600, 52607, 52614, 52621, 52628, 52635, 52642, 52649, - 52656, 52663, 52671, 52677, 52683, 52689, 52695, 52701, 52707, 52713, - 52719, 52725, 52732, 52740, 52748, 52756, 52764, 52772, 52780, 52788, - 52796, 52804, 52813, 52818, 52821, 52825, 52829, 52835, 52838, 52843, - 52849, 52854, 52858, 52863, 52869, 52876, 52879, 52886, 52893, 52897, - 52906, 52915, 52920, 52926, 52931, 52936, 52943, 52950, 52957, 52964, - 52972, 52976, 52984, 52989, 52993, 53000, 53004, 53010, 53018, 53023, - 53030, 53034, 53039, 53043, 53048, 53052, 53057, 53062, 53071, 53073, - 53077, 53081, 53088, 53095, 53101, 53109, 53115, 53122, 53127, 53130, - 53135, 53140, 53145, 53153, 53157, 53164, 53171, 53178, 53183, 53188, - 53194, 53199, 53204, 53210, 53215, 53218, 53222, 53226, 53233, 53243, - 53248, 53257, 53266, 53272, 53278, 53284, 53290, 53296, 53302, 53309, - 53316, 53325, 53334, 53340, 53346, 53351, 53356, 53363, 53370, 53376, - 53379, 53382, 53386, 53390, 53394, 53399, 53405, 53411, 53418, 53425, - 53430, 53434, 53438, 53442, 53446, 53450, 53454, 53458, 53462, 53466, - 53470, 53474, 53478, 53482, 53486, 53490, 53494, 53498, 53502, 53506, - 53510, 53514, 53518, 53522, 53526, 53530, 53534, 53538, 53542, 53546, - 53550, 53554, 53558, 53562, 53566, 53570, 53574, 53578, 53582, 53586, - 53590, 53594, 53598, 53602, 53606, 53610, 53614, 53618, 53622, 53626, - 53630, 53634, 53638, 53642, 53646, 53650, 53654, 53658, 53662, 53666, - 53670, 53674, 53678, 53682, 53686, 53690, 53694, 53698, 53702, 53706, - 53710, 53714, 53718, 53722, 53726, 53730, 53734, 53738, 53742, 53746, - 53750, 53754, 53758, 53762, 53766, 53770, 53774, 53778, 53782, 53786, - 53790, 53794, 53798, 53802, 53806, 53810, 53814, 53818, 53822, 53826, - 53830, 53834, 53838, 53842, 53846, 53850, 53854, 53858, 53862, 53866, - 53870, 53874, 53878, 53882, 53886, 53890, 53894, 53898, 53902, 53906, - 53910, 53914, 53918, 53922, 53926, 53930, 53934, 53938, 53942, 53946, - 53950, 53954, 53958, 53962, 53966, 53970, 53974, 53978, 53982, 53986, - 53990, 53994, 53998, 54002, 54006, 54010, 54014, 54018, 54022, 54026, - 54030, 54034, 54038, 54042, 54046, 54050, 54054, 54058, 54062, 54066, - 54070, 54074, 54078, 54082, 54086, 54090, 54094, 54098, 54102, 54106, - 54110, 54114, 54118, 54122, 54126, 54130, 54134, 54138, 54142, 54146, - 54150, 54154, 54158, 54162, 54166, 54170, 54174, 54178, 54182, 54186, - 54190, 54194, 54198, 54202, 54206, 54210, 54214, 54218, 54222, 54226, - 54230, 54234, 54238, 54242, 54246, 54250, 54254, 54258, 54262, 54266, - 54270, 54274, 54278, 54282, 54286, 54290, 54294, 54298, 54302, 54306, - 54310, 54314, 54318, 54322, 54326, 54330, 54334, 54338, 54342, 54346, - 54350, 54354, 54358, 54362, 54366, 54370, 54374, 54378, 54382, 54386, - 54390, 54394, 54398, 54402, 54406, 54410, 54414, 54418, 54422, 54426, - 54430, 54434, 54438, 54442, 54446, 54450, 54454, 54461, 54469, 54475, - 54481, 54488, 54495, 54501, 54507, 54514, 54521, 54526, 54531, 54536, - 54541, 54547, 54553, 54561, 54568, 54573, 54578, 54586, 54595, 54602, - 54612, 54623, 54626, 54629, 54633, 54637, 54643, 54649, 54659, 54669, - 54678, 54687, 54693, 54699, 54706, 54713, 54722, 54732, 54743, 54753, - 54763, 54773, 54784, 54795, 54805, 54816, 54826, 54836, 54844, 54854, - 54864, 54875, 54886, 54893, 54900, 54907, 54914, 54924, 54934, 54941, - 54948, 54955, 54962, 54969, 54976, 54983, 54988, 54993, 54999, 55007, - 55017, 55025, 55033, 55041, 55049, 55057, 55065, 55073, 55081, 55089, - 55097, 55106, 55115, 55123, 55131, 55140, 55149, 55158, 55167, 55177, - 55187, 55196, 55205, 55215, 55225, 55239, 55255, 55269, 55285, 55299, - 55313, 55327, 55341, 55351, 55362, 55372, 55383, 55399, 55415, 55423, - 55429, 55436, 55443, 55450, 55458, 55463, 55469, 55474, 55479, 55485, - 55490, 55495, 55500, 55505, 55510, 55517, 55523, 55531, 55537, 55543, - 55547, 55551, 55560, 55569, 55578, 55587, 55594, 55601, 55614, 55627, - 55640, 55653, 55661, 55669, 55676, 55683, 55691, 55699, 55707, 55715, - 55719, 55724, 55732, 55740, 55748, 55755, 55759, 55767, 55775, 55778, - 55782, 55787, 55794, 55802, 55810, 55829, 55849, 55868, 55888, 55908, - 55928, 55948, 55968, 55974, 55981, 55990, 55998, 56006, 56012, 56015, - 56018, 56023, 56026, 56046, 56053, 56059, 56065, 56069, 56072, 56075, - 56078, 56088, 56100, 56107, 56114, 56117, 56121, 56124, 56129, 56134, - 56139, 56145, 56154, 56161, 56168, 56176, 56183, 56190, 56193, 56199, - 56205, 56208, 56211, 56216, 56221, 56227, 56233, 56237, 56242, 56249, - 56253, 56259, 56263, 56267, 56275, 56287, 56295, 56299, 56301, 56310, - 56319, 56325, 56328, 56334, 56340, 56345, 56350, 56355, 56360, 56365, - 56370, 56372, 56378, 56383, 56391, 56395, 56401, 56404, 56408, 56416, - 56424, 56426, 56428, 56434, 56440, 56446, 56455, 56464, 56471, 56478, - 56484, 56491, 56496, 56501, 56506, 56512, 56518, 56523, 56530, 56534, - 56538, 56551, 56564, 56576, 56585, 56591, 56598, 56603, 56608, 56613, - 56618, 56623, 56625, 56632, 56640, 56648, 56656, 56663, 56671, 56677, - 56682, 56688, 56694, 56700, 56707, 56713, 56721, 56729, 56737, 56745, - 56753, 56759, 56765, 56774, 56778, 56787, 56796, 56805, 56813, 56817, - 56823, 56830, 56837, 56841, 56847, 56855, 56861, 56866, 56872, 56877, - 56882, 56889, 56896, 56901, 56906, 56914, 56922, 56932, 56942, 56949, - 56956, 56960, 56964, 56976, 56982, 56989, 56994, 56999, 57006, 57013, - 57019, 57025, 57035, 57042, 57050, 57058, 57067, 57074, 57080, 57087, - 57093, 57101, 57109, 57117, 57125, 57131, 57136, 57146, 57157, 57164, - 57173, 57179, 57184, 57189, 57199, 57208, 57214, 57220, 57228, 57233, - 57240, 57247, 57258, 57265, 57272, 57279, 57286, 57293, 57302, 57311, - 57324, 57337, 57349, 57361, 57374, 57388, 57394, 57400, 57410, 57420, - 57427, 57434, 57444, 57454, 57463, 57472, 57480, 57488, 57498, 57508, - 57523, 57538, 57547, 57556, 57569, 57582, 57591, 57600, 57611, 57622, - 57628, 57634, 57643, 57652, 57657, 57662, 57670, 57676, 57682, 57690, - 57698, 57711, 57724, 57728, 57732, 57741, 57750, 57757, 57765, 57773, - 57783, 57793, 57799, 57805, 57813, 57821, 57829, 57837, 57847, 57857, - 57860, 57863, 57868, 57873, 57879, 57885, 57892, 57899, 57910, 57921, - 57928, 57935, 57943, 57951, 57960, 57969, 57978, 57987, 57994, 58001, - 58005, 58009, 58018, 58027, 58032, 58037, 58042, 58047, 58053, 58067, - 58074, 58081, 58085, 58087, 58089, 58094, 58099, 58104, 58109, 58117, - 58124, 58131, 58139, 58151, 58159, 58167, 58178, 58182, 58186, 58192, - 58200, 58213, 58220, 58227, 58234, 58240, 58247, 58256, 58265, 58271, - 58277, 58283, 58294, 58305, 58313, 58322, 58327, 58330, 58335, 58340, - 58345, 58351, 58357, 58361, 58364, 58368, 58372, 58377, 58382, 58388, - 58394, 58398, 58402, 58409, 58416, 58423, 58430, 58437, 58444, 58453, - 58462, 58469, 58476, 58484, 58492, 58496, 58501, 58506, 58512, 58518, - 58521, 58524, 58527, 58530, 58535, 58540, 58545, 58550, 58555, 58560, - 58564, 58568, 58572, 58577, 58582, 58586, 58590, 58596, 58600, 58606, - 58611, 58618, 58626, 58633, 58641, 58648, 58656, 58665, 58672, 58682, - 58693, 58699, 58708, 58714, 58723, 58733, 58739, 58745, 58749, 58753, - 58762, 58772, 58779, 58787, 58796, 58805, 58812, 58818, 58825, 58830, - 58834, 58838, 58843, 58848, 58853, 58861, 58869, 58872, 58876, 58885, - 58895, 58904, 58914, 58926, 58940, 58944, 58949, 58953, 58958, 58963, - 58968, 58974, 58980, 58987, 58994, 59000, 59007, 59013, 59020, 59029, - 59038, 59044, 59051, 59057, 0, 0, 59064, 59072, 59080, 59089, 59098, - 59107, 59117, 59126, 59136, 59142, 59147, 59156, 59168, 59177, 59189, - 59196, 59204, 59211, 59219, 59224, 59230, 59235, 59241, 59249, 59258, - 59266, 59275, 59279, 59282, 59286, 59289, 59299, 0, 59302, 59309, 59318, - 59328, 59337, 59347, 59353, 59360, 59366, 59373, 59384, 59395, 59406, - 59417, 59427, 59437, 59447, 59457, 59465, 59473, 59481, 59489, 59497, - 59505, 59513, 59521, 59527, 59532, 59538, 59543, 59549, 59555, 59561, - 59567, 59579, 59589, 59594, 59601, 59606, 59613, 59616, 59620, 59624, - 59629, 59633, 59638, 59641, 59650, 59659, 59668, 59677, 59682, 59688, - 59694, 59702, 59712, 59719, 59728, 59733, 59736, 59739, 59744, 59749, - 59754, 59759, 59761, 59763, 59765, 59767, 59769, 59771, 59776, 59783, - 59790, 59792, 59794, 59796, 59798, 59800, 59802, 59804, 59806, 59811, - 59816, 59823, 59830, 59839, 59849, 59858, 59868, 59873, 59878, 59880, - 59887, 59894, 59901, 59908, 59915, 59922, 59929, 59932, 59935, 59938, - 59941, 59946, 59951, 59956, 59961, 59966, 59971, 59976, 59981, 59986, - 59991, 59996, 60001, 60007, 60011, 60016, 60021, 60026, 60031, 60036, - 60041, 60046, 60051, 60056, 60061, 60066, 60071, 60076, 60081, 60086, - 60091, 60096, 60101, 60106, 60111, 60116, 60121, 60127, 60132, 60138, - 60147, 60152, 60160, 60167, 60176, 60181, 60186, 60191, 60197, 60204, - 60211, 60216, 60221, 60226, 60231, 60236, 60241, 60246, 60251, 60256, - 60261, 60267, 60271, 60276, 60281, 60286, 60291, 60296, 60301, 60306, - 60311, 60316, 60321, 60326, 60331, 60336, 60341, 60346, 60351, 60356, - 60361, 60366, 60371, 60376, 60381, 60387, 60392, 60398, 60407, 60412, - 60420, 60427, 60436, 60441, 60446, 60451, 60457, 60464, 60471, 60479, - 60487, 60496, 60503, 60511, 60517, 60526, 60534, 60542, 60550, 60558, - 60566, 60574, 60579, 60586, 60591, 60597, 60605, 60612, 60619, 60627, - 60633, 60639, 60646, 60654, 60663, 60673, 60679, 60686, 60691, 60701, - 60711, 60716, 60721, 60726, 60731, 60736, 60741, 60746, 60751, 60756, - 60761, 60766, 60771, 60776, 60781, 60786, 60791, 60796, 60801, 60806, - 60811, 60816, 60821, 60826, 60831, 60836, 60841, 60846, 60851, 60856, - 60861, 60865, 60869, 60874, 60879, 60884, 60889, 60894, 60899, 60904, - 60909, 60914, 60919, 60924, 60929, 60934, 60939, 60944, 60949, 60954, - 60959, 60966, 60973, 60980, 60987, 60994, 61001, 61008, 61015, 61022, - 61029, 61036, 61043, 61050, 61057, 61062, 61067, 61074, 61081, 61088, - 61095, 61102, 61109, 61116, 61123, 61130, 61137, 61144, 61151, 61157, - 61163, 61169, 61175, 61182, 61189, 61196, 61203, 61210, 61217, 61224, - 61231, 61238, 61245, 61253, 61261, 61269, 61277, 61285, 61293, 61301, - 61309, 61313, 61319, 61325, 61329, 61335, 61341, 61347, 61354, 61361, - 61368, 61375, 61380, 61386, 61392, 61399, 0, 0, 0, 0, 0, 61406, 61414, - 61423, 61432, 61440, 61446, 61451, 61456, 61461, 61466, 61471, 61476, - 61481, 61486, 61491, 61496, 61501, 61506, 61511, 61516, 61521, 61526, - 61531, 61536, 61541, 61546, 61551, 61556, 61561, 61566, 61571, 61576, - 61581, 61586, 61591, 61596, 61601, 61606, 61611, 61616, 61621, 61626, - 61631, 61636, 61641, 0, 61646, 0, 0, 0, 0, 0, 61651, 0, 0, 61656, 61660, - 61665, 61670, 61675, 61680, 61689, 61694, 61699, 61704, 61709, 61714, - 61719, 61724, 61729, 61736, 61741, 61746, 61755, 61762, 61767, 61772, - 61777, 61784, 61789, 61796, 61801, 61806, 61813, 61820, 61825, 61830, - 61835, 61842, 61849, 61854, 61859, 61864, 61869, 61874, 61881, 61888, - 61893, 61898, 61903, 61908, 61913, 61918, 61923, 61928, 61933, 61938, - 61943, 61950, 61955, 61960, 0, 0, 0, 0, 0, 0, 0, 61965, 61972, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 61977, 61982, 61986, 61990, 61994, - 61998, 62002, 62006, 62010, 62014, 62018, 62022, 62028, 62032, 62036, - 62040, 62044, 62048, 62052, 62056, 62060, 62064, 62068, 62072, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 62076, 62080, 62084, 62088, 62092, 62096, 62100, 0, - 62104, 62108, 62112, 62116, 62120, 62124, 62128, 0, 62132, 62136, 62140, - 62144, 62148, 62152, 62156, 0, 62160, 62164, 62168, 62172, 62176, 62180, - 62184, 0, 62188, 62192, 62196, 62200, 62204, 62208, 62212, 0, 62216, - 62220, 62224, 62228, 62232, 62236, 62240, 0, 62244, 62248, 62252, 62256, - 62260, 62264, 62268, 0, 62272, 62276, 62280, 62284, 62288, 62292, 62296, - 0, 62300, 62305, 62310, 62315, 62320, 62325, 62330, 62334, 62339, 62344, - 62349, 62353, 62358, 62363, 62368, 62373, 62377, 62382, 62387, 62392, - 62397, 62402, 62407, 62411, 62416, 62421, 62428, 62433, 62438, 62444, - 62451, 62458, 62467, 62474, 62483, 62488, 62493, 62500, 62507, 62513, - 62521, 62527, 62532, 62537, 62541, 62548, 62555, 62559, 62561, 62565, - 62571, 62573, 62577, 62581, 62585, 62591, 62596, 62600, 62604, 62609, - 62615, 62621, 62627, 62632, 62637, 62644, 62651, 62657, 62663, 62669, - 62675, 62681, 62687, 62691, 62695, 62702, 62709, 62715, 62719, 62724, - 62727, 62731, 62738, 62741, 62745, 62749, 62752, 62758, 62764, 62767, - 62773, 62777, 62781, 62787, 62792, 62797, 62799, 62802, 62806, 62812, - 62818, 62822, 62827, 62836, 62839, 62845, 62850, 62854, 62858, 62862, - 62865, 62870, 62876, 62884, 62892, 62898, 62903, 62908, 62914, 62920, - 62927, 62934, 62940, 62946, 62952, 62958, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 62962, 62966, 62970, 62975, 62980, 62985, 62989, 62993, 62997, 63002, - 63007, 63011, 63015, 63019, 63023, 63028, 63033, 63038, 63043, 63047, - 63051, 63056, 63061, 63066, 63071, 63075, 0, 63079, 63083, 63087, 63091, - 63095, 63099, 63103, 63108, 63113, 63117, 63122, 63127, 63136, 63140, - 63144, 63148, 63155, 63159, 63164, 63169, 63173, 63177, 63183, 63188, - 63193, 63198, 63203, 63207, 63211, 63215, 63219, 63223, 63228, 63233, - 63237, 63241, 63246, 63251, 63256, 63260, 63264, 63269, 63274, 63280, - 63286, 63290, 63296, 63302, 63306, 63312, 63318, 63323, 63328, 63332, - 63338, 63342, 63346, 63352, 63358, 63363, 63368, 63372, 63376, 63384, - 63390, 63396, 63402, 63407, 63412, 63417, 63423, 63427, 63433, 63437, - 63441, 63447, 63453, 63459, 63465, 63471, 63477, 63483, 63489, 63495, - 63501, 63507, 63513, 63517, 63523, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 63529, 63532, 63536, 63540, 63544, 63548, 63551, 63554, 63558, 63562, - 63566, 63570, 63573, 63578, 63582, 63586, 63590, 63596, 63600, 63604, - 63608, 63612, 63619, 63625, 63629, 63633, 63637, 63641, 63645, 63649, - 63653, 63657, 63661, 63665, 63669, 63675, 63679, 63683, 63687, 63691, - 63695, 63699, 63703, 63707, 63711, 63715, 63719, 63723, 63727, 63731, - 63735, 63739, 63745, 63751, 63756, 63761, 63765, 63769, 63773, 63777, - 63781, 63785, 63789, 63793, 63797, 63801, 63805, 63809, 63813, 63817, - 63821, 63825, 63829, 63833, 63837, 63841, 63845, 63849, 63853, 63857, - 63863, 63867, 63871, 63875, 63879, 63883, 63887, 63891, 63895, 63900, - 63907, 63911, 63915, 63919, 63923, 63927, 63931, 63935, 63939, 63943, - 63947, 63951, 63955, 63962, 63966, 63972, 63976, 63980, 63984, 63988, - 63992, 63995, 63999, 64003, 64007, 64011, 64015, 64019, 64023, 64027, - 64031, 64035, 64039, 64043, 64047, 64051, 64055, 64059, 64063, 64067, - 64071, 64075, 64079, 64083, 64087, 64091, 64095, 64099, 64103, 64107, - 64111, 64115, 64119, 64123, 64129, 64133, 64137, 64141, 64145, 64149, - 64153, 64157, 64161, 64165, 64169, 64173, 64177, 64181, 64185, 64189, - 64193, 64197, 64201, 64205, 64209, 64213, 64217, 64221, 64225, 64229, - 64233, 64237, 64245, 64249, 64253, 64257, 64261, 64265, 64271, 64275, - 64279, 64283, 64287, 64291, 64295, 64299, 64303, 64307, 64311, 64315, - 64319, 64323, 64329, 64333, 64337, 64341, 64345, 64349, 64353, 64357, - 64361, 64365, 64369, 64373, 64377, 64381, 64385, 64389, 64393, 64397, - 64401, 64405, 64409, 64413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64417, 64425, 64433, 64443, 64453, - 64462, 64472, 64482, 64493, 64505, 64516, 64528, 0, 0, 0, 0, 64535, - 64538, 64541, 64546, 64549, 64556, 64560, 64564, 64568, 64573, 64578, - 64584, 64590, 64595, 64600, 64606, 64612, 64618, 64624, 64627, 64630, - 64637, 64644, 64650, 64656, 64664, 64672, 64677, 64682, 64686, 64694, - 64700, 64707, 64712, 64717, 64722, 64727, 64732, 64737, 64742, 64747, - 64752, 64757, 64762, 64767, 64772, 64777, 64783, 64788, 64792, 64798, - 64809, 64818, 64832, 64841, 64845, 64855, 64861, 64867, 64873, 64878, - 64881, 64886, 64890, 0, 64896, 64901, 64905, 64910, 64914, 64919, 64923, - 64928, 64932, 64937, 64941, 64945, 64950, 64955, 64960, 64965, 64970, - 64975, 64980, 64985, 64990, 64994, 64999, 65004, 65009, 65014, 65019, - 65024, 65029, 65034, 65039, 65044, 65049, 65054, 65059, 65065, 65070, - 65075, 65080, 65085, 65089, 65094, 65098, 65103, 65108, 65113, 65118, - 65122, 65127, 65131, 65136, 65141, 65146, 65151, 65156, 65161, 65166, - 65171, 65176, 65181, 65186, 65191, 65195, 65200, 65205, 65210, 65215, - 65220, 65224, 65230, 65235, 65241, 65246, 65250, 65255, 65260, 65265, - 65270, 65276, 65281, 65286, 65291, 65296, 65301, 65306, 65311, 0, 0, - 65317, 65325, 65333, 65340, 65347, 65352, 65359, 65365, 65370, 65374, - 65377, 65381, 65384, 65388, 65391, 65395, 65398, 65402, 65405, 65408, - 65412, 65416, 65420, 65424, 65428, 65432, 65436, 65440, 65444, 65447, - 65451, 65455, 65459, 65463, 65467, 65471, 65475, 65479, 65483, 65487, - 65491, 65495, 65499, 65504, 65508, 65512, 65516, 65520, 65523, 65527, - 65530, 65534, 65538, 65542, 65546, 65549, 65553, 65556, 65560, 65564, - 65568, 65572, 65576, 65580, 65584, 65588, 65592, 65596, 65600, 65604, - 65607, 65611, 65615, 65619, 65623, 65627, 65630, 65635, 65639, 65644, - 65648, 65651, 65655, 65659, 65663, 65667, 65672, 65676, 65680, 65684, - 65688, 65692, 65696, 65700, 65705, 65709, 65713, 65717, 65721, 65725, - 65732, 65736, 65742, 0, 0, 0, 0, 0, 65747, 65752, 65757, 65762, 65767, - 65772, 65777, 65782, 65786, 65791, 65796, 65801, 65806, 65811, 65816, - 65821, 65826, 65831, 65835, 65840, 65845, 65850, 65854, 65858, 65862, - 65867, 65872, 65877, 65882, 65887, 65892, 65897, 65902, 65907, 65912, - 65916, 65920, 65925, 65930, 65935, 65940, 65945, 65952, 0, 65957, 65961, - 65965, 65969, 65973, 65977, 65981, 65985, 65989, 65993, 65997, 66001, - 66005, 66009, 66013, 66017, 66021, 66025, 66029, 66033, 66037, 66041, - 66045, 66049, 66053, 66057, 66061, 66065, 66069, 66073, 66077, 66080, - 66084, 66087, 66091, 66095, 66098, 66102, 66106, 66109, 66113, 66117, - 66121, 66125, 66128, 66132, 66136, 66140, 66144, 66148, 66152, 66155, - 66158, 66162, 66166, 66170, 66174, 66178, 66182, 66186, 66190, 66194, - 66198, 66202, 66206, 66210, 66214, 66218, 66222, 66226, 66230, 66234, - 66238, 66242, 66246, 66250, 66254, 66258, 66262, 66266, 66270, 66274, - 66278, 66282, 66286, 66290, 66294, 66298, 66302, 66306, 66310, 66314, - 66318, 66322, 0, 66326, 66332, 66338, 66343, 66348, 66353, 66359, 66365, - 66370, 66376, 66382, 66388, 66394, 66400, 66406, 66412, 66418, 66423, - 66428, 66433, 66438, 66443, 66448, 66453, 66458, 66463, 66468, 66473, - 66478, 66483, 66488, 66493, 66498, 66503, 66508, 66513, 66518, 66524, - 66530, 66536, 66542, 66547, 66552, 66557, 66563, 66568, 66573, 66578, - 66583, 66588, 66593, 66598, 66603, 66608, 66613, 66618, 66623, 66628, - 66633, 66638, 66643, 66648, 66653, 66658, 66663, 66668, 66673, 66678, - 66683, 66688, 66693, 66698, 66703, 66708, 66713, 66718, 66723, 66728, - 66733, 66738, 66743, 66748, 66753, 66758, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 66763, 66768, 66773, 66778, 66782, 66787, 66791, 66796, 66801, - 66806, 66811, 66816, 66820, 66825, 66830, 66835, 66840, 66844, 66848, - 66852, 66856, 66860, 66864, 66868, 66872, 66876, 66880, 66884, 66888, - 66892, 66896, 66901, 66906, 66911, 66916, 66921, 66926, 66931, 66936, - 66941, 66946, 66951, 66956, 66961, 66966, 66971, 66978, 0, 66986, 66990, - 66994, 66998, 67002, 67006, 67010, 67014, 67018, 67022, 67027, 67032, - 67037, 67042, 67047, 67052, 67057, 67062, 67067, 67072, 67077, 67082, - 67087, 67092, 67097, 67102, 67107, 67112, 67117, 67122, 67127, 67132, - 67137, 67142, 67147, 67152, 67157, 67162, 67167, 67172, 67177, 67186, - 67195, 67204, 67213, 67222, 67231, 67240, 67249, 67252, 67257, 67262, - 67267, 67272, 67277, 67282, 67287, 67292, 67297, 67301, 67306, 67311, - 67316, 67321, 67326, 67330, 67334, 67338, 67342, 67346, 67350, 67354, - 67358, 67362, 67366, 67370, 67374, 67378, 67382, 67387, 67392, 67397, - 67402, 67407, 67412, 67417, 67422, 67427, 67432, 67437, 67442, 67447, - 67452, 67459, 67466, 67471, 67476, 67480, 67484, 67488, 67492, 67496, - 67500, 67504, 67508, 67512, 67517, 67522, 67527, 67532, 67537, 67542, - 67547, 67552, 67557, 67562, 67567, 67572, 67577, 67582, 67587, 67592, - 67597, 67602, 67607, 67612, 67617, 67622, 67627, 67632, 67637, 67642, - 67647, 67652, 67657, 67662, 67667, 67671, 67676, 67681, 67686, 67691, - 67696, 67701, 67706, 67711, 67716, 67721, 67726, 67731, 67735, 67740, - 67745, 67750, 67755, 67760, 67765, 67770, 67775, 67780, 67784, 67791, - 67798, 67805, 67812, 67819, 67826, 67833, 67840, 67847, 67854, 67861, - 67868, 67871, 67874, 67877, 67882, 67885, 67888, 67891, 67894, 67897, - 67900, 67904, 67908, 67912, 67916, 67919, 67923, 67927, 67931, 67935, - 67939, 67943, 67947, 67951, 67954, 67957, 67961, 67965, 67969, 67973, - 67976, 67980, 67984, 67988, 67992, 67995, 67999, 68003, 68007, 68011, - 68014, 68018, 68022, 68025, 68029, 68033, 68037, 68041, 68045, 68049, - 68053, 68057, 68064, 68067, 68070, 68073, 68076, 68079, 68082, 68085, - 68088, 68091, 68094, 68097, 68100, 68103, 68106, 68109, 68112, 68115, - 68118, 68121, 68124, 68127, 68130, 68133, 68136, 68139, 68142, 68145, - 68148, 68151, 68154, 68157, 68160, 68163, 68166, 68169, 68172, 68175, - 68178, 68181, 68184, 68187, 68190, 68193, 68196, 68199, 68202, 68205, - 68208, 68211, 68214, 68217, 68220, 68223, 68226, 68229, 68232, 68235, - 68238, 68241, 68244, 68247, 68250, 68253, 68256, 68259, 68262, 68265, - 68268, 68271, 68274, 68277, 68280, 68283, 68286, 68289, 68292, 68295, - 68298, 68301, 68304, 68307, 68310, 68313, 68316, 68319, 68322, 68325, - 68328, 68337, 68345, 68353, 68361, 68369, 68377, 68385, 68393, 68401, - 68409, 68418, 68427, 68436, 68445, 68454, 68463, 68472, 68481, 68490, - 68499, 68508, 68517, 68526, 68535, 68544, 68547, 68550, 68553, 68555, - 68558, 68561, 68564, 68569, 68574, 68577, 68584, 68591, 68598, 68605, - 68608, 68613, 68615, 68619, 68621, 68623, 68626, 68629, 68632, 68635, - 68638, 68641, 68644, 68649, 68654, 68657, 68660, 68663, 68666, 68669, - 68672, 68675, 68679, 68682, 68685, 68688, 68691, 68694, 68699, 68702, - 68705, 68708, 68713, 68718, 68723, 68728, 68733, 68738, 68743, 68748, - 68754, 68762, 68764, 68767, 68770, 68773, 68776, 68782, 68790, 68793, - 68796, 68801, 68804, 68807, 68810, 68815, 68818, 68821, 68826, 68829, - 68832, 68837, 68840, 68843, 68848, 68853, 68858, 68861, 68864, 68867, - 68870, 68876, 68879, 68882, 68885, 68887, 68890, 68893, 68896, 68901, - 68904, 68907, 68910, 68913, 68916, 68921, 68924, 68927, 68930, 68933, - 68936, 68939, 68942, 68945, 68948, 68954, 68959, 68967, 68975, 68983, - 68991, 68999, 69007, 69015, 69023, 69031, 69040, 69049, 69058, 69067, - 69076, 69085, 69094, 69103, 69112, 69121, 69130, 69139, 69148, 69157, - 69166, 69175, 69184, 69193, 69202, 69211, 69220, 69229, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69232, 69241, - 69250, 69261, 69268, 69273, 69278, 69285, 69292, 69298, 69303, 69308, - 69313, 69318, 69325, 69330, 69335, 69340, 69351, 69356, 69361, 69368, - 69373, 69380, 69385, 69390, 69397, 69404, 69411, 69420, 69429, 69434, - 69439, 69444, 69451, 69456, 69466, 69473, 69478, 69483, 69488, 69493, - 69498, 69503, 69511, 69518, 69525, 69530, 69537, 69542, 69549, 69558, - 69569, 69574, 69583, 69588, 69595, 69604, 69613, 69618, 69623, 69630, - 69636, 69643, 69650, 69654, 69658, 69661, 69665, 69669, 69673, 69677, - 69681, 69685, 69689, 69692, 69696, 69700, 69704, 69708, 69712, 69716, - 69719, 69723, 69727, 69730, 69734, 69738, 69742, 69746, 69750, 69754, - 69758, 69762, 69766, 69770, 69774, 69778, 69782, 69786, 69790, 69794, - 69798, 69802, 69806, 69810, 69814, 69818, 69822, 69826, 69830, 69834, - 69838, 69842, 69846, 69850, 69854, 69858, 69862, 69866, 69870, 69874, - 69878, 69882, 69886, 69890, 69894, 69898, 69902, 69906, 69909, 69913, - 69917, 69921, 69925, 69929, 69933, 69937, 69941, 69945, 69949, 69953, - 69957, 69961, 69965, 69969, 69973, 69977, 69981, 69985, 69989, 69993, - 69997, 70001, 70005, 70009, 70013, 70017, 70021, 70025, 70029, 70033, - 70037, 70041, 70045, 70049, 70053, 70057, 70061, 70065, 70069, 70073, - 70077, 70081, 70085, 70089, 70093, 70097, 70101, 70105, 70109, 70113, - 70117, 70121, 70125, 70129, 70133, 70137, 70141, 70145, 70149, 70153, - 70157, 70161, 70165, 70169, 70173, 70177, 70181, 70185, 70189, 70193, - 70197, 70201, 70205, 70209, 70213, 70217, 70221, 70225, 70229, 70233, - 70237, 70241, 70245, 70249, 70253, 70257, 70261, 70265, 70269, 70273, - 70277, 70281, 70285, 70289, 70293, 70297, 70301, 70305, 70309, 70313, - 70317, 70321, 70325, 70329, 70333, 70337, 70341, 70345, 70349, 70353, - 70357, 70361, 70365, 70369, 70373, 70377, 70380, 70384, 70388, 70392, - 70396, 70400, 70404, 70408, 70412, 70416, 70420, 70424, 70428, 70432, - 70436, 70440, 70444, 70448, 70452, 70456, 70460, 70464, 70468, 70472, - 70476, 70480, 70484, 70488, 70492, 70496, 70500, 70504, 70508, 70512, - 70516, 70520, 70524, 70528, 70532, 70536, 70540, 70544, 70548, 70552, - 70556, 70560, 70564, 70568, 70572, 70576, 70580, 70584, 70588, 70592, - 70596, 70600, 70604, 70608, 70612, 70616, 70620, 70624, 70628, 70632, - 70636, 70640, 70644, 70648, 70652, 70656, 70660, 70664, 70668, 70672, - 70676, 70680, 70684, 70688, 70692, 70696, 70700, 70704, 70708, 70712, - 70716, 70720, 70724, 70728, 70732, 70736, 70740, 70744, 70748, 70752, - 70756, 70760, 70764, 70768, 70772, 70776, 70780, 70784, 70788, 70792, - 70796, 70800, 70804, 70808, 70812, 70816, 70820, 70824, 70828, 70832, - 70836, 70840, 70843, 70847, 70851, 70855, 70859, 70863, 70867, 70871, - 70875, 70879, 70883, 70887, 70891, 70895, 70899, 70903, 70907, 70911, - 70915, 70919, 70923, 70927, 70931, 70935, 70939, 70943, 70947, 70951, - 70955, 70959, 70963, 70967, 70971, 70975, 70979, 70983, 70987, 70991, - 70995, 70999, 71003, 71007, 71011, 71015, 71019, 71023, 71027, 71031, - 71035, 71039, 71043, 71047, 71051, 71055, 71059, 71063, 71067, 71071, - 71075, 71079, 71083, 71087, 71091, 71095, 71099, 71103, 71107, 71111, - 71115, 71119, 71123, 71127, 71131, 71135, 71139, 71143, 71147, 71151, - 71155, 71159, 71163, 71167, 71171, 71175, 71179, 71183, 71187, 71191, - 71195, 71199, 71202, 71206, 71210, 71214, 71218, 71222, 71226, 71230, - 71234, 71238, 71242, 71246, 71250, 71254, 71258, 71262, 71266, 71270, - 71274, 71278, 71282, 71286, 71290, 71294, 71298, 71302, 71306, 71310, - 71314, 71318, 71322, 71326, 71330, 71334, 71338, 71342, 71346, 71350, - 71354, 71358, 71362, 71366, 71370, 71374, 71378, 71382, 71386, 71390, - 71394, 71398, 71402, 71406, 71410, 71414, 71418, 71422, 71426, 71430, - 71434, 71438, 71441, 71445, 71449, 71453, 71457, 71461, 71465, 71469, - 71473, 71477, 71481, 71485, 71489, 71493, 71497, 71501, 71505, 71509, - 71513, 71517, 71521, 71525, 71529, 71533, 71537, 71541, 71545, 71549, - 71553, 71557, 71561, 71565, 71569, 71573, 71577, 71581, 71585, 71589, - 71593, 71597, 71601, 71605, 71609, 71613, 71617, 71621, 71625, 71629, - 71633, 71637, 71641, 71645, 71649, 71653, 71657, 71661, 71665, 71669, - 71673, 71677, 71681, 71685, 71689, 71693, 71696, 71700, 71704, 71708, - 71712, 71716, 71720, 71724, 71728, 71732, 71736, 71740, 71744, 71748, - 71752, 71756, 71760, 71764, 71768, 71772, 71776, 71780, 71784, 71788, - 71792, 71796, 71800, 71804, 71808, 71812, 71816, 71820, 71824, 71828, - 71832, 71836, 71840, 71844, 71848, 71852, 71856, 71860, 71864, 71868, - 71872, 71876, 71880, 71884, 71888, 71892, 71896, 71900, 71904, 71908, - 71912, 71916, 71920, 71924, 71928, 71932, 71936, 71940, 71944, 71948, - 71952, 71956, 71960, 71964, 71968, 71972, 71976, 71980, 71984, 71988, - 71992, 71996, 72000, 72004, 72008, 72012, 72016, 72020, 72024, 72028, - 72032, 72036, 72040, 72044, 72048, 72052, 72056, 72060, 72064, 72068, - 72072, 72076, 72080, 72084, 72088, 72092, 72096, 72100, 72104, 72108, - 72112, 72116, 72120, 72124, 72128, 72132, 72136, 72140, 72144, 72148, - 72151, 72155, 72159, 72163, 72167, 72171, 72175, 72179, 72183, 72187, - 72191, 72195, 72199, 72203, 72207, 72211, 72215, 72219, 72223, 72227, - 72231, 72235, 72239, 72243, 72247, 72251, 72255, 72259, 72263, 72267, - 72271, 72275, 72279, 72283, 72287, 72291, 72295, 72299, 72303, 72307, - 72311, 72315, 72319, 72323, 72327, 72331, 72335, 72339, 72343, 72347, - 72351, 72355, 72359, 72363, 72367, 72371, 72375, 72379, 72383, 72387, - 72391, 72395, 72399, 72403, 72407, 72411, 72415, 72419, 72423, 72427, - 72431, 72435, 72439, 72443, 72447, 72451, 72455, 72459, 72463, 72467, - 72471, 72475, 72479, 72483, 72487, 72491, 72495, 72499, 72503, 72507, - 72511, 72515, 72519, 72523, 72527, 72531, 72535, 72539, 72543, 72547, - 72551, 72555, 72559, 72563, 72567, 72571, 72575, 72579, 72583, 72587, - 72591, 72595, 72599, 72603, 72607, 72611, 72615, 72619, 72623, 72627, - 72631, 72635, 72639, 72643, 72647, 72651, 72655, 72659, 72663, 72667, - 72671, 72675, 72679, 72683, 72687, 72691, 72695, 72699, 72703, 72707, - 72711, 72715, 72719, 72723, 72727, 72731, 72735, 72739, 72743, 72747, - 72751, 72754, 72758, 72762, 72766, 72770, 72774, 72778, 72782, 72785, - 72789, 72793, 72797, 72801, 72805, 72809, 72813, 72817, 72821, 72825, - 72829, 72833, 72837, 72841, 72845, 72849, 72853, 72857, 72861, 72865, - 72869, 72873, 72877, 72881, 72885, 72889, 72893, 72897, 72901, 72905, - 72909, 72913, 72917, 72921, 72925, 72929, 72933, 72937, 72941, 72945, - 72949, 72953, 72957, 72961, 72965, 72969, 72973, 72977, 72981, 72985, - 72989, 72993, 72997, 73001, 73005, 73009, 73013, 73017, 73021, 73025, - 73029, 73033, 73037, 73041, 73045, 73049, 73053, 73057, 73061, 73065, - 73069, 73073, 73077, 73081, 73085, 73089, 73093, 73097, 73101, 73105, - 73109, 73113, 73117, 73121, 73125, 73129, 73133, 73137, 73141, 73145, - 73149, 73153, 73157, 73161, 73165, 73169, 73173, 73177, 73181, 73185, - 73189, 73193, 73197, 73201, 73205, 73209, 73213, 73217, 73221, 73225, - 73229, 73233, 73237, 73241, 73245, 73249, 73253, 73257, 73261, 73265, - 73269, 73273, 73277, 73281, 73285, 73289, 73293, 73297, 73301, 73305, - 73309, 73313, 73317, 73321, 73325, 73329, 73333, 73337, 73341, 73345, - 73349, 73353, 73357, 73361, 73365, 73369, 73373, 73377, 73381, 73385, - 73389, 73393, 73397, 73401, 73405, 73409, 73413, 73417, 73421, 73425, - 73429, 73433, 73437, 73441, 73445, 73449, 73453, 73457, 73461, 73465, - 73469, 73473, 73477, 73481, 73485, 73489, 73493, 73497, 73501, 73505, - 73509, 73512, 73516, 73520, 73524, 73528, 73532, 73536, 73540, 73544, - 73548, 73552, 73556, 73560, 73564, 73568, 73572, 73576, 73580, 73584, - 73588, 73592, 73596, 73600, 73604, 73608, 73612, 73616, 73620, 73624, - 73628, 73632, 73636, 73640, 73644, 73648, 73652, 73656, 73660, 73664, - 73668, 73672, 73676, 73680, 73684, 73688, 73692, 73696, 73700, 73704, - 73708, 73712, 73716, 73720, 73724, 73728, 73732, 73736, 73740, 73744, - 73748, 73752, 73756, 73760, 73764, 73768, 73772, 73776, 73780, 73784, - 73788, 73792, 73796, 73800, 73804, 73808, 73812, 73816, 73820, 73824, - 73828, 73832, 73836, 73840, 73844, 73848, 73852, 73856, 73860, 73864, - 73868, 73872, 73876, 73880, 73884, 73888, 73892, 73896, 73900, 73904, - 73908, 73912, 73916, 73920, 73924, 73928, 73932, 73936, 73940, 73944, - 73948, 73952, 73956, 73960, 73964, 73968, 73972, 73976, 73980, 73984, - 73988, 73992, 73996, 74000, 74004, 74008, 74012, 74016, 74020, 74024, - 74028, 74032, 74036, 74040, 74044, 74048, 74052, 74056, 74060, 74064, - 74068, 74072, 74076, 74080, 74084, 74088, 74092, 74096, 74100, 74104, - 74108, 74112, 74116, 74120, 74124, 74128, 74132, 74136, 74140, 74144, - 74148, 74152, 74156, 74160, 74164, 74168, 74172, 74176, 74180, 74184, - 74188, 74192, 74196, 74200, 74204, 74208, 74212, 74216, 74220, 74224, - 74228, 74232, 74236, 74240, 74244, 74248, 74252, 74256, 74260, 74264, - 74268, 74272, 74276, 74280, 74284, 74288, 74292, 0, 0, 0, 74296, 74300, - 74304, 74308, 74312, 74316, 74320, 74324, 74328, 74332, 74336, 74340, - 74344, 74348, 74352, 74356, 74360, 74364, 74368, 74372, 74376, 74380, - 74384, 74388, 74392, 74396, 74400, 74404, 74408, 74412, 74416, 74420, - 74424, 74428, 74432, 74436, 74440, 74444, 74448, 74452, 74456, 74460, - 74464, 74468, 74472, 74476, 74480, 74484, 74488, 74492, 74496, 74500, - 74504, 74508, 74512, 0, 0, 0, 0, 0, 0, 0, 0, 0, 74516, 74521, 74525, - 74530, 74535, 74540, 74545, 74550, 74554, 74559, 74564, 74569, 74574, - 74579, 74584, 74589, 74593, 74597, 74601, 74605, 74610, 74615, 74620, - 74624, 74629, 74634, 74639, 74644, 74649, 74653, 74658, 74662, 74667, - 74671, 74676, 74680, 74684, 74688, 74693, 74698, 74703, 74711, 74719, - 74727, 74735, 74742, 74750, 74756, 74764, 74768, 74772, 74776, 74780, - 74784, 74788, 74792, 74796, 74800, 74804, 74808, 74812, 74816, 74820, - 74824, 74828, 74832, 74836, 74840, 74844, 74848, 74852, 74856, 74860, - 74864, 74868, 74872, 74876, 74880, 74884, 74888, 74892, 74896, 74900, - 74904, 74908, 74911, 74915, 74919, 74923, 74927, 74931, 74935, 74939, - 74943, 74947, 74951, 74955, 74959, 74963, 74967, 74971, 74975, 74979, - 74983, 74987, 74991, 74995, 74999, 75003, 75007, 75011, 75015, 75019, - 75023, 75027, 75031, 75035, 75039, 75043, 75047, 75051, 75055, 75058, - 75062, 75066, 75069, 75073, 75077, 75081, 75084, 75088, 75092, 75096, - 75100, 75104, 75108, 75112, 75116, 75120, 75124, 75128, 75132, 75136, - 75139, 75142, 75146, 75150, 75153, 75157, 75161, 75165, 75169, 75173, - 75177, 75180, 75183, 75187, 75191, 75195, 75198, 75201, 75205, 75209, - 75213, 75217, 75221, 75225, 75229, 75233, 75237, 75241, 75245, 75249, - 75253, 75257, 75261, 75265, 75269, 75273, 75277, 75281, 75285, 75289, - 75293, 75297, 75301, 75305, 75309, 75313, 75317, 75321, 75325, 75329, - 75333, 75337, 75341, 75345, 75349, 75352, 75356, 75360, 75364, 75368, - 75372, 75376, 75380, 75384, 75388, 75392, 75396, 75400, 75404, 75408, - 75412, 75416, 75420, 75424, 75428, 75432, 75436, 75440, 75444, 75448, - 75452, 75456, 75460, 75464, 75468, 75472, 75476, 75480, 75484, 75488, - 75492, 75496, 75499, 75503, 75507, 75511, 75515, 75519, 75523, 75527, - 75531, 75535, 75539, 75543, 75547, 75551, 75555, 75559, 75563, 75566, - 75570, 75574, 75578, 75582, 75586, 75590, 75594, 75598, 75602, 75606, - 75610, 75614, 75618, 75622, 75626, 75630, 75634, 75638, 75642, 75646, - 75650, 75653, 75657, 75661, 75665, 75669, 75673, 75677, 75681, 75685, - 75689, 75693, 75697, 75701, 75705, 75709, 75713, 75717, 75721, 75725, - 75729, 75733, 75737, 75741, 75745, 75749, 75753, 75757, 75761, 75765, - 75769, 75773, 75777, 75781, 75785, 75789, 75793, 75797, 75801, 75805, - 75809, 75813, 75817, 75821, 75825, 75828, 75833, 75837, 75843, 75848, - 75854, 75858, 75862, 75866, 75870, 75874, 75878, 75882, 75886, 75890, - 75894, 75898, 75902, 75906, 75910, 75913, 75916, 75919, 75922, 75925, - 75928, 75931, 75934, 75937, 75942, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 75948, 75953, 75958, 75963, 75968, 75975, 75982, - 75987, 75992, 75997, 76002, 76009, 76016, 76023, 76030, 76037, 76044, - 76054, 76064, 76071, 76078, 76085, 76092, 76098, 76104, 76113, 76122, - 76129, 76136, 76147, 76158, 76163, 76168, 76175, 76182, 76189, 76196, - 76203, 76210, 76217, 76224, 76230, 76236, 76242, 76248, 76255, 76262, - 76267, 76271, 76278, 76285, 76292, 76296, 76303, 76307, 76312, 76316, - 76322, 76327, 76333, 76338, 76342, 76346, 76349, 76352, 76357, 76362, - 76367, 76372, 76377, 76382, 76387, 76392, 76397, 76402, 76410, 76418, - 76423, 76428, 76433, 76438, 76443, 76448, 76453, 76458, 76463, 76468, - 76473, 76478, 76483, 76488, 76494, 76500, 76506, 76512, 76517, 76523, - 76526, 76529, 76532, 76536, 76540, 76544, 76548, 76551, 76555, 76558, - 76561, 76564, 76568, 76572, 76576, 76580, 76584, 76588, 76592, 76596, - 76600, 76604, 76608, 76612, 76616, 76620, 76624, 76628, 76632, 76636, - 76640, 76644, 76648, 76652, 76655, 76659, 76663, 76667, 76671, 76675, - 76679, 76683, 76687, 76691, 76695, 76699, 76703, 76707, 76711, 76715, - 76719, 76723, 76727, 76731, 76735, 76739, 76743, 76747, 76751, 76754, - 76758, 76762, 76766, 76770, 76774, 76778, 76782, 76785, 76789, 76793, - 76797, 76801, 76805, 76809, 76813, 76817, 76821, 76825, 76829, 76833, - 76838, 76843, 76846, 76851, 76854, 76857, 76860, 0, 0, 0, 0, 0, 0, 0, 0, - 76864, 76873, 76882, 76891, 76900, 76909, 76918, 76927, 76936, 76944, - 76951, 76959, 76966, 76974, 76984, 76993, 77003, 77012, 77022, 77030, - 77037, 77045, 77052, 77060, 77065, 77070, 77076, 77084, 77090, 77096, - 77103, 77112, 77120, 77128, 77136, 77143, 77150, 77157, 77164, 77169, - 77174, 77179, 77184, 77189, 77194, 77199, 77204, 77212, 77220, 77226, - 77232, 77237, 77242, 77247, 77252, 77257, 77262, 77267, 77272, 77281, - 77290, 77295, 77300, 77310, 77320, 77327, 77334, 77343, 77352, 77364, - 77376, 77382, 77388, 77396, 77404, 77414, 77424, 77431, 77438, 77443, - 77448, 77460, 77472, 77480, 77488, 77498, 77508, 77520, 77532, 77541, - 77550, 77557, 77564, 77571, 77578, 77587, 77596, 77601, 77606, 77613, - 77620, 77627, 77634, 77646, 77658, 77663, 77668, 77673, 77678, 77683, - 77688, 77693, 77698, 77702, 77707, 77712, 77717, 77722, 77727, 77733, - 77738, 77743, 77750, 77757, 77764, 77771, 77778, 77786, 77794, 77799, - 77804, 77810, 77816, 77823, 77830, 77837, 77844, 77851, 77855, 77862, - 77867, 77872, 77878, 77891, 77897, 77905, 77913, 77920, 77927, 77936, - 77945, 77952, 77959, 77966, 77973, 77980, 77987, 77994, 78001, 78008, - 78015, 78024, 78033, 78042, 78051, 78060, 78069, 78078, 78087, 78096, - 78105, 78112, 78120, 78126, 78134, 78140, 78146, 78152, 78158, 78166, - 78171, 78176, 78181, 78186, 78191, 78197, 78203, 78209, 78215, 78221, - 78227, 78233, 78239, 78246, 78253, 78260, 78267, 78276, 78283, 78292, - 78304, 78316, 78328, 0, 0, 0, 0, 0, 78340, 78349, 0, 78358, 0, 78364, - 78370, 78378, 78386, 78393, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 78400, 78405, 78410, 78415, 78423, 78431, - 78438, 78445, 78451, 78458, 78466, 78474, 78482, 78490, 78498, 78504, - 78510, 78517, 78523, 78529, 78535, 78542, 78549, 78556, 78563, 78570, - 78577, 78584, 78591, 78598, 78605, 78612, 78619, 78626, 78633, 78639, - 78646, 78653, 78660, 78667, 78674, 78681, 78688, 78695, 78702, 78709, - 78716, 78723, 78730, 78737, 78744, 78751, 78758, 78765, 78773, 78781, - 78789, 78797, 78805, 0, 0, 0, 78814, 78822, 78830, 78838, 78846, 78854, - 78862, 78868, 78874, 78880, 0, 0, 0, 0, 0, 0, 78886, 78890, 78895, 78900, - 78905, 78910, 78915, 78920, 78925, 78930, 78935, 78940, 78944, 78948, - 78953, 78958, 78962, 78967, 78972, 78977, 78982, 78987, 78992, 78997, - 79001, 79005, 79009, 79014, 79018, 79022, 79026, 79030, 79034, 79038, - 79042, 79047, 79052, 79057, 79062, 79067, 79074, 79080, 79085, 79090, - 79095, 79100, 79106, 79113, 79119, 79126, 79132, 79138, 79143, 79150, - 79156, 79161, 0, 0, 0, 0, 0, 0, 0, 0, 79167, 79172, 79177, 79181, 79186, - 79190, 79195, 79199, 79204, 79209, 79215, 79220, 79226, 79230, 79235, - 79240, 79244, 79249, 79254, 79258, 79263, 79268, 79273, 79278, 79283, - 79288, 79293, 79298, 79303, 79308, 79313, 79318, 79323, 79328, 79333, - 79338, 79343, 79348, 79352, 79356, 79361, 79366, 79371, 79375, 79379, - 79383, 79387, 79392, 79397, 79402, 79406, 79410, 79415, 79421, 79427, - 79432, 79438, 79443, 79449, 79455, 79462, 79468, 79475, 79480, 79486, - 79492, 79497, 79503, 79509, 79514, 0, 0, 0, 0, 0, 0, 0, 0, 79519, 79523, - 79528, 79533, 79537, 79541, 79545, 79549, 79553, 79557, 79561, 79565, 0, - 0, 0, 0, 0, 0, 79569, 79574, 79578, 79582, 79586, 79590, 79594, 79598, - 79602, 79606, 79610, 79614, 79618, 79622, 79626, 79630, 79634, 79639, - 79644, 79650, 79656, 79663, 79668, 79673, 79679, 79683, 79688, 79691, - 79694, 79698, 79703, 79707, 79712, 79719, 79725, 79731, 79737, 79743, - 79749, 79755, 79761, 79767, 79773, 79779, 79786, 79793, 79800, 79806, - 79813, 79820, 79827, 79834, 79841, 79847, 79853, 79860, 79866, 79873, - 79880, 79886, 79892, 79898, 79905, 79912, 79918, 79925, 79932, 79938, - 79945, 79951, 79958, 79965, 79971, 79977, 79984, 79990, 79997, 80004, - 80013, 80020, 80027, 80031, 80036, 80041, 80046, 80051, 80055, 80059, - 80064, 80068, 80073, 80078, 80083, 80087, 80091, 80095, 80099, 80104, - 80108, 80113, 80118, 80123, 80128, 80132, 80137, 80142, 80147, 80153, - 80158, 80164, 80170, 80176, 80182, 80188, 80193, 80199, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 80203, 80208, 80212, 80216, 80220, 80224, 80228, 80232, - 80236, 80240, 80244, 80248, 80252, 80256, 80260, 80264, 80268, 80272, - 80276, 80280, 80284, 80288, 80292, 80296, 80300, 80304, 80308, 80312, - 80316, 80320, 0, 0, 0, 80324, 80329, 80334, 80339, 80344, 80348, 80355, - 80359, 80364, 80368, 80375, 80382, 80391, 80395, 80400, 80404, 80408, - 80415, 80422, 80427, 80434, 80439, 80444, 80451, 80456, 80463, 80470, - 80475, 80480, 80487, 80492, 80499, 80506, 80511, 80518, 80523, 80530, - 80534, 80538, 80545, 80550, 80557, 80561, 80565, 80569, 80576, 80580, - 80585, 80592, 80599, 80603, 80607, 80614, 80620, 80626, 80632, 80640, - 80646, 80654, 80660, 80668, 80674, 80680, 80686, 80692, 80696, 80701, - 80706, 80712, 80718, 80724, 80730, 80736, 80742, 80748, 80754, 80762, - 80768, 0, 80775, 80779, 80784, 80788, 80792, 80796, 80800, 80804, 80808, - 80812, 80816, 0, 0, 0, 0, 80820, 80828, 80834, 80840, 80846, 80852, - 80858, 80864, 80870, 80877, 80884, 80891, 80898, 80905, 80912, 80919, - 80926, 80933, 80940, 80947, 80953, 80959, 80965, 80971, 80977, 80983, - 80989, 80995, 81001, 81008, 81015, 81022, 81029, 0, 81036, 81040, 81044, - 81048, 81052, 81057, 81061, 81065, 81070, 81075, 81080, 81085, 81090, - 81095, 81100, 81105, 81110, 81115, 81120, 81125, 81130, 81135, 81140, - 81145, 81150, 81154, 81159, 81163, 81168, 81173, 81178, 81183, 81188, - 81192, 81197, 81201, 81205, 81209, 81214, 81219, 81223, 81227, 81233, - 81238, 81244, 81250, 81255, 81261, 81266, 81272, 81278, 81284, 81289, - 81294, 81299, 0, 0, 0, 0, 0, 0, 0, 0, 0, 81305, 81311, 81317, 81323, - 81330, 81336, 81342, 81348, 81354, 81360, 81365, 81370, 81376, 81383, 0, - 0, 81390, 81395, 81399, 81403, 81407, 81411, 81415, 81419, 81423, 81427, - 0, 0, 81431, 81437, 81443, 81450, 81458, 81464, 81470, 81476, 81482, - 81488, 81494, 81500, 81506, 81512, 81518, 81524, 81529, 81534, 81539, - 81545, 81551, 81558, 81564, 81570, 81575, 81582, 81589, 81596, 81602, - 81607, 81612, 81617, 81625, 81632, 81639, 81647, 81655, 81662, 81669, - 81676, 81683, 81690, 81697, 81704, 81711, 81718, 81725, 81732, 81739, - 81746, 81753, 81760, 81767, 81774, 81781, 81788, 81795, 81801, 81807, - 81814, 81821, 81828, 81835, 81842, 81849, 81856, 81863, 81870, 81877, - 81884, 81891, 81898, 81905, 81912, 81919, 81926, 81933, 81940, 81947, - 81954, 81961, 81968, 81975, 81981, 81987, 81994, 82000, 82005, 82011, - 82016, 82021, 82026, 82033, 82039, 82045, 82051, 82057, 82063, 82069, - 82075, 82083, 82091, 82099, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 82107, 82113, 82119, 82125, 82133, 82141, - 82147, 82153, 82160, 82167, 82174, 82181, 82188, 82195, 82202, 82209, - 82216, 82224, 82232, 82240, 82248, 82256, 82262, 82270, 82276, 82284, - 82293, 82301, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82307, 82311, 82315, 82319, - 82323, 82327, 0, 0, 82331, 82335, 82339, 82343, 82347, 82351, 0, 0, - 82355, 82359, 82363, 82367, 82371, 82375, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 82379, 82383, 82387, 82391, 82395, 82399, 82403, 0, 82407, 82411, 82415, - 82419, 82423, 82427, 82431, 0, 82435, 82442, 82448, 82454, 82460, 82468, - 82475, 82484, 82496, 82506, 82515, 82523, 82531, 82539, 82545, 82553, - 82561, 82568, 82576, 82586, 82593, 82602, 82608, 82618, 82627, 82632, - 82640, 82649, 82654, 82663, 82670, 82680, 82692, 82697, 82703, 82710, - 82715, 82725, 82735, 82745, 82755, 82770, 82783, 82794, 82802, 82807, - 82819, 82828, 82835, 82842, 82848, 82855, 82860, 82867, 82873, 82884, - 82895, 82905, 82911, 82916, 0, 0, 0, 0, 82921, 82925, 82929, 82933, - 82937, 82941, 82946, 82951, 82955, 82960, 82965, 82970, 82975, 82980, - 82984, 82989, 82994, 82999, 83004, 83009, 83013, 83018, 83023, 83028, - 83033, 83038, 83042, 83047, 83052, 83057, 83062, 83066, 83071, 83076, - 83081, 83086, 83091, 83096, 83101, 83106, 83111, 83116, 83121, 83126, - 83131, 83135, 83140, 83145, 83150, 83155, 83160, 83165, 83170, 83175, - 83180, 83185, 83190, 83195, 83200, 83205, 83210, 83215, 83220, 83225, - 83230, 83235, 83240, 83245, 83250, 83255, 83260, 83265, 83270, 83275, - 83280, 83285, 83290, 83295, 83300, 83305, 83309, 83316, 83323, 83330, - 83337, 83343, 83349, 83356, 83363, 83370, 83377, 83384, 83391, 83398, - 83405, 83412, 83418, 83425, 83432, 83439, 83446, 83453, 83460, 83467, - 83474, 83481, 83488, 83495, 83504, 83513, 83522, 83531, 83540, 83549, - 83558, 83567, 83575, 83583, 83591, 83599, 83607, 83615, 83623, 83631, - 83637, 83645, 0, 0, 83653, 83660, 83666, 83672, 83678, 83684, 83690, - 83696, 83702, 83708, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83714, 83719, 83724, 83729, 83734, - 83739, 83744, 83749, 83754, 83759, 83764, 83769, 83774, 83779, 83784, - 83789, 83794, 83799, 83804, 83809, 83814, 83819, 83824, 0, 0, 0, 0, - 83829, 83833, 83837, 83841, 83845, 83849, 83853, 83857, 83861, 83865, - 83869, 83873, 83877, 83881, 83885, 83889, 83893, 83897, 83901, 83905, - 83909, 83913, 83917, 83921, 83925, 83929, 83933, 83937, 83941, 83945, - 83949, 83953, 83957, 83961, 83965, 83969, 83973, 83977, 83981, 83985, - 83989, 83993, 83997, 84001, 84005, 84009, 84013, 84017, 84021, 0, 0, 0, - 0, 84025, 84029, 84033, 84037, 84041, 84045, 84049, 84053, 84057, 84061, - 84065, 84069, 84073, 84077, 84081, 84085, 84089, 84093, 84097, 84101, - 84105, 84109, 84113, 84117, 84121, 84125, 84129, 84133, 84137, 84141, - 84145, 84149, 84153, 84157, 84161, 84165, 84169, 84173, 84177, 84181, - 84185, 84189, 84193, 84197, 84201, 84205, 84209, 84213, 84217, 84221, - 84225, 84229, 84233, 84237, 84241, 84245, 84249, 84253, 84257, 84261, - 84265, 84269, 84273, 84277, 84281, 84285, 84289, 84293, 84297, 84301, - 84305, 84309, 84313, 84317, 84321, 84325, 84329, 84333, 84337, 84341, - 84345, 84349, 84353, 84357, 84361, 84365, 84369, 84373, 84377, 84381, - 84385, 84389, 84393, 84397, 84401, 84405, 84409, 84413, 84417, 84421, - 84425, 84429, 84433, 84437, 84441, 84445, 84449, 84453, 84457, 84461, - 84465, 84469, 84473, 84477, 84481, 84485, 84489, 84493, 84497, 84501, - 84505, 84509, 84513, 84517, 84521, 84525, 84529, 84533, 84537, 84541, - 84545, 84549, 84553, 84557, 84561, 84565, 84569, 84573, 84577, 84581, - 84585, 84589, 84593, 84597, 84601, 84605, 84609, 84613, 84617, 84621, - 84625, 84629, 84633, 84637, 84641, 84645, 84649, 84653, 84657, 84661, - 84665, 84669, 84673, 84677, 84681, 84685, 84689, 84693, 84697, 84701, - 84705, 84709, 84713, 84717, 84721, 84725, 84729, 84733, 84737, 84741, - 84745, 84749, 84753, 84757, 84761, 84765, 84769, 84773, 84777, 84781, - 84785, 84789, 84793, 84797, 84801, 84805, 84809, 84813, 84817, 84821, - 84825, 84829, 84833, 84837, 84841, 84845, 84849, 84853, 84857, 84861, - 84865, 84869, 84873, 84877, 84881, 84885, 84889, 84893, 84897, 84901, - 84905, 84909, 84913, 84917, 84921, 84925, 84929, 84933, 84937, 84941, - 84945, 84949, 84953, 84957, 84961, 84965, 84969, 84973, 84977, 84981, - 84985, 84989, 84993, 84997, 85001, 85005, 85009, 85013, 85017, 85021, - 85025, 85029, 85033, 85037, 85041, 85045, 85049, 85053, 85057, 85061, - 85065, 85069, 85073, 85077, 85081, 85085, 85089, 85093, 85097, 85101, - 85105, 85109, 85113, 85117, 85121, 85125, 85129, 85133, 85137, 85141, - 85145, 85149, 85153, 85157, 85161, 85165, 85169, 85173, 85177, 85181, - 85185, 85189, 85193, 85197, 85201, 85205, 85209, 85213, 85217, 85221, - 85225, 85229, 85233, 85237, 85241, 85245, 85249, 85253, 85257, 85261, - 85265, 85269, 85273, 85277, 85281, 85285, 85289, 85293, 85297, 85301, - 85305, 85309, 85313, 85317, 85321, 85325, 85329, 85333, 85337, 85341, - 85345, 85349, 85353, 85357, 85361, 85365, 85369, 85373, 85377, 85381, - 85385, 85389, 85393, 85397, 85401, 85405, 85409, 85413, 85417, 85421, - 85425, 85429, 85433, 85437, 85441, 85445, 85449, 85453, 85457, 85461, - 85465, 85469, 85473, 85477, 85481, 85485, 0, 0, 85489, 85493, 85497, - 85501, 85505, 85509, 85513, 85517, 85521, 85525, 85529, 85533, 85537, - 85541, 85545, 85549, 85553, 85557, 85561, 85565, 85569, 85573, 85577, - 85581, 85585, 85589, 85593, 85597, 85601, 85605, 85609, 85613, 85617, - 85621, 85625, 85629, 85633, 85637, 85641, 85645, 85649, 85653, 85657, - 85661, 85665, 85669, 85673, 85677, 85681, 85685, 85689, 85693, 85697, - 85701, 85705, 85709, 85713, 85717, 85721, 85725, 85729, 85733, 85737, - 85741, 85745, 85749, 85753, 85757, 85761, 85765, 85769, 85773, 85777, - 85781, 85785, 85789, 85793, 85797, 85801, 85805, 85809, 85813, 85817, - 85821, 85825, 85829, 85833, 85837, 85841, 85845, 85849, 85853, 85857, - 85861, 85865, 85869, 85873, 85877, 85881, 85885, 85889, 85893, 85897, - 85901, 85905, 85909, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85913, - 85918, 85923, 85928, 85933, 85938, 85946, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 85951, 85959, 85967, 85975, 85983, 0, 0, 0, 0, 0, 85991, 85998, - 86005, 86015, 86021, 86027, 86033, 86039, 86045, 86051, 86058, 86064, - 86070, 86076, 86085, 86094, 86106, 86118, 86124, 86130, 86136, 86143, - 86150, 86157, 86164, 86171, 0, 86178, 86185, 86192, 86200, 86207, 0, - 86214, 0, 86221, 86228, 0, 86235, 86243, 0, 86250, 86257, 86264, 86271, - 86278, 86285, 86292, 86299, 86306, 86313, 86318, 86325, 86332, 86338, - 86344, 86350, 86357, 86363, 86369, 86375, 86382, 86388, 86394, 86400, - 86407, 86413, 86419, 86425, 86432, 86438, 86444, 86450, 86457, 86463, - 86469, 86475, 86482, 86488, 86494, 86500, 86507, 86513, 86519, 86525, - 86532, 86538, 86544, 86550, 86557, 86563, 86569, 86575, 86582, 86588, - 86594, 86600, 86607, 86613, 86619, 86625, 86632, 86638, 86644, 86650, - 86656, 86662, 86668, 86674, 86680, 86686, 86692, 86698, 86704, 86710, - 86716, 86722, 86729, 86735, 86741, 86747, 86754, 86760, 86766, 86772, - 86779, 86785, 86791, 86797, 86804, 86812, 86820, 86826, 86832, 86838, - 86845, 86854, 86863, 86871, 86879, 86887, 86896, 86904, 86912, 86920, - 86929, 86936, 86943, 86954, 86965, 86969, 86973, 86978, 86983, 86988, - 86993, 87002, 87011, 87017, 87023, 87030, 87037, 87044, 87048, 87054, - 87060, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87065, 87071, - 87077, 87083, 87090, 87095, 87100, 87106, 87112, 87118, 87124, 87133, - 87139, 87145, 87153, 87161, 87169, 87177, 87183, 87189, 87195, 87202, - 87215, 87229, 87240, 87251, 87263, 87275, 87287, 87299, 87310, 87321, - 87333, 87345, 87357, 87369, 87381, 87393, 87405, 87422, 87439, 87456, - 87463, 87470, 87477, 87485, 87497, 87508, 87519, 87532, 87543, 87552, - 87560, 87569, 87577, 87587, 87595, 87604, 87612, 87621, 87629, 87639, - 87647, 87656, 87664, 87674, 87682, 87690, 87698, 87706, 87713, 87722, - 87730, 87738, 87747, 87755, 87764, 87772, 87780, 87788, 87797, 87805, - 87814, 87822, 87830, 87838, 87846, 87855, 87863, 87872, 87880, 87889, - 87897, 87906, 87914, 87924, 87932, 87940, 87948, 87958, 87966, 87974, - 87983, 87991, 88000, 88009, 88017, 88027, 88035, 88044, 88052, 88061, - 88069, 88079, 88087, 88095, 88102, 88110, 88117, 88126, 88133, 88142, - 88150, 88159, 88167, 88177, 88185, 88194, 88202, 88212, 88220, 88228, - 88235, 88243, 88250, 88259, 88266, 88276, 88286, 88297, 88306, 88315, - 88324, 88333, 88342, 88352, 88364, 88376, 88387, 88399, 88412, 88423, - 88432, 88441, 88449, 88458, 88468, 88476, 88485, 88494, 88502, 88511, - 88521, 88529, 88538, 88547, 88555, 88564, 88574, 88582, 88592, 88600, - 88610, 88618, 88626, 88635, 88643, 88653, 88661, 88669, 88679, 88687, - 88694, 88701, 88710, 88719, 88727, 88736, 88746, 88754, 88765, 88773, - 88781, 88788, 88796, 88805, 88812, 88824, 88835, 88847, 88858, 88870, - 88879, 88887, 88896, 88904, 88913, 88922, 88930, 88939, 88947, 88956, - 88964, 88972, 88980, 88988, 88995, 89004, 89012, 89021, 89029, 89038, - 89046, 89054, 89063, 89071, 89080, 89088, 89097, 89105, 89113, 89121, - 89130, 89138, 89147, 89155, 89164, 89172, 89181, 89189, 89197, 89205, - 89214, 89222, 89231, 89240, 89248, 89257, 89265, 89274, 89282, 89291, - 89299, 89306, 89314, 89321, 89330, 89338, 89347, 89355, 89364, 89373, - 89381, 89391, 89399, 89406, 89414, 89421, 89429, 89441, 89454, 89463, - 89473, 89482, 89492, 89501, 89511, 89520, 89530, 89539, 89549, 89559, - 89568, 89577, 89586, 89596, 89604, 89613, 89623, 89633, 89643, 89653, - 89661, 89671, 89679, 89689, 89697, 89707, 89715, 89725, 89733, 89742, - 89749, 89759, 89767, 89777, 89785, 89795, 89803, 89813, 89821, 89830, - 89838, 89847, 89855, 89864, 89873, 89882, 89891, 89901, 89909, 89919, - 89927, 89937, 89945, 89955, 89963, 89973, 89981, 89990, 89997, 90007, - 90015, 90025, 90033, 90043, 90051, 90061, 90069, 90078, 90086, 90095, - 90103, 90112, 90121, 90130, 90139, 90148, 90156, 90165, 90173, 90182, - 90191, 90199, 90209, 90218, 90228, 90238, 90247, 90257, 90266, 90275, - 90283, 90291, 90296, 90301, 90307, 90315, 90323, 90331, 90339, 90347, - 90355, 90361, 90367, 90373, 90381, 90387, 90397, 90403, 90409, 90415, - 90426, 90437, 90448, 90458, 90469, 90480, 90490, 90501, 90511, 90521, - 90530, 90541, 90552, 90563, 90576, 90586, 90596, 90607, 90617, 90627, - 90637, 90647, 90657, 90667, 90677, 90688, 90699, 90710, 90720, 90730, - 90742, 90753, 90764, 90774, 90784, 90794, 90804, 90815, 90825, 90835, - 90847, 90857, 90867, 90879, 90890, 90901, 90911, 90921, 90931, 90941, - 90953, 90965, 90977, 90988, 90999, 91009, 91019, 91029, 91038, 91047, - 91057, 91067, 91078, 0, 0, 91088, 91099, 91110, 91120, 91130, 91142, - 91153, 91164, 91177, 91187, 91199, 91208, 91217, 91228, 91239, 91252, - 91263, 91276, 91286, 91298, 91308, 91320, 91332, 91345, 91355, 91365, - 91375, 91386, 91396, 91405, 91415, 91424, 91433, 91443, 91453, 91463, - 91473, 91483, 91493, 91504, 91514, 91525, 91535, 91546, 91557, 91567, - 91577, 91587, 91597, 91607, 91617, 91628, 91638, 91649, 0, 0, 0, 0, 0, 0, - 0, 91660, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 91666, 91681, 91696, 91702, 91708, - 91714, 91720, 91726, 91732, 91738, 91744, 91752, 91756, 91759, 91767, - 91775, 91783, 91786, 91789, 91792, 91795, 91798, 91801, 91804, 91807, - 91810, 91813, 91816, 91819, 91822, 91825, 91828, 91831, 91839, 91848, - 91859, 91867, 91875, 91884, 91893, 91905, 91917, 0, 0, 0, 0, 0, 0, 91927, - 91932, 91937, 91944, 91951, 91957, 91963, 91968, 91973, 91978, 91984, - 91990, 91996, 92002, 92008, 92015, 92022, 92032, 92042, 92052, 92061, - 92072, 92081, 92090, 92101, 92112, 92125, 92138, 92150, 92162, 92174, - 92186, 92197, 92208, 92219, 92230, 92242, 92254, 92258, 92263, 92273, - 92283, 92287, 92291, 92295, 92300, 92305, 92310, 92315, 92318, 92322, 0, - 92327, 92330, 92333, 92337, 92341, 92346, 92350, 92354, 92360, 92366, - 92374, 92382, 92385, 92388, 92391, 92394, 92397, 92401, 92405, 0, 92409, - 92414, 92418, 92422, 0, 0, 0, 0, 92427, 92432, 92439, 92444, 92449, 0, - 92454, 92459, 92465, 92470, 92476, 92481, 92487, 92492, 92498, 92503, - 92509, 92515, 92524, 92533, 92542, 92551, 92561, 92571, 92581, 92591, - 92600, 92609, 92618, 92628, 92633, 92638, 92644, 92650, 92656, 92663, - 92671, 92679, 92685, 92691, 92697, 92704, 92710, 92716, 92722, 92729, - 92735, 92741, 92747, 92754, 92759, 92764, 92769, 92775, 92781, 92787, - 92793, 92800, 92806, 92812, 92818, 92824, 92830, 92836, 92842, 92848, - 92854, 92860, 92866, 92873, 92879, 92885, 92891, 92898, 92904, 92910, - 92916, 92923, 92929, 92935, 92941, 92948, 92954, 92960, 92966, 92973, - 92979, 92985, 92991, 92998, 93004, 93010, 93016, 93023, 93029, 93035, - 93041, 93048, 93054, 93060, 93066, 93073, 93079, 93085, 93091, 93098, - 93104, 93110, 93116, 93123, 93129, 93135, 93141, 93148, 93153, 93158, - 93163, 93169, 93175, 93181, 93187, 93194, 93200, 93206, 93212, 93219, - 93225, 93231, 93238, 93245, 93250, 93255, 93260, 93266, 93278, 93290, - 93302, 93314, 93327, 93340, 93348, 0, 0, 93356, 0, 93364, 93369, 93374, - 93378, 93383, 93388, 93392, 93396, 93401, 93406, 93410, 93414, 93418, - 93422, 93428, 93432, 93437, 93441, 93445, 93449, 93453, 93457, 93461, - 93465, 93469, 93473, 93477, 93481, 93486, 93491, 93496, 93501, 93507, - 93513, 93520, 93527, 93534, 93540, 93547, 93554, 93561, 93567, 93574, - 93581, 93587, 93594, 93601, 93607, 93614, 93621, 93627, 93634, 93641, - 93647, 93654, 93661, 93668, 93675, 93682, 93688, 93694, 93700, 93706, - 93711, 93717, 93723, 93730, 93737, 93744, 93750, 93757, 93764, 93771, - 93777, 93784, 93791, 93797, 93804, 93811, 93817, 93824, 93831, 93837, - 93844, 93851, 93857, 93864, 93871, 93878, 93885, 93892, 93899, 93904, - 93911, 93915, 93921, 93927, 93933, 93939, 93945, 93949, 93954, 93959, - 93964, 93969, 93974, 93979, 93984, 93989, 93995, 94001, 94007, 94015, - 94019, 94023, 94027, 94031, 94035, 94039, 94044, 94049, 94054, 94059, - 94063, 94068, 94073, 94078, 94083, 94088, 94093, 94098, 94103, 94107, - 94111, 94116, 94121, 94126, 94131, 94135, 94140, 94145, 94150, 94155, - 94159, 94164, 94169, 94174, 94179, 94183, 94188, 94193, 94197, 94202, - 94207, 94212, 94217, 94222, 94227, 94234, 94241, 94245, 94250, 94255, - 94260, 94265, 94270, 94275, 94280, 94285, 94290, 94295, 94300, 94305, - 94310, 94315, 94320, 94325, 94330, 94335, 94340, 94345, 94350, 94355, - 94360, 94365, 94370, 94375, 94380, 94385, 94390, 0, 0, 0, 94395, 94399, - 94404, 94408, 94413, 94418, 0, 0, 94422, 94427, 94432, 94436, 94441, - 94446, 0, 0, 94451, 94456, 94460, 94465, 94470, 94475, 0, 0, 94480, - 94485, 94490, 0, 0, 0, 94494, 94499, 94504, 94509, 94513, 94518, 94523, - 0, 94528, 94534, 94537, 94541, 94544, 94548, 94552, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 94556, 94562, 94568, 94574, 94580, 0, 0, 94584, 94590, 94596, - 94602, 94608, 94614, 94621, 94628, 94635, 94642, 94649, 94656, 0, 94663, - 94670, 94677, 94683, 94690, 94697, 94704, 94711, 94717, 94724, 94731, - 94738, 94745, 94751, 94758, 94765, 94772, 94779, 94785, 94792, 94799, - 94806, 94813, 94820, 94827, 94834, 0, 94841, 94847, 94854, 94861, 94868, - 94875, 94881, 94888, 94895, 94902, 94909, 94916, 94923, 94930, 94936, - 94943, 94950, 94957, 94964, 0, 94971, 94978, 0, 94985, 94992, 94999, - 95006, 95013, 95020, 95027, 95034, 95041, 95048, 95055, 95062, 95069, - 95076, 95083, 0, 0, 95089, 95094, 95099, 95104, 95109, 95114, 95119, - 95124, 95129, 95134, 95139, 95144, 95149, 95154, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 95159, 95166, 95173, 95180, 95187, 95194, 95201, 95208, 95215, - 95222, 95229, 95236, 95243, 95250, 95257, 95264, 95271, 95278, 95285, - 95292, 95300, 95308, 95315, 95322, 95327, 95335, 95343, 95350, 95357, - 95362, 95369, 95374, 95379, 95386, 95391, 95396, 95401, 95409, 95414, - 95419, 95426, 95431, 95436, 95443, 95450, 95455, 95460, 95465, 95470, - 95475, 95480, 95485, 95490, 95495, 95502, 95507, 95514, 95519, 95524, - 95529, 95534, 95539, 95544, 95549, 95554, 95559, 95564, 95569, 95576, - 95583, 95590, 95597, 95603, 95608, 95615, 95620, 95625, 95634, 95641, - 95650, 95657, 95662, 95667, 95675, 95680, 95685, 95690, 95695, 95700, - 95707, 95712, 95717, 95722, 95727, 95732, 95739, 95746, 95753, 95760, - 95767, 95774, 95781, 95788, 95795, 95802, 95809, 95816, 95823, 95830, - 95837, 95844, 95851, 95858, 95865, 95872, 95879, 95886, 95893, 95900, - 95907, 95914, 95921, 95928, 0, 0, 0, 0, 0, 95935, 95943, 95951, 0, 0, 0, - 0, 95956, 95960, 95964, 95968, 95972, 95976, 95980, 95984, 95988, 95992, - 95997, 96002, 96007, 96012, 96017, 96022, 96027, 96032, 96037, 96043, - 96049, 96055, 96062, 96069, 96076, 96083, 96090, 96097, 96102, 96107, - 96112, 96118, 96124, 96130, 96136, 96142, 96148, 96154, 96160, 96166, - 96172, 96178, 96184, 96190, 96196, 0, 0, 0, 96202, 96210, 96218, 96226, - 96234, 96242, 96252, 96262, 96270, 96278, 96286, 96294, 96302, 96308, - 96315, 96324, 96332, 96340, 96349, 96358, 96367, 96377, 96388, 96398, - 96409, 96418, 96427, 96436, 96446, 96457, 96467, 96478, 96489, 96498, - 96506, 96512, 96518, 96524, 96530, 96538, 96546, 96552, 96559, 96569, - 96576, 96583, 96590, 96597, 96604, 96614, 96621, 96628, 96636, 96644, - 96653, 96662, 96671, 96680, 96689, 96696, 96704, 96713, 96722, 96726, - 96733, 96738, 96743, 96747, 96751, 96755, 96759, 96764, 96769, 96775, - 96781, 96785, 96791, 96795, 96799, 96803, 96807, 96811, 96815, 96821, - 96825, 96830, 96834, 96838, 0, 96841, 96846, 96851, 96856, 96861, 96868, - 96873, 96878, 96883, 96888, 96893, 96898, 96903, 0, 0, 0, 96906, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96912, 96919, - 96928, 96937, 96944, 96951, 96958, 96965, 96972, 96979, 96985, 96992, - 96999, 97006, 97013, 97020, 97027, 97034, 97041, 97050, 97057, 97064, - 97071, 97078, 97085, 97092, 97099, 97106, 97115, 97122, 97129, 97136, - 97143, 97150, 97157, 97166, 97173, 97180, 97187, 97194, 97203, 97210, - 97217, 97224, 97232, 97241, 0, 0, 97250, 97254, 97258, 97263, 97268, - 97273, 97278, 97282, 97287, 97292, 97297, 97302, 97307, 97312, 97316, - 97321, 97326, 97331, 97336, 97340, 97345, 97350, 97354, 97359, 97364, - 97369, 97374, 97379, 97384, 0, 0, 0, 97389, 97393, 97398, 97403, 97407, - 97412, 97416, 97421, 97426, 97431, 97436, 97441, 97445, 97450, 97455, - 97460, 97465, 97470, 97475, 97479, 97484, 97489, 97494, 97499, 97504, - 97509, 97513, 97517, 97522, 97527, 97532, 97537, 97542, 97547, 97552, - 97557, 97562, 97567, 97572, 97577, 97582, 97587, 97592, 97597, 97602, - 97607, 97612, 97617, 97622, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 97627, 97633, 97638, 97643, 97648, 97653, 97658, 97663, 97668, 97673, - 97678, 97684, 97690, 97696, 97702, 97708, 97714, 97720, 97726, 97732, - 97739, 97746, 97753, 97761, 97769, 97777, 97785, 97793, 0, 0, 0, 0, - 97801, 97805, 97810, 97815, 97820, 97824, 97829, 97834, 97839, 97844, - 97848, 97852, 97857, 97862, 97867, 97872, 97876, 97881, 97886, 97891, - 97896, 97901, 97906, 97910, 97915, 97920, 97925, 97930, 97935, 97940, - 97945, 97950, 97955, 97960, 97965, 97971, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 97977, 97982, 97989, 97996, 98001, 98006, 98011, 98016, 98021, 98026, - 98031, 98036, 98041, 98046, 98051, 98056, 98061, 98066, 98071, 98076, - 98081, 98086, 98091, 98096, 98101, 98106, 98111, 98116, 98121, 98126, 0, - 0, 0, 0, 0, 98133, 98139, 98145, 98151, 98157, 98162, 98168, 98174, - 98180, 98186, 98191, 98197, 98203, 98209, 98215, 98221, 98227, 98233, - 98239, 98245, 98250, 98256, 98262, 98268, 98274, 98280, 98285, 98291, - 98297, 98302, 98308, 98314, 98320, 98326, 98332, 98338, 98344, 98349, - 98355, 98362, 98369, 98376, 98383, 0, 0, 0, 0, 0, 98390, 98395, 98400, - 98405, 98410, 98415, 98420, 98425, 98430, 98435, 98440, 98445, 98450, - 98455, 98460, 98465, 98470, 98475, 98480, 98485, 98490, 98495, 98500, - 98505, 98510, 98515, 98520, 98524, 98528, 98532, 0, 98537, 98543, 98548, - 98553, 98558, 98563, 98569, 98575, 98581, 98587, 98593, 98599, 98605, - 98611, 98617, 98623, 98629, 98635, 98641, 98646, 98652, 98658, 98663, - 98669, 98674, 98680, 98686, 98691, 98697, 98703, 98708, 98714, 98719, - 98724, 98730, 98736, 98742, 0, 0, 0, 0, 98747, 98753, 98759, 98765, - 98771, 98777, 98783, 98789, 98795, 98802, 98807, 98812, 98818, 98824, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98830, 98836, 98842, - 98848, 98855, 98861, 98868, 98875, 98882, 98889, 98897, 98904, 98912, - 98918, 98924, 98930, 98936, 98942, 98948, 98954, 98960, 98966, 98972, - 98978, 98984, 98990, 98996, 99002, 99008, 99014, 99020, 99026, 99032, - 99038, 99044, 99050, 99056, 99062, 99068, 99074, 99080, 99086, 99092, - 99098, 99105, 99111, 99118, 99125, 99132, 99139, 99147, 99154, 99162, - 99168, 99174, 99180, 99186, 99192, 99198, 99204, 99210, 99216, 99222, - 99228, 99234, 99240, 99246, 99252, 99258, 99264, 99270, 99276, 99282, - 99288, 99294, 99300, 99306, 99312, 99318, 99324, 99330, 99335, 99340, - 99345, 99350, 99355, 99360, 99365, 99370, 99375, 99380, 99385, 99390, - 99395, 99400, 99405, 99410, 99415, 99420, 99425, 99430, 99435, 99440, - 99445, 99450, 99455, 99460, 99465, 99470, 99475, 99480, 99485, 99490, - 99495, 99500, 99505, 99510, 99515, 99520, 99525, 99530, 99535, 99540, - 99545, 99550, 99555, 99560, 99565, 99570, 99575, 99580, 99585, 99590, - 99595, 99600, 99605, 99609, 99613, 99618, 99623, 99628, 99633, 99638, - 99643, 99648, 99653, 99658, 99663, 99668, 99672, 99676, 99680, 99684, - 99688, 99692, 99696, 99701, 99706, 0, 0, 99711, 99716, 99720, 99724, - 99728, 99732, 99736, 99740, 99744, 99748, 0, 0, 0, 0, 0, 0, 99752, 99757, - 99763, 99769, 99775, 99781, 99787, 99793, 99798, 99804, 99809, 99815, - 99820, 99825, 99831, 99837, 99842, 99847, 99852, 99857, 99863, 99868, - 99874, 99879, 99885, 99891, 99897, 99903, 99909, 99915, 99921, 99926, - 99932, 99938, 99944, 99950, 0, 0, 0, 0, 99956, 99961, 99967, 99973, - 99979, 99985, 99991, 99997, 100002, 100008, 100013, 100019, 100024, - 100029, 100035, 100041, 100046, 100051, 100056, 100061, 100067, 100072, - 100078, 100083, 100089, 100095, 100101, 100107, 100113, 100119, 100125, - 100130, 100136, 100142, 100148, 100154, 0, 0, 0, 0, 100160, 100164, - 100169, 100174, 100179, 100184, 100189, 100194, 100199, 100203, 100208, - 100213, 100218, 100223, 100227, 100232, 100237, 100242, 100247, 100252, - 100257, 100261, 100266, 100270, 100275, 100280, 100285, 100290, 100295, - 100300, 100305, 100310, 100314, 100319, 100324, 100329, 100334, 100339, - 100344, 100349, 0, 0, 0, 0, 0, 0, 0, 0, 100354, 100361, 100368, 100375, - 100382, 100389, 100396, 100403, 100410, 100417, 100424, 100431, 100438, - 100445, 100452, 100459, 100466, 100473, 100480, 100487, 100494, 100501, - 100508, 100515, 100522, 100529, 100536, 100543, 100550, 100557, 100564, - 100571, 100578, 100585, 100592, 100599, 100606, 100613, 100620, 100627, - 100634, 100641, 100648, 100655, 100662, 100669, 100676, 100683, 100690, - 100697, 100704, 100711, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100718, 100725, - 100730, 100736, 100742, 100748, 100754, 100760, 100766, 100772, 100777, - 100783, 0, 100789, 100794, 100800, 100805, 100811, 100817, 100822, - 100827, 100833, 100839, 100845, 100851, 100856, 100862, 100868, 0, - 100874, 100880, 100886, 100892, 100898, 100903, 100909, 0, 100915, - 100921, 0, 100927, 100932, 100938, 100944, 100950, 100956, 100962, - 100968, 100974, 100979, 100985, 0, 100991, 100996, 101002, 101007, - 101013, 101019, 101024, 101029, 101035, 101041, 101047, 101053, 101058, - 101064, 101070, 0, 101076, 101082, 101088, 101094, 101100, 101105, - 101111, 0, 101117, 101123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 101129, 101134, 101139, 101144, 101149, 101154, 101159, - 101164, 101169, 101174, 101179, 101184, 101189, 101194, 101199, 101204, - 101209, 101214, 101219, 101224, 101229, 101234, 101239, 101244, 101249, - 101254, 101259, 101264, 101269, 101274, 101279, 101284, 101289, 101294, - 101299, 101304, 101309, 101314, 101319, 101324, 101329, 101334, 101339, - 101344, 101349, 101354, 101359, 101364, 101369, 101374, 101379, 101384, - 101389, 101394, 101399, 101404, 101409, 101414, 101419, 101424, 101429, - 101434, 101439, 101444, 101449, 101454, 101459, 101464, 101469, 101474, - 101479, 101484, 101489, 101494, 101499, 101504, 101509, 101514, 101519, - 101524, 101529, 101534, 101539, 101544, 101549, 101554, 101559, 101564, - 101569, 101574, 101579, 101584, 101589, 101594, 101599, 101604, 101609, - 101614, 101619, 101624, 101629, 101634, 101639, 101644, 101649, 101654, - 101659, 101664, 101669, 101674, 101679, 101684, 101689, 101694, 101699, - 101704, 101709, 101714, 101719, 101724, 101729, 101734, 101739, 101744, - 101749, 101754, 101759, 101764, 101769, 101774, 101779, 101784, 101789, - 101794, 101799, 101804, 101809, 101814, 101819, 101824, 101829, 101834, - 101839, 101844, 101849, 101854, 101859, 101864, 101869, 101874, 101879, - 101884, 101889, 101894, 101899, 101904, 101909, 101914, 101919, 101924, - 101929, 101934, 101939, 101944, 101949, 101954, 101959, 101964, 101969, - 101974, 101979, 101984, 101989, 101994, 101999, 102004, 102009, 102014, - 102019, 102024, 102029, 102034, 102039, 102044, 102049, 102054, 102059, - 102064, 102069, 102074, 102079, 102084, 102089, 102094, 102099, 102104, - 102109, 102114, 102119, 102124, 102129, 102134, 102139, 102144, 102149, - 102154, 102159, 102164, 102169, 102174, 102179, 102184, 102189, 102194, - 102199, 102204, 102209, 102214, 102219, 102224, 102229, 102234, 102239, - 102244, 102249, 102254, 102259, 102264, 102269, 102274, 102279, 102284, - 102289, 102294, 102299, 102304, 102309, 102314, 102319, 102324, 102329, - 102334, 102339, 102344, 102349, 102354, 102359, 102364, 102369, 102374, - 102379, 102384, 102389, 102394, 102399, 102404, 102409, 102414, 102419, - 102424, 102429, 102434, 102439, 102444, 102449, 102454, 102459, 102464, - 102469, 102474, 102479, 102484, 102489, 102494, 102499, 102504, 102509, - 102514, 102519, 102524, 102529, 102534, 102539, 102544, 102549, 102554, - 102559, 102564, 102569, 102574, 102579, 102584, 102589, 102594, 102599, - 102604, 102609, 102614, 102619, 102624, 102629, 102634, 102639, 102644, - 102649, 102654, 102659, 102664, 102669, 102674, 102679, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 102684, 102690, 102697, 102704, 102710, 102717, 102724, 102731, - 102738, 102744, 102751, 102758, 102765, 102772, 102779, 102786, 102793, - 102800, 102807, 102814, 102821, 102828, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 102835, 102840, 102845, 102850, 102855, 102860, 102865, 102870, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102875, - 102881, 102889, 102898, 102903, 102909, 0, 102915, 102922, 102933, - 102943, 102950, 102958, 102965, 102976, 102982, 102992, 102999, 103006, - 103012, 103019, 103027, 103034, 103040, 103047, 103059, 103066, 103073, - 103081, 103090, 103103, 103108, 103117, 103123, 103132, 103138, 103144, - 103151, 103156, 103166, 103180, 103188, 103196, 103201, 103211, 103218, - 103229, 103236, 103245, 0, 103253, 103259, 103267, 103277, 103283, - 103289, 103295, 103301, 103311, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 103319, 103323, 103327, 103331, 103335, 103339, 0, - 0, 103344, 0, 103349, 103353, 103358, 103363, 103368, 103373, 103377, - 103382, 103387, 103392, 103397, 103401, 103406, 103411, 103416, 103421, - 103425, 103430, 103435, 103440, 103445, 103449, 103454, 103459, 103464, - 103469, 103473, 103478, 103483, 103488, 103493, 103497, 103502, 103507, - 103512, 103517, 103522, 103527, 103532, 103536, 103541, 103546, 103551, - 103556, 0, 103561, 103566, 0, 0, 0, 103571, 0, 0, 103576, 103581, 103588, - 103595, 103602, 103609, 103616, 103623, 103630, 103637, 103644, 103651, - 103658, 103665, 103672, 103679, 103686, 103693, 103700, 103707, 103714, - 103721, 103728, 0, 103735, 103742, 103748, 103754, 103760, 103767, - 103774, 103782, 103789, 103797, 103802, 103807, 103812, 103817, 103822, - 103827, 103832, 103837, 103842, 103847, 103852, 103857, 103862, 103868, - 103873, 103878, 103883, 103888, 103893, 103898, 103903, 103908, 103913, - 103919, 103925, 103929, 103933, 103937, 103941, 103945, 103950, 103955, - 103961, 103966, 103972, 103977, 103982, 103987, 103993, 103998, 104003, - 104008, 104013, 104018, 104024, 104029, 104035, 104040, 104046, 104051, - 104057, 104062, 104068, 104073, 104078, 104083, 104088, 104093, 104098, - 104103, 104109, 104114, 0, 0, 0, 0, 0, 0, 0, 0, 104119, 104123, 104127, - 104131, 104135, 104141, 104145, 104150, 104155, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 104161, 104166, 104171, - 104176, 104181, 104186, 104191, 104196, 104201, 104206, 104211, 104216, - 104221, 104226, 104231, 104236, 104241, 104246, 104251, 0, 104256, - 104261, 0, 0, 0, 0, 0, 104266, 104270, 104274, 104279, 104284, 104290, - 104295, 104300, 104305, 104310, 104315, 104320, 104325, 104330, 104335, - 104340, 104345, 104350, 104355, 104360, 104365, 104370, 104375, 104380, - 104385, 104390, 104395, 104400, 104404, 104409, 104414, 104420, 104424, - 0, 0, 0, 104428, 104434, 104438, 104443, 104448, 104453, 104457, 104462, - 104466, 104471, 104476, 104480, 104485, 104490, 104494, 104498, 104503, - 104508, 104512, 104517, 104522, 104527, 104532, 104537, 104542, 104547, - 104552, 0, 0, 0, 0, 0, 104557, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 104562, 104567, 104572, 104577, 104582, 104587, 104593, 104599, - 104605, 104610, 104615, 104620, 104626, 104632, 104638, 104643, 104649, - 104654, 104660, 104666, 104671, 104677, 104683, 104688, 104694, 104700, - 104706, 104712, 104718, 104723, 104729, 104735, 104741, 104746, 104751, - 104756, 104761, 104766, 104772, 104778, 104783, 104788, 104793, 104799, - 104804, 104809, 104815, 104821, 104826, 104833, 104839, 104844, 104850, - 104856, 104862, 104867, 0, 0, 0, 0, 104873, 104882, 104890, 104897, - 104904, 104909, 104914, 104919, 104924, 104929, 104934, 104939, 104944, - 104949, 104955, 104961, 104967, 104973, 104979, 104985, 0, 0, 104991, - 104998, 105005, 105012, 105020, 105028, 105036, 105044, 105052, 105060, - 105066, 105072, 105078, 105085, 105092, 105099, 105106, 105113, 105120, - 105127, 105134, 105141, 105148, 105155, 105162, 105169, 105176, 105183, - 105191, 105199, 105207, 105216, 105225, 105234, 105243, 105252, 105261, - 105269, 105277, 105285, 105294, 105303, 105312, 105321, 105330, 105339, - 105348, 105352, 105357, 105362, 0, 105368, 105373, 0, 0, 0, 0, 0, 105378, - 105384, 105391, 105396, 105401, 105405, 105410, 105415, 0, 105420, - 105425, 105430, 0, 105435, 105440, 105445, 105450, 105455, 105460, - 105465, 105470, 105475, 105480, 105485, 105489, 105493, 105498, 105503, - 105508, 105512, 105516, 105520, 105524, 105529, 105534, 105539, 105543, - 105548, 105552, 105557, 105562, 105567, 0, 0, 105572, 105578, 105583, 0, - 0, 0, 0, 105588, 105592, 105596, 105600, 105604, 105608, 105613, 105618, - 105624, 105629, 0, 0, 0, 0, 0, 0, 0, 105636, 105642, 105649, 105655, - 105662, 105668, 105674, 105680, 105687, 0, 0, 0, 0, 0, 0, 0, 105693, - 105701, 105709, 105717, 105725, 105733, 105741, 105749, 105757, 105765, - 105773, 105781, 105789, 105797, 105805, 105813, 105821, 105829, 105837, - 105845, 105853, 105861, 105869, 105877, 105885, 105893, 105901, 105909, - 105917, 105925, 105932, 105940, 105948, 105955, 105962, 105969, 105976, - 105983, 105990, 105997, 106004, 106011, 106018, 106025, 106032, 106039, - 106046, 106053, 106060, 106067, 106074, 106081, 106088, 106095, 106102, - 106109, 106116, 106123, 106130, 106137, 106144, 106151, 106157, 106164, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 106171, 106176, 106181, 106186, 106191, 106196, - 106201, 106206, 106211, 106216, 106221, 106226, 106231, 106236, 106241, - 106246, 106251, 106256, 106261, 106266, 106271, 106276, 106281, 106286, - 106291, 106296, 106301, 106306, 106311, 106316, 106321, 106326, 106331, - 106336, 106341, 106346, 106351, 106356, 106362, 0, 0, 0, 0, 106368, - 106372, 106376, 106381, 106386, 106392, 106398, 106404, 106414, 106423, - 106429, 106436, 0, 0, 0, 0, 0, 0, 0, 0, 0, 106444, 106448, 106453, - 106458, 106463, 106468, 106473, 106478, 106483, 106487, 106492, 106496, - 106501, 106505, 106510, 106514, 106519, 106524, 106529, 106534, 106539, - 106544, 106549, 106554, 106559, 106564, 106569, 106574, 106579, 106584, - 106589, 106594, 106599, 106604, 106609, 106614, 106619, 106624, 106629, - 106634, 106639, 106644, 106649, 106654, 106659, 106664, 106669, 106674, - 106679, 106684, 106689, 106694, 106699, 106704, 0, 0, 0, 106709, 106714, - 106723, 106731, 106740, 106749, 106760, 106771, 106778, 106785, 106792, - 106799, 106806, 106813, 106820, 106827, 106834, 106841, 106848, 106855, - 106862, 106869, 106876, 106883, 106890, 106897, 106904, 106911, 106918, - 0, 0, 106925, 106931, 106937, 106943, 106949, 106956, 106963, 106971, - 106978, 106985, 106992, 106999, 107006, 107013, 107020, 107027, 107034, - 107041, 107048, 107055, 107062, 107069, 107076, 107083, 107090, 107097, - 107104, 0, 0, 0, 0, 0, 107111, 107117, 107123, 107129, 107135, 107142, - 107149, 107157, 107164, 107171, 107178, 107185, 107192, 107199, 107206, - 107213, 107220, 107227, 107234, 107241, 107248, 107255, 107262, 107269, - 107276, 107283, 0, 0, 0, 0, 0, 0, 0, 107290, 107297, 107305, 107315, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 107325, 107331, 107337, 107343, 107349, - 107356, 107363, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 107371, 107378, 107385, 107393, - 107400, 107407, 107414, 107421, 107429, 107437, 107445, 107453, 107461, - 107469, 107477, 107485, 107493, 107501, 107509, 107517, 107525, 107533, - 107541, 107549, 107557, 107565, 107573, 107581, 107589, 107597, 107605, - 107613, 107621, 107629, 107637, 107645, 107653, 107661, 107669, 107677, - 107685, 107693, 107701, 107709, 107717, 107725, 107733, 107741, 107749, - 107757, 107765, 107773, 107781, 107789, 107797, 107805, 107813, 107821, - 107829, 107837, 107845, 107853, 107861, 107869, 107877, 107885, 107893, - 107901, 107909, 107917, 107925, 107933, 107941, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 107949, 107954, 107960, 107966, 107972, 107978, 107984, 107990, 107996, - 108002, 108007, 108014, 108020, 108026, 108032, 108038, 108044, 108049, - 108055, 108061, 108067, 108073, 108079, 108085, 108091, 108097, 108103, - 108109, 108114, 108120, 108128, 108136, 108142, 108148, 108154, 108160, - 108168, 108174, 108180, 108186, 108192, 108198, 108204, 108209, 108215, - 108223, 108231, 108237, 108243, 108249, 108256, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 108262, 108267, 108273, 108279, 108285, 108291, 108297, - 108303, 108309, 108315, 108320, 108327, 108333, 108339, 108345, 108351, - 108357, 108362, 108368, 108374, 108380, 108386, 108392, 108398, 108404, - 108410, 108416, 108422, 108427, 108433, 108441, 108449, 108455, 108461, - 108467, 108473, 108481, 108487, 108493, 108499, 108505, 108511, 108517, - 108522, 108528, 108536, 108544, 108550, 108556, 108562, 108569, 0, 0, 0, - 0, 0, 0, 0, 108575, 108579, 108583, 108588, 108593, 108599, 108604, - 108610, 108617, 108623, 108630, 108637, 108644, 108651, 108657, 108664, - 108671, 108678, 108685, 108691, 108698, 108705, 108711, 108718, 108724, - 108731, 108737, 108743, 108749, 108756, 108765, 108771, 108779, 108786, - 108793, 108800, 108806, 108812, 108818, 108824, 108830, 108837, 108846, - 108853, 108860, 108867, 0, 0, 0, 0, 0, 0, 0, 0, 108874, 108881, 108887, - 108893, 108899, 108905, 108911, 108917, 108923, 108929, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 108935, 108939, 108943, - 108947, 108951, 108955, 108959, 108963, 108967, 108971, 108976, 108981, - 108986, 108991, 108996, 109001, 109006, 109011, 109016, 109022, 109028, - 109034, 109041, 109048, 109055, 109062, 109069, 109076, 109083, 109090, - 109097, 0, 109104, 109109, 109114, 109119, 109124, 109129, 109134, - 109139, 109144, 109149, 109154, 109159, 109164, 109169, 109173, 109178, - 109183, 109188, 109193, 109198, 109203, 109208, 109213, 109218, 109223, - 109228, 109233, 109238, 109246, 109251, 109256, 109261, 109266, 109271, - 109276, 109281, 109286, 109291, 109296, 109301, 109306, 109311, 0, - 109316, 109322, 109328, 0, 0, 109333, 109341, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 109350, 109357, - 109364, 109371, 109377, 109384, 109390, 109397, 109403, 109409, 109416, - 109422, 109428, 109434, 109440, 109446, 109452, 109458, 109464, 109471, - 109482, 109488, 109494, 109502, 109508, 109514, 109521, 109532, 109538, - 109544, 109550, 109557, 109568, 109573, 109578, 109583, 109588, 109593, - 109599, 109605, 109611, 109618, 109626, 0, 0, 0, 0, 0, 0, 0, 0, 109632, - 109637, 109642, 109647, 109652, 109657, 109662, 109667, 109672, 109677, - 109682, 109687, 109692, 109697, 109702, 109707, 109712, 109717, 109722, - 109727, 109732, 109737, 109743, 109748, 109754, 109759, 109765, 109771, - 109777, 109783, 109789, 109796, 109802, 109808, 109812, 109817, 109822, - 109828, 109836, 109847, 109856, 109866, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 109876, 109882, 109888, 109894, 109900, - 109906, 109913, 109919, 109925, 109931, 109937, 109943, 109949, 109955, - 109961, 109967, 109973, 109979, 109985, 109991, 109997, 110004, 110011, - 110017, 110025, 110033, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 110042, - 110047, 110053, 110058, 110063, 110068, 110073, 110078, 110085, 110090, - 110095, 110100, 110105, 110110, 110115, 110120, 110125, 110130, 110135, - 110140, 110145, 110150, 110154, 110158, 110162, 110166, 110171, 110176, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 110182, - 110187, 110192, 110197, 110202, 110207, 110212, 110217, 110222, 110227, - 110232, 110237, 110242, 110247, 110252, 110257, 110262, 110267, 110272, - 110277, 110282, 110287, 110292, 0, 0, 0, 0, 0, 0, 0, 0, 0, 110297, - 110301, 110305, 110309, 110313, 110317, 110320, 110324, 110327, 110331, - 110334, 110338, 110342, 110347, 110351, 110356, 110359, 110363, 110366, - 110370, 110373, 110377, 110381, 110385, 110389, 110393, 110397, 110401, - 110405, 110409, 110413, 110417, 110421, 110425, 110429, 110433, 110437, - 110441, 110445, 110448, 110451, 110455, 110459, 110463, 110466, 110469, - 110472, 110475, 110479, 110483, 110487, 110490, 110493, 110497, 110503, - 110509, 110515, 110520, 110527, 110531, 110536, 110540, 110545, 110550, - 110556, 110561, 110567, 110571, 110576, 110580, 110585, 110588, 110591, - 110595, 110600, 110606, 110611, 110617, 0, 0, 0, 0, 110622, 110625, - 110628, 110631, 110634, 110637, 110640, 110643, 110646, 110649, 110653, - 110657, 110661, 110665, 110669, 110673, 110677, 110681, 110685, 110690, - 110694, 110698, 110701, 110704, 110707, 110710, 110713, 110716, 110719, - 110722, 110725, 110731, 110738, 110745, 110753, 110761, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 110767, 110771, 110776, 110781, 110786, 110790, 110795, 110799, - 110804, 110808, 110813, 110817, 110822, 110826, 110831, 110835, 110840, - 110845, 110850, 110855, 110860, 110865, 110870, 110875, 110880, 110885, - 110890, 110895, 110900, 110905, 110910, 110915, 110920, 110925, 110930, - 110935, 110939, 110943, 110948, 110953, 110958, 110962, 110966, 110970, - 110974, 110979, 110984, 110989, 110993, 110997, 111003, 111008, 111014, - 111019, 111025, 111030, 111036, 111041, 111047, 111052, 111057, 111062, - 111067, 111071, 111076, 111082, 111086, 111091, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 111097, 0, 0, 111102, 111109, 111116, 111123, 111130, 111137, - 111144, 111151, 111158, 111165, 111172, 111179, 111186, 111193, 111200, - 111207, 111214, 111221, 111228, 111235, 111242, 111249, 111256, 111263, - 111270, 0, 0, 0, 0, 0, 0, 0, 111277, 111284, 111290, 111296, 111302, - 111308, 111314, 111320, 111326, 111332, 0, 0, 0, 0, 0, 0, 111338, 111343, - 111348, 111353, 111358, 111362, 111366, 111370, 111375, 111380, 111385, - 111390, 111395, 111400, 111405, 111410, 111415, 111420, 111425, 111430, - 111435, 111440, 111445, 111450, 111455, 111460, 111465, 111470, 111475, - 111480, 111485, 111490, 111495, 111500, 111505, 111510, 111515, 111520, - 111525, 111530, 111535, 111540, 111546, 111551, 111557, 111562, 111568, - 111573, 111579, 111585, 111589, 111594, 111598, 0, 111602, 111607, - 111611, 111615, 111619, 111623, 111627, 111631, 111635, 111639, 111643, - 111648, 111652, 111657, 111662, 111667, 111673, 111679, 0, 0, 0, 0, 0, 0, - 0, 0, 111684, 111688, 111692, 111696, 111700, 111704, 111708, 111713, - 111718, 111723, 111728, 111733, 111738, 111743, 111748, 111753, 111758, - 111763, 111768, 111773, 111778, 111783, 111788, 111793, 111797, 111801, - 111806, 111811, 111816, 111820, 111824, 111828, 111833, 111837, 111841, - 111846, 111851, 111856, 111861, 0, 0, 0, 0, 0, 0, 0, 0, 0, 111866, - 111871, 111876, 111881, 111885, 111890, 111894, 111899, 111903, 111908, - 111913, 111919, 111924, 111930, 111934, 111939, 111943, 111948, 111952, - 111957, 111962, 111967, 111972, 111977, 111982, 111987, 111992, 111997, - 112002, 112007, 112012, 112017, 112022, 112027, 112032, 112037, 112042, - 112046, 112050, 112055, 112060, 112065, 112069, 112073, 112077, 112081, - 112086, 112091, 112096, 112101, 112105, 112109, 112115, 112120, 112126, - 112131, 112137, 112143, 112150, 112156, 112163, 112168, 112174, 112179, - 112185, 112190, 112195, 112200, 112205, 112209, 112213, 112218, 112223, - 112227, 112232, 112237, 112242, 112250, 112255, 112262, 112269, 112274, - 112278, 112282, 112286, 112290, 112294, 112298, 112302, 112306, 112310, - 112314, 112319, 112323, 112328, 112334, 0, 112340, 112345, 112350, - 112355, 112360, 112365, 112370, 112375, 112380, 112385, 112391, 112397, - 112403, 112409, 112415, 112421, 112427, 112433, 112439, 112446, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 112452, 112456, 112461, 112465, 112469, 112473, - 112478, 112482, 112487, 112491, 112496, 112501, 112506, 112511, 112516, - 112521, 112526, 112531, 0, 112536, 112541, 112546, 112551, 112556, - 112561, 112566, 112571, 112576, 112581, 112586, 112591, 112595, 112599, - 112604, 112609, 112614, 112619, 112623, 112627, 112631, 112635, 112640, - 112644, 112648, 112653, 112659, 112664, 112670, 112675, 112680, 112686, - 112691, 112697, 112702, 112707, 112712, 112717, 112721, 112726, 112732, - 112737, 112743, 112748, 112753, 112758, 112764, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 112770, 112774, 112778, 112782, 112786, 112790, 112795, - 0, 112800, 0, 112805, 112810, 112815, 112820, 0, 112825, 112830, 112835, - 112840, 112845, 112850, 112855, 112860, 112865, 112870, 112875, 112880, - 112884, 112888, 112893, 0, 112898, 112903, 112907, 112911, 112915, - 112919, 112924, 112928, 112932, 112937, 112942, 0, 0, 0, 0, 0, 0, 112947, - 112951, 112956, 112960, 112965, 112969, 112974, 112978, 112983, 112987, - 112992, 112996, 113001, 113006, 113011, 113016, 113021, 113026, 113031, - 113036, 113041, 113046, 113051, 113056, 113061, 113066, 113071, 113076, - 113081, 113086, 113091, 113096, 113101, 113106, 113110, 113114, 113119, - 113124, 113129, 113134, 113138, 113142, 113146, 113150, 113155, 113160, - 113164, 113168, 113173, 113179, 113184, 113190, 113195, 113201, 113206, - 113212, 113217, 113223, 113228, 0, 0, 0, 0, 0, 113233, 113238, 113242, - 113246, 113250, 113254, 113258, 113262, 113266, 113270, 0, 0, 0, 0, 0, 0, - 113274, 113281, 113286, 113291, 0, 113296, 113300, 113305, 113309, - 113314, 113318, 113323, 113328, 0, 0, 113333, 113338, 0, 0, 113343, - 113348, 113353, 113357, 113362, 113367, 113372, 113377, 113382, 113387, - 113392, 113397, 113402, 113407, 113412, 113417, 113422, 113427, 113432, - 113437, 113442, 113447, 0, 113451, 113455, 113460, 113465, 113470, - 113474, 113478, 0, 113482, 113486, 0, 113491, 113496, 113501, 113506, - 113510, 0, 113514, 113518, 113523, 113528, 113534, 113539, 113545, - 113550, 113556, 113562, 0, 0, 113569, 113575, 0, 0, 113581, 113587, - 113593, 0, 0, 113598, 0, 0, 0, 0, 0, 0, 113602, 0, 0, 0, 0, 0, 113609, - 113614, 113621, 113629, 113635, 113641, 113647, 0, 0, 113654, 113660, - 113665, 113670, 113675, 113680, 113685, 0, 0, 0, 113690, 113695, 113700, - 113705, 113711, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 113716, 113720, 113725, - 113729, 113734, 113738, 113743, 113748, 113754, 113759, 113765, 113769, - 113774, 113778, 113783, 113787, 113792, 113797, 113802, 113807, 113812, - 113817, 113822, 113827, 113832, 113837, 113842, 113847, 113852, 113857, - 113862, 113867, 113872, 113877, 113882, 113887, 113891, 113896, 113900, - 113905, 113910, 113915, 113919, 113924, 113928, 113932, 113937, 113941, - 113946, 113951, 113956, 113961, 113965, 113969, 113975, 113980, 113986, - 113991, 113997, 114003, 114010, 114016, 114023, 114028, 114034, 114039, - 114045, 114050, 114055, 114060, 114065, 114070, 114075, 114081, 114085, - 114089, 114093, 114098, 114102, 114108, 114113, 114118, 114122, 114126, - 114130, 114134, 114138, 114142, 114146, 114150, 114154, 114159, 0, - 114164, 114169, 114174, 114181, 114186, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 114191, 114195, - 114199, 114204, 114208, 114213, 114217, 114222, 114227, 114233, 114238, - 114244, 114248, 114253, 114257, 114262, 114266, 114271, 114276, 114281, - 114286, 114291, 114296, 114301, 114306, 114311, 114316, 114321, 114326, - 114331, 114336, 114341, 114346, 114351, 114356, 114360, 114364, 114369, - 114374, 114379, 114383, 114387, 114391, 114395, 114400, 114405, 114410, - 114414, 114418, 114424, 114429, 114435, 114440, 114446, 114452, 114459, - 114465, 114472, 114477, 114484, 114490, 114495, 114502, 114508, 114513, - 114518, 114523, 114528, 114533, 114538, 114542, 114547, 0, 0, 0, 0, 0, 0, - 0, 0, 114551, 114556, 114560, 114564, 114568, 114572, 114576, 114580, - 114584, 114588, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 114592, 114596, - 114601, 114605, 114610, 114614, 114619, 114624, 114630, 114635, 114641, - 114645, 114650, 114654, 114659, 114663, 114668, 114673, 114678, 114683, - 114688, 114693, 114698, 114703, 114708, 114713, 114718, 114723, 114728, - 114733, 114738, 114743, 114748, 114753, 114757, 114761, 114766, 114771, - 114776, 114780, 114784, 114788, 114792, 114797, 114802, 114807, 114811, - 114815, 114821, 114826, 114832, 114837, 114843, 114849, 0, 0, 114856, - 114861, 114867, 114872, 114878, 114883, 114888, 114893, 114898, 114903, - 114908, 114912, 114917, 114923, 114928, 114934, 114940, 114946, 114954, - 114967, 114980, 114993, 115007, 115022, 115030, 115041, 115050, 115060, - 115070, 115080, 115091, 115103, 115116, 115124, 115132, 115141, 115147, - 115154, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115162, 115166, 115171, 115175, - 115180, 115184, 115189, 115194, 115200, 115205, 115211, 115215, 115220, - 115224, 115229, 115233, 115238, 115243, 115248, 115253, 115258, 115263, - 115268, 115273, 115278, 115283, 115288, 115293, 115298, 115303, 115308, - 115313, 115318, 115323, 115327, 115331, 115336, 115341, 115346, 115350, - 115354, 115358, 115362, 115367, 115372, 115377, 115381, 115385, 115390, - 115396, 115401, 115407, 115412, 115418, 115424, 115431, 115437, 115444, - 115449, 115455, 115460, 115466, 115471, 115476, 115481, 115486, 115490, - 115495, 115500, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115505, 115510, 115514, - 115518, 115522, 115526, 115530, 115534, 115538, 115542, 0, 0, 0, 0, 0, 0, - 115546, 115552, 115557, 115564, 115572, 115579, 115587, 115596, 115601, - 115610, 115615, 115623, 115632, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 115642, 115646, 115651, 115655, 115660, 115664, 115669, - 115673, 115678, 115682, 115687, 115691, 115696, 115701, 115706, 115711, - 115716, 115721, 115726, 115731, 115736, 115741, 115746, 115751, 115756, - 115761, 115766, 115771, 115776, 115781, 115785, 115789, 115794, 115799, - 115804, 115808, 115812, 115816, 115820, 115825, 115830, 115834, 115838, - 115843, 115848, 115853, 115859, 115864, 115870, 115875, 115881, 115886, - 115892, 115897, 115903, 115908, 115913, 115920, 0, 0, 0, 0, 0, 0, 115925, - 115930, 115934, 115938, 115942, 115946, 115950, 115954, 115958, 115962, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 115966, 115970, 115975, 115980, 115984, 115989, 115996, - 116000, 116005, 116010, 116014, 116019, 116024, 116029, 116033, 116037, - 116041, 116046, 116050, 116054, 116059, 116064, 116069, 116076, 116081, - 116086, 116091, 0, 0, 116098, 116105, 116112, 116121, 116126, 116132, - 116137, 116143, 116148, 116154, 116159, 116165, 116170, 116176, 116182, - 0, 0, 0, 0, 116187, 116192, 116196, 116200, 116204, 116208, 116212, - 116216, 116220, 116224, 116228, 116233, 116238, 116244, 116249, 116254, - 116259, 116264, 116269, 116274, 116279, 116284, 116289, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 116294, 116298, 116303, 116307, 116312, 116316, 116321, 116325, - 116330, 116334, 116339, 116343, 116348, 116353, 116358, 116363, 116368, - 116373, 116378, 116383, 116388, 116393, 116398, 116403, 116408, 116413, - 116418, 116423, 116428, 116433, 116437, 116441, 116446, 116451, 116456, - 116460, 116464, 116468, 116472, 116477, 116482, 116487, 116491, 116495, - 116500, 116506, 116511, 116517, 116522, 116528, 116534, 116541, 116546, - 116552, 116557, 116563, 116568, 116573, 116578, 116583, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116588, - 116596, 116603, 116611, 116619, 116626, 116634, 116642, 116650, 116657, - 116664, 116672, 116680, 116688, 116696, 116704, 116712, 116720, 116728, - 116736, 116744, 116752, 116760, 116768, 116776, 116784, 116792, 116800, - 116808, 116816, 116824, 116832, 116840, 116848, 116855, 116863, 116871, - 116878, 116886, 116894, 116902, 116909, 116916, 116924, 116932, 116940, - 116948, 116956, 116964, 116972, 116980, 116988, 116996, 117004, 117012, - 117020, 117028, 117036, 117044, 117052, 117060, 117068, 117076, 117084, - 117092, 117099, 117105, 117111, 117117, 117123, 117129, 117135, 117141, - 117147, 117153, 117160, 117167, 117174, 117181, 117188, 117195, 117202, - 117209, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 117216, 117222, 117228, - 117235, 117241, 117248, 117254, 117261, 0, 0, 117267, 0, 0, 117273, - 117279, 117286, 117293, 117300, 117307, 117314, 117321, 0, 117328, - 117335, 0, 117342, 117349, 117356, 117363, 117370, 117377, 117384, - 117391, 117397, 117403, 117410, 117417, 117424, 117430, 117436, 117443, - 117449, 117455, 117462, 117469, 117476, 117482, 117488, 117495, 117502, - 117510, 117517, 117525, 117532, 117540, 0, 117547, 117555, 0, 0, 117562, - 117569, 117576, 117583, 117589, 117598, 117605, 117611, 117618, 117625, - 117632, 117640, 0, 0, 0, 0, 0, 0, 0, 0, 0, 117650, 117657, 117663, - 117669, 117675, 117681, 117687, 117693, 117699, 117705, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 117711, 117715, 117720, - 117724, 117729, 117733, 117738, 117743, 0, 0, 117749, 117753, 117758, - 117762, 117767, 117771, 117776, 117781, 117786, 117791, 117796, 117801, - 117806, 117811, 117816, 117821, 117826, 117831, 117836, 117841, 117846, - 117851, 117856, 117861, 117865, 117869, 117874, 117879, 117884, 117888, - 117892, 117896, 117900, 117905, 117910, 117915, 117919, 117923, 117928, - 117933, 117939, 117944, 117950, 117955, 117961, 117967, 0, 0, 117974, - 117979, 117985, 117990, 117996, 118001, 118006, 118011, 118016, 118021, - 118025, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 118032, 118037, 118043, 118050, 118056, 118062, 118069, - 118075, 118082, 118089, 118097, 118104, 118109, 118115, 118121, 118127, - 118133, 118139, 118145, 118151, 118157, 118163, 118169, 118175, 118181, - 118187, 118193, 118199, 118205, 118211, 118216, 118221, 118227, 118233, - 118239, 118244, 118250, 118256, 118262, 118268, 118274, 118280, 118286, - 118291, 118296, 118301, 118307, 118313, 118319, 118324, 118329, 118335, - 118341, 118347, 118353, 118362, 118371, 118377, 118383, 118390, 118397, - 118404, 118411, 118419, 118426, 118434, 118440, 118446, 118453, 118460, - 118469, 118479, 0, 0, 0, 0, 0, 0, 0, 0, 118484, 118488, 118493, 118499, - 118504, 118509, 118514, 118520, 118526, 118532, 118538, 118544, 118550, - 118554, 118559, 118564, 118569, 118574, 118579, 118584, 118589, 118594, - 118599, 118604, 118609, 118614, 118619, 118624, 118629, 118634, 118639, - 118644, 118648, 118652, 118657, 118662, 118667, 118671, 118676, 118681, - 118686, 118691, 118696, 118701, 118705, 118709, 118713, 118718, 118723, - 118728, 118732, 118736, 118741, 118746, 118751, 118757, 118763, 118770, - 118776, 118783, 118790, 118797, 118804, 118811, 118818, 118825, 118831, - 118837, 118844, 118851, 118858, 118863, 118868, 118873, 118877, 118882, - 118887, 118893, 118898, 118914, 118928, 118939, 118945, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 118951, 118957, 118963, 118969, 118975, 118980, - 118986, 118992, 118998, 119004, 119010, 119016, 119022, 119026, 119030, - 119034, 119038, 119046, 119054, 119062, 119070, 119079, 119088, 119097, - 119106, 119114, 119123, 119132, 119140, 119149, 119158, 119167, 119176, - 119184, 119193, 119201, 119210, 119219, 119227, 119235, 119243, 119251, - 119259, 119268, 119277, 119287, 119297, 119307, 119317, 119327, 119336, - 119346, 119356, 119366, 119377, 119387, 119399, 119411, 119422, 119436, - 119447, 119457, 119469, 119480, 119490, 119502, 119514, 119525, 119536, - 119546, 119556, 119568, 119579, 0, 0, 0, 0, 0, 0, 0, 119591, 119595, - 119602, 119606, 119612, 119618, 119626, 119634, 119642, 119650, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 119654, 119658, - 119663, 119667, 119672, 119676, 119681, 119686, 119692, 0, 119697, - 119701, 119706, 119710, 119715, 119719, 119724, 119729, 119734, 119739, - 119744, 119749, 119754, 119759, 119764, 119769, 119774, 119779, 119784, - 119789, 119794, 119799, 119804, 119809, 119813, 119817, 119822, 119827, - 119832, 119836, 119840, 119844, 119848, 119853, 119858, 119863, 119867, - 119871, 119877, 119882, 119888, 119893, 119899, 119905, 119912, 0, - 119918, 119923, 119929, 119934, 119940, 119945, 119950, 119955, 119960, - 119965, 119969, 119974, 119980, 119986, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 119992, 119997, 120001, 120005, 120009, 120013, 120017, 120021, 120025, - 120029, 120033, 120037, 120041, 120045, 120049, 120053, 120057, 120061, - 120065, 120069, 120074, 120079, 120084, 120089, 120094, 120099, 120104, - 120109, 120114, 0, 0, 0, 120121, 120126, 120131, 120135, 120140, 120145, - 120150, 120155, 120160, 120165, 120170, 120175, 120180, 120185, 120189, - 120193, 120198, 120203, 120207, 120212, 120217, 120222, 120227, 120232, - 120237, 120242, 120246, 120250, 120254, 120259, 120263, 120267, 0, 0, - 120271, 120277, 120284, 120291, 120298, 120305, 120312, 120319, 120326, - 120333, 120340, 120347, 120353, 120359, 120366, 120373, 120379, 120386, - 120393, 120400, 120407, 120414, 0, 120421, 120427, 120433, 120439, - 120446, 120452, 120458, 120464, 120470, 120475, 120480, 120485, 120490, - 120495, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 120500, 120505, 120511, 120516, 120522, 120527, 120533, 0, - 120538, 120544, 0, 120549, 120555, 120560, 120566, 120572, 120578, - 120584, 120590, 120596, 120602, 120608, 120614, 120620, 120626, 120632, - 120638, 120644, 120650, 120656, 120662, 120668, 120673, 120678, 120684, - 120690, 120696, 120701, 120706, 120711, 120716, 120722, 120728, 120734, - 120739, 120744, 120750, 120756, 120762, 120768, 120775, 120781, 120788, - 120794, 120801, 0, 0, 0, 120808, 0, 120814, 120821, 0, 120827, 120834, - 120840, 120846, 120852, 120858, 120864, 120869, 120874, 0, 0, 0, 0, 0, 0, - 0, 0, 120879, 120885, 120890, 120895, 120900, 120905, 120910, 120915, - 120920, 120925, 0, 0, 0, 0, 0, 0, 120930, 120935, 120941, 120946, 120952, - 120957, 0, 120963, 120969, 0, 120975, 120981, 120987, 120992, 120998, - 121004, 121010, 121015, 121020, 121026, 121032, 121038, 121043, 121049, - 121055, 121061, 121067, 121072, 121078, 121084, 121090, 121096, 121102, - 121108, 121114, 121120, 121126, 121132, 121137, 121143, 121148, 121153, - 121158, 121165, 121171, 121178, 121184, 0, 121191, 121198, 0, 121205, - 121212, 121219, 121225, 121231, 121236, 0, 0, 0, 0, 0, 0, 0, 121241, - 121247, 121252, 121257, 121262, 121267, 121272, 121277, 121282, 121287, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 121292, 121296, 121301, 121306, - 121310, 121315, 121319, 121324, 121329, 121333, 121338, 121343, 121348, - 121352, 121356, 121360, 121365, 121369, 121373, 121377, 121382, 121387, - 121392, 121397, 121401, 0, 0, 0, 0, 0, 0, 0, 121408, 121413, 121418, - 121423, 121428, 121432, 121437, 121441, 121446, 121450, 121455, 121460, - 121466, 121471, 121477, 121481, 121486, 0, 121490, 121494, 121499, - 121504, 121509, 121514, 121519, 121524, 121529, 121534, 121539, 121544, - 121549, 121554, 121559, 121564, 121569, 121574, 121579, 121584, 121588, - 121592, 121597, 121602, 121607, 121611, 121615, 121619, 121623, 121628, - 121633, 121638, 121642, 121646, 121651, 121657, 121665, 121670, 121676, - 121681, 121687, 0, 0, 0, 121693, 121698, 121704, 121710, 121715, 121719, - 121723, 121728, 121736, 121746, 121752, 121760, 121766, 121773, 121781, - 121787, 121795, 121801, 121809, 121814, 121818, 121822, 121826, 121830, - 121834, 121838, 121842, 121846, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 121850, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 121855, 121861, - 121867, 121873, 121879, 121885, 121891, 121897, 121903, 121909, 121915, - 121921, 121927, 121933, 121939, 121945, 121951, 121957, 121963, 121969, - 121975, 121984, 121988, 121992, 121996, 122000, 122004, 122008, 122012, - 122016, 122020, 122024, 122028, 122032, 122036, 122040, 122044, 122050, - 122056, 122060, 122066, 122072, 122077, 122081, 122086, 122090, 122094, - 122100, 122106, 122110, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122114, - 122122, 122125, 122130, 122136, 122144, 122149, 122155, 122163, 122169, - 122175, 122179, 122183, 122190, 122199, 122206, 122215, 122221, 122230, - 122237, 122244, 122251, 122261, 122267, 122271, 122278, 122287, 122297, - 122304, 122311, 122315, 122319, 122326, 122336, 122340, 122347, 122354, - 122361, 122367, 122374, 122381, 122388, 122395, 122399, 122403, 122407, - 122414, 122418, 122425, 122432, 122446, 122455, 122459, 122463, 122467, - 122474, 122478, 122482, 122486, 122494, 122502, 122521, 122531, 122551, - 122555, 122559, 122563, 122567, 122571, 122575, 122579, 122586, 122590, - 122593, 122597, 122601, 122607, 122614, 122623, 122627, 122636, 122645, - 122653, 122657, 122664, 122668, 122672, 122676, 122680, 122691, 122700, - 122709, 122718, 122727, 122739, 122748, 122757, 122766, 122774, 122783, - 122795, 122804, 122812, 122821, 122833, 122842, 122851, 122863, 122872, - 122881, 122893, 122902, 122906, 122910, 122914, 122918, 122922, 122926, - 122930, 122937, 122941, 122945, 122956, 122960, 122964, 122971, 122977, - 122983, 122987, 122994, 122998, 123002, 123006, 123010, 123014, 123018, - 123024, 123032, 123036, 123040, 123043, 123050, 123062, 123066, 123078, - 123085, 123092, 123099, 123106, 123112, 123116, 123120, 123124, 123128, - 123135, 123144, 123151, 123159, 123167, 123173, 123177, 123181, 123185, - 123189, 123195, 123204, 123216, 123223, 123230, 123239, 123250, 123256, - 123265, 123274, 123281, 123290, 123297, 123303, 123313, 123320, 123327, - 123334, 123341, 123345, 123351, 123355, 123366, 123374, 123383, 123395, - 123402, 123409, 123419, 123426, 123435, 123442, 123451, 123458, 123465, - 123475, 123482, 123489, 123498, 123505, 123517, 123526, 123533, 123540, - 123547, 123556, 123566, 123579, 123586, 123595, 123605, 123612, 123621, - 123634, 123641, 123648, 123655, 123665, 123675, 123681, 123691, 123698, - 123705, 123715, 123721, 123728, 123735, 123742, 123752, 123759, 123766, - 123773, 123779, 123786, 123796, 123803, 123807, 123815, 123819, 123831, - 123835, 123849, 123853, 123857, 123861, 123865, 123871, 123878, 123886, - 123890, 123894, 123898, 123902, 123909, 123913, 123919, 123925, 123933, - 123937, 123944, 123952, 123956, 123960, 123966, 123970, 123979, 123988, - 123995, 124005, 124011, 124015, 124019, 124027, 124034, 124041, 124047, - 124051, 124059, 124063, 124070, 124082, 124089, 124099, 124105, 124109, - 124118, 124125, 124134, 124138, 124142, 124149, 124153, 124157, 124161, - 124165, 124168, 124174, 124180, 124184, 124188, 124195, 124202, 124209, - 124216, 124223, 124230, 124237, 124244, 124250, 124254, 124258, 124265, - 124272, 124279, 124286, 124293, 124297, 124300, 124305, 124309, 124313, - 124322, 124331, 124335, 124339, 124345, 124351, 124368, 124374, 124378, - 124387, 124391, 124395, 124402, 124410, 124418, 124424, 124428, 124432, - 124436, 124440, 124443, 124449, 124456, 124466, 124473, 124480, 124487, - 124493, 124500, 124507, 124514, 124521, 124528, 124537, 124544, 124556, - 124563, 124570, 124580, 124591, 124598, 124605, 124612, 124619, 124626, - 124633, 124640, 124647, 124654, 124661, 124671, 124681, 124691, 124698, - 124708, 124715, 124722, 124729, 124736, 124742, 124749, 124756, 124763, - 124770, 124777, 124784, 124791, 124798, 124804, 124811, 124818, 124827, - 124834, 124841, 124845, 124853, 124857, 124861, 124865, 124869, 124873, - 124880, 124884, 124893, 124897, 124904, 124912, 124916, 124920, 124924, - 124937, 124953, 124957, 124961, 124968, 124974, 124981, 124985, 124989, - 124993, 124997, 125001, 125008, 125012, 125030, 125034, 125038, 125045, - 125049, 125053, 125059, 125063, 125067, 125075, 125079, 125083, 125086, - 125090, 125096, 125107, 125116, 125125, 125132, 125139, 125150, 125157, - 125164, 125171, 125178, 125185, 125192, 125199, 125209, 125215, 125222, - 125232, 125241, 125248, 125257, 125267, 125274, 125281, 125288, 125295, - 125307, 125314, 125321, 125328, 125335, 125342, 125352, 125359, 125366, - 125376, 125389, 125401, 125408, 125418, 125425, 125432, 125439, 125453, - 125459, 125467, 125477, 125487, 125494, 125501, 125507, 125511, 125518, - 125528, 125534, 125547, 125551, 125555, 125562, 125566, 125573, 125583, - 125587, 125591, 125595, 125599, 125603, 125610, 125614, 125621, 125628, - 125635, 125644, 125653, 125663, 125670, 125677, 125684, 125694, 125701, - 125711, 125718, 125728, 125735, 125742, 125752, 125762, 125769, 125775, - 125783, 125791, 125797, 125803, 125807, 125811, 125818, 125826, 125832, - 125836, 125840, 125844, 125851, 125863, 125866, 125873, 125879, 125883, - 125887, 125891, 125895, 125899, 125903, 125907, 125911, 125915, 125919, - 125926, 125930, 125936, 125940, 125944, 125948, 125954, 125961, 125968, - 125975, 125986, 125994, 125998, 126004, 126013, 126020, 126026, 126029, - 126033, 126037, 126043, 126052, 126060, 126064, 126070, 126074, 126078, - 126082, 126088, 126095, 126101, 126105, 126111, 126115, 126119, 126128, - 126140, 126144, 126151, 126158, 126168, 126175, 126187, 126194, 126201, - 126208, 126219, 126229, 126242, 126252, 126259, 126263, 126267, 126271, - 126275, 126284, 126293, 126302, 126319, 126328, 126334, 126341, 126349, - 126362, 126366, 126375, 126384, 126393, 126402, 126413, 126422, 126430, - 126439, 126448, 126457, 126466, 126476, 126479, 126483, 126487, 126491, - 126495, 126499, 126505, 126512, 126519, 126526, 126532, 126538, 126545, - 126551, 126558, 126566, 126570, 126577, 126584, 126591, 126599, 126602, - 126606, 126610, 126614, 126617, 126623, 126627, 126633, 126640, 126647, - 126653, 126660, 126667, 126674, 126681, 126688, 126695, 126702, 126709, - 126716, 126723, 126730, 126737, 126744, 126751, 126757, 126761, 126770, - 126774, 126778, 126782, 126786, 126792, 126799, 126806, 126813, 126820, - 126827, 126833, 126841, 126845, 126849, 126853, 126857, 126863, 126880, - 126897, 126901, 126905, 126909, 126913, 126917, 126921, 126927, 126934, - 126938, 126944, 126951, 126958, 126965, 126972, 126979, 126988, 126995, - 127002, 127009, 127016, 127020, 127024, 127030, 127042, 127046, 127050, - 127059, 127063, 127067, 127071, 127077, 127081, 127085, 127094, 127098, - 127102, 127106, 127113, 127117, 127121, 127125, 127129, 127133, 127137, - 127141, 127145, 127151, 127158, 127165, 127171, 127175, 127192, 127198, - 127202, 127209, 127216, 127223, 127230, 127237, 127244, 127248, 127252, - 127256, 127262, 127266, 127272, 127276, 127280, 127287, 127294, 127311, - 127315, 127319, 127323, 127327, 127331, 127343, 127346, 127351, 127356, - 127371, 127381, 127393, 127397, 127401, 127405, 127411, 127418, 127425, - 127435, 127447, 127453, 127459, 127468, 127472, 127476, 127483, 127493, - 127500, 127506, 127510, 127514, 127521, 127527, 127531, 127537, 127541, - 127549, 127555, 127559, 127567, 127575, 127582, 127588, 127595, 127602, - 127612, 127622, 127626, 127630, 127634, 127638, 127644, 127651, 127657, - 127664, 127671, 127678, 127687, 127694, 127701, 127707, 127714, 127721, - 127728, 127735, 127742, 127749, 127755, 127762, 127769, 127776, 127785, - 127792, 127799, 127803, 127809, 127813, 127819, 127826, 127833, 127840, - 127844, 127848, 127852, 127856, 127860, 127867, 127871, 127875, 127881, - 127889, 127893, 127897, 127901, 127905, 127912, 127916, 127920, 127928, - 127932, 127936, 127940, 127944, 127950, 127954, 127958, 127964, 127971, - 127977, 127984, 127996, 128000, 128007, 128014, 128021, 128028, 128040, - 128047, 128051, 128055, 128059, 128066, 128073, 128080, 128087, 128097, - 128104, 128110, 128117, 128124, 128131, 128138, 128147, 128157, 128164, - 128168, 128175, 128179, 128183, 128187, 128194, 128201, 128211, 128217, - 128221, 128230, 128234, 128241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128245, 128251, 128257, - 128264, 128271, 128278, 128285, 128292, 128299, 128305, 128312, 128319, - 128326, 128333, 128340, 128347, 128353, 128359, 128365, 128371, 128377, - 128383, 128389, 128395, 128401, 128408, 128415, 128422, 128429, 128436, - 128443, 128449, 128455, 128461, 128468, 128475, 128481, 128487, 128496, - 128503, 128510, 128517, 128524, 128531, 128538, 128544, 128550, 128556, - 128565, 128572, 128579, 128590, 128601, 128607, 128613, 128619, 128628, - 128635, 128642, 128652, 128662, 128673, 128684, 128696, 128709, 128720, - 128731, 128743, 128756, 128767, 128778, 128789, 128800, 128811, 128823, - 128831, 128839, 128848, 128857, 128866, 128872, 128878, 128884, 128891, - 128901, 128908, 128918, 128923, 128928, 128934, 128940, 128948, 128956, - 128965, 128976, 128987, 128995, 129003, 129012, 129021, 129029, 129036, - 129044, 129052, 129059, 129066, 129075, 129084, 129093, 129102, 129111, - 0, 129120, 129131, 129138, 129146, 129154, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 129162, 129171, 129178, 129185, 129194, 129201, 129208, 129215, - 129225, 129232, 129239, 129246, 129254, 129261, 129268, 129275, 129286, - 129293, 129300, 129307, 129314, 129321, 129330, 129337, 129343, 129350, - 129359, 129366, 129373, 129380, 129390, 129397, 129404, 129414, 129424, - 129431, 129438, 129445, 129452, 129459, 129466, 129475, 129482, 129489, - 129495, 129503, 129512, 129521, 129532, 129540, 129549, 129558, 129567, - 129576, 129583, 129590, 129599, 129611, 129621, 129628, 129635, 129645, - 129655, 129664, 129674, 129681, 129691, 129698, 129705, 129712, 129722, - 129732, 129739, 129746, 129756, 129762, 129773, 129782, 129792, 129800, - 129813, 129820, 129826, 129834, 129841, 129851, 129855, 129859, 129863, - 129867, 129871, 129875, 129879, 129888, 129892, 129899, 129903, 129907, - 129911, 129915, 129919, 129923, 129927, 129931, 129935, 129939, 129943, - 129947, 129951, 129955, 129959, 129963, 129967, 129971, 129975, 129982, - 129989, 129999, 130012, 130022, 130026, 130030, 130034, 130038, 130042, - 130046, 130050, 130054, 130058, 130062, 130066, 130073, 130080, 130091, - 130098, 130104, 130111, 130118, 130125, 130132, 130139, 130143, 130147, - 130154, 130161, 130168, 130177, 130184, 130197, 130207, 130214, 130221, - 130225, 130229, 130238, 130245, 130252, 130259, 130272, 130279, 130286, - 130296, 130306, 130315, 130322, 130329, 130336, 130343, 130350, 130357, - 130367, 130373, 130381, 130388, 130396, 130403, 130414, 130421, 130427, - 130434, 130441, 130448, 130455, 130465, 130475, 130482, 130489, 130498, - 130506, 130512, 130519, 130526, 130533, 130540, 130544, 130554, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 130564, 130569, 130574, 130579, 130584, 130589, 130594, 130599, - 130604, 130609, 130614, 130619, 130624, 130629, 130634, 130639, 130644, - 130649, 130654, 130659, 130664, 130669, 130674, 130679, 130684, 130689, - 130694, 130699, 130704, 130709, 130714, 130719, 130724, 130729, 130734, - 130739, 130744, 130749, 130754, 130759, 130764, 130769, 130774, 130779, - 130784, 130789, 130794, 130799, 130804, 130809, 130814, 130819, 130824, - 130829, 130834, 130839, 130844, 130849, 130854, 130859, 130864, 130869, - 130874, 130879, 130884, 130889, 130894, 130899, 130904, 130909, 130914, - 130919, 130924, 130929, 130934, 130939, 130944, 130949, 130954, 130959, - 130964, 130969, 130974, 130979, 130984, 130989, 130994, 130999, 131004, - 131009, 131014, 131019, 131024, 131029, 131034, 131039, 131044, 131049, - 131054, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 131059, 131063, 131067, - 131071, 131075, 131079, 131083, 131087, 131091, 131095, 131099, 131103, - 131107, 131111, 131115, 131119, 131123, 131127, 131131, 131135, 131139, - 131143, 131147, 131151, 131155, 131159, 131163, 131167, 131171, 131175, - 131179, 131183, 131187, 131191, 131195, 131199, 131203, 131207, 131211, - 131215, 131219, 131223, 131227, 131231, 131235, 131239, 131243, 131247, - 131251, 131255, 131259, 131263, 131267, 131271, 131275, 131279, 131283, - 131287, 131291, 131295, 131299, 131303, 131307, 131311, 131315, 131319, - 131323, 131327, 131331, 131335, 131339, 131343, 131347, 131351, 131355, - 131359, 131363, 131367, 131371, 131375, 131379, 131383, 131387, 131391, - 131395, 131399, 131403, 131407, 131411, 131415, 131419, 131423, 131427, - 131431, 131435, 131439, 131443, 131447, 131451, 131455, 131459, 131463, - 131467, 131471, 131475, 131479, 131483, 131487, 131491, 131495, 131499, - 131503, 131507, 131511, 131515, 131519, 131523, 131527, 131531, 131535, - 131539, 131543, 131547, 131551, 131555, 131559, 131563, 131567, 131571, - 131575, 131579, 131583, 131587, 131591, 131595, 131599, 131603, 131607, - 131611, 131615, 131619, 131623, 131627, 131631, 131635, 131639, 131643, - 131647, 131651, 131655, 131659, 131663, 131667, 131671, 131675, 131679, - 131683, 131687, 131691, 131695, 131699, 131703, 131707, 131711, 131715, - 131719, 131723, 131727, 131731, 131735, 131739, 131743, 131747, 131751, - 131755, 131759, 131763, 131767, 131771, 131775, 131779, 131783, 131787, - 131791, 131795, 131799, 131803, 131807, 131811, 131815, 131819, 131823, - 131827, 131831, 131835, 131839, 131843, 131847, 131851, 131855, 131859, - 131863, 131867, 131871, 131875, 131879, 131883, 131887, 131891, 131895, - 131899, 131903, 131907, 131911, 131915, 131919, 131923, 131927, 131931, - 131935, 131939, 131943, 131947, 131951, 131955, 131959, 131963, 131967, - 131971, 131975, 131979, 131983, 131987, 131991, 131995, 131999, 132003, - 132007, 132011, 132015, 132019, 132023, 132027, 132031, 132035, 132039, - 132043, 132047, 132051, 132055, 132059, 132063, 132067, 132071, 132075, - 132079, 132083, 132087, 132091, 132095, 132099, 132103, 132107, 132111, - 132115, 132119, 132123, 132127, 132131, 132135, 132139, 132143, 132147, - 132151, 132155, 132159, 132163, 132167, 132171, 132175, 132179, 132183, - 132187, 132191, 132195, 132199, 132203, 132207, 132211, 132215, 132219, - 132223, 132227, 132231, 132235, 132239, 132243, 132247, 132251, 132255, - 132259, 132263, 132267, 132271, 132275, 132279, 132283, 132287, 132291, - 132295, 132299, 132303, 132307, 132311, 132315, 132319, 132323, 132327, - 132331, 132335, 132339, 132343, 132347, 132351, 132355, 132359, 132363, - 132367, 132371, 132375, 132379, 132383, 132387, 132391, 132395, 132399, - 132403, 132407, 132411, 132415, 132419, 132423, 132427, 132431, 132435, - 132439, 132443, 132447, 132451, 132455, 132459, 132463, 132467, 132471, - 132475, 132479, 132483, 132487, 132491, 132495, 132499, 132503, 132507, - 132511, 132515, 132519, 132523, 132527, 132531, 132535, 132539, 132543, - 132547, 132551, 132555, 132559, 132563, 132567, 132571, 132575, 132579, - 132583, 132587, 132591, 132595, 132599, 132603, 132607, 132611, 132615, - 132619, 132623, 132627, 132631, 132635, 132639, 132643, 132647, 132651, - 132655, 132659, 132663, 132667, 132671, 132675, 132679, 132683, 132687, - 132691, 132695, 132699, 132703, 132707, 132711, 132715, 132719, 132723, - 132727, 132731, 132735, 132739, 132743, 132747, 132751, 132755, 132759, - 132763, 132767, 132771, 132775, 132779, 132783, 132787, 132791, 132795, - 132799, 132803, 132807, 132811, 132815, 132819, 132823, 132827, 132831, - 132835, 132839, 132843, 132847, 132851, 132855, 132859, 132863, 132867, - 132871, 132875, 132879, 132883, 132887, 132891, 132895, 132899, 132903, - 132907, 132911, 132915, 132919, 132923, 132927, 132931, 132935, 132939, - 132943, 132947, 132951, 132955, 132959, 132963, 132967, 132971, 132975, - 132979, 132983, 132987, 132991, 132995, 132999, 133003, 133007, 133011, - 133015, 133019, 133023, 133027, 133031, 133035, 133039, 133043, 133047, - 133051, 133055, 133059, 133063, 133067, 133071, 133075, 133079, 133083, - 133087, 133091, 133095, 133099, 133103, 133107, 133111, 133115, 133119, - 133123, 133127, 133131, 133135, 133139, 133143, 133147, 133151, 133155, - 133159, 133163, 133167, 133171, 133175, 133179, 133183, 133187, 133191, - 133195, 133199, 133203, 133207, 133211, 133215, 133219, 133223, 133227, - 133231, 133235, 133239, 133243, 133247, 133251, 133255, 133259, 133263, - 133267, 133271, 133275, 133279, 133283, 133287, 133291, 133295, 133299, - 133303, 133307, 133311, 133315, 133319, 133323, 133327, 133331, 133335, - 133339, 133343, 133347, 133351, 133355, 133359, 133363, 133367, 133371, - 133375, 133379, 133383, 133387, 133391, 133395, 133399, 133403, 133407, - 133411, 133415, 133419, 133423, 133427, 133431, 133435, 133439, 133443, - 133447, 133451, 133455, 133459, 133463, 133467, 133471, 133475, 133479, - 133483, 133487, 133491, 133495, 133499, 133503, 133507, 133511, 133515, - 133519, 133523, 133527, 133531, 133535, 133539, 133543, 133547, 133551, - 133555, 133559, 133563, 133567, 133571, 133575, 133579, 133583, 133587, - 133591, 133595, 133599, 133603, 133607, 133611, 133615, 133619, 133623, - 133627, 133631, 133635, 133639, 133643, 133647, 133651, 133655, 133659, - 133663, 133667, 133671, 133675, 133679, 133683, 133687, 133691, 133695, - 133699, 133703, 133707, 133711, 133715, 133719, 133723, 133727, 133731, - 133735, 133739, 133743, 133747, 133751, 133755, 133759, 133763, 133767, - 133771, 133775, 133779, 133783, 133787, 133791, 133795, 133799, 133803, - 133807, 133811, 133815, 133819, 133823, 133827, 133831, 133835, 133839, - 133843, 133847, 133851, 133855, 133859, 133863, 133867, 133871, 133875, - 133879, 133883, 133887, 133891, 133895, 133899, 133903, 133907, 133911, - 133915, 133919, 133923, 133927, 133931, 133935, 133939, 133943, 133947, - 133951, 133955, 133959, 133963, 133967, 133971, 133975, 133979, 133983, - 133987, 133991, 133995, 133999, 134003, 134007, 134011, 134015, 134019, - 134023, 134027, 134031, 134035, 134039, 134043, 134047, 134051, 134055, - 134059, 134063, 134067, 134071, 134075, 134079, 134083, 134087, 134091, - 134095, 134099, 134103, 134107, 134111, 134115, 134119, 134123, 134127, - 134131, 134135, 134139, 134143, 134147, 134151, 134155, 134159, 134163, - 134167, 134171, 134175, 134179, 134183, 134187, 134191, 134195, 134199, - 134203, 134207, 134211, 134215, 134219, 134223, 134227, 134231, 134235, - 134239, 134243, 134247, 134251, 134255, 134259, 134263, 134267, 134271, - 134275, 134279, 134283, 134287, 134291, 134295, 134299, 134303, 134307, - 134311, 134315, 134319, 134323, 134327, 134331, 134335, 134339, 134343, - 134347, 134351, 134355, 134359, 134363, 134367, 134371, 134375, 134379, - 134383, 134387, 134391, 134395, 134399, 134403, 134407, 134411, 134415, - 134419, 134423, 134427, 134431, 134435, 134439, 134443, 134447, 134451, - 134455, 134459, 134463, 134467, 134471, 134475, 134479, 134483, 134487, - 134491, 134495, 134499, 134503, 134507, 134511, 134515, 134519, 134523, - 134527, 134531, 134535, 134539, 134543, 134547, 134551, 134555, 134559, - 134563, 134567, 134571, 134575, 134579, 134583, 134587, 134591, 134595, - 134599, 134603, 134607, 134611, 134615, 134619, 134623, 134627, 134631, - 134635, 134639, 134643, 134647, 134651, 134655, 134659, 134663, 134667, - 134671, 134675, 134679, 134683, 134687, 134691, 134695, 134699, 134703, - 134707, 134711, 134715, 134719, 134723, 134727, 134731, 134735, 134739, - 134743, 134747, 134751, 134755, 134759, 134763, 134767, 134771, 134775, - 134779, 134783, 134787, 134791, 134795, 134799, 134803, 134807, 134811, - 134815, 134819, 134823, 134827, 134831, 134835, 134839, 134843, 134847, - 134851, 134855, 134859, 134863, 134867, 134871, 134875, 134879, 134883, - 134887, 134891, 134895, 134899, 134903, 134907, 134911, 134915, 134919, - 134923, 134927, 134931, 134935, 134939, 134943, 134947, 134951, 134955, - 134959, 134963, 134967, 134971, 134975, 134979, 134983, 134987, 134991, - 134995, 134999, 135003, 135007, 135011, 135015, 135019, 135023, 135027, - 135031, 135035, 135039, 135043, 135047, 135051, 135055, 135059, 135063, - 135067, 135071, 135075, 135079, 135083, 135087, 135091, 135095, 135099, - 135103, 135107, 135111, 135115, 135119, 135123, 135127, 135131, 135135, - 135139, 135143, 135147, 135151, 135155, 135159, 135163, 135167, 135171, - 135175, 135179, 135183, 135187, 135191, 135195, 135199, 135203, 135207, - 135211, 135215, 135219, 135223, 135227, 135231, 135235, 135239, 135243, - 135247, 135251, 135255, 135259, 135263, 135267, 135271, 135275, 135279, - 135283, 135287, 135291, 135295, 135299, 135303, 135307, 135311, 135315, - 135319, 135323, 135327, 135331, 135335, 135339, 135343, 135347, 135352, - 135358, 135368, 135378, 135388, 135398, 135404, 135410, 135416, 135424, - 135432, 135440, 135446, 135452, 135460, 135468, 135474, 135480, 135485, - 135490, 135496, 135503, 135510, 135521, 135532, 135541, 135552, 135561, - 135577, 135589, 135600, 135616, 135625, 135637, 135646, 135658, 135670, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 135675, 135679, - 135683, 135687, 135691, 135695, 135699, 135703, 135707, 135711, 135715, - 135719, 135723, 135727, 135731, 135735, 135739, 135743, 135747, 135751, - 135755, 135759, 135763, 135767, 135771, 135775, 135779, 135783, 135787, - 135791, 135795, 135799, 135803, 135807, 135811, 135815, 135819, 135823, - 135827, 135831, 135835, 135839, 135843, 135847, 135851, 135855, 135859, - 135863, 135867, 135871, 135875, 135879, 135883, 135887, 135891, 135895, - 135899, 135903, 135907, 135911, 135915, 135919, 135923, 135927, 135931, - 135935, 135939, 135943, 135947, 135951, 135955, 135959, 135963, 135967, - 135971, 135975, 135979, 135983, 135987, 135991, 135995, 135999, 136003, - 136007, 136011, 136015, 136019, 136023, 136027, 136031, 136035, 136039, - 136043, 136047, 136051, 136055, 136059, 136063, 136067, 136071, 136075, - 136079, 136083, 136087, 136091, 136095, 136099, 136103, 136107, 136111, - 136115, 136119, 136123, 136127, 136131, 136135, 136139, 136143, 136147, - 136151, 136155, 136159, 136163, 136167, 136171, 136175, 136179, 136183, - 136187, 136191, 136195, 136199, 136203, 136207, 136211, 136215, 136219, - 136223, 136227, 136231, 136235, 136239, 136243, 136247, 136251, 136255, - 136259, 136263, 136267, 136271, 136275, 136279, 136283, 136287, 136291, - 136295, 136299, 136303, 136307, 136311, 136315, 136319, 136323, 136327, - 136331, 136335, 136339, 136343, 136347, 136351, 136355, 136359, 136363, - 136367, 136371, 136375, 136379, 136383, 136387, 136391, 136395, 136399, - 136403, 136407, 136411, 136415, 136419, 136423, 136427, 136431, 136435, - 136439, 136443, 136447, 136451, 136455, 136459, 136463, 136467, 136471, - 136475, 136479, 136483, 136487, 136491, 136495, 136499, 136503, 136507, - 136511, 136515, 136519, 136523, 136527, 136531, 136535, 136539, 136543, - 136547, 136551, 136555, 136559, 136563, 136567, 136571, 136575, 136579, - 136583, 136587, 136591, 136595, 136599, 136603, 136607, 136611, 136615, - 136619, 136623, 136627, 136631, 136635, 136639, 136643, 136647, 136651, - 136655, 136659, 136663, 136667, 136671, 136675, 136679, 136683, 136687, - 136691, 136695, 136699, 136703, 136707, 136711, 136715, 136719, 136723, - 136727, 136731, 136735, 136739, 136743, 136747, 136751, 136755, 136759, - 136763, 136767, 136771, 136775, 136779, 136783, 136787, 136791, 136795, - 136799, 136803, 136807, 136811, 136815, 136819, 136823, 136827, 136831, - 136835, 136839, 136843, 136847, 136851, 136855, 136859, 136863, 136867, - 136871, 136875, 136879, 136883, 136887, 136891, 136895, 136899, 136903, - 136907, 136911, 136915, 136919, 136923, 136927, 136931, 136935, 136939, - 136943, 136947, 136951, 136955, 136959, 136963, 136967, 136971, 136975, - 136979, 136983, 136987, 136991, 136995, 136999, 137003, 137007, 137011, - 137015, 137019, 137023, 137027, 137031, 137035, 137039, 137043, 137047, - 137051, 137055, 137059, 137063, 137067, 137071, 137075, 137079, 137083, - 137087, 137091, 137095, 137099, 137103, 137107, 137111, 137115, 137119, - 137123, 137127, 137131, 137135, 137139, 137143, 137147, 137151, 137155, - 137159, 137163, 137167, 137171, 137175, 137179, 137183, 137187, 137191, - 137195, 137199, 137203, 137207, 137211, 137215, 137219, 137223, 137227, - 137231, 137235, 137239, 137243, 137247, 137251, 137255, 137259, 137263, - 137267, 137271, 137275, 137279, 137283, 137287, 137291, 137295, 137299, - 137303, 137307, 137311, 137315, 137319, 137323, 137327, 137331, 137335, - 137339, 137343, 137347, 137351, 137355, 137359, 137363, 137367, 137371, - 137375, 137379, 137383, 137387, 137391, 137395, 137399, 137403, 137407, - 137417, 137421, 137425, 137429, 137433, 137437, 137441, 137445, 137449, - 137453, 137457, 137461, 137466, 137470, 137474, 137478, 137482, 137486, - 137490, 137494, 137498, 137502, 137506, 137510, 137514, 137518, 137522, - 137526, 137530, 137539, 137548, 137552, 137556, 137560, 137564, 137568, - 137572, 137576, 137580, 137584, 137588, 137592, 137596, 137600, 137604, - 137608, 137612, 137616, 137620, 137624, 137628, 137632, 137636, 137640, - 137644, 137648, 137652, 137656, 137660, 137664, 137668, 137672, 137676, - 137680, 137684, 137688, 137692, 137696, 137700, 137704, 137708, 137712, - 137716, 137720, 137724, 137728, 137732, 137736, 137740, 137744, 137748, - 137752, 137756, 137760, 137764, 137768, 137772, 137776, 137780, 137784, - 137788, 137792, 137796, 137800, 137804, 137808, 137812, 137816, 137820, - 137824, 137828, 137832, 137836, 137840, 137844, 137848, 137852, 137856, - 137860, 137864, 137868, 137872, 137876, 137880, 137884, 137888, 137892, - 137896, 137900, 137904, 137908, 137912, 137916, 137920, 137924, 137928, - 137932, 137936, 137940, 137944, 137948, 137952, 137956, 137960, 137964, - 137968, 137972, 137976, 137980, 137984, 137988, 137992, 137996, 138000, - 138004, 138008, 138012, 138016, 138020, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 138024, - 138032, 138040, 138050, 138060, 138068, 138074, 138082, 138090, 138100, - 138112, 138124, 138130, 138138, 138144, 138150, 138156, 138162, 138168, - 138174, 138180, 138186, 138192, 138198, 138204, 138212, 138220, 138226, - 138232, 138238, 138244, 138252, 138260, 138269, 138275, 138283, 138289, - 138295, 138301, 138307, 138313, 138321, 138329, 138335, 138341, 138347, - 138353, 138359, 138365, 138371, 138377, 138383, 138389, 138395, 138401, - 138407, 138413, 138419, 138425, 138431, 138437, 138443, 138451, 138457, - 138463, 138473, 138481, 138487, 138493, 138499, 138505, 138511, 138517, - 138523, 138529, 138535, 138541, 138547, 138553, 138559, 138565, 138571, - 138577, 138583, 138589, 138595, 138601, 138607, 138613, 138621, 138627, - 138635, 138643, 138651, 138657, 138663, 138669, 138675, 138681, 138689, - 138699, 138707, 138715, 138721, 138727, 138735, 138743, 138749, 138757, - 138765, 138773, 138779, 138785, 138791, 138797, 138803, 138809, 138817, - 138825, 138831, 138837, 138843, 138849, 138855, 138863, 138869, 138875, - 138881, 138887, 138893, 138899, 138907, 138913, 138919, 138925, 138931, - 138939, 138947, 138953, 138959, 138965, 138970, 138976, 138982, 138990, - 138996, 139002, 139008, 139014, 139020, 139026, 139032, 139038, 139044, - 139054, 139062, 139068, 139074, 139080, 139088, 139094, 139100, 139106, - 139114, 139120, 139126, 139132, 139138, 139144, 139150, 139156, 139162, - 139168, 139174, 139180, 139188, 139194, 139202, 139208, 139214, 139222, - 139228, 139234, 139240, 139246, 139252, 139258, 139264, 139270, 139276, - 139282, 139288, 139294, 139300, 139306, 139312, 139318, 139324, 139330, - 139336, 139344, 139350, 139356, 139362, 139368, 139374, 139380, 139386, - 139392, 139398, 139404, 139410, 139416, 139422, 139430, 139436, 139442, - 139450, 139456, 139462, 139468, 139474, 139480, 139486, 139492, 139498, - 139504, 139510, 139518, 139524, 139530, 139536, 139542, 139548, 139556, - 139564, 139570, 139576, 139582, 139588, 139594, 139600, 139605, 139610, - 139615, 139620, 139625, 139630, 139635, 139640, 139645, 139650, 139655, - 139660, 139665, 139670, 139675, 139680, 139685, 139690, 139695, 139700, - 139705, 139710, 139715, 139720, 139725, 139730, 139735, 139740, 139745, - 139750, 139757, 139762, 139767, 139772, 139777, 139782, 139787, 139792, - 139797, 139802, 139807, 139812, 139817, 139822, 139827, 139832, 139837, - 139842, 139847, 139852, 139857, 139862, 139867, 139872, 139877, 139882, - 139887, 139892, 139897, 139902, 139907, 139912, 139917, 139922, 139927, - 139932, 139937, 139942, 139947, 139952, 139957, 139962, 139967, 139972, - 139977, 139982, 139987, 139992, 139997, 140002, 140007, 140012, 140017, - 140022, 140027, 140032, 140037, 140042, 140047, 140054, 140059, 140064, - 140069, 140074, 140079, 140084, 140089, 140094, 140099, 140104, 140109, - 140114, 140119, 140124, 140129, 140134, 140139, 140144, 140149, 140154, - 140159, 140166, 140171, 140176, 140182, 140187, 140192, 140197, 140202, - 140207, 140212, 140217, 140222, 140227, 140232, 140237, 140242, 140247, - 140252, 140257, 140262, 140267, 140272, 140277, 140282, 140287, 140292, - 140297, 140302, 140307, 140312, 140317, 140322, 140327, 140332, 140337, - 140342, 140347, 140352, 140357, 140362, 140367, 140372, 140377, 140382, - 140387, 140392, 140397, 140404, 140409, 140414, 140421, 140428, 140433, - 140438, 140443, 140448, 140453, 140458, 140463, 140468, 140473, 140478, - 140483, 140488, 140493, 140498, 140503, 140508, 140513, 140518, 140523, - 140528, 140533, 140538, 140543, 140548, 140553, 140560, 140565, 140570, - 140575, 140580, 140585, 140590, 140595, 140600, 140605, 140610, 140615, - 140620, 140625, 140630, 140635, 140640, 140645, 140650, 140657, 140662, - 140667, 140672, 140677, 140682, 140687, 140692, 140698, 140703, 140708, - 140713, 140718, 140723, 140728, 140733, 140738, 140745, 140752, 140757, - 140762, 140766, 140771, 140775, 140779, 140784, 140791, 140796, 140801, - 140810, 140815, 140820, 140825, 140830, 140837, 140844, 140849, 140854, - 140859, 140864, 140871, 140876, 140881, 140886, 140891, 140896, 140901, - 140906, 140911, 140916, 140921, 140926, 140931, 140938, 140942, 140947, - 140952, 140957, 140962, 140966, 140971, 140976, 140981, 140986, 140991, - 140996, 141001, 141006, 141011, 141017, 141023, 141029, 141035, 141041, - 141046, 141052, 141058, 141064, 141070, 141076, 141082, 141088, 141094, - 141100, 141106, 141112, 141118, 141124, 141130, 141136, 141142, 141148, - 141154, 141159, 141165, 141171, 141177, 141183, 141189, 141195, 141201, - 141207, 141213, 141219, 141225, 141231, 141237, 141243, 141249, 141255, - 141261, 141267, 141273, 141279, 141284, 141290, 141296, 141302, 141308, - 141314, 0, 0, 0, 0, 0, 0, 0, 141320, 141325, 141330, 141335, 141340, - 141345, 141350, 141354, 141359, 141364, 141369, 141374, 141379, 141384, - 141389, 141394, 141399, 141403, 141408, 141412, 141417, 141422, 141427, - 141432, 141437, 141441, 141446, 141451, 141455, 141460, 141465, 0, - 141470, 141475, 141479, 141483, 141487, 141491, 141495, 141499, 141503, - 141507, 0, 0, 0, 0, 141511, 141515, 141520, 141525, 141530, 141535, - 141540, 141545, 141550, 141555, 141560, 141565, 141570, 141575, 141580, - 141585, 141590, 141595, 141600, 141605, 141610, 141615, 141620, 141625, - 141630, 141635, 141640, 141645, 141650, 141655, 141660, 141665, 141670, - 141675, 141680, 141686, 141692, 141699, 141706, 141711, 141716, 141721, - 141726, 141731, 141736, 141741, 141746, 141751, 141756, 141761, 141766, - 141770, 141775, 141780, 141785, 141789, 141793, 141798, 141802, 141807, - 141812, 141817, 141821, 141825, 141829, 141833, 141838, 141843, 141848, - 141852, 141857, 141862, 141867, 141872, 141877, 141882, 141887, 141892, - 141897, 141902, 141907, 0, 141912, 141917, 141921, 141925, 141929, - 141933, 141937, 141941, 141945, 141949, 0, 0, 0, 0, 0, 0, 141953, 141960, - 141966, 141973, 141980, 141987, 141994, 142001, 142008, 142015, 142022, - 142029, 142036, 142043, 142050, 142057, 142064, 142071, 142077, 142084, - 142091, 142098, 142104, 142111, 142117, 142123, 142130, 142136, 142143, - 142149, 0, 0, 142155, 142163, 142171, 142180, 142189, 142198, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 142206, 142211, 142216, 142221, 142226, 142231, 142236, - 142241, 142246, 142251, 142256, 142261, 142266, 142271, 142276, 142281, - 142286, 142291, 142296, 142301, 142306, 142311, 142316, 142321, 142326, - 142331, 142336, 142341, 142346, 142351, 142356, 142361, 142366, 142371, - 142376, 142381, 142386, 142391, 142396, 142401, 142406, 142411, 142416, - 142421, 142426, 142431, 142436, 142441, 142446, 142453, 142460, 142467, - 142474, 142481, 142488, 142495, 142502, 142511, 142518, 142525, 142532, - 142539, 142546, 142553, 142560, 142567, 142574, 142581, 142588, 142593, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 142602, 142607, 142611, 142615, 142619, - 142623, 142627, 142631, 142635, 142639, 0, 142643, 142648, 142653, - 142660, 142665, 142672, 142679, 0, 142684, 142691, 142696, 142701, - 142708, 142715, 142720, 142725, 142730, 142735, 142740, 142747, 142754, - 142759, 142764, 142769, 142782, 142791, 142798, 142807, 142816, 0, 0, 0, - 0, 0, 142825, 142832, 142839, 142846, 142853, 142860, 142867, 142874, - 142881, 142888, 142895, 142902, 142909, 142916, 142923, 142930, 142937, - 142944, 142951, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 142958, 142964, 142970, 142976, - 142982, 142988, 142994, 143000, 143006, 143012, 143018, 143024, 143029, - 143035, 143040, 143046, 143051, 143057, 143063, 143068, 143074, 143079, - 143085, 143091, 143097, 143103, 143109, 143115, 143121, 143126, 143131, - 143137, 143143, 143149, 143155, 143161, 143167, 143173, 143179, 143185, - 143191, 143197, 143203, 143209, 143214, 143220, 143225, 143231, 143236, - 143242, 143248, 143253, 143259, 143264, 143270, 143276, 143282, 143288, - 143294, 143300, 143306, 143311, 143316, 143322, 143328, 143333, 143337, - 143341, 143345, 143349, 143353, 143357, 143361, 143365, 143369, 143374, - 143379, 143384, 143389, 143394, 143399, 143404, 143409, 143414, 143419, - 143426, 143433, 143440, 143444, 143450, 143455, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 143461, - 143464, 143468, 143472, 143476, 143479, 143483, 143488, 143492, 143496, - 143500, 143504, 143508, 143513, 143518, 143522, 143526, 143529, 143533, - 143538, 143543, 143547, 143551, 143554, 143558, 143562, 143566, 143570, - 143574, 143578, 143582, 143585, 143589, 143593, 143597, 143601, 143605, - 143609, 143615, 143618, 143622, 143626, 143630, 143634, 143638, 143642, - 143646, 143650, 143654, 143659, 143664, 143670, 143674, 143678, 143682, - 143686, 143690, 143694, 143699, 143702, 143706, 143710, 143714, 143718, - 143724, 143728, 143732, 143736, 143740, 143744, 143748, 143752, 143756, - 143760, 143764, 0, 0, 0, 0, 143768, 143773, 143777, 143781, 143787, - 143793, 143797, 143802, 143807, 143812, 143817, 143821, 143826, 143831, - 143836, 143840, 143845, 143850, 143855, 143859, 143864, 143869, 143874, - 143879, 143884, 143889, 143894, 143899, 143903, 143908, 143913, 143918, - 143923, 143928, 143933, 143938, 143943, 143948, 143953, 143958, 143965, - 143970, 143977, 143982, 143987, 143992, 143997, 144002, 144007, 144012, - 144017, 144022, 144027, 144032, 144037, 144042, 144047, 0, 0, 0, 0, 0, 0, - 0, 144052, 144055, 144060, 144063, 144066, 144070, 144074, 144078, - 144082, 144086, 144090, 144094, 144100, 144106, 144112, 144118, 144124, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 144130, 144134, 144138, - 144144, 144150, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 144155, 144164, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 144173, 144176, 144179, 144182, 144185, - 144188, 144191, 144194, 144197, 144200, 144203, 144206, 144209, 144212, - 144215, 144218, 144221, 144224, 144227, 144230, 144233, 144236, 144239, - 144242, 144245, 144248, 144251, 144254, 144257, 144260, 144263, 144266, - 144269, 144272, 144275, 144278, 144281, 144284, 144287, 144290, 144293, - 144296, 144299, 144302, 144305, 144308, 144311, 144314, 144317, 144320, - 144323, 144326, 144329, 144332, 144335, 144338, 144341, 144344, 144347, - 144350, 144353, 144356, 144359, 144362, 144365, 144368, 144371, 144374, - 144377, 144380, 144383, 144386, 144389, 144392, 144395, 144398, 144401, - 144404, 144407, 144410, 144413, 144416, 144419, 144422, 144425, 144428, - 144431, 144434, 144437, 144440, 144443, 144446, 144449, 144452, 144455, - 144458, 144461, 144464, 144467, 144470, 144473, 144476, 144479, 144482, - 144485, 144488, 144491, 144494, 144497, 144500, 144503, 144506, 144509, - 144512, 144515, 144518, 144521, 144524, 144527, 144530, 144533, 144536, - 144539, 144542, 144545, 144548, 144551, 144554, 144557, 144560, 144563, - 144566, 144569, 144572, 144575, 144578, 144581, 144584, 144587, 144590, - 144593, 144596, 144599, 144602, 144605, 144608, 144611, 144614, 144617, - 144620, 144623, 144626, 144629, 144632, 144635, 144638, 144641, 144644, - 144647, 144650, 144653, 144656, 144659, 144662, 144665, 144668, 144671, - 144674, 144677, 144680, 144683, 144686, 144689, 144692, 144695, 144698, - 144701, 144704, 144707, 144710, 144713, 144716, 144719, 144722, 144725, - 144728, 144731, 144734, 144737, 144740, 144743, 144746, 144749, 144752, - 144755, 144758, 144761, 144764, 144767, 144770, 144773, 144776, 144779, - 144782, 144785, 144788, 144791, 144794, 144797, 144800, 144803, 144806, - 144809, 144812, 144815, 144818, 144821, 144824, 144827, 144830, 144833, - 144836, 144839, 144842, 144845, 144848, 144851, 144854, 144857, 144860, - 144863, 144866, 144869, 144872, 144875, 144878, 144881, 144884, 144887, - 144890, 144893, 144896, 144899, 144902, 144905, 144908, 144911, 144914, - 144917, 144920, 144923, 144926, 144929, 144932, 144935, 144938, 144941, - 144944, 144947, 144950, 144953, 144956, 144959, 144962, 144965, 144968, - 144971, 144974, 144977, 144980, 144983, 144986, 144989, 144992, 144995, - 144998, 145001, 145004, 145007, 145010, 145013, 145016, 145019, 145022, - 145025, 145028, 145031, 145034, 145037, 145040, 145043, 145046, 145049, - 145052, 145055, 145058, 145061, 145064, 145067, 145070, 145073, 145076, - 145079, 145082, 145085, 145088, 145091, 145094, 145097, 145100, 145103, - 145106, 145109, 145112, 145115, 145118, 145121, 145124, 145127, 145130, - 145133, 145136, 145139, 145142, 145145, 145148, 145151, 145154, 145157, - 145160, 145163, 145166, 145169, 145172, 145175, 145178, 145181, 145184, - 145187, 145190, 145193, 145196, 145199, 145202, 145205, 145208, 145211, - 145214, 145217, 145220, 145223, 145226, 145229, 145232, 145235, 145238, - 145241, 145244, 145247, 145250, 145253, 145256, 145259, 145262, 145265, - 145268, 145271, 145274, 145277, 145280, 145283, 145286, 145289, 145292, - 145295, 145298, 145301, 145304, 145307, 145310, 145313, 145316, 145319, - 145322, 145325, 145328, 145331, 145334, 145337, 145340, 145343, 145346, - 145349, 145352, 145355, 145358, 145361, 145364, 145367, 145370, 145373, - 145376, 145379, 145382, 145385, 145388, 145391, 145394, 145397, 145400, - 145403, 145406, 145409, 145412, 145415, 145418, 145421, 145424, 145427, - 145430, 145433, 145436, 145439, 145442, 145445, 145448, 145451, 145454, - 145457, 145460, 145463, 145466, 145469, 145472, 145475, 145478, 145481, - 145484, 145487, 145490, 145493, 145496, 145499, 145502, 145505, 145508, - 145511, 145514, 145517, 145520, 145523, 145526, 145529, 145532, 145535, - 145538, 145541, 145544, 145547, 145550, 145553, 145556, 145559, 145562, - 145565, 145568, 145571, 145574, 145577, 145580, 145583, 145586, 145589, - 145592, 145595, 145598, 145601, 145604, 145607, 145610, 145613, 145616, - 145619, 145622, 145625, 145628, 145631, 145634, 145637, 145640, 145643, - 145646, 145649, 145652, 145655, 145658, 145661, 145664, 145667, 145670, - 145673, 145676, 145679, 145682, 145685, 145688, 145691, 145694, 145697, - 145700, 145703, 145706, 145709, 145712, 145715, 145718, 145721, 145724, - 145727, 145730, 145733, 145736, 145739, 145742, 145745, 145748, 145751, - 145754, 145757, 145760, 145763, 145766, 145769, 145772, 145775, 145778, - 145781, 145784, 145787, 145790, 145793, 145796, 145799, 145802, 145805, - 145808, 145811, 145814, 145817, 145820, 145823, 145826, 145829, 145832, - 145835, 145838, 145841, 145844, 145847, 145850, 145853, 145856, 145859, - 145862, 145865, 145868, 145871, 145874, 145877, 145880, 145883, 145886, - 145889, 145892, 145895, 145898, 145901, 145904, 145907, 145910, 145913, - 145916, 145919, 145922, 145925, 145928, 145931, 145934, 145937, 145940, - 145943, 145946, 145949, 145952, 145955, 145958, 145961, 145964, 145967, - 145970, 145973, 145976, 145979, 145982, 145985, 145988, 145991, 145994, - 145997, 146000, 146003, 146006, 146009, 146012, 146015, 146018, 146021, - 146024, 146027, 146030, 146033, 146036, 146039, 146042, 146045, 146048, - 146051, 146054, 146057, 146060, 146063, 146066, 146069, 146072, 146075, - 146078, 146081, 146084, 146087, 146090, 146093, 146096, 146099, 146102, - 146105, 146108, 146111, 146114, 146117, 146120, 146123, 146126, 146129, - 146132, 146135, 146138, 146141, 146144, 146147, 146150, 146153, 146156, - 146159, 146162, 146165, 146168, 146171, 146174, 146177, 146180, 146183, - 146186, 146189, 146192, 146195, 146198, 146201, 146204, 146207, 146210, - 146213, 146216, 146219, 146222, 146225, 146228, 146231, 146234, 146237, - 146240, 146243, 146246, 146249, 146252, 146255, 146258, 146261, 146264, - 146267, 146270, 146273, 146276, 146279, 146282, 146285, 146288, 146291, - 146294, 146297, 146300, 146303, 146306, 146309, 146312, 146315, 146318, - 146321, 146324, 146327, 146330, 146333, 146336, 146339, 146342, 146345, - 146348, 146351, 146354, 146357, 146360, 146363, 146366, 146369, 146372, - 146375, 146378, 146381, 146384, 146387, 146390, 146393, 146396, 146399, - 146402, 146405, 146408, 146411, 146414, 146417, 146420, 146423, 146426, - 146429, 146432, 146435, 146438, 146441, 146444, 146447, 146450, 146453, - 146456, 146459, 146462, 146465, 146468, 146471, 146474, 146477, 146482, - 146487, 146492, 146497, 146502, 146507, 146512, 146517, 146522, 146527, - 146532, 146537, 146542, 146547, 146552, 146557, 146562, 146567, 146572, - 146577, 146582, 146587, 146592, 146597, 146602, 146607, 146612, 146617, - 146622, 146627, 146632, 146637, 146642, 146647, 146652, 146657, 146662, - 146667, 146672, 146677, 146682, 146687, 146692, 146697, 146702, 146707, - 146712, 146717, 146722, 146727, 146732, 146737, 146742, 146747, 146752, - 146757, 146762, 146767, 146772, 146777, 146782, 146787, 146792, 146797, - 146802, 146807, 146812, 146817, 146822, 146827, 146832, 146837, 146842, - 146847, 146852, 146857, 146862, 146867, 146872, 146877, 146882, 146887, - 146892, 146897, 146902, 146907, 146912, 146917, 146922, 146927, 146932, - 146937, 146942, 146947, 146952, 146957, 146962, 146967, 146972, 146977, - 146982, 146987, 146992, 146997, 147002, 147007, 147012, 147017, 147022, - 147027, 147032, 147037, 147042, 147047, 147052, 147057, 147062, 147067, - 147072, 147077, 147082, 147087, 147092, 147097, 147102, 147107, 147112, - 147117, 147122, 147127, 147132, 147137, 147142, 147147, 147152, 147157, - 147162, 147167, 147172, 147177, 147182, 147187, 147192, 147197, 147202, - 147207, 147212, 147217, 147222, 147227, 147232, 147237, 147242, 147247, - 147252, 147257, 147262, 147267, 147272, 147277, 147282, 147287, 147292, - 147297, 147302, 147307, 147312, 147317, 147322, 147327, 147332, 147337, - 147342, 147347, 147352, 147357, 147362, 147367, 147372, 147377, 147382, - 147387, 147392, 147397, 147402, 147407, 147412, 147417, 147422, 147427, - 147432, 147437, 147442, 147447, 147452, 147457, 147462, 147467, 147472, - 147477, 147482, 147487, 147492, 147497, 147502, 147507, 147512, 147517, - 147522, 147527, 147532, 147537, 147542, 147547, 147552, 147557, 147562, - 147567, 147572, 147577, 147582, 147587, 147592, 147597, 147602, 147607, - 147612, 147617, 147622, 147627, 147632, 147637, 147642, 147647, 147652, - 147657, 147662, 147667, 147672, 147677, 147682, 147687, 147692, 147697, - 147702, 147707, 147712, 147717, 147722, 147727, 147732, 147737, 147742, - 147747, 147752, 147757, 147762, 147767, 147772, 147777, 147782, 147787, - 147792, 147797, 147802, 147807, 147812, 147817, 147822, 147827, 147832, - 147837, 147842, 147847, 147852, 147857, 147862, 147867, 147872, 147877, - 147882, 147887, 147892, 147897, 147902, 147907, 147912, 147917, 147922, - 147927, 147932, 147937, 147942, 147947, 147952, 147957, 147962, 147967, - 147972, 147977, 147982, 147987, 147992, 147997, 148002, 148007, 148012, - 148017, 148022, 148027, 148032, 148037, 148042, 148047, 148052, 148057, - 148062, 148067, 148072, 148077, 148082, 148087, 148092, 148097, 148102, - 148107, 148112, 148117, 148122, 148127, 148132, 148137, 148142, 148147, - 148152, 148157, 148162, 148167, 148172, 148177, 148182, 148187, 148192, - 148197, 148202, 148207, 148212, 148217, 148222, 148227, 148232, 148237, - 148242, 148247, 148252, 148257, 148262, 148267, 148272, 148277, 148282, - 148287, 148292, 148297, 148302, 148307, 148312, 148317, 148322, 148327, - 148332, 148337, 148342, 148347, 148352, 148357, 148362, 148367, 148372, - 148377, 148382, 148387, 148392, 148397, 148402, 148407, 148412, 148417, - 148422, 148427, 148432, 148437, 148442, 148447, 148452, 148457, 148462, - 148467, 148472, 148477, 148482, 148487, 148492, 148497, 148502, 148507, - 148512, 148517, 148522, 148527, 148532, 148537, 148542, 148547, 148552, - 148557, 148562, 148567, 148572, 148577, 148582, 148587, 148592, 148597, - 148602, 148607, 148612, 148617, 148622, 148627, 148632, 148637, 148642, - 148647, 148652, 148657, 148662, 148667, 148672, 148677, 148682, 148687, - 148692, 148697, 148702, 148707, 148712, 148717, 148722, 148727, 148732, - 148737, 148742, 148747, 148752, 148757, 148762, 148767, 148772, 148777, - 148782, 148787, 148792, 148797, 148802, 148807, 148812, 148817, 148822, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 148827, 148833, 148839, 148845, 0, 148851, - 148857, 148863, 148871, 148879, 148887, 148895, 0, 148903, 148911, 0, - 148919, 148924, 148931, 148935, 148939, 148943, 148947, 148951, 148955, - 148959, 148963, 148967, 148971, 148975, 148979, 148983, 148987, 148991, - 148995, 148999, 149003, 149007, 149011, 149015, 149019, 149023, 149027, - 149031, 149035, 149039, 149043, 149047, 149051, 149055, 149059, 149063, - 149067, 149071, 149075, 149079, 149083, 149087, 149091, 149095, 149099, - 149103, 149107, 149111, 149115, 149119, 149123, 149127, 149131, 149135, - 149139, 149143, 149147, 149151, 149155, 149159, 149163, 149167, 149171, - 149175, 149179, 149183, 149187, 149191, 149195, 149199, 149203, 149207, - 149211, 149215, 149219, 149223, 149227, 149231, 149235, 149239, 149243, - 149247, 149251, 149255, 149259, 149263, 149267, 149271, 149275, 149279, - 149283, 149287, 149291, 149295, 149299, 149303, 149307, 149311, 149315, - 149319, 149323, 149327, 149331, 149335, 149339, 149343, 149347, 149351, - 149355, 149359, 149363, 149367, 149371, 149375, 149379, 149383, 149387, - 149391, 149395, 149399, 149403, 149407, 149411, 149415, 149419, 149423, - 149427, 149431, 149435, 149439, 149443, 149447, 149451, 149455, 149459, - 149463, 149467, 149471, 149475, 149479, 149483, 149487, 149491, 149495, - 149499, 149503, 149507, 149511, 149515, 149519, 149523, 149527, 149531, - 149535, 149539, 149543, 149547, 149551, 149555, 149559, 149563, 149567, - 149571, 149575, 149579, 149583, 149587, 149591, 149595, 149599, 149603, - 149607, 149611, 149615, 149619, 149623, 149627, 149631, 149635, 149639, - 149643, 149647, 149651, 149655, 149659, 149663, 149667, 149671, 149675, - 149679, 149683, 149687, 149691, 149695, 149699, 149703, 149707, 149711, - 149715, 149719, 149723, 149727, 149731, 149735, 149739, 149743, 149747, - 149751, 149755, 149759, 149763, 149767, 149771, 149775, 149779, 149783, - 149787, 149791, 149795, 149799, 149803, 149807, 149811, 149815, 149819, - 149823, 149827, 149831, 149835, 149839, 149843, 149847, 149851, 149855, - 149859, 149863, 149867, 149871, 149875, 149879, 149883, 149887, 149891, - 149895, 149899, 149903, 149907, 149911, 149915, 149919, 149923, 149927, - 149931, 149935, 149939, 149943, 149947, 149951, 149955, 149959, 149963, - 149967, 149971, 149975, 149979, 149983, 149987, 149991, 149995, 149999, - 150003, 150007, 150011, 150015, 150019, 150023, 150027, 150031, 150035, - 150039, 150043, 150047, 150051, 150055, 150059, 150063, 150067, 150071, - 150078, 150084, 150090, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 150096, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 150102, 150108, 150114, 0, 0, 150120, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 150125, 150130, 150135, 150140, 0, 0, 0, 0, 0, - 0, 0, 0, 150145, 150148, 150151, 150154, 150157, 150160, 150163, 150166, - 150169, 150172, 150175, 150178, 150181, 150184, 150187, 150190, 150193, - 150196, 150199, 150202, 150205, 150208, 150211, 150214, 150217, 150220, - 150223, 150226, 150229, 150232, 150235, 150238, 150241, 150244, 150247, - 150250, 150253, 150256, 150259, 150262, 150265, 150268, 150271, 150274, - 150277, 150280, 150283, 150286, 150289, 150292, 150295, 150298, 150301, - 150304, 150307, 150310, 150313, 150316, 150319, 150322, 150325, 150328, - 150331, 150334, 150337, 150340, 150343, 150346, 150349, 150352, 150355, - 150358, 150361, 150364, 150367, 150370, 150373, 150376, 150379, 150382, - 150385, 150388, 150391, 150394, 150397, 150400, 150403, 150406, 150409, - 150412, 150415, 150418, 150421, 150424, 150427, 150430, 150433, 150436, - 150439, 150442, 150445, 150448, 150451, 150454, 150457, 150460, 150463, - 150466, 150469, 150472, 150475, 150478, 150481, 150484, 150487, 150490, - 150493, 150496, 150499, 150502, 150505, 150508, 150511, 150514, 150517, - 150520, 150523, 150526, 150529, 150532, 150535, 150538, 150541, 150544, - 150547, 150550, 150553, 150556, 150559, 150562, 150565, 150568, 150571, - 150574, 150577, 150580, 150583, 150586, 150589, 150592, 150595, 150598, - 150601, 150604, 150607, 150610, 150613, 150616, 150619, 150622, 150625, - 150628, 150631, 150634, 150637, 150640, 150643, 150646, 150649, 150652, - 150655, 150658, 150661, 150664, 150667, 150670, 150673, 150676, 150679, - 150682, 150685, 150688, 150691, 150694, 150697, 150700, 150703, 150706, - 150709, 150712, 150715, 150718, 150721, 150724, 150727, 150730, 150733, - 150736, 150739, 150742, 150745, 150748, 150751, 150754, 150757, 150760, - 150763, 150766, 150769, 150772, 150775, 150778, 150781, 150784, 150787, - 150790, 150793, 150796, 150799, 150802, 150805, 150808, 150811, 150814, - 150817, 150820, 150823, 150826, 150829, 150832, 150835, 150838, 150841, - 150844, 150847, 150850, 150853, 150856, 150859, 150862, 150865, 150868, - 150871, 150874, 150877, 150880, 150883, 150886, 150889, 150892, 150895, - 150898, 150901, 150904, 150907, 150910, 150913, 150916, 150919, 150922, - 150925, 150928, 150931, 150934, 150937, 150940, 150943, 150946, 150949, - 150952, 150955, 150958, 150961, 150964, 150967, 150970, 150973, 150976, - 150979, 150982, 150985, 150988, 150991, 150994, 150997, 151000, 151003, - 151006, 151009, 151012, 151015, 151018, 151021, 151024, 151027, 151030, - 151033, 151036, 151039, 151042, 151045, 151048, 151051, 151054, 151057, - 151060, 151063, 151066, 151069, 151072, 151075, 151078, 151081, 151084, - 151087, 151090, 151093, 151096, 151099, 151102, 151105, 151108, 151111, - 151114, 151117, 151120, 151123, 151126, 151129, 151132, 151135, 151138, - 151141, 151144, 151147, 151150, 151153, 151156, 151159, 151162, 151165, - 151168, 151171, 151174, 151177, 151180, 151183, 151186, 151189, 151192, - 151195, 151198, 151201, 151204, 151207, 151210, 151213, 151216, 151219, - 151222, 151225, 151228, 151231, 151234, 151237, 151240, 151243, 151246, - 151249, 151252, 151255, 151258, 151261, 151264, 151267, 151270, 151273, - 151276, 151279, 151282, 151285, 151288, 151291, 151294, 151297, 151300, - 151303, 151306, 151309, 151312, 151315, 151318, 151321, 151324, 151327, - 151330, 0, 0, 0, 0, 151333, 151337, 151341, 151345, 151349, 151353, - 151357, 151360, 151364, 151368, 151372, 151376, 151379, 151385, 151391, - 151397, 151403, 151409, 151413, 151419, 151423, 151427, 151433, 151437, - 151441, 151445, 151449, 151453, 151457, 151461, 151467, 151473, 151479, - 151485, 151492, 151499, 151506, 151516, 151523, 151530, 151536, 151542, - 151548, 151554, 151562, 151570, 151578, 151586, 151595, 151601, 151609, - 151615, 151622, 151628, 151635, 151641, 151649, 151653, 151657, 151662, - 151668, 151674, 151682, 151690, 151696, 151703, 151706, 151712, 151716, - 151719, 151723, 151726, 151729, 151733, 151738, 151742, 151746, 151752, - 151757, 151763, 151767, 151771, 151774, 151778, 151782, 151787, 151791, - 151796, 151800, 151805, 151809, 151813, 151817, 151821, 151825, 151829, - 151833, 151837, 151842, 151847, 151852, 151857, 151863, 151869, 151875, - 151881, 151887, 0, 0, 0, 0, 0, 151892, 151900, 151909, 151917, 151924, - 151932, 151939, 151946, 151955, 151962, 151969, 151977, 151985, 0, 0, 0, - 151993, 151999, 152007, 152013, 152020, 152026, 152032, 152038, 152044, - 0, 0, 0, 0, 0, 0, 0, 152050, 152056, 152064, 152070, 152077, 152083, - 152089, 152095, 152101, 152107, 0, 0, 152112, 152118, 152124, 152127, - 152136, 152143, 152151, 152158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 152165, 152180, 152193, 152202, 152213, 152222, 152231, - 152242, 152251, 152260, 152275, 152288, 152301, 152315, 152327, 152335, - 152345, 152353, 152361, 152371, 152379, 152387, 152401, 152413, 152425, - 152434, 152445, 152454, 152463, 152470, 152479, 152488, 152495, 152500, - 152505, 152510, 152515, 152520, 152525, 152530, 152535, 152540, 152545, - 152550, 152555, 152560, 0, 0, 152569, 152578, 152587, 152596, 152601, - 152608, 152613, 152618, 152626, 152631, 152638, 152643, 152650, 152655, - 152660, 152667, 152674, 152679, 152688, 152694, 152700, 152708, 152714, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 152720, 152724, 152730, 152734, 152742, - 152746, 152750, 152754, 152762, 152766, 152772, 152781, 152785, 152789, - 152793, 152799, 152805, 152811, 152817, 152823, 152829, 152835, 152841, - 152847, 152855, 152863, 152871, 152879, 152884, 152890, 152894, 152898, - 152902, 152906, 152912, 152918, 152924, 152930, 152936, 152944, 152950, - 152958, 152966, 152974, 152982, 152990, 152994, 153002, 153008, 153016, - 153020, 153024, 153028, 153032, 153036, 153040, 153048, 153056, 153068, - 153080, 153086, 153096, 153104, 153114, 153126, 153130, 153136, 153142, - 153148, 153154, 153160, 153166, 153172, 153178, 153184, 153192, 153198, - 153204, 153210, 153218, 153226, 153237, 153248, 153254, 153260, 153270, - 153276, 153284, 153288, 153294, 153300, 153306, 153312, 153318, 153324, - 153330, 153334, 153340, 153346, 153354, 153362, 153370, 153376, 153384, - 153397, 153410, 153418, 153426, 153438, 153446, 153456, 153464, 153468, - 153472, 153476, 153480, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 153484, - 153489, 153494, 153499, 153506, 153513, 153520, 153527, 153532, 153537, - 153542, 153547, 153554, 153559, 153566, 153573, 153578, 153583, 153588, - 153595, 153600, 153605, 153612, 153619, 153624, 153629, 153634, 153641, - 153648, 153655, 153660, 153665, 153672, 153679, 153686, 153693, 153698, - 153703, 153708, 153715, 153720, 153725, 153730, 153737, 153746, 153753, - 153758, 153763, 153768, 153773, 153778, 153783, 153792, 153799, 153804, - 153811, 153818, 153823, 153828, 153833, 153840, 153845, 153852, 153859, - 153864, 153869, 153874, 153881, 153888, 153893, 153898, 153905, 153912, - 153919, 153924, 153929, 153934, 153939, 153946, 153955, 153964, 153969, - 153976, 153985, 153990, 153995, 154000, 154005, 154012, 154019, 154026, - 154033, 154038, 154043, 154048, 154055, 154062, 154069, 154074, 154079, - 154086, 154091, 154098, 154103, 154110, 154115, 154122, 154129, 154134, - 154139, 154144, 154149, 154154, 154159, 154164, 154169, 154174, 154181, - 154188, 154195, 154202, 154209, 154218, 154223, 154228, 154235, 154242, - 154247, 154254, 154261, 154268, 154275, 154282, 154289, 154294, 154299, - 154304, 154309, 154314, 154323, 154332, 154341, 154350, 154359, 154368, - 154377, 154386, 154391, 154402, 154413, 154422, 154427, 154432, 154437, - 154442, 154451, 154458, 154465, 154472, 154479, 154486, 154493, 154502, - 154511, 154522, 154531, 154542, 154551, 154558, 154567, 154578, 154587, - 154596, 154605, 154614, 154621, 154628, 154635, 154644, 154653, 154664, - 154673, 154682, 154693, 154698, 154703, 154714, 154722, 154731, 154740, - 154749, 154760, 154769, 154778, 154789, 154800, 154811, 154822, 154833, - 154844, 154851, 154858, 154865, 154872, 154883, 154892, 154899, 154906, - 154913, 154924, 154935, 154946, 154957, 154968, 154979, 154990, 155001, - 155008, 155015, 155024, 155033, 155040, 155047, 155054, 155063, 155072, - 155081, 155088, 155097, 155106, 155115, 155122, 155129, 155134, 155140, - 155147, 155154, 155161, 155168, 155175, 155182, 155191, 155200, 155209, - 155218, 155225, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 155234, 155240, 155245, - 155250, 155257, 155263, 155269, 155275, 155281, 155287, 155293, 155299, - 155303, 155307, 155313, 155319, 155325, 155329, 155334, 155339, 155343, - 155347, 155351, 155357, 155363, 155369, 155375, 155381, 155387, 155393, - 155399, 155405, 155415, 155425, 155431, 155437, 155447, 155457, 155463, - 0, 0, 155469, 155477, 155482, 155487, 155493, 155499, 155505, 155511, - 155517, 155523, 155530, 155537, 155543, 155549, 155555, 155561, 155567, - 155573, 155579, 155585, 155590, 155596, 155602, 155608, 155614, 155620, - 155629, 155635, 155640, 155648, 155655, 155662, 155671, 155680, 155689, - 155698, 155707, 155716, 155725, 155734, 155744, 155754, 155762, 155770, - 155779, 155788, 155794, 155800, 155806, 155812, 155820, 155828, 155832, - 155838, 155843, 155849, 155855, 155861, 155867, 155873, 155882, 155887, - 155894, 155899, 155904, 155909, 155915, 155921, 155927, 155934, 155939, - 155944, 155949, 155954, 155959, 155965, 155971, 155977, 155983, 155989, - 155995, 156001, 156007, 156012, 156017, 156022, 156027, 156032, 156037, - 156042, 156047, 156053, 156059, 156064, 156069, 156074, 156079, 156084, - 156090, 156097, 156101, 156105, 156109, 156113, 156117, 156121, 156125, - 156129, 156137, 156147, 156151, 156155, 156161, 156167, 156173, 156179, - 156185, 156191, 156197, 156203, 156209, 156215, 156221, 156227, 156233, - 156239, 156243, 156247, 156254, 156260, 156266, 156272, 156277, 156284, - 156289, 156295, 156301, 156307, 156313, 156318, 156322, 156328, 156332, - 156336, 156340, 156346, 156352, 156356, 156362, 156368, 156374, 156380, - 156386, 156394, 156402, 156408, 156414, 156420, 156426, 156438, 156450, - 156464, 156476, 156488, 156502, 156516, 156530, 156534, 156542, 156550, - 156555, 156559, 156563, 156567, 156571, 156575, 156579, 156583, 156589, - 156595, 156601, 156607, 156615, 156624, 156631, 156638, 156646, 156653, - 156665, 156677, 156689, 156701, 156708, 156712, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 156716, 156723, 156730, 156737, - 156744, 156751, 156758, 156765, 156772, 156779, 156786, 156793, 156800, - 156807, 156814, 156821, 156828, 156835, 156842, 156849, 156856, 156863, - 156870, 156877, 156884, 156891, 156898, 156905, 156912, 156919, 156926, - 156933, 156940, 156947, 156954, 156961, 156968, 156975, 156982, 156989, - 156996, 157003, 157010, 157017, 157024, 157031, 157038, 157045, 157052, - 157059, 157066, 157073, 157080, 157087, 157094, 157101, 157108, 157115, - 157122, 157129, 157136, 157143, 157150, 157157, 157164, 157171, 157178, - 157183, 157188, 157193, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 157197, 157203, 157208, 157213, 157218, - 157223, 157228, 157233, 157238, 157243, 157248, 157254, 157260, 157266, - 157272, 157278, 157284, 157290, 157296, 157302, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 157308, 157314, 157319, 157324, 157329, 157334, 157339, - 157344, 157349, 157354, 157359, 157365, 157371, 157377, 157383, 157389, - 157395, 157401, 157407, 157413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 157419, 157424, 157431, 157438, 157445, 157452, 157457, 157462, 157469, - 157474, 157479, 157486, 157491, 157496, 157501, 157508, 157517, 157522, - 157527, 157532, 157537, 157542, 157547, 157554, 157559, 157564, 157569, - 157574, 157579, 157584, 157589, 157594, 157599, 157604, 157609, 157614, - 157620, 157625, 157630, 157635, 157640, 157645, 157650, 157655, 157660, - 157665, 157674, 157679, 157687, 157692, 157697, 157702, 157707, 157712, - 157717, 157722, 157731, 157736, 157741, 157746, 157751, 157756, 157763, - 157768, 157775, 157780, 157785, 157790, 157795, 157800, 157805, 157810, - 157815, 157820, 157825, 157830, 157835, 157840, 157845, 157850, 157855, - 157860, 157865, 157870, 157879, 157884, 157889, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 157894, 157902, 157910, 157918, 157926, 157934, 157942, 157950, - 157958, 157966, 157974, 157982, 157990, 157998, 158006, 158014, 158022, - 158030, 158038, 158043, 158048, 158053, 158058, 158063, 158067, 0, 0, 0, - 0, 0, 0, 0, 158071, 158075, 158080, 158085, 158090, 158094, 158099, - 158104, 158109, 158113, 158118, 158123, 158127, 158132, 158137, 158141, - 158146, 158151, 158155, 158160, 158165, 158169, 158174, 158179, 158184, - 158189, 158194, 158198, 158203, 158208, 158213, 158217, 158222, 158227, - 158232, 158236, 158241, 158246, 158250, 158255, 158260, 158264, 158269, - 158274, 158278, 158283, 158288, 158292, 158297, 158302, 158307, 158312, - 158317, 158321, 158326, 158331, 158336, 158340, 158345, 158350, 158355, - 158359, 158364, 158369, 158373, 158378, 158383, 158387, 158392, 158397, - 158401, 158406, 158411, 158415, 158420, 158425, 158430, 158435, 158440, - 158444, 158449, 158454, 158459, 158463, 158468, 0, 158473, 158477, - 158482, 158487, 158491, 158496, 158501, 158505, 158510, 158515, 158519, - 158524, 158529, 158533, 158538, 158543, 158548, 158553, 158558, 158563, - 158569, 158575, 158581, 158586, 158592, 158598, 158604, 158609, 158615, - 158621, 158626, 158632, 158638, 158643, 158649, 158655, 158660, 158666, - 158672, 158677, 158683, 158689, 158695, 158701, 158707, 158712, 158718, - 158724, 158730, 158735, 158741, 158747, 158753, 158758, 158764, 158770, - 158775, 158781, 158787, 158792, 158798, 158804, 158809, 158815, 158821, - 158826, 158832, 158838, 158844, 158850, 158856, 0, 158860, 158865, 0, 0, - 158870, 0, 0, 158875, 158880, 0, 0, 158885, 158890, 158894, 158899, 0, - 158904, 158909, 158914, 158918, 158923, 158928, 158933, 158938, 158943, - 158947, 158952, 158957, 0, 158962, 0, 158967, 158972, 158976, 158981, - 158986, 158990, 158995, 0, 159000, 159005, 159010, 159014, 159019, - 159024, 159028, 159033, 159038, 159043, 159048, 159053, 159058, 159064, - 159070, 159076, 159081, 159087, 159093, 159099, 159104, 159110, 159116, - 159121, 159127, 159133, 159138, 159144, 159150, 159155, 159161, 159167, - 159172, 159178, 159184, 159190, 159196, 159202, 159207, 159213, 159219, - 159225, 159230, 159236, 159242, 159248, 159253, 159259, 159265, 159270, - 159276, 159282, 159287, 159293, 159299, 159304, 159310, 159316, 159321, - 159327, 159333, 159339, 159345, 159351, 159356, 0, 159362, 159368, - 159373, 159379, 0, 0, 159385, 159391, 159397, 159402, 159408, 159414, - 159419, 159425, 0, 159431, 159437, 159443, 159448, 159454, 159460, - 159466, 0, 159472, 159477, 159483, 159489, 159495, 159500, 159506, - 159512, 159518, 159523, 159529, 159535, 159540, 159546, 159552, 159557, - 159563, 159569, 159574, 159580, 159586, 159591, 159597, 159603, 159609, - 159615, 159621, 159626, 0, 159632, 159638, 159643, 159649, 0, 159655, - 159660, 159666, 159672, 159677, 0, 159683, 0, 0, 0, 159688, 159694, - 159700, 159705, 159711, 159717, 159723, 0, 159729, 159734, 159740, - 159746, 159752, 159757, 159763, 159769, 159775, 159780, 159786, 159792, - 159797, 159803, 159809, 159814, 159820, 159826, 159831, 159837, 159843, - 159848, 159854, 159860, 159866, 159872, 159878, 159884, 159891, 159898, - 159905, 159911, 159918, 159925, 159932, 159938, 159945, 159952, 159958, - 159965, 159972, 159978, 159985, 159992, 159998, 160005, 160012, 160018, - 160025, 160032, 160039, 160046, 160053, 160059, 160066, 160073, 160080, - 160086, 160093, 160100, 160107, 160113, 160120, 160127, 160133, 160140, - 160147, 160153, 160160, 160167, 160173, 160180, 160187, 160193, 160200, - 160207, 160214, 160221, 160228, 160232, 160237, 160242, 160247, 160251, - 160256, 160261, 160266, 160270, 160275, 160280, 160284, 160289, 160294, - 160298, 160303, 160308, 160312, 160317, 160322, 160326, 160331, 160336, - 160341, 160346, 160351, 160355, 160360, 160365, 160370, 160374, 160379, - 160384, 160389, 160393, 160398, 160403, 160407, 160412, 160417, 160421, - 160426, 160431, 160435, 160440, 160445, 160449, 160454, 160459, 160464, - 160469, 160474, 160479, 160485, 160491, 160497, 160502, 160508, 160514, - 160520, 160525, 160531, 160537, 160542, 160548, 160554, 160559, 160565, - 160571, 160576, 160582, 160588, 160593, 160599, 160605, 160611, 160617, - 160623, 160628, 160634, 160640, 160646, 160651, 160657, 160663, 160669, - 160674, 160680, 160686, 160691, 160697, 160703, 160708, 160714, 160720, - 160725, 160731, 160737, 160742, 160748, 160754, 160760, 160766, 160772, - 160777, 160783, 160789, 160795, 160800, 160806, 160812, 160818, 160823, - 160829, 160835, 160840, 160846, 160852, 160857, 160863, 160869, 160874, - 160880, 160886, 160891, 160897, 160903, 160909, 160915, 160921, 160926, - 160932, 160938, 160944, 160949, 160955, 160961, 160967, 160972, 160978, - 160984, 160989, 160995, 161001, 161006, 161012, 161018, 161023, 161029, - 161035, 161040, 161046, 161052, 161058, 161064, 161070, 161076, 161083, - 161090, 161097, 161103, 161110, 161117, 161124, 161130, 161137, 161144, - 161150, 161157, 161164, 161170, 161177, 161184, 161190, 161197, 161204, - 161210, 161217, 161224, 161231, 161238, 161245, 161251, 161258, 161265, - 161272, 161278, 161285, 161292, 161299, 161305, 161312, 161319, 161325, - 161332, 161339, 161345, 161352, 161359, 161365, 161372, 161379, 161385, - 161392, 161399, 161406, 161413, 161420, 161425, 161431, 161437, 161443, - 161448, 161454, 161460, 161466, 161471, 161477, 161483, 161488, 161494, - 161500, 161505, 161511, 161517, 161522, 161528, 161534, 161539, 161545, - 161551, 161557, 161563, 161569, 161574, 161580, 161586, 161592, 161597, - 161603, 161609, 161615, 161620, 161626, 161632, 161637, 161643, 161649, - 161654, 161660, 161666, 161671, 161677, 161683, 161688, 161694, 161700, - 161706, 161712, 161718, 161724, 0, 0, 161731, 161736, 161741, 161746, - 161751, 161756, 161761, 161766, 161771, 161776, 161781, 161786, 161791, - 161796, 161801, 161806, 161811, 161816, 161822, 161827, 161832, 161837, - 161842, 161847, 161852, 161857, 161861, 161866, 161871, 161876, 161881, - 161886, 161891, 161896, 161901, 161906, 161911, 161916, 161921, 161926, - 161931, 161936, 161941, 161946, 161952, 161957, 161962, 161967, 161972, - 161977, 161982, 161987, 161993, 161998, 162003, 162008, 162013, 162018, - 162023, 162028, 162033, 162038, 162043, 162048, 162053, 162058, 162063, - 162068, 162073, 162078, 162083, 162088, 162093, 162098, 162103, 162108, - 162114, 162119, 162124, 162129, 162134, 162139, 162144, 162149, 162153, - 162158, 162163, 162168, 162173, 162178, 162183, 162188, 162193, 162198, - 162203, 162208, 162213, 162218, 162223, 162228, 162233, 162238, 162244, - 162249, 162254, 162259, 162264, 162269, 162274, 162279, 162285, 162290, - 162295, 162300, 162305, 162310, 162315, 162321, 162327, 162333, 162339, - 162345, 162351, 162357, 162363, 162369, 162375, 162381, 162387, 162393, - 162399, 162405, 162411, 162417, 162424, 162430, 162436, 162442, 162448, - 162454, 162460, 162466, 162471, 162477, 162483, 162489, 162495, 162501, - 162507, 162513, 162519, 162525, 162531, 162537, 162543, 162549, 162555, - 162561, 162567, 162573, 162580, 162586, 162592, 162598, 162604, 162610, - 162616, 162622, 162629, 162635, 162641, 162647, 162653, 162659, 162665, - 162671, 162677, 162683, 162689, 162695, 162701, 162707, 162713, 162719, - 162725, 162731, 162737, 162743, 162749, 162755, 162761, 162767, 162774, - 162780, 162786, 162792, 162798, 162804, 162810, 162816, 162821, 162827, - 162833, 162839, 162845, 162851, 162857, 162863, 162869, 162875, 162881, - 162887, 162893, 162899, 162905, 162911, 162917, 162923, 162930, 162936, - 162942, 162948, 162954, 162960, 162966, 162972, 162979, 162985, 162991, - 162997, 163003, 163009, 163015, 163022, 163029, 163036, 163043, 163050, - 163057, 163064, 163071, 163078, 163085, 163092, 163099, 163106, 163113, - 163120, 163127, 163134, 163142, 163149, 163156, 163163, 163170, 163177, - 163184, 163191, 163197, 163204, 163211, 163218, 163225, 163232, 163239, - 163246, 163253, 163260, 163267, 163274, 163281, 163288, 163295, 163302, - 163309, 163316, 163324, 163331, 163338, 163345, 163352, 163359, 163366, - 163373, 163381, 163388, 163395, 163402, 163409, 163416, 163423, 163428, - 0, 0, 163433, 163438, 163442, 163446, 163450, 163454, 163458, 163462, - 163466, 163470, 163474, 163480, 163485, 163490, 163495, 163500, 163505, - 163510, 163515, 163520, 163525, 163530, 163534, 163538, 163542, 163546, - 163550, 163554, 163558, 163562, 163566, 163572, 163577, 163582, 163587, - 163592, 163597, 163602, 163607, 163612, 163617, 163623, 163628, 163633, - 163638, 163643, 163648, 163653, 163658, 163663, 163668, 163672, 163677, - 163682, 163687, 163692, 163697, 163702, 163708, 163716, 163723, 163728, - 163733, 163740, 163746, 163751, 163757, 163763, 163771, 163777, 163784, - 163792, 163798, 163807, 163816, 163824, 163832, 163838, 163845, 163853, - 163861, 163867, 163874, 163883, 163892, 163899, 163910, 163920, 163930, - 163940, 163950, 163957, 163964, 163971, 163978, 163987, 163996, 164007, - 164018, 164027, 164036, 164047, 164056, 164065, 164076, 164085, 164094, - 164102, 164110, 164121, 164132, 164140, 164149, 164158, 164165, 164176, - 164187, 164196, 164205, 164212, 164221, 164230, 164239, 164250, 164259, - 164269, 164278, 164287, 164298, 164311, 164326, 164337, 164350, 164362, - 164371, 164382, 164393, 164402, 164413, 164427, 164442, 164445, 164454, - 164459, 164465, 164473, 164479, 164485, 164494, 164501, 164511, 164523, - 164530, 164533, 164539, 164546, 164552, 164557, 164560, 164565, 164568, - 164576, 164582, 164591, 164598, 164606, 164612, 164617, 164620, 164623, - 164626, 164632, 164639, 164645, 164650, 164658, 164661, 164666, 164674, - 164680, 164689, 164696, 164706, 164715, 164718, 164724, 164731, 164738, - 164745, 164750, 164758, 164766, 164775, 164781, 164790, 164799, 164808, - 164814, 164823, 164830, 164837, 164844, 164852, 164858, 164866, 164872, - 164879, 164886, 164894, 164905, 164915, 164921, 164928, 164935, 164942, - 164948, 164955, 164962, 164967, 164974, 164982, 164991, 164997, 165009, - 165020, 165026, 165034, 165040, 165047, 165054, 165061, 165067, 165074, - 165083, 165089, 165095, 165102, 165109, 165117, 165127, 165137, 165147, - 165157, 165165, 165173, 165183, 165191, 165196, 165201, 165206, 165212, - 165219, 165226, 165232, 165238, 165243, 165250, 165258, 165268, 165276, - 165284, 165294, 165304, 165312, 165322, 165332, 165344, 165356, 165368, - 165378, 165384, 165390, 165397, 165406, 165415, 165424, 165433, 165443, - 165452, 165461, 165470, 165475, 165481, 165490, 165500, 165509, 165515, - 165521, 165528, 165535, 165542, 165548, 165555, 165562, 165569, 165575, - 165579, 165584, 165591, 165598, 165605, 165610, 165618, 165626, 165635, - 165643, 165650, 165658, 165667, 165677, 165680, 165684, 165689, 165694, - 165699, 165704, 165709, 165714, 165719, 165724, 165729, 165734, 165739, - 165744, 165749, 165754, 165759, 165764, 165769, 165776, 165782, 165789, - 165795, 165800, 165807, 165813, 165820, 165826, 165831, 165838, 165845, - 165852, 165858, 165864, 165873, 165882, 165892, 165899, 165906, 165915, - 165924, 165933, 165942, 165951, 165957, 165965, 165971, 165981, 165986, - 165995, 166004, 166011, 166022, 166029, 166036, 166043, 166050, 166057, - 166064, 166071, 166078, 166085, 166092, 166098, 166104, 166110, 166117, - 166124, 166131, 166138, 166145, 166152, 166159, 166166, 166173, 166180, - 166187, 166194, 166199, 166208, 166217, 166226, 166233, 166240, 166247, - 166254, 166261, 166268, 166275, 166282, 166291, 166300, 166309, 166318, - 166327, 166336, 166345, 166354, 166363, 166372, 166381, 166390, 166399, - 166405, 166413, 166419, 166429, 166434, 166443, 166452, 166461, 166472, - 166477, 166484, 166491, 166498, 166503, 166509, 166515, 166521, 166528, - 166535, 166542, 166549, 166556, 166563, 166570, 166577, 166584, 166591, - 166598, 166605, 166610, 166619, 166628, 166637, 166646, 166655, 166664, - 166673, 166682, 166693, 166704, 166711, 166718, 166725, 166732, 166739, - 166746, 166754, 166764, 166774, 166784, 166795, 166806, 166817, 166826, - 166835, 166844, 166849, 166854, 166859, 166864, 166875, 166886, 166897, - 166908, 166919, 166929, 166940, 166949, 166958, 166967, 166976, 166985, - 166993, 167002, 167013, 167024, 167035, 167046, 167057, 167069, 167082, - 167094, 167107, 167119, 167132, 167144, 167157, 167168, 167179, 167188, - 167196, 167205, 167216, 167227, 167239, 167252, 167266, 167281, 167293, - 167306, 167318, 167331, 167342, 167353, 167362, 167370, 167379, 167386, - 167393, 167400, 167407, 167414, 167421, 167428, 167435, 167442, 167449, - 167454, 167459, 167464, 167471, 167481, 167492, 167502, 167513, 167527, - 167542, 167557, 167571, 167586, 167601, 167612, 167623, 167636, 167649, - 167658, 167667, 167680, 167693, 167700, 167707, 167712, 167717, 167722, - 167727, 167732, 167739, 167748, 167753, 167756, 167761, 167768, 167775, - 167782, 167789, 167796, 167803, 167816, 167830, 167845, 167852, 167859, - 167866, 167875, 167883, 167891, 167900, 167905, 167910, 167915, 167920, - 167925, 167930, 167937, 167944, 167950, 167957, 167963, 167970, 167975, - 167980, 167985, 167990, 167995, 168002, 168009, 168014, 168021, 168028, - 168033, 168038, 168043, 168048, 168053, 168058, 168065, 168072, 168079, - 168082, 168087, 168092, 168097, 168102, 168109, 168116, 168124, 168132, - 168137, 168142, 168149, 168156, 168163, 168168, 168175, 168182, 168187, - 168194, 168201, 168208, 168215, 168222, 168229, 168238, 168247, 168254, - 168263, 168272, 168277, 168284, 168291, 168296, 168303, 168310, 168317, - 168324, 168331, 168336, 168343, 168350, 168359, 168366, 168375, 168386, - 168395, 168404, 168413, 168422, 168425, 168430, 168437, 168446, 168453, - 168462, 168469, 168474, 168479, 168482, 168485, 168488, 168495, 168502, - 168511, 168520, 168529, 168536, 168543, 168548, 168560, 168565, 168570, - 168575, 168580, 168585, 168590, 168595, 168600, 168603, 168608, 168613, - 168618, 168623, 168628, 168635, 168640, 168647, 168650, 168655, 168658, - 168661, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 168664, 168669, - 168674, 168679, 168684, 0, 168689, 168694, 168699, 168704, 168709, - 168714, 168719, 168724, 168729, 168734, 168739, 168744, 168749, 168754, - 168759, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 168764, 168774, 168782, 168789, 168796, - 168805, 168814, 168823, 168830, 168844, 168856, 168866, 168874, 168886, - 168895, 168906, 168915, 168922, 168930, 168941, 168953, 168962, 168972, - 168984, 168995, 169004, 169015, 169027, 169035, 169046, 169055, 0, 0, 0, - 0, 0, 0, 169063, 169073, 169083, 169093, 169103, 169113, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 169123, 169128, 169133, 169138, 169143, 169148, - 169153, 0, 169158, 169163, 169168, 169174, 169178, 169183, 169188, - 169193, 169198, 169203, 169208, 169213, 169218, 169223, 169228, 169233, - 169238, 0, 0, 169243, 169248, 169253, 169258, 169263, 169268, 169273, 0, - 169278, 169283, 0, 169289, 169294, 169302, 169309, 169318, 0, 0, 0, 0, 0, - 169323, 169328, 169334, 169340, 169346, 169352, 169358, 169364, 169370, - 169375, 169380, 169386, 169392, 169397, 169403, 169409, 169415, 169421, - 169426, 169432, 169437, 169443, 169449, 169455, 169461, 169466, 169472, - 169478, 169484, 169491, 169497, 169504, 169511, 169517, 169523, 169530, - 169537, 169544, 169551, 169558, 169565, 169572, 169578, 169584, 169591, - 169597, 169604, 169611, 169617, 169624, 169630, 169637, 169644, 169651, - 169659, 169666, 169676, 169684, 169691, 169698, 169707, 169718, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 169727, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 169734, 169741, 169749, 169757, 169765, 169772, 169779, 169787, 169795, - 169803, 169810, 169817, 169825, 169833, 169841, 169848, 169856, 169864, - 169872, 169880, 169888, 169896, 169904, 169911, 169919, 169926, 169934, - 169941, 169949, 169957, 169965, 169973, 169981, 169989, 169997, 170005, - 170013, 170020, 170028, 170035, 170042, 170049, 170057, 170064, 170072, - 0, 0, 0, 170080, 170087, 170094, 170101, 170108, 170115, 170122, 170129, - 170138, 170147, 170156, 170165, 170174, 170184, 0, 0, 170192, 170200, - 170207, 170214, 170221, 170228, 170235, 170242, 170249, 170256, 0, 0, 0, - 0, 170263, 170272, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 170280, - 170284, 170289, 170294, 170299, 170303, 170308, 170312, 170316, 170321, - 170325, 170330, 170334, 170339, 170344, 170348, 170352, 170356, 170360, - 170366, 170371, 170378, 170382, 170386, 170392, 170397, 170404, 170408, - 170413, 170420, 170424, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 170431, 170436, 170440, 170445, 170450, 170455, 170460, 170464, - 170469, 170473, 170477, 170481, 170486, 170491, 170496, 170500, 170505, - 170510, 170515, 170520, 170525, 170529, 170533, 170538, 170542, 170546, - 170551, 170555, 170559, 170563, 170568, 170572, 170577, 170582, 170587, - 170592, 170597, 170602, 170607, 170612, 170617, 170622, 170627, 170632, - 170637, 170642, 170647, 170652, 170657, 170662, 170666, 170670, 170674, - 170678, 170682, 170686, 170690, 170694, 0, 0, 0, 0, 0, 170698, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 170703, 170709, 170716, 170723, 170730, 170737, 170743, - 170750, 170757, 170764, 170771, 170777, 170784, 170791, 170798, 170805, - 170811, 170818, 170825, 170832, 170839, 170845, 170852, 170859, 170866, - 170873, 170880, 170887, 170894, 170901, 170908, 170915, 170922, 170929, - 170935, 170941, 170947, 170953, 170959, 170965, 170971, 170977, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 170983, 170987, 170991, 170995, 170999, 171003, 171007, 0, - 171011, 171017, 171021, 171025, 0, 171029, 171035, 0, 171041, 171047, - 171053, 171059, 171065, 171071, 171077, 171083, 171089, 171095, 171101, - 171107, 171113, 171119, 171125, 0, 171131, 171138, 171144, 171151, - 171158, 171165, 171172, 171179, 171186, 171193, 171200, 171207, 171214, - 171221, 171228, 171235, 171242, 171249, 171256, 171263, 171270, 171277, - 171284, 171291, 171298, 171305, 171312, 171319, 171326, 171333, 171340, - 171347, 171354, 171361, 171368, 171374, 171380, 171386, 171393, 171399, - 171406, 171412, 171419, 171426, 171433, 171440, 171447, 171454, 171460, - 171467, 171474, 171481, 171488, 171495, 171502, 171509, 171515, 171522, - 171529, 171536, 171543, 171550, 171558, 171565, 171572, 171579, 171586, - 171593, 171600, 171607, 171614, 171621, 171628, 171635, 171642, 171648, - 171655, 171662, 171669, 171676, 171683, 171690, 171697, 171705, 171712, - 171718, 171725, 171732, 171739, 171746, 171753, 171760, 171767, 171774, - 171781, 171788, 171795, 171802, 171809, 171816, 171823, 171830, 171837, - 171844, 171851, 171858, 171864, 171871, 171878, 171885, 171892, 171899, - 171906, 171913, 171920, 171927, 171934, 171941, 171948, 171955, 171962, - 171969, 171976, 171983, 171990, 171997, 172004, 172011, 172018, 172026, - 172034, 172042, 172049, 172056, 172063, 172070, 172077, 172084, 172091, - 172098, 172105, 172112, 172118, 172125, 172132, 172139, 172146, 172153, - 172160, 172167, 172174, 172181, 172188, 172195, 172202, 172209, 172216, - 172224, 172232, 172240, 172247, 172254, 172261, 172268, 172275, 172282, - 172289, 172296, 172303, 172310, 172317, 172324, 172331, 172338, 172344, - 172351, 172358, 172365, 172372, 172379, 172386, 172393, 172400, 172407, - 172414, 172421, 172428, 172435, 172442, 172449, 172456, 172463, 172470, - 172477, 172484, 172491, 172498, 0, 0, 172505, 172509, 172513, 172517, - 172521, 172525, 172529, 172533, 172537, 172541, 172547, 172553, 172559, - 172565, 172573, 172581, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 172587, 172593, 172599, 172605, 172611, 172617, 172623, 172629, - 172635, 172640, 172645, 172651, 172656, 172661, 172667, 172673, 172679, - 172685, 172691, 172696, 172701, 172707, 172713, 172718, 172724, 172730, - 172736, 172742, 172748, 172754, 172760, 172766, 172772, 172778, 172784, - 172790, 172796, 172802, 172808, 172814, 172820, 172826, 172832, 172837, - 172842, 172848, 172853, 172858, 172864, 172870, 172876, 172882, 172888, - 172893, 172898, 172904, 172910, 172915, 172921, 172927, 172933, 172939, - 172945, 172951, 172957, 172963, 172969, 172975, 172981, 172987, 172992, - 172997, 173001, 173006, 173013, 173017, 0, 0, 0, 0, 173022, 173027, - 173031, 173035, 173039, 173043, 173047, 173051, 173055, 173059, 0, 0, 0, - 0, 173063, 173069, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 173075, 173080, 173085, 173090, 173095, 173100, - 173105, 173110, 173115, 173120, 173126, 173132, 173138, 173144, 173150, - 173156, 173162, 173168, 173174, 173181, 173188, 173195, 173203, 173211, - 173219, 173227, 173235, 173243, 173249, 173255, 173261, 173268, 173275, - 173282, 173289, 173296, 173303, 173310, 173317, 173324, 173331, 173338, - 173345, 173352, 173359, 173366, 173372, 173378, 173384, 173390, 173396, - 173403, 173410, 173417, 173424, 173431, 173438, 173445, 173452, 173459, - 173464, 173472, 173480, 173488, 173494, 173501, 173508, 173517, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 173525, 173530, 173535, 173540, 173545, 173550, 173555, 173560, - 173565, 173570, 173576, 173582, 173588, 173594, 173600, 173606, 173612, - 173618, 173624, 173631, 173638, 173645, 173653, 173661, 173669, 173677, - 173685, 173693, 173699, 173705, 173711, 173718, 173725, 173732, 173739, - 173746, 173753, 173760, 173767, 173774, 173781, 173788, 173795, 173802, - 173809, 173816, 173821, 173828, 173835, 173842, 173849, 173856, 173863, - 173870, 173877, 173885, 173895, 173905, 173913, 173922, 173930, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 173938, 173942, 173946, - 173950, 0, 173954, 173958, 173962, 173966, 173970, 173974, 173978, - 173982, 173986, 173990, 173994, 173998, 174002, 174006, 174010, 174014, - 174018, 174022, 174026, 174030, 174034, 174038, 174042, 174046, 174052, - 174058, 174064, 0, 174070, 174075, 0, 174080, 0, 0, 174085, 0, 174090, - 174095, 174100, 174105, 174110, 174115, 174120, 174125, 174130, 174135, - 0, 174140, 174145, 174150, 174155, 0, 174160, 0, 174165, 0, 0, 0, 0, 0, - 0, 174170, 0, 0, 0, 0, 174176, 0, 174182, 0, 174188, 0, 174194, 174200, - 174206, 0, 174212, 174218, 0, 174224, 0, 0, 174230, 0, 174236, 0, 174242, - 0, 174248, 0, 174256, 0, 174264, 174270, 0, 174276, 0, 0, 174282, 174288, - 174294, 174300, 0, 174306, 174312, 174318, 174324, 174330, 174336, - 174342, 0, 174348, 174354, 174360, 174366, 0, 174372, 174378, 174384, - 174390, 0, 174398, 0, 174406, 174412, 174418, 174424, 174430, 174436, - 174442, 174448, 174454, 174460, 0, 174466, 174472, 174478, 174484, - 174490, 174496, 174502, 174508, 174514, 174520, 174526, 174532, 174538, - 174544, 174550, 174556, 174562, 0, 0, 0, 0, 0, 174568, 174574, 174580, 0, - 174586, 174592, 174598, 174604, 174610, 0, 174616, 174622, 174628, - 174634, 174640, 174646, 174652, 174658, 174664, 174670, 174676, 174682, - 174688, 174694, 174700, 174706, 174712, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 174718, 174728, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 174736, 174743, 174750, 174757, - 174763, 174770, 174777, 174783, 174790, 174797, 174804, 174812, 174820, - 174828, 174836, 174844, 174852, 174859, 174866, 174873, 174881, 174889, - 174897, 174905, 174913, 174921, 174928, 174935, 174942, 174950, 174958, - 174966, 174974, 174982, 174990, 174995, 175000, 175005, 175010, 175015, - 175020, 175025, 175030, 175035, 0, 0, 0, 0, 175040, 175047, 175052, - 175057, 175062, 175067, 175072, 175077, 175082, 175087, 175092, 175097, - 175102, 175107, 175112, 175117, 175122, 175127, 175132, 175137, 175142, - 175147, 175152, 175157, 175162, 175167, 175172, 175177, 175182, 175187, - 175192, 175197, 175202, 175207, 175212, 175217, 175222, 175227, 175232, - 175237, 175242, 175247, 175252, 175257, 175262, 175267, 175272, 175277, - 175282, 175287, 175292, 175298, 175303, 175308, 175313, 175318, 175323, - 175328, 175333, 175338, 175343, 175348, 175353, 175358, 175363, 175368, - 175373, 175378, 175383, 175388, 175393, 175398, 175403, 175408, 175413, - 175418, 175423, 175428, 175433, 175438, 175443, 175448, 175453, 175458, - 175463, 175468, 175473, 175478, 175483, 175488, 175493, 175498, 175503, - 175508, 175513, 175518, 175523, 175528, 175533, 175538, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 175543, 175549, 175558, 175566, 175574, 175583, 175592, - 175601, 175610, 175619, 175628, 175637, 175646, 175655, 175664, 0, 0, - 175673, 175682, 175690, 175698, 175707, 175716, 175725, 175734, 175743, - 175752, 175761, 175770, 175779, 175788, 175797, 0, 175805, 175814, - 175822, 175830, 175839, 175848, 175857, 175866, 175875, 175884, 175893, - 175902, 175911, 175920, 175929, 0, 175936, 175945, 175953, 175961, - 175970, 175979, 175988, 175997, 176006, 176015, 176024, 176033, 176042, - 176051, 176060, 176067, 176073, 176079, 176085, 176091, 176097, 176103, - 176109, 176115, 176121, 176127, 176133, 176139, 176145, 176151, 176157, - 176163, 176169, 176175, 176181, 176187, 176193, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 176199, 176206, 176211, 176215, 176219, 176223, 176228, 176233, - 176238, 176243, 176248, 176253, 176260, 176269, 176275, 176279, 176288, - 176293, 176299, 176305, 176311, 176316, 176322, 176328, 176334, 176339, - 176345, 176351, 176356, 176362, 176368, 176373, 176379, 176385, 176390, - 176396, 176402, 176407, 176413, 176419, 176425, 176431, 176437, 176448, - 176455, 176461, 176464, 176467, 176470, 176475, 176481, 176487, 176493, - 176498, 176504, 176510, 176516, 176521, 176527, 176533, 176538, 176544, - 176550, 176555, 176561, 176567, 176572, 176578, 176584, 176589, 176595, - 176601, 176607, 176613, 176619, 176622, 176625, 176628, 176631, 176634, - 176637, 176644, 176652, 176660, 176668, 176675, 176683, 176691, 176699, - 176706, 176714, 176722, 176729, 176737, 176745, 176752, 176760, 176768, - 176775, 176783, 176791, 176798, 176806, 176814, 176822, 176830, 176838, - 176843, 176848, 176853, 176856, 176864, 176869, 176876, 176884, 176892, - 176900, 176907, 176915, 176923, 176931, 176938, 176946, 176954, 176961, - 176969, 176977, 176984, 176992, 177000, 177007, 177015, 177023, 177030, - 177038, 177046, 177054, 177062, 177070, 177080, 177085, 177089, 177093, - 177098, 177103, 177106, 177109, 177112, 177115, 177118, 177121, 177124, - 177127, 177130, 177136, 177139, 177143, 177148, 177152, 177157, 177162, - 177168, 177174, 177180, 177185, 177193, 177199, 177202, 177205, 177208, - 177211, 177214, 177217, 177220, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 177225, 177232, - 177240, 177248, 177256, 177263, 177271, 177279, 177287, 177294, 177302, - 177310, 177317, 177325, 177333, 177340, 177348, 177356, 177363, 177371, - 177379, 177386, 177394, 177402, 177410, 177418, 177426, 177431, 177435, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 177438, 177444, 177450, 177456, - 177460, 177466, 177472, 177478, 177484, 177490, 177496, 177502, 177508, - 177514, 177520, 177526, 177532, 177538, 177544, 177550, 177556, 177562, - 177568, 177574, 177580, 177586, 177592, 177598, 177604, 177610, 177616, - 177622, 177628, 177634, 177640, 177646, 177652, 177658, 177664, 177670, - 177676, 177682, 177688, 177694, 0, 0, 0, 0, 177700, 177711, 177722, - 177733, 177744, 177755, 177766, 177777, 177788, 0, 0, 0, 0, 0, 0, 0, - 177799, 177804, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 177809, 177815, - 177821, 177827, 177833, 177839, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 177845, 177847, 177849, 177853, - 177858, 177863, 177865, 177871, 177876, 177878, 177884, 177888, 177890, - 177894, 177900, 177906, 177912, 177917, 177922, 177929, 177936, 177943, - 177948, 177955, 177962, 177969, 177973, 177980, 177989, 177998, 178005, - 178010, 178014, 178018, 178020, 178023, 178026, 178033, 178040, 178050, - 178055, 178060, 178065, 178070, 178072, 178078, 178082, 178084, 178086, - 178088, 178090, 178094, 178098, 178102, 178104, 178108, 178110, 178114, - 178116, 178118, 178120, 178122, 178127, 178132, 178134, 178140, 178144, - 178148, 178156, 178158, 178160, 178162, 178164, 178166, 178168, 178170, - 178172, 178174, 178176, 178180, 178184, 178186, 178188, 178190, 178192, - 178194, 178199, 178205, 178209, 178213, 178217, 178221, 178226, 178230, - 178232, 178234, 178238, 178244, 178246, 178248, 178250, 178254, 178263, - 178269, 178273, 178277, 178279, 178281, 178284, 178286, 178288, 178290, - 178294, 178296, 178300, 178305, 178307, 178312, 178318, 178325, 178329, - 178333, 178337, 178341, 178347, 178351, 178359, 178366, 178368, 178370, - 178374, 178378, 178380, 178384, 178388, 178390, 178394, 178396, 178400, - 178404, 178408, 178412, 178416, 178420, 178424, 178428, 178434, 178438, - 178442, 178453, 178458, 178462, 178466, 178472, 178476, 178480, 178484, - 178491, 178498, 178502, 178506, 178510, 178514, 178518, 178525, 178527, - 178531, 178533, 178535, 178539, 178543, 178547, 178549, 178553, 178557, - 178561, 178565, 178569, 178571, 178575, 178577, 178583, 178586, 178591, - 178593, 178595, 178598, 178600, 178602, 178605, 178612, 178619, 178626, - 178631, 178635, 178637, 178639, 178641, 178645, 178647, 178651, 178655, - 178659, 178661, 178665, 178667, 178671, 178675, 178682, 178684, 178693, - 178702, 178711, 178717, 178719, 178724, 178728, 178732, 178734, 178740, - 178744, 178746, 178750, 178754, 178756, 178760, 178765, 178769, 178775, - 178781, 178783, 178785, 178791, 178793, 178797, 178801, 178803, 178807, - 178809, 178813, 178817, 178821, 178824, 178827, 178832, 178837, 178839, - 178842, 178844, 178851, 178855, 178857, 178864, 178871, 178878, 178885, - 178892, 178894, 178896, 178898, 178902, 178904, 178906, 178908, 178910, - 178912, 178914, 178916, 178918, 178920, 178922, 178924, 178926, 178928, - 178930, 178932, 178934, 178936, 178938, 178940, 178942, 178944, 178946, - 178950, 178952, 178954, 178956, 178960, 178962, 178966, 178968, 178970, - 178974, 178978, 178984, 178986, 178988, 178990, 178992, 178996, 179000, - 179002, 179006, 179010, 179014, 179018, 179022, 179026, 179030, 179034, - 179038, 179042, 179046, 179050, 179054, 179058, 179062, 179066, 179070, - 179074, 179076, 179078, 179080, 179082, 179084, 179086, 179088, 179096, - 179104, 179112, 179120, 179125, 179130, 179135, 179139, 179143, 179148, - 179153, 179155, 179159, 179161, 179163, 179165, 179167, 179169, 179171, - 179173, 179177, 179179, 179181, 179183, 179187, 179191, 179195, 179199, - 179203, 179205, 179211, 179217, 179219, 179221, 179223, 179225, 179227, - 179236, 179243, 179250, 179254, 179261, 179266, 179273, 179282, 179287, - 179291, 179295, 179297, 179301, 179303, 179307, 179311, 179313, 179317, - 179321, 179325, 179327, 179329, 179335, 179337, 179339, 179341, 179345, - 179349, 179351, 179355, 179357, 179359, 179362, 179366, 179368, 179372, - 179374, 179376, 179381, 179383, 179387, 179391, 179394, 179398, 179402, - 179406, 179410, 179414, 179418, 179422, 179427, 179431, 179435, 179444, - 179449, 179452, 179454, 179457, 179460, 179465, 179467, 179470, 179475, - 179479, 179482, 179486, 179490, 179493, 179498, 179502, 179506, 179510, - 179514, 179520, 179526, 179532, 179538, 179543, 179554, 179556, 179560, - 179562, 179564, 179568, 179572, 179574, 179578, 179584, 179589, 179595, - 179597, 179601, 179605, 179612, 179619, 179623, 179625, 179627, 179631, - 179633, 179637, 179641, 179645, 179647, 179649, 179656, 179660, 179664, - 179668, 179672, 179676, 179678, 179682, 179684, 179686, 179690, 179692, - 179696, 179700, 179706, 179710, 179714, 179718, 179720, 179723, 179727, - 179734, 179743, 179752, 179761, 179770, 179772, 179776, 179778, 179782, - 179793, 179797, 179803, 179809, 179814, 179816, 179821, 179825, 179827, - 179829, 179831, 179835, 179839, 179843, 179848, 179859, 179875, 179888, - 179901, 179905, 179909, 179915, 179917, 179925, 179933, 179935, 179939, - 179945, 179951, 179958, 179965, 179967, 179969, 179973, 179975, 179981, - 179983, 179986, 179990, 179996, 180002, 180013, 180019, 180026, 180034, - 180038, 180046, 180054, 180060, 180066, 180073, 180075, 180079, 180081, - 180083, 180088, 180090, 180092, 180094, 180096, 180100, 180110, 180116, - 180120, 180124, 180128, 180134, 180140, 180146, 180152, 180157, 180162, - 180168, 180174, 180181, 180188, 180195, 180202, 180207, 180215, 180219, - 180228, 180237, 180243, 180247, 180251, 180255, 180258, 180263, 180265, - 180267, 180269, 180276, 180281, 180288, 180295, 180302, 180310, 180318, - 180326, 180334, 180342, 180350, 180358, 180366, 180374, 180380, 180386, - 180392, 180398, 180404, 180410, 180416, 180422, 180428, 180434, 180440, - 180446, 180449, 180458, 180467, 180469, 180476, 180480, 180482, 180484, - 180488, 180494, 180498, 180500, 180510, 180516, 180520, 180522, 180526, - 180528, 180532, 180539, 180546, 180553, 180558, 180563, 180572, 180578, - 180583, 180587, 180592, 180596, 180603, 180607, 180610, 180614, 180620, - 180626, 180630, 180634, 180639, 180645, 180654, 180665, 180671, 180677, - 180683, 180693, 180708, 180717, 180725, 180733, 180741, 180749, 180757, - 180765, 180773, 180781, 180789, 180797, 180805, 180813, 180816, 180820, - 180825, 180830, 180832, 180836, 180845, 180854, 180862, 180866, 180870, - 180875, 180880, 180885, 180887, 180892, 180896, 180898, 180902, 180906, - 180912, 180917, 180925, 180930, 180935, 180940, 180947, 180950, 180952, - 180956, 180961, 180967, 180971, 180975, 180981, 180987, 180989, 180993, - 180997, 181001, 181005, 181009, 181011, 181013, 181015, 181017, 181023, - 181029, 181033, 181035, 181037, 181039, 181048, 181052, 181059, 181066, - 181068, 181071, 181075, 181081, 181085, 181089, 181091, 181099, 181103, - 181107, 181112, 181116, 181121, 181126, 181131, 181136, 181141, 181146, - 181151, 181156, 181160, 181166, 181170, 181176, 181181, 181188, 181194, - 181202, 181206, 181213, 181217, 181221, 181225, 181230, 181235, 181237, - 181241, 181250, 181258, 181267, 181281, 181295, 181309, 181316, 181323, - 181327, 181336, 181344, 181348, 181357, 181364, 181368, 181372, 181376, - 181380, 181387, 181391, 181395, 181399, 181403, 181410, 181419, 181428, - 181435, 181447, 181459, 181463, 181467, 181471, 181475, 181479, 181483, - 181491, 181499, 181508, 181512, 181516, 181520, 181524, 181528, 181532, - 181538, 181545, 181549, 181561, 181569, 181573, 181577, 181581, 181585, - 181591, 181598, 181609, 181619, 181630, 181641, 181650, 181661, 181667, - 181673, 181679, 181685, 181691, 181695, 181702, 181711, 181718, 181724, - 181728, 181732, 181736, 181745, 181757, 181761, 181768, 181775, 181782, - 181790, 181797, 181805, 181813, 181822, 181830, 181839, 181848, 181858, - 181867, 181877, 181887, 181898, 181908, 181919, 181926, 181934, 181941, - 181949, 181957, 181966, 181974, 181983, 181990, 182002, 182009, 182021, - 182024, 182028, 182031, 182035, 182041, 182048, 182055, 182063, 182068, - 182074, 182085, 182095, 182106, 182111, 182116, 182122, 182127, 182134, - 182138, 182144, 182146, 182148, 182152, 182156, 182160, 182169, 182171, - 182173, 182176, 182178, 182180, 182184, 182186, 182190, 182192, 182196, - 182198, 182200, 182204, 182208, 182214, 182216, 182220, 182222, 182226, - 182230, 182234, 182238, 182240, 182242, 182246, 182250, 182254, 182258, - 182260, 182262, 182264, 182270, 182275, 182278, 182286, 182294, 182296, - 182301, 182304, 182309, 182320, 182327, 182332, 182337, 182339, 182343, - 182345, 182349, 182351, 182355, 182359, 182362, 182365, 182367, 182370, - 182372, 182376, 182378, 182380, 182382, 182386, 182388, 182392, 182395, - 182402, 182405, 182410, 182413, 182416, 182421, 182425, 182429, 182433, - 182435, 182440, 182443, 182447, 182449, 182451, 182455, 182457, 0, 0, 0, - 0, 182459, 182461, 182465, 182467, 182471, 182476, 182478, 182482, - 182484, 182488, 182492, 182498, 182502, 182507, 182510, 182514, 182518, - 0, 0, 0, 182522, 182524, 182530, 182534, 182538, 182540, 182544, 182546, - 182548, 182552, 182554, 182558, 182562, 0, 0, 0, 182566, 182571, 182576, - 182581, 182586, 182591, 182596, 182603, 182610, 182617, 182624, 182629, - 182634, 182639, 182644, 182651, 182657, 182664, 182671, 182678, 182683, - 182688, 182693, 182698, 182703, 182710, 182717, 182722, 182727, 182734, - 182741, 182749, 182757, 182764, 182771, 182779, 182787, 182795, 182802, - 182812, 182823, 182828, 182835, 182842, 182849, 182857, 182865, 182876, - 182884, 182892, 182900, 182905, 182910, 182915, 182920, 182925, 182930, - 182935, 182940, 182945, 182950, 182955, 182960, 182967, 182972, 182977, - 182984, 182989, 182994, 182999, 183004, 183009, 183014, 183019, 183024, - 183029, 183034, 183039, 183044, 183051, 183059, 183064, 183069, 183076, - 183081, 183086, 183091, 183098, 183103, 183110, 183115, 183122, 183127, - 183136, 183145, 183150, 183155, 183160, 183165, 183170, 183175, 183180, - 183185, 183190, 183195, 183200, 183205, 183210, 183218, 183226, 183231, - 183236, 183241, 183246, 183251, 183257, 183263, 183268, 183270, 0, 0, 0, - 0, 183274, 183276, 183278, 183280, 183282, 183284, 183292, 183300, - 183308, 183316, 183322, 183328, 183332, 183336, 183342, 183348, 183357, - 183361, 183366, 183372, 183376, 183381, 183385, 183389, 183395, 183401, - 183411, 183420, 183423, 183428, 183434, 183440, 183451, 183461, 183465, - 183470, 183476, 183482, 183491, 183496, 183500, 183505, 183509, 183515, - 183521, 183527, 183531, 183534, 183538, 183541, 183544, 183549, 183554, - 183561, 183569, 183576, 183583, 183592, 183601, 183608, 183616, 183623, - 183630, 183639, 183648, 183655, 183663, 183670, 183677, 183686, 183693, - 183701, 183707, 183716, 183724, 183733, 183740, 183750, 183761, 183769, - 183777, 183786, 183794, 183802, 183811, 183819, 183829, 183838, 183846, - 183854, 183863, 183866, 183871, 183874, 183879, 0, 0, 0, 0, 0, 0, 183886, - 183892, 183898, 183904, 183910, 183916, 183922, 183928, 183934, 183940, - 183946, 183952, 0, 0, 0, 0, 183958, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 183962, 183970, 183979, 183987, 183996, 184005, 184015, 184024, - 184034, 184043, 184053, 184062, 0, 0, 0, 0, 184072, 184080, 184089, - 184097, 184106, 184113, 184121, 184128, 184136, 184144, 184153, 184161, - 184170, 184180, 184191, 184201, 184212, 184221, 184231, 184240, 184250, - 184259, 184269, 184278, 184288, 184296, 184305, 184313, 184322, 184330, - 184339, 184347, 184356, 184366, 184377, 184387, 184398, 184402, 184407, - 184411, 184416, 184419, 184423, 184426, 184430, 184434, 184439, 184443, - 184448, 184453, 184459, 184464, 184470, 184473, 184477, 184480, 0, 0, 0, - 0, 0, 0, 0, 0, 184484, 184487, 184491, 184494, 184498, 184503, 184508, - 184514, 184520, 184524, 0, 0, 0, 0, 0, 0, 184528, 184534, 184541, 184547, - 184554, 184562, 184570, 184579, 184588, 184593, 184599, 184604, 184610, - 184617, 184624, 184632, 184640, 184647, 184655, 184662, 184670, 184679, - 184688, 184698, 184708, 184714, 184721, 184727, 184734, 184742, 184750, - 184759, 184768, 184776, 184785, 184793, 184802, 184812, 184822, 184833, - 0, 0, 0, 0, 0, 0, 0, 0, 184844, 184849, 184855, 184860, 184866, 184875, - 184885, 184894, 184904, 184911, 184919, 184926, 184934, 184941, 184950, - 184959, 184968, 184973, 184980, 184987, 184994, 184999, 185004, 185009, - 185014, 185021, 185028, 185035, 185042, 185049, 0, 0, 185058, 185068, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 185080, 185090, 185099, 185104, 185113, 185121, 185129, - 185136, 185140, 185145, 185152, 185161, 185172, 185176, 185179, 185183, - 185187, 185191, 185195, 185200, 185204, 185208, 185213, 185217, 185221, - 185227, 185233, 185240, 185244, 185248, 185250, 185260, 185269, 185276, - 185280, 185284, 185294, 185298, 185302, 185306, 185310, 185318, 185327, - 185340, 185351, 185362, 185378, 185387, 185396, 185400, 185402, 185407, - 185409, 185411, 185417, 185421, 185423, 185429, 185431, 185433, 185437, - 185439, 185443, 185445, 185449, 185453, 185458, 185462, 185466, 185468, - 185472, 185474, 185480, 185486, 185492, 185496, 185502, 185506, 185513, - 185515, 185519, 185521, 185523, 185525, 185527, 185529, 185531, 185535, - 185539, 185546, 185550, 185552, 185557, 185559, 185561, 185563, 185565, - 185569, 185573, 185575, 185580, 185585, 185587, 185589, 185591, 185593, - 185598, 185600, 185604, 185608, 185610, 185614, 185616, 185629, 185633, - 185640, 185652, 185664, 185668, 185672, 185674, 185678, 185686, 185693, - 185695, 185699, 185701, 185705, 185709, 185711, 185715, 185717, 185719, - 185723, 185725, 185727, 185729, 185731, 185733, 185737, 185739, 185741, - 185743, 185745, 185747, 185749, 185751, 185755, 185759, 185761, 185763, - 185765, 185767, 185769, 185771, 185773, 185775, 185777, 185779, 185781, - 185783, 185785, 185787, 185789, 185791, 185793, 185795, 185797, 185799, - 185801, 185803, 185805, 185807, 185809, 185811, 185815, 185819, 185827, - 185835, 185841, 185848, 185850, 185852, 185854, 185856, 185858, 185860, - 185864, 185871, 185875, 185879, 185883, 185887, 185891, 185893, 185897, - 185901, 185903, 185905, 185907, 185909, 185911, 185915, 185919, 185923, - 185925, 185929, 185933, 185937, 185942, 185944, 185946, 185950, 185954, - 185959, 185967, 185971, 185979, 185981, 185983, 185985, 185987, 185989, - 185991, 185993, 185995, 185999, 186003, 186005, 186007, 186009, 186011, - 186017, 186019, 186025, 186029, 186033, 186038, 186040, 186042, 186046, - 186048, 186050, 186052, 186054, 186058, 186063, 186068, 186072, 186076, - 186078, 186080, 186085, 186090, 186092, 186094, 186098, 186104, 186110, - 186116, 186122, 186128, 186134, 186145, 186156, 186168, 186179, 186190, - 186201, 186212, 186223, 186234, 186245, 186256, 186267, 186278, 186289, - 186300, 186312, 186324, 186336, 186348, 186360, 186372, 186386, 186400, - 186415, 186421, 186427, 186433, 186439, 186445, 186451, 186457, 186463, - 186469, 186475, 186481, 186487, 186494, 186501, 186508, 186515, 186522, - 186529, 186543, 186557, 186572, 186586, 186600, 186614, 186628, 186642, - 186656, 186670, 186684, 186698, 186712, 186726, 186740, 186755, 186770, - 186785, 186800, 186815, 186830, 186844, 186858, 186873, 186878, 186883, - 186889, 186900, 186911, 186923, 186928, 186933, 186938, 186943, 186948, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 186953, 186959, 186965, 186971, - 186977, 186983, 186989, 186995, 187000, 187005, 187010, 187015, 187020, - 187025, 0, 0, 187030, 187034, 187038, 187040, 187042, 187046, 187051, - 187055, 187059, 187064, 187068, 187070, 187072, 0, 0, 0, 187074, 187076, - 187078, 187080, 187082, 187086, 187088, 187092, 187094, 0, 0, 0, 0, 0, 0, - 0, 187096, 187100, 187102, 187104, 187106, 187110, 187112, 187116, - 187118, 187121, 187123, 187127, 187129, 187131, 187132, 187134, 187136, - 187138, 187142, 187144, 187146, 187150, 187152, 187154, 187156, 187158, - 187162, 187166, 187169, 187171, 187177, 187181, 187183, 187185, 187187, - 187189, 187191, 187195, 187197, 187199, 187201, 187203, 187207, 187212, - 187214, 187216, 0, 187218, 187220, 187224, 187226, 187230, 187234, - 187238, 0, 0, 0, 0, 0, 0, 0, 0, 187243, 187245, 187247, 187249, 187253, - 187255, 187257, 187259, 187261, 187263, 187267, 187269, 187271, 187275, - 0, 0, 0, 0, 187279, 187283, 187287, 187300, 187307, 187314, 187320, - 187324, 187326, 0, 0, 0, 0, 0, 0, 0, 187330, 187340, 187343, 187346, - 187351, 187356, 187365, 187369, 187374, 0, 0, 0, 0, 0, 0, 0, 187379, - 187382, 187385, 187388, 187391, 187394, 187397, 187400, 187403, 187406, - 187409, 187412, 187415, 187418, 187421, 187424, 187427, 187430, 187433, - 187436, 187439, 187442, 187445, 187448, 187451, 187454, 187457, 187460, - 187463, 187466, 187469, 187472, 187475, 187478, 187481, 187484, 187487, - 187490, 187493, 187496, 187499, 187502, 187505, 187508, 187511, 187514, - 187517, 187520, 187523, 187526, 187529, 187532, 187535, 187538, 187541, - 187544, 187547, 187550, 187553, 187556, 187559, 187571, 187582, 187594, - 187605, 187616, 187628, 187639, 187651, 187662, 187673, 187685, 187697, - 187708, 187720, 187731, 187742, 187754, 187765, 187777, 187788, 187799, - 187811, 187823, 187834, 187846, 187857, 187868, 187880, 187891, 187903, - 187914, 187925, 187937, 187949, 187960, 187972, 187983, 187994, 188006, - 188017, 188029, 188040, 188051, 188063, 188075, 188087, 188099, 188111, - 188119, 188127, 188135, 188143, 188149, 188155, 188161, 188167, 188173, - 188179, 188186, 188193, 188200, 188207, 188214, 188221, 188229, 188237, - 188245, 188253, 188261, 188268, 188274, 188280, 188287, 188293, 188300, - 188306, 188312, 188319, 188325, 188332, 188338, 188344, 188350, 188356, - 188362, 188374, 0, 188387, 188400, 188406, 188414, 188419, 188426, - 188433, 188441, 188449, 188457, 188465, 188473, 188481, 188493, 188504, - 188515, 188526, 188541, 188556, 188570, 188584, 188602, 188620, 188639, - 188657, 188675, 188693, 188700, 188708, 188712, 188717, 188723, 188729, - 188739, 188750, 188761, 188771, 188781, 188785, 188789, 188794, 188800, - 188806, 188816, 188822, 188831, 188840, 188849, 188858, 188864, 188868, - 188877, 188885, 188892, 188899, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 188904, 188909, 188913, 188917, 188921, 188925, 188929, 188933, 188937, - 188941, 0, 0, 0, 0, 0, 0, 188945, 188949, 188953, 188957, 188961, 188965, - 188969, 188973, 188977, 188981, 188985, 188989, 188993, 188997, 189001, - 189005, 189009, 189013, 189017, 189021, 189025, 189029, 189033, 189037, - 189041, 189045, 189049, 189053, 189057, 189061, 189065, 189069, 189073, - 189077, 189081, 189085, 189089, 189093, 189097, 189101, 189105, 189109, - 189113, 189117, 189121, 189125, 189129, 189133, 189137, 189141, 189145, - 189149, 189153, 189157, 189161, 189165, 189169, 189173, 189177, 189181, - 189185, 189189, 189193, 189197, 189201, 189205, 189209, 189213, 189217, - 189221, 189225, 189229, 189233, 189237, 189241, 189245, 189249, 189253, - 189257, 189261, 189265, 189269, 189273, 189277, 189281, 189285, 189289, - 189293, 189297, 189301, 189305, 189309, 189313, 189317, 189321, 189325, - 189329, 189333, 189337, 189341, 189345, 189349, 189353, 189357, 189361, - 189365, 189369, 189373, 189377, 189381, 189385, 189389, 189393, 189397, - 189401, 189405, 189409, 189413, 189417, 189421, 189425, 189429, 189433, - 189437, 189441, 189445, 189449, 189453, 189457, 189461, 189465, 189469, - 189473, 189477, 189481, 189485, 189489, 189493, 189497, 189501, 189505, - 189509, 189513, 189517, 189521, 189525, 189529, 189533, 189537, 189541, - 189545, 189549, 189553, 189557, 189561, 189565, 189569, 189573, 189577, - 189581, 189585, 189589, 189593, 189597, 189601, 189605, 189609, 189613, - 189617, 189621, 189625, 189629, 189633, 189637, 189641, 189645, 189649, - 189653, 189657, 189661, 189665, 189669, 189673, 189677, 189681, 189685, - 189689, 189693, 189697, 189701, 189705, 189709, 189713, 189717, 189721, - 189725, 189729, 189733, 189737, 189741, 189745, 189749, 189753, 189757, - 189761, 189765, 189769, 189773, 189777, 189781, 189785, 189789, 189793, - 189797, 189801, 189805, 189809, 189813, 189817, 189821, 189825, 189829, - 189833, 189837, 189841, 189845, 189849, 189853, 189857, 189861, 189865, - 189869, 189873, 189877, 189881, 189885, 189889, 189893, 189897, 189901, - 189905, 189909, 189913, 189917, 189921, 189925, 189929, 189933, 189937, - 189941, 189945, 189949, 189953, 189957, 189961, 189965, 189969, 189973, - 189977, 189981, 189985, 189989, 189993, 189997, 190001, 190005, 190009, - 190013, 190017, 190021, 190025, 190029, 190033, 190037, 190041, 190045, - 190049, 190053, 190057, 190061, 190065, 190069, 190073, 190077, 190081, - 190085, 190089, 190093, 190097, 190101, 190105, 190109, 190113, 190117, - 190121, 190125, 190129, 190133, 190137, 190141, 190145, 190149, 190153, - 190157, 190161, 190165, 190169, 190173, 190177, 190181, 190185, 190189, - 190193, 190197, 190201, 190205, 190209, 190213, 190217, 190221, 190225, - 190229, 190233, 190237, 190241, 190245, 190249, 190253, 190257, 190261, - 190265, 190269, 190273, 190277, 190281, 190285, 190289, 190293, 190297, - 190301, 190305, 190309, 190313, 190317, 190321, 190325, 190329, 190333, - 190337, 190341, 190345, 190349, 190353, 190357, 190361, 190365, 190369, - 190373, 190377, 190381, 190385, 190389, 190393, 190397, 190401, 190405, - 190409, 190413, 190417, 190421, 190425, 190429, 190433, 190437, 190441, - 190445, 190449, 190453, 190457, 190461, 190465, 190469, 190473, 190477, - 190481, 190485, 190489, 190493, 190497, 190501, 190505, 190509, 190513, - 190517, 190521, 190525, 190529, 190533, 190537, 190541, 190545, 190549, - 190553, 190557, 190561, 190565, 190569, 190573, 190577, 190581, 190585, - 190589, 190593, 190597, 190601, 190605, 190609, 190613, 190617, 190621, - 190625, 190629, 190633, 190637, 190641, 190645, 190649, 190653, 190657, - 190661, 190665, 190669, 190673, 190677, 190681, 190685, 190689, 190693, - 190697, 190701, 190705, 190709, 190713, 190717, 190721, 190725, 190729, - 190733, 190737, 190741, 190745, 190749, 190753, 190757, 190761, 190765, - 190769, 190773, 190777, 190781, 190785, 190789, 190793, 190797, 190801, - 190805, 190809, 190813, 190817, 190821, 190825, 190829, 190833, 190837, - 190841, 190845, 190849, 190853, 190857, 190861, 190865, 190869, 190873, - 190877, 190881, 190885, 190889, 190893, 190897, 190901, 190905, 190909, - 190913, 190917, 190921, 190925, 190929, 190933, 190937, 190941, 190945, - 190949, 190953, 190957, 190961, 190965, 190969, 190973, 190977, 190981, - 190985, 190989, 190993, 190997, 191001, 191005, 191009, 191013, 191017, - 191021, 191025, 191029, 191033, 191037, 191041, 191045, 191049, 191053, - 191057, 191061, 191065, 191069, 191073, 191077, 191081, 191085, 191089, - 191093, 191097, 191101, 191105, 191109, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 191113, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 191117, 191121, 191126, 191131, 191135, 191140, 191145, 191149, 191153, - 191158, 191163, 191167, 191171, 191175, 191179, 191185, 191189, 191194, - 191198, 191202, 191206, 191210, 191214, 191218, 191222, 191226, 191230, - 191234, 191238, 191243, 191248, 191253, 191258, 191264, 191270, 191277, - 191284, 191291, 191297, 191304, 191311, 191318, 191324, 191331, 191338, - 191344, 191351, 191358, 191364, 191371, 191378, 191384, 191391, 191398, - 191404, 191411, 191418, 191425, 191432, 191439, 191445, 191451, 191457, - 191463, 191468, 191474, 191480, 191487, 191494, 191501, 191507, 191514, - 191521, 191528, 191534, 191541, 191548, 191554, 191561, 191568, 191574, - 191581, 191588, 191594, 191601, 191608, 191614, 191621, 191628, 191635, - 191642, 191649, 191656, 191661, 191668, 191672, 191676, 191679, 191682, - 191685, 191688, 191691, 191694, 191697, 191700, 191703, 191706, 191709, - 191712, 191715, 191718, 191721, 191724, 191727, 191730, 191733, 191736, - 191739, 191742, 191745, 191748, 191751, 191754, 191757, 191760, 191763, - 191766, 191769, 191772, 191775, 191778, 191781, 191784, 191787, 191790, - 191793, 191796, 191799, 191802, 191805, 191808, 191811, 191814, 191817, - 191820, 191823, 191826, 191829, 191832, 191835, 191838, 191841, 191844, - 191847, 191850, 191853, 191856, 191859, 191862, 191865, 191868, 191871, - 191874, 191877, 191880, 191883, 191886, 191889, 191892, 191895, 191898, - 191901, 191904, 191907, 191910, 191913, 191916, 191919, 191922, 191925, - 191928, 191931, 191934, 191937, 191940, 191943, 191946, 191949, 191952, - 191955, 191958, 191961, 191964, 191967, 191970, 191973, 191976, 191979, - 191982, 191985, 191988, 191991, 191994, 191997, 192000, 192003, 192006, - 192009, 192012, 192015, 192018, 192021, 192024, 192027, 192030, 192033, - 192036, 192039, 192042, 192045, 192048, 192051, 192054, 192057, 192060, - 192063, 192066, 192069, 192072, 192075, 192078, 192081, 192084, 192087, - 192090, 192093, 192096, 192099, 192102, 192105, 192108, 192111, 192114, - 192117, 192120, 192123, 192126, 192129, 192132, 192135, 192138, 192141, - 192144, 192147, 192150, 192153, 192156, 192159, 192162, 192165, 192168, - 192171, 192174, 192177, 192180, 192183, 192186, 192189, 192192, 192195, - 192198, 192201, 192204, 192207, 192210, 192213, 192216, 192219, 192222, - 192225, 192228, 192231, 192234, 192237, 192240, 192243, 192246, 192249, - 192252, 192255, 192258, 192261, 192264, 192267, 192270, 192273, 192276, - 192279, 192282, 192285, 192288, 192291, 192294, 192297, 192300, 192303, - 192306, 192309, 192312, 192315, 192318, 192321, 192324, 192327, 192330, - 192333, 192336, 192339, 192342, 192345, 192348, 192351, 192354, 192357, - 192360, 192363, 192366, 192369, 192372, 192375, 192378, 192381, 192384, - 192387, 192390, 192393, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 192396, 192398, 192400, 192405, 192407, 192412, 192414, 192419, 192421, - 192426, 192428, 192430, 192432, 192434, 192436, 192438, 192440, 192442, - 192444, 192448, 192452, 192454, 192456, 192460, 192464, 192469, 192471, - 192473, 192475, 192479, 192482, 192484, 192488, 192490, 192494, 192496, - 192500, 192503, 192505, 192509, 192513, 192515, 192521, 192523, 192528, - 192530, 192535, 192537, 192542, 192544, 192549, 192551, 192555, 192557, - 192561, 192563, 192570, 192572, 192574, 192576, 192581, 192583, 192585, - 192587, 192589, 192591, 192593, 192598, 192602, 192604, 192609, 192613, - 192615, 192620, 192624, 192626, 192631, 192635, 192637, 192639, 192641, - 192643, 192647, 192649, 192654, 192656, 192662, 192664, 192670, 192672, - 192674, 192676, 192680, 192682, 192689, 192691, 192698, 192700, 192706, - 192712, 192714, 192721, 192728, 192730, 192736, 192741, 192743, 192749, - 192755, 192757, 192763, 192769, 192771, 192777, 192781, 192783, 192788, - 192790, 192792, 192797, 192799, 192801, 192807, 192809, 192814, 192818, - 192820, 192825, 192829, 192831, 192837, 192839, 192843, 192845, 192849, - 192851, 192858, 192865, 192867, 192874, 192881, 192883, 192888, 192890, - 192898, 192900, 192906, 192908, 192914, 192916, 192920, 192922, 192928, - 192930, 192934, 192936, 192942, 192944, 192946, 192948, 192953, 192958, - 192960, 192969, 192971, 192981, 192986, 192993, 193000, 193005, 193010, - 193022, 193026, 193030, 193034, 193038, 193040, 193042, 193044, 193046, - 193048, 193054, 193056, 193058, 193060, 193062, 193064, 193066, 193068, - 193070, 193072, 193074, 193076, 193078, 193080, 193082, 193084, 193086, - 193088, 193094, 193101, 193106, 193114, 193122, 193127, 193133, 193135, - 193137, 193139, 193141, 193143, 193145, 193147, 193149, 193151, 193153, - 193155, 193157, 193159, 193161, 193163, 193165, 193177, 193182, 193184, - 193186, 193192, 193204, 193210, 193216, 193222, 193228, 193232, 193243, - 193245, 193247, 193249, 193251, 193253, 193255, 193257, 193259, 193261, - 193263, 193265, 193267, 193269, 193271, 193273, 193275, 193277, 193279, - 193281, 193283, 193285, 193287, 193289, 193291, 193293, 193295, 193297, - 193299, 193301, 193303, 193305, 193307, 193309, 193311, 193313, 193315, - 193317, 193319, 193321, 193323, 193325, 193327, 193329, 193331, 193333, - 193335, 193337, 193339, 193341, 193343, 193345, 193347, 193349, 193351, - 193353, 193355, 193357, 193359, 193361, 193363, 193365, 193367, 193369, - 193371, 193373, 193375, 193377, 193379, 193381, 193383, 193385, 193387, - 193389, 193391, 193393, 193395, 193397, 193399, 193401, 193403, 193405, - 193407, 193409, 193411, 193413, 193415, 193417, 193419, 193421, 193423, - 193425, 193427, 193429, 193431, 193433, 193435, 193437, 193439, 193441, - 193443, 193445, 193447, 193449, 193451, 193453, 193455, 193457, 193459, - 193461, 193463, 193465, 193467, 193469, 193471, 193473, 193475, 193477, - 193479, 193481, 193483, 193485, 193487, 193489, 193491, 193493, 193495, - 193497, 193499, 193501, 193503, 193505, 193507, 193509, 193511, 193513, - 193515, 193517, 193519, 193521, 193523, 193525, 193527, 193529, 193531, - 193533, 193535, 193537, 193539, 193541, 193543, 193545, 193547, 193549, - 193551, 193553, 193555, 193557, 193559, 193561, 193563, 193565, 193567, - 193569, 193571, 193573, 193575, 193577, 193579, 193581, 193583, 193585, - 193587, 193589, 193591, 193593, 193595, 193597, 193599, 193601, 193603, - 193605, 193607, 193609, 193611, 193613, 193615, 193617, 193619, 193621, - 193623, 193625, 193627, 193629, 193631, 193633, 193635, 193637, 193639, - 193641, 193643, 193645, 193647, 193649, 193651, 193653, 193655, 193657, - 193659, 193661, 193663, 193665, 193667, 193669, 193671, 193673, 193675, - 193677, 193679, 193681, 193683, 193685, 193687, 193689, 193691, 193693, - 193695, 193697, 193699, 193701, 193703, 193705, 193707, 193709, 193711, - 193713, 193715, 193717, 193719, 193721, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 193723, 193727, 193731, 193736, 193740, 193744, 193748, - 193752, 193756, 193760, 193764, 193768, 193772, 193782, 193792, 193803, - 193814, 193824, 193834, 193844, 193854, 193868, 193882, 193896, 193910, - 193919, 193928, 193941, 193954, 193967, 193980, 193990, 194000, 194011, - 194022, 194033, 194044, 194055, 194064, 194074, 194084, 194094, 194104, - 194115, 194126, 194137, 194148, 194159, 194170, 194181, 194192, 194203, - 194214, 194225, 194239, 194250, 194264, 194272, 194283, 194291, 194299, - 194307, 194315, 194323, 194331, 194341, 194351, 194361, 194371, 194381, - 194391, 194401, 194411, 194419, 194428, 194437, 194446, 194455, 194463, - 194471, 194481, 194491, 194502, 194513, 194525, 194536, 194546, 194557, - 194567, 194578, 194586, 194593, 194600, 194607, 194614, 194621, 194628, - 194635, 194642, 194650, 194658, 194666, 194674, 194682, 194690, 194698, - 194706, 194714, 194722, 194730, 194735, 194739, 194743, 194747, 194751, - 194755, 194759, 194763, 194767, 194771, 194775, 194779, 194782, 194785, - 194789, 194793, 194797, 194801, 194805, 194809, 194813, 194817, 194821, - 194825, 194829, 194833, 194837, 194841, 194845, 194849, 194853, 194857, - 194861, 194865, 194869, 194873, 194877, 194881, 194885, 194889, 194893, - 194897, 194901, 194905, 194909, 194913, 194917, 194921, 194925, 194929, - 194933, 194937, 194941, 194945, 194949, 194953, 194957, 194961, 194965, - 194969, 194973, 194977, 194981, 194985, 194989, 194993, 194997, 195001, - 195005, 195009, 195013, 195017, 195021, 195025, 195029, 195033, 195037, - 195041, 195045, 195049, 195053, 195057, 195061, 195065, 195069, 195073, - 195077, 195081, 195085, 195089, 195093, 195097, 195101, 195105, 195109, - 195113, 195117, 195121, 195125, 195128, 195132, 195136, 195140, 195144, - 195148, 195152, 195156, 195160, 195164, 195168, 195172, 195176, 195180, - 195184, 195188, 195192, 195196, 195200, 195204, 195208, 195212, 195216, - 195220, 195224, 195228, 195232, 195236, 195240, 195244, 195248, 195252, - 195256, 195260, 195264, 195268, 195272, 195276, 195280, 195284, 195288, - 195292, 195296, 195300, 195304, 195308, 195312, 195316, 195320, 195324, - 195328, 195332, 195336, 195340, 195344, 195348, 195352, 195356, 195360, - 195364, 195368, 195372, 195376, 195380, 195384, 195388, 195392, 195396, - 195400, 195404, 195408, 195412, 195416, 195420, 195424, 195428, 195432, - 195436, 195440, 195444, 195448, 195452, 195456, 195460, 195464, 195468, - 195472, 195476, 195480, 195484, 195488, 195492, 195496, 195500, 195504, - 195508, 195512, 195516, 195520, 195524, 195528, 195532, 195536, 195540, - 195544, 195548, 195552, 195556, 195560, 195564, 195568, 195572, 195576, - 195580, 195584, 195588, 195592, 195596, 195600, 195604, 195608, 195612, - 195616, 195620, 195624, 195628, 195632, 195636, 195640, 195644, 195648, - 195652, 195656, 195660, 195664, 195668, 195672, 195676, 195680, 195684, - 195688, 195692, 195696, 195700, 195704, 195708, 195712, 195716, 195720, - 195724, 195728, 195732, 195736, 195740, 195744, 195748, 195752, 195756, - 195760, 195764, 195768, 195772, 195776, 195780, 195784, 195788, 195792, - 195796, 195800, 195804, 195808, 195812, 195816, 195820, 195824, 195828, - 195832, 195836, 195840, 195844, 195848, 195852, 195856, 195860, 195864, - 195868, 195872, 195876, 195880, 195884, 195888, 195892, 195897, 195902, - 195907, 195911, 195917, 195924, 195931, 195938, 195945, 195952, 195959, - 195966, 195973, 195980, 195987, 195994, 196001, 196008, 196014, 196021, - 196028, 196034, 196041, 196048, 196055, 196062, 196069, 196076, 196083, - 196090, 196097, 196104, 196111, 196118, 196125, 196131, 196137, 196143, - 196150, 196159, 196168, 196177, 196186, 196191, 196196, 196203, 196210, - 196217, 196224, 196231, 196237, 196243, 196249, 196255, 196261, 196267, - 196273, 196278, 196284, 196294, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -}; - -/* name->code dictionary */ -static const unsigned int code_hash[] = { - 74224, 4851, 0, 0, 0, 0, 7929, 0, 0, 0, 0, 127931, 0, 42833, 983091, - 12064, 110752, 129548, 194597, 69850, 65842, 0, 0, 0, 78159, 68476, - 72392, 1373, 0, 0, 5816, 0, 0, 4231, 0, 0, 4233, 4234, 4232, 68885, - 70351, 0, 7404, 72393, 0, 0, 0, 0, 0, 41601, 8874, 0, 0, 0, 128498, 0, 0, - 41603, 9784, 0, 9188, 41600, 0, 0, 0, 0, 3535, 0, 0, 0, 66797, 0, 74491, - 0, 3404, 100419, 0, 72411, 1759, 100417, 0, 100418, 69972, 11240, 121038, - 100416, 127764, 0, 0, 0, 0, 0, 69970, 0, 0, 9834, 43249, 2234, 983891, 0, - 0, 0, 0, 92417, 0, 74398, 12035, 0, 983074, 43548, 0, 0, 0, 0, 0, 64318, - 917549, 0, 3390, 74483, 43265, 0, 983884, 0, 0, 0, 3400, 0, 0, 11647, 0, - 0, 0, 0, 2121, 128741, 4043, 8712, 0, 983814, 0, 121172, 0, 129456, 0, 0, - 93042, 0, 0, 983875, 0, 0, 0, 11851, 0, 3181, 66002, 0, 69601, 0, 66021, - 0, 194588, 5457, 5440, 0, 93981, 65282, 2843, 5355, 0, 129333, 69971, - 5194, 11657, 128353, 0, 0, 0, 0, 0, 120766, 100525, 0, 0, 74350, 0, - 10682, 110820, 10602, 800, 70044, 118883, 0, 0, 64930, 118940, 67853, - 72001, 0, 762, 120485, 0, 0, 0, 10906, 1353, 6960, 0, 0, 5828, 8724, 0, - 0, 118548, 0, 0, 7080, 0, 128806, 122979, 0, 72388, 0, 11859, 0, 0, - 68878, 0, 0, 0, 7240, 0, 556, 0, 118544, 0, 0, 0, 72397, 0, 0, 0, 0, 0, - 0, 0, 0, 72986, 0, 0, 43931, 0, 11093, 0, 0, 122960, 7341, 66801, 68527, - 0, 1874, 0, 0, 129314, 0, 0, 0, 0, 0, 0, 7688, 0, 0, 9036, 0, 0, 66389, - 0, 121347, 0, 0, 10100, 0, 2725, 0, 0, 43981, 42128, 0, 0, 68146, 0, 0, - 0, 0, 71349, 7859, 1945, 0, 0, 0, 65918, 7188, 9992, 0, 7389, 127008, - 71341, 0, 0, 0, 528, 129681, 44017, 11429, 71347, 0, 0, 120864, 0, 0, 0, - 11530, 73102, 6188, 0, 0, 68208, 1823, 0, 0, 92928, 0, 64843, 7233, - 92929, 0, 0, 6639, 0, 0, 123149, 0, 1176, 0, 0, 8276, 128667, 0, 0, - 68892, 42931, 0, 0, 0, 0, 0, 0, 0, 5388, 0, 0, 0, 11310, 0, 123607, 0, - 68888, 4199, 119264, 0, 119020, 0, 0, 9560, 0, 0, 43869, 0, 0, 0, 83172, - 0, 0, 0, 83173, 101559, 128875, 0, 0, 74327, 0, 0, 0, 0, 0, 123623, - 68886, 0, 0, 0, 8408, 64704, 0, 0, 0, 0, 118711, 67999, 0, 0, 0, 0, - 43049, 0, 43050, 73028, 0, 0, 0, 0, 0, 127396, 0, 69847, 9322, 0, 0, - 129321, 68192, 120507, 983634, 0, 0, 0, 6199, 67249, 0, 0, 0, 0, 11329, - 66285, 0, 983086, 0, 0, 0, 0, 41335, 118866, 43401, 0, 41334, 0, 0, 0, - 983484, 71997, 983483, 128114, 0, 42627, 0, 32, 6187, 0, 123619, 983480, - 3665, 121083, 42871, 983119, 41336, 0, 0, 983476, 0, 0, 0, 4412, 0, 0, 0, - 0, 119533, 0, 4181, 0, 0, 127589, 0, 0, 71453, 6181, 74755, 917895, 0, 0, - 0, 73557, 121107, 0, 0, 10073, 0, 100738, 127186, 0, 42844, 7498, 1098, - 92565, 119530, 0, 0, 10207, 0, 983233, 0, 983555, 0, 9234, 0, 6182, 0, - 92552, 0, 0, 0, 0, 5471, 9461, 6697, 0, 5473, 0, 0, 0, 0, 0, 0, 70073, 0, - 0, 7767, 8304, 41339, 0, 983494, 69450, 0, 0, 983492, 43855, 41337, 0, 0, - 0, 129706, 0, 0, 0, 72396, 0, 0, 0, 42633, 0, 0, 0, 0, 0, 0, 0, 70005, - 129506, 0, 0, 0, 129580, 69817, 128299, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1437, - 41617, 0, 0, 0, 128853, 0, 0, 0, 0, 0, 128529, 12113, 0, 42772, 0, 0, - 7693, 10749, 67485, 65210, 5773, 978, 128134, 0, 41619, 10239, 0, 0, 0, - 74328, 0, 9748, 0, 0, 0, 0, 0, 0, 0, 70681, 0, 72811, 0, 67464, 0, 92776, - 0, 0, 2379, 11325, 0, 0, 67854, 0, 78547, 42209, 0, 120392, 2369, 0, - 984003, 984004, 0, 0, 73936, 7008, 69415, 122919, 0, 43841, 2367, 127827, - 983888, 0, 2375, 8060, 6194, 0, 0, 119084, 0, 0, 0, 0, 6961, 0, 0, 0, - 68426, 0, 42862, 0, 0, 6192, 127900, 42771, 0, 0, 11435, 128445, 118797, - 120800, 0, 12892, 0, 128621, 67149, 0, 0, 0, 0, 120707, 0, 0, 19954, 0, - 121164, 8983, 0, 0, 0, 0, 0, 6198, 121344, 0, 196, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 983512, 41323, 0, 0, 92289, 0, 0, 0, 983508, 41321, - 12907, 3048, 7752, 41320, 0, 0, 12819, 111247, 72127, 0, 0, 0, 0, 0, - 72971, 0, 0, 0, 0, 78650, 78649, 0, 41326, 0, 11806, 43167, 0, 1245, 0, - 66463, 0, 0, 0, 0, 0, 194619, 0, 194618, 0, 0, 194620, 0, 70403, 325, - 12874, 128454, 74178, 0, 0, 119110, 0, 0, 0, 0, 0, 0, 983563, 92175, 0, - 125016, 0, 121049, 0, 0, 0, 0, 0, 0, 110844, 11776, 0, 19908, 0, 0, 0, - 8753, 69278, 0, 0, 9511, 43493, 0, 93032, 6205, 0, 0, 0, 0, 0, 78928, 0, - 0, 120269, 0, 41607, 0, 0, 120617, 0, 0, 0, 7005, 41609, 9580, 0, 401, 0, - 43779, 0, 127962, 0, 65486, 0, 12857, 0, 11983, 0, 0, 0, 121371, 0, - 194971, 74258, 983647, 0, 0, 0, 0, 0, 8295, 6200, 0, 127864, 0, 0, 71435, - 0, 92523, 0, 128631, 0, 0, 125197, 0, 100426, 0, 127556, 0, 0, 0, 64775, - 0, 68862, 120590, 0, 0, 129959, 8074, 8199, 126641, 1907, 127269, 4432, - 127271, 10808, 120668, 127272, 127259, 3888, 127261, 72724, 127263, - 127262, 127265, 123169, 121195, 127250, 66879, 127252, 100422, 66023, - 67363, 7663, 0, 0, 0, 0, 66321, 0, 12814, 127248, 127169, 0, 0, 194603, - 7641, 92694, 0, 0, 0, 0, 74320, 120818, 120268, 0, 128475, 0, 110627, 0, - 9622, 128972, 120264, 0, 0, 0, 0, 68319, 0, 0, 71484, 118613, 0, 0, - 69906, 0, 0, 947, 0, 194586, 129059, 10969, 119935, 7613, 119937, 119936, - 4795, 119930, 119933, 7376, 0, 0, 0, 72343, 69373, 0, 0, 0, 119919, 7216, - 119921, 7217, 119915, 7218, 119917, 7219, 119927, 119926, 119929, 119928, - 7213, 119922, 7214, 7215, 128622, 0, 8880, 7685, 128849, 0, 0, 119618, - 119853, 8187, 119913, 12815, 7236, 7915, 71906, 0, 121284, 0, 0, 0, 0, 0, - 0, 0, 122969, 0, 0, 0, 0, 0, 10468, 0, 0, 0, 0, 0, 0, 0, 0, 917909, 0, - 110633, 1616, 3795, 67732, 11529, 0, 126225, 0, 0, 1138, 194577, 12677, - 0, 0, 3239, 0, 0, 194809, 194583, 0, 42164, 0, 11778, 67473, 43259, - 118543, 119073, 122975, 0, 0, 67094, 129638, 0, 78421, 128123, 78418, 0, - 0, 0, 0, 43959, 43960, 0, 72257, 0, 9359, 78416, 0, 0, 0, 6662, 0, 0, - 3863, 0, 41329, 55266, 0, 127822, 41328, 75026, 194569, 129516, 0, 0, - 2178, 119595, 569, 0, 0, 0, 119085, 110669, 0, 0, 11610, 11368, 0, - 194570, 41331, 1006, 127747, 120883, 1550, 8201, 0, 194811, 5499, 43956, - 77908, 77910, 77906, 43957, 77904, 77905, 128410, 0, 0, 129581, 100447, - 43955, 77913, 122989, 0, 5511, 0, 983721, 0, 69241, 8255, 5512, 128560, - 119560, 127858, 64313, 127928, 5906, 1119, 128180, 67088, 983367, 0, - 113798, 0, 66423, 0, 0, 0, 67089, 0, 0, 0, 0, 128177, 983728, 0, 0, 0, - 5821, 6186, 129960, 128034, 19961, 0, 983719, 0, 65138, 302, 41113, - 41115, 0, 6637, 5907, 128789, 0, 43642, 0, 128625, 0, 70345, 5513, 6666, - 100567, 78442, 5510, 0, 0, 0, 983725, 78437, 0, 0, 0, 110838, 0, 0, 0, - 92710, 0, 0, 0, 0, 0, 74497, 92395, 120511, 6929, 69412, 0, 110835, - 64442, 0, 0, 74496, 0, 6674, 43397, 0, 1476, 0, 0, 72276, 3233, 0, 0, - 10164, 118555, 0, 3530, 67243, 0, 111219, 6656, 0, 0, 74647, 8512, 72275, - 74261, 8967, 0, 0, 0, 72277, 7986, 73782, 120556, 9006, 983562, 72273, 0, - 7853, 0, 983360, 0, 0, 0, 0, 983971, 0, 0, 0, 0, 0, 0, 0, 0, 127971, - 67983, 13296, 517, 0, 0, 0, 41528, 19923, 65454, 73518, 0, 0, 10531, - 7784, 41526, 71727, 0, 8057, 1126, 73895, 0, 0, 130040, 119186, 4251, - 8235, 43142, 0, 489, 71733, 4250, 71731, 110721, 43151, 94177, 71725, 0, - 121238, 0, 0, 0, 110726, 0, 8711, 6183, 110722, 110723, 0, 0, 7623, 0, 0, - 9235, 12760, 74176, 0, 0, 0, 0, 3743, 11514, 11078, 74582, 0, 0, 126597, - 0, 0, 0, 0, 983907, 267, 3393, 127504, 2364, 0, 69233, 6958, 0, 6201, 0, - 42360, 0, 10652, 41612, 917802, 3402, 917801, 3398, 0, 0, 0, 3391, 70683, - 0, 92541, 128017, 126087, 126590, 0, 12767, 0, 983380, 64261, 0, 127537, - 70852, 70347, 0, 6673, 0, 0, 129346, 12438, 0, 0, 0, 71128, 0, 9053, - 43954, 74523, 0, 0, 0, 6195, 0, 6660, 0, 917760, 917793, 0, 12629, 0, 0, - 0, 0, 0, 127940, 0, 0, 0, 65448, 0, 0, 121084, 129688, 43949, 0, 78099, - 0, 983385, 0, 0, 0, 5741, 1131, 0, 0, 74862, 0, 43952, 42533, 119598, - 78107, 0, 0, 43950, 121297, 118990, 7691, 43951, 578, 0, 0, 0, 42514, - 74547, 74196, 120608, 74561, 0, 983976, 0, 0, 0, 0, 0, 0, 0, 0, 7241, 0, - 93846, 119167, 0, 12811, 78082, 3946, 0, 10998, 66807, 673, 0, 0, 0, 0, - 119301, 0, 68890, 0, 0, 78085, 10267, 0, 74560, 78083, 0, 8729, 0, 0, 0, - 0, 0, 0, 0, 119296, 0, 0, 0, 2181, 983463, 731, 0, 71904, 128316, 0, - 73539, 0, 1175, 0, 68167, 0, 0, 10793, 0, 67644, 7723, 983458, 0, 0, 0, - 0, 5273, 0, 5269, 0, 69607, 2404, 5267, 124967, 124913, 0, 5277, 0, 0, - 6189, 65469, 1314, 0, 0, 118873, 8785, 0, 0, 127527, 68414, 43535, 9204, - 0, 3879, 0, 71696, 6197, 9497, 0, 7567, 64484, 78128, 41390, 41379, - 41882, 67647, 67279, 70085, 0, 121413, 41388, 64446, 41392, 64288, 41387, - 0, 8706, 10675, 0, 700, 0, 5775, 0, 7088, 74756, 7499, 0, 78120, 78111, - 67251, 126557, 0, 0, 128945, 10311, 78115, 6665, 11115, 0, 7618, 10821, - 11455, 0, 64632, 64447, 0, 0, 78093, 78091, 0, 0, 65033, 0, 6668, 0, 0, - 0, 656, 69686, 65037, 0, 0, 127024, 0, 0, 0, 0, 73014, 0, 0, 917774, - 9702, 0, 92273, 66580, 118895, 66683, 43640, 3417, 0, 6832, 0, 917768, 0, - 917767, 118583, 4935, 11906, 0, 0, 67296, 92896, 3651, 0, 67294, 70848, - 0, 67292, 0, 12983, 0, 55272, 0, 0, 1439, 0, 74897, 0, 0, 0, 78373, 0, - 42087, 3063, 0, 0, 7838, 0, 129282, 0, 0, 67968, 0, 128582, 9078, 92446, - 0, 0, 0, 0, 0, 0, 119586, 0, 7750, 128422, 68237, 6190, 0, 0, 0, 72340, - 9857, 7014, 9856, 0, 92620, 120547, 0, 8481, 0, 6202, 0, 10920, 67970, 0, - 0, 983297, 0, 7843, 65818, 66824, 0, 73481, 0, 0, 0, 0, 0, 6657, 207, 0, - 69728, 74819, 0, 0, 0, 0, 0, 0, 0, 0, 41368, 43974, 488, 0, 0, 71339, - 10157, 118700, 43034, 11982, 0, 0, 0, 0, 0, 41372, 6669, 8504, 72103, 0, - 41367, 129328, 119272, 0, 11726, 8261, 129793, 304, 129799, 129795, - 129822, 129807, 113683, 983239, 238, 74522, 0, 0, 19905, 120577, 122968, - 129200, 41044, 67640, 67302, 64814, 9912, 65939, 983470, 0, 0, 0, 917925, - 0, 0, 309, 6622, 0, 10858, 0, 67636, 0, 72749, 0, 0, 0, 67637, 123138, - 9712, 68680, 43970, 0, 65165, 93047, 983831, 0, 0, 0, 0, 0, 6191, 12944, - 0, 0, 67634, 43763, 0, 0, 67635, 9370, 41381, 0, 0, 123148, 118817, 0, - 3222, 121439, 0, 0, 66663, 0, 0, 0, 0, 0, 65732, 121144, 0, 983219, 0, 0, - 67309, 72192, 41383, 64568, 0, 0, 0, 0, 984009, 66725, 0, 0, 0, 0, 73766, - 67306, 3632, 128246, 0, 8376, 3648, 0, 74844, 67639, 3636, 0, 3650, 8837, - 0, 0, 0, 43250, 41562, 0, 0, 68839, 3640, 127190, 0, 11781, 0, 0, 0, 0, - 129659, 0, 126649, 0, 42080, 2529, 0, 78004, 0, 42083, 0, 0, 120531, - 67619, 0, 0, 9634, 0, 0, 0, 0, 0, 0, 0, 68841, 0, 92545, 68874, 127399, - 0, 0, 41987, 119667, 67623, 983779, 0, 925, 127156, 0, 41985, 64441, - 9586, 120988, 41984, 9217, 128372, 0, 0, 9186, 67620, 4016, 983834, 0, - 381, 983700, 0, 42077, 0, 128777, 67622, 42078, 0, 10810, 0, 4585, 19943, - 5860, 67633, 0, 0, 812, 0, 0, 0, 92518, 0, 0, 0, 0, 67629, 0, 10692, 0, - 67630, 0, 924, 0, 67631, 42616, 0, 0, 0, 67317, 67632, 0, 12771, 12736, - 12753, 0, 983753, 67626, 67722, 0, 0, 0, 0, 12751, 74906, 8542, 0, 0, - 3626, 66706, 0, 0, 3883, 64388, 0, 0, 0, 0, 0, 0, 126268, 67624, 0, - 10932, 0, 65585, 64338, 806, 0, 41884, 110845, 1318, 128828, 0, 0, 0, - 983808, 3465, 2405, 983395, 0, 12756, 65259, 69381, 983812, 12752, 5833, - 1432, 110843, 41883, 110841, 9799, 0, 41886, 0, 0, 2062, 0, 0, 0, 0, - 129376, 0, 124969, 983392, 0, 120971, 0, 118832, 0, 983286, 0, 68005, - 10622, 0, 0, 0, 6566, 71195, 0, 73780, 0, 68865, 0, 0, 0, 8284, 0, 0, 0, - 0, 0, 43023, 0, 983290, 6642, 3977, 72743, 64729, 836, 983386, 92947, 0, - 0, 0, 0, 0, 0, 125239, 917923, 0, 0, 0, 0, 0, 0, 1374, 65149, 119014, - 67720, 0, 2273, 0, 0, 0, 11234, 0, 0, 9630, 12597, 0, 0, 0, 6661, 0, - 113751, 120551, 125015, 0, 0, 72151, 0, 73674, 7718, 113755, 0, 69570, 0, - 0, 983777, 0, 0, 0, 127841, 6365, 1887, 983414, 0, 8080, 113681, 0, 0, 0, - 129855, 1544, 0, 0, 64677, 0, 0, 0, 0, 73561, 0, 0, 12812, 7342, 0, - 73784, 66947, 7904, 0, 0, 120910, 0, 0, 0, 0, 9724, 0, 983804, 9524, 0, - 0, 0, 0, 0, 129344, 0, 471, 0, 0, 128302, 72450, 0, 0, 983769, 0, 0, - 6918, 118685, 0, 5156, 0, 128683, 10232, 10615, 10213, 0, 0, 42528, 0, 0, - 0, 0, 65311, 74935, 0, 13306, 10533, 7870, 0, 7625, 0, 120544, 0, 0, - 128816, 126098, 118870, 0, 92819, 0, 0, 92341, 0, 12978, 128533, 0, 0, - 43836, 42675, 0, 12845, 0, 19942, 0, 0, 0, 0, 0, 120000, 120008, 120001, - 0, 194894, 983746, 0, 0, 0, 7186, 73107, 0, 70093, 445, 119028, 0, 0, 0, - 73047, 0, 0, 128442, 0, 0, 0, 3902, 68913, 129916, 0, 0, 1560, 43958, 0, - 4584, 0, 67862, 0, 10866, 92905, 1118, 92209, 74888, 0, 1081, 7436, - 11147, 7252, 0, 121188, 0, 0, 0, 41386, 5162, 129823, 1330, 0, 121270, 0, - 12047, 7675, 0, 0, 1848, 74528, 983148, 64708, 0, 0, 194880, 0, 0, 0, - 983772, 12715, 128349, 0, 101402, 0, 66672, 73710, 66685, 0, 0, 92464, 0, - 68884, 0, 72835, 123546, 70800, 70101, 120725, 0, 194893, 9214, 43494, 0, - 0, 120841, 0, 0, 6313, 65513, 119355, 0, 0, 0, 2345, 72975, 0, 0, 129937, - 0, 3117, 0, 71882, 0, 73100, 0, 0, 0, 0, 78415, 983236, 100907, 0, 13248, - 0, 120241, 129416, 128415, 0, 94193, 12382, 71120, 0, 0, 0, 0, 1471, 0, - 113747, 0, 12378, 0, 69664, 0, 12374, 121357, 0, 0, 0, 0, 0, 0, 12376, 0, - 0, 0, 12380, 10557, 0, 12520, 11122, 2024, 127180, 0, 0, 74588, 0, 0, - 70120, 3853, 0, 0, 0, 983763, 0, 0, 12090, 0, 12474, 92579, 9503, 0, 0, - 73505, 68318, 0, 110834, 0, 0, 0, 12470, 0, 74189, 2742, 12476, 66370, - 10946, 0, 12472, 0, 0, 0, 0, 8213, 43824, 7771, 6161, 983280, 68010, 0, - 0, 0, 68235, 0, 0, 0, 120985, 0, 0, 0, 129814, 73791, 129830, 68871, 0, - 0, 0, 0, 0, 73704, 12015, 128561, 8275, 0, 43459, 120927, 127555, 0, 0, - 0, 68881, 71215, 983642, 118841, 0, 12516, 4444, 0, 119017, 120506, - 10892, 118828, 0, 6473, 0, 0, 71735, 3591, 0, 0, 0, 0, 72345, 0, 0, 0, - 127547, 0, 0, 0, 0, 128253, 0, 0, 0, 0, 94060, 687, 0, 0, 983404, 0, 0, - 43882, 0, 128526, 285, 0, 0, 0, 4459, 0, 0, 74917, 0, 0, 126255, 0, - 119248, 0, 9743, 0, 0, 126535, 0, 0, 73104, 0, 69659, 0, 0, 3081, 74577, - 42921, 0, 0, 0, 0, 0, 0, 0, 9125, 119023, 0, 120820, 0, 65221, 0, 0, - 64852, 0, 0, 0, 0, 66578, 5001, 41879, 0, 0, 5003, 884, 0, 0, 4943, 5150, - 73889, 74182, 0, 41876, 0, 78915, 42448, 42299, 72804, 0, 0, 0, 0, 8491, - 0, 0, 983635, 4530, 42409, 7126, 119526, 66200, 0, 118559, 19929, 0, 0, - 0, 4242, 0, 0, 0, 0, 66034, 65941, 124929, 64522, 10740, 8958, 128257, - 9754, 119102, 983251, 74222, 983249, 983248, 119064, 983246, 983245, 0, - 0, 0, 74518, 66026, 4306, 41468, 68432, 0, 0, 66667, 0, 0, 983499, 42200, - 0, 0, 0, 120236, 6948, 0, 8524, 0, 0, 12385, 0, 74926, 0, 1386, 73996, 0, - 0, 0, 121184, 12392, 0, 8064, 0, 0, 78216, 119004, 2080, 710, 128491, - 12390, 1666, 42091, 0, 12383, 92968, 42092, 68418, 0, 128106, 0, 0, - 42096, 0, 3362, 12377, 127878, 0, 0, 0, 0, 1244, 4401, 73786, 12683, - 10662, 0, 8112, 129837, 119021, 121017, 12379, 73108, 120534, 0, 42208, - 0, 12381, 0, 0, 0, 4327, 0, 0, 128350, 0, 78232, 0, 584, 12933, 0, 12373, - 73105, 13000, 0, 2935, 129113, 12665, 0, 43081, 73098, 120505, 12427, 0, - 983625, 78227, 0, 0, 0, 0, 128760, 74551, 0, 0, 12426, 0, 73497, 0, - 12428, 0, 0, 0, 0, 0, 12429, 6727, 0, 0, 0, 3387, 0, 0, 0, 0, 0, 0, - 73517, 0, 3536, 120589, 9752, 92397, 6162, 0, 0, 10113, 0, 0, 0, 12422, - 0, 439, 3072, 0, 42207, 74549, 120830, 0, 0, 0, 0, 8308, 0, 70807, 0, 0, - 0, 13218, 0, 0, 8082, 12424, 0, 6819, 3539, 93838, 0, 0, 74539, 0, 68181, - 0, 72964, 0, 72969, 12420, 11371, 0, 4600, 0, 127810, 0, 0, 0, 72962, - 128552, 6704, 4591, 72966, 0, 0, 0, 72960, 120623, 561, 12159, 78223, 0, - 78224, 0, 71068, 11932, 7172, 42687, 8368, 0, 0, 93068, 0, 0, 75010, 0, - 0, 0, 0, 42463, 0, 2924, 67183, 0, 129947, 0, 128958, 0, 0, 42330, 73079, - 3969, 0, 129973, 7169, 1992, 9652, 0, 0, 42086, 0, 100865, 0, 0, 0, 0, 0, - 327, 0, 0, 0, 0, 73509, 12433, 0, 0, 118570, 12431, 0, 12434, 983439, 0, - 73544, 0, 7712, 12432, 0, 69377, 129147, 100867, 0, 8212, 0, 128014, 0, - 119066, 7333, 0, 0, 0, 67407, 70006, 128461, 0, 12436, 0, 43160, 0, - 74896, 92757, 71360, 42350, 0, 0, 0, 100566, 0, 11348, 0, 0, 9194, - 983185, 0, 55250, 0, 100569, 0, 0, 0, 0, 0, 64746, 66012, 100565, 3444, - 75029, 64651, 0, 41503, 0, 0, 0, 0, 0, 0, 0, 120876, 0, 0, 129408, 65309, - 12416, 0, 0, 0, 0, 93024, 12418, 74111, 121046, 0, 0, 0, 119361, 0, 4596, - 66339, 12417, 66001, 0, 126491, 12414, 8287, 0, 69499, 0, 1143, 0, 0, - 12415, 0, 0, 983247, 0, 9021, 120783, 0, 11724, 0, 0, 0, 194794, 0, 0, - 8027, 194796, 74257, 127375, 11400, 74197, 194799, 66833, 194798, 0, 0, - 983252, 0, 0, 1324, 0, 0, 0, 194878, 7715, 0, 0, 194777, 194780, 0, 0, 0, - 194787, 0, 0, 0, 0, 0, 66289, 127109, 3889, 129561, 194800, 0, 0, 0, 0, - 121226, 12999, 0, 120902, 0, 0, 0, 0, 0, 64802, 42210, 4597, 983134, 0, - 0, 12371, 67164, 0, 67163, 10805, 0, 0, 0, 0, 118662, 12367, 0, 0, 92557, - 12363, 0, 0, 128611, 983645, 0, 0, 8005, 12365, 0, 0, 3756, 12369, 10649, - 0, 70095, 0, 0, 0, 42923, 0, 0, 0, 0, 0, 0, 66659, 0, 0, 0, 0, 5268, - 4954, 0, 0, 5266, 126980, 5272, 92294, 0, 42230, 983980, 0, 9128, 0, 0, - 0, 0, 6928, 9803, 42282, 9110, 1505, 0, 0, 5276, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 8722, 120805, 0, 0, 66695, 0, 0, 4383, 8900, 0, 0, 74930, 64297, 0, 0, - 0, 0, 3419, 42229, 0, 0, 8911, 0, 42353, 0, 0, 0, 0, 0, 0, 0, 100629, - 41576, 42215, 122888, 0, 0, 8578, 68178, 7573, 41575, 74789, 92310, 0, - 73863, 0, 2670, 0, 0, 11723, 0, 0, 0, 0, 0, 43414, 0, 0, 65675, 0, 67179, - 67168, 12413, 129746, 67177, 0, 0, 0, 0, 12302, 0, 5250, 12407, 12245, - 4404, 9189, 12401, 42007, 0, 42005, 65806, 43997, 122922, 42002, 12404, - 0, 74928, 4940, 12410, 0, 128761, 0, 64567, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 11956, 0, 0, 122882, 0, 6631, 128923, 120704, 74583, 42218, 0, 0, 70094, - 0, 0, 0, 71058, 0, 0, 0, 127341, 0, 0, 0, 0, 0, 43370, 0, 5016, 121052, - 0, 0, 9491, 0, 0, 0, 0, 64922, 0, 0, 0, 0, 92198, 0, 118622, 0, 74619, 0, - 0, 70422, 983688, 10565, 0, 12177, 0, 0, 0, 0, 0, 12395, 127874, 12878, - 92630, 12396, 0, 0, 92537, 0, 43113, 0, 0, 0, 9781, 0, 4927, 0, 0, 0, 0, - 12397, 129089, 128910, 0, 12394, 0, 0, 0, 0, 0, 72789, 10781, 1546, 0, - 5010, 0, 10507, 127891, 128291, 0, 0, 0, 0, 7267, 0, 0, 0, 0, 2819, 0, 0, - 71063, 0, 7266, 128553, 7264, 7265, 0, 1363, 0, 119581, 65080, 0, 0, 0, - 0, 43336, 67004, 0, 126263, 73776, 0, 43339, 0, 9836, 0, 0, 0, 43335, - 41276, 0, 73795, 43337, 817, 11211, 2241, 128841, 41274, 11340, 42408, - 42447, 74932, 0, 0, 12386, 0, 0, 0, 12389, 128398, 0, 41996, 41686, 0, - 8269, 1147, 43849, 120896, 1987, 128540, 43195, 42001, 41990, 41999, - 12391, 0, 0, 4939, 12384, 0, 0, 43243, 0, 0, 70746, 0, 0, 0, 0, 0, 8247, - 0, 0, 7545, 0, 43643, 121445, 0, 10036, 0, 119813, 10178, 119816, 0, - 119815, 11762, 119818, 0, 92282, 120597, 0, 0, 119819, 0, 0, 7719, 0, - 2486, 0, 119808, 1507, 0, 129185, 70301, 9687, 119825, 0, 119811, 66196, - 0, 5262, 0, 74642, 12681, 0, 0, 12406, 12219, 0, 127528, 42810, 110991, - 0, 983692, 128144, 121027, 126096, 120753, 12403, 2500, 118672, 0, 12409, - 0, 0, 0, 74113, 2343, 12412, 19946, 74112, 125042, 13112, 0, 120603, - 67866, 110634, 0, 66369, 5861, 110632, 11999, 12400, 0, 0, 12645, 0, - 11320, 68410, 6748, 65040, 0, 64184, 12974, 66927, 67613, 120645, 0, 0, - 0, 0, 0, 1928, 0, 67649, 0, 0, 67609, 11235, 0, 0, 67610, 8241, 0, 0, - 4206, 0, 0, 0, 128298, 110980, 0, 67238, 0, 0, 0, 1422, 8357, 0, 7187, 0, - 120641, 0, 0, 0, 0, 125022, 111064, 92539, 10120, 12405, 0, 72997, 0, - 13278, 0, 6366, 0, 7945, 0, 4402, 0, 12402, 129372, 0, 74754, 12408, 0, - 44007, 0, 0, 0, 12411, 0, 120824, 128306, 121092, 0, 1575, 0, 0, 0, - 73003, 119622, 0, 0, 12399, 0, 6833, 0, 0, 0, 71878, 9692, 0, 0, 100615, - 6750, 66855, 0, 0, 0, 0, 43527, 0, 727, 0, 0, 0, 0, 6726, 127387, 0, - 12370, 44023, 0, 126592, 2280, 0, 12372, 120642, 0, 0, 0, 0, 12366, - 10963, 6066, 1329, 0, 3052, 72987, 0, 66029, 0, 10803, 0, 983648, 0, - 92473, 0, 0, 0, 0, 1499, 0, 0, 42740, 0, 0, 0, 0, 12056, 126484, 0, 3660, - 69404, 42192, 74253, 0, 42223, 67617, 125254, 0, 0, 0, 0, 9941, 0, 0, - 1933, 0, 0, 0, 0, 73866, 0, 0, 2487, 67614, 7361, 1804, 0, 67615, 0, 0, - 12220, 67616, 0, 0, 0, 68200, 6675, 0, 0, 67592, 126582, 0, 64771, 0, - 9132, 0, 111004, 510, 0, 0, 0, 4561, 7711, 92769, 92944, 111007, 0, - 41569, 121282, 0, 8167, 66885, 123197, 0, 0, 69992, 66403, 6967, 0, 0, 0, - 0, 333, 0, 0, 10566, 66409, 0, 121373, 0, 72965, 110999, 66388, 6678, 0, - 0, 12621, 0, 128775, 10227, 4764, 0, 9981, 0, 70278, 11589, 0, 0, 42202, - 12754, 0, 0, 69576, 0, 67594, 2048, 0, 4050, 67595, 0, 0, 43221, 11184, - 72709, 0, 0, 64175, 0, 72746, 0, 0, 129966, 65461, 9798, 0, 71210, 0, - 69841, 0, 952, 128235, 125107, 0, 70296, 6449, 72102, 0, 0, 43098, 64171, - 8142, 64160, 0, 0, 0, 0, 0, 0, 0, 0, 67597, 6676, 3930, 42615, 73124, - 69991, 67598, 0, 0, 0, 65591, 41581, 128056, 1453, 0, 0, 0, 8500, 42222, - 0, 119270, 72992, 69996, 0, 0, 64676, 0, 0, 67606, 66385, 0, 42217, - 13102, 0, 67607, 6672, 0, 0, 0, 0, 67608, 0, 9001, 0, 11274, 67601, 0, - 64210, 6664, 0, 42056, 67602, 0, 0, 0, 0, 1469, 67603, 65381, 69921, - 4988, 42372, 0, 9598, 904, 352, 42225, 0, 8061, 10673, 0, 0, 128276, - 67600, 67477, 0, 127293, 8575, 127295, 127296, 127289, 127290, 127291, - 127292, 127285, 127286, 127287, 118877, 127281, 127282, 9460, 823, 11587, - 0, 0, 0, 127305, 12387, 0, 0, 127301, 126979, 42783, 69998, 64208, - 127298, 127299, 66031, 0, 11606, 64784, 0, 69973, 0, 124149, 0, 5152, - 11048, 0, 120121, 67605, 0, 69604, 0, 70276, 194847, 0, 127052, 42587, - 42214, 41394, 0, 4763, 0, 118935, 0, 5260, 0, 94038, 326, 120131, 74119, - 0, 10771, 42198, 194920, 194835, 194925, 41398, 127079, 41393, 127077, - 127076, 453, 41396, 0, 13159, 11227, 9572, 0, 0, 194576, 128835, 127081, - 0, 126617, 43144, 0, 72972, 194887, 0, 0, 0, 0, 0, 64061, 0, 0, 64056, - 70310, 0, 0, 0, 66971, 0, 111084, 64301, 72998, 10464, 0, 128393, 72847, - 0, 11528, 64024, 128072, 679, 0, 0, 5850, 758, 7536, 0, 0, 43712, 0, - 64006, 983589, 64005, 70298, 0, 126487, 0, 0, 0, 0, 0, 72999, 0, 64027, - 64029, 0, 0, 64000, 0, 194874, 0, 42201, 12421, 194875, 0, 1852, 0, 0, - 73744, 0, 64041, 129127, 0, 0, 0, 92322, 12423, 12854, 0, 3496, 0, - 110966, 0, 194823, 0, 0, 6158, 8327, 74553, 0, 12419, 0, 11570, 2169, 0, - 123618, 0, 7844, 983820, 194909, 0, 1682, 93039, 194911, 42756, 6765, - 128178, 0, 0, 0, 11412, 6768, 0, 194830, 71316, 0, 0, 0, 11577, 0, - 194829, 1833, 11576, 74334, 0, 0, 42854, 69438, 0, 70307, 0, 194856, - 8085, 0, 194850, 0, 72996, 128778, 1949, 11614, 7847, 120489, 120997, - 64483, 0, 0, 0, 122639, 0, 0, 0, 126651, 42864, 0, 64667, 74624, 0, 0, - 43261, 11484, 127535, 67840, 0, 0, 128965, 0, 72974, 0, 72456, 8995, - 3455, 0, 0, 9879, 0, 0, 4158, 128050, 0, 0, 110929, 0, 0, 0, 332, 118808, - 0, 0, 2407, 0, 42199, 92386, 110865, 0, 77921, 55217, 123161, 125199, - 70043, 0, 0, 0, 121093, 1834, 0, 0, 71315, 0, 65249, 0, 8662, 0, 0, - 123153, 0, 11539, 10784, 0, 67674, 0, 92233, 0, 0, 118858, 0, 0, 0, 0, 0, - 0, 12499, 6280, 0, 0, 0, 0, 0, 0, 43851, 6279, 12508, 0, 12502, 9161, 0, - 1620, 0, 3601, 0, 0, 67246, 609, 11555, 0, 12496, 0, 74181, 120492, - 12505, 0, 194902, 0, 43567, 239, 0, 127085, 0, 0, 42671, 0, 0, 83095, - 43565, 127082, 983955, 12696, 127753, 0, 94062, 12929, 0, 712, 0, 4197, - 0, 42818, 0, 70306, 0, 0, 983824, 0, 43562, 0, 119506, 68076, 0, 111074, - 64628, 0, 0, 0, 0, 7494, 0, 4924, 0, 0, 0, 0, 72368, 0, 127087, 69987, - 64796, 0, 0, 12033, 119492, 0, 72370, 0, 0, 0, 0, 70299, 0, 0, 68324, - 72420, 0, 0, 0, 0, 70309, 127000, 0, 0, 0, 72418, 72963, 0, 5699, 0, - 983898, 9488, 74410, 119112, 70477, 11170, 0, 0, 72312, 0, 5265, 0, 0, 0, - 0, 12464, 0, 43264, 72977, 0, 43345, 120853, 0, 120592, 6807, 0, 9829, - 69997, 0, 0, 43346, 11393, 795, 0, 72412, 12462, 72416, 72415, 0, 0, - 64362, 0, 0, 120811, 0, 12468, 8607, 1008, 0, 120670, 0, 0, 67855, - 125018, 72372, 6758, 0, 0, 1820, 41112, 0, 11202, 129451, 0, 13223, 0, - 64595, 0, 0, 0, 983649, 12616, 0, 127088, 0, 74467, 0, 0, 0, 0, 0, 0, - 67233, 119060, 0, 83448, 19920, 69897, 0, 129057, 0, 1130, 0, 0, 0, - 11823, 0, 0, 118896, 0, 0, 13280, 0, 10747, 118925, 0, 43509, 0, 0, 8959, - 0, 6747, 0, 0, 8568, 0, 120870, 0, 120803, 83060, 42670, 0, 11621, 12460, - 0, 0, 0, 0, 111188, 0, 66570, 72989, 121305, 126476, 120582, 0, 0, 0, - 111191, 70308, 11594, 0, 68333, 69427, 10491, 0, 0, 0, 0, 0, 127506, 0, - 194910, 4923, 65086, 8981, 0, 42133, 0, 72244, 0, 70294, 0, 0, 12485, 0, - 8642, 0, 42766, 0, 2210, 11109, 0, 0, 0, 0, 0, 7398, 0, 0, 0, 8041, 1461, - 0, 119133, 0, 6749, 0, 0, 0, 71705, 0, 0, 68071, 0, 67668, 0, 0, 9193, 0, - 0, 0, 0, 73810, 0, 0, 64305, 0, 0, 623, 781, 670, 10660, 5769, 613, 7543, - 0, 477, 92633, 92521, 0, 592, 0, 12459, 0, 0, 0, 12465, 119578, 654, - 11345, 653, 652, 111250, 647, 0, 633, 120744, 0, 111262, 12480, 74354, 0, - 39, 12487, 0, 0, 74803, 12482, 0, 12489, 0, 128962, 5550, 129175, 0, 0, - 0, 0, 1813, 0, 41311, 111205, 0, 11229, 0, 70496, 1675, 69840, 129435, 0, - 119078, 10070, 10595, 111207, 119077, 111206, 121162, 0, 0, 0, 11222, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 71716, 917841, 0, 0, 270, 0, 0, 0, 0, 0, - 120561, 0, 69741, 0, 0, 68251, 0, 71721, 364, 9595, 0, 0, 0, 707, 110603, - 0, 9282, 0, 224, 0, 68670, 9332, 65581, 68677, 0, 68644, 0, 11764, 68634, - 0, 10732, 68640, 850, 0, 0, 71123, 0, 68619, 44008, 68627, 0, 0, 0, 0, - 66969, 0, 0, 0, 12507, 0, 0, 128311, 0, 120529, 4375, 0, 0, 0, 12198, 0, - 67339, 0, 0, 72994, 74293, 128434, 0, 0, 64546, 0, 71208, 0, 0, 78916, - 42334, 42502, 0, 120887, 72961, 0, 917838, 5767, 0, 0, 71710, 8353, 0, 0, - 0, 121233, 0, 0, 0, 0, 119920, 0, 0, 121186, 0, 0, 0, 72719, 64604, 0, - 6096, 122632, 10063, 0, 0, 119630, 3485, 12987, 0, 127522, 0, 0, 0, 0, 0, - 0, 0, 0, 127173, 0, 0, 68249, 0, 0, 118923, 0, 64574, 128794, 0, 1640, - 12495, 66691, 0, 3138, 12504, 11171, 1922, 0, 12498, 128733, 0, 69939, 0, - 65543, 0, 0, 0, 66643, 0, 120734, 0, 4228, 0, 10303, 128884, 0, 0, 10335, - 3520, 0, 12490, 0, 0, 0, 12493, 121452, 64636, 1002, 12491, 0, 0, 92615, - 2096, 0, 0, 0, 0, 11611, 66228, 0, 11241, 66224, 66221, 66226, 66229, - 66219, 66231, 66216, 0, 66236, 66211, 66218, 0, 66240, 78041, 66233, - 66217, 0, 7909, 66234, 11605, 0, 0, 66208, 0, 0, 128282, 73875, 0, 12898, - 12494, 120939, 12492, 0, 128774, 0, 74153, 0, 127391, 127489, 4882, - 13040, 0, 120762, 4885, 194732, 0, 13042, 4880, 128834, 2429, 118674, - 8647, 0, 0, 0, 0, 0, 0, 68896, 0, 119101, 66693, 0, 1870, 78040, 470, - 68893, 78035, 78036, 983577, 78034, 110607, 110608, 0, 12511, 74453, - 12514, 0, 128609, 7239, 7001, 11974, 121214, 0, 0, 7378, 12512, 11615, - 13041, 0, 0, 128057, 13038, 0, 0, 71717, 70195, 120836, 12510, 127070, - 13039, 75019, 12513, 71969, 12471, 110761, 0, 121385, 70193, 0, 0, 0, - 71714, 0, 12477, 0, 12473, 7666, 67362, 237, 6281, 0, 0, 0, 0, 1312, 0, - 0, 12469, 0, 0, 64335, 12475, 0, 69382, 0, 11524, 10367, 10431, 74368, - 13017, 3388, 129547, 69573, 0, 0, 128725, 4932, 0, 0, 13015, 0, 0, 65451, - 8185, 0, 0, 2189, 129362, 74375, 10129, 0, 7948, 9236, 0, 0, 69512, - 92726, 43473, 6289, 10484, 0, 0, 0, 12082, 12521, 3147, 110643, 110644, - 12524, 110642, 2310, 0, 0, 0, 0, 13013, 0, 8596, 983871, 10804, 70497, 0, - 0, 13014, 12444, 0, 43088, 13016, 0, 0, 0, 0, 12331, 0, 0, 8744, 726, - 121090, 983868, 4155, 0, 0, 0, 71690, 12522, 73128, 0, 0, 127805, 0, - 110647, 0, 0, 983872, 12525, 0, 12523, 2152, 11969, 120596, 403, 0, - 11021, 0, 0, 11030, 8610, 92567, 0, 0, 63998, 0, 0, 0, 0, 0, 0, 0, 12506, - 0, 11146, 71477, 12500, 0, 12509, 0, 0, 0, 0, 6608, 0, 0, 0, 0, 69288, - 77995, 0, 3608, 0, 0, 1107, 0, 129658, 0, 0, 0, 0, 983956, 43217, 66571, - 13222, 118963, 0, 126514, 10463, 11553, 0, 63995, 9043, 128634, 71722, 0, - 0, 127751, 92974, 12529, 8042, 0, 2344, 12528, 0, 0, 0, 69719, 120956, 0, - 0, 66512, 0, 12530, 0, 0, 68917, 12658, 0, 71683, 0, 983241, 0, 127526, - 469, 0, 4363, 3313, 0, 0, 2023, 0, 72251, 78225, 65706, 10051, 78219, - 78220, 0, 9920, 12215, 0, 4931, 1951, 12497, 119363, 0, 0, 119336, 0, 0, - 0, 0, 0, 1491, 128578, 129169, 0, 0, 0, 0, 78898, 94086, 41993, 0, 67379, - 0, 0, 0, 0, 9738, 41995, 1075, 0, 12535, 41992, 0, 2187, 0, 0, 128117, 0, - 9940, 0, 7692, 0, 9727, 41131, 330, 8566, 0, 41133, 41117, 128482, 12532, - 78550, 78546, 43177, 0, 43235, 0, 917542, 78229, 78231, 13031, 12910, - 67710, 78555, 13028, 78553, 12537, 0, 0, 71692, 12536, 2350, 13029, - 78233, 0, 0, 13030, 0, 4527, 71250, 12538, 0, 0, 0, 0, 0, 0, 0, 12484, - 4032, 71459, 194728, 0, 64344, 0, 66700, 66000, 8412, 0, 43466, 1296, - 2325, 0, 121020, 10149, 74118, 0, 0, 12481, 121280, 12488, 0, 0, 0, - 67972, 0, 2354, 42619, 0, 73027, 6295, 901, 0, 0, 0, 0, 0, 128653, 11927, - 66584, 78559, 78560, 78557, 78558, 0, 74649, 0, 126241, 67220, 194726, - 78568, 67226, 78565, 70190, 78563, 78564, 2352, 67219, 78569, 71945, - 11289, 1407, 67973, 0, 13026, 6762, 10399, 70192, 13023, 78578, 9777, - 67208, 1871, 0, 0, 0, 13024, 71936, 0, 9325, 6818, 6283, 11738, 0, 0, - 71938, 11741, 0, 0, 9216, 8263, 11279, 0, 983856, 0, 13021, 71922, 3136, - 0, 983859, 0, 13022, 129143, 9956, 0, 0, 0, 42580, 0, 0, 0, 13020, 10024, - 0, 94013, 0, 0, 0, 43001, 8029, 0, 0, 0, 3335, 127924, 9209, 13048, - 73126, 0, 0, 0, 3333, 119100, 0, 0, 3342, 78582, 78583, 73056, 78581, - 4156, 0, 0, 0, 78591, 1611, 73058, 13018, 78586, 78588, 78584, 3337, - 4537, 78593, 11736, 0, 0, 0, 4214, 73790, 0, 0, 13046, 194844, 425, - 74763, 42066, 78595, 0, 2392, 13047, 0, 0, 12425, 13049, 0, 92243, 0, - 72715, 73944, 13050, 0, 0, 0, 0, 983506, 0, 0, 8929, 6849, 0, 0, 0, - 983990, 0, 13045, 0, 0, 7751, 0, 9726, 0, 3997, 0, 8768, 13044, 0, 0, - 4024, 0, 0, 2419, 9757, 69736, 0, 0, 0, 129500, 0, 0, 0, 72735, 0, 0, 0, - 0, 0, 11911, 124990, 0, 2346, 194691, 69931, 0, 9646, 3773, 43557, 68154, - 42536, 0, 70108, 13043, 92686, 92494, 0, 208, 0, 43766, 0, 0, 0, 10699, - 0, 0, 7825, 7110, 111275, 0, 111274, 41109, 2398, 111271, 0, 0, 0, 0, 0, - 0, 72723, 8294, 42912, 129343, 0, 0, 4876, 111316, 0, 111326, 111282, 0, - 0, 0, 73950, 13053, 9944, 0, 2811, 13051, 111313, 3143, 111246, 66374, - 110759, 0, 0, 13052, 0, 0, 63972, 119071, 7025, 0, 0, 100464, 74161, - 4154, 9863, 129686, 0, 0, 63970, 1564, 0, 0, 0, 0, 0, 9942, 0, 0, 111227, - 0, 128471, 0, 63957, 0, 1626, 0, 63983, 2161, 111232, 0, 0, 121275, - 111292, 6254, 4910, 69453, 0, 64753, 100458, 111303, 111204, 127404, - 111297, 3229, 111306, 42774, 0, 0, 111218, 111286, 2331, 0, 7085, 6137, - 0, 70411, 0, 126070, 0, 128438, 0, 0, 65043, 0, 127588, 70412, 128921, - 64721, 0, 0, 0, 0, 0, 983789, 0, 0, 5311, 0, 965, 0, 11993, 78055, 11278, - 128787, 0, 0, 0, 121076, 120705, 0, 6294, 3144, 0, 0, 65019, 0, 0, 0, 0, - 118721, 63966, 2330, 535, 3148, 12375, 110774, 0, 10556, 2475, 12388, - 4889, 0, 67863, 120404, 0, 72750, 2342, 0, 0, 0, 4894, 0, 4890, 0, 0, 0, - 4893, 128426, 6571, 118581, 4888, 4157, 78048, 78049, 78046, 11263, 0, - 78045, 64895, 121437, 0, 0, 0, 0, 0, 119041, 2332, 78063, 78060, 78061, - 64932, 78059, 65125, 121098, 0, 0, 129991, 73941, 78066, 12203, 78064, - 78065, 8913, 120390, 4875, 73678, 120396, 120389, 71854, 0, 120394, - 120386, 120395, 13104, 78076, 78077, 120393, 78075, 0, 3134, 83096, - 65696, 72432, 0, 0, 0, 8334, 0, 83207, 3449, 0, 0, 83215, 0, 0, 0, 83204, - 0, 0, 0, 69707, 0, 0, 10734, 0, 83198, 83108, 7804, 121401, 83166, 8457, - 83212, 0, 11367, 0, 78054, 0, 72762, 0, 64285, 0, 5464, 0, 83100, 2361, - 7971, 78072, 78073, 78070, 78071, 0, 8086, 0, 6707, 0, 2312, 40977, 0, - 40962, 0, 0, 74962, 40980, 0, 0, 0, 40970, 92895, 110823, 0, 42438, - 72752, 6288, 0, 127946, 5653, 42400, 10891, 73946, 5658, 70401, 0, 0, 0, - 0, 71060, 0, 0, 42326, 100482, 92191, 92685, 42478, 2327, 0, 12959, - 42287, 92883, 0, 83081, 917550, 0, 0, 2867, 128562, 66312, 698, 0, 0, 0, - 70017, 0, 8000, 12641, 83140, 0, 0, 129064, 0, 72979, 83133, 0, 83134, 0, - 0, 111011, 92960, 74356, 0, 74562, 0, 72745, 0, 0, 120568, 0, 0, 0, 0, 0, - 8703, 5462, 83195, 0, 10101, 0, 70049, 0, 0, 128793, 0, 0, 66254, 120821, - 0, 1565, 123621, 0, 119194, 0, 42651, 0, 0, 917847, 83227, 83218, 0, - 75011, 0, 129724, 0, 64399, 0, 12899, 74564, 0, 42206, 0, 72718, 71715, - 83149, 983794, 83146, 12192, 917826, 0, 0, 0, 0, 68056, 0, 67426, 128687, - 0, 0, 0, 0, 0, 0, 67431, 71718, 74357, 0, 121176, 43596, 6090, 0, 7812, - 10534, 0, 0, 0, 0, 129763, 0, 0, 0, 0, 0, 0, 43306, 0, 0, 0, 7930, 0, - 2292, 0, 0, 72737, 0, 6130, 0, 0, 0, 0, 0, 70463, 968, 0, 0, 0, 43304, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 11838, 0, 0, 0, 42682, 0, 0, 0, 41227, 0, - 71475, 0, 64848, 0, 78574, 0, 113792, 0, 0, 129133, 0, 66015, 74614, 959, - 8885, 0, 0, 0, 9469, 9632, 128211, 74761, 64323, 100478, 0, 2266, 78575, - 310, 0, 0, 68403, 100480, 72738, 125279, 0, 0, 6497, 127320, 0, 0, 19958, - 0, 128691, 74953, 0, 118998, 67332, 374, 0, 41933, 120975, 0, 0, 41934, - 7465, 0, 128168, 70666, 11151, 6101, 0, 41936, 100476, 4879, 0, 65446, 0, - 0, 983695, 0, 5374, 0, 128059, 127390, 0, 126618, 983575, 129146, 0, 0, - 1929, 0, 12142, 0, 0, 0, 121472, 0, 12982, 0, 5378, 0, 128679, 0, 0, - 127869, 0, 127343, 0, 0, 0, 78832, 74481, 0, 43262, 100511, 2421, 0, - 2324, 828, 3611, 121055, 0, 64314, 0, 0, 0, 0, 0, 0, 7999, 0, 11217, - 983266, 10634, 10942, 0, 2348, 0, 0, 0, 0, 118587, 9982, 64324, 41240, 0, - 100470, 78462, 1810, 0, 92566, 71299, 0, 0, 917848, 0, 0, 100515, 0, 0, - 0, 43912, 128385, 0, 0, 0, 917850, 0, 7485, 0, 129382, 74576, 44019, - 128171, 917851, 3967, 129335, 0, 0, 0, 0, 119096, 0, 0, 8699, 723, 83084, - 966, 0, 0, 0, 128428, 78778, 2320, 0, 65740, 4968, 0, 0, 8075, 55276, - 123589, 8047, 983787, 78827, 12634, 0, 78781, 71322, 0, 12174, 42610, 0, - 0, 0, 1584, 0, 6045, 0, 0, 65218, 11559, 0, 0, 0, 124991, 0, 2257, 64418, - 0, 0, 0, 0, 0, 0, 67821, 0, 13092, 0, 128365, 0, 0, 0, 0, 0, 11414, 0, - 2531, 13034, 0, 0, 0, 13036, 0, 70866, 70198, 10394, 129979, 13037, 0, - 129956, 0, 0, 100496, 120640, 41129, 0, 42850, 13035, 0, 0, 5466, 0, 0, - 0, 129439, 4535, 0, 4271, 0, 0, 6769, 0, 0, 67350, 6767, 0, 66273, 0, - 6755, 73827, 9046, 67355, 0, 0, 0, 0, 0, 0, 0, 0, 92221, 83235, 2563, - 13033, 247, 83229, 0, 12338, 0, 83231, 11270, 0, 0, 0, 0, 70107, 0, 0, 0, - 0, 3752, 83243, 68895, 66973, 68897, 0, 0, 0, 0, 5009, 0, 0, 0, 0, - 119521, 78823, 78824, 70353, 68399, 3877, 0, 78825, 10145, 43566, 0, 0, - 10236, 0, 43782, 0, 127329, 0, 69652, 2247, 120612, 128058, 0, 43200, - 43777, 71253, 983644, 69558, 0, 71866, 43203, 0, 68894, 0, 127326, 0, - 43778, 119538, 0, 0, 43781, 11303, 65547, 0, 7031, 0, 0, 67343, 83237, - 83267, 0, 67341, 120522, 8535, 0, 0, 0, 66032, 0, 0, 120786, 42233, 0, - 9946, 7667, 0, 11822, 0, 43189, 120673, 100507, 2979, 1579, 0, 0, 0, 0, - 0, 12635, 71337, 0, 94055, 0, 1285, 64882, 0, 0, 83113, 12640, 83112, - 7401, 92869, 12625, 0, 71296, 72744, 0, 74286, 55260, 3396, 12642, 0, - 110719, 0, 12630, 0, 0, 10153, 0, 6166, 120516, 0, 110680, 0, 0, 119499, - 9285, 913, 42259, 83017, 0, 2142, 127889, 0, 94012, 7878, 0, 72733, 0, 0, - 0, 0, 92868, 0, 0, 0, 0, 128918, 5263, 74782, 0, 41939, 43702, 0, 917856, - 0, 10139, 980, 43698, 0, 2208, 0, 43701, 0, 125132, 0, 100528, 0, 10085, - 0, 0, 119989, 100529, 0, 71699, 0, 8072, 0, 43700, 0, 7304, 7783, 66894, - 12398, 0, 0, 0, 0, 0, 0, 120565, 0, 2217, 0, 94015, 6367, 0, 66688, 0, 0, - 0, 0, 0, 92199, 7808, 1829, 0, 41937, 0, 43272, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 92467, 6627, 0, 6258, 10683, 0, 0, 0, 5649, 0, 0, 0, 1643, 127898, - 0, 127846, 67244, 0, 42452, 0, 0, 0, 0, 64291, 0, 0, 0, 6576, 74773, 0, - 0, 66309, 0, 9886, 55225, 11292, 0, 72867, 55227, 0, 12632, 0, 194817, 0, - 7680, 0, 92745, 120714, 12639, 3380, 8123, 0, 12638, 42262, 4501, 0, 0, - 0, 0, 125131, 1494, 983147, 0, 0, 0, 0, 10494, 0, 65872, 0, 0, 0, 0, 0, - 0, 983587, 0, 0, 0, 0, 0, 0, 0, 71077, 0, 127335, 121128, 0, 5570, 1881, - 7210, 0, 1012, 66630, 0, 128982, 7208, 66442, 5569, 113723, 42339, 92655, - 0, 0, 0, 0, 92378, 65602, 0, 92375, 64727, 9160, 0, 0, 0, 124928, 10503, - 0, 3423, 3870, 8483, 10162, 0, 4319, 0, 0, 0, 0, 0, 983117, 0, 69562, 0, - 0, 0, 0, 0, 0, 5571, 7630, 9740, 9121, 5568, 0, 0, 42085, 0, 0, 65056, 0, - 589, 0, 0, 0, 10233, 66252, 66251, 78734, 66253, 0, 0, 42645, 0, 128424, - 8583, 0, 0, 0, 129932, 0, 0, 0, 0, 0, 12204, 92436, 120453, 0, 0, 0, - 983262, 0, 0, 70311, 0, 0, 128012, 41063, 0, 10664, 0, 983660, 0, 4551, - 129090, 74759, 0, 983270, 0, 0, 72806, 0, 0, 12517, 7806, 0, 12034, 0, - 6355, 12519, 41004, 0, 0, 93849, 0, 71707, 0, 121231, 7332, 129075, - 12111, 3927, 0, 12515, 1474, 68768, 0, 6923, 69509, 0, 127802, 0, 43990, - 74639, 126229, 121007, 0, 92706, 0, 0, 0, 0, 0, 9645, 0, 121026, 5853, 0, - 10363, 120729, 12956, 0, 0, 0, 0, 127888, 0, 0, 0, 0, 0, 10514, 65517, 0, - 0, 71101, 0, 0, 0, 43570, 2969, 43420, 129944, 0, 0, 92366, 70809, 0, 0, - 0, 0, 0, 118714, 12125, 41124, 0, 1164, 128817, 0, 120466, 0, 0, 65014, - 66009, 74451, 125075, 983129, 7469, 0, 0, 0, 69988, 120671, 83171, 41123, - 11176, 0, 0, 41126, 9991, 41128, 0, 0, 110949, 0, 0, 42877, 7994, 0, - 6104, 983612, 0, 129869, 0, 0, 0, 0, 74438, 128272, 121409, 41981, 0, - 69296, 42904, 0, 0, 74435, 126640, 0, 0, 0, 127968, 92442, 12703, 9661, - 67360, 67359, 7455, 70732, 11473, 119217, 128512, 0, 92323, 0, 0, 129632, - 67358, 0, 0, 0, 0, 174, 121131, 883, 4161, 128033, 42603, 0, 0, 72256, 0, - 0, 128356, 0, 0, 0, 0, 3846, 8070, 6150, 128109, 4370, 118617, 0, 0, - 74587, 0, 0, 0, 0, 4986, 12189, 917553, 67648, 120499, 0, 4257, 71695, - 123620, 6220, 0, 65561, 0, 0, 0, 0, 122652, 0, 0, 0, 69684, 0, 0, 128452, - 120873, 0, 0, 74922, 0, 71897, 0, 0, 67368, 67367, 8871, 67366, 0, 0, 0, - 0, 0, 67361, 0, 0, 67365, 67364, 3427, 4240, 67376, 67375, 67374, 67373, - 0, 0, 0, 67377, 0, 71689, 0, 0, 67372, 67371, 67370, 67369, 0, 0, 0, - 124962, 0, 0, 0, 0, 65898, 0, 65312, 0, 0, 0, 0, 4010, 121208, 41106, 0, - 0, 0, 41105, 0, 64803, 83456, 0, 0, 0, 0, 0, 0, 0, 11008, 0, 0, 71351, - 41110, 71681, 64892, 9113, 1954, 41108, 0, 42878, 0, 67405, 0, 0, 0, 0, - 0, 119539, 69435, 73463, 0, 4586, 129342, 0, 0, 0, 0, 0, 125233, 92307, - 0, 0, 0, 67382, 0, 9500, 0, 4957, 0, 2422, 2212, 0, 67381, 67380, 11045, - 67378, 0, 0, 3890, 12168, 121328, 0, 0, 0, 41947, 0, 120828, 74946, - 917901, 0, 1571, 66461, 41949, 42805, 8270, 943, 41946, 0, 2073, 0, - 41980, 0, 0, 0, 0, 4429, 6272, 0, 1460, 6954, 128572, 41120, 0, 65733, 0, - 41119, 0, 127006, 0, 0, 0, 129168, 12895, 0, 0, 0, 69440, 0, 1985, 6296, - 0, 0, 0, 0, 0, 41122, 0, 2457, 0, 0, 0, 0, 0, 0, 8840, 8035, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 8681, 0, 121505, 128747, 0, 0, 70102, 0, 124976, 9605, - 0, 13220, 0, 67354, 11312, 0, 9246, 67349, 0, 0, 0, 0, 10012, 12123, 0, - 0, 0, 0, 983846, 0, 0, 0, 67817, 0, 1272, 0, 0, 0, 983578, 0, 1467, - 119501, 917806, 0, 0, 0, 70312, 73537, 124955, 0, 70400, 0, 0, 72817, 0, - 19935, 0, 92162, 0, 0, 0, 128406, 5275, 0, 0, 44006, 129082, 0, 3789, - 128205, 0, 0, 0, 11474, 0, 0, 0, 129050, 0, 92194, 129503, 9537, 4496, 0, - 120443, 2605, 4500, 0, 55224, 8600, 0, 0, 41646, 11667, 69569, 0, 0, - 917905, 4499, 41649, 0, 0, 0, 69254, 0, 0, 0, 65804, 0, 70034, 41866, 0, - 0, 0, 11174, 0, 0, 0, 9559, 128773, 41940, 8299, 41945, 0, 41941, 5455, - 7190, 0, 0, 917810, 65266, 0, 41943, 10762, 0, 41931, 0, 0, 8106, 4128, - 0, 0, 4494, 0, 0, 72405, 0, 119567, 42068, 917808, 0, 11004, 12794, - 65072, 5271, 7317, 0, 0, 0, 0, 0, 0, 92281, 0, 0, 0, 0, 71880, 3868, - 71881, 983573, 128431, 7703, 0, 64390, 0, 7406, 120358, 93850, 0, 3985, - 66425, 0, 66615, 10177, 0, 41853, 71873, 12809, 0, 12193, 0, 10879, - 122945, 0, 9055, 0, 3851, 8132, 0, 0, 119263, 917908, 0, 0, 0, 0, 122940, - 42657, 122952, 7643, 0, 0, 122936, 43568, 0, 11949, 7650, 43569, 64951, - 7647, 7649, 0, 7646, 0, 0, 9651, 125005, 3891, 0, 0, 2337, 77831, 77832, - 67860, 129288, 0, 0, 43561, 67706, 119669, 0, 1860, 0, 68835, 5812, - 12784, 0, 0, 0, 0, 69260, 7727, 0, 69292, 69818, 66444, 128665, 42719, 0, - 1569, 0, 12534, 12124, 7690, 194871, 12533, 0, 68383, 67997, 0, 6969, 0, - 0, 0, 67974, 63895, 128650, 0, 0, 0, 42144, 0, 0, 0, 0, 92211, 119043, 0, - 0, 917545, 0, 0, 12791, 0, 0, 0, 4447, 71065, 12793, 0, 0, 43385, 0, 0, - 12790, 120256, 0, 983840, 12792, 120254, 0, 0, 12789, 128489, 12317, - 74934, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127840, 41652, 2974, 78689, 11476, - 0, 0, 0, 0, 43871, 0, 10894, 119176, 74557, 65686, 0, 0, 3724, 67335, - 67334, 67333, 67338, 67337, 0, 67336, 0, 65306, 0, 128421, 0, 8646, - 129593, 77829, 0, 0, 74852, 0, 0, 0, 0, 0, 220, 120252, 43551, 0, 10044, - 0, 0, 983847, 68659, 110825, 5707, 71362, 0, 0, 0, 0, 0, 0, 10297, 0, - 41308, 67331, 0, 0, 0, 0, 2467, 0, 6003, 0, 0, 8040, 0, 0, 4182, 0, - 11135, 120501, 0, 0, 2510, 0, 10208, 0, 78302, 70829, 0, 0, 6837, 0, 0, - 67348, 0, 0, 0, 0, 1559, 67342, 11104, 67340, 67347, 67346, 67345, 67344, - 0, 0, 67357, 67356, 0, 0, 0, 0, 67352, 67351, 5516, 2845, 7717, 8036, - 65161, 67353, 5514, 12045, 6278, 0, 5515, 0, 0, 0, 0, 0, 65194, 100387, - 5517, 70116, 92774, 0, 67884, 0, 67890, 42094, 67880, 67881, 67882, - 67883, 0, 0, 67879, 120411, 1902, 67887, 67888, 12976, 126546, 12483, - 12368, 41769, 42726, 41765, 69557, 12787, 67874, 7556, 67878, 74351, - 67897, 989, 42677, 67889, 0, 6060, 0, 4326, 11000, 64601, 68478, 0, 0, - 6917, 0, 120837, 0, 0, 0, 6148, 8605, 74205, 0, 0, 0, 42715, 0, 101047, - 0, 68663, 0, 41796, 1269, 42703, 64754, 101049, 101042, 5144, 12221, - 42716, 71048, 5133, 4331, 0, 128675, 0, 5279, 121362, 71046, 0, 0, 42701, - 0, 0, 0, 121470, 0, 0, 0, 983311, 0, 72455, 121259, 42666, 12207, 1067, - 255, 12131, 0, 0, 0, 0, 0, 0, 0, 70728, 43460, 0, 42723, 125216, 0, - 70427, 0, 12797, 0, 0, 983722, 0, 67977, 12799, 0, 92504, 9746, 5135, 0, - 12796, 0, 0, 0, 5139, 346, 74303, 121134, 12795, 125109, 5168, 0, 43845, - 983727, 0, 8253, 8817, 1136, 983735, 43563, 127774, 129542, 0, 0, 0, 0, - 0, 0, 983619, 0, 0, 4041, 0, 2357, 43240, 12786, 0, 0, 0, 44004, 7142, 0, - 67984, 0, 0, 0, 0, 12785, 0, 0, 7770, 10712, 64853, 42679, 118916, 42375, - 0, 983124, 94074, 12119, 0, 11059, 10791, 111092, 450, 0, 0, 0, 0, 5450, - 64691, 0, 0, 44009, 0, 0, 111097, 94085, 1839, 94004, 0, 10927, 1701, 0, - 129610, 41749, 41761, 5453, 8361, 66045, 41758, 5444, 41763, 0, 0, 0, - 66349, 983138, 121274, 0, 0, 8801, 0, 4340, 0, 0, 0, 0, 70001, 41824, 0, - 0, 0, 0, 42700, 0, 127980, 0, 0, 0, 0, 0, 0, 4493, 4336, 129171, 2314, - 983061, 41808, 0, 0, 0, 64638, 0, 65937, 4489, 71331, 0, 0, 5358, 42717, - 0, 71236, 0, 0, 0, 127042, 41813, 2712, 0, 127044, 1410, 0, 0, 0, 0, 0, - 0, 0, 0, 128587, 0, 0, 0, 4892, 0, 0, 0, 0, 122966, 5777, 0, 759, 0, - 2079, 65248, 12788, 0, 64552, 0, 41803, 68043, 0, 0, 0, 0, 128785, 0, - 68492, 67991, 75071, 2340, 0, 120638, 0, 983902, 0, 0, 917865, 64749, 0, - 2321, 3587, 0, 67236, 9953, 9952, 0, 0, 42714, 9951, 0, 0, 127902, 74150, - 0, 0, 74757, 127554, 0, 983826, 2395, 0, 9976, 0, 125128, 0, 0, 0, 42809, - 42807, 0, 66290, 70854, 4150, 64424, 8318, 41790, 67976, 65559, 2360, - 41794, 0, 0, 120987, 0, 0, 2418, 0, 2411, 0, 41783, 0, 41786, 65108, 0, - 0, 41772, 42813, 2317, 0, 118980, 0, 0, 0, 0, 0, 0, 78682, 7753, 2351, - 6655, 64489, 0, 0, 0, 4443, 41697, 230, 65793, 0, 65943, 42803, 0, 0, - 5441, 0, 0, 127053, 0, 855, 0, 6109, 101021, 0, 119116, 69989, 0, 0, - 72146, 0, 101023, 0, 72148, 124918, 19915, 41892, 0, 0, 128901, 41887, 0, - 67980, 9735, 0, 0, 120591, 13082, 101026, 0, 0, 0, 0, 0, 0, 0, 289, 0, 0, - 64504, 0, 69489, 120514, 0, 92962, 0, 42724, 69977, 0, 0, 0, 0, 67994, 0, - 0, 983823, 3565, 0, 0, 127553, 43035, 69898, 0, 0, 0, 0, 4891, 0, 0, - 4602, 0, 121065, 0, 0, 121157, 0, 43978, 8988, 0, 0, 0, 0, 0, 119184, - 121436, 73902, 69740, 0, 0, 72976, 0, 0, 8771, 0, 0, 0, 119209, 74974, - 71737, 0, 0, 67987, 0, 0, 0, 67989, 0, 10065, 8207, 0, 983588, 0, 0, 662, - 0, 41927, 0, 0, 0, 0, 0, 0, 0, 41929, 0, 0, 0, 41926, 69994, 0, 0, 0, - 126230, 68013, 1433, 64648, 6475, 0, 120983, 0, 73876, 0, 0, 0, 67992, - 78052, 0, 3978, 0, 0, 0, 0, 120761, 12281, 0, 0, 13241, 0, 0, 0, 0, - 11765, 42577, 0, 0, 2641, 7192, 0, 0, 118809, 101015, 0, 101016, 128948, - 101013, 6479, 64294, 118683, 0, 0, 0, 64334, 0, 0, 0, 92266, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 9478, 127339, 124964, 0, 202, 0, 0, 1242, 0, 121170, 0, - 63940, 0, 0, 0, 63939, 11990, 92430, 67982, 0, 65440, 70068, 0, 0, 64829, - 0, 0, 0, 0, 0, 2858, 0, 63989, 0, 69239, 0, 121152, 0, 77841, 0, 70078, - 92574, 129519, 0, 0, 0, 128974, 0, 12922, 92498, 0, 66424, 71124, 0, 0, - 0, 2856, 0, 47, 0, 126986, 65858, 0, 0, 0, 0, 119161, 8417, 65903, 0, 0, - 0, 4033, 128164, 0, 0, 0, 129961, 64600, 1903, 12320, 0, 120894, 0, 0, - 8915, 0, 945, 0, 0, 0, 0, 111068, 0, 74828, 0, 69560, 9531, 0, 8505, 0, - 119238, 0, 0, 65538, 0, 0, 0, 0, 0, 0, 63935, 0, 0, 0, 0, 0, 64787, - 111060, 0, 0, 110828, 0, 2230, 0, 0, 71886, 9843, 0, 92419, 111062, - 67488, 92715, 0, 1320, 0, 1673, 0, 92383, 129902, 9338, 128355, 0, 0, 0, - 0, 11997, 0, 0, 0, 0, 0, 0, 43308, 0, 0, 0, 0, 0, 0, 0, 63920, 0, 0, 0, - 0, 0, 0, 3514, 78723, 0, 7492, 0, 0, 0, 7514, 0, 63924, 0, 7502, 7587, 0, - 0, 0, 118689, 43881, 7610, 0, 0, 118710, 692, 43588, 0, 0, 75056, 9688, - 0, 9535, 0, 0, 0, 64530, 0, 125251, 194861, 0, 72209, 7453, 0, 8013, - 66396, 0, 0, 8895, 5356, 0, 5458, 0, 2866, 0, 127860, 71732, 71724, 6700, - 0, 111081, 120583, 0, 110614, 0, 9641, 63830, 65294, 0, 0, 67969, 0, - 7441, 0, 63826, 0, 0, 0, 0, 2844, 983972, 0, 63824, 12139, 67971, 0, 0, - 3358, 65295, 0, 3104, 0, 0, 0, 0, 65772, 0, 0, 0, 0, 2862, 11326, 0, 0, - 94001, 3268, 66591, 0, 6552, 42367, 7035, 120558, 0, 0, 1814, 195092, - 10240, 195093, 0, 0, 0, 0, 0, 66960, 0, 0, 2837, 4341, 0, 0, 129982, - 125064, 195094, 0, 0, 66964, 0, 72721, 863, 66936, 0, 0, 43323, 66928, 0, - 0, 68054, 0, 3654, 66951, 0, 66942, 0, 0, 7653, 0, 0, 66587, 0, 0, 92401, - 0, 0, 12927, 0, 0, 129697, 13056, 0, 0, 3056, 0, 0, 195101, 0, 0, 74506, - 73770, 0, 0, 0, 0, 0, 0, 0, 0, 72233, 0, 5811, 0, 0, 0, 66817, 983855, 0, - 0, 128636, 129311, 0, 128041, 0, 67739, 120965, 0, 0, 67507, 0, 68375, 0, - 0, 70300, 0, 0, 0, 983698, 111078, 0, 11991, 128079, 0, 92943, 1502, - 74117, 127988, 0, 129478, 121253, 0, 67661, 0, 0, 125084, 68667, 0, - 74057, 68639, 0, 42898, 120742, 0, 74388, 74838, 120822, 0, 0, 0, 0, - 69452, 43214, 5893, 0, 0, 92496, 0, 0, 119907, 119900, 0, 0, 0, 0, 41950, - 0, 0, 68610, 0, 68626, 894, 0, 0, 12306, 73846, 0, 0, 0, 8636, 0, 121028, - 42503, 0, 92942, 0, 121468, 119241, 0, 126569, 5096, 5095, 2863, 127505, - 0, 10454, 42530, 5094, 0, 0, 13156, 0, 111035, 5093, 111024, 983419, 0, - 5092, 10708, 11327, 0, 5091, 0, 0, 9153, 4104, 78599, 78601, 2929, 42712, - 75067, 12272, 9832, 0, 0, 111105, 0, 0, 0, 0, 0, 0, 13106, 0, 0, 129111, - 0, 0, 0, 0, 9074, 111111, 0, 111110, 0, 8113, 11168, 92563, 1786, 111109, - 0, 111108, 0, 74423, 0, 586, 74414, 64359, 1267, 0, 127531, 0, 65731, 0, - 0, 0, 92932, 0, 0, 0, 0, 0, 0, 1228, 0, 42846, 0, 0, 70343, 1714, 74406, - 0, 0, 0, 127389, 66225, 0, 0, 42660, 0, 0, 3804, 0, 0, 129859, 0, 2826, - 0, 0, 0, 128396, 0, 0, 0, 0, 0, 0, 12206, 5839, 0, 68524, 74065, 73521, - 0, 0, 126240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67241, 917821, 7030, 0, - 10479, 64959, 2852, 0, 121225, 0, 0, 128586, 0, 6963, 0, 0, 0, 74786, 0, - 0, 0, 0, 121281, 0, 0, 0, 0, 113815, 121360, 0, 9994, 118680, 2864, - 64719, 1148, 0, 41677, 0, 0, 2765, 0, 128181, 0, 0, 0, 92516, 74777, 0, - 0, 65206, 0, 0, 0, 0, 69391, 0, 0, 983770, 0, 41839, 129616, 983773, 0, - 0, 6931, 0, 0, 7177, 125137, 0, 0, 0, 93020, 0, 10722, 0, 0, 128186, - 121050, 0, 0, 127207, 0, 750, 0, 129453, 63912, 0, 0, 7032, 0, 0, 4314, - 128600, 0, 128409, 730, 0, 127866, 0, 0, 41380, 0, 0, 0, 69697, 8240, - 92939, 0, 41378, 0, 6938, 70026, 0, 0, 66246, 0, 0, 0, 0, 0, 0, 983094, - 0, 92754, 41470, 64805, 0, 0, 0, 0, 0, 0, 0, 0, 92938, 68370, 0, 0, - 73831, 0, 0, 0, 2872, 0, 0, 0, 0, 604, 41097, 0, 0, 0, 0, 0, 127488, 0, - 2836, 0, 0, 9707, 0, 43202, 0, 0, 69374, 0, 0, 120916, 2832, 92702, 9670, - 12937, 0, 0, 0, 0, 2822, 0, 0, 92519, 0, 73752, 0, 0, 0, 1331, 92603, 0, - 11856, 73510, 129432, 5090, 5089, 0, 3200, 0, 0, 0, 5088, 0, 0, 9477, 0, - 0, 5087, 92325, 0, 96, 5086, 0, 0, 0, 5085, 64286, 0, 0, 43820, 0, - 129710, 0, 0, 119042, 0, 129660, 0, 0, 0, 0, 0, 127241, 120891, 7601, 0, - 591, 0, 118953, 0, 0, 0, 0, 0, 10939, 7246, 6933, 67142, 67141, 0, 74600, - 120695, 0, 67138, 65574, 0, 78058, 67140, 73851, 74598, 67139, 128094, 0, - 6372, 0, 73514, 7963, 6371, 0, 0, 125040, 0, 0, 0, 0, 0, 0, 0, 8258, - 123591, 0, 0, 65148, 118919, 42, 0, 0, 0, 0, 0, 0, 0, 0, 67135, 67134, - 67133, 0, 0, 0, 0, 67136, 67130, 74597, 11550, 0, 67132, 65868, 0, 12826, - 127872, 124116, 126235, 9737, 92448, 0, 0, 0, 8878, 0, 0, 0, 0, 0, 72220, - 9086, 0, 100952, 0, 7437, 7454, 0, 0, 0, 0, 9042, 0, 0, 0, 0, 3805, 0, - 67128, 44001, 67126, 0, 44022, 19949, 12200, 43522, 983045, 43525, 0, 0, - 0, 64422, 67125, 67124, 7602, 0, 0, 43521, 0, 0, 43711, 43523, 41447, - 8424, 68483, 8704, 2397, 0, 0, 0, 0, 0, 10916, 0, 129290, 93998, 0, 0, 0, - 127800, 67686, 9961, 123203, 0, 68842, 10792, 8889, 121402, 6951, 0, - 68827, 917835, 74342, 0, 0, 0, 68816, 129152, 0, 42909, 66597, 70092, 0, - 0, 10481, 4559, 0, 1956, 43138, 0, 0, 43490, 43148, 0, 0, 0, 43140, 0, 0, - 0, 0, 69268, 8533, 0, 0, 0, 0, 0, 4357, 0, 70289, 983157, 0, 42911, 0, 0, - 0, 10941, 0, 6962, 0, 0, 113808, 0, 11014, 0, 8942, 12000, 0, 0, 73515, - 0, 0, 0, 42650, 0, 75016, 63975, 0, 66210, 0, 0, 129150, 0, 11193, 0, 0, - 0, 0, 0, 0, 0, 43476, 0, 11024, 74811, 72787, 10563, 92954, 0, 0, 2462, - 92955, 0, 0, 66213, 6957, 0, 120559, 0, 0, 0, 74594, 983424, 92347, 0, - 110702, 110708, 110707, 127119, 3109, 127117, 119909, 0, 121434, 0, 0, - 4042, 0, 0, 0, 127123, 127122, 127121, 0, 127999, 0, 3503, 74444, 68300, - 6694, 127997, 0, 0, 74306, 0, 983757, 7736, 0, 0, 0, 10521, 0, 42173, - 9705, 0, 129719, 6955, 71467, 0, 6149, 3887, 19956, 1411, 2824, 0, 0, 0, - 1403, 0, 1347, 66282, 127996, 0, 0, 0, 0, 8640, 0, 1178, 1654, 0, 0, - 129529, 43314, 0, 0, 0, 0, 2873, 67461, 0, 0, 67085, 10861, 0, 0, 70377, - 0, 67082, 11159, 41391, 67084, 0, 376, 6987, 983182, 119904, 0, 8823, 0, - 12943, 65185, 100988, 42099, 0, 0, 100990, 0, 8301, 0, 0, 1684, 0, 0, 0, - 120620, 0, 0, 0, 42121, 0, 66781, 78067, 42115, 0, 127998, 0, 67080, - 1493, 42111, 67077, 4097, 0, 983767, 0, 65808, 41642, 0, 118568, 67076, - 41636, 67074, 65095, 110660, 72254, 121240, 41629, 12154, 75073, 0, - 128179, 74084, 64380, 0, 0, 0, 0, 0, 71193, 65371, 7078, 121218, 0, 0, - 74592, 0, 0, 43275, 0, 41434, 6062, 0, 0, 19916, 0, 6950, 9606, 9842, 0, - 65744, 0, 0, 128659, 0, 41615, 10105, 0, 0, 41632, 7493, 0, 0, 41622, 0, - 0, 0, 0, 7632, 983217, 983216, 9805, 5990, 900, 0, 122955, 0, 120869, - 3612, 0, 64376, 0, 5389, 129469, 73495, 0, 2839, 9621, 582, 0, 0, 3749, - 0, 7569, 0, 0, 92865, 6956, 4403, 0, 0, 3299, 0, 0, 119127, 65676, 0, - 74372, 0, 983497, 7598, 69819, 42469, 42242, 1918, 9542, 480, 7716, 0, 0, - 0, 0, 0, 69918, 0, 8328, 0, 118894, 0, 0, 0, 0, 11132, 983502, 66743, - 74185, 100531, 2854, 66747, 0, 65755, 0, 67120, 67119, 65835, 67117, - 66736, 67123, 67122, 67121, 9881, 100481, 65757, 100538, 100459, 67116, - 8648, 128377, 6741, 43047, 0, 13180, 0, 100487, 66754, 73507, 73487, 0, - 0, 41752, 0, 8641, 100490, 125185, 73477, 100462, 100541, 6942, 69501, - 1024, 42849, 41751, 0, 8941, 101034, 11121, 0, 9023, 40973, 121476, 9928, - 67109, 66865, 0, 67114, 67113, 67112, 67111, 0, 41206, 120724, 9049, - 67108, 43166, 0, 41200, 128201, 125142, 126537, 0, 0, 41188, 119553, 0, - 101007, 917548, 74585, 78626, 0, 0, 11466, 0, 120797, 0, 125067, 2261, 0, - 2860, 0, 0, 70828, 127925, 92357, 67106, 12065, 42872, 0, 43875, 67103, - 43856, 0, 67102, 67105, 7531, 40981, 2413, 100522, 67404, 100521, 0, - 67101, 41196, 100523, 0, 129723, 73512, 43117, 100495, 0, 0, 0, 0, 69876, - 0, 7173, 496, 0, 4313, 64607, 0, 0, 983202, 2065, 42793, 2842, 0, 83152, - 13132, 798, 0, 12801, 67098, 10686, 118528, 128143, 0, 8054, 9174, 67087, - 67086, 67097, 67096, 41611, 67095, 74504, 78854, 42512, 0, 78857, 42089, - 74613, 78856, 0, 101029, 100468, 42079, 100467, 0, 66961, 100474, 0, 0, - 0, 68338, 69958, 0, 0, 0, 0, 0, 78859, 42093, 128951, 100504, 0, 0, 0, - 4580, 0, 0, 0, 92167, 0, 3021, 42004, 0, 0, 42317, 41998, 0, 6946, 77920, - 0, 123610, 0, 0, 0, 121442, 42690, 9880, 0, 0, 64589, 0, 0, 127880, - 68035, 0, 11360, 0, 0, 72242, 0, 0, 0, 0, 0, 64941, 0, 0, 0, 6856, 65671, - 11244, 73706, 6959, 41994, 42907, 0, 0, 122902, 8617, 41982, 8860, 0, 0, - 121256, 0, 0, 9597, 0, 43172, 0, 10117, 0, 92297, 65865, 73549, 0, - 128077, 0, 126065, 0, 187, 0, 65669, 0, 4963, 0, 0, 0, 8964, 0, 7775, 0, - 41948, 0, 0, 101010, 41942, 65449, 3160, 65922, 13226, 42665, 0, 42663, - 128210, 41766, 983503, 78848, 78849, 41760, 1189, 905, 110620, 42658, - 78851, 67859, 9629, 6742, 0, 43625, 12952, 7888, 0, 3980, 0, 42656, 0, - 42055, 0, 0, 0, 64540, 0, 7867, 69218, 6236, 0, 73490, 10505, 0, 12851, - 118948, 0, 5474, 128843, 3103, 0, 41753, 41733, 78051, 983477, 78844, - 78845, 41739, 78843, 70744, 10931, 41756, 43347, 68098, 122909, 41746, - 119147, 92591, 41259, 66954, 69930, 2691, 121338, 11231, 41244, 0, 69800, - 66364, 41262, 67503, 0, 0, 41251, 0, 0, 11805, 0, 0, 68331, 94045, 0, 0, - 0, 74633, 41266, 126642, 0, 0, 0, 65741, 41737, 2275, 2666, 121232, - 41738, 4967, 419, 13126, 0, 0, 42822, 0, 6434, 74913, 0, 0, 6432, 0, - 69932, 128862, 769, 41742, 69927, 74805, 6433, 0, 547, 1943, 6439, 0, - 4994, 487, 0, 0, 3754, 0, 0, 0, 0, 74780, 0, 0, 1595, 92777, 74431, 0, 0, - 74860, 43267, 0, 0, 129083, 12185, 69406, 0, 73479, 100984, 0, 42856, 0, - 0, 983765, 128319, 75057, 0, 0, 0, 65612, 0, 669, 0, 0, 0, 0, 0, 70445, - 100404, 69929, 0, 0, 460, 121513, 0, 0, 0, 120747, 0, 121519, 121518, 0, - 0, 121515, 71491, 65187, 9044, 78497, 11760, 78494, 7577, 78491, 41912, - 100412, 0, 100411, 0, 0, 100394, 78501, 0, 2933, 78500, 0, 66441, 100392, - 100397, 100391, 1549, 0, 100415, 0, 41755, 6206, 8670, 120587, 0, 69935, - 0, 0, 69768, 73492, 0, 66958, 0, 0, 10552, 64342, 41922, 0, 917858, 0, - 917857, 2717, 0, 0, 0, 73664, 41908, 100722, 41916, 0, 0, 0, 92506, - 100723, 66664, 69803, 0, 100725, 0, 0, 43373, 0, 0, 8468, 100729, 121173, - 128297, 119210, 118952, 0, 0, 0, 100686, 0, 0, 0, 128703, 100670, 457, - 78502, 78503, 123180, 43006, 0, 8802, 113777, 0, 0, 0, 0, 126632, 0, - 41757, 0, 100657, 44000, 0, 0, 43534, 0, 0, 11961, 121316, 0, 0, 0, - 128736, 0, 0, 9499, 73522, 128330, 0, 0, 92260, 68184, 0, 0, 7256, 66993, - 983180, 0, 42161, 0, 119126, 128022, 65880, 0, 10802, 64861, 0, 0, 0, 0, - 0, 0, 73109, 0, 955, 0, 0, 5350, 64339, 0, 100705, 10875, 0, 5477, 73121, - 0, 0, 0, 67693, 69790, 0, 0, 3874, 0, 983741, 0, 0, 83272, 100674, - 127397, 0, 100989, 0, 41038, 67502, 9207, 42239, 0, 0, 0, 0, 74432, 0, 0, - 1455, 129680, 0, 11753, 119233, 0, 118594, 127854, 100716, 69801, 0, 0, - 43520, 0, 119556, 0, 0, 0, 0, 100733, 10788, 6088, 0, 129587, 190, - 983346, 12593, 100737, 129308, 64408, 0, 4417, 128615, 74359, 41744, 0, - 0, 100435, 6965, 0, 0, 13201, 100430, 69896, 78868, 74382, 11841, 7918, - 92721, 0, 0, 0, 1728, 0, 0, 0, 983350, 92679, 0, 0, 92711, 0, 0, 119536, - 73491, 66679, 8382, 0, 0, 100381, 0, 917889, 42254, 68371, 100383, 0, 0, - 0, 9923, 0, 0, 11763, 100386, 120688, 0, 78187, 0, 0, 0, 0, 8333, 0, 0, - 0, 917805, 74464, 0, 92320, 74080, 0, 69911, 11910, 0, 74141, 8963, 0, 0, - 0, 121396, 0, 41747, 0, 0, 8968, 0, 0, 129110, 110590, 0, 8836, 12315, 0, - 8300, 0, 0, 0, 8856, 0, 0, 69891, 0, 66965, 120405, 120402, 120403, - 120400, 120401, 12853, 43269, 7263, 120244, 6536, 120238, 120239, 65516, - 12321, 120391, 120388, 55287, 2237, 120246, 9588, 120248, 120382, 120383, - 120380, 120381, 0, 0, 3561, 0, 0, 10613, 0, 110583, 0, 0, 0, 128689, - 5006, 64328, 68219, 917894, 0, 8825, 122972, 0, 0, 0, 128616, 0, 119177, - 0, 0, 128641, 120225, 71366, 120227, 120228, 438, 4510, 41707, 8721, - 120233, 120234, 120235, 12840, 120229, 10845, 120231, 8096, 0, 120935, 0, - 0, 65589, 8733, 0, 0, 0, 0, 0, 0, 93984, 11262, 73747, 128522, 917902, - 64591, 42405, 0, 0, 1632, 127982, 128326, 0, 0, 121327, 121477, 42444, 0, - 0, 215, 41258, 128494, 64494, 1953, 10185, 0, 1256, 3910, 41260, 917903, - 0, 0, 41257, 0, 8675, 10700, 0, 124951, 0, 9333, 0, 121471, 0, 0, 0, 0, - 0, 499, 0, 70729, 42915, 0, 101000, 0, 100999, 0, 0, 73111, 128893, - 122897, 0, 125006, 0, 11118, 0, 128009, 0, 0, 118633, 9180, 0, 0, 0, - 100986, 43438, 118588, 0, 0, 0, 0, 120669, 64782, 0, 0, 73969, 565, - 42484, 118913, 201, 0, 42292, 69610, 0, 0, 119625, 43518, 0, 0, 1022, - 113788, 3880, 74247, 0, 0, 0, 0, 0, 0, 0, 0, 72272, 100997, 0, 0, 66937, - 74255, 0, 0, 92598, 0, 9903, 118993, 0, 68226, 0, 0, 0, 127788, 100955, - 83280, 7892, 0, 10777, 0, 0, 65562, 0, 101002, 0, 8039, 3363, 101009, 0, - 0, 66940, 12596, 70812, 0, 0, 0, 0, 42944, 92425, 74992, 64541, 0, 0, - 10520, 12802, 0, 12998, 0, 83270, 42861, 83273, 11415, 0, 7541, 125068, - 65878, 822, 0, 0, 5774, 194746, 43252, 0, 92619, 7672, 129281, 0, 0, - 7463, 0, 0, 0, 0, 0, 0, 121411, 0, 0, 0, 66938, 0, 475, 0, 120586, 7329, - 0, 0, 195088, 66291, 10645, 0, 6543, 100966, 0, 0, 119065, 0, 0, 0, - 983237, 195095, 0, 8923, 1645, 0, 0, 0, 3196, 72404, 0, 0, 43595, 0, 0, - 0, 0, 0, 195076, 0, 0, 5258, 4328, 0, 0, 0, 405, 11454, 0, 0, 0, 0, - 75052, 41245, 0, 195078, 4523, 11369, 0, 0, 0, 195079, 0, 0, 983510, 0, - 100961, 10480, 74610, 0, 0, 0, 12610, 0, 41247, 0, 7609, 118837, 0, 0, - 92253, 0, 984, 0, 92621, 0, 0, 129885, 73982, 0, 0, 0, 43369, 0, 0, 0, - 983507, 6634, 0, 71952, 0, 66930, 74214, 0, 67709, 0, 0, 0, 71114, 9552, - 0, 0, 0, 12997, 0, 0, 0, 0, 129109, 12883, 10994, 10529, 55283, 0, 74618, - 0, 67736, 10661, 19951, 9614, 2428, 0, 121023, 92837, 126224, 66933, - 71127, 0, 124996, 119162, 1952, 92181, 8455, 100958, 118654, 93033, - 119566, 100960, 0, 12183, 100951, 0, 64929, 0, 0, 0, 128290, 42509, - 73087, 3922, 9187, 983626, 0, 0, 119057, 0, 3353, 9358, 0, 0, 66680, 0, - 73975, 12879, 0, 9795, 68380, 0, 0, 119488, 0, 0, 41027, 0, 66931, 0, - 983631, 0, 70378, 0, 11751, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 129356, 0, 0, - 0, 0, 41029, 0, 126513, 0, 0, 0, 11294, 0, 66665, 0, 0, 127750, 0, 0, - 70105, 0, 983643, 0, 67843, 0, 0, 121167, 983895, 0, 8088, 129412, 0, 0, - 0, 983992, 6926, 72423, 0, 129569, 42369, 4350, 0, 65145, 9041, 43559, 0, - 0, 0, 41263, 0, 0, 0, 65825, 9577, 68199, 0, 0, 983122, 0, 6793, 0, - 70409, 0, 0, 0, 0, 64669, 0, 0, 0, 11200, 72725, 2995, 0, 0, 0, 7868, - 72720, 72020, 11386, 1009, 70405, 66871, 2333, 0, 0, 0, 0, 0, 70407, - 128121, 0, 0, 0, 0, 983657, 66949, 0, 74968, 0, 0, 110601, 0, 0, 41261, - 0, 0, 0, 0, 118989, 6736, 917883, 124132, 43010, 66952, 0, 69635, 73011, - 983716, 0, 0, 7293, 0, 0, 0, 0, 111332, 0, 128245, 69928, 127071, 0, - 127072, 64445, 111336, 6635, 0, 0, 72707, 74936, 0, 0, 917876, 0, 93025, - 66948, 0, 111329, 0, 129887, 128045, 65219, 11925, 0, 92434, 0, 0, 9845, - 101317, 7546, 0, 0, 11230, 4985, 13288, 672, 8098, 0, 0, 0, 128126, - 42655, 0, 0, 1577, 11772, 78327, 0, 66673, 0, 65911, 118705, 0, 0, - 101303, 92180, 0, 0, 120566, 125140, 127177, 0, 0, 119593, 1539, 0, - 74969, 42731, 0, 74970, 71066, 0, 3051, 0, 73783, 0, 0, 0, 0, 78777, 0, - 983161, 0, 0, 101310, 0, 0, 0, 0, 0, 0, 3505, 8707, 0, 6725, 128013, 0, - 92314, 0, 66391, 5479, 0, 6686, 0, 0, 983318, 42754, 0, 0, 0, 0, 0, 0, - 128523, 0, 0, 4433, 41156, 0, 74971, 1443, 9339, 0, 92871, 10926, 0, - 43511, 0, 0, 983324, 0, 126086, 72236, 10021, 0, 101329, 0, 65914, 0, - 66749, 0, 6721, 217, 12466, 0, 0, 10443, 0, 68654, 0, 0, 0, 78334, 0, - 41250, 0, 129532, 128375, 0, 0, 69232, 0, 41252, 66682, 0, 119637, 41249, - 1366, 0, 0, 101326, 0, 0, 4397, 101324, 0, 66946, 9545, 101323, 0, 0, 0, - 3511, 0, 92190, 0, 0, 126244, 760, 0, 12088, 0, 0, 42256, 0, 0, 417, 0, - 111347, 41565, 74965, 0, 111355, 0, 0, 0, 2284, 0, 0, 11311, 0, 0, 0, 0, - 0, 0, 42273, 0, 69430, 121041, 0, 126643, 0, 65910, 0, 10246, 0, 68224, - 12169, 128858, 4552, 0, 0, 0, 1375, 66705, 128412, 0, 3329, 0, 42811, - 74251, 74192, 120794, 7840, 0, 0, 65374, 0, 0, 71072, 0, 4396, 0, 126608, - 0, 10331, 125224, 0, 11543, 0, 8944, 0, 0, 0, 0, 0, 19965, 43025, 10299, - 128436, 68845, 0, 69724, 67412, 92952, 0, 43811, 0, 128924, 0, 11062, - 128748, 0, 0, 0, 69276, 2901, 7865, 66945, 78354, 0, 78347, 0, 126123, 0, - 66363, 0, 0, 0, 74967, 7414, 0, 0, 92691, 0, 128507, 885, 64772, 65180, - 0, 71267, 852, 0, 0, 0, 78614, 121174, 129092, 67809, 9609, 12156, 0, - 122930, 43586, 11035, 10411, 0, 13268, 6710, 0, 0, 0, 43853, 77949, 4315, - 0, 111104, 0, 43639, 43343, 0, 0, 0, 73074, 0, 65812, 43431, 0, 0, 0, 0, - 0, 129890, 0, 0, 0, 0, 994, 125222, 127104, 127103, 73966, 66890, 0, - 65291, 70753, 0, 0, 0, 0, 66873, 4186, 92531, 127106, 127105, 6718, 7330, - 4406, 122946, 8480, 7319, 64373, 128699, 4413, 0, 0, 3198, 0, 0, 92469, - 111126, 0, 128591, 128681, 0, 0, 0, 101321, 73023, 742, 0, 2893, 78738, - 0, 0, 0, 2553, 42294, 6756, 0, 73020, 8363, 0, 2993, 128381, 3916, 4301, - 0, 1141, 42407, 0, 0, 7572, 973, 0, 125077, 0, 2415, 0, 0, 9640, 42333, - 0, 0, 129546, 42486, 43381, 65390, 0, 69434, 1202, 0, 0, 0, 0, 68484, 0, - 0, 64542, 3260, 0, 65388, 43502, 69904, 0, 6738, 0, 0, 74193, 0, 0, 0, - 74641, 6312, 0, 74556, 12446, 0, 0, 128076, 8229, 1235, 0, 11472, 83064, - 0, 0, 101366, 0, 0, 1740, 12872, 0, 985, 0, 0, 0, 12068, 983658, 0, - 101363, 0, 0, 0, 13133, 65071, 110780, 12655, 12134, 0, 92934, 0, 66915, - 120349, 119572, 0, 93030, 41572, 0, 0, 0, 41573, 0, 3931, 0, 74143, 2251, - 127034, 0, 0, 0, 0, 83067, 0, 129303, 0, 0, 0, 0, 0, 0, 83068, 0, 72740, - 128637, 72717, 92935, 120291, 0, 1780, 6936, 0, 0, 819, 0, 9694, 125228, - 0, 0, 0, 0, 8343, 8342, 8345, 8344, 8346, 8338, 7523, 6922, 8348, 8347, - 7525, 3346, 8339, 125004, 72705, 69462, 268, 0, 0, 5754, 94019, 0, - 110684, 8336, 0, 0, 0, 8337, 8341, 0, 11388, 7522, 0, 0, 0, 11090, 6953, - 125240, 0, 74973, 120708, 0, 0, 0, 0, 0, 110782, 0, 9038, 7887, 0, 0, - 42534, 64347, 0, 0, 67660, 120341, 0, 122933, 0, 120878, 0, 0, 73999, 0, - 64580, 0, 0, 64643, 0, 0, 74975, 0, 92227, 129052, 0, 83071, 83072, - 83073, 119154, 0, 119153, 0, 0, 5349, 72440, 2160, 917554, 7411, 0, - 983224, 0, 0, 0, 42736, 70747, 5756, 983229, 92946, 0, 42764, 0, 0, - 119529, 5752, 120600, 0, 0, 0, 0, 0, 78893, 0, 0, 0, 125242, 0, 0, - 120331, 122957, 0, 0, 67501, 0, 10080, 83056, 12647, 0, 0, 69252, 66882, - 0, 0, 0, 0, 0, 72005, 72845, 0, 0, 0, 0, 0, 74213, 0, 0, 0, 0, 0, 6302, - 0, 0, 0, 0, 1417, 983226, 0, 9452, 0, 74393, 0, 0, 110850, 0, 65391, - 63789, 69251, 78659, 78660, 41264, 78658, 6426, 42398, 9179, 78654, - 64906, 41255, 42036, 0, 41269, 0, 41267, 42436, 67759, 42323, 42034, 0, - 0, 42475, 42033, 0, 0, 68916, 43948, 0, 78673, 78674, 1659, 919, 42784, - 1671, 0, 6069, 9219, 0, 1661, 71489, 0, 92690, 10140, 9713, 78400, - 119143, 125236, 0, 2306, 0, 0, 6068, 10612, 0, 0, 121314, 92561, 41462, - 0, 0, 0, 0, 0, 0, 0, 128204, 10635, 0, 983225, 0, 0, 0, 983235, 92251, 0, - 121029, 983227, 0, 8100, 0, 78669, 78670, 13301, 78667, 9667, 78665, 0, - 0, 11003, 9904, 0, 0, 0, 0, 0, 0, 78680, 78681, 78677, 78678, 0, 10313, - 0, 0, 64320, 10265, 78686, 129404, 78684, 78685, 8945, 78683, 70750, 41, - 0, 0, 0, 0, 8655, 0, 0, 71333, 0, 0, 0, 0, 2585, 0, 65254, 3126, 0, - 74136, 10957, 0, 11160, 0, 0, 0, 0, 0, 11408, 0, 7443, 0, 0, 6997, 68004, - 0, 0, 8739, 11075, 0, 65216, 0, 69795, 2593, 0, 0, 0, 0, 125062, 0, 0, 0, - 4411, 0, 72837, 0, 43442, 78799, 0, 0, 0, 66351, 0, 0, 13061, 0, 78687, - 78688, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 119925, 0, 983637, 0, 0, 0, - 71494, 83399, 127541, 83398, 8022, 78808, 0, 73794, 0, 0, 83414, 119916, - 0, 0, 0, 0, 0, 0, 63799, 78427, 12063, 78425, 78424, 0, 0, 0, 75025, 0, - 297, 0, 0, 68326, 0, 78429, 78428, 7077, 2497, 128651, 0, 983112, 0, 0, - 0, 4292, 0, 74815, 10512, 0, 74814, 119931, 0, 72841, 2503, 65070, 1762, - 69794, 2495, 0, 71230, 94069, 77984, 0, 12654, 0, 1899, 0, 2507, 0, 8726, - 0, 65594, 0, 71272, 8892, 0, 0, 0, 0, 0, 420, 0, 0, 125130, 10797, 74637, - 0, 0, 0, 0, 63796, 0, 66581, 0, 119205, 0, 0, 194840, 0, 120788, 92817, - 0, 92956, 0, 0, 0, 0, 119230, 0, 0, 83496, 7399, 0, 66434, 42779, 0, - 92220, 42197, 92543, 5380, 0, 0, 1155, 11365, 43126, 0, 77971, 65684, 0, - 5601, 0, 42765, 78258, 0, 7987, 72843, 0, 69799, 6857, 0, 78735, 119165, - 0, 0, 4473, 0, 72426, 0, 65347, 65346, 65345, 0, 127384, 0, 69802, 0, - 73868, 0, 64826, 0, 0, 0, 0, 6218, 78422, 69676, 4555, 0, 83459, 70071, - 128670, 65190, 0, 0, 65244, 0, 0, 42519, 74472, 0, 0, 83466, 0, 0, 0, - 83468, 92581, 0, 0, 65370, 65369, 65368, 65367, 65366, 65365, 41086, - 65363, 65362, 65361, 65360, 43410, 11323, 65357, 65356, 65355, 5345, - 65353, 65352, 65351, 761, 65349, 19959, 69718, 0, 0, 0, 0, 64647, 0, 0, - 4699, 126077, 0, 129940, 0, 0, 0, 68074, 0, 0, 0, 128347, 0, 72829, 0, - 69773, 121438, 0, 0, 0, 73980, 78255, 78254, 83453, 43157, 0, 0, 0, 7946, - 12541, 0, 74615, 69780, 0, 0, 0, 0, 9005, 1225, 0, 0, 0, 0, 68011, 8847, - 0, 0, 0, 8329, 74590, 43878, 0, 0, 0, 3127, 2595, 71040, 69766, 129188, - 0, 41089, 0, 0, 70292, 983613, 12112, 0, 74200, 0, 8764, 0, 0, 0, 67273, - 67272, 67271, 71044, 0, 0, 0, 71042, 67266, 67265, 0, 67270, 67269, - 67268, 67267, 67282, 67281, 67280, 3572, 10023, 4959, 0, 0, 67275, 9729, - 125110, 0, 67278, 67277, 0, 67276, 0, 7996, 9907, 0, 13304, 83392, 0, - 72830, 0, 11095, 11100, 0, 83358, 83387, 10142, 0, 0, 0, 0, 68022, 0, - 83363, 128292, 19955, 0, 83366, 69807, 125246, 70124, 0, 72230, 83373, - 83385, 0, 0, 0, 0, 68020, 0, 2239, 261, 8406, 7791, 0, 7362, 0, 10696, 0, - 0, 9838, 118920, 0, 83477, 0, 0, 0, 6437, 68830, 83476, 0, 0, 74177, 0, - 0, 67288, 67287, 0, 67286, 0, 83470, 0, 67289, 67283, 83471, 70002, 0, 0, - 0, 67285, 11499, 67297, 7816, 67295, 55247, 68015, 10929, 67298, 122640, - 68017, 9642, 10912, 0, 67293, 11387, 67291, 67290, 70792, 0, 67715, 0, 0, - 68099, 13287, 74430, 10836, 0, 75053, 69775, 0, 128746, 7450, 0, 0, - 119648, 9697, 3606, 0, 0, 0, 0, 125029, 0, 0, 121262, 0, 128873, 1389, - 128871, 0, 0, 0, 12941, 0, 83438, 121062, 0, 12301, 83440, 0, 41102, - 66604, 72025, 0, 0, 0, 66600, 523, 92642, 71100, 74436, 0, 0, 0, 8608, - 83435, 72828, 128704, 0, 127402, 11307, 66707, 67301, 67300, 67299, 0, - 67304, 67303, 0, 0, 0, 0, 122654, 5908, 0, 0, 6744, 67310, 1699, 67308, - 67307, 67314, 67313, 6306, 67311, 983209, 72150, 69862, 3766, 2389, - 67305, 74569, 6611, 65700, 0, 0, 0, 42386, 0, 0, 2599, 917972, 119131, - 119049, 65717, 0, 0, 119654, 0, 0, 73538, 74203, 3760, 1718, 68160, 0, - 3776, 7335, 0, 0, 67324, 69861, 0, 69792, 0, 0, 3778, 0, 9462, 7824, 0, - 78896, 3768, 68142, 765, 72822, 3764, 0, 0, 113822, 129667, 12947, 0, 0, - 0, 118806, 73753, 0, 0, 0, 6829, 5225, 66901, 0, 0, 0, 0, 67319, 67318, - 3162, 67316, 67323, 67322, 67321, 67320, 0, 5353, 128190, 74179, 67315, - 0, 1010, 6851, 0, 67326, 67325, 127870, 6952, 67329, 67328, 67327, 2590, - 120036, 65552, 120034, 120039, 7183, 120037, 120038, 120027, 120028, - 118536, 120026, 120031, 970, 120029, 74611, 120019, 120020, 120017, - 67330, 120023, 120024, 120021, 10961, 113693, 11148, 67486, 0, 0, 128448, - 0, 113703, 64378, 0, 0, 0, 68821, 119649, 11358, 71172, 69797, 0, 11065, - 126464, 0, 68864, 0, 5694, 120839, 66784, 0, 4325, 3047, 0, 43652, - 120962, 93029, 69764, 0, 0, 0, 0, 5431, 6652, 0, 67753, 71460, 0, 0, 0, - 1129, 65016, 0, 65900, 1986, 7846, 0, 8661, 75058, 0, 0, 3845, 0, 0, 0, - 74400, 1456, 7530, 121382, 118631, 0, 0, 0, 120016, 0, 0, 0, 917863, - 127772, 119966, 0, 11002, 7026, 8145, 68216, 0, 12138, 71464, 0, 0, 0, - 12323, 130033, 917869, 0, 0, 0, 92316, 68494, 0, 0, 129384, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 42205, 0, 236, 0, 78867, 0, 0, 113784, 0, 0, 984001, 0, - 0, 119985, 8097, 0, 0, 68012, 72820, 11194, 0, 72824, 0, 127974, 0, 0, - 110602, 129948, 10416, 68070, 3872, 127508, 0, 0, 0, 0, 2838, 917867, 0, - 917866, 119589, 0, 0, 0, 0, 11096, 83019, 10553, 83421, 0, 0, 0, 0, 0, 0, - 73742, 6436, 10096, 0, 0, 0, 113687, 0, 4463, 68018, 0, 78074, 0, 983591, - 7184, 0, 0, 0, 0, 0, 0, 93825, 12818, 12032, 0, 0, 0, 0, 10357, 121418, - 8170, 0, 8556, 0, 9659, 0, 0, 0, 9556, 0, 4503, 92700, 9647, 64004, - 78185, 0, 0, 64002, 78889, 0, 0, 118910, 0, 6438, 0, 9109, 78884, 72382, - 64599, 0, 68009, 0, 0, 2447, 129863, 72381, 0, 126545, 0, 119002, 0, 0, - 0, 19937, 0, 1322, 0, 119204, 254, 72373, 0, 69392, 42425, 0, 0, 65204, - 42312, 0, 118578, 0, 42826, 129731, 42464, 120567, 0, 67155, 74796, - 64400, 64693, 126212, 77861, 0, 0, 67154, 0, 0, 0, 68008, 11785, 0, - 119142, 41978, 0, 0, 43244, 10536, 0, 9901, 7103, 0, 7102, 71428, 120748, - 3140, 0, 0, 68007, 0, 67258, 10909, 0, 1428, 0, 67254, 67253, 7699, - 12393, 67257, 0, 67256, 67255, 0, 0, 69389, 0, 0, 0, 0, 0, 67153, 0, 0, - 127383, 69376, 64554, 0, 3878, 0, 42352, 1752, 0, 129702, 42506, 0, - 10199, 0, 983468, 125231, 0, 0, 0, 720, 0, 0, 0, 68831, 0, 1464, 128339, - 0, 7974, 0, 125017, 68082, 0, 0, 0, 0, 74787, 0, 78864, 92258, 0, 0, - 78863, 0, 1302, 66288, 0, 0, 0, 67152, 0, 983611, 983618, 0, 0, 3995, 0, - 65608, 3714, 0, 0, 67262, 67261, 67260, 67259, 43251, 67264, 67263, 0, - 120557, 92346, 8672, 68006, 11964, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 92610, 0, 468, 0, 0, 0, 983475, 0, 0, 128544, 129397, 65907, 983164, 0, - 0, 0, 0, 0, 983473, 41743, 0, 0, 0, 74880, 0, 121001, 820, 41741, 0, - 120667, 0, 64684, 126992, 128604, 126082, 69934, 65177, 6226, 353, 43645, - 0, 119612, 120738, 67700, 0, 0, 0, 0, 42457, 120276, 0, 120277, 1884, - 129637, 42418, 113678, 41157, 0, 42305, 120279, 0, 0, 41151, 0, 71430, 0, - 42344, 0, 194864, 0, 42497, 0, 194870, 72754, 69933, 73703, 0, 42521, - 8539, 128606, 0, 123609, 69957, 4788, 0, 68023, 0, 0, 983053, 0, 0, 0, 0, - 41590, 118717, 113754, 0, 0, 118901, 68637, 41136, 64351, 0, 128453, - 41154, 113731, 127038, 4038, 41143, 68232, 64859, 0, 129910, 0, 5435, - 129911, 6734, 41343, 127035, 0, 0, 41359, 66761, 0, 119835, 41349, 0, - 129915, 10374, 10310, 0, 0, 10254, 119836, 10278, 10262, 69858, 41363, 0, - 0, 0, 119840, 0, 41356, 10314, 10282, 0, 10378, 0, 40976, 10266, 0, - 119848, 40975, 123547, 129554, 0, 40978, 119851, 92945, 0, 0, 0, 119098, - 119083, 0, 71437, 119854, 69936, 0, 0, 3525, 6824, 0, 0, 119858, 128451, - 0, 72239, 113738, 0, 71424, 0, 0, 0, 0, 0, 10727, 7212, 129071, 71957, 0, - 0, 0, 67156, 808, 7207, 42387, 0, 0, 0, 0, 0, 0, 0, 0, 9225, 121149, 0, - 9145, 128060, 41018, 67841, 983159, 42300, 0, 3084, 983156, 125014, - 41025, 6037, 0, 194885, 0, 10290, 0, 3083, 10322, 111017, 129030, 0, - 41036, 0, 0, 43321, 65606, 0, 41032, 42388, 0, 64700, 0, 1445, 40961, 0, - 0, 0, 40960, 0, 67727, 0, 2223, 64952, 10402, 0, 0, 0, 10603, 0, 118577, - 71438, 0, 0, 0, 128469, 0, 0, 0, 0, 0, 0, 42585, 65032, 10704, 65030, - 4787, 0, 917556, 0, 127015, 0, 128118, 0, 0, 9525, 0, 0, 68773, 0, 0, 0, - 0, 40966, 0, 0, 3998, 0, 0, 65919, 71433, 11792, 2690, 0, 42836, 127150, - 41954, 194921, 194923, 6737, 0, 64933, 126260, 3487, 194873, 71427, - 72758, 65426, 72756, 66757, 0, 0, 41976, 9720, 74964, 11179, 41970, 0, - 12116, 65024, 0, 127912, 9048, 65028, 65027, 65026, 65025, 64757, 0, - 41488, 0, 8527, 0, 126480, 0, 41480, 41053, 3266, 0, 194876, 12093, - 41466, 122881, 78642, 1519, 983925, 3638, 65887, 65429, 0, 0, 0, 0, 8633, - 0, 0, 0, 125118, 0, 70375, 0, 0, 6368, 128124, 0, 70369, 8078, 0, 0, - 70373, 72876, 0, 7002, 121003, 41430, 0, 41051, 41484, 0, 0, 41050, 8872, - 0, 13099, 71445, 70371, 0, 6435, 72154, 11362, 0, 0, 0, 0, 41420, 0, - 3625, 74915, 41409, 71441, 0, 0, 0, 9672, 0, 0, 43317, 0, 0, 0, 41424, - 917598, 0, 0, 0, 0, 41417, 1261, 0, 0, 12102, 119662, 41401, 0, 127538, - 129518, 0, 124943, 72765, 3275, 92472, 0, 0, 0, 118686, 0, 128946, 0, 0, - 125129, 983141, 10598, 0, 128633, 6711, 0, 2920, 0, 0, 0, 0, 19928, 0, 0, - 3917, 0, 113756, 0, 0, 66588, 128078, 0, 0, 113721, 113758, 983081, 0, 0, - 41184, 0, 232, 0, 0, 74170, 0, 0, 0, 0, 9094, 0, 0, 92585, 0, 1064, 0, 0, - 10115, 0, 0, 0, 7862, 0, 13224, 0, 0, 66650, 0, 0, 72877, 1878, 0, 71434, - 2911, 0, 41178, 5427, 0, 0, 0, 12617, 41174, 0, 67148, 67147, 0, 42413, - 41167, 2406, 0, 0, 0, 0, 0, 9618, 128668, 0, 0, 0, 0, 41436, 9337, - 126067, 0, 41456, 0, 119086, 11333, 0, 6703, 0, 125071, 1613, 0, 0, 0, - 983192, 0, 0, 74500, 41460, 78197, 0, 0, 194899, 67144, 65841, 0, 121109, - 74064, 111146, 111144, 120375, 0, 111122, 0, 111121, 64687, 111120, - 42592, 3871, 0, 128305, 9111, 111163, 0, 111156, 120366, 121462, 11150, - 111154, 71488, 111179, 0, 111168, 0, 120362, 41587, 70391, 0, 74322, - 110589, 194908, 111166, 111133, 0, 71443, 194842, 0, 111151, 0, 0, 7928, - 111127, 111140, 41595, 0, 0, 65801, 110587, 110586, 110585, 110584, - 73712, 0, 41598, 3993, 121269, 1545, 40971, 121286, 72874, 0, 0, 0, - 120767, 65286, 0, 0, 0, 0, 2201, 0, 0, 5402, 0, 0, 74462, 73457, 0, 0, - 78194, 64326, 40969, 0, 128110, 983703, 40968, 0, 121139, 0, 128891, 0, - 0, 128513, 8020, 0, 41012, 0, 0, 65805, 41006, 0, 0, 74605, 0, 118942, - 43432, 0, 0, 92900, 0, 0, 68671, 120687, 0, 92958, 0, 0, 68332, 0, 40992, - 0, 0, 0, 0, 0, 42235, 0, 1741, 42370, 0, 0, 0, 11413, 126583, 0, 0, - 128769, 6470, 0, 74517, 0, 0, 120651, 40984, 0, 42742, 0, 12916, 6284, 0, - 41663, 0, 0, 68313, 72840, 70164, 41648, 0, 0, 2299, 41666, 0, 0, 2056, - 41656, 0, 0, 71917, 42219, 0, 0, 78112, 41676, 0, 0, 0, 41670, 0, 92590, - 2796, 0, 0, 9902, 0, 67988, 64785, 82995, 128822, 42631, 983040, 71890, - 0, 74164, 41238, 10049, 11405, 0, 64368, 0, 120925, 0, 397, 12299, 42139, - 0, 9590, 0, 0, 43661, 43819, 0, 6651, 3544, 0, 0, 9620, 0, 0, 0, 92229, - 1333, 7104, 0, 6425, 0, 0, 123561, 0, 0, 129725, 11976, 8554, 13055, 0, - 110733, 0, 110731, 41218, 0, 0, 128673, 1883, 0, 0, 70443, 41225, 70788, - 42419, 983707, 129450, 0, 127896, 0, 65809, 11837, 0, 129104, 7141, 0, 0, - 0, 0, 0, 42363, 0, 0, 0, 0, 69949, 119157, 64732, 0, 0, 126983, 0, 0, - 983697, 7140, 42051, 0, 4164, 118799, 0, 120569, 42049, 42042, 0, 0, 0, - 120637, 69938, 0, 42047, 0, 0, 8470, 11807, 128935, 0, 0, 194825, 74300, - 126267, 0, 120517, 68128, 0, 0, 0, 8736, 0, 42643, 72753, 129925, 0, 0, - 71432, 0, 93023, 110730, 72869, 110728, 0, 0, 0, 0, 68445, 0, 0, 2106, 0, - 11273, 120986, 43004, 0, 82988, 0, 961, 64307, 0, 0, 129752, 67711, - 110615, 0, 1696, 0, 9762, 12105, 0, 110622, 110623, 3264, 110621, 110618, - 43003, 110616, 110617, 0, 120359, 0, 128660, 0, 2322, 0, 70831, 11449, - 128187, 42868, 0, 0, 0, 0, 113746, 983238, 0, 129583, 66398, 0, 0, 0, 0, - 0, 69494, 119224, 0, 0, 64421, 0, 113739, 0, 65823, 0, 11182, 0, 0, 0, - 7766, 55268, 0, 4598, 0, 65839, 0, 0, 3315, 10851, 0, 6179, 92602, 6180, - 129524, 11952, 0, 78648, 78651, 78646, 78647, 78644, 78645, 3801, 78643, - 6176, 120580, 0, 0, 6177, 0, 78652, 78653, 6178, 0, 0, 0, 0, 2214, 8754, - 0, 0, 2137, 0, 0, 0, 0, 66889, 0, 0, 0, 8974, 2308, 0, 74579, 0, 2318, - 122920, 0, 8198, 0, 0, 0, 74307, 0, 119524, 0, 0, 6970, 0, 0, 0, 41159, - 0, 120363, 6385, 0, 128403, 0, 0, 126258, 0, 72785, 42053, 2075, 42057, - 0, 42052, 0, 0, 67651, 0, 9665, 0, 0, 13181, 0, 0, 69379, 0, 0, 0, 0, - 73010, 0, 0, 0, 41145, 0, 0, 0, 41148, 0, 7594, 113686, 75033, 119090, - 10869, 43458, 41146, 0, 0, 121456, 917630, 0, 0, 0, 0, 0, 65184, 11780, - 0, 42796, 0, 69742, 0, 65146, 66803, 0, 0, 0, 7358, 78241, 0, 7988, - 101371, 101370, 3271, 101372, 0, 69281, 0, 0, 0, 101369, 13070, 113736, - 42044, 101365, 1095, 101367, 3599, 101361, 101364, 101157, 129087, 66390, - 101360, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42043, 43232, 67656, 121014, 42046, - 64355, 4036, 123601, 0, 0, 983062, 0, 11954, 0, 41191, 12986, 0, 194854, - 65441, 0, 72202, 0, 129338, 0, 101353, 101352, 12834, 0, 101349, 101348, - 101351, 72858, 101345, 101344, 41190, 101346, 129693, 4575, 41193, 0, - 429, 119174, 124931, 194859, 0, 65792, 128754, 78509, 0, 128866, 0, 0, 0, - 66786, 0, 194862, 10590, 0, 0, 0, 0, 0, 0, 6247, 10214, 65126, 68253, 0, - 0, 0, 983699, 1617, 8050, 0, 0, 0, 101358, 101357, 0, 101359, 101354, 0, - 101356, 6352, 0, 0, 0, 0, 0, 0, 0, 0, 92335, 0, 0, 42926, 0, 0, 0, 8689, - 78750, 70067, 42896, 74147, 3559, 101327, 0, 74526, 65850, 12327, 72763, - 101325, 0, 0, 72761, 0, 78903, 0, 0, 0, 0, 70079, 72751, 0, 12153, - 101340, 101343, 101342, 71940, 0, 101339, 101338, 0, 0, 681, 129406, 703, - 101335, 3272, 101337, 101332, 70077, 101334, 101333, 70514, 78902, 92532, - 71436, 42238, 124930, 3276, 0, 101311, 65928, 0, 0, 101307, 101306, - 101309, 101308, 78813, 78814, 3262, 78811, 42711, 101305, 0, 0, 101302, - 92746, 9995, 1655, 70131, 78818, 78815, 12479, 0, 0, 101296, 70513, - 42797, 0, 0, 128371, 43112, 101318, 43488, 101320, 101315, 101314, 42684, - 101316, 0, 0, 101313, 101312, 128308, 0, 0, 0, 0, 0, 0, 11031, 0, 0, 0, - 70386, 10348, 10412, 0, 0, 74329, 0, 0, 122647, 101285, 101284, 101287, - 101286, 8810, 101280, 686, 101282, 0, 0, 0, 0, 110709, 0, 0, 12040, 0, 0, - 65118, 110704, 0, 118891, 110599, 0, 110598, 0, 120543, 983679, 0, 65455, - 74413, 94097, 0, 119129, 0, 0, 0, 78776, 0, 64467, 10300, 10161, 10396, - 0, 0, 0, 0, 78773, 101294, 101293, 0, 1458, 101290, 0, 72429, 65120, - 11479, 0, 0, 6350, 101289, 101288, 71473, 1061, 69787, 9115, 43111, 0, 0, - 0, 0, 983979, 0, 120907, 1045, 0, 73913, 983564, 0, 0, 0, 0, 0, 0, 8486, - 0, 0, 0, 4362, 0, 0, 93054, 1025, 0, 0, 0, 0, 0, 92328, 128206, 0, 1774, - 0, 122913, 0, 0, 0, 11207, 0, 0, 3988, 0, 0, 983048, 0, 0, 8564, 983977, - 0, 0, 0, 0, 0, 0, 66513, 6256, 0, 579, 55218, 0, 0, 0, 127337, 0, 11814, - 0, 4488, 128716, 127336, 0, 10444, 118846, 78238, 0, 0, 127331, 4487, - 127849, 42832, 1032, 0, 43450, 0, 70155, 0, 614, 0, 127325, 0, 0, 128466, - 0, 127321, 0, 127322, 0, 0, 0, 1050, 7549, 127319, 0, 9314, 0, 0, 0, 0, - 0, 70434, 127314, 12527, 66504, 0, 0, 0, 0, 64333, 127312, 128547, 92594, - 0, 0, 0, 129316, 0, 124960, 10360, 6746, 0, 0, 0, 0, 13085, 9233, 0, 0, - 0, 0, 983474, 0, 92766, 0, 121114, 983944, 74212, 42819, 10910, 118627, - 68044, 9896, 0, 0, 120915, 0, 0, 7970, 0, 0, 0, 0, 113699, 9849, 0, - 122910, 0, 0, 10487, 69714, 0, 10103, 0, 4769, 0, 129967, 0, 2283, 0, 0, - 74785, 0, 0, 0, 110595, 110596, 0, 110594, 64565, 4773, 0, 0, 0, 4770, 0, - 0, 0, 65457, 69441, 0, 0, 127338, 983593, 4774, 0, 68497, 2259, 0, 0, - 10215, 0, 0, 0, 0, 0, 74776, 92160, 4768, 0, 0, 4099, 0, 110699, 110700, - 110697, 2225, 0, 0, 0, 41183, 125217, 11255, 42814, 880, 0, 0, 0, 0, 0, - 67756, 65246, 0, 0, 129463, 7095, 0, 0, 0, 0, 0, 0, 2427, 0, 7093, 0, - 11585, 0, 9962, 0, 12223, 0, 78211, 1434, 42939, 0, 11573, 0, 0, 0, - 121257, 0, 0, 0, 0, 74437, 0, 113711, 917596, 0, 8740, 0, 3782, 64331, 0, - 65167, 1014, 0, 0, 0, 10835, 129987, 0, 0, 0, 0, 0, 118824, 7302, 0, - 67707, 0, 1150, 10547, 0, 0, 68427, 0, 0, 0, 0, 118788, 0, 0, 0, 42257, - 8010, 0, 0, 0, 9643, 0, 0, 12864, 0, 0, 0, 0, 0, 0, 0, 0, 1426, 68217, 0, - 68447, 129971, 0, 0, 0, 73701, 0, 0, 0, 65383, 0, 0, 0, 0, 0, 0, 43196, - 43194, 92549, 10744, 0, 990, 93772, 0, 0, 0, 0, 0, 66470, 0, 0, 0, 3945, - 0, 0, 0, 130039, 0, 127546, 127746, 1020, 73763, 92257, 118669, 0, 64748, - 0, 0, 10205, 0, 0, 10016, 0, 74051, 0, 43242, 125096, 2667, 0, 125037, 0, - 9911, 0, 0, 10097, 0, 0, 0, 118836, 0, 0, 0, 0, 68889, 10159, 113759, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 983343, 92291, 0, 127973, 72882, 0, 1041, 127182, - 6354, 0, 65364, 0, 0, 0, 72884, 0, 128477, 0, 65906, 127819, 72883, 0, - 128470, 5375, 72881, 0, 8215, 0, 10074, 0, 0, 0, 69899, 0, 0, 121426, - 41382, 0, 0, 5173, 65348, 527, 0, 0, 0, 128250, 0, 0, 0, 0, 0, 0, 42695, - 0, 42250, 0, 11187, 113695, 0, 1568, 66806, 0, 0, 113705, 0, 0, 129487, - 0, 0, 128839, 9069, 6144, 0, 0, 0, 0, 66783, 0, 74027, 118934, 66787, - 74580, 0, 110790, 6364, 0, 66794, 43508, 0, 92612, 0, 0, 0, 0, 128405, - 66449, 0, 0, 0, 0, 70714, 0, 70716, 0, 1044, 42411, 0, 0, 0, 0, 43239, 0, - 0, 0, 118572, 42450, 0, 0, 68479, 119237, 0, 0, 0, 0, 0, 69956, 11537, 0, - 121206, 0, 0, 0, 0, 1057, 566, 0, 0, 10907, 42274, 43464, 0, 118698, 0, - 78472, 71207, 42636, 0, 123603, 0, 0, 121171, 64659, 0, 127749, 0, 6357, - 6362, 0, 0, 2216, 9090, 0, 0, 0, 0, 68227, 0, 0, 0, 0, 1053, 12830, 0, 0, - 0, 1052, 1051, 459, 1060, 0, 66479, 0, 0, 0, 128061, 42490, 689, 6508, - 4163, 42298, 8639, 983338, 4246, 0, 43514, 42362, 0, 42337, 64596, 0, 0, - 0, 0, 0, 6359, 0, 43471, 0, 0, 0, 127274, 0, 6358, 6361, 1926, 6356, 0, - 7898, 0, 10935, 0, 127972, 121285, 0, 43685, 0, 0, 42910, 0, 8693, 0, 0, - 44010, 0, 120991, 121454, 0, 0, 0, 0, 129514, 0, 0, 0, 0, 73947, 0, - 129361, 92412, 0, 66477, 0, 0, 0, 43854, 71913, 0, 0, 0, 0, 72227, 65899, - 92275, 0, 0, 0, 68887, 0, 71057, 0, 0, 0, 0, 119183, 2923, 10853, 0, 0, - 0, 0, 72864, 0, 72773, 72772, 0, 120801, 65251, 122624, 68228, 0, 128548, - 0, 0, 5370, 70465, 2931, 73848, 0, 10188, 0, 118848, 0, 983942, 0, 0, - 120584, 72212, 0, 10844, 121016, 128195, 92424, 0, 0, 0, 286, 0, 1062, 0, - 0, 124127, 7395, 0, 1070, 128993, 0, 6095, 0, 0, 0, 127796, 126465, - 64497, 0, 0, 0, 0, 70054, 8189, 78272, 0, 0, 0, 0, 0, 113783, 42102, - 78276, 0, 0, 42101, 0, 78402, 67427, 33, 67425, 67424, 10824, 67430, - 67429, 67428, 427, 64723, 0, 0, 0, 0, 1031, 0, 0, 42104, 0, 0, 2328, 0, - 1071, 42899, 128486, 0, 7673, 0, 0, 1047, 194837, 0, 42908, 0, 0, 10651, - 0, 0, 0, 72433, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13216, 0, 69716, 0, - 0, 0, 0, 0, 92411, 69654, 0, 0, 129904, 2761, 129909, 0, 0, 0, 0, 8643, - 0, 0, 94021, 2757, 11067, 0, 74498, 8910, 10689, 0, 0, 0, 71173, 0, 9196, - 71214, 0, 0, 0, 0, 118911, 0, 0, 0, 0, 0, 0, 0, 0, 68130, 119616, 0, 0, - 42477, 67482, 0, 4495, 0, 0, 0, 0, 70080, 10992, 0, 0, 0, 0, 9318, 0, - 6002, 0, 73808, 0, 92601, 42249, 7639, 43995, 0, 0, 5454, 0, 0, 0, 0, 0, - 0, 0, 121189, 0, 119173, 0, 9704, 120686, 0, 78436, 78435, 11204, 0, 0, - 1731, 0, 92937, 0, 67990, 0, 0, 0, 126576, 127018, 71951, 55265, 0, 0, 0, - 0, 127257, 73826, 0, 3840, 0, 41432, 0, 0, 68430, 0, 43253, 128284, 0, - 3371, 92936, 0, 0, 1479, 69282, 0, 1109, 77997, 0, 129154, 0, 92782, 0, - 0, 8868, 399, 67978, 74842, 0, 0, 194839, 73498, 551, 0, 10156, 0, 92572, - 0, 2544, 65074, 0, 0, 0, 0, 0, 0, 0, 128713, 0, 0, 74268, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 68045, 0, 0, 0, 3447, 0, 0, 121414, 2549, 110818, 0, 0, - 43564, 8946, 0, 74411, 66864, 0, 70480, 7980, 0, 113698, 0, 119653, - 66489, 0, 64695, 128063, 0, 0, 0, 0, 0, 0, 43452, 0, 92993, 0, 10919, 0, - 67810, 0, 0, 0, 0, 6450, 10055, 0, 0, 0, 0, 42720, 0, 9626, 0, 128055, - 74447, 0, 125127, 92573, 0, 0, 0, 119075, 0, 0, 66486, 0, 0, 0, 0, 0, 0, - 75028, 983883, 74839, 0, 0, 0, 0, 0, 55286, 0, 1055, 917628, 0, 0, 0, - 70516, 12146, 118623, 73956, 66488, 0, 0, 0, 0, 0, 0, 42518, 0, 0, 0, - 7407, 74978, 0, 0, 0, 0, 0, 0, 0, 10231, 0, 66626, 0, 0, 92951, 0, 65927, - 0, 0, 69696, 0, 92389, 0, 0, 0, 68095, 92950, 0, 10555, 0, 0, 9091, - 10798, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43222, 0, 74982, 0, 0, 120952, 0, 0, - 2992, 7826, 74321, 110879, 125103, 74981, 92628, 0, 129903, 128289, - 128203, 4361, 129597, 1306, 78770, 1497, 983628, 0, 0, 0, 8248, 0, - 127253, 7973, 128706, 0, 0, 73122, 983949, 0, 0, 2963, 120653, 0, 128554, - 0, 0, 64258, 0, 0, 69677, 74983, 65103, 0, 125008, 42625, 0, 72022, 0, 0, - 64905, 0, 9512, 0, 119076, 6443, 983267, 0, 9135, 0, 0, 123202, 0, 0, - 983882, 93788, 0, 0, 0, 93767, 64256, 0, 11669, 0, 0, 4524, 0, 129182, - 128390, 0, 74266, 0, 0, 0, 70119, 78410, 69809, 121031, 55219, 69815, - 93765, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2986, 0, 93763, 3437, 0, 6203, - 4247, 0, 11920, 8274, 68240, 129694, 1657, 0, 121276, 122951, 0, 2954, - 43506, 42837, 0, 0, 71179, 0, 0, 0, 66476, 68450, 0, 0, 0, 43362, 983135, - 129596, 11705, 0, 0, 0, 127354, 0, 11710, 0, 0, 0, 119507, 74429, 0, 0, - 1058, 129555, 0, 0, 5484, 1144, 0, 0, 0, 0, 0, 118972, 0, 65322, 0, 6441, - 0, 0, 2547, 66484, 43634, 0, 5871, 0, 0, 0, 0, 0, 0, 71204, 0, 0, 1865, - 0, 0, 69950, 0, 93021, 73713, 0, 71199, 65826, 2069, 0, 119092, 43999, - 2997, 0, 126588, 0, 65319, 0, 12316, 0, 0, 123630, 8776, 0, 0, 66294, - 13130, 0, 71191, 126625, 0, 10030, 11709, 12364, 983853, 0, 11704, 0, - 118641, 68672, 0, 0, 0, 0, 11706, 9710, 0, 82985, 0, 413, 65623, 0, 0, - 93980, 74446, 0, 1042, 0, 128378, 12171, 119240, 0, 69384, 4984, 0, 708, - 11391, 0, 0, 0, 983930, 1308, 0, 3673, 810, 0, 120933, 118567, 0, 0, - 1917, 3000, 0, 0, 0, 65628, 66387, 74470, 0, 0, 0, 10027, 0, 0, 0, 0, - 128831, 983168, 2980, 755, 0, 0, 65622, 0, 121012, 7277, 121022, 0, 0, 0, - 0, 8730, 0, 0, 0, 7274, 119250, 0, 7275, 0, 935, 0, 0, 377, 42325, - 121103, 0, 101133, 101132, 101135, 101134, 0, 74911, 2417, 101130, 0, - 19912, 0, 0, 101128, 101127, 0, 101129, 101124, 7248, 101126, 101125, - 1781, 5496, 3627, 62, 1649, 0, 964, 0, 0, 0, 0, 92897, 0, 0, 127364, 0, - 43689, 127911, 66287, 78812, 64389, 66575, 0, 73041, 0, 129687, 0, 7677, - 2991, 3293, 0, 0, 0, 72201, 0, 11341, 127049, 0, 65625, 9714, 11692, 0, - 0, 120850, 6478, 10195, 43673, 65237, 6241, 0, 0, 0, 6238, 0, 129889, 0, - 4409, 0, 0, 67170, 0, 0, 0, 94047, 6237, 5461, 66851, 9176, 92882, - 121341, 65231, 0, 0, 121182, 110581, 0, 44018, 0, 64765, 0, 0, 0, 5685, - 0, 2461, 0, 7091, 0, 0, 0, 68163, 0, 73030, 0, 0, 73928, 0, 0, 0, 0, 0, - 0, 110582, 0, 0, 68506, 0, 0, 0, 0, 0, 2542, 0, 0, 0, 128176, 5776, 0, 0, - 0, 0, 0, 11987, 0, 0, 75036, 68744, 0, 0, 10039, 42828, 0, 0, 0, 0, 0, - 10721, 67664, 43433, 0, 0, 41875, 0, 41870, 266, 129066, 0, 41873, 71271, - 0, 0, 0, 0, 0, 0, 41871, 66186, 3734, 7734, 43683, 8750, 110600, 66011, - 92899, 0, 127937, 0, 0, 10572, 0, 42906, 0, 64349, 7287, 0, 0, 0, 0, - 11167, 69220, 0, 43429, 0, 1697, 0, 0, 68633, 7286, 0, 128738, 10031, - 78754, 0, 68645, 8620, 0, 42162, 0, 0, 7285, 0, 119577, 0, 66842, 43677, - 41583, 0, 65799, 129332, 0, 0, 0, 0, 110806, 0, 3609, 0, 129448, 119074, - 125116, 126254, 128108, 73948, 0, 0, 0, 0, 129189, 42732, 92699, 74984, - 68620, 11691, 74985, 0, 0, 0, 0, 0, 6348, 243, 74075, 0, 0, 92309, - 123585, 0, 0, 10648, 8538, 43687, 0, 118723, 0, 70515, 0, 118954, 92886, - 13307, 129573, 92891, 0, 120770, 983850, 0, 0, 0, 0, 214, 0, 0, 0, 65893, - 0, 120488, 128386, 0, 92893, 0, 2603, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 43, 0, 0, 1016, 0, 0, 0, 3885, 92, 65456, 64608, 0, 0, 0, 70656, 113742, - 0, 0, 0, 128128, 983857, 0, 0, 6791, 983861, 127960, 0, 0, 0, 118976, 0, - 7328, 92358, 0, 7995, 8759, 43421, 0, 68029, 92860, 0, 125272, 0, 3197, - 0, 0, 0, 983151, 0, 11595, 0, 0, 43435, 0, 0, 0, 0, 0, 70660, 0, 741, - 83291, 5494, 0, 70668, 1990, 11107, 4498, 0, 0, 70658, 0, 0, 2960, 73779, - 0, 8969, 101256, 43424, 0, 101257, 2950, 101251, 101254, 101253, 370, 0, - 101250, 101249, 0, 0, 0, 122967, 0, 0, 0, 122900, 0, 0, 983256, 0, 2964, - 43663, 0, 6344, 0, 0, 10144, 0, 8252, 729, 66016, 78446, 0, 0, 0, 78740, - 43669, 9032, 0, 0, 0, 0, 0, 0, 0, 0, 74612, 3761, 101261, 101260, 101263, - 101262, 0, 0, 3850, 101258, 0, 128389, 0, 0, 0, 0, 8611, 0, 0, 0, 43691, - 125032, 0, 41802, 120540, 0, 0, 0, 0, 0, 3848, 101230, 113800, 127536, - 101227, 101226, 101229, 101228, 663, 0, 0, 0, 0, 0, 0, 0, 0, 13221, 0, 0, - 101244, 101243, 101246, 101245, 0, 65579, 12980, 68046, 12143, 101069, - 128067, 0, 43441, 41804, 101241, 101240, 101235, 101234, 101237, 101236, - 66329, 0, 72324, 101232, 0, 125038, 0, 129383, 101214, 101213, 0, 101215, - 101210, 0, 101212, 101211, 0, 1097, 129033, 0, 101209, 101208, 93828, 0, - 101205, 101204, 101207, 101206, 101201, 101200, 101203, 101202, 0, 13110, - 0, 983886, 68229, 1000, 0, 0, 101222, 1209, 101224, 101223, 92354, 1073, - 6321, 77878, 92818, 0, 68213, 0, 12167, 0, 0, 0, 0, 73673, 121500, 0, - 121501, 0, 6587, 0, 0, 0, 9231, 0, 2959, 101191, 0, 101193, 101188, - 101187, 101190, 101189, 101184, 0, 101186, 42941, 0, 0, 68434, 0, 70742, - 0, 0, 12290, 0, 0, 110801, 0, 77873, 8205, 110803, 5131, 118542, 0, 0, 0, - 0, 0, 1944, 78453, 0, 0, 119990, 119991, 12701, 78492, 11308, 119995, 0, - 113702, 66836, 119999, 74263, 92382, 120002, 120003, 7075, 101196, - 101199, 101198, 41817, 73934, 42275, 101194, 120012, 120013, 120014, - 42943, 6041, 0, 41899, 0, 8002, 0, 41902, 0, 0, 64332, 0, 7813, 119117, - 0, 41900, 120633, 101167, 7281, 78455, 7279, 12041, 93027, 101165, 12673, - 0, 129123, 9660, 0, 72984, 101161, 0, 0, 0, 92901, 2970, 0, 101180, - 101179, 77870, 101181, 0, 0, 101178, 0, 0, 0, 0, 0, 3486, 101174, 69498, - 101176, 101171, 101170, 101173, 101172, 0, 69920, 101169, 66834, 0, - 984006, 0, 68312, 101150, 65673, 1019, 78495, 4148, 0, 12289, 101147, - 4316, 0, 13119, 983932, 101145, 101144, 0, 0, 101141, 101140, 43434, - 41865, 101137, 9163, 8659, 9072, 5867, 13302, 7622, 7120, 0, 0, 0, 0, - 7400, 5416, 101160, 101159, 10817, 101153, 101156, 101155, 0, 68162, - 41855, 41867, 0, 983228, 0, 11536, 71988, 0, 7115, 0, 0, 5498, 7337, - 41536, 0, 0, 92587, 7221, 8997, 0, 0, 0, 71949, 0, 0, 127814, 0, 0, 0, 0, - 0, 295, 0, 0, 0, 0, 121292, 0, 43454, 63903, 63902, 63901, 122644, 3971, - 0, 0, 2952, 0, 11038, 10901, 63900, 63899, 63898, 5198, 667, 43273, - 63887, 63886, 128458, 78521, 66830, 0, 92714, 4159, 0, 0, 63885, 63884, - 63883, 63882, 63880, 8555, 63878, 63877, 93057, 0, 0, 63881, 10746, 0, - 118983, 0, 63876, 63875, 63874, 63873, 7432, 1913, 41913, 43686, 0, - 128971, 0, 983894, 0, 446, 41911, 0, 63851, 63850, 41910, 0, 63846, 2972, - 63844, 7262, 0, 63849, 63848, 63847, 72990, 6570, 0, 7259, 63842, 4178, - 63840, 121321, 41521, 63894, 63893, 63892, 0, 0, 1105, 4180, 0, 7418, 0, - 129714, 63891, 63890, 63889, 63888, 0, 0, 0, 0, 1678, 0, 66909, 0, 0, 0, - 0, 11192, 128360, 128404, 9159, 70089, 63861, 63860, 63859, 63858, 63865, - 1615, 63863, 63862, 0, 0, 0, 0, 63857, 63856, 71902, 0, 1077, 0, 65099, - 0, 0, 0, 0, 0, 0, 42773, 121331, 0, 0, 119220, 120912, 129564, 0, 1112, - 119122, 8686, 120654, 0, 65081, 0, 0, 0, 11077, 0, 7260, 0, 5327, 0, - 63870, 63869, 3847, 63867, 0, 2903, 0, 3001, 66762, 0, 43746, 0, 63866, - 0, 0, 0, 0, 0, 127785, 68420, 2990, 0, 128254, 66957, 0, 0, 0, 1117, - 118987, 12212, 129003, 129151, 63836, 63835, 63834, 0, 0, 63839, 63838, - 63837, 0, 125095, 63833, 6042, 66360, 0, 74808, 0, 63821, 63820, 63819, - 63818, 0, 0, 9047, 63822, 128328, 6091, 0, 10691, 0, 74344, 8226, 0, - 63812, 63811, 63810, 63809, 2289, 63815, 63814, 63813, 6047, 0, 0, 780, - 63808, 77925, 77922, 65147, 63931, 63930, 2076, 1093, 9882, 63934, 2082, - 63932, 75050, 63929, 63928, 63927, 77934, 9806, 65566, 77933, 63922, - 63921, 2086, 0, 63926, 2984, 5968, 63923, 0, 0, 129458, 11137, 13169, - 5290, 2089, 0, 63827, 1088, 63825, 7268, 1084, 1085, 63829, 1083, 10131, - 7283, 0, 0, 0, 1092, 0, 7273, 983277, 44016, 43627, 0, 0, 0, 11809, 0, 0, - 0, 2965, 7258, 8808, 0, 1089, 7278, 63937, 63936, 43405, 11106, 940, - 5787, 10099, 63938, 101269, 63897, 101271, 2994, 101265, 101264, 101267, - 101266, 77939, 77940, 77937, 77938, 74343, 93043, 72704, 660, 10127, 666, - 0, 5532, 43667, 5533, 77941, 0, 0, 0, 979, 0, 0, 72706, 92652, 9108, 0, - 72716, 129403, 63951, 71685, 0, 0, 128782, 63946, 1707, 983843, 128612, - 63950, 63949, 63948, 63947, 63945, 6038, 63943, 63942, 101274, 0, 101276, - 101275, 0, 0, 0, 0, 0, 0, 73884, 0, 1690, 63919, 63918, 63917, 70865, - 43659, 0, 983848, 0, 2054, 0, 78515, 63916, 9184, 63914, 69737, 63911, - 63910, 63909, 63908, 0, 0, 63913, 6044, 0, 64838, 9061, 5534, 10672, - 11653, 124932, 5531, 101501, 101500, 101503, 101502, 0, 0, 11957, 101498, - 68668, 124922, 0, 0, 10474, 43426, 0, 42354, 101492, 101491, 101494, - 101493, 101488, 8413, 66841, 101489, 7269, 7272, 0, 0, 101471, 101470, - 78460, 0, 101467, 101466, 101469, 101468, 0, 0, 0, 66840, 0, 101465, - 128441, 0, 101462, 101461, 92187, 7270, 101458, 101457, 6628, 1076, - 128700, 0, 101456, 0, 0, 0, 0, 12807, 43413, 63906, 4548, 63904, 71187, - 70393, 41729, 44005, 1307, 0, 101473, 101472, 0, 0, 128268, 0, 8180, 0, - 127778, 0, 0, 5413, 43681, 123205, 3493, 0, 0, 0, 92544, 73937, 10517, 0, - 4518, 10990, 101447, 5167, 4481, 3771, 101443, 2710, 0, 66277, 0, 0, - 43073, 118579, 0, 0, 0, 121071, 0, 119659, 1628, 0, 0, 0, 65262, 66809, - 10783, 11172, 0, 0, 70840, 113679, 0, 119029, 0, 0, 41530, 66843, 4457, - 0, 0, 0, 0, 0, 41529, 0, 121210, 6031, 65807, 70814, 0, 101455, 71984, - 69705, 101452, 101451, 11926, 6033, 9656, 0, 0, 0, 68869, 0, 128930, 0, - 128100, 0, 42612, 43655, 0, 0, 0, 66468, 0, 0, 68623, 101423, 0, 0, - 101420, 101419, 101422, 101421, 0, 1151, 101418, 73709, 127544, 0, 71106, - 118722, 0, 0, 0, 0, 101437, 101436, 11527, 101438, 0, 0, 11538, 101434, - 0, 11020, 0, 66467, 101432, 8087, 71700, 101433, 9894, 101427, 73485, - 70824, 101424, 0, 78513, 8053, 0, 0, 0, 0, 101407, 101406, 0, 63845, - 101403, 78912, 78602, 101404, 13084, 42966, 8741, 0, 0, 101401, 0, 64605, - 83051, 101397, 473, 43415, 101394, 101393, 101396, 1087, 124966, 71275, - 101392, 0, 66439, 43218, 0, 0, 7237, 101414, 101417, 101416, 71996, - 101410, 92261, 101412, 121036, 4384, 74220, 101408, 2058, 917561, 0, - 129462, 0, 0, 0, 3857, 0, 0, 0, 64630, 0, 0, 74168, 127113, 125088, 4421, - 0, 0, 101381, 66400, 101383, 68431, 101377, 101376, 101379, 83053, 0, 0, - 69640, 127861, 0, 437, 73483, 0, 0, 0, 65236, 13290, 119180, 4997, 64306, - 0, 0, 4999, 0, 0, 0, 4711, 120769, 0, 2739, 0, 92915, 74834, 0, 127175, - 0, 0, 0, 0, 0, 1779, 6600, 6601, 0, 5325, 101390, 101389, 13058, 101391, - 101386, 0, 92186, 101387, 71845, 10575, 43399, 0, 101385, 101384, 1104, - 0, 0, 10655, 0, 0, 69497, 0, 1082, 110878, 0, 67401, 0, 0, 0, 0, 6783, 0, - 0, 42867, 69655, 44021, 6458, 0, 0, 0, 0, 0, 0, 1273, 43407, 0, 0, 0, 0, - 1313, 6322, 41720, 128627, 66433, 0, 0, 0, 11216, 0, 0, 0, 43437, 93833, - 0, 0, 0, 5122, 0, 72728, 129520, 70161, 0, 0, 0, 0, 0, 8303, 0, 128926, - 0, 10003, 0, 0, 0, 1686, 0, 0, 42834, 3664, 0, 126088, 121346, 0, 0, - 4324, 126, 0, 0, 0, 0, 0, 65166, 0, 0, 0, 0, 43817, 0, 43822, 0, 0, - 65600, 13002, 0, 0, 0, 1103, 0, 119575, 129452, 0, 13078, 0, 8116, 0, - 2050, 0, 0, 1102, 0, 6555, 0, 0, 74003, 74794, 0, 0, 42591, 127278, 0, - 1111, 0, 75047, 4707, 0, 0, 0, 0, 43468, 4522, 8645, 0, 74857, 0, 11352, - 0, 92787, 0, 2293, 0, 0, 0, 128265, 71709, 0, 121194, 0, 93827, 0, 0, 0, - 128488, 0, 160, 2677, 0, 0, 120141, 0, 983646, 70790, 0, 42770, 0, 71986, - 0, 43821, 113769, 0, 0, 43816, 0, 0, 1079, 3867, 64817, 0, 118549, 0, 0, - 64768, 0, 0, 4005, 983213, 0, 10991, 0, 92957, 917578, 92850, 917580, - 917575, 128314, 917577, 917576, 917571, 78534, 917573, 917572, 0, 0, - 128359, 73458, 0, 3339, 11448, 1106, 917591, 917590, 129192, 3340, - 917587, 917586, 917589, 917588, 917583, 10605, 1309, 74996, 120743, - 92650, 0, 0, 9485, 0, 129781, 0, 0, 0, 125002, 92533, 128487, 0, 129285, - 4338, 11238, 0, 66825, 0, 0, 0, 0, 122939, 0, 74128, 0, 0, 73680, 0, - 129438, 9553, 1590, 63777, 63776, 128677, 63782, 63781, 63780, 63779, - 1583, 101525, 101528, 101527, 101522, 101521, 101524, 101523, 41522, 0, - 92168, 983803, 66759, 0, 983580, 0, 0, 0, 0, 11394, 0, 983071, 0, 66823, - 1334, 0, 4479, 0, 0, 120663, 0, 122883, 10497, 0, 0, 983796, 66828, 0, 0, - 0, 6809, 63786, 0, 0, 63791, 63790, 1145, 63788, 101535, 63785, 63784, - 63783, 10192, 65267, 101533, 101532, 8928, 0, 0, 0, 0, 0, 74216, 66805, - 0, 0, 63759, 63758, 3523, 1074, 0, 121340, 74077, 92832, 0, 0, 63757, - 43145, 63755, 63754, 63752, 1349, 63750, 63749, 0, 0, 0, 63753, 63802, - 41084, 72784, 0, 41930, 63805, 63804, 11140, 63801, 41082, 43843, 42787, - 101514, 0, 101516, 101515, 63793, 63792, 0, 128241, 10201, 12238, 63795, - 42358, 92394, 43862, 101511, 101510, 41932, 66826, 101507, 101506, 92809, - 121136, 0, 7950, 63772, 63771, 63770, 0, 63767, 63766, 2793, 63764, 0, - 128501, 63769, 9530, 0, 92398, 0, 128642, 63763, 63762, 4595, 63760, 792, - 92808, 0, 0, 8742, 0, 0, 0, 63744, 0, 0, 120815, 63748, 63747, 63746, - 63745, 5055, 0, 0, 1090, 0, 125268, 11665, 92830, 4558, 78919, 72211, 0, - 0, 0, 11513, 983978, 6157, 63775, 63774, 63773, 0, 12170, 9067, 92843, 0, - 10872, 129643, 43891, 43893, 43892, 129747, 43933, 0, 128231, 0, 0, 0, 0, - 0, 11063, 0, 43888, 0, 0, 128368, 43889, 0, 73807, 983105, 7386, 0, 0, - 70295, 0, 0, 0, 71201, 128460, 0, 0, 0, 0, 69915, 2918, 66820, 65300, 0, - 124898, 64726, 2790, 0, 3793, 42065, 127829, 0, 124901, 0, 0, 0, 0, 0, - 92712, 0, 12923, 5270, 2166, 0, 0, 65813, 0, 128499, 0, 75012, 0, 10888, - 0, 93997, 94180, 3330, 129417, 0, 0, 0, 0, 0, 8220, 0, 0, 101581, 72457, - 1627, 101582, 0, 0, 5371, 101578, 0, 1826, 118794, 0, 0, 70023, 0, 0, 0, - 71108, 0, 0, 124907, 0, 92207, 68125, 74898, 71353, 0, 72006, 71098, - 70029, 0, 43116, 10190, 70019, 64346, 0, 101585, 66818, 101587, 70031, 0, - 12666, 120413, 120420, 120414, 101567, 120428, 0, 101564, 101563, 65509, - 101565, 7449, 0, 101562, 0, 7438, 0, 0, 9054, 971, 101558, 92803, 101560, - 65195, 64767, 101557, 101556, 0, 0, 101553, 101552, 0, 0, 0, 64303, - 101576, 2303, 0, 101577, 101572, 101571, 65833, 101573, 7271, 0, 101570, - 92802, 0, 12229, 0, 0, 43411, 73751, 126577, 64813, 0, 0, 10476, 0, 0, - 3932, 64958, 0, 0, 73989, 0, 0, 101542, 101541, 101544, 101543, 101538, - 101537, 101540, 101539, 92645, 65474, 4796, 118892, 129357, 65479, 0, - 42895, 11858, 65500, 983600, 9899, 92608, 2162, 404, 65484, 120639, 0, - 5788, 127852, 0, 65491, 1831, 66020, 0, 984012, 92588, 0, 1343, 120784, - 0, 0, 12018, 0, 0, 0, 0, 0, 4422, 4708, 3799, 101550, 119357, 0, 101547, - 101546, 101549, 101548, 983095, 0, 1364, 0, 8038, 101545, 0, 12868, - 129560, 70425, 55223, 0, 64414, 110689, 122978, 0, 0, 0, 0, 0, 118802, - 118644, 42855, 118856, 42866, 73525, 0, 0, 0, 66438, 0, 983996, 119356, - 92853, 119354, 0, 123556, 0, 73013, 67685, 128062, 119350, 0, 11864, - 10404, 10340, 119352, 1556, 5274, 0, 127821, 10017, 9733, 0, 69488, 0, - 41373, 0, 0, 0, 0, 0, 349, 4863, 41371, 0, 0, 0, 0, 72295, 4398, 8543, - 65618, 128018, 129784, 0, 0, 0, 12441, 0, 119348, 119347, 4318, 10452, 0, - 8032, 0, 119349, 119344, 0, 127844, 121156, 0, 110729, 119345, 8597, 0, - 110727, 9864, 0, 92796, 0, 92799, 0, 0, 0, 7722, 0, 0, 92797, 0, 0, - 66590, 0, 0, 129850, 0, 0, 0, 4965, 0, 917536, 0, 123196, 0, 0, 0, 10436, - 119342, 43147, 119340, 10356, 10420, 982, 2756, 0, 983997, 0, 0, 11162, - 119338, 0, 92914, 0, 65110, 0, 0, 983800, 78543, 0, 118793, 0, 128112, - 119179, 64476, 1694, 8216, 0, 0, 78539, 0, 65620, 0, 78537, 0, 0, 42158, - 65621, 69955, 120324, 120327, 120326, 120321, 120320, 120323, 120322, - 12314, 65616, 55221, 43825, 983553, 119337, 68060, 119335, 0, 71874, - 123628, 128537, 119332, 73089, 0, 41347, 0, 0, 8842, 0, 0, 4379, 127393, - 12692, 0, 0, 66353, 71875, 0, 0, 92907, 0, 0, 71877, 120303, 65619, 9872, - 0, 0, 1846, 120309, 120308, 119256, 71192, 120305, 120304, 120307, 6442, - 120317, 120316, 5379, 120318, 110717, 120312, 120315, 71876, 0, 65934, - 66497, 0, 66986, 0, 0, 0, 0, 0, 0, 0, 0, 72002, 0, 6151, 12110, 0, - 129761, 0, 66959, 0, 0, 0, 0, 68335, 129655, 0, 0, 0, 0, 0, 66041, 9676, - 10202, 0, 0, 0, 64575, 78929, 11965, 0, 124936, 0, 0, 0, 0, 0, 9698, - 66293, 0, 119651, 0, 0, 41921, 0, 0, 0, 119258, 0, 0, 0, 0, 0, 8012, - 12355, 12353, 0, 0, 74107, 0, 0, 41925, 0, 41920, 65444, 0, 0, 41923, - 12694, 0, 10112, 1294, 0, 120091, 0, 120092, 0, 0, 128474, 121400, 0, 0, - 0, 8718, 0, 10284, 10268, 10380, 10316, 92593, 0, 71850, 0, 0, 92889, 0, - 0, 0, 0, 9342, 12829, 0, 0, 101239, 127978, 0, 0, 69428, 0, 73767, 72347, - 0, 7956, 598, 0, 72329, 93837, 0, 0, 128860, 0, 120041, 0, 0, 101242, 0, - 0, 847, 0, 9529, 0, 0, 0, 101247, 120035, 0, 0, 0, 67411, 0, 0, 119497, - 120040, 0, 128580, 0, 9624, 0, 0, 0, 65463, 1554, 0, 0, 0, 0, 71879, 0, - 0, 0, 121161, 19963, 123566, 0, 72326, 92933, 71887, 10324, 10292, 65546, - 0, 68141, 8372, 0, 0, 83018, 120022, 10175, 10388, 42799, 0, 983181, - 10568, 0, 127400, 0, 0, 0, 983762, 0, 4366, 0, 983805, 0, 0, 42608, 0, - 9884, 0, 0, 0, 0, 129180, 0, 128964, 0, 0, 1609, 0, 92773, 73448, 0, - 11661, 0, 5818, 0, 0, 0, 9540, 0, 2554, 5158, 0, 2213, 0, 0, 78522, - 43079, 0, 0, 8264, 11175, 64553, 120863, 42155, 0, 0, 0, 0, 0, 69552, - 8676, 0, 129927, 0, 451, 0, 0, 0, 0, 0, 0, 123167, 43609, 0, 0, 1440, 0, - 0, 0, 127061, 11005, 0, 66656, 127063, 0, 129936, 0, 127065, 43393, 0, - 120643, 0, 0, 0, 0, 120798, 0, 0, 0, 0, 0, 0, 70435, 64356, 0, 0, 0, 383, - 7154, 127815, 43495, 128809, 121448, 0, 0, 0, 11286, 0, 0, 0, 0, 0, 0, 0, - 42644, 73555, 129797, 129801, 8292, 0, 4980, 113726, 92674, 70130, 0, 0, - 0, 0, 74912, 0, 10631, 83330, 100488, 68042, 0, 0, 7900, 101252, 0, - 78779, 4198, 128555, 0, 0, 0, 123159, 0, 0, 12931, 0, 0, 0, 2088, 0, - 72164, 129284, 0, 0, 69265, 0, 0, 0, 69694, 92838, 129794, 8593, 0, 0, 0, - 0, 0, 0, 11798, 0, 100483, 0, 0, 0, 64211, 128865, 120494, 0, 0, 0, - 121228, 68901, 128788, 0, 0, 65162, 0, 0, 0, 0, 0, 128130, 0, 92264, - 127153, 0, 128818, 0, 0, 61, 0, 74373, 92182, 119554, 92862, 0, 12089, 0, - 65834, 83281, 119671, 128701, 0, 0, 42566, 42743, 0, 69824, 0, 92653, 0, - 0, 42621, 0, 64833, 0, 0, 0, 43266, 0, 0, 0, 74843, 0, 0, 119103, 64417, - 0, 0, 64737, 0, 0, 8930, 0, 0, 66900, 10056, 1800, 0, 0, 0, 129337, - 121175, 7743, 0, 0, 119528, 92640, 92453, 9034, 6039, 129139, 10075, 0, - 0, 0, 10748, 0, 0, 0, 0, 0, 92984, 0, 0, 128183, 129421, 0, 43064, - 127558, 0, 7539, 0, 0, 0, 0, 0, 0, 0, 92898, 42567, 0, 0, 73886, 0, - 129988, 12326, 0, 92848, 0, 0, 11355, 0, 0, 0, 0, 69437, 128222, 129803, - 129811, 119537, 72327, 43005, 65342, 118902, 0, 0, 8644, 0, 0, 11186, - 74296, 41909, 0, 128682, 2791, 127472, 1891, 0, 0, 41907, 66647, 0, 0, - 41906, 0, 129672, 10773, 70206, 0, 0, 0, 6412, 2061, 8520, 13146, 0, - 92836, 83275, 65902, 2882, 0, 126232, 65852, 0, 92795, 0, 123627, 0, 0, - 92794, 0, 0, 128098, 0, 0, 0, 70871, 0, 92792, 0, 120087, 0, 0, 92793, - 93971, 0, 3844, 6842, 0, 0, 6612, 0, 0, 0, 0, 0, 783, 0, 0, 0, 983064, - 68032, 119225, 0, 0, 68378, 4556, 67839, 68480, 78663, 120069, 120074, - 67657, 10510, 4382, 74218, 42194, 0, 92806, 9177, 8902, 93958, 9839, - 92804, 120700, 92807, 0, 63999, 41904, 41917, 9788, 120973, 92805, 1862, - 0, 0, 0, 41915, 0, 41919, 63994, 41914, 7981, 0, 0, 0, 0, 0, 0, 0, - 120834, 0, 0, 0, 6784, 78788, 0, 0, 0, 0, 127534, 127484, 127476, 983874, - 0, 983960, 64289, 65289, 0, 129539, 129575, 64509, 0, 0, 126505, 11051, - 0, 66635, 55259, 65885, 0, 128310, 0, 0, 0, 0, 7500, 4506, 0, 0, 0, 0, 0, - 126609, 4040, 128680, 6167, 0, 42945, 0, 0, 0, 0, 7830, 43036, 0, 0, - 63990, 19947, 63988, 63987, 0, 63993, 10440, 9611, 2244, 71883, 0, 65260, - 63986, 11446, 63984, 92641, 3435, 119652, 0, 119108, 0, 128632, 0, 0, - 12748, 0, 0, 92705, 0, 78790, 0, 0, 63956, 42458, 63954, 63953, 63960, - 63959, 63958, 11596, 0, 11469, 69267, 42306, 2723, 0, 0, 70027, 0, 0, 0, - 128093, 2880, 0, 0, 0, 0, 128506, 3498, 4378, 0, 129825, 0, 65551, - 118928, 0, 43387, 0, 64415, 128898, 0, 0, 0, 0, 8161, 393, 12013, 0, - 92216, 126479, 63965, 63964, 63963, 42345, 0, 2174, 63967, 42498, 0, - 2927, 0, 63961, 0, 0, 983946, 0, 69699, 0, 42340, 0, 0, 0, 10730, 0, - 69688, 0, 64187, 118535, 0, 12437, 9813, 0, 42453, 1604, 9565, 0, 69701, - 69235, 42414, 110724, 129196, 0, 42301, 11372, 0, 917973, 0, 0, 63980, - 63979, 63978, 0, 128207, 12017, 63982, 63981, 73687, 0, 63977, 63976, - 72794, 0, 0, 0, 63971, 4347, 4416, 63968, 11009, 63974, 63973, 402, - 69390, 13147, 0, 0, 64646, 13228, 0, 0, 3515, 74252, 65261, 0, 0, 6259, - 0, 0, 0, 0, 0, 0, 74813, 74425, 0, 126998, 126114, 0, 0, 0, 129933, - 983717, 0, 0, 74301, 0, 122633, 0, 0, 74060, 69508, 0, 66235, 5145, 0, 0, - 128394, 0, 73120, 0, 7402, 0, 0, 0, 7952, 7832, 43382, 66616, 0, 983950, - 120852, 0, 127875, 64866, 0, 0, 0, 78784, 74248, 0, 0, 983197, 0, 0, 0, - 78656, 42390, 0, 0, 983940, 0, 0, 0, 92839, 9508, 0, 9544, 11520, 0, - 110898, 3377, 0, 129562, 0, 0, 0, 0, 66989, 66280, 0, 127198, 0, 0, 0, - 1955, 119565, 0, 0, 3076, 0, 42168, 73049, 66304, 0, 0, 8917, 42403, 301, - 0, 111175, 0, 0, 0, 0, 0, 0, 67819, 92987, 0, 0, 0, 983206, 0, 69403, - 3182, 0, 0, 0, 0, 0, 42169, 123162, 74244, 0, 42329, 0, 66326, 6841, 0, - 128913, 0, 1219, 3934, 71276, 11483, 74510, 101122, 121110, 42442, 65470, - 69565, 0, 64622, 7759, 42482, 485, 0, 0, 42290, 0, 0, 42280, 0, 0, 11655, - 64379, 127913, 42431, 10126, 42318, 0, 119631, 74397, 42470, 0, 68315, 0, - 110829, 74041, 0, 0, 0, 5411, 0, 0, 0, 64205, 0, 64206, 42393, 64478, - 1310, 125007, 0, 12052, 10643, 55271, 72727, 0, 121045, 0, 0, 118852, 0, - 0, 0, 0, 113826, 0, 0, 64385, 0, 0, 0, 0, 0, 0, 93848, 92560, 2713, 0, - 9650, 0, 0, 120602, 1406, 983650, 78174, 92659, 0, 68223, 0, 0, 0, 0, - 43475, 0, 65287, 1508, 127938, 8779, 10569, 75034, 0, 0, 0, 0, 0, 0, 0, - 70786, 0, 0, 128344, 9185, 0, 42932, 43403, 0, 0, 0, 0, 0, 0, 0, 0, - 12955, 0, 2888, 0, 0, 0, 0, 0, 0, 0, 2878, 0, 0, 0, 0, 0, 0, 129028, - 13203, 129722, 10429, 10365, 0, 0, 127165, 7503, 0, 113676, 68381, - 119658, 0, 8986, 0, 10632, 11934, 11452, 1332, 0, 0, 0, 0, 73741, 1791, - 8850, 9288, 0, 2892, 0, 43394, 555, 0, 0, 0, 0, 64172, 118899, 0, 0, 0, - 0, 8854, 0, 5858, 73101, 10582, 0, 0, 1361, 0, 0, 7905, 0, 65256, 0, - 41210, 0, 0, 71884, 0, 0, 0, 6828, 0, 92302, 0, 1342, 68440, 0, 64161, - 10903, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64381, 0, 0, 0, 42245, 126467, - 41972, 0, 0, 0, 9127, 0, 66619, 126489, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11620, - 0, 1149, 68316, 0, 0, 0, 0, 0, 92492, 0, 118784, 0, 0, 0, 12838, 0, - 118819, 0, 0, 0, 0, 41087, 0, 0, 0, 0, 12036, 0, 124143, 0, 0, 0, 64428, - 12227, 0, 0, 0, 0, 125248, 120964, 0, 0, 0, 0, 0, 69566, 0, 0, 0, 0, 0, - 1743, 0, 0, 0, 65186, 122626, 0, 0, 0, 0, 64439, 0, 68062, 0, 111259, - 111258, 43866, 0, 111263, 3395, 9362, 111260, 0, 111257, 111256, 111255, - 0, 0, 41091, 3426, 1344, 111249, 111248, 126215, 4735, 11111, 6119, - 111251, 42699, 0, 0, 74818, 1423, 0, 0, 0, 0, 12039, 10559, 0, 0, 0, - 9472, 67734, 11929, 0, 0, 0, 0, 128826, 0, 11579, 0, 0, 128364, 0, 92185, - 0, 0, 1004, 92584, 0, 0, 0, 129755, 0, 2556, 0, 0, 72790, 0, 0, 9686, 0, - 0, 0, 70109, 111102, 0, 10718, 13154, 111100, 9139, 0, 0, 0, 0, 0, 0, 0, - 0, 92831, 92810, 41708, 12860, 41703, 0, 42090, 5403, 10352, 73917, - 129144, 111096, 111088, 5140, 3753, 118785, 41704, 0, 43078, 127789, - 2207, 129360, 0, 983207, 92362, 0, 0, 2410, 92525, 0, 0, 0, 0, 0, 0, 0, - 0, 119253, 0, 126601, 0, 2066, 74199, 0, 43463, 10659, 119623, 68863, 0, - 1336, 0, 0, 69463, 0, 0, 0, 0, 0, 0, 0, 0, 0, 126639, 0, 272, 0, 0, 0, 0, - 983965, 128133, 0, 0, 124940, 0, 1190, 42146, 1335, 42177, 43867, 0, 0, - 10448, 0, 125041, 0, 0, 2099, 5120, 2409, 7799, 0, 74424, 0, 126581, - 4731, 0, 111199, 111198, 111197, 111196, 11689, 0, 74977, 9913, 129430, - 0, 0, 0, 111195, 111194, 11694, 0, 11690, 111189, 92842, 111187, 11693, - 111193, 111192, 43097, 11688, 0, 78797, 194, 111186, 111185, 111184, 0, - 0, 0, 11226, 4519, 70337, 10898, 43072, 70205, 0, 0, 0, 73094, 10695, 0, - 7540, 0, 110984, 41859, 6067, 92790, 110982, 0, 110981, 13311, 92788, - 41857, 92791, 8359, 121224, 12689, 0, 983132, 64577, 92789, 111203, - 68183, 111209, 111208, 6064, 110988, 0, 110979, 74142, 0, 111201, 111200, - 6051, 123613, 0, 0, 983374, 0, 983651, 0, 0, 0, 110864, 10537, 110862, - 1276, 0, 6549, 6052, 0, 0, 0, 0, 118687, 0, 0, 0, 0, 1960, 0, 71232, - 66297, 0, 129313, 0, 0, 1345, 111213, 111212, 111211, 8956, 43083, 0, - 111215, 64682, 0, 6430, 69563, 111210, 119814, 0, 0, 0, 119817, 0, 492, - 43087, 0, 0, 0, 0, 0, 2582, 0, 0, 7444, 72863, 0, 2297, 111243, 73837, 0, - 0, 65096, 197, 74183, 0, 69571, 111241, 111240, 129760, 66515, 43550, - 119829, 111229, 111228, 93764, 111226, 0, 0, 111231, 111230, 71686, 1799, - 0, 42148, 74336, 0, 0, 65340, 111220, 110974, 2262, 111217, 111224, - 74931, 111222, 10896, 0, 0, 0, 0, 6338, 111003, 110997, 110994, 111006, - 111002, 111005, 0, 111279, 111278, 111277, 72133, 0, 111273, 111272, - 110961, 3171, 6623, 4961, 0, 886, 55216, 8654, 110965, 111270, 74390, - 64603, 111267, 129283, 68122, 0, 43084, 0, 0, 0, 0, 69693, 8994, 10944, - 65938, 111239, 111238, 111237, 111236, 66279, 92890, 42510, 0, 0, 6804, - 0, 1947, 0, 0, 0, 42759, 0, 1705, 122631, 0, 0, 0, 0, 72722, 74036, 0, 0, - 66720, 111281, 111280, 0, 4909, 111285, 111284, 111283, 4904, 0, 43503, - 1365, 9253, 42757, 0, 7462, 0, 11860, 0, 0, 119587, 0, 917579, 92526, 0, - 125035, 0, 111311, 111310, 0, 0, 0, 0, 93977, 0, 0, 0, 0, 3629, 0, 13005, - 0, 3628, 0, 111295, 0, 0, 0, 0, 111290, 64809, 2928, 4905, 111083, 851, - 55233, 111291, 111059, 43086, 9114, 43870, 42583, 9315, 4822, 4906, - 121097, 2847, 111028, 10330, 0, 1251, 7777, 41852, 125059, 111327, - 111032, 111325, 12646, 0, 10259, 0, 65821, 75046, 6018, 0, 111324, - 111323, 111322, 68372, 111319, 111318, 71893, 2558, 0, 64584, 111321, - 111320, 0, 0, 0, 0, 78911, 111308, 111307, 69500, 73987, 74599, 71895, - 93012, 0, 128715, 0, 12867, 111296, 0, 0, 11044, 111300, 111299, 8904, - 11824, 65857, 0, 128674, 129027, 4387, 0, 0, 124920, 0, 0, 0, 0, 11842, - 0, 0, 0, 5136, 1968, 983041, 126627, 1337, 0, 0, 0, 0, 66506, 0, 0, 0, 0, - 42314, 121384, 0, 0, 6120, 0, 65670, 67457, 0, 43082, 6016, 0, 42284, - 71894, 4276, 111314, 3619, 41638, 69691, 0, 42322, 8853, 111043, 0, 490, - 0, 13231, 68384, 72310, 65350, 0, 0, 0, 68245, 42435, 6154, 0, 65354, 0, - 0, 42397, 334, 72732, 42416, 65359, 65273, 74634, 128227, 4442, 10364, 0, - 778, 41626, 42455, 7989, 0, 3227, 69907, 111053, 0, 2915, 11502, 983214, - 41702, 10309, 0, 0, 0, 0, 0, 0, 0, 127268, 127258, 127267, 65215, 64410, - 127260, 71175, 0, 0, 0, 0, 0, 0, 41700, 110651, 69266, 126488, 0, 0, - 42495, 0, 0, 0, 10460, 43364, 0, 1356, 3728, 42713, 0, 0, 42342, 10914, - 0, 42489, 64310, 66896, 41861, 42297, 0, 0, 41860, 64862, 0, 0, 5289, - 42336, 128658, 0, 92529, 42410, 71129, 120624, 0, 2649, 74493, 0, 126635, - 0, 3382, 42449, 9081, 1658, 11936, 93019, 113814, 11269, 0, 0, 43100, - 69888, 65508, 0, 0, 121451, 0, 0, 0, 129780, 69272, 4732, 128283, 0, 0, - 0, 121113, 2236, 126551, 0, 6048, 0, 0, 73965, 0, 0, 0, 0, 10151, 9681, - 4475, 0, 41142, 2100, 0, 0, 6035, 0, 123599, 10296, 0, 0, 0, 0, 0, 0, 0, - 983312, 68488, 10392, 10328, 0, 43462, 0, 0, 0, 8979, 0, 0, 983309, 0, 0, - 0, 10977, 0, 10344, 0, 65299, 10408, 0, 0, 121187, 66505, 0, 0, 0, 0, 0, - 122648, 43074, 73799, 0, 0, 122944, 0, 3446, 0, 129891, 128692, 0, 0, - 119582, 4474, 0, 43093, 6282, 0, 0, 127372, 0, 0, 0, 129881, 0, 0, 0, 0, - 66910, 67811, 92277, 0, 64948, 0, 74347, 0, 0, 0, 983981, 8194, 0, - 121165, 11010, 0, 8893, 0, 983988, 0, 0, 0, 983322, 7925, 0, 0, 113825, - 0, 1352, 11069, 7707, 0, 126486, 0, 0, 0, 0, 65605, 6040, 0, 10071, 0, - 128156, 43750, 0, 8899, 69873, 0, 0, 983316, 128208, 7820, 69615, 0, 0, - 7746, 1492, 0, 0, 0, 66866, 0, 11788, 65913, 0, 0, 43095, 0, 0, 92265, - 2999, 0, 120720, 0, 371, 120759, 6023, 0, 0, 11708, 0, 0, 6323, 0, 0, 0, - 8938, 6043, 65866, 0, 78910, 0, 72419, 0, 129480, 2589, 74332, 1689, - 7802, 0, 0, 0, 0, 66704, 0, 129992, 0, 0, 128127, 6049, 0, 4027, 0, 0, - 111334, 111333, 1503, 111331, 0, 111337, 11951, 111335, 2387, 0, 0, 8289, - 111330, 7326, 66514, 65514, 0, 64865, 0, 9668, 0, 0, 0, 0, 93060, 6036, - 92768, 4026, 74089, 127091, 0, 0, 75044, 110821, 0, 110819, 0, 0, 0, 0, - 6021, 0, 128288, 0, 43155, 0, 110822, 124152, 111343, 42691, 111341, - 111340, 2246, 166, 0, 0, 0, 10623, 408, 0, 111339, 13298, 0, 7426, 43694, - 0, 0, 8811, 0, 0, 129753, 0, 0, 74134, 983054, 0, 127811, 0, 0, 0, 6645, - 646, 128813, 0, 42129, 0, 120880, 0, 8697, 0, 120936, 122953, 0, 0, 0, - 5809, 1950, 0, 92432, 68339, 0, 42136, 0, 0, 0, 0, 0, 0, 111354, 983984, - 0, 0, 111349, 111348, 43330, 111346, 111353, 111352, 41567, 111350, 0, 0, - 0, 0, 111345, 111344, 8285, 0, 4509, 0, 128361, 0, 77774, 129851, 0, 0, - 41727, 0, 0, 0, 0, 0, 71188, 0, 74512, 7027, 3886, 0, 74023, 92888, 0, 0, - 126092, 94058, 119855, 0, 121455, 11707, 119852, 0, 7939, 10342, 92460, - 72747, 121408, 917569, 0, 71198, 94077, 119847, 0, 0, 7201, 0, 123554, - 120866, 983987, 1540, 0, 0, 124923, 0, 119856, 41718, 71177, 0, 0, - 128001, 118699, 0, 119040, 0, 9619, 120840, 0, 0, 0, 0, 3560, 0, 6070, - 129000, 0, 2922, 6082, 70147, 65009, 983973, 0, 0, 0, 0, 0, 0, 3607, - 65863, 0, 92487, 42153, 121042, 0, 983862, 2032, 0, 0, 0, 0, 129985, 0, - 43085, 6057, 0, 0, 0, 0, 0, 0, 0, 0, 638, 6083, 126976, 0, 0, 2305, 0, 0, - 118658, 6056, 10878, 0, 0, 6085, 119351, 0, 3915, 0, 0, 0, 0, 0, 0, 4028, - 1787, 0, 43096, 0, 0, 1768, 0, 0, 0, 128125, 0, 0, 583, 129137, 0, 0, - 66004, 0, 0, 0, 92859, 0, 55267, 120810, 128995, 43075, 65049, 0, 74531, - 0, 93009, 70694, 0, 0, 129375, 9869, 128815, 1771, 0, 0, 0, 0, 0, 0, - 119115, 113708, 0, 0, 74101, 0, 0, 0, 0, 83367, 0, 0, 0, 12539, 123631, - 0, 0, 129846, 73862, 69842, 9897, 0, 100561, 0, 124142, 0, 0, 0, 8931, 0, - 1415, 8866, 74552, 0, 128312, 0, 983566, 43106, 127275, 71089, 1580, - 92278, 68424, 0, 0, 7658, 3440, 78215, 1562, 0, 0, 129031, 0, 0, 0, 0, 0, - 0, 6028, 68900, 42892, 0, 111016, 0, 0, 0, 0, 0, 128269, 0, 66776, 42946, - 127276, 92849, 0, 72448, 120510, 11599, 0, 11602, 11591, 11574, 11581, - 11597, 11598, 6253, 11571, 11584, 70273, 11569, 122937, 8906, 0, 5755, - 2636, 0, 10815, 11619, 129094, 0, 7815, 11616, 11617, 70064, 11618, - 11604, 7869, 11612, 0, 42152, 0, 122941, 0, 92586, 126247, 0, 92173, 0, - 0, 6616, 0, 0, 120875, 391, 0, 0, 0, 42296, 11588, 0, 0, 0, 68397, 0, 0, - 42335, 983189, 0, 0, 7538, 94040, 0, 42491, 0, 0, 128088, 4576, 0, 0, - 43809, 4277, 0, 3563, 0, 42338, 368, 0, 0, 42412, 0, 78209, 119144, 0, - 43814, 983616, 1849, 0, 9921, 42451, 4253, 0, 0, 118688, 42404, 64657, - 73919, 3618, 78338, 0, 0, 0, 0, 0, 929, 6827, 42035, 0, 0, 0, 67847, 0, - 0, 0, 0, 0, 0, 0, 0, 4578, 64513, 0, 0, 0, 71049, 68090, 127086, 43305, - 0, 73462, 118530, 0, 42048, 10166, 0, 127095, 113810, 983128, 0, 983991, - 0, 0, 42483, 0, 0, 0, 42291, 0, 71047, 0, 6641, 525, 66404, 0, 8763, - 125091, 0, 0, 0, 0, 0, 42504, 42581, 74280, 6915, 42310, 0, 8559, 0, - 983994, 125100, 0, 0, 11666, 8679, 0, 1576, 42423, 0, 0, 73840, 983092, - 11374, 0, 10889, 129076, 0, 42462, 0, 77982, 0, 2718, 42424, 0, 0, - 127166, 0, 1179, 0, 0, 0, 363, 11015, 72229, 0, 43857, 0, 66692, 0, 0, 0, - 11041, 72018, 0, 0, 0, 0, 125184, 0, 92520, 0, 9492, 66709, 9212, 12833, - 0, 0, 1297, 122932, 0, 0, 0, 0, 0, 12924, 0, 0, 10090, 125249, 0, 42505, - 0, 42507, 0, 42311, 92940, 120919, 68401, 10759, 0, 0, 120924, 42351, - 42919, 9398, 66292, 0, 9422, 122942, 122943, 0, 0, 0, 129440, 92575, - 1603, 0, 0, 0, 0, 0, 69703, 11250, 0, 0, 10546, 0, 0, 11600, 0, 2797, - 73821, 42427, 306, 714, 3058, 120154, 0, 0, 0, 42395, 0, 11607, 0, 11198, - 127512, 0, 72232, 129067, 0, 42433, 0, 7603, 74063, 0, 42141, 0, 0, 0, - 129085, 8244, 362, 125069, 0, 8037, 0, 0, 0, 69510, 41606, 66696, 77912, - 0, 2093, 0, 120676, 122929, 41604, 0, 0, 0, 0, 10523, 1446, 42320, 0, - 120247, 64773, 42472, 0, 0, 1722, 5581, 0, 64496, 0, 0, 64914, 0, 42620, - 128603, 124988, 0, 0, 10549, 130035, 71190, 0, 0, 0, 0, 0, 71712, 0, 0, - 0, 0, 0, 0, 0, 7684, 66338, 0, 1174, 0, 0, 983621, 0, 0, 0, 42277, 0, - 42456, 65667, 0, 0, 0, 0, 42417, 0, 0, 120812, 42304, 0, 0, 0, 74443, - 127894, 0, 8313, 0, 0, 1316, 66690, 0, 0, 0, 0, 0, 0, 66844, 983715, 0, - 0, 0, 65200, 3383, 0, 0, 70063, 122947, 0, 0, 42420, 119185, 0, 0, - 983917, 0, 121079, 72369, 0, 42343, 124980, 42706, 1751, 42496, 65742, - 13166, 0, 0, 0, 0, 0, 42683, 12697, 0, 0, 0, 125047, 0, 42346, 0, 0, - 3757, 0, 0, 121075, 65869, 0, 9247, 74976, 3193, 0, 0, 42459, 7596, 7921, - 0, 74095, 0, 42499, 11590, 66006, 0, 42307, 0, 43953, 118591, 0, 1023, - 474, 0, 0, 0, 0, 42487, 0, 0, 0, 42295, 0, 121474, 72237, 0, 9835, 0, - 127782, 0, 12275, 0, 0, 8595, 0, 0, 0, 0, 0, 10118, 0, 129156, 0, 0, 0, - 0, 0, 0, 699, 0, 120923, 11601, 0, 92941, 0, 7581, 0, 92530, 0, 0, 0, - 7765, 65583, 0, 0, 64597, 43444, 0, 92197, 0, 64279, 7036, 5823, 1937, 0, - 917854, 65415, 13308, 65417, 0, 65217, 0, 0, 11017, 0, 0, 7294, 0, 0, 0, - 0, 42466, 65416, 68858, 0, 71350, 65413, 92381, 126498, 12964, 42240, - 1941, 0, 0, 1713, 118679, 0, 0, 11407, 42441, 128262, 6297, 0, 0, 0, - 42481, 0, 0, 7179, 42289, 0, 120921, 969, 0, 0, 0, 6165, 0, 0, 0, 0, - 42402, 0, 0, 0, 129511, 0, 72234, 0, 0, 64876, 92635, 6046, 0, 6208, - 128870, 129309, 73749, 0, 0, 42422, 0, 0, 128155, 73775, 338, 0, 121369, - 0, 42328, 10767, 0, 8115, 0, 0, 0, 0, 92687, 0, 0, 0, 0, 73029, 0, 0, 0, - 71687, 4486, 128082, 2171, 0, 10925, 0, 0, 0, 0, 42309, 10257, 0, 10273, - 7668, 10305, 42461, 74882, 42349, 8832, 0, 0, 10644, 0, 129531, 42278, 0, - 0, 69874, 0, 129949, 42429, 0, 42316, 11223, 0, 0, 42468, 0, 0, 0, 65402, - 0, 0, 72235, 0, 0, 41963, 120990, 0, 0, 125013, 6823, 42391, 1588, 65400, - 0, 0, 0, 65398, 787, 0, 0, 0, 0, 2078, 127239, 65399, 0, 0, 0, 65401, 0, - 121196, 0, 113816, 644, 0, 71335, 0, 3659, 0, 0, 0, 13107, 92669, 0, - 10502, 74457, 0, 11221, 41554, 0, 0, 0, 41557, 11209, 0, 11070, 119221, - 0, 0, 73858, 41555, 9514, 0, 66771, 64641, 92447, 0, 7520, 73888, 77955, - 0, 0, 0, 0, 0, 64527, 0, 118707, 12723, 0, 68776, 0, 0, 0, 78835, 4055, - 78826, 77960, 65212, 0, 127353, 12319, 0, 0, 983218, 7964, 65427, 0, - 65424, 72217, 120966, 0, 65425, 74890, 128251, 0, 0, 0, 3448, 10827, 0, - 9866, 74527, 0, 0, 8625, 69783, 92304, 10477, 0, 0, 0, 65423, 0, 0, 0, 0, - 6152, 0, 0, 6629, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11046, 11490, 0, 4485, - 71126, 0, 0, 0, 0, 0, 5869, 118533, 119633, 0, 7040, 3588, 0, 12825, 0, - 0, 128569, 0, 0, 0, 0, 0, 126637, 0, 0, 128449, 64499, 65245, 127367, - 1171, 127368, 69717, 127365, 1805, 8772, 0, 127363, 9930, 65247, 0, 0, - 2338, 127362, 92695, 0, 0, 0, 69219, 0, 120104, 0, 120103, 72221, 120102, - 129924, 118814, 8734, 4212, 0, 0, 66701, 0, 65862, 0, 120095, 42903, 0, - 0, 0, 126117, 426, 0, 120098, 8251, 0, 65436, 0, 2120, 43302, 1224, 0, - 65576, 0, 66876, 1764, 6074, 0, 12858, 0, 0, 65439, 6378, 74566, 128885, - 41960, 0, 41644, 0, 2129, 0, 9222, 0, 0, 4259, 9092, 0, 41961, 0, 0, - 66357, 42331, 64935, 0, 0, 1293, 0, 2132, 0, 983569, 0, 2454, 0, 3613, - 128837, 71117, 0, 0, 69681, 10978, 10840, 0, 10668, 72826, 127197, 9118, - 120164, 0, 0, 0, 1157, 64903, 8638, 0, 101295, 0, 0, 0, 0, 67466, 128981, - 10086, 0, 11128, 0, 0, 65430, 74013, 6079, 0, 10764, 127910, 64435, - 128051, 1339, 118643, 65428, 1317, 8822, 0, 0, 0, 127143, 0, 0, 0, 43110, - 0, 10428, 129848, 0, 0, 5742, 43076, 4692, 0, 0, 4007, 5004, 128781, 0, - 751, 6595, 6596, 0, 66373, 0, 0, 64908, 0, 6593, 72349, 12004, 119192, - 74097, 43108, 0, 0, 119333, 92188, 6598, 0, 6599, 0, 93031, 74194, 0, - 121483, 66674, 6597, 0, 73921, 0, 64745, 2281, 0, 0, 128996, 43790, 0, - 2430, 41678, 71492, 0, 43785, 113716, 0, 121263, 0, 0, 1921, 0, 19927, - 70390, 65406, 0, 43786, 4284, 128346, 72210, 43789, 12841, 9229, 0, - 42285, 0, 0, 0, 0, 3521, 0, 118690, 8325, 0, 65403, 0, 1854, 0, 0, 0, 0, - 0, 0, 0, 0, 4344, 0, 65433, 6076, 0, 0, 74764, 12074, 0, 0, 129148, 0, - 12934, 119555, 65432, 128877, 0, 6071, 65434, 0, 65435, 4053, 128623, 0, - 0, 0, 917934, 69823, 127463, 0, 121403, 127473, 8421, 73836, 0, 43705, - 502, 0, 65431, 0, 0, 0, 1303, 316, 7364, 0, 2136, 0, 120796, 64365, - 43480, 92639, 4860, 0, 127877, 0, 129728, 9583, 0, 5546, 0, 118565, 0, 0, - 0, 5544, 127475, 0, 70352, 5543, 128917, 72821, 12137, 5548, 0, 0, 10007, - 0, 127523, 6077, 0, 65452, 0, 119341, 11214, 65952, 0, 72226, 0, 0, 1319, - 74210, 65410, 67399, 92606, 0, 0, 118660, 0, 66716, 83513, 4691, 128619, - 9345, 621, 92872, 0, 122889, 65411, 0, 74575, 121246, 65408, 73899, 0, - 9474, 2812, 119118, 65412, 3786, 65409, 8894, 83246, 119611, 7923, 3716, - 92798, 0, 0, 0, 7012, 124122, 128439, 9566, 0, 94176, 0, 65012, 126242, - 545, 9575, 0, 10050, 12718, 0, 8859, 6820, 124915, 129941, 120740, 0, 0, - 9119, 2787, 0, 984000, 8507, 2012, 7985, 0, 0, 0, 0, 194634, 0, 410, 0, - 0, 120789, 120609, 0, 120378, 120379, 0, 0, 120374, 72742, 120376, - 120377, 120370, 120371, 120372, 120373, 3860, 120367, 72205, 74031, - 111131, 73685, 11748, 120365, 7941, 111134, 8749, 111132, 12698, 111129, - 361, 110793, 845, 67509, 0, 0, 4562, 72241, 2926, 0, 4569, 0, 110797, - 43487, 0, 0, 0, 74287, 122885, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6291, 0, 0, 0, - 9734, 0, 0, 0, 0, 127754, 7359, 83523, 43863, 0, 111150, 8769, 111148, - 111147, 111145, 4859, 111143, 111142, 0, 0, 0, 0, 12172, 111136, 0, - 127899, 111141, 64764, 4210, 111138, 0, 804, 0, 83520, 0, 70344, 0, 0, - 67202, 10091, 67200, 119257, 67206, 67205, 67204, 67203, 72302, 0, 0, 0, - 128959, 0, 1425, 92259, 119229, 11049, 0, 71480, 42649, 8482, 0, 0, - 66715, 67209, 11940, 67207, 664, 0, 0, 0, 70200, 127525, 0, 70194, 93061, - 111155, 68474, 111153, 6032, 67218, 67217, 7430, 194670, 70191, 0, 0, 0, - 0, 0, 41161, 0, 9765, 10993, 41162, 0, 70189, 1169, 111181, 0, 1905, - 6034, 41164, 64744, 43236, 0, 128800, 73110, 0, 0, 788, 0, 0, 111167, - 111128, 1663, 128976, 42901, 127237, 67211, 67210, 0, 0, 67215, 67214, - 67213, 67212, 111160, 111159, 111158, 111157, 0, 69492, 0, 111161, 43612, - 0, 0, 0, 10855, 67223, 9355, 67221, 65198, 120355, 0, 221, 0, 0, 0, - 121141, 7191, 118930, 72208, 125212, 0, 0, 0, 0, 67228, 67227, 43333, - 67225, 0, 0, 0, 67229, 0, 7245, 0, 74405, 69922, 72219, 111178, 3873, - 8367, 111174, 111173, 111172, 43649, 0, 111177, 111176, 0, 11164, 0, - 74403, 111171, 111170, 111169, 7682, 74404, 1462, 10235, 0, 0, 0, 0, 0, - 111130, 0, 0, 74402, 0, 92299, 0, 0, 74052, 0, 126127, 120549, 0, 64295, - 0, 0, 0, 0, 0, 120662, 0, 0, 67231, 67230, 10755, 55257, 11155, 128568, - 983137, 9470, 0, 127540, 0, 69680, 64384, 0, 128607, 0, 0, 0, 122987, - 73764, 8204, 0, 0, 0, 0, 0, 8728, 0, 10904, 73446, 19936, 7833, 0, 0, 0, - 0, 92546, 0, 0, 0, 8537, 0, 0, 0, 121244, 0, 0, 2254, 128193, 0, 0, 0, 0, - 3062, 0, 0, 0, 0, 0, 41160, 41147, 41158, 0, 120777, 0, 41155, 111116, - 111115, 111114, 0, 121332, 111119, 111118, 111117, 129878, 0, 129091, 0, - 0, 0, 64594, 2456, 66867, 0, 0, 0, 0, 3721, 0, 0, 1230, 2678, 0, 3597, - 917795, 0, 0, 92215, 0, 67737, 8352, 0, 0, 0, 64515, 121378, 0, 129128, - 67846, 0, 129767, 92466, 0, 0, 71338, 0, 8660, 0, 0, 0, 0, 0, 4483, 0, 0, - 0, 6080, 0, 0, 1746, 1315, 0, 70201, 0, 13140, 74508, 0, 0, 4480, 0, - 111113, 111112, 0, 67979, 0, 6360, 10897, 111106, 605, 68302, 110737, - 69875, 110735, 110736, 66681, 0, 0, 0, 0, 0, 0, 0, 10877, 118868, 64885, - 0, 0, 0, 0, 0, 0, 345, 0, 0, 64606, 9917, 0, 0, 92196, 0, 1776, 8422, - 43992, 0, 0, 0, 126543, 43328, 0, 0, 1295, 0, 42869, 0, 0, 0, 0, 128772, - 65123, 125210, 11293, 11288, 0, 0, 65666, 0, 92369, 65420, 0, 0, 4252, 0, - 0, 0, 706, 72800, 0, 0, 129931, 65419, 92177, 0, 8419, 65421, 0, 66702, - 0, 12670, 118608, 0, 0, 0, 72825, 65422, 83008, 0, 0, 0, 0, 0, 124153, - 9736, 4184, 65418, 0, 0, 74035, 0, 129955, 0, 0, 0, 0, 129447, 0, 7962, - 12211, 9837, 83505, 0, 0, 5719, 0, 129720, 119068, 73777, 1857, 0, 9927, - 0, 983959, 0, 10037, 0, 73695, 78322, 78319, 7818, 0, 0, 127769, 0, 0, 0, - 65077, 0, 78325, 78326, 78323, 43327, 43989, 0, 65828, 0, 0, 83499, 0, - 68390, 0, 110687, 78336, 78339, 9543, 78335, 78332, 78333, 0, 127964, 0, - 129552, 983914, 0, 69448, 0, 71429, 0, 0, 0, 11914, 69431, 0, 0, 0, 9949, - 0, 0, 119215, 0, 12073, 73519, 0, 0, 0, 101218, 2260, 0, 0, 0, 0, 0, 0, - 1939, 0, 0, 0, 69903, 0, 0, 0, 0, 6643, 92477, 128485, 0, 78330, 78331, - 78328, 78329, 0, 92551, 0, 0, 0, 0, 124124, 72417, 0, 0, 0, 0, 78341, - 78342, 120944, 78340, 129513, 127529, 92350, 3784, 78350, 0, 78348, - 78349, 78345, 43324, 78343, 78344, 2231, 0, 0, 0, 42467, 0, 0, 42894, - 78363, 13281, 78360, 78361, 78356, 78358, 78353, 64899, 0, 41149, 0, - 43162, 68096, 41150, 0, 10571, 67162, 67161, 67160, 67159, 6947, 41152, - 887, 9249, 6565, 64806, 74366, 0, 67158, 67157, 0, 10831, 67175, 67174, - 120232, 65827, 43325, 67178, 10168, 67176, 0, 0, 9190, 128497, 9666, - 41997, 0, 0, 0, 0, 0, 0, 129411, 0, 78508, 0, 78351, 78352, 0, 75063, - 72839, 983749, 0, 126604, 0, 0, 0, 983422, 0, 2270, 0, 129957, 0, 78365, - 0, 67189, 72818, 0, 0, 0, 0, 0, 0, 0, 72833, 101119, 78366, 78367, 0, 0, - 0, 0, 10137, 6121, 10995, 0, 71050, 8119, 0, 71052, 0, 0, 0, 0, 0, 0, 0, - 1394, 0, 0, 128960, 0, 67184, 2998, 67182, 67181, 67188, 67187, 67186, - 67185, 0, 101185, 0, 0, 67180, 42003, 0, 0, 67193, 67192, 67191, 67190, - 67197, 67196, 67195, 67194, 0, 72770, 43315, 71051, 0, 1593, 0, 125120, - 619, 4635, 0, 72875, 0, 128859, 118657, 0, 0, 0, 67199, 67198, 0, 42790, - 42006, 0, 0, 0, 128998, 10757, 9347, 127767, 0, 0, 74227, 78904, 0, - 74116, 128423, 121073, 120860, 0, 92427, 0, 0, 0, 0, 64590, 0, 4371, 0, - 0, 92478, 0, 0, 73977, 0, 0, 127847, 0, 120862, 0, 64550, 73745, 70451, - 0, 121013, 0, 0, 0, 129286, 0, 0, 0, 0, 9131, 118648, 125214, 983223, 0, - 0, 64260, 0, 12606, 0, 0, 0, 0, 562, 983614, 0, 129648, 66455, 127533, - 3219, 0, 0, 0, 1037, 0, 64491, 0, 78579, 78572, 78580, 4568, 549, 0, 0, - 0, 0, 0, 128095, 70851, 2205, 0, 0, 0, 0, 129716, 0, 10825, 8079, 118962, - 0, 0, 0, 128855, 0, 13071, 0, 0, 41049, 42840, 43614, 129341, 74881, - 74596, 127191, 5212, 0, 66402, 119191, 0, 9747, 0, 0, 129778, 984008, - 41047, 1668, 0, 0, 0, 1187, 0, 74416, 0, 0, 0, 0, 3240, 128518, 9213, 0, - 0, 0, 127174, 69822, 0, 0, 0, 0, 1623, 0, 0, 0, 0, 0, 0, 11272, 0, 73914, - 65048, 1909, 42172, 0, 0, 10736, 11580, 72228, 7615, 0, 0, 4237, 66576, - 0, 65815, 68083, 0, 0, 0, 3489, 0, 0, 0, 0, 0, 0, 127146, 3796, 6800, 0, - 65582, 0, 129521, 0, 0, 68036, 0, 0, 64857, 121213, 126493, 0, 66308, 0, - 0, 64634, 127817, 0, 0, 0, 0, 3246, 0, 43972, 128643, 0, 0, 0, 0, 120751, - 0, 0, 0, 0, 1496, 42827, 0, 942, 2378, 119213, 0, 0, 0, 0, 9510, 1232, - 8139, 0, 0, 0, 11409, 0, 6382, 0, 66319, 121237, 0, 0, 0, 127887, 2374, - 0, 8475, 120844, 66313, 0, 0, 64879, 119298, 0, 0, 70869, 0, 0, 129025, - 0, 7705, 11942, 0, 0, 3309, 0, 119302, 0, 83345, 983866, 0, 0, 1280, - 6998, 128104, 0, 0, 0, 129945, 0, 0, 0, 0, 0, 0, 0, 74239, 983073, 0, 0, - 0, 6078, 121354, 0, 1475, 0, 9938, 6084, 0, 983995, 0, 118571, 0, 3256, - 0, 43973, 0, 0, 0, 8727, 0, 0, 0, 110831, 110832, 10562, 110830, 0, 0, 0, - 3248, 0, 0, 9015, 0, 0, 3635, 64337, 0, 0, 43852, 7195, 0, 2007, 64431, - 0, 0, 0, 0, 0, 0, 0, 65613, 77909, 0, 0, 0, 0, 119218, 7984, 11670, - 74434, 127770, 4176, 69248, 2034, 69442, 11154, 65891, 0, 0, 318, 2038, - 0, 0, 0, 3649, 13149, 42145, 42798, 3634, 0, 0, 128483, 122928, 124113, - 0, 11402, 120954, 94032, 74238, 0, 43313, 0, 0, 7938, 0, 1761, 0, 65379, - 68386, 128185, 1159, 71183, 0, 0, 0, 66687, 120851, 0, 41680, 0, 0, 0, - 1514, 11668, 67891, 9313, 0, 128490, 67877, 0, 41681, 0, 0, 12848, 69982, - 67873, 0, 74278, 0, 0, 12649, 0, 0, 1194, 3242, 9761, 9555, 8598, 0, - 120524, 0, 1551, 65447, 129414, 126211, 0, 0, 0, 67875, 0, 3495, 66648, - 125079, 0, 73024, 983232, 0, 126130, 10641, 0, 0, 0, 77845, 0, 0, 0, 0, - 0, 11131, 0, 0, 0, 0, 0, 42685, 72017, 193, 0, 0, 0, 42667, 0, 0, 92318, - 71958, 0, 1362, 9558, 0, 0, 0, 7351, 73789, 0, 0, 4426, 0, 0, 0, 0, 7276, - 42163, 5220, 0, 0, 67822, 0, 0, 0, 0, 41692, 0, 72283, 0, 0, 3223, 65492, - 0, 0, 4549, 983706, 0, 0, 101162, 10807, 0, 0, 0, 42182, 8688, 12866, 0, - 3294, 0, 0, 128101, 0, 64514, 0, 43329, 129989, 0, 0, 0, 119061, 0, - 43422, 0, 0, 128618, 0, 42729, 0, 3215, 120982, 68880, 917564, 0, 0, 0, - 65682, 0, 0, 65924, 0, 73506, 0, 1501, 0, 118807, 0, 0, 9607, 0, 65794, - 72243, 983046, 10989, 0, 74399, 0, 0, 7152, 0, 0, 129530, 7483, 125083, - 0, 8104, 70128, 7474, 0, 5189, 0, 0, 0, 8141, 0, 42537, 69612, 0, 0, 0, - 0, 0, 127307, 42934, 0, 0, 0, 0, 0, 0, 64517, 0, 0, 1650, 0, 0, 128502, - 7901, 3238, 0, 65556, 0, 0, 65158, 43416, 74959, 0, 7527, 0, 43319, 0, 0, - 45, 0, 0, 0, 0, 0, 7347, 0, 0, 0, 13129, 0, 9084, 0, 8737, 0, 0, 0, - 66808, 9639, 7912, 2620, 129653, 3564, 0, 0, 0, 0, 75049, 0, 2853, 0, 0, - 0, 0, 0, 2850, 8084, 0, 0, 71446, 92284, 43122, 0, 0, 0, 126503, 72214, - 0, 74767, 0, 7331, 110646, 0, 8245, 0, 3158, 92396, 3983, 0, 923, 0, - 69397, 292, 0, 126548, 0, 3221, 1763, 0, 0, 0, 0, 7253, 194636, 68391, - 75002, 0, 3637, 12996, 0, 70461, 0, 0, 3228, 0, 0, 0, 0, 0, 0, 120833, - 118939, 0, 7696, 78589, 0, 0, 0, 43316, 4177, 0, 9089, 0, 128805, 72116, - 64500, 68133, 0, 0, 1856, 100572, 0, 6379, 0, 118999, 0, 3208, 0, 0, 0, - 0, 0, 0, 129402, 0, 0, 0, 2033, 0, 0, 0, 55254, 7740, 0, 0, 0, 128197, 0, - 93988, 0, 67612, 0, 0, 41689, 129380, 0, 0, 6646, 0, 0, 0, 983964, 0, 0, - 4573, 0, 0, 0, 0, 0, 92961, 0, 118620, 41688, 0, 0, 0, 8314, 0, 0, 0, 0, - 0, 66721, 0, 0, 121033, 0, 128226, 0, 0, 0, 13164, 0, 66237, 983982, 0, - 0, 0, 3257, 0, 0, 1845, 0, 0, 0, 0, 128783, 0, 0, 0, 0, 3499, 8609, 0, - 7145, 0, 0, 0, 0, 74829, 984007, 983296, 0, 0, 0, 7591, 0, 0, 0, 73778, - 70132, 128167, 0, 0, 0, 0, 119261, 0, 0, 118561, 13083, 0, 0, 0, 0, - 66177, 983274, 5429, 0, 0, 68168, 66181, 0, 0, 983258, 0, 0, 5433, 67659, - 0, 42776, 1547, 66176, 92428, 0, 5425, 4977, 9999, 0, 5423, 64560, - 125094, 0, 0, 0, 74122, 0, 0, 0, 128003, 4418, 66199, 0, 92300, 0, 0, 0, - 11863, 124995, 0, 11908, 0, 9360, 125101, 983204, 0, 66187, 12837, - 983293, 0, 11112, 0, 92321, 43318, 0, 0, 0, 0, 126518, 120604, 0, 983291, - 0, 129595, 0, 983801, 0, 9958, 0, 125108, 0, 0, 0, 2433, 128602, 0, 3352, - 0, 0, 0, 0, 0, 0, 305, 567, 67662, 0, 69979, 65242, 0, 41695, 0, 0, 0, - 7837, 92873, 129002, 5337, 917622, 7325, 43312, 917619, 68742, 917617, - 74086, 68777, 917614, 917613, 10973, 917611, 1372, 128768, 917608, - 917607, 1254, 917605, 917604, 93967, 917602, 65228, 113753, 129367, - 67723, 8068, 0, 0, 983970, 0, 3245, 64393, 119069, 118681, 0, 0, 0, 0, 0, - 0, 983284, 0, 119563, 129935, 78865, 0, 126638, 0, 0, 43322, 0, 0, 0, 0, - 92698, 3226, 67695, 0, 0, 983958, 10200, 0, 128779, 101143, 0, 65610, 0, - 0, 0, 3585, 250, 101142, 43320, 0, 0, 0, 0, 1152, 129849, 1688, 0, 0, 0, - 0, 0, 121040, 128340, 0, 0, 0, 2107, 0, 129048, 0, 0, 0, 43868, 129832, - 129817, 0, 128239, 0, 0, 127777, 0, 6927, 42267, 42261, 11464, 3365, 0, - 0, 0, 0, 0, 41869, 0, 0, 0, 43326, 0, 11519, 0, 5530, 5210, 0, 983989, 0, - 5208, 0, 128842, 0, 2424, 7976, 0, 0, 3244, 5529, 0, 73894, 128852, 5432, - 0, 5527, 0, 78484, 0, 5528, 0, 0, 120281, 0, 0, 43545, 120282, 0, 0, - 73686, 42565, 0, 0, 3206, 120278, 73985, 0, 101149, 0, 0, 211, 3216, - 83407, 0, 120998, 3220, 68750, 0, 118586, 8951, 5214, 0, 8118, 0, 10768, - 8735, 0, 5852, 124952, 0, 0, 67513, 0, 0, 2623, 127859, 0, 0, 127388, - 4698, 66509, 0, 0, 4701, 0, 120289, 74225, 120284, 8267, 0, 1421, 66426, - 0, 0, 2625, 92724, 0, 74309, 0, 0, 0, 7850, 120296, 69639, 127032, 0, 0, - 43384, 12660, 110663, 0, 0, 110706, 110661, 0, 92380, 0, 0, 69649, 0, - 713, 41073, 0, 3990, 0, 0, 0, 5017, 128313, 120352, 0, 0, 1030, 0, - 983121, 9513, 0, 0, 0, 4668, 0, 120350, 0, 6339, 0, 0, 0, 64650, 0, 0, - 74766, 983869, 8908, 0, 0, 0, 0, 10752, 13003, 68769, 0, 41307, 8732, - 120336, 0, 41310, 0, 4696, 0, 983953, 0, 120334, 3641, 5419, 124119, 0, - 0, 0, 120344, 128129, 0, 7320, 65230, 11808, 0, 93970, 936, 13289, 0, - 69892, 65774, 0, 65243, 0, 19953, 0, 126469, 121375, 127256, 12913, - 70722, 68759, 0, 0, 70203, 0, 4113, 0, 2372, 1819, 0, 128053, 12152, 0, - 682, 7655, 120330, 129921, 0, 10593, 1703, 0, 0, 8033, 69953, 0, 9810, 0, - 0, 127949, 0, 119159, 10109, 0, 73898, 0, 71730, 126704, 0, 0, 917620, - 1965, 917621, 0, 0, 73887, 0, 0, 0, 6314, 0, 8501, 0, 0, 0, 41317, 0, - 5417, 983582, 0, 0, 9353, 68148, 41315, 0, 11161, 0, 41314, 194892, 0, - 126562, 119236, 634, 0, 0, 0, 69779, 4355, 12016, 0, 9654, 12856, 6924, - 7660, 0, 0, 0, 0, 0, 42692, 0, 74604, 0, 0, 0, 680, 6274, 0, 1181, 0, - 3174, 67248, 0, 0, 0, 0, 113776, 10650, 917603, 92295, 70672, 118965, 0, - 64644, 126981, 0, 0, 0, 0, 983961, 0, 65302, 40989, 68239, 68230, 68234, - 0, 0, 124989, 0, 40987, 4667, 0, 983963, 8828, 0, 0, 0, 4746, 0, 129840, - 2269, 4749, 0, 100598, 65192, 4744, 7345, 0, 242, 100595, 0, 8217, 0, - 68919, 0, 2245, 0, 0, 66790, 10850, 0, 0, 0, 983391, 0, 129853, 64680, 0, - 0, 120562, 0, 127324, 0, 100551, 128721, 0, 7316, 0, 983610, 100552, - 74157, 1646, 0, 0, 73995, 120857, 73500, 0, 7350, 0, 0, 0, 9099, 4107, - 3441, 0, 2975, 194701, 0, 983966, 55220, 10084, 73943, 120845, 118649, 0, - 0, 3399, 0, 0, 11909, 0, 0, 7687, 0, 6789, 0, 0, 72739, 71367, 0, 0, - 92589, 9151, 1137, 0, 749, 7505, 125076, 5385, 0, 69387, 0, 0, 41298, 0, - 69461, 0, 0, 0, 0, 0, 0, 128455, 0, 519, 0, 64547, 5766, 0, 0, 0, 8848, - 0, 41297, 0, 0, 0, 41300, 74468, 65160, 0, 129839, 127511, 0, 0, 6558, 0, - 0, 128686, 92775, 0, 71450, 41302, 127927, 0, 0, 128646, 68762, 11729, - 8719, 9060, 0, 128796, 0, 0, 118573, 129682, 0, 11734, 93011, 11730, - 73450, 9593, 5757, 2403, 0, 55275, 0, 11728, 65894, 0, 0, 0, 68741, 0, 0, - 0, 43489, 4282, 983864, 0, 83497, 70328, 128103, 70324, 0, 69490, 127509, - 0, 8456, 0, 0, 74783, 0, 78250, 0, 70320, 120722, 9792, 0, 70326, 0, 0, - 83500, 70322, 10019, 71701, 123617, 6568, 4365, 129399, 0, 3647, 0, - 41134, 128341, 0, 125043, 41135, 0, 0, 0, 129938, 0, 123616, 0, 41137, - 41139, 0, 6545, 0, 125139, 7597, 10528, 75054, 0, 3732, 73910, 0, 0, 0, - 7312, 983639, 9062, 93840, 11853, 0, 0, 128324, 41538, 0, 0, 118702, 0, - 194706, 41531, 1263, 3720, 0, 68028, 0, 41524, 64692, 119635, 0, 41534, - 0, 92193, 0, 41168, 0, 67398, 127347, 3524, 0, 8831, 127349, 127357, 0, - 127360, 127352, 129816, 0, 0, 0, 0, 0, 5845, 0, 0, 0, 71909, 8200, 0, - 68460, 0, 43283, 5551, 0, 0, 0, 6340, 983552, 100602, 0, 0, 0, 0, 0, - 5422, 0, 0, 0, 2471, 0, 0, 2749, 0, 73774, 10913, 72122, 0, 8666, 675, - 74093, 0, 194986, 0, 69262, 0, 0, 0, 10928, 0, 41153, 0, 0, 0, 3738, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42347, 12092, 9615, 7234, 74047, - 129782, 0, 0, 123639, 0, 0, 2934, 0, 0, 0, 0, 74507, 0, 74461, 0, 0, - 74290, 0, 64562, 129975, 64473, 0, 0, 73728, 0, 11212, 0, 12128, 6534, 0, - 0, 1901, 0, 0, 0, 0, 0, 127520, 0, 0, 0, 0, 69940, 65459, 68293, 92290, - 128808, 3770, 0, 0, 0, 64579, 128511, 0, 0, 983337, 983345, 0, 0, 0, - 5941, 0, 0, 65079, 0, 0, 0, 73961, 983339, 0, 0, 0, 0, 0, 0, 10638, 0, 0, - 0, 71486, 0, 0, 983354, 0, 43840, 129495, 0, 5233, 983351, 64792, 71233, - 0, 983329, 0, 73553, 9847, 0, 1685, 595, 0, 73971, 1292, 8940, 0, 11088, - 0, 10004, 0, 0, 6541, 0, 0, 0, 5603, 9014, 5606, 0, 538, 128705, 5602, - 8467, 74391, 6547, 0, 0, 0, 0, 8458, 129534, 8495, 0, 0, 917552, 10981, - 78314, 125057, 2465, 0, 0, 0, 9730, 9280, 0, 0, 74155, 72766, 113690, 0, - 504, 0, 120715, 0, 983606, 0, 0, 0, 123141, 125024, 0, 0, 732, 3737, 0, - 1548, 0, 0, 1832, 5604, 0, 41141, 0, 5607, 72854, 2176, 3745, 0, 0, - 128137, 0, 0, 3869, 11937, 5725, 0, 66566, 7416, 5728, 0, 0, 0, 11918, - 66567, 5724, 118829, 5727, 0, 0, 0, 5723, 118585, 128116, 71999, 0, 0, 0, - 42532, 0, 12303, 0, 11423, 0, 983116, 68303, 74074, 0, 128267, 6559, - 64557, 71348, 0, 66763, 43019, 0, 10238, 0, 0, 43377, 0, 71346, 124937, - 9783, 42704, 0, 71719, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41144, 129465, 0, - 0, 0, 72793, 92176, 0, 70682, 0, 8820, 0, 0, 0, 11515, 526, 0, 0, 0, 0, - 0, 0, 8635, 0, 0, 8288, 11815, 0, 0, 0, 1543, 3713, 0, 0, 0, 68041, - 127816, 0, 0, 64357, 0, 42082, 0, 0, 8987, 42081, 0, 0, 0, 0, 0, 0, 6553, - 0, 0, 11253, 0, 0, 5475, 0, 0, 0, 119334, 12990, 1160, 42084, 0, 123152, - 0, 0, 360, 0, 0, 128274, 5863, 3137, 0, 983320, 0, 0, 10959, 3146, 0, - 127374, 0, 68341, 13076, 3135, 983303, 0, 0, 3142, 0, 94068, 10819, - 128479, 0, 74635, 12877, 119867, 73967, 0, 70808, 0, 0, 0, 0, 6163, - 129745, 113728, 0, 0, 0, 8603, 0, 0, 3306, 0, 43392, 0, 917565, 5751, 0, - 0, 0, 0, 0, 7403, 0, 118933, 0, 122628, 64783, 92658, 0, 0, 129592, 0, 0, - 65569, 7021, 0, 0, 119864, 0, 0, 6540, 6974, 0, 0, 0, 0, 0, 0, 0, 983655, - 0, 43585, 0, 6551, 983993, 0, 0, 0, 0, 0, 72216, 8977, 602, 120814, 0, 0, - 0, 72119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 983624, 74812, 0, 0, 0, 9475, 0, - 65105, 0, 118556, 0, 43592, 7831, 66751, 0, 0, 73915, 0, 43593, 0, 43591, - 43061, 0, 0, 43589, 43584, 0, 13113, 0, 0, 43590, 8766, 9087, 0, 0, - 41574, 78337, 0, 42900, 6376, 0, 0, 0, 0, 9854, 0, 0, 0, 0, 0, 0, 0, - 2909, 110928, 0, 0, 6529, 110930, 75004, 3751, 0, 0, 0, 1798, 0, 0, 1354, - 0, 13152, 6557, 12430, 0, 94098, 0, 0, 0, 68123, 128097, 0, 0, 0, 71264, - 123559, 11082, 0, 65677, 8682, 42054, 92595, 42045, 9804, 0, 0, 3595, 0, - 0, 119498, 0, 42399, 0, 0, 0, 65541, 0, 7324, 0, 0, 0, 8797, 77895, 0, - 64888, 7167, 2356, 95, 110810, 0, 0, 42286, 0, 0, 69999, 0, 120877, 0, 0, - 42324, 129359, 0, 0, 43492, 0, 43406, 0, 0, 0, 0, 0, 43400, 0, 0, 71720, - 0, 66435, 0, 0, 3201, 514, 74502, 0, 43396, 0, 64493, 0, 43404, 11218, 0, - 0, 43398, 0, 0, 41341, 129485, 6564, 1463, 41342, 0, 5293, 0, 0, 3733, 0, - 0, 41344, 0, 0, 0, 0, 41346, 0, 69747, 0, 0, 0, 0, 0, 0, 0, 983764, 0, 0, - 0, 65272, 0, 0, 1270, 1132, 0, 0, 0, 66655, 0, 0, 74314, 64761, 0, - 110853, 8510, 0, 129600, 0, 0, 0, 0, 0, 0, 69692, 0, 0, 42383, 69690, 0, - 69700, 13141, 0, 92465, 0, 0, 0, 41566, 0, 0, 129334, 127171, 0, 0, 0, 0, - 0, 0, 0, 6308, 0, 0, 2611, 0, 66881, 0, 65063, 0, 0, 0, 0, 4484, 8747, - 110597, 128369, 0, 0, 0, 0, 0, 0, 12902, 0, 0, 7299, 0, 0, 12107, 7100, - 10905, 65010, 0, 125135, 66018, 9284, 0, 0, 0, 0, 0, 0, 0, 12010, 0, - 126093, 120949, 121032, 0, 0, 0, 0, 0, 0, 0, 0, 6618, 3562, 66365, 0, - 42234, 12648, 128039, 0, 0, 0, 41309, 9764, 41316, 0, 0, 13230, 41299, 0, - 0, 68365, 0, 0, 0, 0, 0, 0, 4153, 0, 0, 128047, 0, 0, 42889, 0, 129322, - 41578, 0, 41577, 0, 68092, 0, 6533, 0, 41570, 0, 72414, 0, 41580, 74628, - 0, 12901, 0, 0, 0, 0, 71461, 41360, 0, 0, 4743, 0, 0, 0, 0, 68398, - 110781, 5890, 110779, 111103, 3739, 8695, 92514, 0, 3964, 8984, 111095, - 68288, 0, 0, 70000, 111090, 111089, 67504, 3956, 82952, 111093, 6563, - 111091, 41305, 0, 0, 12067, 41312, 0, 0, 0, 129708, 0, 8175, 0, 3600, 0, - 934, 0, 0, 173, 129844, 0, 110784, 110785, 1750, 110783, 41358, 68368, - 1807, 0, 92298, 0, 5889, 0, 0, 0, 67127, 129472, 0, 121395, 6982, 1721, - 0, 7891, 0, 42160, 67129, 4512, 983790, 69460, 0, 0, 0, 122636, 0, - 120716, 0, 0, 0, 0, 0, 119140, 3975, 72253, 74087, 0, 12672, 0, 129821, - 0, 0, 129836, 0, 121100, 0, 0, 41095, 3962, 68242, 2932, 41101, 3954, - 6457, 4513, 0, 0, 0, 0, 1468, 0, 0, 55237, 128230, 0, 127244, 55238, - 41080, 0, 0, 4320, 74104, 0, 0, 83315, 0, 77918, 118563, 128384, 8256, 0, - 72413, 0, 8879, 0, 0, 8770, 0, 0, 92214, 0, 0, 128786, 4283, 129689, 0, - 68361, 0, 74826, 0, 0, 0, 0, 127954, 65106, 42761, 121516, 4581, 8411, 0, - 0, 72259, 0, 93037, 0, 0, 0, 92452, 4392, 0, 10786, 69661, 0, 8184, 0, 0, - 7396, 0, 0, 69788, 0, 43512, 7965, 111039, 111038, 111037, 111036, 41350, - 0, 0, 0, 2294, 64501, 68034, 0, 68405, 111034, 0, 0, 111030, 111029, - 71105, 111027, 0, 111033, 92200, 111031, 0, 6764, 0, 0, 111026, 111025, - 72454, 65203, 128010, 0, 0, 0, 3210, 0, 129978, 0, 0, 82958, 127970, - 82957, 0, 68875, 10043, 71979, 1186, 41571, 0, 5209, 9464, 82960, 66657, - 5207, 65062, 5213, 0, 0, 41348, 41568, 128803, 3253, 111045, 111044, - 74067, 111042, 111049, 5596, 111047, 111046, 0, 64887, 0, 5217, 111041, - 72252, 0, 0, 0, 0, 2635, 92760, 0, 0, 0, 92742, 0, 113672, 0, 0, 0, 2258, - 67081, 0, 67083, 0, 0, 0, 5784, 0, 0, 0, 0, 4011, 0, 0, 0, 0, 4254, 0, - 111054, 5600, 111052, 111051, 10447, 5598, 1207, 111055, 0, 3501, 42582, - 0, 111050, 0, 1124, 5597, 983501, 78908, 9321, 129464, 75040, 983498, 0, - 1719, 68356, 68354, 9671, 1125, 2721, 0, 129876, 983504, 7631, 5488, - 111082, 0, 0, 5491, 111086, 8937, 0, 3236, 74187, 5490, 0, 5489, 8522, - 68358, 111069, 6300, 111067, 111066, 0, 0, 111071, 111070, 0, 9875, 7593, - 111065, 0, 0, 43182, 0, 68379, 3311, 111058, 111057, 3746, 11016, 65752, - 111061, 0, 43423, 68775, 0, 111056, 72225, 0, 0, 127120, 0, 2232, 0, 0, - 0, 0, 0, 126555, 0, 0, 8656, 0, 128358, 0, 0, 983490, 983491, 917563, - 983489, 983486, 983487, 0, 0, 0, 129669, 0, 111183, 128043, 983495, 1036, - 983493, 111075, 1723, 111073, 111072, 111079, 41579, 111077, 111076, - 10705, 0, 983485, 74486, 71693, 740, 983481, 983482, 129645, 0, 0, 74846, - 92255, 0, 0, 0, 0, 0, 10438, 74487, 73798, 13285, 0, 0, 0, 5690, 0, - 93992, 0, 0, 13095, 0, 127857, 121419, 7321, 121203, 13254, 70176, 75070, - 0, 0, 0, 0, 127845, 3247, 317, 0, 0, 0, 0, 917543, 0, 10173, 0, 0, 0, 0, - 0, 5223, 0, 0, 119564, 5226, 0, 94044, 5880, 94065, 7758, 0, 0, 5224, - 5487, 94041, 5692, 41725, 983467, 0, 5695, 41711, 0, 43171, 0, 94049, - 5691, 983472, 866, 1488, 983471, 983457, 65665, 94036, 983456, 74797, 0, - 0, 11039, 983465, 11145, 71211, 983464, 983461, 983462, 983459, 983460, - 42492, 43402, 125208, 3302, 0, 72842, 43153, 0, 0, 120885, 121300, 0, - 7856, 8690, 0, 73076, 110880, 0, 0, 73091, 0, 69925, 120635, 65153, 0, 0, - 0, 0, 0, 0, 4540, 0, 0, 0, 0, 11844, 121209, 8863, 0, 75061, 71978, 6389, - 0, 42371, 83205, 8790, 120911, 0, 111125, 71168, 8869, 0, 0, 42060, 0, - 9648, 111123, 71170, 10270, 10286, 10318, 10382, 43529, 0, 0, 0, 0, 0, - 70110, 43835, 119520, 70111, 119360, 118815, 127084, 127083, 8767, 0, - 128437, 41281, 0, 5201, 0, 6215, 67072, 6214, 13101, 0, 0, 65268, 67073, - 0, 0, 127976, 72995, 127073, 10511, 42075, 0, 73475, 129509, 0, 67115, - 127069, 111293, 127068, 0, 127067, 0, 74845, 0, 42071, 43156, 0, 0, 0, 0, - 7954, 0, 0, 0, 8485, 4671, 0, 69513, 4740, 0, 0, 42618, 78294, 3064, - 6212, 0, 0, 0, 9554, 0, 83044, 0, 126598, 0, 78291, 6159, 6213, 12885, 0, - 129086, 64720, 0, 983926, 0, 0, 0, 11430, 0, 7518, 9317, 0, 3729, 10406, - 0, 119259, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73825, 0, 0, 129599, 8786, 10390, - 0, 0, 917601, 93034, 0, 7924, 0, 43307, 0, 0, 0, 0, 0, 0, 118843, 9623, - 435, 0, 0, 12893, 8093, 9079, 0, 0, 0, 0, 0, 64430, 0, 10294, 10326, 0, - 0, 0, 0, 0, 0, 3623, 125188, 83378, 0, 43197, 0, 111149, 0, 78296, 0, 0, - 0, 7914, 0, 69749, 0, 2624, 0, 0, 0, 120859, 67110, 11058, 0, 67107, 0, - 0, 0, 0, 120793, 0, 0, 6717, 10619, 0, 0, 0, 11832, 128664, 0, 0, 0, - 70202, 0, 0, 0, 3232, 73824, 74581, 0, 0, 0, 41889, 0, 0, 1161, 41895, - 74103, 9701, 0, 0, 129385, 73819, 120588, 5012, 0, 41362, 0, 68507, 0, 0, - 0, 0, 0, 41364, 0, 0, 41352, 41361, 0, 41366, 0, 70129, 129065, 917, 0, - 119934, 119923, 92421, 119912, 0, 119924, 64841, 118582, 71482, 0, 0, 0, - 125136, 128583, 0, 7022, 0, 4739, 0, 5802, 9816, 8615, 0, 0, 491, 65837, - 0, 0, 128644, 0, 8426, 11092, 9891, 0, 0, 0, 41881, 118823, 3736, 7394, - 42648, 0, 68448, 9095, 7741, 12684, 41885, 0, 0, 0, 0, 5815, 0, 0, 0, - 127392, 0, 0, 41878, 0, 0, 0, 0, 0, 0, 0, 0, 119503, 0, 120804, 0, 0, - 2267, 0, 78289, 78359, 78288, 0, 0, 78318, 65920, 0, 194819, 7057, 9408, - 9409, 9410, 9411, 9412, 9413, 9414, 9415, 9416, 9417, 9418, 9419, 9420, - 9421, 5897, 9423, 917933, 127107, 0, 127108, 917937, 127963, 8955, 9399, - 9400, 9401, 9402, 9403, 9404, 9405, 9406, 9407, 0, 128626, 42669, 73832, - 78261, 67683, 2631, 119308, 78259, 0, 78260, 3996, 0, 119307, 0, 0, 0, 0, - 0, 0, 64825, 917916, 917913, 917914, 917919, 5899, 917917, 129990, 12085, - 0, 574, 69734, 77825, 73828, 9473, 77824, 118918, 73900, 41735, 42211, 0, - 4190, 77834, 77835, 77830, 77833, 3616, 77828, 77837, 77838, 7708, 77836, - 2228, 113765, 0, 0, 4191, 42968, 77844, 73800, 77842, 77843, 77839, - 77840, 0, 78311, 83375, 0, 0, 10415, 74102, 0, 5896, 0, 10351, 67151, 0, - 73829, 0, 127159, 0, 73998, 41355, 42883, 70736, 71212, 8021, 0, 119150, - 983732, 41357, 8011, 42885, 42887, 41354, 0, 0, 10026, 5472, 120554, - 1191, 101217, 5470, 128784, 5476, 101216, 0, 0, 0, 42874, 78281, 42876, - 6304, 78283, 0, 2675, 120690, 0, 0, 128954, 0, 0, 5478, 5904, 0, 0, 0, - 7291, 77848, 43761, 13067, 0, 0, 119271, 120360, 69731, 77856, 77857, - 77854, 77855, 77852, 77853, 77850, 10750, 43714, 77858, 0, 0, 0, 12887, - 120364, 127745, 77866, 77867, 77864, 77865, 9929, 5199, 77859, 1120, 0, - 0, 0, 9486, 7554, 0, 77868, 72832, 0, 0, 5894, 70069, 0, 0, 92511, 70358, - 1323, 13162, 120937, 0, 0, 0, 77881, 66022, 0, 72857, 0, 0, 0, 0, 0, - 1142, 0, 8271, 0, 0, 126645, 12903, 43622, 4002, 0, 10442, 10676, 120368, - 0, 120369, 0, 0, 0, 0, 66642, 1277, 0, 7871, 0, 0, 78853, 0, 119015, 0, - 0, 11784, 0, 78012, 4700, 0, 78858, 0, 78855, 0, 0, 92400, 77879, 19932, - 77876, 77877, 74804, 77874, 77869, 77871, 0, 71487, 43118, 0, 0, 6774, - 6773, 0, 194684, 10346, 10410, 78860, 118974, 0, 101197, 6108, 0, 110612, - 0, 0, 5901, 121309, 74166, 124973, 0, 0, 0, 69407, 0, 70357, 0, 0, 74217, - 0, 64698, 4192, 9289, 0, 0, 128847, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11603, 0, - 0, 101166, 82976, 0, 0, 67812, 0, 101163, 0, 42572, 0, 128300, 119146, - 1963, 11622, 0, 43237, 82981, 7550, 67100, 5903, 82984, 78009, 129750, - 9662, 0, 128391, 0, 0, 0, 0, 11013, 0, 0, 0, 128433, 67090, 0, 0, 0, 0, - 0, 11568, 983704, 43367, 0, 0, 7852, 119496, 0, 0, 0, 0, 194676, 0, - 194675, 0, 0, 416, 129668, 0, 73834, 0, 68921, 10984, 0, 0, 101175, - 129838, 101182, 0, 127013, 92423, 0, 983261, 121199, 0, 0, 12540, 0, - 983220, 0, 0, 11445, 101168, 2112, 0, 0, 0, 1021, 0, 9507, 10210, 78005, - 8023, 93963, 78006, 78001, 43181, 78003, 9532, 119094, 0, 0, 0, 0, 0, - 1885, 43268, 129802, 129798, 120542, 121153, 392, 7894, 4391, 129810, - 8221, 119597, 77999, 77998, 0, 0, 0, 92967, 0, 3558, 0, 3913, 70429, - 121376, 0, 0, 1265, 0, 6309, 0, 12969, 0, 101151, 0, 101146, 0, 101139, - 0, 41864, 0, 0, 74294, 0, 167, 0, 917584, 0, 93983, 72354, 68477, 0, 0, - 917594, 0, 2493, 129827, 0, 129804, 0, 917570, 917593, 0, 0, 406, 917592, - 0, 0, 0, 0, 0, 0, 0, 127161, 0, 128597, 0, 0, 0, 3421, 10561, 0, 8365, - 917581, 0, 127569, 120787, 128669, 0, 0, 0, 0, 7834, 0, 0, 101154, 10298, - 6624, 4908, 0, 1639, 120842, 0, 0, 6327, 6724, 0, 0, 0, 69910, 4817, 0, - 0, 0, 68059, 0, 11022, 0, 0, 0, 118888, 0, 0, 7548, 64794, 0, 12291, - 983166, 0, 0, 0, 0, 0, 0, 1134, 1838, 0, 2057, 0, 0, 0, 0, 0, 0, 5206, 0, - 0, 42523, 0, 0, 0, 0, 65550, 8570, 4816, 0, 127926, 0, 4821, 0, 0, 0, - 4818, 125257, 119974, 119977, 0, 0, 119970, 119973, 0, 119983, 119982, - 67470, 119984, 119979, 119978, 0, 119980, 119670, 129297, 0, 11284, - 119987, 70097, 65155, 119988, 0, 9363, 0, 0, 0, 5900, 93990, 7889, 2722, - 128770, 0, 0, 0, 0, 2282, 0, 0, 0, 68093, 0, 0, 0, 0, 0, 70150, 118628, - 0, 0, 0, 129651, 70146, 983079, 119967, 71330, 70148, 0, 0, 94006, 70144, - 119964, 110677, 110678, 110675, 110676, 0, 110674, 4226, 0, 123165, 5732, - 71327, 0, 0, 65119, 0, 0, 92971, 64770, 0, 0, 6093, 0, 0, 1395, 0, 0, 0, - 121179, 786, 0, 43174, 64340, 0, 125269, 0, 983662, 125138, 10132, 0, 0, - 0, 0, 0, 93956, 0, 68444, 0, 92437, 123143, 0, 0, 92656, 0, 0, 0, 1399, - 121463, 0, 121465, 121464, 120808, 241, 121469, 4907, 0, 0, 0, 0, 0, 0, - 0, 0, 127904, 0, 0, 42780, 0, 0, 0, 4217, 0, 0, 0, 0, 72158, 0, 0, 43099, - 3965, 0, 0, 0, 13300, 0, 0, 43057, 0, 0, 0, 0, 0, 65372, 0, 6410, 126073, - 125252, 70468, 0, 0, 0, 119558, 0, 0, 0, 0, 0, 0, 43188, 2626, 7762, 0, - 0, 0, 127183, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67726, 0, 126993, 1542, 0, 0, - 92550, 0, 0, 74311, 0, 0, 10181, 2150, 0, 0, 0, 0, 124921, 68053, 6029, - 72852, 0, 0, 0, 0, 8993, 0, 0, 0, 93968, 606, 118664, 0, 0, 0, 4311, 0, - 6027, 126615, 4322, 0, 65207, 0, 2184, 983920, 0, 0, 2735, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 70806, 0, 73547, 0, 92783, 92844, 0, 65817, 55288, - 127934, 66564, 8530, 0, 7709, 0, 121202, 66560, 128528, 917595, 12876, - 66561, 0, 121430, 983957, 7789, 5855, 809, 0, 0, 72853, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 64386, 0, 74909, 64845, 120607, 66416, 83360, 6532, 0, 0, - 0, 0, 128224, 0, 0, 0, 0, 43091, 92287, 0, 0, 129312, 0, 0, 0, 11361, 0, - 0, 8153, 128105, 0, 10741, 0, 0, 0, 0, 0, 64706, 917922, 0, 69505, 78870, - 9466, 78866, 9824, 0, 0, 0, 120977, 915, 0, 0, 43865, 0, 0, 0, 67131, - 70096, 67137, 0, 129614, 73648, 6730, 78862, 68161, 0, 78861, 126542, 0, - 0, 94010, 118655, 0, 0, 66043, 0, 0, 43107, 0, 0, 92343, 0, 73879, 0, 0, - 0, 6103, 0, 0, 92470, 0, 12889, 0, 127137, 0, 0, 0, 0, 0, 0, 119262, - 83028, 0, 0, 0, 69279, 0, 0, 0, 13118, 7700, 917537, 9690, 0, 0, 68080, - 512, 0, 72792, 0, 0, 77892, 632, 77890, 77891, 42529, 0, 0, 0, 0, 0, 0, - 0, 128273, 0, 0, 7379, 64581, 5386, 0, 0, 10633, 72316, 64488, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 124956, 71307, 0, 0, 0, 0, 0, 92370, 0, 0, 0, 0, 0, - 71314, 1801, 0, 0, 120867, 0, 0, 77888, 2085, 702, 77887, 77884, 77885, - 13074, 77883, 66299, 0, 0, 12106, 78905, 0, 1755, 0, 77897, 77898, 1163, - 3102, 77893, 77894, 0, 0, 0, 0, 69227, 0, 77901, 77902, 77899, 77900, - 65171, 0, 0, 0, 70157, 0, 0, 0, 64846, 2908, 0, 11177, 64902, 64950, 0, - 128740, 66906, 124959, 70499, 0, 0, 0, 64352, 0, 125031, 1007, 0, 9199, - 0, 127371, 118992, 41890, 0, 2730, 119072, 0, 5428, 0, 73771, 129993, 0, - 0, 0, 71458, 0, 0, 0, 68089, 0, 44012, 0, 71456, 0, 9158, 66878, 69905, - 92440, 0, 101272, 0, 484, 0, 0, 0, 194742, 0, 0, 0, 0, 572, 7041, 2736, - 0, 0, 93962, 0, 68628, 0, 128727, 5438, 5222, 5381, 43114, 0, 5193, 5125, - 5456, 5509, 0, 120664, 113700, 0, 0, 0, 3430, 0, 42905, 0, 74929, 6050, - 0, 0, 129197, 0, 0, 10908, 0, 0, 127809, 64617, 0, 0, 3957, 0, 0, 0, 674, - 0, 0, 2946, 5354, 5251, 5328, 5307, 3759, 72318, 8364, 5123, 0, 5281, - 5469, 5121, 0, 0, 0, 5130, 0, 129608, 0, 0, 0, 1221, 2733, 0, 0, 0, - 72321, 127245, 0, 0, 0, 101277, 0, 5939, 0, 0, 0, 71867, 68400, 128216, - 10321, 10289, 0, 10385, 123164, 0, 0, 0, 0, 118943, 0, 11411, 0, 5938, 0, - 120865, 0, 0, 10401, 10337, 0, 0, 0, 0, 0, 0, 0, 71942, 0, 0, 12165, 0, - 0, 9885, 0, 8077, 0, 127908, 0, 0, 0, 0, 129138, 4220, 10725, 10433, 0, - 68395, 4987, 64519, 0, 0, 0, 123626, 120356, 0, 11733, 0, 120792, 0, - 127233, 0, 0, 0, 92345, 68254, 983661, 77991, 0, 2724, 0, 0, 12313, - 110619, 515, 119947, 119944, 119945, 119942, 119943, 119940, 119941, - 119938, 8606, 4046, 4589, 4521, 0, 9141, 0, 0, 2741, 0, 0, 1370, 0, 0, 0, - 0, 0, 0, 66880, 0, 66003, 0, 64440, 0, 129943, 69458, 0, 11593, 68669, - 68666, 68660, 0, 0, 2744, 72285, 68638, 0, 814, 0, 119962, 119963, - 119960, 119961, 101106, 43029, 119956, 11623, 119954, 11955, 119952, - 119953, 41986, 119951, 0, 120497, 4847, 110975, 0, 0, 0, 0, 1581, 64920, - 93830, 12954, 963, 110973, 110972, 110971, 110969, 5278, 110967, 68621, - 92222, 983454, 68625, 983452, 68617, 110960, 0, 101459, 101487, 110964, - 110963, 110962, 0, 0, 101464, 101483, 101463, 983443, 983440, 92648, - 127379, 0, 65137, 6483, 65392, 0, 4213, 129649, 41303, 0, 0, 0, 41306, - 129751, 2698, 0, 0, 0, 68396, 0, 41304, 824, 0, 78011, 72315, 78894, - 74827, 78892, 64804, 9820, 119820, 110985, 110976, 0, 6739, 0, 5481, - 3490, 110978, 110977, 71706, 69947, 67702, 9124, 12688, 119833, 101496, - 0, 101495, 119821, 119824, 67480, 42575, 101474, 101478, 119827, 101481, - 101476, 71087, 68658, 119946, 8025, 68630, 101490, 68675, 92445, 71097, - 69613, 0, 0, 0, 0, 983435, 2745, 11797, 110990, 983431, 9202, 983429, - 983430, 0, 0, 0, 10525, 5436, 74584, 110987, 110986, 121506, 43080, - 121508, 121507, 983420, 6246, 119958, 10921, 9723, 6777, 6776, 6775, 0, - 0, 70287, 92384, 0, 8669, 0, 0, 65093, 0, 78881, 2716, 0, 0, 11252, - 101475, 68369, 0, 11060, 12985, 2711, 78872, 78027, 78026, 7992, 0, 0, - 42938, 78033, 78032, 78877, 70724, 78029, 78028, 78031, 78030, 64535, - 110998, 10130, 110996, 0, 0, 111001, 111000, 127914, 983417, 78014, 5713, - 110995, 7570, 110993, 110992, 0, 11190, 129700, 9026, 0, 74864, 7547, - 78891, 0, 10008, 10222, 0, 129543, 9744, 0, 68809, 983413, 119656, - 983411, 94070, 983409, 983410, 983407, 9045, 78888, 4225, 78886, 78887, - 68757, 78885, 78882, 78883, 983402, 983403, 8405, 983401, 10423, 10359, - 983396, 983397, 0, 129149, 4215, 9789, 0, 4321, 12309, 983405, 41313, 0, - 5368, 66886, 0, 0, 5366, 0, 5372, 101482, 67512, 0, 7720, 7390, 2696, 0, - 0, 8268, 0, 1790, 0, 0, 118977, 0, 0, 0, 5376, 1835, 72313, 78704, - 128089, 0, 0, 68655, 1180, 0, 0, 0, 0, 119274, 0, 0, 9122, 118584, 11928, - 0, 65283, 0, 101449, 5971, 101448, 43500, 1268, 65097, 983222, 0, 101445, - 0, 1427, 128440, 0, 5970, 3431, 72299, 101439, 101435, 983389, 983390, - 983387, 2738, 125066, 10455, 0, 74026, 0, 4222, 6240, 0, 119013, 983394, - 68377, 6248, 983378, 67815, 983376, 917907, 92582, 0, 101453, 125215, 0, - 2728, 65549, 64563, 101428, 101425, 101429, 128145, 0, 10713, 7166, - 119559, 2622, 101450, 0, 0, 0, 8954, 0, 94008, 2632, 42617, 10108, 1011, - 42852, 12080, 2709, 0, 5716, 0, 0, 0, 0, 127100, 69378, 0, 9515, 127098, - 66465, 6451, 0, 127097, 8918, 983556, 0, 0, 19950, 0, 0, 0, 44003, 0, - 64735, 0, 0, 0, 0, 983500, 74022, 0, 128795, 68643, 67410, 0, 5721, 0, 0, - 0, 121074, 11267, 983369, 66464, 5720, 983368, 0, 4219, 5718, 8696, 5717, - 122651, 983375, 983897, 983373, 541, 983371, 983372, 119948, 119089, - 68389, 983357, 119949, 56, 4216, 10577, 0, 0, 77849, 69620, 983362, - 983363, 66899, 983361, 0, 0, 67628, 0, 0, 7086, 0, 67998, 67621, 0, 2734, - 69616, 0, 67627, 118937, 0, 67625, 0, 0, 0, 42593, 0, 128217, 0, 0, - 119939, 0, 68180, 0, 0, 71104, 7442, 43665, 359, 41253, 68392, 6239, - 120599, 41256, 0, 67740, 111023, 111022, 111021, 9346, 69660, 41254, 0, - 43291, 78002, 0, 67491, 124993, 93841, 0, 0, 0, 4368, 983505, 0, 68137, - 0, 0, 41024, 0, 0, 121359, 121420, 0, 0, 0, 4223, 0, 8574, 83502, 0, 0, - 0, 118576, 0, 92718, 983636, 70432, 128323, 68382, 0, 0, 0, 0, 0, 4144, - 0, 83193, 6245, 0, 2732, 92644, 0, 0, 64558, 83501, 0, 0, 0, 128005, 0, - 0, 129652, 983149, 3097, 0, 0, 77996, 0, 0, 10863, 111020, 111019, - 111018, 0, 111015, 111014, 111013, 111012, 118964, 0, 10216, 64293, 0, 0, - 69393, 128331, 12325, 111010, 8717, 111008, 101413, 0, 101380, 0, 8700, - 0, 101382, 68363, 10426, 0, 71091, 10362, 0, 1715, 101378, 0, 64918, - 101409, 43278, 42635, 0, 0, 65275, 0, 0, 101319, 0, 69746, 1607, 466, - 118949, 0, 0, 127918, 6243, 983901, 1350, 74195, 64420, 1993, 5362, - 10666, 2708, 92471, 0, 13143, 234, 3199, 0, 41268, 6334, 2173, 0, 0, - 73750, 0, 73762, 10458, 0, 8576, 127136, 0, 2704, 64953, 0, 64832, 8322, - 0, 3132, 0, 2694, 0, 0, 2439, 65104, 69804, 0, 303, 74625, 92622, 0, - 2437, 0, 9817, 4844, 0, 0, 0, 0, 0, 121120, 43292, 0, 2441, 0, 0, 0, 0, - 0, 2451, 2714, 0, 0, 43379, 127984, 74541, 753, 5849, 0, 43089, 0, 0, - 119534, 72380, 0, 0, 0, 2726, 3107, 0, 0, 64937, 0, 78841, 1408, 0, 4607, - 101299, 181, 0, 67728, 9539, 0, 0, 65201, 121121, 92973, 64185, 4142, - 64183, 0, 0, 0, 9706, 64178, 64177, 64176, 0, 64182, 64181, 64180, 64179, - 11401, 125124, 0, 1822, 0, 128581, 68055, 3865, 122918, 0, 10500, 129602, - 119024, 0, 110732, 9830, 0, 0, 0, 65131, 0, 0, 0, 0, 74608, 7038, 0, - 9599, 8748, 0, 0, 9557, 0, 0, 0, 11494, 0, 0, 10865, 0, 43279, 64186, - 68521, 0, 64191, 64190, 8898, 64188, 129153, 41030, 78836, 0, 0, 78820, - 126100, 0, 78805, 78806, 78801, 78802, 6745, 78800, 0, 0, 0, 110866, 0, - 0, 73679, 67838, 41039, 78809, 128162, 0, 129893, 0, 110869, 127045, - 110867, 110868, 127039, 4400, 0, 64207, 10275, 8925, 10371, 10307, 64202, - 4248, 0, 72802, 4541, 6299, 64204, 64203, 64201, 64200, 64199, 64198, - 126471, 0, 0, 0, 64193, 64192, 0, 9943, 64197, 64196, 64195, 64194, - 13282, 42652, 64174, 64173, 83495, 846, 72337, 9965, 74495, 72330, 83493, - 83494, 2543, 12163, 64170, 83490, 64167, 64166, 64165, 64164, 72333, 0, - 64169, 64168, 64949, 0, 10251, 10247, 64163, 64162, 2295, 43299, 43301, - 129363, 0, 70791, 0, 0, 550, 9910, 0, 0, 66579, 0, 0, 0, 9504, 0, 0, - 10373, 0, 0, 10261, 10253, 7821, 10277, 0, 74823, 1552, 0, 0, 129389, 0, - 121435, 19910, 0, 0, 118849, 121150, 0, 43985, 68051, 0, 69890, 121329, - 78355, 983776, 0, 66405, 2431, 3744, 66852, 1809, 0, 0, 0, 73759, 1264, - 0, 78676, 11697, 121278, 9785, 64716, 0, 0, 0, 0, 121307, 0, 0, 42609, - 128388, 0, 66912, 127016, 0, 983904, 74229, 118590, 6487, 93798, 70743, - 0, 0, 0, 83484, 83485, 83486, 83487, 83480, 8355, 7854, 83483, 954, - 64927, 0, 41045, 0, 41438, 0, 0, 10711, 0, 0, 0, 0, 64774, 13309, 10947, - 66727, 101426, 0, 0, 66795, 0, 0, 0, 0, 0, 0, 0, 120634, 69228, 0, 0, 0, - 0, 101430, 0, 3060, 83478, 9986, 0, 83473, 83474, 11698, 77880, 83469, - 9916, 11701, 83472, 42586, 0, 8320, 0, 119095, 0, 0, 1477, 43289, 0, - 74358, 10884, 69446, 9908, 0, 0, 0, 3414, 74304, 0, 0, 0, 0, 2110, 0, - 68306, 0, 74532, 0, 129865, 0, 0, 7164, 0, 0, 0, 11950, 5392, 42248, - 65129, 68656, 5397, 129579, 0, 68136, 0, 0, 5395, 72870, 5393, 354, - 68615, 0, 0, 0, 0, 0, 126236, 0, 0, 626, 0, 5895, 0, 0, 5780, 0, 66407, - 10220, 0, 71121, 43297, 0, 0, 11468, 64436, 0, 0, 0, 73818, 3918, 0, - 3797, 72786, 122961, 0, 4140, 0, 71254, 0, 9030, 813, 0, 68131, 4146, - 119957, 5360, 0, 129498, 0, 0, 6249, 0, 0, 0, 0, 0, 73092, 0, 4911, 988, - 0, 73125, 0, 42948, 0, 0, 0, 0, 74972, 0, 0, 0, 9825, 0, 0, 12803, - 126977, 11032, 67654, 6244, 0, 0, 68662, 0, 129351, 0, 72131, 4169, 0, 0, - 0, 129986, 121410, 120657, 0, 0, 68657, 128943, 78496, 0, 0, 5898, 74540, - 0, 41856, 93056, 194926, 118538, 127373, 83424, 83425, 83426, 73736, - 83420, 68870, 6448, 6835, 0, 4831, 83418, 83419, 67731, 0, 0, 0, 0, 0, 0, - 0, 78499, 0, 0, 0, 43288, 122931, 0, 0, 0, 0, 43418, 0, 0, 0, 7876, - 68132, 917872, 0, 917870, 43378, 0, 0, 120890, 5892, 43605, 0, 0, 0, - 129058, 0, 0, 6251, 83409, 83410, 83411, 83412, 126512, 0, 71092, 83408, - 10114, 0, 0, 5387, 0, 0, 0, 0, 65553, 78346, 1747, 917849, 65109, 69240, - 917852, 126509, 0, 0, 0, 0, 125065, 0, 9850, 0, 367, 1472, 917859, 6687, - 0, 0, 5905, 12339, 8919, 73953, 65680, 0, 2204, 78664, 0, 9134, 118589, - 78666, 43011, 0, 126626, 0, 0, 0, 43013, 10614, 0, 0, 83413, 66646, - 83415, 83416, 0, 73881, 43012, 121127, 83293, 54, 43009, 73885, 0, 6211, - 0, 0, 83295, 68119, 43008, 10758, 0, 0, 0, 0, 0, 70018, 0, 0, 0, 0, - 12765, 0, 0, 0, 0, 126580, 0, 0, 43657, 0, 0, 0, 983737, 0, 83405, - 917843, 0, 0, 83401, 83402, 83403, 83404, 83397, 11363, 12057, 83400, - 1567, 0, 0, 83396, 0, 8957, 4139, 0, 0, 129336, 0, 0, 12740, 0, 92195, - 12761, 127793, 12759, 0, 72304, 67169, 83467, 44002, 0, 83462, 83463, - 83464, 12755, 12762, 41022, 67690, 64217, 476, 0, 983734, 0, 64212, - 41020, 1382, 64209, 64216, 64215, 64214, 64213, 0, 0, 0, 67584, 8720, - 3908, 0, 0, 0, 0, 101529, 129576, 0, 0, 3849, 92324, 94026, 9778, 917906, - 5891, 917912, 55, 917910, 917911, 0, 0, 7935, 67586, 0, 1114, 92599, - 67585, 78675, 0, 83447, 83449, 0, 0, 0, 64717, 0, 0, 0, 66884, 6292, - 65303, 0, 6452, 917886, 917887, 66249, 917885, 917890, 917891, 917888, - 719, 101446, 0, 917892, 0, 0, 0, 94083, 10868, 121333, 2349, 5902, - 917896, 6335, 101350, 917899, 917900, 0, 64369, 0, 0, 0, 69245, 0, - 126564, 0, 0, 128565, 0, 0, 0, 0, 0, 6454, 1229, 83457, 83458, 83450, - 83451, 83452, 65100, 120508, 8224, 917873, 917874, 917879, 917880, - 917877, 917878, 128929, 0, 917881, 917882, 5365, 67836, 8901, 0, 0, - 129951, 0, 69257, 5925, 83436, 64330, 128400, 83431, 83432, 83433, 83434, - 83427, 83428, 83429, 83430, 64928, 10543, 0, 0, 83446, 414, 0, 0, 83442, - 6456, 71490, 83445, 11905, 83439, 66284, 83441, 0, 68337, 0, 83437, - 43832, 983140, 9751, 0, 128085, 11770, 0, 0, 69600, 65061, 0, 0, 0, 0, 0, - 0, 121087, 0, 0, 69924, 0, 0, 0, 69913, 0, 121387, 101513, 101504, - 101512, 42038, 387, 0, 12737, 0, 0, 43368, 0, 0, 0, 0, 129713, 129449, - 121295, 0, 69400, 127309, 0, 375, 0, 0, 0, 983905, 0, 0, 119202, 119203, - 124117, 43120, 0, 0, 119196, 119197, 0, 4529, 119200, 119201, 119198, - 119199, 0, 0, 69698, 13150, 64492, 0, 0, 0, 0, 0, 42891, 66327, 74298, 0, - 0, 0, 2587, 42193, 0, 6455, 0, 4241, 0, 0, 0, 0, 0, 0, 0, 118821, 0, 0, - 0, 125030, 0, 128684, 129390, 6988, 5373, 0, 0, 119232, 10015, 0, 0, 0, - 68642, 0, 120855, 42040, 128827, 5779, 129841, 42037, 83282, 0, 0, 93040, - 83283, 101116, 0, 101117, 6983, 0, 0, 101115, 0, 0, 0, 127323, 101111, 0, - 119588, 0, 92495, 74558, 0, 68138, 70163, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 11144, 73484, 2551, 73482, 6453, 0, 6235, 0, 0, 129081, 72886, 44020, - 11826, 0, 7780, 5369, 118958, 0, 0, 5367, 66870, 0, 0, 5377, 0, 68143, - 128624, 78245, 5218, 0, 127333, 0, 0, 129717, 0, 0, 1300, 0, 127334, - 64505, 0, 0, 119624, 1465, 0, 127316, 0, 0, 0, 101109, 0, 113694, 10729, - 0, 0, 8839, 119243, 0, 7785, 126530, 0, 0, 0, 0, 118638, 0, 0, 0, 3897, - 0, 92331, 74417, 113704, 0, 68127, 71425, 70688, 0, 0, 0, 0, 69287, 3542, - 0, 120685, 7951, 68152, 118857, 0, 92972, 0, 0, 127311, 73683, 0, 65150, - 68031, 0, 0, 0, 0, 9985, 0, 127328, 0, 0, 0, 0, 10830, 0, 615, 64490, - 7574, 0, 0, 0, 12909, 73698, 64559, 127332, 73951, 0, 67996, 2020, 0, 0, - 0, 120701, 0, 983640, 0, 0, 0, 92991, 0, 0, 9070, 0, 68411, 11281, 42829, - 0, 1033, 0, 78918, 0, 118610, 0, 65226, 0, 0, 0, 0, 0, 3450, 0, 7397, 0, - 0, 42778, 10000, 41088, 449, 0, 0, 68458, 113725, 0, 0, 10738, 69634, 0, - 0, 41085, 0, 0, 0, 12764, 0, 93058, 3596, 7322, 0, 0, 0, 0, 0, 0, 0, 0, - 2092, 0, 0, 0, 121350, 10820, 0, 0, 126567, 1853, 0, 0, 93014, 0, 12770, - 0, 0, 124997, 0, 0, 0, 0, 0, 129053, 4828, 1258, 0, 2006, 0, 0, 74285, - 127987, 0, 120683, 122880, 983900, 983903, 8846, 128255, 0, 128091, 2650, - 9182, 1961, 121399, 11525, 0, 1959, 0, 55228, 11774, 41016, 0, 0, 128054, - 41017, 13109, 0, 10519, 66331, 3454, 19930, 0, 41019, 92894, 0, 0, 78362, - 41021, 101566, 0, 0, 0, 0, 65531, 0, 0, 0, 0, 0, 0, 8865, 6402, 113827, - 77923, 0, 101536, 0, 7733, 0, 4998, 68493, 0, 78930, 0, 4268, 101368, 0, - 0, 101555, 101579, 10881, 0, 0, 0, 0, 2014, 0, 71901, 0, 0, 195057, 0, 0, - 78357, 65281, 0, 0, 0, 0, 0, 2015, 0, 0, 71840, 66318, 74824, 101575, 0, - 101574, 101569, 0, 70061, 8094, 10135, 101551, 0, 794, 0, 0, 66335, 0, - 121303, 4343, 0, 4833, 0, 0, 0, 0, 189, 12611, 0, 72215, 0, 4838, 126214, - 4834, 65078, 2183, 126104, 4837, 118853, 0, 121230, 4832, 128271, 0, - 101584, 127838, 0, 0, 0, 0, 0, 118697, 0, 3976, 118995, 128937, 0, 0, 0, - 0, 0, 119010, 0, 121015, 0, 0, 0, 0, 2871, 0, 0, 999, 0, 68177, 0, 0, - 2017, 0, 67824, 0, 0, 0, 0, 0, 0, 4775, 12555, 12571, 12550, 12583, - 12560, 2019, 12556, 12584, 12586, 0, 12562, 12561, 12566, 12569, 12554, - 0, 83344, 0, 68882, 0, 12567, 1402, 0, 0, 83348, 125072, 83347, 0, 83346, - 0, 0, 0, 0, 64391, 0, 83341, 69602, 0, 1999, 0, 128141, 0, 0, 0, 0, 0, 0, - 0, 68873, 0, 0, 66913, 2377, 101090, 0, 12572, 11318, 12557, 12559, 9192, - 12549, 12568, 2373, 9446, 9447, 9448, 9449, 0, 9480, 481, 0, 9438, 9439, - 9440, 9441, 9442, 9443, 9444, 9445, 9430, 9431, 9432, 9433, 9434, 9435, - 9436, 9437, 983097, 0, 9424, 9425, 9426, 9427, 9428, 7481, 0, 2362, 9655, - 0, 2004, 0, 9782, 0, 0, 0, 0, 0, 0, 0, 1108, 0, 92461, 0, 128764, 0, - 64781, 0, 0, 0, 121126, 0, 1392, 0, 0, 917557, 0, 8065, 42994, 128739, 0, - 0, 0, 121068, 92418, 0, 0, 0, 43280, 0, 70718, 1812, 0, 73046, 0, 0, 0, - 0, 0, 6054, 10697, 3169, 0, 0, 70720, 11487, 70712, 0, 0, 0, 194716, 0, - 0, 41863, 0, 0, 2304, 0, 92326, 0, 42951, 0, 0, 64760, 11766, 0, 0, 0, 0, - 69236, 119171, 0, 8773, 10733, 36, 0, 0, 0, 0, 0, 11074, 0, 64910, - 983131, 2009, 0, 0, 128036, 68114, 128906, 0, 0, 0, 983998, 12852, 3031, - 0, 0, 129088, 0, 66414, 0, 0, 119950, 42613, 65933, 366, 0, 9892, 0, - 11754, 101107, 83329, 65301, 44013, 83058, 67245, 10102, 0, 7739, 41026, - 0, 0, 0, 0, 0, 0, 0, 0, 78386, 129475, 71868, 113811, 13081, 10923, - 129330, 0, 68145, 0, 65861, 74083, 0, 0, 128392, 83063, 83065, 0, 70706, - 0, 0, 0, 70168, 66586, 4183, 64967, 66250, 0, 92547, 0, 0, 113685, 0, - 3792, 2011, 0, 0, 77748, 83332, 77749, 120595, 0, 68489, 41023, 77747, 0, - 11659, 7922, 12614, 2005, 8523, 129880, 0, 7513, 1863, 129436, 83337, - 128969, 0, 120274, 120033, 0, 8144, 0, 73031, 77767, 127524, 120270, - 42241, 8783, 77764, 77765, 77766, 77760, 77761, 77762, 77763, 0, 10680, - 0, 43293, 68771, 0, 119164, 83320, 72003, 10187, 77742, 77743, 0, 77737, - 77738, 77739, 0, 10968, 43296, 119044, 0, 0, 101400, 0, 1005, 43826, - 120030, 0, 2870, 0, 101399, 0, 0, 983798, 0, 235, 1384, 77758, 74887, - 70494, 77754, 77755, 9796, 69895, 77750, 77751, 77752, 13186, 120407, - 120250, 0, 0, 0, 42527, 12911, 43427, 1383, 983581, 0, 0, 0, 6156, 68117, - 0, 7993, 4288, 0, 0, 13238, 13244, 0, 0, 120426, 13234, 120427, 0, - 118904, 0, 11364, 0, 1380, 65617, 120253, 120261, 13196, 13197, 120311, - 120419, 9495, 0, 0, 120418, 0, 73976, 128160, 0, 6941, 0, 13205, 13211, - 5801, 0, 74271, 120319, 0, 120302, 7670, 0, 68075, 983583, 0, 19957, - 72314, 2021, 93811, 43877, 0, 0, 0, 0, 3875, 120431, 64341, 0, 9814, - 43457, 13066, 3314, 7787, 0, 0, 0, 0, 0, 0, 64531, 129860, 0, 0, 0, 0, 0, - 127138, 0, 0, 9742, 0, 0, 10800, 77718, 8404, 0, 92592, 77714, 7089, - 77716, 78545, 0, 77712, 77713, 0, 0, 4772, 5771, 101405, 0, 9841, 8843, - 0, 0, 0, 129862, 120816, 0, 123137, 0, 77735, 0, 0, 0, 77731, 8849, - 77733, 77734, 65112, 1796, 77729, 77730, 69665, 8164, 41301, 3502, 0, - 122884, 128387, 0, 983835, 5825, 0, 0, 0, 0, 121322, 10983, 10354, 10418, - 0, 2022, 0, 1409, 100789, 0, 0, 0, 0, 1390, 0, 0, 10471, 65904, 5846, - 126472, 0, 0, 0, 0, 0, 0, 66035, 77725, 0, 77726, 77720, 77721, 67458, - 3168, 67733, 0, 0, 2370, 0, 126243, 0, 195049, 0, 0, 1836, 0, 121207, - 119137, 118959, 125232, 0, 0, 0, 2390, 3944, 0, 0, 0, 0, 69908, 125011, - 0, 0, 123200, 0, 0, 8975, 64739, 0, 0, 0, 0, 64409, 0, 0, 0, 0, 128564, - 0, 0, 0, 0, 6204, 0, 0, 0, 10911, 64954, 119003, 74809, 118903, 4267, 0, - 0, 0, 0, 0, 0, 72023, 0, 0, 119504, 92887, 0, 0, 0, 0, 121125, 0, 128337, - 5842, 0, 41439, 0, 0, 0, 9328, 0, 120980, 120917, 0, 0, 2285, 0, 0, 0, 0, - 118634, 64555, 0, 0, 72162, 9541, 0, 0, 0, 41441, 0, 0, 0, 41040, 2459, - 0, 0, 41041, 0, 0, 0, 0, 0, 10450, 0, 41043, 0, 0, 43125, 0, 0, 0, 0, 0, - 121008, 68436, 128040, 0, 120649, 0, 0, 4312, 43927, 0, 0, 11923, 42227, - 0, 5763, 0, 4827, 74559, 42228, 64406, 0, 0, 129703, 433, 119620, 0, - 2499, 67167, 67166, 0, 11973, 0, 4293, 42271, 42224, 0, 0, 66322, 42226, - 0, 0, 0, 74180, 0, 55277, 0, 0, 0, 119317, 0, 74632, 0, 0, 71103, 0, 0, - 0, 585, 2383, 0, 43263, 0, 4290, 64842, 0, 68920, 0, 8511, 0, 0, 0, - 119048, 2380, 126119, 0, 71704, 2376, 0, 0, 0, 5197, 127046, 127047, - 127048, 2366, 127050, 127051, 73442, 0, 0, 0, 93835, 0, 93818, 0, 0, - 74188, 113813, 0, 0, 0, 983838, 0, 0, 0, 0, 1847, 0, 72771, 0, 42384, 0, - 4227, 74158, 0, 92501, 0, 0, 42365, 0, 128902, 0, 92821, 0, 0, 0, 0, 0, - 0, 0, 0, 122934, 128563, 0, 983509, 127560, 2754, 0, 0, 128900, 0, - 127867, 119638, 0, 1711, 12984, 92365, 77776, 6255, 77770, 77771, 77772, - 77773, 0, 42063, 74184, 0, 0, 0, 0, 0, 77785, 77786, 41035, 43274, 77781, - 11256, 77783, 77784, 520, 77778, 41037, 77780, 0, 0, 41034, 0, 983829, - 64815, 0, 0, 321, 41028, 0, 0, 0, 0, 0, 0, 0, 74191, 0, 0, 72767, 1861, - 118938, 129666, 0, 0, 100770, 0, 0, 128530, 3859, 0, 41660, 0, 70793, 0, - 983756, 75014, 0, 127514, 41658, 0, 0, 0, 0, 0, 4414, 77769, 0, 42632, 0, - 0, 0, 0, 0, 1405, 0, 43220, 43341, 0, 0, 0, 0, 0, 983733, 11199, 0, 3513, - 0, 70341, 43342, 0, 65529, 0, 0, 0, 6485, 1397, 0, 0, 92678, 118566, - 124137, 0, 82961, 0, 82962, 0, 74270, 43287, 983731, 0, 0, 983738, 0, - 71914, 4317, 10490, 0, 0, 194867, 74463, 128952, 464, 41624, 0, 0, 0, - 1346, 128240, 69271, 64724, 128566, 423, 0, 0, 113748, 0, 128161, 0, 0, - 120563, 64960, 0, 0, 0, 0, 9584, 77795, 77796, 78927, 0, 9718, 77792, - 42642, 77794, 64750, 77789, 77790, 0, 0, 128333, 0, 3204, 64666, 0, - 43530, 2752, 0, 0, 119594, 0, 0, 0, 0, 92371, 0, 41983, 0, 7010, 0, 0, - 41495, 92379, 5877, 42252, 93070, 8009, 3305, 0, 0, 0, 0, 92293, 0, 0, 0, - 100836, 0, 65915, 1400, 75018, 10685, 75017, 2103, 122908, 0, 43276, 0, - 11169, 0, 6481, 0, 0, 0, 100837, 72249, 100838, 74198, 0, 9116, 0, 0, 0, - 0, 0, 0, 8129, 92994, 0, 124992, 0, 11658, 0, 0, 3452, 41031, 0, 1385, 0, - 100754, 0, 43340, 11123, 41033, 6493, 12758, 0, 0, 11426, 0, 1681, - 100755, 1204, 11960, 69902, 0, 69457, 0, 119322, 129483, 7415, 43338, 0, - 0, 67717, 64915, 0, 100759, 72021, 41497, 65044, 0, 19960, 65358, 983601, - 0, 0, 0, 73670, 0, 1789, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64728, 0, 0, 0, - 6506, 64312, 0, 2368, 0, 0, 0, 0, 3439, 1825, 1192, 0, 73739, 10639, 0, - 7790, 5430, 0, 0, 2848, 92981, 0, 0, 7607, 0, 0, 0, 120658, 0, 0, 8883, - 0, 728, 0, 0, 0, 0, 92931, 0, 121372, 128348, 0, 68078, 8091, 11447, 0, - 0, 126261, 983729, 0, 70003, 0, 0, 74419, 12335, 0, 0, 3443, 0, 0, 0, - 127145, 0, 0, 0, 0, 11843, 0, 9205, 8624, 128543, 92930, 43295, 0, 65445, - 0, 6277, 41672, 0, 10010, 70186, 983052, 0, 835, 71340, 0, 0, 0, 0, 0, - 5426, 4258, 0, 64891, 5424, 0, 8283, 0, 5434, 0, 0, 0, 0, 0, 11947, 0, - 1404, 0, 11432, 0, 3464, 6486, 4819, 0, 0, 570, 8095, 0, 0, 1498, 0, 0, - 0, 431, 67820, 0, 120574, 128096, 0, 0, 13096, 0, 0, 43408, 0, 128538, - 8835, 77875, 0, 0, 122973, 0, 0, 0, 0, 0, 3477, 227, 10488, 0, 382, - 11418, 0, 5878, 0, 0, 0, 0, 6484, 92355, 66039, 0, 0, 0, 78717, 0, 92662, - 119665, 0, 0, 43290, 0, 0, 0, 0, 8782, 0, 0, 4323, 128649, 0, 120903, - 12094, 67499, 0, 0, 0, 92953, 3856, 120970, 124138, 5872, 6495, 72306, 0, - 0, 0, 67173, 67172, 67171, 3953, 0, 0, 93063, 11994, 4339, 0, 92654, 0, - 0, 0, 0, 128804, 0, 5228, 0, 9766, 0, 92741, 0, 0, 0, 0, 68860, 0, 1162, - 0, 2671, 0, 73666, 92632, 92631, 72117, 0, 73811, 0, 194895, 0, 68085, 0, - 74331, 11424, 0, 10466, 121239, 0, 194890, 0, 4820, 0, 0, 0, 194891, 0, - 119212, 4896, 0, 4897, 42821, 64611, 0, 4438, 0, 0, 1753, 11331, 6147, 0, - 43282, 8833, 0, 0, 6504, 0, 0, 0, 118670, 0, 1413, 0, 0, 64353, 12141, - 121138, 0, 0, 43163, 0, 72880, 64789, 127094, 838, 127092, 120697, - 127090, 5014, 0, 256, 0, 0, 42443, 42739, 0, 7542, 0, 70389, 0, 6489, - 10048, 74326, 0, 66573, 0, 125271, 78712, 11761, 126078, 129603, 41094, - 0, 0, 0, 0, 92689, 8453, 0, 0, 120942, 128184, 0, 11816, 0, 0, 2930, - 93845, 0, 41098, 92771, 41093, 0, 0, 6498, 41096, 0, 0, 1238, 200, 0, - 1660, 74476, 0, 0, 74362, 0, 0, 72301, 9224, 0, 0, 0, 0, 0, 0, 0, 0, - 72729, 43284, 0, 72110, 67459, 13183, 0, 0, 0, 1669, 10776, 0, 0, 0, 0, - 0, 1732, 4030, 0, 3963, 0, 0, 0, 6491, 0, 0, 914, 121394, 0, 0, 0, 78713, - 0, 92441, 74367, 42960, 0, 0, 0, 0, 0, 0, 0, 65537, 0, 0, 43430, 5301, 0, - 92618, 0, 43285, 0, 0, 125186, 0, 0, 5876, 0, 69555, 0, 0, 110713, 0, 0, - 0, 0, 0, 0, 11114, 74536, 0, 0, 0, 0, 983130, 0, 0, 0, 0, 10915, 983069, - 12007, 0, 0, 0, 0, 67655, 92604, 0, 8629, 0, 43168, 41872, 0, 0, 0, - 42488, 0, 0, 0, 0, 0, 64730, 70041, 0, 122895, 0, 0, 0, 92306, 11416, - 4280, 128516, 8765, 73451, 0, 1393, 0, 11157, 74386, 0, 0, 0, 0, 6683, 0, - 93832, 12144, 0, 74513, 13019, 74994, 0, 0, 0, 983272, 0, 6488, 357, 0, - 41100, 0, 41104, 0, 41099, 0, 71320, 0, 0, 0, 4434, 0, 0, 0, 74231, - 83107, 0, 194914, 0, 0, 72286, 68305, 0, 41759, 12757, 0, 0, 72769, 9790, - 7674, 0, 121095, 68209, 0, 41764, 0, 0, 72322, 2268, 0, 129845, 983608, - 12743, 0, 6480, 0, 41779, 0, 66601, 0, 74490, 10986, 66602, 0, 64807, 0, - 0, 41767, 119629, 0, 0, 0, 3955, 64571, 194918, 127089, 0, 70187, 69975, - 9770, 12305, 12230, 0, 73551, 0, 0, 74752, 0, 0, 123168, 128263, 74449, - 0, 65948, 69611, 0, 0, 71131, 129505, 78573, 0, 0, 11116, 0, 5747, 0, - 110667, 9802, 41092, 120731, 0, 0, 0, 0, 0, 120733, 41090, 0, 0, 0, - 11271, 57, 0, 0, 983244, 0, 71268, 121290, 43137, 0, 0, 110672, 126221, - 0, 0, 0, 0, 0, 277, 74385, 0, 0, 0, 72155, 0, 13025, 8757, 0, 0, 1574, 0, - 126124, 100800, 0, 5749, 129923, 0, 42824, 0, 1039, 9801, 0, 5745, 0, - 41858, 0, 0, 120655, 0, 41862, 0, 0, 78822, 436, 4771, 118635, 42501, 0, - 10573, 0, 77931, 118560, 917986, 9644, 0, 0, 0, 0, 69837, 0, 0, 0, 0, - 67409, 0, 0, 0, 125204, 11939, 0, 0, 0, 0, 0, 0, 0, 3504, 0, 0, 92854, - 126209, 0, 10226, 65558, 0, 3594, 0, 0, 40, 0, 0, 0, 0, 0, 74312, 72138, - 74337, 0, 69577, 0, 0, 0, 70476, 0, 121143, 72317, 0, 0, 4304, 0, 0, - 78707, 0, 0, 0, 78597, 1348, 78596, 0, 0, 0, 70406, 92392, 0, 7599, 0, 0, - 13269, 0, 129729, 0, 100804, 0, 74494, 6097, 7568, 43980, 4982, 78592, 0, - 0, 0, 0, 13270, 0, 128090, 13138, 0, 9484, 0, 0, 71364, 0, 0, 0, 9487, 0, - 92913, 0, 71911, 78668, 73963, 6193, 0, 0, 0, 194848, 7228, 10011, - 194849, 194852, 194851, 11654, 194853, 126218, 194855, 0, 194857, 3604, - 0, 0, 0, 0, 0, 94110, 43740, 94109, 194860, 194863, 66750, 121021, 0, - 94111, 6995, 74173, 5437, 74174, 0, 8702, 7339, 129981, 0, 199, 194843, - 194846, 194845, 0, 126069, 0, 67818, 0, 7560, 0, 0, 0, 0, 6472, 65814, 0, - 128983, 70845, 0, 0, 9191, 0, 0, 0, 0, 124904, 10196, 0, 72452, 6585, 0, - 120750, 0, 0, 71872, 129129, 0, 0, 78590, 72308, 11382, 129499, 0, - 983670, 0, 194833, 194832, 2165, 129540, 94020, 194836, 42727, 194838, - 128252, 78585, 43874, 119610, 0, 0, 43248, 0, 194816, 0, 194818, 128845, - 194820, 127879, 5297, 194821, 13284, 6112, 93964, 93010, 73927, 42947, 0, - 65746, 0, 0, 194827, 194826, 4342, 42839, 194831, 1677, 0, 72135, 0, 0, - 0, 11011, 66399, 0, 0, 0, 10160, 0, 0, 0, 0, 2052, 4308, 92174, 43000, - 118659, 543, 64916, 122964, 0, 0, 119170, 0, 118922, 2064, 0, 43158, 0, - 0, 69984, 0, 0, 129187, 0, 0, 0, 0, 41631, 92728, 0, 0, 6228, 0, 0, 0, 0, - 0, 0, 506, 0, 0, 65735, 2055, 43255, 121407, 0, 0, 0, 0, 0, 0, 194666, - 2063, 0, 0, 0, 0, 72136, 0, 74333, 194912, 11827, 74308, 194913, 194916, - 194915, 64564, 194917, 67986, 194919, 0, 11037, 0, 121102, 0, 0, 10560, - 0, 120756, 194922, 113737, 194924, 194927, 120495, 1931, 0, 0, 0, 128228, - 0, 12643, 8751, 123629, 0, 12294, 0, 78834, 9138, 78831, 78833, 12631, - 78829, 11080, 78821, 0, 0, 1239, 0, 121067, 0, 12636, 0, 0, 0, 0, 0, 0, - 8998, 0, 0, 9152, 0, 0, 0, 67589, 0, 64290, 0, 92393, 12615, 0, 129141, - 6914, 93013, 0, 119569, 0, 65188, 0, 67611, 4337, 0, 194897, 194896, - 78516, 194898, 7681, 194900, 194903, 67596, 194905, 194904, 2477, 93974, - 0, 0, 0, 67604, 70705, 0, 194882, 194881, 194884, 194883, 194886, 128914, - 194888, 67599, 0, 194889, 0, 0, 0, 0, 3357, 0, 78852, 4207, 1288, 78842, - 78839, 78840, 78837, 78838, 66354, 194872, 0, 128432, 0, 67618, 92664, 0, - 42788, 0, 64612, 129897, 10774, 194877, 0, 194879, 129125, 0, 0, 997, - 194901, 0, 92577, 0, 11440, 11379, 42000, 13139, 0, 0, 74030, 72293, - 73796, 0, 0, 0, 0, 2818, 0, 0, 73793, 0, 4172, 93028, 126523, 124981, 0, - 129896, 0, 0, 129522, 69706, 0, 6834, 0, 0, 194865, 126982, 121211, - 194866, 194869, 194868, 766, 1257, 0, 0, 0, 3265, 66617, 3274, 0, 0, - 94042, 0, 8373, 41989, 69507, 73460, 3418, 3263, 0, 0, 0, 3270, 64539, - 11489, 0, 118945, 126220, 0, 127795, 0, 94031, 0, 0, 0, 0, 0, 70512, - 983983, 186, 0, 119156, 5770, 13179, 0, 12612, 12949, 64856, 12800, 0, 0, - 983152, 11507, 0, 0, 118929, 0, 0, 72141, 0, 73459, 0, 0, 0, 73461, 9254, - 66877, 194907, 0, 92338, 5624, 126253, 0, 0, 0, 120472, 120464, 0, 0, - 122915, 120462, 0, 1872, 66508, 120467, 41079, 0, 5502, 119330, 41078, - 194906, 0, 0, 4511, 68449, 0, 0, 0, 0, 43245, 41083, 68861, 0, 0, 9003, - 119959, 0, 5305, 9653, 41081, 43146, 9546, 0, 0, 120478, 0, 65205, 71713, - 64063, 120459, 0, 0, 0, 64058, 43101, 43102, 0, 64062, 1028, 64060, - 64059, 0, 10567, 110816, 110817, 92857, 110815, 0, 2902, 64043, 64042, - 43749, 10756, 64047, 64046, 64045, 64044, 0, 10076, 64040, 64039, 0, - 1034, 0, 0, 64034, 64033, 64032, 42735, 64038, 64037, 64036, 64035, 4291, - 67497, 64015, 64014, 83393, 83394, 83395, 983784, 0, 43090, 83391, 3476, - 64013, 64012, 64011, 64010, 64008, 64007, 2003, 7706, 0, 0, 119050, - 64009, 204, 0, 0, 4430, 8239, 64003, 10626, 64001, 64057, 13079, 64055, - 64054, 0, 0, 43246, 9343, 64049, 64048, 0, 1133, 64053, 64052, 64051, - 64050, 0, 0, 0, 66415, 12329, 0, 0, 129698, 1942, 0, 0, 0, 128249, 0, - 68291, 10760, 64023, 64022, 64021, 64020, 43670, 77924, 64025, 41412, - 78243, 78244, 0, 0, 64019, 64018, 64017, 64016, 0, 0, 78251, 78252, - 78248, 78249, 77914, 78247, 0, 917560, 77919, 6788, 13094, 0, 7532, - 41414, 0, 3179, 70745, 64769, 0, 0, 71967, 0, 10751, 0, 0, 0, 0, 0, 0, 0, - 2008, 64031, 64030, 294, 41874, 83383, 83384, 64844, 83376, 129063, - 83379, 83380, 64028, 11396, 64026, 83374, 0, 0, 118795, 71739, 43247, 0, - 70153, 70846, 0, 0, 0, 0, 0, 0, 0, 7801, 83359, 83361, 128931, 0, 3297, - 83356, 83357, 1135, 83350, 83351, 73696, 1995, 7927, 71738, 110742, 2552, - 83372, 60, 0, 8649, 83368, 83369, 83370, 83371, 10541, 83365, 78679, - 43833, 0, 0, 2013, 83362, 0, 110636, 0, 0, 12832, 110638, 8081, 8362, - 120188, 0, 9137, 0, 0, 0, 0, 3466, 0, 0, 1996, 0, 3453, 3412, 0, 2002, - 2000, 120176, 0, 0, 0, 0, 1998, 0, 1842, 7037, 0, 9628, 68446, 0, 9826, - 64502, 1767, 3413, 0, 0, 0, 0, 0, 0, 13108, 44024, 120204, 0, 92693, 0, - 0, 0, 70291, 12650, 983210, 0, 68061, 0, 3592, 0, 0, 0, 0, 983975, 0, - 66417, 128792, 10742, 0, 0, 1994, 9281, 3296, 64475, 1997, 1895, 128936, - 43024, 0, 0, 123184, 72391, 0, 8999, 0, 983633, 0, 66480, 0, 0, 0, - 983083, 0, 596, 0, 0, 120216, 8651, 120217, 0, 0, 12995, 0, 0, 70740, 0, - 42930, 119955, 64810, 917834, 6825, 0, 917839, 120208, 64275, 120889, - 128069, 120210, 6384, 917840, 126477, 0, 67698, 0, 0, 0, 120496, 0, - 43412, 0, 0, 0, 0, 0, 120172, 0, 120763, 0, 0, 0, 128343, 1457, 0, 0, - 6381, 2815, 0, 65240, 129664, 0, 0, 119522, 70487, 0, 0, 0, 0, 0, 120572, - 0, 0, 0, 0, 0, 125253, 0, 0, 0, 11862, 0, 0, 0, 3055, 9852, 0, 65288, 0, - 11398, 0, 0, 93016, 123550, 0, 603, 128557, 0, 0, 0, 129366, 3350, 0, 0, - 917828, 917827, 68428, 917825, 73045, 917831, 917830, 917829, 0, 1919, 0, - 110767, 83296, 83297, 83298, 66446, 64141, 8562, 64139, 64138, 64136, - 64135, 64134, 64133, 11297, 0, 0, 11966, 64128, 66286, 0, 123541, 64132, - 10867, 64130, 64129, 0, 43374, 9779, 2764, 0, 0, 9471, 0, 0, 0, 0, 66010, - 0, 8857, 128771, 121423, 0, 69223, 0, 194660, 983876, 0, 0, 43984, 0, 0, - 0, 0, 0, 0, 10717, 64570, 5630, 0, 64143, 64142, 83300, 67758, 83302, 0, - 77930, 0, 0, 0, 11631, 64146, 64145, 64144, 2384, 72801, 127380, 0, 0, 0, - 0, 118547, 0, 0, 0, 0, 122916, 8933, 1601, 917803, 858, 118637, 64109, - 64108, 8090, 0, 72387, 917811, 587, 0, 82971, 0, 0, 0, 78214, 2750, 0, - 9983, 64158, 64157, 83288, 83289, 83290, 2167, 83284, 83285, 83286, - 83287, 64156, 64155, 64154, 69495, 64151, 64150, 12679, 10053, 10421, 0, - 64153, 64152, 0, 0, 4839, 0, 0, 4435, 119016, 0, 64126, 64125, 64124, - 64123, 129287, 0, 67478, 7007, 0, 65443, 0, 0, 64122, 0, 0, 93834, 64117, - 64116, 6287, 64114, 64121, 64120, 64119, 64118, 110659, 127842, 1177, - 65601, 12322, 64106, 92169, 110654, 64102, 64101, 64100, 64099, 0, 10453, - 64104, 64103, 7997, 0, 92534, 0, 8705, 64097, 64096, 9571, 0, 110652, - 127398, 12132, 0, 0, 0, 110624, 73841, 83339, 83340, 9056, 0, 129970, 0, - 6155, 64068, 64067, 64066, 64065, 64072, 64071, 63, 64069, 127382, 0, - 93822, 7257, 64064, 0, 0, 0, 0, 0, 0, 78748, 0, 0, 0, 120519, 0, 66242, - 66232, 4333, 9855, 64112, 0, 0, 118531, 0, 0, 0, 0, 66222, 0, 0, 0, 0, - 69816, 0, 118796, 0, 8708, 0, 64077, 64076, 8996, 4992, 4471, 83343, - 64079, 64078, 92179, 0, 0, 123540, 64615, 0, 0, 12075, 42041, 0, 0, 0, 0, - 127557, 3123, 0, 983754, 0, 0, 0, 83328, 0, 9223, 0, 83321, 83322, 73797, - 83327, 1116, 0, 83319, 7136, 73550, 0, 0, 0, 75031, 0, 0, 0, 64092, - 43675, 10104, 83338, 83331, 64095, 64094, 8111, 66247, 0, 64089, 64088, - 0, 70106, 42236, 11434, 64083, 64082, 43216, 7737, 64087, 64086, 64085, - 64084, 0, 0, 0, 4118, 1797, 83312, 0, 0, 46, 83308, 83309, 298, 83303, - 72402, 83305, 83306, 0, 0, 0, 128905, 11495, 0, 67490, 0, 127377, 194828, - 127370, 0, 0, 0, 66239, 74945, 64403, 0, 0, 83314, 0, 0, 65758, 43536, 0, - 8544, 0, 0, 0, 0, 194824, 0, 0, 0, 0, 0, 3639, 11242, 194822, 0, 0, 0, 0, - 0, 0, 68409, 0, 0, 0, 101121, 0, 0, 0, 128654, 8789, 126248, 0, 0, - 128325, 0, 0, 0, 0, 65058, 0, 78234, 68064, 0, 66227, 71694, 5573, - 118936, 0, 44, 0, 66244, 118907, 0, 66238, 12844, 0, 1622, 129190, 1900, - 0, 11458, 0, 0, 6581, 5576, 128303, 0, 126122, 0, 113680, 8947, 0, - 113812, 0, 69744, 0, 7908, 0, 917998, 6579, 0, 0, 0, 0, 2138, 6583, 7761, - 0, 0, 0, 66802, 5058, 0, 0, 0, 5057, 125256, 0, 74538, 5054, 0, 0, 0, 0, - 0, 0, 658, 3497, 128509, 0, 5061, 5060, 4235, 0, 0, 0, 127757, 4236, - 4727, 0, 0, 0, 128791, 0, 7488, 128693, 7476, 0, 125259, 120646, 0, 0, 0, - 66209, 0, 0, 0, 78931, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128903, 0, 9341, - 119596, 0, 0, 0, 64668, 0, 8125, 0, 6743, 119175, 0, 129441, 83406, 0, - 127966, 119235, 74092, 0, 0, 43660, 71125, 0, 127901, 0, 0, 0, 264, 0, - 74954, 0, 0, 0, 0, 0, 6019, 0, 0, 129121, 0, 0, 0, 8800, 0, 66376, 0, - 120948, 0, 100744, 0, 0, 92333, 725, 68014, 110579, 110578, 72099, 0, 0, - 0, 0, 74899, 0, 0, 0, 110804, 0, 72142, 5074, 5073, 0, 0, 128726, 0, - 70723, 5072, 128576, 13098, 72403, 0, 11040, 0, 0, 0, 4929, 0, 0, 0, 0, - 0, 0, 0, 0, 67754, 4934, 0, 0, 9758, 0, 0, 70181, 42584, 0, 4329, 0, - 4979, 8663, 74521, 0, 983042, 74418, 983653, 0, 5071, 0, 3642, 0, 5070, - 10042, 0, 3987, 5068, 120209, 8909, 0, 0, 69917, 0, 73981, 983142, 70749, - 4531, 120212, 9105, 0, 4921, 121059, 4926, 65544, 113786, 69621, 0, 0, 0, - 83269, 0, 120790, 4922, 0, 992, 119568, 4925, 0, 0, 9526, 4920, 128617, - 948, 0, 0, 4930, 0, 0, 0, 4933, 0, 0, 0, 4928, 0, 0, 0, 0, 128379, 722, - 118696, 127483, 127482, 127485, 82997, 127487, 1509, 0, 5468, 66214, - 127474, 127477, 1672, 127479, 10864, 127481, 72132, 127467, 72159, - 127469, 127468, 127471, 127470, 68336, 82999, 120115, 1679, 120116, 0, - 120113, 127462, 127465, 127464, 127110, 120119, 120112, 0, 120109, 6968, - 5761, 342, 8553, 0, 8143, 127115, 127114, 2253, 624, 127111, 4057, 0, - 5078, 0, 0, 0, 5076, 0, 0, 0, 120097, 685, 9025, 1524, 8003, 0, 5539, - 113727, 113795, 118673, 7138, 120552, 0, 0, 0, 113724, 0, 8058, 9732, 0, - 5080, 0, 5036, 5035, 0, 42604, 72118, 0, 0, 275, 13291, 69995, 0, 0, - 983927, 5033, 0, 0, 4836, 70184, 73792, 0, 0, 0, 120681, 43704, 0, 2274, - 119000, 124983, 0, 8858, 6409, 0, 119585, 0, 0, 0, 0, 0, 68442, 0, 3432, - 10218, 0, 6094, 11232, 0, 0, 0, 0, 1676, 129157, 0, 0, 5030, 0, 118810, - 0, 73869, 0, 0, 69944, 6787, 0, 0, 0, 983595, 10544, 12919, 69425, 92218, - 0, 0, 0, 129172, 118715, 67703, 0, 0, 0, 0, 0, 72290, 0, 0, 0, 0, 7018, - 66241, 0, 0, 0, 0, 0, 74056, 0, 11833, 0, 67975, 65232, 40964, 251, - 12686, 7895, 4395, 43538, 0, 0, 0, 78042, 0, 0, 40967, 5879, 0, 0, 0, 0, - 0, 65540, 128590, 625, 0, 120194, 1113, 120195, 13103, 3630, 67224, 8179, - 74264, 67886, 9316, 10980, 2489, 120958, 8150, 1359, 121353, 70464, - 127330, 127327, 5042, 5041, 42769, 12084, 11196, 42961, 92279, 72398, - 120535, 127317, 127318, 127315, 12283, 127313, 11453, 70207, 8795, 66245, - 0, 5919, 0, 5037, 118864, 0, 0, 67724, 0, 66893, 74006, 129535, 8431, 0, - 0, 0, 0, 12620, 6826, 73773, 70169, 5040, 0, 0, 0, 0, 0, 5039, 0, 0, 0, - 5038, 0, 0, 0, 0, 0, 65908, 0, 0, 0, 0, 0, 65157, 0, 0, 70182, 0, 73909, - 4835, 0, 0, 0, 4309, 7127, 0, 0, 0, 1301, 0, 0, 12222, 0, 73813, 711, - 92439, 7133, 0, 0, 0, 0, 0, 0, 0, 7661, 72263, 129541, 0, 0, 70453, 7627, - 0, 5031, 92340, 42738, 65784, 0, 65782, 3758, 0, 65781, 67865, 0, 2440, - 65780, 70795, 8449, 121393, 121479, 0, 2118, 0, 12121, 0, 0, 129510, - 2128, 2130, 2131, 2126, 2133, 0, 121250, 2114, 2116, 2455, 0, 2122, 2123, - 2124, 2125, 983806, 8714, 0, 2113, 0, 2115, 0, 127907, 43713, 5052, - 66220, 66653, 65777, 65778, 65775, 5051, 65773, 1429, 42647, 5050, 65769, - 388, 70685, 735, 0, 129899, 128035, 0, 12726, 0, 0, 0, 0, 0, 5109, 5053, - 0, 120854, 0, 0, 0, 2470, 0, 0, 1925, 71251, 0, 10971, 113770, 5048, - 5047, 0, 0, 194946, 92313, 129972, 0, 0, 8089, 128468, 639, 0, 68179, 0, - 70180, 0, 4599, 0, 0, 0, 0, 983817, 648, 194948, 65819, 0, 0, 0, 129968, - 94017, 0, 11777, 9750, 983123, 0, 0, 92367, 70175, 5046, 66255, 0, 0, - 65253, 0, 5045, 0, 1916, 74069, 5044, 92348, 0, 0, 5043, 0, 0, 0, 74004, - 9669, 12341, 0, 8402, 0, 0, 70174, 0, 3586, 64508, 92456, 0, 0, 119606, - 0, 42628, 10069, 0, 0, 0, 0, 123, 120703, 0, 121326, 0, 10719, 129409, - 120444, 10829, 120593, 0, 12130, 0, 0, 0, 0, 3925, 0, 0, 75065, 71112, - 92372, 71110, 71111, 0, 120441, 120452, 983179, 0, 0, 0, 0, 0, 0, 0, 0, - 69879, 8509, 120449, 0, 0, 0, 120448, 0, 118889, 194858, 0, 0, 0, 66445, - 0, 71109, 0, 0, 72425, 0, 12136, 0, 983629, 0, 0, 0, 0, 19922, 41768, - 74002, 0, 0, 0, 0, 2458, 0, 0, 0, 41074, 4266, 64834, 0, 41077, 0, 9050, - 0, 0, 73693, 0, 0, 41075, 2476, 0, 0, 0, 69761, 0, 0, 74202, 78745, 0, - 121324, 70152, 66033, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83106, 0, 0, 0, 43693, - 78753, 0, 12194, 66215, 71987, 121273, 67216, 121499, 0, 121118, 0, - 78756, 0, 0, 55256, 0, 0, 0, 0, 43876, 0, 0, 0, 12948, 195003, 195002, - 195005, 195004, 195007, 195006, 0, 128320, 4287, 70183, 4902, 74020, 0, - 917961, 0, 1816, 0, 0, 168, 0, 4898, 64298, 0, 78450, 4901, 1821, 0, - 43294, 3653, 120899, 791, 9162, 6977, 121183, 0, 70160, 0, 73731, 8354, - 0, 0, 0, 7557, 0, 0, 8234, 194992, 78456, 194994, 194993, 194996, 101519, - 65925, 194997, 195000, 194999, 0, 66996, 0, 64397, 0, 0, 0, 71310, - 194977, 194976, 2448, 194978, 194981, 194980, 2452, 194982, 194985, - 194984, 78694, 72292, 7845, 0, 78692, 4408, 4122, 6772, 194988, 8723, - 72147, 194989, 73472, 11857, 119304, 119303, 2438, 119297, 119300, - 119299, 41953, 0, 42135, 373, 119172, 2119, 11457, 129618, 41955, 0, 0, - 0, 41952, 0, 0, 2127, 0, 128496, 5202, 0, 78765, 42823, 11291, 0, 0, - 12963, 0, 0, 4125, 41958, 12133, 0, 125099, 1271, 129427, 0, 66024, 0, - 3864, 127825, 0, 0, 0, 0, 4166, 0, 0, 129917, 7459, 0, 119914, 5384, 0, - 0, 70154, 5759, 0, 0, 0, 0, 66744, 0, 120571, 0, 75066, 5552, 0, 0, - 127192, 5553, 0, 0, 0, 12906, 0, 0, 110787, 110792, 110788, 5554, 0, - 12344, 110786, 101508, 0, 0, 0, 0, 8517, 101509, 0, 0, 66017, 5555, - 92317, 0, 983672, 0, 0, 0, 9143, 0, 195067, 67995, 195069, 127162, - 195071, 195070, 4577, 64624, 0, 0, 125105, 983680, 4269, 983674, 983671, - 983669, 0, 950, 0, 983673, 983683, 983668, 0, 983675, 0, 119121, 0, 5098, - 0, 0, 119099, 5097, 0, 9848, 0, 10293, 983664, 72798, 0, 0, 70303, - 983684, 5102, 5101, 128370, 0, 8138, 4517, 1932, 5100, 195060, 65022, - 1247, 10034, 195064, 5099, 0, 1441, 0, 4724, 650, 0, 73954, 983271, - 129348, 195040, 195043, 9031, 195045, 195044, 195047, 8545, 66356, - 195048, 0, 9154, 127243, 0, 0, 2676, 2277, 0, 73812, 195051, 8599, - 195053, 917918, 195055, 65462, 0, 92524, 195033, 71903, 0, 0, 41199, 0, - 11399, 195035, 195034, 195037, 195036, 195039, 195038, 5108, 5107, 0, - 66019, 0, 0, 5541, 0, 0, 12613, 5284, 0, 0, 118537, 4275, 74865, 854, - 68147, 74381, 120918, 0, 5103, 124986, 64348, 0, 0, 5221, 69811, 0, - 71493, 121163, 0, 0, 11438, 0, 0, 70158, 0, 0, 5106, 195024, 110749, - 65154, 69813, 195028, 5105, 195030, 69720, 195032, 5104, 983780, 0, 3176, - 127342, 70149, 932, 0, 6567, 195009, 195008, 195011, 195010, 70145, - 43850, 195015, 195014, 195017, 195016, 0, 0, 0, 69511, 10670, 0, 13273, - 0, 195020, 121370, 8803, 195021, 72431, 8151, 67145, 72436, 0, 12553, 0, - 0, 0, 0, 13065, 12570, 0, 0, 0, 983199, 124985, 0, 0, 66466, 0, 0, - 194595, 0, 194596, 11351, 43256, 0, 0, 0, 0, 41754, 0, 0, 2720, 194975, - 68462, 8232, 120758, 0, 0, 0, 0, 122959, 0, 0, 93067, 10834, 0, 0, - 119266, 0, 0, 125025, 67679, 0, 75064, 7781, 0, 0, 126076, 0, 12077, 0, - 64586, 127164, 42396, 0, 3475, 0, 2479, 0, 0, 0, 120728, 0, 42434, - 129709, 194963, 194962, 110611, 67894, 42473, 194966, 110609, 1843, - 42283, 0, 0, 0, 0, 0, 194970, 0, 42321, 7284, 194974, 194973, 194950, - 194949, 194952, 194951, 0, 194953, 123614, 128645, 0, 0, 0, 0, 74952, - 194954, 194957, 194956, 66367, 194958, 41069, 67689, 9988, 0, 41068, 0, - 4295, 0, 0, 41951, 67835, 0, 785, 8236, 128647, 9027, 0, 194943, 0, - 122986, 0, 0, 0, 0, 41071, 41059, 0, 92458, 129442, 0, 0, 0, 123612, - 2067, 4310, 0, 123611, 5180, 123605, 0, 73872, 0, 69880, 5184, 42385, - 194947, 983774, 128531, 0, 0, 119149, 73503, 121334, 0, 983781, 0, 0, - 5178, 194929, 120548, 194931, 5188, 194933, 194932, 72245, 194934, 1166, - 64429, 42639, 0, 0, 0, 0, 128071, 2442, 10703, 194940, 194939, 194635, - 42439, 0, 0, 0, 73933, 983242, 42401, 0, 0, 0, 42288, 0, 0, 0, 13145, 0, - 2468, 0, 42327, 0, 0, 0, 42479, 128698, 0, 0, 92580, 0, 74939, 120678, 0, - 73733, 0, 0, 2715, 0, 71257, 0, 74114, 0, 0, 0, 0, 0, 66325, 69603, 0, - 9240, 0, 0, 129142, 0, 0, 0, 9815, 0, 11246, 0, 73912, 42733, 0, 0, 2480, - 0, 0, 0, 6494, 5537, 0, 0, 0, 0, 1211, 0, 121379, 0, 0, 12318, 0, 113796, - 0, 0, 0, 0, 0, 64642, 0, 0, 0, 0, 64864, 0, 0, 0, 121212, 0, 0, 3589, - 92719, 4035, 6492, 92236, 4265, 6843, 0, 74186, 41778, 113764, 119216, - 2488, 0, 4582, 0, 71426, 41777, 12926, 72708, 7528, 10550, 113761, 0, 0, - 11439, 0, 0, 64878, 0, 0, 0, 0, 2286, 0, 0, 126646, 127909, 5909, 400, - 126500, 0, 0, 0, 0, 0, 64827, 0, 74948, 390, 0, 71301, 0, 3473, 0, 0, - 66742, 0, 55285, 0, 0, 0, 92206, 194964, 0, 8004, 0, 6763, 0, 0, 7006, 0, - 0, 6757, 73707, 126648, 0, 6766, 0, 0, 0, 6146, 0, 771, 0, 0, 41318, 0, - 42272, 0, 120211, 69559, 0, 953, 12917, 72287, 12300, 64837, 11491, - 68612, 0, 0, 71321, 7490, 11389, 7489, 3379, 0, 7487, 42996, 7486, 7484, - 7482, 6753, 7480, 7479, 7478, 7477, 6501, 7475, 42995, 7473, 7472, 2474, - 7470, 7468, 124977, 0, 0, 0, 0, 71871, 11834, 128376, 0, 6017, 0, 128763, - 0, 0, 0, 119365, 73949, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2472, 69945, - 120699, 121133, 2139, 4256, 120776, 74380, 0, 73847, 73844, 0, 0, 101375, - 0, 101374, 0, 0, 101347, 7083, 0, 8066, 7678, 0, 121124, 101341, 101373, - 101336, 0, 101331, 0, 101304, 0, 101301, 0, 0, 0, 8330, 0, 101298, - 101322, 101297, 0, 0, 19934, 0, 1770, 67091, 0, 128671, 129617, 110605, - 101355, 73843, 110604, 0, 101362, 67092, 0, 71334, 0, 0, 0, 0, 0, 8162, - 0, 5996, 129644, 4903, 0, 0, 43063, 0, 5172, 0, 7139, 0, 127385, 0, - 118667, 0, 0, 4334, 6324, 41975, 12186, 10674, 12308, 0, 0, 0, 72807, - 41977, 68002, 0, 126630, 2018, 121388, 41979, 68003, 0, 68000, 0, 0, - 126984, 68001, 9334, 118609, 71440, 0, 7975, 0, 0, 0, 66621, 4884, 70367, - 983759, 0, 121010, 0, 0, 0, 0, 127799, 0, 0, 0, 463, 0, 194584, 69617, - 6509, 5460, 0, 0, 0, 0, 42279, 0, 0, 0, 0, 0, 0, 0, 125027, 0, 121119, 0, - 0, 0, 5663, 0, 0, 0, 0, 2482, 66202, 0, 0, 42247, 65174, 73925, 0, - 100940, 0, 0, 126573, 0, 0, 2460, 0, 11944, 0, 0, 64679, 120835, 127310, - 0, 0, 0, 5870, 0, 0, 0, 100931, 539, 100933, 100932, 100935, 9064, - 100937, 100936, 100939, 100938, 0, 0, 0, 0, 0, 0, 41295, 100941, 2478, - 100943, 4162, 100945, 4260, 12953, 100950, 100949, 129800, 0, 0, 0, 0, 0, - 0, 0, 5000, 0, 0, 0, 69672, 71439, 0, 74017, 0, 0, 6709, 0, 0, 983739, 0, - 0, 100922, 100921, 10301, 10333, 10397, 100925, 100928, 100927, 0, 0, 0, - 127830, 0, 4014, 12842, 0, 67413, 0, 0, 3893, 0, 0, 12210, 0, 42147, 0, - 983622, 74465, 0, 0, 0, 0, 0, 0, 0, 0, 110805, 8231, 0, 69946, 41968, - 100929, 41973, 12935, 41969, 0, 2453, 0, 0, 78807, 122893, 0, 10349, - 10413, 122956, 41962, 3202, 119097, 0, 8316, 129174, 0, 7314, 0, 0, 0, 0, - 1840, 0, 0, 0, 4883, 100908, 4723, 70099, 100909, 0, 0, 0, 0, 11089, 240, - 19906, 0, 0, 0, 43600, 121004, 13134, 93065, 0, 65931, 110649, 110650, - 42634, 110648, 0, 121005, 11463, 0, 0, 129861, 10445, 0, 92969, 0, 2614, - 0, 129954, 1729, 0, 0, 100911, 0, 43334, 100912, 100915, 100914, 66201, - 100916, 69662, 100896, 100899, 100898, 4121, 100900, 70272, 82954, 63879, - 0, 70872, 0, 0, 4039, 643, 7726, 120082, 0, 120068, 58, 0, 0, 0, 63872, - 0, 0, 100891, 0, 10625, 100892, 100895, 100894, 1416, 120073, 917761, - 67393, 0, 0, 0, 6996, 4264, 0, 100902, 66179, 66768, 100903, 13114, - 72311, 67510, 3094, 0, 0, 127074, 4437, 0, 0, 0, 55280, 42174, 0, 42430, - 129796, 72246, 42355, 0, 0, 0, 0, 121251, 127401, 0, 0, 0, 0, 0, 0, - 100882, 100881, 74037, 100883, 0, 127099, 0, 0, 0, 0, 0, 69646, 65035, - 65034, 11480, 6116, 65039, 65038, 41180, 65036, 194565, 0, 12101, 5822, - 0, 0, 0, 0, 11663, 127873, 63854, 119657, 63853, 0, 63852, 65810, 4289, - 100885, 63896, 100887, 100890, 43621, 0, 0, 0, 129613, 194560, 7461, - 73901, 0, 331, 0, 0, 0, 128029, 0, 0, 0, 74629, 0, 0, 0, 41964, 0, 63843, - 2084, 41965, 0, 100864, 100863, 100866, 63841, 78549, 41220, 13032, - 100869, 8383, 0, 78548, 126102, 0, 0, 1351, 983865, 8698, 100874, 100877, - 1930, 100879, 78554, 74360, 100880, 69859, 78551, 0, 0, 129433, 3657, 0, - 65202, 6000, 119206, 41901, 0, 0, 41740, 0, 41283, 73543, 119267, 0, 0, - 100871, 9695, 100873, 7562, 100853, 5170, 100855, 100854, 676, 100856, - 100859, 100858, 9978, 100860, 0, 0, 64934, 0, 0, 0, 113714, 113706, - 41829, 65886, 5159, 0, 41832, 704, 43077, 0, 120532, 0, 68496, 65065, - 41830, 0, 917799, 917798, 917797, 917796, 0, 67864, 113696, 917800, - 12336, 4135, 69805, 341, 2727, 4129, 100862, 100861, 0, 64503, 7913, 0, - 0, 4131, 63868, 0, 63871, 4133, 63864, 210, 0, 0, 0, 4137, 78505, 78506, - 0, 78504, 78830, 0, 0, 43873, 0, 0, 0, 0, 11988, 78510, 195, 68321, - 41501, 0, 42031, 0, 13135, 0, 0, 0, 41499, 0, 0, 9680, 41498, 917794, - 42025, 78567, 78556, 0, 0, 0, 0, 0, 0, 101074, 120502, 92597, 0, 0, - 917784, 7864, 129001, 129704, 917788, 121106, 917786, 917785, 5753, - 67816, 72371, 2219, 0, 0, 0, 0, 0, 0, 121277, 0, 917777, 917776, 917775, - 69644, 917781, 917780, 917779, 917778, 8668, 0, 121383, 917782, 5999, 0, - 0, 129195, 128243, 43653, 1726, 1015, 0, 127247, 0, 0, 64919, 0, 0, 0, - 128478, 0, 69791, 927, 0, 0, 42010, 0, 42021, 0, 0, 1299, 12240, 64537, - 0, 0, 0, 0, 0, 0, 69454, 0, 0, 0, 122903, 19914, 12179, 0, 2296, 0, 0, - 63832, 917773, 0, 63816, 2594, 63823, 63817, 11178, 0, 0, 0, 11265, - 68295, 0, 0, 0, 10554, 3972, 0, 121198, 0, 917766, 10816, 917764, 119608, - 74374, 917769, 11210, 93069, 8586, 3882, 8532, 120183, 1573, 128648, 0, - 69916, 0, 101051, 67719, 0, 0, 0, 0, 0, 0, 0, 128821, 119169, 0, 0, 6626, - 42763, 130034, 118884, 128613, 0, 83128, 0, 0, 0, 0, 0, 983561, 0, 0, 0, - 9171, 0, 0, 71305, 983919, 121146, 0, 101095, 128881, 119604, 126596, 0, - 0, 0, 128214, 42368, 0, 983106, 2271, 41487, 12118, 74124, 68651, 110836, - 110833, 3009, 41476, 41489, 69825, 3007, 1448, 3018, 0, 41491, 8521, - 5083, 5082, 0, 0, 8519, 0, 3014, 5081, 73926, 0, 128549, 0, 69951, 5079, - 129963, 2557, 128086, 65532, 11828, 0, 71297, 11105, 0, 0, 0, 8518, - 10779, 0, 71303, 0, 0, 42170, 110769, 0, 629, 1924, 0, 12037, 0, 5987, - 8462, 127744, 0, 63933, 69735, 110770, 128295, 63941, 67981, 5077, 0, - 10880, 64849, 5075, 0, 128152, 65075, 0, 11007, 983736, 0, 0, 0, 66684, - 72331, 3434, 72338, 1904, 0, 0, 72730, 0, 10499, 4507, 9578, 63925, 0, - 7979, 0, 9831, 66689, 0, 461, 194834, 0, 4504, 0, 0, 6325, 0, 43021, 0, - 0, 55236, 0, 0, 5177, 41324, 12055, 63831, 0, 41327, 12591, 0, 4114, 409, - 0, 0, 8948, 41325, 0, 721, 10182, 0, 71311, 0, 0, 94052, 74963, 83503, - 5998, 0, 0, 74825, 0, 12587, 0, 78571, 74889, 71328, 128955, 0, 74121, - 78570, 73499, 0, 0, 5995, 0, 42568, 0, 0, 63944, 73860, 126586, 0, 4167, - 0, 43175, 0, 74120, 0, 65076, 938, 73857, 73854, 11737, 9721, 0, 0, 0, - 11742, 0, 0, 11493, 12334, 128762, 0, 66623, 0, 9173, 0, 11978, 0, 12734, - 113750, 113741, 0, 6759, 0, 0, 0, 126222, 0, 70388, 129093, 13027, 42777, - 7683, 1167, 0, 4983, 0, 861, 0, 0, 68297, 0, 43757, 92978, 129298, - 122630, 127804, 0, 73546, 70815, 9616, 0, 0, 12816, 43759, 0, 12710, - 68674, 12721, 4101, 66185, 0, 5992, 7616, 0, 0, 12577, 0, 0, 853, 42693, - 0, 121088, 0, 0, 917915, 0, 42835, 0, 0, 0, 0, 0, 12712, 7105, 127807, - 65060, 66875, 9900, 0, 0, 0, 121482, 119265, 0, 64778, 12585, 0, 0, 0, 0, - 0, 0, 77826, 0, 4900, 125245, 0, 0, 0, 4119, 74768, 8971, 0, 0, 0, 78594, - 41132, 9245, 73060, 0, 4138, 194841, 0, 0, 0, 77827, 0, 13054, 0, 0, - 128416, 110760, 0, 0, 3948, 128878, 0, 0, 0, 1680, 0, 11861, 0, 0, - 120032, 0, 0, 0, 0, 74833, 74190, 5993, 42709, 0, 12706, 77846, 1893, 0, - 63915, 0, 0, 110744, 129826, 0, 63997, 120018, 63996, 3077, 0, 0, 1512, - 0, 12589, 41479, 0, 0, 0, 0, 11831, 120727, 122949, 41481, 0, 118912, 0, - 3090, 0, 3086, 1664, 1850, 0, 3079, 0, 0, 94080, 127140, 0, 0, 74401, 0, - 917555, 0, 0, 0, 0, 0, 11526, 63985, 5864, 0, 63992, 0, 63991, 0, 5480, - 7858, 0, 4116, 78149, 0, 0, 0, 63907, 0, 0, 126131, 63905, 119601, 0, - 983191, 0, 119666, 0, 0, 7534, 507, 91, 2042, 120775, 118596, 0, 66028, - 118811, 41844, 70680, 774, 0, 0, 0, 5994, 0, 12733, 0, 0, 0, 72297, 0, 0, - 0, 0, 6026, 0, 0, 0, 162, 0, 125247, 78151, 78152, 983590, 92709, 0, - 68304, 0, 0, 0, 66658, 0, 0, 0, 0, 121511, 2226, 121512, 129349, 10492, - 0, 121510, 0, 43119, 0, 0, 0, 66192, 0, 0, 4899, 12729, 0, 0, 0, 0, 4103, - 0, 129842, 77851, 69429, 129046, 0, 12859, 70087, 0, 101580, 0, 0, 0, 0, - 0, 0, 65264, 5146, 0, 194694, 71684, 0, 0, 983652, 983863, 78924, 71688, - 78463, 5147, 125019, 0, 74524, 71682, 128435, 0, 194692, 5991, 3445, 0, - 4976, 66193, 0, 0, 0, 0, 128309, 128594, 129819, 69579, 0, 63855, 0, - 10138, 0, 0, 8897, 0, 75027, 0, 120931, 77862, 65836, 0, 0, 77860, 0, 0, - 1123, 4124, 41553, 77903, 0, 71680, 121386, 398, 0, 129035, 41551, 0, 0, - 0, 41550, 9970, 0, 93062, 42392, 1305, 78901, 0, 129292, 0, 7346, 41464, - 0, 0, 0, 41465, 983567, 8528, 9149, 0, 63955, 165, 3024, 11852, 119163, - 0, 9093, 0, 9147, 0, 0, 110989, 9148, 0, 4096, 53, 8296, 0, 71352, 0, - 9594, 0, 0, 63952, 0, 10997, 0, 0, 5805, 0, 0, 129777, 42176, 71455, - 74601, 129604, 10591, 0, 92852, 0, 0, 0, 0, 0, 0, 92475, 0, 0, 42379, 0, - 0, 9220, 0, 121425, 0, 0, 4132, 0, 0, 11239, 0, 0, 74837, 0, 66408, 0, - 8055, 0, 0, 0, 63962, 74042, 8924, 43123, 5988, 0, 63969, 0, 42718, 8788, - 1357, 77872, 65743, 0, 8774, 0, 0, 0, 0, 92748, 120598, 128234, 9564, 0, - 0, 119124, 0, 121241, 110983, 92975, 3121, 0, 0, 0, 70081, 0, 0, 0, 0, 0, - 64851, 0, 0, 73085, 119532, 0, 0, 0, 0, 1198, 69293, 66708, 64619, 0, - 64663, 93991, 0, 0, 2101, 1398, 0, 92554, 0, 0, 92684, 11406, 101588, - 12127, 66998, 840, 0, 0, 7101, 120938, 0, 0, 12880, 0, 43104, 0, 0, 0, - 2117, 0, 0, 0, 0, 123023, 0, 0, 7769, 129867, 92413, 0, 0, 100695, 0, - 40986, 83117, 0, 0, 4127, 0, 0, 129034, 0, 0, 0, 70738, 0, 129466, 0, 0, - 0, 0, 119081, 0, 10581, 0, 4533, 0, 128941, 6490, 0, 12038, 0, 0, 68225, - 0, 0, 69704, 0, 1948, 119007, 129607, 101586, 0, 0, 0, 120802, 0, 9494, - 0, 0, 0, 4843, 0, 74772, 4098, 0, 0, 0, 3436, 0, 127279, 12817, 0, - 126607, 118678, 0, 0, 0, 74433, 0, 0, 71962, 0, 121296, 65916, 0, 0, - 121458, 0, 129107, 93815, 0, 73743, 0, 0, 983133, 67676, 0, 0, 74627, - 128928, 0, 127892, 0, 71326, 67222, 0, 75013, 92435, 0, 128500, 0, 0, - 9613, 43425, 4526, 121415, 0, 64520, 71336, 0, 0, 55278, 10228, 64957, 0, - 0, 3807, 2081, 66640, 0, 0, 0, 0, 119269, 0, 128688, 0, 128142, 1451, 0, - 0, 4134, 0, 74847, 0, 74793, 0, 78913, 74295, 9960, 1201, 0, 12846, - 121271, 0, 11919, 64962, 0, 43739, 0, 66358, 0, 0, 0, 43679, 72284, - 72289, 0, 129523, 1253, 983870, 65766, 500, 65764, 65765, 65762, 65763, - 65760, 65761, 70334, 983867, 9821, 11702, 110630, 110631, 110628, 110629, - 128481, 0, 7533, 66717, 92500, 92305, 0, 0, 69277, 127758, 71332, 0, 0, - 0, 0, 11188, 0, 4112, 0, 0, 12890, 0, 0, 9915, 0, 68423, 0, 0, 2876, 0, - 0, 0, 0, 7382, 92415, 0, 128132, 0, 0, 0, 0, 69561, 127915, 0, 7003, 0, - 0, 7704, 0, 0, 0, 4123, 0, 0, 9977, 0, 0, 65759, 0, 0, 128266, 9808, 0, - 92611, 4126, 0, 9521, 9589, 64755, 0, 0, 0, 69948, 0, 92368, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 93814, 0, 0, 92234, 0, 10693, 0, 0, 65897, 4058, 0, 0, - 64660, 0, 0, 0, 983730, 1139, 43298, 0, 65929, 8970, 0, 9934, 0, 11023, - 128020, 42522, 0, 0, 0, 78899, 3057, 128113, 7349, 69959, 128722, 68065, - 110813, 0, 92826, 67201, 0, 0, 0, 9528, 0, 0, 0, 9102, 627, 92827, 6273, - 129496, 0, 0, 983212, 92966, 43300, 0, 983740, 11696, 92825, 1018, 65554, - 0, 74338, 0, 7645, 0, 128321, 0, 0, 0, 0, 73814, 11544, 12563, 10728, 0, - 0, 127340, 43311, 64966, 92841, 0, 0, 118946, 0, 0, 74779, 0, 185, 65085, - 74533, 0, 0, 7535, 0, 42525, 0, 9749, 41701, 6131, 0, 4117, 129062, - 126988, 0, 92429, 65693, 0, 73445, 0, 69695, 0, 0, 0, 0, 0, 0, 0, 1184, - 0, 815, 0, 0, 0, 0, 0, 71325, 0, 0, 64683, 983816, 0, 127959, 0, 0, 0, 0, - 0, 0, 0, 68166, 0, 0, 0, 0, 66799, 0, 128912, 0, 5142, 0, 69643, 0, 0, - 68367, 93975, 0, 0, 0, 123209, 124133, 0, 0, 74855, 121330, 0, 0, 0, 0, - 10940, 66030, 0, 70385, 73494, 0, 2652, 120527, 0, 129946, 0, 126508, 0, - 0, 0, 0, 0, 0, 1828, 0, 128357, 0, 8531, 0, 74799, 12324, 72434, 65238, - 68374, 0, 65573, 0, 68308, 68679, 12904, 43445, 0, 0, 0, 11247, 0, 0, - 41426, 0, 0, 0, 0, 0, 67250, 69451, 83354, 11869, 0, 0, 0, 0, 0, 0, 637, - 0, 0, 0, 121178, 0, 0, 74474, 71306, 0, 7298, 128256, 0, 0, 0, 0, 8210, - 0, 0, 0, 2046, 0, 0, 0, 70333, 0, 1506, 69926, 0, 83353, 0, 12651, 0, 0, - 11867, 12058, 120626, 72111, 7803, 0, 0, 65592, 118844, 0, 0, 355, 9719, - 0, 118961, 0, 121077, 127246, 0, 42178, 0, 69760, 42571, 0, 0, 0, 0, 0, - 0, 127176, 3178, 0, 0, 92704, 83381, 9080, 120943, 67697, 0, 121342, - 129875, 0, 71485, 0, 917837, 0, 0, 78157, 0, 0, 0, 0, 0, 71313, 0, 70710, - 128212, 0, 72238, 67858, 0, 0, 0, 0, 0, 0, 0, 10770, 118994, 0, 465, 0, - 983656, 74348, 0, 0, 0, 0, 0, 0, 0, 10930, 0, 0, 0, 119091, 69388, - 122637, 129918, 0, 0, 0, 0, 0, 10092, 0, 0, 0, 0, 119019, 1766, 11282, - 11996, 66644, 4547, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120906, 4345, 0, 0, - 128947, 0, 0, 0, 0, 0, 5382, 0, 0, 118552, 0, 0, 5406, 43127, 120007, 0, - 3590, 129874, 0, 0, 0, 42016, 0, 0, 121002, 0, 7742, 0, 66562, 71323, 0, - 0, 5310, 0, 123625, 0, 43594, 0, 128260, 66723, 0, 73816, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1326, 128723, 0, 0, 74519, 0, 0, 0, 0, 71308, 0, 5410, 5783, - 0, 8403, 5400, 120526, 0, 128863, 0, 0, 0, 64412, 0, 0, 5587, 42865, - 71858, 0, 0, 129854, 0, 113785, 0, 120755, 0, 69738, 0, 74867, 10461, - 12103, 0, 0, 70701, 0, 0, 0, 0, 0, 94009, 0, 2760, 0, 8816, 41515, 0, - 11802, 0, 7585, 910, 0, 0, 0, 3658, 83386, 120525, 0, 7617, 0, 12888, 0, - 0, 64631, 0, 41514, 11097, 5703, 0, 41517, 41504, 41519, 0, 70104, 0, - 65864, 0, 120533, 0, 121037, 0, 0, 43553, 120774, 0, 0, 0, 0, 0, 1578, 0, - 43449, 0, 0, 8225, 121191, 94024, 72799, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 110655, 0, 110656, 121247, 72213, 0, 110658, 0, 74997, 0, 3195, 10999, - 983570, 7897, 0, 1203, 74396, 0, 64544, 0, 0, 0, 2877, 0, 0, 0, 121112, - 0, 0, 128977, 119607, 0, 0, 0, 0, 983623, 0, 0, 0, 0, 0, 0, 0, 0, 983078, - 0, 0, 0, 9939, 0, 0, 0, 0, 0, 0, 0, 10714, 0, 0, 0, 0, 0, 67738, 0, - 74038, 0, 42897, 0, 0, 0, 0, 0, 0, 7730, 0, 0, 0, 11163, 0, 0, 0, 113701, - 4966, 128802, 70674, 129468, 123207, 3841, 0, 0, 983231, 77886, 0, 4972, - 0, 64699, 0, 0, 0, 0, 0, 12705, 10203, 9608, 0, 0, 11962, 121397, 0, - 1196, 67684, 0, 777, 0, 0, 65271, 0, 0, 0, 0, 64824, 983195, 0, 9454, - 63778, 8658, 0, 0, 2705, 0, 64894, 0, 0, 11986, 92636, 0, 8280, 0, 2701, - 0, 0, 0, 0, 0, 9809, 0, 0, 0, 0, 0, 63761, 1748, 0, 65719, 121078, 0, 0, - 0, 55244, 3061, 0, 63765, 63787, 0, 41520, 0, 7694, 0, 8896, 63768, - 55282, 0, 127781, 0, 0, 63807, 1591, 0, 6386, 118554, 0, 0, 0, 983200, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 68289, 0, 0, 7624, 67487, 10996, 92247, 10609, 0, - 127181, 10987, 0, 70370, 3894, 0, 0, 0, 0, 493, 0, 0, 1717, 12228, 479, - 917941, 129347, 129473, 917935, 917939, 917924, 917932, 92303, 64315, - 92170, 0, 83522, 6233, 42681, 83525, 83518, 83519, 64911, 83521, 0, 0, - 83516, 83517, 129843, 8378, 11632, 0, 0, 7323, 0, 120771, 0, 0, 0, 0, - 120904, 83526, 0, 128710, 92672, 0, 0, 0, 0, 0, 0, 0, 63806, 63800, 0, 0, - 0, 63798, 63803, 244, 11542, 0, 0, 73761, 0, 12669, 120310, 0, 0, 0, 0, - 120680, 71908, 0, 0, 8612, 0, 0, 0, 0, 0, 64662, 125056, 1360, 248, 0, - 63797, 0, 63794, 0, 7292, 983685, 63756, 42786, 74957, 0, 12663, 0, 0, 0, - 0, 0, 0, 0, 4579, 0, 0, 0, 0, 0, 0, 71130, 65545, 9602, 8623, 0, 128052, - 0, 0, 0, 0, 0, 0, 0, 659, 6098, 0, 12234, 83511, 83512, 8311, 83514, - 7669, 83508, 83509, 83510, 0, 0, 0, 0, 983951, 0, 0, 2323, 0, 2319, - 77917, 120900, 77916, 2311, 83077, 4415, 1586, 68050, 0, 128724, 83020, - 2309, 83022, 8173, 83013, 83014, 83015, 83016, 0, 83010, 69275, 83012, - 9397, 0, 9395, 9396, 9393, 9394, 9391, 9392, 9389, 6209, 9387, 9388, - 9385, 9386, 9383, 9384, 0, 0, 0, 0, 0, 11259, 0, 0, 0, 2313, 0, 119661, - 0, 0, 0, 0, 10570, 65776, 110968, 0, 83006, 83007, 11998, 83009, 83002, - 83003, 83004, 66406, 0, 128780, 83000, 11818, 9381, 9382, 9379, 9380, - 9377, 9378, 9375, 9376, 1683, 9374, 0, 9372, 0, 0, 0, 0, 127801, 0, - 42029, 11079, 0, 43451, 42032, 0, 0, 118666, 0, 5005, 0, 0, 42030, 5007, - 78828, 126210, 0, 4951, 110776, 0, 110775, 0, 43309, 121222, 92172, 0, - 92334, 0, 9548, 0, 119138, 71896, 0, 0, 0, 0, 0, 0, 65691, 65580, 64361, - 10496, 0, 0, 0, 917975, 0, 0, 41046, 0, 0, 0, 13177, 0, 64703, 0, 43499, - 3389, 10589, 0, 11208, 120719, 78395, 73964, 78393, 78392, 78391, 11314, - 8281, 113732, 113667, 113745, 9076, 8862, 69743, 41052, 78397, 64766, - 69821, 0, 0, 0, 82992, 82994, 10671, 82998, 82987, 82989, 82990, 6303, - 113664, 498, 64471, 82986, 129901, 0, 9349, 0, 0, 119343, 8031, 2249, 0, - 128999, 3231, 0, 6422, 0, 0, 119339, 2537, 78405, 41429, 78403, 78401, - 78399, 0, 0, 41433, 4719, 41431, 0, 78411, 5211, 41428, 78407, 82983, - 1772, 0, 0, 82979, 66850, 64812, 82982, 82975, 68767, 82977, 82978, 0, 0, - 0, 0, 41064, 70368, 9663, 66838, 129381, 12304, 125113, 0, 41062, 66847, - 0, 0, 41061, 70454, 0, 127187, 83049, 83050, 41509, 83054, 83045, 83046, - 83047, 83048, 0, 43184, 41507, 1958, 0, 66816, 41506, 0, 0, 0, 120717, 0, - 0, 0, 74349, 72113, 8008, 0, 0, 0, 65083, 6839, 0, 126517, 73803, 127055, - 127056, 3508, 127058, 127059, 78038, 0, 120932, 0, 6411, 128115, 0, 0, - 128832, 100930, 0, 0, 0, 0, 0, 129776, 128546, 0, 0, 120914, 0, 0, 0, 0, - 917822, 128810, 983676, 65599, 0, 9966, 12607, 4948, 128070, 0, 128149, - 0, 0, 6207, 0, 6117, 73916, 0, 0, 0, 0, 68244, 41511, 0, 129489, 127304, - 0, 121289, 0, 118618, 83031, 83032, 0, 41556, 0, 0, 0, 128571, 73504, 0, - 0, 118645, 41510, 7953, 0, 0, 41513, 0, 0, 0, 83038, 83039, 83040, 83041, - 83034, 83035, 848, 9868, 983150, 6424, 118625, 83033, 0, 0, 0, 0, 118539, - 0, 893, 64576, 13299, 0, 0, 71998, 71447, 0, 0, 0, 0, 8903, 0, 0, 0, - 8099, 0, 0, 0, 0, 0, 0, 0, 0, 113713, 0, 0, 0, 0, 0, 83027, 41483, 83029, - 83030, 83023, 83024, 69436, 64836, 194756, 41485, 194758, 194757, 194760, - 41482, 42737, 64588, 0, 127787, 0, 10014, 0, 0, 194763, 194762, 68785, - 194764, 194767, 194766, 0, 0, 0, 11377, 122634, 0, 983811, 0, 0, 0, 9776, - 0, 93824, 5215, 194750, 13227, 8758, 194751, 128744, 0, 0, 5363, 12957, - 0, 0, 129051, 129526, 6421, 0, 0, 121304, 0, 0, 0, 0, 92625, 119070, - 67895, 983962, 0, 68608, 6482, 0, 0, 11945, 0, 0, 8838, 0, 4025, 10709, - 0, 2108, 0, 73929, 0, 0, 10617, 194737, 128031, 194739, 194738, 68614, - 194740, 68611, 9924, 129952, 194744, 0, 0, 0, 3277, 0, 4947, 41055, 0, - 194722, 129930, 194724, 194723, 64626, 194725, 42266, 194727, 8371, - 194729, 127028, 12806, 41492, 0, 0, 73930, 194731, 124140, 41054, 1078, - 194735, 194734, 41057, 0, 0, 0, 0, 0, 92210, 73009, 0, 41496, 0, 9165, - 1572, 0, 129712, 0, 128635, 9215, 9330, 129809, 10032, 41745, 43183, - 6401, 5831, 0, 0, 0, 8056, 0, 65681, 92377, 0, 0, 0, 121048, 0, 118887, - 6408, 0, 0, 5661, 82972, 82973, 3603, 0, 82967, 3548, 82969, 82970, 0, - 82964, 82965, 9918, 118787, 11321, 0, 0, 0, 128992, 0, 0, 0, 0, 0, 0, - 41558, 41471, 0, 8158, 41561, 41472, 0, 0, 194672, 43762, 77927, 6701, - 41559, 1896, 66256, 66248, 194680, 5665, 0, 194681, 0, 0, 0, 74352, 0, - 5664, 127895, 194682, 12310, 5662, 194687, 194686, 73924, 1121, 82953, - 82955, 0, 74378, 0, 0, 74966, 0, 71892, 0, 69413, 194667, 8627, 194669, - 10110, 194671, 42024, 6420, 42028, 0, 10509, 2795, 73923, 0, 69231, 0, - 6275, 93957, 917927, 124972, 194655, 127786, 6423, 129733, 0, 0, 68526, - 12823, 0, 0, 42026, 42017, 0, 7524, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12691, - 68072, 42722, 69877, 82956, 78655, 78661, 82959, 78662, 41265, 41065, - 1795, 917809, 118791, 10587, 0, 917807, 0, 194640, 0, 12946, 194641, - 71921, 194643, 9169, 70372, 194648, 194647, 68202, 194649, 73990, 65111, - 0, 748, 41067, 6234, 194651, 9990, 72795, 194652, 194629, 194628, 194631, - 194630, 67896, 194632, 917812, 3593, 82948, 82949, 82950, 82951, 82944, - 69729, 82946, 82947, 194638, 194637, 0, 581, 0, 42929, 7944, 0, 0, 0, 0, - 0, 0, 72143, 0, 10119, 6415, 42893, 0, 69702, 0, 0, 11375, 0, 0, 0, 412, - 92765, 42928, 42880, 43587, 0, 0, 0, 0, 0, 0, 122638, 0, 0, 0, 65854, - 92508, 65811, 75024, 194624, 194627, 9344, 8826, 92916, 0, 125090, 74781, - 0, 0, 129582, 0, 0, 0, 127783, 0, 0, 0, 0, 10133, 92755, 0, 0, 0, 0, - 78414, 78413, 118950, 74011, 0, 0, 121080, 0, 1908, 127378, 4918, 0, 0, - 70709, 67825, 6250, 0, 10811, 78412, 11339, 4914, 0, 0, 118971, 4917, - 70686, 0, 0, 4912, 69722, 73845, 0, 0, 129527, 0, 0, 0, 118986, 0, 0, - 74317, 0, 8319, 194714, 194717, 10960, 72196, 8305, 12573, 983620, 72193, - 0, 13202, 0, 12582, 0, 72198, 69856, 0, 0, 78598, 0, 72195, 0, 65802, - 74822, 7698, 12708, 74045, 0, 0, 70460, 4913, 127990, 0, 123539, 0, 0, - 12728, 129980, 128895, 0, 101281, 0, 130038, 0, 101283, 0, 12588, 8821, - 6153, 194705, 78900, 194707, 194710, 194709, 194712, 194711, 118854, - 194713, 651, 0, 0, 0, 0, 0, 78468, 78469, 69433, 78467, 69614, 74905, - 194695, 78461, 194697, 194696, 0, 4716, 43277, 0, 2185, 78475, 128592, - 120928, 194700, 55264, 194702, 12732, 0, 12707, 0, 0, 0, 0, 121417, 8479, - 4151, 0, 0, 0, 0, 0, 0, 0, 0, 113799, 0, 74050, 0, 0, 0, 0, 0, 129467, - 12278, 0, 129507, 0, 2700, 12576, 7842, 0, 67471, 0, 2699, 0, 0, 2985, 0, - 126475, 0, 129873, 119314, 0, 119312, 9827, 101292, 119311, 101291, - 119309, 119306, 11481, 118718, 119305, 0, 35, 78481, 78482, 66694, 78480, - 78477, 78478, 0, 0, 64257, 0, 0, 0, 78485, 78486, 78483, 4272, 0, 0, - 40965, 0, 12704, 78487, 983568, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5244, 4189, - 94108, 0, 127948, 4188, 1879, 0, 0, 0, 43743, 71974, 8873, 2279, 0, 0, 0, - 12574, 12735, 92749, 92753, 983921, 0, 0, 75001, 0, 0, 0, 12578, 12720, - 128628, 101088, 0, 12346, 128596, 101089, 0, 0, 7251, 0, 0, 118850, - 73025, 0, 0, 0, 0, 0, 12564, 66457, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101131, - 0, 41564, 10976, 0, 121223, 0, 0, 10054, 9197, 120618, 0, 9012, 65737, - 74420, 0, 13215, 12730, 0, 0, 0, 0, 816, 0, 101123, 122664, 83191, 0, 0, - 92752, 101120, 4715, 94107, 94106, 71075, 0, 0, 0, 67729, 0, 307, 0, - 9585, 0, 0, 0, 101255, 0, 125267, 0, 70727, 65567, 101238, 75006, 101231, - 983909, 0, 12236, 41419, 101259, 194621, 101248, 75003, 194622, 73675, - 120957, 41421, 75005, 4462, 118569, 126599, 983911, 821, 0, 2498, 5800, - 100834, 100833, 1760, 67483, 4469, 64377, 100840, 100839, 0, 757, 1185, - 118558, 100841, 0, 10628, 100842, 68849, 100844, 43971, 100846, 100849, - 64763, 0, 7713, 0, 0, 0, 4380, 194608, 128073, 194610, 194609, 194612, - 862, 65626, 194613, 65627, 65629, 5137, 194617, 0, 0, 0, 65069, 7566, - 64688, 67143, 118592, 100823, 100822, 100825, 4748, 92228, 100826, - 100829, 42260, 129494, 64107, 0, 0, 0, 0, 128189, 0, 194604, 13137, 8775, - 127945, 123633, 194607, 0, 8410, 4454, 194585, 0, 92542, 4449, 92330, - 127064, 75022, 92761, 70664, 194589, 339, 194591, 194590, 0, 70662, 0, - 100830, 41543, 0, 0, 0, 41542, 127066, 8916, 6705, 0, 129296, 0, 0, 0, 0, - 0, 41548, 6729, 119329, 0, 7348, 0, 0, 7537, 0, 11819, 0, 0, 123624, - 71269, 0, 7344, 100808, 129073, 9780, 0, 11117, 74993, 0, 194578, 10483, - 194580, 194579, 194582, 194581, 68781, 125114, 100820, 100819, 0, 4211, - 1259, 7517, 0, 0, 194561, 70827, 194563, 194562, 641, 5219, 94034, - 194566, 11064, 194568, 0, 129820, 0, 0, 0, 0, 100812, 100811, 100814, - 100813, 100816, 100815, 100818, 100817, 100798, 100797, 41410, 100799, - 64262, 0, 41407, 75000, 0, 0, 93812, 0, 0, 72803, 74999, 78897, 0, 0, - 67675, 0, 0, 0, 0, 43647, 0, 0, 100792, 100791, 100794, 100793, 100796, - 100795, 983276, 74630, 11933, 0, 0, 41903, 67892, 11001, 100801, 42255, - 100803, 100802, 100805, 41905, 100807, 100806, 10775, 9793, 0, 0, 74452, - 0, 983063, 42535, 0, 64529, 41408, 42853, 0, 0, 42674, 118915, 0, 0, - 983807, 0, 70838, 0, 0, 0, 64506, 0, 66738, 4747, 100783, 69844, 100785, - 5832, 0, 0, 5141, 42600, 124147, 0, 0, 0, 0, 0, 93790, 0, 7657, 0, 71132, - 74137, 0, 128362, 73682, 73681, 859, 0, 0, 0, 6059, 126985, 55235, 0, 0, - 0, 0, 0, 100787, 11488, 72838, 100788, 0, 100790, 10558, 0, 124144, - 118646, 126090, 71069, 0, 0, 1788, 0, 0, 0, 0, 119571, 92822, 9028, 0, - 69234, 73665, 0, 9905, 73556, 41242, 70086, 0, 74109, 100765, 100764, - 100767, 100766, 70830, 83184, 70082, 3940, 0, 43754, 0, 128188, 8665, 0, - 0, 0, 1653, 100775, 42406, 100777, 100780, 70825, 120523, 0, 8815, 0, - 65046, 0, 42445, 0, 11180, 119318, 119315, 68454, 42485, 0, 0, 8211, - 42293, 983602, 0, 0, 0, 0, 65385, 100771, 42332, 100773, 78431, 78432, - 78423, 78430, 78420, 10022, 65387, 78419, 65384, 0, 0, 0, 65386, 0, - 11248, 0, 43198, 64751, 0, 0, 0, 0, 0, 0, 101102, 7363, 0, 0, 119323, - 119324, 100752, 100751, 0, 119320, 0, 983632, 0, 8237, 0, 0, 0, 0, 0, 0, - 9914, 0, 100763, 100762, 120009, 6351, 119993, 92740, 68766, 0, 120010, - 41243, 0, 74108, 11467, 120165, 119998, 4358, 0, 6353, 0, 0, 0, 93045, - 1710, 0, 0, 92237, 0, 49, 73871, 120005, 78671, 0, 78672, 9741, 78443, - 78444, 78441, 43443, 78439, 78440, 69244, 78438, 3470, 0, 0, 92814, 0, 0, - 78445, 0, 1072, 78457, 78452, 78454, 74230, 78451, 78447, 78449, 1080, 0, - 74100, 0, 1101, 68404, 78458, 78459, 71082, 0, 1086, 1869, 0, 0, 0, - 65458, 0, 0, 41988, 0, 1091, 0, 7977, 0, 66992, 0, 0, 0, 92758, 0, 0, 0, - 0, 0, 71255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64582, 0, 0, 70794, 0, 120989, - 128495, 74106, 0, 66883, 0, 0, 0, 0, 0, 0, 0, 92553, 43752, 110592, 0, - 71249, 120886, 0, 0, 0, 0, 6063, 100857, 101221, 917995, 6053, 74096, 0, - 0, 74169, 13100, 0, 917999, 0, 71081, 0, 70387, 6055, 7800, 4279, 8490, - 120114, 120111, 64786, 8602, 120110, 83389, 92204, 0, 0, 74961, 0, - 120117, 120118, 120099, 120100, 65087, 64402, 3674, 120096, 0, 120094, - 120107, 118624, 120105, 10107, 42159, 42870, 120101, 69632, 0, 0, 43281, - 127078, 0, 74098, 0, 0, 126497, 74099, 129056, 0, 0, 0, 121123, 5847, - 125258, 0, 0, 0, 0, 0, 66592, 64469, 71698, 19966, 0, 42561, 0, 129170, - 66854, 8120, 75042, 0, 0, 0, 0, 0, 0, 126068, 8369, 0, 0, 122912, 3369, - 0, 121094, 0, 0, 69238, 10495, 121365, 0, 557, 9457, 0, 0, 121054, 73880, - 127220, 0, 74937, 74094, 0, 0, 119001, 92171, 127219, 128175, 127939, - 120424, 0, 127214, 2109, 67893, 127211, 69656, 127217, 10604, 127215, 0, - 0, 0, 129727, 126561, 0, 0, 0, 0, 1618, 0, 0, 83175, 10430, 0, 0, 13063, - 917585, 0, 92982, 113666, 0, 78390, 83489, 12060, 0, 113669, 0, 6329, 0, - 0, 0, 74395, 2707, 8309, 0, 127054, 78398, 0, 2697, 0, 78396, 127057, - 2695, 0, 0, 68334, 0, 0, 0, 72325, 2693, 74091, 0, 0, 2703, 113729, - 70283, 41918, 983169, 127542, 8687, 127543, 12178, 43361, 92540, 64075, - 110705, 5248, 110703, 120538, 6427, 0, 0, 0, 0, 110710, 0, 74990, 74989, - 70703, 127031, 0, 9873, 0, 0, 0, 64762, 2053, 0, 6591, 9340, 0, 1589, 0, - 296, 67712, 128315, 12766, 118931, 74370, 120417, 2414, 128068, 43829, - 111202, 74836, 0, 12579, 0, 12575, 6416, 5656, 0, 13262, 65590, 5299, - 983702, 0, 5449, 1252, 0, 78404, 69748, 74369, 65373, 5295, 0, 121066, - 1223, 1642, 78408, 0, 12158, 5303, 0, 120546, 41413, 3212, 127025, 3211, - 74810, 41425, 127029, 0, 74450, 9728, 0, 10924, 74778, 6636, 73552, - 129884, 0, 0, 129882, 9519, 0, 0, 129106, 101110, 68780, 0, 0, 0, 119182, - 0, 12104, 77942, 77951, 9004, 0, 74249, 10230, 0, 0, 0, 77947, 0, 69679, - 121475, 9890, 125049, 12971, 0, 92556, 0, 67903, 70051, 983924, 0, 0, - 9635, 12600, 0, 0, 0, 118900, 6469, 0, 101113, 65304, 4679, 101114, - 64300, 64867, 6531, 101118, 101099, 101098, 92813, 101100, 42916, 0, 0, - 0, 0, 0, 0, 4445, 72296, 0, 11533, 0, 3416, 124112, 0, 0, 0, 78566, 0, 0, - 101091, 92815, 101093, 5447, 72140, 70752, 101097, 101096, 0, 0, 0, - 64448, 0, 43920, 70677, 0, 6232, 101101, 101104, 101103, 43608, 101105, - 101108, 6538, 4335, 0, 3941, 74986, 11061, 0, 74988, 74987, 0, 12155, - 128278, 0, 0, 0, 0, 74578, 0, 65832, 0, 129459, 70789, 0, 125050, 0, 0, - 350, 10951, 101081, 509, 101083, 101086, 101085, 0, 0, 0, 917540, 0, - 100905, 110970, 12162, 64741, 0, 9354, 0, 70802, 100901, 2496, 11516, - 944, 128238, 0, 0, 1438, 0, 0, 120185, 70785, 1220, 917952, 93844, 0, 0, - 5008, 42630, 70787, 101087, 2229, 68206, 564, 0, 312, 0, 0, 0, 70797, - 8877, 269, 0, 128065, 9617, 0, 0, 100910, 0, 0, 10862, 0, 0, 41416, 0, - 4173, 0, 0, 0, 1906, 983854, 41418, 74073, 101068, 101067, 41415, 69622, - 9582, 0, 64287, 0, 0, 11428, 1730, 0, 0, 19918, 10469, 101076, 101079, - 68088, 0, 101080, 72342, 0, 129692, 0, 6129, 0, 0, 0, 0, 7874, 0, 0, - 11206, 13136, 118529, 129305, 0, 64374, 74925, 0, 73892, 0, 101073, - 101072, 101075, 74960, 9228, 101054, 101057, 101056, 5240, 9811, 0, - 101060, 129718, 0, 0, 74079, 65873, 0, 0, 0, 9501, 0, 68081, 72808, - 65465, 64654, 7467, 0, 0, 83460, 10040, 0, 3096, 0, 101053, 101052, - 68820, 83461, 0, 0, 0, 0, 0, 0, 83377, 0, 68801, 0, 101062, 101061, - 101064, 101063, 0, 8637, 70741, 0, 77983, 77969, 11471, 43554, 0, 77968, - 0, 0, 0, 2426, 12042, 0, 0, 0, 3961, 12115, 129633, 0, 77972, 64561, 0, - 4981, 74644, 129558, 0, 0, 42686, 77976, 128776, 64686, 0, 77958, 7589, - 0, 0, 3237, 0, 68215, 0, 8541, 127157, 71067, 120174, 0, 0, 0, 0, 0, - 43555, 0, 0, 10060, 111261, 100917, 0, 0, 0, 64877, 0, 0, 8614, 65220, - 41493, 0, 0, 0, 43780, 0, 0, 70689, 0, 0, 0, 0, 0, 0, 4012, 10395, 0, 0, - 111253, 126511, 111254, 125051, 695, 739, 696, 7611, 0, 42755, 68421, - 9227, 7506, 7510, 67493, 691, 738, 7511, 7512, 7515, 7501, 688, 41847, - 690, 2548, 737, 974, 43386, 0, 0, 0, 0, 0, 0, 65860, 0, 7051, 69777, - 4682, 0, 983096, 6406, 4685, 0, 0, 10347, 4680, 6341, 0, 0, 92607, 74325, - 0, 123555, 0, 0, 0, 0, 0, 0, 43505, 92468, 11718, 42373, 11714, 0, 0, - 129567, 11717, 0, 10594, 129732, 11712, 122962, 0, 10967, 0, 0, 0, 66632, - 118647, 0, 0, 0, 1735, 0, 11134, 2363, 983136, 0, 0, 70695, 128032, 0, - 7491, 7495, 7580, 7496, 7497, 7584, 121478, 127853, 0, 0, 70025, 0, 8498, - 0, 8949, 3065, 0, 0, 0, 0, 0, 0, 11713, 0, 64939, 0, 6418, 4543, 0, 0, 0, - 74800, 0, 0, 0, 0, 0, 0, 0, 12282, 3165, 0, 0, 64556, 0, 9238, 0, 68063, - 0, 0, 0, 65438, 0, 128525, 0, 119268, 0, 0, 12900, 67489, 10950, 0, 0, 0, - 41400, 126636, 119664, 0, 42232, 0, 1744, 0, 41402, 0, 0, 0, 41399, 0, - 125028, 0, 0, 12690, 0, 0, 43672, 0, 0, 0, 100870, 11315, 0, 278, 121204, - 41405, 129345, 0, 10077, 129650, 70667, 0, 0, 0, 68210, 0, 0, 11189, - 70657, 0, 0, 0, 7934, 0, 93829, 120940, 0, 0, 122971, 0, 0, 0, 6413, - 6550, 0, 1940, 2809, 43637, 70045, 0, 0, 10678, 0, 0, 0, 129701, 78804, - 6403, 6556, 78803, 0, 0, 123557, 0, 0, 0, 123553, 0, 3742, 74408, 3959, - 0, 0, 917969, 123565, 0, 128024, 0, 123558, 127956, 0, 0, 0, 6855, 4676, - 983049, 9210, 0, 78143, 983922, 0, 78168, 983100, 11540, 43546, 6692, 0, - 0, 0, 0, 9083, 0, 0, 78144, 128515, 0, 9677, 0, 70867, 74175, 0, 74070, - 0, 0, 365, 0, 43027, 0, 0, 128236, 0, 119574, 70284, 13151, 0, 0, 127935, - 127950, 544, 13249, 119018, 0, 120846, 0, 0, 73671, 65339, 73000, 2211, - 0, 0, 0, 0, 0, 0, 0, 0, 128037, 0, 0, 0, 0, 0, 0, 0, 127188, 92977, - 69708, 9638, 0, 100878, 0, 0, 0, 74545, 128820, 128819, 75062, 128963, 0, - 0, 0, 11264, 43994, 0, 0, 0, 1311, 0, 0, 0, 0, 13068, 0, 0, 78164, 78155, - 0, 949, 0, 0, 0, 78176, 69709, 78177, 63828, 0, 0, 118629, 70282, 0, 0, - 0, 64822, 0, 6530, 983275, 0, 70493, 0, 129325, 0, 0, 4431, 118839, - 127490, 983760, 73667, 127986, 0, 10336, 10400, 0, 0, 92959, 0, 0, 0, - 42270, 128880, 6428, 0, 0, 0, 0, 43455, 0, 43526, 100888, 12835, 129501, - 9493, 0, 0, 11793, 0, 127897, 74394, 0, 10653, 0, 0, 0, 0, 6560, 7016, - 74274, 983627, 43556, 3929, 123615, 6614, 2768, 0, 65609, 0, 11811, - 129696, 0, 118615, 127513, 0, 6554, 0, 6305, 66283, 4675, 118826, 78552, - 0, 0, 74361, 0, 0, 68108, 0, 0, 92232, 0, 93022, 7392, 8230, 9365, - 983742, 0, 0, 0, 0, 42925, 0, 0, 122965, 0, 229, 43834, 119884, 0, 43552, - 119881, 119880, 119883, 119882, 119877, 119876, 119879, 119878, 119873, - 119872, 119875, 119874, 0, 0, 0, 0, 0, 66352, 0, 0, 0, 128663, 0, 12239, - 0, 0, 10432, 12097, 0, 194815, 1233, 78179, 0, 127200, 0, 66395, 0, 0, - 129504, 0, 0, 92342, 0, 2388, 92555, 119868, 119871, 119870, 119865, 895, - 92668, 119866, 64889, 7143, 119863, 119862, 0, 0, 69983, 0, 74376, 3053, - 2168, 0, 2047, 0, 0, 0, 121279, 67985, 194801, 92600, 194803, 194802, - 194805, 194804, 194807, 194806, 129134, 194808, 0, 0, 0, 10473, 129331, - 0, 194810, 129806, 194812, 129813, 194814, 194813, 123195, 43528, 69673, - 194791, 0, 194793, 1912, 120779, 10306, 10370, 0, 0, 8867, 10250, 10258, - 10274, 1635, 120152, 0, 0, 0, 129379, 0, 0, 9919, 120148, 559, 128157, - 41825, 127975, 92989, 0, 74016, 194781, 6542, 41957, 7318, 124126, 0, - 41956, 65749, 65750, 65751, 121323, 64487, 0, 0, 10223, 42062, 100640, - 101195, 125044, 3668, 65754, 43560, 12226, 0, 93973, 194784, 41959, - 194786, 194785, 194788, 43618, 65747, 10937, 2962, 0, 2953, 10062, 65745, - 71457, 8921, 66013, 129370, 0, 194769, 194768, 43409, 194770, 2949, - 194772, 194775, 194774, 2958, 194776, 74868, 2300, 2951, 120061, 0, - 120043, 194778, 0, 120051, 194779, 120056, 120065, 70798, 120048, 0, - 120062, 120055, 71989, 100668, 0, 0, 71985, 0, 71992, 70796, 127818, 0, - 0, 64890, 0, 43630, 11336, 799, 0, 10276, 10308, 10372, 917541, 0, 0, - 10252, 10260, 68220, 55284, 125225, 0, 10384, 0, 0, 0, 64523, 129744, 0, - 65736, 0, 0, 0, 0, 0, 0, 0, 124912, 43549, 65738, 42150, 65739, 0, 78195, - 10288, 10320, 0, 10596, 129829, 67673, 65045, 121283, 78198, 2049, 10098, - 0, 122904, 127943, 10264, 10280, 10312, 10376, 7013, 0, 69504, 0, 0, - 66375, 0, 4862, 0, 6537, 0, 128335, 3914, 92178, 93976, 9065, 64816, 0, - 72218, 73026, 0, 0, 72139, 4694, 11420, 4690, 0, 0, 983211, 4693, 0, 0, - 0, 4688, 0, 0, 128892, 0, 8238, 3110, 0, 983939, 0, 6528, 0, 0, 0, 218, - 0, 1520, 129577, 70039, 0, 983594, 0, 120167, 78167, 10088, 6548, 100786, - 0, 0, 0, 8888, 0, 124954, 0, 0, 126593, 68876, 0, 0, 0, 0, 0, 0, 0, 4689, - 43541, 77954, 120157, 0, 120156, 78810, 120163, 0, 0, 0, 0, 78121, 0, 0, - 11450, 0, 71900, 92613, 0, 121317, 74622, 128720, 9244, 0, 0, 127763, 0, - 0, 0, 0, 0, 0, 71084, 0, 0, 0, 0, 10513, 0, 0, 0, 52, 119178, 0, 0, - 93961, 0, 0, 4812, 0, 0, 0, 0, 0, 0, 128425, 0, 6850, 0, 77959, 10170, - 120450, 6544, 0, 0, 69782, 121517, 0, 0, 65258, 10369, 0, 1585, 74014, - 10249, 422, 1500, 2036, 986, 0, 64394, 69502, 5599, 917981, 2494, 0, 0, - 74021, 983896, 78203, 127808, 0, 72871, 65102, 8961, 74305, 10243, 10245, - 128170, 0, 0, 0, 0, 0, 2508, 129591, 120440, 0, 120439, 0, 0, 0, 0, 0, 0, - 64533, 983187, 0, 0, 74008, 0, 0, 43375, 0, 2504, 0, 121313, 0, 983941, - 6943, 0, 5859, 100677, 0, 0, 72873, 983945, 0, 0, 983923, 92390, 2753, - 1936, 2153, 67701, 2751, 12662, 2763, 8953, 0, 10731, 0, 7052, 0, 0, 0, - 0, 119899, 0, 66675, 0, 119897, 0, 71053, 0, 119903, 0, 67829, 7899, - 119901, 71119, 43798, 7072, 119902, 122898, 11260, 0, 71059, 0, 0, 212, - 0, 12350, 0, 0, 0, 0, 0, 128402, 2759, 0, 0, 93064, 0, 0, 0, 1291, 0, - 195065, 121318, 119911, 0, 119910, 0, 12062, 0, 121216, 0, 129124, - 121044, 120611, 8246, 128874, 0, 0, 0, 0, 0, 73962, 0, 0, 43524, 0, - 64426, 0, 0, 0, 0, 65664, 6693, 0, 0, 8674, 0, 128812, 0, 11846, 70690, - 121461, 69395, 4811, 0, 5986, 0, 3046, 74480, 5985, 0, 0, 0, 0, 12187, - 83148, 71041, 5984, 0, 93817, 4393, 126264, 120206, 917599, 0, 0, 0, - 93806, 93805, 0, 3491, 0, 67146, 0, 93819, 0, 72428, 0, 0, 0, 124968, - 41284, 126228, 0, 0, 41287, 0, 100689, 0, 0, 92189, 0, 0, 219, 120874, 0, - 0, 0, 68485, 119672, 43241, 0, 7147, 73554, 0, 0, 0, 0, 0, 64610, 11804, - 0, 7149, 64808, 0, 0, 0, 92301, 73690, 0, 5253, 0, 0, 0, 0, 129045, - 983596, 11098, 68433, 0, 120484, 111009, 0, 0, 0, 0, 0, 70801, 100779, 0, - 128198, 9604, 0, 130036, 0, 0, 118941, 64392, 0, 118684, 0, 0, 41974, - 126262, 0, 0, 0, 129818, 0, 129833, 0, 0, 0, 0, 0, 983243, 5308, 0, 290, - 0, 125278, 128382, 2792, 0, 0, 120521, 0, 126237, 0, 126099, 0, 0, 0, 0, - 128503, 0, 0, 72816, 0, 0, 0, 92671, 0, 195061, 42646, 7606, 2591, 73896, - 0, 43513, 64482, 0, 0, 65270, 0, 0, 983701, 9112, 0, 113763, 9490, 0, 0, - 0, 0, 0, 9071, 0, 0, 0, 0, 74607, 0, 2535, 65504, 43602, 0, 0, 71256, - 2248, 0, 123147, 11845, 11006, 92315, 7807, 8073, 0, 10629, 0, 74088, 0, - 10823, 0, 113762, 8762, 0, 69689, 123536, 43969, 65047, 10737, 3463, - 67467, 129585, 66645, 0, 4815, 0, 0, 12345, 983761, 0, 5195, 129808, 0, - 66639, 0, 0, 66941, 0, 92759, 92385, 1262, 0, 6561, 19939, 0, 0, 100772, - 123160, 69269, 0, 100774, 0, 0, 0, 0, 0, 0, 67511, 0, 0, 0, 0, 0, 0, - 5702, 3655, 0, 8430, 0, 68807, 0, 0, 121137, 0, 0, 5254, 0, 0, 124917, 0, - 119107, 5129, 0, 70816, 0, 92280, 5614, 0, 0, 11720, 0, 11721, 70804, - 4798, 0, 120541, 66038, 4793, 67851, 7352, 0, 0, 0, 0, 917600, 0, 300, 0, - 0, 128575, 92660, 0, 0, 2562, 70156, 120856, 0, 0, 92738, 0, 0, 127820, - 71093, 0, 127969, 128221, 0, 3424, 93843, 0, 0, 7074, 70873, 128519, 0, - 0, 10832, 0, 0, 69852, 72430, 0, 0, 0, 0, 0, 176, 0, 0, 0, 0, 0, 1215, 0, - 5744, 0, 66440, 0, 0, 0, 42881, 0, 8980, 118988, 67861, 8844, 7433, 0, 0, - 4278, 124925, 0, 0, 70821, 9312, 4348, 0, 128401, 65946, 0, 7087, 5255, - 0, 661, 0, 0, 0, 0, 0, 0, 0, 121009, 73694, 0, 123154, 0, 73688, 0, - 127179, 3621, 83325, 66666, 72968, 0, 6562, 12928, 0, 73991, 0, 0, 11383, - 0, 0, 65588, 120739, 0, 0, 0, 0, 0, 0, 0, 0, 11436, 2070, 64, 110824, 0, - 10291, 10323, 10387, 0, 0, 0, 42008, 9708, 42710, 0, 42011, 0, 92164, 0, - 0, 1702, 1240, 128383, 6286, 9689, 111080, 0, 0, 0, 1765, 0, 0, 92373, 0, - 0, 0, 8401, 72991, 42014, 0, 67237, 0, 0, 0, 0, 0, 0, 0, 70819, 0, 0, 0, - 0, 12667, 0, 0, 10147, 0, 127568, 126483, 72812, 0, 0, 0, 0, 123139, - 128968, 0, 64947, 0, 0, 0, 0, 10435, 11462, 0, 7084, 0, 0, 0, 0, 0, - 126084, 0, 66662, 0, 0, 0, 0, 125134, 0, 0, 77990, 263, 983747, 41288, - 127953, 0, 78387, 74340, 70313, 129140, 0, 0, 0, 42022, 71265, 0, 0, 0, - 0, 0, 0, 42020, 123146, 0, 6992, 42019, 0, 41290, 0, 12295, 126233, - 71304, 0, 120984, 71300, 120631, 5954, 64931, 69385, 100699, 198, 68453, - 78129, 0, 121351, 0, 70818, 13165, 7107, 0, 42804, 678, 72850, 118960, 0, - 72985, 42806, 42808, 0, 0, 2097, 0, 120560, 70823, 0, 0, 3892, 68632, 0, - 6712, 917959, 0, 0, 0, 0, 123158, 69954, 0, 497, 12100, 5953, 92667, - 7796, 0, 43254, 0, 0, 11072, 5952, 1281, 43747, 0, 69380, 10677, 0, 0, 0, - 1859, 0, 72856, 3425, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65199, 1738, 0, - 122911, 0, 0, 0, 11101, 0, 0, 0, 0, 127002, 69651, 4436, 194683, 73984, - 6860, 70305, 64872, 128296, 0, 0, 0, 121377, 0, 6862, 0, 6861, 983109, 0, - 119109, 0, 70826, 319, 0, 43479, 73001, 0, 0, 12849, 0, 7640, 71083, - 9673, 0, 0, 0, 92670, 0, 92665, 113717, 41422, 0, 100708, 74941, 3772, 0, - 120660, 5011, 0, 0, 126587, 111315, 0, 0, 6677, 111312, 0, 41427, 64419, - 129445, 92262, 0, 70799, 0, 0, 0, 6106, 0, 41271, 6760, 983758, 4534, - 41270, 128876, 0, 0, 119561, 0, 0, 3671, 8976, 123177, 0, 41275, 0, - 128084, 55261, 0, 42013, 0, 568, 0, 41273, 0, 0, 6728, 0, 9715, 0, 0, - 121058, 74820, 0, 92268, 0, 194564, 11191, 43688, 128023, 0, 0, 0, - 126266, 0, 0, 0, 11958, 11165, 0, 125087, 0, 0, 66336, 127944, 0, 0, 0, - 0, 42858, 11789, 72878, 5557, 0, 69444, 7300, 0, 9467, 5558, 64486, - 43844, 0, 0, 6706, 10146, 0, 127185, 64566, 0, 0, 0, 0, 0, 0, 0, 4546, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 64528, 123136, 6307, 128966, 0, 7544, 0, 43469, - 111317, 0, 10152, 0, 65091, 0, 129047, 0, 0, 66652, 0, 0, 0, 0, 64823, - 5559, 0, 70711, 6702, 5556, 0, 0, 0, 0, 0, 11166, 0, 0, 5506, 0, 1911, - 73021, 0, 12598, 8845, 66698, 0, 73012, 123145, 73496, 2098, 0, 0, 0, - 66622, 194678, 0, 0, 0, 9898, 0, 0, 7552, 0, 0, 0, 7223, 65723, 0, 0, 0, - 7024, 65728, 127155, 1210, 0, 65175, 10184, 65726, 43654, 0, 0, 0, 38, - 65729, 66669, 0, 917948, 0, 0, 0, 0, 119837, 0, 74233, 73018, 119843, - 42860, 111301, 92576, 65721, 65722, 0, 0, 0, 0, 68843, 0, 68850, 0, - 92388, 92267, 128536, 65577, 42967, 0, 127518, 11650, 5013, 92663, 68810, - 92568, 118914, 6613, 74371, 0, 0, 122985, 0, 64714, 71479, 0, 983797, - 12120, 0, 0, 43124, 0, 0, 78037, 69263, 0, 126219, 0, 0, 1837, 125086, 0, - 0, 0, 127210, 4952, 65718, 64405, 5504, 65720, 65714, 65715, 65716, - 10403, 127005, 0, 41449, 0, 74028, 72019, 0, 119234, 1127, 455, 0, 0, - 72860, 3483, 0, 1989, 0, 69678, 9104, 0, 65375, 0, 0, 0, 1864, 0, 72810, - 8107, 2540, 0, 0, 11257, 128807, 119576, 0, 120999, 0, 73501, 8604, 0, 0, - 0, 0, 128270, 0, 0, 3115, 0, 10106, 120498, 118842, 101136, 0, 9631, 0, - 0, 0, 0, 0, 0, 0, 258, 129079, 0, 0, 0, 92292, 0, 70699, 0, 11478, 0, - 129640, 11522, 0, 8549, 0, 128430, 0, 0, 0, 0, 0, 0, 123140, 0, 0, 0, - 9221, 12590, 73048, 0, 0, 0, 67741, 111294, 12619, 0, 10154, 111266, - 74439, 2039, 0, 7446, 0, 111276, 10974, 458, 72831, 0, 0, 0, 11916, 0, 0, - 69671, 0, 121057, 12288, 0, 111288, 0, 111289, 983177, 0, 128199, 13080, - 0, 67828, 6610, 6030, 8059, 7508, 123170, 0, 0, 0, 0, 41278, 129393, - 118691, 128192, 41277, 64658, 984002, 101278, 6625, 983160, 19904, 0, 0, - 0, 0, 0, 0, 833, 0, 6369, 0, 0, 42664, 0, 0, 0, 0, 129765, 0, 6913, 933, - 1341, 68828, 6720, 0, 0, 983604, 0, 0, 7405, 128025, 0, 0, 0, 0, 0, 0, 0, - 70704, 0, 0, 0, 0, 9716, 0, 0, 0, 70719, 0, 0, 0, 0, 72862, 70687, 0, - 93987, 0, 0, 0, 70721, 9573, 0, 0, 111245, 83225, 83226, 6949, 126482, - 74061, 83222, 83223, 83224, 0, 19962, 83219, 83220, 0, 111233, 0, 42830, - 0, 111234, 74236, 66276, 0, 546, 72861, 0, 70661, 0, 472, 11083, 10319, - 10383, 917971, 0, 83202, 83203, 3602, 83206, 41182, 83199, 83200, 69796, - 3790, 0, 10271, 10287, 684, 0, 0, 0, 83214, 4592, 83216, 83217, 83210, - 11963, 43620, 83213, 0, 0, 83208, 83209, 0, 92623, 128559, 3415, 0, - 121267, 0, 0, 123151, 43447, 0, 92212, 0, 418, 0, 0, 10295, 10327, 10391, - 0, 83189, 83190, 83192, 83194, 83185, 83186, 83187, 83188, 120879, 0, - 41446, 70700, 118652, 0, 120809, 10599, 66892, 0, 0, 0, 0, 0, 129184, - 11437, 0, 0, 0, 0, 0, 0, 12624, 0, 41185, 72865, 69439, 8159, 0, 11686, - 71478, 65224, 0, 4655, 0, 0, 92183, 0, 10343, 10407, 0, 0, 0, 111221, 0, - 0, 0, 94057, 68201, 129574, 0, 983572, 72156, 42792, 5743, 10424, 0, 0, - 0, 0, 0, 8875, 111225, 0, 917991, 13117, 12847, 4651, 118917, 0, 962, 0, - 0, 2242, 42564, 0, 1582, 0, 5508, 0, 0, 0, 10801, 123602, 118798, 73705, - 0, 66911, 10439, 66891, 0, 0, 7860, 0, 906, 917985, 0, 6405, 64722, 0, - 83266, 64694, 83268, 917990, 1153, 83263, 64788, 83265, 0, 12626, 83260, - 83261, 9964, 0, 0, 4642, 66574, 127886, 0, 0, 0, 0, 0, 9008, 100847, 0, - 0, 0, 83248, 917976, 917993, 123173, 42842, 83244, 83245, 83247, 83239, - 83240, 83241, 83242, 0, 11335, 92661, 83238, 3920, 0, 0, 0, 83255, 83256, - 41967, 83258, 83251, 83252, 83253, 8920, 0, 0, 83249, 83250, 0, 0, 43919, - 0, 0, 0, 0, 128021, 0, 68113, 65196, 0, 0, 128472, 0, 10111, 64875, 0, - 83491, 43998, 83232, 83233, 83234, 70691, 83228, 42149, 83230, 68508, 0, - 0, 0, 0, 0, 0, 0, 4110, 66005, 74034, 0, 0, 0, 66703, 0, 0, 983158, 6025, - 69242, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70733, 0, 983043, 0, 73513, 0, 68817, - 0, 0, 0, 0, 0, 0, 43286, 0, 68765, 0, 0, 0, 0, 129871, 65144, 0, 0, - 83236, 65840, 0, 0, 10081, 0, 0, 983912, 0, 0, 0, 127394, 65882, 0, - 128758, 0, 0, 3605, 10985, 0, 0, 128872, 93972, 1745, 0, 73835, 0, 0, 0, - 0, 0, 0, 8806, 7023, 0, 0, 0, 70702, 70304, 0, 0, 0, 0, 0, 0, 0, 0, 348, - 10089, 0, 9017, 0, 0, 0, 0, 0, 0, 0, 67465, 0, 42515, 0, 0, 0, 0, 5391, - 983240, 110576, 0, 0, 5561, 0, 9429, 0, 67150, 7933, 5562, 0, 0, 0, 0, - 78039, 0, 0, 0, 0, 3979, 71248, 0, 0, 0, 68847, 0, 0, 118847, 65847, - 68836, 68838, 0, 10585, 0, 92676, 7334, 0, 0, 0, 831, 0, 0, 10716, 0, - 121325, 0, 12218, 0, 6939, 70697, 65042, 0, 0, 916, 0, 0, 11968, 0, - 122641, 5563, 0, 0, 128830, 5560, 41212, 41774, 0, 4497, 0, 0, 0, 9039, - 70678, 41776, 0, 8716, 3567, 119252, 0, 0, 74260, 0, 93954, 0, 0, 100827, - 0, 128879, 70072, 68355, 68357, 0, 0, 8634, 0, 0, 4209, 120702, 68832, - 65879, 68825, 68819, 68822, 0, 5679, 68813, 68815, 68811, 68812, 64697, - 5678, 11821, 68802, 93969, 0, 0, 0, 0, 70114, 0, 0, 0, 0, 0, 0, 0, 0, - 7782, 0, 0, 0, 0, 129977, 65711, 65712, 1216, 0, 69409, 5792, 0, 0, 0, 0, - 0, 12244, 0, 5683, 0, 120895, 121336, 43448, 70670, 0, 0, 5682, 10242, - 75043, 74520, 5680, 917568, 10001, 0, 0, 1449, 10241, 0, 70708, 0, 0, - 83180, 83182, 83183, 8584, 83176, 5567, 83178, 83179, 0, 5564, 42886, - 42884, 42882, 5565, 119022, 120881, 0, 65708, 65709, 5566, 0, 65704, - 65705, 11904, 42875, 0, 42873, 5942, 0, 0, 10361, 10425, 65697, 65698, - 65699, 0, 66598, 0, 64664, 10647, 78702, 78703, 78690, 78700, 0, 65701, - 1934, 0, 0, 0, 78710, 0, 78706, 78709, 6087, 78705, 78716, 78719, 78711, - 8043, 8950, 65694, 64485, 0, 10457, 0, 78724, 78725, 78722, 72332, 78720, - 78721, 0, 65515, 0, 10035, 13069, 0, 0, 127773, 0, 0, 0, 125207, 0, 0, - 1667, 0, 0, 42428, 110950, 0, 0, 41750, 0, 0, 93999, 0, 8101, 3610, - 113670, 41748, 110948, 0, 78394, 119208, 0, 0, 113691, 64549, 68359, 0, - 0, 65692, 92701, 0, 917960, 12896, 10456, 68298, 0, 0, 0, 0, 917962, 0, - 0, 113665, 70502, 0, 65687, 0, 0, 74009, 0, 113673, 8536, 70671, 0, - 78726, 0, 724, 0, 113675, 78749, 9975, 78746, 78747, 78744, 4175, 78741, - 78743, 78751, 939, 0, 128799, 983120, 0, 0, 0, 78763, 78764, 78760, - 78761, 78758, 78759, 78755, 8425, 0, 0, 0, 8188, 0, 0, 0, 0, 0, 6370, 0, - 7827, 68441, 75008, 0, 917943, 0, 118863, 0, 0, 0, 0, 121243, 73988, 0, - 113668, 0, 11012, 0, 43764, 178, 12972, 74620, 113671, 0, 113735, 0, - 66764, 0, 0, 65690, 72339, 0, 0, 917950, 9252, 0, 4652, 74259, 0, 917947, - 0, 0, 0, 10806, 0, 0, 70016, 0, 6723, 0, 0, 6993, 0, 0, 12855, 0, 0, - 11390, 0, 0, 0, 92503, 0, 0, 983162, 125270, 92627, 8278, 0, 4034, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 12750, 9350, 66037, 0, 0, 73700, 12747, 0, 0, - 128064, 8922, 74640, 0, 0, 43150, 0, 983090, 983088, 66779, 66777, 10813, - 2592, 43139, 0, 0, 118612, 0, 0, 71891, 0, 0, 0, 0, 0, 0, 71697, 0, - 128825, 1596, 0, 0, 0, 0, 6838, 66572, 0, 126574, 120627, 8092, 12805, - 41928, 0, 78406, 78409, 0, 0, 0, 9931, 0, 0, 0, 0, 0, 983778, 6107, 0, 0, - 0, 0, 128745, 0, 335, 127003, 64689, 0, 0, 5765, 0, 0, 119227, 6092, - 118851, 0, 8876, 83465, 74947, 83455, 129186, 83454, 70713, 0, 0, 126606, - 70121, 41602, 0, 92308, 74831, 0, 11783, 68482, 0, 0, 0, 0, 0, 0, 843, 0, - 71099, 0, 0, 41935, 0, 0, 0, 0, 1371, 0, 43818, 43159, 8069, 9579, 41938, - 41608, 0, 92444, 6242, 0, 0, 128595, 128244, 0, 92499, 8805, 1742, - 113722, 0, 8202, 72399, 0, 983198, 0, 0, 73882, 100809, 0, 43467, 123636, - 55290, 0, 1712, 5932, 0, 41762, 71982, 0, 11967, 1775, 0, 75009, 0, - 11868, 120387, 9458, 0, 126614, 0, 0, 43176, 101032, 101031, 42782, - 101033, 101036, 101035, 101038, 101037, 101040, 101039, 0, 0, 0, 0, - 101041, 5794, 92274, 2662, 101045, 101044, 8254, 101046, 10975, 101048, - 120625, 101050, 917977, 4108, 8478, 917982, 194790, 0, 92263, 917980, - 7507, 0, 43149, 0, 65031, 7961, 1636, 0, 65029, 0, 129665, 70188, 9674, - 0, 99, 98, 97, 101022, 92203, 4049, 101027, 43880, 7090, 101028, 0, - 101030, 66589, 0, 65310, 66593, 66599, 129805, 0, 0, 7447, 66594, 0, 0, - 0, 73920, 66595, 66596, 42570, 5593, 0, 0, 0, 0, 6061, 64854, 119, 118, - 117, 116, 0, 122, 121, 120, 111, 110, 109, 108, 115, 114, 113, 112, 103, - 102, 101, 100, 107, 106, 105, 104, 128504, 73974, 534, 0, 67713, 1536, - 73973, 73970, 0, 129671, 0, 6020, 12716, 0, 12744, 65143, 0, 13266, - 127813, 0, 0, 0, 127116, 0, 1212, 65560, 0, 8134, 42935, 12129, 73870, 0, - 1866, 0, 122948, 0, 0, 65073, 12059, 66585, 121391, 0, 0, 0, 5935, 1250, - 0, 8174, 9787, 6733, 9859, 9858, 9861, 9860, 101012, 1882, 1892, 6731, - 10882, 10795, 101018, 73911, 101020, 101019, 41169, 8939, 0, 120713, - 41170, 1454, 0, 65130, 69732, 0, 0, 129611, 41172, 7855, 0, 71472, 0, 0, - 0, 71691, 65901, 0, 0, 645, 100992, 100991, 100994, 100993, 100996, - 100995, 100998, 65587, 0, 10688, 0, 0, 7729, 0, 101001, 120518, 101003, - 66722, 101005, 101004, 68415, 101006, 4538, 101008, 43141, 0, 0, 73699, - 0, 0, 0, 71918, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71454, 0, 2381, 983752, 0, 0, - 69857, 100981, 0, 100983, 100982, 100985, 10856, 100987, 55255, 41478, - 8582, 10064, 0, 0, 0, 0, 64896, 0, 74609, 0, 128048, 10082, 11575, 0, 0, - 0, 917505, 0, 6145, 75020, 0, 92433, 71916, 83279, 43186, 0, 0, 83274, - 83276, 83277, 83278, 10191, 83271, 69633, 72353, 0, 0, 0, 0, 120090, - 120089, 7931, 8558, 917946, 0, 0, 0, 119145, 120081, 120084, 120083, - 120086, 71449, 120088, 7366, 7019, 75021, 0, 917951, 120078, 120077, - 120080, 8657, 100967, 8594, 100969, 100968, 0, 100970, 120072, 120071, 0, - 0, 43154, 0, 0, 11332, 0, 7728, 100978, 100977, 100980, 100979, 7851, 0, - 8375, 128662, 0, 0, 126095, 9085, 0, 0, 9327, 6160, 0, 0, 0, 0, 70698, - 74012, 0, 0, 4439, 121151, 100972, 100971, 100974, 100973, 100976, - 100975, 100956, 42524, 71220, 100957, 10826, 100959, 11296, 0, 0, 0, - 7504, 43161, 127868, 0, 64670, 0, 78056, 0, 11295, 0, 78053, 0, 0, 0, - 10902, 0, 0, 122650, 78068, 10472, 100954, 100953, 120215, 78062, 2371, - 78069, 118893, 259, 0, 0, 2402, 12157, 6440, 0, 100963, 100962, 100965, - 100964, 65380, 9103, 2278, 0, 0, 7301, 0, 10219, 0, 0, 0, 67718, 43178, - 0, 120214, 119362, 917974, 8613, 0, 126121, 917978, 917979, 121449, - 12005, 7353, 0, 1890, 129130, 0, 0, 0, 42815, 7991, 0, 10578, 0, 0, 0, 0, - 0, 0, 0, 111190, 120601, 42668, 9348, 0, 6164, 0, 0, 0, 7676, 0, 0, 0, 0, - 128732, 129422, 83443, 71096, 83444, 9175, 0, 78047, 9088, 73689, 0, - 1396, 0, 0, 11461, 71088, 127835, 92252, 0, 71090, 121185, 69872, 0, 0, - 0, 0, 74043, 119632, 0, 0, 0, 5928, 4525, 10658, 0, 1266, 10180, 64472, - 0, 12622, 0, 0, 0, 0, 127139, 13310, 773, 19933, 0, 0, 0, 0, 92205, 0, 0, - 0, 0, 5862, 7823, 0, 0, 0, 3250, 43991, 69687, 66649, 0, 0, 0, 0, 0, - 64673, 917963, 917964, 0, 0, 917967, 917968, 917965, 917966, 127791, - 75041, 3471, 917970, 64573, 882, 0, 119584, 0, 120772, 0, 0, 0, 92696, 0, - 0, 72988, 0, 3225, 0, 73729, 0, 0, 43173, 11752, 4381, 0, 0, 917945, - 11756, 11757, 917944, 917949, 42654, 127848, 118663, 0, 0, 5160, 1387, 0, - 917953, 0, 128933, 917956, 917957, 917954, 917955, 118595, 121082, - 917958, 10789, 68314, 0, 126521, 11143, 0, 0, 70669, 128904, 42179, 0, - 5931, 11744, 11215, 70676, 119245, 0, 0, 0, 77915, 10217, 64635, 128661, - 83292, 0, 0, 0, 0, 0, 41296, 11747, 41291, 0, 0, 0, 41294, 41282, 5923, - 120610, 0, 0, 0, 0, 66800, 5786, 68252, 42539, 119869, 119860, 0, 41474, - 0, 0, 0, 5934, 74572, 66583, 119231, 0, 94072, 64481, 0, 0, 0, 0, 67240, - 0, 0, 123201, 0, 5819, 0, 0, 0, 0, 0, 129387, 0, 0, 0, 67993, 1237, - 194749, 0, 0, 983557, 0, 0, 0, 0, 0, 0, 0, 69789, 11266, 69845, 0, 10506, - 194747, 0, 0, 0, 0, 43185, 194748, 100533, 100532, 100535, 10769, 100537, - 100536, 100539, 9753, 121035, 100540, 0, 0, 121433, 0, 100542, 6072, - 100544, 100543, 100546, 100545, 100548, 100547, 100550, 100549, 0, - 113744, 0, 0, 7222, 10283, 10315, 10379, 4996, 0, 129294, 66517, 0, - 10087, 127833, 74938, 0, 0, 83492, 7565, 42890, 0, 73520, 43180, 77928, - 74891, 77929, 43982, 100526, 622, 77926, 100527, 100530, 1602, 0, 0, 0, - 129559, 12160, 0, 10212, 77936, 194605, 12071, 43143, 77935, 917983, - 917984, 917989, 77932, 917987, 917988, 10255, 10263, 10279, 4194, 10375, - 93035, 0, 0, 12644, 127516, 917994, 75007, 110791, 67408, 110789, 11501, - 41177, 0, 0, 71912, 0, 0, 8715, 0, 41179, 0, 0, 0, 41176, 0, 41181, 0, - 8452, 121006, 13161, 0, 70503, 5921, 0, 2597, 0, 5922, 72128, 0, 74242, - 128374, 0, 0, 0, 0, 0, 0, 0, 127906, 0, 64944, 0, 0, 0, 0, 5924, 5920, - 129508, 6921, 78081, 74007, 78078, 8418, 11681, 43169, 10176, 0, 0, 0, - 78087, 10772, 65276, 5937, 1914, 78084, 11682, 0, 0, 0, 11685, 0, 100513, - 7772, 11680, 100514, 100517, 100516, 100519, 7417, 718, 100520, 70083, - 100500, 120718, 3235, 0, 43164, 0, 8018, 0, 0, 128708, 6937, 67672, - 128508, 0, 10067, 120849, 0, 0, 0, 118693, 0, 100491, 0, 100493, 100492, - 13116, 100494, 100497, 9945, 100499, 100498, 0, 0, 0, 0, 2059, 0, 100502, - 100501, 1431, 100503, 66565, 100505, 100508, 12804, 100510, 100509, - 78090, 3307, 78088, 78089, 0, 4544, 71228, 0, 0, 0, 78097, 11110, 66810, - 12882, 64511, 78094, 78100, 78102, 71226, 10141, 0, 78280, 65298, 4476, - 78109, 94005, 71216, 8907, 78105, 78106, 78103, 78104, 120898, 0, 10665, - 64616, 128944, 0, 127545, 69605, 83159, 83160, 4554, 0, 83155, 83156, - 83157, 83158, 0, 125123, 0, 72258, 129831, 0, 129815, 0, 43179, 0, 0, 0, - 717, 10754, 83168, 83169, 83162, 83163, 83164, 83165, 78282, 0, 0, 83161, - 68848, 10611, 72859, 126978, 71474, 129426, 127871, 0, 0, 0, 12820, - 110882, 0, 7009, 70103, 0, 0, 67848, 41173, 4574, 0, 0, 128338, 575, - 78110, 43456, 8563, 100469, 0, 0, 65565, 123598, 5936, 7290, 78117, - 78118, 74919, 308, 78113, 78114, 83151, 78123, 83153, 83154, 0, 0, 0, 0, - 67496, 5926, 68250, 78130, 78126, 78127, 78124, 78125, 42513, 0, 129026, - 0, 11651, 13093, 78135, 0, 100471, 0, 100473, 100472, 100475, 74048, - 100477, 71995, 100457, 100456, 43703, 13097, 0, 100460, 13283, 0, 0, - 125073, 3488, 5933, 10033, 983947, 0, 65570, 0, 12297, 0, 0, 0, 128517, - 42538, 0, 129293, 0, 100451, 0, 100453, 100452, 100455, 100454, 121221, - 0, 0, 7638, 0, 129193, 0, 43109, 7637, 0, 11213, 100461, 83355, 100463, - 100466, 100465, 0, 0, 7636, 0, 0, 0, 128848, 983087, 291, 0, 0, 2027, - 78141, 78142, 78136, 78137, 83481, 4640, 64713, 10224, 120429, 11183, - 83482, 120430, 0, 0, 0, 127148, 83479, 0, 0, 83488, 0, 0, 0, 0, 68837, - 5778, 0, 0, 0, 12680, 119130, 0, 67242, 93041, 0, 0, 0, 11552, 0, 127855, - 0, 70091, 0, 10172, 65453, 120408, 66014, 120410, 0, 4641, 11556, 64819, - 78269, 120416, 72341, 41469, 41467, 120412, 120415, 4646, 120425, 865, - 78275, 78274, 78273, 4645, 78271, 78270, 0, 983173, 7338, 0, 68840, 0, - 12565, 0, 0, 0, 195089, 119655, 195091, 195090, 2913, 13120, 128956, - 69493, 195097, 195096, 128019, 0, 71462, 0, 7916, 10485, 195098, 0, - 195100, 195099, 0, 67705, 128351, 195077, 195080, 129636, 129549, 195081, - 0, 0, 0, 10229, 10687, 826, 128081, 195082, 195085, 195084, 195087, - 195086, 0, 1808, 7848, 0, 0, 0, 0, 0, 0, 128897, 69255, 42942, 67704, 0, - 0, 0, 0, 42940, 0, 9144, 0, 0, 92992, 9840, 0, 0, 0, 0, 0, 0, 74448, - 83475, 0, 10962, 66904, 113718, 983188, 0, 0, 74537, 195072, 1792, - 195074, 195073, 78266, 195075, 0, 0, 12066, 0, 385, 4152, 0, 0, 0, 67397, - 0, 0, 0, 0, 43258, 0, 0, 13157, 0, 0, 3570, 0, 0, 0, 67252, 0, 71218, - 126631, 7879, 68247, 128579, 78914, 0, 70196, 0, 0, 8463, 7810, 917862, - 7839, 983878, 127768, 917860, 9691, 0, 129323, 0, 120385, 0, 917844, 0, - 10066, 0, 2175, 0, 0, 0, 8016, 0, 983072, 64831, 0, 126103, 0, 73493, - 1634, 68115, 94192, 11056, 0, 0, 0, 41165, 11328, 12450, 0, 41166, 0, - 12456, 0, 171, 67508, 12452, 917544, 12458, 12531, 0, 917853, 0, 74162, - 0, 0, 9969, 0, 12454, 74160, 42132, 110755, 78878, 110753, 3230, 73711, - 0, 0, 8932, 4399, 5810, 64534, 8415, 0, 110756, 110757, 74159, 0, 0, 960, - 74156, 6981, 92374, 12938, 9201, 0, 118713, 74904, 0, 72866, 92270, 0, 0, - 0, 129792, 5851, 73833, 5824, 0, 5844, 110848, 110849, 110846, 110847, - 4663, 0, 0, 0, 0, 0, 74085, 0, 0, 0, 0, 0, 92339, 0, 0, 5782, 67495, 0, - 0, 43796, 129639, 0, 195083, 125223, 128004, 0, 43861, 0, 0, 0, 92976, 0, - 0, 0, 4659, 0, 128894, 0, 0, 129386, 0, 11129, 2238, 329, 0, 92707, - 121416, 0, 0, 0, 69943, 67692, 42167, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 69618, 43671, 0, 64701, 0, 0, 0, 93055, 1172, 125089, 6786, 43601, 0, - 74126, 0, 0, 0, 0, 0, 118695, 0, 0, 118804, 0, 66741, 5347, 125026, - 983663, 0, 0, 10588, 0, 0, 0, 0, 5343, 0, 0, 0, 5341, 0, 0, 74916, 5351, - 0, 0, 917884, 0, 92692, 0, 121148, 128916, 0, 0, 66785, 126256, 6638, 0, - 0, 271, 0, 917904, 0, 0, 12653, 67588, 0, 0, 0, 0, 128838, 11912, 128301, - 983665, 0, 11800, 0, 0, 11103, 0, 7340, 0, 110695, 0, 0, 70170, 0, 2423, - 0, 0, 0, 128136, 42705, 0, 0, 0, 11854, 0, 0, 0, 0, 4916, 0, 380, 10958, - 66563, 127790, 78284, 67587, 0, 12918, 0, 917897, 0, 917898, 917893, - 10684, 0, 125063, 92906, 0, 0, 8182, 0, 0, 129434, 0, 0, 0, 6859, 0, - 6630, 100405, 0, 123191, 0, 0, 0, 65876, 5535, 129892, 0, 0, 92609, 0, - 983348, 6477, 43795, 92217, 129571, 72163, 69496, 43848, 0, 0, 74256, - 2665, 11304, 43751, 0, 4970, 74353, 0, 8934, 0, 93996, 4492, 92908, - 65011, 0, 0, 92909, 1188, 7254, 1100, 0, 0, 0, 2912, 11749, 92643, 0, 0, - 65057, 0, 12343, 0, 78879, 0, 78880, 0, 0, 0, 70355, 0, 0, 11803, 0, 0, - 41450, 0, 100897, 0, 41451, 0, 0, 8273, 0, 3451, 0, 972, 41453, 68164, - 78876, 0, 92408, 73945, 43504, 2288, 78873, 9538, 78874, 128685, 0, - 129095, 0, 0, 0, 0, 11019, 0, 0, 121205, 0, 73007, 71365, 92716, 5927, 0, - 0, 0, 0, 128484, 0, 6073, 0, 0, 0, 6075, 93995, 282, 126510, 0, 74078, - 121459, 2206, 0, 0, 66791, 0, 3474, 0, 0, 0, 6081, 0, 127843, 74076, 0, - 0, 0, 128908, 0, 0, 0, 12623, 120273, 9120, 120275, 4665, 12628, 4670, - 120271, 120272, 0, 0, 121480, 958, 0, 0, 0, 4666, 0, 4915, 0, 4669, 0, 0, - 0, 4664, 0, 120550, 0, 0, 0, 0, 94023, 0, 917875, 8664, 11664, 0, 129327, - 11224, 0, 0, 1063, 119088, 120251, 9772, 7255, 8886, 0, 127932, 120257, - 120258, 120259, 120260, 42661, 71345, 120255, 119125, 120265, 120266, - 120267, 42721, 92407, 120262, 120263, 66788, 1017, 0, 118580, 505, 1447, - 0, 0, 70340, 66793, 65115, 42789, 128443, 0, 0, 123634, 0, 119195, 0, 0, - 11745, 7919, 0, 1641, 0, 0, 8966, 0, 0, 8743, 71870, 0, 67813, 0, 0, 0, - 123206, 0, 0, 128505, 10169, 71324, 0, 10068, 0, 120457, 120456, 120455, - 120454, 257, 43170, 13153, 0, 0, 0, 0, 0, 0, 6496, 19917, 5930, 128354, - 11033, 0, 0, 5622, 120436, 8477, 8474, 120433, 120432, 0, 0, 0, 41435, - 4352, 0, 2435, 0, 5621, 0, 4201, 8450, 4203, 4202, 4205, 4204, 120447, - 120446, 120445, 66792, 41440, 120442, 8473, 6373, 8469, 120438, 0, 4564, - 125206, 0, 0, 0, 8374, 73669, 0, 0, 66796, 0, 0, 0, 0, 0, 69297, 129762, - 5626, 43507, 11771, 0, 0, 0, 42614, 0, 5625, 0, 0, 0, 5623, 0, 0, 42623, - 64277, 69942, 0, 0, 120752, 0, 5817, 5629, 0, 7551, 10325, 5632, 69674, - 0, 0, 124946, 125194, 5628, 129766, 5631, 0, 0, 2400, 5627, 0, 0, 118786, - 74792, 0, 0, 0, 203, 129084, 74365, 0, 0, 0, 0, 83382, 83422, 0, 0, 554, - 0, 0, 0, 12182, 0, 64569, 110840, 73891, 0, 0, 0, 7689, 69798, 9323, - 10269, 10285, 10317, 175, 0, 0, 0, 0, 0, 1243, 42154, 0, 92387, 0, 0, - 43651, 0, 125021, 0, 9075, 118597, 0, 64777, 128570, 0, 0, 0, 0, 65255, - 0, 121142, 4490, 0, 6649, 120698, 12181, 0, 11977, 7249, 8366, 0, 7756, - 12342, 0, 51, 41516, 69432, 0, 9568, 71318, 456, 0, 10437, 1168, 9251, - 9082, 0, 0, 42781, 3866, 0, 41512, 0, 0, 68121, 41494, 0, 4660, 0, 10405, - 0, 0, 0, 0, 0, 73918, 119627, 110686, 41454, 12605, 0, 126611, 41455, - 917996, 983605, 0, 8214, 0, 100413, 129320, 41457, 983077, 0, 1969, - 127771, 0, 69554, 7413, 0, 69426, 10341, 43864, 78079, 5854, 0, 0, 0, - 129684, 72819, 0, 0, 73548, 0, 0, 8429, 0, 72328, 0, 6429, 0, 0, 0, 0, - 110688, 83417, 0, 917864, 120813, 83423, 1662, 125000, 0, 0, 917871, - 917868, 0, 0, 66, 65, 68, 67, 70, 69, 72, 71, 74, 73, 76, 75, 78, 77, 80, - 79, 82, 81, 84, 83, 86, 85, 88, 87, 90, 89, 0, 0, 7385, 70508, 1704, - 12993, 0, 0, 0, 0, 0, 0, 0, 0, 11353, 72207, 0, 0, 0, 0, 118831, 0, 0, 0, - 0, 0, 118719, 83364, 0, 0, 1289, 0, 0, 119583, 0, 65507, 0, 0, 0, 128042, - 0, 74409, 0, 0, 0, 0, 64793, 0, 0, 100843, 5675, 119239, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 6972, 70735, 0, 121108, 126217, 0, 0, 0, 0, 0, 110640, - 67687, 0, 0, 119634, 0, 43977, 111252, 129105, 0, 7412, 64671, 0, 1412, - 4594, 1391, 0, 8067, 12478, 110639, 78375, 110637, 10281, 110635, 0, 0, - 7960, 43271, 0, 12518, 69846, 0, 3566, 0, 0, 69864, 0, 0, 68021, 0, 0, 0, - 8223, 0, 4261, 121460, 68918, 0, 0, 121294, 113712, 0, 128046, 43419, - 72748, 92866, 10574, 0, 67691, 0, 0, 73785, 0, 78875, 128541, 0, 127366, - 0, 0, 0, 0, 6695, 65113, 324, 0, 128373, 40985, 0, 0, 0, 0, 0, 72307, - 43474, 0, 121190, 0, 0, 3420, 0, 0, 0, 0, 0, 0, 0, 0, 0, 110871, 9574, - 120684, 110870, 110814, 5204, 74774, 0, 11835, 0, 0, 983186, 0, 0, 0, 0, - 0, 0, 11750, 68898, 127004, 0, 0, 0, 0, 8130, 0, 0, 0, 121268, 0, 129443, - 0, 68455, 42863, 73839, 0, 0, 0, 92288, 0, 0, 0, 612, 110875, 110876, - 72231, 10538, 0, 1674, 0, 0, 0, 12280, 0, 540, 74550, 0, 66422, 8432, 0, - 11073, 0, 64316, 129894, 0, 7388, 0, 0, 0, 0, 126107, 0, 3359, 0, 0, - 67284, 0, 0, 65482, 129589, 0, 64742, 129304, 0, 124141, 74273, 0, 19941, - 0, 0, 0, 0, 9481, 65555, 0, 66628, 129126, 1195, 64898, 0, 0, 0, 2010, 0, - 0, 0, 0, 0, 0, 4360, 127009, 9739, 0, 72885, 0, 0, 0, 126265, 72200, 0, - 0, 120025, 72199, 0, 0, 65734, 0, 0, 129690, 13075, 0, 94063, 0, 43532, - 10837, 2492, 74516, 983075, 120882, 0, 0, 11813, 9649, 0, 119617, 5128, - 7377, 0, 65604, 0, 0, 6771, 1648, 7819, 0, 0, 0, 125192, 128131, 12709, - 6986, 0, 0, 0, 0, 0, 12581, 0, 5175, 0, 73806, 0, 128420, 0, 0, 77950, 0, - 0, 607, 0, 0, 128846, 119605, 67475, 129528, 65477, 0, 121130, 0, 8265, - 0, 0, 0, 5840, 42838, 0, 0, 68366, 0, 119255, 0, 0, 0, 127929, 0, 2550, - 121011, 6779, 70059, 0, 0, 0, 0, 0, 0, 5619, 65822, 0, 0, 0, 129392, - 5616, 11486, 0, 0, 0, 0, 5615, 0, 121319, 42380, 127958, 0, 66451, 74407, - 0, 11347, 0, 1026, 5620, 0, 0, 11350, 5617, 0, 0, 64639, 0, 0, 0, 1338, - 0, 0, 0, 4603, 0, 70715, 92484, 0, 9002, 0, 3974, 78213, 0, 0, 0, 0, 0, - 0, 75038, 66040, 70455, 0, 0, 0, 72982, 0, 0, 0, 0, 0, 118661, 0, 0, - 119105, 0, 0, 0, 0, 0, 128883, 0, 66897, 0, 0, 0, 42594, 0, 0, 0, 0, - 6714, 10083, 0, 121019, 0, 69976, 0, 0, 9073, 0, 64302, 0, 128286, 9725, - 0, 0, 121288, 73769, 121306, 0, 9570, 0, 11500, 2689, 917626, 0, 983813, - 66740, 0, 0, 0, 917623, 13286, 5500, 42598, 42596, 503, 0, 0, 917618, 0, - 0, 0, 0, 917615, 1652, 772, 6688, 8310, 0, 0, 72124, 0, 10194, 43542, 0, - 125054, 0, 6468, 68110, 0, 917606, 11767, 0, 0, 5836, 12358, 0, 0, 65624, - 12180, 0, 127994, 0, 43699, 0, 0, 72114, 43706, 0, 12362, 12435, 12360, - 0, 9020, 0, 12356, 8616, 0, 42924, 2227, 0, 0, 7315, 12354, 83097, 83098, - 83099, 2358, 83092, 83093, 83094, 0, 0, 83089, 83090, 0, 11759, 71723, 0, - 72834, 83109, 41423, 0, 83103, 83104, 83105, 42237, 110653, 70717, 72260, - 83102, 0, 67856, 0, 128534, 110657, 129354, 129194, 0, 64395, 0, 73008, - 120897, 74816, 0, 0, 0, 83088, 0, 0, 94064, 83083, 83085, 83086, 83087, - 83079, 83080, 2041, 9178, 0, 64870, 0, 83076, 74924, 0, 0, 0, 0, 0, - 78739, 0, 0, 0, 0, 0, 0, 3726, 0, 0, 0, 0, 0, 121432, 129457, 0, 0, 0, 0, - 0, 74901, 0, 0, 0, 0, 0, 124944, 113781, 0, 7410, 2669, 903, 0, 0, 0, - 127232, 74603, 0, 128264, 0, 128411, 0, 0, 11732, 0, 72797, 41448, 41461, - 124934, 0, 917558, 0, 8819, 0, 0, 74606, 92847, 121412, 74835, 0, 9168, - 65786, 0, 73691, 0, 67665, 0, 11758, 68425, 0, 0, 0, 128044, 0, 19924, - 67312, 0, 128755, 64551, 0, 8516, 0, 0, 7561, 983999, 74018, 0, 0, 0, 0, - 83074, 83075, 0, 11233, 83062, 83066, 3787, 83070, 83055, 41458, 83059, - 41463, 65308, 41459, 8683, 775, 0, 65584, 69923, 0, 110798, 110799, - 110796, 43440, 0, 0, 0, 3656, 0, 0, 0, 67694, 1599, 83138, 83139, 8514, - 8513, 83036, 83135, 83136, 110794, 110795, 83131, 83132, 0, 0, 0, 11684, - 10542, 9937, 83150, 0, 75037, 83145, 65730, 83147, 0, 8427, 83142, 55246, - 0, 0, 11497, 0, 0, 0, 119222, 0, 983598, 0, 10621, 0, 0, 129295, 119111, - 120745, 0, 0, 0, 11648, 83126, 83127, 42118, 83129, 83122, 65512, 83124, - 83125, 0, 0, 0, 83121, 74530, 128456, 0, 0, 0, 65724, 0, 0, 0, 65727, 0, - 0, 64963, 73830, 66042, 0, 0, 7875, 0, 0, 0, 129476, 0, 0, 536, 0, 0, 0, - 0, 65173, 129122, 0, 70331, 0, 0, 118598, 0, 129419, 0, 0, 0, 1687, 0, 0, - 0, 0, 0, 0, 10526, 0, 8323, 0, 83301, 11731, 73530, 0, 65460, 12242, 0, - 0, 10843, 11554, 0, 0, 8266, 0, 121101, 0, 0, 0, 0, 67667, 118694, - 119155, 0, 0, 119636, 67857, 0, 0, 0, 11755, 66305, 0, 0, 10917, 93979, - 113688, 0, 2040, 92596, 0, 0, 0, 0, 1227, 83119, 83120, 0, 0, 83115, - 74427, 11149, 4978, 83111, 1984, 11830, 83114, 128934, 74548, 118545, - 9373, 0, 0, 0, 0, 0, 0, 0, 0, 9237, 9390, 0, 0, 0, 0, 0, 1830, 0, 0, 0, - 0, 0, 128577, 983839, 68086, 0, 0, 0, 983059, 0, 983145, 0, 0, 0, 72197, - 55291, 11683, 0, 983659, 0, 11451, 0, 72714, 3731, 2359, 0, 67844, 0, - 121503, 548, 121502, 983250, 121405, 983253, 0, 66272, 0, 64678, 0, 9547, - 0, 0, 1614, 0, 0, 66307, 128092, 1358, 120871, 428, 0, 1466, 0, 10982, 0, - 0, 0, 407, 0, 0, 0, 0, 0, 0, 5804, 73464, 0, 0, 0, 70167, 9057, 42446, 0, - 125097, 0, 0, 8250, 10952, 8048, 0, 129155, 0, 118955, 0, 0, 118593, - 4407, 74648, 0, 0, 0, 8448, 92491, 0, 0, 12675, 12659, 0, 0, 983285, - 68077, 55273, 10766, 12012, 2386, 0, 9170, 0, 9123, 128194, 0, 0, 0, 0, - 129942, 0, 0, 0, 0, 0, 0, 8709, 0, 72383, 0, 0, 0, 0, 0, 0, 0, 128342, 0, - 577, 128610, 0, 0, 124999, 68087, 74840, 126474, 127036, 0, 0, 0, 1414, - 124963, 9683, 43486, 92231, 0, 2536, 0, 66330, 0, 0, 0, 0, 0, 0, 0, - 66317, 0, 66315, 66316, 0, 0, 0, 0, 0, 0, 0, 0, 66323, 66324, 0, 0, 3106, - 65917, 0, 2182, 0, 891, 0, 0, 42624, 0, 0, 8824, 65089, 128734, 10936, 0, - 0, 0, 0, 92688, 0, 0, 0, 0, 12745, 0, 0, 41285, 3547, 0, 0, 129877, 0, - 118701, 6089, 0, 68490, 120578, 4170, 1029, 127761, 0, 0, 42374, 917625, - 744, 917624, 0, 0, 0, 93046, 0, 3551, 0, 0, 4623, 0, 0, 12340, 0, 65136, - 0, 0, 0, 0, 0, 0, 0, 72291, 0, 0, 120778, 0, 11972, 0, 78757, 0, 122886, - 177, 122894, 0, 0, 0, 0, 55243, 0, 0, 0, 70172, 120249, 120242, 128027, - 120243, 0, 0, 0, 120237, 120245, 94079, 0, 0, 9136, 120240, 120614, - 41280, 0, 0, 0, 0, 74149, 128327, 0, 0, 66361, 12601, 72194, 64360, - 65163, 125241, 0, 0, 0, 0, 0, 5404, 43332, 3667, 7936, 12925, 0, 0, 0, 0, - 0, 10874, 65505, 0, 0, 0, 0, 128920, 983681, 0, 0, 0, 0, 0, 0, 0, 0, - 66677, 0, 0, 0, 70088, 74148, 0, 0, 72868, 120230, 120224, 74172, 0, 0, - 94096, 0, 128414, 120636, 0, 127519, 917609, 917616, 0, 128652, 0, 0, - 11441, 0, 3512, 0, 0, 43597, 0, 0, 72734, 68153, 41563, 0, 0, 129352, - 41544, 0, 0, 74927, 0, 129177, 0, 0, 0, 118908, 0, 78108, 67396, 73804, - 64711, 0, 0, 917610, 0, 0, 0, 11557, 127776, 0, 12079, 0, 0, 0, 0, - 128861, 0, 0, 0, 0, 0, 983201, 8103, 72303, 128174, 92486, 110698, 0, - 64587, 0, 0, 124961, 0, 0, 0, 126481, 0, 0, 0, 0, 0, 70348, 1450, 0, - 1340, 0, 0, 128970, 0, 0, 125117, 0, 0, 0, 0, 6539, 92948, 0, 128213, - 125060, 0, 0, 0, 3973, 0, 70504, 121193, 7982, 0, 0, 127194, 0, 0, 0, - 128408, 118968, 6417, 120619, 129748, 0, 0, 0, 129455, 4919, 65121, - 110872, 7755, 0, 0, 64548, 0, 1621, 0, 0, 0, 0, 0, 12188, 0, 0, 0, 0, - 5015, 0, 0, 42590, 70354, 1756, 0, 0, 0, 120694, 0, 0, 7555, 73874, 5408, - 2817, 1214, 69919, 0, 983126, 0, 0, 125055, 127195, 7957, 0, 0, 1056, - 74944, 0, 0, 0, 0, 7073, 74979, 0, 70853, 0, 110874, 0, 0, 2341, 126644, - 8484, 0, 0, 68322, 0, 8461, 67721, 42269, 0, 0, 43709, 43708, 9451, 7571, - 13073, 43847, 126647, 0, 983263, 0, 0, 0, 8781, 12894, 78134, 0, 78132, - 0, 0, 78184, 0, 11338, 120768, 0, 0, 0, 0, 0, 121367, 65021, 64795, - 74574, 0, 10047, 0, 0, 0, 0, 0, 0, 119181, 163, 576, 9895, 0, 0, 74591, - 0, 0, 66888, 0, 0, 0, 0, 0, 0, 7017, 128111, 0, 0, 129922, 0, 41591, - 11036, 65252, 120795, 129488, 0, 0, 0, 0, 0, 0, 8887, 0, 7295, 71203, 0, - 127221, 0, 0, 0, 0, 8755, 0, 0, 8147, 73127, 0, 0, 121348, 0, 129377, 0, - 74499, 0, 0, 0, 4619, 0, 6654, 123192, 0, 0, 0, 65689, 10128, 0, 129612, - 0, 0, 92651, 0, 2401, 0, 8792, 118546, 0, 74980, 0, 92246, 0, 0, 0, - 12886, 0, 66624, 0, 0, 74133, 65170, 0, 74135, 0, 0, 9984, 73867, 3010, - 0, 70349, 10698, 41475, 0, 119151, 0, 119152, 0, 0, 9100, 0, 0, 0, 78116, - 64780, 2001, 0, 55230, 0, 4052, 92856, 7626, 78080, 0, 0, 0, 41477, 0, 0, - 0, 43707, 74127, 0, 0, 0, 78086, 73758, 2335, 10663, 0, 0, 129872, - 119602, 0, 0, 70325, 0, 41443, 0, 0, 0, 9711, 1523, 0, 0, 41445, 0, 0, - 8567, 41442, 12821, 0, 0, 118978, 0, 65274, 0, 94082, 0, 127515, 0, 0, - 43446, 0, 0, 0, 0, 127985, 0, 10206, 127167, 6375, 2673, 0, 0, 0, 43219, - 129355, 0, 0, 0, 0, 129400, 11799, 101225, 68466, 0, 0, 0, 0, 0, 120736, - 0, 7203, 0, 0, 70361, 127213, 120615, 127216, 0, 0, 0, 0, 43121, 0, - 128366, 72161, 0, 129868, 0, 121260, 73781, 70365, 0, 68039, 70446, - 10057, 0, 0, 0, 101219, 120963, 101220, 2307, 0, 0, 0, 0, 73873, 0, - 94035, 0, 0, 67469, 0, 129983, 7327, 0, 0, 440, 0, 0, 68613, 75059, 0, 0, - 9957, 0, 0, 8046, 0, 119158, 0, 0, 68609, 0, 129405, 1521, 129460, 92256, - 65344, 0, 11850, 68737, 0, 0, 68914, 7303, 65770, 5243, 0, 5239, 65771, - 121429, 0, 5237, 0, 68756, 0, 5247, 0, 0, 0, 12873, 5764, 0, 0, 3008, - 118981, 128102, 0, 0, 55231, 41103, 0, 92756, 0, 0, 92717, 70074, 7872, - 74886, 917567, 8731, 65378, 118564, 0, 11316, 128163, 126600, 70360, - 3019, 9997, 0, 0, 9456, 129545, 0, 0, 101192, 0, 0, 92682, 4281, 0, 0, 0, - 118982, 0, 69993, 78096, 0, 78095, 0, 78098, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 2134, 0, 10116, 9877, 70679, 0, 0, 92723, 8379, 0, 6778, 0, 0, 8243, 0, - 0, 0, 0, 128008, 0, 0, 0, 983630, 119668, 129962, 92722, 983098, 5637, - 125115, 0, 0, 120479, 0, 113730, 0, 0, 194990, 64432, 0, 70363, 121368, - 1156, 68052, 0, 0, 120482, 0, 68030, 0, 0, 0, 7634, 0, 0, 65536, 0, 0, 0, - 7702, 0, 78890, 0, 65779, 65783, 195066, 120961, 5700, 0, 0, 92161, 2339, - 92476, 5697, 0, 0, 0, 74923, 0, 5696, 92677, 0, 3862, 0, 0, 0, 983055, 0, - 0, 0, 0, 5701, 9722, 41490, 41370, 5698, 0, 0, 0, 42204, 55270, 8571, 0, - 0, 43859, 0, 78731, 0, 12184, 0, 0, 0, 0, 0, 5650, 0, 64712, 120474, 0, - 120458, 5647, 120473, 7387, 0, 92675, 11477, 5646, 0, 11018, 0, 0, 0, 0, - 0, 0, 69280, 128459, 126128, 5651, 0, 0, 0, 5648, 0, 120920, 0, 127517, - 3545, 0, 6984, 0, 0, 0, 69414, 126613, 0, 10123, 0, 69274, 0, 0, 65020, - 74885, 119166, 0, 0, 0, 0, 0, 1140, 78426, 0, 0, 0, 122665, 8128, 9889, - 0, 0, 1815, 0, 890, 0, 3267, 0, 0, 0, 983686, 4410, 125081, 10576, 8102, - 0, 580, 74232, 0, 0, 0, 0, 0, 19938, 0, 0, 0, 0, 3298, 6546, 0, 0, 0, 0, - 6134, 41246, 0, 0, 0, 917770, 0, 6264, 0, 0, 0, 0, 0, 0, 69445, 0, 0, 0, - 92697, 11915, 10377, 0, 10072, 0, 0, 2329, 0, 0, 0, 0, 0, 0, 0, 67498, 0, - 101164, 0, 11201, 92708, 74769, 0, 13263, 0, 0, 92404, 126066, 69491, 0, - 0, 64917, 0, 0, 494, 128026, 0, 65098, 0, 956, 125265, 129556, 0, 73740, - 0, 0, 0, 74281, 128638, 0, 0, 69217, 120930, 0, 0, 0, 0, 0, 9922, 0, - 126269, 100948, 0, 65229, 0, 118671, 0, 0, 0, 0, 3907, 118833, 64526, - 11829, 68197, 0, 0, 11475, 70329, 3020, 42264, 0, 0, 0, 7098, 0, 0, - 127967, 957, 42696, 0, 3016, 0, 0, 0, 0, 0, 121248, 92510, 3006, 4620, 0, - 0, 0, 0, 129369, 129425, 0, 0, 0, 126246, 8626, 0, 128824, 0, 65377, 0, - 983103, 42920, 1698, 0, 64477, 0, 0, 43813, 100432, 100431, 100434, - 100433, 100436, 70321, 100438, 100437, 100440, 100439, 0, 121024, 101177, - 70327, 100441, 55252, 100443, 100442, 100445, 100444, 66641, 100446, - 100449, 100448, 0, 100450, 113820, 74866, 64375, 0, 127850, 129477, 0, 0, - 0, 0, 983799, 0, 0, 120827, 0, 0, 123637, 0, 0, 0, 101183, 8110, 100421, - 0, 100423, 5830, 100425, 100424, 100427, 73540, 100429, 100428, 42389, - 78611, 121398, 0, 0, 0, 0, 0, 0, 0, 83342, 983954, 0, 127147, 119187, - 2135, 11836, 0, 0, 78869, 42313, 5579, 0, 70384, 983082, 94002, 0, 5578, - 11840, 73006, 42023, 69849, 5669, 92559, 0, 0, 68833, 917845, 128275, - 5583, 0, 0, 42426, 5580, 42276, 0, 892, 2220, 42465, 74313, 73440, 5795, - 194991, 68774, 65702, 68770, 0, 65695, 0, 65710, 128399, 0, 0, 68783, 0, - 0, 0, 1638, 10966, 0, 917547, 0, 118921, 0, 0, 0, 8172, 120760, 0, 0, 0, - 0, 0, 6374, 0, 0, 120972, 0, 0, 0, 0, 0, 0, 0, 72204, 64900, 7153, 65785, - 68826, 0, 3015, 68743, 68740, 68738, 68805, 6400, 68749, 68748, 68760, - 68758, 11276, 68754, 100420, 372, 101138, 68761, 118874, 0, 41585, - 128202, 0, 74228, 276, 129895, 74234, 0, 74226, 0, 9007, 0, 41588, - 125001, 119189, 10763, 0, 0, 983560, 126097, 68525, 6257, 73112, 100393, - 100396, 100395, 100398, 92409, 100400, 100399, 101148, 74848, 120006, - 983592, 100401, 66498, 100403, 100402, 64790, 73454, 100407, 100406, - 70356, 100408, 0, 100410, 66829, 70817, 5711, 41633, 12098, 65571, 9166, - 0, 5710, 0, 6790, 65213, 0, 0, 0, 69726, 0, 73817, 0, 0, 5715, 0, 70408, - 0, 5712, 100382, 41620, 100384, 3074, 5722, 100389, 100388, 73768, 0, - 118906, 0, 0, 0, 66419, 71972, 0, 0, 0, 0, 64839, 78607, 0, 129074, 0, 0, - 0, 0, 0, 0, 113682, 0, 11261, 0, 0, 0, 8701, 0, 11236, 0, 129490, 100390, - 0, 0, 0, 78293, 0, 0, 0, 64946, 0, 0, 0, 70336, 0, 0, 93986, 68814, - 42902, 0, 0, 0, 0, 92344, 0, 67845, 42641, 71444, 0, 0, 70366, 101152, - 100369, 100368, 5084, 100370, 101158, 118861, 0, 733, 74646, 0, 0, 0, - 125085, 0, 9218, 0, 100380, 100379, 71070, 0, 0, 0, 0, 70323, 0, 0, 5155, - 0, 0, 983775, 0, 0, 72351, 0, 0, 0, 122891, 0, 0, 0, 100372, 100371, - 100374, 100373, 100376, 100375, 100378, 100377, 4974, 100357, 100360, - 100359, 0, 0, 0, 12205, 0, 0, 64507, 0, 0, 0, 0, 0, 0, 12149, 13088, - 78290, 0, 12241, 0, 0, 0, 6932, 100352, 73676, 100354, 100353, 100356, - 351, 68764, 0, 0, 0, 0, 73443, 0, 0, 100361, 42377, 100363, 100362, - 100365, 100364, 100367, 9013, 4054, 0, 0, 71939, 0, 120782, 5585, 65881, - 0, 0, 118541, 0, 5584, 8358, 128975, 121177, 0, 0, 0, 41616, 0, 983815, - 2218, 0, 5589, 0, 2664, 41613, 5586, 118890, 0, 11356, 0, 0, 0, 78609, 0, - 0, 0, 0, 0, 129870, 0, 0, 8135, 129685, 0, 983810, 0, 0, 0, 5657, 0, - 12915, 121453, 0, 10179, 5654, 12939, 0, 120799, 0, 0, 5652, 10945, - 118626, 0, 0, 113710, 0, 73449, 68069, 0, 70332, 0, 5659, 0, 0, 66729, - 5655, 0, 0, 0, 68806, 0, 128225, 66310, 73444, 0, 0, 70362, 0, 11609, 0, - 126990, 92949, 10272, 10304, 10368, 74511, 594, 10244, 10248, 10256, - 983918, 122974, 0, 3467, 41010, 0, 3331, 946, 0, 1495, 13184, 74330, - 128242, 9562, 0, 123175, 0, 70036, 122976, 0, 0, 123176, 0, 0, 0, 5666, - 65227, 123174, 68419, 0, 11796, 123178, 0, 0, 10186, 123172, 7732, - 983755, 0, 0, 0, 5668, 83334, 0, 74645, 5670, 0, 0, 12741, 126619, - 123638, 5667, 19952, 120807, 113766, 12749, 0, 67757, 2263, 0, 0, 119260, - 129131, 9286, 83335, 128457, 83336, 70359, 0, 3571, 13247, 5874, 78279, - 73447, 68435, 78278, 78267, 78268, 0, 78265, 553, 113768, 0, 93053, 5829, - 0, 4587, 78285, 78299, 129699, 12746, 0, 70338, 0, 5633, 0, 94101, 94102, - 94099, 94100, 94105, 74856, 94103, 12742, 0, 983837, 0, 0, 0, 70330, 0, - 983830, 0, 0, 0, 12148, 0, 0, 0, 0, 0, 64938, 67234, 5634, 0, 0, 2146, 0, - 118880, 2425, 65182, 983832, 43636, 0, 83326, 328, 0, 68736, 0, 5636, - 123163, 5329, 0, 5638, 0, 7940, 0, 43223, 43760, 5635, 3373, 72424, - 78292, 74223, 73441, 68763, 78287, 9833, 0, 74208, 41635, 0, 77775, - 43040, 78297, 68778, 78295, 5639, 65603, 5660, 5640, 78303, 0, 78300, 0, - 68301, 0, 0, 78312, 0, 78310, 41625, 78308, 78309, 100731, 41780, 5642, - 100732, 100735, 100734, 4356, 100736, 100739, 12051, 70166, 100740, 5641, - 8259, 0, 0, 0, 119570, 0, 0, 121264, 983558, 0, 0, 0, 73890, 0, 0, 2800, - 11220, 5645, 64964, 8652, 83323, 0, 0, 121356, 5608, 128281, 119932, - 118562, 0, 0, 9000, 0, 83324, 92673, 129176, 0, 5613, 74267, 100721, - 100724, 5610, 100726, 92965, 100728, 5612, 100730, 10787, 0, 3615, - 123647, 5609, 78316, 78317, 78313, 78315, 5875, 5808, 0, 8186, 0, 74269, - 122977, 70004, 65874, 72422, 5807, 0, 66320, 5306, 12936, 0, 92970, - 127961, 0, 92583, 10211, 0, 0, 78871, 121063, 0, 129512, 0, 0, 0, 0, 0, - 74237, 0, 9133, 74262, 0, 92840, 0, 64779, 4672, 73529, 6185, 64776, 0, - 121266, 6499, 0, 0, 0, 92720, 0, 67494, 93791, 2534, 0, 93768, 93778, - 93762, 71849, 71869, 93781, 64583, 93761, 93780, 78922, 93787, 92443, - 128714, 71848, 93774, 66411, 93785, 71841, 93770, 93769, 0, 0, 0, 121168, - 68443, 69774, 931, 0, 125052, 6363, 2748, 0, 0, 0, 983603, 44011, 0, 0, - 100711, 119009, 100713, 100712, 100715, 65896, 100717, 78298, 100719, - 100718, 128836, 100720, 11649, 0, 0, 0, 0, 0, 42341, 65284, 0, 0, 12884, - 0, 7907, 127255, 0, 0, 0, 0, 68779, 0, 68786, 0, 100691, 0, 100693, - 100692, 42851, 100694, 100697, 100696, 92276, 78226, 66393, 100700, 0, - 93773, 93776, 93777, 100702, 78301, 100704, 100703, 42415, 78307, 4542, - 69909, 94022, 100709, 0, 0, 0, 0, 42454, 11565, 7949, 124939, 0, 0, - 42494, 3073, 0, 0, 42302, 0, 126553, 70810, 0, 72401, 0, 0, 0, 129319, - 4877, 100681, 100684, 100683, 10548, 100685, 100688, 100687, 100690, - 64798, 70805, 5346, 0, 126570, 124135, 4874, 124136, 0, 0, 0, 0, 65884, - 0, 0, 0, 11378, 0, 42785, 0, 3251, 11203, 0, 0, 0, 69568, 11052, 0, 5342, - 8317, 0, 0, 5340, 0, 122970, 128599, 0, 129538, 0, 128395, 0, 128510, 0, - 0, 9142, 0, 0, 0, 10938, 0, 0, 1182, 127381, 4829, 0, 0, 72438, 529, 0, - 0, 0, 10586, 10790, 10839, 121427, 41593, 100669, 0, 118532, 41594, 225, - 66418, 0, 0, 983969, 11376, 0, 41596, 0, 64975, 0, 0, 11084, 3194, 0, - 78306, 78305, 0, 0, 0, 11324, 0, 0, 8420, 127756, 128844, 0, 41338, - 129683, 11485, 0, 41322, 66605, 100671, 0, 100673, 100672, 100675, 5161, - 41330, 100676, 100679, 100678, 100659, 100658, 0, 100660, 0, 100485, - 12361, 0, 12359, 983559, 41369, 66412, 12191, 0, 0, 0, 0, 78221, 41376, - 0, 9870, 0, 41385, 65824, 100651, 11938, 100653, 100652, 100655, 100654, - 42678, 100656, 0, 64649, 0, 0, 0, 0, 0, 983967, 100662, 100661, 100664, - 66334, 100666, 70280, 832, 100667, 2240, 78473, 66007, 78471, 65703, 0, - 0, 0, 12357, 0, 41395, 0, 0, 0, 0, 0, 0, 983466, 0, 41114, 65466, 0, - 983844, 6024, 0, 9979, 0, 0, 0, 0, 0, 0, 0, 4285, 0, 0, 4230, 0, 7367, 0, - 92353, 7563, 42376, 0, 128532, 0, 0, 0, 0, 67500, 0, 78466, 0, 12208, - 128138, 0, 66311, 71309, 0, 41130, 78286, 0, 0, 70047, 0, 6022, 0, 0, 0, - 0, 0, 41125, 0, 66453, 0, 41107, 0, 41121, 5300, 129588, 0, 0, 128759, - 74801, 70855, 2074, 73456, 0, 0, 12453, 0, 0, 0, 0, 68159, 12457, 0, 0, - 66278, 0, 0, 0, 0, 0, 66637, 12455, 0, 128473, 0, 12449, 0, 71224, 0, 0, - 66908, 0, 10165, 0, 119249, 113715, 0, 128223, 0, 0, 0, 0, 4993, 0, 6168, - 74033, 4995, 0, 69459, 77756, 4639, 0, 72223, 0, 73478, 0, 0, 0, 73486, - 66991, 0, 0, 0, 0, 0, 0, 83310, 0, 0, 0, 0, 0, 0, 0, 0, 129594, 4953, 0, - 0, 0, 0, 83311, 0, 73453, 65688, 0, 10125, 3517, 0, 0, 0, 65094, 74791, - 78262, 10627, 66333, 78256, 78257, 83304, 78253, 0, 71317, 64923, 0, - 65208, 10608, 78263, 78264, 0, 0, 0, 65883, 0, 0, 74914, 0, 0, 6853, 0, - 0, 12912, 119012, 0, 128191, 0, 0, 129586, 0, 1290, 0, 0, 0, 0, 113719, - 71442, 0, 0, 8978, 0, 119135, 120979, 10527, 71079, 0, 0, 0, 0, 0, 0, - 5336, 0, 0, 6934, 0, 10780, 0, 0, 78767, 0, 0, 0, 347, 0, 0, 78775, - 64675, 41582, 78774, 78771, 68094, 74903, 78769, 69221, 69657, 0, 0, - 11153, 120981, 78526, 0, 0, 0, 0, 41584, 0, 69464, 0, 0, 0, 0, 43510, - 66661, 0, 66306, 78791, 66384, 0, 6609, 0, 0, 11319, 0, 66984, 0, 41730, - 0, 0, 127920, 0, 65172, 41728, 41721, 0, 0, 0, 41203, 0, 0, 41726, 0, 0, - 5758, 0, 0, 41140, 2028, 78092, 0, 0, 0, 92739, 983196, 41138, 0, 0, 0, - 125082, 1115, 127060, 9794, 127062, 67671, 92238, 12237, 78787, 66314, - 78785, 9290, 73668, 78783, 78780, 66985, 127144, 7926, 0, 0, 0, 64398, - 100924, 71274, 12311, 101268, 78796, 78798, 78794, 78795, 78792, 78793, - 0, 101270, 0, 73455, 0, 0, 0, 42142, 9968, 11583, 0, 7092, 129835, 9627, - 78536, 73677, 78535, 0, 0, 1248, 10148, 127755, 0, 0, 101273, 0, 66447, - 0, 0, 0, 0, 65305, 0, 4031, 42794, 119986, 0, 8154, 0, 0, 128028, 126259, - 129926, 125220, 73452, 0, 0, 0, 6696, 0, 119599, 0, 0, 0, 4364, 0, 0, 0, - 120976, 0, 120922, 0, 10124, 7526, 8601, 0, 68246, 0, 129318, 1418, - 10885, 0, 0, 0, 0, 0, 0, 4571, 0, 0, 0, 12078, 41597, 0, 10933, 0, 72129, - 67479, 0, 0, 41599, 0, 0, 0, 12950, 119190, 10498, 0, 66782, 4239, 0, 0, - 66511, 68066, 2637, 110685, 8460, 110683, 8476, 110681, 0, 110679, 0, - 127919, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5412, 66243, 9935, 122892, 0, - 73864, 41734, 8206, 74081, 0, 3286, 120730, 0, 0, 41732, 0, 41736, - 983203, 41731, 0, 0, 70842, 0, 0, 0, 0, 129329, 0, 66853, 0, 0, 78742, - 72755, 11277, 65892, 0, 10620, 92272, 68165, 0, 0, 0, 73942, 67001, - 100479, 0, 119093, 3459, 0, 129398, 0, 0, 72130, 92512, 0, 66377, 69781, - 128718, 0, 111304, 3161, 69981, 0, 0, 0, 0, 0, 9016, 78153, 0, 0, 43641, - 0, 121018, 0, 101279, 0, 0, 0, 0, 0, 68342, 120950, 94043, 0, 12332, - 121310, 6086, 41722, 0, 120709, 0, 0, 111305, 118677, 0, 128307, 74288, - 0, 74546, 124123, 129178, 124125, 92224, 42460, 0, 0, 0, 0, 120941, - 42421, 0, 41723, 110606, 64358, 11460, 983511, 0, 64718, 120838, 66869, - 0, 42348, 0, 6752, 452, 42500, 0, 128258, 0, 42308, 0, 0, 0, 12932, 0, - 69968, 42950, 66827, 917582, 0, 0, 8302, 0, 66929, 0, 0, 7250, 13214, - 10041, 8105, 65568, 127780, 69969, 127759, 0, 0, 121467, 0, 121466, - 41384, 0, 69878, 0, 5538, 9987, 111298, 118932, 129307, 0, 552, 0, 7357, - 10785, 66995, 0, 4557, 0, 0, 10171, 68320, 0, 5540, 0, 0, 281, 0, 0, - 42622, 0, 5536, 0, 0, 1388, 0, 0, 10504, 0, 0, 11531, 74324, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 3663, 0, 121081, 70335, 74859, 0, 5334, 0, 110738, - 72319, 0, 11305, 66997, 68456, 0, 66611, 0, 19907, 64363, 3478, 7583, - 7679, 74154, 0, 0, 1158, 0, 983890, 73748, 0, 0, 1915, 4846, 0, 120132, - 118984, 120134, 120129, 120128, 805, 120130, 64438, 120124, 8760, 120126, - 72137, 120120, 120123, 94003, 0, 0, 0, 0, 0, 12225, 0, 0, 0, 70173, - 75045, 0, 129515, 8083, 0, 0, 0, 111094, 92626, 0, 0, 0, 0, 0, 0, 110837, - 0, 67699, 560, 5643, 0, 0, 0, 0, 0, 0, 0, 120144, 0, 120661, 78304, 1597, - 120143, 120142, 206, 70126, 120139, 120138, 8168, 0, 73086, 0, 0, 0, - 118650, 125036, 0, 0, 3546, 42573, 66811, 67000, 0, 128397, 8400, 0, 0, - 0, 0, 0, 7903, 9287, 72791, 0, 0, 0, 0, 72134, 66603, 1695, 917861, - 124150, 0, 111101, 0, 0, 0, 0, 0, 0, 0, 111099, 0, 111098, 4754, 0, - 69222, 128229, 0, 0, 7354, 7408, 0, 0, 121181, 0, 0, 0, 12739, 0, 1278, - 4187, 0, 42119, 42120, 0, 121158, 0, 12467, 0, 68902, 0, 12463, 0, 0, - 118827, 0, 9664, 70834, 74475, 0, 0, 0, 0, 0, 3661, 0, 0, 9022, 127955, - 0, 101460, 126257, 0, 6118, 222, 126250, 3884, 0, 74151, 0, 6502, 0, - 11085, 121261, 0, 0, 0, 0, 0, 0, 0, 0, 12461, 0, 0, 0, 94059, 11254, - 10860, 64880, 0, 64685, 0, 0, 94087, 7776, 11219, 0, 0, 121339, 69730, - 801, 43165, 0, 78212, 0, 0, 13277, 0, 12951, 0, 9906, 5486, 2334, 128672, - 67680, 5483, 73732, 120884, 119128, 2256, 0, 127876, 2539, 0, 78507, - 5485, 69826, 42697, 0, 0, 113689, 4502, 68057, 253, 73672, 0, 0, 9203, 0, - 0, 0, 0, 0, 121242, 11127, 0, 0, 0, 13257, 0, 0, 0, 69645, 0, 0, 0, - 70431, 0, 5693, 64470, 0, 66610, 67678, 0, 983678, 0, 0, 0, 0, 0, 0, 0, - 94078, 0, 0, 66608, 3111, 0, 8804, 66607, 0, 0, 0, 66606, 0, 0, 0, 1436, - 0, 55226, 0, 111287, 7393, 41592, 0, 0, 1598, 78101, 0, 0, 65193, 4423, - 0, 113692, 10515, 41589, 0, 0, 0, 101485, 1430, 101486, 0, 120606, 0, - 66223, 7619, 3255, 128280, 74032, 11549, 10735, 93038, 100741, 6801, - 100743, 100746, 2148, 100748, 100747, 100750, 100749, 0, 121229, 101479, - 69243, 41724, 67716, 69669, 41690, 111269, 983666, 8380, 100355, 983849, - 0, 101480, 0, 0, 0, 0, 6333, 111264, 42315, 0, 129502, 111265, 0, 0, - 5339, 74323, 0, 13004, 0, 0, 0, 0, 0, 0, 5684, 0, 0, 0, 5689, 0, 0, - 68464, 12633, 12870, 0, 65183, 5688, 0, 0, 6310, 5686, 0, 0, 0, 120647, - 70046, 50, 94095, 9871, 0, 0, 121446, 0, 0, 0, 66905, 0, 4448, 0, 121406, - 113734, 72125, 1321, 0, 10640, 0, 0, 101497, 0, 0, 73542, 0, 0, 0, 0, 0, - 12501, 0, 0, 0, 0, 8812, 0, 69986, 8673, 0, 129024, 0, 0, 2105, 72101, - 72712, 0, 129929, 0, 0, 0, 4636, 55262, 77745, 4515, 2382, 0, 0, 7313, - 101477, 0, 0, 194626, 0, 0, 0, 0, 0, 0, 0, 10197, 194719, 0, 0, 0, - 194718, 0, 0, 0, 64189, 0, 1873, 0, 0, 0, 0, 0, 983682, 0, 0, 101499, - 72282, 126991, 71113, 0, 0, 129340, 9489, 0, 70843, 0, 0, 0, 0, 128030, - 13295, 43191, 0, 0, 1154, 0, 1205, 0, 0, 0, 12958, 0, 0, 0, 66968, 0, - 10592, 0, 495, 0, 41712, 7983, 0, 0, 0, 6347, 69465, 7654, 41710, 4196, - 0, 0, 41709, 73772, 70832, 0, 9465, 983783, 0, 0, 917612, 0, 72374, - 41714, 0, 0, 0, 6343, 72376, 0, 43996, 0, 8044, 66979, 0, 41789, 0, - 10809, 71953, 0, 0, 0, 8146, 11025, 0, 120513, 642, 0, 0, 0, 12875, 0, 0, - 13229, 71950, 41788, 0, 92835, 0, 41791, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 8428, 6569, 92851, 0, 0, 0, 10167, 0, 68248, 8049, 0, 0, 0, 0, 128882, - 4761, 0, 4766, 64623, 0, 121180, 194653, 118876, 0, 6912, 9232, 7033, 0, - 0, 41545, 0, 71970, 72160, 72107, 0, 0, 0, 3484, 0, 0, 0, 8503, 41539, - 41527, 0, 0, 983842, 0, 0, 66983, 41537, 0, 41541, 8282, 11817, 129965, - 128219, 0, 0, 126132, 0, 0, 70115, 66609, 111235, 65921, 0, 0, 194664, 0, - 129326, 77970, 42246, 75030, 120605, 0, 65926, 7744, 68859, 94056, 74277, - 126108, 0, 6966, 194633, 8136, 0, 0, 0, 0, 0, 4762, 0, 0, 0, 4765, 69443, - 983585, 66970, 4760, 0, 0, 10871, 43199, 194645, 0, 93955, 0, 0, 11546, - 0, 337, 0, 0, 0, 12279, 7768, 0, 128352, 0, 69812, 10143, 7883, 121444, - 7880, 64618, 13012, 5704, 13010, 0, 0, 119531, 0, 0, 0, 0, 66654, 0, 0, - 0, 13008, 0, 4385, 0, 13011, 0, 92569, 66972, 13009, 74771, 70159, 0, 0, - 41793, 64450, 74221, 120996, 41792, 111242, 94054, 126094, 0, 111244, - 5709, 120689, 71076, 0, 0, 0, 0, 0, 5708, 0, 0, 0, 5706, 66362, 5705, - 8791, 41797, 0, 10237, 66436, 0, 66974, 0, 0, 128083, 13170, 0, 127075, - 0, 0, 41377, 0, 0, 10058, 120735, 101431, 0, 0, 0, 0, 0, 0, 129641, - 119525, 0, 0, 72350, 0, 983584, 2144, 0, 120765, 0, 0, 1754, 92226, - 13246, 864, 0, 118926, 8972, 0, 7849, 0, 0, 13240, 0, 5192, 0, 0, 10948, - 0, 13199, 0, 1236, 13208, 13261, 13189, 13188, 93993, 0, 7440, 66976, 0, - 0, 1844, 125229, 0, 13178, 0, 0, 0, 125230, 0, 0, 13260, 4550, 121249, - 125227, 0, 71071, 0, 0, 68523, 0, 0, 11354, 94071, 0, 42795, 129317, 0, - 0, 0, 125237, 0, 13194, 13274, 0, 0, 129533, 65586, 68311, 0, 119193, - 4601, 194661, 101454, 194658, 0, 194659, 0, 121422, 128790, 194657, - 41717, 67402, 101444, 121129, 41716, 127376, 7910, 0, 0, 754, 41944, 0, - 8183, 120741, 2037, 101440, 0, 101441, 125, 0, 0, 0, 983125, 101442, - 41719, 0, 7990, 12637, 13258, 9536, 71056, 0, 4427, 0, 71200, 0, 12217, - 0, 41532, 129315, 0, 0, 0, 0, 111063, 83349, 0, 0, 120622, 0, 0, 0, 0, - 43632, 0, 0, 8140, 0, 6260, 0, 0, 66765, 129657, 0, 3898, 0, 0, 13200, 0, - 0, 66582, 0, 0, 0, 0, 1068, 71178, 13259, 12945, 0, 42203, 0, 3124, - 69411, 0, 4386, 12224, 6973, 129563, 0, 0, 119535, 0, 121312, 0, 12232, - 0, 0, 5681, 64578, 75023, 72016, 13209, 0, 0, 0, 0, 0, 11053, 0, 74902, - 128107, 128942, 7588, 0, 1693, 74942, 43204, 65831, 124120, 0, 0, 68803, - 111216, 111223, 0, 0, 65685, 9523, 2243, 0, 0, 0, 0, 0, 0, 0, 0, 13191, - 0, 3500, 3139, 100643, 3170, 100645, 100644, 66934, 100646, 13006, 64433, - 0, 100650, 941, 0, 0, 120967, 3727, 0, 0, 0, 72378, 0, 0, 118611, 94039, - 129299, 92455, 0, 0, 64444, 0, 0, 43603, 94075, 65397, 288, 0, 0, 0, - 10025, 73692, 0, 0, 68182, 0, 0, 0, 92438, 65395, 0, 0, 0, 65393, 83078, - 121111, 0, 122666, 0, 0, 0, 65394, 11548, 72305, 0, 65396, 0, 0, 13256, - 1282, 0, 0, 0, 111085, 0, 0, 0, 111087, 72115, 0, 0, 0, 0, 0, 3304, 0, 0, - 0, 126595, 72437, 68353, 0, 0, 42113, 0, 0, 0, 0, 0, 43094, 0, 0, 94037, - 68317, 9035, 0, 0, 0, 0, 0, 70822, 128467, 164, 68309, 94067, 94000, - 100631, 100634, 100633, 100636, 100635, 100638, 100637, 68808, 100639, - 110665, 73893, 11099, 110664, 13175, 13207, 0, 127552, 0, 74643, 5929, 0, - 0, 119502, 983654, 11306, 0, 119059, 3180, 125102, 0, 0, 0, 13062, 0, - 129551, 128707, 0, 0, 74428, 0, 128000, 0, 11251, 70204, 0, 10045, 0, - 13275, 0, 11057, 0, 13276, 125133, 41525, 983084, 128015, 11444, 0, - 129158, 0, 122642, 41523, 127765, 0, 0, 0, 0, 0, 0, 0, 3858, 0, 119573, - 0, 0, 0, 0, 0, 0, 101014, 369, 74908, 41784, 0, 120994, 0, 71180, 0, 0, - 13210, 41782, 0, 73536, 101388, 41781, 10486, 74058, 43002, 0, 0, 0, 0, - 0, 3741, 0, 0, 0, 118540, 41222, 0, 128317, 3982, 0, 4388, 126105, 746, - 0, 0, 0, 13131, 0, 0, 0, 0, 0, 10434, 8794, 122963, 0, 0, 0, 0, 0, 11700, - 4374, 129413, 0, 0, 0, 0, 0, 917597, 0, 69814, 0, 6735, 73979, 13174, - 73968, 13225, 0, 69808, 0, 0, 2365, 7841, 71476, 0, 120934, 66510, - 128099, 0, 0, 0, 41785, 41171, 0, 13173, 4372, 6854, 0, 0, 0, 128939, 0, - 0, 12965, 384, 0, 0, 12685, 41473, 0, 13242, 13236, 0, 0, 0, 41787, 0, - 70684, 0, 68486, 13272, 0, 13232, 13233, 65838, 0, 0, 11656, 0, 126110, - 119885, 12861, 0, 13271, 0, 92737, 1096, 0, 0, 0, 0, 0, 0, 2255, 5203, 0, - 92902, 0, 13243, 13237, 12719, 0, 0, 0, 64884, 78043, 43052, 0, 0, 0, - 12014, 0, 101415, 0, 0, 13195, 41452, 64961, 41535, 42969, 10459, 0, - 124949, 0, 0, 0, 41533, 66337, 0, 92184, 0, 126091, 0, 0, 73849, 0, - 43638, 0, 101398, 6261, 0, 129568, 0, 1957, 0, 0, 0, 13292, 13206, 0, 0, - 2925, 73809, 42576, 101395, 13212, 43238, 0, 13190, 13187, 0, 13198, 0, - 0, 5242, 0, 0, 128146, 0, 73535, 6770, 43331, 127539, 0, 0, 71074, - 126466, 73524, 41444, 0, 0, 64799, 5246, 119106, 13185, 9709, 0, 0, - 92751, 0, 5238, 0, 71085, 0, 5236, 40979, 0, 74201, 8286, 0, 3936, 92833, - 11699, 0, 127249, 13235, 69578, 41248, 127264, 13245, 13239, 0, 7969, - 127266, 74832, 127251, 0, 120509, 0, 983893, 734, 127270, 0, 127254, - 70297, 127273, 64921, 120969, 66631, 41771, 120490, 0, 983172, 41770, - 1670, 42560, 0, 121349, 129634, 0, 41163, 0, 11136, 0, 11506, 0, 42841, - 13267, 126109, 0, 41775, 0, 7130, 41773, 0, 0, 0, 0, 0, 0, 0, 42673, - 65572, 0, 65250, 13265, 13264, 64518, 66798, 6100, 0, 0, 6740, 71080, - 67814, 12967, 70028, 68101, 4583, 0, 0, 68097, 0, 0, 0, 0, 119211, 0, 0, - 42653, 83181, 68102, 0, 7814, 71045, 0, 73702, 0, 0, 0, 9756, 6985, 0, 0, - 74219, 0, 0, 129069, 124987, 5674, 0, 66421, 0, 5677, 5588, 0, 0, 0, 0, - 5673, 73488, 5676, 0, 94048, 0, 5672, 6476, 0, 128798, 110951, 42511, - 1727, 0, 0, 0, 0, 0, 0, 0, 3550, 736, 0, 4505, 5873, 74090, 5826, 55232, - 5813, 0, 120712, 5841, 5837, 55234, 0, 3105, 64370, 5838, 5796, 0, - 119592, 5793, 0, 5866, 5797, 41011, 5865, 0, 0, 71899, 0, 71235, 5806, - 73528, 0, 9037, 5671, 0, 0, 0, 0, 71266, 126616, 7296, 0, 0, 0, 0, 6980, - 0, 72108, 0, 0, 0, 0, 0, 64613, 983910, 0, 129969, 0, 78277, 7114, 0, - 72100, 43190, 93842, 128666, 72096, 42611, 42563, 0, 125080, 0, 6792, - 43201, 72098, 0, 128719, 0, 72106, 73534, 0, 5644, 0, 66627, 69727, 0, 0, - 0, 65116, 0, 0, 73526, 0, 66410, 94104, 41013, 0, 0, 0, 2869, 0, 41015, - 0, 2785, 120616, 0, 73907, 194689, 0, 0, 0, 194688, 4759, 0, 0, 43192, - 129913, 1170, 43365, 69810, 73908, 0, 902, 0, 0, 0, 0, 8122, 66420, - 129642, 0, 3861, 0, 11028, 0, 73820, 5714, 0, 0, 0, 807, 127001, 78474, - 0, 976, 113782, 0, 0, 0, 0, 0, 128657, 118801, 71043, 0, 127017, 0, 0, - 5582, 0, 0, 5798, 0, 0, 0, 128521, 0, 0, 68058, 120553, 983184, 0, 0, - 74933, 74283, 0, 0, 194698, 66044, 0, 0, 0, 0, 0, 10094, 0, 0, 10857, - 69225, 0, 0, 93, 0, 10954, 0, 0, 0, 8171, 0, 0, 82996, 0, 0, 0, 73527, - 92634, 0, 0, 5187, 120711, 71086, 118704, 0, 0, 0, 5232, 0, 41009, 0, - 41005, 0, 43205, 0, 0, 0, 194708, 0, 71054, 10028, 66478, 7076, 13182, - 100385, 0, 0, 0, 78782, 7972, 78786, 0, 0, 0, 78789, 11309, 3806, 71252, - 0, 0, 0, 78819, 0, 125218, 0, 127532, 0, 0, 0, 78817, 0, 64366, 65156, - 8814, 0, 0, 0, 0, 12836, 42725, 120079, 0, 0, 0, 0, 69258, 13255, 0, 0, - 7464, 0, 93831, 0, 0, 0, 0, 13213, 118557, 0, 64516, 0, 0, 0, 41007, - 983929, 0, 40995, 12209, 983933, 119136, 123635, 0, 0, 0, 0, 0, 69283, - 43558, 5522, 0, 71061, 0, 74105, 3633, 983931, 119364, 41234, 41231, 0, - 9771, 983936, 13251, 0, 0, 6262, 2784, 0, 71078, 8126, 66483, 0, 0, 441, - 0, 0, 0, 41002, 40999, 0, 129394, 7108, 0, 10890, 0, 74445, 8324, 0, 0, - 74817, 2813, 119056, 74853, 983690, 0, 0, 0, 1193, 10462, 65197, 13253, - 13252, 7829, 120992, 130032, 0, 0, 0, 77911, 0, 77907, 0, 10386, 0, - 41042, 0, 65944, 65683, 10338, 66469, 0, 0, 0, 0, 0, 41966, 0, 0, 0, - 68915, 0, 0, 911, 983889, 128932, 40963, 0, 65159, 0, 122950, 0, 5520, 0, - 0, 0, 0, 0, 0, 0, 42965, 0, 0, 0, 0, 0, 983892, 0, 0, 66839, 0, 0, 0, - 68647, 0, 5857, 68135, 92727, 119120, 983694, 13171, 0, 0, 0, 120338, 0, - 0, 0, 13250, 69663, 0, 92201, 66397, 0, 0, 0, 8761, 12942, 5748, 92713, - 92414, 0, 83174, 8796, 0, 0, 0, 43633, 0, 72805, 71073, 0, 0, 0, 0, 0, - 12843, 4520, 0, 0, 73004, 983691, 0, 0, 194935, 110754, 64345, 0, 983677, - 3457, 0, 0, 0, 110750, 110758, 110751, 0, 0, 10427, 0, 73859, 0, 9755, - 1110, 65239, 0, 0, 0, 0, 0, 0, 0, 194936, 0, 983821, 0, 70437, 3620, 0, - 0, 72855, 0, 0, 0, 74250, 0, 0, 11980, 0, 66482, 67823, 0, 128345, - 110768, 0, 0, 0, 0, 12891, 983786, 983667, 0, 2016, 0, 65668, 92311, - 67696, 10366, 70117, 9155, 120652, 9786, 65082, 0, 8579, 0, 0, 0, 0, - 4508, 64883, 0, 92522, 129847, 0, 64592, 74276, 67688, 0, 69270, 0, - 69456, 0, 113821, 0, 12147, 9024, 66378, 66472, 0, 0, 0, 0, 0, 71935, 0, - 0, 113697, 0, 0, 69285, 0, 74275, 0, 122896, 127941, 41214, 0, 67476, 0, - 0, 0, 7773, 0, 0, 9963, 68649, 0, 73734, 0, 0, 0, 0, 6594, 983771, 0, 0, - 3624, 70342, 0, 64655, 121481, 0, 0, 0, 0, 0, 65932, 0, 983809, 6803, - 120968, 7738, 0, 0, 120628, 129721, 66614, 122921, 0, 43810, 7029, 0, - 41292, 118898, 0, 43115, 9517, 11518, 0, 0, 0, 0, 64423, 0, 0, 0, 12503, - 9591, 4516, 0, 118845, 0, 0, 129479, 43650, 983193, 69250, 0, 0, 68079, - 0, 11397, 2884, 0, 0, 12678, 0, 0, 41014, 73730, 917539, 4270, 92254, - 127836, 68205, 6633, 118947, 0, 5230, 101055, 0, 0, 983234, 121392, 0, - 92985, 0, 0, 0, 0, 415, 0, 0, 0, 0, 5183, 1877, 0, 0, 0, 0, 0, 4472, 0, - 0, 0, 128285, 110682, 78230, 4756, 0, 7081, 0, 0, 0, 78606, 0, 42922, - 42103, 8628, 74861, 0, 0, 0, 43059, 10539, 0, 0, 0, 0, 0, 0, 0, 0, 64873, - 11992, 129444, 0, 0, 11801, 3622, 0, 0, 983215, 0, 0, 11521, 0, 1966, - 43628, 111048, 0, 0, 0, 0, 0, 0, 42098, 66671, 10694, 128520, 0, 0, 0, 0, - 42100, 0, 111040, 0, 42097, 0, 0, 0, 0, 11302, 118640, 129145, 43395, - 83259, 0, 0, 92351, 0, 0, 11299, 1561, 0, 92359, 92725, 69253, 0, 194733, - 0, 194730, 0, 127893, 11280, 0, 0, 983802, 0, 0, 72760, 0, 12486, 65018, - 66516, 5409, 0, 0, 194720, 5399, 9685, 0, 983713, 5401, 0, 0, 66832, 0, - 0, 5405, 0, 0, 0, 0, 0, 2235, 0, 11330, 983711, 64690, 3254, 0, 129974, - 0, 0, 43678, 0, 0, 983146, 0, 6388, 3355, 0, 9867, 0, 55258, 5611, 0, - 128527, 0, 0, 129181, 0, 78228, 0, 0, 119119, 0, 0, 194959, 0, 0, 1379, - 246, 0, 0, 64736, 0, 0, 0, 121227, 0, 0, 0, 0, 0, 0, 11855, 0, 0, 0, - 71961, 10656, 0, 65214, 119242, 0, 0, 13163, 0, 120831, 0, 0, 101484, 0, - 0, 0, 0, 0, 4755, 0, 122627, 11443, 0, 0, 0, 608, 600, 0, 8580, 128712, - 0, 43635, 0, 129695, 74485, 43808, 0, 0, 0, 13160, 0, 129418, 42268, - 128006, 70505, 9828, 0, 69261, 0, 0, 9351, 7778, 0, 0, 0, 6916, 1208, 0, - 0, 194754, 0, 0, 0, 0, 0, 83318, 83317, 0, 43539, 0, 72024, 0, 0, 0, - 9150, 66831, 0, 128322, 0, 66848, 0, 0, 12166, 128492, 194685, 0, 2546, - 0, 213, 0, 65611, 83316, 0, 0, 74310, 70836, 0, 65285, 5452, 0, 983938, - 92772, 0, 0, 0, 0, 65518, 129029, 12609, 194679, 125255, 123193, 0, 0, 0, - 74638, 194677, 125190, 4143, 110854, 110855, 65748, 4141, 9682, 110851, - 118790, 194674, 0, 0, 8725, 0, 66638, 0, 42263, 4145, 6380, 0, 66613, 0, - 119207, 0, 0, 9550, 100621, 0, 100623, 100622, 78050, 100624, 65753, - 100626, 65756, 72731, 0, 100630, 0, 0, 0, 0, 9657, 9019, 121154, 0, 0, - 5390, 0, 0, 194965, 72144, 69937, 69286, 6328, 0, 0, 0, 0, 0, 983047, 0, - 5235, 803, 69289, 0, 0, 127979, 43838, 0, 119562, 43544, 0, 0, 0, 0, - 194960, 70426, 9107, 5191, 119113, 0, 0, 0, 121099, 0, 0, 0, 0, 0, - 128150, 983067, 0, 7289, 74055, 0, 0, 0, 0, 0, 0, 0, 1784, 124947, 0, 0, - 0, 0, 64868, 0, 13158, 0, 7211, 0, 9371, 129378, 0, 0, 1625, 7664, 0, 0, - 0, 0, 0, 0, 69273, 0, 0, 0, 0, 4482, 118886, 0, 0, 0, 0, 0, 0, 0, 100612, - 66849, 100614, 100613, 100616, 444, 100618, 100617, 100620, 100619, 0, - 129401, 0, 11349, 40991, 0, 0, 129324, 0, 0, 1197, 0, 40993, 0, 0, 0, - 40990, 43765, 0, 3492, 0, 127942, 0, 0, 100592, 100591, 100594, 19948, - 100596, 3099, 92239, 100597, 100600, 100599, 0, 129042, 0, 0, 100601, - 194969, 100603, 8152, 100605, 100604, 100607, 100606, 100609, 12828, 0, - 75015, 0, 0, 129950, 0, 0, 75068, 127507, 0, 92680, 0, 0, 129928, 129920, - 0, 130037, 0, 118820, 0, 0, 0, 0, 0, 100581, 0, 100583, 100582, 100585, - 100584, 100587, 100586, 100589, 7576, 11995, 100590, 43260, 0, 0, 64830, - 0, 125046, 101526, 0, 43979, 8870, 0, 0, 42357, 0, 0, 12822, 0, 0, 0, - 118944, 0, 0, 42637, 0, 0, 70725, 0, 129934, 0, 71344, 0, 0, 72449, - 194745, 7170, 9596, 8277, 194743, 43629, 110610, 0, 0, 983571, 123545, 0, - 66699, 42952, 0, 0, 0, 43234, 66008, 12627, 0, 0, 0, 43619, 43303, 11300, - 0, 0, 8745, 0, 7558, 71342, 100570, 0, 0, 127881, 3461, 121258, 129471, - 69264, 0, 0, 0, 73877, 74335, 124982, 0, 0, 0, 64620, 74762, 12069, - 10838, 92548, 43616, 0, 10061, 0, 64840, 10508, 209, 0, 43193, 120581, 0, - 0, 128049, 0, 10899, 69855, 100571, 100574, 100573, 100576, 993, 100578, - 100577, 100580, 100579, 100560, 100559, 7232, 0, 0, 0, 0, 0, 0, 10489, - 42166, 0, 128588, 0, 0, 4224, 7671, 41518, 121311, 0, 0, 0, 0, 64820, - 92538, 12966, 100554, 100553, 100556, 100555, 100558, 100557, 4263, 8793, - 0, 0, 41502, 0, 983, 0, 100563, 100562, 13086, 4109, 4274, 841, 5888, - 100568, 68522, 0, 43481, 0, 120926, 0, 7209, 0, 41505, 0, 78698, 127012, - 0, 2147, 0, 0, 66629, 0, 0, 1255, 4149, 0, 0, 66633, 0, 129391, 92352, 0, - 65101, 0, 0, 0, 0, 5835, 128797, 66625, 10842, 0, 42123, 0, 0, 66634, - 1094, 66636, 0, 0, 0, 0, 0, 9972, 73865, 129289, 6114, 0, 0, 0, 0, 93960, - 0, 0, 0, 0, 12070, 0, 881, 7857, 0, 65164, 0, 0, 118703, 124151, 0, - 64404, 64321, 0, 125187, 0, 0, 11245, 129395, 69506, 71859, 128886, 0, 0, - 1287, 121509, 0, 0, 0, 125264, 74152, 120504, 64545, 0, 69668, 8985, 0, - 0, 0, 0, 0, 0, 3652, 0, 0, 0, 0, 0, 279, 0, 0, 0, 0, 1489, 125189, 0, 0, - 3899, 0, 42124, 43828, 42122, 0, 0, 0, 11985, 73755, 78600, 0, 0, 10988, - 0, 0, 42138, 78610, 0, 65768, 78608, 78604, 78605, 6285, 78603, 78612, - 78613, 74339, 65767, 8685, 0, 0, 0, 78622, 78623, 68475, 11470, 64538, - 78618, 78615, 78616, 0, 0, 0, 101534, 2527, 0, 128209, 2799, 0, 0, 0, - 9933, 0, 0, 767, 5524, 7028, 0, 101520, 0, 0, 0, 78633, 67481, 0, 94011, - 0, 6971, 0, 70731, 0, 0, 118979, 126075, 2434, 94018, 0, 120579, 0, 4631, - 0, 0, 6407, 0, 19931, 0, 0, 124905, 0, 3192, 0, 8414, 0, 0, 0, 124902, 0, - 9164, 66612, 93959, 8228, 124897, 0, 0, 0, 78624, 0, 0, 9993, 0, 0, - 129350, 78631, 78632, 78629, 78630, 78627, 78628, 78625, 2399, 0, 92399, - 71202, 41208, 0, 0, 8178, 2149, 3367, 0, 78640, 78641, 78636, 78638, - 78634, 6337, 0, 78909, 0, 0, 11068, 0, 9331, 0, 74798, 9181, 0, 0, 8017, - 0, 0, 0, 0, 0, 0, 0, 12126, 119494, 129306, 0, 0, 69650, 0, 0, 0, 43436, - 983744, 0, 0, 0, 0, 66845, 69249, 0, 0, 5398, 0, 127386, 93953, 0, 0, 0, - 0, 0, 9476, 68899, 0, 12763, 126603, 74788, 0, 42114, 11181, 92502, 0, 0, - 0, 3469, 42107, 42116, 0, 0, 119493, 0, 9853, 69648, 9040, 101518, 64665, - 119557, 0, 0, 0, 69638, 12602, 983068, 3852, 0, 67872, 12231, 11317, 0, - 119812, 0, 11410, 10964, 12274, 122890, 100524, 0, 119810, 9865, 195019, - 0, 0, 0, 0, 12276, 0, 124919, 0, 0, 119613, 0, 111214, 10467, 0, 2443, - 10918, 0, 0, 1001, 9241, 1927, 0, 0, 0, 127885, 195022, 0, 113752, - 119830, 65678, 0, 0, 8260, 0, 7519, 11505, 101505, 0, 518, 0, 119832, 0, - 13204, 0, 857, 121252, 0, 0, 92336, 83177, 0, 0, 0, 0, 0, 0, 92762, 0, 0, - 120613, 67247, 1629, 124926, 796, 0, 0, 74123, 72334, 127587, 72336, - 43388, 0, 43944, 72335, 478, 65151, 0, 128147, 0, 0, 0, 0, 0, 42933, - 1206, 71209, 43837, 0, 3843, 12011, 0, 3361, 0, 8121, 10715, 7578, 0, 0, - 0, 10530, 12348, 8653, 0, 73545, 0, 9551, 0, 0, 784, 0, 0, 0, 0, 0, 0, - 43937, 0, 0, 43938, 43935, 73765, 66230, 0, 0, 0, 43936, 0, 43932, 11102, - 0, 0, 42753, 67165, 0, 78324, 0, 0, 6975, 917928, 5415, 12176, 0, 0, - 3462, 43940, 42629, 78691, 128016, 43942, 0, 9759, 0, 0, 78320, 8114, - 78321, 78697, 78696, 78695, 8710, 118812, 118956, 0, 4051, 92657, 0, - 71206, 0, 0, 0, 128857, 0, 1619, 9703, 77986, 0, 42112, 0, 1875, 0, - 42109, 0, 0, 71189, 121160, 64907, 5396, 13144, 0, 0, 5575, 9675, 0, - 5940, 226, 0, 6336, 0, 0, 0, 5116, 64521, 0, 0, 0, 121390, 125048, 74138, - 0, 74139, 128447, 92249, 0, 0, 0, 0, 8935, 0, 0, 0, 0, 616, 78131, 65178, - 4684, 78701, 983899, 74631, 0, 0, 0, 74460, 42110, 0, 10870, 8557, 11054, - 68664, 0, 0, 0, 122629, 0, 0, 0, 0, 65597, 0, 7651, 6846, 0, 0, 68868, 0, - 0, 118966, 129302, 40997, 127218, 0, 0, 40998, 0, 74488, 71182, 9800, 0, - 0, 0, 41000, 0, 5114, 55263, 3386, 70730, 42574, 0, 5115, 5394, 0, - 128756, 5113, 0, 64855, 0, 4425, 0, 0, 0, 43967, 0, 0, 0, 5112, 12173, - 127037, 0, 0, 74998, 118668, 0, 0, 0, 0, 64874, 43964, 1587, 0, 0, 0, 0, - 1369, 917931, 9959, 0, 43963, 4560, 0, 0, 0, 0, 124896, 0, 43961, 42601, - 4514, 72149, 0, 0, 0, 65041, 10965, 120905, 0, 0, 12542, 0, 65341, 0, - 65829, 0, 0, 10475, 0, 0, 0, 0, 11795, 0, 0, 2164, 127102, 127101, 74956, - 7099, 11275, 67681, 127096, 0, 9336, 0, 42626, 43966, 7798, 64474, 64259, - 0, 5730, 119809, 43018, 983175, 93796, 0, 0, 0, 69401, 0, 0, 5127, 11285, - 0, 5495, 4273, 0, 74765, 10849, 6346, 5493, 6342, 68636, 74319, 5492, 0, - 0, 169, 5497, 125053, 0, 0, 68198, 0, 0, 128417, 0, 0, 12738, 0, 983076, - 5321, 0, 0, 0, 5323, 120732, 9773, 125209, 4683, 74318, 0, 68823, 0, 0, - 0, 0, 129553, 0, 123562, 0, 0, 834, 0, 1803, 0, 5733, 0, 0, 71312, 5731, - 1381, 2891, 128639, 0, 127212, 64525, 0, 2881, 92996, 93847, 9601, 2879, - 0, 0, 73129, 5729, 0, 0, 0, 64881, 127905, 9361, 0, 2887, 0, 3526, 6298, - 0, 121219, 0, 0, 0, 8572, 127863, 77896, 0, 71174, 0, 0, 71197, 0, 12096, - 0, 0, 0, 110745, 71176, 110746, 65279, 0, 121236, 5734, 0, 0, 0, 0, 0, - 41641, 12717, 0, 12552, 983615, 66713, 0, 0, 41643, 110747, 0, 8713, - 41640, 78657, 41645, 66712, 125196, 0, 66726, 66711, 0, 93994, 0, 3472, - 64863, 0, 121424, 0, 0, 0, 125203, 67837, 0, 0, 0, 0, 0, 0, 121440, 0, 0, - 129461, 119008, 92402, 65017, 0, 0, 66668, 0, 0, 0, 0, 0, 119822, 0, 0, - 124148, 0, 0, 0, 0, 0, 0, 0, 0, 121043, 66471, 12216, 0, 40988, 0, 0, 0, - 0, 0, 2396, 129078, 0, 0, 0, 64940, 0, 8321, 119823, 128165, 100409, - 83299, 996, 0, 0, 4249, 0, 83294, 92535, 8222, 0, 118875, 71213, 0, 0, 0, - 0, 8534, 72844, 40983, 0, 125195, 0, 12551, 73960, 125193, 74469, 12558, - 121039, 0, 10052, 40982, 129371, 0, 0, 0, 127403, 0, 917559, 0, 78364, - 1563, 0, 0, 19911, 0, 0, 0, 71363, 0, 7797, 78708, 10006, 0, 3308, - 119134, 74940, 0, 0, 78488, 0, 0, 0, 0, 0, 128462, 9200, 10046, 9612, 0, - 8218, 66496, 0, 43742, 78489, 0, 0, 0, 0, 67826, 0, 70056, 508, 128585, - 0, 126539, 0, 0, 0, 0, 0, 0, 0, 124950, 0, 194601, 0, 0, 0, 0, 6659, 0, - 0, 0, 0, 0, 0, 41634, 0, 41639, 71169, 11941, 0, 0, 0, 42180, 68505, - 43753, 3249, 41637, 93982, 12328, 501, 93985, 10601, 129783, 6503, 0, - 92192, 0, 71181, 0, 6505, 74010, 0, 13064, 126112, 121105, 6500, 5526, 0, - 128949, 0, 0, 92376, 0, 9678, 120832, 0, 41706, 0, 0, 0, 8936, 92964, - 119123, 4208, 0, 0, 0, 67742, 0, 74379, 128605, 0, 0, 92422, 983110, 0, - 66475, 0, 5027, 0, 0, 0, 5069, 0, 5028, 0, 0, 0, 5026, 0, 0, 6331, 0, 0, - 0, 0, 41076, 0, 74790, 0, 0, 0, 0, 5029, 0, 5317, 3598, 0, 41070, 92166, - 11185, 6663, 0, 6507, 0, 126079, 0, 1716, 983710, 0, 917824, 620, 41001, - 0, 917823, 43758, 0, 71116, 5024, 0, 41003, 0, 5025, 7297, 122988, 75039, - 69745, 119328, 65557, 0, 0, 983599, 0, 0, 0, 0, 43947, 43946, 0, 0, - 128363, 6105, 0, 119325, 983230, 0, 68203, 43945, 66491, 43939, 0, 68144, - 78718, 2301, 0, 0, 66490, 6979, 101561, 7721, 0, 0, 1592, 0, 0, 121096, - 41048, 129358, 829, 0, 92406, 0, 73541, 0, 41056, 0, 118665, 10953, - 41066, 0, 917813, 482, 101554, 0, 0, 43606, 71185, 0, 917926, 0, 72262, - 110863, 72421, 12050, 0, 5315, 917817, 0, 0, 42061, 917816, 0, 0, 68417, - 917815, 0, 0, 42059, 0, 0, 120723, 42058, 3960, 11043, 11337, 121358, 0, - 92824, 3958, 101568, 0, 917818, 0, 917819, 0, 0, 42064, 11959, 983714, 0, - 0, 0, 0, 73511, 64336, 10478, 92629, 70350, 118692, 0, 0, 42437, 1555, 0, - 8691, 129656, 2215, 41662, 119046, 0, 0, 0, 93952, 0, 66481, 41664, 0, - 42578, 0, 41661, 78715, 78714, 9356, 0, 129544, 0, 1286, 110701, 0, 0, - 983208, 128925, 42476, 0, 11156, 78895, 0, 0, 101583, 72123, 0, 10020, - 43359, 72827, 0, 120946, 41627, 0, 11979, 0, 41628, 533, 11931, 65225, 0, - 125122, 129994, 0, 68118, 0, 4377, 0, 0, 8587, 72097, 13193, 64350, - 68233, 0, 41924, 0, 7735, 0, 127585, 120843, 0, 65820, 0, 0, 43461, 7757, - 0, 0, 43787, 66493, 77943, 4168, 43904, 73952, 0, 0, 121072, 4440, 43902, - 77948, 66837, 77946, 43903, 77944, 77945, 0, 120909, 120826, 120226, - 66492, 43901, 64625, 0, 0, 0, 0, 10013, 64434, 0, 983113, 0, 11782, - 64382, 0, 0, 0, 0, 41630, 630, 120960, 0, 0, 70165, 1043, 93017, 0, 0, 0, - 124945, 313, 129590, 0, 0, 65593, 7445, 43906, 5750, 42258, 0, 55222, - 68222, 11268, 11225, 0, 8526, 0, 0, 43894, 66495, 69990, 0, 92990, 0, - 10707, 7863, 0, 0, 70692, 631, 77952, 77953, 66443, 71171, 83313, 0, 0, - 0, 13305, 77961, 43925, 43924, 77956, 77957, 66903, 66328, 42381, 77962, - 0, 0, 0, 0, 0, 0, 43899, 66821, 77967, 9157, 77965, 77966, 77963, 77964, - 0, 0, 180, 73904, 0, 0, 66494, 12674, 43896, 0, 0, 43890, 43897, 0, - 11535, 0, 66769, 5185, 7165, 5521, 10334, 5519, 71329, 10302, 12351, - 83333, 1027, 5181, 0, 5117, 2186, 5179, 73955, 6845, 991, 3332, 43676, - 41647, 0, 73883, 92571, 77979, 3405, 69572, 0, 5523, 43915, 66487, 92459, - 74943, 9549, 0, 125093, 43923, 0, 43682, 74884, 120537, 0, 43921, 0, - 71184, 0, 43922, 128709, 0, 10414, 9846, 0, 10350, 0, 43918, 77981, - 75075, 77978, 77980, 66485, 77977, 77973, 77974, 78057, 43909, 73983, - 12330, 0, 0, 0, 43910, 69291, 3407, 6293, 0, 68149, 43908, 129060, 0, - 10209, 0, 4195, 0, 9010, 983705, 75072, 6332, 0, 0, 65871, 0, 1736, 0, - 3901, 0, 0, 65890, 128801, 10446, 0, 693, 9130, 314, 78119, 64149, 0, 0, - 0, 11026, 0, 5332, 6940, 0, 0, 127007, 119831, 0, 273, 8165, 118551, - 83307, 0, 0, 12824, 43911, 4528, 5320, 6301, 43662, 6133, 0, 9463, 73738, - 127141, 10922, 121069, 0, 0, 0, 0, 0, 2569, 0, 2326, 0, 2565, 0, 66401, - 0, 0, 0, 0, 41848, 2567, 78620, 121145, 4044, 92646, 0, 12233, 0, 9509, - 0, 0, 127158, 7336, 0, 0, 0, 129598, 0, 67235, 0, 0, 0, 0, 2222, 66499, - 0, 127170, 0, 10895, 118682, 274, 983782, 1858, 0, 67849, 55251, 2172, - 3133, 0, 71857, 0, 9610, 0, 8197, 0, 0, 0, 41665, 5868, 0, 0, 72120, 0, - 19940, 43668, 41667, 0, 0, 1923, 0, 0, 0, 0, 0, 0, 0, 0, 6464, 92750, - 2996, 125221, 0, 68481, 41835, 4047, 41842, 0, 0, 129601, 0, 0, 0, 0, - 293, 0, 0, 64791, 41827, 0, 0, 10579, 8560, 0, 0, 118835, 4803, 73805, - 1739, 0, 3900, 128967, 73737, 0, 72451, 73957, 0, 66474, 41971, 0, 0, 0, - 0, 0, 11716, 66473, 0, 92647, 0, 78920, 0, 0, 0, 0, 0, 0, 0, 6632, 73861, - 0, 74770, 0, 0, 8914, 0, 0, 3183, 1435, 0, 0, 0, 0, 0, 0, 5746, 67392, 0, - 0, 0, 83506, 0, 7082, 71481, 12618, 5059, 983597, 83524, 43604, 0, 0, 0, - 0, 0, 0, 8227, 0, 1218, 0, 64416, 65848, 92884, 0, 0, 0, 126987, 0, 0, 0, - 0, 0, 0, 83515, 83507, 0, 0, 42672, 71194, 43224, 0, 0, 0, 0, 0, 0, 0, - 65905, 0, 42662, 0, 121159, 0, 129536, 0, 7794, 0, 42953, 6377, 0, - 126080, 3669, 3968, 0, 71319, 69658, 129550, 0, 66296, 118616, 0, 0, 0, - 124998, 6699, 126120, 0, 0, 66678, 0, 0, 0, 8409, 119527, 19967, 0, 0, - 9502, 0, 0, 6115, 0, 41654, 0, 0, 0, 41655, 113779, 43975, 72427, 128080, - 0, 0, 0, 41657, 10778, 0, 9533, 184, 1553, 128868, 69574, 0, 0, 0, - 129420, 0, 101589, 983576, 73697, 0, 92480, 0, 128938, 74292, 0, 5157, - 4020, 0, 128154, 43788, 64818, 0, 0, 0, 92979, 0, 0, 74377, 11029, 66651, - 0, 0, 125202, 0, 0, 7877, 121070, 101411, 0, 119828, 2810, 9955, 0, - 69375, 42817, 0, 65122, 11715, 0, 0, 0, 71270, 0, 0, 0, 0, 0, 70199, 0, - 0, 0, 0, 0, 0, 127862, 0, 0, 0, 78222, 127981, 0, 0, 0, 0, 0, 11290, 0, - 0, 0, 0, 8315, 0, 0, 0, 74595, 0, 0, 0, 42531, 0, 0, 0, 74589, 43993, 0, - 0, 0, 0, 43690, 0, 119139, 42730, 0, 0, 0, 64926, 0, 0, 43830, 65257, 0, - 42728, 0, 128697, 123150, 0, 43540, 0, 0, 12725, 72993, 78635, 127826, - 223, 0, 69675, 0, 0, 0, 0, 0, 0, 42605, 0, 0, 0, 0, 0, 0, 0, 0, 78621, 0, - 78619, 119062, 0, 0, 0, 42676, 129353, 64800, 78617, 83504, 68126, 1213, - 0, 0, 797, 0, 0, 83021, 83005, 64387, 4115, 0, 0, 0, 129857, 10679, - 83001, 121091, 0, 64276, 83498, 13168, 83011, 0, 10136, 0, 0, 65088, 0, - 4262, 129866, 0, 0, 10701, 0, 3101, 0, 123204, 0, 0, 11373, 0, 0, 12731, - 9117, 0, 0, 4539, 0, 0, 12727, 0, 0, 0, 43684, 74567, 68877, 983726, - 12724, 73940, 0, 0, 0, 0, 0, 7947, 12003, 0, 74593, 121140, 69653, 74807, - 42018, 0, 0, 0, 65888, 0, 0, 69683, 0, 120306, 0, 0, 12595, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 69848, 68307, 0, 4405, 0, 128336, 129032, 69216, 0, - 128011, 118656, 0, 6817, 67400, 120314, 0, 0, 998, 0, 13105, 120313, - 64327, 1558, 0, 1991, 7882, 0, 0, 0, 530, 0, 0, 0, 12002, 0, 68422, 0, - 10979, 0, 41823, 70696, 0, 0, 7896, 0, 66676, 0, 120325, 0, 0, 129407, - 94033, 0, 6311, 110725, 41698, 0, 12049, 78133, 0, 125020, 41705, 0, 0, - 121298, 0, 66822, 0, 65389, 0, 66027, 0, 0, 41699, 8340, 0, 69776, 0, - 78921, 0, 1988, 5407, 69978, 0, 65912, 93059, 0, 2336, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 126238, 0, 19913, 0, 113733, 0, 0, 74279, 0, 10956, 0, 41674, - 19964, 41679, 65084, 41675, 195031, 0, 0, 0, 0, 983089, 0, 10794, 128961, - 13217, 0, 0, 0, 5280, 0, 0, 12905, 41610, 11532, 0, 0, 768, 120545, 442, - 0, 0, 0, 64081, 41682, 0, 41693, 0, 77993, 77994, 0, 4804, 6994, 983115, - 0, 0, 41696, 467, 983934, 0, 0, 0, 0, 8678, 0, 69682, 64801, 0, 0, 0, - 2193, 64093, 12043, 0, 69666, 0, 2029, 65191, 119246, 42847, 0, 0, 0, 0, - 0, 0, 0, 70339, 126116, 0, 0, 8019, 73856, 0, 0, 0, 118709, 2355, 12150, - 65725, 77988, 77989, 68033, 77987, 0, 77985, 0, 0, 68388, 0, 74171, 0, 0, - 0, 11301, 78013, 78008, 78010, 9874, 78007, 983331, 71064, 3050, 0, 0, 0, - 78016, 78017, 71852, 78015, 0, 0, 0, 92242, 0, 69642, 0, 0, 43883, 0, 0, - 0, 78025, 0, 78023, 78024, 11847, 10545, 0, 10887, 0, 123179, 0, 0, 0, - 83352, 64942, 92363, 9996, 8508, 0, 0, 8195, 0, 42171, 0, 3722, 0, 63751, - 0, 0, 92637, 69670, 0, 41552, 69854, 0, 78639, 0, 0, 129374, 128978, 0, - 0, 0, 7920, 70285, 4021, 0, 0, 0, 119663, 0, 0, 78021, 78022, 78019, - 78020, 1802, 78018, 0, 74895, 41659, 41671, 1827, 0, 64396, 41668, - 128524, 41673, 0, 11422, 71846, 0, 11370, 0, 68412, 41345, 0, 0, 0, 0, 0, - 0, 65114, 0, 2104, 64858, 0, 0, 7553, 0, 41560, 11970, 0, 917920, 0, - 68495, 74131, 74130, 0, 0, 0, 611, 74129, 64871, 129958, 0, 0, 0, 74854, - 0, 70466, 0, 0, 0, 121147, 0, 68487, 41669, 7094, 917921, 0, 123144, - 74054, 0, 0, 0, 839, 0, 7695, 0, 0, 0, 92202, 0, 121053, 123157, 67885, - 0, 7206, 0, 6647, 43986, 129743, 0, 0, 122646, 0, 0, 127936, 43748, - 66746, 0, 12298, 110802, 984011, 110800, 64924, 0, 73931, 9468, 74245, 0, - 0, 74246, 0, 0, 118830, 0, 71851, 1279, 0, 6224, 0, 92405, 128601, - 129886, 128997, 0, 0, 0, 5032, 0, 0, 0, 0, 0, 5034, 0, 0, 72846, 42702, - 0, 0, 13294, 0, 64869, 0, 67808, 9129, 123632, 0, 0, 120819, 68387, - 120168, 120169, 120170, 120171, 5518, 4174, 120166, 66932, 120160, - 120161, 120162, 434, 41437, 66212, 120158, 120159, 0, 0, 118867, 0, 524, - 0, 74029, 0, 126559, 0, 0, 0, 10355, 10419, 74025, 77847, 0, 69725, 0, - 120656, 0, 67876, 0, 0, 0, 74145, 74039, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 5445, 0, 93779, 71855, 7391, 8989, 0, 74068, 0, 0, 0, 0, 4962, 120409, - 8855, 0, 70820, 0, 0, 0, 0, 71847, 0, 120406, 0, 10451, 0, 67653, 120153, - 12443, 120155, 9947, 120149, 120150, 120151, 13128, 0, 120146, 120147, 0, - 0, 0, 0, 0, 129715, 74059, 74062, 6217, 74053, 43846, 0, 74049, 0, 0, 0, - 0, 0, 0, 0, 0, 42595, 0, 68112, 118860, 0, 0, 92497, 74949, 128953, - 126245, 0, 0, 0, 42997, 122984, 119251, 0, 0, 0, 0, 0, 6216, 0, 0, 9455, - 127027, 8124, 128851, 0, 6944, 0, 0, 0, 2828, 128550, 531, 42638, 0, 0, - 129888, 43428, 0, 3614, 2827, 9696, 0, 129711, 0, 4354, 0, 78562, 78561, - 0, 118553, 0, 42599, 42597, 0, 68829, 125012, 0, 127277, 0, 120421, 0, - 983165, 0, 0, 10121, 120422, 74950, 123142, 69715, 0, 0, 120423, 120630, - 12608, 125244, 0, 74144, 9700, 12580, 0, 128911, 0, 71864, 0, 74071, 0, - 0, 12713, 0, 70402, 0, 0, 0, 1734, 0, 0, 0, 119491, 118951, 231, 0, - 74167, 542, 0, 0, 0, 0, 128074, 0, 121343, 0, 4446, 10584, 74235, 0, - 4037, 0, 0, 0, 5687, 0, 0, 0, 0, 0, 0, 78434, 92816, 0, 113709, 74284, 0, - 0, 0, 126495, 0, 0, 0, 74482, 93978, 1709, 69721, 9909, 92286, 0, 0, 0, - 55229, 8667, 0, 0, 0, 0, 0, 0, 0, 0, 127586, 1226, 6930, 124146, 71736, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 41500, 0, 311, 74282, 6221, 92988, 0, 67682, - 0, 120528, 122901, 74272, 0, 0, 0, 0, 69667, 0, 124933, 74456, 74302, - 42589, 0, 0, 0, 0, 64847, 0, 66987, 0, 41508, 0, 323, 125211, 0, 42698, - 8131, 0, 4625, 0, 4630, 0, 0, 0, 74316, 78417, 2668, 92483, 0, 42640, 0, - 2519, 0, 92474, 92479, 0, 983085, 5049, 42659, 119011, 64705, 7754, - 10854, 8738, 74623, 0, 0, 0, 649, 0, 0, 73480, 0, 0, 1013, 70707, 68212, - 705, 0, 0, 127803, 1183, 126519, 9320, 0, 0, 8157, 0, 0, 0, 0, 0, 0, 0, - 11913, 0, 42848, 0, 64925, 0, 0, 70693, 0, 0, 2051, 0, 0, 0, 66988, 0, 0, - 0, 8466, 0, 4626, 8464, 8472, 68844, 4629, 8499, 0, 0, 4624, 194623, 0, - 94025, 0, 7805, 0, 94007, 6935, 0, 0, 0, 0, 0, 0, 0, 8492, 0, 8459, 0, - 8497, 8496, 0, 129864, 0, 0, 129834, 69553, 73476, 0, 65849, 0, 0, 0, - 12451, 3328, 8684, 0, 6102, 0, 5298, 110881, 5294, 0, 129615, 0, 0, 0, 0, - 43617, 0, 0, 0, 0, 0, 77863, 128695, 0, 0, 0, 0, 0, 5292, 0, 0, 42688, - 5302, 3970, 73516, 0, 1793, 0, 0, 0, 0, 0, 65263, 0, 0, 0, 0, 0, 0, - 13219, 9569, 69567, 74383, 0, 0, 72157, 0, 42949, 0, 0, 0, 5322, 0, 0, - 43631, 5324, 0, 128694, 41614, 65269, 6230, 0, 0, 0, 3360, 0, 11523, - 72726, 92488, 9926, 7197, 0, 68429, 126575, 41821, 1249, 0, 127951, 0, - 123641, 0, 0, 0, 74459, 41807, 0, 41815, 0, 0, 0, 119918, 0, 128248, 0, - 66835, 0, 0, 72145, 41800, 0, 0, 0, 41811, 74466, 93966, 6670, 77882, 0, - 0, 43092, 0, 0, 0, 0, 0, 128655, 0, 0, 0, 0, 74501, 74005, 0, 74387, - 69860, 315, 12813, 128556, 72409, 0, 72408, 0, 0, 73061, 0, 0, 1378, 0, - 0, 0, 72407, 3066, 0, 0, 72406, 0, 0, 0, 8787, 194615, 0, 41618, 0, 0, 0, - 194614, 64652, 194611, 42088, 125226, 0, 0, 0, 0, 7176, 43756, 0, 122649, - 74492, 0, 74534, 0, 0, 0, 127199, 0, 128630, 74525, 0, 194594, 12930, - 7168, 74514, 0, 74515, 0, 128919, 43962, 9527, 120659, 70123, 12977, - 69723, 0, 93783, 194598, 41236, 92235, 65168, 118838, 41237, 5848, 0, - 194600, 3670, 129905, 129906, 129907, 129908, 7890, 0, 11298, 0, 0, 6229, - 0, 0, 0, 194593, 128907, 0, 0, 194592, 4120, 65337, 65336, 0, 0, 0, 0, - 9366, 0, 0, 0, 65327, 65326, 65325, 65324, 65323, 42216, 65321, 65320, - 65335, 65334, 65333, 65332, 65331, 65330, 65329, 42689, 0, 43943, 118885, - 42073, 6785, 68491, 0, 42076, 7196, 65318, 2035, 65316, 4106, 65314, - 65313, 42074, 0, 41228, 0, 0, 41241, 93786, 41239, 43533, 0, 7189, - 194602, 0, 43941, 0, 42802, 0, 8487, 0, 0, 4615, 12695, 0, 0, 12175, - 100414, 0, 0, 7809, 0, 0, 0, 0, 6590, 69762, 0, 64738, 0, 0, 0, 0, 0, 0, - 2025, 0, 0, 0, 10637, 71860, 0, 1570, 43839, 2835, 83052, 10624, 43623, - 194587, 0, 78433, 0, 42812, 0, 2825, 0, 128287, 0, 2821, 0, 92327, 7365, - 83043, 0, 68296, 0, 2823, 0, 0, 0, 2831, 0, 0, 11465, 0, 0, 0, 0, 0, - 7181, 92855, 41332, 0, 12333, 0, 0, 0, 124914, 0, 9883, 127294, 73906, - 70751, 0, 71863, 0, 0, 0, 0, 0, 0, 43741, 0, 8166, 70739, 0, 0, 74535, 0, - 65297, 68294, 571, 0, 8752, 0, 5288, 118822, 1541, 0, 127284, 8864, 0, - 73559, 0, 0, 0, 113778, 12151, 0, 66874, 0, 1035, 0, 0, 7881, 701, 65936, - 128493, 0, 70462, 0, 11403, 0, 0, 82991, 0, 983143, 70472, 3994, 11421, - 121217, 127297, 127242, 127300, 70659, 127303, 0, 125205, 2855, 127828, - 0, 41621, 68214, 0, 0, 10654, 82945, 119226, 12164, 41623, 7906, 0, - 74297, 7182, 0, 83069, 0, 0, 0, 0, 121115, 0, 0, 747, 0, 92463, 12019, - 43136, 0, 110861, 0, 0, 8001, 0, 0, 69394, 0, 0, 0, 68373, 0, 0, 0, - 128279, 0, 71915, 0, 129742, 7282, 94066, 0, 0, 0, 0, 0, 5286, 83061, 0, - 3718, 0, 83057, 78933, 124906, 71905, 0, 128480, 0, 0, 0, 0, 9206, 82980, - 113824, 6802, 0, 41653, 0, 1241, 0, 0, 0, 0, 68124, 41651, 42937, 0, - 83042, 41650, 0, 83037, 0, 12914, 2814, 0, 119552, 120691, 0, 0, 71968, - 0, 0, 0, 917546, 71862, 0, 0, 0, 3494, 10189, 69784, 0, 0, 71861, 0, 0, - 65875, 0, 0, 127762, 0, 74215, 43065, 0, 0, 7200, 0, 3261, 0, 0, 0, - 65889, 71888, 71975, 0, 0, 0, 0, 0, 77793, 0, 0, 129424, 77791, 635, 0, - 0, 74753, 0, 92420, 73997, 0, 0, 43905, 0, 118834, 126125, 0, 6667, 0, - 983268, 0, 0, 125200, 0, 0, 0, 0, 83137, 0, 0, 0, 0, 0, 121104, 127856, - 125112, 71885, 0, 120125, 7866, 194573, 92770, 194574, 0, 120140, 126074, - 2849, 0, 0, 42157, 12960, 0, 11812, 0, 74509, 0, 69881, 0, 0, 0, 123156, - 7178, 0, 0, 0, 0, 129041, 11534, 1967, 0, 0, 71361, 7015, 120298, 72757, - 0, 12989, 0, 9368, 983638, 1624, 43270, 0, 0, 10818, 0, 83091, 0, 120908, - 0, 0, 0, 0, 0, 0, 6169, 12871, 0, 2798, 65176, 4958, 42752, 119025, 0, 0, - 0, 70346, 66448, 0, 113780, 68364, 0, 0, 0, 68360, 0, 73746, 120945, - 68352, 0, 73787, 83110, 2154, 7199, 64955, 0, 0, 0, 0, 71980, 66507, 0, - 69853, 0, 0, 0, 0, 0, 0, 0, 92517, 118882, 120301, 13297, 0, 129446, - 71963, 0, 0, 0, 6658, 8045, 0, 0, 983873, 92319, 83101, 0, 72126, 0, 0, - 0, 2416, 3310, 0, 0, 379, 0, 43755, 0, 0, 0, 68362, 1284, 0, 73756, 0, 0, - 83141, 70784, 71977, 0, 0, 0, 8515, 83144, 83143, 0, 0, 0, 8529, 93782, - 0, 7564, 0, 0, 0, 0, 73757, 73760, 42359, 0, 2031, 0, 7202, 129984, - 12676, 0, 0, 128418, 0, 7710, 1610, 73801, 0, 0, 118706, 983607, 43917, - 0, 9974, 228, 0, 10398, 0, 0, 0, 92241, 70062, 118927, 42999, 1725, - 65533, 8196, 9352, 0, 0, 66868, 0, 8502, 5762, 0, 0, 43898, 0, 0, 0, 0, - 43914, 0, 126507, 64598, 13001, 9326, 83082, 43916, 1557, 0, 983879, - 6330, 6805, 8631, 2545, 70052, 0, 0, 0, 42998, 70410, 0, 42762, 71941, - 42914, 126516, 262, 1637, 0, 83025, 129491, 83026, 128757, 0, 0, 0, - 128922, 0, 43658, 0, 0, 129183, 6419, 0, 0, 0, 0, 93989, 0, 128173, 7194, - 5291, 67395, 43666, 0, 0, 0, 0, 128293, 0, 12881, 123596, 0, 73842, 0, - 9011, 0, 0, 0, 70436, 179, 43644, 0, 0, 64747, 0, 118813, 0, 0, 121389, - 92649, 126629, 0, 73850, 2801, 119495, 42069, 119839, 119838, 119841, - 42072, 92736, 119842, 0, 0, 0, 8377, 0, 42070, 119313, 119834, 119310, - 4389, 43656, 1633, 119857, 118632, 119859, 11119, 119845, 119844, 9967, - 119846, 119849, 4612, 92867, 119850, 42913, 70456, 0, 71983, 10782, - 66898, 0, 119141, 0, 0, 0, 11541, 69636, 0, 0, 119614, 2731, 0, 0, 0, - 4102, 0, 73878, 0, 0, 0, 0, 0, 11283, 0, 0, 0, 0, 0, 43674, 0, 0, 126705, - 0, 0, 0, 0, 11142, 128304, 0, 12975, 0, 123208, 0, 0, 74072, 0, 55269, 0, - 0, 0, 78577, 78576, 0, 0, 82966, 82974, 70448, 0, 0, 82968, 0, 0, 0, 0, - 0, 113809, 0, 69399, 64909, 0, 11790, 74019, 0, 128066, 0, 8561, 94076, - 129481, 125045, 69259, 65674, 7230, 0, 0, 8778, 0, 0, 67725, 2071, 0, - 6459, 68325, 7628, 65092, 73903, 0, 11342, 129388, 0, 0, 93965, 94081, 0, - 11810, 70057, 10723, 967, 0, 71973, 73905, 0, 6387, 0, 12307, 43913, - 121089, 0, 127584, 0, 1886, 0, 43895, 870, 7648, 0, 7662, 7652, 876, 871, - 877, 7665, 878, 42015, 879, 43692, 4563, 0, 0, 0, 73072, 867, 9520, 872, - 7656, 868, 873, 7642, 7659, 869, 874, 7644, 0, 875, 790, 0, 0, 0, 0, 0, - 124899, 0, 0, 0, 0, 0, 68452, 0, 0, 42067, 0, 0, 0, 12292, 0, 0, 0, - 42012, 0, 0, 83388, 0, 0, 8494, 4611, 0, 72344, 0, 9679, 0, 0, 0, 0, - 93015, 0, 74364, 4628, 4245, 0, 0, 0, 1851, 0, 127189, 0, 0, 0, 118897, - 0, 64674, 124971, 983887, 8829, 983693, 128864, 0, 0, 0, 0, 8809, 983696, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 7427, 0, 4588, 43680, 72300, 74484, 0, 0, 0, - 0, 113787, 74363, 129043, 0, 793, 0, 11197, 0, 0, 0, 842, 0, 8208, 70833, - 0, 1647, 0, 70841, 0, 73508, 818, 0, 0, 0, 0, 0, 0, 120594, 0, 0, 70179, - 0, 13167, 66359, 0, 127172, 0, 4969, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2840, 0, - 0, 0, 66887, 65877, 9068, 0, 68194, 0, 0, 12991, 0, 2651, 68016, 983915, - 0, 983264, 70835, 0, 70844, 43648, 0, 0, 0, 0, 0, 0, 64372, 121064, 7458, - 655, 752, 7457, 7456, 7452, 3285, 74894, 11152, 73099, 0, 2391, 93766, - 92271, 671, 7435, 7434, 618, 668, 610, 42800, 7431, 7451, 42801, 640, - 42927, 7448, 7439, 628, 3905, 100742, 0, 0, 0, 67850, 0, 0, 0, 4605, 0, - 100745, 43372, 65945, 72710, 0, 119590, 0, 0, 70495, 987, 71229, 11572, - 0, 0, 10002, 9971, 70673, 0, 0, 0, 0, 0, 0, 11334, 0, 129493, 42364, - 11503, 0, 0, 0, 4627, 70090, 127784, 73473, 0, 74046, 68872, 92562, 0, 0, - 129900, 0, 129812, 0, 0, 42569, 64965, 0, 0, 10516, 129828, 12190, 0, - 42140, 0, 0, 0, 0, 9887, 0, 4000, 7429, 7428, 665, 7424, 0, 0, 7884, 0, - 0, 0, 0, 0, 2509, 0, 120573, 0, 0, 92449, 0, 10690, 0, 119114, 126226, 0, - 0, 73080, 4590, 0, 74440, 0, 0, 0, 1708, 0, 0, 983609, 0, 0, 69226, - 69974, 8813, 0, 1066, 0, 0, 71965, 127921, 70447, 0, 0, 0, 2202, 0, 7516, - 0, 0, 0, 8034, 0, 0, 3631, 110696, 0, 0, 8416, 110694, 71937, 0, 0, - 110692, 74621, 0, 70185, 0, 74850, 0, 0, 12099, 70475, 0, 6252, 0, 0, 0, - 0, 0, 0, 66368, 0, 64956, 7071, 129070, 70457, 128159, 118800, 0, 77757, - 0, 9357, 0, 1773, 0, 125092, 0, 68451, 7745, 9844, 0, 0, 94, 1880, - 120929, 0, 0, 0, 0, 0, 0, 0, 0, 11237, 0, 129173, 0, 0, 0, 1757, 6964, - 42480, 72823, 0, 120806, 0, 0, 7731, 0, 0, 127883, 0, 77777, 43988, - 70423, 74758, 0, 7592, 856, 74299, 0, 0, 0, 78138, 1459, 0, 0, 0, 0, 0, - 1504, 0, 0, 0, 0, 7529, 0, 0, 0, 0, 12594, 0, 0, 336, 0, 7509, 0, 0, 0, - 0, 127882, 0, 0, 0, 65859, 0, 983986, 43062, 124948, 0, 0, 0, 0, 12970, - 0, 0, 0, 0, 0, 0, 0, 119247, 0, 65068, 74291, 122938, 7069, 0, 0, 66977, - 11130, 2087, 0, 0, 0, 0, 126249, 0, 92747, 0, 92614, 2091, 0, 2090, 0, 0, - 7117, 2077, 72281, 0, 77889, 2083, 0, 71196, 0, 0, 71981, 0, 0, 0, 0, - 4165, 8746, 0, 0, 0, 0, 129572, 7066, 77779, 70415, 128135, 0, 0, 7786, - 127766, 2233, 0, 124965, 121122, 2302, 0, 0, 7056, 0, 0, 0, 0, 118639, 0, - 126506, 6920, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 983099, 70438, 2613, 0, 0, - 110734, 0, 74571, 42760, 0, 0, 0, 0, 0, 0, 71843, 0, 0, 70506, 1246, - 74243, 0, 0, 41008, 0, 0, 0, 921, 70048, 0, 12702, 119500, 0, 1566, 8407, - 0, 64653, 0, 74617, 0, 0, 72711, 5313, 951, 0, 0, 0, 0, 77807, 4009, - 70277, 71844, 0, 83123, 0, 72250, 0, 119898, 113760, 0, 0, 0, 0, 70024, - 0, 0, 119892, 0, 0, 0, 119890, 2579, 119906, 3177, 11357, 69224, 0, 0, - 83130, 64734, 0, 9822, 110670, 70471, 110668, 66990, 110666, 66967, 0, 0, - 0, 9851, 983748, 110673, 9059, 110671, 77736, 0, 41687, 129054, 0, 71842, - 70178, 0, 66975, 1777, 67003, 10158, 69767, 122982, 42366, 70444, 0, 0, - 0, 70127, 71955, 5989, 110716, 74636, 126999, 0, 41685, 0, 0, 9769, - 41684, 0, 6225, 111328, 11740, 0, 118840, 0, 2600, 0, 70416, 0, 118720, - 3666, 70420, 127193, 71976, 0, 0, 74542, 69771, 0, 0, 0, 0, 0, 69765, - 77804, 252, 0, 69769, 0, 194616, 0, 69763, 0, 0, 0, 0, 0, 0, 0, 120947, - 0, 129410, 0, 118792, 0, 68323, 125219, 0, 119188, 0, 2177, 121335, 0, 0, - 0, 0, 0, 7764, 983745, 11094, 120825, 119490, 0, 92505, 8298, 0, 0, 0, 0, - 0, 64449, 0, 126650, 0, 0, 0, 70442, 0, 0, 0, 0, 7774, 10607, 0, 0, 0, 0, - 0, 120764, 0, 0, 77746, 0, 3458, 0, 70053, 0, 120995, 0, 2602, 0, 0, 0, - 74907, 0, 0, 0, 0, 172, 0, 4971, 70419, 1889, 7238, 0, 0, 0, 8257, 0, 0, - 78917, 129570, 0, 111342, 71948, 0, 43366, 43363, 9807, 0, 0, 0, 72247, - 64479, 0, 0, 0, 113707, 0, 10900, 121355, 0, 0, 12048, 0, 64292, 0, 0, 0, - 6099, 94084, 129486, 0, 0, 299, 0, 8525, 92356, 0, 0, 111338, 0, 92564, - 3075, 0, 94053, 0, 94050, 0, 0, 70440, 0, 123590, 0, 0, 0, 2581, 11395, - 0, 0, 0, 0, 128584, 0, 0, 129423, 101092, 118855, 0, 0, 0, 7204, 70065, - 2588, 2914, 7011, 55281, 0, 7466, 0, 2883, 42253, 83118, 0, 0, 0, 83116, - 0, 41230, 68299, 0, 43571, 0, 6219, 0, 9980, 41232, 92245, 0, 66036, - 41229, 118967, 0, 120666, 94016, 0, 12711, 0, 0, 74289, 68472, 42857, - 66950, 0, 0, 0, 127306, 119006, 0, 11380, 72348, 0, 0, 0, 0, 0, 0, 0, - 983579, 12722, 0, 922, 0, 0, 983127, 74958, 3218, 120471, 120470, 120469, - 120476, 120475, 8569, 11404, 70450, 120463, 3214, 120461, 120468, 74910, - 3207, 120465, 78729, 78728, 78727, 0, 120460, 7425, 3205, 0, 78737, - 78736, 71729, 43383, 78733, 78732, 2606, 78730, 73897, 0, 11496, 1173, 0, - 0, 129135, 0, 0, 0, 120737, 120953, 120872, 120629, 378, 2610, 0, 0, 0, - 0, 0, 37, 7068, 0, 120480, 70421, 3209, 120477, 0, 120483, 9768, 120481, - 0, 0, 0, 0, 0, 0, 65510, 0, 100625, 0, 0, 0, 100627, 0, 126633, 0, 7060, - 100628, 0, 127752, 0, 69284, 70428, 71463, 0, 7380, 0, 0, 100593, 126997, - 0, 124900, 0, 71465, 121030, 3243, 0, 0, 0, 7050, 0, 70050, 0, 0, 122983, - 71466, 8203, 71102, 68241, 0, 65211, 194599, 983406, 118636, 0, 779, - 125061, 64367, 100906, 69901, 8193, 55279, 0, 0, 0, 7065, 0, 4346, 0, 0, - 908, 0, 0, 8982, 0, 0, 0, 782, 0, 10883, 0, 0, 129396, 65542, 121302, 0, - 68650, 100575, 92244, 0, 0, 111351, 0, 4376, 0, 11787, 12961, 0, 0, - 42888, 0, 100610, 6231, 0, 65713, 100608, 1783, 0, 68238, 0, 0, 0, - 194945, 0, 0, 0, 68653, 0, 983051, 0, 764, 0, 0, 43531, 0, 9033, 0, 0, - 6223, 11042, 0, 0, 0, 0, 0, 917792, 0, 0, 0, 0, 0, 0, 120648, 0, 0, 0, 0, - 0, 0, 71971, 0, 1478, 78923, 11825, 2607, 0, 0, 0, 74543, 0, 0, 100588, - 6132, 0, 0, 0, 70058, 0, 0, 0, 43537, 6761, 10093, 4369, 0, 0, 73735, - 100564, 3947, 110778, 0, 0, 0, 0, 100942, 0, 0, 0, 0, 0, 0, 7686, 0, 0, - 0, 100934, 0, 100944, 66577, 41221, 0, 42281, 0, 74024, 12293, 0, 94014, - 11794, 0, 120893, 1737, 0, 0, 0, 7205, 0, 9335, 12850, 77810, 2272, 7055, - 0, 0, 0, 67751, 0, 124910, 6780, 65067, 0, 1327, 68393, 983574, 0, 41217, - 0, 10018, 0, 0, 0, 100611, 68176, 41219, 0, 4147, 983171, 41216, 983712, - 2616, 70197, 68461, 65234, 0, 0, 0, 0, 119660, 0, 0, 0, 0, 127930, - 119580, 70675, 64943, 2608, 1470, 0, 0, 6227, 0, 0, 74775, 0, 0, 72320, - 101024, 0, 73822, 67456, 0, 0, 0, 0, 10876, 92482, 0, 0, 5834, 0, 6222, - 0, 0, 12086, 0, 1600, 64309, 0, 0, 68883, 127957, 93836, 0, 8882, 0, - 129415, 2570, 0, 0, 194606, 0, 0, 1234, 0, 13115, 110743, 110740, 100923, - 5002, 110739, 41286, 100926, 127019, 0, 0, 0, 0, 0, 0, 0, 41289, 0, 0, - 75051, 41272, 0, 0, 0, 0, 0, 124978, 0, 41279, 0, 0, 0, 11081, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 9637, 7112, 77975, 128984, 0, 10886, 0, 8548, 983860, - 0, 0, 0, 8076, 43048, 8290, 8291, 43051, 92570, 0, 2596, 0, 0, 41293, 0, - 0, 2393, 7058, 66432, 0, 68673, 0, 0, 0, 0, 0, 128558, 0, 0, 0, 0, 0, - 64696, 0, 0, 121086, 74165, 0, 0, 0, 0, 0, 0, 7063, 983183, 64893, 73096, - 0, 68038, 113757, 709, 0, 0, 1876, 0, 0, 120868, 8137, 110662, 67752, - 70850, 100832, 245, 100831, 11456, 41233, 7070, 0, 94046, 6136, 100835, - 0, 100781, 41235, 73474, 0, 100782, 100642, 432, 0, 100784, 65437, 0, - 100647, 128909, 0, 100641, 100649, 0, 100648, 0, 43215, 0, 0, 0, 0, 9052, - 0, 0, 110826, 110827, 74784, 10580, 0, 100845, 0, 64640, 983176, 74455, - 0, 129670, 70035, 0, 12652, 12199, 127030, 0, 2566, 11971, 0, 0, 1065, 0, - 0, 0, 2576, 0, 66819, 0, 984005, 129852, 0, 0, 983050, 983845, 0, 2921, - 119104, 0, 5772, 12968, 70055, 0, 0, 0, 2580, 983841, 0, 0, 70032, 0, 0, - 0, 128148, 0, 0, 121308, 11346, 0, 12054, 100824, 92426, 101112, 0, - 13091, 0, 0, 100821, 100828, 0, 127026, 128334, 74821, 0, 66295, 68037, - 68047, 127865, 13090, 0, 67492, 0, 118985, 0, 0, 0, 0, 0, 127824, 0, 0, - 100776, 119319, 42356, 42432, 100778, 92823, 0, 0, 0, 78752, 70030, - 66914, 0, 0, 7061, 0, 3854, 0, 70020, 68413, 0, 42319, 0, 0, 7067, 0, 0, - 0, 0, 0, 0, 127797, 9029, 43543, 92820, 2353, 119316, 0, 100769, 0, - 100768, 983178, 0, 0, 43664, 0, 0, 0, 12277, 0, 78122, 11066, 65233, 0, - 41224, 0, 0, 3747, 10522, 0, 77722, 1691, 41226, 0, 77724, 0, 41223, - 121135, 121299, 697, 0, 121051, 4244, 0, 0, 0, 13121, 128573, 0, 0, 0, 0, - 0, 0, 129879, 0, 65816, 68111, 0, 127933, 0, 0, 0, 0, 0, 0, 66895, 74602, - 0, 7123, 70038, 5785, 9198, 0, 100810, 0, 7383, 64656, 0, 0, 0, 0, 0, 0, - 0, 0, 13122, 0, 191, 70060, 8585, 126610, 64411, 0, 0, 64850, 41072, - 118996, 0, 0, 0, 0, 78907, 127010, 100753, 0, 100756, 683, 396, 0, - 100758, 0, 100757, 43058, 100760, 343, 7129, 42680, 0, 0, 0, 0, 0, - 100761, 0, 74040, 0, 1724, 0, 119321, 0, 0, 2203, 0, 0, 0, 6592, 0, - 983044, 0, 0, 0, 0, 3730, 1778, 0, 0, 128854, 121254, 0, 9018, 0, 0, 0, - 0, 92763, 5547, 0, 0, 128950, 0, 0, 284, 8108, 0, 0, 74001, 0, 66460, - 7174, 92703, 126072, 0, 0, 4394, 127480, 0, 0, 0, 101082, 66459, 0, 7180, - 101084, 0, 92812, 68800, 42471, 0, 0, 67232, 64304, 42243, 101094, 2583, - 0, 77728, 0, 0, 0, 71702, 3855, 0, 0, 0, 0, 0, 0, 0, 92416, 7132, 0, - 92743, 0, 64756, 3798, 6578, 0, 0, 92481, 9774, 1275, 0, 119273, 983056, - 0, 120515, 7873, 77719, 129754, 0, 0, 77717, 0, 73994, 73992, 0, 0, 0, - 41851, 0, 41846, 126485, 92337, 7633, 41849, 68385, 70726, 3224, 0, - 69806, 0, 0, 0, 1510, 68129, 0, 0, 0, 0, 12109, 0, 0, 0, 0, 0, 78377, - 1910, 8671, 78374, 127118, 70290, 0, 0, 0, 2654, 7893, 0, 0, 0, 72394, 0, - 67394, 0, 118970, 70066, 78372, 78371, 78370, 78369, 78368, 0, 0, 0, - 1733, 0, 2568, 0, 0, 0, 0, 41486, 0, 127839, 7116, 0, 0, 0, 7185, 0, 0, - 0, 0, 0, 120575, 120829, 0, 0, 0, 0, 92489, 0, 0, 0, 70022, 7171, 0, 340, - 0, 0, 72980, 0, 128535, 0, 124979, 94073, 0, 0, 0, 11392, 92509, 0, 0, 0, - 0, 0, 0, 0, 100632, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11948, 0, 6999, 617, - 983825, 0, 3675, 10600, 0, 0, 74616, 2617, 0, 0, 0, 128446, 0, 0, 8630, - 194771, 7288, 983828, 5545, 983818, 2586, 0, 0, 73123, 983851, 0, 0, 0, - 70847, 0, 0, 0, 0, 11195, 71708, 0, 7835, 70040, 0, 0, 92285, 0, 0, - 72973, 0, 0, 100852, 71118, 10029, 983167, 0, 0, 70033, 11359, 0, 0, - 194782, 0, 0, 118975, 0, 0, 3903, 100893, 983858, 0, 120555, 0, 93036, - 110645, 0, 983565, 0, 0, 194773, 0, 0, 0, 127238, 983822, 100919, 0, - 100918, 64752, 0, 983139, 100920, 118642, 43045, 100904, 0, 0, 0, 66394, - 7128, 0, 0, 0, 0, 0, 43044, 2604, 0, 100851, 43046, 121421, 69985, 11768, - 43043, 10470, 0, 7122, 194789, 4390, 454, 41397, 194792, 0, 78762, 0, 0, - 120576, 64572, 0, 68091, 2394, 2575, 113749, 0, 0, 74802, 100913, 129280, - 0, 0, 11989, 0, 0, 128856, 0, 0, 8249, 128172, 0, 0, 6640, 74806, 2598, - 513, 0, 6586, 127521, 129301, 120710, 65008, 0, 0, 92515, 0, 194795, - 66755, 0, 126585, 0, 43152, 78637, 0, 194797, 0, 69893, 6582, 0, 0, - 12839, 0, 78906, 983221, 0, 2444, 119489, 66620, 0, 0, 0, 0, 69894, 0, 0, - 0, 0, 4238, 11071, 9459, 68437, 78140, 78139, 0, 10079, 128985, 0, 0, 0, - 0, 11907, 43928, 0, 0, 0, 0, 92490, 43929, 0, 43926, 64498, 0, 9506, - 6978, 126234, 0, 0, 0, 0, 43934, 0, 1122, 65564, 0, 71055, 0, 0, 1920, 0, - 43930, 827, 0, 0, 0, 0, 6577, 1304, 64733, 0, 10606, 0, 0, 69503, 9329, - 92997, 9239, 74422, 0, 129373, 1222, 11076, 0, 69229, 43615, 8262, 72280, - 64627, 19909, 983554, 72279, 0, 287, 0, 233, 0, 0, 42816, 0, 0, 65140, - 128158, 8830, 0, 0, 10524, 41175, 125033, 72294, 0, 5296, 0, 127559, 0, - 0, 0, 127154, 74858, 6516, 6515, 6514, 6513, 6512, 0, 70870, 0, 0, 0, - 12122, 92462, 100868, 43976, 1785, 92507, 0, 0, 917771, 5138, 0, 0, 0, - 100884, 0, 0, 0, 123564, 0, 5134, 69980, 322, 4643, 5132, 0, 194942, 0, - 5143, 0, 72309, 119628, 0, 0, 72112, 0, 129964, 0, 0, 0, 0, 0, 0, 73097, - 0, 0, 0, 127923, 0, 0, 0, 0, 0, 3234, 0, 100886, 0, 100889, 118924, 0, 0, - 100875, 68231, 74489, 100872, 120746, 0, 100876, 0, 12714, 0, 64585, - 93775, 0, 0, 0, 129428, 0, 11027, 0, 10059, 0, 64524, 9767, 789, 1749, 0, - 66766, 984010, 320, 0, 0, 0, 3049, 0, 6471, 0, 74479, 9925, 127356, - 127355, 127358, 4960, 5549, 127359, 127346, 127345, 127348, 5418, 127350, - 3351, 120892, 127351, 10610, 5414, 93789, 0, 4286, 5421, 127344, 67867, - 0, 127794, 0, 6653, 122958, 0, 64510, 0, 41868, 0, 128823, 0, 0, 11613, - 70737, 12603, 7131, 11108, 4566, 0, 0, 0, 0, 0, 124938, 127369, 0, 0, - 5200, 0, 129484, 0, 9183, 127361, 74458, 73075, 395, 5482, 1376, 4349, 0, - 0, 5196, 0, 6113, 42009, 5205, 0, 120530, 0, 118973, 70467, 0, 0, 129691, - 0, 9126, 70498, 0, 0, 0, 0, 0, 3203, 192, 0, 3385, 120785, 128620, 5383, - 0, 0, 0, 5738, 69449, 3336, 0, 5361, 9633, 0, 0, 0, 0, 8581, 0, 1260, - 3149, 5359, 12962, 74955, 10441, 5357, 0, 0, 0, 5364, 0, 11431, 0, 9101, - 0, 0, 0, 0, 78378, 121155, 42917, 0, 129179, 0, 0, 0, 43360, 78385, - 78384, 78383, 78382, 78381, 78380, 78379, 9319, 7097, 0, 127748, 0, 0, 0, - 120632, 0, 71205, 0, 0, 0, 1720, 0, 0, 0, 8622, 0, 70430, 68772, 0, 0, 0, - 73084, 0, 0, 11921, 0, 11769, 68782, 0, 0, 0, 0, 194571, 41586, 0, 0, 0, - 3356, 194572, 64709, 194575, 0, 7134, 0, 78389, 0, 677, 0, 0, 0, 129474, - 68747, 0, 68751, 3349, 74125, 0, 8927, 0, 0, 0, 0, 0, 0, 0, 6806, 0, - 8384, 68755, 0, 0, 0, 0, 0, 124924, 0, 7113, 7586, 0, 10852, 0, 0, 4606, - 0, 0, 70084, 0, 0, 1046, 7124, 121192, 68753, 0, 5171, 65539, 0, 0, 0, - 42394, 0, 74849, 127823, 0, 5169, 11935, 0, 0, 3175, 0, 1537, 0, 5176, - 8905, 4136, 4871, 78388, 0, 0, 122661, 0, 1128, 0, 0, 0, 74066, 0, 73069, - 0, 0, 3662, 113767, 3378, 0, 71298, 0, 127995, 6320, 71302, 983163, - 10163, 0, 5165, 5126, 0, 66902, 41389, 0, 71368, 3374, 113740, 0, 7119, - 0, 0, 3507, 0, 7629, 6848, 19925, 0, 68463, 183, 127208, 127209, 70811, - 10636, 0, 128465, 2250, 0, 78772, 0, 0, 0, 78768, 6580, 4332, 123584, 0, - 10726, 66686, 127203, 127204, 127205, 127206, 0, 70813, 127201, 127202, - 0, 0, 5448, 41058, 5446, 0, 0, 71369, 5442, 7135, 0, 0, 5451, 0, 78470, - 0, 0, 0, 0, 11243, 10859, 65867, 10345, 10409, 123606, 0, 0, 129077, - 42181, 0, 0, 2060, 0, 7111, 0, 0, 0, 0, 72741, 0, 205, 93784, 72346, - 93771, 0, 9862, 6588, 43257, 0, 0, 0, 5505, 93760, 5503, 65376, 0, 7125, - 9819, 0, 0, 0, 5507, 12044, 194567, 0, 0, 0, 7109, 0, 0, 7911, 10329, - 10393, 8991, 125104, 69778, 11133, 129619, 8550, 0, 5592, 2919, 0, 0, - 5595, 0, 0, 4367, 0, 0, 5591, 41060, 5594, 0, 0, 13142, 5590, 0, 72274, - 118909, 75069, 123586, 9731, 71225, 64633, 0, 0, 71217, 121361, 71227, 0, - 0, 0, 0, 7137, 0, 0, 0, 10551, 10710, 0, 0, 0, 120570, 0, 92364, 9936, - 3348, 0, 0, 1444, 119058, 0, 74206, 983107, 0, 1442, 129080, 0, 120959, - 0, 0, 0, 0, 0, 0, 0, 3334, 73068, 118803, 0, 0, 71219, 69770, 1651, 0, - 8861, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43626, 0, 0, 3344, 0, 0, 12920, 0, - 0, 0, 71853, 3438, 128711, 0, 0, 0, 0, 129068, 0, 0, 65117, 0, 0, 0, 0, - 66366, 128915, 0, 69772, 0, 0, 0, 0, 4973, 8784, 0, 0, 0, 0, 0, 0, 0, - 125198, 983288, 0, 0, 66413, 0, 0, 0, 0, 122663, 9243, 2464, 0, 0, 3372, - 0, 0, 0, 70364, 7121, 0, 0, 0, 92163, 0, 0, 0, 0, 0, 0, 0, 3354, 0, 0, - 983104, 101233, 0, 3876, 0, 127983, 6858, 43696, 43380, 0, 74240, 0, 0, - 0, 983985, 75074, 6589, 0, 0, 120993, 0, 0, 69609, 0, 66962, 0, 10630, - 71960, 0, 121293, 0, 0, 121287, 917942, 121337, 121215, 0, 0, 0, 0, 0, - 917940, 3366, 0, 917938, 0, 0, 0, 71062, 0, 121197, 0, 6925, 71856, 0, - 917929, 66780, 66274, 0, 72768, 0, 917930, 129482, 11138, 0, 6754, 7118, - 0, 64672, 65296, 0, 118957, 0, 0, 12296, 68457, 121320, 0, 5282, 0, - 72278, 0, 0, 0, 0, 0, 0, 66355, 0, 0, 68073, 64343, 0, 92744, 195058, - 195029, 0, 0, 195056, 195027, 0, 0, 128814, 195025, 6584, 195026, 10657, - 0, 74544, 0, 1200, 12243, 92269, 195062, 0, 129300, 11545, 0, 120493, - 3343, 4424, 11047, 0, 69863, 3896, 0, 0, 2947, 0, 0, 42221, 0, 68139, - 13059, 7942, 0, 3381, 0, 0, 0, 0, 0, 0, 78235, 0, 0, 0, 7044, 65800, - 78236, 0, 7045, 7175, 7047, 127884, 11791, 0, 0, 3881, 0, 0, 127395, 0, - 0, 67075, 7106, 72000, 0, 0, 74211, 41897, 92513, 0, 73040, 66745, 0, 0, - 0, 0, 121245, 0, 64354, 73083, 8777, 0, 129108, 8884, 2385, 73067, 92450, - 0, 0, 0, 42027, 12114, 0, 0, 64936, 0, 0, 0, 0, 0, 126605, 0, 0, 0, 0, - 73064, 0, 0, 0, 0, 0, 0, 0, 73057, 0, 123587, 0, 0, 0, 0, 0, 70803, 0, 0, - 124953, 0, 0, 0, 7048, 11087, 123600, 92536, 7043, 9600, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 42050, 0, 55289, 0, 0, 657, 0, 195054, 4461, 92903, 0, 92904, - 126490, 0, 4468, 0, 0, 0, 4456, 73070, 10720, 123588, 0, 123544, 0, 0, 0, - 195046, 260, 7714, 74163, 2045, 0, 65064, 4466, 0, 0, 128087, 129768, - 41403, 0, 0, 0, 41406, 120692, 0, 0, 73939, 0, 0, 0, 41404, 1165, 0, - 4451, 13087, 0, 11258, 0, 73855, 0, 43014, 5439, 12061, 74586, 3375, - 128869, 0, 0, 0, 0, 0, 0, 0, 113823, 67078, 0, 67079, 0, 0, 0, 0, 68459, - 0, 0, 0, 0, 0, 0, 7280, 0, 0, 0, 4868, 8297, 0, 0, 42791, 0, 66737, - 66739, 0, 0, 5182, 0, 0, 72764, 0, 4465, 0, 12135, 0, 4464, 0, 0, 977, - 4458, 43827, 0, 0, 120888, 0, 344, 67463, 0, 0, 0, 0, 92240, 0, 64443, - 126995, 73078, 129525, 0, 0, 0, 43026, 7612, 119591, 64413, 0, 0, 0, 0, - 0, 0, 0, 0, 123622, 0, 119160, 10204, 127947, 73063, 0, 0, 127236, 0, - 68746, 0, 8852, 0, 0, 0, 0, 128427, 123597, 7932, 92858, 128463, 0, 0, - 72453, 0, 0, 0, 0, 74893, 9567, 0, 73095, 0, 8650, 0, 0, 0, 69900, - 118872, 0, 70868, 0, 6719, 0, 0, 0, 72836, 0, 0, 118991, 0, 123594, - 73815, 4420, 0, 10583, 7760, 0, 0, 128752, 71711, 0, 128407, 0, 0, 77809, - 9066, 0, 74795, 0, 0, 0, 0, 0, 0, 0, 42825, 41854, 5304, 0, 124942, 6919, - 8619, 0, 10038, 66454, 9592, 129049, 0, 0, 110771, 110777, 110772, 0, 0, - 0, 0, 0, 78498, 110773, 43624, 0, 7779, 0, 0, 9479, 78493, 0, 66956, - 2224, 0, 0, 0, 0, 0, 42378, 3368, 0, 66804, 7697, 69237, 0, 2030, 0, - 68236, 8370, 0, 66953, 0, 0, 983355, 127903, 983353, 983352, 5174, 42831, - 983349, 70439, 983347, 8881, 119047, 0, 70433, 0, 0, 0, 0, 0, 0, 9576, 0, - 3347, 4160, 5154, 0, 3794, 0, 0, 0, 0, 0, 127916, 73073, 8381, 4572, - 69564, 126101, 0, 0, 0, 0, 0, 0, 0, 92283, 0, 0, 5799, 983344, 70100, - 983342, 983341, 983340, 43031, 64425, 65128, 983336, 0, 73059, 0, 68616, - 0, 0, 0, 0, 119826, 0, 0, 123604, 0, 0, 283, 68665, 0, 532, 0, 0, 983827, - 0, 0, 3370, 73077, 119132, 5443, 71431, 0, 118630, 0, 0, 0, 2298, 0, 0, - 0, 983335, 983334, 983333, 983332, 7144, 983330, 119600, 983328, 983327, - 983326, 0, 78816, 128833, 0, 0, 0, 0, 0, 0, 0, 0, 73088, 0, 123592, - 983952, 0, 0, 0, 0, 5186, 7360, 127837, 0, 12108, 0, 65124, 0, 0, 0, - 6326, 43344, 0, 0, 42562, 0, 0, 0, 983325, 65495, 983323, 101066, 983321, - 101065, 983319, 65490, 983317, 125034, 0, 101070, 127178, 55245, 128927, - 1630, 128232, 65483, 0, 0, 0, 65476, 0, 0, 119214, 9283, 10183, 0, 0, - 65499, 0, 64593, 66758, 3376, 0, 0, 0, 101077, 43872, 12940, 0, 0, 78587, - 101078, 5957, 0, 8926, 983315, 983314, 983313, 10745, 10174, 983310, - 113793, 983308, 983307, 983306, 0, 123593, 5056, 0, 0, 0, 120773, 0, - 9812, 0, 4460, 127792, 73066, 0, 128038, 0, 123608, 0, 64278, 0, 0, 0, - 66760, 0, 0, 70122, 0, 0, 917627, 0, 73823, 101071, 127922, 2276, 0, - 42579, 0, 983305, 983304, 127831, 983302, 983301, 983300, 983299, 983298, - 74207, 121255, 10482, 12863, 73002, 2412, 0, 9522, 0, 983906, 120674, - 101059, 3384, 101058, 10702, 830, 0, 128166, 0, 8451, 0, 0, 121380, - 69739, 128957, 0, 0, 0, 0, 0, 0, 0, 4243, 92454, 73093, 0, 129705, 4441, - 0, 983295, 983294, 66618, 983292, 125141, 411, 983289, 68068, 983287, - 4056, 983913, 0, 92666, 0, 983916, 983968, 0, 0, 3364, 42265, 64437, - 129635, 118816, 0, 9684, 216, 0, 1401, 0, 0, 0, 122643, 0, 0, 0, 11126, - 5768, 3191, 0, 0, 0, 0, 0, 0, 65895, 0, 0, 3338, 73935, 983283, 983282, - 983281, 129605, 983279, 983278, 2794, 8807, 0, 0, 110720, 0, 8312, 0, - 110718, 11953, 11662, 0, 0, 0, 0, 9534, 66767, 129040, 0, 11113, 0, 0, - 73082, 0, 981, 0, 4330, 119244, 120536, 1824, 0, 0, 7034, 41683, 123166, - 0, 73754, 0, 0, 74478, 128259, 983273, 983260, 983259, 43831, 983257, - 66752, 983255, 983254, 0, 70288, 65343, 0, 0, 43225, 0, 0, 0, 0, 126129, - 0, 128608, 0, 0, 0, 120726, 0, 983852, 11746, 0, 5216, 0, 0, 0, 0, 3468, - 127149, 9230, 65942, 0, 0, 5803, 120677, 0, 0, 13124, 0, 0, 0, 42843, 0, - 0, 0, 66753, 11739, 128318, 0, 128444, 0, 0, 0, 12448, 0, 121441, 13057, - 73852, 124994, 0, 0, 0, 0, 0, 0, 126612, 0, 68903, 0, 129470, 0, 917992, - 0, 0, 0, 0, 0, 0, 0, 92457, 0, 0, 0, 0, 0, 0, 0, 0, 125078, 0, 0, 0, - 10970, 92208, 0, 0, 0, 19944, 0, 9009, 8551, 0, 0, 0, 7575, 67484, 0, - 128899, 0, 129609, 78847, 0, 78846, 73502, 0, 69256, 0, 0, 0, 0, 9775, - 100682, 129191, 119052, 68629, 194703, 0, 0, 78850, 92880, 0, 0, 0, 0, 0, - 0, 0, 71273, 6184, 41540, 3303, 66182, 11786, 66180, 66203, 3422, 0, - 68290, 43007, 4478, 66178, 0, 0, 126216, 0, 4477, 0, 69608, 66184, 66183, - 66204, 66194, 0, 66198, 41880, 66188, 66197, 78148, 66195, 66190, 66191, - 41111, 66189, 73788, 7788, 0, 0, 0, 0, 0, 2221, 78163, 6535, 78161, - 78162, 430, 78160, 78156, 78158, 0, 0, 4945, 0, 4950, 0, 78165, 0, 67118, - 0, 5964, 12908, 0, 0, 0, 74477, 83390, 0, 4949, 0, 443, 0, 4944, 5467, - 119603, 983265, 0, 9364, 0, 119148, 4946, 0, 3788, 126106, 983718, 0, - 120847, 129858, 74441, 0, 0, 12072, 92248, 0, 983708, 0, 128676, 12091, - 0, 0, 0, 4673, 0, 4678, 0, 0, 65059, 43860, 0, 0, 0, 128151, 1199, 0, - 8356, 0, 0, 4677, 0, 0, 0, 2192, 78173, 78175, 78171, 78172, 72255, - 78170, 78166, 4674, 128450, 194944, 0, 124970, 0, 119579, 0, 129919, - 1855, 0, 0, 127806, 0, 0, 68912, 72323, 0, 12988, 121000, 0, 0, 0, 4654, - 6840, 983432, 0, 73993, 0, 4649, 65209, 983908, 93839, 4648, 122635, - 121169, 983436, 126231, 983427, 66846, 7828, 4650, 983426, 72879, 0, - 4653, 7822, 0, 0, 43187, 0, 983586, 6821, 0, 0, 0, 0, 0, 0, 66756, - 983433, 0, 0, 0, 8547, 0, 42165, 0, 119228, 6836, 0, 0, 4662, 0, 0, 0, - 9146, 599, 4657, 0, 120754, 0, 4656, 0, 0, 7811, 40994, 0, 6414, 5967, - 4658, 3725, 0, 5814, 4661, 127760, 194961, 0, 0, 64904, 0, 10833, 0, 0, - 4867, 128717, 0, 11459, 3054, 0, 40996, 0, 7605, 4622, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 19926, 0, 0, 65307, 4617, 0, 0, 0, 4616, 10518, 0, 127160, 0, - 5958, 0, 983449, 4618, 0, 983442, 120675, 4621, 0, 983444, 522, 125213, - 11139, 65803, 194972, 0, 12201, 6135, 121060, 983425, 0, 983093, 0, - 983423, 983416, 983437, 4638, 983421, 0, 78242, 5965, 78240, 66569, - 68646, 0, 983455, 74392, 5335, 0, 0, 4633, 0, 119045, 983451, 4632, 0, - 5542, 5333, 0, 983428, 68648, 5331, 4634, 0, 92870, 5338, 4637, 0, 0, - 43477, 0, 42493, 0, 42361, 0, 0, 73853, 0, 0, 0, 74204, 11343, 0, 10358, - 10422, 4758, 0, 1608, 5252, 0, 0, 4753, 78239, 11344, 78237, 0, 5231, - 74384, 0, 0, 118676, 0, 0, 0, 0, 71991, 5229, 4757, 0, 0, 5227, 4752, 0, - 65235, 5234, 73044, 0, 0, 0, 0, 0, 0, 7460, 0, 917936, 0, 0, 74760, - 65189, 0, 92230, 0, 0, 5574, 128980, 0, 65139, 5577, 0, 0, 118871, 68641, - 8965, 7635, 0, 5316, 70021, 5314, 74555, 5572, 0, 5312, 0, 5525, 5330, - 5319, 68292, 0, 65066, 0, 0, 983496, 0, 0, 127851, 0, 74851, 0, 0, 64609, - 0, 0, 128593, 0, 129339, 0, 8632, 0, 0, 0, 195012, 5735, 195013, 1692, - 70151, 4610, 122653, 4305, 0, 4609, 43478, 4614, 77753, 118534, 5287, - 5309, 5285, 0, 5961, 4647, 5283, 10743, 0, 71889, 601, 4613, 77759, 0, - 9208, 4608, 74044, 71107, 5190, 0, 0, 92410, 43965, 2265, 0, 0, 0, 0, 0, - 0, 0, 129953, 0, 0, 5960, 0, 8992, 65293, 0, 1782, 0, 0, 0, 0, 0, 5501, - 0, 42508, 69759, 120749, 129120, 0, 195023, 77740, 43900, 77741, 0, - 68134, 111180, 74209, 0, 64740, 0, 0, 0, 983935, 3767, 5737, 0, 4865, 0, - 5740, 0, 5736, 7724, 0, 7193, 0, 0, 5739, 77744, 4866, 0, 0, 0, 4869, - 67093, 0, 0, 128514, 6650, 983488, 0, 983479, 78376, 4870, 0, 68661, - 6716, 983478, 2190, 69786, 68676, 0, 10122, 4864, 66568, 0, 0, 0, 9603, - 68652, 126213, 42734, 745, 0, 124131, 124130, 4777, 0, 77788, 68631, - 42775, 68196, 0, 124128, 124129, 0, 5966, 0, 4778, 127890, 0, 0, 4781, - 127196, 64407, 0, 74132, 8577, 71221, 0, 71223, 0, 4782, 0, 0, 120757, - 68618, 43472, 43056, 68622, 0, 92986, 4776, 0, 11492, 0, 0, 13176, 0, 0, - 0, 73558, 0, 0, 0, 4849, 8242, 9561, 73922, 0, 0, 0, 0, 5963, 0, 125201, - 0, 4850, 72121, 0, 590, 4853, 0, 4854, 0, 5164, 0, 1605, 5124, 0, 111165, - 0, 8471, 0, 111164, 12445, 3785, 0, 111162, 0, 0, 4848, 2530, 0, 2068, - 1964, 0, 0, 10796, 0, 0, 0, 0, 0, 4794, 0, 0, 0, 4797, 68040, 111152, - 43465, 4792, 0, 0, 0, 0, 0, 110842, 983102, 92963, 0, 0, 0, 4221, 92360, - 118869, 0, 0, 0, 70042, 0, 0, 0, 0, 10739, 65090, 0, 119327, 126541, 0, - 0, 119326, 0, 0, 4937, 43376, 0, 0, 10597, 983445, 11722, 9248, 129566, - 42879, 11725, 0, 0, 7579, 11141, 73958, 4941, 0, 917538, 9140, 4936, - 5261, 0, 0, 72298, 0, 4942, 0, 4938, 0, 0, 5259, 9369, 983434, 111182, - 5257, 78932, 6844, 4964, 5264, 0, 0, 0, 41411, 0, 121473, 73684, 128233, - 9482, 4873, 41991, 64707, 42526, 127989, 64480, 64725, 983447, 0, 0, 0, - 0, 0, 0, 73043, 0, 389, 10893, 7521, 0, 4872, 5463, 0, 3125, 111124, 0, - 4878, 5459, 4604, 0, 0, 5465, 0, 0, 0, 0, 9563, 0, 0, 128419, 125273, - 82963, 0, 0, 0, 67735, 0, 0, 0, 0, 0, 73560, 0, 129707, 0, 917833, 0, - 917836, 0, 0, 3082, 0, 0, 0, 0, 118621, 7079, 5856, 917842, 5163, 0, 0, - 1817, 66724, 0, 0, 10564, 7763, 13077, 124115, 0, 68140, 111137, 0, - 77782, 0, 111139, 123548, 77787, 121457, 0, 0, 0, 983190, 73081, 0, 0, - 983118, 124114, 0, 42156, 0, 0, 0, 983080, 0, 0, 0, 119254, 120693, 0, - 69386, 0, 118881, 0, 78189, 0, 78186, 78188, 129654, 0, 0, 0, 110877, 0, - 3108, 9745, 0, 0, 0, 118825, 92785, 0, 122954, 0, 0, 10972, 92786, 0, - 42768, 715, 983114, 121117, 9453, 5348, 10943, 0, 983170, 92784, 0, 0, - 983154, 0, 0, 11551, 128464, 0, 0, 9051, 0, 71728, 0, 120791, 119523, 0, - 6404, 66458, 68376, 11984, 9156, 65222, 74454, 78180, 0, 3128, 4789, - 5067, 5066, 0, 4784, 0, 8827, 1146, 5065, 78196, 78192, 78193, 78190, - 78191, 5064, 5326, 0, 9450, 5063, 120361, 78200, 78201, 5062, 69733, - 74146, 0, 0, 0, 0, 77992, 0, 3933, 77768, 0, 12337, 0, 125023, 0, 0, 0, - 194759, 0, 0, 82993, 42130, 0, 5151, 917832, 120357, 0, 73523, 0, 7620, - 3800, 0, 0, 0, 127952, 0, 0, 4786, 127991, 4185, 0, 128742, 0, 983194, - 73978, 0, 4593, 77715, 77727, 124909, 0, 110715, 10532, 77732, 110714, - 110711, 110712, 64759, 1325, 5166, 9888, 0, 5148, 0, 0, 78205, 78206, - 64140, 78204, 64131, 3119, 917814, 0, 983438, 917820, 12095, 0, 0, 636, - 128002, 0, 983469, 0, 78531, 7836, 42741, 64137, 0, 118969, 0, 92431, 0, - 0, 0, 0, 0, 8618, 0, 11865, 0, 0, 0, 3937, 12312, 128261, 0, 0, 0, 912, - 6349, 4536, 71964, 0, 126594, 0, 0, 0, 3935, 120665, 0, 0, 0, 0, 118859, - 0, 121116, 0, 0, 12046, 12599, 0, 0, 0, 0, 7227, 0, 0, 0, 983066, 0, 0, - 0, 113817, 2179, 78246, 0, 0, 0, 0, 0, 127405, 101531, 0, 101530, 43907, - 0, 0, 0, 0, 4644, 8818, 0, 0, 0, 0, 93066, 66452, 126081, 1644, 101043, - 9658, 43744, 11385, 65947, 983174, 43983, 0, 0, 0, 8962, 0, 0, 2466, - 42039, 67669, 0, 0, 42117, 100698, 0, 0, 0, 0, 43745, 5318, 0, 77723, 0, - 0, 0, 7054, 64147, 0, 917804, 68195, 6698, 0, 0, 0, 70849, 11981, 12202, - 0, 121364, 0, 7059, 11608, 975, 0, 65843, 170, 0, 67239, 42708, 0, 0, - 6058, 0, 0, 0, 70507, 0, 0, 9818, 0, 0, 42106, 0, 983065, 4738, 42105, - 7062, 0, 4737, 11779, 4742, 120564, 92391, 0, 41374, 41375, 983381, 6715, - 12700, 7049, 983379, 0, 0, 0, 4741, 42108, 983370, 64159, 4736, 64148, 0, - 849, 0, 128247, 983366, 0, 120913, 917997, 0, 983384, 9496, 66371, - 983408, 983382, 11322, 0, 93008, 3928, 983153, 0, 10706, 7198, 0, 4842, - 12053, 0, 0, 4841, 0, 4171, 12008, 68416, 3923, 1490, 0, 0, 983398, - 40972, 5245, 72288, 983400, 126578, 0, 4845, 8332, 40974, 0, 4840, 9077, - 2252, 2408, 72851, 4825, 0, 917574, 0, 0, 126251, 0, 0, 983358, 0, - 983359, 0, 4826, 42440, 0, 0, 1274, 0, 74315, 0, 120384, 118614, 121200, - 0, 0, 0, 4830, 983393, 129044, 0, 0, 119082, 0, 64105, 0, 0, 4824, - 120397, 0, 0, 1888, 64127, 7861, 125111, 78524, 41836, 110613, 10873, - 72439, 0, 64098, 12214, 124134, 41834, 0, 358, 128120, 41833, 11442, 0, - 0, 0, 0, 64115, 0, 0, 0, 120721, 119053, 0, 119055, 119054, 0, 0, 0, 0, - 4017, 12827, 5241, 0, 73042, 41118, 3924, 0, 11366, 0, 0, 0, 0, 41116, - 69455, 0, 0, 0, 0, 11917, 0, 74000, 4721, 123551, 983937, 0, 0, 0, 0, 0, - 0, 122907, 0, 128702, 4722, 6816, 124974, 0, 4725, 67099, 4726, 0, - 129856, 123171, 0, 123194, 0, 0, 0, 4015, 0, 8052, 78766, 123538, 0, - 128294, 0, 0, 4720, 73090, 125003, 0, 0, 1656, 41831, 0, 0, 41843, 92846, - 0, 1452, 13111, 0, 0, 0, 8552, 64113, 41845, 64073, 120354, 0, 0, 120066, - 120067, 7064, 64070, 9948, 0, 0, 0, 92828, 2420, 92811, 0, 0, 0, 120052, - 120053, 120050, 74920, 3938, 120057, 120054, 92829, 120060, 71920, - 120058, 120059, 120064, 72203, 7955, 64074, 4713, 128196, 983108, 0, 0, - 0, 65152, 10198, 120044, 120045, 120042, 6713, 4532, 120049, 120046, - 120047, 4717, 7046, 0, 66450, 4712, 75055, 0, 121085, 0, 8155, 4718, - 3942, 4714, 9625, 0, 6383, 0, 12006, 0, 0, 0, 0, 0, 65414, 0, 0, 129061, - 66437, 66025, 74115, 0, 0, 11228, 4809, 0, 68211, 72352, 0, 0, 983101, - 65405, 129912, 0, 0, 2163, 4545, 0, 917566, 0, 4813, 78699, 0, 0, 4808, - 0, 0, 65475, 0, 0, 4814, 72240, 4810, 0, 0, 68784, 10761, 67514, 3522, 0, - 78693, 65404, 0, 0, 0, 0, 0, 6691, 70125, 0, 126223, 0, 0, 0, 43858, - 129914, 0, 12992, 65407, 0, 0, 3919, 72379, 0, 92845, 0, 0, 0, 12235, - 110748, 0, 0, 64091, 68739, 64080, 0, 64090, 0, 0, 0, 0, 0, 8454, 0, 0, - 983877, 0, 0, 120398, 4780, 0, 0, 92764, 64621, 6732, 0, 0, 0, 0, 121363, - 0, 0, 120817, 6976, 0, 119005, 0, 93809, 0, 93808, 0, 12526, 120399, - 2315, 0, 1938, 0, 0, 0, 0, 0, 0, 0, 111135, 93794, 0, 0, 0, 93810, 0, - 2291, 0, 0, 0, 0, 129429, 0, 10799, 0, 0, 66372, 0, 4193, 0, 0, 983057, - 7998, 0, 0, 0, 0, 2316, 0, 0, 0, 0, 120106, 0, 0, 74140, 0, 0, 0, 0, - 3762, 93813, 120672, 93820, 0, 0, 0, 70098, 3780, 12808, 8163, 983155, 0, - 0, 3906, 12349, 0, 8326, 0, 65498, 3763, 0, 5618, 0, 3779, 0, 43613, 0, - 128007, 0, 0, 0, 0, 280, 0, 126252, 983453, 13072, 1894, 0, 0, 65478, - 43310, 7231, 0, 11773, 0, 0, 0, 101517, 122662, 0, 7559, 11652, 10009, - 110765, 110766, 110763, 110764, 4470, 110762, 0, 0, 983446, 0, 5249, 0, - 0, 8756, 0, 0, 41694, 120585, 92349, 0, 0, 0, 69685, 123549, 983450, - 113794, 0, 6808, 41319, 13125, 66332, 127977, 0, 2290, 0, 983418, 0, 0, - 3943, 0, 41205, 0, 0, 0, 0, 5352, 0, 0, 41207, 0, 7384, 69647, 41204, - 123552, 41209, 69637, 0, 43607, 0, 0, 5420, 0, 10134, 0, 0, 4018, 7150, - 0, 0, 0, 0, 0, 129606, 2561, 65023, 0, 7148, 12076, 0, 0, 129201, 0, - 6276, 1706, 0, 0, 7146, 0, 128277, 41819, 74991, 0, 10847, 41822, 72248, - 860, 0, 0, 0, 69641, 10753, 41820, 126118, 0, 71898, 0, 92617, 128567, 0, - 121514, 43016, 0, 0, 92225, 0, 0, 0, 0, 4022, 0, 0, 110807, 0, 41691, 0, - 75060, 11866, 0, 65292, 0, 110812, 0, 3911, 110811, 110808, 110809, 0, - 125191, 7000, 3904, 118997, 72261, 0, 0, 0, 13123, 10846, 0, 0, 0, 0, 0, - 74082, 0, 123542, 0, 0, 3777, 128329, 0, 9636, 71726, 0, 0, 9367, 593, 0, - 3999, 0, 41713, 0, 0, 67677, 0, 0, 0, 9763, 120280, 120283, 12347, 124, - 12981, 41127, 92527, 0, 0, 0, 0, 0, 43987, 0, 0, 1769, 41715, 2463, 2151, - 0, 0, 71222, 1538, 93044, 0, 0, 123543, 7795, 120300, 0, 92493, 10955, 0, - 0, 72375, 78208, 9498, 78207, 127033, 78210, 120288, 3939, 120290, - 120285, 8943, 120287, 120286, 120297, 4491, 120299, 42602, 120293, - 120292, 120295, 120294, 0, 0, 0, 0, 0, 0, 1511, 9324, 0, 0, 0, 0, 0, - 64536, 0, 0, 0, 124935, 6822, 12862, 0, 0, 42143, 41828, 0, 917629, - 70864, 118879, 0, 0, 0, 41826, 128413, 0, 0, 13279, 7917, 0, 0, 0, 0, 0, - 92800, 92332, 0, 0, 43515, 0, 0, 0, 4013, 0, 66980, 0, 72224, 125266, 0, - 68243, 2432, 92834, 0, 0, 0, 0, 69952, 0, 0, 0, 10949, 0, 0, 0, 0, 0, 0, - 0, 128574, 43233, 0, 42517, 0, 0, 0, 0, 0, 64468, 119359, 6474, 119358, - 43497, 12656, 128122, 119353, 0, 1665, 0, 0, 0, 64512, 0, 0, 5256, 0, 0, - 0, 2859, 123563, 0, 0, 0, 0, 92801, 128220, 0, 770, 0, 811, 0, 0, 917551, - 42244, 64427, 0, 72222, 0, 3895, 0, 74341, 12087, 0, 42859, 10193, 3116, - 7747, 0, 0, 43496, 0, 0, 0, 0, 41877, 0, 65382, 64614, 0, 64296, 0, 6345, - 0, 2663, 0, 121234, 0, 0, 10150, 0, 64308, 1522, 597, 0, 0, 41201, 64731, - 0, 0, 41198, 123537, 71483, 3092, 0, 0, 4783, 71448, 92213, 0, 0, 10812, - 0, 0, 0, 3078, 0, 0, 0, 0, 0, 71703, 394, 3088, 0, 0, 0, 3991, 0, 129072, - 0, 424, 67652, 72377, 0, 0, 0, 0, 0, 0, 42231, 2209, 128215, 72983, 0, - 41840, 129136, 5344, 1298, 0, 13155, 0, 128973, 41838, 0, 8488, 1003, - 41837, 0, 0, 0, 48, 0, 0, 8493, 0, 0, 0, 65487, 118550, 8465, 10332, - 13172, 0, 0, 10449, 126989, 127014, 69606, 69447, 3984, 129159, 0, 0, 0, - 0, 0, 0, 0, 0, 64758, 0, 100947, 0, 0, 9096, 0, 0, 9172, 128545, 0, 0, - 5955, 67666, 0, 0, 0, 0, 0, 74426, 3926, 71734, 0, 8798, 100946, 92165, - 0, 0, 120696, 0, 0, 0, 118805, 10353, 10417, 0, 123560, 0, 128629, 4019, - 0, 0, 0, 8219, 68402, 0, 0, 121301, 128218, 0, 0, 0, 0, 0, 0, 0, 110625, - 42474, 10642, 3909, 9950, 0, 128139, 69619, 68678, 92917, 0, 1049, 43517, - 65707, 11943, 41806, 0, 68635, 3921, 0, 11775, 121352, 69820, 1038, - 42303, 9823, 0, 2145, 4008, 68624, 0, 121025, 0, 0, 5153, 41805, 0, 0, - 763, 9211, 0, 0, 0, 0, 2188, 127142, 0, 0, 65179, 0, 8621, 0, 118878, 0, - 0, 0, 0, 182, 0, 0, 0, 0, 72978, 9058, 8489, 0, 66935, 5969, 65909, - 10848, 4570, 0, 128614, 4255, 0, 0, 41189, 4003, 69785, 68109, 13293, - 41192, 0, 0, 42251, 0, 0, 126085, 11287, 6128, 121315, 11034, 0, 68207, - 0, 65506, 42382, 0, 0, 66872, 9932, 43516, 0, 125098, 0, 41814, 0, 71234, - 64835, 12117, 127040, 127041, 10540, 127043, 9063, 78000, 0, 0, 0, 12897, - 0, 0, 0, 6065, 0, 0, 0, 8692, 41186, 41816, 0, 41818, 41187, 0, 42196, 0, - 110690, 110691, 126115, 0, 0, 125235, 4710, 0, 5956, 7621, 110641, 92624, - 4705, 716, 74918, 110693, 4704, 124916, 0, 127112, 161, 67468, 0, 0, - 4706, 0, 0, 0, 4709, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1700, 119223, 0, 0, - 128119, 4004, 0, 73071, 69383, 69914, 8506, 128237, 0, 126996, 2538, 937, - 0, 4734, 0, 0, 0, 0, 0, 4729, 0, 0, 0, 4728, 0, 72809, 120644, 0, 8109, - 43105, 11249, 4730, 447, 0, 1513, 4733, 0, 0, 0, 0, 0, 0, 0, 8565, 2469, - 0, 6690, 0, 0, 43439, 78218, 43103, 78217, 2674, 0, 11922, 0, 0, 3510, 0, - 129368, 0, 5605, 42095, 126572, 0, 9098, 120512, 0, 121272, 68891, 74570, - 0, 67708, 0, 119346, 0, 5959, 0, 0, 66275, 43371, 0, 0, 0, 0, 0, 12769, - 69793, 0, 1283, 0, 4779, 0, 3719, 4006, 0, 0, 71186, 68204, 124957, 0, - 119331, 43028, 65493, 0, 125058, 5962, 65485, 92616, 0, 43501, 5827, 0, - 120951, 0, 65494, 0, 129365, 0, 0, 43879, 0, 0, 0, 0, 983205, 65467, 0, - 0, 0, 0, 521, 0, 0, 983928, 0, 0, 483, 7096, 0, 0, 928, 0, 0, 0, 0, - 92983, 3989, 73972, 122980, 0, 0, 0, 12145, 0, 73932, 0, 0, 3769, 67460, - 0, 0, 0, 0, 0, 65290, 92223, 0, 65855, 0, 0, 0, 0, 128811, 0, 0, 0, 0, 0, - 0, 73838, 0, 0, 13007, 67506, 0, 0, 12661, 7608, 75032, 12213, 0, 0, 0, - 0, 12195, 4001, 3112, 67474, 0, 7590, 0, 0, 421, 0, 0, 0, 4130, 127775, - 7595, 42588, 7600, 0, 0, 0, 0, 65851, 42607, 0, 92403, 8680, 0, 42134, 0, - 0, 2846, 92605, 0, 0, 0, 0, 12979, 0, 0, 92558, 3740, 69843, 120437, 0, - 120451, 65923, 120435, 0, 120434, 0, 93800, 3118, 74265, 93795, 93816, - 93823, 93797, 8127, 92912, 93792, 7943, 93821, 93799, 10618, 2584, 93793, - 0, 0, 9998, 0, 0, 0, 66350, 0, 0, 0, 121374, 8279, 128169, 0, 4975, - 70075, 0, 118675, 1631, 0, 0, 0, 6290, 128994, 66386, 0, 64645, 0, 0, 0, - 0, 0, 9242, 93807, 93802, 93801, 983269, 93803, 3122, 93804, 7793, 0, 0, - 0, 0, 12604, 92885, 6615, 67650, 0, 3986, 44025, 0, 8912, 0, 7409, 0, 0, - 0, 0, 0, 0, 8540, 11498, 0, 0, 0, 0, 0, 13060, 120682, 0, 0, 0, 0, 0, - 121345, 0, 0, 7020, 120353, 3765, 92881, 0, 1606, 120348, 120351, 3093, - 110593, 0, 0, 0, 0, 0, 0, 92892, 120337, 69402, 120339, 4023, 120333, - 120332, 120335, 92250, 120345, 12810, 120347, 120346, 4455, 120340, - 120343, 120342, 66660, 0, 0, 0, 0, 113720, 13089, 74355, 120329, 120328, - 42758, 12196, 128429, 0, 0, 0, 0, 128867, 94179, 0, 3120, 9797, 0, 0, - 11086, 10389, 0, 101025, 4895, 128153, 124941, 4359, 0, 0, 3509, 70037, - 486, 0, 0, 0, 0, 0, 7004, 0, 0, 0, 0, 4855, 128200, 0, 0, 0, 0, 0, 0, - 10381, 70839, 0, 0, 0, 0, 125121, 70837, 125070, 129431, 983377, 983365, - 0, 983364, 0, 120063, 0, 0, 0, 75048, 0, 74900, 0, 0, 120978, 12161, - 983356, 0, 10339, 0, 77808, 0, 0, 917846, 77806, 0, 43032, 125010, 0, - 983383, 12671, 11384, 0, 0, 120901, 64797, 0, 5820, 0, 0, 0, 0, 0, - 120650, 42137, 9893, 8851, 12664, 0, 0, 13192, 0, 41799, 65530, 0, 0, - 43039, 3114, 0, 0, 0, 0, 0, 926, 77803, 72004, 77805, 77799, 77800, - 77801, 77802, 43037, 41798, 77797, 77798, 123214, 41801, 0, 0, 0, 4200, - 12699, 8331, 70118, 3091, 92980, 66298, 70293, 8360, 0, 78044, 0, 4229, - 64543, 126227, 65563, 0, 129310, 2861, 43793, 10095, 121428, 9195, - 121381, 121132, 0, 129578, 0, 0, 43041, 0, 43794, 0, 83167, 0, 43797, - 8209, 0, 129132, 12973, 0, 0, 0, 0, 0, 121235, 5760, 0, 743, 0, 0, 0, - 118712, 0, 0, 83170, 128589, 129537, 0, 119063, 0, 0, 0, 19919, 0, 64532, - 0, 43710, 0, 0, 9483, 71115, 0, 43697, 0, 0, 83211, 0, 0, 0, 7247, 0, 0, - 0, 0, 0, 113674, 0, 7471, 120823, 128743, 12682, 0, 0, 65679, 983144, 0, - 0, 83201, 1099, 74241, 0, 10501, 0, 0, 113743, 0, 64743, 128476, 67663, - 0, 0, 92219, 0, 83197, 64897, 9973, 1818, 0, 0, 8272, 127812, 0, 4218, - 3087, 0, 127234, 122935, 101300, 65181, 9954, 10465, 0, 0, 0, 9106, 0, - 67406, 0, 0, 0, 0, 43038, 0, 0, 265, 70208, 0, 0, 0, 0, 0, 69405, 0, 59, - 0, 0, 0, 0, 126239, 41810, 0, 126492, 0, 41809, 41888, 0, 41795, 0, - 42213, 0, 0, 43033, 511, 42963, 0, 13127, 0, 0, 0, 0, 111107, 100489, - 4467, 41812, 41215, 0, 41211, 917783, 4453, 69575, 0, 129883, 0, 983412, - 41213, 92864, 118716, 0, 0, 129730, 41841, 6617, 130041, 0, 92995, 462, - 0, 10493, 0, 55248, 0, 0, 74471, 6644, 0, 0, 0, 983388, 100484, 9581, - 67104, 3098, 0, 0, 983415, 125250, 0, 120621, 0, 0, 0, 129584, 101011, 0, - 118789, 74473, 3755, 64661, 7748, 7235, 3966, 0, 0, 127510, 0, 0, 0, - 5726, 66456, 42175, 100486, 0, 42212, 92681, 121443, 2851, 43017, 120108, - 121056, 4373, 0, 0, 9587, 0, 6671, 128840, 3100, 0, 917790, 0, 0, 0, - 917789, 70209, 8190, 12083, 917791, 0, 6689, 64629, 0, 0, 0, 4419, - 917787, 101017, 0, 69851, 0, 0, 8891, 3080, 0, 2347, 0, 0, 8990, 0, - 121201, 0, 92528, 249, 129008, 0, 69424, 0, 0, 0, 55253, 0, 0, 11173, - 995, 0, 121047, 119861, 0, 73708, 0, 0, 19945, 0, 558, 983399, 12273, 0, - 983881, 0, 69912, 120861, 129492, 67274, 94178, 0, 68019, 43030, 3129, 0, - 2102, 0, 0, 121450, 0, 7725, 0, 11120, 0, 126111, 69246, 0, 0, 0, 41894, - 0, 41898, 0, 41893, 74921, 128678, 3540, 11848, 0, 73005, 120848, 0, 0, - 126113, 73959, 0, 0, 128735, 120858, 0, 0, 9699, 128656, 41896, 0, 83196, - 69230, 74951, 0, 72736, 0, 0, 3095, 983689, 11946, 983885, 0, 0, 0, 0, 0, - 113677, 3672, 111309, 0, 0, 0, 128539, 8890, 93826, 0, 128182, 0, 0, 0, - 126568, 0, 0, 983617, 9516, 983441, 72109, 0, 42220, 0, 4450, 0, 11547, - 43417, 128542, 356, 0, 0, 0, 0, 64901, 0, 0, 0, 0, 0, 0, 111302, 65940, - 2541, 71231, 0, 123215, 126470, 3549, 0, 0, 0, 2743, 0, 0, 0, 9097, - 128896, 43015, 0, 0, 776, 2524, 0, 8573, 100665, 126494, 0, 0, 42694, - 71122, 8952, 10814, 118818, 0, 43646, 128598, 66944, 0, 0, 128380, - 100663, 0, 65853, 42707, 1897, 93071, 0, 0, 71907, 69410, 0, 125106, 0, - 0, 0, 68473, 66778, 43573, 92638, 0, 0, 0, 120955, 73986, 0, 0, 43022, 0, - 74841, 0, 67714, 0, 0, 0, 0, 0, 4553, 0, 0, 0, 0, 0, 19921, 0, 0, 983687, - 4567, 41891, 0, 983819, 55249, 194663, 0, 194662, 0, 194665, 43042, - 121291, 1377, 12869, 0, 0, 9250, 0, 0, 0, 129779, 125039, 194642, 0, - 74995, 0, 194644, 0, 0, 101328, 194668, 121166, 0, 70275, 1898, 69556, 0, - 0, 802, 0, 0, 0, 6648, 0, 2528, 0, 0, 194646, 194625, 101330, 68804, 844, - 0, 68824, 0, 68818, 194650, 0, 0, 0, 983743, 65464, 0, 0, 0, 0, 83221, 0, - 0, 100680, 42954, 0, 64371, 70665, 0, 194654, 0, 0, 0, 0, 0, 6196, 6945, - 0, 0, 0, 120491, 0, 68846, 6210, 0, 70274, 0, 0, 0, 68067, 68834, 194715, - 588, 9760, 129112, 0, 983723, 119505, 0, 127992, 0, 0, 118905, 0, 0, - 92485, 110839, 69396, 0, 3394, 70734, 194639, 0, 0, 0, 0, 0, 0, 194656, - 7817, 1841, 11055, 195001, 194979, 194983, 127011, 67403, 194987, 7701, - 194998, 0, 194995, 1946, 121404, 0, 0, 917631, 0, 0, 10934, 0, 70376, 0, - 0, 8071, 3538, 0, 2287, 65328, 0, 0, 7614, 0, 0, 0, 12009, 43968, 0, - 67852, 0, 0, 10841, 123640, 0, 0, 0, 0, 8960, 0, 0, 65317, 128829, 0, 0, - 70374, 0, 0, 0, 65315, 0, 0, 0, 0, 0, 119621, 0, 11849, 12447, 0, 0, - 110741, 0, 0, 0, 129976, 42767, 0, 0, 0, 43695, 120520, 11975, 194941, - 983448, 0, 2555, 0, 128640, 70070, 42936, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 66714, 0, 0, 70076, 65596, 121034, 66710, 67658, 0, 126994, 65338, - 7792, 0, 0, 67871, 119027, 0, 8233, 43572, 0, 0, 0, 3442, 110933, 2841, - 12543, 0, 1473, 42820, 64329, 127832, 917772, 126126, 7937, 0, 1048, 0, - 0, 983943, 0, 3406, 1054, 100701, 1040, 65450, 0, 92329, 1069, 917763, - 128367, 128940, 0, 917765, 0, 983724, 9693, 110873, 0, 0, 0, 983948, - 4353, 118653, 1059, 127530, 0, 0, 0, 127093, 118862, 120500, 10646, - 118708, 100710, 917762, 70424, 74830, 0, 0, 983720, 10221, 100706, 68255, - 0, 0, 74346, 119619, 100707, 64945, 12921, 0, 0, 0, 0, 0, 983795, 43020, - 0, 0, 74254, 0, 983785, 0, 0, 983792, 0, 71954, 0, 0, 0, 0, 122625, 0, - 120503, 70663, 0, 2755, 0, 0, 0, 4857, 0, 4428, 0, 0, 983791, 0, 0, 0, - 43842, 0, 122899, 0, 7978, 0, 70392, 127080, 11924, 43812, 0, 65015, - 67472, 563, 68340, 0, 12798, 0, 100727, 0, 0, 0, 74110, 0, 94051, 0, 694, - 0, 9876, 0, 119168, 0, 0, 0, 92361, 0, 0, 7229, 0, 0, 0, 0, 64811, 0, - 119087, 126478, 0, 7381, 0, 2525, 4852, 11586, 68465, 41605, 126089, 0, - 11582, 7151, 10155, 92578, 188, 0, 11592, 0, 74015, 0, 0, 4858, 122645, - 0, 0, 4861, 0, 2786, 121431, 4856, 8051, 0, 119609, 0, 113797, 71133, 0, - 78448, 0, 0, 67842, 68084, 0, 0, 0, 0, 0, 10234, 5843, 0, 71865, 66728, - 0, 3157, 0, 0, 75035, 72788, 983750, 0, 10822, 5149, 129517, 0, 65142, - 129454, 4565, 0, 0, 0, 12657, 0, 0, 386, 0, 8834, 120974, 0, 43574, 0, 0, - 0, 70113, 7220, 11839, 124984, 74883, 194752, 0, 65241, 74503, 8160, 0, - 194753, 0, 0, 0, 0, 0, 121265, 6847, 13303, 0, 0, 194755, 0, 118865, 0, - 194761, 0, 0, 74505, 0, 0, 0, 100518, 194721, 8780, 100512, 0, 68745, - 110626, 66697, 0, 2672, 3735, 983641, 0, 68752, 11205, 10724, 41202, 0, - 100714, 0, 0, 0, 0, 194765, 3842, 0, 78183, 12442, 78182, 9791, 78181, 0, - 42516, 67730, 64821, 195059, 78178, 0, 78464, 119219, 78465, 127466, - 194690, 195063, 0, 0, 0, 0, 78540, 78541, 78538, 1962, 78490, 78476, - 65930, 11660, 0, 2072, 0, 0, 78544, 194704, 78542, 10669, 110859, 110860, - 110857, 110858, 129749, 110856, 4105, 0, 194699, 0, 0, 0, 13148, 195068, - 78479, 9226, 0, 0, 10765, 127486, 71919, 6263, 195050, 0, 195041, 0, 0, - 0, 0, 0, 0, 92312, 7886, 0, 6682, 0, 6680, 195042, 126473, 195052, 6679, - 74412, 0, 72206, 74421, 66281, 0, 0, 127478, 0, 0, 92861, 6681, 0, 12693, - 0, 0, 0, 0, 0, 65442, 129055, 0, 9989, 74415, 194673, 0, 0, 983788, 0, 0, - 0, 0, 7042, 127240, 119026, 7968, 0, 983768, 194741, 194736, 983793, 0, - 69889, 74389, 128696, 0, 0, 128979, 5781, 0, 78199, 0, 124145, 11091, 0, - 2719, 0, 0, 0, 64495, 0, 0, 0, 65169, 42845, 0, 128551, 983766, 2200, - 72435, 0, 0, 0, 917855, 66670, 0, 983709, 0, 0, 0, 7902, 0, 65265, 0, 0, - 0, 0, 0, 0, 0, 12994, 0, 10828, 983974, 0, 4307, 3482, 0, 0, 72389, 0, - 64299, 74573, 41194, 7343, 0, 0, 41195, 0, 8169, 0, 8841, 66770, 516, - 72981, 41197, 119051, 34, 128850, 120186, 11504, 1612, 120187, 120182, - 120181, 120184, 12001, 120178, 120177, 120180, 120179, 71966, 120173, - 7749, 120175, 0, 1758, 0, 10667, 0, 120197, 0, 1935, 11517, 120193, - 120196, 78925, 120190, 120189, 120192, 120191, 1217, 64702, 128075, 825, - 0, 129824, 0, 0, 66748, 0, 11050, 0, 123187, 0, 0, 74554, 110577, 0, - 8677, 123188, 11313, 123185, 3403, 0, 123186, 64364, 92683, 0, 0, 0, 0, - 123189, 0, 0, 983880, 0, 69408, 41850, 0, 3433, 127965, 0, 1594, 65607, - 0, 66392, 0, 129291, 74565, 41353, 125119, 78926, 0, 0, 0, 918, 127280, - 41351, 0, 0, 12140, 0, 12668, 72395, 0, 128753, 0, 127302, 0, 127288, - 129497, 127235, 573, 0, 0, 11417, 0, 127283, 0, 0, 0, 72410, 0, 11482, 0, - 3981, 74345, 0, 0, 0, 0, 0, 0, 125238, 0, 0, 42195, 0, 123190, 129764, - 64602, 0, 0, 121366, 0, 121061, 128690, 0, 8423, 0, 448, 66907, 9717, 0, - 0, 0, 0, 0, 0, 0, 71910, 129898, 0, 0, 120679, 65013, 78169, 0, 72390, 0, - 0, 127917, 0, 74892, 0, 0, 127798, 0, 0, 66982, 0, 0, 0, 12197, 125074, - 0, 121447, 0, 0, 0, 0, 0, 0, 0, 74563, 64828, 11419, 0, 8592, 0, 0, 0, - 11381, 0, 0, 74529, 0, 0, 83254, 0, 72796, 0, 83257, 0, 0, 0, 129437, - 65672, 0, 0, 0, 0, 0, 0, 0, 0, 9505, 0, 0, 756, 0, 125243, 100358, - 110852, 7261, 0, 0, 0, 0, 0, 64401, 65830, 41365, 0, 0, 0, 127834, 0, 0, - 0, 0, 0, 74626, 123155, 11578, 0, 2170, 0, 0, 0, 0, 74568, 0, 113684, - 1794, 68310, 120218, 120219, 120220, 120221, 120222, 120223, 3617, - 120011, 64886, 94061, 78202, 120213, 66999, 10225, 983060, 0, 65223, - 983058, 0, 0, 4452, 127779, 0, 0, 66981, 0, 0, 0, 11425, 0, 0, 1231, 0, - 0, 0, 124121, 8192, 124118, 0, 0, 10616, 8694, 0, 68867, 128332, 123595, - 120200, 120201, 120202, 120203, 9878, 120205, 119626, 120207, 0, 8799, - 42131, 0, 127163, 0, 120198, 120199, 837, 120015, 72384, 0, 983836, 2180, - 11427, 0, 78154, 0, 70171, 0, 78150, 42606, 0, 119615, 78147, 64637, - 78146, 43060, 78145, 125009, 3392, 0, 194783, 119067, 119650, 65468, - 43498, 126083, 0, 0, 0, 194928, 194937, 194938, 64681, 194930, 83264, - 92451, 0, 194955, 83262, 983751, 8973, 0, 194967, 70177, 194968, 0, 4800, - 195018, 0, 0, 11820, 6852, 122981, 0, 4802, 4111, 111268, 0, 4805, - 127308, 68193, 7885, 121220, 0, 0, 0, 4767, 0, 0, 0, 0, 0, 125234, - 100366, 43453, 0, 41340, 0, 0, 10005, 65856, 41333, 0, 9518, 0, 0, 0, - 42520, 100850, 0, 0, 917562, 100506, 0, 0, 0, 0, 0, 0, 9167, 42151, - 124958, 0, 2026, 100848, 124139, 0, 100534, 12768, 0, 7582, 0, 0, 0, 0, - 129557, 0, 120539, 68879, 0, 43547, 119992, 8546, 126071, 78520, 7604, - 78518, 78519, 78514, 78517, 78511, 78512, 73802, 128140, 0, 6708, 10535, - 0, 68218, 55274, 68221, 92296, 0, 0, 0, 0, 0, 72385, 0, 0, 0, 73727, 0, - 120706, 74442, 66943, 0, 0, 4351, 0, 119887, 119888, 0, 119886, 119891, - 68866, 119889, 11433, 119895, 119896, 0, 119894, 65578, 194693, 0, 0, - 983070, 10681, 0, 0, 128737, 0, 983111, 0, 6722, 129364, 0, 119997, - 41546, 64860, 68394, 0, 41549, 118619, 72386, 0, 0, 0, 0, 64710, 41547, - 0, 0, 0, 78530, 78532, 78528, 78529, 71343, 78527, 78523, 78525, 3537, - 119908, 119905, 7155, 2264, 0, 78533, 67755, 0, 0, 0, 0, 0, 0, 0, 64715, - 0, 0, 537, 0, 4179, 0, 0, 0, 0, 0, 0, 0, 0, 12081, 0, 0, 4048, 7053, 0, - 0, 70459, 0, 124975, 0, 3059, 0, 0, 43491, 983833, 0, 0, 127993, 4100, - 920, 1811, 1355, 0, 0, 64383, 10078, 69398, 0, 118651, 0, 65870, 0, - 129565, 0, 72400, 42918, 0, 66789, 0, 12865, 0, 73938, +static const unsigned short dawg_codepoint_to_pos_index2[] = { + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 29174, 13037, 26950, 24736, 10779, 26523, 358, 1041, 19550, + 27163, 2511, 26774, 8150, 15996, 13206, 29017, 10563, 10548, 10560, + 10557, 10542, 10539, 10554, 10551, 10566, 10545, 7753, 27749, 19776, + 12475, 13751, 26948, 8149, 18159, 18205, 18215, 18231, 18246, 18291, + 18295, 18312, 18326, 18355, 18360, 18372, 18390, 18399, 18415, 18465, + 18473, 18476, 18496, 18519, 18548, 18587, 18598, 18607, 18610, 18624, + 19518, 27073, 27177, 6518, 20535, 13722, 18716, 18766, 18786, 18809, + 18845, 18904, 18912, 18930, 18949, 18986, 18992, 19006, 19044, 19057, + 19081, 19138, 19149, 19155, 19193, 19234, 19307, 19355, 19369, 19378, + 19386, 19402, 19466, 33652, 27135, 32321, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 24729, + 16349, 5830, 26815, 9647, 34209, 4636, 27731, 10531, 8344, 13111, 19565, + 24711, 28968, 26996, 22169, 10248, 26786, 29740, 29739, 4, 22895, 26671, + 22898, 5826, 29743, 21136, 27214, 33780, 33778, 33786, 16352, 18188, + 18189, 18177, 18191, 18170, 18172, 18193, 18216, 18277, 18278, 18249, + 18264, 18342, 18343, 18332, 18330, 18288, 18413, 18454, 18455, 18422, + 18440, 18429, 23603, 18438, 18579, 18580, 18549, 18552, 18619, 18540, + 19224, 18747, 18748, 18736, 18750, 18727, 18729, 18753, 18787, 18878, + 18879, 18848, 18863, 18967, 18968, 18950, 18952, 18903, 19076, 19120, + 19121, 19082, 19106, 19089, 10690, 19104, 19342, 19345, 19310, 19313, + 19397, 19256, 19388, 18175, 18734, 18160, 18717, 18185, 18744, 18220, + 18792, 18218, 18789, 18224, 18797, 18219, 18791, 18238, 18817, 18235, + 18811, 18267, 18867, 18280, 18881, 18259, 18858, 18274, 18875, 18258, + 18857, 18297, 18914, 18300, 18917, 18304, 18922, 18296, 18913, 18315, + 18933, 18322, 18942, 18336, 18964, 18334, 18959, 18345, 18970, 18339, + 18961, 18329, 18833, 18636, 19422, 18356, 18987, 18361, 18993, 19005, + 18386, 19023, 18382, 19010, 18384, 19013, 18379, 19020, 18381, 19031, + 18408, 19069, 18400, 19058, 18402, 19062, 19077, 18290, 18886, 18418, + 19099, 18457, 19123, 18435, 19095, 18637, 19425, 18485, 19172, 18477, + 19156, 18478, 19158, 18502, 19194, 18501, 19200, 18499, 19198, 18497, + 19196, 18520, 19235, 18523, 19239, 18530, 19251, 18576, 19339, 18568, + 19329, 18582, 19347, 18583, 19338, 18559, 19320, 18573, 19334, 18599, + 19370, 18611, 19387, 18612, 18627, 19403, 18630, 19409, 18626, 19406, + 19036, 18775, 18211, 18206, 18767, 18543, 19259, 18460, 18222, 18795, + 18198, 18243, 18239, 18812, 19264, 18494, 18518, 18459, 18292, 18907, + 18303, 18310, 18948, 18353, 18346, 18371, 19004, 19009, 19032, 18537, + 18406, 19063, 18421, 18447, 19113, 18462, 19135, 18471, 19146, 18713, + 18544, 19260, 18289, 18653, 19247, 18529, 19248, 18528, 18561, 19322, + 18586, 18591, 18616, 19392, 18633, 19412, 18282, 18284, 18896, 18901, + 18706, 18545, 19261, 18652, 18705, 18707, 18708, 18645, 18655, 18245, + 18233, 18839, 18389, 18380, 19043, 18414, 18403, 19080, 18183, 18742, + 18333, 18951, 18428, 19088, 18551, 19312, 18556, 19317, 18555, 19316, + 18553, 19314, 18554, 19315, 19296, 18171, 18728, 18167, 18724, 18195, + 18756, 18305, 18923, 18298, 18915, 18362, 18994, 18436, 19102, 18437, + 19103, 18283, 18898, 18989, 18244, 18232, 18838, 18299, 18916, 18324, + 18606, 18407, 19068, 18173, 18730, 18194, 18755, 18439, 19105, 18169, + 18726, 18190, 18749, 18263, 18862, 18279, 18880, 18327, 18958, 18344, + 18969, 18434, 19094, 18456, 19122, 18482, 19162, 18487, 19173, 18558, + 19319, 18581, 19346, 18500, 19199, 18522, 19237, 18623, 19401, 18316, + 18934, 18404, 18816, 18464, 19137, 18635, 19416, 18166, 18723, 18247, + 18846, 18430, 19090, 18443, 19109, 18431, 19091, 18432, 19092, 18620, + 19398, 19012, 19061, 19238, 18830, 18843, 19154, 18192, 18225, 18798, + 18374, 18524, 19206, 19411, 18306, 18924, 18212, 18585, 18539, 18281, + 18883, 18359, 18991, 18512, 19152, 18489, 19176, 18622, 19396, 19288, + 18758, 19289, 18774, 19126, 18790, 18813, 18821, 19185, 19215, 19219, + 19132, 19180, 19182, 18805, 18831, 18921, 19222, 18682, 18928, 19192, + 19265, 18941, 18947, 18971, 18982, 18660, 19018, 19007, 19026, 19033, + 19291, 19292, 19052, 19065, 19074, 18693, 18778, 18667, 18804, 19148, + 19276, 19279, 19282, 19167, 19168, 19163, 19183, 18669, 18661, 19212, + 18889, 18832, 19232, 18893, 19283, 19250, 19308, 19349, 19362, 19285, + 19300, 19293, 18700, 19415, 19405, 18895, 18897, 18709, 18711, 18650, + 18702, 18648, 18680, 18803, 18683, 18689, 18988, 19298, 18662, 19151, + 18710, 18654, 18840, 18826, 18841, 19303, 19252, 19302, 18910, 19040, + 19041, 18647, 18649, 19266, 19267, 23222, 23223, 23231, 23253, 23280, + 23283, 23178, 23300, 23302, 23151, 23094, 23308, 23005, 23159, 23161, + 23137, 23110, 23157, 23139, 23163, 23310, 23096, 23086, 5759, 23314, + 23140, 23004, 23109, 23135, 23126, 23132, 23131, 23307, 23117, 23038, + 23037, 23309, 23095, 23150, 23148, 4629, 10885, 27334, 25266, 28928, + 10944, 23164, 23087, 23221, 23233, 23260, 23301, 23257, 23101, 23116, + 23144, 23129, 23106, 23316, 23315, 23313, 23311, 23093, 23122, 23134, + 23124, 23127, 23128, 23147, 23146, 23145, 23130, 23156, 23007, 23107, + 23008, 23108, 23166, 23149, 23123, 7961, 7759, 7843, 8125, 8067, 8087, + 7769, 7868, 7865, 7974, 8112, 7894, 7775, 8140, 7893, 7895, 7777, 7977, + 8133, 7780, 8095, 7781, 7962, 7760, 8052, 8108, 8046, 7976, 8049, 8135, + 7899, 8092, 8076, 8091, 8096, 7871, 7867, 8111, 7782, 7845, 8085, 8139, + 7772, 7980, 7776, 7844, 7771, 7978, 8129, 8072, 8066, 7896, 8128, 8116, + 8064, 8115, 8063, 8103, 7979, 8119, 8123, 8147, 8141, 7882, 7963, 7761, + 7971, 7970, 7973, 7972, 7773, 7908, 7892, 8045, 8078, 7975, 7768, 8053, + 8134, 7966, 8099, 8050, 7909, 8146, 8041, 8100, 8098, 8104, 7870, 7765, + 7887, 8114, 7876, 7875, 7879, 7880, 7888, 7877, 7886, 7993, 8001, 8006, + 8014, 8017, 7999, 8031, 8033, 8035, 8020, 8023, 8038, 8039, 13936, 14200, + 13831, 14067, 14018, 14014, 13925, 14182, 35762, 35762, 14257, 14207, + 14208, 14206, 14262, 13939, 35762, 35762, 35762, 35762, 14222, 13952, + 13829, 13805, 13862, 13852, 13876, 35762, 13908, 35762, 13923, 13898, + 14114, 13808, 13935, 13933, 13931, 13853, 13937, 13832, 13929, 13863, + 13932, 13938, 13940, 13941, 13942, 13899, 13928, 13909, 35762, 13911, + 13930, 13914, 13926, 13934, 13927, 13878, 13868, 13919, 14064, 14079, + 14104, 14123, 14134, 14039, 14199, 14197, 14069, 14070, 14201, 14080, + 14194, 14105, 14145, 14202, 14203, 14204, 14205, 14172, 14185, 14186, + 14196, 14192, 14195, 14125, 14183, 14198, 14184, 14147, 14110, 14130, + 14181, 14143, 14171, 13947, 14259, 14218, 14226, 14224, 14225, 14034, + 14035, 13999, 14010, 14066, 14009, 14191, 14012, 14068, 14011, 14146, + 14008, 14189, 8225, 8319, 8203, 8297, 8199, 8293, 8197, 8291, 8195, 8289, + 8224, 8318, 8194, 8288, 13998, 14037, 14015, 14013, 13948, 14016, 14038, + 13913, 14193, 13943, 13912, 14190, 14036, 13945, 13946, 13944, 9913, + 9915, 9862, 9901, 9837, 9866, 9853, 9972, 9985, 9809, 9812, 9826, 9940, + 9910, 9953, 9870, 9838, 9854, 9986, 9895, 9874, 9912, 9979, 9975, 9908, + 9951, 9925, 9876, 9892, 9881, 9944, 9813, 9887, 9890, 9823, 9832, 9894, + 9902, 9829, 9855, 9958, 9956, 9906, 9969, 9961, 9875, 9974, 9966, 9997, + 10013, 10186, 10054, 10033, 10071, 10179, 10175, 10067, 10129, 10084, + 10035, 10051, 10040, 10110, 10115, 10046, 10049, 10147, 10157, 10053, + 10061, 10153, 10014, 10136, 10134, 10065, 10169, 10139, 10034, 10174, + 10166, 10072, 10074, 10021, 10060, 10162, 10025, 10012, 10172, 10185, + 10103, 10109, 10150, 10099, 10069, 10131, 10029, 9945, 10111, 9968, + 10168, 9921, 10080, 9808, 10101, 9917, 10076, 9850, 10009, 9918, 10077, + 9941, 10100, 9816, 10119, 9984, 10184, 9923, 10082, 9924, 10083, 9836, + 10161, 9817, 10124, 9946, 10112, 9948, 10114, 9938, 10097, 10217, 7836, + 7830, 7833, 7831, 7832, 7786, 7839, 9952, 10130, 9965, 10143, 9888, + 10047, 9897, 10056, 9899, 10058, 9896, 10055, 9981, 10181, 9977, 10177, + 9926, 10085, 9928, 10087, 9929, 10088, 9848, 10007, 9883, 10042, 9991, + 10190, 9814, 10116, 9844, 10003, 9891, 10050, 9825, 10149, 9963, 10141, + 9964, 10142, 9903, 10062, 9990, 10189, 9857, 10016, 9858, 10017, 9954, + 10132, 9841, 10000, 9842, 10001, 9994, 9982, 10182, 9927, 10086, 9879, + 10038, 9886, 10045, 9885, 10044, 9939, 10098, 9893, 10052, 10118, 9840, + 9999, 9839, 9998, 9989, 10188, 9914, 10073, 9949, 10127, 9950, 10128, + 9980, 10180, 9976, 10176, 9843, 10002, 9911, 10070, 9909, 10068, 9947, + 10113, 9846, 10005, 9847, 10006, 9889, 10048, 9835, 10160, 9834, 10159, + 9833, 10158, 9856, 10015, 9898, 10057, 9970, 10170, 9900, 10059, 9904, + 10063, 9905, 10064, 9932, 10091, 9931, 10090, 9937, 10096, 9930, 10089, + 9933, 10092, 9934, 10093, 9935, 10094, 9936, 10095, 9821, 10123, 9880, + 10039, 9810, 10104, 9822, 10126, 9967, 10167, 9988, 10187, 9987, 10165, + 9845, 10004, 9877, 10036, 9882, 10041, 9815, 10117, 9955, 10133, 9884, + 10043, 9868, 10027, 9872, 10031, 9878, 10037, 35762, 2429, 2436, 2420, + 2442, 2416, 2440, 2417, 2418, 2407, 2439, 2435, 2432, 2434, 2412, 2424, + 2441, 2422, 2419, 2410, 2437, 2408, 2438, 2427, 2431, 2411, 2426, 2421, + 2415, 2428, 2430, 2406, 2414, 2413, 2409, 2425, 2423, 2443, 2433, 35762, + 35762, 2493, 2405, 2445, 2446, 2444, 2497, 2404, 2466, 2469, 2479, 2457, + 2485, 2453, 2483, 2454, 2455, 2468, 2482, 2478, 2475, 2477, 2449, 2461, + 2484, 2459, 2456, 2447, 2480, 2472, 2481, 2464, 2471, 2448, 2463, 2458, + 2452, 2465, 2470, 2467, 2451, 2450, 2474, 2462, 2460, 2486, 2476, 2487, + 2473, 2496, 2494, 35762, 35762, 27207, 19558, 2495, 35762, 15349, 15352, + 15353, 15360, 15361, 15357, 15364, 15362, 15347, 15359, 15356, 15340, + 15341, 15342, 15350, 15355, 15348, 15337, 15345, 15346, 15343, 15344, + 15339, 15351, 15354, 15358, 15365, 15366, 15338, 15363, 15444, 15460, + 15448, 15446, 15447, 15449, 15462, 15458, 15452, 15454, 15450, 15451, + 15456, 15445, 15463, 15469, 15457, 15466, 15459, 15461, 15467, 15443, + 15442, 15468, 15455, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 15367, 15374, 15417, 15415, 15392, 15423, 15397, 15394, 15409, + 15434, 15383, 15377, 15419, 15389, 15421, 15388, 15395, 15399, 15373, + 15385, 15380, 15387, 15413, 15390, 15407, 15401, 15411, 35762, 35762, + 35762, 35762, 15470, 15438, 15441, 15439, 15465, 15464, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 2249, + 2283, 1081, 2284, 2285, 2248, 2392, 2393, 2259, 2390, 2391, 2582, 1056, + 1063, 2253, 2289, 2282, 2288, 2280, 2281, 2290, 2310, 2296, 2325, 2292, + 2341, 2340, 2276, 1367, 1072, 2380, 2388, 1322, 1275, 1139, 1129, 1554, + 1132, 1570, 1111, 1153, 1497, 1496, 1517, 1301, 1260, 1341, 1178, 1514, + 1419, 1596, 1453, 1466, 1445, 1193, 1475, 1591, 1101, 1247, 1328, 1325, + 1222, 1221, 1220, 2368, 1227, 1410, 1312, 1346, 1359, 1383, 1277, 1549, + 1147, 1561, 1079, 1061, 1091, 1073, 1057, 1087, 2277, 2345, 2102, 1086, + 1085, 2344, 2266, 2103, 2389, 2384, 2383, 2385, 2260, 1074, 2387, 2400, + 2402, 2399, 2398, 2395, 2394, 2397, 2396, 2403, 2401, 2257, 1068, 2382, + 1082, 1205, 1207, 1472, 1144, 1136, 1135, 1297, 1298, 1300, 1535, 1299, + 1523, 1529, 1173, 1505, 1504, 1398, 1509, 1168, 1270, 1268, 1378, 1208, + 1267, 1484, 1491, 1202, 1187, 1179, 1180, 1190, 1199, 1213, 1183, 1186, + 1436, 1422, 1433, 1430, 1423, 1431, 1426, 1309, 1429, 1454, 1457, 1458, + 1448, 1447, 1478, 1104, 1206, 1230, 1228, 1542, 1232, 1405, 1413, 1414, + 1323, 1474, 1317, 1316, 1368, 1314, 1238, 1241, 1369, 1240, 1254, 1239, + 1350, 1348, 1352, 1351, 1392, 1384, 1439, 1393, 1389, 1288, 1486, 1285, + 1278, 1279, 1500, 1558, 1335, 1588, 1534, 1585, 1338, 1557, 1541, 1216, + 1579, 1575, 1551, 1600, 1580, 1562, 1565, 1083, 1152, 2299, 2298, 2301, + 2300, 2327, 2309, 2307, 1071, 2367, 2324, 2323, 2293, 2302, 2339, 2303, + 2343, 2342, 2321, 2304, 2255, 1070, 1069, 2264, 2338, 1182, 1427, 13052, + 13054, 13051, 13050, 13047, 13046, 13049, 13048, 13055, 13053, 1467, + 1194, 1249, 2287, 2286, 1284, 29867, 29941, 29938, 29939, 29935, 29876, + 29863, 29864, 29940, 29937, 29862, 29872, 29871, 29870, 35762, 29860, + 29908, 29904, 29918, 29914, 29915, 29878, 29877, 29879, 29921, 29919, + 29880, 29911, 29912, 29916, 29917, 29909, 29881, 29893, 29920, 29900, + 29907, 29922, 29894, 29898, 29906, 29910, 29899, 29905, 29913, 29895, + 29897, 29896, 29927, 29926, 29925, 29930, 29929, 29928, 29932, 29931, + 29866, 29865, 29875, 29874, 29873, 29869, 29868, 29933, 29947, 29948, + 29934, 29945, 29944, 29943, 29942, 29924, 29923, 29946, 29861, 35762, + 35762, 29901, 29902, 29903, 1159, 1162, 1157, 1158, 1160, 1161, 1155, + 1269, 1266, 1185, 1181, 1424, 1460, 1106, 1102, 1105, 1233, 1231, 1330, + 1326, 1324, 1362, 1361, 1390, 1387, 1388, 1353, 1425, 1428, 1459, 1265, + 1263, 1456, 1420, 1264, 1138, 1137, 1219, 1218, 1217, 1553, 1552, 1564, + 1563, 1261, 1461, 1455, 1313, 31890, 31903, 31899, 31916, 31915, 31894, + 31891, 31879, 31910, 31895, 31884, 31883, 31906, 31893, 31886, 31887, + 31904, 31882, 31912, 31905, 31917, 31898, 31897, 31896, 31908, 31889, + 31892, 31907, 31913, 31902, 31901, 31881, 31909, 31914, 31880, 31888, + 31885, 31911, 31875, 31874, 31921, 31877, 31922, 31920, 31876, 31878, + 31919, 31918, 31923, 31900, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 24597, 24599, + 24596, 24595, 24592, 24591, 24594, 24593, 24600, 24598, 24632, 24619, + 24633, 24618, 24634, 24616, 24615, 24603, 24608, 24621, 24627, 24629, + 24607, 24617, 24602, 24614, 24613, 24628, 24620, 24622, 24624, 24625, + 24610, 24626, 24611, 24609, 24623, 24630, 24631, 24612, 24605, 24604, + 24606, 24584, 24585, 24586, 24582, 24579, 24580, 24581, 24583, 24587, + 24636, 24635, 24638, 24637, 24588, 24639, 24601, 35762, 35762, 24589, + 24590, 24640, 27560, 27547, 27561, 27549, 27552, 27548, 27563, 27551, + 27558, 27567, 27553, 27554, 27564, 27566, 27555, 27550, 27568, 27559, + 27565, 27562, 27556, 27557, 27570, 27571, 27574, 27569, 27575, 27572, + 27594, 27604, 27599, 27593, 27603, 27598, 27592, 27602, 27576, 27600, + 27596, 27606, 27577, 27595, 27605, 27597, 27601, 27573, 35762, 35762, + 27584, 27578, 27580, 27583, 27581, 27585, 27607, 27590, 27588, 27591, + 27587, 27589, 27582, 27586, 27579, 35762, 20924, 20911, 20913, 20912, + 20914, 20923, 20921, 20926, 20906, 20904, 20903, 20915, 20916, 20917, + 20907, 20925, 20918, 20909, 20919, 20920, 20908, 20905, 20922, 20927, + 20910, 20931, 20929, 20928, 35762, 35762, 20930, 35762, 29886, 29891, + 29887, 29889, 29885, 29884, 29888, 29892, 29883, 29882, 29890, 35762, + 35762, 35762, 35762, 35762, 1125, 1115, 1126, 1142, 1124, 1112, 1121, + 1118, 1122, 1120, 1143, 1117, 1128, 1114, 1116, 1127, 1113, 1119, 1123, + 2369, 2370, 2372, 1522, 2265, 2258, 1391, 1262, 1479, 1477, 1327, 2386, + 35762, 2254, 2256, 35762, 35762, 35762, 35762, 35762, 35762, 2311, 2332, + 2331, 2334, 2101, 2349, 1064, 1084, 1156, 1163, 1302, 1476, 1229, 1411, + 1347, 1360, 1576, 1578, 1432, 1550, 1444, 1358, 1184, 1446, 1242, 1473, + 1599, 1103, 1315, 1412, 1154, 1399, 1502, 1421, 1577, 1099, 1097, 1100, + 1400, 1503, 1524, 1485, 1329, 1248, 1098, 1304, 1303, 1349, 1259, 2291, + 2294, 2322, 2317, 2326, 1095, 1094, 2348, 1096, 1093, 2337, 2312, 2308, + 2329, 2328, 2305, 2330, 2313, 2315, 2314, 2316, 2319, 2318, 2295, 2306, + 1067, 2381, 1052, 1050, 1054, 1053, 1051, 1055, 2375, 2377, 2379, 2374, + 2376, 2378, 2252, 2251, 2250, 2320, 1076, 1075, 1088, 1606, 2261, 1605, + 2263, 1065, 1066, 2262, 1060, 2104, 10466, 10454, 10468, 10473, 10389, + 10363, 10364, 10433, 10434, 10412, 10413, 10428, 10430, 10371, 10390, + 10441, 10365, 10372, 10391, 10395, 10366, 10406, 10405, 10384, 10382, + 10418, 10369, 10373, 10403, 10401, 10419, 10425, 10424, 10377, 10376, + 10417, 10427, 10426, 10379, 10378, 10420, 10416, 10436, 10435, 10400, + 10399, 10387, 10411, 10409, 10408, 10423, 10422, 10421, 10432, 10392, + 10393, 10394, 10386, 10486, 10485, 10470, 10467, 10476, 10498, 10499, + 10488, 10489, 10494, 10495, 10482, 10492, 10500, 10477, 10483, 10493, + 10484, 10478, 10472, 10487, 10479, 10514, 10475, 10474, 10358, 10355, + 10481, 10491, 10490, 10440, 10404, 10381, 10438, 10374, 10407, 10439, + 10410, 10429, 10431, 10496, 10497, 10502, 10501, 10509, 10511, 10508, + 10507, 10504, 10503, 10506, 10505, 10512, 10510, 10356, 10471, 10370, + 10397, 10396, 10367, 10415, 10414, 10388, 10437, 10385, 10383, 10402, + 10380, 10375, 10398, 3530, 3599, 3598, 3602, 35762, 3553, 3554, 3567, + 3568, 3565, 3566, 3547, 3549, 35762, 35762, 3589, 3555, 35762, 35762, + 3590, 3556, 3540, 3537, 3581, 3580, 3569, 3579, 3578, 3583, 3582, 3571, + 3562, 3561, 3558, 3557, 3570, 3564, 3563, 3560, 3559, 3572, 35762, 3585, + 3584, 3577, 3576, 3588, 3552, 3541, 35762, 3587, 35762, 35762, 35762, + 3573, 3574, 3575, 3586, 35762, 35762, 3600, 3597, 3604, 3613, 3614, 3611, + 3612, 3607, 3608, 35762, 35762, 3615, 3605, 35762, 35762, 3616, 3606, + 3601, 3538, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 3528, + 35762, 35762, 35762, 35762, 3545, 3544, 35762, 3551, 3548, 3550, 3609, + 3610, 35762, 35762, 3623, 3625, 3622, 3621, 3618, 3617, 3620, 3619, 3626, + 3624, 3543, 3542, 3592, 3591, 3531, 3535, 3534, 3533, 3532, 3536, 3603, + 3627, 3546, 3529, 3596, 35762, 35762, 14491, 14492, 14497, 35762, 14445, + 14446, 14459, 14460, 14457, 14458, 35762, 35762, 35762, 35762, 14478, + 14447, 35762, 35762, 14477, 14448, 14442, 14441, 14439, 14438, 14463, + 14470, 14469, 14472, 14471, 14465, 14454, 14453, 14450, 14449, 14464, + 14456, 14455, 14452, 14451, 14466, 35762, 14474, 14473, 14468, 14467, + 14481, 14483, 14444, 35762, 14462, 14461, 35762, 14482, 14475, 35762, + 14476, 14480, 35762, 35762, 14494, 35762, 14498, 14503, 14504, 14501, + 14502, 35762, 35762, 35762, 35762, 14506, 14499, 35762, 35762, 14505, + 14500, 14496, 35762, 35762, 35762, 14493, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 14440, 14437, 14484, 14443, 35762, 14479, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 14516, 14518, 14515, 14514, + 14511, 14510, 14513, 14512, 14519, 14517, 14507, 14436, 14508, 14520, + 14509, 14495, 14435, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 14331, 14338, 14341, 35762, 14281, 14282, 14300, + 14301, 14298, 14299, 14293, 14295, 14357, 35762, 14328, 14283, 14358, + 35762, 14329, 14284, 14321, 14320, 14317, 14316, 14305, 14315, 14314, + 14319, 14318, 14307, 14290, 14289, 14286, 14285, 14306, 14292, 14291, + 14288, 14287, 14308, 35762, 14323, 14322, 14313, 14312, 14325, 14327, + 14326, 35762, 14303, 14302, 35762, 14297, 14309, 14310, 14311, 14324, + 35762, 35762, 14339, 14337, 14344, 14353, 14354, 14351, 14352, 14347, + 14348, 14342, 35762, 14355, 14345, 14343, 35762, 14356, 14346, 14340, + 35762, 35762, 14371, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 14294, 14296, + 14349, 14350, 35762, 35762, 14367, 14369, 14366, 14365, 14362, 14361, + 14364, 14363, 14370, 14368, 14359, 14360, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 14304, 14336, 14335, 14332, 14334, 14330, 14333, + 35762, 25865, 25864, 25869, 35762, 25814, 25815, 25833, 25834, 25831, + 25832, 25826, 25828, 35762, 35762, 25859, 25816, 35762, 35762, 25860, + 25817, 25853, 25852, 25849, 25848, 25837, 25847, 25846, 25851, 25850, + 25839, 25823, 25822, 25819, 25818, 25838, 25825, 25824, 25821, 25820, + 25840, 35762, 25855, 25854, 25845, 25844, 25857, 25813, 25811, 35762, + 25836, 25835, 35762, 25830, 25841, 25842, 25843, 25856, 35762, 35762, + 25866, 25863, 25870, 25879, 25880, 25877, 25878, 25873, 25874, 35762, + 35762, 25881, 25871, 35762, 35762, 25882, 25872, 25868, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 25867, 25800, 25801, 35762, 35762, + 35762, 35762, 25810, 25809, 35762, 25812, 25827, 25829, 25875, 25876, + 35762, 35762, 25889, 25891, 25888, 25887, 25884, 25883, 25886, 25885, + 25892, 25890, 25808, 25858, 25805, 25804, 25807, 25802, 25803, 25806, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 30505, 30522, 35762, 30473, 30474, 30481, 30482, 30477, 30478, 35762, + 35762, 35762, 30486, 30487, 30475, 35762, 30479, 30480, 30476, 30491, + 35762, 35762, 35762, 30463, 30488, 35762, 30490, 35762, 30464, 30466, + 35762, 35762, 35762, 30462, 30467, 35762, 35762, 35762, 30465, 30461, + 30493, 35762, 35762, 35762, 30492, 30495, 30472, 30471, 30470, 30469, + 30468, 30494, 30483, 30484, 30485, 30489, 35762, 35762, 35762, 35762, + 30792, 30799, 30800, 30795, 30796, 35762, 35762, 35762, 30801, 30802, + 30793, 35762, 30797, 30798, 30794, 30521, 35762, 35762, 30808, 35762, + 35762, 35762, 35762, 35762, 35762, 30397, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 30434, 30436, 30433, 30432, 30429, 30428, 30431, 30430, 30437, 30435, + 30499, 30497, 30498, 30427, 30807, 30806, 30426, 30424, 30396, 30502, + 30500, 35762, 35762, 35762, 35762, 35762, 31755, 31756, 31760, 31763, + 31754, 31718, 31719, 31731, 31732, 31727, 31728, 31722, 31724, 35762, + 31748, 31749, 31720, 35762, 31729, 31730, 31721, 31745, 31744, 31741, + 31740, 31707, 31739, 31738, 31743, 31742, 31709, 31714, 31713, 31698, + 31697, 31708, 31717, 31715, 31701, 31699, 31705, 35762, 31747, 31746, + 31737, 31736, 31751, 31752, 31712, 31711, 31704, 31703, 31702, 31726, + 31733, 31734, 31735, 31750, 35762, 35762, 31761, 31759, 31764, 31775, + 31776, 31771, 31772, 31767, 31768, 35762, 31777, 31778, 31765, 35762, + 31773, 31774, 31766, 31762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 31753, 31689, 35762, 31716, 31700, 31710, 35762, 35762, 31706, + 35762, 35762, 31723, 31725, 31769, 31770, 35762, 35762, 31785, 31787, + 31784, 31783, 31780, 31779, 31782, 31781, 31788, 31786, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 31757, 31696, 31694, 31692, 31690, + 31695, 31693, 31691, 31758, 16808, 16807, 16811, 16816, 16809, 16761, + 16762, 16782, 16783, 16778, 16779, 16773, 16775, 35762, 16799, 16800, + 16763, 35762, 16780, 16781, 16764, 16796, 16795, 16792, 16791, 16756, + 16790, 16789, 16794, 16793, 16758, 16770, 16769, 16766, 16765, 16757, + 16772, 16771, 16768, 16767, 16754, 35762, 16798, 16797, 16788, 16787, + 16803, 16804, 16760, 16759, 16753, 16752, 35762, 16777, 16784, 16785, + 16786, 16802, 35762, 35762, 16812, 16810, 16818, 16829, 16830, 16825, + 16826, 16821, 16822, 35762, 16831, 16832, 16819, 35762, 16827, 16828, + 16820, 16815, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 16805, + 16817, 35762, 35762, 35762, 35762, 35762, 35762, 16755, 16801, 35762, + 16774, 16776, 16823, 16824, 35762, 35762, 16839, 16841, 16838, 16837, + 16834, 16833, 16836, 16835, 16842, 16840, 35762, 16813, 16814, 16806, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 20866, 20868, 20873, 20871, 20823, 20797, 20799, 20843, + 20844, 20839, 20840, 20824, 20826, 35762, 20858, 20859, 20800, 35762, + 20841, 20842, 20801, 20855, 20854, 20851, 20850, 20831, 20812, 20811, + 20853, 20852, 20832, 20820, 20818, 20815, 20814, 20830, 20822, 20821, + 20817, 20816, 20833, 20829, 20857, 20856, 20849, 20848, 20861, 20862, + 20838, 20837, 20836, 20835, 20834, 20828, 20845, 20846, 20847, 20860, + 20819, 20869, 20867, 20872, 20875, 20886, 20887, 20882, 20883, 20878, + 20879, 35762, 20888, 20889, 20876, 35762, 20884, 20885, 20877, 20870, + 20813, 20874, 35762, 35762, 35762, 35762, 20809, 20810, 20804, 20772, + 20789, 20787, 20794, 20784, 20785, 20795, 20788, 20798, 20825, 20827, + 20880, 20881, 35762, 35762, 20780, 20782, 20779, 20778, 20775, 20774, + 20777, 20776, 20783, 20781, 20865, 20863, 20864, 20792, 20791, 20796, + 20786, 20790, 20793, 20773, 20806, 20805, 20807, 20802, 20803, 20808, + 35762, 28828, 28827, 28829, 35762, 28773, 28770, 28758, 28757, 28781, + 28780, 28783, 28782, 28779, 28778, 28777, 28776, 28775, 28774, 28771, + 28802, 28801, 28772, 35762, 35762, 35762, 28767, 28792, 28765, 28790, + 28815, 28805, 28764, 28789, 28766, 28791, 28812, 28813, 28806, 28759, + 28784, 28761, 28786, 28796, 28803, 28760, 28785, 28762, 28787, 28799, + 35762, 28804, 28768, 28793, 28763, 28788, 28794, 28769, 28811, 28809, + 35762, 28798, 35762, 35762, 28810, 28814, 28797, 28800, 28808, 28795, + 28807, 35762, 35762, 35762, 28826, 35762, 35762, 35762, 35762, 28846, + 28838, 28833, 28839, 28834, 28840, 35762, 28835, 35762, 28836, 28841, + 28832, 28845, 28842, 28843, 28844, 28837, 35762, 35762, 35762, 35762, + 35762, 35762, 28822, 28824, 28821, 28820, 28817, 28816, 28819, 28818, + 28825, 28823, 35762, 35762, 28830, 28831, 28847, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 31942, + 31939, 31937, 31936, 31938, 31940, 31956, 31925, 31927, 31926, 31985, + 31928, 31997, 31929, 31994, 31990, 31987, 31988, 31958, 31930, 31993, + 31992, 31989, 31991, 31959, 31924, 31965, 31962, 31931, 31963, 31932, + 31964, 31954, 31998, 31966, 31967, 31944, 31946, 31995, 31983, 31982, + 31984, 31935, 31943, 31999, 31934, 31960, 31968, 31948, 31971, 31973, + 31978, 31979, 31975, 31976, 31974, 31977, 31961, 35762, 35762, 35762, + 35762, 32000, 31980, 31972, 31981, 31970, 31969, 31945, 31953, 31952, + 31951, 31949, 31950, 31947, 31986, 31957, 31996, 31933, 32007, 32009, + 32006, 32005, 32002, 32001, 32004, 32003, 32010, 32008, 31955, 31941, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 18051, 18049, 35762, + 18050, 35762, 18064, 18079, 18083, 18063, 18073, 35762, 18065, 18080, + 18061, 18059, 18058, 18056, 18055, 18060, 18084, 18076, 18074, 18075, + 18057, 18081, 18082, 18069, 18067, 18046, 18068, 18045, 18062, 18085, + 18088, 18053, 35762, 18054, 35762, 18087, 18070, 18071, 18072, 18077, + 18066, 18089, 18078, 18115, 18097, 18102, 18098, 18100, 18110, 18111, + 18104, 18105, 18106, 18107, 18092, 18103, 18091, 18090, 35762, 35762, + 18108, 18109, 18112, 18101, 18099, 35762, 18113, 35762, 18096, 18093, + 18094, 18095, 18126, 18127, 18114, 35762, 18122, 18124, 18121, 18120, + 18117, 18116, 18119, 18118, 18125, 18123, 35762, 35762, 18042, 18041, + 18048, 18047, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 32233, 32140, 32138, 32139, 32148, 32136, + 32133, 32137, 32158, 32128, 32126, 32149, 32164, 32159, 32154, 32162, + 32153, 32157, 32156, 32132, 32141, 32124, 32123, 32051, 32052, 32050, + 32172, 32173, 32174, 32176, 32177, 32175, 32073, 32075, 32072, 32071, + 32068, 32067, 32070, 32069, 32076, 32074, 32065, 32062, 32061, 32058, + 32057, 32060, 32059, 32066, 32064, 32063, 32129, 32151, 32131, 32150, + 32134, 32161, 32142, 32143, 32144, 32145, 32183, 32169, 32082, 32080, + 32110, 32109, 32092, 32108, 32107, 32117, 35762, 32094, 32102, 32101, + 32087, 32086, 32093, 32104, 32103, 32091, 32090, 32095, 32112, 32111, + 32106, 32105, 32119, 32100, 32099, 32089, 32088, 32120, 32113, 32114, + 32115, 32121, 32084, 32118, 32096, 32097, 32098, 32116, 32122, 32079, + 32085, 32081, 32083, 35762, 35762, 35762, 35762, 32257, 32253, 32254, + 32249, 32250, 32245, 32246, 32247, 32248, 32255, 32256, 32251, 32252, + 32180, 32181, 32243, 32244, 32171, 32185, 32146, 32155, 32167, 32182, + 32168, 32170, 32165, 32166, 32184, 32232, 32231, 32230, 32197, 32196, + 32216, 32215, 32198, 32214, 32213, 32223, 35762, 32200, 32208, 32207, + 32190, 32189, 32199, 32210, 32209, 32194, 32193, 32201, 32218, 32217, + 32212, 32211, 32225, 32206, 32205, 32192, 32191, 32227, 32219, 32220, + 32221, 32228, 32226, 32224, 32202, 32203, 32204, 32222, 32229, 32195, + 32187, 32188, 32186, 35762, 32077, 32078, 32053, 32054, 32056, 32055, + 32234, 32241, 32239, 32242, 32240, 32235, 32238, 32237, 32236, 35762, + 32179, 32178, 32127, 32130, 32152, 32147, 32135, 27208, 19559, 27209, + 19560, 32163, 32160, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 23897, 23876, 23875, 23874, 23906, 23974, 23973, 23976, 23975, 23907, + 23904, 23952, 23951, 23958, 23957, 23905, 23936, 23953, 23960, 23959, + 23908, 23978, 23977, 23972, 23971, 23903, 23980, 23910, 23970, 23956, + 23935, 23979, 23969, 23866, 23930, 23967, 23968, 23965, 23966, 23869, + 23902, 23981, 23868, 24063, 24047, 24070, 24071, 24068, 24069, 24059, + 24044, 24052, 24053, 24060, 23988, 24007, 24012, 24011, 23987, 23861, + 23859, 23860, 23858, 23873, 24078, 24080, 24077, 24076, 24073, 24072, + 24075, 24074, 24081, 24079, 24010, 23999, 24017, 24021, 24016, 24020, + 23911, 23934, 23961, 23962, 23963, 23964, 24064, 24065, 24066, 24067, + 23901, 23900, 23898, 23899, 23864, 23863, 23862, 23933, 24054, 24032, + 24033, 23955, 23954, 24061, 24062, 24002, 24003, 24004, 24005, 24006, + 23872, 23871, 23870, 24048, 24050, 24051, 24049, 23925, 23924, 23923, + 23921, 23929, 23913, 23926, 23914, 23916, 23927, 23919, 23917, 23928, + 23865, 24058, 24055, 24056, 24057, 23994, 23995, 23996, 23997, 23992, + 23993, 23991, 23909, 24008, 24028, 24030, 24027, 24026, 24023, 24022, + 24025, 24024, 24031, 24029, 23989, 23990, 24045, 24046, 24019, 24018, + 13332, 13358, 13343, 13364, 13365, 13363, 13353, 13354, 13366, 13347, + 13356, 13359, 13361, 13367, 13349, 13352, 13357, 13351, 13355, 13368, + 13348, 13346, 13342, 13362, 13350, 13338, 13341, 13345, 13340, 13339, + 13360, 13344, 13333, 13337, 13335, 13370, 13334, 13336, 35762, 13369, + 35762, 35762, 35762, 35762, 35762, 13331, 35762, 35762, 13415, 13446, + 13423, 13452, 13421, 13451, 13444, 13441, 13453, 13433, 13435, 13447, + 13449, 13454, 13437, 13443, 13445, 13439, 13442, 13412, 13436, 13432, + 13422, 13450, 13438, 13416, 13419, 13431, 13418, 13417, 13448, 13430, + 13426, 13429, 13427, 13456, 13424, 13428, 13457, 13455, 13420, 13440, + 13414, 13504, 23112, 13413, 13425, 13434, 14693, 14767, 14701, 14772, + 14765, 14729, 14696, 14711, 14769, 14743, 14761, 14675, 14673, 14759, + 14660, 14695, 14779, 14708, 14782, 14703, 14768, 14705, 14704, 14776, + 14739, 14763, 14742, 14688, 14698, 14692, 14721, 14726, 14725, 14712, + 14716, 14714, 14717, 14718, 14715, 14723, 14722, 14724, 14719, 14690, + 14691, 14750, 14756, 14755, 14748, 14753, 14744, 14745, 14747, 14758, + 14752, 14751, 14749, 14754, 14746, 14757, 14665, 14664, 14670, 14669, + 14728, 14685, 14684, 14682, 14677, 14687, 14678, 14771, 14681, 14680, + 14683, 14676, 14780, 14674, 14667, 14663, 14672, 14668, 14661, 14662, + 14666, 14671, 14709, 14689, 14770, 14781, 14694, 14707, 14702, 14706, + 14773, 14784, 15022, 14928, 14938, 14986, 14990, 14940, 14939, 14992, + 14991, 14967, 15019, 15020, 14977, 14998, 14978, 15018, 15017, 15021, + 15007, 14944, 14996, 14951, 14936, 14937, 14988, 14987, 14942, 14943, + 14941, 14994, 14995, 14975, 14974, 14970, 14968, 14976, 14999, 15000, + 15001, 15006, 15005, 14983, 14984, 14982, 14979, 14985, 15012, 15011, + 15010, 15009, 15008, 15016, 15014, 14950, 14947, 14997, 14952, 14954, + 14961, 14965, 14963, 14953, 14929, 14931, 14934, 14933, 14966, 14935, + 14989, 14993, 14972, 14973, 14804, 14905, 14807, 14827, 14830, 14834, + 14909, 14855, 14856, 14861, 14865, 14874, 14877, 14870, 14882, 14814, + 14844, 14847, 14883, 14900, 14796, 14787, 14790, 14813, 14918, 14840, + 14791, 14806, 14808, 14833, 14832, 14836, 14835, 14831, 14916, 14910, + 14858, 14881, 14875, 14876, 14895, 14862, 14864, 14869, 14868, 14859, + 14873, 14871, 14860, 14878, 14824, 14821, 14815, 14820, 14819, 14817, + 14822, 14826, 14803, 14845, 14849, 14854, 14802, 14885, 14893, 14886, + 14889, 14837, 14798, 14799, 14908, 14797, 14919, 14923, 14926, 14842, + 14801, 14794, 14792, 14793, 14795, 14927, 14810, 14811, 14809, 14805, + 14812, 14906, 12703, 12710, 12709, 12704, 12708, 12707, 12705, 12706, + 12930, 12938, 12937, 12931, 12935, 12934, 12932, 12936, 12696, 12702, + 12700, 12697, 12699, 12698, 12701, 12687, 12747, 12755, 12754, 12748, + 12752, 12751, 12749, 12745, 12859, 12866, 12864, 12860, 12862, 12861, + 12865, 12863, 12834, 12843, 12842, 12835, 12839, 12838, 12836, 12840, + 12874, 12880, 12879, 12875, 12849, 12844, 12876, 12878, 12850, 12858, + 12857, 12851, 12855, 12854, 12852, 12856, 12826, 12833, 12832, 12827, + 12831, 12830, 12828, 12829, 12814, 35762, 12818, 12815, 12817, 12816, + 35762, 35762, 12807, 12813, 12811, 12808, 12810, 12809, 12812, 35762, + 12802, 35762, 12806, 12803, 12805, 12804, 35762, 35762, 12537, 12544, + 12543, 12538, 12542, 12541, 12539, 12528, 12999, 13006, 13004, 13000, + 13002, 13001, 13005, 13003, 12912, 12920, 12919, 12913, 12917, 12916, + 12914, 12918, 12575, 12583, 12582, 12576, 12580, 12579, 12577, 12581, + 12967, 12974, 12973, 12968, 12972, 12971, 12969, 12970, 12955, 35762, + 12959, 12956, 12958, 12957, 35762, 35762, 12765, 12773, 12772, 12766, + 12770, 12769, 12767, 12771, 12756, 12764, 12763, 12757, 12761, 12760, + 12758, 12762, 12657, 12665, 12664, 12658, 12662, 12661, 12659, 12663, + 12735, 12742, 12741, 12736, 12740, 12739, 12737, 12738, 12723, 35762, + 12727, 12724, 12726, 12725, 35762, 35762, 12716, 12722, 12720, 12717, + 12719, 12718, 12721, 35762, 12711, 35762, 12715, 12712, 12714, 12713, + 35762, 35762, 12939, 12946, 12945, 12940, 12944, 12943, 12941, 12942, + 12775, 12781, 12779, 12776, 12778, 12777, 12780, 35762, 12990, 12998, + 12997, 12991, 12995, 12994, 12992, 12996, 12975, 12982, 12980, 12976, + 12978, 12977, 12981, 12979, 12947, 12954, 12953, 12948, 12952, 12951, + 12949, 12950, 12605, 12613, 12612, 12606, 12610, 12609, 12607, 12611, + 12590, 12598, 12597, 12591, 12595, 12594, 12592, 12596, 12921, 12929, + 12928, 12922, 12926, 12925, 12923, 12927, 12678, 12626, 12684, 12679, + 12683, 12682, 12680, 12681, 12666, 35762, 12670, 12667, 12669, 12668, + 35762, 35762, 12650, 12656, 12654, 12651, 12653, 12652, 12655, 12646, + 12881, 12889, 12888, 12882, 12886, 12885, 12883, 12887, 12566, 12574, + 12573, 12567, 12571, 12570, 12568, 12572, 12774, 12789, 12788, 12782, + 12786, 12785, 12783, 12787, 12904, 12911, 12909, 12905, 12907, 12906, + 12910, 12908, 12896, 12903, 12902, 12897, 12901, 12900, 12898, 12899, + 12618, 12625, 12623, 12619, 12621, 12620, 12624, 12616, 12794, 12801, + 12800, 12795, 12799, 12798, 12796, 12792, 12841, 12753, 12622, 35762, + 35762, 12506, 12508, 12507, 12525, 13028, 13026, 12509, 12524, 12510, + 12523, 13027, 12522, 13024, 13022, 13021, 13018, 13017, 13020, 13019, + 13025, 13023, 12511, 12514, 12513, 12518, 12517, 12521, 12520, 12516, + 12519, 12515, 12512, 35762, 35762, 35762, 12847, 12746, 12744, 12743, + 12845, 12529, 12527, 12526, 12846, 12617, 12615, 12614, 12848, 12793, + 12791, 12790, 13016, 13007, 13013, 13014, 13009, 13011, 13015, 13010, + 13008, 13012, 35762, 35762, 35762, 35762, 35762, 35762, 6081, 6082, 6083, + 6084, 6085, 6086, 6044, 6080, 6045, 6046, 6047, 6048, 6049, 6009, 6010, + 6011, 6012, 6013, 6014, 6050, 6051, 6052, 6053, 6054, 6055, 6056, 6057, + 6058, 6059, 6060, 6015, 6008, 6016, 6017, 6018, 6019, 6020, 6021, 6062, + 6063, 6064, 6065, 6066, 6067, 6023, 6022, 6024, 6025, 6026, 6027, 6028, + 6002, 6041, 6003, 6042, 6004, 6043, 6005, 6006, 6007, 6001, 6029, 6030, + 6031, 6032, 6033, 6034, 6035, 6036, 6037, 6038, 6039, 6040, 6068, 6069, + 6070, 6071, 6072, 6073, 6074, 6075, 6076, 6077, 6078, 6079, 6061, 35762, + 35762, 6161, 6162, 6163, 6164, 6165, 6147, 35762, 35762, 5223, 5195, + 4968, 5225, 5226, 5375, 5389, 5672, 5179, 5039, 4966, 4967, 5549, 5639, + 5659, 5637, 5660, 5638, 5641, 5635, 5642, 5636, 5304, 5656, 5633, 5657, + 5634, 5305, 4970, 5673, 5691, 5212, 5211, 5213, 5214, 5206, 5207, 5204, + 5203, 5216, 5210, 5215, 5205, 5197, 5227, 5388, 4974, 5409, 5402, 5407, + 5408, 5404, 5405, 5663, 5037, 5038, 5400, 5401, 5399, 5578, 5397, 5576, + 5398, 5577, 5392, 5574, 5393, 5575, 5395, 5572, 5396, 5573, 5662, 5391, + 5571, 5030, 5548, 5531, 5546, 5547, 5544, 5545, 5670, 5001, 5014, 5529, + 5530, 5539, 5631, 5537, 5629, 5538, 5630, 5535, 5627, 5536, 5628, 5533, + 5625, 5534, 5626, 5310, 5491, 5526, 5527, 5528, 5525, 5246, 5240, 5244, + 5245, 5242, 5243, 5665, 5238, 5239, 5237, 5623, 5235, 5621, 5236, 5622, + 5233, 5619, 5234, 5620, 5230, 5617, 5231, 5618, 5307, 5228, 5229, 5471, + 5472, 5473, 5470, 5194, 5181, 5192, 5193, 5190, 5191, 5664, 4998, 5180, + 5188, 5616, 5186, 5614, 5187, 5615, 5184, 5612, 5185, 5613, 5182, 5610, + 5183, 5611, 5306, 4997, 5447, 5272, 5280, 5289, 5290, 5275, 5276, 5667, + 5278, 5279, 5288, 5570, 5286, 5568, 5287, 5569, 5284, 5566, 5285, 5567, + 5282, 5564, 5283, 5565, 5308, 5271, 5563, 5291, 4972, 5448, 5364, 5325, + 5362, 5363, 5352, 5353, 5668, 5296, 5324, 5361, 5589, 5355, 5587, 5356, + 5588, 5309, 5292, 5070, 5365, 5270, 5257, 5268, 5269, 5266, 5267, 5666, + 5255, 5256, 5265, 5557, 5263, 5555, 5264, 5556, 5261, 5553, 5262, 5554, + 5259, 5551, 5260, 5552, 5247, 5550, 5273, 5490, 5450, 5488, 5489, 5469, + 5474, 5669, 5430, 5449, 5483, 5609, 5481, 5607, 5482, 5608, 5479, 5605, + 5480, 5606, 5477, 5603, 5478, 5604, 5302, 5429, 4973, 5476, 4993, 5277, + 5297, 5303, 5300, 5301, 5298, 5299, 5468, 5466, 5467, 5460, 5461, 5463, + 5464, 5459, 5602, 5457, 5600, 5458, 5601, 5452, 5598, 5453, 5599, 5455, + 5596, 5456, 5597, 5451, 5690, 5676, 5688, 5689, 5678, 5679, 5671, 5674, + 5675, 5687, 5586, 5685, 5584, 5686, 5585, 5683, 5582, 5684, 5583, 5681, + 5580, 5682, 5581, 5311, 5661, 4994, 5579, 5446, 5428, 5412, 5562, 5422, + 5426, 5427, 5424, 5425, 5560, 5420, 5421, 5558, 5414, 5591, 5410, 5590, + 5274, 5222, 5201, 5202, 5217, 5219, 5220, 5199, 5200, 5221, 5632, 5198, + 5510, 5295, 5508, 5293, 5509, 5294, 5506, 5507, 5504, 5505, 5502, 5624, + 5492, 5523, 5524, 5520, 5518, 5517, 5541, 5542, 5543, 5540, 5350, 5348, + 5349, 5346, 5347, 5344, 5345, 5343, 5351, 5224, 5369, 5373, 5374, 5371, + 5372, 5367, 5368, 5366, 5515, 5516, 5511, 5514, 5593, 5594, 5595, 5592, + 5330, 5334, 5335, 5332, 5333, 5328, 5329, 5327, 5336, 5444, 5445, 5440, + 5443, 5652, 5653, 5654, 5651, 5643, 5253, 5254, 5251, 5252, 5249, 5250, + 5248, 5500, 5498, 5499, 5496, 5497, 5494, 5495, 5493, 4971, 4990, 4991, + 4992, 4989, 4978, 4979, 4980, 4977, 4986, 4987, 4988, 4985, 4982, 4983, + 4984, 4981, 5435, 5436, 5432, 5434, 5020, 5019, 5015, 5016, 5018, 5017, + 5166, 5165, 5161, 5162, 5164, 5163, 5172, 5171, 5167, 5168, 5170, 5169, + 5036, 5035, 5031, 5032, 5034, 5033, 5130, 5129, 5125, 5126, 5128, 5127, + 5124, 5123, 5119, 5120, 5122, 5121, 5093, 5092, 5088, 5089, 5091, 5090, + 5087, 5029, 5028, 5025, 5026, 5027, 5023, 5066, 5065, 5061, 5062, 5064, + 5063, 5060, 5059, 5055, 5056, 5058, 5057, 5054, 5073, 5072, 5067, 5068, + 5071, 5069, 5160, 5159, 5155, 5156, 5158, 5157, 5178, 5177, 5173, 5174, + 5176, 5175, 5053, 5437, 5052, 5047, 5048, 5051, 5439, 5050, 5046, 5045, + 5041, 5042, 5044, 5043, 5148, 5147, 5143, 5144, 5146, 5145, 5007, 5006, + 5002, 5003, 5005, 5004, 5142, 5141, 5137, 5138, 5140, 5139, 5106, 5105, + 5101, 5102, 5104, 5103, 5112, 5111, 5107, 5108, 5110, 5109, 5100, 5099, + 5095, 5096, 5098, 5097, 5094, 5040, 5013, 5012, 5008, 5009, 5011, 5010, + 5086, 5085, 5081, 5082, 5084, 5083, 5080, 5079, 5075, 5076, 5078, 5077, + 5074, 5136, 5135, 5131, 5132, 5134, 5133, 5154, 5153, 5149, 5150, 5152, + 5151, 5118, 5117, 5113, 5114, 5116, 5115, 5189, 5218, 5370, 5331, 5341, + 5342, 5339, 5340, 5337, 5338, 5650, 5648, 5649, 5646, 5647, 5644, 5645, + 5655, 4976, 25265, 25240, 25251, 25247, 25257, 25254, 25260, 25263, + 25264, 25243, 25242, 25262, 25248, 25253, 25258, 25252, 25239, 25255, + 25261, 25245, 25249, 25244, 25256, 25259, 25250, 25246, 25241, 25237, + 25238, 35762, 35762, 35762, 27467, 27523, 27517, 27521, 27520, 27515, + 27513, 27460, 27445, 27491, 27444, 27443, 27488, 27503, 27490, 27494, + 27495, 27497, 27483, 27449, 27482, 27468, 27461, 27469, 27471, 27516, + 27473, 27472, 27486, 27500, 27512, 27502, 27454, 27476, 27457, 27480, + 27470, 27485, 27506, 27477, 27519, 27446, 27509, 27508, 27504, 27447, + 27525, 27514, 27505, 27452, 27511, 27499, 27455, 27493, 27458, 27518, + 27487, 27501, 27484, 27453, 27475, 27474, 27456, 27492, 27459, 27479, + 27451, 27450, 27448, 27510, 27489, 27507, 27478, 27522, 27524, 27526, + 27527, 27442, 27528, 27529, 27441, 27481, 27498, 27496, 27465, 27464, + 27466, 27463, 27462, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 30050, 30067, 30068, 30058, 30056, 30052, 30064, 30055, 30053, 30061, + 30054, 30060, 30066, 30062, 30059, 30065, 30063, 30057, 30071, 30072, + 30070, 30069, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 30051, 15194, 15195, 15196, 15185, 15183, 15179, 15191, 15182, + 15180, 15188, 15181, 15187, 15193, 15189, 15186, 15192, 15190, 15184, + 15198, 15199, 15197, 26633, 26634, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 4689, 4690, 4691, 4680, 4678, 4674, 4686, + 4677, 4675, 4683, 4676, 4682, 4688, 4684, 4681, 4687, 4685, 4679, 4692, + 4693, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 30086, 30087, 30088, 30078, 30077, 30073, 30083, + 30076, 30074, 30081, 30075, 30080, 30085, 35762, 30079, 30084, 30082, + 35762, 30089, 30090, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 17762, 17760, 17763, 17761, 17764, + 17758, 17756, 17759, 17757, 17766, 17780, 17776, 17781, 17777, 17765, + 17778, 17774, 17779, 17775, 17767, 17788, 17768, 17770, 17769, 17784, + 17787, 17785, 17783, 17786, 17772, 17771, 17773, 17789, 17782, 17790, + 17737, 17735, 17745, 17746, 17741, 17744, 17742, 17743, 17754, 17755, + 17752, 17753, 17747, 17736, 17740, 17739, 17738, 17857, 17856, 17858, + 17863, 17865, 17869, 17871, 17873, 17875, 17874, 17866, 17870, 17864, + 17876, 17860, 17861, 17868, 17862, 17811, 17805, 17810, 17812, 17807, + 17796, 17804, 17806, 17801, 17793, 17794, 17813, 17800, 17795, 17802, + 17797, 17799, 17808, 17798, 17809, 17803, 17734, 17791, 17792, 35762, + 35762, 17883, 17885, 17882, 17881, 17878, 17877, 17880, 17879, 17886, + 17884, 35762, 35762, 35762, 35762, 35762, 35762, 17835, 17834, 17831, + 17833, 17832, 17826, 17829, 17830, 17828, 17827, 35762, 35762, 35762, + 35762, 35762, 35762, 23479, 23491, 23487, 23336, 23486, 23337, 23484, + 23475, 23488, 23489, 23490, 23335, 23334, 23333, 23485, 23332, 23328, + 23330, 23327, 23326, 23323, 23322, 23325, 23324, 23331, 23329, 35762, + 35762, 35762, 35762, 35762, 35762, 23340, 23454, 23471, 23456, 23458, + 23457, 23459, 23455, 23465, 23368, 23460, 23466, 23467, 23463, 23372, + 23453, 23415, 23414, 23445, 23461, 23369, 23464, 23470, 23468, 23469, + 23462, 23451, 23450, 23444, 23448, 23449, 23447, 23452, 23446, 23371, + 23424, 23442, 23443, 23431, 23433, 23432, 23434, 23418, 23435, 23438, + 23439, 23427, 23437, 23426, 23420, 23429, 23422, 23425, 23441, 23440, + 23436, 23428, 23430, 23421, 23423, 23419, 23413, 23398, 23399, 23407, + 23406, 23403, 23411, 23394, 23396, 23412, 23401, 23393, 23408, 23410, + 23409, 23395, 23397, 23392, 23405, 23402, 23400, 23404, 23391, 23389, + 23390, 23388, 23387, 23370, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 23342, 23344, 23346, 23353, 23352, 23360, 23356, 23341, 23351, + 23367, 23354, 23366, 23358, 23357, 23348, 23355, 23359, 23345, 23362, + 23361, 23365, 23363, 23364, 23343, 23417, 23416, 23380, 23385, 23376, + 23381, 23377, 23373, 23378, 23374, 23386, 23375, 23383, 23384, 23350, + 23349, 23379, 23347, 23382, 35762, 35762, 35762, 35762, 35762, 5390, + 4975, 4969, 5658, 5406, 5403, 5394, 5532, 5241, 5232, 5281, 5354, 5326, + 5258, 5475, 5431, 5462, 5465, 5454, 5680, 5677, 5423, 5359, 5379, 5360, + 5380, 5357, 5377, 5358, 5378, 5419, 5417, 5418, 5415, 5416, 5413, 5386, + 5387, 5384, 5383, 5385, 5376, 5381, 5382, 5196, 5640, 5209, 5208, 5411, + 5561, 5559, 5503, 5501, 5522, 5521, 5519, 5513, 5512, 5442, 5441, 5433, + 5022, 4999, 5024, 5021, 5438, 5049, 4995, 4996, 5000, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 19858, 19825, + 19824, 19805, 19804, 19811, 19819, 19818, 19823, 19822, 19810, 19808, + 19806, 19821, 19820, 19812, 19827, 19826, 19817, 19816, 19830, 19809, + 19831, 19829, 19832, 19813, 19814, 19815, 19828, 19803, 19807, 35762, + 19849, 19856, 19857, 19855, 19850, 19853, 19851, 19854, 19852, 19848, + 19846, 19847, 35762, 35762, 35762, 35762, 19840, 19837, 19839, 19845, + 19838, 19843, 19842, 19844, 19841, 19834, 19833, 19835, 35762, 35762, + 35762, 35762, 19836, 35762, 35762, 35762, 19859, 19860, 19867, 19869, + 19866, 19865, 19862, 19861, 19864, 19863, 19870, 19868, 30111, 30123, + 30106, 30103, 30121, 30124, 30105, 30104, 30118, 30113, 30112, 30119, + 30116, 30122, 30117, 30120, 30110, 30102, 30107, 30091, 30125, 30095, + 30096, 30114, 30109, 30108, 30115, 30094, 30092, 30093, 35762, 35762, + 30097, 30098, 30099, 30100, 30101, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 24411, 24433, 24393, 24395, + 24398, 24415, 24417, 24420, 24401, 24397, 24413, 24423, 24419, 24435, + 24402, 24400, 24399, 24424, 24422, 24421, 24404, 24403, 24410, 24426, + 24425, 24432, 24407, 24412, 24409, 24429, 24434, 24431, 24408, 24406, + 24405, 24430, 24428, 24427, 24392, 24394, 24414, 24416, 24396, 24418, + 35762, 35762, 35762, 35762, 24456, 24441, 24445, 24451, 24454, 24457, + 24443, 24447, 24448, 24452, 24444, 24442, 24455, 24450, 24449, 24453, + 24446, 24391, 24386, 24385, 24390, 24389, 24388, 24387, 24438, 24439, + 35762, 35762, 35762, 35762, 35762, 35762, 24464, 24466, 24463, 24462, + 24459, 24458, 24461, 24460, 24467, 24465, 24440, 35762, 35762, 35762, + 24436, 24437, 17836, 17855, 17848, 17851, 17853, 17846, 17844, 17842, + 17838, 17840, 17825, 17823, 17815, 17819, 17821, 17817, 17849, 17854, + 17847, 17850, 17852, 17845, 17843, 17841, 17837, 17839, 17824, 17822, + 17814, 17818, 17820, 17816, 4658, 4655, 4647, 4646, 4660, 4652, 4645, + 4644, 4663, 4654, 4651, 4650, 4653, 4657, 4649, 4648, 4665, 4661, 4659, + 4664, 4662, 4666, 4656, 4669, 4671, 4668, 4670, 4667, 35762, 35762, 4673, + 4672, 30159, 30157, 30158, 30175, 30174, 30173, 30199, 30165, 30164, + 30178, 30185, 30177, 30200, 30193, 30160, 30205, 30176, 30192, 30169, + 30168, 30182, 30181, 30201, 30204, 30167, 30166, 30170, 30180, 30183, + 30179, 30206, 30186, 30172, 30191, 30194, 30187, 30189, 30207, 30161, + 30162, 30163, 30171, 30190, 30208, 30184, 30197, 30198, 30195, 30196, + 30203, 30202, 30188, 30156, 30131, 30130, 30128, 30219, 30126, 30127, + 30129, 30132, 30133, 30134, 35762, 30227, 30234, 30238, 30235, 30244, + 30250, 30251, 30249, 30248, 30246, 30247, 30239, 30240, 30243, 30252, + 30236, 30242, 30237, 30245, 30241, 30218, 30230, 30231, 30211, 30212, + 30213, 30222, 30221, 30214, 35762, 35762, 30135, 30142, 30144, 30141, + 30140, 30137, 30136, 30139, 30138, 30145, 30143, 35762, 35762, 35762, + 35762, 35762, 35762, 30152, 30154, 30151, 30150, 30147, 30146, 30149, + 30148, 30155, 30153, 35762, 35762, 35762, 35762, 35762, 35762, 30228, + 30229, 30226, 30217, 30210, 30232, 30223, 30220, 30215, 30216, 30224, + 30225, 30209, 30233, 35762, 35762, 7898, 7866, 7982, 7900, 8132, 8145, + 8144, 8084, 7881, 8061, 8120, 8090, 7885, 8089, 8088, 8030, 8024, 8047, + 8106, 8048, 8107, 8118, 8077, 7981, 8093, 7884, 7883, 8130, 8008, 8009, + 8010, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 2698, 2697, 2700, 2696, 2699, 2608, 2609, 2625, 2626, 2629, 2630, 2647, + 2648, 2638, 2639, 2622, 2612, 2627, 2628, 2633, 2635, 2623, 2624, 2642, + 2615, 2616, 2631, 2632, 2643, 2654, 2653, 2619, 2618, 2641, 2652, 2655, + 2617, 2620, 2640, 2644, 2645, 2613, 2614, 2660, 2662, 2646, 2637, 2661, + 2650, 2651, 2649, 2659, 2701, 2712, 2715, 2716, 2706, 2707, 2704, 2705, + 2702, 2703, 2708, 2709, 2711, 2710, 2713, 2714, 2717, 2634, 2636, 2656, + 2621, 2657, 2658, 2610, 2611, 35762, 35762, 35762, 2725, 2727, 2724, + 2723, 2720, 2719, 2722, 2721, 2728, 2726, 2694, 2691, 2718, 2605, 2607, + 2606, 2693, 2680, 2678, 2681, 2672, 2673, 2679, 2675, 2677, 2676, 2674, + 2670, 2669, 2665, 2663, 2667, 2666, 2664, 2668, 2671, 2690, 2689, 2688, + 2687, 2682, 2684, 2685, 2686, 2683, 2695, 2692, 35762, 29705, 29703, + 29704, 29656, 29691, 29693, 29658, 29692, 29668, 29669, 29676, 29684, + 29679, 29670, 29677, 29681, 29690, 29671, 29685, 29678, 29672, 29683, + 29661, 29686, 29674, 29682, 29689, 29665, 29663, 29687, 29667, 29688, + 29680, 29651, 29652, 29653, 29711, 29710, 29712, 29709, 29707, 29708, + 29702, 29706, 29654, 29655, 29675, 29666, 29719, 29721, 29718, 29717, + 29714, 29713, 29716, 29715, 29722, 29720, 29650, 29664, 29662, 29673, + 29659, 29660, 3488, 3474, 3482, 3466, 3454, 3478, 3477, 3463, 3469, 3462, + 3455, 3486, 3472, 3464, 3481, 3465, 3483, 3480, 3485, 3470, 3453, 3468, + 3475, 3458, 3476, 3471, 3456, 3487, 3473, 3460, 3484, 3467, 3461, 3479, + 3459, 3457, 3489, 3490, 3497, 3503, 3500, 3504, 3505, 3501, 3506, 3502, + 3498, 3499, 3451, 3452, 3491, 3492, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 3496, 3494, 3495, 3493, 19688, 19687, 19686, 19700, + 19699, 19705, 19715, 19714, 19718, 19706, 19713, 19712, 19694, 19707, + 19691, 19690, 19689, 19698, 19697, 19696, 19695, 19704, 19703, 19709, + 19708, 19693, 19723, 19720, 19719, 19702, 19701, 19721, 19717, 19716, + 19722, 19724, 19733, 19732, 19738, 19740, 19736, 19737, 19734, 19735, + 19739, 19677, 19682, 19681, 19679, 19683, 19684, 19685, 19680, 19678, + 19731, 19730, 35762, 35762, 35762, 19725, 19728, 19729, 19727, 19726, + 19747, 19749, 19746, 19745, 19742, 19741, 19744, 19743, 19750, 19748, + 35762, 35762, 35762, 19711, 19710, 19692, 25311, 25313, 25310, 25309, + 25306, 25305, 25308, 25307, 25314, 25312, 25284, 25275, 25273, 25272, + 25274, 25285, 25269, 25268, 25270, 25271, 25287, 25283, 25281, 25280, + 25282, 25289, 25295, 25296, 25294, 25297, 25286, 25279, 25276, 25278, + 25277, 25288, 25290, 25291, 25293, 25292, 25299, 25300, 25298, 25304, + 25303, 25315, 25302, 25301, 10125, 10102, 10108, 10164, 10146, 10154, + 10144, 10145, 10163, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 13460, 13491, 13468, 13497, 13466, 13496, 13489, 13486, 13498, 13478, + 13480, 13492, 13494, 13499, 13482, 13488, 13490, 13484, 13487, 13500, + 13481, 13477, 13467, 13495, 13483, 13461, 13464, 13476, 13463, 13462, + 13493, 13475, 13471, 13474, 13472, 13502, 13469, 13473, 13503, 13501, + 13465, 13485, 13459, 35762, 35762, 13458, 13470, 13479, 29701, 29699, + 29700, 29698, 29697, 29696, 29695, 29694, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 33625, 33638, 33627, 33605, 33619, 33633, + 33634, 33635, 33620, 33636, 33623, 33631, 33626, 33624, 33632, 33630, + 33629, 33637, 33618, 33616, 33607, 33614, 33606, 33617, 33615, 33596, + 33597, 33599, 33600, 33612, 33610, 33611, 33609, 33598, 33602, 33608, + 33621, 33604, 33613, 33601, 33628, 33622, 33603, 35762, 35762, 35762, + 35762, 35762, 18684, 18685, 19290, 18681, 18686, 18687, 18658, 18657, + 19275, 19268, 18690, 18691, 18664, 18692, 18670, 18665, 18666, 19225, + 19226, 19227, 19270, 18668, 19262, 18784, 18694, 18671, 18679, 18674, + 18697, 19230, 19229, 19228, 18698, 18699, 18701, 18659, 18712, 18646, + 14004, 14007, 14003, 14006, 14002, 9995, 23018, 23019, 23009, 23010, + 23021, 23022, 23012, 23024, 23014, 23025, 23026, 23027, 23028, 23029, + 23030, 23013, 23016, 23017, 23031, 23011, 23033, 23034, 23036, 23167, + 23274, 23168, 23276, 23171, 23196, 23210, 23264, 23249, 23279, 23217, + 23287, 23298, 23227, 23214, 23247, 23250, 23271, 23173, 23251, 23266, + 23291, 23265, 23277, 23295, 23169, 23175, 23218, 23201, 23219, 23195, + 19431, 19439, 19441, 19442, 14213, 14209, 14212, 14211, 14210, 19351, + 18770, 18819, 18905, 19047, 19067, 19144, 19171, 19164, 19209, 19245, + 19413, 19297, 23085, 18976, 19255, 18714, 18983, 19140, 18715, 19350, + 18771, 18823, 18906, 18919, 19002, 19029, 19048, 19073, 19145, 19174, + 19210, 18892, 19358, 19385, 19414, 18733, 18759, 18822, 18882, 19133, + 19181, 19218, 18973, 19129, 18894, 19337, 18900, 23275, 23176, 23194, + 23212, 23258, 23215, 23202, 23263, 23286, 23229, 23230, 23177, 23179, + 23232, 23236, 23238, 23182, 23228, 23278, 23246, 23245, 23188, 23172, + 23252, 23262, 23211, 23267, 23293, 23294, 23190, 23297, 23288, 23207, + 23209, 23208, 23213, 23290, 7874, 7873, 8122, 8121, 8074, 7965, 8073, + 7758, 7964, 7757, 8022, 7770, 8075, 7897, 8086, 8113, 7983, 8137, 8138, + 8005, 7996, 7997, 7998, 8000, 8007, 8003, 8032, 7988, 8034, 8011, 7989, + 7990, 8036, 7991, 7992, 8021, 8025, 8013, 8040, 7995, 8027, 8028, 8026, + 8004, 8012, 8016, 8037, 8002, 8019, 8029, 7994, 8015, 8018, 8136, 7987, + 7986, 7869, 8142, 7872, 7864, 7878, 7767, 8042, 8097, 18174, 18731, + 18210, 18773, 18209, 18772, 18208, 18769, 18217, 18788, 18242, 18825, + 18241, 18824, 18240, 18820, 18236, 18814, 18237, 18815, 18268, 18868, + 18269, 18869, 18257, 18856, 18266, 18866, 18248, 18847, 18293, 18908, + 18301, 18918, 18320, 18938, 18319, 18937, 18317, 18935, 18314, 18932, + 18313, 18931, 18337, 18965, 18331, 18953, 18368, 19000, 18365, 18997, + 18369, 19001, 18376, 19014, 18377, 19015, 18387, 19024, 18383, 19011, + 18391, 19045, 18393, 19050, 18392, 19049, 18411, 19072, 18410, 19071, + 18405, 19064, 18401, 19059, 18442, 19108, 18441, 19107, 18419, 19100, + 18420, 19101, 18470, 19143, 18472, 19147, 18481, 19161, 18479, 19159, + 18480, 19160, 18486, 19166, 18506, 19204, 18504, 19202, 18503, 19195, + 18498, 19197, 18505, 19203, 18526, 19243, 18525, 19242, 18527, 19246, + 18521, 19236, 18557, 19318, 18578, 19341, 18550, 19311, 18577, 19340, + 18569, 19330, 18590, 19361, 18589, 19357, 18603, 19374, 18604, 19375, + 18600, 19371, 18602, 19373, 18601, 19372, 18609, 19380, 18608, 19379, + 18614, 19390, 18625, 19404, 18629, 19408, 18631, 19410, 18939, 19241, + 19376, 19400, 18732, 19038, 19037, 19039, 18515, 18829, 18168, 18725, + 18184, 18743, 18180, 18739, 18179, 18738, 18178, 18737, 18182, 18741, + 18181, 18740, 18163, 18720, 18162, 18719, 18161, 18718, 18165, 18722, + 18164, 18721, 18262, 18861, 18273, 18874, 18265, 18865, 18253, 18852, + 18252, 18851, 18251, 18850, 18256, 18855, 18255, 18854, 18338, 18966, + 18328, 18957, 18433, 19093, 18453, 19119, 18425, 19085, 18424, 19084, + 18423, 19083, 18427, 19087, 18426, 19086, 18450, 19116, 18449, 19115, + 18448, 19114, 18452, 19118, 18451, 19117, 18560, 19321, 18567, 19328, + 18564, 19325, 18563, 19324, 18562, 19323, 18566, 19327, 18565, 19326, + 18615, 19391, 18613, 19389, 18617, 19393, 18621, 19399, 18396, 19053, + 18397, 19054, 18618, 19394, 14051, 14043, 14056, 14048, 14052, 14044, + 14054, 14046, 13817, 13809, 13820, 13812, 13818, 13810, 13822, 13814, + 14074, 14071, 14076, 14073, 14075, 14072, 35762, 35762, 13857, 13854, + 13859, 13856, 13858, 13855, 35762, 35762, 14089, 14081, 14094, 14086, + 14090, 14082, 14092, 14084, 13841, 13833, 13844, 13836, 13842, 13834, + 13846, 13838, 14115, 14106, 14118, 14109, 14117, 14108, 14116, 14107, + 13869, 13864, 13872, 13867, 13871, 13866, 13870, 13865, 14176, 14173, + 14178, 14175, 14177, 14174, 35762, 35762, 13903, 13900, 13905, 13902, + 13904, 13901, 35762, 35762, 14135, 14126, 14138, 14129, 14137, 14128, + 14136, 14127, 35762, 13915, 35762, 13918, 35762, 13917, 35762, 13916, + 14156, 14148, 14161, 14153, 14157, 14149, 14159, 14151, 13887, 13879, + 13890, 13882, 13888, 13880, 13892, 13884, 14041, 14061, 14078, 14077, + 14101, 14099, 14121, 14122, 14180, 14179, 14141, 14142, 14168, 14166, + 35762, 35762, 14058, 14050, 14057, 14049, 14053, 14045, 14055, 14047, + 13824, 13816, 13821, 13813, 13819, 13811, 13823, 13815, 14096, 14088, + 14095, 14087, 14091, 14083, 14093, 14085, 13848, 13840, 13845, 13837, + 13843, 13835, 13847, 13839, 14163, 14155, 14162, 14154, 14158, 14150, + 14160, 14152, 13894, 13886, 13891, 13883, 13889, 13881, 13893, 13885, + 14040, 14065, 14042, 14063, 14062, 35762, 14059, 14060, 13826, 13830, + 13827, 13828, 13825, 14000, 14028, 14029, 14033, 13949, 14102, 14103, + 14100, 35762, 14097, 14098, 13861, 13860, 13851, 13850, 13849, 14032, + 14031, 14030, 14120, 14124, 14113, 14112, 35762, 35762, 14119, 14111, + 13873, 13877, 13874, 13875, 35762, 13957, 13956, 13955, 14140, 14144, + 14133, 14132, 14188, 14187, 14139, 14131, 13920, 13924, 13921, 13922, + 13910, 13951, 13950, 14227, 35762, 35762, 14169, 14170, 14167, 35762, + 14164, 14165, 13907, 13906, 13897, 13896, 13895, 14025, 13954, 35762, + 12447, 12444, 12449, 12446, 32044, 13184, 28853, 13117, 26923, 32017, + 14524, 35568, 35567, 35569, 19570, 27221, 15992, 24652, 13116, 12448, + 12445, 15946, 10941, 10915, 19515, 27171, 28728, 28726, 19475, 27145, + 10914, 10909, 10223, 10908, 4694, 32505, 25769, 32572, 15964, 15995, + 19876, 26269, 19569, 27220, 26798, 19568, 27219, 24257, 26502, 26503, + 26884, 10923, 32519, 27088, 27082, 27096, 5706, 28727, 28729, 27105, + 10945, 16335, 26084, 32621, 5992, 5707, 2513, 15994, 13188, 19523, 27182, + 10946, 26947, 13036, 32418, 27087, 3828, 3867, 20532, 27093, 7742, 32569, + 8148, 29770, 16351, 13152, 32024, 26943, 13177, 13139, 32573, 13178, + 10887, 32530, 33645, 22296, 34177, 13310, 16353, 16355, 16354, 35762, + 19567, 27218, 13132, 26797, 16249, 7, 16248, 6, 24252, 24650, 29741, + 29729, 35762, 35762, 29736, 29735, 29738, 29737, 29728, 29742, 29732, + 29733, 29727, 29731, 29734, 29730, 29615, 29617, 29614, 29613, 29610, + 29609, 29612, 29611, 29604, 29616, 29605, 29606, 29603, 29607, 29608, + 35762, 19428, 19429, 19437, 19443, 19427, 19430, 19433, 19434, 19435, + 19436, 19438, 19426, 19440, 35762, 35762, 35762, 13033, 7755, 8394, + 13194, 20484, 22903, 24185, 26526, 27538, 34181, 24384, 10881, 13034, + 18028, 32539, 11052, 13505, 26527, 14277, 2524, 16001, 5825, 20485, + 29183, 31790, 16239, 32540, 24700, 20985, 27407, 18155, 3742, 29165, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 8051, 8105, 8065, 8117, 7763, 7779, + 8044, 8102, 8110, 7778, 7762, 8124, 7910, 7901, 7904, 7907, 7902, 8054, + 7903, 7905, 7906, 8094, 7891, 7764, 8131, 8143, 8056, 8062, 8109, 8055, + 8043, 8101, 7766, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 0, 100, 10957, 10247, + 5829, 5708, 4959, 13035, 27726, 10249, 27723, 27715, 3917, 10958, 26688, + 26689, 27716, 3918, 27717, 27724, 20657, 10959, 24743, 29081, 27719, + 10955, 10960, 27720, 3919, 10961, 26860, 27066, 27750, 31685, 32492, + 33639, 10962, 26078, 26086, 16350, 3920, 32563, 17143, 951, 27712, 3916, + 12503, 27722, 27713, 27714, 32547, 27718, 27725, 346, 3633, 13508, 10236, + 16246, 27395, 13096, 10969, 10968, 10954, 10956, 10970, 32556, 32557, + 27092, 32558, 10967, 10963, 10964, 10965, 10966, 26888, 32542, 26504, + 2584, 32560, 29846, 33781, 33779, 33783, 33784, 33789, 33777, 33788, + 33787, 33775, 33782, 33774, 33776, 33785, 33773, 33790, 13189, 27365, + 27376, 27377, 27364, 27361, 27370, 27372, 27380, 27381, 27373, 27379, + 27375, 27358, 27366, 27362, 27368, 28915, 28919, 28920, 28914, 28911, + 28923, 28922, 28910, 28924, 28921, 28909, 28918, 28913, 28916, 28912, + 28917, 27369, 27363, 27374, 27378, 19187, 27371, 27360, 27359, 27367, + 33791, 32551, 32550, 35762, 35762, 35762, 35762, 19571, 32718, 27223, + 10989, 19497, 32643, 24682, 24656, 29055, 29069, 19591, 27245, 19654, + 27322, 19651, 32768, 27321, 11022, 19594, 27248, 19602, 32731, 27230, + 11003, 32644, 19600, 27254, 19587, 27241, 19505, 19500, 11026, 32728, + 32729, 10998, 10999, 27237, 10990, 960, 7726, 24684, 19582, 965, 7728, + 19620, 19614, 32745, 32742, 27282, 27276, 11039, 11036, 27256, 32720, + 19604, 19666, 32771, 27288, 11047, 19621, 27271, 19657, 19504, 27264, + 19655, 32735, 27262, 11029, 19502, 32646, 24694, 24668, 29066, 29078, + 19641, 27312, 19670, 27292, 32721, 10991, 19661, 32736, 27268, 11030, + 19581, 27236, 19652, 32772, 27323, 11024, 32773, 32775, 32776, 32777, + 32779, 32780, 27324, 24683, 29058, 32648, 27132, 11001, 32032, 19601, + 27255, 19499, 19585, 27239, 19498, 19665, 27287, 19507, 13172, 8153, + 26414, 32012, 32011, 12437, 16167, 24141, 12386, 24703, 28895, 8161, + 10707, 28888, 12451, 24100, 24088, 24092, 22907, 22914, 10882, 10689, + 27755, 2512, 27333, 4695, 29403, 8400, 13183, 26887, 16240, 27122, 947, + 22170, 29184, 10693, 10708, 26273, 24708, 20493, 20500, 16328, 32623, + 16313, 10912, 32529, 8167, 29763, 33769, 7729, 7720, 962, 32013, 3634, + 26977, 26886, 10883, 13038, 13330, 15982, 32322, 27094, 16347, 28848, + 34185, 24713, 22913, 2517, 24704, 1043, 1046, 24340, 351, 24705, 353, + 32520, 348, 12489, 13328, 10699, 1047, 13329, 1044, 16130, 7754, 12487, + 27331, 27332, 8346, 12504, 12490, 29565, 10252, 12473, 22181, 26949, + 24715, 16006, 24716, 29596, 19770, 13741, 19772, 13744, 19761, 13734, + 23857, 23856, 3632, 24714, 24718, 24717, 24345, 24342, 19769, 13740, + 24344, 24341, 19771, 13742, 24346, 24343, 26861, 29633, 26870, 29642, + 26869, 29641, 10710, 10713, 29621, 29749, 24701, 24702, 29627, 29755, + 24338, 24339, 29626, 29754, 23611, 23612, 23613, 29276, 29365, 29278, + 29367, 29214, 29221, 6503, 6449, 6508, 6241, 6254, 6504, 6230, 6513, + 6255, 29532, 29525, 29546, 29480, 27197, 19537, 10976, 32652, 2518, + 22922, 32536, 13173, 32523, 10939, 10712, 24712, 10715, 24337, 26871, + 29643, 24698, 8162, 24699, 8163, 25799, 16129, 23614, 15761, 16336, + 34206, 24186, 24655, 27128, 27193, 24097, 24098, 24099, 24093, 10529, + 10884, 29567, 10691, 4099, 19549, 27158, 19513, 27169, 27095, 9642, 9641, + 10933, 10932, 10911, 10936, 26682, 12474, 19775, 13750, 33682, 33681, + 19759, 13745, 12472, 12471, 12469, 12470, 10711, 10714, 24709, 24710, + 29277, 29366, 19760, 13733, 26868, 29640, 24706, 10705, 24707, 10706, + 33644, 22899, 32651, 10979, 12387, 12389, 28896, 12392, 12391, 28897, + 12390, 12388, 8164, 8165, 28889, 8166, 28890, 35480, 10530, 12384, 15976, + 32636, 10980, 26885, 26521, 33954, 19471, 27140, 19548, 27149, 4090, + 4087, 32441, 32438, 27085, 29309, 2508, 27736, 27732, 31683, 26806, + 33693, 26685, 32554, 33945, 15974, 32437, 32440, 4086, 4089, 32434, 4080, + 13198, 28954, 32637, 25791, 12500, 34190, 17145, 19564, 27213, 12499, + 3630, 10218, 349, 29856, 32456, 10700, 8172, 28880, 8348, 8349, 991, + 1029, 1015, 1003, 1004, 1020, 1001, 971, 976, 1026, 1031, 1017, 1016, + 1011, 1018, 999, 1023, 1012, 1019, 974, 983, 982, 1005, 1008, 984, 1037, + 1010, 1034, 980, 1009, 1007, 1035, 987, 1006, 1022, 981, 988, 997, 975, + 1036, 1021, 972, 1002, 1033, 978, 1027, 996, 973, 985, 998, 1039, 1038, + 977, 979, 1040, 1028, 1025, 1014, 1013, 986, 1032, 989, 1024, 994, 993, + 1030, 990, 995, 992, 24719, 27127, 27937, 3526, 33656, 16312, 8170, + 10615, 12443, 8152, 34095, 12465, 354, 15472, 6285, 6507, 4635, 32622, + 23495, 15998, 25787, 25788, 26426, 26427, 10610, 28971, 1000, 10244, + 26872, 24569, 26874, 7749, 19552, 19553, 19551, 27165, 27166, 27164, + 19520, 19527, 19519, 27179, 27186, 27178, 19469, 19467, 19468, 9644, + 27138, 27136, 27137, 16323, 15947, 32688, 32704, 29646, 29644, 32443, + 4081, 4082, 26958, 19555, 27199, 15955, 15956, 15957, 15958, 10263, + 10266, 10267, 10256, 10260, 10268, 10257, 10261, 10264, 10255, 10259, + 10254, 10258, 10262, 10265, 29244, 27067, 13061, 33653, 22739, 22731, + 22738, 22732, 22736, 22737, 22735, 22734, 22733, 11219, 13313, 32436, + 4085, 32429, 4084, 32444, 4092, 34104, 3631, 29592, 13145, 8, 12385, + 10245, 3856, 3821, 3900, 3804, 3857, 3822, 3859, 357, 29590, 32330, + 15975, 3840, 3843, 3845, 3837, 10937, 3879, 3751, 26820, 26817, 26818, + 26819, 25220, 29841, 29849, 29850, 29830, 29828, 29831, 29842, 29816, + 29817, 29835, 29837, 29836, 29834, 29818, 29847, 29848, 29820, 29824, + 29823, 29822, 29821, 29839, 29853, 29829, 29819, 29827, 29851, 29832, + 29833, 29844, 29843, 29845, 29854, 29825, 3924, 25774, 29840, 29826, + 29852, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 25232, 25227, 25230, 25231, + 25224, 25225, 25223, 25222, 25229, 25226, 25228, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 6251, 6248, 6247, + 6244, 6243, 6246, 6245, 6252, 6250, 6472, 6452, 6497, 6485, 6467, 6455, + 6471, 6469, 6451, 6498, 6486, 26360, 26358, 26357, 26354, 26353, 26356, + 26355, 26361, 26359, 26352, 26343, 26351, 26349, 26344, 26345, 26347, + 26348, 26342, 26346, 26350, 10550, 10562, 10559, 10544, 10541, 10556, + 10553, 10568, 10547, 24739, 24732, 24740, 24738, 24733, 24734, 24735, + 24737, 24731, 24742, 24741, 26388, 26389, 26390, 26391, 26392, 26393, + 26394, 26395, 26396, 26397, 26398, 26399, 26400, 26401, 26402, 26403, + 26404, 26405, 26406, 26407, 26408, 26409, 26410, 26411, 26412, 26413, + 6395, 6396, 6397, 6398, 6399, 6400, 6401, 6402, 6403, 6404, 6405, 6406, + 6407, 6408, 6409, 6410, 6411, 6412, 6413, 6414, 6415, 6416, 6417, 6418, + 6419, 6420, 6421, 6422, 6423, 6424, 6425, 6426, 6427, 6428, 6429, 6430, + 6431, 6432, 6433, 6434, 6435, 6436, 6437, 6438, 6439, 6440, 6441, 6442, + 6443, 6444, 6445, 6446, 6249, 24266, 24264, 24262, 24267, 24268, 24270, + 24271, 24265, 24269, 24263, 10903, 10901, 10900, 10897, 10896, 10899, + 10898, 10904, 10902, 10895, 24261, 4206, 4153, 4202, 4149, 4196, 4148, + 4195, 4147, 4194, 4146, 4193, 4145, 4190, 4123, 4117, 4144, 4189, 4121, + 4115, 4143, 4201, 4227, 4221, 4138, 4200, 4225, 4219, 4136, 4205, 4243, + 4220, 4116, 4240, 4122, 4226, 4152, 4204, 4242, 4218, 4114, 4239, 4120, + 4224, 4151, 4188, 4157, 4211, 4125, 4119, 4214, 4160, 4142, 4199, 4156, + 4210, 4228, 4222, 4213, 4159, 4137, 4203, 4158, 4212, 4241, 4217, 4118, + 4238, 4162, 4216, 4155, 4209, 4124, 4223, 4215, 4161, 4150, 4186, 4140, + 4185, 4139, 4113, 4109, 4130, 4127, 4105, 4129, 4126, 4104, 4233, 4230, + 4108, 4232, 4229, 4107, 4245, 4236, 4112, 4244, 4235, 4111, 4131, 4128, + 4103, 4234, 4231, 4106, 4246, 4237, 4110, 4164, 4163, 4165, 4166, 4182, + 4181, 4183, 4191, 4197, 4208, 4187, 4132, 4134, 4154, 4141, 4192, 4198, + 4133, 4135, 32667, 20583, 20582, 20585, 20538, 20581, 20586, 20584, + 13205, 19514, 19535, 19546, 19485, 19534, 19495, 19496, 27152, 19790, + 22298, 10230, 32691, 27161, 26940, 26941, 26932, 26933, 26934, 26935, + 26936, 26937, 26938, 26939, 3877, 34082, 34091, 34085, 29418, 29427, + 29417, 29424, 29426, 29416, 3875, 34079, 3871, 34073, 3908, 34115, 3853, + 34063, 3902, 34111, 3901, 34110, 3858, 34070, 3863, 34069, 3862, 34068, + 3806, 34028, 3805, 34027, 3826, 34054, 3825, 34053, 3824, 34052, 3796, + 34017, 34018, 13136, 20588, 34004, 10886, 6224, 4698, 3747, 6216, 6225, + 6217, 6222, 6221, 6223, 19483, 27150, 16343, 16341, 32670, 20536, 32689, + 32706, 20579, 20559, 32672, 20539, 3833, 3832, 3903, 3904, 33970, 29421, + 29428, 29423, 29420, 34094, 34112, 32659, 32660, 18152, 34092, 34088, + 34089, 34093, 34011, 34009, 34010, 34012, 32687, 32711, 20557, 34059, + 3850, 34058, 3849, 20564, 3881, 7743, 32616, 28961, 8155, 3890, 34101, + 19800, 32049, 29647, 2509, 10270, 8173, 25795, 3896, 34103, 2731, 2737, + 2738, 27545, 32618, 15970, 34076, 3888, 27911, 27090, 3831, 3869, 34051, + 34108, 34072, 34026, 28859, 5822, 26956, 3744, 4958, 970, 25895, 6179, + 8381, 8380, 29568, 13106, 102, 14650, 26492, 35478, 32508, 32509, 32514, + 32511, 32513, 32512, 32510, 32507, 33966, 34038, 34080, 3876, 34099, + 13129, 18156, 22729, 13112, 11215, 20893, 16465, 27615, 32781, 24571, + 26787, 2507, 31672, 13327, 5696, 19675, 33695, 20488, 27708, 27543, 5702, + 2585, 26680, 33976, 33992, 33995, 33971, 33979, 33989, 3767, 3783, 3786, + 3762, 3770, 3780, 3889, 34041, 34022, 3795, 34081, 3816, 3801, 34013, + 15971, 26945, 12340, 3512, 3513, 23616, 23615, 23617, 33964, 11220, + 32632, 26984, 26985, 26986, 26987, 26988, 26989, 26990, 26991, 3906, + 26983, 26419, 26524, 33967, 10532, 10533, 10534, 10535, 10536, 10537, + 34006, 34008, 3748, 3750, 23492, 23493, 10572, 10575, 10574, 10573, + 34032, 3812, 14651, 968, 8389, 29561, 27703, 345, 13151, 13323, 29562, + 2520, 13149, 26075, 32026, 32025, 33939, 15829, 10972, 10973, 16327, + 20892, 20891, 20890, 33657, 15965, 22307, 22284, 22297, 21059, 10694, + 32634, 8372, 13311, 24381, 5832, 26228, 16466, 33685, 6182, 3851, 27758, + 27748, 26951, 27752, 28966, 3449, 29494, 34029, 34030, 3809, 3810, 28962, + 29649, 26961, 3883, 32048, 32546, 32545, 34023, 8390, 10614, 25794, + 26665, 5764, 15471, 6237, 5833, 24643, 355, 3897, 34106, 3829, 34049, + 11061, 15328, 19472, 29537, 13100, 3894, 27063, 27064, 2516, 15256, + 26499, 27211, 19562, 16348, 3760, 27916, 6214, 5824, 15934, 13324, 13325, + 20988, 23510, 32617, 13185, 13146, 13114, 27699, 29243, 28857, 16005, + 26511, 31791, 16363, 15232, 13312, 9637, 34033, 3884, 32665, 3887, 20580, + 34074, 34042, 31684, 31671, 226, 12462, 26972, 26966, 33687, 34188, + 20578, 26501, 32705, 34062, 3914, 5998, 15254, 23610, 15290, 2741, 15246, + 26077, 15336, 25778, 15292, 18638, 27761, 26074, 20894, 29566, 13181, + 13179, 15275, 13175, 3813, 34037, 29173, 29594, 6510, 25776, 3761, 26076, + 15294, 26677, 27763, 15245, 25777, 12339, 12336, 12334, 28851, 12335, + 15268, 32567, 28854, 31677, 25775, 15320, 28849, 3811, 34034, 12337, + 6499, 15319, 28964, 32320, 15253, 29172, 15313, 2730, 12338, 15270, 8386, + 27762, 24329, 20577, 32703, 20562, 32708, 3915, 34066, 34031, 3798, + 15272, 19797, 22304, 15335, 15303, 15304, 15264, 15265, 15287, 15286, + 9649, 15273, 15279, 15249, 27392, 13150, 27391, 22291, 22294, 22285, + 22286, 22292, 22295, 15283, 15296, 15282, 15295, 19789, 19787, 22290, + 22293, 10597, 10595, 10594, 10591, 10590, 10593, 10592, 10598, 10596, + 10589, 10608, 10605, 10604, 10601, 10600, 10603, 10602, 10609, 10607, + 10599, 10587, 10584, 10583, 10580, 10579, 10582, 10581, 10588, 10586, + 10578, 15331, 15334, 15291, 15261, 15309, 15297, 15316, 11053, 15300, + 32502, 15322, 10233, 15260, 3864, 32040, 32043, 3865, 15247, 15248, + 29555, 15259, 27216, 19557, 2597, 13196, 15288, 15327, 24721, 9643, + 24723, 6286, 34117, 3921, 3923, 3922, 15250, 15252, 15251, 31678, 15321, + 33960, 15332, 25789, 10905, 32023, 34105, 26505, 25785, 25784, 19512, + 27168, 25896, 27074, 29760, 33643, 21756, 20508, 21577, 29522, 29523, + 34021, 969, 12394, 20576, 32684, 19494, 27159, 13204, 18144, 18143, + 19453, 19452, 19493, 20523, 20512, 32653, 20589, 34014, 34015, 34016, + 34087, 34090, 21757, 21751, 21760, 21754, 21759, 21753, 21758, 21752, + 21761, 21755, 32749, 11043, 964, 7722, 27131, 20513, 20518, 20511, 20515, + 20520, 20510, 20514, 20519, 20516, 20521, 20522, 4624, 4369, 4497, 4370, + 4561, 4434, 4498, 4371, 4593, 4466, 4530, 4403, 4562, 4435, 4499, 4372, + 4609, 4482, 4546, 4419, 4578, 4451, 4515, 4388, 4594, 4467, 4531, 4404, + 4563, 4436, 4500, 4373, 4617, 4490, 4554, 4427, 4586, 4459, 4523, 4396, + 4602, 4475, 4539, 4412, 4571, 4444, 4508, 4381, 4610, 4483, 4547, 4420, + 4579, 4452, 4516, 4389, 4595, 4468, 4532, 4405, 4564, 4437, 4501, 4374, + 4621, 4494, 4558, 4431, 4590, 4463, 4527, 4400, 4606, 4479, 4543, 4416, + 4575, 4448, 4512, 4385, 4614, 4487, 4551, 4424, 4583, 4456, 4520, 4393, + 4599, 4472, 4536, 4409, 4568, 4441, 4505, 4378, 4618, 4491, 4555, 4428, + 4587, 4460, 4524, 4397, 4603, 4476, 4540, 4413, 4572, 4445, 4509, 4382, + 4611, 4484, 4548, 4421, 4580, 4453, 4517, 4390, 4596, 4469, 4533, 4406, + 4565, 4438, 4502, 4375, 4623, 4496, 4560, 4433, 4592, 4465, 4529, 4402, + 4608, 4481, 4545, 4418, 4577, 4450, 4514, 4387, 4616, 4489, 4553, 4426, + 4585, 4458, 4522, 4395, 4601, 4474, 4538, 4411, 4570, 4443, 4507, 4380, + 4620, 4493, 4557, 4430, 4589, 4462, 4526, 4399, 4605, 4478, 4542, 4415, + 4574, 4447, 4511, 4384, 4613, 4486, 4550, 4423, 4582, 4455, 4519, 4392, + 4598, 4471, 4535, 4408, 4567, 4440, 4504, 4377, 4622, 4495, 4559, 4432, + 4591, 4464, 4528, 4401, 4607, 4480, 4544, 4417, 4576, 4449, 4513, 4386, + 4615, 4488, 4552, 4425, 4584, 4457, 4521, 4394, 4600, 4473, 4537, 4410, + 4569, 4442, 4506, 4379, 4619, 4492, 4556, 4429, 4588, 4461, 4525, 4398, + 4604, 4477, 4541, 4414, 4573, 4446, 4510, 4383, 4612, 4485, 4549, 4422, + 4581, 4454, 4518, 4391, 4597, 4470, 4534, 4407, 4566, 4439, 4503, 4376, + 27318, 27317, 19656, 27263, 19503, 27319, 19658, 27265, 11000, 32730, + 32767, 11021, 19660, 27267, 19640, 27311, 27320, 27238, 32732, 11004, + 27250, 27249, 27313, 27315, 27314, 19605, 27257, 19659, 27266, 19583, + 27235, 19603, 27231, 24681, 24661, 24687, 24660, 29059, 29071, 24686, + 24659, 29056, 29070, 27337, 13098, 29057, 24657, 13099, 27338, 24658, + 24685, 33948, 2500, 2499, 2502, 2503, 27217, 19556, 32426, 4083, 32428, + 32427, 20560, 20555, 961, 7719, 27226, 19572, 27924, 27242, 19588, 27234, + 19501, 32770, 19462, 19461, 32641, 32640, 19463, 32642, 19460, 32639, + 19619, 27281, 32744, 11038, 19613, 27275, 32741, 11035, 19618, 27280, + 32743, 11037, 19612, 27274, 32740, 11034, 19615, 32739, 27279, 11032, + 19617, 19611, 27277, 27272, 19616, 19610, 27278, 27273, 32738, 11033, + 27143, 12479, 32324, 19576, 27228, 27227, 19756, 19579, 13729, 29620, + 19578, 29746, 19547, 27148, 32650, 10978, 32522, 35491, 35492, 19539, + 27201, 19541, 27203, 35486, 35482, 35487, 35483, 19524, 27183, 19522, + 27180, 19521, 27181, 19456, 27124, 19457, 27130, 10918, 10943, 19465, + 27134, 10893, 33670, 22179, 27129, 22180, 948, 5, 29185, 29186, 32543, + 27080, 949, 27081, 25218, 25217, 22178, 22177, 22172, 22171, 22176, + 22174, 22175, 22173, 27103, 12441, 12440, 12438, 12439, 6226, 6514, 6501, + 6505, 6502, 6227, 6219, 6228, 32635, 6509, 6232, 6447, 6515, 6218, 6220, + 29486, 29481, 29552, 29538, 29539, 32578, 32501, 32499, 27540, 32498, + 27194, 19529, 33640, 4100, 4101, 3913, 32331, 32332, 34046, 3820, 19544, + 27206, 19473, 27144, 16164, 32258, 16241, 10971, 29429, 16166, 27943, + 12480, 12481, 16007, 13613, 32015, 10983, 10984, 3799, 3834, 34007, 3749, + 12493, 12496, 12492, 12495, 12491, 12494, 27409, 27075, 29018, 27076, + 3737, 3736, 10925, 32518, 19563, 27212, 32333, 22915, 24087, 24085, + 24086, 24095, 24094, 24090, 24091, 32580, 32579, 24089, 23317, 29645, + 26942, 13142, 16322, 16314, 6519, 966, 19872, 19873, 19874, 16315, 26944, + 16319, 16316, 16320, 16318, 16321, 16317, 16463, 18145, 35488, 35489, + 35490, 26779, 26784, 26782, 26778, 26781, 26780, 26783, 22908, 22909, + 22911, 22910, 26775, 26776, 33684, 23609, 23608, 27747, 28939, 23604, + 23605, 6448, 23606, 6242, 26777, 22912, 23607, 16337, 27222, 35484, 362, + 16333, 32627, 32628, 16332, 16331, 32629, 32625, 16330, 32624, 16329, + 32626, 16334, 7735, 7741, 10926, 10927, 7736, 20496, 20504, 10916, 10917, + 32576, 32577, 28879, 28878, 20501, 20498, 20506, 20497, 20505, 20495, + 20499, 20494, 28929, 20503, 20502, 35485, 35481, 12485, 16008, 32516, + 32517, 32326, 32325, 28723, 8174, 12486, 352, 1045, 12476, 26785, 12477, + 10906, 32571, 32034, 12484, 12488, 19773, 13748, 19774, 13749, 19765, + 13735, 19768, 13738, 19766, 13736, 19767, 13737, 19764, 13739, 19758, + 13731, 19757, 13730, 19755, 13727, 19753, 13725, 19752, 13724, 19751, + 13728, 19754, 13726, 28864, 28862, 28865, 28863, 10953, 10952, 10949, + 10948, 28722, 28721, 28720, 28719, 10919, 10921, 10920, 13743, 13732, + 19762, 13746, 19763, 13747, 28937, 18153, 28938, 18154, 12482, 26864, + 29636, 26865, 29637, 26867, 29639, 26863, 29635, 26866, 29638, 26862, + 29634, 10922, 10931, 29631, 29759, 29629, 29757, 29630, 29758, 29628, + 29756, 29623, 29751, 29624, 29752, 29622, 29750, 29625, 29753, 29311, + 29398, 7730, 7732, 7731, 7733, 29618, 29745, 29619, 29744, 29748, 29747, + 12393, 26683, 32496, 13170, 24654, 27928, 27929, 27925, 26506, 33642, + 10940, 33641, 10938, 20507, 27930, 27927, 27926, 10907, 10935, 10929, + 27084, 10709, 33655, 33654, 10977, 26272, 26271, 32521, 32524, 32515, + 32528, 32527, 10951, 10950, 32525, 18142, 10934, 34113, 24096, 24670, + 24696, 29068, 29080, 19506, 19609, 32734, 11028, 24667, 24693, 29065, + 29077, 19508, 32645, 27246, 27247, 19592, 19593, 29422, 29415, 29425, + 29419, 10525, 10526, 10524, 10523, 10889, 3836, 34047, 3911, 34116, 3854, + 34064, 34044, 3817, 15945, 3835, 3839, 34056, 3842, 34060, 3872, 3873, + 34077, 3819, 34045, 3907, 34114, 19459, 32027, 19458, 20517, 19648, + 19647, 19649, 19650, 19584, 19596, 19595, 19643, 19645, 19644, 19580, + 33947, 12478, 27077, 19573, 27233, 27232, 19674, 27327, 27078, 27224, + 32323, 19575, 19574, 27225, 11017, 27923, 27921, 34057, 3874, 34078, + 3861, 34067, 15280, 15293, 15257, 15255, 15258, 28866, 2595, 28867, 2594, + 3628, 27922, 19625, 32753, 27296, 11006, 19510, 32649, 24691, 24665, + 29063, 29075, 19637, 32764, 27308, 11018, 7727, 959, 19636, 32755, 27307, + 11008, 35762, 35762, 24692, 24666, 29064, 29076, 19627, 32763, 27298, + 11016, 15962, 33664, 19626, 32754, 27297, 11007, 19638, 32765, 27309, + 11019, 19608, 32733, 27260, 11027, 956, 957, 955, 958, 27068, 27069, + 24566, 24567, 13176, 27261, 35762, 29855, 32038, 32042, 32039, 32041, + 3827, 3905, 3866, 3807, 11010, 11011, 32757, 32758, 19630, 27301, 19629, + 27300, 3752, 3753, 3754, 3755, 3756, 3758, 3757, 3759, 27115, 27116, + 27113, 27114, 27110, 27112, 27109, 27111, 32774, 32638, 26082, 26081, + 26083, 2736, 6517, 6231, 3878, 3797, 32544, 15944, 3912, 3846, 3838, + 3841, 3844, 24572, 32430, 4077, 19785, 27393, 34036, 27394, 29383, 32620, + 14275, 26791, 26790, 26789, 26788, 32495, 26891, 2515, 15999, 26664, + 24349, 34061, 3800, 32537, 9639, 15230, 35570, 18035, 1042, 97, 33772, + 26801, 19484, 27151, 29569, 29570, 19646, 32769, 27316, 11023, 12498, + 12497, 27759, 27535, 27533, 27534, 27532, 27536, 27537, 12483, 32631, + 27757, 10974, 26424, 27091, 15473, 13513, 13515, 13549, 13523, 13519, + 13550, 13557, 13520, 13556, 13529, 13525, 13524, 13518, 13560, 13531, + 13532, 13533, 13534, 13536, 13538, 13542, 13546, 13559, 13521, 13558, + 13535, 13537, 13539, 13548, 13517, 13541, 13552, 13551, 13553, 13543, + 13555, 13544, 13545, 13554, 13527, 13514, 13526, 13522, 13528, 13540, + 13547, 13530, 13516, 13561, 13563, 13597, 13571, 13567, 13598, 13605, + 13568, 13604, 13577, 13573, 13572, 13566, 13608, 13579, 13580, 13581, + 13582, 13584, 13586, 13590, 13594, 13607, 13569, 13606, 13583, 13585, + 13587, 13596, 13565, 13589, 13600, 13599, 13601, 13591, 13603, 13592, + 13593, 13602, 13575, 13562, 13574, 13570, 13576, 13588, 13595, 13578, + 13564, 18375, 19017, 18378, 18467, 18483, 18751, 19240, 18318, 18936, + 18364, 18996, 18628, 19407, 18197, 18395, 18532, 18533, 19360, 18605, + 19377, 19359, 18323, 18943, 19305, 18864, 19281, 19097, 18675, 19432, + 23035, 18508, 18632, 8182, 8276, 8232, 8326, 8196, 8290, 8193, 8287, + 8237, 8331, 8227, 8321, 8231, 8325, 8198, 8292, 8229, 8323, 8235, 8329, + 8201, 8295, 8206, 8300, 8238, 8332, 8239, 8333, 8202, 8296, 8207, 8301, + 8234, 8328, 8236, 8330, 8228, 8322, 8230, 8324, 8240, 8334, 8204, 8298, + 8200, 8294, 8233, 8327, 8223, 8317, 8190, 8284, 8218, 8312, 8186, 8280, + 8191, 8285, 8192, 8286, 8187, 8281, 8216, 8310, 8226, 8320, 8188, 8282, + 8214, 8308, 8217, 8311, 8181, 8275, 8189, 8283, 8209, 8303, 8210, 8304, + 8205, 8299, 8212, 8306, 8211, 8305, 8208, 8302, 8215, 8309, 8213, 8307, + 8221, 8315, 8219, 8313, 8220, 8314, 8222, 8316, 8336, 8337, 8338, 8340, + 8341, 8335, 8339, 8184, 8278, 8185, 8279, 8180, 8179, 8178, 8183, 8277, + 35762, 35762, 35762, 35762, 35762, 8274, 8271, 8272, 8273, 8269, 8270, + 8342, 13372, 13398, 13383, 13404, 13405, 13403, 13393, 13394, 13406, + 13387, 13396, 13399, 13401, 13407, 13389, 13392, 13397, 13391, 13395, + 13408, 13388, 13386, 13382, 13402, 13390, 13378, 13381, 13385, 13380, + 13379, 13400, 13384, 13373, 13377, 13375, 13410, 13374, 13376, 35762, + 13409, 35762, 35762, 35762, 35762, 35762, 13371, 35762, 35762, 32273, + 32284, 32285, 32278, 32280, 32263, 32302, 32274, 32277, 32275, 32276, + 32312, 32301, 32281, 32267, 32283, 32286, 32262, 32271, 32287, 32300, + 32282, 32268, 32307, 32272, 32313, 32295, 32261, 32269, 32303, 32304, + 32305, 32266, 32270, 32306, 32315, 32297, 32298, 32279, 32265, 32260, + 32288, 32290, 32289, 32291, 32292, 32299, 32293, 32308, 32309, 32310, + 32294, 32264, 32296, 32311, 32314, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 32316, 32317, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 32259, 12933, + 12750, 12837, 12877, 12853, 12540, 12915, 12578, 12768, 12759, 12660, + 12993, 12608, 12593, 12924, 12884, 12569, 12784, 12797, 12645, 12649, + 12648, 12647, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 12867, 12873, 12871, 12868, 12870, 12869, 12872, 35762, 12559, + 12565, 12563, 12560, 12562, 12561, 12564, 35762, 12983, 12989, 12987, + 12984, 12986, 12985, 12988, 35762, 12552, 12558, 12556, 12553, 12555, + 12554, 12557, 35762, 12819, 12825, 12823, 12820, 12822, 12821, 12824, + 35762, 12728, 12734, 12732, 12729, 12731, 12730, 12733, 35762, 12960, + 12966, 12964, 12961, 12963, 12962, 12965, 35762, 12671, 12677, 12675, + 12672, 12674, 12673, 12676, 35762, 7788, 7826, 7823, 7790, 7820, 7821, + 7827, 7794, 7795, 7796, 7803, 7825, 7797, 7791, 7819, 7816, 7818, 7822, + 7806, 7805, 7824, 7792, 7828, 7802, 7789, 7815, 7811, 7813, 7800, 7814, + 7787, 7799, 27126, 27125, 19528, 27187, 19477, 27141, 26965, 26964, + 10892, 19531, 27192, 26974, 19511, 27167, 11222, 26270, 13169, 27086, + 15997, 10891, 11005, 32717, 10894, 10942, 16344, 26229, 15993, 32329, + 19492, 27157, 32328, 32327, 19554, 27198, 32439, 32442, 4088, 4091, + 19516, 27172, 19476, 27146, 32574, 25768, 29482, 13140, 27101, 33667, + 27330, 34176, 32548, 26963, 26973, 32559, 10224, 10225, 32549, 32433, + 32584, 32045, 29582, 33669, 34159, 5701, 10910, 27100, 10913, 10231, + 10930, 16345, 16346, 20533, 20534, 10928, 10888, 32526, 22281, 26268, + 26922, 8345, 8383, 8382, 32417, 22280, 22282, 19526, 27185, 19525, 27184, + 32431, 32432, 4078, 4079, 25219, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 7615, + 7568, 7618, 7617, 7616, 7611, 7539, 7636, 7650, 7649, 7572, 7619, 7632, + 7631, 7601, 7600, 7599, 7598, 7628, 7637, 7627, 7626, 7587, 7586, 7590, + 7614, 35762, 7571, 7634, 7608, 7573, 7606, 7566, 7642, 7641, 7580, 7610, + 7609, 7620, 7570, 7574, 7595, 7537, 7579, 7630, 7629, 7542, 7625, 7553, + 7648, 7647, 7646, 7645, 7603, 7633, 7613, 7578, 7651, 7541, 7540, 7602, + 7607, 7584, 7583, 7582, 7638, 7569, 7644, 7643, 7557, 7621, 7589, 7556, + 7555, 7581, 7565, 7622, 7640, 7639, 7567, 7549, 7597, 7596, 7552, 7550, + 7605, 7604, 7612, 7543, 7559, 7551, 7561, 7547, 7577, 7576, 7575, 7545, + 7588, 7564, 7538, 7585, 7546, 7563, 7554, 7623, 7624, 7548, 7594, 7544, + 7592, 7560, 7593, 7562, 7635, 7591, 7558, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 16662, 16644, + 16578, 16698, 16686, 16630, 16730, 16645, 16658, 16641, 16593, 16597, + 16582, 16567, 16633, 16719, 16665, 16636, 16670, 16747, 16704, 16675, + 16627, 16732, 16576, 16687, 16563, 16667, 16538, 16656, 16592, 16590, + 16685, 16613, 16615, 16595, 16545, 16744, 16570, 16678, 16632, 16714, + 16637, 16565, 16703, 16654, 16676, 16745, 16663, 16728, 16588, 16692, + 16579, 16647, 16731, 16694, 16553, 16712, 16554, 16706, 16624, 16621, + 16584, 16622, 16555, 16673, 16684, 16577, 16540, 16715, 16660, 16717, + 16683, 16657, 16727, 16638, 16707, 16572, 16738, 16583, 16566, 16612, + 16561, 16705, 16737, 16604, 16562, 16599, 16581, 16620, 16699, 16601, + 16569, 16585, 16668, 16634, 16648, 16722, 16711, 16643, 16749, 16602, + 16549, 16695, 16580, 16740, 16716, 16575, 16598, 16700, 16536, 16709, + 16702, 16726, 16616, 16560, 16710, 16541, 16677, 16696, 16635, 16661, + 16691, 16610, 16666, 16539, 16669, 16589, 16556, 16649, 16650, 16688, + 16537, 16652, 16723, 16664, 16550, 16708, 16568, 16617, 16721, 16631, + 16546, 16736, 16564, 16739, 16689, 16629, 16701, 16733, 16557, 16671, + 16542, 16690, 16680, 16679, 16611, 16552, 16559, 16543, 16653, 16735, + 16571, 16743, 16574, 16734, 16614, 16646, 16619, 16655, 16697, 16693, + 16672, 16548, 16746, 16600, 16639, 16718, 16642, 16713, 16640, 16742, + 16607, 16591, 16625, 16608, 16628, 16551, 16720, 16623, 16603, 16681, + 16558, 16618, 16605, 16544, 16682, 16573, 16741, 16626, 16748, 16651, + 16547, 16596, 16609, 16725, 16587, 16674, 16659, 16594, 16724, 16586, + 16729, 16606, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 16031, 16029, + 16030, 16028, 16043, 16039, 16038, 16035, 16036, 16037, 16033, 16032, + 16040, 16034, 16044, 16042, 16128, 16027, 16126, 10698, 16362, 16127, + 16026, 16046, 19455, 27123, 19474, 27142, 19470, 27139, 19538, 27200, + 19464, 27133, 26803, 13506, 19536, 27196, 19540, 27202, 19543, 27205, + 19542, 27204, 33946, 27083, 10924, 20531, 26804, 15127, 15120, 15117, + 15123, 15122, 15125, 15124, 15128, 15126, 16124, 16123, 16045, 16122, + 14786, 14785, 33952, 33647, 33650, 33648, 33651, 33649, 6500, 16120, + 15121, 15119, 15118, 33646, 21138, 26422, 16125, 16121, 35762, 15849, + 15835, 15851, 15929, 15853, 15931, 15850, 15928, 15852, 15930, 15890, + 15880, 15892, 15882, 15894, 15884, 15891, 15881, 15893, 15883, 15854, + 15915, 15856, 15917, 15858, 15919, 15855, 15916, 15857, 15918, 15910, + 15875, 15912, 15877, 15848, 15914, 15879, 15911, 15876, 15913, 15878, + 15870, 15872, 15874, 15871, 15873, 15885, 15865, 15900, 15887, 15859, + 15902, 15889, 15868, 15904, 15886, 15866, 15901, 15888, 15867, 15903, + 15895, 15897, 15899, 15896, 15898, 15842, 15924, 15844, 15926, 15843, + 15925, 15905, 15907, 15909, 15906, 15908, 15838, 15920, 15922, 15921, + 15923, 15869, 15927, 15845, 15846, 35762, 35762, 7985, 7984, 16987, + 16986, 15933, 15932, 15834, 16984, 16914, 16843, 16916, 16977, 16918, + 16979, 16915, 16976, 16917, 16978, 16939, 16929, 16941, 16931, 16943, + 16933, 16940, 16930, 16942, 16932, 16919, 16964, 16921, 16966, 16923, + 16968, 16920, 16965, 16922, 16967, 16954, 16924, 16956, 16926, 16901, + 16958, 16928, 16955, 16925, 16957, 16927, 16881, 16883, 16885, 16882, + 16884, 16934, 16858, 16944, 16936, 16852, 16946, 16938, 16861, 16948, + 16935, 16859, 16945, 16937, 16860, 16947, 16876, 16862, 16879, 16877, + 16878, 16906, 16973, 16908, 16975, 16907, 16974, 16949, 16951, 16953, + 16950, 16952, 16902, 16969, 16971, 16970, 16972, 16880, 16963, 16896, + 16897, 16959, 16961, 16960, 16962, 16983, 16985, 16982, 16980, 16981, + 35762, 35762, 35762, 35762, 35762, 4063, 4071, 4070, 4068, 4067, 4074, + 4039, 4059, 4027, 4055, 4069, 4065, 4072, 4076, 4052, 4058, 4062, 4073, + 4051, 4057, 4061, 4007, 4043, 4019, 4024, 4008, 4025, 4010, 4050, 4012, + 4020, 4013, 4021, 4026, 4032, 4017, 4038, 4075, 4040, 4029, 4035, 4046, + 4042, 35762, 15039, 15083, 15040, 15045, 15046, 15048, 15075, 15086, + 15061, 15062, 15064, 15066, 15073, 15069, 15065, 15072, 15041, 15051, + 15085, 15052, 15076, 15088, 15033, 15028, 15082, 15027, 15038, 15074, + 15059, 15112, 15023, 15026, 15109, 15110, 15030, 15029, 15096, 15095, + 15113, 15092, 15093, 15114, 15101, 15115, 15091, 15090, 15094, 15105, + 15031, 15111, 15032, 15116, 15084, 15047, 15050, 15049, 15063, 15070, + 15067, 15068, 15071, 15042, 15044, 15043, 15037, 15058, 15056, 15053, + 15054, 15057, 15055, 15035, 15036, 15078, 15079, 15081, 15080, 15077, + 15060, 15089, 15098, 15100, 15099, 15034, 15087, 15097, 15102, 15103, + 15104, 15107, 15106, 15108, 15024, 15025, 35762, 16020, 16023, 16022, + 16018, 16016, 16012, 16019, 16014, 16010, 16013, 16021, 16017, 16011, + 16024, 16025, 16015, 4064, 4053, 4066, 4030, 4023, 4022, 4049, 4045, + 4037, 4014, 4033, 4018, 4036, 4041, 4009, 4011, 4016, 4048, 4044, 4034, + 4005, 4006, 4004, 4003, 4028, 4060, 4054, 4002, 4031, 4056, 4047, 4015, + 7680, 7683, 7684, 7682, 7671, 7656, 7662, 7653, 7661, 7675, 7663, 7659, + 7654, 7660, 7657, 7686, 7652, 7670, 7666, 7678, 7685, 7655, 7665, 7674, + 7673, 7679, 7677, 7667, 7669, 7681, 7676, 7672, 7664, 7658, 7668, 7687, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 16041, 16899, 16911, 16912, 16900, 16910, 16886, 16888, 16890, + 16887, 16889, 16913, 16891, 16893, 16895, 16892, 16894, 26284, 26288, + 26300, 26294, 26286, 26292, 26296, 26302, 26277, 26275, 26282, 26298, + 26290, 26280, 26285, 26289, 26301, 26295, 26287, 26293, 26297, 26303, + 26278, 26276, 26283, 26299, 26291, 26281, 26279, 26341, 26340, 35762, + 26339, 26335, 26333, 26314, 26312, 26332, 26324, 26309, 26318, 26334, + 26317, 26311, 26337, 26336, 26316, 26308, 26331, 26329, 26338, 26326, + 26319, 26327, 26310, 26305, 26315, 26322, 26306, 26328, 26330, 26307, + 26320, 26304, 26313, 26321, 26325, 26323, 6319, 6307, 6329, 6308, 6473, + 6487, 6475, 6457, 6454, 6470, 6468, 6450, 26421, 6488, 6494, 6493, 6490, + 6489, 6492, 6491, 6496, 6495, 6474, 6476, 6482, 6481, 6478, 6477, 6267, + 6271, 6283, 6277, 6269, 6275, 6279, 6260, 6258, 6256, 6265, 6281, 6273, + 6263, 6268, 6272, 6284, 6278, 6270, 6276, 6280, 6261, 6259, 6257, 6266, + 6282, 6274, 6264, 6394, 6393, 6262, 18033, 6342, 6337, 6335, 6304, 6302, + 6334, 6325, 6299, 6317, 6336, 6315, 6301, 6339, 6338, 6313, 6297, 6328, + 6333, 6306, 6330, 6318, 6331, 6300, 6293, 6309, 6324, 6314, 6303, 6327, + 6298, 6341, 6290, 6340, 6321, 6294, 6292, 6305, 6295, 6310, 6311, 6323, + 6312, 6322, 6332, 6326, 6296, 6320, 6288, 6316, 6480, 6479, 6484, 6483, + 6456, 6458, 6464, 6463, 6460, 6459, 6462, 6461, 6466, 6465, 6453, 16111, + 16114, 16115, 16053, 16116, 16112, 16113, 16052, 16118, 16119, 16117, + 16085, 29271, 29240, 29242, 19871, 6388, 6390, 6392, 6389, 6391, 6351, + 6353, 6355, 6352, 6354, 6371, 6373, 6375, 6372, 6374, 6376, 6378, 6380, + 6377, 6379, 6361, 6363, 6365, 6362, 6364, 6346, 6348, 6350, 6347, 6349, + 6356, 6358, 6360, 6357, 6359, 6385, 6387, 6386, 6366, 6368, 6370, 6367, + 6369, 6381, 6383, 6382, 6384, 29238, 29202, 29200, 29199, 29201, 29274, + 29275, 29434, 29241, 29234, 29364, 29368, 29281, 29283, 29282, 29246, + 29247, 29251, 29250, 29284, 29249, 29285, 29288, 29286, 29287, 29252, + 29253, 29295, 29296, 29297, 29294, 29293, 29404, 29405, 29408, 29406, + 29407, 29225, 29229, 29230, 29413, 29357, 29358, 29259, 29371, 29372, + 29206, 29380, 29378, 29379, 29209, 29266, 29265, 29208, 29267, 29260, + 29377, 29375, 29261, 29376, 29374, 29211, 29381, 29210, 29264, 29382, + 29262, 29263, 29321, 29322, 29325, 29324, 29323, 29331, 29332, 29333, + 29328, 29329, 29330, 29432, 29431, 29433, 29399, 29400, 29402, 29401, + 29397, 29396, 29414, 16109, 16110, 16092, 16094, 16101, 16100, 16107, + 16105, 16096, 16103, 16095, 16098, 16091, 16093, 16102, 16099, 16108, + 16106, 16097, 16104, 16086, 16090, 16089, 16088, 16087, 29269, 29224, + 29204, 29207, 29369, 29385, 29226, 29228, 29227, 29279, 29235, 29239, + 29236, 29237, 29216, 29373, 29356, 29338, 29320, 29280, 29302, 29326, + 29256, 29213, 29299, 29386, 29359, 29339, 29340, 29353, 29303, 29272, + 29298, 29350, 29254, 29412, 29341, 29354, 29233, 29305, 29245, 29360, + 29342, 29335, 29217, 29289, 29337, 29219, 29319, 29292, 29336, 29218, + 29318, 29291, 29315, 29316, 29370, 29301, 29352, 29255, 29393, 29394, + 29395, 29390, 29361, 29343, 29355, 29391, 29362, 29344, 29346, 29307, + 29347, 29392, 29363, 29345, 29348, 29308, 29349, 29300, 29317, 29203, + 29212, 29222, 29223, 29220, 29215, 29231, 29257, 29258, 29268, 29273, + 29304, 29290, 29306, 29312, 29313, 29310, 29314, 29327, 29334, 29351, + 29387, 29388, 29384, 29389, 29409, 29410, 29430, 29205, 29198, 16084, + 16069, 16057, 16076, 16075, 16082, 16080, 16071, 16078, 16070, 16073, + 16068, 16056, 16077, 16074, 16083, 16081, 16072, 16079, 16058, 16066, + 16064, 16063, 16060, 16059, 16062, 16061, 16067, 16065, 16054, 16055, + 29248, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 15811, + 15814, 15775, 15825, 15822, 15770, 15808, 15787, 15804, 15821, 15799, + 15805, 15780, 15782, 15792, 15826, 15779, 15823, 15763, 15769, 15767, + 15786, 15806, 15800, 15789, 15785, 15793, 15784, 15809, 15812, 15791, + 15777, 15801, 15783, 15798, 15778, 15813, 15796, 15794, 15773, 15772, + 15790, 15768, 15771, 15781, 15797, 15795, 15815, 15802, 15810, 15807, + 15819, 15774, 15817, 15765, 15816, 15818, 15820, 15776, 15824, 15788, + 15803, 15764, 15766, 34695, 34702, 34694, 34701, 34699, 34700, 34697, + 34698, 35470, 35471, 35468, 35469, 35467, 35465, 35466, 35474, 35475, + 35472, 35473, 35477, 35476, 35342, 34362, 34363, 34356, 34361, 34359, + 34360, 34357, 34358, 34366, 34367, 34364, 34365, 34347, 34345, 34346, + 34370, 34371, 34368, 34369, 34355, 34353, 34354, 34351, 34352, 34344, + 34350, 34349, 34348, 34376, 34377, 34372, 34375, 34374, 34373, 35074, + 35075, 35069, 35073, 35072, 35070, 35071, 35078, 35079, 35076, 35077, + 35063, 35061, 35062, 35082, 35083, 35080, 35081, 35067, 35068, 35060, + 35066, 35065, 35064, 35088, 35089, 35084, 35087, 35086, 35085, 34330, + 34331, 34324, 34329, 34327, 34328, 34325, 34326, 34334, 34335, 34332, + 34333, 34315, 34313, 34314, 34338, 34339, 34336, 34337, 34323, 34321, + 34322, 34319, 34320, 34312, 34318, 34317, 34316, 34342, 34343, 34340, + 34341, 34877, 34878, 34872, 34876, 34875, 34873, 34874, 34881, 34882, + 34879, 34880, 34885, 34886, 34883, 34884, 34891, 34892, 34887, 34890, + 34889, 34888, 34897, 34898, 34893, 34896, 34895, 34894, 34620, 34621, + 34615, 34619, 34618, 34616, 34617, 34624, 34625, 34622, 34623, 34609, + 34607, 34608, 34628, 34629, 34626, 34627, 34613, 34614, 34606, 34612, + 34611, 34610, 34634, 34630, 34633, 34632, 34631, 34856, 34857, 34851, + 34855, 34854, 34852, 34853, 34860, 34861, 34858, 34859, 34844, 34845, + 34842, 34843, 34864, 34865, 34862, 34863, 34871, 34870, 34849, 34850, + 34841, 34848, 34847, 34846, 34868, 34869, 34866, 34867, 34501, 34502, + 34499, 34500, 34497, 34498, 34495, 34496, 34494, 34492, 34493, 34511, + 34512, 34507, 34510, 34509, 34508, 34505, 34506, 34503, 34504, 35320, + 35321, 35314, 35319, 35317, 35318, 35315, 35316, 35324, 35325, 35322, + 35323, 35328, 35329, 35326, 35327, 35313, 35312, 35334, 35335, 35330, + 35333, 35332, 35331, 35340, 35341, 35336, 35339, 35338, 35337, 34479, + 34480, 34474, 34478, 34477, 34475, 34476, 34486, 34487, 34484, 34485, + 34468, 34467, 34490, 34491, 34488, 34489, 34483, 34481, 34482, 34472, + 34473, 34466, 34471, 34470, 34469, 35299, 35300, 35294, 35298, 35297, + 35295, 35296, 35306, 35307, 35304, 35305, 35287, 35288, 35285, 35286, + 35310, 35311, 35308, 35309, 35303, 35301, 35302, 35292, 35293, 35284, + 35291, 35290, 35289, 34453, 34454, 34448, 34452, 34451, 34449, 34450, + 34460, 34461, 34458, 34459, 34442, 34440, 34441, 34464, 34465, 34462, + 34463, 34457, 34455, 34456, 34446, 34447, 34439, 34445, 34444, 34443, + 34903, 34904, 34899, 34902, 34901, 34900, 34910, 34911, 34908, 34909, + 34914, 34915, 34912, 34913, 34907, 34905, 34906, 34920, 34921, 34916, + 34919, 34918, 34917, 34650, 34651, 34644, 34649, 34647, 34648, 34645, + 34646, 34654, 34655, 34652, 34653, 34639, 34638, 34636, 34637, 34635, + 34643, 34641, 34642, 34640, 35048, 35049, 35043, 35047, 35046, 35044, + 35045, 35052, 35050, 35051, 35037, 35035, 35036, 35058, 35059, 35056, + 35057, 35055, 35053, 35054, 35041, 35042, 35034, 35040, 35039, 35038, + 34588, 34589, 34583, 34587, 34586, 34584, 34585, 34598, 34599, 34596, + 34597, 34577, 34575, 34576, 34595, 34593, 34594, 34592, 34590, 34591, + 34581, 34582, 34574, 34580, 34579, 34578, 34604, 34605, 34600, 34603, + 34602, 34601, 34803, 34804, 34797, 34802, 34800, 34801, 34798, 34799, + 34807, 34808, 34805, 34806, 34787, 34788, 34785, 34786, 34811, 34812, + 34809, 34810, 34796, 34794, 34795, 34792, 34793, 34784, 34791, 34790, + 34789, 34817, 34818, 34813, 34816, 34815, 34814, 34557, 34558, 34551, + 34556, 34554, 34555, 34552, 34553, 34561, 34562, 34559, 34560, 34544, + 34545, 34542, 34543, 34569, 34570, 34567, 34568, 34565, 34566, 34563, + 34564, 34549, 34550, 34541, 34548, 34547, 34546, 34770, 34771, 34765, + 34769, 34768, 34766, 34767, 34774, 34775, 34772, 34773, 34759, 34757, + 34758, 34782, 34783, 34780, 34781, 34778, 34779, 34776, 34777, 34763, + 34764, 34756, 34762, 34761, 34760, 34517, 34518, 34513, 34516, 34514, + 34515, 34531, 34532, 34529, 34530, 34522, 34523, 34520, 34521, 34539, + 34540, 34537, 34538, 34535, 34536, 34533, 34534, 34527, 34528, 34519, + 34526, 34525, 34524, 34840, 34839, 34833, 34834, 34831, 34832, 34822, + 34820, 34821, 34837, 34838, 34835, 34836, 34830, 34828, 34829, 34826, + 34827, 34819, 34825, 34824, 34823, 34669, 34670, 34663, 34668, 34666, + 34667, 34664, 34665, 34673, 34674, 34671, 34672, 34658, 34659, 34656, + 34657, 34677, 34678, 34675, 34676, 34662, 34660, 34661, 34930, 34928, + 34929, 34933, 34934, 34931, 34932, 34923, 34924, 34922, 34937, 34938, + 34935, 34936, 34927, 34925, 34926, 34573, 34572, 34571, 34688, 34689, + 34686, 34687, 34681, 34682, 34679, 34680, 34692, 34693, 34690, 34691, + 34685, 34683, 34684, 35354, 35355, 35352, 35353, 35345, 35343, 35344, + 35351, 35349, 35350, 35348, 35346, 35347, 35417, 35418, 35412, 35416, + 35415, 35413, 35414, 35453, 35454, 35451, 35452, 35406, 35404, 35405, + 35457, 35458, 35455, 35456, 35450, 35448, 35449, 35410, 35411, 35403, + 35409, 35408, 35407, 35463, 35464, 35459, 35462, 35461, 35460, 34423, + 34424, 34417, 34422, 34420, 34421, 34418, 34419, 34427, 34428, 34425, + 34426, 34408, 34406, 34407, 34431, 34432, 34429, 34430, 34416, 34414, + 34415, 34412, 34413, 34405, 34411, 34410, 34409, 34437, 34438, 34433, + 34436, 34435, 34434, 35431, 35432, 35425, 35430, 35428, 35429, 35426, + 35427, 35435, 35436, 35433, 35434, 35424, 35422, 35423, 35421, 35419, + 35420, 35441, 35437, 35440, 35439, 35438, 35446, 35447, 35442, 35445, + 35444, 35443, 35020, 35021, 35015, 35019, 35018, 35016, 35017, 35024, + 35025, 35022, 35023, 35008, 35007, 35014, 35013, 35033, 35032, 35012, + 35006, 35011, 35010, 35009, 35030, 35031, 35026, 35029, 35028, 35027, + 35265, 35266, 35260, 35264, 35263, 35261, 35262, 35272, 35273, 35270, + 35271, 35254, 35252, 35253, 35276, 35277, 35274, 35275, 35269, 35267, + 35268, 35258, 35259, 35251, 35257, 35256, 35255, 35282, 35283, 35278, + 35281, 35280, 35279, 35201, 35202, 35196, 35200, 35199, 35197, 35198, + 35208, 35209, 35206, 35207, 35212, 35213, 35210, 35211, 35205, 35203, + 35204, 35216, 35217, 35214, 35215, 35222, 35223, 35218, 35221, 35220, + 35219, 35387, 35388, 35385, 35386, 35379, 35377, 35378, 35395, 35396, + 35393, 35394, 35391, 35392, 35389, 35390, 35383, 35384, 35376, 35382, + 35381, 35380, 35401, 35402, 35397, 35400, 35399, 35398, 34389, 34390, + 34387, 34388, 34381, 34382, 34379, 34380, 34397, 34398, 34395, 34396, + 34393, 34394, 34391, 34392, 34386, 34378, 34385, 34384, 34383, 34403, + 34404, 34399, 34402, 34401, 34400, 35169, 35168, 35148, 35147, 35160, + 35161, 35158, 35159, 35156, 35157, 35154, 35155, 35152, 35153, 35146, + 35151, 35150, 35149, 35166, 35167, 35162, 35165, 35164, 35163, 34969, + 34970, 34967, 34968, 34966, 34964, 34965, 34973, 34974, 34971, 34972, + 34979, 34980, 34975, 34978, 34977, 34976, 34985, 34986, 34981, 34984, + 34983, 34982, 35235, 35236, 35233, 35234, 35227, 35225, 35226, 35243, + 35244, 35241, 35242, 35239, 35240, 35237, 35238, 35231, 35232, 35224, + 35230, 35229, 35228, 35249, 35250, 35245, 35248, 35247, 35246, 35184, + 35185, 35182, 35183, 35173, 35171, 35172, 35188, 35189, 35186, 35187, + 35181, 35179, 35180, 35177, 35178, 35170, 35176, 35175, 35174, 35194, + 35195, 35190, 35193, 35192, 35191, 34744, 34745, 34738, 34743, 34741, + 34742, 34739, 34740, 34731, 34732, 34729, 34730, 34748, 34749, 34746, + 34747, 34736, 34737, 34728, 34735, 34734, 34733, 34754, 34755, 34750, + 34753, 34752, 34751, 35106, 35107, 35100, 35105, 35103, 35104, 35101, + 35102, 35093, 35094, 35091, 35092, 35110, 35111, 35108, 35109, 35098, + 35099, 35090, 35097, 35096, 35095, 35116, 35117, 35112, 35115, 35114, + 35113, 34718, 34719, 34712, 34717, 34715, 34716, 34713, 34714, 34706, + 34704, 34705, 34722, 34723, 34720, 34721, 34710, 34711, 34703, 34709, + 34708, 34707, 34726, 34727, 34724, 34725, 34952, 34953, 34946, 34951, + 34949, 34950, 34947, 34948, 34941, 34940, 34956, 34957, 34954, 34955, + 34945, 34939, 34944, 34943, 34942, 34962, 34963, 34958, 34961, 34960, + 34959, 35000, 35001, 34994, 34999, 34997, 34998, 34995, 34996, 34990, + 34988, 34989, 35004, 35005, 35002, 35003, 34992, 34993, 34987, 34991, + 35362, 35363, 35356, 35361, 35359, 35360, 35357, 35358, 35375, 35374, + 35366, 35367, 35364, 35365, 35372, 35373, 35368, 35371, 35370, 35369, + 35134, 35135, 35128, 35133, 35131, 35132, 35129, 35130, 35121, 35122, + 35119, 35120, 35138, 35139, 35136, 35137, 35126, 35127, 35118, 35125, + 35124, 35123, 35144, 35145, 35140, 35143, 35142, 35141, 35762, 35762, + 35762, 34309, 34282, 34280, 34287, 34261, 34297, 34268, 34270, 34286, + 34273, 34284, 34257, 34285, 34303, 34291, 34272, 34298, 34271, 34304, + 34262, 34265, 34258, 34267, 34288, 34299, 34311, 34276, 34307, 34292, + 34275, 34302, 34300, 34296, 34301, 34308, 34279, 34289, 34278, 34269, + 34277, 34310, 34266, 34293, 34283, 34260, 34259, 34264, 34274, 34294, + 34305, 34295, 34263, 34306, 34290, 34281, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 20474, 20463, 20462, 20446, 20444, + 20443, 20457, 20461, 20460, 20476, 20455, 20454, 20445, 20442, 20441, + 20478, 20453, 20477, 20465, 20468, 20469, 20452, 20459, 20480, 20458, + 20475, 20479, 20464, 20467, 20456, 20470, 20471, 20450, 20451, 20481, + 20472, 20447, 20448, 20449, 20473, 20437, 20440, 20438, 20436, 20439, + 20435, 20482, 20483, 33047, 33048, 32884, 33033, 33034, 33007, 32810, + 32817, 32920, 32893, 32927, 32867, 32993, 33021, 32845, 32838, 32796, + 32789, 32911, 33014, 32803, 32946, 32831, 32824, 32859, 32852, 32986, + 33000, 32965, 33028, 32906, 32952, 32873, 32934, 32979, 32972, 33056, + 33057, 32888, 32889, 33042, 33043, 33009, 32812, 32819, 32922, 32899, + 32929, 32870, 32995, 33023, 32847, 32840, 32798, 32791, 32915, 33016, + 32805, 32948, 32833, 32826, 32861, 32854, 32988, 33002, 32967, 33030, + 32907, 32957, 32878, 32936, 32981, 32974, 33054, 33055, 32959, 32886, + 32887, 33040, 33041, 33008, 32811, 32818, 32921, 32897, 32898, 32928, + 32869, 32994, 33022, 32846, 32839, 32797, 32790, 32914, 33015, 32804, + 32947, 32832, 32825, 32860, 32853, 32987, 33001, 32966, 33029, 32903, + 32904, 32956, 32877, 32935, 32980, 32973, 33051, 33052, 32882, 33037, + 33038, 33005, 32808, 32815, 32918, 32896, 32925, 32865, 32991, 33019, + 32843, 32836, 32794, 32787, 32913, 33012, 32801, 32944, 32829, 32822, + 32857, 32850, 32984, 32998, 32963, 33026, 32902, 32955, 32876, 32932, + 32977, 32970, 33058, 33059, 32890, 32891, 33044, 33045, 33010, 32813, + 32820, 32923, 32900, 32930, 32871, 32996, 33024, 32848, 32841, 32799, + 32792, 32916, 33017, 32806, 32949, 32834, 32827, 32862, 32855, 32989, + 33003, 32968, 33031, 32908, 32958, 32879, 32937, 32982, 32975, 33050, + 33053, 32961, 32880, 32881, 33036, 33039, 33004, 32807, 32814, 32917, + 32895, 32924, 32863, 32864, 32990, 33018, 32842, 32835, 32793, 32786, + 32912, 33011, 32800, 32938, 32828, 32821, 32856, 32849, 32983, 32997, + 32962, 33025, 32901, 32954, 32875, 32931, 32976, 32969, 33046, 33049, + 32960, 32883, 32885, 33032, 33035, 33006, 32809, 32816, 32919, 32892, + 32894, 32926, 32866, 32868, 32992, 33020, 32844, 32837, 32795, 32788, + 32909, 33013, 32802, 32945, 32830, 32823, 32858, 32851, 32985, 32999, + 32964, 33027, 32905, 32951, 32953, 32872, 32874, 32933, 32978, 32971, + 32950, 32910, 32783, 32784, 32785, 32941, 32942, 32939, 33063, 33066, + 33069, 33068, 33072, 33064, 33071, 33062, 33060, 33067, 33070, 33061, + 33065, 33079, 33081, 33078, 33077, 33074, 33073, 33076, 33075, 33082, + 33080, 32943, 32940, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 9978, 10178, 9867, 10026, 9818, 10120, 9922, 10081, + 9863, 10022, 9943, 10106, 9851, 10010, 9811, 10107, 9971, 10171, 9919, + 10078, 9820, 10122, 9920, 10079, 9859, 10018, 9852, 10011, 9916, 10075, + 9973, 10173, 9819, 10121, 9962, 10140, 9959, 10137, 9960, 10138, 9942, + 10105, 9849, 10008, 9864, 10023, 9993, 7842, 7834, 7785, 7835, 28868, + 7809, 7798, 7812, 7808, 7817, 7810, 7807, 7804, 7840, 7829, 9992, 9996, + 9873, 10032, 9871, 10030, 9983, 10183, 9861, 10020, 9869, 10028, 9824, + 10148, 9831, 10156, 9828, 10152, 9827, 10151, 9830, 10155, 9907, 10066, + 9957, 10135, 9865, 10024, 9860, 10019, 23047, 23084, 7793, 7801, 3393, + 2760, 3396, 2762, 3392, 3368, 3385, 3395, 2789, 3394, 2765, 3365, 3371, + 3370, 2763, 2769, 3384, 2788, 2782, 2768, 3380, 2776, 3375, 3381, 3374, + 3378, 2758, 2754, 2786, 2785, 2780, 3387, 3377, 3388, 3389, 2787, 2752, + 3361, 2781, 2784, 3364, 3390, 3362, 2749, 3373, 2767, 2774, 2791, 3367, + 3372, 2753, 2777, 2778, 2779, 3376, 3363, 2751, 2750, 3391, 2790, 2766, + 3366, 2764, 2755, 2771, 3369, 2770, 2773, 3386, 2761, 2775, 2772, 3383, + 2759, 3382, 2783, 3379, 2748, 2756, 2757, 2745, 2744, 3397, 3399, 2747, + 2746, 3398, 3400, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 23044, 23040, 23043, 23039, 23045, 23041, 23046, 23042, 23099, 23114, + 23142, 23121, 23104, 23098, 23113, 23141, 23120, 23103, 23100, 23115, + 23143, 23125, 23105, 23092, 23090, 23091, 23136, 23155, 23152, 23154, + 23153, 23133, 23303, 23304, 18285, 18884, 18286, 18885, 18325, 18946, + 18547, 19306, 18546, 19263, 18227, 18806, 18228, 18807, 18688, 18696, + 18201, 18762, 18202, 18763, 18203, 18764, 18199, 18760, 18200, 18761, + 18204, 18765, 18493, 19188, 18366, 18998, 18363, 18995, 18367, 18999, + 18213, 18783, 18385, 19022, 18416, 19096, 18417, 19098, 18463, 19136, + 18468, 19141, 18466, 19139, 18469, 19142, 18475, 19153, 18474, 19150, + 18490, 19178, 18495, 19191, 18588, 19356, 18597, 19368, 18592, 19363, + 18541, 19257, 18542, 19258, 18596, 19367, 18287, 18902, 18354, 18985, + 18229, 18808, 23312, 18844, 19042, 19056, 19079, 19190, 18673, 19301, + 19353, 18347, 18974, 18348, 18975, 18349, 18531, 19269, 18536, 19299, + 18350, 18977, 18351, 18978, 18352, 18979, 23119, 23088, 23165, 18514, + 19213, 18534, 19027, 18704, 18409, 19070, 18223, 18796, 18793, 18940, + 18207, 18768, 18294, 18909, 18593, 19364, 18594, 19365, 18595, 19366, + 18302, 18920, 18370, 19003, 18412, 19075, 18488, 19175, 18510, 19211, + 18321, 18492, 18517, 18373, 18513, 18695, 18535, 18538, 18357, 18230, + 18214, 18785, 18461, 19134, 18584, 19344, 18307, 18925, 18308, 18926, + 18309, 18927, 18458, 19125, 18196, 18757, 18221, 18511, 18634, 18234, + 18810, 18507, 19205, 35762, 35762, 35762, 35762, 35762, 18226, 18802, + 35762, 18837, 35762, 18834, 18398, 19055, 18516, 19231, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 23020, 23023, 23032, 18491, 19179, 18644, 23015, 23244, + 18678, 18642, 18643, 18640, 18641, 18639, 29798, 29800, 29810, 29802, + 29799, 29801, 29809, 29790, 29789, 29786, 29785, 29808, 29784, 29783, + 29788, 29787, 29778, 29777, 29772, 29771, 29780, 29779, 29774, 29773, + 29796, 29792, 29791, 29782, 29781, 29795, 29776, 29794, 29775, 29797, + 29793, 29812, 29814, 29815, 29813, 29811, 29803, 29804, 29805, 29806, + 29807, 35762, 35762, 35762, 24678, 24677, 24680, 24675, 24676, 24679, + 24672, 24671, 24674, 24673, 35762, 35762, 35762, 35762, 35762, 35762, + 26558, 26557, 26546, 26547, 26534, 26536, 26568, 26549, 26556, 26555, + 26539, 26550, 26560, 26559, 26565, 26570, 26552, 26551, 26538, 26573, + 26561, 26562, 26540, 26575, 26572, 26569, 26541, 26542, 26567, 26531, + 26576, 26578, 26563, 26577, 26571, 26574, 26566, 26545, 26564, 26583, + 26584, 26554, 26553, 26537, 26548, 26532, 26544, 26543, 26533, 26582, + 26585, 26535, 26581, 26586, 26580, 26579, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 27667, 27669, 27616, 27617, 27637, 27638, + 27633, 27634, 27628, 27629, 27630, 27631, 27660, 27661, 27618, 27635, + 27636, 27619, 27657, 27656, 27653, 27652, 27641, 27651, 27650, 27655, + 27654, 27643, 27625, 27624, 27621, 27620, 27642, 27627, 27626, 27623, + 27622, 27644, 27659, 27658, 27649, 27648, 27663, 27665, 27664, 27640, + 27632, 27645, 27646, 27647, 27662, 27639, 27682, 27683, 27694, 27695, + 27690, 27691, 27686, 27687, 27688, 27689, 27696, 27697, 27684, 27692, + 27693, 27685, 27668, 27666, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 27671, 27670, 27678, 27680, 27677, 27676, 27673, 27672, + 27675, 27674, 27681, 27679, 35762, 35762, 35762, 35762, 35762, 35762, + 7860, 7862, 7859, 7858, 7855, 7854, 7857, 7856, 7863, 7861, 7851, 7852, + 7847, 7848, 7849, 7850, 7846, 7853, 10463, 10456, 10465, 10458, 10457, + 10455, 10462, 10359, 10357, 10362, 10464, 10513, 10368, 10480, 17118, + 17120, 17117, 17116, 17113, 17112, 17115, 17114, 17121, 17119, 17082, + 17081, 17092, 17078, 17086, 17085, 17099, 17079, 17088, 17074, 17080, + 17084, 17083, 17094, 17091, 17089, 17095, 17098, 17093, 17097, 17087, + 17075, 17096, 17090, 17100, 17076, 17101, 17077, 17110, 17107, 17109, + 17108, 17111, 17106, 17104, 17105, 17102, 17103, 27041, 27038, 27032, + 27046, 27037, 27034, 27043, 27035, 27028, 27036, 27040, 27030, 27045, + 27044, 27042, 27048, 27047, 27039, 27027, 27031, 27033, 27029, 27049, + 27056, 27058, 27051, 27054, 27057, 27055, 27053, 27052, 27024, 27023, + 27026, 27025, 27059, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 27050, 14774, 14777, 14778, 14775, 14732, + 14733, 14741, 14735, 14737, 14740, 14734, 14730, 14736, 14738, 14731, + 14697, 14699, 14700, 14713, 14720, 14727, 14762, 14679, 14686, 14760, + 14764, 14710, 14783, 14766, 35762, 35762, 35762, 16437, 16435, 16439, + 16438, 16409, 16377, 16376, 16378, 16418, 16397, 16383, 16384, 16416, + 16410, 16417, 16379, 16380, 16381, 16393, 16394, 16382, 16391, 16392, + 16407, 16386, 16408, 16385, 16405, 16406, 16372, 16373, 16388, 16403, + 16404, 16374, 16375, 16387, 16395, 16396, 16389, 16390, 16413, 16415, + 16398, 16399, 16412, 16414, 16401, 16402, 16400, 16411, 16436, 16442, + 16444, 16445, 16446, 16440, 16441, 16443, 16448, 16447, 16368, 16369, + 16370, 16433, 16371, 16419, 16422, 16431, 16424, 16429, 16427, 16425, + 16423, 16420, 16421, 16426, 16434, 35762, 16432, 16455, 16457, 16454, + 16453, 16450, 16449, 16452, 16451, 16458, 16456, 35762, 35762, 35762, + 35762, 16428, 16430, 23922, 23920, 23915, 23912, 23918, 23998, 23986, + 23938, 23950, 23946, 23945, 23948, 23947, 23940, 23939, 23937, 24040, + 24042, 24039, 24038, 24035, 24034, 24037, 24036, 24043, 24041, 23949, + 23942, 23941, 23944, 23943, 35762, 5944, 5962, 5964, 5961, 5945, 5963, + 5953, 5952, 5949, 5948, 5924, 5925, 5947, 5946, 5951, 5950, 5926, 5928, + 5927, 5955, 5954, 5941, 5940, 5929, 5930, 5939, 5935, 5934, 5933, 5938, + 5937, 5931, 5932, 5936, 5960, 5958, 5957, 5959, 5942, 5943, 5956, 5969, + 5972, 5973, 5978, 5976, 5975, 5974, 5970, 5971, 5977, 5912, 5910, 5909, + 5911, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 5918, 5917, 5914, 5906, 5916, 5922, 5913, 5920, 5923, 5921, 5919, 5915, + 5908, 5907, 35762, 35762, 5985, 5987, 5984, 5983, 5980, 5979, 5982, 5981, + 5988, 5986, 35762, 35762, 5965, 5967, 5966, 5968, 23892, 23885, 23884, + 23889, 23888, 23882, 23881, 23880, 23878, 23877, 23879, 23883, 23894, + 23887, 23886, 23891, 23985, 23895, 23896, 23893, 23982, 23983, 23984, + 24013, 24015, 24014, 23867, 24009, 24000, 24001, 23931, 23932, 30279, + 30255, 30278, 30254, 30277, 30253, 30292, 30268, 30286, 30262, 30281, + 30257, 30280, 30256, 30297, 30273, 30287, 30263, 30290, 30266, 30285, + 30261, 30284, 30260, 30288, 30264, 30289, 30265, 30283, 30259, 30282, + 30258, 30291, 30267, 30295, 30271, 30299, 30275, 30296, 30272, 30294, + 30270, 30298, 30274, 30293, 30269, 30300, 30276, 30301, 30313, 30321, + 30318, 30317, 30323, 30324, 30302, 30322, 30319, 30320, 30312, 30316, + 30315, 30314, 30311, 30308, 30309, 30310, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 30304, 30305, 30307, 30306, 30303, 22359, 22360, 22318, 22335, 22346, + 22345, 22322, 22321, 22334, 22340, 22341, 22373, 22375, 22365, 22367, + 22366, 22313, 22310, 22312, 22362, 22363, 22377, 22378, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 12895, 12893, + 12892, 12891, 12890, 12894, 35762, 35762, 12589, 12587, 12586, 12585, + 12584, 12588, 35762, 35762, 12604, 12602, 12601, 12600, 12599, 12603, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 12545, + 12551, 12549, 12546, 12548, 12547, 12550, 35762, 12530, 12536, 12534, + 12531, 12533, 12532, 12535, 35762, 18776, 18752, 18782, 18777, 18873, + 19035, 19223, 19025, 19016, 19019, 19046, 19060, 18887, 18780, 18781, + 19130, 18981, 19272, 19271, 19273, 19274, 19233, 18672, 19177, 18835, + 19157, 18836, 19220, 19221, 18779, 19343, 19309, 19352, 19295, 19348, + 18799, 18800, 18801, 19384, 19381, 19382, 19383, 19395, 23002, 23225, + 23234, 23235, 23292, 19214, 18984, 19131, 19354, 18980, 14005, 18842, + 19304, 19277, 23289, 23138, 23162, 35762, 35762, 35762, 35762, 6167, + 6168, 6169, 6170, 6171, 6172, 6130, 6166, 6131, 6132, 6133, 6134, 6135, + 6095, 6096, 6097, 6098, 6099, 6100, 6136, 6137, 6138, 6139, 6140, 6141, + 6142, 6143, 6144, 6145, 6146, 6101, 6094, 6102, 6103, 6104, 6105, 6106, + 6107, 6148, 6149, 6150, 6151, 6152, 6153, 6109, 6108, 6110, 6111, 6112, + 6113, 6114, 6088, 6127, 6089, 6128, 6090, 6129, 6091, 6092, 6093, 6087, + 6115, 6116, 6117, 6118, 6119, 6120, 6121, 6122, 6123, 6124, 6125, 6126, + 6154, 6155, 6156, 6157, 6158, 6159, 6160, 22327, 22339, 22349, 22351, + 22336, 22330, 22317, 22342, 22329, 22332, 22344, 22355, 22357, 22353, + 22358, 22347, 22338, 22356, 22324, 22325, 22354, 22316, 22326, 22320, + 22323, 22319, 22315, 22328, 22350, 22352, 22337, 22331, 22343, 22333, + 22348, 22369, 22372, 22364, 22371, 22370, 22374, 22368, 22376, 22314, + 22361, 22311, 35762, 35762, 22385, 22387, 22384, 22383, 22380, 22379, + 22382, 22381, 22388, 22386, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 14971, 14969, 15002, 15003, + 15004, 14980, 14981, 15013, 15015, 14948, 14946, 14945, 14949, 14955, + 14956, 14958, 14957, 14962, 14959, 14960, 14964, 14932, 14930, 35762, + 35762, 35762, 35762, 14828, 14829, 14897, 14898, 14917, 14911, 14912, + 14915, 14914, 14913, 14872, 14857, 14896, 14863, 14867, 14866, 14880, + 14879, 14800, 14825, 14818, 14903, 14816, 14823, 14853, 14846, 14852, + 14907, 14848, 14851, 14850, 14891, 14884, 14901, 14902, 14890, 14888, + 14887, 14892, 14894, 14839, 14838, 14924, 14925, 14789, 14788, 14904, + 14843, 14841, 35762, 35762, 35762, 35762, 7281, 7282, 7283, 7284, 7285, + 7286, 7287, 7288, 7289, 7290, 7291, 7292, 7293, 7294, 7295, 7296, 7297, + 7298, 7299, 7300, 7301, 7302, 7303, 7304, 7305, 7306, 7307, 7308, 7309, + 7310, 7311, 7312, 7313, 7314, 7315, 7316, 7317, 7318, 7319, 7320, 7321, + 7322, 7323, 7324, 7325, 7326, 7327, 7328, 7329, 7330, 7331, 7332, 7333, + 7334, 7335, 7336, 7337, 7338, 7339, 7340, 7341, 7342, 7343, 7344, 7345, + 7346, 7347, 7348, 7349, 7350, 7351, 7352, 7353, 7354, 7355, 7356, 7357, + 7358, 7359, 7360, 7361, 7362, 7363, 7364, 7365, 7366, 7367, 7368, 7369, + 7370, 7371, 7372, 7373, 7374, 7375, 7376, 7377, 7378, 7379, 7380, 7381, + 7382, 7383, 7384, 7385, 7386, 7387, 7388, 7389, 7390, 7391, 7392, 7393, + 7394, 7395, 7396, 7397, 7398, 7399, 7400, 7401, 7402, 7403, 7404, 7405, + 7406, 7407, 7408, 7409, 7410, 7411, 7412, 7413, 7414, 7415, 7416, 7417, + 7418, 7419, 7420, 7421, 7422, 7423, 7424, 7425, 7426, 7427, 7428, 7429, + 7430, 7431, 7432, 7433, 7434, 7435, 7436, 7437, 7438, 7439, 7440, 7441, + 7442, 7443, 7444, 7445, 7446, 7447, 7448, 7449, 7450, 7451, 7452, 7453, + 7454, 7455, 7456, 7457, 7458, 7459, 7460, 7461, 7462, 7463, 7464, 7465, + 7466, 7467, 7468, 7469, 7470, 7471, 7472, 7473, 7474, 7475, 7476, 7477, + 7478, 7479, 7480, 7481, 7482, 7483, 7484, 7485, 7486, 7487, 7488, 7489, + 7490, 7491, 7492, 7493, 7494, 7495, 7496, 7497, 7498, 7499, 7500, 7501, + 7502, 7503, 7504, 7505, 7506, 7507, 7508, 7509, 7510, 7511, 7512, 7513, + 7514, 7515, 7516, 7517, 7518, 7519, 7520, 7521, 7522, 7523, 7524, 7525, + 7526, 7527, 7528, 7529, 7530, 7531, 7532, 7533, 7534, 7535, 7536, 7079, + 7080, 7081, 7082, 7083, 7084, 7085, 7086, 7087, 7088, 7089, 7090, 7091, + 7092, 7093, 7094, 7095, 7096, 7097, 7098, 7099, 7100, 7101, 7102, 7103, + 7104, 7105, 7106, 7107, 7108, 7109, 7110, 7111, 7112, 7113, 7114, 7115, + 7116, 7117, 7118, 7119, 7120, 7121, 7122, 7123, 7124, 7125, 7126, 7127, + 7128, 7129, 7130, 7131, 7132, 7133, 7134, 7135, 7136, 7137, 7138, 7139, + 7140, 7141, 7142, 7143, 7144, 7145, 7146, 7147, 7148, 7149, 7150, 7151, + 7152, 7153, 7154, 7155, 7156, 7157, 7158, 7159, 7160, 7161, 7162, 7163, + 7164, 7165, 7166, 7167, 7168, 7169, 7170, 7171, 7172, 7173, 7174, 7065, + 7066, 7067, 7068, 7069, 7070, 7071, 7072, 7073, 7074, 7075, 7076, 7077, + 7078, 35762, 35762, 7175, 7176, 7177, 7178, 7179, 7180, 7181, 7182, 7183, + 7184, 7185, 7186, 7187, 7188, 7189, 7190, 7191, 7192, 7193, 7194, 7195, + 7196, 7197, 7198, 7199, 7200, 7201, 7202, 7203, 7204, 7205, 7206, 7207, + 7208, 7209, 7210, 7211, 7212, 7213, 7214, 7215, 7216, 7217, 7218, 7219, + 7220, 7221, 7222, 7223, 7224, 7225, 7226, 7227, 7228, 7229, 7230, 7231, + 7232, 7233, 7234, 7235, 7236, 7237, 7238, 7239, 7240, 7241, 7242, 7243, + 7244, 7245, 7246, 7247, 7248, 7249, 7250, 7251, 7252, 7253, 7254, 7255, + 7256, 7257, 7258, 7259, 7260, 7261, 7262, 7263, 7264, 7265, 7266, 7267, + 7268, 7269, 7270, 7271, 7272, 7273, 7274, 7275, 7276, 7277, 7278, 7279, + 7280, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 19417, + 19420, 19421, 19418, 19419, 19423, 19424, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 2490, 2491, 2489, + 2492, 2488, 35762, 35762, 35762, 35762, 35762, 15435, 15453, 15440, + 15371, 15427, 15430, 15432, 15431, 15426, 15433, 15429, 15428, 15372, + 15405, 15406, 15403, 15404, 15369, 15370, 15368, 15376, 15418, 15416, + 15393, 15425, 15398, 35762, 15410, 15436, 15384, 15379, 15420, 35762, + 15422, 35762, 15396, 15400, 35762, 15386, 15382, 35762, 15414, 15391, + 15408, 15402, 15412, 15424, 15375, 15378, 15381, 15437, 1146, 1145, 1176, + 1174, 1175, 1177, 1403, 1401, 1402, 1404, 1171, 1169, 1170, 1172, 1532, + 1530, 1531, 1533, 1512, 1510, 1511, 1513, 1527, 1525, 1526, 1528, 1545, + 1543, 1544, 1546, 1408, 1406, 1407, 1409, 1211, 1209, 1210, 1212, 1381, + 1379, 1380, 1382, 1489, 1487, 1488, 1490, 1494, 1492, 1493, 1495, 1201, + 1200, 1192, 1191, 1215, 1214, 1204, 1203, 1311, 1310, 1438, 1437, 1333, + 1331, 1332, 1334, 1245, 1243, 1244, 1246, 1257, 1255, 1256, 1258, 1372, + 1370, 1371, 1373, 1386, 1385, 1442, 1440, 1441, 1443, 1287, 1286, 1282, + 1280, 1281, 1283, 1291, 1289, 1290, 1292, 1569, 1568, 1567, 1566, 2352, + 2351, 2360, 2359, 2356, 2355, 2354, 2353, 2364, 2363, 2350, 2358, 2357, + 2366, 2362, 2361, 2365, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 1376, + 1374, 1375, 1377, 1538, 1537, 1590, 1589, 1587, 1586, 1536, 1548, 1547, + 1337, 1336, 1340, 1339, 1603, 1601, 1602, 1604, 1539, 1540, 2043, 2042, + 2045, 2044, 2064, 2063, 2072, 2071, 2062, 2061, 2068, 2067, 2048, 2046, + 2047, 2097, 2095, 2096, 1225, 1223, 1224, 1226, 2054, 2052, 2058, 2041, + 2066, 1645, 1636, 1641, 1648, 1643, 1654, 2006, 1994, 2001, 2014, 2017, + 2022, 2024, 2029, 2026, 2035, 1723, 1729, 1708, 1703, 1762, 1758, 1764, + 1913, 1906, 1918, 1926, 1885, 1889, 1667, 1659, 1663, 1669, 1987, 1982, + 2099, 1616, 1612, 1697, 1693, 1681, 1686, 1677, 1684, 1679, 1688, 1867, + 1863, 1865, 1869, 1738, 1740, 1748, 1746, 1743, 1754, 1736, 1757, 1790, + 1782, 1794, 1800, 1774, 1803, 1821, 1810, 1815, 1825, 1804, 1826, 1842, + 1832, 1854, 1847, 1850, 1857, 1718, 1714, 1715, 1716, 2082, 2075, 2084, + 2090, 2039, 2094, 2023, 1880, 1628, 1934, 1937, 1941, 1935, 1938, 1940, + 2070, 2069, 2056, 2060, 2040, 2065, 1652, 1651, 1646, 1650, 1642, 1653, + 2020, 2019, 2012, 2018, 2016, 2021, 2033, 2032, 2027, 2031, 2025, 2034, + 1678, 1687, 1864, 1868, 1737, 1741, 1752, 1735, 1756, 1798, 1773, 1802, + 1805, 1823, 1855, 1852, 1845, 1851, 1849, 1856, 1627, 2092, 2079, 2088, + 2078, 2038, 2093, 2053, 2051, 2055, 2057, 2049, 1644, 1635, 1640, 1647, + 1637, 2005, 1993, 2000, 2013, 1995, 2028, 1722, 1728, 1707, 1702, 1761, + 1763, 1912, 1905, 1917, 1925, 1884, 1892, 1888, 1666, 1658, 1662, 1668, + 1986, 2098, 1615, 1611, 1696, 1692, 1680, 1685, 1676, 1683, 1866, 1862, + 1739, 1747, 1745, 1742, 1753, 1789, 1781, 1793, 1799, 1783, 1820, 1809, + 1814, 1824, 1841, 1831, 1853, 1846, 1833, 1717, 1713, 1719, 2081, 2074, + 2083, 2089, 2076, 2059, 2050, 1649, 1638, 2015, 1996, 2030, 2036, 1927, + 1909, 1964, 1944, 1744, 1755, 1801, 1848, 1834, 2091, 2077, 1942, 1936, + 1939, 1985, 1989, 1618, 1620, 1695, 1699, 1929, 1933, 1966, 1974, 1705, + 1710, 1731, 1733, 1760, 1766, 1891, 1896, 1665, 1673, 1955, 1950, 1969, + 1963, 1972, 1931, 1894, 1671, 1984, 1988, 1617, 1619, 1694, 1698, 1928, + 1932, 1965, 1973, 1704, 1709, 1730, 1732, 1759, 1765, 1890, 1895, 1664, + 1672, 1953, 1948, 1967, 1961, 1971, 1930, 1893, 1670, 1954, 1949, 1968, + 1962, 1908, 1943, 1981, 1914, 1907, 1919, 1956, 1951, 1970, 1983, 2100, + 1629, 1630, 25893, 25894, 1877, 1872, 1876, 1873, 1874, 1875, 1903, 1622, + 1624, 1623, 1621, 1871, 1902, 1625, 1976, 1878, 2003, 1992, 1991, 1990, + 1998, 2008, 2010, 2009, 1725, 1724, 1701, 1700, 1904, 1911, 1910, 1921, + 1920, 1922, 1924, 1923, 1882, 1881, 1887, 1946, 1945, 1952, 1958, 1957, + 1960, 1959, 1656, 1661, 1660, 1978, 1977, 1979, 1980, 1614, 1609, 1608, + 1607, 1689, 1691, 1690, 1675, 1674, 1860, 1858, 1779, 1780, 1777, 1784, + 1785, 1792, 1791, 1796, 1795, 1806, 1807, 1808, 1818, 1816, 1811, 1812, + 35762, 35762, 1817, 1711, 1712, 1829, 1828, 1839, 1838, 1837, 1844, 1843, + 2086, 2085, 1639, 2004, 2002, 1999, 1997, 2011, 2007, 1727, 1720, 1726, + 1915, 1883, 1947, 1657, 1788, 1797, 2073, 2080, 2087, 1822, 1861, 1830, + 1859, 1778, 1610, 1751, 1835, 1813, 1786, 1750, 1787, 1836, 1721, 1706, + 1819, 1682, 1634, 1749, 1613, 1886, 1916, 1840, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 1898, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 1899, 1870, 1631, 1632, + 1827, 1897, 1879, 1626, 2037, 1900, 1901, 1734, 27339, 1655, 1975, 1633, + 33083, 33194, 33262, 33273, 33284, 33295, 33306, 33317, 33328, 33084, + 33095, 33106, 33117, 33128, 33139, 33150, 26827, 26832, 26833, 26826, + 26857, 26828, 26859, 26835, 26849, 26831, 35762, 35762, 35762, 35762, + 35762, 35762, 8057, 8059, 7889, 7890, 8068, 8070, 7783, 8058, 8060, 8126, + 8127, 8069, 8071, 7784, 7837, 7838, 26858, 26829, 26830, 26844, 26856, + 26841, 26853, 26839, 26851, 26843, 26855, 26836, 26845, 26837, 26846, + 26840, 26852, 26838, 26850, 26834, 26847, 27753, 34075, 26842, 26854, + 10235, 5828, 33955, 10947, 10234, 5827, 33953, 28892, 28901, 28935, + 35762, 28926, 28893, 28936, 28899, 28900, 28903, 28907, 28902, 28906, + 28904, 28908, 28934, 28883, 28885, 28933, 28931, 28905, 28930, 28898, + 35762, 28925, 28894, 28932, 28891, 35762, 35762, 35762, 35762, 1080, + 2371, 1062, 2373, 1092, 35762, 1077, 1078, 1058, 1059, 1089, 1090, 2278, + 2279, 2346, 2347, 1276, 1141, 1140, 1131, 1130, 1556, 1555, 1134, 1133, + 1573, 1571, 1572, 1574, 1151, 1150, 1166, 1164, 1165, 1167, 1499, 1498, + 1508, 1506, 1507, 1501, 1520, 1518, 1519, 1521, 1307, 1305, 1306, 1308, + 1273, 1271, 1272, 1274, 1344, 1342, 1343, 1345, 1189, 1188, 1516, 1515, + 1435, 1434, 1598, 1597, 1464, 1462, 1463, 1465, 1470, 1468, 1469, 1471, + 1451, 1449, 1450, 1452, 1197, 1195, 1196, 1198, 1482, 1480, 1481, 1483, + 1594, 1592, 1593, 1595, 1109, 1107, 1108, 1110, 1252, 1250, 1251, 1253, + 1236, 1234, 1235, 1237, 1417, 1415, 1416, 1418, 1320, 1318, 1319, 1321, + 1356, 1354, 1355, 1357, 1365, 1363, 1364, 1366, 1396, 1394, 1395, 1397, + 1295, 1293, 1294, 1296, 1560, 1559, 1149, 1148, 1583, 1581, 1582, 1584, + 1772, 1771, 1768, 1767, 1770, 1769, 1776, 1775, 35762, 35762, 35566, + 35762, 13299, 13303, 13271, 13287, 13273, 13285, 13284, 13214, 13277, + 13286, 13274, 13209, 13302, 13308, 13281, 13294, 13296, 13293, 13292, + 13289, 13288, 13291, 13290, 13297, 13295, 13210, 13280, 13216, 13298, + 13301, 13304, 13208, 13217, 13218, 13219, 13220, 13221, 13222, 13223, + 13224, 13225, 13226, 13227, 13228, 13229, 13230, 13231, 13232, 13233, + 13234, 13235, 13236, 13237, 13238, 13239, 13240, 13241, 13242, 13215, + 13279, 13278, 13207, 13269, 13300, 13243, 13244, 13245, 13246, 13247, + 13248, 13249, 13250, 13251, 13252, 13253, 13254, 13255, 13256, 13257, + 13258, 13259, 13260, 13261, 13262, 13263, 13264, 13265, 13266, 13267, + 13268, 13212, 13309, 13275, 13306, 13213, 13276, 14644, 14637, 14639, + 14643, 14635, 14627, 14582, 14584, 14586, 14583, 14585, 14578, 14580, + 14579, 14581, 14636, 14628, 14630, 14632, 14629, 14631, 14603, 14605, + 14607, 14604, 14606, 14587, 14589, 14591, 14588, 14590, 14618, 14620, + 14622, 14619, 14621, 14593, 14595, 14597, 14594, 14596, 14598, 14600, + 14602, 14599, 14601, 14608, 14610, 14612, 14609, 14611, 14623, 14625, + 14624, 14613, 14615, 14617, 14614, 14616, 14626, 14592, 14634, 14633, + 14577, 14527, 14544, 14528, 14529, 14530, 14531, 14565, 14546, 14535, + 14540, 14539, 14538, 14542, 14536, 14537, 14541, 14563, 14533, 14545, + 14534, 14548, 14547, 14562, 14557, 14543, 14556, 14526, 14564, 14532, + 14571, 35762, 35762, 35762, 14572, 14573, 14551, 14552, 14559, 14558, + 35762, 35762, 14550, 14549, 14574, 14568, 14569, 14575, 35762, 35762, + 14554, 14576, 14567, 14566, 14570, 14555, 35762, 35762, 14560, 14553, + 14561, 35762, 35762, 35762, 13211, 13272, 13270, 13283, 13307, 13282, + 13305, 35762, 14642, 14638, 14641, 14640, 14647, 14645, 14646, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 16324, + 16326, 16325, 25221, 27062, 35762, 35762, 20348, 20374, 20367, 20400, + 20358, 20349, 20378, 20344, 20356, 20386, 20389, 20383, 35762, 20372, + 20399, 20403, 20382, 20397, 20404, 20411, 20414, 20359, 20410, 20357, + 20360, 20343, 20366, 20369, 20392, 20393, 20351, 20408, 20373, 20354, + 20390, 20352, 20409, 20368, 20376, 35762, 20401, 20365, 20385, 20350, + 20361, 20375, 20346, 20380, 20355, 20387, 20388, 20345, 20371, 20347, + 20398, 20391, 20405, 20379, 20381, 35762, 20353, 20407, 35762, 20364, + 20363, 20377, 20413, 20406, 20416, 20384, 20362, 20394, 20402, 20370, + 20395, 20396, 20412, 20415, 35762, 35762, 20426, 20427, 20429, 20428, + 20417, 20418, 20425, 20419, 20420, 20430, 20421, 20422, 20423, 20424, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 20232, 20231, 20233, 20220, 20221, 20222, + 20223, 20224, 20225, 20226, 20228, 20227, 20230, 20229, 20238, 20235, + 20236, 20234, 20237, 20337, 20338, 20240, 20239, 20241, 20340, 20339, + 20243, 20244, 20245, 20242, 20246, 20249, 20248, 20250, 20251, 20252, + 20341, 20253, 20254, 20247, 20257, 20258, 20256, 20255, 20259, 20260, + 20261, 20262, 20263, 20264, 20267, 20268, 20269, 20266, 20270, 20265, + 20271, 20272, 20273, 20274, 20275, 20276, 20277, 20278, 20279, 20280, + 20282, 20281, 20283, 20284, 20286, 20287, 20288, 20285, 20289, 20290, + 20291, 20292, 20294, 20293, 20295, 20296, 20342, 20297, 20298, 20300, + 20301, 20302, 20299, 20303, 20304, 20305, 20306, 20307, 20335, 20315, + 20316, 20317, 20318, 20319, 20320, 20321, 20322, 20323, 20324, 20325, + 20326, 20327, 20328, 20329, 20330, 20331, 20332, 20333, 20334, 20308, + 20309, 20310, 20311, 20312, 20313, 20314, 20336, 35762, 35762, 35762, + 35762, 35762, 112, 113, 159, 35762, 35762, 35762, 35762, 156, 151, 146, + 126, 121, 139, 134, 114, 129, 154, 149, 144, 124, 119, 140, 135, 115, + 130, 157, 152, 147, 127, 122, 142, 137, 117, 132, 158, 153, 148, 128, + 123, 143, 138, 118, 133, 155, 150, 145, 125, 120, 141, 136, 116, 131, + 35762, 35762, 35762, 111, 107, 109, 110, 108, 103, 104, 105, 106, 13770, + 13767, 13771, 13757, 13752, 13758, 13761, 13753, 13763, 13772, 13755, + 13765, 13759, 13768, 13762, 13764, 13774, 13756, 13766, 13760, 13769, + 13773, 13754, 13775, 13787, 13796, 13786, 13782, 13795, 13777, 13783, + 13799, 13803, 13804, 13785, 13788, 13794, 13793, 13801, 13802, 13784, + 13791, 13797, 13792, 13781, 13800, 13789, 13776, 13778, 13798, 13790, + 13779, 13780, 14022, 14023, 14221, 14217, 14258, 14223, 13953, 14027, + 14220, 14216, 13959, 13958, 14019, 14001, 14017, 14026, 14021, 13807, + 13806, 14260, 14219, 14261, 14024, 14215, 13997, 24651, 35762, 27384, + 27387, 27382, 27385, 27356, 27386, 27354, 27357, 27383, 27355, 27388, + 27353, 2510, 35762, 35762, 35762, 14214, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 26611, 26612, 26623, 26592, 26595, 26626, 26604, + 26603, 26624, 26631, 26590, 26617, 26596, 26609, 26610, 26619, 26608, + 26589, 26593, 26600, 26598, 26620, 26597, 26588, 26618, 26605, 26606, + 26591, 26594, 26616, 26630, 26601, 26625, 26587, 26613, 26632, 26614, + 26615, 26607, 26629, 26628, 26602, 26621, 26622, 26627, 26599, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 20605, + 20607, 20600, 20601, 20612, 20611, 20614, 20622, 20624, 20603, 20615, + 20598, 20618, 20616, 20596, 20609, 20597, 20610, 20621, 20617, 20599, + 20619, 20620, 20602, 20604, 20606, 20608, 20613, 20623, 35762, 35762, + 35762, 5738, 5749, 5740, 5711, 5734, 5750, 5712, 5739, 5756, 5754, 5714, + 5755, 5741, 5729, 5724, 5725, 5723, 5709, 5732, 5722, 5757, 5719, 5731, + 5748, 5728, 5752, 5742, 5737, 5746, 5747, 5720, 5733, 5744, 5745, 5726, + 5727, 5721, 5753, 5710, 5730, 5735, 5751, 5715, 5716, 5717, 5718, 5713, + 5743, 5736, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 8241, 8267, 8265, 8264, + 8261, 8260, 8263, 8262, 8268, 8266, 8259, 8258, 8256, 8247, 8245, 8254, + 8252, 8243, 8249, 8250, 8257, 8255, 8246, 8244, 8253, 8251, 8242, 8248, + 35762, 35762, 35762, 35762, 25459, 25453, 25439, 25454, 25426, 25456, + 25458, 25455, 25450, 25446, 25438, 25434, 25435, 25436, 25428, 25460, + 25449, 25442, 25440, 25430, 25427, 25451, 25444, 25432, 25448, 25437, + 25433, 25431, 25452, 25447, 25445, 25429, 25464, 25462, 25463, 25461, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 25457, + 25443, 25441, 13617, 13633, 13641, 13635, 13616, 13626, 13620, 13619, + 13628, 13638, 13642, 13639, 13636, 13624, 13640, 13631, 13625, 13623, + 13627, 13637, 13629, 13630, 13632, 13621, 13618, 13634, 13622, 35762, + 35762, 35762, 35762, 35762, 25531, 25530, 25527, 25500, 25501, 25523, + 25498, 25524, 25499, 25503, 25532, 25525, 25506, 25507, 25514, 25508, + 25526, 25511, 25513, 25534, 25497, 25510, 25509, 25521, 25518, 25528, + 25529, 25502, 25533, 25512, 25515, 25516, 25517, 25520, 25505, 25522, + 25519, 25504, 8083, 8081, 8079, 8080, 8082, 35762, 35762, 35762, 35762, + 35762, 32585, 32588, 32592, 32596, 32589, 32593, 32611, 32607, 32594, + 32604, 32606, 32595, 32601, 32597, 32612, 32590, 32609, 32608, 32600, + 32586, 32610, 32599, 32587, 32598, 32603, 32591, 32605, 32613, 32614, + 32602, 35762, 32615, 25540, 25582, 25583, 25563, 25564, 25561, 25562, + 25560, 25575, 25552, 25553, 25557, 25558, 25547, 25550, 25551, 25556, + 25579, 25544, 25576, 25565, 25566, 25569, 25570, 25571, 25580, 25554, + 25555, 25567, 25568, 25578, 25574, 25581, 25572, 25573, 25577, 35762, + 35762, 35762, 35762, 25541, 25542, 25543, 25559, 25548, 25549, 25545, + 25546, 25584, 25539, 25536, 25537, 25535, 25538, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 10286, + 10285, 10281, 10282, 10283, 10284, 10292, 10291, 10287, 10288, 10289, + 10290, 10309, 10294, 10308, 10305, 10310, 10303, 10300, 10296, 10301, + 10299, 10302, 10307, 10306, 10276, 10304, 10275, 10295, 10271, 10298, + 10272, 10297, 10279, 10277, 10278, 10273, 10274, 10293, 10280, 10326, + 10325, 10321, 10322, 10323, 10324, 10332, 10331, 10327, 10328, 10329, + 10330, 10349, 10334, 10348, 10345, 10350, 10343, 10340, 10336, 10341, + 10339, 10342, 10347, 10346, 10316, 10344, 10315, 10335, 10311, 10338, + 10312, 10337, 10319, 10317, 10318, 10313, 10314, 10333, 10320, 27890, + 27896, 27907, 27904, 27894, 27893, 27892, 27871, 27899, 27877, 27906, + 27902, 27905, 27908, 27895, 27903, 27882, 27901, 27898, 27876, 27881, + 27883, 27880, 27875, 27869, 27866, 27888, 27897, 27886, 27870, 27891, + 27909, 27873, 27867, 27879, 27910, 27887, 27884, 27885, 27868, 27864, + 27889, 27865, 27874, 27863, 27872, 27878, 27900, 25971, 25989, 25995, + 25993, 25996, 25977, 25974, 25994, 25979, 25978, 25975, 25973, 25991, + 25990, 25981, 25976, 25984, 25980, 25985, 25986, 25992, 25997, 25970, + 25987, 25998, 25982, 25999, 25972, 25988, 25983, 35762, 35762, 26006, + 26008, 26005, 26004, 26001, 26000, 26003, 26002, 26009, 26007, 35762, + 35762, 35762, 35762, 35762, 35762, 25898, 25899, 25900, 25901, 25926, + 25919, 25905, 25902, 25908, 25918, 25917, 25932, 25911, 25906, 25910, + 25927, 25928, 25929, 25912, 25913, 25930, 25907, 25923, 25922, 25916, + 25904, 25915, 25903, 25914, 25920, 25933, 25931, 25909, 25921, 25925, + 25924, 35762, 35762, 35762, 35762, 25934, 25935, 25936, 25937, 25962, + 25955, 25941, 25938, 25944, 25954, 25953, 25968, 25947, 25942, 25946, + 25963, 25964, 25965, 25948, 25949, 25966, 25943, 25959, 25958, 25952, + 25940, 25951, 25939, 25950, 25956, 25969, 25967, 25945, 25957, 25961, + 25960, 35762, 35762, 35762, 35762, 12376, 12367, 12356, 12355, 12358, + 12347, 12357, 12354, 12353, 12368, 12344, 12343, 12369, 12377, 12370, + 12360, 12346, 12345, 12371, 12350, 12349, 12348, 12378, 12372, 12373, + 12352, 12351, 12362, 12361, 12364, 12363, 12379, 12374, 12375, 12380, + 12366, 12365, 12342, 12341, 12359, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 5770, 5819, 5786, 5782, 5784, 5809, 5783, 5807, + 5804, 5773, 5806, 5808, 5787, 5798, 5794, 5789, 5817, 5781, 5772, 5790, + 5793, 5795, 5820, 5811, 5769, 5775, 5776, 5778, 5812, 5810, 5815, 5779, + 5799, 5791, 5818, 5803, 5814, 5780, 5774, 5797, 5785, 5816, 5801, 5813, + 5802, 5800, 5788, 5777, 5771, 5805, 5796, 5792, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 5821, 33727, + 33696, 33697, 33707, 33706, 33709, 33708, 33699, 33698, 33716, 33724, + 35762, 33715, 33714, 33700, 33701, 33717, 33725, 33703, 33702, 33718, + 33705, 33704, 33728, 33719, 33726, 33720, 35762, 33711, 33710, 33713, + 33712, 33729, 33721, 33722, 35762, 33730, 33723, 35762, 33762, 33731, + 33732, 33742, 33741, 33744, 33743, 33734, 33733, 33751, 33759, 35762, + 33750, 33749, 33735, 33736, 33752, 33760, 33738, 33737, 33753, 33740, + 33739, 33763, 33754, 33761, 33755, 35762, 33746, 33745, 33748, 33747, + 33764, 33756, 33757, 35762, 33765, 33758, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 20199, 20200, 20201, 20202, 20203, 20204, 20205, + 20206, 20207, 20138, 20139, 20140, 20141, 20142, 20151, 20143, 20144, + 20145, 20146, 20147, 20148, 20149, 20150, 20152, 20153, 20154, 20155, + 20219, 20156, 20157, 20158, 20159, 20160, 20161, 20162, 20163, 20164, + 20165, 20166, 20167, 20168, 20169, 20170, 20171, 20172, 20173, 20174, + 20175, 20176, 20177, 20178, 20179, 20180, 20181, 20182, 20183, 20184, + 20185, 20186, 20187, 20188, 20189, 20190, 20191, 20192, 20193, 20194, + 20195, 20196, 20197, 20198, 19879, 20215, 20208, 19880, 20209, 20210, + 20211, 20212, 19881, 20216, 20217, 20213, 20214, 20218, 19885, 19886, + 19887, 19888, 19889, 19890, 19891, 19892, 19882, 19883, 19884, 19896, + 19897, 19898, 19893, 19894, 19895, 19899, 19900, 19901, 19902, 19903, + 19904, 19907, 19908, 19909, 19910, 19911, 19912, 19913, 19914, 19915, + 19916, 19917, 19918, 19919, 19920, 19921, 19922, 19923, 19924, 19925, + 19926, 19927, 19928, 19929, 19930, 19931, 19932, 19933, 19934, 19935, + 19936, 19937, 19938, 19939, 19940, 19941, 19942, 19943, 19944, 19945, + 19946, 19947, 19948, 19949, 19950, 19951, 19952, 19953, 19954, 19955, + 19956, 19905, 19906, 19957, 19958, 19959, 19960, 19961, 19962, 19963, + 19964, 19965, 19966, 19967, 19968, 19969, 19970, 19971, 19972, 19973, + 19974, 19975, 19976, 19977, 19978, 19979, 19980, 19981, 19982, 19983, + 19984, 19985, 19986, 19987, 19988, 19989, 20021, 20022, 20023, 20024, + 20025, 20026, 20027, 20028, 20029, 19990, 19991, 19992, 19993, 19994, + 19995, 19996, 19997, 19998, 19999, 20000, 20001, 20002, 20003, 20004, + 20005, 20006, 20007, 20008, 20009, 20010, 20011, 20012, 20013, 20014, + 20015, 20016, 20017, 20018, 20019, 20020, 20036, 20037, 20038, 20039, + 20040, 20041, 20042, 20043, 20044, 20045, 20046, 20047, 20048, 20049, + 20050, 20051, 20052, 20053, 20054, 20055, 20030, 20031, 20032, 20033, + 20034, 20035, 20056, 20057, 20058, 20059, 20060, 20061, 20062, 20063, + 20098, 20099, 20100, 20101, 20102, 20103, 20104, 20105, 20106, 20107, + 20064, 20065, 20066, 20067, 20068, 20069, 20070, 20071, 20072, 20073, + 20074, 20075, 20076, 20077, 20078, 20079, 20080, 20081, 20082, 20083, + 20089, 20090, 20091, 20092, 20093, 20094, 20095, 20096, 20097, 20084, + 20085, 20086, 20087, 20088, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 20119, 20114, 20117, 20116, 20120, 20115, 20113, + 20118, 20112, 20108, 20111, 20110, 20109, 20126, 20121, 20125, 20122, + 20123, 20124, 20127, 20129, 20128, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 20130, 20131, 20132, 20133, 20134, + 20135, 20136, 20137, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 23185, 23306, 23305, + 23170, 23186, 23174, 35762, 23204, 23206, 23205, 23200, 23199, 23197, + 23198, 23259, 23192, 23216, 23256, 23180, 23220, 23181, 23224, 23187, + 23226, 23203, 23240, 23241, 23239, 23183, 23237, 23242, 23243, 23284, + 23285, 23248, 23184, 23193, 23299, 23281, 23282, 23255, 23254, 23189, + 23269, 23272, 23273, 23270, 23268, 23296, 35762, 23191, 23111, 23158, + 23006, 23089, 23118, 23003, 23160, 23261, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 9704, 9705, 9706, 9707, 9708, 9698, + 35762, 35762, 9699, 35762, 9654, 9655, 9656, 9657, 9658, 9659, 9660, + 9661, 9662, 9663, 9664, 9665, 9666, 9667, 9668, 9669, 9670, 9671, 9672, + 9673, 9674, 9675, 9676, 9677, 9678, 9679, 9680, 9681, 9682, 9683, 9684, + 9685, 9686, 9687, 9688, 9689, 9690, 9691, 9692, 9693, 9694, 9695, 9696, + 9697, 35762, 9702, 9703, 35762, 35762, 35762, 9700, 35762, 35762, 9701, + 16146, 16157, 16148, 16142, 16154, 16159, 16149, 16155, 16140, 16153, + 16156, 16143, 16161, 16158, 16150, 16147, 16160, 16151, 16144, 16145, + 16152, 16141, 35762, 16162, 16137, 16133, 16136, 16134, 16132, 16138, + 16139, 16135, 26241, 26252, 26243, 26237, 26249, 26254, 26244, 26250, + 26235, 26248, 26251, 26238, 26256, 26234, 26253, 26245, 26242, 26255, + 26246, 26239, 26240, 26247, 26236, 26233, 26257, 26264, 26259, 26260, + 26263, 26262, 26261, 26258, 24101, 24116, 24106, 24127, 24118, 24112, + 24108, 24124, 24129, 24119, 24125, 24110, 24104, 24123, 24105, 24126, + 24102, 24113, 24109, 24131, 24107, 24128, 24120, 24117, 24130, 24121, + 24114, 24115, 24103, 24122, 24111, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 24136, 24133, 24134, 24139, 24140, 24138, 24135, + 24132, 24137, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 15202, 15218, 15210, 15209, 15215, 15220, 15204, 15216, 15205, 15214, + 15217, 15207, 15222, 15219, 15211, 15203, 15221, 15212, 15208, 35762, + 15213, 15206, 35762, 35762, 35762, 35762, 35762, 15223, 15227, 15226, + 15225, 15224, 26635, 26654, 26650, 26637, 26638, 26646, 26647, 26639, + 26645, 26648, 26651, 26653, 26656, 26652, 26643, 26636, 26655, 26641, + 26640, 26649, 26642, 26644, 26661, 26660, 26657, 26662, 26658, 26659, + 35762, 35762, 35762, 26663, 20631, 20637, 20641, 20639, 20633, 20649, + 20642, 20650, 20643, 20627, 20644, 20635, 20645, 20647, 20630, 20625, + 20648, 20640, 20646, 20629, 20626, 20632, 20634, 20628, 20636, 20638, + 35762, 35762, 35762, 35762, 35762, 20651, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 22722, 22723, 22724, 22725, 22721, 22720, 22696, 22697, 22718, 22717, + 22700, 22701, 22702, 22703, 22698, 22699, 22716, 22713, 22712, 22704, + 22705, 22706, 22714, 22719, 22707, 22708, 22709, 22710, 22711, 22715, + 22726, 22727, 22618, 22639, 22640, 22641, 22638, 22637, 22630, 22634, + 22633, 22623, 22624, 22636, 22632, 22628, 22627, 22625, 22619, 22626, + 22629, 22635, 22620, 22621, 22622, 22631, 35762, 35762, 35762, 35762, + 22606, 22611, 22643, 22642, 22692, 22684, 22678, 22655, 22649, 22672, + 22666, 22644, 22661, 22690, 22688, 22682, 22659, 22653, 22676, 22670, + 35762, 35762, 22693, 22685, 22679, 22656, 22650, 22673, 22667, 22646, + 22663, 22695, 22687, 22681, 22658, 22652, 22675, 22669, 22648, 22665, + 22691, 22689, 22683, 22660, 22654, 22677, 22671, 22645, 22662, 22694, + 22686, 22680, 22657, 22651, 22674, 22668, 22647, 22664, 22610, 22616, + 22615, 22609, 22608, 22613, 22612, 22607, 22617, 22614, 17200, 17222, + 17224, 17220, 35762, 17221, 17223, 35762, 35762, 35762, 35762, 35762, + 17225, 17216, 17219, 17218, 17166, 17164, 17188, 17187, 35762, 17186, + 17185, 17194, 35762, 17174, 17170, 17169, 17177, 17176, 17173, 17172, + 17171, 17179, 17178, 17175, 17190, 17189, 17184, 17183, 17196, 17198, + 17197, 17195, 17192, 17180, 17181, 17182, 17199, 17193, 17165, 17167, + 17168, 17191, 35762, 35762, 17214, 17215, 17217, 35762, 35762, 35762, + 35762, 17226, 17163, 17162, 17161, 17160, 17202, 17201, 17203, 17204, + 17227, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 17208, 17213, + 17206, 17205, 17212, 17210, 17209, 17207, 17211, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 25648, 25644, 25649, 25654, 25645, 25652, + 25638, 25646, 25650, 25642, 25637, 25633, 25651, 25634, 25636, 25635, + 25653, 25626, 25627, 25629, 25632, 25630, 25631, 25641, 25643, 25628, + 25647, 25640, 25639, 25656, 25655, 25657, 25470, 25488, 25469, 25479, + 25491, 25492, 25481, 25485, 25483, 25476, 25480, 25472, 25487, 25471, + 25493, 25482, 25484, 25465, 25466, 25489, 25468, 25490, 25467, 25475, + 25477, 25473, 25486, 25474, 25478, 25496, 25495, 25494, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 20932, 20936, 20935, 20940, 20939, 20937, 20961, 20964, 20980, 20944, + 20943, 20942, 20941, 20962, 20954, 20960, 20946, 20956, 20945, 20958, + 20938, 20953, 20967, 20963, 20950, 20934, 20933, 20966, 20965, 20951, + 20948, 20957, 20947, 20959, 20952, 20949, 20955, 20982, 20981, 35762, + 35762, 35762, 35762, 20968, 20972, 20971, 20970, 20969, 20979, 20977, + 20975, 20974, 20973, 20978, 20976, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 2526, 2527, 2533, 2529, 2532, 2528, 2530, + 2531, 2569, 2570, 2559, 2560, 2561, 2562, 2557, 2558, 2574, 2547, 2546, + 2545, 2536, 2534, 2535, 2571, 2573, 2556, 2554, 2566, 2565, 2555, 2577, + 2572, 2564, 2563, 2541, 2540, 2539, 2544, 2543, 2542, 2576, 2537, 2552, + 2553, 2579, 2578, 2575, 2551, 2568, 2549, 2567, 2548, 2550, 2538, 35762, + 35762, 35762, 2580, 32334, 28927, 18140, 18135, 18141, 18136, 16288, + 16299, 16290, 16284, 16296, 16301, 16291, 16297, 16282, 16295, 16298, + 16285, 16303, 16300, 16292, 16289, 16302, 16293, 16286, 16287, 16294, + 16283, 35762, 35762, 16308, 16305, 16306, 16311, 16307, 16304, 16309, + 16310, 16257, 16271, 16262, 16258, 16268, 16261, 16263, 16269, 16255, + 16267, 16270, 16259, 16260, 16272, 16264, 16273, 16265, 16266, 16256, + 35762, 35762, 35762, 35762, 35762, 16278, 16275, 16276, 16281, 16277, + 16274, 16279, 16280, 26895, 26909, 26900, 26896, 26906, 26899, 26901, + 26907, 26905, 26908, 26897, 26898, 26910, 26902, 26912, 26903, 26904, + 26911, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 26920, 26921, + 26893, 26894, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 26917, 26914, 26915, 26919, 26916, 26913, + 26918, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 25658, 25700, 25701, 25690, 25726, 25719, 25693, 25694, 25728, + 25671, 25711, 25659, 25704, 25673, 25713, 25661, 25705, 25672, 25712, + 25660, 25689, 25725, 25679, 25718, 25668, 25708, 25662, 25706, 25695, + 25729, 25674, 25714, 25663, 25684, 25687, 25675, 25664, 25702, 25682, + 25721, 25680, 25720, 25683, 25722, 25710, 25681, 25703, 25688, 25696, + 25691, 25686, 25724, 25676, 25715, 25692, 25727, 25697, 25730, 25677, + 25716, 25665, 25669, 25666, 25670, 25709, 25685, 25723, 25678, 25717, + 25667, 25707, 25698, 25699, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 25318, + 25321, 25344, 25319, 25333, 25329, 25335, 25345, 25320, 25323, 25365, + 25346, 25347, 25336, 25337, 25348, 25366, 25367, 25349, 25350, 25322, + 25362, 25338, 25339, 25324, 25326, 25330, 25358, 25360, 25354, 25356, + 25359, 25351, 25325, 25352, 25368, 25331, 25332, 25340, 25327, 25341, + 25334, 25361, 25364, 25355, 25357, 25353, 25342, 25343, 25328, 25363, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 25369, 25372, 25395, 25370, 25384, 25380, 25386, + 25396, 25371, 25374, 25416, 25397, 25398, 25387, 25388, 25399, 25417, + 25418, 25400, 25401, 25373, 25413, 25389, 25390, 25375, 25377, 25381, + 25409, 25411, 25405, 25407, 25410, 25402, 25376, 25403, 25419, 25382, + 25383, 25391, 25378, 25392, 25385, 25412, 25415, 25406, 25408, 25404, + 25393, 25394, 25379, 25414, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 25422, 25421, 25425, 25420, 25423, 25424, 15157, 15144, 15152, + 15136, 15135, 15149, 15145, 15148, 15133, 15146, 15130, 15129, 15138, + 15137, 15156, 15143, 15142, 15134, 15147, 15150, 15151, 15141, 15154, + 15131, 15155, 15132, 15139, 15140, 15153, 15164, 15166, 15168, 15165, + 15167, 15159, 15158, 15163, 15160, 15162, 15161, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 15175, 15177, 15174, 15173, 15170, + 15169, 15172, 15171, 15178, 15176, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 27439, + 27437, 27436, 27433, 27432, 27435, 27434, 27440, 27438, 27431, 27430, + 27428, 27419, 27417, 27426, 27424, 27415, 27421, 27422, 27429, 27427, + 27418, 27416, 27425, 27423, 27414, 27420, 27411, 27412, 27410, 27413, + 35762, 34219, 34253, 34233, 34232, 34238, 34237, 34215, 34214, 34213, + 34224, 34245, 34218, 34249, 34252, 34251, 34248, 34256, 34235, 34234, + 34236, 34217, 34239, 34250, 34220, 34244, 34255, 34240, 34241, 34228, + 34226, 34225, 34227, 34229, 34216, 34231, 34254, 34242, 34243, 34222, + 34223, 34246, 34221, 35762, 34211, 34210, 34212, 35762, 35762, 34230, + 34247, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 2335, 2336, 2333, 25588, 25596, + 25610, 25597, 25601, 25607, 25598, 25613, 25602, 25608, 25606, 25609, + 25600, 25615, 25611, 25590, 25591, 25603, 25589, 25587, 25614, 25604, + 25592, 25593, 25599, 25605, 25612, 25594, 25595, 25622, 25620, 25617, + 25625, 25624, 25621, 25619, 25618, 25623, 25586, 25616, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 28985, 28999, 28987, 28996, + 29003, 28991, 28997, 28995, 28998, 28988, 29005, 29001, 28992, 28986, + 29004, 28993, 28990, 28994, 29002, 29000, 28989, 28984, 28979, 28977, + 28980, 28978, 28983, 28982, 28974, 28973, 28975, 28981, 28976, 29006, + 29009, 29008, 29007, 29012, 29013, 29010, 29014, 29011, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 25735, 25747, 25745, 25750, 25739, 25744, 25743, 25746, 25737, 25752, + 25748, 25740, 25751, 25741, 25736, 25742, 25749, 25738, 25734, 25733, + 25732, 25731, 25756, 25753, 25754, 25755, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 6190, 6184, 6198, 6192, 6187, 6195, 6201, + 6183, 6193, 6196, 6194, 6197, 6188, 6203, 6199, 6185, 6191, 6202, 6189, + 6186, 6200, 6208, 6205, 6206, 6210, 6207, 6204, 6209, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 12403, 12414, + 12405, 12399, 12411, 12416, 12406, 12412, 12397, 12410, 12413, 12400, + 12418, 12415, 12407, 12404, 12417, 12408, 12401, 12402, 12409, 12398, + 12419, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 4335, 4339, 4337, 4336, 4338, 4261, 4262, 4280, 4281, 4278, 4279, 4273, + 4274, 4275, 4276, 4307, 4263, 4254, 4264, 4300, 4299, 4296, 4295, 4284, + 4294, 4293, 4298, 4297, 4286, 4270, 4269, 4266, 4265, 4285, 4272, 4271, + 4268, 4267, 4287, 4302, 4301, 4292, 4291, 4304, 4306, 4305, 4283, 4277, + 4288, 4289, 4290, 4303, 4282, 4255, 4260, 4259, 4344, 4343, 4353, 4354, + 4351, 4352, 4347, 4348, 4349, 4350, 4355, 4345, 4340, 4346, 4356, 4358, + 4357, 4332, 4331, 4330, 4333, 4329, 35762, 35762, 35762, 35762, 4325, + 4323, 4320, 4311, 4313, 4318, 4316, 4308, 4314, 4324, 4322, 4321, 4310, + 4312, 4319, 4317, 4309, 4315, 4326, 4327, 4365, 4367, 4364, 4363, 4360, + 4359, 4362, 4361, 4368, 4366, 4334, 4257, 4258, 4341, 4342, 4256, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 4328, 16513, + 16515, 16517, 16473, 16474, 16483, 16484, 16481, 16482, 16511, 16475, + 16512, 16476, 16501, 16500, 16497, 16496, 16485, 16495, 16494, 16499, + 16498, 16487, 16478, 16477, 16470, 16468, 16469, 16504, 16486, 16480, + 16479, 16472, 16471, 16488, 16503, 16502, 16493, 16492, 16508, 16510, + 16505, 16507, 16509, 16489, 16490, 16491, 16506, 16523, 16528, 16529, + 16526, 16527, 16530, 16524, 16531, 16525, 16516, 16514, 16534, 16535, + 16532, 16518, 16519, 16521, 16520, 16522, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 16533, 35762, 35762, 29037, + 29038, 29027, 29028, 29029, 29030, 29023, 29024, 29034, 29026, 29039, + 29035, 29040, 29036, 29031, 29033, 29032, 29025, 29041, 29020, 29042, + 29044, 29043, 29021, 29022, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 29051, 29053, 29050, 29049, 29046, 29045, 29048, 29047, 29054, + 29052, 35762, 35762, 35762, 35762, 35762, 35762, 5873, 5875, 5874, 5869, + 5871, 5872, 5870, 5858, 5857, 5854, 5853, 5839, 5852, 5851, 5856, 5855, + 5841, 5844, 5843, 5836, 5835, 5840, 5846, 5845, 5838, 5837, 5842, 5862, + 5861, 5850, 5849, 5864, 5847, 5848, 5865, 5860, 5868, 5866, 5863, 5877, + 5885, 5886, 5881, 5882, 5883, 5879, 5887, 5880, 5888, 5905, 5904, 5889, + 5903, 35762, 5898, 5900, 5897, 5896, 5893, 5892, 5895, 5894, 5901, 5899, + 5876, 5891, 5890, 5902, 5859, 5878, 5884, 5867, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 20693, 20695, 20697, 20694, 20696, + 20685, 20684, 20681, 20680, 20679, 20678, 20683, 20682, 20664, 20673, + 20672, 20669, 20668, 20663, 20675, 20674, 20671, 20670, 20665, 20687, + 20686, 20677, 20676, 20690, 20667, 20689, 20692, 20691, 20688, 20666, + 20700, 20701, 20699, 20698, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 27836, 27835, 27841, 27780, 27781, 27799, 27800, + 27797, 27798, 27792, 27793, 27794, 27795, 27826, 27782, 27827, 27783, + 27819, 27818, 27815, 27814, 27803, 27813, 27812, 27817, 27816, 27805, + 27789, 27788, 27785, 27784, 27804, 27791, 27790, 27787, 27786, 27806, + 27821, 27820, 27811, 27810, 27823, 27825, 27824, 27802, 27801, 27796, + 27807, 27808, 27809, 27822, 27845, 27854, 27855, 27852, 27853, 27848, + 27849, 27850, 27851, 27856, 27846, 27857, 27847, 27840, 27834, 27838, + 27839, 27860, 27766, 27765, 27858, 27831, 27828, 27837, 27843, 27777, + 27842, 27844, 27832, 27773, 27775, 27772, 27771, 27768, 27767, 27770, + 27769, 27776, 27774, 27778, 27833, 27779, 27859, 27829, 27830, 35762, + 28741, 28739, 28738, 28735, 28734, 28737, 28736, 28742, 28740, 28753, + 28752, 28751, 28747, 28746, 28750, 28749, 28745, 28748, 28743, 28744, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 17905, 17906, 17932, 17934, 17931, 17907, 17933, 17908, 17922, + 17921, 17897, 17895, 17896, 17915, 17920, 17919, 17904, 17903, 35762, + 17917, 17910, 17909, 17900, 17899, 17916, 17912, 17911, 17902, 17898, + 17901, 17918, 17924, 17923, 17894, 17892, 17893, 17926, 17930, 17928, + 17914, 17929, 17891, 17925, 17913, 17942, 17945, 17946, 17949, 17947, + 17943, 17948, 17944, 17939, 17937, 17938, 17935, 17889, 17888, 17950, + 17940, 17887, 17951, 17936, 17927, 17890, 17941, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 23597, + 23599, 23600, 23598, 23588, 23587, 23586, 35762, 23585, 35762, 23584, + 23583, 23576, 23575, 35762, 23570, 23578, 23577, 23566, 23564, 23565, + 23569, 23580, 23579, 23568, 23567, 23571, 23590, 23589, 23582, 35762, + 23581, 23593, 23596, 23574, 23592, 23595, 23594, 23591, 23573, 23572, + 23601, 35762, 35762, 35762, 35762, 35762, 35762, 17968, 17969, 17978, + 17979, 17976, 17977, 17997, 17970, 17998, 17971, 17987, 17986, 17957, + 17955, 17956, 17980, 17985, 17984, 17960, 17959, 17958, 17982, 17973, + 17972, 17963, 17961, 17966, 17962, 17981, 17975, 17974, 17965, 17964, + 17983, 17989, 17988, 17954, 17952, 17953, 17994, 17996, 17967, 17993, + 17995, 17990, 17991, 17992, 18001, 18002, 18007, 18008, 18005, 18006, + 18009, 18003, 18010, 18004, 18000, 17999, 35762, 35762, 35762, 35762, + 35762, 18017, 18019, 18016, 18015, 18012, 18011, 18014, 18013, 18020, + 18018, 35762, 35762, 35762, 35762, 35762, 35762, 13699, 13700, 13703, + 13706, 35762, 13656, 13657, 13670, 13671, 13668, 13669, 13651, 13653, + 35762, 35762, 13694, 13658, 35762, 35762, 13693, 13659, 13690, 13689, + 13686, 13685, 13674, 13684, 13683, 13688, 13687, 13676, 13665, 13664, + 13661, 13660, 13675, 13667, 13666, 13663, 13662, 13677, 35762, 13692, + 13691, 13682, 13681, 13696, 13698, 13697, 35762, 13673, 13672, 35762, + 13655, 13678, 13679, 13680, 13695, 35762, 7774, 13704, 13702, 13707, + 13716, 13717, 13714, 13715, 13710, 13711, 35762, 35762, 13719, 13708, + 35762, 35762, 13718, 13709, 13705, 35762, 35762, 13721, 35762, 35762, + 35762, 35762, 35762, 35762, 13720, 35762, 35762, 35762, 35762, 35762, + 13701, 13650, 13649, 13652, 13654, 13712, 13713, 35762, 35762, 7954, + 7955, 7953, 7952, 7951, 7950, 7949, 35762, 35762, 35762, 7960, 7957, + 7958, 7956, 7959, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 24495, 24496, 24509, 24510, 24507, 24508, 24491, 24492, 24493, + 24494, 24535, 24497, 24536, 24498, 24523, 24522, 24519, 24518, 24484, + 24483, 24517, 24516, 24521, 24520, 24486, 24485, 24504, 24503, 24500, + 24499, 24488, 24506, 24505, 24502, 24501, 24489, 24487, 24529, 24528, + 24515, 24514, 24527, 24526, 24534, 24531, 24530, 24525, 24524, 24533, + 24511, 24512, 24513, 24532, 24549, 24558, 24559, 24556, 24557, 24552, + 24553, 24554, 24555, 24560, 24550, 24561, 24551, 24544, 24539, 24538, + 24545, 24540, 24537, 24542, 24565, 24546, 24471, 24469, 24564, 24482, + 24562, 24478, 24480, 24477, 24476, 24473, 24472, 24475, 24474, 24481, + 24479, 24470, 24548, 35762, 24563, 24547, 24490, 24541, 24543, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 32336, + 32337, 32338, 32356, 32357, 32354, 32355, 32349, 32350, 32351, 32352, + 32382, 32339, 32383, 32340, 32374, 32373, 32370, 32369, 32358, 32368, + 32367, 32372, 32371, 32360, 32346, 32345, 32342, 32341, 32359, 32348, + 32347, 32344, 32343, 32361, 32376, 32375, 32366, 32365, 32379, 32381, + 32380, 32378, 32353, 32362, 32363, 32364, 32377, 32390, 32401, 32402, + 32399, 32400, 32395, 32396, 32397, 32398, 32403, 32393, 32391, 32404, + 32394, 32392, 32386, 32385, 32389, 32388, 32387, 32384, 32415, 32335, + 32416, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 32411, + 32413, 32410, 32409, 32406, 32405, 32408, 32407, 32414, 32412, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 27949, 27951, 27972, 27973, 27970, + 27971, 27965, 27966, 27967, 27968, 27998, 27952, 27999, 27953, 27990, + 27989, 27986, 27985, 27974, 27984, 27983, 27988, 27987, 27976, 27959, + 27958, 27962, 27961, 27975, 27960, 27955, 27964, 27963, 27977, 27992, + 27991, 27982, 27981, 27995, 27997, 27996, 27994, 27969, 27978, 27979, + 27980, 27993, 28027, 28034, 28035, 28032, 28033, 28030, 28031, 35762, + 35762, 28036, 28028, 28037, 28029, 28020, 28022, 28024, 28023, 28021, + 28019, 27947, 27946, 28018, 28017, 28000, 28001, 28002, 27948, 28015, + 28014, 28012, 28010, 28011, 28003, 28004, 28013, 28016, 28008, 28009, + 28007, 28006, 28005, 27954, 27956, 27957, 27950, 28025, 28026, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 22953, 22954, 22972, 22973, 22970, 22971, 22965, + 22966, 22967, 22968, 22999, 22955, 23000, 22956, 22992, 22991, 22988, + 22987, 22976, 22986, 22985, 22990, 22989, 22978, 22962, 22961, 22958, + 22957, 22977, 22964, 22963, 22960, 22959, 22979, 22994, 22993, 22984, + 22983, 22996, 22998, 22997, 22975, 22969, 22980, 22981, 22982, 22995, + 22974, 22928, 22937, 22938, 22935, 22936, 22931, 22932, 22933, 22934, + 22939, 22929, 22940, 22930, 22924, 22927, 22926, 22923, 22942, 22941, + 23001, 22925, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 22949, 22951, 22948, 22947, 22944, 22943, 22946, + 22945, 22952, 22950, 35762, 35762, 35762, 35762, 35762, 35762, 23481, + 23476, 23321, 23482, 23480, 23478, 23477, 23338, 23339, 23472, 23474, + 23473, 23483, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 30326, 30328, 30343, 30344, 30341, 30342, 30368, 30329, 30369, + 30330, 30358, 30357, 30354, 30353, 30345, 30352, 30351, 30356, 30355, + 30347, 30338, 30337, 30334, 30333, 30346, 30340, 30339, 30336, 30335, + 30348, 30360, 30359, 30350, 30349, 30365, 30367, 30332, 30364, 30366, + 30361, 30362, 30363, 30331, 30371, 30373, 30374, 30379, 30380, 30377, + 30378, 30381, 30375, 30382, 30376, 30372, 30370, 30327, 30325, 35762, + 35762, 35762, 35762, 35762, 35762, 30389, 30391, 30388, 30387, 30384, + 30383, 30386, 30385, 30392, 30390, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 191, 190, + 178, 181, 175, 167, 193, 192, 183, 195, 189, 184, 174, 196, 177, 197, + 180, 194, 164, 171, 170, 187, 166, 186, 182, 188, 165, 35762, 35762, 162, + 163, 161, 203, 204, 210, 211, 208, 209, 212, 207, 213, 205, 206, 200, + 35762, 35762, 35762, 35762, 222, 224, 221, 220, 217, 216, 219, 218, 225, + 223, 215, 214, 198, 199, 201, 202, 185, 173, 172, 169, 168, 179, 176, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 10719, 10720, 10733, 10734, 10731, + 10732, 10759, 10721, 10760, 10722, 10751, 10750, 10747, 10746, 10735, + 10745, 10744, 10749, 10748, 10737, 10728, 10727, 10724, 10723, 10736, + 10730, 10729, 10726, 10725, 10738, 10753, 10752, 10743, 10742, 10756, + 10758, 10718, 10755, 10757, 10739, 10740, 10741, 10754, 10717, 10763, + 10768, 10769, 10766, 10767, 10761, 10762, 10770, 10764, 10771, 10765, + 10774, 10776, 10775, 10773, 10772, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 33866, 33855, 33884, 33874, 33876, + 33877, 33883, 33873, 33859, 33868, 33856, 33886, 33882, 33861, 33875, + 33872, 33860, 33869, 33878, 33867, 33885, 33858, 33857, 33880, 33881, + 33864, 33863, 33862, 33865, 33870, 33871, 33879, 33898, 33887, 33916, + 33906, 33908, 33909, 33915, 33905, 33891, 33900, 33888, 33918, 33914, + 33893, 33907, 33904, 33892, 33901, 33910, 33899, 33917, 33890, 33889, + 33912, 33913, 33896, 33895, 33894, 33897, 33902, 33903, 33911, 33925, + 33927, 33924, 33923, 33920, 33919, 33922, 33921, 33928, 33926, 33937, + 33936, 33935, 33931, 33930, 33934, 33933, 33929, 33932, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 33938, 10633, 10634, 10641, 10642, 10639, 10640, 10668, 35762, 35762, + 10669, 35762, 35762, 10659, 10658, 10657, 10656, 10645, 10655, 10654, + 10663, 35762, 10647, 10629, 35762, 10636, 10635, 10646, 10630, 10628, + 10638, 10637, 10648, 10661, 10660, 10653, 10652, 10664, 10632, 10631, + 10665, 10644, 10666, 10649, 10650, 10651, 10662, 10643, 10667, 10674, + 10678, 10679, 10676, 10677, 10680, 35762, 10675, 10681, 35762, 35762, + 10673, 10671, 10670, 10682, 10687, 10684, 10688, 10683, 10672, 10617, + 10685, 10686, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 10624, 10626, 10623, 10622, 10619, 10618, 10621, 10620, 10627, + 10625, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 24192, 24193, 24206, 24207, 24204, 24205, 24187, 24188, 35762, + 35762, 24232, 24194, 24233, 24195, 24226, 24225, 24222, 24221, 24210, + 24220, 24219, 24224, 24223, 24212, 24201, 24200, 24197, 24196, 24211, + 24203, 24202, 24199, 24198, 24213, 24228, 24227, 24218, 24217, 24230, + 24231, 24191, 24209, 24189, 24214, 24215, 24216, 24229, 24208, 24190, + 24242, 24247, 24248, 24245, 24246, 24240, 24241, 35762, 35762, 24249, + 24243, 24250, 24244, 24236, 24238, 24237, 24235, 24234, 24251, 24239, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35543, 35564, 35561, + 35560, 35563, 35559, 35558, 35556, 35557, 35562, 35555, 35511, 35510, + 35530, 35529, 35512, 35528, 35527, 35537, 35514, 35522, 35521, 35504, + 35503, 35513, 35524, 35523, 35508, 35507, 35515, 35532, 35531, 35526, + 35525, 35539, 35520, 35519, 35506, 35505, 35533, 35534, 35535, 35542, + 35540, 35538, 35541, 35516, 35517, 35518, 35536, 35509, 35502, 35552, + 35549, 35550, 35551, 35548, 35553, 35499, 35498, 35496, 35495, 35497, + 35501, 35494, 35547, 35545, 35544, 35546, 35500, 35493, 35554, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 29142, 29163, 29161, + 29160, 29162, 29158, 29159, 29156, 29157, 29155, 29154, 29164, 29109, + 29108, 29128, 29127, 29110, 29126, 29125, 29130, 29129, 29112, 29120, + 29119, 29103, 29102, 29111, 29122, 29121, 29106, 29104, 29113, 29132, + 29131, 29124, 29123, 29138, 29118, 29117, 29105, 29133, 29134, 29135, + 29141, 29139, 29137, 29140, 29114, 29115, 29116, 29136, 29107, 29147, + 29149, 29085, 29084, 29082, 29083, 29093, 29094, 29089, 29092, 29088, + 29091, 29096, 29097, 29095, 29087, 29086, 29090, 29150, 29148, 29098, + 29151, 29146, 29145, 29144, 29143, 29101, 29100, 29099, 29152, 29153, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 5316, 5317, 5314, 5315, 5312, 5313, 5322, 5323, + 5320, 5321, 5318, 5319, 5485, 5486, 5487, 5484, 26453, 26451, 26460, + 26461, 26457, 26465, 26464, 26446, 26459, 26458, 26450, 26463, 26456, + 26449, 26455, 26454, 26447, 26452, 26462, 26441, 26448, 26466, 26467, + 26442, 26468, 26444, 26445, 26443, 26437, 26434, 26438, 26436, 26432, + 26435, 26439, 26433, 26440, 26474, 26473, 26484, 26475, 26476, 26485, + 26481, 26480, 26482, 26483, 26477, 26431, 26478, 26479, 26470, 26469, + 26429, 26471, 26472, 26430, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 10360, 10361, 10450, 10451, 10452, 10453, 10460, 10459, 10461, + 10469, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 3641, 3642, 3655, 3656, + 3653, 3654, 3637, 3638, 3639, 35762, 3681, 3643, 3682, 3644, 3673, 3672, + 3669, 3668, 3657, 3667, 3666, 3671, 3670, 3659, 3650, 3649, 3646, 3645, + 3658, 3652, 3651, 3648, 3647, 3660, 3675, 3674, 3665, 3664, 3678, 3680, + 3679, 3677, 3640, 3661, 3662, 3663, 3676, 3709, 3714, 3715, 3712, 3713, + 3706, 3707, 3708, 35762, 3716, 3710, 3717, 3711, 3703, 3702, 3705, 3704, + 3701, 3719, 3718, 3730, 3731, 3732, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 3726, 3728, 3725, 3724, 3721, 3720, + 3723, 3722, 3729, 3727, 3700, 3698, 3695, 3686, 3688, 3693, 3691, 3683, + 3689, 3699, 3697, 3696, 3685, 3687, 3694, 3692, 3684, 3690, 3733, 35762, + 35762, 35762, 21057, 21058, 21003, 21002, 21012, 20997, 21001, 21000, + 21014, 20998, 20994, 20993, 20996, 20999, 21005, 21004, 21011, 21016, + 20992, 20991, 20995, 21018, 21008, 21009, 21010, 21019, 21017, 21015, + 21006, 21007, 21013, 21020, 35762, 35762, 21035, 21034, 21043, 21029, + 21033, 21032, 21045, 21030, 21026, 21025, 21028, 21031, 21037, 21036, + 21042, 21047, 21024, 21023, 21027, 21049, 21040, 21041, 35762, 21050, + 21048, 21046, 21038, 21039, 21044, 21051, 21052, 21054, 21056, 21053, + 21055, 21022, 21021, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 21069, 21070, 21079, 21080, + 21077, 21078, 21106, 35762, 21071, 21107, 35762, 21072, 21085, 21084, + 21098, 21097, 21086, 21096, 21095, 21063, 21062, 21088, 21065, 21064, + 21074, 21073, 21087, 21068, 21066, 21076, 21075, 21089, 21100, 21099, + 21094, 21093, 21102, 21105, 21103, 21082, 21104, 21090, 21091, 21092, + 21101, 21081, 21083, 21061, 21067, 21116, 21121, 21122, 21119, 21120, + 21115, 35762, 35762, 35762, 21123, 35762, 21117, 21124, 35762, 21118, + 21114, 21113, 21112, 21110, 21111, 21125, 21109, 21108, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 21132, 21134, 21131, 21130, + 21127, 21126, 21129, 21128, 21135, 21133, 35762, 35762, 35762, 35762, + 35762, 35762, 14372, 14373, 14388, 14389, 14384, 14385, 35762, 14405, + 14374, 35762, 14404, 14375, 14411, 14410, 14393, 14392, 14407, 14401, + 14400, 14383, 14382, 14391, 14397, 14396, 14379, 14378, 14387, 14395, + 14394, 14381, 14380, 14390, 14399, 14398, 14377, 14376, 14386, 14403, + 14402, 14406, 14408, 14409, 14414, 14419, 14420, 14417, 14418, 35762, + 14422, 14415, 35762, 14421, 14416, 14413, 14412, 14423, 14434, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 14430, 14432, 14429, 14428, + 14425, 14424, 14427, 14426, 14433, 14431, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 20755, 20753, 20747, 20758, + 20750, 20757, 20761, 20752, 20749, 20751, 20754, 20748, 20763, 20759, + 20756, 20762, 20760, 20764, 20770, 20767, 20769, 20766, 20768, 20765, + 20746, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 17048, 17050, + 17046, 17049, 16988, 16989, 17008, 17009, 17006, 17007, 17002, 17003, + 17004, 17005, 17033, 16990, 17034, 35762, 17024, 17023, 17022, 17021, + 17010, 17020, 17019, 16993, 16992, 17012, 16999, 16998, 16995, 16994, + 17011, 17001, 17000, 16997, 16996, 17013, 17026, 17025, 17018, 17017, + 17029, 17032, 17030, 17028, 17031, 17014, 17015, 17016, 17027, 16991, + 17052, 17051, 17059, 17060, 17057, 17058, 17054, 35762, 35762, 35762, + 17055, 17053, 17056, 17047, 17073, 17062, 17061, 17041, 17044, 17040, + 17042, 17038, 17037, 17045, 17036, 17039, 17043, 17035, 17069, 17071, + 17068, 17067, 17064, 17063, 17066, 17065, 17072, 17070, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 20466, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 30449, 30445, 30439, 30448, 30441, 30450, 30454, 30456, 30451, 30446, + 30447, 30452, 30440, 30457, 30455, 30442, 30453, 30443, 30444, 30458, + 30459, 30523, 30506, 30504, 30513, 30512, 30508, 30514, 30510, 30509, + 30516, 30517, 30518, 30515, 30507, 30520, 30438, 30425, 30496, 30503, + 30804, 30805, 30423, 30398, 30524, 30803, 30460, 30525, 30511, 30519, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 30501, 8517, 8525, 8523, 8519, 8524, 8520, 8518, + 8521, 8522, 8586, 8526, 8535, 8534, 8528, 8527, 8539, 8529, 8530, 8538, + 8532, 8533, 8540, 8541, 8546, 8543, 8542, 8544, 8545, 8548, 8550, 8552, + 8551, 8553, 8559, 8556, 8557, 8561, 8554, 8555, 8560, 8558, 8563, 8562, + 8564, 8566, 8567, 8571, 8570, 8568, 8569, 8572, 8585, 8573, 8574, 8575, + 8584, 8576, 8580, 8581, 8579, 8577, 8578, 8583, 8582, 8587, 8588, 8599, + 8590, 8594, 8595, 8596, 8597, 8598, 8600, 8603, 8602, 8601, 8604, 8606, + 8607, 8608, 8609, 8610, 8611, 8612, 8613, 8614, 8615, 8616, 8617, 8618, + 8619, 8620, 8621, 8622, 8623, 8638, 8624, 8625, 8635, 8629, 8626, 8627, + 8628, 8636, 8633, 8637, 8634, 8630, 8632, 8645, 8641, 8642, 8643, 8646, + 8657, 8647, 8650, 8651, 8653, 8654, 8655, 8658, 8661, 8659, 8660, 8662, + 8663, 8665, 8666, 8695, 8702, 8696, 8697, 8698, 8699, 8700, 8701, 8703, + 8705, 8704, 8706, 8709, 8710, 8713, 8707, 8708, 8714, 8759, 8758, 8760, + 8715, 8718, 8719, 8720, 8716, 8717, 8721, 8724, 8722, 8725, 8727, 8736, + 8737, 8738, 8739, 8757, 8740, 8741, 8754, 8755, 8753, 8742, 8743, 8744, + 8745, 8746, 8747, 8748, 8751, 8752, 8761, 8851, 8762, 8763, 8765, 8764, + 8771, 8766, 8768, 8770, 8774, 8773, 8775, 8776, 8783, 8777, 8778, 8782, + 8786, 8787, 8784, 8785, 8793, 8790, 8794, 8795, 8796, 8797, 8798, 8800, + 8801, 8803, 8802, 8805, 8804, 8807, 8806, 8808, 8809, 8811, 8812, 8816, + 8818, 8822, 8823, 8836, 8828, 8829, 8824, 8825, 8826, 8830, 8834, 8831, + 8832, 8833, 8837, 8838, 8840, 8841, 8842, 8843, 8844, 8845, 8855, 8846, + 8847, 8850, 8849, 8848, 8852, 8853, 8854, 8856, 8857, 8860, 8861, 8862, + 8863, 8864, 8866, 8865, 8882, 8873, 8874, 8867, 8868, 8870, 8871, 8869, + 8872, 8881, 8875, 8880, 8878, 8877, 8879, 8884, 8903, 8885, 8886, 8887, + 8890, 8889, 8891, 8892, 8894, 8895, 8896, 8904, 8897, 8898, 8899, 8902, + 8901, 8900, 8905, 8906, 8908, 8909, 8910, 8911, 8913, 8917, 8914, 8918, + 8916, 8915, 8919, 8920, 8921, 8922, 8926, 8925, 8923, 8924, 8927, 8928, + 8930, 8949, 8951, 8931, 8933, 8932, 8934, 8935, 8938, 8939, 8937, 8936, + 8940, 8941, 8942, 8943, 8946, 8944, 8945, 8947, 8948, 8952, 8953, 8950, + 8954, 8955, 8956, 8957, 8959, 8962, 8961, 8963, 8964, 8966, 8967, 8968, + 8972, 8971, 8969, 8970, 8973, 8977, 8976, 8975, 8978, 8979, 8981, 8982, + 8986, 8983, 8984, 8989, 8987, 8990, 8991, 8993, 8992, 8994, 8995, 9017, + 9016, 9019, 9020, 9001, 9002, 8999, 9000, 8998, 8996, 9004, 9003, 9005, + 9007, 9013, 9014, 9011, 9012, 9021, 9022, 9023, 9040, 9026, 9027, 9028, + 9024, 9025, 9029, 9030, 9031, 9032, 9033, 9034, 9035, 9036, 9037, 9038, + 9063, 9041, 9044, 9042, 9043, 9049, 9050, 9047, 9048, 9045, 9046, 9051, + 9052, 9060, 9053, 9054, 9061, 9058, 9059, 9062, 9055, 9056, 9057, 9064, + 9065, 9066, 9067, 9068, 9069, 9070, 9072, 9073, 9071, 9074, 9075, 9116, + 9117, 9078, 9079, 9076, 9077, 9082, 9083, 9081, 9087, 9084, 9086, 9085, + 9091, 9092, 9090, 9088, 9089, 9093, 9094, 9095, 9096, 9097, 9098, 9099, + 9118, 9104, 9100, 9101, 9102, 9103, 9105, 9107, 9106, 9108, 9109, 9111, + 9110, 9112, 9114, 9113, 9119, 9120, 9123, 9124, 9121, 9122, 9198, 9193, + 9194, 9195, 9196, 9197, 9199, 9202, 9200, 9201, 9203, 9245, 9204, 9234, + 9235, 9211, 9213, 9230, 9214, 9236, 9218, 9216, 9217, 9219, 9220, 9221, + 9222, 9231, 9232, 9225, 9226, 9228, 9237, 9205, 9206, 9210, 9208, 9246, + 9238, 9240, 9239, 9241, 9247, 9248, 9242, 9243, 9244, 9249, 9250, 9251, + 9254, 9255, 9256, 9252, 9253, 9257, 9258, 9260, 9262, 9263, 9281, 9279, + 9280, 9283, 9282, 9264, 9271, 9269, 9270, 9265, 9266, 9272, 9273, 9274, + 9275, 9276, 9278, 9284, 9293, 9285, 9287, 9288, 9286, 9289, 9291, 9290, + 9292, 9295, 9297, 9296, 9298, 9299, 9332, 9334, 9300, 9302, 9301, 9304, + 9307, 9305, 9306, 9310, 9314, 9317, 9316, 9319, 9322, 9320, 9321, 9325, + 9327, 9333, 9335, 9336, 9340, 9347, 9345, 9343, 9344, 9346, 9349, 9348, + 9341, 9342, 9350, 9353, 9359, 9354, 9357, 9352, 9351, 9360, 9358, 9355, + 9356, 9361, 9362, 9363, 9364, 9365, 9366, 9367, 9369, 9372, 9373, 9376, + 9377, 9378, 9374, 9375, 9370, 9371, 9379, 9380, 9381, 9382, 9383, 9384, + 9386, 9387, 9388, 9389, 9390, 9394, 9391, 9415, 9408, 9409, 9414, 9397, + 9396, 9410, 9413, 9411, 9400, 9399, 9402, 9404, 9405, 9406, 9407, 9403, + 9416, 9392, 9417, 9418, 9419, 9420, 9421, 9422, 9430, 9428, 9426, 9429, + 9425, 9427, 9423, 9424, 9431, 9433, 9434, 9435, 9442, 9437, 9438, 9446, + 9447, 9443, 9445, 9444, 9448, 9450, 9449, 9451, 9462, 9453, 9452, 9461, + 9459, 9454, 9455, 9456, 9458, 9457, 9460, 9466, 9463, 9465, 9464, 9467, + 9468, 9469, 9470, 9473, 9474, 9476, 9477, 9478, 9479, 9481, 9480, 9482, + 9489, 9483, 9484, 9490, 9485, 9486, 9487, 9488, 9491, 9495, 9492, 9493, + 9494, 9496, 9497, 9498, 9499, 9505, 9503, 9501, 9502, 9500, 9504, 9506, + 9508, 9525, 9526, 9509, 9514, 9516, 9510, 9513, 9511, 9512, 9517, 9523, + 9524, 9518, 9521, 9522, 9527, 9533, 9532, 9528, 9530, 9529, 9614, 9615, + 9534, 9535, 9540, 9541, 9538, 9539, 9542, 9536, 9537, 9543, 9546, 9547, + 9549, 9550, 9551, 9555, 9552, 9553, 9554, 9544, 9545, 9556, 9558, 9557, + 9559, 9561, 9562, 9563, 9569, 9568, 9564, 9565, 9566, 9601, 9570, 9571, + 9572, 9573, 9574, 9593, 9576, 9577, 9579, 9578, 9580, 9581, 9597, 9582, + 9584, 9583, 9596, 9586, 9594, 9598, 9589, 9588, 9595, 9590, 9592, 9591, + 9599, 9600, 9602, 9606, 9604, 9605, 9603, 9609, 9608, 9607, 9613, 9610, + 9611, 9612, 9616, 9618, 9617, 9621, 9619, 9636, 9622, 9625, 9627, 9623, + 9624, 9628, 9626, 9629, 9631, 9633, 9634, 9635, 9039, 8536, 8547, 8565, + 8631, 8640, 8656, 8664, 8756, 8749, 8767, 8769, 8859, 8883, 8929, 8958, + 8960, 8974, 8980, 9015, 8988, 9018, 8997, 9006, 9010, 9080, 9209, 9212, + 9227, 9259, 9277, 9294, 9303, 9331, 9329, 9308, 9339, 9368, 9385, 9395, + 9515, 9548, 9531, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 8501, 8496, 8433, 8419, 8480, 8476, 8408, + 8453, 8500, 8441, 8425, 8486, 8475, 8407, 8452, 8439, 8423, 8482, 8472, + 8402, 8449, 8462, 8506, 8498, 8435, 8421, 8484, 8474, 8404, 8451, 8463, + 8507, 8499, 8436, 8422, 8508, 8490, 8491, 8437, 8413, 8479, 8471, 8401, + 8448, 8466, 8509, 8492, 8493, 8438, 8414, 8477, 8478, 8461, 8504, 8487, + 8488, 8428, 8418, 8494, 8495, 8429, 8432, 8430, 8431, 8485, 8470, 8468, + 8469, 8405, 8406, 8444, 8446, 8447, 8445, 8502, 8497, 8434, 8420, 8481, + 8460, 8503, 8489, 8426, 8427, 8416, 8417, 8443, 8442, 8456, 8505, 8465, + 8511, 8415, 8464, 8510, 8457, 8458, 8454, 8455, 8459, 8467, 8409, 8412, + 8411, 8410, 8440, 8424, 8483, 8473, 8403, 8450, 35762, 8516, 8515, 8514, + 8512, 8513, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 8537, 8531, 8549, 8589, 8591, 8592, 8593, 8605, + 8644, 8639, 8649, 8648, 8652, 8669, 8667, 8668, 8670, 8671, 8689, 8675, + 8672, 8673, 8674, 8691, 8692, 8690, 8679, 8678, 8676, 8677, 8682, 8680, + 8681, 8683, 8684, 8685, 8686, 8693, 8694, 8688, 8687, 8712, 8711, 8723, + 8726, 8731, 8735, 8728, 8732, 8733, 8729, 8730, 8734, 8750, 8772, 8779, + 8780, 8781, 8788, 8789, 8792, 8791, 8799, 8810, 8813, 8814, 8815, 8817, + 8819, 8820, 8821, 8827, 8835, 8839, 8858, 8876, 8888, 8893, 8907, 8912, + 8965, 8985, 9008, 9009, 9115, 9135, 9125, 9126, 9134, 9130, 9131, 9132, + 9129, 9128, 9127, 9133, 9137, 9136, 9143, 9144, 9138, 9139, 9140, 9145, + 9141, 9142, 9146, 9147, 9148, 9149, 9150, 9151, 9158, 9152, 9157, 9156, + 9154, 9153, 9155, 9159, 9160, 9165, 9166, 9161, 9162, 9163, 9164, 9192, + 9188, 9167, 9175, 9176, 9174, 9173, 9177, 9168, 9169, 9171, 9172, 9170, + 9189, 9178, 9185, 9187, 9182, 9183, 9186, 9181, 9184, 9180, 9179, 9190, + 9191, 9207, 9233, 9215, 9223, 9224, 9229, 9261, 9268, 9267, 9328, 9309, + 9311, 9330, 9312, 9313, 9315, 9318, 9323, 9324, 9326, 9393, 9412, 9398, + 9401, 9432, 9436, 9439, 9440, 9441, 9472, 9471, 9475, 9507, 9519, 9520, + 9560, 9567, 9575, 9587, 9585, 9620, 9630, 9632, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 9709, + 9710, 9711, 9712, 9713, 9714, 9715, 9716, 9719, 9720, 9717, 9718, 9721, + 9722, 9723, 9724, 9725, 9726, 9727, 9728, 9729, 9730, 9731, 9732, 9733, + 9734, 9735, 9736, 9737, 9738, 9739, 9740, 9741, 9742, 9743, 9744, 9745, + 9746, 9747, 9748, 9749, 9750, 9751, 9752, 9753, 9754, 9755, 9775, 9776, + 9777, 9778, 9779, 9780, 9781, 9782, 9783, 9758, 9759, 9760, 9761, 9762, + 9756, 9757, 9763, 9764, 9765, 9784, 9785, 9786, 9787, 9788, 9789, 9790, + 9791, 9792, 9793, 9766, 9767, 9768, 9769, 9770, 9771, 9772, 9773, 9774, + 9794, 9795, 9796, 9797, 9798, 9799, 9800, 9801, 9802, 9803, 9804, 9805, + 9806, 9807, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 11228, 11229, 11230, 11231, 11226, + 11227, 11223, 11224, 11225, 11232, 11233, 11234, 11239, 11240, 11241, + 11242, 11235, 11236, 11243, 11244, 11237, 11238, 11245, 11246, 11273, + 11274, 11275, 11276, 11277, 11278, 11279, 11280, 11281, 11282, 11263, + 11264, 11261, 11262, 11265, 11266, 11267, 11268, 11269, 11270, 11271, + 11247, 11248, 11255, 11249, 11250, 11251, 11252, 11256, 11253, 11254, + 11257, 11258, 11259, 11260, 11283, 11284, 11285, 11286, 11287, 11288, + 11289, 11290, 11291, 11292, 11293, 11294, 11295, 11296, 11297, 11298, + 11299, 11300, 11301, 11302, 11272, 11342, 11343, 11344, 11345, 11340, + 11341, 11346, 11347, 11348, 11349, 11354, 11350, 11351, 11352, 11353, + 11355, 11356, 11357, 11358, 11359, 11360, 11361, 11362, 11363, 11364, + 11365, 11366, 11367, 11368, 11369, 11370, 11371, 11372, 11373, 11374, + 11375, 11376, 11377, 11380, 11381, 11382, 11383, 11384, 11385, 11386, + 11378, 11379, 11387, 11460, 11461, 11462, 11463, 11464, 11465, 11466, + 11467, 11468, 11469, 11451, 11452, 11453, 11454, 11455, 11456, 11457, + 11449, 11450, 11458, 11459, 11392, 11388, 11389, 11393, 11394, 11390, + 11391, 11395, 11396, 11397, 11398, 11399, 11404, 11405, 11406, 11407, + 11408, 11409, 11400, 11401, 11410, 11402, 11403, 11411, 11412, 11413, + 11414, 11415, 11416, 11417, 11418, 11419, 11420, 11421, 11426, 11422, + 11423, 11427, 11424, 11425, 11428, 11429, 11430, 11431, 11432, 11442, + 11443, 11444, 11445, 11446, 11447, 11448, 11433, 11434, 11435, 11436, + 11437, 11438, 11439, 11440, 11441, 11474, 11475, 11476, 11477, 11478, + 11479, 11480, 11470, 11471, 11472, 11473, 11506, 11507, 11508, 11509, + 11510, 11511, 11502, 11503, 11504, 11505, 11512, 11513, 11481, 11482, + 11485, 11486, 11487, 11488, 11489, 11490, 11491, 11483, 11484, 11492, + 11495, 11496, 11497, 11498, 11493, 11494, 11499, 11500, 11501, 11517, + 11518, 11519, 11520, 11521, 11522, 11523, 11524, 11525, 11526, 11529, + 11530, 11531, 11527, 11528, 11532, 11533, 11534, 11535, 11536, 11537, + 11573, 11571, 11572, 11574, 11575, 11576, 11577, 11578, 11579, 11580, + 11581, 11544, 11538, 11539, 11545, 11546, 11547, 11548, 11549, 11540, + 11541, 11542, 11543, 11550, 11557, 11558, 11559, 11560, 11561, 11551, + 11552, 11553, 11554, 11555, 11556, 11562, 11563, 11568, 11564, 11565, + 11566, 11567, 11569, 11570, 11588, 11589, 11590, 11591, 11592, 11586, + 11587, 11583, 11584, 11585, 11593, 11594, 11597, 11595, 11596, 11598, + 11599, 11600, 11601, 11602, 11603, 11604, 11605, 11630, 11631, 11634, + 11635, 11636, 11637, 11638, 11632, 11633, 11639, 11640, 11641, 11610, + 11611, 11612, 11613, 11614, 11615, 11606, 11607, 11608, 11609, 11616, + 11617, 11622, 11623, 11624, 11618, 11619, 11625, 11620, 11621, 11626, + 11627, 11628, 11629, 11642, 11643, 11644, 11645, 11646, 11649, 11650, + 11651, 11652, 11653, 11647, 11648, 11654, 11655, 11663, 11664, 11665, + 11666, 11659, 11660, 11667, 11668, 11669, 11661, 11662, 11670, 11671, + 11672, 11673, 11674, 11675, 11676, 11677, 12318, 12319, 12320, 12321, + 12322, 12323, 12324, 12325, 11689, 11685, 11686, 11690, 11691, 11692, + 11687, 11688, 11693, 11694, 11696, 11697, 11698, 11701, 11699, 11700, + 11702, 11703, 11704, 11705, 11706, 11707, 11717, 11718, 11725, 11708, + 11709, 11710, 11711, 11712, 11713, 11714, 11715, 11716, 11726, 11727, + 11719, 11720, 11721, 11722, 11723, 11724, 11728, 11729, 11736, 11737, + 11730, 11731, 11738, 11732, 11733, 11739, 11740, 11741, 11734, 11735, + 11742, 11748, 11746, 11747, 11749, 11743, 11744, 11745, 11750, 11751, + 11752, 11753, 11754, 11755, 11756, 11757, 11758, 11759, 11760, 11761, + 11818, 11819, 11820, 11821, 11822, 11823, 11824, 11825, 11826, 11781, + 11782, 11783, 11784, 11785, 11786, 11787, 11788, 11778, 11779, 11780, + 11789, 11806, 11807, 11808, 11809, 11810, 11804, 11805, 11811, 11812, + 11813, 11814, 11798, 11799, 11800, 11790, 11791, 11792, 11793, 11794, + 11795, 11801, 11796, 11797, 11802, 11803, 11815, 11816, 11817, 11829, + 11830, 11831, 11832, 11827, 11828, 11833, 11834, 11835, 11836, 11839, + 11840, 11841, 11842, 11843, 11844, 11845, 11837, 11838, 11846, 11847, + 11848, 11866, 11867, 11868, 11869, 11870, 11871, 11872, 11873, 11874, + 11849, 11850, 11851, 11852, 11855, 11856, 11857, 11858, 11859, 11860, + 11853, 11854, 11861, 11864, 11865, 11862, 11863, 11882, 11883, 11886, + 11887, 11888, 11884, 11885, 11875, 11876, 11877, 11878, 11879, 11880, + 11881, 11889, 11890, 11891, 11892, 11893, 11894, 11895, 11898, 11899, + 11900, 11901, 11902, 11903, 11904, 11905, 11896, 11897, 11906, 11907, + 11914, 11915, 11916, 11908, 11909, 11910, 11911, 11917, 11918, 11919, + 11912, 11913, 11925, 11926, 11929, 11930, 11927, 11928, 11931, 11932, + 11920, 11921, 11922, 11923, 11924, 11933, 11934, 11935, 11940, 11941, + 11942, 11943, 11944, 11945, 11946, 11947, 11948, 11949, 11936, 11937, + 11938, 11939, 11951, 11952, 11955, 11953, 11954, 11956, 11957, 11958, + 11959, 11960, 11961, 11962, 11963, 12326, 12327, 12328, 12329, 12330, + 12331, 12332, 11969, 11967, 11968, 11964, 11965, 11966, 11970, 11971, + 11972, 11973, 11974, 11975, 11976, 11977, 11980, 11981, 11982, 11983, + 11984, 11978, 11979, 11985, 11986, 11987, 11988, 11989, 11990, 11991, + 11992, 11993, 11994, 11995, 11996, 11997, 12002, 11998, 11999, 12003, + 12004, 12005, 12000, 12001, 12006, 12007, 12008, 12014, 12015, 12016, + 12017, 12009, 12010, 12011, 12018, 12019, 12012, 12013, 12020, 12021, + 12025, 12026, 12027, 12028, 12029, 12030, 12022, 12023, 12024, 12031, + 12032, 12033, 12036, 12037, 12038, 12039, 12040, 12034, 12035, 12041, + 12042, 12043, 12044, 12045, 12046, 12047, 12048, 12049, 12050, 12051, + 12060, 12061, 12052, 12053, 12062, 12063, 12064, 12054, 12055, 12056, + 12057, 12058, 12059, 12069, 12065, 12066, 12070, 12071, 12072, 12073, + 12067, 12068, 12074, 12075, 12076, 12086, 12087, 12088, 12089, 12090, + 12091, 12092, 12093, 12094, 12095, 12081, 12082, 12077, 12078, 12079, + 12080, 12083, 12084, 12085, 12100, 12101, 12102, 12103, 12104, 12097, + 12098, 12099, 12105, 12106, 12107, 12134, 12135, 12136, 12137, 12138, + 12139, 12140, 12141, 12142, 12143, 12112, 12113, 12114, 12108, 12109, + 12115, 12116, 12117, 12118, 12119, 12110, 12111, 12122, 12123, 12120, + 12121, 12124, 12125, 12126, 12127, 12128, 12129, 12130, 12131, 12132, + 12133, 12147, 12148, 12149, 12150, 12151, 12152, 12153, 12154, 12155, + 12156, 12157, 12158, 12159, 12160, 12161, 12162, 12144, 12145, 12146, + 12163, 12164, 12173, 12165, 12166, 12167, 12168, 12170, 12171, 12172, + 12174, 12175, 12176, 12177, 12178, 12179, 12180, 12181, 12182, 12183, + 12184, 12185, 12186, 12187, 12188, 12189, 12190, 12191, 12192, 12193, + 12200, 12201, 12194, 12195, 12202, 12203, 12204, 12205, 12196, 12197, + 12198, 12199, 12206, 12207, 12208, 12209, 12214, 12210, 12211, 12215, + 12216, 12217, 12212, 12213, 12218, 12219, 12220, 12221, 12227, 12228, + 12223, 12224, 12229, 12230, 12231, 12232, 12233, 12225, 12226, 12234, + 12235, 12242, 12243, 12244, 12236, 12237, 12245, 12246, 12238, 12239, + 12240, 12241, 12247, 12250, 12251, 12252, 12253, 12248, 12249, 12254, + 12263, 12264, 12265, 12256, 12257, 12258, 12266, 12259, 12260, 12267, + 12261, 12262, 12268, 12269, 12270, 12271, 12272, 12273, 12274, 12275, + 12276, 12289, 12277, 12278, 12279, 12280, 12281, 12282, 12283, 12284, + 12285, 12286, 12287, 12288, 12290, 12291, 12292, 12293, 12313, 12314, + 12315, 12316, 12317, 12294, 12295, 12296, 12297, 12298, 12299, 12300, + 12301, 12302, 12303, 12304, 12305, 12306, 12307, 12308, 12309, 12310, + 12311, 12312, 11306, 11307, 11308, 11309, 11310, 11311, 11303, 11304, + 11305, 11312, 11313, 11317, 11318, 11319, 11320, 11321, 11322, 11323, + 11324, 11325, 11326, 11327, 11328, 11329, 11330, 11331, 11332, 11333, + 11334, 11335, 11336, 11314, 11315, 11316, 12169, 12222, 11658, 11683, + 11680, 11682, 11679, 11950, 11337, 11514, 11684, 11681, 11678, 11339, + 11516, 11338, 11515, 11777, 11582, 11656, 11695, 11657, 12096, 12255, + 11773, 11764, 11768, 11775, 11771, 11765, 11770, 11767, 11774, 11763, + 11769, 11776, 11772, 11766, 11762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 435, 436, 437, 438, 439, 440, 441, + 442, 443, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 365, + 366, 367, 368, 369, 370, 363, 364, 371, 372, 373, 415, 416, 417, 418, + 419, 420, 421, 422, 423, 413, 414, 381, 377, 378, 382, 383, 384, 379, + 380, 374, 375, 376, 385, 386, 387, 444, 445, 446, 447, 448, 449, 450, + 451, 452, 453, 392, 393, 394, 395, 396, 397, 388, 389, 390, 391, 398, + 399, 400, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, + 466, 467, 468, 469, 470, 471, 472, 473, 405, 406, 407, 408, 409, 410, + 411, 401, 402, 403, 404, 412, 485, 486, 487, 488, 489, 490, 491, 474, + 475, 476, 477, 482, 483, 484, 492, 478, 479, 480, 481, 493, 494, 495, + 496, 497, 500, 501, 502, 503, 498, 499, 504, 505, 506, 507, 510, 511, + 512, 513, 514, 508, 509, 515, 516, 517, 518, 521, 522, 523, 524, 525, + 519, 520, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, + 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, + 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, + 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, + 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 597, 598, 590, 591, + 592, 599, 600, 601, 602, 593, 594, 603, 595, 596, 608, 609, 610, 611, + 612, 604, 605, 606, 607, 613, 614, 615, 641, 642, 643, 644, 645, 646, + 647, 639, 640, 648, 649, 661, 662, 663, 664, 665, 666, 667, 668, 669, + 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, + 684, 685, 686, 687, 688, 689, 690, 652, 653, 654, 655, 656, 657, 658, + 650, 651, 659, 660, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, + 630, 631, 632, 633, 634, 635, 636, 637, 638, 628, 629, 620, 621, 622, + 623, 616, 617, 624, 625, 626, 627, 618, 619, 703, 704, 705, 706, 707, + 708, 709, 710, 711, 701, 702, 795, 796, 797, 798, 799, 800, 801, 802, + 803, 804, 714, 715, 716, 717, 718, 719, 720, 721, 722, 712, 713, 741, + 742, 738, 739, 740, 743, 744, 745, 734, 735, 736, 737, 746, 747, 748, + 805, 806, 807, 808, 809, 810, 811, 812, 813, 814, 725, 726, 727, 728, + 729, 730, 731, 732, 733, 723, 724, 753, 754, 755, 756, 749, 750, 757, + 758, 759, 751, 752, 760, 786, 784, 785, 787, 788, 789, 790, 791, 792, + 793, 794, 767, 763, 764, 768, 761, 762, 769, 770, 765, 766, 771, 772, + 773, 775, 776, 777, 774, 778, 779, 780, 781, 782, 783, 846, 847, 848, + 849, 850, 851, 852, 853, 854, 855, 815, 816, 817, 818, 819, 820, 821, + 822, 823, 824, 825, 856, 857, 858, 859, 860, 861, 862, 863, 864, 865, + 866, 867, 868, 869, 870, 871, 872, 873, 874, 875, 876, 877, 878, 879, + 880, 881, 882, 883, 884, 885, 826, 827, 830, 831, 832, 833, 834, 835, + 828, 829, 836, 837, 886, 887, 888, 889, 890, 891, 892, 893, 894, 895, + 896, 897, 898, 899, 900, 901, 902, 903, 904, 905, 906, 907, 908, 909, + 910, 911, 912, 913, 914, 915, 838, 839, 840, 841, 842, 843, 844, 845, + 917, 918, 919, 920, 921, 922, 923, 924, 925, 926, 927, 928, 929, 930, + 931, 932, 933, 934, 935, 936, 937, 938, 939, 940, 941, 942, 943, 944, + 945, 916, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 2827, 2794, 2852, 2853, 2823, + 2860, 2871, 2842, 2859, 2854, 2855, 2807, 2872, 2829, 2808, 2813, 2820, + 2866, 2838, 2797, 2832, 2867, 2828, 2804, 2805, 2836, 2810, 2851, 2793, + 2850, 2819, 2843, 2874, 2792, 2837, 2868, 2822, 2821, 2817, 2795, 2849, + 2826, 2856, 2809, 2846, 2857, 2873, 2802, 2863, 2870, 2811, 2798, 2825, + 2800, 2818, 2861, 2803, 2876, 2878, 2799, 2864, 2814, 2858, 2835, 2862, + 2840, 2847, 2831, 2875, 2830, 2812, 2844, 2815, 2841, 2869, 2865, 2848, + 2833, 2806, 2839, 2796, 2834, 2877, 2801, 2845, 2824, 2816, 2910, 2926, + 2924, 2923, 2889, 2895, 2884, 2930, 2894, 2886, 2916, 2929, 2888, 2914, + 2915, 2879, 2919, 2927, 2921, 2922, 2901, 2898, 2913, 2882, 2880, 2881, + 2887, 2917, 2934, 2908, 2906, 2931, 2920, 2928, 2900, 2904, 2905, 2902, + 2925, 2897, 2903, 2912, 2918, 2899, 2932, 2896, 2933, 2883, 2893, 2892, + 2890, 2907, 2911, 2891, 2885, 2909, 2986, 3006, 3027, 3023, 2985, 2974, + 2987, 2935, 2963, 2937, 3007, 3003, 2960, 3008, 2978, 2957, 2940, 2936, + 2942, 3026, 3005, 2968, 2998, 2966, 3028, 2947, 2948, 3012, 2979, 3016, + 2994, 3020, 3015, 2981, 3022, 2972, 2954, 3004, 2982, 2950, 2965, 2970, + 3001, 3017, 2984, 3031, 2975, 3000, 2997, 3030, 3021, 2962, 3032, 2990, + 2949, 3019, 2995, 2992, 2944, 2980, 2956, 2967, 2952, 2946, 2991, 2989, + 3024, 2983, 2999, 3002, 2945, 2996, 2976, 2953, 3029, 2977, 3013, 3011, + 2964, 2955, 2959, 2941, 2961, 2943, 2958, 3025, 2993, 2971, 2969, 3014, + 2939, 2938, 2988, 2973, 2951, 3009, 3010, 3018, 3060, 3144, 3093, 3067, + 3094, 3053, 3092, 3098, 3080, 3107, 3143, 3089, 3123, 3090, 3037, 3136, + 3121, 3096, 3128, 3041, 3145, 3043, 3130, 3065, 3075, 3056, 3062, 3132, + 3149, 3091, 3038, 3086, 3138, 3036, 3088, 3033, 3076, 3070, 3048, 3077, + 3072, 3071, 3113, 3069, 3066, 3054, 3099, 3058, 3046, 3105, 3134, 3133, + 3146, 3039, 3120, 3137, 3085, 3064, 3100, 3040, 3116, 3111, 3106, 3051, + 3079, 3068, 3083, 3147, 3115, 3148, 3078, 3102, 3127, 3044, 3082, 3087, + 3139, 3061, 3045, 3101, 3135, 3057, 3081, 3049, 3084, 3097, 3095, 3035, + 3042, 3117, 3141, 3140, 3108, 3119, 3050, 3063, 3055, 3129, 3074, 3125, + 3122, 3047, 3110, 3126, 3103, 3112, 3109, 3124, 3114, 3073, 3052, 3118, + 3142, 3104, 3059, 3131, 3034, 3203, 3280, 3190, 3177, 3287, 3180, 3243, + 3269, 3259, 3229, 3206, 3254, 3274, 3215, 3170, 3290, 3262, 3208, 3244, + 3279, 3172, 3182, 3231, 3221, 3187, 3218, 3222, 3230, 3261, 3228, 3247, + 3270, 3211, 3194, 3164, 3217, 3225, 3188, 3181, 3209, 3205, 3271, 3263, + 3257, 3202, 3210, 3295, 3163, 3284, 3291, 3251, 3283, 3167, 3268, 3277, + 3285, 3288, 3176, 3253, 3273, 3161, 3223, 3264, 3193, 3191, 3236, 3240, + 3160, 3282, 3171, 3303, 3234, 3296, 3192, 3204, 3249, 3299, 3179, 3153, + 3159, 3220, 3169, 3186, 3216, 3165, 3155, 3232, 3245, 3293, 3207, 3235, + 3237, 3252, 3196, 3154, 3239, 3197, 3162, 3152, 3200, 3255, 3219, 3173, + 3250, 3233, 3292, 3212, 3241, 3151, 3158, 3226, 3304, 3281, 3306, 3305, + 3178, 3242, 3272, 3275, 3201, 3267, 3294, 3213, 3300, 3297, 3298, 3302, + 3301, 3168, 3246, 3227, 3256, 3289, 3157, 3286, 3184, 3195, 3260, 3258, + 3214, 3224, 3265, 3266, 3150, 3238, 3248, 3183, 3175, 3198, 3185, 3189, + 3276, 3174, 3199, 3278, 3156, 3166, 3311, 3360, 3313, 3358, 3338, 3351, + 3332, 3315, 3341, 3340, 3320, 3350, 3330, 3326, 3317, 3348, 3343, 3349, + 3346, 3309, 3308, 3328, 3327, 3325, 3353, 3345, 3354, 3329, 3334, 3331, + 3355, 3335, 3342, 3333, 3337, 3307, 3323, 3324, 3344, 3336, 3359, 3356, + 3316, 3314, 3312, 3318, 3339, 3321, 3322, 3319, 3352, 3310, 3347, 3357, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 23535, 23527, 23548, + 23525, 23549, 23536, 23551, 23531, 23522, 23539, 23537, 23547, 23521, + 23529, 23524, 23526, 23532, 23530, 23528, 23541, 23544, 23533, 23543, + 23550, 23542, 23523, 23546, 23545, 23538, 23540, 23534, 35762, 23560, + 23562, 23559, 23558, 23555, 23554, 23557, 23556, 23563, 23561, 35762, + 35762, 35762, 35762, 23553, 23552, 30867, 30864, 30865, 30866, 30819, + 30816, 30817, 30818, 30871, 30868, 30869, 30870, 30859, 30856, 30857, + 30858, 30863, 30860, 30861, 30862, 30855, 30852, 30853, 30854, 30815, + 30812, 30813, 30814, 30847, 30844, 30845, 30846, 30820, 30825, 30836, + 30837, 30848, 30851, 30849, 30850, 30843, 30840, 30841, 30842, 30831, + 30828, 30829, 30830, 30882, 30881, 30880, 30832, 30839, 30889, 30887, + 30884, 30834, 30883, 30885, 30827, 30835, 30824, 30826, 30823, 30874, + 30878, 30886, 30833, 30838, 30876, 30873, 30879, 30822, 30872, 30888, + 30821, 30877, 30875, 30890, 35762, 30897, 30899, 30896, 30895, 30892, + 30891, 30894, 30893, 30900, 30898, 35762, 35762, 35762, 35762, 35762, + 35762, 3421, 3426, 3442, 3444, 3434, 3432, 3424, 3418, 3425, 3438, 3433, + 3429, 3440, 3423, 3419, 3441, 3428, 3439, 3443, 3437, 3431, 3445, 3430, + 3446, 3435, 3436, 3427, 3422, 3420, 3447, 35762, 35762, 3414, 3416, 3417, + 3415, 3413, 3448, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 26200, 26201, 26206, 26207, 26194, 26195, 26210, 26211, + 26202, 26203, 26192, 26193, 26212, 26213, 26196, 26197, 26208, 26209, + 26214, 26215, 26204, 26205, 26198, 26199, 26216, 26217, 26190, 26191, + 26136, 26127, 26133, 26124, 26129, 26135, 26128, 26132, 26138, 26122, + 26134, 26120, 26125, 26123, 26131, 26126, 26130, 26139, 26137, 26121, + 26144, 26143, 26141, 26140, 26142, 26146, 26145, 26176, 26177, 26155, + 26175, 26173, 26181, 26183, 26182, 26184, 26174, 26166, 26179, 26164, + 26186, 26159, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 26224, 26226, 26223, 26222, 26219, 26218, 26221, 26220, + 26227, 26225, 35762, 26151, 26148, 26150, 26153, 26147, 26149, 26152, + 35762, 26178, 26185, 26163, 26171, 26187, 26162, 26169, 26180, 26168, + 26189, 26170, 26165, 26172, 26188, 26167, 26161, 26154, 26157, 26158, + 26160, 26156, 35762, 35762, 35762, 35762, 35762, 26108, 26115, 26107, + 26106, 26116, 26104, 26101, 26119, 26111, 26109, 26117, 26103, 26102, + 26112, 26118, 26114, 26110, 26105, 26113, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 22208, 22212, 22215, 22216, 22186, 22218, 22194, 22209, + 22213, 22204, 22203, 22205, 22193, 22185, 22206, 22202, 22199, 22200, + 22214, 22196, 22207, 22210, 22192, 22190, 22217, 22201, 22198, 22188, + 22211, 22197, 22187, 22195, 22266, 22270, 22273, 22274, 22244, 22276, + 22252, 22267, 22271, 22262, 22261, 22263, 22251, 22243, 22264, 22260, + 22257, 22258, 22272, 22254, 22265, 22268, 22250, 22248, 22275, 22259, + 22256, 22246, 22269, 22255, 22245, 22253, 22230, 22224, 22222, 22220, + 22227, 22226, 22229, 22228, 22232, 22231, 22235, 22237, 22234, 22233, + 22238, 22239, 22241, 22242, 22236, 22240, 22225, 22223, 22221, 22219, + 22279, 22277, 22278, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 22822, 22748, 22810, 22821, 22826, 22825, + 22745, 22827, 22802, 22801, 22799, 22756, 22805, 22806, 22798, 22755, + 22764, 22772, 22808, 22744, 22769, 22768, 22763, 22762, 22761, 22760, + 22786, 22754, 22785, 22753, 22828, 22759, 22809, 22820, 22819, 22767, + 22766, 22743, 22824, 22830, 22758, 22757, 22795, 22751, 22771, 22770, + 22794, 22750, 22803, 22807, 22779, 22782, 22783, 22817, 22815, 22796, + 22752, 22804, 22784, 22818, 22816, 22814, 22812, 22742, 22813, 22811, + 22829, 22746, 22823, 22747, 22781, 22749, 22800, 22797, 22780, 35762, + 35762, 35762, 35762, 22834, 22765, 22833, 22832, 22831, 22839, 22845, + 22844, 22840, 22841, 22866, 22870, 22887, 22886, 22848, 22851, 22852, + 22868, 22855, 22856, 22857, 22858, 22859, 22862, 22864, 22865, 22861, + 22872, 22873, 22874, 22875, 22880, 22876, 22877, 22881, 22883, 22842, + 22843, 22850, 22885, 22849, 22884, 22846, 22854, 22847, 22871, 22888, + 22889, 22878, 22882, 22869, 22867, 22890, 22863, 22853, 22860, 22879, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 22838, 22836, 22837, + 22835, 22787, 22788, 22789, 22790, 22791, 22792, 22793, 22773, 22774, + 22775, 22776, 22777, 22778, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 31669, 25140, + 25317, 25316, 17699, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 33692, 33691, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 30901, 30902, 30903, 30904, 30905, 30906, 30907, 30908, 30909, 30910, + 30911, 30912, 30913, 30914, 30915, 30916, 30917, 30918, 30919, 30920, + 30921, 30922, 30923, 30924, 30925, 30926, 30927, 30928, 30929, 30930, + 30931, 30932, 30933, 30934, 30935, 30936, 30937, 30938, 30939, 30940, + 30941, 30942, 30943, 30944, 30945, 30946, 30947, 30948, 30949, 30950, + 30951, 30952, 30953, 30954, 30955, 30956, 30957, 30958, 30959, 30960, + 30961, 30962, 30963, 30964, 30965, 30966, 30967, 30968, 30969, 30970, + 30971, 30972, 30973, 30974, 30975, 30976, 30977, 30978, 30979, 30980, + 30981, 30982, 30983, 30984, 30985, 30986, 30987, 30988, 30989, 30990, + 30991, 30992, 30993, 30994, 30995, 30996, 30997, 30998, 30999, 31000, + 31001, 31002, 31003, 31004, 31005, 31006, 31007, 31008, 31009, 31010, + 31011, 31012, 31013, 31014, 31015, 31016, 31017, 31018, 31019, 31020, + 31021, 31022, 31023, 31024, 31025, 31026, 31027, 31028, 31029, 31030, + 31031, 31032, 31033, 31034, 31035, 31036, 31037, 31038, 31039, 31040, + 31041, 31042, 31043, 31044, 31045, 31046, 31047, 31048, 31049, 31050, + 31051, 31052, 31053, 31054, 31055, 31056, 31057, 31058, 31059, 31060, + 31061, 31062, 31063, 31064, 31065, 31066, 31067, 31068, 31069, 31070, + 31071, 31072, 31073, 31074, 31075, 31076, 31077, 31078, 31079, 31080, + 31081, 31082, 31083, 31084, 31085, 31086, 31087, 31088, 31089, 31090, + 31091, 31092, 31093, 31094, 31095, 31096, 31097, 31098, 31099, 31100, + 31101, 31102, 31103, 31104, 31105, 31106, 31107, 31108, 31109, 31110, + 31111, 31112, 31113, 31114, 31115, 31116, 31117, 31118, 31119, 31120, + 31121, 31122, 31123, 31124, 31125, 31126, 31127, 31128, 31129, 31130, + 31131, 31132, 31133, 31134, 31135, 31136, 31137, 31138, 31139, 31140, + 31141, 31142, 31143, 31144, 31145, 31146, 31147, 31148, 31149, 31150, + 31151, 31152, 31153, 31154, 31155, 31156, 31157, 31158, 31159, 31160, + 31161, 31162, 31163, 31164, 31165, 31166, 31167, 31168, 31169, 31170, + 31171, 31172, 31173, 31174, 31175, 31176, 31177, 31178, 31179, 31180, + 31181, 31182, 31183, 31184, 31185, 31186, 31187, 31188, 31189, 31190, + 31191, 31192, 31193, 31194, 31195, 31196, 31197, 31198, 31199, 31200, + 31201, 31202, 31203, 31204, 31205, 31206, 31207, 31208, 31209, 31210, + 31211, 31212, 31213, 31214, 31215, 31216, 31217, 31218, 31219, 31220, + 31221, 31222, 31223, 31224, 31225, 31226, 31227, 31228, 31229, 31230, + 31231, 31232, 31233, 31234, 31235, 31236, 31237, 31238, 31239, 31240, + 31241, 31242, 31243, 31244, 31245, 31246, 31247, 31248, 31249, 31250, + 31251, 31252, 31253, 31254, 31255, 31256, 31257, 31258, 31259, 31260, + 31261, 31262, 31263, 31264, 31265, 31266, 31267, 31268, 31269, 31270, + 31271, 31272, 31273, 31274, 31275, 31276, 31277, 31278, 31279, 31280, + 31281, 31282, 31283, 31284, 31285, 31286, 31287, 31288, 31289, 31290, + 31291, 31292, 31293, 31294, 31295, 31296, 31297, 31298, 31299, 31300, + 31301, 31302, 31303, 31304, 31305, 31306, 31307, 31308, 31309, 31310, + 31311, 31312, 31313, 31314, 31315, 31316, 31317, 31318, 31319, 31320, + 31321, 31322, 31323, 31324, 31325, 31326, 31327, 31328, 31329, 31330, + 31331, 31332, 31333, 31334, 31335, 31336, 31337, 31338, 31339, 31340, + 31341, 31342, 31343, 31344, 31345, 31346, 31347, 31348, 31349, 31350, + 31351, 31352, 31353, 31354, 31355, 31356, 31357, 31358, 31359, 31360, + 31361, 31362, 31363, 31364, 31365, 31366, 31367, 31368, 31369, 31370, + 31371, 31372, 31373, 31374, 31375, 31376, 31377, 31378, 31379, 31380, + 31381, 31382, 31383, 31384, 31385, 31386, 31387, 31388, 31389, 31390, + 31391, 31392, 31393, 31394, 31395, 31396, 31397, 31398, 31399, 31400, + 31401, 31402, 31403, 31404, 31405, 31406, 31407, 31408, 31409, 31410, + 31411, 31412, 31413, 31414, 31415, 31416, 31417, 31418, 31419, 31420, + 31421, 31422, 31423, 31424, 31425, 31426, 31427, 31428, 31429, 31430, + 31431, 31432, 31433, 31434, 31435, 31436, 31437, 31438, 31439, 31440, + 31441, 31442, 31443, 31444, 31445, 31446, 31447, 31448, 31449, 31450, + 31451, 31452, 31453, 31454, 31455, 31456, 31457, 31458, 31459, 31460, + 31461, 31462, 31463, 31464, 31465, 31466, 31467, 31468, 31469, 31470, + 31471, 31472, 31473, 31474, 31475, 31476, 31477, 31478, 31479, 31480, + 31481, 31482, 31483, 31484, 31485, 31486, 31487, 31488, 31489, 31490, + 31491, 31492, 31493, 31494, 31495, 31496, 31497, 31498, 31499, 31500, + 31501, 31502, 31503, 31504, 31505, 31506, 31507, 31508, 31509, 31510, + 31511, 31512, 31513, 31514, 31515, 31516, 31517, 31518, 31519, 31520, + 31521, 31522, 31523, 31524, 31525, 31526, 31527, 31528, 31529, 31530, + 31531, 31532, 31533, 31534, 31535, 31536, 31537, 31538, 31539, 31540, + 31541, 31542, 31543, 31544, 31545, 31546, 31547, 31548, 31549, 31550, + 31551, 31552, 31553, 31554, 31555, 31556, 31557, 31558, 31559, 31560, + 31561, 31562, 31563, 31564, 31565, 31566, 31567, 31568, 31569, 31570, + 31571, 31572, 31573, 31574, 31575, 31576, 31577, 31578, 31579, 31580, + 31581, 31582, 31583, 31584, 31585, 31586, 31587, 31588, 31589, 31590, + 31591, 31592, 31593, 31594, 31595, 31596, 31597, 31598, 31599, 31600, + 31601, 31602, 31603, 31604, 31605, 31606, 31607, 31608, 31609, 31610, + 31611, 31612, 31613, 31614, 31615, 31616, 31617, 31618, 31619, 31620, + 31621, 31622, 31623, 31624, 31625, 31626, 31627, 31628, 31629, 31630, + 31631, 31632, 31633, 31634, 31635, 31636, 31637, 31638, 31639, 31640, + 31641, 31642, 31643, 31644, 31645, 31646, 31647, 31648, 31649, 31650, + 31651, 31652, 31653, 31654, 31655, 31656, 31657, 31658, 31659, 31660, + 31661, 31662, 31663, 31664, 31665, 31666, 31667, 31668, 17229, 17230, + 17231, 17232, 17233, 17234, 17235, 17236, 17237, 17238, 17239, 17240, + 17241, 17242, 17243, 17244, 17245, 17246, 17247, 17248, 17249, 17250, + 17251, 17252, 17253, 17254, 17255, 17256, 17257, 17258, 17259, 17260, + 17261, 17262, 17263, 17264, 17265, 17266, 17267, 17268, 17269, 17270, + 17271, 17272, 17273, 17274, 17275, 17276, 17277, 17278, 17279, 17280, + 17281, 17282, 17283, 17284, 17285, 17286, 17287, 17288, 17289, 17290, + 17291, 17292, 17293, 17294, 17295, 17296, 17297, 17298, 17299, 17300, + 17301, 17302, 17303, 17304, 17305, 17306, 17307, 17308, 17309, 17310, + 17311, 17312, 17313, 17314, 17315, 17316, 17317, 17318, 17319, 17320, + 17321, 17322, 17323, 17324, 17325, 17326, 17327, 17328, 17329, 17330, + 17331, 17332, 17333, 17334, 17335, 17336, 17337, 17338, 17339, 17340, + 17341, 17342, 17343, 17344, 17345, 17346, 17347, 17348, 17349, 17350, + 17351, 17352, 17353, 17354, 17355, 17356, 17357, 17358, 17359, 17360, + 17361, 17362, 17363, 17364, 17365, 17366, 17367, 17368, 17369, 17370, + 17371, 17372, 17373, 17374, 17375, 17376, 17377, 17378, 17379, 17380, + 17381, 17382, 17383, 17384, 17385, 17386, 17387, 17388, 17389, 17390, + 17391, 17392, 17393, 17394, 17395, 17396, 17397, 17398, 17399, 17400, + 17401, 17402, 17403, 17404, 17405, 17406, 17407, 17408, 17409, 17410, + 17411, 17412, 17413, 17414, 17415, 17416, 17417, 17418, 17419, 17420, + 17421, 17422, 17423, 17424, 17425, 17426, 17427, 17428, 17429, 17430, + 17431, 17432, 17433, 17434, 17435, 17436, 17437, 17438, 17439, 17440, + 17441, 17442, 17443, 17444, 17445, 17446, 17447, 17448, 17449, 17450, + 17451, 17452, 17453, 17454, 17455, 17456, 17457, 17458, 17459, 17460, + 17461, 17462, 17463, 17464, 17465, 17466, 17467, 17468, 17469, 17470, + 17471, 17472, 17473, 17474, 17475, 17476, 17477, 17478, 17479, 17480, + 17481, 17482, 17483, 17484, 17491, 17492, 17493, 17494, 17495, 17496, + 17497, 17498, 17499, 17500, 17501, 17502, 17503, 17504, 17505, 17506, + 17507, 17508, 17509, 17510, 17511, 17512, 17513, 17514, 17515, 17516, + 17517, 17518, 17519, 17520, 17521, 17522, 17523, 17524, 17525, 17526, + 17527, 17528, 17529, 17530, 17531, 17532, 17533, 17534, 17535, 17536, + 17537, 17538, 17539, 17540, 17541, 17542, 17543, 17544, 17545, 17546, + 17547, 17548, 17549, 17550, 17551, 17552, 17553, 17554, 17555, 17556, + 17557, 17558, 17559, 17560, 17561, 17562, 17563, 17564, 17565, 17566, + 17567, 17568, 17569, 17570, 17571, 17572, 17573, 17574, 17575, 17576, + 17577, 17578, 17579, 17580, 17581, 17582, 17583, 17584, 17585, 17586, + 17587, 17588, 17589, 17590, 17591, 17592, 17593, 17594, 17595, 17596, + 17597, 17598, 17599, 17600, 17601, 17602, 17603, 17604, 17605, 17606, + 17607, 17608, 17609, 17610, 17611, 17612, 17613, 17614, 17615, 17616, + 17617, 17618, 17619, 17620, 17621, 17622, 17623, 17624, 17625, 17626, + 17627, 17628, 17629, 17630, 17631, 17632, 17633, 17634, 17635, 17636, + 17637, 17638, 17639, 17640, 17641, 17642, 17643, 17644, 17645, 17646, + 17647, 17648, 17649, 17650, 17651, 17652, 17653, 17654, 17655, 17656, + 17657, 17658, 17659, 17660, 17661, 17662, 17663, 17664, 17665, 17666, + 17667, 17668, 17669, 17670, 17671, 17672, 17673, 17674, 17675, 17676, + 17677, 17678, 17679, 17680, 17681, 17682, 17683, 17684, 17685, 17686, + 17687, 17688, 17689, 17690, 17691, 17692, 17693, 17694, 17695, 17696, + 17697, 17698, 17485, 17486, 17487, 17488, 17489, 17490, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 16870, 16871, 16872, 16873, 35762, 16874, 16875, 16863, 16864, 16865, + 16866, 16867, 35762, 16868, 16869, 35762, 16851, 15837, 15476, 15477, + 15478, 15475, 15757, 15758, 15759, 15760, 15749, 15750, 15751, 15752, + 15753, 15744, 15745, 15746, 15747, 15748, 15754, 15755, 15756, 15515, + 15519, 15520, 15521, 15522, 15523, 15524, 15525, 15526, 15516, 15517, + 15518, 15531, 15532, 15533, 15534, 15535, 15536, 15537, 15538, 15545, + 15546, 15547, 15548, 15549, 15550, 15551, 15539, 15540, 15541, 15542, + 15543, 15544, 15528, 15529, 15530, 15527, 15640, 15641, 15642, 15643, + 15644, 15645, 15646, 15647, 15656, 15657, 15658, 15659, 15660, 15661, + 15648, 15649, 15650, 15651, 15652, 15653, 15654, 15655, 15662, 15663, + 15664, 15665, 15666, 15667, 15668, 15669, 15670, 15671, 15672, 15673, + 15702, 15703, 15704, 15705, 15695, 15696, 15697, 15698, 15699, 15700, + 15701, 15691, 15692, 15693, 15694, 15690, 15674, 15675, 15676, 15677, + 15678, 15679, 15680, 15681, 15682, 15684, 15685, 15686, 15687, 15688, + 15689, 15683, 15594, 15595, 15596, 15597, 15598, 15599, 15600, 15601, + 15602, 15587, 15588, 15589, 15590, 15591, 15592, 15593, 15586, 15608, + 15609, 15610, 15580, 15581, 15582, 15583, 15584, 15585, 15579, 15603, + 15604, 15605, 15606, 15607, 15487, 15490, 15491, 15492, 15493, 15494, + 15495, 15496, 15497, 15488, 15489, 15508, 15509, 15510, 15511, 15512, + 15513, 15514, 15498, 15499, 15500, 15501, 15502, 15503, 15504, 15505, + 15506, 15507, 15479, 15480, 15481, 15482, 15483, 15484, 15485, 15486, + 15561, 15562, 15563, 15564, 15565, 15566, 15567, 15568, 15569, 15570, + 15571, 15572, 15573, 15574, 15575, 15576, 15577, 15578, 15553, 15554, + 15552, 15555, 15556, 15557, 15558, 15559, 15560, 15728, 15729, 15730, + 15731, 15732, 15727, 15739, 15740, 15741, 15742, 15733, 15734, 15735, + 15736, 15737, 15738, 15632, 15633, 15634, 15635, 15625, 15626, 15627, + 15628, 15629, 15630, 15631, 15619, 15620, 15621, 15622, 15623, 15624, + 15636, 15637, 15638, 15639, 15613, 15614, 15615, 15616, 15617, 15618, + 15706, 15707, 15708, 15709, 15710, 15711, 15712, 15713, 15714, 15715, + 15723, 15724, 15725, 15726, 15716, 15717, 15718, 15719, 15720, 15721, + 15722, 15611, 15612, 15836, 16849, 16848, 16850, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 15847, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 15840, 15839, 15841, 35762, 35762, 16898, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 16904, 16903, 16905, 16909, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 24744, 24745, 24746, 24747, 24748, 24749, + 24750, 24751, 24752, 24753, 24754, 24755, 24756, 24757, 24758, 24759, + 24760, 24761, 24762, 24763, 24764, 24765, 24766, 24767, 24768, 24769, + 24770, 24771, 24772, 24773, 24774, 24775, 24776, 24777, 24778, 24779, + 24780, 24781, 24782, 24783, 24784, 24785, 24786, 24787, 24788, 24789, + 24790, 24791, 24792, 24793, 24794, 24795, 24796, 24797, 24798, 24799, + 24800, 24801, 24802, 24803, 24804, 24805, 24806, 24807, 24808, 24809, + 24810, 24811, 24812, 24813, 24814, 24815, 24816, 24817, 24818, 24819, + 24820, 24821, 24822, 24823, 24824, 24825, 24826, 24827, 24828, 24829, + 24830, 24831, 24832, 24833, 24834, 24835, 24836, 24837, 24838, 24839, + 24840, 24841, 24842, 24843, 24844, 24845, 24846, 24847, 24848, 24849, + 24850, 24851, 24852, 24853, 24854, 24855, 24856, 24857, 24858, 24859, + 24860, 24861, 24862, 24863, 24864, 24865, 24866, 24867, 24868, 24869, + 24870, 24871, 24872, 24873, 24874, 24875, 24876, 24877, 24878, 24879, + 24880, 24881, 24882, 24883, 24884, 24885, 24886, 24887, 24888, 24889, + 24890, 24891, 24892, 24893, 24894, 24895, 24896, 24897, 24898, 24899, + 24900, 24901, 24902, 24903, 24904, 24905, 24906, 24907, 24908, 24909, + 24910, 24911, 24912, 24913, 24914, 24915, 24916, 24917, 24918, 24919, + 24920, 24921, 24922, 24923, 24924, 24925, 24926, 24927, 24928, 24929, + 24930, 24931, 24932, 24933, 24934, 24935, 24936, 24937, 24938, 24939, + 24940, 24941, 24942, 24943, 24944, 24945, 24946, 24947, 24948, 24949, + 24950, 24951, 24952, 24953, 24954, 24955, 24956, 24957, 24958, 24959, + 24960, 24961, 24962, 24963, 24964, 24965, 24966, 24967, 24968, 24969, + 24970, 24971, 24972, 24973, 24974, 24975, 24976, 24977, 24978, 24979, + 24980, 24981, 24982, 24983, 24984, 24985, 24986, 24987, 24988, 24989, + 24990, 24991, 24992, 24993, 24994, 24995, 24996, 24997, 24998, 24999, + 25000, 25001, 25002, 25003, 25004, 25005, 25006, 25007, 25008, 25009, + 25010, 25011, 25012, 25013, 25014, 25015, 25016, 25017, 25018, 25019, + 25020, 25021, 25022, 25023, 25024, 25025, 25026, 25027, 25028, 25029, + 25030, 25031, 25032, 25033, 25034, 25035, 25036, 25037, 25038, 25039, + 25040, 25041, 25042, 25043, 25044, 25045, 25046, 25047, 25048, 25049, + 25050, 25051, 25052, 25053, 25054, 25055, 25056, 25057, 25058, 25059, + 25060, 25061, 25062, 25063, 25064, 25065, 25066, 25067, 25068, 25069, + 25070, 25071, 25072, 25073, 25074, 25075, 25076, 25077, 25078, 25079, + 25080, 25081, 25082, 25083, 25084, 25085, 25086, 25087, 25088, 25089, + 25090, 25091, 25092, 25093, 25094, 25095, 25096, 25097, 25098, 25099, + 25100, 25101, 25102, 25103, 25104, 25105, 25106, 25107, 25108, 25109, + 25110, 25111, 25112, 25113, 25114, 25115, 25116, 25117, 25118, 25119, + 25120, 25121, 25122, 25123, 25124, 25125, 25126, 25127, 25128, 25129, + 25130, 25131, 25132, 25133, 25134, 25135, 25136, 25137, 25138, 25139, + 35762, 35762, 35762, 35762, 11196, 11194, 11143, 11176, 11103, 11116, + 11120, 11201, 11097, 11184, 11105, 11147, 11146, 11098, 11104, 11118, + 11150, 11179, 11172, 11099, 11119, 11173, 11197, 11123, 11151, 11124, + 11129, 11107, 11152, 11125, 11130, 11110, 11153, 11127, 11132, 11108, + 11109, 11161, 11162, 11128, 11133, 11114, 11165, 11126, 11131, 11111, + 11154, 11115, 11112, 11113, 11159, 11160, 11157, 11158, 11178, 11177, + 11186, 11192, 11189, 11164, 11163, 11117, 11106, 11155, 11156, 11095, + 11170, 11140, 11138, 11096, 11198, 11100, 11199, 11175, 11183, 11101, + 11167, 11148, 11166, 11121, 11200, 11180, 11102, 11195, 11181, 11122, + 11149, 11182, 11174, 11139, 11142, 11141, 11191, 11187, 11193, 11190, + 11188, 11137, 11136, 11135, 11134, 11145, 11144, 11168, 11171, 11169, + 11185, 35762, 35762, 35762, 35762, 35762, 11080, 11093, 11092, 11087, + 11094, 11074, 11067, 11066, 11063, 11065, 11068, 11069, 11064, 35762, + 35762, 35762, 11076, 11072, 11075, 11070, 11079, 11078, 11071, 11077, + 11073, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 11081, 11085, + 11088, 11083, 11091, 11090, 11084, 11089, 11086, 11082, 35762, 35762, + 11205, 11202, 11203, 11204, 27932, 27931, 27933, 27934, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35578, 35583, 35617, 35580, 35585, 35613, 35607, 35601, 35624, 35603, + 35597, 35621, 35579, 35584, 35618, 35581, 35586, 35614, 35608, 35602, + 35625, 35604, 35598, 35622, 35619, 35605, 35612, 35599, 35600, 35623, + 35606, 35582, 35628, 35593, 35610, 35620, 35631, 35630, 35596, 35629, + 35590, 35589, 35627, 35611, 35609, 35588, 35762, 35762, 35633, 35634, + 35635, 35626, 35576, 35591, 35594, 35595, 35573, 35574, 35592, 35615, + 35616, 35577, 35632, 35575, 35587, 35572, 35754, 35755, 35752, 35753, + 35756, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35652, 35653, 35669, 35641, 35650, 35749, 35704, 35705, 35672, 35673, + 35706, 35636, 35670, 35750, 35648, 35645, 35647, 35646, 35644, 35746, + 35745, 35748, 35747, 35742, 35741, 35744, 35743, 35642, 35676, 35638, + 35649, 35637, 35674, 35687, 35688, 35686, 35685, 35639, 35683, 35684, + 35682, 35680, 35681, 35679, 35678, 35689, 35691, 35692, 35690, 35654, + 35677, 35643, 35651, 35751, 35693, 35698, 35695, 35699, 35696, 35701, + 35702, 35697, 35694, 35700, 35675, 35703, 35736, 35733, 35724, 35734, + 35735, 35725, 35713, 35712, 35740, 35710, 35709, 35707, 35711, 35708, + 35727, 35732, 35726, 35730, 35731, 35728, 35729, 35656, 35660, 35659, + 35658, 35657, 35739, 35737, 35738, 35663, 35668, 35667, 35666, 35665, + 35664, 35714, 35723, 35716, 35721, 35715, 35719, 35720, 35717, 35718, + 35722, 35655, 35662, 35640, 35661, 35671, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 4893, 4765, 4886, 4868, 4869, + 4937, 4938, 4818, 4915, 4875, 4949, 4950, 4841, 4720, 4771, 4918, 4819, + 4723, 4724, 4913, 4925, 4864, 4801, 4892, 4744, 4941, 4813, 4827, 4823, + 4916, 4878, 4907, 4871, 4940, 4726, 4728, 4828, 4894, 4879, 4936, 4718, + 4896, 4910, 4912, 4866, 4920, 4848, 4766, 4928, 4919, 4838, 4719, 4778, + 4809, 4930, 4816, 4884, 4888, 4831, 4742, 4895, 4873, 4876, 4815, 4953, + 4883, 4832, 4931, 4908, 4807, 4814, 4865, 4870, 4882, 4834, 4881, 4839, + 4885, 4822, 4826, 4952, 4725, 4721, 4951, 4840, 4774, 4745, 4863, 4939, + 4880, 4889, 4872, 4717, 4849, 4877, 4874, 4770, 4842, 4716, 4932, 4773, + 4911, 4914, 4743, 4772, 4897, 4954, 4934, 4890, 4929, 4933, 4887, 4935, + 4891, 4804, 4730, 4769, 4867, 4922, 4923, 4921, 4924, 4817, 4767, 4942, + 4943, 4906, 4830, 4763, 4835, 4836, 4837, 4727, 4729, 4762, 4927, 4917, + 4833, 4843, 4847, 4846, 4845, 4844, 4803, 4800, 4799, 4757, 4759, 4760, + 4758, 4926, 4731, 4811, 4750, 4714, 4708, 4709, 4712, 4713, 4711, 4710, + 4715, 4856, 4851, 4852, 4850, 4861, 4860, 4859, 4858, 4862, 4854, 4812, + 4722, 4777, 4776, 4775, 4857, 4855, 4853, 4805, 4806, 4768, 4810, 4808, + 4779, 4786, 4782, 4790, 4785, 4794, 4784, 4783, 4780, 4781, 4788, 4789, + 4796, 4793, 4791, 4740, 4741, 4739, 4787, 4795, 4948, 4753, 4751, 4754, + 4756, 4755, 4752, 4944, 4946, 4945, 4947, 4797, 4798, 4747, 4746, 4748, + 4749, 4902, 4905, 4903, 4904, 4898, 4901, 4899, 4900, 4761, 4764, 4909, + 4738, 4732, 4737, 4735, 4734, 4733, 4736, 4820, 4824, 4821, 4825, 4829, + 4802, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 23803, 23680, 23696, 23788, 23675, 23800, 23738, 23789, 23787, + 23676, 23672, 23799, 23666, 23784, 23785, 23786, 23691, 23692, 23629, + 23630, 23625, 23624, 23755, 23826, 23823, 23698, 23697, 23804, 23805, + 23699, 23708, 23709, 23710, 23669, 23701, 23702, 23703, 23682, 23683, + 35762, 35762, 23746, 23679, 23681, 23707, 23706, 23751, 23750, 23802, + 23801, 23778, 23779, 23665, 23671, 23767, 23768, 23782, 23783, 23747, + 23849, 23721, 23781, 23690, 23807, 23825, 23809, 23754, 23847, 23770, + 23670, 23810, 23811, 23834, 23835, 23838, 23839, 23836, 23837, 23830, + 23831, 23832, 23833, 23744, 23745, 23840, 23841, 23769, 23845, 23752, + 23749, 23633, 23634, 23628, 23848, 23720, 23780, 23689, 23806, 23824, + 23808, 23753, 23654, 23655, 23658, 23659, 23660, 23693, 23694, 23695, + 23637, 23644, 23645, 23646, 23647, 23648, 23622, 23687, 23623, 23688, + 23621, 23685, 23620, 23684, 23635, 23653, 23661, 23652, 23638, 23639, + 23636, 23663, 23718, 23717, 23642, 23664, 23649, 23656, 23662, 23641, + 23657, 23790, 23813, 23852, 23777, 23740, 23700, 23668, 23677, 23714, + 23713, 23829, 23842, 23851, 23843, 23844, 23756, 23759, 23760, 23761, + 23762, 23763, 23764, 23765, 23766, 23757, 23758, 23722, 23748, 23686, + 23678, 23640, 23643, 23650, 23651, 23772, 23771, 23719, 23712, 23711, + 23850, 23673, 23674, 23739, 23735, 23626, 23793, 23795, 23741, 23743, + 23796, 23798, 23704, 23705, 23737, 23736, 23627, 23794, 23742, 23797, + 23821, 23820, 23822, 23819, 23815, 23816, 23817, 23818, 23667, 23715, + 23716, 23812, 23846, 23774, 23632, 23791, 23631, 23827, 23775, 23776, + 23792, 23828, 23773, 23723, 23726, 23730, 23733, 23732, 23731, 23727, + 23728, 23724, 23725, 23729, 23814, 23734, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 14240, 14228, 14251, + 14252, 14234, 14253, 14254, 14255, 14256, 14241, 14242, 14243, 14244, + 14245, 14246, 14247, 14248, 14249, 14250, 14229, 14230, 14231, 14232, + 14233, 14235, 14236, 14237, 14238, 14239, 13960, 13968, 13981, 13989, + 13995, 13996, 13961, 13962, 13963, 13964, 13965, 13966, 13967, 13969, + 13970, 13971, 13972, 13973, 13974, 13975, 13976, 13977, 13978, 13979, + 13980, 13982, 13983, 13984, 13985, 13986, 13987, 13988, 13990, 13991, + 13992, 13993, 13994, 7968, 7967, 7969, 14020, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 17140, 17141, + 17138, 17136, 17127, 17126, 17133, 17131, 17122, 17129, 17139, 17124, + 17137, 17135, 17128, 17125, 17134, 17132, 17123, 17130, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 22166, 22167, 22164, 22162, 22153, 22152, 22159, 22157, 22148, 22155, + 22165, 22150, 22163, 22161, 22154, 22151, 22160, 22158, 22149, 22156, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 23494, 10576, 10577, 10571, 10570, 10569, 31810, 31830, + 31851, 31799, 31844, 31808, 31794, 31853, 31798, 31812, 31818, 31841, + 31842, 31856, 31862, 31809, 31840, 31870, 31828, 31795, 31858, 31860, + 31827, 31873, 31807, 31822, 31819, 31800, 31814, 31797, 31855, 31848, + 31802, 31845, 31834, 31868, 31857, 31831, 31859, 31847, 31861, 31836, + 31824, 31867, 31837, 31823, 31854, 31863, 31833, 31869, 31806, 31850, + 31826, 31872, 31816, 31801, 31838, 31835, 31849, 31793, 31821, 31820, + 31871, 31865, 31843, 31813, 31811, 31817, 31825, 31864, 31866, 31839, + 31805, 31803, 31832, 31796, 31804, 31852, 31815, 31846, 31829, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 8366, 8364, 8363, + 8360, 8359, 8362, 8361, 8367, 8365, 8357, 8355, 8354, 8351, 8350, 8353, + 8352, 8358, 8356, 16051, 16050, 16049, 16048, 16047, 30395, 30394, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 21146, 21148, 21176, 21139, 21152, 21184, + 21155, 21185, 21157, 21186, 21159, 21161, 21178, 21180, 21163, 21166, + 21187, 21170, 21172, 21142, 21174, 21188, 21189, 21182, 21190, 21150, + 21194, 21196, 21229, 21191, 21200, 21203, 21205, 21237, 21207, 21238, + 21209, 21211, 21231, 21233, 21213, 21216, 21239, 21220, 21222, 21224, + 21227, 21240, 21241, 21235, 21242, 21198, 21634, 21636, 21666, 21640, + 21642, 21674, 21645, 21675, 21647, 21676, 21649, 21651, 21668, 21670, + 21653, 21656, 21677, 21660, 21662, 21630, 21664, 21678, 21679, 21672, + 21680, 21638, 21582, 21584, 21617, 21578, 21588, 21591, 21593, 35762, + 21595, 21625, 21597, 21599, 21619, 21621, 21601, 21604, 21626, 21608, + 21610, 21612, 21615, 21627, 21628, 21623, 21629, 21586, 21299, 21301, + 21331, 21305, 21307, 21339, 21310, 21340, 21312, 21341, 21314, 21316, + 21333, 21335, 21318, 21321, 21342, 21325, 21327, 21295, 21329, 21343, + 21344, 21337, 21345, 21303, 21353, 21355, 21390, 21359, 21361, 21364, + 21366, 21398, 21368, 21399, 21370, 21372, 21392, 21394, 21374, 21377, + 21400, 21381, 21383, 21385, 21388, 21401, 21402, 21396, 21403, 21357, + 22106, 35762, 22107, 22108, 35762, 35762, 22109, 35762, 35762, 22110, + 22111, 35762, 35762, 22112, 22113, 22114, 22115, 35762, 22116, 22117, + 22118, 22119, 22120, 22121, 22122, 22123, 22124, 22125, 22126, 22127, + 35762, 22128, 35762, 22129, 22130, 22131, 22132, 22133, 22134, 22135, + 35762, 22136, 22137, 22138, 22139, 22140, 22141, 22142, 22143, 22144, + 22145, 22146, 21243, 21244, 21245, 21246, 21247, 21248, 21249, 21250, + 21251, 21252, 21253, 21254, 21255, 21256, 21257, 21258, 21259, 21260, + 21261, 21262, 21263, 21264, 21265, 21266, 21267, 21268, 21269, 21270, + 21271, 21272, 21273, 21274, 21275, 21276, 21277, 21278, 21279, 21280, + 21281, 21282, 21283, 21284, 21285, 21286, 21287, 21288, 21289, 21290, + 21291, 21292, 21293, 21294, 21530, 21531, 35762, 21532, 21533, 21534, + 21535, 35762, 35762, 21536, 21537, 21538, 21539, 21540, 21541, 21542, + 21543, 35762, 21544, 21545, 21546, 21547, 21548, 21549, 21550, 35762, + 21551, 21552, 21553, 21554, 21555, 21556, 21557, 21558, 21559, 21560, + 21561, 21562, 21563, 21564, 21565, 21566, 21567, 21568, 21569, 21570, + 21571, 21572, 21573, 21574, 21575, 21576, 21475, 21476, 35762, 21477, + 21478, 21479, 21480, 35762, 21481, 21482, 21483, 21484, 21485, 35762, + 21486, 35762, 35762, 35762, 21487, 21488, 21489, 21490, 21491, 21492, + 21493, 35762, 21494, 21495, 21496, 21497, 21498, 21499, 21500, 21501, + 21502, 21503, 21504, 21505, 21506, 21507, 21508, 21509, 21510, 21511, + 21512, 21513, 21514, 21515, 21516, 21517, 21518, 21519, 21413, 21414, + 21415, 21416, 21417, 21418, 21419, 21420, 21421, 21422, 21423, 21424, + 21425, 21426, 21427, 21428, 21429, 21430, 21431, 21432, 21433, 21434, + 21435, 21436, 21437, 21438, 21439, 21440, 21441, 21442, 21443, 21444, + 21445, 21446, 21447, 21448, 21449, 21450, 21451, 21452, 21453, 21454, + 21455, 21456, 21457, 21458, 21459, 21460, 21461, 21462, 21463, 21464, + 22044, 22045, 22046, 22047, 22048, 22049, 22050, 22051, 22052, 22053, + 22054, 22055, 22056, 22057, 22058, 22059, 22060, 22061, 22062, 22063, + 22064, 22065, 22066, 22067, 22068, 22069, 22070, 22071, 22072, 22073, + 22074, 22075, 22076, 22077, 22078, 22079, 22080, 22081, 22082, 22083, + 22084, 22085, 22086, 22087, 22088, 22089, 22090, 22091, 22092, 22093, + 22094, 22095, 21876, 21878, 21908, 21882, 21884, 21916, 21887, 21917, + 21889, 21918, 21891, 21893, 21910, 21912, 21895, 21898, 21919, 21902, + 21904, 21872, 21906, 21920, 21921, 21914, 21922, 21880, 21930, 21932, + 21967, 21936, 21938, 21941, 21943, 21975, 21945, 21976, 21947, 21949, + 21969, 21971, 21951, 21954, 21977, 21958, 21960, 21962, 21965, 21978, + 21979, 21973, 21980, 21934, 21992, 21993, 21994, 21995, 21996, 21997, + 21998, 21999, 22000, 22001, 22002, 22003, 22004, 22005, 22006, 22007, + 22008, 22009, 22010, 22011, 22012, 22013, 22014, 22015, 22016, 22017, + 22018, 22019, 22020, 22021, 22022, 22023, 22024, 22025, 22026, 22027, + 22028, 22029, 22030, 22031, 22032, 22033, 22034, 22035, 22036, 22037, + 22038, 22039, 22040, 22041, 22042, 22043, 21766, 21768, 21798, 21772, + 21774, 21806, 21777, 21807, 21779, 21808, 21781, 21783, 21800, 21802, + 21785, 21788, 21809, 21792, 21794, 21762, 21796, 21810, 21811, 21804, + 21812, 21770, 21820, 21822, 21857, 21826, 21828, 21831, 21833, 21865, + 21835, 21866, 21837, 21839, 21859, 21861, 21841, 21844, 21867, 21848, + 21850, 21852, 21855, 21868, 21869, 21863, 21870, 21824, 21689, 21690, + 21691, 21692, 21693, 21694, 21695, 21696, 21697, 21698, 21699, 21700, + 21701, 21702, 21703, 21704, 21705, 21706, 21707, 21708, 21709, 21710, + 21711, 21712, 21713, 21714, 21715, 21716, 21717, 21718, 21719, 21720, + 21721, 21722, 21723, 21724, 21725, 21726, 21727, 21728, 21729, 21730, + 21731, 21732, 21733, 21734, 21735, 21736, 21737, 21738, 21739, 21740, + 21579, 21580, 35762, 35762, 21147, 21149, 21156, 21141, 21153, 21151, + 21154, 21143, 21158, 21160, 21162, 21179, 21181, 21183, 21164, 21169, + 21171, 21144, 21173, 21145, 21175, 21167, 21177, 21168, 21165, 21407, + 21195, 21197, 21206, 21193, 21201, 21199, 21202, 21225, 21208, 21210, + 21212, 21232, 21234, 21236, 21214, 21219, 21221, 21204, 21223, 21226, + 21228, 21217, 21230, 21218, 21215, 21409, 21405, 21412, 21406, 21408, + 21411, 21410, 21635, 21637, 21646, 21641, 21643, 21639, 21644, 21631, + 21648, 21650, 21652, 21669, 21671, 21673, 21654, 21659, 21661, 21632, + 21663, 21633, 21665, 21657, 21667, 21658, 21655, 21683, 21583, 21585, + 21594, 21581, 21589, 21587, 21590, 21613, 21596, 21598, 21600, 21620, + 21622, 21624, 21602, 21607, 21609, 21592, 21611, 21614, 21616, 21605, + 21618, 21606, 21603, 21685, 21681, 21688, 21682, 21684, 21687, 21686, + 21300, 21302, 21311, 21306, 21308, 21304, 21309, 21296, 21313, 21315, + 21317, 21334, 21336, 21338, 21319, 21324, 21326, 21297, 21328, 21298, + 21330, 21322, 21332, 21323, 21320, 21348, 21354, 21356, 21367, 21360, + 21362, 21358, 21363, 21386, 21369, 21371, 21373, 21393, 21395, 21397, + 21375, 21380, 21382, 21365, 21384, 21387, 21389, 21378, 21391, 21379, + 21376, 21350, 21346, 21404, 21347, 21349, 21352, 21351, 21877, 21879, + 21888, 21883, 21885, 21881, 21886, 21873, 21890, 21892, 21894, 21911, + 21913, 21915, 21896, 21901, 21903, 21874, 21905, 21875, 21907, 21899, + 21909, 21900, 21897, 21925, 21931, 21933, 21944, 21937, 21939, 21935, + 21940, 21963, 21946, 21948, 21950, 21970, 21972, 21974, 21952, 21957, + 21959, 21942, 21961, 21964, 21966, 21955, 21968, 21956, 21953, 21927, + 21923, 21981, 21924, 21926, 21929, 21928, 21767, 21769, 21778, 21773, + 21775, 21771, 21776, 21763, 21780, 21782, 21784, 21801, 21803, 21805, + 21786, 21791, 21793, 21764, 21795, 21765, 21797, 21789, 21799, 21790, + 21787, 21815, 21821, 21823, 21834, 21827, 21829, 21825, 21830, 21853, + 21836, 21838, 21840, 21860, 21862, 21864, 21842, 21847, 21849, 21832, + 21851, 21854, 21856, 21845, 21858, 21846, 21843, 21817, 21813, 21871, + 21814, 21816, 21819, 21818, 21140, 21192, 35762, 35762, 21471, 21473, + 21470, 21469, 21466, 21465, 21468, 21467, 21474, 21472, 21526, 21528, + 21525, 21524, 21521, 21520, 21523, 21522, 21529, 21527, 22102, 22104, + 22101, 22100, 22097, 22096, 22099, 22098, 22105, 22103, 21988, 21990, + 21987, 21986, 21983, 21982, 21985, 21984, 21991, 21989, 21747, 21749, + 21746, 21745, 21742, 21741, 21744, 21743, 21750, 21748, 28184, 28140, + 28165, 28381, 28336, 28122, 28185, 28149, 28298, 28250, 28226, 28187, + 28190, 28147, 28191, 28141, 28192, 28214, 28209, 28247, 28188, 28194, + 28203, 28204, 28195, 28201, 28205, 28143, 28277, 28186, 28215, 28144, + 28224, 28193, 28223, 28210, 28249, 28248, 28189, 28208, 28218, 28219, + 28222, 28221, 28289, 28197, 28198, 28199, 28271, 28239, 28202, 28206, + 28200, 28196, 28270, 28231, 28269, 28268, 28228, 28227, 28230, 28220, + 28217, 28216, 28266, 28265, 28267, 28238, 28314, 28318, 28317, 28315, + 28316, 28159, 28305, 28335, 28307, 28320, 28312, 28321, 28313, 28322, + 28311, 28169, 28170, 28334, 28380, 28308, 28309, 28310, 28306, 28332, + 28319, 28330, 28323, 28331, 28329, 28327, 28324, 28325, 28326, 28328, + 28156, 28162, 28160, 28161, 28365, 28364, 28172, 28164, 28175, 28178, + 28173, 28176, 28174, 28177, 28182, 28179, 28139, 28374, 28379, 28376, + 28378, 28353, 28355, 28333, 28363, 28356, 28360, 28354, 28362, 28361, + 28359, 28121, 28211, 28146, 28338, 28124, 28347, 28213, 28212, 28339, + 28252, 28255, 28254, 28253, 28262, 28302, 28151, 28375, 28133, 28258, + 28261, 28256, 28257, 28350, 28260, 28349, 28132, 28131, 28259, 28150, + 28348, 28130, 28225, 28145, 28340, 28357, 28123, 28207, 28142, 28278, + 28358, 28134, 28286, 28282, 28284, 28155, 28377, 28135, 28279, 28281, + 28280, 28285, 28283, 28373, 28251, 28148, 28180, 28367, 28368, 28366, + 28168, 28346, 28126, 28125, 28275, 28351, 28273, 28154, 28263, 28274, + 28372, 28272, 28276, 28264, 28152, 28181, 28171, 28352, 28137, 28138, + 28136, 28153, 28157, 28158, 28370, 28371, 28369, 28337, 28240, 28342, + 28243, 28244, 28245, 28242, 28246, 28241, 28235, 28236, 28237, 28234, + 28232, 28163, 28233, 28229, 28166, 28167, 28344, 28345, 28341, 28343, + 28128, 28129, 28127, 28287, 28292, 28295, 28296, 28297, 28303, 28288, + 28290, 28291, 28299, 28294, 28300, 28301, 28293, 28183, 28304, 28695, + 28694, 28693, 28715, 28714, 28713, 28670, 28669, 28668, 28054, 28053, + 28052, 28656, 28655, 28654, 28666, 28667, 28662, 28665, 28661, 28664, + 28663, 28111, 28114, 28110, 28113, 28112, 28660, 28530, 28531, 28532, + 28533, 28528, 28529, 28534, 28574, 28479, 28592, 28591, 28589, 28590, + 28593, 28568, 28571, 28569, 28570, 28567, 28598, 28597, 28595, 28596, + 28544, 28543, 28542, 28548, 28547, 28546, 28545, 28566, 28565, 28564, + 28541, 28540, 28539, 28614, 28613, 28612, 28588, 28587, 28586, 28711, + 28710, 28709, 28708, 28707, 28706, 28712, 28705, 28704, 28703, 28448, + 28447, 28445, 28446, 28452, 28451, 28449, 28450, 28440, 28439, 28437, + 28438, 28444, 28443, 28441, 28442, 28502, 28501, 28499, 28500, 28503, + 28517, 28520, 28518, 28519, 28476, 28507, 28506, 28505, 28504, 28462, + 28475, 28474, 28473, 28463, 28461, 28460, 28459, 28526, 28525, 28524, + 28523, 28522, 28521, 28698, 28697, 28696, 28701, 28700, 28699, 28702, + 28561, 28560, 28558, 28559, 28552, 28551, 28549, 28550, 28557, 28556, + 28579, 28578, 28575, 28580, 28585, 28582, 28581, 28601, 28600, 28599, + 28604, 28603, 28602, 28555, 28563, 28562, 28651, 28648, 28647, 28594, + 28554, 28577, 28584, 28609, 28653, 28650, 28646, 28553, 28576, 28583, + 28608, 28652, 28649, 28645, 28607, 28606, 28605, 28466, 28465, 28483, + 28481, 28482, 28480, 28492, 28490, 28491, 28489, 28509, 28508, 28640, + 28637, 28643, 28468, 28467, 28484, 28485, 28487, 28486, 28496, 28494, + 28495, 28493, 28511, 28510, 28641, 28638, 28644, 28472, 28471, 28469, + 28470, 28464, 28488, 28497, 28512, 28513, 28514, 28639, 28636, 28642, + 28498, 28538, 28536, 28537, 28535, 28458, 28456, 28454, 28457, 28455, + 28453, 28611, 28610, 28516, 28515, 28573, 28572, 28478, 28477, 28070, + 28069, 28065, 28068, 28072, 28071, 28066, 28067, 28064, 28073, 28383, + 28390, 28388, 28387, 28385, 28386, 28384, 28389, 28103, 28101, 28102, + 28079, 28078, 28077, 28062, 28060, 28061, 28063, 28118, 28117, 28116, + 28097, 28098, 28094, 28075, 28074, 28093, 28095, 28092, 28096, 28076, + 28091, 28089, 28090, 28086, 28088, 28087, 28080, 28082, 28081, 28084, + 28083, 28085, 28057, 28056, 28055, 28680, 28679, 28681, 28100, 28617, + 28616, 28619, 28618, 28047, 28049, 28046, 28048, 28051, 28050, 28412, + 28410, 28411, 28417, 28419, 28418, 28414, 28416, 28415, 28431, 28430, + 28429, 28423, 28424, 28425, 28426, 28427, 28428, 28420, 28422, 28421, + 28432, 28433, 28434, 28401, 28399, 28400, 28413, 28436, 28435, 28688, + 28687, 28685, 28686, 28684, 28689, 28683, 28682, 28672, 28677, 28675, + 28676, 28673, 28674, 28678, 28615, 28527, 28620, 28382, 28099, 28658, + 28657, 28120, 28115, 28659, 28691, 28690, 28692, 28716, 28391, 28392, + 28393, 28394, 28395, 28396, 28397, 28398, 28109, 28409, 28408, 28403, + 28406, 28405, 28402, 28404, 28407, 28059, 28119, 28671, 28058, 28717, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 28104, 28105, 28106, 28107, 28108, + 35762, 28628, 28629, 28630, 28631, 28632, 28633, 28634, 28635, 28621, + 28622, 28623, 28624, 28625, 28626, 28627, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 18911, 19184, 18676, 19189, + 18663, 19034, 19294, 19186, 19280, 19249, 18656, 18890, 18891, 19284, + 18651, 18703, 18677, 19028, 18827, 19008, 18888, 19278, 19165, 19253, + 18899, 18828, 18972, 19124, 19254, 18794, 19201, 35762, 35762, 35762, + 35762, 35762, 35762, 18818, 19021, 19066, 19170, 19208, 19244, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 7924, 7926, 7936, 7930, 7912, 7937, 7944, 35762, 7943, + 7917, 7914, 7913, 7911, 7948, 7932, 7931, 7933, 7947, 7934, 7935, 7919, + 7922, 7946, 7928, 7945, 35762, 35762, 7920, 7923, 7927, 7921, 7939, 7938, + 7940, 35762, 7942, 7918, 35762, 7941, 7916, 7925, 7915, 7929, 35762, + 35762, 35762, 35762, 35762, 23081, 23050, 23078, 23076, 23052, 23074, + 23071, 23072, 23073, 23080, 23057, 23058, 23082, 23061, 23059, 23054, + 23067, 23083, 23056, 23079, 23066, 23075, 23065, 23068, 23053, 23070, + 23051, 23064, 23048, 23077, 23049, 23062, 23060, 10214, 10192, 10212, + 10199, 10195, 10209, 10206, 10207, 10208, 10213, 10197, 10215, 10211, + 10198, 10216, 10196, 10201, 10205, 10210, 10204, 10202, 10203, 10200, + 10191, 10194, 10193, 23055, 23069, 23063, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 7841, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 25172, 25156, 25147, 25158, 25165, 25155, 25160, 25151, + 25177, 25181, 25183, 25186, 25150, 25145, 25180, 25170, 25154, 25153, + 25184, 25146, 25157, 25178, 25164, 25182, 25185, 25152, 25174, 25159, + 25149, 25169, 25148, 25166, 25171, 25173, 25179, 25163, 25161, 25162, + 25187, 25188, 25167, 25168, 25175, 25176, 25189, 35762, 35762, 35762, + 25198, 25202, 25201, 25204, 25203, 25200, 25199, 25194, 25192, 25191, + 25195, 25193, 25196, 25197, 35762, 35762, 25211, 25213, 25210, 25209, + 25206, 25205, 25208, 25207, 25214, 25212, 35762, 35762, 35762, 35762, + 25190, 25144, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 32479, 32462, 32482, 32472, 32476, 32473, 32478, 32466, + 32465, 32481, 32469, 32484, 32483, 32475, 32474, 32480, 32477, 32463, + 32457, 32464, 32458, 32486, 32467, 32459, 32468, 32460, 32485, 32471, + 32461, 32470, 32487, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 33793, 33792, 33824, 33825, 33826, 33828, 33817, 33820, 33806, 33809, + 33821, 33813, 33810, 33827, 33823, 33822, 33830, 33835, 33834, 33833, + 33819, 33798, 33797, 33832, 33831, 33818, 33829, 33801, 33803, 33807, + 33814, 33805, 33812, 33811, 33800, 33795, 33796, 33804, 33799, 33802, + 33794, 33808, 33815, 33816, 33839, 33840, 33837, 33838, 33847, 33849, + 33846, 33845, 33842, 33841, 33844, 33843, 33850, 33848, 35762, 35762, + 35762, 35762, 35762, 33836, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 24159, 24162, 24161, 24163, 24160, 24142, 24146, 24144, + 24143, 24145, 24154, 24157, 24155, 24158, 24156, 24164, 24165, 24166, + 24167, 24168, 24147, 24149, 24152, 24153, 24148, 24151, 24150, 24172, + 24169, 24173, 24171, 24170, 24180, 24182, 24179, 24178, 24175, 24174, + 24177, 24176, 24183, 24181, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 12689, 12695, 12693, 12690, 12692, 12691, + 12694, 35762, 12644, 12688, 12686, 12685, 35762, 12632, 12631, 35762, + 12643, 12642, 12641, 12628, 12627, 12640, 12639, 12638, 12637, 12636, + 12635, 12630, 12629, 12634, 12633, 35762, 22398, 22399, 22400, 22466, + 22487, 22475, 22440, 22573, 22401, 22402, 22406, 22525, 22510, 22515, + 22439, 22591, 22542, 22461, 22445, 22536, 22405, 22403, 22404, 22451, + 22495, 22548, 22586, 22411, 22407, 22415, 22552, 22490, 22501, 22528, + 22416, 22413, 22412, 22565, 22503, 22563, 22541, 22532, 22530, 22531, + 22592, 22571, 22410, 22425, 22417, 22564, 22509, 22534, 22470, 22593, + 22421, 22422, 22423, 22479, 22471, 22455, 22556, 22507, 22408, 22414, + 22409, 22482, 22577, 22578, 22418, 22419, 22420, 22493, 22448, 22498, + 22465, 22426, 22424, 22427, 22551, 22508, 22557, 22459, 22569, 22428, + 22432, 22436, 22505, 22477, 22545, 22526, 22429, 22433, 22434, 22476, + 22468, 22533, 22486, 22594, 22497, 22435, 22430, 22431, 22513, 22566, + 22572, 22444, 22584, 22437, 22496, 22446, 22543, 22483, 22522, 22453, + 22535, 22485, 22452, 22590, 22442, 22488, 22438, 22484, 22512, 22538, + 22550, 22520, 22555, 22523, 22481, 22499, 22580, 22549, 22516, 22559, + 22587, 22562, 22560, 22583, 22456, 22570, 22463, 22491, 22447, 22478, + 22454, 22502, 22458, 22537, 22457, 22517, 22443, 22581, 22472, 22567, + 22568, 22585, 22558, 22500, 22540, 22529, 22492, 22467, 22441, 22506, + 22514, 22553, 22519, 22449, 22544, 22489, 22504, 22473, 22474, 22576, + 22518, 22521, 22524, 22588, 22511, 22460, 22462, 22547, 22589, 22539, + 22527, 22579, 22582, 22554, 22574, 22480, 22546, 22469, 22561, 22450, + 22575, 22494, 22464, 35762, 35762, 22602, 22600, 22599, 22596, 22595, + 22598, 22597, 22603, 22601, 22393, 22392, 22396, 22394, 22391, 22395, + 22397, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 27, 9, 24, 14, 29, 21, 34, 28, 37, 39, 35, 40, 41, 10, 30, + 32, 18, 15, 31, 42, 13, 25, 36, 23, 12, 20, 33, 19, 38, 17, 11, 26, 16, + 22, 62, 44, 59, 49, 64, 56, 69, 63, 72, 74, 70, 75, 76, 45, 65, 67, 53, + 50, 66, 77, 48, 60, 71, 58, 47, 55, 68, 54, 73, 52, 46, 61, 51, 57, 85, + 86, 79, 84, 43, 78, 83, 82, 35762, 35762, 35762, 35762, 93, 95, 92, 91, + 88, 87, 90, 89, 96, 94, 35762, 35762, 35762, 35762, 80, 81, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 16234, 16220, 16215, 16195, 16190, 16208, 16203, 16183, 16198, + 16223, 16218, 16213, 16193, 16188, 16209, 16204, 16184, 16199, 16235, + 16221, 16216, 16196, 16191, 16211, 16206, 16186, 16201, 16236, 16222, + 16217, 16197, 16192, 16212, 16207, 16187, 16202, 16224, 16219, 16214, + 16194, 16189, 16210, 16205, 16185, 16200, 16181, 16182, 16172, 16179, + 16180, 16232, 16230, 16229, 16226, 16225, 16228, 16227, 16233, 16231, + 16238, 16174, 16173, 16175, 16237, 16178, 16177, 16176, 16171, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 26069, 26064, 26059, 26039, 26034, + 26052, 26047, 26027, 26042, 26067, 26062, 26057, 26037, 26032, 26053, + 26048, 26028, 26043, 26070, 26065, 26060, 26040, 26035, 26055, 26050, + 26030, 26045, 26071, 26066, 26061, 26041, 26036, 26056, 26051, 26031, + 26046, 26068, 26063, 26058, 26038, 26033, 26054, 26049, 26029, 26044, + 26026, 26019, 26021, 26011, 26013, 26014, 26016, 26023, 26022, 26017, + 26012, 26015, 26020, 26018, 26025, 26024, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 2231, 2240, 2237, 2135, 35762, 2247, 2235, 2239, 2227, 2243, 2234, 2183, + 2238, 2245, 2210, 2232, 2241, 2211, 2246, 2242, 2209, 2230, 2229, 2233, + 2228, 2134, 2236, 2244, 2105, 2107, 2106, 2108, 35762, 2147, 2145, 35762, + 2142, 35762, 35762, 2141, 35762, 2149, 2144, 2152, 2146, 2151, 2139, + 2154, 2148, 2140, 2153, 35762, 2138, 2137, 2136, 2143, 35762, 2155, + 35762, 2150, 35762, 35762, 35762, 35762, 35762, 35762, 2219, 35762, + 35762, 35762, 35762, 2220, 35762, 2221, 35762, 2224, 35762, 2223, 2216, + 2226, 35762, 2217, 2225, 35762, 2215, 35762, 35762, 2218, 35762, 2214, + 35762, 2222, 35762, 2212, 35762, 2213, 35762, 2202, 2199, 35762, 2196, + 35762, 35762, 2195, 2190, 2204, 2198, 35762, 2200, 2206, 2193, 2208, + 2203, 2194, 2207, 35762, 2192, 2191, 2189, 2197, 35762, 2188, 2201, 2205, + 2186, 35762, 2187, 35762, 2160, 2172, 2170, 2180, 2163, 2182, 2168, 2162, + 2166, 2175, 35762, 2178, 2171, 2177, 2157, 2161, 2173, 2158, 2181, 2174, + 2156, 2167, 2165, 2159, 2164, 2179, 2169, 2176, 35762, 35762, 35762, + 35762, 35762, 2122, 2119, 2130, 35762, 2133, 2117, 2121, 2115, 2125, + 35762, 2128, 2120, 2127, 2110, 2132, 2123, 2111, 2131, 2124, 2109, 2116, + 2114, 2112, 2113, 2129, 2118, 2126, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 2184, 2185, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 20707, 20723, 20738, 20714, 20742, 20741, 20739, + 20719, 20736, 20733, 20712, 20709, 20728, 20725, 20705, 20716, 20720, + 20737, 20734, 20713, 20710, 20729, 20726, 20706, 20717, 20718, 20735, + 20732, 20711, 20708, 20727, 20724, 20704, 20715, 20722, 20721, 20702, + 20745, 20731, 20730, 20743, 20740, 20744, 20703, 35762, 35762, 35762, + 35762, 10829, 10780, 10781, 10782, 10783, 10784, 10785, 10786, 10787, + 10788, 10789, 10790, 10791, 10792, 10793, 10794, 10795, 10796, 10797, + 10798, 10799, 10800, 10801, 10802, 10803, 10804, 10805, 10806, 10807, + 10808, 10809, 10810, 10811, 10812, 10813, 10814, 10815, 10816, 10817, + 10818, 10819, 10820, 10821, 10822, 10823, 10824, 10825, 10826, 10827, + 10828, 10879, 10830, 10831, 10832, 10833, 10834, 10835, 10836, 10837, + 10838, 10839, 10840, 10841, 10842, 10843, 10844, 10845, 10846, 10847, + 10848, 10849, 10850, 10851, 10852, 10853, 10854, 10855, 10856, 10857, + 10858, 10859, 10860, 10861, 10862, 10863, 10864, 10865, 10866, 10867, + 10868, 10869, 10870, 10871, 10872, 10873, 10874, 10875, 10876, 10877, + 10878, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 26691, 26761, 26736, 26732, 26695, 26700, 26720, + 26716, 26712, 26765, 26728, 26769, 26704, 26724, 26708, 35762, 35762, + 26762, 26737, 26733, 26696, 26701, 26721, 26717, 26713, 26766, 26729, + 26770, 26705, 26725, 26709, 26692, 35762, 26763, 26738, 26734, 26697, + 26702, 26722, 26718, 26714, 26767, 26730, 26771, 26706, 26726, 26710, + 26690, 35762, 26760, 26735, 26731, 26694, 26699, 26719, 26715, 26711, + 26764, 26727, 26768, 26703, 26723, 26707, 26693, 26698, 26742, 26739, + 26753, 26754, 26755, 26756, 26757, 26758, 26759, 26743, 26744, 26745, + 26746, 26747, 26748, 26749, 26750, 26751, 26752, 26740, 26741, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 10565, + 10564, 10549, 10561, 10558, 10543, 10540, 10555, 10552, 10567, 10546, + 10606, 10585, 6512, 6229, 6253, 26362, 26363, 26364, 26365, 26366, 26367, + 26368, 26369, 26370, 26371, 26372, 26373, 26374, 26375, 26376, 26377, + 26378, 26379, 26380, 26381, 26382, 26383, 26384, 26385, 26386, 26387, + 32455, 6343, 6344, 6240, 6511, 8343, 29496, 29497, 29498, 29499, 29500, + 29501, 29502, 29503, 29504, 29505, 29506, 29507, 29508, 29509, 29510, + 29511, 29512, 29513, 29514, 29515, 29516, 29517, 29518, 29519, 29520, + 29521, 29490, 29526, 29541, 29542, 29531, 29553, 24272, 24273, 24274, + 24275, 24276, 24277, 24278, 24279, 24280, 24281, 24282, 24283, 24284, + 24285, 24286, 24287, 24288, 24289, 24290, 24291, 24292, 24293, 24294, + 24295, 24296, 24297, 26969, 26970, 26971, 6239, 6238, 6287, 24303, 24304, + 24305, 24306, 24307, 24308, 24309, 24310, 24311, 24312, 24313, 24314, + 24315, 24316, 24317, 24318, 24319, 24320, 24321, 24322, 24323, 24324, + 24325, 24326, 24327, 24328, 8387, 24332, 24334, 24335, 24331, 24333, + 29232, 29479, 29478, 29485, 29554, 29527, 29528, 29530, 29540, 29548, + 29551, 29543, 29533, 29545, 29483, 29547, 29484, 29534, 29544, 29536, + 29529, 29495, 29489, 29488, 29487, 29524, 29535, 29549, 29550, 21137, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 26997, 26998, 26999, 27000, + 27001, 27002, 27003, 27004, 27005, 27006, 27007, 27008, 27009, 27010, + 27011, 27012, 27013, 27014, 27015, 27016, 27017, 27018, 27019, 27020, + 27021, 27022, 29270, 29491, 29493, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 29457, 29452, + 29444, 29492, 29438, 29450, 29473, 29449, 29437, 29462, 29470, 29461, + 29442, 29453, 29454, 29460, 29441, 29471, 29468, 29475, 29451, 29446, + 29465, 29455, 29458, 29435, 29436, 29477, 29448, 29439, 29443, 29459, + 29474, 29456, 29469, 29472, 29445, 29466, 29464, 29463, 29467, 29440, + 29447, 29476, 35762, 35762, 35762, 35762, 32452, 32446, 32447, 32449, + 32453, 32450, 32454, 32448, 32451, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 6291, 6289, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 27401, 27402, + 27399, 27403, 27398, 27400, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 10219, 13162, + 7734, 24578, 29724, 29723, 6522, 29725, 26962, 4630, 33941, 33767, 22902, + 11218, 11216, 11217, 13610, 24383, 33853, 13131, 33854, 13203, 33852, + 18158, 33851, 8377, 24382, 13130, 18157, 13202, 29648, 13611, 27918, + 32014, 3808, 34096, 34100, 34097, 34098, 7747, 7746, 7745, 7744, 13161, + 34162, 15972, 31673, 4706, 6175, 27734, 13062, 10243, 26230, 5823, 15969, + 32566, 6173, 27389, 15937, 29726, 3985, 11212, 11213, 15762, 13180, + 20989, 13101, 19445, 23855, 32421, 2525, 13723, 22390, 33944, 30811, + 19779, 3406, 26676, 26994, 14263, 26496, 26493, 6174, 29593, 14654, + 28875, 22182, 26811, 27117, 27118, 8177, 9648, 29581, 29170, 4628, 13193, + 27405, 10228, 26088, 29766, 13201, 13137, 28969, 27862, 16002, 10975, + 8176, 6212, 5698, 20592, 9650, 15943, 27935, 3629, 26809, 8175, 13167, + 31675, 27701, 34164, 7751, 32533, 3520, 7693, 2589, 13168, 4093, 26799, + 27108, 34184, 3740, 16359, 6213, 13107, 13127, 13126, 2729, 26420, 8156, + 30810, 8388, 26675, 16364, 5760, 34161, 23499, 27706, 13648, 15234, 4095, + 22901, 27061, 23619, 29597, 19778, 8168, 3510, 3511, 13122, 98, 5758, + 13113, 27348, 13135, 22894, 23520, 6215, 15233, 2506, 32435, 6520, 32420, + 7689, 26525, 33689, 10611, 28881, 3739, 13322, 4098, 13153, 23854, 23602, + 27700, 14279, 23618, 32538, 33694, 23853, 27530, 31789, 28856, 3412, + 6176, 28963, 27531, 29764, 29196, 32535, 15967, 360, 27408, 29769, 33963, + 13647, 26952, 26953, 8379, 33768, 13141, 16004, 29954, 28960, 4964, 3516, + 4705, 15979, 6521, 10520, 7690, 10351, 10352, 24253, 29579, 15978, 15977, + 25236, 16361, 13032, 15980, 3401, 2522, 15973, 20528, 8171, 27705, 10269, + 13097, 16357, 16360, 13031, 34065, 3855, 33950, 33949, 27390, 3870, + 18037, 2600, 4102, 359, 12426, 12427, 12428, 12429, 12430, 26976, 23515, + 26091, 33942, 8370, 32318, 19676, 26978, 5765, 11054, 8391, 34118, 28957, + 28958, 15966, 26981, 13615, 27940, 23497, 27352, 6181, 10716, 26667, + 4252, 12395, 25234, 29191, 4643, 954, 15942, 18039, 13134, 32534, 3986, + 32564, 15201, 2588, 13197, 3741, 26497, 18034, 26821, 11056, 2598, 10778, + 23517, 8371, 32319, 26979, 5766, 11055, 29195, 15968, 23498, 10777, + 26669, 13200, 14652, 34183, 3515, 26267, 26668, 26486, 6180, 13059, + 13057, 11211, 24730, 23518, 32422, 34107, 34024, 34050, 34071, 13138, + 33951, 26087, 32046, 32047, 7688, 25781, 8393, 34173, 13058, 24573, + 29951, 16461, 11062, 18029, 3745, 34172, 26925, 14658, 26816, 20983, + 2519, 15833, 34174, 34171, 13166, 4701, 4700, 4250, 13510, 20896, 34169, + 13105, 20902, 32581, 32582, 26796, 34170, 4631, 26510, 20899, 20900, + 25760, 25758, 2587, 8159, 26878, 16366, 16365, 14521, 2590, 13045, 356, + 16131, 28858, 16247, 14278, 10227, 20434, 24184, 13093, 14525, 3410, + 29949, 26672, 18026, 20527, 27328, 13326, 18021, 4094, 8369, 33961, 3517, + 4637, 32575, 29171, 14276, 15236, 3988, 14265, 34208, 26924, 15235, + 27104, 15237, 10528, 12383, 952, 4249, 28870, 7756, 29192, 11058, 10232, + 26670, 13148, 10696, 29182, 32021, 34035, 15989, 23319, 9646, 15266, + 8376, 3403, 3405, 3404, 3402, 23318, 5994, 27730, 26520, 4632, 22904, + 13154, 25792, 11209, 13118, 25779, 26095, 26097, 4961, 31676, 5703, 5993, + 5995, 3408, 7694, 26927, 27396, 26488, 29591, 32504, 3999, 19777, 24727, + 24728, 7740, 25773, 14264, 3987, 25796, 4000, 24255, 27727, 22741, 31681, + 26098, 13104, 27614, 26928, 6000, 26073, 16356, 26487, 13060, 16163, + 12464, 7737, 7738, 25783, 25782, 26805, 26802, 24568, 22918, 22919, + 33686, 22920, 24648, 967, 4962, 4963, 33688, 31688, 26955, 33690, 13121, + 26800, 26892, 32568, 7724, 7725, 7721, 963, 20529, 15828, 29177, 29176, + 29178, 29179, 3509, 12381, 19566, 27215, 20492, 7739, 17144, 20489, + 25786, 3523, 3525, 3998, 20432, 26957, 2592, 12459, 25762, 29019, 32445, + 24647, 17159, 16250, 16251, 16254, 16253, 16252, 13123, 12382, 34187, + 14648, 25141, 15981, 26681, 22893, 31687, 8398, 28852, 16367, 32506, + 3880, 34083, 18148, 18130, 18138, 18131, 28887, 28886, 32658, 10981, + 32656, 10982, 20561, 32707, 6236, 8385, 8384, 24720, 24722, 29838, 34048, + 15281, 5831, 26089, 11049, 17142, 23504, 29859, 22604, 4096, 7705, 7715, + 7717, 7701, 7699, 7709, 7707, 7697, 7703, 7711, 7695, 7713, 7706, 7716, + 7718, 7702, 7700, 7710, 7708, 7698, 7704, 7712, 7696, 7714, 27173, 27174, + 27175, 4696, 4697, 27336, 3997, 5697, 20986, 3882, 24646, 15941, 20897, + 28873, 10229, 29187, 29188, 16462, 20901, 19490, 31682, 27156, 34102, + 3895, 31686, 7691, 2593, 29563, 12463, 13160, 26500, 20431, 3852, 20554, + 20540, 20552, 20553, 20558, 19545, 32555, 26967, 27089, 27097, 27098, + 27102, 27099, 26968, 34025, 28043, 28042, 28039, 28038, 3830, 3868, + 28045, 28044, 28041, 28040, 3898, 3802, 3815, 10353, 17146, 32037, 26875, + 26822, 3818, 34039, 28970, 31670, 34167, 25770, 32570, 32033, 32490, + 25585, 15229, 27711, 26876, 13103, 25793, 10702, 10703, 10704, 13190, + 13192, 13191, 3814, 13164, 25780, 5704, 5705, 13119, 12431, 12432, 12433, + 24724, 24725, 24726, 12442, 12435, 12436, 10701, 26094, 26099, 33957, + 29190, 29189, 10354, 22905, 22168, 26080, 7723, 5695, 16165, 10246, 8151, + 25757, 27347, 26096, 29589, 10226, 20433, 29180, 32029, 32028, 32030, + 32031, 19517, 27176, 32583, 32035, 19533, 27189, 19454, 27121, 23501, + 19802, 19801, 2734, 2740, 2735, 2739, 2732, 19799, 2733, 34178, 23514, + 32489, 29577, 28855, 23519, 14268, 14270, 13084, 28945, 28947, 28946, + 28948, 28944, 28943, 34165, 28949, 13064, 27060, 28942, 28952, 28955, + 24380, 13056, 32619, 13067, 26498, 8157, 8158, 18022, 13094, 18023, + 18024, 13081, 13082, 13083, 10613, 34179, 953, 26814, 8397, 26522, 13088, + 10612, 13199, 950, 13110, 33959, 28872, 32419, 14273, 20591, 13072, + 15988, 13074, 13065, 2514, 13155, 28871, 10697, 13091, 13069, 14272, + 5767, 28940, 28941, 5768, 18025, 26813, 8396, 33958, 28876, 28877, 32716, + 13087, 13077, 13071, 26519, 27735, 15239, 29175, 15200, 26517, 26516, + 26512, 26514, 24689, 29073, 24663, 29061, 32553, 32562, 32552, 32561, + 24688, 29072, 24662, 29060, 15317, 15310, 15314, 15307, 24690, 29074, + 24664, 29062, 15318, 15311, 15315, 15308, 15939, 15940, 29015, 29016, + 19669, 32750, 27291, 11044, 27721, 15312, 19781, 15289, 15244, 29767, + 27608, 27609, 27610, 15333, 27611, 15301, 33677, 33674, 5996, 27070, + 27346, 15474, 29580, 26960, 15831, 15832, 32497, 22740, 19788, 29578, + 32493, 32494, 4699, 25767, 32532, 4702, 22906, 361, 13124, 26794, 25765, + 31674, 25766, 2521, 25763, 26993, 10251, 2505, 32491, 23496, 23511, + 29765, 23512, 160, 27917, 27404, 29181, 15963, 33668, 8160, 26795, 32503, + 11050, 24644, 28956, 24649, 26926, 11048, 26807, 24653, 3735, 24642, + 3734, 23513, 26529, 24645, 6178, 22605, 34175, 27065, 2591, 32488, 33940, + 27939, 3507, 3508, 26428, 9651, 2604, 19491, 32500, 26889, 6345, 4251, + 13511, 8368, 28869, 27920, 3527, 3636, 26686, 25233, 27919, 29599, 26100, + 15935, 15991, 12396, 35762, 35762, 35762, 35762, 34168, 26772, 33965, + 27329, 14649, 27913, 25267, 23509, 26959, 23506, 32654, 32657, 32655, + 28884, 24697, 227, 228, 35762, 35762, 35762, 27613, 25764, 10538, 26425, + 27709, 23507, 5700, 28874, 13159, 28861, 2523, 26666, 27349, 35762, + 35762, 35762, 295, 243, 344, 342, 339, 237, 235, 236, 233, 234, 332, 334, + 335, 321, 288, 250, 281, 282, 283, 265, 309, 286, 336, 337, 307, 308, + 270, 323, 276, 277, 259, 300, 256, 278, 319, 257, 258, 255, 310, 317, + 338, 329, 279, 238, 318, 311, 316, 333, 298, 299, 297, 301, 302, 303, + 230, 231, 284, 312, 241, 304, 305, 240, 246, 326, 327, 296, 247, 248, + 249, 232, 343, 322, 328, 271, 340, 289, 254, 331, 253, 325, 252, 330, + 313, 280, 324, 341, 274, 242, 291, 251, 290, 239, 314, 315, 320, 294, + 268, 266, 267, 293, 292, 260, 261, 262, 263, 264, 229, 244, 245, 306, + 275, 287, 269, 285, 273, 272, 20525, 25235, 20594, 35762, 35762, 35762, + 35762, 15228, 20771, 13645, 26946, 25897, 3823, 3899, 3860, 3803, 3885, + 22283, 3994, 15329, 33678, 13042, 34005, 27397, 3893, 3886, 19796, 22308, + 3995, 15330, 33679, 13043, 34084, 34086, 29411, 3891, 3909, 3847, 34019, + 34020, 10527, 3892, 3910, 3848, 34055, 32018, 19798, 22309, 3996, 33683, + 33680, 13044, 32016, 19791, 22301, 3990, 15302, 33675, 13039, 19784, + 22289, 3993, 15277, 33673, 13041, 19792, 22300, 3991, 15306, 33676, + 13040, 19782, 22306, 3992, 15271, 33672, 19794, 22303, 32036, 22302, + 19786, 22288, 13182, 22287, 27071, 19783, 15276, 22299, 15305, 28850, + 22305, 15269, 33671, 15267, 19793, 15324, 15323, 6506, 24298, 6516, + 24299, 24576, 35762, 35762, 35762, 35762, 35762, 35762, 18137, 18150, + 18133, 18146, 18128, 18149, 18132, 18139, 18151, 18134, 18147, 18129, + 35762, 35762, 35762, 35762, 15274, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 19590, 32726, 27244, 10996, 19597, 32723, 27251, 10993, 19586, 32722, + 27240, 10992, 35762, 35762, 35762, 35762, 19589, 32725, 27243, 10995, + 19599, 32727, 27253, 10997, 15285, 15326, 15299, 15263, 15284, 15325, + 15298, 15262, 19633, 32760, 27304, 11013, 19632, 32759, 27303, 11012, + 19631, 32756, 27302, 11009, 19635, 32762, 27306, 11015, 19634, 32761, + 27305, 11014, 19663, 32737, 27270, 11031, 19671, 32752, 27293, 11046, + 19673, 32748, 27326, 11042, 19623, 32746, 27284, 11040, 19624, 32747, + 27285, 11041, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 19672, 32751, 27294, 11045, 24695, 24669, 29067, 29079, 19509, 32647, + 35762, 35762, 35762, 35762, 35762, 35762, 34121, 34136, 34126, 34131, + 34146, 34141, 34151, 34156, 34123, 34138, 34128, 34133, 34148, 34143, + 34153, 34158, 34122, 34137, 34127, 34132, 34147, 34142, 34152, 34157, + 34119, 34134, 34124, 34129, 34144, 34139, 34149, 34154, 34120, 34135, + 34125, 34130, 34145, 34140, 34150, 34155, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 19639, 32766, 27310, 11020, 19653, 32778, + 27325, 11025, 19598, 32724, 27252, 10994, 15240, 15243, 15242, 15241, + 19607, 27259, 19642, 27295, 19664, 27290, 19668, 27286, 19606, 27258, + 19662, 27269, 33969, 33968, 35762, 35762, 2501, 2498, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 6234, 6235, 6233, 19481, 19479, + 19480, 19482, 19478, 10985, 10987, 10986, 10988, 26673, 34040, 4639, + 26674, 35571, 23320, 13085, 24574, 32019, 13068, 27406, 15990, 28718, + 4960, 26975, 19561, 27210, 14659, 14655, 16358, 13066, 7748, 24254, + 27351, 11059, 20652, 13092, 28959, 13076, 14271, 14269, 13086, 27751, + 28950, 13073, 27938, 26823, 4627, 26265, 27760, 26877, 20898, 23505, + 27942, 26507, 16464, 13115, 22921, 34186, 33943, 14657, 10692, 34160, + 11060, 7692, 32565, 29194, 13614, 27340, 13133, 27733, 32020, 4247, + 21060, 9645, 18038, 28972, 13158, 8392, 2581, 9652, 2599, 26808, 5763, + 2602, 14266, 27764, 29598, 12333, 13609, 26494, 18027, 26266, 11206, + 13174, 30393, 6211, 4097, 9638, 7752, 4638, 26684, 26873, 9653, 27612, + 5699, 19446, 20987, 23500, 2603, 28951, 34207, 28953, 13078, 13090, + 26079, 13195, 24577, 10616, 13095, 13080, 27702, 18036, 13643, 15936, + 13143, 8399, 20486, 27707, 32541, 32633, 11221, 11207, 3450, 27861, + 26090, 13187, 4704, 10522, 13644, 20487, 27106, 27941, 29556, 13512, + 35565, 15827, 27698, 29952, 8378, 16750, 20658, 26491, 15938, 26423, + 26954, 20590, 23503, 22896, 2601, 29768, 20895, 11051, 28882, 26072, + 25798, 28860, 13147, 26085, 3518, 3746, 27729, 14280, 26890, 12422, + 12423, 12425, 12424, 4253, 19780, 13165, 32423, 29761, 29762, 27541, + 11214, 23508, 20984, 22183, 22184, 5999, 9640, 27544, 3635, 13321, 25772, + 13102, 33956, 4703, 22147, 16003, 4641, 32531, 29564, 18031, 10521, + 13070, 101, 6177, 25759, 3514, 26515, 26508, 26518, 26509, 20662, 13108, + 33339, 22728, 12420, 13507, 35757, 4625, 25797, 3738, 27704, 13612, 8374, + 28967, 26995, 13128, 16467, 31792, 26528, 11208, 8154, 2583, 13125, + 32425, 4634, 20661, 20593, 20524, 29193, 2742, 27542, 31680, 4640, 3411, + 27350, 3409, 29197, 26982, 24256, 24357, 24368, 24371, 24360, 24350, + 24365, 33980, 3771, 24351, 33977, 33993, 33996, 33972, 33985, 33990, + 3768, 3784, 3787, 3763, 3776, 3781, 24358, 24369, 24372, 24361, 24356, + 24366, 33981, 3772, 24352, 33999, 34002, 34003, 33998, 34000, 34001, + 3790, 3793, 3794, 3789, 3791, 3792, 24375, 24378, 24379, 24374, 24376, + 24377, 33982, 3773, 24353, 33978, 33994, 33997, 33973, 33983, 33991, + 3769, 3785, 3788, 3764, 3774, 3782, 24359, 24370, 24373, 24362, 24354, + 24367, 33984, 3775, 24355, 33974, 3765, 24363, 33975, 3766, 24364, 33987, + 33988, 33986, 3778, 3779, 3777, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 34202, 34205, 34201, 34203, + 34200, 34199, 34204, 34195, 34198, 34194, 34196, 34193, 34192, 34197, + 35762, 35762, 2743, 25771, 4633, 27936, 32022, 19795, 14267, 26678, + 11057, 99, 29583, 34191, 8395, 35762, 35762, 35762, 35479, 18030, 26274, + 4001, 20660, 26679, 24347, 20990, 13156, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 27335, 5834, 26980, 2586, 10695, 3407, 22900, 1, + 20509, 8373, 5761, 27710, 18040, 15983, 22916, 34163, 26792, 27756, + 18032, 4707, 23516, 32424, 15231, 26687, 27345, 22917, 16009, 20530, + 14653, 13163, 14523, 17228, 13157, 34180, 3521, 7750, 26810, 34182, + 13109, 20526, 8347, 12434, 24348, 16000, 16460, 34166, 35762, 13646, 946, + 20595, 26530, 26825, 26824, 26513, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 23502, 10880, 3989, 3524, 25761, 13144, 30809, + 13186, 31679, 26812, 3519, 16459, 13509, 26495, 35762, 35762, 35762, + 35762, 22389, 27546, 13075, 13079, 13089, 10890, 3743, 4642, 27912, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 14656, 27283, 19622, + 26231, 26232, 16170, 15238, 19667, 27289, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 3925, 3955, 3926, 3970, 3941, 3956, 3927, 3978, + 3948, 3964, 3934, 3971, 3942, 3957, 3928, 3982, 3952, 3967, 3938, 3975, + 3961, 3931, 3979, 3949, 3965, 3935, 3972, 3943, 3958, 3929, 3984, 3954, + 3969, 3940, 3977, 3947, 3963, 3933, 3981, 3951, 3937, 3974, 3945, 3960, + 3930, 3983, 3953, 3968, 3939, 3976, 3946, 3962, 3932, 3980, 3950, 3966, + 3936, 3973, 3944, 3959, 20541, 20542, 20549, 20551, 20546, 20574, 20575, + 20571, 20573, 20569, 20572, 20565, 20568, 20566, 20570, 20567, 20545, + 20548, 20543, 20547, 20544, 20550, 32692, 32693, 32700, 32702, 32697, + 32682, 32683, 32679, 32681, 32677, 32680, 32673, 32676, 32674, 32678, + 32675, 32696, 32699, 32694, 32698, 32695, 32701, 32664, 19447, 32661, + 19449, 19530, 32715, 27195, 20587, 33658, 33659, 33660, 33661, 33662, + 33663, 15949, 15950, 15951, 15952, 15953, 15954, 19448, 19450, 27120, + 27119, 32663, 15948, 32690, 32713, 32666, 32714, 32712, 27160, 27190, + 27147, 27191, 27170, 19489, 27155, 32671, 20537, 16342, 32668, 32669, + 35762, 19488, 5997, 16338, 15278, 32685, 32709, 32662, 19451, 32686, + 32710, 20563, 20556, 4173, 4177, 4169, 4172, 4174, 4179, 4170, 4167, + 4176, 4178, 4180, 4175, 4168, 4171, 4184, 4207, 2504, 16339, 19487, + 27154, 16340, 19577, 27229, 11002, 32719, 19486, 27153, 33766, 27162, + 24301, 24300, 24302, 34043, 19532, 22897, 27188, 24330, 29584, 29585, + 29587, 29588, 29586, 34109, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 27743, 27745, 27742, 27741, 27738, 27737, 27740, 27739, 27746, + 27744, 35762, 35762, 35762, 35762, 35762, 35762, 6553, 6554, 6555, 6556, + 6557, 6558, 6559, 6560, 6561, 6562, 6563, 6564, 6565, 6566, 6567, 6568, + 6569, 6570, 6571, 6572, 6573, 6574, 6575, 6576, 6577, 6578, 6579, 6580, + 6581, 6582, 6583, 6584, 6585, 6586, 6587, 6588, 6589, 6590, 6591, 6592, + 6593, 6594, 6595, 6596, 6597, 6598, 6599, 6600, 6601, 6602, 6603, 6604, + 6605, 6606, 6607, 6608, 6609, 6610, 6611, 6612, 6613, 6614, 6615, 6616, + 6617, 6618, 6619, 6620, 6621, 6622, 6623, 6624, 6625, 6626, 6627, 6628, + 6629, 6630, 6631, 6632, 6633, 6634, 6635, 6636, 6637, 6638, 6639, 6640, + 6641, 6642, 6643, 6644, 6645, 6646, 6647, 6648, 6649, 6650, 6651, 6652, + 6653, 6654, 6655, 6656, 6657, 6658, 6659, 6660, 6661, 6662, 6663, 6664, + 6665, 6666, 6667, 6668, 6669, 6670, 6671, 6672, 6673, 6674, 6675, 6676, + 6677, 6678, 6679, 6680, 6681, 6682, 6683, 6684, 6685, 6686, 6687, 6688, + 6689, 6690, 6691, 6692, 6693, 6694, 6695, 6696, 6697, 6698, 6699, 6700, + 6701, 6702, 6703, 6704, 6705, 6706, 6707, 6708, 6709, 6710, 6711, 6712, + 6713, 6714, 6715, 6716, 6717, 6718, 6719, 6720, 6721, 6722, 6723, 6724, + 6725, 6726, 6727, 6728, 6729, 6730, 6731, 6732, 6733, 6734, 6735, 6736, + 6737, 6738, 6739, 6740, 6741, 6742, 6743, 6744, 6745, 6746, 6747, 6748, + 6749, 6750, 6751, 6752, 6753, 6754, 6755, 6756, 6757, 6758, 6759, 6760, + 6761, 6762, 6763, 6764, 6765, 6766, 6767, 6768, 6769, 6770, 6771, 6772, + 6773, 6774, 6775, 6776, 6777, 6778, 6779, 6780, 6781, 6782, 6783, 6784, + 6785, 6786, 6787, 6788, 6789, 6790, 6791, 6792, 6793, 6794, 6795, 6796, + 6797, 6798, 6799, 6800, 6801, 6802, 6803, 6804, 6805, 6806, 6807, 6808, + 6809, 6810, 6811, 6812, 6813, 6814, 6815, 6816, 6817, 6818, 6819, 6820, + 6821, 6822, 6823, 6824, 6825, 6826, 6827, 6828, 6829, 6830, 6831, 6832, + 6833, 6834, 6835, 6836, 6837, 6838, 6839, 6840, 6841, 6842, 6843, 6844, + 6845, 6846, 6847, 6848, 6849, 6850, 6851, 6852, 6853, 6854, 6855, 6856, + 6857, 6858, 6859, 6860, 6861, 6862, 6863, 6864, 6865, 6866, 6867, 6868, + 6869, 6870, 6871, 6872, 6873, 6874, 6875, 6876, 6877, 6878, 6879, 6880, + 6881, 6882, 6883, 6884, 6885, 6886, 6887, 6888, 6889, 6890, 6891, 6892, + 6893, 6894, 6895, 6896, 6897, 6898, 6899, 6900, 6901, 6902, 6903, 6904, + 6905, 6906, 6907, 6908, 6909, 6910, 6911, 6912, 6913, 6914, 6915, 6916, + 6917, 6918, 6919, 6920, 6921, 6922, 6923, 6924, 6925, 6926, 6927, 6928, + 6929, 6930, 6931, 6932, 6933, 6934, 6935, 6936, 6937, 6938, 6939, 6940, + 6941, 6942, 6943, 6944, 6945, 6946, 6947, 6948, 6949, 6950, 6951, 6952, + 6953, 6954, 6955, 6956, 6957, 6958, 6959, 6960, 6961, 6962, 6963, 6964, + 6965, 6966, 6967, 6968, 6969, 6970, 6971, 6972, 6973, 6974, 6975, 6976, + 6977, 6978, 6979, 6980, 6981, 6982, 6983, 6984, 6985, 6986, 6987, 6988, + 6989, 6990, 6991, 6992, 6993, 6994, 6995, 6996, 6997, 6998, 6999, 7000, + 7001, 7002, 7003, 7004, 7005, 7006, 7007, 7008, 7009, 7010, 7011, 7012, + 7013, 7014, 7015, 7016, 7017, 7018, 7019, 7020, 7021, 7022, 7023, 7024, + 7025, 7026, 7027, 7028, 7029, 7030, 7031, 7032, 7033, 7034, 7035, 7036, + 7037, 7038, 7039, 7040, 7041, 7042, 7043, 7044, 7045, 7046, 7047, 7048, + 7049, 7050, 7051, 7052, 7053, 7054, 7055, 7056, 7057, 7058, 7059, 7060, + 7061, 7062, 7063, 7064, 6537, 6538, 6539, 6540, 6541, 6542, 6543, 6544, + 6545, 6546, 6547, 6548, 6549, 6550, 6551, 6552, 6523, 6524, 6525, 6526, + 6527, 6528, 6529, 6530, 6531, 6532, 6533, 6534, 6535, 6536, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 19444, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 30045, 29974, 30037, 30046, + 29962, 30035, 29956, 29955, 30032, 30040, 29957, 30036, 29960, 29977, + 30048, 30044, 29969, 29971, 29968, 29967, 29964, 29963, 29966, 29965, + 29972, 29970, 29961, 30043, 30030, 29973, 29976, 30038, 29959, 29978, + 29979, 29980, 29981, 29982, 29983, 29984, 29985, 29986, 29987, 29988, + 29989, 29990, 29991, 29992, 29993, 29994, 29995, 29996, 29997, 29998, + 29999, 30000, 30001, 30002, 30003, 30033, 30042, 30041, 29958, 30034, + 29975, 30004, 30005, 30006, 30007, 30008, 30009, 30010, 30011, 30012, + 30013, 30014, 30015, 30016, 30017, 30018, 30019, 30020, 30021, 30022, + 30023, 30024, 30025, 30026, 30027, 30028, 30029, 30031, 30049, 30039, + 30047, 5694, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 33161, 33172, 33183, 33195, 33206, 33217, 33228, 33239, 33250, 33258, + 33259, 33260, 33261, 33263, 33264, 33265, 33266, 33267, 33268, 33269, + 33270, 33271, 33272, 33274, 33275, 33276, 33277, 33278, 33279, 33280, + 33281, 33282, 33283, 33285, 33286, 33287, 33288, 33289, 33290, 33291, + 33292, 33293, 33294, 33296, 33297, 33298, 33299, 33300, 33301, 33302, + 33303, 33304, 33305, 33307, 33308, 33309, 33310, 33311, 33312, 33313, + 33314, 33315, 33316, 33318, 33319, 33320, 33321, 33322, 33323, 33324, + 33325, 33326, 33327, 33329, 33330, 33331, 33332, 33333, 33334, 33335, + 33336, 33337, 33338, 33085, 33086, 33087, 33088, 33089, 33090, 33091, + 33092, 33093, 33094, 33096, 33097, 33098, 33099, 33100, 33101, 33102, + 33103, 33104, 33105, 33107, 33108, 33109, 33110, 33111, 33112, 33113, + 33114, 33115, 33116, 33118, 33119, 33120, 33121, 33122, 33123, 33124, + 33125, 33126, 33127, 33129, 33130, 33131, 33132, 33133, 33134, 33135, + 33136, 33137, 33138, 33140, 33141, 33142, 33143, 33144, 33145, 33146, + 33147, 33148, 33149, 33151, 33152, 33153, 33154, 33155, 33156, 33157, + 33158, 33159, 33160, 33162, 33163, 33164, 33165, 33166, 33167, 33168, + 33169, 33170, 33171, 33173, 33174, 33175, 33176, 33177, 33178, 33179, + 33180, 33181, 33182, 33184, 33185, 33186, 33187, 33188, 33189, 33190, + 33191, 33192, 33193, 33196, 33197, 33198, 33199, 33200, 33201, 33202, + 33203, 33204, 33205, 33207, 33208, 33209, 33210, 33211, 33212, 33213, + 33214, 33215, 33216, 33218, 33219, 33220, 33221, 33222, 33223, 33224, + 33225, 33226, 33227, 33229, 33230, 33231, 33232, 33233, 33234, 33235, + 33236, 33237, 33238, 33240, 33241, 33242, 33243, 33244, 33245, 33246, + 33247, 33248, 33249, 33251, 33252, 33253, 33254, 33255, 33256, 33257, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 25143, 25142, 29575, 29166, + 29576, 29601, 12457, 13030, 12455, 12468, 12461, 12460, 3, 2, 347, 3522, + 2596, 4957, 5989, 15959, 15985, 29953, 19875, 24468, 12458, 20659, 25216, + 12466, 19877, 33665, 33770, 13171, 13320, 5762, 8375, 27914, 20491, + 28965, 27915, 20490, 27945, 10237, 11210, 10519, 10238, 10518, 10239, + 10517, 10240, 10515, 10241, 24336, 24258, 29858, 29857, 12456, 13029, + 5692, 4965, 12454, 12467, 12421, 29632, 29602, 12502, 12501, 16242, + 13120, 13318, 16243, 14274, 14522, 16244, 26992, 27539, 16245, 32630, + 32782, 29168, 10253, 10250, 26093, 26092, 15830, 15984, 4626, 4956, + 24641, 24260, 16169, 16168, 24570, 24575, 29572, 29559, 12453, 12505, + 5991, 15961, 15987, 5990, 15960, 15986, 19878, 33666, 33771, 26416, + 26415, 26793, 26417, 26418, 26773, 27072, 27079, 27107, 28731, 28732, + 29557, 28730, 28733, 29558, 10516, 10242, 26881, 26882, 26929, 26880, + 26883, 26930, 27754, 29600, 5693, 10222, 22730, 24084, 29571, 29574, + 29169, 12452, 12450, 13063, 29573, 29167, 28725, 29950, 28724, 27728, + 8169, 10221, 29595, 29560, 25790, 26010, 26879, 26931, 1048, 1049, 24259, + 27944, 18311, 18929, 10220, 2297, 350, 29936, 16751, 18043, 18044, 18086, + 18052, 32125, 14921, 14922, 14899, 14920, 13314, 13315, 13316, 24082, + 13317, 29657, 35760, 35759, 35761, 20655, 27343, 20653, 27341, 26489, + 20656, 27344, 25215, 24083, 34189, 20654, 27342, 13319, 26490, 33962, + 22891, 22892, 19628, 27299, 34696, 23890, 33340, 33451, 33519, 33530, + 33541, 33552, 33563, 33574, 33585, 33341, 33352, 33363, 33374, 33385, + 33396, 33407, 26848, 4955, 4248, 35758, 9338, 9337, 22191, 22189, 22249, + 22247, 15743, 4792, 33418, 33429, 33440, 33452, 33463, 33474, 33485, + 33496, 33507, 33515, 33516, 33517, 33518, 33520, 33521, 33522, 33523, + 33524, 33525, 33526, 33527, 33528, 33529, 33531, 33532, 33533, 33534, + 33535, 33536, 33537, 33538, 33539, 33540, 33542, 33543, 33544, 33545, + 33546, 33547, 33548, 33549, 33550, 33551, 33553, 33554, 33555, 33556, + 33557, 33558, 33559, 33560, 33561, 33562, 33564, 33565, 33566, 33567, + 33568, 33569, 33570, 33571, 33572, 33573, 33575, 33576, 33577, 33578, + 33579, 33580, 33581, 33582, 33583, 33584, 33586, 33587, 33588, 33589, + 33590, 33591, 33592, 33593, 33594, 33595, 33342, 33343, 33344, 33345, + 33346, 33347, 33348, 33349, 33350, 33351, 33353, 33354, 33355, 33356, + 33357, 33358, 33359, 33360, 33361, 33362, 33364, 33365, 33366, 33367, + 33368, 33369, 33370, 33371, 33372, 33373, 33375, 33376, 33377, 33378, + 33379, 33380, 33381, 33382, 33383, 33384, 33386, 33387, 33388, 33389, + 33390, 33391, 33392, 33393, 33394, 33395, 33397, 33398, 33399, 33400, + 33401, 33402, 33403, 33404, 33405, 33406, 33408, 33409, 33410, 33411, + 33412, 33413, 33414, 33415, 33416, 33417, 33419, 33420, 33421, 33422, + 33423, 33424, 33425, 33426, 33427, 33428, 33430, 33431, 33432, 33433, + 33434, 33435, 33436, 33437, 33438, 33439, 33441, 33442, 33443, 33444, + 33445, 33446, 33447, 33448, 33449, 33450, 33453, 33454, 33455, 33456, + 33457, 33458, 33459, 33460, 33461, 33462, 33464, 33465, 33466, 33467, + 33468, 33469, 33470, 33471, 33472, 33473, 33475, 33476, 33477, 33478, + 33479, 33480, 33481, 33482, 33483, 33484, 33486, 33487, 33488, 33489, + 33490, 33491, 33492, 33493, 33494, 33495, 33497, 33498, 33499, 33500, + 33501, 33502, 33503, 33504, 33505, 33506, 33508, 33509, 33510, 33511, + 33512, 33513, 33514, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 17147, 17148, 17155, 17157, 17154, 17153, 17150, 17149, + 17152, 17151, 17158, 17156, 18176, 18735, 18335, 18960, 18570, 19331, + 18270, 18870, 18271, 18871, 18272, 18872, 18444, 19110, 18445, 19111, + 18446, 19112, 18509, 19207, 18254, 18853, 18250, 18849, 18955, 19078, + 18186, 18745, 18187, 18746, 18275, 18876, 18276, 18877, 18260, 18859, + 18261, 18860, 18954, 18956, 18340, 18962, 18341, 18963, 18358, 18990, + 18388, 19030, 18394, 19051, 18484, 19169, 18574, 19335, 18575, 19336, + 18571, 19332, 18572, 19333, 18754, 19127, 19128, 19286, 19287, 19216, + 19217, 18944, 18945, 2267, 2270, 2268, 2272, 2274, 2271, 2273, 2269, + 2275, 10448, 10443, 10442, 10449, 10444, 10445, 10447, 10446, 3594, 3593, + 3595, 14488, 14487, 14486, 14485, 14490, 14489, 25862, 25861, 3539, + 30399, 30407, 30416, 30408, 30410, 30405, 30409, 30404, 30420, 30419, + 30422, 30414, 30401, 30421, 30403, 30402, 30415, 30406, 30418, 30412, + 30413, 30411, 30417, 30400, 30538, 30545, 30546, 30541, 30542, 30547, + 30548, 30539, 30543, 30544, 30540, 30604, 30611, 30612, 30607, 30608, + 30613, 30614, 30605, 30609, 30610, 30606, 30715, 30722, 30723, 30718, + 30719, 30724, 30725, 30716, 30720, 30721, 30717, 30615, 30622, 30623, + 30618, 30619, 30624, 30625, 30616, 30620, 30621, 30617, 30693, 30700, + 30701, 30696, 30697, 30702, 30703, 30694, 30698, 30699, 30695, 30593, + 30600, 30601, 30596, 30597, 30602, 30603, 30594, 30598, 30599, 30595, + 30704, 30711, 30712, 30707, 30708, 30713, 30714, 30705, 30709, 30710, + 30706, 30626, 30633, 30634, 30629, 30630, 30635, 30636, 30627, 30631, + 30632, 30628, 30759, 30766, 30767, 30762, 30763, 30768, 30769, 30760, + 30764, 30765, 30761, 30748, 30755, 30756, 30751, 30752, 30757, 30758, + 30749, 30753, 30754, 30750, 30781, 30788, 30789, 30784, 30785, 30790, + 30791, 30782, 30786, 30787, 30783, 30648, 30655, 30656, 30651, 30652, + 30657, 30658, 30649, 30653, 30654, 30650, 30571, 30578, 30579, 30574, + 30575, 30580, 30581, 30572, 30576, 30577, 30573, 30770, 30777, 30778, + 30773, 30774, 30779, 30780, 30771, 30775, 30776, 30772, 30549, 30556, + 30557, 30552, 30553, 30558, 30559, 30550, 30554, 30555, 30551, 30560, + 30567, 30568, 30563, 30564, 30569, 30570, 30561, 30565, 30566, 30562, + 30637, 30644, 30645, 30640, 30641, 30646, 30647, 30638, 30642, 30643, + 30639, 30582, 30589, 30590, 30585, 30586, 30591, 30592, 30583, 30587, + 30588, 30584, 30737, 30744, 30745, 30740, 30741, 30746, 30747, 30738, + 30742, 30743, 30739, 30659, 30667, 30668, 30662, 30663, 30669, 30670, + 30660, 30664, 30665, 30661, 30671, 30678, 30679, 30674, 30675, 30680, + 30681, 30672, 30676, 30677, 30673, 30682, 30689, 30690, 30685, 30686, + 30691, 30692, 30683, 30687, 30688, 30684, 30726, 30733, 30734, 30729, + 30730, 30735, 30736, 30727, 30731, 30732, 30728, 30526, 30527, 30534, + 30535, 30530, 30531, 30536, 30537, 30528, 30532, 30533, 30529, 30666, + 28756, 28754, 28755, 13411, 17710, 17708, 17711, 17709, 17700, 17706, + 17704, 17707, 17705, 17701, 17721, 17717, 17722, 17718, 17702, 17719, + 17715, 17720, 17716, 17703, 17732, 17712, 17714, 17713, 17728, 17731, + 17729, 17724, 17730, 17725, 17726, 17727, 17733, 17723, 17872, 17749, + 17750, 17751, 17748, 17867, 17859, 15860, 15862, 15864, 15861, 15863, + 16853, 16855, 16857, 16854, 16856, 16846, 16845, 16844, 16847, 23097, + 23102, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, 35762, + 35762, 35762, }; -#define code_magic 47 -#define code_size 65536 -#define code_poly 65581 static const unsigned int aliases_start = 0xf0000; static const unsigned int aliases_end = 0xf01d9; diff --git a/Modules/xxlimited.c b/Modules/xxlimited.c index 3935c00fc26530..0bb5e12d7c3dd9 100644 --- a/Modules/xxlimited.c +++ b/Modules/xxlimited.c @@ -62,7 +62,12 @@ pass */ -#define Py_LIMITED_API 0x030b0000 +#include "pyconfig.h" // Py_GIL_DISABLED + +#ifndef Py_GIL_DISABLED +// Need limited C API version 3.12 for Py_MOD_PER_INTERPRETER_GIL_SUPPORTED +#define Py_LIMITED_API 0x030c0000 +#endif #include "Python.h" #include diff --git a/Modules/xxlimited_35.c b/Modules/xxlimited_35.c index 1ff3ef1cb6f296..754a368f77e940 100644 --- a/Modules/xxlimited_35.c +++ b/Modules/xxlimited_35.c @@ -5,7 +5,11 @@ * See the xxlimited module for an extension module template. */ +#include "pyconfig.h" // Py_GIL_DISABLED + +#ifndef Py_GIL_DISABLED #define Py_LIMITED_API 0x03050000 +#endif #include "Python.h" @@ -293,7 +297,6 @@ xx_modexec(PyObject *m) static PyModuleDef_Slot xx_slots[] = { {Py_mod_exec, xx_modexec}, - {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {0, NULL} }; diff --git a/Modules/xxsubtype.c b/Modules/xxsubtype.c index 63b22268c597b6..560f43e5b3a643 100644 --- a/Modules/xxsubtype.c +++ b/Modules/xxsubtype.c @@ -1,5 +1,7 @@ #include "Python.h" + #include // offsetof() +#include // clock() PyDoc_STRVAR(xxsubtype__doc__, diff --git a/Modules/zlibmodule.c b/Modules/zlibmodule.c index a98a37adadcff0..fe9a6d8d4150ab 100644 --- a/Modules/zlibmodule.c +++ b/Modules/zlibmodule.c @@ -3,6 +3,10 @@ /* Windows users: read Python's PCbuild\readme.txt */ +#ifndef Py_BUILD_CORE_BUILTIN +# define Py_BUILD_CORE_MODULE 1 +#endif + #include "Python.h" #include "zlib.h" @@ -1892,12 +1896,20 @@ zlib_crc32_impl(PyObject *module, Py_buffer *data, unsigned int value) Py_BEGIN_ALLOW_THREADS /* Avoid truncation of length for very large buffers. crc32() takes - length as an unsigned int, which may be narrower than Py_ssize_t. */ - while ((size_t)len > UINT_MAX) { - value = crc32(value, buf, UINT_MAX); - buf += (size_t) UINT_MAX; - len -= (size_t) UINT_MAX; + length as an unsigned int, which may be narrower than Py_ssize_t. + We further limit size due to bugs in Apple's macOS zlib. + See https://github.com/python/cpython/issues/105967. + */ +#define ZLIB_CRC_CHUNK_SIZE 0x40000000 +#if ZLIB_CRC_CHUNK_SIZE > INT_MAX +# error "unsupported less than 32-bit platform?" +#endif + while ((size_t)len > ZLIB_CRC_CHUNK_SIZE) { + value = crc32(value, buf, ZLIB_CRC_CHUNK_SIZE); + buf += (size_t) ZLIB_CRC_CHUNK_SIZE; + len -= (size_t) ZLIB_CRC_CHUNK_SIZE; } +#undef ZLIB_CRC_CHUNK_SIZE value = crc32(value, buf, (unsigned int)len); Py_END_ALLOW_THREADS } else { diff --git a/Objects/abstract.c b/Objects/abstract.c index b4edcec6007710..1ec5c5b8c3dc2f 100644 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -2,16 +2,17 @@ #include "Python.h" #include "pycore_abstract.h" // _PyIndex_Check() +#include "pycore_pybuffer.h" #include "pycore_call.h" // _PyObject_CallNoArgs() #include "pycore_ceval.h" // _Py_EnterRecursiveCallTstate() +#include "pycore_crossinterp.h" // _Py_CallInInterpreter() #include "pycore_object.h" // _Py_CheckSlotResult() #include "pycore_long.h" // _Py_IsNegative #include "pycore_pyerrors.h" // _PyErr_Occurred() #include "pycore_pystate.h" // _PyThreadState_GET() #include "pycore_unionobject.h" // _PyUnion_Check() -#include -#include // offsetof() +#include // offsetof() /* Shorthands to return certain errors */ @@ -203,12 +204,7 @@ int PyMapping_GetOptionalItem(PyObject *obj, PyObject *key, PyObject **result) { if (PyDict_CheckExact(obj)) { - *result = PyDict_GetItemWithError(obj, key); /* borrowed */ - if (*result) { - Py_INCREF(*result); - return 1; - } - return PyErr_Occurred() ? -1 : 0; + return PyDict_GetItemRef(obj, key, result); } *result = PyObject_GetItem(obj, key); @@ -807,6 +803,27 @@ PyBuffer_Release(Py_buffer *view) Py_DECREF(obj); } +static int +_buffer_release_call(void *arg) +{ + PyBuffer_Release((Py_buffer *)arg); + return 0; +} + +int +_PyBuffer_ReleaseInInterpreter(PyInterpreterState *interp, + Py_buffer *view) +{ + return _Py_CallInInterpreter(interp, _buffer_release_call, view); +} + +int +_PyBuffer_ReleaseInInterpreterAndRawFree(PyInterpreterState *interp, + Py_buffer *view) +{ + return _Py_CallInInterpreterAndRawFree(interp, _buffer_release_call, view); +} + PyObject * PyObject_Format(PyObject *obj, PyObject *format_spec) { @@ -1163,29 +1180,10 @@ PyNumber_Multiply(PyObject *v, PyObject *w) return result; } -PyObject * -PyNumber_MatrixMultiply(PyObject *v, PyObject *w) -{ - return binary_op(v, w, NB_SLOT(nb_matrix_multiply), "@"); -} - -PyObject * -PyNumber_FloorDivide(PyObject *v, PyObject *w) -{ - return binary_op(v, w, NB_SLOT(nb_floor_divide), "//"); -} - -PyObject * -PyNumber_TrueDivide(PyObject *v, PyObject *w) -{ - return binary_op(v, w, NB_SLOT(nb_true_divide), "/"); -} - -PyObject * -PyNumber_Remainder(PyObject *v, PyObject *w) -{ - return binary_op(v, w, NB_SLOT(nb_remainder), "%"); -} +BINARY_FUNC(PyNumber_MatrixMultiply, nb_matrix_multiply, "@") +BINARY_FUNC(PyNumber_FloorDivide, nb_floor_divide, "//") +BINARY_FUNC(PyNumber_TrueDivide, nb_true_divide, "/") +BINARY_FUNC(PyNumber_Remainder, nb_remainder, "%") PyObject * PyNumber_Power(PyObject *v, PyObject *w, PyObject *z) @@ -1362,73 +1360,27 @@ _PyNumber_InPlacePowerNoMod(PyObject *lhs, PyObject *rhs) /* Unary operators and functions */ -PyObject * -PyNumber_Negative(PyObject *o) -{ - if (o == NULL) { - return null_error(); - } - - PyNumberMethods *m = Py_TYPE(o)->tp_as_number; - if (m && m->nb_negative) { - PyObject *res = (*m->nb_negative)(o); - assert(_Py_CheckSlotResult(o, "__neg__", res != NULL)); - return res; - } - - return type_error("bad operand type for unary -: '%.200s'", o); -} - -PyObject * -PyNumber_Positive(PyObject *o) -{ - if (o == NULL) { - return null_error(); - } - - PyNumberMethods *m = Py_TYPE(o)->tp_as_number; - if (m && m->nb_positive) { - PyObject *res = (*m->nb_positive)(o); - assert(_Py_CheckSlotResult(o, "__pos__", res != NULL)); - return res; - } - - return type_error("bad operand type for unary +: '%.200s'", o); -} - -PyObject * -PyNumber_Invert(PyObject *o) -{ - if (o == NULL) { - return null_error(); - } - - PyNumberMethods *m = Py_TYPE(o)->tp_as_number; - if (m && m->nb_invert) { - PyObject *res = (*m->nb_invert)(o); - assert(_Py_CheckSlotResult(o, "__invert__", res != NULL)); - return res; - } - - return type_error("bad operand type for unary ~: '%.200s'", o); -} - -PyObject * -PyNumber_Absolute(PyObject *o) -{ - if (o == NULL) { - return null_error(); - } - - PyNumberMethods *m = Py_TYPE(o)->tp_as_number; - if (m && m->nb_absolute) { - PyObject *res = m->nb_absolute(o); - assert(_Py_CheckSlotResult(o, "__abs__", res != NULL)); - return res; - } - - return type_error("bad operand type for abs(): '%.200s'", o); -} +#define UNARY_FUNC(func, op, meth_name, descr) \ + PyObject * \ + func(PyObject *o) { \ + if (o == NULL) { \ + return null_error(); \ + } \ + \ + PyNumberMethods *m = Py_TYPE(o)->tp_as_number; \ + if (m && m->op) { \ + PyObject *res = (*m->op)(o); \ + assert(_Py_CheckSlotResult(o, #meth_name, res != NULL)); \ + return res; \ + } \ + \ + return type_error("bad operand type for "descr": '%.200s'", o); \ + } + +UNARY_FUNC(PyNumber_Negative, nb_negative, __neg__, "unary -") +UNARY_FUNC(PyNumber_Positive, nb_positive, __pow__, "unary +") +UNARY_FUNC(PyNumber_Invert, nb_invert, __invert__, "unary ~") +UNARY_FUNC(PyNumber_Absolute, nb_absolute, __abs__, "abs()") int @@ -2394,11 +2346,13 @@ int PyMapping_GetOptionalItemString(PyObject *obj, const char *key, PyObject **result) { if (key == NULL) { + *result = NULL; null_error(); return -1; } PyObject *okey = PyUnicode_FromString(key); if (okey == NULL) { + *result = NULL; return -1; } int rc = PyMapping_GetOptionalItem(obj, okey, result); @@ -2426,31 +2380,71 @@ PyMapping_SetItemString(PyObject *o, const char *key, PyObject *value) } int -PyMapping_HasKeyString(PyObject *o, const char *key) +PyMapping_HasKeyStringWithError(PyObject *obj, const char *key) { - PyObject *v; + PyObject *res; + int rc = PyMapping_GetOptionalItemString(obj, key, &res); + Py_XDECREF(res); + return rc; +} - v = PyMapping_GetItemString(o, key); - if (v) { - Py_DECREF(v); - return 1; - } - PyErr_Clear(); - return 0; +int +PyMapping_HasKeyWithError(PyObject *obj, PyObject *key) +{ + PyObject *res; + int rc = PyMapping_GetOptionalItem(obj, key, &res); + Py_XDECREF(res); + return rc; } int -PyMapping_HasKey(PyObject *o, PyObject *key) +PyMapping_HasKeyString(PyObject *obj, const char *key) { - PyObject *v; + PyObject *value; + int rc; + if (obj == NULL) { + // For backward compatibility. + // PyMapping_GetOptionalItemString() crashes if obj is NULL. + null_error(); + rc = -1; + } + else { + rc = PyMapping_GetOptionalItemString(obj, key, &value); + } + if (rc < 0) { + PyErr_FormatUnraisable( + "Exception ignored in PyMapping_HasKeyString(); consider using " + "PyMapping_HasKeyStringWithError(), " + "PyMapping_GetOptionalItemString() or PyMapping_GetItemString()"); + return 0; + } + Py_XDECREF(value); + return rc; +} - v = PyObject_GetItem(o, key); - if (v) { - Py_DECREF(v); - return 1; +int +PyMapping_HasKey(PyObject *obj, PyObject *key) +{ + PyObject *value; + int rc; + if (obj == NULL || key == NULL) { + // For backward compatibility. + // PyMapping_GetOptionalItem() crashes if any of them is NULL. + null_error(); + rc = -1; } - PyErr_Clear(); - return 0; + else { + rc = PyMapping_GetOptionalItem(obj, key, &value); + } + if (rc < 0) { + PyErr_FormatUnraisable( + "Exception ignored in PyMapping_HasKey(); consider using " + "PyMapping_HasKeyWithError(), " + "PyMapping_GetOptionalItem() or PyObject_GetItem()"); + return 0; + } + Py_XDECREF(value); + return rc; } /* This function is quite similar to PySequence_Fast(), but specialized to be @@ -2812,7 +2806,7 @@ object_issubclass(PyThreadState *tstate, PyObject *derived, PyObject *cls) return -1; } - /* Probably never reached anymore. */ + /* Can be reached when infinite recursion happens. */ return recursive_issubclass(derived, cls); } diff --git a/Objects/boolobject.c b/Objects/boolobject.c index e2e359437f0edf..fb48dcbeca7850 100644 --- a/Objects/boolobject.c +++ b/Objects/boolobject.c @@ -110,9 +110,10 @@ bool_xor(PyObject *a, PyObject *b) /* Doc string */ PyDoc_STRVAR(bool_doc, -"bool(x) -> bool\n\ +"bool(object=False, /)\n\ +--\n\ \n\ -Returns True when the argument x is true, False otherwise.\n\ +Returns True when the argument is true, False otherwise.\n\ The builtins True and False are the only two instances of the class bool.\n\ The class bool is a subclass of the class int, and cannot be subclassed."); diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c index 18a24a369a64c1..659de7d3dd5a99 100644 --- a/Objects/bytearrayobject.c +++ b/Objects/bytearrayobject.c @@ -4,6 +4,7 @@ #include "pycore_abstract.h" // _PyIndex_Check() #include "pycore_bytes_methods.h" #include "pycore_bytesobject.h" +#include "pycore_ceval.h" // _PyEval_GetBuiltin() #include "pycore_object.h" // _PyObject_GC_UNTRACK() #include "pycore_strhex.h" // _Py_strhex_with_sep() #include "pycore_long.h" // _PyLong_FromUnsignedChar() @@ -2006,7 +2007,10 @@ static PyObject * bytearray_join(PyByteArrayObject *self, PyObject *iterable_of_bytes) /*[clinic end generated code: output=a8516370bf68ae08 input=aba6b1f9b30fcb8e]*/ { - return stringlib_bytes_join((PyObject*)self, iterable_of_bytes); + self->ob_exports++; // this protects `self` from being cleared/resized if `iterable_of_bytes` is a custom iterator + PyObject* ret = stringlib_bytes_join((PyObject*)self, iterable_of_bytes); + self->ob_exports--; // unexport `self` + return ret; } /*[clinic input] diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c index afe9192720c628..26227dd251122d 100644 --- a/Objects/bytesobject.c +++ b/Objects/bytesobject.c @@ -2,11 +2,12 @@ #include "Python.h" #include "pycore_abstract.h" // _PyIndex_Check() -#include "pycore_bytesobject.h" // _PyBytes_Find(), _PyBytes_Repeat() #include "pycore_bytes_methods.h" // _Py_bytes_startswith() +#include "pycore_bytesobject.h" // _PyBytes_Find(), _PyBytes_Repeat() #include "pycore_call.h" // _PyObject_CallNoArgs() +#include "pycore_ceval.h" // _PyEval_GetBuiltin() #include "pycore_format.h" // F_LJUST -#include "pycore_global_objects.h" // _Py_GET_GLOBAL_OBJECT() +#include "pycore_global_objects.h"// _Py_GET_GLOBAL_OBJECT() #include "pycore_initconfig.h" // _PyStatus_OK() #include "pycore_long.h" // _PyLong_DigitValue #include "pycore_object.h" // _PyObject_GC_TRACK @@ -721,11 +722,11 @@ _PyBytes_FormatEx(const char *format, Py_ssize_t format_len, if (--fmtcnt >= 0) c = *fmt++; } - else if (c >= 0 && isdigit(c)) { + else if (c >= 0 && Py_ISDIGIT(c)) { width = c - '0'; while (--fmtcnt >= 0) { c = Py_CHARMASK(*fmt++); - if (!isdigit(c)) + if (!Py_ISDIGIT(c)) break; if (width > (PY_SSIZE_T_MAX - ((int)c - '0')) / 10) { PyErr_SetString( @@ -752,7 +753,7 @@ _PyBytes_FormatEx(const char *format, Py_ssize_t format_len, "* wants int"); goto error; } - prec = _PyLong_AsInt(v); + prec = PyLong_AsInt(v); if (prec == -1 && PyErr_Occurred()) goto error; if (prec < 0) @@ -760,11 +761,11 @@ _PyBytes_FormatEx(const char *format, Py_ssize_t format_len, if (--fmtcnt >= 0) c = *fmt++; } - else if (c >= 0 && isdigit(c)) { + else if (c >= 0 && Py_ISDIGIT(c)) { prec = c - '0'; while (--fmtcnt >= 0) { c = Py_CHARMASK(*fmt++); - if (!isdigit(c)) + if (!Py_ISDIGIT(c)) break; if (prec > (INT_MAX - ((int)c - '0')) / 10) { PyErr_SetString( diff --git a/Objects/capsule.c b/Objects/capsule.c index baaddb3f1f0849..555979dab2b789 100644 --- a/Objects/capsule.c +++ b/Objects/capsule.c @@ -1,6 +1,10 @@ /* Wrap void * pointers to be passed between C modules */ #include "Python.h" +#include "pycore_capsule.h" // export _PyCapsule_SetTraverse() +#include "pycore_gc.h" // _PyObject_GC_IS_TRACKED() +#include "pycore_object.h" // _PyObject_GC_TRACK() + /* Internal structure of PyCapsule */ typedef struct { @@ -9,18 +13,28 @@ typedef struct { const char *name; void *context; PyCapsule_Destructor destructor; + traverseproc traverse_func; + inquiry clear_func; } PyCapsule; static int -_is_legal_capsule(PyCapsule *capsule, const char *invalid_capsule) +_is_legal_capsule(PyObject *op, const char *invalid_capsule) { - if (!capsule || !PyCapsule_CheckExact(capsule) || capsule->pointer == NULL) { - PyErr_SetString(PyExc_ValueError, invalid_capsule); - return 0; + if (!op || !PyCapsule_CheckExact(op)) { + goto error; + } + PyCapsule *capsule = (PyCapsule *)op; + + if (capsule->pointer == NULL) { + goto error; } return 1; + +error: + PyErr_SetString(PyExc_ValueError, invalid_capsule); + return 0; } #define is_legal_capsule(capsule, name) \ @@ -50,7 +64,7 @@ PyCapsule_New(void *pointer, const char *name, PyCapsule_Destructor destructor) return NULL; } - capsule = PyObject_New(PyCapsule, &PyCapsule_Type); + capsule = PyObject_GC_New(PyCapsule, &PyCapsule_Type); if (capsule == NULL) { return NULL; } @@ -59,15 +73,18 @@ PyCapsule_New(void *pointer, const char *name, PyCapsule_Destructor destructor) capsule->name = name; capsule->context = NULL; capsule->destructor = destructor; + capsule->traverse_func = NULL; + capsule->clear_func = NULL; + // Only track the object by the GC when _PyCapsule_SetTraverse() is called return (PyObject *)capsule; } int -PyCapsule_IsValid(PyObject *o, const char *name) +PyCapsule_IsValid(PyObject *op, const char *name) { - PyCapsule *capsule = (PyCapsule *)o; + PyCapsule *capsule = (PyCapsule *)op; return (capsule != NULL && PyCapsule_CheckExact(capsule) && @@ -77,13 +94,12 @@ PyCapsule_IsValid(PyObject *o, const char *name) void * -PyCapsule_GetPointer(PyObject *o, const char *name) +PyCapsule_GetPointer(PyObject *op, const char *name) { - PyCapsule *capsule = (PyCapsule *)o; - - if (!is_legal_capsule(capsule, "PyCapsule_GetPointer")) { + if (!is_legal_capsule(op, "PyCapsule_GetPointer")) { return NULL; } + PyCapsule *capsule = (PyCapsule *)op; if (!name_matches(name, capsule->name)) { PyErr_SetString(PyExc_ValueError, "PyCapsule_GetPointer called with incorrect name"); @@ -95,52 +111,48 @@ PyCapsule_GetPointer(PyObject *o, const char *name) const char * -PyCapsule_GetName(PyObject *o) +PyCapsule_GetName(PyObject *op) { - PyCapsule *capsule = (PyCapsule *)o; - - if (!is_legal_capsule(capsule, "PyCapsule_GetName")) { + if (!is_legal_capsule(op, "PyCapsule_GetName")) { return NULL; } + PyCapsule *capsule = (PyCapsule *)op; return capsule->name; } PyCapsule_Destructor -PyCapsule_GetDestructor(PyObject *o) +PyCapsule_GetDestructor(PyObject *op) { - PyCapsule *capsule = (PyCapsule *)o; - - if (!is_legal_capsule(capsule, "PyCapsule_GetDestructor")) { + if (!is_legal_capsule(op, "PyCapsule_GetDestructor")) { return NULL; } + PyCapsule *capsule = (PyCapsule *)op; return capsule->destructor; } void * -PyCapsule_GetContext(PyObject *o) +PyCapsule_GetContext(PyObject *op) { - PyCapsule *capsule = (PyCapsule *)o; - - if (!is_legal_capsule(capsule, "PyCapsule_GetContext")) { + if (!is_legal_capsule(op, "PyCapsule_GetContext")) { return NULL; } + PyCapsule *capsule = (PyCapsule *)op; return capsule->context; } int -PyCapsule_SetPointer(PyObject *o, void *pointer) +PyCapsule_SetPointer(PyObject *op, void *pointer) { - PyCapsule *capsule = (PyCapsule *)o; - - if (!pointer) { - PyErr_SetString(PyExc_ValueError, "PyCapsule_SetPointer called with null pointer"); + if (!is_legal_capsule(op, "PyCapsule_SetPointer")) { return -1; } + PyCapsule *capsule = (PyCapsule *)op; - if (!is_legal_capsule(capsule, "PyCapsule_SetPointer")) { + if (!pointer) { + PyErr_SetString(PyExc_ValueError, "PyCapsule_SetPointer called with null pointer"); return -1; } @@ -150,13 +162,12 @@ PyCapsule_SetPointer(PyObject *o, void *pointer) int -PyCapsule_SetName(PyObject *o, const char *name) +PyCapsule_SetName(PyObject *op, const char *name) { - PyCapsule *capsule = (PyCapsule *)o; - - if (!is_legal_capsule(capsule, "PyCapsule_SetName")) { + if (!is_legal_capsule(op, "PyCapsule_SetName")) { return -1; } + PyCapsule *capsule = (PyCapsule *)op; capsule->name = name; return 0; @@ -164,13 +175,12 @@ PyCapsule_SetName(PyObject *o, const char *name) int -PyCapsule_SetDestructor(PyObject *o, PyCapsule_Destructor destructor) +PyCapsule_SetDestructor(PyObject *op, PyCapsule_Destructor destructor) { - PyCapsule *capsule = (PyCapsule *)o; - - if (!is_legal_capsule(capsule, "PyCapsule_SetDestructor")) { + if (!is_legal_capsule(op, "PyCapsule_SetDestructor")) { return -1; } + PyCapsule *capsule = (PyCapsule *)op; capsule->destructor = destructor; return 0; @@ -178,19 +188,42 @@ PyCapsule_SetDestructor(PyObject *o, PyCapsule_Destructor destructor) int -PyCapsule_SetContext(PyObject *o, void *context) +PyCapsule_SetContext(PyObject *op, void *context) { - PyCapsule *capsule = (PyCapsule *)o; - - if (!is_legal_capsule(capsule, "PyCapsule_SetContext")) { + if (!is_legal_capsule(op, "PyCapsule_SetContext")) { return -1; } + PyCapsule *capsule = (PyCapsule *)op; capsule->context = context; return 0; } +int +_PyCapsule_SetTraverse(PyObject *op, traverseproc traverse_func, inquiry clear_func) +{ + if (!is_legal_capsule(op, "_PyCapsule_SetTraverse")) { + return -1; + } + PyCapsule *capsule = (PyCapsule *)op; + + if (traverse_func == NULL || clear_func == NULL) { + PyErr_SetString(PyExc_ValueError, + "_PyCapsule_SetTraverse() called with NULL callback"); + return -1; + } + + if (!_PyObject_GC_IS_TRACKED(op)) { + _PyObject_GC_TRACK(op); + } + + capsule->traverse_func = traverse_func; + capsule->clear_func = clear_func; + return 0; +} + + void * PyCapsule_Import(const char *name, int no_block) { @@ -249,13 +282,14 @@ PyCapsule_Import(const char *name, int no_block) static void -capsule_dealloc(PyObject *o) +capsule_dealloc(PyObject *op) { - PyCapsule *capsule = (PyCapsule *)o; + PyCapsule *capsule = (PyCapsule *)op; + PyObject_GC_UnTrack(op); if (capsule->destructor) { - capsule->destructor(o); + capsule->destructor(op); } - PyObject_Free(o); + PyObject_GC_Del(op); } @@ -279,6 +313,27 @@ capsule_repr(PyObject *o) } +static int +capsule_traverse(PyCapsule *capsule, visitproc visit, void *arg) +{ + // Capsule object is only tracked by the GC + // if _PyCapsule_SetTraverse() is called + assert(capsule->traverse_func != NULL); + + return capsule->traverse_func((PyObject*)capsule, visit, arg); +} + + +static int +capsule_clear(PyCapsule *capsule) +{ + // Capsule object is only tracked by the GC + // if _PyCapsule_SetTraverse() is called + assert(capsule->clear_func != NULL); + + return capsule->clear_func((PyObject*)capsule); +} + PyDoc_STRVAR(PyCapsule_Type__doc__, "Capsule objects let you wrap a C \"void *\" pointer in a Python\n\ @@ -293,27 +348,14 @@ Python import mechanism to link to one another.\n\ PyTypeObject PyCapsule_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) - "PyCapsule", /*tp_name*/ - sizeof(PyCapsule), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - /* methods */ - capsule_dealloc, /*tp_dealloc*/ - 0, /*tp_vectorcall_offset*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_as_async*/ - capsule_repr, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash*/ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - 0, /*tp_flags*/ - PyCapsule_Type__doc__ /*tp_doc*/ + .tp_name = "PyCapsule", + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, + .tp_basicsize = sizeof(PyCapsule), + .tp_dealloc = capsule_dealloc, + .tp_repr = capsule_repr, + .tp_doc = PyCapsule_Type__doc__, + .tp_traverse = (traverseproc)capsule_traverse, + .tp_clear = (inquiry)capsule_clear, }; diff --git a/Objects/cellobject.c b/Objects/cellobject.c index f516707f6f8086..f1a43be38b2b58 100644 --- a/Objects/cellobject.c +++ b/Objects/cellobject.c @@ -1,6 +1,7 @@ /* Cell object implementation */ #include "Python.h" +#include "pycore_modsupport.h" // _PyArg_NoKeywords() #include "pycore_object.h" PyObject * diff --git a/Objects/classobject.c b/Objects/classobject.c index 5471045d777c9d..d7e520f556d9a0 100644 --- a/Objects/classobject.c +++ b/Objects/classobject.c @@ -2,6 +2,7 @@ #include "Python.h" #include "pycore_call.h" // _PyObject_VectorcallTstate() +#include "pycore_ceval.h" // _PyEval_GetBuiltin() #include "pycore_object.h" #include "pycore_pyerrors.h" #include "pycore_pystate.h" // _PyThreadState_GET() @@ -318,6 +319,13 @@ method_traverse(PyMethodObject *im, visitproc visit, void *arg) return 0; } +static PyObject * +method_descr_get(PyObject *meth, PyObject *obj, PyObject *cls) +{ + Py_INCREF(meth); + return meth; +} + PyTypeObject PyMethod_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) .tp_name = "method", @@ -338,6 +346,7 @@ PyTypeObject PyMethod_Type = { .tp_methods = method_methods, .tp_members = method_memberlist, .tp_getset = method_getset, + .tp_descr_get = method_descr_get, .tp_new = method_new, }; diff --git a/Objects/clinic/bytearrayobject.c.h b/Objects/clinic/bytearrayobject.c.h index 33caca28224565..d95245067e2608 100644 --- a/Objects/clinic/bytearrayobject.c.h +++ b/Objects/clinic/bytearrayobject.c.h @@ -3,10 +3,11 @@ 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() +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() #endif - +#include "pycore_abstract.h" // _PyNumber_Index() +#include "pycore_modsupport.h" // _PyArg_UnpackKeywords() static int bytearray___init___impl(PyByteArrayObject *self, PyObject *arg, @@ -161,10 +162,6 @@ bytearray_removeprefix(PyByteArrayObject *self, PyObject *arg) if (PyObject_GetBuffer(arg, &prefix, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&prefix, 'C')) { - _PyArg_BadArgument("removeprefix", "argument", "contiguous buffer", arg); - goto exit; - } return_value = bytearray_removeprefix_impl(self, &prefix); exit: @@ -201,10 +198,6 @@ bytearray_removesuffix(PyByteArrayObject *self, PyObject *arg) if (PyObject_GetBuffer(arg, &suffix, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&suffix, 'C')) { - _PyArg_BadArgument("removesuffix", "argument", "contiguous buffer", arg); - goto exit; - } return_value = bytearray_removesuffix_impl(self, &suffix); exit: @@ -315,17 +308,9 @@ bytearray_maketrans(void *null, PyObject *const *args, Py_ssize_t nargs) if (PyObject_GetBuffer(args[0], &frm, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&frm, 'C')) { - _PyArg_BadArgument("maketrans", "argument 1", "contiguous buffer", args[0]); - goto exit; - } if (PyObject_GetBuffer(args[1], &to, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&to, 'C')) { - _PyArg_BadArgument("maketrans", "argument 2", "contiguous buffer", args[1]); - goto exit; - } return_value = bytearray_maketrans_impl(&frm, &to); exit: @@ -375,17 +360,9 @@ bytearray_replace(PyByteArrayObject *self, PyObject *const *args, Py_ssize_t nar if (PyObject_GetBuffer(args[0], &old, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&old, 'C')) { - _PyArg_BadArgument("replace", "argument 1", "contiguous buffer", args[0]); - goto exit; - } if (PyObject_GetBuffer(args[1], &new, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&new, 'C')) { - _PyArg_BadArgument("replace", "argument 2", "contiguous buffer", args[1]); - goto exit; - } if (nargs < 3) { goto skip_optional; } @@ -1203,7 +1180,7 @@ bytearray_hex(PyByteArrayObject *self, PyObject *const *args, Py_ssize_t nargs, goto skip_optional_pos; } } - bytes_per_sep = _PyLong_AsInt(args[1]); + bytes_per_sep = PyLong_AsInt(args[1]); if (bytes_per_sep == -1 && PyErr_Occurred()) { goto exit; } @@ -1256,7 +1233,7 @@ bytearray_reduce_ex(PyByteArrayObject *self, PyObject *const *args, Py_ssize_t n if (nargs < 1) { goto skip_optional; } - proto = _PyLong_AsInt(args[0]); + proto = PyLong_AsInt(args[0]); if (proto == -1 && PyErr_Occurred()) { goto exit; } @@ -1284,4 +1261,4 @@ bytearray_sizeof(PyByteArrayObject *self, PyObject *Py_UNUSED(ignored)) { return bytearray_sizeof_impl(self); } -/*[clinic end generated code: output=0817195f176cd8e3 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=0797a5e03cda2a16 input=a9049054013a1b77]*/ diff --git a/Objects/clinic/bytesobject.c.h b/Objects/clinic/bytesobject.c.h index 1ec0c95485a209..1e45be3e7aefb3 100644 --- a/Objects/clinic/bytesobject.c.h +++ b/Objects/clinic/bytesobject.c.h @@ -3,10 +3,11 @@ 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() +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() #endif - +#include "pycore_abstract.h" // _PyNumber_Index() +#include "pycore_modsupport.h" // _PyArg_UnpackKeywords() PyDoc_STRVAR(bytes___bytes____doc__, "__bytes__($self, /)\n" @@ -140,10 +141,6 @@ bytes_partition(PyBytesObject *self, PyObject *arg) if (PyObject_GetBuffer(arg, &sep, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&sep, 'C')) { - _PyArg_BadArgument("partition", "argument", "contiguous buffer", arg); - goto exit; - } return_value = bytes_partition_impl(self, &sep); exit: @@ -183,10 +180,6 @@ bytes_rpartition(PyBytesObject *self, PyObject *arg) if (PyObject_GetBuffer(arg, &sep, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&sep, 'C')) { - _PyArg_BadArgument("rpartition", "argument", "contiguous buffer", arg); - goto exit; - } return_value = bytes_rpartition_impl(self, &sep); exit: @@ -502,17 +495,9 @@ bytes_maketrans(void *null, PyObject *const *args, Py_ssize_t nargs) if (PyObject_GetBuffer(args[0], &frm, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&frm, 'C')) { - _PyArg_BadArgument("maketrans", "argument 1", "contiguous buffer", args[0]); - goto exit; - } if (PyObject_GetBuffer(args[1], &to, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&to, 'C')) { - _PyArg_BadArgument("maketrans", "argument 2", "contiguous buffer", args[1]); - goto exit; - } return_value = bytes_maketrans_impl(&frm, &to); exit: @@ -562,17 +547,9 @@ bytes_replace(PyBytesObject *self, PyObject *const *args, Py_ssize_t nargs) if (PyObject_GetBuffer(args[0], &old, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&old, 'C')) { - _PyArg_BadArgument("replace", "argument 1", "contiguous buffer", args[0]); - goto exit; - } if (PyObject_GetBuffer(args[1], &new, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&new, 'C')) { - _PyArg_BadArgument("replace", "argument 2", "contiguous buffer", args[1]); - goto exit; - } if (nargs < 3) { goto skip_optional; } @@ -628,10 +605,6 @@ bytes_removeprefix(PyBytesObject *self, PyObject *arg) if (PyObject_GetBuffer(arg, &prefix, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&prefix, 'C')) { - _PyArg_BadArgument("removeprefix", "argument", "contiguous buffer", arg); - goto exit; - } return_value = bytes_removeprefix_impl(self, &prefix); exit: @@ -668,10 +641,6 @@ bytes_removesuffix(PyBytesObject *self, PyObject *arg) if (PyObject_GetBuffer(arg, &suffix, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&suffix, 'C')) { - _PyArg_BadArgument("removesuffix", "argument", "contiguous buffer", arg); - goto exit; - } return_value = bytes_removesuffix_impl(self, &suffix); exit: @@ -958,7 +927,7 @@ bytes_hex(PyBytesObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject goto skip_optional_pos; } } - bytes_per_sep = _PyLong_AsInt(args[1]); + bytes_per_sep = PyLong_AsInt(args[1]); if (bytes_per_sep == -1 && PyErr_Occurred()) { goto exit; } @@ -1060,4 +1029,4 @@ bytes_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) exit: return return_value; } -/*[clinic end generated code: output=bc4801bf1fa628f4 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=8a49dbbd78914a6f input=a9049054013a1b77]*/ diff --git a/Objects/clinic/classobject.c.h b/Objects/clinic/classobject.c.h index a7bac63052bc40..3e149c97324a6a 100644 --- a/Objects/clinic/classobject.c.h +++ b/Objects/clinic/classobject.c.h @@ -2,11 +2,7 @@ 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 - +#include "pycore_modsupport.h" // _PyArg_CheckPositional() PyDoc_STRVAR(method___reduce____doc__, "__reduce__($self, /)\n" @@ -86,4 +82,4 @@ instancemethod_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) exit: return return_value; } -/*[clinic end generated code: output=2a5e7fa5947a86cb input=a9049054013a1b77]*/ +/*[clinic end generated code: output=5a5e3f2d0726f189 input=a9049054013a1b77]*/ diff --git a/Objects/clinic/codeobject.c.h b/Objects/clinic/codeobject.c.h index 1f2ab56775a1ee..68e2d7f528c061 100644 --- a/Objects/clinic/codeobject.c.h +++ b/Objects/clinic/codeobject.c.h @@ -3,10 +3,10 @@ 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() +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() #endif - +#include "pycore_modsupport.h" // _PyArg_CheckPositional() PyDoc_STRVAR(code_new__doc__, "code(argcount, posonlyargcount, kwonlyargcount, nlocals, stacksize,\n" @@ -57,27 +57,27 @@ code_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) if (!_PyArg_CheckPositional("code", PyTuple_GET_SIZE(args), 16, 18)) { goto exit; } - argcount = _PyLong_AsInt(PyTuple_GET_ITEM(args, 0)); + argcount = PyLong_AsInt(PyTuple_GET_ITEM(args, 0)); if (argcount == -1 && PyErr_Occurred()) { goto exit; } - posonlyargcount = _PyLong_AsInt(PyTuple_GET_ITEM(args, 1)); + posonlyargcount = PyLong_AsInt(PyTuple_GET_ITEM(args, 1)); if (posonlyargcount == -1 && PyErr_Occurred()) { goto exit; } - kwonlyargcount = _PyLong_AsInt(PyTuple_GET_ITEM(args, 2)); + kwonlyargcount = PyLong_AsInt(PyTuple_GET_ITEM(args, 2)); if (kwonlyargcount == -1 && PyErr_Occurred()) { goto exit; } - nlocals = _PyLong_AsInt(PyTuple_GET_ITEM(args, 3)); + nlocals = PyLong_AsInt(PyTuple_GET_ITEM(args, 3)); if (nlocals == -1 && PyErr_Occurred()) { goto exit; } - stacksize = _PyLong_AsInt(PyTuple_GET_ITEM(args, 4)); + stacksize = PyLong_AsInt(PyTuple_GET_ITEM(args, 4)); if (stacksize == -1 && PyErr_Occurred()) { goto exit; } - flags = _PyLong_AsInt(PyTuple_GET_ITEM(args, 5)); + flags = PyLong_AsInt(PyTuple_GET_ITEM(args, 5)); if (flags == -1 && PyErr_Occurred()) { goto exit; } @@ -116,7 +116,7 @@ code_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) goto exit; } qualname = PyTuple_GET_ITEM(args, 12); - firstlineno = _PyLong_AsInt(PyTuple_GET_ITEM(args, 13)); + firstlineno = PyLong_AsInt(PyTuple_GET_ITEM(args, 13)); if (firstlineno == -1 && PyErr_Occurred()) { goto exit; } @@ -154,12 +154,7 @@ code_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) } PyDoc_STRVAR(code_replace__doc__, -"replace($self, /, *, co_argcount=-1, co_posonlyargcount=-1,\n" -" co_kwonlyargcount=-1, co_nlocals=-1, co_stacksize=-1,\n" -" co_flags=-1, co_firstlineno=-1, co_code=None, co_consts=None,\n" -" co_names=None, co_varnames=None, co_freevars=None,\n" -" co_cellvars=None, co_filename=None, co_name=None,\n" -" co_qualname=None, co_linetable=None, co_exceptiontable=None)\n" +"replace($self, /, **changes)\n" "--\n" "\n" "Return a copy of the code object with new values for the specified fields."); @@ -171,13 +166,12 @@ static PyObject * code_replace_impl(PyCodeObject *self, int co_argcount, int co_posonlyargcount, int co_kwonlyargcount, int co_nlocals, int co_stacksize, int co_flags, - int co_firstlineno, PyBytesObject *co_code, - PyObject *co_consts, PyObject *co_names, - PyObject *co_varnames, PyObject *co_freevars, - PyObject *co_cellvars, PyObject *co_filename, - PyObject *co_name, PyObject *co_qualname, - PyBytesObject *co_linetable, - PyBytesObject *co_exceptiontable); + int co_firstlineno, PyObject *co_code, PyObject *co_consts, + PyObject *co_names, PyObject *co_varnames, + PyObject *co_freevars, PyObject *co_cellvars, + PyObject *co_filename, PyObject *co_name, + PyObject *co_qualname, PyObject *co_linetable, + PyObject *co_exceptiontable); static PyObject * code_replace(PyCodeObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) @@ -217,7 +211,7 @@ code_replace(PyCodeObject *self, PyObject *const *args, Py_ssize_t nargs, PyObje int co_stacksize = self->co_stacksize; int co_flags = self->co_flags; int co_firstlineno = self->co_firstlineno; - PyBytesObject *co_code = NULL; + PyObject *co_code = NULL; PyObject *co_consts = self->co_consts; PyObject *co_names = self->co_names; PyObject *co_varnames = NULL; @@ -226,8 +220,8 @@ code_replace(PyCodeObject *self, PyObject *const *args, Py_ssize_t nargs, PyObje PyObject *co_filename = self->co_filename; PyObject *co_name = self->co_name; PyObject *co_qualname = self->co_qualname; - PyBytesObject *co_linetable = (PyBytesObject *)self->co_linetable; - PyBytesObject *co_exceptiontable = (PyBytesObject *)self->co_exceptiontable; + PyObject *co_linetable = self->co_linetable; + PyObject *co_exceptiontable = self->co_exceptiontable; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 0, 0, argsbuf); if (!args) { @@ -237,7 +231,7 @@ code_replace(PyCodeObject *self, PyObject *const *args, Py_ssize_t nargs, PyObje goto skip_optional_kwonly; } if (args[0]) { - co_argcount = _PyLong_AsInt(args[0]); + co_argcount = PyLong_AsInt(args[0]); if (co_argcount == -1 && PyErr_Occurred()) { goto exit; } @@ -246,7 +240,7 @@ code_replace(PyCodeObject *self, PyObject *const *args, Py_ssize_t nargs, PyObje } } if (args[1]) { - co_posonlyargcount = _PyLong_AsInt(args[1]); + co_posonlyargcount = PyLong_AsInt(args[1]); if (co_posonlyargcount == -1 && PyErr_Occurred()) { goto exit; } @@ -255,7 +249,7 @@ code_replace(PyCodeObject *self, PyObject *const *args, Py_ssize_t nargs, PyObje } } if (args[2]) { - co_kwonlyargcount = _PyLong_AsInt(args[2]); + co_kwonlyargcount = PyLong_AsInt(args[2]); if (co_kwonlyargcount == -1 && PyErr_Occurred()) { goto exit; } @@ -264,7 +258,7 @@ code_replace(PyCodeObject *self, PyObject *const *args, Py_ssize_t nargs, PyObje } } if (args[3]) { - co_nlocals = _PyLong_AsInt(args[3]); + co_nlocals = PyLong_AsInt(args[3]); if (co_nlocals == -1 && PyErr_Occurred()) { goto exit; } @@ -273,7 +267,7 @@ code_replace(PyCodeObject *self, PyObject *const *args, Py_ssize_t nargs, PyObje } } if (args[4]) { - co_stacksize = _PyLong_AsInt(args[4]); + co_stacksize = PyLong_AsInt(args[4]); if (co_stacksize == -1 && PyErr_Occurred()) { goto exit; } @@ -282,7 +276,7 @@ code_replace(PyCodeObject *self, PyObject *const *args, Py_ssize_t nargs, PyObje } } if (args[5]) { - co_flags = _PyLong_AsInt(args[5]); + co_flags = PyLong_AsInt(args[5]); if (co_flags == -1 && PyErr_Occurred()) { goto exit; } @@ -291,7 +285,7 @@ code_replace(PyCodeObject *self, PyObject *const *args, Py_ssize_t nargs, PyObje } } if (args[6]) { - co_firstlineno = _PyLong_AsInt(args[6]); + co_firstlineno = PyLong_AsInt(args[6]); if (co_firstlineno == -1 && PyErr_Occurred()) { goto exit; } @@ -304,7 +298,7 @@ code_replace(PyCodeObject *self, PyObject *const *args, Py_ssize_t nargs, PyObje _PyArg_BadArgument("replace", "argument 'co_code'", "bytes", args[7]); goto exit; } - co_code = (PyBytesObject *)args[7]; + co_code = args[7]; if (!--noptargs) { goto skip_optional_kwonly; } @@ -394,7 +388,7 @@ code_replace(PyCodeObject *self, PyObject *const *args, Py_ssize_t nargs, PyObje _PyArg_BadArgument("replace", "argument 'co_linetable'", "bytes", args[16]); goto exit; } - co_linetable = (PyBytesObject *)args[16]; + co_linetable = args[16]; if (!--noptargs) { goto skip_optional_kwonly; } @@ -403,7 +397,7 @@ code_replace(PyCodeObject *self, PyObject *const *args, Py_ssize_t nargs, PyObje _PyArg_BadArgument("replace", "argument 'co_exceptiontable'", "bytes", args[17]); goto exit; } - co_exceptiontable = (PyBytesObject *)args[17]; + co_exceptiontable = args[17]; skip_optional_kwonly: return_value = code_replace_impl(self, co_argcount, co_posonlyargcount, co_kwonlyargcount, co_nlocals, co_stacksize, co_flags, co_firstlineno, co_code, co_consts, co_names, co_varnames, co_freevars, co_cellvars, co_filename, co_name, co_qualname, co_linetable, co_exceptiontable); @@ -461,7 +455,7 @@ code__varname_from_oparg(PyCodeObject *self, PyObject *const *args, Py_ssize_t n if (!args) { goto exit; } - oparg = _PyLong_AsInt(args[0]); + oparg = PyLong_AsInt(args[0]); if (oparg == -1 && PyErr_Occurred()) { goto exit; } @@ -470,4 +464,4 @@ code__varname_from_oparg(PyCodeObject *self, PyObject *const *args, Py_ssize_t n exit: return return_value; } -/*[clinic end generated code: output=4ca4c0c403dbfa71 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=d604263a3ca72a0f input=a9049054013a1b77]*/ diff --git a/Objects/clinic/complexobject.c.h b/Objects/clinic/complexobject.c.h index bb2b3815415f85..49b50304021f7b 100644 --- a/Objects/clinic/complexobject.c.h +++ b/Objects/clinic/complexobject.c.h @@ -3,10 +3,10 @@ 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() +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() #endif - +#include "pycore_modsupport.h" // _PyArg_BadArgument() PyDoc_STRVAR(complex_conjugate__doc__, "conjugate($self, /)\n" @@ -157,4 +157,4 @@ complex_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) exit: return return_value; } -/*[clinic end generated code: output=d438b7ed87f8459e input=a9049054013a1b77]*/ +/*[clinic end generated code: output=04e6261649967b30 input=a9049054013a1b77]*/ diff --git a/Objects/clinic/descrobject.c.h b/Objects/clinic/descrobject.c.h index 75706437df83f9..02fb440d9c83af 100644 --- a/Objects/clinic/descrobject.c.h +++ b/Objects/clinic/descrobject.c.h @@ -3,10 +3,10 @@ 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() +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() #endif - +#include "pycore_modsupport.h" // _PyArg_UnpackKeywords() static PyObject * mappingproxy_new_impl(PyTypeObject *type, PyObject *mapping); @@ -167,4 +167,4 @@ property_init(PyObject *self, PyObject *args, PyObject *kwargs) exit: return return_value; } -/*[clinic end generated code: output=8dc1ddfcf764ac8e input=a9049054013a1b77]*/ +/*[clinic end generated code: output=a4664ccf3da10f5a input=a9049054013a1b77]*/ diff --git a/Objects/clinic/dictobject.c.h b/Objects/clinic/dictobject.c.h index bc2452330e4e2f..641514235c2341 100644 --- a/Objects/clinic/dictobject.c.h +++ b/Objects/clinic/dictobject.c.h @@ -2,11 +2,7 @@ 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 - +#include "pycore_modsupport.h" // _PyArg_CheckPositional() PyDoc_STRVAR(dict_fromkeys__doc__, "fromkeys($type, iterable, value=None, /)\n" @@ -197,4 +193,4 @@ dict___reversed__(PyDictObject *self, PyObject *Py_UNUSED(ignored)) { return dict___reversed___impl(self); } -/*[clinic end generated code: output=c0064abbea6091c5 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=17c3c4cf9a9b95a7 input=a9049054013a1b77]*/ diff --git a/Objects/clinic/enumobject.c.h b/Objects/clinic/enumobject.c.h index adf78efd0d66f4..09774a73c8145c 100644 --- a/Objects/clinic/enumobject.c.h +++ b/Objects/clinic/enumobject.c.h @@ -3,10 +3,10 @@ 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() +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() #endif - +#include "pycore_modsupport.h" // _PyArg_UnpackKeywords() PyDoc_STRVAR(enum_new__doc__, "enumerate(iterable, start=0)\n" @@ -107,4 +107,4 @@ reversed_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) exit: return return_value; } -/*[clinic end generated code: output=aba0ddbeab1601e3 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=5c48a9a482a52e91 input=a9049054013a1b77]*/ diff --git a/Objects/clinic/floatobject.c.h b/Objects/clinic/floatobject.c.h index 3d9cd3a683ff5f..10f6149cc88c22 100644 --- a/Objects/clinic/floatobject.c.h +++ b/Objects/clinic/floatobject.c.h @@ -2,11 +2,7 @@ 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 - +#include "pycore_modsupport.h" // _PyArg_CheckPositional() PyDoc_STRVAR(float_is_integer__doc__, "is_integer($self, /)\n" @@ -322,4 +318,4 @@ float___format__(PyObject *self, PyObject *arg) exit: return return_value; } -/*[clinic end generated code: output=355c3f5102034a41 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=c79743c8551c30d9 input=a9049054013a1b77]*/ diff --git a/Objects/clinic/funcobject.c.h b/Objects/clinic/funcobject.c.h index c3a3a8edc39278..8f20bda26438cf 100644 --- a/Objects/clinic/funcobject.c.h +++ b/Objects/clinic/funcobject.c.h @@ -3,13 +3,14 @@ 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() +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() #endif - +#include "pycore_modsupport.h" // _PyArg_UnpackKeywords() PyDoc_STRVAR(func_new__doc__, -"function(code, globals, name=None, argdefs=None, closure=None)\n" +"function(code, globals, name=None, argdefs=None, closure=None,\n" +" kwdefaults=None)\n" "--\n" "\n" "Create a function object.\n" @@ -23,11 +24,14 @@ PyDoc_STRVAR(func_new__doc__, " argdefs\n" " a tuple that specifies the default argument values\n" " closure\n" -" a tuple that supplies the bindings for free variables"); +" a tuple that supplies the bindings for free variables\n" +" kwdefaults\n" +" a dictionary that specifies the default keyword argument values"); static PyObject * func_new_impl(PyTypeObject *type, PyCodeObject *code, PyObject *globals, - PyObject *name, PyObject *defaults, PyObject *closure); + PyObject *name, PyObject *defaults, PyObject *closure, + PyObject *kwdefaults); static PyObject * func_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) @@ -35,14 +39,14 @@ func_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) PyObject *return_value = NULL; #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - #define NUM_KEYWORDS 5 + #define NUM_KEYWORDS 6 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(code), &_Py_ID(globals), &_Py_ID(name), &_Py_ID(argdefs), &_Py_ID(closure), }, + .ob_item = { &_Py_ID(code), &_Py_ID(globals), &_Py_ID(name), &_Py_ID(argdefs), &_Py_ID(closure), &_Py_ID(kwdefaults), }, }; #undef NUM_KEYWORDS #define KWTUPLE (&_kwtuple.ob_base.ob_base) @@ -51,14 +55,14 @@ func_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) # define KWTUPLE NULL #endif // !Py_BUILD_CORE - static const char * const _keywords[] = {"code", "globals", "name", "argdefs", "closure", NULL}; + static const char * const _keywords[] = {"code", "globals", "name", "argdefs", "closure", "kwdefaults", NULL}; static _PyArg_Parser _parser = { .keywords = _keywords, .fname = "function", .kwtuple = KWTUPLE, }; #undef KWTUPLE - PyObject *argsbuf[5]; + PyObject *argsbuf[6]; PyObject * const *fastargs; Py_ssize_t nargs = PyTuple_GET_SIZE(args); Py_ssize_t noptargs = nargs + (kwargs ? PyDict_GET_SIZE(kwargs) : 0) - 2; @@ -67,8 +71,9 @@ func_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) PyObject *name = Py_None; PyObject *defaults = Py_None; PyObject *closure = Py_None; + PyObject *kwdefaults = Py_None; - fastargs = _PyArg_UnpackKeywords(_PyTuple_CAST(args)->ob_item, nargs, kwargs, NULL, &_parser, 2, 5, 0, argsbuf); + fastargs = _PyArg_UnpackKeywords(_PyTuple_CAST(args)->ob_item, nargs, kwargs, NULL, &_parser, 2, 6, 0, argsbuf); if (!fastargs) { goto exit; } @@ -97,11 +102,17 @@ func_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) goto skip_optional_pos; } } - closure = fastargs[4]; + if (fastargs[4]) { + closure = fastargs[4]; + if (!--noptargs) { + goto skip_optional_pos; + } + } + kwdefaults = fastargs[5]; skip_optional_pos: - return_value = func_new_impl(type, code, globals, name, defaults, closure); + return_value = func_new_impl(type, code, globals, name, defaults, closure, kwdefaults); exit: return return_value; } -/*[clinic end generated code: output=777cead7b1f6fad3 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=10947342188f38a9 input=a9049054013a1b77]*/ diff --git a/Objects/clinic/listobject.c.h b/Objects/clinic/listobject.c.h index e3d6ffa9f76fdb..cf6f7449df5e1d 100644 --- a/Objects/clinic/listobject.c.h +++ b/Objects/clinic/listobject.c.h @@ -3,10 +3,12 @@ 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() +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() #endif - +#include "pycore_abstract.h" // _PyNumber_Index() +#include "pycore_critical_section.h"// Py_BEGIN_CRITICAL_SECTION() +#include "pycore_modsupport.h" // _PyArg_CheckPositional() PyDoc_STRVAR(list_insert__doc__, "insert($self, index, object, /)\n" @@ -43,28 +45,36 @@ list_insert(PyListObject *self, PyObject *const *args, Py_ssize_t nargs) index = ival; } object = args[1]; + Py_BEGIN_CRITICAL_SECTION(self); return_value = list_insert_impl(self, index, object); + Py_END_CRITICAL_SECTION(); exit: return return_value; } -PyDoc_STRVAR(list_clear__doc__, +PyDoc_STRVAR(py_list_clear__doc__, "clear($self, /)\n" "--\n" "\n" "Remove all items from list."); -#define LIST_CLEAR_METHODDEF \ - {"clear", (PyCFunction)list_clear, METH_NOARGS, list_clear__doc__}, +#define PY_LIST_CLEAR_METHODDEF \ + {"clear", (PyCFunction)py_list_clear, METH_NOARGS, py_list_clear__doc__}, static PyObject * -list_clear_impl(PyListObject *self); +py_list_clear_impl(PyListObject *self); static PyObject * -list_clear(PyListObject *self, PyObject *Py_UNUSED(ignored)) +py_list_clear(PyListObject *self, PyObject *Py_UNUSED(ignored)) { - return list_clear_impl(self); + PyObject *return_value = NULL; + + Py_BEGIN_CRITICAL_SECTION(self); + return_value = py_list_clear_impl(self); + Py_END_CRITICAL_SECTION(); + + return return_value; } PyDoc_STRVAR(list_copy__doc__, @@ -94,14 +104,14 @@ PyDoc_STRVAR(list_append__doc__, #define LIST_APPEND_METHODDEF \ {"append", (PyCFunction)list_append, METH_O, list_append__doc__}, -PyDoc_STRVAR(list_extend__doc__, +PyDoc_STRVAR(py_list_extend__doc__, "extend($self, iterable, /)\n" "--\n" "\n" "Extend list by appending elements from the iterable."); -#define LIST_EXTEND_METHODDEF \ - {"extend", (PyCFunction)list_extend, METH_O, list_extend__doc__}, +#define PY_LIST_EXTEND_METHODDEF \ + {"extend", (PyCFunction)py_list_extend, METH_O, py_list_extend__doc__}, PyDoc_STRVAR(list_pop__doc__, "pop($self, index=-1, /)\n" @@ -142,7 +152,9 @@ list_pop(PyListObject *self, PyObject *const *args, Py_ssize_t nargs) index = ival; } skip_optional: + Py_BEGIN_CRITICAL_SECTION(self); return_value = list_pop_impl(self, index); + Py_END_CRITICAL_SECTION(); exit: return return_value; @@ -241,7 +253,13 @@ list_reverse_impl(PyListObject *self); static PyObject * list_reverse(PyListObject *self, PyObject *Py_UNUSED(ignored)) { - return list_reverse_impl(self); + PyObject *return_value = NULL; + + Py_BEGIN_CRITICAL_SECTION(self); + return_value = list_reverse_impl(self); + Py_END_CRITICAL_SECTION(); + + return return_value; } PyDoc_STRVAR(list_index__doc__, @@ -310,6 +328,21 @@ PyDoc_STRVAR(list_remove__doc__, #define LIST_REMOVE_METHODDEF \ {"remove", (PyCFunction)list_remove, METH_O, list_remove__doc__}, +static PyObject * +list_remove_impl(PyListObject *self, PyObject *value); + +static PyObject * +list_remove(PyListObject *self, PyObject *value) +{ + PyObject *return_value = NULL; + + Py_BEGIN_CRITICAL_SECTION(self); + return_value = list_remove_impl(self, value); + Py_END_CRITICAL_SECTION(); + + return return_value; +} + PyDoc_STRVAR(list___init____doc__, "list(iterable=(), /)\n" "--\n" @@ -383,4 +416,4 @@ list___reversed__(PyListObject *self, PyObject *Py_UNUSED(ignored)) { return list___reversed___impl(self); } -/*[clinic end generated code: output=2ca109d8acc775bc input=a9049054013a1b77]*/ +/*[clinic end generated code: output=3c9f24fd3212b18b input=a9049054013a1b77]*/ diff --git a/Objects/clinic/longobject.c.h b/Objects/clinic/longobject.c.h index d37e44f2f330bd..4a3d71c6111af5 100644 --- a/Objects/clinic/longobject.c.h +++ b/Objects/clinic/longobject.c.h @@ -3,10 +3,11 @@ 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() +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() #endif - +#include "pycore_abstract.h" // _PyNumber_Index() +#include "pycore_modsupport.h" // _PyArg_UnpackKeywords() static PyObject * long_new_impl(PyTypeObject *type, PyObject *x, PyObject *obase); @@ -475,4 +476,4 @@ int_is_integer(PyObject *self, PyObject *Py_UNUSED(ignored)) { return int_is_integer_impl(self); } -/*[clinic end generated code: output=75ed306fff493ba1 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=7e6e57246e55911f input=a9049054013a1b77]*/ diff --git a/Objects/clinic/memoryobject.c.h b/Objects/clinic/memoryobject.c.h index 0e6d9a4cad9e8f..f199434dacb9e8 100644 --- a/Objects/clinic/memoryobject.c.h +++ b/Objects/clinic/memoryobject.c.h @@ -3,10 +3,10 @@ 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() +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() #endif - +#include "pycore_modsupport.h" // _PyArg_UnpackKeywords() PyDoc_STRVAR(memoryview__doc__, "memoryview(object)\n" @@ -112,7 +112,7 @@ memoryview__from_flags(PyTypeObject *type, PyObject *const *args, Py_ssize_t nar goto exit; } object = args[0]; - flags = _PyLong_AsInt(args[1]); + flags = PyLong_AsInt(args[1]); if (flags == -1 && PyErr_Occurred()) { goto exit; } @@ -403,7 +403,7 @@ memoryview_hex(PyMemoryViewObject *self, PyObject *const *args, Py_ssize_t nargs goto skip_optional_pos; } } - bytes_per_sep = _PyLong_AsInt(args[1]); + bytes_per_sep = PyLong_AsInt(args[1]); if (bytes_per_sep == -1 && PyErr_Occurred()) { goto exit; } @@ -413,4 +413,4 @@ memoryview_hex(PyMemoryViewObject *self, PyObject *const *args, Py_ssize_t nargs exit: return return_value; } -/*[clinic end generated code: output=a4f6992947bcaf25 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=7e76a09106921ba2 input=a9049054013a1b77]*/ diff --git a/Objects/clinic/moduleobject.c.h b/Objects/clinic/moduleobject.c.h index 29df3888531933..3c0bbe22d5ebab 100644 --- a/Objects/clinic/moduleobject.c.h +++ b/Objects/clinic/moduleobject.c.h @@ -3,10 +3,10 @@ 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() +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() #endif - +#include "pycore_modsupport.h" // _PyArg_UnpackKeywords() PyDoc_STRVAR(module___init____doc__, "module(name, doc=None)\n" @@ -74,4 +74,4 @@ module___init__(PyObject *self, PyObject *args, PyObject *kwargs) exit: return return_value; } -/*[clinic end generated code: output=a5a750cc8190576e input=a9049054013a1b77]*/ +/*[clinic end generated code: output=e8a71bfbed774c15 input=a9049054013a1b77]*/ diff --git a/Objects/clinic/odictobject.c.h b/Objects/clinic/odictobject.c.h index 115a134e3f7f54..5ef5380656905a 100644 --- a/Objects/clinic/odictobject.c.h +++ b/Objects/clinic/odictobject.c.h @@ -3,10 +3,10 @@ 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() +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() #endif - +#include "pycore_modsupport.h" // _PyArg_UnpackKeywords() PyDoc_STRVAR(OrderedDict_fromkeys__doc__, "fromkeys($type, /, iterable, value=None)\n" @@ -332,4 +332,4 @@ OrderedDict_move_to_end(PyODictObject *self, PyObject *const *args, Py_ssize_t n exit: return return_value; } -/*[clinic end generated code: output=76d85a9162d62ca8 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=eff78d2a3f9379bd input=a9049054013a1b77]*/ diff --git a/Objects/clinic/structseq.c.h b/Objects/clinic/structseq.c.h index 40ba18a544f4b3..cec49ebccccb24 100644 --- a/Objects/clinic/structseq.c.h +++ b/Objects/clinic/structseq.c.h @@ -3,10 +3,10 @@ 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() +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() #endif - +#include "pycore_modsupport.h" // _PyArg_UnpackKeywords() static PyObject * structseq_new_impl(PyTypeObject *type, PyObject *arg, PyObject *dict); @@ -62,4 +62,4 @@ structseq_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) exit: return return_value; } -/*[clinic end generated code: output=802d5663c7d01024 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=5bf39b3f06a34ce4 input=a9049054013a1b77]*/ diff --git a/Objects/clinic/tupleobject.c.h b/Objects/clinic/tupleobject.c.h index 3de95759a13f21..5d6a2c481a5f2a 100644 --- a/Objects/clinic/tupleobject.c.h +++ b/Objects/clinic/tupleobject.c.h @@ -2,11 +2,7 @@ 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 - +#include "pycore_modsupport.h" // _PyArg_CheckPositional() PyDoc_STRVAR(tuple_index__doc__, "index($self, value, start=0, stop=sys.maxsize, /)\n" @@ -118,4 +114,4 @@ tuple___getnewargs__(PyTupleObject *self, PyObject *Py_UNUSED(ignored)) { return tuple___getnewargs___impl(self); } -/*[clinic end generated code: output=48a9e0834b300ac3 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=a6a9abba5d121f4c input=a9049054013a1b77]*/ diff --git a/Objects/clinic/typeobject.c.h b/Objects/clinic/typeobject.c.h index 6feb5b1920fe20..1fa153598db213 100644 --- a/Objects/clinic/typeobject.c.h +++ b/Objects/clinic/typeobject.c.h @@ -2,11 +2,7 @@ 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 - +#include "pycore_modsupport.h" // _PyArg_BadArgument() PyDoc_STRVAR(type___instancecheck____doc__, "__instancecheck__($self, instance, /)\n" @@ -190,7 +186,7 @@ object___reduce_ex__(PyObject *self, PyObject *arg) PyObject *return_value = NULL; int protocol; - protocol = _PyLong_AsInt(arg); + protocol = PyLong_AsInt(arg); if (protocol == -1 && PyErr_Occurred()) { goto exit; } @@ -266,4 +262,4 @@ object___dir__(PyObject *self, PyObject *Py_UNUSED(ignored)) { return object___dir___impl(self); } -/*[clinic end generated code: output=43533e6981550e9e input=a9049054013a1b77]*/ +/*[clinic end generated code: output=b56c87f9cace1921 input=a9049054013a1b77]*/ diff --git a/Objects/clinic/typevarobject.c.h b/Objects/clinic/typevarobject.c.h index 54189b98446814..2bb0a98a2ed64c 100644 --- a/Objects/clinic/typevarobject.c.h +++ b/Objects/clinic/typevarobject.c.h @@ -3,13 +3,13 @@ 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() +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() #endif - +#include "pycore_modsupport.h" // _PyArg_UnpackKeywordsWithVararg() PyDoc_STRVAR(typevar_new__doc__, -"typevar(name, *constraints, *, bound=None, covariant=False,\n" +"typevar(name, *constraints, bound=None, covariant=False,\n" " contravariant=False, infer_variance=False)\n" "--\n" "\n" @@ -110,58 +110,12 @@ typevar_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) } PyDoc_STRVAR(typevar_typing_subst__doc__, -"__typing_subst__($self, /, arg)\n" +"__typing_subst__($self, arg, /)\n" "--\n" "\n"); #define TYPEVAR_TYPING_SUBST_METHODDEF \ - {"__typing_subst__", _PyCFunction_CAST(typevar_typing_subst), METH_FASTCALL|METH_KEYWORDS, typevar_typing_subst__doc__}, - -static PyObject * -typevar_typing_subst_impl(typevarobject *self, PyObject *arg); - -static PyObject * -typevar_typing_subst(typevarobject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(arg), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"arg", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "__typing_subst__", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; - PyObject *arg; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); - if (!args) { - goto exit; - } - arg = args[0]; - return_value = typevar_typing_subst_impl(self, arg); - -exit: - return return_value; -} + {"__typing_subst__", (PyCFunction)typevar_typing_subst, METH_O, typevar_typing_subst__doc__}, PyDoc_STRVAR(typevar_reduce__doc__, "__reduce__($self, /)\n" @@ -386,106 +340,33 @@ paramspec_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) } PyDoc_STRVAR(paramspec_typing_subst__doc__, -"__typing_subst__($self, /, arg)\n" +"__typing_subst__($self, arg, /)\n" "--\n" "\n"); #define PARAMSPEC_TYPING_SUBST_METHODDEF \ - {"__typing_subst__", _PyCFunction_CAST(paramspec_typing_subst), METH_FASTCALL|METH_KEYWORDS, paramspec_typing_subst__doc__}, - -static PyObject * -paramspec_typing_subst_impl(paramspecobject *self, PyObject *arg); - -static PyObject * -paramspec_typing_subst(paramspecobject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(arg), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"arg", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "__typing_subst__", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; - PyObject *arg; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); - if (!args) { - goto exit; - } - arg = args[0]; - return_value = paramspec_typing_subst_impl(self, arg); - -exit: - return return_value; -} + {"__typing_subst__", (PyCFunction)paramspec_typing_subst, METH_O, paramspec_typing_subst__doc__}, PyDoc_STRVAR(paramspec_typing_prepare_subst__doc__, -"__typing_prepare_subst__($self, /, alias, args)\n" +"__typing_prepare_subst__($self, alias, args, /)\n" "--\n" "\n"); #define PARAMSPEC_TYPING_PREPARE_SUBST_METHODDEF \ - {"__typing_prepare_subst__", _PyCFunction_CAST(paramspec_typing_prepare_subst), METH_FASTCALL|METH_KEYWORDS, paramspec_typing_prepare_subst__doc__}, + {"__typing_prepare_subst__", _PyCFunction_CAST(paramspec_typing_prepare_subst), METH_FASTCALL, paramspec_typing_prepare_subst__doc__}, static PyObject * paramspec_typing_prepare_subst_impl(paramspecobject *self, PyObject *alias, PyObject *args); static PyObject * -paramspec_typing_prepare_subst(paramspecobject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +paramspec_typing_prepare_subst(paramspecobject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 2 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(alias), &_Py_ID(args), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"alias", "args", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "__typing_prepare_subst__", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[2]; PyObject *alias; PyObject *__clinic_args; - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); - if (!args) { + if (!_PyArg_CheckPositional("__typing_prepare_subst__", nargs, 2, 2)) { goto exit; } alias = args[0]; @@ -572,106 +453,33 @@ typevartuple(PyTypeObject *type, PyObject *args, PyObject *kwargs) } PyDoc_STRVAR(typevartuple_typing_subst__doc__, -"__typing_subst__($self, /, arg)\n" +"__typing_subst__($self, arg, /)\n" "--\n" "\n"); #define TYPEVARTUPLE_TYPING_SUBST_METHODDEF \ - {"__typing_subst__", _PyCFunction_CAST(typevartuple_typing_subst), METH_FASTCALL|METH_KEYWORDS, typevartuple_typing_subst__doc__}, - -static PyObject * -typevartuple_typing_subst_impl(typevartupleobject *self, PyObject *arg); - -static PyObject * -typevartuple_typing_subst(typevartupleobject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(arg), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"arg", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "__typing_subst__", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; - PyObject *arg; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); - if (!args) { - goto exit; - } - arg = args[0]; - return_value = typevartuple_typing_subst_impl(self, arg); - -exit: - return return_value; -} + {"__typing_subst__", (PyCFunction)typevartuple_typing_subst, METH_O, typevartuple_typing_subst__doc__}, PyDoc_STRVAR(typevartuple_typing_prepare_subst__doc__, -"__typing_prepare_subst__($self, /, alias, args)\n" +"__typing_prepare_subst__($self, alias, args, /)\n" "--\n" "\n"); #define TYPEVARTUPLE_TYPING_PREPARE_SUBST_METHODDEF \ - {"__typing_prepare_subst__", _PyCFunction_CAST(typevartuple_typing_prepare_subst), METH_FASTCALL|METH_KEYWORDS, typevartuple_typing_prepare_subst__doc__}, + {"__typing_prepare_subst__", _PyCFunction_CAST(typevartuple_typing_prepare_subst), METH_FASTCALL, typevartuple_typing_prepare_subst__doc__}, static PyObject * typevartuple_typing_prepare_subst_impl(typevartupleobject *self, PyObject *alias, PyObject *args); static PyObject * -typevartuple_typing_prepare_subst(typevartupleobject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +typevartuple_typing_prepare_subst(typevartupleobject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 2 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(alias), &_Py_ID(args), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"alias", "args", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "__typing_prepare_subst__", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[2]; PyObject *alias; PyObject *__clinic_args; - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); - if (!args) { + if (!_PyArg_CheckPositional("__typing_prepare_subst__", nargs, 2, 2)) { goto exit; } alias = args[0]; @@ -783,4 +591,4 @@ typealias_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) exit: return return_value; } -/*[clinic end generated code: output=807bcd30ebd10ac3 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=5a582d9d89ad787b input=a9049054013a1b77]*/ diff --git a/Objects/clinic/unicodeobject.c.h b/Objects/clinic/unicodeobject.c.h index b9127e428f4c99..3e5167d9242fe4 100644 --- a/Objects/clinic/unicodeobject.c.h +++ b/Objects/clinic/unicodeobject.c.h @@ -3,10 +3,11 @@ 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() +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() #endif - +#include "pycore_abstract.h" // _PyNumber_Index() +#include "pycore_modsupport.h" // _PyArg_CheckPositional() PyDoc_STRVAR(EncodingMap_size__doc__, "size($self, /)\n" @@ -289,7 +290,7 @@ unicode_expandtabs(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyOb if (!noptargs) { goto skip_optional_pos; } - tabsize = _PyLong_AsInt(args[0]); + tabsize = PyLong_AsInt(args[0]); if (tabsize == -1 && PyErr_Occurred()) { goto exit; } @@ -950,12 +951,14 @@ PyDoc_STRVAR(unicode_split__doc__, " The separator used to split the string.\n" "\n" " When set to None (the default value), will split on any whitespace\n" -" character (including \\\\n \\\\r \\\\t \\\\f and spaces) and will discard\n" +" character (including \\n \\r \\t \\f and spaces) and will discard\n" " empty strings from the result.\n" " maxsplit\n" -" Maximum number of splits (starting from the left).\n" +" Maximum number of splits.\n" " -1 (the default value) means no limit.\n" "\n" +"Splitting starts at the front of the string and works to the end.\n" +"\n" "Note, str.split() is mainly useful for data that has been intentionally\n" "delimited. With natural text that includes punctuation, consider using\n" "the regular expression module."); @@ -1074,10 +1077,10 @@ PyDoc_STRVAR(unicode_rsplit__doc__, " The separator used to split the string.\n" "\n" " When set to None (the default value), will split on any whitespace\n" -" character (including \\\\n \\\\r \\\\t \\\\f and spaces) and will discard\n" +" character (including \\n \\r \\t \\f and spaces) and will discard\n" " empty strings from the result.\n" " maxsplit\n" -" Maximum number of splits (starting from the left).\n" +" Maximum number of splits.\n" " -1 (the default value) means no limit.\n" "\n" "Splitting starts at the end of the string and works to the front."); @@ -1504,4 +1507,4 @@ unicode_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) exit: return return_value; } -/*[clinic end generated code: output=ee76a1b49cd4cbb3 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=1aab29bab5201c78 input=a9049054013a1b77]*/ diff --git a/Objects/codeobject.c b/Objects/codeobject.c index 81fa33962e0101..dc46b773c26528 100644 --- a/Objects/codeobject.c +++ b/Objects/codeobject.c @@ -6,14 +6,13 @@ #include "pycore_code.h" // _PyCodeConstructor #include "pycore_frame.h" // FRAME_SPECIALS_SIZE #include "pycore_interp.h" // PyInterpreterState.co_extra_freefuncs -#include "pycore_opcode.h" // _PyOpcode_Deopt +#include "pycore_opcode_metadata.h" // _PyOpcode_Deopt, _PyOpcode_Caches +#include "pycore_opcode_utils.h" // RESUME_AT_FUNC_START #include "pycore_pystate.h" // _PyInterpreterState_GET() #include "pycore_setobject.h" // _PySet_NextEntry() #include "pycore_tuple.h" // _PyTuple_ITEMS() #include "clinic/codeobject.c.h" -static PyObject* code_repr(PyCodeObject *co); - static const char * code_event_name(PyCodeEvent event) { switch (event) { @@ -41,21 +40,9 @@ notify_code_watchers(PyCodeEvent event, PyCodeObject *co) // callback must be non-null if the watcher bit is set assert(cb != NULL); if (cb(event, co) < 0) { - // Don't risk resurrecting the object if an unraisablehook keeps - // a reference; pass a string as context. - PyObject *context = NULL; - PyObject *repr = code_repr(co); - if (repr) { - context = PyUnicode_FromFormat( - "%s watcher callback for %U", - code_event_name(event), repr); - Py_DECREF(repr); - } - if (context == NULL) { - context = Py_NewRef(Py_None); - } - PyErr_WriteUnraisable(context); - Py_DECREF(context); + PyErr_FormatUnraisable( + "Exception ignored in %s watcher callback for %R", + code_event_name(event), co); } } i++; @@ -395,6 +382,9 @@ init_code(PyCodeObject *co, struct _PyCodeConstructor *con) int nlocals, ncellvars, nfreevars; get_localsplus_counts(con->localsplusnames, con->localspluskinds, &nlocals, &ncellvars, &nfreevars); + if (con->stacksize == 0) { + con->stacksize = 1; + } co->co_filename = Py_NewRef(con->filename); co->co_name = Py_NewRef(con->name); @@ -424,9 +414,10 @@ init_code(PyCodeObject *co, struct _PyCodeConstructor *con) co->co_framesize = nlocalsplus + con->stacksize + FRAME_SPECIALS_SIZE; co->co_ncellvars = ncellvars; co->co_nfreevars = nfreevars; - co->co_version = _Py_next_func_version; - if (_Py_next_func_version != 0) { - _Py_next_func_version++; + PyInterpreterState *interp = _PyInterpreterState_GET(); + co->co_version = interp->next_func_version; + if (interp->next_func_version != 0) { + interp->next_func_version++; } co->_co_monitoring = NULL; co->_co_instrumentation_version = 0; @@ -652,6 +643,35 @@ PyUnstable_Code_NewWithPosOnlyArgs( _Py_set_localsplus_info(offset, name, CO_FAST_FREE, localsplusnames, localspluskinds); } + + // gh-110543: Make sure the CO_FAST_HIDDEN flag is set correctly. + if (!(flags & CO_OPTIMIZED)) { + Py_ssize_t code_len = PyBytes_GET_SIZE(code); + _Py_CODEUNIT *code_data = (_Py_CODEUNIT *)PyBytes_AS_STRING(code); + Py_ssize_t num_code_units = code_len / sizeof(_Py_CODEUNIT); + int extended_arg = 0; + for (int i = 0; i < num_code_units; i += 1 + _PyOpcode_Caches[code_data[i].op.code]) { + _Py_CODEUNIT *instr = &code_data[i]; + uint8_t opcode = instr->op.code; + if (opcode == EXTENDED_ARG) { + extended_arg = extended_arg << 8 | instr->op.arg; + continue; + } + if (opcode == LOAD_FAST_AND_CLEAR) { + int oparg = extended_arg << 8 | instr->op.arg; + if (oparg >= nlocalsplus) { + PyErr_Format(PyExc_ValueError, + "code: LOAD_FAST_AND_CLEAR oparg %d out of range", + oparg); + goto error; + } + _PyLocals_Kind kind = _PyLocals_GetKind(localspluskinds, oparg); + _PyLocals_SetKind(localspluskinds, oparg, kind | CO_FAST_HIDDEN); + } + extended_arg = 0; + } + } + // If any cells were args then nlocalsplus will have shrunk. if (nlocalsplus != PyTuple_GET_SIZE(localsplusnames)) { if (_PyTuple_Resize(&localsplusnames, nlocalsplus) < 0 @@ -729,7 +749,7 @@ PyUnstable_Code_New(int argcount, int kwonlyargcount, // test.test_code.CodeLocationTest.test_code_new_empty to keep it in sync! static const uint8_t assert0[6] = { - RESUME, 0, + RESUME, RESUME_AT_FUNC_START, LOAD_ASSERTION_ERROR, 0, RAISE_VARARGS, 1 }; @@ -1476,6 +1496,23 @@ clear_executors(PyCodeObject *co) co->co_executors = NULL; } +void +_PyCode_Clear_Executors(PyCodeObject *code) { + int code_len = (int)Py_SIZE(code); + for (int i = 0; i < code_len; i += _PyInstruction_GetLength(code, i)) { + _Py_CODEUNIT *instr = &_PyCode_CODE(code)[i]; + uint8_t opcode = instr->op.code; + uint8_t oparg = instr->op.arg; + if (opcode == ENTER_EXECUTOR) { + _PyExecutorObject *exec = code->co_executors->executors[oparg]; + assert(exec->vm_data.opcode != ENTER_EXECUTOR); + instr->op.code = exec->vm_data.opcode; + instr->op.arg = exec->vm_data.oparg; + } + } + clear_executors(code); +} + static void deopt_code(PyCodeObject *code, _Py_CODEUNIT *instructions) { @@ -1484,7 +1521,7 @@ deopt_code(PyCodeObject *code, _Py_CODEUNIT *instructions) int opcode = _Py_GetBaseOpcode(code, i); if (opcode == ENTER_EXECUTOR) { _PyExecutorObject *exec = code->co_executors->executors[instructions[i].op.arg]; - opcode = exec->vm_data.opcode; + opcode = _PyOpcode_Deopt[exec->vm_data.opcode]; instructions[i].op.arg = exec->vm_data.oparg; } assert(opcode != ENTER_EXECUTOR); @@ -1777,13 +1814,31 @@ code_richcompare(PyObject *self, PyObject *other, int op) for (int i = 0; i < Py_SIZE(co); i++) { _Py_CODEUNIT co_instr = _PyCode_CODE(co)[i]; _Py_CODEUNIT cp_instr = _PyCode_CODE(cp)[i]; - co_instr.op.code = _PyOpcode_Deopt[co_instr.op.code]; - cp_instr.op.code = _PyOpcode_Deopt[cp_instr.op.code]; - eq = co_instr.cache == cp_instr.cache; - if (!eq) { + uint8_t co_code = _Py_GetBaseOpcode(co, i); + uint8_t co_arg = co_instr.op.arg; + uint8_t cp_code = _Py_GetBaseOpcode(cp, i); + uint8_t cp_arg = cp_instr.op.arg; + + if (co_code == ENTER_EXECUTOR) { + const int exec_index = co_arg; + _PyExecutorObject *exec = co->co_executors->executors[exec_index]; + co_code = _PyOpcode_Deopt[exec->vm_data.opcode]; + co_arg = exec->vm_data.oparg; + } + assert(co_code != ENTER_EXECUTOR); + + if (cp_code == ENTER_EXECUTOR) { + const int exec_index = cp_arg; + _PyExecutorObject *exec = cp->co_executors->executors[exec_index]; + cp_code = _PyOpcode_Deopt[exec->vm_data.opcode]; + cp_arg = exec->vm_data.oparg; + } + assert(cp_code != ENTER_EXECUTOR); + + if (co_code != cp_code || co_arg != cp_arg) { goto unequal; } - i += _PyOpcode_Caches[co_instr.op.code]; + i += _PyOpcode_Caches[co_code]; } /* compare constants */ @@ -1862,10 +1917,22 @@ code_hash(PyCodeObject *co) SCRAMBLE_IN(co->co_firstlineno); SCRAMBLE_IN(Py_SIZE(co)); for (int i = 0; i < Py_SIZE(co); i++) { - int deop = _Py_GetBaseOpcode(co, i); - SCRAMBLE_IN(deop); - SCRAMBLE_IN(_PyCode_CODE(co)[i].op.arg); - i += _PyOpcode_Caches[deop]; + _Py_CODEUNIT co_instr = _PyCode_CODE(co)[i]; + uint8_t co_code = co_instr.op.code; + uint8_t co_arg = co_instr.op.arg; + if (co_code == ENTER_EXECUTOR) { + _PyExecutorObject *exec = co->co_executors->executors[co_arg]; + assert(exec != NULL); + assert(exec->vm_data.opcode != ENTER_EXECUTOR); + co_code = _PyOpcode_Deopt[exec->vm_data.opcode]; + co_arg = exec->vm_data.oparg; + } + else { + co_code = _Py_GetBaseOpcode(co, i); + } + SCRAMBLE_IN(co_code); + SCRAMBLE_IN(co_arg); + i += _PyOpcode_Caches[co_code]; } if ((Py_hash_t)uhash == -1) { return -2; @@ -1968,27 +2035,28 @@ code_linesiterator(PyCodeObject *code, PyObject *Py_UNUSED(args)) } /*[clinic input] +@text_signature "($self, /, **changes)" code.replace * - co_argcount: int(c_default="self->co_argcount") = -1 - co_posonlyargcount: int(c_default="self->co_posonlyargcount") = -1 - co_kwonlyargcount: int(c_default="self->co_kwonlyargcount") = -1 - co_nlocals: int(c_default="self->co_nlocals") = -1 - co_stacksize: int(c_default="self->co_stacksize") = -1 - co_flags: int(c_default="self->co_flags") = -1 - co_firstlineno: int(c_default="self->co_firstlineno") = -1 - co_code: PyBytesObject(c_default="NULL") = None - co_consts: object(subclass_of="&PyTuple_Type", c_default="self->co_consts") = None - co_names: object(subclass_of="&PyTuple_Type", c_default="self->co_names") = None - co_varnames: object(subclass_of="&PyTuple_Type", c_default="NULL") = None - co_freevars: object(subclass_of="&PyTuple_Type", c_default="NULL") = None - co_cellvars: object(subclass_of="&PyTuple_Type", c_default="NULL") = None - co_filename: unicode(c_default="self->co_filename") = None - co_name: unicode(c_default="self->co_name") = None - co_qualname: unicode(c_default="self->co_qualname") = None - co_linetable: PyBytesObject(c_default="(PyBytesObject *)self->co_linetable") = None - co_exceptiontable: PyBytesObject(c_default="(PyBytesObject *)self->co_exceptiontable") = None + co_argcount: int(c_default="self->co_argcount") = unchanged + co_posonlyargcount: int(c_default="self->co_posonlyargcount") = unchanged + co_kwonlyargcount: int(c_default="self->co_kwonlyargcount") = unchanged + co_nlocals: int(c_default="self->co_nlocals") = unchanged + co_stacksize: int(c_default="self->co_stacksize") = unchanged + co_flags: int(c_default="self->co_flags") = unchanged + co_firstlineno: int(c_default="self->co_firstlineno") = unchanged + co_code: object(subclass_of="&PyBytes_Type", c_default="NULL") = unchanged + co_consts: object(subclass_of="&PyTuple_Type", c_default="self->co_consts") = unchanged + co_names: object(subclass_of="&PyTuple_Type", c_default="self->co_names") = unchanged + co_varnames: object(subclass_of="&PyTuple_Type", c_default="NULL") = unchanged + co_freevars: object(subclass_of="&PyTuple_Type", c_default="NULL") = unchanged + co_cellvars: object(subclass_of="&PyTuple_Type", c_default="NULL") = unchanged + co_filename: unicode(c_default="self->co_filename") = unchanged + co_name: unicode(c_default="self->co_name") = unchanged + co_qualname: unicode(c_default="self->co_qualname") = unchanged + co_linetable: object(subclass_of="&PyBytes_Type", c_default="self->co_linetable") = unchanged + co_exceptiontable: object(subclass_of="&PyBytes_Type", c_default="self->co_exceptiontable") = unchanged Return a copy of the code object with new values for the specified fields. [clinic start generated code]*/ @@ -1997,14 +2065,13 @@ static PyObject * code_replace_impl(PyCodeObject *self, int co_argcount, int co_posonlyargcount, int co_kwonlyargcount, int co_nlocals, int co_stacksize, int co_flags, - int co_firstlineno, PyBytesObject *co_code, - PyObject *co_consts, PyObject *co_names, - PyObject *co_varnames, PyObject *co_freevars, - PyObject *co_cellvars, PyObject *co_filename, - PyObject *co_name, PyObject *co_qualname, - PyBytesObject *co_linetable, - PyBytesObject *co_exceptiontable) -/*[clinic end generated code: output=b6cd9988391d5711 input=f6f68e03571f8d7c]*/ + int co_firstlineno, PyObject *co_code, PyObject *co_consts, + PyObject *co_names, PyObject *co_varnames, + PyObject *co_freevars, PyObject *co_cellvars, + PyObject *co_filename, PyObject *co_name, + PyObject *co_qualname, PyObject *co_linetable, + PyObject *co_exceptiontable) +/*[clinic end generated code: output=e75c48a15def18b9 input=18e280e07846c122]*/ { #define CHECK_INT_ARG(ARG) \ if (ARG < 0) { \ @@ -2029,7 +2096,7 @@ code_replace_impl(PyCodeObject *self, int co_argcount, if (code == NULL) { return NULL; } - co_code = (PyBytesObject *)code; + co_code = code; } if (PySys_Audit("code.__new__", "OOOiiiiii", @@ -2068,10 +2135,10 @@ code_replace_impl(PyCodeObject *self, int co_argcount, co = PyCode_NewWithPosOnlyArgs( co_argcount, co_posonlyargcount, co_kwonlyargcount, co_nlocals, - co_stacksize, co_flags, (PyObject*)co_code, co_consts, co_names, + co_stacksize, co_flags, co_code, co_consts, co_names, co_varnames, co_freevars, co_cellvars, co_filename, co_name, co_qualname, co_firstlineno, - (PyObject*)co_linetable, (PyObject*)co_exceptiontable); + co_linetable, co_exceptiontable); error: Py_XDECREF(code); @@ -2110,6 +2177,7 @@ static struct PyMethodDef code_methods[] = { {"co_positions", (PyCFunction)code_positionsiterator, METH_NOARGS}, CODE_REPLACE_METHODDEF CODE__VARNAME_FROM_OPARG_METHODDEF + {"__replace__", _PyCFunction_CAST(code_replace), METH_FASTCALL|METH_KEYWORDS}, {NULL, NULL} /* sentinel */ }; diff --git a/Objects/descrobject.c b/Objects/descrobject.c index 60383dd06d1add..8d771adf307dc4 100644 --- a/Objects/descrobject.c +++ b/Objects/descrobject.c @@ -4,7 +4,9 @@ #include "pycore_abstract.h" // _PyObject_RealIsSubclass() #include "pycore_call.h" // _PyStack_AsDict() #include "pycore_ceval.h" // _Py_EnterRecursiveCallTstate() +#include "pycore_emscripten_trampoline.h" // descr_set_trampoline_call(), descr_get_trampoline_call() #include "pycore_descrobject.h" // _PyMethodWrapper_Type +#include "pycore_modsupport.h" // _PyArg_UnpackStack() #include "pycore_object.h" // _PyObject_GC_UNTRACK() #include "pycore_pystate.h" // _PyThreadState_GET() #include "pycore_tuple.h" // _PyTuple_ITEMS() @@ -16,28 +18,10 @@ class property "propertyobject *" "&PyProperty_Type" [clinic start generated code]*/ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=556352653fd4c02e]*/ -// see pycore_object.h -#if defined(__EMSCRIPTEN__) && defined(PY_CALL_TRAMPOLINE) -#include -EM_JS(int, descr_set_trampoline_call, (setter set, PyObject *obj, PyObject *value, void *closure), { - return wasmTable.get(set)(obj, value, closure); -}); - -EM_JS(PyObject*, descr_get_trampoline_call, (getter get, PyObject *obj, void *closure), { - return wasmTable.get(get)(obj, closure); -}); -#else -#define descr_set_trampoline_call(set, obj, value, closure) \ - (set)((obj), (value), (closure)) - -#define descr_get_trampoline_call(get, obj, closure) \ - (get)((obj), (closure)) - -#endif // __EMSCRIPTEN__ && PY_CALL_TRAMPOLINE - static void -descr_dealloc(PyDescrObject *descr) +descr_dealloc(PyObject *self) { + PyDescrObject *descr = (PyDescrObject *)self; _PyObject_GC_UNTRACK(descr); Py_XDECREF(descr->d_type); Py_XDECREF(descr->d_name); @@ -64,28 +48,28 @@ descr_repr(PyDescrObject *descr, const char *format) } static PyObject * -method_repr(PyMethodDescrObject *descr) +method_repr(PyObject *descr) { return descr_repr((PyDescrObject *)descr, ""); } static PyObject * -member_repr(PyMemberDescrObject *descr) +member_repr(PyObject *descr) { return descr_repr((PyDescrObject *)descr, ""); } static PyObject * -getset_repr(PyGetSetDescrObject *descr) +getset_repr(PyObject *descr) { return descr_repr((PyDescrObject *)descr, ""); } static PyObject * -wrapperdescr_repr(PyWrapperDescrObject *descr) +wrapperdescr_repr(PyObject *descr) { return descr_repr((PyDescrObject *)descr, ""); @@ -107,8 +91,9 @@ descr_check(PyDescrObject *descr, PyObject *obj) } static PyObject * -classmethod_get(PyMethodDescrObject *descr, PyObject *obj, PyObject *type) +classmethod_get(PyObject *self, PyObject *obj, PyObject *type) { + PyMethodDescrObject *descr = (PyMethodDescrObject *)self; /* Ensure a valid type. Class methods ignore obj. */ if (type == NULL) { if (obj != NULL) @@ -149,8 +134,9 @@ classmethod_get(PyMethodDescrObject *descr, PyObject *obj, PyObject *type) } static PyObject * -method_get(PyMethodDescrObject *descr, PyObject *obj, PyObject *type) +method_get(PyObject *self, PyObject *obj, PyObject *type) { + PyMethodDescrObject *descr = (PyMethodDescrObject *)self; if (obj == NULL) { return Py_NewRef(descr); } @@ -173,8 +159,9 @@ method_get(PyMethodDescrObject *descr, PyObject *obj, PyObject *type) } static PyObject * -member_get(PyMemberDescrObject *descr, PyObject *obj, PyObject *type) +member_get(PyObject *self, PyObject *obj, PyObject *type) { + PyMemberDescrObject *descr = (PyMemberDescrObject *)self; if (obj == NULL) { return Py_NewRef(descr); } @@ -193,8 +180,9 @@ member_get(PyMemberDescrObject *descr, PyObject *obj, PyObject *type) } static PyObject * -getset_get(PyGetSetDescrObject *descr, PyObject *obj, PyObject *type) +getset_get(PyObject *self, PyObject *obj, PyObject *type) { + PyGetSetDescrObject *descr = (PyGetSetDescrObject *)self; if (obj == NULL) { return Py_NewRef(descr); } @@ -212,8 +200,9 @@ getset_get(PyGetSetDescrObject *descr, PyObject *obj, PyObject *type) } static PyObject * -wrapperdescr_get(PyWrapperDescrObject *descr, PyObject *obj, PyObject *type) +wrapperdescr_get(PyObject *self, PyObject *obj, PyObject *type) { + PyWrapperDescrObject *descr = (PyWrapperDescrObject *)self; if (obj == NULL) { return Py_NewRef(descr); } @@ -240,8 +229,9 @@ descr_setcheck(PyDescrObject *descr, PyObject *obj, PyObject *value) } static int -member_set(PyMemberDescrObject *descr, PyObject *obj, PyObject *value) +member_set(PyObject *self, PyObject *obj, PyObject *value) { + PyMemberDescrObject *descr = (PyMemberDescrObject *)self; if (descr_setcheck((PyDescrObject *)descr, obj, value) < 0) { return -1; } @@ -249,8 +239,9 @@ member_set(PyMemberDescrObject *descr, PyObject *obj, PyObject *value) } static int -getset_set(PyGetSetDescrObject *descr, PyObject *obj, PyObject *value) +getset_set(PyObject *self, PyObject *obj, PyObject *value) { + PyGetSetDescrObject *descr = (PyGetSetDescrObject *)self; if (descr_setcheck((PyDescrObject *)descr, obj, value) < 0) { return -1; } @@ -496,9 +487,10 @@ method_vectorcall_O( we implement this simply by calling __get__ and then calling the result. */ static PyObject * -classmethoddescr_call(PyMethodDescrObject *descr, PyObject *args, +classmethoddescr_call(PyObject *_descr, PyObject *args, PyObject *kwds) { + PyMethodDescrObject *descr = (PyMethodDescrObject *)_descr; Py_ssize_t argc = PyTuple_GET_SIZE(args); if (argc < 1) { PyErr_Format(PyExc_TypeError, @@ -509,7 +501,7 @@ classmethoddescr_call(PyMethodDescrObject *descr, PyObject *args, return NULL; } PyObject *self = PyTuple_GET_ITEM(args, 0); - PyObject *bound = classmethod_get(descr, NULL, self); + PyObject *bound = classmethod_get((PyObject *)descr, NULL, self); if (bound == NULL) { return NULL; } @@ -540,8 +532,9 @@ wrapperdescr_raw_call(PyWrapperDescrObject *descr, PyObject *self, } static PyObject * -wrapperdescr_call(PyWrapperDescrObject *descr, PyObject *args, PyObject *kwds) +wrapperdescr_call(PyObject *_descr, PyObject *args, PyObject *kwds) { + PyWrapperDescrObject *descr = (PyWrapperDescrObject *)_descr; Py_ssize_t argc; PyObject *self, *result; @@ -580,15 +573,19 @@ wrapperdescr_call(PyWrapperDescrObject *descr, PyObject *args, PyObject *kwds) static PyObject * -method_get_doc(PyMethodDescrObject *descr, void *closure) +method_get_doc(PyObject *_descr, void *closure) { + PyMethodDescrObject *descr = (PyMethodDescrObject *)_descr; return _PyType_GetDocFromInternalDoc(descr->d_method->ml_name, descr->d_method->ml_doc); } static PyObject * -method_get_text_signature(PyMethodDescrObject *descr, void *closure) +method_get_text_signature(PyObject *_descr, void *closure) { - return _PyType_GetTextSignatureFromInternalDoc(descr->d_method->ml_name, descr->d_method->ml_doc); + PyMethodDescrObject *descr = (PyMethodDescrObject *)_descr; + return _PyType_GetTextSignatureFromInternalDoc(descr->d_method->ml_name, + descr->d_method->ml_doc, + descr->d_method->ml_flags); } static PyObject * @@ -620,22 +617,24 @@ calculate_qualname(PyDescrObject *descr) } static PyObject * -descr_get_qualname(PyDescrObject *descr, void *Py_UNUSED(ignored)) +descr_get_qualname(PyObject *self, void *Py_UNUSED(ignored)) { + PyDescrObject *descr = (PyDescrObject *)self; if (descr->d_qualname == NULL) descr->d_qualname = calculate_qualname(descr); return Py_XNewRef(descr->d_qualname); } static PyObject * -descr_reduce(PyDescrObject *descr, PyObject *Py_UNUSED(ignored)) +descr_reduce(PyObject *self, PyObject *Py_UNUSED(ignored)) { + PyDescrObject *descr = (PyDescrObject *)self; return Py_BuildValue("N(OO)", _PyEval_GetBuiltin(&_Py_ID(getattr)), PyDescr_TYPE(descr), PyDescr_NAME(descr)); } static PyMethodDef descr_methods[] = { - {"__reduce__", (PyCFunction)descr_reduce, METH_NOARGS, NULL}, + {"__reduce__", descr_reduce, METH_NOARGS, NULL}, {NULL, NULL} }; @@ -646,15 +645,16 @@ static PyMemberDef descr_members[] = { }; static PyGetSetDef method_getset[] = { - {"__doc__", (getter)method_get_doc}, - {"__qualname__", (getter)descr_get_qualname}, - {"__text_signature__", (getter)method_get_text_signature}, + {"__doc__", method_get_doc}, + {"__qualname__", descr_get_qualname}, + {"__text_signature__", method_get_text_signature}, {0} }; static PyObject * -member_get_doc(PyMemberDescrObject *descr, void *closure) +member_get_doc(PyObject *_descr, void *closure) { + PyMemberDescrObject *descr = (PyMemberDescrObject *)_descr; if (descr->d_member->doc == NULL) { Py_RETURN_NONE; } @@ -662,14 +662,15 @@ member_get_doc(PyMemberDescrObject *descr, void *closure) } static PyGetSetDef member_getset[] = { - {"__doc__", (getter)member_get_doc}, - {"__qualname__", (getter)descr_get_qualname}, + {"__doc__", member_get_doc}, + {"__qualname__", descr_get_qualname}, {0} }; static PyObject * -getset_get_doc(PyGetSetDescrObject *descr, void *closure) +getset_get_doc(PyObject *self, void *closure) { + PyGetSetDescrObject *descr = (PyGetSetDescrObject *)self; if (descr->d_getset->doc == NULL) { Py_RETURN_NONE; } @@ -677,27 +678,30 @@ getset_get_doc(PyGetSetDescrObject *descr, void *closure) } static PyGetSetDef getset_getset[] = { - {"__doc__", (getter)getset_get_doc}, - {"__qualname__", (getter)descr_get_qualname}, + {"__doc__", getset_get_doc}, + {"__qualname__", descr_get_qualname}, {0} }; static PyObject * -wrapperdescr_get_doc(PyWrapperDescrObject *descr, void *closure) +wrapperdescr_get_doc(PyObject *self, void *closure) { + PyWrapperDescrObject *descr = (PyWrapperDescrObject *)self; return _PyType_GetDocFromInternalDoc(descr->d_base->name, descr->d_base->doc); } static PyObject * -wrapperdescr_get_text_signature(PyWrapperDescrObject *descr, void *closure) +wrapperdescr_get_text_signature(PyObject *self, void *closure) { - return _PyType_GetTextSignatureFromInternalDoc(descr->d_base->name, descr->d_base->doc); + PyWrapperDescrObject *descr = (PyWrapperDescrObject *)self; + return _PyType_GetTextSignatureFromInternalDoc(descr->d_base->name, + descr->d_base->doc, 0); } static PyGetSetDef wrapperdescr_getset[] = { - {"__doc__", (getter)wrapperdescr_get_doc}, - {"__qualname__", (getter)descr_get_qualname}, - {"__text_signature__", (getter)wrapperdescr_get_text_signature}, + {"__doc__", wrapperdescr_get_doc}, + {"__qualname__", descr_get_qualname}, + {"__text_signature__", wrapperdescr_get_text_signature}, {0} }; @@ -714,12 +718,12 @@ PyTypeObject PyMethodDescr_Type = { "method_descriptor", sizeof(PyMethodDescrObject), 0, - (destructor)descr_dealloc, /* tp_dealloc */ + descr_dealloc, /* tp_dealloc */ offsetof(PyMethodDescrObject, vectorcall), /* tp_vectorcall_offset */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_as_async */ - (reprfunc)method_repr, /* tp_repr */ + method_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ @@ -744,7 +748,7 @@ PyTypeObject PyMethodDescr_Type = { method_getset, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ - (descrgetfunc)method_get, /* tp_descr_get */ + method_get, /* tp_descr_get */ 0, /* tp_descr_set */ }; @@ -754,17 +758,17 @@ PyTypeObject PyClassMethodDescr_Type = { "classmethod_descriptor", sizeof(PyMethodDescrObject), 0, - (destructor)descr_dealloc, /* tp_dealloc */ + descr_dealloc, /* tp_dealloc */ 0, /* tp_vectorcall_offset */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_as_async */ - (reprfunc)method_repr, /* tp_repr */ + method_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ - (ternaryfunc)classmethoddescr_call, /* tp_call */ + classmethoddescr_call, /* tp_call */ 0, /* tp_str */ PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ @@ -782,7 +786,7 @@ PyTypeObject PyClassMethodDescr_Type = { method_getset, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ - (descrgetfunc)classmethod_get, /* tp_descr_get */ + classmethod_get, /* tp_descr_get */ 0, /* tp_descr_set */ }; @@ -791,12 +795,12 @@ PyTypeObject PyMemberDescr_Type = { "member_descriptor", sizeof(PyMemberDescrObject), 0, - (destructor)descr_dealloc, /* tp_dealloc */ + descr_dealloc, /* tp_dealloc */ 0, /* tp_vectorcall_offset */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_as_async */ - (reprfunc)member_repr, /* tp_repr */ + member_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ @@ -819,8 +823,8 @@ PyTypeObject PyMemberDescr_Type = { member_getset, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ - (descrgetfunc)member_get, /* tp_descr_get */ - (descrsetfunc)member_set, /* tp_descr_set */ + member_get, /* tp_descr_get */ + member_set, /* tp_descr_set */ }; PyTypeObject PyGetSetDescr_Type = { @@ -828,12 +832,12 @@ PyTypeObject PyGetSetDescr_Type = { "getset_descriptor", sizeof(PyGetSetDescrObject), 0, - (destructor)descr_dealloc, /* tp_dealloc */ + descr_dealloc, /* tp_dealloc */ 0, /* tp_vectorcall_offset */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_as_async */ - (reprfunc)getset_repr, /* tp_repr */ + getset_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ @@ -856,8 +860,8 @@ PyTypeObject PyGetSetDescr_Type = { getset_getset, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ - (descrgetfunc)getset_get, /* tp_descr_get */ - (descrsetfunc)getset_set, /* tp_descr_set */ + getset_get, /* tp_descr_get */ + getset_set, /* tp_descr_set */ }; PyTypeObject PyWrapperDescr_Type = { @@ -865,17 +869,17 @@ PyTypeObject PyWrapperDescr_Type = { "wrapper_descriptor", sizeof(PyWrapperDescrObject), 0, - (destructor)descr_dealloc, /* tp_dealloc */ + descr_dealloc, /* tp_dealloc */ 0, /* tp_vectorcall_offset */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_as_async */ - (reprfunc)wrapperdescr_repr, /* tp_repr */ + wrapperdescr_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ - (ternaryfunc)wrapperdescr_call, /* tp_call */ + wrapperdescr_call, /* tp_call */ 0, /* tp_str */ PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ @@ -894,7 +898,7 @@ PyTypeObject PyWrapperDescr_Type = { wrapperdescr_getset, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ - (descrgetfunc)wrapperdescr_get, /* tp_descr_get */ + wrapperdescr_get, /* tp_descr_get */ 0, /* tp_descr_set */ }; @@ -1036,20 +1040,22 @@ typedef struct { } mappingproxyobject; static Py_ssize_t -mappingproxy_len(mappingproxyobject *pp) +mappingproxy_len(PyObject *self) { + mappingproxyobject *pp = (mappingproxyobject *)self; return PyObject_Size(pp->mapping); } static PyObject * -mappingproxy_getitem(mappingproxyobject *pp, PyObject *key) +mappingproxy_getitem(PyObject *self, PyObject *key) { + mappingproxyobject *pp = (mappingproxyobject *)self; return PyObject_GetItem(pp->mapping, key); } static PyMappingMethods mappingproxy_as_mapping = { - (lenfunc)mappingproxy_len, /* mp_length */ - (binaryfunc)mappingproxy_getitem, /* mp_subscript */ + mappingproxy_len, /* mp_length */ + mappingproxy_getitem, /* mp_subscript */ 0, /* mp_ass_subscript */ }; @@ -1078,8 +1084,9 @@ static PyNumberMethods mappingproxy_as_number = { }; static int -mappingproxy_contains(mappingproxyobject *pp, PyObject *key) +mappingproxy_contains(PyObject *self, PyObject *key) { + mappingproxyobject *pp = (mappingproxyobject *)self; if (PyDict_CheckExact(pp->mapping)) return PyDict_Contains(pp->mapping, key); else @@ -1094,14 +1101,15 @@ static PySequenceMethods mappingproxy_as_sequence = { 0, /* sq_slice */ 0, /* sq_ass_item */ 0, /* sq_ass_slice */ - (objobjproc)mappingproxy_contains, /* sq_contains */ + mappingproxy_contains, /* sq_contains */ 0, /* sq_inplace_concat */ 0, /* sq_inplace_repeat */ }; static PyObject * -mappingproxy_get(mappingproxyobject *pp, PyObject *const *args, Py_ssize_t nargs) +mappingproxy_get(PyObject *self, PyObject *const *args, Py_ssize_t nargs) { + mappingproxyobject *pp = (mappingproxyobject *)self; /* newargs: mapping, key, default=None */ PyObject *newargs[3]; newargs[0] = pp->mapping; @@ -1118,32 +1126,37 @@ mappingproxy_get(mappingproxyobject *pp, PyObject *const *args, Py_ssize_t nargs } static PyObject * -mappingproxy_keys(mappingproxyobject *pp, PyObject *Py_UNUSED(ignored)) +mappingproxy_keys(PyObject *self, PyObject *Py_UNUSED(ignored)) { + mappingproxyobject *pp = (mappingproxyobject *)self; return PyObject_CallMethodNoArgs(pp->mapping, &_Py_ID(keys)); } static PyObject * -mappingproxy_values(mappingproxyobject *pp, PyObject *Py_UNUSED(ignored)) +mappingproxy_values(PyObject *self, PyObject *Py_UNUSED(ignored)) { + mappingproxyobject *pp = (mappingproxyobject *)self; return PyObject_CallMethodNoArgs(pp->mapping, &_Py_ID(values)); } static PyObject * -mappingproxy_items(mappingproxyobject *pp, PyObject *Py_UNUSED(ignored)) +mappingproxy_items(PyObject *self, PyObject *Py_UNUSED(ignored)) { + mappingproxyobject *pp = (mappingproxyobject *)self; return PyObject_CallMethodNoArgs(pp->mapping, &_Py_ID(items)); } static PyObject * -mappingproxy_copy(mappingproxyobject *pp, PyObject *Py_UNUSED(ignored)) +mappingproxy_copy(PyObject *self, PyObject *Py_UNUSED(ignored)) { + mappingproxyobject *pp = (mappingproxyobject *)self; return PyObject_CallMethodNoArgs(pp->mapping, &_Py_ID(copy)); } static PyObject * -mappingproxy_reversed(mappingproxyobject *pp, PyObject *Py_UNUSED(ignored)) +mappingproxy_reversed(PyObject *self, PyObject *Py_UNUSED(ignored)) { + mappingproxyobject *pp = (mappingproxyobject *)self; return PyObject_CallMethodNoArgs(pp->mapping, &_Py_ID(__reversed__)); } @@ -1154,50 +1167,55 @@ static PyMethodDef mappingproxy_methods[] = { {"get", _PyCFunction_CAST(mappingproxy_get), METH_FASTCALL, PyDoc_STR("D.get(k[,d]) -> D[k] if k in D, else d." " d defaults to None.")}, - {"keys", (PyCFunction)mappingproxy_keys, METH_NOARGS, + {"keys", mappingproxy_keys, METH_NOARGS, PyDoc_STR("D.keys() -> a set-like object providing a view on D's keys")}, - {"values", (PyCFunction)mappingproxy_values, METH_NOARGS, + {"values", mappingproxy_values, METH_NOARGS, PyDoc_STR("D.values() -> an object providing a view on D's values")}, - {"items", (PyCFunction)mappingproxy_items, METH_NOARGS, + {"items", mappingproxy_items, METH_NOARGS, PyDoc_STR("D.items() -> a set-like object providing a view on D's items")}, - {"copy", (PyCFunction)mappingproxy_copy, METH_NOARGS, + {"copy", mappingproxy_copy, METH_NOARGS, PyDoc_STR("D.copy() -> a shallow copy of D")}, {"__class_getitem__", Py_GenericAlias, METH_O|METH_CLASS, PyDoc_STR("See PEP 585")}, - {"__reversed__", (PyCFunction)mappingproxy_reversed, METH_NOARGS, + {"__reversed__", mappingproxy_reversed, METH_NOARGS, PyDoc_STR("D.__reversed__() -> reverse iterator")}, {0} }; static void -mappingproxy_dealloc(mappingproxyobject *pp) +mappingproxy_dealloc(PyObject *self) { + mappingproxyobject *pp = (mappingproxyobject *)self; _PyObject_GC_UNTRACK(pp); Py_DECREF(pp->mapping); PyObject_GC_Del(pp); } static PyObject * -mappingproxy_getiter(mappingproxyobject *pp) +mappingproxy_getiter(PyObject *self) { + mappingproxyobject *pp = (mappingproxyobject *)self; return PyObject_GetIter(pp->mapping); } static Py_hash_t -mappingproxy_hash(mappingproxyobject *pp) +mappingproxy_hash(PyObject *self) { + mappingproxyobject *pp = (mappingproxyobject *)self; return PyObject_Hash(pp->mapping); } static PyObject * -mappingproxy_str(mappingproxyobject *pp) +mappingproxy_str(PyObject *self) { + mappingproxyobject *pp = (mappingproxyobject *)self; return PyObject_Str(pp->mapping); } static PyObject * -mappingproxy_repr(mappingproxyobject *pp) +mappingproxy_repr(PyObject *self) { + mappingproxyobject *pp = (mappingproxyobject *)self; return PyUnicode_FromFormat("mappingproxy(%R)", pp->mapping); } @@ -1210,8 +1228,9 @@ mappingproxy_traverse(PyObject *self, visitproc visit, void *arg) } static PyObject * -mappingproxy_richcompare(mappingproxyobject *v, PyObject *w, int op) +mappingproxy_richcompare(PyObject *self, PyObject *w, int op) { + mappingproxyobject *v = (mappingproxyobject *)self; return PyObject_RichCompare(v->mapping, w, op); } @@ -1285,8 +1304,9 @@ typedef struct { #define Wrapper_Check(v) Py_IS_TYPE(v, &_PyMethodWrapper_Type) static void -wrapper_dealloc(wrapperobject *wp) +wrapper_dealloc(PyObject *self) { + wrapperobject *wp = (wrapperobject *)self; PyObject_GC_UnTrack(wp); Py_TRASHCAN_BEGIN(wp, wrapper_dealloc) Py_XDECREF(wp->descr); @@ -1322,8 +1342,9 @@ wrapper_richcompare(PyObject *a, PyObject *b, int op) } static Py_hash_t -wrapper_hash(wrapperobject *wp) +wrapper_hash(PyObject *self) { + wrapperobject *wp = (wrapperobject *)self; Py_hash_t x, y; x = _Py_HashPointer(wp->self); y = _Py_HashPointer(wp->descr); @@ -1334,8 +1355,9 @@ wrapper_hash(wrapperobject *wp) } static PyObject * -wrapper_repr(wrapperobject *wp) +wrapper_repr(PyObject *self) { + wrapperobject *wp = (wrapperobject *)self; return PyUnicode_FromFormat("", wp->descr->d_base->name, Py_TYPE(wp->self)->tp_name, @@ -1343,14 +1365,15 @@ wrapper_repr(wrapperobject *wp) } static PyObject * -wrapper_reduce(wrapperobject *wp, PyObject *Py_UNUSED(ignored)) +wrapper_reduce(PyObject *self, PyObject *Py_UNUSED(ignored)) { + wrapperobject *wp = (wrapperobject *)self; return Py_BuildValue("N(OO)", _PyEval_GetBuiltin(&_Py_ID(getattr)), wp->self, PyDescr_NAME(wp->descr)); } static PyMethodDef wrapper_methods[] = { - {"__reduce__", (PyCFunction)wrapper_reduce, METH_NOARGS, NULL}, + {"__reduce__", wrapper_reduce, METH_NOARGS, NULL}, {NULL, NULL} }; @@ -1360,51 +1383,56 @@ static PyMemberDef wrapper_members[] = { }; static PyObject * -wrapper_objclass(wrapperobject *wp, void *Py_UNUSED(ignored)) +wrapper_objclass(PyObject *wp, void *Py_UNUSED(ignored)) { - PyObject *c = (PyObject *)PyDescr_TYPE(wp->descr); + PyObject *c = (PyObject *)PyDescr_TYPE(((wrapperobject *)wp)->descr); return Py_NewRef(c); } static PyObject * -wrapper_name(wrapperobject *wp, void *Py_UNUSED(ignored)) +wrapper_name(PyObject *wp, void *Py_UNUSED(ignored)) { - const char *s = wp->descr->d_base->name; + const char *s = ((wrapperobject *)wp)->descr->d_base->name; return PyUnicode_FromString(s); } static PyObject * -wrapper_doc(wrapperobject *wp, void *Py_UNUSED(ignored)) +wrapper_doc(PyObject *self, void *Py_UNUSED(ignored)) { + wrapperobject *wp = (wrapperobject *)self; return _PyType_GetDocFromInternalDoc(wp->descr->d_base->name, wp->descr->d_base->doc); } static PyObject * -wrapper_text_signature(wrapperobject *wp, void *Py_UNUSED(ignored)) +wrapper_text_signature(PyObject *self, void *Py_UNUSED(ignored)) { - return _PyType_GetTextSignatureFromInternalDoc(wp->descr->d_base->name, wp->descr->d_base->doc); + wrapperobject *wp = (wrapperobject *)self; + return _PyType_GetTextSignatureFromInternalDoc(wp->descr->d_base->name, + wp->descr->d_base->doc, 0); } static PyObject * -wrapper_qualname(wrapperobject *wp, void *Py_UNUSED(ignored)) +wrapper_qualname(PyObject *self, void *Py_UNUSED(ignored)) { - return descr_get_qualname((PyDescrObject *)wp->descr, NULL); + wrapperobject *wp = (wrapperobject *)self; + return descr_get_qualname((PyObject *)wp->descr, NULL); } static PyGetSetDef wrapper_getsets[] = { - {"__objclass__", (getter)wrapper_objclass}, - {"__name__", (getter)wrapper_name}, - {"__qualname__", (getter)wrapper_qualname}, - {"__doc__", (getter)wrapper_doc}, - {"__text_signature__", (getter)wrapper_text_signature}, + {"__objclass__", wrapper_objclass}, + {"__name__", wrapper_name}, + {"__qualname__", wrapper_qualname}, + {"__doc__", wrapper_doc}, + {"__text_signature__", wrapper_text_signature}, {0} }; static PyObject * -wrapper_call(wrapperobject *wp, PyObject *args, PyObject *kwds) +wrapper_call(PyObject *self, PyObject *args, PyObject *kwds) { + wrapperobject *wp = (wrapperobject *)self; return wrapperdescr_raw_call(wp->descr, wp->self, args, kwds); } @@ -1423,17 +1451,17 @@ PyTypeObject _PyMethodWrapper_Type = { sizeof(wrapperobject), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ - (destructor)wrapper_dealloc, /* tp_dealloc */ + wrapper_dealloc, /* tp_dealloc */ 0, /* tp_vectorcall_offset */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_as_async */ - (reprfunc)wrapper_repr, /* tp_repr */ + wrapper_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ - (hashfunc)wrapper_hash, /* tp_hash */ - (ternaryfunc)wrapper_call, /* tp_call */ + wrapper_hash, /* tp_hash */ + wrapper_call, /* tp_call */ 0, /* tp_str */ PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ @@ -1554,6 +1582,9 @@ property_deleter(PyObject *self, PyObject *deleter) PyDoc_STRVAR(set_name_doc, + "__set_name__($self, owner, name, /)\n" + "--\n" + "\n" "Method to set name of a property."); static PyObject * @@ -1920,18 +1951,18 @@ PyTypeObject PyDictProxy_Type = { sizeof(mappingproxyobject), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ - (destructor)mappingproxy_dealloc, /* tp_dealloc */ + mappingproxy_dealloc, /* tp_dealloc */ 0, /* tp_vectorcall_offset */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_as_async */ - (reprfunc)mappingproxy_repr, /* tp_repr */ + mappingproxy_repr, /* tp_repr */ &mappingproxy_as_number, /* tp_as_number */ &mappingproxy_as_sequence, /* tp_as_sequence */ &mappingproxy_as_mapping, /* tp_as_mapping */ - (hashfunc)mappingproxy_hash, /* tp_hash */ + mappingproxy_hash, /* tp_hash */ 0, /* tp_call */ - (reprfunc)mappingproxy_str, /* tp_str */ + mappingproxy_str, /* tp_str */ PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ @@ -1940,9 +1971,9 @@ PyTypeObject PyDictProxy_Type = { 0, /* tp_doc */ mappingproxy_traverse, /* tp_traverse */ 0, /* tp_clear */ - (richcmpfunc)mappingproxy_richcompare, /* tp_richcompare */ + mappingproxy_richcompare, /* tp_richcompare */ 0, /* tp_weaklistoffset */ - (getiterfunc)mappingproxy_getiter, /* tp_iter */ + mappingproxy_getiter, /* tp_iter */ 0, /* tp_iternext */ mappingproxy_methods, /* tp_methods */ 0, /* tp_members */ @@ -1982,7 +2013,7 @@ PyTypeObject PyProperty_Type = { Py_TPFLAGS_BASETYPE, /* tp_flags */ property_init__doc__, /* tp_doc */ property_traverse, /* tp_traverse */ - (inquiry)property_clear, /* tp_clear */ + property_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ diff --git a/Objects/dictobject.c b/Objects/dictobject.c index 41ae1fca90b468..2482a918ba983b 100644 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -115,8 +115,9 @@ As a consequence of this, split keys have a maximum size of 16. #include "Python.h" #include "pycore_bitutils.h" // _Py_bit_length #include "pycore_call.h" // _PyObject_CallNoArgs() +#include "pycore_ceval.h" // _PyEval_GetBuiltin() #include "pycore_code.h" // stats -#include "pycore_dict.h" // PyDictKeysObject +#include "pycore_dict.h" // export _PyDict_SizeOf() #include "pycore_gc.h" // _PyObject_GC_IS_TRACKED() #include "pycore_object.h" // _PyObject_GC_TRACK(), _PyDebugAllocatorStats() #include "pycore_pyerrors.h" // _PyErr_GetRaisedException() @@ -236,7 +237,7 @@ equally good collision statistics, needed less code & used less memory. static int dictresize(PyInterpreterState *interp, PyDictObject *mp, uint8_t log_newsize, int unicode); -static PyObject* dict_iter(PyDictObject *dict); +static PyObject* dict_iter(PyObject *dict); #include "clinic/dictobject.c.h" @@ -791,7 +792,7 @@ static PyDictKeysObject * clone_combined_dict_keys(PyDictObject *orig) { assert(PyDict_Check(orig)); - assert(Py_TYPE(orig)->tp_iter == (getiterfunc)dict_iter); + assert(Py_TYPE(orig)->tp_iter == dict_iter); assert(orig->ma_values == NULL); assert(orig->ma_keys != Py_EMPTY_KEYS); assert(orig->ma_keys->dk_refcnt == 1); @@ -1662,8 +1663,8 @@ _PyDict_FromItems(PyObject *const *keys, Py_ssize_t keys_offset, * function hits a stack-depth error, which can cause this to return NULL * even if the key is present. */ -PyObject * -PyDict_GetItem(PyObject *op, PyObject *key) +static PyObject * +dict_getitem(PyObject *op, PyObject *key, const char *warnmsg) { if (!PyDict_Check(op)) { return NULL; @@ -1674,7 +1675,7 @@ PyDict_GetItem(PyObject *op, PyObject *key) if (!PyUnicode_CheckExact(key) || (hash = unicode_get_hash(key)) == -1) { hash = PyObject_Hash(key); if (hash == -1) { - PyErr_Clear(); + PyErr_FormatUnraisable(warnmsg); return NULL; } } @@ -1695,12 +1696,24 @@ PyDict_GetItem(PyObject *op, PyObject *key) ix = _Py_dict_lookup(mp, key, hash, &value); /* Ignore any exception raised by the lookup */ + PyObject *exc2 = _PyErr_Occurred(tstate); + if (exc2 && !PyErr_GivenExceptionMatches(exc2, PyExc_KeyError)) { + PyErr_FormatUnraisable(warnmsg); + } _PyErr_SetRaisedException(tstate, exc); assert(ix >= 0 || value == NULL); return value; // borrowed reference } +PyObject * +PyDict_GetItem(PyObject *op, PyObject *key) +{ + return dict_getitem(op, key, + "Exception ignored in PyDict_GetItem(); consider using " + "PyDict_GetItemRef() or PyDict_GetItemWithError()"); +} + Py_ssize_t _PyDict_LookupIndex(PyDictObject *mp, PyObject *key) { @@ -1839,9 +1852,10 @@ _PyDict_GetItemStringWithError(PyObject *v, const char *key) } rv = PyDict_GetItemWithError(v, kv); Py_DECREF(kv); - return rv; // borrowed reference + return rv; } + /* Fast version of global value lookup (LOAD_GLOBAL). * Lookup in globals, then builtins. * @@ -2226,64 +2240,119 @@ PyDict_Next(PyObject *op, Py_ssize_t *ppos, PyObject **pkey, PyObject **pvalue) return _PyDict_Next(op, ppos, pkey, pvalue, NULL); } + /* Internal version of dict.pop(). */ -PyObject * -_PyDict_Pop_KnownHash(PyObject *dict, PyObject *key, Py_hash_t hash, PyObject *deflt) +int +_PyDict_Pop_KnownHash(PyDictObject *mp, PyObject *key, Py_hash_t hash, + PyObject **result) { - Py_ssize_t ix; - PyObject *old_value; - PyDictObject *mp; - PyInterpreterState *interp = _PyInterpreterState_GET(); - - assert(PyDict_Check(dict)); - mp = (PyDictObject *)dict; + assert(PyDict_Check(mp)); if (mp->ma_used == 0) { - if (deflt) { - return Py_NewRef(deflt); + if (result) { + *result = NULL; } - _PyErr_SetKeyError(key); - return NULL; + return 0; } - ix = _Py_dict_lookup(mp, key, hash, &old_value); - if (ix == DKIX_ERROR) - return NULL; + + PyObject *old_value; + Py_ssize_t ix = _Py_dict_lookup(mp, key, hash, &old_value); + if (ix == DKIX_ERROR) { + if (result) { + *result = NULL; + } + return -1; + } + if (ix == DKIX_EMPTY || old_value == NULL) { - if (deflt) { - return Py_NewRef(deflt); + if (result) { + *result = NULL; } - _PyErr_SetKeyError(key); - return NULL; + return 0; } + assert(old_value != NULL); + PyInterpreterState *interp = _PyInterpreterState_GET(); uint64_t new_version = _PyDict_NotifyEvent( interp, PyDict_EVENT_DELETED, mp, key, NULL); delitem_common(mp, hash, ix, Py_NewRef(old_value), new_version); ASSERT_CONSISTENT(mp); - return old_value; + if (result) { + *result = old_value; + } + else { + Py_DECREF(old_value); + } + return 1; } -PyObject * -_PyDict_Pop(PyObject *dict, PyObject *key, PyObject *deflt) + +int +PyDict_Pop(PyObject *op, PyObject *key, PyObject **result) { - Py_hash_t hash; + if (!PyDict_Check(op)) { + if (result) { + *result = NULL; + } + PyErr_BadInternalCall(); + return -1; + } + PyDictObject *dict = (PyDictObject *)op; - if (((PyDictObject *)dict)->ma_used == 0) { - if (deflt) { - return Py_NewRef(deflt); + if (dict->ma_used == 0) { + if (result) { + *result = NULL; } - _PyErr_SetKeyError(key); - return NULL; + return 0; } + + Py_hash_t hash; if (!PyUnicode_CheckExact(key) || (hash = unicode_get_hash(key)) == -1) { hash = PyObject_Hash(key); - if (hash == -1) - return NULL; + if (hash == -1) { + if (result) { + *result = NULL; + } + return -1; + } + } + return _PyDict_Pop_KnownHash(dict, key, hash, result); +} + + +int +PyDict_PopString(PyObject *op, const char *key, PyObject **result) +{ + PyObject *key_obj = PyUnicode_FromString(key); + if (key_obj == NULL) { + if (result != NULL) { + *result = NULL; + } + return -1; + } + + int res = PyDict_Pop(op, key_obj, result); + Py_DECREF(key_obj); + return res; +} + + +PyObject * +_PyDict_Pop(PyObject *dict, PyObject *key, PyObject *default_value) +{ + PyObject *result; + if (PyDict_Pop(dict, key, &result) == 0) { + if (default_value != NULL) { + return Py_NewRef(default_value); + } + _PyErr_SetKeyError(key); + return NULL; } - return _PyDict_Pop_KnownHash(dict, key, hash, deflt); + return result; } + /* Internal version of dict.from_keys(). It is subclass-friendly. */ PyObject * _PyDict_FromKeys(PyObject *cls, PyObject *iterable, PyObject *value) @@ -2381,8 +2450,9 @@ _PyDict_FromKeys(PyObject *cls, PyObject *iterable, PyObject *value) /* Methods */ static void -dict_dealloc(PyDictObject *mp) +dict_dealloc(PyObject *self) { + PyDictObject *mp = (PyDictObject *)self; PyInterpreterState *interp = _PyInterpreterState_GET(); assert(Py_REFCNT(mp) == 0); Py_SET_REFCNT(mp, 1); @@ -2430,8 +2500,9 @@ dict_dealloc(PyDictObject *mp) static PyObject * -dict_repr(PyDictObject *mp) +dict_repr(PyObject *self) { + PyDictObject *mp = (PyDictObject *)self; Py_ssize_t i; PyObject *key = NULL, *value = NULL; _PyUnicodeWriter writer; @@ -2513,14 +2584,16 @@ dict_repr(PyDictObject *mp) } static Py_ssize_t -dict_length(PyDictObject *mp) +dict_length(PyObject *self) { + PyDictObject *mp = (PyDictObject *)self; return mp->ma_used; } static PyObject * -dict_subscript(PyDictObject *mp, PyObject *key) +dict_subscript(PyObject *self, PyObject *key) { + PyDictObject *mp = (PyDictObject *)self; Py_ssize_t ix; Py_hash_t hash; PyObject *value; @@ -2554,18 +2627,18 @@ dict_subscript(PyDictObject *mp, PyObject *key) } static int -dict_ass_sub(PyDictObject *mp, PyObject *v, PyObject *w) +dict_ass_sub(PyObject *mp, PyObject *v, PyObject *w) { if (w == NULL) - return PyDict_DelItem((PyObject *)mp, v); + return PyDict_DelItem(mp, v); else - return PyDict_SetItem((PyObject *)mp, v, w); + return PyDict_SetItem(mp, v, w); } static PyMappingMethods dict_as_mapping = { - (lenfunc)dict_length, /*mp_length*/ - (binaryfunc)dict_subscript, /*mp_subscript*/ - (objobjargproc)dict_ass_sub, /*mp_ass_subscript*/ + dict_length, /*mp_length*/ + dict_subscript, /*mp_subscript*/ + dict_ass_sub, /*mp_ass_subscript*/ }; static PyObject * @@ -2700,12 +2773,11 @@ dict_update_arg(PyObject *self, PyObject *arg) if (PyDict_CheckExact(arg)) { return PyDict_Merge(self, arg, 1); } - PyObject *func; - if (PyObject_GetOptionalAttr(arg, &_Py_ID(keys), &func) < 0) { + int has_keys = PyObject_HasAttrWithError(arg, &_Py_ID(keys)); + if (has_keys < 0) { return -1; } - if (func != NULL) { - Py_DECREF(func); + if (has_keys) { return PyDict_Merge(self, arg, 1); } return PyDict_MergeFromSeq2(self, arg, 1); @@ -2857,7 +2929,7 @@ dict_merge(PyInterpreterState *interp, PyObject *a, PyObject *b, int override) return -1; } mp = (PyDictObject*)a; - if (PyDict_Check(b) && (Py_TYPE(b)->tp_iter == (getiterfunc)dict_iter)) { + if (PyDict_Check(b) && (Py_TYPE(b)->tp_iter == dict_iter)) { other = (PyDictObject*)b; if (other == mp || other->ma_used == 0) /* a.update(a) or a.update({}); nothing to do */ @@ -3037,9 +3109,9 @@ _PyDict_MergeEx(PyObject *a, PyObject *b, int override) } static PyObject * -dict_copy(PyDictObject *mp, PyObject *Py_UNUSED(ignored)) +dict_copy(PyObject *mp, PyObject *Py_UNUSED(ignored)) { - return PyDict_Copy((PyObject*)mp); + return PyDict_Copy(mp); } PyObject * @@ -3087,7 +3159,7 @@ PyDict_Copy(PyObject *o) return (PyObject *)split_copy; } - if (Py_TYPE(mp)->tp_iter == (getiterfunc)dict_iter && + if (Py_TYPE(mp)->tp_iter == dict_iter && mp->ma_values == NULL && (mp->ma_used >= (mp->ma_keys->dk_nentries * 2) / 3)) { @@ -3441,9 +3513,9 @@ dict_setdefault_impl(PyDictObject *self, PyObject *key, } static PyObject * -dict_clear(PyDictObject *mp, PyObject *Py_UNUSED(ignored)) +dict_clear(PyObject *mp, PyObject *Py_UNUSED(ignored)) { - PyDict_Clear((PyObject *)mp); + PyDict_Clear(mp); Py_RETURN_NONE; } @@ -3632,8 +3704,9 @@ _PyDict_KeysSize(PyDictKeysObject *keys) } static PyObject * -dict_sizeof(PyDictObject *mp, PyObject *Py_UNUSED(ignored)) +dict_sizeof(PyObject *self, PyObject *Py_UNUSED(ignored)) { + PyDictObject *mp = (PyDictObject *)self; return PyLong_FromSsize_t(_PyDict_SizeOf(mp)); } @@ -3695,9 +3768,9 @@ PyDoc_STRVAR(values__doc__, static PyMethodDef mapp_methods[] = { DICT___CONTAINS___METHODDEF - {"__getitem__", _PyCFunction_CAST(dict_subscript), METH_O | METH_COEXIST, + {"__getitem__", dict_subscript, METH_O | METH_COEXIST, getitem__doc__}, - {"__sizeof__", _PyCFunction_CAST(dict_sizeof), METH_NOARGS, + {"__sizeof__", dict_sizeof, METH_NOARGS, sizeof__doc__}, DICT_GET_METHODDEF DICT_SETDEFAULT_METHODDEF @@ -3712,9 +3785,9 @@ static PyMethodDef mapp_methods[] = { {"update", _PyCFunction_CAST(dict_update), METH_VARARGS | METH_KEYWORDS, update__doc__}, DICT_FROMKEYS_METHODDEF - {"clear", (PyCFunction)dict_clear, METH_NOARGS, + {"clear", dict_clear, METH_NOARGS, clear__doc__}, - {"copy", (PyCFunction)dict_copy, METH_NOARGS, + {"copy", dict_copy, METH_NOARGS, copy__doc__}, DICT___REVERSED___METHODDEF {"__class_getitem__", Py_GenericAlias, METH_O|METH_CLASS, PyDoc_STR("See PEP 585")}, @@ -3741,6 +3814,18 @@ PyDict_Contains(PyObject *op, PyObject *key) return (ix != DKIX_EMPTY && value != NULL); } +int +PyDict_ContainsString(PyObject *op, const char *key) +{ + PyObject *key_obj = PyUnicode_FromString(key); + if (key_obj == NULL) { + return -1; + } + int res = PyDict_Contains(op, key_obj); + Py_DECREF(key_obj); + return res; +} + /* Internal version of PyDict_Contains used when the hash value is already known */ int _PyDict_Contains_KnownHash(PyObject *op, PyObject *key, Py_hash_t hash) @@ -3857,8 +3942,9 @@ dict_vectorcall(PyObject *type, PyObject * const*args, } static PyObject * -dict_iter(PyDictObject *dict) +dict_iter(PyObject *self) { + PyDictObject *dict = (PyDictObject *)self; return dictiter_new(dict, &PyDictIterKey_Type); } @@ -3878,12 +3964,12 @@ PyTypeObject PyDict_Type = { "dict", sizeof(PyDictObject), 0, - (destructor)dict_dealloc, /* tp_dealloc */ + dict_dealloc, /* tp_dealloc */ 0, /* tp_vectorcall_offset */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_as_async */ - (reprfunc)dict_repr, /* tp_repr */ + dict_repr, /* tp_repr */ &dict_as_number, /* tp_as_number */ &dict_as_sequence, /* tp_as_sequence */ &dict_as_mapping, /* tp_as_mapping */ @@ -3901,7 +3987,7 @@ PyTypeObject PyDict_Type = { dict_tp_clear, /* tp_clear */ dict_richcompare, /* tp_richcompare */ 0, /* tp_weaklistoffset */ - (getiterfunc)dict_iter, /* tp_iter */ + dict_iter, /* tp_iter */ 0, /* tp_iternext */ mapp_methods, /* tp_methods */ 0, /* tp_members */ @@ -3926,10 +4012,14 @@ PyDict_GetItemString(PyObject *v, const char *key) PyObject *kv, *rv; kv = PyUnicode_FromString(key); if (kv == NULL) { - PyErr_Clear(); + PyErr_FormatUnraisable( + "Exception ignored in PyDict_GetItemString(); consider using " + "PyDict_GetItemRefString()"); return NULL; } - rv = PyDict_GetItem(v, kv); + rv = dict_getitem(v, kv, + "Exception ignored in PyDict_GetItemString(); consider using " + "PyDict_GetItemRefString()"); Py_DECREF(kv); return rv; // borrowed reference } @@ -4044,8 +4134,9 @@ dictiter_new(PyDictObject *dict, PyTypeObject *itertype) } static void -dictiter_dealloc(dictiterobject *di) +dictiter_dealloc(PyObject *self) { + dictiterobject *di = (dictiterobject *)self; /* bpo-31095: UnTrack is needed before calling any callbacks */ _PyObject_GC_UNTRACK(di); Py_XDECREF(di->di_dict); @@ -4054,16 +4145,18 @@ dictiter_dealloc(dictiterobject *di) } static int -dictiter_traverse(dictiterobject *di, visitproc visit, void *arg) +dictiter_traverse(PyObject *self, visitproc visit, void *arg) { + dictiterobject *di = (dictiterobject *)self; Py_VISIT(di->di_dict); Py_VISIT(di->di_result); return 0; } static PyObject * -dictiter_len(dictiterobject *di, PyObject *Py_UNUSED(ignored)) +dictiter_len(PyObject *self, PyObject *Py_UNUSED(ignored)) { + dictiterobject *di = (dictiterobject *)self; Py_ssize_t len = 0; if (di->di_dict != NULL && di->di_used == di->di_dict->ma_used) len = di->len; @@ -4074,21 +4167,22 @@ PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it))."); static PyObject * -dictiter_reduce(dictiterobject *di, PyObject *Py_UNUSED(ignored)); +dictiter_reduce(PyObject *di, PyObject *Py_UNUSED(ignored)); PyDoc_STRVAR(reduce_doc, "Return state information for pickling."); static PyMethodDef dictiter_methods[] = { - {"__length_hint__", _PyCFunction_CAST(dictiter_len), METH_NOARGS, + {"__length_hint__", dictiter_len, METH_NOARGS, length_hint_doc}, - {"__reduce__", _PyCFunction_CAST(dictiter_reduce), METH_NOARGS, + {"__reduce__", dictiter_reduce, METH_NOARGS, reduce_doc}, {NULL, NULL} /* sentinel */ }; static PyObject* -dictiter_iternextkey(dictiterobject *di) +dictiter_iternextkey(PyObject *self) { + dictiterobject *di = (dictiterobject *)self; PyObject *key; Py_ssize_t i; PyDictKeysObject *k; @@ -4160,7 +4254,7 @@ PyTypeObject PyDictIterKey_Type = { sizeof(dictiterobject), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ - (destructor)dictiter_dealloc, /* tp_dealloc */ + dictiter_dealloc, /* tp_dealloc */ 0, /* tp_vectorcall_offset */ 0, /* tp_getattr */ 0, /* tp_setattr */ @@ -4177,19 +4271,20 @@ PyTypeObject PyDictIterKey_Type = { 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */ 0, /* tp_doc */ - (traverseproc)dictiter_traverse, /* tp_traverse */ + dictiter_traverse, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ PyObject_SelfIter, /* tp_iter */ - (iternextfunc)dictiter_iternextkey, /* tp_iternext */ + dictiter_iternextkey, /* tp_iternext */ dictiter_methods, /* tp_methods */ 0, }; static PyObject * -dictiter_iternextvalue(dictiterobject *di) +dictiter_iternextvalue(PyObject *self) { + dictiterobject *di = (dictiterobject *)self; PyObject *value; Py_ssize_t i; PyDictObject *d = di->di_dict; @@ -4259,7 +4354,7 @@ PyTypeObject PyDictIterValue_Type = { sizeof(dictiterobject), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ - (destructor)dictiter_dealloc, /* tp_dealloc */ + dictiter_dealloc, /* tp_dealloc */ 0, /* tp_vectorcall_offset */ 0, /* tp_getattr */ 0, /* tp_setattr */ @@ -4276,19 +4371,20 @@ PyTypeObject PyDictIterValue_Type = { 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ 0, /* tp_doc */ - (traverseproc)dictiter_traverse, /* tp_traverse */ + dictiter_traverse, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ PyObject_SelfIter, /* tp_iter */ - (iternextfunc)dictiter_iternextvalue, /* tp_iternext */ + dictiter_iternextvalue, /* tp_iternext */ dictiter_methods, /* tp_methods */ 0, }; static PyObject * -dictiter_iternextitem(dictiterobject *di) +dictiter_iternextitem(PyObject *self) { + dictiterobject *di = (dictiterobject *)self; PyObject *key, *value, *result; Py_ssize_t i; PyDictObject *d = di->di_dict; @@ -4383,7 +4479,7 @@ PyTypeObject PyDictIterItem_Type = { sizeof(dictiterobject), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ - (destructor)dictiter_dealloc, /* tp_dealloc */ + dictiter_dealloc, /* tp_dealloc */ 0, /* tp_vectorcall_offset */ 0, /* tp_getattr */ 0, /* tp_setattr */ @@ -4400,12 +4496,12 @@ PyTypeObject PyDictIterItem_Type = { 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */ 0, /* tp_doc */ - (traverseproc)dictiter_traverse, /* tp_traverse */ + dictiter_traverse, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ PyObject_SelfIter, /* tp_iter */ - (iternextfunc)dictiter_iternextitem, /* tp_iternext */ + dictiter_iternextitem, /* tp_iternext */ dictiter_methods, /* tp_methods */ 0, }; @@ -4414,8 +4510,9 @@ PyTypeObject PyDictIterItem_Type = { /* dictreviter */ static PyObject * -dictreviter_iternext(dictiterobject *di) +dictreviter_iternext(PyObject *self) { + dictiterobject *di = (dictiterobject *)self; PyDictObject *d = di->di_dict; if (d == NULL) { @@ -4516,11 +4613,11 @@ PyTypeObject PyDictRevIterKey_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) "dict_reversekeyiterator", sizeof(dictiterobject), - .tp_dealloc = (destructor)dictiter_dealloc, + .tp_dealloc = dictiter_dealloc, .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, - .tp_traverse = (traverseproc)dictiter_traverse, + .tp_traverse = dictiter_traverse, .tp_iter = PyObject_SelfIter, - .tp_iternext = (iternextfunc)dictreviter_iternext, + .tp_iternext = dictreviter_iternext, .tp_methods = dictiter_methods }; @@ -4540,8 +4637,9 @@ dict___reversed___impl(PyDictObject *self) } static PyObject * -dictiter_reduce(dictiterobject *di, PyObject *Py_UNUSED(ignored)) +dictiter_reduce(PyObject *self, PyObject *Py_UNUSED(ignored)) { + dictiterobject *di = (dictiterobject *)self; /* copy the iterator state */ dictiterobject tmp = *di; Py_XINCREF(tmp.di_dict); @@ -4557,11 +4655,11 @@ PyTypeObject PyDictRevIterItem_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) "dict_reverseitemiterator", sizeof(dictiterobject), - .tp_dealloc = (destructor)dictiter_dealloc, + .tp_dealloc = dictiter_dealloc, .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, - .tp_traverse = (traverseproc)dictiter_traverse, + .tp_traverse = dictiter_traverse, .tp_iter = PyObject_SelfIter, - .tp_iternext = (iternextfunc)dictreviter_iternext, + .tp_iternext = dictreviter_iternext, .tp_methods = dictiter_methods }; @@ -4569,11 +4667,11 @@ PyTypeObject PyDictRevIterValue_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) "dict_reversevalueiterator", sizeof(dictiterobject), - .tp_dealloc = (destructor)dictiter_dealloc, + .tp_dealloc = dictiter_dealloc, .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, - .tp_traverse = (traverseproc)dictiter_traverse, + .tp_traverse = dictiter_traverse, .tp_iter = PyObject_SelfIter, - .tp_iternext = (iternextfunc)dictreviter_iternext, + .tp_iternext = dictreviter_iternext, .tp_methods = dictiter_methods }; @@ -4584,8 +4682,9 @@ PyTypeObject PyDictRevIterValue_Type = { /* The instance lay-out is the same for all three; but the type differs. */ static void -dictview_dealloc(_PyDictViewObject *dv) +dictview_dealloc(PyObject *self) { + _PyDictViewObject *dv = (_PyDictViewObject *)self; /* bpo-31095: UnTrack is needed before calling any callbacks */ _PyObject_GC_UNTRACK(dv); Py_XDECREF(dv->dv_dict); @@ -4593,15 +4692,17 @@ dictview_dealloc(_PyDictViewObject *dv) } static int -dictview_traverse(_PyDictViewObject *dv, visitproc visit, void *arg) +dictview_traverse(PyObject *self, visitproc visit, void *arg) { + _PyDictViewObject *dv = (_PyDictViewObject *)self; Py_VISIT(dv->dv_dict); return 0; } static Py_ssize_t -dictview_len(_PyDictViewObject *dv) +dictview_len(PyObject *self) { + _PyDictViewObject *dv = (_PyDictViewObject *)self; Py_ssize_t len = 0; if (dv->dv_dict != NULL) len = dv->dv_dict->ma_used; @@ -4643,7 +4744,7 @@ dictview_mapping(PyObject *view, void *Py_UNUSED(ignored)) { static PyGetSetDef dictview_getset[] = { {"mapping", dictview_mapping, (setter)NULL, - "dictionary that this view refers to", NULL}, + PyDoc_STR("dictionary that this view refers to"), NULL}, {0} }; @@ -4741,8 +4842,9 @@ dictview_richcompare(PyObject *self, PyObject *other, int op) } static PyObject * -dictview_repr(_PyDictViewObject *dv) +dictview_repr(PyObject *self) { + _PyDictViewObject *dv = (_PyDictViewObject *)self; PyObject *seq; PyObject *result = NULL; Py_ssize_t rc; @@ -4766,8 +4868,9 @@ dictview_repr(_PyDictViewObject *dv) /*** dict_keys ***/ static PyObject * -dictkeys_iter(_PyDictViewObject *dv) +dictkeys_iter(PyObject *self) { + _PyDictViewObject *dv = (_PyDictViewObject *)self; if (dv->dv_dict == NULL) { Py_RETURN_NONE; } @@ -4775,22 +4878,23 @@ dictkeys_iter(_PyDictViewObject *dv) } static int -dictkeys_contains(_PyDictViewObject *dv, PyObject *obj) +dictkeys_contains(PyObject *self, PyObject *obj) { + _PyDictViewObject *dv = (_PyDictViewObject *)self; if (dv->dv_dict == NULL) return 0; return PyDict_Contains((PyObject *)dv->dv_dict, obj); } static PySequenceMethods dictkeys_as_sequence = { - (lenfunc)dictview_len, /* sq_length */ + dictview_len, /* sq_length */ 0, /* sq_concat */ 0, /* sq_repeat */ 0, /* sq_item */ 0, /* sq_slice */ 0, /* sq_ass_item */ 0, /* sq_ass_slice */ - (objobjproc)dictkeys_contains, /* sq_contains */ + dictkeys_contains, /* sq_contains */ }; // Create a set object from dictviews object. @@ -4830,7 +4934,7 @@ dictviews_sub(PyObject *self, PyObject *other) } static int -dictitems_contains(_PyDictViewObject *dv, PyObject *obj); +dictitems_contains(PyObject *dv, PyObject *obj); PyObject * _PyDictView_Intersect(PyObject* self, PyObject *other) @@ -4840,7 +4944,7 @@ _PyDictView_Intersect(PyObject* self, PyObject *other) PyObject *key; Py_ssize_t len_self; int rv; - int (*dict_contains)(_PyDictViewObject *, PyObject *); + objobjproc dict_contains; /* Python interpreter swaps parameters when dict view is on right side of & */ @@ -4850,7 +4954,7 @@ _PyDictView_Intersect(PyObject* self, PyObject *other) self = tmp; } - len_self = dictview_len((_PyDictViewObject *)self); + len_self = dictview_len(self); /* if other is a set and self is smaller than other, reuse set intersection logic */ @@ -4862,7 +4966,7 @@ _PyDictView_Intersect(PyObject* self, PyObject *other) /* if other is another dict view, and it is bigger than self, swap them */ if (PyDictViewSet_Check(other)) { - Py_ssize_t len_other = dictview_len((_PyDictViewObject *)other); + Py_ssize_t len_other = dictview_len(other); if (len_other > len_self) { PyObject *tmp = other; other = self; @@ -4892,7 +4996,7 @@ _PyDictView_Intersect(PyObject* self, PyObject *other) } while ((key = PyIter_Next(it)) != NULL) { - rv = dict_contains((_PyDictViewObject *)self, key); + rv = dict_contains(self, key); if (rv < 0) { goto error; } @@ -5066,7 +5170,7 @@ dictviews_isdisjoint(PyObject *self, PyObject *other) PyObject *item = NULL; if (self == other) { - if (dictview_len((_PyDictViewObject *)self) == 0) + if (dictview_len(self) == 0) Py_RETURN_TRUE; else Py_RETURN_FALSE; @@ -5075,7 +5179,7 @@ dictviews_isdisjoint(PyObject *self, PyObject *other) /* Iterate over the shorter object (only if other is a set, * because PySequence_Contains may be expensive otherwise): */ if (PyAnySet_Check(other) || PyDictViewSet_Check(other)) { - Py_ssize_t len_self = dictview_len((_PyDictViewObject *)self); + Py_ssize_t len_self = dictview_len(self); Py_ssize_t len_other = PyObject_Size(other); if (len_other == -1) return NULL; @@ -5113,15 +5217,15 @@ dictviews_isdisjoint(PyObject *self, PyObject *other) PyDoc_STRVAR(isdisjoint_doc, "Return True if the view and the given iterable have a null intersection."); -static PyObject* dictkeys_reversed(_PyDictViewObject *dv, PyObject *Py_UNUSED(ignored)); +static PyObject* dictkeys_reversed(PyObject *dv, PyObject *Py_UNUSED(ignored)); PyDoc_STRVAR(reversed_keys_doc, "Return a reverse iterator over the dict keys."); static PyMethodDef dictkeys_methods[] = { - {"isdisjoint", (PyCFunction)dictviews_isdisjoint, METH_O, + {"isdisjoint", dictviews_isdisjoint, METH_O, isdisjoint_doc}, - {"__reversed__", _PyCFunction_CAST(dictkeys_reversed), METH_NOARGS, + {"__reversed__", dictkeys_reversed, METH_NOARGS, reversed_keys_doc}, {NULL, NULL} /* sentinel */ }; @@ -5132,12 +5236,12 @@ PyTypeObject PyDictKeys_Type = { sizeof(_PyDictViewObject), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ - (destructor)dictview_dealloc, /* tp_dealloc */ + dictview_dealloc, /* tp_dealloc */ 0, /* tp_vectorcall_offset */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_as_async */ - (reprfunc)dictview_repr, /* tp_repr */ + dictview_repr, /* tp_repr */ &dictviews_as_number, /* tp_as_number */ &dictkeys_as_sequence, /* tp_as_sequence */ 0, /* tp_as_mapping */ @@ -5149,11 +5253,11 @@ PyTypeObject PyDictKeys_Type = { 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */ 0, /* tp_doc */ - (traverseproc)dictview_traverse, /* tp_traverse */ + dictview_traverse, /* tp_traverse */ 0, /* tp_clear */ dictview_richcompare, /* tp_richcompare */ 0, /* tp_weaklistoffset */ - (getiterfunc)dictkeys_iter, /* tp_iter */ + dictkeys_iter, /* tp_iter */ 0, /* tp_iternext */ dictkeys_methods, /* tp_methods */ .tp_getset = dictview_getset, @@ -5166,8 +5270,9 @@ dictkeys_new(PyObject *dict, PyObject *Py_UNUSED(ignored)) } static PyObject * -dictkeys_reversed(_PyDictViewObject *dv, PyObject *Py_UNUSED(ignored)) +dictkeys_reversed(PyObject *self, PyObject *Py_UNUSED(ignored)) { + _PyDictViewObject *dv = (_PyDictViewObject *)self; if (dv->dv_dict == NULL) { Py_RETURN_NONE; } @@ -5177,8 +5282,9 @@ dictkeys_reversed(_PyDictViewObject *dv, PyObject *Py_UNUSED(ignored)) /*** dict_items ***/ static PyObject * -dictitems_iter(_PyDictViewObject *dv) +dictitems_iter(PyObject *self) { + _PyDictViewObject *dv = (_PyDictViewObject *)self; if (dv->dv_dict == NULL) { Py_RETURN_NONE; } @@ -5186,8 +5292,9 @@ dictitems_iter(_PyDictViewObject *dv) } static int -dictitems_contains(_PyDictViewObject *dv, PyObject *obj) +dictitems_contains(PyObject *self, PyObject *obj) { + _PyDictViewObject *dv = (_PyDictViewObject *)self; int result; PyObject *key, *value, *found; if (dv->dv_dict == NULL) @@ -5205,25 +5312,25 @@ dictitems_contains(_PyDictViewObject *dv, PyObject *obj) } static PySequenceMethods dictitems_as_sequence = { - (lenfunc)dictview_len, /* sq_length */ + dictview_len, /* sq_length */ 0, /* sq_concat */ 0, /* sq_repeat */ 0, /* sq_item */ 0, /* sq_slice */ 0, /* sq_ass_item */ 0, /* sq_ass_slice */ - (objobjproc)dictitems_contains, /* sq_contains */ + dictitems_contains, /* sq_contains */ }; -static PyObject* dictitems_reversed(_PyDictViewObject *dv, PyObject *Py_UNUSED(ignored)); +static PyObject* dictitems_reversed(PyObject *dv, PyObject *Py_UNUSED(ignored)); PyDoc_STRVAR(reversed_items_doc, "Return a reverse iterator over the dict items."); static PyMethodDef dictitems_methods[] = { - {"isdisjoint", (PyCFunction)dictviews_isdisjoint, METH_O, + {"isdisjoint", dictviews_isdisjoint, METH_O, isdisjoint_doc}, - {"__reversed__", (PyCFunction)dictitems_reversed, METH_NOARGS, + {"__reversed__", dictitems_reversed, METH_NOARGS, reversed_items_doc}, {NULL, NULL} /* sentinel */ }; @@ -5234,12 +5341,12 @@ PyTypeObject PyDictItems_Type = { sizeof(_PyDictViewObject), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ - (destructor)dictview_dealloc, /* tp_dealloc */ + dictview_dealloc, /* tp_dealloc */ 0, /* tp_vectorcall_offset */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_as_async */ - (reprfunc)dictview_repr, /* tp_repr */ + dictview_repr, /* tp_repr */ &dictviews_as_number, /* tp_as_number */ &dictitems_as_sequence, /* tp_as_sequence */ 0, /* tp_as_mapping */ @@ -5251,11 +5358,11 @@ PyTypeObject PyDictItems_Type = { 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */ 0, /* tp_doc */ - (traverseproc)dictview_traverse, /* tp_traverse */ + dictview_traverse, /* tp_traverse */ 0, /* tp_clear */ dictview_richcompare, /* tp_richcompare */ 0, /* tp_weaklistoffset */ - (getiterfunc)dictitems_iter, /* tp_iter */ + dictitems_iter, /* tp_iter */ 0, /* tp_iternext */ dictitems_methods, /* tp_methods */ .tp_getset = dictview_getset, @@ -5268,8 +5375,9 @@ dictitems_new(PyObject *dict, PyObject *Py_UNUSED(ignored)) } static PyObject * -dictitems_reversed(_PyDictViewObject *dv, PyObject *Py_UNUSED(ignored)) +dictitems_reversed(PyObject *self, PyObject *Py_UNUSED(ignored)) { + _PyDictViewObject *dv = (_PyDictViewObject *)self; if (dv->dv_dict == NULL) { Py_RETURN_NONE; } @@ -5279,8 +5387,9 @@ dictitems_reversed(_PyDictViewObject *dv, PyObject *Py_UNUSED(ignored)) /*** dict_values ***/ static PyObject * -dictvalues_iter(_PyDictViewObject *dv) +dictvalues_iter(PyObject *self) { + _PyDictViewObject *dv = (_PyDictViewObject *)self; if (dv->dv_dict == NULL) { Py_RETURN_NONE; } @@ -5288,7 +5397,7 @@ dictvalues_iter(_PyDictViewObject *dv) } static PySequenceMethods dictvalues_as_sequence = { - (lenfunc)dictview_len, /* sq_length */ + dictview_len, /* sq_length */ 0, /* sq_concat */ 0, /* sq_repeat */ 0, /* sq_item */ @@ -5298,13 +5407,13 @@ static PySequenceMethods dictvalues_as_sequence = { (objobjproc)0, /* sq_contains */ }; -static PyObject* dictvalues_reversed(_PyDictViewObject *dv, PyObject *Py_UNUSED(ignored)); +static PyObject* dictvalues_reversed(PyObject *dv, PyObject *Py_UNUSED(ignored)); PyDoc_STRVAR(reversed_values_doc, "Return a reverse iterator over the dict values."); static PyMethodDef dictvalues_methods[] = { - {"__reversed__", (PyCFunction)dictvalues_reversed, METH_NOARGS, + {"__reversed__", dictvalues_reversed, METH_NOARGS, reversed_values_doc}, {NULL, NULL} /* sentinel */ }; @@ -5315,12 +5424,12 @@ PyTypeObject PyDictValues_Type = { sizeof(_PyDictViewObject), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ - (destructor)dictview_dealloc, /* tp_dealloc */ + dictview_dealloc, /* tp_dealloc */ 0, /* tp_vectorcall_offset */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_as_async */ - (reprfunc)dictview_repr, /* tp_repr */ + dictview_repr, /* tp_repr */ 0, /* tp_as_number */ &dictvalues_as_sequence, /* tp_as_sequence */ 0, /* tp_as_mapping */ @@ -5332,11 +5441,11 @@ PyTypeObject PyDictValues_Type = { 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */ 0, /* tp_doc */ - (traverseproc)dictview_traverse, /* tp_traverse */ + dictview_traverse, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ - (getiterfunc)dictvalues_iter, /* tp_iter */ + dictvalues_iter, /* tp_iter */ 0, /* tp_iternext */ dictvalues_methods, /* tp_methods */ .tp_getset = dictview_getset, @@ -5349,8 +5458,9 @@ dictvalues_new(PyObject *dict, PyObject *Py_UNUSED(ignored)) } static PyObject * -dictvalues_reversed(_PyDictViewObject *dv, PyObject *Py_UNUSED(ignored)) +dictvalues_reversed(PyObject *self, PyObject *Py_UNUSED(ignored)) { + _PyDictViewObject *dv = (_PyDictViewObject *)self; if (dv->dv_dict == NULL) { Py_RETURN_NONE; } @@ -5464,6 +5574,37 @@ _PyObject_MakeDictFromInstanceAttributes(PyObject *obj, PyDictValues *values) return make_dict_from_instance_attributes(interp, keys, values); } +// Return true if the dict was dematerialized, false otherwise. +bool +_PyObject_MakeInstanceAttributesFromDict(PyObject *obj, PyDictOrValues *dorv) +{ + assert(_PyObject_DictOrValuesPointer(obj) == dorv); + assert(!_PyDictOrValues_IsValues(*dorv)); + PyDictObject *dict = (PyDictObject *)_PyDictOrValues_GetDict(*dorv); + if (dict == NULL) { + return false; + } + // It's likely that this dict still shares its keys (if it was materialized + // on request and not heavily modified): + if (!PyDict_CheckExact(dict)) { + return false; + } + assert(_PyType_HasFeature(Py_TYPE(obj), Py_TPFLAGS_HEAPTYPE)); + if (dict->ma_keys != CACHED_KEYS(Py_TYPE(obj)) || Py_REFCNT(dict) != 1) { + return false; + } + assert(dict->ma_values); + // We have an opportunity to do something *really* cool: dematerialize it! + _PyDictKeys_DecRef(dict->ma_keys); + _PyDictOrValues_SetValues(dorv, dict->ma_values); + OBJECT_STAT_INC(dict_dematerialized); + // Don't try this at home, kids: + dict->ma_keys = NULL; + dict->ma_values = NULL; + Py_DECREF(dict); + return true; +} + int _PyObject_StoreInstanceAttribute(PyObject *obj, PyDictValues *values, PyObject *name, PyObject *value) @@ -5619,7 +5760,7 @@ _PyObject_FreeInstanceAttributes(PyObject *self) } int -_PyObject_VisitManagedDict(PyObject *obj, visitproc visit, void *arg) +PyObject_VisitManagedDict(PyObject *obj, visitproc visit, void *arg) { PyTypeObject *tp = Py_TYPE(obj); if((tp->tp_flags & Py_TPFLAGS_MANAGED_DICT) == 0) { @@ -5642,7 +5783,7 @@ _PyObject_VisitManagedDict(PyObject *obj, visitproc visit, void *arg) } void -_PyObject_ClearManagedDict(PyObject *obj) +PyObject_ClearManagedDict(PyObject *obj) { PyTypeObject *tp = Py_TYPE(obj); if((tp->tp_flags & Py_TPFLAGS_MANAGED_DICT) == 0) { @@ -5688,6 +5829,7 @@ PyObject_GenericGetDict(PyObject *obj, void *context) dict = _PyDictOrValues_GetDict(*dorv_ptr); if (dict == NULL) { dictkeys_incref(CACHED_KEYS(tp)); + OBJECT_STAT_INC(dict_materialized_on_request); dict = new_dict_with_shared_keys(interp, CACHED_KEYS(tp)); dorv_ptr->dict = dict; } @@ -5730,6 +5872,7 @@ _PyObjectDict_SetItem(PyTypeObject *tp, PyObject **dictptr, assert(dictptr != NULL); dict = *dictptr; if (dict == NULL) { + assert(!_PyType_HasFeature(tp, Py_TPFLAGS_MANAGED_DICT)); dictkeys_incref(cached); dict = new_dict_with_shared_keys(interp, cached); if (dict == NULL) @@ -5880,14 +6023,9 @@ _PyDict_SendEvent(int watcher_bits, // unraisablehook keep a reference to it, so we don't pass the // dict as context, just an informative string message. Dict // repr can call arbitrary code, so we invent a simpler version. - PyObject *context = PyUnicode_FromFormat( - "%s watcher callback for ", + PyErr_FormatUnraisable( + "Exception ignored in %s watcher callback for ", dict_event_name(event), mp); - if (context == NULL) { - context = Py_NewRef(Py_None); - } - PyErr_WriteUnraisable(context); - Py_DECREF(context); } } watcher_bits >>= 1; diff --git a/Objects/exception_handling_notes.txt b/Objects/exception_handling_notes.txt index 7de01fdbf5ff48..387ef935ce739e 100644 --- a/Objects/exception_handling_notes.txt +++ b/Objects/exception_handling_notes.txt @@ -47,7 +47,7 @@ a table to determine where to jump to when an exception is raised. 2 2 NOP - 3 4 LOAD_GLOBAL 1 (NULL + g) + 3 4 LOAD_GLOBAL 1 (g + NULL) 16 LOAD_CONST 1 (0) 18 PRECALL 1 22 CALL 1 diff --git a/Objects/exceptions.c b/Objects/exceptions.c index 62a44234b34047..a685ed803cd02d 100644 --- a/Objects/exceptions.c +++ b/Objects/exceptions.c @@ -8,10 +8,11 @@ #include #include "pycore_abstract.h" // _PyObject_RealIsSubclass() #include "pycore_ceval.h" // _Py_EnterRecursiveCall -#include "pycore_pyerrors.h" // struct _PyErr_SetRaisedException #include "pycore_exceptions.h" // struct _Py_exc_state #include "pycore_initconfig.h" +#include "pycore_modsupport.h" // _PyArg_NoKeywords() #include "pycore_object.h" +#include "pycore_pyerrors.h" // struct _PyErr_SetRaisedException #include "osdefs.h" // SEP @@ -875,13 +876,9 @@ BaseExceptionGroup_str(PyBaseExceptionGroupObject *self) } static PyObject * -BaseExceptionGroup_derive(PyObject *self_, PyObject *args) +BaseExceptionGroup_derive(PyObject *self_, PyObject *excs) { PyBaseExceptionGroupObject *self = _PyBaseExceptionGroupObject_cast(self_); - PyObject *excs = NULL; - if (!PyArg_ParseTuple(args, "O", &excs)) { - return NULL; - } PyObject *init_args = PyTuple_Pack(2, self->msg, excs); if (!init_args) { return NULL; @@ -1175,13 +1172,8 @@ exceptiongroup_split_recursive(PyObject *exc, } static PyObject * -BaseExceptionGroup_split(PyObject *self, PyObject *args) +BaseExceptionGroup_split(PyObject *self, PyObject *matcher_value) { - PyObject *matcher_value = NULL; - if (!PyArg_UnpackTuple(args, "split", 1, 1, &matcher_value)) { - return NULL; - } - _exceptiongroup_split_matcher_type matcher_type; if (get_matcher_type(matcher_value, &matcher_type) < 0) { return NULL; @@ -1206,13 +1198,8 @@ BaseExceptionGroup_split(PyObject *self, PyObject *args) } static PyObject * -BaseExceptionGroup_subgroup(PyObject *self, PyObject *args) +BaseExceptionGroup_subgroup(PyObject *self, PyObject *matcher_value) { - PyObject *matcher_value = NULL; - if (!PyArg_UnpackTuple(args, "subgroup", 1, 1, &matcher_value)) { - return NULL; - } - _exceptiongroup_split_matcher_type matcher_type; if (get_matcher_type(matcher_value, &matcher_type) < 0) { return NULL; @@ -1487,9 +1474,9 @@ static PyMemberDef BaseExceptionGroup_members[] = { static PyMethodDef BaseExceptionGroup_methods[] = { {"__class_getitem__", (PyCFunction)Py_GenericAlias, METH_O|METH_CLASS, PyDoc_STR("See PEP 585")}, - {"derive", (PyCFunction)BaseExceptionGroup_derive, METH_VARARGS}, - {"split", (PyCFunction)BaseExceptionGroup_split, METH_VARARGS}, - {"subgroup", (PyCFunction)BaseExceptionGroup_subgroup, METH_VARARGS}, + {"derive", (PyCFunction)BaseExceptionGroup_derive, METH_O}, + {"split", (PyCFunction)BaseExceptionGroup_split, METH_O}, + {"subgroup", (PyCFunction)BaseExceptionGroup_subgroup, METH_O}, {NULL} }; @@ -3699,10 +3686,6 @@ _PyExc_FiniTypes(PyInterpreterState *interp) PyStatus _PyExc_InitGlobalObjects(PyInterpreterState *interp) { - if (!_Py_IsMainInterpreter(interp)) { - return _PyStatus_OK(); - } - if (preallocate_memerrors() < 0) { return _PyStatus_NO_MEMORY(); } diff --git a/Objects/fileobject.c b/Objects/fileobject.c index 751fb69d0891cf..5522eba34eace9 100644 --- a/Objects/fileobject.c +++ b/Objects/fileobject.c @@ -4,15 +4,19 @@ #include "pycore_call.h" // _PyObject_CallNoArgs() #include "pycore_runtime.h" // _PyRuntime +#ifdef HAVE_UNISTD_H +# include // isatty() +#endif + #if defined(HAVE_GETC_UNLOCKED) && !defined(_Py_MEMORY_SANITIZER) -/* clang MemorySanitizer doesn't yet understand getc_unlocked. */ -#define GETC(f) getc_unlocked(f) -#define FLOCKFILE(f) flockfile(f) -#define FUNLOCKFILE(f) funlockfile(f) + /* clang MemorySanitizer doesn't yet understand getc_unlocked. */ +# define GETC(f) getc_unlocked(f) +# define FLOCKFILE(f) flockfile(f) +# define FUNLOCKFILE(f) funlockfile(f) #else -#define GETC(f) getc(f) -#define FLOCKFILE(f) -#define FUNLOCKFILE(f) +# define GETC(f) getc(f) +# define FLOCKFILE(f) +# define FUNLOCKFILE(f) #endif /* Newline flags */ @@ -21,10 +25,6 @@ #define NEWLINE_LF 2 /* \n newline seen */ #define NEWLINE_CRLF 4 /* \r\n newline seen */ -#ifdef __cplusplus -extern "C" { -#endif - /* External C interface */ PyObject * @@ -174,7 +174,7 @@ PyObject_AsFileDescriptor(PyObject *o) PyObject *meth; if (PyLong_Check(o)) { - fd = _PyLong_AsInt(o); + fd = PyLong_AsInt(o); } else if (PyObject_GetOptionalAttr(o, &_Py_ID(fileno), &meth) < 0) { return -1; @@ -186,7 +186,7 @@ PyObject_AsFileDescriptor(PyObject *o) return -1; if (PyLong_Check(fno)) { - fd = _PyLong_AsInt(fno); + fd = PyLong_AsInt(fno); Py_DECREF(fno); } else { @@ -529,6 +529,13 @@ PyFile_OpenCode(const char *utf8path) } -#ifdef __cplusplus +int +_PyFile_Flush(PyObject *file) +{ + PyObject *tmp = PyObject_CallMethodNoArgs(file, &_Py_ID(flush)); + if (tmp == NULL) { + return -1; + } + Py_DECREF(tmp); + return 0; } -#endif diff --git a/Objects/floatobject.c b/Objects/floatobject.c index 6a0c2e033e3e9a..f1a09c0a94f4a6 100644 --- a/Objects/floatobject.c +++ b/Objects/floatobject.c @@ -4,6 +4,7 @@ for any kind of float exception without losing portability. */ #include "Python.h" +#include "pycore_abstract.h" // _PyNumber_Index() #include "pycore_dtoa.h" // _Py_dg_dtoa() #include "pycore_floatobject.h" // _PyFloat_FormatAdvancedWriter() #include "pycore_initconfig.h" // _PyStatus_OK() @@ -15,8 +16,7 @@ #include "pycore_pystate.h" // _PyInterpreterState_GET() #include "pycore_structseq.h" // _PyStructSequence_FiniBuiltin() -#include -#include +#include // DBL_MAX #include // strtol() /*[clinic input] @@ -26,17 +26,13 @@ class float "PyObject *" "&PyFloat_Type" #include "clinic/floatobject.c.h" -#ifndef PyFloat_MAXFREELIST -# define PyFloat_MAXFREELIST 100 -#endif - - -#if PyFloat_MAXFREELIST > 0 +#ifdef WITH_FREELISTS static struct _Py_float_state * get_float_state(void) { - PyInterpreterState *interp = _PyInterpreterState_GET(); - return &interp->float_state; + _PyFreeListState *state = _PyFreeListState_GET(); + assert(state != NULL); + return &state->float_state; } #endif @@ -132,7 +128,7 @@ PyObject * PyFloat_FromDouble(double fval) { PyFloatObject *op; -#if PyFloat_MAXFREELIST > 0 +#ifdef WITH_FREELISTS struct _Py_float_state *state = get_float_state(); op = state->free_list; if (op != NULL) { @@ -252,13 +248,9 @@ _PyFloat_ExactDealloc(PyObject *obj) { assert(PyFloat_CheckExact(obj)); PyFloatObject *op = (PyFloatObject *)obj; -#if PyFloat_MAXFREELIST > 0 +#ifdef WITH_FREELISTS struct _Py_float_state *state = get_float_state(); -#ifdef Py_DEBUG - // float_dealloc() must not be called after _PyFloat_Fini() - assert(state->numfree != -1); -#endif - if (state->numfree >= PyFloat_MAXFREELIST) { + if (state->numfree >= PyFloat_MAXFREELIST || state->numfree < 0) { PyObject_Free(op); return; } @@ -275,7 +267,7 @@ static void float_dealloc(PyObject *op) { assert(PyFloat_Check(op)); -#if PyFloat_MAXFREELIST > 0 +#ifdef WITH_FREELISTS if (PyFloat_CheckExact(op)) { _PyFloat_ExactDealloc(op); } @@ -646,7 +638,7 @@ float_rem(PyObject *v, PyObject *w) CONVERT_TO_DOUBLE(w, wx); if (wx == 0.0) { PyErr_SetString(PyExc_ZeroDivisionError, - "float modulo"); + "float modulo by zero"); return NULL; } mod = fmod(vx, wx); @@ -2002,10 +1994,10 @@ _PyFloat_InitTypes(PyInterpreterState *interp) } void -_PyFloat_ClearFreeList(PyInterpreterState *interp) +_PyFloat_ClearFreeList(_PyFreeListState *freelist_state, int is_finalization) { -#if PyFloat_MAXFREELIST > 0 - struct _Py_float_state *state = &interp->float_state; +#ifdef WITH_FREELISTS + struct _Py_float_state *state = &freelist_state->float_state; PyFloatObject *f = state->free_list; while (f != NULL) { PyFloatObject *next = (PyFloatObject*) Py_TYPE(f); @@ -2013,18 +2005,19 @@ _PyFloat_ClearFreeList(PyInterpreterState *interp) f = next; } state->free_list = NULL; - state->numfree = 0; + if (is_finalization) { + state->numfree = -1; + } + else { + state->numfree = 0; + } #endif } void -_PyFloat_Fini(PyInterpreterState *interp) +_PyFloat_Fini(_PyFreeListState *state) { - _PyFloat_ClearFreeList(interp); -#if defined(Py_DEBUG) && PyFloat_MAXFREELIST > 0 - struct _Py_float_state *state = &interp->float_state; - state->numfree = -1; -#endif + _PyFloat_ClearFreeList(state, 1); } void @@ -2037,7 +2030,7 @@ _PyFloat_FiniType(PyInterpreterState *interp) void _PyFloat_DebugMallocStats(FILE *out) { -#if PyFloat_MAXFREELIST > 0 +#ifdef WITH_FREELISTS struct _Py_float_state *state = get_float_state(); _PyDebugAllocatorStats(out, "free PyFloatObject", diff --git a/Objects/frame_layout.md b/Objects/frame_layout.md index 2f95214db56498..b348e85689f507 100644 --- a/Objects/frame_layout.md +++ b/Objects/frame_layout.md @@ -130,3 +130,28 @@ returns. This extra frame is inserted so that `RETURN_VALUE`, `YIELD_VALUE`, and `RETURN_GENERATOR` do not need to check whether the current frame is the entry frame. The shim frame points to a special code object containing the `INTERPRETER_EXIT` instruction which cleans up the shim frame and returns. + + +### The Instruction Pointer + +`_PyInterpreterFrame` has two fields which are used to maintain the instruction +pointer: `instr_ptr` and `return_offset`. + +When a frame is executing, `instr_ptr` points to the instruction currently being +executed. In a suspended frame, it points to the instruction that would execute +if the frame were to resume. After `frame.f_lineno` is set, `instr_ptr` points to +the next instruction to be executed. During a call to a python function, +`instr_ptr` points to the call instruction, because this is what we would expect +to see in an exception traceback. + +The `return_offset` field determines where a `RETURN` should go in the caller, +relative to `instr_ptr`. It is only meaningful to the callee, so it needs to +be set in any instruction that implements a call (to a Python function), +including CALL, SEND and BINARY_SUBSCR_GETITEM, among others. If there is no +callee, then return_offset is meaningless. It is necessary to have a separate +field for the return offset because (1) if we apply this offset to `instr_ptr` +while executing the `RETURN`, this is too early and would lose us information +about the previous instruction which we could need for introspecting and +debugging. (2) `SEND` needs to pass two offsets to the generator: one for +`RETURN` and one for `YIELD`. It uses the `oparg` for one, and the +`return_offset` for the other. diff --git a/Objects/frameobject.c b/Objects/frameobject.c index 17571535048e23..cafe4ef6141d9a 100644 --- a/Objects/frameobject.c +++ b/Objects/frameobject.c @@ -6,7 +6,8 @@ #include "pycore_function.h" // _PyFunction_FromConstructor() #include "pycore_moduleobject.h" // _PyModule_GetDict() #include "pycore_object.h" // _PyObject_GC_UNTRACK() -#include "pycore_opcode.h" // _PyOpcode_Caches +#include "pycore_opcode_metadata.h" // _PyOpcode_Deopt, _PyOpcode_Caches + #include "frameobject.h" // PyFrameObject #include "pycore_frame.h" @@ -24,10 +25,16 @@ static PyMemberDef frame_memberlist[] = { static PyObject * frame_getlocals(PyFrameObject *f, void *closure) { - if (PyFrame_FastToLocalsWithError(f) < 0) + if (f == NULL) { + PyErr_BadInternalCall(); return NULL; - PyObject *locals = f->f_frame->f_locals; - return Py_NewRef(locals); + } + assert(!_PyFrame_IsIncomplete(f->f_frame)); + PyObject *locals = _PyFrame_GetLocals(f->f_frame, 1); + if (locals) { + f->f_fast_as_locals = 1; + } + return locals; } int @@ -120,10 +127,13 @@ frame_settrace_opcodes(PyFrameObject *f, PyObject* value, void *Py_UNUSED(ignore } if (value == Py_True) { f->f_trace_opcodes = 1; - _PyInterpreterState_GET()->f_opcode_trace_set = true; + if (f->f_trace) { + return _PyEval_SetOpcodeTrace(f, true); + } } else { f->f_trace_opcodes = 0; + return _PyEval_SetOpcodeTrace(f, false); } return 0; } @@ -322,6 +332,8 @@ mark_stacks(PyCodeObject *code_obj, int len) switch (opcode) { case POP_JUMP_IF_FALSE: case POP_JUMP_IF_TRUE: + case POP_JUMP_IF_NONE: + case POP_JUMP_IF_NOT_NONE: { int64_t target_stack; int j = next_i + oparg; @@ -404,10 +416,10 @@ mark_stacks(PyCodeObject *code_obj, int len) case LOAD_GLOBAL: { int j = oparg; + next_stack = push_value(next_stack, Object); if (j & 1) { next_stack = push_value(next_stack, Null); } - next_stack = push_value(next_stack, Object); stacks[next_i] = next_stack; break; } @@ -417,22 +429,12 @@ mark_stacks(PyCodeObject *code_obj, int len) int j = oparg; if (j & 1) { next_stack = pop_value(next_stack); - next_stack = push_value(next_stack, Null); next_stack = push_value(next_stack, Object); + next_stack = push_value(next_stack, Null); } stacks[next_i] = next_stack; break; } - case CALL: - { - int args = oparg; - for (int j = 0; j < args+2; j++) { - next_stack = pop_value(next_stack); - } - next_stack = push_value(next_stack, Object); - stacks[next_i] = next_stack; - break; - } case SWAP: { int n = oparg; @@ -590,39 +592,28 @@ first_line_not_before(int *lines, int len, int line) return result; } -static PyFrameState -_PyFrame_GetState(PyFrameObject *frame) +static bool +frame_is_cleared(PyFrameObject *frame) { assert(!_PyFrame_IsIncomplete(frame->f_frame)); if (frame->f_frame->stacktop == 0) { - return FRAME_CLEARED; + return true; } - switch(frame->f_frame->owner) { - case FRAME_OWNED_BY_GENERATOR: - { - PyGenObject *gen = _PyFrame_GetGenerator(frame->f_frame); - return gen->gi_frame_state; - } - case FRAME_OWNED_BY_THREAD: - { - if (_PyInterpreterFrame_LASTI(frame->f_frame) < 0) { - return FRAME_CREATED; - } - switch (frame->f_frame->prev_instr->op.code) - { - case COPY_FREE_VARS: - case MAKE_CELL: - case RETURN_GENERATOR: - /* Frame not fully initialized */ - return FRAME_CREATED; - default: - return FRAME_EXECUTING; - } - } - case FRAME_OWNED_BY_FRAME_OBJECT: - return FRAME_COMPLETED; + if (frame->f_frame->owner == FRAME_OWNED_BY_GENERATOR) { + PyGenObject *gen = _PyFrame_GetGenerator(frame->f_frame); + return gen->gi_frame_state == FRAME_CLEARED; } - Py_UNREACHABLE(); + return false; +} + +static bool frame_is_suspended(PyFrameObject *frame) +{ + assert(!_PyFrame_IsIncomplete(frame->f_frame)); + if (frame->f_frame->owner == FRAME_OWNED_BY_GENERATOR) { + PyGenObject *gen = _PyFrame_GetGenerator(frame->f_frame); + return FRAME_STATE_SUSPENDED(gen->gi_frame_state); + } + return false; } /* Setter for f_lineno - you can set f_lineno from within a trace function in @@ -654,7 +645,7 @@ frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno, void *Py_UNUSED(ignore return -1; } - PyFrameState state = _PyFrame_GetState(f); + bool is_suspended = frame_is_suspended(f); /* * This code preserves the historical restrictions on * setting the line number of a frame. @@ -810,20 +801,17 @@ frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno, void *Py_UNUSED(ignore } assert(unbound == 0); } - if (state == FRAME_SUSPENDED) { + if (is_suspended) { /* Account for value popped by yield */ start_stack = pop_value(start_stack); } while (start_stack > best_stack) { if (top_of_stack(start_stack) == Except) { /* Pop exception stack as well as the evaluation stack */ - PyThreadState *tstate = _PyThreadState_GET(); - _PyErr_StackItem *exc_info = tstate->exc_info; - PyObject *value = exc_info->exc_value; PyObject *exc = _PyFrame_StackPop(f->f_frame); assert(PyExceptionInstance_Check(exc) || exc == Py_None); - exc_info->exc_value = exc; - Py_XDECREF(value); + PyThreadState *tstate = _PyThreadState_GET(); + Py_XSETREF(tstate->exc_info->exc_value, exc == Py_None ? NULL : exc); } else { PyObject *v = _PyFrame_StackPop(f->f_frame); @@ -833,7 +821,7 @@ frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno, void *Py_UNUSED(ignore } /* Finally set the new lasti and return OK. */ f->f_lineno = 0; - f->f_frame->prev_instr = _PyCode_CODE(code) + best_addr; + f->f_frame->instr_ptr = _PyCode_CODE(code) + best_addr; return 0; } @@ -854,6 +842,9 @@ frame_settrace(PyFrameObject *f, PyObject* v, void *closure) } if (v != f->f_trace) { Py_XSETREF(f->f_trace, Py_XNewRef(v)); + if (v != NULL && f->f_trace_opcodes) { + return _PyEval_SetOpcodeTrace(f, true); + } } return 0; } @@ -946,6 +937,9 @@ frame_clear(PyFrameObject *f, PyObject *Py_UNUSED(ignored)) if (gen->gi_frame_state == FRAME_EXECUTING) { goto running; } + if (FRAME_STATE_SUSPENDED(gen->gi_frame_state)) { + goto suspended; + } _PyGen_Finalize((PyObject *)gen); } else if (f->f_frame->owner == FRAME_OWNED_BY_THREAD) { @@ -960,6 +954,10 @@ frame_clear(PyFrameObject *f, PyObject *Py_UNUSED(ignored)) PyErr_SetString(PyExc_RuntimeError, "cannot clear an executing frame"); return NULL; +suspended: + PyErr_SetString(PyExc_RuntimeError, + "cannot clear a suspended frame"); + return NULL; } PyDoc_STRVAR(clear__doc__, @@ -1091,7 +1089,7 @@ PyFrame_New(PyThreadState *tstate, PyCodeObject *code, f->f_frame = (_PyInterpreterFrame *)f->_f_frame_data; f->f_frame->owner = FRAME_OWNED_BY_FRAME_OBJECT; // This frame needs to be "complete", so pretend that the first RESUME ran: - f->f_frame->prev_instr = _PyCode_CODE(code) + code->_co_firsttraceable; + f->f_frame->instr_ptr = _PyCode_CODE(code) + code->_co_firsttraceable + 1; assert(!_PyFrame_IsIncomplete(f->f_frame)); Py_DECREF(func); _PyObject_GC_TRACK(f); @@ -1105,7 +1103,7 @@ _PyFrame_OpAlreadyRan(_PyInterpreterFrame *frame, int opcode, int oparg) assert(_PyOpcode_Deopt[opcode] == opcode); int check_oparg = 0; for (_Py_CODEUNIT *instruction = _PyCode_CODE(_PyFrame_GetCode(frame)); - instruction < frame->prev_instr; instruction++) + instruction < frame->instr_ptr; instruction++) { int check_opcode = _PyOpcode_Deopt[instruction->op.code]; check_oparg |= instruction->op.arg; @@ -1147,7 +1145,7 @@ frame_init_get_vars(_PyInterpreterFrame *frame) frame->localsplus[offset + i] = Py_NewRef(o); } // COPY_FREE_VARS doesn't have inline CACHEs, either: - frame->prev_instr = _PyCode_CODE(_PyFrame_GetCode(frame)); + frame->instr_ptr = _PyCode_CODE(_PyFrame_GetCode(frame)); } @@ -1352,11 +1350,11 @@ PyFrame_GetVarString(PyFrameObject *frame, const char *name) int PyFrame_FastToLocalsWithError(PyFrameObject *f) { - assert(!_PyFrame_IsIncomplete(f->f_frame)); if (f == NULL) { PyErr_BadInternalCall(); return -1; } + assert(!_PyFrame_IsIncomplete(f->f_frame)); int err = _PyFrame_FastToLocalsWithError(f->f_frame); if (err == 0) { f->f_fast_as_locals = 1; @@ -1454,7 +1452,7 @@ void PyFrame_LocalsToFast(PyFrameObject *f, int clear) { assert(!_PyFrame_IsIncomplete(f->f_frame)); - if (f && f->f_fast_as_locals && _PyFrame_GetState(f) != FRAME_CLEARED) { + if (f && f->f_fast_as_locals && !frame_is_cleared(f)) { _PyFrame_LocalsToFast(f->f_frame, clear); f->f_fast_as_locals = 0; } diff --git a/Objects/funcobject.c b/Objects/funcobject.c index 8c0bface3ac710..2620dc69bfd79b 100644 --- a/Objects/funcobject.c +++ b/Objects/funcobject.c @@ -3,13 +3,11 @@ #include "Python.h" #include "pycore_ceval.h" // _PyEval_BuiltinsFromGlobals() -#include "pycore_code.h" // _Py_next_func_version +#include "pycore_modsupport.h" // _PyArg_NoKeywords() #include "pycore_object.h" // _PyObject_GC_UNTRACK() #include "pycore_pyerrors.h" // _PyErr_Occurred() -static PyObject* func_repr(PyFunctionObject *op); - static const char * func_event_name(PyFunction_WatchEvent event) { switch (event) { @@ -35,21 +33,9 @@ notify_func_watchers(PyInterpreterState *interp, PyFunction_WatchEvent event, // callback must be non-null if the watcher bit is set assert(cb != NULL); if (cb(event, func, new_value) < 0) { - // Don't risk resurrecting the func if an unraisablehook keeps a - // reference; pass a string as context. - PyObject *context = NULL; - PyObject *repr = func_repr(func); - if (repr != NULL) { - context = PyUnicode_FromFormat( - "%s watcher callback for %U", - func_event_name(event), repr); - Py_DECREF(repr); - } - if (context == NULL) { - context = Py_NewRef(Py_None); - } - PyErr_WriteUnraisable(context); - Py_DECREF(context); + PyErr_FormatUnraisable( + "Exception ignored in %s watcher callback for function %U at %p", + func_event_name(event), func->func_qualname, func); } } i++; @@ -106,8 +92,8 @@ PyFunction_ClearWatcher(int watcher_id) PyFunctionObject * _PyFunction_FromConstructor(PyFrameConstructor *constr) { - PyObject *module = Py_XNewRef(PyDict_GetItemWithError(constr->fc_globals, &_Py_ID(__name__))); - if (!module && PyErr_Occurred()) { + PyObject *module; + if (PyDict_GetItemRef(constr->fc_globals, &_Py_ID(__name__), &module) < 0) { return NULL; } @@ -172,12 +158,11 @@ PyFunction_NewWithQualName(PyObject *code, PyObject *globals, PyObject *qualname Py_INCREF(doc); // __module__: Use globals['__name__'] if it exists, or NULL. - PyObject *module = PyDict_GetItemWithError(globals, &_Py_ID(__name__)); + PyObject *module; PyObject *builtins = NULL; - if (module == NULL && _PyErr_Occurred(tstate)) { + if (PyDict_GetItemRef(globals, &_Py_ID(__name__), &module) < 0) { goto error; } - Py_XINCREF(module); builtins = _PyEval_BuiltinsFromGlobals(tstate, globals); // borrowed ref if (builtins == NULL) { @@ -223,7 +208,79 @@ PyFunction_NewWithQualName(PyObject *code, PyObject *globals, PyObject *qualname return NULL; } -uint32_t _PyFunction_GetVersionForCurrentState(PyFunctionObject *func) +/* +Function versions +----------------- + +Function versions are used to detect when a function object has been +updated, invalidating inline cache data used by the `CALL` bytecode +(notably `CALL_PY_EXACT_ARGS` and a few other `CALL` specializations). + +They are also used by the Tier 2 superblock creation code to find +the function being called (and from there the code object). + +How does a function's `func_version` field get initialized? + +- `PyFunction_New` and friends initialize it to 0. +- The `MAKE_FUNCTION` instruction sets it from the code's `co_version`. +- It is reset to 0 when various attributes like `__code__` are set. +- A new version is allocated by `_PyFunction_GetVersionForCurrentState` + when the specializer needs a version and the version is 0. + +The latter allocates versions using a counter in the interpreter state; +when the counter wraps around to 0, no more versions are allocated. +There is one other special case: functions with a non-standard +`vectorcall` field are not given a version. + +When the function version is 0, the `CALL` bytecode is not specialized. + +Code object versions +-------------------- + +So where to code objects get their `co_version`? +There is a per-interpreter counter, `next_func_version`. +This is initialized to 1 when the interpreter is created. + +Code objects get a new `co_version` allocated from this counter upon +creation. Since code objects are nominally immutable, `co_version` can +not be invalidated. The only way it can be 0 is when 2**32 or more +code objects have been created during the process's lifetime. +(The counter isn't reset by `fork()`, extending the lifetime.) +*/ + +void +_PyFunction_SetVersion(PyFunctionObject *func, uint32_t version) +{ + PyInterpreterState *interp = _PyInterpreterState_GET(); + if (func->func_version != 0) { + PyFunctionObject **slot = + interp->func_state.func_version_cache + + (func->func_version % FUNC_VERSION_CACHE_SIZE); + if (*slot == func) { + *slot = NULL; + } + } + func->func_version = version; + if (version != 0) { + interp->func_state.func_version_cache[ + version % FUNC_VERSION_CACHE_SIZE] = func; + } +} + +PyFunctionObject * +_PyFunction_LookupByVersion(uint32_t version) +{ + PyInterpreterState *interp = _PyInterpreterState_GET(); + PyFunctionObject *func = interp->func_state.func_version_cache[ + version % FUNC_VERSION_CACHE_SIZE]; + if (func != NULL && func->func_version == version) { + return func; + } + return NULL; +} + +uint32_t +_PyFunction_GetVersionForCurrentState(PyFunctionObject *func) { if (func->func_version != 0) { return func->func_version; @@ -236,7 +293,7 @@ uint32_t _PyFunction_GetVersionForCurrentState(PyFunctionObject *func) return 0; } uint32_t v = interp->func_state.next_version++; - func->func_version = v; + _PyFunction_SetVersion(func, v); return v; } @@ -304,7 +361,7 @@ PyFunction_SetDefaults(PyObject *op, PyObject *defaults) } handle_func_event(PyFunction_EVENT_MODIFY_DEFAULTS, (PyFunctionObject *) op, defaults); - ((PyFunctionObject *)op)->func_version = 0; + _PyFunction_SetVersion((PyFunctionObject *)op, 0); Py_XSETREF(((PyFunctionObject *)op)->func_defaults, defaults); return 0; } @@ -313,7 +370,7 @@ void PyFunction_SetVectorcall(PyFunctionObject *func, vectorcallfunc vectorcall) { assert(func != NULL); - func->func_version = 0; + _PyFunction_SetVersion(func, 0); func->vectorcall = vectorcall; } @@ -346,7 +403,7 @@ PyFunction_SetKwDefaults(PyObject *op, PyObject *defaults) } handle_func_event(PyFunction_EVENT_MODIFY_KWDEFAULTS, (PyFunctionObject *) op, defaults); - ((PyFunctionObject *)op)->func_version = 0; + _PyFunction_SetVersion((PyFunctionObject *)op, 0); Py_XSETREF(((PyFunctionObject *)op)->func_kwdefaults, defaults); return 0; } @@ -379,7 +436,7 @@ PyFunction_SetClosure(PyObject *op, PyObject *closure) Py_TYPE(closure)->tp_name); return -1; } - ((PyFunctionObject *)op)->func_version = 0; + _PyFunction_SetVersion((PyFunctionObject *)op, 0); Py_XSETREF(((PyFunctionObject *)op)->func_closure, closure); return 0; } @@ -441,7 +498,7 @@ PyFunction_SetAnnotations(PyObject *op, PyObject *annotations) "non-dict annotations"); return -1; } - ((PyFunctionObject *)op)->func_version = 0; + _PyFunction_SetVersion((PyFunctionObject *)op, 0); Py_XSETREF(((PyFunctionObject *)op)->func_annotations, annotations); return 0; } @@ -499,8 +556,22 @@ func_set_code(PyFunctionObject *op, PyObject *value, void *Py_UNUSED(ignored)) nclosure, nfree); return -1; } + + PyObject *func_code = PyFunction_GET_CODE(op); + int old_flags = ((PyCodeObject *)func_code)->co_flags; + int new_flags = ((PyCodeObject *)value)->co_flags; + int mask = CO_GENERATOR | CO_COROUTINE | CO_ASYNC_GENERATOR; + if ((old_flags & mask) != (new_flags & mask)) { + if (PyErr_Warn(PyExc_DeprecationWarning, + "Assigning a code object of non-matching type is deprecated " + "(e.g., from a generator to a plain function)") < 0) + { + return -1; + } + } + handle_func_event(PyFunction_EVENT_MODIFY_CODE, op, value); - op->func_version = 0; + _PyFunction_SetVersion(op, 0); Py_XSETREF(op->func_code, Py_NewRef(value)); return 0; } @@ -580,7 +651,7 @@ func_set_defaults(PyFunctionObject *op, PyObject *value, void *Py_UNUSED(ignored } handle_func_event(PyFunction_EVENT_MODIFY_DEFAULTS, op, value); - op->func_version = 0; + _PyFunction_SetVersion(op, 0); Py_XSETREF(op->func_defaults, Py_XNewRef(value)); return 0; } @@ -621,7 +692,7 @@ func_set_kwdefaults(PyFunctionObject *op, PyObject *value, void *Py_UNUSED(ignor } handle_func_event(PyFunction_EVENT_MODIFY_KWDEFAULTS, op, value); - op->func_version = 0; + _PyFunction_SetVersion(op, 0); Py_XSETREF(op->func_kwdefaults, Py_XNewRef(value)); return 0; } @@ -651,7 +722,7 @@ func_set_annotations(PyFunctionObject *op, PyObject *value, void *Py_UNUSED(igno "__annotations__ must be set to a dict object"); return -1; } - op->func_version = 0; + _PyFunction_SetVersion(op, 0); Py_XSETREF(op->func_annotations, Py_XNewRef(value)); return 0; } @@ -738,14 +809,17 @@ function.__new__ as func_new a tuple that specifies the default argument values closure: object = None a tuple that supplies the bindings for free variables + kwdefaults: object = None + a dictionary that specifies the default keyword argument values Create a function object. [clinic start generated code]*/ static PyObject * func_new_impl(PyTypeObject *type, PyCodeObject *code, PyObject *globals, - PyObject *name, PyObject *defaults, PyObject *closure) -/*[clinic end generated code: output=99c6d9da3a24e3be input=93611752fc2daf11]*/ + PyObject *name, PyObject *defaults, PyObject *closure, + PyObject *kwdefaults) +/*[clinic end generated code: output=de72f4c22ac57144 input=20c9c9f04ad2d3f2]*/ { PyFunctionObject *newfunc; Py_ssize_t nclosure; @@ -772,6 +846,11 @@ func_new_impl(PyTypeObject *type, PyCodeObject *code, PyObject *globals, return NULL; } } + if (kwdefaults != Py_None && !PyDict_Check(kwdefaults)) { + PyErr_SetString(PyExc_TypeError, + "arg 6 (kwdefaults) must be None or dict"); + return NULL; + } /* check that the closure is well-formed */ nclosure = closure == Py_None ? 0 : PyTuple_GET_SIZE(closure); @@ -808,6 +887,9 @@ func_new_impl(PyTypeObject *type, PyCodeObject *code, PyObject *globals, if (closure != Py_None) { newfunc->func_closure = Py_NewRef(closure); } + if (kwdefaults != Py_None) { + newfunc->func_kwdefaults = Py_NewRef(kwdefaults); + } return (PyObject *)newfunc; } @@ -815,7 +897,7 @@ func_new_impl(PyTypeObject *type, PyCodeObject *code, PyObject *globals, static int func_clear(PyFunctionObject *op) { - op->func_version = 0; + _PyFunction_SetVersion(op, 0); Py_CLEAR(op->func_globals); Py_CLEAR(op->func_builtins); Py_CLEAR(op->func_module); @@ -851,6 +933,7 @@ func_dealloc(PyFunctionObject *op) if (op->func_weakreflist != NULL) { PyObject_ClearWeakRefs((PyObject *) op); } + _PyFunction_SetVersion(op, 0); (void)func_clear(op); // These aren't cleared by func_clear(). Py_DECREF(op->func_code); @@ -1037,10 +1120,6 @@ cm_descr_get(PyObject *self, PyObject *obj, PyObject *type) } if (type == NULL) type = (PyObject *)(Py_TYPE(obj)); - if (Py_TYPE(cm->cm_callable)->tp_descr_get != NULL) { - return Py_TYPE(cm->cm_callable)->tp_descr_get(cm->cm_callable, type, - type); - } return PyMethod_New(cm->cm_callable, type); } @@ -1095,7 +1174,8 @@ cm_repr(classmethod *cm) } PyDoc_STRVAR(classmethod_doc, -"classmethod(function) -> method\n\ +"classmethod(function, /)\n\ +--\n\ \n\ Convert a function to be a class method.\n\ \n\ @@ -1290,7 +1370,8 @@ sm_repr(staticmethod *sm) } PyDoc_STRVAR(staticmethod_doc, -"staticmethod(function) -> method\n\ +"staticmethod(function, /)\n\ +--\n\ \n\ Convert a function to be a static method.\n\ \n\ diff --git a/Objects/genericaliasobject.c b/Objects/genericaliasobject.c index df8873454aeb36..c045d495e85526 100644 --- a/Objects/genericaliasobject.c +++ b/Objects/genericaliasobject.c @@ -1,6 +1,8 @@ // types.GenericAlias -- used to represent e.g. list[int]. #include "Python.h" +#include "pycore_ceval.h" // _PyEval_GetBuiltin() +#include "pycore_modsupport.h" // _PyArg_NoKeywords() #include "pycore_object.h" #include "pycore_unionobject.h" // _Py_union_type_or, _PyGenericAlias_Check @@ -54,8 +56,7 @@ ga_repr_item(_PyUnicodeWriter *writer, PyObject *p) PyObject *qualname = NULL; PyObject *module = NULL; PyObject *r = NULL; - PyObject *tmp; - int err; + int rc; if (p == Py_Ellipsis) { // The Ellipsis object @@ -63,19 +64,14 @@ ga_repr_item(_PyUnicodeWriter *writer, PyObject *p) goto done; } - if (PyObject_GetOptionalAttr(p, &_Py_ID(__origin__), &tmp) < 0) { - goto done; + if ((rc = PyObject_HasAttrWithError(p, &_Py_ID(__origin__))) > 0 && + (rc = PyObject_HasAttrWithError(p, &_Py_ID(__args__))) > 0) + { + // It looks like a GenericAlias + goto use_repr; } - if (tmp != NULL) { - Py_DECREF(tmp); - if (PyObject_GetOptionalAttr(p, &_Py_ID(__args__), &tmp) < 0) { - goto done; - } - if (tmp != NULL) { - Py_DECREF(tmp); - // It looks like a GenericAlias - goto use_repr; - } + if (rc < 0) { + goto done; } if (PyObject_GetOptionalAttr(p, &_Py_ID(__qualname__), &qualname) < 0) { @@ -112,13 +108,13 @@ ga_repr_item(_PyUnicodeWriter *writer, PyObject *p) Py_XDECREF(module); if (r == NULL) { // error if any of the above PyObject_Repr/PyUnicode_From* fail - err = -1; + rc = -1; } else { - err = _PyUnicodeWriter_WriteStr(writer, r); + rc = _PyUnicodeWriter_WriteStr(writer, r); Py_DECREF(r); } - return err; + return rc; } static int @@ -252,18 +248,17 @@ _Py_make_parameters(PyObject *args) Py_ssize_t iparam = 0; for (Py_ssize_t iarg = 0; iarg < nargs; iarg++) { PyObject *t = PyTuple_GET_ITEM(args, iarg); - PyObject *subst; // We don't want __parameters__ descriptor of a bare Python class. if (PyType_Check(t)) { continue; } - if (PyObject_GetOptionalAttr(t, &_Py_ID(__typing_subst__), &subst) < 0) { + int rc = PyObject_HasAttrWithError(t, &_Py_ID(__typing_subst__)); + if (rc < 0) { Py_DECREF(parameters); return NULL; } - if (subst) { + if (rc) { iparam += tuple_add(parameters, iparam, t); - Py_DECREF(subst); } else { PyObject *subparams; @@ -626,6 +621,7 @@ ga_vectorcall(PyObject *self, PyObject *const *args, static const char* const attr_exceptions[] = { "__class__", + "__bases__", "__origin__", "__args__", "__unpacked__", @@ -812,7 +808,7 @@ ga_unpacked_tuple_args(PyObject *self, void *unused) } static PyGetSetDef ga_properties[] = { - {"__parameters__", ga_parameters, (setter)NULL, "Type variables in the GenericAlias.", NULL}, + {"__parameters__", ga_parameters, (setter)NULL, PyDoc_STR("Type variables in the GenericAlias."), NULL}, {"__typing_unpacked_tuple_args__", ga_unpacked_tuple_args, (setter)NULL, NULL}, {0} }; diff --git a/Objects/genobject.c b/Objects/genobject.c index 65782be182cd71..f03919c75d70a5 100644 --- a/Objects/genobject.c +++ b/Objects/genobject.c @@ -6,13 +6,14 @@ #include "pycore_call.h" // _PyObject_CallNoArgs() #include "pycore_ceval.h" // _PyEval_EvalFrame() #include "pycore_frame.h" // _PyInterpreterFrame +#include "pycore_gc.h" // _PyGC_CLEAR_FINALIZED() #include "pycore_genobject.h" // struct _Py_async_gen_state +#include "pycore_modsupport.h" // _PyArg_CheckPositional() #include "pycore_object.h" // _PyObject_GC_UNTRACK() +#include "pycore_opcode_utils.h" // RESUME_AFTER_YIELD_FROM #include "pycore_pyerrors.h" // _PyErr_ClearExcState() #include "pycore_pystate.h" // _PyThreadState_GET() -#include "opcode.h" // SEND -#include "frameobject.h" // _PyInterpreterFrame_GetLine #include "pystats.h" static PyObject *gen_close(PyGenObject *, PyObject *); @@ -40,19 +41,12 @@ PyGen_GetCode(PyGenObject *gen) { return res; } -static inline int -exc_state_traverse(_PyErr_StackItem *exc_state, visitproc visit, void *arg) -{ - Py_VISIT(exc_state->exc_value); - return 0; -} - static int gen_traverse(PyGenObject *gen, visitproc visit, void *arg) { Py_VISIT(gen->gi_name); Py_VISIT(gen->gi_qualname); - if (gen->gi_frame_state < FRAME_CLEARED) { + if (gen->gi_frame_state != FRAME_CLEARED) { _PyInterpreterFrame *frame = (_PyInterpreterFrame *)(gen->gi_iframe); assert(frame->frame_obj == NULL || frame->frame_obj->f_frame->owner == FRAME_OWNED_BY_GENERATOR); @@ -63,7 +57,8 @@ gen_traverse(PyGenObject *gen, visitproc visit, void *arg) } /* No need to visit cr_origin, because it's just tuples/str/int, so can't participate in a reference cycle. */ - return exc_state_traverse(&gen->gi_exc_state, visit, arg); + Py_VISIT(gen->gi_exc_state.exc_value); + return 0; } void @@ -71,7 +66,7 @@ _PyGen_Finalize(PyObject *self) { PyGenObject *gen = (PyGenObject *)self; - if (gen->gi_frame_state >= FRAME_COMPLETED) { + if (FRAME_STATE_FINISHED(gen->gi_frame_state)) { /* Generator isn't paused, so no need to close */ return; } @@ -144,7 +139,7 @@ gen_dealloc(PyGenObject *gen) and GC_Del. */ Py_CLEAR(((PyAsyncGenObject*)gen)->ag_origin_or_finalizer); } - if (gen->gi_frame_state < FRAME_CLEARED) { + if (gen->gi_frame_state != FRAME_CLEARED) { _PyInterpreterFrame *frame = (_PyInterpreterFrame *)gen->gi_iframe; gen->gi_frame_state = FRAME_CLEARED; frame->previous = NULL; @@ -168,7 +163,6 @@ gen_send_ex2(PyGenObject *gen, PyObject *arg, PyObject **presult, { PyThreadState *tstate = _PyThreadState_GET(); _PyInterpreterFrame *frame = (_PyInterpreterFrame *)gen->gi_iframe; - PyObject *result; *presult = NULL; if (gen->gi_frame_state == FRAME_CREATED && arg && arg != Py_None) { @@ -195,7 +189,7 @@ gen_send_ex2(PyGenObject *gen, PyObject *arg, PyObject **presult, PyErr_SetString(PyExc_ValueError, msg); return PYGEN_ERROR; } - if (gen->gi_frame_state >= FRAME_COMPLETED) { + if (FRAME_STATE_FINISHED(gen->gi_frame_state)) { if (PyCoro_CheckExact(gen) && !closing) { /* `gen` is an exhausted coroutine: raise an error, except when called from gen_close(), which should @@ -213,10 +207,12 @@ gen_send_ex2(PyGenObject *gen, PyObject *arg, PyObject **presult, return PYGEN_ERROR; } - assert(gen->gi_frame_state < FRAME_EXECUTING); + assert((gen->gi_frame_state == FRAME_CREATED) || + FRAME_STATE_SUSPENDED(gen->gi_frame_state)); + /* Push arg onto the frame's value stack */ - result = arg ? arg : Py_None; - _PyFrame_StackPush(frame, Py_NewRef(result)); + PyObject *arg_obj = arg ? arg : Py_None; + _PyFrame_StackPush(frame, Py_NewRef(arg_obj)); _PyErr_StackItem *prev_exc_info = tstate->exc_info; gen->gi_exc_state.previous_item = prev_exc_info; @@ -229,7 +225,7 @@ gen_send_ex2(PyGenObject *gen, PyObject *arg, PyObject **presult, gen->gi_frame_state = FRAME_EXECUTING; EVAL_CALL_STAT_INC(EVAL_CALL_GENERATOR); - result = _PyEval_EvalFrame(tstate, frame, exc); + PyObject *result = _PyEval_EvalFrame(tstate, frame, exc); assert(tstate->exc_info == prev_exc_info); assert(gen->gi_exc_state.previous_item == NULL); assert(gen->gi_frame_state != FRAME_EXECUTING); @@ -238,7 +234,7 @@ gen_send_ex2(PyGenObject *gen, PyObject *arg, PyObject **presult, /* If the generator just returned (as opposed to yielding), signal * that the generator is exhausted. */ if (result) { - if (gen->gi_frame_state == FRAME_SUSPENDED) { + if (FRAME_STATE_SUSPENDED(gen->gi_frame_state)) { *presult = result; return PYGEN_NEXT; } @@ -333,56 +329,40 @@ gen_close_iter(PyObject *yf) static inline bool is_resume(_Py_CODEUNIT *instr) { - return instr->op.code == RESUME || instr->op.code == INSTRUMENTED_RESUME; -} - -static inline bool -is_yield(_Py_CODEUNIT *instr) -{ - return instr->op.code == YIELD_VALUE || instr->op.code == INSTRUMENTED_YIELD_VALUE; + return ( + instr->op.code == RESUME || + instr->op.code == RESUME_CHECK || + instr->op.code == INSTRUMENTED_RESUME + ); } PyObject * _PyGen_yf(PyGenObject *gen) { - PyObject *yf = NULL; - - if (gen->gi_frame_state < FRAME_CLEARED) { + if (gen->gi_frame_state == FRAME_SUSPENDED_YIELD_FROM) { _PyInterpreterFrame *frame = (_PyInterpreterFrame *)gen->gi_iframe; - - if (gen->gi_frame_state == FRAME_CREATED) { - /* Return immediately if the frame didn't start yet. SEND - always come after LOAD_CONST: a code object should not start - with SEND */ - assert(_PyCode_CODE(_PyGen_GetCode(gen))[0].op.code != SEND); - return NULL; - } - _Py_CODEUNIT next = frame->prev_instr[1]; - if (!is_resume(&next) || next.op.arg < 2) - { - /* Not in a yield from */ - return NULL; - } - yf = Py_NewRef(_PyFrame_StackPeek(frame)); + assert(is_resume(frame->instr_ptr)); + assert((frame->instr_ptr->op.arg & RESUME_OPARG_LOCATION_MASK) >= RESUME_AFTER_YIELD_FROM); + return Py_NewRef(_PyFrame_StackPeek(frame)); } - - return yf; + return NULL; } static PyObject * gen_close(PyGenObject *gen, PyObject *args) { PyObject *retval; - PyObject *yf = _PyGen_yf(gen); int err = 0; + if (gen->gi_frame_state == FRAME_CREATED) { gen->gi_frame_state = FRAME_COMPLETED; Py_RETURN_NONE; } - if (gen->gi_frame_state >= FRAME_COMPLETED) { + if (FRAME_STATE_FINISHED(gen->gi_frame_state)) { Py_RETURN_NONE; } + PyObject *yf = _PyGen_yf(gen); if (yf) { PyFrameState state = gen->gi_frame_state; gen->gi_frame_state = FRAME_EXECUTING; @@ -391,16 +371,15 @@ gen_close(PyGenObject *gen, PyObject *args) Py_DECREF(yf); } _PyInterpreterFrame *frame = (_PyInterpreterFrame *)gen->gi_iframe; - /* It is possible for the previous instruction to not be a - * YIELD_VALUE if the debugger has changed the lineno. */ - if (err == 0 && is_yield(frame->prev_instr)) { - assert(is_resume(frame->prev_instr + 1)); - int exception_handler_depth = frame->prev_instr[0].op.code; - assert(exception_handler_depth > 0); + if (is_resume(frame->instr_ptr)) { /* We can safely ignore the outermost try block - * as it automatically generated to handle + * as it is automatically generated to handle * StopIteration. */ - if (exception_handler_depth == 1) { + int oparg = frame->instr_ptr->op.arg; + if (oparg & RESUME_OPARG_DEPTH1_MASK) { + // RESUME after YIELD_VALUE and exception depth is 1 + assert((oparg & RESUME_OPARG_LOCATION_MASK) != RESUME_AT_FUNC_START); + gen->gi_frame_state = FRAME_COMPLETED; Py_RETURN_NONE; } } @@ -476,9 +455,9 @@ _gen_throw(PyGenObject *gen, int close_on_genexit, will be reported correctly to the user. */ /* XXX We should probably be updating the current frame somewhere in ceval.c. */ - _PyInterpreterFrame *prev = tstate->cframe->current_frame; + _PyInterpreterFrame *prev = tstate->current_frame; frame->previous = prev; - tstate->cframe->current_frame = frame; + tstate->current_frame = frame; /* Close the generator that we are currently iterating with 'yield from' or awaiting on with 'await'. */ PyFrameState state = gen->gi_frame_state; @@ -486,7 +465,7 @@ _gen_throw(PyGenObject *gen, int close_on_genexit, ret = _gen_throw((PyGenObject *)yf, close_on_genexit, typ, val, tb); gen->gi_frame_state = state; - tstate->cframe->current_frame = prev; + tstate->current_frame = prev; frame->previous = NULL; } else { /* `yf` is an iterator or a coroutine-like object. */ @@ -745,7 +724,7 @@ gen_getrunning(PyGenObject *gen, void *Py_UNUSED(ignored)) static PyObject * gen_getsuspended(PyGenObject *gen, void *Py_UNUSED(ignored)) { - return PyBool_FromLong(gen->gi_frame_state == FRAME_SUSPENDED); + return PyBool_FromLong(FRAME_STATE_SUSPENDED(gen->gi_frame_state)); } static PyObject * @@ -754,7 +733,7 @@ _gen_getframe(PyGenObject *gen, const char *const name) if (PySys_Audit("object.__getattr__", "Os", gen, name) < 0) { return NULL; } - if (gen->gi_frame_state == FRAME_CLEARED) { + if (FRAME_STATE_FINISHED(gen->gi_frame_state)) { Py_RETURN_NONE; } return _Py_XNewRef((PyObject *)_PyFrame_GetFrameObject((_PyInterpreterFrame *)gen->gi_iframe)); @@ -938,7 +917,7 @@ _Py_MakeCoro(PyFunctionObject *func) if (origin_depth == 0) { ((PyCoroObject *)coro)->cr_origin_or_finalizer = NULL; } else { - _PyInterpreterFrame *frame = tstate->cframe->current_frame; + _PyInterpreterFrame *frame = tstate->current_frame; assert(frame); assert(_PyFrame_IsIncomplete(frame)); frame = _PyFrame_GetFirstComplete(frame->previous); @@ -1100,7 +1079,7 @@ coro_get_cr_await(PyCoroObject *coro, void *Py_UNUSED(ignored)) static PyObject * cr_getsuspended(PyCoroObject *coro, void *Py_UNUSED(ignored)) { - if (coro->cr_frame_state == FRAME_SUSPENDED) { + if (FRAME_STATE_SUSPENDED(coro->cr_frame_state)) { Py_RETURN_TRUE; } Py_RETURN_FALSE; @@ -1537,7 +1516,7 @@ ag_getcode(PyGenObject *gen, void *Py_UNUSED(ignored)) static PyObject * ag_getsuspended(PyAsyncGenObject *ag, void *Py_UNUSED(ignored)) { - if (ag->ag_frame_state == FRAME_SUSPENDED) { + if (FRAME_STATE_SUSPENDED(ag->ag_frame_state)) { Py_RETURN_TRUE; } Py_RETURN_FALSE; @@ -1761,6 +1740,7 @@ async_gen_asend_dealloc(PyAsyncGenASend *o) #endif if (state->asend_numfree < _PyAsyncGen_MAXFREELIST) { assert(PyAsyncGenASend_CheckExact(o)); + _PyGC_CLEAR_FINALIZED((PyObject *)o); state->asend_freelist[state->asend_numfree++] = o; } else @@ -2109,7 +2089,7 @@ async_gen_athrow_send(PyAsyncGenAThrow *o, PyObject *arg) return NULL; } - if (gen->gi_frame_state >= FRAME_COMPLETED) { + if (FRAME_STATE_FINISHED(gen->gi_frame_state)) { o->agt_state = AWAITABLE_STATE_CLOSED; PyErr_SetNone(PyExc_StopIteration); return NULL; diff --git a/Objects/iterobject.c b/Objects/iterobject.c index cf7cb8af52a274..135ced9ea1f268 100644 --- a/Objects/iterobject.c +++ b/Objects/iterobject.c @@ -3,6 +3,7 @@ #include "Python.h" #include "pycore_abstract.h" // _PyObject_HasLen() #include "pycore_call.h" // _PyObject_CallNoArgs() +#include "pycore_ceval.h" // _PyEval_GetBuiltin() #include "pycore_object.h" // _PyObject_GC_TRACK() typedef struct { diff --git a/Objects/listobject.c b/Objects/listobject.c index c0da9dd916851a..c05c4fdff83883 100644 --- a/Objects/listobject.c +++ b/Objects/listobject.c @@ -2,6 +2,7 @@ #include "Python.h" #include "pycore_abstract.h" // _PyIndex_Check() +#include "pycore_ceval.h" // _PyEval_GetBuiltin() #include "pycore_interp.h" // PyInterpreterState.list #include "pycore_list.h" // struct _Py_list_state, _PyListIterObject #include "pycore_long.h" // _PyLong_DigitCount @@ -23,8 +24,9 @@ _Py_DECLARE_STR(list_err, "list index out of range"); static struct _Py_list_state * get_list_state(void) { - PyInterpreterState *interp = _PyInterpreterState_GET(); - return &interp->list; + _PyFreeListState *state = _PyFreeListState_GET(); + assert(state != NULL); + return &state->list_state; } #endif @@ -119,26 +121,25 @@ list_preallocate_exact(PyListObject *self, Py_ssize_t size) } void -_PyList_ClearFreeList(PyInterpreterState *interp) +_PyList_ClearFreeList(_PyFreeListState *freelist_state, int is_finalization) { #if PyList_MAXFREELIST > 0 - struct _Py_list_state *state = &interp->list; - while (state->numfree) { + struct _Py_list_state *state = &freelist_state->list_state; + while (state->numfree > 0) { PyListObject *op = state->free_list[--state->numfree]; assert(PyList_CheckExact(op)); PyObject_GC_Del(op); } + if (is_finalization) { + state->numfree = -1; + } #endif } void -_PyList_Fini(PyInterpreterState *interp) +_PyList_Fini(_PyFreeListState *state) { - _PyList_ClearFreeList(interp); -#if defined(Py_DEBUG) && PyList_MAXFREELIST > 0 - struct _Py_list_state *state = &interp->list; - state->numfree = -1; -#endif + _PyList_ClearFreeList(state, 1); } /* Print summary info about the state of the optimized allocator */ @@ -342,8 +343,9 @@ PyList_Append(PyObject *op, PyObject *newitem) /* Methods */ static void -list_dealloc(PyListObject *op) +list_dealloc(PyObject *self) { + PyListObject *op = (PyListObject *)self; Py_ssize_t i; PyObject_GC_UnTrack(op); Py_TRASHCAN_BEGIN(op, list_dealloc) @@ -377,8 +379,9 @@ list_dealloc(PyListObject *op) } static PyObject * -list_repr(PyListObject *v) +list_repr(PyObject *self) { + PyListObject *v = (PyListObject *)self; Py_ssize_t i; PyObject *s; _PyUnicodeWriter writer; @@ -433,14 +436,15 @@ list_repr(PyListObject *v) } static Py_ssize_t -list_length(PyListObject *a) +list_length(PyObject *a) { return Py_SIZE(a); } static int -list_contains(PyListObject *a, PyObject *el) +list_contains(PyObject *aa, PyObject *el) { + PyListObject *a = (PyListObject *)aa; PyObject *item; Py_ssize_t i; int cmp; @@ -455,8 +459,9 @@ list_contains(PyListObject *a, PyObject *el) } static PyObject * -list_item(PyListObject *a, Py_ssize_t i) +list_item(PyObject *aa, Py_ssize_t i) { + PyListObject *a = (PyListObject *)aa; if (!valid_index(i, Py_SIZE(a))) { PyErr_SetObject(PyExc_IndexError, &_Py_STR(list_err)); return NULL; @@ -511,8 +516,9 @@ PyList_GetSlice(PyObject *a, Py_ssize_t ilow, Py_ssize_t ihigh) } static PyObject * -list_concat(PyListObject *a, PyObject *bb) +list_concat(PyObject *aa, PyObject *bb) { + PyListObject *a = (PyListObject *)aa; Py_ssize_t size; Py_ssize_t i; PyObject **src, **dest; @@ -551,8 +557,9 @@ list_concat(PyListObject *a, PyObject *bb) } static PyObject * -list_repeat(PyListObject *a, Py_ssize_t n) +list_repeat(PyObject *aa, Py_ssize_t n) { + PyListObject *a = (PyListObject *)aa; const Py_ssize_t input_size = Py_SIZE(a); if (input_size == 0 || n <= 0) return PyList_New(0); @@ -591,26 +598,33 @@ list_repeat(PyListObject *a, Py_ssize_t n) return (PyObject *) np; } -static int -_list_clear(PyListObject *a) +static void +list_clear(PyListObject *a) { - Py_ssize_t i; - PyObject **item = a->ob_item; - if (item != NULL) { - /* Because XDECREF can recursively invoke operations on - this list, we make it empty first. */ - i = Py_SIZE(a); - Py_SET_SIZE(a, 0); - a->ob_item = NULL; - a->allocated = 0; - while (--i >= 0) { - Py_XDECREF(item[i]); - } - PyMem_Free(item); + PyObject **items = a->ob_item; + if (items == NULL) { + return; } - /* Never fails; the return value can be ignored. - Note that there is no guarantee that the list is actually empty - at this point, because XDECREF may have populated it again! */ + + /* Because XDECREF can recursively invoke operations on + this list, we make it empty first. */ + Py_ssize_t i = Py_SIZE(a); + Py_SET_SIZE(a, 0); + a->ob_item = NULL; + a->allocated = 0; + while (--i >= 0) { + Py_XDECREF(items[i]); + } + PyMem_Free(items); + + // Note that there is no guarantee that the list is actually empty + // at this point, because XDECREF may have populated it indirectly again! +} + +static int +list_clear_slot(PyObject *self) +{ + list_clear((PyListObject *)self); return 0; } @@ -674,7 +688,8 @@ list_ass_slice(PyListObject *a, Py_ssize_t ilow, Py_ssize_t ihigh, PyObject *v) d = n - norig; if (Py_SIZE(a) + d == 0) { Py_XDECREF(v_as_SF); - return _list_clear(a); + list_clear(a); + return 0; } item = a->ob_item; /* recycle the items that we are about to remove */ @@ -736,15 +751,16 @@ PyList_SetSlice(PyObject *a, Py_ssize_t ilow, Py_ssize_t ihigh, PyObject *v) } static PyObject * -list_inplace_repeat(PyListObject *self, Py_ssize_t n) +list_inplace_repeat(PyObject *_self, Py_ssize_t n) { + PyListObject *self = (PyListObject *)_self; Py_ssize_t input_size = PyList_GET_SIZE(self); if (input_size == 0 || n == 1) { return Py_NewRef(self); } if (n < 1) { - (void)_list_clear(self); + list_clear(self); return Py_NewRef(self); } @@ -767,8 +783,9 @@ list_inplace_repeat(PyListObject *self, Py_ssize_t n) } static int -list_ass_item(PyListObject *a, Py_ssize_t i, PyObject *v) +list_ass_item(PyObject *aa, Py_ssize_t i, PyObject *v) { + PyListObject *a = (PyListObject *)aa; if (!valid_index(i, Py_SIZE(a))) { PyErr_SetString(PyExc_IndexError, "list assignment index out of range"); @@ -781,6 +798,7 @@ list_ass_item(PyListObject *a, Py_ssize_t i, PyObject *v) } /*[clinic input] +@critical_section list.insert index: Py_ssize_t @@ -792,7 +810,7 @@ Insert object before index. static PyObject * list_insert_impl(PyListObject *self, Py_ssize_t index, PyObject *object) -/*[clinic end generated code: output=7f35e32f60c8cb78 input=858514cf894c7eab]*/ +/*[clinic end generated code: output=7f35e32f60c8cb78 input=b1987ca998a4ae2d]*/ { if (ins1(self, index, object) == 0) Py_RETURN_NONE; @@ -800,16 +818,17 @@ list_insert_impl(PyListObject *self, Py_ssize_t index, PyObject *object) } /*[clinic input] -list.clear +@critical_section +list.clear as py_list_clear Remove all items from list. [clinic start generated code]*/ static PyObject * -list_clear_impl(PyListObject *self) -/*[clinic end generated code: output=67a1896c01f74362 input=ca3c1646856742f6]*/ +py_list_clear_impl(PyListObject *self) +/*[clinic end generated code: output=83726743807e3518 input=e285b7f09051a9ba]*/ { - _list_clear(self); + list_clear(self); Py_RETURN_NONE; } @@ -845,83 +864,61 @@ list_append(PyListObject *self, PyObject *object) Py_RETURN_NONE; } -/*[clinic input] -list.extend - - iterable: object - / - -Extend list by appending elements from the iterable. -[clinic start generated code]*/ - -static PyObject * -list_extend(PyListObject *self, PyObject *iterable) -/*[clinic end generated code: output=630fb3bca0c8e789 input=9ec5ba3a81be3a4d]*/ +static int +list_extend_fast(PyListObject *self, PyObject *iterable) { - PyObject *it; /* iter(v) */ - Py_ssize_t m; /* size of self */ - Py_ssize_t n; /* guess for size of iterable */ - Py_ssize_t i; - PyObject *(*iternext)(PyObject *); + Py_ssize_t n = PySequence_Fast_GET_SIZE(iterable); + if (n == 0) { + /* short circuit when iterable is empty */ + return 0; + } - /* Special cases: - 1) lists and tuples which can use PySequence_Fast ops - 2) extending self to self requires making a copy first - */ - if (PyList_CheckExact(iterable) || PyTuple_CheckExact(iterable) || - (PyObject *)self == iterable) { - PyObject **src, **dest; - iterable = PySequence_Fast(iterable, "argument must be iterable"); - if (!iterable) - return NULL; - n = PySequence_Fast_GET_SIZE(iterable); - if (n == 0) { - /* short circuit when iterable is empty */ - Py_DECREF(iterable); - Py_RETURN_NONE; - } - m = Py_SIZE(self); - /* It should not be possible to allocate a list large enough to cause - an overflow on any relevant platform */ - assert(m < PY_SSIZE_T_MAX - n); - if (self->ob_item == NULL) { - if (list_preallocate_exact(self, n) < 0) { - return NULL; - } - Py_SET_SIZE(self, n); - } - else if (list_resize(self, m + n) < 0) { - Py_DECREF(iterable); - return NULL; - } - /* note that we may still have self == iterable here for the - * situation a.extend(a), but the following code works - * in that case too. Just make sure to resize self - * before calling PySequence_Fast_ITEMS. - */ - /* populate the end of self with iterable's items */ - src = PySequence_Fast_ITEMS(iterable); - dest = self->ob_item + m; - for (i = 0; i < n; i++) { - PyObject *o = src[i]; - dest[i] = Py_NewRef(o); + Py_ssize_t m = Py_SIZE(self); + // It should not be possible to allocate a list large enough to cause + // an overflow on any relevant platform. + assert(m < PY_SSIZE_T_MAX - n); + if (self->ob_item == NULL) { + if (list_preallocate_exact(self, n) < 0) { + return -1; } - Py_DECREF(iterable); - Py_RETURN_NONE; + Py_SET_SIZE(self, n); + } + else if (list_resize(self, m + n) < 0) { + return -1; } - it = PyObject_GetIter(iterable); - if (it == NULL) - return NULL; - iternext = *Py_TYPE(it)->tp_iternext; + // note that we may still have self == iterable here for the + // situation a.extend(a), but the following code works + // in that case too. Just make sure to resize self + // before calling PySequence_Fast_ITEMS. + // + // populate the end of self with iterable's items. + PyObject **src = PySequence_Fast_ITEMS(iterable); + PyObject **dest = self->ob_item + m; + for (Py_ssize_t i = 0; i < n; i++) { + PyObject *o = src[i]; + dest[i] = Py_NewRef(o); + } + return 0; +} + +static int +list_extend_iter(PyListObject *self, PyObject *iterable) +{ + PyObject *it = PyObject_GetIter(iterable); + if (it == NULL) { + return -1; + } + PyObject *(*iternext)(PyObject *) = *Py_TYPE(it)->tp_iternext; /* Guess a result list size. */ - n = PyObject_LengthHint(iterable, 8); + Py_ssize_t n = PyObject_LengthHint(iterable, 8); if (n < 0) { Py_DECREF(it); - return NULL; + return -1; } - m = Py_SIZE(self); + + Py_ssize_t m = Py_SIZE(self); if (m > PY_SSIZE_T_MAX - n) { /* m + n overflowed; on the chance that n lied, and there really * is enough room, ignore it. If n was telling the truth, we'll @@ -934,8 +931,10 @@ list_extend(PyListObject *self, PyObject *iterable) } else { /* Make room. */ - if (list_resize(self, m + n) < 0) + if (list_resize(self, m + n) < 0) { goto error; + } + /* Make the list sane again. */ Py_SET_SIZE(self, m); } @@ -952,11 +951,11 @@ list_extend(PyListObject *self, PyObject *iterable) } break; } + if (Py_SIZE(self) < self->allocated) { - /* steals ref */ Py_ssize_t len = Py_SIZE(self); + PyList_SET_ITEM(self, len, item); // steals item ref Py_SET_SIZE(self, len + 1); - PyList_SET_ITEM(self, len, item); } else { if (_PyList_AppendTakeRef(self, item) < 0) @@ -971,32 +970,101 @@ list_extend(PyListObject *self, PyObject *iterable) } Py_DECREF(it); - Py_RETURN_NONE; + return 0; error: Py_DECREF(it); - return NULL; + return -1; +} + + +static int +list_extend(PyListObject *self, PyObject *iterable) +{ + // Special cases: + // 1) lists and tuples which can use PySequence_Fast ops + // 2) extending self to self requires making a copy first + if (PyList_CheckExact(iterable) + || PyTuple_CheckExact(iterable) + || (PyObject *)self == iterable) + { + iterable = PySequence_Fast(iterable, "argument must be iterable"); + if (!iterable) { + return -1; + } + + int res = list_extend_fast(self, iterable); + Py_DECREF(iterable); + return res; + } + else { + return list_extend_iter(self, iterable); + } } + PyObject * _PyList_Extend(PyListObject *self, PyObject *iterable) { - return list_extend(self, iterable); + if (list_extend(self, iterable) < 0) { + return NULL; + } + Py_RETURN_NONE; } + +/*[clinic input] +list.extend as py_list_extend + + iterable: object + / + +Extend list by appending elements from the iterable. +[clinic start generated code]*/ + static PyObject * -list_inplace_concat(PyListObject *self, PyObject *other) +py_list_extend(PyListObject *self, PyObject *iterable) +/*[clinic end generated code: output=b8e0bff0ceae2abd input=9a8376a8633ed3ba]*/ { - PyObject *result; + return _PyList_Extend(self, iterable); +} + + +int +PyList_Extend(PyObject *self, PyObject *iterable) +{ + if (!PyList_Check(self)) { + PyErr_BadInternalCall(); + return -1; + } + return list_extend((PyListObject*)self, iterable); +} + - result = list_extend(self, other); - if (result == NULL) - return result; - Py_DECREF(result); +int +PyList_Clear(PyObject *self) +{ + if (!PyList_Check(self)) { + PyErr_BadInternalCall(); + return -1; + } + list_clear((PyListObject*)self); + return 0; +} + + +static PyObject * +list_inplace_concat(PyObject *_self, PyObject *other) +{ + PyListObject *self = (PyListObject *)_self; + if (list_extend(self, other) < 0) { + return NULL; + } return Py_NewRef(self); } /*[clinic input] +@critical_section list.pop index: Py_ssize_t = -1 @@ -1009,7 +1077,7 @@ Raises IndexError if list is empty or index is out of range. static PyObject * list_pop_impl(PyListObject *self, Py_ssize_t index) -/*[clinic end generated code: output=6bd69dcb3f17eca8 input=b83675976f329e6f]*/ +/*[clinic end generated code: output=6bd69dcb3f17eca8 input=c269141068ae4b8f]*/ { PyObject *v; int status; @@ -1031,7 +1099,8 @@ list_pop_impl(PyListObject *self, Py_ssize_t index) const Py_ssize_t size_after_pop = Py_SIZE(self) - 1; if (size_after_pop == 0) { Py_INCREF(v); - status = _list_clear(self); + list_clear(self); + status = 0; } else { if ((size_after_pop - index) > 0) { @@ -2500,7 +2569,7 @@ list_sort_impl(PyListObject *self, PyObject *keyfunc, int reverse) self->ob_item = saved_ob_item; self->allocated = saved_allocated; if (final_ob_item != NULL) { - /* we cannot use _list_clear() for this because it does not + /* we cannot use list_clear() for this because it does not guarantee that the list is really empty when it returns */ while (--i >= 0) { Py_XDECREF(final_ob_item[i]); @@ -2527,6 +2596,7 @@ PyList_Sort(PyObject *v) } /*[clinic input] +@critical_section list.reverse Reverse *IN PLACE*. @@ -2534,7 +2604,7 @@ Reverse *IN PLACE*. static PyObject * list_reverse_impl(PyListObject *self) -/*[clinic end generated code: output=482544fc451abea9 input=eefd4c3ae1bc9887]*/ +/*[clinic end generated code: output=482544fc451abea9 input=04ac8e0c6a66e4d9]*/ { if (Py_SIZE(self) > 1) reverse_slice(self->ob_item, self->ob_item + Py_SIZE(self)); @@ -2664,6 +2734,7 @@ list_count(PyListObject *self, PyObject *value) } /*[clinic input] +@critical_section list.remove value: object @@ -2675,8 +2746,8 @@ Raises ValueError if the value is not present. [clinic start generated code]*/ static PyObject * -list_remove(PyListObject *self, PyObject *value) -/*[clinic end generated code: output=f087e1951a5e30d1 input=2dc2ba5bb2fb1f82]*/ +list_remove_impl(PyListObject *self, PyObject *value) +/*[clinic end generated code: output=b9b76a6633b18778 input=26c813dbb95aa93b]*/ { Py_ssize_t i; @@ -2699,8 +2770,9 @@ list_remove(PyListObject *self, PyObject *value) } static int -list_traverse(PyListObject *o, visitproc visit, void *arg) +list_traverse(PyObject *self, visitproc visit, void *arg) { + PyListObject *o = (PyListObject *)self; Py_ssize_t i; for (i = Py_SIZE(o); --i >= 0; ) @@ -2788,13 +2860,12 @@ list___init___impl(PyListObject *self, PyObject *iterable) /* Empty previous contents */ if (self->ob_item != NULL) { - (void)_list_clear(self); + list_clear(self); } if (iterable != NULL) { - PyObject *rv = list_extend(self, iterable); - if (rv == NULL) + if (list_extend(self, iterable) < 0) { return -1; - Py_DECREF(rv); + } } return 0; } @@ -2841,18 +2912,18 @@ list___sizeof___impl(PyListObject *self) } static PyObject *list_iter(PyObject *seq); -static PyObject *list_subscript(PyListObject*, PyObject*); +static PyObject *list_subscript(PyObject*, PyObject*); static PyMethodDef list_methods[] = { - {"__getitem__", (PyCFunction)list_subscript, METH_O|METH_COEXIST, + {"__getitem__", list_subscript, METH_O|METH_COEXIST, PyDoc_STR("__getitem__($self, index, /)\n--\n\nReturn self[index].")}, LIST___REVERSED___METHODDEF LIST___SIZEOF___METHODDEF - LIST_CLEAR_METHODDEF + PY_LIST_CLEAR_METHODDEF LIST_COPY_METHODDEF LIST_APPEND_METHODDEF LIST_INSERT_METHODDEF - LIST_EXTEND_METHODDEF + PY_LIST_EXTEND_METHODDEF LIST_POP_METHODDEF LIST_REMOVE_METHODDEF LIST_INDEX_METHODDEF @@ -2864,21 +2935,22 @@ static PyMethodDef list_methods[] = { }; static PySequenceMethods list_as_sequence = { - (lenfunc)list_length, /* sq_length */ - (binaryfunc)list_concat, /* sq_concat */ - (ssizeargfunc)list_repeat, /* sq_repeat */ - (ssizeargfunc)list_item, /* sq_item */ + list_length, /* sq_length */ + list_concat, /* sq_concat */ + list_repeat, /* sq_repeat */ + list_item, /* sq_item */ 0, /* sq_slice */ - (ssizeobjargproc)list_ass_item, /* sq_ass_item */ + list_ass_item, /* sq_ass_item */ 0, /* sq_ass_slice */ - (objobjproc)list_contains, /* sq_contains */ - (binaryfunc)list_inplace_concat, /* sq_inplace_concat */ - (ssizeargfunc)list_inplace_repeat, /* sq_inplace_repeat */ + list_contains, /* sq_contains */ + list_inplace_concat, /* sq_inplace_concat */ + list_inplace_repeat, /* sq_inplace_repeat */ }; static PyObject * -list_subscript(PyListObject* self, PyObject* item) +list_subscript(PyObject* _self, PyObject* item) { + PyListObject* self = (PyListObject*)_self; if (_PyIndex_Check(item)) { Py_ssize_t i; i = PyNumber_AsSsize_t(item, PyExc_IndexError); @@ -2886,7 +2958,7 @@ list_subscript(PyListObject* self, PyObject* item) return NULL; if (i < 0) i += PyList_GET_SIZE(self); - return list_item(self, i); + return list_item((PyObject *)self, i); } else if (PySlice_Check(item)) { Py_ssize_t start, stop, step, slicelength, i; @@ -2931,15 +3003,16 @@ list_subscript(PyListObject* self, PyObject* item) } static int -list_ass_subscript(PyListObject* self, PyObject* item, PyObject* value) +list_ass_subscript(PyObject* _self, PyObject* item, PyObject* value) { + PyListObject *self = (PyListObject *)_self; if (_PyIndex_Check(item)) { Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError); if (i == -1 && PyErr_Occurred()) return -1; if (i < 0) i += PyList_GET_SIZE(self); - return list_ass_item(self, i, value); + return list_ass_item((PyObject *)self, i, value); } else if (PySlice_Check(item)) { Py_ssize_t start, stop, step, slicelength; @@ -3093,9 +3166,9 @@ list_ass_subscript(PyListObject* self, PyObject* item, PyObject* value) } static PyMappingMethods list_as_mapping = { - (lenfunc)list_length, - (binaryfunc)list_subscript, - (objobjargproc)list_ass_subscript + list_length, + list_subscript, + list_ass_subscript }; PyTypeObject PyList_Type = { @@ -3103,12 +3176,12 @@ PyTypeObject PyList_Type = { "list", sizeof(PyListObject), 0, - (destructor)list_dealloc, /* tp_dealloc */ + list_dealloc, /* tp_dealloc */ 0, /* tp_vectorcall_offset */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_as_async */ - (reprfunc)list_repr, /* tp_repr */ + list_repr, /* tp_repr */ 0, /* tp_as_number */ &list_as_sequence, /* tp_as_sequence */ &list_as_mapping, /* tp_as_mapping */ @@ -3122,8 +3195,8 @@ PyTypeObject PyList_Type = { Py_TPFLAGS_BASETYPE | Py_TPFLAGS_LIST_SUBCLASS | _Py_TPFLAGS_MATCH_SELF | Py_TPFLAGS_SEQUENCE, /* tp_flags */ list___init____doc__, /* tp_doc */ - (traverseproc)list_traverse, /* tp_traverse */ - (inquiry)_list_clear, /* tp_clear */ + list_traverse, /* tp_traverse */ + list_clear_slot, /* tp_clear */ list_richcompare, /* tp_richcompare */ 0, /* tp_weaklistoffset */ list_iter, /* tp_iter */ @@ -3145,22 +3218,22 @@ PyTypeObject PyList_Type = { /*********************** List Iterator **************************/ -static void listiter_dealloc(_PyListIterObject *); -static int listiter_traverse(_PyListIterObject *, visitproc, void *); -static PyObject *listiter_next(_PyListIterObject *); -static PyObject *listiter_len(_PyListIterObject *, PyObject *); +static void listiter_dealloc(PyObject *); +static int listiter_traverse(PyObject *, visitproc, void *); +static PyObject *listiter_next(PyObject *); +static PyObject *listiter_len(PyObject *, PyObject *); static PyObject *listiter_reduce_general(void *_it, int forward); -static PyObject *listiter_reduce(_PyListIterObject *, PyObject *); -static PyObject *listiter_setstate(_PyListIterObject *, PyObject *state); +static PyObject *listiter_reduce(PyObject *, PyObject *); +static PyObject *listiter_setstate(PyObject *, PyObject *state); PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it))."); PyDoc_STRVAR(reduce_doc, "Return state information for pickling."); PyDoc_STRVAR(setstate_doc, "Set state information for unpickling."); static PyMethodDef listiter_methods[] = { - {"__length_hint__", (PyCFunction)listiter_len, METH_NOARGS, length_hint_doc}, - {"__reduce__", (PyCFunction)listiter_reduce, METH_NOARGS, reduce_doc}, - {"__setstate__", (PyCFunction)listiter_setstate, METH_O, setstate_doc}, + {"__length_hint__", listiter_len, METH_NOARGS, length_hint_doc}, + {"__reduce__", listiter_reduce, METH_NOARGS, reduce_doc}, + {"__setstate__", listiter_setstate, METH_O, setstate_doc}, {NULL, NULL} /* sentinel */ }; @@ -3170,7 +3243,7 @@ PyTypeObject PyListIter_Type = { sizeof(_PyListIterObject), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ - (destructor)listiter_dealloc, /* tp_dealloc */ + listiter_dealloc, /* tp_dealloc */ 0, /* tp_vectorcall_offset */ 0, /* tp_getattr */ 0, /* tp_setattr */ @@ -3187,12 +3260,12 @@ PyTypeObject PyListIter_Type = { 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */ 0, /* tp_doc */ - (traverseproc)listiter_traverse, /* tp_traverse */ + listiter_traverse, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ PyObject_SelfIter, /* tp_iter */ - (iternextfunc)listiter_next, /* tp_iternext */ + listiter_next, /* tp_iternext */ listiter_methods, /* tp_methods */ 0, /* tp_members */ }; @@ -3217,23 +3290,25 @@ list_iter(PyObject *seq) } static void -listiter_dealloc(_PyListIterObject *it) +listiter_dealloc(PyObject *self) { + _PyListIterObject *it = (_PyListIterObject *)self; _PyObject_GC_UNTRACK(it); Py_XDECREF(it->it_seq); PyObject_GC_Del(it); } static int -listiter_traverse(_PyListIterObject *it, visitproc visit, void *arg) +listiter_traverse(PyObject *it, visitproc visit, void *arg) { - Py_VISIT(it->it_seq); + Py_VISIT(((_PyListIterObject *)it)->it_seq); return 0; } static PyObject * -listiter_next(_PyListIterObject *it) +listiter_next(PyObject *self) { + _PyListIterObject *it = (_PyListIterObject *)self; PyListObject *seq; PyObject *item; @@ -3255,8 +3330,9 @@ listiter_next(_PyListIterObject *it) } static PyObject * -listiter_len(_PyListIterObject *it, PyObject *Py_UNUSED(ignored)) +listiter_len(PyObject *self, PyObject *Py_UNUSED(ignored)) { + _PyListIterObject *it = (_PyListIterObject *)self; Py_ssize_t len; if (it->it_seq) { len = PyList_GET_SIZE(it->it_seq) - it->it_index; @@ -3267,14 +3343,15 @@ listiter_len(_PyListIterObject *it, PyObject *Py_UNUSED(ignored)) } static PyObject * -listiter_reduce(_PyListIterObject *it, PyObject *Py_UNUSED(ignored)) +listiter_reduce(PyObject *it, PyObject *Py_UNUSED(ignored)) { return listiter_reduce_general(it, 1); } static PyObject * -listiter_setstate(_PyListIterObject *it, PyObject *state) +listiter_setstate(PyObject *self, PyObject *state) { + _PyListIterObject *it = (_PyListIterObject *)self; Py_ssize_t index = PyLong_AsSsize_t(state); if (index == -1 && PyErr_Occurred()) return NULL; @@ -3296,17 +3373,17 @@ typedef struct { PyListObject *it_seq; /* Set to NULL when iterator is exhausted */ } listreviterobject; -static void listreviter_dealloc(listreviterobject *); -static int listreviter_traverse(listreviterobject *, visitproc, void *); -static PyObject *listreviter_next(listreviterobject *); -static PyObject *listreviter_len(listreviterobject *, PyObject *); -static PyObject *listreviter_reduce(listreviterobject *, PyObject *); -static PyObject *listreviter_setstate(listreviterobject *, PyObject *); +static void listreviter_dealloc(PyObject *); +static int listreviter_traverse(PyObject *, visitproc, void *); +static PyObject *listreviter_next(PyObject *); +static PyObject *listreviter_len(PyObject *, PyObject *); +static PyObject *listreviter_reduce(PyObject *, PyObject *); +static PyObject *listreviter_setstate(PyObject *, PyObject *); static PyMethodDef listreviter_methods[] = { - {"__length_hint__", (PyCFunction)listreviter_len, METH_NOARGS, length_hint_doc}, - {"__reduce__", (PyCFunction)listreviter_reduce, METH_NOARGS, reduce_doc}, - {"__setstate__", (PyCFunction)listreviter_setstate, METH_O, setstate_doc}, + {"__length_hint__", listreviter_len, METH_NOARGS, length_hint_doc}, + {"__reduce__", listreviter_reduce, METH_NOARGS, reduce_doc}, + {"__setstate__", listreviter_setstate, METH_O, setstate_doc}, {NULL, NULL} /* sentinel */ }; @@ -3316,7 +3393,7 @@ PyTypeObject PyListRevIter_Type = { sizeof(listreviterobject), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ - (destructor)listreviter_dealloc, /* tp_dealloc */ + listreviter_dealloc, /* tp_dealloc */ 0, /* tp_vectorcall_offset */ 0, /* tp_getattr */ 0, /* tp_setattr */ @@ -3333,12 +3410,12 @@ PyTypeObject PyListRevIter_Type = { 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */ 0, /* tp_doc */ - (traverseproc)listreviter_traverse, /* tp_traverse */ + listreviter_traverse, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ PyObject_SelfIter, /* tp_iter */ - (iternextfunc)listreviter_next, /* tp_iternext */ + listreviter_next, /* tp_iternext */ listreviter_methods, /* tp_methods */ 0, }; @@ -3366,23 +3443,25 @@ list___reversed___impl(PyListObject *self) } static void -listreviter_dealloc(listreviterobject *it) +listreviter_dealloc(PyObject *self) { + listreviterobject *it = (listreviterobject *)self; PyObject_GC_UnTrack(it); Py_XDECREF(it->it_seq); PyObject_GC_Del(it); } static int -listreviter_traverse(listreviterobject *it, visitproc visit, void *arg) +listreviter_traverse(PyObject *it, visitproc visit, void *arg) { - Py_VISIT(it->it_seq); + Py_VISIT(((listreviterobject *)it)->it_seq); return 0; } static PyObject * -listreviter_next(listreviterobject *it) +listreviter_next(PyObject *self) { + listreviterobject *it = (listreviterobject *)self; PyObject *item; Py_ssize_t index; PyListObject *seq; @@ -3407,8 +3486,9 @@ listreviter_next(listreviterobject *it) } static PyObject * -listreviter_len(listreviterobject *it, PyObject *Py_UNUSED(ignored)) +listreviter_len(PyObject *self, PyObject *Py_UNUSED(ignored)) { + listreviterobject *it = (listreviterobject *)self; Py_ssize_t len = it->it_index + 1; if (it->it_seq == NULL || PyList_GET_SIZE(it->it_seq) < len) len = 0; @@ -3416,14 +3496,15 @@ listreviter_len(listreviterobject *it, PyObject *Py_UNUSED(ignored)) } static PyObject * -listreviter_reduce(listreviterobject *it, PyObject *Py_UNUSED(ignored)) +listreviter_reduce(PyObject *it, PyObject *Py_UNUSED(ignored)) { return listiter_reduce_general(it, 0); } static PyObject * -listreviter_setstate(listreviterobject *it, PyObject *state) +listreviter_setstate(PyObject *self, PyObject *state) { + listreviterobject *it = (listreviterobject *)self; Py_ssize_t index = PyLong_AsSsize_t(state); if (index == -1 && PyErr_Occurred()) return NULL; diff --git a/Objects/lnotab_notes.txt b/Objects/lnotab_notes.txt index 362b87a86a481f..0f3599340318f0 100644 --- a/Objects/lnotab_notes.txt +++ b/Objects/lnotab_notes.txt @@ -1,4 +1,7 @@ -Description of the internal format of the line number table +Description of the internal format of the line number table in Python 3.10 +and earlier. + +(For 3.11 onwards, see Objects/locations.md) Conceptually, the line number table consists of a sequence of triples: start-offset (inclusive), end-offset (exclusive), line-number. @@ -57,7 +60,7 @@ Final form: Iterating over the table. ------------------------- -For the `co_lines` attribute we want to emit the full form, omitting the (350, 360, No line number) and empty entries. +For the `co_lines` method we want to emit the full form, omitting the (350, 360, No line number) and empty entries. The code is as follows: diff --git a/Objects/longobject.c b/Objects/longobject.c index 354cba9d6d800f..fae70dd13bb18a 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -5,15 +5,14 @@ #include "Python.h" #include "pycore_bitutils.h" // _Py_popcount32() #include "pycore_initconfig.h" // _PyStatus_OK() +#include "pycore_call.h" // _PyObject_MakeTpCall #include "pycore_long.h" // _Py_SmallInts #include "pycore_object.h" // _PyObject_Init() #include "pycore_runtime.h" // _PY_NSMALLPOSINTS #include "pycore_structseq.h" // _PyStructSequence_FiniBuiltin() -#include -#include -#include -#include // abs() +#include // DBL_MANT_DIG +#include // offsetof #include "clinic/longobject.c.h" /*[clinic input] @@ -549,7 +548,7 @@ PyLong_AsLong(PyObject *obj) method. Return -1 and set an error if overflow occurs. */ int -_PyLong_AsInt(PyObject *obj) +PyLong_AsInt(PyObject *obj) { int overflow; long result = PyLong_AsLongAndOverflow(obj, &overflow); @@ -6154,6 +6153,29 @@ int_is_integer_impl(PyObject *self) Py_RETURN_TRUE; } +static PyObject * +long_vectorcall(PyObject *type, PyObject * const*args, + size_t nargsf, PyObject *kwnames) +{ + Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); + if (kwnames != NULL) { + PyThreadState *tstate = PyThreadState_GET(); + return _PyObject_MakeTpCall(tstate, type, args, nargs, kwnames); + } + switch (nargs) { + case 0: + return _PyLong_GetZero(); + case 1: + return PyNumber_Long(args[0]); + case 2: + return long_new_impl(_PyType_CAST(type), args[0], args[1]); + default: + return PyErr_Format(PyExc_TypeError, + "int expected at most 2 argument%s, got %zd", + nargs); + } +} + static PyMethodDef long_methods[] = { {"conjugate", long_long_meth, METH_NOARGS, "Returns self, the complex conjugate of any int."}, @@ -6291,6 +6313,7 @@ PyTypeObject PyLong_Type = { 0, /* tp_alloc */ long_new, /* tp_new */ PyObject_Free, /* tp_free */ + .tp_vectorcall = long_vectorcall, }; static PyTypeObject Int_InfoType; diff --git a/Objects/memoryobject.c b/Objects/memoryobject.c index b0168044d9f85a..6a38952fdc1f3b 100644 --- a/Objects/memoryobject.c +++ b/Objects/memoryobject.c @@ -12,6 +12,7 @@ #include "Python.h" #include "pycore_abstract.h" // _PyIndex_Check() +#include "pycore_memoryobject.h" // _PyManagedBuffer_Type #include "pycore_object.h" // _PyObject_GC_UNTRACK() #include "pycore_strhex.h" // _Py_strhex_with_sep() #include // offsetof() @@ -118,8 +119,9 @@ mbuf_release(_PyManagedBufferObject *self) } static void -mbuf_dealloc(_PyManagedBufferObject *self) +mbuf_dealloc(PyObject *_self) { + _PyManagedBufferObject *self = (_PyManagedBufferObject *)_self; assert(self->exports == 0); mbuf_release(self); if (self->flags&_Py_MANAGED_BUFFER_FREE_FORMAT) @@ -128,15 +130,17 @@ mbuf_dealloc(_PyManagedBufferObject *self) } static int -mbuf_traverse(_PyManagedBufferObject *self, visitproc visit, void *arg) +mbuf_traverse(PyObject *_self, visitproc visit, void *arg) { + _PyManagedBufferObject *self = (_PyManagedBufferObject *)_self; Py_VISIT(self->master.obj); return 0; } static int -mbuf_clear(_PyManagedBufferObject *self) +mbuf_clear(PyObject *_self) { + _PyManagedBufferObject *self = (_PyManagedBufferObject *)_self; assert(self->exports >= 0); mbuf_release(self); return 0; @@ -147,7 +151,7 @@ PyTypeObject _PyManagedBuffer_Type = { "managedbuffer", sizeof(_PyManagedBufferObject), 0, - (destructor)mbuf_dealloc, /* tp_dealloc */ + mbuf_dealloc, /* tp_dealloc */ 0, /* tp_vectorcall_offset */ 0, /* tp_getattr */ 0, /* tp_setattr */ @@ -164,8 +168,8 @@ PyTypeObject _PyManagedBuffer_Type = { 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ 0, /* tp_doc */ - (traverseproc)mbuf_traverse, /* tp_traverse */ - (inquiry)mbuf_clear /* tp_clear */ + mbuf_traverse, /* tp_traverse */ + mbuf_clear /* tp_clear */ }; @@ -1136,8 +1140,9 @@ memoryview_release_impl(PyMemoryViewObject *self) } static void -memory_dealloc(PyMemoryViewObject *self) +memory_dealloc(PyObject *_self) { + PyMemoryViewObject *self = (PyMemoryViewObject *)_self; assert(self->exports == 0); _PyObject_GC_UNTRACK(self); (void)_memory_release(self); @@ -1148,15 +1153,17 @@ memory_dealloc(PyMemoryViewObject *self) } static int -memory_traverse(PyMemoryViewObject *self, visitproc visit, void *arg) +memory_traverse(PyObject *_self, visitproc visit, void *arg) { + PyMemoryViewObject *self = (PyMemoryViewObject *)_self; Py_VISIT(self->mbuf); return 0; } static int -memory_clear(PyMemoryViewObject *self) +memory_clear(PyObject *_self) { + PyMemoryViewObject *self = (PyMemoryViewObject *)_self; (void)_memory_release(self); Py_CLEAR(self->mbuf); return 0; @@ -1509,8 +1516,9 @@ memoryview_toreadonly_impl(PyMemoryViewObject *self) /**************************************************************************/ static int -memory_getbuf(PyMemoryViewObject *self, Py_buffer *view, int flags) +memory_getbuf(PyObject *_self, Py_buffer *view, int flags) { + PyMemoryViewObject *self = (PyMemoryViewObject *)_self; Py_buffer *base = &self->view; int baseflags = self->flags; @@ -1588,8 +1596,9 @@ memory_getbuf(PyMemoryViewObject *self, Py_buffer *view, int flags) } static void -memory_releasebuf(PyMemoryViewObject *self, Py_buffer *view) +memory_releasebuf(PyObject *_self, Py_buffer *view) { + PyMemoryViewObject *self = (PyMemoryViewObject *)_self; self->exports--; return; /* PyBuffer_Release() decrements view->obj after this function returns. */ @@ -1597,8 +1606,8 @@ memory_releasebuf(PyMemoryViewObject *self, Py_buffer *view) /* Buffer methods */ static PyBufferProcs memory_as_buffer = { - (getbufferproc)memory_getbuf, /* bf_getbuffer */ - (releasebufferproc)memory_releasebuf, /* bf_releasebuffer */ + memory_getbuf, /* bf_getbuffer */ + memory_releasebuf, /* bf_releasebuffer */ }; @@ -2343,8 +2352,9 @@ memoryview_hex_impl(PyMemoryViewObject *self, PyObject *sep, } static PyObject * -memory_repr(PyMemoryViewObject *self) +memory_repr(PyObject *_self) { + PyMemoryViewObject *self = (PyMemoryViewObject *)_self; if (self->flags & _Py_MEMORYVIEW_RELEASED) return PyUnicode_FromFormat("", self); else @@ -2420,8 +2430,9 @@ ptr_from_tuple(const Py_buffer *view, PyObject *tup) with the type specified by view->format. Otherwise, the item is a sub-view. The function is used in memory_subscript() and memory_as_sequence. */ static PyObject * -memory_item(PyMemoryViewObject *self, Py_ssize_t index) +memory_item(PyObject *_self, Py_ssize_t index) { + PyMemoryViewObject *self = (PyMemoryViewObject *)_self; Py_buffer *view = &(self->view); const char *fmt; @@ -2545,8 +2556,9 @@ is_multiindex(PyObject *key) 0-d memoryview objects can be referenced using mv[...] or mv[()] but not with anything else. */ static PyObject * -memory_subscript(PyMemoryViewObject *self, PyObject *key) +memory_subscript(PyObject *_self, PyObject *key) { + PyMemoryViewObject *self = (PyMemoryViewObject *)_self; Py_buffer *view; view = &(self->view); @@ -2574,7 +2586,7 @@ memory_subscript(PyMemoryViewObject *self, PyObject *key) index = PyNumber_AsSsize_t(key, PyExc_IndexError); if (index == -1 && PyErr_Occurred()) return NULL; - return memory_item(self, index); + return memory_item((PyObject *)self, index); } else if (PySlice_Check(key)) { CHECK_RESTRICTED(self); @@ -2607,8 +2619,9 @@ memory_subscript(PyMemoryViewObject *self, PyObject *key) } static int -memory_ass_sub(PyMemoryViewObject *self, PyObject *key, PyObject *value) +memory_ass_sub(PyObject *_self, PyObject *key, PyObject *value) { + PyMemoryViewObject *self = (PyMemoryViewObject *)_self; Py_buffer *view = &(self->view); Py_buffer src; const char *fmt; @@ -2709,8 +2722,9 @@ memory_ass_sub(PyMemoryViewObject *self, PyObject *key, PyObject *value) } static Py_ssize_t -memory_length(PyMemoryViewObject *self) +memory_length(PyObject *_self) { + PyMemoryViewObject *self = (PyMemoryViewObject *)_self; CHECK_RELEASED_INT(self); if (self->view.ndim == 0) { PyErr_SetString(PyExc_TypeError, "0-dim memory has no length"); @@ -2721,17 +2735,17 @@ memory_length(PyMemoryViewObject *self) /* As mapping */ static PyMappingMethods memory_as_mapping = { - (lenfunc)memory_length, /* mp_length */ - (binaryfunc)memory_subscript, /* mp_subscript */ - (objobjargproc)memory_ass_sub, /* mp_ass_subscript */ + memory_length, /* mp_length */ + memory_subscript, /* mp_subscript */ + memory_ass_sub, /* mp_ass_subscript */ }; /* As sequence */ static PySequenceMethods memory_as_sequence = { - (lenfunc)memory_length, /* sq_length */ + memory_length, /* sq_length */ 0, /* sq_concat */ 0, /* sq_repeat */ - (ssizeargfunc)memory_item, /* sq_item */ + memory_item, /* sq_item */ }; @@ -3033,8 +3047,9 @@ memory_richcompare(PyObject *v, PyObject *w, int op) /**************************************************************************/ static Py_hash_t -memory_hash(PyMemoryViewObject *self) +memory_hash(PyObject *_self) { + PyMemoryViewObject *self = (PyMemoryViewObject *)_self; if (self->hash == -1) { Py_buffer *view = &self->view; char *mem = view->buf; @@ -3111,8 +3126,9 @@ _IntTupleFromSsizet(int len, Py_ssize_t *vals) } static PyObject * -memory_obj_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored)) +memory_obj_get(PyObject *_self, void *Py_UNUSED(ignored)) { + PyMemoryViewObject *self = (PyMemoryViewObject *)_self; Py_buffer *view = &self->view; CHECK_RELEASED(self); @@ -3123,78 +3139,89 @@ memory_obj_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored)) } static PyObject * -memory_nbytes_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored)) +memory_nbytes_get(PyObject *_self, void *Py_UNUSED(ignored)) { + PyMemoryViewObject *self = (PyMemoryViewObject *)_self; CHECK_RELEASED(self); return PyLong_FromSsize_t(self->view.len); } static PyObject * -memory_format_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored)) +memory_format_get(PyObject *_self, void *Py_UNUSED(ignored)) { + PyMemoryViewObject *self = (PyMemoryViewObject *)_self; CHECK_RELEASED(self); return PyUnicode_FromString(self->view.format); } static PyObject * -memory_itemsize_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored)) +memory_itemsize_get(PyObject *_self, void *Py_UNUSED(ignored)) { + PyMemoryViewObject *self = (PyMemoryViewObject *)_self; CHECK_RELEASED(self); return PyLong_FromSsize_t(self->view.itemsize); } static PyObject * -memory_shape_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored)) +memory_shape_get(PyObject *_self, void *Py_UNUSED(ignored)) { + PyMemoryViewObject *self = (PyMemoryViewObject *)_self; CHECK_RELEASED(self); return _IntTupleFromSsizet(self->view.ndim, self->view.shape); } static PyObject * -memory_strides_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored)) +memory_strides_get(PyObject *_self, void *Py_UNUSED(ignored)) { + PyMemoryViewObject *self = (PyMemoryViewObject *)_self; CHECK_RELEASED(self); return _IntTupleFromSsizet(self->view.ndim, self->view.strides); } static PyObject * -memory_suboffsets_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored)) +memory_suboffsets_get(PyObject *_self, void *Py_UNUSED(ignored)) { + PyMemoryViewObject *self = (PyMemoryViewObject *)_self; CHECK_RELEASED(self); return _IntTupleFromSsizet(self->view.ndim, self->view.suboffsets); } static PyObject * -memory_readonly_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored)) +memory_readonly_get(PyObject *_self, void *Py_UNUSED(ignored)) { + PyMemoryViewObject *self = (PyMemoryViewObject *)_self; CHECK_RELEASED(self); return PyBool_FromLong(self->view.readonly); } static PyObject * -memory_ndim_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored)) +memory_ndim_get(PyObject *_self, void *Py_UNUSED(ignored)) { + PyMemoryViewObject *self = (PyMemoryViewObject *)_self; CHECK_RELEASED(self); return PyLong_FromLong(self->view.ndim); } static PyObject * -memory_c_contiguous(PyMemoryViewObject *self, PyObject *dummy) +memory_c_contiguous(PyObject *_self, void *Py_UNUSED(ignored)) { + PyMemoryViewObject *self = (PyMemoryViewObject *)_self; CHECK_RELEASED(self); return PyBool_FromLong(MV_C_CONTIGUOUS(self->flags)); } static PyObject * -memory_f_contiguous(PyMemoryViewObject *self, PyObject *dummy) +memory_f_contiguous(PyObject *_self, void *Py_UNUSED(ignored)) { + PyMemoryViewObject *self = (PyMemoryViewObject *)_self; CHECK_RELEASED(self); return PyBool_FromLong(MV_F_CONTIGUOUS(self->flags)); } static PyObject * -memory_contiguous(PyMemoryViewObject *self, PyObject *dummy) +memory_contiguous(PyObject *_self, void *Py_UNUSED(ignored)) { + PyMemoryViewObject *self = (PyMemoryViewObject *)_self; CHECK_RELEASED(self); return PyBool_FromLong(MV_ANY_CONTIGUOUS(self->flags)); } @@ -3231,18 +3258,18 @@ PyDoc_STRVAR(memory_contiguous_doc, static PyGetSetDef memory_getsetlist[] = { - {"obj", (getter)memory_obj_get, NULL, memory_obj_doc}, - {"nbytes", (getter)memory_nbytes_get, NULL, memory_nbytes_doc}, - {"readonly", (getter)memory_readonly_get, NULL, memory_readonly_doc}, - {"itemsize", (getter)memory_itemsize_get, NULL, memory_itemsize_doc}, - {"format", (getter)memory_format_get, NULL, memory_format_doc}, - {"ndim", (getter)memory_ndim_get, NULL, memory_ndim_doc}, - {"shape", (getter)memory_shape_get, NULL, memory_shape_doc}, - {"strides", (getter)memory_strides_get, NULL, memory_strides_doc}, - {"suboffsets", (getter)memory_suboffsets_get, NULL, memory_suboffsets_doc}, - {"c_contiguous", (getter)memory_c_contiguous, NULL, memory_c_contiguous_doc}, - {"f_contiguous", (getter)memory_f_contiguous, NULL, memory_f_contiguous_doc}, - {"contiguous", (getter)memory_contiguous, NULL, memory_contiguous_doc}, + {"obj", memory_obj_get, NULL, memory_obj_doc}, + {"nbytes", memory_nbytes_get, NULL, memory_nbytes_doc}, + {"readonly", memory_readonly_get, NULL, memory_readonly_doc}, + {"itemsize", memory_itemsize_get, NULL, memory_itemsize_doc}, + {"format", memory_format_get, NULL, memory_format_doc}, + {"ndim", memory_ndim_get, NULL, memory_ndim_doc}, + {"shape", memory_shape_get, NULL, memory_shape_doc}, + {"strides", memory_strides_get, NULL, memory_strides_doc}, + {"suboffsets", memory_suboffsets_get, NULL, memory_suboffsets_doc}, + {"c_contiguous", memory_c_contiguous, NULL, memory_c_contiguous_doc}, + {"f_contiguous", memory_f_contiguous, NULL, memory_f_contiguous_doc}, + {"contiguous", memory_contiguous, NULL, memory_contiguous_doc}, {NULL, NULL, NULL, NULL}, }; @@ -3275,23 +3302,26 @@ typedef struct { } memoryiterobject; static void -memoryiter_dealloc(memoryiterobject *it) +memoryiter_dealloc(PyObject *self) { + memoryiterobject *it = (memoryiterobject *)self; _PyObject_GC_UNTRACK(it); Py_XDECREF(it->it_seq); PyObject_GC_Del(it); } static int -memoryiter_traverse(memoryiterobject *it, visitproc visit, void *arg) +memoryiter_traverse(PyObject *self, visitproc visit, void *arg) { + memoryiterobject *it = (memoryiterobject *)self; Py_VISIT(it->it_seq); return 0; } static PyObject * -memoryiter_next(memoryiterobject *it) +memoryiter_next(PyObject *self) { + memoryiterobject *it = (memoryiterobject *)self; PyMemoryViewObject *seq; seq = it->it_seq; if (seq == NULL) { @@ -3346,7 +3376,7 @@ memory_iter(PyObject *seq) return NULL; } it->it_fmt = fmt; - it->it_length = memory_length(obj); + it->it_length = memory_length((PyObject *)obj); it->it_index = 0; it->it_seq = (PyMemoryViewObject*)Py_NewRef(obj); _PyObject_GC_TRACK(it); @@ -3358,12 +3388,12 @@ PyTypeObject _PyMemoryIter_Type = { .tp_name = "memory_iterator", .tp_basicsize = sizeof(memoryiterobject), // methods - .tp_dealloc = (destructor)memoryiter_dealloc, + .tp_dealloc = memoryiter_dealloc, .tp_getattro = PyObject_GenericGetAttr, .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, - .tp_traverse = (traverseproc)memoryiter_traverse, + .tp_traverse = memoryiter_traverse, .tp_iter = PyObject_SelfIter, - .tp_iternext = (iternextfunc)memoryiter_next, + .tp_iternext = memoryiter_next, }; PyTypeObject PyMemoryView_Type = { @@ -3371,16 +3401,16 @@ PyTypeObject PyMemoryView_Type = { "memoryview", /* tp_name */ offsetof(PyMemoryViewObject, ob_array), /* tp_basicsize */ sizeof(Py_ssize_t), /* tp_itemsize */ - (destructor)memory_dealloc, /* tp_dealloc */ + memory_dealloc, /* tp_dealloc */ 0, /* tp_vectorcall_offset */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_as_async */ - (reprfunc)memory_repr, /* tp_repr */ + memory_repr, /* tp_repr */ 0, /* tp_as_number */ &memory_as_sequence, /* tp_as_sequence */ &memory_as_mapping, /* tp_as_mapping */ - (hashfunc)memory_hash, /* tp_hash */ + memory_hash, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ PyObject_GenericGetAttr, /* tp_getattro */ @@ -3389,8 +3419,8 @@ PyTypeObject PyMemoryView_Type = { Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_SEQUENCE, /* tp_flags */ memoryview__doc__, /* tp_doc */ - (traverseproc)memory_traverse, /* tp_traverse */ - (inquiry)memory_clear, /* tp_clear */ + memory_traverse, /* tp_traverse */ + memory_clear, /* tp_clear */ memory_richcompare, /* tp_richcompare */ offsetof(PyMemoryViewObject, weakreflist),/* tp_weaklistoffset */ memory_iter, /* tp_iter */ diff --git a/Objects/methodobject.c b/Objects/methodobject.c index 628d227ef33c39..b40b2821c3880d 100644 --- a/Objects/methodobject.c +++ b/Objects/methodobject.c @@ -192,7 +192,9 @@ static PyMethodDef meth_methods[] = { static PyObject * meth_get__text_signature__(PyCFunctionObject *m, void *closure) { - return _PyType_GetTextSignatureFromInternalDoc(m->m_ml->ml_name, m->m_ml->ml_doc); + return _PyType_GetTextSignatureFromInternalDoc(m->m_ml->ml_name, + m->m_ml->ml_doc, + m->m_ml->ml_flags); } static PyObject * @@ -551,10 +553,3 @@ cfunction_call(PyObject *func, PyObject *args, PyObject *kwargs) return _Py_CheckFunctionResult(tstate, func, result, NULL); } -#if defined(__EMSCRIPTEN__) && defined(PY_CALL_TRAMPOLINE) -#include - -EM_JS(PyObject*, _PyCFunctionWithKeywords_TrampolineCall, (PyCFunctionWithKeywords func, PyObject *self, PyObject *args, PyObject *kw), { - return wasmTable.get(func)(self, args, kw); -}); -#endif diff --git a/Objects/mimalloc/alloc-aligned.c b/Objects/mimalloc/alloc-aligned.c new file mode 100644 index 00000000000000..4c15f4043ec117 --- /dev/null +++ b/Objects/mimalloc/alloc-aligned.c @@ -0,0 +1,298 @@ +/* ---------------------------------------------------------------------------- +Copyright (c) 2018-2021, Microsoft Research, Daan Leijen +This is free software; you can redistribute it and/or modify it under the +terms of the MIT license. A copy of the license can be found in the file +"LICENSE" at the root of this distribution. +-----------------------------------------------------------------------------*/ + +#include "mimalloc.h" +#include "mimalloc/internal.h" +#include "mimalloc/prim.h" // mi_prim_get_default_heap + +#include // memset + +// ------------------------------------------------------ +// Aligned Allocation +// ------------------------------------------------------ + +// Fallback primitive aligned allocation -- split out for better codegen +static mi_decl_noinline void* mi_heap_malloc_zero_aligned_at_fallback(mi_heap_t* const heap, const size_t size, const size_t alignment, const size_t offset, const bool zero) mi_attr_noexcept +{ + mi_assert_internal(size <= PTRDIFF_MAX); + mi_assert_internal(alignment != 0 && _mi_is_power_of_two(alignment)); + + const uintptr_t align_mask = alignment - 1; // for any x, `(x & align_mask) == (x % alignment)` + const size_t padsize = size + MI_PADDING_SIZE; + + // use regular allocation if it is guaranteed to fit the alignment constraints + if (offset==0 && alignment<=padsize && padsize<=MI_MAX_ALIGN_GUARANTEE && (padsize&align_mask)==0) { + void* p = _mi_heap_malloc_zero(heap, size, zero); + mi_assert_internal(p == NULL || ((uintptr_t)p % alignment) == 0); + return p; + } + + void* p; + size_t oversize; + if mi_unlikely(alignment > MI_ALIGNMENT_MAX) { + // use OS allocation for very large alignment and allocate inside a huge page (dedicated segment with 1 page) + // This can support alignments >= MI_SEGMENT_SIZE by ensuring the object can be aligned at a point in the + // first (and single) page such that the segment info is `MI_SEGMENT_SIZE` bytes before it (so it can be found by aligning the pointer down) + if mi_unlikely(offset != 0) { + // todo: cannot support offset alignment for very large alignments yet + #if MI_DEBUG > 0 + _mi_error_message(EOVERFLOW, "aligned allocation with a very large alignment cannot be used with an alignment offset (size %zu, alignment %zu, offset %zu)\n", size, alignment, offset); + #endif + return NULL; + } + oversize = (size <= MI_SMALL_SIZE_MAX ? MI_SMALL_SIZE_MAX + 1 /* ensure we use generic malloc path */ : size); + p = _mi_heap_malloc_zero_ex(heap, oversize, false, alignment); // the page block size should be large enough to align in the single huge page block + // zero afterwards as only the area from the aligned_p may be committed! + if (p == NULL) return NULL; + } + else { + // otherwise over-allocate + oversize = size + alignment - 1; + p = _mi_heap_malloc_zero(heap, oversize, zero); + if (p == NULL) return NULL; + } + + // .. and align within the allocation + const uintptr_t poffset = ((uintptr_t)p + offset) & align_mask; + const uintptr_t adjust = (poffset == 0 ? 0 : alignment - poffset); + mi_assert_internal(adjust < alignment); + void* aligned_p = (void*)((uintptr_t)p + adjust); + if (aligned_p != p) { + mi_page_t* page = _mi_ptr_page(p); + mi_page_set_has_aligned(page, true); + _mi_padding_shrink(page, (mi_block_t*)p, adjust + size); + } + // todo: expand padding if overallocated ? + + mi_assert_internal(mi_page_usable_block_size(_mi_ptr_page(p)) >= adjust + size); + mi_assert_internal(p == _mi_page_ptr_unalign(_mi_ptr_segment(aligned_p), _mi_ptr_page(aligned_p), aligned_p)); + mi_assert_internal(((uintptr_t)aligned_p + offset) % alignment == 0); + mi_assert_internal(mi_usable_size(aligned_p)>=size); + mi_assert_internal(mi_usable_size(p) == mi_usable_size(aligned_p)+adjust); + + // now zero the block if needed + if (alignment > MI_ALIGNMENT_MAX) { + // for the tracker, on huge aligned allocations only from the start of the large block is defined + mi_track_mem_undefined(aligned_p, size); + if (zero) { + _mi_memzero_aligned(aligned_p, mi_usable_size(aligned_p)); + } + } + + if (p != aligned_p) { + mi_track_align(p,aligned_p,adjust,mi_usable_size(aligned_p)); + } + return aligned_p; +} + +// Primitive aligned allocation +static void* mi_heap_malloc_zero_aligned_at(mi_heap_t* const heap, const size_t size, const size_t alignment, const size_t offset, const bool zero) mi_attr_noexcept +{ + // note: we don't require `size > offset`, we just guarantee that the address at offset is aligned regardless of the allocated size. + if mi_unlikely(alignment == 0 || !_mi_is_power_of_two(alignment)) { // require power-of-two (see ) + #if MI_DEBUG > 0 + _mi_error_message(EOVERFLOW, "aligned allocation requires the alignment to be a power-of-two (size %zu, alignment %zu)\n", size, alignment); + #endif + return NULL; + } + + if mi_unlikely(size > PTRDIFF_MAX) { // we don't allocate more than PTRDIFF_MAX (see ) + #if MI_DEBUG > 0 + _mi_error_message(EOVERFLOW, "aligned allocation request is too large (size %zu, alignment %zu)\n", size, alignment); + #endif + return NULL; + } + const uintptr_t align_mask = alignment-1; // for any x, `(x & align_mask) == (x % alignment)` + const size_t padsize = size + MI_PADDING_SIZE; // note: cannot overflow due to earlier size > PTRDIFF_MAX check + + // try first if there happens to be a small block available with just the right alignment + if mi_likely(padsize <= MI_SMALL_SIZE_MAX && alignment <= padsize) { + mi_page_t* page = _mi_heap_get_free_small_page(heap, padsize); + const bool is_aligned = (((uintptr_t)page->free+offset) & align_mask)==0; + if mi_likely(page->free != NULL && is_aligned) + { + #if MI_STAT>1 + mi_heap_stat_increase(heap, malloc, size); + #endif + void* p = _mi_page_malloc(heap, page, padsize, zero); // TODO: inline _mi_page_malloc + mi_assert_internal(p != NULL); + mi_assert_internal(((uintptr_t)p + offset) % alignment == 0); + mi_track_malloc(p,size,zero); + return p; + } + } + // fallback + return mi_heap_malloc_zero_aligned_at_fallback(heap, size, alignment, offset, zero); +} + + +// ------------------------------------------------------ +// Optimized mi_heap_malloc_aligned / mi_malloc_aligned +// ------------------------------------------------------ + +mi_decl_nodiscard mi_decl_restrict void* mi_heap_malloc_aligned_at(mi_heap_t* heap, size_t size, size_t alignment, size_t offset) mi_attr_noexcept { + return mi_heap_malloc_zero_aligned_at(heap, size, alignment, offset, false); +} + +mi_decl_nodiscard mi_decl_restrict void* mi_heap_malloc_aligned(mi_heap_t* heap, size_t size, size_t alignment) mi_attr_noexcept { + if mi_unlikely(alignment == 0 || !_mi_is_power_of_two(alignment)) return NULL; + #if !MI_PADDING + // without padding, any small sized allocation is naturally aligned (see also `_mi_segment_page_start`) + if mi_likely(_mi_is_power_of_two(size) && size >= alignment && size <= MI_SMALL_SIZE_MAX) + #else + // with padding, we can only guarantee this for fixed alignments + if mi_likely((alignment == sizeof(void*) || (alignment == MI_MAX_ALIGN_SIZE && size > (MI_MAX_ALIGN_SIZE/2))) + && size <= MI_SMALL_SIZE_MAX) + #endif + { + // fast path for common alignment and size + return mi_heap_malloc_small(heap, size); + } + else { + return mi_heap_malloc_aligned_at(heap, size, alignment, 0); + } +} + +// ensure a definition is emitted +#if defined(__cplusplus) +static void* _mi_heap_malloc_aligned = (void*)&mi_heap_malloc_aligned; +#endif + +// ------------------------------------------------------ +// Aligned Allocation +// ------------------------------------------------------ + +mi_decl_nodiscard mi_decl_restrict void* mi_heap_zalloc_aligned_at(mi_heap_t* heap, size_t size, size_t alignment, size_t offset) mi_attr_noexcept { + return mi_heap_malloc_zero_aligned_at(heap, size, alignment, offset, true); +} + +mi_decl_nodiscard mi_decl_restrict void* mi_heap_zalloc_aligned(mi_heap_t* heap, size_t size, size_t alignment) mi_attr_noexcept { + return mi_heap_zalloc_aligned_at(heap, size, alignment, 0); +} + +mi_decl_nodiscard mi_decl_restrict void* mi_heap_calloc_aligned_at(mi_heap_t* heap, size_t count, size_t size, size_t alignment, size_t offset) mi_attr_noexcept { + size_t total; + if (mi_count_size_overflow(count, size, &total)) return NULL; + return mi_heap_zalloc_aligned_at(heap, total, alignment, offset); +} + +mi_decl_nodiscard mi_decl_restrict void* mi_heap_calloc_aligned(mi_heap_t* heap, size_t count, size_t size, size_t alignment) mi_attr_noexcept { + return mi_heap_calloc_aligned_at(heap,count,size,alignment,0); +} + +mi_decl_nodiscard mi_decl_restrict void* mi_malloc_aligned_at(size_t size, size_t alignment, size_t offset) mi_attr_noexcept { + return mi_heap_malloc_aligned_at(mi_prim_get_default_heap(), size, alignment, offset); +} + +mi_decl_nodiscard mi_decl_restrict void* mi_malloc_aligned(size_t size, size_t alignment) mi_attr_noexcept { + return mi_heap_malloc_aligned(mi_prim_get_default_heap(), size, alignment); +} + +mi_decl_nodiscard mi_decl_restrict void* mi_zalloc_aligned_at(size_t size, size_t alignment, size_t offset) mi_attr_noexcept { + return mi_heap_zalloc_aligned_at(mi_prim_get_default_heap(), size, alignment, offset); +} + +mi_decl_nodiscard mi_decl_restrict void* mi_zalloc_aligned(size_t size, size_t alignment) mi_attr_noexcept { + return mi_heap_zalloc_aligned(mi_prim_get_default_heap(), size, alignment); +} + +mi_decl_nodiscard mi_decl_restrict void* mi_calloc_aligned_at(size_t count, size_t size, size_t alignment, size_t offset) mi_attr_noexcept { + return mi_heap_calloc_aligned_at(mi_prim_get_default_heap(), count, size, alignment, offset); +} + +mi_decl_nodiscard mi_decl_restrict void* mi_calloc_aligned(size_t count, size_t size, size_t alignment) mi_attr_noexcept { + return mi_heap_calloc_aligned(mi_prim_get_default_heap(), count, size, alignment); +} + + +// ------------------------------------------------------ +// Aligned re-allocation +// ------------------------------------------------------ + +static void* mi_heap_realloc_zero_aligned_at(mi_heap_t* heap, void* p, size_t newsize, size_t alignment, size_t offset, bool zero) mi_attr_noexcept { + mi_assert(alignment > 0); + if (alignment <= sizeof(uintptr_t)) return _mi_heap_realloc_zero(heap,p,newsize,zero); + if (p == NULL) return mi_heap_malloc_zero_aligned_at(heap,newsize,alignment,offset,zero); + size_t size = mi_usable_size(p); + if (newsize <= size && newsize >= (size - (size / 2)) + && (((uintptr_t)p + offset) % alignment) == 0) { + return p; // reallocation still fits, is aligned and not more than 50% waste + } + else { + // note: we don't zero allocate upfront so we only zero initialize the expanded part + void* newp = mi_heap_malloc_aligned_at(heap,newsize,alignment,offset); + if (newp != NULL) { + if (zero && newsize > size) { + // also set last word in the previous allocation to zero to ensure any padding is zero-initialized + size_t start = (size >= sizeof(intptr_t) ? size - sizeof(intptr_t) : 0); + _mi_memzero((uint8_t*)newp + start, newsize - start); + } + _mi_memcpy_aligned(newp, p, (newsize > size ? size : newsize)); + mi_free(p); // only free if successful + } + return newp; + } +} + +static void* mi_heap_realloc_zero_aligned(mi_heap_t* heap, void* p, size_t newsize, size_t alignment, bool zero) mi_attr_noexcept { + mi_assert(alignment > 0); + if (alignment <= sizeof(uintptr_t)) return _mi_heap_realloc_zero(heap,p,newsize,zero); + size_t offset = ((uintptr_t)p % alignment); // use offset of previous allocation (p can be NULL) + return mi_heap_realloc_zero_aligned_at(heap,p,newsize,alignment,offset,zero); +} + +mi_decl_nodiscard void* mi_heap_realloc_aligned_at(mi_heap_t* heap, void* p, size_t newsize, size_t alignment, size_t offset) mi_attr_noexcept { + return mi_heap_realloc_zero_aligned_at(heap,p,newsize,alignment,offset,false); +} + +mi_decl_nodiscard void* mi_heap_realloc_aligned(mi_heap_t* heap, void* p, size_t newsize, size_t alignment) mi_attr_noexcept { + return mi_heap_realloc_zero_aligned(heap,p,newsize,alignment,false); +} + +mi_decl_nodiscard void* mi_heap_rezalloc_aligned_at(mi_heap_t* heap, void* p, size_t newsize, size_t alignment, size_t offset) mi_attr_noexcept { + return mi_heap_realloc_zero_aligned_at(heap, p, newsize, alignment, offset, true); +} + +mi_decl_nodiscard void* mi_heap_rezalloc_aligned(mi_heap_t* heap, void* p, size_t newsize, size_t alignment) mi_attr_noexcept { + return mi_heap_realloc_zero_aligned(heap, p, newsize, alignment, true); +} + +mi_decl_nodiscard void* mi_heap_recalloc_aligned_at(mi_heap_t* heap, void* p, size_t newcount, size_t size, size_t alignment, size_t offset) mi_attr_noexcept { + size_t total; + if (mi_count_size_overflow(newcount, size, &total)) return NULL; + return mi_heap_rezalloc_aligned_at(heap, p, total, alignment, offset); +} + +mi_decl_nodiscard void* mi_heap_recalloc_aligned(mi_heap_t* heap, void* p, size_t newcount, size_t size, size_t alignment) mi_attr_noexcept { + size_t total; + if (mi_count_size_overflow(newcount, size, &total)) return NULL; + return mi_heap_rezalloc_aligned(heap, p, total, alignment); +} + +mi_decl_nodiscard void* mi_realloc_aligned_at(void* p, size_t newsize, size_t alignment, size_t offset) mi_attr_noexcept { + return mi_heap_realloc_aligned_at(mi_prim_get_default_heap(), p, newsize, alignment, offset); +} + +mi_decl_nodiscard void* mi_realloc_aligned(void* p, size_t newsize, size_t alignment) mi_attr_noexcept { + return mi_heap_realloc_aligned(mi_prim_get_default_heap(), p, newsize, alignment); +} + +mi_decl_nodiscard void* mi_rezalloc_aligned_at(void* p, size_t newsize, size_t alignment, size_t offset) mi_attr_noexcept { + return mi_heap_rezalloc_aligned_at(mi_prim_get_default_heap(), p, newsize, alignment, offset); +} + +mi_decl_nodiscard void* mi_rezalloc_aligned(void* p, size_t newsize, size_t alignment) mi_attr_noexcept { + return mi_heap_rezalloc_aligned(mi_prim_get_default_heap(), p, newsize, alignment); +} + +mi_decl_nodiscard void* mi_recalloc_aligned_at(void* p, size_t newcount, size_t size, size_t alignment, size_t offset) mi_attr_noexcept { + return mi_heap_recalloc_aligned_at(mi_prim_get_default_heap(), p, newcount, size, alignment, offset); +} + +mi_decl_nodiscard void* mi_recalloc_aligned(void* p, size_t newcount, size_t size, size_t alignment) mi_attr_noexcept { + return mi_heap_recalloc_aligned(mi_prim_get_default_heap(), p, newcount, size, alignment); +} diff --git a/Objects/mimalloc/alloc-override.c b/Objects/mimalloc/alloc-override.c new file mode 100644 index 00000000000000..873065dc63495c --- /dev/null +++ b/Objects/mimalloc/alloc-override.c @@ -0,0 +1,297 @@ +/* ---------------------------------------------------------------------------- +Copyright (c) 2018-2021, Microsoft Research, Daan Leijen +This is free software; you can redistribute it and/or modify it under the +terms of the MIT license. A copy of the license can be found in the file +"LICENSE" at the root of this distribution. +-----------------------------------------------------------------------------*/ + +#if !defined(MI_IN_ALLOC_C) +#error "this file should be included from 'alloc.c' (so aliases can work)" +#endif + +#if defined(MI_MALLOC_OVERRIDE) && defined(_WIN32) && !(defined(MI_SHARED_LIB) && defined(_DLL)) +#error "It is only possible to override "malloc" on Windows when building as a DLL (and linking the C runtime as a DLL)" +#endif + +#if defined(MI_MALLOC_OVERRIDE) && !(defined(_WIN32)) + +#if defined(__APPLE__) +#include +mi_decl_externc void vfree(void* p); +mi_decl_externc size_t malloc_size(const void* p); +mi_decl_externc size_t malloc_good_size(size_t size); +#endif + +// helper definition for C override of C++ new +typedef struct mi_nothrow_s { int _tag; } mi_nothrow_t; + +// ------------------------------------------------------ +// Override system malloc +// ------------------------------------------------------ + +#if (defined(__GNUC__) || defined(__clang__)) && !defined(__APPLE__) && !MI_TRACK_ENABLED + // gcc, clang: use aliasing to alias the exported function to one of our `mi_` functions + #if (defined(__GNUC__) && __GNUC__ >= 9) + #pragma GCC diagnostic ignored "-Wattributes" // or we get warnings that nodiscard is ignored on a forward + #define MI_FORWARD(fun) __attribute__((alias(#fun), used, visibility("default"), copy(fun))); + #else + #define MI_FORWARD(fun) __attribute__((alias(#fun), used, visibility("default"))); + #endif + #define MI_FORWARD1(fun,x) MI_FORWARD(fun) + #define MI_FORWARD2(fun,x,y) MI_FORWARD(fun) + #define MI_FORWARD3(fun,x,y,z) MI_FORWARD(fun) + #define MI_FORWARD0(fun,x) MI_FORWARD(fun) + #define MI_FORWARD02(fun,x,y) MI_FORWARD(fun) +#else + // otherwise use forwarding by calling our `mi_` function + #define MI_FORWARD1(fun,x) { return fun(x); } + #define MI_FORWARD2(fun,x,y) { return fun(x,y); } + #define MI_FORWARD3(fun,x,y,z) { return fun(x,y,z); } + #define MI_FORWARD0(fun,x) { fun(x); } + #define MI_FORWARD02(fun,x,y) { fun(x,y); } +#endif + + +#if defined(__APPLE__) && defined(MI_SHARED_LIB_EXPORT) && defined(MI_OSX_INTERPOSE) + // define MI_OSX_IS_INTERPOSED as we should not provide forwarding definitions for + // functions that are interposed (or the interposing does not work) + #define MI_OSX_IS_INTERPOSED + + mi_decl_externc size_t mi_malloc_size_checked(void *p) { + if (!mi_is_in_heap_region(p)) return 0; + return mi_usable_size(p); + } + + // use interposing so `DYLD_INSERT_LIBRARIES` works without `DYLD_FORCE_FLAT_NAMESPACE=1` + // See: + struct mi_interpose_s { + const void* replacement; + const void* target; + }; + #define MI_INTERPOSE_FUN(oldfun,newfun) { (const void*)&newfun, (const void*)&oldfun } + #define MI_INTERPOSE_MI(fun) MI_INTERPOSE_FUN(fun,mi_##fun) + + __attribute__((used)) static struct mi_interpose_s _mi_interposes[] __attribute__((section("__DATA, __interpose"))) = + { + MI_INTERPOSE_MI(malloc), + MI_INTERPOSE_MI(calloc), + MI_INTERPOSE_MI(realloc), + MI_INTERPOSE_MI(strdup), + MI_INTERPOSE_MI(strndup), + MI_INTERPOSE_MI(realpath), + MI_INTERPOSE_MI(posix_memalign), + MI_INTERPOSE_MI(reallocf), + MI_INTERPOSE_MI(valloc), + MI_INTERPOSE_FUN(malloc_size,mi_malloc_size_checked), + MI_INTERPOSE_MI(malloc_good_size), + #if defined(MAC_OS_X_VERSION_10_15) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_15 + MI_INTERPOSE_MI(aligned_alloc), + #endif + #ifdef MI_OSX_ZONE + // we interpose malloc_default_zone in alloc-override-osx.c so we can use mi_free safely + MI_INTERPOSE_MI(free), + MI_INTERPOSE_FUN(vfree,mi_free), + #else + // sometimes code allocates from default zone but deallocates using plain free :-( (like NxHashResizeToCapacity ) + MI_INTERPOSE_FUN(free,mi_cfree), // use safe free that checks if pointers are from us + MI_INTERPOSE_FUN(vfree,mi_cfree), + #endif + }; + + #ifdef __cplusplus + extern "C" { + #endif + void _ZdlPv(void* p); // delete + void _ZdaPv(void* p); // delete[] + void _ZdlPvm(void* p, size_t n); // delete + void _ZdaPvm(void* p, size_t n); // delete[] + void* _Znwm(size_t n); // new + void* _Znam(size_t n); // new[] + void* _ZnwmRKSt9nothrow_t(size_t n, mi_nothrow_t tag); // new nothrow + void* _ZnamRKSt9nothrow_t(size_t n, mi_nothrow_t tag); // new[] nothrow + #ifdef __cplusplus + } + #endif + __attribute__((used)) static struct mi_interpose_s _mi_cxx_interposes[] __attribute__((section("__DATA, __interpose"))) = + { + MI_INTERPOSE_FUN(_ZdlPv,mi_free), + MI_INTERPOSE_FUN(_ZdaPv,mi_free), + MI_INTERPOSE_FUN(_ZdlPvm,mi_free_size), + MI_INTERPOSE_FUN(_ZdaPvm,mi_free_size), + MI_INTERPOSE_FUN(_Znwm,mi_new), + MI_INTERPOSE_FUN(_Znam,mi_new), + MI_INTERPOSE_FUN(_ZnwmRKSt9nothrow_t,mi_new_nothrow), + MI_INTERPOSE_FUN(_ZnamRKSt9nothrow_t,mi_new_nothrow), + }; + +#elif defined(_MSC_VER) + // cannot override malloc unless using a dll. + // we just override new/delete which does work in a static library. +#else + // On all other systems forward to our API + mi_decl_export void* malloc(size_t size) MI_FORWARD1(mi_malloc, size) + mi_decl_export void* calloc(size_t size, size_t n) MI_FORWARD2(mi_calloc, size, n) + mi_decl_export void* realloc(void* p, size_t newsize) MI_FORWARD2(mi_realloc, p, newsize) + mi_decl_export void free(void* p) MI_FORWARD0(mi_free, p) +#endif + +#if (defined(__GNUC__) || defined(__clang__)) && !defined(__APPLE__) +#pragma GCC visibility push(default) +#endif + +// ------------------------------------------------------ +// Override new/delete +// This is not really necessary as they usually call +// malloc/free anyway, but it improves performance. +// ------------------------------------------------------ +#ifdef __cplusplus + // ------------------------------------------------------ + // With a C++ compiler we override the new/delete operators. + // see + // ------------------------------------------------------ + #include + + #ifndef MI_OSX_IS_INTERPOSED + void operator delete(void* p) noexcept MI_FORWARD0(mi_free,p) + void operator delete[](void* p) noexcept MI_FORWARD0(mi_free,p) + + void* operator new(std::size_t n) noexcept(false) MI_FORWARD1(mi_new,n) + void* operator new[](std::size_t n) noexcept(false) MI_FORWARD1(mi_new,n) + + void* operator new (std::size_t n, const std::nothrow_t& tag) noexcept { MI_UNUSED(tag); return mi_new_nothrow(n); } + void* operator new[](std::size_t n, const std::nothrow_t& tag) noexcept { MI_UNUSED(tag); return mi_new_nothrow(n); } + + #if (__cplusplus >= 201402L || _MSC_VER >= 1916) + void operator delete (void* p, std::size_t n) noexcept MI_FORWARD02(mi_free_size,p,n) + void operator delete[](void* p, std::size_t n) noexcept MI_FORWARD02(mi_free_size,p,n) + #endif + #endif + + #if (__cplusplus > 201402L && defined(__cpp_aligned_new)) && (!defined(__GNUC__) || (__GNUC__ > 5)) + void operator delete (void* p, std::align_val_t al) noexcept { mi_free_aligned(p, static_cast(al)); } + void operator delete[](void* p, std::align_val_t al) noexcept { mi_free_aligned(p, static_cast(al)); } + void operator delete (void* p, std::size_t n, std::align_val_t al) noexcept { mi_free_size_aligned(p, n, static_cast(al)); }; + void operator delete[](void* p, std::size_t n, std::align_val_t al) noexcept { mi_free_size_aligned(p, n, static_cast(al)); }; + void operator delete (void* p, std::align_val_t al, const std::nothrow_t&) noexcept { mi_free_aligned(p, static_cast(al)); } + void operator delete[](void* p, std::align_val_t al, const std::nothrow_t&) noexcept { mi_free_aligned(p, static_cast(al)); } + + void* operator new( std::size_t n, std::align_val_t al) noexcept(false) { return mi_new_aligned(n, static_cast(al)); } + void* operator new[]( std::size_t n, std::align_val_t al) noexcept(false) { return mi_new_aligned(n, static_cast(al)); } + void* operator new (std::size_t n, std::align_val_t al, const std::nothrow_t&) noexcept { return mi_new_aligned_nothrow(n, static_cast(al)); } + void* operator new[](std::size_t n, std::align_val_t al, const std::nothrow_t&) noexcept { return mi_new_aligned_nothrow(n, static_cast(al)); } + #endif + +#elif (defined(__GNUC__) || defined(__clang__)) + // ------------------------------------------------------ + // Override by defining the mangled C++ names of the operators (as + // used by GCC and CLang). + // See + // ------------------------------------------------------ + + void _ZdlPv(void* p) MI_FORWARD0(mi_free,p) // delete + void _ZdaPv(void* p) MI_FORWARD0(mi_free,p) // delete[] + void _ZdlPvm(void* p, size_t n) MI_FORWARD02(mi_free_size,p,n) + void _ZdaPvm(void* p, size_t n) MI_FORWARD02(mi_free_size,p,n) + void _ZdlPvSt11align_val_t(void* p, size_t al) { mi_free_aligned(p,al); } + void _ZdaPvSt11align_val_t(void* p, size_t al) { mi_free_aligned(p,al); } + void _ZdlPvmSt11align_val_t(void* p, size_t n, size_t al) { mi_free_size_aligned(p,n,al); } + void _ZdaPvmSt11align_val_t(void* p, size_t n, size_t al) { mi_free_size_aligned(p,n,al); } + + #if (MI_INTPTR_SIZE==8) + void* _Znwm(size_t n) MI_FORWARD1(mi_new,n) // new 64-bit + void* _Znam(size_t n) MI_FORWARD1(mi_new,n) // new[] 64-bit + void* _ZnwmRKSt9nothrow_t(size_t n, mi_nothrow_t tag) { MI_UNUSED(tag); return mi_new_nothrow(n); } + void* _ZnamRKSt9nothrow_t(size_t n, mi_nothrow_t tag) { MI_UNUSED(tag); return mi_new_nothrow(n); } + void* _ZnwmSt11align_val_t(size_t n, size_t al) MI_FORWARD2(mi_new_aligned, n, al) + void* _ZnamSt11align_val_t(size_t n, size_t al) MI_FORWARD2(mi_new_aligned, n, al) + void* _ZnwmSt11align_val_tRKSt9nothrow_t(size_t n, size_t al, mi_nothrow_t tag) { MI_UNUSED(tag); return mi_new_aligned_nothrow(n,al); } + void* _ZnamSt11align_val_tRKSt9nothrow_t(size_t n, size_t al, mi_nothrow_t tag) { MI_UNUSED(tag); return mi_new_aligned_nothrow(n,al); } + #elif (MI_INTPTR_SIZE==4) + void* _Znwj(size_t n) MI_FORWARD1(mi_new,n) // new 64-bit + void* _Znaj(size_t n) MI_FORWARD1(mi_new,n) // new[] 64-bit + void* _ZnwjRKSt9nothrow_t(size_t n, mi_nothrow_t tag) { MI_UNUSED(tag); return mi_new_nothrow(n); } + void* _ZnajRKSt9nothrow_t(size_t n, mi_nothrow_t tag) { MI_UNUSED(tag); return mi_new_nothrow(n); } + void* _ZnwjSt11align_val_t(size_t n, size_t al) MI_FORWARD2(mi_new_aligned, n, al) + void* _ZnajSt11align_val_t(size_t n, size_t al) MI_FORWARD2(mi_new_aligned, n, al) + void* _ZnwjSt11align_val_tRKSt9nothrow_t(size_t n, size_t al, mi_nothrow_t tag) { MI_UNUSED(tag); return mi_new_aligned_nothrow(n,al); } + void* _ZnajSt11align_val_tRKSt9nothrow_t(size_t n, size_t al, mi_nothrow_t tag) { MI_UNUSED(tag); return mi_new_aligned_nothrow(n,al); } + #else + #error "define overloads for new/delete for this platform (just for performance, can be skipped)" + #endif +#endif // __cplusplus + +// ------------------------------------------------------ +// Further Posix & Unix functions definitions +// ------------------------------------------------------ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef MI_OSX_IS_INTERPOSED + // Forward Posix/Unix calls as well + void* reallocf(void* p, size_t newsize) MI_FORWARD2(mi_reallocf,p,newsize) + size_t malloc_size(const void* p) MI_FORWARD1(mi_usable_size,p) + #if !defined(__ANDROID__) && !defined(__FreeBSD__) + size_t malloc_usable_size(void *p) MI_FORWARD1(mi_usable_size,p) + #else + size_t malloc_usable_size(const void *p) MI_FORWARD1(mi_usable_size,p) + #endif + + // No forwarding here due to aliasing/name mangling issues + void* valloc(size_t size) { return mi_valloc(size); } + void vfree(void* p) { mi_free(p); } + size_t malloc_good_size(size_t size) { return mi_malloc_good_size(size); } + int posix_memalign(void** p, size_t alignment, size_t size) { return mi_posix_memalign(p, alignment, size); } + + // `aligned_alloc` is only available when __USE_ISOC11 is defined. + // Note: it seems __USE_ISOC11 is not defined in musl (and perhaps other libc's) so we only check + // for it if using glibc. + // Note: Conda has a custom glibc where `aligned_alloc` is declared `static inline` and we cannot + // override it, but both _ISOC11_SOURCE and __USE_ISOC11 are undefined in Conda GCC7 or GCC9. + // Fortunately, in the case where `aligned_alloc` is declared as `static inline` it + // uses internally `memalign`, `posix_memalign`, or `_aligned_malloc` so we can avoid overriding it ourselves. + #if !defined(__GLIBC__) || __USE_ISOC11 + void* aligned_alloc(size_t alignment, size_t size) { return mi_aligned_alloc(alignment, size); } + #endif +#endif + +// no forwarding here due to aliasing/name mangling issues +void cfree(void* p) { mi_free(p); } +void* pvalloc(size_t size) { return mi_pvalloc(size); } +void* reallocarray(void* p, size_t count, size_t size) { return mi_reallocarray(p, count, size); } +int reallocarr(void* p, size_t count, size_t size) { return mi_reallocarr(p, count, size); } +void* memalign(size_t alignment, size_t size) { return mi_memalign(alignment, size); } +void* _aligned_malloc(size_t alignment, size_t size) { return mi_aligned_alloc(alignment, size); } + +#if defined(__wasi__) + // forward __libc interface (see PR #667) + void* __libc_malloc(size_t size) MI_FORWARD1(mi_malloc, size) + void* __libc_calloc(size_t count, size_t size) MI_FORWARD2(mi_calloc, count, size) + void* __libc_realloc(void* p, size_t size) MI_FORWARD2(mi_realloc, p, size) + void __libc_free(void* p) MI_FORWARD0(mi_free, p) + void* __libc_memalign(size_t alignment, size_t size) { return mi_memalign(alignment, size); } + +#elif defined(__GLIBC__) && defined(__linux__) + // forward __libc interface (needed for glibc-based Linux distributions) + void* __libc_malloc(size_t size) MI_FORWARD1(mi_malloc,size) + void* __libc_calloc(size_t count, size_t size) MI_FORWARD2(mi_calloc,count,size) + void* __libc_realloc(void* p, size_t size) MI_FORWARD2(mi_realloc,p,size) + void __libc_free(void* p) MI_FORWARD0(mi_free,p) + void __libc_cfree(void* p) MI_FORWARD0(mi_free,p) + + void* __libc_valloc(size_t size) { return mi_valloc(size); } + void* __libc_pvalloc(size_t size) { return mi_pvalloc(size); } + void* __libc_memalign(size_t alignment, size_t size) { return mi_memalign(alignment,size); } + int __posix_memalign(void** p, size_t alignment, size_t size) { return mi_posix_memalign(p,alignment,size); } +#endif + +#ifdef __cplusplus +} +#endif + +#if (defined(__GNUC__) || defined(__clang__)) && !defined(__APPLE__) +#pragma GCC visibility pop +#endif + +#endif // MI_MALLOC_OVERRIDE && !_WIN32 diff --git a/Objects/mimalloc/alloc-posix.c b/Objects/mimalloc/alloc-posix.c new file mode 100644 index 00000000000000..225752fd8707fe --- /dev/null +++ b/Objects/mimalloc/alloc-posix.c @@ -0,0 +1,185 @@ +/* ---------------------------------------------------------------------------- +Copyright (c) 2018-2021, Microsoft Research, Daan Leijen +This is free software; you can redistribute it and/or modify it under the +terms of the MIT license. A copy of the license can be found in the file +"LICENSE" at the root of this distribution. +-----------------------------------------------------------------------------*/ + +// ------------------------------------------------------------------------ +// mi prefixed publi definitions of various Posix, Unix, and C++ functions +// for convenience and used when overriding these functions. +// ------------------------------------------------------------------------ +#include "mimalloc.h" +#include "mimalloc/internal.h" + +// ------------------------------------------------------ +// Posix & Unix functions definitions +// ------------------------------------------------------ + +#include +#include // memset +#include // getenv + +#ifdef _MSC_VER +#pragma warning(disable:4996) // getenv _wgetenv +#endif + +#ifndef EINVAL +#define EINVAL 22 +#endif +#ifndef ENOMEM +#define ENOMEM 12 +#endif + + +mi_decl_nodiscard size_t mi_malloc_size(const void* p) mi_attr_noexcept { + // if (!mi_is_in_heap_region(p)) return 0; + return mi_usable_size(p); +} + +mi_decl_nodiscard size_t mi_malloc_usable_size(const void *p) mi_attr_noexcept { + // if (!mi_is_in_heap_region(p)) return 0; + return mi_usable_size(p); +} + +mi_decl_nodiscard size_t mi_malloc_good_size(size_t size) mi_attr_noexcept { + return mi_good_size(size); +} + +void mi_cfree(void* p) mi_attr_noexcept { + if (mi_is_in_heap_region(p)) { + mi_free(p); + } +} + +int mi_posix_memalign(void** p, size_t alignment, size_t size) mi_attr_noexcept { + // Note: The spec dictates we should not modify `*p` on an error. (issue#27) + // + if (p == NULL) return EINVAL; + if ((alignment % sizeof(void*)) != 0) return EINVAL; // natural alignment + // it is also required that alignment is a power of 2 and > 0; this is checked in `mi_malloc_aligned` + if (alignment==0 || !_mi_is_power_of_two(alignment)) return EINVAL; // not a power of 2 + void* q = mi_malloc_aligned(size, alignment); + if (q==NULL && size != 0) return ENOMEM; + mi_assert_internal(((uintptr_t)q % alignment) == 0); + *p = q; + return 0; +} + +mi_decl_nodiscard mi_decl_restrict void* mi_memalign(size_t alignment, size_t size) mi_attr_noexcept { + void* p = mi_malloc_aligned(size, alignment); + mi_assert_internal(((uintptr_t)p % alignment) == 0); + return p; +} + +mi_decl_nodiscard mi_decl_restrict void* mi_valloc(size_t size) mi_attr_noexcept { + return mi_memalign( _mi_os_page_size(), size ); +} + +mi_decl_nodiscard mi_decl_restrict void* mi_pvalloc(size_t size) mi_attr_noexcept { + size_t psize = _mi_os_page_size(); + if (size >= SIZE_MAX - psize) return NULL; // overflow + size_t asize = _mi_align_up(size, psize); + return mi_malloc_aligned(asize, psize); +} + +mi_decl_nodiscard mi_decl_restrict void* mi_aligned_alloc(size_t alignment, size_t size) mi_attr_noexcept { + // C11 requires the size to be an integral multiple of the alignment, see . + // unfortunately, it turns out quite some programs pass a size that is not an integral multiple so skip this check.. + /* if mi_unlikely((size & (alignment - 1)) != 0) { // C11 requires alignment>0 && integral multiple, see + #if MI_DEBUG > 0 + _mi_error_message(EOVERFLOW, "(mi_)aligned_alloc requires the size to be an integral multiple of the alignment (size %zu, alignment %zu)\n", size, alignment); + #endif + return NULL; + } + */ + // C11 also requires alignment to be a power-of-two (and > 0) which is checked in mi_malloc_aligned + void* p = mi_malloc_aligned(size, alignment); + mi_assert_internal(((uintptr_t)p % alignment) == 0); + return p; +} + +mi_decl_nodiscard void* mi_reallocarray( void* p, size_t count, size_t size ) mi_attr_noexcept { // BSD + void* newp = mi_reallocn(p,count,size); + if (newp==NULL) { errno = ENOMEM; } + return newp; +} + +mi_decl_nodiscard int mi_reallocarr( void* p, size_t count, size_t size ) mi_attr_noexcept { // NetBSD + mi_assert(p != NULL); + if (p == NULL) { + errno = EINVAL; + return EINVAL; + } + void** op = (void**)p; + void* newp = mi_reallocarray(*op, count, size); + if mi_unlikely(newp == NULL) { return errno; } + *op = newp; + return 0; +} + +void* mi__expand(void* p, size_t newsize) mi_attr_noexcept { // Microsoft + void* res = mi_expand(p, newsize); + if (res == NULL) { errno = ENOMEM; } + return res; +} + +mi_decl_nodiscard mi_decl_restrict unsigned short* mi_wcsdup(const unsigned short* s) mi_attr_noexcept { + if (s==NULL) return NULL; + size_t len; + for(len = 0; s[len] != 0; len++) { } + size_t size = (len+1)*sizeof(unsigned short); + unsigned short* p = (unsigned short*)mi_malloc(size); + if (p != NULL) { + _mi_memcpy(p,s,size); + } + return p; +} + +mi_decl_nodiscard mi_decl_restrict unsigned char* mi_mbsdup(const unsigned char* s) mi_attr_noexcept { + return (unsigned char*)mi_strdup((const char*)s); +} + +int mi_dupenv_s(char** buf, size_t* size, const char* name) mi_attr_noexcept { + if (buf==NULL || name==NULL) return EINVAL; + if (size != NULL) *size = 0; + char* p = getenv(name); // mscver warning 4996 + if (p==NULL) { + *buf = NULL; + } + else { + *buf = mi_strdup(p); + if (*buf==NULL) return ENOMEM; + if (size != NULL) *size = _mi_strlen(p); + } + return 0; +} + +int mi_wdupenv_s(unsigned short** buf, size_t* size, const unsigned short* name) mi_attr_noexcept { + if (buf==NULL || name==NULL) return EINVAL; + if (size != NULL) *size = 0; +#if !defined(_WIN32) || (defined(WINAPI_FAMILY) && (WINAPI_FAMILY != WINAPI_FAMILY_DESKTOP_APP)) + // not supported + *buf = NULL; + return EINVAL; +#else + unsigned short* p = (unsigned short*)_wgetenv((const wchar_t*)name); // msvc warning 4996 + if (p==NULL) { + *buf = NULL; + } + else { + *buf = mi_wcsdup(p); + if (*buf==NULL) return ENOMEM; + if (size != NULL) *size = wcslen((const wchar_t*)p); + } + return 0; +#endif +} + +mi_decl_nodiscard void* mi_aligned_offset_recalloc(void* p, size_t newcount, size_t size, size_t alignment, size_t offset) mi_attr_noexcept { // Microsoft + return mi_recalloc_aligned_at(p, newcount, size, alignment, offset); +} + +mi_decl_nodiscard void* mi_aligned_recalloc(void* p, size_t newcount, size_t size, size_t alignment) mi_attr_noexcept { // Microsoft + return mi_recalloc_aligned(p, newcount, size, alignment); +} diff --git a/Objects/mimalloc/alloc.c b/Objects/mimalloc/alloc.c new file mode 100644 index 00000000000000..f96c6f0b37f873 --- /dev/null +++ b/Objects/mimalloc/alloc.c @@ -0,0 +1,1062 @@ +/* ---------------------------------------------------------------------------- +Copyright (c) 2018-2022, Microsoft Research, Daan Leijen +This is free software; you can redistribute it and/or modify it under the +terms of the MIT license. A copy of the license can be found in the file +"LICENSE" at the root of this distribution. +-----------------------------------------------------------------------------*/ +#ifndef _DEFAULT_SOURCE +#define _DEFAULT_SOURCE // for realpath() on Linux +#endif + +#include "mimalloc.h" +#include "mimalloc/internal.h" +#include "mimalloc/atomic.h" +#include "mimalloc/prim.h" // _mi_prim_thread_id() + +#include // memset, strlen (for mi_strdup) +#include // malloc, abort + +#define _ZSt15get_new_handlerv _Py__ZSt15get_new_handlerv + +#define MI_IN_ALLOC_C +#include "alloc-override.c" +#undef MI_IN_ALLOC_C + +// ------------------------------------------------------ +// Allocation +// ------------------------------------------------------ + +// Fast allocation in a page: just pop from the free list. +// Fall back to generic allocation only if the list is empty. +extern inline void* _mi_page_malloc(mi_heap_t* heap, mi_page_t* page, size_t size, bool zero) mi_attr_noexcept { + mi_assert_internal(page->xblock_size==0||mi_page_block_size(page) >= size); + mi_block_t* const block = page->free; + if mi_unlikely(block == NULL) { + return _mi_malloc_generic(heap, size, zero, 0); + } + mi_assert_internal(block != NULL && _mi_ptr_page(block) == page); + // pop from the free list + page->used++; + page->free = mi_block_next(page, block); + mi_assert_internal(page->free == NULL || _mi_ptr_page(page->free) == page); + #if MI_DEBUG>3 + if (page->free_is_zero) { + mi_assert_expensive(mi_mem_is_zero(block+1,size - sizeof(*block))); + } + #endif + + // allow use of the block internally + // note: when tracking we need to avoid ever touching the MI_PADDING since + // that is tracked by valgrind etc. as non-accessible (through the red-zone, see `mimalloc/track.h`) + mi_track_mem_undefined(block, mi_page_usable_block_size(page)); + + // zero the block? note: we need to zero the full block size (issue #63) + if mi_unlikely(zero) { + mi_assert_internal(page->xblock_size != 0); // do not call with zero'ing for huge blocks (see _mi_malloc_generic) + mi_assert_internal(page->xblock_size >= MI_PADDING_SIZE); + if (page->free_is_zero) { + block->next = 0; + mi_track_mem_defined(block, page->xblock_size - MI_PADDING_SIZE); + } + else { + _mi_memzero_aligned(block, page->xblock_size - MI_PADDING_SIZE); + } + } + +#if (MI_DEBUG>0) && !MI_TRACK_ENABLED && !MI_TSAN + if (!zero && !mi_page_is_huge(page)) { + memset(block, MI_DEBUG_UNINIT, mi_page_usable_block_size(page)); + } +#elif (MI_SECURE!=0) + if (!zero) { block->next = 0; } // don't leak internal data +#endif + +#if (MI_STAT>0) + const size_t bsize = mi_page_usable_block_size(page); + if (bsize <= MI_MEDIUM_OBJ_SIZE_MAX) { + mi_heap_stat_increase(heap, normal, bsize); + mi_heap_stat_counter_increase(heap, normal_count, 1); +#if (MI_STAT>1) + const size_t bin = _mi_bin(bsize); + mi_heap_stat_increase(heap, normal_bins[bin], 1); +#endif + } +#endif + +#if MI_PADDING // && !MI_TRACK_ENABLED + mi_padding_t* const padding = (mi_padding_t*)((uint8_t*)block + mi_page_usable_block_size(page)); + ptrdiff_t delta = ((uint8_t*)padding - (uint8_t*)block - (size - MI_PADDING_SIZE)); + #if (MI_DEBUG>=2) + mi_assert_internal(delta >= 0 && mi_page_usable_block_size(page) >= (size - MI_PADDING_SIZE + delta)); + #endif + mi_track_mem_defined(padding,sizeof(mi_padding_t)); // note: re-enable since mi_page_usable_block_size may set noaccess + padding->canary = (uint32_t)(mi_ptr_encode(page,block,page->keys)); + padding->delta = (uint32_t)(delta); + #if MI_PADDING_CHECK + if (!mi_page_is_huge(page)) { + uint8_t* fill = (uint8_t*)padding - delta; + const size_t maxpad = (delta > MI_MAX_ALIGN_SIZE ? MI_MAX_ALIGN_SIZE : delta); // set at most N initial padding bytes + for (size_t i = 0; i < maxpad; i++) { fill[i] = MI_DEBUG_PADDING; } + } + #endif +#endif + + return block; +} + +static inline mi_decl_restrict void* mi_heap_malloc_small_zero(mi_heap_t* heap, size_t size, bool zero) mi_attr_noexcept { + mi_assert(heap != NULL); + #if MI_DEBUG + const uintptr_t tid = _mi_thread_id(); + mi_assert(heap->thread_id == 0 || heap->thread_id == tid); // heaps are thread local + #endif + mi_assert(size <= MI_SMALL_SIZE_MAX); + #if (MI_PADDING) + if (size == 0) { size = sizeof(void*); } + #endif + mi_page_t* page = _mi_heap_get_free_small_page(heap, size + MI_PADDING_SIZE); + void* const p = _mi_page_malloc(heap, page, size + MI_PADDING_SIZE, zero); + mi_track_malloc(p,size,zero); + #if MI_STAT>1 + if (p != NULL) { + if (!mi_heap_is_initialized(heap)) { heap = mi_prim_get_default_heap(); } + mi_heap_stat_increase(heap, malloc, mi_usable_size(p)); + } + #endif + #if MI_DEBUG>3 + if (p != NULL && zero) { + mi_assert_expensive(mi_mem_is_zero(p, size)); + } + #endif + return p; +} + +// allocate a small block +mi_decl_nodiscard extern inline mi_decl_restrict void* mi_heap_malloc_small(mi_heap_t* heap, size_t size) mi_attr_noexcept { + return mi_heap_malloc_small_zero(heap, size, false); +} + +mi_decl_nodiscard extern inline mi_decl_restrict void* mi_malloc_small(size_t size) mi_attr_noexcept { + return mi_heap_malloc_small(mi_prim_get_default_heap(), size); +} + +// The main allocation function +extern inline void* _mi_heap_malloc_zero_ex(mi_heap_t* heap, size_t size, bool zero, size_t huge_alignment) mi_attr_noexcept { + if mi_likely(size <= MI_SMALL_SIZE_MAX) { + mi_assert_internal(huge_alignment == 0); + return mi_heap_malloc_small_zero(heap, size, zero); + } + else { + mi_assert(heap!=NULL); + mi_assert(heap->thread_id == 0 || heap->thread_id == _mi_thread_id()); // heaps are thread local + void* const p = _mi_malloc_generic(heap, size + MI_PADDING_SIZE, zero, huge_alignment); // note: size can overflow but it is detected in malloc_generic + mi_track_malloc(p,size,zero); + #if MI_STAT>1 + if (p != NULL) { + if (!mi_heap_is_initialized(heap)) { heap = mi_prim_get_default_heap(); } + mi_heap_stat_increase(heap, malloc, mi_usable_size(p)); + } + #endif + #if MI_DEBUG>3 + if (p != NULL && zero) { + mi_assert_expensive(mi_mem_is_zero(p, size)); + } + #endif + return p; + } +} + +extern inline void* _mi_heap_malloc_zero(mi_heap_t* heap, size_t size, bool zero) mi_attr_noexcept { + return _mi_heap_malloc_zero_ex(heap, size, zero, 0); +} + +mi_decl_nodiscard extern inline mi_decl_restrict void* mi_heap_malloc(mi_heap_t* heap, size_t size) mi_attr_noexcept { + return _mi_heap_malloc_zero(heap, size, false); +} + +mi_decl_nodiscard extern inline mi_decl_restrict void* mi_malloc(size_t size) mi_attr_noexcept { + return mi_heap_malloc(mi_prim_get_default_heap(), size); +} + +// zero initialized small block +mi_decl_nodiscard mi_decl_restrict void* mi_zalloc_small(size_t size) mi_attr_noexcept { + return mi_heap_malloc_small_zero(mi_prim_get_default_heap(), size, true); +} + +mi_decl_nodiscard extern inline mi_decl_restrict void* mi_heap_zalloc(mi_heap_t* heap, size_t size) mi_attr_noexcept { + return _mi_heap_malloc_zero(heap, size, true); +} + +mi_decl_nodiscard mi_decl_restrict void* mi_zalloc(size_t size) mi_attr_noexcept { + return mi_heap_zalloc(mi_prim_get_default_heap(),size); +} + + +// ------------------------------------------------------ +// Check for double free in secure and debug mode +// This is somewhat expensive so only enabled for secure mode 4 +// ------------------------------------------------------ + +#if (MI_ENCODE_FREELIST && (MI_SECURE>=4 || MI_DEBUG!=0)) +// linear check if the free list contains a specific element +static bool mi_list_contains(const mi_page_t* page, const mi_block_t* list, const mi_block_t* elem) { + while (list != NULL) { + if (elem==list) return true; + list = mi_block_next(page, list); + } + return false; +} + +static mi_decl_noinline bool mi_check_is_double_freex(const mi_page_t* page, const mi_block_t* block) { + // The decoded value is in the same page (or NULL). + // Walk the free lists to verify positively if it is already freed + if (mi_list_contains(page, page->free, block) || + mi_list_contains(page, page->local_free, block) || + mi_list_contains(page, mi_page_thread_free(page), block)) + { + _mi_error_message(EAGAIN, "double free detected of block %p with size %zu\n", block, mi_page_block_size(page)); + return true; + } + return false; +} + +#define mi_track_page(page,access) { size_t psize; void* pstart = _mi_page_start(_mi_page_segment(page),page,&psize); mi_track_mem_##access( pstart, psize); } + +static inline bool mi_check_is_double_free(const mi_page_t* page, const mi_block_t* block) { + bool is_double_free = false; + mi_block_t* n = mi_block_nextx(page, block, page->keys); // pretend it is freed, and get the decoded first field + if (((uintptr_t)n & (MI_INTPTR_SIZE-1))==0 && // quick check: aligned pointer? + (n==NULL || mi_is_in_same_page(block, n))) // quick check: in same page or NULL? + { + // Suspicous: decoded value a in block is in the same page (or NULL) -- maybe a double free? + // (continue in separate function to improve code generation) + is_double_free = mi_check_is_double_freex(page, block); + } + return is_double_free; +} +#else +static inline bool mi_check_is_double_free(const mi_page_t* page, const mi_block_t* block) { + MI_UNUSED(page); + MI_UNUSED(block); + return false; +} +#endif + +// --------------------------------------------------------------------------- +// Check for heap block overflow by setting up padding at the end of the block +// --------------------------------------------------------------------------- + +#if MI_PADDING // && !MI_TRACK_ENABLED +static bool mi_page_decode_padding(const mi_page_t* page, const mi_block_t* block, size_t* delta, size_t* bsize) { + *bsize = mi_page_usable_block_size(page); + const mi_padding_t* const padding = (mi_padding_t*)((uint8_t*)block + *bsize); + mi_track_mem_defined(padding,sizeof(mi_padding_t)); + *delta = padding->delta; + uint32_t canary = padding->canary; + uintptr_t keys[2]; + keys[0] = page->keys[0]; + keys[1] = page->keys[1]; + bool ok = ((uint32_t)mi_ptr_encode(page,block,keys) == canary && *delta <= *bsize); + mi_track_mem_noaccess(padding,sizeof(mi_padding_t)); + return ok; +} + +// Return the exact usable size of a block. +static size_t mi_page_usable_size_of(const mi_page_t* page, const mi_block_t* block) { + size_t bsize; + size_t delta; + bool ok = mi_page_decode_padding(page, block, &delta, &bsize); + mi_assert_internal(ok); mi_assert_internal(delta <= bsize); + return (ok ? bsize - delta : 0); +} + +// When a non-thread-local block is freed, it becomes part of the thread delayed free +// list that is freed later by the owning heap. If the exact usable size is too small to +// contain the pointer for the delayed list, then shrink the padding (by decreasing delta) +// so it will later not trigger an overflow error in `mi_free_block`. +void _mi_padding_shrink(const mi_page_t* page, const mi_block_t* block, const size_t min_size) { + size_t bsize; + size_t delta; + bool ok = mi_page_decode_padding(page, block, &delta, &bsize); + mi_assert_internal(ok); + if (!ok || (bsize - delta) >= min_size) return; // usually already enough space + mi_assert_internal(bsize >= min_size); + if (bsize < min_size) return; // should never happen + size_t new_delta = (bsize - min_size); + mi_assert_internal(new_delta < bsize); + mi_padding_t* padding = (mi_padding_t*)((uint8_t*)block + bsize); + mi_track_mem_defined(padding,sizeof(mi_padding_t)); + padding->delta = (uint32_t)new_delta; + mi_track_mem_noaccess(padding,sizeof(mi_padding_t)); +} +#else +static size_t mi_page_usable_size_of(const mi_page_t* page, const mi_block_t* block) { + MI_UNUSED(block); + return mi_page_usable_block_size(page); +} + +void _mi_padding_shrink(const mi_page_t* page, const mi_block_t* block, const size_t min_size) { + MI_UNUSED(page); + MI_UNUSED(block); + MI_UNUSED(min_size); +} +#endif + +#if MI_PADDING && MI_PADDING_CHECK + +static bool mi_verify_padding(const mi_page_t* page, const mi_block_t* block, size_t* size, size_t* wrong) { + size_t bsize; + size_t delta; + bool ok = mi_page_decode_padding(page, block, &delta, &bsize); + *size = *wrong = bsize; + if (!ok) return false; + mi_assert_internal(bsize >= delta); + *size = bsize - delta; + if (!mi_page_is_huge(page)) { + uint8_t* fill = (uint8_t*)block + bsize - delta; + const size_t maxpad = (delta > MI_MAX_ALIGN_SIZE ? MI_MAX_ALIGN_SIZE : delta); // check at most the first N padding bytes + mi_track_mem_defined(fill, maxpad); + for (size_t i = 0; i < maxpad; i++) { + if (fill[i] != MI_DEBUG_PADDING) { + *wrong = bsize - delta + i; + ok = false; + break; + } + } + mi_track_mem_noaccess(fill, maxpad); + } + return ok; +} + +static void mi_check_padding(const mi_page_t* page, const mi_block_t* block) { + size_t size; + size_t wrong; + if (!mi_verify_padding(page,block,&size,&wrong)) { + _mi_error_message(EFAULT, "buffer overflow in heap block %p of size %zu: write after %zu bytes\n", block, size, wrong ); + } +} + +#else + +static void mi_check_padding(const mi_page_t* page, const mi_block_t* block) { + MI_UNUSED(page); + MI_UNUSED(block); +} + +#endif + +// only maintain stats for smaller objects if requested +#if (MI_STAT>0) +static void mi_stat_free(const mi_page_t* page, const mi_block_t* block) { + #if (MI_STAT < 2) + MI_UNUSED(block); + #endif + mi_heap_t* const heap = mi_heap_get_default(); + const size_t bsize = mi_page_usable_block_size(page); + #if (MI_STAT>1) + const size_t usize = mi_page_usable_size_of(page, block); + mi_heap_stat_decrease(heap, malloc, usize); + #endif + if (bsize <= MI_MEDIUM_OBJ_SIZE_MAX) { + mi_heap_stat_decrease(heap, normal, bsize); + #if (MI_STAT > 1) + mi_heap_stat_decrease(heap, normal_bins[_mi_bin(bsize)], 1); + #endif + } + else if (bsize <= MI_LARGE_OBJ_SIZE_MAX) { + mi_heap_stat_decrease(heap, large, bsize); + } + else { + mi_heap_stat_decrease(heap, huge, bsize); + } +} +#else +static void mi_stat_free(const mi_page_t* page, const mi_block_t* block) { + MI_UNUSED(page); MI_UNUSED(block); +} +#endif + +#if MI_HUGE_PAGE_ABANDON +#if (MI_STAT>0) +// maintain stats for huge objects +static void mi_stat_huge_free(const mi_page_t* page) { + mi_heap_t* const heap = mi_heap_get_default(); + const size_t bsize = mi_page_block_size(page); // to match stats in `page.c:mi_page_huge_alloc` + if (bsize <= MI_LARGE_OBJ_SIZE_MAX) { + mi_heap_stat_decrease(heap, large, bsize); + } + else { + mi_heap_stat_decrease(heap, huge, bsize); + } +} +#else +static void mi_stat_huge_free(const mi_page_t* page) { + MI_UNUSED(page); +} +#endif +#endif + +// ------------------------------------------------------ +// Free +// ------------------------------------------------------ + +// multi-threaded free (or free in huge block if compiled with MI_HUGE_PAGE_ABANDON) +static mi_decl_noinline void _mi_free_block_mt(mi_page_t* page, mi_block_t* block) +{ + // The padding check may access the non-thread-owned page for the key values. + // that is safe as these are constant and the page won't be freed (as the block is not freed yet). + mi_check_padding(page, block); + _mi_padding_shrink(page, block, sizeof(mi_block_t)); // for small size, ensure we can fit the delayed thread pointers without triggering overflow detection + + // huge page segments are always abandoned and can be freed immediately + mi_segment_t* segment = _mi_page_segment(page); + if (segment->kind == MI_SEGMENT_HUGE) { + #if MI_HUGE_PAGE_ABANDON + // huge page segments are always abandoned and can be freed immediately + mi_stat_huge_free(page); + _mi_segment_huge_page_free(segment, page, block); + return; + #else + // huge pages are special as they occupy the entire segment + // as these are large we reset the memory occupied by the page so it is available to other threads + // (as the owning thread needs to actually free the memory later). + _mi_segment_huge_page_reset(segment, page, block); + #endif + } + + #if (MI_DEBUG>0) && !MI_TRACK_ENABLED && !MI_TSAN // note: when tracking, cannot use mi_usable_size with multi-threading + if (segment->kind != MI_SEGMENT_HUGE) { // not for huge segments as we just reset the content + memset(block, MI_DEBUG_FREED, mi_usable_size(block)); + } + #endif + + // Try to put the block on either the page-local thread free list, or the heap delayed free list. + mi_thread_free_t tfreex; + bool use_delayed; + mi_thread_free_t tfree = mi_atomic_load_relaxed(&page->xthread_free); + do { + use_delayed = (mi_tf_delayed(tfree) == MI_USE_DELAYED_FREE); + if mi_unlikely(use_delayed) { + // unlikely: this only happens on the first concurrent free in a page that is in the full list + tfreex = mi_tf_set_delayed(tfree,MI_DELAYED_FREEING); + } + else { + // usual: directly add to page thread_free list + mi_block_set_next(page, block, mi_tf_block(tfree)); + tfreex = mi_tf_set_block(tfree,block); + } + } while (!mi_atomic_cas_weak_release(&page->xthread_free, &tfree, tfreex)); + + if mi_unlikely(use_delayed) { + // racy read on `heap`, but ok because MI_DELAYED_FREEING is set (see `mi_heap_delete` and `mi_heap_collect_abandon`) + mi_heap_t* const heap = (mi_heap_t*)(mi_atomic_load_acquire(&page->xheap)); //mi_page_heap(page); + mi_assert_internal(heap != NULL); + if (heap != NULL) { + // add to the delayed free list of this heap. (do this atomically as the lock only protects heap memory validity) + mi_block_t* dfree = mi_atomic_load_ptr_relaxed(mi_block_t, &heap->thread_delayed_free); + do { + mi_block_set_nextx(heap,block,dfree, heap->keys); + } while (!mi_atomic_cas_ptr_weak_release(mi_block_t,&heap->thread_delayed_free, &dfree, block)); + } + + // and reset the MI_DELAYED_FREEING flag + tfree = mi_atomic_load_relaxed(&page->xthread_free); + do { + tfreex = tfree; + mi_assert_internal(mi_tf_delayed(tfree) == MI_DELAYED_FREEING); + tfreex = mi_tf_set_delayed(tfree,MI_NO_DELAYED_FREE); + } while (!mi_atomic_cas_weak_release(&page->xthread_free, &tfree, tfreex)); + } +} + +// regular free +static inline void _mi_free_block(mi_page_t* page, bool local, mi_block_t* block) +{ + // and push it on the free list + //const size_t bsize = mi_page_block_size(page); + if mi_likely(local) { + // owning thread can free a block directly + if mi_unlikely(mi_check_is_double_free(page, block)) return; + mi_check_padding(page, block); + #if (MI_DEBUG>0) && !MI_TRACK_ENABLED && !MI_TSAN + if (!mi_page_is_huge(page)) { // huge page content may be already decommitted + memset(block, MI_DEBUG_FREED, mi_page_block_size(page)); + } + #endif + mi_block_set_next(page, block, page->local_free); + page->local_free = block; + page->used--; + if mi_unlikely(mi_page_all_free(page)) { + _mi_page_retire(page); + } + else if mi_unlikely(mi_page_is_in_full(page)) { + _mi_page_unfull(page); + } + } + else { + _mi_free_block_mt(page,block); + } +} + + +// Adjust a block that was allocated aligned, to the actual start of the block in the page. +mi_block_t* _mi_page_ptr_unalign(const mi_segment_t* segment, const mi_page_t* page, const void* p) { + mi_assert_internal(page!=NULL && p!=NULL); + const size_t diff = (uint8_t*)p - _mi_page_start(segment, page, NULL); + const size_t adjust = (diff % mi_page_block_size(page)); + return (mi_block_t*)((uintptr_t)p - adjust); +} + + +void mi_decl_noinline _mi_free_generic(const mi_segment_t* segment, mi_page_t* page, bool is_local, void* p) mi_attr_noexcept { + mi_block_t* const block = (mi_page_has_aligned(page) ? _mi_page_ptr_unalign(segment, page, p) : (mi_block_t*)p); + mi_stat_free(page, block); // stat_free may access the padding + mi_track_free_size(block, mi_page_usable_size_of(page,block)); + _mi_free_block(page, is_local, block); +} + +// Get the segment data belonging to a pointer +// This is just a single `and` in assembly but does further checks in debug mode +// (and secure mode) if this was a valid pointer. +static inline mi_segment_t* mi_checked_ptr_segment(const void* p, const char* msg) +{ + MI_UNUSED(msg); + mi_assert(p != NULL); + +#if (MI_DEBUG>0) + if mi_unlikely(((uintptr_t)p & (MI_INTPTR_SIZE - 1)) != 0) { + _mi_error_message(EINVAL, "%s: invalid (unaligned) pointer: %p\n", msg, p); + return NULL; + } +#endif + + mi_segment_t* const segment = _mi_ptr_segment(p); + mi_assert_internal(segment != NULL); + +#if 0 && (MI_DEBUG>0) + if mi_unlikely(!mi_is_in_heap_region(p)) { + #if (MI_INTPTR_SIZE == 8 && defined(__linux__)) + if (((uintptr_t)p >> 40) != 0x7F) { // linux tends to align large blocks above 0x7F000000000 (issue #640) + #else + { + #endif + _mi_warning_message("%s: pointer might not point to a valid heap region: %p\n" + "(this may still be a valid very large allocation (over 64MiB))\n", msg, p); + if mi_likely(_mi_ptr_cookie(segment) == segment->cookie) { + _mi_warning_message("(yes, the previous pointer %p was valid after all)\n", p); + } + } + } +#endif +#if (MI_DEBUG>0 || MI_SECURE>=4) + if mi_unlikely(_mi_ptr_cookie(segment) != segment->cookie) { + _mi_error_message(EINVAL, "%s: pointer does not point to a valid heap space: %p\n", msg, p); + return NULL; + } +#endif + + return segment; +} + +// Free a block +// fast path written carefully to prevent spilling on the stack +void mi_free(void* p) mi_attr_noexcept +{ + if mi_unlikely(p == NULL) return; + mi_segment_t* const segment = mi_checked_ptr_segment(p,"mi_free"); + const bool is_local= (_mi_prim_thread_id() == mi_atomic_load_relaxed(&segment->thread_id)); + mi_page_t* const page = _mi_segment_page_of(segment, p); + + if mi_likely(is_local) { // thread-local free? + if mi_likely(page->flags.full_aligned == 0) // and it is not a full page (full pages need to move from the full bin), nor has aligned blocks (aligned blocks need to be unaligned) + { + mi_block_t* const block = (mi_block_t*)p; + if mi_unlikely(mi_check_is_double_free(page, block)) return; + mi_check_padding(page, block); + mi_stat_free(page, block); + #if (MI_DEBUG>0) && !MI_TRACK_ENABLED && !MI_TSAN + memset(block, MI_DEBUG_FREED, mi_page_block_size(page)); + #endif + mi_track_free_size(p, mi_page_usable_size_of(page,block)); // faster then mi_usable_size as we already know the page and that p is unaligned + mi_block_set_next(page, block, page->local_free); + page->local_free = block; + if mi_unlikely(--page->used == 0) { // using this expression generates better code than: page->used--; if (mi_page_all_free(page)) + _mi_page_retire(page); + } + } + else { + // page is full or contains (inner) aligned blocks; use generic path + _mi_free_generic(segment, page, true, p); + } + } + else { + // not thread-local; use generic path + _mi_free_generic(segment, page, false, p); + } +} + +// return true if successful +bool _mi_free_delayed_block(mi_block_t* block) { + // get segment and page + const mi_segment_t* const segment = _mi_ptr_segment(block); + mi_assert_internal(_mi_ptr_cookie(segment) == segment->cookie); + mi_assert_internal(_mi_thread_id() == segment->thread_id); + mi_page_t* const page = _mi_segment_page_of(segment, block); + + // Clear the no-delayed flag so delayed freeing is used again for this page. + // This must be done before collecting the free lists on this page -- otherwise + // some blocks may end up in the page `thread_free` list with no blocks in the + // heap `thread_delayed_free` list which may cause the page to be never freed! + // (it would only be freed if we happen to scan it in `mi_page_queue_find_free_ex`) + if (!_mi_page_try_use_delayed_free(page, MI_USE_DELAYED_FREE, false /* dont overwrite never delayed */)) { + return false; + } + + // collect all other non-local frees to ensure up-to-date `used` count + _mi_page_free_collect(page, false); + + // and free the block (possibly freeing the page as well since used is updated) + _mi_free_block(page, true, block); + return true; +} + +// Bytes available in a block +mi_decl_noinline static size_t mi_page_usable_aligned_size_of(const mi_segment_t* segment, const mi_page_t* page, const void* p) mi_attr_noexcept { + const mi_block_t* block = _mi_page_ptr_unalign(segment, page, p); + const size_t size = mi_page_usable_size_of(page, block); + const ptrdiff_t adjust = (uint8_t*)p - (uint8_t*)block; + mi_assert_internal(adjust >= 0 && (size_t)adjust <= size); + return (size - adjust); +} + +static inline size_t _mi_usable_size(const void* p, const char* msg) mi_attr_noexcept { + if (p == NULL) return 0; + const mi_segment_t* const segment = mi_checked_ptr_segment(p, msg); + const mi_page_t* const page = _mi_segment_page_of(segment, p); + if mi_likely(!mi_page_has_aligned(page)) { + const mi_block_t* block = (const mi_block_t*)p; + return mi_page_usable_size_of(page, block); + } + else { + // split out to separate routine for improved code generation + return mi_page_usable_aligned_size_of(segment, page, p); + } +} + +mi_decl_nodiscard size_t mi_usable_size(const void* p) mi_attr_noexcept { + return _mi_usable_size(p, "mi_usable_size"); +} + + +// ------------------------------------------------------ +// Allocation extensions +// ------------------------------------------------------ + +void mi_free_size(void* p, size_t size) mi_attr_noexcept { + MI_UNUSED_RELEASE(size); + mi_assert(p == NULL || size <= _mi_usable_size(p,"mi_free_size")); + mi_free(p); +} + +void mi_free_size_aligned(void* p, size_t size, size_t alignment) mi_attr_noexcept { + MI_UNUSED_RELEASE(alignment); + mi_assert(((uintptr_t)p % alignment) == 0); + mi_free_size(p,size); +} + +void mi_free_aligned(void* p, size_t alignment) mi_attr_noexcept { + MI_UNUSED_RELEASE(alignment); + mi_assert(((uintptr_t)p % alignment) == 0); + mi_free(p); +} + +mi_decl_nodiscard extern inline mi_decl_restrict void* mi_heap_calloc(mi_heap_t* heap, size_t count, size_t size) mi_attr_noexcept { + size_t total; + if (mi_count_size_overflow(count,size,&total)) return NULL; + return mi_heap_zalloc(heap,total); +} + +mi_decl_nodiscard mi_decl_restrict void* mi_calloc(size_t count, size_t size) mi_attr_noexcept { + return mi_heap_calloc(mi_prim_get_default_heap(),count,size); +} + +// Uninitialized `calloc` +mi_decl_nodiscard extern mi_decl_restrict void* mi_heap_mallocn(mi_heap_t* heap, size_t count, size_t size) mi_attr_noexcept { + size_t total; + if (mi_count_size_overflow(count, size, &total)) return NULL; + return mi_heap_malloc(heap, total); +} + +mi_decl_nodiscard mi_decl_restrict void* mi_mallocn(size_t count, size_t size) mi_attr_noexcept { + return mi_heap_mallocn(mi_prim_get_default_heap(),count,size); +} + +// Expand (or shrink) in place (or fail) +void* mi_expand(void* p, size_t newsize) mi_attr_noexcept { + #if MI_PADDING + // we do not shrink/expand with padding enabled + MI_UNUSED(p); MI_UNUSED(newsize); + return NULL; + #else + if (p == NULL) return NULL; + const size_t size = _mi_usable_size(p,"mi_expand"); + if (newsize > size) return NULL; + return p; // it fits + #endif +} + +void* _mi_heap_realloc_zero(mi_heap_t* heap, void* p, size_t newsize, bool zero) mi_attr_noexcept { + // if p == NULL then behave as malloc. + // else if size == 0 then reallocate to a zero-sized block (and don't return NULL, just as mi_malloc(0)). + // (this means that returning NULL always indicates an error, and `p` will not have been freed in that case.) + const size_t size = _mi_usable_size(p,"mi_realloc"); // also works if p == NULL (with size 0) + if mi_unlikely(newsize <= size && newsize >= (size / 2) && newsize > 0) { // note: newsize must be > 0 or otherwise we return NULL for realloc(NULL,0) + mi_assert_internal(p!=NULL); + // todo: do not track as the usable size is still the same in the free; adjust potential padding? + // mi_track_resize(p,size,newsize) + // if (newsize < size) { mi_track_mem_noaccess((uint8_t*)p + newsize, size - newsize); } + return p; // reallocation still fits and not more than 50% waste + } + void* newp = mi_heap_malloc(heap,newsize); + if mi_likely(newp != NULL) { + if (zero && newsize > size) { + // also set last word in the previous allocation to zero to ensure any padding is zero-initialized + const size_t start = (size >= sizeof(intptr_t) ? size - sizeof(intptr_t) : 0); + _mi_memzero((uint8_t*)newp + start, newsize - start); + } + else if (newsize == 0) { + ((uint8_t*)newp)[0] = 0; // work around for applications that expect zero-reallocation to be zero initialized (issue #725) + } + if mi_likely(p != NULL) { + const size_t copysize = (newsize > size ? size : newsize); + mi_track_mem_defined(p,copysize); // _mi_useable_size may be too large for byte precise memory tracking.. + _mi_memcpy(newp, p, copysize); + mi_free(p); // only free the original pointer if successful + } + } + return newp; +} + +mi_decl_nodiscard void* mi_heap_realloc(mi_heap_t* heap, void* p, size_t newsize) mi_attr_noexcept { + return _mi_heap_realloc_zero(heap, p, newsize, false); +} + +mi_decl_nodiscard void* mi_heap_reallocn(mi_heap_t* heap, void* p, size_t count, size_t size) mi_attr_noexcept { + size_t total; + if (mi_count_size_overflow(count, size, &total)) return NULL; + return mi_heap_realloc(heap, p, total); +} + + +// Reallocate but free `p` on errors +mi_decl_nodiscard void* mi_heap_reallocf(mi_heap_t* heap, void* p, size_t newsize) mi_attr_noexcept { + void* newp = mi_heap_realloc(heap, p, newsize); + if (newp==NULL && p!=NULL) mi_free(p); + return newp; +} + +mi_decl_nodiscard void* mi_heap_rezalloc(mi_heap_t* heap, void* p, size_t newsize) mi_attr_noexcept { + return _mi_heap_realloc_zero(heap, p, newsize, true); +} + +mi_decl_nodiscard void* mi_heap_recalloc(mi_heap_t* heap, void* p, size_t count, size_t size) mi_attr_noexcept { + size_t total; + if (mi_count_size_overflow(count, size, &total)) return NULL; + return mi_heap_rezalloc(heap, p, total); +} + + +mi_decl_nodiscard void* mi_realloc(void* p, size_t newsize) mi_attr_noexcept { + return mi_heap_realloc(mi_prim_get_default_heap(),p,newsize); +} + +mi_decl_nodiscard void* mi_reallocn(void* p, size_t count, size_t size) mi_attr_noexcept { + return mi_heap_reallocn(mi_prim_get_default_heap(),p,count,size); +} + +// Reallocate but free `p` on errors +mi_decl_nodiscard void* mi_reallocf(void* p, size_t newsize) mi_attr_noexcept { + return mi_heap_reallocf(mi_prim_get_default_heap(),p,newsize); +} + +mi_decl_nodiscard void* mi_rezalloc(void* p, size_t newsize) mi_attr_noexcept { + return mi_heap_rezalloc(mi_prim_get_default_heap(), p, newsize); +} + +mi_decl_nodiscard void* mi_recalloc(void* p, size_t count, size_t size) mi_attr_noexcept { + return mi_heap_recalloc(mi_prim_get_default_heap(), p, count, size); +} + + + +// ------------------------------------------------------ +// strdup, strndup, and realpath +// ------------------------------------------------------ + +// `strdup` using mi_malloc +mi_decl_nodiscard mi_decl_restrict char* mi_heap_strdup(mi_heap_t* heap, const char* s) mi_attr_noexcept { + if (s == NULL) return NULL; + size_t n = strlen(s); + char* t = (char*)mi_heap_malloc(heap,n+1); + if (t == NULL) return NULL; + _mi_memcpy(t, s, n); + t[n] = 0; + return t; +} + +mi_decl_nodiscard mi_decl_restrict char* mi_strdup(const char* s) mi_attr_noexcept { + return mi_heap_strdup(mi_prim_get_default_heap(), s); +} + +// `strndup` using mi_malloc +mi_decl_nodiscard mi_decl_restrict char* mi_heap_strndup(mi_heap_t* heap, const char* s, size_t n) mi_attr_noexcept { + if (s == NULL) return NULL; + const char* end = (const char*)memchr(s, 0, n); // find end of string in the first `n` characters (returns NULL if not found) + const size_t m = (end != NULL ? (size_t)(end - s) : n); // `m` is the minimum of `n` or the end-of-string + mi_assert_internal(m <= n); + char* t = (char*)mi_heap_malloc(heap, m+1); + if (t == NULL) return NULL; + _mi_memcpy(t, s, m); + t[m] = 0; + return t; +} + +mi_decl_nodiscard mi_decl_restrict char* mi_strndup(const char* s, size_t n) mi_attr_noexcept { + return mi_heap_strndup(mi_prim_get_default_heap(),s,n); +} + +#ifndef __wasi__ +// `realpath` using mi_malloc +#ifdef _WIN32 +#ifndef PATH_MAX +#define PATH_MAX MAX_PATH +#endif +#include +mi_decl_nodiscard mi_decl_restrict char* mi_heap_realpath(mi_heap_t* heap, const char* fname, char* resolved_name) mi_attr_noexcept { + // todo: use GetFullPathNameW to allow longer file names + char buf[PATH_MAX]; + DWORD res = GetFullPathNameA(fname, PATH_MAX, (resolved_name == NULL ? buf : resolved_name), NULL); + if (res == 0) { + errno = GetLastError(); return NULL; + } + else if (res > PATH_MAX) { + errno = EINVAL; return NULL; + } + else if (resolved_name != NULL) { + return resolved_name; + } + else { + return mi_heap_strndup(heap, buf, PATH_MAX); + } +} +#else +/* +#include // pathconf +static size_t mi_path_max(void) { + static size_t path_max = 0; + if (path_max <= 0) { + long m = pathconf("/",_PC_PATH_MAX); + if (m <= 0) path_max = 4096; // guess + else if (m < 256) path_max = 256; // at least 256 + else path_max = m; + } + return path_max; +} +*/ +char* mi_heap_realpath(mi_heap_t* heap, const char* fname, char* resolved_name) mi_attr_noexcept { + if (resolved_name != NULL) { + return realpath(fname,resolved_name); + } + else { + char* rname = realpath(fname, NULL); + if (rname == NULL) return NULL; + char* result = mi_heap_strdup(heap, rname); + free(rname); // use regular free! (which may be redirected to our free but that's ok) + return result; + } + /* + const size_t n = mi_path_max(); + char* buf = (char*)mi_malloc(n+1); + if (buf == NULL) { + errno = ENOMEM; + return NULL; + } + char* rname = realpath(fname,buf); + char* result = mi_heap_strndup(heap,rname,n); // ok if `rname==NULL` + mi_free(buf); + return result; + } + */ +} +#endif + +mi_decl_nodiscard mi_decl_restrict char* mi_realpath(const char* fname, char* resolved_name) mi_attr_noexcept { + return mi_heap_realpath(mi_prim_get_default_heap(),fname,resolved_name); +} +#endif + +/*------------------------------------------------------- +C++ new and new_aligned +The standard requires calling into `get_new_handler` and +throwing the bad_alloc exception on failure. If we compile +with a C++ compiler we can implement this precisely. If we +use a C compiler we cannot throw a `bad_alloc` exception +but we call `exit` instead (i.e. not returning). +-------------------------------------------------------*/ + +#ifdef __cplusplus +#include +static bool mi_try_new_handler(bool nothrow) { + #if defined(_MSC_VER) || (__cplusplus >= 201103L) + std::new_handler h = std::get_new_handler(); + #else + std::new_handler h = std::set_new_handler(); + std::set_new_handler(h); + #endif + if (h==NULL) { + _mi_error_message(ENOMEM, "out of memory in 'new'"); + if (!nothrow) { + throw std::bad_alloc(); + } + return false; + } + else { + h(); + return true; + } +} +#else +typedef void (*std_new_handler_t)(void); + +#if (defined(__GNUC__) || (defined(__clang__) && !defined(_MSC_VER))) // exclude clang-cl, see issue #631 +std_new_handler_t __attribute__((weak)) _ZSt15get_new_handlerv(void) { + return NULL; +} +static std_new_handler_t mi_get_new_handler(void) { + return _ZSt15get_new_handlerv(); +} +#else +// note: on windows we could dynamically link to `?get_new_handler@std@@YAP6AXXZXZ`. +static std_new_handler_t mi_get_new_handler() { + return NULL; +} +#endif + +static bool mi_try_new_handler(bool nothrow) { + std_new_handler_t h = mi_get_new_handler(); + if (h==NULL) { + _mi_error_message(ENOMEM, "out of memory in 'new'"); + if (!nothrow) { + abort(); // cannot throw in plain C, use abort + } + return false; + } + else { + h(); + return true; + } +} +#endif + +mi_decl_export mi_decl_noinline void* mi_heap_try_new(mi_heap_t* heap, size_t size, bool nothrow ) { + void* p = NULL; + while(p == NULL && mi_try_new_handler(nothrow)) { + p = mi_heap_malloc(heap,size); + } + return p; +} + +static mi_decl_noinline void* mi_try_new(size_t size, bool nothrow) { + return mi_heap_try_new(mi_prim_get_default_heap(), size, nothrow); +} + + +mi_decl_nodiscard mi_decl_restrict void* mi_heap_alloc_new(mi_heap_t* heap, size_t size) { + void* p = mi_heap_malloc(heap,size); + if mi_unlikely(p == NULL) return mi_heap_try_new(heap, size, false); + return p; +} + +mi_decl_nodiscard mi_decl_restrict void* mi_new(size_t size) { + return mi_heap_alloc_new(mi_prim_get_default_heap(), size); +} + + +mi_decl_nodiscard mi_decl_restrict void* mi_heap_alloc_new_n(mi_heap_t* heap, size_t count, size_t size) { + size_t total; + if mi_unlikely(mi_count_size_overflow(count, size, &total)) { + mi_try_new_handler(false); // on overflow we invoke the try_new_handler once to potentially throw std::bad_alloc + return NULL; + } + else { + return mi_heap_alloc_new(heap,total); + } +} + +mi_decl_nodiscard mi_decl_restrict void* mi_new_n(size_t count, size_t size) { + return mi_heap_alloc_new_n(mi_prim_get_default_heap(), size, count); +} + + +mi_decl_nodiscard mi_decl_restrict void* mi_new_nothrow(size_t size) mi_attr_noexcept { + void* p = mi_malloc(size); + if mi_unlikely(p == NULL) return mi_try_new(size, true); + return p; +} + +mi_decl_nodiscard mi_decl_restrict void* mi_new_aligned(size_t size, size_t alignment) { + void* p; + do { + p = mi_malloc_aligned(size, alignment); + } + while(p == NULL && mi_try_new_handler(false)); + return p; +} + +mi_decl_nodiscard mi_decl_restrict void* mi_new_aligned_nothrow(size_t size, size_t alignment) mi_attr_noexcept { + void* p; + do { + p = mi_malloc_aligned(size, alignment); + } + while(p == NULL && mi_try_new_handler(true)); + return p; +} + +mi_decl_nodiscard void* mi_new_realloc(void* p, size_t newsize) { + void* q; + do { + q = mi_realloc(p, newsize); + } while (q == NULL && mi_try_new_handler(false)); + return q; +} + +mi_decl_nodiscard void* mi_new_reallocn(void* p, size_t newcount, size_t size) { + size_t total; + if mi_unlikely(mi_count_size_overflow(newcount, size, &total)) { + mi_try_new_handler(false); // on overflow we invoke the try_new_handler once to potentially throw std::bad_alloc + return NULL; + } + else { + return mi_new_realloc(p, total); + } +} + +// ------------------------------------------------------ +// ensure explicit external inline definitions are emitted! +// ------------------------------------------------------ + +#ifdef __cplusplus +void* _mi_externs[] = { + (void*)&_mi_page_malloc, + (void*)&_mi_heap_malloc_zero, + (void*)&_mi_heap_malloc_zero_ex, + (void*)&mi_malloc, + (void*)&mi_malloc_small, + (void*)&mi_zalloc_small, + (void*)&mi_heap_malloc, + (void*)&mi_heap_zalloc, + (void*)&mi_heap_malloc_small, + // (void*)&mi_heap_alloc_new, + // (void*)&mi_heap_alloc_new_n +}; +#endif diff --git a/Objects/mimalloc/arena.c b/Objects/mimalloc/arena.c new file mode 100644 index 00000000000000..f8883603860dce --- /dev/null +++ b/Objects/mimalloc/arena.c @@ -0,0 +1,935 @@ +/* ---------------------------------------------------------------------------- +Copyright (c) 2019-2023, Microsoft Research, Daan Leijen +This is free software; you can redistribute it and/or modify it under the +terms of the MIT license. A copy of the license can be found in the file +"LICENSE" at the root of this distribution. +-----------------------------------------------------------------------------*/ + +/* ---------------------------------------------------------------------------- +"Arenas" are fixed area's of OS memory from which we can allocate +large blocks (>= MI_ARENA_MIN_BLOCK_SIZE, 4MiB). +In contrast to the rest of mimalloc, the arenas are shared between +threads and need to be accessed using atomic operations. + +Arenas are used to for huge OS page (1GiB) reservations or for reserving +OS memory upfront which can be improve performance or is sometimes needed +on embedded devices. We can also employ this with WASI or `sbrk` systems +to reserve large arenas upfront and be able to reuse the memory more effectively. + +The arena allocation needs to be thread safe and we use an atomic bitmap to allocate. +-----------------------------------------------------------------------------*/ +#include "mimalloc.h" +#include "mimalloc/internal.h" +#include "mimalloc/atomic.h" + +#include // memset +#include // ENOMEM + +#include "bitmap.h" // atomic bitmap + +/* ----------------------------------------------------------- + Arena allocation +----------------------------------------------------------- */ + +// Block info: bit 0 contains the `in_use` bit, the upper bits the +// size in count of arena blocks. +typedef uintptr_t mi_block_info_t; +#define MI_ARENA_BLOCK_SIZE (MI_SEGMENT_SIZE) // 64MiB (must be at least MI_SEGMENT_ALIGN) +#define MI_ARENA_MIN_OBJ_SIZE (MI_ARENA_BLOCK_SIZE/2) // 32MiB +#define MI_MAX_ARENAS (112) // not more than 126 (since we use 7 bits in the memid and an arena index + 1) + +// A memory arena descriptor +typedef struct mi_arena_s { + mi_arena_id_t id; // arena id; 0 for non-specific + mi_memid_t memid; // memid of the memory area + _Atomic(uint8_t*) start; // the start of the memory area + size_t block_count; // size of the area in arena blocks (of `MI_ARENA_BLOCK_SIZE`) + size_t field_count; // number of bitmap fields (where `field_count * MI_BITMAP_FIELD_BITS >= block_count`) + size_t meta_size; // size of the arena structure itself (including its bitmaps) + mi_memid_t meta_memid; // memid of the arena structure itself (OS or static allocation) + int numa_node; // associated NUMA node + bool exclusive; // only allow allocations if specifically for this arena + bool is_large; // memory area consists of large- or huge OS pages (always committed) + _Atomic(size_t) search_idx; // optimization to start the search for free blocks + _Atomic(mi_msecs_t) purge_expire; // expiration time when blocks should be decommitted from `blocks_decommit`. + mi_bitmap_field_t* blocks_dirty; // are the blocks potentially non-zero? + mi_bitmap_field_t* blocks_committed; // are the blocks committed? (can be NULL for memory that cannot be decommitted) + mi_bitmap_field_t* blocks_purge; // blocks that can be (reset) decommitted. (can be NULL for memory that cannot be (reset) decommitted) + mi_bitmap_field_t blocks_inuse[1]; // in-place bitmap of in-use blocks (of size `field_count`) +} mi_arena_t; + + +// The available arenas +static mi_decl_cache_align _Atomic(mi_arena_t*) mi_arenas[MI_MAX_ARENAS]; +static mi_decl_cache_align _Atomic(size_t) mi_arena_count; // = 0 + + +//static bool mi_manage_os_memory_ex2(void* start, size_t size, bool is_large, int numa_node, bool exclusive, mi_memid_t memid, mi_arena_id_t* arena_id) mi_attr_noexcept; + +/* ----------------------------------------------------------- + Arena id's + id = arena_index + 1 +----------------------------------------------------------- */ + +static size_t mi_arena_id_index(mi_arena_id_t id) { + return (size_t)(id <= 0 ? MI_MAX_ARENAS : id - 1); +} + +static mi_arena_id_t mi_arena_id_create(size_t arena_index) { + mi_assert_internal(arena_index < MI_MAX_ARENAS); + return (int)arena_index + 1; +} + +mi_arena_id_t _mi_arena_id_none(void) { + return 0; +} + +static bool mi_arena_id_is_suitable(mi_arena_id_t arena_id, bool arena_is_exclusive, mi_arena_id_t req_arena_id) { + return ((!arena_is_exclusive && req_arena_id == _mi_arena_id_none()) || + (arena_id == req_arena_id)); +} + +bool _mi_arena_memid_is_suitable(mi_memid_t memid, mi_arena_id_t request_arena_id) { + if (memid.memkind == MI_MEM_ARENA) { + return mi_arena_id_is_suitable(memid.mem.arena.id, memid.mem.arena.is_exclusive, request_arena_id); + } + else { + return mi_arena_id_is_suitable(0, false, request_arena_id); + } +} + +bool _mi_arena_memid_is_os_allocated(mi_memid_t memid) { + return (memid.memkind == MI_MEM_OS); +} + +/* ----------------------------------------------------------- + Arena allocations get a (currently) 16-bit memory id where the + lower 8 bits are the arena id, and the upper bits the block index. +----------------------------------------------------------- */ + +static size_t mi_block_count_of_size(size_t size) { + return _mi_divide_up(size, MI_ARENA_BLOCK_SIZE); +} + +static size_t mi_arena_block_size(size_t bcount) { + return (bcount * MI_ARENA_BLOCK_SIZE); +} + +static size_t mi_arena_size(mi_arena_t* arena) { + return mi_arena_block_size(arena->block_count); +} + +static mi_memid_t mi_memid_create_arena(mi_arena_id_t id, bool is_exclusive, mi_bitmap_index_t bitmap_index) { + mi_memid_t memid = _mi_memid_create(MI_MEM_ARENA); + memid.mem.arena.id = id; + memid.mem.arena.block_index = bitmap_index; + memid.mem.arena.is_exclusive = is_exclusive; + return memid; +} + +static bool mi_arena_memid_indices(mi_memid_t memid, size_t* arena_index, mi_bitmap_index_t* bitmap_index) { + mi_assert_internal(memid.memkind == MI_MEM_ARENA); + *arena_index = mi_arena_id_index(memid.mem.arena.id); + *bitmap_index = memid.mem.arena.block_index; + return memid.mem.arena.is_exclusive; +} + + + +/* ----------------------------------------------------------- + Special static area for mimalloc internal structures + to avoid OS calls (for example, for the arena metadata) +----------------------------------------------------------- */ + +#define MI_ARENA_STATIC_MAX (MI_INTPTR_SIZE*MI_KiB) // 8 KiB on 64-bit + +static uint8_t mi_arena_static[MI_ARENA_STATIC_MAX]; +static _Atomic(size_t) mi_arena_static_top; + +static void* mi_arena_static_zalloc(size_t size, size_t alignment, mi_memid_t* memid) { + *memid = _mi_memid_none(); + if (size == 0 || size > MI_ARENA_STATIC_MAX) return NULL; + if ((mi_atomic_load_relaxed(&mi_arena_static_top) + size) > MI_ARENA_STATIC_MAX) return NULL; + + // try to claim space + if (alignment == 0) { alignment = 1; } + const size_t oversize = size + alignment - 1; + if (oversize > MI_ARENA_STATIC_MAX) return NULL; + const size_t oldtop = mi_atomic_add_acq_rel(&mi_arena_static_top, oversize); + size_t top = oldtop + oversize; + if (top > MI_ARENA_STATIC_MAX) { + // try to roll back, ok if this fails + mi_atomic_cas_strong_acq_rel(&mi_arena_static_top, &top, oldtop); + return NULL; + } + + // success + *memid = _mi_memid_create(MI_MEM_STATIC); + const size_t start = _mi_align_up(oldtop, alignment); + uint8_t* const p = &mi_arena_static[start]; + _mi_memzero(p, size); + return p; +} + +static void* mi_arena_meta_zalloc(size_t size, mi_memid_t* memid, mi_stats_t* stats) { + *memid = _mi_memid_none(); + + // try static + void* p = mi_arena_static_zalloc(size, MI_ALIGNMENT_MAX, memid); + if (p != NULL) return p; + + // or fall back to the OS + return _mi_os_alloc(size, memid, stats); +} + +static void mi_arena_meta_free(void* p, mi_memid_t memid, size_t size, mi_stats_t* stats) { + if (mi_memkind_is_os(memid.memkind)) { + _mi_os_free(p, size, memid, stats); + } + else { + mi_assert(memid.memkind == MI_MEM_STATIC); + } +} + +static void* mi_arena_block_start(mi_arena_t* arena, mi_bitmap_index_t bindex) { + return (arena->start + mi_arena_block_size(mi_bitmap_index_bit(bindex))); +} + + +/* ----------------------------------------------------------- + Thread safe allocation in an arena +----------------------------------------------------------- */ + +// claim the `blocks_inuse` bits +static bool mi_arena_try_claim(mi_arena_t* arena, size_t blocks, mi_bitmap_index_t* bitmap_idx) +{ + size_t idx = 0; // mi_atomic_load_relaxed(&arena->search_idx); // start from last search; ok to be relaxed as the exact start does not matter + if (_mi_bitmap_try_find_from_claim_across(arena->blocks_inuse, arena->field_count, idx, blocks, bitmap_idx)) { + mi_atomic_store_relaxed(&arena->search_idx, mi_bitmap_index_field(*bitmap_idx)); // start search from found location next time around + return true; + }; + return false; +} + + +/* ----------------------------------------------------------- + Arena Allocation +----------------------------------------------------------- */ + +static mi_decl_noinline void* mi_arena_try_alloc_at(mi_arena_t* arena, size_t arena_index, size_t needed_bcount, + bool commit, mi_memid_t* memid, mi_os_tld_t* tld) +{ + MI_UNUSED(arena_index); + mi_assert_internal(mi_arena_id_index(arena->id) == arena_index); + + mi_bitmap_index_t bitmap_index; + if (!mi_arena_try_claim(arena, needed_bcount, &bitmap_index)) return NULL; + + // claimed it! + void* p = mi_arena_block_start(arena, bitmap_index); + *memid = mi_memid_create_arena(arena->id, arena->exclusive, bitmap_index); + memid->is_pinned = arena->memid.is_pinned; + + // none of the claimed blocks should be scheduled for a decommit + if (arena->blocks_purge != NULL) { + // this is thread safe as a potential purge only decommits parts that are not yet claimed as used (in `blocks_inuse`). + _mi_bitmap_unclaim_across(arena->blocks_purge, arena->field_count, needed_bcount, bitmap_index); + } + + // set the dirty bits (todo: no need for an atomic op here?) + if (arena->memid.initially_zero && arena->blocks_dirty != NULL) { + memid->initially_zero = _mi_bitmap_claim_across(arena->blocks_dirty, arena->field_count, needed_bcount, bitmap_index, NULL); + } + + // set commit state + if (arena->blocks_committed == NULL) { + // always committed + memid->initially_committed = true; + } + else if (commit) { + // commit requested, but the range may not be committed as a whole: ensure it is committed now + memid->initially_committed = true; + bool any_uncommitted; + _mi_bitmap_claim_across(arena->blocks_committed, arena->field_count, needed_bcount, bitmap_index, &any_uncommitted); + if (any_uncommitted) { + bool commit_zero = false; + if (!_mi_os_commit(p, mi_arena_block_size(needed_bcount), &commit_zero, tld->stats)) { + memid->initially_committed = false; + } + else { + if (commit_zero) { memid->initially_zero = true; } + } + } + } + else { + // no need to commit, but check if already fully committed + memid->initially_committed = _mi_bitmap_is_claimed_across(arena->blocks_committed, arena->field_count, needed_bcount, bitmap_index); + } + + return p; +} + +// allocate in a speficic arena +static void* mi_arena_try_alloc_at_id(mi_arena_id_t arena_id, bool match_numa_node, int numa_node, size_t size, size_t alignment, + bool commit, bool allow_large, mi_arena_id_t req_arena_id, mi_memid_t* memid, mi_os_tld_t* tld ) +{ + MI_UNUSED_RELEASE(alignment); + mi_assert_internal(alignment <= MI_SEGMENT_ALIGN); + const size_t bcount = mi_block_count_of_size(size); + const size_t arena_index = mi_arena_id_index(arena_id); + mi_assert_internal(arena_index < mi_atomic_load_relaxed(&mi_arena_count)); + mi_assert_internal(size <= mi_arena_block_size(bcount)); + + // Check arena suitability + mi_arena_t* arena = mi_atomic_load_ptr_acquire(mi_arena_t, &mi_arenas[arena_index]); + if (arena == NULL) return NULL; + if (!allow_large && arena->is_large) return NULL; + if (!mi_arena_id_is_suitable(arena->id, arena->exclusive, req_arena_id)) return NULL; + if (req_arena_id == _mi_arena_id_none()) { // in not specific, check numa affinity + const bool numa_suitable = (numa_node < 0 || arena->numa_node < 0 || arena->numa_node == numa_node); + if (match_numa_node) { if (!numa_suitable) return NULL; } + else { if (numa_suitable) return NULL; } + } + + // try to allocate + void* p = mi_arena_try_alloc_at(arena, arena_index, bcount, commit, memid, tld); + mi_assert_internal(p == NULL || _mi_is_aligned(p, alignment)); + return p; +} + + +// allocate from an arena with fallback to the OS +static mi_decl_noinline void* mi_arena_try_alloc(int numa_node, size_t size, size_t alignment, + bool commit, bool allow_large, + mi_arena_id_t req_arena_id, mi_memid_t* memid, mi_os_tld_t* tld ) +{ + MI_UNUSED(alignment); + mi_assert_internal(alignment <= MI_SEGMENT_ALIGN); + const size_t max_arena = mi_atomic_load_relaxed(&mi_arena_count); + if mi_likely(max_arena == 0) return NULL; + + if (req_arena_id != _mi_arena_id_none()) { + // try a specific arena if requested + if (mi_arena_id_index(req_arena_id) < max_arena) { + void* p = mi_arena_try_alloc_at_id(req_arena_id, true, numa_node, size, alignment, commit, allow_large, req_arena_id, memid, tld); + if (p != NULL) return p; + } + } + else { + // try numa affine allocation + for (size_t i = 0; i < max_arena; i++) { + void* p = mi_arena_try_alloc_at_id(mi_arena_id_create(i), true, numa_node, size, alignment, commit, allow_large, req_arena_id, memid, tld); + if (p != NULL) return p; + } + + // try from another numa node instead.. + if (numa_node >= 0) { // if numa_node was < 0 (no specific affinity requested), all arena's have been tried already + for (size_t i = 0; i < max_arena; i++) { + void* p = mi_arena_try_alloc_at_id(mi_arena_id_create(i), false /* only proceed if not numa local */, numa_node, size, alignment, commit, allow_large, req_arena_id, memid, tld); + if (p != NULL) return p; + } + } + } + return NULL; +} + +// try to reserve a fresh arena space +static bool mi_arena_reserve(size_t req_size, bool allow_large, mi_arena_id_t req_arena_id, mi_arena_id_t *arena_id) +{ + if (_mi_preloading()) return false; // use OS only while pre loading + if (req_arena_id != _mi_arena_id_none()) return false; + + const size_t arena_count = mi_atomic_load_acquire(&mi_arena_count); + if (arena_count > (MI_MAX_ARENAS - 4)) return false; + + size_t arena_reserve = mi_option_get_size(mi_option_arena_reserve); + if (arena_reserve == 0) return false; + + if (!_mi_os_has_virtual_reserve()) { + arena_reserve = arena_reserve/4; // be conservative if virtual reserve is not supported (for some embedded systems for example) + } + arena_reserve = _mi_align_up(arena_reserve, MI_ARENA_BLOCK_SIZE); + if (arena_count >= 8 && arena_count <= 128) { + arena_reserve = ((size_t)1<<(arena_count/8)) * arena_reserve; // scale up the arena sizes exponentially + } + if (arena_reserve < req_size) return false; // should be able to at least handle the current allocation size + + // commit eagerly? + bool arena_commit = false; + if (mi_option_get(mi_option_arena_eager_commit) == 2) { arena_commit = _mi_os_has_overcommit(); } + else if (mi_option_get(mi_option_arena_eager_commit) == 1) { arena_commit = true; } + + return (mi_reserve_os_memory_ex(arena_reserve, arena_commit, allow_large, false /* exclusive */, arena_id) == 0); +} + + +void* _mi_arena_alloc_aligned(size_t size, size_t alignment, size_t align_offset, bool commit, bool allow_large, + mi_arena_id_t req_arena_id, mi_memid_t* memid, mi_os_tld_t* tld) +{ + mi_assert_internal(memid != NULL && tld != NULL); + mi_assert_internal(size > 0); + *memid = _mi_memid_none(); + + const int numa_node = _mi_os_numa_node(tld); // current numa node + + // try to allocate in an arena if the alignment is small enough and the object is not too small (as for heap meta data) + if (size >= MI_ARENA_MIN_OBJ_SIZE && alignment <= MI_SEGMENT_ALIGN && align_offset == 0) { + void* p = mi_arena_try_alloc(numa_node, size, alignment, commit, allow_large, req_arena_id, memid, tld); + if (p != NULL) return p; + + // otherwise, try to first eagerly reserve a new arena + if (req_arena_id == _mi_arena_id_none()) { + mi_arena_id_t arena_id = 0; + if (mi_arena_reserve(size, allow_large, req_arena_id, &arena_id)) { + // and try allocate in there + mi_assert_internal(req_arena_id == _mi_arena_id_none()); + p = mi_arena_try_alloc_at_id(arena_id, true, numa_node, size, alignment, commit, allow_large, req_arena_id, memid, tld); + if (p != NULL) return p; + } + } + } + + // if we cannot use OS allocation, return NULL + if (mi_option_is_enabled(mi_option_limit_os_alloc) || req_arena_id != _mi_arena_id_none()) { + errno = ENOMEM; + return NULL; + } + + // finally, fall back to the OS + if (align_offset > 0) { + return _mi_os_alloc_aligned_at_offset(size, alignment, align_offset, commit, allow_large, memid, tld->stats); + } + else { + return _mi_os_alloc_aligned(size, alignment, commit, allow_large, memid, tld->stats); + } +} + +void* _mi_arena_alloc(size_t size, bool commit, bool allow_large, mi_arena_id_t req_arena_id, mi_memid_t* memid, mi_os_tld_t* tld) +{ + return _mi_arena_alloc_aligned(size, MI_ARENA_BLOCK_SIZE, 0, commit, allow_large, req_arena_id, memid, tld); +} + + +void* mi_arena_area(mi_arena_id_t arena_id, size_t* size) { + if (size != NULL) *size = 0; + size_t arena_index = mi_arena_id_index(arena_id); + if (arena_index >= MI_MAX_ARENAS) return NULL; + mi_arena_t* arena = mi_atomic_load_ptr_acquire(mi_arena_t, &mi_arenas[arena_index]); + if (arena == NULL) return NULL; + if (size != NULL) { *size = mi_arena_block_size(arena->block_count); } + return arena->start; +} + + +/* ----------------------------------------------------------- + Arena purge +----------------------------------------------------------- */ + +static long mi_arena_purge_delay(void) { + // <0 = no purging allowed, 0=immediate purging, >0=milli-second delay + return (mi_option_get(mi_option_purge_delay) * mi_option_get(mi_option_arena_purge_mult)); +} + +// reset or decommit in an arena and update the committed/decommit bitmaps +// assumes we own the area (i.e. blocks_in_use is claimed by us) +static void mi_arena_purge(mi_arena_t* arena, size_t bitmap_idx, size_t blocks, mi_stats_t* stats) { + mi_assert_internal(arena->blocks_committed != NULL); + mi_assert_internal(arena->blocks_purge != NULL); + mi_assert_internal(!arena->memid.is_pinned); + const size_t size = mi_arena_block_size(blocks); + void* const p = mi_arena_block_start(arena, bitmap_idx); + bool needs_recommit; + if (_mi_bitmap_is_claimed_across(arena->blocks_committed, arena->field_count, blocks, bitmap_idx)) { + // all blocks are committed, we can purge freely + needs_recommit = _mi_os_purge(p, size, stats); + } + else { + // some blocks are not committed -- this can happen when a partially committed block is freed + // in `_mi_arena_free` and it is conservatively marked as uncommitted but still scheduled for a purge + // we need to ensure we do not try to reset (as that may be invalid for uncommitted memory), + // and also undo the decommit stats (as it was already adjusted) + mi_assert_internal(mi_option_is_enabled(mi_option_purge_decommits)); + needs_recommit = _mi_os_purge_ex(p, size, false /* allow reset? */, stats); + _mi_stat_increase(&stats->committed, size); + } + + // clear the purged blocks + _mi_bitmap_unclaim_across(arena->blocks_purge, arena->field_count, blocks, bitmap_idx); + // update committed bitmap + if (needs_recommit) { + _mi_bitmap_unclaim_across(arena->blocks_committed, arena->field_count, blocks, bitmap_idx); + } +} + +// Schedule a purge. This is usually delayed to avoid repeated decommit/commit calls. +// Note: assumes we (still) own the area as we may purge immediately +static void mi_arena_schedule_purge(mi_arena_t* arena, size_t bitmap_idx, size_t blocks, mi_stats_t* stats) { + mi_assert_internal(arena->blocks_purge != NULL); + const long delay = mi_arena_purge_delay(); + if (delay < 0) return; // is purging allowed at all? + + if (_mi_preloading() || delay == 0) { + // decommit directly + mi_arena_purge(arena, bitmap_idx, blocks, stats); + } + else { + // schedule decommit + mi_msecs_t expire = mi_atomic_loadi64_relaxed(&arena->purge_expire); + if (expire != 0) { + mi_atomic_addi64_acq_rel(&arena->purge_expire, delay/10); // add smallish extra delay + } + else { + mi_atomic_storei64_release(&arena->purge_expire, _mi_clock_now() + delay); + } + _mi_bitmap_claim_across(arena->blocks_purge, arena->field_count, blocks, bitmap_idx, NULL); + } +} + +// purge a range of blocks +// return true if the full range was purged. +// assumes we own the area (i.e. blocks_in_use is claimed by us) +static bool mi_arena_purge_range(mi_arena_t* arena, size_t idx, size_t startidx, size_t bitlen, size_t purge, mi_stats_t* stats) { + const size_t endidx = startidx + bitlen; + size_t bitidx = startidx; + bool all_purged = false; + while (bitidx < endidx) { + // count consequetive ones in the purge mask + size_t count = 0; + while (bitidx + count < endidx && (purge & ((size_t)1 << (bitidx + count))) != 0) { + count++; + } + if (count > 0) { + // found range to be purged + const mi_bitmap_index_t range_idx = mi_bitmap_index_create(idx, bitidx); + mi_arena_purge(arena, range_idx, count, stats); + if (count == bitlen) { + all_purged = true; + } + } + bitidx += (count+1); // +1 to skip the zero bit (or end) + } + return all_purged; +} + +// returns true if anything was purged +static bool mi_arena_try_purge(mi_arena_t* arena, mi_msecs_t now, bool force, mi_stats_t* stats) +{ + if (arena->memid.is_pinned || arena->blocks_purge == NULL) return false; + mi_msecs_t expire = mi_atomic_loadi64_relaxed(&arena->purge_expire); + if (expire == 0) return false; + if (!force && expire > now) return false; + + // reset expire (if not already set concurrently) + mi_atomic_casi64_strong_acq_rel(&arena->purge_expire, &expire, 0); + + // potential purges scheduled, walk through the bitmap + bool any_purged = false; + bool full_purge = true; + for (size_t i = 0; i < arena->field_count; i++) { + size_t purge = mi_atomic_load_relaxed(&arena->blocks_purge[i]); + if (purge != 0) { + size_t bitidx = 0; + while (bitidx < MI_BITMAP_FIELD_BITS) { + // find consequetive range of ones in the purge mask + size_t bitlen = 0; + while (bitidx + bitlen < MI_BITMAP_FIELD_BITS && (purge & ((size_t)1 << (bitidx + bitlen))) != 0) { + bitlen++; + } + // try to claim the longest range of corresponding in_use bits + const mi_bitmap_index_t bitmap_index = mi_bitmap_index_create(i, bitidx); + while( bitlen > 0 ) { + if (_mi_bitmap_try_claim(arena->blocks_inuse, arena->field_count, bitlen, bitmap_index)) { + break; + } + bitlen--; + } + // actual claimed bits at `in_use` + if (bitlen > 0) { + // read purge again now that we have the in_use bits + purge = mi_atomic_load_acquire(&arena->blocks_purge[i]); + if (!mi_arena_purge_range(arena, i, bitidx, bitlen, purge, stats)) { + full_purge = false; + } + any_purged = true; + // release the claimed `in_use` bits again + _mi_bitmap_unclaim(arena->blocks_inuse, arena->field_count, bitlen, bitmap_index); + } + bitidx += (bitlen+1); // +1 to skip the zero (or end) + } // while bitidx + } // purge != 0 + } + // if not fully purged, make sure to purge again in the future + if (!full_purge) { + const long delay = mi_arena_purge_delay(); + mi_msecs_t expected = 0; + mi_atomic_casi64_strong_acq_rel(&arena->purge_expire,&expected,_mi_clock_now() + delay); + } + return any_purged; +} + +static void mi_arenas_try_purge( bool force, bool visit_all, mi_stats_t* stats ) { + if (_mi_preloading() || mi_arena_purge_delay() <= 0) return; // nothing will be scheduled + + const size_t max_arena = mi_atomic_load_acquire(&mi_arena_count); + if (max_arena == 0) return; + + // allow only one thread to purge at a time + static mi_atomic_guard_t purge_guard; + mi_atomic_guard(&purge_guard) + { + mi_msecs_t now = _mi_clock_now(); + size_t max_purge_count = (visit_all ? max_arena : 1); + for (size_t i = 0; i < max_arena; i++) { + mi_arena_t* arena = mi_atomic_load_ptr_acquire(mi_arena_t, &mi_arenas[i]); + if (arena != NULL) { + if (mi_arena_try_purge(arena, now, force, stats)) { + if (max_purge_count <= 1) break; + max_purge_count--; + } + } + } + } +} + + +/* ----------------------------------------------------------- + Arena free +----------------------------------------------------------- */ + +void _mi_arena_free(void* p, size_t size, size_t committed_size, mi_memid_t memid, mi_stats_t* stats) { + mi_assert_internal(size > 0 && stats != NULL); + mi_assert_internal(committed_size <= size); + if (p==NULL) return; + if (size==0) return; + const bool all_committed = (committed_size == size); + + if (mi_memkind_is_os(memid.memkind)) { + // was a direct OS allocation, pass through + if (!all_committed && committed_size > 0) { + // if partially committed, adjust the committed stats (as `_mi_os_free` will increase decommit by the full size) + _mi_stat_decrease(&stats->committed, committed_size); + } + _mi_os_free(p, size, memid, stats); + } + else if (memid.memkind == MI_MEM_ARENA) { + // allocated in an arena + size_t arena_idx; + size_t bitmap_idx; + mi_arena_memid_indices(memid, &arena_idx, &bitmap_idx); + mi_assert_internal(arena_idx < MI_MAX_ARENAS); + mi_arena_t* arena = mi_atomic_load_ptr_acquire(mi_arena_t,&mi_arenas[arena_idx]); + mi_assert_internal(arena != NULL); + const size_t blocks = mi_block_count_of_size(size); + + // checks + if (arena == NULL) { + _mi_error_message(EINVAL, "trying to free from non-existent arena: %p, size %zu, memid: 0x%zx\n", p, size, memid); + return; + } + mi_assert_internal(arena->field_count > mi_bitmap_index_field(bitmap_idx)); + if (arena->field_count <= mi_bitmap_index_field(bitmap_idx)) { + _mi_error_message(EINVAL, "trying to free from non-existent arena block: %p, size %zu, memid: 0x%zx\n", p, size, memid); + return; + } + + // need to set all memory to undefined as some parts may still be marked as no_access (like padding etc.) + mi_track_mem_undefined(p,size); + + // potentially decommit + if (arena->memid.is_pinned || arena->blocks_committed == NULL) { + mi_assert_internal(all_committed); + } + else { + mi_assert_internal(arena->blocks_committed != NULL); + mi_assert_internal(arena->blocks_purge != NULL); + + if (!all_committed) { + // mark the entire range as no longer committed (so we recommit the full range when re-using) + _mi_bitmap_unclaim_across(arena->blocks_committed, arena->field_count, blocks, bitmap_idx); + mi_track_mem_noaccess(p,size); + if (committed_size > 0) { + // if partially committed, adjust the committed stats (is it will be recommitted when re-using) + // in the delayed purge, we now need to not count a decommit if the range is not marked as committed. + _mi_stat_decrease(&stats->committed, committed_size); + } + // note: if not all committed, it may be that the purge will reset/decommit the entire range + // that contains already decommitted parts. Since purge consistently uses reset or decommit that + // works (as we should never reset decommitted parts). + } + // (delay) purge the entire range + mi_arena_schedule_purge(arena, bitmap_idx, blocks, stats); + } + + // and make it available to others again + bool all_inuse = _mi_bitmap_unclaim_across(arena->blocks_inuse, arena->field_count, blocks, bitmap_idx); + if (!all_inuse) { + _mi_error_message(EAGAIN, "trying to free an already freed arena block: %p, size %zu\n", p, size); + return; + }; + } + else { + // arena was none, external, or static; nothing to do + mi_assert_internal(memid.memkind < MI_MEM_OS); + } + + // purge expired decommits + mi_arenas_try_purge(false, false, stats); +} + +// destroy owned arenas; this is unsafe and should only be done using `mi_option_destroy_on_exit` +// for dynamic libraries that are unloaded and need to release all their allocated memory. +static void mi_arenas_unsafe_destroy(void) { + const size_t max_arena = mi_atomic_load_relaxed(&mi_arena_count); + size_t new_max_arena = 0; + for (size_t i = 0; i < max_arena; i++) { + mi_arena_t* arena = mi_atomic_load_ptr_acquire(mi_arena_t, &mi_arenas[i]); + if (arena != NULL) { + if (arena->start != NULL && mi_memkind_is_os(arena->memid.memkind)) { + mi_atomic_store_ptr_release(mi_arena_t, &mi_arenas[i], NULL); + _mi_os_free(arena->start, mi_arena_size(arena), arena->memid, &_mi_stats_main); + } + else { + new_max_arena = i; + } + mi_arena_meta_free(arena, arena->meta_memid, arena->meta_size, &_mi_stats_main); + } + } + + // try to lower the max arena. + size_t expected = max_arena; + mi_atomic_cas_strong_acq_rel(&mi_arena_count, &expected, new_max_arena); +} + +// Purge the arenas; if `force_purge` is true, amenable parts are purged even if not yet expired +void _mi_arena_collect(bool force_purge, mi_stats_t* stats) { + mi_arenas_try_purge(force_purge, true /* visit all */, stats); +} + +// destroy owned arenas; this is unsafe and should only be done using `mi_option_destroy_on_exit` +// for dynamic libraries that are unloaded and need to release all their allocated memory. +void _mi_arena_unsafe_destroy_all(mi_stats_t* stats) { + mi_arenas_unsafe_destroy(); + _mi_arena_collect(true /* force purge */, stats); // purge non-owned arenas +} + +// Is a pointer inside any of our arenas? +bool _mi_arena_contains(const void* p) { + const size_t max_arena = mi_atomic_load_relaxed(&mi_arena_count); + for (size_t i = 0; i < max_arena; i++) { + mi_arena_t* arena = mi_atomic_load_ptr_acquire(mi_arena_t, &mi_arenas[i]); + if (arena != NULL && arena->start <= (const uint8_t*)p && arena->start + mi_arena_block_size(arena->block_count) > (const uint8_t*)p) { + return true; + } + } + return false; +} + + +/* ----------------------------------------------------------- + Add an arena. +----------------------------------------------------------- */ + +static bool mi_arena_add(mi_arena_t* arena, mi_arena_id_t* arena_id) { + mi_assert_internal(arena != NULL); + mi_assert_internal((uintptr_t)mi_atomic_load_ptr_relaxed(uint8_t,&arena->start) % MI_SEGMENT_ALIGN == 0); + mi_assert_internal(arena->block_count > 0); + if (arena_id != NULL) { *arena_id = -1; } + + size_t i = mi_atomic_increment_acq_rel(&mi_arena_count); + if (i >= MI_MAX_ARENAS) { + mi_atomic_decrement_acq_rel(&mi_arena_count); + return false; + } + arena->id = mi_arena_id_create(i); + mi_atomic_store_ptr_release(mi_arena_t,&mi_arenas[i], arena); + if (arena_id != NULL) { *arena_id = arena->id; } + return true; +} + +static bool mi_manage_os_memory_ex2(void* start, size_t size, bool is_large, int numa_node, bool exclusive, mi_memid_t memid, mi_arena_id_t* arena_id) mi_attr_noexcept +{ + if (arena_id != NULL) *arena_id = _mi_arena_id_none(); + if (size < MI_ARENA_BLOCK_SIZE) return false; + + if (is_large) { + mi_assert_internal(memid.initially_committed && memid.is_pinned); + } + + const size_t bcount = size / MI_ARENA_BLOCK_SIZE; + const size_t fields = _mi_divide_up(bcount, MI_BITMAP_FIELD_BITS); + const size_t bitmaps = (memid.is_pinned ? 2 : 4); + const size_t asize = sizeof(mi_arena_t) + (bitmaps*fields*sizeof(mi_bitmap_field_t)); + mi_memid_t meta_memid; + mi_arena_t* arena = (mi_arena_t*)mi_arena_meta_zalloc(asize, &meta_memid, &_mi_stats_main); // TODO: can we avoid allocating from the OS? + if (arena == NULL) return false; + + // already zero'd due to os_alloc + // _mi_memzero(arena, asize); + arena->id = _mi_arena_id_none(); + arena->memid = memid; + arena->exclusive = exclusive; + arena->meta_size = asize; + arena->meta_memid = meta_memid; + arena->block_count = bcount; + arena->field_count = fields; + arena->start = (uint8_t*)start; + arena->numa_node = numa_node; // TODO: or get the current numa node if -1? (now it allows anyone to allocate on -1) + arena->is_large = is_large; + arena->purge_expire = 0; + arena->search_idx = 0; + arena->blocks_dirty = &arena->blocks_inuse[fields]; // just after inuse bitmap + arena->blocks_committed = (arena->memid.is_pinned ? NULL : &arena->blocks_inuse[2*fields]); // just after dirty bitmap + arena->blocks_purge = (arena->memid.is_pinned ? NULL : &arena->blocks_inuse[3*fields]); // just after committed bitmap + // initialize committed bitmap? + if (arena->blocks_committed != NULL && arena->memid.initially_committed) { + memset((void*)arena->blocks_committed, 0xFF, fields*sizeof(mi_bitmap_field_t)); // cast to void* to avoid atomic warning + } + + // and claim leftover blocks if needed (so we never allocate there) + ptrdiff_t post = (fields * MI_BITMAP_FIELD_BITS) - bcount; + mi_assert_internal(post >= 0); + if (post > 0) { + // don't use leftover bits at the end + mi_bitmap_index_t postidx = mi_bitmap_index_create(fields - 1, MI_BITMAP_FIELD_BITS - post); + _mi_bitmap_claim(arena->blocks_inuse, fields, post, postidx, NULL); + } + return mi_arena_add(arena, arena_id); + +} + +bool mi_manage_os_memory_ex(void* start, size_t size, bool is_committed, bool is_large, bool is_zero, int numa_node, bool exclusive, mi_arena_id_t* arena_id) mi_attr_noexcept { + mi_memid_t memid = _mi_memid_create(MI_MEM_EXTERNAL); + memid.initially_committed = is_committed; + memid.initially_zero = is_zero; + memid.is_pinned = is_large; + return mi_manage_os_memory_ex2(start,size,is_large,numa_node,exclusive,memid, arena_id); +} + +// Reserve a range of regular OS memory +int mi_reserve_os_memory_ex(size_t size, bool commit, bool allow_large, bool exclusive, mi_arena_id_t* arena_id) mi_attr_noexcept { + if (arena_id != NULL) *arena_id = _mi_arena_id_none(); + size = _mi_align_up(size, MI_ARENA_BLOCK_SIZE); // at least one block + mi_memid_t memid; + void* start = _mi_os_alloc_aligned(size, MI_SEGMENT_ALIGN, commit, allow_large, &memid, &_mi_stats_main); + if (start == NULL) return ENOMEM; + const bool is_large = memid.is_pinned; // todo: use separate is_large field? + if (!mi_manage_os_memory_ex2(start, size, is_large, -1 /* numa node */, exclusive, memid, arena_id)) { + _mi_os_free_ex(start, size, commit, memid, &_mi_stats_main); + _mi_verbose_message("failed to reserve %zu k memory\n", _mi_divide_up(size, 1024)); + return ENOMEM; + } + _mi_verbose_message("reserved %zu KiB memory%s\n", _mi_divide_up(size, 1024), is_large ? " (in large os pages)" : ""); + return 0; +} + + +// Manage a range of regular OS memory +bool mi_manage_os_memory(void* start, size_t size, bool is_committed, bool is_large, bool is_zero, int numa_node) mi_attr_noexcept { + return mi_manage_os_memory_ex(start, size, is_committed, is_large, is_zero, numa_node, false /* exclusive? */, NULL); +} + +// Reserve a range of regular OS memory +int mi_reserve_os_memory(size_t size, bool commit, bool allow_large) mi_attr_noexcept { + return mi_reserve_os_memory_ex(size, commit, allow_large, false, NULL); +} + + +/* ----------------------------------------------------------- + Debugging +----------------------------------------------------------- */ + +static size_t mi_debug_show_bitmap(const char* prefix, mi_bitmap_field_t* fields, size_t field_count ) { + size_t inuse_count = 0; + for (size_t i = 0; i < field_count; i++) { + char buf[MI_BITMAP_FIELD_BITS + 1]; + uintptr_t field = mi_atomic_load_relaxed(&fields[i]); + for (size_t bit = 0; bit < MI_BITMAP_FIELD_BITS; bit++) { + bool inuse = ((((uintptr_t)1 << bit) & field) != 0); + if (inuse) inuse_count++; + buf[MI_BITMAP_FIELD_BITS - 1 - bit] = (inuse ? 'x' : '.'); + } + buf[MI_BITMAP_FIELD_BITS] = 0; + _mi_verbose_message("%s%s\n", prefix, buf); + } + return inuse_count; +} + +void mi_debug_show_arenas(void) mi_attr_noexcept { + size_t max_arenas = mi_atomic_load_relaxed(&mi_arena_count); + for (size_t i = 0; i < max_arenas; i++) { + mi_arena_t* arena = mi_atomic_load_ptr_relaxed(mi_arena_t, &mi_arenas[i]); + if (arena == NULL) break; + size_t inuse_count = 0; + _mi_verbose_message("arena %zu: %zu blocks with %zu fields\n", i, arena->block_count, arena->field_count); + inuse_count += mi_debug_show_bitmap(" ", arena->blocks_inuse, arena->field_count); + _mi_verbose_message(" blocks in use ('x'): %zu\n", inuse_count); + } +} + + +/* ----------------------------------------------------------- + Reserve a huge page arena. +----------------------------------------------------------- */ +// reserve at a specific numa node +int mi_reserve_huge_os_pages_at_ex(size_t pages, int numa_node, size_t timeout_msecs, bool exclusive, mi_arena_id_t* arena_id) mi_attr_noexcept { + if (arena_id != NULL) *arena_id = -1; + if (pages==0) return 0; + if (numa_node < -1) numa_node = -1; + if (numa_node >= 0) numa_node = numa_node % _mi_os_numa_node_count(); + size_t hsize = 0; + size_t pages_reserved = 0; + mi_memid_t memid; + void* p = _mi_os_alloc_huge_os_pages(pages, numa_node, timeout_msecs, &pages_reserved, &hsize, &memid); + if (p==NULL || pages_reserved==0) { + _mi_warning_message("failed to reserve %zu GiB huge pages\n", pages); + return ENOMEM; + } + _mi_verbose_message("numa node %i: reserved %zu GiB huge pages (of the %zu GiB requested)\n", numa_node, pages_reserved, pages); + + if (!mi_manage_os_memory_ex2(p, hsize, true, numa_node, exclusive, memid, arena_id)) { + _mi_os_free(p, hsize, memid, &_mi_stats_main); + return ENOMEM; + } + return 0; +} + +int mi_reserve_huge_os_pages_at(size_t pages, int numa_node, size_t timeout_msecs) mi_attr_noexcept { + return mi_reserve_huge_os_pages_at_ex(pages, numa_node, timeout_msecs, false, NULL); +} + +// reserve huge pages evenly among the given number of numa nodes (or use the available ones as detected) +int mi_reserve_huge_os_pages_interleave(size_t pages, size_t numa_nodes, size_t timeout_msecs) mi_attr_noexcept { + if (pages == 0) return 0; + + // pages per numa node + size_t numa_count = (numa_nodes > 0 ? numa_nodes : _mi_os_numa_node_count()); + if (numa_count <= 0) numa_count = 1; + const size_t pages_per = pages / numa_count; + const size_t pages_mod = pages % numa_count; + const size_t timeout_per = (timeout_msecs==0 ? 0 : (timeout_msecs / numa_count) + 50); + + // reserve evenly among numa nodes + for (size_t numa_node = 0; numa_node < numa_count && pages > 0; numa_node++) { + size_t node_pages = pages_per; // can be 0 + if (numa_node < pages_mod) node_pages++; + int err = mi_reserve_huge_os_pages_at(node_pages, (int)numa_node, timeout_per); + if (err) return err; + if (pages < node_pages) { + pages = 0; + } + else { + pages -= node_pages; + } + } + + return 0; +} + +int mi_reserve_huge_os_pages(size_t pages, double max_secs, size_t* pages_reserved) mi_attr_noexcept { + MI_UNUSED(max_secs); + _mi_warning_message("mi_reserve_huge_os_pages is deprecated: use mi_reserve_huge_os_pages_interleave/at instead\n"); + if (pages_reserved != NULL) *pages_reserved = 0; + int err = mi_reserve_huge_os_pages_interleave(pages, 0, (size_t)(max_secs * 1000.0)); + if (err==0 && pages_reserved!=NULL) *pages_reserved = pages; + return err; +} diff --git a/Objects/mimalloc/bitmap.c b/Objects/mimalloc/bitmap.c new file mode 100644 index 00000000000000..ec3c755822dac1 --- /dev/null +++ b/Objects/mimalloc/bitmap.c @@ -0,0 +1,432 @@ +/* ---------------------------------------------------------------------------- +Copyright (c) 2019-2023 Microsoft Research, Daan Leijen +This is free software; you can redistribute it and/or modify it under the +terms of the MIT license. A copy of the license can be found in the file +"LICENSE" at the root of this distribution. +-----------------------------------------------------------------------------*/ + +/* ---------------------------------------------------------------------------- +Concurrent bitmap that can set/reset sequences of bits atomically, +represeted as an array of fields where each field is a machine word (`size_t`) + +There are two api's; the standard one cannot have sequences that cross +between the bitmap fields (and a sequence must be <= MI_BITMAP_FIELD_BITS). + +The `_across` postfixed functions do allow sequences that can cross over +between the fields. (This is used in arena allocation) +---------------------------------------------------------------------------- */ + +#include "mimalloc.h" +#include "mimalloc/internal.h" +#include "bitmap.h" + +/* ----------------------------------------------------------- + Bitmap definition +----------------------------------------------------------- */ + +// The bit mask for a given number of blocks at a specified bit index. +static inline size_t mi_bitmap_mask_(size_t count, size_t bitidx) { + mi_assert_internal(count + bitidx <= MI_BITMAP_FIELD_BITS); + mi_assert_internal(count > 0); + if (count >= MI_BITMAP_FIELD_BITS) return MI_BITMAP_FIELD_FULL; + if (count == 0) return 0; + return ((((size_t)1 << count) - 1) << bitidx); +} + + +/* ----------------------------------------------------------- + Claim a bit sequence atomically +----------------------------------------------------------- */ + +// Try to atomically claim a sequence of `count` bits in a single +// field at `idx` in `bitmap`. Returns `true` on success. +inline bool _mi_bitmap_try_find_claim_field(mi_bitmap_t bitmap, size_t idx, const size_t count, mi_bitmap_index_t* bitmap_idx) +{ + mi_assert_internal(bitmap_idx != NULL); + mi_assert_internal(count <= MI_BITMAP_FIELD_BITS); + mi_assert_internal(count > 0); + mi_bitmap_field_t* field = &bitmap[idx]; + size_t map = mi_atomic_load_relaxed(field); + if (map==MI_BITMAP_FIELD_FULL) return false; // short cut + + // search for 0-bit sequence of length count + const size_t mask = mi_bitmap_mask_(count, 0); + const size_t bitidx_max = MI_BITMAP_FIELD_BITS - count; + +#ifdef MI_HAVE_FAST_BITSCAN + size_t bitidx = mi_ctz(~map); // quickly find the first zero bit if possible +#else + size_t bitidx = 0; // otherwise start at 0 +#endif + size_t m = (mask << bitidx); // invariant: m == mask shifted by bitidx + + // scan linearly for a free range of zero bits + while (bitidx <= bitidx_max) { + const size_t mapm = (map & m); + if (mapm == 0) { // are the mask bits free at bitidx? + mi_assert_internal((m >> bitidx) == mask); // no overflow? + const size_t newmap = (map | m); + mi_assert_internal((newmap^map) >> bitidx == mask); + if (!mi_atomic_cas_strong_acq_rel(field, &map, newmap)) { // TODO: use weak cas here? + // no success, another thread claimed concurrently.. keep going (with updated `map`) + continue; + } + else { + // success, we claimed the bits! + *bitmap_idx = mi_bitmap_index_create(idx, bitidx); + return true; + } + } + else { + // on to the next bit range +#ifdef MI_HAVE_FAST_BITSCAN + mi_assert_internal(mapm != 0); + const size_t shift = (count == 1 ? 1 : (MI_INTPTR_BITS - mi_clz(mapm) - bitidx)); + mi_assert_internal(shift > 0 && shift <= count); +#else + const size_t shift = 1; +#endif + bitidx += shift; + m <<= shift; + } + } + // no bits found + return false; +} + +// Find `count` bits of 0 and set them to 1 atomically; returns `true` on success. +// Starts at idx, and wraps around to search in all `bitmap_fields` fields. +// `count` can be at most MI_BITMAP_FIELD_BITS and will never cross fields. +bool _mi_bitmap_try_find_from_claim(mi_bitmap_t bitmap, const size_t bitmap_fields, const size_t start_field_idx, const size_t count, mi_bitmap_index_t* bitmap_idx) { + size_t idx = start_field_idx; + for (size_t visited = 0; visited < bitmap_fields; visited++, idx++) { + if (idx >= bitmap_fields) { idx = 0; } // wrap + if (_mi_bitmap_try_find_claim_field(bitmap, idx, count, bitmap_idx)) { + return true; + } + } + return false; +} + +// Like _mi_bitmap_try_find_from_claim but with an extra predicate that must be fullfilled +bool _mi_bitmap_try_find_from_claim_pred(mi_bitmap_t bitmap, const size_t bitmap_fields, + const size_t start_field_idx, const size_t count, + mi_bitmap_pred_fun_t pred_fun, void* pred_arg, + mi_bitmap_index_t* bitmap_idx) { + size_t idx = start_field_idx; + for (size_t visited = 0; visited < bitmap_fields; visited++, idx++) { + if (idx >= bitmap_fields) idx = 0; // wrap + if (_mi_bitmap_try_find_claim_field(bitmap, idx, count, bitmap_idx)) { + if (pred_fun == NULL || pred_fun(*bitmap_idx, pred_arg)) { + return true; + } + // predicate returned false, unclaim and look further + _mi_bitmap_unclaim(bitmap, bitmap_fields, count, *bitmap_idx); + } + } + return false; +} + +// Set `count` bits at `bitmap_idx` to 0 atomically +// Returns `true` if all `count` bits were 1 previously. +bool _mi_bitmap_unclaim(mi_bitmap_t bitmap, size_t bitmap_fields, size_t count, mi_bitmap_index_t bitmap_idx) { + const size_t idx = mi_bitmap_index_field(bitmap_idx); + const size_t bitidx = mi_bitmap_index_bit_in_field(bitmap_idx); + const size_t mask = mi_bitmap_mask_(count, bitidx); + mi_assert_internal(bitmap_fields > idx); MI_UNUSED(bitmap_fields); + // mi_assert_internal((bitmap[idx] & mask) == mask); + const size_t prev = mi_atomic_and_acq_rel(&bitmap[idx], ~mask); + return ((prev & mask) == mask); +} + + +// Set `count` bits at `bitmap_idx` to 1 atomically +// Returns `true` if all `count` bits were 0 previously. `any_zero` is `true` if there was at least one zero bit. +bool _mi_bitmap_claim(mi_bitmap_t bitmap, size_t bitmap_fields, size_t count, mi_bitmap_index_t bitmap_idx, bool* any_zero) { + const size_t idx = mi_bitmap_index_field(bitmap_idx); + const size_t bitidx = mi_bitmap_index_bit_in_field(bitmap_idx); + const size_t mask = mi_bitmap_mask_(count, bitidx); + mi_assert_internal(bitmap_fields > idx); MI_UNUSED(bitmap_fields); + //mi_assert_internal(any_zero != NULL || (bitmap[idx] & mask) == 0); + size_t prev = mi_atomic_or_acq_rel(&bitmap[idx], mask); + if (any_zero != NULL) { *any_zero = ((prev & mask) != mask); } + return ((prev & mask) == 0); +} + +// Returns `true` if all `count` bits were 1. `any_ones` is `true` if there was at least one bit set to one. +static bool mi_bitmap_is_claimedx(mi_bitmap_t bitmap, size_t bitmap_fields, size_t count, mi_bitmap_index_t bitmap_idx, bool* any_ones) { + const size_t idx = mi_bitmap_index_field(bitmap_idx); + const size_t bitidx = mi_bitmap_index_bit_in_field(bitmap_idx); + const size_t mask = mi_bitmap_mask_(count, bitidx); + mi_assert_internal(bitmap_fields > idx); MI_UNUSED(bitmap_fields); + const size_t field = mi_atomic_load_relaxed(&bitmap[idx]); + if (any_ones != NULL) { *any_ones = ((field & mask) != 0); } + return ((field & mask) == mask); +} + +// Try to set `count` bits at `bitmap_idx` from 0 to 1 atomically. +// Returns `true` if successful when all previous `count` bits were 0. +bool _mi_bitmap_try_claim(mi_bitmap_t bitmap, size_t bitmap_fields, size_t count, mi_bitmap_index_t bitmap_idx) { + const size_t idx = mi_bitmap_index_field(bitmap_idx); + const size_t bitidx = mi_bitmap_index_bit_in_field(bitmap_idx); + const size_t mask = mi_bitmap_mask_(count, bitidx); + mi_assert_internal(bitmap_fields > idx); MI_UNUSED(bitmap_fields); + size_t expected = mi_atomic_load_relaxed(&bitmap[idx]); + do { + if ((expected & mask) != 0) return false; + } + while (!mi_atomic_cas_strong_acq_rel(&bitmap[idx], &expected, expected | mask)); + mi_assert_internal((expected & mask) == 0); + return true; +} + + +bool _mi_bitmap_is_claimed(mi_bitmap_t bitmap, size_t bitmap_fields, size_t count, mi_bitmap_index_t bitmap_idx) { + return mi_bitmap_is_claimedx(bitmap, bitmap_fields, count, bitmap_idx, NULL); +} + +bool _mi_bitmap_is_any_claimed(mi_bitmap_t bitmap, size_t bitmap_fields, size_t count, mi_bitmap_index_t bitmap_idx) { + bool any_ones; + mi_bitmap_is_claimedx(bitmap, bitmap_fields, count, bitmap_idx, &any_ones); + return any_ones; +} + + +//-------------------------------------------------------------------------- +// the `_across` functions work on bitmaps where sequences can cross over +// between the fields. This is used in arena allocation +//-------------------------------------------------------------------------- + +// Try to atomically claim a sequence of `count` bits starting from the field +// at `idx` in `bitmap` and crossing into subsequent fields. Returns `true` on success. +// Only needs to consider crossing into the next fields (see `mi_bitmap_try_find_from_claim_across`) +static bool mi_bitmap_try_find_claim_field_across(mi_bitmap_t bitmap, size_t bitmap_fields, size_t idx, const size_t count, const size_t retries, mi_bitmap_index_t* bitmap_idx) +{ + mi_assert_internal(bitmap_idx != NULL); + + // check initial trailing zeros + mi_bitmap_field_t* field = &bitmap[idx]; + size_t map = mi_atomic_load_relaxed(field); + const size_t initial = mi_clz(map); // count of initial zeros starting at idx + mi_assert_internal(initial <= MI_BITMAP_FIELD_BITS); + if (initial == 0) return false; + if (initial >= count) return _mi_bitmap_try_find_claim_field(bitmap, idx, count, bitmap_idx); // no need to cross fields (this case won't happen for us) + if (_mi_divide_up(count - initial, MI_BITMAP_FIELD_BITS) >= (bitmap_fields - idx)) return false; // not enough entries + + // scan ahead + size_t found = initial; + size_t mask = 0; // mask bits for the final field + while(found < count) { + field++; + map = mi_atomic_load_relaxed(field); + const size_t mask_bits = (found + MI_BITMAP_FIELD_BITS <= count ? MI_BITMAP_FIELD_BITS : (count - found)); + mi_assert_internal(mask_bits > 0 && mask_bits <= MI_BITMAP_FIELD_BITS); + mask = mi_bitmap_mask_(mask_bits, 0); + if ((map & mask) != 0) return false; // some part is already claimed + found += mask_bits; + } + mi_assert_internal(field < &bitmap[bitmap_fields]); + + // we found a range of contiguous zeros up to the final field; mask contains mask in the final field + // now try to claim the range atomically + mi_bitmap_field_t* const final_field = field; + const size_t final_mask = mask; + mi_bitmap_field_t* const initial_field = &bitmap[idx]; + const size_t initial_idx = MI_BITMAP_FIELD_BITS - initial; + const size_t initial_mask = mi_bitmap_mask_(initial, initial_idx); + + // initial field + size_t newmap; + field = initial_field; + map = mi_atomic_load_relaxed(field); + do { + newmap = (map | initial_mask); + if ((map & initial_mask) != 0) { goto rollback; }; + } while (!mi_atomic_cas_strong_acq_rel(field, &map, newmap)); + + // intermediate fields + while (++field < final_field) { + newmap = MI_BITMAP_FIELD_FULL; + map = 0; + if (!mi_atomic_cas_strong_acq_rel(field, &map, newmap)) { goto rollback; } + } + + // final field + mi_assert_internal(field == final_field); + map = mi_atomic_load_relaxed(field); + do { + newmap = (map | final_mask); + if ((map & final_mask) != 0) { goto rollback; } + } while (!mi_atomic_cas_strong_acq_rel(field, &map, newmap)); + + // claimed! + *bitmap_idx = mi_bitmap_index_create(idx, initial_idx); + return true; + +rollback: + // roll back intermediate fields + // (we just failed to claim `field` so decrement first) + while (--field > initial_field) { + newmap = 0; + map = MI_BITMAP_FIELD_FULL; + mi_assert_internal(mi_atomic_load_relaxed(field) == map); + mi_atomic_store_release(field, newmap); + } + if (field == initial_field) { // (if we failed on the initial field, `field + 1 == initial_field`) + map = mi_atomic_load_relaxed(field); + do { + mi_assert_internal((map & initial_mask) == initial_mask); + newmap = (map & ~initial_mask); + } while (!mi_atomic_cas_strong_acq_rel(field, &map, newmap)); + } + // retry? (we make a recursive call instead of goto to be able to use const declarations) + if (retries <= 2) { + return mi_bitmap_try_find_claim_field_across(bitmap, bitmap_fields, idx, count, retries+1, bitmap_idx); + } + else { + return false; + } +} + + +// Find `count` bits of zeros and set them to 1 atomically; returns `true` on success. +// Starts at idx, and wraps around to search in all `bitmap_fields` fields. +bool _mi_bitmap_try_find_from_claim_across(mi_bitmap_t bitmap, const size_t bitmap_fields, const size_t start_field_idx, const size_t count, mi_bitmap_index_t* bitmap_idx) { + mi_assert_internal(count > 0); + if (count <= 2) { + // we don't bother with crossover fields for small counts + return _mi_bitmap_try_find_from_claim(bitmap, bitmap_fields, start_field_idx, count, bitmap_idx); + } + + // visit the fields + size_t idx = start_field_idx; + for (size_t visited = 0; visited < bitmap_fields; visited++, idx++) { + if (idx >= bitmap_fields) { idx = 0; } // wrap + // first try to claim inside a field + if (count <= MI_BITMAP_FIELD_BITS) { + if (_mi_bitmap_try_find_claim_field(bitmap, idx, count, bitmap_idx)) { + return true; + } + } + // if that fails, then try to claim across fields + if (mi_bitmap_try_find_claim_field_across(bitmap, bitmap_fields, idx, count, 0, bitmap_idx)) { + return true; + } + } + return false; +} + +// Helper for masks across fields; returns the mid count, post_mask may be 0 +static size_t mi_bitmap_mask_across(mi_bitmap_index_t bitmap_idx, size_t bitmap_fields, size_t count, size_t* pre_mask, size_t* mid_mask, size_t* post_mask) { + MI_UNUSED(bitmap_fields); + const size_t bitidx = mi_bitmap_index_bit_in_field(bitmap_idx); + if mi_likely(bitidx + count <= MI_BITMAP_FIELD_BITS) { + *pre_mask = mi_bitmap_mask_(count, bitidx); + *mid_mask = 0; + *post_mask = 0; + mi_assert_internal(mi_bitmap_index_field(bitmap_idx) < bitmap_fields); + return 0; + } + else { + const size_t pre_bits = MI_BITMAP_FIELD_BITS - bitidx; + mi_assert_internal(pre_bits < count); + *pre_mask = mi_bitmap_mask_(pre_bits, bitidx); + count -= pre_bits; + const size_t mid_count = (count / MI_BITMAP_FIELD_BITS); + *mid_mask = MI_BITMAP_FIELD_FULL; + count %= MI_BITMAP_FIELD_BITS; + *post_mask = (count==0 ? 0 : mi_bitmap_mask_(count, 0)); + mi_assert_internal(mi_bitmap_index_field(bitmap_idx) + mid_count + (count==0 ? 0 : 1) < bitmap_fields); + return mid_count; + } +} + +// Set `count` bits at `bitmap_idx` to 0 atomically +// Returns `true` if all `count` bits were 1 previously. +bool _mi_bitmap_unclaim_across(mi_bitmap_t bitmap, size_t bitmap_fields, size_t count, mi_bitmap_index_t bitmap_idx) { + size_t idx = mi_bitmap_index_field(bitmap_idx); + size_t pre_mask; + size_t mid_mask; + size_t post_mask; + size_t mid_count = mi_bitmap_mask_across(bitmap_idx, bitmap_fields, count, &pre_mask, &mid_mask, &post_mask); + bool all_one = true; + mi_bitmap_field_t* field = &bitmap[idx]; + size_t prev = mi_atomic_and_acq_rel(field++, ~pre_mask); // clear first part + if ((prev & pre_mask) != pre_mask) all_one = false; + while(mid_count-- > 0) { + prev = mi_atomic_and_acq_rel(field++, ~mid_mask); // clear mid part + if ((prev & mid_mask) != mid_mask) all_one = false; + } + if (post_mask!=0) { + prev = mi_atomic_and_acq_rel(field, ~post_mask); // clear end part + if ((prev & post_mask) != post_mask) all_one = false; + } + return all_one; +} + +// Set `count` bits at `bitmap_idx` to 1 atomically +// Returns `true` if all `count` bits were 0 previously. `any_zero` is `true` if there was at least one zero bit. +bool _mi_bitmap_claim_across(mi_bitmap_t bitmap, size_t bitmap_fields, size_t count, mi_bitmap_index_t bitmap_idx, bool* pany_zero) { + size_t idx = mi_bitmap_index_field(bitmap_idx); + size_t pre_mask; + size_t mid_mask; + size_t post_mask; + size_t mid_count = mi_bitmap_mask_across(bitmap_idx, bitmap_fields, count, &pre_mask, &mid_mask, &post_mask); + bool all_zero = true; + bool any_zero = false; + _Atomic(size_t)*field = &bitmap[idx]; + size_t prev = mi_atomic_or_acq_rel(field++, pre_mask); + if ((prev & pre_mask) != 0) all_zero = false; + if ((prev & pre_mask) != pre_mask) any_zero = true; + while (mid_count-- > 0) { + prev = mi_atomic_or_acq_rel(field++, mid_mask); + if ((prev & mid_mask) != 0) all_zero = false; + if ((prev & mid_mask) != mid_mask) any_zero = true; + } + if (post_mask!=0) { + prev = mi_atomic_or_acq_rel(field, post_mask); + if ((prev & post_mask) != 0) all_zero = false; + if ((prev & post_mask) != post_mask) any_zero = true; + } + if (pany_zero != NULL) { *pany_zero = any_zero; } + return all_zero; +} + + +// Returns `true` if all `count` bits were 1. +// `any_ones` is `true` if there was at least one bit set to one. +static bool mi_bitmap_is_claimedx_across(mi_bitmap_t bitmap, size_t bitmap_fields, size_t count, mi_bitmap_index_t bitmap_idx, bool* pany_ones) { + size_t idx = mi_bitmap_index_field(bitmap_idx); + size_t pre_mask; + size_t mid_mask; + size_t post_mask; + size_t mid_count = mi_bitmap_mask_across(bitmap_idx, bitmap_fields, count, &pre_mask, &mid_mask, &post_mask); + bool all_ones = true; + bool any_ones = false; + mi_bitmap_field_t* field = &bitmap[idx]; + size_t prev = mi_atomic_load_relaxed(field++); + if ((prev & pre_mask) != pre_mask) all_ones = false; + if ((prev & pre_mask) != 0) any_ones = true; + while (mid_count-- > 0) { + prev = mi_atomic_load_relaxed(field++); + if ((prev & mid_mask) != mid_mask) all_ones = false; + if ((prev & mid_mask) != 0) any_ones = true; + } + if (post_mask!=0) { + prev = mi_atomic_load_relaxed(field); + if ((prev & post_mask) != post_mask) all_ones = false; + if ((prev & post_mask) != 0) any_ones = true; + } + if (pany_ones != NULL) { *pany_ones = any_ones; } + return all_ones; +} + +bool _mi_bitmap_is_claimed_across(mi_bitmap_t bitmap, size_t bitmap_fields, size_t count, mi_bitmap_index_t bitmap_idx) { + return mi_bitmap_is_claimedx_across(bitmap, bitmap_fields, count, bitmap_idx, NULL); +} + +bool _mi_bitmap_is_any_claimed_across(mi_bitmap_t bitmap, size_t bitmap_fields, size_t count, mi_bitmap_index_t bitmap_idx) { + bool any_ones; + mi_bitmap_is_claimedx_across(bitmap, bitmap_fields, count, bitmap_idx, &any_ones); + return any_ones; +} diff --git a/Objects/mimalloc/bitmap.h b/Objects/mimalloc/bitmap.h new file mode 100644 index 00000000000000..9ba15d5d6f09ea --- /dev/null +++ b/Objects/mimalloc/bitmap.h @@ -0,0 +1,115 @@ +/* ---------------------------------------------------------------------------- +Copyright (c) 2019-2023 Microsoft Research, Daan Leijen +This is free software; you can redistribute it and/or modify it under the +terms of the MIT license. A copy of the license can be found in the file +"LICENSE" at the root of this distribution. +-----------------------------------------------------------------------------*/ + +/* ---------------------------------------------------------------------------- +Concurrent bitmap that can set/reset sequences of bits atomically, +represeted as an array of fields where each field is a machine word (`size_t`) + +There are two api's; the standard one cannot have sequences that cross +between the bitmap fields (and a sequence must be <= MI_BITMAP_FIELD_BITS). +(this is used in region allocation) + +The `_across` postfixed functions do allow sequences that can cross over +between the fields. (This is used in arena allocation) +---------------------------------------------------------------------------- */ +#pragma once +#ifndef MI_BITMAP_H +#define MI_BITMAP_H + +/* ----------------------------------------------------------- + Bitmap definition +----------------------------------------------------------- */ + +#define MI_BITMAP_FIELD_BITS (8*MI_SIZE_SIZE) +#define MI_BITMAP_FIELD_FULL (~((size_t)0)) // all bits set + +// An atomic bitmap of `size_t` fields +typedef _Atomic(size_t) mi_bitmap_field_t; +typedef mi_bitmap_field_t* mi_bitmap_t; + +// A bitmap index is the index of the bit in a bitmap. +typedef size_t mi_bitmap_index_t; + +// Create a bit index. +static inline mi_bitmap_index_t mi_bitmap_index_create(size_t idx, size_t bitidx) { + mi_assert_internal(bitidx < MI_BITMAP_FIELD_BITS); + return (idx*MI_BITMAP_FIELD_BITS) + bitidx; +} + +// Create a bit index. +static inline mi_bitmap_index_t mi_bitmap_index_create_from_bit(size_t full_bitidx) { + return mi_bitmap_index_create(full_bitidx / MI_BITMAP_FIELD_BITS, full_bitidx % MI_BITMAP_FIELD_BITS); +} + +// Get the field index from a bit index. +static inline size_t mi_bitmap_index_field(mi_bitmap_index_t bitmap_idx) { + return (bitmap_idx / MI_BITMAP_FIELD_BITS); +} + +// Get the bit index in a bitmap field +static inline size_t mi_bitmap_index_bit_in_field(mi_bitmap_index_t bitmap_idx) { + return (bitmap_idx % MI_BITMAP_FIELD_BITS); +} + +// Get the full bit index +static inline size_t mi_bitmap_index_bit(mi_bitmap_index_t bitmap_idx) { + return bitmap_idx; +} + +/* ----------------------------------------------------------- + Claim a bit sequence atomically +----------------------------------------------------------- */ + +// Try to atomically claim a sequence of `count` bits in a single +// field at `idx` in `bitmap`. Returns `true` on success. +bool _mi_bitmap_try_find_claim_field(mi_bitmap_t bitmap, size_t idx, const size_t count, mi_bitmap_index_t* bitmap_idx); + +// Starts at idx, and wraps around to search in all `bitmap_fields` fields. +// For now, `count` can be at most MI_BITMAP_FIELD_BITS and will never cross fields. +bool _mi_bitmap_try_find_from_claim(mi_bitmap_t bitmap, const size_t bitmap_fields, const size_t start_field_idx, const size_t count, mi_bitmap_index_t* bitmap_idx); + +// Like _mi_bitmap_try_find_from_claim but with an extra predicate that must be fullfilled +typedef bool (mi_cdecl *mi_bitmap_pred_fun_t)(mi_bitmap_index_t bitmap_idx, void* pred_arg); +bool _mi_bitmap_try_find_from_claim_pred(mi_bitmap_t bitmap, const size_t bitmap_fields, const size_t start_field_idx, const size_t count, mi_bitmap_pred_fun_t pred_fun, void* pred_arg, mi_bitmap_index_t* bitmap_idx); + +// Set `count` bits at `bitmap_idx` to 0 atomically +// Returns `true` if all `count` bits were 1 previously. +bool _mi_bitmap_unclaim(mi_bitmap_t bitmap, size_t bitmap_fields, size_t count, mi_bitmap_index_t bitmap_idx); + +// Try to set `count` bits at `bitmap_idx` from 0 to 1 atomically. +// Returns `true` if successful when all previous `count` bits were 0. +bool _mi_bitmap_try_claim(mi_bitmap_t bitmap, size_t bitmap_fields, size_t count, mi_bitmap_index_t bitmap_idx); + +// Set `count` bits at `bitmap_idx` to 1 atomically +// Returns `true` if all `count` bits were 0 previously. `any_zero` is `true` if there was at least one zero bit. +bool _mi_bitmap_claim(mi_bitmap_t bitmap, size_t bitmap_fields, size_t count, mi_bitmap_index_t bitmap_idx, bool* any_zero); + +bool _mi_bitmap_is_claimed(mi_bitmap_t bitmap, size_t bitmap_fields, size_t count, mi_bitmap_index_t bitmap_idx); +bool _mi_bitmap_is_any_claimed(mi_bitmap_t bitmap, size_t bitmap_fields, size_t count, mi_bitmap_index_t bitmap_idx); + + +//-------------------------------------------------------------------------- +// the `_across` functions work on bitmaps where sequences can cross over +// between the fields. This is used in arena allocation +//-------------------------------------------------------------------------- + +// Find `count` bits of zeros and set them to 1 atomically; returns `true` on success. +// Starts at idx, and wraps around to search in all `bitmap_fields` fields. +bool _mi_bitmap_try_find_from_claim_across(mi_bitmap_t bitmap, const size_t bitmap_fields, const size_t start_field_idx, const size_t count, mi_bitmap_index_t* bitmap_idx); + +// Set `count` bits at `bitmap_idx` to 0 atomically +// Returns `true` if all `count` bits were 1 previously. +bool _mi_bitmap_unclaim_across(mi_bitmap_t bitmap, size_t bitmap_fields, size_t count, mi_bitmap_index_t bitmap_idx); + +// Set `count` bits at `bitmap_idx` to 1 atomically +// Returns `true` if all `count` bits were 0 previously. `any_zero` is `true` if there was at least one zero bit. +bool _mi_bitmap_claim_across(mi_bitmap_t bitmap, size_t bitmap_fields, size_t count, mi_bitmap_index_t bitmap_idx, bool* pany_zero); + +bool _mi_bitmap_is_claimed_across(mi_bitmap_t bitmap, size_t bitmap_fields, size_t count, mi_bitmap_index_t bitmap_idx); +bool _mi_bitmap_is_any_claimed_across(mi_bitmap_t bitmap, size_t bitmap_fields, size_t count, mi_bitmap_index_t bitmap_idx); + +#endif diff --git a/Objects/mimalloc/heap.c b/Objects/mimalloc/heap.c new file mode 100644 index 00000000000000..6468999a7d5766 --- /dev/null +++ b/Objects/mimalloc/heap.c @@ -0,0 +1,641 @@ +/*---------------------------------------------------------------------------- +Copyright (c) 2018-2021, Microsoft Research, Daan Leijen +This is free software; you can redistribute it and/or modify it under the +terms of the MIT license. A copy of the license can be found in the file +"LICENSE" at the root of this distribution. +-----------------------------------------------------------------------------*/ + +#include "mimalloc.h" +#include "mimalloc/internal.h" +#include "mimalloc/atomic.h" +#include "mimalloc/prim.h" // mi_prim_get_default_heap + +#include // memset, memcpy + +#if defined(_MSC_VER) && (_MSC_VER < 1920) +#pragma warning(disable:4204) // non-constant aggregate initializer +#endif + +/* ----------------------------------------------------------- + Helpers +----------------------------------------------------------- */ + +// return `true` if ok, `false` to break +typedef bool (heap_page_visitor_fun)(mi_heap_t* heap, mi_page_queue_t* pq, mi_page_t* page, void* arg1, void* arg2); + +// Visit all pages in a heap; returns `false` if break was called. +static bool mi_heap_visit_pages(mi_heap_t* heap, heap_page_visitor_fun* fn, void* arg1, void* arg2) +{ + if (heap==NULL || heap->page_count==0) return 0; + + // visit all pages + #if MI_DEBUG>1 + size_t total = heap->page_count; + size_t count = 0; + #endif + + for (size_t i = 0; i <= MI_BIN_FULL; i++) { + mi_page_queue_t* pq = &heap->pages[i]; + mi_page_t* page = pq->first; + while(page != NULL) { + mi_page_t* next = page->next; // save next in case the page gets removed from the queue + mi_assert_internal(mi_page_heap(page) == heap); + #if MI_DEBUG>1 + count++; + #endif + if (!fn(heap, pq, page, arg1, arg2)) return false; + page = next; // and continue + } + } + mi_assert_internal(count == total); + return true; +} + + +#if MI_DEBUG>=2 +static bool mi_heap_page_is_valid(mi_heap_t* heap, mi_page_queue_t* pq, mi_page_t* page, void* arg1, void* arg2) { + MI_UNUSED(arg1); + MI_UNUSED(arg2); + MI_UNUSED(pq); + mi_assert_internal(mi_page_heap(page) == heap); + mi_segment_t* segment = _mi_page_segment(page); + mi_assert_internal(segment->thread_id == heap->thread_id); + mi_assert_expensive(_mi_page_is_valid(page)); + return true; +} +#endif +#if MI_DEBUG>=3 +static bool mi_heap_is_valid(mi_heap_t* heap) { + mi_assert_internal(heap!=NULL); + mi_heap_visit_pages(heap, &mi_heap_page_is_valid, NULL, NULL); + return true; +} +#endif + + + + +/* ----------------------------------------------------------- + "Collect" pages by migrating `local_free` and `thread_free` + lists and freeing empty pages. This is done when a thread + stops (and in that case abandons pages if there are still + blocks alive) +----------------------------------------------------------- */ + +typedef enum mi_collect_e { + MI_NORMAL, + MI_FORCE, + MI_ABANDON +} mi_collect_t; + + +static bool mi_heap_page_collect(mi_heap_t* heap, mi_page_queue_t* pq, mi_page_t* page, void* arg_collect, void* arg2 ) { + MI_UNUSED(arg2); + MI_UNUSED(heap); + mi_assert_internal(mi_heap_page_is_valid(heap, pq, page, NULL, NULL)); + mi_collect_t collect = *((mi_collect_t*)arg_collect); + _mi_page_free_collect(page, collect >= MI_FORCE); + if (mi_page_all_free(page)) { + // no more used blocks, free the page. + // note: this will free retired pages as well. + _mi_page_free(page, pq, collect >= MI_FORCE); + } + else if (collect == MI_ABANDON) { + // still used blocks but the thread is done; abandon the page + _mi_page_abandon(page, pq); + } + return true; // don't break +} + +static bool mi_heap_page_never_delayed_free(mi_heap_t* heap, mi_page_queue_t* pq, mi_page_t* page, void* arg1, void* arg2) { + MI_UNUSED(arg1); + MI_UNUSED(arg2); + MI_UNUSED(heap); + MI_UNUSED(pq); + _mi_page_use_delayed_free(page, MI_NEVER_DELAYED_FREE, false); + return true; // don't break +} + +static void mi_heap_collect_ex(mi_heap_t* heap, mi_collect_t collect) +{ + if (heap==NULL || !mi_heap_is_initialized(heap)) return; + + const bool force = collect >= MI_FORCE; + _mi_deferred_free(heap, force); + + // gh-112532: we may be called from a thread that is not the owner of the heap + bool is_main_thread = _mi_is_main_thread() && heap->thread_id == _mi_thread_id(); + + // note: never reclaim on collect but leave it to threads that need storage to reclaim + const bool force_main = + #ifdef NDEBUG + collect == MI_FORCE + #else + collect >= MI_FORCE + #endif + && is_main_thread && mi_heap_is_backing(heap) && !heap->no_reclaim; + + if (force_main) { + // the main thread is abandoned (end-of-program), try to reclaim all abandoned segments. + // if all memory is freed by now, all segments should be freed. + _mi_abandoned_reclaim_all(heap, &heap->tld->segments); + } + + // if abandoning, mark all pages to no longer add to delayed_free + if (collect == MI_ABANDON) { + mi_heap_visit_pages(heap, &mi_heap_page_never_delayed_free, NULL, NULL); + } + + // free all current thread delayed blocks. + // (if abandoning, after this there are no more thread-delayed references into the pages.) + _mi_heap_delayed_free_all(heap); + + // collect retired pages + _mi_heap_collect_retired(heap, force); + + // collect all pages owned by this thread + mi_heap_visit_pages(heap, &mi_heap_page_collect, &collect, NULL); + mi_assert_internal( collect != MI_ABANDON || mi_atomic_load_ptr_acquire(mi_block_t,&heap->thread_delayed_free) == NULL ); + + // collect abandoned segments (in particular, purge expired parts of segments in the abandoned segment list) + // note: forced purge can be quite expensive if many threads are created/destroyed so we do not force on abandonment + _mi_abandoned_collect(heap, collect == MI_FORCE /* force? */, &heap->tld->segments); + + // collect segment local caches + if (force) { + _mi_segment_thread_collect(&heap->tld->segments); + } + + // collect regions on program-exit (or shared library unload) + if (force && is_main_thread && mi_heap_is_backing(heap)) { + _mi_thread_data_collect(); // collect thread data cache + _mi_arena_collect(true /* force purge */, &heap->tld->stats); + } +} + +void _mi_heap_collect_abandon(mi_heap_t* heap) { + mi_heap_collect_ex(heap, MI_ABANDON); +} + +void mi_heap_collect(mi_heap_t* heap, bool force) mi_attr_noexcept { + mi_heap_collect_ex(heap, (force ? MI_FORCE : MI_NORMAL)); +} + +void mi_collect(bool force) mi_attr_noexcept { + mi_heap_collect(mi_prim_get_default_heap(), force); +} + + +/* ----------------------------------------------------------- + Heap new +----------------------------------------------------------- */ + +mi_heap_t* mi_heap_get_default(void) { + mi_thread_init(); + return mi_prim_get_default_heap(); +} + +static bool mi_heap_is_default(const mi_heap_t* heap) { + return (heap == mi_prim_get_default_heap()); +} + + +mi_heap_t* mi_heap_get_backing(void) { + mi_heap_t* heap = mi_heap_get_default(); + mi_assert_internal(heap!=NULL); + mi_heap_t* bheap = heap->tld->heap_backing; + mi_assert_internal(bheap!=NULL); + mi_assert_internal(bheap->thread_id == _mi_thread_id()); + return bheap; +} + +void _mi_heap_init_ex(mi_heap_t* heap, mi_tld_t* tld, mi_arena_id_t arena_id, bool no_reclaim, uint8_t tag) +{ + _mi_memcpy_aligned(heap, &_mi_heap_empty, sizeof(mi_heap_t)); + heap->tld = tld; + heap->thread_id = _mi_thread_id(); + heap->arena_id = arena_id; + if (heap == tld->heap_backing) { + _mi_random_init(&heap->random); + } + else { + _mi_random_split(&tld->heap_backing->random, &heap->random); + } + heap->cookie = _mi_heap_random_next(heap) | 1; + heap->keys[0] = _mi_heap_random_next(heap); + heap->keys[1] = _mi_heap_random_next(heap); + heap->no_reclaim = no_reclaim; + heap->tag = tag; + // push on the thread local heaps list + heap->next = heap->tld->heaps; + heap->tld->heaps = heap; +} + +mi_decl_nodiscard mi_heap_t* mi_heap_new_in_arena(mi_arena_id_t arena_id) { + mi_heap_t* bheap = mi_heap_get_backing(); + mi_heap_t* heap = mi_heap_malloc_tp(bheap, mi_heap_t); // todo: OS allocate in secure mode? + if (heap == NULL) return NULL; + // don't reclaim abandoned pages or otherwise destroy is unsafe + _mi_heap_init_ex(heap, bheap->tld, arena_id, true, 0); + return heap; +} + +mi_decl_nodiscard mi_heap_t* mi_heap_new(void) { + return mi_heap_new_in_arena(_mi_arena_id_none()); +} + +bool _mi_heap_memid_is_suitable(mi_heap_t* heap, mi_memid_t memid) { + return _mi_arena_memid_is_suitable(memid, heap->arena_id); +} + +uintptr_t _mi_heap_random_next(mi_heap_t* heap) { + return _mi_random_next(&heap->random); +} + +// zero out the page queues +static void mi_heap_reset_pages(mi_heap_t* heap) { + mi_assert_internal(heap != NULL); + mi_assert_internal(mi_heap_is_initialized(heap)); + // TODO: copy full empty heap instead? + memset(&heap->pages_free_direct, 0, sizeof(heap->pages_free_direct)); + _mi_memcpy_aligned(&heap->pages, &_mi_heap_empty.pages, sizeof(heap->pages)); + heap->thread_delayed_free = NULL; + heap->page_count = 0; +} + +// called from `mi_heap_destroy` and `mi_heap_delete` to free the internal heap resources. +static void mi_heap_free(mi_heap_t* heap) { + mi_assert(heap != NULL); + mi_assert_internal(mi_heap_is_initialized(heap)); + if (heap==NULL || !mi_heap_is_initialized(heap)) return; + if (mi_heap_is_backing(heap)) return; // dont free the backing heap + + // reset default + if (mi_heap_is_default(heap)) { + _mi_heap_set_default_direct(heap->tld->heap_backing); + } + + // remove ourselves from the thread local heaps list + // linear search but we expect the number of heaps to be relatively small + mi_heap_t* prev = NULL; + mi_heap_t* curr = heap->tld->heaps; + while (curr != heap && curr != NULL) { + prev = curr; + curr = curr->next; + } + mi_assert_internal(curr == heap); + if (curr == heap) { + if (prev != NULL) { prev->next = heap->next; } + else { heap->tld->heaps = heap->next; } + } + mi_assert_internal(heap->tld->heaps != NULL); + + // and free the used memory + mi_free(heap); +} + + +/* ----------------------------------------------------------- + Heap destroy +----------------------------------------------------------- */ + +static bool _mi_heap_page_destroy(mi_heap_t* heap, mi_page_queue_t* pq, mi_page_t* page, void* arg1, void* arg2) { + MI_UNUSED(arg1); + MI_UNUSED(arg2); + MI_UNUSED(heap); + MI_UNUSED(pq); + + // ensure no more thread_delayed_free will be added + _mi_page_use_delayed_free(page, MI_NEVER_DELAYED_FREE, false); + + // stats + const size_t bsize = mi_page_block_size(page); + if (bsize > MI_MEDIUM_OBJ_SIZE_MAX) { + if (bsize <= MI_LARGE_OBJ_SIZE_MAX) { + mi_heap_stat_decrease(heap, large, bsize); + } + else { + mi_heap_stat_decrease(heap, huge, bsize); + } + } +#if (MI_STAT) + _mi_page_free_collect(page, false); // update used count + const size_t inuse = page->used; + if (bsize <= MI_LARGE_OBJ_SIZE_MAX) { + mi_heap_stat_decrease(heap, normal, bsize * inuse); +#if (MI_STAT>1) + mi_heap_stat_decrease(heap, normal_bins[_mi_bin(bsize)], inuse); +#endif + } + mi_heap_stat_decrease(heap, malloc, bsize * inuse); // todo: off for aligned blocks... +#endif + + /// pretend it is all free now + mi_assert_internal(mi_page_thread_free(page) == NULL); + page->used = 0; + + // and free the page + // mi_page_free(page,false); + page->next = NULL; + page->prev = NULL; + _mi_segment_page_free(page,false /* no force? */, &heap->tld->segments); + + return true; // keep going +} + +void _mi_heap_destroy_pages(mi_heap_t* heap) { + mi_heap_visit_pages(heap, &_mi_heap_page_destroy, NULL, NULL); + mi_heap_reset_pages(heap); +} + +#if MI_TRACK_HEAP_DESTROY +static bool mi_cdecl mi_heap_track_block_free(const mi_heap_t* heap, const mi_heap_area_t* area, void* block, size_t block_size, void* arg) { + MI_UNUSED(heap); MI_UNUSED(area); MI_UNUSED(arg); MI_UNUSED(block_size); + mi_track_free_size(block,mi_usable_size(block)); + return true; +} +#endif + +void mi_heap_destroy(mi_heap_t* heap) { + mi_assert(heap != NULL); + mi_assert(mi_heap_is_initialized(heap)); + mi_assert(heap->no_reclaim); + mi_assert_expensive(mi_heap_is_valid(heap)); + if (heap==NULL || !mi_heap_is_initialized(heap)) return; + if (!heap->no_reclaim) { + // don't free in case it may contain reclaimed pages + mi_heap_delete(heap); + } + else { + // track all blocks as freed + #if MI_TRACK_HEAP_DESTROY + mi_heap_visit_blocks(heap, true, mi_heap_track_block_free, NULL); + #endif + // free all pages + _mi_heap_destroy_pages(heap); + mi_heap_free(heap); + } +} + +// forcefully destroy all heaps in the current thread +void _mi_heap_unsafe_destroy_all(void) { + mi_heap_t* bheap = mi_heap_get_backing(); + mi_heap_t* curr = bheap->tld->heaps; + while (curr != NULL) { + mi_heap_t* next = curr->next; + if (curr->no_reclaim) { + mi_heap_destroy(curr); + } + else { + _mi_heap_destroy_pages(curr); + } + curr = next; + } +} + +/* ----------------------------------------------------------- + Safe Heap delete +----------------------------------------------------------- */ + +// Transfer the pages from one heap to the other +static void mi_heap_absorb(mi_heap_t* heap, mi_heap_t* from) { + mi_assert_internal(heap!=NULL); + if (from==NULL || from->page_count == 0) return; + + // reduce the size of the delayed frees + _mi_heap_delayed_free_partial(from); + + // transfer all pages by appending the queues; this will set a new heap field + // so threads may do delayed frees in either heap for a while. + // note: appending waits for each page to not be in the `MI_DELAYED_FREEING` state + // so after this only the new heap will get delayed frees + for (size_t i = 0; i <= MI_BIN_FULL; i++) { + mi_page_queue_t* pq = &heap->pages[i]; + mi_page_queue_t* append = &from->pages[i]; + size_t pcount = _mi_page_queue_append(heap, pq, append); + heap->page_count += pcount; + from->page_count -= pcount; + } + mi_assert_internal(from->page_count == 0); + + // and do outstanding delayed frees in the `from` heap + // note: be careful here as the `heap` field in all those pages no longer point to `from`, + // turns out to be ok as `_mi_heap_delayed_free` only visits the list and calls a + // the regular `_mi_free_delayed_block` which is safe. + _mi_heap_delayed_free_all(from); + #if !defined(_MSC_VER) || (_MSC_VER > 1900) // somehow the following line gives an error in VS2015, issue #353 + mi_assert_internal(mi_atomic_load_ptr_relaxed(mi_block_t,&from->thread_delayed_free) == NULL); + #endif + + // and reset the `from` heap + mi_heap_reset_pages(from); +} + +// Safe delete a heap without freeing any still allocated blocks in that heap. +void mi_heap_delete(mi_heap_t* heap) +{ + mi_assert(heap != NULL); + mi_assert(mi_heap_is_initialized(heap)); + mi_assert_expensive(mi_heap_is_valid(heap)); + if (heap==NULL || !mi_heap_is_initialized(heap)) return; + + if (!mi_heap_is_backing(heap)) { + // tranfer still used pages to the backing heap + mi_heap_absorb(heap->tld->heap_backing, heap); + } + else { + // the backing heap abandons its pages + _mi_heap_collect_abandon(heap); + } + mi_assert_internal(heap->page_count==0); + mi_heap_free(heap); +} + +mi_heap_t* mi_heap_set_default(mi_heap_t* heap) { + mi_assert(heap != NULL); + mi_assert(mi_heap_is_initialized(heap)); + if (heap==NULL || !mi_heap_is_initialized(heap)) return NULL; + mi_assert_expensive(mi_heap_is_valid(heap)); + mi_heap_t* old = mi_prim_get_default_heap(); + _mi_heap_set_default_direct(heap); + return old; +} + + + + +/* ----------------------------------------------------------- + Analysis +----------------------------------------------------------- */ + +// static since it is not thread safe to access heaps from other threads. +static mi_heap_t* mi_heap_of_block(const void* p) { + if (p == NULL) return NULL; + mi_segment_t* segment = _mi_ptr_segment(p); + bool valid = (_mi_ptr_cookie(segment) == segment->cookie); + mi_assert_internal(valid); + if mi_unlikely(!valid) return NULL; + return mi_page_heap(_mi_segment_page_of(segment,p)); +} + +bool mi_heap_contains_block(mi_heap_t* heap, const void* p) { + mi_assert(heap != NULL); + if (heap==NULL || !mi_heap_is_initialized(heap)) return false; + return (heap == mi_heap_of_block(p)); +} + + +static bool mi_heap_page_check_owned(mi_heap_t* heap, mi_page_queue_t* pq, mi_page_t* page, void* p, void* vfound) { + MI_UNUSED(heap); + MI_UNUSED(pq); + bool* found = (bool*)vfound; + mi_segment_t* segment = _mi_page_segment(page); + void* start = _mi_page_start(segment, page, NULL); + void* end = (uint8_t*)start + (page->capacity * mi_page_block_size(page)); + *found = (p >= start && p < end); + return (!*found); // continue if not found +} + +bool mi_heap_check_owned(mi_heap_t* heap, const void* p) { + mi_assert(heap != NULL); + if (heap==NULL || !mi_heap_is_initialized(heap)) return false; + if (((uintptr_t)p & (MI_INTPTR_SIZE - 1)) != 0) return false; // only aligned pointers + bool found = false; + mi_heap_visit_pages(heap, &mi_heap_page_check_owned, (void*)p, &found); + return found; +} + +bool mi_check_owned(const void* p) { + return mi_heap_check_owned(mi_prim_get_default_heap(), p); +} + +/* ----------------------------------------------------------- + Visit all heap blocks and areas + Todo: enable visiting abandoned pages, and + enable visiting all blocks of all heaps across threads +----------------------------------------------------------- */ + +// Separate struct to keep `mi_page_t` out of the public interface +typedef struct mi_heap_area_ex_s { + mi_heap_area_t area; + mi_page_t* page; +} mi_heap_area_ex_t; + +static bool mi_heap_area_visit_blocks(const mi_heap_area_ex_t* xarea, mi_block_visit_fun* visitor, void* arg) { + mi_assert(xarea != NULL); + if (xarea==NULL) return true; + const mi_heap_area_t* area = &xarea->area; + mi_page_t* page = xarea->page; + mi_assert(page != NULL); + if (page == NULL) return true; + + _mi_page_free_collect(page,true); + mi_assert_internal(page->local_free == NULL); + if (page->used == 0) return true; + + const size_t bsize = mi_page_block_size(page); + const size_t ubsize = mi_page_usable_block_size(page); // without padding + size_t psize; + uint8_t* pstart = _mi_page_start(_mi_page_segment(page), page, &psize); + + if (page->capacity == 1) { + // optimize page with one block + mi_assert_internal(page->used == 1 && page->free == NULL); + return visitor(mi_page_heap(page), area, pstart, ubsize, arg); + } + + // create a bitmap of free blocks. + #define MI_MAX_BLOCKS (MI_SMALL_PAGE_SIZE / sizeof(void*)) + uintptr_t free_map[MI_MAX_BLOCKS / sizeof(uintptr_t)]; + memset(free_map, 0, sizeof(free_map)); + + #if MI_DEBUG>1 + size_t free_count = 0; + #endif + for (mi_block_t* block = page->free; block != NULL; block = mi_block_next(page,block)) { + #if MI_DEBUG>1 + free_count++; + #endif + mi_assert_internal((uint8_t*)block >= pstart && (uint8_t*)block < (pstart + psize)); + size_t offset = (uint8_t*)block - pstart; + mi_assert_internal(offset % bsize == 0); + size_t blockidx = offset / bsize; // Todo: avoid division? + mi_assert_internal( blockidx < MI_MAX_BLOCKS); + size_t bitidx = (blockidx / sizeof(uintptr_t)); + size_t bit = blockidx - (bitidx * sizeof(uintptr_t)); + free_map[bitidx] |= ((uintptr_t)1 << bit); + } + mi_assert_internal(page->capacity == (free_count + page->used)); + + // walk through all blocks skipping the free ones + #if MI_DEBUG>1 + size_t used_count = 0; + #endif + for (size_t i = 0; i < page->capacity; i++) { + size_t bitidx = (i / sizeof(uintptr_t)); + size_t bit = i - (bitidx * sizeof(uintptr_t)); + uintptr_t m = free_map[bitidx]; + if (bit == 0 && m == UINTPTR_MAX) { + i += (sizeof(uintptr_t) - 1); // skip a run of free blocks + } + else if ((m & ((uintptr_t)1 << bit)) == 0) { + #if MI_DEBUG>1 + used_count++; + #endif + uint8_t* block = pstart + (i * bsize); + if (!visitor(mi_page_heap(page), area, block, ubsize, arg)) return false; + } + } + mi_assert_internal(page->used == used_count); + return true; +} + +typedef bool (mi_heap_area_visit_fun)(const mi_heap_t* heap, const mi_heap_area_ex_t* area, void* arg); + + +static bool mi_heap_visit_areas_page(mi_heap_t* heap, mi_page_queue_t* pq, mi_page_t* page, void* vfun, void* arg) { + MI_UNUSED(heap); + MI_UNUSED(pq); + mi_heap_area_visit_fun* fun = (mi_heap_area_visit_fun*)vfun; + mi_heap_area_ex_t xarea; + const size_t bsize = mi_page_block_size(page); + const size_t ubsize = mi_page_usable_block_size(page); + xarea.page = page; + xarea.area.reserved = page->reserved * bsize; + xarea.area.committed = page->capacity * bsize; + xarea.area.blocks = _mi_page_start(_mi_page_segment(page), page, NULL); + xarea.area.used = page->used; // number of blocks in use (#553) + xarea.area.block_size = ubsize; + xarea.area.full_block_size = bsize; + return fun(heap, &xarea, arg); +} + +// Visit all heap pages as areas +static bool mi_heap_visit_areas(const mi_heap_t* heap, mi_heap_area_visit_fun* visitor, void* arg) { + if (visitor == NULL) return false; + return mi_heap_visit_pages((mi_heap_t*)heap, &mi_heap_visit_areas_page, (void*)(visitor), arg); // note: function pointer to void* :-{ +} + +// Just to pass arguments +typedef struct mi_visit_blocks_args_s { + bool visit_blocks; + mi_block_visit_fun* visitor; + void* arg; +} mi_visit_blocks_args_t; + +static bool mi_heap_area_visitor(const mi_heap_t* heap, const mi_heap_area_ex_t* xarea, void* arg) { + mi_visit_blocks_args_t* args = (mi_visit_blocks_args_t*)arg; + if (!args->visitor(heap, &xarea->area, NULL, xarea->area.block_size, args->arg)) return false; + if (args->visit_blocks) { + return mi_heap_area_visit_blocks(xarea, args->visitor, args->arg); + } + else { + return true; + } +} + +// Visit all blocks in a heap +bool mi_heap_visit_blocks(const mi_heap_t* heap, bool visit_blocks, mi_block_visit_fun* visitor, void* arg) { + mi_visit_blocks_args_t args = { visit_blocks, visitor, arg }; + return mi_heap_visit_areas(heap, &mi_heap_area_visitor, &args); +} diff --git a/Objects/mimalloc/init.c b/Objects/mimalloc/init.c new file mode 100644 index 00000000000000..5897f0512f8ef9 --- /dev/null +++ b/Objects/mimalloc/init.c @@ -0,0 +1,706 @@ +/* ---------------------------------------------------------------------------- +Copyright (c) 2018-2022, Microsoft Research, Daan Leijen +This is free software; you can redistribute it and/or modify it under the +terms of the MIT license. A copy of the license can be found in the file +"LICENSE" at the root of this distribution. +-----------------------------------------------------------------------------*/ +#include "mimalloc.h" +#include "mimalloc/internal.h" +#include "mimalloc/prim.h" + +#include // memcpy, memset +#include // atexit + + +// Empty page used to initialize the small free pages array +const mi_page_t _mi_page_empty = { + 0, false, false, false, 0, + 0, // capacity + 0, // reserved capacity + { 0 }, // flags + false, // is_zero + 0, // retire_expire + NULL, // free + 0, // used + 0, // xblock_size + NULL, // local_free + #if (MI_PADDING || MI_ENCODE_FREELIST) + { 0, 0 }, + #endif + MI_ATOMIC_VAR_INIT(0), // xthread_free + MI_ATOMIC_VAR_INIT(0), // xheap + NULL, NULL + #if MI_INTPTR_SIZE==8 + , { 0 } // padding + #endif +}; + +#define MI_PAGE_EMPTY() ((mi_page_t*)&_mi_page_empty) + +#if (MI_SMALL_WSIZE_MAX==128) +#if (MI_PADDING>0) && (MI_INTPTR_SIZE >= 8) +#define MI_SMALL_PAGES_EMPTY { MI_INIT128(MI_PAGE_EMPTY), MI_PAGE_EMPTY(), MI_PAGE_EMPTY() } +#elif (MI_PADDING>0) +#define MI_SMALL_PAGES_EMPTY { MI_INIT128(MI_PAGE_EMPTY), MI_PAGE_EMPTY(), MI_PAGE_EMPTY(), MI_PAGE_EMPTY() } +#else +#define MI_SMALL_PAGES_EMPTY { MI_INIT128(MI_PAGE_EMPTY), MI_PAGE_EMPTY() } +#endif +#else +#error "define right initialization sizes corresponding to MI_SMALL_WSIZE_MAX" +#endif + +// Empty page queues for every bin +#define QNULL(sz) { NULL, NULL, (sz)*sizeof(uintptr_t) } +#define MI_PAGE_QUEUES_EMPTY \ + { QNULL(1), \ + QNULL( 1), QNULL( 2), QNULL( 3), QNULL( 4), QNULL( 5), QNULL( 6), QNULL( 7), QNULL( 8), /* 8 */ \ + QNULL( 10), QNULL( 12), QNULL( 14), QNULL( 16), QNULL( 20), QNULL( 24), QNULL( 28), QNULL( 32), /* 16 */ \ + QNULL( 40), QNULL( 48), QNULL( 56), QNULL( 64), QNULL( 80), QNULL( 96), QNULL( 112), QNULL( 128), /* 24 */ \ + QNULL( 160), QNULL( 192), QNULL( 224), QNULL( 256), QNULL( 320), QNULL( 384), QNULL( 448), QNULL( 512), /* 32 */ \ + QNULL( 640), QNULL( 768), QNULL( 896), QNULL( 1024), QNULL( 1280), QNULL( 1536), QNULL( 1792), QNULL( 2048), /* 40 */ \ + QNULL( 2560), QNULL( 3072), QNULL( 3584), QNULL( 4096), QNULL( 5120), QNULL( 6144), QNULL( 7168), QNULL( 8192), /* 48 */ \ + QNULL( 10240), QNULL( 12288), QNULL( 14336), QNULL( 16384), QNULL( 20480), QNULL( 24576), QNULL( 28672), QNULL( 32768), /* 56 */ \ + QNULL( 40960), QNULL( 49152), QNULL( 57344), QNULL( 65536), QNULL( 81920), QNULL( 98304), QNULL(114688), QNULL(131072), /* 64 */ \ + QNULL(163840), QNULL(196608), QNULL(229376), QNULL(262144), QNULL(327680), QNULL(393216), QNULL(458752), QNULL(524288), /* 72 */ \ + QNULL(MI_MEDIUM_OBJ_WSIZE_MAX + 1 /* 655360, Huge queue */), \ + QNULL(MI_MEDIUM_OBJ_WSIZE_MAX + 2) /* Full queue */ } + +#define MI_STAT_COUNT_NULL() {0,0,0,0} + +// Empty statistics +#if MI_STAT>1 +#define MI_STAT_COUNT_END_NULL() , { MI_STAT_COUNT_NULL(), MI_INIT32(MI_STAT_COUNT_NULL) } +#else +#define MI_STAT_COUNT_END_NULL() +#endif + +#define MI_STATS_NULL \ + MI_STAT_COUNT_NULL(), MI_STAT_COUNT_NULL(), \ + MI_STAT_COUNT_NULL(), MI_STAT_COUNT_NULL(), \ + MI_STAT_COUNT_NULL(), MI_STAT_COUNT_NULL(), \ + MI_STAT_COUNT_NULL(), MI_STAT_COUNT_NULL(), \ + MI_STAT_COUNT_NULL(), MI_STAT_COUNT_NULL(), \ + MI_STAT_COUNT_NULL(), MI_STAT_COUNT_NULL(), \ + MI_STAT_COUNT_NULL(), MI_STAT_COUNT_NULL(), \ + MI_STAT_COUNT_NULL(), \ + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, \ + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } \ + MI_STAT_COUNT_END_NULL() + + +// Empty slice span queues for every bin +#define SQNULL(sz) { NULL, NULL, sz } +#define MI_SEGMENT_SPAN_QUEUES_EMPTY \ + { SQNULL(1), \ + SQNULL( 1), SQNULL( 2), SQNULL( 3), SQNULL( 4), SQNULL( 5), SQNULL( 6), SQNULL( 7), SQNULL( 10), /* 8 */ \ + SQNULL( 12), SQNULL( 14), SQNULL( 16), SQNULL( 20), SQNULL( 24), SQNULL( 28), SQNULL( 32), SQNULL( 40), /* 16 */ \ + SQNULL( 48), SQNULL( 56), SQNULL( 64), SQNULL( 80), SQNULL( 96), SQNULL( 112), SQNULL( 128), SQNULL( 160), /* 24 */ \ + SQNULL( 192), SQNULL( 224), SQNULL( 256), SQNULL( 320), SQNULL( 384), SQNULL( 448), SQNULL( 512), SQNULL( 640), /* 32 */ \ + SQNULL( 768), SQNULL( 896), SQNULL( 1024) /* 35 */ } + + +// -------------------------------------------------------- +// Statically allocate an empty heap as the initial +// thread local value for the default heap, +// and statically allocate the backing heap for the main +// thread so it can function without doing any allocation +// itself (as accessing a thread local for the first time +// may lead to allocation itself on some platforms) +// -------------------------------------------------------- + +mi_decl_cache_align const mi_heap_t _mi_heap_empty = { + NULL, + MI_SMALL_PAGES_EMPTY, + MI_PAGE_QUEUES_EMPTY, + MI_ATOMIC_VAR_INIT(NULL), + 0, // tid + 0, // cookie + 0, // arena id + { 0, 0 }, // keys + { {0}, {0}, 0, true }, // random + 0, // page count + MI_BIN_FULL, 0, // page retired min/max + NULL, // next + false, + 0 +}; + +#define tld_empty_stats ((mi_stats_t*)((uint8_t*)&tld_empty + offsetof(mi_tld_t,stats))) +#define tld_empty_os ((mi_os_tld_t*)((uint8_t*)&tld_empty + offsetof(mi_tld_t,os))) + +mi_decl_cache_align static const mi_tld_t tld_empty = { + 0, + false, + NULL, NULL, + { MI_SEGMENT_SPAN_QUEUES_EMPTY, 0, 0, 0, 0, tld_empty_stats, tld_empty_os, &_mi_abandoned_default }, // segments + { 0, tld_empty_stats }, // os + { MI_STATS_NULL } // stats +}; + +mi_threadid_t _mi_thread_id(void) mi_attr_noexcept { + return _mi_prim_thread_id(); +} + +// the thread-local default heap for allocation +mi_decl_thread mi_heap_t* _mi_heap_default = (mi_heap_t*)&_mi_heap_empty; + +extern mi_heap_t _mi_heap_main; + +static mi_tld_t tld_main = { + 0, false, + &_mi_heap_main, & _mi_heap_main, + { MI_SEGMENT_SPAN_QUEUES_EMPTY, 0, 0, 0, 0, &tld_main.stats, &tld_main.os, &_mi_abandoned_default }, // segments + { 0, &tld_main.stats }, // os + { MI_STATS_NULL } // stats +}; + +mi_heap_t _mi_heap_main = { + &tld_main, + MI_SMALL_PAGES_EMPTY, + MI_PAGE_QUEUES_EMPTY, + MI_ATOMIC_VAR_INIT(NULL), + 0, // thread id + 0, // initial cookie + 0, // arena id + { 0, 0 }, // the key of the main heap can be fixed (unlike page keys that need to be secure!) + { {0x846ca68b}, {0}, 0, true }, // random + 0, // page count + MI_BIN_FULL, 0, // page retired min/max + NULL, // next heap + false // can reclaim +}; + +bool _mi_process_is_initialized = false; // set to `true` in `mi_process_init`. + +mi_stats_t _mi_stats_main = { MI_STATS_NULL }; + + +static void mi_heap_main_init(void) { + if (_mi_heap_main.cookie == 0) { + _mi_heap_main.thread_id = _mi_thread_id(); + _mi_heap_main.cookie = 1; + #if defined(_WIN32) && !defined(MI_SHARED_LIB) + _mi_random_init_weak(&_mi_heap_main.random); // prevent allocation failure during bcrypt dll initialization with static linking + #else + _mi_random_init(&_mi_heap_main.random); + #endif + _mi_heap_main.cookie = _mi_heap_random_next(&_mi_heap_main); + _mi_heap_main.keys[0] = _mi_heap_random_next(&_mi_heap_main); + _mi_heap_main.keys[1] = _mi_heap_random_next(&_mi_heap_main); + } +} + +mi_heap_t* _mi_heap_main_get(void) { + mi_heap_main_init(); + return &_mi_heap_main; +} + + +/* ----------------------------------------------------------- + Initialization and freeing of the thread local heaps +----------------------------------------------------------- */ + +// note: in x64 in release build `sizeof(mi_thread_data_t)` is under 4KiB (= OS page size). +typedef struct mi_thread_data_s { + mi_heap_t heap; // must come first due to cast in `_mi_heap_done` + mi_tld_t tld; + mi_memid_t memid; +} mi_thread_data_t; + + +// Thread meta-data is allocated directly from the OS. For +// some programs that do not use thread pools and allocate and +// destroy many OS threads, this may causes too much overhead +// per thread so we maintain a small cache of recently freed metadata. + +#define TD_CACHE_SIZE (16) +static _Atomic(mi_thread_data_t*) td_cache[TD_CACHE_SIZE]; + +static mi_thread_data_t* mi_thread_data_zalloc(void) { + // try to find thread metadata in the cache + bool is_zero = false; + mi_thread_data_t* td = NULL; + for (int i = 0; i < TD_CACHE_SIZE; i++) { + td = mi_atomic_load_ptr_relaxed(mi_thread_data_t, &td_cache[i]); + if (td != NULL) { + // found cached allocation, try use it + td = mi_atomic_exchange_ptr_acq_rel(mi_thread_data_t, &td_cache[i], NULL); + if (td != NULL) { + break; + } + } + } + + // if that fails, allocate as meta data + if (td == NULL) { + mi_memid_t memid; + td = (mi_thread_data_t*)_mi_os_alloc(sizeof(mi_thread_data_t), &memid, &_mi_stats_main); + if (td == NULL) { + // if this fails, try once more. (issue #257) + td = (mi_thread_data_t*)_mi_os_alloc(sizeof(mi_thread_data_t), &memid, &_mi_stats_main); + if (td == NULL) { + // really out of memory + _mi_error_message(ENOMEM, "unable to allocate thread local heap metadata (%zu bytes)\n", sizeof(mi_thread_data_t)); + } + } + if (td != NULL) { + td->memid = memid; + is_zero = memid.initially_zero; + } + } + + if (td != NULL && !is_zero) { + _mi_memzero_aligned(td, sizeof(*td)); + } + return td; +} + +static void mi_thread_data_free( mi_thread_data_t* tdfree ) { + // try to add the thread metadata to the cache + for (int i = 0; i < TD_CACHE_SIZE; i++) { + mi_thread_data_t* td = mi_atomic_load_ptr_relaxed(mi_thread_data_t, &td_cache[i]); + if (td == NULL) { + mi_thread_data_t* expected = NULL; + if (mi_atomic_cas_ptr_weak_acq_rel(mi_thread_data_t, &td_cache[i], &expected, tdfree)) { + return; + } + } + } + // if that fails, just free it directly + _mi_os_free(tdfree, sizeof(mi_thread_data_t), tdfree->memid, &_mi_stats_main); +} + +void _mi_thread_data_collect(void) { + // free all thread metadata from the cache + for (int i = 0; i < TD_CACHE_SIZE; i++) { + mi_thread_data_t* td = mi_atomic_load_ptr_relaxed(mi_thread_data_t, &td_cache[i]); + if (td != NULL) { + td = mi_atomic_exchange_ptr_acq_rel(mi_thread_data_t, &td_cache[i], NULL); + if (td != NULL) { + _mi_os_free(td, sizeof(mi_thread_data_t), td->memid, &_mi_stats_main); + } + } + } +} + +// Initialize the thread local default heap, called from `mi_thread_init` +static bool _mi_heap_init(void) { + if (mi_heap_is_initialized(mi_prim_get_default_heap())) return true; + if (_mi_is_main_thread()) { + // mi_assert_internal(_mi_heap_main.thread_id != 0); // can happen on freeBSD where alloc is called before any initialization + // the main heap is statically allocated + mi_heap_main_init(); + _mi_heap_set_default_direct(&_mi_heap_main); + //mi_assert_internal(_mi_heap_default->tld->heap_backing == mi_prim_get_default_heap()); + } + else { + // use `_mi_os_alloc` to allocate directly from the OS + mi_thread_data_t* td = mi_thread_data_zalloc(); + if (td == NULL) return false; + + _mi_tld_init(&td->tld, &td->heap); + _mi_heap_init_ex(&td->heap, &td->tld, _mi_arena_id_none(), false, 0); + _mi_heap_set_default_direct(&td->heap); + } + return false; +} + +void _mi_tld_init(mi_tld_t* tld, mi_heap_t* bheap) { + _mi_memcpy_aligned(tld, &tld_empty, sizeof(*tld)); + tld->segments.stats = &tld->stats; + tld->segments.os = &tld->os; + tld->segments.abandoned = &_mi_abandoned_default; + tld->os.stats = &tld->stats; + tld->heap_backing = bheap; +} + +// Free the thread local default heap (called from `mi_thread_done`) +static bool _mi_heap_done(mi_heap_t* heap) { + if (!mi_heap_is_initialized(heap)) return true; + + // reset default heap + _mi_heap_set_default_direct(_mi_is_main_thread() ? &_mi_heap_main : (mi_heap_t*)&_mi_heap_empty); + + // switch to backing heap + heap = heap->tld->heap_backing; + if (!mi_heap_is_initialized(heap)) return false; + + // delete all non-backing heaps in this thread + mi_heap_t* curr = heap->tld->heaps; + while (curr != NULL) { + mi_heap_t* next = curr->next; // save `next` as `curr` will be freed + if (curr != heap) { + mi_assert_internal(!mi_heap_is_backing(curr)); + mi_heap_delete(curr); + } + curr = next; + } + mi_assert_internal(heap->tld->heaps == heap && heap->next == NULL); + mi_assert_internal(mi_heap_is_backing(heap)); + + // collect if not the main thread + if (heap != &_mi_heap_main) { + _mi_heap_collect_abandon(heap); + } + + // merge stats + _mi_stats_done(&heap->tld->stats); + + // free if not the main thread + if (heap != &_mi_heap_main) { + // the following assertion does not always hold for huge segments as those are always treated + // as abondened: one may allocate it in one thread, but deallocate in another in which case + // the count can be too large or negative. todo: perhaps not count huge segments? see issue #363 + // mi_assert_internal(heap->tld->segments.count == 0 || heap->thread_id != _mi_thread_id()); + mi_thread_data_free((mi_thread_data_t*)heap); + } + else { + #if 0 + // never free the main thread even in debug mode; if a dll is linked statically with mimalloc, + // there may still be delete/free calls after the mi_fls_done is called. Issue #207 + _mi_heap_destroy_pages(heap); + mi_assert_internal(heap->tld->heap_backing == &_mi_heap_main); + #endif + } + return false; +} + + + +// -------------------------------------------------------- +// Try to run `mi_thread_done()` automatically so any memory +// owned by the thread but not yet released can be abandoned +// and re-owned by another thread. +// +// 1. windows dynamic library: +// call from DllMain on DLL_THREAD_DETACH +// 2. windows static library: +// use `FlsAlloc` to call a destructor when the thread is done +// 3. unix, pthreads: +// use a pthread key to call a destructor when a pthread is done +// +// In the last two cases we also need to call `mi_process_init` +// to set up the thread local keys. +// -------------------------------------------------------- + +// Set up handlers so `mi_thread_done` is called automatically +static void mi_process_setup_auto_thread_done(void) { + static bool tls_initialized = false; // fine if it races + if (tls_initialized) return; + tls_initialized = true; + _mi_prim_thread_init_auto_done(); + _mi_heap_set_default_direct(&_mi_heap_main); +} + + +bool _mi_is_main_thread(void) { + return (_mi_heap_main.thread_id==0 || _mi_heap_main.thread_id == _mi_thread_id()); +} + +static _Atomic(size_t) thread_count = MI_ATOMIC_VAR_INIT(1); + +size_t _mi_current_thread_count(void) { + return mi_atomic_load_relaxed(&thread_count); +} + +// This is called from the `mi_malloc_generic` +void mi_thread_init(void) mi_attr_noexcept +{ + // ensure our process has started already + mi_process_init(); + + // initialize the thread local default heap + // (this will call `_mi_heap_set_default_direct` and thus set the + // fiber/pthread key to a non-zero value, ensuring `_mi_thread_done` is called) + if (_mi_heap_init()) return; // returns true if already initialized + + _mi_stat_increase(&_mi_stats_main.threads, 1); + mi_atomic_increment_relaxed(&thread_count); + //_mi_verbose_message("thread init: 0x%zx\n", _mi_thread_id()); +} + +void mi_thread_done(void) mi_attr_noexcept { + _mi_thread_done(NULL); +} + +void _mi_thread_done(mi_heap_t* heap) +{ + // calling with NULL implies using the default heap + if (heap == NULL) { + heap = mi_prim_get_default_heap(); + if (heap == NULL) return; + } + + // prevent re-entrancy through heap_done/heap_set_default_direct (issue #699) + if (!mi_heap_is_initialized(heap)) { + return; + } + + // adjust stats + mi_atomic_decrement_relaxed(&thread_count); + _mi_stat_decrease(&_mi_stats_main.threads, 1); + + // check thread-id as on Windows shutdown with FLS the main (exit) thread may call this on thread-local heaps... + if (heap->thread_id != _mi_thread_id()) return; + + // abandon the thread local heap + if (_mi_heap_done(heap)) return; // returns true if already ran +} + +void _mi_heap_set_default_direct(mi_heap_t* heap) { + mi_assert_internal(heap != NULL); + #if defined(MI_TLS_SLOT) + mi_prim_tls_slot_set(MI_TLS_SLOT,heap); + #elif defined(MI_TLS_PTHREAD_SLOT_OFS) + *mi_tls_pthread_heap_slot() = heap; + #elif defined(MI_TLS_PTHREAD) + // we use _mi_heap_default_key + #else + _mi_heap_default = heap; + #endif + + // ensure the default heap is passed to `_mi_thread_done` + // setting to a non-NULL value also ensures `mi_thread_done` is called. + _mi_prim_thread_associate_default_heap(heap); +} + + +// -------------------------------------------------------- +// Run functions on process init/done, and thread init/done +// -------------------------------------------------------- +static void mi_cdecl mi_process_done(void); + +static bool os_preloading = true; // true until this module is initialized +static bool mi_redirected = false; // true if malloc redirects to mi_malloc + +// Returns true if this module has not been initialized; Don't use C runtime routines until it returns false. +bool mi_decl_noinline _mi_preloading(void) { + return os_preloading; +} + +mi_decl_nodiscard bool mi_is_redirected(void) mi_attr_noexcept { + return mi_redirected; +} + +// Communicate with the redirection module on Windows +#if defined(_WIN32) && defined(MI_SHARED_LIB) && !defined(MI_WIN_NOREDIRECT) +#ifdef __cplusplus +extern "C" { +#endif +mi_decl_export void _mi_redirect_entry(DWORD reason) { + // called on redirection; careful as this may be called before DllMain + if (reason == DLL_PROCESS_ATTACH) { + mi_redirected = true; + } + else if (reason == DLL_PROCESS_DETACH) { + mi_redirected = false; + } + else if (reason == DLL_THREAD_DETACH) { + mi_thread_done(); + } +} +__declspec(dllimport) bool mi_cdecl mi_allocator_init(const char** message); +__declspec(dllimport) void mi_cdecl mi_allocator_done(void); +#ifdef __cplusplus +} +#endif +#else +static bool mi_allocator_init(const char** message) { + if (message != NULL) *message = NULL; + return true; +} +static void mi_allocator_done(void) { + // nothing to do +} +#endif + +// Called once by the process loader +static void mi_process_load(void) { + mi_heap_main_init(); + #if defined(__APPLE__) || defined(MI_TLS_RECURSE_GUARD) + volatile mi_heap_t* dummy = _mi_heap_default; // access TLS to allocate it before setting tls_initialized to true; + if (dummy == NULL) return; // use dummy or otherwise the access may get optimized away (issue #697) + #endif + os_preloading = false; + mi_assert_internal(_mi_is_main_thread()); + #if !(defined(_WIN32) && defined(MI_SHARED_LIB)) // use Dll process detach (see below) instead of atexit (issue #521) + atexit(&mi_process_done); + #endif + _mi_options_init(); + mi_process_setup_auto_thread_done(); + mi_process_init(); + if (mi_redirected) _mi_verbose_message("malloc is redirected.\n"); + + // show message from the redirector (if present) + const char* msg = NULL; + mi_allocator_init(&msg); + if (msg != NULL && (mi_option_is_enabled(mi_option_verbose) || mi_option_is_enabled(mi_option_show_errors))) { + _mi_fputs(NULL,NULL,NULL,msg); + } + + // reseed random + _mi_random_reinit_if_weak(&_mi_heap_main.random); +} + +#if defined(_WIN32) && (defined(_M_IX86) || defined(_M_X64)) +#include +mi_decl_cache_align bool _mi_cpu_has_fsrm = false; + +static void mi_detect_cpu_features(void) { + // FSRM for fast rep movsb support (AMD Zen3+ (~2020) or Intel Ice Lake+ (~2017)) + int32_t cpu_info[4]; + __cpuid(cpu_info, 7); + _mi_cpu_has_fsrm = ((cpu_info[3] & (1 << 4)) != 0); // bit 4 of EDX : see +} +#else +static void mi_detect_cpu_features(void) { + // nothing +} +#endif + +// Initialize the process; called by thread_init or the process loader +void mi_process_init(void) mi_attr_noexcept { + // ensure we are called once + static mi_atomic_once_t process_init; + #if _MSC_VER < 1920 + mi_heap_main_init(); // vs2017 can dynamically re-initialize _mi_heap_main + #endif + if (!mi_atomic_once(&process_init)) return; + _mi_process_is_initialized = true; + _mi_verbose_message("process init: 0x%zx\n", _mi_thread_id()); + mi_process_setup_auto_thread_done(); + + mi_detect_cpu_features(); + _mi_os_init(); + mi_heap_main_init(); + #if MI_DEBUG + _mi_verbose_message("debug level : %d\n", MI_DEBUG); + #endif + _mi_verbose_message("secure level: %d\n", MI_SECURE); + _mi_verbose_message("mem tracking: %s\n", MI_TRACK_TOOL); + #if MI_TSAN + _mi_verbose_message("thread santizer enabled\n"); + #endif + mi_thread_init(); + + #if defined(_WIN32) + // On windows, when building as a static lib the FLS cleanup happens to early for the main thread. + // To avoid this, set the FLS value for the main thread to NULL so the fls cleanup + // will not call _mi_thread_done on the (still executing) main thread. See issue #508. + _mi_prim_thread_associate_default_heap(NULL); + #endif + + mi_stats_reset(); // only call stat reset *after* thread init (or the heap tld == NULL) + mi_track_init(); + + if (mi_option_is_enabled(mi_option_reserve_huge_os_pages)) { + size_t pages = mi_option_get_clamp(mi_option_reserve_huge_os_pages, 0, 128*1024); + long reserve_at = mi_option_get(mi_option_reserve_huge_os_pages_at); + if (reserve_at != -1) { + mi_reserve_huge_os_pages_at(pages, reserve_at, pages*500); + } else { + mi_reserve_huge_os_pages_interleave(pages, 0, pages*500); + } + } + if (mi_option_is_enabled(mi_option_reserve_os_memory)) { + long ksize = mi_option_get(mi_option_reserve_os_memory); + if (ksize > 0) { + mi_reserve_os_memory((size_t)ksize*MI_KiB, true /* commit? */, true /* allow large pages? */); + } + } +} + +// Called when the process is done (through `at_exit`) +static void mi_cdecl mi_process_done(void) { + // only shutdown if we were initialized + if (!_mi_process_is_initialized) return; + // ensure we are called once + static bool process_done = false; + if (process_done) return; + process_done = true; + + // release any thread specific resources and ensure _mi_thread_done is called on all but the main thread + _mi_prim_thread_done_auto_done(); + + #ifndef MI_SKIP_COLLECT_ON_EXIT + #if (MI_DEBUG || !defined(MI_SHARED_LIB)) + // free all memory if possible on process exit. This is not needed for a stand-alone process + // but should be done if mimalloc is statically linked into another shared library which + // is repeatedly loaded/unloaded, see issue #281. + mi_collect(true /* force */ ); + #endif + #endif + + // Forcefully release all retained memory; this can be dangerous in general if overriding regular malloc/free + // since after process_done there might still be other code running that calls `free` (like at_exit routines, + // or C-runtime termination code. + if (mi_option_is_enabled(mi_option_destroy_on_exit)) { + mi_collect(true /* force */); + _mi_heap_unsafe_destroy_all(); // forcefully release all memory held by all heaps (of this thread only!) + _mi_arena_unsafe_destroy_all(& _mi_heap_main_get()->tld->stats); + } + + if (mi_option_is_enabled(mi_option_show_stats) || mi_option_is_enabled(mi_option_verbose)) { + mi_stats_print(NULL); + } + mi_allocator_done(); + _mi_verbose_message("process done: 0x%zx\n", _mi_heap_main.thread_id); + os_preloading = true; // don't call the C runtime anymore +} + + + +#if defined(_WIN32) && defined(MI_SHARED_LIB) + // Windows DLL: easy to hook into process_init and thread_done + __declspec(dllexport) BOOL WINAPI DllMain(HINSTANCE inst, DWORD reason, LPVOID reserved) { + MI_UNUSED(reserved); + MI_UNUSED(inst); + if (reason==DLL_PROCESS_ATTACH) { + mi_process_load(); + } + else if (reason==DLL_PROCESS_DETACH) { + mi_process_done(); + } + else if (reason==DLL_THREAD_DETACH) { + if (!mi_is_redirected()) { + mi_thread_done(); + } + } + return TRUE; + } + +#elif defined(_MSC_VER) + // MSVC: use data section magic for static libraries + // See + static int _mi_process_init(void) { + mi_process_load(); + return 0; + } + typedef int(*_mi_crt_callback_t)(void); + #if defined(_M_X64) || defined(_M_ARM64) + __pragma(comment(linker, "/include:" "_mi_msvc_initu")) + #pragma section(".CRT$XIU", long, read) + #else + __pragma(comment(linker, "/include:" "__mi_msvc_initu")) + #endif + #pragma data_seg(".CRT$XIU") + mi_decl_externc _mi_crt_callback_t _mi_msvc_initu[] = { &_mi_process_init }; + #pragma data_seg() + +#elif defined(__cplusplus) + // C++: use static initialization to detect process start + static bool _mi_process_init(void) { + mi_process_load(); + return (_mi_heap_main.thread_id != 0); + } + static bool mi_initialized = _mi_process_init(); + +#elif defined(__GNUC__) || defined(__clang__) + // GCC,Clang: use the constructor attribute + static void __attribute__((constructor)) _mi_process_init(void) { + mi_process_load(); + } + +#else +#pragma message("define a way to call mi_process_load on your platform") +#endif diff --git a/Objects/mimalloc/options.c b/Objects/mimalloc/options.c new file mode 100644 index 00000000000000..345b560e3e7f4c --- /dev/null +++ b/Objects/mimalloc/options.c @@ -0,0 +1,571 @@ +/* ---------------------------------------------------------------------------- +Copyright (c) 2018-2021, Microsoft Research, Daan Leijen +This is free software; you can redistribute it and/or modify it under the +terms of the MIT license. A copy of the license can be found in the file +"LICENSE" at the root of this distribution. +-----------------------------------------------------------------------------*/ +#include "mimalloc.h" +#include "mimalloc/internal.h" +#include "mimalloc/atomic.h" +#include "mimalloc/prim.h" // mi_prim_out_stderr + +#include // FILE +#include // abort +#include + + +static long mi_max_error_count = 16; // stop outputting errors after this (use < 0 for no limit) +static long mi_max_warning_count = 16; // stop outputting warnings after this (use < 0 for no limit) + +static void mi_add_stderr_output(void); + +int mi_version(void) mi_attr_noexcept { + return MI_MALLOC_VERSION; +} + + +// -------------------------------------------------------- +// Options +// These can be accessed by multiple threads and may be +// concurrently initialized, but an initializing data race +// is ok since they resolve to the same value. +// -------------------------------------------------------- +typedef enum mi_init_e { + UNINIT, // not yet initialized + DEFAULTED, // not found in the environment, use default value + INITIALIZED // found in environment or set explicitly +} mi_init_t; + +typedef struct mi_option_desc_s { + long value; // the value + mi_init_t init; // is it initialized yet? (from the environment) + mi_option_t option; // for debugging: the option index should match the option + const char* name; // option name without `mimalloc_` prefix + const char* legacy_name; // potential legacy option name +} mi_option_desc_t; + +#define MI_OPTION(opt) mi_option_##opt, #opt, NULL +#define MI_OPTION_LEGACY(opt,legacy) mi_option_##opt, #opt, #legacy + +static mi_option_desc_t options[_mi_option_last] = +{ + // stable options + #if MI_DEBUG || defined(MI_SHOW_ERRORS) + { 1, UNINIT, MI_OPTION(show_errors) }, + #else + { 0, UNINIT, MI_OPTION(show_errors) }, + #endif + { 0, UNINIT, MI_OPTION(show_stats) }, + { 0, UNINIT, MI_OPTION(verbose) }, + + // the following options are experimental and not all combinations make sense. + { 1, UNINIT, MI_OPTION(eager_commit) }, // commit per segment directly (4MiB) (but see also `eager_commit_delay`) + { 2, UNINIT, MI_OPTION_LEGACY(arena_eager_commit,eager_region_commit) }, // eager commit arena's? 2 is used to enable this only on an OS that has overcommit (i.e. linux) + { 1, UNINIT, MI_OPTION_LEGACY(purge_decommits,reset_decommits) }, // purge decommits memory (instead of reset) (note: on linux this uses MADV_DONTNEED for decommit) + { 0, UNINIT, MI_OPTION_LEGACY(allow_large_os_pages,large_os_pages) }, // use large OS pages, use only with eager commit to prevent fragmentation of VMA's + { 0, UNINIT, MI_OPTION(reserve_huge_os_pages) }, // per 1GiB huge pages + {-1, UNINIT, MI_OPTION(reserve_huge_os_pages_at) }, // reserve huge pages at node N + { 0, UNINIT, MI_OPTION(reserve_os_memory) }, + { 0, UNINIT, MI_OPTION(deprecated_segment_cache) }, // cache N segments per thread + { 0, UNINIT, MI_OPTION(deprecated_page_reset) }, // reset page memory on free + { 0, UNINIT, MI_OPTION_LEGACY(abandoned_page_purge,abandoned_page_reset) }, // reset free page memory when a thread terminates + { 0, UNINIT, MI_OPTION(deprecated_segment_reset) }, // reset segment memory on free (needs eager commit) +#if defined(__NetBSD__) + { 0, UNINIT, MI_OPTION(eager_commit_delay) }, // the first N segments per thread are not eagerly committed +#else + { 1, UNINIT, MI_OPTION(eager_commit_delay) }, // the first N segments per thread are not eagerly committed (but per page in the segment on demand) +#endif + { 10, UNINIT, MI_OPTION_LEGACY(purge_delay,reset_delay) }, // purge delay in milli-seconds + { 0, UNINIT, MI_OPTION(use_numa_nodes) }, // 0 = use available numa nodes, otherwise use at most N nodes. + { 0, UNINIT, MI_OPTION(limit_os_alloc) }, // 1 = do not use OS memory for allocation (but only reserved arenas) + { 100, UNINIT, MI_OPTION(os_tag) }, // only apple specific for now but might serve more or less related purpose + { 16, UNINIT, MI_OPTION(max_errors) }, // maximum errors that are output + { 16, UNINIT, MI_OPTION(max_warnings) }, // maximum warnings that are output + { 8, UNINIT, MI_OPTION(max_segment_reclaim)}, // max. number of segment reclaims from the abandoned segments per try. + { 0, UNINIT, MI_OPTION(destroy_on_exit)}, // release all OS memory on process exit; careful with dangling pointer or after-exit frees! + #if (MI_INTPTR_SIZE>4) + { 1024L * 1024L, UNINIT, MI_OPTION(arena_reserve) }, // reserve memory N KiB at a time + #else + { 128L * 1024L, UNINIT, MI_OPTION(arena_reserve) }, + #endif + { 10, UNINIT, MI_OPTION(arena_purge_mult) }, // purge delay multiplier for arena's + { 1, UNINIT, MI_OPTION_LEGACY(purge_extend_delay, decommit_extend_delay) }, +}; + +static void mi_option_init(mi_option_desc_t* desc); + +void _mi_options_init(void) { + // called on process load; should not be called before the CRT is initialized! + // (e.g. do not call this from process_init as that may run before CRT initialization) + mi_add_stderr_output(); // now it safe to use stderr for output + for(int i = 0; i < _mi_option_last; i++ ) { + mi_option_t option = (mi_option_t)i; + long l = mi_option_get(option); MI_UNUSED(l); // initialize + // if (option != mi_option_verbose) + { + mi_option_desc_t* desc = &options[option]; + _mi_verbose_message("option '%s': %ld\n", desc->name, desc->value); + } + } + mi_max_error_count = mi_option_get(mi_option_max_errors); + mi_max_warning_count = mi_option_get(mi_option_max_warnings); +} + +mi_decl_nodiscard long mi_option_get(mi_option_t option) { + mi_assert(option >= 0 && option < _mi_option_last); + if (option < 0 || option >= _mi_option_last) return 0; + mi_option_desc_t* desc = &options[option]; + mi_assert(desc->option == option); // index should match the option + if mi_unlikely(desc->init == UNINIT) { + mi_option_init(desc); + } + return desc->value; +} + +mi_decl_nodiscard long mi_option_get_clamp(mi_option_t option, long min, long max) { + long x = mi_option_get(option); + return (x < min ? min : (x > max ? max : x)); +} + +mi_decl_nodiscard size_t mi_option_get_size(mi_option_t option) { + mi_assert_internal(option == mi_option_reserve_os_memory || option == mi_option_arena_reserve); + long x = mi_option_get(option); + return (x < 0 ? 0 : (size_t)x * MI_KiB); +} + +void mi_option_set(mi_option_t option, long value) { + mi_assert(option >= 0 && option < _mi_option_last); + if (option < 0 || option >= _mi_option_last) return; + mi_option_desc_t* desc = &options[option]; + mi_assert(desc->option == option); // index should match the option + desc->value = value; + desc->init = INITIALIZED; +} + +void mi_option_set_default(mi_option_t option, long value) { + mi_assert(option >= 0 && option < _mi_option_last); + if (option < 0 || option >= _mi_option_last) return; + mi_option_desc_t* desc = &options[option]; + if (desc->init != INITIALIZED) { + desc->value = value; + } +} + +mi_decl_nodiscard bool mi_option_is_enabled(mi_option_t option) { + return (mi_option_get(option) != 0); +} + +void mi_option_set_enabled(mi_option_t option, bool enable) { + mi_option_set(option, (enable ? 1 : 0)); +} + +void mi_option_set_enabled_default(mi_option_t option, bool enable) { + mi_option_set_default(option, (enable ? 1 : 0)); +} + +void mi_option_enable(mi_option_t option) { + mi_option_set_enabled(option,true); +} + +void mi_option_disable(mi_option_t option) { + mi_option_set_enabled(option,false); +} + +static void mi_cdecl mi_out_stderr(const char* msg, void* arg) { + MI_UNUSED(arg); + if (msg != NULL && msg[0] != 0) { + _mi_prim_out_stderr(msg); + } +} + +// Since an output function can be registered earliest in the `main` +// function we also buffer output that happens earlier. When +// an output function is registered it is called immediately with +// the output up to that point. +#ifndef MI_MAX_DELAY_OUTPUT +#define MI_MAX_DELAY_OUTPUT ((size_t)(32*1024)) +#endif +static char out_buf[MI_MAX_DELAY_OUTPUT+1]; +static _Atomic(size_t) out_len; + +static void mi_cdecl mi_out_buf(const char* msg, void* arg) { + MI_UNUSED(arg); + if (msg==NULL) return; + if (mi_atomic_load_relaxed(&out_len)>=MI_MAX_DELAY_OUTPUT) return; + size_t n = _mi_strlen(msg); + if (n==0) return; + // claim space + size_t start = mi_atomic_add_acq_rel(&out_len, n); + if (start >= MI_MAX_DELAY_OUTPUT) return; + // check bound + if (start+n >= MI_MAX_DELAY_OUTPUT) { + n = MI_MAX_DELAY_OUTPUT-start-1; + } + _mi_memcpy(&out_buf[start], msg, n); +} + +static void mi_out_buf_flush(mi_output_fun* out, bool no_more_buf, void* arg) { + if (out==NULL) return; + // claim (if `no_more_buf == true`, no more output will be added after this point) + size_t count = mi_atomic_add_acq_rel(&out_len, (no_more_buf ? MI_MAX_DELAY_OUTPUT : 1)); + // and output the current contents + if (count>MI_MAX_DELAY_OUTPUT) count = MI_MAX_DELAY_OUTPUT; + out_buf[count] = 0; + out(out_buf,arg); + if (!no_more_buf) { + out_buf[count] = '\n'; // if continue with the buffer, insert a newline + } +} + + +// Once this module is loaded, switch to this routine +// which outputs to stderr and the delayed output buffer. +static void mi_cdecl mi_out_buf_stderr(const char* msg, void* arg) { + mi_out_stderr(msg,arg); + mi_out_buf(msg,arg); +} + + + +// -------------------------------------------------------- +// Default output handler +// -------------------------------------------------------- + +// Should be atomic but gives errors on many platforms as generally we cannot cast a function pointer to a uintptr_t. +// For now, don't register output from multiple threads. +static mi_output_fun* volatile mi_out_default; // = NULL +static _Atomic(void*) mi_out_arg; // = NULL + +static mi_output_fun* mi_out_get_default(void** parg) { + if (parg != NULL) { *parg = mi_atomic_load_ptr_acquire(void,&mi_out_arg); } + mi_output_fun* out = mi_out_default; + return (out == NULL ? &mi_out_buf : out); +} + +void mi_register_output(mi_output_fun* out, void* arg) mi_attr_noexcept { + mi_out_default = (out == NULL ? &mi_out_stderr : out); // stop using the delayed output buffer + mi_atomic_store_ptr_release(void,&mi_out_arg, arg); + if (out!=NULL) mi_out_buf_flush(out,true,arg); // output all the delayed output now +} + +// add stderr to the delayed output after the module is loaded +static void mi_add_stderr_output(void) { + mi_assert_internal(mi_out_default == NULL); + mi_out_buf_flush(&mi_out_stderr, false, NULL); // flush current contents to stderr + mi_out_default = &mi_out_buf_stderr; // and add stderr to the delayed output +} + +// -------------------------------------------------------- +// Messages, all end up calling `_mi_fputs`. +// -------------------------------------------------------- +static _Atomic(size_t) error_count; // = 0; // when >= max_error_count stop emitting errors +static _Atomic(size_t) warning_count; // = 0; // when >= max_warning_count stop emitting warnings + +// When overriding malloc, we may recurse into mi_vfprintf if an allocation +// inside the C runtime causes another message. +// In some cases (like on macOS) the loader already allocates which +// calls into mimalloc; if we then access thread locals (like `recurse`) +// this may crash as the access may call _tlv_bootstrap that tries to +// (recursively) invoke malloc again to allocate space for the thread local +// variables on demand. This is why we use a _mi_preloading test on such +// platforms. However, C code generator may move the initial thread local address +// load before the `if` and we therefore split it out in a separate funcion. +static mi_decl_thread bool recurse = false; + +static mi_decl_noinline bool mi_recurse_enter_prim(void) { + if (recurse) return false; + recurse = true; + return true; +} + +static mi_decl_noinline void mi_recurse_exit_prim(void) { + recurse = false; +} + +static bool mi_recurse_enter(void) { + #if defined(__APPLE__) || defined(MI_TLS_RECURSE_GUARD) + if (_mi_preloading()) return false; + #endif + return mi_recurse_enter_prim(); +} + +static void mi_recurse_exit(void) { + #if defined(__APPLE__) || defined(MI_TLS_RECURSE_GUARD) + if (_mi_preloading()) return; + #endif + mi_recurse_exit_prim(); +} + +void _mi_fputs(mi_output_fun* out, void* arg, const char* prefix, const char* message) { + if (out==NULL || (void*)out==(void*)stdout || (void*)out==(void*)stderr) { // TODO: use mi_out_stderr for stderr? + if (!mi_recurse_enter()) return; + out = mi_out_get_default(&arg); + if (prefix != NULL) out(prefix, arg); + out(message, arg); + mi_recurse_exit(); + } + else { + if (prefix != NULL) out(prefix, arg); + out(message, arg); + } +} + +// Define our own limited `fprintf` that avoids memory allocation. +// We do this using `snprintf` with a limited buffer. +static void mi_vfprintf( mi_output_fun* out, void* arg, const char* prefix, const char* fmt, va_list args ) { + char buf[512]; + if (fmt==NULL) return; + if (!mi_recurse_enter()) return; + vsnprintf(buf,sizeof(buf)-1,fmt,args); + mi_recurse_exit(); + _mi_fputs(out,arg,prefix,buf); +} + +void _mi_fprintf( mi_output_fun* out, void* arg, const char* fmt, ... ) { + va_list args; + va_start(args,fmt); + mi_vfprintf(out,arg,NULL,fmt,args); + va_end(args); +} + +static void mi_vfprintf_thread(mi_output_fun* out, void* arg, const char* prefix, const char* fmt, va_list args) { + if (prefix != NULL && _mi_strnlen(prefix,33) <= 32 && !_mi_is_main_thread()) { + char tprefix[64]; + snprintf(tprefix, sizeof(tprefix), "%sthread 0x%llx: ", prefix, (unsigned long long)_mi_thread_id()); + mi_vfprintf(out, arg, tprefix, fmt, args); + } + else { + mi_vfprintf(out, arg, prefix, fmt, args); + } +} + +void _mi_trace_message(const char* fmt, ...) { + if (mi_option_get(mi_option_verbose) <= 1) return; // only with verbose level 2 or higher + va_list args; + va_start(args, fmt); + mi_vfprintf_thread(NULL, NULL, "mimalloc: ", fmt, args); + va_end(args); +} + +void _mi_verbose_message(const char* fmt, ...) { + if (!mi_option_is_enabled(mi_option_verbose)) return; + va_list args; + va_start(args,fmt); + mi_vfprintf(NULL, NULL, "mimalloc: ", fmt, args); + va_end(args); +} + +static void mi_show_error_message(const char* fmt, va_list args) { + if (!mi_option_is_enabled(mi_option_verbose)) { + if (!mi_option_is_enabled(mi_option_show_errors)) return; + if (mi_max_error_count >= 0 && (long)mi_atomic_increment_acq_rel(&error_count) > mi_max_error_count) return; + } + mi_vfprintf_thread(NULL, NULL, "mimalloc: error: ", fmt, args); +} + +void _mi_warning_message(const char* fmt, ...) { + if (!mi_option_is_enabled(mi_option_verbose)) { + if (!mi_option_is_enabled(mi_option_show_errors)) return; + if (mi_max_warning_count >= 0 && (long)mi_atomic_increment_acq_rel(&warning_count) > mi_max_warning_count) return; + } + va_list args; + va_start(args,fmt); + mi_vfprintf_thread(NULL, NULL, "mimalloc: warning: ", fmt, args); + va_end(args); +} + + +#if MI_DEBUG +void _mi_assert_fail(const char* assertion, const char* fname, unsigned line, const char* func ) { + _mi_fprintf(NULL, NULL, "mimalloc: assertion failed: at \"%s\":%u, %s\n assertion: \"%s\"\n", fname, line, (func==NULL?"":func), assertion); + abort(); +} +#endif + +// -------------------------------------------------------- +// Errors +// -------------------------------------------------------- + +static mi_error_fun* volatile mi_error_handler; // = NULL +static _Atomic(void*) mi_error_arg; // = NULL + +static void mi_error_default(int err) { + MI_UNUSED(err); +#if (MI_DEBUG>0) + if (err==EFAULT) { + #ifdef _MSC_VER + __debugbreak(); + #endif + abort(); + } +#endif +#if (MI_SECURE>0) + if (err==EFAULT) { // abort on serious errors in secure mode (corrupted meta-data) + abort(); + } +#endif +#if defined(MI_XMALLOC) + if (err==ENOMEM || err==EOVERFLOW) { // abort on memory allocation fails in xmalloc mode + abort(); + } +#endif +} + +void mi_register_error(mi_error_fun* fun, void* arg) { + mi_error_handler = fun; // can be NULL + mi_atomic_store_ptr_release(void,&mi_error_arg, arg); +} + +void _mi_error_message(int err, const char* fmt, ...) { + // show detailed error message + va_list args; + va_start(args, fmt); + mi_show_error_message(fmt, args); + va_end(args); + // and call the error handler which may abort (or return normally) + if (mi_error_handler != NULL) { + mi_error_handler(err, mi_atomic_load_ptr_acquire(void,&mi_error_arg)); + } + else { + mi_error_default(err); + } +} + +// -------------------------------------------------------- +// Initialize options by checking the environment +// -------------------------------------------------------- +char _mi_toupper(char c) { + if (c >= 'a' && c <= 'z') return (c - 'a' + 'A'); + else return c; +} + +int _mi_strnicmp(const char* s, const char* t, size_t n) { + if (n == 0) return 0; + for (; *s != 0 && *t != 0 && n > 0; s++, t++, n--) { + if (_mi_toupper(*s) != _mi_toupper(*t)) break; + } + return (n == 0 ? 0 : *s - *t); +} + +void _mi_strlcpy(char* dest, const char* src, size_t dest_size) { + if (dest==NULL || src==NULL || dest_size == 0) return; + // copy until end of src, or when dest is (almost) full + while (*src != 0 && dest_size > 1) { + *dest++ = *src++; + dest_size--; + } + // always zero terminate + *dest = 0; +} + +void _mi_strlcat(char* dest, const char* src, size_t dest_size) { + if (dest==NULL || src==NULL || dest_size == 0) return; + // find end of string in the dest buffer + while (*dest != 0 && dest_size > 1) { + dest++; + dest_size--; + } + // and catenate + _mi_strlcpy(dest, src, dest_size); +} + +size_t _mi_strlen(const char* s) { + if (s==NULL) return 0; + size_t len = 0; + while(s[len] != 0) { len++; } + return len; +} + +size_t _mi_strnlen(const char* s, size_t max_len) { + if (s==NULL) return 0; + size_t len = 0; + while(s[len] != 0 && len < max_len) { len++; } + return len; +} + +#ifdef MI_NO_GETENV +static bool mi_getenv(const char* name, char* result, size_t result_size) { + MI_UNUSED(name); + MI_UNUSED(result); + MI_UNUSED(result_size); + return false; +} +#else +static bool mi_getenv(const char* name, char* result, size_t result_size) { + if (name==NULL || result == NULL || result_size < 64) return false; + return _mi_prim_getenv(name,result,result_size); +} +#endif + +// TODO: implement ourselves to reduce dependencies on the C runtime +#include // strtol +#include // strstr + + +static void mi_option_init(mi_option_desc_t* desc) { + // Read option value from the environment + char s[64 + 1]; + char buf[64+1]; + _mi_strlcpy(buf, "mimalloc_", sizeof(buf)); + _mi_strlcat(buf, desc->name, sizeof(buf)); + bool found = mi_getenv(buf, s, sizeof(s)); + if (!found && desc->legacy_name != NULL) { + _mi_strlcpy(buf, "mimalloc_", sizeof(buf)); + _mi_strlcat(buf, desc->legacy_name, sizeof(buf)); + found = mi_getenv(buf, s, sizeof(s)); + if (found) { + _mi_warning_message("environment option \"mimalloc_%s\" is deprecated -- use \"mimalloc_%s\" instead.\n", desc->legacy_name, desc->name); + } + } + + if (found) { + size_t len = _mi_strnlen(s, sizeof(buf) - 1); + for (size_t i = 0; i < len; i++) { + buf[i] = _mi_toupper(s[i]); + } + buf[len] = 0; + if (buf[0] == 0 || strstr("1;TRUE;YES;ON", buf) != NULL) { + desc->value = 1; + desc->init = INITIALIZED; + } + else if (strstr("0;FALSE;NO;OFF", buf) != NULL) { + desc->value = 0; + desc->init = INITIALIZED; + } + else { + char* end = buf; + long value = strtol(buf, &end, 10); + if (desc->option == mi_option_reserve_os_memory || desc->option == mi_option_arena_reserve) { + // this option is interpreted in KiB to prevent overflow of `long` + if (*end == 'K') { end++; } + else if (*end == 'M') { value *= MI_KiB; end++; } + else if (*end == 'G') { value *= MI_MiB; end++; } + else { value = (value + MI_KiB - 1) / MI_KiB; } + if (end[0] == 'I' && end[1] == 'B') { end += 2; } + else if (*end == 'B') { end++; } + } + if (*end == 0) { + desc->value = value; + desc->init = INITIALIZED; + } + else { + // set `init` first to avoid recursion through _mi_warning_message on mimalloc_verbose. + desc->init = DEFAULTED; + if (desc->option == mi_option_verbose && desc->value == 0) { + // if the 'mimalloc_verbose' env var has a bogus value we'd never know + // (since the value defaults to 'off') so in that case briefly enable verbose + desc->value = 1; + _mi_warning_message("environment option mimalloc_%s has an invalid value.\n", desc->name); + desc->value = 0; + } + else { + _mi_warning_message("environment option mimalloc_%s has an invalid value.\n", desc->name); + } + } + } + mi_assert_internal(desc->init != UNINIT); + } + else if (!_mi_preloading()) { + desc->init = DEFAULTED; + } +} diff --git a/Objects/mimalloc/os.c b/Objects/mimalloc/os.c new file mode 100644 index 00000000000000..f3bc7184c41c5b --- /dev/null +++ b/Objects/mimalloc/os.c @@ -0,0 +1,690 @@ +/* ---------------------------------------------------------------------------- +Copyright (c) 2018-2023, Microsoft Research, Daan Leijen +This is free software; you can redistribute it and/or modify it under the +terms of the MIT license. A copy of the license can be found in the file +"LICENSE" at the root of this distribution. +-----------------------------------------------------------------------------*/ +#include "mimalloc.h" +#include "mimalloc/internal.h" +#include "mimalloc/atomic.h" +#include "mimalloc/prim.h" + + +/* ----------------------------------------------------------- + Initialization. + On windows initializes support for aligned allocation and + large OS pages (if MIMALLOC_LARGE_OS_PAGES is true). +----------------------------------------------------------- */ + +static mi_os_mem_config_t mi_os_mem_config = { + 4096, // page size + 0, // large page size (usually 2MiB) + 4096, // allocation granularity + true, // has overcommit? (if true we use MAP_NORESERVE on mmap systems) + false, // must free whole? (on mmap systems we can free anywhere in a mapped range, but on Windows we must free the entire span) + true // has virtual reserve? (if true we can reserve virtual address space without using commit or physical memory) +}; + +bool _mi_os_has_overcommit(void) { + return mi_os_mem_config.has_overcommit; +} + +bool _mi_os_has_virtual_reserve(void) { + return mi_os_mem_config.has_virtual_reserve; +} + + +// OS (small) page size +size_t _mi_os_page_size(void) { + return mi_os_mem_config.page_size; +} + +// if large OS pages are supported (2 or 4MiB), then return the size, otherwise return the small page size (4KiB) +size_t _mi_os_large_page_size(void) { + return (mi_os_mem_config.large_page_size != 0 ? mi_os_mem_config.large_page_size : _mi_os_page_size()); +} + +bool _mi_os_use_large_page(size_t size, size_t alignment) { + // if we have access, check the size and alignment requirements + if (mi_os_mem_config.large_page_size == 0 || !mi_option_is_enabled(mi_option_allow_large_os_pages)) return false; + return ((size % mi_os_mem_config.large_page_size) == 0 && (alignment % mi_os_mem_config.large_page_size) == 0); +} + +// round to a good OS allocation size (bounded by max 12.5% waste) +size_t _mi_os_good_alloc_size(size_t size) { + size_t align_size; + if (size < 512*MI_KiB) align_size = _mi_os_page_size(); + else if (size < 2*MI_MiB) align_size = 64*MI_KiB; + else if (size < 8*MI_MiB) align_size = 256*MI_KiB; + else if (size < 32*MI_MiB) align_size = 1*MI_MiB; + else align_size = 4*MI_MiB; + if mi_unlikely(size >= (SIZE_MAX - align_size)) return size; // possible overflow? + return _mi_align_up(size, align_size); +} + +void _mi_os_init(void) { + _mi_prim_mem_init(&mi_os_mem_config); +} + + +/* ----------------------------------------------------------- + Util +-------------------------------------------------------------- */ +bool _mi_os_decommit(void* addr, size_t size, mi_stats_t* stats); +bool _mi_os_commit(void* addr, size_t size, bool* is_zero, mi_stats_t* tld_stats); + +static void* mi_align_up_ptr(void* p, size_t alignment) { + return (void*)_mi_align_up((uintptr_t)p, alignment); +} + +static void* mi_align_down_ptr(void* p, size_t alignment) { + return (void*)_mi_align_down((uintptr_t)p, alignment); +} + + +/* ----------------------------------------------------------- + aligned hinting +-------------------------------------------------------------- */ + +// On 64-bit systems, we can do efficient aligned allocation by using +// the 2TiB to 30TiB area to allocate those. +#if (MI_INTPTR_SIZE >= 8) +static mi_decl_cache_align _Atomic(uintptr_t)aligned_base; + +// Return a MI_SEGMENT_SIZE aligned address that is probably available. +// If this returns NULL, the OS will determine the address but on some OS's that may not be +// properly aligned which can be more costly as it needs to be adjusted afterwards. +// For a size > 1GiB this always returns NULL in order to guarantee good ASLR randomization; +// (otherwise an initial large allocation of say 2TiB has a 50% chance to include (known) addresses +// in the middle of the 2TiB - 6TiB address range (see issue #372)) + +#define MI_HINT_BASE ((uintptr_t)2 << 40) // 2TiB start +#define MI_HINT_AREA ((uintptr_t)4 << 40) // upto 6TiB (since before win8 there is "only" 8TiB available to processes) +#define MI_HINT_MAX ((uintptr_t)30 << 40) // wrap after 30TiB (area after 32TiB is used for huge OS pages) + +void* _mi_os_get_aligned_hint(size_t try_alignment, size_t size) +{ + if (try_alignment <= 1 || try_alignment > MI_SEGMENT_SIZE) return NULL; + size = _mi_align_up(size, MI_SEGMENT_SIZE); + if (size > 1*MI_GiB) return NULL; // guarantee the chance of fixed valid address is at most 1/(MI_HINT_AREA / 1<<30) = 1/4096. + #if (MI_SECURE>0) + size += MI_SEGMENT_SIZE; // put in `MI_SEGMENT_SIZE` virtual gaps between hinted blocks; this splits VLA's but increases guarded areas. + #endif + + uintptr_t hint = mi_atomic_add_acq_rel(&aligned_base, size); + if (hint == 0 || hint > MI_HINT_MAX) { // wrap or initialize + uintptr_t init = MI_HINT_BASE; + #if (MI_SECURE>0 || MI_DEBUG==0) // security: randomize start of aligned allocations unless in debug mode + uintptr_t r = _mi_heap_random_next(mi_prim_get_default_heap()); + init = init + ((MI_SEGMENT_SIZE * ((r>>17) & 0xFFFFF)) % MI_HINT_AREA); // (randomly 20 bits)*4MiB == 0 to 4TiB + #endif + uintptr_t expected = hint + size; + mi_atomic_cas_strong_acq_rel(&aligned_base, &expected, init); + hint = mi_atomic_add_acq_rel(&aligned_base, size); // this may still give 0 or > MI_HINT_MAX but that is ok, it is a hint after all + } + if (hint%try_alignment != 0) return NULL; + return (void*)hint; +} +#else +void* _mi_os_get_aligned_hint(size_t try_alignment, size_t size) { + MI_UNUSED(try_alignment); MI_UNUSED(size); + return NULL; +} +#endif + + +/* ----------------------------------------------------------- + Free memory +-------------------------------------------------------------- */ + +static void mi_os_free_huge_os_pages(void* p, size_t size, mi_stats_t* stats); + +static void mi_os_prim_free(void* addr, size_t size, bool still_committed, mi_stats_t* tld_stats) { + MI_UNUSED(tld_stats); + mi_assert_internal((size % _mi_os_page_size()) == 0); + if (addr == NULL || size == 0) return; // || _mi_os_is_huge_reserved(addr) + int err = _mi_prim_free(addr, size); + if (err != 0) { + _mi_warning_message("unable to free OS memory (error: %d (0x%x), size: 0x%zx bytes, address: %p)\n", err, err, size, addr); + } + mi_stats_t* stats = &_mi_stats_main; + if (still_committed) { _mi_stat_decrease(&stats->committed, size); } + _mi_stat_decrease(&stats->reserved, size); +} + +void _mi_os_free_ex(void* addr, size_t size, bool still_committed, mi_memid_t memid, mi_stats_t* tld_stats) { + if (mi_memkind_is_os(memid.memkind)) { + size_t csize = _mi_os_good_alloc_size(size); + void* base = addr; + // different base? (due to alignment) + if (memid.mem.os.base != NULL) { + mi_assert(memid.mem.os.base <= addr); + mi_assert((uint8_t*)memid.mem.os.base + memid.mem.os.alignment >= (uint8_t*)addr); + base = memid.mem.os.base; + csize += ((uint8_t*)addr - (uint8_t*)memid.mem.os.base); + } + // free it + if (memid.memkind == MI_MEM_OS_HUGE) { + mi_assert(memid.is_pinned); + mi_os_free_huge_os_pages(base, csize, tld_stats); + } + else { + mi_os_prim_free(base, csize, still_committed, tld_stats); + } + } + else { + // nothing to do + mi_assert(memid.memkind < MI_MEM_OS); + } +} + +void _mi_os_free(void* p, size_t size, mi_memid_t memid, mi_stats_t* tld_stats) { + _mi_os_free_ex(p, size, true, memid, tld_stats); +} + + +/* ----------------------------------------------------------- + Primitive allocation from the OS. +-------------------------------------------------------------- */ + +// Note: the `try_alignment` is just a hint and the returned pointer is not guaranteed to be aligned. +static void* mi_os_prim_alloc(size_t size, size_t try_alignment, bool commit, bool allow_large, bool* is_large, bool* is_zero, mi_stats_t* stats) { + mi_assert_internal(size > 0 && (size % _mi_os_page_size()) == 0); + mi_assert_internal(is_zero != NULL); + mi_assert_internal(is_large != NULL); + if (size == 0) return NULL; + if (!commit) { allow_large = false; } + if (try_alignment == 0) { try_alignment = 1; } // avoid 0 to ensure there will be no divide by zero when aligning + + *is_zero = false; + void* p = NULL; + int err = _mi_prim_alloc(size, try_alignment, commit, allow_large, is_large, is_zero, &p); + if (err != 0) { + _mi_warning_message("unable to allocate OS memory (error: %d (0x%x), size: 0x%zx bytes, align: 0x%zx, commit: %d, allow large: %d)\n", err, err, size, try_alignment, commit, allow_large); + } + mi_stat_counter_increase(stats->mmap_calls, 1); + if (p != NULL) { + _mi_stat_increase(&stats->reserved, size); + if (commit) { + _mi_stat_increase(&stats->committed, size); + // seems needed for asan (or `mimalloc-test-api` fails) + #ifdef MI_TRACK_ASAN + if (*is_zero) { mi_track_mem_defined(p,size); } + else { mi_track_mem_undefined(p,size); } + #endif + } + } + return p; +} + + +// Primitive aligned allocation from the OS. +// This function guarantees the allocated memory is aligned. +static void* mi_os_prim_alloc_aligned(size_t size, size_t alignment, bool commit, bool allow_large, bool* is_large, bool* is_zero, void** base, mi_stats_t* stats) { + mi_assert_internal(alignment >= _mi_os_page_size() && ((alignment & (alignment - 1)) == 0)); + mi_assert_internal(size > 0 && (size % _mi_os_page_size()) == 0); + mi_assert_internal(is_large != NULL); + mi_assert_internal(is_zero != NULL); + mi_assert_internal(base != NULL); + if (!commit) allow_large = false; + if (!(alignment >= _mi_os_page_size() && ((alignment & (alignment - 1)) == 0))) return NULL; + size = _mi_align_up(size, _mi_os_page_size()); + + // try first with a hint (this will be aligned directly on Win 10+ or BSD) + void* p = mi_os_prim_alloc(size, alignment, commit, allow_large, is_large, is_zero, stats); + if (p == NULL) return NULL; + + // aligned already? + if (((uintptr_t)p % alignment) == 0) { + *base = p; + } + else { + // if not aligned, free it, overallocate, and unmap around it + // NOTE(sgross): this warning causes issues in Python tests + // _mi_warning_message("unable to allocate aligned OS memory directly, fall back to over-allocation (size: 0x%zx bytes, address: %p, alignment: 0x%zx, commit: %d)\n", size, p, alignment, commit); + mi_os_prim_free(p, size, commit, stats); + if (size >= (SIZE_MAX - alignment)) return NULL; // overflow + const size_t over_size = size + alignment; + + if (mi_os_mem_config.must_free_whole) { // win32 virtualAlloc cannot free parts of an allocate block + // over-allocate uncommitted (virtual) memory + p = mi_os_prim_alloc(over_size, 1 /*alignment*/, false /* commit? */, false /* allow_large */, is_large, is_zero, stats); + if (p == NULL) return NULL; + + // set p to the aligned part in the full region + // note: this is dangerous on Windows as VirtualFree needs the actual base pointer + // this is handled though by having the `base` field in the memid's + *base = p; // remember the base + p = mi_align_up_ptr(p, alignment); + + // explicitly commit only the aligned part + if (commit) { + _mi_os_commit(p, size, NULL, stats); + } + } + else { // mmap can free inside an allocation + // overallocate... + p = mi_os_prim_alloc(over_size, 1, commit, false, is_large, is_zero, stats); + if (p == NULL) return NULL; + + // and selectively unmap parts around the over-allocated area. (noop on sbrk) + void* aligned_p = mi_align_up_ptr(p, alignment); + size_t pre_size = (uint8_t*)aligned_p - (uint8_t*)p; + size_t mid_size = _mi_align_up(size, _mi_os_page_size()); + size_t post_size = over_size - pre_size - mid_size; + mi_assert_internal(pre_size < over_size&& post_size < over_size&& mid_size >= size); + if (pre_size > 0) { mi_os_prim_free(p, pre_size, commit, stats); } + if (post_size > 0) { mi_os_prim_free((uint8_t*)aligned_p + mid_size, post_size, commit, stats); } + // we can return the aligned pointer on `mmap` (and sbrk) systems + p = aligned_p; + *base = aligned_p; // since we freed the pre part, `*base == p`. + } + } + + mi_assert_internal(p == NULL || (p != NULL && *base != NULL && ((uintptr_t)p % alignment) == 0)); + return p; +} + + +/* ----------------------------------------------------------- + OS API: alloc and alloc_aligned +----------------------------------------------------------- */ + +void* _mi_os_alloc(size_t size, mi_memid_t* memid, mi_stats_t* tld_stats) { + MI_UNUSED(tld_stats); + *memid = _mi_memid_none(); + mi_stats_t* stats = &_mi_stats_main; + if (size == 0) return NULL; + size = _mi_os_good_alloc_size(size); + bool os_is_large = false; + bool os_is_zero = false; + void* p = mi_os_prim_alloc(size, 0, true, false, &os_is_large, &os_is_zero, stats); + if (p != NULL) { + *memid = _mi_memid_create_os(true, os_is_zero, os_is_large); + } + return p; +} + +void* _mi_os_alloc_aligned(size_t size, size_t alignment, bool commit, bool allow_large, mi_memid_t* memid, mi_stats_t* tld_stats) +{ + MI_UNUSED(&_mi_os_get_aligned_hint); // suppress unused warnings + MI_UNUSED(tld_stats); + *memid = _mi_memid_none(); + if (size == 0) return NULL; + size = _mi_os_good_alloc_size(size); + alignment = _mi_align_up(alignment, _mi_os_page_size()); + + bool os_is_large = false; + bool os_is_zero = false; + void* os_base = NULL; + void* p = mi_os_prim_alloc_aligned(size, alignment, commit, allow_large, &os_is_large, &os_is_zero, &os_base, &_mi_stats_main /*tld->stats*/ ); + if (p != NULL) { + *memid = _mi_memid_create_os(commit, os_is_zero, os_is_large); + memid->mem.os.base = os_base; + memid->mem.os.alignment = alignment; + } + return p; +} + +/* ----------------------------------------------------------- + OS aligned allocation with an offset. This is used + for large alignments > MI_ALIGNMENT_MAX. We use a large mimalloc + page where the object can be aligned at an offset from the start of the segment. + As we may need to overallocate, we need to free such pointers using `mi_free_aligned` + to use the actual start of the memory region. +----------------------------------------------------------- */ + +void* _mi_os_alloc_aligned_at_offset(size_t size, size_t alignment, size_t offset, bool commit, bool allow_large, mi_memid_t* memid, mi_stats_t* tld_stats) { + mi_assert(offset <= MI_SEGMENT_SIZE); + mi_assert(offset <= size); + mi_assert((alignment % _mi_os_page_size()) == 0); + *memid = _mi_memid_none(); + if (offset > MI_SEGMENT_SIZE) return NULL; + if (offset == 0) { + // regular aligned allocation + return _mi_os_alloc_aligned(size, alignment, commit, allow_large, memid, tld_stats); + } + else { + // overallocate to align at an offset + const size_t extra = _mi_align_up(offset, alignment) - offset; + const size_t oversize = size + extra; + void* const start = _mi_os_alloc_aligned(oversize, alignment, commit, allow_large, memid, tld_stats); + if (start == NULL) return NULL; + + void* const p = (uint8_t*)start + extra; + mi_assert(_mi_is_aligned((uint8_t*)p + offset, alignment)); + // decommit the overallocation at the start + if (commit && extra > _mi_os_page_size()) { + _mi_os_decommit(start, extra, tld_stats); + } + return p; + } +} + +/* ----------------------------------------------------------- + OS memory API: reset, commit, decommit, protect, unprotect. +----------------------------------------------------------- */ + +// OS page align within a given area, either conservative (pages inside the area only), +// or not (straddling pages outside the area is possible) +static void* mi_os_page_align_areax(bool conservative, void* addr, size_t size, size_t* newsize) { + mi_assert(addr != NULL && size > 0); + if (newsize != NULL) *newsize = 0; + if (size == 0 || addr == NULL) return NULL; + + // page align conservatively within the range + void* start = (conservative ? mi_align_up_ptr(addr, _mi_os_page_size()) + : mi_align_down_ptr(addr, _mi_os_page_size())); + void* end = (conservative ? mi_align_down_ptr((uint8_t*)addr + size, _mi_os_page_size()) + : mi_align_up_ptr((uint8_t*)addr + size, _mi_os_page_size())); + ptrdiff_t diff = (uint8_t*)end - (uint8_t*)start; + if (diff <= 0) return NULL; + + mi_assert_internal((conservative && (size_t)diff <= size) || (!conservative && (size_t)diff >= size)); + if (newsize != NULL) *newsize = (size_t)diff; + return start; +} + +static void* mi_os_page_align_area_conservative(void* addr, size_t size, size_t* newsize) { + return mi_os_page_align_areax(true, addr, size, newsize); +} + +bool _mi_os_commit(void* addr, size_t size, bool* is_zero, mi_stats_t* tld_stats) { + MI_UNUSED(tld_stats); + mi_stats_t* stats = &_mi_stats_main; + if (is_zero != NULL) { *is_zero = false; } + _mi_stat_increase(&stats->committed, size); // use size for precise commit vs. decommit + _mi_stat_counter_increase(&stats->commit_calls, 1); + + // page align range + size_t csize; + void* start = mi_os_page_align_areax(false /* conservative? */, addr, size, &csize); + if (csize == 0) return true; + + // commit + bool os_is_zero = false; + int err = _mi_prim_commit(start, csize, &os_is_zero); + if (err != 0) { + _mi_warning_message("cannot commit OS memory (error: %d (0x%x), address: %p, size: 0x%zx bytes)\n", err, err, start, csize); + return false; + } + if (os_is_zero && is_zero != NULL) { + *is_zero = true; + mi_assert_expensive(mi_mem_is_zero(start, csize)); + } + // note: the following seems required for asan (otherwise `mimalloc-test-stress` fails) + #ifdef MI_TRACK_ASAN + if (os_is_zero) { mi_track_mem_defined(start,csize); } + else { mi_track_mem_undefined(start,csize); } + #endif + return true; +} + +static bool mi_os_decommit_ex(void* addr, size_t size, bool* needs_recommit, mi_stats_t* tld_stats) { + MI_UNUSED(tld_stats); + mi_stats_t* stats = &_mi_stats_main; + mi_assert_internal(needs_recommit!=NULL); + _mi_stat_decrease(&stats->committed, size); + + // page align + size_t csize; + void* start = mi_os_page_align_area_conservative(addr, size, &csize); + if (csize == 0) return true; + + // decommit + *needs_recommit = true; + int err = _mi_prim_decommit(start,csize,needs_recommit); + if (err != 0) { + _mi_warning_message("cannot decommit OS memory (error: %d (0x%x), address: %p, size: 0x%zx bytes)\n", err, err, start, csize); + } + mi_assert_internal(err == 0); + return (err == 0); +} + +bool _mi_os_decommit(void* addr, size_t size, mi_stats_t* tld_stats) { + bool needs_recommit; + return mi_os_decommit_ex(addr, size, &needs_recommit, tld_stats); +} + + +// Signal to the OS that the address range is no longer in use +// but may be used later again. This will release physical memory +// pages and reduce swapping while keeping the memory committed. +// We page align to a conservative area inside the range to reset. +bool _mi_os_reset(void* addr, size_t size, mi_stats_t* stats) { + // page align conservatively within the range + size_t csize; + void* start = mi_os_page_align_area_conservative(addr, size, &csize); + if (csize == 0) return true; // || _mi_os_is_huge_reserved(addr) + _mi_stat_increase(&stats->reset, csize); + _mi_stat_counter_increase(&stats->reset_calls, 1); + + #if (MI_DEBUG>1) && !MI_SECURE && !MI_TRACK_ENABLED // && !MI_TSAN + memset(start, 0, csize); // pretend it is eagerly reset + #endif + + int err = _mi_prim_reset(start, csize); + if (err != 0) { + _mi_warning_message("cannot reset OS memory (error: %d (0x%x), address: %p, size: 0x%zx bytes)\n", err, err, start, csize); + } + return (err == 0); +} + + +// either resets or decommits memory, returns true if the memory needs +// to be recommitted if it is to be re-used later on. +bool _mi_os_purge_ex(void* p, size_t size, bool allow_reset, mi_stats_t* stats) +{ + if (mi_option_get(mi_option_purge_delay) < 0) return false; // is purging allowed? + _mi_stat_counter_increase(&stats->purge_calls, 1); + _mi_stat_increase(&stats->purged, size); + + if (mi_option_is_enabled(mi_option_purge_decommits) && // should decommit? + !_mi_preloading()) // don't decommit during preloading (unsafe) + { + bool needs_recommit = true; + mi_os_decommit_ex(p, size, &needs_recommit, stats); + return needs_recommit; + } + else { + if (allow_reset) { // this can sometimes be not allowed if the range is not fully committed + _mi_os_reset(p, size, stats); + } + return false; // needs no recommit + } +} + +// either resets or decommits memory, returns true if the memory needs +// to be recommitted if it is to be re-used later on. +bool _mi_os_purge(void* p, size_t size, mi_stats_t * stats) { + return _mi_os_purge_ex(p, size, true, stats); +} + +// Protect a region in memory to be not accessible. +static bool mi_os_protectx(void* addr, size_t size, bool protect) { + // page align conservatively within the range + size_t csize = 0; + void* start = mi_os_page_align_area_conservative(addr, size, &csize); + if (csize == 0) return false; + /* + if (_mi_os_is_huge_reserved(addr)) { + _mi_warning_message("cannot mprotect memory allocated in huge OS pages\n"); + } + */ + int err = _mi_prim_protect(start,csize,protect); + if (err != 0) { + _mi_warning_message("cannot %s OS memory (error: %d (0x%x), address: %p, size: 0x%zx bytes)\n", (protect ? "protect" : "unprotect"), err, err, start, csize); + } + return (err == 0); +} + +bool _mi_os_protect(void* addr, size_t size) { + return mi_os_protectx(addr, size, true); +} + +bool _mi_os_unprotect(void* addr, size_t size) { + return mi_os_protectx(addr, size, false); +} + + + +/* ---------------------------------------------------------------------------- +Support for allocating huge OS pages (1Gib) that are reserved up-front +and possibly associated with a specific NUMA node. (use `numa_node>=0`) +-----------------------------------------------------------------------------*/ +#define MI_HUGE_OS_PAGE_SIZE (MI_GiB) + + +#if (MI_INTPTR_SIZE >= 8) +// To ensure proper alignment, use our own area for huge OS pages +static mi_decl_cache_align _Atomic(uintptr_t) mi_huge_start; // = 0 + +// Claim an aligned address range for huge pages +static uint8_t* mi_os_claim_huge_pages(size_t pages, size_t* total_size) { + if (total_size != NULL) *total_size = 0; + const size_t size = pages * MI_HUGE_OS_PAGE_SIZE; + + uintptr_t start = 0; + uintptr_t end = 0; + uintptr_t huge_start = mi_atomic_load_relaxed(&mi_huge_start); + do { + start = huge_start; + if (start == 0) { + // Initialize the start address after the 32TiB area + start = ((uintptr_t)32 << 40); // 32TiB virtual start address + #if (MI_SECURE>0 || MI_DEBUG==0) // security: randomize start of huge pages unless in debug mode + uintptr_t r = _mi_heap_random_next(mi_prim_get_default_heap()); + start = start + ((uintptr_t)MI_HUGE_OS_PAGE_SIZE * ((r>>17) & 0x0FFF)); // (randomly 12bits)*1GiB == between 0 to 4TiB + #endif + } + end = start + size; + mi_assert_internal(end % MI_SEGMENT_SIZE == 0); + } while (!mi_atomic_cas_strong_acq_rel(&mi_huge_start, &huge_start, end)); + + if (total_size != NULL) *total_size = size; + return (uint8_t*)start; +} +#else +static uint8_t* mi_os_claim_huge_pages(size_t pages, size_t* total_size) { + MI_UNUSED(pages); + if (total_size != NULL) *total_size = 0; + return NULL; +} +#endif + +// Allocate MI_SEGMENT_SIZE aligned huge pages +void* _mi_os_alloc_huge_os_pages(size_t pages, int numa_node, mi_msecs_t max_msecs, size_t* pages_reserved, size_t* psize, mi_memid_t* memid) { + *memid = _mi_memid_none(); + if (psize != NULL) *psize = 0; + if (pages_reserved != NULL) *pages_reserved = 0; + size_t size = 0; + uint8_t* start = mi_os_claim_huge_pages(pages, &size); + if (start == NULL) return NULL; // or 32-bit systems + + // Allocate one page at the time but try to place them contiguously + // We allocate one page at the time to be able to abort if it takes too long + // or to at least allocate as many as available on the system. + mi_msecs_t start_t = _mi_clock_start(); + size_t page = 0; + bool all_zero = true; + while (page < pages) { + // allocate a page + bool is_zero = false; + void* addr = start + (page * MI_HUGE_OS_PAGE_SIZE); + void* p = NULL; + int err = _mi_prim_alloc_huge_os_pages(addr, MI_HUGE_OS_PAGE_SIZE, numa_node, &is_zero, &p); + if (!is_zero) { all_zero = false; } + if (err != 0) { + _mi_warning_message("unable to allocate huge OS page (error: %d (0x%x), address: %p, size: %zx bytes)\n", err, err, addr, MI_HUGE_OS_PAGE_SIZE); + break; + } + + // Did we succeed at a contiguous address? + if (p != addr) { + // no success, issue a warning and break + if (p != NULL) { + _mi_warning_message("could not allocate contiguous huge OS page %zu at %p\n", page, addr); + mi_os_prim_free(p, MI_HUGE_OS_PAGE_SIZE, true, &_mi_stats_main); + } + break; + } + + // success, record it + page++; // increase before timeout check (see issue #711) + _mi_stat_increase(&_mi_stats_main.committed, MI_HUGE_OS_PAGE_SIZE); + _mi_stat_increase(&_mi_stats_main.reserved, MI_HUGE_OS_PAGE_SIZE); + + // check for timeout + if (max_msecs > 0) { + mi_msecs_t elapsed = _mi_clock_end(start_t); + if (page >= 1) { + mi_msecs_t estimate = ((elapsed / (page+1)) * pages); + if (estimate > 2*max_msecs) { // seems like we are going to timeout, break + elapsed = max_msecs + 1; + } + } + if (elapsed > max_msecs) { + _mi_warning_message("huge OS page allocation timed out (after allocating %zu page(s))\n", page); + break; + } + } + } + mi_assert_internal(page*MI_HUGE_OS_PAGE_SIZE <= size); + if (pages_reserved != NULL) { *pages_reserved = page; } + if (psize != NULL) { *psize = page * MI_HUGE_OS_PAGE_SIZE; } + if (page != 0) { + mi_assert(start != NULL); + *memid = _mi_memid_create_os(true /* is committed */, all_zero, true /* is_large */); + memid->memkind = MI_MEM_OS_HUGE; + mi_assert(memid->is_pinned); + #ifdef MI_TRACK_ASAN + if (all_zero) { mi_track_mem_defined(start,size); } + #endif + } + return (page == 0 ? NULL : start); +} + +// free every huge page in a range individually (as we allocated per page) +// note: needed with VirtualAlloc but could potentially be done in one go on mmap'd systems. +static void mi_os_free_huge_os_pages(void* p, size_t size, mi_stats_t* stats) { + if (p==NULL || size==0) return; + uint8_t* base = (uint8_t*)p; + while (size >= MI_HUGE_OS_PAGE_SIZE) { + mi_os_prim_free(base, MI_HUGE_OS_PAGE_SIZE, true, stats); + size -= MI_HUGE_OS_PAGE_SIZE; + base += MI_HUGE_OS_PAGE_SIZE; + } +} + +/* ---------------------------------------------------------------------------- +Support NUMA aware allocation +-----------------------------------------------------------------------------*/ + +_Atomic(size_t) _mi_numa_node_count; // = 0 // cache the node count + +size_t _mi_os_numa_node_count_get(void) { + size_t count = mi_atomic_load_acquire(&_mi_numa_node_count); + if (count <= 0) { + long ncount = mi_option_get(mi_option_use_numa_nodes); // given explicitly? + if (ncount > 0) { + count = (size_t)ncount; + } + else { + count = _mi_prim_numa_node_count(); // or detect dynamically + if (count == 0) count = 1; + } + mi_atomic_store_release(&_mi_numa_node_count, count); // save it + _mi_verbose_message("using %zd numa regions\n", count); + } + return count; +} + +int _mi_os_numa_node_get(mi_os_tld_t* tld) { + MI_UNUSED(tld); + size_t numa_count = _mi_os_numa_node_count(); + if (numa_count<=1) return 0; // optimize on single numa node systems: always node 0 + // never more than the node count and >= 0 + size_t numa_node = _mi_prim_numa_node(); + if (numa_node >= numa_count) { numa_node = numa_node % numa_count; } + return (int)numa_node; +} diff --git a/Objects/mimalloc/page-queue.c b/Objects/mimalloc/page-queue.c new file mode 100644 index 00000000000000..cb54b3740196e9 --- /dev/null +++ b/Objects/mimalloc/page-queue.c @@ -0,0 +1,332 @@ +/*---------------------------------------------------------------------------- +Copyright (c) 2018-2020, Microsoft Research, Daan Leijen +This is free software; you can redistribute it and/or modify it under the +terms of the MIT license. A copy of the license can be found in the file +"LICENSE" at the root of this distribution. +-----------------------------------------------------------------------------*/ + +/* ----------------------------------------------------------- + Definition of page queues for each block size +----------------------------------------------------------- */ + +#ifndef MI_IN_PAGE_C +#error "this file should be included from 'page.c'" +#endif + +/* ----------------------------------------------------------- + Minimal alignment in machine words (i.e. `sizeof(void*)`) +----------------------------------------------------------- */ + +#if (MI_MAX_ALIGN_SIZE > 4*MI_INTPTR_SIZE) + #error "define alignment for more than 4x word size for this platform" +#elif (MI_MAX_ALIGN_SIZE > 2*MI_INTPTR_SIZE) + #define MI_ALIGN4W // 4 machine words minimal alignment +#elif (MI_MAX_ALIGN_SIZE > MI_INTPTR_SIZE) + #define MI_ALIGN2W // 2 machine words minimal alignment +#else + // ok, default alignment is 1 word +#endif + + +/* ----------------------------------------------------------- + Queue query +----------------------------------------------------------- */ + + +static inline bool mi_page_queue_is_huge(const mi_page_queue_t* pq) { + return (pq->block_size == (MI_MEDIUM_OBJ_SIZE_MAX+sizeof(uintptr_t))); +} + +static inline bool mi_page_queue_is_full(const mi_page_queue_t* pq) { + return (pq->block_size == (MI_MEDIUM_OBJ_SIZE_MAX+(2*sizeof(uintptr_t)))); +} + +static inline bool mi_page_queue_is_special(const mi_page_queue_t* pq) { + return (pq->block_size > MI_MEDIUM_OBJ_SIZE_MAX); +} + +/* ----------------------------------------------------------- + Bins +----------------------------------------------------------- */ + +// Return the bin for a given field size. +// Returns MI_BIN_HUGE if the size is too large. +// We use `wsize` for the size in "machine word sizes", +// i.e. byte size == `wsize*sizeof(void*)`. +static inline uint8_t mi_bin(size_t size) { + size_t wsize = _mi_wsize_from_size(size); + uint8_t bin; + if (wsize <= 1) { + bin = 1; + } + #if defined(MI_ALIGN4W) + else if (wsize <= 4) { + bin = (uint8_t)((wsize+1)&~1); // round to double word sizes + } + #elif defined(MI_ALIGN2W) + else if (wsize <= 8) { + bin = (uint8_t)((wsize+1)&~1); // round to double word sizes + } + #else + else if (wsize <= 8) { + bin = (uint8_t)wsize; + } + #endif + else if (wsize > MI_MEDIUM_OBJ_WSIZE_MAX) { + bin = MI_BIN_HUGE; + } + else { + #if defined(MI_ALIGN4W) + if (wsize <= 16) { wsize = (wsize+3)&~3; } // round to 4x word sizes + #endif + wsize--; + // find the highest bit + uint8_t b = (uint8_t)mi_bsr(wsize); // note: wsize != 0 + // and use the top 3 bits to determine the bin (~12.5% worst internal fragmentation). + // - adjust with 3 because we use do not round the first 8 sizes + // which each get an exact bin + bin = ((b << 2) + (uint8_t)((wsize >> (b - 2)) & 0x03)) - 3; + mi_assert_internal(bin < MI_BIN_HUGE); + } + mi_assert_internal(bin > 0 && bin <= MI_BIN_HUGE); + return bin; +} + + + +/* ----------------------------------------------------------- + Queue of pages with free blocks +----------------------------------------------------------- */ + +uint8_t _mi_bin(size_t size) { + return mi_bin(size); +} + +size_t _mi_bin_size(uint8_t bin) { + return _mi_heap_empty.pages[bin].block_size; +} + +// Good size for allocation +size_t mi_good_size(size_t size) mi_attr_noexcept { + if (size <= MI_MEDIUM_OBJ_SIZE_MAX) { + return _mi_bin_size(mi_bin(size)); + } + else { + return _mi_align_up(size,_mi_os_page_size()); + } +} + +#if (MI_DEBUG>1) +static bool mi_page_queue_contains(mi_page_queue_t* queue, const mi_page_t* page) { + mi_assert_internal(page != NULL); + mi_page_t* list = queue->first; + while (list != NULL) { + mi_assert_internal(list->next == NULL || list->next->prev == list); + mi_assert_internal(list->prev == NULL || list->prev->next == list); + if (list == page) break; + list = list->next; + } + return (list == page); +} + +#endif + +#if (MI_DEBUG>1) +static bool mi_heap_contains_queue(const mi_heap_t* heap, const mi_page_queue_t* pq) { + return (pq >= &heap->pages[0] && pq <= &heap->pages[MI_BIN_FULL]); +} +#endif + +static mi_page_queue_t* mi_page_queue_of(const mi_page_t* page) { + uint8_t bin = (mi_page_is_in_full(page) ? MI_BIN_FULL : mi_bin(page->xblock_size)); + mi_heap_t* heap = mi_page_heap(page); + mi_assert_internal(heap != NULL && bin <= MI_BIN_FULL); + mi_page_queue_t* pq = &heap->pages[bin]; + mi_assert_internal(bin >= MI_BIN_HUGE || page->xblock_size == pq->block_size); + mi_assert_expensive(mi_page_queue_contains(pq, page)); + return pq; +} + +static mi_page_queue_t* mi_heap_page_queue_of(mi_heap_t* heap, const mi_page_t* page) { + uint8_t bin = (mi_page_is_in_full(page) ? MI_BIN_FULL : mi_bin(page->xblock_size)); + mi_assert_internal(bin <= MI_BIN_FULL); + mi_page_queue_t* pq = &heap->pages[bin]; + mi_assert_internal(mi_page_is_in_full(page) || page->xblock_size == pq->block_size); + return pq; +} + +// The current small page array is for efficiency and for each +// small size (up to 256) it points directly to the page for that +// size without having to compute the bin. This means when the +// current free page queue is updated for a small bin, we need to update a +// range of entries in `_mi_page_small_free`. +static inline void mi_heap_queue_first_update(mi_heap_t* heap, const mi_page_queue_t* pq) { + mi_assert_internal(mi_heap_contains_queue(heap,pq)); + size_t size = pq->block_size; + if (size > MI_SMALL_SIZE_MAX) return; + + mi_page_t* page = pq->first; + if (pq->first == NULL) page = (mi_page_t*)&_mi_page_empty; + + // find index in the right direct page array + size_t start; + size_t idx = _mi_wsize_from_size(size); + mi_page_t** pages_free = heap->pages_free_direct; + + if (pages_free[idx] == page) return; // already set + + // find start slot + if (idx<=1) { + start = 0; + } + else { + // find previous size; due to minimal alignment upto 3 previous bins may need to be skipped + uint8_t bin = mi_bin(size); + const mi_page_queue_t* prev = pq - 1; + while( bin == mi_bin(prev->block_size) && prev > &heap->pages[0]) { + prev--; + } + start = 1 + _mi_wsize_from_size(prev->block_size); + if (start > idx) start = idx; + } + + // set size range to the right page + mi_assert(start <= idx); + for (size_t sz = start; sz <= idx; sz++) { + pages_free[sz] = page; + } +} + +/* +static bool mi_page_queue_is_empty(mi_page_queue_t* queue) { + return (queue->first == NULL); +} +*/ + +static void mi_page_queue_remove(mi_page_queue_t* queue, mi_page_t* page) { + mi_assert_internal(page != NULL); + mi_assert_expensive(mi_page_queue_contains(queue, page)); + mi_assert_internal(page->xblock_size == queue->block_size || (page->xblock_size > MI_MEDIUM_OBJ_SIZE_MAX && mi_page_queue_is_huge(queue)) || (mi_page_is_in_full(page) && mi_page_queue_is_full(queue))); + mi_heap_t* heap = mi_page_heap(page); + + if (page->prev != NULL) page->prev->next = page->next; + if (page->next != NULL) page->next->prev = page->prev; + if (page == queue->last) queue->last = page->prev; + if (page == queue->first) { + queue->first = page->next; + // update first + mi_assert_internal(mi_heap_contains_queue(heap, queue)); + mi_heap_queue_first_update(heap,queue); + } + heap->page_count--; + page->next = NULL; + page->prev = NULL; + // mi_atomic_store_ptr_release(mi_atomic_cast(void*, &page->heap), NULL); + mi_page_set_in_full(page,false); +} + + +static void mi_page_queue_push(mi_heap_t* heap, mi_page_queue_t* queue, mi_page_t* page) { + mi_assert_internal(mi_page_heap(page) == heap); + mi_assert_internal(!mi_page_queue_contains(queue, page)); + #if MI_HUGE_PAGE_ABANDON + mi_assert_internal(_mi_page_segment(page)->kind != MI_SEGMENT_HUGE); + #endif + mi_assert_internal(page->xblock_size == queue->block_size || + (page->xblock_size > MI_MEDIUM_OBJ_SIZE_MAX) || + (mi_page_is_in_full(page) && mi_page_queue_is_full(queue))); + + mi_page_set_in_full(page, mi_page_queue_is_full(queue)); + // mi_atomic_store_ptr_release(mi_atomic_cast(void*, &page->heap), heap); + page->next = queue->first; + page->prev = NULL; + if (queue->first != NULL) { + mi_assert_internal(queue->first->prev == NULL); + queue->first->prev = page; + queue->first = page; + } + else { + queue->first = queue->last = page; + } + + // update direct + mi_heap_queue_first_update(heap, queue); + heap->page_count++; +} + + +static void mi_page_queue_enqueue_from(mi_page_queue_t* to, mi_page_queue_t* from, mi_page_t* page) { + mi_assert_internal(page != NULL); + mi_assert_expensive(mi_page_queue_contains(from, page)); + mi_assert_expensive(!mi_page_queue_contains(to, page)); + + mi_assert_internal((page->xblock_size == to->block_size && page->xblock_size == from->block_size) || + (page->xblock_size == to->block_size && mi_page_queue_is_full(from)) || + (page->xblock_size == from->block_size && mi_page_queue_is_full(to)) || + (page->xblock_size > MI_LARGE_OBJ_SIZE_MAX && mi_page_queue_is_huge(to)) || + (page->xblock_size > MI_LARGE_OBJ_SIZE_MAX && mi_page_queue_is_full(to))); + + mi_heap_t* heap = mi_page_heap(page); + if (page->prev != NULL) page->prev->next = page->next; + if (page->next != NULL) page->next->prev = page->prev; + if (page == from->last) from->last = page->prev; + if (page == from->first) { + from->first = page->next; + // update first + mi_assert_internal(mi_heap_contains_queue(heap, from)); + mi_heap_queue_first_update(heap, from); + } + + page->prev = to->last; + page->next = NULL; + if (to->last != NULL) { + mi_assert_internal(heap == mi_page_heap(to->last)); + to->last->next = page; + to->last = page; + } + else { + to->first = page; + to->last = page; + mi_heap_queue_first_update(heap, to); + } + + mi_page_set_in_full(page, mi_page_queue_is_full(to)); +} + +// Only called from `mi_heap_absorb`. +size_t _mi_page_queue_append(mi_heap_t* heap, mi_page_queue_t* pq, mi_page_queue_t* append) { + mi_assert_internal(mi_heap_contains_queue(heap,pq)); + mi_assert_internal(pq->block_size == append->block_size); + + if (append->first==NULL) return 0; + + // set append pages to new heap and count + size_t count = 0; + for (mi_page_t* page = append->first; page != NULL; page = page->next) { + // inline `mi_page_set_heap` to avoid wrong assertion during absorption; + // in this case it is ok to be delayed freeing since both "to" and "from" heap are still alive. + mi_atomic_store_release(&page->xheap, (uintptr_t)heap); + // set the flag to delayed free (not overriding NEVER_DELAYED_FREE) which has as a + // side effect that it spins until any DELAYED_FREEING is finished. This ensures + // that after appending only the new heap will be used for delayed free operations. + _mi_page_use_delayed_free(page, MI_USE_DELAYED_FREE, false); + count++; + } + + if (pq->last==NULL) { + // take over afresh + mi_assert_internal(pq->first==NULL); + pq->first = append->first; + pq->last = append->last; + mi_heap_queue_first_update(heap, pq); + } + else { + // append to end + mi_assert_internal(pq->last!=NULL); + mi_assert_internal(append->first!=NULL); + pq->last->next = append->first; + append->first->prev = pq->last; + pq->last = append->last; + } + return count; +} diff --git a/Objects/mimalloc/page.c b/Objects/mimalloc/page.c new file mode 100644 index 00000000000000..8f0ce920156e04 --- /dev/null +++ b/Objects/mimalloc/page.c @@ -0,0 +1,940 @@ +/*---------------------------------------------------------------------------- +Copyright (c) 2018-2020, Microsoft Research, Daan Leijen +This is free software; you can redistribute it and/or modify it under the +terms of the MIT license. A copy of the license can be found in the file +"LICENSE" at the root of this distribution. +-----------------------------------------------------------------------------*/ + +/* ----------------------------------------------------------- + The core of the allocator. Every segment contains + pages of a certain block size. The main function + exported is `mi_malloc_generic`. +----------------------------------------------------------- */ + +#include "mimalloc.h" +#include "mimalloc/internal.h" +#include "mimalloc/atomic.h" + +/* ----------------------------------------------------------- + Definition of page queues for each block size +----------------------------------------------------------- */ + +#define MI_IN_PAGE_C +#include "page-queue.c" +#undef MI_IN_PAGE_C + + +/* ----------------------------------------------------------- + Page helpers +----------------------------------------------------------- */ + +// Index a block in a page +static inline mi_block_t* mi_page_block_at(const mi_page_t* page, void* page_start, size_t block_size, size_t i) { + MI_UNUSED(page); + mi_assert_internal(page != NULL); + mi_assert_internal(i <= page->reserved); + return (mi_block_t*)((uint8_t*)page_start + (i * block_size)); +} + +static void mi_page_init(mi_heap_t* heap, mi_page_t* page, size_t size, mi_tld_t* tld); +static void mi_page_extend_free(mi_heap_t* heap, mi_page_t* page, mi_tld_t* tld); + +#if (MI_DEBUG>=3) +static size_t mi_page_list_count(mi_page_t* page, mi_block_t* head) { + size_t count = 0; + while (head != NULL) { + mi_assert_internal(page == _mi_ptr_page(head)); + count++; + head = mi_block_next(page, head); + } + return count; +} + +/* +// Start of the page available memory +static inline uint8_t* mi_page_area(const mi_page_t* page) { + return _mi_page_start(_mi_page_segment(page), page, NULL); +} +*/ + +static bool mi_page_list_is_valid(mi_page_t* page, mi_block_t* p) { + size_t psize; + uint8_t* page_area = _mi_page_start(_mi_page_segment(page), page, &psize); + mi_block_t* start = (mi_block_t*)page_area; + mi_block_t* end = (mi_block_t*)(page_area + psize); + while(p != NULL) { + if (p < start || p >= end) return false; + p = mi_block_next(page, p); + } +#if MI_DEBUG>3 // generally too expensive to check this + if (page->free_is_zero) { + const size_t ubsize = mi_page_usable_block_size(page); + for (mi_block_t* block = page->free; block != NULL; block = mi_block_next(page, block)) { + mi_assert_expensive(mi_mem_is_zero(block + 1, ubsize - sizeof(mi_block_t))); + } + } +#endif + return true; +} + +static bool mi_page_is_valid_init(mi_page_t* page) { + mi_assert_internal(page->xblock_size > 0); + mi_assert_internal(page->used <= page->capacity); + mi_assert_internal(page->capacity <= page->reserved); + + mi_segment_t* segment = _mi_page_segment(page); + uint8_t* start = _mi_page_start(segment,page,NULL); + mi_assert_internal(start == _mi_segment_page_start(segment,page,NULL)); + //const size_t bsize = mi_page_block_size(page); + //mi_assert_internal(start + page->capacity*page->block_size == page->top); + + mi_assert_internal(mi_page_list_is_valid(page,page->free)); + mi_assert_internal(mi_page_list_is_valid(page,page->local_free)); + + #if MI_DEBUG>3 // generally too expensive to check this + if (page->free_is_zero) { + const size_t ubsize = mi_page_usable_block_size(page); + for(mi_block_t* block = page->free; block != NULL; block = mi_block_next(page,block)) { + mi_assert_expensive(mi_mem_is_zero(block + 1, ubsize - sizeof(mi_block_t))); + } + } + #endif + + #if !MI_TRACK_ENABLED && !MI_TSAN + mi_block_t* tfree = mi_page_thread_free(page); + mi_assert_internal(mi_page_list_is_valid(page, tfree)); + //size_t tfree_count = mi_page_list_count(page, tfree); + //mi_assert_internal(tfree_count <= page->thread_freed + 1); + #endif + + size_t free_count = mi_page_list_count(page, page->free) + mi_page_list_count(page, page->local_free); + mi_assert_internal(page->used + free_count == page->capacity); + + return true; +} + +extern bool _mi_process_is_initialized; // has mi_process_init been called? + +bool _mi_page_is_valid(mi_page_t* page) { + mi_assert_internal(mi_page_is_valid_init(page)); + #if MI_SECURE + mi_assert_internal(page->keys[0] != 0); + #endif + if (mi_page_heap(page)!=NULL) { + mi_segment_t* segment = _mi_page_segment(page); + + mi_assert_internal(!_mi_process_is_initialized || segment->thread_id==0 || segment->thread_id == mi_page_heap(page)->thread_id); + #if MI_HUGE_PAGE_ABANDON + if (segment->kind != MI_SEGMENT_HUGE) + #endif + { + mi_page_queue_t* pq = mi_page_queue_of(page); + mi_assert_internal(mi_page_queue_contains(pq, page)); + mi_assert_internal(pq->block_size==mi_page_block_size(page) || mi_page_block_size(page) > MI_MEDIUM_OBJ_SIZE_MAX || mi_page_is_in_full(page)); + mi_assert_internal(mi_heap_contains_queue(mi_page_heap(page),pq)); + } + } + return true; +} +#endif + +void _mi_page_use_delayed_free(mi_page_t* page, mi_delayed_t delay, bool override_never) { + while (!_mi_page_try_use_delayed_free(page, delay, override_never)) { + mi_atomic_yield(); + } +} + +bool _mi_page_try_use_delayed_free(mi_page_t* page, mi_delayed_t delay, bool override_never) { + mi_thread_free_t tfreex; + mi_delayed_t old_delay; + mi_thread_free_t tfree; + size_t yield_count = 0; + do { + tfree = mi_atomic_load_acquire(&page->xthread_free); // note: must acquire as we can break/repeat this loop and not do a CAS; + tfreex = mi_tf_set_delayed(tfree, delay); + old_delay = mi_tf_delayed(tfree); + if mi_unlikely(old_delay == MI_DELAYED_FREEING) { + if (yield_count >= 4) return false; // give up after 4 tries + yield_count++; + mi_atomic_yield(); // delay until outstanding MI_DELAYED_FREEING are done. + // tfree = mi_tf_set_delayed(tfree, MI_NO_DELAYED_FREE); // will cause CAS to busy fail + } + else if (delay == old_delay) { + break; // avoid atomic operation if already equal + } + else if (!override_never && old_delay == MI_NEVER_DELAYED_FREE) { + break; // leave never-delayed flag set + } + } while ((old_delay == MI_DELAYED_FREEING) || + !mi_atomic_cas_weak_release(&page->xthread_free, &tfree, tfreex)); + + return true; // success +} + +/* ----------------------------------------------------------- + Page collect the `local_free` and `thread_free` lists +----------------------------------------------------------- */ + +// Collect the local `thread_free` list using an atomic exchange. +// Note: The exchange must be done atomically as this is used right after +// moving to the full list in `mi_page_collect_ex` and we need to +// ensure that there was no race where the page became unfull just before the move. +static void _mi_page_thread_free_collect(mi_page_t* page) +{ + mi_block_t* head; + mi_thread_free_t tfreex; + mi_thread_free_t tfree = mi_atomic_load_relaxed(&page->xthread_free); + do { + head = mi_tf_block(tfree); + tfreex = mi_tf_set_block(tfree,NULL); + } while (!mi_atomic_cas_weak_acq_rel(&page->xthread_free, &tfree, tfreex)); + + // return if the list is empty + if (head == NULL) return; + + // find the tail -- also to get a proper count (without data races) + uint32_t max_count = page->capacity; // cannot collect more than capacity + uint32_t count = 1; + mi_block_t* tail = head; + mi_block_t* next; + while ((next = mi_block_next(page,tail)) != NULL && count <= max_count) { + count++; + tail = next; + } + // if `count > max_count` there was a memory corruption (possibly infinite list due to double multi-threaded free) + if (count > max_count) { + _mi_error_message(EFAULT, "corrupted thread-free list\n"); + return; // the thread-free items cannot be freed + } + + // and append the current local free list + mi_block_set_next(page,tail, page->local_free); + page->local_free = head; + + // update counts now + page->used -= count; +} + +void _mi_page_free_collect(mi_page_t* page, bool force) { + mi_assert_internal(page!=NULL); + + // collect the thread free list + if (force || mi_page_thread_free(page) != NULL) { // quick test to avoid an atomic operation + _mi_page_thread_free_collect(page); + } + + // and the local free list + if (page->local_free != NULL) { + if mi_likely(page->free == NULL) { + // usual case + page->free = page->local_free; + page->local_free = NULL; + page->free_is_zero = false; + } + else if (force) { + // append -- only on shutdown (force) as this is a linear operation + mi_block_t* tail = page->local_free; + mi_block_t* next; + while ((next = mi_block_next(page, tail)) != NULL) { + tail = next; + } + mi_block_set_next(page, tail, page->free); + page->free = page->local_free; + page->local_free = NULL; + page->free_is_zero = false; + } + } + + mi_assert_internal(!force || page->local_free == NULL); +} + + + +/* ----------------------------------------------------------- + Page fresh and retire +----------------------------------------------------------- */ + +// called from segments when reclaiming abandoned pages +void _mi_page_reclaim(mi_heap_t* heap, mi_page_t* page) { + mi_assert_expensive(mi_page_is_valid_init(page)); + + mi_assert_internal(mi_page_heap(page) == heap); + mi_assert_internal(mi_page_thread_free_flag(page) != MI_NEVER_DELAYED_FREE); + #if MI_HUGE_PAGE_ABANDON + mi_assert_internal(_mi_page_segment(page)->kind != MI_SEGMENT_HUGE); + #endif + + // TODO: push on full queue immediately if it is full? + mi_page_queue_t* pq = mi_page_queue(heap, mi_page_block_size(page)); + mi_page_queue_push(heap, pq, page); + mi_assert_expensive(_mi_page_is_valid(page)); +} + +// allocate a fresh page from a segment +static mi_page_t* mi_page_fresh_alloc(mi_heap_t* heap, mi_page_queue_t* pq, size_t block_size, size_t page_alignment) { + #if !MI_HUGE_PAGE_ABANDON + mi_assert_internal(pq != NULL); + mi_assert_internal(mi_heap_contains_queue(heap, pq)); + mi_assert_internal(page_alignment > 0 || block_size > MI_MEDIUM_OBJ_SIZE_MAX || block_size == pq->block_size); + #endif + mi_page_t* page = _mi_segment_page_alloc(heap, block_size, page_alignment, &heap->tld->segments, &heap->tld->os); + if (page == NULL) { + // this may be out-of-memory, or an abandoned page was reclaimed (and in our queue) + return NULL; + } + mi_assert_internal(page_alignment >0 || block_size > MI_MEDIUM_OBJ_SIZE_MAX || _mi_page_segment(page)->kind != MI_SEGMENT_HUGE); + mi_assert_internal(pq!=NULL || page->xblock_size != 0); + mi_assert_internal(pq!=NULL || mi_page_block_size(page) >= block_size); + // a fresh page was found, initialize it + const size_t full_block_size = ((pq == NULL || mi_page_queue_is_huge(pq)) ? mi_page_block_size(page) : block_size); // see also: mi_segment_huge_page_alloc + mi_assert_internal(full_block_size >= block_size); + mi_page_init(heap, page, full_block_size, heap->tld); + mi_heap_stat_increase(heap, pages, 1); + if (pq != NULL) { mi_page_queue_push(heap, pq, page); } + mi_assert_expensive(_mi_page_is_valid(page)); + return page; +} + +// Get a fresh page to use +static mi_page_t* mi_page_fresh(mi_heap_t* heap, mi_page_queue_t* pq) { + mi_assert_internal(mi_heap_contains_queue(heap, pq)); + mi_page_t* page = mi_page_fresh_alloc(heap, pq, pq->block_size, 0); + if (page==NULL) return NULL; + mi_assert_internal(pq->block_size==mi_page_block_size(page)); + mi_assert_internal(pq==mi_page_queue(heap, mi_page_block_size(page))); + return page; +} + +/* ----------------------------------------------------------- + Do any delayed frees + (put there by other threads if they deallocated in a full page) +----------------------------------------------------------- */ +void _mi_heap_delayed_free_all(mi_heap_t* heap) { + while (!_mi_heap_delayed_free_partial(heap)) { + mi_atomic_yield(); + } +} + +// returns true if all delayed frees were processed +bool _mi_heap_delayed_free_partial(mi_heap_t* heap) { + // take over the list (note: no atomic exchange since it is often NULL) + mi_block_t* block = mi_atomic_load_ptr_relaxed(mi_block_t, &heap->thread_delayed_free); + while (block != NULL && !mi_atomic_cas_ptr_weak_acq_rel(mi_block_t, &heap->thread_delayed_free, &block, NULL)) { /* nothing */ }; + bool all_freed = true; + + // and free them all + while(block != NULL) { + mi_block_t* next = mi_block_nextx(heap,block, heap->keys); + // use internal free instead of regular one to keep stats etc correct + if (!_mi_free_delayed_block(block)) { + // we might already start delayed freeing while another thread has not yet + // reset the delayed_freeing flag; in that case delay it further by reinserting the current block + // into the delayed free list + all_freed = false; + mi_block_t* dfree = mi_atomic_load_ptr_relaxed(mi_block_t, &heap->thread_delayed_free); + do { + mi_block_set_nextx(heap, block, dfree, heap->keys); + } while (!mi_atomic_cas_ptr_weak_release(mi_block_t,&heap->thread_delayed_free, &dfree, block)); + } + block = next; + } + return all_freed; +} + +/* ----------------------------------------------------------- + Unfull, abandon, free and retire +----------------------------------------------------------- */ + +// Move a page from the full list back to a regular list +void _mi_page_unfull(mi_page_t* page) { + mi_assert_internal(page != NULL); + mi_assert_expensive(_mi_page_is_valid(page)); + mi_assert_internal(mi_page_is_in_full(page)); + if (!mi_page_is_in_full(page)) return; + + mi_heap_t* heap = mi_page_heap(page); + mi_page_queue_t* pqfull = &heap->pages[MI_BIN_FULL]; + mi_page_set_in_full(page, false); // to get the right queue + mi_page_queue_t* pq = mi_heap_page_queue_of(heap, page); + mi_page_set_in_full(page, true); + mi_page_queue_enqueue_from(pq, pqfull, page); +} + +static void mi_page_to_full(mi_page_t* page, mi_page_queue_t* pq) { + mi_assert_internal(pq == mi_page_queue_of(page)); + mi_assert_internal(!mi_page_immediate_available(page)); + mi_assert_internal(!mi_page_is_in_full(page)); + + if (mi_page_is_in_full(page)) return; + mi_page_queue_enqueue_from(&mi_page_heap(page)->pages[MI_BIN_FULL], pq, page); + _mi_page_free_collect(page,false); // try to collect right away in case another thread freed just before MI_USE_DELAYED_FREE was set +} + + +// Abandon a page with used blocks at the end of a thread. +// Note: only call if it is ensured that no references exist from +// the `page->heap->thread_delayed_free` into this page. +// Currently only called through `mi_heap_collect_ex` which ensures this. +void _mi_page_abandon(mi_page_t* page, mi_page_queue_t* pq) { + mi_assert_internal(page != NULL); + mi_assert_expensive(_mi_page_is_valid(page)); + mi_assert_internal(pq == mi_page_queue_of(page)); + mi_assert_internal(mi_page_heap(page) != NULL); + + mi_heap_t* pheap = mi_page_heap(page); + + // remove from our page list + mi_segments_tld_t* segments_tld = &pheap->tld->segments; + mi_page_queue_remove(pq, page); + + // page is no longer associated with our heap + mi_assert_internal(mi_page_thread_free_flag(page)==MI_NEVER_DELAYED_FREE); + mi_page_set_heap(page, NULL); + +#if (MI_DEBUG>1) && !MI_TRACK_ENABLED + // check there are no references left.. + for (mi_block_t* block = (mi_block_t*)pheap->thread_delayed_free; block != NULL; block = mi_block_nextx(pheap, block, pheap->keys)) { + mi_assert_internal(_mi_ptr_page(block) != page); + } +#endif + + // and abandon it + mi_assert_internal(mi_page_heap(page) == NULL); + _mi_segment_page_abandon(page,segments_tld); +} + + +// Free a page with no more free blocks +void _mi_page_free(mi_page_t* page, mi_page_queue_t* pq, bool force) { + mi_assert_internal(page != NULL); + mi_assert_expensive(_mi_page_is_valid(page)); + mi_assert_internal(pq == mi_page_queue_of(page)); + mi_assert_internal(mi_page_all_free(page)); + mi_assert_internal(mi_page_thread_free_flag(page)!=MI_DELAYED_FREEING); + + // no more aligned blocks in here + mi_page_set_has_aligned(page, false); + + mi_heap_t* heap = mi_page_heap(page); + + // remove from the page list + // (no need to do _mi_heap_delayed_free first as all blocks are already free) + mi_segments_tld_t* segments_tld = &heap->tld->segments; + mi_page_queue_remove(pq, page); + + // and free it + mi_page_set_heap(page,NULL); + _mi_segment_page_free(page, force, segments_tld); +} + +// Retire parameters +#define MI_MAX_RETIRE_SIZE (MI_MEDIUM_OBJ_SIZE_MAX) +#define MI_RETIRE_CYCLES (16) + +// Retire a page with no more used blocks +// Important to not retire too quickly though as new +// allocations might coming. +// Note: called from `mi_free` and benchmarks often +// trigger this due to freeing everything and then +// allocating again so careful when changing this. +void _mi_page_retire(mi_page_t* page) mi_attr_noexcept { + mi_assert_internal(page != NULL); + mi_assert_expensive(_mi_page_is_valid(page)); + mi_assert_internal(mi_page_all_free(page)); + + mi_page_set_has_aligned(page, false); + + // don't retire too often.. + // (or we end up retiring and re-allocating most of the time) + // NOTE: refine this more: we should not retire if this + // is the only page left with free blocks. It is not clear + // how to check this efficiently though... + // for now, we don't retire if it is the only page left of this size class. + mi_page_queue_t* pq = mi_page_queue_of(page); + if mi_likely(page->xblock_size <= MI_MAX_RETIRE_SIZE && !mi_page_queue_is_special(pq)) { // not too large && not full or huge queue? + if (pq->last==page && pq->first==page) { // the only page in the queue? + mi_stat_counter_increase(_mi_stats_main.page_no_retire,1); + page->retire_expire = 1 + (page->xblock_size <= MI_SMALL_OBJ_SIZE_MAX ? MI_RETIRE_CYCLES : MI_RETIRE_CYCLES/4); + mi_heap_t* heap = mi_page_heap(page); + mi_assert_internal(pq >= heap->pages); + const size_t index = pq - heap->pages; + mi_assert_internal(index < MI_BIN_FULL && index < MI_BIN_HUGE); + if (index < heap->page_retired_min) heap->page_retired_min = index; + if (index > heap->page_retired_max) heap->page_retired_max = index; + mi_assert_internal(mi_page_all_free(page)); + return; // dont't free after all + } + } + _mi_page_free(page, pq, false); +} + +// free retired pages: we don't need to look at the entire queues +// since we only retire pages that are at the head position in a queue. +void _mi_heap_collect_retired(mi_heap_t* heap, bool force) { + size_t min = MI_BIN_FULL; + size_t max = 0; + for(size_t bin = heap->page_retired_min; bin <= heap->page_retired_max; bin++) { + mi_page_queue_t* pq = &heap->pages[bin]; + mi_page_t* page = pq->first; + if (page != NULL && page->retire_expire != 0) { + if (mi_page_all_free(page)) { + page->retire_expire--; + if (force || page->retire_expire == 0) { + _mi_page_free(pq->first, pq, force); + } + else { + // keep retired, update min/max + if (bin < min) min = bin; + if (bin > max) max = bin; + } + } + else { + page->retire_expire = 0; + } + } + } + heap->page_retired_min = min; + heap->page_retired_max = max; +} + + +/* ----------------------------------------------------------- + Initialize the initial free list in a page. + In secure mode we initialize a randomized list by + alternating between slices. +----------------------------------------------------------- */ + +#define MI_MAX_SLICE_SHIFT (6) // at most 64 slices +#define MI_MAX_SLICES (1UL << MI_MAX_SLICE_SHIFT) +#define MI_MIN_SLICES (2) + +static void mi_page_free_list_extend_secure(mi_heap_t* const heap, mi_page_t* const page, const size_t bsize, const size_t extend, mi_stats_t* const stats) { + MI_UNUSED(stats); + #if (MI_SECURE<=2) + mi_assert_internal(page->free == NULL); + mi_assert_internal(page->local_free == NULL); + #endif + mi_assert_internal(page->capacity + extend <= page->reserved); + mi_assert_internal(bsize == mi_page_block_size(page)); + void* const page_area = _mi_page_start(_mi_page_segment(page), page, NULL); + + // initialize a randomized free list + // set up `slice_count` slices to alternate between + size_t shift = MI_MAX_SLICE_SHIFT; + while ((extend >> shift) == 0) { + shift--; + } + const size_t slice_count = (size_t)1U << shift; + const size_t slice_extend = extend / slice_count; + mi_assert_internal(slice_extend >= 1); + mi_block_t* blocks[MI_MAX_SLICES]; // current start of the slice + size_t counts[MI_MAX_SLICES]; // available objects in the slice + for (size_t i = 0; i < slice_count; i++) { + blocks[i] = mi_page_block_at(page, page_area, bsize, page->capacity + i*slice_extend); + counts[i] = slice_extend; + } + counts[slice_count-1] += (extend % slice_count); // final slice holds the modulus too (todo: distribute evenly?) + + // and initialize the free list by randomly threading through them + // set up first element + const uintptr_t r = _mi_heap_random_next(heap); + size_t current = r % slice_count; + counts[current]--; + mi_block_t* const free_start = blocks[current]; + // and iterate through the rest; use `random_shuffle` for performance + uintptr_t rnd = _mi_random_shuffle(r|1); // ensure not 0 + for (size_t i = 1; i < extend; i++) { + // call random_shuffle only every INTPTR_SIZE rounds + const size_t round = i%MI_INTPTR_SIZE; + if (round == 0) rnd = _mi_random_shuffle(rnd); + // select a random next slice index + size_t next = ((rnd >> 8*round) & (slice_count-1)); + while (counts[next]==0) { // ensure it still has space + next++; + if (next==slice_count) next = 0; + } + // and link the current block to it + counts[next]--; + mi_block_t* const block = blocks[current]; + blocks[current] = (mi_block_t*)((uint8_t*)block + bsize); // bump to the following block + mi_block_set_next(page, block, blocks[next]); // and set next; note: we may have `current == next` + current = next; + } + // prepend to the free list (usually NULL) + mi_block_set_next(page, blocks[current], page->free); // end of the list + page->free = free_start; +} + +static mi_decl_noinline void mi_page_free_list_extend( mi_page_t* const page, const size_t bsize, const size_t extend, mi_stats_t* const stats) +{ + MI_UNUSED(stats); + #if (MI_SECURE <= 2) + mi_assert_internal(page->free == NULL); + mi_assert_internal(page->local_free == NULL); + #endif + mi_assert_internal(page->capacity + extend <= page->reserved); + mi_assert_internal(bsize == mi_page_block_size(page)); + void* const page_area = _mi_page_start(_mi_page_segment(page), page, NULL ); + + mi_block_t* const start = mi_page_block_at(page, page_area, bsize, page->capacity); + + // initialize a sequential free list + mi_block_t* const last = mi_page_block_at(page, page_area, bsize, page->capacity + extend - 1); + mi_block_t* block = start; + while(block <= last) { + mi_block_t* next = (mi_block_t*)((uint8_t*)block + bsize); + mi_block_set_next(page,block,next); + block = next; + } + // prepend to free list (usually `NULL`) + mi_block_set_next(page, last, page->free); + page->free = start; +} + +/* ----------------------------------------------------------- + Page initialize and extend the capacity +----------------------------------------------------------- */ + +#define MI_MAX_EXTEND_SIZE (4*1024) // heuristic, one OS page seems to work well. +#if (MI_SECURE>0) +#define MI_MIN_EXTEND (8*MI_SECURE) // extend at least by this many +#else +#define MI_MIN_EXTEND (4) +#endif + +// Extend the capacity (up to reserved) by initializing a free list +// We do at most `MI_MAX_EXTEND` to avoid touching too much memory +// Note: we also experimented with "bump" allocation on the first +// allocations but this did not speed up any benchmark (due to an +// extra test in malloc? or cache effects?) +static void mi_page_extend_free(mi_heap_t* heap, mi_page_t* page, mi_tld_t* tld) { + MI_UNUSED(tld); + mi_assert_expensive(mi_page_is_valid_init(page)); + #if (MI_SECURE<=2) + mi_assert(page->free == NULL); + mi_assert(page->local_free == NULL); + if (page->free != NULL) return; + #endif + if (page->capacity >= page->reserved) return; + + size_t page_size; + _mi_page_start(_mi_page_segment(page), page, &page_size); + mi_stat_counter_increase(tld->stats.pages_extended, 1); + + // calculate the extend count + const size_t bsize = (page->xblock_size < MI_HUGE_BLOCK_SIZE ? page->xblock_size : page_size); + size_t extend = page->reserved - page->capacity; + mi_assert_internal(extend > 0); + + size_t max_extend = (bsize >= MI_MAX_EXTEND_SIZE ? MI_MIN_EXTEND : MI_MAX_EXTEND_SIZE/(uint32_t)bsize); + if (max_extend < MI_MIN_EXTEND) { max_extend = MI_MIN_EXTEND; } + mi_assert_internal(max_extend > 0); + + if (extend > max_extend) { + // ensure we don't touch memory beyond the page to reduce page commit. + // the `lean` benchmark tests this. Going from 1 to 8 increases rss by 50%. + extend = max_extend; + } + + mi_assert_internal(extend > 0 && extend + page->capacity <= page->reserved); + mi_assert_internal(extend < (1UL<<16)); + + // and append the extend the free list + if (extend < MI_MIN_SLICES || MI_SECURE==0) { //!mi_option_is_enabled(mi_option_secure)) { + mi_page_free_list_extend(page, bsize, extend, &tld->stats ); + } + else { + mi_page_free_list_extend_secure(heap, page, bsize, extend, &tld->stats); + } + // enable the new free list + page->capacity += (uint16_t)extend; + mi_stat_increase(tld->stats.page_committed, extend * bsize); + mi_assert_expensive(mi_page_is_valid_init(page)); +} + +// Initialize a fresh page +static void mi_page_init(mi_heap_t* heap, mi_page_t* page, size_t block_size, mi_tld_t* tld) { + mi_assert(page != NULL); + mi_segment_t* segment = _mi_page_segment(page); + mi_assert(segment != NULL); + mi_assert_internal(block_size > 0); + // set fields + mi_page_set_heap(page, heap); + page->tag = heap->tag; + page->xblock_size = (block_size < MI_HUGE_BLOCK_SIZE ? (uint32_t)block_size : MI_HUGE_BLOCK_SIZE); // initialize before _mi_segment_page_start + size_t page_size; + const void* page_start = _mi_segment_page_start(segment, page, &page_size); + MI_UNUSED(page_start); + mi_track_mem_noaccess(page_start,page_size); + mi_assert_internal(mi_page_block_size(page) <= page_size); + mi_assert_internal(page_size <= page->slice_count*MI_SEGMENT_SLICE_SIZE); + mi_assert_internal(page_size / block_size < (1L<<16)); + page->reserved = (uint16_t)(page_size / block_size); + mi_assert_internal(page->reserved > 0); + #if (MI_PADDING || MI_ENCODE_FREELIST) + page->keys[0] = _mi_heap_random_next(heap); + page->keys[1] = _mi_heap_random_next(heap); + #endif + page->free_is_zero = page->is_zero_init; + #if MI_DEBUG>2 + if (page->is_zero_init) { + mi_track_mem_defined(page_start, page_size); + mi_assert_expensive(mi_mem_is_zero(page_start, page_size)); + } + #endif + + mi_assert_internal(page->is_committed); + mi_assert_internal(page->capacity == 0); + mi_assert_internal(page->free == NULL); + mi_assert_internal(page->used == 0); + mi_assert_internal(page->xthread_free == 0); + mi_assert_internal(page->next == NULL); + mi_assert_internal(page->prev == NULL); + mi_assert_internal(page->retire_expire == 0); + mi_assert_internal(!mi_page_has_aligned(page)); + #if (MI_PADDING || MI_ENCODE_FREELIST) + mi_assert_internal(page->keys[0] != 0); + mi_assert_internal(page->keys[1] != 0); + #endif + mi_assert_expensive(mi_page_is_valid_init(page)); + + // initialize an initial free list + mi_page_extend_free(heap,page,tld); + mi_assert(mi_page_immediate_available(page)); +} + + +/* ----------------------------------------------------------- + Find pages with free blocks +-------------------------------------------------------------*/ + +// Find a page with free blocks of `page->block_size`. +static mi_page_t* mi_page_queue_find_free_ex(mi_heap_t* heap, mi_page_queue_t* pq, bool first_try) +{ + // search through the pages in "next fit" order + #if MI_STAT + size_t count = 0; + #endif + mi_page_t* page = pq->first; + while (page != NULL) + { + mi_page_t* next = page->next; // remember next + #if MI_STAT + count++; + #endif + + // 0. collect freed blocks by us and other threads + _mi_page_free_collect(page, false); + + // 1. if the page contains free blocks, we are done + if (mi_page_immediate_available(page)) { + break; // pick this one + } + + // 2. Try to extend + if (page->capacity < page->reserved) { + mi_page_extend_free(heap, page, heap->tld); + mi_assert_internal(mi_page_immediate_available(page)); + break; + } + + // 3. If the page is completely full, move it to the `mi_pages_full` + // queue so we don't visit long-lived pages too often. + mi_assert_internal(!mi_page_is_in_full(page) && !mi_page_immediate_available(page)); + mi_page_to_full(page, pq); + + page = next; + } // for each page + + mi_heap_stat_counter_increase(heap, searches, count); + + if (page == NULL) { + _mi_heap_collect_retired(heap, false); // perhaps make a page available? + page = mi_page_fresh(heap, pq); + if (page == NULL && first_try) { + // out-of-memory _or_ an abandoned page with free blocks was reclaimed, try once again + page = mi_page_queue_find_free_ex(heap, pq, false); + } + } + else { + mi_assert(pq->first == page); + page->retire_expire = 0; + } + mi_assert_internal(page == NULL || mi_page_immediate_available(page)); + return page; +} + + + +// Find a page with free blocks of `size`. +static inline mi_page_t* mi_find_free_page(mi_heap_t* heap, size_t size) { + mi_page_queue_t* pq = mi_page_queue(heap,size); + mi_page_t* page = pq->first; + if (page != NULL) { + #if (MI_SECURE>=3) // in secure mode, we extend half the time to increase randomness + if (page->capacity < page->reserved && ((_mi_heap_random_next(heap) & 1) == 1)) { + mi_page_extend_free(heap, page, heap->tld); + mi_assert_internal(mi_page_immediate_available(page)); + } + else + #endif + { + _mi_page_free_collect(page,false); + } + + if (mi_page_immediate_available(page)) { + page->retire_expire = 0; + return page; // fast path + } + } + return mi_page_queue_find_free_ex(heap, pq, true); +} + + +/* ----------------------------------------------------------- + Users can register a deferred free function called + when the `free` list is empty. Since the `local_free` + is separate this is deterministically called after + a certain number of allocations. +----------------------------------------------------------- */ + +static mi_deferred_free_fun* volatile deferred_free = NULL; +static _Atomic(void*) deferred_arg; // = NULL + +void _mi_deferred_free(mi_heap_t* heap, bool force) { + heap->tld->heartbeat++; + if (deferred_free != NULL && !heap->tld->recurse) { + heap->tld->recurse = true; + deferred_free(force, heap->tld->heartbeat, mi_atomic_load_ptr_relaxed(void,&deferred_arg)); + heap->tld->recurse = false; + } +} + +void mi_register_deferred_free(mi_deferred_free_fun* fn, void* arg) mi_attr_noexcept { + deferred_free = fn; + mi_atomic_store_ptr_release(void,&deferred_arg, arg); +} + + +/* ----------------------------------------------------------- + General allocation +----------------------------------------------------------- */ + +// Large and huge page allocation. +// Huge pages are allocated directly without being in a queue. +// Because huge pages contain just one block, and the segment contains +// just that page, we always treat them as abandoned and any thread +// that frees the block can free the whole page and segment directly. +// Huge pages are also use if the requested alignment is very large (> MI_ALIGNMENT_MAX). +static mi_page_t* mi_large_huge_page_alloc(mi_heap_t* heap, size_t size, size_t page_alignment) { + size_t block_size = _mi_os_good_alloc_size(size); + mi_assert_internal(mi_bin(block_size) == MI_BIN_HUGE || page_alignment > 0); + bool is_huge = (block_size > MI_LARGE_OBJ_SIZE_MAX || page_alignment > 0); + #if MI_HUGE_PAGE_ABANDON + mi_page_queue_t* pq = (is_huge ? NULL : mi_page_queue(heap, block_size)); + #else + mi_page_queue_t* pq = mi_page_queue(heap, is_huge ? MI_HUGE_BLOCK_SIZE : block_size); // not block_size as that can be low if the page_alignment > 0 + mi_assert_internal(!is_huge || mi_page_queue_is_huge(pq)); + #endif + mi_page_t* page = mi_page_fresh_alloc(heap, pq, block_size, page_alignment); + if (page != NULL) { + mi_assert_internal(mi_page_immediate_available(page)); + + if (is_huge) { + mi_assert_internal(_mi_page_segment(page)->kind == MI_SEGMENT_HUGE); + mi_assert_internal(_mi_page_segment(page)->used==1); + #if MI_HUGE_PAGE_ABANDON + mi_assert_internal(_mi_page_segment(page)->thread_id==0); // abandoned, not in the huge queue + mi_page_set_heap(page, NULL); + #endif + } + else { + mi_assert_internal(_mi_page_segment(page)->kind != MI_SEGMENT_HUGE); + } + + const size_t bsize = mi_page_usable_block_size(page); // note: not `mi_page_block_size` to account for padding + if (bsize <= MI_LARGE_OBJ_SIZE_MAX) { + mi_heap_stat_increase(heap, large, bsize); + mi_heap_stat_counter_increase(heap, large_count, 1); + } + else { + mi_heap_stat_increase(heap, huge, bsize); + mi_heap_stat_counter_increase(heap, huge_count, 1); + } + } + return page; +} + + +// Allocate a page +// Note: in debug mode the size includes MI_PADDING_SIZE and might have overflowed. +static mi_page_t* mi_find_page(mi_heap_t* heap, size_t size, size_t huge_alignment) mi_attr_noexcept { + // huge allocation? + const size_t req_size = size - MI_PADDING_SIZE; // correct for padding_size in case of an overflow on `size` + if mi_unlikely(req_size > (MI_MEDIUM_OBJ_SIZE_MAX - MI_PADDING_SIZE) || huge_alignment > 0) { + if mi_unlikely(req_size > PTRDIFF_MAX) { // we don't allocate more than PTRDIFF_MAX (see ) + _mi_error_message(EOVERFLOW, "allocation request is too large (%zu bytes)\n", req_size); + return NULL; + } + else { + return mi_large_huge_page_alloc(heap,size,huge_alignment); + } + } + else { + // otherwise find a page with free blocks in our size segregated queues + #if MI_PADDING + mi_assert_internal(size >= MI_PADDING_SIZE); + #endif + return mi_find_free_page(heap, size); + } +} + +// Generic allocation routine if the fast path (`alloc.c:mi_page_malloc`) does not succeed. +// Note: in debug mode the size includes MI_PADDING_SIZE and might have overflowed. +// The `huge_alignment` is normally 0 but is set to a multiple of MI_SEGMENT_SIZE for +// very large requested alignments in which case we use a huge segment. +void* _mi_malloc_generic(mi_heap_t* heap, size_t size, bool zero, size_t huge_alignment) mi_attr_noexcept +{ + mi_assert_internal(heap != NULL); + + // initialize if necessary + if mi_unlikely(!mi_heap_is_initialized(heap)) { + heap = mi_heap_get_default(); // calls mi_thread_init + if mi_unlikely(!mi_heap_is_initialized(heap)) { return NULL; } + } + mi_assert_internal(mi_heap_is_initialized(heap)); + + // call potential deferred free routines + _mi_deferred_free(heap, false); + + // free delayed frees from other threads (but skip contended ones) + _mi_heap_delayed_free_partial(heap); + + // find (or allocate) a page of the right size + mi_page_t* page = mi_find_page(heap, size, huge_alignment); + if mi_unlikely(page == NULL) { // first time out of memory, try to collect and retry the allocation once more + mi_heap_collect(heap, true /* force */); + page = mi_find_page(heap, size, huge_alignment); + } + + if mi_unlikely(page == NULL) { // out of memory + const size_t req_size = size - MI_PADDING_SIZE; // correct for padding_size in case of an overflow on `size` + _mi_error_message(ENOMEM, "unable to allocate memory (%zu bytes)\n", req_size); + return NULL; + } + + mi_assert_internal(mi_page_immediate_available(page)); + mi_assert_internal(mi_page_block_size(page) >= size); + + // and try again, this time succeeding! (i.e. this should never recurse through _mi_page_malloc) + if mi_unlikely(zero && page->xblock_size == 0) { + // note: we cannot call _mi_page_malloc with zeroing for huge blocks; we zero it afterwards in that case. + void* p = _mi_page_malloc(heap, page, size, false); + mi_assert_internal(p != NULL); + _mi_memzero_aligned(p, mi_page_usable_block_size(page)); + return p; + } + else { + return _mi_page_malloc(heap, page, size, zero); + } +} diff --git a/Objects/mimalloc/prim/osx/alloc-override-zone.c b/Objects/mimalloc/prim/osx/alloc-override-zone.c new file mode 100644 index 00000000000000..0e0a99d9388c8a --- /dev/null +++ b/Objects/mimalloc/prim/osx/alloc-override-zone.c @@ -0,0 +1,458 @@ +/* ---------------------------------------------------------------------------- +Copyright (c) 2018-2022, Microsoft Research, Daan Leijen +This is free software; you can redistribute it and/or modify it under the +terms of the MIT license. A copy of the license can be found in the file +"LICENSE" at the root of this distribution. +-----------------------------------------------------------------------------*/ + +#include "mimalloc.h" +#include "mimalloc/internal.h" + +#if defined(MI_MALLOC_OVERRIDE) + +#if !defined(__APPLE__) +#error "this file should only be included on macOS" +#endif + +/* ------------------------------------------------------ + Override system malloc on macOS + This is done through the malloc zone interface. + It seems to be most robust in combination with interposing + though or otherwise we may get zone errors as there are could + be allocations done by the time we take over the + zone. +------------------------------------------------------ */ + +#include +#include +#include // memset +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(MAC_OS_X_VERSION_10_6) && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6) +// only available from OSX 10.6 +extern malloc_zone_t* malloc_default_purgeable_zone(void) __attribute__((weak_import)); +#endif + +/* ------------------------------------------------------ + malloc zone members +------------------------------------------------------ */ + +static size_t zone_size(malloc_zone_t* zone, const void* p) { + MI_UNUSED(zone); + if (!mi_is_in_heap_region(p)){ return 0; } // not our pointer, bail out + return mi_usable_size(p); +} + +static void* zone_malloc(malloc_zone_t* zone, size_t size) { + MI_UNUSED(zone); + return mi_malloc(size); +} + +static void* zone_calloc(malloc_zone_t* zone, size_t count, size_t size) { + MI_UNUSED(zone); + return mi_calloc(count, size); +} + +static void* zone_valloc(malloc_zone_t* zone, size_t size) { + MI_UNUSED(zone); + return mi_malloc_aligned(size, _mi_os_page_size()); +} + +static void zone_free(malloc_zone_t* zone, void* p) { + MI_UNUSED(zone); + mi_cfree(p); +} + +static void* zone_realloc(malloc_zone_t* zone, void* p, size_t newsize) { + MI_UNUSED(zone); + return mi_realloc(p, newsize); +} + +static void* zone_memalign(malloc_zone_t* zone, size_t alignment, size_t size) { + MI_UNUSED(zone); + return mi_malloc_aligned(size,alignment); +} + +static void zone_destroy(malloc_zone_t* zone) { + MI_UNUSED(zone); + // todo: ignore for now? +} + +static unsigned zone_batch_malloc(malloc_zone_t* zone, size_t size, void** ps, unsigned count) { + size_t i; + for (i = 0; i < count; i++) { + ps[i] = zone_malloc(zone, size); + if (ps[i] == NULL) break; + } + return i; +} + +static void zone_batch_free(malloc_zone_t* zone, void** ps, unsigned count) { + for(size_t i = 0; i < count; i++) { + zone_free(zone, ps[i]); + ps[i] = NULL; + } +} + +static size_t zone_pressure_relief(malloc_zone_t* zone, size_t size) { + MI_UNUSED(zone); MI_UNUSED(size); + mi_collect(false); + return 0; +} + +static void zone_free_definite_size(malloc_zone_t* zone, void* p, size_t size) { + MI_UNUSED(size); + zone_free(zone,p); +} + +static boolean_t zone_claimed_address(malloc_zone_t* zone, void* p) { + MI_UNUSED(zone); + return mi_is_in_heap_region(p); +} + + +/* ------------------------------------------------------ + Introspection members +------------------------------------------------------ */ + +static kern_return_t intro_enumerator(task_t task, void* p, + unsigned type_mask, vm_address_t zone_address, + memory_reader_t reader, + vm_range_recorder_t recorder) +{ + // todo: enumerate all memory + MI_UNUSED(task); MI_UNUSED(p); MI_UNUSED(type_mask); MI_UNUSED(zone_address); + MI_UNUSED(reader); MI_UNUSED(recorder); + return KERN_SUCCESS; +} + +static size_t intro_good_size(malloc_zone_t* zone, size_t size) { + MI_UNUSED(zone); + return mi_good_size(size); +} + +static boolean_t intro_check(malloc_zone_t* zone) { + MI_UNUSED(zone); + return true; +} + +static void intro_print(malloc_zone_t* zone, boolean_t verbose) { + MI_UNUSED(zone); MI_UNUSED(verbose); + mi_stats_print(NULL); +} + +static void intro_log(malloc_zone_t* zone, void* p) { + MI_UNUSED(zone); MI_UNUSED(p); + // todo? +} + +static void intro_force_lock(malloc_zone_t* zone) { + MI_UNUSED(zone); + // todo? +} + +static void intro_force_unlock(malloc_zone_t* zone) { + MI_UNUSED(zone); + // todo? +} + +static void intro_statistics(malloc_zone_t* zone, malloc_statistics_t* stats) { + MI_UNUSED(zone); + // todo... + stats->blocks_in_use = 0; + stats->size_in_use = 0; + stats->max_size_in_use = 0; + stats->size_allocated = 0; +} + +static boolean_t intro_zone_locked(malloc_zone_t* zone) { + MI_UNUSED(zone); + return false; +} + + +/* ------------------------------------------------------ + At process start, override the default allocator +------------------------------------------------------ */ + +#if defined(__GNUC__) && !defined(__clang__) +#pragma GCC diagnostic ignored "-Wmissing-field-initializers" +#endif + +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wc99-extensions" +#endif + +static malloc_introspection_t mi_introspect = { + .enumerator = &intro_enumerator, + .good_size = &intro_good_size, + .check = &intro_check, + .print = &intro_print, + .log = &intro_log, + .force_lock = &intro_force_lock, + .force_unlock = &intro_force_unlock, +#if defined(MAC_OS_X_VERSION_10_6) && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6) && !defined(__ppc__) + .statistics = &intro_statistics, + .zone_locked = &intro_zone_locked, +#endif +}; + +static malloc_zone_t mi_malloc_zone = { + // note: even with designators, the order is important for C++ compilation + //.reserved1 = NULL, + //.reserved2 = NULL, + .size = &zone_size, + .malloc = &zone_malloc, + .calloc = &zone_calloc, + .valloc = &zone_valloc, + .free = &zone_free, + .realloc = &zone_realloc, + .destroy = &zone_destroy, + .zone_name = "mimalloc", + .batch_malloc = &zone_batch_malloc, + .batch_free = &zone_batch_free, + .introspect = &mi_introspect, +#if defined(MAC_OS_X_VERSION_10_6) && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6) && !defined(__ppc__) + #if defined(MAC_OS_X_VERSION_10_14) && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_14) + .version = 10, + #else + .version = 9, + #endif + // switch to version 9+ on OSX 10.6 to support memalign. + .memalign = &zone_memalign, + .free_definite_size = &zone_free_definite_size, + .pressure_relief = &zone_pressure_relief, + #if defined(MAC_OS_X_VERSION_10_14) && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_14) + .claimed_address = &zone_claimed_address, + #endif +#else + .version = 4, +#endif +}; + +#ifdef __cplusplus +} +#endif + + +#if defined(MI_OSX_INTERPOSE) && defined(MI_SHARED_LIB_EXPORT) + +// ------------------------------------------------------ +// Override malloc_xxx and malloc_zone_xxx api's to use only +// our mimalloc zone. Since even the loader uses malloc +// on macOS, this ensures that all allocations go through +// mimalloc (as all calls are interposed). +// The main `malloc`, `free`, etc calls are interposed in `alloc-override.c`, +// Here, we also override macOS specific API's like +// `malloc_zone_calloc` etc. see +// ------------------------------------------------------ + +static inline malloc_zone_t* mi_get_default_zone(void) +{ + static bool init; + if mi_unlikely(!init) { + init = true; + malloc_zone_register(&mi_malloc_zone); // by calling register we avoid a zone error on free (see ) + } + return &mi_malloc_zone; +} + +mi_decl_externc int malloc_jumpstart(uintptr_t cookie); +mi_decl_externc void _malloc_fork_prepare(void); +mi_decl_externc void _malloc_fork_parent(void); +mi_decl_externc void _malloc_fork_child(void); + + +static malloc_zone_t* mi_malloc_create_zone(vm_size_t size, unsigned flags) { + MI_UNUSED(size); MI_UNUSED(flags); + return mi_get_default_zone(); +} + +static malloc_zone_t* mi_malloc_default_zone (void) { + return mi_get_default_zone(); +} + +static malloc_zone_t* mi_malloc_default_purgeable_zone(void) { + return mi_get_default_zone(); +} + +static void mi_malloc_destroy_zone(malloc_zone_t* zone) { + MI_UNUSED(zone); + // nothing. +} + +static kern_return_t mi_malloc_get_all_zones (task_t task, memory_reader_t mr, vm_address_t** addresses, unsigned* count) { + MI_UNUSED(task); MI_UNUSED(mr); + if (addresses != NULL) *addresses = NULL; + if (count != NULL) *count = 0; + return KERN_SUCCESS; +} + +static const char* mi_malloc_get_zone_name(malloc_zone_t* zone) { + return (zone == NULL ? mi_malloc_zone.zone_name : zone->zone_name); +} + +static void mi_malloc_set_zone_name(malloc_zone_t* zone, const char* name) { + MI_UNUSED(zone); MI_UNUSED(name); +} + +static int mi_malloc_jumpstart(uintptr_t cookie) { + MI_UNUSED(cookie); + return 1; // or 0 for no error? +} + +static void mi__malloc_fork_prepare(void) { + // nothing +} +static void mi__malloc_fork_parent(void) { + // nothing +} +static void mi__malloc_fork_child(void) { + // nothing +} + +static void mi_malloc_printf(const char* fmt, ...) { + MI_UNUSED(fmt); +} + +static bool zone_check(malloc_zone_t* zone) { + MI_UNUSED(zone); + return true; +} + +static malloc_zone_t* zone_from_ptr(const void* p) { + MI_UNUSED(p); + return mi_get_default_zone(); +} + +static void zone_log(malloc_zone_t* zone, void* p) { + MI_UNUSED(zone); MI_UNUSED(p); +} + +static void zone_print(malloc_zone_t* zone, bool b) { + MI_UNUSED(zone); MI_UNUSED(b); +} + +static void zone_print_ptr_info(void* p) { + MI_UNUSED(p); +} + +static void zone_register(malloc_zone_t* zone) { + MI_UNUSED(zone); +} + +static void zone_unregister(malloc_zone_t* zone) { + MI_UNUSED(zone); +} + +// use interposing so `DYLD_INSERT_LIBRARIES` works without `DYLD_FORCE_FLAT_NAMESPACE=1` +// See: +struct mi_interpose_s { + const void* replacement; + const void* target; +}; +#define MI_INTERPOSE_FUN(oldfun,newfun) { (const void*)&newfun, (const void*)&oldfun } +#define MI_INTERPOSE_MI(fun) MI_INTERPOSE_FUN(fun,mi_##fun) +#define MI_INTERPOSE_ZONE(fun) MI_INTERPOSE_FUN(malloc_##fun,fun) +__attribute__((used)) static const struct mi_interpose_s _mi_zone_interposes[] __attribute__((section("__DATA, __interpose"))) = +{ + + MI_INTERPOSE_MI(malloc_create_zone), + MI_INTERPOSE_MI(malloc_default_purgeable_zone), + MI_INTERPOSE_MI(malloc_default_zone), + MI_INTERPOSE_MI(malloc_destroy_zone), + MI_INTERPOSE_MI(malloc_get_all_zones), + MI_INTERPOSE_MI(malloc_get_zone_name), + MI_INTERPOSE_MI(malloc_jumpstart), + MI_INTERPOSE_MI(malloc_printf), + MI_INTERPOSE_MI(malloc_set_zone_name), + MI_INTERPOSE_MI(_malloc_fork_child), + MI_INTERPOSE_MI(_malloc_fork_parent), + MI_INTERPOSE_MI(_malloc_fork_prepare), + + MI_INTERPOSE_ZONE(zone_batch_free), + MI_INTERPOSE_ZONE(zone_batch_malloc), + MI_INTERPOSE_ZONE(zone_calloc), + MI_INTERPOSE_ZONE(zone_check), + MI_INTERPOSE_ZONE(zone_free), + MI_INTERPOSE_ZONE(zone_from_ptr), + MI_INTERPOSE_ZONE(zone_log), + MI_INTERPOSE_ZONE(zone_malloc), + MI_INTERPOSE_ZONE(zone_memalign), + MI_INTERPOSE_ZONE(zone_print), + MI_INTERPOSE_ZONE(zone_print_ptr_info), + MI_INTERPOSE_ZONE(zone_realloc), + MI_INTERPOSE_ZONE(zone_register), + MI_INTERPOSE_ZONE(zone_unregister), + MI_INTERPOSE_ZONE(zone_valloc) +}; + + +#else + +// ------------------------------------------------------ +// hook into the zone api's without interposing +// This is the official way of adding an allocator but +// it seems less robust than using interpose. +// ------------------------------------------------------ + +static inline malloc_zone_t* mi_get_default_zone(void) +{ + // The first returned zone is the real default + malloc_zone_t** zones = NULL; + unsigned count = 0; + kern_return_t ret = malloc_get_all_zones(0, NULL, (vm_address_t**)&zones, &count); + if (ret == KERN_SUCCESS && count > 0) { + return zones[0]; + } + else { + // fallback + return malloc_default_zone(); + } +} + +#if defined(__clang__) +__attribute__((constructor(0))) +#else +__attribute__((constructor)) // seems not supported by g++-11 on the M1 +#endif +static void _mi_macos_override_malloc(void) { + malloc_zone_t* purgeable_zone = NULL; + + #if defined(MAC_OS_X_VERSION_10_6) && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6) + // force the purgeable zone to exist to avoid strange bugs + if (malloc_default_purgeable_zone) { + purgeable_zone = malloc_default_purgeable_zone(); + } + #endif + + // Register our zone. + // thomcc: I think this is still needed to put us in the zone list. + malloc_zone_register(&mi_malloc_zone); + // Unregister the default zone, this makes our zone the new default + // as that was the last registered. + malloc_zone_t *default_zone = mi_get_default_zone(); + // thomcc: Unsure if the next test is *always* false or just false in the + // cases I've tried. I'm also unsure if the code inside is needed. at all + if (default_zone != &mi_malloc_zone) { + malloc_zone_unregister(default_zone); + + // Reregister the default zone so free and realloc in that zone keep working. + malloc_zone_register(default_zone); + } + + // Unregister, and re-register the purgeable_zone to avoid bugs if it occurs + // earlier than the default zone. + if (purgeable_zone != NULL) { + malloc_zone_unregister(purgeable_zone); + malloc_zone_register(purgeable_zone); + } + +} +#endif // MI_OSX_INTERPOSE + +#endif // MI_MALLOC_OVERRIDE diff --git a/Objects/mimalloc/prim/osx/prim.c b/Objects/mimalloc/prim/osx/prim.c new file mode 100644 index 00000000000000..8a2f4e8aa47316 --- /dev/null +++ b/Objects/mimalloc/prim/osx/prim.c @@ -0,0 +1,9 @@ +/* ---------------------------------------------------------------------------- +Copyright (c) 2018-2023, Microsoft Research, Daan Leijen +This is free software; you can redistribute it and/or modify it under the +terms of the MIT license. A copy of the license can be found in the file +"LICENSE" at the root of this distribution. +-----------------------------------------------------------------------------*/ + +// We use the unix/prim.c with the mmap API on macOSX +#include "../unix/prim.c" diff --git a/Objects/mimalloc/prim/prim.c b/Objects/mimalloc/prim/prim.c new file mode 100644 index 00000000000000..9a597d8eb603e9 --- /dev/null +++ b/Objects/mimalloc/prim/prim.c @@ -0,0 +1,24 @@ +/* ---------------------------------------------------------------------------- +Copyright (c) 2018-2023, Microsoft Research, Daan Leijen +This is free software; you can redistribute it and/or modify it under the +terms of the MIT license. A copy of the license can be found in the file +"LICENSE" at the root of this distribution. +-----------------------------------------------------------------------------*/ + +// Select the implementation of the primitives +// depending on the OS. + +#if defined(_WIN32) +#include "windows/prim.c" // VirtualAlloc (Windows) + +#elif defined(__APPLE__) +#include "osx/prim.c" // macOSX (actually defers to mmap in unix/prim.c) + +#elif defined(__wasi__) +#define MI_USE_SBRK +#include "wasi/prim.c" // memory-grow or sbrk (Wasm) + +#else +#include "unix/prim.c" // mmap() (Linux, macOSX, BSD, Illumnos, Haiku, DragonFly, etc.) + +#endif diff --git a/Objects/mimalloc/prim/readme.md b/Objects/mimalloc/prim/readme.md new file mode 100644 index 00000000000000..380dd3a7178419 --- /dev/null +++ b/Objects/mimalloc/prim/readme.md @@ -0,0 +1,9 @@ +## Portability Primitives + +This is the portability layer where all primitives needed from the OS are defined. + +- `include/mimalloc/prim.h`: primitive portability API definition. +- `prim.c`: Selects one of `unix/prim.c`, `wasi/prim.c`, or `windows/prim.c` depending on the host platform + (and on macOS, `osx/prim.c` defers to `unix/prim.c`). + +Note: still work in progress, there may still be places in the sources that still depend on OS ifdef's. \ No newline at end of file diff --git a/Objects/mimalloc/prim/unix/prim.c b/Objects/mimalloc/prim/unix/prim.c new file mode 100644 index 00000000000000..ec8447ab40d70c --- /dev/null +++ b/Objects/mimalloc/prim/unix/prim.c @@ -0,0 +1,859 @@ +/* ---------------------------------------------------------------------------- +Copyright (c) 2018-2023, Microsoft Research, Daan Leijen +This is free software; you can redistribute it and/or modify it under the +terms of the MIT license. A copy of the license can be found in the file +"LICENSE" at the root of this distribution. +-----------------------------------------------------------------------------*/ + +// This file is included in `src/prim/prim.c` + +#ifndef _DEFAULT_SOURCE +#define _DEFAULT_SOURCE // ensure mmap flags and syscall are defined +#endif + +#if defined(__sun) +// illumos provides new mman.h api when any of these are defined +// otherwise the old api based on caddr_t which predates the void pointers one. +// stock solaris provides only the former, chose to atomically to discard those +// flags only here rather than project wide tough. +#undef _XOPEN_SOURCE +#undef _POSIX_C_SOURCE +#endif + +#include "mimalloc.h" +#include "mimalloc/internal.h" +#include "mimalloc/atomic.h" +#include "mimalloc/prim.h" + +#include // mmap +#include // sysconf + +#if defined(__linux__) + #include + #include + #if defined(__GLIBC__) + #include // linux mmap flags + #else + #include + #endif +#elif defined(__APPLE__) + #include + #if !TARGET_IOS_IPHONE && !TARGET_IOS_SIMULATOR + #include + #endif +#elif defined(__FreeBSD__) || defined(__DragonFly__) + #include + #if __FreeBSD_version >= 1200000 + #include + #include + #endif + #include +#endif + +#if !defined(__HAIKU__) && !defined(__APPLE__) && !defined(__CYGWIN__) && !defined(_AIX) && !defined(__FreeBSD__) && !defined(__sun) + #define MI_HAS_SYSCALL_H + #include +#endif + +//------------------------------------------------------------------------------------ +// Use syscalls for some primitives to allow for libraries that override open/read/close etc. +// and do allocation themselves; using syscalls prevents recursion when mimalloc is +// still initializing (issue #713) +//------------------------------------------------------------------------------------ + +#if defined(MI_HAS_SYSCALL_H) && defined(SYS_open) && defined(SYS_close) && defined(SYS_read) && defined(SYS_access) + +static int mi_prim_open(const char* fpath, int open_flags) { + return syscall(SYS_open,fpath,open_flags,0); +} +static ssize_t mi_prim_read(int fd, void* buf, size_t bufsize) { + return syscall(SYS_read,fd,buf,bufsize); +} +static int mi_prim_close(int fd) { + return syscall(SYS_close,fd); +} +static int mi_prim_access(const char *fpath, int mode) { + return syscall(SYS_access,fpath,mode); +} + +#elif !defined(__APPLE__) && !defined(_AIX) && !defined(__FreeBSD__) && !defined(__sun) // avoid unused warnings + +static int mi_prim_open(const char* fpath, int open_flags) { + return open(fpath,open_flags); +} +static ssize_t mi_prim_read(int fd, void* buf, size_t bufsize) { + return read(fd,buf,bufsize); +} +static int mi_prim_close(int fd) { + return close(fd); +} +static int mi_prim_access(const char *fpath, int mode) { + return access(fpath,mode); +} + +#endif + + + +//--------------------------------------------- +// init +//--------------------------------------------- + +static bool unix_detect_overcommit(void) { + bool os_overcommit = true; +#if defined(__linux__) + int fd = mi_prim_open("/proc/sys/vm/overcommit_memory", O_RDONLY); + if (fd >= 0) { + char buf[32] = {0}; + ssize_t nread = mi_prim_read(fd, &buf, sizeof(buf)); + mi_prim_close(fd); + // + // 0: heuristic overcommit, 1: always overcommit, 2: never overcommit (ignore NORESERVE) + if (nread >= 1) { + os_overcommit = (buf[0] == '0' || buf[0] == '1'); + } + } +#elif defined(__FreeBSD__) + int val = 0; + size_t olen = sizeof(val); + if (sysctlbyname("vm.overcommit", &val, &olen, NULL, 0) == 0) { + os_overcommit = (val != 0); + } +#else + // default: overcommit is true +#endif + return os_overcommit; +} + +void _mi_prim_mem_init( mi_os_mem_config_t* config ) { + long psize = sysconf(_SC_PAGESIZE); + if (psize > 0) { + config->page_size = (size_t)psize; + config->alloc_granularity = (size_t)psize; + } + config->large_page_size = 2*MI_MiB; // TODO: can we query the OS for this? + config->has_overcommit = unix_detect_overcommit(); + config->must_free_whole = false; // mmap can free in parts + config->has_virtual_reserve = true; // todo: check if this true for NetBSD? (for anonymous mmap with PROT_NONE) +} + + +//--------------------------------------------- +// free +//--------------------------------------------- + +int _mi_prim_free(void* addr, size_t size ) { + bool err = (munmap(addr, size) == -1); + return (err ? errno : 0); +} + + +//--------------------------------------------- +// mmap +//--------------------------------------------- + +static int unix_madvise(void* addr, size_t size, int advice) { + #if defined(__sun) + return madvise((caddr_t)addr, size, advice); // Solaris needs cast (issue #520) + #else + return madvise(addr, size, advice); + #endif +} + +static void* unix_mmap_prim(void* addr, size_t size, size_t try_alignment, int protect_flags, int flags, int fd) { + MI_UNUSED(try_alignment); + void* p = NULL; + #if defined(MAP_ALIGNED) // BSD + if (addr == NULL && try_alignment > 1 && (try_alignment % _mi_os_page_size()) == 0) { + size_t n = mi_bsr(try_alignment); + if (((size_t)1 << n) == try_alignment && n >= 12 && n <= 30) { // alignment is a power of 2 and 4096 <= alignment <= 1GiB + p = mmap(addr, size, protect_flags, flags | MAP_ALIGNED(n), fd, 0); + if (p==MAP_FAILED || !_mi_is_aligned(p,try_alignment)) { + int err = errno; + _mi_verbose_message("unable to directly request aligned OS memory (error: %d (0x%x), size: 0x%zx bytes, alignment: 0x%zx, hint address: %p)\n", err, err, size, try_alignment, addr); + } + if (p!=MAP_FAILED) return p; + // fall back to regular mmap + } + } + #elif defined(MAP_ALIGN) // Solaris + if (addr == NULL && try_alignment > 1 && (try_alignment % _mi_os_page_size()) == 0) { + p = mmap((void*)try_alignment, size, protect_flags, flags | MAP_ALIGN, fd, 0); // addr parameter is the required alignment + if (p!=MAP_FAILED) return p; + // fall back to regular mmap + } + #endif + #if (MI_INTPTR_SIZE >= 8) && !defined(MAP_ALIGNED) + // on 64-bit systems, use the virtual address area after 2TiB for 4MiB aligned allocations + if (addr == NULL) { + void* hint = _mi_os_get_aligned_hint(try_alignment, size); + if (hint != NULL) { + p = mmap(hint, size, protect_flags, flags, fd, 0); + if (p==MAP_FAILED || !_mi_is_aligned(p,try_alignment)) { + #if MI_TRACK_ENABLED // asan sometimes does not instrument errno correctly? + int err = 0; + #else + int err = errno; + #endif + _mi_verbose_message("unable to directly request hinted aligned OS memory (error: %d (0x%x), size: 0x%zx bytes, alignment: 0x%zx, hint address: %p)\n", err, err, size, try_alignment, hint); + } + if (p!=MAP_FAILED) return p; + // fall back to regular mmap + } + } + #endif + // regular mmap + p = mmap(addr, size, protect_flags, flags, fd, 0); + if (p!=MAP_FAILED) return p; + // failed to allocate + return NULL; +} + +static int unix_mmap_fd(void) { + #if defined(VM_MAKE_TAG) + // macOS: tracking anonymous page with a specific ID. (All up to 98 are taken officially but LLVM sanitizers had taken 99) + int os_tag = (int)mi_option_get(mi_option_os_tag); + if (os_tag < 100 || os_tag > 255) { os_tag = 100; } + return VM_MAKE_TAG(os_tag); + #else + return -1; + #endif +} + +static void* unix_mmap(void* addr, size_t size, size_t try_alignment, int protect_flags, bool large_only, bool allow_large, bool* is_large) { + #if !defined(MAP_ANONYMOUS) + #define MAP_ANONYMOUS MAP_ANON + #endif + #if !defined(MAP_NORESERVE) + #define MAP_NORESERVE 0 + #endif + void* p = NULL; + const int fd = unix_mmap_fd(); + int flags = MAP_PRIVATE | MAP_ANONYMOUS; + if (_mi_os_has_overcommit()) { + flags |= MAP_NORESERVE; + } + #if defined(PROT_MAX) + protect_flags |= PROT_MAX(PROT_READ | PROT_WRITE); // BSD + #endif + // huge page allocation + if ((large_only || _mi_os_use_large_page(size, try_alignment)) && allow_large) { + static _Atomic(size_t) large_page_try_ok; // = 0; + size_t try_ok = mi_atomic_load_acquire(&large_page_try_ok); + if (!large_only && try_ok > 0) { + // If the OS is not configured for large OS pages, or the user does not have + // enough permission, the `mmap` will always fail (but it might also fail for other reasons). + // Therefore, once a large page allocation failed, we don't try again for `large_page_try_ok` times + // to avoid too many failing calls to mmap. + mi_atomic_cas_strong_acq_rel(&large_page_try_ok, &try_ok, try_ok - 1); + } + else { + int lflags = flags & ~MAP_NORESERVE; // using NORESERVE on huge pages seems to fail on Linux + int lfd = fd; + #ifdef MAP_ALIGNED_SUPER + lflags |= MAP_ALIGNED_SUPER; + #endif + #ifdef MAP_HUGETLB + lflags |= MAP_HUGETLB; + #endif + #ifdef MAP_HUGE_1GB + static bool mi_huge_pages_available = true; + if ((size % MI_GiB) == 0 && mi_huge_pages_available) { + lflags |= MAP_HUGE_1GB; + } + else + #endif + { + #ifdef MAP_HUGE_2MB + lflags |= MAP_HUGE_2MB; + #endif + } + #ifdef VM_FLAGS_SUPERPAGE_SIZE_2MB + lfd |= VM_FLAGS_SUPERPAGE_SIZE_2MB; + #endif + if (large_only || lflags != flags) { + // try large OS page allocation + *is_large = true; + p = unix_mmap_prim(addr, size, try_alignment, protect_flags, lflags, lfd); + #ifdef MAP_HUGE_1GB + if (p == NULL && (lflags & MAP_HUGE_1GB) != 0) { + mi_huge_pages_available = false; // don't try huge 1GiB pages again + _mi_warning_message("unable to allocate huge (1GiB) page, trying large (2MiB) pages instead (errno: %i)\n", errno); + lflags = ((lflags & ~MAP_HUGE_1GB) | MAP_HUGE_2MB); + p = unix_mmap_prim(addr, size, try_alignment, protect_flags, lflags, lfd); + } + #endif + if (large_only) return p; + if (p == NULL) { + mi_atomic_store_release(&large_page_try_ok, (size_t)8); // on error, don't try again for the next N allocations + } + } + } + } + // regular allocation + if (p == NULL) { + *is_large = false; + p = unix_mmap_prim(addr, size, try_alignment, protect_flags, flags, fd); + if (p != NULL) { + #if defined(MADV_HUGEPAGE) + // Many Linux systems don't allow MAP_HUGETLB but they support instead + // transparent huge pages (THP). Generally, it is not required to call `madvise` with MADV_HUGE + // though since properly aligned allocations will already use large pages if available + // in that case -- in particular for our large regions (in `memory.c`). + // However, some systems only allow THP if called with explicit `madvise`, so + // when large OS pages are enabled for mimalloc, we call `madvise` anyways. + if (allow_large && _mi_os_use_large_page(size, try_alignment)) { + if (unix_madvise(p, size, MADV_HUGEPAGE) == 0) { + *is_large = true; // possibly + }; + } + #elif defined(__sun) + if (allow_large && _mi_os_use_large_page(size, try_alignment)) { + struct memcntl_mha cmd = {0}; + cmd.mha_pagesize = 2*MI_MiB; + cmd.mha_cmd = MHA_MAPSIZE_VA; + if (memcntl((caddr_t)p, size, MC_HAT_ADVISE, (caddr_t)&cmd, 0, 0) == 0) { + *is_large = true; + } + } + #endif + } + } + return p; +} + +// Note: the `try_alignment` is just a hint and the returned pointer is not guaranteed to be aligned. +int _mi_prim_alloc(size_t size, size_t try_alignment, bool commit, bool allow_large, bool* is_large, bool* is_zero, void** addr) { + mi_assert_internal(size > 0 && (size % _mi_os_page_size()) == 0); + mi_assert_internal(commit || !allow_large); + mi_assert_internal(try_alignment > 0); + + *is_zero = true; + int protect_flags = (commit ? (PROT_WRITE | PROT_READ) : PROT_NONE); + *addr = unix_mmap(NULL, size, try_alignment, protect_flags, false, allow_large, is_large); + return (*addr != NULL ? 0 : errno); +} + + +//--------------------------------------------- +// Commit/Reset +//--------------------------------------------- + +static void unix_mprotect_hint(int err) { + #if defined(__linux__) && (MI_SECURE>=2) // guard page around every mimalloc page + if (err == ENOMEM) { + _mi_warning_message("The next warning may be caused by a low memory map limit.\n" + " On Linux this is controlled by the vm.max_map_count -- maybe increase it?\n" + " For example: sudo sysctl -w vm.max_map_count=262144\n"); + } + #else + MI_UNUSED(err); + #endif +} + +int _mi_prim_commit(void* start, size_t size, bool* is_zero) { + // commit: ensure we can access the area + // note: we may think that *is_zero can be true since the memory + // was either from mmap PROT_NONE, or from decommit MADV_DONTNEED, but + // we sometimes call commit on a range with still partially committed + // memory and `mprotect` does not zero the range. + *is_zero = false; + int err = mprotect(start, size, (PROT_READ | PROT_WRITE)); + if (err != 0) { + err = errno; + unix_mprotect_hint(err); + } + return err; +} + +int _mi_prim_decommit(void* start, size_t size, bool* needs_recommit) { + int err = 0; + // decommit: use MADV_DONTNEED as it decreases rss immediately (unlike MADV_FREE) + err = unix_madvise(start, size, MADV_DONTNEED); + #if !MI_DEBUG && !MI_SECURE + *needs_recommit = false; + #else + *needs_recommit = true; + mprotect(start, size, PROT_NONE); + #endif + /* + // decommit: use mmap with MAP_FIXED and PROT_NONE to discard the existing memory (and reduce rss) + *needs_recommit = true; + const int fd = unix_mmap_fd(); + void* p = mmap(start, size, PROT_NONE, (MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE), fd, 0); + if (p != start) { err = errno; } + */ + return err; +} + +int _mi_prim_reset(void* start, size_t size) { + // We try to use `MADV_FREE` as that is the fastest. A drawback though is that it + // will not reduce the `rss` stats in tools like `top` even though the memory is available + // to other processes. With the default `MIMALLOC_PURGE_DECOMMITS=1` we ensure that by + // default `MADV_DONTNEED` is used though. + #if defined(MADV_FREE) + static _Atomic(size_t) advice = MI_ATOMIC_VAR_INIT(MADV_FREE); + int oadvice = (int)mi_atomic_load_relaxed(&advice); + int err; + while ((err = unix_madvise(start, size, oadvice)) != 0 && errno == EAGAIN) { errno = 0; }; + if (err != 0 && errno == EINVAL && oadvice == MADV_FREE) { + // if MADV_FREE is not supported, fall back to MADV_DONTNEED from now on + mi_atomic_store_release(&advice, (size_t)MADV_DONTNEED); + err = unix_madvise(start, size, MADV_DONTNEED); + } + #else + int err = unix_madvise(start, size, MADV_DONTNEED); + #endif + return err; +} + +int _mi_prim_protect(void* start, size_t size, bool protect) { + int err = mprotect(start, size, protect ? PROT_NONE : (PROT_READ | PROT_WRITE)); + if (err != 0) { err = errno; } + unix_mprotect_hint(err); + return err; +} + + + +//--------------------------------------------- +// Huge page allocation +//--------------------------------------------- + +#if (MI_INTPTR_SIZE >= 8) && !defined(__HAIKU__) && !defined(__CYGWIN__) + +#ifndef MPOL_PREFERRED +#define MPOL_PREFERRED 1 +#endif + +#if defined(MI_HAS_SYSCALL_H) && defined(SYS_mbind) +static long mi_prim_mbind(void* start, unsigned long len, unsigned long mode, const unsigned long* nmask, unsigned long maxnode, unsigned flags) { + return syscall(SYS_mbind, start, len, mode, nmask, maxnode, flags); +} +#else +static long mi_prim_mbind(void* start, unsigned long len, unsigned long mode, const unsigned long* nmask, unsigned long maxnode, unsigned flags) { + MI_UNUSED(start); MI_UNUSED(len); MI_UNUSED(mode); MI_UNUSED(nmask); MI_UNUSED(maxnode); MI_UNUSED(flags); + return 0; +} +#endif + +int _mi_prim_alloc_huge_os_pages(void* hint_addr, size_t size, int numa_node, bool* is_zero, void** addr) { + bool is_large = true; + *is_zero = true; + *addr = unix_mmap(hint_addr, size, MI_SEGMENT_SIZE, PROT_READ | PROT_WRITE, true, true, &is_large); + if (*addr != NULL && numa_node >= 0 && numa_node < 8*MI_INTPTR_SIZE) { // at most 64 nodes + unsigned long numa_mask = (1UL << numa_node); + // TODO: does `mbind` work correctly for huge OS pages? should we + // use `set_mempolicy` before calling mmap instead? + // see: + long err = mi_prim_mbind(*addr, size, MPOL_PREFERRED, &numa_mask, 8*MI_INTPTR_SIZE, 0); + if (err != 0) { + err = errno; + _mi_warning_message("failed to bind huge (1GiB) pages to numa node %d (error: %d (0x%x))\n", numa_node, err, err); + } + } + return (*addr != NULL ? 0 : errno); +} + +#else + +int _mi_prim_alloc_huge_os_pages(void* hint_addr, size_t size, int numa_node, bool* is_zero, void** addr) { + MI_UNUSED(hint_addr); MI_UNUSED(size); MI_UNUSED(numa_node); + *is_zero = false; + *addr = NULL; + return ENOMEM; +} + +#endif + +//--------------------------------------------- +// NUMA nodes +//--------------------------------------------- + +#if defined(__linux__) + +#include // snprintf + +size_t _mi_prim_numa_node(void) { + #if defined(MI_HAS_SYSCALL_H) && defined(SYS_getcpu) + unsigned long node = 0; + unsigned long ncpu = 0; + long err = syscall(SYS_getcpu, &ncpu, &node, NULL); + if (err != 0) return 0; + return node; + #else + return 0; + #endif +} + +size_t _mi_prim_numa_node_count(void) { + char buf[128]; + unsigned node = 0; + for(node = 0; node < 256; node++) { + // enumerate node entries -- todo: it there a more efficient way to do this? (but ensure there is no allocation) + snprintf(buf, 127, "/sys/devices/system/node/node%u", node + 1); + if (mi_prim_access(buf,R_OK) != 0) break; + } + return (node+1); +} + +#elif defined(__FreeBSD__) && __FreeBSD_version >= 1200000 + +size_t _mi_prim_numa_node(void) { + domainset_t dom; + size_t node; + int policy; + if (cpuset_getdomain(CPU_LEVEL_CPUSET, CPU_WHICH_PID, -1, sizeof(dom), &dom, &policy) == -1) return 0ul; + for (node = 0; node < MAXMEMDOM; node++) { + if (DOMAINSET_ISSET(node, &dom)) return node; + } + return 0ul; +} + +size_t _mi_prim_numa_node_count(void) { + size_t ndomains = 0; + size_t len = sizeof(ndomains); + if (sysctlbyname("vm.ndomains", &ndomains, &len, NULL, 0) == -1) return 0ul; + return ndomains; +} + +#elif defined(__DragonFly__) + +size_t _mi_prim_numa_node(void) { + // TODO: DragonFly does not seem to provide any userland means to get this information. + return 0ul; +} + +size_t _mi_prim_numa_node_count(void) { + size_t ncpus = 0, nvirtcoresperphys = 0; + size_t len = sizeof(size_t); + if (sysctlbyname("hw.ncpu", &ncpus, &len, NULL, 0) == -1) return 0ul; + if (sysctlbyname("hw.cpu_topology_ht_ids", &nvirtcoresperphys, &len, NULL, 0) == -1) return 0ul; + return nvirtcoresperphys * ncpus; +} + +#else + +size_t _mi_prim_numa_node(void) { + return 0; +} + +size_t _mi_prim_numa_node_count(void) { + return 1; +} + +#endif + +// ---------------------------------------------------------------- +// Clock +// ---------------------------------------------------------------- + +#include + +#if defined(CLOCK_REALTIME) || defined(CLOCK_MONOTONIC) + +mi_msecs_t _mi_prim_clock_now(void) { + struct timespec t; + #ifdef CLOCK_MONOTONIC + clock_gettime(CLOCK_MONOTONIC, &t); + #else + clock_gettime(CLOCK_REALTIME, &t); + #endif + return ((mi_msecs_t)t.tv_sec * 1000) + ((mi_msecs_t)t.tv_nsec / 1000000); +} + +#else + +// low resolution timer +mi_msecs_t _mi_prim_clock_now(void) { + #if !defined(CLOCKS_PER_SEC) || (CLOCKS_PER_SEC == 1000) || (CLOCKS_PER_SEC == 0) + return (mi_msecs_t)clock(); + #elif (CLOCKS_PER_SEC < 1000) + return (mi_msecs_t)clock() * (1000 / (mi_msecs_t)CLOCKS_PER_SEC); + #else + return (mi_msecs_t)clock() / ((mi_msecs_t)CLOCKS_PER_SEC / 1000); + #endif +} + +#endif + + + + +//---------------------------------------------------------------- +// Process info +//---------------------------------------------------------------- + +#if defined(__unix__) || defined(__unix) || defined(unix) || defined(__APPLE__) || defined(__HAIKU__) +#include +#include +#include + +#if defined(__APPLE__) +#include +#endif + +#if defined(__HAIKU__) +#include +#endif + +static mi_msecs_t timeval_secs(const struct timeval* tv) { + return ((mi_msecs_t)tv->tv_sec * 1000L) + ((mi_msecs_t)tv->tv_usec / 1000L); +} + +void _mi_prim_process_info(mi_process_info_t* pinfo) +{ + struct rusage rusage; + getrusage(RUSAGE_SELF, &rusage); + pinfo->utime = timeval_secs(&rusage.ru_utime); + pinfo->stime = timeval_secs(&rusage.ru_stime); +#if !defined(__HAIKU__) + pinfo->page_faults = rusage.ru_majflt; +#endif +#if defined(__HAIKU__) + // Haiku does not have (yet?) a way to + // get these stats per process + thread_info tid; + area_info mem; + ssize_t c; + get_thread_info(find_thread(0), &tid); + while (get_next_area_info(tid.team, &c, &mem) == B_OK) { + pinfo->peak_rss += mem.ram_size; + } + pinfo->page_faults = 0; +#elif defined(__APPLE__) + pinfo->peak_rss = rusage.ru_maxrss; // macos reports in bytes + #ifdef MACH_TASK_BASIC_INFO + struct mach_task_basic_info info; + mach_msg_type_number_t infoCount = MACH_TASK_BASIC_INFO_COUNT; + if (task_info(mach_task_self(), MACH_TASK_BASIC_INFO, (task_info_t)&info, &infoCount) == KERN_SUCCESS) { + pinfo->current_rss = (size_t)info.resident_size; + } + #else + struct task_basic_info info; + mach_msg_type_number_t infoCount = TASK_BASIC_INFO_COUNT; + if (task_info(mach_task_self(), TASK_BASIC_INFO, (task_info_t)&info, &infoCount) == KERN_SUCCESS) { + pinfo->current_rss = (size_t)info.resident_size; + } + #endif +#else + pinfo->peak_rss = rusage.ru_maxrss * 1024; // Linux/BSD report in KiB +#endif + // use defaults for commit +} + +#else + +#ifndef __wasi__ +// WebAssembly instances are not processes +#pragma message("define a way to get process info") +#endif + +void _mi_prim_process_info(mi_process_info_t* pinfo) +{ + // use defaults + MI_UNUSED(pinfo); +} + +#endif + + +//---------------------------------------------------------------- +// Output +//---------------------------------------------------------------- + +void _mi_prim_out_stderr( const char* msg ) { + fputs(msg,stderr); +} + + +//---------------------------------------------------------------- +// Environment +//---------------------------------------------------------------- + +#if !defined(MI_USE_ENVIRON) || (MI_USE_ENVIRON!=0) +// On Posix systemsr use `environ` to access environment variables +// even before the C runtime is initialized. +#if defined(__APPLE__) && defined(__has_include) && __has_include() +#include +static char** mi_get_environ(void) { + return (*_NSGetEnviron()); +} +#else +extern char** environ; +static char** mi_get_environ(void) { + return environ; +} +#endif +bool _mi_prim_getenv(const char* name, char* result, size_t result_size) { + if (name==NULL) return false; + const size_t len = _mi_strlen(name); + if (len == 0) return false; + char** env = mi_get_environ(); + if (env == NULL) return false; + // compare up to 10000 entries + for (int i = 0; i < 10000 && env[i] != NULL; i++) { + const char* s = env[i]; + if (_mi_strnicmp(name, s, len) == 0 && s[len] == '=') { // case insensitive + // found it + _mi_strlcpy(result, s + len + 1, result_size); + return true; + } + } + return false; +} +#else +// fallback: use standard C `getenv` but this cannot be used while initializing the C runtime +bool _mi_prim_getenv(const char* name, char* result, size_t result_size) { + // cannot call getenv() when still initializing the C runtime. + if (_mi_preloading()) return false; + const char* s = getenv(name); + if (s == NULL) { + // we check the upper case name too. + char buf[64+1]; + size_t len = _mi_strnlen(name,sizeof(buf)-1); + for (size_t i = 0; i < len; i++) { + buf[i] = _mi_toupper(name[i]); + } + buf[len] = 0; + s = getenv(buf); + } + if (s == NULL || _mi_strnlen(s,result_size) >= result_size) return false; + _mi_strlcpy(result, s, result_size); + return true; +} +#endif // !MI_USE_ENVIRON + + +//---------------------------------------------------------------- +// Random +//---------------------------------------------------------------- + +#if defined(__APPLE__) + +#include +#if defined(MAC_OS_X_VERSION_10_10) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_10 +#include +#include +#endif +bool _mi_prim_random_buf(void* buf, size_t buf_len) { + #if defined(MAC_OS_X_VERSION_10_15) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_15 + // We prefere CCRandomGenerateBytes as it returns an error code while arc4random_buf + // may fail silently on macOS. See PR #390, and + return (CCRandomGenerateBytes(buf, buf_len) == kCCSuccess); + #else + // fall back on older macOS + arc4random_buf(buf, buf_len); + return true; + #endif +} + +#elif defined(__ANDROID__) || defined(__DragonFly__) || \ + defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || \ + defined(__sun) + +#include +bool _mi_prim_random_buf(void* buf, size_t buf_len) { + arc4random_buf(buf, buf_len); + return true; +} + +#elif defined(__linux__) || defined(__HAIKU__) + +#include +#include +#include +#include + +bool _mi_prim_random_buf(void* buf, size_t buf_len) { + // Modern Linux provides `getrandom` but different distributions either use `sys/random.h` or `linux/random.h` + // and for the latter the actual `getrandom` call is not always defined. + // (see ) + // We therefore use a syscall directly and fall back dynamically to /dev/urandom when needed. + #if defined(MI_HAS_SYSCALL_H) && defined(SYS_getrandom) + #ifndef GRND_NONBLOCK + #define GRND_NONBLOCK (1) + #endif + static _Atomic(uintptr_t) no_getrandom; // = 0 + if (mi_atomic_load_acquire(&no_getrandom)==0) { + ssize_t ret = syscall(SYS_getrandom, buf, buf_len, GRND_NONBLOCK); + if (ret >= 0) return (buf_len == (size_t)ret); + if (errno != ENOSYS) return false; + mi_atomic_store_release(&no_getrandom, (uintptr_t)1); // don't call again, and fall back to /dev/urandom + } + #endif + int flags = O_RDONLY; + #if defined(O_CLOEXEC) + flags |= O_CLOEXEC; + #endif + int fd = mi_prim_open("/dev/urandom", flags); + if (fd < 0) return false; + size_t count = 0; + while(count < buf_len) { + ssize_t ret = mi_prim_read(fd, (char*)buf + count, buf_len - count); + if (ret<=0) { + if (errno!=EAGAIN && errno!=EINTR) break; + } + else { + count += ret; + } + } + mi_prim_close(fd); + return (count==buf_len); +} + +#else + +bool _mi_prim_random_buf(void* buf, size_t buf_len) { + return false; +} + +#endif + + +//---------------------------------------------------------------- +// Thread init/done +//---------------------------------------------------------------- + +#if defined(MI_USE_PTHREADS) + +// use pthread local storage keys to detect thread ending +// (and used with MI_TLS_PTHREADS for the default heap) +pthread_key_t _mi_heap_default_key = (pthread_key_t)(-1); + +static void mi_pthread_done(void* value) { + if (value!=NULL) { + _mi_thread_done((mi_heap_t*)value); + } +} + +void _mi_prim_thread_init_auto_done(void) { + mi_assert_internal(_mi_heap_default_key == (pthread_key_t)(-1)); + pthread_key_create(&_mi_heap_default_key, &mi_pthread_done); +} + +void _mi_prim_thread_done_auto_done(void) { + // nothing to do +} + +void _mi_prim_thread_associate_default_heap(mi_heap_t* heap) { + if (_mi_heap_default_key != (pthread_key_t)(-1)) { // can happen during recursive invocation on freeBSD + pthread_setspecific(_mi_heap_default_key, heap); + } +} + +#else + +void _mi_prim_thread_init_auto_done(void) { + // nothing +} + +void _mi_prim_thread_done_auto_done(void) { + // nothing +} + +void _mi_prim_thread_associate_default_heap(mi_heap_t* heap) { + MI_UNUSED(heap); +} + +#endif diff --git a/Objects/mimalloc/prim/wasi/prim.c b/Objects/mimalloc/prim/wasi/prim.c new file mode 100644 index 00000000000000..640dac0493f573 --- /dev/null +++ b/Objects/mimalloc/prim/wasi/prim.c @@ -0,0 +1,276 @@ +/* ---------------------------------------------------------------------------- +Copyright (c) 2018-2023, Microsoft Research, Daan Leijen +This is free software; you can redistribute it and/or modify it under the +terms of the MIT license. A copy of the license can be found in the file +"LICENSE" at the root of this distribution. +-----------------------------------------------------------------------------*/ + +// This file is included in `src/prim/prim.c` + +#include "mimalloc.h" +#include "mimalloc/internal.h" +#include "mimalloc/atomic.h" +#include "mimalloc/prim.h" +#include // sbrk() + +//--------------------------------------------- +// Initialize +//--------------------------------------------- + +void _mi_prim_mem_init( mi_os_mem_config_t* config ) { + config->page_size = 64*MI_KiB; // WebAssembly has a fixed page size: 64KiB + config->alloc_granularity = 16; + config->has_overcommit = false; + config->must_free_whole = true; + config->has_virtual_reserve = false; +} + +//--------------------------------------------- +// Free +//--------------------------------------------- + +int _mi_prim_free(void* addr, size_t size ) { + MI_UNUSED(addr); MI_UNUSED(size); + // wasi heap cannot be shrunk + return 0; +} + + +//--------------------------------------------- +// Allocation: sbrk or memory_grow +//--------------------------------------------- + +#if defined(MI_USE_SBRK) + static void* mi_memory_grow( size_t size ) { + void* p = sbrk(size); + if (p == (void*)(-1)) return NULL; + #if !defined(__wasi__) // on wasi this is always zero initialized already (?) + memset(p,0,size); + #endif + return p; + } +#elif defined(__wasi__) + static void* mi_memory_grow( size_t size ) { + size_t base = (size > 0 ? __builtin_wasm_memory_grow(0,_mi_divide_up(size, _mi_os_page_size())) + : __builtin_wasm_memory_size(0)); + if (base == SIZE_MAX) return NULL; + return (void*)(base * _mi_os_page_size()); + } +#endif + +#if defined(MI_USE_PTHREADS) +static pthread_mutex_t mi_heap_grow_mutex = PTHREAD_MUTEX_INITIALIZER; +#endif + +static void* mi_prim_mem_grow(size_t size, size_t try_alignment) { + void* p = NULL; + if (try_alignment <= 1) { + // `sbrk` is not thread safe in general so try to protect it (we could skip this on WASM but leave it in for now) + #if defined(MI_USE_PTHREADS) + pthread_mutex_lock(&mi_heap_grow_mutex); + #endif + p = mi_memory_grow(size); + #if defined(MI_USE_PTHREADS) + pthread_mutex_unlock(&mi_heap_grow_mutex); + #endif + } + else { + void* base = NULL; + size_t alloc_size = 0; + // to allocate aligned use a lock to try to avoid thread interaction + // between getting the current size and actual allocation + // (also, `sbrk` is not thread safe in general) + #if defined(MI_USE_PTHREADS) + pthread_mutex_lock(&mi_heap_grow_mutex); + #endif + { + void* current = mi_memory_grow(0); // get current size + if (current != NULL) { + void* aligned_current = mi_align_up_ptr(current, try_alignment); // and align from there to minimize wasted space + alloc_size = _mi_align_up( ((uint8_t*)aligned_current - (uint8_t*)current) + size, _mi_os_page_size()); + base = mi_memory_grow(alloc_size); + } + } + #if defined(MI_USE_PTHREADS) + pthread_mutex_unlock(&mi_heap_grow_mutex); + #endif + if (base != NULL) { + p = mi_align_up_ptr(base, try_alignment); + if ((uint8_t*)p + size > (uint8_t*)base + alloc_size) { + // another thread used wasm_memory_grow/sbrk in-between and we do not have enough + // space after alignment. Give up (and waste the space as we cannot shrink :-( ) + // (in `mi_os_mem_alloc_aligned` this will fall back to overallocation to align) + p = NULL; + } + } + } + /* + if (p == NULL) { + _mi_warning_message("unable to allocate sbrk/wasm_memory_grow OS memory (%zu bytes, %zu alignment)\n", size, try_alignment); + errno = ENOMEM; + return NULL; + } + */ + mi_assert_internal( p == NULL || try_alignment == 0 || (uintptr_t)p % try_alignment == 0 ); + return p; +} + +// Note: the `try_alignment` is just a hint and the returned pointer is not guaranteed to be aligned. +int _mi_prim_alloc(size_t size, size_t try_alignment, bool commit, bool allow_large, bool* is_large, bool* is_zero, void** addr) { + MI_UNUSED(allow_large); MI_UNUSED(commit); + *is_large = false; + *is_zero = false; + *addr = mi_prim_mem_grow(size, try_alignment); + return (*addr != NULL ? 0 : ENOMEM); +} + + +//--------------------------------------------- +// Commit/Reset/Protect +//--------------------------------------------- + +int _mi_prim_commit(void* addr, size_t size, bool* is_zero) { + MI_UNUSED(addr); MI_UNUSED(size); + *is_zero = false; + return 0; +} + +int _mi_prim_decommit(void* addr, size_t size, bool* needs_recommit) { + MI_UNUSED(addr); MI_UNUSED(size); + *needs_recommit = false; + return 0; +} + +int _mi_prim_reset(void* addr, size_t size) { + MI_UNUSED(addr); MI_UNUSED(size); + return 0; +} + +int _mi_prim_protect(void* addr, size_t size, bool protect) { + MI_UNUSED(addr); MI_UNUSED(size); MI_UNUSED(protect); + return 0; +} + + +//--------------------------------------------- +// Huge pages and NUMA nodes +//--------------------------------------------- + +int _mi_prim_alloc_huge_os_pages(void* hint_addr, size_t size, int numa_node, bool* is_zero, void** addr) { + MI_UNUSED(hint_addr); MI_UNUSED(size); MI_UNUSED(numa_node); + *is_zero = true; + *addr = NULL; + return ENOSYS; +} + +size_t _mi_prim_numa_node(void) { + return 0; +} + +size_t _mi_prim_numa_node_count(void) { + return 1; +} + + +//---------------------------------------------------------------- +// Clock +//---------------------------------------------------------------- + +#include + +#if defined(CLOCK_REALTIME) || defined(CLOCK_MONOTONIC) + +mi_msecs_t _mi_prim_clock_now(void) { + struct timespec t; + #ifdef CLOCK_MONOTONIC + clock_gettime(CLOCK_MONOTONIC, &t); + #else + clock_gettime(CLOCK_REALTIME, &t); + #endif + return ((mi_msecs_t)t.tv_sec * 1000) + ((mi_msecs_t)t.tv_nsec / 1000000); +} + +#else + +// low resolution timer +mi_msecs_t _mi_prim_clock_now(void) { + #if !defined(CLOCKS_PER_SEC) || (CLOCKS_PER_SEC == 1000) || (CLOCKS_PER_SEC == 0) + return (mi_msecs_t)clock(); + #elif (CLOCKS_PER_SEC < 1000) + return (mi_msecs_t)clock() * (1000 / (mi_msecs_t)CLOCKS_PER_SEC); + #else + return (mi_msecs_t)clock() / ((mi_msecs_t)CLOCKS_PER_SEC / 1000); + #endif +} + +#endif + + +//---------------------------------------------------------------- +// Process info +//---------------------------------------------------------------- + +void _mi_prim_process_info(mi_process_info_t* pinfo) +{ + // use defaults + MI_UNUSED(pinfo); +} + + +//---------------------------------------------------------------- +// Output +//---------------------------------------------------------------- + +void _mi_prim_out_stderr( const char* msg ) { + fputs(msg,stderr); +} + + +//---------------------------------------------------------------- +// Environment +//---------------------------------------------------------------- + +bool _mi_prim_getenv(const char* name, char* result, size_t result_size) { + // cannot call getenv() when still initializing the C runtime. + if (_mi_preloading()) return false; + const char* s = getenv(name); + if (s == NULL) { + // we check the upper case name too. + char buf[64+1]; + size_t len = _mi_strnlen(name,sizeof(buf)-1); + for (size_t i = 0; i < len; i++) { + buf[i] = _mi_toupper(name[i]); + } + buf[len] = 0; + s = getenv(buf); + } + if (s == NULL || _mi_strnlen(s,result_size) >= result_size) return false; + _mi_strlcpy(result, s, result_size); + return true; +} + + +//---------------------------------------------------------------- +// Random +//---------------------------------------------------------------- + +bool _mi_prim_random_buf(void* buf, size_t buf_len) { + return false; +} + + +//---------------------------------------------------------------- +// Thread init/done +//---------------------------------------------------------------- + +void _mi_prim_thread_init_auto_done(void) { + // nothing +} + +void _mi_prim_thread_done_auto_done(void) { + // nothing +} + +void _mi_prim_thread_associate_default_heap(mi_heap_t* heap) { + MI_UNUSED(heap); +} diff --git a/Objects/mimalloc/prim/windows/etw-mimalloc.wprp b/Objects/mimalloc/prim/windows/etw-mimalloc.wprp new file mode 100644 index 00000000000000..b00cd7adf2285c --- /dev/null +++ b/Objects/mimalloc/prim/windows/etw-mimalloc.wprp @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Objects/mimalloc/prim/windows/etw.h b/Objects/mimalloc/prim/windows/etw.h new file mode 100644 index 00000000000000..4e0a092a10f4ba --- /dev/null +++ b/Objects/mimalloc/prim/windows/etw.h @@ -0,0 +1,905 @@ +//**********************************************************************` +//* This is an include file generated by Message Compiler. *` +//* *` +//* Copyright (c) Microsoft Corporation. All Rights Reserved. *` +//**********************************************************************` +#pragma once + +//***************************************************************************** +// +// Notes on the ETW event code generated by MC: +// +// - Structures and arrays of structures are treated as an opaque binary blob. +// The caller is responsible for packing the data for the structure into a +// single region of memory, with no padding between values. The macro will +// have an extra parameter for the length of the blob. +// - Arrays of nul-terminated strings must be packed by the caller into a +// single binary blob containing the correct number of strings, with a nul +// after each string. The size of the blob is specified in characters, and +// includes the final nul. +// - Arrays of SID are treated as a single binary blob. The caller is +// responsible for packing the SID values into a single region of memory with +// no padding. +// - The length attribute on the data element in the manifest is significant +// for values with intype win:UnicodeString, win:AnsiString, or win:Binary. +// The length attribute must be specified for win:Binary, and is optional for +// win:UnicodeString and win:AnsiString (if no length is given, the strings +// are assumed to be nul-terminated). For win:UnicodeString, the length is +// measured in characters, not bytes. +// - For an array of win:UnicodeString, win:AnsiString, or win:Binary, the +// length attribute applies to every value in the array, so every value in +// the array must have the same length. The values in the array are provided +// to the macro via a single pointer -- the caller is responsible for packing +// all of the values into a single region of memory with no padding between +// values. +// - Values of type win:CountedUnicodeString, win:CountedAnsiString, and +// win:CountedBinary can be generated and collected on Vista or later. +// However, they may not decode properly without the Windows 10 2018 Fall +// Update. +// - Arrays of type win:CountedUnicodeString, win:CountedAnsiString, and +// win:CountedBinary must be packed by the caller into a single region of +// memory. The format for each item is a UINT16 byte-count followed by that +// many bytes of data. When providing the array to the generated macro, you +// must provide the total size of the packed array data, including the UINT16 +// sizes for each item. In the case of win:CountedUnicodeString, the data +// size is specified in WCHAR (16-bit) units. In the case of +// win:CountedAnsiString and win:CountedBinary, the data size is specified in +// bytes. +// +//***************************************************************************** + +#include +#include +#include + +#ifndef ETW_INLINE + #ifdef _ETW_KM_ + // In kernel mode, save stack space by never inlining templates. + #define ETW_INLINE DECLSPEC_NOINLINE __inline + #else + // In user mode, save code size by inlining templates as appropriate. + #define ETW_INLINE __inline + #endif +#endif // ETW_INLINE + +#if defined(__cplusplus) +extern "C" { +#endif + +// +// MCGEN_DISABLE_PROVIDER_CODE_GENERATION macro: +// Define this macro to have the compiler skip the generated functions in this +// header. +// +#ifndef MCGEN_DISABLE_PROVIDER_CODE_GENERATION + +// +// MCGEN_USE_KERNEL_MODE_APIS macro: +// Controls whether the generated code uses kernel-mode or user-mode APIs. +// - Set to 0 to use Windows user-mode APIs such as EventRegister. +// - Set to 1 to use Windows kernel-mode APIs such as EtwRegister. +// Default is based on whether the _ETW_KM_ macro is defined (i.e. by wdm.h). +// Note that the APIs can also be overridden directly, e.g. by setting the +// MCGEN_EVENTWRITETRANSFER or MCGEN_EVENTREGISTER macros. +// +#ifndef MCGEN_USE_KERNEL_MODE_APIS + #ifdef _ETW_KM_ + #define MCGEN_USE_KERNEL_MODE_APIS 1 + #else + #define MCGEN_USE_KERNEL_MODE_APIS 0 + #endif +#endif // MCGEN_USE_KERNEL_MODE_APIS + +// +// MCGEN_HAVE_EVENTSETINFORMATION macro: +// Controls how McGenEventSetInformation uses the EventSetInformation API. +// - Set to 0 to disable the use of EventSetInformation +// (McGenEventSetInformation will always return an error). +// - Set to 1 to directly invoke MCGEN_EVENTSETINFORMATION. +// - Set to 2 to to locate EventSetInformation at runtime via GetProcAddress +// (user-mode) or MmGetSystemRoutineAddress (kernel-mode). +// Default is determined as follows: +// - If MCGEN_EVENTSETINFORMATION has been customized, set to 1 +// (i.e. use MCGEN_EVENTSETINFORMATION). +// - Else if the target OS version has EventSetInformation, set to 1 +// (i.e. use MCGEN_EVENTSETINFORMATION). +// - Else set to 2 (i.e. try to dynamically locate EventSetInformation). +// Note that an McGenEventSetInformation function will only be generated if one +// or more provider in a manifest has provider traits. +// +#ifndef MCGEN_HAVE_EVENTSETINFORMATION + #ifdef MCGEN_EVENTSETINFORMATION // if MCGEN_EVENTSETINFORMATION has been customized, + #define MCGEN_HAVE_EVENTSETINFORMATION 1 // directly invoke MCGEN_EVENTSETINFORMATION(...). + #elif MCGEN_USE_KERNEL_MODE_APIS // else if using kernel-mode APIs, + #if NTDDI_VERSION >= 0x06040000 // if target OS is Windows 10 or later, + #define MCGEN_HAVE_EVENTSETINFORMATION 1 // directly invoke MCGEN_EVENTSETINFORMATION(...). + #else // else + #define MCGEN_HAVE_EVENTSETINFORMATION 2 // find "EtwSetInformation" via MmGetSystemRoutineAddress. + #endif // else (using user-mode APIs) + #else // if target OS and SDK is Windows 8 or later, + #if WINVER >= 0x0602 && defined(EVENT_FILTER_TYPE_SCHEMATIZED) + #define MCGEN_HAVE_EVENTSETINFORMATION 1 // directly invoke MCGEN_EVENTSETINFORMATION(...). + #else // else + #define MCGEN_HAVE_EVENTSETINFORMATION 2 // find "EventSetInformation" via GetModuleHandleExW/GetProcAddress. + #endif + #endif +#endif // MCGEN_HAVE_EVENTSETINFORMATION + +// +// MCGEN Override Macros +// +// The following override macros may be defined before including this header +// to control the APIs used by this header: +// +// - MCGEN_EVENTREGISTER +// - MCGEN_EVENTUNREGISTER +// - MCGEN_EVENTSETINFORMATION +// - MCGEN_EVENTWRITETRANSFER +// +// If the the macro is undefined, the MC implementation will default to the +// corresponding ETW APIs. For example, if the MCGEN_EVENTREGISTER macro is +// undefined, the EventRegister[MyProviderName] macro will use EventRegister +// in user mode and will use EtwRegister in kernel mode. +// +// To prevent issues from conflicting definitions of these macros, the value +// of the override macro will be used as a suffix in certain internal function +// names. Because of this, the override macros must follow certain rules: +// +// - The macro must be defined before any MC-generated header is included and +// must not be undefined or redefined after any MC-generated header is +// included. Different translation units (i.e. different .c or .cpp files) +// may set the macros to different values, but within a translation unit +// (within a single .c or .cpp file), the macro must be set once and not +// changed. +// - The override must be an object-like macro, not a function-like macro +// (i.e. the override macro must not have a parameter list). +// - The override macro's value must be a simple identifier, i.e. must be +// something that starts with a letter or '_' and contains only letters, +// numbers, and '_' characters. +// - If the override macro's value is the name of a second object-like macro, +// the second object-like macro must follow the same rules. (The override +// macro's value can also be the name of a function-like macro, in which +// case the function-like macro does not need to follow the same rules.) +// +// For example, the following will cause compile errors: +// +// #define MCGEN_EVENTWRITETRANSFER MyNamespace::MyClass::MyFunction // Value has non-identifier characters (colon). +// #define MCGEN_EVENTWRITETRANSFER GetEventWriteFunctionPointer(7) // Value has non-identifier characters (parentheses). +// #define MCGEN_EVENTWRITETRANSFER(h,e,a,r,c,d) EventWrite(h,e,c,d) // Override is defined as a function-like macro. +// #define MY_OBJECT_LIKE_MACRO MyNamespace::MyClass::MyEventWriteFunction +// #define MCGEN_EVENTWRITETRANSFER MY_OBJECT_LIKE_MACRO // Evaluates to something with non-identifier characters (colon). +// +// The following would be ok: +// +// #define MCGEN_EVENTWRITETRANSFER MyEventWriteFunction1 // OK, suffix will be "MyEventWriteFunction1". +// #define MY_OBJECT_LIKE_MACRO MyEventWriteFunction2 +// #define MCGEN_EVENTWRITETRANSFER MY_OBJECT_LIKE_MACRO // OK, suffix will be "MyEventWriteFunction2". +// #define MY_FUNCTION_LIKE_MACRO(h,e,a,r,c,d) MyNamespace::MyClass::MyEventWriteFunction3(h,e,c,d) +// #define MCGEN_EVENTWRITETRANSFER MY_FUNCTION_LIKE_MACRO // OK, suffix will be "MY_FUNCTION_LIKE_MACRO". +// +#ifndef MCGEN_EVENTREGISTER + #if MCGEN_USE_KERNEL_MODE_APIS + #define MCGEN_EVENTREGISTER EtwRegister + #else + #define MCGEN_EVENTREGISTER EventRegister + #endif +#endif // MCGEN_EVENTREGISTER +#ifndef MCGEN_EVENTUNREGISTER + #if MCGEN_USE_KERNEL_MODE_APIS + #define MCGEN_EVENTUNREGISTER EtwUnregister + #else + #define MCGEN_EVENTUNREGISTER EventUnregister + #endif +#endif // MCGEN_EVENTUNREGISTER +#ifndef MCGEN_EVENTSETINFORMATION + #if MCGEN_USE_KERNEL_MODE_APIS + #define MCGEN_EVENTSETINFORMATION EtwSetInformation + #else + #define MCGEN_EVENTSETINFORMATION EventSetInformation + #endif +#endif // MCGEN_EVENTSETINFORMATION +#ifndef MCGEN_EVENTWRITETRANSFER + #if MCGEN_USE_KERNEL_MODE_APIS + #define MCGEN_EVENTWRITETRANSFER EtwWriteTransfer + #else + #define MCGEN_EVENTWRITETRANSFER EventWriteTransfer + #endif +#endif // MCGEN_EVENTWRITETRANSFER + +// +// MCGEN_EVENT_ENABLED macro: +// Override to control how the EventWrite[EventName] macros determine whether +// an event is enabled. The default behavior is for EventWrite[EventName] to +// use the EventEnabled[EventName] macros. +// +#ifndef MCGEN_EVENT_ENABLED +#define MCGEN_EVENT_ENABLED(EventName) EventEnabled##EventName() +#endif + +// +// MCGEN_EVENT_ENABLED_FORCONTEXT macro: +// Override to control how the EventWrite[EventName]_ForContext macros +// determine whether an event is enabled. The default behavior is for +// EventWrite[EventName]_ForContext to use the +// EventEnabled[EventName]_ForContext macros. +// +#ifndef MCGEN_EVENT_ENABLED_FORCONTEXT +#define MCGEN_EVENT_ENABLED_FORCONTEXT(pContext, EventName) EventEnabled##EventName##_ForContext(pContext) +#endif + +// +// MCGEN_ENABLE_CHECK macro: +// Determines whether the specified event would be considered as enabled +// based on the state of the specified context. Slightly faster than calling +// McGenEventEnabled directly. +// +#ifndef MCGEN_ENABLE_CHECK +#define MCGEN_ENABLE_CHECK(Context, Descriptor) (Context.IsEnabled && McGenEventEnabled(&Context, &Descriptor)) +#endif + +#if !defined(MCGEN_TRACE_CONTEXT_DEF) +#define MCGEN_TRACE_CONTEXT_DEF +// This structure is for use by MC-generated code and should not be used directly. +typedef struct _MCGEN_TRACE_CONTEXT +{ + TRACEHANDLE RegistrationHandle; + TRACEHANDLE Logger; // Used as pointer to provider traits. + ULONGLONG MatchAnyKeyword; + ULONGLONG MatchAllKeyword; + ULONG Flags; + ULONG IsEnabled; + UCHAR Level; + UCHAR Reserve; + USHORT EnableBitsCount; + PULONG EnableBitMask; + const ULONGLONG* EnableKeyWords; + const UCHAR* EnableLevel; +} MCGEN_TRACE_CONTEXT, *PMCGEN_TRACE_CONTEXT; +#endif // MCGEN_TRACE_CONTEXT_DEF + +#if !defined(MCGEN_LEVEL_KEYWORD_ENABLED_DEF) +#define MCGEN_LEVEL_KEYWORD_ENABLED_DEF +// +// Determines whether an event with a given Level and Keyword would be +// considered as enabled based on the state of the specified context. +// Note that you may want to use MCGEN_ENABLE_CHECK instead of calling this +// function directly. +// +FORCEINLINE +BOOLEAN +McGenLevelKeywordEnabled( + _In_ PMCGEN_TRACE_CONTEXT EnableInfo, + _In_ UCHAR Level, + _In_ ULONGLONG Keyword + ) +{ + // + // Check if the event Level is lower than the level at which + // the channel is enabled. + // If the event Level is 0 or the channel is enabled at level 0, + // all levels are enabled. + // + + if ((Level <= EnableInfo->Level) || // This also covers the case of Level == 0. + (EnableInfo->Level == 0)) { + + // + // Check if Keyword is enabled + // + + if ((Keyword == (ULONGLONG)0) || + ((Keyword & EnableInfo->MatchAnyKeyword) && + ((Keyword & EnableInfo->MatchAllKeyword) == EnableInfo->MatchAllKeyword))) { + return TRUE; + } + } + + return FALSE; +} +#endif // MCGEN_LEVEL_KEYWORD_ENABLED_DEF + +#if !defined(MCGEN_EVENT_ENABLED_DEF) +#define MCGEN_EVENT_ENABLED_DEF +// +// Determines whether the specified event would be considered as enabled based +// on the state of the specified context. Note that you may want to use +// MCGEN_ENABLE_CHECK instead of calling this function directly. +// +FORCEINLINE +BOOLEAN +McGenEventEnabled( + _In_ PMCGEN_TRACE_CONTEXT EnableInfo, + _In_ PCEVENT_DESCRIPTOR EventDescriptor + ) +{ + return McGenLevelKeywordEnabled(EnableInfo, EventDescriptor->Level, EventDescriptor->Keyword); +} +#endif // MCGEN_EVENT_ENABLED_DEF + +#if !defined(MCGEN_CONTROL_CALLBACK) +#define MCGEN_CONTROL_CALLBACK + +// This function is for use by MC-generated code and should not be used directly. +DECLSPEC_NOINLINE __inline +VOID +__stdcall +McGenControlCallbackV2( + _In_ LPCGUID SourceId, + _In_ ULONG ControlCode, + _In_ UCHAR Level, + _In_ ULONGLONG MatchAnyKeyword, + _In_ ULONGLONG MatchAllKeyword, + _In_opt_ PEVENT_FILTER_DESCRIPTOR FilterData, + _Inout_opt_ PVOID CallbackContext + ) +/*++ + +Routine Description: + + This is the notification callback for Windows Vista and later. + +Arguments: + + SourceId - The GUID that identifies the session that enabled the provider. + + ControlCode - The parameter indicates whether the provider + is being enabled or disabled. + + Level - The level at which the event is enabled. + + MatchAnyKeyword - The bitmask of keywords that the provider uses to + determine the category of events that it writes. + + MatchAllKeyword - This bitmask additionally restricts the category + of events that the provider writes. + + FilterData - The provider-defined data. + + CallbackContext - The context of the callback that is defined when the provider + called EtwRegister to register itself. + +Remarks: + + ETW calls this function to notify provider of enable/disable + +--*/ +{ + PMCGEN_TRACE_CONTEXT Ctx = (PMCGEN_TRACE_CONTEXT)CallbackContext; + ULONG Ix; +#ifndef MCGEN_PRIVATE_ENABLE_CALLBACK_V2 + UNREFERENCED_PARAMETER(SourceId); + UNREFERENCED_PARAMETER(FilterData); +#endif + + if (Ctx == NULL) { + return; + } + + switch (ControlCode) { + + case EVENT_CONTROL_CODE_ENABLE_PROVIDER: + Ctx->Level = Level; + Ctx->MatchAnyKeyword = MatchAnyKeyword; + Ctx->MatchAllKeyword = MatchAllKeyword; + Ctx->IsEnabled = EVENT_CONTROL_CODE_ENABLE_PROVIDER; + + for (Ix = 0; Ix < Ctx->EnableBitsCount; Ix += 1) { + if (McGenLevelKeywordEnabled(Ctx, Ctx->EnableLevel[Ix], Ctx->EnableKeyWords[Ix]) != FALSE) { + Ctx->EnableBitMask[Ix >> 5] |= (1 << (Ix % 32)); + } else { + Ctx->EnableBitMask[Ix >> 5] &= ~(1 << (Ix % 32)); + } + } + break; + + case EVENT_CONTROL_CODE_DISABLE_PROVIDER: + Ctx->IsEnabled = EVENT_CONTROL_CODE_DISABLE_PROVIDER; + Ctx->Level = 0; + Ctx->MatchAnyKeyword = 0; + Ctx->MatchAllKeyword = 0; + if (Ctx->EnableBitsCount > 0) { +#pragma warning(suppress: 26451) // Arithmetic overflow cannot occur, no matter the value of EnableBitCount + RtlZeroMemory(Ctx->EnableBitMask, (((Ctx->EnableBitsCount - 1) / 32) + 1) * sizeof(ULONG)); + } + break; + + default: + break; + } + +#ifdef MCGEN_PRIVATE_ENABLE_CALLBACK_V2 + // + // Call user defined callback + // + MCGEN_PRIVATE_ENABLE_CALLBACK_V2( + SourceId, + ControlCode, + Level, + MatchAnyKeyword, + MatchAllKeyword, + FilterData, + CallbackContext + ); +#endif // MCGEN_PRIVATE_ENABLE_CALLBACK_V2 + + return; +} + +#endif // MCGEN_CONTROL_CALLBACK + +#ifndef _mcgen_PENABLECALLBACK + #if MCGEN_USE_KERNEL_MODE_APIS + #define _mcgen_PENABLECALLBACK PETWENABLECALLBACK + #else + #define _mcgen_PENABLECALLBACK PENABLECALLBACK + #endif +#endif // _mcgen_PENABLECALLBACK + +#if !defined(_mcgen_PASTE2) +// This macro is for use by MC-generated code and should not be used directly. +#define _mcgen_PASTE2(a, b) _mcgen_PASTE2_imp(a, b) +#define _mcgen_PASTE2_imp(a, b) a##b +#endif // _mcgen_PASTE2 + +#if !defined(_mcgen_PASTE3) +// This macro is for use by MC-generated code and should not be used directly. +#define _mcgen_PASTE3(a, b, c) _mcgen_PASTE3_imp(a, b, c) +#define _mcgen_PASTE3_imp(a, b, c) a##b##_##c +#endif // _mcgen_PASTE3 + +// +// Macro validation +// + +// Validate MCGEN_EVENTREGISTER: + +// Trigger an error if MCGEN_EVENTREGISTER is not an unqualified (simple) identifier: +struct _mcgen_PASTE2(MCGEN_EVENTREGISTER_definition_must_be_an_unqualified_identifier_, MCGEN_EVENTREGISTER); + +// Trigger an error if MCGEN_EVENTREGISTER is redefined: +typedef struct _mcgen_PASTE2(MCGEN_EVENTREGISTER_definition_must_be_an_unqualified_identifier_, MCGEN_EVENTREGISTER) + MCGEN_EVENTREGISTER_must_not_be_redefined_between_headers; + +// Trigger an error if MCGEN_EVENTREGISTER is defined as a function-like macro: +typedef void MCGEN_EVENTREGISTER_must_not_be_a_functionLike_macro_MCGEN_EVENTREGISTER; +typedef int _mcgen_PASTE2(MCGEN_EVENTREGISTER_must_not_be_a_functionLike_macro_, MCGEN_EVENTREGISTER); + +// Validate MCGEN_EVENTUNREGISTER: + +// Trigger an error if MCGEN_EVENTUNREGISTER is not an unqualified (simple) identifier: +struct _mcgen_PASTE2(MCGEN_EVENTUNREGISTER_definition_must_be_an_unqualified_identifier_, MCGEN_EVENTUNREGISTER); + +// Trigger an error if MCGEN_EVENTUNREGISTER is redefined: +typedef struct _mcgen_PASTE2(MCGEN_EVENTUNREGISTER_definition_must_be_an_unqualified_identifier_, MCGEN_EVENTUNREGISTER) + MCGEN_EVENTUNREGISTER_must_not_be_redefined_between_headers; + +// Trigger an error if MCGEN_EVENTUNREGISTER is defined as a function-like macro: +typedef void MCGEN_EVENTUNREGISTER_must_not_be_a_functionLike_macro_MCGEN_EVENTUNREGISTER; +typedef int _mcgen_PASTE2(MCGEN_EVENTUNREGISTER_must_not_be_a_functionLike_macro_, MCGEN_EVENTUNREGISTER); + +// Validate MCGEN_EVENTSETINFORMATION: + +// Trigger an error if MCGEN_EVENTSETINFORMATION is not an unqualified (simple) identifier: +struct _mcgen_PASTE2(MCGEN_EVENTSETINFORMATION_definition_must_be_an_unqualified_identifier_, MCGEN_EVENTSETINFORMATION); + +// Trigger an error if MCGEN_EVENTSETINFORMATION is redefined: +typedef struct _mcgen_PASTE2(MCGEN_EVENTSETINFORMATION_definition_must_be_an_unqualified_identifier_, MCGEN_EVENTSETINFORMATION) + MCGEN_EVENTSETINFORMATION_must_not_be_redefined_between_headers; + +// Trigger an error if MCGEN_EVENTSETINFORMATION is defined as a function-like macro: +typedef void MCGEN_EVENTSETINFORMATION_must_not_be_a_functionLike_macro_MCGEN_EVENTSETINFORMATION; +typedef int _mcgen_PASTE2(MCGEN_EVENTSETINFORMATION_must_not_be_a_functionLike_macro_, MCGEN_EVENTSETINFORMATION); + +// Validate MCGEN_EVENTWRITETRANSFER: + +// Trigger an error if MCGEN_EVENTWRITETRANSFER is not an unqualified (simple) identifier: +struct _mcgen_PASTE2(MCGEN_EVENTWRITETRANSFER_definition_must_be_an_unqualified_identifier_, MCGEN_EVENTWRITETRANSFER); + +// Trigger an error if MCGEN_EVENTWRITETRANSFER is redefined: +typedef struct _mcgen_PASTE2(MCGEN_EVENTWRITETRANSFER_definition_must_be_an_unqualified_identifier_, MCGEN_EVENTWRITETRANSFER) + MCGEN_EVENTWRITETRANSFER_must_not_be_redefined_between_headers;; + +// Trigger an error if MCGEN_EVENTWRITETRANSFER is defined as a function-like macro: +typedef void MCGEN_EVENTWRITETRANSFER_must_not_be_a_functionLike_macro_MCGEN_EVENTWRITETRANSFER; +typedef int _mcgen_PASTE2(MCGEN_EVENTWRITETRANSFER_must_not_be_a_functionLike_macro_, MCGEN_EVENTWRITETRANSFER); + +#ifndef McGenEventWrite_def +#define McGenEventWrite_def + +// This macro is for use by MC-generated code and should not be used directly. +#define McGenEventWrite _mcgen_PASTE2(McGenEventWrite_, MCGEN_EVENTWRITETRANSFER) + +// This function is for use by MC-generated code and should not be used directly. +DECLSPEC_NOINLINE __inline +ULONG __stdcall +McGenEventWrite( + _In_ PMCGEN_TRACE_CONTEXT Context, + _In_ PCEVENT_DESCRIPTOR Descriptor, + _In_opt_ LPCGUID ActivityId, + _In_range_(1, 128) ULONG EventDataCount, + _Pre_cap_(EventDataCount) EVENT_DATA_DESCRIPTOR* EventData + ) +{ + const USHORT UNALIGNED* Traits; + + // Some customized MCGEN_EVENTWRITETRANSFER macros might ignore ActivityId. + UNREFERENCED_PARAMETER(ActivityId); + + Traits = (const USHORT UNALIGNED*)(UINT_PTR)Context->Logger; + + if (Traits == NULL) { + EventData[0].Ptr = 0; + EventData[0].Size = 0; + EventData[0].Reserved = 0; + } else { + EventData[0].Ptr = (ULONG_PTR)Traits; + EventData[0].Size = *Traits; + EventData[0].Reserved = 2; // EVENT_DATA_DESCRIPTOR_TYPE_PROVIDER_METADATA + } + + return MCGEN_EVENTWRITETRANSFER( + Context->RegistrationHandle, + Descriptor, + ActivityId, + NULL, + EventDataCount, + EventData); +} +#endif // McGenEventWrite_def + +#if !defined(McGenEventRegisterUnregister) +#define McGenEventRegisterUnregister + +// This macro is for use by MC-generated code and should not be used directly. +#define McGenEventRegister _mcgen_PASTE2(McGenEventRegister_, MCGEN_EVENTREGISTER) + +#pragma warning(push) +#pragma warning(disable:6103) +// This function is for use by MC-generated code and should not be used directly. +DECLSPEC_NOINLINE __inline +ULONG __stdcall +McGenEventRegister( + _In_ LPCGUID ProviderId, + _In_opt_ _mcgen_PENABLECALLBACK EnableCallback, + _In_opt_ PVOID CallbackContext, + _Inout_ PREGHANDLE RegHandle + ) +/*++ + +Routine Description: + + This function registers the provider with ETW. + +Arguments: + + ProviderId - Provider ID to register with ETW. + + EnableCallback - Callback to be used. + + CallbackContext - Context for the callback. + + RegHandle - Pointer to registration handle. + +Remarks: + + Should not be called if the provider is already registered (i.e. should not + be called if *RegHandle != 0). Repeatedly registering a provider is a bug + and may indicate a race condition. However, for compatibility with previous + behavior, this function will return SUCCESS in this case. + +--*/ +{ + ULONG Error; + + if (*RegHandle != 0) + { + Error = 0; // ERROR_SUCCESS + } + else + { + Error = MCGEN_EVENTREGISTER(ProviderId, EnableCallback, CallbackContext, RegHandle); + } + + return Error; +} +#pragma warning(pop) + +// This macro is for use by MC-generated code and should not be used directly. +#define McGenEventUnregister _mcgen_PASTE2(McGenEventUnregister_, MCGEN_EVENTUNREGISTER) + +// This function is for use by MC-generated code and should not be used directly. +DECLSPEC_NOINLINE __inline +ULONG __stdcall +McGenEventUnregister(_Inout_ PREGHANDLE RegHandle) +/*++ + +Routine Description: + + Unregister from ETW and set *RegHandle = 0. + +Arguments: + + RegHandle - the pointer to the provider registration handle + +Remarks: + + If provider has not been registered (i.e. if *RegHandle == 0), + return SUCCESS. It is safe to call McGenEventUnregister even if the + call to McGenEventRegister returned an error. + +--*/ +{ + ULONG Error; + + if(*RegHandle == 0) + { + Error = 0; // ERROR_SUCCESS + } + else + { + Error = MCGEN_EVENTUNREGISTER(*RegHandle); + *RegHandle = (REGHANDLE)0; + } + + return Error; +} + +#endif // McGenEventRegisterUnregister + +#ifndef _mcgen_EVENT_BIT_SET + #if defined(_M_IX86) || defined(_M_X64) + // This macro is for use by MC-generated code and should not be used directly. + #define _mcgen_EVENT_BIT_SET(EnableBits, BitPosition) ((((const unsigned char*)EnableBits)[BitPosition >> 3] & (1u << (BitPosition & 7))) != 0) + #else // CPU type + // This macro is for use by MC-generated code and should not be used directly. + #define _mcgen_EVENT_BIT_SET(EnableBits, BitPosition) ((EnableBits[BitPosition >> 5] & (1u << (BitPosition & 31))) != 0) + #endif // CPU type +#endif // _mcgen_EVENT_BIT_SET + +#endif // MCGEN_DISABLE_PROVIDER_CODE_GENERATION + +//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// Provider "microsoft-windows-mimalloc" event count 2 +//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +// Provider GUID = 138f4dbb-ee04-4899-aa0a-572ad4475779 +EXTERN_C __declspec(selectany) const GUID ETW_MI_Provider = {0x138f4dbb, 0xee04, 0x4899, {0xaa, 0x0a, 0x57, 0x2a, 0xd4, 0x47, 0x57, 0x79}}; + +#ifndef ETW_MI_Provider_Traits +#define ETW_MI_Provider_Traits NULL +#endif // ETW_MI_Provider_Traits + +// +// Event Descriptors +// +EXTERN_C __declspec(selectany) const EVENT_DESCRIPTOR ETW_MI_ALLOC = {0x64, 0x1, 0x0, 0x4, 0x0, 0x0, 0x0}; +#define ETW_MI_ALLOC_value 0x64 +EXTERN_C __declspec(selectany) const EVENT_DESCRIPTOR ETW_MI_FREE = {0x65, 0x1, 0x0, 0x4, 0x0, 0x0, 0x0}; +#define ETW_MI_FREE_value 0x65 + +// +// MCGEN_DISABLE_PROVIDER_CODE_GENERATION macro: +// Define this macro to have the compiler skip the generated functions in this +// header. +// +#ifndef MCGEN_DISABLE_PROVIDER_CODE_GENERATION + +// +// Event Enablement Bits +// These variables are for use by MC-generated code and should not be used directly. +// +EXTERN_C __declspec(selectany) DECLSPEC_CACHEALIGN ULONG microsoft_windows_mimallocEnableBits[1]; +EXTERN_C __declspec(selectany) const ULONGLONG microsoft_windows_mimallocKeywords[1] = {0x0}; +EXTERN_C __declspec(selectany) const unsigned char microsoft_windows_mimallocLevels[1] = {4}; + +// +// Provider context +// +EXTERN_C __declspec(selectany) MCGEN_TRACE_CONTEXT ETW_MI_Provider_Context = {0, (ULONG_PTR)ETW_MI_Provider_Traits, 0, 0, 0, 0, 0, 0, 1, microsoft_windows_mimallocEnableBits, microsoft_windows_mimallocKeywords, microsoft_windows_mimallocLevels}; + +// +// Provider REGHANDLE +// +#define microsoft_windows_mimallocHandle (ETW_MI_Provider_Context.RegistrationHandle) + +// +// This macro is set to 0, indicating that the EventWrite[Name] macros do not +// have an Activity parameter. This is controlled by the -km and -um options. +// +#define ETW_MI_Provider_EventWriteActivity 0 + +// +// Register with ETW using the control GUID specified in the manifest. +// Invoke this macro during module initialization (i.e. program startup, +// DLL process attach, or driver load) to initialize the provider. +// Note that if this function returns an error, the error means that +// will not work, but no action needs to be taken -- even if EventRegister +// returns an error, it is generally safe to use EventWrite and +// EventUnregister macros (they will be no-ops if EventRegister failed). +// +#ifndef EventRegistermicrosoft_windows_mimalloc +#define EventRegistermicrosoft_windows_mimalloc() McGenEventRegister(&ETW_MI_Provider, McGenControlCallbackV2, &ETW_MI_Provider_Context, µsoft_windows_mimallocHandle) +#endif + +// +// Register with ETW using a specific control GUID (i.e. a GUID other than what +// is specified in the manifest). Advanced scenarios only. +// +#ifndef EventRegisterByGuidmicrosoft_windows_mimalloc +#define EventRegisterByGuidmicrosoft_windows_mimalloc(Guid) McGenEventRegister(&(Guid), McGenControlCallbackV2, &ETW_MI_Provider_Context, µsoft_windows_mimallocHandle) +#endif + +// +// Unregister with ETW and close the provider. +// Invoke this macro during module shutdown (i.e. program exit, DLL process +// detach, or driver unload) to unregister the provider. +// Note that you MUST call EventUnregister before DLL or driver unload +// (not optional): failure to unregister a provider before DLL or driver unload +// will result in crashes. +// +#ifndef EventUnregistermicrosoft_windows_mimalloc +#define EventUnregistermicrosoft_windows_mimalloc() McGenEventUnregister(µsoft_windows_mimallocHandle) +#endif + +// +// MCGEN_ENABLE_FORCONTEXT_CODE_GENERATION macro: +// Define this macro to enable support for caller-allocated provider context. +// +#ifdef MCGEN_ENABLE_FORCONTEXT_CODE_GENERATION + +// +// Advanced scenarios: Caller-allocated provider context. +// Use when multiple differently-configured provider handles are needed, +// e.g. for container-aware drivers, one context per container. +// +// Usage: +// +// - Caller enables the feature before including this header, e.g. +// #define MCGEN_ENABLE_FORCONTEXT_CODE_GENERATION 1 +// - Caller allocates memory, e.g. pContext = malloc(sizeof(McGenContext_microsoft_windows_mimalloc)); +// - Caller registers the provider, e.g. EventRegistermicrosoft_windows_mimalloc_ForContext(pContext); +// - Caller writes events, e.g. EventWriteMyEvent_ForContext(pContext, ...); +// - Caller unregisters, e.g. EventUnregistermicrosoft_windows_mimalloc_ForContext(pContext); +// - Caller frees memory, e.g. free(pContext); +// + +typedef struct tagMcGenContext_microsoft_windows_mimalloc { + // The fields of this structure are subject to change and should + // not be accessed directly. To access the provider's REGHANDLE, + // use microsoft_windows_mimallocHandle_ForContext(pContext). + MCGEN_TRACE_CONTEXT Context; + ULONG EnableBits[1]; +} McGenContext_microsoft_windows_mimalloc; + +#define EventRegistermicrosoft_windows_mimalloc_ForContext(pContext) _mcgen_PASTE2(_mcgen_RegisterForContext_microsoft_windows_mimalloc_, MCGEN_EVENTREGISTER)(&ETW_MI_Provider, pContext) +#define EventRegisterByGuidmicrosoft_windows_mimalloc_ForContext(Guid, pContext) _mcgen_PASTE2(_mcgen_RegisterForContext_microsoft_windows_mimalloc_, MCGEN_EVENTREGISTER)(&(Guid), pContext) +#define EventUnregistermicrosoft_windows_mimalloc_ForContext(pContext) McGenEventUnregister(&(pContext)->Context.RegistrationHandle) + +// +// Provider REGHANDLE for caller-allocated context. +// +#define microsoft_windows_mimallocHandle_ForContext(pContext) ((pContext)->Context.RegistrationHandle) + +// This function is for use by MC-generated code and should not be used directly. +// Initialize and register the caller-allocated context. +__inline +ULONG __stdcall +_mcgen_PASTE2(_mcgen_RegisterForContext_microsoft_windows_mimalloc_, MCGEN_EVENTREGISTER)( + _In_ LPCGUID pProviderId, + _Out_ McGenContext_microsoft_windows_mimalloc* pContext) +{ + RtlZeroMemory(pContext, sizeof(*pContext)); + pContext->Context.Logger = (ULONG_PTR)ETW_MI_Provider_Traits; + pContext->Context.EnableBitsCount = 1; + pContext->Context.EnableBitMask = pContext->EnableBits; + pContext->Context.EnableKeyWords = microsoft_windows_mimallocKeywords; + pContext->Context.EnableLevel = microsoft_windows_mimallocLevels; + return McGenEventRegister( + pProviderId, + McGenControlCallbackV2, + &pContext->Context, + &pContext->Context.RegistrationHandle); +} + +// This function is for use by MC-generated code and should not be used directly. +// Trigger a compile error if called with the wrong parameter type. +FORCEINLINE +_Ret_ McGenContext_microsoft_windows_mimalloc* +_mcgen_CheckContextType_microsoft_windows_mimalloc(_In_ McGenContext_microsoft_windows_mimalloc* pContext) +{ + return pContext; +} + +#endif // MCGEN_ENABLE_FORCONTEXT_CODE_GENERATION + +// +// Enablement check macro for event "ETW_MI_ALLOC" +// +#define EventEnabledETW_MI_ALLOC() _mcgen_EVENT_BIT_SET(microsoft_windows_mimallocEnableBits, 0) +#define EventEnabledETW_MI_ALLOC_ForContext(pContext) _mcgen_EVENT_BIT_SET(_mcgen_CheckContextType_microsoft_windows_mimalloc(pContext)->EnableBits, 0) + +// +// Event write macros for event "ETW_MI_ALLOC" +// +#define EventWriteETW_MI_ALLOC(Address, Size) \ + MCGEN_EVENT_ENABLED(ETW_MI_ALLOC) \ + ? _mcgen_TEMPLATE_FOR_ETW_MI_ALLOC(&ETW_MI_Provider_Context, &ETW_MI_ALLOC, Address, Size) : 0 +#define EventWriteETW_MI_ALLOC_AssumeEnabled(Address, Size) \ + _mcgen_TEMPLATE_FOR_ETW_MI_ALLOC(&ETW_MI_Provider_Context, &ETW_MI_ALLOC, Address, Size) +#define EventWriteETW_MI_ALLOC_ForContext(pContext, Address, Size) \ + MCGEN_EVENT_ENABLED_FORCONTEXT(pContext, ETW_MI_ALLOC) \ + ? _mcgen_TEMPLATE_FOR_ETW_MI_ALLOC(&(pContext)->Context, &ETW_MI_ALLOC, Address, Size) : 0 +#define EventWriteETW_MI_ALLOC_ForContextAssumeEnabled(pContext, Address, Size) \ + _mcgen_TEMPLATE_FOR_ETW_MI_ALLOC(&_mcgen_CheckContextType_microsoft_windows_mimalloc(pContext)->Context, &ETW_MI_ALLOC, Address, Size) + +// This macro is for use by MC-generated code and should not be used directly. +#define _mcgen_TEMPLATE_FOR_ETW_MI_ALLOC _mcgen_PASTE2(McTemplateU0xx_, MCGEN_EVENTWRITETRANSFER) + +// +// Enablement check macro for event "ETW_MI_FREE" +// +#define EventEnabledETW_MI_FREE() _mcgen_EVENT_BIT_SET(microsoft_windows_mimallocEnableBits, 0) +#define EventEnabledETW_MI_FREE_ForContext(pContext) _mcgen_EVENT_BIT_SET(_mcgen_CheckContextType_microsoft_windows_mimalloc(pContext)->EnableBits, 0) + +// +// Event write macros for event "ETW_MI_FREE" +// +#define EventWriteETW_MI_FREE(Address, Size) \ + MCGEN_EVENT_ENABLED(ETW_MI_FREE) \ + ? _mcgen_TEMPLATE_FOR_ETW_MI_FREE(&ETW_MI_Provider_Context, &ETW_MI_FREE, Address, Size) : 0 +#define EventWriteETW_MI_FREE_AssumeEnabled(Address, Size) \ + _mcgen_TEMPLATE_FOR_ETW_MI_FREE(&ETW_MI_Provider_Context, &ETW_MI_FREE, Address, Size) +#define EventWriteETW_MI_FREE_ForContext(pContext, Address, Size) \ + MCGEN_EVENT_ENABLED_FORCONTEXT(pContext, ETW_MI_FREE) \ + ? _mcgen_TEMPLATE_FOR_ETW_MI_FREE(&(pContext)->Context, &ETW_MI_FREE, Address, Size) : 0 +#define EventWriteETW_MI_FREE_ForContextAssumeEnabled(pContext, Address, Size) \ + _mcgen_TEMPLATE_FOR_ETW_MI_FREE(&_mcgen_CheckContextType_microsoft_windows_mimalloc(pContext)->Context, &ETW_MI_FREE, Address, Size) + +// This macro is for use by MC-generated code and should not be used directly. +#define _mcgen_TEMPLATE_FOR_ETW_MI_FREE _mcgen_PASTE2(McTemplateU0xx_, MCGEN_EVENTWRITETRANSFER) + +#endif // MCGEN_DISABLE_PROVIDER_CODE_GENERATION + +// +// MCGEN_DISABLE_PROVIDER_CODE_GENERATION macro: +// Define this macro to have the compiler skip the generated functions in this +// header. +// +#ifndef MCGEN_DISABLE_PROVIDER_CODE_GENERATION + +// +// Template Functions +// + +// +// Function for template "ETW_CUSTOM_HEAP_ALLOC_DATA" (and possibly others). +// This function is for use by MC-generated code and should not be used directly. +// +#ifndef McTemplateU0xx_def +#define McTemplateU0xx_def +ETW_INLINE +ULONG +_mcgen_PASTE2(McTemplateU0xx_, MCGEN_EVENTWRITETRANSFER)( + _In_ PMCGEN_TRACE_CONTEXT Context, + _In_ PCEVENT_DESCRIPTOR Descriptor, + _In_ const unsigned __int64 _Arg0, + _In_ const unsigned __int64 _Arg1 + ) +{ +#define McTemplateU0xx_ARGCOUNT 2 + + EVENT_DATA_DESCRIPTOR EventData[McTemplateU0xx_ARGCOUNT + 1]; + + EventDataDescCreate(&EventData[1],&_Arg0, sizeof(const unsigned __int64) ); + + EventDataDescCreate(&EventData[2],&_Arg1, sizeof(const unsigned __int64) ); + + return McGenEventWrite(Context, Descriptor, NULL, McTemplateU0xx_ARGCOUNT + 1, EventData); +} +#endif // McTemplateU0xx_def + +#endif // MCGEN_DISABLE_PROVIDER_CODE_GENERATION + +#if defined(__cplusplus) +} +#endif diff --git a/Objects/mimalloc/prim/windows/etw.man b/Objects/mimalloc/prim/windows/etw.man new file mode 100644 index 00000000000000..cfd1f8a9eaacd5 Binary files /dev/null and b/Objects/mimalloc/prim/windows/etw.man differ diff --git a/Objects/mimalloc/prim/windows/prim.c b/Objects/mimalloc/prim/windows/prim.c new file mode 100644 index 00000000000000..a038277ad21cb0 --- /dev/null +++ b/Objects/mimalloc/prim/windows/prim.c @@ -0,0 +1,622 @@ +/* ---------------------------------------------------------------------------- +Copyright (c) 2018-2023, Microsoft Research, Daan Leijen +This is free software; you can redistribute it and/or modify it under the +terms of the MIT license. A copy of the license can be found in the file +"LICENSE" at the root of this distribution. +-----------------------------------------------------------------------------*/ + +// This file is included in `src/prim/prim.c` + +#include "mimalloc.h" +#include "mimalloc/internal.h" +#include "mimalloc/atomic.h" +#include "mimalloc/prim.h" +#include // fputs, stderr + + +//--------------------------------------------- +// Dynamically bind Windows API points for portability +//--------------------------------------------- + +// We use VirtualAlloc2 for aligned allocation, but it is only supported on Windows 10 and Windows Server 2016. +// So, we need to look it up dynamically to run on older systems. (use __stdcall for 32-bit compatibility) +// NtAllocateVirtualAllocEx is used for huge OS page allocation (1GiB) +// We define a minimal MEM_EXTENDED_PARAMETER ourselves in order to be able to compile with older SDK's. +typedef enum MI_MEM_EXTENDED_PARAMETER_TYPE_E { + MiMemExtendedParameterInvalidType = 0, + MiMemExtendedParameterAddressRequirements, + MiMemExtendedParameterNumaNode, + MiMemExtendedParameterPartitionHandle, + MiMemExtendedParameterUserPhysicalHandle, + MiMemExtendedParameterAttributeFlags, + MiMemExtendedParameterMax +} MI_MEM_EXTENDED_PARAMETER_TYPE; + +typedef struct DECLSPEC_ALIGN(8) MI_MEM_EXTENDED_PARAMETER_S { + struct { DWORD64 Type : 8; DWORD64 Reserved : 56; } Type; + union { DWORD64 ULong64; PVOID Pointer; SIZE_T Size; HANDLE Handle; DWORD ULong; } Arg; +} MI_MEM_EXTENDED_PARAMETER; + +typedef struct MI_MEM_ADDRESS_REQUIREMENTS_S { + PVOID LowestStartingAddress; + PVOID HighestEndingAddress; + SIZE_T Alignment; +} MI_MEM_ADDRESS_REQUIREMENTS; + +#define MI_MEM_EXTENDED_PARAMETER_NONPAGED_HUGE 0x00000010 + +#include +typedef PVOID (__stdcall *PVirtualAlloc2)(HANDLE, PVOID, SIZE_T, ULONG, ULONG, MI_MEM_EXTENDED_PARAMETER*, ULONG); +typedef NTSTATUS (__stdcall *PNtAllocateVirtualMemoryEx)(HANDLE, PVOID*, SIZE_T*, ULONG, ULONG, MI_MEM_EXTENDED_PARAMETER*, ULONG); +static PVirtualAlloc2 pVirtualAlloc2 = NULL; +static PNtAllocateVirtualMemoryEx pNtAllocateVirtualMemoryEx = NULL; + +// Similarly, GetNumaProcesorNodeEx is only supported since Windows 7 +typedef struct MI_PROCESSOR_NUMBER_S { WORD Group; BYTE Number; BYTE Reserved; } MI_PROCESSOR_NUMBER; + +typedef VOID (__stdcall *PGetCurrentProcessorNumberEx)(MI_PROCESSOR_NUMBER* ProcNumber); +typedef BOOL (__stdcall *PGetNumaProcessorNodeEx)(MI_PROCESSOR_NUMBER* Processor, PUSHORT NodeNumber); +typedef BOOL (__stdcall* PGetNumaNodeProcessorMaskEx)(USHORT Node, PGROUP_AFFINITY ProcessorMask); +typedef BOOL (__stdcall *PGetNumaProcessorNode)(UCHAR Processor, PUCHAR NodeNumber); +static PGetCurrentProcessorNumberEx pGetCurrentProcessorNumberEx = NULL; +static PGetNumaProcessorNodeEx pGetNumaProcessorNodeEx = NULL; +static PGetNumaNodeProcessorMaskEx pGetNumaNodeProcessorMaskEx = NULL; +static PGetNumaProcessorNode pGetNumaProcessorNode = NULL; + +//--------------------------------------------- +// Enable large page support dynamically (if possible) +//--------------------------------------------- + +static bool win_enable_large_os_pages(size_t* large_page_size) +{ + static bool large_initialized = false; + if (large_initialized) return (_mi_os_large_page_size() > 0); + large_initialized = true; + + // Try to see if large OS pages are supported + // To use large pages on Windows, we first need access permission + // Set "Lock pages in memory" permission in the group policy editor + // + unsigned long err = 0; + HANDLE token = NULL; + BOOL ok = OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token); + if (ok) { + TOKEN_PRIVILEGES tp; + ok = LookupPrivilegeValue(NULL, TEXT("SeLockMemoryPrivilege"), &tp.Privileges[0].Luid); + if (ok) { + tp.PrivilegeCount = 1; + tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; + ok = AdjustTokenPrivileges(token, FALSE, &tp, 0, (PTOKEN_PRIVILEGES)NULL, 0); + if (ok) { + err = GetLastError(); + ok = (err == ERROR_SUCCESS); + if (ok && large_page_size != NULL) { + *large_page_size = GetLargePageMinimum(); + } + } + } + CloseHandle(token); + } + if (!ok) { + if (err == 0) err = GetLastError(); + _mi_warning_message("cannot enable large OS page support, error %lu\n", err); + } + return (ok!=0); +} + + +//--------------------------------------------- +// Initialize +//--------------------------------------------- + +void _mi_prim_mem_init( mi_os_mem_config_t* config ) +{ + config->has_overcommit = false; + config->must_free_whole = true; + config->has_virtual_reserve = true; + // get the page size + SYSTEM_INFO si; + GetSystemInfo(&si); + if (si.dwPageSize > 0) { config->page_size = si.dwPageSize; } + if (si.dwAllocationGranularity > 0) { config->alloc_granularity = si.dwAllocationGranularity; } + // get the VirtualAlloc2 function + HINSTANCE hDll; + hDll = LoadLibrary(TEXT("kernelbase.dll")); + if (hDll != NULL) { + // use VirtualAlloc2FromApp if possible as it is available to Windows store apps + pVirtualAlloc2 = (PVirtualAlloc2)(void (*)(void))GetProcAddress(hDll, "VirtualAlloc2FromApp"); + if (pVirtualAlloc2==NULL) pVirtualAlloc2 = (PVirtualAlloc2)(void (*)(void))GetProcAddress(hDll, "VirtualAlloc2"); + FreeLibrary(hDll); + } + // NtAllocateVirtualMemoryEx is used for huge page allocation + hDll = LoadLibrary(TEXT("ntdll.dll")); + if (hDll != NULL) { + pNtAllocateVirtualMemoryEx = (PNtAllocateVirtualMemoryEx)(void (*)(void))GetProcAddress(hDll, "NtAllocateVirtualMemoryEx"); + FreeLibrary(hDll); + } + // Try to use Win7+ numa API + hDll = LoadLibrary(TEXT("kernel32.dll")); + if (hDll != NULL) { + pGetCurrentProcessorNumberEx = (PGetCurrentProcessorNumberEx)(void (*)(void))GetProcAddress(hDll, "GetCurrentProcessorNumberEx"); + pGetNumaProcessorNodeEx = (PGetNumaProcessorNodeEx)(void (*)(void))GetProcAddress(hDll, "GetNumaProcessorNodeEx"); + pGetNumaNodeProcessorMaskEx = (PGetNumaNodeProcessorMaskEx)(void (*)(void))GetProcAddress(hDll, "GetNumaNodeProcessorMaskEx"); + pGetNumaProcessorNode = (PGetNumaProcessorNode)(void (*)(void))GetProcAddress(hDll, "GetNumaProcessorNode"); + FreeLibrary(hDll); + } + if (mi_option_is_enabled(mi_option_allow_large_os_pages) || mi_option_is_enabled(mi_option_reserve_huge_os_pages)) { + win_enable_large_os_pages(&config->large_page_size); + } +} + + +//--------------------------------------------- +// Free +//--------------------------------------------- + +int _mi_prim_free(void* addr, size_t size ) { + MI_UNUSED(size); + DWORD errcode = 0; + bool err = (VirtualFree(addr, 0, MEM_RELEASE) == 0); + if (err) { errcode = GetLastError(); } + if (errcode == ERROR_INVALID_ADDRESS) { + // In mi_os_mem_alloc_aligned the fallback path may have returned a pointer inside + // the memory region returned by VirtualAlloc; in that case we need to free using + // the start of the region. + MEMORY_BASIC_INFORMATION info = { 0 }; + VirtualQuery(addr, &info, sizeof(info)); + if (info.AllocationBase < addr && ((uint8_t*)addr - (uint8_t*)info.AllocationBase) < (ptrdiff_t)MI_SEGMENT_SIZE) { + errcode = 0; + err = (VirtualFree(info.AllocationBase, 0, MEM_RELEASE) == 0); + if (err) { errcode = GetLastError(); } + } + } + return (int)errcode; +} + + +//--------------------------------------------- +// VirtualAlloc +//--------------------------------------------- + +static void* win_virtual_alloc_prim(void* addr, size_t size, size_t try_alignment, DWORD flags) { + #if (MI_INTPTR_SIZE >= 8) + // on 64-bit systems, try to use the virtual address area after 2TiB for 4MiB aligned allocations + if (addr == NULL) { + void* hint = _mi_os_get_aligned_hint(try_alignment,size); + if (hint != NULL) { + void* p = VirtualAlloc(hint, size, flags, PAGE_READWRITE); + if (p != NULL) return p; + _mi_verbose_message("warning: unable to allocate hinted aligned OS memory (%zu bytes, error code: 0x%x, address: %p, alignment: %zu, flags: 0x%x)\n", size, GetLastError(), hint, try_alignment, flags); + // fall through on error + } + } + #endif + // on modern Windows try use VirtualAlloc2 for aligned allocation + if (try_alignment > 1 && (try_alignment % _mi_os_page_size()) == 0 && pVirtualAlloc2 != NULL) { + MI_MEM_ADDRESS_REQUIREMENTS reqs = { 0, 0, 0 }; + reqs.Alignment = try_alignment; + MI_MEM_EXTENDED_PARAMETER param = { {0, 0}, {0} }; + param.Type.Type = MiMemExtendedParameterAddressRequirements; + param.Arg.Pointer = &reqs; + void* p = (*pVirtualAlloc2)(GetCurrentProcess(), addr, size, flags, PAGE_READWRITE, ¶m, 1); + if (p != NULL) return p; + _mi_warning_message("unable to allocate aligned OS memory (%zu bytes, error code: 0x%x, address: %p, alignment: %zu, flags: 0x%x)\n", size, GetLastError(), addr, try_alignment, flags); + // fall through on error + } + // last resort + return VirtualAlloc(addr, size, flags, PAGE_READWRITE); +} + +static void* win_virtual_alloc(void* addr, size_t size, size_t try_alignment, DWORD flags, bool large_only, bool allow_large, bool* is_large) { + mi_assert_internal(!(large_only && !allow_large)); + static _Atomic(size_t) large_page_try_ok; // = 0; + void* p = NULL; + // Try to allocate large OS pages (2MiB) if allowed or required. + if ((large_only || _mi_os_use_large_page(size, try_alignment)) + && allow_large && (flags&MEM_COMMIT)!=0 && (flags&MEM_RESERVE)!=0) { + size_t try_ok = mi_atomic_load_acquire(&large_page_try_ok); + if (!large_only && try_ok > 0) { + // if a large page allocation fails, it seems the calls to VirtualAlloc get very expensive. + // therefore, once a large page allocation failed, we don't try again for `large_page_try_ok` times. + mi_atomic_cas_strong_acq_rel(&large_page_try_ok, &try_ok, try_ok - 1); + } + else { + // large OS pages must always reserve and commit. + *is_large = true; + p = win_virtual_alloc_prim(addr, size, try_alignment, flags | MEM_LARGE_PAGES); + if (large_only) return p; + // fall back to non-large page allocation on error (`p == NULL`). + if (p == NULL) { + mi_atomic_store_release(&large_page_try_ok,10UL); // on error, don't try again for the next N allocations + } + } + } + // Fall back to regular page allocation + if (p == NULL) { + *is_large = ((flags&MEM_LARGE_PAGES) != 0); + p = win_virtual_alloc_prim(addr, size, try_alignment, flags); + } + //if (p == NULL) { _mi_warning_message("unable to allocate OS memory (%zu bytes, error code: 0x%x, address: %p, alignment: %zu, flags: 0x%x, large only: %d, allow large: %d)\n", size, GetLastError(), addr, try_alignment, flags, large_only, allow_large); } + return p; +} + +int _mi_prim_alloc(size_t size, size_t try_alignment, bool commit, bool allow_large, bool* is_large, bool* is_zero, void** addr) { + mi_assert_internal(size > 0 && (size % _mi_os_page_size()) == 0); + mi_assert_internal(commit || !allow_large); + mi_assert_internal(try_alignment > 0); + *is_zero = true; + int flags = MEM_RESERVE; + if (commit) { flags |= MEM_COMMIT; } + *addr = win_virtual_alloc(NULL, size, try_alignment, flags, false, allow_large, is_large); + return (*addr != NULL ? 0 : (int)GetLastError()); +} + + +//--------------------------------------------- +// Commit/Reset/Protect +//--------------------------------------------- +#ifdef _MSC_VER +#pragma warning(disable:6250) // suppress warning calling VirtualFree without MEM_RELEASE (for decommit) +#endif + +int _mi_prim_commit(void* addr, size_t size, bool* is_zero) { + *is_zero = false; + /* + // zero'ing only happens on an initial commit... but checking upfront seems expensive.. + _MEMORY_BASIC_INFORMATION meminfo; _mi_memzero_var(meminfo); + if (VirtualQuery(addr, &meminfo, size) > 0) { + if ((meminfo.State & MEM_COMMIT) == 0) { + *is_zero = true; + } + } + */ + // commit + void* p = VirtualAlloc(addr, size, MEM_COMMIT, PAGE_READWRITE); + if (p == NULL) return (int)GetLastError(); + return 0; +} + +int _mi_prim_decommit(void* addr, size_t size, bool* needs_recommit) { + BOOL ok = VirtualFree(addr, size, MEM_DECOMMIT); + *needs_recommit = true; // for safety, assume always decommitted even in the case of an error. + return (ok ? 0 : (int)GetLastError()); +} + +int _mi_prim_reset(void* addr, size_t size) { + void* p = VirtualAlloc(addr, size, MEM_RESET, PAGE_READWRITE); + mi_assert_internal(p == addr); + #if 0 + if (p != NULL) { + VirtualUnlock(addr,size); // VirtualUnlock after MEM_RESET removes the memory directly from the working set + } + #endif + return (p != NULL ? 0 : (int)GetLastError()); +} + +int _mi_prim_protect(void* addr, size_t size, bool protect) { + DWORD oldprotect = 0; + BOOL ok = VirtualProtect(addr, size, protect ? PAGE_NOACCESS : PAGE_READWRITE, &oldprotect); + return (ok ? 0 : (int)GetLastError()); +} + + +//--------------------------------------------- +// Huge page allocation +//--------------------------------------------- + +static void* _mi_prim_alloc_huge_os_pagesx(void* hint_addr, size_t size, int numa_node) +{ + const DWORD flags = MEM_LARGE_PAGES | MEM_COMMIT | MEM_RESERVE; + + win_enable_large_os_pages(NULL); + + MI_MEM_EXTENDED_PARAMETER params[3] = { {{0,0},{0}},{{0,0},{0}},{{0,0},{0}} }; + // on modern Windows try use NtAllocateVirtualMemoryEx for 1GiB huge pages + static bool mi_huge_pages_available = true; + if (pNtAllocateVirtualMemoryEx != NULL && mi_huge_pages_available) { + params[0].Type.Type = MiMemExtendedParameterAttributeFlags; + params[0].Arg.ULong64 = MI_MEM_EXTENDED_PARAMETER_NONPAGED_HUGE; + ULONG param_count = 1; + if (numa_node >= 0) { + param_count++; + params[1].Type.Type = MiMemExtendedParameterNumaNode; + params[1].Arg.ULong = (unsigned)numa_node; + } + SIZE_T psize = size; + void* base = hint_addr; + NTSTATUS err = (*pNtAllocateVirtualMemoryEx)(GetCurrentProcess(), &base, &psize, flags, PAGE_READWRITE, params, param_count); + if (err == 0 && base != NULL) { + return base; + } + else { + // fall back to regular large pages + mi_huge_pages_available = false; // don't try further huge pages + _mi_warning_message("unable to allocate using huge (1GiB) pages, trying large (2MiB) pages instead (status 0x%lx)\n", err); + } + } + // on modern Windows try use VirtualAlloc2 for numa aware large OS page allocation + if (pVirtualAlloc2 != NULL && numa_node >= 0) { + params[0].Type.Type = MiMemExtendedParameterNumaNode; + params[0].Arg.ULong = (unsigned)numa_node; + return (*pVirtualAlloc2)(GetCurrentProcess(), hint_addr, size, flags, PAGE_READWRITE, params, 1); + } + + // otherwise use regular virtual alloc on older windows + return VirtualAlloc(hint_addr, size, flags, PAGE_READWRITE); +} + +int _mi_prim_alloc_huge_os_pages(void* hint_addr, size_t size, int numa_node, bool* is_zero, void** addr) { + *is_zero = true; + *addr = _mi_prim_alloc_huge_os_pagesx(hint_addr,size,numa_node); + return (*addr != NULL ? 0 : (int)GetLastError()); +} + + +//--------------------------------------------- +// Numa nodes +//--------------------------------------------- + +size_t _mi_prim_numa_node(void) { + USHORT numa_node = 0; + if (pGetCurrentProcessorNumberEx != NULL && pGetNumaProcessorNodeEx != NULL) { + // Extended API is supported + MI_PROCESSOR_NUMBER pnum; + (*pGetCurrentProcessorNumberEx)(&pnum); + USHORT nnode = 0; + BOOL ok = (*pGetNumaProcessorNodeEx)(&pnum, &nnode); + if (ok) { numa_node = nnode; } + } + else if (pGetNumaProcessorNode != NULL) { + // Vista or earlier, use older API that is limited to 64 processors. Issue #277 + DWORD pnum = GetCurrentProcessorNumber(); + UCHAR nnode = 0; + BOOL ok = pGetNumaProcessorNode((UCHAR)pnum, &nnode); + if (ok) { numa_node = nnode; } + } + return numa_node; +} + +size_t _mi_prim_numa_node_count(void) { + ULONG numa_max = 0; + GetNumaHighestNodeNumber(&numa_max); + // find the highest node number that has actual processors assigned to it. Issue #282 + while(numa_max > 0) { + if (pGetNumaNodeProcessorMaskEx != NULL) { + // Extended API is supported + GROUP_AFFINITY affinity; + if ((*pGetNumaNodeProcessorMaskEx)((USHORT)numa_max, &affinity)) { + if (affinity.Mask != 0) break; // found the maximum non-empty node + } + } + else { + // Vista or earlier, use older API that is limited to 64 processors. + ULONGLONG mask; + if (GetNumaNodeProcessorMask((UCHAR)numa_max, &mask)) { + if (mask != 0) break; // found the maximum non-empty node + }; + } + // max node was invalid or had no processor assigned, try again + numa_max--; + } + return ((size_t)numa_max + 1); +} + + +//---------------------------------------------------------------- +// Clock +//---------------------------------------------------------------- + +static mi_msecs_t mi_to_msecs(LARGE_INTEGER t) { + static LARGE_INTEGER mfreq; // = 0 + if (mfreq.QuadPart == 0LL) { + LARGE_INTEGER f; + QueryPerformanceFrequency(&f); + mfreq.QuadPart = f.QuadPart/1000LL; + if (mfreq.QuadPart == 0) mfreq.QuadPart = 1; + } + return (mi_msecs_t)(t.QuadPart / mfreq.QuadPart); +} + +mi_msecs_t _mi_prim_clock_now(void) { + LARGE_INTEGER t; + QueryPerformanceCounter(&t); + return mi_to_msecs(t); +} + + +//---------------------------------------------------------------- +// Process Info +//---------------------------------------------------------------- + +#include +#include + +static mi_msecs_t filetime_msecs(const FILETIME* ftime) { + ULARGE_INTEGER i; + i.LowPart = ftime->dwLowDateTime; + i.HighPart = ftime->dwHighDateTime; + mi_msecs_t msecs = (i.QuadPart / 10000); // FILETIME is in 100 nano seconds + return msecs; +} + +typedef BOOL (WINAPI *PGetProcessMemoryInfo)(HANDLE, PPROCESS_MEMORY_COUNTERS, DWORD); +static PGetProcessMemoryInfo pGetProcessMemoryInfo = NULL; + +void _mi_prim_process_info(mi_process_info_t* pinfo) +{ + FILETIME ct; + FILETIME ut; + FILETIME st; + FILETIME et; + GetProcessTimes(GetCurrentProcess(), &ct, &et, &st, &ut); + pinfo->utime = filetime_msecs(&ut); + pinfo->stime = filetime_msecs(&st); + + // load psapi on demand + if (pGetProcessMemoryInfo == NULL) { + HINSTANCE hDll = LoadLibrary(TEXT("psapi.dll")); + if (hDll != NULL) { + pGetProcessMemoryInfo = (PGetProcessMemoryInfo)(void (*)(void))GetProcAddress(hDll, "GetProcessMemoryInfo"); + } + } + + // get process info + PROCESS_MEMORY_COUNTERS info; + memset(&info, 0, sizeof(info)); + if (pGetProcessMemoryInfo != NULL) { + pGetProcessMemoryInfo(GetCurrentProcess(), &info, sizeof(info)); + } + pinfo->current_rss = (size_t)info.WorkingSetSize; + pinfo->peak_rss = (size_t)info.PeakWorkingSetSize; + pinfo->current_commit = (size_t)info.PagefileUsage; + pinfo->peak_commit = (size_t)info.PeakPagefileUsage; + pinfo->page_faults = (size_t)info.PageFaultCount; +} + +//---------------------------------------------------------------- +// Output +//---------------------------------------------------------------- + +void _mi_prim_out_stderr( const char* msg ) +{ + // on windows with redirection, the C runtime cannot handle locale dependent output + // after the main thread closes so we use direct console output. + if (!_mi_preloading()) { + // _cputs(msg); // _cputs cannot be used at is aborts if it fails to lock the console + static HANDLE hcon = INVALID_HANDLE_VALUE; + static bool hconIsConsole; + if (hcon == INVALID_HANDLE_VALUE) { + CONSOLE_SCREEN_BUFFER_INFO sbi; + hcon = GetStdHandle(STD_ERROR_HANDLE); + hconIsConsole = ((hcon != INVALID_HANDLE_VALUE) && GetConsoleScreenBufferInfo(hcon, &sbi)); + } + const size_t len = _mi_strlen(msg); + if (len > 0 && len < UINT32_MAX) { + DWORD written = 0; + if (hconIsConsole) { + WriteConsoleA(hcon, msg, (DWORD)len, &written, NULL); + } + else if (hcon != INVALID_HANDLE_VALUE) { + // use direct write if stderr was redirected + WriteFile(hcon, msg, (DWORD)len, &written, NULL); + } + else { + // finally fall back to fputs after all + fputs(msg, stderr); + } + } + } +} + + +//---------------------------------------------------------------- +// Environment +//---------------------------------------------------------------- + +// On Windows use GetEnvironmentVariable instead of getenv to work +// reliably even when this is invoked before the C runtime is initialized. +// i.e. when `_mi_preloading() == true`. +// Note: on windows, environment names are not case sensitive. +bool _mi_prim_getenv(const char* name, char* result, size_t result_size) { + result[0] = 0; + size_t len = GetEnvironmentVariableA(name, result, (DWORD)result_size); + return (len > 0 && len < result_size); +} + + + +//---------------------------------------------------------------- +// Random +//---------------------------------------------------------------- + +#if defined(MI_USE_RTLGENRANDOM) // || defined(__cplusplus) +// We prefer to use BCryptGenRandom instead of (the unofficial) RtlGenRandom but when using +// dynamic overriding, we observed it can raise an exception when compiled with C++, and +// sometimes deadlocks when also running under the VS debugger. +// In contrast, issue #623 implies that on Windows Server 2019 we need to use BCryptGenRandom. +// To be continued.. +#pragma comment (lib,"advapi32.lib") +#define RtlGenRandom SystemFunction036 +mi_decl_externc BOOLEAN NTAPI RtlGenRandom(PVOID RandomBuffer, ULONG RandomBufferLength); + +bool _mi_prim_random_buf(void* buf, size_t buf_len) { + return (RtlGenRandom(buf, (ULONG)buf_len) != 0); +} + +#else + +#ifndef BCRYPT_USE_SYSTEM_PREFERRED_RNG +#define BCRYPT_USE_SYSTEM_PREFERRED_RNG 0x00000002 +#endif + +typedef LONG (NTAPI *PBCryptGenRandom)(HANDLE, PUCHAR, ULONG, ULONG); +static PBCryptGenRandom pBCryptGenRandom = NULL; + +bool _mi_prim_random_buf(void* buf, size_t buf_len) { + if (pBCryptGenRandom == NULL) { + HINSTANCE hDll = LoadLibrary(TEXT("bcrypt.dll")); + if (hDll != NULL) { + pBCryptGenRandom = (PBCryptGenRandom)(void (*)(void))GetProcAddress(hDll, "BCryptGenRandom"); + } + if (pBCryptGenRandom == NULL) return false; + } + return (pBCryptGenRandom(NULL, (PUCHAR)buf, (ULONG)buf_len, BCRYPT_USE_SYSTEM_PREFERRED_RNG) >= 0); +} + +#endif // MI_USE_RTLGENRANDOM + +//---------------------------------------------------------------- +// Thread init/done +//---------------------------------------------------------------- + +#if !defined(MI_SHARED_LIB) + +// use thread local storage keys to detect thread ending +#include +#if (_WIN32_WINNT < 0x600) // before Windows Vista +WINBASEAPI DWORD WINAPI FlsAlloc( _In_opt_ PFLS_CALLBACK_FUNCTION lpCallback ); +WINBASEAPI PVOID WINAPI FlsGetValue( _In_ DWORD dwFlsIndex ); +WINBASEAPI BOOL WINAPI FlsSetValue( _In_ DWORD dwFlsIndex, _In_opt_ PVOID lpFlsData ); +WINBASEAPI BOOL WINAPI FlsFree(_In_ DWORD dwFlsIndex); +#endif + +static DWORD mi_fls_key = (DWORD)(-1); + +static void NTAPI mi_fls_done(PVOID value) { + mi_heap_t* heap = (mi_heap_t*)value; + if (heap != NULL) { + _mi_thread_done(heap); + FlsSetValue(mi_fls_key, NULL); // prevent recursion as _mi_thread_done may set it back to the main heap, issue #672 + } +} + +void _mi_prim_thread_init_auto_done(void) { + mi_fls_key = FlsAlloc(&mi_fls_done); +} + +void _mi_prim_thread_done_auto_done(void) { + // call thread-done on all threads (except the main thread) to prevent + // dangling callback pointer if statically linked with a DLL; Issue #208 + FlsFree(mi_fls_key); +} + +void _mi_prim_thread_associate_default_heap(mi_heap_t* heap) { + mi_assert_internal(mi_fls_key != (DWORD)(-1)); + FlsSetValue(mi_fls_key, heap); +} + +#else + +// Dll; nothing to do as in that case thread_done is handled through the DLL_THREAD_DETACH event. + +void _mi_prim_thread_init_auto_done(void) { +} + +void _mi_prim_thread_done_auto_done(void) { +} + +void _mi_prim_thread_associate_default_heap(mi_heap_t* heap) { + MI_UNUSED(heap); +} + +#endif diff --git a/Objects/mimalloc/prim/windows/readme.md b/Objects/mimalloc/prim/windows/readme.md new file mode 100644 index 00000000000000..217c3d174db473 --- /dev/null +++ b/Objects/mimalloc/prim/windows/readme.md @@ -0,0 +1,17 @@ +## Primitives: + +- `prim.c` contains Windows primitives for OS allocation. + +## Event Tracing for Windows (ETW) + +- `etw.h` is generated from `etw.man` which contains the manifest for mimalloc events. + (100 is an allocation, 101 is for a free) + +- `etw-mimalloc.wprp` is a profile for the Windows Performance Recorder (WPR). + In an admin prompt, you can use: + ``` + > wpr -start src\prim\windows\etw-mimalloc.wprp -filemode + > + > wpr -stop test.etl + ``` + and then open `test.etl` in the Windows Performance Analyzer (WPA). \ No newline at end of file diff --git a/Objects/mimalloc/random.c b/Objects/mimalloc/random.c new file mode 100644 index 00000000000000..35a0633a800d6c --- /dev/null +++ b/Objects/mimalloc/random.c @@ -0,0 +1,254 @@ +/* ---------------------------------------------------------------------------- +Copyright (c) 2019-2021, Microsoft Research, Daan Leijen +This is free software; you can redistribute it and/or modify it under the +terms of the MIT license. A copy of the license can be found in the file +"LICENSE" at the root of this distribution. +-----------------------------------------------------------------------------*/ +#include "mimalloc.h" +#include "mimalloc/internal.h" +#include "mimalloc/prim.h" // _mi_prim_random_buf +#include // memset + +/* ---------------------------------------------------------------------------- +We use our own PRNG to keep predictable performance of random number generation +and to avoid implementations that use a lock. We only use the OS provided +random source to initialize the initial seeds. Since we do not need ultimate +performance but we do rely on the security (for secret cookies in secure mode) +we use a cryptographically secure generator (chacha20). +-----------------------------------------------------------------------------*/ + +#define MI_CHACHA_ROUNDS (20) // perhaps use 12 for better performance? + + +/* ---------------------------------------------------------------------------- +Chacha20 implementation as the original algorithm with a 64-bit nonce +and counter: https://en.wikipedia.org/wiki/Salsa20 +The input matrix has sixteen 32-bit values: +Position 0 to 3: constant key +Position 4 to 11: the key +Position 12 to 13: the counter. +Position 14 to 15: the nonce. + +The implementation uses regular C code which compiles very well on modern compilers. +(gcc x64 has no register spills, and clang 6+ uses SSE instructions) +-----------------------------------------------------------------------------*/ + +static inline uint32_t rotl(uint32_t x, uint32_t shift) { + return (x << shift) | (x >> (32 - shift)); +} + +static inline void qround(uint32_t x[16], size_t a, size_t b, size_t c, size_t d) { + x[a] += x[b]; x[d] = rotl(x[d] ^ x[a], 16); + x[c] += x[d]; x[b] = rotl(x[b] ^ x[c], 12); + x[a] += x[b]; x[d] = rotl(x[d] ^ x[a], 8); + x[c] += x[d]; x[b] = rotl(x[b] ^ x[c], 7); +} + +static void chacha_block(mi_random_ctx_t* ctx) +{ + // scramble into `x` + uint32_t x[16]; + for (size_t i = 0; i < 16; i++) { + x[i] = ctx->input[i]; + } + for (size_t i = 0; i < MI_CHACHA_ROUNDS; i += 2) { + qround(x, 0, 4, 8, 12); + qround(x, 1, 5, 9, 13); + qround(x, 2, 6, 10, 14); + qround(x, 3, 7, 11, 15); + qround(x, 0, 5, 10, 15); + qround(x, 1, 6, 11, 12); + qround(x, 2, 7, 8, 13); + qround(x, 3, 4, 9, 14); + } + + // add scrambled data to the initial state + for (size_t i = 0; i < 16; i++) { + ctx->output[i] = x[i] + ctx->input[i]; + } + ctx->output_available = 16; + + // increment the counter for the next round + ctx->input[12] += 1; + if (ctx->input[12] == 0) { + ctx->input[13] += 1; + if (ctx->input[13] == 0) { // and keep increasing into the nonce + ctx->input[14] += 1; + } + } +} + +static uint32_t chacha_next32(mi_random_ctx_t* ctx) { + if (ctx->output_available <= 0) { + chacha_block(ctx); + ctx->output_available = 16; // (assign again to suppress static analysis warning) + } + const uint32_t x = ctx->output[16 - ctx->output_available]; + ctx->output[16 - ctx->output_available] = 0; // reset once the data is handed out + ctx->output_available--; + return x; +} + +static inline uint32_t read32(const uint8_t* p, size_t idx32) { + const size_t i = 4*idx32; + return ((uint32_t)p[i+0] | (uint32_t)p[i+1] << 8 | (uint32_t)p[i+2] << 16 | (uint32_t)p[i+3] << 24); +} + +static void chacha_init(mi_random_ctx_t* ctx, const uint8_t key[32], uint64_t nonce) +{ + // since we only use chacha for randomness (and not encryption) we + // do not _need_ to read 32-bit values as little endian but we do anyways + // just for being compatible :-) + memset(ctx, 0, sizeof(*ctx)); + for (size_t i = 0; i < 4; i++) { + const uint8_t* sigma = (uint8_t*)"expand 32-byte k"; + ctx->input[i] = read32(sigma,i); + } + for (size_t i = 0; i < 8; i++) { + ctx->input[i + 4] = read32(key,i); + } + ctx->input[12] = 0; + ctx->input[13] = 0; + ctx->input[14] = (uint32_t)nonce; + ctx->input[15] = (uint32_t)(nonce >> 32); +} + +static void chacha_split(mi_random_ctx_t* ctx, uint64_t nonce, mi_random_ctx_t* ctx_new) { + memset(ctx_new, 0, sizeof(*ctx_new)); + _mi_memcpy(ctx_new->input, ctx->input, sizeof(ctx_new->input)); + ctx_new->input[12] = 0; + ctx_new->input[13] = 0; + ctx_new->input[14] = (uint32_t)nonce; + ctx_new->input[15] = (uint32_t)(nonce >> 32); + mi_assert_internal(ctx->input[14] != ctx_new->input[14] || ctx->input[15] != ctx_new->input[15]); // do not reuse nonces! + chacha_block(ctx_new); +} + + +/* ---------------------------------------------------------------------------- +Random interface +-----------------------------------------------------------------------------*/ + +#if MI_DEBUG>1 +static bool mi_random_is_initialized(mi_random_ctx_t* ctx) { + return (ctx != NULL && ctx->input[0] != 0); +} +#endif + +void _mi_random_split(mi_random_ctx_t* ctx, mi_random_ctx_t* ctx_new) { + mi_assert_internal(mi_random_is_initialized(ctx)); + mi_assert_internal(ctx != ctx_new); + chacha_split(ctx, (uintptr_t)ctx_new /*nonce*/, ctx_new); +} + +uintptr_t _mi_random_next(mi_random_ctx_t* ctx) { + mi_assert_internal(mi_random_is_initialized(ctx)); + #if MI_INTPTR_SIZE <= 4 + return chacha_next32(ctx); + #elif MI_INTPTR_SIZE == 8 + return (((uintptr_t)chacha_next32(ctx) << 32) | chacha_next32(ctx)); + #else + # error "define mi_random_next for this platform" + #endif +} + + +/* ---------------------------------------------------------------------------- +To initialize a fresh random context. +If we cannot get good randomness, we fall back to weak randomness based on a timer and ASLR. +-----------------------------------------------------------------------------*/ + +uintptr_t _mi_os_random_weak(uintptr_t extra_seed) { + uintptr_t x = (uintptr_t)&_mi_os_random_weak ^ extra_seed; // ASLR makes the address random + x ^= _mi_prim_clock_now(); + // and do a few randomization steps + uintptr_t max = ((x ^ (x >> 17)) & 0x0F) + 1; + for (uintptr_t i = 0; i < max; i++) { + x = _mi_random_shuffle(x); + } + mi_assert_internal(x != 0); + return x; +} + +static void mi_random_init_ex(mi_random_ctx_t* ctx, bool use_weak) { + uint8_t key[32] = {0}; + if (use_weak || !_mi_prim_random_buf(key, sizeof(key))) { + // if we fail to get random data from the OS, we fall back to a + // weak random source based on the current time + #if !defined(__wasi__) + if (!use_weak) { _mi_warning_message("unable to use secure randomness\n"); } + #endif + uintptr_t x = _mi_os_random_weak(0); + for (size_t i = 0; i < 8; i++) { // key is eight 32-bit words. + x = _mi_random_shuffle(x); + ((uint32_t*)key)[i] = (uint32_t)x; + } + ctx->weak = true; + } + else { + ctx->weak = false; + } + chacha_init(ctx, key, (uintptr_t)ctx /*nonce*/ ); +} + +void _mi_random_init(mi_random_ctx_t* ctx) { + mi_random_init_ex(ctx, false); +} + +void _mi_random_init_weak(mi_random_ctx_t * ctx) { + mi_random_init_ex(ctx, true); +} + +void _mi_random_reinit_if_weak(mi_random_ctx_t * ctx) { + if (ctx->weak) { + _mi_random_init(ctx); + } +} + +/* -------------------------------------------------------- +test vectors from +----------------------------------------------------------- */ +/* +static bool array_equals(uint32_t* x, uint32_t* y, size_t n) { + for (size_t i = 0; i < n; i++) { + if (x[i] != y[i]) return false; + } + return true; +} +static void chacha_test(void) +{ + uint32_t x[4] = { 0x11111111, 0x01020304, 0x9b8d6f43, 0x01234567 }; + uint32_t x_out[4] = { 0xea2a92f4, 0xcb1cf8ce, 0x4581472e, 0x5881c4bb }; + qround(x, 0, 1, 2, 3); + mi_assert_internal(array_equals(x, x_out, 4)); + + uint32_t y[16] = { + 0x879531e0, 0xc5ecf37d, 0x516461b1, 0xc9a62f8a, + 0x44c20ef3, 0x3390af7f, 0xd9fc690b, 0x2a5f714c, + 0x53372767, 0xb00a5631, 0x974c541a, 0x359e9963, + 0x5c971061, 0x3d631689, 0x2098d9d6, 0x91dbd320 }; + uint32_t y_out[16] = { + 0x879531e0, 0xc5ecf37d, 0xbdb886dc, 0xc9a62f8a, + 0x44c20ef3, 0x3390af7f, 0xd9fc690b, 0xcfacafd2, + 0xe46bea80, 0xb00a5631, 0x974c541a, 0x359e9963, + 0x5c971061, 0xccc07c79, 0x2098d9d6, 0x91dbd320 }; + qround(y, 2, 7, 8, 13); + mi_assert_internal(array_equals(y, y_out, 16)); + + mi_random_ctx_t r = { + { 0x61707865, 0x3320646e, 0x79622d32, 0x6b206574, + 0x03020100, 0x07060504, 0x0b0a0908, 0x0f0e0d0c, + 0x13121110, 0x17161514, 0x1b1a1918, 0x1f1e1d1c, + 0x00000001, 0x09000000, 0x4a000000, 0x00000000 }, + {0}, + 0 + }; + uint32_t r_out[16] = { + 0xe4e7f110, 0x15593bd1, 0x1fdd0f50, 0xc47120a3, + 0xc7f4d1c7, 0x0368c033, 0x9aaa2204, 0x4e6cd4c3, + 0x466482d2, 0x09aa9f07, 0x05d7c214, 0xa2028bd9, + 0xd19c12b5, 0xb94e16de, 0xe883d0cb, 0x4e3c50a2 }; + chacha_block(&r); + mi_assert_internal(array_equals(r.output, r_out, 16)); +} +*/ diff --git a/Objects/mimalloc/segment-map.c b/Objects/mimalloc/segment-map.c new file mode 100644 index 00000000000000..3cd2127e56c1a7 --- /dev/null +++ b/Objects/mimalloc/segment-map.c @@ -0,0 +1,153 @@ +/* ---------------------------------------------------------------------------- +Copyright (c) 2019-2023, Microsoft Research, Daan Leijen +This is free software; you can redistribute it and/or modify it under the +terms of the MIT license. A copy of the license can be found in the file +"LICENSE" at the root of this distribution. +-----------------------------------------------------------------------------*/ + +/* ----------------------------------------------------------- + The following functions are to reliably find the segment or + block that encompasses any pointer p (or NULL if it is not + in any of our segments). + We maintain a bitmap of all memory with 1 bit per MI_SEGMENT_SIZE (64MiB) + set to 1 if it contains the segment meta data. +----------------------------------------------------------- */ +#include "mimalloc.h" +#include "mimalloc/internal.h" +#include "mimalloc/atomic.h" + +#if (MI_INTPTR_SIZE==8) +#define MI_MAX_ADDRESS ((size_t)40 << 40) // 40TB (to include huge page areas) +#else +#define MI_MAX_ADDRESS ((size_t)2 << 30) // 2Gb +#endif + +#define MI_SEGMENT_MAP_BITS (MI_MAX_ADDRESS / MI_SEGMENT_SIZE) +#define MI_SEGMENT_MAP_SIZE (MI_SEGMENT_MAP_BITS / 8) +#define MI_SEGMENT_MAP_WSIZE (MI_SEGMENT_MAP_SIZE / MI_INTPTR_SIZE) + +static _Atomic(uintptr_t) mi_segment_map[MI_SEGMENT_MAP_WSIZE + 1]; // 2KiB per TB with 64MiB segments + +static size_t mi_segment_map_index_of(const mi_segment_t* segment, size_t* bitidx) { + mi_assert_internal(_mi_ptr_segment(segment + 1) == segment); // is it aligned on MI_SEGMENT_SIZE? + if ((uintptr_t)segment >= MI_MAX_ADDRESS) { + *bitidx = 0; + return MI_SEGMENT_MAP_WSIZE; + } + else { + const uintptr_t segindex = ((uintptr_t)segment) / MI_SEGMENT_SIZE; + *bitidx = segindex % MI_INTPTR_BITS; + const size_t mapindex = segindex / MI_INTPTR_BITS; + mi_assert_internal(mapindex < MI_SEGMENT_MAP_WSIZE); + return mapindex; + } +} + +void _mi_segment_map_allocated_at(const mi_segment_t* segment) { + size_t bitidx; + size_t index = mi_segment_map_index_of(segment, &bitidx); + mi_assert_internal(index <= MI_SEGMENT_MAP_WSIZE); + if (index==MI_SEGMENT_MAP_WSIZE) return; + uintptr_t mask = mi_atomic_load_relaxed(&mi_segment_map[index]); + uintptr_t newmask; + do { + newmask = (mask | ((uintptr_t)1 << bitidx)); + } while (!mi_atomic_cas_weak_release(&mi_segment_map[index], &mask, newmask)); +} + +void _mi_segment_map_freed_at(const mi_segment_t* segment) { + size_t bitidx; + size_t index = mi_segment_map_index_of(segment, &bitidx); + mi_assert_internal(index <= MI_SEGMENT_MAP_WSIZE); + if (index == MI_SEGMENT_MAP_WSIZE) return; + uintptr_t mask = mi_atomic_load_relaxed(&mi_segment_map[index]); + uintptr_t newmask; + do { + newmask = (mask & ~((uintptr_t)1 << bitidx)); + } while (!mi_atomic_cas_weak_release(&mi_segment_map[index], &mask, newmask)); +} + +// Determine the segment belonging to a pointer or NULL if it is not in a valid segment. +static mi_segment_t* _mi_segment_of(const void* p) { + if (p == NULL) return NULL; + mi_segment_t* segment = _mi_ptr_segment(p); + mi_assert_internal(segment != NULL); + size_t bitidx; + size_t index = mi_segment_map_index_of(segment, &bitidx); + // fast path: for any pointer to valid small/medium/large object or first MI_SEGMENT_SIZE in huge + const uintptr_t mask = mi_atomic_load_relaxed(&mi_segment_map[index]); + if mi_likely((mask & ((uintptr_t)1 << bitidx)) != 0) { + return segment; // yes, allocated by us + } + if (index==MI_SEGMENT_MAP_WSIZE) return NULL; + + // TODO: maintain max/min allocated range for efficiency for more efficient rejection of invalid pointers? + + // search downwards for the first segment in case it is an interior pointer + // could be slow but searches in MI_INTPTR_SIZE * MI_SEGMENT_SIZE (512MiB) steps trough + // valid huge objects + // note: we could maintain a lowest index to speed up the path for invalid pointers? + size_t lobitidx; + size_t loindex; + uintptr_t lobits = mask & (((uintptr_t)1 << bitidx) - 1); + if (lobits != 0) { + loindex = index; + lobitidx = mi_bsr(lobits); // lobits != 0 + } + else if (index == 0) { + return NULL; + } + else { + mi_assert_internal(index > 0); + uintptr_t lomask = mask; + loindex = index; + do { + loindex--; + lomask = mi_atomic_load_relaxed(&mi_segment_map[loindex]); + } while (lomask != 0 && loindex > 0); + if (lomask == 0) return NULL; + lobitidx = mi_bsr(lomask); // lomask != 0 + } + mi_assert_internal(loindex < MI_SEGMENT_MAP_WSIZE); + // take difference as the addresses could be larger than the MAX_ADDRESS space. + size_t diff = (((index - loindex) * (8*MI_INTPTR_SIZE)) + bitidx - lobitidx) * MI_SEGMENT_SIZE; + segment = (mi_segment_t*)((uint8_t*)segment - diff); + + if (segment == NULL) return NULL; + mi_assert_internal((void*)segment < p); + bool cookie_ok = (_mi_ptr_cookie(segment) == segment->cookie); + mi_assert_internal(cookie_ok); + if mi_unlikely(!cookie_ok) return NULL; + if (((uint8_t*)segment + mi_segment_size(segment)) <= (uint8_t*)p) return NULL; // outside the range + mi_assert_internal(p >= (void*)segment && (uint8_t*)p < (uint8_t*)segment + mi_segment_size(segment)); + return segment; +} + +// Is this a valid pointer in our heap? +static bool mi_is_valid_pointer(const void* p) { + return ((_mi_segment_of(p) != NULL) || (_mi_arena_contains(p))); +} + +mi_decl_nodiscard mi_decl_export bool mi_is_in_heap_region(const void* p) mi_attr_noexcept { + return mi_is_valid_pointer(p); +} + +/* +// Return the full segment range belonging to a pointer +static void* mi_segment_range_of(const void* p, size_t* size) { + mi_segment_t* segment = _mi_segment_of(p); + if (segment == NULL) { + if (size != NULL) *size = 0; + return NULL; + } + else { + if (size != NULL) *size = segment->segment_size; + return segment; + } + mi_assert_expensive(page == NULL || mi_segment_is_valid(_mi_page_segment(page),tld)); + mi_assert_internal(page == NULL || (mi_segment_page_size(_mi_page_segment(page)) - (MI_SECURE == 0 ? 0 : _mi_os_page_size())) >= block_size); + mi_reset_delayed(tld); + mi_assert_internal(page == NULL || mi_page_not_in_queue(page, tld)); + return page; +} +*/ diff --git a/Objects/mimalloc/segment.c b/Objects/mimalloc/segment.c new file mode 100644 index 00000000000000..d9b39b03fd6c5f --- /dev/null +++ b/Objects/mimalloc/segment.c @@ -0,0 +1,1616 @@ +/* ---------------------------------------------------------------------------- +Copyright (c) 2018-2020, Microsoft Research, Daan Leijen +This is free software; you can redistribute it and/or modify it under the +terms of the MIT license. A copy of the license can be found in the file +"LICENSE" at the root of this distribution. +-----------------------------------------------------------------------------*/ +#include "mimalloc.h" +#include "mimalloc/internal.h" +#include "mimalloc/atomic.h" + +#include // memset +#include + +#define MI_PAGE_HUGE_ALIGN (256*1024) + +static void mi_segment_try_purge(mi_segment_t* segment, bool force, mi_stats_t* stats); + + +// ------------------------------------------------------------------- +// commit mask +// ------------------------------------------------------------------- + +static bool mi_commit_mask_all_set(const mi_commit_mask_t* commit, const mi_commit_mask_t* cm) { + for (size_t i = 0; i < MI_COMMIT_MASK_FIELD_COUNT; i++) { + if ((commit->mask[i] & cm->mask[i]) != cm->mask[i]) return false; + } + return true; +} + +static bool mi_commit_mask_any_set(const mi_commit_mask_t* commit, const mi_commit_mask_t* cm) { + for (size_t i = 0; i < MI_COMMIT_MASK_FIELD_COUNT; i++) { + if ((commit->mask[i] & cm->mask[i]) != 0) return true; + } + return false; +} + +static void mi_commit_mask_create_intersect(const mi_commit_mask_t* commit, const mi_commit_mask_t* cm, mi_commit_mask_t* res) { + for (size_t i = 0; i < MI_COMMIT_MASK_FIELD_COUNT; i++) { + res->mask[i] = (commit->mask[i] & cm->mask[i]); + } +} + +static void mi_commit_mask_clear(mi_commit_mask_t* res, const mi_commit_mask_t* cm) { + for (size_t i = 0; i < MI_COMMIT_MASK_FIELD_COUNT; i++) { + res->mask[i] &= ~(cm->mask[i]); + } +} + +static void mi_commit_mask_set(mi_commit_mask_t* res, const mi_commit_mask_t* cm) { + for (size_t i = 0; i < MI_COMMIT_MASK_FIELD_COUNT; i++) { + res->mask[i] |= cm->mask[i]; + } +} + +static void mi_commit_mask_create(size_t bitidx, size_t bitcount, mi_commit_mask_t* cm) { + mi_assert_internal(bitidx < MI_COMMIT_MASK_BITS); + mi_assert_internal((bitidx + bitcount) <= MI_COMMIT_MASK_BITS); + if (bitcount == MI_COMMIT_MASK_BITS) { + mi_assert_internal(bitidx==0); + mi_commit_mask_create_full(cm); + } + else if (bitcount == 0) { + mi_commit_mask_create_empty(cm); + } + else { + mi_commit_mask_create_empty(cm); + size_t i = bitidx / MI_COMMIT_MASK_FIELD_BITS; + size_t ofs = bitidx % MI_COMMIT_MASK_FIELD_BITS; + while (bitcount > 0) { + mi_assert_internal(i < MI_COMMIT_MASK_FIELD_COUNT); + size_t avail = MI_COMMIT_MASK_FIELD_BITS - ofs; + size_t count = (bitcount > avail ? avail : bitcount); + size_t mask = (count >= MI_COMMIT_MASK_FIELD_BITS ? ~((size_t)0) : (((size_t)1 << count) - 1) << ofs); + cm->mask[i] = mask; + bitcount -= count; + ofs = 0; + i++; + } + } +} + +size_t _mi_commit_mask_committed_size(const mi_commit_mask_t* cm, size_t total) { + mi_assert_internal((total%MI_COMMIT_MASK_BITS)==0); + size_t count = 0; + for (size_t i = 0; i < MI_COMMIT_MASK_FIELD_COUNT; i++) { + size_t mask = cm->mask[i]; + if (~mask == 0) { + count += MI_COMMIT_MASK_FIELD_BITS; + } + else { + for (; mask != 0; mask >>= 1) { // todo: use popcount + if ((mask&1)!=0) count++; + } + } + } + // we use total since for huge segments each commit bit may represent a larger size + return ((total / MI_COMMIT_MASK_BITS) * count); +} + + +size_t _mi_commit_mask_next_run(const mi_commit_mask_t* cm, size_t* idx) { + size_t i = (*idx) / MI_COMMIT_MASK_FIELD_BITS; + size_t ofs = (*idx) % MI_COMMIT_MASK_FIELD_BITS; + size_t mask = 0; + // find first ones + while (i < MI_COMMIT_MASK_FIELD_COUNT) { + mask = cm->mask[i]; + mask >>= ofs; + if (mask != 0) { + while ((mask&1) == 0) { + mask >>= 1; + ofs++; + } + break; + } + i++; + ofs = 0; + } + if (i >= MI_COMMIT_MASK_FIELD_COUNT) { + // not found + *idx = MI_COMMIT_MASK_BITS; + return 0; + } + else { + // found, count ones + size_t count = 0; + *idx = (i*MI_COMMIT_MASK_FIELD_BITS) + ofs; + do { + mi_assert_internal(ofs < MI_COMMIT_MASK_FIELD_BITS && (mask&1) == 1); + do { + count++; + mask >>= 1; + } while ((mask&1) == 1); + if ((((*idx + count) % MI_COMMIT_MASK_FIELD_BITS) == 0)) { + i++; + if (i >= MI_COMMIT_MASK_FIELD_COUNT) break; + mask = cm->mask[i]; + ofs = 0; + } + } while ((mask&1) == 1); + mi_assert_internal(count > 0); + return count; + } +} + + +/* -------------------------------------------------------------------------------- + Segment allocation + + If a thread ends, it "abandons" pages with used blocks + and there is an abandoned segment list whose segments can + be reclaimed by still running threads, much like work-stealing. +-------------------------------------------------------------------------------- */ + + +/* ----------------------------------------------------------- + Slices +----------------------------------------------------------- */ + + +static const mi_slice_t* mi_segment_slices_end(const mi_segment_t* segment) { + return &segment->slices[segment->slice_entries]; +} + +static uint8_t* mi_slice_start(const mi_slice_t* slice) { + mi_segment_t* segment = _mi_ptr_segment(slice); + mi_assert_internal(slice >= segment->slices && slice < mi_segment_slices_end(segment)); + return ((uint8_t*)segment + ((slice - segment->slices)*MI_SEGMENT_SLICE_SIZE)); +} + + +/* ----------------------------------------------------------- + Bins +----------------------------------------------------------- */ +// Use bit scan forward to quickly find the first zero bit if it is available + +static inline size_t mi_slice_bin8(size_t slice_count) { + if (slice_count<=1) return slice_count; + mi_assert_internal(slice_count <= MI_SLICES_PER_SEGMENT); + slice_count--; + size_t s = mi_bsr(slice_count); // slice_count > 1 + if (s <= 2) return slice_count + 1; + size_t bin = ((s << 2) | ((slice_count >> (s - 2))&0x03)) - 4; + return bin; +} + +static inline size_t mi_slice_bin(size_t slice_count) { + mi_assert_internal(slice_count*MI_SEGMENT_SLICE_SIZE <= MI_SEGMENT_SIZE); + mi_assert_internal(mi_slice_bin8(MI_SLICES_PER_SEGMENT) <= MI_SEGMENT_BIN_MAX); + size_t bin = mi_slice_bin8(slice_count); + mi_assert_internal(bin <= MI_SEGMENT_BIN_MAX); + return bin; +} + +static inline size_t mi_slice_index(const mi_slice_t* slice) { + mi_segment_t* segment = _mi_ptr_segment(slice); + ptrdiff_t index = slice - segment->slices; + mi_assert_internal(index >= 0 && index < (ptrdiff_t)segment->slice_entries); + return index; +} + + +/* ----------------------------------------------------------- + Slice span queues +----------------------------------------------------------- */ + +static void mi_span_queue_push(mi_span_queue_t* sq, mi_slice_t* slice) { + // todo: or push to the end? + mi_assert_internal(slice->prev == NULL && slice->next==NULL); + slice->prev = NULL; // paranoia + slice->next = sq->first; + sq->first = slice; + if (slice->next != NULL) slice->next->prev = slice; + else sq->last = slice; + slice->xblock_size = 0; // free +} + +static mi_span_queue_t* mi_span_queue_for(size_t slice_count, mi_segments_tld_t* tld) { + size_t bin = mi_slice_bin(slice_count); + mi_span_queue_t* sq = &tld->spans[bin]; + mi_assert_internal(sq->slice_count >= slice_count); + return sq; +} + +static void mi_span_queue_delete(mi_span_queue_t* sq, mi_slice_t* slice) { + mi_assert_internal(slice->xblock_size==0 && slice->slice_count>0 && slice->slice_offset==0); + // should work too if the queue does not contain slice (which can happen during reclaim) + if (slice->prev != NULL) slice->prev->next = slice->next; + if (slice == sq->first) sq->first = slice->next; + if (slice->next != NULL) slice->next->prev = slice->prev; + if (slice == sq->last) sq->last = slice->prev; + slice->prev = NULL; + slice->next = NULL; + slice->xblock_size = 1; // no more free +} + + +/* ----------------------------------------------------------- + Invariant checking +----------------------------------------------------------- */ + +static bool mi_slice_is_used(const mi_slice_t* slice) { + return (slice->xblock_size > 0); +} + + +#if (MI_DEBUG>=3) +static bool mi_span_queue_contains(mi_span_queue_t* sq, mi_slice_t* slice) { + for (mi_slice_t* s = sq->first; s != NULL; s = s->next) { + if (s==slice) return true; + } + return false; +} + +static bool mi_segment_is_valid(mi_segment_t* segment, mi_segments_tld_t* tld) { + mi_assert_internal(segment != NULL); + mi_assert_internal(_mi_ptr_cookie(segment) == segment->cookie); + mi_assert_internal(segment->abandoned <= segment->used); + mi_assert_internal(segment->thread_id == 0 || segment->thread_id == _mi_thread_id()); + mi_assert_internal(mi_commit_mask_all_set(&segment->commit_mask, &segment->purge_mask)); // can only decommit committed blocks + //mi_assert_internal(segment->segment_info_size % MI_SEGMENT_SLICE_SIZE == 0); + mi_slice_t* slice = &segment->slices[0]; + const mi_slice_t* end = mi_segment_slices_end(segment); + size_t used_count = 0; + mi_span_queue_t* sq; + while(slice < end) { + mi_assert_internal(slice->slice_count > 0); + mi_assert_internal(slice->slice_offset == 0); + size_t index = mi_slice_index(slice); + size_t maxindex = (index + slice->slice_count >= segment->slice_entries ? segment->slice_entries : index + slice->slice_count) - 1; + if (mi_slice_is_used(slice)) { // a page in use, we need at least MAX_SLICE_OFFSET valid back offsets + used_count++; + for (size_t i = 0; i <= MI_MAX_SLICE_OFFSET && index + i <= maxindex; i++) { + mi_assert_internal(segment->slices[index + i].slice_offset == i*sizeof(mi_slice_t)); + mi_assert_internal(i==0 || segment->slices[index + i].slice_count == 0); + mi_assert_internal(i==0 || segment->slices[index + i].xblock_size == 1); + } + // and the last entry as well (for coalescing) + const mi_slice_t* last = slice + slice->slice_count - 1; + if (last > slice && last < mi_segment_slices_end(segment)) { + mi_assert_internal(last->slice_offset == (slice->slice_count-1)*sizeof(mi_slice_t)); + mi_assert_internal(last->slice_count == 0); + mi_assert_internal(last->xblock_size == 1); + } + } + else { // free range of slices; only last slice needs a valid back offset + mi_slice_t* last = &segment->slices[maxindex]; + if (segment->kind != MI_SEGMENT_HUGE || slice->slice_count <= (segment->slice_entries - segment->segment_info_slices)) { + mi_assert_internal((uint8_t*)slice == (uint8_t*)last - last->slice_offset); + } + mi_assert_internal(slice == last || last->slice_count == 0 ); + mi_assert_internal(last->xblock_size == 0 || (segment->kind==MI_SEGMENT_HUGE && last->xblock_size==1)); + if (segment->kind != MI_SEGMENT_HUGE && segment->thread_id != 0) { // segment is not huge or abandoned + sq = mi_span_queue_for(slice->slice_count,tld); + mi_assert_internal(mi_span_queue_contains(sq,slice)); + } + } + slice = &segment->slices[maxindex+1]; + } + mi_assert_internal(slice == end); + mi_assert_internal(used_count == segment->used + 1); + return true; +} +#endif + +/* ----------------------------------------------------------- + Segment size calculations +----------------------------------------------------------- */ + +static size_t mi_segment_info_size(mi_segment_t* segment) { + return segment->segment_info_slices * MI_SEGMENT_SLICE_SIZE; +} + +static uint8_t* _mi_segment_page_start_from_slice(const mi_segment_t* segment, const mi_slice_t* slice, size_t xblock_size, size_t* page_size) +{ + ptrdiff_t idx = slice - segment->slices; + size_t psize = (size_t)slice->slice_count * MI_SEGMENT_SLICE_SIZE; + // make the start not OS page aligned for smaller blocks to avoid page/cache effects + // note: the offset must always be an xblock_size multiple since we assume small allocations + // are aligned (see `mi_heap_malloc_aligned`). + size_t start_offset = 0; + if (xblock_size >= MI_INTPTR_SIZE) { + if (xblock_size <= 64) { start_offset = 3*xblock_size; } + else if (xblock_size <= 512) { start_offset = xblock_size; } + } + if (page_size != NULL) { *page_size = psize - start_offset; } + return (uint8_t*)segment + ((idx*MI_SEGMENT_SLICE_SIZE) + start_offset); +} + +// Start of the page available memory; can be used on uninitialized pages +uint8_t* _mi_segment_page_start(const mi_segment_t* segment, const mi_page_t* page, size_t* page_size) +{ + const mi_slice_t* slice = mi_page_to_slice((mi_page_t*)page); + uint8_t* p = _mi_segment_page_start_from_slice(segment, slice, page->xblock_size, page_size); + mi_assert_internal(page->xblock_size > 0 || _mi_ptr_page(p) == page); + mi_assert_internal(_mi_ptr_segment(p) == segment); + return p; +} + + +static size_t mi_segment_calculate_slices(size_t required, size_t* pre_size, size_t* info_slices) { + size_t page_size = _mi_os_page_size(); + size_t isize = _mi_align_up(sizeof(mi_segment_t), page_size); + size_t guardsize = 0; + + if (MI_SECURE>0) { + // in secure mode, we set up a protected page in between the segment info + // and the page data (and one at the end of the segment) + guardsize = page_size; + if (required > 0) { + required = _mi_align_up(required, MI_SEGMENT_SLICE_SIZE) + page_size; + } + } + + if (pre_size != NULL) *pre_size = isize; + isize = _mi_align_up(isize + guardsize, MI_SEGMENT_SLICE_SIZE); + if (info_slices != NULL) *info_slices = isize / MI_SEGMENT_SLICE_SIZE; + size_t segment_size = (required==0 ? MI_SEGMENT_SIZE : _mi_align_up( required + isize + guardsize, MI_SEGMENT_SLICE_SIZE) ); + mi_assert_internal(segment_size % MI_SEGMENT_SLICE_SIZE == 0); + return (segment_size / MI_SEGMENT_SLICE_SIZE); +} + + +/* ---------------------------------------------------------------------------- +Segment caches +We keep a small segment cache per thread to increase local +reuse and avoid setting/clearing guard pages in secure mode. +------------------------------------------------------------------------------- */ + +static void mi_segments_track_size(long segment_size, mi_segments_tld_t* tld) { + if (segment_size>=0) _mi_stat_increase(&tld->stats->segments,1); + else _mi_stat_decrease(&tld->stats->segments,1); + tld->count += (segment_size >= 0 ? 1 : -1); + if (tld->count > tld->peak_count) tld->peak_count = tld->count; + tld->current_size += segment_size; + if (tld->current_size > tld->peak_size) tld->peak_size = tld->current_size; +} + +static void mi_segment_os_free(mi_segment_t* segment, mi_segments_tld_t* tld) { + segment->thread_id = 0; + _mi_segment_map_freed_at(segment); + mi_segments_track_size(-((long)mi_segment_size(segment)),tld); + if (MI_SECURE>0) { + // _mi_os_unprotect(segment, mi_segment_size(segment)); // ensure no more guard pages are set + // unprotect the guard pages; we cannot just unprotect the whole segment size as part may be decommitted + size_t os_pagesize = _mi_os_page_size(); + _mi_os_unprotect((uint8_t*)segment + mi_segment_info_size(segment) - os_pagesize, os_pagesize); + uint8_t* end = (uint8_t*)segment + mi_segment_size(segment) - os_pagesize; + _mi_os_unprotect(end, os_pagesize); + } + + // purge delayed decommits now? (no, leave it to the arena) + // mi_segment_try_purge(segment,true,tld->stats); + + const size_t size = mi_segment_size(segment); + const size_t csize = _mi_commit_mask_committed_size(&segment->commit_mask, size); + + _mi_abandoned_await_readers(tld->abandoned); // wait until safe to free + _mi_arena_free(segment, mi_segment_size(segment), csize, segment->memid, tld->stats); +} + +// called by threads that are terminating +void _mi_segment_thread_collect(mi_segments_tld_t* tld) { + MI_UNUSED(tld); + // nothing to do +} + + +/* ----------------------------------------------------------- + Commit/Decommit ranges +----------------------------------------------------------- */ + +static void mi_segment_commit_mask(mi_segment_t* segment, bool conservative, uint8_t* p, size_t size, uint8_t** start_p, size_t* full_size, mi_commit_mask_t* cm) { + mi_assert_internal(_mi_ptr_segment(p + 1) == segment); + mi_assert_internal(segment->kind != MI_SEGMENT_HUGE); + mi_commit_mask_create_empty(cm); + if (size == 0 || size > MI_SEGMENT_SIZE || segment->kind == MI_SEGMENT_HUGE) return; + const size_t segstart = mi_segment_info_size(segment); + const size_t segsize = mi_segment_size(segment); + if (p >= (uint8_t*)segment + segsize) return; + + size_t pstart = (p - (uint8_t*)segment); + mi_assert_internal(pstart + size <= segsize); + + size_t start; + size_t end; + if (conservative) { + // decommit conservative + start = _mi_align_up(pstart, MI_COMMIT_SIZE); + end = _mi_align_down(pstart + size, MI_COMMIT_SIZE); + mi_assert_internal(start >= segstart); + mi_assert_internal(end <= segsize); + } + else { + // commit liberal + start = _mi_align_down(pstart, MI_MINIMAL_COMMIT_SIZE); + end = _mi_align_up(pstart + size, MI_MINIMAL_COMMIT_SIZE); + } + if (pstart >= segstart && start < segstart) { // note: the mask is also calculated for an initial commit of the info area + start = segstart; + } + if (end > segsize) { + end = segsize; + } + + mi_assert_internal(start <= pstart && (pstart + size) <= end); + mi_assert_internal(start % MI_COMMIT_SIZE==0 && end % MI_COMMIT_SIZE == 0); + *start_p = (uint8_t*)segment + start; + *full_size = (end > start ? end - start : 0); + if (*full_size == 0) return; + + size_t bitidx = start / MI_COMMIT_SIZE; + mi_assert_internal(bitidx < MI_COMMIT_MASK_BITS); + + size_t bitcount = *full_size / MI_COMMIT_SIZE; // can be 0 + if (bitidx + bitcount > MI_COMMIT_MASK_BITS) { + _mi_warning_message("commit mask overflow: idx=%zu count=%zu start=%zx end=%zx p=0x%p size=%zu fullsize=%zu\n", bitidx, bitcount, start, end, p, size, *full_size); + } + mi_assert_internal((bitidx + bitcount) <= MI_COMMIT_MASK_BITS); + mi_commit_mask_create(bitidx, bitcount, cm); +} + +static bool mi_segment_commit(mi_segment_t* segment, uint8_t* p, size_t size, mi_stats_t* stats) { + mi_assert_internal(mi_commit_mask_all_set(&segment->commit_mask, &segment->purge_mask)); + + // commit liberal + uint8_t* start = NULL; + size_t full_size = 0; + mi_commit_mask_t mask; + mi_segment_commit_mask(segment, false /* conservative? */, p, size, &start, &full_size, &mask); + if (mi_commit_mask_is_empty(&mask) || full_size == 0) return true; + + if (!mi_commit_mask_all_set(&segment->commit_mask, &mask)) { + // committing + bool is_zero = false; + mi_commit_mask_t cmask; + mi_commit_mask_create_intersect(&segment->commit_mask, &mask, &cmask); + _mi_stat_decrease(&_mi_stats_main.committed, _mi_commit_mask_committed_size(&cmask, MI_SEGMENT_SIZE)); // adjust for overlap + if (!_mi_os_commit(start, full_size, &is_zero, stats)) return false; + mi_commit_mask_set(&segment->commit_mask, &mask); + } + + // increase purge expiration when using part of delayed purges -- we assume more allocations are coming soon. + if (mi_commit_mask_any_set(&segment->purge_mask, &mask)) { + segment->purge_expire = _mi_clock_now() + mi_option_get(mi_option_purge_delay); + } + + // always clear any delayed purges in our range (as they are either committed now) + mi_commit_mask_clear(&segment->purge_mask, &mask); + return true; +} + +static bool mi_segment_ensure_committed(mi_segment_t* segment, uint8_t* p, size_t size, mi_stats_t* stats) { + mi_assert_internal(mi_commit_mask_all_set(&segment->commit_mask, &segment->purge_mask)); + // note: assumes commit_mask is always full for huge segments as otherwise the commit mask bits can overflow + if (mi_commit_mask_is_full(&segment->commit_mask) && mi_commit_mask_is_empty(&segment->purge_mask)) return true; // fully committed + mi_assert_internal(segment->kind != MI_SEGMENT_HUGE); + return mi_segment_commit(segment, p, size, stats); +} + +static bool mi_segment_purge(mi_segment_t* segment, uint8_t* p, size_t size, mi_stats_t* stats) { + mi_assert_internal(mi_commit_mask_all_set(&segment->commit_mask, &segment->purge_mask)); + if (!segment->allow_purge) return true; + + // purge conservative + uint8_t* start = NULL; + size_t full_size = 0; + mi_commit_mask_t mask; + mi_segment_commit_mask(segment, true /* conservative? */, p, size, &start, &full_size, &mask); + if (mi_commit_mask_is_empty(&mask) || full_size==0) return true; + + if (mi_commit_mask_any_set(&segment->commit_mask, &mask)) { + // purging + mi_assert_internal((void*)start != (void*)segment); + mi_assert_internal(segment->allow_decommit); + const bool decommitted = _mi_os_purge(start, full_size, stats); // reset or decommit + if (decommitted) { + mi_commit_mask_t cmask; + mi_commit_mask_create_intersect(&segment->commit_mask, &mask, &cmask); + _mi_stat_increase(&_mi_stats_main.committed, full_size - _mi_commit_mask_committed_size(&cmask, MI_SEGMENT_SIZE)); // adjust for double counting + mi_commit_mask_clear(&segment->commit_mask, &mask); + } + } + + // always clear any scheduled purges in our range + mi_commit_mask_clear(&segment->purge_mask, &mask); + return true; +} + +static void mi_segment_schedule_purge(mi_segment_t* segment, uint8_t* p, size_t size, mi_stats_t* stats) { + if (!segment->allow_purge) return; + + if (mi_option_get(mi_option_purge_delay) == 0) { + mi_segment_purge(segment, p, size, stats); + } + else { + // register for future purge in the purge mask + uint8_t* start = NULL; + size_t full_size = 0; + mi_commit_mask_t mask; + mi_segment_commit_mask(segment, true /*conservative*/, p, size, &start, &full_size, &mask); + if (mi_commit_mask_is_empty(&mask) || full_size==0) return; + + // update delayed commit + mi_assert_internal(segment->purge_expire > 0 || mi_commit_mask_is_empty(&segment->purge_mask)); + mi_commit_mask_t cmask; + mi_commit_mask_create_intersect(&segment->commit_mask, &mask, &cmask); // only purge what is committed; span_free may try to decommit more + mi_commit_mask_set(&segment->purge_mask, &cmask); + mi_msecs_t now = _mi_clock_now(); + if (segment->purge_expire == 0) { + // no previous purgess, initialize now + segment->purge_expire = now + mi_option_get(mi_option_purge_delay); + } + else if (segment->purge_expire <= now) { + // previous purge mask already expired + if (segment->purge_expire + mi_option_get(mi_option_purge_extend_delay) <= now) { + mi_segment_try_purge(segment, true, stats); + } + else { + segment->purge_expire = now + mi_option_get(mi_option_purge_extend_delay); // (mi_option_get(mi_option_purge_delay) / 8); // wait a tiny bit longer in case there is a series of free's + } + } + else { + // previous purge mask is not yet expired, increase the expiration by a bit. + segment->purge_expire += mi_option_get(mi_option_purge_extend_delay); + } + } +} + +static void mi_segment_try_purge(mi_segment_t* segment, bool force, mi_stats_t* stats) { + if (!segment->allow_purge || mi_commit_mask_is_empty(&segment->purge_mask)) return; + mi_msecs_t now = _mi_clock_now(); + if (!force && now < segment->purge_expire) return; + + mi_commit_mask_t mask = segment->purge_mask; + segment->purge_expire = 0; + mi_commit_mask_create_empty(&segment->purge_mask); + + size_t idx; + size_t count; + mi_commit_mask_foreach(&mask, idx, count) { + // if found, decommit that sequence + if (count > 0) { + uint8_t* p = (uint8_t*)segment + (idx*MI_COMMIT_SIZE); + size_t size = count * MI_COMMIT_SIZE; + mi_segment_purge(segment, p, size, stats); + } + } + mi_commit_mask_foreach_end() + mi_assert_internal(mi_commit_mask_is_empty(&segment->purge_mask)); +} + + +/* ----------------------------------------------------------- + Span free +----------------------------------------------------------- */ + +static bool mi_segment_is_abandoned(mi_segment_t* segment) { + return (segment->thread_id == 0); +} + +// note: can be called on abandoned segments +static void mi_segment_span_free(mi_segment_t* segment, size_t slice_index, size_t slice_count, bool allow_purge, mi_segments_tld_t* tld) { + mi_assert_internal(slice_index < segment->slice_entries); + mi_span_queue_t* sq = (segment->kind == MI_SEGMENT_HUGE || mi_segment_is_abandoned(segment) + ? NULL : mi_span_queue_for(slice_count,tld)); + if (slice_count==0) slice_count = 1; + mi_assert_internal(slice_index + slice_count - 1 < segment->slice_entries); + + // set first and last slice (the intermediates can be undetermined) + mi_slice_t* slice = &segment->slices[slice_index]; + slice->slice_count = (uint32_t)slice_count; + mi_assert_internal(slice->slice_count == slice_count); // no overflow? + slice->slice_offset = 0; + if (slice_count > 1) { + mi_slice_t* last = &segment->slices[slice_index + slice_count - 1]; + last->slice_count = 0; + last->slice_offset = (uint32_t)(sizeof(mi_page_t)*(slice_count - 1)); + last->xblock_size = 0; + } + + // perhaps decommit + if (allow_purge) { + mi_segment_schedule_purge(segment, mi_slice_start(slice), slice_count * MI_SEGMENT_SLICE_SIZE, tld->stats); + } + + // and push it on the free page queue (if it was not a huge page) + if (sq != NULL) mi_span_queue_push( sq, slice ); + else slice->xblock_size = 0; // mark huge page as free anyways +} + +/* +// called from reclaim to add existing free spans +static void mi_segment_span_add_free(mi_slice_t* slice, mi_segments_tld_t* tld) { + mi_segment_t* segment = _mi_ptr_segment(slice); + mi_assert_internal(slice->xblock_size==0 && slice->slice_count>0 && slice->slice_offset==0); + size_t slice_index = mi_slice_index(slice); + mi_segment_span_free(segment,slice_index,slice->slice_count,tld); +} +*/ + +static void mi_segment_span_remove_from_queue(mi_slice_t* slice, mi_segments_tld_t* tld) { + mi_assert_internal(slice->slice_count > 0 && slice->slice_offset==0 && slice->xblock_size==0); + mi_assert_internal(_mi_ptr_segment(slice)->kind != MI_SEGMENT_HUGE); + mi_span_queue_t* sq = mi_span_queue_for(slice->slice_count, tld); + mi_span_queue_delete(sq, slice); +} + +// note: can be called on abandoned segments +static mi_slice_t* mi_segment_span_free_coalesce(mi_slice_t* slice, mi_segments_tld_t* tld) { + mi_assert_internal(slice != NULL && slice->slice_count > 0 && slice->slice_offset == 0); + mi_segment_t* segment = _mi_ptr_segment(slice); + bool is_abandoned = mi_segment_is_abandoned(segment); + + // for huge pages, just mark as free but don't add to the queues + if (segment->kind == MI_SEGMENT_HUGE) { + // issue #691: segment->used can be 0 if the huge page block was freed while abandoned (reclaim will get here in that case) + mi_assert_internal((segment->used==0 && slice->xblock_size==0) || segment->used == 1); // decreased right after this call in `mi_segment_page_clear` + slice->xblock_size = 0; // mark as free anyways + // we should mark the last slice `xblock_size=0` now to maintain invariants but we skip it to + // avoid a possible cache miss (and the segment is about to be freed) + return slice; + } + + // otherwise coalesce the span and add to the free span queues + size_t slice_count = slice->slice_count; + mi_slice_t* next = slice + slice->slice_count; + mi_assert_internal(next <= mi_segment_slices_end(segment)); + if (next < mi_segment_slices_end(segment) && next->xblock_size==0) { + // free next block -- remove it from free and merge + mi_assert_internal(next->slice_count > 0 && next->slice_offset==0); + slice_count += next->slice_count; // extend + if (!is_abandoned) { mi_segment_span_remove_from_queue(next, tld); } + } + if (slice > segment->slices) { + mi_slice_t* prev = mi_slice_first(slice - 1); + mi_assert_internal(prev >= segment->slices); + if (prev->xblock_size==0) { + // free previous slice -- remove it from free and merge + mi_assert_internal(prev->slice_count > 0 && prev->slice_offset==0); + slice_count += prev->slice_count; + if (!is_abandoned) { mi_segment_span_remove_from_queue(prev, tld); } + slice = prev; + } + } + + // and add the new free page + mi_segment_span_free(segment, mi_slice_index(slice), slice_count, true, tld); + return slice; +} + + + +/* ----------------------------------------------------------- + Page allocation +----------------------------------------------------------- */ + +// Note: may still return NULL if committing the memory failed +static mi_page_t* mi_segment_span_allocate(mi_segment_t* segment, size_t slice_index, size_t slice_count, mi_segments_tld_t* tld) { + mi_assert_internal(slice_index < segment->slice_entries); + mi_slice_t* const slice = &segment->slices[slice_index]; + mi_assert_internal(slice->xblock_size==0 || slice->xblock_size==1); + + // commit before changing the slice data + if (!mi_segment_ensure_committed(segment, _mi_segment_page_start_from_slice(segment, slice, 0, NULL), slice_count * MI_SEGMENT_SLICE_SIZE, tld->stats)) { + return NULL; // commit failed! + } + + // convert the slices to a page + slice->slice_offset = 0; + slice->slice_count = (uint32_t)slice_count; + mi_assert_internal(slice->slice_count == slice_count); + const size_t bsize = slice_count * MI_SEGMENT_SLICE_SIZE; + slice->xblock_size = (uint32_t)(bsize >= MI_HUGE_BLOCK_SIZE ? MI_HUGE_BLOCK_SIZE : bsize); + mi_page_t* page = mi_slice_to_page(slice); + mi_assert_internal(mi_page_block_size(page) == bsize); + + // set slice back pointers for the first MI_MAX_SLICE_OFFSET entries + size_t extra = slice_count-1; + if (extra > MI_MAX_SLICE_OFFSET) extra = MI_MAX_SLICE_OFFSET; + if (slice_index + extra >= segment->slice_entries) extra = segment->slice_entries - slice_index - 1; // huge objects may have more slices than avaiable entries in the segment->slices + + mi_slice_t* slice_next = slice + 1; + for (size_t i = 1; i <= extra; i++, slice_next++) { + slice_next->slice_offset = (uint32_t)(sizeof(mi_slice_t)*i); + slice_next->slice_count = 0; + slice_next->xblock_size = 1; + } + + // and also for the last one (if not set already) (the last one is needed for coalescing and for large alignments) + // note: the cast is needed for ubsan since the index can be larger than MI_SLICES_PER_SEGMENT for huge allocations (see #543) + mi_slice_t* last = slice + slice_count - 1; + mi_slice_t* end = (mi_slice_t*)mi_segment_slices_end(segment); + if (last > end) last = end; + if (last > slice) { + last->slice_offset = (uint32_t)(sizeof(mi_slice_t) * (last - slice)); + last->slice_count = 0; + last->xblock_size = 1; + } + + // and initialize the page + page->is_committed = true; + segment->used++; + return page; +} + +static void mi_segment_slice_split(mi_segment_t* segment, mi_slice_t* slice, size_t slice_count, mi_segments_tld_t* tld) { + mi_assert_internal(_mi_ptr_segment(slice) == segment); + mi_assert_internal(slice->slice_count >= slice_count); + mi_assert_internal(slice->xblock_size > 0); // no more in free queue + if (slice->slice_count <= slice_count) return; + mi_assert_internal(segment->kind != MI_SEGMENT_HUGE); + size_t next_index = mi_slice_index(slice) + slice_count; + size_t next_count = slice->slice_count - slice_count; + mi_segment_span_free(segment, next_index, next_count, false /* don't purge left-over part */, tld); + slice->slice_count = (uint32_t)slice_count; +} + +static mi_page_t* mi_segments_page_find_and_allocate(size_t slice_count, mi_arena_id_t req_arena_id, mi_segments_tld_t* tld) { + mi_assert_internal(slice_count*MI_SEGMENT_SLICE_SIZE <= MI_LARGE_OBJ_SIZE_MAX); + // search from best fit up + mi_span_queue_t* sq = mi_span_queue_for(slice_count, tld); + if (slice_count == 0) slice_count = 1; + while (sq <= &tld->spans[MI_SEGMENT_BIN_MAX]) { + for (mi_slice_t* slice = sq->first; slice != NULL; slice = slice->next) { + if (slice->slice_count >= slice_count) { + // found one + mi_segment_t* segment = _mi_ptr_segment(slice); + if (_mi_arena_memid_is_suitable(segment->memid, req_arena_id)) { + // found a suitable page span + mi_span_queue_delete(sq, slice); + + if (slice->slice_count > slice_count) { + mi_segment_slice_split(segment, slice, slice_count, tld); + } + mi_assert_internal(slice != NULL && slice->slice_count == slice_count && slice->xblock_size > 0); + mi_page_t* page = mi_segment_span_allocate(segment, mi_slice_index(slice), slice->slice_count, tld); + if (page == NULL) { + // commit failed; return NULL but first restore the slice + mi_segment_span_free_coalesce(slice, tld); + return NULL; + } + return page; + } + } + } + sq++; + } + // could not find a page.. + return NULL; +} + + +/* ----------------------------------------------------------- + Segment allocation +----------------------------------------------------------- */ + +static mi_segment_t* mi_segment_os_alloc( size_t required, size_t page_alignment, bool eager_delayed, mi_arena_id_t req_arena_id, + size_t* psegment_slices, size_t* ppre_size, size_t* pinfo_slices, + bool commit, mi_segments_tld_t* tld, mi_os_tld_t* os_tld) + +{ + mi_memid_t memid; + bool allow_large = (!eager_delayed && (MI_SECURE == 0)); // only allow large OS pages once we are no longer lazy + size_t align_offset = 0; + size_t alignment = MI_SEGMENT_ALIGN; + + if (page_alignment > 0) { + // mi_assert_internal(huge_page != NULL); + mi_assert_internal(page_alignment >= MI_SEGMENT_ALIGN); + alignment = page_alignment; + const size_t info_size = (*pinfo_slices) * MI_SEGMENT_SLICE_SIZE; + align_offset = _mi_align_up( info_size, MI_SEGMENT_ALIGN ); + const size_t extra = align_offset - info_size; + // recalculate due to potential guard pages + *psegment_slices = mi_segment_calculate_slices(required + extra, ppre_size, pinfo_slices); + } + + const size_t segment_size = (*psegment_slices) * MI_SEGMENT_SLICE_SIZE; + mi_segment_t* segment = (mi_segment_t*)_mi_arena_alloc_aligned(segment_size, alignment, align_offset, commit, allow_large, req_arena_id, &memid, os_tld); + if (segment == NULL) { + return NULL; // failed to allocate + } + + // ensure metadata part of the segment is committed + mi_commit_mask_t commit_mask; + if (memid.initially_committed) { + mi_commit_mask_create_full(&commit_mask); + } + else { + // at least commit the info slices + const size_t commit_needed = _mi_divide_up((*pinfo_slices)*MI_SEGMENT_SLICE_SIZE, MI_COMMIT_SIZE); + mi_assert_internal(commit_needed>0); + mi_commit_mask_create(0, commit_needed, &commit_mask); + mi_assert_internal(commit_needed*MI_COMMIT_SIZE >= (*pinfo_slices)*MI_SEGMENT_SLICE_SIZE); + if (!_mi_os_commit(segment, commit_needed*MI_COMMIT_SIZE, NULL, tld->stats)) { + _mi_arena_free(segment,segment_size,0,memid,tld->stats); + return NULL; + } + } + mi_assert_internal(segment != NULL && (uintptr_t)segment % MI_SEGMENT_SIZE == 0); + + segment->memid = memid; + segment->allow_decommit = !memid.is_pinned; + segment->allow_purge = segment->allow_decommit && (mi_option_get(mi_option_purge_delay) >= 0); + segment->segment_size = segment_size; + segment->commit_mask = commit_mask; + segment->purge_expire = 0; + mi_commit_mask_create_empty(&segment->purge_mask); + mi_atomic_store_ptr_release(mi_segment_t, &segment->abandoned_next, NULL); // tsan + + mi_segments_track_size((long)(segment_size), tld); + _mi_segment_map_allocated_at(segment); + return segment; +} + + +// Allocate a segment from the OS aligned to `MI_SEGMENT_SIZE` . +static mi_segment_t* mi_segment_alloc(size_t required, size_t page_alignment, mi_arena_id_t req_arena_id, mi_segments_tld_t* tld, mi_os_tld_t* os_tld, mi_page_t** huge_page) +{ + mi_assert_internal((required==0 && huge_page==NULL) || (required>0 && huge_page != NULL)); + + // calculate needed sizes first + size_t info_slices; + size_t pre_size; + size_t segment_slices = mi_segment_calculate_slices(required, &pre_size, &info_slices); + + // Commit eagerly only if not the first N lazy segments (to reduce impact of many threads that allocate just a little) + const bool eager_delay = (// !_mi_os_has_overcommit() && // never delay on overcommit systems + _mi_current_thread_count() > 1 && // do not delay for the first N threads + tld->count < (size_t)mi_option_get(mi_option_eager_commit_delay)); + const bool eager = !eager_delay && mi_option_is_enabled(mi_option_eager_commit); + bool commit = eager || (required > 0); + + // Allocate the segment from the OS + mi_segment_t* segment = mi_segment_os_alloc(required, page_alignment, eager_delay, req_arena_id, + &segment_slices, &pre_size, &info_slices, commit, tld, os_tld); + if (segment == NULL) return NULL; + + // zero the segment info? -- not always needed as it may be zero initialized from the OS + if (!segment->memid.initially_zero) { + ptrdiff_t ofs = offsetof(mi_segment_t, next); + size_t prefix = offsetof(mi_segment_t, slices) - ofs; + size_t zsize = prefix + (sizeof(mi_slice_t) * (segment_slices + 1)); // one more + _mi_memzero((uint8_t*)segment + ofs, zsize); + } + + // initialize the rest of the segment info + const size_t slice_entries = (segment_slices > MI_SLICES_PER_SEGMENT ? MI_SLICES_PER_SEGMENT : segment_slices); + segment->segment_slices = segment_slices; + segment->segment_info_slices = info_slices; + segment->thread_id = _mi_thread_id(); + segment->cookie = _mi_ptr_cookie(segment); + segment->slice_entries = slice_entries; + segment->kind = (required == 0 ? MI_SEGMENT_NORMAL : MI_SEGMENT_HUGE); + + // _mi_memzero(segment->slices, sizeof(mi_slice_t)*(info_slices+1)); + _mi_stat_increase(&tld->stats->page_committed, mi_segment_info_size(segment)); + + // set up guard pages + size_t guard_slices = 0; + if (MI_SECURE>0) { + // in secure mode, we set up a protected page in between the segment info + // and the page data, and at the end of the segment. + size_t os_pagesize = _mi_os_page_size(); + mi_assert_internal(mi_segment_info_size(segment) - os_pagesize >= pre_size); + _mi_os_protect((uint8_t*)segment + mi_segment_info_size(segment) - os_pagesize, os_pagesize); + uint8_t* end = (uint8_t*)segment + mi_segment_size(segment) - os_pagesize; + mi_segment_ensure_committed(segment, end, os_pagesize, tld->stats); + _mi_os_protect(end, os_pagesize); + if (slice_entries == segment_slices) segment->slice_entries--; // don't use the last slice :-( + guard_slices = 1; + } + + // reserve first slices for segment info + mi_page_t* page0 = mi_segment_span_allocate(segment, 0, info_slices, tld); + mi_assert_internal(page0!=NULL); if (page0==NULL) return NULL; // cannot fail as we always commit in advance + mi_assert_internal(segment->used == 1); + segment->used = 0; // don't count our internal slices towards usage + + // initialize initial free pages + if (segment->kind == MI_SEGMENT_NORMAL) { // not a huge page + mi_assert_internal(huge_page==NULL); + mi_segment_span_free(segment, info_slices, segment->slice_entries - info_slices, false /* don't purge */, tld); + } + else { + mi_assert_internal(huge_page!=NULL); + mi_assert_internal(mi_commit_mask_is_empty(&segment->purge_mask)); + mi_assert_internal(mi_commit_mask_is_full(&segment->commit_mask)); + *huge_page = mi_segment_span_allocate(segment, info_slices, segment_slices - info_slices - guard_slices, tld); + mi_assert_internal(*huge_page != NULL); // cannot fail as we commit in advance + } + + mi_assert_expensive(mi_segment_is_valid(segment,tld)); + return segment; +} + + +static void mi_segment_free(mi_segment_t* segment, bool force, mi_segments_tld_t* tld) { + MI_UNUSED(force); + mi_assert_internal(segment != NULL); + mi_assert_internal(segment->next == NULL); + mi_assert_internal(segment->used == 0); + + // Remove the free pages + mi_slice_t* slice = &segment->slices[0]; + const mi_slice_t* end = mi_segment_slices_end(segment); + #if MI_DEBUG>1 + size_t page_count = 0; + #endif + while (slice < end) { + mi_assert_internal(slice->slice_count > 0); + mi_assert_internal(slice->slice_offset == 0); + mi_assert_internal(mi_slice_index(slice)==0 || slice->xblock_size == 0); // no more used pages .. + if (slice->xblock_size == 0 && segment->kind != MI_SEGMENT_HUGE) { + mi_segment_span_remove_from_queue(slice, tld); + } + #if MI_DEBUG>1 + page_count++; + #endif + slice = slice + slice->slice_count; + } + mi_assert_internal(page_count == 2); // first page is allocated by the segment itself + + // stats + _mi_stat_decrease(&tld->stats->page_committed, mi_segment_info_size(segment)); + + // return it to the OS + mi_segment_os_free(segment, tld); +} + + +/* ----------------------------------------------------------- + Page Free +----------------------------------------------------------- */ + +static void mi_segment_abandon(mi_segment_t* segment, mi_segments_tld_t* tld); + +// note: can be called on abandoned pages +static mi_slice_t* mi_segment_page_clear(mi_page_t* page, mi_segments_tld_t* tld) { + mi_assert_internal(page->xblock_size > 0); + mi_assert_internal(mi_page_all_free(page)); + mi_segment_t* segment = _mi_ptr_segment(page); + mi_assert_internal(segment->used > 0); + + size_t inuse = page->capacity * mi_page_block_size(page); + _mi_stat_decrease(&tld->stats->page_committed, inuse); + _mi_stat_decrease(&tld->stats->pages, 1); + + // reset the page memory to reduce memory pressure? + if (segment->allow_decommit && mi_option_is_enabled(mi_option_deprecated_page_reset)) { + size_t psize; + uint8_t* start = _mi_page_start(segment, page, &psize); + _mi_os_reset(start, psize, tld->stats); + } + + // zero the page data, but not the segment fields + page->is_zero_init = false; + ptrdiff_t ofs = offsetof(mi_page_t, capacity); + _mi_memzero((uint8_t*)page + ofs, sizeof(*page) - ofs); + page->xblock_size = 1; + + // and free it + mi_slice_t* slice = mi_segment_span_free_coalesce(mi_page_to_slice(page), tld); + segment->used--; + // cannot assert segment valid as it is called during reclaim + // mi_assert_expensive(mi_segment_is_valid(segment, tld)); + return slice; +} + +void _mi_segment_page_free(mi_page_t* page, bool force, mi_segments_tld_t* tld) +{ + mi_assert(page != NULL); + + mi_segment_t* segment = _mi_page_segment(page); + mi_assert_expensive(mi_segment_is_valid(segment,tld)); + + // mark it as free now + mi_segment_page_clear(page, tld); + mi_assert_expensive(mi_segment_is_valid(segment, tld)); + + if (segment->used == 0) { + // no more used pages; remove from the free list and free the segment + mi_segment_free(segment, force, tld); + } + else if (segment->used == segment->abandoned) { + // only abandoned pages; remove from free list and abandon + mi_segment_abandon(segment,tld); + } +} + + +/* ----------------------------------------------------------- +Abandonment + +When threads terminate, they can leave segments with +live blocks (reachable through other threads). Such segments +are "abandoned" and will be reclaimed by other threads to +reuse their pages and/or free them eventually + +We maintain a global list of abandoned segments that are +reclaimed on demand. Since this is shared among threads +the implementation needs to avoid the A-B-A problem on +popping abandoned segments: +We use tagged pointers to avoid accidentally identifying +reused segments, much like stamped references in Java. +Secondly, we maintain a reader counter to avoid resetting +or decommitting segments that have a pending read operation. + +Note: the current implementation is one possible design; +another way might be to keep track of abandoned segments +in the arenas/segment_cache's. This would have the advantage of keeping +all concurrent code in one place and not needing to deal +with ABA issues. The drawback is that it is unclear how to +scan abandoned segments efficiently in that case as they +would be spread among all other segments in the arenas. +----------------------------------------------------------- */ + +// Use the bottom 20-bits (on 64-bit) of the aligned segment pointers +// to put in a tag that increments on update to avoid the A-B-A problem. +#define MI_TAGGED_MASK MI_SEGMENT_MASK + +static mi_segment_t* mi_tagged_segment_ptr(mi_tagged_segment_t ts) { + return (mi_segment_t*)(ts & ~MI_TAGGED_MASK); +} + +static mi_tagged_segment_t mi_tagged_segment(mi_segment_t* segment, mi_tagged_segment_t ts) { + mi_assert_internal(((uintptr_t)segment & MI_TAGGED_MASK) == 0); + uintptr_t tag = ((ts & MI_TAGGED_MASK) + 1) & MI_TAGGED_MASK; + return ((uintptr_t)segment | tag); +} + +mi_abandoned_pool_t _mi_abandoned_default; + +// Push on the visited list +static void mi_abandoned_visited_push(mi_abandoned_pool_t *pool, mi_segment_t* segment) { + mi_assert_internal(segment->thread_id == 0); + mi_assert_internal(mi_atomic_load_ptr_relaxed(mi_segment_t,&segment->abandoned_next) == NULL); + mi_assert_internal(segment->next == NULL); + mi_assert_internal(segment->used > 0); + mi_segment_t* anext = mi_atomic_load_ptr_relaxed(mi_segment_t, &pool->abandoned_visited); + do { + mi_atomic_store_ptr_release(mi_segment_t, &segment->abandoned_next, anext); + } while (!mi_atomic_cas_ptr_weak_release(mi_segment_t, &pool->abandoned_visited, &anext, segment)); + mi_atomic_increment_relaxed(&pool->abandoned_visited_count); +} + +// Move the visited list to the abandoned list. +static bool mi_abandoned_visited_revisit(mi_abandoned_pool_t *pool) +{ + // quick check if the visited list is empty + if (mi_atomic_load_ptr_relaxed(mi_segment_t, &pool->abandoned_visited) == NULL) return false; + + // grab the whole visited list + mi_segment_t* first = mi_atomic_exchange_ptr_acq_rel(mi_segment_t, &pool->abandoned_visited, NULL); + if (first == NULL) return false; + + // first try to swap directly if the abandoned list happens to be NULL + mi_tagged_segment_t afirst; + mi_tagged_segment_t ts = mi_atomic_load_relaxed(&pool->abandoned); + if (mi_tagged_segment_ptr(ts)==NULL) { + size_t count = mi_atomic_load_relaxed(&pool->abandoned_visited_count); + afirst = mi_tagged_segment(first, ts); + if (mi_atomic_cas_strong_acq_rel(&pool->abandoned, &ts, afirst)) { + mi_atomic_add_relaxed(&pool->abandoned_count, count); + mi_atomic_sub_relaxed(&pool->abandoned_visited_count, count); + return true; + } + } + + // find the last element of the visited list: O(n) + mi_segment_t* last = first; + mi_segment_t* next; + while ((next = mi_atomic_load_ptr_relaxed(mi_segment_t, &last->abandoned_next)) != NULL) { + last = next; + } + + // and atomically prepend to the abandoned list + // (no need to increase the readers as we don't access the abandoned segments) + mi_tagged_segment_t anext = mi_atomic_load_relaxed(&pool->abandoned); + size_t count; + do { + count = mi_atomic_load_relaxed(&pool->abandoned_visited_count); + mi_atomic_store_ptr_release(mi_segment_t, &last->abandoned_next, mi_tagged_segment_ptr(anext)); + afirst = mi_tagged_segment(first, anext); + } while (!mi_atomic_cas_weak_release(&pool->abandoned, &anext, afirst)); + mi_atomic_add_relaxed(&pool->abandoned_count, count); + mi_atomic_sub_relaxed(&pool->abandoned_visited_count, count); + return true; +} + +// Push on the abandoned list. +static void mi_abandoned_push(mi_abandoned_pool_t* pool, mi_segment_t* segment) { + mi_assert_internal(segment->thread_id == 0); + mi_assert_internal(mi_atomic_load_ptr_relaxed(mi_segment_t, &segment->abandoned_next) == NULL); + mi_assert_internal(segment->next == NULL); + mi_assert_internal(segment->used > 0); + mi_tagged_segment_t next; + mi_tagged_segment_t ts = mi_atomic_load_relaxed(&pool->abandoned); + do { + mi_atomic_store_ptr_release(mi_segment_t, &segment->abandoned_next, mi_tagged_segment_ptr(ts)); + next = mi_tagged_segment(segment, ts); + } while (!mi_atomic_cas_weak_release(&pool->abandoned, &ts, next)); + mi_atomic_increment_relaxed(&pool->abandoned_count); +} + +// Wait until there are no more pending reads on segments that used to be in the abandoned list +// called for example from `arena.c` before decommitting +void _mi_abandoned_await_readers(mi_abandoned_pool_t* pool) { + size_t n; + do { + n = mi_atomic_load_acquire(&pool->abandoned_readers); + if (n != 0) mi_atomic_yield(); + } while (n != 0); +} + +// Pop from the abandoned list +static mi_segment_t* mi_abandoned_pop(mi_abandoned_pool_t* pool) { + mi_segment_t* segment; + // Check efficiently if it is empty (or if the visited list needs to be moved) + mi_tagged_segment_t ts = mi_atomic_load_relaxed(&pool->abandoned); + segment = mi_tagged_segment_ptr(ts); + if mi_likely(segment == NULL) { + if mi_likely(!mi_abandoned_visited_revisit(pool)) { // try to swap in the visited list on NULL + return NULL; + } + } + + // Do a pop. We use a reader count to prevent + // a segment to be decommitted while a read is still pending, + // and a tagged pointer to prevent A-B-A link corruption. + // (this is called from `region.c:_mi_mem_free` for example) + mi_atomic_increment_relaxed(&pool->abandoned_readers); // ensure no segment gets decommitted + mi_tagged_segment_t next = 0; + ts = mi_atomic_load_acquire(&pool->abandoned); + do { + segment = mi_tagged_segment_ptr(ts); + if (segment != NULL) { + mi_segment_t* anext = mi_atomic_load_ptr_relaxed(mi_segment_t, &segment->abandoned_next); + next = mi_tagged_segment(anext, ts); // note: reads the segment's `abandoned_next` field so should not be decommitted + } + } while (segment != NULL && !mi_atomic_cas_weak_acq_rel(&pool->abandoned, &ts, next)); + mi_atomic_decrement_relaxed(&pool->abandoned_readers); // release reader lock + if (segment != NULL) { + mi_atomic_store_ptr_release(mi_segment_t, &segment->abandoned_next, NULL); + mi_atomic_decrement_relaxed(&pool->abandoned_count); + } + return segment; +} + +/* ----------------------------------------------------------- + Abandon segment/page +----------------------------------------------------------- */ + +static void mi_segment_abandon(mi_segment_t* segment, mi_segments_tld_t* tld) { + mi_assert_internal(segment->used == segment->abandoned); + mi_assert_internal(segment->used > 0); + mi_assert_internal(mi_atomic_load_ptr_relaxed(mi_segment_t, &segment->abandoned_next) == NULL); + mi_assert_internal(segment->abandoned_visits == 0); + mi_assert_expensive(mi_segment_is_valid(segment,tld)); + + // remove the free pages from the free page queues + mi_slice_t* slice = &segment->slices[0]; + const mi_slice_t* end = mi_segment_slices_end(segment); + while (slice < end) { + mi_assert_internal(slice->slice_count > 0); + mi_assert_internal(slice->slice_offset == 0); + if (slice->xblock_size == 0) { // a free page + mi_segment_span_remove_from_queue(slice,tld); + slice->xblock_size = 0; // but keep it free + } + slice = slice + slice->slice_count; + } + + // perform delayed decommits (forcing is much slower on mstress) + mi_segment_try_purge(segment, mi_option_is_enabled(mi_option_abandoned_page_purge) /* force? */, tld->stats); + + // all pages in the segment are abandoned; add it to the abandoned list + _mi_stat_increase(&tld->stats->segments_abandoned, 1); + mi_segments_track_size(-((long)mi_segment_size(segment)), tld); + segment->thread_id = 0; + mi_atomic_store_ptr_release(mi_segment_t, &segment->abandoned_next, NULL); + segment->abandoned_visits = 1; // from 0 to 1 to signify it is abandoned + mi_abandoned_push(tld->abandoned, segment); +} + +void _mi_segment_page_abandon(mi_page_t* page, mi_segments_tld_t* tld) { + mi_assert(page != NULL); + mi_assert_internal(mi_page_thread_free_flag(page)==MI_NEVER_DELAYED_FREE); + mi_assert_internal(mi_page_heap(page) == NULL); + mi_segment_t* segment = _mi_page_segment(page); + + mi_assert_expensive(mi_segment_is_valid(segment,tld)); + segment->abandoned++; + + _mi_stat_increase(&tld->stats->pages_abandoned, 1); + mi_assert_internal(segment->abandoned <= segment->used); + if (segment->used == segment->abandoned) { + // all pages are abandoned, abandon the entire segment + mi_segment_abandon(segment, tld); + } +} + +/* ----------------------------------------------------------- + Reclaim abandoned pages +----------------------------------------------------------- */ + +static mi_slice_t* mi_slices_start_iterate(mi_segment_t* segment, const mi_slice_t** end) { + mi_slice_t* slice = &segment->slices[0]; + *end = mi_segment_slices_end(segment); + mi_assert_internal(slice->slice_count>0 && slice->xblock_size>0); // segment allocated page + slice = slice + slice->slice_count; // skip the first segment allocated page + return slice; +} + +// Possibly free pages and check if free space is available +static bool mi_segment_check_free(mi_segment_t* segment, size_t slices_needed, size_t block_size, mi_segments_tld_t* tld) +{ + mi_assert_internal(block_size < MI_HUGE_BLOCK_SIZE); + mi_assert_internal(mi_segment_is_abandoned(segment)); + bool has_page = false; + + // for all slices + const mi_slice_t* end; + mi_slice_t* slice = mi_slices_start_iterate(segment, &end); + while (slice < end) { + mi_assert_internal(slice->slice_count > 0); + mi_assert_internal(slice->slice_offset == 0); + if (mi_slice_is_used(slice)) { // used page + // ensure used count is up to date and collect potential concurrent frees + mi_page_t* const page = mi_slice_to_page(slice); + _mi_page_free_collect(page, false); + if (mi_page_all_free(page)) { + // if this page is all free now, free it without adding to any queues (yet) + mi_assert_internal(page->next == NULL && page->prev==NULL); + _mi_stat_decrease(&tld->stats->pages_abandoned, 1); + segment->abandoned--; + slice = mi_segment_page_clear(page, tld); // re-assign slice due to coalesce! + mi_assert_internal(!mi_slice_is_used(slice)); + if (slice->slice_count >= slices_needed) { + has_page = true; + } + } + else { + if (page->xblock_size == block_size && mi_page_has_any_available(page)) { + // a page has available free blocks of the right size + has_page = true; + } + } + } + else { + // empty span + if (slice->slice_count >= slices_needed) { + has_page = true; + } + } + slice = slice + slice->slice_count; + } + return has_page; +} + +static mi_heap_t* mi_heap_by_tag(mi_heap_t* heap, uint8_t tag) { + if (heap->tag == tag) { + return heap; + } + for (mi_heap_t *curr = heap->tld->heaps; curr != NULL; curr = curr->next) { + if (curr->tag == tag) { + return curr; + } + } + return NULL; +} + +// Reclaim an abandoned segment; returns NULL if the segment was freed +// set `right_page_reclaimed` to `true` if it reclaimed a page of the right `block_size` that was not full. +static mi_segment_t* mi_segment_reclaim(mi_segment_t* segment, mi_heap_t* heap, size_t requested_block_size, bool* right_page_reclaimed, mi_segments_tld_t* tld) { + mi_assert_internal(mi_atomic_load_ptr_relaxed(mi_segment_t, &segment->abandoned_next) == NULL); + mi_assert_expensive(mi_segment_is_valid(segment, tld)); + if (right_page_reclaimed != NULL) { *right_page_reclaimed = false; } + + segment->thread_id = _mi_thread_id(); + segment->abandoned_visits = 0; + mi_segments_track_size((long)mi_segment_size(segment), tld); + mi_assert_internal(segment->next == NULL); + _mi_stat_decrease(&tld->stats->segments_abandoned, 1); + + // for all slices + const mi_slice_t* end; + mi_slice_t* slice = mi_slices_start_iterate(segment, &end); + while (slice < end) { + mi_assert_internal(slice->slice_count > 0); + mi_assert_internal(slice->slice_offset == 0); + if (mi_slice_is_used(slice)) { + // in use: reclaim the page in our heap + mi_page_t* page = mi_slice_to_page(slice); + mi_heap_t* target_heap = mi_heap_by_tag(heap, page->tag); + mi_assert_internal(page->is_committed); + mi_assert_internal(mi_page_thread_free_flag(page)==MI_NEVER_DELAYED_FREE); + mi_assert_internal(mi_page_heap(page) == NULL); + mi_assert_internal(page->next == NULL && page->prev==NULL); + _mi_stat_decrease(&tld->stats->pages_abandoned, 1); + segment->abandoned--; + // set the heap again and allow delayed free again + mi_page_set_heap(page, target_heap); + _mi_page_use_delayed_free(page, MI_USE_DELAYED_FREE, true); // override never (after heap is set) + _mi_page_free_collect(page, false); // ensure used count is up to date + if (mi_page_all_free(page)) { + // if everything free by now, free the page + slice = mi_segment_page_clear(page, tld); // set slice again due to coalesceing + } + else { + // otherwise reclaim it into the heap + _mi_page_reclaim(target_heap, page); + if (requested_block_size == page->xblock_size && mi_page_has_any_available(page) && + heap == target_heap) { + if (right_page_reclaimed != NULL) { *right_page_reclaimed = true; } + } + } + } + else { + // the span is free, add it to our page queues + slice = mi_segment_span_free_coalesce(slice, tld); // set slice again due to coalesceing + } + mi_assert_internal(slice->slice_count>0 && slice->slice_offset==0); + slice = slice + slice->slice_count; + } + + mi_assert(segment->abandoned == 0); + if (segment->used == 0) { // due to page_clear + mi_assert_internal(right_page_reclaimed == NULL || !(*right_page_reclaimed)); + mi_segment_free(segment, false, tld); + return NULL; + } + else { + return segment; + } +} + + +void _mi_abandoned_reclaim_all(mi_heap_t* heap, mi_segments_tld_t* tld) { + mi_segment_t* segment; + while ((segment = mi_abandoned_pop(tld->abandoned)) != NULL) { + mi_segment_reclaim(segment, heap, 0, NULL, tld); + } +} + +static mi_segment_t* mi_segment_try_reclaim(mi_heap_t* heap, size_t needed_slices, size_t block_size, bool* reclaimed, mi_segments_tld_t* tld) +{ + *reclaimed = false; + mi_segment_t* segment; + long max_tries = mi_option_get_clamp(mi_option_max_segment_reclaim, 8, 1024); // limit the work to bound allocation times + while ((max_tries-- > 0) && ((segment = mi_abandoned_pop(tld->abandoned)) != NULL)) { + segment->abandoned_visits++; + // todo: an arena exclusive heap will potentially visit many abandoned unsuitable segments + // and push them into the visited list and use many tries. Perhaps we can skip non-suitable ones in a better way? + bool is_suitable = _mi_heap_memid_is_suitable(heap, segment->memid); + bool has_page = mi_segment_check_free(segment,needed_slices,block_size,tld); // try to free up pages (due to concurrent frees) + if (segment->used == 0) { + // free the segment (by forced reclaim) to make it available to other threads. + // note1: we prefer to free a segment as that might lead to reclaiming another + // segment that is still partially used. + // note2: we could in principle optimize this by skipping reclaim and directly + // freeing but that would violate some invariants temporarily) + mi_segment_reclaim(segment, heap, 0, NULL, tld); + } + else if (has_page && is_suitable) { + // found a large enough free span, or a page of the right block_size with free space + // we return the result of reclaim (which is usually `segment`) as it might free + // the segment due to concurrent frees (in which case `NULL` is returned). + return mi_segment_reclaim(segment, heap, block_size, reclaimed, tld); + } + else if (segment->abandoned_visits > 3 && is_suitable) { + // always reclaim on 3rd visit to limit the abandoned queue length. + mi_segment_reclaim(segment, heap, 0, NULL, tld); + } + else { + // otherwise, push on the visited list so it gets not looked at too quickly again + mi_segment_try_purge(segment, true /* force? */, tld->stats); // force purge if needed as we may not visit soon again + mi_abandoned_visited_push(tld->abandoned, segment); + } + } + return NULL; +} + + +void _mi_abandoned_collect(mi_heap_t* heap, bool force, mi_segments_tld_t* tld) +{ + mi_segment_t* segment; + mi_abandoned_pool_t* pool = tld->abandoned; + int max_tries = (force ? 16*1024 : 1024); // limit latency + if (force) { + mi_abandoned_visited_revisit(pool); + } + while ((max_tries-- > 0) && ((segment = mi_abandoned_pop(pool)) != NULL)) { + mi_segment_check_free(segment,0,0,tld); // try to free up pages (due to concurrent frees) + if (segment->used == 0) { + // free the segment (by forced reclaim) to make it available to other threads. + // note: we could in principle optimize this by skipping reclaim and directly + // freeing but that would violate some invariants temporarily) + mi_segment_reclaim(segment, heap, 0, NULL, tld); + } + else { + // otherwise, purge if needed and push on the visited list + // note: forced purge can be expensive if many threads are destroyed/created as in mstress. + mi_segment_try_purge(segment, force, tld->stats); + mi_abandoned_visited_push(pool, segment); + } + } +} + +/* ----------------------------------------------------------- + Reclaim or allocate +----------------------------------------------------------- */ + +static mi_segment_t* mi_segment_reclaim_or_alloc(mi_heap_t* heap, size_t needed_slices, size_t block_size, mi_segments_tld_t* tld, mi_os_tld_t* os_tld) +{ + mi_assert_internal(block_size < MI_HUGE_BLOCK_SIZE); + mi_assert_internal(block_size <= MI_LARGE_OBJ_SIZE_MAX); + + // 1. try to reclaim an abandoned segment + bool reclaimed; + mi_segment_t* segment = mi_segment_try_reclaim(heap, needed_slices, block_size, &reclaimed, tld); + if (reclaimed) { + // reclaimed the right page right into the heap + mi_assert_internal(segment != NULL); + return NULL; // pretend out-of-memory as the page will be in the page queue of the heap with available blocks + } + else if (segment != NULL) { + // reclaimed a segment with a large enough empty span in it + return segment; + } + // 2. otherwise allocate a fresh segment + return mi_segment_alloc(0, 0, heap->arena_id, tld, os_tld, NULL); +} + + +/* ----------------------------------------------------------- + Page allocation +----------------------------------------------------------- */ + +static mi_page_t* mi_segments_page_alloc(mi_heap_t* heap, mi_page_kind_t page_kind, size_t required, size_t block_size, mi_segments_tld_t* tld, mi_os_tld_t* os_tld) +{ + mi_assert_internal(required <= MI_LARGE_OBJ_SIZE_MAX && page_kind <= MI_PAGE_LARGE); + + // find a free page + size_t page_size = _mi_align_up(required, (required > MI_MEDIUM_PAGE_SIZE ? MI_MEDIUM_PAGE_SIZE : MI_SEGMENT_SLICE_SIZE)); + size_t slices_needed = page_size / MI_SEGMENT_SLICE_SIZE; + mi_assert_internal(slices_needed * MI_SEGMENT_SLICE_SIZE == page_size); + mi_page_t* page = mi_segments_page_find_and_allocate(slices_needed, heap->arena_id, tld); //(required <= MI_SMALL_SIZE_MAX ? 0 : slices_needed), tld); + if (page==NULL) { + // no free page, allocate a new segment and try again + if (mi_segment_reclaim_or_alloc(heap, slices_needed, block_size, tld, os_tld) == NULL) { + // OOM or reclaimed a good page in the heap + return NULL; + } + else { + // otherwise try again + return mi_segments_page_alloc(heap, page_kind, required, block_size, tld, os_tld); + } + } + mi_assert_internal(page != NULL && page->slice_count*MI_SEGMENT_SLICE_SIZE == page_size); + mi_assert_internal(_mi_ptr_segment(page)->thread_id == _mi_thread_id()); + mi_segment_try_purge(_mi_ptr_segment(page), false, tld->stats); + return page; +} + + + +/* ----------------------------------------------------------- + Huge page allocation +----------------------------------------------------------- */ + +static mi_page_t* mi_segment_huge_page_alloc(size_t size, size_t page_alignment, mi_arena_id_t req_arena_id, mi_segments_tld_t* tld, mi_os_tld_t* os_tld) +{ + mi_page_t* page = NULL; + mi_segment_t* segment = mi_segment_alloc(size,page_alignment,req_arena_id,tld,os_tld,&page); + if (segment == NULL || page==NULL) return NULL; + mi_assert_internal(segment->used==1); + mi_assert_internal(mi_page_block_size(page) >= size); + #if MI_HUGE_PAGE_ABANDON + segment->thread_id = 0; // huge segments are immediately abandoned + #endif + + // for huge pages we initialize the xblock_size as we may + // overallocate to accommodate large alignments. + size_t psize; + uint8_t* start = _mi_segment_page_start(segment, page, &psize); + page->xblock_size = (psize > MI_HUGE_BLOCK_SIZE ? MI_HUGE_BLOCK_SIZE : (uint32_t)psize); + + // decommit the part of the prefix of a page that will not be used; this can be quite large (close to MI_SEGMENT_SIZE) + if (page_alignment > 0 && segment->allow_decommit) { + uint8_t* aligned_p = (uint8_t*)_mi_align_up((uintptr_t)start, page_alignment); + mi_assert_internal(_mi_is_aligned(aligned_p, page_alignment)); + mi_assert_internal(psize - (aligned_p - start) >= size); + uint8_t* decommit_start = start + sizeof(mi_block_t); // for the free list + ptrdiff_t decommit_size = aligned_p - decommit_start; + _mi_os_reset(decommit_start, decommit_size, &_mi_stats_main); // note: cannot use segment_decommit on huge segments + } + + return page; +} + +#if MI_HUGE_PAGE_ABANDON +// free huge block from another thread +void _mi_segment_huge_page_free(mi_segment_t* segment, mi_page_t* page, mi_block_t* block) { + // huge page segments are always abandoned and can be freed immediately by any thread + mi_assert_internal(segment->kind==MI_SEGMENT_HUGE); + mi_assert_internal(segment == _mi_page_segment(page)); + mi_assert_internal(mi_atomic_load_relaxed(&segment->thread_id)==0); + + // claim it and free + mi_heap_t* heap = mi_heap_get_default(); // issue #221; don't use the internal get_default_heap as we need to ensure the thread is initialized. + // paranoia: if this it the last reference, the cas should always succeed + size_t expected_tid = 0; + if (mi_atomic_cas_strong_acq_rel(&segment->thread_id, &expected_tid, heap->thread_id)) { + mi_block_set_next(page, block, page->free); + page->free = block; + page->used--; + page->is_zero = false; + mi_assert(page->used == 0); + mi_tld_t* tld = heap->tld; + _mi_segment_page_free(page, true, &tld->segments); + } +#if (MI_DEBUG!=0) + else { + mi_assert_internal(false); + } +#endif +} + +#else +// reset memory of a huge block from another thread +void _mi_segment_huge_page_reset(mi_segment_t* segment, mi_page_t* page, mi_block_t* block) { + MI_UNUSED(page); + mi_assert_internal(segment->kind == MI_SEGMENT_HUGE); + mi_assert_internal(segment == _mi_page_segment(page)); + mi_assert_internal(page->used == 1); // this is called just before the free + mi_assert_internal(page->free == NULL); + if (segment->allow_decommit) { + size_t csize = mi_usable_size(block); + if (csize > sizeof(mi_block_t)) { + csize = csize - sizeof(mi_block_t); + uint8_t* p = (uint8_t*)block + sizeof(mi_block_t); + _mi_os_reset(p, csize, &_mi_stats_main); // note: cannot use segment_decommit on huge segments + } + } +} +#endif + +/* ----------------------------------------------------------- + Page allocation and free +----------------------------------------------------------- */ +mi_page_t* _mi_segment_page_alloc(mi_heap_t* heap, size_t block_size, size_t page_alignment, mi_segments_tld_t* tld, mi_os_tld_t* os_tld) { + mi_page_t* page; + if mi_unlikely(page_alignment > MI_ALIGNMENT_MAX) { + mi_assert_internal(_mi_is_power_of_two(page_alignment)); + mi_assert_internal(page_alignment >= MI_SEGMENT_SIZE); + if (page_alignment < MI_SEGMENT_SIZE) { page_alignment = MI_SEGMENT_SIZE; } + page = mi_segment_huge_page_alloc(block_size,page_alignment,heap->arena_id,tld,os_tld); + } + else if (block_size <= MI_SMALL_OBJ_SIZE_MAX) { + page = mi_segments_page_alloc(heap,MI_PAGE_SMALL,block_size,block_size,tld,os_tld); + } + else if (block_size <= MI_MEDIUM_OBJ_SIZE_MAX) { + page = mi_segments_page_alloc(heap,MI_PAGE_MEDIUM,MI_MEDIUM_PAGE_SIZE,block_size,tld, os_tld); + } + else if (block_size <= MI_LARGE_OBJ_SIZE_MAX) { + page = mi_segments_page_alloc(heap,MI_PAGE_LARGE,block_size,block_size,tld, os_tld); + } + else { + page = mi_segment_huge_page_alloc(block_size,page_alignment,heap->arena_id,tld,os_tld); + } + mi_assert_internal(page == NULL || _mi_heap_memid_is_suitable(heap, _mi_page_segment(page)->memid)); + mi_assert_expensive(page == NULL || mi_segment_is_valid(_mi_page_segment(page),tld)); + return page; +} diff --git a/Objects/mimalloc/static.c b/Objects/mimalloc/static.c new file mode 100644 index 00000000000000..98c4aa18e450cd --- /dev/null +++ b/Objects/mimalloc/static.c @@ -0,0 +1,40 @@ +/* ---------------------------------------------------------------------------- +Copyright (c) 2018-2020, Microsoft Research, Daan Leijen +This is free software; you can redistribute it and/or modify it under the +terms of the MIT license. A copy of the license can be found in the file +"LICENSE" at the root of this distribution. +-----------------------------------------------------------------------------*/ +#ifndef _DEFAULT_SOURCE +#define _DEFAULT_SOURCE +#endif +#if defined(__sun) +// same remarks as os.c for the static's context. +#undef _XOPEN_SOURCE +#undef _POSIX_C_SOURCE +#endif + +#include "mimalloc.h" +#include "mimalloc/internal.h" + +// For a static override we create a single object file +// containing the whole library. If it is linked first +// it will override all the standard library allocation +// functions (on Unix's). +#include "alloc.c" // includes alloc-override.c +#include "alloc-aligned.c" +#include "alloc-posix.c" +#include "arena.c" +#include "bitmap.c" +#include "heap.c" +#include "init.c" +#include "options.c" +#include "os.c" +#include "page.c" // includes page-queue.c +#include "random.c" +#include "segment.c" +#include "segment-map.c" +#include "stats.c" +#include "prim/prim.c" +#if MI_OSX_ZONE +#include "prim/osx/alloc-override-zone.c" +#endif diff --git a/Objects/mimalloc/stats.c b/Objects/mimalloc/stats.c new file mode 100644 index 00000000000000..e7ea397ec4c384 --- /dev/null +++ b/Objects/mimalloc/stats.c @@ -0,0 +1,467 @@ +/* ---------------------------------------------------------------------------- +Copyright (c) 2018-2021, Microsoft Research, Daan Leijen +This is free software; you can redistribute it and/or modify it under the +terms of the MIT license. A copy of the license can be found in the file +"LICENSE" at the root of this distribution. +-----------------------------------------------------------------------------*/ +#include "mimalloc.h" +#include "mimalloc/internal.h" +#include "mimalloc/atomic.h" +#include "mimalloc/prim.h" + +#include // snprintf +#include // memset + +#if defined(_MSC_VER) && (_MSC_VER < 1920) +#pragma warning(disable:4204) // non-constant aggregate initializer +#endif + +/* ----------------------------------------------------------- + Statistics operations +----------------------------------------------------------- */ + +static bool mi_is_in_main(void* stat) { + return ((uint8_t*)stat >= (uint8_t*)&_mi_stats_main + && (uint8_t*)stat < ((uint8_t*)&_mi_stats_main + sizeof(mi_stats_t))); +} + +static void mi_stat_update(mi_stat_count_t* stat, int64_t amount) { + if (amount == 0) return; + if (mi_is_in_main(stat)) + { + // add atomically (for abandoned pages) + int64_t current = mi_atomic_addi64_relaxed(&stat->current, amount); + mi_atomic_maxi64_relaxed(&stat->peak, current + amount); + if (amount > 0) { + mi_atomic_addi64_relaxed(&stat->allocated,amount); + } + else { + mi_atomic_addi64_relaxed(&stat->freed, -amount); + } + } + else { + // add thread local + stat->current += amount; + if (stat->current > stat->peak) stat->peak = stat->current; + if (amount > 0) { + stat->allocated += amount; + } + else { + stat->freed += -amount; + } + } +} + +void _mi_stat_counter_increase(mi_stat_counter_t* stat, size_t amount) { + if (mi_is_in_main(stat)) { + mi_atomic_addi64_relaxed( &stat->count, 1 ); + mi_atomic_addi64_relaxed( &stat->total, (int64_t)amount ); + } + else { + stat->count++; + stat->total += amount; + } +} + +void _mi_stat_increase(mi_stat_count_t* stat, size_t amount) { + mi_stat_update(stat, (int64_t)amount); +} + +void _mi_stat_decrease(mi_stat_count_t* stat, size_t amount) { + mi_stat_update(stat, -((int64_t)amount)); +} + +// must be thread safe as it is called from stats_merge +static void mi_stat_add(mi_stat_count_t* stat, const mi_stat_count_t* src, int64_t unit) { + if (stat==src) return; + if (src->allocated==0 && src->freed==0) return; + mi_atomic_addi64_relaxed( &stat->allocated, src->allocated * unit); + mi_atomic_addi64_relaxed( &stat->current, src->current * unit); + mi_atomic_addi64_relaxed( &stat->freed, src->freed * unit); + // peak scores do not work across threads.. + mi_atomic_addi64_relaxed( &stat->peak, src->peak * unit); +} + +static void mi_stat_counter_add(mi_stat_counter_t* stat, const mi_stat_counter_t* src, int64_t unit) { + if (stat==src) return; + mi_atomic_addi64_relaxed( &stat->total, src->total * unit); + mi_atomic_addi64_relaxed( &stat->count, src->count * unit); +} + +// must be thread safe as it is called from stats_merge +static void mi_stats_add(mi_stats_t* stats, const mi_stats_t* src) { + if (stats==src) return; + mi_stat_add(&stats->segments, &src->segments,1); + mi_stat_add(&stats->pages, &src->pages,1); + mi_stat_add(&stats->reserved, &src->reserved, 1); + mi_stat_add(&stats->committed, &src->committed, 1); + mi_stat_add(&stats->reset, &src->reset, 1); + mi_stat_add(&stats->purged, &src->purged, 1); + mi_stat_add(&stats->page_committed, &src->page_committed, 1); + + mi_stat_add(&stats->pages_abandoned, &src->pages_abandoned, 1); + mi_stat_add(&stats->segments_abandoned, &src->segments_abandoned, 1); + mi_stat_add(&stats->threads, &src->threads, 1); + + mi_stat_add(&stats->malloc, &src->malloc, 1); + mi_stat_add(&stats->segments_cache, &src->segments_cache, 1); + mi_stat_add(&stats->normal, &src->normal, 1); + mi_stat_add(&stats->huge, &src->huge, 1); + mi_stat_add(&stats->large, &src->large, 1); + + mi_stat_counter_add(&stats->pages_extended, &src->pages_extended, 1); + mi_stat_counter_add(&stats->mmap_calls, &src->mmap_calls, 1); + mi_stat_counter_add(&stats->commit_calls, &src->commit_calls, 1); + mi_stat_counter_add(&stats->reset_calls, &src->reset_calls, 1); + mi_stat_counter_add(&stats->purge_calls, &src->purge_calls, 1); + + mi_stat_counter_add(&stats->page_no_retire, &src->page_no_retire, 1); + mi_stat_counter_add(&stats->searches, &src->searches, 1); + mi_stat_counter_add(&stats->normal_count, &src->normal_count, 1); + mi_stat_counter_add(&stats->huge_count, &src->huge_count, 1); + mi_stat_counter_add(&stats->large_count, &src->large_count, 1); +#if MI_STAT>1 + for (size_t i = 0; i <= MI_BIN_HUGE; i++) { + if (src->normal_bins[i].allocated > 0 || src->normal_bins[i].freed > 0) { + mi_stat_add(&stats->normal_bins[i], &src->normal_bins[i], 1); + } + } +#endif +} + +/* ----------------------------------------------------------- + Display statistics +----------------------------------------------------------- */ + +// unit > 0 : size in binary bytes +// unit == 0: count as decimal +// unit < 0 : count in binary +static void mi_printf_amount(int64_t n, int64_t unit, mi_output_fun* out, void* arg, const char* fmt) { + char buf[32]; buf[0] = 0; + int len = 32; + const char* suffix = (unit <= 0 ? " " : "B"); + const int64_t base = (unit == 0 ? 1000 : 1024); + if (unit>0) n *= unit; + + const int64_t pos = (n < 0 ? -n : n); + if (pos < base) { + if (n!=1 || suffix[0] != 'B') { // skip printing 1 B for the unit column + snprintf(buf, len, "%d %-3s", (int)n, (n==0 ? "" : suffix)); + } + } + else { + int64_t divider = base; + const char* magnitude = "K"; + if (pos >= divider*base) { divider *= base; magnitude = "M"; } + if (pos >= divider*base) { divider *= base; magnitude = "G"; } + const int64_t tens = (n / (divider/10)); + const long whole = (long)(tens/10); + const long frac1 = (long)(tens%10); + char unitdesc[8]; + snprintf(unitdesc, 8, "%s%s%s", magnitude, (base==1024 ? "i" : ""), suffix); + snprintf(buf, len, "%ld.%ld %-3s", whole, (frac1 < 0 ? -frac1 : frac1), unitdesc); + } + _mi_fprintf(out, arg, (fmt==NULL ? "%12s" : fmt), buf); +} + + +static void mi_print_amount(int64_t n, int64_t unit, mi_output_fun* out, void* arg) { + mi_printf_amount(n,unit,out,arg,NULL); +} + +static void mi_print_count(int64_t n, int64_t unit, mi_output_fun* out, void* arg) { + if (unit==1) _mi_fprintf(out, arg, "%12s"," "); + else mi_print_amount(n,0,out,arg); +} + +static void mi_stat_print_ex(const mi_stat_count_t* stat, const char* msg, int64_t unit, mi_output_fun* out, void* arg, const char* notok ) { + _mi_fprintf(out, arg,"%10s:", msg); + if (unit > 0) { + mi_print_amount(stat->peak, unit, out, arg); + mi_print_amount(stat->allocated, unit, out, arg); + mi_print_amount(stat->freed, unit, out, arg); + mi_print_amount(stat->current, unit, out, arg); + mi_print_amount(unit, 1, out, arg); + mi_print_count(stat->allocated, unit, out, arg); + if (stat->allocated > stat->freed) { + _mi_fprintf(out, arg, " "); + _mi_fprintf(out, arg, (notok == NULL ? "not all freed" : notok)); + _mi_fprintf(out, arg, "\n"); + } + else { + _mi_fprintf(out, arg, " ok\n"); + } + } + else if (unit<0) { + mi_print_amount(stat->peak, -1, out, arg); + mi_print_amount(stat->allocated, -1, out, arg); + mi_print_amount(stat->freed, -1, out, arg); + mi_print_amount(stat->current, -1, out, arg); + if (unit==-1) { + _mi_fprintf(out, arg, "%24s", ""); + } + else { + mi_print_amount(-unit, 1, out, arg); + mi_print_count((stat->allocated / -unit), 0, out, arg); + } + if (stat->allocated > stat->freed) + _mi_fprintf(out, arg, " not all freed!\n"); + else + _mi_fprintf(out, arg, " ok\n"); + } + else { + mi_print_amount(stat->peak, 1, out, arg); + mi_print_amount(stat->allocated, 1, out, arg); + _mi_fprintf(out, arg, "%11s", " "); // no freed + mi_print_amount(stat->current, 1, out, arg); + _mi_fprintf(out, arg, "\n"); + } +} + +static void mi_stat_print(const mi_stat_count_t* stat, const char* msg, int64_t unit, mi_output_fun* out, void* arg) { + mi_stat_print_ex(stat, msg, unit, out, arg, NULL); +} + +static void mi_stat_peak_print(const mi_stat_count_t* stat, const char* msg, int64_t unit, mi_output_fun* out, void* arg) { + _mi_fprintf(out, arg, "%10s:", msg); + mi_print_amount(stat->peak, unit, out, arg); + _mi_fprintf(out, arg, "\n"); +} + +static void mi_stat_counter_print(const mi_stat_counter_t* stat, const char* msg, mi_output_fun* out, void* arg ) { + _mi_fprintf(out, arg, "%10s:", msg); + mi_print_amount(stat->total, -1, out, arg); + _mi_fprintf(out, arg, "\n"); +} + + +static void mi_stat_counter_print_avg(const mi_stat_counter_t* stat, const char* msg, mi_output_fun* out, void* arg) { + const int64_t avg_tens = (stat->count == 0 ? 0 : (stat->total*10 / stat->count)); + const long avg_whole = (long)(avg_tens/10); + const long avg_frac1 = (long)(avg_tens%10); + _mi_fprintf(out, arg, "%10s: %5ld.%ld avg\n", msg, avg_whole, avg_frac1); +} + + +static void mi_print_header(mi_output_fun* out, void* arg ) { + _mi_fprintf(out, arg, "%10s: %11s %11s %11s %11s %11s %11s\n", "heap stats", "peak ", "total ", "freed ", "current ", "unit ", "count "); +} + +#if MI_STAT>1 +static void mi_stats_print_bins(const mi_stat_count_t* bins, size_t max, const char* fmt, mi_output_fun* out, void* arg) { + bool found = false; + char buf[64]; + for (size_t i = 0; i <= max; i++) { + if (bins[i].allocated > 0) { + found = true; + int64_t unit = _mi_bin_size((uint8_t)i); + snprintf(buf, 64, "%s %3lu", fmt, (long)i); + mi_stat_print(&bins[i], buf, unit, out, arg); + } + } + if (found) { + _mi_fprintf(out, arg, "\n"); + mi_print_header(out, arg); + } +} +#endif + + + +//------------------------------------------------------------ +// Use an output wrapper for line-buffered output +// (which is nice when using loggers etc.) +//------------------------------------------------------------ +typedef struct buffered_s { + mi_output_fun* out; // original output function + void* arg; // and state + char* buf; // local buffer of at least size `count+1` + size_t used; // currently used chars `used <= count` + size_t count; // total chars available for output +} buffered_t; + +static void mi_buffered_flush(buffered_t* buf) { + buf->buf[buf->used] = 0; + _mi_fputs(buf->out, buf->arg, NULL, buf->buf); + buf->used = 0; +} + +static void mi_cdecl mi_buffered_out(const char* msg, void* arg) { + buffered_t* buf = (buffered_t*)arg; + if (msg==NULL || buf==NULL) return; + for (const char* src = msg; *src != 0; src++) { + char c = *src; + if (buf->used >= buf->count) mi_buffered_flush(buf); + mi_assert_internal(buf->used < buf->count); + buf->buf[buf->used++] = c; + if (c == '\n') mi_buffered_flush(buf); + } +} + +//------------------------------------------------------------ +// Print statistics +//------------------------------------------------------------ + +static void _mi_stats_print(mi_stats_t* stats, mi_output_fun* out0, void* arg0) mi_attr_noexcept { + // wrap the output function to be line buffered + char buf[256]; + buffered_t buffer = { out0, arg0, NULL, 0, 255 }; + buffer.buf = buf; + mi_output_fun* out = &mi_buffered_out; + void* arg = &buffer; + + // and print using that + mi_print_header(out,arg); + #if MI_STAT>1 + mi_stats_print_bins(stats->normal_bins, MI_BIN_HUGE, "normal",out,arg); + #endif + #if MI_STAT + mi_stat_print(&stats->normal, "normal", (stats->normal_count.count == 0 ? 1 : -(stats->normal.allocated / stats->normal_count.count)), out, arg); + mi_stat_print(&stats->large, "large", (stats->large_count.count == 0 ? 1 : -(stats->large.allocated / stats->large_count.count)), out, arg); + mi_stat_print(&stats->huge, "huge", (stats->huge_count.count == 0 ? 1 : -(stats->huge.allocated / stats->huge_count.count)), out, arg); + mi_stat_count_t total = { 0,0,0,0 }; + mi_stat_add(&total, &stats->normal, 1); + mi_stat_add(&total, &stats->large, 1); + mi_stat_add(&total, &stats->huge, 1); + mi_stat_print(&total, "total", 1, out, arg); + #endif + #if MI_STAT>1 + mi_stat_print(&stats->malloc, "malloc req", 1, out, arg); + _mi_fprintf(out, arg, "\n"); + #endif + mi_stat_print_ex(&stats->reserved, "reserved", 1, out, arg, ""); + mi_stat_print_ex(&stats->committed, "committed", 1, out, arg, ""); + mi_stat_peak_print(&stats->reset, "reset", 1, out, arg ); + mi_stat_peak_print(&stats->purged, "purged", 1, out, arg ); + mi_stat_print(&stats->page_committed, "touched", 1, out, arg); + mi_stat_print(&stats->segments, "segments", -1, out, arg); + mi_stat_print(&stats->segments_abandoned, "-abandoned", -1, out, arg); + mi_stat_print(&stats->segments_cache, "-cached", -1, out, arg); + mi_stat_print(&stats->pages, "pages", -1, out, arg); + mi_stat_print(&stats->pages_abandoned, "-abandoned", -1, out, arg); + mi_stat_counter_print(&stats->pages_extended, "-extended", out, arg); + mi_stat_counter_print(&stats->page_no_retire, "-noretire", out, arg); + mi_stat_counter_print(&stats->mmap_calls, "mmaps", out, arg); + mi_stat_counter_print(&stats->commit_calls, "commits", out, arg); + mi_stat_counter_print(&stats->reset_calls, "resets", out, arg); + mi_stat_counter_print(&stats->purge_calls, "purges", out, arg); + mi_stat_print(&stats->threads, "threads", -1, out, arg); + mi_stat_counter_print_avg(&stats->searches, "searches", out, arg); + _mi_fprintf(out, arg, "%10s: %5zu\n", "numa nodes", _mi_os_numa_node_count()); + + size_t elapsed; + size_t user_time; + size_t sys_time; + size_t current_rss; + size_t peak_rss; + size_t current_commit; + size_t peak_commit; + size_t page_faults; + mi_process_info(&elapsed, &user_time, &sys_time, ¤t_rss, &peak_rss, ¤t_commit, &peak_commit, &page_faults); + _mi_fprintf(out, arg, "%10s: %5ld.%03ld s\n", "elapsed", elapsed/1000, elapsed%1000); + _mi_fprintf(out, arg, "%10s: user: %ld.%03ld s, system: %ld.%03ld s, faults: %lu, rss: ", "process", + user_time/1000, user_time%1000, sys_time/1000, sys_time%1000, (unsigned long)page_faults ); + mi_printf_amount((int64_t)peak_rss, 1, out, arg, "%s"); + if (peak_commit > 0) { + _mi_fprintf(out, arg, ", commit: "); + mi_printf_amount((int64_t)peak_commit, 1, out, arg, "%s"); + } + _mi_fprintf(out, arg, "\n"); +} + +static mi_msecs_t mi_process_start; // = 0 + +static mi_stats_t* mi_stats_get_default(void) { + mi_heap_t* heap = mi_heap_get_default(); + return &heap->tld->stats; +} + +static void mi_stats_merge_from(mi_stats_t* stats) { + if (stats != &_mi_stats_main) { + mi_stats_add(&_mi_stats_main, stats); + memset(stats, 0, sizeof(mi_stats_t)); + } +} + +void mi_stats_reset(void) mi_attr_noexcept { + mi_stats_t* stats = mi_stats_get_default(); + if (stats != &_mi_stats_main) { memset(stats, 0, sizeof(mi_stats_t)); } + memset(&_mi_stats_main, 0, sizeof(mi_stats_t)); + if (mi_process_start == 0) { mi_process_start = _mi_clock_start(); }; +} + +void mi_stats_merge(void) mi_attr_noexcept { + mi_stats_merge_from( mi_stats_get_default() ); +} + +void _mi_stats_done(mi_stats_t* stats) { // called from `mi_thread_done` + mi_stats_merge_from(stats); +} + +void mi_stats_print_out(mi_output_fun* out, void* arg) mi_attr_noexcept { + mi_stats_merge_from(mi_stats_get_default()); + _mi_stats_print(&_mi_stats_main, out, arg); +} + +void mi_stats_print(void* out) mi_attr_noexcept { + // for compatibility there is an `out` parameter (which can be `stdout` or `stderr`) + mi_stats_print_out((mi_output_fun*)out, NULL); +} + +void mi_thread_stats_print_out(mi_output_fun* out, void* arg) mi_attr_noexcept { + _mi_stats_print(mi_stats_get_default(), out, arg); +} + + +// ---------------------------------------------------------------- +// Basic timer for convenience; use milli-seconds to avoid doubles +// ---------------------------------------------------------------- + +static mi_msecs_t mi_clock_diff; + +mi_msecs_t _mi_clock_now(void) { + return _mi_prim_clock_now(); +} + +mi_msecs_t _mi_clock_start(void) { + if (mi_clock_diff == 0.0) { + mi_msecs_t t0 = _mi_clock_now(); + mi_clock_diff = _mi_clock_now() - t0; + } + return _mi_clock_now(); +} + +mi_msecs_t _mi_clock_end(mi_msecs_t start) { + mi_msecs_t end = _mi_clock_now(); + return (end - start - mi_clock_diff); +} + + +// -------------------------------------------------------- +// Basic process statistics +// -------------------------------------------------------- + +mi_decl_export void mi_process_info(size_t* elapsed_msecs, size_t* user_msecs, size_t* system_msecs, size_t* current_rss, size_t* peak_rss, size_t* current_commit, size_t* peak_commit, size_t* page_faults) mi_attr_noexcept +{ + mi_process_info_t pinfo; + _mi_memzero_var(pinfo); + pinfo.elapsed = _mi_clock_end(mi_process_start); + pinfo.current_commit = (size_t)(mi_atomic_loadi64_relaxed((_Atomic(int64_t)*)&_mi_stats_main.committed.current)); + pinfo.peak_commit = (size_t)(mi_atomic_loadi64_relaxed((_Atomic(int64_t)*)&_mi_stats_main.committed.peak)); + pinfo.current_rss = pinfo.current_commit; + pinfo.peak_rss = pinfo.peak_commit; + pinfo.utime = 0; + pinfo.stime = 0; + pinfo.page_faults = 0; + + _mi_prim_process_info(&pinfo); + + if (elapsed_msecs!=NULL) *elapsed_msecs = (pinfo.elapsed < 0 ? 0 : (pinfo.elapsed < (mi_msecs_t)PTRDIFF_MAX ? (size_t)pinfo.elapsed : PTRDIFF_MAX)); + if (user_msecs!=NULL) *user_msecs = (pinfo.utime < 0 ? 0 : (pinfo.utime < (mi_msecs_t)PTRDIFF_MAX ? (size_t)pinfo.utime : PTRDIFF_MAX)); + if (system_msecs!=NULL) *system_msecs = (pinfo.stime < 0 ? 0 : (pinfo.stime < (mi_msecs_t)PTRDIFF_MAX ? (size_t)pinfo.stime : PTRDIFF_MAX)); + if (current_rss!=NULL) *current_rss = pinfo.current_rss; + if (peak_rss!=NULL) *peak_rss = pinfo.peak_rss; + if (current_commit!=NULL) *current_commit = pinfo.current_commit; + if (peak_commit!=NULL) *peak_commit = pinfo.peak_commit; + if (page_faults!=NULL) *page_faults = pinfo.page_faults; +} diff --git a/Objects/moduleobject.c b/Objects/moduleobject.c index 7e890d021cb946..3a1c516658dce7 100644 --- a/Objects/moduleobject.c +++ b/Objects/moduleobject.c @@ -510,25 +510,32 @@ PyModule_GetDict(PyObject *m) } PyObject* -PyModule_GetNameObject(PyObject *m) +PyModule_GetNameObject(PyObject *mod) { - PyObject *d; - PyObject *name; - if (!PyModule_Check(m)) { + if (!PyModule_Check(mod)) { PyErr_BadArgument(); return NULL; } - d = ((PyModuleObject *)m)->md_dict; - if (d == NULL || !PyDict_Check(d) || - (name = PyDict_GetItemWithError(d, &_Py_ID(__name__))) == NULL || - !PyUnicode_Check(name)) - { - if (!PyErr_Occurred()) { - PyErr_SetString(PyExc_SystemError, "nameless module"); - } - return NULL; + PyObject *dict = ((PyModuleObject *)mod)->md_dict; // borrowed reference + if (dict == NULL || !PyDict_Check(dict)) { + goto error; } - return Py_NewRef(name); + PyObject *name; + if (PyDict_GetItemRef(dict, &_Py_ID(__name__), &name) <= 0) { + // error or not found + goto error; + } + if (!PyUnicode_Check(name)) { + Py_DECREF(name); + goto error; + } + return name; + +error: + if (!PyErr_Occurred()) { + PyErr_SetString(PyExc_SystemError, "nameless module"); + } + return NULL; } const char * @@ -544,25 +551,32 @@ PyModule_GetName(PyObject *m) } PyObject* -PyModule_GetFilenameObject(PyObject *m) +PyModule_GetFilenameObject(PyObject *mod) { - PyObject *d; - PyObject *fileobj; - if (!PyModule_Check(m)) { + if (!PyModule_Check(mod)) { PyErr_BadArgument(); return NULL; } - d = ((PyModuleObject *)m)->md_dict; - if (d == NULL || - (fileobj = PyDict_GetItemWithError(d, &_Py_ID(__file__))) == NULL || - !PyUnicode_Check(fileobj)) - { - if (!PyErr_Occurred()) { - PyErr_SetString(PyExc_SystemError, "module filename missing"); - } - return NULL; + PyObject *dict = ((PyModuleObject *)mod)->md_dict; // borrowed reference + if (dict == NULL) { + goto error; } - return Py_NewRef(fileobj); + PyObject *fileobj; + if (PyDict_GetItemRef(dict, &_Py_ID(__file__), &fileobj) <= 0) { + // error or not found + goto error; + } + if (!PyUnicode_Check(fileobj)) { + Py_DECREF(fileobj); + goto error; + } + return fileobj; + +error: + if (!PyErr_Occurred()) { + PyErr_SetString(PyExc_SystemError, "module filename missing"); + } + return NULL; } const char * @@ -635,7 +649,7 @@ _PyModule_ClearDict(PyObject *d) PyErr_Clear(); } if (PyDict_SetItem(d, key, Py_None) != 0) { - PyErr_WriteUnraisable(NULL); + PyErr_FormatUnraisable("Exception ignored on clearing module dict"); } } } @@ -656,7 +670,7 @@ _PyModule_ClearDict(PyObject *d) PyErr_Clear(); } if (PyDict_SetItem(d, key, Py_None) != 0) { - PyErr_WriteUnraisable(NULL); + PyErr_FormatUnraisable("Exception ignored on clearing module dict"); } } } @@ -735,27 +749,20 @@ module_repr(PyModuleObject *m) } /* Check if the "_initializing" attribute of the module spec is set to true. - Clear the exception and return 0 if spec is NULL. */ int _PyModuleSpec_IsInitializing(PyObject *spec) { - if (spec != NULL) { - PyObject *value; - int ok = PyObject_GetOptionalAttr(spec, &_Py_ID(_initializing), &value); - if (ok == 0) { - return 0; - } - if (value != NULL) { - int initializing = PyObject_IsTrue(value); - Py_DECREF(value); - if (initializing >= 0) { - return initializing; - } - } + if (spec == NULL) { + return 0; } - PyErr_Clear(); - return 0; + PyObject *value; + int rc = PyObject_GetOptionalAttr(spec, &_Py_ID(_initializing), &value); + if (rc > 0) { + rc = PyObject_IsTrue(value); + Py_DECREF(value); + } + return rc; } /* Check if the submodule name is in the "_uninitialized_submodules" attribute @@ -768,24 +775,20 @@ _PyModuleSpec_IsUninitializedSubmodule(PyObject *spec, PyObject *name) return 0; } - PyObject *value = PyObject_GetAttr(spec, &_Py_ID(_uninitialized_submodules)); - if (value == NULL) { - return 0; - } - - int is_uninitialized = PySequence_Contains(value, name); - Py_DECREF(value); - if (is_uninitialized == -1) { - return 0; + PyObject *value; + int rc = PyObject_GetOptionalAttr(spec, &_Py_ID(_uninitialized_submodules), &value); + if (rc > 0) { + rc = PySequence_Contains(value, name); + Py_DECREF(value); } - return is_uninitialized; + return rc; } PyObject* _Py_module_getattro_impl(PyModuleObject *m, PyObject *name, int suppress) { // When suppress=1, this function suppresses AttributeError. - PyObject *attr, *mod_name, *getattr; + PyObject *attr, *mod_name, *getattr, *origin; attr = _PyObject_GenericGetAttrWithDict((PyObject *)m, name, NULL, suppress); if (attr) { return attr; @@ -804,54 +807,76 @@ _Py_module_getattro_impl(PyModuleObject *m, PyObject *name, int suppress) PyErr_Clear(); } assert(m->md_dict != NULL); - getattr = PyDict_GetItemWithError(m->md_dict, &_Py_ID(__getattr__)); + if (PyDict_GetItemRef(m->md_dict, &_Py_ID(__getattr__), &getattr) < 0) { + return NULL; + } if (getattr) { PyObject *result = PyObject_CallOneArg(getattr, name); if (result == NULL && suppress == 1 && PyErr_ExceptionMatches(PyExc_AttributeError)) { // suppress AttributeError PyErr_Clear(); } + Py_DECREF(getattr); return result; } - if (PyErr_Occurred()) { + if (PyDict_GetItemRef(m->md_dict, &_Py_ID(__name__), &mod_name) < 0) { return NULL; } - mod_name = PyDict_GetItemWithError(m->md_dict, &_Py_ID(__name__)); if (mod_name && PyUnicode_Check(mod_name)) { - Py_INCREF(mod_name); - PyObject *spec = PyDict_GetItemWithError(m->md_dict, &_Py_ID(__spec__)); - if (spec == NULL && PyErr_Occurred()) { + PyObject *spec; + if (PyDict_GetItemRef(m->md_dict, &_Py_ID(__spec__), &spec) < 0) { Py_DECREF(mod_name); return NULL; } if (suppress != 1) { - Py_XINCREF(spec); - if (_PyModuleSpec_IsInitializing(spec)) { - PyErr_Format(PyExc_AttributeError, + int rc = _PyModuleSpec_IsInitializing(spec); + if (rc > 0) { + int valid_spec = PyObject_GetOptionalAttr(spec, &_Py_ID(origin), &origin); + if (valid_spec == -1) { + Py_XDECREF(spec); + Py_DECREF(mod_name); + return NULL; + } + if (valid_spec == 1 && !PyUnicode_Check(origin)) { + valid_spec = 0; + Py_DECREF(origin); + } + if (valid_spec == 1) { + PyErr_Format(PyExc_AttributeError, + "partially initialized " + "module '%U' from '%U' has no attribute '%U' " + "(most likely due to a circular import)", + mod_name, origin, name); + Py_DECREF(origin); + } + else { + PyErr_Format(PyExc_AttributeError, "partially initialized " "module '%U' has no attribute '%U' " "(most likely due to a circular import)", mod_name, name); + } } - else if (_PyModuleSpec_IsUninitializedSubmodule(spec, name)) { - PyErr_Format(PyExc_AttributeError, + else if (rc == 0) { + rc = _PyModuleSpec_IsUninitializedSubmodule(spec, name); + if (rc > 0) { + PyErr_Format(PyExc_AttributeError, "cannot access submodule '%U' of module '%U' " "(most likely due to a circular import)", name, mod_name); - } - else { - PyErr_Format(PyExc_AttributeError, + } + else if (rc == 0) { + PyErr_Format(PyExc_AttributeError, "module '%U' has no attribute '%U'", mod_name, name); + } } - Py_XDECREF(spec); } + Py_XDECREF(spec); Py_DECREF(mod_name); return NULL; } - else if (PyErr_Occurred()) { - return NULL; - } + Py_XDECREF(mod_name); if (suppress != 1) { PyErr_Format(PyExc_AttributeError, "module has no attribute '%U'", name); @@ -890,10 +915,9 @@ module_clear(PyModuleObject *m) { int res = m->md_def->m_clear((PyObject*)m); if (PyErr_Occurred()) { - PySys_FormatStderr("Exception ignored in m_clear of module%s%V\n", - m->md_name ? " " : "", - m->md_name, ""); - PyErr_WriteUnraisable(NULL); + PyErr_FormatUnraisable("Exception ignored in m_clear of module%s%V", + m->md_name ? " " : "", + m->md_name, ""); } if (res) return res; @@ -946,11 +970,8 @@ module_get_annotations(PyModuleObject *m, void *Py_UNUSED(ignored)) return NULL; } - PyObject *annotations = PyDict_GetItemWithError(dict, &_Py_ID(__annotations__)); - if (annotations) { - Py_INCREF(annotations); - } - else if (!PyErr_Occurred()) { + PyObject *annotations; + if (PyDict_GetItemRef(dict, &_Py_ID(__annotations__), &annotations) == 0) { annotations = PyDict_New(); if (annotations) { int result = PyDict_SetItem( diff --git a/Objects/namespaceobject.c b/Objects/namespaceobject.c index 11cf859add3ab8..b975bcfeea2cdf 100644 --- a/Objects/namespaceobject.c +++ b/Objects/namespaceobject.c @@ -1,12 +1,12 @@ // namespace object implementation #include "Python.h" +#include "pycore_modsupport.h" // _PyArg_NoPositional() #include "pycore_namespace.h" // _PyNamespace_Type #include // offsetof() - typedef struct { PyObject_HEAD PyObject *ns_dict; @@ -189,9 +189,37 @@ namespace_reduce(_PyNamespaceObject *ns, PyObject *Py_UNUSED(ignored)) } +static PyObject * +namespace_replace(PyObject *self, PyObject *args, PyObject *kwargs) +{ + if (!_PyArg_NoPositional("__replace__", args)) { + return NULL; + } + + PyObject *result = PyObject_CallNoArgs((PyObject *)Py_TYPE(self)); + if (!result) { + return NULL; + } + if (PyDict_Update(((_PyNamespaceObject*)result)->ns_dict, + ((_PyNamespaceObject*)self)->ns_dict) < 0) + { + Py_DECREF(result); + return NULL; + } + if (kwargs) { + if (PyDict_Update(((_PyNamespaceObject*)result)->ns_dict, kwargs) < 0) { + Py_DECREF(result); + return NULL; + } + } + return result; +} + + static PyMethodDef namespace_methods[] = { {"__reduce__", (PyCFunction)namespace_reduce, METH_NOARGS, namespace_reduce__doc__}, + {"__replace__", _PyCFunction_CAST(namespace_replace), METH_VARARGS|METH_KEYWORDS, NULL}, {NULL, NULL} // sentinel }; diff --git a/Objects/object.c b/Objects/object.c index c4413a00ede80c..587c5528c01345 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -9,15 +9,19 @@ #include "pycore_dict.h" // _PyObject_MakeDictFromInstanceAttributes() #include "pycore_floatobject.h" // _PyFloat_DebugMallocStats() #include "pycore_initconfig.h" // _PyStatus_EXCEPTION() +#include "pycore_hashtable.h" // _Py_hashtable_new() +#include "pycore_memoryobject.h" // _PyManagedBuffer_Type #include "pycore_namespace.h" // _PyNamespace_Type #include "pycore_object.h" // PyAPI_DATA() _Py_SwappedOp definition +#include "pycore_optimizer.h" // _PyUOpExecutor_Type, _PyUOpOptimizer_Type, ... #include "pycore_pyerrors.h" // _PyErr_Occurred() #include "pycore_pymem.h" // _PyMem_IsPtrFreed() #include "pycore_pystate.h" // _PyThreadState_GET() #include "pycore_symtable.h" // PySTEntry_Type -#include "pycore_typevarobject.h" // _PyTypeAlias_Type, _Py_initialize_generic #include "pycore_typeobject.h" // _PyBufferWrapper_Type +#include "pycore_typevarobject.h" // _PyTypeAlias_Type, _Py_initialize_generic #include "pycore_unionobject.h" // _PyUnion_Type + #include "interpreteridobject.h" // _PyInterpreterID_Type #ifdef Py_LIMITED_API @@ -25,10 +29,6 @@ # error "Py_LIMITED_API macro must not be defined" #endif -#ifdef __cplusplus -extern "C" { -#endif - /* Defined in tracemalloc.c */ extern void _PyMem_DumpTraceback(int fd, const void *ptr); @@ -160,36 +160,51 @@ _PyDebug_PrintTotalRefs(void) { #ifdef Py_TRACE_REFS -#define REFCHAIN(interp) &interp->object_state.refchain - -/* Insert op at the front of the list of all objects. If force is true, - * op is added even if _ob_prev and _ob_next are non-NULL already. If - * force is false amd _ob_prev or _ob_next are non-NULL, do nothing. - * force should be true if and only if op points to freshly allocated, - * uninitialized memory, or you've unlinked op from the list and are - * relinking it into the front. - * Note that objects are normally added to the list via _Py_NewReference, - * which is called by PyObject_Init. Not all objects are initialized that - * way, though; exceptions include statically allocated type objects, and - * statically allocated singletons (like Py_True and Py_None). - */ -void -_Py_AddToAllObjects(PyObject *op, int force) +#define REFCHAIN(interp) interp->object_state.refchain +#define REFCHAIN_VALUE ((void*)(uintptr_t)1) + +bool +_PyRefchain_IsTraced(PyInterpreterState *interp, PyObject *obj) { -#ifdef Py_DEBUG - if (!force) { - /* If it's initialized memory, op must be in or out of - * the list unambiguously. - */ - _PyObject_ASSERT(op, (op->_ob_prev == NULL) == (op->_ob_next == NULL)); + return (_Py_hashtable_get(REFCHAIN(interp), obj) == REFCHAIN_VALUE); +} + + +static void +_PyRefchain_Trace(PyInterpreterState *interp, PyObject *obj) +{ + if (_Py_hashtable_set(REFCHAIN(interp), obj, REFCHAIN_VALUE) < 0) { + // Use a fatal error because _Py_NewReference() cannot report + // the error to the caller. + Py_FatalError("_Py_hashtable_set() memory allocation failed"); } +} + + +static void +_PyRefchain_Remove(PyInterpreterState *interp, PyObject *obj) +{ + void *value = _Py_hashtable_steal(REFCHAIN(interp), obj); +#ifndef NDEBUG + assert(value == REFCHAIN_VALUE); +#else + (void)value; #endif - if (force || op->_ob_prev == NULL) { - PyObject *refchain = REFCHAIN(_PyInterpreterState_GET()); - op->_ob_next = refchain->_ob_next; - op->_ob_prev = refchain; - refchain->_ob_next->_ob_prev = op; - refchain->_ob_next = op; +} + + +/* Add an object to the refchain hash table. + * + * Note that objects are normally added to the list by PyObject_Init() + * indirectly. Not all objects are initialized that way, though; exceptions + * include statically allocated type objects, and statically allocated + * singletons (like Py_True and Py_None). */ +void +_Py_AddToAllObjects(PyObject *op) +{ + PyInterpreterState *interp = _PyInterpreterState_GET(); + if (!_PyRefchain_IsTraced(interp, op)) { + _PyRefchain_Trace(interp, op); } } #endif /* Py_TRACE_REFS */ @@ -281,6 +296,126 @@ _Py_DecRef(PyObject *o) Py_DECREF(o); } +#ifdef Py_GIL_DISABLED +# ifdef Py_REF_DEBUG +static inline int +is_shared_refcnt_dead(Py_ssize_t shared) +{ +# if SIZEOF_SIZE_T == 8 + return shared == (Py_ssize_t)0xDDDDDDDDDDDDDDDD; +# else + return shared == (Py_ssize_t)0xDDDDDDDD; +# endif +} +# endif + +void +_Py_DecRefSharedDebug(PyObject *o, const char *filename, int lineno) +{ + // Should we queue the object for the owning thread to merge? + int should_queue; + + Py_ssize_t new_shared; + Py_ssize_t shared = _Py_atomic_load_ssize_relaxed(&o->ob_ref_shared); + do { + should_queue = (shared == 0 || shared == _Py_REF_MAYBE_WEAKREF); + + if (should_queue) { + // If the object had refcount zero, not queued, and not merged, + // then we enqueue the object to be merged by the owning thread. + // In this case, we don't subtract one from the reference count + // because the queue holds a reference. + new_shared = _Py_REF_QUEUED; + } + else { + // Otherwise, subtract one from the reference count. This might + // be negative! + new_shared = shared - (1 << _Py_REF_SHARED_SHIFT); + } + +#ifdef Py_REF_DEBUG + if ((_Py_REF_IS_MERGED(new_shared) && new_shared < 0) || + is_shared_refcnt_dead(shared)) + { + _Py_NegativeRefcount(filename, lineno, o); + } +#endif + } while (!_Py_atomic_compare_exchange_ssize(&o->ob_ref_shared, + &shared, new_shared)); + + if (should_queue) { + // TODO: the inter-thread queue is not yet implemented. For now, + // we just merge the refcount here. + Py_ssize_t refcount = _Py_ExplicitMergeRefcount(o, -1); + if (refcount == 0) { + _Py_Dealloc(o); + } + } + else if (new_shared == _Py_REF_MERGED) { + // refcount is zero AND merged + _Py_Dealloc(o); + } +} + +void +_Py_DecRefShared(PyObject *o) +{ + _Py_DecRefSharedDebug(o, NULL, 0); +} + +void +_Py_MergeZeroLocalRefcount(PyObject *op) +{ + assert(op->ob_ref_local == 0); + + _Py_atomic_store_uintptr_relaxed(&op->ob_tid, 0); + Py_ssize_t shared = _Py_atomic_load_ssize_relaxed(&op->ob_ref_shared); + if (shared == 0) { + // Fast-path: shared refcount is zero (including flags) + _Py_Dealloc(op); + return; + } + + // Slow-path: atomically set the flags (low two bits) to _Py_REF_MERGED. + Py_ssize_t new_shared; + do { + new_shared = (shared & ~_Py_REF_SHARED_FLAG_MASK) | _Py_REF_MERGED; + } while (!_Py_atomic_compare_exchange_ssize(&op->ob_ref_shared, + &shared, new_shared)); + + if (new_shared == _Py_REF_MERGED) { + // i.e., the shared refcount is zero (only the flags are set) so we + // deallocate the object. + _Py_Dealloc(op); + } +} + +Py_ssize_t +_Py_ExplicitMergeRefcount(PyObject *op, Py_ssize_t extra) +{ + assert(!_Py_IsImmortal(op)); + Py_ssize_t refcnt; + Py_ssize_t new_shared; + Py_ssize_t shared = _Py_atomic_load_ssize_relaxed(&op->ob_ref_shared); + do { + refcnt = Py_ARITHMETIC_RIGHT_SHIFT(Py_ssize_t, shared, _Py_REF_SHARED_SHIFT); + if (_Py_REF_IS_MERGED(shared)) { + return refcnt; + } + + refcnt += (Py_ssize_t)op->ob_ref_local; + refcnt += extra; + + new_shared = _Py_REF_SHARED(refcnt, _Py_REF_MERGED); + } while (!_Py_atomic_compare_exchange_ssize(&op->ob_ref_shared, + &shared, new_shared)); + + _Py_atomic_store_uint32_relaxed(&op->ob_ref_local, 0); + _Py_atomic_store_uintptr_relaxed(&op->ob_tid, 0); + return refcnt; +} +#endif /* Py_GIL_DISABLED */ + /**************************************/ @@ -374,9 +509,7 @@ PyObject_CallFinalizerFromDealloc(PyObject *self) /* tp_finalize resurrected it! Make it look like the original Py_DECREF * never happened. */ - Py_ssize_t refcnt = Py_REFCNT(self); - _Py_NewReferenceNoTotal(self); - Py_SET_REFCNT(self, refcnt); + _Py_ResurrectReference(self); _PyObject_ASSERT(self, (!_PyType_IS_GC(Py_TYPE(self)) @@ -461,16 +594,6 @@ _PyObject_IsFreed(PyObject *op) if (_PyMem_IsPtrFreed(op) || _PyMem_IsPtrFreed(Py_TYPE(op))) { return 1; } - /* ignore op->ob_ref: its value can have be modified - by Py_INCREF() and Py_DECREF(). */ -#ifdef Py_TRACE_REFS - if (op->_ob_next != NULL && _PyMem_IsPtrFreed(op->_ob_next)) { - return 1; - } - if (op->_ob_prev != NULL && _PyMem_IsPtrFreed(op->_ob_prev)) { - return 1; - } -#endif return 0; } @@ -903,26 +1026,27 @@ PyObject_GetAttrString(PyObject *v, const char *name) } int -PyObject_HasAttrString(PyObject *v, const char *name) +PyObject_HasAttrStringWithError(PyObject *obj, const char *name) { - if (Py_TYPE(v)->tp_getattr != NULL) { - PyObject *res = (*Py_TYPE(v)->tp_getattr)(v, (char*)name); - if (res != NULL) { - Py_DECREF(res); - return 1; - } - PyErr_Clear(); - return 0; - } + PyObject *res; + int rc = PyObject_GetOptionalAttrString(obj, name, &res); + Py_XDECREF(res); + return rc; +} - PyObject *attr_name = PyUnicode_FromString(name); - if (attr_name == NULL) { - PyErr_Clear(); + +int +PyObject_HasAttrString(PyObject *obj, const char *name) +{ + int rc = PyObject_HasAttrStringWithError(obj, name); + if (rc < 0) { + PyErr_FormatUnraisable( + "Exception ignored in PyObject_HasAttrString(); consider using " + "PyObject_HasAttrStringWithError(), " + "PyObject_GetOptionalAttrString() or PyObject_GetAttrString()"); return 0; } - int ok = PyObject_HasAttr(v, attr_name); - Py_DECREF(attr_name); - return ok; + return rc; } int @@ -1070,7 +1194,7 @@ PyObject_GetOptionalAttr(PyObject *v, PyObject *name, PyObject **result) } return 0; } - if (tp->tp_getattro == (getattrofunc)_Py_type_getattro) { + if (tp->tp_getattro == _Py_type_getattro) { int supress_missing_attribute_exception = 0; *result = _Py_type_getattro_impl((PyTypeObject*)v, name, &supress_missing_attribute_exception); if (supress_missing_attribute_exception) { @@ -1141,18 +1265,26 @@ PyObject_GetOptionalAttrString(PyObject *obj, const char *name, PyObject **resul } int -PyObject_HasAttr(PyObject *v, PyObject *name) +PyObject_HasAttrWithError(PyObject *obj, PyObject *name) { PyObject *res; - if (PyObject_GetOptionalAttr(v, name, &res) < 0) { - PyErr_Clear(); - return 0; - } - if (res == NULL) { + int rc = PyObject_GetOptionalAttr(obj, name, &res); + Py_XDECREF(res); + return rc; +} + +int +PyObject_HasAttr(PyObject *obj, PyObject *name) +{ + int rc = PyObject_HasAttrWithError(obj, name); + if (rc < 0) { + PyErr_FormatUnraisable( + "Exception ignored in PyObject_HasAttr(); consider using " + "PyObject_HasAttrWithError(), " + "PyObject_GetOptionalAttr() or PyObject_GetAttr()"); return 0; } - Py_DECREF(res); - return 1; + return rc; } int @@ -1356,19 +1488,14 @@ _PyObject_GetMethod(PyObject *obj, PyObject *name, PyObject **method) } if (dict != NULL) { Py_INCREF(dict); - PyObject *attr = PyDict_GetItemWithError(dict, name); - if (attr != NULL) { - *method = Py_NewRef(attr); + if (PyDict_GetItemRef(dict, name, method) != 0) { + // found or error Py_DECREF(dict); Py_XDECREF(descr); return 0; } + // not found Py_DECREF(dict); - - if (PyErr_Occurred()) { - Py_XDECREF(descr); - return 0; - } } if (meth_found) { @@ -1473,21 +1600,17 @@ _PyObject_GenericGetAttrWithDict(PyObject *obj, PyObject *name, } if (dict != NULL) { Py_INCREF(dict); - res = PyDict_GetItemWithError(dict, name); + int rc = PyDict_GetItemRef(dict, name, &res); + Py_DECREF(dict); if (res != NULL) { - Py_INCREF(res); - Py_DECREF(dict); goto done; } - else { - Py_DECREF(dict); - if (PyErr_Occurred()) { - if (suppress && PyErr_ExceptionMatches(PyExc_AttributeError)) { - PyErr_Clear(); - } - else { - goto done; - } + else if (rc < 0) { + if (suppress && PyErr_ExceptionMatches(PyExc_AttributeError)) { + PyErr_Clear(); + } + else { + goto done; } } } @@ -1569,6 +1692,14 @@ _PyObject_GenericSetAttrWithDict(PyObject *obj, PyObject *name, goto error_check; } dictptr = &dorv_ptr->dict; + if (*dictptr == NULL) { + if (_PyObject_InitInlineValues(obj, tp) < 0) { + goto done; + } + res = _PyObject_StoreInstanceAttribute( + obj, _PyDictOrValues_GetValues(*dorv_ptr), name, value); + goto error_check; + } } else { dictptr = _PyObject_ComputedDictPointer(obj); @@ -1893,7 +2024,7 @@ PyTypeObject _PyNone_Type = { 0, /*tp_doc */ 0, /*tp_traverse */ 0, /*tp_clear */ - 0, /*tp_richcompare */ + _Py_BaseObject_RichCompare, /*tp_richcompare */ 0, /*tp_weaklistoffset */ 0, /*tp_iter */ 0, /*tp_iternext */ @@ -1910,11 +2041,7 @@ PyTypeObject _PyNone_Type = { none_new, /*tp_new */ }; -PyObject _Py_NoneStruct = { - _PyObject_EXTRA_INIT - { _Py_IMMORTAL_REFCNT }, - &_PyNone_Type -}; +PyObject _Py_NoneStruct = _PyObject_HEAD_INIT(&_PyNone_Type); /* NotImplemented is an object that can be used to signal that an operation is not implemented for the given type combination. */ @@ -2013,17 +2140,45 @@ PyTypeObject _PyNotImplemented_Type = { notimplemented_new, /*tp_new */ }; -PyObject _Py_NotImplementedStruct = { - _PyObject_EXTRA_INIT - { _Py_IMMORTAL_REFCNT }, - &_PyNotImplemented_Type -}; +PyObject _Py_NotImplementedStruct = _PyObject_HEAD_INIT(&_PyNotImplemented_Type); -extern PyTypeObject _Py_GenericAliasIterType; -extern PyTypeObject _PyMemoryIter_Type; + +PyStatus +_PyObject_InitState(PyInterpreterState *interp) +{ +#ifdef Py_TRACE_REFS + _Py_hashtable_allocator_t alloc = { + // Don't use default PyMem_Malloc() and PyMem_Free() which + // require the caller to hold the GIL. + .malloc = PyMem_RawMalloc, + .free = PyMem_RawFree, + }; + REFCHAIN(interp) = _Py_hashtable_new_full( + _Py_hashtable_hash_ptr, _Py_hashtable_compare_direct, + NULL, NULL, &alloc); + if (REFCHAIN(interp) == NULL) { + return _PyStatus_NO_MEMORY(); + } +#endif + return _PyStatus_OK(); +} + +void +_PyObject_FiniState(PyInterpreterState *interp) +{ +#ifdef Py_TRACE_REFS + _Py_hashtable_destroy(REFCHAIN(interp)); + REFCHAIN(interp) = NULL; +#endif +} + + +extern PyTypeObject _PyAnextAwaitable_Type; +extern PyTypeObject _PyLegacyEventHandler_Type; extern PyTypeObject _PyLineIterator; +extern PyTypeObject _PyMemoryIter_Type; extern PyTypeObject _PyPositionsIterator; -extern PyTypeObject _PyLegacyEventHandler_Type; +extern PyTypeObject _Py_GenericAliasIterType; static PyTypeObject* static_types[] = { // The two most important base types: must be initialized first and @@ -2112,6 +2267,9 @@ static PyTypeObject* static_types[] = { &_PyBufferWrapper_Type, &_PyContextTokenMissing_Type, &_PyCoroWrapper_Type, + &_PyCounterExecutor_Type, + &_PyCounterOptimizer_Type, + &_PyDefaultOptimizer_Type, &_Py_GenericAliasIterType, &_PyHamtItems_Type, &_PyHamtKeys_Type, @@ -2131,6 +2289,8 @@ static PyTypeObject* static_types[] = { &_PyPositionsIterator, &_PyUnicodeASCIIIter_Type, &_PyUnion_Type, + &_PyUOpExecutor_Type, + &_PyUOpOptimizer_Type, &_PyWeakref_CallableProxyType, &_PyWeakref_ProxyType, &_PyWeakref_RefType, @@ -2197,9 +2357,18 @@ new_reference(PyObject *op) _PyTraceMalloc_NewReference(op); } // Skip the immortal object check in Py_SET_REFCNT; always set refcnt to 1 +#if !defined(Py_GIL_DISABLED) op->ob_refcnt = 1; +#else + op->ob_tid = _Py_ThreadId(); + op->_padding = 0; + op->ob_mutex = (struct _PyMutex){ 0 }; + op->ob_gc_bits = 0; + op->ob_ref_local = 1; + op->ob_ref_shared = 0; +#endif #ifdef Py_TRACE_REFS - _Py_AddToAllObjects(op, 1); + _Py_AddToAllObjects(op); #endif } @@ -2218,6 +2387,17 @@ _Py_NewReferenceNoTotal(PyObject *op) new_reference(op); } +void +_Py_ResurrectReference(PyObject *op) +{ + if (_PyRuntime.tracemalloc.config.tracing) { + _PyTraceMalloc_NewReference(op); + } +#ifdef Py_TRACE_REFS + _Py_AddToAllObjects(op); +#endif +} + #ifdef Py_TRACE_REFS void @@ -2227,53 +2407,62 @@ _Py_ForgetReference(PyObject *op) _PyObject_ASSERT_FAILED_MSG(op, "negative refcnt"); } - PyObject *refchain = REFCHAIN(_PyInterpreterState_GET()); - if (op == refchain || - op->_ob_prev->_ob_next != op || op->_ob_next->_ob_prev != op) - { - _PyObject_ASSERT_FAILED_MSG(op, "invalid object chain"); - } + PyInterpreterState *interp = _PyInterpreterState_GET(); #ifdef SLOW_UNREF_CHECK - PyObject *p; - for (p = refchain->_ob_next; p != refchain; p = p->_ob_next) { - if (p == op) { - break; - } - } - if (p == refchain) { + if (!_PyRefchain_Get(interp, op)) { /* Not found */ _PyObject_ASSERT_FAILED_MSG(op, "object not found in the objects list"); } #endif - op->_ob_next->_ob_prev = op->_ob_prev; - op->_ob_prev->_ob_next = op->_ob_next; - op->_ob_next = op->_ob_prev = NULL; + _PyRefchain_Remove(interp, op); +} + +static int +_Py_PrintReference(_Py_hashtable_t *ht, + const void *key, const void *value, + void *user_data) +{ + PyObject *op = (PyObject*)key; + FILE *fp = (FILE *)user_data; + fprintf(fp, "%p [%zd] ", (void *)op, Py_REFCNT(op)); + if (PyObject_Print(op, fp, 0) != 0) { + PyErr_Clear(); + } + putc('\n', fp); + return 0; } + /* Print all live objects. Because PyObject_Print is called, the * interpreter must be in a healthy state. */ void _Py_PrintReferences(PyInterpreterState *interp, FILE *fp) { - PyObject *op; if (interp == NULL) { interp = _PyInterpreterState_Main(); } fprintf(fp, "Remaining objects:\n"); - PyObject *refchain = REFCHAIN(interp); - for (op = refchain->_ob_next; op != refchain; op = op->_ob_next) { - fprintf(fp, "%p [%zd] ", (void *)op, Py_REFCNT(op)); - if (PyObject_Print(op, fp, 0) != 0) { - PyErr_Clear(); - } - putc('\n', fp); - } + _Py_hashtable_foreach(REFCHAIN(interp), _Py_PrintReference, fp); } + +static int +_Py_PrintReferenceAddress(_Py_hashtable_t *ht, + const void *key, const void *value, + void *user_data) +{ + PyObject *op = (PyObject*)key; + FILE *fp = (FILE *)user_data; + fprintf(fp, "%p [%zd] %s\n", + (void *)op, Py_REFCNT(op), Py_TYPE(op)->tp_name); + return 0; +} + + /* Print the addresses of all live objects. Unlike _Py_PrintReferences, this * doesn't make any calls to the Python C API, so is always safe to call. */ @@ -2284,49 +2473,98 @@ _Py_PrintReferences(PyInterpreterState *interp, FILE *fp) void _Py_PrintReferenceAddresses(PyInterpreterState *interp, FILE *fp) { - PyObject *op; - PyObject *refchain = REFCHAIN(interp); fprintf(fp, "Remaining object addresses:\n"); - for (op = refchain->_ob_next; op != refchain; op = op->_ob_next) - fprintf(fp, "%p [%zd] %s\n", (void *)op, - Py_REFCNT(op), Py_TYPE(op)->tp_name); + _Py_hashtable_foreach(REFCHAIN(interp), _Py_PrintReferenceAddress, fp); +} + + +typedef struct { + PyObject *self; + PyObject *args; + PyObject *list; + PyObject *type; + Py_ssize_t limit; +} _Py_GetObjectsData; + +enum { + _PY_GETOBJECTS_IGNORE = 0, + _PY_GETOBJECTS_ERROR = 1, + _PY_GETOBJECTS_STOP = 2, +}; + +static int +_Py_GetObject(_Py_hashtable_t *ht, + const void *key, const void *value, + void *user_data) +{ + PyObject *op = (PyObject *)key; + _Py_GetObjectsData *data = user_data; + if (data->limit > 0) { + if (PyList_GET_SIZE(data->list) >= data->limit) { + return _PY_GETOBJECTS_STOP; + } + } + + if (op == data->self) { + return _PY_GETOBJECTS_IGNORE; + } + if (op == data->args) { + return _PY_GETOBJECTS_IGNORE; + } + if (op == data->list) { + return _PY_GETOBJECTS_IGNORE; + } + if (data->type != NULL) { + if (op == data->type) { + return _PY_GETOBJECTS_IGNORE; + } + if (!Py_IS_TYPE(op, (PyTypeObject *)data->type)) { + return _PY_GETOBJECTS_IGNORE; + } + } + + if (PyList_Append(data->list, op) < 0) { + return _PY_GETOBJECTS_ERROR; + } + return 0; } + /* The implementation of sys.getobjects(). */ PyObject * _Py_GetObjects(PyObject *self, PyObject *args) { - int i, n; - PyObject *t = NULL; - PyObject *res, *op; - PyInterpreterState *interp = _PyInterpreterState_GET(); + Py_ssize_t limit; + PyObject *type = NULL; + if (!PyArg_ParseTuple(args, "n|O", &limit, &type)) { + return NULL; + } - if (!PyArg_ParseTuple(args, "i|O", &n, &t)) + PyObject *list = PyList_New(0); + if (list == NULL) { return NULL; - PyObject *refchain = REFCHAIN(interp); - op = refchain->_ob_next; - res = PyList_New(0); - if (res == NULL) + } + + _Py_GetObjectsData data = { + .self = self, + .args = args, + .list = list, + .type = type, + .limit = limit, + }; + PyInterpreterState *interp = _PyInterpreterState_GET(); + int res = _Py_hashtable_foreach(REFCHAIN(interp), _Py_GetObject, &data); + if (res == _PY_GETOBJECTS_ERROR) { + Py_DECREF(list); return NULL; - for (i = 0; (n == 0 || i < n) && op != refchain; i++) { - while (op == self || op == args || op == res || op == t || - (t != NULL && !Py_IS_TYPE(op, (PyTypeObject *) t))) { - op = op->_ob_next; - if (op == refchain) - return res; - } - if (PyList_Append(res, op) < 0) { - Py_DECREF(res); - return NULL; - } - op = op->_ob_next; } - return res; + return list; } #undef REFCHAIN +#undef REFCHAIN_VALUE -#endif +#endif /* Py_TRACE_REFS */ /* Hack to force loading of abstract.o */ @@ -2702,6 +2940,10 @@ int Py_IsFalse(PyObject *x) return Py_Is(x, Py_False); } -#ifdef __cplusplus + +// Py_SET_REFCNT() implementation for stable ABI +void +_Py_SetRefcnt(PyObject *ob, Py_ssize_t refcnt) +{ + Py_SET_REFCNT(ob, refcnt); } -#endif diff --git a/Objects/object_layout.md b/Objects/object_layout.md index 4430790f4f0f36..3f7d72eb22f224 100644 --- a/Objects/object_layout.md +++ b/Objects/object_layout.md @@ -36,7 +36,7 @@ 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 +In 3.12 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: diff --git a/Objects/obmalloc.c b/Objects/obmalloc.c index 7d552ff57c8f1e..883adcb1c19b6e 100644 --- a/Objects/obmalloc.c +++ b/Objects/obmalloc.c @@ -10,6 +10,15 @@ #include // malloc() #include +#ifdef WITH_MIMALLOC +# include "pycore_mimalloc.h" +# include "mimalloc/static.c" +# include "mimalloc/internal.h" // for stats +#endif + +#if defined(Py_GIL_DISABLED) && !defined(WITH_MIMALLOC) +# error "Py_GIL_DISABLED requires WITH_MIMALLOC" +#endif #undef uint #define uint pymem_uint @@ -74,25 +83,131 @@ _PyMem_RawFree(void *Py_UNUSED(ctx), void *ptr) free(ptr); } +#ifdef WITH_MIMALLOC + +void * +_PyMem_MiMalloc(void *ctx, size_t size) +{ +#ifdef Py_GIL_DISABLED + _PyThreadStateImpl *tstate = (_PyThreadStateImpl *)_PyThreadState_GET(); + mi_heap_t *heap = &tstate->mimalloc.heaps[_Py_MIMALLOC_HEAP_MEM]; + return mi_heap_malloc(heap, size); +#else + return mi_malloc(size); +#endif +} + +void * +_PyMem_MiCalloc(void *ctx, size_t nelem, size_t elsize) +{ +#ifdef Py_GIL_DISABLED + _PyThreadStateImpl *tstate = (_PyThreadStateImpl *)_PyThreadState_GET(); + mi_heap_t *heap = &tstate->mimalloc.heaps[_Py_MIMALLOC_HEAP_MEM]; + return mi_heap_calloc(heap, nelem, elsize); +#else + return mi_calloc(nelem, elsize); +#endif +} + +void * +_PyMem_MiRealloc(void *ctx, void *ptr, size_t size) +{ +#ifdef Py_GIL_DISABLED + _PyThreadStateImpl *tstate = (_PyThreadStateImpl *)_PyThreadState_GET(); + mi_heap_t *heap = &tstate->mimalloc.heaps[_Py_MIMALLOC_HEAP_MEM]; + return mi_heap_realloc(heap, ptr, size); +#else + return mi_realloc(ptr, size); +#endif +} + +void +_PyMem_MiFree(void *ctx, void *ptr) +{ + mi_free(ptr); +} + +void * +_PyObject_MiMalloc(void *ctx, size_t nbytes) +{ +#ifdef Py_GIL_DISABLED + _PyThreadStateImpl *tstate = (_PyThreadStateImpl *)_PyThreadState_GET(); + mi_heap_t *heap = tstate->mimalloc.current_object_heap; + return mi_heap_malloc(heap, nbytes); +#else + return mi_malloc(nbytes); +#endif +} + +void * +_PyObject_MiCalloc(void *ctx, size_t nelem, size_t elsize) +{ +#ifdef Py_GIL_DISABLED + _PyThreadStateImpl *tstate = (_PyThreadStateImpl *)_PyThreadState_GET(); + mi_heap_t *heap = tstate->mimalloc.current_object_heap; + return mi_heap_calloc(heap, nelem, elsize); +#else + return mi_calloc(nelem, elsize); +#endif +} + + +void * +_PyObject_MiRealloc(void *ctx, void *ptr, size_t nbytes) +{ +#ifdef Py_GIL_DISABLED + _PyThreadStateImpl *tstate = (_PyThreadStateImpl *)_PyThreadState_GET(); + mi_heap_t *heap = tstate->mimalloc.current_object_heap; + return mi_heap_realloc(heap, ptr, nbytes); +#else + return mi_realloc(ptr, nbytes); +#endif +} + +void +_PyObject_MiFree(void *ctx, void *ptr) +{ + mi_free(ptr); +} + +#endif // WITH_MIMALLOC + + #define MALLOC_ALLOC {NULL, _PyMem_RawMalloc, _PyMem_RawCalloc, _PyMem_RawRealloc, _PyMem_RawFree} -#define PYRAW_ALLOC MALLOC_ALLOC -/* the default object allocator */ + +#ifdef WITH_MIMALLOC +# define MIMALLOC_ALLOC {NULL, _PyMem_MiMalloc, _PyMem_MiCalloc, _PyMem_MiRealloc, _PyMem_MiFree} +# define MIMALLOC_OBJALLOC {NULL, _PyObject_MiMalloc, _PyObject_MiCalloc, _PyObject_MiRealloc, _PyObject_MiFree} +#endif + +/* the pymalloc allocator */ // The actual implementation is further down. -#ifdef WITH_PYMALLOC +#if defined(WITH_PYMALLOC) void* _PyObject_Malloc(void *ctx, size_t size); void* _PyObject_Calloc(void *ctx, size_t nelem, size_t elsize); void _PyObject_Free(void *ctx, void *p); void* _PyObject_Realloc(void *ctx, void *ptr, size_t size); # define PYMALLOC_ALLOC {NULL, _PyObject_Malloc, _PyObject_Calloc, _PyObject_Realloc, _PyObject_Free} +#endif // WITH_PYMALLOC + +#if defined(Py_GIL_DISABLED) +// Py_GIL_DISABLED requires using mimalloc for "mem" and "obj" domains. +# define PYRAW_ALLOC MALLOC_ALLOC +# define PYMEM_ALLOC MIMALLOC_ALLOC +# define PYOBJ_ALLOC MIMALLOC_OBJALLOC +#elif defined(WITH_PYMALLOC) +# define PYRAW_ALLOC MALLOC_ALLOC +# define PYMEM_ALLOC PYMALLOC_ALLOC # define PYOBJ_ALLOC PYMALLOC_ALLOC #else +# define PYRAW_ALLOC MALLOC_ALLOC +# define PYMEM_ALLOC MALLOC_ALLOC # define PYOBJ_ALLOC MALLOC_ALLOC -#endif // WITH_PYMALLOC +#endif -#define PYMEM_ALLOC PYOBJ_ALLOC /* the default debug allocators */ @@ -259,13 +374,9 @@ int _PyMem_SetDefaultAllocator(PyMemAllocatorDomain domain, PyMemAllocatorEx *old_alloc) { - if (ALLOCATORS_MUTEX == NULL) { - /* The runtime must be initializing. */ - return set_default_allocator_unlocked(domain, pydebug, old_alloc); - } - PyThread_acquire_lock(ALLOCATORS_MUTEX, WAIT_LOCK); + PyMutex_Lock(&ALLOCATORS_MUTEX); int res = set_default_allocator_unlocked(domain, pydebug, old_alloc); - PyThread_release_lock(ALLOCATORS_MUTEX); + PyMutex_Unlock(&ALLOCATORS_MUTEX); return res; } @@ -284,7 +395,7 @@ _PyMem_GetAllocatorName(const char *name, PyMemAllocatorName *allocator) else if (strcmp(name, "debug") == 0) { *allocator = PYMEM_ALLOCATOR_DEBUG; } -#ifdef WITH_PYMALLOC +#if defined(WITH_PYMALLOC) && !defined(Py_GIL_DISABLED) else if (strcmp(name, "pymalloc") == 0) { *allocator = PYMEM_ALLOCATOR_PYMALLOC; } @@ -292,12 +403,22 @@ _PyMem_GetAllocatorName(const char *name, PyMemAllocatorName *allocator) *allocator = PYMEM_ALLOCATOR_PYMALLOC_DEBUG; } #endif +#ifdef WITH_MIMALLOC + else if (strcmp(name, "mimalloc") == 0) { + *allocator = PYMEM_ALLOCATOR_MIMALLOC; + } + else if (strcmp(name, "mimalloc_debug") == 0) { + *allocator = PYMEM_ALLOCATOR_MIMALLOC_DEBUG; + } +#endif +#ifndef Py_GIL_DISABLED else if (strcmp(name, "malloc") == 0) { *allocator = PYMEM_ALLOCATOR_MALLOC; } else if (strcmp(name, "malloc_debug") == 0) { *allocator = PYMEM_ALLOCATOR_MALLOC_DEBUG; } +#endif else { /* unknown allocator */ return -1; @@ -343,6 +464,26 @@ set_up_allocators_unlocked(PyMemAllocatorName allocator) break; } #endif +#ifdef WITH_MIMALLOC + case PYMEM_ALLOCATOR_MIMALLOC: + case PYMEM_ALLOCATOR_MIMALLOC_DEBUG: + { + PyMemAllocatorEx malloc_alloc = MALLOC_ALLOC; + set_allocator_unlocked(PYMEM_DOMAIN_RAW, &malloc_alloc); + + PyMemAllocatorEx pymalloc = MIMALLOC_ALLOC; + set_allocator_unlocked(PYMEM_DOMAIN_MEM, &pymalloc); + + PyMemAllocatorEx objmalloc = MIMALLOC_OBJALLOC; + set_allocator_unlocked(PYMEM_DOMAIN_OBJ, &objmalloc); + + if (allocator == PYMEM_ALLOCATOR_MIMALLOC_DEBUG) { + set_up_debug_hooks_unlocked(); + } + + break; + } +#endif case PYMEM_ALLOCATOR_MALLOC: case PYMEM_ALLOCATOR_MALLOC_DEBUG: @@ -369,9 +510,9 @@ set_up_allocators_unlocked(PyMemAllocatorName allocator) int _PyMem_SetupAllocators(PyMemAllocatorName allocator) { - PyThread_acquire_lock(ALLOCATORS_MUTEX, WAIT_LOCK); + PyMutex_Lock(&ALLOCATORS_MUTEX); int res = set_up_allocators_unlocked(allocator); - PyThread_release_lock(ALLOCATORS_MUTEX); + PyMutex_Unlock(&ALLOCATORS_MUTEX); return res; } @@ -390,6 +531,10 @@ get_current_allocator_name_unlocked(void) #ifdef WITH_PYMALLOC PyMemAllocatorEx pymalloc = PYMALLOC_ALLOC; #endif +#ifdef WITH_MIMALLOC + PyMemAllocatorEx mimalloc = MIMALLOC_ALLOC; + PyMemAllocatorEx mimalloc_obj = MIMALLOC_OBJALLOC; +#endif if (pymemallocator_eq(&_PyMem_Raw, &malloc_alloc) && pymemallocator_eq(&_PyMem, &malloc_alloc) && @@ -405,6 +550,14 @@ get_current_allocator_name_unlocked(void) return "pymalloc"; } #endif +#ifdef WITH_MIMALLOC + if (pymemallocator_eq(&_PyMem_Raw, &malloc_alloc) && + pymemallocator_eq(&_PyMem, &mimalloc) && + pymemallocator_eq(&_PyObject, &mimalloc_obj)) + { + return "mimalloc"; + } +#endif PyMemAllocatorEx dbg_raw = PYDBGRAW_ALLOC; PyMemAllocatorEx dbg_mem = PYDBGMEM_ALLOC; @@ -428,6 +581,14 @@ get_current_allocator_name_unlocked(void) { return "pymalloc_debug"; } +#endif +#ifdef WITH_MIMALLOC + if (pymemallocator_eq(&_PyMem_Debug.raw.alloc, &malloc_alloc) && + pymemallocator_eq(&_PyMem_Debug.mem.alloc, &mimalloc) && + pymemallocator_eq(&_PyMem_Debug.obj.alloc, &mimalloc_obj)) + { + return "mimalloc_debug"; + } #endif } return NULL; @@ -436,9 +597,9 @@ get_current_allocator_name_unlocked(void) const char* _PyMem_GetCurrentAllocatorName(void) { - PyThread_acquire_lock(ALLOCATORS_MUTEX, WAIT_LOCK); + PyMutex_Lock(&ALLOCATORS_MUTEX); const char *name = get_current_allocator_name_unlocked(); - PyThread_release_lock(ALLOCATORS_MUTEX); + PyMutex_Unlock(&ALLOCATORS_MUTEX); return name; } @@ -460,7 +621,21 @@ _PyMem_PymallocEnabled(void) return (_PyObject.malloc == _PyObject_Malloc); } } -#endif + +#ifdef WITH_MIMALLOC +static int +_PyMem_MimallocEnabled(void) +{ + if (_PyMem_DebugEnabled()) { + return (_PyMem_Debug.obj.alloc.malloc == _PyObject_MiMalloc); + } + else { + return (_PyObject.malloc == _PyObject_MiMalloc); + } +} +#endif // WITH_MIMALLOC + +#endif // WITH_PYMALLOC static void @@ -521,14 +696,9 @@ set_up_debug_hooks_unlocked(void) void PyMem_SetupDebugHooks(void) { - if (ALLOCATORS_MUTEX == NULL) { - /* The runtime must not be completely initialized yet. */ - set_up_debug_hooks_unlocked(); - return; - } - PyThread_acquire_lock(ALLOCATORS_MUTEX, WAIT_LOCK); + PyMutex_Lock(&ALLOCATORS_MUTEX); set_up_debug_hooks_unlocked(); - PyThread_release_lock(ALLOCATORS_MUTEX); + PyMutex_Unlock(&ALLOCATORS_MUTEX); } static void @@ -564,53 +734,33 @@ set_allocator_unlocked(PyMemAllocatorDomain domain, PyMemAllocatorEx *allocator) void PyMem_GetAllocator(PyMemAllocatorDomain domain, PyMemAllocatorEx *allocator) { - if (ALLOCATORS_MUTEX == NULL) { - /* The runtime must not be completely initialized yet. */ - get_allocator_unlocked(domain, allocator); - return; - } - PyThread_acquire_lock(ALLOCATORS_MUTEX, WAIT_LOCK); + PyMutex_Lock(&ALLOCATORS_MUTEX); get_allocator_unlocked(domain, allocator); - PyThread_release_lock(ALLOCATORS_MUTEX); + PyMutex_Unlock(&ALLOCATORS_MUTEX); } void PyMem_SetAllocator(PyMemAllocatorDomain domain, PyMemAllocatorEx *allocator) { - if (ALLOCATORS_MUTEX == NULL) { - /* The runtime must not be completely initialized yet. */ - set_allocator_unlocked(domain, allocator); - return; - } - PyThread_acquire_lock(ALLOCATORS_MUTEX, WAIT_LOCK); + PyMutex_Lock(&ALLOCATORS_MUTEX); set_allocator_unlocked(domain, allocator); - PyThread_release_lock(ALLOCATORS_MUTEX); + PyMutex_Unlock(&ALLOCATORS_MUTEX); } void PyObject_GetArenaAllocator(PyObjectArenaAllocator *allocator) { - if (ALLOCATORS_MUTEX == NULL) { - /* The runtime must not be completely initialized yet. */ - *allocator = _PyObject_Arena; - return; - } - PyThread_acquire_lock(ALLOCATORS_MUTEX, WAIT_LOCK); + PyMutex_Lock(&ALLOCATORS_MUTEX); *allocator = _PyObject_Arena; - PyThread_release_lock(ALLOCATORS_MUTEX); + PyMutex_Unlock(&ALLOCATORS_MUTEX); } void PyObject_SetArenaAllocator(PyObjectArenaAllocator *allocator) { - if (ALLOCATORS_MUTEX == NULL) { - /* The runtime must not be completely initialized yet. */ - _PyObject_Arena = *allocator; - return; - } - PyThread_acquire_lock(ALLOCATORS_MUTEX, WAIT_LOCK); + PyMutex_Lock(&ALLOCATORS_MUTEX); _PyObject_Arena = *allocator; - PyThread_release_lock(ALLOCATORS_MUTEX); + PyMutex_Unlock(&ALLOCATORS_MUTEX); } @@ -883,9 +1033,31 @@ get_state(void) #define narenas_highwater (state->mgmt.narenas_highwater) #define raw_allocated_blocks (state->mgmt.raw_allocated_blocks) +#ifdef WITH_MIMALLOC +static bool count_blocks( + const mi_heap_t* heap, const mi_heap_area_t* area, + void* block, size_t block_size, void* allocated_blocks) +{ + *(size_t *)allocated_blocks += area->used; + return 1; +} +#endif + Py_ssize_t _PyInterpreterState_GetAllocatedBlocks(PyInterpreterState *interp) { +#ifdef WITH_MIMALLOC + // TODO(sgross): this only counts the current thread's blocks. + if (_PyMem_MimallocEnabled()) { + size_t allocated_blocks = 0; + + mi_heap_t *heap = mi_heap_get_default(); + mi_heap_visit_blocks(heap, false, &count_blocks, &allocated_blocks); + + return allocated_blocks; + } +#endif + #ifdef Py_DEBUG assert(has_own_state(interp)); #else @@ -919,6 +1091,11 @@ _PyInterpreterState_GetAllocatedBlocks(PyInterpreterState *interp) void _PyInterpreterState_FinalizeAllocatedBlocks(PyInterpreterState *interp) { +#ifdef WITH_MIMALLOC + if (_PyMem_MimallocEnabled()) { + return; + } +#endif if (has_own_state(interp)) { Py_ssize_t leaked = _PyInterpreterState_GetAllocatedBlocks(interp); assert(has_own_state(interp) || leaked == 0); @@ -944,6 +1121,16 @@ _Py_FinalizeAllocatedBlocks(_PyRuntimeState *runtime) static Py_ssize_t get_num_global_allocated_blocks(_PyRuntimeState *runtime) { +#ifdef WITH_MIMALLOC + if (_PyMem_MimallocEnabled()) { + size_t allocated_blocks = 0; + + mi_heap_t *heap = mi_heap_get_default(); + mi_heap_visit_blocks(heap, false, &count_blocks, &allocated_blocks); + + return allocated_blocks; + } +#endif Py_ssize_t total = 0; if (_PyRuntimeState_GetFinalizing(runtime) != NULL) { PyInterpreterState *interp = _PyInterpreterState_Main(); @@ -2536,19 +2723,55 @@ pool_is_in_list(const poolp target, poolp list) } #endif -/* Print summary info to "out" about the state of pymalloc's structures. - * In Py_DEBUG mode, also perform some expensive internal consistency - * checks. - * - * Return 0 if the memory debug hooks are not installed or no statistics was - * written into out, return 1 otherwise. - */ -int -_PyObject_DebugMallocStats(FILE *out) +#ifdef WITH_MIMALLOC +struct _alloc_stats { + size_t allocated_blocks; + size_t allocated_bytes; + size_t allocated_with_overhead; + size_t bytes_reserved; + size_t bytes_committed; +}; + +static bool _collect_alloc_stats( + const mi_heap_t* heap, const mi_heap_area_t* area, + void* block, size_t block_size, void* arg) +{ + struct _alloc_stats *stats = (struct _alloc_stats *)arg; + stats->allocated_blocks += area->used; + stats->allocated_bytes += area->used * area->block_size; + stats->allocated_with_overhead += area->used * area->full_block_size; + stats->bytes_reserved += area->reserved; + stats->bytes_committed += area->committed; + return 1; +} + +static void +py_mimalloc_print_stats(FILE *out) +{ + fprintf(out, "Small block threshold = %zd, in %u size classes.\n", + MI_SMALL_OBJ_SIZE_MAX, MI_BIN_HUGE); + fprintf(out, "Medium block threshold = %zd\n", + MI_MEDIUM_OBJ_SIZE_MAX); + fprintf(out, "Large object max size = %zd\n", + MI_LARGE_OBJ_SIZE_MAX); + + mi_heap_t *heap = mi_heap_get_default(); + struct _alloc_stats stats; + memset(&stats, 0, sizeof(stats)); + mi_heap_visit_blocks(heap, false, &_collect_alloc_stats, &stats); + + fprintf(out, " Allocated Blocks: %zd\n", stats.allocated_blocks); + fprintf(out, " Allocated Bytes: %zd\n", stats.allocated_bytes); + fprintf(out, " Allocated Bytes w/ Overhead: %zd\n", stats.allocated_with_overhead); + fprintf(out, " Bytes Reserved: %zd\n", stats.bytes_reserved); + fprintf(out, " Bytes Committed: %zd\n", stats.bytes_committed); +} +#endif + + +static void +pymalloc_print_stats(FILE *out) { - if (!_PyMem_PymallocEnabled()) { - return 0; - } OMState *state = get_state(); uint i; @@ -2701,7 +2924,32 @@ _PyObject_DebugMallocStats(FILE *out) #endif #endif - return 1; +} + +/* Print summary info to "out" about the state of pymalloc's structures. + * In Py_DEBUG mode, also perform some expensive internal consistency + * checks. + * + * Return 0 if the memory debug hooks are not installed or no statistics was + * written into out, return 1 otherwise. + */ +int +_PyObject_DebugMallocStats(FILE *out) +{ +#ifdef WITH_MIMALLOC + if (_PyMem_MimallocEnabled()) { + py_mimalloc_print_stats(out); + return 1; + } + else +#endif + if (_PyMem_PymallocEnabled()) { + pymalloc_print_stats(out); + return 1; + } + else { + return 0; + } } #endif /* #ifdef WITH_PYMALLOC */ diff --git a/Objects/odictobject.c b/Objects/odictobject.c index e76d2ded61cf74..b5280c39e1be54 100644 --- a/Objects/odictobject.c +++ b/Objects/odictobject.c @@ -466,8 +466,10 @@ Potential Optimizations #include "Python.h" #include "pycore_call.h" // _PyObject_CallNoArgs() -#include "pycore_object.h" // _PyObject_GC_UNTRACK() +#include "pycore_ceval.h" // _PyEval_GetBuiltin() #include "pycore_dict.h" // _Py_dict_lookup() +#include "pycore_object.h" // _PyObject_GC_UNTRACK() +#include "pycore_pyerrors.h" // _PyErr_ChainExceptions1() #include // offsetof() #include "clinic/odictobject.c.h" @@ -1047,7 +1049,10 @@ _odict_popkey_hash(PyObject *od, PyObject *key, PyObject *failobj, return NULL; } /* Now delete the value from the dict. */ - value = _PyDict_Pop_KnownHash(od, key, hash, failobj); + if (_PyDict_Pop_KnownHash((PyDictObject *)od, key, hash, + &value) == 0) { + value = Py_NewRef(failobj); + } } else if (value == NULL && !PyErr_Occurred()) { /* Apply the fallback value, if necessary. */ diff --git a/Objects/rangeobject.c b/Objects/rangeobject.c index 6e06bef95032cf..ce9eef69ad75a8 100644 --- a/Objects/rangeobject.c +++ b/Objects/rangeobject.c @@ -2,6 +2,7 @@ #include "Python.h" #include "pycore_abstract.h" // _PyIndex_Check() +#include "pycore_ceval.h" // _PyEval_GetBuiltin() #include "pycore_long.h" // _PyLong_GetZero() #include "pycore_modsupport.h" // _PyArg_NoKwnames() #include "pycore_range.h" diff --git a/Objects/setobject.c b/Objects/setobject.c index c96b62e38ec27e..88d20019bfb4a7 100644 --- a/Objects/setobject.c +++ b/Objects/setobject.c @@ -32,9 +32,11 @@ */ #include "Python.h" +#include "pycore_ceval.h" // _PyEval_GetBuiltin() #include "pycore_dict.h" // _PyDict_Contains_KnownHash() #include "pycore_modsupport.h" // _PyArg_NoKwnames() #include "pycore_object.h" // _PyObject_GC_UNTRACK() +#include "pycore_pyerrors.h" // _PyErr_SetKeyError() #include "pycore_setobject.h" // _PySet_NextEntry() definition #include // offsetof() @@ -940,7 +942,10 @@ set_update(PySetObject *so, PyObject *args) } PyDoc_STRVAR(update_doc, -"Update a set with the union of itself and others."); +"update($self, /, *others)\n\ +--\n\ +\n\ +Update the set, adding elements from all others."); /* XXX Todo: If aligned memory allocations become available, make the @@ -1139,9 +1144,10 @@ set_union(PySetObject *so, PyObject *args) } PyDoc_STRVAR(union_doc, - "Return the union of sets as a new set.\n\ +"union($self, /, *others)\n\ +--\n\ \n\ -(i.e. all elements that are in either set.)"); +Return a new set with elements from the set and all others."); static PyObject * set_or(PySetObject *so, PyObject *other) @@ -1279,9 +1285,10 @@ set_intersection_multi(PySetObject *so, PyObject *args) } PyDoc_STRVAR(intersection_doc, -"Return the intersection of two sets as a new set.\n\ +"intersection($self, /, *others)\n\ +--\n\ \n\ -(i.e. all elements that are in both sets.)"); +Return a new set with elements common to the set and all others."); static PyObject * set_intersection_update(PySetObject *so, PyObject *other) @@ -1310,7 +1317,10 @@ set_intersection_update_multi(PySetObject *so, PyObject *args) } PyDoc_STRVAR(intersection_update_doc, -"Update a set with the intersection of itself and another."); +"intersection_update($self, /, *others)\n\ +--\n\ +\n\ +Update the set, keeping only elements found in it and all others."); static PyObject * set_and(PySetObject *so, PyObject *other) @@ -1468,7 +1478,10 @@ set_difference_update(PySetObject *so, PyObject *args) } PyDoc_STRVAR(difference_update_doc, -"Remove all elements of another set from this set."); +"difference_update($self, /, *others)\n\ +--\n\ +\n\ +Update the set, removing elements found in others."); static PyObject * set_copy_and_difference(PySetObject *so, PyObject *other) @@ -1585,9 +1598,10 @@ set_difference_multi(PySetObject *so, PyObject *args) } PyDoc_STRVAR(difference_doc, -"Return the difference of two or more sets as a new set.\n\ +"difference($self, /, *others)\n\ +--\n\ \n\ -(i.e. all elements that are in this set but not the others.)"); +Return a new set with elements in the set that are not in the others."); static PyObject * set_sub(PySetObject *so, PyObject *other) { @@ -1671,7 +1685,10 @@ set_symmetric_difference_update(PySetObject *so, PyObject *other) } PyDoc_STRVAR(symmetric_difference_update_doc, -"Update a set with the symmetric difference of itself and another."); +"symmetric_difference_update($self, other, /)\n\ +--\n\ +\n\ +Update the set, keeping only elements found in either set, but not in both."); static PyObject * set_symmetric_difference(PySetObject *so, PyObject *other) @@ -1692,9 +1709,10 @@ set_symmetric_difference(PySetObject *so, PyObject *other) } PyDoc_STRVAR(symmetric_difference_doc, -"Return the symmetric difference of two sets as a new set.\n\ +"symmetric_difference($self, other, /)\n\ +--\n\ \n\ -(i.e. all elements that are in exactly one of the sets.)"); +Return a new set with elements in either the set or other but not both."); static PyObject * set_xor(PySetObject *so, PyObject *other) @@ -2020,13 +2038,6 @@ static PySequenceMethods set_as_sequence = { /* set object ********************************************************/ -#ifdef Py_DEBUG -static PyObject *test_c_api(PySetObject *so, PyObject *Py_UNUSED(ignored)); - -PyDoc_STRVAR(test_c_api_doc, "Exercises C API. Returns True.\n\ -All is well if assertions don't fail."); -#endif - static PyMethodDef set_methods[] = { {"add", (PyCFunction)set_add, METH_O, add_doc}, @@ -2064,10 +2075,6 @@ static PyMethodDef set_methods[] = { symmetric_difference_doc}, {"symmetric_difference_update",(PyCFunction)set_symmetric_difference_update, METH_O, symmetric_difference_update_doc}, -#ifdef Py_DEBUG - {"test_c_api", (PyCFunction)test_c_api, METH_NOARGS, - test_c_api_doc}, -#endif {"union", (PyCFunction)set_union, METH_VARARGS, union_doc}, {"update", (PyCFunction)set_update, METH_VARARGS, @@ -2109,8 +2116,8 @@ static PyNumberMethods set_as_number = { }; PyDoc_STRVAR(set_doc, -"set() -> new empty set object\n\ -set(iterable) -> new set object\n\ +"set(iterable=(), /)\n\ +--\n\ \n\ Build an unordered collection of unique elements."); @@ -2210,8 +2217,8 @@ static PyNumberMethods frozenset_as_number = { }; PyDoc_STRVAR(frozenset_doc, -"frozenset() -> empty frozenset object\n\ -frozenset(iterable) -> frozenset object\n\ +"frozenset(iterable=(), /)\n\ +--\n\ \n\ Build an immutable unordered collection of unique elements."); @@ -2366,148 +2373,6 @@ _PySet_Update(PyObject *set, PyObject *iterable) /* Exported for the gdb plugin's benefit. */ PyObject *_PySet_Dummy = dummy; -#ifdef Py_DEBUG - -/* Test code to be called with any three element set. - Returns True and original set is restored. */ - -#define assertRaises(call_return_value, exception) \ - do { \ - assert(call_return_value); \ - assert(PyErr_ExceptionMatches(exception)); \ - PyErr_Clear(); \ - } while(0) - -static PyObject * -test_c_api(PySetObject *so, PyObject *Py_UNUSED(ignored)) -{ - Py_ssize_t count; - const char *s; - Py_ssize_t i; - PyObject *elem=NULL, *dup=NULL, *t, *f, *dup2, *x=NULL; - PyObject *ob = (PyObject *)so; - Py_hash_t hash; - PyObject *str; - - /* Verify preconditions */ - assert(PyAnySet_Check(ob)); - assert(PyAnySet_CheckExact(ob)); - assert(!PyFrozenSet_CheckExact(ob)); - - /* so.clear(); so |= set("abc"); */ - str = PyUnicode_FromString("abc"); - if (str == NULL) - return NULL; - set_clear_internal(so); - if (set_update_internal(so, str)) { - Py_DECREF(str); - return NULL; - } - Py_DECREF(str); - - /* Exercise type/size checks */ - assert(PySet_Size(ob) == 3); - assert(PySet_GET_SIZE(ob) == 3); - - /* Raise TypeError for non-iterable constructor arguments */ - assertRaises(PySet_New(Py_None) == NULL, PyExc_TypeError); - assertRaises(PyFrozenSet_New(Py_None) == NULL, PyExc_TypeError); - - /* Raise TypeError for unhashable key */ - dup = PySet_New(ob); - assertRaises(PySet_Discard(ob, dup) == -1, PyExc_TypeError); - assertRaises(PySet_Contains(ob, dup) == -1, PyExc_TypeError); - assertRaises(PySet_Add(ob, dup) == -1, PyExc_TypeError); - - /* Exercise successful pop, contains, add, and discard */ - elem = PySet_Pop(ob); - assert(PySet_Contains(ob, elem) == 0); - assert(PySet_GET_SIZE(ob) == 2); - assert(PySet_Add(ob, elem) == 0); - assert(PySet_Contains(ob, elem) == 1); - assert(PySet_GET_SIZE(ob) == 3); - assert(PySet_Discard(ob, elem) == 1); - assert(PySet_GET_SIZE(ob) == 2); - assert(PySet_Discard(ob, elem) == 0); - assert(PySet_GET_SIZE(ob) == 2); - - /* Exercise clear */ - dup2 = PySet_New(dup); - assert(PySet_Clear(dup2) == 0); - assert(PySet_Size(dup2) == 0); - Py_DECREF(dup2); - - /* Raise SystemError on clear or update of frozen set */ - f = PyFrozenSet_New(dup); - assertRaises(PySet_Clear(f) == -1, PyExc_SystemError); - assertRaises(_PySet_Update(f, dup) == -1, PyExc_SystemError); - assert(PySet_Add(f, elem) == 0); - Py_INCREF(f); - assertRaises(PySet_Add(f, elem) == -1, PyExc_SystemError); - Py_DECREF(f); - Py_DECREF(f); - - /* Exercise direct iteration */ - i = 0, count = 0; - while (_PySet_NextEntry((PyObject *)dup, &i, &x, &hash)) { - s = PyUnicode_AsUTF8(x); - assert(s && (s[0] == 'a' || s[0] == 'b' || s[0] == 'c')); - count++; - } - assert(count == 3); - - /* Exercise updates */ - dup2 = PySet_New(NULL); - assert(_PySet_Update(dup2, dup) == 0); - assert(PySet_Size(dup2) == 3); - assert(_PySet_Update(dup2, dup) == 0); - assert(PySet_Size(dup2) == 3); - Py_DECREF(dup2); - - /* Raise SystemError when self argument is not a set or frozenset. */ - t = PyTuple_New(0); - assertRaises(PySet_Size(t) == -1, PyExc_SystemError); - assertRaises(PySet_Contains(t, elem) == -1, PyExc_SystemError); - Py_DECREF(t); - - /* Raise SystemError when self argument is not a set. */ - f = PyFrozenSet_New(dup); - assert(PySet_Size(f) == 3); - assert(PyFrozenSet_CheckExact(f)); - assertRaises(PySet_Discard(f, elem) == -1, PyExc_SystemError); - assertRaises(PySet_Pop(f) == NULL, PyExc_SystemError); - Py_DECREF(f); - - /* Raise KeyError when popping from an empty set */ - assert(PyNumber_InPlaceSubtract(ob, ob) == ob); - Py_DECREF(ob); - assert(PySet_GET_SIZE(ob) == 0); - assertRaises(PySet_Pop(ob) == NULL, PyExc_KeyError); - - /* Restore the set from the copy using the PyNumber API */ - assert(PyNumber_InPlaceOr(ob, dup) == ob); - Py_DECREF(ob); - - /* Verify constructors accept NULL arguments */ - f = PySet_New(NULL); - assert(f != NULL); - assert(PySet_GET_SIZE(f) == 0); - Py_DECREF(f); - f = PyFrozenSet_New(NULL); - assert(f != NULL); - assert(PyFrozenSet_CheckExact(f)); - assert(PySet_GET_SIZE(f) == 0); - Py_DECREF(f); - - Py_DECREF(elem); - Py_DECREF(dup); - Py_RETURN_TRUE; -} - -#undef assertRaises - -#endif - /***** Dummy Struct *************************************************/ static PyObject * @@ -2545,8 +2410,4 @@ static PyTypeObject _PySetDummy_Type = { Py_TPFLAGS_DEFAULT, /*tp_flags */ }; -static PyObject _dummy_struct = { - _PyObject_EXTRA_INIT - { _Py_IMMORTAL_REFCNT }, - &_PySetDummy_Type -}; +static PyObject _dummy_struct = _PyObject_HEAD_INIT(&_PySetDummy_Type); diff --git a/Objects/sliceobject.c b/Objects/sliceobject.c index 8cf654fb6f812d..a3ed0c096d84ed 100644 --- a/Objects/sliceobject.c +++ b/Objects/sliceobject.c @@ -16,6 +16,7 @@ this type and there is exactly one in existence. #include "Python.h" #include "pycore_abstract.h" // _PyIndex_Check() #include "pycore_long.h" // _PyLong_GetZero() +#include "pycore_modsupport.h" // _PyArg_NoKeywords() #include "pycore_object.h" // _PyObject_GC_TRACK() @@ -97,11 +98,7 @@ PyTypeObject PyEllipsis_Type = { ellipsis_new, /* tp_new */ }; -PyObject _Py_EllipsisObject = { - _PyObject_EXTRA_INIT - { _Py_IMMORTAL_REFCNT }, - &PyEllipsis_Type -}; +PyObject _Py_EllipsisObject = _PyObject_HEAD_INIT(&PyEllipsis_Type); /* Slice object implementation */ diff --git a/Objects/stringlib/clinic/transmogrify.h.h b/Objects/stringlib/clinic/transmogrify.h.h index 49388cf043ced2..3a985ab5c7a9f5 100644 --- a/Objects/stringlib/clinic/transmogrify.h.h +++ b/Objects/stringlib/clinic/transmogrify.h.h @@ -3,10 +3,11 @@ 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() +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() #endif - +#include "pycore_abstract.h" // _PyNumber_Index() +#include "pycore_modsupport.h" // _PyArg_UnpackKeywords() PyDoc_STRVAR(stringlib_expandtabs__doc__, "expandtabs($self, /, tabsize=8)\n" @@ -62,7 +63,7 @@ stringlib_expandtabs(PyObject *self, PyObject *const *args, Py_ssize_t nargs, Py if (!noptargs) { goto skip_optional_pos; } - tabsize = _PyLong_AsInt(args[0]); + tabsize = PyLong_AsInt(args[0]); if (tabsize == -1 && PyErr_Occurred()) { goto exit; } @@ -278,4 +279,4 @@ stringlib_zfill(PyObject *self, PyObject *arg) exit: return return_value; } -/*[clinic end generated code: output=d44a269805f6739e input=a9049054013a1b77]*/ +/*[clinic end generated code: output=b409bdf9ab68d5a6 input=a9049054013a1b77]*/ diff --git a/Objects/structseq.c b/Objects/structseq.c index 700f67c09c9e57..581d6ad240885a 100644 --- a/Objects/structseq.c +++ b/Objects/structseq.c @@ -8,11 +8,11 @@ */ #include "Python.h" -#include "pycore_tuple.h" // _PyTuple_FromArray() +#include "pycore_initconfig.h" // _PyStatus_OK() +#include "pycore_modsupport.h" // _PyArg_NoPositional() #include "pycore_object.h" // _PyObject_GC_TRACK() - #include "pycore_structseq.h" // PyStructSequence_InitType() -#include "pycore_initconfig.h" // _PyStatus_OK() +#include "pycore_tuple.h" // _PyTuple_FromArray() static const char visible_length_key[] = "n_sequence_fields"; static const char real_length_key[] = "n_fields"; @@ -148,7 +148,6 @@ static PyObject * structseq_new_impl(PyTypeObject *type, PyObject *arg, PyObject *dict) /*[clinic end generated code: output=baa082e788b171da input=90532511101aa3fb]*/ { - PyObject *ob; PyStructSequence *res = NULL; Py_ssize_t len, min_len, max_len, i, n_unnamed_fields; @@ -217,22 +216,34 @@ structseq_new_impl(PyTypeObject *type, PyObject *arg, PyObject *dict) res->ob_item[i] = Py_NewRef(v); } Py_DECREF(arg); - for (; i < max_len; ++i) { - if (dict == NULL) { - ob = Py_None; - } - else { - ob = _PyDict_GetItemStringWithError(dict, - type->tp_members[i-n_unnamed_fields].name); + if (dict != NULL && PyDict_GET_SIZE(dict) > 0) { + Py_ssize_t n_found_keys = 0; + for (i = len; i < max_len; ++i) { + PyObject *ob = NULL; + const char *name = type->tp_members[i - n_unnamed_fields].name; + if (PyDict_GetItemStringRef(dict, name, &ob) < 0) { + Py_DECREF(res); + return NULL; + } if (ob == NULL) { - if (PyErr_Occurred()) { - Py_DECREF(res); - return NULL; - } - ob = Py_None; + ob = Py_NewRef(Py_None); } + else { + ++n_found_keys; + } + res->ob_item[i] = ob; + } + if (PyDict_GET_SIZE(dict) > n_found_keys) { + PyErr_Format(PyExc_TypeError, + "%.500s() got duplicate or unexpected field name(s)", + type->tp_name); + Py_DECREF(res); + return NULL; + } + } else { + for (i = len; i < max_len; ++i) { + res->ob_item[i] = Py_NewRef(Py_None); } - res->ob_item[i] = Py_NewRef(ob); } _PyObject_GC_TRACK(res); @@ -369,9 +380,81 @@ structseq_reduce(PyStructSequence* self, PyObject *Py_UNUSED(ignored)) return NULL; } + +static PyObject * +structseq_replace(PyStructSequence *self, PyObject *args, PyObject *kwargs) +{ + PyStructSequence *result = NULL; + Py_ssize_t n_fields, n_unnamed_fields, i; + + if (!_PyArg_NoPositional("__replace__", args)) { + return NULL; + } + + n_fields = REAL_SIZE(self); + if (n_fields < 0) { + return NULL; + } + n_unnamed_fields = UNNAMED_FIELDS(self); + if (n_unnamed_fields < 0) { + return NULL; + } + if (n_unnamed_fields > 0) { + PyErr_Format(PyExc_TypeError, + "__replace__() is not supported for %.500s " + "because it has unnamed field(s)", + Py_TYPE(self)->tp_name); + return NULL; + } + + result = (PyStructSequence *) PyStructSequence_New(Py_TYPE(self)); + if (!result) { + return NULL; + } + + if (kwargs != NULL) { + // We do not support types with unnamed fields, so we can iterate over + // i >= n_visible_fields case without slicing with (i - n_unnamed_fields). + for (i = 0; i < n_fields; ++i) { + PyObject *ob; + if (PyDict_PopString(kwargs, Py_TYPE(self)->tp_members[i].name, + &ob) < 0) { + goto error; + } + if (ob == NULL) { + ob = Py_NewRef(self->ob_item[i]); + } + result->ob_item[i] = ob; + } + // Check if there are any unexpected fields. + if (PyDict_GET_SIZE(kwargs) > 0) { + PyObject *names = PyDict_Keys(kwargs); + if (names) { + PyErr_Format(PyExc_TypeError, "Got unexpected field name(s): %R", names); + Py_DECREF(names); + } + goto error; + } + } + else + { + // Just create a copy of the original. + for (i = 0; i < n_fields; ++i) { + result->ob_item[i] = Py_NewRef(self->ob_item[i]); + } + } + + return (PyObject *)result; + +error: + Py_DECREF(result); + return NULL; +} + static PyMethodDef structseq_methods[] = { {"__reduce__", (PyCFunction)structseq_reduce, METH_NOARGS, NULL}, - {NULL, NULL} + {"__replace__", _PyCFunction_CAST(structseq_replace), METH_VARARGS | METH_KEYWORDS, NULL}, + {NULL, NULL} // sentinel }; static Py_ssize_t @@ -577,9 +660,10 @@ PyStructSequence_InitType2(PyTypeObject *type, PyStructSequence_Desc *desc) Py_ssize_t n_members, n_unnamed_members; #ifdef Py_TRACE_REFS - /* if the type object was chained, unchain it first + /* if the type object was traced, remove it first before overwriting its storage */ - if (type->ob_base.ob_base._ob_next) { + PyInterpreterState *interp = _PyInterpreterState_GET(); + if (_PyRefchain_IsTraced(interp, (PyObject *)type)) { _Py_ForgetReference((PyObject *)type); } #endif diff --git a/Objects/tupleobject.c b/Objects/tupleobject.c index b669a3dd8525eb..e1b8e4004c6163 100644 --- a/Objects/tupleobject.c +++ b/Objects/tupleobject.c @@ -3,6 +3,7 @@ #include "Python.h" #include "pycore_abstract.h" // _PyIndex_Check() +#include "pycore_ceval.h" // _PyEval_GetBuiltin() #include "pycore_gc.h" // _PyObject_GC_IS_TRACKED() #include "pycore_initconfig.h" // _PyStatus_OK() #include "pycore_modsupport.h" // _PyArg_NoKwnames() @@ -961,18 +962,18 @@ _PyTuple_Resize(PyObject **pv, Py_ssize_t newsize) } -static void maybe_freelist_clear(PyInterpreterState *, int); +static void maybe_freelist_clear(_PyFreeListState *, int); void -_PyTuple_Fini(PyInterpreterState *interp) +_PyTuple_Fini(_PyFreeListState *state) { - maybe_freelist_clear(interp, 1); + maybe_freelist_clear(state, 1); } void -_PyTuple_ClearFreeList(PyInterpreterState *interp) +_PyTuple_ClearFreeList(_PyFreeListState *state, int is_finalization) { - maybe_freelist_clear(interp, 0); + maybe_freelist_clear(state, is_finalization); } /*********************** Tuple Iterator **************************/ @@ -1124,18 +1125,14 @@ tuple_iter(PyObject *seq) * freelists * *************/ -#define STATE (interp->tuple) +#define STATE (state->tuple_state) #define FREELIST_FINALIZED (STATE.numfree[0] < 0) static inline PyTupleObject * maybe_freelist_pop(Py_ssize_t size) { -#if PyTuple_NFREELISTS > 0 - PyInterpreterState *interp = _PyInterpreterState_GET(); -#ifdef Py_DEBUG - /* maybe_freelist_pop() must not be called after maybe_freelist_fini(). */ - assert(!FREELIST_FINALIZED); -#endif +#ifdef WITH_FREELISTS + _PyFreeListState *state = _PyFreeListState_GET(); if (size == 0) { return NULL; } @@ -1168,18 +1165,15 @@ maybe_freelist_pop(Py_ssize_t size) static inline int maybe_freelist_push(PyTupleObject *op) { -#if PyTuple_NFREELISTS > 0 - PyInterpreterState *interp = _PyInterpreterState_GET(); -#ifdef Py_DEBUG - /* maybe_freelist_push() must not be called after maybe_freelist_fini(). */ - assert(!FREELIST_FINALIZED); -#endif +#ifdef WITH_FREELISTS + _PyFreeListState *state = _PyFreeListState_GET(); if (Py_SIZE(op) == 0) { return 0; } Py_ssize_t index = Py_SIZE(op) - 1; if (index < PyTuple_NFREELISTS && STATE.numfree[index] < PyTuple_MAXFREELIST + && STATE.numfree[index] >= 0 && Py_IS_TYPE(op, &PyTuple_Type)) { /* op is the head of a linked list, with the first item @@ -1195,9 +1189,9 @@ maybe_freelist_push(PyTupleObject *op) } static void -maybe_freelist_clear(PyInterpreterState *interp, int fini) +maybe_freelist_clear(_PyFreeListState *state, int fini) { -#if PyTuple_NFREELISTS > 0 +#ifdef WITH_FREELISTS for (Py_ssize_t i = 0; i < PyTuple_NFREELISTS; i++) { PyTupleObject *p = STATE.free_list[i]; STATE.free_list[i] = NULL; @@ -1215,8 +1209,8 @@ maybe_freelist_clear(PyInterpreterState *interp, int fini) void _PyTuple_DebugMallocStats(FILE *out) { -#if PyTuple_NFREELISTS > 0 - PyInterpreterState *interp = _PyInterpreterState_GET(); +#ifdef WITH_FREELISTS + _PyFreeListState *state = _PyFreeListState_GET(); for (int i = 0; i < PyTuple_NFREELISTS; i++) { int len = i + 1; char buf[128]; diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 76809494dd8817..ea29a38d74ae3e 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -19,8 +19,6 @@ #include "pycore_weakref.h" // _PyWeakref_GET_REF() #include "opcode.h" // MAKE_CELL - -#include #include // ptrdiff_t /*[clinic input] @@ -586,8 +584,29 @@ _PyType_GetDocFromInternalDoc(const char *name, const char *internal_doc) return PyUnicode_FromString(doc); } +static const char * +signature_from_flags(int flags) +{ + switch (flags & ~METH_COEXIST) { + case METH_NOARGS: + return "($self, /)"; + case METH_NOARGS|METH_CLASS: + return "($type, /)"; + case METH_NOARGS|METH_STATIC: + return "()"; + case METH_O: + return "($self, object, /)"; + case METH_O|METH_CLASS: + return "($type, object, /)"; + case METH_O|METH_STATIC: + return "(object, /)"; + default: + return NULL; + } +} + PyObject * -_PyType_GetTextSignatureFromInternalDoc(const char *name, const char *internal_doc) +_PyType_GetTextSignatureFromInternalDoc(const char *name, const char *internal_doc, int flags) { const char *start = find_signature(name, internal_doc); const char *end; @@ -597,6 +616,10 @@ _PyType_GetTextSignatureFromInternalDoc(const char *name, const char *internal_d else end = NULL; if (!end) { + start = signature_from_flags(flags); + if (start) { + return PyUnicode_FromString(start); + } Py_RETURN_NONE; } @@ -805,7 +828,9 @@ PyType_Modified(PyTypeObject *type) if (bits & 1) { PyType_WatchCallback cb = interp->type_watchers[i]; if (cb && (cb(type) < 0)) { - PyErr_WriteUnraisable((PyObject *)type); + PyErr_FormatUnraisable( + "Exception ignored in type watcher callback #%d for %R", + i, type); } } i++; @@ -1067,14 +1092,9 @@ type_module(PyTypeObject *type, void *context) if (type->tp_flags & Py_TPFLAGS_HEAPTYPE) { PyObject *dict = lookup_tp_dict(type); - mod = PyDict_GetItemWithError(dict, &_Py_ID(__module__)); - if (mod == NULL) { - if (!PyErr_Occurred()) { - PyErr_Format(PyExc_AttributeError, "__module__"); - } - return NULL; + if (PyDict_GetItemRef(dict, &_Py_ID(__module__), &mod) == 0) { + PyErr_Format(PyExc_AttributeError, "__module__"); } - Py_INCREF(mod); } else { const char *s = strrchr(type->tp_name, '.'); @@ -1109,17 +1129,16 @@ type_abstractmethods(PyTypeObject *type, void *context) PyObject *mod = NULL; /* type itself has an __abstractmethods__ descriptor (this). Don't return that. */ - if (type != &PyType_Type) { - PyObject *dict = lookup_tp_dict(type); - mod = PyDict_GetItemWithError(dict, &_Py_ID(__abstractmethods__)); + if (type == &PyType_Type) { + PyErr_SetObject(PyExc_AttributeError, &_Py_ID(__abstractmethods__)); } - if (!mod) { - if (!PyErr_Occurred()) { + else { + PyObject *dict = lookup_tp_dict(type); + if (PyDict_GetItemRef(dict, &_Py_ID(__abstractmethods__), &mod) == 0) { PyErr_SetObject(PyExc_AttributeError, &_Py_ID(__abstractmethods__)); } - return NULL; } - return Py_NewRef(mod); + return mod; } static int @@ -1410,18 +1429,14 @@ type_get_doc(PyTypeObject *type, void *context) return _PyType_GetDocFromInternalDoc(type->tp_name, type->tp_doc); } PyObject *dict = lookup_tp_dict(type); - result = PyDict_GetItemWithError(dict, &_Py_ID(__doc__)); - if (result == NULL) { - if (!PyErr_Occurred()) { - result = Py_NewRef(Py_None); - } - } - else if (Py_TYPE(result)->tp_descr_get) { - result = Py_TYPE(result)->tp_descr_get(result, NULL, - (PyObject *)type); + if (PyDict_GetItemRef(dict, &_Py_ID(__doc__), &result) == 0) { + result = Py_NewRef(Py_None); } - else { - Py_INCREF(result); + else if (result) { + descrgetfunc descr_get = Py_TYPE(result)->tp_descr_get; + if (descr_get) { + Py_SETREF(result, descr_get(result, NULL, (PyObject *)type)); + } } return result; } @@ -1429,7 +1444,7 @@ type_get_doc(PyTypeObject *type, void *context) static PyObject * type_get_text_signature(PyTypeObject *type, void *context) { - return _PyType_GetTextSignatureFromInternalDoc(type->tp_name, type->tp_doc); + return _PyType_GetTextSignatureFromInternalDoc(type->tp_name, type->tp_doc, 0); } static int @@ -1452,16 +1467,16 @@ type_get_annotations(PyTypeObject *type, void *context) PyObject *annotations; PyObject *dict = lookup_tp_dict(type); - annotations = PyDict_GetItemWithError(dict, &_Py_ID(__annotations__)); + if (PyDict_GetItemRef(dict, &_Py_ID(__annotations__), &annotations) < 0) { + return NULL; + } if (annotations) { - if (Py_TYPE(annotations)->tp_descr_get) { - annotations = Py_TYPE(annotations)->tp_descr_get( - annotations, NULL, (PyObject *)type); - } else { - Py_INCREF(annotations); + descrgetfunc get = Py_TYPE(annotations)->tp_descr_get; + if (get) { + Py_SETREF(annotations, get(annotations, NULL, (PyObject *)type)); } } - else if (!PyErr_Occurred()) { + else { annotations = PyDict_New(); if (annotations) { int result = PyDict_SetItem( @@ -1508,16 +1523,11 @@ type_set_annotations(PyTypeObject *type, PyObject *value, void *context) static PyObject * type_get_type_params(PyTypeObject *type, void *context) { - PyObject *params = PyDict_GetItemWithError(lookup_tp_dict(type), &_Py_ID(__type_params__)); - - if (params) { - return Py_NewRef(params); - } - if (PyErr_Occurred()) { - return NULL; + PyObject *params; + if (PyDict_GetItemRef(lookup_tp_dict(type), &_Py_ID(__type_params__), ¶ms) == 0) { + return PyTuple_New(0); } - - return PyTuple_New(0); + return params; } static int @@ -1587,8 +1597,9 @@ static PyGetSetDef type_getsets[] = { }; static PyObject * -type_repr(PyTypeObject *type) +type_repr(PyObject *self) { + PyTypeObject *type = (PyTypeObject *)self; if (type->tp_name == NULL) { // type_repr() called before the type is fully initialized // by PyType_Ready(). @@ -1620,8 +1631,9 @@ type_repr(PyTypeObject *type) } static PyObject * -type_call(PyTypeObject *type, PyObject *args, PyObject *kwds) +type_call(PyObject *self, PyObject *args, PyObject *kwds) { + PyTypeObject *type = (PyTypeObject *)self; PyObject *obj; PyThreadState *tstate = _PyThreadState_GET(); @@ -1812,7 +1824,7 @@ subtype_traverse(PyObject *self, visitproc visit, void *arg) assert(base->tp_dictoffset == 0); if (type->tp_flags & Py_TPFLAGS_MANAGED_DICT) { assert(type->tp_dictoffset == -1); - int err = _PyObject_VisitManagedDict(self, visit, arg); + int err = PyObject_VisitManagedDict(self, visit, arg); if (err) { return err; } @@ -1882,7 +1894,7 @@ subtype_clear(PyObject *self) __dict__ slots (as in the case 'self.__dict__ is self'). */ if (type->tp_flags & Py_TPFLAGS_MANAGED_DICT) { if ((base->tp_flags & Py_TPFLAGS_MANAGED_DICT) == 0) { - _PyObject_ClearManagedDict(self); + PyObject_ClearManagedDict(self); } } else if (type->tp_dictoffset != base->tp_dictoffset) { @@ -2419,7 +2431,7 @@ set_mro_error(PyObject **to_merge, Py_ssize_t to_merge_size, int *remain) n = PyDict_GET_SIZE(set); off = PyOS_snprintf(buf, sizeof(buf), "Cannot create a \ -consistent method resolution\norder (MRO) for bases"); +consistent method resolution order (MRO) for bases"); i = 0; while (PyDict_Next(set, &i, &k, &v) && (size_t)off < sizeof(buf)) { PyObject *name = class_name(k); @@ -2996,21 +3008,21 @@ subtype_getweakref(PyObject *obj, void *context) static PyGetSetDef subtype_getsets_full[] = { {"__dict__", subtype_dict, subtype_setdict, - PyDoc_STR("dictionary for instance variables (if defined)")}, + PyDoc_STR("dictionary for instance variables")}, {"__weakref__", subtype_getweakref, NULL, - PyDoc_STR("list of weak references to the object (if defined)")}, + PyDoc_STR("list of weak references to the object")}, {0} }; static PyGetSetDef subtype_getsets_dict_only[] = { {"__dict__", subtype_dict, subtype_setdict, - PyDoc_STR("dictionary for instance variables (if defined)")}, + PyDoc_STR("dictionary for instance variables")}, {0} }; static PyGetSetDef subtype_getsets_weakref_only[] = { {"__weakref__", subtype_getweakref, NULL, - PyDoc_STR("list of weak references to the object (if defined)")}, + PyDoc_STR("list of weak references to the object")}, {0} }; @@ -3411,18 +3423,13 @@ type_new_set_module(PyTypeObject *type) return 0; } - PyObject *module = PyDict_GetItemWithError(globals, &_Py_ID(__name__)); - if (module == NULL) { - if (PyErr_Occurred()) { - return -1; - } - return 0; - } - - if (PyDict_SetItem(dict, &_Py_ID(__module__), module) < 0) { - return -1; + PyObject *module; + r = PyDict_GetItemRef(globals, &_Py_ID(__name__), &module); + if (module) { + r = PyDict_SetItem(dict, &_Py_ID(__module__), module); + Py_DECREF(module); } - return 0; + return r; } @@ -3433,23 +3440,24 @@ type_new_set_ht_name(PyTypeObject *type) { PyHeapTypeObject *et = (PyHeapTypeObject *)type; PyObject *dict = lookup_tp_dict(type); - PyObject *qualname = PyDict_GetItemWithError(dict, &_Py_ID(__qualname__)); + PyObject *qualname; + if (PyDict_GetItemRef(dict, &_Py_ID(__qualname__), &qualname) < 0) { + return -1; + } if (qualname != NULL) { if (!PyUnicode_Check(qualname)) { PyErr_Format(PyExc_TypeError, "type __qualname__ must be a str, not %s", Py_TYPE(qualname)->tp_name); + Py_DECREF(qualname); return -1; } - et->ht_qualname = Py_NewRef(qualname); + et->ht_qualname = qualname; if (PyDict_DelItem(dict, &_Py_ID(__qualname__)) < 0) { return -1; } } else { - if (PyErr_Occurred()) { - return -1; - } et->ht_qualname = Py_NewRef(et->ht_name); } return 0; @@ -3856,16 +3864,14 @@ type_new_get_bases(type_new_ctx *ctx, PyObject **type) if (PyType_Check(base)) { continue; } - PyObject *mro_entries; - if (PyObject_GetOptionalAttr(base, &_Py_ID(__mro_entries__), - &mro_entries) < 0) { + int rc = PyObject_HasAttrWithError(base, &_Py_ID(__mro_entries__)); + if (rc < 0) { return -1; } - if (mro_entries != NULL) { + if (rc) { PyErr_SetString(PyExc_TypeError, "type() doesn't support MRO entry resolution; " "use types.new_class()"); - Py_DECREF(mro_entries); return -1; } } @@ -4264,9 +4270,9 @@ _PyType_FromMetaclass_impl( if (_allow_tp_new) { if (PyErr_WarnFormat( PyExc_DeprecationWarning, 1, - "Using PyType_Spec with metaclasses that have custom " - "tp_new is deprecated and will no longer be allowed in " - "Python 3.14.") < 0) { + "Type %s uses PyType_Spec with a metaclass that has custom " + "tp_new. This is deprecated and will no longer be allowed in " + "Python 3.14.", spec->name) < 0) { goto finally; } } @@ -4536,6 +4542,12 @@ PyType_GetQualName(PyTypeObject *type) return type_qualname(type, NULL); } +PyObject * +_PyType_GetModuleName(PyTypeObject *type) +{ + return type_module(type, NULL); +} + void * PyType_GetSlot(PyTypeObject *type, int slot) { @@ -4907,14 +4919,15 @@ _Py_type_getattro_impl(PyTypeObject *type, PyObject *name, int * suppress_missin /* This is similar to PyObject_GenericGetAttr(), but uses _PyType_Lookup() instead of just looking in type->tp_dict. */ PyObject * -_Py_type_getattro(PyTypeObject *type, PyObject *name) +_Py_type_getattro(PyObject *type, PyObject *name) { - return _Py_type_getattro_impl(type, name, NULL); + return _Py_type_getattro_impl((PyTypeObject *)type, name, NULL); } static int -type_setattro(PyTypeObject *type, PyObject *name, PyObject *value) +type_setattro(PyObject *self, PyObject *name, PyObject *value) { + PyTypeObject *type = (PyTypeObject *)self; int res; if (type->tp_flags & Py_TPFLAGS_IMMUTABLETYPE) { PyErr_Format( @@ -4965,9 +4978,6 @@ type_setattro(PyTypeObject *type, PyObject *name, PyObject *value) return res; } -extern void -_PyDictKeys_DecRef(PyDictKeysObject *keys); - static void type_dealloc_common(PyTypeObject *type) @@ -5062,8 +5072,10 @@ _PyStaticType_Dealloc(PyInterpreterState *interp, PyTypeObject *type) static void -type_dealloc(PyTypeObject *type) +type_dealloc(PyObject *self) { + PyTypeObject *type = (PyTypeObject *)self; + // Assert this is a heap-allocated type object _PyObject_ASSERT((PyObject *)type, type->tp_flags & Py_TPFLAGS_HEAPTYPE); @@ -5234,8 +5246,10 @@ static PyMethodDef type_methods[] = { TYPE___SUBCLASSES___METHODDEF {"__prepare__", _PyCFunction_CAST(type_prepare), METH_FASTCALL | METH_KEYWORDS | METH_CLASS, - PyDoc_STR("__prepare__() -> dict\n" - "used to create the namespace for the class statement")}, + PyDoc_STR("__prepare__($cls, name, bases, /, **kwds)\n" + "--\n" + "\n" + "Create the namespace for the class statement")}, TYPE___INSTANCECHECK___METHODDEF TYPE___SUBCLASSCHECK___METHODDEF TYPE___DIR___METHODDEF @@ -5248,8 +5262,10 @@ PyDoc_STRVAR(type_doc, "type(name, bases, dict, **kwds) -> a new type"); static int -type_traverse(PyTypeObject *type, visitproc visit, void *arg) +type_traverse(PyObject *self, visitproc visit, void *arg) { + PyTypeObject *type = (PyTypeObject *)self; + /* Because of type_is_gc(), the collector only calls this for heaptypes. */ if (!(type->tp_flags & Py_TPFLAGS_HEAPTYPE)) { @@ -5277,8 +5293,10 @@ type_traverse(PyTypeObject *type, visitproc visit, void *arg) } static int -type_clear(PyTypeObject *type) +type_clear(PyObject *self) { + PyTypeObject *type = (PyTypeObject *)self; + /* Because of type_is_gc(), the collector only calls this for heaptypes. */ _PyObject_ASSERT((PyObject *)type, type->tp_flags & Py_TPFLAGS_HEAPTYPE); @@ -5325,9 +5343,9 @@ type_clear(PyTypeObject *type) } static int -type_is_gc(PyTypeObject *type) +type_is_gc(PyObject *type) { - return type->tp_flags & Py_TPFLAGS_HEAPTYPE; + return ((PyTypeObject *)type)->tp_flags & Py_TPFLAGS_HEAPTYPE; } @@ -5340,28 +5358,28 @@ PyTypeObject PyType_Type = { "type", /* tp_name */ sizeof(PyHeapTypeObject), /* tp_basicsize */ sizeof(PyMemberDef), /* tp_itemsize */ - (destructor)type_dealloc, /* tp_dealloc */ + type_dealloc, /* tp_dealloc */ offsetof(PyTypeObject, tp_vectorcall), /* tp_vectorcall_offset */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_as_async */ - (reprfunc)type_repr, /* tp_repr */ + type_repr, /* tp_repr */ &type_as_number, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ - (ternaryfunc)type_call, /* tp_call */ + type_call, /* tp_call */ 0, /* tp_str */ - (getattrofunc)_Py_type_getattro, /* tp_getattro */ - (setattrofunc)type_setattro, /* tp_setattro */ + _Py_type_getattro, /* tp_getattro */ + type_setattro, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_TYPE_SUBCLASS | Py_TPFLAGS_HAVE_VECTORCALL | Py_TPFLAGS_ITEMS_AT_END, /* tp_flags */ type_doc, /* tp_doc */ - (traverseproc)type_traverse, /* tp_traverse */ - (inquiry)type_clear, /* tp_clear */ + type_traverse, /* tp_traverse */ + type_clear, /* tp_clear */ 0, /* tp_richcompare */ offsetof(PyTypeObject, tp_weaklist), /* tp_weaklistoffset */ 0, /* tp_iter */ @@ -5378,7 +5396,7 @@ PyTypeObject PyType_Type = { 0, /* tp_alloc */ type_new, /* tp_new */ PyObject_GC_Del, /* tp_free */ - (inquiry)type_is_gc, /* tp_is_gc */ + type_is_gc, /* tp_is_gc */ .tp_vectorcall = type_vectorcall, }; @@ -5616,6 +5634,12 @@ object_richcompare(PyObject *self, PyObject *other, int op) return res; } +PyObject* +_Py_BaseObject_RichCompare(PyObject* self, PyObject* other, int op) +{ + return object_richcompare(self, other, op); +} + static PyObject * object_get_class(PyObject *self, void *closure) { @@ -5866,24 +5890,22 @@ _PyType_GetSlotNames(PyTypeObject *cls) /* Get the slot names from the cache in the class if possible. */ PyObject *dict = lookup_tp_dict(cls); - slotnames = PyDict_GetItemWithError(dict, &_Py_ID(__slotnames__)); + if (PyDict_GetItemRef(dict, &_Py_ID(__slotnames__), &slotnames) < 0) { + return NULL; + } if (slotnames != NULL) { if (slotnames != Py_None && !PyList_Check(slotnames)) { PyErr_Format(PyExc_TypeError, "%.200s.__slotnames__ should be a list or None, " "not %.200s", cls->tp_name, Py_TYPE(slotnames)->tp_name); + Py_DECREF(slotnames); return NULL; } - return Py_NewRef(slotnames); - } - else { - if (PyErr_Occurred()) { - return NULL; - } - /* The class does not have the slot names cached yet. */ + return slotnames; } + /* The class does not have the slot names cached yet. */ copyreg = import_copyreg(); if (copyreg == NULL) return NULL; @@ -6548,6 +6570,12 @@ PyDoc_STRVAR(object_doc, "When called, it accepts no arguments and returns a new featureless\n" "instance that has no instance attributes and cannot be given any.\n"); +static Py_hash_t +object_hash(PyObject *obj) +{ + return _Py_HashPointer(obj); +} + PyTypeObject PyBaseObject_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) "object", /* tp_name */ @@ -6562,7 +6590,7 @@ PyTypeObject PyBaseObject_Type = { 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ - (hashfunc)_Py_HashPointer, /* tp_hash */ + object_hash, /* tp_hash */ 0, /* tp_call */ object_str, /* tp_str */ PyObject_GenericGetAttr, /* tp_getattro */ @@ -7486,7 +7514,7 @@ type_ready(PyTypeObject *type, int rerunbuiltin) * to get type objects into the doubly-linked list of all objects. * Still, not all type objects go through PyType_Ready. */ - _Py_AddToAllObjects((PyObject *)type, 0); + _Py_AddToAllObjects((PyObject *)type); #endif /* Initialize tp_dict: _PyType_IsReady() tests if tp_dict != NULL */ @@ -9272,7 +9300,7 @@ releasebuffer_call_python(PyObject *self, Py_buffer *buffer) // from a Python __buffer__ function. mv = PyMemoryView_FromBuffer(buffer); if (mv == NULL) { - PyErr_WriteUnraisable(self); + PyErr_FormatUnraisable("Exception ignored in bf_releasebuffer of %s", Py_TYPE(self)->tp_name); goto end; } // Set the memoryview to restricted mode, which forbids @@ -9285,7 +9313,7 @@ releasebuffer_call_python(PyObject *self, Py_buffer *buffer) PyObject *stack[2] = {self, mv}; PyObject *ret = vectorcall_method(&_Py_ID(__release_buffer__), stack, 2); if (ret == NULL) { - PyErr_WriteUnraisable(self); + PyErr_FormatUnraisable("Exception ignored in __release_buffer__ of %s", Py_TYPE(self)->tp_name); } else { Py_DECREF(ret); @@ -9293,7 +9321,7 @@ releasebuffer_call_python(PyObject *self, Py_buffer *buffer) if (!is_buffer_wrapper) { PyObject *res = PyObject_CallMethodNoArgs(mv, &_Py_ID(release)); if (res == NULL) { - PyErr_WriteUnraisable(self); + PyErr_FormatUnraisable("Exception ignored in bf_releasebuffer of %s", Py_TYPE(self)->tp_name); } else { Py_DECREF(res); @@ -10242,23 +10270,18 @@ _super_lookup_descr(PyTypeObject *su_type, PyTypeObject *su_obj_type, PyObject * return NULL; /* keep a strong reference to mro because su_obj_type->tp_mro can be - replaced during PyDict_GetItemWithError(dict, name) */ + replaced during PyDict_GetItemRef(dict, name, &res) */ Py_INCREF(mro); do { PyObject *obj = PyTuple_GET_ITEM(mro, i); PyObject *dict = lookup_tp_dict(_PyType_CAST(obj)); assert(dict != NULL && PyDict_Check(dict)); - res = PyDict_GetItemWithError(dict, name); - if (res != NULL) { - Py_INCREF(res); + if (PyDict_GetItemRef(dict, name, &res) != 0) { + // found or error Py_DECREF(mro); return res; } - else if (PyErr_Occurred()) { - Py_DECREF(mro); - return NULL; - } i++; } while (i < n); @@ -10381,9 +10404,22 @@ supercheck(PyTypeObject *type, PyObject *obj) Py_XDECREF(class_attr); } - PyErr_SetString(PyExc_TypeError, - "super(type, obj): " - "obj must be an instance or subtype of type"); + const char *type_or_instance, *obj_str; + + if (PyType_Check(obj)) { + type_or_instance = "type"; + obj_str = ((PyTypeObject*)obj)->tp_name; + } + else { + type_or_instance = "instance of"; + obj_str = Py_TYPE(obj)->tp_name; + } + + PyErr_Format(PyExc_TypeError, + "super(type, obj): obj (%s %.200s) is not " + "an instance or subtype of type (%.200s).", + type_or_instance, obj_str, type->tp_name); + return NULL; } diff --git a/Objects/typevarobject.c b/Objects/typevarobject.c index e09e6a62553cff..7f80c9c61b8abc 100644 --- a/Objects/typevarobject.c +++ b/Objects/typevarobject.c @@ -107,7 +107,7 @@ make_union(PyObject *self, PyObject *other) static PyObject * caller(void) { - _PyInterpreterFrame *f = _PyThreadState_GET()->cframe->current_frame; + _PyInterpreterFrame *f = _PyThreadState_GET()->current_frame; if (f == NULL) { Py_RETURN_NONE; } @@ -200,7 +200,8 @@ typevar_dealloc(PyObject *self) Py_XDECREF(tv->evaluate_bound); Py_XDECREF(tv->constraints); Py_XDECREF(tv->evaluate_constraints); - _PyObject_ClearManagedDict(self); + PyObject_ClearManagedDict(self); + PyObject_ClearWeakRefs(self); Py_TYPE(self)->tp_free(self); Py_DECREF(tp); @@ -215,7 +216,7 @@ typevar_traverse(PyObject *self, visitproc visit, void *arg) Py_VISIT(tv->evaluate_bound); Py_VISIT(tv->constraints); Py_VISIT(tv->evaluate_constraints); - _PyObject_VisitManagedDict(self, visit, arg); + PyObject_VisitManagedDict(self, visit, arg); return 0; } @@ -226,7 +227,7 @@ typevar_clear(typevarobject *self) Py_CLEAR(self->evaluate_bound); Py_CLEAR(self->constraints); Py_CLEAR(self->evaluate_constraints); - _PyObject_ClearManagedDict((PyObject *)self); + PyObject_ClearManagedDict((PyObject *)self); return 0; } @@ -326,7 +327,6 @@ typevar.__new__ as typevar_new name: object(subclass_of="&PyUnicode_Type") *constraints: object - * bound: object = None covariant: bool = False contravariant: bool = False @@ -339,7 +339,7 @@ static PyObject * typevar_new_impl(PyTypeObject *type, PyObject *name, PyObject *constraints, PyObject *bound, int covariant, int contravariant, int infer_variance) -/*[clinic end generated code: output=1d200450ee99226d input=2c07ab87c94f462b]*/ +/*[clinic end generated code: output=1d200450ee99226d input=41ae33a916bfe76f]*/ { if (covariant && contravariant) { PyErr_SetString(PyExc_ValueError, @@ -363,11 +363,7 @@ typevar_new_impl(PyTypeObject *type, PyObject *name, PyObject *constraints, } } - if (!PyTuple_CheckExact(constraints)) { - PyErr_SetString(PyExc_TypeError, - "constraints must be a tuple"); - return NULL; - } + assert(PyTuple_CheckExact(constraints)); Py_ssize_t n_constraints = PyTuple_GET_SIZE(constraints); if (n_constraints == 1) { PyErr_SetString(PyExc_TypeError, @@ -401,12 +397,13 @@ typevar_new_impl(PyTypeObject *type, PyObject *name, PyObject *constraints, typevar.__typing_subst__ as typevar_typing_subst arg: object + / [clinic start generated code]*/ static PyObject * -typevar_typing_subst_impl(typevarobject *self, PyObject *arg) -/*[clinic end generated code: output=c76ced134ed8f4e1 input=6b70a4bb2da838de]*/ +typevar_typing_subst(typevarobject *self, PyObject *arg) +/*[clinic end generated code: output=0773735e8ce18968 input=9e87b57f0fc59b92]*/ { PyObject *args[2] = {(PyObject *)self, arg}; PyObject *result = call_typing_func_object("_typevar_subst", args, 2); @@ -742,7 +739,8 @@ paramspec_dealloc(PyObject *self) Py_DECREF(ps->name); Py_XDECREF(ps->bound); - _PyObject_ClearManagedDict(self); + PyObject_ClearManagedDict(self); + PyObject_ClearWeakRefs(self); Py_TYPE(self)->tp_free(self); Py_DECREF(tp); @@ -754,7 +752,7 @@ paramspec_traverse(PyObject *self, visitproc visit, void *arg) Py_VISIT(Py_TYPE(self)); paramspecobject *ps = (paramspecobject *)self; Py_VISIT(ps->bound); - _PyObject_VisitManagedDict(self, visit, arg); + PyObject_VisitManagedDict(self, visit, arg); return 0; } @@ -762,7 +760,7 @@ static int paramspec_clear(paramspecobject *self) { Py_CLEAR(self->bound); - _PyObject_ClearManagedDict((PyObject *)self); + PyObject_ClearManagedDict((PyObject *)self); return 0; } @@ -803,8 +801,8 @@ paramspec_kwargs(PyObject *self, void *unused) } static PyGetSetDef paramspec_getset[] = { - {"args", (getter)paramspec_args, NULL, "Represents positional arguments.", NULL}, - {"kwargs", (getter)paramspec_kwargs, NULL, "Represents keyword arguments.", NULL}, + {"args", (getter)paramspec_args, NULL, PyDoc_STR("Represents positional arguments."), NULL}, + {"kwargs", (getter)paramspec_kwargs, NULL, PyDoc_STR("Represents keyword arguments."), NULL}, {0}, }; @@ -882,12 +880,13 @@ paramspec_new_impl(PyTypeObject *type, PyObject *name, PyObject *bound, paramspec.__typing_subst__ as paramspec_typing_subst arg: object + / [clinic start generated code]*/ static PyObject * -paramspec_typing_subst_impl(paramspecobject *self, PyObject *arg) -/*[clinic end generated code: output=803e1ade3f13b57d input=4e0005d24023e896]*/ +paramspec_typing_subst(paramspecobject *self, PyObject *arg) +/*[clinic end generated code: output=4c5b4aaada1c5814 input=2d5b5e3d4a717189]*/ { PyObject *args[2] = {(PyObject *)self, arg}; PyObject *result = call_typing_func_object("_paramspec_subst", args, 2); @@ -899,13 +898,14 @@ paramspec.__typing_prepare_subst__ as paramspec_typing_prepare_subst alias: object args: object + / [clinic start generated code]*/ static PyObject * paramspec_typing_prepare_subst_impl(paramspecobject *self, PyObject *alias, PyObject *args) -/*[clinic end generated code: output=95449d630a2adb9a input=4375e2ffcb2ad635]*/ +/*[clinic end generated code: output=95449d630a2adb9a input=6df6f9fef3e150da]*/ { PyObject *args_array[3] = {(PyObject *)self, alias, args}; PyObject *result = call_typing_func_object( @@ -1021,7 +1021,8 @@ typevartuple_dealloc(PyObject *self) typevartupleobject *tvt = (typevartupleobject *)self; Py_DECREF(tvt->name); - _PyObject_ClearManagedDict(self); + PyObject_ClearManagedDict(self); + PyObject_ClearWeakRefs(self); Py_TYPE(self)->tp_free(self); Py_DECREF(tp); @@ -1103,12 +1104,13 @@ typevartuple_impl(PyTypeObject *type, PyObject *name) typevartuple.__typing_subst__ as typevartuple_typing_subst arg: object + / [clinic start generated code]*/ static PyObject * -typevartuple_typing_subst_impl(typevartupleobject *self, PyObject *arg) -/*[clinic end generated code: output=814316519441cd76 input=670c4e0a36e5d8c0]*/ +typevartuple_typing_subst(typevartupleobject *self, PyObject *arg) +/*[clinic end generated code: output=237054c6d7484eea input=3fcf2dfd9eee7945]*/ { PyErr_SetString(PyExc_TypeError, "Substitution of bare TypeVarTuple is not supported"); return NULL; @@ -1119,13 +1121,14 @@ typevartuple.__typing_prepare_subst__ as typevartuple_typing_prepare_subst alias: object args: object + / [clinic start generated code]*/ static PyObject * typevartuple_typing_prepare_subst_impl(typevartupleobject *self, PyObject *alias, PyObject *args) -/*[clinic end generated code: output=ff999bc5b02036c1 input=a211b05f2eeb4306]*/ +/*[clinic end generated code: output=ff999bc5b02036c1 input=685b149b0fc47556]*/ { PyObject *args_array[3] = {(PyObject *)self, alias, args}; PyObject *result = call_typing_func_object( @@ -1157,14 +1160,14 @@ static int typevartuple_traverse(PyObject *self, visitproc visit, void *arg) { Py_VISIT(Py_TYPE(self)); - _PyObject_VisitManagedDict(self, visit, arg); + PyObject_VisitManagedDict(self, visit, arg); return 0; } static int typevartuple_clear(PyObject *self) { - _PyObject_ClearManagedDict(self); + PyObject_ClearManagedDict(self); return 0; } diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index c6876d4ca0ef0f..4b03cc3f4da5fa 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -40,9 +40,9 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include "Python.h" #include "pycore_abstract.h" // _PyIndex_Check() -#include "pycore_atomic_funcs.h" // _Py_atomic_size_get() #include "pycore_bytes_methods.h" // _Py_bytes_lower() #include "pycore_bytesobject.h" // _PyBytes_Repeat() +#include "pycore_ceval.h" // _PyEval_GetBuiltin() #include "pycore_codecs.h" // _PyCodec_Lookup() #include "pycore_format.h" // F_LJUST #include "pycore_initconfig.h" // _PyStatus_OK() @@ -56,6 +56,7 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include "pycore_ucnhash.h" // _PyUnicode_Name_CAPI #include "pycore_unicodeobject.h" // struct _Py_unicode_state #include "pycore_unicodeobject_generated.h" // _PyUnicode_InitStaticStrings() + #include "stringlib/eq.h" // unicode_eq() #include // ptrdiff_t @@ -99,11 +100,6 @@ NOTE: In the interpreter's initialization phase, some globals are currently */ - -#ifdef __cplusplus -extern "C" { -#endif - // Maximum code point of Unicode 6.0: 0x10ffff (1,114,111). // The value must be the same in fileutils.c. #define MAX_UNICODE 0x10ffff @@ -1901,24 +1897,25 @@ PyUnicode_FromString(const char *u) PyObject * _PyUnicode_FromId(_Py_Identifier *id) { + PyMutex_Lock((PyMutex *)&id->mutex); PyInterpreterState *interp = _PyInterpreterState_GET(); struct _Py_unicode_ids *ids = &interp->unicode.ids; - Py_ssize_t index = _Py_atomic_size_get(&id->index); + Py_ssize_t index = _Py_atomic_load_ssize(&id->index); if (index < 0) { struct _Py_unicode_runtime_ids *rt_ids = &interp->runtime->unicode_state.ids; - PyThread_acquire_lock(rt_ids->lock, WAIT_LOCK); + PyMutex_Lock(&rt_ids->mutex); // Check again to detect concurrent access. Another thread can have // initialized the index while this thread waited for the lock. - index = _Py_atomic_size_get(&id->index); + index = _Py_atomic_load_ssize(&id->index); if (index < 0) { assert(rt_ids->next_index < PY_SSIZE_T_MAX); index = rt_ids->next_index; rt_ids->next_index++; - _Py_atomic_size_set(&id->index, index); + _Py_atomic_store_ssize(&id->index, index); } - PyThread_release_lock(rt_ids->lock); + PyMutex_Unlock(&rt_ids->mutex); } assert(index >= 0); @@ -1927,14 +1924,14 @@ _PyUnicode_FromId(_Py_Identifier *id) obj = ids->array[index]; if (obj) { // Return a borrowed reference - return obj; + goto end; } } obj = PyUnicode_DecodeUTF8Stateful(id->string, strlen(id->string), NULL, NULL); if (!obj) { - return NULL; + goto end; } PyUnicode_InternInPlace(&obj); @@ -1945,7 +1942,8 @@ _PyUnicode_FromId(_Py_Identifier *id) PyObject **new_array = PyMem_Realloc(ids->array, new_size * item_size); if (new_array == NULL) { PyErr_NoMemory(); - return NULL; + obj = NULL; + goto end; } memset(&new_array[ids->size], 0, (new_size - ids->size) * item_size); ids->array = new_array; @@ -1955,6 +1953,8 @@ _PyUnicode_FromId(_Py_Identifier *id) // The array stores a strong reference ids->array[index] = obj; +end: + PyMutex_Unlock((PyMutex *)&id->mutex); // Return a borrowed reference return obj; } @@ -3824,17 +3824,24 @@ PyUnicode_AsUTF8AndSize(PyObject *unicode, Py_ssize_t *psize) { if (!PyUnicode_Check(unicode)) { PyErr_BadArgument(); + if (psize) { + *psize = -1; + } return NULL; } if (PyUnicode_UTF8(unicode) == NULL) { if (unicode_fill_utf8(unicode) == -1) { + if (psize) { + *psize = -1; + } return NULL; } } - if (psize) + if (psize) { *psize = PyUnicode_UTF8_LENGTH(unicode); + } return PyUnicode_UTF8(unicode); } @@ -3844,6 +3851,18 @@ PyUnicode_AsUTF8(PyObject *unicode) return PyUnicode_AsUTF8AndSize(unicode, NULL); } +const char * +_PyUnicode_AsUTF8NoNUL(PyObject *unicode) +{ + Py_ssize_t size; + const char *s = PyUnicode_AsUTF8AndSize(unicode, &size); + if (s && strlen(s) != (size_t)size) { + PyErr_SetString(PyExc_ValueError, "embedded null character"); + return NULL; + } + return s; +} + /* PyUnicode_GetSize() has been deprecated since Python 3.3 because it returned length of Py_UNICODE. @@ -5854,6 +5873,23 @@ PyUnicode_AsUTF16String(PyObject *unicode) return _PyUnicode_EncodeUTF16(unicode, NULL, 0); } +_PyUnicode_Name_CAPI * +_PyUnicode_GetNameCAPI(void) +{ + PyInterpreterState *interp = _PyInterpreterState_GET(); + _PyUnicode_Name_CAPI *ucnhash_capi; + + ucnhash_capi = _Py_atomic_load_ptr(&interp->unicode.ucnhash_capi); + if (ucnhash_capi == NULL) { + ucnhash_capi = (_PyUnicode_Name_CAPI *)PyCapsule_Import( + PyUnicodeData_CAPSULE_NAME, 1); + + // It's fine if we overwite the value here. It's always the same value. + _Py_atomic_store_ptr(&interp->unicode.ucnhash_capi, ucnhash_capi); + } + return ucnhash_capi; +} + /* --- Unicode Escape Codec ----------------------------------------------- */ PyObject * @@ -5869,7 +5905,6 @@ _PyUnicode_DecodeUnicodeEscapeInternal(const char *s, PyObject *errorHandler = NULL; PyObject *exc = NULL; _PyUnicode_Name_CAPI *ucnhash_capi; - PyInterpreterState *interp = _PyInterpreterState_GET(); // so we can remember if we've seen an invalid escape char or not *first_invalid_escape = NULL; @@ -6017,19 +6052,13 @@ _PyUnicode_DecodeUnicodeEscapeInternal(const char *s, /* \N{name} */ case 'N': - ucnhash_capi = interp->unicode.ucnhash_capi; + ucnhash_capi = _PyUnicode_GetNameCAPI(); if (ucnhash_capi == NULL) { - /* load the unicode data module */ - ucnhash_capi = (_PyUnicode_Name_CAPI *)PyCapsule_Import( - PyUnicodeData_CAPSULE_NAME, 1); - if (ucnhash_capi == NULL) { - PyErr_SetString( + PyErr_SetString( PyExc_UnicodeError, "\\N escapes not supported (can't load unicodedata module)" - ); - goto onError; - } - interp->unicode.ucnhash_capi = ucnhash_capi; + ); + goto onError; } message = "malformed \\N character escape"; @@ -7099,7 +7128,7 @@ decode_code_page_errors(UINT code_page, if (err != ERROR_NO_UNICODE_TRANSLATION && err != ERROR_INSUFFICIENT_BUFFER) { - PyErr_SetFromWindowsErr(0); + PyErr_SetFromWindowsErr(err); goto error; } insize++; @@ -10677,6 +10706,82 @@ PyUnicode_CompareWithASCIIString(PyObject* uni, const char* str) } } +int +PyUnicode_EqualToUTF8(PyObject *unicode, const char *str) +{ + return PyUnicode_EqualToUTF8AndSize(unicode, str, strlen(str)); +} + +int +PyUnicode_EqualToUTF8AndSize(PyObject *unicode, const char *str, Py_ssize_t size) +{ + assert(_PyUnicode_CHECK(unicode)); + assert(str); + + if (PyUnicode_IS_ASCII(unicode)) { + Py_ssize_t len = PyUnicode_GET_LENGTH(unicode); + return size == len && + memcmp(PyUnicode_1BYTE_DATA(unicode), str, len) == 0; + } + if (PyUnicode_UTF8(unicode) != NULL) { + Py_ssize_t len = PyUnicode_UTF8_LENGTH(unicode); + return size == len && + memcmp(PyUnicode_UTF8(unicode), str, len) == 0; + } + + Py_ssize_t len = PyUnicode_GET_LENGTH(unicode); + if ((size_t)len >= (size_t)size || (size_t)len < (size_t)size / 4) { + return 0; + } + const unsigned char *s = (const unsigned char *)str; + const unsigned char *ends = s + (size_t)size; + int kind = PyUnicode_KIND(unicode); + const void *data = PyUnicode_DATA(unicode); + /* Compare Unicode string and UTF-8 string */ + for (Py_ssize_t i = 0; i < len; i++) { + Py_UCS4 ch = PyUnicode_READ(kind, data, i); + if (ch < 0x80) { + if (ends == s || s[0] != ch) { + return 0; + } + s += 1; + } + else if (ch < 0x800) { + if ((ends - s) < 2 || + s[0] != (0xc0 | (ch >> 6)) || + s[1] != (0x80 | (ch & 0x3f))) + { + return 0; + } + s += 2; + } + else if (ch < 0x10000) { + if (Py_UNICODE_IS_SURROGATE(ch) || + (ends - s) < 3 || + s[0] != (0xe0 | (ch >> 12)) || + s[1] != (0x80 | ((ch >> 6) & 0x3f)) || + s[2] != (0x80 | (ch & 0x3f))) + { + return 0; + } + s += 3; + } + else { + assert(ch <= MAX_UNICODE); + if ((ends - s) < 4 || + s[0] != (0xf0 | (ch >> 18)) || + s[1] != (0x80 | ((ch >> 12) & 0x3f)) || + s[2] != (0x80 | ((ch >> 6) & 0x3f)) || + s[3] != (0x80 | (ch & 0x3f))) + { + return 0; + } + s += 4; + } + } + return s == ends; +} + int _PyUnicode_EqualToASCIIString(PyObject *unicode, const char *str) { @@ -12400,14 +12505,16 @@ str.split as unicode_split The separator used to split the string. When set to None (the default value), will split on any whitespace - character (including \\n \\r \\t \\f and spaces) and will discard + character (including \n \r \t \f and spaces) and will discard empty strings from the result. maxsplit: Py_ssize_t = -1 - Maximum number of splits (starting from the left). + Maximum number of splits. -1 (the default value) means no limit. Return a list of the substrings in the string, using sep as the separator string. +Splitting starts at the front of the string and works to the end. + Note, str.split() is mainly useful for data that has been intentionally delimited. With natural text that includes punctuation, consider using the regular expression module. @@ -12416,7 +12523,7 @@ the regular expression module. static PyObject * unicode_split_impl(PyObject *self, PyObject *sep, Py_ssize_t maxsplit) -/*[clinic end generated code: output=3a65b1db356948dc input=906d953b44efc43b]*/ +/*[clinic end generated code: output=3a65b1db356948dc input=a29bcc0c7a5af0eb]*/ { if (sep == Py_None) return split(self, NULL, maxsplit); @@ -13299,15 +13406,17 @@ _PyUnicodeWriter_Dealloc(_PyUnicodeWriter *writer) #include "stringlib/unicode_format.h" PyDoc_STRVAR(format__doc__, - "S.format(*args, **kwargs) -> str\n\ + "format($self, /, *args, **kwargs)\n\ +--\n\ \n\ -Return a formatted version of S, using substitutions from args and kwargs.\n\ +Return a formatted version of the string, using substitutions from args and kwargs.\n\ The substitutions are identified by braces ('{' and '}')."); PyDoc_STRVAR(format_map__doc__, - "S.format_map(mapping) -> str\n\ + "format_map($self, /, mapping)\n\ +--\n\ \n\ -Return a formatted version of S, using substitutions from mapping.\n\ +Return a formatted version of the string, using substitutions from mapping.\n\ The substitutions are identified by braces ('{' and '}')."); /*[clinic input] @@ -14032,7 +14141,7 @@ unicode_format_arg_parse(struct unicode_formatter_t *ctx, "* wants int"); return -1; } - arg->prec = _PyLong_AsInt(v); + arg->prec = PyLong_AsInt(v); if (arg->prec == -1 && PyErr_Occurred()) return -1; if (arg->prec < 0) @@ -14605,7 +14714,7 @@ errors is specified, then the object must expose a data buffer\n\ that will be decoded using the given encoding and error handler.\n\ Otherwise, returns the result of object.__str__() (if defined)\n\ or repr(object).\n\ -encoding defaults to sys.getdefaultencoding().\n\ +encoding defaults to 'utf-8'.\n\ errors defaults to 'strict'."); static PyObject *unicode_iter(PyObject *seq); @@ -14882,7 +14991,7 @@ _PyUnicode_ClearInterned(PyInterpreterState *interp) // Skip the Immortal Instance check and restore // the two references (key and value) ignored // by PyUnicode_InternInPlace(). - s->ob_refcnt = 2; + _Py_SetMortal(s, 2); #ifdef INTERNED_STATS total_length += PyUnicode_GET_LENGTH(s); #endif @@ -15396,8 +15505,3 @@ PyInit__string(void) { return PyModuleDef_Init(&_string_module); } - - -#ifdef __cplusplus -} -#endif diff --git a/Objects/unicodetype_db.h b/Objects/unicodetype_db.h index 22f8243eaec1b7..e6dbeffbe2aa3e 100644 --- a/Objects/unicodetype_db.h +++ b/Objects/unicodetype_db.h @@ -1,4 +1,4 @@ -/* this file was generated by Tools/unicode/makeunicodedata.py 3.3 */ +/* this file was generated by ./Tools/unicode/makeunicodedata.py 3.3 */ /* a list of unique character type descriptors */ const _PyUnicode_TypeRecord _PyUnicode_TypeRecords[] = { @@ -360,6 +360,7 @@ const _PyUnicode_TypeRecord _PyUnicode_TypeRecords[] = { {0, -128, 0, 0, 0, 10113}, {0, -126, 0, 0, 0, 10113}, {33555335, 18875268, 16778121, 0, 0, 26433}, + {0, 0, 0, 0, 0, 4608}, {0, 0, 0, 0, 0, 3076}, {0, 0, 0, 0, 4, 3076}, {0, 0, 0, 0, 5, 3076}, @@ -1760,603 +1761,603 @@ static const unsigned short index1[] = { 76, 64, 77, 78, 79, 80, 81, 82, 83, 64, 64, 84, 85, 34, 34, 34, 34, 34, 34, 86, 34, 34, 34, 34, 34, 87, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 88, 89, 90, 91, 34, 34, 34, 92, 34, 34, - 34, 93, 94, 34, 34, 34, 34, 34, 95, 34, 34, 34, 96, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 97, 98, 99, 34, 34, 34, 34, 34, 34, 100, 101, 34, 34, - 34, 34, 34, 34, 34, 34, 102, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 103, 34, 34, 34, 34, 34, 34, 34, 34, 104, 34, 34, 34, 34, - 100, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 103, 34, 34, 34, 34, 34, 34, 105, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 106, 107, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 108, 109, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 110, 34, 34, 34, 34, 34, - 34, 34, 34, 111, 34, 34, 112, 113, 114, 115, 116, 117, 118, 119, 120, - 121, 122, 123, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 88, 89, 90, 91, 92, 93, 34, 94, 34, 34, + 34, 95, 96, 34, 34, 34, 34, 34, 97, 34, 34, 34, 98, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 99, 100, 101, 34, 34, 34, 34, 34, 34, 102, 103, 34, + 34, 34, 34, 34, 34, 34, 34, 104, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 105, 34, 34, 34, 93, 34, 34, 34, 34, 34, 34, 34, 34, 106, 34, 34, 34, 34, + 107, 108, 34, 34, 34, 34, 34, 109, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 93, 34, 34, 34, 34, 34, 34, 110, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 111, 112, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 113, 34, 34, 34, 34, 114, 34, 34, 115, 116, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 117, 34, 34, 34, + 34, 34, 34, 34, 34, 118, 34, 34, 119, 120, 121, 122, 123, 124, 125, 126, + 127, 128, 129, 130, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 124, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 126, 127, 128, - 129, 130, 131, 132, 34, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, - 125, 143, 144, 145, 146, 147, 148, 149, 34, 34, 150, 151, 152, 153, 154, - 155, 156, 157, 158, 159, 160, 161, 162, 125, 163, 164, 165, 166, 167, - 168, 169, 170, 171, 172, 173, 125, 174, 175, 125, 176, 177, 178, 179, - 125, 180, 181, 182, 183, 184, 185, 186, 125, 187, 188, 189, 190, 125, - 191, 192, 193, 34, 34, 34, 34, 34, 34, 34, 194, 195, 34, 196, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 197, 34, 34, 34, 34, 34, 34, 34, 34, 198, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 34, 34, 34, 34, 199, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 34, 34, 34, 34, 200, 201, 202, 203, 125, 125, 125, 125, 204, - 205, 206, 207, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 131, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 133, 134, + 135, 136, 137, 138, 139, 34, 140, 141, 142, 143, 144, 145, 146, 147, 148, + 149, 132, 150, 151, 152, 153, 154, 155, 156, 34, 34, 157, 158, 159, 160, + 161, 162, 163, 164, 165, 166, 167, 168, 169, 132, 170, 171, 172, 173, + 174, 175, 176, 177, 178, 179, 180, 132, 181, 182, 132, 183, 184, 185, + 186, 132, 187, 188, 189, 190, 191, 192, 193, 132, 194, 195, 196, 197, + 132, 198, 199, 200, 34, 34, 34, 34, 34, 34, 34, 201, 202, 34, 203, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 204, 34, 34, 34, 34, 34, 34, 34, 34, 205, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 34, 34, 34, 34, 206, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 34, 34, 34, 34, 207, 208, 209, 210, 132, 132, 132, 132, + 211, 212, 213, 214, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 208, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 209, 210, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 211, 34, 34, 212, 34, 34, 213, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 214, 215, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 216, 217, 64, 218, - 219, 220, 221, 222, 223, 125, 224, 225, 226, 227, 228, 229, 230, 231, 64, - 64, 64, 64, 232, 233, 125, 125, 125, 125, 125, 125, 125, 125, 234, 125, - 235, 236, 237, 125, 125, 238, 125, 125, 125, 239, 125, 125, 125, 125, - 125, 240, 34, 241, 242, 125, 125, 125, 125, 125, 243, 244, 245, 125, 246, - 247, 125, 125, 248, 249, 250, 251, 252, 125, 64, 253, 64, 64, 64, 64, 64, - 254, 255, 256, 257, 258, 64, 64, 259, 260, 64, 261, 125, 125, 125, 125, - 125, 125, 125, 125, 262, 263, 264, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 86, 265, 34, 266, 267, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 215, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 216, 217, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 218, 34, 34, 219, 34, 34, 220, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 221, 222, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 223, 224, 64, + 225, 226, 227, 228, 229, 230, 132, 231, 232, 233, 234, 235, 236, 237, + 238, 64, 64, 64, 64, 239, 240, 132, 132, 132, 132, 132, 132, 132, 132, + 241, 132, 242, 243, 244, 132, 132, 245, 132, 132, 132, 246, 132, 132, + 132, 132, 132, 247, 34, 248, 249, 132, 132, 132, 132, 132, 250, 251, 252, + 132, 253, 254, 132, 132, 255, 256, 257, 258, 259, 132, 64, 260, 64, 64, + 64, 64, 64, 261, 262, 263, 264, 265, 64, 64, 266, 267, 64, 268, 132, 132, + 132, 132, 132, 132, 132, 132, 269, 270, 271, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 86, 272, 34, 273, 274, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 268, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 269, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 270, + 34, 34, 34, 34, 34, 34, 34, 34, 275, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 276, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 277, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 271, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 109, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 272, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 273, 34, 274, 34, 34, + 278, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 279, 34, 280, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 275, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 281, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 276, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 34, 268, 34, 34, 277, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 282, 34, 34, 34, 34, 283, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 34, 275, 34, 34, 284, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 278, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 285, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 279, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 280, 125, 281, 282, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, - 125, 125, 125, + 34, 34, 34, 34, 34, 34, 286, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 287, 132, 288, 289, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, }; static const unsigned short index2[] = { @@ -2777,27 +2778,27 @@ static const unsigned short index2[] = { 342, 265, 265, 343, 343, 0, 5, 5, 5, 264, 264, 344, 345, 346, 126, 347, 348, 265, 265, 349, 349, 130, 5, 5, 5, 0, 0, 350, 351, 352, 0, 353, 354, 355, 355, 356, 356, 357, 5, 5, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 20, - 20, 20, 20, 20, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 5, 4, 4, 5, 2, 2, 20, 20, 20, 20, 20, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 17, 17, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 17, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1, 20, 20, 20, 20, 20, 0, 20, 20, - 20, 20, 20, 20, 20, 20, 20, 20, 358, 101, 0, 0, 359, 360, 361, 362, 363, - 364, 4, 4, 4, 4, 4, 101, 358, 25, 21, 22, 359, 360, 361, 362, 363, 364, - 4, 4, 4, 4, 4, 0, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, - 101, 101, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 5, - 5, 5, 5, 24, 5, 5, 5, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 120, 4, 4, 4, 4, 120, 4, - 4, 19, 120, 120, 120, 19, 19, 120, 120, 120, 19, 4, 120, 4, 4, 365, 120, - 120, 120, 120, 120, 4, 4, 4, 4, 4, 4, 120, 4, 366, 4, 120, 4, 367, 368, - 120, 120, 365, 19, 120, 120, 369, 120, 19, 54, 54, 54, 54, 19, 4, 4, 19, - 19, 120, 120, 4, 4, 4, 4, 4, 120, 19, 19, 19, 19, 4, 4, 4, 4, 370, 4, 26, - 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 371, 371, - 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, + 358, 358, 20, 20, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 5, 4, 4, 5, 2, 2, 20, 20, 20, 20, 20, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 17, 17, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 17, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1, 20, 20, 20, 20, 20, 0, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 359, 101, 0, 0, 360, 361, 362, 363, + 364, 365, 4, 4, 4, 4, 4, 101, 359, 25, 21, 22, 360, 361, 362, 363, 364, + 365, 4, 4, 4, 4, 4, 0, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, + 101, 101, 101, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 5, 5, 5, 5, 24, 5, 5, 5, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 120, 4, 4, 4, 4, + 120, 4, 4, 19, 120, 120, 120, 19, 19, 120, 120, 120, 19, 4, 120, 4, 4, + 366, 120, 120, 120, 120, 120, 4, 4, 4, 4, 4, 4, 120, 4, 367, 4, 120, 4, + 368, 369, 120, 120, 366, 19, 120, 120, 370, 120, 19, 54, 54, 54, 54, 19, + 4, 4, 19, 19, 120, 120, 4, 4, 4, 4, 4, 120, 19, 19, 19, 19, 4, 4, 4, 4, + 371, 4, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, - 372, 372, 242, 242, 242, 29, 30, 242, 242, 242, 242, 26, 4, 4, 0, 0, 0, - 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 372, 372, 373, 373, 373, 373, 373, 373, 373, 373, 373, 373, 373, 373, + 373, 373, 373, 373, 242, 242, 242, 29, 30, 242, 242, 242, 242, 26, 4, 4, + 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, @@ -2808,26 +2809,26 @@ static const unsigned short index2[] = { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 25, 21, 22, 359, 360, 361, 362, 363, 364, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 26, 25, 21, 22, 359, 360, 361, 362, 363, 364, 26, 26, 26, 26, - 26, 26, 26, 26, 26, 26, 26, 25, 21, 22, 359, 360, 361, 362, 363, 364, 26, - 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 373, 373, 373, 373, 373, - 373, 373, 373, 373, 373, 373, 373, 373, 373, 373, 373, 373, 373, 373, - 373, 373, 373, 373, 373, 373, 373, 374, 374, 374, 374, 374, 374, 374, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 25, 21, 22, 360, 361, 362, 363, 364, 365, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 25, 21, 22, 360, 361, 362, 363, 364, 365, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 25, 21, 22, 360, 361, 362, 363, 364, + 365, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 374, 374, 374, 374, 374, 374, 374, 374, 374, 374, 374, 374, 374, 374, 374, 374, 374, 374, - 374, 374, 374, 374, 374, 358, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 25, - 21, 22, 359, 360, 361, 362, 363, 364, 26, 358, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 374, 374, 374, 374, 374, 374, 374, 374, 375, 375, 375, 375, 375, 375, + 375, 375, 375, 375, 375, 375, 375, 375, 375, 375, 375, 375, 375, 375, + 375, 375, 375, 375, 375, 375, 359, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 25, 21, 22, 360, 361, 362, 363, 364, 365, 26, 359, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 25, 21, 22, 359, 360, 361, 362, - 363, 364, 26, 25, 21, 22, 359, 360, 361, 362, 363, 364, 26, 25, 21, 22, - 359, 360, 361, 362, 363, 364, 26, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 25, 21, 22, 360, 361, + 362, 363, 364, 365, 26, 25, 21, 22, 360, 361, 362, 363, 364, 365, 26, 25, + 21, 22, 360, 361, 362, 363, 364, 365, 26, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, @@ -2836,85 +2837,85 @@ static const unsigned short index2[] = { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 135, 135, 135, 135, 135, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 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, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, + 135, 135, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, - 136, 136, 136, 136, 136, 136, 136, 29, 30, 375, 376, 377, 378, 379, 29, - 30, 29, 30, 29, 30, 380, 381, 382, 383, 19, 29, 30, 19, 29, 30, 19, 19, - 19, 19, 19, 101, 101, 384, 384, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, - 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, - 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, - 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, - 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, - 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, - 19, 4, 4, 4, 4, 4, 4, 29, 30, 29, 30, 24, 24, 24, 29, 30, 0, 0, 0, 0, 0, - 4, 4, 4, 4, 26, 4, 4, 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, - 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, - 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, 0, - 385, 0, 0, 0, 0, 0, 385, 0, 0, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 0, 0, 0, 0, 0, 0, 0, 102, 4, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 54, 54, 54, 54, 54, 54, 54, 0, 54, 54, 54, 54, 54, 54, - 54, 0, 54, 54, 54, 54, 54, 54, 54, 0, 54, 54, 54, 54, 54, 54, 54, 0, 54, - 54, 54, 54, 54, 54, 54, 0, 54, 54, 54, 54, 54, 54, 54, 0, 54, 54, 54, 54, - 54, 54, 54, 0, 54, 54, 54, 54, 54, 54, 54, 0, 24, 24, 24, 24, 24, 24, 24, + 136, 136, 136, 136, 136, 136, 136, 136, 29, 30, 376, 377, 378, 379, 380, + 29, 30, 29, 30, 29, 30, 381, 382, 383, 384, 19, 29, 30, 19, 29, 30, 19, + 19, 19, 19, 19, 101, 101, 385, 385, 29, 30, 29, 30, 29, 30, 29, 30, 29, + 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, + 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, + 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, + 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, + 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, + 30, 19, 4, 4, 4, 4, 4, 4, 29, 30, 29, 30, 24, 24, 24, 29, 30, 0, 0, 0, 0, + 0, 4, 4, 4, 4, 26, 4, 4, 386, 386, 386, 386, 386, 386, 386, 386, 386, + 386, 386, 386, 386, 386, 386, 386, 386, 386, 386, 386, 386, 386, 386, + 386, 386, 386, 386, 386, 386, 386, 386, 386, 386, 386, 386, 386, 386, + 386, 0, 386, 0, 0, 0, 0, 0, 386, 0, 0, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 0, 0, 0, 0, 0, 0, 0, 102, + 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 54, 54, 54, 54, 54, 54, 54, 0, 54, 54, 54, 54, 54, + 54, 54, 0, 54, 54, 54, 54, 54, 54, 54, 0, 54, 54, 54, 54, 54, 54, 54, 0, + 54, 54, 54, 54, 54, 54, 54, 0, 54, 54, 54, 54, 54, 54, 54, 0, 54, 54, 54, + 54, 54, 54, 54, 0, 54, 54, 54, 54, 54, 54, 54, 0, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, - 24, 24, 24, 24, 24, 24, 24, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 24, 24, 24, 24, 24, 24, 24, 24, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 386, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 387, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 0, 0, 0, 0, 1, 4, 4, 4, 4, 102, 54, 242, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 242, 242, 242, - 242, 242, 242, 242, 242, 242, 24, 24, 24, 24, 17, 17, 4, 102, 102, 102, - 102, 102, 4, 4, 242, 242, 242, 102, 54, 4, 4, 4, 0, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1, 4, 4, 4, 4, 102, 54, 242, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 242, 242, + 242, 242, 242, 242, 242, 242, 242, 24, 24, 24, 24, 17, 17, 4, 102, 102, + 102, 102, 102, 4, 4, 242, 242, 242, 102, 54, 4, 4, 4, 0, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 0, 0, 24, 24, 5, 5, 102, 102, 54, 4, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 0, 0, 24, 24, 5, 5, 102, 102, 54, + 4, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 4, 102, 102, 102, 54, 0, 0, 0, 0, 0, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 17, 102, 102, 102, 54, 0, 0, 0, 0, 0, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 0, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 0, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 0, 4, 4, 26, 26, 26, 26, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 54, + 54, 54, 54, 54, 0, 4, 4, 26, 26, 26, 26, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 4, 4, 4, 4, 4, 4, 4, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 54, 54, 54, 54, + 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, @@ -2927,14 +2928,14 @@ static const unsigned short index2[] = { 26, 26, 26, 26, 26, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 54, 54, - 54, 54, 54, 387, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 388, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 387, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 388, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, @@ -2943,7 +2944,7 @@ static const unsigned short index2[] = { 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 387, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 388, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, @@ -2952,7 +2953,7 @@ static const unsigned short index2[] = { 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 387, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 388, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, @@ -2961,501 +2962,551 @@ static const unsigned short index2[] = { 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 387, 54, 54, 387, 54, 54, 54, 387, - 54, 387, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 388, 54, 54, 388, 54, 54, 54, 388, + 54, 388, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 388, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 388, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 387, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 388, 54, 54, 54, 54, 54, 54, 54, 388, 54, 388, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 387, 54, 54, 54, 54, 54, 54, 54, 387, 54, 387, + 54, 54, 54, 388, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 388, 388, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 388, 54, 54, 54, 54, 54, 54, 54, 54, 388, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 387, 387, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 388, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 387, 54, 54, 54, 54, 54, 54, 54, 54, 387, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 387, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 388, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 387, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 387, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 387, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 387, 54, 387, 54, - 387, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 388, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 388, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 387, 54, 387, 387, 387, - 54, 54, 54, 54, 54, 54, 387, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 388, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 387, 387, - 387, 387, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 388, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 388, 54, 388, 54, 388, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 388, + 54, 388, 388, 388, 54, 54, 54, 54, 54, 54, 388, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 387, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 388, 388, 388, 388, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 387, 54, 54, 54, - 54, 54, 54, 54, 387, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 388, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 387, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 387, 387, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 387, 387, 387, 54, 387, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 388, 54, 54, 54, 54, 54, 54, 54, 388, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 388, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 387, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 388, 388, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 388, 388, 388, + 54, 388, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 387, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 387, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 388, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 387, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 388, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 388, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 387, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 388, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 388, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 387, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 388, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 387, 54, 54, 54, 54, 387, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 387, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 388, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 387, 54, 54, 54, 54, + 54, 54, 388, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 387, 54, 54, 54, - 54, 54, 387, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 387, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 387, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 102, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 388, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 388, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 0, 0, - 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 102, - 102, 102, 102, 102, 102, 4, 4, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 102, 4, 4, 4, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 54, 54, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 30, 29, 30, 29, 30, 29, 30, - 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, - 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, - 29, 30, 54, 24, 5, 5, 5, 4, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 4, - 102, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, - 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 101, 101, 24, 24, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 242, 242, 242, 242, - 242, 242, 242, 242, 242, 242, 24, 24, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, - 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 102, 102, 102, 102, 102, 102, 102, 102, 102, 5, 5, 29, 30, 29, 30, 29, - 30, 29, 30, 29, 30, 29, 30, 29, 30, 19, 19, 29, 30, 29, 30, 29, 30, 29, - 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, - 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 388, 54, 54, + 54, 54, 388, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 388, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 388, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 388, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 388, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 388, 54, 54, 54, 54, 54, 388, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 388, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 388, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 102, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 0, 0, 0, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 102, 102, 102, + 102, 102, 102, 4, 4, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 102, + 4, 4, 4, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 54, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, - 30, 101, 19, 19, 19, 19, 19, 19, 19, 19, 29, 30, 29, 30, 388, 29, 30, 29, - 30, 29, 30, 29, 30, 29, 30, 102, 5, 5, 29, 30, 389, 19, 54, 29, 30, 29, - 30, 390, 19, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, - 30, 29, 30, 29, 30, 391, 392, 393, 394, 391, 19, 395, 396, 397, 398, 29, - 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 399, 400, - 401, 29, 30, 29, 30, 0, 0, 0, 0, 0, 29, 30, 0, 19, 0, 19, 29, 30, 29, 30, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 101, 101, 101, 29, 30, 54, 101, 101, 19, 54, 54, 54, 54, 54, 54, 54, 24, - 54, 54, 54, 24, 54, 54, 54, 54, 24, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 17, 17, 24, 24, - 17, 4, 4, 4, 4, 24, 0, 0, 0, 26, 26, 26, 26, 26, 26, 4, 4, 4, 4, 0, 0, 0, - 0, 0, 0, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 54, + 24, 5, 5, 5, 4, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 4, 102, 29, 30, + 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, + 29, 30, 29, 30, 29, 30, 29, 30, 101, 101, 24, 24, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 242, 242, 242, 242, 242, 242, + 242, 242, 242, 242, 24, 24, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 102, + 102, 102, 102, 102, 102, 102, 102, 102, 5, 5, 29, 30, 29, 30, 29, 30, 29, + 30, 29, 30, 29, 30, 29, 30, 19, 19, 29, 30, 29, 30, 29, 30, 29, 30, 29, + 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, + 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, + 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 101, + 19, 19, 19, 19, 19, 19, 19, 19, 29, 30, 29, 30, 389, 29, 30, 29, 30, 29, + 30, 29, 30, 29, 30, 102, 5, 5, 29, 30, 390, 19, 54, 29, 30, 29, 30, 391, + 19, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, + 30, 29, 30, 392, 393, 394, 395, 392, 19, 396, 397, 398, 399, 29, 30, 29, + 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 400, 401, 402, 29, + 30, 29, 30, 0, 0, 0, 0, 0, 29, 30, 0, 19, 0, 19, 29, 30, 29, 30, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101, 101, + 101, 29, 30, 54, 101, 101, 19, 54, 54, 54, 54, 54, 54, 54, 24, 54, 54, + 54, 24, 54, 54, 54, 54, 24, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 17, 17, 24, 24, 17, 4, 4, + 4, 4, 24, 0, 0, 0, 26, 26, 26, 26, 26, 26, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 24, 24, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 6, 7, 8, 9, 10, - 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 24, 24, 24, 24, 24, 24, 24, 24, 24, - 24, 24, 24, 24, 24, 24, 24, 24, 24, 54, 54, 54, 54, 54, 54, 4, 4, 4, 54, - 4, 54, 54, 24, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 24, 24, 24, 24, 24, 24, 24, 24, 4, 4, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 4, 4, 4, + 4, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 17, 17, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 4, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 0, 0, 0, 24, - 24, 24, 17, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 24, 17, 17, 24, - 24, 24, 24, 17, 17, 24, 24, 17, 17, 17, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 0, 102, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 4, 4, 54, - 54, 54, 54, 54, 24, 102, 54, 54, 54, 54, 54, 54, 54, 54, 54, 6, 7, 8, 9, - 10, 11, 12, 13, 14, 15, 54, 54, 54, 54, 54, 0, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 24, 24, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 6, 7, 8, 9, 10, 11, 12, + 13, 14, 15, 0, 0, 0, 0, 0, 0, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 54, 54, 54, 54, 54, 54, 4, 4, 4, 54, 4, 54, + 54, 24, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 24, 24, 24, 24, 24, 24, 24, 24, 4, 4, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 24, - 24, 24, 24, 24, 24, 17, 17, 24, 24, 17, 17, 24, 24, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 54, 54, 54, 24, 54, 54, 54, 54, 54, 54, 54, 54, 24, 17, 0, 0, 6, 7, - 8, 9, 10, 11, 12, 13, 14, 15, 0, 0, 4, 4, 4, 4, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 102, 54, 54, 54, 54, 54, 54, 4, - 4, 4, 54, 17, 24, 17, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 24, 54, 24, 24, 24, 54, 54, 24, 24, 54, 54, 54, 54, 54, 24, 24, 54, - 24, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 54, 54, 102, 4, 4, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 17, - 24, 24, 17, 17, 4, 4, 54, 102, 102, 17, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 54, 54, 54, 54, 54, 54, 0, 0, 54, 54, 54, 54, 54, 54, 0, 0, 54, 54, 54, - 54, 54, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 54, 54, 54, 54, 54, 54, 0, 54, - 54, 54, 54, 54, 54, 54, 0, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 402, 19, 19, 19, 19, 19, 19, 19, 5, 101, 101, - 101, 101, 19, 19, 19, 19, 19, 19, 19, 19, 19, 101, 5, 5, 0, 0, 0, 0, 403, - 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, - 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, - 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, - 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, - 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, - 474, 475, 476, 477, 478, 479, 480, 481, 482, 54, 54, 54, 54, 54, 54, 54, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 17, 17, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 4, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 0, 0, 0, 24, 24, + 24, 17, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 17, 17, 24, 17, 17, 24, 17, 17, - 4, 17, 24, 0, 0, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 24, 17, 17, 24, 24, + 24, 24, 17, 17, 24, 24, 17, 17, 17, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 0, 102, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 4, 4, 54, 54, + 54, 54, 54, 24, 102, 54, 54, 54, 54, 54, 54, 54, 54, 54, 6, 7, 8, 9, 10, + 11, 12, 13, 14, 15, 54, 54, 54, 54, 54, 0, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 24, 24, + 24, 24, 24, 24, 17, 17, 24, 24, 17, 17, 24, 24, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 54, 54, 54, 24, 54, 54, 54, 54, 54, 54, 54, 54, 24, 17, 0, 0, 6, 7, 8, + 9, 10, 11, 12, 13, 14, 15, 0, 0, 4, 4, 4, 4, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 102, 54, 54, 54, 54, 54, 54, 4, 4, 4, + 54, 17, 24, 17, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 24, 54, 24, 24, 24, 54, 54, 24, 24, 54, 54, 54, 54, 54, 24, 24, 54, 24, + 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 54, 54, 102, 4, 4, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 17, 24, + 24, 17, 17, 4, 4, 54, 102, 102, 17, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, + 54, 54, 54, 54, 54, 0, 0, 54, 54, 54, 54, 54, 54, 0, 0, 54, 54, 54, 54, + 54, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 54, 54, 54, 54, 54, 54, 0, 54, 54, + 54, 54, 54, 54, 54, 0, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 403, 19, 19, 19, 19, 19, 19, 19, 5, 101, 101, 101, + 101, 19, 19, 19, 19, 19, 19, 19, 19, 19, 101, 5, 5, 0, 0, 0, 0, 404, 405, + 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, + 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, + 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, + 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, + 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, + 476, 477, 478, 479, 480, 481, 482, 483, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 17, 17, 24, 17, 17, 24, 17, 17, 4, + 17, 24, 0, 0, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 0, 0, 0, 0, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 0, 0, 0, 0, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 0, 0, 0, 0, 0, 0, 0, 0, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 0, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 387, 54, 54, 54, 54, 54, 54, 54, 387, 54, 54, 54, 54, 387, 54, + 388, 54, 54, 54, 54, 54, 54, 54, 388, 54, 54, 54, 54, 388, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 387, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 387, 54, 387, + 388, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 388, 54, 388, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 387, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 388, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 0, 0, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 0, 0, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 483, 484, 485, 486, 487, 488, 489, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 490, 491, 492, 493, 494, 0, 0, 0, 0, 0, 54, 24, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 4, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 0, 54, 54, 54, 54, 54, 0, 54, 0, 54, 54, 0, 54, 54, 0, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 484, + 485, 486, 487, 488, 489, 490, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 491, + 492, 493, 494, 495, 0, 0, 0, 0, 0, 54, 24, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 4, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 0, 54, + 54, 54, 54, 54, 0, 54, 0, 54, 54, 0, 54, 54, 0, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 495, - 495, 495, 495, 495, 495, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 496, 496, 496, + 496, 496, 496, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 0, 0, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 0, 0, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 0, 0, 0, 0, 0, 0, 0, 4, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 495, 495, - 4, 4, 4, 4, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, - 24, 4, 4, 4, 5, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 24, 24, 24, 24, 24, - 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 4, 4, 4, 17, 17, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 17, 17, 17, - 4, 4, 5, 0, 4, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, - 4, 4, 4, 4, 0, 0, 0, 0, 495, 54, 495, 54, 495, 0, 495, 54, 495, 54, 495, - 54, 495, 54, 495, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 0, 0, 0, 0, 0, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 496, 496, 4, 4, 4, + 4, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 4, 4, + 4, 5, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 4, 4, 4, 17, 17, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 17, 17, 17, 4, 4, 5, 0, + 4, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 4, 4, 4, 4, + 0, 0, 0, 0, 496, 54, 496, 54, 496, 0, 496, 54, 496, 54, 496, 54, 496, 54, + 496, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 0, 0, 20, 0, 4, 4, 4, 4, 4, 4, 5, 4, 4, 4, 4, 4, 4, 5, 4, - 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 5, 4, 4, 4, 4, 4, 4, 16, 16, 16, 16, + 54, 0, 0, 20, 0, 4, 4, 4, 4, 4, 4, 5, 4, 4, 4, 4, 4, 4, 5, 4, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 5, 4, 4, 4, 4, 4, 4, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 4, 4, 4, 5, 17, 5, 18, 18, 18, 18, 18, 18, 18, 18, 18, - 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 102, + 16, 4, 4, 4, 5, 17, 5, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 17, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 102, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 496, 496, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 497, 497, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 0, 0, 0, 54, 54, 54, 54, 54, 54, 0, 0, 54, 54, - 54, 54, 54, 54, 0, 0, 54, 54, 54, 54, 54, 54, 0, 0, 54, 54, 54, 0, 0, 0, - 4, 4, 4, 5, 4, 4, 4, 0, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 20, 20, 20, 4, 4, 0, 0, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 0, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 0, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 0, 54, 54, 0, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 0, 0, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 54, + 54, 54, 54, 0, 0, 0, 54, 54, 54, 54, 54, 54, 0, 0, 54, 54, 54, 54, 54, + 54, 0, 0, 54, 54, 54, 54, 54, 54, 0, 0, 54, 54, 54, 0, 0, 0, 4, 4, 4, 5, + 4, 4, 4, 0, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 20, + 20, 4, 4, 0, 0, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 0, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 0, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 0, 54, 54, 0, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 0, 0, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 0, 0, 0, 0, 0, 4, 4, - 4, 0, 0, 0, 0, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 0, 0, 0, 0, 0, 4, 4, 4, 0, 0, 0, + 0, 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, - 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 0, 0, 0, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, - 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 26, - 26, 26, 26, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 26, 26, 4, - 4, 4, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 4, 0, 0, 0, 0, + 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 26, 26, 26, 26, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 26, 26, 4, 4, 4, 0, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 24, 0, 0, 54, 54, 54, 54, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 24, 0, 0, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 0, 0, 0, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 0, 0, 0, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 26, 26, + 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 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, 54, 54, 54, 54, 54, 54, 54, 54, + 26, 26, 26, 26, 0, 0, 0, 0, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 26, 26, 26, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, + 54, 54, 54, 26, 26, 26, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 242, 54, + 54, 54, 54, 54, 54, 54, 54, 242, 0, 0, 0, 0, 0, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 242, 54, 54, 54, 54, 54, 54, 54, 54, 242, 0, 0, 0, 0, 0, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 24, - 24, 24, 24, 24, 0, 0, 0, 0, 0, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 24, 24, 24, 24, + 24, 0, 0, 0, 0, 0, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 0, 4, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 0, 4, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 0, 0, 0, 0, 54, 54, 54, 54, 54, 54, 54, 54, 4, 242, 242, 242, - 242, 242, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 497, 497, - 497, 497, 497, 497, 497, 497, 497, 497, 497, 497, 497, 497, 497, 497, - 497, 497, 497, 497, 497, 497, 497, 497, 497, 497, 497, 497, 497, 497, - 497, 497, 497, 497, 497, 497, 497, 497, 497, 497, 498, 498, 498, 498, + 0, 0, 0, 0, 54, 54, 54, 54, 54, 54, 54, 54, 4, 242, 242, 242, 242, 242, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 498, 498, 498, 498, 498, 498, 498, 498, 498, 498, 498, 498, 498, 498, 498, 498, 498, 498, 498, 498, 498, 498, 498, 498, 498, 498, 498, 498, 498, 498, 498, 498, - 498, 498, 498, 498, 498, 498, 498, 498, 54, 54, 54, 54, 54, 54, 54, 54, + 498, 498, 498, 498, 498, 498, 498, 498, 499, 499, 499, 499, 499, 499, + 499, 499, 499, 499, 499, 499, 499, 499, 499, 499, 499, 499, 499, 499, + 499, 499, 499, 499, 499, 499, 499, 499, 499, 499, 499, 499, 499, 499, + 499, 499, 499, 499, 499, 499, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 0, 0, 6, - 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 497, 497, 497, 497, - 497, 497, 497, 497, 497, 497, 497, 497, 497, 497, 497, 497, 497, 497, - 497, 497, 497, 497, 497, 497, 497, 497, 497, 497, 497, 497, 497, 497, - 497, 497, 497, 497, 0, 0, 0, 0, 498, 498, 498, 498, 498, 498, 498, 498, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 0, 0, 6, 7, 8, 9, 10, + 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 498, 498, 498, 498, 498, 498, 498, 498, 498, 498, 498, 498, 498, 498, 498, 498, 498, 498, 498, 498, 498, - 498, 498, 498, 498, 498, 498, 498, 498, 498, 498, 498, 498, 498, 498, 0, - 0, 0, 0, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 498, 498, 498, 498, 498, 498, 498, 498, 498, 498, 498, 498, 498, 498, + 498, 0, 0, 0, 0, 499, 499, 499, 499, 499, 499, 499, 499, 499, 499, 499, + 499, 499, 499, 499, 499, 499, 499, 499, 499, 499, 499, 499, 499, 499, + 499, 499, 499, 499, 499, 499, 499, 499, 499, 499, 499, 0, 0, 0, 0, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 0, 0, 0, 0, 0, 0, 0, 0, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 0, 0, 0, 0, 0, 0, 0, 0, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 4, 499, 499, 499, 499, 499, 499, 499, 499, 499, 499, 499, 0, 499, 499, - 499, 499, 499, 499, 499, 499, 499, 499, 499, 499, 499, 499, 499, 0, 499, - 499, 499, 499, 499, 499, 499, 0, 499, 499, 0, 500, 500, 500, 500, 500, - 500, 500, 500, 500, 500, 500, 0, 500, 500, 500, 500, 500, 500, 500, 500, - 500, 500, 500, 500, 500, 500, 500, 0, 500, 500, 500, 500, 500, 500, 500, - 0, 500, 500, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 500, 500, + 500, 500, 500, 500, 500, 500, 500, 500, 500, 0, 500, 500, 500, 500, 500, + 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 0, 500, 500, 500, 500, + 500, 500, 500, 0, 500, 500, 0, 501, 501, 501, 501, 501, 501, 501, 501, + 501, 501, 501, 0, 501, 501, 501, 501, 501, 501, 501, 501, 501, 501, 501, + 501, 501, 501, 501, 0, 501, 501, 501, 501, 501, 501, 501, 0, 501, 501, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 54, 54, 54, 54, 54, 54, 54, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101, 102, 102, 101, 101, 101, 0, 101, 101, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 54, 54, 54, 54, + 54, 54, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 101, 102, 102, 101, 101, 101, 0, 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, 0, 101, 101, - 101, 101, 101, 101, 101, 101, 101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 101, 101, 101, 101, 101, 101, 101, 101, 101, 0, 101, 101, 101, 101, 101, + 101, 101, 101, 101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 54, 54, 54, 54, 54, 54, 0, 0, 54, 0, 54, 54, 54, + 0, 0, 0, 54, 54, 54, 54, 54, 54, 0, 0, 54, 0, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 0, 54, 54, 0, 0, 0, 54, 0, 0, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 0, 4, - 26, 26, 26, 26, 26, 26, 26, 26, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 4, 4, 26, 26, 26, 26, - 26, 26, 26, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 0, 0, 0, - 0, 0, 0, 0, 0, 26, 26, 26, 26, 26, 26, 26, 26, 26, 0, 0, 0, 0, 0, 0, 0, + 54, 0, 54, 54, 0, 0, 0, 54, 0, 0, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 0, 4, 26, 26, 26, 26, + 26, 26, 26, 26, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 4, 4, 26, 26, 26, 26, 26, 26, 26, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 0, 0, 0, 0, 0, 0, 0, 0, + 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 0, 54, 54, 0, 0, - 0, 0, 0, 26, 26, 26, 26, 26, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 26, 26, 26, 26, 26, 26, 0, 0, - 0, 4, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 0, 54, 54, 0, 0, 0, 0, 0, 26, 26, + 26, 26, 26, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 26, 26, 26, 26, 26, 26, 0, 0, 0, 4, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 0, 0, 0, 0, 0, 0, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 0, 0, 0, 0, 26, 26, 54, 54, 26, 26, - 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 0, 0, 26, 26, 26, + 54, 54, 54, 54, 54, 54, 0, 0, 0, 0, 26, 26, 54, 54, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 0, 0, 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, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 26, 26, 26, 26, 54, 24, 24, 24, 0, 24, 24, 0, 0, 0, 0, 0, 24, - 24, 24, 24, 54, 54, 54, 54, 0, 54, 54, 54, 0, 54, 54, 54, 54, 54, 54, 54, + 26, 26, 26, 26, 54, 24, 24, 24, 0, 24, 24, 0, 0, 0, 0, 0, 24, 24, 24, 24, + 54, 54, 54, 54, 0, 54, 54, 54, 0, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 0, 0, 24, 24, 24, 0, 0, 0, 0, 24, 25, 21, 22, 359, 26, - 26, 26, 26, 26, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, - 0, 0, 0, 0, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 26, 26, 4, 54, + 54, 0, 0, 24, 24, 24, 0, 0, 0, 0, 24, 25, 21, 22, 360, 26, 26, 26, 26, + 26, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 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, 54, 54, 54, 54, 54, 54, 54, 54, 4, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 26, 26, 4, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 24, 24, 0, 0, 0, 0, 26, 26, 26, 26, 26, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 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, 54, 54, + 54, 54, 54, 54, 54, 54, 4, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 24, + 24, 0, 0, 0, 0, 26, 26, 26, 26, 26, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 0, 0, 26, 26, - 26, 26, 26, 26, 26, 26, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 0, 0, 0, 0, 0, 26, 26, 26, 26, 26, 26, 26, - 26, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 26, 26, 26, 26, 26, 26, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 54, 54, 54, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 0, 0, 26, 26, 26, + 26, 26, 26, 26, 26, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 0, 0, 0, 0, 0, 26, 26, 26, 26, 26, 26, 26, 26, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 54, 54, 54, 54, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 0, 0, 0, 0, 0, 0, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -3473,7 +3524,7 @@ static const unsigned short 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, 25, 21, 22, 359, 360, 361, 362, 363, 364, 26, 26, + 0, 0, 0, 0, 0, 0, 0, 0, 25, 21, 22, 360, 361, 362, 363, 364, 365, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 0, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, @@ -3498,7 +3549,7 @@ static const unsigned short index2[] = { 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 4, 4, 4, 4, - 4, 4, 4, 0, 0, 0, 0, 25, 21, 22, 359, 360, 361, 362, 363, 364, 26, 26, + 4, 4, 4, 0, 0, 0, 0, 25, 21, 22, 360, 361, 362, 363, 364, 365, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 24, 54, 54, 24, 24, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 24, 24, 17, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, @@ -3974,12 +4025,12 @@ static const unsigned short index2[] = { 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 0, 0, 26, 26, 26, 26, 26, 26, 26, 26, 26, 24, 24, 24, 24, 24, 24, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 501, 501, 501, 501, - 501, 501, 501, 501, 501, 501, 501, 501, 501, 501, 501, 501, 501, 501, - 501, 501, 501, 501, 501, 501, 501, 501, 501, 501, 501, 501, 501, 501, - 501, 501, 502, 502, 502, 502, 502, 502, 502, 502, 502, 502, 502, 502, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 502, 502, 502, 502, + 502, 502, 502, 502, 502, 502, 502, 502, 502, 502, 502, 502, 502, 502, 502, 502, 502, 502, 502, 502, 502, 502, 502, 502, 502, 502, 502, 502, - 502, 502, 502, 502, 502, 502, 502, 502, 24, 24, 24, 24, 24, 24, 24, 102, + 502, 502, 503, 503, 503, 503, 503, 503, 503, 503, 503, 503, 503, 503, + 503, 503, 503, 503, 503, 503, 503, 503, 503, 503, 503, 503, 503, 503, + 503, 503, 503, 503, 503, 503, 503, 503, 24, 24, 24, 24, 24, 24, 24, 102, 0, 0, 0, 0, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -4023,15 +4074,15 @@ static const unsigned short index2[] = { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 358, 358, 25, 21, 22, 359, 360, 361, 362, 363, 364, 26, 26, 4, 4, + 0, 0, 359, 359, 25, 21, 22, 360, 361, 362, 363, 364, 365, 26, 26, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 503, 503, 503, 503, 503, 503, 503, 503, 503, - 503, 503, 503, 503, 503, 503, 503, 503, 503, 503, 503, 503, 503, 503, - 503, 503, 503, 4, 4, 4, 4, 4, 4, 503, 503, 503, 503, 503, 503, 503, 503, - 503, 503, 503, 503, 503, 503, 503, 503, 503, 503, 503, 503, 503, 503, - 503, 503, 503, 503, 4, 4, 4, 4, 4, 4, 503, 503, 503, 503, 503, 503, 503, - 503, 503, 503, 503, 503, 503, 503, 503, 503, 503, 503, 503, 503, 503, - 503, 503, 503, 503, 503, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 504, 504, 504, 504, 504, 504, 504, 504, 504, + 504, 504, 504, 504, 504, 504, 504, 504, 504, 504, 504, 504, 504, 504, + 504, 504, 504, 4, 4, 4, 4, 4, 4, 504, 504, 504, 504, 504, 504, 504, 504, + 504, 504, 504, 504, 504, 504, 504, 504, 504, 504, 504, 504, 504, 504, + 504, 504, 504, 504, 4, 4, 4, 4, 4, 4, 504, 504, 504, 504, 504, 504, 504, + 504, 504, 504, 504, 504, 504, 504, 504, 504, 504, 504, 504, 504, 504, + 504, 504, 504, 504, 504, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -4089,30 +4140,30 @@ static const unsigned short index2[] = { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7, - 8, 9, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 54, 387, 54, 54, 54, 54, + 8, 9, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 54, 388, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 387, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 388, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 387, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 388, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 387, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 388, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 387, 54, 54, 54, 54, 54, 54, 54, 54, 387, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 387, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 388, 54, 54, 54, 54, 54, 54, 54, 54, 388, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 388, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, @@ -4124,23 +4175,23 @@ static const unsigned short index2[] = { 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 387, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 387, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 387, 54, 54, 54, 54, 54, 54, + 388, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 388, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 388, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 387, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 388, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 387, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 388, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, @@ -4148,7 +4199,7 @@ static const unsigned short index2[] = { 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 387, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 388, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, @@ -4159,68 +4210,68 @@ static const unsigned short index2[] = { 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 387, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 0, 0, 0, 0, 0, 0, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 0, 0, 0, 0, 0, 0, 54, 54, 54, + 0, 0, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 0, 0, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 54, 54, 54, 54, 54, 54, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 0, 0, 0, 0, 0, 0, 0, 0, + 54, 54, 54, 54, 54, 54, 54, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 54, 54, 54, 54, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 0, 0, 0, - 0, 0, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 0, 0, 0, 0, 0, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, - 20, 20, 20, 20, 20, 20, 20, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 20, 20, 20, 20, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, @@ -4233,8 +4284,8 @@ static const unsigned short index2[] = { 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, - 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, }; /* Returns the numeric value as double for Unicode characters @@ -4282,6 +4333,7 @@ double _PyUnicode_ToNumeric(Py_UCS4 ch) case 0x24EA: case 0x24FF: case 0x3007: + case 0x6D1E: case 0x96F6: case 0xA620: case 0xA6EF: @@ -4713,6 +4765,7 @@ double _PyUnicode_ToNumeric(Py_UCS4 ch) case 0x1ECA0: case 0x1ECB4: return (double) 100000.0; + case 0x5146: case 0x16B5E: return (double) 1000000.0; case 0x1ECA1: @@ -4721,11 +4774,14 @@ double _PyUnicode_ToNumeric(Py_UCS4 ch) case 0x5104: case 0x16B5F: return (double) 100000000.0; + case 0x79ED: + return (double) 1000000000.0; case 0x16B60: return (double) 10000000000.0; - case 0x5146: case 0x16B61: return (double) 1000000000000.0; + case 0x4EAC: + return (double) 1e+16; case 0x216A: case 0x217A: case 0x246A: @@ -4865,7 +4921,10 @@ double _PyUnicode_ToNumeric(Py_UCS4 ch) case 0x3221: case 0x3281: case 0x3483: + case 0x4E24: case 0x4E8C: + case 0x4FE9: + case 0x5006: case 0x5169: case 0x5F0D: case 0x5F10: @@ -5008,6 +5067,7 @@ double _PyUnicode_ToNumeric(Py_UCS4 ch) case 0x1EC7B: case 0x1ED0B: return (double) 20.0; + case 0x7695: case 0x1011A: case 0x102F4: case 0x109D3: @@ -5894,6 +5954,7 @@ double _PyUnicode_ToNumeric(Py_UCS4 ch) case 0x3286: case 0x3B4D: case 0x4E03: + case 0x62D0: case 0x67D2: case 0x6F06: case 0xA627: @@ -6198,6 +6259,8 @@ double _PyUnicode_ToNumeric(Py_UCS4 ch) case 0x4E5D: case 0x5EFE: case 0x7396: + case 0x920E: + case 0x94A9: case 0xA629: case 0xA6EE: case 0xA8D9: diff --git a/Objects/unionobject.c b/Objects/unionobject.c index 347945a4c45972..bf5605686f8df7 100644 --- a/Objects/unionobject.c +++ b/Objects/unionobject.c @@ -186,28 +186,21 @@ union_repr_item(_PyUnicodeWriter *writer, PyObject *p) { PyObject *qualname = NULL; PyObject *module = NULL; - PyObject *tmp; PyObject *r = NULL; - int err; + int rc; if (p == (PyObject *)&_PyNone_Type) { return _PyUnicodeWriter_WriteASCIIString(writer, "None", 4); } - if (PyObject_GetOptionalAttr(p, &_Py_ID(__origin__), &tmp) < 0) { - goto exit; + if ((rc = PyObject_HasAttrWithError(p, &_Py_ID(__origin__))) > 0 && + (rc = PyObject_HasAttrWithError(p, &_Py_ID(__args__))) > 0) + { + // It looks like a GenericAlias + goto use_repr; } - - if (tmp) { - Py_DECREF(tmp); - if (PyObject_GetOptionalAttr(p, &_Py_ID(__args__), &tmp) < 0) { - goto exit; - } - if (tmp) { - // It looks like a GenericAlias - Py_DECREF(tmp); - goto use_repr; - } + if (rc < 0) { + goto exit; } if (PyObject_GetOptionalAttr(p, &_Py_ID(__qualname__), &qualname) < 0) { @@ -244,9 +237,9 @@ union_repr_item(_PyUnicodeWriter *writer, PyObject *p) if (r == NULL) { return -1; } - err = _PyUnicodeWriter_WriteStr(writer, r); + rc = _PyUnicodeWriter_WriteStr(writer, r); Py_DECREF(r); - return err; + return rc; } static PyObject * @@ -331,7 +324,8 @@ union_parameters(PyObject *self, void *Py_UNUSED(unused)) } static PyGetSetDef union_properties[] = { - {"__parameters__", union_parameters, (setter)NULL, "Type variables in the types.UnionType.", NULL}, + {"__parameters__", union_parameters, (setter)NULL, + PyDoc_STR("Type variables in the types.UnionType."), NULL}, {0} }; diff --git a/Objects/weakrefobject.c b/Objects/weakrefobject.c index 1814c6eb69c29b..df74be6aba7244 100644 --- a/Objects/weakrefobject.c +++ b/Objects/weakrefobject.c @@ -1,6 +1,7 @@ #include "Python.h" #include "pycore_modsupport.h" // _PyArg_NoKwnames() #include "pycore_object.h" // _PyObject_GET_WEAKREFS_LISTPTR() +#include "pycore_pyerrors.h" // _PyErr_ChainExceptions1() #include "pycore_weakref.h" // _PyWeakref_GET_REF() diff --git a/PC/_testconsole.c b/PC/_testconsole.c index 3221b985d01ba0..1dc0d230c4d7c3 100644 --- a/PC/_testconsole.c +++ b/PC/_testconsole.c @@ -35,6 +35,23 @@ PyModuleDef_Slot testconsole_slots[] = { {0, NULL}, }; +/*[python input] +class HANDLE_converter(CConverter): + type = 'void *' + format_unit = '"_Py_PARSE_UINTPTR"' + + def parse_arg(self, argname, displayname, *, limited_capi): + return self.format_code(""" + {paramname} = PyLong_AsVoidPtr({argname}); + if (!{paramname} && PyErr_Occurred()) {{{{ + goto exit; + }}}} + """, + argname=argname) +[python start generated code]*/ +/*[python end generated code: output=da39a3ee5e6b4b0d input=380aa5c91076742b]*/ +/*[python end generated code:]*/ + /*[clinic input] module _testconsole @@ -116,6 +133,7 @@ _testconsole_read_output_impl(PyObject *module, PyObject *file) Py_RETURN_NONE; } + #include "clinic\_testconsole.c.h" PyMethodDef testconsole_methods[] = { diff --git a/PC/_wmimodule.cpp b/PC/_wmimodule.cpp index 310aa86d94d9b6..5ab6dcb032550b 100644 --- a/PC/_wmimodule.cpp +++ b/PC/_wmimodule.cpp @@ -8,6 +8,11 @@ // Version history // 2022-08: Initial contribution (Steve Dower) +// clinic/_wmimodule.cpp.h uses internal pycore_modsupport.h API +#ifndef Py_BUILD_CORE_BUILTIN +# define Py_BUILD_CORE_MODULE 1 +#endif + #define _WIN32_DCOM #include #include @@ -39,6 +44,8 @@ struct _query_data { LPCWSTR query; HANDLE writePipe; HANDLE readPipe; + HANDLE initEvent; + HANDLE connectEvent; }; @@ -75,12 +82,18 @@ _query_thread(LPVOID param) IID_IWbemLocator, (LPVOID *)&locator ); } + if (SUCCEEDED(hr) && !SetEvent(data->initEvent)) { + hr = HRESULT_FROM_WIN32(GetLastError()); + } if (SUCCEEDED(hr)) { hr = locator->ConnectServer( bstr_t(L"ROOT\\CIMV2"), NULL, NULL, 0, NULL, 0, 0, &services ); } + if (SUCCEEDED(hr) && !SetEvent(data->connectEvent)) { + hr = HRESULT_FROM_WIN32(GetLastError()); + } if (SUCCEEDED(hr)) { hr = CoSetProxyBlanket( services, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL, @@ -184,6 +197,24 @@ _query_thread(LPVOID param) } +static DWORD +wait_event(HANDLE event, DWORD timeout) +{ + DWORD err = 0; + switch (WaitForSingleObject(event, timeout)) { + case WAIT_OBJECT_0: + break; + case WAIT_TIMEOUT: + err = WAIT_TIMEOUT; + break; + default: + err = GetLastError(); + break; + } + return err; +} + + /*[clinic input] _wmi.exec_query @@ -226,7 +257,11 @@ _wmi_exec_query_impl(PyObject *module, PyObject *query) Py_BEGIN_ALLOW_THREADS - if (!CreatePipe(&data.readPipe, &data.writePipe, NULL, 0)) { + data.initEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + data.connectEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + if (!data.initEvent || !data.connectEvent || + !CreatePipe(&data.readPipe, &data.writePipe, NULL, 0)) + { err = GetLastError(); } else { hThread = CreateThread(NULL, 0, _query_thread, (LPVOID*)&data, 0, NULL); @@ -238,6 +273,17 @@ _wmi_exec_query_impl(PyObject *module, PyObject *query) } } + // gh-112278: If current user doesn't have permission to query the WMI, the + // function IWbemLocator::ConnectServer will hang for 5 seconds, and there + // is no way to specify the timeout. So we use an Event object to simulate + // a timeout. The initEvent will be set after COM initialization, it will + // take a longer time when first initialized. The connectEvent will be set + // after connected to WMI. + err = wait_event(data.initEvent, 1000); + if (!err) { + err = wait_event(data.connectEvent, 100); + } + while (!err) { if (ReadFile( data.readPipe, @@ -260,7 +306,7 @@ _wmi_exec_query_impl(PyObject *module, PyObject *query) } // Allow the thread some time to clean up - switch (WaitForSingleObject(hThread, 1000)) { + switch (WaitForSingleObject(hThread, 100)) { case WAIT_OBJECT_0: // Thread ended cleanly if (!GetExitCodeThread(hThread, (LPDWORD)&err)) { @@ -281,6 +327,8 @@ _wmi_exec_query_impl(PyObject *module, PyObject *query) } CloseHandle(hThread); + CloseHandle(data.initEvent); + CloseHandle(data.connectEvent); hThread = NULL; Py_END_ALLOW_THREADS diff --git a/PC/clinic/_testconsole.c.h b/PC/clinic/_testconsole.c.h index b2f3b4ce8b08a2..2c71c11c438b5b 100644 --- a/PC/clinic/_testconsole.c.h +++ b/PC/clinic/_testconsole.c.h @@ -3,10 +3,10 @@ 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() +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() #endif - +#include "pycore_modsupport.h" // _PyArg_UnpackKeywords() #if defined(MS_WINDOWS) @@ -140,4 +140,4 @@ _testconsole_read_output(PyObject *module, PyObject *const *args, Py_ssize_t nar #ifndef _TESTCONSOLE_READ_OUTPUT_METHODDEF #define _TESTCONSOLE_READ_OUTPUT_METHODDEF #endif /* !defined(_TESTCONSOLE_READ_OUTPUT_METHODDEF) */ -/*[clinic end generated code: output=208c72e2c873555b input=a9049054013a1b77]*/ +/*[clinic end generated code: output=08a1c844b3657272 input=a9049054013a1b77]*/ diff --git a/PC/clinic/_wmimodule.cpp.h b/PC/clinic/_wmimodule.cpp.h index bfcad41750b319..fccf3d795d5340 100644 --- a/PC/clinic/_wmimodule.cpp.h +++ b/PC/clinic/_wmimodule.cpp.h @@ -3,10 +3,10 @@ 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() +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() #endif - +#include "pycore_modsupport.h" // _PyArg_UnpackKeywords() PyDoc_STRVAR(_wmi_exec_query__doc__, "exec_query($module, /, query)\n" @@ -69,4 +69,4 @@ _wmi_exec_query(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObj exit: return return_value; } -/*[clinic end generated code: output=923d09bee1d15c5f input=a9049054013a1b77]*/ +/*[clinic end generated code: output=ba04920d127f3ceb input=a9049054013a1b77]*/ diff --git a/PC/clinic/msvcrtmodule.c.h b/PC/clinic/msvcrtmodule.c.h index 94e17306f2258e..e3f7ea43f38211 100644 --- a/PC/clinic/msvcrtmodule.c.h +++ b/PC/clinic/msvcrtmodule.c.h @@ -2,11 +2,7 @@ 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 - +#include "pycore_modsupport.h" // _PyArg_CheckPositional() PyDoc_STRVAR(msvcrt_heapmin__doc__, "heapmin($module, /)\n" @@ -59,11 +55,11 @@ msvcrt_locking(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("locking", nargs, 3, 3)) { goto exit; } - fd = _PyLong_AsInt(args[0]); + fd = PyLong_AsInt(args[0]); if (fd == -1 && PyErr_Occurred()) { goto exit; } - mode = _PyLong_AsInt(args[1]); + mode = PyLong_AsInt(args[1]); if (mode == -1 && PyErr_Occurred()) { goto exit; } @@ -105,11 +101,11 @@ msvcrt_setmode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("setmode", nargs, 2, 2)) { goto exit; } - fd = _PyLong_AsInt(args[0]); + fd = PyLong_AsInt(args[0]); if (fd == -1 && PyErr_Occurred()) { goto exit; } - flags = _PyLong_AsInt(args[1]); + flags = PyLong_AsInt(args[1]); if (flags == -1 && PyErr_Occurred()) { goto exit; } @@ -154,7 +150,7 @@ msvcrt_open_osfhandle(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!handle && PyErr_Occurred()) { goto exit; } - flags = _PyLong_AsInt(args[1]); + flags = PyLong_AsInt(args[1]); if (flags == -1 && PyErr_Occurred()) { goto exit; } @@ -189,7 +185,7 @@ msvcrt_get_osfhandle(PyObject *module, PyObject *arg) int fd; void *_return_value; - fd = _PyLong_AsInt(arg); + fd = PyLong_AsInt(arg); if (fd == -1 && PyErr_Occurred()) { goto exit; } @@ -207,7 +203,7 @@ PyDoc_STRVAR(msvcrt_kbhit__doc__, "kbhit($module, /)\n" "--\n" "\n" -"Return true if a keypress is waiting to be read."); +"Returns a nonzero value if a keypress is waiting to be read. Otherwise, return 0."); #define MSVCRT_KBHIT_METHODDEF \ {"kbhit", (PyCFunction)msvcrt_kbhit, METH_NOARGS, msvcrt_kbhit__doc__}, @@ -514,7 +510,7 @@ msvcrt_CrtSetReportFile(PyObject *module, PyObject *const *args, Py_ssize_t narg if (!_PyArg_CheckPositional("CrtSetReportFile", nargs, 2, 2)) { goto exit; } - type = _PyLong_AsInt(args[0]); + type = PyLong_AsInt(args[0]); if (type == -1 && PyErr_Occurred()) { goto exit; } @@ -561,11 +557,11 @@ msvcrt_CrtSetReportMode(PyObject *module, PyObject *const *args, Py_ssize_t narg if (!_PyArg_CheckPositional("CrtSetReportMode", nargs, 2, 2)) { goto exit; } - type = _PyLong_AsInt(args[0]); + type = PyLong_AsInt(args[0]); if (type == -1 && PyErr_Occurred()) { goto exit; } - mode = _PyLong_AsInt(args[1]); + mode = PyLong_AsInt(args[1]); if (mode == -1 && PyErr_Occurred()) { goto exit; } @@ -604,7 +600,7 @@ msvcrt_set_error_mode(PyObject *module, PyObject *arg) int mode; long _return_value; - mode = _PyLong_AsInt(arg); + mode = PyLong_AsInt(arg); if (mode == -1 && PyErr_Occurred()) { goto exit; } @@ -701,4 +697,4 @@ msvcrt_SetErrorMode(PyObject *module, PyObject *arg) #ifndef MSVCRT_GETERRORMODE_METHODDEF #define MSVCRT_GETERRORMODE_METHODDEF #endif /* !defined(MSVCRT_GETERRORMODE_METHODDEF) */ -/*[clinic end generated code: output=9dd12bf210e362a4 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=de9687b46212c2ed input=a9049054013a1b77]*/ diff --git a/PC/clinic/winreg.c.h b/PC/clinic/winreg.c.h index 2aa0698185960b..7e5545e113e718 100644 --- a/PC/clinic/winreg.c.h +++ b/PC/clinic/winreg.c.h @@ -3,10 +3,11 @@ 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() +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() #endif - +#include "pycore_long.h" // _PyLong_UnsignedLong_Converter() +#include "pycore_modsupport.h" // _PyArg_CheckPositional() #if (defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_SYSTEM) || defined(MS_WINDOWS_GAMES)) @@ -92,53 +93,26 @@ winreg_HKEYType___enter__(PyHKEYObject *self, PyObject *Py_UNUSED(ignored)) #if (defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_SYSTEM) || defined(MS_WINDOWS_GAMES)) PyDoc_STRVAR(winreg_HKEYType___exit____doc__, -"__exit__($self, /, exc_type, exc_value, traceback)\n" +"__exit__($self, exc_type, exc_value, traceback, /)\n" "--\n" "\n"); #define WINREG_HKEYTYPE___EXIT___METHODDEF \ - {"__exit__", _PyCFunction_CAST(winreg_HKEYType___exit__), METH_FASTCALL|METH_KEYWORDS, winreg_HKEYType___exit____doc__}, + {"__exit__", _PyCFunction_CAST(winreg_HKEYType___exit__), METH_FASTCALL, winreg_HKEYType___exit____doc__}, static PyObject * winreg_HKEYType___exit___impl(PyHKEYObject *self, PyObject *exc_type, PyObject *exc_value, PyObject *traceback); static PyObject * -winreg_HKEYType___exit__(PyHKEYObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +winreg_HKEYType___exit__(PyHKEYObject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 3 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(exc_type), &_Py_ID(exc_value), &_Py_ID(traceback), }, - }; - #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[] = {"exc_type", "exc_value", "traceback", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "__exit__", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[3]; PyObject *exc_type; PyObject *exc_value; PyObject *traceback; - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 3, 3, 0, argsbuf); - if (!args) { + if (!_PyArg_CheckPositional("__exit__", nargs, 3, 3)) { goto exit; } exc_type = args[0]; @@ -401,7 +375,7 @@ winreg_CreateKeyEx(PyObject *module, PyObject *const *args, Py_ssize_t nargs, Py goto skip_optional_pos; } if (args[2]) { - reserved = _PyLong_AsInt(args[2]); + reserved = PyLong_AsInt(args[2]); if (reserved == -1 && PyErr_Occurred()) { goto exit; } @@ -409,7 +383,7 @@ winreg_CreateKeyEx(PyObject *module, PyObject *const *args, Py_ssize_t nargs, Py goto skip_optional_pos; } } - access = _PyLong_AsInt(args[3]); + access = PyLong_AsInt(args[3]); if (access == -1 && PyErr_Occurred()) { goto exit; } @@ -579,7 +553,7 @@ winreg_DeleteKeyEx(PyObject *module, PyObject *const *args, Py_ssize_t nargs, Py goto skip_optional_pos; } if (args[2]) { - access = _PyLong_AsInt(args[2]); + access = PyLong_AsInt(args[2]); if (access == -1 && PyErr_Occurred()) { goto exit; } @@ -587,7 +561,7 @@ winreg_DeleteKeyEx(PyObject *module, PyObject *const *args, Py_ssize_t nargs, Py goto skip_optional_pos; } } - reserved = _PyLong_AsInt(args[3]); + reserved = PyLong_AsInt(args[3]); if (reserved == -1 && PyErr_Occurred()) { goto exit; } @@ -695,7 +669,7 @@ winreg_EnumKey(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!clinic_HKEY_converter(_PyModule_GetState(module), args[0], &key)) { goto exit; } - index = _PyLong_AsInt(args[1]); + index = PyLong_AsInt(args[1]); if (index == -1 && PyErr_Occurred()) { goto exit; } @@ -752,7 +726,7 @@ winreg_EnumValue(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!clinic_HKEY_converter(_PyModule_GetState(module), args[0], &key)) { goto exit; } - index = _PyLong_AsInt(args[1]); + index = PyLong_AsInt(args[1]); if (index == -1 && PyErr_Occurred()) { goto exit; } @@ -1016,7 +990,7 @@ winreg_OpenKey(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObje goto skip_optional_pos; } if (args[2]) { - reserved = _PyLong_AsInt(args[2]); + reserved = PyLong_AsInt(args[2]); if (reserved == -1 && PyErr_Occurred()) { goto exit; } @@ -1024,7 +998,7 @@ winreg_OpenKey(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObje goto skip_optional_pos; } } - access = _PyLong_AsInt(args[3]); + access = PyLong_AsInt(args[3]); if (access == -1 && PyErr_Occurred()) { goto exit; } @@ -1133,7 +1107,7 @@ winreg_OpenKeyEx(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyOb goto skip_optional_pos; } if (args[2]) { - reserved = _PyLong_AsInt(args[2]); + reserved = PyLong_AsInt(args[2]); if (reserved == -1 && PyErr_Occurred()) { goto exit; } @@ -1141,7 +1115,7 @@ winreg_OpenKeyEx(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyOb goto skip_optional_pos; } } - access = _PyLong_AsInt(args[3]); + access = PyLong_AsInt(args[3]); if (access == -1 && PyErr_Occurred()) { goto exit; } @@ -1788,4 +1762,4 @@ winreg_QueryReflectionKey(PyObject *module, PyObject *arg) #ifndef WINREG_QUERYREFLECTIONKEY_METHODDEF #define WINREG_QUERYREFLECTIONKEY_METHODDEF #endif /* !defined(WINREG_QUERYREFLECTIONKEY_METHODDEF) */ -/*[clinic end generated code: output=d2bf1f58ad07e5f8 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=1ee4098b2f143b6a input=a9049054013a1b77]*/ diff --git a/PC/clinic/winsound.c.h b/PC/clinic/winsound.c.h index 241d547c267a4c..6cc989565b638e 100644 --- a/PC/clinic/winsound.c.h +++ b/PC/clinic/winsound.c.h @@ -2,12 +2,6 @@ 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(winsound_PlaySound__doc__, "PlaySound($module, /, sound, flags)\n" "--\n" @@ -20,53 +14,22 @@ PyDoc_STRVAR(winsound_PlaySound__doc__, " Flag values, ored together. See module documentation."); #define WINSOUND_PLAYSOUND_METHODDEF \ - {"PlaySound", _PyCFunction_CAST(winsound_PlaySound), METH_FASTCALL|METH_KEYWORDS, winsound_PlaySound__doc__}, + {"PlaySound", (PyCFunction)(void(*)(void))winsound_PlaySound, METH_VARARGS|METH_KEYWORDS, winsound_PlaySound__doc__}, static PyObject * winsound_PlaySound_impl(PyObject *module, PyObject *sound, int flags); static PyObject * -winsound_PlaySound(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +winsound_PlaySound(PyObject *module, PyObject *args, PyObject *kwargs) { 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(sound), &_Py_ID(flags), }, - }; - #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[] = {"sound", "flags", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "PlaySound", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[2]; + static char *_keywords[] = {"sound", "flags", NULL}; PyObject *sound; int flags; - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); - if (!args) { - goto exit; - } - sound = args[0]; - flags = _PyLong_AsInt(args[1]); - if (flags == -1 && PyErr_Occurred()) { + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi:PlaySound", _keywords, + &sound, &flags)) goto exit; - } return_value = winsound_PlaySound_impl(module, sound, flags); exit: @@ -86,56 +49,22 @@ PyDoc_STRVAR(winsound_Beep__doc__, " How long the sound should play, in milliseconds."); #define WINSOUND_BEEP_METHODDEF \ - {"Beep", _PyCFunction_CAST(winsound_Beep), METH_FASTCALL|METH_KEYWORDS, winsound_Beep__doc__}, + {"Beep", (PyCFunction)(void(*)(void))winsound_Beep, METH_VARARGS|METH_KEYWORDS, winsound_Beep__doc__}, static PyObject * winsound_Beep_impl(PyObject *module, int frequency, int duration); static PyObject * -winsound_Beep(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +winsound_Beep(PyObject *module, PyObject *args, PyObject *kwargs) { 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(frequency), &_Py_ID(duration), }, - }; - #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[] = {"frequency", "duration", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "Beep", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[2]; + static char *_keywords[] = {"frequency", "duration", NULL}; int frequency; int duration; - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); - if (!args) { + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:Beep", _keywords, + &frequency, &duration)) goto exit; - } - frequency = _PyLong_AsInt(args[0]); - if (frequency == -1 && PyErr_Occurred()) { - goto exit; - } - duration = _PyLong_AsInt(args[1]); - if (duration == -1 && PyErr_Occurred()) { - goto exit; - } return_value = winsound_Beep_impl(module, frequency, duration); exit: @@ -151,59 +80,24 @@ PyDoc_STRVAR(winsound_MessageBeep__doc__, "x defaults to MB_OK."); #define WINSOUND_MESSAGEBEEP_METHODDEF \ - {"MessageBeep", _PyCFunction_CAST(winsound_MessageBeep), METH_FASTCALL|METH_KEYWORDS, winsound_MessageBeep__doc__}, + {"MessageBeep", (PyCFunction)(void(*)(void))winsound_MessageBeep, METH_VARARGS|METH_KEYWORDS, winsound_MessageBeep__doc__}, static PyObject * winsound_MessageBeep_impl(PyObject *module, int type); static PyObject * -winsound_MessageBeep(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +winsound_MessageBeep(PyObject *module, PyObject *args, PyObject *kwargs) { PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(type), }, - }; - #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[] = {"type", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "MessageBeep", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; + static char *_keywords[] = {"type", NULL}; int type = MB_OK; - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf); - if (!args) { - goto exit; - } - if (!noptargs) { - goto skip_optional_pos; - } - type = _PyLong_AsInt(args[0]); - if (type == -1 && PyErr_Occurred()) { + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:MessageBeep", _keywords, + &type)) goto exit; - } -skip_optional_pos: return_value = winsound_MessageBeep_impl(module, type); exit: return return_value; } -/*[clinic end generated code: output=f70b7730127208d8 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=18a3771b34cdf97d input=a9049054013a1b77]*/ diff --git a/PC/config.c b/PC/config.c index 88f69758aac764..5eff2f5b2310bb 100644 --- a/PC/config.c +++ b/PC/config.c @@ -22,6 +22,7 @@ extern PyObject* PyInit__sha1(void); extern PyObject* PyInit__sha2(void); extern PyObject* PyInit__sha3(void); extern PyObject* PyInit__statistics(void); +extern PyObject* PyInit__sysconfig(void); extern PyObject* PyInit__typing(void); extern PyObject* PyInit__blake2(void); extern PyObject* PyInit_time(void); @@ -36,15 +37,14 @@ extern PyObject* PyInit__weakref(void); extern PyObject* PyInit_xxsubtype(void); extern PyObject* PyInit__xxsubinterpreters(void); extern PyObject* PyInit__xxinterpchannels(void); +extern PyObject* PyInit__xxinterpqueues(void); extern PyObject* PyInit__random(void); extern PyObject* PyInit_itertools(void); extern PyObject* PyInit__collections(void); extern PyObject* PyInit__heapq(void); extern PyObject* PyInit__bisect(void); extern PyObject* PyInit__symtable(void); -#if defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_GAMES) extern PyObject* PyInit_mmap(void); -#endif extern PyObject* PyInit__csv(void); extern PyObject* PyInit__sre(void); #if defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_SYSTEM) || defined(MS_WINDOWS_GAMES) @@ -102,6 +102,7 @@ struct _inittab _PyImport_Inittab[] = { {"_sha2", PyInit__sha2}, {"_sha3", PyInit__sha3}, {"_blake2", PyInit__blake2}, + {"_sysconfig", PyInit__sysconfig}, {"time", PyInit_time}, {"_thread", PyInit__thread}, {"_tokenize", PyInit__tokenize}, @@ -140,6 +141,7 @@ struct _inittab _PyImport_Inittab[] = { {"xxsubtype", PyInit_xxsubtype}, {"_xxsubinterpreters", PyInit__xxsubinterpreters}, {"_xxinterpchannels", PyInit__xxinterpchannels}, + {"_xxinterpqueues", PyInit__xxinterpqueues}, #ifdef _Py_HAVE_ZLIB {"zlib", PyInit_zlib}, #endif diff --git a/PC/launcher2.c b/PC/launcher2.c index bb500d4b6bfb07..2a8f8a101fc8a6 100644 --- a/PC/launcher2.c +++ b/PC/launcher2.c @@ -195,6 +195,13 @@ join(wchar_t *buffer, size_t bufferLength, const wchar_t *fragment) } +bool +split_parent(wchar_t *buffer, size_t bufferLength) +{ + return SUCCEEDED(PathCchRemoveFileSpec(buffer, bufferLength)); +} + + int _compare(const wchar_t *x, int xLen, const wchar_t *y, int yLen) { @@ -414,8 +421,8 @@ typedef struct { // if true, treats 'tag' as a non-PEP 514 filter bool oldStyleTag; // if true, ignores 'tag' when a high priority environment is found - // gh-92817: This is currently set when a tag is read from configuration or - // the environment, rather than the command line or a shebang line, and the + // gh-92817: This is currently set when a tag is read from configuration, + // the environment, or a shebang, rather than the command line, and the // only currently possible high priority environment is an active virtual // environment bool lowPriorityTag; @@ -431,7 +438,7 @@ typedef struct { bool list; // if true, only list detected runtimes with paths without launching bool listPaths; - // if true, display help message before contiuning + // if true, display help message before continuing bool help; // if set, limits search to registry keys with the specified Company // This is intended for debugging and testing only @@ -794,6 +801,8 @@ searchPath(SearchInfo *search, const wchar_t *shebang, int shebangLength) } } + debug(L"# Search PATH for %s\n", filename); + wchar_t pathVariable[MAXLEN]; int n = GetEnvironmentVariableW(L"PATH", pathVariable, MAXLEN); if (!n) { @@ -1031,8 +1040,11 @@ checkShebang(SearchInfo *search) debug(L"Shebang: %s\n", shebang); // Handle shebangs that we should search PATH for + int executablePathWasSetByUsrBinEnv = 0; exitCode = searchPath(search, shebang, shebangLength); - if (exitCode != RC_NO_SHEBANG) { + if (exitCode == 0) { + executablePathWasSetByUsrBinEnv = 1; + } else if (exitCode != RC_NO_SHEBANG) { return exitCode; } @@ -1067,7 +1079,7 @@ checkShebang(SearchInfo *search) search->tagLength = commandLength; // If we had 'python3.12.exe' then we want to strip the suffix // off of the tag - if (search->tagLength > 4) { + if (search->tagLength >= 4) { const wchar_t *suffix = &search->tag[search->tagLength - 4]; if (0 == _comparePath(suffix, 4, L".exe", -1)) { search->tagLength -= 4; @@ -1075,13 +1087,14 @@ checkShebang(SearchInfo *search) } // If we had 'python3_d' then we want to strip the '_d' (any // '.exe' is already gone) - if (search->tagLength > 2) { + if (search->tagLength >= 2) { const wchar_t *suffix = &search->tag[search->tagLength - 2]; if (0 == _comparePath(suffix, 2, L"_d", -1)) { search->tagLength -= 2; } } search->oldStyleTag = true; + search->lowPriorityTag = true; search->executableArgs = &command[commandLength]; search->executableArgsLength = shebangLength - commandLength; if (search->tag && search->tagLength) { @@ -1095,6 +1108,11 @@ checkShebang(SearchInfo *search) } } + // Didn't match a template, but we found it on PATH + if (executablePathWasSetByUsrBinEnv) { + return 0; + } + // Unrecognised executables are first tried as command aliases commandLength = 0; while (commandLength < shebangLength && !isspace(shebang[commandLength])) { @@ -1765,7 +1783,15 @@ virtualenvSearch(const SearchInfo *search, EnvironmentInfo **result) return 0; } - if (INVALID_FILE_ATTRIBUTES == GetFileAttributesW(buffer)) { + DWORD attr = GetFileAttributesW(buffer); + if (INVALID_FILE_ATTRIBUTES == attr && search->lowPriorityTag) { + if (!split_parent(buffer, MAXLEN) || !join(buffer, MAXLEN, L"python.exe")) { + return 0; + } + attr = GetFileAttributesW(buffer); + } + + if (INVALID_FILE_ATTRIBUTES == attr) { debug(L"Python executable %s missing from virtual env\n", buffer); return 0; } diff --git a/PC/layout/main.py b/PC/layout/main.py index cb2e4878da26b1..accfd51dd978fb 100644 --- a/PC/layout/main.py +++ b/PC/layout/main.py @@ -73,7 +73,10 @@ def copy_if_modified(src, dest): ) if do_copy: - shutil.copy2(src, dest) + try: + shutil.copy2(src, dest) + except FileNotFoundError: + raise FileNotFoundError(src) from None def get_lib_layout(ns): @@ -208,8 +211,7 @@ def _c(d): for dest, src in rglob(ns.source / "Include", "**/*.h"): yield "include/{}".format(dest), src - src = ns.source / "PC" / "pyconfig.h" - yield "include/pyconfig.h", src + yield "include/pyconfig.h", ns.build / "pyconfig.h" for dest, src in get_tcltk_lib(ns): yield dest, src diff --git a/PC/msvcrtmodule.c b/PC/msvcrtmodule.c index afc810adcf7499..5ff703217b421f 100644 --- a/PC/msvcrtmodule.c +++ b/PC/msvcrtmodule.c @@ -38,13 +38,14 @@ class HANDLE_converter(CConverter): type = 'void *' format_unit = '"_Py_PARSE_UINTPTR"' - def parse_arg(self, argname, displayname): - return """ + def parse_arg(self, argname, displayname, *, limited_capi): + return self.format_code(""" {paramname} = PyLong_AsVoidPtr({argname}); if (!{paramname} && PyErr_Occurred()) {{{{ goto exit; }}}} - """.format(argname=argname, paramname=self.parser_name) + """, + argname=argname) class HANDLE_return_converter(CReturnConverter): type = 'void *' @@ -74,7 +75,7 @@ class wchar_t_return_converter(CReturnConverter): data.return_conversion.append( 'return_value = PyUnicode_FromOrdinal(_return_value);\n') [python start generated code]*/ -/*[python end generated code: output=da39a3ee5e6b4b0d input=1e8e9fa3538ec08f]*/ +/*[python end generated code: output=da39a3ee5e6b4b0d input=ff031be44ab3250d]*/ /*[clinic input] module msvcrt @@ -219,12 +220,12 @@ msvcrt_get_osfhandle_impl(PyObject *module, int fd) /*[clinic input] msvcrt.kbhit -> long -Return true if a keypress is waiting to be read. +Returns a nonzero value if a keypress is waiting to be read. Otherwise, return 0. [clinic start generated code]*/ static long msvcrt_kbhit_impl(PyObject *module) -/*[clinic end generated code: output=940dfce6587c1890 input=e70d678a5c2f6acc]*/ +/*[clinic end generated code: output=940dfce6587c1890 input=d0f4cb3289ff51e2]*/ { return _kbhit(); } @@ -614,6 +615,10 @@ exec_module(PyObject* m) INSERTPTR(m, "CRTDBG_FILE_STDERR", _CRTDBG_FILE_STDERR); INSERTPTR(m, "CRTDBG_FILE_STDOUT", _CRTDBG_FILE_STDOUT); INSERTPTR(m, "CRTDBG_REPORT_FILE", _CRTDBG_REPORT_FILE); + INSERTINT(m, "OUT_TO_DEFAULT", _OUT_TO_DEFAULT); + INSERTINT(m, "OUT_TO_STDERR", _OUT_TO_STDERR); + INSERTINT(m, "OUT_TO_MSGBOX", _OUT_TO_MSGBOX); + INSERTINT(m, "REPORT_ERRMODE", _REPORT_ERRMODE); #endif #undef INSERTINT diff --git a/PC/pyconfig.h b/PC/pyconfig.h deleted file mode 100644 index ac20129cd30fcc..00000000000000 --- a/PC/pyconfig.h +++ /dev/null @@ -1,739 +0,0 @@ -#ifndef Py_CONFIG_H -#define Py_CONFIG_H - -/* pyconfig.h. NOT Generated automatically by configure. - -This is a manually maintained version used for the Watcom, -Borland and Microsoft Visual C++ compilers. It is a -standard part of the Python distribution. - -WINDOWS DEFINES: -The code specific to Windows should be wrapped around one of -the following #defines - -MS_WIN64 - Code specific to the MS Win64 API -MS_WIN32 - Code specific to the MS Win32 (and Win64) API (obsolete, this covers all supported APIs) -MS_WINDOWS - Code specific to Windows, but all versions. -Py_ENABLE_SHARED - Code if the Python core is built as a DLL. - -Also note that neither "_M_IX86" or "_MSC_VER" should be used for -any purpose other than "Windows Intel x86 specific" and "Microsoft -compiler specific". Therefore, these should be very rare. - - -NOTE: The following symbols are deprecated: -NT, USE_DL_EXPORT, USE_DL_IMPORT, DL_EXPORT, DL_IMPORT -MS_CORE_DLL. - -WIN32 is still required for the locale module. - -*/ - -/* Deprecated USE_DL_EXPORT macro - please use Py_BUILD_CORE */ -#ifdef USE_DL_EXPORT -# define Py_BUILD_CORE -#endif /* USE_DL_EXPORT */ - -/* Visual Studio 2005 introduces deprecation warnings for - "insecure" and POSIX functions. The insecure functions should - be replaced by *_s versions (according to Microsoft); the - POSIX functions by _* versions (which, according to Microsoft, - would be ISO C conforming). Neither renaming is feasible, so - we just silence the warnings. */ - -#ifndef _CRT_SECURE_NO_DEPRECATE -#define _CRT_SECURE_NO_DEPRECATE 1 -#endif -#ifndef _CRT_NONSTDC_NO_DEPRECATE -#define _CRT_NONSTDC_NO_DEPRECATE 1 -#endif - -#define HAVE_IO_H -#define HAVE_SYS_UTIME_H -#define HAVE_TEMPNAM -#define HAVE_TMPFILE -#define HAVE_TMPNAM -#define HAVE_CLOCK -#define HAVE_STRERROR - -#include - -#define HAVE_STRFTIME -#define DONT_HAVE_SIG_ALARM -#define DONT_HAVE_SIG_PAUSE -#define LONG_BIT 32 -#define WORD_BIT 32 - -#define MS_WIN32 /* only support win32 and greater. */ -#define MS_WINDOWS -#define NT_THREADS -#define WITH_THREAD -#ifndef NETSCAPE_PI -#define USE_SOCKET -#endif - -#if defined(Py_BUILD_CORE) || defined(Py_BUILD_CORE_BUILTIN) || defined(Py_BUILD_CORE_MODULE) -#include - -#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) -#define MS_WINDOWS_DESKTOP -#endif -#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) -#define MS_WINDOWS_APP -#endif -#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_SYSTEM) -#define MS_WINDOWS_SYSTEM -#endif -#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_GAMES) -#define MS_WINDOWS_GAMES -#endif - -/* Define to 1 if you support windows console io */ -#if defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_APP) || defined(MS_WINDOWS_SYSTEM) -#define HAVE_WINDOWS_CONSOLE_IO 1 -#endif -#endif /* Py_BUILD_CORE || Py_BUILD_CORE_BUILTIN || Py_BUILD_CORE_MODULE */ - -/* Compiler specific defines */ - -/* ------------------------------------------------------------------------*/ -/* Microsoft C defines _MSC_VER, as does clang-cl.exe */ -#ifdef _MSC_VER - -/* We want COMPILER to expand to a string containing _MSC_VER's *value*. - * This is horridly tricky, because the stringization operator only works - * on macro arguments, and doesn't evaluate macros passed *as* arguments. - */ -#define _Py_PASTE_VERSION(SUFFIX) \ - ("[MSC v." _Py_STRINGIZE(_MSC_VER) " " SUFFIX "]") -/* e.g., this produces, after compile-time string catenation, - * ("[MSC v.1900 64 bit (Intel)]") - * - * _Py_STRINGIZE(_MSC_VER) expands to - * _Py_STRINGIZE1(_MSC_VER) and this second macro call is scanned - * again for macros and so further expands to - * _Py_STRINGIZE1(1900) which then expands to - * "1900" - */ -#define _Py_STRINGIZE(X) _Py_STRINGIZE1(X) -#define _Py_STRINGIZE1(X) #X - -/* MSVC defines _WINxx to differentiate the windows platform types - - Note that for compatibility reasons _WIN32 is defined on Win32 - *and* on Win64. For the same reasons, in Python, MS_WIN32 is - defined on Win32 *and* Win64. Win32 only code must therefore be - guarded as follows: - #if defined(MS_WIN32) && !defined(MS_WIN64) -*/ -#ifdef _WIN64 -#define MS_WIN64 -#endif - -/* set the COMPILER and support tier - * - * win_amd64 MSVC (x86_64-pc-windows-msvc): 1 - * win32 MSVC (i686-pc-windows-msvc): 1 - * win_arm64 MSVC (aarch64-pc-windows-msvc): 3 - * other archs and ICC: 0 - */ -#ifdef MS_WIN64 -#if defined(_M_X64) || defined(_M_AMD64) -#if defined(__clang__) -#define COMPILER ("[Clang " __clang_version__ "] 64 bit (AMD64) with MSC v." _Py_STRINGIZE(_MSC_VER) " CRT]") -#define PY_SUPPORT_TIER 0 -#elif defined(__INTEL_COMPILER) -#define COMPILER ("[ICC v." _Py_STRINGIZE(__INTEL_COMPILER) " 64 bit (amd64) with MSC v." _Py_STRINGIZE(_MSC_VER) " CRT]") -#define PY_SUPPORT_TIER 0 -#else -#define COMPILER _Py_PASTE_VERSION("64 bit (AMD64)") -#define PY_SUPPORT_TIER 1 -#endif /* __clang__ */ -#define PYD_PLATFORM_TAG "win_amd64" -#elif defined(_M_ARM64) -#define COMPILER _Py_PASTE_VERSION("64 bit (ARM64)") -#define PY_SUPPORT_TIER 3 -#define PYD_PLATFORM_TAG "win_arm64" -#else -#define COMPILER _Py_PASTE_VERSION("64 bit (Unknown)") -#define PY_SUPPORT_TIER 0 -#endif -#endif /* MS_WIN64 */ - -/* set the version macros for the windows headers */ -/* Python 3.9+ requires Windows 8 or greater */ -#define Py_WINVER 0x0602 /* _WIN32_WINNT_WIN8 */ -#define Py_NTDDI NTDDI_WIN8 - -/* We only set these values when building Python - we don't want to force - these values on extensions, as that will affect the prototypes and - structures exposed in the Windows headers. Even when building Python, we - allow a single source file to override this - they may need access to - structures etc so it can optionally use new Windows features if it - determines at runtime they are available. -*/ -#if defined(Py_BUILD_CORE) || defined(Py_BUILD_CORE_BUILTIN) || defined(Py_BUILD_CORE_MODULE) -#ifndef NTDDI_VERSION -#define NTDDI_VERSION Py_NTDDI -#endif -#ifndef WINVER -#define WINVER Py_WINVER -#endif -#ifndef _WIN32_WINNT -#define _WIN32_WINNT Py_WINVER -#endif -#endif - -/* _W64 is not defined for VC6 or eVC4 */ -#ifndef _W64 -#define _W64 -#endif - -/* Define like size_t, omitting the "unsigned" */ -#ifdef MS_WIN64 -typedef __int64 Py_ssize_t; -# define PY_SSIZE_T_MAX LLONG_MAX -#else -typedef _W64 int Py_ssize_t; -# define PY_SSIZE_T_MAX INT_MAX -#endif -#define HAVE_PY_SSIZE_T 1 - -#if defined(MS_WIN32) && !defined(MS_WIN64) -#if defined(_M_IX86) -#if defined(__clang__) -#define COMPILER ("[Clang " __clang_version__ "] 32 bit (Intel) with MSC v." _Py_STRINGIZE(_MSC_VER) " CRT]") -#define PY_SUPPORT_TIER 0 -#elif defined(__INTEL_COMPILER) -#define COMPILER ("[ICC v." _Py_STRINGIZE(__INTEL_COMPILER) " 32 bit (Intel) with MSC v." _Py_STRINGIZE(_MSC_VER) " CRT]") -#define PY_SUPPORT_TIER 0 -#else -#define COMPILER _Py_PASTE_VERSION("32 bit (Intel)") -#define PY_SUPPORT_TIER 1 -#endif /* __clang__ */ -#define PYD_PLATFORM_TAG "win32" -#elif defined(_M_ARM) -#define COMPILER _Py_PASTE_VERSION("32 bit (ARM)") -#define PYD_PLATFORM_TAG "win_arm32" -#define PY_SUPPORT_TIER 0 -#else -#define COMPILER _Py_PASTE_VERSION("32 bit (Unknown)") -#define PY_SUPPORT_TIER 0 -#endif -#endif /* MS_WIN32 && !MS_WIN64 */ - -typedef int pid_t; - -/* define some ANSI types that are not defined in earlier Win headers */ -#if _MSC_VER >= 1200 -/* This file only exists in VC 6.0 or higher */ -#include -#endif - -#endif /* _MSC_VER */ - -/* ------------------------------------------------------------------------*/ -/* mingw and mingw-w64 define __MINGW32__ */ -#ifdef __MINGW32__ - -#ifdef _WIN64 -#define MS_WIN64 -#endif - -#endif /* __MINGW32__*/ - -/* ------------------------------------------------------------------------*/ -/* egcs/gnu-win32 defines __GNUC__ and _WIN32 */ -#if defined(__GNUC__) && defined(_WIN32) -/* XXX These defines are likely incomplete, but should be easy to fix. - They should be complete enough to build extension modules. */ -/* Suggested by Rene Liebscher to avoid a GCC 2.91.* - bug that requires structure imports. More recent versions of the - compiler don't exhibit this bug. -*/ -#if (__GNUC__==2) && (__GNUC_MINOR__<=91) -#warning "Please use an up-to-date version of gcc! (>2.91 recommended)" -#endif - -#define COMPILER "[gcc]" -#define PY_LONG_LONG long long -#define PY_LLONG_MIN LLONG_MIN -#define PY_LLONG_MAX LLONG_MAX -#define PY_ULLONG_MAX ULLONG_MAX -#endif /* GNUC */ - -/* ------------------------------------------------------------------------*/ -/* lcc-win32 defines __LCC__ */ -#if defined(__LCC__) -/* XXX These defines are likely incomplete, but should be easy to fix. - They should be complete enough to build extension modules. */ - -#define COMPILER "[lcc-win32]" -typedef int pid_t; -/* __declspec() is supported here too - do nothing to get the defaults */ - -#endif /* LCC */ - -/* ------------------------------------------------------------------------*/ -/* End of compilers - finish up */ - -#ifndef NO_STDIO_H -# include -#endif - -/* 64 bit ints are usually spelt __int64 unless compiler has overridden */ -#ifndef PY_LONG_LONG -# define PY_LONG_LONG __int64 -# define PY_LLONG_MAX _I64_MAX -# define PY_LLONG_MIN _I64_MIN -# define PY_ULLONG_MAX _UI64_MAX -#endif - -/* For Windows the Python core is in a DLL by default. Test -Py_NO_ENABLE_SHARED to find out. Also support MS_NO_COREDLL for b/w compat */ -#if !defined(MS_NO_COREDLL) && !defined(Py_NO_ENABLE_SHARED) -# define Py_ENABLE_SHARED 1 /* standard symbol for shared library */ -# define MS_COREDLL /* deprecated old symbol */ -#endif /* !MS_NO_COREDLL && ... */ - -/* All windows compilers that use this header support __declspec */ -#define HAVE_DECLSPEC_DLL - -/* For an MSVC DLL, we can nominate the .lib files used by extensions */ -#ifdef MS_COREDLL -# if !defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_BUILTIN) - /* not building the core - must be an ext */ -# if defined(_MSC_VER) - /* So MSVC users need not specify the .lib - file in their Makefile (other compilers are - generally taken care of by distutils.) */ -# if defined(_DEBUG) -# pragma comment(lib,"python313_d.lib") -# elif defined(Py_LIMITED_API) -# pragma comment(lib,"python3.lib") -# else -# pragma comment(lib,"python313.lib") -# endif /* _DEBUG */ -# endif /* _MSC_VER */ -# endif /* Py_BUILD_CORE */ -#endif /* MS_COREDLL */ - -#ifdef MS_WIN64 -/* maintain "win32" sys.platform for backward compatibility of Python code, - the Win64 API should be close enough to the Win32 API to make this - preferable */ -# define PLATFORM "win32" -# define SIZEOF_VOID_P 8 -# define SIZEOF_TIME_T 8 -# define SIZEOF_OFF_T 4 -# define SIZEOF_FPOS_T 8 -# define SIZEOF_HKEY 8 -# define SIZEOF_SIZE_T 8 -# define ALIGNOF_SIZE_T 8 -# define ALIGNOF_MAX_ALIGN_T 8 -/* configure.ac defines HAVE_LARGEFILE_SUPPORT iff - sizeof(off_t) > sizeof(long), and sizeof(long long) >= sizeof(off_t). - On Win64 the second condition is not true, but if fpos_t replaces off_t - then this is true. The uses of HAVE_LARGEFILE_SUPPORT imply that Win64 - should define this. */ -# define HAVE_LARGEFILE_SUPPORT -#elif defined(MS_WIN32) -# define PLATFORM "win32" -# define HAVE_LARGEFILE_SUPPORT -# define SIZEOF_VOID_P 4 -# define SIZEOF_OFF_T 4 -# define SIZEOF_FPOS_T 8 -# define SIZEOF_HKEY 4 -# define SIZEOF_SIZE_T 4 -# define ALIGNOF_SIZE_T 4 - /* MS VS2005 changes time_t to a 64-bit type on all platforms */ -# if defined(_MSC_VER) && _MSC_VER >= 1400 -# define SIZEOF_TIME_T 8 -# else -# define SIZEOF_TIME_T 4 -# endif -# define ALIGNOF_MAX_ALIGN_T 8 -#endif - -#ifdef _DEBUG -# define Py_DEBUG -#endif - - -#ifdef MS_WIN32 - -#define SIZEOF_SHORT 2 -#define SIZEOF_INT 4 -#define SIZEOF_LONG 4 -#define ALIGNOF_LONG 4 -#define SIZEOF_LONG_LONG 8 -#define SIZEOF_DOUBLE 8 -#define SIZEOF_FLOAT 4 - -/* VC 7.1 has them and VC 6.0 does not. VC 6.0 has a version number of 1200. - Microsoft eMbedded Visual C++ 4.0 has a version number of 1201 and doesn't - define these. - If some compiler does not provide them, modify the #if appropriately. */ -#if defined(_MSC_VER) -#if _MSC_VER > 1300 -#define HAVE_UINTPTR_T 1 -#define HAVE_INTPTR_T 1 -#else -/* VC6, VS 2002 and eVC4 don't support the C99 LL suffix for 64-bit integer literals */ -#define Py_LL(x) x##I64 -#endif /* _MSC_VER > 1300 */ -#endif /* _MSC_VER */ - -#endif - -/* define signed and unsigned exact-width 32-bit and 64-bit types, used in the - implementation of Python integers. */ -#define PY_UINT32_T uint32_t -#define PY_UINT64_T uint64_t -#define PY_INT32_T int32_t -#define PY_INT64_T int64_t - -/* Fairly standard from here! */ - -/* Define if on AIX 3. - System headers sometimes define this. - We just want to avoid a redefinition error message. */ -#ifndef _ALL_SOURCE -/* #undef _ALL_SOURCE */ -#endif - -/* Define to empty if the keyword does not work. */ -/* #define const */ - -/* Define to 1 if you have the header file. */ -#define HAVE_CONIO_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_DIRECT_H 1 - -/* Define to 1 if you have the declaration of `tzname', and to 0 if you don't. - */ -#define HAVE_DECL_TZNAME 1 - -/* Define if you have dirent.h. */ -/* #define DIRENT 1 */ - -/* Define to the type of elements in the array set by `getgroups'. - Usually this is either `int' or `gid_t'. */ -/* #undef GETGROUPS_T */ - -/* Define to `int' if doesn't define. */ -/* #undef gid_t */ - -/* Define if your struct tm has tm_zone. */ -/* #undef HAVE_TM_ZONE */ - -/* Define if you don't have tm_zone but do have the external array - tzname. */ -#define HAVE_TZNAME - -/* Define to `int' if doesn't define. */ -/* #undef mode_t */ - -/* Define if you don't have dirent.h, but have ndir.h. */ -/* #undef NDIR */ - -/* Define to `long' if doesn't define. */ -/* #undef off_t */ - -/* Define to `int' if doesn't define. */ -/* #undef pid_t */ - -/* Define if the system does not provide POSIX.1 features except - with this defined. */ -/* #undef _POSIX_1_SOURCE */ - -/* Define if you need to in order for stat and other things to work. */ -/* #undef _POSIX_SOURCE */ - -/* Define as the return type of signal handlers (int or void). */ -#define RETSIGTYPE void - -/* Define to `unsigned' if doesn't define. */ -/* #undef size_t */ - -/* Define if you have the ANSI C header files. */ -#define STDC_HEADERS 1 - -/* Define if you don't have dirent.h, but have sys/dir.h. */ -/* #undef SYSDIR */ - -/* Define if you don't have dirent.h, but have sys/ndir.h. */ -/* #undef SYSNDIR */ - -/* Define if you can safely include both and . */ -/* #undef TIME_WITH_SYS_TIME */ - -/* Define if your declares struct tm. */ -/* #define TM_IN_SYS_TIME 1 */ - -/* Define to `int' if doesn't define. */ -/* #undef uid_t */ - -/* Define if the closedir function returns void instead of int. */ -/* #undef VOID_CLOSEDIR */ - -/* Define if getpgrp() must be called as getpgrp(0) - and (consequently) setpgrp() as setpgrp(0, 0). */ -/* #undef GETPGRP_HAVE_ARGS */ - -/* Define this if your time.h defines altzone */ -/* #define HAVE_ALTZONE */ - -/* Define if you have the putenv function. */ -#define HAVE_PUTENV - -/* Define if your compiler supports function prototypes */ -#define HAVE_PROTOTYPES - -/* Define if you can safely include both and - (which you can't on SCO ODT 3.0). */ -/* #undef SYS_SELECT_WITH_SYS_TIME */ - -/* Define if you want build the _decimal module using a coroutine-local rather - than a thread-local context */ -#define WITH_DECIMAL_CONTEXTVAR 1 - -/* Define if you want documentation strings in extension modules */ -#define WITH_DOC_STRINGS 1 - -/* Define if you want to compile in rudimentary thread support */ -/* #undef WITH_THREAD */ - -/* Define if you want to use the GNU readline library */ -/* #define WITH_READLINE 1 */ - -/* Use Python's own small-block memory-allocator. */ -#define WITH_PYMALLOC 1 - -/* Define if you want to compile in object freelists optimization */ -#define WITH_FREELISTS 1 - -/* Define if you have clock. */ -/* #define HAVE_CLOCK */ - -/* Define when any dynamic module loading is enabled */ -#define HAVE_DYNAMIC_LOADING - -/* Define if you have ftime. */ -#define HAVE_FTIME - -/* Define if you have getpeername. */ -#define HAVE_GETPEERNAME - -/* Define if you have getpgrp. */ -/* #undef HAVE_GETPGRP */ - -/* Define if you have getpid. */ -#define HAVE_GETPID - -/* Define if you have gettimeofday. */ -/* #undef HAVE_GETTIMEOFDAY */ - -/* Define if you have getwd. */ -/* #undef HAVE_GETWD */ - -/* Define if you have lstat. */ -/* #undef HAVE_LSTAT */ - -/* Define if you have the mktime function. */ -#define HAVE_MKTIME - -/* Define if you have nice. */ -/* #undef HAVE_NICE */ - -/* Define if you have readlink. */ -/* #undef HAVE_READLINK */ - -/* Define if you have setpgid. */ -/* #undef HAVE_SETPGID */ - -/* Define if you have setpgrp. */ -/* #undef HAVE_SETPGRP */ - -/* Define if you have setsid. */ -/* #undef HAVE_SETSID */ - -/* Define if you have setvbuf. */ -#define HAVE_SETVBUF - -/* Define if you have siginterrupt. */ -/* #undef HAVE_SIGINTERRUPT */ - -/* Define to 1 if you have the `shutdown' function. */ -#define HAVE_SHUTDOWN 1 - -/* Define if you have symlink. */ -/* #undef HAVE_SYMLINK */ - -/* Define if you have tcgetpgrp. */ -/* #undef HAVE_TCGETPGRP */ - -/* Define if you have tcsetpgrp. */ -/* #undef HAVE_TCSETPGRP */ - -/* Define if you have times. */ -/* #undef HAVE_TIMES */ - -/* Define to 1 if you have the `umask' function. */ -#define HAVE_UMASK 1 - -/* Define if you have uname. */ -/* #undef HAVE_UNAME */ - -/* Define if you have waitpid. */ -/* #undef HAVE_WAITPID */ - -/* Define to 1 if you have the `wcsftime' function. */ -#if defined(_MSC_VER) && _MSC_VER >= 1310 -#define HAVE_WCSFTIME 1 -#endif - -/* Define to 1 if you have the `wcscoll' function. */ -#define HAVE_WCSCOLL 1 - -/* Define to 1 if you have the `wcsxfrm' function. */ -#define HAVE_WCSXFRM 1 - -/* Define if the zlib library has inflateCopy */ -#define HAVE_ZLIB_COPY 1 - -/* Define if you have the header file. */ -/* #undef HAVE_DLFCN_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_ERRNO_H 1 - -/* Define if you have the header file. */ -#define HAVE_FCNTL_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_PROCESS_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SIGNAL_H 1 - -/* Define if you have the header file. */ -#define HAVE_STDDEF_H 1 - -/* Define if you have the header file. */ -/* #undef HAVE_SYS_AUDIOIO_H */ - -/* Define if you have the header file. */ -/* #define HAVE_SYS_PARAM_H 1 */ - -/* Define if you have the header file. */ -/* #define HAVE_SYS_SELECT_H 1 */ - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_STAT_H 1 - -/* Define if you have the header file. */ -/* #define HAVE_SYS_TIME_H 1 */ - -/* Define if you have the header file. */ -/* #define HAVE_SYS_TIMES_H 1 */ - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_TYPES_H 1 - -/* Define if you have the header file. */ -/* #define HAVE_SYS_UN_H 1 */ - -/* Define if you have the header file. */ -/* #define HAVE_SYS_UTIME_H 1 */ - -/* Define if you have the header file. */ -/* #define HAVE_SYS_UTSNAME_H 1 */ - -/* Define if you have the header file. */ -/* #define HAVE_UNISTD_H 1 */ - -/* Define if you have the header file. */ -/* #define HAVE_UTIME_H 1 */ - -/* Define if the compiler provides a wchar.h header file. */ -#define HAVE_WCHAR_H 1 - -/* The size of `wchar_t', as computed by sizeof. */ -#define SIZEOF_WCHAR_T 2 - -/* The size of `_Bool', as computed by sizeof. */ -#define SIZEOF__BOOL 1 - -/* The size of `pid_t', as computed by sizeof. */ -#define SIZEOF_PID_T SIZEOF_INT - -/* Define if you have the dl library (-ldl). */ -/* #undef HAVE_LIBDL */ - -/* Define if you have the mpc library (-lmpc). */ -/* #undef HAVE_LIBMPC */ - -/* Define if you have the seq library (-lseq). */ -/* #undef HAVE_LIBSEQ */ - -/* Define if you have the socket library (-lsocket). */ -#define HAVE_LIBSOCKET 1 - -/* Define if you have the sun library (-lsun). */ -/* #undef HAVE_LIBSUN */ - -/* Define if you have the termcap library (-ltermcap). */ -/* #undef HAVE_LIBTERMCAP */ - -/* Define if you have the termlib library (-ltermlib). */ -/* #undef HAVE_LIBTERMLIB */ - -/* Define if you have the thread library (-lthread). */ -/* #undef HAVE_LIBTHREAD */ - -/* WinSock does not use a bitmask in select, and uses - socket handles greater than FD_SETSIZE */ -#define Py_SOCKET_FD_CAN_BE_GE_FD_SETSIZE - -/* Define if C doubles are 64-bit IEEE 754 binary format, stored with the - least significant byte first */ -#define DOUBLE_IS_LITTLE_ENDIAN_IEEE754 1 - -/* Define to 1 if you have the `erf' function. */ -#define HAVE_ERF 1 - -/* Define to 1 if you have the `erfc' function. */ -#define HAVE_ERFC 1 - -// netdb.h functions (provided by winsock.h) -#define HAVE_GETHOSTNAME 1 -#define HAVE_GETHOSTBYADDR 1 -#define HAVE_GETHOSTBYNAME 1 -#define HAVE_GETPROTOBYNAME 1 -#define HAVE_GETSERVBYNAME 1 -#define HAVE_GETSERVBYPORT 1 -// sys/socket.h functions (provided by winsock.h) -#define HAVE_INET_PTON 1 -#define HAVE_INET_NTOA 1 -#define HAVE_ACCEPT 1 -#define HAVE_BIND 1 -#define HAVE_CONNECT 1 -#define HAVE_GETSOCKNAME 1 -#define HAVE_LISTEN 1 -#define HAVE_RECVFROM 1 -#define HAVE_SENDTO 1 -#define HAVE_SETSOCKOPT 1 -#define HAVE_SOCKET 1 - -/* Define to 1 if you have the `dup' function. */ -#define HAVE_DUP 1 - -/* framework name */ -#define _PYTHONFRAMEWORK "" - -/* Define if libssl has X509_VERIFY_PARAM_set1_host and related function */ -#define HAVE_X509_VERIFY_PARAM_SET1_HOST 1 - -#endif /* !Py_CONFIG_H */ diff --git a/PC/pyconfig.h.in b/PC/pyconfig.h.in new file mode 100644 index 00000000000000..d8f0a6be69c21a --- /dev/null +++ b/PC/pyconfig.h.in @@ -0,0 +1,745 @@ +#ifndef Py_CONFIG_H +#define Py_CONFIG_H + +/* pyconfig.h. NOT Generated automatically by configure. + +This is a manually maintained version used for the Watcom, +Borland and Microsoft Visual C++ compilers. It is a +standard part of the Python distribution. + +WINDOWS DEFINES: +The code specific to Windows should be wrapped around one of +the following #defines + +MS_WIN64 - Code specific to the MS Win64 API +MS_WIN32 - Code specific to the MS Win32 (and Win64) API (obsolete, this covers all supported APIs) +MS_WINDOWS - Code specific to Windows, but all versions. +Py_ENABLE_SHARED - Code if the Python core is built as a DLL. + +Also note that neither "_M_IX86" or "_MSC_VER" should be used for +any purpose other than "Windows Intel x86 specific" and "Microsoft +compiler specific". Therefore, these should be very rare. + + +NOTE: The following symbols are deprecated: +NT, USE_DL_EXPORT, USE_DL_IMPORT, DL_EXPORT, DL_IMPORT +MS_CORE_DLL. + +WIN32 is still required for the locale module. + +*/ + +/* Deprecated USE_DL_EXPORT macro - please use Py_BUILD_CORE */ +#ifdef USE_DL_EXPORT +# define Py_BUILD_CORE +#endif /* USE_DL_EXPORT */ + +/* Visual Studio 2005 introduces deprecation warnings for + "insecure" and POSIX functions. The insecure functions should + be replaced by *_s versions (according to Microsoft); the + POSIX functions by _* versions (which, according to Microsoft, + would be ISO C conforming). Neither renaming is feasible, so + we just silence the warnings. */ + +#ifndef _CRT_SECURE_NO_DEPRECATE +#define _CRT_SECURE_NO_DEPRECATE 1 +#endif +#ifndef _CRT_NONSTDC_NO_DEPRECATE +#define _CRT_NONSTDC_NO_DEPRECATE 1 +#endif + +#define HAVE_IO_H +#define HAVE_SYS_UTIME_H +#define HAVE_TEMPNAM +#define HAVE_TMPFILE +#define HAVE_TMPNAM +#define HAVE_CLOCK +#define HAVE_STRERROR + +#include + +#define HAVE_STRFTIME +#define DONT_HAVE_SIG_ALARM +#define DONT_HAVE_SIG_PAUSE +#define LONG_BIT 32 +#define WORD_BIT 32 + +#define MS_WIN32 /* only support win32 and greater. */ +#define MS_WINDOWS +#define NT_THREADS +#define WITH_THREAD +#ifndef NETSCAPE_PI +#define USE_SOCKET +#endif + +#if defined(Py_BUILD_CORE) || defined(Py_BUILD_CORE_BUILTIN) || defined(Py_BUILD_CORE_MODULE) +#include + +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) +#define MS_WINDOWS_DESKTOP +#endif +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) +#define MS_WINDOWS_APP +#endif +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_SYSTEM) +#define MS_WINDOWS_SYSTEM +#endif +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_GAMES) +#define MS_WINDOWS_GAMES +#endif + +/* Define to 1 if you support windows console io */ +#if defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_APP) || defined(MS_WINDOWS_SYSTEM) +#define HAVE_WINDOWS_CONSOLE_IO 1 +#endif +#endif /* Py_BUILD_CORE || Py_BUILD_CORE_BUILTIN || Py_BUILD_CORE_MODULE */ + +/* Compiler specific defines */ + +/* ------------------------------------------------------------------------*/ +/* Microsoft C defines _MSC_VER, as does clang-cl.exe */ +#ifdef _MSC_VER + +/* We want COMPILER to expand to a string containing _MSC_VER's *value*. + * This is horridly tricky, because the stringization operator only works + * on macro arguments, and doesn't evaluate macros passed *as* arguments. + */ +#define _Py_PASTE_VERSION(SUFFIX) \ + ("[MSC v." _Py_STRINGIZE(_MSC_VER) " " SUFFIX "]") +/* e.g., this produces, after compile-time string catenation, + * ("[MSC v.1900 64 bit (Intel)]") + * + * _Py_STRINGIZE(_MSC_VER) expands to + * _Py_STRINGIZE1(_MSC_VER) and this second macro call is scanned + * again for macros and so further expands to + * _Py_STRINGIZE1(1900) which then expands to + * "1900" + */ +#define _Py_STRINGIZE(X) _Py_STRINGIZE1(X) +#define _Py_STRINGIZE1(X) #X + +/* MSVC defines _WINxx to differentiate the windows platform types + + Note that for compatibility reasons _WIN32 is defined on Win32 + *and* on Win64. For the same reasons, in Python, MS_WIN32 is + defined on Win32 *and* Win64. Win32 only code must therefore be + guarded as follows: + #if defined(MS_WIN32) && !defined(MS_WIN64) +*/ +#ifdef _WIN64 +#define MS_WIN64 +#endif + +/* set the COMPILER and support tier + * + * win_amd64 MSVC (x86_64-pc-windows-msvc): 1 + * win32 MSVC (i686-pc-windows-msvc): 1 + * win_arm64 MSVC (aarch64-pc-windows-msvc): 3 + * other archs and ICC: 0 + */ +#ifdef MS_WIN64 +#if defined(_M_X64) || defined(_M_AMD64) +#if defined(__clang__) +#define COMPILER ("[Clang " __clang_version__ "] 64 bit (AMD64) with MSC v." _Py_STRINGIZE(_MSC_VER) " CRT]") +#define PY_SUPPORT_TIER 0 +#elif defined(__INTEL_COMPILER) +#define COMPILER ("[ICC v." _Py_STRINGIZE(__INTEL_COMPILER) " 64 bit (amd64) with MSC v." _Py_STRINGIZE(_MSC_VER) " CRT]") +#define PY_SUPPORT_TIER 0 +#else +#define COMPILER _Py_PASTE_VERSION("64 bit (AMD64)") +#define PY_SUPPORT_TIER 1 +#endif /* __clang__ */ +#define PYD_PLATFORM_TAG "win_amd64" +#elif defined(_M_ARM64) +#define COMPILER _Py_PASTE_VERSION("64 bit (ARM64)") +#define PY_SUPPORT_TIER 3 +#define PYD_PLATFORM_TAG "win_arm64" +#else +#define COMPILER _Py_PASTE_VERSION("64 bit (Unknown)") +#define PY_SUPPORT_TIER 0 +#endif +#endif /* MS_WIN64 */ + +/* set the version macros for the windows headers */ +/* Python 3.9+ requires Windows 8 or greater */ +#define Py_WINVER 0x0602 /* _WIN32_WINNT_WIN8 */ +#define Py_NTDDI NTDDI_WIN8 + +/* We only set these values when building Python - we don't want to force + these values on extensions, as that will affect the prototypes and + structures exposed in the Windows headers. Even when building Python, we + allow a single source file to override this - they may need access to + structures etc so it can optionally use new Windows features if it + determines at runtime they are available. +*/ +#if defined(Py_BUILD_CORE) || defined(Py_BUILD_CORE_BUILTIN) || defined(Py_BUILD_CORE_MODULE) +#ifndef NTDDI_VERSION +#define NTDDI_VERSION Py_NTDDI +#endif +#ifndef WINVER +#define WINVER Py_WINVER +#endif +#ifndef _WIN32_WINNT +#define _WIN32_WINNT Py_WINVER +#endif +#endif + +/* _W64 is not defined for VC6 or eVC4 */ +#ifndef _W64 +#define _W64 +#endif + +/* Define like size_t, omitting the "unsigned" */ +#ifdef MS_WIN64 +typedef __int64 Py_ssize_t; +# define PY_SSIZE_T_MAX LLONG_MAX +#else +typedef _W64 int Py_ssize_t; +# define PY_SSIZE_T_MAX INT_MAX +#endif +#define HAVE_PY_SSIZE_T 1 + +#if defined(MS_WIN32) && !defined(MS_WIN64) +#if defined(_M_IX86) +#if defined(__clang__) +#define COMPILER ("[Clang " __clang_version__ "] 32 bit (Intel) with MSC v." _Py_STRINGIZE(_MSC_VER) " CRT]") +#define PY_SUPPORT_TIER 0 +#elif defined(__INTEL_COMPILER) +#define COMPILER ("[ICC v." _Py_STRINGIZE(__INTEL_COMPILER) " 32 bit (Intel) with MSC v." _Py_STRINGIZE(_MSC_VER) " CRT]") +#define PY_SUPPORT_TIER 0 +#else +#define COMPILER _Py_PASTE_VERSION("32 bit (Intel)") +#define PY_SUPPORT_TIER 1 +#endif /* __clang__ */ +#define PYD_PLATFORM_TAG "win32" +#elif defined(_M_ARM) +#define COMPILER _Py_PASTE_VERSION("32 bit (ARM)") +#define PYD_PLATFORM_TAG "win_arm32" +#define PY_SUPPORT_TIER 0 +#else +#define COMPILER _Py_PASTE_VERSION("32 bit (Unknown)") +#define PY_SUPPORT_TIER 0 +#endif +#endif /* MS_WIN32 && !MS_WIN64 */ + +typedef int pid_t; + +/* define some ANSI types that are not defined in earlier Win headers */ +#if _MSC_VER >= 1200 +/* This file only exists in VC 6.0 or higher */ +#include +#endif + +#endif /* _MSC_VER */ + +/* ------------------------------------------------------------------------*/ +/* mingw and mingw-w64 define __MINGW32__ */ +#ifdef __MINGW32__ + +#ifdef _WIN64 +#define MS_WIN64 +#endif + +#endif /* __MINGW32__*/ + +/* ------------------------------------------------------------------------*/ +/* egcs/gnu-win32 defines __GNUC__ and _WIN32 */ +#if defined(__GNUC__) && defined(_WIN32) +/* XXX These defines are likely incomplete, but should be easy to fix. + They should be complete enough to build extension modules. */ +/* Suggested by Rene Liebscher to avoid a GCC 2.91.* + bug that requires structure imports. More recent versions of the + compiler don't exhibit this bug. +*/ +#if (__GNUC__==2) && (__GNUC_MINOR__<=91) +#warning "Please use an up-to-date version of gcc! (>2.91 recommended)" +#endif + +#define COMPILER "[gcc]" +#define PY_LONG_LONG long long +#define PY_LLONG_MIN LLONG_MIN +#define PY_LLONG_MAX LLONG_MAX +#define PY_ULLONG_MAX ULLONG_MAX +#endif /* GNUC */ + +/* ------------------------------------------------------------------------*/ +/* lcc-win32 defines __LCC__ */ +#if defined(__LCC__) +/* XXX These defines are likely incomplete, but should be easy to fix. + They should be complete enough to build extension modules. */ + +#define COMPILER "[lcc-win32]" +typedef int pid_t; +/* __declspec() is supported here too - do nothing to get the defaults */ + +#endif /* LCC */ + +/* ------------------------------------------------------------------------*/ +/* End of compilers - finish up */ + +#ifndef NO_STDIO_H +# include +#endif + +/* 64 bit ints are usually spelt __int64 unless compiler has overridden */ +#ifndef PY_LONG_LONG +# define PY_LONG_LONG __int64 +# define PY_LLONG_MAX _I64_MAX +# define PY_LLONG_MIN _I64_MIN +# define PY_ULLONG_MAX _UI64_MAX +#endif + +/* For Windows the Python core is in a DLL by default. Test +Py_NO_ENABLE_SHARED to find out. Also support MS_NO_COREDLL for b/w compat */ +#if !defined(MS_NO_COREDLL) && !defined(Py_NO_ENABLE_SHARED) +# define Py_ENABLE_SHARED 1 /* standard symbol for shared library */ +# define MS_COREDLL /* deprecated old symbol */ +#endif /* !MS_NO_COREDLL && ... */ + +/* All windows compilers that use this header support __declspec */ +#define HAVE_DECLSPEC_DLL + +/* For an MSVC DLL, we can nominate the .lib files used by extensions */ +#ifdef MS_COREDLL +# if !defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_BUILTIN) + /* not building the core - must be an ext */ +# if defined(_MSC_VER) + /* So MSVC users need not specify the .lib + file in their Makefile (other compilers are + generally taken care of by distutils.) */ +# if defined(_DEBUG) +# pragma comment(lib,"python313_d.lib") +# elif defined(Py_LIMITED_API) +# pragma comment(lib,"python3.lib") +# else +# pragma comment(lib,"python313.lib") +# endif /* _DEBUG */ +# endif /* _MSC_VER */ +# endif /* Py_BUILD_CORE */ +#endif /* MS_COREDLL */ + +#ifdef MS_WIN64 +/* maintain "win32" sys.platform for backward compatibility of Python code, + the Win64 API should be close enough to the Win32 API to make this + preferable */ +# define PLATFORM "win32" +# define SIZEOF_VOID_P 8 +# define SIZEOF_TIME_T 8 +# define SIZEOF_OFF_T 4 +# define SIZEOF_FPOS_T 8 +# define SIZEOF_HKEY 8 +# define SIZEOF_SIZE_T 8 +# define ALIGNOF_SIZE_T 8 +# define ALIGNOF_MAX_ALIGN_T 8 +/* configure.ac defines HAVE_LARGEFILE_SUPPORT iff + sizeof(off_t) > sizeof(long), and sizeof(long long) >= sizeof(off_t). + On Win64 the second condition is not true, but if fpos_t replaces off_t + then this is true. The uses of HAVE_LARGEFILE_SUPPORT imply that Win64 + should define this. */ +# define HAVE_LARGEFILE_SUPPORT +#elif defined(MS_WIN32) +# define PLATFORM "win32" +# define HAVE_LARGEFILE_SUPPORT +# define SIZEOF_VOID_P 4 +# define SIZEOF_OFF_T 4 +# define SIZEOF_FPOS_T 8 +# define SIZEOF_HKEY 4 +# define SIZEOF_SIZE_T 4 +# define ALIGNOF_SIZE_T 4 + /* MS VS2005 changes time_t to a 64-bit type on all platforms */ +# if defined(_MSC_VER) && _MSC_VER >= 1400 +# define SIZEOF_TIME_T 8 +# else +# define SIZEOF_TIME_T 4 +# endif +# define ALIGNOF_MAX_ALIGN_T 8 +#endif + +#ifdef _DEBUG +# define Py_DEBUG +#endif + + +#ifdef MS_WIN32 + +#define SIZEOF_SHORT 2 +#define SIZEOF_INT 4 +#define SIZEOF_LONG 4 +#define ALIGNOF_LONG 4 +#define SIZEOF_LONG_LONG 8 +#define SIZEOF_DOUBLE 8 +#define SIZEOF_FLOAT 4 + +/* VC 7.1 has them and VC 6.0 does not. VC 6.0 has a version number of 1200. + Microsoft eMbedded Visual C++ 4.0 has a version number of 1201 and doesn't + define these. + If some compiler does not provide them, modify the #if appropriately. */ +#if defined(_MSC_VER) +#if _MSC_VER > 1300 +#define HAVE_UINTPTR_T 1 +#define HAVE_INTPTR_T 1 +#else +/* VC6, VS 2002 and eVC4 don't support the C99 LL suffix for 64-bit integer literals */ +#define Py_LL(x) x##I64 +#endif /* _MSC_VER > 1300 */ +#endif /* _MSC_VER */ + +#endif + +/* define signed and unsigned exact-width 32-bit and 64-bit types, used in the + implementation of Python integers. */ +#define PY_UINT32_T uint32_t +#define PY_UINT64_T uint64_t +#define PY_INT32_T int32_t +#define PY_INT64_T int64_t + +/* Fairly standard from here! */ + +/* Define if on AIX 3. + System headers sometimes define this. + We just want to avoid a redefinition error message. */ +#ifndef _ALL_SOURCE +/* #undef _ALL_SOURCE */ +#endif + +/* Define to empty if the keyword does not work. */ +/* #define const */ + +/* Define to 1 if you have the header file. */ +#define HAVE_CONIO_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_DIRECT_H 1 + +/* Define to 1 if you have the declaration of `tzname', and to 0 if you don't. + */ +#define HAVE_DECL_TZNAME 1 + +/* Define if you have dirent.h. */ +/* #define DIRENT 1 */ + +/* Define to the type of elements in the array set by `getgroups'. + Usually this is either `int' or `gid_t'. */ +/* #undef GETGROUPS_T */ + +/* Define to `int' if doesn't define. */ +/* #undef gid_t */ + +/* Define if your struct tm has tm_zone. */ +/* #undef HAVE_TM_ZONE */ + +/* Define if you don't have tm_zone but do have the external array + tzname. */ +#define HAVE_TZNAME + +/* Define to `int' if doesn't define. */ +/* #undef mode_t */ + +/* Define if you don't have dirent.h, but have ndir.h. */ +/* #undef NDIR */ + +/* Define to `long' if doesn't define. */ +/* #undef off_t */ + +/* Define to `int' if doesn't define. */ +/* #undef pid_t */ + +/* Define if the system does not provide POSIX.1 features except + with this defined. */ +/* #undef _POSIX_1_SOURCE */ + +/* Define if you need to in order for stat and other things to work. */ +/* #undef _POSIX_SOURCE */ + +/* Define as the return type of signal handlers (int or void). */ +#define RETSIGTYPE void + +/* Define to `unsigned' if doesn't define. */ +/* #undef size_t */ + +/* Define if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define if you don't have dirent.h, but have sys/dir.h. */ +/* #undef SYSDIR */ + +/* Define if you don't have dirent.h, but have sys/ndir.h. */ +/* #undef SYSNDIR */ + +/* Define if you can safely include both and . */ +/* #undef TIME_WITH_SYS_TIME */ + +/* Define if your declares struct tm. */ +/* #define TM_IN_SYS_TIME 1 */ + +/* Define to `int' if doesn't define. */ +/* #undef uid_t */ + +/* Define if the closedir function returns void instead of int. */ +/* #undef VOID_CLOSEDIR */ + +/* Define if getpgrp() must be called as getpgrp(0) + and (consequently) setpgrp() as setpgrp(0, 0). */ +/* #undef GETPGRP_HAVE_ARGS */ + +/* Define this if your time.h defines altzone */ +/* #define HAVE_ALTZONE */ + +/* Define if you have the putenv function. */ +#define HAVE_PUTENV + +/* Define if your compiler supports function prototypes */ +#define HAVE_PROTOTYPES + +/* Define if you can safely include both and + (which you can't on SCO ODT 3.0). */ +/* #undef SYS_SELECT_WITH_SYS_TIME */ + +/* Define if you want build the _decimal module using a coroutine-local rather + than a thread-local context */ +#define WITH_DECIMAL_CONTEXTVAR 1 + +/* Define if you want documentation strings in extension modules */ +#define WITH_DOC_STRINGS 1 + +/* Define if you want to compile in rudimentary thread support */ +/* #undef WITH_THREAD */ + +/* Define if you want to use the GNU readline library */ +/* #define WITH_READLINE 1 */ + +/* Use Python's own small-block memory-allocator. */ +#define WITH_PYMALLOC 1 + +/* Define if you want to compile in mimalloc memory allocator. */ +#define WITH_MIMALLOC 1 + +/* Define if you want to compile in object freelists optimization */ +#define WITH_FREELISTS 1 + +/* Define if you have clock. */ +/* #define HAVE_CLOCK */ + +/* Define when any dynamic module loading is enabled */ +#define HAVE_DYNAMIC_LOADING + +/* Define if you have ftime. */ +#define HAVE_FTIME + +/* Define if you have getpeername. */ +#define HAVE_GETPEERNAME + +/* Define if you have getpgrp. */ +/* #undef HAVE_GETPGRP */ + +/* Define if you have getpid. */ +#define HAVE_GETPID + +/* Define if you have gettimeofday. */ +/* #undef HAVE_GETTIMEOFDAY */ + +/* Define if you have getwd. */ +/* #undef HAVE_GETWD */ + +/* Define if you have lstat. */ +/* #undef HAVE_LSTAT */ + +/* Define if you have the mktime function. */ +#define HAVE_MKTIME + +/* Define if you have nice. */ +/* #undef HAVE_NICE */ + +/* Define if you have readlink. */ +/* #undef HAVE_READLINK */ + +/* Define if you have setpgid. */ +/* #undef HAVE_SETPGID */ + +/* Define if you have setpgrp. */ +/* #undef HAVE_SETPGRP */ + +/* Define if you have setsid. */ +/* #undef HAVE_SETSID */ + +/* Define if you have setvbuf. */ +#define HAVE_SETVBUF + +/* Define if you have siginterrupt. */ +/* #undef HAVE_SIGINTERRUPT */ + +/* Define to 1 if you have the `shutdown' function. */ +#define HAVE_SHUTDOWN 1 + +/* Define if you have symlink. */ +/* #undef HAVE_SYMLINK */ + +/* Define if you have tcgetpgrp. */ +/* #undef HAVE_TCGETPGRP */ + +/* Define if you have tcsetpgrp. */ +/* #undef HAVE_TCSETPGRP */ + +/* Define if you have times. */ +/* #undef HAVE_TIMES */ + +/* Define to 1 if you have the `umask' function. */ +#define HAVE_UMASK 1 + +/* Define if you have uname. */ +/* #undef HAVE_UNAME */ + +/* Define if you have waitpid. */ +/* #undef HAVE_WAITPID */ + +/* Define to 1 if you have the `wcsftime' function. */ +#if defined(_MSC_VER) && _MSC_VER >= 1310 +#define HAVE_WCSFTIME 1 +#endif + +/* Define to 1 if you have the `wcscoll' function. */ +#define HAVE_WCSCOLL 1 + +/* Define to 1 if you have the `wcsxfrm' function. */ +#define HAVE_WCSXFRM 1 + +/* Define if the zlib library has inflateCopy */ +#define HAVE_ZLIB_COPY 1 + +/* Define if you have the header file. */ +/* #undef HAVE_DLFCN_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_ERRNO_H 1 + +/* Define if you have the header file. */ +#define HAVE_FCNTL_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_PROCESS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SIGNAL_H 1 + +/* Define if you have the header file. */ +#define HAVE_STDDEF_H 1 + +/* Define if you have the header file. */ +/* #undef HAVE_SYS_AUDIOIO_H */ + +/* Define if you have the header file. */ +/* #define HAVE_SYS_PARAM_H 1 */ + +/* Define if you have the header file. */ +/* #define HAVE_SYS_SELECT_H 1 */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define if you have the header file. */ +/* #define HAVE_SYS_TIME_H 1 */ + +/* Define if you have the header file. */ +/* #define HAVE_SYS_TIMES_H 1 */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define if you have the header file. */ +/* #define HAVE_SYS_UN_H 1 */ + +/* Define if you have the header file. */ +/* #define HAVE_SYS_UTIME_H 1 */ + +/* Define if you have the header file. */ +/* #define HAVE_SYS_UTSNAME_H 1 */ + +/* Define if you have the header file. */ +/* #define HAVE_UNISTD_H 1 */ + +/* Define if you have the header file. */ +/* #define HAVE_UTIME_H 1 */ + +/* Define if the compiler provides a wchar.h header file. */ +#define HAVE_WCHAR_H 1 + +/* The size of `wchar_t', as computed by sizeof. */ +#define SIZEOF_WCHAR_T 2 + +/* The size of `_Bool', as computed by sizeof. */ +#define SIZEOF__BOOL 1 + +/* The size of `pid_t', as computed by sizeof. */ +#define SIZEOF_PID_T SIZEOF_INT + +/* Define if you have the dl library (-ldl). */ +/* #undef HAVE_LIBDL */ + +/* Define if you have the mpc library (-lmpc). */ +/* #undef HAVE_LIBMPC */ + +/* Define if you have the seq library (-lseq). */ +/* #undef HAVE_LIBSEQ */ + +/* Define if you have the socket library (-lsocket). */ +#define HAVE_LIBSOCKET 1 + +/* Define if you have the sun library (-lsun). */ +/* #undef HAVE_LIBSUN */ + +/* Define if you have the termcap library (-ltermcap). */ +/* #undef HAVE_LIBTERMCAP */ + +/* Define if you have the termlib library (-ltermlib). */ +/* #undef HAVE_LIBTERMLIB */ + +/* Define if you have the thread library (-lthread). */ +/* #undef HAVE_LIBTHREAD */ + +/* WinSock does not use a bitmask in select, and uses + socket handles greater than FD_SETSIZE */ +#define Py_SOCKET_FD_CAN_BE_GE_FD_SETSIZE + +/* Define if C doubles are 64-bit IEEE 754 binary format, stored with the + least significant byte first */ +#define DOUBLE_IS_LITTLE_ENDIAN_IEEE754 1 + +/* Define to 1 if you have the `erf' function. */ +#define HAVE_ERF 1 + +/* Define to 1 if you have the `erfc' function. */ +#define HAVE_ERFC 1 + +// netdb.h functions (provided by winsock.h) +#define HAVE_GETHOSTNAME 1 +#define HAVE_GETHOSTBYADDR 1 +#define HAVE_GETHOSTBYNAME 1 +#define HAVE_GETPROTOBYNAME 1 +#define HAVE_GETSERVBYNAME 1 +#define HAVE_GETSERVBYPORT 1 +// sys/socket.h functions (provided by winsock.h) +#define HAVE_INET_PTON 1 +#define HAVE_INET_NTOA 1 +#define HAVE_ACCEPT 1 +#define HAVE_BIND 1 +#define HAVE_CONNECT 1 +#define HAVE_GETSOCKNAME 1 +#define HAVE_LISTEN 1 +#define HAVE_RECVFROM 1 +#define HAVE_SENDTO 1 +#define HAVE_SETSOCKOPT 1 +#define HAVE_SOCKET 1 + +/* Define to 1 if you have the `dup' function. */ +#define HAVE_DUP 1 + +/* framework name */ +#define _PYTHONFRAMEWORK "" + +/* Define if libssl has X509_VERIFY_PARAM_set1_host and related function */ +#define HAVE_X509_VERIFY_PARAM_SET1_HOST 1 + +/* Define if you want to disable the GIL */ +#undef Py_GIL_DISABLED + +#endif /* !Py_CONFIG_H */ diff --git a/PC/python3dll.c b/PC/python3dll.c index 64dfbba3e424a1..07aa84c91f9fc7 100755 --- a/PC/python3dll.c +++ b/PC/python3dll.c @@ -19,6 +19,7 @@ EXPORT_FUNC(_Py_Dealloc) EXPORT_FUNC(_Py_DecRef) EXPORT_FUNC(_Py_IncRef) EXPORT_FUNC(_Py_NegativeRefcount) +EXPORT_FUNC(_Py_SetRefcnt) EXPORT_FUNC(_Py_VaBuildValue_SizeT) EXPORT_FUNC(_PyArg_Parse_SizeT) EXPORT_FUNC(_PyArg_ParseTuple_SizeT) @@ -69,6 +70,7 @@ EXPORT_FUNC(Py_Initialize) EXPORT_FUNC(Py_InitializeEx) EXPORT_FUNC(Py_Is) EXPORT_FUNC(Py_IsFalse) +EXPORT_FUNC(Py_IsFinalizing) EXPORT_FUNC(Py_IsInitialized) EXPORT_FUNC(Py_IsNone) EXPORT_FUNC(Py_IsTrue) @@ -331,6 +333,7 @@ EXPORT_FUNC(PyList_SetSlice) EXPORT_FUNC(PyList_Size) EXPORT_FUNC(PyList_Sort) EXPORT_FUNC(PyLong_AsDouble) +EXPORT_FUNC(PyLong_AsInt) EXPORT_FUNC(PyLong_AsLong) EXPORT_FUNC(PyLong_AsLongAndOverflow) EXPORT_FUNC(PyLong_AsLongLong) @@ -358,6 +361,8 @@ EXPORT_FUNC(PyMapping_GetOptionalItem) EXPORT_FUNC(PyMapping_GetOptionalItemString) EXPORT_FUNC(PyMapping_HasKey) EXPORT_FUNC(PyMapping_HasKeyString) +EXPORT_FUNC(PyMapping_HasKeyStringWithError) +EXPORT_FUNC(PyMapping_HasKeyWithError) EXPORT_FUNC(PyMapping_Items) EXPORT_FUNC(PyMapping_Keys) EXPORT_FUNC(PyMapping_Length) @@ -369,6 +374,10 @@ EXPORT_FUNC(PyMarshal_WriteObjectToString) EXPORT_FUNC(PyMem_Calloc) EXPORT_FUNC(PyMem_Free) EXPORT_FUNC(PyMem_Malloc) +EXPORT_FUNC(PyMem_RawCalloc) +EXPORT_FUNC(PyMem_RawFree) +EXPORT_FUNC(PyMem_RawMalloc) +EXPORT_FUNC(PyMem_RawRealloc) EXPORT_FUNC(PyMem_Realloc) EXPORT_FUNC(PyMember_GetOne) EXPORT_FUNC(PyMember_SetOne) @@ -479,6 +488,8 @@ EXPORT_FUNC(PyObject_GetOptionalAttrString) EXPORT_FUNC(PyObject_GetTypeData) EXPORT_FUNC(PyObject_HasAttr) EXPORT_FUNC(PyObject_HasAttrString) +EXPORT_FUNC(PyObject_HasAttrStringWithError) +EXPORT_FUNC(PyObject_HasAttrWithError) EXPORT_FUNC(PyObject_Hash) EXPORT_FUNC(PyObject_HashNotImplemented) EXPORT_FUNC(PyObject_Init) @@ -558,6 +569,8 @@ EXPORT_FUNC(PyStructSequence_SetItem) EXPORT_FUNC(PySys_AddWarnOption) EXPORT_FUNC(PySys_AddWarnOptionUnicode) EXPORT_FUNC(PySys_AddXOption) +EXPORT_FUNC(PySys_Audit) +EXPORT_FUNC(PySys_AuditTuple) EXPORT_FUNC(PySys_FormatStderr) EXPORT_FUNC(PySys_FormatStdout) EXPORT_FUNC(PySys_GetObject) @@ -683,6 +696,8 @@ EXPORT_FUNC(PyUnicode_DecodeUTF8Stateful) EXPORT_FUNC(PyUnicode_EncodeCodePage) EXPORT_FUNC(PyUnicode_EncodeFSDefault) EXPORT_FUNC(PyUnicode_EncodeLocale) +EXPORT_FUNC(PyUnicode_EqualToUTF8) +EXPORT_FUNC(PyUnicode_EqualToUTF8AndSize) EXPORT_FUNC(PyUnicode_Find) EXPORT_FUNC(PyUnicode_FindChar) EXPORT_FUNC(PyUnicode_Format) diff --git a/PC/winreg.c b/PC/winreg.c index ed6258d2b33e56..77b80217ac0ab1 100644 --- a/PC/winreg.c +++ b/PC/winreg.c @@ -220,14 +220,17 @@ class DWORD_converter(unsigned_long_converter): class HKEY_converter(CConverter): type = 'HKEY' converter = 'clinic_HKEY_converter' - - def parse_arg(self, argname, displayname): - return """ - if (!{converter}(_PyModule_GetState(module), {argname}, &{paramname})) {{{{ - goto exit; - }}}} - """.format(argname=argname, paramname=self.parser_name, - converter=self.converter) + broken_limited_capi = True + + def parse_arg(self, argname, displayname, *, limited_capi): + assert not limited_capi + return self.format_code(""" + if (!{converter}(_PyModule_GetState(module), {argname}, &{paramname})) {{{{ + goto exit; + }}}} + """, + argname=argname, + converter=self.converter) class HKEY_return_converter(CReturnConverter): type = 'HKEY' @@ -249,7 +252,7 @@ class self_return_converter(CReturnConverter): data.return_conversion.append( 'return_value = (PyObject *)_return_value;\n') [python start generated code]*/ -/*[python end generated code: output=da39a3ee5e6b4b0d input=17e645060c7b8ae1]*/ +/*[python end generated code: output=da39a3ee5e6b4b0d input=4979f33998ffb6f8]*/ #include "clinic/winreg.c.h" @@ -323,12 +326,14 @@ winreg.HKEYType.__exit__ exc_type: object exc_value: object traceback: object + / + [clinic start generated code]*/ static PyObject * winreg_HKEYType___exit___impl(PyHKEYObject *self, PyObject *exc_type, PyObject *exc_value, PyObject *traceback) -/*[clinic end generated code: output=923ebe7389e6a263 input=fb32489ee92403c7]*/ +/*[clinic end generated code: output=923ebe7389e6a263 input=1eac83cd06962689]*/ { winreg_state *st = _PyType_GetModuleState(Py_TYPE(self)); assert(st != NULL); diff --git a/PC/winsound.c b/PC/winsound.c index 68a917810f884d..7e4ebd90f50c2e 100644 --- a/PC/winsound.c +++ b/PC/winsound.c @@ -35,6 +35,13 @@ winsound.PlaySound(None, 0) */ +#include "pyconfig.h" // Py_GIL_DISABLED + +#ifndef Py_GIL_DISABLED +// Need limited C API version 3.12 for Py_MOD_PER_INTERPRETER_GIL_SUPPORTED +#define Py_LIMITED_API 0x030c0000 +#endif + #include #include #include @@ -95,9 +102,13 @@ winsound_PlaySound_impl(PyObject *module, PyObject *sound, int flags) } wsound = (wchar_t *)view.buf; } else if (PyBytes_Check(sound)) { - PyErr_Format(PyExc_TypeError, - "'sound' must be str, os.PathLike, or None, not '%s'", - Py_TYPE(sound)->tp_name); + PyObject *type_name = PyType_GetQualName(Py_TYPE(sound)); + if (type_name != NULL) { + PyErr_Format(PyExc_TypeError, + "'sound' must be str, os.PathLike, or None, not %S", + type_name); + Py_DECREF(type_name); + } return NULL; } else { PyObject *obj = PyOS_FSPath(sound); diff --git a/PCbuild/_freeze_module.vcxproj b/PCbuild/_freeze_module.vcxproj index e247637a0dfe5c..610581bc96cb1a 100644 --- a/PCbuild/_freeze_module.vcxproj +++ b/PCbuild/_freeze_module.vcxproj @@ -89,6 +89,7 @@ Py_NO_ENABLE_SHARED;Py_BUILD_CORE;_CONSOLE;%(PreprocessorDefinitions) + $(IntDir);%(AdditionalIncludeDirectories) Disabled false @@ -172,7 +173,14 @@ - + + + + + + + + @@ -188,16 +196,20 @@ + + - + + + @@ -213,11 +225,14 @@ + + + @@ -246,122 +261,125 @@ + + + importlib._bootstrap $(IntDir)importlib._bootstrap.g.h - $(PySourcePath)Python\frozen_modules\importlib._bootstrap.h + $(GeneratedFrozenModulesDir)Python\frozen_modules\importlib._bootstrap.h importlib._bootstrap_external $(IntDir)importlib._bootstrap_external.g.h - $(PySourcePath)Python\frozen_modules\importlib._bootstrap_external.h + $(GeneratedFrozenModulesDir)Python\frozen_modules\importlib._bootstrap_external.h zipimport $(IntDir)zipimport.g.h - $(PySourcePath)Python\frozen_modules\zipimport.h + $(GeneratedFrozenModulesDir)Python\frozen_modules\zipimport.h abc $(IntDir)abc.g.h - $(PySourcePath)Python\frozen_modules\abc.h + $(GeneratedFrozenModulesDir)Python\frozen_modules\abc.h codecs $(IntDir)codecs.g.h - $(PySourcePath)Python\frozen_modules\codecs.h + $(GeneratedFrozenModulesDir)Python\frozen_modules\codecs.h io $(IntDir)io.g.h - $(PySourcePath)Python\frozen_modules\io.h + $(GeneratedFrozenModulesDir)Python\frozen_modules\io.h _collections_abc $(IntDir)_collections_abc.g.h - $(PySourcePath)Python\frozen_modules\_collections_abc.h + $(GeneratedFrozenModulesDir)Python\frozen_modules\_collections_abc.h _sitebuiltins $(IntDir)_sitebuiltins.g.h - $(PySourcePath)Python\frozen_modules\_sitebuiltins.h + $(GeneratedFrozenModulesDir)Python\frozen_modules\_sitebuiltins.h genericpath $(IntDir)genericpath.g.h - $(PySourcePath)Python\frozen_modules\genericpath.h + $(GeneratedFrozenModulesDir)Python\frozen_modules\genericpath.h ntpath $(IntDir)ntpath.g.h - $(PySourcePath)Python\frozen_modules\ntpath.h + $(GeneratedFrozenModulesDir)Python\frozen_modules\ntpath.h posixpath $(IntDir)posixpath.g.h - $(PySourcePath)Python\frozen_modules\posixpath.h + $(GeneratedFrozenModulesDir)Python\frozen_modules\posixpath.h os $(IntDir)os.g.h - $(PySourcePath)Python\frozen_modules\os.h + $(GeneratedFrozenModulesDir)Python\frozen_modules\os.h site $(IntDir)site.g.h - $(PySourcePath)Python\frozen_modules\site.h + $(GeneratedFrozenModulesDir)Python\frozen_modules\site.h stat $(IntDir)stat.g.h - $(PySourcePath)Python\frozen_modules\stat.h + $(GeneratedFrozenModulesDir)Python\frozen_modules\stat.h importlib.util $(IntDir)importlib.util.g.h - $(PySourcePath)Python\frozen_modules\importlib.util.h + $(GeneratedFrozenModulesDir)Python\frozen_modules\importlib.util.h importlib.machinery $(IntDir)importlib.machinery.g.h - $(PySourcePath)Python\frozen_modules\importlib.machinery.h + $(GeneratedFrozenModulesDir)Python\frozen_modules\importlib.machinery.h runpy $(IntDir)runpy.g.h - $(PySourcePath)Python\frozen_modules\runpy.h + $(GeneratedFrozenModulesDir)Python\frozen_modules\runpy.h __hello__ $(IntDir)__hello__.g.h - $(PySourcePath)Python\frozen_modules\__hello__.h + $(GeneratedFrozenModulesDir)Python\frozen_modules\__hello__.h __phello__ $(IntDir)__phello__.g.h - $(PySourcePath)Python\frozen_modules\__phello__.h + $(GeneratedFrozenModulesDir)Python\frozen_modules\__phello__.h __phello__.ham $(IntDir)__phello__.ham.g.h - $(PySourcePath)Python\frozen_modules\__phello__.ham.h + $(GeneratedFrozenModulesDir)Python\frozen_modules\__phello__.ham.h __phello__.ham.eggs $(IntDir)__phello__.ham.eggs.g.h - $(PySourcePath)Python\frozen_modules\__phello__.ham.eggs.h + $(GeneratedFrozenModulesDir)Python\frozen_modules\__phello__.ham.eggs.h __phello__.spam $(IntDir)__phello__.spam.g.h - $(PySourcePath)Python\frozen_modules\__phello__.spam.h + $(GeneratedFrozenModulesDir)Python\frozen_modules\__phello__.spam.h frozen_only $(IntDir)frozen_only.g.h - $(PySourcePath)Python\frozen_modules\frozen_only.h + $(GeneratedFrozenModulesDir)Python\frozen_modules\frozen_only.h @@ -370,12 +388,65 @@ getpath $(IntDir)getpath.g.h - $(PySourcePath)Python\frozen_modules\getpath.h + $(GeneratedFrozenModulesDir)Python\frozen_modules\getpath.h + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @(PyConfigH->'%(FullPath)', ';') + $([System.IO.File]::ReadAllText($(PyConfigH))) + $([System.IO.File]::ReadAllText('$(IntDir)pyconfig.h')) + + + $(PyConfigHText.Replace('#undef Py_GIL_DISABLED', '#define Py_GIL_DISABLED 1')) + + + + + @@ -404,32 +475,19 @@ AfterTargets="_RebuildFrozen" DependsOnTargets="FindPythonForBuild" Condition="$(Configuration) != 'PGUpdate'"> + + + +$(IntDir)\deepfreeze_mappings.txt + + + + - + @@ -438,7 +496,7 @@ - + diff --git a/PCbuild/_freeze_module.vcxproj.filters b/PCbuild/_freeze_module.vcxproj.filters index 2a0e009308022b..3141913c043869 100644 --- a/PCbuild/_freeze_module.vcxproj.filters +++ b/PCbuild/_freeze_module.vcxproj.filters @@ -103,6 +103,12 @@ Source Files + + Source Files + + + Source Files + Source Files @@ -124,9 +130,6 @@ Source Files - - Source Files - Source Files @@ -163,6 +166,15 @@ Source Files + + Source Files + + + Source Files + + + Source Files + Source Files @@ -223,6 +235,9 @@ Source Files + + Source Files + Source Files @@ -283,9 +298,15 @@ Source Files + + Source Files + Source Files + + Source Files + Source Files @@ -394,7 +415,28 @@ Source Files - + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + Source Files diff --git a/PCbuild/_testcapi.vcxproj b/PCbuild/_testcapi.vcxproj index de17d74c52e56f..1c15541d3ec735 100644 --- a/PCbuild/_testcapi.vcxproj +++ b/PCbuild/_testcapi.vcxproj @@ -99,18 +99,32 @@ + + + + + + + + + + + + + + diff --git a/PCbuild/_testcapi.vcxproj.filters b/PCbuild/_testcapi.vcxproj.filters index 637f7178d39d0e..6059959bb9a040 100644 --- a/PCbuild/_testcapi.vcxproj.filters +++ b/PCbuild/_testcapi.vcxproj.filters @@ -27,9 +27,30 @@ Source Files + + Source Files + + + Source Files + + + Source Files + Source Files + + Source Files + + + Source Files + + + Source Files + + + Source Files + Source Files @@ -48,6 +69,12 @@ Source Files + + Source Files + + + Source Files + Source Files @@ -60,9 +87,24 @@ Source Files + + Source Files + Source Files + + Source Files + + + Source Files + + + Source Files + + + Source Files + Source Files diff --git a/PCbuild/_testclinic_limited.vcxproj b/PCbuild/_testclinic_limited.vcxproj new file mode 100644 index 00000000000000..b00b2be491b423 --- /dev/null +++ b/PCbuild/_testclinic_limited.vcxproj @@ -0,0 +1,109 @@ + + + + + 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 + + + + {01FDF29A-40A1-46DF-84F5-85EBBD2A2410} + _testclinic_limited + Win32Proj + + + + + DynamicLibrary + NotSet + + + + .pyd + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + + + + + + + + + + {cf7ac3d1-e2df-41d2-bea6-1e2556cdea26} + false + + + + + + \ No newline at end of file diff --git a/PCbuild/_testclinic_limited.vcxproj.filters b/PCbuild/_testclinic_limited.vcxproj.filters new file mode 100644 index 00000000000000..8ecdd99a4ac220 --- /dev/null +++ b/PCbuild/_testclinic_limited.vcxproj.filters @@ -0,0 +1,21 @@ + + + + + {2422278e-eeeb-4241-8182-433e2bc5a7fc} + + + {41f1cd52-b682-46aa-a7fd-7bdf81a18010} + + + + + Source Files + + + + + Resource Files + + + diff --git a/PCbuild/_testinternalcapi.vcxproj b/PCbuild/_testinternalcapi.vcxproj index 6c5b12cd40e983..558f66ca95cd33 100644 --- a/PCbuild/_testinternalcapi.vcxproj +++ b/PCbuild/_testinternalcapi.vcxproj @@ -94,6 +94,10 @@ + + + + diff --git a/PCbuild/_testinternalcapi.vcxproj.filters b/PCbuild/_testinternalcapi.vcxproj.filters index 7734da0b7b426b..abfeeb39630daf 100644 --- a/PCbuild/_testinternalcapi.vcxproj.filters +++ b/PCbuild/_testinternalcapi.vcxproj.filters @@ -12,6 +12,15 @@ Source Files + + Source Files + + + Source Files + + + Source Files + diff --git a/PCbuild/build.bat b/PCbuild/build.bat index d333ceabd2e53a..e61267b5852a8f 100644 --- a/PCbuild/build.bat +++ b/PCbuild/build.bat @@ -33,6 +33,7 @@ echo. -k Attempt to kill any running Pythons before building (usually done echo. automatically by the pythoncore project) echo. --pgo Build with Profile-Guided Optimization. This flag echo. overrides -c and -d +echo. --disable-gil Enable experimental support for running without the GIL. echo. --test-marker Enable the test marker within the build. echo. --regen Regenerate all opcodes, grammar and tokens. echo. @@ -80,6 +81,7 @@ if "%~1"=="-q" (set verbose=/v:q /nologo /clp:summary) & shift & goto CheckOpts if "%~1"=="-k" (set kill=true) & shift & goto CheckOpts if "%~1"=="--pgo" (set do_pgo=true) & shift & goto CheckOpts if "%~1"=="--pgo-job" (set do_pgo=true) & (set pgo_job=%~2) & shift & shift & goto CheckOpts +if "%~1"=="--disable-gil" (set UseDisableGil=true) & shift & goto CheckOpts if "%~1"=="--test-marker" (set UseTestMarker=true) & shift & goto CheckOpts if "%~1"=="-V" shift & goto Version if "%~1"=="--regen" (set Regen=true) & shift & goto CheckOpts @@ -172,6 +174,7 @@ echo on /p:IncludeExternals=%IncludeExternals%^ /p:IncludeCTypes=%IncludeCTypes%^ /p:IncludeSSL=%IncludeSSL% /p:IncludeTkinter=%IncludeTkinter%^ + /p:DisableGil=%UseDisableGil%^ /p:UseTestMarker=%UseTestMarker% %GITProperty%^ %1 %2 %3 %4 %5 %6 %7 %8 %9 diff --git a/PCbuild/find_python.bat b/PCbuild/find_python.bat index 7af5503d80a0fc..d3f62c93869003 100644 --- a/PCbuild/find_python.bat +++ b/PCbuild/find_python.bat @@ -52,7 +52,7 @@ @if "%_Py_NUGET%"=="" (set _Py_NUGET=%_Py_EXTERNALS_DIR%\nuget.exe) @if "%_Py_NUGET_URL%"=="" (set _Py_NUGET_URL=https://aka.ms/nugetclidl) @if NOT exist "%_Py_NUGET%" ( - @echo Downloading nuget... + @if not "%_Py_Quiet%"=="1" @echo Downloading nuget... @rem NB: Must use single quotes around NUGET here, NOT double! @rem Otherwise, a space in the path would break things @rem If it fails, retry with any available copy of Python @@ -63,7 +63,11 @@ ) @if not "%_Py_Quiet%"=="1" @echo Installing Python via nuget... -@"%_Py_NUGET%" install pythonx86 -ExcludeVersion -OutputDirectory "%_Py_EXTERNALS_DIR%" +@if not "%_Py_Quiet%"=="1" ( + @"%_Py_NUGET%" install pythonx86 -ExcludeVersion -OutputDirectory "%_Py_EXTERNALS_DIR%" +) else ( + @"%_Py_NUGET%" install pythonx86 -Verbosity quiet -ExcludeVersion -OutputDirectory "%_Py_EXTERNALS_DIR%" +) @rem Quote it here; it's not quoted later because "py -x.y" wouldn't work @if not errorlevel 1 (set PYTHON="%_Py_EXTERNALS_DIR%\pythonx86\tools\python.exe") & (set _Py_Python_Source=found on nuget.org) & goto :found diff --git a/PCbuild/get_externals.bat b/PCbuild/get_externals.bat index 257b360ba3506f..3919c0592ec00d 100644 --- a/PCbuild/get_externals.bat +++ b/PCbuild/get_externals.bat @@ -53,10 +53,10 @@ echo.Fetching external libraries... set libraries= set libraries=%libraries% bzip2-1.0.8 if NOT "%IncludeLibffiSrc%"=="false" set libraries=%libraries% libffi-3.4.4 -if NOT "%IncludeSSLSrc%"=="false" set libraries=%libraries% openssl-3.0.9 -set libraries=%libraries% sqlite-3.42.0.0 -if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tcl-core-8.6.13.0 -if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tk-8.6.13.0 +if NOT "%IncludeSSLSrc%"=="false" set libraries=%libraries% openssl-3.0.11 +set libraries=%libraries% sqlite-3.44.2.0 +if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tcl-core-8.6.13.1 +if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tk-8.6.13.1 set libraries=%libraries% xz-5.2.5 set libraries=%libraries% zlib-1.2.13 @@ -76,8 +76,8 @@ echo.Fetching external binaries... set binaries= if NOT "%IncludeLibffi%"=="false" set binaries=%binaries% libffi-3.4.4 -if NOT "%IncludeSSL%"=="false" set binaries=%binaries% openssl-bin-3.0.9 -if NOT "%IncludeTkinter%"=="false" set binaries=%binaries% tcltk-8.6.13.0 +if NOT "%IncludeSSL%"=="false" set binaries=%binaries% openssl-bin-3.0.11 +if NOT "%IncludeTkinter%"=="false" set binaries=%binaries% tcltk-8.6.13.1 if NOT "%IncludeSSLSrc%"=="false" set binaries=%binaries% nasm-2.11.06 for %%b in (%binaries%) do ( diff --git a/PCbuild/pcbuild.proj b/PCbuild/pcbuild.proj index 7735c22f8ae1b3..b7b78be768d7ec 100644 --- a/PCbuild/pcbuild.proj +++ b/PCbuild/pcbuild.proj @@ -77,7 +77,7 @@ - + diff --git a/PCbuild/pcbuild.sln b/PCbuild/pcbuild.sln index ca70213755310c..a0b5fbd1304b41 100644 --- a/PCbuild/pcbuild.sln +++ b/PCbuild/pcbuild.sln @@ -10,43 +10,43 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "python", "python.vcxproj", "{B11D750F-CD1F-4A96-85CE-E69A5C5259F9}" ProjectSection(ProjectDependencies) = postProject - {9E48B300-37D1-11DD-8C41-005056C00008} = {9E48B300-37D1-11DD-8C41-005056C00008} - {9EC7190A-249F-4180-A900-548FDCF3055F} = {9EC7190A-249F-4180-A900-548FDCF3055F} - {78D80A15-BD8C-44E2-B49E-1F05B0A0A687} = {78D80A15-BD8C-44E2-B49E-1F05B0A0A687} - {6901D91C-6E48-4BB7-9FEC-700C8131DF1D} = {6901D91C-6E48-4BB7-9FEC-700C8131DF1D} - {54B1431F-B86B-4ACB-B28C-88BCF93191D8} = {54B1431F-B86B-4ACB-B28C-88BCF93191D8} - {F749B822-B489-4CA5-A3AD-CE078F5F338A} = {F749B822-B489-4CA5-A3AD-CE078F5F338A} - {D06B6426-4762-44CC-8BAD-D79052507F2F} = {D06B6426-4762-44CC-8BAD-D79052507F2F} - {36D0C52C-DF4E-45D0-8BC7-E294C3ABC781} = {36D0C52C-DF4E-45D0-8BC7-E294C3ABC781} - {CB435430-EBB1-478B-8F4E-C256F6838F55} = {CB435430-EBB1-478B-8F4E-C256F6838F55} - {17E1E049-C309-4D79-843F-AE483C264AEA} = {17E1E049-C309-4D79-843F-AE483C264AEA} - {384C224A-7474-476E-A01B-750EA7DE918C} = {384C224A-7474-476E-A01B-750EA7DE918C} + {01FDF29A-40A1-46DF-84F5-85EBBD2A2410} = {01FDF29A-40A1-46DF-84F5-85EBBD2A2410} + {0E9791DB-593A-465F-98BC-681011311617} = {0E9791DB-593A-465F-98BC-681011311617} + {0E9791DB-593A-465F-98BC-681011311618} = {0E9791DB-593A-465F-98BC-681011311618} {12728250-16EC-4DC6-94D7-E21DD88947F8} = {12728250-16EC-4DC6-94D7-E21DD88947F8} - {86937F53-C189-40EF-8CE8-8759D8E7D480} = {86937F53-C189-40EF-8CE8-8759D8E7D480} - {28B5D777-DDF2-4B6B-B34F-31D938813856} = {28B5D777-DDF2-4B6B-B34F-31D938813856} - {31FFC478-7B4A-43E8-9954-8D03E2187E9C} = {31FFC478-7B4A-43E8-9954-8D03E2187E9C} - {F9D71780-F393-11E0-BE50-0800200C9A66} = {F9D71780-F393-11E0-BE50-0800200C9A66} - {494BAC80-A60C-43A9-99E7-ACB691CE2C4D} = {494BAC80-A60C-43A9-99E7-ACB691CE2C4D} - {C6E20F84-3247-4AD6-B051-B073268F73BA} = {C6E20F84-3247-4AD6-B051-B073268F73BA} - {B244E787-C445-441C-BDF4-5A4F1A3A1E51} = {B244E787-C445-441C-BDF4-5A4F1A3A1E51} - {18CAE28C-B454-46C1-87A0-493D91D97F03} = {18CAE28C-B454-46C1-87A0-493D91D97F03} {13CECB97-4119-4316-9D42-8534019A5A44} = {13CECB97-4119-4316-9D42-8534019A5A44} - {885D4898-D08D-4091-9C40-C700CFE3FC5A} = {885D4898-D08D-4091-9C40-C700CFE3FC5A} + {16BFE6F0-22EF-40B5-B831-7E937119EF10} = {16BFE6F0-22EF-40B5-B831-7E937119EF10} + {17E1E049-C309-4D79-843F-AE483C264AEA} = {17E1E049-C309-4D79-843F-AE483C264AEA} + {18CAE28C-B454-46C1-87A0-493D91D97F03} = {18CAE28C-B454-46C1-87A0-493D91D97F03} + {2097F1C1-597C-4167-93E3-656A7D6339B2} = {2097F1C1-597C-4167-93E3-656A7D6339B2} + {28B5D777-DDF2-4B6B-B34F-31D938813856} = {28B5D777-DDF2-4B6B-B34F-31D938813856} + {36D0C52C-DF4E-45D0-8BC7-E294C3ABC781} = {36D0C52C-DF4E-45D0-8BC7-E294C3ABC781} + {384C224A-7474-476E-A01B-750EA7DE918C} = {384C224A-7474-476E-A01B-750EA7DE918C} {447F05A8-F581-4CAC-A466-5AC7936E207E} = {447F05A8-F581-4CAC-A466-5AC7936E207E} - {ECC7CEAC-A5E5-458E-BB9E-2413CC847881} = {ECC7CEAC-A5E5-458E-BB9E-2413CC847881} {4946ECAC-2E69-4BF8-A90A-F5136F5094DF} = {4946ECAC-2E69-4BF8-A90A-F5136F5094DF} - {FDB84CBB-2FB6-47C8-A2D6-091E0833239D} = {FDB84CBB-2FB6-47C8-A2D6-091E0833239D} + {494BAC80-A60C-43A9-99E7-ACB691CE2C4D} = {494BAC80-A60C-43A9-99E7-ACB691CE2C4D} + {54B1431F-B86B-4ACB-B28C-88BCF93191D8} = {54B1431F-B86B-4ACB-B28C-88BCF93191D8} + {6901D91C-6E48-4BB7-9FEC-700C8131DF1D} = {6901D91C-6E48-4BB7-9FEC-700C8131DF1D} + {6DAC66D9-E703-4624-BE03-49112AB5AA62} = {6DAC66D9-E703-4624-BE03-49112AB5AA62} {73FCD2BD-F133-46B7-8EC1-144CD82A59D5} = {73FCD2BD-F133-46B7-8EC1-144CD82A59D5} - {2097F1C1-597C-4167-93E3-656A7D6339B2} = {2097F1C1-597C-4167-93E3-656A7D6339B2} - {A2697BD3-28C1-4AEC-9106-8B748639FD16} = {A2697BD3-28C1-4AEC-9106-8B748639FD16} + {78D80A15-BD8C-44E2-B49E-1F05B0A0A687} = {78D80A15-BD8C-44E2-B49E-1F05B0A0A687} + {86937F53-C189-40EF-8CE8-8759D8E7D480} = {86937F53-C189-40EF-8CE8-8759D8E7D480} + {885D4898-D08D-4091-9C40-C700CFE3FC5A} = {885D4898-D08D-4091-9C40-C700CFE3FC5A} {900342D7-516A-4469-B1AD-59A66E49A25F} = {900342D7-516A-4469-B1AD-59A66E49A25F} - {6DAC66D9-E703-4624-BE03-49112AB5AA62} = {6DAC66D9-E703-4624-BE03-49112AB5AA62} - {0E9791DB-593A-465F-98BC-681011311617} = {0E9791DB-593A-465F-98BC-681011311617} - {0E9791DB-593A-465F-98BC-681011311618} = {0E9791DB-593A-465F-98BC-681011311618} + {9E48B300-37D1-11DD-8C41-005056C00008} = {9E48B300-37D1-11DD-8C41-005056C00008} + {9EC7190A-249F-4180-A900-548FDCF3055F} = {9EC7190A-249F-4180-A900-548FDCF3055F} + {A2697BD3-28C1-4AEC-9106-8B748639FD16} = {A2697BD3-28C1-4AEC-9106-8B748639FD16} + {A840DDFB-ED50-484B-B527-B32E7CF90FD5} = {A840DDFB-ED50-484B-B527-B32E7CF90FD5} + {B244E787-C445-441C-BDF4-5A4F1A3A1E51} = {B244E787-C445-441C-BDF4-5A4F1A3A1E51} + {C6E20F84-3247-4AD6-B051-B073268F73BA} = {C6E20F84-3247-4AD6-B051-B073268F73BA} + {CB435430-EBB1-478B-8F4E-C256F6838F55} = {CB435430-EBB1-478B-8F4E-C256F6838F55} + {D06B6426-4762-44CC-8BAD-D79052507F2F} = {D06B6426-4762-44CC-8BAD-D79052507F2F} {EB6E69DD-04BF-4543-9B92-49FAABCEAC2E} = {EB6E69DD-04BF-4543-9B92-49FAABCEAC2E} - {16BFE6F0-22EF-40B5-B831-7E937119EF10} = {16BFE6F0-22EF-40B5-B831-7E937119EF10} + {ECC7CEAC-A5E5-458E-BB9E-2413CC847881} = {ECC7CEAC-A5E5-458E-BB9E-2413CC847881} + {F749B822-B489-4CA5-A3AD-CE078F5F338A} = {F749B822-B489-4CA5-A3AD-CE078F5F338A} + {F9D71780-F393-11E0-BE50-0800200C9A66} = {F9D71780-F393-11E0-BE50-0800200C9A66} {FCBE1EF2-E0F0-40B1-88B5-00A35D378742} = {FCBE1EF2-E0F0-40B1-88B5-00A35D378742} - {A840DDFB-ED50-484B-B527-B32E7CF90FD5} = {A840DDFB-ED50-484B-B527-B32E7CF90FD5} + {FDB84CBB-2FB6-47C8-A2D6-091E0833239D} = {FDB84CBB-2FB6-47C8-A2D6-091E0833239D} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pythoncore", "pythoncore.vcxproj", "{CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26}" @@ -157,6 +157,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_uuid", "_uuid.vcxproj", "{ EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_wmi", "_wmi.vcxproj", "{54B1431F-B86B-4ACB-B28C-88BCF93191D8}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_testclinic_limited", "_testclinic_limited.vcxproj", "{01FDF29A-40A1-46DF-84F5-85EBBD2A2410}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|ARM = Debug|ARM @@ -433,38 +435,6 @@ Global {17E1E049-C309-4D79-843F-AE483C264AEA}.Release|Win32.Build.0 = Release|Win32 {17E1E049-C309-4D79-843F-AE483C264AEA}.Release|x64.ActiveCfg = Release|x64 {17E1E049-C309-4D79-843F-AE483C264AEA}.Release|x64.Build.0 = Release|x64 - {31FFC478-7B4A-43E8-9954-8D03E2187E9C}.Debug|ARM.ActiveCfg = Debug|ARM - {31FFC478-7B4A-43E8-9954-8D03E2187E9C}.Debug|ARM.Build.0 = Debug|ARM - {31FFC478-7B4A-43E8-9954-8D03E2187E9C}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {31FFC478-7B4A-43E8-9954-8D03E2187E9C}.Debug|ARM64.Build.0 = Debug|ARM64 - {31FFC478-7B4A-43E8-9954-8D03E2187E9C}.Debug|Win32.ActiveCfg = Debug|Win32 - {31FFC478-7B4A-43E8-9954-8D03E2187E9C}.Debug|Win32.Build.0 = Debug|Win32 - {31FFC478-7B4A-43E8-9954-8D03E2187E9C}.Debug|x64.ActiveCfg = Debug|x64 - {31FFC478-7B4A-43E8-9954-8D03E2187E9C}.Debug|x64.Build.0 = Debug|x64 - {31FFC478-7B4A-43E8-9954-8D03E2187E9C}.PGInstrument|ARM.ActiveCfg = PGInstrument|ARM - {31FFC478-7B4A-43E8-9954-8D03E2187E9C}.PGInstrument|ARM.Build.0 = PGInstrument|ARM - {31FFC478-7B4A-43E8-9954-8D03E2187E9C}.PGInstrument|ARM64.ActiveCfg = PGInstrument|ARM64 - {31FFC478-7B4A-43E8-9954-8D03E2187E9C}.PGInstrument|ARM64.Build.0 = PGInstrument|ARM64 - {31FFC478-7B4A-43E8-9954-8D03E2187E9C}.PGInstrument|Win32.ActiveCfg = PGInstrument|Win32 - {31FFC478-7B4A-43E8-9954-8D03E2187E9C}.PGInstrument|Win32.Build.0 = PGInstrument|Win32 - {31FFC478-7B4A-43E8-9954-8D03E2187E9C}.PGInstrument|x64.ActiveCfg = PGInstrument|x64 - {31FFC478-7B4A-43E8-9954-8D03E2187E9C}.PGInstrument|x64.Build.0 = PGInstrument|x64 - {31FFC478-7B4A-43E8-9954-8D03E2187E9C}.PGUpdate|ARM.ActiveCfg = PGUpdate|ARM - {31FFC478-7B4A-43E8-9954-8D03E2187E9C}.PGUpdate|ARM.Build.0 = PGUpdate|ARM - {31FFC478-7B4A-43E8-9954-8D03E2187E9C}.PGUpdate|ARM64.ActiveCfg = PGUpdate|ARM64 - {31FFC478-7B4A-43E8-9954-8D03E2187E9C}.PGUpdate|ARM64.Build.0 = PGUpdate|ARM64 - {31FFC478-7B4A-43E8-9954-8D03E2187E9C}.PGUpdate|Win32.ActiveCfg = PGUpdate|Win32 - {31FFC478-7B4A-43E8-9954-8D03E2187E9C}.PGUpdate|Win32.Build.0 = PGUpdate|Win32 - {31FFC478-7B4A-43E8-9954-8D03E2187E9C}.PGUpdate|x64.ActiveCfg = PGUpdate|x64 - {31FFC478-7B4A-43E8-9954-8D03E2187E9C}.PGUpdate|x64.Build.0 = PGUpdate|x64 - {31FFC478-7B4A-43E8-9954-8D03E2187E9C}.Release|ARM.ActiveCfg = Release|ARM - {31FFC478-7B4A-43E8-9954-8D03E2187E9C}.Release|ARM.Build.0 = Release|ARM - {31FFC478-7B4A-43E8-9954-8D03E2187E9C}.Release|ARM64.ActiveCfg = Release|ARM64 - {31FFC478-7B4A-43E8-9954-8D03E2187E9C}.Release|ARM64.Build.0 = Release|ARM64 - {31FFC478-7B4A-43E8-9954-8D03E2187E9C}.Release|Win32.ActiveCfg = Release|Win32 - {31FFC478-7B4A-43E8-9954-8D03E2187E9C}.Release|Win32.Build.0 = Release|Win32 - {31FFC478-7B4A-43E8-9954-8D03E2187E9C}.Release|x64.ActiveCfg = Release|x64 - {31FFC478-7B4A-43E8-9954-8D03E2187E9C}.Release|x64.Build.0 = Release|x64 {86937F53-C189-40EF-8CE8-8759D8E7D480}.Debug|ARM.ActiveCfg = Debug|ARM {86937F53-C189-40EF-8CE8-8759D8E7D480}.Debug|ARM.Build.0 = Debug|ARM {86937F53-C189-40EF-8CE8-8759D8E7D480}.Debug|ARM64.ActiveCfg = Debug|ARM64 @@ -1646,6 +1616,38 @@ Global {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 + {01FDF29A-40A1-46DF-84F5-85EBBD2A2410}.Debug|ARM.ActiveCfg = Debug|ARM + {01FDF29A-40A1-46DF-84F5-85EBBD2A2410}.Debug|ARM.Build.0 = Debug|ARM + {01FDF29A-40A1-46DF-84F5-85EBBD2A2410}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {01FDF29A-40A1-46DF-84F5-85EBBD2A2410}.Debug|ARM64.Build.0 = Debug|ARM64 + {01FDF29A-40A1-46DF-84F5-85EBBD2A2410}.Debug|Win32.ActiveCfg = Debug|Win32 + {01FDF29A-40A1-46DF-84F5-85EBBD2A2410}.Debug|Win32.Build.0 = Debug|Win32 + {01FDF29A-40A1-46DF-84F5-85EBBD2A2410}.Debug|x64.ActiveCfg = Debug|x64 + {01FDF29A-40A1-46DF-84F5-85EBBD2A2410}.Debug|x64.Build.0 = Debug|x64 + {01FDF29A-40A1-46DF-84F5-85EBBD2A2410}.PGInstrument|ARM.ActiveCfg = PGInstrument|ARM + {01FDF29A-40A1-46DF-84F5-85EBBD2A2410}.PGInstrument|ARM.Build.0 = PGInstrument|ARM + {01FDF29A-40A1-46DF-84F5-85EBBD2A2410}.PGInstrument|ARM64.ActiveCfg = PGInstrument|ARM64 + {01FDF29A-40A1-46DF-84F5-85EBBD2A2410}.PGInstrument|ARM64.Build.0 = PGInstrument|ARM64 + {01FDF29A-40A1-46DF-84F5-85EBBD2A2410}.PGInstrument|Win32.ActiveCfg = PGInstrument|Win32 + {01FDF29A-40A1-46DF-84F5-85EBBD2A2410}.PGInstrument|Win32.Build.0 = PGInstrument|Win32 + {01FDF29A-40A1-46DF-84F5-85EBBD2A2410}.PGInstrument|x64.ActiveCfg = PGInstrument|x64 + {01FDF29A-40A1-46DF-84F5-85EBBD2A2410}.PGInstrument|x64.Build.0 = PGInstrument|x64 + {01FDF29A-40A1-46DF-84F5-85EBBD2A2410}.PGUpdate|ARM.ActiveCfg = PGUpdate|ARM + {01FDF29A-40A1-46DF-84F5-85EBBD2A2410}.PGUpdate|ARM.Build.0 = PGUpdate|ARM + {01FDF29A-40A1-46DF-84F5-85EBBD2A2410}.PGUpdate|ARM64.ActiveCfg = PGUpdate|ARM64 + {01FDF29A-40A1-46DF-84F5-85EBBD2A2410}.PGUpdate|ARM64.Build.0 = PGUpdate|ARM64 + {01FDF29A-40A1-46DF-84F5-85EBBD2A2410}.PGUpdate|Win32.ActiveCfg = PGUpdate|Win32 + {01FDF29A-40A1-46DF-84F5-85EBBD2A2410}.PGUpdate|Win32.Build.0 = PGUpdate|Win32 + {01FDF29A-40A1-46DF-84F5-85EBBD2A2410}.PGUpdate|x64.ActiveCfg = PGUpdate|x64 + {01FDF29A-40A1-46DF-84F5-85EBBD2A2410}.PGUpdate|x64.Build.0 = PGUpdate|x64 + {01FDF29A-40A1-46DF-84F5-85EBBD2A2410}.Release|ARM.ActiveCfg = Release|ARM + {01FDF29A-40A1-46DF-84F5-85EBBD2A2410}.Release|ARM.Build.0 = Release|ARM + {01FDF29A-40A1-46DF-84F5-85EBBD2A2410}.Release|ARM64.ActiveCfg = Release|ARM64 + {01FDF29A-40A1-46DF-84F5-85EBBD2A2410}.Release|ARM64.Build.0 = Release|ARM64 + {01FDF29A-40A1-46DF-84F5-85EBBD2A2410}.Release|Win32.ActiveCfg = Release|Win32 + {01FDF29A-40A1-46DF-84F5-85EBBD2A2410}.Release|Win32.Build.0 = Release|Win32 + {01FDF29A-40A1-46DF-84F5-85EBBD2A2410}.Release|x64.ActiveCfg = Release|x64 + {01FDF29A-40A1-46DF-84F5-85EBBD2A2410}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/PCbuild/pyproject.props b/PCbuild/pyproject.props index fd928cafd77aaa..16ad91ef0278c8 100644 --- a/PCbuild/pyproject.props +++ b/PCbuild/pyproject.props @@ -10,6 +10,9 @@ $(MSBuildThisFileDirectory)obj\ $(Py_IntDir)\$(MajorVersionNumber)$(MinorVersionNumber)$(ArchName)_$(Configuration)\$(ProjectName)\ $(IntDir.Replace(`\\`, `\`)) + + $(Py_IntDir)\$(MajorVersionNumber)$(MinorVersionNumber)$(ArchName)_$(Configuration)\pythoncore\ + $(Py_IntDir)\$(MajorVersionNumber)$(MinorVersionNumber)_frozen\ $(ProjectName) $(TargetName)$(PyDebugExt) false @@ -26,6 +29,7 @@ true + true @@ -38,8 +42,9 @@ - $(PySourcePath)Include;$(PySourcePath)Include\internal;$(PySourcePath)PC;$(IntDir);%(AdditionalIncludeDirectories) + $(PySourcePath)Include;$(PySourcePath)Include\internal;$(PySourcePath)Include\internal\mimalloc;$(GeneratedPyConfigDir);$(PySourcePath)PC;%(AdditionalIncludeDirectories) WIN32;$(_Py3NamePreprocessorDefinition);$(_PlatformPreprocessorDefinition)$(_DebugPreprocessorDefinition)$(_PydPreprocessorDefinition)%(PreprocessorDefinitions) + _Py_USING_PGO=1;%(PreprocessorDefinitions) MaxSpeed true @@ -58,6 +63,8 @@ -Wno-deprecated-non-prototype -Wno-unused-label -Wno-pointer-sign -Wno-incompatible-pointer-types-discards-qualifiers -Wno-unused-function %(AdditionalOptions) -flto %(AdditionalOptions) -d2pattern-opt-disable:-932189325 %(AdditionalOptions) + -d2ssa-patterns-all- %(AdditionalOptions) + /sourceDependencies "$(IntDir.Trim(`\`))" %(AdditionalOptions) OnlyExplicitInline @@ -232,7 +239,10 @@ public override bool Execute() { - + + + + diff --git a/PCbuild/python.props b/PCbuild/python.props index d3586235c82652..3b7a8876a707df 100644 --- a/PCbuild/python.props +++ b/PCbuild/python.props @@ -68,14 +68,14 @@ - $(ExternalsDir)sqlite-3.42.0.0\ + $(ExternalsDir)sqlite-3.44.2.0\ $(ExternalsDir)bzip2-1.0.8\ $(ExternalsDir)xz-5.2.5\ $(ExternalsDir)libffi-3.4.4\ $(libffiDir)$(ArchName)\ $(libffiOutDir)include - $(ExternalsDir)openssl-3.0.9\ - $(ExternalsDir)openssl-bin-3.0.9\$(ArchName)\ + $(ExternalsDir)openssl-3.0.11\ + $(ExternalsDir)openssl-bin-3.0.11\$(ArchName)\ $(opensslOutDir)include $(ExternalsDir)\nasm-2.11.06\ $(ExternalsDir)\zlib-1.2.13\ diff --git a/PCbuild/python.vcxproj b/PCbuild/python.vcxproj index f4640454a73070..8b733865962373 100644 --- a/PCbuild/python.vcxproj +++ b/PCbuild/python.vcxproj @@ -95,7 +95,7 @@ Console 2000000 - 8000000 + 12000000 diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj index bfe59acf12a69d..a8b753ca489ab7 100644 --- a/PCbuild/pythoncore.vcxproj +++ b/PCbuild/pythoncore.vcxproj @@ -111,6 +111,7 @@ + $(GeneratedFrozenModulesDir);%(AdditionalIncludeDirectories) PREFIX=NULL; EXEC_PREFIX=NULL; @@ -158,7 +159,6 @@ - @@ -166,14 +166,18 @@ + + + + @@ -200,12 +204,11 @@ - - + @@ -215,6 +218,8 @@ + + @@ -226,6 +231,7 @@ + @@ -235,11 +241,15 @@ + + + + @@ -248,6 +258,8 @@ + + @@ -256,11 +268,14 @@ + + + @@ -272,6 +287,7 @@ + @@ -279,6 +295,7 @@ + @@ -289,6 +306,12 @@ + + + + + + @@ -298,6 +321,7 @@ + @@ -348,13 +372,16 @@ - + + + + + - + - @@ -398,6 +425,7 @@ + @@ -425,6 +453,7 @@ + @@ -432,6 +461,7 @@ + @@ -493,7 +523,14 @@ - + + + + + + + + @@ -518,16 +555,22 @@ + + - - + + $(GeneratedFrozenModulesDir)Python;%(AdditionalIncludeDirectories) + + + + @@ -543,11 +586,14 @@ + + + @@ -578,7 +624,7 @@ - + @@ -608,6 +654,35 @@ + + + + + + + + + + @(PyConfigH->'%(FullPath)', ';') + $([System.IO.File]::ReadAllText($(PyConfigH))) + $([System.IO.File]::ReadAllText('$(IntDir)pyconfig.h')) + + + $(PyConfigHText.Replace('#undef Py_GIL_DISABLED', '#define Py_GIL_DISABLED 1')) + + + + + + + + + + + git diff --git a/PCbuild/pythoncore.vcxproj.filters b/PCbuild/pythoncore.vcxproj.filters index 0a8b0c3faf51e1..965efa2e3d34b9 100644 --- a/PCbuild/pythoncore.vcxproj.filters +++ b/PCbuild/pythoncore.vcxproj.filters @@ -4,6 +4,9 @@ {086b0afb-270c-4603-a02a-63d46f0b2b92} + + {1dc8d8bd-d493-478e-9b7a-7eb108bb8bd5} + {8e81609f-13ca-4eae-9fdb-f8af20c710c7} @@ -19,6 +22,9 @@ {ab29a558-143d-4fe7-a039-b431fb429856} + + {ad449c55-23cb-44f8-ada4-04b23c9ec388} + {97349fee-0abf-48b0-a8f5-771bf39b8aee} @@ -144,6 +150,9 @@ Include + + Include + Include @@ -288,7 +297,19 @@ Objects - + + Parser + + + Parser + + + Parser + + + Parser + + Parser @@ -297,9 +318,6 @@ PC - - Python - Python @@ -405,9 +423,6 @@ Include\cpython - - Include\cpython - Include\cpython @@ -423,6 +438,18 @@ Include + + Include + + + Include + + + Include + + + Include + Include @@ -441,6 +468,9 @@ Include\cpython + + Include\cpython + Include\cpython @@ -480,6 +510,9 @@ Include\cpython + + Include\cpython + Include\cpython @@ -510,12 +543,6 @@ Include\internal - - Include\internal - - - Include - Include\internal @@ -528,6 +555,9 @@ Include\internal + + Include\internal + Include\internal @@ -552,6 +582,12 @@ Include\internal + + Include\internal + + + Include\internal + Include\internal @@ -582,6 +618,12 @@ Include\internal + + Include\internal + + + Include\internal + Include\internal @@ -609,9 +651,15 @@ Include\internal + + Include\internal + Include\internal + + Include\internal + Include\internal @@ -624,6 +672,12 @@ Include\internal + + Include\internal + + + Include\internal + Include\internal @@ -648,6 +702,12 @@ Include\internal + + Include\internal + + + Include\internal + Include\internal @@ -672,6 +732,12 @@ Include\internal + + Include\internal + + + Include\internal + Include\internal @@ -687,6 +753,9 @@ Include\internal + + Include\internal + Include\internal @@ -717,6 +786,9 @@ Include\internal + + Include\internal + Include\internal @@ -732,6 +804,27 @@ Include\internal + + Include\internal + + + Include\internal\mimalloc + + + Include\internal\mimalloc + + + Include\internal\mimalloc + + + Include\internal\mimalloc + + + Include\internal\mimalloc + + + Include\internal\mimalloc + Modules\zlib @@ -845,6 +938,9 @@ Modules + + Modules + Modules @@ -914,6 +1010,9 @@ Modules + + Modules + Modules @@ -1091,7 +1190,28 @@ Parser - + + Parser + + + Parser + + + Parser + + + Parser + + + Parser + + + Parser + + + Parser + + Parser @@ -1139,6 +1259,12 @@ Python + + Python + + + Source Files + Python @@ -1148,9 +1274,6 @@ Python - - Python - Python @@ -1166,6 +1289,15 @@ Python + + Python + + + Python + + + Python + Python @@ -1208,6 +1340,9 @@ Source Files + + Source Files + Python @@ -1223,6 +1358,12 @@ Python + + Python + + + Python + Python @@ -1382,6 +1523,9 @@ Modules + + Modules + Parser diff --git a/PCbuild/readme.txt b/PCbuild/readme.txt index 86ad3ab1a40d9c..b9d76515c383f7 100644 --- a/PCbuild/readme.txt +++ b/PCbuild/readme.txt @@ -144,6 +144,7 @@ _socket _testbuffer _testcapi _testclinic +_testclinic_limited _testconsole _testimportmultiple _testmultiphase @@ -188,7 +189,7 @@ _ssl again when building. _sqlite3 - Wraps SQLite 3.42.0, which is itself built by sqlite3.vcxproj + Wraps SQLite 3.44.2, which is itself built by sqlite3.vcxproj Homepage: https://www.sqlite.org/ _tkinter @@ -251,9 +252,11 @@ against a profiling library and contain extra debug information. The PGUpdate configuration takes the profiling data and generates optimized binaries. -The build_pgo.bat script automates the creation of optimized binaries. -It creates the PGI files, runs the unit test suite or PyBench with the -PGI python, and finally creates the optimized files. +The build.bat script has an argument `--pgo` that automate the creation +of optimized binaries. +It creates the PGI files, runs the unit test suite with the PGI python, +and finally creates the optimized files. +You can customize the job for profiling with `--pgo-job ` option. See https://docs.microsoft.com/en-us/cpp/build/profile-guided-optimizations @@ -290,3 +293,31 @@ project, with some projects overriding certain specific values. The GUI doesn't always reflect the correct settings and may confuse the user with false information, especially for settings that automatically adapt for different configurations. + +Add a new project +----------------- + +For example, add a new _testclinic_limited project to build a new +_testclinic_limited extension, the file Modules/_testclinic_limited.c: + +* In PCbuild/, copy _testclinic.vcxproj to _testclinic_limited.vcxproj, + replace RootNamespace value with `_testclinic_limited`, replace + `_asyncio.c` with `_testclinic_limited.c`. +* Open Visual Studio, open PCbuild\pcbuild.sln solution, add the + PCbuild\_testclinic_limited.vcxproj project to the solution ("add existing + project). +* Add a dependency on the python project to the new _testclinic_limited + project. +* Save and exit Visual Studio. +* Add `;_testclinic_limited` to `` in + PCbuild\pcbuild.proj. +* Update "exts" in Tools\msi\lib\lib_files.wxs file or in + Tools\msi\test\test_files.wxs file (for tests). +* PC\layout\main.py needs updating if you add a test-only extension whose name + doesn't start with "_test". +* Add the extension to PCbuild\readme.txt (this file). +* Build Python from scratch (clean the solution) to check that the new project + is built successfully. +* Ensure the new .vcxproj and .vcxproj.filters files are added to your commit, + as well as the changes to pcbuild.sln, pcbuild.proj and any other modified + files. diff --git a/PCbuild/regen.targets b/PCbuild/regen.targets index 99cfff5acc0baf..cc9469c7ddd726 100644 --- a/PCbuild/regen.targets +++ b/PCbuild/regen.targets @@ -13,8 +13,6 @@ <_ASTOutputs Include="$(PySourcePath)Python\Python-ast.c"> -C - <_OpcodeSources Include="$(PySourcePath)Tools\build\generate_opcode_h.py;$(PySourcePath)Lib\opcode.py" /> - <_OpcodeOutputs Include="$(PySourcePath)Include\opcode.h;$(PySourcePath)Include\internal\pycore_opcode.h;$(PySourcePath)Python\opcode_targets.h" /> <_TokenSources Include="$(PySourcePath)Grammar\Tokens" /> <_TokenOutputs Include="$(PySourcePath)Doc\library\token-list.inc"> rst @@ -34,7 +32,7 @@ - @@ -55,14 +53,6 @@ WorkingDirectory="$(PySourcePath)" /> - - - - - @@ -89,7 +79,7 @@ + DependsOnTargets="_TouchRegenSources;_RegenPegen;_RegenAST_H;_RegenTokens;_RegenKeywords;_RegenGlobalObjects"> diff --git a/PCbuild/rt.bat b/PCbuild/rt.bat index 29813c5a87fca7..332ba5edcf4082 100644 --- a/PCbuild/rt.bat +++ b/PCbuild/rt.bat @@ -32,7 +32,7 @@ set pcbuild=%~dp0 set suffix= set qmode= set dashO= -set regrtestargs= +set regrtestargs=--fast-ci set exe= :CheckOpts @@ -48,7 +48,7 @@ if NOT "%1"=="" (set regrtestargs=%regrtestargs% %1) & shift & goto CheckOpts if not defined prefix set prefix=%pcbuild%amd64 set exe=%prefix%\python%suffix%.exe -set cmd="%exe%" %dashO% -u -Wd -E -bb -m test %regrtestargs% +set cmd="%exe%" %dashO% -m test %regrtestargs% if defined qmode goto Qmode echo Deleting .pyc files ... diff --git a/PCbuild/tcltk.props b/PCbuild/tcltk.props index 96dd289face6a5..8ddf01d5dd1dca 100644 --- a/PCbuild/tcltk.props +++ b/PCbuild/tcltk.props @@ -2,7 +2,7 @@ - 8.6.13.0 + 8.6.13.1 $(TclVersion) $([System.Version]::Parse($(TclVersion)).Major) $([System.Version]::Parse($(TclVersion)).Minor) diff --git a/Parser/action_helpers.c b/Parser/action_helpers.c index 36e0750220a30d..3f6c282ffa7a68 100644 --- a/Parser/action_helpers.c +++ b/Parser/action_helpers.c @@ -1,7 +1,6 @@ #include #include "pegen.h" -#include "tokenizer.h" #include "string_parser.h" #include "pycore_runtime.h" // _PyRuntime @@ -119,38 +118,8 @@ expr_ty _PyPegen_join_names_with_dot(Parser *p, expr_ty first_name, expr_ty second_name) { assert(first_name != NULL && second_name != NULL); - PyObject *first_identifier = first_name->v.Name.id; - PyObject *second_identifier = second_name->v.Name.id; - - const char *first_str = PyUnicode_AsUTF8(first_identifier); - if (!first_str) { - return NULL; - } - const char *second_str = PyUnicode_AsUTF8(second_identifier); - if (!second_str) { - return NULL; - } - Py_ssize_t len = strlen(first_str) + strlen(second_str) + 1; // +1 for the dot - - PyObject *str = PyBytes_FromStringAndSize(NULL, len); - if (!str) { - return NULL; - } - - char *s = PyBytes_AS_STRING(str); - if (!s) { - return NULL; - } - - strcpy(s, first_str); - s += strlen(first_str); - *s++ = '.'; - strcpy(s, second_str); - s += strlen(second_str); - *s = '\0'; - - PyObject *uni = PyUnicode_DecodeUTF8(PyBytes_AS_STRING(str), PyBytes_GET_SIZE(str), NULL); - Py_DECREF(str); + PyObject *uni = PyUnicode_FromFormat("%U.%U", + first_name->v.Name.id, second_name->v.Name.id); if (!uni) { return NULL; } @@ -998,18 +967,38 @@ _PyPegen_setup_full_format_spec(Parser *p, Token *colon, asdl_expr_seq *spec, in return NULL; } - // This is needed to keep compatibility with 3.11, where an empty format spec is parsed - // as an *empty* JoinedStr node, instead of having an empty constant in it. - if (asdl_seq_LEN(spec) == 1) { - expr_ty e = asdl_seq_GET(spec, 0); - if (e->kind == Constant_kind - && PyUnicode_Check(e->v.Constant.value) - && PyUnicode_GetLength(e->v.Constant.value) == 0) { - spec = _Py_asdl_expr_seq_new(0, arena); + // This is needed to keep compatibility with 3.11, where an empty format + // spec is parsed as an *empty* JoinedStr node, instead of having an empty + // constant in it. + Py_ssize_t n_items = asdl_seq_LEN(spec); + Py_ssize_t non_empty_count = 0; + for (Py_ssize_t i = 0; i < n_items; i++) { + expr_ty item = asdl_seq_GET(spec, i); + non_empty_count += !(item->kind == Constant_kind && + PyUnicode_CheckExact(item->v.Constant.value) && + PyUnicode_GET_LENGTH(item->v.Constant.value) == 0); + } + if (non_empty_count != n_items) { + asdl_expr_seq *resized_spec = + _Py_asdl_expr_seq_new(non_empty_count, p->arena); + if (resized_spec == NULL) { + return NULL; } + Py_ssize_t j = 0; + for (Py_ssize_t i = 0; i < n_items; i++) { + expr_ty item = asdl_seq_GET(spec, i); + if (item->kind == Constant_kind && + PyUnicode_CheckExact(item->v.Constant.value) && + PyUnicode_GET_LENGTH(item->v.Constant.value) == 0) { + continue; + } + asdl_seq_SET(resized_spec, j++, item); + } + assert(j == non_empty_count); + spec = resized_spec; } - - expr_ty res = _PyAST_JoinedStr(spec, lineno, col_offset, end_lineno, end_col_offset, p->arena); + expr_ty res = _PyAST_JoinedStr(spec, lineno, col_offset, end_lineno, + end_col_offset, p->arena); if (!res) { return NULL; } diff --git a/Parser/asdl_c.py b/Parser/asdl_c.py index 2a36610527f898..4bb337349748cf 100755 --- a/Parser/asdl_c.py +++ b/Parser/asdl_c.py @@ -518,7 +518,7 @@ def sumTrailer(self, name, add_label=False): if add_label: self.emit("failed:", 1) self.emit("Py_XDECREF(tmp);", 1) - self.emit("return 1;", 1) + self.emit("return -1;", 1) self.emit("}", 0) self.emit("", 0) @@ -529,7 +529,7 @@ def simpleSum(self, sum, name): "state->%s_type);") self.emit(line % (t.name,), 1) self.emit("if (isinstance == -1) {", 1) - self.emit("return 1;", 2) + self.emit("return -1;", 2) self.emit("}", 1) self.emit("if (isinstance) {", 1) self.emit("*out = %s;" % t.name, 2) @@ -558,7 +558,7 @@ def complexSum(self, sum, name): self.emit("tp = state->%s_type;" % (t.name,), 1) self.emit("isinstance = PyObject_IsInstance(obj, tp);", 1) self.emit("if (isinstance == -1) {", 1) - self.emit("return 1;", 2) + self.emit("return -1;", 2) self.emit("}", 1) self.emit("if (isinstance) {", 1) for f in t.fields: @@ -605,7 +605,7 @@ def visitProduct(self, prod, name): self.emit("return 0;", 1) self.emit("failed:", 0) self.emit("Py_XDECREF(tmp);", 1) - self.emit("return 1;", 1) + self.emit("return -1;", 1) self.emit("}", 0) self.emit("", 0) @@ -631,13 +631,13 @@ def visitField(self, field, name, sum=None, prod=None, depth=0): ctype = get_c_type(field.type) line = "if (PyObject_GetOptionalAttr(obj, state->%s, &tmp) < 0) {" self.emit(line % field.name, depth) - self.emit("return 1;", depth+1) + self.emit("return -1;", depth+1) self.emit("}", depth) if field.seq: self.emit("if (tmp == NULL) {", depth) self.emit("tmp = PyList_New(0);", depth+1) self.emit("if (tmp == NULL) {", depth+1) - self.emit("return 1;", depth+2) + self.emit("return -1;", depth+2) self.emit("}", depth+1) self.emit("}", depth) self.emit("{", depth) @@ -647,7 +647,7 @@ def visitField(self, field, name, sum=None, prod=None, depth=0): message = "required field \\\"%s\\\" missing from %s" % (field.name, name) format = "PyErr_SetString(PyExc_TypeError, \"%s\");" self.emit(format % message, depth+1, reflow=False) - self.emit("return 1;", depth+1) + self.emit("return -1;", depth+1) else: self.emit("if (tmp == NULL || tmp == Py_None) {", depth) self.emit("Py_CLEAR(tmp);", depth+1) @@ -731,7 +731,7 @@ def emit_sequence_constructor(self, name, type): class PyTypesDeclareVisitor(PickleVisitor): def visitProduct(self, prod, name): - self.emit("static PyObject* ast2obj_%s(struct ast_state *state, void*);" % name, 0) + self.emit("static PyObject* ast2obj_%s(struct ast_state *state, struct validator *vstate, void*);" % name, 0) if prod.attributes: self.emit("static const char * const %s_attributes[] = {" % name, 0) for a in prod.attributes: @@ -752,7 +752,7 @@ def visitSum(self, sum, name): ptype = "void*" if is_simple(sum): ptype = get_c_type(name) - self.emit("static PyObject* ast2obj_%s(struct ast_state *state, %s);" % (name, ptype), 0) + self.emit("static PyObject* ast2obj_%s(struct ast_state *state, struct validator *vstate, %s);" % (name, ptype), 0) for t in sum.types: self.visitConstructor(t, name) @@ -968,23 +968,24 @@ def visitModule(self, mod): int i, result; PyObject *s, *l = PyTuple_New(num_fields); if (!l) - return 0; + return -1; for (i = 0; i < num_fields; i++) { s = PyUnicode_InternFromString(attrs[i]); if (!s) { Py_DECREF(l); - return 0; + return -1; } PyTuple_SET_ITEM(l, i, s); } - result = PyObject_SetAttr(type, state->_attributes, l) >= 0; + result = PyObject_SetAttr(type, state->_attributes, l); Py_DECREF(l); return result; } /* Conversion AST -> Python */ -static PyObject* ast2obj_list(struct ast_state *state, asdl_seq *seq, PyObject* (*func)(struct ast_state *state, void*)) +static PyObject* ast2obj_list(struct ast_state *state, struct validator *vstate, asdl_seq *seq, + PyObject* (*func)(struct ast_state *state, struct validator *vstate, void*)) { Py_ssize_t i, n = asdl_seq_LEN(seq); PyObject *result = PyList_New(n); @@ -992,7 +993,7 @@ def visitModule(self, mod): if (!result) return NULL; for (i = 0; i < n; i++) { - value = func(state, asdl_seq_GET_UNTYPED(seq, i)); + value = func(state, vstate, asdl_seq_GET_UNTYPED(seq, i)); if (!value) { Py_DECREF(result); return NULL; @@ -1002,7 +1003,7 @@ def visitModule(self, mod): return result; } -static PyObject* ast2obj_object(struct ast_state *Py_UNUSED(state), void *o) +static PyObject* ast2obj_object(struct ast_state *Py_UNUSED(state), struct validator *Py_UNUSED(vstate), void *o) { PyObject *op = (PyObject*)o; if (!op) { @@ -1014,7 +1015,7 @@ def visitModule(self, mod): #define ast2obj_identifier ast2obj_object #define ast2obj_string ast2obj_object -static PyObject* ast2obj_int(struct ast_state *Py_UNUSED(state), long b) +static PyObject* ast2obj_int(struct ast_state *Py_UNUSED(state), struct validator *Py_UNUSED(vstate), long b) { return PyLong_FromLong(b); } @@ -1052,7 +1053,7 @@ def visitModule(self, mod): { if (!PyUnicode_CheckExact(obj) && obj != Py_None) { PyErr_SetString(PyExc_TypeError, "AST identifier must be of type str"); - return 1; + return -1; } return obj2ast_object(state, obj, out, arena); } @@ -1061,7 +1062,7 @@ def visitModule(self, mod): { if (!PyUnicode_CheckExact(obj) && !PyBytes_CheckExact(obj)) { PyErr_SetString(PyExc_TypeError, "AST string must be of type str"); - return 1; + return -1; } return obj2ast_object(state, obj, out, arena); } @@ -1071,12 +1072,12 @@ def visitModule(self, mod): int i; if (!PyLong_Check(obj)) { PyErr_Format(PyExc_ValueError, "invalid integer value: %R", obj); - return 1; + return -1; } - i = _PyLong_AsInt(obj); + i = PyLong_AsInt(obj); if (i == -1 && PyErr_Occurred()) - return 1; + return -1; *out = i; return 0; } @@ -1102,31 +1103,21 @@ def visitModule(self, mod): static int init_types(struct ast_state *state) { - // init_types() must not be called after _PyAST_Fini() - // has been called - assert(state->initialized >= 0); - - if (state->initialized) { - return 1; - } if (init_identifiers(state) < 0) { - return 0; + return -1; } state->AST_type = PyType_FromSpec(&AST_type_spec); if (!state->AST_type) { - return 0; + return -1; } if (add_ast_fields(state) < 0) { - return 0; + return -1; } ''')) for dfn in mod.dfns: self.visit(dfn) self.file.write(textwrap.dedent(''' - state->recursion_depth = 0; - state->recursion_limit = 0; - state->initialized = 1; - return 1; + return 0; } ''')) @@ -1138,12 +1129,12 @@ def visitProduct(self, prod, name): self.emit('state->%s_type = make_type(state, "%s", state->AST_type, %s, %d,' % (name, name, fields, len(prod.fields)), 1) self.emit('%s);' % reflow_c_string(asdl_of(name, prod), 2), 2, reflow=False) - self.emit("if (!state->%s_type) return 0;" % name, 1) + self.emit("if (!state->%s_type) return -1;" % name, 1) if prod.attributes: - self.emit("if (!add_attributes(state, state->%s_type, %s_attributes, %d)) return 0;" % + self.emit("if (add_attributes(state, state->%s_type, %s_attributes, %d) < 0) return -1;" % (name, name, len(prod.attributes)), 1) else: - self.emit("if (!add_attributes(state, state->%s_type, NULL, 0)) return 0;" % name, 1) + self.emit("if (add_attributes(state, state->%s_type, NULL, 0) < 0) return -1;" % name, 1) self.emit_defaults(name, prod.fields, 1) self.emit_defaults(name, prod.attributes, 1) @@ -1151,12 +1142,12 @@ def visitSum(self, sum, name): self.emit('state->%s_type = make_type(state, "%s", state->AST_type, NULL, 0,' % (name, name), 1) self.emit('%s);' % reflow_c_string(asdl_of(name, sum), 2), 2, reflow=False) - self.emit("if (!state->%s_type) return 0;" % name, 1) + self.emit("if (!state->%s_type) return -1;" % name, 1) if sum.attributes: - self.emit("if (!add_attributes(state, state->%s_type, %s_attributes, %d)) return 0;" % + self.emit("if (add_attributes(state, state->%s_type, %s_attributes, %d) < 0) return -1;" % (name, name, len(sum.attributes)), 1) else: - self.emit("if (!add_attributes(state, state->%s_type, NULL, 0)) return 0;" % name, 1) + self.emit("if (add_attributes(state, state->%s_type, NULL, 0) < 0) return -1;" % name, 1) self.emit_defaults(name, sum.attributes, 1) simple = is_simple(sum) for t in sum.types: @@ -1170,20 +1161,20 @@ def visitConstructor(self, cons, name, simple): self.emit('state->%s_type = make_type(state, "%s", state->%s_type, %s, %d,' % (cons.name, cons.name, name, fields, len(cons.fields)), 1) self.emit('%s);' % reflow_c_string(asdl_of(cons.name, cons), 2), 2, reflow=False) - self.emit("if (!state->%s_type) return 0;" % cons.name, 1) + self.emit("if (!state->%s_type) return -1;" % cons.name, 1) self.emit_defaults(cons.name, cons.fields, 1) if simple: self.emit("state->%s_singleton = PyType_GenericNew((PyTypeObject *)" "state->%s_type, NULL, NULL);" % (cons.name, cons.name), 1) - self.emit("if (!state->%s_singleton) return 0;" % cons.name, 1) + self.emit("if (!state->%s_singleton) return -1;" % cons.name, 1) def emit_defaults(self, name, fields, depth): for field in fields: if field.opt: self.emit('if (PyObject_SetAttr(state->%s_type, state->%s, Py_None) == -1)' % (name, field.name), depth) - self.emit("return 0;", depth+1) + self.emit("return -1;", depth+1) class ASTModuleVisitor(PickleVisitor): @@ -1208,6 +1199,9 @@ def visitModule(self, mod): self.emit('if (PyModule_AddIntMacro(m, PyCF_TYPE_COMMENTS) < 0) {', 1) self.emit("return -1;", 2) self.emit('}', 1) + self.emit('if (PyModule_AddIntMacro(m, PyCF_OPTIMIZED_AST) < 0) {', 1) + self.emit("return -1;", 2) + self.emit('}', 1) for dfn in mod.dfns: self.visit(dfn) self.emit("return 0;", 1) @@ -1265,7 +1259,7 @@ class ObjVisitor(PickleVisitor): def func_begin(self, name): ctype = get_c_type(name) self.emit("PyObject*", 0) - self.emit("ast2obj_%s(struct ast_state *state, void* _o)" % (name), 0) + self.emit("ast2obj_%s(struct ast_state *state, struct validator *vstate, void* _o)" % (name), 0) self.emit("{", 0) self.emit("%s o = (%s)_o;" % (ctype, ctype), 1) self.emit("PyObject *result = NULL, *value = NULL;", 1) @@ -1273,16 +1267,17 @@ def func_begin(self, name): self.emit('if (!o) {', 1) self.emit("Py_RETURN_NONE;", 2) self.emit("}", 1) - self.emit("if (++state->recursion_depth > state->recursion_limit) {", 1) + self.emit("if (++vstate->recursion_depth > vstate->recursion_limit) {", 1) self.emit("PyErr_SetString(PyExc_RecursionError,", 2) self.emit('"maximum recursion depth exceeded during ast construction");', 3) - self.emit("return 0;", 2) + self.emit("return NULL;", 2) self.emit("}", 1) def func_end(self): - self.emit("state->recursion_depth--;", 1) + self.emit("vstate->recursion_depth--;", 1) self.emit("return result;", 1) self.emit("failed:", 0) + self.emit("vstate->recursion_depth--;", 1) self.emit("Py_XDECREF(value);", 1) self.emit("Py_XDECREF(result);", 1) self.emit("return NULL;", 1) @@ -1300,7 +1295,7 @@ def visitSum(self, sum, name): self.visitConstructor(t, i + 1, name) self.emit("}", 1) for a in sum.attributes: - self.emit("value = ast2obj_%s(state, o->%s);" % (a.type, a.name), 1) + self.emit("value = ast2obj_%s(state, vstate, o->%s);" % (a.type, a.name), 1) self.emit("if (!value) goto failed;", 1) self.emit('if (PyObject_SetAttr(result, state->%s, value) < 0)' % a.name, 1) self.emit('goto failed;', 2) @@ -1308,7 +1303,7 @@ def visitSum(self, sum, name): self.func_end() def simpleSum(self, sum, name): - self.emit("PyObject* ast2obj_%s(struct ast_state *state, %s_ty o)" % (name, name), 0) + self.emit("PyObject* ast2obj_%s(struct ast_state *state, struct validator *vstate, %s_ty o)" % (name, name), 0) self.emit("{", 0) self.emit("switch(o) {", 1) for t in sum.types: @@ -1326,7 +1321,7 @@ def visitProduct(self, prod, name): for field in prod.fields: self.visitField(field, name, 1, True) for a in prod.attributes: - self.emit("value = ast2obj_%s(state, o->%s);" % (a.type, a.name), 1) + self.emit("value = ast2obj_%s(state, vstate, o->%s);" % (a.type, a.name), 1) self.emit("if (!value) goto failed;", 1) self.emit("if (PyObject_SetAttr(result, state->%s, value) < 0)" % a.name, 1) self.emit('goto failed;', 2) @@ -1367,7 +1362,7 @@ def set(self, field, value, depth): self.emit("for(i = 0; i < n; i++)", depth+1) # This cannot fail, so no need for error handling self.emit( - "PyList_SET_ITEM(value, i, ast2obj_{0}(state, ({0}_ty)asdl_seq_GET({1}, i)));".format( + "PyList_SET_ITEM(value, i, ast2obj_{0}(state, vstate, ({0}_ty)asdl_seq_GET({1}, i)));".format( field.type, value ), @@ -1376,9 +1371,9 @@ def set(self, field, value, depth): ) self.emit("}", depth) else: - self.emit("value = ast2obj_list(state, (asdl_seq*)%s, ast2obj_%s);" % (value, field.type), depth) + self.emit("value = ast2obj_list(state, vstate, (asdl_seq*)%s, ast2obj_%s);" % (value, field.type), depth) else: - self.emit("value = ast2obj_%s(state, %s);" % (field.type, value), depth, reflow=False) + self.emit("value = ast2obj_%s(state, vstate, %s);" % (field.type, value), depth, reflow=False) class PartingShots(StaticVisitor): @@ -1396,21 +1391,22 @@ class PartingShots(StaticVisitor): int COMPILER_STACK_FRAME_SCALE = 2; PyThreadState *tstate = _PyThreadState_GET(); if (!tstate) { - return 0; + return NULL; } - state->recursion_limit = C_RECURSION_LIMIT * COMPILER_STACK_FRAME_SCALE; - int recursion_depth = C_RECURSION_LIMIT - tstate->c_recursion_remaining; + struct validator vstate; + vstate.recursion_limit = Py_C_RECURSION_LIMIT * COMPILER_STACK_FRAME_SCALE; + int recursion_depth = Py_C_RECURSION_LIMIT - tstate->c_recursion_remaining; starting_recursion_depth = recursion_depth * COMPILER_STACK_FRAME_SCALE; - state->recursion_depth = starting_recursion_depth; + vstate.recursion_depth = starting_recursion_depth; - PyObject *result = ast2obj_mod(state, t); + PyObject *result = ast2obj_mod(state, &vstate, t); /* Check that the recursion depth counting balanced correctly */ - if (result && state->recursion_depth != starting_recursion_depth) { + if (result && vstate.recursion_depth != starting_recursion_depth) { PyErr_Format(PyExc_SystemError, "AST constructor recursion depth mismatch (before=%d, after=%d)", - starting_recursion_depth, state->recursion_depth); - return 0; + starting_recursion_depth, vstate.recursion_depth); + return NULL; } return result; } @@ -1477,9 +1473,8 @@ def visit(self, object): def generate_ast_state(module_state, f): f.write('struct ast_state {\n') - f.write(' int initialized;\n') - f.write(' int recursion_depth;\n') - f.write(' int recursion_limit;\n') + f.write(' _PyOnceFlag once;\n') + f.write(' int finalized;\n') for s in module_state: f.write(' PyObject *' + s + ';\n') f.write('};') @@ -1497,11 +1492,8 @@ def generate_ast_fini(module_state, f): f.write(textwrap.dedent(""" Py_CLEAR(_Py_INTERP_CACHED_OBJECT(interp, str_replace_inf)); - #if !defined(NDEBUG) - state->initialized = -1; - #else - state->initialized = 0; - #endif + state->finalized = 1; + state->once = (_PyOnceFlag){0}; } """)) @@ -1540,10 +1532,16 @@ def generate_module_def(mod, metadata, f, internal_h): #include "pycore_ast.h" #include "pycore_ast_state.h" // struct ast_state #include "pycore_ceval.h" // _Py_EnterRecursiveCall + #include "pycore_lock.h" // _PyOnceFlag #include "pycore_interp.h" // _PyInterpreterState.ast #include "pycore_pystate.h" // _PyInterpreterState_GET() #include + struct validator { + int recursion_depth; /* current recursion depth */ + int recursion_limit; /* recursion limit */ + }; + // Forward declaration static int init_types(struct ast_state *state); @@ -1552,7 +1550,8 @@ def generate_module_def(mod, metadata, f, internal_h): { PyInterpreterState *interp = _PyInterpreterState_GET(); struct ast_state *state = &interp->ast; - if (!init_types(state)) { + assert(!state->finalized); + if (_PyOnceFlag_CallOnce(&state->once, (_Py_once_fn_t *)&init_types, state) < 0) { return NULL; } return state; @@ -1566,8 +1565,8 @@ def generate_module_def(mod, metadata, f, internal_h): for identifier in state_strings: f.write(' if ((state->' + identifier) f.write(' = PyUnicode_InternFromString("') - f.write(identifier + '")) == NULL) return 0;\n') - f.write(' return 1;\n') + f.write(identifier + '")) == NULL) return -1;\n') + f.write(' return 0;\n') f.write('};\n\n') def write_header(mod, metadata, f): @@ -1582,7 +1581,7 @@ def write_header(mod, metadata, f): # error "this header requires Py_BUILD_CORE define" #endif - #include "pycore_asdl.h" + #include "pycore_asdl.h" // _ASDL_SEQ_HEAD """).lstrip()) @@ -1625,6 +1624,9 @@ def write_internal_h_header(mod, f): print(textwrap.dedent(""" #ifndef Py_INTERNAL_AST_STATE_H #define Py_INTERNAL_AST_STATE_H + + #include "pycore_lock.h" // _PyOnceFlag + #ifdef __cplusplus extern "C" { #endif diff --git a/Parser/lexer/buffer.c b/Parser/lexer/buffer.c new file mode 100644 index 00000000000000..f6502bf8f7f2d1 --- /dev/null +++ b/Parser/lexer/buffer.c @@ -0,0 +1,76 @@ +#include "Python.h" +#include "errcode.h" + +#include "state.h" + +/* Traverse and remember all f-string buffers, in order to be able to restore + them after reallocating tok->buf */ +void +_PyLexer_remember_fstring_buffers(struct tok_state *tok) +{ + int index; + tokenizer_mode *mode; + + for (index = tok->tok_mode_stack_index; index >= 0; --index) { + mode = &(tok->tok_mode_stack[index]); + mode->f_string_start_offset = mode->f_string_start - tok->buf; + mode->f_string_multi_line_start_offset = mode->f_string_multi_line_start - tok->buf; + } +} + +/* Traverse and restore all f-string buffers after reallocating tok->buf */ +void +_PyLexer_restore_fstring_buffers(struct tok_state *tok) +{ + int index; + tokenizer_mode *mode; + + for (index = tok->tok_mode_stack_index; index >= 0; --index) { + mode = &(tok->tok_mode_stack[index]); + mode->f_string_start = tok->buf + mode->f_string_start_offset; + mode->f_string_multi_line_start = tok->buf + mode->f_string_multi_line_start_offset; + } +} + +/* Read a line of text from TOK into S, using the stream in TOK. + Return NULL on failure, else S. + + On entry, tok->decoding_buffer will be one of: + 1) NULL: need to call tok->decoding_readline to get a new line + 2) PyUnicodeObject *: decoding_feof has called tok->decoding_readline and + stored the result in tok->decoding_buffer + 3) PyByteArrayObject *: previous call to tok_readline_recode did not have enough room + (in the s buffer) to copy entire contents of the line read + by tok->decoding_readline. tok->decoding_buffer has the overflow. + In this case, tok_readline_recode is called in a loop (with an expanded buffer) + until the buffer ends with a '\n' (or until the end of the file is + reached): see tok_nextc and its calls to tok_reserve_buf. +*/ +int +_PyLexer_tok_reserve_buf(struct tok_state *tok, Py_ssize_t size) +{ + Py_ssize_t cur = tok->cur - tok->buf; + Py_ssize_t oldsize = tok->inp - tok->buf; + Py_ssize_t newsize = oldsize + Py_MAX(size, oldsize >> 1); + if (newsize > tok->end - tok->buf) { + char *newbuf = tok->buf; + Py_ssize_t start = tok->start == NULL ? -1 : tok->start - tok->buf; + Py_ssize_t line_start = tok->start == NULL ? -1 : tok->line_start - tok->buf; + Py_ssize_t multi_line_start = tok->multi_line_start - tok->buf; + _PyLexer_remember_fstring_buffers(tok); + newbuf = (char *)PyMem_Realloc(newbuf, newsize); + if (newbuf == NULL) { + tok->done = E_NOMEM; + return 0; + } + tok->buf = newbuf; + tok->cur = tok->buf + cur; + tok->inp = tok->buf + oldsize; + tok->end = tok->buf + newsize; + tok->start = start < 0 ? NULL : tok->buf + start; + tok->line_start = line_start < 0 ? NULL : tok->buf + line_start; + tok->multi_line_start = multi_line_start < 0 ? NULL : tok->buf + multi_line_start; + _PyLexer_restore_fstring_buffers(tok); + } + return 1; +} diff --git a/Parser/lexer/buffer.h b/Parser/lexer/buffer.h new file mode 100644 index 00000000000000..bb218162ff4845 --- /dev/null +++ b/Parser/lexer/buffer.h @@ -0,0 +1,10 @@ +#ifndef _LEXER_BUFFER_H_ +#define _LEXER_BUFFER_H_ + +#include "pyport.h" + +void _PyLexer_remember_fstring_buffers(struct tok_state *tok); +void _PyLexer_restore_fstring_buffers(struct tok_state *tok); +int _PyLexer_tok_reserve_buf(struct tok_state *tok, Py_ssize_t size); + +#endif diff --git a/Parser/lexer/lexer.c b/Parser/lexer/lexer.c new file mode 100644 index 00000000000000..ebf7686773ff45 --- /dev/null +++ b/Parser/lexer/lexer.c @@ -0,0 +1,1484 @@ +#include "Python.h" +#include "pycore_token.h" +#include "pycore_unicodeobject.h" +#include "errcode.h" + +#include "state.h" +#include "../tokenizer/helpers.h" + +/* Alternate tab spacing */ +#define ALTTABSIZE 1 + +#define is_potential_identifier_start(c) (\ + (c >= 'a' && c <= 'z')\ + || (c >= 'A' && c <= 'Z')\ + || c == '_'\ + || (c >= 128)) + +#define is_potential_identifier_char(c) (\ + (c >= 'a' && c <= 'z')\ + || (c >= 'A' && c <= 'Z')\ + || (c >= '0' && c <= '9')\ + || c == '_'\ + || (c >= 128)) + +#ifdef Py_DEBUG +static inline tokenizer_mode* TOK_GET_MODE(struct tok_state* tok) { + assert(tok->tok_mode_stack_index >= 0); + assert(tok->tok_mode_stack_index < MAXFSTRINGLEVEL); + return &(tok->tok_mode_stack[tok->tok_mode_stack_index]); +} +static inline tokenizer_mode* TOK_NEXT_MODE(struct tok_state* tok) { + assert(tok->tok_mode_stack_index >= 0); + assert(tok->tok_mode_stack_index + 1 < MAXFSTRINGLEVEL); + return &(tok->tok_mode_stack[++tok->tok_mode_stack_index]); +} +#else +#define TOK_GET_MODE(tok) (&(tok->tok_mode_stack[tok->tok_mode_stack_index])) +#define TOK_NEXT_MODE(tok) (&(tok->tok_mode_stack[++tok->tok_mode_stack_index])) +#endif + +#define MAKE_TOKEN(token_type) _PyLexer_token_setup(tok, token, token_type, p_start, p_end) +#define MAKE_TYPE_COMMENT_TOKEN(token_type, col_offset, end_col_offset) (\ + _PyLexer_type_comment_token_setup(tok, token, token_type, col_offset, end_col_offset, p_start, p_end)) + +/* Spaces in this constant are treated as "zero or more spaces or tabs" when + tokenizing. */ +static const char* type_comment_prefix = "# type: "; + +static inline int +contains_null_bytes(const char* str, size_t size) +{ + return memchr(str, 0, size) != NULL; +} + +/* Get next char, updating state; error code goes into tok->done */ +static int +tok_nextc(struct tok_state *tok) +{ + int rc; + for (;;) { + if (tok->cur != tok->inp) { + if ((unsigned int) tok->col_offset >= (unsigned int) INT_MAX) { + tok->done = E_COLUMNOVERFLOW; + return EOF; + } + tok->col_offset++; + return Py_CHARMASK(*tok->cur++); /* Fast path */ + } + if (tok->done != E_OK) { + return EOF; + } + rc = tok->underflow(tok); +#if defined(Py_DEBUG) + if (tok->debug) { + fprintf(stderr, "line[%d] = ", tok->lineno); + _PyTokenizer_print_escape(stderr, tok->cur, tok->inp - tok->cur); + fprintf(stderr, " tok->done = %d\n", tok->done); + } +#endif + if (!rc) { + tok->cur = tok->inp; + return EOF; + } + tok->line_start = tok->cur; + + if (contains_null_bytes(tok->line_start, tok->inp - tok->line_start)) { + _PyTokenizer_syntaxerror(tok, "source code cannot contain null bytes"); + tok->cur = tok->inp; + return EOF; + } + } + Py_UNREACHABLE(); +} + +/* Back-up one character */ +static void +tok_backup(struct tok_state *tok, int c) +{ + if (c != EOF) { + if (--tok->cur < tok->buf) { + Py_FatalError("tokenizer beginning of buffer"); + } + if ((int)(unsigned char)*tok->cur != Py_CHARMASK(c)) { + Py_FatalError("tok_backup: wrong character"); + } + tok->col_offset--; + } +} + +static int +set_fstring_expr(struct tok_state* tok, struct token *token, char c) { + assert(token != NULL); + assert(c == '}' || c == ':' || c == '!'); + tokenizer_mode *tok_mode = TOK_GET_MODE(tok); + + if (!tok_mode->f_string_debug || token->metadata) { + return 0; + } + PyObject *res = NULL; + + // Check if there is a # character in the expression + int hash_detected = 0; + for (Py_ssize_t i = 0; i < tok_mode->last_expr_size - tok_mode->last_expr_end; i++) { + if (tok_mode->last_expr_buffer[i] == '#') { + hash_detected = 1; + break; + } + } + + if (hash_detected) { + Py_ssize_t input_length = tok_mode->last_expr_size - tok_mode->last_expr_end; + char *result = (char *)PyObject_Malloc((input_length + 1) * sizeof(char)); + if (!result) { + return -1; + } + + Py_ssize_t i = 0; + Py_ssize_t j = 0; + + for (i = 0, j = 0; i < input_length; i++) { + if (tok_mode->last_expr_buffer[i] == '#') { + // Skip characters until newline or end of string + while (tok_mode->last_expr_buffer[i] != '\0' && i < input_length) { + if (tok_mode->last_expr_buffer[i] == '\n') { + result[j++] = tok_mode->last_expr_buffer[i]; + break; + } + i++; + } + } else { + result[j++] = tok_mode->last_expr_buffer[i]; + } + } + + result[j] = '\0'; // Null-terminate the result string + res = PyUnicode_DecodeUTF8(result, j, NULL); + PyObject_Free(result); + } else { + res = PyUnicode_DecodeUTF8( + tok_mode->last_expr_buffer, + tok_mode->last_expr_size - tok_mode->last_expr_end, + NULL + ); + + } + + + if (!res) { + return -1; + } + token->metadata = res; + return 0; +} + +int +_PyLexer_update_fstring_expr(struct tok_state *tok, char cur) +{ + assert(tok->cur != NULL); + + Py_ssize_t size = strlen(tok->cur); + tokenizer_mode *tok_mode = TOK_GET_MODE(tok); + + switch (cur) { + case 0: + if (!tok_mode->last_expr_buffer || tok_mode->last_expr_end >= 0) { + return 1; + } + char *new_buffer = PyMem_Realloc( + tok_mode->last_expr_buffer, + tok_mode->last_expr_size + size + ); + if (new_buffer == NULL) { + PyMem_Free(tok_mode->last_expr_buffer); + goto error; + } + tok_mode->last_expr_buffer = new_buffer; + strncpy(tok_mode->last_expr_buffer + tok_mode->last_expr_size, tok->cur, size); + tok_mode->last_expr_size += size; + break; + case '{': + if (tok_mode->last_expr_buffer != NULL) { + PyMem_Free(tok_mode->last_expr_buffer); + } + tok_mode->last_expr_buffer = PyMem_Malloc(size); + if (tok_mode->last_expr_buffer == NULL) { + goto error; + } + tok_mode->last_expr_size = size; + tok_mode->last_expr_end = -1; + strncpy(tok_mode->last_expr_buffer, tok->cur, size); + break; + case '}': + case '!': + case ':': + if (tok_mode->last_expr_end == -1) { + tok_mode->last_expr_end = strlen(tok->start); + } + break; + default: + Py_UNREACHABLE(); + } + return 1; +error: + tok->done = E_NOMEM; + return 0; +} + +static int +lookahead(struct tok_state *tok, const char *test) +{ + const char *s = test; + int res = 0; + while (1) { + int c = tok_nextc(tok); + if (*s == 0) { + res = !is_potential_identifier_char(c); + } + else if (c == *s) { + s++; + continue; + } + + tok_backup(tok, c); + while (s != test) { + tok_backup(tok, *--s); + } + return res; + } +} + +static int +verify_end_of_number(struct tok_state *tok, int c, const char *kind) { + if (tok->tok_extra_tokens) { + // When we are parsing extra tokens, we don't want to emit warnings + // about invalid literals, because we want to be a bit more liberal. + return 1; + } + /* Emit a deprecation warning only if the numeric literal is immediately + * followed by one of keywords which can occur after a numeric literal + * in valid code: "and", "else", "for", "if", "in", "is" and "or". + * It allows to gradually deprecate existing valid code without adding + * warning before error in most cases of invalid numeric literal (which + * would be confusing and break existing tests). + * Raise a syntax error with slightly better message than plain + * "invalid syntax" if the numeric literal is immediately followed by + * other keyword or identifier. + */ + int r = 0; + if (c == 'a') { + r = lookahead(tok, "nd"); + } + else if (c == 'e') { + r = lookahead(tok, "lse"); + } + else if (c == 'f') { + r = lookahead(tok, "or"); + } + else if (c == 'i') { + int c2 = tok_nextc(tok); + if (c2 == 'f' || c2 == 'n' || c2 == 's') { + r = 1; + } + tok_backup(tok, c2); + } + else if (c == 'o') { + r = lookahead(tok, "r"); + } + else if (c == 'n') { + r = lookahead(tok, "ot"); + } + if (r) { + tok_backup(tok, c); + if (_PyTokenizer_parser_warn(tok, PyExc_SyntaxWarning, + "invalid %s literal", kind)) + { + return 0; + } + tok_nextc(tok); + } + else /* In future releases, only error will remain. */ + if (c < 128 && is_potential_identifier_char(c)) { + tok_backup(tok, c); + _PyTokenizer_syntaxerror(tok, "invalid %s literal", kind); + return 0; + } + return 1; +} + +/* Verify that the identifier follows PEP 3131. + All identifier strings are guaranteed to be "ready" unicode objects. + */ +static int +verify_identifier(struct tok_state *tok) +{ + if (tok->tok_extra_tokens) { + return 1; + } + PyObject *s; + if (tok->decoding_erred) + return 0; + s = PyUnicode_DecodeUTF8(tok->start, tok->cur - tok->start, NULL); + if (s == NULL) { + if (PyErr_ExceptionMatches(PyExc_UnicodeDecodeError)) { + tok->done = E_DECODE; + } + else { + tok->done = E_ERROR; + } + return 0; + } + Py_ssize_t invalid = _PyUnicode_ScanIdentifier(s); + if (invalid < 0) { + Py_DECREF(s); + tok->done = E_ERROR; + return 0; + } + assert(PyUnicode_GET_LENGTH(s) > 0); + if (invalid < PyUnicode_GET_LENGTH(s)) { + Py_UCS4 ch = PyUnicode_READ_CHAR(s, invalid); + if (invalid + 1 < PyUnicode_GET_LENGTH(s)) { + /* Determine the offset in UTF-8 encoded input */ + Py_SETREF(s, PyUnicode_Substring(s, 0, invalid + 1)); + if (s != NULL) { + Py_SETREF(s, PyUnicode_AsUTF8String(s)); + } + if (s == NULL) { + tok->done = E_ERROR; + return 0; + } + tok->cur = (char *)tok->start + PyBytes_GET_SIZE(s); + } + Py_DECREF(s); + if (Py_UNICODE_ISPRINTABLE(ch)) { + _PyTokenizer_syntaxerror(tok, "invalid character '%c' (U+%04X)", ch, ch); + } + else { + _PyTokenizer_syntaxerror(tok, "invalid non-printable character U+%04X", ch); + } + return 0; + } + Py_DECREF(s); + return 1; +} + +static int +tok_decimal_tail(struct tok_state *tok) +{ + int c; + + while (1) { + do { + c = tok_nextc(tok); + } while (Py_ISDIGIT(c)); + if (c != '_') { + break; + } + c = tok_nextc(tok); + if (!Py_ISDIGIT(c)) { + tok_backup(tok, c); + _PyTokenizer_syntaxerror(tok, "invalid decimal literal"); + return 0; + } + } + return c; +} + +static inline int +tok_continuation_line(struct tok_state *tok) { + int c = tok_nextc(tok); + if (c == '\r') { + c = tok_nextc(tok); + } + if (c != '\n') { + tok->done = E_LINECONT; + return -1; + } + c = tok_nextc(tok); + if (c == EOF) { + tok->done = E_EOF; + tok->cur = tok->inp; + return -1; + } else { + tok_backup(tok, c); + } + return c; +} + +static int +tok_get_normal_mode(struct tok_state *tok, tokenizer_mode* current_tok, struct token *token) +{ + int c; + int blankline, nonascii; + + const char *p_start = NULL; + const char *p_end = NULL; + nextline: + tok->start = NULL; + tok->starting_col_offset = -1; + blankline = 0; + + + /* Get indentation level */ + if (tok->atbol) { + int col = 0; + int altcol = 0; + tok->atbol = 0; + int cont_line_col = 0; + for (;;) { + c = tok_nextc(tok); + if (c == ' ') { + col++, altcol++; + } + else if (c == '\t') { + col = (col / tok->tabsize + 1) * tok->tabsize; + altcol = (altcol / ALTTABSIZE + 1) * ALTTABSIZE; + } + else if (c == '\014') {/* Control-L (formfeed) */ + col = altcol = 0; /* For Emacs users */ + } + else if (c == '\\') { + // Indentation cannot be split over multiple physical lines + // using backslashes. This means that if we found a backslash + // preceded by whitespace, **the first one we find** determines + // the level of indentation of whatever comes next. + cont_line_col = cont_line_col ? cont_line_col : col; + if ((c = tok_continuation_line(tok)) == -1) { + return MAKE_TOKEN(ERRORTOKEN); + } + } + else { + break; + } + } + tok_backup(tok, c); + if (c == '#' || c == '\n' || c == '\r') { + /* Lines with only whitespace and/or comments + shouldn't affect the indentation and are + not passed to the parser as NEWLINE tokens, + except *totally* empty lines in interactive + mode, which signal the end of a command group. */ + if (col == 0 && c == '\n' && tok->prompt != NULL) { + blankline = 0; /* Let it through */ + } + else if (tok->prompt != NULL && tok->lineno == 1) { + /* In interactive mode, if the first line contains + only spaces and/or a comment, let it through. */ + blankline = 0; + col = altcol = 0; + } + else { + blankline = 1; /* Ignore completely */ + } + /* We can't jump back right here since we still + may need to skip to the end of a comment */ + } + if (!blankline && tok->level == 0) { + col = cont_line_col ? cont_line_col : col; + altcol = cont_line_col ? cont_line_col : altcol; + if (col == tok->indstack[tok->indent]) { + /* No change */ + if (altcol != tok->altindstack[tok->indent]) { + return MAKE_TOKEN(_PyTokenizer_indenterror(tok)); + } + } + else if (col > tok->indstack[tok->indent]) { + /* Indent -- always one */ + if (tok->indent+1 >= MAXINDENT) { + tok->done = E_TOODEEP; + tok->cur = tok->inp; + return MAKE_TOKEN(ERRORTOKEN); + } + if (altcol <= tok->altindstack[tok->indent]) { + return MAKE_TOKEN(_PyTokenizer_indenterror(tok)); + } + tok->pendin++; + tok->indstack[++tok->indent] = col; + tok->altindstack[tok->indent] = altcol; + } + else /* col < tok->indstack[tok->indent] */ { + /* Dedent -- any number, must be consistent */ + while (tok->indent > 0 && + col < tok->indstack[tok->indent]) { + tok->pendin--; + tok->indent--; + } + if (col != tok->indstack[tok->indent]) { + tok->done = E_DEDENT; + tok->cur = tok->inp; + return MAKE_TOKEN(ERRORTOKEN); + } + if (altcol != tok->altindstack[tok->indent]) { + return MAKE_TOKEN(_PyTokenizer_indenterror(tok)); + } + } + } + } + + tok->start = tok->cur; + tok->starting_col_offset = tok->col_offset; + + /* Return pending indents/dedents */ + if (tok->pendin != 0) { + if (tok->pendin < 0) { + if (tok->tok_extra_tokens) { + p_start = tok->cur; + p_end = tok->cur; + } + tok->pendin++; + return MAKE_TOKEN(DEDENT); + } + else { + if (tok->tok_extra_tokens) { + p_start = tok->buf; + p_end = tok->cur; + } + tok->pendin--; + return MAKE_TOKEN(INDENT); + } + } + + /* Peek ahead at the next character */ + c = tok_nextc(tok); + tok_backup(tok, c); + + again: + tok->start = NULL; + /* Skip spaces */ + do { + c = tok_nextc(tok); + } while (c == ' ' || c == '\t' || c == '\014'); + + /* Set start of current token */ + tok->start = tok->cur == NULL ? NULL : tok->cur - 1; + tok->starting_col_offset = tok->col_offset - 1; + + /* Skip comment, unless it's a type comment */ + if (c == '#') { + + const char* p = NULL; + const char *prefix, *type_start; + int current_starting_col_offset; + + while (c != EOF && c != '\n' && c != '\r') { + c = tok_nextc(tok); + } + + if (tok->tok_extra_tokens) { + p = tok->start; + } + + if (tok->type_comments) { + p = tok->start; + current_starting_col_offset = tok->starting_col_offset; + prefix = type_comment_prefix; + while (*prefix && p < tok->cur) { + if (*prefix == ' ') { + while (*p == ' ' || *p == '\t') { + p++; + current_starting_col_offset++; + } + } else if (*prefix == *p) { + p++; + current_starting_col_offset++; + } else { + break; + } + + prefix++; + } + + /* This is a type comment if we matched all of type_comment_prefix. */ + if (!*prefix) { + int is_type_ignore = 1; + // +6 in order to skip the word 'ignore' + const char *ignore_end = p + 6; + const int ignore_end_col_offset = current_starting_col_offset + 6; + tok_backup(tok, c); /* don't eat the newline or EOF */ + + type_start = p; + + /* A TYPE_IGNORE is "type: ignore" followed by the end of the token + * or anything ASCII and non-alphanumeric. */ + is_type_ignore = ( + tok->cur >= ignore_end && memcmp(p, "ignore", 6) == 0 + && !(tok->cur > ignore_end + && ((unsigned char)ignore_end[0] >= 128 || Py_ISALNUM(ignore_end[0])))); + + if (is_type_ignore) { + p_start = ignore_end; + p_end = tok->cur; + + /* If this type ignore is the only thing on the line, consume the newline also. */ + if (blankline) { + tok_nextc(tok); + tok->atbol = 1; + } + return MAKE_TYPE_COMMENT_TOKEN(TYPE_IGNORE, ignore_end_col_offset, tok->col_offset); + } else { + p_start = type_start; + p_end = tok->cur; + return MAKE_TYPE_COMMENT_TOKEN(TYPE_COMMENT, current_starting_col_offset, tok->col_offset); + } + } + } + if (tok->tok_extra_tokens) { + tok_backup(tok, c); /* don't eat the newline or EOF */ + p_start = p; + p_end = tok->cur; + tok->comment_newline = blankline; + return MAKE_TOKEN(COMMENT); + } + } + + if (tok->done == E_INTERACT_STOP) { + return MAKE_TOKEN(ENDMARKER); + } + + /* Check for EOF and errors now */ + if (c == EOF) { + if (tok->level) { + return MAKE_TOKEN(ERRORTOKEN); + } + return MAKE_TOKEN(tok->done == E_EOF ? ENDMARKER : ERRORTOKEN); + } + + /* Identifier (most frequent token!) */ + nonascii = 0; + if (is_potential_identifier_start(c)) { + /* Process the various legal combinations of b"", r"", u"", and f"". */ + int saw_b = 0, saw_r = 0, saw_u = 0, saw_f = 0; + while (1) { + if (!(saw_b || saw_u || saw_f) && (c == 'b' || c == 'B')) + saw_b = 1; + /* Since this is a backwards compatibility support literal we don't + want to support it in arbitrary order like byte literals. */ + else if (!(saw_b || saw_u || saw_r || saw_f) + && (c == 'u'|| c == 'U')) { + saw_u = 1; + } + /* ur"" and ru"" are not supported */ + else if (!(saw_r || saw_u) && (c == 'r' || c == 'R')) { + saw_r = 1; + } + else if (!(saw_f || saw_b || saw_u) && (c == 'f' || c == 'F')) { + saw_f = 1; + } + else { + break; + } + c = tok_nextc(tok); + if (c == '"' || c == '\'') { + if (saw_f) { + goto f_string_quote; + } + goto letter_quote; + } + } + while (is_potential_identifier_char(c)) { + if (c >= 128) { + nonascii = 1; + } + c = tok_nextc(tok); + } + tok_backup(tok, c); + if (nonascii && !verify_identifier(tok)) { + return MAKE_TOKEN(ERRORTOKEN); + } + + p_start = tok->start; + p_end = tok->cur; + + return MAKE_TOKEN(NAME); + } + + if (c == '\r') { + c = tok_nextc(tok); + } + + /* Newline */ + if (c == '\n') { + tok->atbol = 1; + if (blankline || tok->level > 0) { + if (tok->tok_extra_tokens) { + if (tok->comment_newline) { + tok->comment_newline = 0; + } + p_start = tok->start; + p_end = tok->cur; + return MAKE_TOKEN(NL); + } + goto nextline; + } + if (tok->comment_newline && tok->tok_extra_tokens) { + tok->comment_newline = 0; + p_start = tok->start; + p_end = tok->cur; + return MAKE_TOKEN(NL); + } + p_start = tok->start; + p_end = tok->cur - 1; /* Leave '\n' out of the string */ + tok->cont_line = 0; + return MAKE_TOKEN(NEWLINE); + } + + /* Period or number starting with period? */ + if (c == '.') { + c = tok_nextc(tok); + if (Py_ISDIGIT(c)) { + goto fraction; + } else if (c == '.') { + c = tok_nextc(tok); + if (c == '.') { + p_start = tok->start; + p_end = tok->cur; + return MAKE_TOKEN(ELLIPSIS); + } + else { + tok_backup(tok, c); + } + tok_backup(tok, '.'); + } + else { + tok_backup(tok, c); + } + p_start = tok->start; + p_end = tok->cur; + return MAKE_TOKEN(DOT); + } + + /* Number */ + if (Py_ISDIGIT(c)) { + if (c == '0') { + /* Hex, octal or binary -- maybe. */ + c = tok_nextc(tok); + if (c == 'x' || c == 'X') { + /* Hex */ + c = tok_nextc(tok); + do { + if (c == '_') { + c = tok_nextc(tok); + } + if (!Py_ISXDIGIT(c)) { + tok_backup(tok, c); + return MAKE_TOKEN(_PyTokenizer_syntaxerror(tok, "invalid hexadecimal literal")); + } + do { + c = tok_nextc(tok); + } while (Py_ISXDIGIT(c)); + } while (c == '_'); + if (!verify_end_of_number(tok, c, "hexadecimal")) { + return MAKE_TOKEN(ERRORTOKEN); + } + } + else if (c == 'o' || c == 'O') { + /* Octal */ + c = tok_nextc(tok); + do { + if (c == '_') { + c = tok_nextc(tok); + } + if (c < '0' || c >= '8') { + if (Py_ISDIGIT(c)) { + return MAKE_TOKEN(_PyTokenizer_syntaxerror(tok, + "invalid digit '%c' in octal literal", c)); + } + else { + tok_backup(tok, c); + return MAKE_TOKEN(_PyTokenizer_syntaxerror(tok, "invalid octal literal")); + } + } + do { + c = tok_nextc(tok); + } while ('0' <= c && c < '8'); + } while (c == '_'); + if (Py_ISDIGIT(c)) { + return MAKE_TOKEN(_PyTokenizer_syntaxerror(tok, + "invalid digit '%c' in octal literal", c)); + } + if (!verify_end_of_number(tok, c, "octal")) { + return MAKE_TOKEN(ERRORTOKEN); + } + } + else if (c == 'b' || c == 'B') { + /* Binary */ + c = tok_nextc(tok); + do { + if (c == '_') { + c = tok_nextc(tok); + } + if (c != '0' && c != '1') { + if (Py_ISDIGIT(c)) { + return MAKE_TOKEN(_PyTokenizer_syntaxerror(tok, "invalid digit '%c' in binary literal", c)); + } + else { + tok_backup(tok, c); + return MAKE_TOKEN(_PyTokenizer_syntaxerror(tok, "invalid binary literal")); + } + } + do { + c = tok_nextc(tok); + } while (c == '0' || c == '1'); + } while (c == '_'); + if (Py_ISDIGIT(c)) { + return MAKE_TOKEN(_PyTokenizer_syntaxerror(tok, "invalid digit '%c' in binary literal", c)); + } + if (!verify_end_of_number(tok, c, "binary")) { + return MAKE_TOKEN(ERRORTOKEN); + } + } + else { + int nonzero = 0; + /* maybe old-style octal; c is first char of it */ + /* in any case, allow '0' as a literal */ + while (1) { + if (c == '_') { + c = tok_nextc(tok); + if (!Py_ISDIGIT(c)) { + tok_backup(tok, c); + return MAKE_TOKEN(_PyTokenizer_syntaxerror(tok, "invalid decimal literal")); + } + } + if (c != '0') { + break; + } + c = tok_nextc(tok); + } + char* zeros_end = tok->cur; + if (Py_ISDIGIT(c)) { + nonzero = 1; + c = tok_decimal_tail(tok); + if (c == 0) { + return MAKE_TOKEN(ERRORTOKEN); + } + } + if (c == '.') { + c = tok_nextc(tok); + goto fraction; + } + else if (c == 'e' || c == 'E') { + goto exponent; + } + else if (c == 'j' || c == 'J') { + goto imaginary; + } + else if (nonzero && !tok->tok_extra_tokens) { + /* Old-style octal: now disallowed. */ + tok_backup(tok, c); + return MAKE_TOKEN(_PyTokenizer_syntaxerror_known_range( + tok, (int)(tok->start + 1 - tok->line_start), + (int)(zeros_end - tok->line_start), + "leading zeros in decimal integer " + "literals are not permitted; " + "use an 0o prefix for octal integers")); + } + if (!verify_end_of_number(tok, c, "decimal")) { + return MAKE_TOKEN(ERRORTOKEN); + } + } + } + else { + /* Decimal */ + c = tok_decimal_tail(tok); + if (c == 0) { + return MAKE_TOKEN(ERRORTOKEN); + } + { + /* Accept floating point numbers. */ + if (c == '.') { + c = tok_nextc(tok); + fraction: + /* Fraction */ + if (Py_ISDIGIT(c)) { + c = tok_decimal_tail(tok); + if (c == 0) { + return MAKE_TOKEN(ERRORTOKEN); + } + } + } + if (c == 'e' || c == 'E') { + int e; + exponent: + e = c; + /* Exponent part */ + c = tok_nextc(tok); + if (c == '+' || c == '-') { + c = tok_nextc(tok); + if (!Py_ISDIGIT(c)) { + tok_backup(tok, c); + return MAKE_TOKEN(_PyTokenizer_syntaxerror(tok, "invalid decimal literal")); + } + } else if (!Py_ISDIGIT(c)) { + tok_backup(tok, c); + if (!verify_end_of_number(tok, e, "decimal")) { + return MAKE_TOKEN(ERRORTOKEN); + } + tok_backup(tok, e); + p_start = tok->start; + p_end = tok->cur; + return MAKE_TOKEN(NUMBER); + } + c = tok_decimal_tail(tok); + if (c == 0) { + return MAKE_TOKEN(ERRORTOKEN); + } + } + if (c == 'j' || c == 'J') { + /* Imaginary part */ + imaginary: + c = tok_nextc(tok); + if (!verify_end_of_number(tok, c, "imaginary")) { + return MAKE_TOKEN(ERRORTOKEN); + } + } + else if (!verify_end_of_number(tok, c, "decimal")) { + return MAKE_TOKEN(ERRORTOKEN); + } + } + } + tok_backup(tok, c); + p_start = tok->start; + p_end = tok->cur; + return MAKE_TOKEN(NUMBER); + } + + f_string_quote: + if (((Py_TOLOWER(*tok->start) == 'f' || Py_TOLOWER(*tok->start) == 'r') && (c == '\'' || c == '"'))) { + int quote = c; + int quote_size = 1; /* 1 or 3 */ + + /* Nodes of type STRING, especially multi line strings + must be handled differently in order to get both + the starting line number and the column offset right. + (cf. issue 16806) */ + tok->first_lineno = tok->lineno; + tok->multi_line_start = tok->line_start; + + /* Find the quote size and start of string */ + int after_quote = tok_nextc(tok); + if (after_quote == quote) { + int after_after_quote = tok_nextc(tok); + if (after_after_quote == quote) { + quote_size = 3; + } + else { + // TODO: Check this + tok_backup(tok, after_after_quote); + tok_backup(tok, after_quote); + } + } + if (after_quote != quote) { + tok_backup(tok, after_quote); + } + + + p_start = tok->start; + p_end = tok->cur; + if (tok->tok_mode_stack_index + 1 >= MAXFSTRINGLEVEL) { + return MAKE_TOKEN(_PyTokenizer_syntaxerror(tok, "too many nested f-strings")); + } + tokenizer_mode *the_current_tok = TOK_NEXT_MODE(tok); + the_current_tok->kind = TOK_FSTRING_MODE; + the_current_tok->f_string_quote = quote; + the_current_tok->f_string_quote_size = quote_size; + the_current_tok->f_string_start = tok->start; + the_current_tok->f_string_multi_line_start = tok->line_start; + the_current_tok->f_string_line_start = tok->lineno; + the_current_tok->f_string_start_offset = -1; + the_current_tok->f_string_multi_line_start_offset = -1; + the_current_tok->last_expr_buffer = NULL; + the_current_tok->last_expr_size = 0; + the_current_tok->last_expr_end = -1; + the_current_tok->f_string_debug = 0; + + switch (*tok->start) { + case 'F': + case 'f': + the_current_tok->f_string_raw = Py_TOLOWER(*(tok->start + 1)) == 'r'; + break; + case 'R': + case 'r': + the_current_tok->f_string_raw = 1; + break; + default: + Py_UNREACHABLE(); + } + + the_current_tok->curly_bracket_depth = 0; + the_current_tok->curly_bracket_expr_start_depth = -1; + return MAKE_TOKEN(FSTRING_START); + } + + letter_quote: + /* String */ + if (c == '\'' || c == '"') { + int quote = c; + int quote_size = 1; /* 1 or 3 */ + int end_quote_size = 0; + int has_escaped_quote = 0; + + /* Nodes of type STRING, especially multi line strings + must be handled differently in order to get both + the starting line number and the column offset right. + (cf. issue 16806) */ + tok->first_lineno = tok->lineno; + tok->multi_line_start = tok->line_start; + + /* Find the quote size and start of string */ + c = tok_nextc(tok); + if (c == quote) { + c = tok_nextc(tok); + if (c == quote) { + quote_size = 3; + } + else { + end_quote_size = 1; /* empty string found */ + } + } + if (c != quote) { + tok_backup(tok, c); + } + + /* Get rest of string */ + while (end_quote_size != quote_size) { + c = tok_nextc(tok); + if (tok->done == E_ERROR) { + return MAKE_TOKEN(ERRORTOKEN); + } + 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 + // the start of string, and report the error + // from the initial quote character + tok->cur = (char *)tok->start; + tok->cur++; + tok->line_start = tok->multi_line_start; + int start = tok->lineno; + tok->lineno = tok->first_lineno; + + if (INSIDE_FSTRING(tok)) { + /* When we are in an f-string, before raising the + * unterminated string literal error, check whether + * does the initial quote matches with f-strings quotes + * and if it is, then this must be a missing '}' token + * so raise the proper error */ + tokenizer_mode *the_current_tok = TOK_GET_MODE(tok); + if (the_current_tok->f_string_quote == quote && + the_current_tok->f_string_quote_size == quote_size) { + return MAKE_TOKEN(_PyTokenizer_syntaxerror(tok, "f-string: expecting '}'", start)); + } + } + + if (quote_size == 3) { + _PyTokenizer_syntaxerror(tok, "unterminated triple-quoted string literal" + " (detected at line %d)", start); + if (c != '\n') { + tok->done = E_EOFS; + } + return MAKE_TOKEN(ERRORTOKEN); + } + else { + if (has_escaped_quote) { + _PyTokenizer_syntaxerror( + tok, + "unterminated string literal (detected at line %d); " + "perhaps you escaped the end quote?", + start + ); + } else { + _PyTokenizer_syntaxerror( + tok, "unterminated string literal (detected at line %d)", start + ); + } + if (c != '\n') { + tok->done = E_EOLS; + } + return MAKE_TOKEN(ERRORTOKEN); + } + } + if (c == quote) { + end_quote_size += 1; + } + else { + end_quote_size = 0; + if (c == '\\') { + c = tok_nextc(tok); /* skip escaped char */ + if (c == quote) { /* but record whether the escaped char was a quote */ + has_escaped_quote = 1; + } + if (c == '\r') { + c = tok_nextc(tok); + } + } + } + } + + p_start = tok->start; + p_end = tok->cur; + return MAKE_TOKEN(STRING); + } + + /* Line continuation */ + if (c == '\\') { + if ((c = tok_continuation_line(tok)) == -1) { + return MAKE_TOKEN(ERRORTOKEN); + } + tok->cont_line = 1; + goto again; /* Read next line */ + } + + /* Punctuation character */ + int is_punctuation = (c == ':' || c == '}' || c == '!' || c == '{'); + if (is_punctuation && INSIDE_FSTRING(tok) && INSIDE_FSTRING_EXPR(current_tok)) { + /* This code block gets executed before the curly_bracket_depth is incremented + * by the `{` case, so for ensuring that we are on the 0th level, we need + * to adjust it manually */ + int cursor = current_tok->curly_bracket_depth - (c != '{'); + if (cursor == 0 && !_PyLexer_update_fstring_expr(tok, c)) { + return MAKE_TOKEN(ENDMARKER); + } + if (cursor == 0 && c != '{' && set_fstring_expr(tok, token, c)) { + return MAKE_TOKEN(ERRORTOKEN); + } + + if (c == ':' && cursor == current_tok->curly_bracket_expr_start_depth) { + current_tok->kind = TOK_FSTRING_MODE; + p_start = tok->start; + p_end = tok->cur; + return MAKE_TOKEN(_PyToken_OneChar(c)); + } + } + + /* Check for two-character token */ + { + int c2 = tok_nextc(tok); + int current_token = _PyToken_TwoChars(c, c2); + if (current_token != OP) { + int c3 = tok_nextc(tok); + int current_token3 = _PyToken_ThreeChars(c, c2, c3); + if (current_token3 != OP) { + current_token = current_token3; + } + else { + tok_backup(tok, c3); + } + p_start = tok->start; + p_end = tok->cur; + return MAKE_TOKEN(current_token); + } + tok_backup(tok, c2); + } + + /* Keep track of parentheses nesting level */ + switch (c) { + case '(': + case '[': + case '{': + if (tok->level >= MAXLEVEL) { + return MAKE_TOKEN(_PyTokenizer_syntaxerror(tok, "too many nested parentheses")); + } + tok->parenstack[tok->level] = c; + tok->parenlinenostack[tok->level] = tok->lineno; + tok->parencolstack[tok->level] = (int)(tok->start - tok->line_start); + tok->level++; + if (INSIDE_FSTRING(tok)) { + current_tok->curly_bracket_depth++; + } + break; + case ')': + case ']': + case '}': + if (INSIDE_FSTRING(tok) && !current_tok->curly_bracket_depth && c == '}') { + return MAKE_TOKEN(_PyTokenizer_syntaxerror(tok, "f-string: single '}' is not allowed")); + } + if (!tok->tok_extra_tokens && !tok->level) { + return MAKE_TOKEN(_PyTokenizer_syntaxerror(tok, "unmatched '%c'", c)); + } + if (tok->level > 0) { + tok->level--; + int opening = tok->parenstack[tok->level]; + if (!tok->tok_extra_tokens && !((opening == '(' && c == ')') || + (opening == '[' && c == ']') || + (opening == '{' && c == '}'))) { + /* If the opening bracket belongs to an f-string's expression + part (e.g. f"{)}") and the closing bracket is an arbitrary + nested expression, then instead of matching a different + syntactical construct with it; we'll throw an unmatched + parentheses error. */ + if (INSIDE_FSTRING(tok) && opening == '{') { + assert(current_tok->curly_bracket_depth >= 0); + int previous_bracket = current_tok->curly_bracket_depth - 1; + if (previous_bracket == current_tok->curly_bracket_expr_start_depth) { + return MAKE_TOKEN(_PyTokenizer_syntaxerror(tok, "f-string: unmatched '%c'", c)); + } + } + if (tok->parenlinenostack[tok->level] != tok->lineno) { + return MAKE_TOKEN(_PyTokenizer_syntaxerror(tok, + "closing parenthesis '%c' does not match " + "opening parenthesis '%c' on line %d", + c, opening, tok->parenlinenostack[tok->level])); + } + else { + return MAKE_TOKEN(_PyTokenizer_syntaxerror(tok, + "closing parenthesis '%c' does not match " + "opening parenthesis '%c'", + c, opening)); + } + } + } + + if (INSIDE_FSTRING(tok)) { + current_tok->curly_bracket_depth--; + if (c == '}' && current_tok->curly_bracket_depth == current_tok->curly_bracket_expr_start_depth) { + current_tok->curly_bracket_expr_start_depth--; + current_tok->kind = TOK_FSTRING_MODE; + current_tok->f_string_debug = 0; + } + } + break; + default: + break; + } + + if (!Py_UNICODE_ISPRINTABLE(c)) { + return MAKE_TOKEN(_PyTokenizer_syntaxerror(tok, "invalid non-printable character U+%04X", c)); + } + + if( c == '=' && INSIDE_FSTRING_EXPR(current_tok)) { + current_tok->f_string_debug = 1; + } + + /* Punctuation character */ + p_start = tok->start; + p_end = tok->cur; + return MAKE_TOKEN(_PyToken_OneChar(c)); +} + +static int +tok_get_fstring_mode(struct tok_state *tok, tokenizer_mode* current_tok, struct token *token) +{ + const char *p_start = NULL; + const char *p_end = NULL; + int end_quote_size = 0; + int unicode_escape = 0; + + tok->start = tok->cur; + tok->first_lineno = tok->lineno; + tok->starting_col_offset = tok->col_offset; + + // If we start with a bracket, we defer to the normal mode as there is nothing for us to tokenize + // before it. + int start_char = tok_nextc(tok); + if (start_char == '{') { + int peek1 = tok_nextc(tok); + tok_backup(tok, peek1); + tok_backup(tok, start_char); + if (peek1 != '{') { + current_tok->curly_bracket_expr_start_depth++; + if (current_tok->curly_bracket_expr_start_depth >= MAX_EXPR_NESTING) { + return MAKE_TOKEN(_PyTokenizer_syntaxerror(tok, "f-string: expressions nested too deeply")); + } + TOK_GET_MODE(tok)->kind = TOK_REGULAR_MODE; + return tok_get_normal_mode(tok, current_tok, token); + } + } + else { + tok_backup(tok, start_char); + } + + // Check if we are at the end of the string + for (int i = 0; i < current_tok->f_string_quote_size; i++) { + int quote = tok_nextc(tok); + if (quote != current_tok->f_string_quote) { + tok_backup(tok, quote); + goto f_string_middle; + } + } + + if (current_tok->last_expr_buffer != NULL) { + PyMem_Free(current_tok->last_expr_buffer); + current_tok->last_expr_buffer = NULL; + current_tok->last_expr_size = 0; + current_tok->last_expr_end = -1; + } + + p_start = tok->start; + p_end = tok->cur; + tok->tok_mode_stack_index--; + return MAKE_TOKEN(FSTRING_END); + +f_string_middle: + + // TODO: This is a bit of a hack, but it works for now. We need to find a better way to handle + // this. + tok->multi_line_start = tok->line_start; + while (end_quote_size != current_tok->f_string_quote_size) { + int c = tok_nextc(tok); + if (tok->done == E_ERROR) { + return MAKE_TOKEN(ERRORTOKEN); + } + int in_format_spec = ( + current_tok->last_expr_end != -1 + && + INSIDE_FSTRING_EXPR(current_tok) + ); + + if (c == EOF || (current_tok->f_string_quote_size == 1 && c == '\n')) { + if (tok->decoding_erred) { + return MAKE_TOKEN(ERRORTOKEN); + } + + // If we are in a format spec and we found a newline, + // it means that the format spec ends here and we should + // return to the regular mode. + if (in_format_spec && c == '\n') { + tok_backup(tok, c); + TOK_GET_MODE(tok)->kind = TOK_REGULAR_MODE; + p_start = tok->start; + p_end = tok->cur; + return MAKE_TOKEN(FSTRING_MIDDLE); + } + + assert(tok->multi_line_start != NULL); + // shift the tok_state's location into + // the start of string, and report the error + // from the initial quote character + tok->cur = (char *)current_tok->f_string_start; + tok->cur++; + tok->line_start = current_tok->f_string_multi_line_start; + int start = tok->lineno; + + tokenizer_mode *the_current_tok = TOK_GET_MODE(tok); + tok->lineno = the_current_tok->f_string_line_start; + + if (current_tok->f_string_quote_size == 3) { + _PyTokenizer_syntaxerror(tok, + "unterminated triple-quoted f-string literal" + " (detected at line %d)", start); + if (c != '\n') { + tok->done = E_EOFS; + } + return MAKE_TOKEN(ERRORTOKEN); + } + else { + return MAKE_TOKEN(_PyTokenizer_syntaxerror(tok, + "unterminated f-string literal (detected at" + " line %d)", start)); + } + } + + if (c == current_tok->f_string_quote) { + end_quote_size += 1; + continue; + } else { + end_quote_size = 0; + } + + if (c == '{') { + int peek = tok_nextc(tok); + if (peek != '{' || in_format_spec) { + tok_backup(tok, peek); + tok_backup(tok, c); + current_tok->curly_bracket_expr_start_depth++; + if (current_tok->curly_bracket_expr_start_depth >= MAX_EXPR_NESTING) { + return MAKE_TOKEN(_PyTokenizer_syntaxerror(tok, "f-string: expressions nested too deeply")); + } + TOK_GET_MODE(tok)->kind = TOK_REGULAR_MODE; + p_start = tok->start; + p_end = tok->cur; + } else { + p_start = tok->start; + p_end = tok->cur - 1; + } + return MAKE_TOKEN(FSTRING_MIDDLE); + } else if (c == '}') { + if (unicode_escape) { + p_start = tok->start; + p_end = tok->cur; + return MAKE_TOKEN(FSTRING_MIDDLE); + } + int peek = tok_nextc(tok); + + // The tokenizer can only be in the format spec if we have already completed the expression + // scanning (indicated by the end of the expression being set) and we are not at the top level + // of the bracket stack (-1 is the top level). Since format specifiers can't legally use double + // brackets, we can bypass it here. + if (peek == '}' && !in_format_spec) { + p_start = tok->start; + p_end = tok->cur - 1; + } else { + tok_backup(tok, peek); + tok_backup(tok, c); + TOK_GET_MODE(tok)->kind = TOK_REGULAR_MODE; + p_start = tok->start; + p_end = tok->cur; + } + return MAKE_TOKEN(FSTRING_MIDDLE); + } else if (c == '\\') { + int peek = tok_nextc(tok); + if (peek == '\r') { + peek = tok_nextc(tok); + } + // Special case when the backslash is right before a curly + // brace. We have to restore and return the control back + // to the loop for the next iteration. + if (peek == '{' || peek == '}') { + if (!current_tok->f_string_raw) { + if (_PyTokenizer_warn_invalid_escape_sequence(tok, peek)) { + return MAKE_TOKEN(ERRORTOKEN); + } + } + tok_backup(tok, peek); + continue; + } + + if (!current_tok->f_string_raw) { + if (peek == 'N') { + /* Handle named unicode escapes (\N{BULLET}) */ + peek = tok_nextc(tok); + if (peek == '{') { + unicode_escape = 1; + } else { + tok_backup(tok, peek); + } + } + } /* else { + skip the escaped character + }*/ + } + } + + // Backup the f-string quotes to emit a final FSTRING_MIDDLE and + // add the quotes to the FSTRING_END in the next tokenizer iteration. + for (int i = 0; i < current_tok->f_string_quote_size; i++) { + tok_backup(tok, current_tok->f_string_quote); + } + p_start = tok->start; + p_end = tok->cur; + return MAKE_TOKEN(FSTRING_MIDDLE); +} + +static int +tok_get(struct tok_state *tok, struct token *token) +{ + tokenizer_mode *current_tok = TOK_GET_MODE(tok); + if (current_tok->kind == TOK_REGULAR_MODE) { + return tok_get_normal_mode(tok, current_tok, token); + } else { + return tok_get_fstring_mode(tok, current_tok, token); + } +} + +int +_PyTokenizer_Get(struct tok_state *tok, struct token *token) +{ + int result = tok_get(tok, token); + if (tok->decoding_erred) { + result = ERRORTOKEN; + tok->done = E_DECODE; + } + return result; +} diff --git a/Parser/lexer/lexer.h b/Parser/lexer/lexer.h new file mode 100644 index 00000000000000..7f21bf56bba2d1 --- /dev/null +++ b/Parser/lexer/lexer.h @@ -0,0 +1,10 @@ +#ifndef _PY_LEXER_LEXER_H_ +#define _PY_LEXER_LEXER_H_ + +#include "state.h" + +int _PyLexer_update_fstring_expr(struct tok_state *tok, char cur); + +int _PyTokenizer_Get(struct tok_state *, struct token *); + +#endif diff --git a/Parser/lexer/state.c b/Parser/lexer/state.c new file mode 100644 index 00000000000000..653ddafd411095 --- /dev/null +++ b/Parser/lexer/state.c @@ -0,0 +1,149 @@ +#include "Python.h" +#include "pycore_pystate.h" +#include "pycore_token.h" +#include "errcode.h" + +#include "state.h" + +/* Never change this */ +#define TABSIZE 8 + +/* Create and initialize a new tok_state structure */ +struct tok_state * +_PyTokenizer_tok_new(void) +{ + struct tok_state *tok = (struct tok_state *)PyMem_Malloc( + sizeof(struct tok_state)); + if (tok == NULL) + return NULL; + tok->buf = tok->cur = tok->inp = NULL; + tok->fp_interactive = 0; + tok->interactive_src_start = NULL; + tok->interactive_src_end = NULL; + tok->start = NULL; + tok->end = NULL; + tok->done = E_OK; + tok->fp = NULL; + tok->input = NULL; + tok->tabsize = TABSIZE; + tok->indent = 0; + tok->indstack[0] = 0; + tok->atbol = 1; + tok->pendin = 0; + tok->prompt = tok->nextprompt = NULL; + tok->lineno = 0; + tok->starting_col_offset = -1; + tok->col_offset = -1; + tok->level = 0; + tok->altindstack[0] = 0; + tok->decoding_state = STATE_INIT; + tok->decoding_erred = 0; + tok->enc = NULL; + tok->encoding = NULL; + tok->cont_line = 0; + tok->filename = NULL; + tok->decoding_readline = NULL; + tok->decoding_buffer = NULL; + tok->readline = NULL; + tok->type_comments = 0; + tok->interactive_underflow = IUNDERFLOW_NORMAL; + tok->underflow = NULL; + tok->str = NULL; + tok->report_warnings = 1; + tok->tok_extra_tokens = 0; + tok->comment_newline = 0; + tok->implicit_newline = 0; + tok->tok_mode_stack[0] = (tokenizer_mode){.kind =TOK_REGULAR_MODE, .f_string_quote='\0', .f_string_quote_size = 0, .f_string_debug=0}; + tok->tok_mode_stack_index = 0; +#ifdef Py_DEBUG + tok->debug = _Py_GetConfig()->parser_debug; +#endif + return tok; +} + +static void +free_fstring_expressions(struct tok_state *tok) +{ + int index; + tokenizer_mode *mode; + + for (index = tok->tok_mode_stack_index; index >= 0; --index) { + mode = &(tok->tok_mode_stack[index]); + if (mode->last_expr_buffer != NULL) { + PyMem_Free(mode->last_expr_buffer); + mode->last_expr_buffer = NULL; + mode->last_expr_size = 0; + mode->last_expr_end = -1; + } + } +} + +/* Free a tok_state structure */ +void +_PyTokenizer_Free(struct tok_state *tok) +{ + if (tok->encoding != NULL) { + PyMem_Free(tok->encoding); + } + Py_XDECREF(tok->decoding_readline); + Py_XDECREF(tok->decoding_buffer); + Py_XDECREF(tok->readline); + Py_XDECREF(tok->filename); + if ((tok->readline != NULL || tok->fp != NULL ) && tok->buf != NULL) { + PyMem_Free(tok->buf); + } + if (tok->input) { + PyMem_Free(tok->input); + } + if (tok->interactive_src_start != NULL) { + PyMem_Free(tok->interactive_src_start); + } + free_fstring_expressions(tok); + PyMem_Free(tok); +} + +void +_PyToken_Free(struct token *token) { + Py_XDECREF(token->metadata); +} + +void +_PyToken_Init(struct token *token) { + token->metadata = NULL; +} + +int +_PyLexer_type_comment_token_setup(struct tok_state *tok, struct token *token, int type, int col_offset, + int end_col_offset, const char *start, const char *end) +{ + token->level = tok->level; + token->lineno = token->end_lineno = tok->lineno; + token->col_offset = col_offset; + token->end_col_offset = end_col_offset; + token->start = start; + token->end = end; + return type; +} + +int +_PyLexer_token_setup(struct tok_state *tok, struct token *token, int type, const char *start, const char *end) +{ + assert((start == NULL && end == NULL) || (start != NULL && end != NULL)); + token->level = tok->level; + if (ISSTRINGLIT(type)) { + token->lineno = tok->first_lineno; + } + else { + token->lineno = tok->lineno; + } + token->end_lineno = tok->lineno; + token->col_offset = token->end_col_offset = -1; + token->start = start; + token->end = end; + + if (start != NULL && end != NULL) { + token->col_offset = tok->starting_col_offset; + token->end_col_offset = tok->col_offset; + } + return type; +} diff --git a/Parser/lexer/state.h b/Parser/lexer/state.h new file mode 100644 index 00000000000000..61d090d6d2fe21 --- /dev/null +++ b/Parser/lexer/state.h @@ -0,0 +1,141 @@ +#ifndef _PY_LEXER_H_ +#define _PY_LEXER_H_ + +#include "object.h" + +#define MAXINDENT 100 /* Max indentation level */ +#define MAXLEVEL 200 /* Max parentheses level */ +#define MAXFSTRINGLEVEL 150 /* Max f-string nesting level */ + +#define INSIDE_FSTRING(tok) (tok->tok_mode_stack_index > 0) +#define INSIDE_FSTRING_EXPR(tok) (tok->curly_bracket_expr_start_depth >= 0) + +enum decoding_state { + STATE_INIT, + STATE_SEEK_CODING, + STATE_NORMAL +}; + +enum interactive_underflow_t { + /* Normal mode of operation: return a new token when asked in interactive mode */ + IUNDERFLOW_NORMAL, + /* Forcefully return ENDMARKER when asked for a new token in interactive mode. This + * can be used to prevent the tokenizer to prompt the user for new tokens */ + IUNDERFLOW_STOP, +}; + +struct token { + int level; + int lineno, col_offset, end_lineno, end_col_offset; + const char *start, *end; + PyObject *metadata; +}; + +enum tokenizer_mode_kind_t { + TOK_REGULAR_MODE, + TOK_FSTRING_MODE, +}; + +#define MAX_EXPR_NESTING 3 + +typedef struct _tokenizer_mode { + enum tokenizer_mode_kind_t kind; + + int curly_bracket_depth; + int curly_bracket_expr_start_depth; + + char f_string_quote; + int f_string_quote_size; + int f_string_raw; + const char* f_string_start; + const char* f_string_multi_line_start; + int f_string_line_start; + + Py_ssize_t f_string_start_offset; + Py_ssize_t f_string_multi_line_start_offset; + + Py_ssize_t last_expr_size; + Py_ssize_t last_expr_end; + char* last_expr_buffer; + int f_string_debug; +} tokenizer_mode; + +/* Tokenizer state */ +struct tok_state { + /* Input state; buf <= cur <= inp <= end */ + /* NB an entire line is held in the buffer */ + char *buf; /* Input buffer, or NULL; malloc'ed if fp != NULL or readline != NULL */ + char *cur; /* Next character in buffer */ + char *inp; /* End of data in buffer */ + int fp_interactive; /* If the file descriptor is interactive */ + char *interactive_src_start; /* The start of the source parsed so far in interactive mode */ + char *interactive_src_end; /* The end of the source parsed so far in interactive mode */ + const char *end; /* End of input buffer if buf != NULL */ + const char *start; /* Start of current token if not NULL */ + int done; /* E_OK normally, E_EOF at EOF, otherwise error code */ + /* NB If done != E_OK, cur must be == inp!!! */ + FILE *fp; /* Rest of input; NULL if tokenizing a string */ + int tabsize; /* Tab spacing */ + int indent; /* Current indentation index */ + int indstack[MAXINDENT]; /* Stack of indents */ + int atbol; /* Nonzero if at begin of new line */ + int pendin; /* Pending indents (if > 0) or dedents (if < 0) */ + const char *prompt, *nextprompt; /* For interactive prompting */ + int lineno; /* Current line number */ + int first_lineno; /* First line of a single line or multi line string + expression (cf. issue 16806) */ + int starting_col_offset; /* The column offset at the beginning of a token */ + int col_offset; /* Current col offset */ + int level; /* () [] {} Parentheses nesting level */ + /* Used to allow free continuations inside them */ + char parenstack[MAXLEVEL]; + int parenlinenostack[MAXLEVEL]; + int parencolstack[MAXLEVEL]; + PyObject *filename; + /* Stuff for checking on different tab sizes */ + int altindstack[MAXINDENT]; /* Stack of alternate indents */ + /* Stuff for PEP 0263 */ + enum decoding_state decoding_state; + int decoding_erred; /* whether erred in decoding */ + char *encoding; /* Source encoding. */ + int cont_line; /* whether we are in a continuation line. */ + const char* line_start; /* pointer to start of current line */ + const char* multi_line_start; /* pointer to start of first line of + a single line or multi line string + expression (cf. issue 16806) */ + PyObject *decoding_readline; /* open(...).readline */ + PyObject *decoding_buffer; + PyObject *readline; /* readline() function */ + const char* enc; /* Encoding for the current str. */ + char* str; /* Source string being tokenized (if tokenizing from a string)*/ + char* input; /* Tokenizer's newline translated copy of the string. */ + + int type_comments; /* Whether to look for type comments */ + + /* How to proceed when asked for a new token in interactive mode */ + enum interactive_underflow_t interactive_underflow; + int (*underflow)(struct tok_state *); /* Function to call when buffer is empty and we need to refill it*/ + + int report_warnings; + // TODO: Factor this into its own thing + tokenizer_mode tok_mode_stack[MAXFSTRINGLEVEL]; + int tok_mode_stack_index; + int tok_extra_tokens; + int comment_newline; + int implicit_newline; +#ifdef Py_DEBUG + int debug; +#endif +}; + +int _PyLexer_type_comment_token_setup(struct tok_state *tok, struct token *token, int type, int col_offset, + int end_col_offset, const char *start, const char *end); +int _PyLexer_token_setup(struct tok_state *tok, struct token *token, int type, const char *start, const char *end); + +struct tok_state *_PyTokenizer_tok_new(void); +void _PyTokenizer_Free(struct tok_state *); +void _PyToken_Free(struct token *); +void _PyToken_Init(struct token *); + + +#endif diff --git a/Parser/myreadline.c b/Parser/myreadline.c index 815387388218c6..1825665354844b 100644 --- a/Parser/myreadline.c +++ b/Parser/myreadline.c @@ -1,5 +1,5 @@ -/* Readline interface for tokenizer.c and [raw_]input() in bltinmodule.c. +/* Readline interface for the tokenizer and [raw_]input() in bltinmodule.c. By default, or when stdin is not a tty device, we have a super simple my_readline function using fgets. Optionally, we can use the GNU readline library. @@ -14,11 +14,15 @@ #include "pycore_pystate.h" // _PyThreadState_GET() #ifdef MS_WINDOWS # ifndef WIN32_LEAN_AND_MEAN -# define WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN # endif # include "windows.h" #endif /* MS_WINDOWS */ +#ifdef HAVE_UNISTD_H +# include // isatty() +#endif + // Export the symbol since it's used by the readline shared extension PyAPI_DATA(PyThreadState*) _PyOS_ReadlineTState; @@ -360,7 +364,7 @@ PyOS_StdioReadline(FILE *sys_stdin, FILE *sys_stdout, const char *prompt) char *(*PyOS_ReadlineFunctionPointer)(FILE *, FILE *, const char *) = NULL; -/* Interface used by tokenizer.c and bltinmodule.c */ +/* Interface used by file_tokenizer.c and bltinmodule.c */ char * PyOS_Readline(FILE *sys_stdin, FILE *sys_stdout, const char *prompt) diff --git a/Parser/parser.c b/Parser/parser.c index 44312cff125ae7..779b18e9650e9f 100644 --- a/Parser/parser.c +++ b/Parser/parser.c @@ -8,7 +8,11 @@ #endif #ifdef __wasi__ -# define MAXSTACK 4000 +# ifdef Py_DEBUG +# define MAXSTACK 1000 +# else +# define MAXSTACK 4000 +# endif #else # define MAXSTACK 6000 #endif @@ -17,54 +21,54 @@ static KeywordToken *reserved_keywords[] = { (KeywordToken[]) {{NULL, -1}}, (KeywordToken[]) {{NULL, -1}}, (KeywordToken[]) { - {"if", 656}, - {"as", 654}, - {"in", 667}, + {"if", 661}, + {"as", 659}, + {"in", 672}, {"or", 581}, {"is", 589}, {NULL, -1}, }, (KeywordToken[]) { - {"del", 613}, - {"def", 669}, - {"for", 666}, - {"try", 638}, + {"del", 616}, + {"def", 674}, + {"for", 671}, + {"try", 643}, {"and", 582}, {"not", 588}, {NULL, -1}, }, (KeywordToken[]) { - {"from", 618}, + {"from", 621}, {"pass", 504}, - {"with", 629}, - {"elif", 658}, - {"else", 659}, - {"None", 611}, - {"True", 610}, + {"with", 634}, + {"elif", 663}, + {"else", 664}, + {"None", 614}, + {"True", 613}, {NULL, -1}, }, (KeywordToken[]) { {"raise", 525}, {"yield", 580}, {"break", 508}, - {"async", 668}, - {"class", 671}, - {"while", 661}, - {"False", 612}, + {"async", 673}, + {"class", 676}, + {"while", 666}, + {"False", 615}, {"await", 590}, {NULL, -1}, }, (KeywordToken[]) { {"return", 522}, - {"import", 617}, + {"import", 620}, {"assert", 529}, {"global", 526}, - {"except", 651}, - {"lambda", 609}, + {"except", 656}, + {"lambda", 612}, {NULL, -1}, }, (KeywordToken[]) { - {"finally", 647}, + {"finally", 652}, {NULL, -1}, }, (KeywordToken[]) { @@ -84,159 +88,159 @@ static char *soft_keywords[] = { #define interactive_type 1001 #define eval_type 1002 #define func_type_type 1003 -#define fstring_type 1004 -#define statements_type 1005 -#define statement_type 1006 -#define statement_newline_type 1007 -#define simple_stmts_type 1008 -#define simple_stmt_type 1009 -#define compound_stmt_type 1010 -#define assignment_type 1011 -#define annotated_rhs_type 1012 -#define augassign_type 1013 -#define return_stmt_type 1014 -#define raise_stmt_type 1015 -#define global_stmt_type 1016 -#define nonlocal_stmt_type 1017 -#define del_stmt_type 1018 -#define yield_stmt_type 1019 -#define assert_stmt_type 1020 -#define import_stmt_type 1021 -#define import_name_type 1022 -#define import_from_type 1023 -#define import_from_targets_type 1024 -#define import_from_as_names_type 1025 -#define import_from_as_name_type 1026 -#define dotted_as_names_type 1027 -#define dotted_as_name_type 1028 -#define dotted_name_type 1029 // Left-recursive -#define block_type 1030 -#define decorators_type 1031 -#define class_def_type 1032 -#define class_def_raw_type 1033 -#define function_def_type 1034 -#define function_def_raw_type 1035 -#define params_type 1036 -#define parameters_type 1037 -#define slash_no_default_type 1038 -#define slash_with_default_type 1039 -#define star_etc_type 1040 -#define kwds_type 1041 -#define param_no_default_type 1042 -#define param_no_default_star_annotation_type 1043 -#define param_with_default_type 1044 -#define param_maybe_default_type 1045 -#define param_type 1046 -#define param_star_annotation_type 1047 -#define annotation_type 1048 -#define star_annotation_type 1049 -#define default_type 1050 -#define if_stmt_type 1051 -#define elif_stmt_type 1052 -#define else_block_type 1053 -#define while_stmt_type 1054 -#define for_stmt_type 1055 -#define with_stmt_type 1056 -#define with_item_type 1057 -#define try_stmt_type 1058 -#define except_block_type 1059 -#define except_star_block_type 1060 -#define finally_block_type 1061 -#define match_stmt_type 1062 -#define subject_expr_type 1063 -#define case_block_type 1064 -#define guard_type 1065 -#define patterns_type 1066 -#define pattern_type 1067 -#define as_pattern_type 1068 -#define or_pattern_type 1069 -#define closed_pattern_type 1070 -#define literal_pattern_type 1071 -#define literal_expr_type 1072 -#define complex_number_type 1073 -#define signed_number_type 1074 -#define signed_real_number_type 1075 -#define real_number_type 1076 -#define imaginary_number_type 1077 -#define capture_pattern_type 1078 -#define pattern_capture_target_type 1079 -#define wildcard_pattern_type 1080 -#define value_pattern_type 1081 -#define attr_type 1082 // Left-recursive -#define name_or_attr_type 1083 // Left-recursive -#define group_pattern_type 1084 -#define sequence_pattern_type 1085 -#define open_sequence_pattern_type 1086 -#define maybe_sequence_pattern_type 1087 -#define maybe_star_pattern_type 1088 -#define star_pattern_type 1089 -#define mapping_pattern_type 1090 -#define items_pattern_type 1091 -#define key_value_pattern_type 1092 -#define double_star_pattern_type 1093 -#define class_pattern_type 1094 -#define positional_patterns_type 1095 -#define keyword_patterns_type 1096 -#define keyword_pattern_type 1097 -#define type_alias_type 1098 -#define type_params_type 1099 -#define type_param_seq_type 1100 -#define type_param_type 1101 -#define type_param_bound_type 1102 -#define expressions_type 1103 -#define expression_type 1104 -#define yield_expr_type 1105 -#define star_expressions_type 1106 -#define star_expression_type 1107 -#define star_named_expressions_type 1108 -#define star_named_expression_type 1109 -#define assignment_expression_type 1110 -#define named_expression_type 1111 -#define disjunction_type 1112 -#define conjunction_type 1113 -#define inversion_type 1114 -#define comparison_type 1115 -#define compare_op_bitwise_or_pair_type 1116 -#define eq_bitwise_or_type 1117 -#define noteq_bitwise_or_type 1118 -#define lte_bitwise_or_type 1119 -#define lt_bitwise_or_type 1120 -#define gte_bitwise_or_type 1121 -#define gt_bitwise_or_type 1122 -#define notin_bitwise_or_type 1123 -#define in_bitwise_or_type 1124 -#define isnot_bitwise_or_type 1125 -#define is_bitwise_or_type 1126 -#define bitwise_or_type 1127 // Left-recursive -#define bitwise_xor_type 1128 // Left-recursive -#define bitwise_and_type 1129 // Left-recursive -#define shift_expr_type 1130 // Left-recursive -#define sum_type 1131 // Left-recursive -#define term_type 1132 // Left-recursive -#define factor_type 1133 -#define power_type 1134 -#define await_primary_type 1135 -#define primary_type 1136 // Left-recursive -#define slices_type 1137 -#define slice_type 1138 -#define atom_type 1139 -#define group_type 1140 -#define lambdef_type 1141 -#define lambda_params_type 1142 -#define lambda_parameters_type 1143 -#define lambda_slash_no_default_type 1144 -#define lambda_slash_with_default_type 1145 -#define lambda_star_etc_type 1146 -#define lambda_kwds_type 1147 -#define lambda_param_no_default_type 1148 -#define lambda_param_with_default_type 1149 -#define lambda_param_maybe_default_type 1150 -#define lambda_param_type 1151 -#define fstring_middle_type 1152 -#define fstring_replacement_field_type 1153 -#define fstring_conversion_type 1154 -#define fstring_full_format_spec_type 1155 -#define fstring_format_spec_type 1156 +#define statements_type 1004 +#define statement_type 1005 +#define statement_newline_type 1006 +#define simple_stmts_type 1007 +#define simple_stmt_type 1008 +#define compound_stmt_type 1009 +#define assignment_type 1010 +#define annotated_rhs_type 1011 +#define augassign_type 1012 +#define return_stmt_type 1013 +#define raise_stmt_type 1014 +#define global_stmt_type 1015 +#define nonlocal_stmt_type 1016 +#define del_stmt_type 1017 +#define yield_stmt_type 1018 +#define assert_stmt_type 1019 +#define import_stmt_type 1020 +#define import_name_type 1021 +#define import_from_type 1022 +#define import_from_targets_type 1023 +#define import_from_as_names_type 1024 +#define import_from_as_name_type 1025 +#define dotted_as_names_type 1026 +#define dotted_as_name_type 1027 +#define dotted_name_type 1028 // Left-recursive +#define block_type 1029 +#define decorators_type 1030 +#define class_def_type 1031 +#define class_def_raw_type 1032 +#define function_def_type 1033 +#define function_def_raw_type 1034 +#define params_type 1035 +#define parameters_type 1036 +#define slash_no_default_type 1037 +#define slash_with_default_type 1038 +#define star_etc_type 1039 +#define kwds_type 1040 +#define param_no_default_type 1041 +#define param_no_default_star_annotation_type 1042 +#define param_with_default_type 1043 +#define param_maybe_default_type 1044 +#define param_type 1045 +#define param_star_annotation_type 1046 +#define annotation_type 1047 +#define star_annotation_type 1048 +#define default_type 1049 +#define if_stmt_type 1050 +#define elif_stmt_type 1051 +#define else_block_type 1052 +#define while_stmt_type 1053 +#define for_stmt_type 1054 +#define with_stmt_type 1055 +#define with_item_type 1056 +#define try_stmt_type 1057 +#define except_block_type 1058 +#define except_star_block_type 1059 +#define finally_block_type 1060 +#define match_stmt_type 1061 +#define subject_expr_type 1062 +#define case_block_type 1063 +#define guard_type 1064 +#define patterns_type 1065 +#define pattern_type 1066 +#define as_pattern_type 1067 +#define or_pattern_type 1068 +#define closed_pattern_type 1069 +#define literal_pattern_type 1070 +#define literal_expr_type 1071 +#define complex_number_type 1072 +#define signed_number_type 1073 +#define signed_real_number_type 1074 +#define real_number_type 1075 +#define imaginary_number_type 1076 +#define capture_pattern_type 1077 +#define pattern_capture_target_type 1078 +#define wildcard_pattern_type 1079 +#define value_pattern_type 1080 +#define attr_type 1081 // Left-recursive +#define name_or_attr_type 1082 // Left-recursive +#define group_pattern_type 1083 +#define sequence_pattern_type 1084 +#define open_sequence_pattern_type 1085 +#define maybe_sequence_pattern_type 1086 +#define maybe_star_pattern_type 1087 +#define star_pattern_type 1088 +#define mapping_pattern_type 1089 +#define items_pattern_type 1090 +#define key_value_pattern_type 1091 +#define double_star_pattern_type 1092 +#define class_pattern_type 1093 +#define positional_patterns_type 1094 +#define keyword_patterns_type 1095 +#define keyword_pattern_type 1096 +#define type_alias_type 1097 +#define type_params_type 1098 +#define type_param_seq_type 1099 +#define type_param_type 1100 +#define type_param_bound_type 1101 +#define expressions_type 1102 +#define expression_type 1103 +#define yield_expr_type 1104 +#define star_expressions_type 1105 +#define star_expression_type 1106 +#define star_named_expressions_type 1107 +#define star_named_expression_type 1108 +#define assignment_expression_type 1109 +#define named_expression_type 1110 +#define disjunction_type 1111 +#define conjunction_type 1112 +#define inversion_type 1113 +#define comparison_type 1114 +#define compare_op_bitwise_or_pair_type 1115 +#define eq_bitwise_or_type 1116 +#define noteq_bitwise_or_type 1117 +#define lte_bitwise_or_type 1118 +#define lt_bitwise_or_type 1119 +#define gte_bitwise_or_type 1120 +#define gt_bitwise_or_type 1121 +#define notin_bitwise_or_type 1122 +#define in_bitwise_or_type 1123 +#define isnot_bitwise_or_type 1124 +#define is_bitwise_or_type 1125 +#define bitwise_or_type 1126 // Left-recursive +#define bitwise_xor_type 1127 // Left-recursive +#define bitwise_and_type 1128 // Left-recursive +#define shift_expr_type 1129 // Left-recursive +#define sum_type 1130 // Left-recursive +#define term_type 1131 // Left-recursive +#define factor_type 1132 +#define power_type 1133 +#define await_primary_type 1134 +#define primary_type 1135 // Left-recursive +#define slices_type 1136 +#define slice_type 1137 +#define atom_type 1138 +#define group_type 1139 +#define lambdef_type 1140 +#define lambda_params_type 1141 +#define lambda_parameters_type 1142 +#define lambda_slash_no_default_type 1143 +#define lambda_slash_with_default_type 1144 +#define lambda_star_etc_type 1145 +#define lambda_kwds_type 1146 +#define lambda_param_no_default_type 1147 +#define lambda_param_with_default_type 1148 +#define lambda_param_maybe_default_type 1149 +#define lambda_param_type 1150 +#define fstring_middle_type 1151 +#define fstring_replacement_field_type 1152 +#define fstring_conversion_type 1153 +#define fstring_full_format_spec_type 1154 +#define fstring_format_spec_type 1155 +#define fstring_type 1156 #define string_type 1157 #define strings_type 1158 #define list_type 1159 @@ -300,312 +304,320 @@ static char *soft_keywords[] = { #define invalid_group_type 1217 #define invalid_import_type 1218 #define invalid_import_from_targets_type 1219 -#define invalid_with_stmt_type 1220 -#define invalid_with_stmt_indent_type 1221 -#define invalid_try_stmt_type 1222 -#define invalid_except_stmt_type 1223 -#define invalid_finally_stmt_type 1224 -#define invalid_except_stmt_indent_type 1225 -#define invalid_except_star_stmt_indent_type 1226 -#define invalid_match_stmt_type 1227 -#define invalid_case_block_type 1228 -#define invalid_as_pattern_type 1229 -#define invalid_class_pattern_type 1230 -#define invalid_class_argument_pattern_type 1231 -#define invalid_if_stmt_type 1232 -#define invalid_elif_stmt_type 1233 -#define invalid_else_stmt_type 1234 -#define invalid_while_stmt_type 1235 -#define invalid_for_stmt_type 1236 -#define invalid_def_raw_type 1237 -#define invalid_class_def_raw_type 1238 -#define invalid_double_starred_kvpairs_type 1239 -#define invalid_kvpair_type 1240 -#define invalid_starred_expression_type 1241 -#define invalid_replacement_field_type 1242 -#define invalid_conversion_character_type 1243 -#define _loop0_1_type 1244 -#define _loop0_2_type 1245 -#define _loop0_3_type 1246 -#define _loop1_4_type 1247 -#define _loop0_6_type 1248 -#define _gather_5_type 1249 -#define _tmp_7_type 1250 -#define _tmp_8_type 1251 -#define _tmp_9_type 1252 -#define _tmp_10_type 1253 -#define _tmp_11_type 1254 -#define _tmp_12_type 1255 -#define _tmp_13_type 1256 -#define _tmp_14_type 1257 -#define _loop1_15_type 1258 -#define _tmp_16_type 1259 -#define _tmp_17_type 1260 -#define _tmp_18_type 1261 -#define _loop0_20_type 1262 -#define _gather_19_type 1263 -#define _loop0_22_type 1264 -#define _gather_21_type 1265 -#define _tmp_23_type 1266 -#define _tmp_24_type 1267 -#define _loop0_25_type 1268 -#define _loop1_26_type 1269 -#define _loop0_28_type 1270 -#define _gather_27_type 1271 -#define _tmp_29_type 1272 -#define _loop0_31_type 1273 -#define _gather_30_type 1274 -#define _tmp_32_type 1275 -#define _loop1_33_type 1276 -#define _tmp_34_type 1277 -#define _tmp_35_type 1278 -#define _tmp_36_type 1279 -#define _loop0_37_type 1280 -#define _loop0_38_type 1281 -#define _loop0_39_type 1282 -#define _loop1_40_type 1283 -#define _loop0_41_type 1284 -#define _loop1_42_type 1285 -#define _loop1_43_type 1286 -#define _loop1_44_type 1287 -#define _loop0_45_type 1288 -#define _loop1_46_type 1289 -#define _loop0_47_type 1290 -#define _loop1_48_type 1291 -#define _loop0_49_type 1292 -#define _loop0_50_type 1293 -#define _loop1_51_type 1294 -#define _loop0_53_type 1295 -#define _gather_52_type 1296 -#define _loop0_55_type 1297 -#define _gather_54_type 1298 -#define _loop0_57_type 1299 -#define _gather_56_type 1300 -#define _loop0_59_type 1301 -#define _gather_58_type 1302 -#define _tmp_60_type 1303 -#define _loop1_61_type 1304 -#define _loop1_62_type 1305 -#define _tmp_63_type 1306 -#define _tmp_64_type 1307 -#define _loop1_65_type 1308 -#define _loop0_67_type 1309 -#define _gather_66_type 1310 -#define _tmp_68_type 1311 -#define _tmp_69_type 1312 -#define _tmp_70_type 1313 -#define _tmp_71_type 1314 -#define _loop0_73_type 1315 -#define _gather_72_type 1316 -#define _loop0_75_type 1317 -#define _gather_74_type 1318 -#define _tmp_76_type 1319 -#define _loop0_78_type 1320 -#define _gather_77_type 1321 -#define _loop0_80_type 1322 -#define _gather_79_type 1323 -#define _loop0_82_type 1324 -#define _gather_81_type 1325 -#define _loop1_83_type 1326 -#define _loop1_84_type 1327 -#define _loop0_86_type 1328 -#define _gather_85_type 1329 -#define _loop1_87_type 1330 -#define _loop1_88_type 1331 -#define _loop1_89_type 1332 -#define _tmp_90_type 1333 -#define _loop0_92_type 1334 -#define _gather_91_type 1335 -#define _tmp_93_type 1336 -#define _tmp_94_type 1337 -#define _tmp_95_type 1338 -#define _tmp_96_type 1339 -#define _tmp_97_type 1340 -#define _tmp_98_type 1341 -#define _loop0_99_type 1342 -#define _loop0_100_type 1343 -#define _loop0_101_type 1344 -#define _loop1_102_type 1345 -#define _loop0_103_type 1346 -#define _loop1_104_type 1347 -#define _loop1_105_type 1348 -#define _loop1_106_type 1349 -#define _loop0_107_type 1350 -#define _loop1_108_type 1351 -#define _loop0_109_type 1352 -#define _loop1_110_type 1353 -#define _loop0_111_type 1354 -#define _loop1_112_type 1355 -#define _tmp_113_type 1356 -#define _loop0_114_type 1357 -#define _loop1_115_type 1358 -#define _tmp_116_type 1359 -#define _loop0_118_type 1360 -#define _gather_117_type 1361 -#define _loop1_119_type 1362 -#define _loop0_120_type 1363 -#define _loop0_121_type 1364 -#define _tmp_122_type 1365 -#define _loop0_124_type 1366 -#define _gather_123_type 1367 -#define _tmp_125_type 1368 -#define _loop0_127_type 1369 -#define _gather_126_type 1370 -#define _loop0_129_type 1371 -#define _gather_128_type 1372 -#define _loop0_131_type 1373 -#define _gather_130_type 1374 -#define _loop0_133_type 1375 -#define _gather_132_type 1376 +#define invalid_compound_stmt_type 1220 +#define invalid_with_stmt_type 1221 +#define invalid_with_stmt_indent_type 1222 +#define invalid_try_stmt_type 1223 +#define invalid_except_stmt_type 1224 +#define invalid_finally_stmt_type 1225 +#define invalid_except_stmt_indent_type 1226 +#define invalid_except_star_stmt_indent_type 1227 +#define invalid_match_stmt_type 1228 +#define invalid_case_block_type 1229 +#define invalid_as_pattern_type 1230 +#define invalid_class_pattern_type 1231 +#define invalid_class_argument_pattern_type 1232 +#define invalid_if_stmt_type 1233 +#define invalid_elif_stmt_type 1234 +#define invalid_else_stmt_type 1235 +#define invalid_while_stmt_type 1236 +#define invalid_for_stmt_type 1237 +#define invalid_def_raw_type 1238 +#define invalid_class_def_raw_type 1239 +#define invalid_double_starred_kvpairs_type 1240 +#define invalid_kvpair_type 1241 +#define invalid_starred_expression_type 1242 +#define invalid_replacement_field_type 1243 +#define invalid_conversion_character_type 1244 +#define _loop0_1_type 1245 +#define _loop0_2_type 1246 +#define _loop1_3_type 1247 +#define _loop0_5_type 1248 +#define _gather_4_type 1249 +#define _tmp_6_type 1250 +#define _tmp_7_type 1251 +#define _tmp_8_type 1252 +#define _tmp_9_type 1253 +#define _tmp_10_type 1254 +#define _tmp_11_type 1255 +#define _tmp_12_type 1256 +#define _tmp_13_type 1257 +#define _loop1_14_type 1258 +#define _tmp_15_type 1259 +#define _tmp_16_type 1260 +#define _tmp_17_type 1261 +#define _loop0_19_type 1262 +#define _gather_18_type 1263 +#define _loop0_21_type 1264 +#define _gather_20_type 1265 +#define _tmp_22_type 1266 +#define _tmp_23_type 1267 +#define _loop0_24_type 1268 +#define _loop1_25_type 1269 +#define _loop0_27_type 1270 +#define _gather_26_type 1271 +#define _tmp_28_type 1272 +#define _loop0_30_type 1273 +#define _gather_29_type 1274 +#define _tmp_31_type 1275 +#define _loop1_32_type 1276 +#define _tmp_33_type 1277 +#define _tmp_34_type 1278 +#define _tmp_35_type 1279 +#define _loop0_36_type 1280 +#define _loop0_37_type 1281 +#define _loop0_38_type 1282 +#define _loop1_39_type 1283 +#define _loop0_40_type 1284 +#define _loop1_41_type 1285 +#define _loop1_42_type 1286 +#define _loop1_43_type 1287 +#define _loop0_44_type 1288 +#define _loop1_45_type 1289 +#define _loop0_46_type 1290 +#define _loop1_47_type 1291 +#define _loop0_48_type 1292 +#define _loop0_49_type 1293 +#define _loop1_50_type 1294 +#define _loop0_52_type 1295 +#define _gather_51_type 1296 +#define _loop0_54_type 1297 +#define _gather_53_type 1298 +#define _loop0_56_type 1299 +#define _gather_55_type 1300 +#define _loop0_58_type 1301 +#define _gather_57_type 1302 +#define _tmp_59_type 1303 +#define _loop1_60_type 1304 +#define _loop1_61_type 1305 +#define _tmp_62_type 1306 +#define _tmp_63_type 1307 +#define _loop1_64_type 1308 +#define _loop0_66_type 1309 +#define _gather_65_type 1310 +#define _tmp_67_type 1311 +#define _tmp_68_type 1312 +#define _tmp_69_type 1313 +#define _tmp_70_type 1314 +#define _loop0_72_type 1315 +#define _gather_71_type 1316 +#define _loop0_74_type 1317 +#define _gather_73_type 1318 +#define _tmp_75_type 1319 +#define _loop0_77_type 1320 +#define _gather_76_type 1321 +#define _loop0_79_type 1322 +#define _gather_78_type 1323 +#define _loop0_81_type 1324 +#define _gather_80_type 1325 +#define _loop1_82_type 1326 +#define _loop1_83_type 1327 +#define _loop0_85_type 1328 +#define _gather_84_type 1329 +#define _loop1_86_type 1330 +#define _loop1_87_type 1331 +#define _loop1_88_type 1332 +#define _tmp_89_type 1333 +#define _loop0_91_type 1334 +#define _gather_90_type 1335 +#define _tmp_92_type 1336 +#define _tmp_93_type 1337 +#define _tmp_94_type 1338 +#define _tmp_95_type 1339 +#define _tmp_96_type 1340 +#define _tmp_97_type 1341 +#define _loop0_98_type 1342 +#define _loop0_99_type 1343 +#define _loop0_100_type 1344 +#define _loop1_101_type 1345 +#define _loop0_102_type 1346 +#define _loop1_103_type 1347 +#define _loop1_104_type 1348 +#define _loop1_105_type 1349 +#define _loop0_106_type 1350 +#define _loop1_107_type 1351 +#define _loop0_108_type 1352 +#define _loop1_109_type 1353 +#define _loop0_110_type 1354 +#define _loop1_111_type 1355 +#define _tmp_112_type 1356 +#define _loop0_113_type 1357 +#define _loop0_114_type 1358 +#define _loop1_115_type 1359 +#define _tmp_116_type 1360 +#define _loop0_118_type 1361 +#define _gather_117_type 1362 +#define _loop1_119_type 1363 +#define _loop0_120_type 1364 +#define _loop0_121_type 1365 +#define _tmp_122_type 1366 +#define _tmp_123_type 1367 +#define _loop0_125_type 1368 +#define _gather_124_type 1369 +#define _tmp_126_type 1370 +#define _loop0_128_type 1371 +#define _gather_127_type 1372 +#define _loop0_130_type 1373 +#define _gather_129_type 1374 +#define _loop0_132_type 1375 +#define _gather_131_type 1376 #define _loop0_134_type 1377 -#define _loop0_136_type 1378 -#define _gather_135_type 1379 -#define _loop1_137_type 1380 -#define _tmp_138_type 1381 -#define _loop0_140_type 1382 -#define _gather_139_type 1383 -#define _loop0_142_type 1384 -#define _gather_141_type 1385 -#define _loop0_144_type 1386 -#define _gather_143_type 1387 -#define _loop0_146_type 1388 -#define _gather_145_type 1389 -#define _loop0_148_type 1390 -#define _gather_147_type 1391 -#define _tmp_149_type 1392 -#define _tmp_150_type 1393 -#define _tmp_151_type 1394 -#define _tmp_152_type 1395 -#define _tmp_153_type 1396 -#define _tmp_154_type 1397 -#define _tmp_155_type 1398 -#define _tmp_156_type 1399 -#define _tmp_157_type 1400 -#define _tmp_158_type 1401 -#define _tmp_159_type 1402 -#define _tmp_160_type 1403 -#define _loop0_161_type 1404 -#define _loop0_162_type 1405 -#define _loop0_163_type 1406 -#define _tmp_164_type 1407 -#define _tmp_165_type 1408 -#define _tmp_166_type 1409 -#define _tmp_167_type 1410 -#define _tmp_168_type 1411 -#define _loop0_169_type 1412 -#define _loop0_170_type 1413 -#define _loop0_171_type 1414 -#define _loop1_172_type 1415 -#define _tmp_173_type 1416 -#define _loop0_174_type 1417 -#define _tmp_175_type 1418 -#define _loop0_176_type 1419 -#define _loop1_177_type 1420 -#define _tmp_178_type 1421 -#define _tmp_179_type 1422 -#define _tmp_180_type 1423 -#define _loop0_181_type 1424 -#define _tmp_182_type 1425 -#define _tmp_183_type 1426 -#define _loop1_184_type 1427 -#define _tmp_185_type 1428 -#define _loop0_186_type 1429 -#define _loop0_187_type 1430 -#define _loop0_188_type 1431 -#define _loop0_190_type 1432 -#define _gather_189_type 1433 -#define _tmp_191_type 1434 -#define _loop0_192_type 1435 -#define _tmp_193_type 1436 -#define _loop0_194_type 1437 -#define _loop1_195_type 1438 -#define _loop1_196_type 1439 -#define _tmp_197_type 1440 -#define _tmp_198_type 1441 -#define _loop0_199_type 1442 -#define _tmp_200_type 1443 -#define _tmp_201_type 1444 -#define _tmp_202_type 1445 -#define _loop0_204_type 1446 -#define _gather_203_type 1447 -#define _loop0_206_type 1448 -#define _gather_205_type 1449 -#define _loop0_208_type 1450 -#define _gather_207_type 1451 -#define _loop0_210_type 1452 -#define _gather_209_type 1453 -#define _loop0_212_type 1454 -#define _gather_211_type 1455 -#define _tmp_213_type 1456 -#define _loop0_214_type 1457 -#define _loop1_215_type 1458 -#define _tmp_216_type 1459 -#define _loop0_217_type 1460 -#define _loop1_218_type 1461 -#define _tmp_219_type 1462 -#define _tmp_220_type 1463 -#define _tmp_221_type 1464 -#define _tmp_222_type 1465 -#define _tmp_223_type 1466 -#define _tmp_224_type 1467 -#define _tmp_225_type 1468 -#define _tmp_226_type 1469 -#define _tmp_227_type 1470 -#define _tmp_228_type 1471 -#define _loop0_230_type 1472 -#define _gather_229_type 1473 -#define _tmp_231_type 1474 -#define _tmp_232_type 1475 -#define _tmp_233_type 1476 -#define _tmp_234_type 1477 -#define _tmp_235_type 1478 -#define _tmp_236_type 1479 -#define _tmp_237_type 1480 -#define _tmp_238_type 1481 -#define _tmp_239_type 1482 -#define _tmp_240_type 1483 -#define _tmp_241_type 1484 -#define _tmp_242_type 1485 -#define _tmp_243_type 1486 -#define _loop0_244_type 1487 -#define _tmp_245_type 1488 -#define _tmp_246_type 1489 -#define _tmp_247_type 1490 -#define _tmp_248_type 1491 -#define _tmp_249_type 1492 -#define _tmp_250_type 1493 -#define _tmp_251_type 1494 -#define _tmp_252_type 1495 -#define _tmp_253_type 1496 -#define _tmp_254_type 1497 -#define _tmp_255_type 1498 -#define _tmp_256_type 1499 -#define _tmp_257_type 1500 -#define _tmp_258_type 1501 -#define _tmp_259_type 1502 -#define _tmp_260_type 1503 -#define _tmp_261_type 1504 -#define _tmp_262_type 1505 -#define _tmp_263_type 1506 -#define _tmp_264_type 1507 -#define _tmp_265_type 1508 -#define _tmp_266_type 1509 -#define _tmp_267_type 1510 -#define _tmp_268_type 1511 -#define _tmp_269_type 1512 -#define _tmp_270_type 1513 -#define _tmp_271_type 1514 -#define _tmp_272_type 1515 -#define _tmp_273_type 1516 -#define _tmp_274_type 1517 -#define _tmp_275_type 1518 -#define _tmp_276_type 1519 +#define _gather_133_type 1378 +#define _loop0_135_type 1379 +#define _loop0_137_type 1380 +#define _gather_136_type 1381 +#define _loop1_138_type 1382 +#define _tmp_139_type 1383 +#define _loop0_141_type 1384 +#define _gather_140_type 1385 +#define _loop0_143_type 1386 +#define _gather_142_type 1387 +#define _loop0_145_type 1388 +#define _gather_144_type 1389 +#define _loop0_147_type 1390 +#define _gather_146_type 1391 +#define _loop0_149_type 1392 +#define _gather_148_type 1393 +#define _tmp_150_type 1394 +#define _tmp_151_type 1395 +#define _tmp_152_type 1396 +#define _tmp_153_type 1397 +#define _tmp_154_type 1398 +#define _tmp_155_type 1399 +#define _tmp_156_type 1400 +#define _tmp_157_type 1401 +#define _tmp_158_type 1402 +#define _tmp_159_type 1403 +#define _tmp_160_type 1404 +#define _tmp_161_type 1405 +#define _loop0_162_type 1406 +#define _loop0_163_type 1407 +#define _loop0_164_type 1408 +#define _tmp_165_type 1409 +#define _tmp_166_type 1410 +#define _tmp_167_type 1411 +#define _tmp_168_type 1412 +#define _tmp_169_type 1413 +#define _loop0_170_type 1414 +#define _loop0_171_type 1415 +#define _loop0_172_type 1416 +#define _loop1_173_type 1417 +#define _tmp_174_type 1418 +#define _loop0_175_type 1419 +#define _tmp_176_type 1420 +#define _loop0_177_type 1421 +#define _loop1_178_type 1422 +#define _tmp_179_type 1423 +#define _tmp_180_type 1424 +#define _tmp_181_type 1425 +#define _loop0_182_type 1426 +#define _tmp_183_type 1427 +#define _tmp_184_type 1428 +#define _loop1_185_type 1429 +#define _tmp_186_type 1430 +#define _loop0_187_type 1431 +#define _loop0_188_type 1432 +#define _loop0_189_type 1433 +#define _loop0_191_type 1434 +#define _gather_190_type 1435 +#define _tmp_192_type 1436 +#define _loop0_193_type 1437 +#define _tmp_194_type 1438 +#define _loop0_195_type 1439 +#define _loop1_196_type 1440 +#define _loop1_197_type 1441 +#define _tmp_198_type 1442 +#define _tmp_199_type 1443 +#define _loop0_200_type 1444 +#define _tmp_201_type 1445 +#define _tmp_202_type 1446 +#define _tmp_203_type 1447 +#define _loop0_205_type 1448 +#define _gather_204_type 1449 +#define _loop0_207_type 1450 +#define _gather_206_type 1451 +#define _loop0_209_type 1452 +#define _gather_208_type 1453 +#define _loop0_211_type 1454 +#define _gather_210_type 1455 +#define _loop0_213_type 1456 +#define _gather_212_type 1457 +#define _tmp_214_type 1458 +#define _loop0_215_type 1459 +#define _loop1_216_type 1460 +#define _tmp_217_type 1461 +#define _loop0_218_type 1462 +#define _loop1_219_type 1463 +#define _tmp_220_type 1464 +#define _tmp_221_type 1465 +#define _tmp_222_type 1466 +#define _tmp_223_type 1467 +#define _tmp_224_type 1468 +#define _tmp_225_type 1469 +#define _tmp_226_type 1470 +#define _tmp_227_type 1471 +#define _tmp_228_type 1472 +#define _tmp_229_type 1473 +#define _loop0_231_type 1474 +#define _gather_230_type 1475 +#define _tmp_232_type 1476 +#define _tmp_233_type 1477 +#define _tmp_234_type 1478 +#define _tmp_235_type 1479 +#define _tmp_236_type 1480 +#define _tmp_237_type 1481 +#define _tmp_238_type 1482 +#define _tmp_239_type 1483 +#define _tmp_240_type 1484 +#define _tmp_241_type 1485 +#define _tmp_242_type 1486 +#define _tmp_243_type 1487 +#define _tmp_244_type 1488 +#define _loop0_245_type 1489 +#define _tmp_246_type 1490 +#define _tmp_247_type 1491 +#define _tmp_248_type 1492 +#define _tmp_249_type 1493 +#define _tmp_250_type 1494 +#define _tmp_251_type 1495 +#define _tmp_252_type 1496 +#define _tmp_253_type 1497 +#define _tmp_254_type 1498 +#define _tmp_255_type 1499 +#define _tmp_256_type 1500 +#define _tmp_257_type 1501 +#define _tmp_258_type 1502 +#define _tmp_259_type 1503 +#define _tmp_260_type 1504 +#define _loop0_261_type 1505 +#define _tmp_262_type 1506 +#define _tmp_263_type 1507 +#define _tmp_264_type 1508 +#define _tmp_265_type 1509 +#define _tmp_266_type 1510 +#define _tmp_267_type 1511 +#define _tmp_268_type 1512 +#define _tmp_269_type 1513 +#define _tmp_270_type 1514 +#define _tmp_271_type 1515 +#define _tmp_272_type 1516 +#define _tmp_273_type 1517 +#define _tmp_274_type 1518 +#define _tmp_275_type 1519 +#define _tmp_276_type 1520 +#define _loop0_278_type 1521 +#define _gather_277_type 1522 +#define _tmp_279_type 1523 +#define _tmp_280_type 1524 +#define _tmp_281_type 1525 +#define _tmp_282_type 1526 +#define _tmp_283_type 1527 +#define _tmp_284_type 1528 static mod_ty file_rule(Parser *p); static mod_ty interactive_rule(Parser *p); static mod_ty eval_rule(Parser *p); static mod_ty func_type_rule(Parser *p); -static expr_ty fstring_rule(Parser *p); static asdl_stmt_seq* statements_rule(Parser *p); static asdl_stmt_seq* statement_rule(Parser *p); static asdl_stmt_seq* statement_newline_rule(Parser *p); @@ -758,6 +770,7 @@ static expr_ty fstring_replacement_field_rule(Parser *p); static ResultTokenWithMetadata* fstring_conversion_rule(Parser *p); static ResultTokenWithMetadata* fstring_full_format_spec_rule(Parser *p); static expr_ty fstring_format_spec_rule(Parser *p); +static expr_ty fstring_rule(Parser *p); static expr_ty string_rule(Parser *p); static expr_ty strings_rule(Parser *p); static expr_ty list_rule(Parser *p); @@ -821,6 +834,7 @@ static void *invalid_for_target_rule(Parser *p); static void *invalid_group_rule(Parser *p); static void *invalid_import_rule(Parser *p); static void *invalid_import_from_targets_rule(Parser *p); +static void *invalid_compound_stmt_rule(Parser *p); static void *invalid_with_stmt_rule(Parser *p); static void *invalid_with_stmt_indent_rule(Parser *p); static void *invalid_try_stmt_rule(Parser *p); @@ -847,10 +861,10 @@ static void *invalid_replacement_field_rule(Parser *p); static void *invalid_conversion_character_rule(Parser *p); static asdl_seq *_loop0_1_rule(Parser *p); static asdl_seq *_loop0_2_rule(Parser *p); -static asdl_seq *_loop0_3_rule(Parser *p); -static asdl_seq *_loop1_4_rule(Parser *p); -static asdl_seq *_loop0_6_rule(Parser *p); -static asdl_seq *_gather_5_rule(Parser *p); +static asdl_seq *_loop1_3_rule(Parser *p); +static asdl_seq *_loop0_5_rule(Parser *p); +static asdl_seq *_gather_4_rule(Parser *p); +static void *_tmp_6_rule(Parser *p); static void *_tmp_7_rule(Parser *p); static void *_tmp_8_rule(Parser *p); static void *_tmp_9_rule(Parser *p); @@ -858,106 +872,106 @@ static void *_tmp_10_rule(Parser *p); static void *_tmp_11_rule(Parser *p); static void *_tmp_12_rule(Parser *p); static void *_tmp_13_rule(Parser *p); -static void *_tmp_14_rule(Parser *p); -static asdl_seq *_loop1_15_rule(Parser *p); +static asdl_seq *_loop1_14_rule(Parser *p); +static void *_tmp_15_rule(Parser *p); static void *_tmp_16_rule(Parser *p); static void *_tmp_17_rule(Parser *p); -static void *_tmp_18_rule(Parser *p); -static asdl_seq *_loop0_20_rule(Parser *p); -static asdl_seq *_gather_19_rule(Parser *p); -static asdl_seq *_loop0_22_rule(Parser *p); -static asdl_seq *_gather_21_rule(Parser *p); +static asdl_seq *_loop0_19_rule(Parser *p); +static asdl_seq *_gather_18_rule(Parser *p); +static asdl_seq *_loop0_21_rule(Parser *p); +static asdl_seq *_gather_20_rule(Parser *p); +static void *_tmp_22_rule(Parser *p); static void *_tmp_23_rule(Parser *p); -static void *_tmp_24_rule(Parser *p); -static asdl_seq *_loop0_25_rule(Parser *p); -static asdl_seq *_loop1_26_rule(Parser *p); -static asdl_seq *_loop0_28_rule(Parser *p); -static asdl_seq *_gather_27_rule(Parser *p); -static void *_tmp_29_rule(Parser *p); -static asdl_seq *_loop0_31_rule(Parser *p); -static asdl_seq *_gather_30_rule(Parser *p); -static void *_tmp_32_rule(Parser *p); -static asdl_seq *_loop1_33_rule(Parser *p); +static asdl_seq *_loop0_24_rule(Parser *p); +static asdl_seq *_loop1_25_rule(Parser *p); +static asdl_seq *_loop0_27_rule(Parser *p); +static asdl_seq *_gather_26_rule(Parser *p); +static void *_tmp_28_rule(Parser *p); +static asdl_seq *_loop0_30_rule(Parser *p); +static asdl_seq *_gather_29_rule(Parser *p); +static void *_tmp_31_rule(Parser *p); +static asdl_seq *_loop1_32_rule(Parser *p); +static void *_tmp_33_rule(Parser *p); static void *_tmp_34_rule(Parser *p); static void *_tmp_35_rule(Parser *p); -static void *_tmp_36_rule(Parser *p); +static asdl_seq *_loop0_36_rule(Parser *p); static asdl_seq *_loop0_37_rule(Parser *p); static asdl_seq *_loop0_38_rule(Parser *p); -static asdl_seq *_loop0_39_rule(Parser *p); -static asdl_seq *_loop1_40_rule(Parser *p); -static asdl_seq *_loop0_41_rule(Parser *p); +static asdl_seq *_loop1_39_rule(Parser *p); +static asdl_seq *_loop0_40_rule(Parser *p); +static asdl_seq *_loop1_41_rule(Parser *p); static asdl_seq *_loop1_42_rule(Parser *p); static asdl_seq *_loop1_43_rule(Parser *p); -static asdl_seq *_loop1_44_rule(Parser *p); -static asdl_seq *_loop0_45_rule(Parser *p); -static asdl_seq *_loop1_46_rule(Parser *p); -static asdl_seq *_loop0_47_rule(Parser *p); -static asdl_seq *_loop1_48_rule(Parser *p); +static asdl_seq *_loop0_44_rule(Parser *p); +static asdl_seq *_loop1_45_rule(Parser *p); +static asdl_seq *_loop0_46_rule(Parser *p); +static asdl_seq *_loop1_47_rule(Parser *p); +static asdl_seq *_loop0_48_rule(Parser *p); static asdl_seq *_loop0_49_rule(Parser *p); -static asdl_seq *_loop0_50_rule(Parser *p); -static asdl_seq *_loop1_51_rule(Parser *p); -static asdl_seq *_loop0_53_rule(Parser *p); -static asdl_seq *_gather_52_rule(Parser *p); -static asdl_seq *_loop0_55_rule(Parser *p); -static asdl_seq *_gather_54_rule(Parser *p); -static asdl_seq *_loop0_57_rule(Parser *p); -static asdl_seq *_gather_56_rule(Parser *p); -static asdl_seq *_loop0_59_rule(Parser *p); -static asdl_seq *_gather_58_rule(Parser *p); -static void *_tmp_60_rule(Parser *p); +static asdl_seq *_loop1_50_rule(Parser *p); +static asdl_seq *_loop0_52_rule(Parser *p); +static asdl_seq *_gather_51_rule(Parser *p); +static asdl_seq *_loop0_54_rule(Parser *p); +static asdl_seq *_gather_53_rule(Parser *p); +static asdl_seq *_loop0_56_rule(Parser *p); +static asdl_seq *_gather_55_rule(Parser *p); +static asdl_seq *_loop0_58_rule(Parser *p); +static asdl_seq *_gather_57_rule(Parser *p); +static void *_tmp_59_rule(Parser *p); +static asdl_seq *_loop1_60_rule(Parser *p); static asdl_seq *_loop1_61_rule(Parser *p); -static asdl_seq *_loop1_62_rule(Parser *p); +static void *_tmp_62_rule(Parser *p); static void *_tmp_63_rule(Parser *p); -static void *_tmp_64_rule(Parser *p); -static asdl_seq *_loop1_65_rule(Parser *p); -static asdl_seq *_loop0_67_rule(Parser *p); -static asdl_seq *_gather_66_rule(Parser *p); +static asdl_seq *_loop1_64_rule(Parser *p); +static asdl_seq *_loop0_66_rule(Parser *p); +static asdl_seq *_gather_65_rule(Parser *p); +static void *_tmp_67_rule(Parser *p); static void *_tmp_68_rule(Parser *p); static void *_tmp_69_rule(Parser *p); static void *_tmp_70_rule(Parser *p); -static void *_tmp_71_rule(Parser *p); -static asdl_seq *_loop0_73_rule(Parser *p); -static asdl_seq *_gather_72_rule(Parser *p); -static asdl_seq *_loop0_75_rule(Parser *p); -static asdl_seq *_gather_74_rule(Parser *p); -static void *_tmp_76_rule(Parser *p); -static asdl_seq *_loop0_78_rule(Parser *p); -static asdl_seq *_gather_77_rule(Parser *p); -static asdl_seq *_loop0_80_rule(Parser *p); -static asdl_seq *_gather_79_rule(Parser *p); -static asdl_seq *_loop0_82_rule(Parser *p); -static asdl_seq *_gather_81_rule(Parser *p); +static asdl_seq *_loop0_72_rule(Parser *p); +static asdl_seq *_gather_71_rule(Parser *p); +static asdl_seq *_loop0_74_rule(Parser *p); +static asdl_seq *_gather_73_rule(Parser *p); +static void *_tmp_75_rule(Parser *p); +static asdl_seq *_loop0_77_rule(Parser *p); +static asdl_seq *_gather_76_rule(Parser *p); +static asdl_seq *_loop0_79_rule(Parser *p); +static asdl_seq *_gather_78_rule(Parser *p); +static asdl_seq *_loop0_81_rule(Parser *p); +static asdl_seq *_gather_80_rule(Parser *p); +static asdl_seq *_loop1_82_rule(Parser *p); static asdl_seq *_loop1_83_rule(Parser *p); -static asdl_seq *_loop1_84_rule(Parser *p); -static asdl_seq *_loop0_86_rule(Parser *p); -static asdl_seq *_gather_85_rule(Parser *p); +static asdl_seq *_loop0_85_rule(Parser *p); +static asdl_seq *_gather_84_rule(Parser *p); +static asdl_seq *_loop1_86_rule(Parser *p); static asdl_seq *_loop1_87_rule(Parser *p); static asdl_seq *_loop1_88_rule(Parser *p); -static asdl_seq *_loop1_89_rule(Parser *p); -static void *_tmp_90_rule(Parser *p); -static asdl_seq *_loop0_92_rule(Parser *p); -static asdl_seq *_gather_91_rule(Parser *p); +static void *_tmp_89_rule(Parser *p); +static asdl_seq *_loop0_91_rule(Parser *p); +static asdl_seq *_gather_90_rule(Parser *p); +static void *_tmp_92_rule(Parser *p); static void *_tmp_93_rule(Parser *p); static void *_tmp_94_rule(Parser *p); static void *_tmp_95_rule(Parser *p); static void *_tmp_96_rule(Parser *p); static void *_tmp_97_rule(Parser *p); -static void *_tmp_98_rule(Parser *p); +static asdl_seq *_loop0_98_rule(Parser *p); static asdl_seq *_loop0_99_rule(Parser *p); static asdl_seq *_loop0_100_rule(Parser *p); -static asdl_seq *_loop0_101_rule(Parser *p); -static asdl_seq *_loop1_102_rule(Parser *p); -static asdl_seq *_loop0_103_rule(Parser *p); +static asdl_seq *_loop1_101_rule(Parser *p); +static asdl_seq *_loop0_102_rule(Parser *p); +static asdl_seq *_loop1_103_rule(Parser *p); static asdl_seq *_loop1_104_rule(Parser *p); static asdl_seq *_loop1_105_rule(Parser *p); -static asdl_seq *_loop1_106_rule(Parser *p); -static asdl_seq *_loop0_107_rule(Parser *p); -static asdl_seq *_loop1_108_rule(Parser *p); -static asdl_seq *_loop0_109_rule(Parser *p); -static asdl_seq *_loop1_110_rule(Parser *p); -static asdl_seq *_loop0_111_rule(Parser *p); -static asdl_seq *_loop1_112_rule(Parser *p); -static void *_tmp_113_rule(Parser *p); +static asdl_seq *_loop0_106_rule(Parser *p); +static asdl_seq *_loop1_107_rule(Parser *p); +static asdl_seq *_loop0_108_rule(Parser *p); +static asdl_seq *_loop1_109_rule(Parser *p); +static asdl_seq *_loop0_110_rule(Parser *p); +static asdl_seq *_loop1_111_rule(Parser *p); +static void *_tmp_112_rule(Parser *p); +static asdl_seq *_loop0_113_rule(Parser *p); static asdl_seq *_loop0_114_rule(Parser *p); static asdl_seq *_loop1_115_rule(Parser *p); static void *_tmp_116_rule(Parser *p); @@ -967,33 +981,33 @@ static asdl_seq *_loop1_119_rule(Parser *p); static asdl_seq *_loop0_120_rule(Parser *p); static asdl_seq *_loop0_121_rule(Parser *p); static void *_tmp_122_rule(Parser *p); -static asdl_seq *_loop0_124_rule(Parser *p); -static asdl_seq *_gather_123_rule(Parser *p); -static void *_tmp_125_rule(Parser *p); -static asdl_seq *_loop0_127_rule(Parser *p); -static asdl_seq *_gather_126_rule(Parser *p); -static asdl_seq *_loop0_129_rule(Parser *p); -static asdl_seq *_gather_128_rule(Parser *p); -static asdl_seq *_loop0_131_rule(Parser *p); -static asdl_seq *_gather_130_rule(Parser *p); -static asdl_seq *_loop0_133_rule(Parser *p); -static asdl_seq *_gather_132_rule(Parser *p); +static void *_tmp_123_rule(Parser *p); +static asdl_seq *_loop0_125_rule(Parser *p); +static asdl_seq *_gather_124_rule(Parser *p); +static void *_tmp_126_rule(Parser *p); +static asdl_seq *_loop0_128_rule(Parser *p); +static asdl_seq *_gather_127_rule(Parser *p); +static asdl_seq *_loop0_130_rule(Parser *p); +static asdl_seq *_gather_129_rule(Parser *p); +static asdl_seq *_loop0_132_rule(Parser *p); +static asdl_seq *_gather_131_rule(Parser *p); static asdl_seq *_loop0_134_rule(Parser *p); -static asdl_seq *_loop0_136_rule(Parser *p); -static asdl_seq *_gather_135_rule(Parser *p); -static asdl_seq *_loop1_137_rule(Parser *p); -static void *_tmp_138_rule(Parser *p); -static asdl_seq *_loop0_140_rule(Parser *p); -static asdl_seq *_gather_139_rule(Parser *p); -static asdl_seq *_loop0_142_rule(Parser *p); -static asdl_seq *_gather_141_rule(Parser *p); -static asdl_seq *_loop0_144_rule(Parser *p); -static asdl_seq *_gather_143_rule(Parser *p); -static asdl_seq *_loop0_146_rule(Parser *p); -static asdl_seq *_gather_145_rule(Parser *p); -static asdl_seq *_loop0_148_rule(Parser *p); -static asdl_seq *_gather_147_rule(Parser *p); -static void *_tmp_149_rule(Parser *p); +static asdl_seq *_gather_133_rule(Parser *p); +static asdl_seq *_loop0_135_rule(Parser *p); +static asdl_seq *_loop0_137_rule(Parser *p); +static asdl_seq *_gather_136_rule(Parser *p); +static asdl_seq *_loop1_138_rule(Parser *p); +static void *_tmp_139_rule(Parser *p); +static asdl_seq *_loop0_141_rule(Parser *p); +static asdl_seq *_gather_140_rule(Parser *p); +static asdl_seq *_loop0_143_rule(Parser *p); +static asdl_seq *_gather_142_rule(Parser *p); +static asdl_seq *_loop0_145_rule(Parser *p); +static asdl_seq *_gather_144_rule(Parser *p); +static asdl_seq *_loop0_147_rule(Parser *p); +static asdl_seq *_gather_146_rule(Parser *p); +static asdl_seq *_loop0_149_rule(Parser *p); +static asdl_seq *_gather_148_rule(Parser *p); static void *_tmp_150_rule(Parser *p); static void *_tmp_151_rule(Parser *p); static void *_tmp_152_rule(Parser *p); @@ -1005,65 +1019,65 @@ static void *_tmp_157_rule(Parser *p); static void *_tmp_158_rule(Parser *p); static void *_tmp_159_rule(Parser *p); static void *_tmp_160_rule(Parser *p); -static asdl_seq *_loop0_161_rule(Parser *p); +static void *_tmp_161_rule(Parser *p); static asdl_seq *_loop0_162_rule(Parser *p); static asdl_seq *_loop0_163_rule(Parser *p); -static void *_tmp_164_rule(Parser *p); +static asdl_seq *_loop0_164_rule(Parser *p); static void *_tmp_165_rule(Parser *p); static void *_tmp_166_rule(Parser *p); static void *_tmp_167_rule(Parser *p); static void *_tmp_168_rule(Parser *p); -static asdl_seq *_loop0_169_rule(Parser *p); +static void *_tmp_169_rule(Parser *p); static asdl_seq *_loop0_170_rule(Parser *p); static asdl_seq *_loop0_171_rule(Parser *p); -static asdl_seq *_loop1_172_rule(Parser *p); -static void *_tmp_173_rule(Parser *p); -static asdl_seq *_loop0_174_rule(Parser *p); -static void *_tmp_175_rule(Parser *p); -static asdl_seq *_loop0_176_rule(Parser *p); -static asdl_seq *_loop1_177_rule(Parser *p); -static void *_tmp_178_rule(Parser *p); +static asdl_seq *_loop0_172_rule(Parser *p); +static asdl_seq *_loop1_173_rule(Parser *p); +static void *_tmp_174_rule(Parser *p); +static asdl_seq *_loop0_175_rule(Parser *p); +static void *_tmp_176_rule(Parser *p); +static asdl_seq *_loop0_177_rule(Parser *p); +static asdl_seq *_loop1_178_rule(Parser *p); static void *_tmp_179_rule(Parser *p); static void *_tmp_180_rule(Parser *p); -static asdl_seq *_loop0_181_rule(Parser *p); -static void *_tmp_182_rule(Parser *p); +static void *_tmp_181_rule(Parser *p); +static asdl_seq *_loop0_182_rule(Parser *p); static void *_tmp_183_rule(Parser *p); -static asdl_seq *_loop1_184_rule(Parser *p); -static void *_tmp_185_rule(Parser *p); -static asdl_seq *_loop0_186_rule(Parser *p); +static void *_tmp_184_rule(Parser *p); +static asdl_seq *_loop1_185_rule(Parser *p); +static void *_tmp_186_rule(Parser *p); static asdl_seq *_loop0_187_rule(Parser *p); static asdl_seq *_loop0_188_rule(Parser *p); -static asdl_seq *_loop0_190_rule(Parser *p); -static asdl_seq *_gather_189_rule(Parser *p); -static void *_tmp_191_rule(Parser *p); -static asdl_seq *_loop0_192_rule(Parser *p); -static void *_tmp_193_rule(Parser *p); -static asdl_seq *_loop0_194_rule(Parser *p); -static asdl_seq *_loop1_195_rule(Parser *p); +static asdl_seq *_loop0_189_rule(Parser *p); +static asdl_seq *_loop0_191_rule(Parser *p); +static asdl_seq *_gather_190_rule(Parser *p); +static void *_tmp_192_rule(Parser *p); +static asdl_seq *_loop0_193_rule(Parser *p); +static void *_tmp_194_rule(Parser *p); +static asdl_seq *_loop0_195_rule(Parser *p); static asdl_seq *_loop1_196_rule(Parser *p); -static void *_tmp_197_rule(Parser *p); +static asdl_seq *_loop1_197_rule(Parser *p); static void *_tmp_198_rule(Parser *p); -static asdl_seq *_loop0_199_rule(Parser *p); -static void *_tmp_200_rule(Parser *p); +static void *_tmp_199_rule(Parser *p); +static asdl_seq *_loop0_200_rule(Parser *p); static void *_tmp_201_rule(Parser *p); static void *_tmp_202_rule(Parser *p); -static asdl_seq *_loop0_204_rule(Parser *p); -static asdl_seq *_gather_203_rule(Parser *p); -static asdl_seq *_loop0_206_rule(Parser *p); -static asdl_seq *_gather_205_rule(Parser *p); -static asdl_seq *_loop0_208_rule(Parser *p); -static asdl_seq *_gather_207_rule(Parser *p); -static asdl_seq *_loop0_210_rule(Parser *p); -static asdl_seq *_gather_209_rule(Parser *p); -static asdl_seq *_loop0_212_rule(Parser *p); -static asdl_seq *_gather_211_rule(Parser *p); -static void *_tmp_213_rule(Parser *p); -static asdl_seq *_loop0_214_rule(Parser *p); -static asdl_seq *_loop1_215_rule(Parser *p); -static void *_tmp_216_rule(Parser *p); -static asdl_seq *_loop0_217_rule(Parser *p); -static asdl_seq *_loop1_218_rule(Parser *p); -static void *_tmp_219_rule(Parser *p); +static void *_tmp_203_rule(Parser *p); +static asdl_seq *_loop0_205_rule(Parser *p); +static asdl_seq *_gather_204_rule(Parser *p); +static asdl_seq *_loop0_207_rule(Parser *p); +static asdl_seq *_gather_206_rule(Parser *p); +static asdl_seq *_loop0_209_rule(Parser *p); +static asdl_seq *_gather_208_rule(Parser *p); +static asdl_seq *_loop0_211_rule(Parser *p); +static asdl_seq *_gather_210_rule(Parser *p); +static asdl_seq *_loop0_213_rule(Parser *p); +static asdl_seq *_gather_212_rule(Parser *p); +static void *_tmp_214_rule(Parser *p); +static asdl_seq *_loop0_215_rule(Parser *p); +static asdl_seq *_loop1_216_rule(Parser *p); +static void *_tmp_217_rule(Parser *p); +static asdl_seq *_loop0_218_rule(Parser *p); +static asdl_seq *_loop1_219_rule(Parser *p); static void *_tmp_220_rule(Parser *p); static void *_tmp_221_rule(Parser *p); static void *_tmp_222_rule(Parser *p); @@ -1073,9 +1087,9 @@ static void *_tmp_225_rule(Parser *p); static void *_tmp_226_rule(Parser *p); static void *_tmp_227_rule(Parser *p); static void *_tmp_228_rule(Parser *p); -static asdl_seq *_loop0_230_rule(Parser *p); -static asdl_seq *_gather_229_rule(Parser *p); -static void *_tmp_231_rule(Parser *p); +static void *_tmp_229_rule(Parser *p); +static asdl_seq *_loop0_231_rule(Parser *p); +static asdl_seq *_gather_230_rule(Parser *p); static void *_tmp_232_rule(Parser *p); static void *_tmp_233_rule(Parser *p); static void *_tmp_234_rule(Parser *p); @@ -1088,8 +1102,8 @@ static void *_tmp_240_rule(Parser *p); static void *_tmp_241_rule(Parser *p); static void *_tmp_242_rule(Parser *p); static void *_tmp_243_rule(Parser *p); -static asdl_seq *_loop0_244_rule(Parser *p); -static void *_tmp_245_rule(Parser *p); +static void *_tmp_244_rule(Parser *p); +static asdl_seq *_loop0_245_rule(Parser *p); static void *_tmp_246_rule(Parser *p); static void *_tmp_247_rule(Parser *p); static void *_tmp_248_rule(Parser *p); @@ -1105,7 +1119,7 @@ static void *_tmp_257_rule(Parser *p); static void *_tmp_258_rule(Parser *p); static void *_tmp_259_rule(Parser *p); static void *_tmp_260_rule(Parser *p); -static void *_tmp_261_rule(Parser *p); +static asdl_seq *_loop0_261_rule(Parser *p); static void *_tmp_262_rule(Parser *p); static void *_tmp_263_rule(Parser *p); static void *_tmp_264_rule(Parser *p); @@ -1121,6 +1135,14 @@ static void *_tmp_273_rule(Parser *p); static void *_tmp_274_rule(Parser *p); static void *_tmp_275_rule(Parser *p); static void *_tmp_276_rule(Parser *p); +static asdl_seq *_loop0_278_rule(Parser *p); +static asdl_seq *_gather_277_rule(Parser *p); +static void *_tmp_279_rule(Parser *p); +static void *_tmp_280_rule(Parser *p); +static void *_tmp_281_rule(Parser *p); +static void *_tmp_282_rule(Parser *p); +static void *_tmp_283_rule(Parser *p); +static void *_tmp_284_rule(Parser *p); // file: statements? $ @@ -1128,8 +1150,7 @@ static mod_ty file_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -1175,8 +1196,7 @@ static mod_ty interactive_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -1219,8 +1239,7 @@ static mod_ty eval_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -1269,8 +1288,7 @@ static mod_ty func_type_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -1326,63 +1344,12 @@ func_type_rule(Parser *p) return _res; } -// fstring: FSTRING_START fstring_middle* FSTRING_END -static expr_ty -fstring_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - expr_ty _res = NULL; - int _mark = p->mark; - { // FSTRING_START fstring_middle* FSTRING_END - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> fstring[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "FSTRING_START fstring_middle* FSTRING_END")); - Token * a; - asdl_seq * b; - Token * c; - if ( - (a = _PyPegen_expect_token(p, FSTRING_START)) // token='FSTRING_START' - && - (b = _loop0_3_rule(p)) // fstring_middle* - && - (c = _PyPegen_expect_token(p, FSTRING_END)) // token='FSTRING_END' - ) - { - D(fprintf(stderr, "%*c+ fstring[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "FSTRING_START fstring_middle* FSTRING_END")); - _res = _PyPegen_joined_str ( p , a , ( asdl_expr_seq* ) b , c ); - if (_res == NULL && PyErr_Occurred()) { - p->error_indicator = 1; - p->level--; - return NULL; - } - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s fstring[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "FSTRING_START fstring_middle* FSTRING_END")); - } - _res = NULL; - done: - p->level--; - return _res; -} - // statements: statement+ static asdl_stmt_seq* statements_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -1398,7 +1365,7 @@ statements_rule(Parser *p) D(fprintf(stderr, "%*c> statements[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "statement+")); asdl_seq * a; if ( - (a = _loop1_4_rule(p)) // statement+ + (a = _loop1_3_rule(p)) // statement+ ) { D(fprintf(stderr, "%*c+ statements[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "statement+")); @@ -1425,8 +1392,7 @@ static asdl_stmt_seq* statement_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -1493,8 +1459,7 @@ static asdl_stmt_seq* statement_newline_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -1625,8 +1590,7 @@ static asdl_stmt_seq* simple_stmts_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -1674,7 +1638,7 @@ simple_stmts_rule(Parser *p) asdl_stmt_seq* a; Token * newline_var; if ( - (a = (asdl_stmt_seq*)_gather_5_rule(p)) // ';'.simple_stmt+ + (a = (asdl_stmt_seq*)_gather_4_rule(p)) // ';'.simple_stmt+ && (_opt_var = _PyPegen_expect_token(p, 13), !p->error_indicator) // ';'? && @@ -1719,8 +1683,7 @@ static stmt_ty simple_stmt_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -1843,7 +1806,7 @@ simple_stmt_rule(Parser *p) D(fprintf(stderr, "%*c> simple_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&('import' | 'from') import_stmt")); stmt_ty import_stmt_var; if ( - _PyPegen_lookahead(1, _tmp_7_rule, p) + _PyPegen_lookahead(1, _tmp_6_rule, p) && (import_stmt_var = import_stmt_rule(p)) // import_stmt ) @@ -1918,7 +1881,7 @@ simple_stmt_rule(Parser *p) D(fprintf(stderr, "%*c> simple_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&'del' del_stmt")); stmt_ty del_stmt_var; if ( - _PyPegen_lookahead_with_int(1, _PyPegen_expect_token, p, 613) // token='del' + _PyPegen_lookahead_with_int(1, _PyPegen_expect_token, p, 616) // token='del' && (del_stmt_var = del_stmt_rule(p)) // del_stmt ) @@ -2089,6 +2052,7 @@ simple_stmt_rule(Parser *p) } // compound_stmt: +// | invalid_compound_stmt // | &('def' | '@' | 'async') function_def // | &'if' if_stmt // | &('class' | '@') class_def @@ -2101,8 +2065,7 @@ static stmt_ty compound_stmt_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -2110,6 +2073,25 @@ compound_stmt_rule(Parser *p) } stmt_ty _res = NULL; int _mark = p->mark; + if (p->call_invalid_rules) { // invalid_compound_stmt + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> compound_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_compound_stmt")); + void *invalid_compound_stmt_var; + if ( + (invalid_compound_stmt_var = invalid_compound_stmt_rule(p)) // invalid_compound_stmt + ) + { + D(fprintf(stderr, "%*c+ compound_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "invalid_compound_stmt")); + _res = invalid_compound_stmt_var; + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s compound_stmt[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "invalid_compound_stmt")); + } { // &('def' | '@' | 'async') function_def if (p->error_indicator) { p->level--; @@ -2118,7 +2100,7 @@ compound_stmt_rule(Parser *p) D(fprintf(stderr, "%*c> compound_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&('def' | '@' | 'async') function_def")); stmt_ty function_def_var; if ( - _PyPegen_lookahead(1, _tmp_8_rule, p) + _PyPegen_lookahead(1, _tmp_7_rule, p) && (function_def_var = function_def_rule(p)) // function_def ) @@ -2139,7 +2121,7 @@ compound_stmt_rule(Parser *p) D(fprintf(stderr, "%*c> compound_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&'if' if_stmt")); stmt_ty if_stmt_var; if ( - _PyPegen_lookahead_with_int(1, _PyPegen_expect_token, p, 656) // token='if' + _PyPegen_lookahead_with_int(1, _PyPegen_expect_token, p, 661) // token='if' && (if_stmt_var = if_stmt_rule(p)) // if_stmt ) @@ -2160,7 +2142,7 @@ compound_stmt_rule(Parser *p) D(fprintf(stderr, "%*c> compound_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&('class' | '@') class_def")); stmt_ty class_def_var; if ( - _PyPegen_lookahead(1, _tmp_9_rule, p) + _PyPegen_lookahead(1, _tmp_8_rule, p) && (class_def_var = class_def_rule(p)) // class_def ) @@ -2181,7 +2163,7 @@ compound_stmt_rule(Parser *p) D(fprintf(stderr, "%*c> compound_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&('with' | 'async') with_stmt")); stmt_ty with_stmt_var; if ( - _PyPegen_lookahead(1, _tmp_10_rule, p) + _PyPegen_lookahead(1, _tmp_9_rule, p) && (with_stmt_var = with_stmt_rule(p)) // with_stmt ) @@ -2202,7 +2184,7 @@ compound_stmt_rule(Parser *p) D(fprintf(stderr, "%*c> compound_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&('for' | 'async') for_stmt")); stmt_ty for_stmt_var; if ( - _PyPegen_lookahead(1, _tmp_11_rule, p) + _PyPegen_lookahead(1, _tmp_10_rule, p) && (for_stmt_var = for_stmt_rule(p)) // for_stmt ) @@ -2223,7 +2205,7 @@ compound_stmt_rule(Parser *p) D(fprintf(stderr, "%*c> compound_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&'try' try_stmt")); stmt_ty try_stmt_var; if ( - _PyPegen_lookahead_with_int(1, _PyPegen_expect_token, p, 638) // token='try' + _PyPegen_lookahead_with_int(1, _PyPegen_expect_token, p, 643) // token='try' && (try_stmt_var = try_stmt_rule(p)) // try_stmt ) @@ -2244,7 +2226,7 @@ compound_stmt_rule(Parser *p) D(fprintf(stderr, "%*c> compound_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&'while' while_stmt")); stmt_ty while_stmt_var; if ( - _PyPegen_lookahead_with_int(1, _PyPegen_expect_token, p, 661) // token='while' + _PyPegen_lookahead_with_int(1, _PyPegen_expect_token, p, 666) // token='while' && (while_stmt_var = while_stmt_rule(p)) // while_stmt ) @@ -2292,8 +2274,7 @@ static stmt_ty assignment_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -2327,7 +2308,7 @@ assignment_rule(Parser *p) && (b = expression_rule(p)) // expression && - (c = _tmp_12_rule(p), !p->error_indicator) // ['=' annotated_rhs] + (c = _tmp_11_rule(p), !p->error_indicator) // ['=' annotated_rhs] ) { D(fprintf(stderr, "%*c+ assignment[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME ':' expression ['=' annotated_rhs]")); @@ -2363,13 +2344,13 @@ assignment_rule(Parser *p) expr_ty b; void *c; if ( - (a = _tmp_13_rule(p)) // '(' single_target ')' | single_subscript_attribute_target + (a = _tmp_12_rule(p)) // '(' single_target ')' | single_subscript_attribute_target && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && (b = expression_rule(p)) // expression && - (c = _tmp_14_rule(p), !p->error_indicator) // ['=' annotated_rhs] + (c = _tmp_13_rule(p), !p->error_indicator) // ['=' annotated_rhs] ) { D(fprintf(stderr, "%*c+ assignment[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "('(' single_target ')' | single_subscript_attribute_target) ':' expression ['=' annotated_rhs]")); @@ -2404,9 +2385,9 @@ assignment_rule(Parser *p) void *b; void *tc; if ( - (a = (asdl_expr_seq*)_loop1_15_rule(p)) // ((star_targets '='))+ + (a = (asdl_expr_seq*)_loop1_14_rule(p)) // ((star_targets '='))+ && - (b = _tmp_16_rule(p)) // yield_expr | star_expressions + (b = _tmp_15_rule(p)) // yield_expr | star_expressions && _PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, 22) // token='=' && @@ -2452,7 +2433,7 @@ assignment_rule(Parser *p) && (_cut_var = 1) && - (c = _tmp_17_rule(p)) // yield_expr | star_expressions + (c = _tmp_16_rule(p)) // yield_expr | star_expressions ) { D(fprintf(stderr, "%*c+ assignment[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "single_target augassign ~ (yield_expr | star_expressions)")); @@ -2511,8 +2492,7 @@ static expr_ty annotated_rhs_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -2582,8 +2562,7 @@ static AugOperator* augassign_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -2914,8 +2893,7 @@ static stmt_ty return_stmt_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -2979,8 +2957,7 @@ static stmt_ty raise_stmt_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -3011,7 +2988,7 @@ raise_stmt_rule(Parser *p) && (a = expression_rule(p)) // expression && - (b = _tmp_18_rule(p), !p->error_indicator) // ['from' expression] + (b = _tmp_17_rule(p), !p->error_indicator) // ['from' expression] ) { D(fprintf(stderr, "%*c+ raise_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'raise' expression ['from' expression]")); @@ -3080,8 +3057,7 @@ static stmt_ty global_stmt_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -3109,7 +3085,7 @@ global_stmt_rule(Parser *p) if ( (_keyword = _PyPegen_expect_token(p, 526)) // token='global' && - (a = (asdl_expr_seq*)_gather_19_rule(p)) // ','.NAME+ + (a = (asdl_expr_seq*)_gather_18_rule(p)) // ','.NAME+ ) { D(fprintf(stderr, "%*c+ global_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'global' ','.NAME+")); @@ -3145,8 +3121,7 @@ static stmt_ty nonlocal_stmt_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -3174,7 +3149,7 @@ nonlocal_stmt_rule(Parser *p) if ( (_keyword = _PyPegen_expect_token(p, 527)) // token='nonlocal' && - (a = (asdl_expr_seq*)_gather_21_rule(p)) // ','.NAME+ + (a = (asdl_expr_seq*)_gather_20_rule(p)) // ','.NAME+ ) { D(fprintf(stderr, "%*c+ nonlocal_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'nonlocal' ','.NAME+")); @@ -3210,8 +3185,7 @@ static stmt_ty del_stmt_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -3237,11 +3211,11 @@ del_stmt_rule(Parser *p) Token * _keyword; asdl_expr_seq* a; if ( - (_keyword = _PyPegen_expect_token(p, 613)) // token='del' + (_keyword = _PyPegen_expect_token(p, 616)) // token='del' && (a = del_targets_rule(p)) // del_targets && - _PyPegen_lookahead(1, _tmp_23_rule, p) + _PyPegen_lookahead(1, _tmp_22_rule, p) ) { D(fprintf(stderr, "%*c+ del_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'del' del_targets &(';' | NEWLINE)")); @@ -3296,8 +3270,7 @@ static stmt_ty yield_stmt_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -3358,8 +3331,7 @@ static stmt_ty assert_stmt_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -3390,7 +3362,7 @@ assert_stmt_rule(Parser *p) && (a = expression_rule(p)) // expression && - (b = _tmp_24_rule(p), !p->error_indicator) // [',' expression] + (b = _tmp_23_rule(p), !p->error_indicator) // [',' expression] ) { D(fprintf(stderr, "%*c+ assert_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'assert' expression [',' expression]")); @@ -3426,8 +3398,7 @@ static stmt_ty import_stmt_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -3503,8 +3474,7 @@ static stmt_ty import_name_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -3530,7 +3500,7 @@ import_name_rule(Parser *p) Token * _keyword; asdl_alias_seq* a; if ( - (_keyword = _PyPegen_expect_token(p, 617)) // token='import' + (_keyword = _PyPegen_expect_token(p, 620)) // token='import' && (a = dotted_as_names_rule(p)) // dotted_as_names ) @@ -3570,8 +3540,7 @@ static stmt_ty import_from_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -3600,13 +3569,13 @@ import_from_rule(Parser *p) expr_ty b; asdl_alias_seq* c; if ( - (_keyword = _PyPegen_expect_token(p, 618)) // token='from' + (_keyword = _PyPegen_expect_token(p, 621)) // token='from' && - (a = _loop0_25_rule(p)) // (('.' | '...'))* + (a = _loop0_24_rule(p)) // (('.' | '...'))* && (b = dotted_name_rule(p)) // dotted_name && - (_keyword_1 = _PyPegen_expect_token(p, 617)) // token='import' + (_keyword_1 = _PyPegen_expect_token(p, 620)) // token='import' && (c = import_from_targets_rule(p)) // import_from_targets ) @@ -3644,11 +3613,11 @@ import_from_rule(Parser *p) asdl_seq * a; asdl_alias_seq* b; if ( - (_keyword = _PyPegen_expect_token(p, 618)) // token='from' + (_keyword = _PyPegen_expect_token(p, 621)) // token='from' && - (a = _loop1_26_rule(p)) // (('.' | '...'))+ + (a = _loop1_25_rule(p)) // (('.' | '...'))+ && - (_keyword_1 = _PyPegen_expect_token(p, 617)) // token='import' + (_keyword_1 = _PyPegen_expect_token(p, 620)) // token='import' && (b = import_from_targets_rule(p)) // import_from_targets ) @@ -3690,8 +3659,7 @@ static asdl_alias_seq* import_from_targets_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -3826,8 +3794,7 @@ static asdl_alias_seq* import_from_as_names_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -3843,7 +3810,7 @@ import_from_as_names_rule(Parser *p) D(fprintf(stderr, "%*c> import_from_as_names[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.import_from_as_name+")); asdl_alias_seq* a; if ( - (a = (asdl_alias_seq*)_gather_27_rule(p)) // ','.import_from_as_name+ + (a = (asdl_alias_seq*)_gather_26_rule(p)) // ','.import_from_as_name+ ) { D(fprintf(stderr, "%*c+ import_from_as_names[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.import_from_as_name+")); @@ -3870,8 +3837,7 @@ static alias_ty import_from_as_name_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -3899,7 +3865,7 @@ import_from_as_name_rule(Parser *p) if ( (a = _PyPegen_name_token(p)) // NAME && - (b = _tmp_29_rule(p), !p->error_indicator) // ['as' NAME] + (b = _tmp_28_rule(p), !p->error_indicator) // ['as' NAME] ) { D(fprintf(stderr, "%*c+ import_from_as_name[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME ['as' NAME]")); @@ -3935,8 +3901,7 @@ static asdl_alias_seq* dotted_as_names_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -3952,7 +3917,7 @@ dotted_as_names_rule(Parser *p) D(fprintf(stderr, "%*c> dotted_as_names[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.dotted_as_name+")); asdl_alias_seq* a; if ( - (a = (asdl_alias_seq*)_gather_30_rule(p)) // ','.dotted_as_name+ + (a = (asdl_alias_seq*)_gather_29_rule(p)) // ','.dotted_as_name+ ) { D(fprintf(stderr, "%*c+ dotted_as_names[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.dotted_as_name+")); @@ -3979,8 +3944,7 @@ static alias_ty dotted_as_name_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -4008,7 +3972,7 @@ dotted_as_name_rule(Parser *p) if ( (a = dotted_name_rule(p)) // dotted_name && - (b = _tmp_32_rule(p), !p->error_indicator) // ['as' NAME] + (b = _tmp_31_rule(p), !p->error_indicator) // ['as' NAME] ) { D(fprintf(stderr, "%*c+ dotted_as_name[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "dotted_name ['as' NAME]")); @@ -4046,8 +4010,7 @@ static expr_ty dotted_name_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, dotted_name_type, &_res)) { @@ -4081,8 +4044,7 @@ static expr_ty dotted_name_raw(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -4150,8 +4112,7 @@ static asdl_stmt_seq* block_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -4246,8 +4207,7 @@ static asdl_expr_seq* decorators_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -4263,7 +4223,7 @@ decorators_rule(Parser *p) D(fprintf(stderr, "%*c> decorators[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(('@' named_expression NEWLINE))+")); asdl_expr_seq* a; if ( - (a = (asdl_expr_seq*)_loop1_33_rule(p)) // (('@' named_expression NEWLINE))+ + (a = (asdl_expr_seq*)_loop1_32_rule(p)) // (('@' named_expression NEWLINE))+ ) { D(fprintf(stderr, "%*c+ decorators[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(('@' named_expression NEWLINE))+")); @@ -4290,8 +4250,7 @@ static stmt_ty class_def_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -4358,8 +4317,7 @@ static stmt_ty class_def_raw_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -4408,13 +4366,13 @@ class_def_raw_rule(Parser *p) asdl_stmt_seq* c; void *t; if ( - (_keyword = _PyPegen_expect_token(p, 671)) // token='class' + (_keyword = _PyPegen_expect_token(p, 676)) // token='class' && (a = _PyPegen_name_token(p)) // NAME && (t = type_params_rule(p), !p->error_indicator) // type_params? && - (b = _tmp_34_rule(p), !p->error_indicator) // ['(' arguments? ')'] + (b = _tmp_33_rule(p), !p->error_indicator) // ['(' arguments? ')'] && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && @@ -4454,8 +4412,7 @@ static stmt_ty function_def_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -4523,8 +4480,7 @@ static stmt_ty function_def_raw_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -4577,7 +4533,7 @@ function_def_raw_rule(Parser *p) void *t; void *tc; if ( - (_keyword = _PyPegen_expect_token(p, 669)) // token='def' + (_keyword = _PyPegen_expect_token(p, 674)) // token='def' && (n = _PyPegen_name_token(p)) // NAME && @@ -4589,7 +4545,7 @@ function_def_raw_rule(Parser *p) && (_literal_1 = _PyPegen_expect_token(p, 8)) // token=')' && - (a = _tmp_35_rule(p), !p->error_indicator) // ['->' expression] + (a = _tmp_34_rule(p), !p->error_indicator) // ['->' expression] && (_literal_2 = _PyPegen_expect_forced_token(p, 11, ":")) // forced_token=':' && @@ -4638,9 +4594,9 @@ function_def_raw_rule(Parser *p) void *t; void *tc; if ( - (_keyword = _PyPegen_expect_token(p, 668)) // token='async' + (_keyword = _PyPegen_expect_token(p, 673)) // token='async' && - (_keyword_1 = _PyPegen_expect_token(p, 669)) // token='def' + (_keyword_1 = _PyPegen_expect_token(p, 674)) // token='def' && (n = _PyPegen_name_token(p)) // NAME && @@ -4652,7 +4608,7 @@ function_def_raw_rule(Parser *p) && (_literal_1 = _PyPegen_expect_token(p, 8)) // token=')' && - (a = _tmp_36_rule(p), !p->error_indicator) // ['->' expression] + (a = _tmp_35_rule(p), !p->error_indicator) // ['->' expression] && (_literal_2 = _PyPegen_expect_forced_token(p, 11, ":")) // forced_token=':' && @@ -4694,8 +4650,7 @@ static arguments_ty params_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -4757,8 +4712,7 @@ static arguments_ty parameters_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -4779,9 +4733,9 @@ parameters_rule(Parser *p) if ( (a = slash_no_default_rule(p)) // slash_no_default && - (b = (asdl_arg_seq*)_loop0_37_rule(p)) // param_no_default* + (b = (asdl_arg_seq*)_loop0_36_rule(p)) // param_no_default* && - (c = _loop0_38_rule(p)) // param_with_default* + (c = _loop0_37_rule(p)) // param_with_default* && (d = star_etc_rule(p), !p->error_indicator) // star_etc? ) @@ -4811,7 +4765,7 @@ parameters_rule(Parser *p) if ( (a = slash_with_default_rule(p)) // slash_with_default && - (b = _loop0_39_rule(p)) // param_with_default* + (b = _loop0_38_rule(p)) // param_with_default* && (c = star_etc_rule(p), !p->error_indicator) // star_etc? ) @@ -4839,9 +4793,9 @@ parameters_rule(Parser *p) asdl_seq * b; void *c; if ( - (a = (asdl_arg_seq*)_loop1_40_rule(p)) // param_no_default+ + (a = (asdl_arg_seq*)_loop1_39_rule(p)) // param_no_default+ && - (b = _loop0_41_rule(p)) // param_with_default* + (b = _loop0_40_rule(p)) // param_with_default* && (c = star_etc_rule(p), !p->error_indicator) // star_etc? ) @@ -4868,7 +4822,7 @@ parameters_rule(Parser *p) asdl_seq * a; void *b; if ( - (a = _loop1_42_rule(p)) // param_with_default+ + (a = _loop1_41_rule(p)) // param_with_default+ && (b = star_etc_rule(p), !p->error_indicator) // star_etc? ) @@ -4921,8 +4875,7 @@ static asdl_arg_seq* slash_no_default_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -4940,7 +4893,7 @@ slash_no_default_rule(Parser *p) Token * _literal_1; asdl_arg_seq* a; if ( - (a = (asdl_arg_seq*)_loop1_43_rule(p)) // param_no_default+ + (a = (asdl_arg_seq*)_loop1_42_rule(p)) // param_no_default+ && (_literal = _PyPegen_expect_token(p, 17)) // token='/' && @@ -4969,7 +4922,7 @@ slash_no_default_rule(Parser *p) Token * _literal; asdl_arg_seq* a; if ( - (a = (asdl_arg_seq*)_loop1_44_rule(p)) // param_no_default+ + (a = (asdl_arg_seq*)_loop1_43_rule(p)) // param_no_default+ && (_literal = _PyPegen_expect_token(p, 17)) // token='/' && @@ -5002,8 +4955,7 @@ static SlashWithDefault* slash_with_default_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -5022,9 +4974,9 @@ slash_with_default_rule(Parser *p) asdl_seq * a; asdl_seq * b; if ( - (a = _loop0_45_rule(p)) // param_no_default* + (a = _loop0_44_rule(p)) // param_no_default* && - (b = _loop1_46_rule(p)) // param_with_default+ + (b = _loop1_45_rule(p)) // param_with_default+ && (_literal = _PyPegen_expect_token(p, 17)) // token='/' && @@ -5054,9 +5006,9 @@ slash_with_default_rule(Parser *p) asdl_seq * a; asdl_seq * b; if ( - (a = _loop0_47_rule(p)) // param_no_default* + (a = _loop0_46_rule(p)) // param_no_default* && - (b = _loop1_48_rule(p)) // param_with_default+ + (b = _loop1_47_rule(p)) // param_with_default+ && (_literal = _PyPegen_expect_token(p, 17)) // token='/' && @@ -5092,8 +5044,7 @@ static StarEtc* star_etc_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -5135,7 +5086,7 @@ star_etc_rule(Parser *p) && (a = param_no_default_rule(p)) // param_no_default && - (b = _loop0_49_rule(p)) // param_maybe_default* + (b = _loop0_48_rule(p)) // param_maybe_default* && (c = kwds_rule(p), !p->error_indicator) // kwds? ) @@ -5168,7 +5119,7 @@ star_etc_rule(Parser *p) && (a = param_no_default_star_annotation_rule(p)) // param_no_default_star_annotation && - (b = _loop0_50_rule(p)) // param_maybe_default* + (b = _loop0_49_rule(p)) // param_maybe_default* && (c = kwds_rule(p), !p->error_indicator) // kwds? ) @@ -5201,7 +5152,7 @@ star_etc_rule(Parser *p) && (_literal_1 = _PyPegen_expect_token(p, 12)) // token=',' && - (b = _loop1_51_rule(p)) // param_maybe_default+ + (b = _loop1_50_rule(p)) // param_maybe_default+ && (c = kwds_rule(p), !p->error_indicator) // kwds? ) @@ -5254,8 +5205,7 @@ static arg_ty kwds_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -5320,8 +5270,7 @@ static arg_ty param_no_default_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -5401,8 +5350,7 @@ static arg_ty param_no_default_star_annotation_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -5480,8 +5428,7 @@ static NameDefaultPair* param_with_default_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -5567,8 +5514,7 @@ static NameDefaultPair* param_maybe_default_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -5652,8 +5598,7 @@ static arg_ty param_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -5717,8 +5662,7 @@ static arg_ty param_star_annotation_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -5782,8 +5726,7 @@ static expr_ty annotation_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -5829,8 +5772,7 @@ static expr_ty star_annotation_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -5876,8 +5818,7 @@ static expr_ty default_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -5945,8 +5886,7 @@ static stmt_ty if_stmt_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -5994,7 +5934,7 @@ if_stmt_rule(Parser *p) asdl_stmt_seq* b; stmt_ty c; if ( - (_keyword = _PyPegen_expect_token(p, 656)) // token='if' + (_keyword = _PyPegen_expect_token(p, 661)) // token='if' && (a = named_expression_rule(p)) // named_expression && @@ -6039,7 +5979,7 @@ if_stmt_rule(Parser *p) asdl_stmt_seq* b; void *c; if ( - (_keyword = _PyPegen_expect_token(p, 656)) // token='if' + (_keyword = _PyPegen_expect_token(p, 661)) // token='if' && (a = named_expression_rule(p)) // named_expression && @@ -6086,8 +6026,7 @@ static stmt_ty elif_stmt_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -6135,7 +6074,7 @@ elif_stmt_rule(Parser *p) asdl_stmt_seq* b; stmt_ty c; if ( - (_keyword = _PyPegen_expect_token(p, 658)) // token='elif' + (_keyword = _PyPegen_expect_token(p, 663)) // token='elif' && (a = named_expression_rule(p)) // named_expression && @@ -6180,7 +6119,7 @@ elif_stmt_rule(Parser *p) asdl_stmt_seq* b; void *c; if ( - (_keyword = _PyPegen_expect_token(p, 658)) // token='elif' + (_keyword = _PyPegen_expect_token(p, 663)) // token='elif' && (a = named_expression_rule(p)) // named_expression && @@ -6224,8 +6163,7 @@ static asdl_stmt_seq* else_block_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -6262,7 +6200,7 @@ else_block_rule(Parser *p) Token * _literal; asdl_stmt_seq* b; if ( - (_keyword = _PyPegen_expect_token(p, 659)) // token='else' + (_keyword = _PyPegen_expect_token(p, 664)) // token='else' && (_literal = _PyPegen_expect_forced_token(p, 11, ":")) // forced_token=':' && @@ -6293,8 +6231,7 @@ static stmt_ty while_stmt_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -6342,7 +6279,7 @@ while_stmt_rule(Parser *p) asdl_stmt_seq* b; void *c; if ( - (_keyword = _PyPegen_expect_token(p, 661)) // token='while' + (_keyword = _PyPegen_expect_token(p, 666)) // token='while' && (a = named_expression_rule(p)) // named_expression && @@ -6390,8 +6327,7 @@ static stmt_ty for_stmt_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -6443,11 +6379,11 @@ for_stmt_rule(Parser *p) expr_ty t; void *tc; if ( - (_keyword = _PyPegen_expect_token(p, 666)) // token='for' + (_keyword = _PyPegen_expect_token(p, 671)) // token='for' && (t = star_targets_rule(p)) // star_targets && - (_keyword_1 = _PyPegen_expect_token(p, 667)) // token='in' + (_keyword_1 = _PyPegen_expect_token(p, 672)) // token='in' && (_cut_var = 1) && @@ -6505,13 +6441,13 @@ for_stmt_rule(Parser *p) expr_ty t; void *tc; if ( - (_keyword = _PyPegen_expect_token(p, 668)) // token='async' + (_keyword = _PyPegen_expect_token(p, 673)) // token='async' && - (_keyword_1 = _PyPegen_expect_token(p, 666)) // token='for' + (_keyword_1 = _PyPegen_expect_token(p, 671)) // token='for' && (t = star_targets_rule(p)) // star_targets && - (_keyword_2 = _PyPegen_expect_token(p, 667)) // token='in' + (_keyword_2 = _PyPegen_expect_token(p, 672)) // token='in' && (_cut_var = 1) && @@ -6579,7 +6515,7 @@ for_stmt_rule(Parser *p) // with_stmt: // | invalid_with_stmt_indent -// | 'with' '(' ','.with_item+ ','? ')' ':' block +// | 'with' '(' ','.with_item+ ','? ')' ':' TYPE_COMMENT? block // | 'with' ','.with_item+ ':' TYPE_COMMENT? block // | 'async' 'with' '(' ','.with_item+ ','? ')' ':' block // | 'async' 'with' ','.with_item+ ':' TYPE_COMMENT? block @@ -6588,8 +6524,7 @@ static stmt_ty with_stmt_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -6625,12 +6560,12 @@ with_stmt_rule(Parser *p) D(fprintf(stderr, "%*c%s with_stmt[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "invalid_with_stmt_indent")); } - { // 'with' '(' ','.with_item+ ','? ')' ':' block + { // 'with' '(' ','.with_item+ ','? ')' ':' TYPE_COMMENT? block if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> with_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'with' '(' ','.with_item+ ','? ')' ':' block")); + D(fprintf(stderr, "%*c> with_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'with' '(' ','.with_item+ ','? ')' ':' TYPE_COMMENT? block")); Token * _keyword; Token * _literal; Token * _literal_1; @@ -6639,12 +6574,13 @@ with_stmt_rule(Parser *p) UNUSED(_opt_var); // Silence compiler warnings asdl_withitem_seq* a; asdl_stmt_seq* b; + void *tc; if ( - (_keyword = _PyPegen_expect_token(p, 629)) // token='with' + (_keyword = _PyPegen_expect_token(p, 634)) // token='with' && (_literal = _PyPegen_expect_token(p, 7)) // token='(' && - (a = (asdl_withitem_seq*)_gather_52_rule(p)) // ','.with_item+ + (a = (asdl_withitem_seq*)_gather_51_rule(p)) // ','.with_item+ && (_opt_var = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? && @@ -6652,10 +6588,12 @@ with_stmt_rule(Parser *p) && (_literal_2 = _PyPegen_expect_token(p, 11)) // token=':' && + (tc = _PyPegen_expect_token(p, TYPE_COMMENT), !p->error_indicator) // TYPE_COMMENT? + && (b = block_rule(p)) // block ) { - D(fprintf(stderr, "%*c+ with_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'with' '(' ','.with_item+ ','? ')' ':' block")); + D(fprintf(stderr, "%*c+ with_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'with' '(' ','.with_item+ ','? ')' ':' TYPE_COMMENT? block")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { p->level--; @@ -6665,7 +6603,7 @@ with_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 = CHECK_VERSION ( stmt_ty , 9 , "Parenthesized context managers are" , _PyAST_With ( a , b , NULL , EXTRA ) ); + _res = CHECK_VERSION ( stmt_ty , 9 , "Parenthesized context managers are" , _PyAST_With ( a , b , NEW_TYPE_COMMENT ( p , tc ) , EXTRA ) ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; p->level--; @@ -6675,7 +6613,7 @@ with_stmt_rule(Parser *p) } p->mark = _mark; D(fprintf(stderr, "%*c%s with_stmt[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'with' '(' ','.with_item+ ','? ')' ':' block")); + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'with' '(' ','.with_item+ ','? ')' ':' TYPE_COMMENT? block")); } { // 'with' ','.with_item+ ':' TYPE_COMMENT? block if (p->error_indicator) { @@ -6689,9 +6627,9 @@ with_stmt_rule(Parser *p) asdl_stmt_seq* b; void *tc; if ( - (_keyword = _PyPegen_expect_token(p, 629)) // token='with' + (_keyword = _PyPegen_expect_token(p, 634)) // token='with' && - (a = (asdl_withitem_seq*)_gather_54_rule(p)) // ','.with_item+ + (a = (asdl_withitem_seq*)_gather_53_rule(p)) // ','.with_item+ && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && @@ -6738,13 +6676,13 @@ with_stmt_rule(Parser *p) asdl_withitem_seq* a; asdl_stmt_seq* b; if ( - (_keyword = _PyPegen_expect_token(p, 668)) // token='async' + (_keyword = _PyPegen_expect_token(p, 673)) // token='async' && - (_keyword_1 = _PyPegen_expect_token(p, 629)) // token='with' + (_keyword_1 = _PyPegen_expect_token(p, 634)) // token='with' && (_literal = _PyPegen_expect_token(p, 7)) // token='(' && - (a = (asdl_withitem_seq*)_gather_56_rule(p)) // ','.with_item+ + (a = (asdl_withitem_seq*)_gather_55_rule(p)) // ','.with_item+ && (_opt_var = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? && @@ -6790,11 +6728,11 @@ with_stmt_rule(Parser *p) asdl_stmt_seq* b; void *tc; if ( - (_keyword = _PyPegen_expect_token(p, 668)) // token='async' + (_keyword = _PyPegen_expect_token(p, 673)) // token='async' && - (_keyword_1 = _PyPegen_expect_token(p, 629)) // token='with' + (_keyword_1 = _PyPegen_expect_token(p, 634)) // token='with' && - (a = (asdl_withitem_seq*)_gather_58_rule(p)) // ','.with_item+ + (a = (asdl_withitem_seq*)_gather_57_rule(p)) // ','.with_item+ && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && @@ -6858,8 +6796,7 @@ static withitem_ty with_item_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -6879,11 +6816,11 @@ with_item_rule(Parser *p) if ( (e = expression_rule(p)) // expression && - (_keyword = _PyPegen_expect_token(p, 654)) // token='as' + (_keyword = _PyPegen_expect_token(p, 659)) // token='as' && (t = star_target_rule(p)) // star_target && - _PyPegen_lookahead(1, _tmp_60_rule, p) + _PyPegen_lookahead(1, _tmp_59_rule, p) ) { D(fprintf(stderr, "%*c+ with_item[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression 'as' star_target &(',' | ')' | ':')")); @@ -6957,8 +6894,7 @@ static stmt_ty try_stmt_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -7005,7 +6941,7 @@ try_stmt_rule(Parser *p) asdl_stmt_seq* b; asdl_stmt_seq* f; if ( - (_keyword = _PyPegen_expect_token(p, 638)) // token='try' + (_keyword = _PyPegen_expect_token(p, 643)) // token='try' && (_literal = _PyPegen_expect_forced_token(p, 11, ":")) // forced_token=':' && @@ -7049,13 +6985,13 @@ try_stmt_rule(Parser *p) asdl_excepthandler_seq* ex; void *f; if ( - (_keyword = _PyPegen_expect_token(p, 638)) // token='try' + (_keyword = _PyPegen_expect_token(p, 643)) // token='try' && (_literal = _PyPegen_expect_forced_token(p, 11, ":")) // forced_token=':' && (b = block_rule(p)) // block && - (ex = (asdl_excepthandler_seq*)_loop1_61_rule(p)) // except_block+ + (ex = (asdl_excepthandler_seq*)_loop1_60_rule(p)) // except_block+ && (el = else_block_rule(p), !p->error_indicator) // else_block? && @@ -7097,13 +7033,13 @@ try_stmt_rule(Parser *p) asdl_excepthandler_seq* ex; void *f; if ( - (_keyword = _PyPegen_expect_token(p, 638)) // token='try' + (_keyword = _PyPegen_expect_token(p, 643)) // token='try' && (_literal = _PyPegen_expect_forced_token(p, 11, ":")) // forced_token=':' && (b = block_rule(p)) // block && - (ex = (asdl_excepthandler_seq*)_loop1_62_rule(p)) // except_star_block+ + (ex = (asdl_excepthandler_seq*)_loop1_61_rule(p)) // except_star_block+ && (el = else_block_rule(p), !p->error_indicator) // else_block? && @@ -7147,8 +7083,7 @@ static excepthandler_ty except_block_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -7196,11 +7131,11 @@ except_block_rule(Parser *p) expr_ty e; void *t; if ( - (_keyword = _PyPegen_expect_token(p, 651)) // token='except' + (_keyword = _PyPegen_expect_token(p, 656)) // token='except' && (e = expression_rule(p)) // expression && - (t = _tmp_63_rule(p), !p->error_indicator) // ['as' NAME] + (t = _tmp_62_rule(p), !p->error_indicator) // ['as' NAME] && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && @@ -7239,7 +7174,7 @@ except_block_rule(Parser *p) Token * _literal; asdl_stmt_seq* b; if ( - (_keyword = _PyPegen_expect_token(p, 651)) // token='except' + (_keyword = _PyPegen_expect_token(p, 656)) // token='except' && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && @@ -7301,8 +7236,7 @@ static excepthandler_ty except_star_block_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -7351,13 +7285,13 @@ except_star_block_rule(Parser *p) expr_ty e; void *t; if ( - (_keyword = _PyPegen_expect_token(p, 651)) // token='except' + (_keyword = _PyPegen_expect_token(p, 656)) // token='except' && (_literal = _PyPegen_expect_token(p, 16)) // token='*' && (e = expression_rule(p)) // expression && - (t = _tmp_64_rule(p), !p->error_indicator) // ['as' NAME] + (t = _tmp_63_rule(p), !p->error_indicator) // ['as' NAME] && (_literal_1 = _PyPegen_expect_token(p, 11)) // token=':' && @@ -7416,8 +7350,7 @@ static asdl_stmt_seq* finally_block_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -7454,7 +7387,7 @@ finally_block_rule(Parser *p) Token * _literal; asdl_stmt_seq* a; if ( - (_keyword = _PyPegen_expect_token(p, 647)) // token='finally' + (_keyword = _PyPegen_expect_token(p, 652)) // token='finally' && (_literal = _PyPegen_expect_forced_token(p, 11, ":")) // forced_token=':' && @@ -7487,8 +7420,7 @@ static stmt_ty match_stmt_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -7529,7 +7461,7 @@ match_stmt_rule(Parser *p) && (indent_var = _PyPegen_expect_token(p, INDENT)) // token='INDENT' && - (cases = (asdl_match_case_seq*)_loop1_65_rule(p)) // case_block+ + (cases = (asdl_match_case_seq*)_loop1_64_rule(p)) // case_block+ && (dedent_var = _PyPegen_expect_token(p, DEDENT)) // token='DEDENT' ) @@ -7586,8 +7518,7 @@ static expr_ty subject_expr_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -7673,8 +7604,7 @@ static match_case_ty case_block_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -7748,8 +7678,7 @@ static expr_ty guard_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -7766,7 +7695,7 @@ guard_rule(Parser *p) Token * _keyword; expr_ty guard; if ( - (_keyword = _PyPegen_expect_token(p, 656)) // token='if' + (_keyword = _PyPegen_expect_token(p, 661)) // token='if' && (guard = named_expression_rule(p)) // named_expression ) @@ -7795,8 +7724,7 @@ static pattern_ty patterns_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -7876,8 +7804,7 @@ static pattern_ty pattern_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -7934,8 +7861,7 @@ static pattern_ty as_pattern_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -7964,7 +7890,7 @@ as_pattern_rule(Parser *p) if ( (pattern = or_pattern_rule(p)) // or_pattern && - (_keyword = _PyPegen_expect_token(p, 654)) // token='as' + (_keyword = _PyPegen_expect_token(p, 659)) // token='as' && (target = pattern_capture_target_rule(p)) // pattern_capture_target ) @@ -8021,8 +7947,7 @@ static pattern_ty or_pattern_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -8047,7 +7972,7 @@ or_pattern_rule(Parser *p) D(fprintf(stderr, "%*c> or_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'|'.closed_pattern+")); asdl_pattern_seq* patterns; if ( - (patterns = (asdl_pattern_seq*)_gather_66_rule(p)) // '|'.closed_pattern+ + (patterns = (asdl_pattern_seq*)_gather_65_rule(p)) // '|'.closed_pattern+ ) { D(fprintf(stderr, "%*c+ or_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'|'.closed_pattern+")); @@ -8091,8 +8016,7 @@ static pattern_ty closed_pattern_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -8274,8 +8198,7 @@ static pattern_ty literal_pattern_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -8302,7 +8225,7 @@ literal_pattern_rule(Parser *p) if ( (value = signed_number_rule(p)) // signed_number && - _PyPegen_lookahead(0, _tmp_68_rule, p) + _PyPegen_lookahead(0, _tmp_67_rule, p) ) { D(fprintf(stderr, "%*c+ literal_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "signed_number !('+' | '-')")); @@ -8401,7 +8324,7 @@ literal_pattern_rule(Parser *p) D(fprintf(stderr, "%*c> literal_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'None'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 611)) // token='None' + (_keyword = _PyPegen_expect_token(p, 614)) // token='None' ) { D(fprintf(stderr, "%*c+ literal_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'None'")); @@ -8434,7 +8357,7 @@ literal_pattern_rule(Parser *p) D(fprintf(stderr, "%*c> literal_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'True'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 610)) // token='True' + (_keyword = _PyPegen_expect_token(p, 613)) // token='True' ) { D(fprintf(stderr, "%*c+ literal_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'True'")); @@ -8467,7 +8390,7 @@ literal_pattern_rule(Parser *p) D(fprintf(stderr, "%*c> literal_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'False'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 612)) // token='False' + (_keyword = _PyPegen_expect_token(p, 615)) // token='False' ) { D(fprintf(stderr, "%*c+ literal_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'False'")); @@ -8509,8 +8432,7 @@ static expr_ty literal_expr_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -8537,7 +8459,7 @@ literal_expr_rule(Parser *p) if ( (signed_number_var = signed_number_rule(p)) // signed_number && - _PyPegen_lookahead(0, _tmp_69_rule, p) + _PyPegen_lookahead(0, _tmp_68_rule, p) ) { D(fprintf(stderr, "%*c+ literal_expr[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "signed_number !('+' | '-')")); @@ -8594,7 +8516,7 @@ literal_expr_rule(Parser *p) D(fprintf(stderr, "%*c> literal_expr[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'None'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 611)) // token='None' + (_keyword = _PyPegen_expect_token(p, 614)) // token='None' ) { D(fprintf(stderr, "%*c+ literal_expr[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'None'")); @@ -8627,7 +8549,7 @@ literal_expr_rule(Parser *p) D(fprintf(stderr, "%*c> literal_expr[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'True'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 610)) // token='True' + (_keyword = _PyPegen_expect_token(p, 613)) // token='True' ) { D(fprintf(stderr, "%*c+ literal_expr[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'True'")); @@ -8660,7 +8582,7 @@ literal_expr_rule(Parser *p) D(fprintf(stderr, "%*c> literal_expr[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'False'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 612)) // token='False' + (_keyword = _PyPegen_expect_token(p, 615)) // token='False' ) { D(fprintf(stderr, "%*c+ literal_expr[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'False'")); @@ -8698,8 +8620,7 @@ static expr_ty complex_number_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -8805,8 +8726,7 @@ static expr_ty signed_number_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -8889,8 +8809,7 @@ static expr_ty signed_real_number_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -8973,8 +8892,7 @@ static expr_ty real_number_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -9017,8 +8935,7 @@ static expr_ty imaginary_number_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -9061,8 +8978,7 @@ static pattern_ty capture_pattern_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -9123,8 +9039,7 @@ static expr_ty pattern_capture_target_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -9144,7 +9059,7 @@ pattern_capture_target_rule(Parser *p) && (name = _PyPegen_name_token(p)) // NAME && - _PyPegen_lookahead(0, _tmp_70_rule, p) + _PyPegen_lookahead(0, _tmp_69_rule, p) ) { D(fprintf(stderr, "%*c+ pattern_capture_target[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "!\"_\" NAME !('.' | '(' | '=')")); @@ -9171,8 +9086,7 @@ static pattern_ty wildcard_pattern_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -9233,8 +9147,7 @@ static pattern_ty value_pattern_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -9261,7 +9174,7 @@ value_pattern_rule(Parser *p) if ( (attr = attr_rule(p)) // attr && - _PyPegen_lookahead(0, _tmp_71_rule, p) + _PyPegen_lookahead(0, _tmp_70_rule, p) ) { D(fprintf(stderr, "%*c+ value_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "attr !('.' | '(' | '=')")); @@ -9299,8 +9212,7 @@ static expr_ty attr_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, attr_type, &_res)) { @@ -9334,8 +9246,7 @@ static expr_ty attr_raw(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -9403,8 +9314,7 @@ static expr_ty name_or_attr_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -9461,8 +9371,7 @@ static pattern_ty group_pattern_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -9511,8 +9420,7 @@ static pattern_ty sequence_pattern_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -9618,8 +9526,7 @@ static asdl_seq* open_sequence_pattern_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -9668,8 +9575,7 @@ static asdl_seq* maybe_sequence_pattern_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -9687,7 +9593,7 @@ maybe_sequence_pattern_rule(Parser *p) UNUSED(_opt_var); // Silence compiler warnings asdl_seq * patterns; if ( - (patterns = _gather_72_rule(p)) // ','.maybe_star_pattern+ + (patterns = _gather_71_rule(p)) // ','.maybe_star_pattern+ && (_opt_var = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? ) @@ -9716,8 +9622,7 @@ static pattern_ty maybe_star_pattern_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -9774,8 +9679,7 @@ static pattern_ty star_pattern_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -9884,8 +9788,7 @@ static pattern_ty mapping_pattern_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -10084,8 +9987,7 @@ static asdl_seq* items_pattern_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -10099,13 +10001,13 @@ items_pattern_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> items_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.key_value_pattern+")); - asdl_seq * _gather_74_var; + asdl_seq * _gather_73_var; if ( - (_gather_74_var = _gather_74_rule(p)) // ','.key_value_pattern+ + (_gather_73_var = _gather_73_rule(p)) // ','.key_value_pattern+ ) { D(fprintf(stderr, "%*c+ items_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.key_value_pattern+")); - _res = _gather_74_var; + _res = _gather_73_var; goto done; } p->mark = _mark; @@ -10123,8 +10025,7 @@ static KeyPatternPair* key_value_pattern_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -10142,7 +10043,7 @@ key_value_pattern_rule(Parser *p) void *key; pattern_ty pattern; if ( - (key = _tmp_76_rule(p)) // literal_expr | attr + (key = _tmp_75_rule(p)) // literal_expr | attr && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && @@ -10173,8 +10074,7 @@ static expr_ty double_star_pattern_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -10225,8 +10125,7 @@ static pattern_ty class_pattern_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -10456,8 +10355,7 @@ static asdl_pattern_seq* positional_patterns_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -10473,7 +10371,7 @@ positional_patterns_rule(Parser *p) D(fprintf(stderr, "%*c> positional_patterns[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.pattern+")); asdl_pattern_seq* args; if ( - (args = (asdl_pattern_seq*)_gather_77_rule(p)) // ','.pattern+ + (args = (asdl_pattern_seq*)_gather_76_rule(p)) // ','.pattern+ ) { D(fprintf(stderr, "%*c+ positional_patterns[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.pattern+")); @@ -10500,8 +10398,7 @@ static asdl_seq* keyword_patterns_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -10515,13 +10412,13 @@ keyword_patterns_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> keyword_patterns[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.keyword_pattern+")); - asdl_seq * _gather_79_var; + asdl_seq * _gather_78_var; if ( - (_gather_79_var = _gather_79_rule(p)) // ','.keyword_pattern+ + (_gather_78_var = _gather_78_rule(p)) // ','.keyword_pattern+ ) { D(fprintf(stderr, "%*c+ keyword_patterns[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.keyword_pattern+")); - _res = _gather_79_var; + _res = _gather_78_var; goto done; } p->mark = _mark; @@ -10539,8 +10436,7 @@ static KeyPatternPair* keyword_pattern_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -10589,8 +10485,7 @@ static stmt_ty type_alias_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -10663,8 +10558,7 @@ static asdl_type_param_seq* type_params_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -10713,8 +10607,7 @@ static asdl_type_param_seq* type_param_seq_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -10732,7 +10625,7 @@ type_param_seq_rule(Parser *p) UNUSED(_opt_var); // Silence compiler warnings asdl_type_param_seq* a; if ( - (a = (asdl_type_param_seq*)_gather_81_rule(p)) // ','.type_param+ + (a = (asdl_type_param_seq*)_gather_80_rule(p)) // ','.type_param+ && (_opt_var = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? ) @@ -10758,16 +10651,15 @@ type_param_seq_rule(Parser *p) // type_param: // | NAME type_param_bound? -// | '*' NAME ":" expression +// | '*' NAME ':' expression // | '*' NAME -// | '**' NAME ":" expression +// | '**' NAME ':' expression // | '**' NAME static type_param_ty type_param_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -10824,12 +10716,12 @@ type_param_rule(Parser *p) D(fprintf(stderr, "%*c%s type_param[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "NAME type_param_bound?")); } - { // '*' NAME ":" expression + { // '*' NAME ':' expression if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> type_param[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' NAME \":\" expression")); + D(fprintf(stderr, "%*c> type_param[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' NAME ':' expression")); Token * _literal; expr_ty a; Token * colon; @@ -10844,7 +10736,7 @@ type_param_rule(Parser *p) (e = expression_rule(p)) // expression ) { - D(fprintf(stderr, "%*c+ type_param[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' NAME \":\" expression")); + D(fprintf(stderr, "%*c+ type_param[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' NAME ':' expression")); _res = RAISE_SYNTAX_ERROR_STARTING_FROM ( colon , e -> kind == Tuple_kind ? "cannot use constraints with TypeVarTuple" : "cannot use bound with TypeVarTuple" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -10855,7 +10747,7 @@ type_param_rule(Parser *p) } p->mark = _mark; D(fprintf(stderr, "%*c%s type_param[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'*' NAME \":\" expression")); + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'*' NAME ':' expression")); } { // '*' NAME if (p->error_indicator) { @@ -10893,12 +10785,12 @@ type_param_rule(Parser *p) D(fprintf(stderr, "%*c%s type_param[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'*' NAME")); } - { // '**' NAME ":" expression + { // '**' NAME ':' expression if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> type_param[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**' NAME \":\" expression")); + D(fprintf(stderr, "%*c> type_param[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**' NAME ':' expression")); Token * _literal; expr_ty a; Token * colon; @@ -10913,7 +10805,7 @@ type_param_rule(Parser *p) (e = expression_rule(p)) // expression ) { - D(fprintf(stderr, "%*c+ type_param[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**' NAME \":\" expression")); + D(fprintf(stderr, "%*c+ type_param[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**' NAME ':' expression")); _res = RAISE_SYNTAX_ERROR_STARTING_FROM ( colon , e -> kind == Tuple_kind ? "cannot use constraints with ParamSpec" : "cannot use bound with ParamSpec" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -10924,7 +10816,7 @@ type_param_rule(Parser *p) } p->mark = _mark; D(fprintf(stderr, "%*c%s type_param[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'**' NAME \":\" expression")); + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'**' NAME ':' expression")); } { // '**' NAME if (p->error_indicator) { @@ -10969,13 +10861,12 @@ type_param_rule(Parser *p) return _res; } -// type_param_bound: ":" expression +// type_param_bound: ':' expression static expr_ty type_param_bound_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -10983,12 +10874,12 @@ type_param_bound_rule(Parser *p) } expr_ty _res = NULL; int _mark = p->mark; - { // ":" expression + { // ':' expression if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> type_param_bound[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "\":\" expression")); + D(fprintf(stderr, "%*c> type_param_bound[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':' expression")); Token * _literal; expr_ty e; if ( @@ -10997,7 +10888,7 @@ type_param_bound_rule(Parser *p) (e = expression_rule(p)) // expression ) { - D(fprintf(stderr, "%*c+ type_param_bound[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "\":\" expression")); + D(fprintf(stderr, "%*c+ type_param_bound[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':' expression")); _res = e; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -11008,7 +10899,7 @@ type_param_bound_rule(Parser *p) } p->mark = _mark; D(fprintf(stderr, "%*c%s type_param_bound[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "\":\" expression")); + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':' expression")); } _res = NULL; done: @@ -11021,8 +10912,7 @@ static expr_ty expressions_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -11052,7 +10942,7 @@ expressions_rule(Parser *p) if ( (a = expression_rule(p)) // expression && - (b = _loop1_83_rule(p)) // ((',' expression))+ + (b = _loop1_82_rule(p)) // ((',' expression))+ && (_opt_var = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? ) @@ -11150,8 +11040,7 @@ static expr_ty expression_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -11224,11 +11113,11 @@ expression_rule(Parser *p) if ( (a = disjunction_rule(p)) // disjunction && - (_keyword = _PyPegen_expect_token(p, 656)) // token='if' + (_keyword = _PyPegen_expect_token(p, 661)) // token='if' && (b = disjunction_rule(p)) // disjunction && - (_keyword_1 = _PyPegen_expect_token(p, 659)) // token='else' + (_keyword_1 = _PyPegen_expect_token(p, 664)) // token='else' && (c = expression_rule(p)) // expression ) @@ -11305,8 +11194,7 @@ static expr_ty yield_expr_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -11335,7 +11223,7 @@ yield_expr_rule(Parser *p) if ( (_keyword = _PyPegen_expect_token(p, 580)) // token='yield' && - (_keyword_1 = _PyPegen_expect_token(p, 618)) // token='from' + (_keyword_1 = _PyPegen_expect_token(p, 621)) // token='from' && (a = expression_rule(p)) // expression ) @@ -11412,8 +11300,7 @@ static expr_ty star_expressions_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -11443,7 +11330,7 @@ star_expressions_rule(Parser *p) if ( (a = star_expression_rule(p)) // star_expression && - (b = _loop1_84_rule(p)) // ((',' star_expression))+ + (b = _loop1_83_rule(p)) // ((',' star_expression))+ && (_opt_var = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? ) @@ -11536,8 +11423,7 @@ static expr_ty star_expression_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -11625,8 +11511,7 @@ static asdl_expr_seq* star_named_expressions_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -11644,7 +11529,7 @@ star_named_expressions_rule(Parser *p) UNUSED(_opt_var); // Silence compiler warnings asdl_expr_seq* a; if ( - (a = (asdl_expr_seq*)_gather_85_rule(p)) // ','.star_named_expression+ + (a = (asdl_expr_seq*)_gather_84_rule(p)) // ','.star_named_expression+ && (_opt_var = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? ) @@ -11673,8 +11558,7 @@ static expr_ty star_named_expression_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -11757,8 +11641,7 @@ static expr_ty assignment_expression_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -11832,8 +11715,7 @@ static expr_ty named_expression_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -11911,8 +11793,7 @@ static expr_ty disjunction_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -11944,7 +11825,7 @@ disjunction_rule(Parser *p) if ( (a = conjunction_rule(p)) // conjunction && - (b = _loop1_87_rule(p)) // (('or' conjunction))+ + (b = _loop1_86_rule(p)) // (('or' conjunction))+ ) { D(fprintf(stderr, "%*c+ disjunction[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "conjunction (('or' conjunction))+")); @@ -12000,8 +11881,7 @@ static expr_ty conjunction_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -12033,7 +11913,7 @@ conjunction_rule(Parser *p) if ( (a = inversion_rule(p)) // inversion && - (b = _loop1_88_rule(p)) // (('and' inversion))+ + (b = _loop1_87_rule(p)) // (('and' inversion))+ ) { D(fprintf(stderr, "%*c+ conjunction[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "inversion (('and' inversion))+")); @@ -12089,8 +11969,7 @@ static expr_ty inversion_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -12178,8 +12057,7 @@ static expr_ty comparison_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -12207,7 +12085,7 @@ comparison_rule(Parser *p) if ( (a = bitwise_or_rule(p)) // bitwise_or && - (b = _loop1_89_rule(p)) // compare_op_bitwise_or_pair+ + (b = _loop1_88_rule(p)) // compare_op_bitwise_or_pair+ ) { D(fprintf(stderr, "%*c+ comparison[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "bitwise_or compare_op_bitwise_or_pair+")); @@ -12272,8 +12150,7 @@ static CmpopExprPair* compare_op_bitwise_or_pair_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -12482,8 +12359,7 @@ static CmpopExprPair* eq_bitwise_or_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -12529,8 +12405,7 @@ static CmpopExprPair* noteq_bitwise_or_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -12544,10 +12419,10 @@ noteq_bitwise_or_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> noteq_bitwise_or[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('!=') bitwise_or")); - void *_tmp_90_var; + void *_tmp_89_var; expr_ty a; if ( - (_tmp_90_var = _tmp_90_rule(p)) // '!=' + (_tmp_89_var = _tmp_89_rule(p)) // '!=' && (a = bitwise_or_rule(p)) // bitwise_or ) @@ -12576,8 +12451,7 @@ static CmpopExprPair* lte_bitwise_or_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -12623,8 +12497,7 @@ static CmpopExprPair* lt_bitwise_or_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -12670,8 +12543,7 @@ static CmpopExprPair* gte_bitwise_or_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -12717,8 +12589,7 @@ static CmpopExprPair* gt_bitwise_or_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -12764,8 +12635,7 @@ static CmpopExprPair* notin_bitwise_or_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -12785,7 +12655,7 @@ notin_bitwise_or_rule(Parser *p) if ( (_keyword = _PyPegen_expect_token(p, 588)) // token='not' && - (_keyword_1 = _PyPegen_expect_token(p, 667)) // token='in' + (_keyword_1 = _PyPegen_expect_token(p, 672)) // token='in' && (a = bitwise_or_rule(p)) // bitwise_or ) @@ -12814,8 +12684,7 @@ static CmpopExprPair* in_bitwise_or_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -12832,7 +12701,7 @@ in_bitwise_or_rule(Parser *p) Token * _keyword; expr_ty a; if ( - (_keyword = _PyPegen_expect_token(p, 667)) // token='in' + (_keyword = _PyPegen_expect_token(p, 672)) // token='in' && (a = bitwise_or_rule(p)) // bitwise_or ) @@ -12861,8 +12730,7 @@ static CmpopExprPair* isnot_bitwise_or_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -12911,8 +12779,7 @@ static CmpopExprPair* is_bitwise_or_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -12960,8 +12827,7 @@ static expr_ty bitwise_or_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, bitwise_or_type, &_res)) { @@ -12995,8 +12861,7 @@ static expr_ty bitwise_or_raw(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -13084,8 +12949,7 @@ static expr_ty bitwise_xor_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, bitwise_xor_type, &_res)) { @@ -13119,8 +12983,7 @@ static expr_ty bitwise_xor_raw(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -13208,8 +13071,7 @@ static expr_ty bitwise_and_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, bitwise_and_type, &_res)) { @@ -13243,8 +13105,7 @@ static expr_ty bitwise_and_raw(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -13332,8 +13193,7 @@ static expr_ty shift_expr_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, shift_expr_type, &_res)) { @@ -13367,8 +13227,7 @@ static expr_ty shift_expr_raw(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -13495,8 +13354,7 @@ static expr_ty sum_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, sum_type, &_res)) { @@ -13530,8 +13388,7 @@ static expr_ty sum_raw(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -13664,8 +13521,7 @@ static expr_ty term_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, term_type, &_res)) { @@ -13699,8 +13555,7 @@ static expr_ty term_raw(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -13942,8 +13797,7 @@ static expr_ty factor_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -14103,8 +13957,7 @@ static expr_ty power_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -14190,8 +14043,7 @@ static expr_ty await_primary_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -14286,8 +14138,7 @@ static expr_ty primary_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, primary_type, &_res)) { @@ -14321,8 +14172,7 @@ static expr_ty primary_raw(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -14528,8 +14378,7 @@ static expr_ty slices_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -14582,7 +14431,7 @@ slices_rule(Parser *p) UNUSED(_opt_var); // Silence compiler warnings asdl_expr_seq* a; if ( - (a = (asdl_expr_seq*)_gather_91_rule(p)) // ','.(slice | starred_expression)+ + (a = (asdl_expr_seq*)_gather_90_rule(p)) // ','.(slice | starred_expression)+ && (_opt_var = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? ) @@ -14620,8 +14469,7 @@ static expr_ty slice_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -14655,7 +14503,7 @@ slice_rule(Parser *p) && (b = expression_rule(p), !p->error_indicator) // expression? && - (c = _tmp_93_rule(p), !p->error_indicator) // [':' expression?] + (c = _tmp_92_rule(p), !p->error_indicator) // [':' expression?] ) { D(fprintf(stderr, "%*c+ slice[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression? ':' expression? [':' expression?]")); @@ -14725,8 +14573,7 @@ static expr_ty atom_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -14770,7 +14617,7 @@ atom_rule(Parser *p) D(fprintf(stderr, "%*c> atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'True'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 610)) // token='True' + (_keyword = _PyPegen_expect_token(p, 613)) // token='True' ) { D(fprintf(stderr, "%*c+ atom[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'True'")); @@ -14803,7 +14650,7 @@ atom_rule(Parser *p) D(fprintf(stderr, "%*c> atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'False'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 612)) // token='False' + (_keyword = _PyPegen_expect_token(p, 615)) // token='False' ) { D(fprintf(stderr, "%*c+ atom[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'False'")); @@ -14836,7 +14683,7 @@ atom_rule(Parser *p) D(fprintf(stderr, "%*c> atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'None'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 611)) // token='None' + (_keyword = _PyPegen_expect_token(p, 614)) // token='None' ) { D(fprintf(stderr, "%*c+ atom[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'None'")); @@ -14869,7 +14716,7 @@ atom_rule(Parser *p) D(fprintf(stderr, "%*c> atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&(STRING | FSTRING_START) strings")); expr_ty strings_var; if ( - _PyPegen_lookahead(1, _tmp_94_rule, p) + _PyPegen_lookahead(1, _tmp_93_rule, p) && (strings_var = strings_rule(p)) // strings ) @@ -14907,15 +14754,15 @@ atom_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&'(' (tuple | group | genexp)")); - void *_tmp_95_var; + void *_tmp_94_var; if ( _PyPegen_lookahead_with_int(1, _PyPegen_expect_token, p, 7) // token='(' && - (_tmp_95_var = _tmp_95_rule(p)) // tuple | group | genexp + (_tmp_94_var = _tmp_94_rule(p)) // tuple | group | genexp ) { D(fprintf(stderr, "%*c+ atom[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "&'(' (tuple | group | genexp)")); - _res = _tmp_95_var; + _res = _tmp_94_var; goto done; } p->mark = _mark; @@ -14928,15 +14775,15 @@ atom_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&'[' (list | listcomp)")); - void *_tmp_96_var; + void *_tmp_95_var; if ( _PyPegen_lookahead_with_int(1, _PyPegen_expect_token, p, 9) // token='[' && - (_tmp_96_var = _tmp_96_rule(p)) // list | listcomp + (_tmp_95_var = _tmp_95_rule(p)) // list | listcomp ) { D(fprintf(stderr, "%*c+ atom[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "&'[' (list | listcomp)")); - _res = _tmp_96_var; + _res = _tmp_95_var; goto done; } p->mark = _mark; @@ -14949,15 +14796,15 @@ atom_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&'{' (dict | set | dictcomp | setcomp)")); - void *_tmp_97_var; + void *_tmp_96_var; if ( _PyPegen_lookahead_with_int(1, _PyPegen_expect_token, p, 25) // token='{' && - (_tmp_97_var = _tmp_97_rule(p)) // dict | set | dictcomp | setcomp + (_tmp_96_var = _tmp_96_rule(p)) // dict | set | dictcomp | setcomp ) { D(fprintf(stderr, "%*c+ atom[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "&'{' (dict | set | dictcomp | setcomp)")); - _res = _tmp_97_var; + _res = _tmp_96_var; goto done; } p->mark = _mark; @@ -15008,8 +14855,7 @@ static expr_ty group_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -15029,7 +14875,7 @@ group_rule(Parser *p) if ( (_literal = _PyPegen_expect_token(p, 7)) // token='(' && - (a = _tmp_98_rule(p)) // yield_expr | named_expression + (a = _tmp_97_rule(p)) // yield_expr | named_expression && (_literal_1 = _PyPegen_expect_token(p, 8)) // token=')' ) @@ -15077,8 +14923,7 @@ static expr_ty lambdef_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -15106,7 +14951,7 @@ lambdef_rule(Parser *p) void *a; expr_ty b; if ( - (_keyword = _PyPegen_expect_token(p, 609)) // token='lambda' + (_keyword = _PyPegen_expect_token(p, 612)) // token='lambda' && (a = lambda_params_rule(p), !p->error_indicator) // lambda_params? && @@ -15148,8 +14993,7 @@ static arguments_ty lambda_params_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -15211,8 +15055,7 @@ static arguments_ty lambda_parameters_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -15233,9 +15076,9 @@ lambda_parameters_rule(Parser *p) if ( (a = lambda_slash_no_default_rule(p)) // lambda_slash_no_default && - (b = (asdl_arg_seq*)_loop0_99_rule(p)) // lambda_param_no_default* + (b = (asdl_arg_seq*)_loop0_98_rule(p)) // lambda_param_no_default* && - (c = _loop0_100_rule(p)) // lambda_param_with_default* + (c = _loop0_99_rule(p)) // lambda_param_with_default* && (d = lambda_star_etc_rule(p), !p->error_indicator) // lambda_star_etc? ) @@ -15265,7 +15108,7 @@ lambda_parameters_rule(Parser *p) if ( (a = lambda_slash_with_default_rule(p)) // lambda_slash_with_default && - (b = _loop0_101_rule(p)) // lambda_param_with_default* + (b = _loop0_100_rule(p)) // lambda_param_with_default* && (c = lambda_star_etc_rule(p), !p->error_indicator) // lambda_star_etc? ) @@ -15293,9 +15136,9 @@ lambda_parameters_rule(Parser *p) asdl_seq * b; void *c; if ( - (a = (asdl_arg_seq*)_loop1_102_rule(p)) // lambda_param_no_default+ + (a = (asdl_arg_seq*)_loop1_101_rule(p)) // lambda_param_no_default+ && - (b = _loop0_103_rule(p)) // lambda_param_with_default* + (b = _loop0_102_rule(p)) // lambda_param_with_default* && (c = lambda_star_etc_rule(p), !p->error_indicator) // lambda_star_etc? ) @@ -15322,7 +15165,7 @@ lambda_parameters_rule(Parser *p) asdl_seq * a; void *b; if ( - (a = _loop1_104_rule(p)) // lambda_param_with_default+ + (a = _loop1_103_rule(p)) // lambda_param_with_default+ && (b = lambda_star_etc_rule(p), !p->error_indicator) // lambda_star_etc? ) @@ -15377,8 +15220,7 @@ static asdl_arg_seq* lambda_slash_no_default_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -15396,7 +15238,7 @@ lambda_slash_no_default_rule(Parser *p) Token * _literal_1; asdl_arg_seq* a; if ( - (a = (asdl_arg_seq*)_loop1_105_rule(p)) // lambda_param_no_default+ + (a = (asdl_arg_seq*)_loop1_104_rule(p)) // lambda_param_no_default+ && (_literal = _PyPegen_expect_token(p, 17)) // token='/' && @@ -15425,7 +15267,7 @@ lambda_slash_no_default_rule(Parser *p) Token * _literal; asdl_arg_seq* a; if ( - (a = (asdl_arg_seq*)_loop1_106_rule(p)) // lambda_param_no_default+ + (a = (asdl_arg_seq*)_loop1_105_rule(p)) // lambda_param_no_default+ && (_literal = _PyPegen_expect_token(p, 17)) // token='/' && @@ -15458,8 +15300,7 @@ static SlashWithDefault* lambda_slash_with_default_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -15478,9 +15319,9 @@ lambda_slash_with_default_rule(Parser *p) asdl_seq * a; asdl_seq * b; if ( - (a = _loop0_107_rule(p)) // lambda_param_no_default* + (a = _loop0_106_rule(p)) // lambda_param_no_default* && - (b = _loop1_108_rule(p)) // lambda_param_with_default+ + (b = _loop1_107_rule(p)) // lambda_param_with_default+ && (_literal = _PyPegen_expect_token(p, 17)) // token='/' && @@ -15510,9 +15351,9 @@ lambda_slash_with_default_rule(Parser *p) asdl_seq * a; asdl_seq * b; if ( - (a = _loop0_109_rule(p)) // lambda_param_no_default* + (a = _loop0_108_rule(p)) // lambda_param_no_default* && - (b = _loop1_110_rule(p)) // lambda_param_with_default+ + (b = _loop1_109_rule(p)) // lambda_param_with_default+ && (_literal = _PyPegen_expect_token(p, 17)) // token='/' && @@ -15547,8 +15388,7 @@ static StarEtc* lambda_star_etc_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -15590,7 +15430,7 @@ lambda_star_etc_rule(Parser *p) && (a = lambda_param_no_default_rule(p)) // lambda_param_no_default && - (b = _loop0_111_rule(p)) // lambda_param_maybe_default* + (b = _loop0_110_rule(p)) // lambda_param_maybe_default* && (c = lambda_kwds_rule(p), !p->error_indicator) // lambda_kwds? ) @@ -15623,7 +15463,7 @@ lambda_star_etc_rule(Parser *p) && (_literal_1 = _PyPegen_expect_token(p, 12)) // token=',' && - (b = _loop1_112_rule(p)) // lambda_param_maybe_default+ + (b = _loop1_111_rule(p)) // lambda_param_maybe_default+ && (c = lambda_kwds_rule(p), !p->error_indicator) // lambda_kwds? ) @@ -15676,8 +15516,7 @@ static arg_ty lambda_kwds_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -15742,8 +15581,7 @@ static arg_ty lambda_param_no_default_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -15815,8 +15653,7 @@ static NameDefaultPair* lambda_param_with_default_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -15894,8 +15731,7 @@ static NameDefaultPair* lambda_param_maybe_default_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -15973,8 +15809,7 @@ static arg_ty lambda_param_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -16035,8 +15870,7 @@ static expr_ty fstring_middle_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -16094,14 +15928,13 @@ fstring_middle_rule(Parser *p) } // fstring_replacement_field: -// | '{' (yield_expr | star_expressions) "="? fstring_conversion? fstring_full_format_spec? '}' +// | '{' (yield_expr | star_expressions) '='? fstring_conversion? fstring_full_format_spec? '}' // | invalid_replacement_field static expr_ty fstring_replacement_field_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -16118,12 +15951,12 @@ fstring_replacement_field_rule(Parser *p) UNUSED(_start_lineno); // Only used by EXTRA macro int _start_col_offset = p->tokens[_mark]->col_offset; UNUSED(_start_col_offset); // Only used by EXTRA macro - { // '{' (yield_expr | star_expressions) "="? fstring_conversion? fstring_full_format_spec? '}' + { // '{' (yield_expr | star_expressions) '='? fstring_conversion? fstring_full_format_spec? '}' if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> fstring_replacement_field[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{' (yield_expr | star_expressions) \"=\"? fstring_conversion? fstring_full_format_spec? '}'")); + D(fprintf(stderr, "%*c> fstring_replacement_field[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{' (yield_expr | star_expressions) '='? fstring_conversion? fstring_full_format_spec? '}'")); Token * _literal; void *a; void *conversion; @@ -16133,9 +15966,9 @@ fstring_replacement_field_rule(Parser *p) if ( (_literal = _PyPegen_expect_token(p, 25)) // token='{' && - (a = _tmp_113_rule(p)) // yield_expr | star_expressions + (a = _tmp_112_rule(p)) // yield_expr | star_expressions && - (debug_expr = _PyPegen_expect_token(p, 22), !p->error_indicator) // "="? + (debug_expr = _PyPegen_expect_token(p, 22), !p->error_indicator) // '='? && (conversion = fstring_conversion_rule(p), !p->error_indicator) // fstring_conversion? && @@ -16144,7 +15977,7 @@ fstring_replacement_field_rule(Parser *p) (rbrace = _PyPegen_expect_token(p, 26)) // token='}' ) { - D(fprintf(stderr, "%*c+ fstring_replacement_field[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' (yield_expr | star_expressions) \"=\"? fstring_conversion? fstring_full_format_spec? '}'")); + D(fprintf(stderr, "%*c+ fstring_replacement_field[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' (yield_expr | star_expressions) '='? fstring_conversion? fstring_full_format_spec? '}'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { p->level--; @@ -16164,7 +15997,7 @@ fstring_replacement_field_rule(Parser *p) } p->mark = _mark; D(fprintf(stderr, "%*c%s fstring_replacement_field[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'{' (yield_expr | star_expressions) \"=\"? fstring_conversion? fstring_full_format_spec? '}'")); + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'{' (yield_expr | star_expressions) '='? fstring_conversion? fstring_full_format_spec? '}'")); } if (p->call_invalid_rules) { // invalid_replacement_field if (p->error_indicator) { @@ -16196,8 +16029,7 @@ static ResultTokenWithMetadata* fstring_conversion_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -16243,8 +16075,7 @@ static ResultTokenWithMetadata* fstring_full_format_spec_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -16272,7 +16103,7 @@ fstring_full_format_spec_rule(Parser *p) if ( (colon = _PyPegen_expect_token(p, 11)) // token=':' && - (spec = _loop0_114_rule(p)) // fstring_format_spec* + (spec = _loop0_113_rule(p)) // fstring_format_spec* ) { D(fprintf(stderr, "%*c+ fstring_full_format_spec[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':' fstring_format_spec*")); @@ -16308,8 +16139,7 @@ static expr_ty fstring_format_spec_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -16366,13 +16196,61 @@ fstring_format_spec_rule(Parser *p) return _res; } +// fstring: FSTRING_START fstring_middle* FSTRING_END +static expr_ty +fstring_rule(Parser *p) +{ + if (p->level++ == MAXSTACK) { + _Pypegen_stack_overflow(p); + } + if (p->error_indicator) { + p->level--; + return NULL; + } + expr_ty _res = NULL; + int _mark = p->mark; + { // FSTRING_START fstring_middle* FSTRING_END + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> fstring[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "FSTRING_START fstring_middle* FSTRING_END")); + Token * a; + asdl_seq * b; + Token * c; + if ( + (a = _PyPegen_expect_token(p, FSTRING_START)) // token='FSTRING_START' + && + (b = _loop0_114_rule(p)) // fstring_middle* + && + (c = _PyPegen_expect_token(p, FSTRING_END)) // token='FSTRING_END' + ) + { + D(fprintf(stderr, "%*c+ fstring[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "FSTRING_START fstring_middle* FSTRING_END")); + _res = _PyPegen_joined_str ( p , a , ( asdl_expr_seq* ) b , c ); + if (_res == NULL && PyErr_Occurred()) { + p->error_indicator = 1; + p->level--; + return NULL; + } + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s fstring[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "FSTRING_START fstring_middle* FSTRING_END")); + } + _res = NULL; + done: + p->level--; + return _res; +} + // string: STRING static expr_ty string_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -16415,8 +16293,7 @@ static expr_ty strings_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -16482,8 +16359,7 @@ static expr_ty list_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -16550,8 +16426,7 @@ static expr_ty tuple_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -16618,8 +16493,7 @@ static expr_ty set_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -16686,8 +16560,7 @@ static expr_ty dict_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -16779,8 +16652,7 @@ static asdl_seq* double_starred_kvpairs_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -16827,8 +16699,7 @@ static KeyValuePair* double_starred_kvpair_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -16893,8 +16764,7 @@ static KeyValuePair* kvpair_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -16943,8 +16813,7 @@ static asdl_comprehension_seq* for_if_clauses_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -16985,13 +16854,13 @@ for_if_clauses_rule(Parser *p) // for_if_clause: // | 'async' 'for' star_targets 'in' ~ disjunction (('if' disjunction))* // | 'for' star_targets 'in' ~ disjunction (('if' disjunction))* +// | 'async'? 'for' (bitwise_or ((',' bitwise_or))* ','?) !'in' // | invalid_for_target static comprehension_ty for_if_clause_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -17013,13 +16882,13 @@ for_if_clause_rule(Parser *p) expr_ty b; asdl_expr_seq* c; if ( - (_keyword = _PyPegen_expect_token(p, 668)) // token='async' + (_keyword = _PyPegen_expect_token(p, 673)) // token='async' && - (_keyword_1 = _PyPegen_expect_token(p, 666)) // token='for' + (_keyword_1 = _PyPegen_expect_token(p, 671)) // token='for' && (a = star_targets_rule(p)) // star_targets && - (_keyword_2 = _PyPegen_expect_token(p, 667)) // token='in' + (_keyword_2 = _PyPegen_expect_token(p, 672)) // token='in' && (_cut_var = 1) && @@ -17058,11 +16927,11 @@ for_if_clause_rule(Parser *p) expr_ty b; asdl_expr_seq* c; if ( - (_keyword = _PyPegen_expect_token(p, 666)) // token='for' + (_keyword = _PyPegen_expect_token(p, 671)) // token='for' && (a = star_targets_rule(p)) // star_targets && - (_keyword_1 = _PyPegen_expect_token(p, 667)) // token='in' + (_keyword_1 = _PyPegen_expect_token(p, 672)) // token='in' && (_cut_var = 1) && @@ -17088,6 +16957,39 @@ for_if_clause_rule(Parser *p) return NULL; } } + { // 'async'? 'for' (bitwise_or ((',' bitwise_or))* ','?) !'in' + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> for_if_clause[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'async'? 'for' (bitwise_or ((',' bitwise_or))* ','?) !'in'")); + Token * _keyword; + void *_opt_var; + UNUSED(_opt_var); // Silence compiler warnings + void *_tmp_122_var; + if ( + (_opt_var = _PyPegen_expect_token(p, 673), !p->error_indicator) // 'async'? + && + (_keyword = _PyPegen_expect_token(p, 671)) // token='for' + && + (_tmp_122_var = _tmp_122_rule(p)) // bitwise_or ((',' bitwise_or))* ','? + && + _PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, 672) // token='in' + ) + { + D(fprintf(stderr, "%*c+ for_if_clause[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'async'? 'for' (bitwise_or ((',' bitwise_or))* ','?) !'in'")); + _res = RAISE_SYNTAX_ERROR ( "'in' expected after for-loop variables" ); + if (_res == NULL && PyErr_Occurred()) { + p->error_indicator = 1; + p->level--; + return NULL; + } + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s for_if_clause[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'async'? 'for' (bitwise_or ((',' bitwise_or))* ','?) !'in'")); + } if (p->call_invalid_rules) { // invalid_for_target if (p->error_indicator) { p->level--; @@ -17118,8 +17020,7 @@ static expr_ty listcomp_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -17208,8 +17109,7 @@ static expr_ty setcomp_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -17300,8 +17200,7 @@ static expr_ty genexp_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -17331,7 +17230,7 @@ genexp_rule(Parser *p) if ( (_literal = _PyPegen_expect_token(p, 7)) // token='(' && - (a = _tmp_122_rule(p)) // assignment_expression | expression !':=' + (a = _tmp_123_rule(p)) // assignment_expression | expression !':=' && (b = for_if_clauses_rule(p)) // for_if_clauses && @@ -17390,8 +17289,7 @@ static expr_ty dictcomp_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -17480,8 +17378,7 @@ static expr_ty arguments_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -17556,8 +17453,7 @@ static expr_ty args_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -17583,9 +17479,9 @@ args_rule(Parser *p) asdl_expr_seq* a; void *b; if ( - (a = (asdl_expr_seq*)_gather_123_rule(p)) // ','.(starred_expression | (assignment_expression | expression !':=') !'=')+ + (a = (asdl_expr_seq*)_gather_124_rule(p)) // ','.(starred_expression | (assignment_expression | expression !':=') !'=')+ && - (b = _tmp_125_rule(p), !p->error_indicator) // [',' kwargs] + (b = _tmp_126_rule(p), !p->error_indicator) // [',' kwargs] ) { D(fprintf(stderr, "%*c+ args[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.(starred_expression | (assignment_expression | expression !':=') !'=')+ [',' kwargs]")); @@ -17657,8 +17553,7 @@ static asdl_seq* kwargs_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -17676,11 +17571,11 @@ kwargs_rule(Parser *p) asdl_seq * a; asdl_seq * b; if ( - (a = _gather_126_rule(p)) // ','.kwarg_or_starred+ + (a = _gather_127_rule(p)) // ','.kwarg_or_starred+ && (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (b = _gather_128_rule(p)) // ','.kwarg_or_double_starred+ + (b = _gather_129_rule(p)) // ','.kwarg_or_double_starred+ ) { D(fprintf(stderr, "%*c+ kwargs[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.kwarg_or_starred+ ',' ','.kwarg_or_double_starred+")); @@ -17702,13 +17597,13 @@ kwargs_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> kwargs[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.kwarg_or_starred+")); - asdl_seq * _gather_130_var; + asdl_seq * _gather_131_var; if ( - (_gather_130_var = _gather_130_rule(p)) // ','.kwarg_or_starred+ + (_gather_131_var = _gather_131_rule(p)) // ','.kwarg_or_starred+ ) { D(fprintf(stderr, "%*c+ kwargs[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.kwarg_or_starred+")); - _res = _gather_130_var; + _res = _gather_131_var; goto done; } p->mark = _mark; @@ -17721,13 +17616,13 @@ kwargs_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> kwargs[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.kwarg_or_double_starred+")); - asdl_seq * _gather_132_var; + asdl_seq * _gather_133_var; if ( - (_gather_132_var = _gather_132_rule(p)) // ','.kwarg_or_double_starred+ + (_gather_133_var = _gather_133_rule(p)) // ','.kwarg_or_double_starred+ ) { D(fprintf(stderr, "%*c+ kwargs[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.kwarg_or_double_starred+")); - _res = _gather_132_var; + _res = _gather_133_var; goto done; } p->mark = _mark; @@ -17745,8 +17640,7 @@ static expr_ty starred_expression_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -17829,8 +17723,7 @@ static KeywordOrStarred* kwarg_or_starred_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -17940,8 +17833,7 @@ static KeywordOrStarred* kwarg_or_double_starred_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -18063,8 +17955,7 @@ static expr_ty star_targets_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -18120,7 +18011,7 @@ star_targets_rule(Parser *p) if ( (a = star_target_rule(p)) // star_target && - (b = _loop0_134_rule(p)) // ((',' star_target))* + (b = _loop0_135_rule(p)) // ((',' star_target))* && (_opt_var = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? ) @@ -18158,8 +18049,7 @@ static asdl_expr_seq* star_targets_list_seq_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -18177,7 +18067,7 @@ star_targets_list_seq_rule(Parser *p) UNUSED(_opt_var); // Silence compiler warnings asdl_expr_seq* a; if ( - (a = (asdl_expr_seq*)_gather_135_rule(p)) // ','.star_target+ + (a = (asdl_expr_seq*)_gather_136_rule(p)) // ','.star_target+ && (_opt_var = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? ) @@ -18206,8 +18096,7 @@ static asdl_expr_seq* star_targets_tuple_seq_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -18228,7 +18117,7 @@ star_targets_tuple_seq_rule(Parser *p) if ( (a = star_target_rule(p)) // star_target && - (b = _loop1_137_rule(p)) // ((',' star_target))+ + (b = _loop1_138_rule(p)) // ((',' star_target))+ && (_opt_var = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? ) @@ -18284,8 +18173,7 @@ static expr_ty star_target_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -18317,7 +18205,7 @@ star_target_rule(Parser *p) if ( (_literal = _PyPegen_expect_token(p, 16)) // token='*' && - (a = _tmp_138_rule(p)) // !'*' star_target + (a = _tmp_139_rule(p)) // !'*' star_target ) { D(fprintf(stderr, "%*c+ star_target[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' (!'*' star_target)")); @@ -18376,8 +18264,7 @@ static expr_ty target_with_star_atom_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -18518,8 +18405,7 @@ static expr_ty star_atom_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -18679,8 +18565,7 @@ static expr_ty single_target_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -18774,8 +18659,7 @@ static expr_ty single_subscript_attribute_target_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -18895,8 +18779,7 @@ static expr_ty t_primary_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, t_primary_type, &_res)) { @@ -18930,8 +18813,7 @@ static expr_ty t_primary_raw(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -19152,8 +19034,7 @@ static void * t_lookahead_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -19229,8 +19110,7 @@ static asdl_expr_seq* del_targets_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -19248,7 +19128,7 @@ del_targets_rule(Parser *p) UNUSED(_opt_var); // Silence compiler warnings asdl_expr_seq* a; if ( - (a = (asdl_expr_seq*)_gather_139_rule(p)) // ','.del_target+ + (a = (asdl_expr_seq*)_gather_140_rule(p)) // ','.del_target+ && (_opt_var = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? ) @@ -19280,8 +19160,7 @@ static expr_ty del_target_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -19418,8 +19297,7 @@ static expr_ty del_t_atom_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -19586,8 +19464,7 @@ static asdl_expr_seq* type_expressions_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -19609,7 +19486,7 @@ type_expressions_rule(Parser *p) expr_ty b; expr_ty c; if ( - (a = _gather_141_rule(p)) // ','.expression+ + (a = _gather_142_rule(p)) // ','.expression+ && (_literal = _PyPegen_expect_token(p, 12)) // token=',' && @@ -19648,7 +19525,7 @@ type_expressions_rule(Parser *p) asdl_seq * a; expr_ty b; if ( - (a = _gather_143_rule(p)) // ','.expression+ + (a = _gather_144_rule(p)) // ','.expression+ && (_literal = _PyPegen_expect_token(p, 12)) // token=',' && @@ -19681,7 +19558,7 @@ type_expressions_rule(Parser *p) asdl_seq * a; expr_ty b; if ( - (a = _gather_145_rule(p)) // ','.expression+ + (a = _gather_146_rule(p)) // ','.expression+ && (_literal = _PyPegen_expect_token(p, 12)) // token=',' && @@ -19801,7 +19678,7 @@ type_expressions_rule(Parser *p) D(fprintf(stderr, "%*c> type_expressions[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.expression+")); asdl_expr_seq* a; if ( - (a = (asdl_expr_seq*)_gather_147_rule(p)) // ','.expression+ + (a = (asdl_expr_seq*)_gather_148_rule(p)) // ','.expression+ ) { D(fprintf(stderr, "%*c+ type_expressions[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.expression+")); @@ -19831,8 +19708,7 @@ static Token* func_type_comment_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -19853,7 +19729,7 @@ func_type_comment_rule(Parser *p) && (t = _PyPegen_expect_token(p, TYPE_COMMENT)) // token='TYPE_COMMENT' && - _PyPegen_lookahead(1, _tmp_149_rule, p) + _PyPegen_lookahead(1, _tmp_150_rule, p) ) { D(fprintf(stderr, "%*c+ func_type_comment[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NEWLINE TYPE_COMMENT &(NEWLINE INDENT)")); @@ -19914,7 +19790,7 @@ func_type_comment_rule(Parser *p) } // invalid_arguments: -// | args ',' '*' +// | ((','.(starred_expression | (assignment_expression | expression !':=') !'=')+ ',' kwargs) | kwargs) ',' '*' // | expression for_if_clauses ',' [args | expression for_if_clauses] // | NAME '=' expression for_if_clauses // | [(args ',')] NAME '=' &(',' | ')') @@ -19925,8 +19801,7 @@ static void * invalid_arguments_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -19934,25 +19809,25 @@ invalid_arguments_rule(Parser *p) } void * _res = NULL; int _mark = p->mark; - { // args ',' '*' + { // ((','.(starred_expression | (assignment_expression | expression !':=') !'=')+ ',' kwargs) | kwargs) ',' '*' if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> invalid_arguments[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "args ',' '*'")); + D(fprintf(stderr, "%*c> invalid_arguments[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "((','.(starred_expression | (assignment_expression | expression !':=') !'=')+ ',' kwargs) | kwargs) ',' '*'")); Token * _literal; - Token * _literal_1; - expr_ty a; + void *_tmp_151_var; + Token * b; if ( - (a = args_rule(p)) // args + (_tmp_151_var = _tmp_151_rule(p)) // (','.(starred_expression | (assignment_expression | expression !':=') !'=')+ ',' kwargs) | kwargs && (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (_literal_1 = _PyPegen_expect_token(p, 16)) // token='*' + (b = _PyPegen_expect_token(p, 16)) // token='*' ) { - D(fprintf(stderr, "%*c+ invalid_arguments[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "args ',' '*'")); - _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "iterable argument unpacking follows keyword argument unpacking" ); + D(fprintf(stderr, "%*c+ invalid_arguments[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "((','.(starred_expression | (assignment_expression | expression !':=') !'=')+ ',' kwargs) | kwargs) ',' '*'")); + _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( b , "iterable argument unpacking follows keyword argument unpacking" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; p->level--; @@ -19962,7 +19837,7 @@ invalid_arguments_rule(Parser *p) } p->mark = _mark; D(fprintf(stderr, "%*c%s invalid_arguments[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "args ',' '*'")); + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "((','.(starred_expression | (assignment_expression | expression !':=') !'=')+ ',' kwargs) | kwargs) ',' '*'")); } { // expression for_if_clauses ',' [args | expression for_if_clauses] if (p->error_indicator) { @@ -19982,7 +19857,7 @@ invalid_arguments_rule(Parser *p) && (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (_opt_var = _tmp_150_rule(p), !p->error_indicator) // [args | expression for_if_clauses] + (_opt_var = _tmp_152_rule(p), !p->error_indicator) // [args | expression for_if_clauses] ) { D(fprintf(stderr, "%*c+ invalid_arguments[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression for_if_clauses ',' [args | expression for_if_clauses]")); @@ -20042,13 +19917,13 @@ invalid_arguments_rule(Parser *p) expr_ty a; Token * b; if ( - (_opt_var = _tmp_151_rule(p), !p->error_indicator) // [(args ',')] + (_opt_var = _tmp_153_rule(p), !p->error_indicator) // [(args ',')] && (a = _PyPegen_name_token(p)) // NAME && (b = _PyPegen_expect_token(p, 22)) // token='=' && - _PyPegen_lookahead(1, _tmp_152_rule, p) + _PyPegen_lookahead(1, _tmp_154_rule, p) ) { D(fprintf(stderr, "%*c+ invalid_arguments[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "[(args ',')] NAME '=' &(',' | ')')")); @@ -20169,8 +20044,7 @@ static void * invalid_kwarg_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -20187,7 +20061,7 @@ invalid_kwarg_rule(Parser *p) Token* a; Token * b; if ( - (a = (Token*)_tmp_153_rule(p)) // 'True' | 'False' | 'None' + (a = (Token*)_tmp_155_rule(p)) // 'True' | 'False' | 'None' && (b = _PyPegen_expect_token(p, 22)) // token='=' ) @@ -20247,7 +20121,7 @@ invalid_kwarg_rule(Parser *p) expr_ty a; Token * b; if ( - _PyPegen_lookahead(0, _tmp_154_rule, p) + _PyPegen_lookahead(0, _tmp_156_rule, p) && (a = expression_rule(p)) // expression && @@ -20316,8 +20190,7 @@ expression_without_invalid_rule(Parser *p) int _prev_call_invalid = p->call_invalid_rules; p->call_invalid_rules = 0; if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->call_invalid_rules = _prev_call_invalid; @@ -20351,11 +20224,11 @@ expression_without_invalid_rule(Parser *p) if ( (a = disjunction_rule(p)) // disjunction && - (_keyword = _PyPegen_expect_token(p, 656)) // token='if' + (_keyword = _PyPegen_expect_token(p, 661)) // token='if' && (b = disjunction_rule(p)) // disjunction && - (_keyword_1 = _PyPegen_expect_token(p, 659)) // token='else' + (_keyword_1 = _PyPegen_expect_token(p, 664)) // token='else' && (c = expression_rule(p)) // expression ) @@ -20436,8 +20309,7 @@ static void * invalid_legacy_expression_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -20483,13 +20355,12 @@ invalid_legacy_expression_rule(Parser *p) // invalid_expression: // | !(NAME STRING | SOFT_KEYWORD) disjunction expression_without_invalid // | disjunction 'if' disjunction !('else' | ':') -// | 'lambda' lambda_params? ':' &(FSTRING_MIDDLE | fstring_replacement_field) +// | 'lambda' lambda_params? ':' &FSTRING_MIDDLE static void * invalid_expression_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -20506,7 +20377,7 @@ invalid_expression_rule(Parser *p) expr_ty a; expr_ty b; if ( - _PyPegen_lookahead(0, _tmp_155_rule, p) + _PyPegen_lookahead(0, _tmp_157_rule, p) && (a = disjunction_rule(p)) // disjunction && @@ -20538,11 +20409,11 @@ invalid_expression_rule(Parser *p) if ( (a = disjunction_rule(p)) // disjunction && - (_keyword = _PyPegen_expect_token(p, 656)) // token='if' + (_keyword = _PyPegen_expect_token(p, 661)) // token='if' && (b = disjunction_rule(p)) // disjunction && - _PyPegen_lookahead(0, _tmp_156_rule, p) + _PyPegen_lookahead(0, _tmp_158_rule, p) ) { D(fprintf(stderr, "%*c+ invalid_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "disjunction 'if' disjunction !('else' | ':')")); @@ -20558,27 +20429,27 @@ invalid_expression_rule(Parser *p) D(fprintf(stderr, "%*c%s invalid_expression[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "disjunction 'if' disjunction !('else' | ':')")); } - { // 'lambda' lambda_params? ':' &(FSTRING_MIDDLE | fstring_replacement_field) + { // 'lambda' lambda_params? ':' &FSTRING_MIDDLE if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> invalid_expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'lambda' lambda_params? ':' &(FSTRING_MIDDLE | fstring_replacement_field)")); + D(fprintf(stderr, "%*c> invalid_expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'lambda' lambda_params? ':' &FSTRING_MIDDLE")); void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings Token * a; Token * b; if ( - (a = _PyPegen_expect_token(p, 609)) // token='lambda' + (a = _PyPegen_expect_token(p, 612)) // token='lambda' && (_opt_var = lambda_params_rule(p), !p->error_indicator) // lambda_params? && (b = _PyPegen_expect_token(p, 11)) // token=':' && - _PyPegen_lookahead(1, _tmp_157_rule, p) + _PyPegen_lookahead_with_int(1, _PyPegen_expect_token, p, FSTRING_MIDDLE) // token=FSTRING_MIDDLE ) { - D(fprintf(stderr, "%*c+ invalid_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'lambda' lambda_params? ':' &(FSTRING_MIDDLE | fstring_replacement_field)")); + D(fprintf(stderr, "%*c+ invalid_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'lambda' lambda_params? ':' &FSTRING_MIDDLE")); _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "f-string: lambda expressions are not allowed without parentheses" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -20589,7 +20460,7 @@ invalid_expression_rule(Parser *p) } p->mark = _mark; D(fprintf(stderr, "%*c%s invalid_expression[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'lambda' lambda_params? ':' &(FSTRING_MIDDLE | fstring_replacement_field)")); + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'lambda' lambda_params? ':' &FSTRING_MIDDLE")); } _res = NULL; done: @@ -20605,8 +20476,7 @@ static void * invalid_named_expression_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -20664,7 +20534,7 @@ invalid_named_expression_rule(Parser *p) && (b = bitwise_or_rule(p)) // bitwise_or && - _PyPegen_lookahead(0, _tmp_158_rule, p) + _PyPegen_lookahead(0, _tmp_159_rule, p) ) { D(fprintf(stderr, "%*c+ invalid_named_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME '=' bitwise_or !('=' | ':=')")); @@ -20690,7 +20560,7 @@ invalid_named_expression_rule(Parser *p) Token * b; expr_ty bitwise_or_var; if ( - _PyPegen_lookahead(0, _tmp_159_rule, p) + _PyPegen_lookahead(0, _tmp_160_rule, p) && (a = bitwise_or_rule(p)) // bitwise_or && @@ -20698,7 +20568,7 @@ invalid_named_expression_rule(Parser *p) && (bitwise_or_var = bitwise_or_rule(p)) // bitwise_or && - _PyPegen_lookahead(0, _tmp_160_rule, p) + _PyPegen_lookahead(0, _tmp_161_rule, p) ) { D(fprintf(stderr, "%*c+ invalid_named_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "!(list | tuple | genexp | 'True' | 'None' | 'False') bitwise_or '=' bitwise_or !('=' | ':=')")); @@ -20732,8 +20602,7 @@ static void * invalid_assignment_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -20779,7 +20648,7 @@ invalid_assignment_rule(Parser *p) D(fprintf(stderr, "%*c> invalid_assignment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_named_expression ',' star_named_expressions* ':' expression")); Token * _literal; Token * _literal_1; - asdl_seq * _loop0_161_var; + asdl_seq * _loop0_162_var; expr_ty a; expr_ty expression_var; if ( @@ -20787,7 +20656,7 @@ invalid_assignment_rule(Parser *p) && (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (_loop0_161_var = _loop0_161_rule(p)) // star_named_expressions* + (_loop0_162_var = _loop0_162_rule(p)) // star_named_expressions* && (_literal_1 = _PyPegen_expect_token(p, 11)) // token=':' && @@ -20844,10 +20713,10 @@ invalid_assignment_rule(Parser *p) } D(fprintf(stderr, "%*c> invalid_assignment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "((star_targets '='))* star_expressions '='")); Token * _literal; - asdl_seq * _loop0_162_var; + asdl_seq * _loop0_163_var; expr_ty a; if ( - (_loop0_162_var = _loop0_162_rule(p)) // ((star_targets '='))* + (_loop0_163_var = _loop0_163_rule(p)) // ((star_targets '='))* && (a = star_expressions_rule(p)) // star_expressions && @@ -20874,10 +20743,10 @@ invalid_assignment_rule(Parser *p) } D(fprintf(stderr, "%*c> invalid_assignment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "((star_targets '='))* yield_expr '='")); Token * _literal; - asdl_seq * _loop0_163_var; + asdl_seq * _loop0_164_var; expr_ty a; if ( - (_loop0_163_var = _loop0_163_rule(p)) // ((star_targets '='))* + (_loop0_164_var = _loop0_164_rule(p)) // ((star_targets '='))* && (a = yield_expr_rule(p)) // yield_expr && @@ -20903,7 +20772,7 @@ invalid_assignment_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_assignment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions augassign (yield_expr | star_expressions)")); - void *_tmp_164_var; + void *_tmp_165_var; expr_ty a; AugOperator* augassign_var; if ( @@ -20911,7 +20780,7 @@ invalid_assignment_rule(Parser *p) && (augassign_var = augassign_rule(p)) // augassign && - (_tmp_164_var = _tmp_164_rule(p)) // yield_expr | star_expressions + (_tmp_165_var = _tmp_165_rule(p)) // yield_expr | star_expressions ) { D(fprintf(stderr, "%*c+ invalid_assignment[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions augassign (yield_expr | star_expressions)")); @@ -20938,8 +20807,7 @@ static expr_ty invalid_ann_assign_target_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -21026,8 +20894,7 @@ static void * invalid_del_stmt_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -21044,7 +20911,7 @@ invalid_del_stmt_rule(Parser *p) Token * _keyword; expr_ty a; if ( - (_keyword = _PyPegen_expect_token(p, 613)) // token='del' + (_keyword = _PyPegen_expect_token(p, 616)) // token='del' && (a = star_expressions_rule(p)) // star_expressions ) @@ -21073,8 +20940,7 @@ static void * invalid_block_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -21122,8 +20988,7 @@ static void * invalid_comprehension_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -21137,11 +21002,11 @@ invalid_comprehension_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_comprehension[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('[' | '(' | '{') starred_expression for_if_clauses")); - void *_tmp_165_var; + void *_tmp_166_var; expr_ty a; asdl_comprehension_seq* for_if_clauses_var; if ( - (_tmp_165_var = _tmp_165_rule(p)) // '[' | '(' | '{' + (_tmp_166_var = _tmp_166_rule(p)) // '[' | '(' | '{' && (a = starred_expression_rule(p)) // starred_expression && @@ -21168,12 +21033,12 @@ invalid_comprehension_rule(Parser *p) } D(fprintf(stderr, "%*c> invalid_comprehension[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('[' | '{') star_named_expression ',' star_named_expressions for_if_clauses")); Token * _literal; - void *_tmp_166_var; + void *_tmp_167_var; expr_ty a; asdl_expr_seq* b; asdl_comprehension_seq* for_if_clauses_var; if ( - (_tmp_166_var = _tmp_166_rule(p)) // '[' | '{' + (_tmp_167_var = _tmp_167_rule(p)) // '[' | '{' && (a = star_named_expression_rule(p)) // star_named_expression && @@ -21203,12 +21068,12 @@ invalid_comprehension_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_comprehension[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('[' | '{') star_named_expression ',' for_if_clauses")); - void *_tmp_167_var; + void *_tmp_168_var; expr_ty a; Token * b; asdl_comprehension_seq* for_if_clauses_var; if ( - (_tmp_167_var = _tmp_167_rule(p)) // '[' | '{' + (_tmp_168_var = _tmp_168_rule(p)) // '[' | '{' && (a = star_named_expression_rule(p)) // star_named_expression && @@ -21241,8 +21106,7 @@ static void * invalid_dict_comprehension_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -21303,8 +21167,7 @@ static void * invalid_parameters_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -21345,13 +21208,13 @@ invalid_parameters_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(slash_no_default | slash_with_default) param_maybe_default* '/'")); - asdl_seq * _loop0_169_var; - void *_tmp_168_var; + asdl_seq * _loop0_170_var; + void *_tmp_169_var; Token * a; if ( - (_tmp_168_var = _tmp_168_rule(p)) // slash_no_default | slash_with_default + (_tmp_169_var = _tmp_169_rule(p)) // slash_no_default | slash_with_default && - (_loop0_169_var = _loop0_169_rule(p)) // param_maybe_default* + (_loop0_170_var = _loop0_170_rule(p)) // param_maybe_default* && (a = _PyPegen_expect_token(p, 17)) // token='/' ) @@ -21375,7 +21238,7 @@ invalid_parameters_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "slash_no_default? param_no_default* invalid_parameters_helper param_no_default")); - asdl_seq * _loop0_170_var; + asdl_seq * _loop0_171_var; void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings arg_ty a; @@ -21383,7 +21246,7 @@ invalid_parameters_rule(Parser *p) if ( (_opt_var = slash_no_default_rule(p), !p->error_indicator) // slash_no_default? && - (_loop0_170_var = _loop0_170_rule(p)) // param_no_default* + (_loop0_171_var = _loop0_171_rule(p)) // param_no_default* && (invalid_parameters_helper_var = invalid_parameters_helper_rule(p)) // invalid_parameters_helper && @@ -21409,18 +21272,18 @@ invalid_parameters_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default* '(' param_no_default+ ','? ')'")); - asdl_seq * _loop0_171_var; - asdl_seq * _loop1_172_var; + asdl_seq * _loop0_172_var; + asdl_seq * _loop1_173_var; void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings Token * a; Token * b; if ( - (_loop0_171_var = _loop0_171_rule(p)) // param_no_default* + (_loop0_172_var = _loop0_172_rule(p)) // param_no_default* && (a = _PyPegen_expect_token(p, 7)) // token='(' && - (_loop1_172_var = _loop1_172_rule(p)) // param_no_default+ + (_loop1_173_var = _loop1_173_rule(p)) // param_no_default+ && (_opt_var = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? && @@ -21447,22 +21310,22 @@ invalid_parameters_rule(Parser *p) } D(fprintf(stderr, "%*c> invalid_parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "[(slash_no_default | slash_with_default)] param_maybe_default* '*' (',' | param_no_default) param_maybe_default* '/'")); Token * _literal; - asdl_seq * _loop0_174_var; - asdl_seq * _loop0_176_var; + asdl_seq * _loop0_175_var; + asdl_seq * _loop0_177_var; void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings - void *_tmp_175_var; + void *_tmp_176_var; Token * a; if ( - (_opt_var = _tmp_173_rule(p), !p->error_indicator) // [(slash_no_default | slash_with_default)] + (_opt_var = _tmp_174_rule(p), !p->error_indicator) // [(slash_no_default | slash_with_default)] && - (_loop0_174_var = _loop0_174_rule(p)) // param_maybe_default* + (_loop0_175_var = _loop0_175_rule(p)) // param_maybe_default* && (_literal = _PyPegen_expect_token(p, 16)) // token='*' && - (_tmp_175_var = _tmp_175_rule(p)) // ',' | param_no_default + (_tmp_176_var = _tmp_176_rule(p)) // ',' | param_no_default && - (_loop0_176_var = _loop0_176_rule(p)) // param_maybe_default* + (_loop0_177_var = _loop0_177_rule(p)) // param_maybe_default* && (a = _PyPegen_expect_token(p, 17)) // token='/' ) @@ -21487,10 +21350,10 @@ invalid_parameters_rule(Parser *p) } D(fprintf(stderr, "%*c> invalid_parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_maybe_default+ '/' '*'")); Token * _literal; - asdl_seq * _loop1_177_var; + asdl_seq * _loop1_178_var; Token * a; if ( - (_loop1_177_var = _loop1_177_rule(p)) // param_maybe_default+ + (_loop1_178_var = _loop1_178_rule(p)) // param_maybe_default+ && (_literal = _PyPegen_expect_token(p, 17)) // token='/' && @@ -21521,8 +21384,7 @@ static void * invalid_default_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -21540,7 +21402,7 @@ invalid_default_rule(Parser *p) if ( (a = _PyPegen_expect_token(p, 22)) // token='=' && - _PyPegen_lookahead(1, _tmp_178_rule, p) + _PyPegen_lookahead(1, _tmp_179_rule, p) ) { D(fprintf(stderr, "%*c+ invalid_default[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'=' &(')' | ',')")); @@ -21571,8 +21433,7 @@ static void * invalid_star_etc_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -21586,12 +21447,12 @@ invalid_star_etc_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_star_etc[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' (')' | ',' (')' | '**'))")); - void *_tmp_179_var; + void *_tmp_180_var; Token * a; if ( (a = _PyPegen_expect_token(p, 16)) // token='*' && - (_tmp_179_var = _tmp_179_rule(p)) // ')' | ',' (')' | '**') + (_tmp_180_var = _tmp_180_rule(p)) // ')' | ',' (')' | '**') ) { D(fprintf(stderr, "%*c+ invalid_star_etc[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' (')' | ',' (')' | '**'))")); @@ -21674,20 +21535,20 @@ invalid_star_etc_rule(Parser *p) } D(fprintf(stderr, "%*c> invalid_star_etc[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' (param_no_default | ',') param_maybe_default* '*' (param_no_default | ',')")); Token * _literal; - asdl_seq * _loop0_181_var; - void *_tmp_180_var; - void *_tmp_182_var; + asdl_seq * _loop0_182_var; + void *_tmp_181_var; + void *_tmp_183_var; Token * a; if ( (_literal = _PyPegen_expect_token(p, 16)) // token='*' && - (_tmp_180_var = _tmp_180_rule(p)) // param_no_default | ',' + (_tmp_181_var = _tmp_181_rule(p)) // param_no_default | ',' && - (_loop0_181_var = _loop0_181_rule(p)) // param_maybe_default* + (_loop0_182_var = _loop0_182_rule(p)) // param_maybe_default* && (a = _PyPegen_expect_token(p, 16)) // token='*' && - (_tmp_182_var = _tmp_182_rule(p)) // param_no_default | ',' + (_tmp_183_var = _tmp_183_rule(p)) // param_no_default | ',' ) { D(fprintf(stderr, "%*c+ invalid_star_etc[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' (param_no_default | ',') param_maybe_default* '*' (param_no_default | ',')")); @@ -21714,8 +21575,7 @@ static void * invalid_kwds_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -21803,7 +21663,7 @@ invalid_kwds_rule(Parser *p) && (_literal_1 = _PyPegen_expect_token(p, 12)) // token=',' && - (a = (Token*)_tmp_183_rule(p)) // '*' | '**' | '/' + (a = (Token*)_tmp_184_rule(p)) // '*' | '**' | '/' ) { D(fprintf(stderr, "%*c+ invalid_kwds[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**' param ',' ('*' | '**' | '/')")); @@ -21830,8 +21690,7 @@ static void * invalid_parameters_helper_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -21869,13 +21728,13 @@ invalid_parameters_helper_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_parameters_helper[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default+")); - asdl_seq * _loop1_184_var; + asdl_seq * _loop1_185_var; if ( - (_loop1_184_var = _loop1_184_rule(p)) // param_with_default+ + (_loop1_185_var = _loop1_185_rule(p)) // param_with_default+ ) { D(fprintf(stderr, "%*c+ invalid_parameters_helper[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "param_with_default+")); - _res = _loop1_184_var; + _res = _loop1_185_var; goto done; } p->mark = _mark; @@ -21899,8 +21758,7 @@ static void * invalid_lambda_parameters_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -21941,13 +21799,13 @@ invalid_lambda_parameters_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_lambda_parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(lambda_slash_no_default | lambda_slash_with_default) lambda_param_maybe_default* '/'")); - asdl_seq * _loop0_186_var; - void *_tmp_185_var; + asdl_seq * _loop0_187_var; + void *_tmp_186_var; Token * a; if ( - (_tmp_185_var = _tmp_185_rule(p)) // lambda_slash_no_default | lambda_slash_with_default + (_tmp_186_var = _tmp_186_rule(p)) // lambda_slash_no_default | lambda_slash_with_default && - (_loop0_186_var = _loop0_186_rule(p)) // lambda_param_maybe_default* + (_loop0_187_var = _loop0_187_rule(p)) // lambda_param_maybe_default* && (a = _PyPegen_expect_token(p, 17)) // token='/' ) @@ -21971,7 +21829,7 @@ invalid_lambda_parameters_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_lambda_parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_slash_no_default? lambda_param_no_default* invalid_lambda_parameters_helper lambda_param_no_default")); - asdl_seq * _loop0_187_var; + asdl_seq * _loop0_188_var; void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings arg_ty a; @@ -21979,7 +21837,7 @@ invalid_lambda_parameters_rule(Parser *p) if ( (_opt_var = lambda_slash_no_default_rule(p), !p->error_indicator) // lambda_slash_no_default? && - (_loop0_187_var = _loop0_187_rule(p)) // lambda_param_no_default* + (_loop0_188_var = _loop0_188_rule(p)) // lambda_param_no_default* && (invalid_lambda_parameters_helper_var = invalid_lambda_parameters_helper_rule(p)) // invalid_lambda_parameters_helper && @@ -22005,18 +21863,18 @@ invalid_lambda_parameters_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_lambda_parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default* '(' ','.lambda_param+ ','? ')'")); - asdl_seq * _gather_189_var; - asdl_seq * _loop0_188_var; + asdl_seq * _gather_190_var; + asdl_seq * _loop0_189_var; void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings Token * a; Token * b; if ( - (_loop0_188_var = _loop0_188_rule(p)) // lambda_param_no_default* + (_loop0_189_var = _loop0_189_rule(p)) // lambda_param_no_default* && (a = _PyPegen_expect_token(p, 7)) // token='(' && - (_gather_189_var = _gather_189_rule(p)) // ','.lambda_param+ + (_gather_190_var = _gather_190_rule(p)) // ','.lambda_param+ && (_opt_var = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? && @@ -22043,22 +21901,22 @@ invalid_lambda_parameters_rule(Parser *p) } D(fprintf(stderr, "%*c> invalid_lambda_parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "[(lambda_slash_no_default | lambda_slash_with_default)] lambda_param_maybe_default* '*' (',' | lambda_param_no_default) lambda_param_maybe_default* '/'")); Token * _literal; - asdl_seq * _loop0_192_var; - asdl_seq * _loop0_194_var; + asdl_seq * _loop0_193_var; + asdl_seq * _loop0_195_var; void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings - void *_tmp_193_var; + void *_tmp_194_var; Token * a; if ( - (_opt_var = _tmp_191_rule(p), !p->error_indicator) // [(lambda_slash_no_default | lambda_slash_with_default)] + (_opt_var = _tmp_192_rule(p), !p->error_indicator) // [(lambda_slash_no_default | lambda_slash_with_default)] && - (_loop0_192_var = _loop0_192_rule(p)) // lambda_param_maybe_default* + (_loop0_193_var = _loop0_193_rule(p)) // lambda_param_maybe_default* && (_literal = _PyPegen_expect_token(p, 16)) // token='*' && - (_tmp_193_var = _tmp_193_rule(p)) // ',' | lambda_param_no_default + (_tmp_194_var = _tmp_194_rule(p)) // ',' | lambda_param_no_default && - (_loop0_194_var = _loop0_194_rule(p)) // lambda_param_maybe_default* + (_loop0_195_var = _loop0_195_rule(p)) // lambda_param_maybe_default* && (a = _PyPegen_expect_token(p, 17)) // token='/' ) @@ -22083,10 +21941,10 @@ invalid_lambda_parameters_rule(Parser *p) } D(fprintf(stderr, "%*c> invalid_lambda_parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_maybe_default+ '/' '*'")); Token * _literal; - asdl_seq * _loop1_195_var; + asdl_seq * _loop1_196_var; Token * a; if ( - (_loop1_195_var = _loop1_195_rule(p)) // lambda_param_maybe_default+ + (_loop1_196_var = _loop1_196_rule(p)) // lambda_param_maybe_default+ && (_literal = _PyPegen_expect_token(p, 17)) // token='/' && @@ -22119,8 +21977,7 @@ static void * invalid_lambda_parameters_helper_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -22158,13 +22015,13 @@ invalid_lambda_parameters_helper_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_lambda_parameters_helper[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default+")); - asdl_seq * _loop1_196_var; + asdl_seq * _loop1_197_var; if ( - (_loop1_196_var = _loop1_196_rule(p)) // lambda_param_with_default+ + (_loop1_197_var = _loop1_197_rule(p)) // lambda_param_with_default+ ) { D(fprintf(stderr, "%*c+ invalid_lambda_parameters_helper[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default+")); - _res = _loop1_196_var; + _res = _loop1_197_var; goto done; } p->mark = _mark; @@ -22185,8 +22042,7 @@ static void * invalid_lambda_star_etc_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -22201,11 +22057,11 @@ invalid_lambda_star_etc_rule(Parser *p) } D(fprintf(stderr, "%*c> invalid_lambda_star_etc[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' (':' | ',' (':' | '**'))")); Token * _literal; - void *_tmp_197_var; + void *_tmp_198_var; if ( (_literal = _PyPegen_expect_token(p, 16)) // token='*' && - (_tmp_197_var = _tmp_197_rule(p)) // ':' | ',' (':' | '**') + (_tmp_198_var = _tmp_198_rule(p)) // ':' | ',' (':' | '**') ) { D(fprintf(stderr, "%*c+ invalid_lambda_star_etc[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' (':' | ',' (':' | '**'))")); @@ -22258,20 +22114,20 @@ invalid_lambda_star_etc_rule(Parser *p) } D(fprintf(stderr, "%*c> invalid_lambda_star_etc[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' (lambda_param_no_default | ',') lambda_param_maybe_default* '*' (lambda_param_no_default | ',')")); Token * _literal; - asdl_seq * _loop0_199_var; - void *_tmp_198_var; - void *_tmp_200_var; + asdl_seq * _loop0_200_var; + void *_tmp_199_var; + void *_tmp_201_var; Token * a; if ( (_literal = _PyPegen_expect_token(p, 16)) // token='*' && - (_tmp_198_var = _tmp_198_rule(p)) // lambda_param_no_default | ',' + (_tmp_199_var = _tmp_199_rule(p)) // lambda_param_no_default | ',' && - (_loop0_199_var = _loop0_199_rule(p)) // lambda_param_maybe_default* + (_loop0_200_var = _loop0_200_rule(p)) // lambda_param_maybe_default* && (a = _PyPegen_expect_token(p, 16)) // token='*' && - (_tmp_200_var = _tmp_200_rule(p)) // lambda_param_no_default | ',' + (_tmp_201_var = _tmp_201_rule(p)) // lambda_param_no_default | ',' ) { D(fprintf(stderr, "%*c+ invalid_lambda_star_etc[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' (lambda_param_no_default | ',') lambda_param_maybe_default* '*' (lambda_param_no_default | ',')")); @@ -22301,8 +22157,7 @@ static void * invalid_lambda_kwds_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -22390,7 +22245,7 @@ invalid_lambda_kwds_rule(Parser *p) && (_literal_1 = _PyPegen_expect_token(p, 12)) // token=',' && - (a = (Token*)_tmp_201_rule(p)) // '*' | '**' | '/' + (a = (Token*)_tmp_202_rule(p)) // '*' | '**' | '/' ) { D(fprintf(stderr, "%*c+ invalid_lambda_kwds[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**' lambda_param ',' ('*' | '**' | '/')")); @@ -22417,8 +22272,7 @@ static void * invalid_double_type_comments_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -22473,8 +22327,7 @@ static void * invalid_with_item_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -22494,11 +22347,11 @@ invalid_with_item_rule(Parser *p) if ( (expression_var = expression_rule(p)) // expression && - (_keyword = _PyPegen_expect_token(p, 654)) // token='as' + (_keyword = _PyPegen_expect_token(p, 659)) // token='as' && (a = expression_rule(p)) // expression && - _PyPegen_lookahead(1, _tmp_202_rule, p) + _PyPegen_lookahead(1, _tmp_203_rule, p) ) { D(fprintf(stderr, "%*c+ invalid_with_item[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression 'as' expression &(',' | ')' | ':')")); @@ -22525,8 +22378,7 @@ static void * invalid_for_target_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -22545,9 +22397,9 @@ invalid_for_target_rule(Parser *p) UNUSED(_opt_var); // Silence compiler warnings expr_ty a; if ( - (_opt_var = _PyPegen_expect_token(p, 668), !p->error_indicator) // 'async'? + (_opt_var = _PyPegen_expect_token(p, 673), !p->error_indicator) // 'async'? && - (_keyword = _PyPegen_expect_token(p, 666)) // token='for' + (_keyword = _PyPegen_expect_token(p, 671)) // token='for' && (a = star_expressions_rule(p)) // star_expressions ) @@ -22576,8 +22428,7 @@ static void * invalid_group_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -22659,8 +22510,7 @@ static void * invalid_import_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -22674,16 +22524,16 @@ invalid_import_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_import[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'import' ','.dotted_name+ 'from' dotted_name")); - asdl_seq * _gather_203_var; + asdl_seq * _gather_204_var; Token * _keyword; Token * a; expr_ty dotted_name_var; if ( - (a = _PyPegen_expect_token(p, 617)) // token='import' + (a = _PyPegen_expect_token(p, 620)) // token='import' && - (_gather_203_var = _gather_203_rule(p)) // ','.dotted_name+ + (_gather_204_var = _gather_204_rule(p)) // ','.dotted_name+ && - (_keyword = _PyPegen_expect_token(p, 618)) // token='from' + (_keyword = _PyPegen_expect_token(p, 621)) // token='from' && (dotted_name_var = dotted_name_rule(p)) // dotted_name ) @@ -22712,8 +22562,7 @@ static void * invalid_import_from_targets_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -22757,6 +22606,82 @@ invalid_import_from_targets_rule(Parser *p) return _res; } +// invalid_compound_stmt: 'elif' named_expression ':' | 'else' ':' +static void * +invalid_compound_stmt_rule(Parser *p) +{ + if (p->level++ == MAXSTACK) { + _Pypegen_stack_overflow(p); + } + if (p->error_indicator) { + p->level--; + return NULL; + } + void * _res = NULL; + int _mark = p->mark; + { // 'elif' named_expression ':' + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> invalid_compound_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'elif' named_expression ':'")); + Token * _literal; + Token * a; + expr_ty named_expression_var; + if ( + (a = _PyPegen_expect_token(p, 663)) // token='elif' + && + (named_expression_var = named_expression_rule(p)) // named_expression + && + (_literal = _PyPegen_expect_token(p, 11)) // token=':' + ) + { + D(fprintf(stderr, "%*c+ invalid_compound_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'elif' named_expression ':'")); + _res = RAISE_SYNTAX_ERROR_STARTING_FROM ( a , "'elif' must match an if-statement here" ); + if (_res == NULL && PyErr_Occurred()) { + p->error_indicator = 1; + p->level--; + return NULL; + } + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s invalid_compound_stmt[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'elif' named_expression ':'")); + } + { // 'else' ':' + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> invalid_compound_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'else' ':'")); + Token * _literal; + Token * a; + if ( + (a = _PyPegen_expect_token(p, 664)) // token='else' + && + (_literal = _PyPegen_expect_token(p, 11)) // token=':' + ) + { + D(fprintf(stderr, "%*c+ invalid_compound_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'else' ':'")); + _res = RAISE_SYNTAX_ERROR_STARTING_FROM ( a , "'else' must match a valid statement here" ); + if (_res == NULL && PyErr_Occurred()) { + p->error_indicator = 1; + p->level--; + return NULL; + } + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s invalid_compound_stmt[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'else' ':'")); + } + _res = NULL; + done: + p->level--; + return _res; +} + // invalid_with_stmt: // | 'async'? 'with' ','.(expression ['as' star_target])+ NEWLINE // | 'async'? 'with' '(' ','.(expressions ['as' star_target])+ ','? ')' NEWLINE @@ -22764,8 +22689,7 @@ static void * invalid_with_stmt_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -22779,17 +22703,17 @@ invalid_with_stmt_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_with_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'async'? 'with' ','.(expression ['as' star_target])+ NEWLINE")); - asdl_seq * _gather_205_var; + asdl_seq * _gather_206_var; Token * _keyword; void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings Token * newline_var; if ( - (_opt_var = _PyPegen_expect_token(p, 668), !p->error_indicator) // 'async'? + (_opt_var = _PyPegen_expect_token(p, 673), !p->error_indicator) // 'async'? && - (_keyword = _PyPegen_expect_token(p, 629)) // token='with' + (_keyword = _PyPegen_expect_token(p, 634)) // token='with' && - (_gather_205_var = _gather_205_rule(p)) // ','.(expression ['as' star_target])+ + (_gather_206_var = _gather_206_rule(p)) // ','.(expression ['as' star_target])+ && (newline_var = _PyPegen_expect_token(p, NEWLINE)) // token='NEWLINE' ) @@ -22813,7 +22737,7 @@ invalid_with_stmt_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_with_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'async'? 'with' '(' ','.(expressions ['as' star_target])+ ','? ')' NEWLINE")); - asdl_seq * _gather_207_var; + asdl_seq * _gather_208_var; Token * _keyword; Token * _literal; Token * _literal_1; @@ -22823,13 +22747,13 @@ invalid_with_stmt_rule(Parser *p) UNUSED(_opt_var_1); // Silence compiler warnings Token * newline_var; if ( - (_opt_var = _PyPegen_expect_token(p, 668), !p->error_indicator) // 'async'? + (_opt_var = _PyPegen_expect_token(p, 673), !p->error_indicator) // 'async'? && - (_keyword = _PyPegen_expect_token(p, 629)) // token='with' + (_keyword = _PyPegen_expect_token(p, 634)) // token='with' && (_literal = _PyPegen_expect_token(p, 7)) // token='(' && - (_gather_207_var = _gather_207_rule(p)) // ','.(expressions ['as' star_target])+ + (_gather_208_var = _gather_208_rule(p)) // ','.(expressions ['as' star_target])+ && (_opt_var_1 = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? && @@ -22864,8 +22788,7 @@ static void * invalid_with_stmt_indent_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -22879,18 +22802,18 @@ invalid_with_stmt_indent_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_with_stmt_indent[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'async'? 'with' ','.(expression ['as' star_target])+ ':' NEWLINE !INDENT")); - asdl_seq * _gather_209_var; + asdl_seq * _gather_210_var; Token * _literal; void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings Token * a; Token * newline_var; if ( - (_opt_var = _PyPegen_expect_token(p, 668), !p->error_indicator) // 'async'? + (_opt_var = _PyPegen_expect_token(p, 673), !p->error_indicator) // 'async'? && - (a = _PyPegen_expect_token(p, 629)) // token='with' + (a = _PyPegen_expect_token(p, 634)) // token='with' && - (_gather_209_var = _gather_209_rule(p)) // ','.(expression ['as' star_target])+ + (_gather_210_var = _gather_210_rule(p)) // ','.(expression ['as' star_target])+ && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && @@ -22918,7 +22841,7 @@ invalid_with_stmt_indent_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_with_stmt_indent[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'async'? 'with' '(' ','.(expressions ['as' star_target])+ ','? ')' ':' NEWLINE !INDENT")); - asdl_seq * _gather_211_var; + asdl_seq * _gather_212_var; Token * _literal; Token * _literal_1; Token * _literal_2; @@ -22929,13 +22852,13 @@ invalid_with_stmt_indent_rule(Parser *p) Token * a; Token * newline_var; if ( - (_opt_var = _PyPegen_expect_token(p, 668), !p->error_indicator) // 'async'? + (_opt_var = _PyPegen_expect_token(p, 673), !p->error_indicator) // 'async'? && - (a = _PyPegen_expect_token(p, 629)) // token='with' + (a = _PyPegen_expect_token(p, 634)) // token='with' && (_literal = _PyPegen_expect_token(p, 7)) // token='(' && - (_gather_211_var = _gather_211_rule(p)) // ','.(expressions ['as' star_target])+ + (_gather_212_var = _gather_212_rule(p)) // ','.(expressions ['as' star_target])+ && (_opt_var_1 = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? && @@ -22976,8 +22899,7 @@ static void * invalid_try_stmt_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -22995,7 +22917,7 @@ invalid_try_stmt_rule(Parser *p) Token * a; Token * newline_var; if ( - (a = _PyPegen_expect_token(p, 638)) // token='try' + (a = _PyPegen_expect_token(p, 643)) // token='try' && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && @@ -23027,13 +22949,13 @@ invalid_try_stmt_rule(Parser *p) Token * _literal; asdl_stmt_seq* block_var; if ( - (_keyword = _PyPegen_expect_token(p, 638)) // token='try' + (_keyword = _PyPegen_expect_token(p, 643)) // token='try' && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && (block_var = block_rule(p)) // block && - _PyPegen_lookahead(0, _tmp_213_rule, p) + _PyPegen_lookahead(0, _tmp_214_rule, p) ) { D(fprintf(stderr, "%*c+ invalid_try_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'try' ':' block !('except' | 'finally')")); @@ -23058,29 +22980,29 @@ invalid_try_stmt_rule(Parser *p) Token * _keyword; Token * _literal; Token * _literal_1; - asdl_seq * _loop0_214_var; - asdl_seq * _loop1_215_var; + asdl_seq * _loop0_215_var; + asdl_seq * _loop1_216_var; void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings Token * a; Token * b; expr_ty expression_var; if ( - (_keyword = _PyPegen_expect_token(p, 638)) // token='try' + (_keyword = _PyPegen_expect_token(p, 643)) // token='try' && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && - (_loop0_214_var = _loop0_214_rule(p)) // block* + (_loop0_215_var = _loop0_215_rule(p)) // block* && - (_loop1_215_var = _loop1_215_rule(p)) // except_block+ + (_loop1_216_var = _loop1_216_rule(p)) // except_block+ && - (a = _PyPegen_expect_token(p, 651)) // token='except' + (a = _PyPegen_expect_token(p, 656)) // token='except' && (b = _PyPegen_expect_token(p, 16)) // token='*' && (expression_var = expression_rule(p)) // expression && - (_opt_var = _tmp_216_rule(p), !p->error_indicator) // ['as' NAME] + (_opt_var = _tmp_217_rule(p), !p->error_indicator) // ['as' NAME] && (_literal_1 = _PyPegen_expect_token(p, 11)) // token=':' ) @@ -23107,23 +23029,23 @@ invalid_try_stmt_rule(Parser *p) Token * _keyword; Token * _literal; Token * _literal_1; - asdl_seq * _loop0_217_var; - asdl_seq * _loop1_218_var; + asdl_seq * _loop0_218_var; + asdl_seq * _loop1_219_var; void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings Token * a; if ( - (_keyword = _PyPegen_expect_token(p, 638)) // token='try' + (_keyword = _PyPegen_expect_token(p, 643)) // token='try' && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && - (_loop0_217_var = _loop0_217_rule(p)) // block* + (_loop0_218_var = _loop0_218_rule(p)) // block* && - (_loop1_218_var = _loop1_218_rule(p)) // except_star_block+ + (_loop1_219_var = _loop1_219_rule(p)) // except_star_block+ && - (a = _PyPegen_expect_token(p, 651)) // token='except' + (a = _PyPegen_expect_token(p, 656)) // token='except' && - (_opt_var = _tmp_219_rule(p), !p->error_indicator) // [expression ['as' NAME]] + (_opt_var = _tmp_220_rule(p), !p->error_indicator) // [expression ['as' NAME]] && (_literal_1 = _PyPegen_expect_token(p, 11)) // token=':' ) @@ -23156,8 +23078,7 @@ static void * invalid_except_stmt_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -23181,7 +23102,7 @@ invalid_except_stmt_rule(Parser *p) expr_ty a; expr_ty expressions_var; if ( - (_keyword = _PyPegen_expect_token(p, 651)) // token='except' + (_keyword = _PyPegen_expect_token(p, 656)) // token='except' && (_opt_var = _PyPegen_expect_token(p, 16), !p->error_indicator) // '*'? && @@ -23191,7 +23112,7 @@ invalid_except_stmt_rule(Parser *p) && (expressions_var = expressions_rule(p)) // expressions && - (_opt_var_1 = _tmp_220_rule(p), !p->error_indicator) // ['as' NAME] + (_opt_var_1 = _tmp_221_rule(p), !p->error_indicator) // ['as' NAME] && (_literal_1 = _PyPegen_expect_token(p, 11)) // token=':' ) @@ -23223,13 +23144,13 @@ invalid_except_stmt_rule(Parser *p) expr_ty expression_var; Token * newline_var; if ( - (a = _PyPegen_expect_token(p, 651)) // token='except' + (a = _PyPegen_expect_token(p, 656)) // token='except' && (_opt_var = _PyPegen_expect_token(p, 16), !p->error_indicator) // '*'? && (expression_var = expression_rule(p)) // expression && - (_opt_var_1 = _tmp_221_rule(p), !p->error_indicator) // ['as' NAME] + (_opt_var_1 = _tmp_222_rule(p), !p->error_indicator) // ['as' NAME] && (newline_var = _PyPegen_expect_token(p, NEWLINE)) // token='NEWLINE' ) @@ -23256,7 +23177,7 @@ invalid_except_stmt_rule(Parser *p) Token * a; Token * newline_var; if ( - (a = _PyPegen_expect_token(p, 651)) // token='except' + (a = _PyPegen_expect_token(p, 656)) // token='except' && (newline_var = _PyPegen_expect_token(p, NEWLINE)) // token='NEWLINE' ) @@ -23281,14 +23202,14 @@ invalid_except_stmt_rule(Parser *p) } D(fprintf(stderr, "%*c> invalid_except_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'except' '*' (NEWLINE | ':')")); Token * _literal; - void *_tmp_222_var; + void *_tmp_223_var; Token * a; if ( - (a = _PyPegen_expect_token(p, 651)) // token='except' + (a = _PyPegen_expect_token(p, 656)) // token='except' && (_literal = _PyPegen_expect_token(p, 16)) // token='*' && - (_tmp_222_var = _tmp_222_rule(p)) // NEWLINE | ':' + (_tmp_223_var = _tmp_223_rule(p)) // NEWLINE | ':' ) { D(fprintf(stderr, "%*c+ invalid_except_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'except' '*' (NEWLINE | ':')")); @@ -23315,8 +23236,7 @@ static void * invalid_finally_stmt_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -23334,7 +23254,7 @@ invalid_finally_stmt_rule(Parser *p) Token * a; Token * newline_var; if ( - (a = _PyPegen_expect_token(p, 647)) // token='finally' + (a = _PyPegen_expect_token(p, 652)) // token='finally' && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && @@ -23369,8 +23289,7 @@ static void * invalid_except_stmt_indent_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -23391,11 +23310,11 @@ invalid_except_stmt_indent_rule(Parser *p) expr_ty expression_var; Token * newline_var; if ( - (a = _PyPegen_expect_token(p, 651)) // token='except' + (a = _PyPegen_expect_token(p, 656)) // token='except' && (expression_var = expression_rule(p)) // expression && - (_opt_var = _tmp_223_rule(p), !p->error_indicator) // ['as' NAME] + (_opt_var = _tmp_224_rule(p), !p->error_indicator) // ['as' NAME] && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && @@ -23427,7 +23346,7 @@ invalid_except_stmt_indent_rule(Parser *p) Token * a; Token * newline_var; if ( - (a = _PyPegen_expect_token(p, 651)) // token='except' + (a = _PyPegen_expect_token(p, 656)) // token='except' && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && @@ -23461,8 +23380,7 @@ static void * invalid_except_star_stmt_indent_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -23484,13 +23402,13 @@ invalid_except_star_stmt_indent_rule(Parser *p) expr_ty expression_var; Token * newline_var; if ( - (a = _PyPegen_expect_token(p, 651)) // token='except' + (a = _PyPegen_expect_token(p, 656)) // token='except' && (_literal = _PyPegen_expect_token(p, 16)) // token='*' && (expression_var = expression_rule(p)) // expression && - (_opt_var = _tmp_224_rule(p), !p->error_indicator) // ['as' NAME] + (_opt_var = _tmp_225_rule(p), !p->error_indicator) // ['as' NAME] && (_literal_1 = _PyPegen_expect_token(p, 11)) // token=':' && @@ -23525,8 +23443,7 @@ static void * invalid_match_stmt_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -23612,8 +23529,7 @@ static void * invalid_case_block_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -23705,8 +23621,7 @@ static void * invalid_as_pattern_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -23726,7 +23641,7 @@ invalid_as_pattern_rule(Parser *p) if ( (or_pattern_var = or_pattern_rule(p)) // or_pattern && - (_keyword = _PyPegen_expect_token(p, 654)) // token='as' + (_keyword = _PyPegen_expect_token(p, 659)) // token='as' && (a = _PyPegen_expect_soft_keyword(p, "_")) // soft_keyword='"_"' ) @@ -23756,7 +23671,7 @@ invalid_as_pattern_rule(Parser *p) if ( (or_pattern_var = or_pattern_rule(p)) // or_pattern && - (_keyword = _PyPegen_expect_token(p, 654)) // token='as' + (_keyword = _PyPegen_expect_token(p, 659)) // token='as' && _PyPegen_lookahead_with_name(0, _PyPegen_name_token, p) && @@ -23787,8 +23702,7 @@ static void * invalid_class_pattern_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -23838,8 +23752,7 @@ static asdl_pattern_seq* invalid_class_argument_pattern_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -23859,7 +23772,7 @@ invalid_class_argument_pattern_rule(Parser *p) asdl_pattern_seq* a; asdl_seq* keyword_patterns_var; if ( - (_opt_var = _tmp_225_rule(p), !p->error_indicator) // [positional_patterns ','] + (_opt_var = _tmp_226_rule(p), !p->error_indicator) // [positional_patterns ','] && (keyword_patterns_var = keyword_patterns_rule(p)) // keyword_patterns && @@ -23894,8 +23807,7 @@ static void * invalid_if_stmt_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -23913,7 +23825,7 @@ invalid_if_stmt_rule(Parser *p) expr_ty named_expression_var; Token * newline_var; if ( - (_keyword = _PyPegen_expect_token(p, 656)) // token='if' + (_keyword = _PyPegen_expect_token(p, 661)) // token='if' && (named_expression_var = named_expression_rule(p)) // named_expression && @@ -23944,7 +23856,7 @@ invalid_if_stmt_rule(Parser *p) expr_ty a_1; Token * newline_var; if ( - (a = _PyPegen_expect_token(p, 656)) // token='if' + (a = _PyPegen_expect_token(p, 661)) // token='if' && (a_1 = named_expression_rule(p)) // named_expression && @@ -23981,8 +23893,7 @@ static void * invalid_elif_stmt_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -24000,7 +23911,7 @@ invalid_elif_stmt_rule(Parser *p) expr_ty named_expression_var; Token * newline_var; if ( - (_keyword = _PyPegen_expect_token(p, 658)) // token='elif' + (_keyword = _PyPegen_expect_token(p, 663)) // token='elif' && (named_expression_var = named_expression_rule(p)) // named_expression && @@ -24031,7 +23942,7 @@ invalid_elif_stmt_rule(Parser *p) expr_ty named_expression_var; Token * newline_var; if ( - (a = _PyPegen_expect_token(p, 658)) // token='elif' + (a = _PyPegen_expect_token(p, 663)) // token='elif' && (named_expression_var = named_expression_rule(p)) // named_expression && @@ -24066,8 +23977,7 @@ static void * invalid_else_stmt_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -24085,7 +23995,7 @@ invalid_else_stmt_rule(Parser *p) Token * a; Token * newline_var; if ( - (a = _PyPegen_expect_token(p, 659)) // token='else' + (a = _PyPegen_expect_token(p, 664)) // token='else' && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && @@ -24120,8 +24030,7 @@ static void * invalid_while_stmt_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -24139,7 +24048,7 @@ invalid_while_stmt_rule(Parser *p) expr_ty named_expression_var; Token * newline_var; if ( - (_keyword = _PyPegen_expect_token(p, 661)) // token='while' + (_keyword = _PyPegen_expect_token(p, 666)) // token='while' && (named_expression_var = named_expression_rule(p)) // named_expression && @@ -24170,7 +24079,7 @@ invalid_while_stmt_rule(Parser *p) expr_ty named_expression_var; Token * newline_var; if ( - (a = _PyPegen_expect_token(p, 661)) // token='while' + (a = _PyPegen_expect_token(p, 666)) // token='while' && (named_expression_var = named_expression_rule(p)) // named_expression && @@ -24207,8 +24116,7 @@ static void * invalid_for_stmt_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -24230,13 +24138,13 @@ invalid_for_stmt_rule(Parser *p) expr_ty star_expressions_var; expr_ty star_targets_var; if ( - (_opt_var = _PyPegen_expect_token(p, 668), !p->error_indicator) // 'async'? + (_opt_var = _PyPegen_expect_token(p, 673), !p->error_indicator) // 'async'? && - (_keyword = _PyPegen_expect_token(p, 666)) // token='for' + (_keyword = _PyPegen_expect_token(p, 671)) // token='for' && (star_targets_var = star_targets_rule(p)) // star_targets && - (_keyword_1 = _PyPegen_expect_token(p, 667)) // token='in' + (_keyword_1 = _PyPegen_expect_token(p, 672)) // token='in' && (star_expressions_var = star_expressions_rule(p)) // star_expressions && @@ -24271,13 +24179,13 @@ invalid_for_stmt_rule(Parser *p) expr_ty star_expressions_var; expr_ty star_targets_var; if ( - (_opt_var = _PyPegen_expect_token(p, 668), !p->error_indicator) // 'async'? + (_opt_var = _PyPegen_expect_token(p, 673), !p->error_indicator) // 'async'? && - (a = _PyPegen_expect_token(p, 666)) // token='for' + (a = _PyPegen_expect_token(p, 671)) // token='for' && (star_targets_var = star_targets_rule(p)) // star_targets && - (_keyword = _PyPegen_expect_token(p, 667)) // token='in' + (_keyword = _PyPegen_expect_token(p, 672)) // token='in' && (star_expressions_var = star_expressions_rule(p)) // star_expressions && @@ -24308,13 +24216,12 @@ invalid_for_stmt_rule(Parser *p) } // invalid_def_raw: -// | 'async'? 'def' NAME '(' params? ')' ['->' expression] ':' NEWLINE !INDENT +// | 'async'? 'def' NAME type_params? '(' params? ')' ['->' expression] ':' NEWLINE !INDENT static void * invalid_def_raw_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -24322,12 +24229,12 @@ invalid_def_raw_rule(Parser *p) } void * _res = NULL; int _mark = p->mark; - { // 'async'? 'def' NAME '(' params? ')' ['->' expression] ':' NEWLINE !INDENT + { // 'async'? 'def' NAME type_params? '(' params? ')' ['->' expression] ':' NEWLINE !INDENT if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> invalid_def_raw[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'async'? 'def' NAME '(' params? ')' ['->' expression] ':' NEWLINE !INDENT")); + D(fprintf(stderr, "%*c> invalid_def_raw[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'async'? 'def' NAME type_params? '(' params? ')' ['->' expression] ':' NEWLINE !INDENT")); Token * _literal; Token * _literal_1; Token * _literal_2; @@ -24337,23 +24244,27 @@ invalid_def_raw_rule(Parser *p) UNUSED(_opt_var_1); // Silence compiler warnings void *_opt_var_2; UNUSED(_opt_var_2); // Silence compiler warnings + void *_opt_var_3; + UNUSED(_opt_var_3); // Silence compiler warnings Token * a; expr_ty name_var; Token * newline_var; if ( - (_opt_var = _PyPegen_expect_token(p, 668), !p->error_indicator) // 'async'? + (_opt_var = _PyPegen_expect_token(p, 673), !p->error_indicator) // 'async'? && - (a = _PyPegen_expect_token(p, 669)) // token='def' + (a = _PyPegen_expect_token(p, 674)) // token='def' && (name_var = _PyPegen_name_token(p)) // NAME && + (_opt_var_1 = type_params_rule(p), !p->error_indicator) // type_params? + && (_literal = _PyPegen_expect_token(p, 7)) // token='(' && - (_opt_var_1 = params_rule(p), !p->error_indicator) // params? + (_opt_var_2 = params_rule(p), !p->error_indicator) // params? && (_literal_1 = _PyPegen_expect_token(p, 8)) // token=')' && - (_opt_var_2 = _tmp_226_rule(p), !p->error_indicator) // ['->' expression] + (_opt_var_3 = _tmp_227_rule(p), !p->error_indicator) // ['->' expression] && (_literal_2 = _PyPegen_expect_token(p, 11)) // token=':' && @@ -24362,7 +24273,7 @@ invalid_def_raw_rule(Parser *p) _PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, INDENT) // token=INDENT ) { - D(fprintf(stderr, "%*c+ invalid_def_raw[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'async'? 'def' NAME '(' params? ')' ['->' expression] ':' NEWLINE !INDENT")); + D(fprintf(stderr, "%*c+ invalid_def_raw[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'async'? 'def' NAME type_params? '(' params? ')' ['->' expression] ':' NEWLINE !INDENT")); _res = RAISE_INDENTATION_ERROR ( "expected an indented block after function definition on line %d" , a -> lineno ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -24373,7 +24284,7 @@ invalid_def_raw_rule(Parser *p) } p->mark = _mark; D(fprintf(stderr, "%*c%s invalid_def_raw[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'async'? 'def' NAME '(' params? ')' ['->' expression] ':' NEWLINE !INDENT")); + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'async'? 'def' NAME type_params? '(' params? ')' ['->' expression] ':' NEWLINE !INDENT")); } _res = NULL; done: @@ -24382,14 +24293,13 @@ invalid_def_raw_rule(Parser *p) } // invalid_class_def_raw: -// | 'class' NAME ['(' arguments? ')'] NEWLINE -// | 'class' NAME ['(' arguments? ')'] ':' NEWLINE !INDENT +// | 'class' NAME type_params? ['(' arguments? ')'] NEWLINE +// | 'class' NAME type_params? ['(' arguments? ')'] ':' NEWLINE !INDENT static void * invalid_class_def_raw_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -24397,28 +24307,32 @@ invalid_class_def_raw_rule(Parser *p) } void * _res = NULL; int _mark = p->mark; - { // 'class' NAME ['(' arguments? ')'] NEWLINE + { // 'class' NAME type_params? ['(' arguments? ')'] NEWLINE if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> invalid_class_def_raw[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'class' NAME ['(' arguments? ')'] NEWLINE")); + D(fprintf(stderr, "%*c> invalid_class_def_raw[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'class' NAME type_params? ['(' arguments? ')'] NEWLINE")); Token * _keyword; void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings + void *_opt_var_1; + UNUSED(_opt_var_1); // Silence compiler warnings expr_ty name_var; Token * newline_var; if ( - (_keyword = _PyPegen_expect_token(p, 671)) // token='class' + (_keyword = _PyPegen_expect_token(p, 676)) // token='class' && (name_var = _PyPegen_name_token(p)) // NAME && - (_opt_var = _tmp_227_rule(p), !p->error_indicator) // ['(' arguments? ')'] + (_opt_var = type_params_rule(p), !p->error_indicator) // type_params? + && + (_opt_var_1 = _tmp_228_rule(p), !p->error_indicator) // ['(' arguments? ')'] && (newline_var = _PyPegen_expect_token(p, NEWLINE)) // token='NEWLINE' ) { - D(fprintf(stderr, "%*c+ invalid_class_def_raw[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'class' NAME ['(' arguments? ')'] NEWLINE")); + D(fprintf(stderr, "%*c+ invalid_class_def_raw[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'class' NAME type_params? ['(' arguments? ')'] NEWLINE")); _res = RAISE_SYNTAX_ERROR ( "expected ':'" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -24429,26 +24343,30 @@ invalid_class_def_raw_rule(Parser *p) } p->mark = _mark; D(fprintf(stderr, "%*c%s invalid_class_def_raw[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'class' NAME ['(' arguments? ')'] NEWLINE")); + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'class' NAME type_params? ['(' arguments? ')'] NEWLINE")); } - { // 'class' NAME ['(' arguments? ')'] ':' NEWLINE !INDENT + { // 'class' NAME type_params? ['(' arguments? ')'] ':' NEWLINE !INDENT if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> invalid_class_def_raw[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'class' NAME ['(' arguments? ')'] ':' NEWLINE !INDENT")); + D(fprintf(stderr, "%*c> invalid_class_def_raw[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'class' NAME type_params? ['(' arguments? ')'] ':' NEWLINE !INDENT")); Token * _literal; void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings + void *_opt_var_1; + UNUSED(_opt_var_1); // Silence compiler warnings Token * a; expr_ty name_var; Token * newline_var; if ( - (a = _PyPegen_expect_token(p, 671)) // token='class' + (a = _PyPegen_expect_token(p, 676)) // token='class' && (name_var = _PyPegen_name_token(p)) // NAME && - (_opt_var = _tmp_228_rule(p), !p->error_indicator) // ['(' arguments? ')'] + (_opt_var = type_params_rule(p), !p->error_indicator) // type_params? + && + (_opt_var_1 = _tmp_229_rule(p), !p->error_indicator) // ['(' arguments? ')'] && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && @@ -24457,7 +24375,7 @@ invalid_class_def_raw_rule(Parser *p) _PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, INDENT) // token=INDENT ) { - D(fprintf(stderr, "%*c+ invalid_class_def_raw[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'class' NAME ['(' arguments? ')'] ':' NEWLINE !INDENT")); + D(fprintf(stderr, "%*c+ invalid_class_def_raw[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'class' NAME type_params? ['(' arguments? ')'] ':' NEWLINE !INDENT")); _res = RAISE_INDENTATION_ERROR ( "expected an indented block after class definition on line %d" , a -> lineno ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -24468,7 +24386,7 @@ invalid_class_def_raw_rule(Parser *p) } p->mark = _mark; D(fprintf(stderr, "%*c%s invalid_class_def_raw[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'class' NAME ['(' arguments? ')'] ':' NEWLINE !INDENT")); + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'class' NAME type_params? ['(' arguments? ')'] ':' NEWLINE !INDENT")); } _res = NULL; done: @@ -24484,8 +24402,7 @@ static void * invalid_double_starred_kvpairs_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -24499,11 +24416,11 @@ invalid_double_starred_kvpairs_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_double_starred_kvpairs[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.double_starred_kvpair+ ',' invalid_kvpair")); - asdl_seq * _gather_229_var; + asdl_seq * _gather_230_var; Token * _literal; void *invalid_kvpair_var; if ( - (_gather_229_var = _gather_229_rule(p)) // ','.double_starred_kvpair+ + (_gather_230_var = _gather_230_rule(p)) // ','.double_starred_kvpair+ && (_literal = _PyPegen_expect_token(p, 12)) // token=',' && @@ -24511,7 +24428,7 @@ invalid_double_starred_kvpairs_rule(Parser *p) ) { D(fprintf(stderr, "%*c+ invalid_double_starred_kvpairs[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.double_starred_kvpair+ ',' invalid_kvpair")); - _res = _PyPegen_dummy_name(p, _gather_229_var, _literal, invalid_kvpair_var); + _res = _PyPegen_dummy_name(p, _gather_230_var, _literal, invalid_kvpair_var); goto done; } p->mark = _mark; @@ -24564,7 +24481,7 @@ invalid_double_starred_kvpairs_rule(Parser *p) && (a = _PyPegen_expect_token(p, 11)) // token=':' && - _PyPegen_lookahead(1, _tmp_231_rule, p) + _PyPegen_lookahead(1, _tmp_232_rule, p) ) { D(fprintf(stderr, "%*c+ invalid_double_starred_kvpairs[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ':' &('}' | ',')")); @@ -24594,8 +24511,7 @@ static void * invalid_kvpair_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -24675,7 +24591,7 @@ invalid_kvpair_rule(Parser *p) && (a = _PyPegen_expect_token(p, 11)) // token=':' && - _PyPegen_lookahead(1, _tmp_232_rule, p) + _PyPegen_lookahead(1, _tmp_233_rule, p) ) { D(fprintf(stderr, "%*c+ invalid_kvpair[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ':' &('}' | ',')")); @@ -24702,8 +24618,7 @@ static void * invalid_starred_expression_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -24766,8 +24681,7 @@ static void * invalid_replacement_field_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -24893,7 +24807,7 @@ invalid_replacement_field_rule(Parser *p) if ( (_literal = _PyPegen_expect_token(p, 25)) // token='{' && - _PyPegen_lookahead(0, _tmp_233_rule, p) + _PyPegen_lookahead(0, _tmp_234_rule, p) ) { D(fprintf(stderr, "%*c+ invalid_replacement_field[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' !(yield_expr | star_expressions)")); @@ -24916,13 +24830,13 @@ invalid_replacement_field_rule(Parser *p) } D(fprintf(stderr, "%*c> invalid_replacement_field[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{' (yield_expr | star_expressions) !('=' | '!' | ':' | '}')")); Token * _literal; - void *_tmp_234_var; + void *_tmp_235_var; if ( (_literal = _PyPegen_expect_token(p, 25)) // token='{' && - (_tmp_234_var = _tmp_234_rule(p)) // yield_expr | star_expressions + (_tmp_235_var = _tmp_235_rule(p)) // yield_expr | star_expressions && - _PyPegen_lookahead(0, _tmp_235_rule, p) + _PyPegen_lookahead(0, _tmp_236_rule, p) ) { D(fprintf(stderr, "%*c+ invalid_replacement_field[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' (yield_expr | star_expressions) !('=' | '!' | ':' | '}')")); @@ -24946,15 +24860,15 @@ invalid_replacement_field_rule(Parser *p) D(fprintf(stderr, "%*c> invalid_replacement_field[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{' (yield_expr | star_expressions) '=' !('!' | ':' | '}')")); Token * _literal; Token * _literal_1; - void *_tmp_236_var; + void *_tmp_237_var; if ( (_literal = _PyPegen_expect_token(p, 25)) // token='{' && - (_tmp_236_var = _tmp_236_rule(p)) // yield_expr | star_expressions + (_tmp_237_var = _tmp_237_rule(p)) // yield_expr | star_expressions && (_literal_1 = _PyPegen_expect_token(p, 22)) // token='=' && - _PyPegen_lookahead(0, _tmp_237_rule, p) + _PyPegen_lookahead(0, _tmp_238_rule, p) ) { D(fprintf(stderr, "%*c+ invalid_replacement_field[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' (yield_expr | star_expressions) '=' !('!' | ':' | '}')")); @@ -24979,12 +24893,12 @@ invalid_replacement_field_rule(Parser *p) Token * _literal; void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings - void *_tmp_238_var; + void *_tmp_239_var; void *invalid_conversion_character_var; if ( (_literal = _PyPegen_expect_token(p, 25)) // token='{' && - (_tmp_238_var = _tmp_238_rule(p)) // yield_expr | star_expressions + (_tmp_239_var = _tmp_239_rule(p)) // yield_expr | star_expressions && (_opt_var = _PyPegen_expect_token(p, 22), !p->error_indicator) // '='? && @@ -24992,7 +24906,7 @@ invalid_replacement_field_rule(Parser *p) ) { D(fprintf(stderr, "%*c+ invalid_replacement_field[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' (yield_expr | star_expressions) '='? invalid_conversion_character")); - _res = _PyPegen_dummy_name(p, _literal, _tmp_238_var, _opt_var, invalid_conversion_character_var); + _res = _PyPegen_dummy_name(p, _literal, _tmp_239_var, _opt_var, invalid_conversion_character_var); goto done; } p->mark = _mark; @@ -25010,17 +24924,17 @@ invalid_replacement_field_rule(Parser *p) UNUSED(_opt_var); // Silence compiler warnings void *_opt_var_1; UNUSED(_opt_var_1); // Silence compiler warnings - void *_tmp_239_var; + void *_tmp_240_var; if ( (_literal = _PyPegen_expect_token(p, 25)) // token='{' && - (_tmp_239_var = _tmp_239_rule(p)) // yield_expr | star_expressions + (_tmp_240_var = _tmp_240_rule(p)) // yield_expr | star_expressions && (_opt_var = _PyPegen_expect_token(p, 22), !p->error_indicator) // '='? && - (_opt_var_1 = _tmp_240_rule(p), !p->error_indicator) // ['!' NAME] + (_opt_var_1 = _tmp_241_rule(p), !p->error_indicator) // ['!' NAME] && - _PyPegen_lookahead(0, _tmp_241_rule, p) + _PyPegen_lookahead(0, _tmp_242_rule, p) ) { D(fprintf(stderr, "%*c+ invalid_replacement_field[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' (yield_expr | star_expressions) '='? ['!' NAME] !(':' | '}')")); @@ -25044,24 +24958,24 @@ invalid_replacement_field_rule(Parser *p) D(fprintf(stderr, "%*c> invalid_replacement_field[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{' (yield_expr | star_expressions) '='? ['!' NAME] ':' fstring_format_spec* !'}'")); Token * _literal; Token * _literal_1; - asdl_seq * _loop0_244_var; + asdl_seq * _loop0_245_var; void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings void *_opt_var_1; UNUSED(_opt_var_1); // Silence compiler warnings - void *_tmp_242_var; + void *_tmp_243_var; if ( (_literal = _PyPegen_expect_token(p, 25)) // token='{' && - (_tmp_242_var = _tmp_242_rule(p)) // yield_expr | star_expressions + (_tmp_243_var = _tmp_243_rule(p)) // yield_expr | star_expressions && (_opt_var = _PyPegen_expect_token(p, 22), !p->error_indicator) // '='? && - (_opt_var_1 = _tmp_243_rule(p), !p->error_indicator) // ['!' NAME] + (_opt_var_1 = _tmp_244_rule(p), !p->error_indicator) // ['!' NAME] && (_literal_1 = _PyPegen_expect_token(p, 11)) // token=':' && - (_loop0_244_var = _loop0_244_rule(p)) // fstring_format_spec* + (_loop0_245_var = _loop0_245_rule(p)) // fstring_format_spec* && _PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, 26) // token='}' ) @@ -25090,15 +25004,15 @@ invalid_replacement_field_rule(Parser *p) UNUSED(_opt_var); // Silence compiler warnings void *_opt_var_1; UNUSED(_opt_var_1); // Silence compiler warnings - void *_tmp_245_var; + void *_tmp_246_var; if ( (_literal = _PyPegen_expect_token(p, 25)) // token='{' && - (_tmp_245_var = _tmp_245_rule(p)) // yield_expr | star_expressions + (_tmp_246_var = _tmp_246_rule(p)) // yield_expr | star_expressions && (_opt_var = _PyPegen_expect_token(p, 22), !p->error_indicator) // '='? && - (_opt_var_1 = _tmp_246_rule(p), !p->error_indicator) // ['!' NAME] + (_opt_var_1 = _tmp_247_rule(p), !p->error_indicator) // ['!' NAME] && _PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, 26) // token='}' ) @@ -25127,8 +25041,7 @@ static void * invalid_conversion_character_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -25146,7 +25059,7 @@ invalid_conversion_character_rule(Parser *p) if ( (_literal = _PyPegen_expect_token(p, 54)) // token='!' && - _PyPegen_lookahead(1, _tmp_247_rule, p) + _PyPegen_lookahead(1, _tmp_248_rule, p) ) { D(fprintf(stderr, "%*c+ invalid_conversion_character[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'!' &(':' | '}')")); @@ -25199,8 +25112,7 @@ static asdl_seq * _loop0_1_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -25267,8 +25179,7 @@ static asdl_seq * _loop0_2_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -25330,81 +25241,12 @@ _loop0_2_rule(Parser *p) return _seq; } -// _loop0_3: fstring_middle +// _loop1_3: statement static asdl_seq * -_loop0_3_rule(Parser *p) +_loop1_3_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void *_res = NULL; - int _mark = p->mark; - void **_children = PyMem_Malloc(sizeof(void *)); - if (!_children) { - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - Py_ssize_t _children_capacity = 1; - Py_ssize_t _n = 0; - { // fstring_middle - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _loop0_3[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "fstring_middle")); - expr_ty fstring_middle_var; - while ( - (fstring_middle_var = fstring_middle_rule(p)) // fstring_middle - ) - { - _res = fstring_middle_var; - if (_n == _children_capacity) { - _children_capacity *= 2; - void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); - if (!_new_children) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - _children = _new_children; - } - _children[_n++] = _res; - _mark = p->mark; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_3[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "fstring_middle")); - } - asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); - if (!_seq) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); - PyMem_Free(_children); - p->level--; - return _seq; -} - -// _loop1_4: statement -static asdl_seq * -_loop1_4_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -25426,7 +25268,7 @@ _loop1_4_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_4[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "statement")); + D(fprintf(stderr, "%*c> _loop1_3[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "statement")); asdl_stmt_seq* statement_var; while ( (statement_var = statement_rule(p)) // statement @@ -25449,7 +25291,7 @@ _loop1_4_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_4[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_3[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "statement")); } if (_n == 0 || p->error_indicator) { @@ -25471,13 +25313,12 @@ _loop1_4_rule(Parser *p) return _seq; } -// _loop0_6: ';' simple_stmt +// _loop0_5: ';' simple_stmt static asdl_seq * -_loop0_6_rule(Parser *p) +_loop0_5_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -25499,7 +25340,7 @@ _loop0_6_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_6[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "';' simple_stmt")); + D(fprintf(stderr, "%*c> _loop0_5[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "';' simple_stmt")); Token * _literal; stmt_ty elem; while ( @@ -25531,7 +25372,7 @@ _loop0_6_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_6[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_5[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "';' simple_stmt")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -25548,13 +25389,12 @@ _loop0_6_rule(Parser *p) return _seq; } -// _gather_5: simple_stmt _loop0_6 +// _gather_4: simple_stmt _loop0_5 static asdl_seq * -_gather_5_rule(Parser *p) +_gather_4_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -25562,27 +25402,27 @@ _gather_5_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // simple_stmt _loop0_6 + { // simple_stmt _loop0_5 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_5[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "simple_stmt _loop0_6")); + D(fprintf(stderr, "%*c> _gather_4[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "simple_stmt _loop0_5")); stmt_ty elem; asdl_seq * seq; if ( (elem = simple_stmt_rule(p)) // simple_stmt && - (seq = _loop0_6_rule(p)) // _loop0_6 + (seq = _loop0_5_rule(p)) // _loop0_5 ) { - D(fprintf(stderr, "%*c+ _gather_5[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "simple_stmt _loop0_6")); + D(fprintf(stderr, "%*c+ _gather_4[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "simple_stmt _loop0_5")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_5[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "simple_stmt _loop0_6")); + D(fprintf(stderr, "%*c%s _gather_4[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "simple_stmt _loop0_5")); } _res = NULL; done: @@ -25590,13 +25430,12 @@ _gather_5_rule(Parser *p) return _res; } -// _tmp_7: 'import' | 'from' +// _tmp_6: 'import' | 'from' static void * -_tmp_7_rule(Parser *p) +_tmp_6_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -25609,18 +25448,18 @@ _tmp_7_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_7[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'import'")); + D(fprintf(stderr, "%*c> _tmp_6[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'import'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 617)) // token='import' + (_keyword = _PyPegen_expect_token(p, 620)) // token='import' ) { - D(fprintf(stderr, "%*c+ _tmp_7[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'import'")); + D(fprintf(stderr, "%*c+ _tmp_6[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'import'")); _res = _keyword; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_7[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_6[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'import'")); } { // 'from' @@ -25628,18 +25467,18 @@ _tmp_7_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_7[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'from'")); + D(fprintf(stderr, "%*c> _tmp_6[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'from'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 618)) // token='from' + (_keyword = _PyPegen_expect_token(p, 621)) // token='from' ) { - D(fprintf(stderr, "%*c+ _tmp_7[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'from'")); + D(fprintf(stderr, "%*c+ _tmp_6[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'from'")); _res = _keyword; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_7[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_6[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'from'")); } _res = NULL; @@ -25648,13 +25487,12 @@ _tmp_7_rule(Parser *p) return _res; } -// _tmp_8: 'def' | '@' | 'async' +// _tmp_7: 'def' | '@' | 'async' static void * -_tmp_8_rule(Parser *p) +_tmp_7_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -25667,18 +25505,18 @@ _tmp_8_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_8[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'def'")); + D(fprintf(stderr, "%*c> _tmp_7[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'def'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 669)) // token='def' + (_keyword = _PyPegen_expect_token(p, 674)) // token='def' ) { - D(fprintf(stderr, "%*c+ _tmp_8[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'def'")); + D(fprintf(stderr, "%*c+ _tmp_7[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'def'")); _res = _keyword; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_8[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_7[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'def'")); } { // '@' @@ -25686,18 +25524,18 @@ _tmp_8_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_8[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'@'")); + D(fprintf(stderr, "%*c> _tmp_7[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'@'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 49)) // token='@' ) { - D(fprintf(stderr, "%*c+ _tmp_8[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'@'")); + D(fprintf(stderr, "%*c+ _tmp_7[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'@'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_8[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_7[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'@'")); } { // 'async' @@ -25705,18 +25543,18 @@ _tmp_8_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_8[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'async'")); + D(fprintf(stderr, "%*c> _tmp_7[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'async'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 668)) // token='async' + (_keyword = _PyPegen_expect_token(p, 673)) // token='async' ) { - D(fprintf(stderr, "%*c+ _tmp_8[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'async'")); + D(fprintf(stderr, "%*c+ _tmp_7[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'async'")); _res = _keyword; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_8[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_7[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'async'")); } _res = NULL; @@ -25725,13 +25563,12 @@ _tmp_8_rule(Parser *p) return _res; } -// _tmp_9: 'class' | '@' +// _tmp_8: 'class' | '@' static void * -_tmp_9_rule(Parser *p) +_tmp_8_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -25744,18 +25581,18 @@ _tmp_9_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_9[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'class'")); + D(fprintf(stderr, "%*c> _tmp_8[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'class'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 671)) // token='class' + (_keyword = _PyPegen_expect_token(p, 676)) // token='class' ) { - D(fprintf(stderr, "%*c+ _tmp_9[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'class'")); + D(fprintf(stderr, "%*c+ _tmp_8[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'class'")); _res = _keyword; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_9[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_8[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'class'")); } { // '@' @@ -25763,18 +25600,18 @@ _tmp_9_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_9[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'@'")); + D(fprintf(stderr, "%*c> _tmp_8[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'@'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 49)) // token='@' ) { - D(fprintf(stderr, "%*c+ _tmp_9[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'@'")); + D(fprintf(stderr, "%*c+ _tmp_8[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'@'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_9[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_8[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'@'")); } _res = NULL; @@ -25783,13 +25620,12 @@ _tmp_9_rule(Parser *p) return _res; } -// _tmp_10: 'with' | 'async' +// _tmp_9: 'with' | 'async' static void * -_tmp_10_rule(Parser *p) +_tmp_9_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -25802,18 +25638,18 @@ _tmp_10_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_10[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'with'")); + D(fprintf(stderr, "%*c> _tmp_9[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'with'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 629)) // token='with' + (_keyword = _PyPegen_expect_token(p, 634)) // token='with' ) { - D(fprintf(stderr, "%*c+ _tmp_10[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'with'")); + D(fprintf(stderr, "%*c+ _tmp_9[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'with'")); _res = _keyword; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_10[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_9[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'with'")); } { // 'async' @@ -25821,18 +25657,18 @@ _tmp_10_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_10[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'async'")); + D(fprintf(stderr, "%*c> _tmp_9[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'async'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 668)) // token='async' + (_keyword = _PyPegen_expect_token(p, 673)) // token='async' ) { - D(fprintf(stderr, "%*c+ _tmp_10[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'async'")); + D(fprintf(stderr, "%*c+ _tmp_9[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'async'")); _res = _keyword; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_10[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_9[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'async'")); } _res = NULL; @@ -25841,13 +25677,12 @@ _tmp_10_rule(Parser *p) return _res; } -// _tmp_11: 'for' | 'async' +// _tmp_10: 'for' | 'async' static void * -_tmp_11_rule(Parser *p) +_tmp_10_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -25860,18 +25695,18 @@ _tmp_11_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_11[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'for'")); + D(fprintf(stderr, "%*c> _tmp_10[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'for'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 666)) // token='for' + (_keyword = _PyPegen_expect_token(p, 671)) // token='for' ) { - D(fprintf(stderr, "%*c+ _tmp_11[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'for'")); + D(fprintf(stderr, "%*c+ _tmp_10[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'for'")); _res = _keyword; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_11[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_10[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'for'")); } { // 'async' @@ -25879,18 +25714,18 @@ _tmp_11_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_11[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'async'")); + D(fprintf(stderr, "%*c> _tmp_10[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'async'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 668)) // token='async' + (_keyword = _PyPegen_expect_token(p, 673)) // token='async' ) { - D(fprintf(stderr, "%*c+ _tmp_11[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'async'")); + D(fprintf(stderr, "%*c+ _tmp_10[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'async'")); _res = _keyword; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_11[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_10[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'async'")); } _res = NULL; @@ -25899,13 +25734,12 @@ _tmp_11_rule(Parser *p) return _res; } -// _tmp_12: '=' annotated_rhs +// _tmp_11: '=' annotated_rhs static void * -_tmp_12_rule(Parser *p) +_tmp_11_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -25918,7 +25752,7 @@ _tmp_12_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_12[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'=' annotated_rhs")); + D(fprintf(stderr, "%*c> _tmp_11[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'=' annotated_rhs")); Token * _literal; expr_ty d; if ( @@ -25927,7 +25761,7 @@ _tmp_12_rule(Parser *p) (d = annotated_rhs_rule(p)) // annotated_rhs ) { - D(fprintf(stderr, "%*c+ _tmp_12[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'=' annotated_rhs")); + D(fprintf(stderr, "%*c+ _tmp_11[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'=' annotated_rhs")); _res = d; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -25937,7 +25771,7 @@ _tmp_12_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_12[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_11[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'=' annotated_rhs")); } _res = NULL; @@ -25946,13 +25780,12 @@ _tmp_12_rule(Parser *p) return _res; } -// _tmp_13: '(' single_target ')' | single_subscript_attribute_target +// _tmp_12: '(' single_target ')' | single_subscript_attribute_target static void * -_tmp_13_rule(Parser *p) +_tmp_12_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -25965,7 +25798,7 @@ _tmp_13_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_13[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' single_target ')'")); + D(fprintf(stderr, "%*c> _tmp_12[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' single_target ')'")); Token * _literal; Token * _literal_1; expr_ty b; @@ -25977,7 +25810,7 @@ _tmp_13_rule(Parser *p) (_literal_1 = _PyPegen_expect_token(p, 8)) // token=')' ) { - D(fprintf(stderr, "%*c+ _tmp_13[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' single_target ')'")); + D(fprintf(stderr, "%*c+ _tmp_12[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' single_target ')'")); _res = b; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -25987,7 +25820,7 @@ _tmp_13_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_13[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_12[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'(' single_target ')'")); } { // single_subscript_attribute_target @@ -25995,18 +25828,18 @@ _tmp_13_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_13[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "single_subscript_attribute_target")); + D(fprintf(stderr, "%*c> _tmp_12[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "single_subscript_attribute_target")); expr_ty single_subscript_attribute_target_var; if ( (single_subscript_attribute_target_var = single_subscript_attribute_target_rule(p)) // single_subscript_attribute_target ) { - D(fprintf(stderr, "%*c+ _tmp_13[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "single_subscript_attribute_target")); + D(fprintf(stderr, "%*c+ _tmp_12[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "single_subscript_attribute_target")); _res = single_subscript_attribute_target_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_13[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_12[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "single_subscript_attribute_target")); } _res = NULL; @@ -26015,13 +25848,12 @@ _tmp_13_rule(Parser *p) return _res; } -// _tmp_14: '=' annotated_rhs +// _tmp_13: '=' annotated_rhs static void * -_tmp_14_rule(Parser *p) +_tmp_13_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -26034,7 +25866,7 @@ _tmp_14_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_14[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'=' annotated_rhs")); + D(fprintf(stderr, "%*c> _tmp_13[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'=' annotated_rhs")); Token * _literal; expr_ty d; if ( @@ -26043,7 +25875,7 @@ _tmp_14_rule(Parser *p) (d = annotated_rhs_rule(p)) // annotated_rhs ) { - D(fprintf(stderr, "%*c+ _tmp_14[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'=' annotated_rhs")); + D(fprintf(stderr, "%*c+ _tmp_13[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'=' annotated_rhs")); _res = d; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -26053,7 +25885,7 @@ _tmp_14_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_14[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_13[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'=' annotated_rhs")); } _res = NULL; @@ -26062,13 +25894,12 @@ _tmp_14_rule(Parser *p) return _res; } -// _loop1_15: (star_targets '=') +// _loop1_14: (star_targets '=') static asdl_seq * -_loop1_15_rule(Parser *p) +_loop1_14_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -26090,13 +25921,13 @@ _loop1_15_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_15[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(star_targets '=')")); - void *_tmp_248_var; + D(fprintf(stderr, "%*c> _loop1_14[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(star_targets '=')")); + void *_tmp_249_var; while ( - (_tmp_248_var = _tmp_248_rule(p)) // star_targets '=' + (_tmp_249_var = _tmp_249_rule(p)) // star_targets '=' ) { - _res = _tmp_248_var; + _res = _tmp_249_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -26113,7 +25944,7 @@ _loop1_15_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_15[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_14[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(star_targets '=')")); } if (_n == 0 || p->error_indicator) { @@ -26135,13 +25966,12 @@ _loop1_15_rule(Parser *p) return _seq; } -// _tmp_16: yield_expr | star_expressions +// _tmp_15: yield_expr | star_expressions static void * -_tmp_16_rule(Parser *p) +_tmp_15_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -26154,18 +25984,18 @@ _tmp_16_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_16[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); + D(fprintf(stderr, "%*c> _tmp_15[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); expr_ty yield_expr_var; if ( (yield_expr_var = yield_expr_rule(p)) // yield_expr ) { - D(fprintf(stderr, "%*c+ _tmp_16[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr")); + D(fprintf(stderr, "%*c+ _tmp_15[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr")); _res = yield_expr_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_16[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_15[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "yield_expr")); } { // star_expressions @@ -26173,18 +26003,18 @@ _tmp_16_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_16[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions")); + D(fprintf(stderr, "%*c> _tmp_15[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions")); expr_ty star_expressions_var; if ( (star_expressions_var = star_expressions_rule(p)) // star_expressions ) { - D(fprintf(stderr, "%*c+ _tmp_16[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions")); + D(fprintf(stderr, "%*c+ _tmp_15[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions")); _res = star_expressions_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_16[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_15[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_expressions")); } _res = NULL; @@ -26193,13 +26023,12 @@ _tmp_16_rule(Parser *p) return _res; } -// _tmp_17: yield_expr | star_expressions +// _tmp_16: yield_expr | star_expressions static void * -_tmp_17_rule(Parser *p) +_tmp_16_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -26212,18 +26041,18 @@ _tmp_17_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_17[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); + D(fprintf(stderr, "%*c> _tmp_16[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); expr_ty yield_expr_var; if ( (yield_expr_var = yield_expr_rule(p)) // yield_expr ) { - D(fprintf(stderr, "%*c+ _tmp_17[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr")); + D(fprintf(stderr, "%*c+ _tmp_16[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr")); _res = yield_expr_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_17[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_16[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "yield_expr")); } { // star_expressions @@ -26231,18 +26060,18 @@ _tmp_17_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_17[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions")); + D(fprintf(stderr, "%*c> _tmp_16[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions")); expr_ty star_expressions_var; if ( (star_expressions_var = star_expressions_rule(p)) // star_expressions ) { - D(fprintf(stderr, "%*c+ _tmp_17[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions")); + D(fprintf(stderr, "%*c+ _tmp_16[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions")); _res = star_expressions_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_17[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_16[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_expressions")); } _res = NULL; @@ -26251,13 +26080,12 @@ _tmp_17_rule(Parser *p) return _res; } -// _tmp_18: 'from' expression +// _tmp_17: 'from' expression static void * -_tmp_18_rule(Parser *p) +_tmp_17_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -26270,16 +26098,16 @@ _tmp_18_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_18[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'from' expression")); + D(fprintf(stderr, "%*c> _tmp_17[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'from' expression")); Token * _keyword; expr_ty z; if ( - (_keyword = _PyPegen_expect_token(p, 618)) // token='from' + (_keyword = _PyPegen_expect_token(p, 621)) // token='from' && (z = expression_rule(p)) // expression ) { - D(fprintf(stderr, "%*c+ _tmp_18[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'from' expression")); + D(fprintf(stderr, "%*c+ _tmp_17[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'from' expression")); _res = z; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -26289,7 +26117,7 @@ _tmp_18_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_18[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_17[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'from' expression")); } _res = NULL; @@ -26298,13 +26126,12 @@ _tmp_18_rule(Parser *p) return _res; } -// _loop0_20: ',' NAME +// _loop0_19: ',' NAME static asdl_seq * -_loop0_20_rule(Parser *p) +_loop0_19_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -26326,7 +26153,7 @@ _loop0_20_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_20[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' NAME")); + D(fprintf(stderr, "%*c> _loop0_19[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' NAME")); Token * _literal; expr_ty elem; while ( @@ -26358,7 +26185,7 @@ _loop0_20_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_20[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_19[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' NAME")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -26375,13 +26202,12 @@ _loop0_20_rule(Parser *p) return _seq; } -// _gather_19: NAME _loop0_20 +// _gather_18: NAME _loop0_19 static asdl_seq * -_gather_19_rule(Parser *p) +_gather_18_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -26389,27 +26215,27 @@ _gather_19_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // NAME _loop0_20 + { // NAME _loop0_19 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_19[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME _loop0_20")); + D(fprintf(stderr, "%*c> _gather_18[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME _loop0_19")); expr_ty elem; asdl_seq * seq; if ( (elem = _PyPegen_name_token(p)) // NAME && - (seq = _loop0_20_rule(p)) // _loop0_20 + (seq = _loop0_19_rule(p)) // _loop0_19 ) { - D(fprintf(stderr, "%*c+ _gather_19[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME _loop0_20")); + D(fprintf(stderr, "%*c+ _gather_18[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME _loop0_19")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_19[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "NAME _loop0_20")); + D(fprintf(stderr, "%*c%s _gather_18[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "NAME _loop0_19")); } _res = NULL; done: @@ -26417,13 +26243,12 @@ _gather_19_rule(Parser *p) return _res; } -// _loop0_22: ',' NAME +// _loop0_21: ',' NAME static asdl_seq * -_loop0_22_rule(Parser *p) +_loop0_21_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -26445,7 +26270,7 @@ _loop0_22_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_22[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' NAME")); + D(fprintf(stderr, "%*c> _loop0_21[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' NAME")); Token * _literal; expr_ty elem; while ( @@ -26477,7 +26302,7 @@ _loop0_22_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_22[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_21[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' NAME")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -26494,13 +26319,12 @@ _loop0_22_rule(Parser *p) return _seq; } -// _gather_21: NAME _loop0_22 +// _gather_20: NAME _loop0_21 static asdl_seq * -_gather_21_rule(Parser *p) +_gather_20_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -26508,27 +26332,27 @@ _gather_21_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // NAME _loop0_22 + { // NAME _loop0_21 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_21[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME _loop0_22")); + D(fprintf(stderr, "%*c> _gather_20[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME _loop0_21")); expr_ty elem; asdl_seq * seq; if ( (elem = _PyPegen_name_token(p)) // NAME && - (seq = _loop0_22_rule(p)) // _loop0_22 + (seq = _loop0_21_rule(p)) // _loop0_21 ) { - D(fprintf(stderr, "%*c+ _gather_21[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME _loop0_22")); + D(fprintf(stderr, "%*c+ _gather_20[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME _loop0_21")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_21[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "NAME _loop0_22")); + D(fprintf(stderr, "%*c%s _gather_20[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "NAME _loop0_21")); } _res = NULL; done: @@ -26536,13 +26360,12 @@ _gather_21_rule(Parser *p) return _res; } -// _tmp_23: ';' | NEWLINE +// _tmp_22: ';' | NEWLINE static void * -_tmp_23_rule(Parser *p) +_tmp_22_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -26555,18 +26378,18 @@ _tmp_23_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_23[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "';'")); + D(fprintf(stderr, "%*c> _tmp_22[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "';'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 13)) // token=';' ) { - D(fprintf(stderr, "%*c+ _tmp_23[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "';'")); + D(fprintf(stderr, "%*c+ _tmp_22[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "';'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_23[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_22[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "';'")); } { // NEWLINE @@ -26574,18 +26397,18 @@ _tmp_23_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_23[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NEWLINE")); + D(fprintf(stderr, "%*c> _tmp_22[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NEWLINE")); Token * newline_var; if ( (newline_var = _PyPegen_expect_token(p, NEWLINE)) // token='NEWLINE' ) { - D(fprintf(stderr, "%*c+ _tmp_23[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NEWLINE")); + D(fprintf(stderr, "%*c+ _tmp_22[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NEWLINE")); _res = newline_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_23[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_22[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "NEWLINE")); } _res = NULL; @@ -26594,13 +26417,12 @@ _tmp_23_rule(Parser *p) return _res; } -// _tmp_24: ',' expression +// _tmp_23: ',' expression static void * -_tmp_24_rule(Parser *p) +_tmp_23_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -26613,7 +26435,7 @@ _tmp_24_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_24[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression")); + D(fprintf(stderr, "%*c> _tmp_23[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression")); Token * _literal; expr_ty z; if ( @@ -26622,7 +26444,7 @@ _tmp_24_rule(Parser *p) (z = expression_rule(p)) // expression ) { - D(fprintf(stderr, "%*c+ _tmp_24[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' expression")); + D(fprintf(stderr, "%*c+ _tmp_23[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' expression")); _res = z; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -26632,7 +26454,7 @@ _tmp_24_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_24[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_23[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' expression")); } _res = NULL; @@ -26641,13 +26463,12 @@ _tmp_24_rule(Parser *p) return _res; } -// _loop0_25: ('.' | '...') +// _loop0_24: ('.' | '...') static asdl_seq * -_loop0_25_rule(Parser *p) +_loop0_24_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -26669,13 +26490,13 @@ _loop0_25_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_25[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('.' | '...')")); - void *_tmp_249_var; + D(fprintf(stderr, "%*c> _loop0_24[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('.' | '...')")); + void *_tmp_250_var; while ( - (_tmp_249_var = _tmp_249_rule(p)) // '.' | '...' + (_tmp_250_var = _tmp_250_rule(p)) // '.' | '...' ) { - _res = _tmp_249_var; + _res = _tmp_250_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -26692,7 +26513,7 @@ _loop0_25_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_25[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_24[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "('.' | '...')")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -26709,13 +26530,12 @@ _loop0_25_rule(Parser *p) return _seq; } -// _loop1_26: ('.' | '...') +// _loop1_25: ('.' | '...') static asdl_seq * -_loop1_26_rule(Parser *p) +_loop1_25_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -26737,13 +26557,13 @@ _loop1_26_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_26[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('.' | '...')")); - void *_tmp_250_var; + D(fprintf(stderr, "%*c> _loop1_25[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('.' | '...')")); + void *_tmp_251_var; while ( - (_tmp_250_var = _tmp_250_rule(p)) // '.' | '...' + (_tmp_251_var = _tmp_251_rule(p)) // '.' | '...' ) { - _res = _tmp_250_var; + _res = _tmp_251_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -26760,7 +26580,7 @@ _loop1_26_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_26[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_25[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "('.' | '...')")); } if (_n == 0 || p->error_indicator) { @@ -26782,13 +26602,12 @@ _loop1_26_rule(Parser *p) return _seq; } -// _loop0_28: ',' import_from_as_name +// _loop0_27: ',' import_from_as_name static asdl_seq * -_loop0_28_rule(Parser *p) +_loop0_27_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -26810,7 +26629,7 @@ _loop0_28_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_28[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' import_from_as_name")); + D(fprintf(stderr, "%*c> _loop0_27[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' import_from_as_name")); Token * _literal; alias_ty elem; while ( @@ -26842,7 +26661,7 @@ _loop0_28_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_28[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_27[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' import_from_as_name")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -26859,13 +26678,12 @@ _loop0_28_rule(Parser *p) return _seq; } -// _gather_27: import_from_as_name _loop0_28 +// _gather_26: import_from_as_name _loop0_27 static asdl_seq * -_gather_27_rule(Parser *p) +_gather_26_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -26873,27 +26691,27 @@ _gather_27_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // import_from_as_name _loop0_28 + { // import_from_as_name _loop0_27 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_27[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "import_from_as_name _loop0_28")); + D(fprintf(stderr, "%*c> _gather_26[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "import_from_as_name _loop0_27")); alias_ty elem; asdl_seq * seq; if ( (elem = import_from_as_name_rule(p)) // import_from_as_name && - (seq = _loop0_28_rule(p)) // _loop0_28 + (seq = _loop0_27_rule(p)) // _loop0_27 ) { - D(fprintf(stderr, "%*c+ _gather_27[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "import_from_as_name _loop0_28")); + D(fprintf(stderr, "%*c+ _gather_26[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "import_from_as_name _loop0_27")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_27[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "import_from_as_name _loop0_28")); + D(fprintf(stderr, "%*c%s _gather_26[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "import_from_as_name _loop0_27")); } _res = NULL; done: @@ -26901,13 +26719,12 @@ _gather_27_rule(Parser *p) return _res; } -// _tmp_29: 'as' NAME +// _tmp_28: 'as' NAME static void * -_tmp_29_rule(Parser *p) +_tmp_28_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -26920,16 +26737,16 @@ _tmp_29_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_29[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); + D(fprintf(stderr, "%*c> _tmp_28[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); Token * _keyword; expr_ty z; if ( - (_keyword = _PyPegen_expect_token(p, 654)) // token='as' + (_keyword = _PyPegen_expect_token(p, 659)) // token='as' && (z = _PyPegen_name_token(p)) // NAME ) { - D(fprintf(stderr, "%*c+ _tmp_29[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); + D(fprintf(stderr, "%*c+ _tmp_28[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); _res = z; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -26939,7 +26756,7 @@ _tmp_29_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_29[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_28[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' NAME")); } _res = NULL; @@ -26948,13 +26765,12 @@ _tmp_29_rule(Parser *p) return _res; } -// _loop0_31: ',' dotted_as_name +// _loop0_30: ',' dotted_as_name static asdl_seq * -_loop0_31_rule(Parser *p) +_loop0_30_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -26976,7 +26792,7 @@ _loop0_31_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_31[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' dotted_as_name")); + D(fprintf(stderr, "%*c> _loop0_30[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' dotted_as_name")); Token * _literal; alias_ty elem; while ( @@ -27008,7 +26824,7 @@ _loop0_31_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_31[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_30[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' dotted_as_name")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -27025,13 +26841,12 @@ _loop0_31_rule(Parser *p) return _seq; } -// _gather_30: dotted_as_name _loop0_31 +// _gather_29: dotted_as_name _loop0_30 static asdl_seq * -_gather_30_rule(Parser *p) +_gather_29_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -27039,27 +26854,27 @@ _gather_30_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // dotted_as_name _loop0_31 + { // dotted_as_name _loop0_30 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_30[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "dotted_as_name _loop0_31")); + D(fprintf(stderr, "%*c> _gather_29[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "dotted_as_name _loop0_30")); alias_ty elem; asdl_seq * seq; if ( (elem = dotted_as_name_rule(p)) // dotted_as_name && - (seq = _loop0_31_rule(p)) // _loop0_31 + (seq = _loop0_30_rule(p)) // _loop0_30 ) { - D(fprintf(stderr, "%*c+ _gather_30[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "dotted_as_name _loop0_31")); + D(fprintf(stderr, "%*c+ _gather_29[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "dotted_as_name _loop0_30")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_30[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "dotted_as_name _loop0_31")); + D(fprintf(stderr, "%*c%s _gather_29[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "dotted_as_name _loop0_30")); } _res = NULL; done: @@ -27067,13 +26882,12 @@ _gather_30_rule(Parser *p) return _res; } -// _tmp_32: 'as' NAME +// _tmp_31: 'as' NAME static void * -_tmp_32_rule(Parser *p) +_tmp_31_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -27086,16 +26900,16 @@ _tmp_32_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_32[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); + D(fprintf(stderr, "%*c> _tmp_31[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); Token * _keyword; expr_ty z; if ( - (_keyword = _PyPegen_expect_token(p, 654)) // token='as' + (_keyword = _PyPegen_expect_token(p, 659)) // token='as' && (z = _PyPegen_name_token(p)) // NAME ) { - D(fprintf(stderr, "%*c+ _tmp_32[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); + D(fprintf(stderr, "%*c+ _tmp_31[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); _res = z; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -27105,7 +26919,7 @@ _tmp_32_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_32[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_31[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' NAME")); } _res = NULL; @@ -27114,13 +26928,12 @@ _tmp_32_rule(Parser *p) return _res; } -// _loop1_33: ('@' named_expression NEWLINE) +// _loop1_32: ('@' named_expression NEWLINE) static asdl_seq * -_loop1_33_rule(Parser *p) +_loop1_32_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -27142,13 +26955,13 @@ _loop1_33_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_33[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('@' named_expression NEWLINE)")); - void *_tmp_251_var; + D(fprintf(stderr, "%*c> _loop1_32[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('@' named_expression NEWLINE)")); + void *_tmp_252_var; while ( - (_tmp_251_var = _tmp_251_rule(p)) // '@' named_expression NEWLINE + (_tmp_252_var = _tmp_252_rule(p)) // '@' named_expression NEWLINE ) { - _res = _tmp_251_var; + _res = _tmp_252_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -27165,7 +26978,7 @@ _loop1_33_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_33[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_32[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "('@' named_expression NEWLINE)")); } if (_n == 0 || p->error_indicator) { @@ -27187,13 +27000,12 @@ _loop1_33_rule(Parser *p) return _seq; } -// _tmp_34: '(' arguments? ')' +// _tmp_33: '(' arguments? ')' static void * -_tmp_34_rule(Parser *p) +_tmp_33_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -27206,7 +27018,7 @@ _tmp_34_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_34[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' arguments? ')'")); + D(fprintf(stderr, "%*c> _tmp_33[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' arguments? ')'")); Token * _literal; Token * _literal_1; void *z; @@ -27218,7 +27030,7 @@ _tmp_34_rule(Parser *p) (_literal_1 = _PyPegen_expect_token(p, 8)) // token=')' ) { - D(fprintf(stderr, "%*c+ _tmp_34[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' arguments? ')'")); + D(fprintf(stderr, "%*c+ _tmp_33[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' arguments? ')'")); _res = z; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -27228,7 +27040,7 @@ _tmp_34_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_34[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_33[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'(' arguments? ')'")); } _res = NULL; @@ -27237,13 +27049,12 @@ _tmp_34_rule(Parser *p) return _res; } -// _tmp_35: '->' expression +// _tmp_34: '->' expression static void * -_tmp_35_rule(Parser *p) +_tmp_34_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -27256,7 +27067,7 @@ _tmp_35_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_35[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'->' expression")); + D(fprintf(stderr, "%*c> _tmp_34[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'->' expression")); Token * _literal; expr_ty z; if ( @@ -27265,7 +27076,7 @@ _tmp_35_rule(Parser *p) (z = expression_rule(p)) // expression ) { - D(fprintf(stderr, "%*c+ _tmp_35[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'->' expression")); + D(fprintf(stderr, "%*c+ _tmp_34[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'->' expression")); _res = z; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -27275,7 +27086,7 @@ _tmp_35_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_35[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_34[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'->' expression")); } _res = NULL; @@ -27284,13 +27095,12 @@ _tmp_35_rule(Parser *p) return _res; } -// _tmp_36: '->' expression +// _tmp_35: '->' expression static void * -_tmp_36_rule(Parser *p) +_tmp_35_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -27303,7 +27113,7 @@ _tmp_36_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_36[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'->' expression")); + D(fprintf(stderr, "%*c> _tmp_35[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'->' expression")); Token * _literal; expr_ty z; if ( @@ -27312,7 +27122,7 @@ _tmp_36_rule(Parser *p) (z = expression_rule(p)) // expression ) { - D(fprintf(stderr, "%*c+ _tmp_36[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'->' expression")); + D(fprintf(stderr, "%*c+ _tmp_35[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'->' expression")); _res = z; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -27322,7 +27132,7 @@ _tmp_36_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_36[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_35[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'->' expression")); } _res = NULL; @@ -27331,13 +27141,12 @@ _tmp_36_rule(Parser *p) return _res; } -// _loop0_37: param_no_default +// _loop0_36: param_no_default static asdl_seq * -_loop0_37_rule(Parser *p) +_loop0_36_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -27359,7 +27168,7 @@ _loop0_37_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_37[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); + D(fprintf(stderr, "%*c> _loop0_36[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); arg_ty param_no_default_var; while ( (param_no_default_var = param_no_default_rule(p)) // param_no_default @@ -27382,7 +27191,7 @@ _loop0_37_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_37[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_36[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_no_default")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -27399,13 +27208,12 @@ _loop0_37_rule(Parser *p) return _seq; } -// _loop0_38: param_with_default +// _loop0_37: param_with_default static asdl_seq * -_loop0_38_rule(Parser *p) +_loop0_37_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -27427,7 +27235,7 @@ _loop0_38_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_38[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default")); + D(fprintf(stderr, "%*c> _loop0_37[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default")); NameDefaultPair* param_with_default_var; while ( (param_with_default_var = param_with_default_rule(p)) // param_with_default @@ -27450,7 +27258,7 @@ _loop0_38_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_38[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_37[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_with_default")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -27467,13 +27275,12 @@ _loop0_38_rule(Parser *p) return _seq; } -// _loop0_39: param_with_default +// _loop0_38: param_with_default static asdl_seq * -_loop0_39_rule(Parser *p) +_loop0_38_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -27495,7 +27302,7 @@ _loop0_39_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_39[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default")); + D(fprintf(stderr, "%*c> _loop0_38[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default")); NameDefaultPair* param_with_default_var; while ( (param_with_default_var = param_with_default_rule(p)) // param_with_default @@ -27518,7 +27325,7 @@ _loop0_39_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_39[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_38[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_with_default")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -27535,13 +27342,12 @@ _loop0_39_rule(Parser *p) return _seq; } -// _loop1_40: param_no_default +// _loop1_39: param_no_default static asdl_seq * -_loop1_40_rule(Parser *p) +_loop1_39_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -27563,7 +27369,7 @@ _loop1_40_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_40[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); + D(fprintf(stderr, "%*c> _loop1_39[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); arg_ty param_no_default_var; while ( (param_no_default_var = param_no_default_rule(p)) // param_no_default @@ -27586,7 +27392,7 @@ _loop1_40_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_40[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_39[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_no_default")); } if (_n == 0 || p->error_indicator) { @@ -27608,13 +27414,12 @@ _loop1_40_rule(Parser *p) return _seq; } -// _loop0_41: param_with_default +// _loop0_40: param_with_default static asdl_seq * -_loop0_41_rule(Parser *p) +_loop0_40_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -27636,7 +27441,7 @@ _loop0_41_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_41[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default")); + D(fprintf(stderr, "%*c> _loop0_40[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default")); NameDefaultPair* param_with_default_var; while ( (param_with_default_var = param_with_default_rule(p)) // param_with_default @@ -27659,7 +27464,7 @@ _loop0_41_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_41[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_40[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_with_default")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -27676,13 +27481,12 @@ _loop0_41_rule(Parser *p) return _seq; } -// _loop1_42: param_with_default +// _loop1_41: param_with_default static asdl_seq * -_loop1_42_rule(Parser *p) +_loop1_41_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -27704,7 +27508,7 @@ _loop1_42_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_42[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default")); + D(fprintf(stderr, "%*c> _loop1_41[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default")); NameDefaultPair* param_with_default_var; while ( (param_with_default_var = param_with_default_rule(p)) // param_with_default @@ -27727,7 +27531,7 @@ _loop1_42_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_42[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_41[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_with_default")); } if (_n == 0 || p->error_indicator) { @@ -27749,13 +27553,12 @@ _loop1_42_rule(Parser *p) return _seq; } -// _loop1_43: param_no_default +// _loop1_42: param_no_default static asdl_seq * -_loop1_43_rule(Parser *p) +_loop1_42_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -27777,7 +27580,7 @@ _loop1_43_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_43[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); + D(fprintf(stderr, "%*c> _loop1_42[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); arg_ty param_no_default_var; while ( (param_no_default_var = param_no_default_rule(p)) // param_no_default @@ -27800,7 +27603,7 @@ _loop1_43_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_43[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_42[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_no_default")); } if (_n == 0 || p->error_indicator) { @@ -27822,13 +27625,12 @@ _loop1_43_rule(Parser *p) return _seq; } -// _loop1_44: param_no_default +// _loop1_43: param_no_default static asdl_seq * -_loop1_44_rule(Parser *p) +_loop1_43_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -27850,7 +27652,7 @@ _loop1_44_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_44[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); + D(fprintf(stderr, "%*c> _loop1_43[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); arg_ty param_no_default_var; while ( (param_no_default_var = param_no_default_rule(p)) // param_no_default @@ -27873,7 +27675,7 @@ _loop1_44_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_44[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_43[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_no_default")); } if (_n == 0 || p->error_indicator) { @@ -27895,13 +27697,12 @@ _loop1_44_rule(Parser *p) return _seq; } -// _loop0_45: param_no_default +// _loop0_44: param_no_default static asdl_seq * -_loop0_45_rule(Parser *p) +_loop0_44_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -27923,7 +27724,7 @@ _loop0_45_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_45[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); + D(fprintf(stderr, "%*c> _loop0_44[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); arg_ty param_no_default_var; while ( (param_no_default_var = param_no_default_rule(p)) // param_no_default @@ -27946,7 +27747,7 @@ _loop0_45_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_45[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_44[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_no_default")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -27963,13 +27764,12 @@ _loop0_45_rule(Parser *p) return _seq; } -// _loop1_46: param_with_default +// _loop1_45: param_with_default static asdl_seq * -_loop1_46_rule(Parser *p) +_loop1_45_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -27991,7 +27791,7 @@ _loop1_46_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_46[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default")); + D(fprintf(stderr, "%*c> _loop1_45[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default")); NameDefaultPair* param_with_default_var; while ( (param_with_default_var = param_with_default_rule(p)) // param_with_default @@ -28014,7 +27814,7 @@ _loop1_46_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_46[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_45[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_with_default")); } if (_n == 0 || p->error_indicator) { @@ -28036,13 +27836,12 @@ _loop1_46_rule(Parser *p) return _seq; } -// _loop0_47: param_no_default +// _loop0_46: param_no_default static asdl_seq * -_loop0_47_rule(Parser *p) +_loop0_46_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -28064,7 +27863,7 @@ _loop0_47_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_47[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); + D(fprintf(stderr, "%*c> _loop0_46[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); arg_ty param_no_default_var; while ( (param_no_default_var = param_no_default_rule(p)) // param_no_default @@ -28087,7 +27886,7 @@ _loop0_47_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_47[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_46[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_no_default")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -28104,13 +27903,12 @@ _loop0_47_rule(Parser *p) return _seq; } -// _loop1_48: param_with_default +// _loop1_47: param_with_default static asdl_seq * -_loop1_48_rule(Parser *p) +_loop1_47_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -28132,7 +27930,7 @@ _loop1_48_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_48[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default")); + D(fprintf(stderr, "%*c> _loop1_47[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default")); NameDefaultPair* param_with_default_var; while ( (param_with_default_var = param_with_default_rule(p)) // param_with_default @@ -28155,7 +27953,7 @@ _loop1_48_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_48[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_47[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_with_default")); } if (_n == 0 || p->error_indicator) { @@ -28177,13 +27975,12 @@ _loop1_48_rule(Parser *p) return _seq; } -// _loop0_49: param_maybe_default +// _loop0_48: param_maybe_default static asdl_seq * -_loop0_49_rule(Parser *p) +_loop0_48_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -28205,7 +28002,7 @@ _loop0_49_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_49[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_maybe_default")); + D(fprintf(stderr, "%*c> _loop0_48[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_maybe_default")); NameDefaultPair* param_maybe_default_var; while ( (param_maybe_default_var = param_maybe_default_rule(p)) // param_maybe_default @@ -28228,7 +28025,7 @@ _loop0_49_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_49[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_48[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_maybe_default")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -28245,13 +28042,12 @@ _loop0_49_rule(Parser *p) return _seq; } -// _loop0_50: param_maybe_default +// _loop0_49: param_maybe_default static asdl_seq * -_loop0_50_rule(Parser *p) +_loop0_49_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -28273,7 +28069,7 @@ _loop0_50_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_50[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_maybe_default")); + D(fprintf(stderr, "%*c> _loop0_49[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_maybe_default")); NameDefaultPair* param_maybe_default_var; while ( (param_maybe_default_var = param_maybe_default_rule(p)) // param_maybe_default @@ -28296,7 +28092,7 @@ _loop0_50_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_50[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_49[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_maybe_default")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -28313,13 +28109,12 @@ _loop0_50_rule(Parser *p) return _seq; } -// _loop1_51: param_maybe_default +// _loop1_50: param_maybe_default static asdl_seq * -_loop1_51_rule(Parser *p) +_loop1_50_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -28341,7 +28136,7 @@ _loop1_51_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_51[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_maybe_default")); + D(fprintf(stderr, "%*c> _loop1_50[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_maybe_default")); NameDefaultPair* param_maybe_default_var; while ( (param_maybe_default_var = param_maybe_default_rule(p)) // param_maybe_default @@ -28364,7 +28159,7 @@ _loop1_51_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_51[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_50[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_maybe_default")); } if (_n == 0 || p->error_indicator) { @@ -28386,13 +28181,12 @@ _loop1_51_rule(Parser *p) return _seq; } -// _loop0_53: ',' with_item +// _loop0_52: ',' with_item static asdl_seq * -_loop0_53_rule(Parser *p) +_loop0_52_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -28414,7 +28208,7 @@ _loop0_53_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_53[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' with_item")); + D(fprintf(stderr, "%*c> _loop0_52[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' with_item")); Token * _literal; withitem_ty elem; while ( @@ -28446,7 +28240,7 @@ _loop0_53_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_53[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_52[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' with_item")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -28463,13 +28257,12 @@ _loop0_53_rule(Parser *p) return _seq; } -// _gather_52: with_item _loop0_53 +// _gather_51: with_item _loop0_52 static asdl_seq * -_gather_52_rule(Parser *p) +_gather_51_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -28477,27 +28270,27 @@ _gather_52_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // with_item _loop0_53 + { // with_item _loop0_52 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_52[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "with_item _loop0_53")); + D(fprintf(stderr, "%*c> _gather_51[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "with_item _loop0_52")); withitem_ty elem; asdl_seq * seq; if ( (elem = with_item_rule(p)) // with_item && - (seq = _loop0_53_rule(p)) // _loop0_53 + (seq = _loop0_52_rule(p)) // _loop0_52 ) { - D(fprintf(stderr, "%*c+ _gather_52[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "with_item _loop0_53")); + D(fprintf(stderr, "%*c+ _gather_51[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "with_item _loop0_52")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_52[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "with_item _loop0_53")); + D(fprintf(stderr, "%*c%s _gather_51[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "with_item _loop0_52")); } _res = NULL; done: @@ -28505,13 +28298,12 @@ _gather_52_rule(Parser *p) return _res; } -// _loop0_55: ',' with_item +// _loop0_54: ',' with_item static asdl_seq * -_loop0_55_rule(Parser *p) +_loop0_54_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -28533,7 +28325,7 @@ _loop0_55_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_55[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' with_item")); + D(fprintf(stderr, "%*c> _loop0_54[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' with_item")); Token * _literal; withitem_ty elem; while ( @@ -28565,7 +28357,7 @@ _loop0_55_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_55[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_54[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' with_item")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -28582,13 +28374,12 @@ _loop0_55_rule(Parser *p) return _seq; } -// _gather_54: with_item _loop0_55 +// _gather_53: with_item _loop0_54 static asdl_seq * -_gather_54_rule(Parser *p) +_gather_53_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -28596,27 +28387,27 @@ _gather_54_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // with_item _loop0_55 + { // with_item _loop0_54 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_54[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "with_item _loop0_55")); + D(fprintf(stderr, "%*c> _gather_53[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "with_item _loop0_54")); withitem_ty elem; asdl_seq * seq; if ( (elem = with_item_rule(p)) // with_item && - (seq = _loop0_55_rule(p)) // _loop0_55 + (seq = _loop0_54_rule(p)) // _loop0_54 ) { - D(fprintf(stderr, "%*c+ _gather_54[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "with_item _loop0_55")); + D(fprintf(stderr, "%*c+ _gather_53[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "with_item _loop0_54")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_54[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "with_item _loop0_55")); + D(fprintf(stderr, "%*c%s _gather_53[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "with_item _loop0_54")); } _res = NULL; done: @@ -28624,13 +28415,12 @@ _gather_54_rule(Parser *p) return _res; } -// _loop0_57: ',' with_item +// _loop0_56: ',' with_item static asdl_seq * -_loop0_57_rule(Parser *p) +_loop0_56_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -28652,7 +28442,7 @@ _loop0_57_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_57[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' with_item")); + D(fprintf(stderr, "%*c> _loop0_56[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' with_item")); Token * _literal; withitem_ty elem; while ( @@ -28684,7 +28474,7 @@ _loop0_57_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_57[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_56[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' with_item")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -28701,13 +28491,12 @@ _loop0_57_rule(Parser *p) return _seq; } -// _gather_56: with_item _loop0_57 +// _gather_55: with_item _loop0_56 static asdl_seq * -_gather_56_rule(Parser *p) +_gather_55_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -28715,27 +28504,27 @@ _gather_56_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // with_item _loop0_57 + { // with_item _loop0_56 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_56[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "with_item _loop0_57")); + D(fprintf(stderr, "%*c> _gather_55[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "with_item _loop0_56")); withitem_ty elem; asdl_seq * seq; if ( (elem = with_item_rule(p)) // with_item && - (seq = _loop0_57_rule(p)) // _loop0_57 + (seq = _loop0_56_rule(p)) // _loop0_56 ) { - D(fprintf(stderr, "%*c+ _gather_56[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "with_item _loop0_57")); + D(fprintf(stderr, "%*c+ _gather_55[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "with_item _loop0_56")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_56[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "with_item _loop0_57")); + D(fprintf(stderr, "%*c%s _gather_55[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "with_item _loop0_56")); } _res = NULL; done: @@ -28743,13 +28532,12 @@ _gather_56_rule(Parser *p) return _res; } -// _loop0_59: ',' with_item +// _loop0_58: ',' with_item static asdl_seq * -_loop0_59_rule(Parser *p) +_loop0_58_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -28771,7 +28559,7 @@ _loop0_59_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_59[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' with_item")); + D(fprintf(stderr, "%*c> _loop0_58[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' with_item")); Token * _literal; withitem_ty elem; while ( @@ -28803,7 +28591,7 @@ _loop0_59_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_59[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_58[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' with_item")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -28820,13 +28608,12 @@ _loop0_59_rule(Parser *p) return _seq; } -// _gather_58: with_item _loop0_59 +// _gather_57: with_item _loop0_58 static asdl_seq * -_gather_58_rule(Parser *p) +_gather_57_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -28834,27 +28621,27 @@ _gather_58_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // with_item _loop0_59 + { // with_item _loop0_58 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_58[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "with_item _loop0_59")); + D(fprintf(stderr, "%*c> _gather_57[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "with_item _loop0_58")); withitem_ty elem; asdl_seq * seq; if ( (elem = with_item_rule(p)) // with_item && - (seq = _loop0_59_rule(p)) // _loop0_59 + (seq = _loop0_58_rule(p)) // _loop0_58 ) { - D(fprintf(stderr, "%*c+ _gather_58[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "with_item _loop0_59")); + D(fprintf(stderr, "%*c+ _gather_57[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "with_item _loop0_58")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_58[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "with_item _loop0_59")); + D(fprintf(stderr, "%*c%s _gather_57[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "with_item _loop0_58")); } _res = NULL; done: @@ -28862,13 +28649,12 @@ _gather_58_rule(Parser *p) return _res; } -// _tmp_60: ',' | ')' | ':' +// _tmp_59: ',' | ')' | ':' static void * -_tmp_60_rule(Parser *p) +_tmp_59_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -28881,18 +28667,18 @@ _tmp_60_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_60[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c> _tmp_59[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' ) { - D(fprintf(stderr, "%*c+ _tmp_60[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c+ _tmp_59[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_60[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_59[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "','")); } { // ')' @@ -28900,18 +28686,18 @@ _tmp_60_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_60[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); + D(fprintf(stderr, "%*c> _tmp_59[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 8)) // token=')' ) { - D(fprintf(stderr, "%*c+ _tmp_60[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'")); + D(fprintf(stderr, "%*c+ _tmp_59[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_60[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_59[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "')'")); } { // ':' @@ -28919,18 +28705,18 @@ _tmp_60_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_60[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c> _tmp_59[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 11)) // token=':' ) { - D(fprintf(stderr, "%*c+ _tmp_60[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c+ _tmp_59[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_60[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_59[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':'")); } _res = NULL; @@ -28939,13 +28725,12 @@ _tmp_60_rule(Parser *p) return _res; } -// _loop1_61: except_block +// _loop1_60: except_block static asdl_seq * -_loop1_61_rule(Parser *p) +_loop1_60_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -28967,7 +28752,7 @@ _loop1_61_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_61[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "except_block")); + D(fprintf(stderr, "%*c> _loop1_60[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "except_block")); excepthandler_ty except_block_var; while ( (except_block_var = except_block_rule(p)) // except_block @@ -28990,7 +28775,7 @@ _loop1_61_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_61[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_60[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "except_block")); } if (_n == 0 || p->error_indicator) { @@ -29012,13 +28797,12 @@ _loop1_61_rule(Parser *p) return _seq; } -// _loop1_62: except_star_block +// _loop1_61: except_star_block static asdl_seq * -_loop1_62_rule(Parser *p) +_loop1_61_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -29040,7 +28824,7 @@ _loop1_62_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_62[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "except_star_block")); + D(fprintf(stderr, "%*c> _loop1_61[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "except_star_block")); excepthandler_ty except_star_block_var; while ( (except_star_block_var = except_star_block_rule(p)) // except_star_block @@ -29063,7 +28847,7 @@ _loop1_62_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_62[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_61[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "except_star_block")); } if (_n == 0 || p->error_indicator) { @@ -29085,13 +28869,12 @@ _loop1_62_rule(Parser *p) return _seq; } -// _tmp_63: 'as' NAME +// _tmp_62: 'as' NAME static void * -_tmp_63_rule(Parser *p) +_tmp_62_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -29104,16 +28887,16 @@ _tmp_63_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_63[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); + D(fprintf(stderr, "%*c> _tmp_62[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); Token * _keyword; expr_ty z; if ( - (_keyword = _PyPegen_expect_token(p, 654)) // token='as' + (_keyword = _PyPegen_expect_token(p, 659)) // token='as' && (z = _PyPegen_name_token(p)) // NAME ) { - D(fprintf(stderr, "%*c+ _tmp_63[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); + D(fprintf(stderr, "%*c+ _tmp_62[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); _res = z; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -29123,7 +28906,7 @@ _tmp_63_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_63[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_62[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' NAME")); } _res = NULL; @@ -29132,13 +28915,12 @@ _tmp_63_rule(Parser *p) return _res; } -// _tmp_64: 'as' NAME +// _tmp_63: 'as' NAME static void * -_tmp_64_rule(Parser *p) +_tmp_63_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -29151,16 +28933,16 @@ _tmp_64_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_64[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); + D(fprintf(stderr, "%*c> _tmp_63[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); Token * _keyword; expr_ty z; if ( - (_keyword = _PyPegen_expect_token(p, 654)) // token='as' + (_keyword = _PyPegen_expect_token(p, 659)) // token='as' && (z = _PyPegen_name_token(p)) // NAME ) { - D(fprintf(stderr, "%*c+ _tmp_64[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); + D(fprintf(stderr, "%*c+ _tmp_63[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); _res = z; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -29170,7 +28952,7 @@ _tmp_64_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_64[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_63[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' NAME")); } _res = NULL; @@ -29179,13 +28961,12 @@ _tmp_64_rule(Parser *p) return _res; } -// _loop1_65: case_block +// _loop1_64: case_block static asdl_seq * -_loop1_65_rule(Parser *p) +_loop1_64_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -29207,7 +28988,7 @@ _loop1_65_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_65[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "case_block")); + D(fprintf(stderr, "%*c> _loop1_64[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "case_block")); match_case_ty case_block_var; while ( (case_block_var = case_block_rule(p)) // case_block @@ -29230,7 +29011,7 @@ _loop1_65_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_65[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_64[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "case_block")); } if (_n == 0 || p->error_indicator) { @@ -29252,13 +29033,12 @@ _loop1_65_rule(Parser *p) return _seq; } -// _loop0_67: '|' closed_pattern +// _loop0_66: '|' closed_pattern static asdl_seq * -_loop0_67_rule(Parser *p) +_loop0_66_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -29280,7 +29060,7 @@ _loop0_67_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_67[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'|' closed_pattern")); + D(fprintf(stderr, "%*c> _loop0_66[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'|' closed_pattern")); Token * _literal; pattern_ty elem; while ( @@ -29312,7 +29092,7 @@ _loop0_67_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_67[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_66[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'|' closed_pattern")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -29329,13 +29109,12 @@ _loop0_67_rule(Parser *p) return _seq; } -// _gather_66: closed_pattern _loop0_67 +// _gather_65: closed_pattern _loop0_66 static asdl_seq * -_gather_66_rule(Parser *p) +_gather_65_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -29343,27 +29122,27 @@ _gather_66_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // closed_pattern _loop0_67 + { // closed_pattern _loop0_66 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_66[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "closed_pattern _loop0_67")); + D(fprintf(stderr, "%*c> _gather_65[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "closed_pattern _loop0_66")); pattern_ty elem; asdl_seq * seq; if ( (elem = closed_pattern_rule(p)) // closed_pattern && - (seq = _loop0_67_rule(p)) // _loop0_67 + (seq = _loop0_66_rule(p)) // _loop0_66 ) { - D(fprintf(stderr, "%*c+ _gather_66[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "closed_pattern _loop0_67")); + D(fprintf(stderr, "%*c+ _gather_65[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "closed_pattern _loop0_66")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_66[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "closed_pattern _loop0_67")); + D(fprintf(stderr, "%*c%s _gather_65[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "closed_pattern _loop0_66")); } _res = NULL; done: @@ -29371,13 +29150,12 @@ _gather_66_rule(Parser *p) return _res; } -// _tmp_68: '+' | '-' +// _tmp_67: '+' | '-' static void * -_tmp_68_rule(Parser *p) +_tmp_67_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -29390,18 +29168,18 @@ _tmp_68_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_68[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'+'")); + D(fprintf(stderr, "%*c> _tmp_67[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'+'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 14)) // token='+' ) { - D(fprintf(stderr, "%*c+ _tmp_68[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'+'")); + D(fprintf(stderr, "%*c+ _tmp_67[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'+'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_68[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_67[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'+'")); } { // '-' @@ -29409,18 +29187,18 @@ _tmp_68_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_68[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'-'")); + D(fprintf(stderr, "%*c> _tmp_67[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'-'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 15)) // token='-' ) { - D(fprintf(stderr, "%*c+ _tmp_68[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'-'")); + D(fprintf(stderr, "%*c+ _tmp_67[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'-'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_68[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_67[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'-'")); } _res = NULL; @@ -29429,13 +29207,12 @@ _tmp_68_rule(Parser *p) return _res; } -// _tmp_69: '+' | '-' +// _tmp_68: '+' | '-' static void * -_tmp_69_rule(Parser *p) +_tmp_68_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -29448,18 +29225,18 @@ _tmp_69_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_69[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'+'")); + D(fprintf(stderr, "%*c> _tmp_68[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'+'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 14)) // token='+' ) { - D(fprintf(stderr, "%*c+ _tmp_69[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'+'")); + D(fprintf(stderr, "%*c+ _tmp_68[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'+'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_69[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_68[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'+'")); } { // '-' @@ -29467,18 +29244,18 @@ _tmp_69_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_69[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'-'")); + D(fprintf(stderr, "%*c> _tmp_68[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'-'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 15)) // token='-' ) { - D(fprintf(stderr, "%*c+ _tmp_69[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'-'")); + D(fprintf(stderr, "%*c+ _tmp_68[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'-'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_69[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_68[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'-'")); } _res = NULL; @@ -29487,13 +29264,12 @@ _tmp_69_rule(Parser *p) return _res; } -// _tmp_70: '.' | '(' | '=' +// _tmp_69: '.' | '(' | '=' static void * -_tmp_70_rule(Parser *p) +_tmp_69_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -29506,18 +29282,18 @@ _tmp_70_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_70[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'.'")); + D(fprintf(stderr, "%*c> _tmp_69[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'.'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 23)) // token='.' ) { - D(fprintf(stderr, "%*c+ _tmp_70[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'.'")); + D(fprintf(stderr, "%*c+ _tmp_69[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'.'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_70[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_69[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'.'")); } { // '(' @@ -29525,18 +29301,18 @@ _tmp_70_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_70[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'('")); + D(fprintf(stderr, "%*c> _tmp_69[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'('")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 7)) // token='(' ) { - D(fprintf(stderr, "%*c+ _tmp_70[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'('")); + D(fprintf(stderr, "%*c+ _tmp_69[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'('")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_70[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_69[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'('")); } { // '=' @@ -29544,18 +29320,18 @@ _tmp_70_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_70[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'='")); + D(fprintf(stderr, "%*c> _tmp_69[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'='")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 22)) // token='=' ) { - D(fprintf(stderr, "%*c+ _tmp_70[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'='")); + D(fprintf(stderr, "%*c+ _tmp_69[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'='")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_70[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_69[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'='")); } _res = NULL; @@ -29564,13 +29340,12 @@ _tmp_70_rule(Parser *p) return _res; } -// _tmp_71: '.' | '(' | '=' +// _tmp_70: '.' | '(' | '=' static void * -_tmp_71_rule(Parser *p) +_tmp_70_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -29583,18 +29358,18 @@ _tmp_71_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_71[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'.'")); + D(fprintf(stderr, "%*c> _tmp_70[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'.'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 23)) // token='.' ) { - D(fprintf(stderr, "%*c+ _tmp_71[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'.'")); + D(fprintf(stderr, "%*c+ _tmp_70[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'.'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_71[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_70[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'.'")); } { // '(' @@ -29602,18 +29377,18 @@ _tmp_71_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_71[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'('")); + D(fprintf(stderr, "%*c> _tmp_70[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'('")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 7)) // token='(' ) { - D(fprintf(stderr, "%*c+ _tmp_71[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'('")); + D(fprintf(stderr, "%*c+ _tmp_70[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'('")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_71[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_70[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'('")); } { // '=' @@ -29621,18 +29396,18 @@ _tmp_71_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_71[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'='")); + D(fprintf(stderr, "%*c> _tmp_70[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'='")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 22)) // token='=' ) { - D(fprintf(stderr, "%*c+ _tmp_71[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'='")); + D(fprintf(stderr, "%*c+ _tmp_70[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'='")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_71[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_70[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'='")); } _res = NULL; @@ -29641,13 +29416,12 @@ _tmp_71_rule(Parser *p) return _res; } -// _loop0_73: ',' maybe_star_pattern +// _loop0_72: ',' maybe_star_pattern static asdl_seq * -_loop0_73_rule(Parser *p) +_loop0_72_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -29669,7 +29443,7 @@ _loop0_73_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_73[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' maybe_star_pattern")); + D(fprintf(stderr, "%*c> _loop0_72[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' maybe_star_pattern")); Token * _literal; pattern_ty elem; while ( @@ -29701,7 +29475,7 @@ _loop0_73_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_73[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_72[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' maybe_star_pattern")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -29718,13 +29492,12 @@ _loop0_73_rule(Parser *p) return _seq; } -// _gather_72: maybe_star_pattern _loop0_73 +// _gather_71: maybe_star_pattern _loop0_72 static asdl_seq * -_gather_72_rule(Parser *p) +_gather_71_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -29732,27 +29505,27 @@ _gather_72_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // maybe_star_pattern _loop0_73 + { // maybe_star_pattern _loop0_72 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_72[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "maybe_star_pattern _loop0_73")); + D(fprintf(stderr, "%*c> _gather_71[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "maybe_star_pattern _loop0_72")); pattern_ty elem; asdl_seq * seq; if ( (elem = maybe_star_pattern_rule(p)) // maybe_star_pattern && - (seq = _loop0_73_rule(p)) // _loop0_73 + (seq = _loop0_72_rule(p)) // _loop0_72 ) { - D(fprintf(stderr, "%*c+ _gather_72[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "maybe_star_pattern _loop0_73")); + D(fprintf(stderr, "%*c+ _gather_71[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "maybe_star_pattern _loop0_72")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_72[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "maybe_star_pattern _loop0_73")); + D(fprintf(stderr, "%*c%s _gather_71[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "maybe_star_pattern _loop0_72")); } _res = NULL; done: @@ -29760,13 +29533,12 @@ _gather_72_rule(Parser *p) return _res; } -// _loop0_75: ',' key_value_pattern +// _loop0_74: ',' key_value_pattern static asdl_seq * -_loop0_75_rule(Parser *p) +_loop0_74_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -29788,7 +29560,7 @@ _loop0_75_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_75[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' key_value_pattern")); + D(fprintf(stderr, "%*c> _loop0_74[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' key_value_pattern")); Token * _literal; KeyPatternPair* elem; while ( @@ -29820,7 +29592,7 @@ _loop0_75_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_75[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_74[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' key_value_pattern")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -29837,13 +29609,12 @@ _loop0_75_rule(Parser *p) return _seq; } -// _gather_74: key_value_pattern _loop0_75 +// _gather_73: key_value_pattern _loop0_74 static asdl_seq * -_gather_74_rule(Parser *p) +_gather_73_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -29851,27 +29622,27 @@ _gather_74_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // key_value_pattern _loop0_75 + { // key_value_pattern _loop0_74 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_74[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "key_value_pattern _loop0_75")); + D(fprintf(stderr, "%*c> _gather_73[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "key_value_pattern _loop0_74")); KeyPatternPair* elem; asdl_seq * seq; if ( (elem = key_value_pattern_rule(p)) // key_value_pattern && - (seq = _loop0_75_rule(p)) // _loop0_75 + (seq = _loop0_74_rule(p)) // _loop0_74 ) { - D(fprintf(stderr, "%*c+ _gather_74[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "key_value_pattern _loop0_75")); + D(fprintf(stderr, "%*c+ _gather_73[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "key_value_pattern _loop0_74")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_74[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "key_value_pattern _loop0_75")); + D(fprintf(stderr, "%*c%s _gather_73[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "key_value_pattern _loop0_74")); } _res = NULL; done: @@ -29879,13 +29650,12 @@ _gather_74_rule(Parser *p) return _res; } -// _tmp_76: literal_expr | attr +// _tmp_75: literal_expr | attr static void * -_tmp_76_rule(Parser *p) +_tmp_75_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -29898,18 +29668,18 @@ _tmp_76_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_76[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "literal_expr")); + D(fprintf(stderr, "%*c> _tmp_75[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "literal_expr")); expr_ty literal_expr_var; if ( (literal_expr_var = literal_expr_rule(p)) // literal_expr ) { - D(fprintf(stderr, "%*c+ _tmp_76[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "literal_expr")); + D(fprintf(stderr, "%*c+ _tmp_75[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "literal_expr")); _res = literal_expr_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_76[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_75[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "literal_expr")); } { // attr @@ -29917,18 +29687,18 @@ _tmp_76_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_76[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "attr")); + D(fprintf(stderr, "%*c> _tmp_75[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "attr")); expr_ty attr_var; if ( (attr_var = attr_rule(p)) // attr ) { - D(fprintf(stderr, "%*c+ _tmp_76[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "attr")); + D(fprintf(stderr, "%*c+ _tmp_75[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "attr")); _res = attr_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_76[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_75[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "attr")); } _res = NULL; @@ -29937,13 +29707,12 @@ _tmp_76_rule(Parser *p) return _res; } -// _loop0_78: ',' pattern +// _loop0_77: ',' pattern static asdl_seq * -_loop0_78_rule(Parser *p) +_loop0_77_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -29965,7 +29734,7 @@ _loop0_78_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_78[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' pattern")); + D(fprintf(stderr, "%*c> _loop0_77[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' pattern")); Token * _literal; pattern_ty elem; while ( @@ -29997,7 +29766,7 @@ _loop0_78_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_78[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_77[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' pattern")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -30014,13 +29783,12 @@ _loop0_78_rule(Parser *p) return _seq; } -// _gather_77: pattern _loop0_78 +// _gather_76: pattern _loop0_77 static asdl_seq * -_gather_77_rule(Parser *p) +_gather_76_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -30028,27 +29796,27 @@ _gather_77_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // pattern _loop0_78 + { // pattern _loop0_77 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_77[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "pattern _loop0_78")); + D(fprintf(stderr, "%*c> _gather_76[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "pattern _loop0_77")); pattern_ty elem; asdl_seq * seq; if ( (elem = pattern_rule(p)) // pattern && - (seq = _loop0_78_rule(p)) // _loop0_78 + (seq = _loop0_77_rule(p)) // _loop0_77 ) { - D(fprintf(stderr, "%*c+ _gather_77[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "pattern _loop0_78")); + D(fprintf(stderr, "%*c+ _gather_76[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "pattern _loop0_77")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_77[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "pattern _loop0_78")); + D(fprintf(stderr, "%*c%s _gather_76[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "pattern _loop0_77")); } _res = NULL; done: @@ -30056,13 +29824,12 @@ _gather_77_rule(Parser *p) return _res; } -// _loop0_80: ',' keyword_pattern +// _loop0_79: ',' keyword_pattern static asdl_seq * -_loop0_80_rule(Parser *p) +_loop0_79_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -30084,7 +29851,7 @@ _loop0_80_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_80[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' keyword_pattern")); + D(fprintf(stderr, "%*c> _loop0_79[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' keyword_pattern")); Token * _literal; KeyPatternPair* elem; while ( @@ -30116,7 +29883,7 @@ _loop0_80_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_80[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_79[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' keyword_pattern")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -30133,13 +29900,12 @@ _loop0_80_rule(Parser *p) return _seq; } -// _gather_79: keyword_pattern _loop0_80 +// _gather_78: keyword_pattern _loop0_79 static asdl_seq * -_gather_79_rule(Parser *p) +_gather_78_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -30147,27 +29913,27 @@ _gather_79_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // keyword_pattern _loop0_80 + { // keyword_pattern _loop0_79 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_79[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "keyword_pattern _loop0_80")); + D(fprintf(stderr, "%*c> _gather_78[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "keyword_pattern _loop0_79")); KeyPatternPair* elem; asdl_seq * seq; if ( (elem = keyword_pattern_rule(p)) // keyword_pattern && - (seq = _loop0_80_rule(p)) // _loop0_80 + (seq = _loop0_79_rule(p)) // _loop0_79 ) { - D(fprintf(stderr, "%*c+ _gather_79[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "keyword_pattern _loop0_80")); + D(fprintf(stderr, "%*c+ _gather_78[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "keyword_pattern _loop0_79")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_79[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "keyword_pattern _loop0_80")); + D(fprintf(stderr, "%*c%s _gather_78[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "keyword_pattern _loop0_79")); } _res = NULL; done: @@ -30175,13 +29941,12 @@ _gather_79_rule(Parser *p) return _res; } -// _loop0_82: ',' type_param +// _loop0_81: ',' type_param static asdl_seq * -_loop0_82_rule(Parser *p) +_loop0_81_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -30203,7 +29968,7 @@ _loop0_82_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_82[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' type_param")); + D(fprintf(stderr, "%*c> _loop0_81[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' type_param")); Token * _literal; type_param_ty elem; while ( @@ -30235,7 +30000,7 @@ _loop0_82_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_82[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_81[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' type_param")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -30252,13 +30017,12 @@ _loop0_82_rule(Parser *p) return _seq; } -// _gather_81: type_param _loop0_82 +// _gather_80: type_param _loop0_81 static asdl_seq * -_gather_81_rule(Parser *p) +_gather_80_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -30266,27 +30030,27 @@ _gather_81_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // type_param _loop0_82 + { // type_param _loop0_81 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_81[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "type_param _loop0_82")); + D(fprintf(stderr, "%*c> _gather_80[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "type_param _loop0_81")); type_param_ty elem; asdl_seq * seq; if ( (elem = type_param_rule(p)) // type_param && - (seq = _loop0_82_rule(p)) // _loop0_82 + (seq = _loop0_81_rule(p)) // _loop0_81 ) { - D(fprintf(stderr, "%*c+ _gather_81[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "type_param _loop0_82")); + D(fprintf(stderr, "%*c+ _gather_80[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "type_param _loop0_81")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_81[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "type_param _loop0_82")); + D(fprintf(stderr, "%*c%s _gather_80[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "type_param _loop0_81")); } _res = NULL; done: @@ -30294,13 +30058,12 @@ _gather_81_rule(Parser *p) return _res; } -// _loop1_83: (',' expression) +// _loop1_82: (',' expression) static asdl_seq * -_loop1_83_rule(Parser *p) +_loop1_82_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -30322,13 +30085,13 @@ _loop1_83_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_83[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' expression)")); - void *_tmp_252_var; + D(fprintf(stderr, "%*c> _loop1_82[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' expression)")); + void *_tmp_253_var; while ( - (_tmp_252_var = _tmp_252_rule(p)) // ',' expression + (_tmp_253_var = _tmp_253_rule(p)) // ',' expression ) { - _res = _tmp_252_var; + _res = _tmp_253_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -30345,7 +30108,7 @@ _loop1_83_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_83[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_82[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(',' expression)")); } if (_n == 0 || p->error_indicator) { @@ -30367,13 +30130,12 @@ _loop1_83_rule(Parser *p) return _seq; } -// _loop1_84: (',' star_expression) +// _loop1_83: (',' star_expression) static asdl_seq * -_loop1_84_rule(Parser *p) +_loop1_83_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -30395,13 +30157,13 @@ _loop1_84_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_84[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' star_expression)")); - void *_tmp_253_var; + D(fprintf(stderr, "%*c> _loop1_83[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' star_expression)")); + void *_tmp_254_var; while ( - (_tmp_253_var = _tmp_253_rule(p)) // ',' star_expression + (_tmp_254_var = _tmp_254_rule(p)) // ',' star_expression ) { - _res = _tmp_253_var; + _res = _tmp_254_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -30418,7 +30180,7 @@ _loop1_84_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_84[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_83[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(',' star_expression)")); } if (_n == 0 || p->error_indicator) { @@ -30440,13 +30202,12 @@ _loop1_84_rule(Parser *p) return _seq; } -// _loop0_86: ',' star_named_expression +// _loop0_85: ',' star_named_expression static asdl_seq * -_loop0_86_rule(Parser *p) +_loop0_85_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -30468,7 +30229,7 @@ _loop0_86_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_86[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_named_expression")); + D(fprintf(stderr, "%*c> _loop0_85[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_named_expression")); Token * _literal; expr_ty elem; while ( @@ -30500,7 +30261,7 @@ _loop0_86_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_86[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_85[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' star_named_expression")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -30517,13 +30278,12 @@ _loop0_86_rule(Parser *p) return _seq; } -// _gather_85: star_named_expression _loop0_86 +// _gather_84: star_named_expression _loop0_85 static asdl_seq * -_gather_85_rule(Parser *p) +_gather_84_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -30531,27 +30291,27 @@ _gather_85_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // star_named_expression _loop0_86 + { // star_named_expression _loop0_85 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_85[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_named_expression _loop0_86")); + D(fprintf(stderr, "%*c> _gather_84[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_named_expression _loop0_85")); expr_ty elem; asdl_seq * seq; if ( (elem = star_named_expression_rule(p)) // star_named_expression && - (seq = _loop0_86_rule(p)) // _loop0_86 + (seq = _loop0_85_rule(p)) // _loop0_85 ) { - D(fprintf(stderr, "%*c+ _gather_85[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_named_expression _loop0_86")); + D(fprintf(stderr, "%*c+ _gather_84[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_named_expression _loop0_85")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_85[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_named_expression _loop0_86")); + D(fprintf(stderr, "%*c%s _gather_84[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_named_expression _loop0_85")); } _res = NULL; done: @@ -30559,13 +30319,12 @@ _gather_85_rule(Parser *p) return _res; } -// _loop1_87: ('or' conjunction) +// _loop1_86: ('or' conjunction) static asdl_seq * -_loop1_87_rule(Parser *p) +_loop1_86_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -30587,13 +30346,13 @@ _loop1_87_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_87[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('or' conjunction)")); - void *_tmp_254_var; + D(fprintf(stderr, "%*c> _loop1_86[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('or' conjunction)")); + void *_tmp_255_var; while ( - (_tmp_254_var = _tmp_254_rule(p)) // 'or' conjunction + (_tmp_255_var = _tmp_255_rule(p)) // 'or' conjunction ) { - _res = _tmp_254_var; + _res = _tmp_255_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -30610,7 +30369,7 @@ _loop1_87_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_87[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_86[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "('or' conjunction)")); } if (_n == 0 || p->error_indicator) { @@ -30632,13 +30391,12 @@ _loop1_87_rule(Parser *p) return _seq; } -// _loop1_88: ('and' inversion) +// _loop1_87: ('and' inversion) static asdl_seq * -_loop1_88_rule(Parser *p) +_loop1_87_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -30660,13 +30418,13 @@ _loop1_88_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_88[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('and' inversion)")); - void *_tmp_255_var; + D(fprintf(stderr, "%*c> _loop1_87[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('and' inversion)")); + void *_tmp_256_var; while ( - (_tmp_255_var = _tmp_255_rule(p)) // 'and' inversion + (_tmp_256_var = _tmp_256_rule(p)) // 'and' inversion ) { - _res = _tmp_255_var; + _res = _tmp_256_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -30683,7 +30441,7 @@ _loop1_88_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_88[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_87[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "('and' inversion)")); } if (_n == 0 || p->error_indicator) { @@ -30705,13 +30463,12 @@ _loop1_88_rule(Parser *p) return _seq; } -// _loop1_89: compare_op_bitwise_or_pair +// _loop1_88: compare_op_bitwise_or_pair static asdl_seq * -_loop1_89_rule(Parser *p) +_loop1_88_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -30733,7 +30490,7 @@ _loop1_89_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_89[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "compare_op_bitwise_or_pair")); + D(fprintf(stderr, "%*c> _loop1_88[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "compare_op_bitwise_or_pair")); CmpopExprPair* compare_op_bitwise_or_pair_var; while ( (compare_op_bitwise_or_pair_var = compare_op_bitwise_or_pair_rule(p)) // compare_op_bitwise_or_pair @@ -30756,7 +30513,7 @@ _loop1_89_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_89[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_88[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "compare_op_bitwise_or_pair")); } if (_n == 0 || p->error_indicator) { @@ -30778,13 +30535,12 @@ _loop1_89_rule(Parser *p) return _seq; } -// _tmp_90: '!=' +// _tmp_89: '!=' static void * -_tmp_90_rule(Parser *p) +_tmp_89_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -30797,13 +30553,13 @@ _tmp_90_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_90[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'!='")); + D(fprintf(stderr, "%*c> _tmp_89[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'!='")); Token * tok; if ( (tok = _PyPegen_expect_token(p, 28)) // token='!=' ) { - D(fprintf(stderr, "%*c+ _tmp_90[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'!='")); + D(fprintf(stderr, "%*c+ _tmp_89[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'!='")); _res = _PyPegen_check_barry_as_flufl ( p , tok ) ? NULL : tok; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -30813,7 +30569,7 @@ _tmp_90_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_90[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_89[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'!='")); } _res = NULL; @@ -30822,13 +30578,12 @@ _tmp_90_rule(Parser *p) return _res; } -// _loop0_92: ',' (slice | starred_expression) +// _loop0_91: ',' (slice | starred_expression) static asdl_seq * -_loop0_92_rule(Parser *p) +_loop0_91_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -30850,13 +30605,13 @@ _loop0_92_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_92[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (slice | starred_expression)")); + D(fprintf(stderr, "%*c> _loop0_91[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (slice | starred_expression)")); Token * _literal; void *elem; while ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (elem = _tmp_256_rule(p)) // slice | starred_expression + (elem = _tmp_257_rule(p)) // slice | starred_expression ) { _res = elem; @@ -30882,7 +30637,7 @@ _loop0_92_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_92[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_91[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (slice | starred_expression)")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -30899,13 +30654,12 @@ _loop0_92_rule(Parser *p) return _seq; } -// _gather_91: (slice | starred_expression) _loop0_92 +// _gather_90: (slice | starred_expression) _loop0_91 static asdl_seq * -_gather_91_rule(Parser *p) +_gather_90_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -30913,27 +30667,27 @@ _gather_91_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // (slice | starred_expression) _loop0_92 + { // (slice | starred_expression) _loop0_91 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_91[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(slice | starred_expression) _loop0_92")); + D(fprintf(stderr, "%*c> _gather_90[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(slice | starred_expression) _loop0_91")); void *elem; asdl_seq * seq; if ( - (elem = _tmp_256_rule(p)) // slice | starred_expression + (elem = _tmp_257_rule(p)) // slice | starred_expression && - (seq = _loop0_92_rule(p)) // _loop0_92 + (seq = _loop0_91_rule(p)) // _loop0_91 ) { - D(fprintf(stderr, "%*c+ _gather_91[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(slice | starred_expression) _loop0_92")); + D(fprintf(stderr, "%*c+ _gather_90[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(slice | starred_expression) _loop0_91")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_91[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(slice | starred_expression) _loop0_92")); + D(fprintf(stderr, "%*c%s _gather_90[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(slice | starred_expression) _loop0_91")); } _res = NULL; done: @@ -30941,13 +30695,12 @@ _gather_91_rule(Parser *p) return _res; } -// _tmp_93: ':' expression? +// _tmp_92: ':' expression? static void * -_tmp_93_rule(Parser *p) +_tmp_92_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -30960,7 +30713,7 @@ _tmp_93_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_93[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':' expression?")); + D(fprintf(stderr, "%*c> _tmp_92[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':' expression?")); Token * _literal; void *d; if ( @@ -30969,7 +30722,7 @@ _tmp_93_rule(Parser *p) (d = expression_rule(p), !p->error_indicator) // expression? ) { - D(fprintf(stderr, "%*c+ _tmp_93[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':' expression?")); + D(fprintf(stderr, "%*c+ _tmp_92[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':' expression?")); _res = d; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -30979,7 +30732,7 @@ _tmp_93_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_93[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_92[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':' expression?")); } _res = NULL; @@ -30988,13 +30741,12 @@ _tmp_93_rule(Parser *p) return _res; } -// _tmp_94: STRING | FSTRING_START +// _tmp_93: STRING | FSTRING_START static void * -_tmp_94_rule(Parser *p) +_tmp_93_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -31007,18 +30759,18 @@ _tmp_94_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_94[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "STRING")); + D(fprintf(stderr, "%*c> _tmp_93[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "STRING")); expr_ty string_var; if ( (string_var = _PyPegen_string_token(p)) // STRING ) { - D(fprintf(stderr, "%*c+ _tmp_94[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "STRING")); + D(fprintf(stderr, "%*c+ _tmp_93[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "STRING")); _res = string_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_94[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_93[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "STRING")); } { // FSTRING_START @@ -31026,18 +30778,18 @@ _tmp_94_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_94[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "FSTRING_START")); + D(fprintf(stderr, "%*c> _tmp_93[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "FSTRING_START")); Token * fstring_start_var; if ( (fstring_start_var = _PyPegen_expect_token(p, FSTRING_START)) // token='FSTRING_START' ) { - D(fprintf(stderr, "%*c+ _tmp_94[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "FSTRING_START")); + D(fprintf(stderr, "%*c+ _tmp_93[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "FSTRING_START")); _res = fstring_start_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_94[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_93[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "FSTRING_START")); } _res = NULL; @@ -31046,13 +30798,12 @@ _tmp_94_rule(Parser *p) return _res; } -// _tmp_95: tuple | group | genexp +// _tmp_94: tuple | group | genexp static void * -_tmp_95_rule(Parser *p) +_tmp_94_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -31065,18 +30816,18 @@ _tmp_95_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_95[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "tuple")); + D(fprintf(stderr, "%*c> _tmp_94[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "tuple")); expr_ty tuple_var; if ( (tuple_var = tuple_rule(p)) // tuple ) { - D(fprintf(stderr, "%*c+ _tmp_95[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "tuple")); + D(fprintf(stderr, "%*c+ _tmp_94[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "tuple")); _res = tuple_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_95[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_94[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "tuple")); } { // group @@ -31084,18 +30835,18 @@ _tmp_95_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_95[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "group")); + D(fprintf(stderr, "%*c> _tmp_94[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "group")); expr_ty group_var; if ( (group_var = group_rule(p)) // group ) { - D(fprintf(stderr, "%*c+ _tmp_95[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "group")); + D(fprintf(stderr, "%*c+ _tmp_94[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "group")); _res = group_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_95[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_94[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "group")); } { // genexp @@ -31103,18 +30854,18 @@ _tmp_95_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_95[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "genexp")); + D(fprintf(stderr, "%*c> _tmp_94[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "genexp")); expr_ty genexp_var; if ( (genexp_var = genexp_rule(p)) // genexp ) { - D(fprintf(stderr, "%*c+ _tmp_95[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "genexp")); + D(fprintf(stderr, "%*c+ _tmp_94[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "genexp")); _res = genexp_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_95[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_94[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "genexp")); } _res = NULL; @@ -31123,13 +30874,12 @@ _tmp_95_rule(Parser *p) return _res; } -// _tmp_96: list | listcomp +// _tmp_95: list | listcomp static void * -_tmp_96_rule(Parser *p) +_tmp_95_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -31142,18 +30892,18 @@ _tmp_96_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_96[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "list")); + D(fprintf(stderr, "%*c> _tmp_95[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "list")); expr_ty list_var; if ( (list_var = list_rule(p)) // list ) { - D(fprintf(stderr, "%*c+ _tmp_96[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "list")); + D(fprintf(stderr, "%*c+ _tmp_95[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "list")); _res = list_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_96[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_95[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "list")); } { // listcomp @@ -31161,18 +30911,18 @@ _tmp_96_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_96[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "listcomp")); + D(fprintf(stderr, "%*c> _tmp_95[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "listcomp")); expr_ty listcomp_var; if ( (listcomp_var = listcomp_rule(p)) // listcomp ) { - D(fprintf(stderr, "%*c+ _tmp_96[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "listcomp")); + D(fprintf(stderr, "%*c+ _tmp_95[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "listcomp")); _res = listcomp_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_96[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_95[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "listcomp")); } _res = NULL; @@ -31181,13 +30931,12 @@ _tmp_96_rule(Parser *p) return _res; } -// _tmp_97: dict | set | dictcomp | setcomp +// _tmp_96: dict | set | dictcomp | setcomp static void * -_tmp_97_rule(Parser *p) +_tmp_96_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -31200,18 +30949,18 @@ _tmp_97_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_97[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "dict")); + D(fprintf(stderr, "%*c> _tmp_96[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "dict")); expr_ty dict_var; if ( (dict_var = dict_rule(p)) // dict ) { - D(fprintf(stderr, "%*c+ _tmp_97[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "dict")); + D(fprintf(stderr, "%*c+ _tmp_96[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "dict")); _res = dict_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_97[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_96[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "dict")); } { // set @@ -31219,18 +30968,18 @@ _tmp_97_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_97[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "set")); + D(fprintf(stderr, "%*c> _tmp_96[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "set")); expr_ty set_var; if ( (set_var = set_rule(p)) // set ) { - D(fprintf(stderr, "%*c+ _tmp_97[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "set")); + D(fprintf(stderr, "%*c+ _tmp_96[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "set")); _res = set_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_97[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_96[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "set")); } { // dictcomp @@ -31238,18 +30987,18 @@ _tmp_97_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_97[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "dictcomp")); + D(fprintf(stderr, "%*c> _tmp_96[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "dictcomp")); expr_ty dictcomp_var; if ( (dictcomp_var = dictcomp_rule(p)) // dictcomp ) { - D(fprintf(stderr, "%*c+ _tmp_97[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "dictcomp")); + D(fprintf(stderr, "%*c+ _tmp_96[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "dictcomp")); _res = dictcomp_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_97[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_96[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "dictcomp")); } { // setcomp @@ -31257,18 +31006,18 @@ _tmp_97_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_97[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "setcomp")); + D(fprintf(stderr, "%*c> _tmp_96[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "setcomp")); expr_ty setcomp_var; if ( (setcomp_var = setcomp_rule(p)) // setcomp ) { - D(fprintf(stderr, "%*c+ _tmp_97[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "setcomp")); + D(fprintf(stderr, "%*c+ _tmp_96[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "setcomp")); _res = setcomp_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_97[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_96[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "setcomp")); } _res = NULL; @@ -31277,13 +31026,12 @@ _tmp_97_rule(Parser *p) return _res; } -// _tmp_98: yield_expr | named_expression +// _tmp_97: yield_expr | named_expression static void * -_tmp_98_rule(Parser *p) +_tmp_97_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -31296,18 +31044,18 @@ _tmp_98_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_98[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); + D(fprintf(stderr, "%*c> _tmp_97[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); expr_ty yield_expr_var; if ( (yield_expr_var = yield_expr_rule(p)) // yield_expr ) { - D(fprintf(stderr, "%*c+ _tmp_98[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr")); + D(fprintf(stderr, "%*c+ _tmp_97[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr")); _res = yield_expr_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_98[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_97[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "yield_expr")); } { // named_expression @@ -31315,18 +31063,18 @@ _tmp_98_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_98[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "named_expression")); + D(fprintf(stderr, "%*c> _tmp_97[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "named_expression")); expr_ty named_expression_var; if ( (named_expression_var = named_expression_rule(p)) // named_expression ) { - D(fprintf(stderr, "%*c+ _tmp_98[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "named_expression")); + D(fprintf(stderr, "%*c+ _tmp_97[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "named_expression")); _res = named_expression_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_98[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_97[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "named_expression")); } _res = NULL; @@ -31335,13 +31083,12 @@ _tmp_98_rule(Parser *p) return _res; } -// _loop0_99: lambda_param_no_default +// _loop0_98: lambda_param_no_default static asdl_seq * -_loop0_99_rule(Parser *p) +_loop0_98_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -31363,7 +31110,7 @@ _loop0_99_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_99[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); + D(fprintf(stderr, "%*c> _loop0_98[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); arg_ty lambda_param_no_default_var; while ( (lambda_param_no_default_var = lambda_param_no_default_rule(p)) // lambda_param_no_default @@ -31386,7 +31133,7 @@ _loop0_99_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_99[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_98[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_no_default")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -31403,13 +31150,12 @@ _loop0_99_rule(Parser *p) return _seq; } -// _loop0_100: lambda_param_with_default +// _loop0_99: lambda_param_with_default static asdl_seq * -_loop0_100_rule(Parser *p) +_loop0_99_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -31431,7 +31177,7 @@ _loop0_100_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_100[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); + D(fprintf(stderr, "%*c> _loop0_99[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); NameDefaultPair* lambda_param_with_default_var; while ( (lambda_param_with_default_var = lambda_param_with_default_rule(p)) // lambda_param_with_default @@ -31454,7 +31200,7 @@ _loop0_100_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_100[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_99[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_with_default")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -31471,13 +31217,12 @@ _loop0_100_rule(Parser *p) return _seq; } -// _loop0_101: lambda_param_with_default +// _loop0_100: lambda_param_with_default static asdl_seq * -_loop0_101_rule(Parser *p) +_loop0_100_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -31499,7 +31244,7 @@ _loop0_101_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_101[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); + D(fprintf(stderr, "%*c> _loop0_100[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); NameDefaultPair* lambda_param_with_default_var; while ( (lambda_param_with_default_var = lambda_param_with_default_rule(p)) // lambda_param_with_default @@ -31522,7 +31267,7 @@ _loop0_101_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_101[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_100[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_with_default")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -31539,13 +31284,12 @@ _loop0_101_rule(Parser *p) return _seq; } -// _loop1_102: lambda_param_no_default +// _loop1_101: lambda_param_no_default static asdl_seq * -_loop1_102_rule(Parser *p) +_loop1_101_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -31567,7 +31311,7 @@ _loop1_102_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_102[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); + D(fprintf(stderr, "%*c> _loop1_101[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); arg_ty lambda_param_no_default_var; while ( (lambda_param_no_default_var = lambda_param_no_default_rule(p)) // lambda_param_no_default @@ -31590,7 +31334,7 @@ _loop1_102_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_102[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_101[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_no_default")); } if (_n == 0 || p->error_indicator) { @@ -31612,13 +31356,12 @@ _loop1_102_rule(Parser *p) return _seq; } -// _loop0_103: lambda_param_with_default +// _loop0_102: lambda_param_with_default static asdl_seq * -_loop0_103_rule(Parser *p) +_loop0_102_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -31640,7 +31383,7 @@ _loop0_103_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_103[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); + D(fprintf(stderr, "%*c> _loop0_102[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); NameDefaultPair* lambda_param_with_default_var; while ( (lambda_param_with_default_var = lambda_param_with_default_rule(p)) // lambda_param_with_default @@ -31663,7 +31406,7 @@ _loop0_103_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_103[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_102[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_with_default")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -31680,13 +31423,12 @@ _loop0_103_rule(Parser *p) return _seq; } -// _loop1_104: lambda_param_with_default +// _loop1_103: lambda_param_with_default static asdl_seq * -_loop1_104_rule(Parser *p) +_loop1_103_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -31708,7 +31450,7 @@ _loop1_104_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_104[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); + D(fprintf(stderr, "%*c> _loop1_103[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); NameDefaultPair* lambda_param_with_default_var; while ( (lambda_param_with_default_var = lambda_param_with_default_rule(p)) // lambda_param_with_default @@ -31731,7 +31473,7 @@ _loop1_104_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_104[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_103[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_with_default")); } if (_n == 0 || p->error_indicator) { @@ -31753,13 +31495,12 @@ _loop1_104_rule(Parser *p) return _seq; } -// _loop1_105: lambda_param_no_default +// _loop1_104: lambda_param_no_default static asdl_seq * -_loop1_105_rule(Parser *p) +_loop1_104_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -31781,7 +31522,7 @@ _loop1_105_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_105[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); + D(fprintf(stderr, "%*c> _loop1_104[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); arg_ty lambda_param_no_default_var; while ( (lambda_param_no_default_var = lambda_param_no_default_rule(p)) // lambda_param_no_default @@ -31804,7 +31545,7 @@ _loop1_105_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_105[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_104[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_no_default")); } if (_n == 0 || p->error_indicator) { @@ -31826,13 +31567,12 @@ _loop1_105_rule(Parser *p) return _seq; } -// _loop1_106: lambda_param_no_default +// _loop1_105: lambda_param_no_default static asdl_seq * -_loop1_106_rule(Parser *p) +_loop1_105_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -31854,7 +31594,7 @@ _loop1_106_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_106[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); + D(fprintf(stderr, "%*c> _loop1_105[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); arg_ty lambda_param_no_default_var; while ( (lambda_param_no_default_var = lambda_param_no_default_rule(p)) // lambda_param_no_default @@ -31877,7 +31617,7 @@ _loop1_106_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_106[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_105[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_no_default")); } if (_n == 0 || p->error_indicator) { @@ -31899,13 +31639,12 @@ _loop1_106_rule(Parser *p) return _seq; } -// _loop0_107: lambda_param_no_default +// _loop0_106: lambda_param_no_default static asdl_seq * -_loop0_107_rule(Parser *p) +_loop0_106_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -31927,7 +31666,7 @@ _loop0_107_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_107[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); + D(fprintf(stderr, "%*c> _loop0_106[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); arg_ty lambda_param_no_default_var; while ( (lambda_param_no_default_var = lambda_param_no_default_rule(p)) // lambda_param_no_default @@ -31950,7 +31689,7 @@ _loop0_107_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_107[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_106[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_no_default")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -31967,13 +31706,12 @@ _loop0_107_rule(Parser *p) return _seq; } -// _loop1_108: lambda_param_with_default +// _loop1_107: lambda_param_with_default static asdl_seq * -_loop1_108_rule(Parser *p) +_loop1_107_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -31995,7 +31733,7 @@ _loop1_108_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_108[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); + D(fprintf(stderr, "%*c> _loop1_107[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); NameDefaultPair* lambda_param_with_default_var; while ( (lambda_param_with_default_var = lambda_param_with_default_rule(p)) // lambda_param_with_default @@ -32018,7 +31756,7 @@ _loop1_108_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_108[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_107[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_with_default")); } if (_n == 0 || p->error_indicator) { @@ -32040,13 +31778,12 @@ _loop1_108_rule(Parser *p) return _seq; } -// _loop0_109: lambda_param_no_default +// _loop0_108: lambda_param_no_default static asdl_seq * -_loop0_109_rule(Parser *p) +_loop0_108_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -32068,7 +31805,7 @@ _loop0_109_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_109[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); + D(fprintf(stderr, "%*c> _loop0_108[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); arg_ty lambda_param_no_default_var; while ( (lambda_param_no_default_var = lambda_param_no_default_rule(p)) // lambda_param_no_default @@ -32091,7 +31828,7 @@ _loop0_109_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_109[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_108[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_no_default")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -32108,13 +31845,12 @@ _loop0_109_rule(Parser *p) return _seq; } -// _loop1_110: lambda_param_with_default +// _loop1_109: lambda_param_with_default static asdl_seq * -_loop1_110_rule(Parser *p) +_loop1_109_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -32136,7 +31872,7 @@ _loop1_110_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_110[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); + D(fprintf(stderr, "%*c> _loop1_109[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); NameDefaultPair* lambda_param_with_default_var; while ( (lambda_param_with_default_var = lambda_param_with_default_rule(p)) // lambda_param_with_default @@ -32159,7 +31895,7 @@ _loop1_110_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_110[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_109[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_with_default")); } if (_n == 0 || p->error_indicator) { @@ -32181,13 +31917,12 @@ _loop1_110_rule(Parser *p) return _seq; } -// _loop0_111: lambda_param_maybe_default +// _loop0_110: lambda_param_maybe_default static asdl_seq * -_loop0_111_rule(Parser *p) +_loop0_110_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -32209,7 +31944,7 @@ _loop0_111_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_111[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_maybe_default")); + D(fprintf(stderr, "%*c> _loop0_110[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_maybe_default")); NameDefaultPair* lambda_param_maybe_default_var; while ( (lambda_param_maybe_default_var = lambda_param_maybe_default_rule(p)) // lambda_param_maybe_default @@ -32232,7 +31967,7 @@ _loop0_111_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_111[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_110[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_maybe_default")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -32249,13 +31984,12 @@ _loop0_111_rule(Parser *p) return _seq; } -// _loop1_112: lambda_param_maybe_default +// _loop1_111: lambda_param_maybe_default static asdl_seq * -_loop1_112_rule(Parser *p) +_loop1_111_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -32277,7 +32011,7 @@ _loop1_112_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_112[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_maybe_default")); + D(fprintf(stderr, "%*c> _loop1_111[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_maybe_default")); NameDefaultPair* lambda_param_maybe_default_var; while ( (lambda_param_maybe_default_var = lambda_param_maybe_default_rule(p)) // lambda_param_maybe_default @@ -32300,7 +32034,7 @@ _loop1_112_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_112[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_111[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_maybe_default")); } if (_n == 0 || p->error_indicator) { @@ -32322,13 +32056,12 @@ _loop1_112_rule(Parser *p) return _seq; } -// _tmp_113: yield_expr | star_expressions +// _tmp_112: yield_expr | star_expressions static void * -_tmp_113_rule(Parser *p) +_tmp_112_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -32341,18 +32074,18 @@ _tmp_113_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_113[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); + D(fprintf(stderr, "%*c> _tmp_112[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); expr_ty yield_expr_var; if ( (yield_expr_var = yield_expr_rule(p)) // yield_expr ) { - D(fprintf(stderr, "%*c+ _tmp_113[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr")); + D(fprintf(stderr, "%*c+ _tmp_112[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr")); _res = yield_expr_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_113[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_112[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "yield_expr")); } { // star_expressions @@ -32360,18 +32093,18 @@ _tmp_113_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_113[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions")); + D(fprintf(stderr, "%*c> _tmp_112[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions")); expr_ty star_expressions_var; if ( (star_expressions_var = star_expressions_rule(p)) // star_expressions ) { - D(fprintf(stderr, "%*c+ _tmp_113[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions")); + D(fprintf(stderr, "%*c+ _tmp_112[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions")); _res = star_expressions_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_113[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_112[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_expressions")); } _res = NULL; @@ -32380,13 +32113,12 @@ _tmp_113_rule(Parser *p) return _res; } -// _loop0_114: fstring_format_spec +// _loop0_113: fstring_format_spec static asdl_seq * -_loop0_114_rule(Parser *p) +_loop0_113_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -32408,7 +32140,7 @@ _loop0_114_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_114[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "fstring_format_spec")); + D(fprintf(stderr, "%*c> _loop0_113[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "fstring_format_spec")); expr_ty fstring_format_spec_var; while ( (fstring_format_spec_var = fstring_format_spec_rule(p)) // fstring_format_spec @@ -32431,7 +32163,7 @@ _loop0_114_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_114[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_113[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "fstring_format_spec")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -32448,13 +32180,79 @@ _loop0_114_rule(Parser *p) return _seq; } -// _loop1_115: (fstring | string) +// _loop0_114: fstring_middle static asdl_seq * -_loop1_115_rule(Parser *p) +_loop0_114_rule(Parser *p) { if (p->level++ == MAXSTACK) { + _Pypegen_stack_overflow(p); + } + if (p->error_indicator) { + p->level--; + return NULL; + } + void *_res = NULL; + int _mark = p->mark; + void **_children = PyMem_Malloc(sizeof(void *)); + if (!_children) { + p->error_indicator = 1; + PyErr_NoMemory(); + p->level--; + return NULL; + } + Py_ssize_t _children_capacity = 1; + Py_ssize_t _n = 0; + { // fstring_middle + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> _loop0_114[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "fstring_middle")); + expr_ty fstring_middle_var; + while ( + (fstring_middle_var = fstring_middle_rule(p)) // fstring_middle + ) + { + _res = fstring_middle_var; + if (_n == _children_capacity) { + _children_capacity *= 2; + void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); + if (!_new_children) { + PyMem_Free(_children); + p->error_indicator = 1; + PyErr_NoMemory(); + p->level--; + return NULL; + } + _children = _new_children; + } + _children[_n++] = _res; + _mark = p->mark; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s _loop0_114[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "fstring_middle")); + } + asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); + if (!_seq) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); + p->level--; + return NULL; + } + for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); + PyMem_Free(_children); + p->level--; + return _seq; +} + +// _loop1_115: (fstring | string) +static asdl_seq * +_loop1_115_rule(Parser *p) +{ + if (p->level++ == MAXSTACK) { + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -32477,12 +32275,12 @@ _loop1_115_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> _loop1_115[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(fstring | string)")); - void *_tmp_257_var; + void *_tmp_258_var; while ( - (_tmp_257_var = _tmp_257_rule(p)) // fstring | string + (_tmp_258_var = _tmp_258_rule(p)) // fstring | string ) { - _res = _tmp_257_var; + _res = _tmp_258_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -32526,8 +32324,7 @@ static void * _tmp_116_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -32576,8 +32373,7 @@ static asdl_seq * _loop0_118_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -32653,8 +32449,7 @@ static asdl_seq * _gather_117_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -32695,8 +32490,7 @@ static asdl_seq * _loop1_119_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -32768,8 +32562,7 @@ static asdl_seq * _loop0_120_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -32792,12 +32585,12 @@ _loop0_120_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> _loop0_120[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('if' disjunction)")); - void *_tmp_258_var; + void *_tmp_259_var; while ( - (_tmp_258_var = _tmp_258_rule(p)) // 'if' disjunction + (_tmp_259_var = _tmp_259_rule(p)) // 'if' disjunction ) { - _res = _tmp_258_var; + _res = _tmp_259_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -32836,8 +32629,7 @@ static asdl_seq * _loop0_121_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -32860,12 +32652,12 @@ _loop0_121_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> _loop0_121[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('if' disjunction)")); - void *_tmp_259_var; + void *_tmp_260_var; while ( - (_tmp_259_var = _tmp_259_rule(p)) // 'if' disjunction + (_tmp_260_var = _tmp_260_rule(p)) // 'if' disjunction ) { - _res = _tmp_259_var; + _res = _tmp_260_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -32899,13 +32691,57 @@ _loop0_121_rule(Parser *p) return _seq; } -// _tmp_122: assignment_expression | expression !':=' +// _tmp_122: bitwise_or ((',' bitwise_or))* ','? static void * _tmp_122_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); + } + if (p->error_indicator) { + p->level--; + return NULL; + } + void * _res = NULL; + int _mark = p->mark; + { // bitwise_or ((',' bitwise_or))* ','? + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> _tmp_122[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "bitwise_or ((',' bitwise_or))* ','?")); + asdl_seq * _loop0_261_var; + void *_opt_var; + UNUSED(_opt_var); // Silence compiler warnings + expr_ty bitwise_or_var; + if ( + (bitwise_or_var = bitwise_or_rule(p)) // bitwise_or + && + (_loop0_261_var = _loop0_261_rule(p)) // ((',' bitwise_or))* + && + (_opt_var = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? + ) + { + D(fprintf(stderr, "%*c+ _tmp_122[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "bitwise_or ((',' bitwise_or))* ','?")); + _res = _PyPegen_dummy_name(p, bitwise_or_var, _loop0_261_var, _opt_var); + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s _tmp_122[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "bitwise_or ((',' bitwise_or))* ','?")); + } + _res = NULL; + done: + p->level--; + return _res; +} + +// _tmp_123: assignment_expression | expression !':=' +static void * +_tmp_123_rule(Parser *p) +{ + if (p->level++ == MAXSTACK) { + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -32918,18 +32754,18 @@ _tmp_122_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_122[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "assignment_expression")); + D(fprintf(stderr, "%*c> _tmp_123[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "assignment_expression")); expr_ty assignment_expression_var; if ( (assignment_expression_var = assignment_expression_rule(p)) // assignment_expression ) { - D(fprintf(stderr, "%*c+ _tmp_122[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "assignment_expression")); + D(fprintf(stderr, "%*c+ _tmp_123[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "assignment_expression")); _res = assignment_expression_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_122[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_123[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "assignment_expression")); } { // expression !':=' @@ -32937,7 +32773,7 @@ _tmp_122_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_122[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression !':='")); + D(fprintf(stderr, "%*c> _tmp_123[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression !':='")); expr_ty expression_var; if ( (expression_var = expression_rule(p)) // expression @@ -32945,12 +32781,12 @@ _tmp_122_rule(Parser *p) _PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, 53) // token=':=' ) { - D(fprintf(stderr, "%*c+ _tmp_122[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression !':='")); + D(fprintf(stderr, "%*c+ _tmp_123[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression !':='")); _res = expression_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_122[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_123[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression !':='")); } _res = NULL; @@ -32959,13 +32795,12 @@ _tmp_122_rule(Parser *p) return _res; } -// _loop0_124: ',' (starred_expression | (assignment_expression | expression !':=') !'=') +// _loop0_125: ',' (starred_expression | (assignment_expression | expression !':=') !'=') static asdl_seq * -_loop0_124_rule(Parser *p) +_loop0_125_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -32987,13 +32822,13 @@ _loop0_124_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_124[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (starred_expression | (assignment_expression | expression !':=') !'=')")); + D(fprintf(stderr, "%*c> _loop0_125[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (starred_expression | (assignment_expression | expression !':=') !'=')")); Token * _literal; void *elem; while ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (elem = _tmp_260_rule(p)) // starred_expression | (assignment_expression | expression !':=') !'=' + (elem = _tmp_262_rule(p)) // starred_expression | (assignment_expression | expression !':=') !'=' ) { _res = elem; @@ -33019,7 +32854,7 @@ _loop0_124_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_124[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_125[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (starred_expression | (assignment_expression | expression !':=') !'=')")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -33036,14 +32871,13 @@ _loop0_124_rule(Parser *p) return _seq; } -// _gather_123: -// | (starred_expression | (assignment_expression | expression !':=') !'=') _loop0_124 +// _gather_124: +// | (starred_expression | (assignment_expression | expression !':=') !'=') _loop0_125 static asdl_seq * -_gather_123_rule(Parser *p) +_gather_124_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -33051,27 +32885,27 @@ _gather_123_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // (starred_expression | (assignment_expression | expression !':=') !'=') _loop0_124 + { // (starred_expression | (assignment_expression | expression !':=') !'=') _loop0_125 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_123[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(starred_expression | (assignment_expression | expression !':=') !'=') _loop0_124")); + D(fprintf(stderr, "%*c> _gather_124[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(starred_expression | (assignment_expression | expression !':=') !'=') _loop0_125")); void *elem; asdl_seq * seq; if ( - (elem = _tmp_260_rule(p)) // starred_expression | (assignment_expression | expression !':=') !'=' + (elem = _tmp_262_rule(p)) // starred_expression | (assignment_expression | expression !':=') !'=' && - (seq = _loop0_124_rule(p)) // _loop0_124 + (seq = _loop0_125_rule(p)) // _loop0_125 ) { - D(fprintf(stderr, "%*c+ _gather_123[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(starred_expression | (assignment_expression | expression !':=') !'=') _loop0_124")); + D(fprintf(stderr, "%*c+ _gather_124[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(starred_expression | (assignment_expression | expression !':=') !'=') _loop0_125")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_123[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(starred_expression | (assignment_expression | expression !':=') !'=') _loop0_124")); + D(fprintf(stderr, "%*c%s _gather_124[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(starred_expression | (assignment_expression | expression !':=') !'=') _loop0_125")); } _res = NULL; done: @@ -33079,13 +32913,12 @@ _gather_123_rule(Parser *p) return _res; } -// _tmp_125: ',' kwargs +// _tmp_126: ',' kwargs static void * -_tmp_125_rule(Parser *p) +_tmp_126_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -33098,7 +32931,7 @@ _tmp_125_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_125[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwargs")); + D(fprintf(stderr, "%*c> _tmp_126[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwargs")); Token * _literal; asdl_seq* k; if ( @@ -33107,7 +32940,7 @@ _tmp_125_rule(Parser *p) (k = kwargs_rule(p)) // kwargs ) { - D(fprintf(stderr, "%*c+ _tmp_125[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' kwargs")); + D(fprintf(stderr, "%*c+ _tmp_126[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' kwargs")); _res = k; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -33117,7 +32950,7 @@ _tmp_125_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_125[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_126[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' kwargs")); } _res = NULL; @@ -33126,13 +32959,12 @@ _tmp_125_rule(Parser *p) return _res; } -// _loop0_127: ',' kwarg_or_starred +// _loop0_128: ',' kwarg_or_starred static asdl_seq * -_loop0_127_rule(Parser *p) +_loop0_128_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -33154,7 +32986,7 @@ _loop0_127_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_127[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwarg_or_starred")); + D(fprintf(stderr, "%*c> _loop0_128[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwarg_or_starred")); Token * _literal; KeywordOrStarred* elem; while ( @@ -33186,7 +33018,7 @@ _loop0_127_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_127[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_128[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' kwarg_or_starred")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -33203,13 +33035,12 @@ _loop0_127_rule(Parser *p) return _seq; } -// _gather_126: kwarg_or_starred _loop0_127 +// _gather_127: kwarg_or_starred _loop0_128 static asdl_seq * -_gather_126_rule(Parser *p) +_gather_127_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -33217,27 +33048,27 @@ _gather_126_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // kwarg_or_starred _loop0_127 + { // kwarg_or_starred _loop0_128 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_126[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kwarg_or_starred _loop0_127")); + D(fprintf(stderr, "%*c> _gather_127[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kwarg_or_starred _loop0_128")); KeywordOrStarred* elem; asdl_seq * seq; if ( (elem = kwarg_or_starred_rule(p)) // kwarg_or_starred && - (seq = _loop0_127_rule(p)) // _loop0_127 + (seq = _loop0_128_rule(p)) // _loop0_128 ) { - D(fprintf(stderr, "%*c+ _gather_126[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "kwarg_or_starred _loop0_127")); + D(fprintf(stderr, "%*c+ _gather_127[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "kwarg_or_starred _loop0_128")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_126[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "kwarg_or_starred _loop0_127")); + D(fprintf(stderr, "%*c%s _gather_127[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "kwarg_or_starred _loop0_128")); } _res = NULL; done: @@ -33245,13 +33076,12 @@ _gather_126_rule(Parser *p) return _res; } -// _loop0_129: ',' kwarg_or_double_starred +// _loop0_130: ',' kwarg_or_double_starred static asdl_seq * -_loop0_129_rule(Parser *p) +_loop0_130_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -33273,7 +33103,7 @@ _loop0_129_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_129[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwarg_or_double_starred")); + D(fprintf(stderr, "%*c> _loop0_130[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwarg_or_double_starred")); Token * _literal; KeywordOrStarred* elem; while ( @@ -33305,7 +33135,7 @@ _loop0_129_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_129[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_130[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' kwarg_or_double_starred")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -33322,13 +33152,12 @@ _loop0_129_rule(Parser *p) return _seq; } -// _gather_128: kwarg_or_double_starred _loop0_129 +// _gather_129: kwarg_or_double_starred _loop0_130 static asdl_seq * -_gather_128_rule(Parser *p) +_gather_129_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -33336,27 +33165,27 @@ _gather_128_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // kwarg_or_double_starred _loop0_129 + { // kwarg_or_double_starred _loop0_130 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_128[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kwarg_or_double_starred _loop0_129")); + D(fprintf(stderr, "%*c> _gather_129[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kwarg_or_double_starred _loop0_130")); KeywordOrStarred* elem; asdl_seq * seq; if ( (elem = kwarg_or_double_starred_rule(p)) // kwarg_or_double_starred && - (seq = _loop0_129_rule(p)) // _loop0_129 + (seq = _loop0_130_rule(p)) // _loop0_130 ) { - D(fprintf(stderr, "%*c+ _gather_128[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "kwarg_or_double_starred _loop0_129")); + D(fprintf(stderr, "%*c+ _gather_129[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "kwarg_or_double_starred _loop0_130")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_128[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "kwarg_or_double_starred _loop0_129")); + D(fprintf(stderr, "%*c%s _gather_129[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "kwarg_or_double_starred _loop0_130")); } _res = NULL; done: @@ -33364,13 +33193,12 @@ _gather_128_rule(Parser *p) return _res; } -// _loop0_131: ',' kwarg_or_starred +// _loop0_132: ',' kwarg_or_starred static asdl_seq * -_loop0_131_rule(Parser *p) +_loop0_132_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -33392,7 +33220,7 @@ _loop0_131_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_131[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwarg_or_starred")); + D(fprintf(stderr, "%*c> _loop0_132[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwarg_or_starred")); Token * _literal; KeywordOrStarred* elem; while ( @@ -33424,7 +33252,7 @@ _loop0_131_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_131[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_132[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' kwarg_or_starred")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -33441,13 +33269,12 @@ _loop0_131_rule(Parser *p) return _seq; } -// _gather_130: kwarg_or_starred _loop0_131 +// _gather_131: kwarg_or_starred _loop0_132 static asdl_seq * -_gather_130_rule(Parser *p) +_gather_131_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -33455,27 +33282,27 @@ _gather_130_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // kwarg_or_starred _loop0_131 + { // kwarg_or_starred _loop0_132 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_130[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kwarg_or_starred _loop0_131")); + D(fprintf(stderr, "%*c> _gather_131[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kwarg_or_starred _loop0_132")); KeywordOrStarred* elem; asdl_seq * seq; if ( (elem = kwarg_or_starred_rule(p)) // kwarg_or_starred && - (seq = _loop0_131_rule(p)) // _loop0_131 + (seq = _loop0_132_rule(p)) // _loop0_132 ) { - D(fprintf(stderr, "%*c+ _gather_130[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "kwarg_or_starred _loop0_131")); + D(fprintf(stderr, "%*c+ _gather_131[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "kwarg_or_starred _loop0_132")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_130[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "kwarg_or_starred _loop0_131")); + D(fprintf(stderr, "%*c%s _gather_131[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "kwarg_or_starred _loop0_132")); } _res = NULL; done: @@ -33483,13 +33310,12 @@ _gather_130_rule(Parser *p) return _res; } -// _loop0_133: ',' kwarg_or_double_starred +// _loop0_134: ',' kwarg_or_double_starred static asdl_seq * -_loop0_133_rule(Parser *p) +_loop0_134_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -33511,7 +33337,7 @@ _loop0_133_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_133[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwarg_or_double_starred")); + D(fprintf(stderr, "%*c> _loop0_134[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwarg_or_double_starred")); Token * _literal; KeywordOrStarred* elem; while ( @@ -33543,7 +33369,7 @@ _loop0_133_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_133[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_134[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' kwarg_or_double_starred")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -33560,13 +33386,12 @@ _loop0_133_rule(Parser *p) return _seq; } -// _gather_132: kwarg_or_double_starred _loop0_133 +// _gather_133: kwarg_or_double_starred _loop0_134 static asdl_seq * -_gather_132_rule(Parser *p) +_gather_133_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -33574,27 +33399,27 @@ _gather_132_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // kwarg_or_double_starred _loop0_133 + { // kwarg_or_double_starred _loop0_134 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_132[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kwarg_or_double_starred _loop0_133")); + D(fprintf(stderr, "%*c> _gather_133[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kwarg_or_double_starred _loop0_134")); KeywordOrStarred* elem; asdl_seq * seq; if ( (elem = kwarg_or_double_starred_rule(p)) // kwarg_or_double_starred && - (seq = _loop0_133_rule(p)) // _loop0_133 + (seq = _loop0_134_rule(p)) // _loop0_134 ) { - D(fprintf(stderr, "%*c+ _gather_132[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "kwarg_or_double_starred _loop0_133")); + D(fprintf(stderr, "%*c+ _gather_133[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "kwarg_or_double_starred _loop0_134")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_132[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "kwarg_or_double_starred _loop0_133")); + D(fprintf(stderr, "%*c%s _gather_133[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "kwarg_or_double_starred _loop0_134")); } _res = NULL; done: @@ -33602,13 +33427,12 @@ _gather_132_rule(Parser *p) return _res; } -// _loop0_134: (',' star_target) +// _loop0_135: (',' star_target) static asdl_seq * -_loop0_134_rule(Parser *p) +_loop0_135_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -33630,13 +33454,13 @@ _loop0_134_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_134[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' star_target)")); - void *_tmp_261_var; + D(fprintf(stderr, "%*c> _loop0_135[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' star_target)")); + void *_tmp_263_var; while ( - (_tmp_261_var = _tmp_261_rule(p)) // ',' star_target + (_tmp_263_var = _tmp_263_rule(p)) // ',' star_target ) { - _res = _tmp_261_var; + _res = _tmp_263_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -33653,7 +33477,7 @@ _loop0_134_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_134[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_135[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(',' star_target)")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -33670,13 +33494,12 @@ _loop0_134_rule(Parser *p) return _seq; } -// _loop0_136: ',' star_target +// _loop0_137: ',' star_target static asdl_seq * -_loop0_136_rule(Parser *p) +_loop0_137_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -33698,7 +33521,7 @@ _loop0_136_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_136[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_target")); + D(fprintf(stderr, "%*c> _loop0_137[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_target")); Token * _literal; expr_ty elem; while ( @@ -33730,7 +33553,7 @@ _loop0_136_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_136[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_137[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' star_target")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -33747,13 +33570,12 @@ _loop0_136_rule(Parser *p) return _seq; } -// _gather_135: star_target _loop0_136 +// _gather_136: star_target _loop0_137 static asdl_seq * -_gather_135_rule(Parser *p) +_gather_136_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -33761,27 +33583,27 @@ _gather_135_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // star_target _loop0_136 + { // star_target _loop0_137 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_135[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_target _loop0_136")); + D(fprintf(stderr, "%*c> _gather_136[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_target _loop0_137")); expr_ty elem; asdl_seq * seq; if ( (elem = star_target_rule(p)) // star_target && - (seq = _loop0_136_rule(p)) // _loop0_136 + (seq = _loop0_137_rule(p)) // _loop0_137 ) { - D(fprintf(stderr, "%*c+ _gather_135[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_target _loop0_136")); + D(fprintf(stderr, "%*c+ _gather_136[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_target _loop0_137")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_135[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_target _loop0_136")); + D(fprintf(stderr, "%*c%s _gather_136[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_target _loop0_137")); } _res = NULL; done: @@ -33789,13 +33611,12 @@ _gather_135_rule(Parser *p) return _res; } -// _loop1_137: (',' star_target) +// _loop1_138: (',' star_target) static asdl_seq * -_loop1_137_rule(Parser *p) +_loop1_138_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -33817,13 +33638,13 @@ _loop1_137_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_137[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' star_target)")); - void *_tmp_262_var; + D(fprintf(stderr, "%*c> _loop1_138[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' star_target)")); + void *_tmp_264_var; while ( - (_tmp_262_var = _tmp_262_rule(p)) // ',' star_target + (_tmp_264_var = _tmp_264_rule(p)) // ',' star_target ) { - _res = _tmp_262_var; + _res = _tmp_264_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -33840,7 +33661,7 @@ _loop1_137_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_137[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_138[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(',' star_target)")); } if (_n == 0 || p->error_indicator) { @@ -33862,13 +33683,12 @@ _loop1_137_rule(Parser *p) return _seq; } -// _tmp_138: !'*' star_target +// _tmp_139: !'*' star_target static void * -_tmp_138_rule(Parser *p) +_tmp_139_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -33881,7 +33701,7 @@ _tmp_138_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_138[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "!'*' star_target")); + D(fprintf(stderr, "%*c> _tmp_139[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "!'*' star_target")); expr_ty star_target_var; if ( _PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, 16) // token='*' @@ -33889,12 +33709,12 @@ _tmp_138_rule(Parser *p) (star_target_var = star_target_rule(p)) // star_target ) { - D(fprintf(stderr, "%*c+ _tmp_138[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "!'*' star_target")); + D(fprintf(stderr, "%*c+ _tmp_139[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "!'*' star_target")); _res = star_target_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_138[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_139[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "!'*' star_target")); } _res = NULL; @@ -33903,13 +33723,12 @@ _tmp_138_rule(Parser *p) return _res; } -// _loop0_140: ',' del_target +// _loop0_141: ',' del_target static asdl_seq * -_loop0_140_rule(Parser *p) +_loop0_141_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -33931,7 +33750,7 @@ _loop0_140_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_140[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' del_target")); + D(fprintf(stderr, "%*c> _loop0_141[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' del_target")); Token * _literal; expr_ty elem; while ( @@ -33963,7 +33782,7 @@ _loop0_140_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_140[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_141[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' del_target")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -33980,13 +33799,12 @@ _loop0_140_rule(Parser *p) return _seq; } -// _gather_139: del_target _loop0_140 +// _gather_140: del_target _loop0_141 static asdl_seq * -_gather_139_rule(Parser *p) +_gather_140_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -33994,27 +33812,27 @@ _gather_139_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // del_target _loop0_140 + { // del_target _loop0_141 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_139[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "del_target _loop0_140")); + D(fprintf(stderr, "%*c> _gather_140[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "del_target _loop0_141")); expr_ty elem; asdl_seq * seq; if ( (elem = del_target_rule(p)) // del_target && - (seq = _loop0_140_rule(p)) // _loop0_140 + (seq = _loop0_141_rule(p)) // _loop0_141 ) { - D(fprintf(stderr, "%*c+ _gather_139[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "del_target _loop0_140")); + D(fprintf(stderr, "%*c+ _gather_140[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "del_target _loop0_141")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_139[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "del_target _loop0_140")); + D(fprintf(stderr, "%*c%s _gather_140[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "del_target _loop0_141")); } _res = NULL; done: @@ -34022,13 +33840,12 @@ _gather_139_rule(Parser *p) return _res; } -// _loop0_142: ',' expression +// _loop0_143: ',' expression static asdl_seq * -_loop0_142_rule(Parser *p) +_loop0_143_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -34050,7 +33867,7 @@ _loop0_142_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_142[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression")); + D(fprintf(stderr, "%*c> _loop0_143[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression")); Token * _literal; expr_ty elem; while ( @@ -34082,7 +33899,7 @@ _loop0_142_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_142[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_143[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' expression")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -34099,13 +33916,12 @@ _loop0_142_rule(Parser *p) return _seq; } -// _gather_141: expression _loop0_142 +// _gather_142: expression _loop0_143 static asdl_seq * -_gather_141_rule(Parser *p) +_gather_142_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -34113,27 +33929,27 @@ _gather_141_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // expression _loop0_142 + { // expression _loop0_143 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_141[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression _loop0_142")); + D(fprintf(stderr, "%*c> _gather_142[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression _loop0_143")); expr_ty elem; asdl_seq * seq; if ( (elem = expression_rule(p)) // expression && - (seq = _loop0_142_rule(p)) // _loop0_142 + (seq = _loop0_143_rule(p)) // _loop0_143 ) { - D(fprintf(stderr, "%*c+ _gather_141[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression _loop0_142")); + D(fprintf(stderr, "%*c+ _gather_142[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression _loop0_143")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_141[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression _loop0_142")); + D(fprintf(stderr, "%*c%s _gather_142[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression _loop0_143")); } _res = NULL; done: @@ -34141,13 +33957,12 @@ _gather_141_rule(Parser *p) return _res; } -// _loop0_144: ',' expression +// _loop0_145: ',' expression static asdl_seq * -_loop0_144_rule(Parser *p) +_loop0_145_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -34169,7 +33984,7 @@ _loop0_144_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_144[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression")); + D(fprintf(stderr, "%*c> _loop0_145[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression")); Token * _literal; expr_ty elem; while ( @@ -34201,7 +34016,7 @@ _loop0_144_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_144[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_145[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' expression")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -34218,13 +34033,12 @@ _loop0_144_rule(Parser *p) return _seq; } -// _gather_143: expression _loop0_144 +// _gather_144: expression _loop0_145 static asdl_seq * -_gather_143_rule(Parser *p) +_gather_144_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -34232,27 +34046,27 @@ _gather_143_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // expression _loop0_144 + { // expression _loop0_145 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_143[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression _loop0_144")); + D(fprintf(stderr, "%*c> _gather_144[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression _loop0_145")); expr_ty elem; asdl_seq * seq; if ( (elem = expression_rule(p)) // expression && - (seq = _loop0_144_rule(p)) // _loop0_144 + (seq = _loop0_145_rule(p)) // _loop0_145 ) { - D(fprintf(stderr, "%*c+ _gather_143[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression _loop0_144")); + D(fprintf(stderr, "%*c+ _gather_144[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression _loop0_145")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_143[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression _loop0_144")); + D(fprintf(stderr, "%*c%s _gather_144[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression _loop0_145")); } _res = NULL; done: @@ -34260,13 +34074,12 @@ _gather_143_rule(Parser *p) return _res; } -// _loop0_146: ',' expression +// _loop0_147: ',' expression static asdl_seq * -_loop0_146_rule(Parser *p) +_loop0_147_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -34288,7 +34101,7 @@ _loop0_146_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_146[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression")); + D(fprintf(stderr, "%*c> _loop0_147[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression")); Token * _literal; expr_ty elem; while ( @@ -34320,7 +34133,7 @@ _loop0_146_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_146[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_147[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' expression")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -34337,13 +34150,12 @@ _loop0_146_rule(Parser *p) return _seq; } -// _gather_145: expression _loop0_146 +// _gather_146: expression _loop0_147 static asdl_seq * -_gather_145_rule(Parser *p) +_gather_146_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -34351,27 +34163,27 @@ _gather_145_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // expression _loop0_146 + { // expression _loop0_147 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_145[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression _loop0_146")); + D(fprintf(stderr, "%*c> _gather_146[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression _loop0_147")); expr_ty elem; asdl_seq * seq; if ( (elem = expression_rule(p)) // expression && - (seq = _loop0_146_rule(p)) // _loop0_146 + (seq = _loop0_147_rule(p)) // _loop0_147 ) { - D(fprintf(stderr, "%*c+ _gather_145[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression _loop0_146")); + D(fprintf(stderr, "%*c+ _gather_146[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression _loop0_147")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_145[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression _loop0_146")); + D(fprintf(stderr, "%*c%s _gather_146[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression _loop0_147")); } _res = NULL; done: @@ -34379,13 +34191,12 @@ _gather_145_rule(Parser *p) return _res; } -// _loop0_148: ',' expression +// _loop0_149: ',' expression static asdl_seq * -_loop0_148_rule(Parser *p) +_loop0_149_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -34407,7 +34218,7 @@ _loop0_148_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_148[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression")); + D(fprintf(stderr, "%*c> _loop0_149[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression")); Token * _literal; expr_ty elem; while ( @@ -34439,7 +34250,7 @@ _loop0_148_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_148[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_149[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' expression")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -34456,13 +34267,12 @@ _loop0_148_rule(Parser *p) return _seq; } -// _gather_147: expression _loop0_148 +// _gather_148: expression _loop0_149 static asdl_seq * -_gather_147_rule(Parser *p) +_gather_148_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -34470,27 +34280,27 @@ _gather_147_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // expression _loop0_148 + { // expression _loop0_149 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_147[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression _loop0_148")); + D(fprintf(stderr, "%*c> _gather_148[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression _loop0_149")); expr_ty elem; asdl_seq * seq; if ( (elem = expression_rule(p)) // expression && - (seq = _loop0_148_rule(p)) // _loop0_148 + (seq = _loop0_149_rule(p)) // _loop0_149 ) { - D(fprintf(stderr, "%*c+ _gather_147[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression _loop0_148")); + D(fprintf(stderr, "%*c+ _gather_148[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression _loop0_149")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_147[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression _loop0_148")); + D(fprintf(stderr, "%*c%s _gather_148[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression _loop0_149")); } _res = NULL; done: @@ -34498,13 +34308,12 @@ _gather_147_rule(Parser *p) return _res; } -// _tmp_149: NEWLINE INDENT +// _tmp_150: NEWLINE INDENT static void * -_tmp_149_rule(Parser *p) +_tmp_150_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -34517,7 +34326,7 @@ _tmp_149_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_149[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NEWLINE INDENT")); + D(fprintf(stderr, "%*c> _tmp_150[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NEWLINE INDENT")); Token * indent_var; Token * newline_var; if ( @@ -34526,12 +34335,12 @@ _tmp_149_rule(Parser *p) (indent_var = _PyPegen_expect_token(p, INDENT)) // token='INDENT' ) { - D(fprintf(stderr, "%*c+ _tmp_149[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NEWLINE INDENT")); + D(fprintf(stderr, "%*c+ _tmp_150[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NEWLINE INDENT")); _res = _PyPegen_dummy_name(p, newline_var, indent_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_149[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_150[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "NEWLINE INDENT")); } _res = NULL; @@ -34540,13 +34349,71 @@ _tmp_149_rule(Parser *p) return _res; } -// _tmp_150: args | expression for_if_clauses +// _tmp_151: +// | (','.(starred_expression | (assignment_expression | expression !':=') !'=')+ ',' kwargs) +// | kwargs static void * -_tmp_150_rule(Parser *p) +_tmp_151_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); + } + if (p->error_indicator) { + p->level--; + return NULL; + } + void * _res = NULL; + int _mark = p->mark; + { // (','.(starred_expression | (assignment_expression | expression !':=') !'=')+ ',' kwargs) + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> _tmp_151[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(','.(starred_expression | (assignment_expression | expression !':=') !'=')+ ',' kwargs)")); + void *_tmp_265_var; + if ( + (_tmp_265_var = _tmp_265_rule(p)) // ','.(starred_expression | (assignment_expression | expression !':=') !'=')+ ',' kwargs + ) + { + D(fprintf(stderr, "%*c+ _tmp_151[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(','.(starred_expression | (assignment_expression | expression !':=') !'=')+ ',' kwargs)")); + _res = _tmp_265_var; + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s _tmp_151[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(','.(starred_expression | (assignment_expression | expression !':=') !'=')+ ',' kwargs)")); + } + { // kwargs + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> _tmp_151[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kwargs")); + asdl_seq* kwargs_var; + if ( + (kwargs_var = kwargs_rule(p)) // kwargs + ) + { + D(fprintf(stderr, "%*c+ _tmp_151[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "kwargs")); + _res = kwargs_var; + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s _tmp_151[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "kwargs")); + } + _res = NULL; + done: + p->level--; + return _res; +} + +// _tmp_152: args | expression for_if_clauses +static void * +_tmp_152_rule(Parser *p) +{ + if (p->level++ == MAXSTACK) { + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -34559,18 +34426,18 @@ _tmp_150_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_150[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "args")); + D(fprintf(stderr, "%*c> _tmp_152[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "args")); expr_ty args_var; if ( (args_var = args_rule(p)) // args ) { - D(fprintf(stderr, "%*c+ _tmp_150[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "args")); + D(fprintf(stderr, "%*c+ _tmp_152[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "args")); _res = args_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_150[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_152[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "args")); } { // expression for_if_clauses @@ -34578,7 +34445,7 @@ _tmp_150_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_150[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression for_if_clauses")); + D(fprintf(stderr, "%*c> _tmp_152[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression for_if_clauses")); expr_ty expression_var; asdl_comprehension_seq* for_if_clauses_var; if ( @@ -34587,12 +34454,12 @@ _tmp_150_rule(Parser *p) (for_if_clauses_var = for_if_clauses_rule(p)) // for_if_clauses ) { - D(fprintf(stderr, "%*c+ _tmp_150[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression for_if_clauses")); + D(fprintf(stderr, "%*c+ _tmp_152[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression for_if_clauses")); _res = _PyPegen_dummy_name(p, expression_var, for_if_clauses_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_150[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_152[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression for_if_clauses")); } _res = NULL; @@ -34601,13 +34468,12 @@ _tmp_150_rule(Parser *p) return _res; } -// _tmp_151: args ',' +// _tmp_153: args ',' static void * -_tmp_151_rule(Parser *p) +_tmp_153_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -34620,7 +34486,7 @@ _tmp_151_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_151[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "args ','")); + D(fprintf(stderr, "%*c> _tmp_153[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "args ','")); Token * _literal; expr_ty args_var; if ( @@ -34629,12 +34495,12 @@ _tmp_151_rule(Parser *p) (_literal = _PyPegen_expect_token(p, 12)) // token=',' ) { - D(fprintf(stderr, "%*c+ _tmp_151[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "args ','")); + D(fprintf(stderr, "%*c+ _tmp_153[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "args ','")); _res = _PyPegen_dummy_name(p, args_var, _literal); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_151[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_153[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "args ','")); } _res = NULL; @@ -34643,13 +34509,12 @@ _tmp_151_rule(Parser *p) return _res; } -// _tmp_152: ',' | ')' +// _tmp_154: ',' | ')' static void * -_tmp_152_rule(Parser *p) +_tmp_154_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -34662,18 +34527,18 @@ _tmp_152_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_152[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c> _tmp_154[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' ) { - D(fprintf(stderr, "%*c+ _tmp_152[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c+ _tmp_154[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_152[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_154[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "','")); } { // ')' @@ -34681,18 +34546,18 @@ _tmp_152_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_152[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); + D(fprintf(stderr, "%*c> _tmp_154[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 8)) // token=')' ) { - D(fprintf(stderr, "%*c+ _tmp_152[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'")); + D(fprintf(stderr, "%*c+ _tmp_154[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_152[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_154[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "')'")); } _res = NULL; @@ -34701,13 +34566,12 @@ _tmp_152_rule(Parser *p) return _res; } -// _tmp_153: 'True' | 'False' | 'None' +// _tmp_155: 'True' | 'False' | 'None' static void * -_tmp_153_rule(Parser *p) +_tmp_155_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -34720,18 +34584,18 @@ _tmp_153_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_153[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'True'")); + D(fprintf(stderr, "%*c> _tmp_155[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'True'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 610)) // token='True' + (_keyword = _PyPegen_expect_token(p, 613)) // token='True' ) { - D(fprintf(stderr, "%*c+ _tmp_153[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'True'")); + D(fprintf(stderr, "%*c+ _tmp_155[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'True'")); _res = _keyword; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_153[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_155[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'True'")); } { // 'False' @@ -34739,18 +34603,18 @@ _tmp_153_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_153[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'False'")); + D(fprintf(stderr, "%*c> _tmp_155[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'False'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 612)) // token='False' + (_keyword = _PyPegen_expect_token(p, 615)) // token='False' ) { - D(fprintf(stderr, "%*c+ _tmp_153[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'False'")); + D(fprintf(stderr, "%*c+ _tmp_155[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'False'")); _res = _keyword; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_153[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_155[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'False'")); } { // 'None' @@ -34758,18 +34622,18 @@ _tmp_153_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_153[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'None'")); + D(fprintf(stderr, "%*c> _tmp_155[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'None'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 611)) // token='None' + (_keyword = _PyPegen_expect_token(p, 614)) // token='None' ) { - D(fprintf(stderr, "%*c+ _tmp_153[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'None'")); + D(fprintf(stderr, "%*c+ _tmp_155[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'None'")); _res = _keyword; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_153[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_155[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'None'")); } _res = NULL; @@ -34778,13 +34642,12 @@ _tmp_153_rule(Parser *p) return _res; } -// _tmp_154: NAME '=' +// _tmp_156: NAME '=' static void * -_tmp_154_rule(Parser *p) +_tmp_156_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -34797,7 +34660,7 @@ _tmp_154_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_154[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME '='")); + D(fprintf(stderr, "%*c> _tmp_156[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME '='")); Token * _literal; expr_ty name_var; if ( @@ -34806,12 +34669,12 @@ _tmp_154_rule(Parser *p) (_literal = _PyPegen_expect_token(p, 22)) // token='=' ) { - D(fprintf(stderr, "%*c+ _tmp_154[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME '='")); + D(fprintf(stderr, "%*c+ _tmp_156[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME '='")); _res = _PyPegen_dummy_name(p, name_var, _literal); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_154[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_156[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "NAME '='")); } _res = NULL; @@ -34820,13 +34683,12 @@ _tmp_154_rule(Parser *p) return _res; } -// _tmp_155: NAME STRING | SOFT_KEYWORD +// _tmp_157: NAME STRING | SOFT_KEYWORD static void * -_tmp_155_rule(Parser *p) +_tmp_157_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -34839,7 +34701,7 @@ _tmp_155_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_155[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME STRING")); + D(fprintf(stderr, "%*c> _tmp_157[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME STRING")); expr_ty name_var; expr_ty string_var; if ( @@ -34848,12 +34710,12 @@ _tmp_155_rule(Parser *p) (string_var = _PyPegen_string_token(p)) // STRING ) { - D(fprintf(stderr, "%*c+ _tmp_155[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME STRING")); + D(fprintf(stderr, "%*c+ _tmp_157[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME STRING")); _res = _PyPegen_dummy_name(p, name_var, string_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_155[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_157[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "NAME STRING")); } { // SOFT_KEYWORD @@ -34861,18 +34723,18 @@ _tmp_155_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_155[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "SOFT_KEYWORD")); + D(fprintf(stderr, "%*c> _tmp_157[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "SOFT_KEYWORD")); expr_ty soft_keyword_var; if ( (soft_keyword_var = _PyPegen_soft_keyword_token(p)) // SOFT_KEYWORD ) { - D(fprintf(stderr, "%*c+ _tmp_155[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "SOFT_KEYWORD")); + D(fprintf(stderr, "%*c+ _tmp_157[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "SOFT_KEYWORD")); _res = soft_keyword_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_155[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_157[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "SOFT_KEYWORD")); } _res = NULL; @@ -34881,13 +34743,12 @@ _tmp_155_rule(Parser *p) return _res; } -// _tmp_156: 'else' | ':' +// _tmp_158: 'else' | ':' static void * -_tmp_156_rule(Parser *p) +_tmp_158_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -34900,18 +34761,18 @@ _tmp_156_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_156[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'else'")); + D(fprintf(stderr, "%*c> _tmp_158[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'else'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 659)) // token='else' + (_keyword = _PyPegen_expect_token(p, 664)) // token='else' ) { - D(fprintf(stderr, "%*c+ _tmp_156[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'else'")); + D(fprintf(stderr, "%*c+ _tmp_158[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'else'")); _res = _keyword; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_156[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_158[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'else'")); } { // ':' @@ -34919,18 +34780,18 @@ _tmp_156_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_156[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c> _tmp_158[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 11)) // token=':' ) { - D(fprintf(stderr, "%*c+ _tmp_156[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c+ _tmp_158[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_156[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_158[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':'")); } _res = NULL; @@ -34939,71 +34800,12 @@ _tmp_156_rule(Parser *p) return _res; } -// _tmp_157: FSTRING_MIDDLE | fstring_replacement_field +// _tmp_159: '=' | ':=' static void * -_tmp_157_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void * _res = NULL; - int _mark = p->mark; - { // FSTRING_MIDDLE - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_157[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "FSTRING_MIDDLE")); - Token * fstring_middle_var; - if ( - (fstring_middle_var = _PyPegen_expect_token(p, FSTRING_MIDDLE)) // token='FSTRING_MIDDLE' - ) - { - D(fprintf(stderr, "%*c+ _tmp_157[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "FSTRING_MIDDLE")); - _res = fstring_middle_var; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_157[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "FSTRING_MIDDLE")); - } - { // fstring_replacement_field - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_157[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "fstring_replacement_field")); - expr_ty fstring_replacement_field_var; - if ( - (fstring_replacement_field_var = fstring_replacement_field_rule(p)) // fstring_replacement_field - ) - { - D(fprintf(stderr, "%*c+ _tmp_157[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "fstring_replacement_field")); - _res = fstring_replacement_field_var; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_157[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "fstring_replacement_field")); - } - _res = NULL; - done: - p->level--; - return _res; -} - -// _tmp_158: '=' | ':=' -static void * -_tmp_158_rule(Parser *p) +_tmp_159_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -35016,18 +34818,18 @@ _tmp_158_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_158[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'='")); + D(fprintf(stderr, "%*c> _tmp_159[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'='")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 22)) // token='=' ) { - D(fprintf(stderr, "%*c+ _tmp_158[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'='")); + D(fprintf(stderr, "%*c+ _tmp_159[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'='")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_158[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_159[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'='")); } { // ':=' @@ -35035,18 +34837,18 @@ _tmp_158_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_158[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':='")); + D(fprintf(stderr, "%*c> _tmp_159[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':='")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 53)) // token=':=' ) { - D(fprintf(stderr, "%*c+ _tmp_158[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':='")); + D(fprintf(stderr, "%*c+ _tmp_159[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':='")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_158[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_159[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':='")); } _res = NULL; @@ -35055,13 +34857,12 @@ _tmp_158_rule(Parser *p) return _res; } -// _tmp_159: list | tuple | genexp | 'True' | 'None' | 'False' +// _tmp_160: list | tuple | genexp | 'True' | 'None' | 'False' static void * -_tmp_159_rule(Parser *p) +_tmp_160_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -35074,18 +34875,18 @@ _tmp_159_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_159[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "list")); + D(fprintf(stderr, "%*c> _tmp_160[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "list")); expr_ty list_var; if ( (list_var = list_rule(p)) // list ) { - D(fprintf(stderr, "%*c+ _tmp_159[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "list")); + D(fprintf(stderr, "%*c+ _tmp_160[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "list")); _res = list_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_159[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_160[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "list")); } { // tuple @@ -35093,18 +34894,18 @@ _tmp_159_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_159[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "tuple")); + D(fprintf(stderr, "%*c> _tmp_160[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "tuple")); expr_ty tuple_var; if ( (tuple_var = tuple_rule(p)) // tuple ) { - D(fprintf(stderr, "%*c+ _tmp_159[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "tuple")); + D(fprintf(stderr, "%*c+ _tmp_160[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "tuple")); _res = tuple_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_159[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_160[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "tuple")); } { // genexp @@ -35112,18 +34913,18 @@ _tmp_159_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_159[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "genexp")); + D(fprintf(stderr, "%*c> _tmp_160[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "genexp")); expr_ty genexp_var; if ( (genexp_var = genexp_rule(p)) // genexp ) { - D(fprintf(stderr, "%*c+ _tmp_159[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "genexp")); + D(fprintf(stderr, "%*c+ _tmp_160[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "genexp")); _res = genexp_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_159[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_160[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "genexp")); } { // 'True' @@ -35131,18 +34932,18 @@ _tmp_159_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_159[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'True'")); + D(fprintf(stderr, "%*c> _tmp_160[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'True'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 610)) // token='True' + (_keyword = _PyPegen_expect_token(p, 613)) // token='True' ) { - D(fprintf(stderr, "%*c+ _tmp_159[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'True'")); + D(fprintf(stderr, "%*c+ _tmp_160[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'True'")); _res = _keyword; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_159[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_160[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'True'")); } { // 'None' @@ -35150,18 +34951,18 @@ _tmp_159_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_159[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'None'")); + D(fprintf(stderr, "%*c> _tmp_160[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'None'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 611)) // token='None' + (_keyword = _PyPegen_expect_token(p, 614)) // token='None' ) { - D(fprintf(stderr, "%*c+ _tmp_159[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'None'")); + D(fprintf(stderr, "%*c+ _tmp_160[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'None'")); _res = _keyword; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_159[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_160[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'None'")); } { // 'False' @@ -35169,18 +34970,18 @@ _tmp_159_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_159[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'False'")); + D(fprintf(stderr, "%*c> _tmp_160[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'False'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 612)) // token='False' + (_keyword = _PyPegen_expect_token(p, 615)) // token='False' ) { - D(fprintf(stderr, "%*c+ _tmp_159[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'False'")); + D(fprintf(stderr, "%*c+ _tmp_160[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'False'")); _res = _keyword; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_159[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_160[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'False'")); } _res = NULL; @@ -35189,13 +34990,12 @@ _tmp_159_rule(Parser *p) return _res; } -// _tmp_160: '=' | ':=' +// _tmp_161: '=' | ':=' static void * -_tmp_160_rule(Parser *p) +_tmp_161_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -35208,18 +35008,18 @@ _tmp_160_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_160[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'='")); + D(fprintf(stderr, "%*c> _tmp_161[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'='")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 22)) // token='=' ) { - D(fprintf(stderr, "%*c+ _tmp_160[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'='")); + D(fprintf(stderr, "%*c+ _tmp_161[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'='")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_160[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_161[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'='")); } { // ':=' @@ -35227,18 +35027,18 @@ _tmp_160_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_160[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':='")); + D(fprintf(stderr, "%*c> _tmp_161[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':='")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 53)) // token=':=' ) { - D(fprintf(stderr, "%*c+ _tmp_160[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':='")); + D(fprintf(stderr, "%*c+ _tmp_161[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':='")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_160[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_161[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':='")); } _res = NULL; @@ -35247,13 +35047,12 @@ _tmp_160_rule(Parser *p) return _res; } -// _loop0_161: star_named_expressions +// _loop0_162: star_named_expressions static asdl_seq * -_loop0_161_rule(Parser *p) +_loop0_162_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -35275,7 +35074,7 @@ _loop0_161_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_161[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_named_expressions")); + D(fprintf(stderr, "%*c> _loop0_162[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_named_expressions")); asdl_expr_seq* star_named_expressions_var; while ( (star_named_expressions_var = star_named_expressions_rule(p)) // star_named_expressions @@ -35298,76 +35097,8 @@ _loop0_161_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_161[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_named_expressions")); - } - asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); - if (!_seq) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); - PyMem_Free(_children); - p->level--; - return _seq; -} - -// _loop0_162: (star_targets '=') -static asdl_seq * -_loop0_162_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void *_res = NULL; - int _mark = p->mark; - void **_children = PyMem_Malloc(sizeof(void *)); - if (!_children) { - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - Py_ssize_t _children_capacity = 1; - Py_ssize_t _n = 0; - { // (star_targets '=') - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _loop0_162[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(star_targets '=')")); - void *_tmp_263_var; - while ( - (_tmp_263_var = _tmp_263_rule(p)) // star_targets '=' - ) - { - _res = _tmp_263_var; - if (_n == _children_capacity) { - _children_capacity *= 2; - void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); - if (!_new_children) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - _children = _new_children; - } - _children[_n++] = _res; - _mark = p->mark; - } - p->mark = _mark; D(fprintf(stderr, "%*c%s _loop0_162[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(star_targets '=')")); + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_named_expressions")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); if (!_seq) { @@ -35388,8 +35119,7 @@ static asdl_seq * _loop0_163_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -35412,12 +35142,12 @@ _loop0_163_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> _loop0_163[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(star_targets '=')")); - void *_tmp_264_var; + void *_tmp_266_var; while ( - (_tmp_264_var = _tmp_264_rule(p)) // star_targets '=' + (_tmp_266_var = _tmp_266_rule(p)) // star_targets '=' ) { - _res = _tmp_264_var; + _res = _tmp_266_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -35451,13 +35181,79 @@ _loop0_163_rule(Parser *p) return _seq; } -// _tmp_164: yield_expr | star_expressions -static void * -_tmp_164_rule(Parser *p) +// _loop0_164: (star_targets '=') +static asdl_seq * +_loop0_164_rule(Parser *p) { if (p->level++ == MAXSTACK) { + _Pypegen_stack_overflow(p); + } + if (p->error_indicator) { + p->level--; + return NULL; + } + void *_res = NULL; + int _mark = p->mark; + void **_children = PyMem_Malloc(sizeof(void *)); + if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); + p->level--; + return NULL; + } + Py_ssize_t _children_capacity = 1; + Py_ssize_t _n = 0; + { // (star_targets '=') + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> _loop0_164[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(star_targets '=')")); + void *_tmp_267_var; + while ( + (_tmp_267_var = _tmp_267_rule(p)) // star_targets '=' + ) + { + _res = _tmp_267_var; + if (_n == _children_capacity) { + _children_capacity *= 2; + void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); + if (!_new_children) { + PyMem_Free(_children); + p->error_indicator = 1; + PyErr_NoMemory(); + p->level--; + return NULL; + } + _children = _new_children; + } + _children[_n++] = _res; + _mark = p->mark; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s _loop0_164[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(star_targets '=')")); + } + asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); + if (!_seq) { + PyMem_Free(_children); + p->error_indicator = 1; + PyErr_NoMemory(); + p->level--; + return NULL; + } + for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); + PyMem_Free(_children); + p->level--; + return _seq; +} + +// _tmp_165: yield_expr | star_expressions +static void * +_tmp_165_rule(Parser *p) +{ + if (p->level++ == MAXSTACK) { + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -35470,18 +35266,18 @@ _tmp_164_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_164[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); + D(fprintf(stderr, "%*c> _tmp_165[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); expr_ty yield_expr_var; if ( (yield_expr_var = yield_expr_rule(p)) // yield_expr ) { - D(fprintf(stderr, "%*c+ _tmp_164[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr")); + D(fprintf(stderr, "%*c+ _tmp_165[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr")); _res = yield_expr_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_164[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_165[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "yield_expr")); } { // star_expressions @@ -35489,18 +35285,18 @@ _tmp_164_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_164[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions")); + D(fprintf(stderr, "%*c> _tmp_165[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions")); expr_ty star_expressions_var; if ( (star_expressions_var = star_expressions_rule(p)) // star_expressions ) { - D(fprintf(stderr, "%*c+ _tmp_164[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions")); + D(fprintf(stderr, "%*c+ _tmp_165[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions")); _res = star_expressions_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_164[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_165[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_expressions")); } _res = NULL; @@ -35509,13 +35305,12 @@ _tmp_164_rule(Parser *p) return _res; } -// _tmp_165: '[' | '(' | '{' +// _tmp_166: '[' | '(' | '{' static void * -_tmp_165_rule(Parser *p) +_tmp_166_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -35528,18 +35323,18 @@ _tmp_165_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_165[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'['")); + D(fprintf(stderr, "%*c> _tmp_166[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'['")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 9)) // token='[' ) { - D(fprintf(stderr, "%*c+ _tmp_165[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'['")); + D(fprintf(stderr, "%*c+ _tmp_166[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'['")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_165[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_166[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'['")); } { // '(' @@ -35547,18 +35342,18 @@ _tmp_165_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_165[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'('")); + D(fprintf(stderr, "%*c> _tmp_166[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'('")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 7)) // token='(' ) { - D(fprintf(stderr, "%*c+ _tmp_165[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'('")); + D(fprintf(stderr, "%*c+ _tmp_166[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'('")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_165[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_166[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'('")); } { // '{' @@ -35566,18 +35361,18 @@ _tmp_165_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_165[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{'")); + D(fprintf(stderr, "%*c> _tmp_166[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 25)) // token='{' ) { - D(fprintf(stderr, "%*c+ _tmp_165[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{'")); + D(fprintf(stderr, "%*c+ _tmp_166[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_165[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_166[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'{'")); } _res = NULL; @@ -35586,13 +35381,12 @@ _tmp_165_rule(Parser *p) return _res; } -// _tmp_166: '[' | '{' +// _tmp_167: '[' | '{' static void * -_tmp_166_rule(Parser *p) +_tmp_167_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -35605,18 +35399,18 @@ _tmp_166_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_166[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'['")); + D(fprintf(stderr, "%*c> _tmp_167[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'['")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 9)) // token='[' ) { - D(fprintf(stderr, "%*c+ _tmp_166[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'['")); + D(fprintf(stderr, "%*c+ _tmp_167[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'['")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_166[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_167[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'['")); } { // '{' @@ -35624,18 +35418,18 @@ _tmp_166_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_166[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{'")); + D(fprintf(stderr, "%*c> _tmp_167[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 25)) // token='{' ) { - D(fprintf(stderr, "%*c+ _tmp_166[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{'")); + D(fprintf(stderr, "%*c+ _tmp_167[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_166[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_167[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'{'")); } _res = NULL; @@ -35644,13 +35438,12 @@ _tmp_166_rule(Parser *p) return _res; } -// _tmp_167: '[' | '{' +// _tmp_168: '[' | '{' static void * -_tmp_167_rule(Parser *p) +_tmp_168_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -35663,18 +35456,18 @@ _tmp_167_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_167[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'['")); + D(fprintf(stderr, "%*c> _tmp_168[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'['")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 9)) // token='[' ) { - D(fprintf(stderr, "%*c+ _tmp_167[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'['")); + D(fprintf(stderr, "%*c+ _tmp_168[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'['")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_167[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_168[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'['")); } { // '{' @@ -35682,18 +35475,18 @@ _tmp_167_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_167[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{'")); + D(fprintf(stderr, "%*c> _tmp_168[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 25)) // token='{' ) { - D(fprintf(stderr, "%*c+ _tmp_167[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{'")); + D(fprintf(stderr, "%*c+ _tmp_168[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_167[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_168[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'{'")); } _res = NULL; @@ -35702,13 +35495,12 @@ _tmp_167_rule(Parser *p) return _res; } -// _tmp_168: slash_no_default | slash_with_default +// _tmp_169: slash_no_default | slash_with_default static void * -_tmp_168_rule(Parser *p) +_tmp_169_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -35721,18 +35513,18 @@ _tmp_168_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_168[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "slash_no_default")); + D(fprintf(stderr, "%*c> _tmp_169[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "slash_no_default")); asdl_arg_seq* slash_no_default_var; if ( (slash_no_default_var = slash_no_default_rule(p)) // slash_no_default ) { - D(fprintf(stderr, "%*c+ _tmp_168[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "slash_no_default")); + D(fprintf(stderr, "%*c+ _tmp_169[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "slash_no_default")); _res = slash_no_default_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_168[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_169[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "slash_no_default")); } { // slash_with_default @@ -35740,18 +35532,18 @@ _tmp_168_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_168[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "slash_with_default")); + D(fprintf(stderr, "%*c> _tmp_169[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "slash_with_default")); SlashWithDefault* slash_with_default_var; if ( (slash_with_default_var = slash_with_default_rule(p)) // slash_with_default ) { - D(fprintf(stderr, "%*c+ _tmp_168[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "slash_with_default")); + D(fprintf(stderr, "%*c+ _tmp_169[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "slash_with_default")); _res = slash_with_default_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_168[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_169[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "slash_with_default")); } _res = NULL; @@ -35760,13 +35552,12 @@ _tmp_168_rule(Parser *p) return _res; } -// _loop0_169: param_maybe_default +// _loop0_170: param_maybe_default static asdl_seq * -_loop0_169_rule(Parser *p) +_loop0_170_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -35788,7 +35579,7 @@ _loop0_169_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_169[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_maybe_default")); + D(fprintf(stderr, "%*c> _loop0_170[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_maybe_default")); NameDefaultPair* param_maybe_default_var; while ( (param_maybe_default_var = param_maybe_default_rule(p)) // param_maybe_default @@ -35811,7 +35602,7 @@ _loop0_169_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_169[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_170[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_maybe_default")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -35828,13 +35619,12 @@ _loop0_169_rule(Parser *p) return _seq; } -// _loop0_170: param_no_default +// _loop0_171: param_no_default static asdl_seq * -_loop0_170_rule(Parser *p) +_loop0_171_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -35856,7 +35646,7 @@ _loop0_170_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_170[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); + D(fprintf(stderr, "%*c> _loop0_171[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); arg_ty param_no_default_var; while ( (param_no_default_var = param_no_default_rule(p)) // param_no_default @@ -35879,7 +35669,7 @@ _loop0_170_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_170[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_171[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_no_default")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -35896,13 +35686,12 @@ _loop0_170_rule(Parser *p) return _seq; } -// _loop0_171: param_no_default +// _loop0_172: param_no_default static asdl_seq * -_loop0_171_rule(Parser *p) +_loop0_172_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -35924,7 +35713,7 @@ _loop0_171_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_171[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); + D(fprintf(stderr, "%*c> _loop0_172[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); arg_ty param_no_default_var; while ( (param_no_default_var = param_no_default_rule(p)) // param_no_default @@ -35947,7 +35736,7 @@ _loop0_171_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_171[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_172[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_no_default")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -35964,13 +35753,12 @@ _loop0_171_rule(Parser *p) return _seq; } -// _loop1_172: param_no_default +// _loop1_173: param_no_default static asdl_seq * -_loop1_172_rule(Parser *p) +_loop1_173_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -35992,7 +35780,7 @@ _loop1_172_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_172[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); + D(fprintf(stderr, "%*c> _loop1_173[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); arg_ty param_no_default_var; while ( (param_no_default_var = param_no_default_rule(p)) // param_no_default @@ -36015,7 +35803,7 @@ _loop1_172_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_172[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_173[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_no_default")); } if (_n == 0 || p->error_indicator) { @@ -36037,13 +35825,12 @@ _loop1_172_rule(Parser *p) return _seq; } -// _tmp_173: slash_no_default | slash_with_default +// _tmp_174: slash_no_default | slash_with_default static void * -_tmp_173_rule(Parser *p) +_tmp_174_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -36056,18 +35843,18 @@ _tmp_173_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_173[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "slash_no_default")); + D(fprintf(stderr, "%*c> _tmp_174[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "slash_no_default")); asdl_arg_seq* slash_no_default_var; if ( (slash_no_default_var = slash_no_default_rule(p)) // slash_no_default ) { - D(fprintf(stderr, "%*c+ _tmp_173[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "slash_no_default")); + D(fprintf(stderr, "%*c+ _tmp_174[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "slash_no_default")); _res = slash_no_default_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_173[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_174[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "slash_no_default")); } { // slash_with_default @@ -36075,18 +35862,18 @@ _tmp_173_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_173[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "slash_with_default")); + D(fprintf(stderr, "%*c> _tmp_174[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "slash_with_default")); SlashWithDefault* slash_with_default_var; if ( (slash_with_default_var = slash_with_default_rule(p)) // slash_with_default ) { - D(fprintf(stderr, "%*c+ _tmp_173[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "slash_with_default")); + D(fprintf(stderr, "%*c+ _tmp_174[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "slash_with_default")); _res = slash_with_default_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_173[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_174[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "slash_with_default")); } _res = NULL; @@ -36095,13 +35882,12 @@ _tmp_173_rule(Parser *p) return _res; } -// _loop0_174: param_maybe_default +// _loop0_175: param_maybe_default static asdl_seq * -_loop0_174_rule(Parser *p) +_loop0_175_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -36123,7 +35909,7 @@ _loop0_174_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_174[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_maybe_default")); + D(fprintf(stderr, "%*c> _loop0_175[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_maybe_default")); NameDefaultPair* param_maybe_default_var; while ( (param_maybe_default_var = param_maybe_default_rule(p)) // param_maybe_default @@ -36146,7 +35932,7 @@ _loop0_174_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_174[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_175[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_maybe_default")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -36163,13 +35949,12 @@ _loop0_174_rule(Parser *p) return _seq; } -// _tmp_175: ',' | param_no_default +// _tmp_176: ',' | param_no_default static void * -_tmp_175_rule(Parser *p) +_tmp_176_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -36182,18 +35967,18 @@ _tmp_175_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_175[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c> _tmp_176[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' ) { - D(fprintf(stderr, "%*c+ _tmp_175[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c+ _tmp_176[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_175[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_176[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "','")); } { // param_no_default @@ -36201,18 +35986,18 @@ _tmp_175_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_175[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); + D(fprintf(stderr, "%*c> _tmp_176[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); arg_ty param_no_default_var; if ( (param_no_default_var = param_no_default_rule(p)) // param_no_default ) { - D(fprintf(stderr, "%*c+ _tmp_175[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "param_no_default")); + D(fprintf(stderr, "%*c+ _tmp_176[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "param_no_default")); _res = param_no_default_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_175[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_176[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_no_default")); } _res = NULL; @@ -36221,13 +36006,12 @@ _tmp_175_rule(Parser *p) return _res; } -// _loop0_176: param_maybe_default +// _loop0_177: param_maybe_default static asdl_seq * -_loop0_176_rule(Parser *p) +_loop0_177_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -36249,7 +36033,7 @@ _loop0_176_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_176[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_maybe_default")); + D(fprintf(stderr, "%*c> _loop0_177[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_maybe_default")); NameDefaultPair* param_maybe_default_var; while ( (param_maybe_default_var = param_maybe_default_rule(p)) // param_maybe_default @@ -36272,7 +36056,7 @@ _loop0_176_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_176[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_177[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_maybe_default")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -36289,13 +36073,12 @@ _loop0_176_rule(Parser *p) return _seq; } -// _loop1_177: param_maybe_default +// _loop1_178: param_maybe_default static asdl_seq * -_loop1_177_rule(Parser *p) +_loop1_178_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -36317,7 +36100,7 @@ _loop1_177_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_177[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_maybe_default")); + D(fprintf(stderr, "%*c> _loop1_178[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_maybe_default")); NameDefaultPair* param_maybe_default_var; while ( (param_maybe_default_var = param_maybe_default_rule(p)) // param_maybe_default @@ -36340,7 +36123,7 @@ _loop1_177_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_177[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_178[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_maybe_default")); } if (_n == 0 || p->error_indicator) { @@ -36362,13 +36145,12 @@ _loop1_177_rule(Parser *p) return _seq; } -// _tmp_178: ')' | ',' +// _tmp_179: ')' | ',' static void * -_tmp_178_rule(Parser *p) +_tmp_179_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -36381,18 +36163,18 @@ _tmp_178_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_178[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); + D(fprintf(stderr, "%*c> _tmp_179[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 8)) // token=')' ) { - D(fprintf(stderr, "%*c+ _tmp_178[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'")); + D(fprintf(stderr, "%*c+ _tmp_179[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_178[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_179[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "')'")); } { // ',' @@ -36400,18 +36182,18 @@ _tmp_178_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_178[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c> _tmp_179[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' ) { - D(fprintf(stderr, "%*c+ _tmp_178[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c+ _tmp_179[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_178[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_179[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "','")); } _res = NULL; @@ -36420,13 +36202,12 @@ _tmp_178_rule(Parser *p) return _res; } -// _tmp_179: ')' | ',' (')' | '**') +// _tmp_180: ')' | ',' (')' | '**') static void * -_tmp_179_rule(Parser *p) +_tmp_180_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -36439,18 +36220,18 @@ _tmp_179_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_179[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); + D(fprintf(stderr, "%*c> _tmp_180[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 8)) // token=')' ) { - D(fprintf(stderr, "%*c+ _tmp_179[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'")); + D(fprintf(stderr, "%*c+ _tmp_180[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_179[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_180[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "')'")); } { // ',' (')' | '**') @@ -36458,21 +36239,21 @@ _tmp_179_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_179[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (')' | '**')")); + D(fprintf(stderr, "%*c> _tmp_180[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (')' | '**')")); Token * _literal; - void *_tmp_265_var; + void *_tmp_268_var; if ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (_tmp_265_var = _tmp_265_rule(p)) // ')' | '**' + (_tmp_268_var = _tmp_268_rule(p)) // ')' | '**' ) { - D(fprintf(stderr, "%*c+ _tmp_179[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' (')' | '**')")); - _res = _PyPegen_dummy_name(p, _literal, _tmp_265_var); + D(fprintf(stderr, "%*c+ _tmp_180[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' (')' | '**')")); + _res = _PyPegen_dummy_name(p, _literal, _tmp_268_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_179[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_180[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (')' | '**')")); } _res = NULL; @@ -36481,13 +36262,12 @@ _tmp_179_rule(Parser *p) return _res; } -// _tmp_180: param_no_default | ',' +// _tmp_181: param_no_default | ',' static void * -_tmp_180_rule(Parser *p) +_tmp_181_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -36500,18 +36280,18 @@ _tmp_180_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_180[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); + D(fprintf(stderr, "%*c> _tmp_181[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); arg_ty param_no_default_var; if ( (param_no_default_var = param_no_default_rule(p)) // param_no_default ) { - D(fprintf(stderr, "%*c+ _tmp_180[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "param_no_default")); + D(fprintf(stderr, "%*c+ _tmp_181[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "param_no_default")); _res = param_no_default_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_180[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_181[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_no_default")); } { // ',' @@ -36519,18 +36299,18 @@ _tmp_180_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_180[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c> _tmp_181[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' ) { - D(fprintf(stderr, "%*c+ _tmp_180[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c+ _tmp_181[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_180[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_181[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "','")); } _res = NULL; @@ -36539,13 +36319,12 @@ _tmp_180_rule(Parser *p) return _res; } -// _loop0_181: param_maybe_default +// _loop0_182: param_maybe_default static asdl_seq * -_loop0_181_rule(Parser *p) +_loop0_182_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -36567,7 +36346,7 @@ _loop0_181_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_181[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_maybe_default")); + D(fprintf(stderr, "%*c> _loop0_182[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_maybe_default")); NameDefaultPair* param_maybe_default_var; while ( (param_maybe_default_var = param_maybe_default_rule(p)) // param_maybe_default @@ -36590,7 +36369,7 @@ _loop0_181_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_181[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_182[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_maybe_default")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -36607,13 +36386,12 @@ _loop0_181_rule(Parser *p) return _seq; } -// _tmp_182: param_no_default | ',' +// _tmp_183: param_no_default | ',' static void * -_tmp_182_rule(Parser *p) +_tmp_183_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -36626,18 +36404,18 @@ _tmp_182_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_182[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); + D(fprintf(stderr, "%*c> _tmp_183[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); arg_ty param_no_default_var; if ( (param_no_default_var = param_no_default_rule(p)) // param_no_default ) { - D(fprintf(stderr, "%*c+ _tmp_182[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "param_no_default")); + D(fprintf(stderr, "%*c+ _tmp_183[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "param_no_default")); _res = param_no_default_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_182[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_183[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_no_default")); } { // ',' @@ -36645,18 +36423,18 @@ _tmp_182_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_182[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c> _tmp_183[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' ) { - D(fprintf(stderr, "%*c+ _tmp_182[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c+ _tmp_183[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_182[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_183[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "','")); } _res = NULL; @@ -36665,13 +36443,12 @@ _tmp_182_rule(Parser *p) return _res; } -// _tmp_183: '*' | '**' | '/' +// _tmp_184: '*' | '**' | '/' static void * -_tmp_183_rule(Parser *p) +_tmp_184_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -36684,18 +36461,18 @@ _tmp_183_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_183[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*'")); + D(fprintf(stderr, "%*c> _tmp_184[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 16)) // token='*' ) { - D(fprintf(stderr, "%*c+ _tmp_183[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*'")); + D(fprintf(stderr, "%*c+ _tmp_184[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_183[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_184[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'*'")); } { // '**' @@ -36703,18 +36480,18 @@ _tmp_183_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_183[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**'")); + D(fprintf(stderr, "%*c> _tmp_184[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 35)) // token='**' ) { - D(fprintf(stderr, "%*c+ _tmp_183[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**'")); + D(fprintf(stderr, "%*c+ _tmp_184[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_183[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_184[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'**'")); } { // '/' @@ -36722,18 +36499,18 @@ _tmp_183_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_183[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'/'")); + D(fprintf(stderr, "%*c> _tmp_184[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'/'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 17)) // token='/' ) { - D(fprintf(stderr, "%*c+ _tmp_183[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'/'")); + D(fprintf(stderr, "%*c+ _tmp_184[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'/'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_183[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_184[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'/'")); } _res = NULL; @@ -36742,13 +36519,12 @@ _tmp_183_rule(Parser *p) return _res; } -// _loop1_184: param_with_default +// _loop1_185: param_with_default static asdl_seq * -_loop1_184_rule(Parser *p) +_loop1_185_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -36770,7 +36546,7 @@ _loop1_184_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_184[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default")); + D(fprintf(stderr, "%*c> _loop1_185[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default")); NameDefaultPair* param_with_default_var; while ( (param_with_default_var = param_with_default_rule(p)) // param_with_default @@ -36793,7 +36569,7 @@ _loop1_184_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_184[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_185[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_with_default")); } if (_n == 0 || p->error_indicator) { @@ -36815,13 +36591,12 @@ _loop1_184_rule(Parser *p) return _seq; } -// _tmp_185: lambda_slash_no_default | lambda_slash_with_default +// _tmp_186: lambda_slash_no_default | lambda_slash_with_default static void * -_tmp_185_rule(Parser *p) +_tmp_186_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -36834,18 +36609,18 @@ _tmp_185_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_185[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_slash_no_default")); + D(fprintf(stderr, "%*c> _tmp_186[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_slash_no_default")); asdl_arg_seq* lambda_slash_no_default_var; if ( (lambda_slash_no_default_var = lambda_slash_no_default_rule(p)) // lambda_slash_no_default ) { - D(fprintf(stderr, "%*c+ _tmp_185[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_slash_no_default")); + D(fprintf(stderr, "%*c+ _tmp_186[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_slash_no_default")); _res = lambda_slash_no_default_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_185[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_186[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_slash_no_default")); } { // lambda_slash_with_default @@ -36853,18 +36628,18 @@ _tmp_185_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_185[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_slash_with_default")); + D(fprintf(stderr, "%*c> _tmp_186[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_slash_with_default")); SlashWithDefault* lambda_slash_with_default_var; if ( (lambda_slash_with_default_var = lambda_slash_with_default_rule(p)) // lambda_slash_with_default ) { - D(fprintf(stderr, "%*c+ _tmp_185[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_slash_with_default")); + D(fprintf(stderr, "%*c+ _tmp_186[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_slash_with_default")); _res = lambda_slash_with_default_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_185[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_186[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_slash_with_default")); } _res = NULL; @@ -36873,13 +36648,12 @@ _tmp_185_rule(Parser *p) return _res; } -// _loop0_186: lambda_param_maybe_default +// _loop0_187: lambda_param_maybe_default static asdl_seq * -_loop0_186_rule(Parser *p) +_loop0_187_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -36901,7 +36675,7 @@ _loop0_186_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_186[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_maybe_default")); + D(fprintf(stderr, "%*c> _loop0_187[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_maybe_default")); NameDefaultPair* lambda_param_maybe_default_var; while ( (lambda_param_maybe_default_var = lambda_param_maybe_default_rule(p)) // lambda_param_maybe_default @@ -36924,7 +36698,7 @@ _loop0_186_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_186[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_187[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_maybe_default")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -36941,13 +36715,12 @@ _loop0_186_rule(Parser *p) return _seq; } -// _loop0_187: lambda_param_no_default +// _loop0_188: lambda_param_no_default static asdl_seq * -_loop0_187_rule(Parser *p) +_loop0_188_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -36969,7 +36742,7 @@ _loop0_187_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_187[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); + D(fprintf(stderr, "%*c> _loop0_188[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); arg_ty lambda_param_no_default_var; while ( (lambda_param_no_default_var = lambda_param_no_default_rule(p)) // lambda_param_no_default @@ -36992,7 +36765,7 @@ _loop0_187_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_187[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_188[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_no_default")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -37009,13 +36782,12 @@ _loop0_187_rule(Parser *p) return _seq; } -// _loop0_188: lambda_param_no_default +// _loop0_189: lambda_param_no_default static asdl_seq * -_loop0_188_rule(Parser *p) +_loop0_189_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -37037,7 +36809,7 @@ _loop0_188_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_188[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); + D(fprintf(stderr, "%*c> _loop0_189[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); arg_ty lambda_param_no_default_var; while ( (lambda_param_no_default_var = lambda_param_no_default_rule(p)) // lambda_param_no_default @@ -37060,7 +36832,7 @@ _loop0_188_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_188[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_189[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_no_default")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -37077,13 +36849,12 @@ _loop0_188_rule(Parser *p) return _seq; } -// _loop0_190: ',' lambda_param +// _loop0_191: ',' lambda_param static asdl_seq * -_loop0_190_rule(Parser *p) +_loop0_191_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -37105,7 +36876,7 @@ _loop0_190_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_190[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' lambda_param")); + D(fprintf(stderr, "%*c> _loop0_191[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' lambda_param")); Token * _literal; arg_ty elem; while ( @@ -37137,7 +36908,7 @@ _loop0_190_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_190[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_191[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' lambda_param")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -37154,13 +36925,12 @@ _loop0_190_rule(Parser *p) return _seq; } -// _gather_189: lambda_param _loop0_190 +// _gather_190: lambda_param _loop0_191 static asdl_seq * -_gather_189_rule(Parser *p) +_gather_190_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -37168,27 +36938,27 @@ _gather_189_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // lambda_param _loop0_190 + { // lambda_param _loop0_191 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_189[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param _loop0_190")); + D(fprintf(stderr, "%*c> _gather_190[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param _loop0_191")); arg_ty elem; asdl_seq * seq; if ( (elem = lambda_param_rule(p)) // lambda_param && - (seq = _loop0_190_rule(p)) // _loop0_190 + (seq = _loop0_191_rule(p)) // _loop0_191 ) { - D(fprintf(stderr, "%*c+ _gather_189[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_param _loop0_190")); + D(fprintf(stderr, "%*c+ _gather_190[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_param _loop0_191")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_189[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param _loop0_190")); + D(fprintf(stderr, "%*c%s _gather_190[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param _loop0_191")); } _res = NULL; done: @@ -37196,13 +36966,12 @@ _gather_189_rule(Parser *p) return _res; } -// _tmp_191: lambda_slash_no_default | lambda_slash_with_default +// _tmp_192: lambda_slash_no_default | lambda_slash_with_default static void * -_tmp_191_rule(Parser *p) +_tmp_192_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -37215,18 +36984,18 @@ _tmp_191_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_191[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_slash_no_default")); + D(fprintf(stderr, "%*c> _tmp_192[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_slash_no_default")); asdl_arg_seq* lambda_slash_no_default_var; if ( (lambda_slash_no_default_var = lambda_slash_no_default_rule(p)) // lambda_slash_no_default ) { - D(fprintf(stderr, "%*c+ _tmp_191[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_slash_no_default")); + D(fprintf(stderr, "%*c+ _tmp_192[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_slash_no_default")); _res = lambda_slash_no_default_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_191[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_192[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_slash_no_default")); } { // lambda_slash_with_default @@ -37234,18 +37003,18 @@ _tmp_191_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_191[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_slash_with_default")); + D(fprintf(stderr, "%*c> _tmp_192[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_slash_with_default")); SlashWithDefault* lambda_slash_with_default_var; if ( (lambda_slash_with_default_var = lambda_slash_with_default_rule(p)) // lambda_slash_with_default ) { - D(fprintf(stderr, "%*c+ _tmp_191[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_slash_with_default")); + D(fprintf(stderr, "%*c+ _tmp_192[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_slash_with_default")); _res = lambda_slash_with_default_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_191[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_192[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_slash_with_default")); } _res = NULL; @@ -37254,13 +37023,12 @@ _tmp_191_rule(Parser *p) return _res; } -// _loop0_192: lambda_param_maybe_default +// _loop0_193: lambda_param_maybe_default static asdl_seq * -_loop0_192_rule(Parser *p) +_loop0_193_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -37282,7 +37050,7 @@ _loop0_192_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_192[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_maybe_default")); + D(fprintf(stderr, "%*c> _loop0_193[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_maybe_default")); NameDefaultPair* lambda_param_maybe_default_var; while ( (lambda_param_maybe_default_var = lambda_param_maybe_default_rule(p)) // lambda_param_maybe_default @@ -37305,7 +37073,7 @@ _loop0_192_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_192[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_193[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_maybe_default")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -37322,13 +37090,12 @@ _loop0_192_rule(Parser *p) return _seq; } -// _tmp_193: ',' | lambda_param_no_default +// _tmp_194: ',' | lambda_param_no_default static void * -_tmp_193_rule(Parser *p) +_tmp_194_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -37341,18 +37108,18 @@ _tmp_193_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_193[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c> _tmp_194[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' ) { - D(fprintf(stderr, "%*c+ _tmp_193[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c+ _tmp_194[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_193[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_194[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "','")); } { // lambda_param_no_default @@ -37360,18 +37127,18 @@ _tmp_193_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_193[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); + D(fprintf(stderr, "%*c> _tmp_194[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); arg_ty lambda_param_no_default_var; if ( (lambda_param_no_default_var = lambda_param_no_default_rule(p)) // lambda_param_no_default ) { - D(fprintf(stderr, "%*c+ _tmp_193[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); + D(fprintf(stderr, "%*c+ _tmp_194[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); _res = lambda_param_no_default_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_193[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_194[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_no_default")); } _res = NULL; @@ -37380,13 +37147,12 @@ _tmp_193_rule(Parser *p) return _res; } -// _loop0_194: lambda_param_maybe_default +// _loop0_195: lambda_param_maybe_default static asdl_seq * -_loop0_194_rule(Parser *p) +_loop0_195_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -37408,7 +37174,7 @@ _loop0_194_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_194[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_maybe_default")); + D(fprintf(stderr, "%*c> _loop0_195[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_maybe_default")); NameDefaultPair* lambda_param_maybe_default_var; while ( (lambda_param_maybe_default_var = lambda_param_maybe_default_rule(p)) // lambda_param_maybe_default @@ -37431,7 +37197,7 @@ _loop0_194_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_194[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_195[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_maybe_default")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -37448,13 +37214,12 @@ _loop0_194_rule(Parser *p) return _seq; } -// _loop1_195: lambda_param_maybe_default +// _loop1_196: lambda_param_maybe_default static asdl_seq * -_loop1_195_rule(Parser *p) +_loop1_196_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -37476,7 +37241,7 @@ _loop1_195_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_195[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_maybe_default")); + D(fprintf(stderr, "%*c> _loop1_196[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_maybe_default")); NameDefaultPair* lambda_param_maybe_default_var; while ( (lambda_param_maybe_default_var = lambda_param_maybe_default_rule(p)) // lambda_param_maybe_default @@ -37499,7 +37264,7 @@ _loop1_195_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_195[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_196[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_maybe_default")); } if (_n == 0 || p->error_indicator) { @@ -37521,13 +37286,12 @@ _loop1_195_rule(Parser *p) return _seq; } -// _loop1_196: lambda_param_with_default +// _loop1_197: lambda_param_with_default static asdl_seq * -_loop1_196_rule(Parser *p) +_loop1_197_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -37549,7 +37313,7 @@ _loop1_196_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_196[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); + D(fprintf(stderr, "%*c> _loop1_197[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); NameDefaultPair* lambda_param_with_default_var; while ( (lambda_param_with_default_var = lambda_param_with_default_rule(p)) // lambda_param_with_default @@ -37572,7 +37336,7 @@ _loop1_196_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_196[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_197[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_with_default")); } if (_n == 0 || p->error_indicator) { @@ -37594,13 +37358,12 @@ _loop1_196_rule(Parser *p) return _seq; } -// _tmp_197: ':' | ',' (':' | '**') +// _tmp_198: ':' | ',' (':' | '**') static void * -_tmp_197_rule(Parser *p) +_tmp_198_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -37613,18 +37376,18 @@ _tmp_197_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_197[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c> _tmp_198[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 11)) // token=':' ) { - D(fprintf(stderr, "%*c+ _tmp_197[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c+ _tmp_198[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_197[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_198[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':'")); } { // ',' (':' | '**') @@ -37632,21 +37395,21 @@ _tmp_197_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_197[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (':' | '**')")); + D(fprintf(stderr, "%*c> _tmp_198[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (':' | '**')")); Token * _literal; - void *_tmp_266_var; + void *_tmp_269_var; if ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (_tmp_266_var = _tmp_266_rule(p)) // ':' | '**' + (_tmp_269_var = _tmp_269_rule(p)) // ':' | '**' ) { - D(fprintf(stderr, "%*c+ _tmp_197[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' (':' | '**')")); - _res = _PyPegen_dummy_name(p, _literal, _tmp_266_var); + D(fprintf(stderr, "%*c+ _tmp_198[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' (':' | '**')")); + _res = _PyPegen_dummy_name(p, _literal, _tmp_269_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_197[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_198[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (':' | '**')")); } _res = NULL; @@ -37655,13 +37418,12 @@ _tmp_197_rule(Parser *p) return _res; } -// _tmp_198: lambda_param_no_default | ',' +// _tmp_199: lambda_param_no_default | ',' static void * -_tmp_198_rule(Parser *p) +_tmp_199_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -37674,18 +37436,18 @@ _tmp_198_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_198[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); + D(fprintf(stderr, "%*c> _tmp_199[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); arg_ty lambda_param_no_default_var; if ( (lambda_param_no_default_var = lambda_param_no_default_rule(p)) // lambda_param_no_default ) { - D(fprintf(stderr, "%*c+ _tmp_198[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); + D(fprintf(stderr, "%*c+ _tmp_199[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); _res = lambda_param_no_default_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_198[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_199[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_no_default")); } { // ',' @@ -37693,18 +37455,18 @@ _tmp_198_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_198[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c> _tmp_199[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' ) { - D(fprintf(stderr, "%*c+ _tmp_198[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c+ _tmp_199[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_198[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_199[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "','")); } _res = NULL; @@ -37713,13 +37475,12 @@ _tmp_198_rule(Parser *p) return _res; } -// _loop0_199: lambda_param_maybe_default +// _loop0_200: lambda_param_maybe_default static asdl_seq * -_loop0_199_rule(Parser *p) +_loop0_200_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -37741,7 +37502,7 @@ _loop0_199_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_199[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_maybe_default")); + D(fprintf(stderr, "%*c> _loop0_200[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_maybe_default")); NameDefaultPair* lambda_param_maybe_default_var; while ( (lambda_param_maybe_default_var = lambda_param_maybe_default_rule(p)) // lambda_param_maybe_default @@ -37764,7 +37525,7 @@ _loop0_199_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_199[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_200[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_maybe_default")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -37781,13 +37542,12 @@ _loop0_199_rule(Parser *p) return _seq; } -// _tmp_200: lambda_param_no_default | ',' +// _tmp_201: lambda_param_no_default | ',' static void * -_tmp_200_rule(Parser *p) +_tmp_201_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -37800,18 +37560,18 @@ _tmp_200_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_200[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); + D(fprintf(stderr, "%*c> _tmp_201[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); arg_ty lambda_param_no_default_var; if ( (lambda_param_no_default_var = lambda_param_no_default_rule(p)) // lambda_param_no_default ) { - D(fprintf(stderr, "%*c+ _tmp_200[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); + D(fprintf(stderr, "%*c+ _tmp_201[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); _res = lambda_param_no_default_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_200[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_201[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_no_default")); } { // ',' @@ -37819,18 +37579,18 @@ _tmp_200_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_200[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c> _tmp_201[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' ) { - D(fprintf(stderr, "%*c+ _tmp_200[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c+ _tmp_201[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_200[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_201[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "','")); } _res = NULL; @@ -37839,13 +37599,12 @@ _tmp_200_rule(Parser *p) return _res; } -// _tmp_201: '*' | '**' | '/' +// _tmp_202: '*' | '**' | '/' static void * -_tmp_201_rule(Parser *p) +_tmp_202_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -37858,18 +37617,18 @@ _tmp_201_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_201[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*'")); + D(fprintf(stderr, "%*c> _tmp_202[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 16)) // token='*' ) { - D(fprintf(stderr, "%*c+ _tmp_201[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*'")); + D(fprintf(stderr, "%*c+ _tmp_202[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_201[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_202[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'*'")); } { // '**' @@ -37877,18 +37636,18 @@ _tmp_201_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_201[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**'")); + D(fprintf(stderr, "%*c> _tmp_202[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 35)) // token='**' ) { - D(fprintf(stderr, "%*c+ _tmp_201[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**'")); + D(fprintf(stderr, "%*c+ _tmp_202[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_201[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_202[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'**'")); } { // '/' @@ -37896,18 +37655,18 @@ _tmp_201_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_201[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'/'")); + D(fprintf(stderr, "%*c> _tmp_202[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'/'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 17)) // token='/' ) { - D(fprintf(stderr, "%*c+ _tmp_201[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'/'")); + D(fprintf(stderr, "%*c+ _tmp_202[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'/'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_201[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_202[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'/'")); } _res = NULL; @@ -37916,13 +37675,12 @@ _tmp_201_rule(Parser *p) return _res; } -// _tmp_202: ',' | ')' | ':' +// _tmp_203: ',' | ')' | ':' static void * -_tmp_202_rule(Parser *p) +_tmp_203_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -37935,18 +37693,18 @@ _tmp_202_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_202[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c> _tmp_203[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' ) { - D(fprintf(stderr, "%*c+ _tmp_202[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c+ _tmp_203[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_202[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_203[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "','")); } { // ')' @@ -37954,18 +37712,18 @@ _tmp_202_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_202[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); + D(fprintf(stderr, "%*c> _tmp_203[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 8)) // token=')' ) { - D(fprintf(stderr, "%*c+ _tmp_202[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'")); + D(fprintf(stderr, "%*c+ _tmp_203[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_202[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_203[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "')'")); } { // ':' @@ -37973,18 +37731,18 @@ _tmp_202_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_202[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c> _tmp_203[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 11)) // token=':' ) { - D(fprintf(stderr, "%*c+ _tmp_202[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c+ _tmp_203[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_202[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_203[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':'")); } _res = NULL; @@ -37993,13 +37751,12 @@ _tmp_202_rule(Parser *p) return _res; } -// _loop0_204: ',' dotted_name +// _loop0_205: ',' dotted_name static asdl_seq * -_loop0_204_rule(Parser *p) +_loop0_205_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -38021,7 +37778,7 @@ _loop0_204_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_204[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' dotted_name")); + D(fprintf(stderr, "%*c> _loop0_205[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' dotted_name")); Token * _literal; expr_ty elem; while ( @@ -38053,7 +37810,7 @@ _loop0_204_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_204[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_205[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' dotted_name")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -38070,13 +37827,12 @@ _loop0_204_rule(Parser *p) return _seq; } -// _gather_203: dotted_name _loop0_204 +// _gather_204: dotted_name _loop0_205 static asdl_seq * -_gather_203_rule(Parser *p) +_gather_204_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -38084,27 +37840,27 @@ _gather_203_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // dotted_name _loop0_204 + { // dotted_name _loop0_205 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_203[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "dotted_name _loop0_204")); + D(fprintf(stderr, "%*c> _gather_204[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "dotted_name _loop0_205")); expr_ty elem; asdl_seq * seq; if ( (elem = dotted_name_rule(p)) // dotted_name && - (seq = _loop0_204_rule(p)) // _loop0_204 + (seq = _loop0_205_rule(p)) // _loop0_205 ) { - D(fprintf(stderr, "%*c+ _gather_203[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "dotted_name _loop0_204")); + D(fprintf(stderr, "%*c+ _gather_204[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "dotted_name _loop0_205")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_203[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "dotted_name _loop0_204")); + D(fprintf(stderr, "%*c%s _gather_204[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "dotted_name _loop0_205")); } _res = NULL; done: @@ -38112,13 +37868,12 @@ _gather_203_rule(Parser *p) return _res; } -// _loop0_206: ',' (expression ['as' star_target]) +// _loop0_207: ',' (expression ['as' star_target]) static asdl_seq * -_loop0_206_rule(Parser *p) +_loop0_207_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -38140,13 +37895,13 @@ _loop0_206_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_206[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (expression ['as' star_target])")); + D(fprintf(stderr, "%*c> _loop0_207[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (expression ['as' star_target])")); Token * _literal; void *elem; while ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (elem = _tmp_267_rule(p)) // expression ['as' star_target] + (elem = _tmp_270_rule(p)) // expression ['as' star_target] ) { _res = elem; @@ -38172,7 +37927,7 @@ _loop0_206_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_206[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_207[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (expression ['as' star_target])")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -38189,13 +37944,12 @@ _loop0_206_rule(Parser *p) return _seq; } -// _gather_205: (expression ['as' star_target]) _loop0_206 +// _gather_206: (expression ['as' star_target]) _loop0_207 static asdl_seq * -_gather_205_rule(Parser *p) +_gather_206_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -38203,27 +37957,27 @@ _gather_205_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // (expression ['as' star_target]) _loop0_206 + { // (expression ['as' star_target]) _loop0_207 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_205[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expression ['as' star_target]) _loop0_206")); + D(fprintf(stderr, "%*c> _gather_206[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expression ['as' star_target]) _loop0_207")); void *elem; asdl_seq * seq; if ( - (elem = _tmp_267_rule(p)) // expression ['as' star_target] + (elem = _tmp_270_rule(p)) // expression ['as' star_target] && - (seq = _loop0_206_rule(p)) // _loop0_206 + (seq = _loop0_207_rule(p)) // _loop0_207 ) { - D(fprintf(stderr, "%*c+ _gather_205[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(expression ['as' star_target]) _loop0_206")); + D(fprintf(stderr, "%*c+ _gather_206[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(expression ['as' star_target]) _loop0_207")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_205[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(expression ['as' star_target]) _loop0_206")); + D(fprintf(stderr, "%*c%s _gather_206[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(expression ['as' star_target]) _loop0_207")); } _res = NULL; done: @@ -38231,13 +37985,12 @@ _gather_205_rule(Parser *p) return _res; } -// _loop0_208: ',' (expressions ['as' star_target]) +// _loop0_209: ',' (expressions ['as' star_target]) static asdl_seq * -_loop0_208_rule(Parser *p) +_loop0_209_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -38259,13 +38012,13 @@ _loop0_208_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_208[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (expressions ['as' star_target])")); + D(fprintf(stderr, "%*c> _loop0_209[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (expressions ['as' star_target])")); Token * _literal; void *elem; while ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (elem = _tmp_268_rule(p)) // expressions ['as' star_target] + (elem = _tmp_271_rule(p)) // expressions ['as' star_target] ) { _res = elem; @@ -38291,7 +38044,7 @@ _loop0_208_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_208[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_209[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (expressions ['as' star_target])")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -38308,13 +38061,12 @@ _loop0_208_rule(Parser *p) return _seq; } -// _gather_207: (expressions ['as' star_target]) _loop0_208 +// _gather_208: (expressions ['as' star_target]) _loop0_209 static asdl_seq * -_gather_207_rule(Parser *p) +_gather_208_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -38322,27 +38074,27 @@ _gather_207_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // (expressions ['as' star_target]) _loop0_208 + { // (expressions ['as' star_target]) _loop0_209 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_207[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expressions ['as' star_target]) _loop0_208")); + D(fprintf(stderr, "%*c> _gather_208[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expressions ['as' star_target]) _loop0_209")); void *elem; asdl_seq * seq; if ( - (elem = _tmp_268_rule(p)) // expressions ['as' star_target] + (elem = _tmp_271_rule(p)) // expressions ['as' star_target] && - (seq = _loop0_208_rule(p)) // _loop0_208 + (seq = _loop0_209_rule(p)) // _loop0_209 ) { - D(fprintf(stderr, "%*c+ _gather_207[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(expressions ['as' star_target]) _loop0_208")); + D(fprintf(stderr, "%*c+ _gather_208[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(expressions ['as' star_target]) _loop0_209")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_207[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(expressions ['as' star_target]) _loop0_208")); + D(fprintf(stderr, "%*c%s _gather_208[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(expressions ['as' star_target]) _loop0_209")); } _res = NULL; done: @@ -38350,13 +38102,12 @@ _gather_207_rule(Parser *p) return _res; } -// _loop0_210: ',' (expression ['as' star_target]) +// _loop0_211: ',' (expression ['as' star_target]) static asdl_seq * -_loop0_210_rule(Parser *p) +_loop0_211_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -38378,13 +38129,13 @@ _loop0_210_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_210[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (expression ['as' star_target])")); + D(fprintf(stderr, "%*c> _loop0_211[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (expression ['as' star_target])")); Token * _literal; void *elem; while ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (elem = _tmp_269_rule(p)) // expression ['as' star_target] + (elem = _tmp_272_rule(p)) // expression ['as' star_target] ) { _res = elem; @@ -38410,7 +38161,7 @@ _loop0_210_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_210[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_211[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (expression ['as' star_target])")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -38427,13 +38178,12 @@ _loop0_210_rule(Parser *p) return _seq; } -// _gather_209: (expression ['as' star_target]) _loop0_210 +// _gather_210: (expression ['as' star_target]) _loop0_211 static asdl_seq * -_gather_209_rule(Parser *p) +_gather_210_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -38441,27 +38191,27 @@ _gather_209_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // (expression ['as' star_target]) _loop0_210 + { // (expression ['as' star_target]) _loop0_211 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_209[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expression ['as' star_target]) _loop0_210")); + D(fprintf(stderr, "%*c> _gather_210[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expression ['as' star_target]) _loop0_211")); void *elem; asdl_seq * seq; if ( - (elem = _tmp_269_rule(p)) // expression ['as' star_target] + (elem = _tmp_272_rule(p)) // expression ['as' star_target] && - (seq = _loop0_210_rule(p)) // _loop0_210 + (seq = _loop0_211_rule(p)) // _loop0_211 ) { - D(fprintf(stderr, "%*c+ _gather_209[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(expression ['as' star_target]) _loop0_210")); + D(fprintf(stderr, "%*c+ _gather_210[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(expression ['as' star_target]) _loop0_211")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_209[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(expression ['as' star_target]) _loop0_210")); + D(fprintf(stderr, "%*c%s _gather_210[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(expression ['as' star_target]) _loop0_211")); } _res = NULL; done: @@ -38469,13 +38219,12 @@ _gather_209_rule(Parser *p) return _res; } -// _loop0_212: ',' (expressions ['as' star_target]) +// _loop0_213: ',' (expressions ['as' star_target]) static asdl_seq * -_loop0_212_rule(Parser *p) +_loop0_213_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -38497,13 +38246,13 @@ _loop0_212_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_212[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (expressions ['as' star_target])")); + D(fprintf(stderr, "%*c> _loop0_213[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (expressions ['as' star_target])")); Token * _literal; void *elem; while ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (elem = _tmp_270_rule(p)) // expressions ['as' star_target] + (elem = _tmp_273_rule(p)) // expressions ['as' star_target] ) { _res = elem; @@ -38529,7 +38278,7 @@ _loop0_212_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_212[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_213[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (expressions ['as' star_target])")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -38546,13 +38295,12 @@ _loop0_212_rule(Parser *p) return _seq; } -// _gather_211: (expressions ['as' star_target]) _loop0_212 +// _gather_212: (expressions ['as' star_target]) _loop0_213 static asdl_seq * -_gather_211_rule(Parser *p) +_gather_212_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -38560,27 +38308,27 @@ _gather_211_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // (expressions ['as' star_target]) _loop0_212 + { // (expressions ['as' star_target]) _loop0_213 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_211[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expressions ['as' star_target]) _loop0_212")); + D(fprintf(stderr, "%*c> _gather_212[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expressions ['as' star_target]) _loop0_213")); void *elem; asdl_seq * seq; if ( - (elem = _tmp_270_rule(p)) // expressions ['as' star_target] + (elem = _tmp_273_rule(p)) // expressions ['as' star_target] && - (seq = _loop0_212_rule(p)) // _loop0_212 + (seq = _loop0_213_rule(p)) // _loop0_213 ) { - D(fprintf(stderr, "%*c+ _gather_211[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(expressions ['as' star_target]) _loop0_212")); + D(fprintf(stderr, "%*c+ _gather_212[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(expressions ['as' star_target]) _loop0_213")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_211[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(expressions ['as' star_target]) _loop0_212")); + D(fprintf(stderr, "%*c%s _gather_212[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(expressions ['as' star_target]) _loop0_213")); } _res = NULL; done: @@ -38588,13 +38336,12 @@ _gather_211_rule(Parser *p) return _res; } -// _tmp_213: 'except' | 'finally' +// _tmp_214: 'except' | 'finally' static void * -_tmp_213_rule(Parser *p) +_tmp_214_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -38607,18 +38354,18 @@ _tmp_213_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_213[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'except'")); + D(fprintf(stderr, "%*c> _tmp_214[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'except'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 651)) // token='except' + (_keyword = _PyPegen_expect_token(p, 656)) // token='except' ) { - D(fprintf(stderr, "%*c+ _tmp_213[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'except'")); + D(fprintf(stderr, "%*c+ _tmp_214[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'except'")); _res = _keyword; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_213[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_214[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'except'")); } { // 'finally' @@ -38626,18 +38373,18 @@ _tmp_213_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_213[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'finally'")); + D(fprintf(stderr, "%*c> _tmp_214[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'finally'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 647)) // token='finally' + (_keyword = _PyPegen_expect_token(p, 652)) // token='finally' ) { - D(fprintf(stderr, "%*c+ _tmp_213[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'finally'")); + D(fprintf(stderr, "%*c+ _tmp_214[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'finally'")); _res = _keyword; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_213[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_214[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'finally'")); } _res = NULL; @@ -38646,13 +38393,12 @@ _tmp_213_rule(Parser *p) return _res; } -// _loop0_214: block +// _loop0_215: block static asdl_seq * -_loop0_214_rule(Parser *p) +_loop0_215_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -38674,7 +38420,7 @@ _loop0_214_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_214[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "block")); + D(fprintf(stderr, "%*c> _loop0_215[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "block")); asdl_stmt_seq* block_var; while ( (block_var = block_rule(p)) // block @@ -38697,7 +38443,7 @@ _loop0_214_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_214[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_215[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "block")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -38714,13 +38460,12 @@ _loop0_214_rule(Parser *p) return _seq; } -// _loop1_215: except_block +// _loop1_216: except_block static asdl_seq * -_loop1_215_rule(Parser *p) +_loop1_216_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -38742,7 +38487,7 @@ _loop1_215_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_215[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "except_block")); + D(fprintf(stderr, "%*c> _loop1_216[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "except_block")); excepthandler_ty except_block_var; while ( (except_block_var = except_block_rule(p)) // except_block @@ -38765,7 +38510,7 @@ _loop1_215_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_215[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_216[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "except_block")); } if (_n == 0 || p->error_indicator) { @@ -38787,13 +38532,12 @@ _loop1_215_rule(Parser *p) return _seq; } -// _tmp_216: 'as' NAME +// _tmp_217: 'as' NAME static void * -_tmp_216_rule(Parser *p) +_tmp_217_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -38806,21 +38550,21 @@ _tmp_216_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_216[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); + D(fprintf(stderr, "%*c> _tmp_217[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); Token * _keyword; expr_ty name_var; if ( - (_keyword = _PyPegen_expect_token(p, 654)) // token='as' + (_keyword = _PyPegen_expect_token(p, 659)) // token='as' && (name_var = _PyPegen_name_token(p)) // NAME ) { - D(fprintf(stderr, "%*c+ _tmp_216[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); + D(fprintf(stderr, "%*c+ _tmp_217[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); _res = _PyPegen_dummy_name(p, _keyword, name_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_216[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_217[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' NAME")); } _res = NULL; @@ -38829,13 +38573,12 @@ _tmp_216_rule(Parser *p) return _res; } -// _loop0_217: block +// _loop0_218: block static asdl_seq * -_loop0_217_rule(Parser *p) +_loop0_218_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -38857,7 +38600,7 @@ _loop0_217_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_217[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "block")); + D(fprintf(stderr, "%*c> _loop0_218[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "block")); asdl_stmt_seq* block_var; while ( (block_var = block_rule(p)) // block @@ -38880,7 +38623,7 @@ _loop0_217_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_217[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_218[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "block")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -38897,13 +38640,12 @@ _loop0_217_rule(Parser *p) return _seq; } -// _loop1_218: except_star_block +// _loop1_219: except_star_block static asdl_seq * -_loop1_218_rule(Parser *p) +_loop1_219_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -38925,7 +38667,7 @@ _loop1_218_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_218[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "except_star_block")); + D(fprintf(stderr, "%*c> _loop1_219[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "except_star_block")); excepthandler_ty except_star_block_var; while ( (except_star_block_var = except_star_block_rule(p)) // except_star_block @@ -38948,7 +38690,7 @@ _loop1_218_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_218[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_219[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "except_star_block")); } if (_n == 0 || p->error_indicator) { @@ -38970,13 +38712,12 @@ _loop1_218_rule(Parser *p) return _seq; } -// _tmp_219: expression ['as' NAME] +// _tmp_220: expression ['as' NAME] static void * -_tmp_219_rule(Parser *p) +_tmp_220_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -38989,22 +38730,22 @@ _tmp_219_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_219[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression ['as' NAME]")); + D(fprintf(stderr, "%*c> _tmp_220[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression ['as' NAME]")); void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings expr_ty expression_var; if ( (expression_var = expression_rule(p)) // expression && - (_opt_var = _tmp_271_rule(p), !p->error_indicator) // ['as' NAME] + (_opt_var = _tmp_274_rule(p), !p->error_indicator) // ['as' NAME] ) { - D(fprintf(stderr, "%*c+ _tmp_219[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ['as' NAME]")); + D(fprintf(stderr, "%*c+ _tmp_220[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ['as' NAME]")); _res = _PyPegen_dummy_name(p, expression_var, _opt_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_219[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_220[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression ['as' NAME]")); } _res = NULL; @@ -39013,13 +38754,12 @@ _tmp_219_rule(Parser *p) return _res; } -// _tmp_220: 'as' NAME +// _tmp_221: 'as' NAME static void * -_tmp_220_rule(Parser *p) +_tmp_221_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -39032,21 +38772,21 @@ _tmp_220_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_220[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); + D(fprintf(stderr, "%*c> _tmp_221[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); Token * _keyword; expr_ty name_var; if ( - (_keyword = _PyPegen_expect_token(p, 654)) // token='as' + (_keyword = _PyPegen_expect_token(p, 659)) // token='as' && (name_var = _PyPegen_name_token(p)) // NAME ) { - D(fprintf(stderr, "%*c+ _tmp_220[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); + D(fprintf(stderr, "%*c+ _tmp_221[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); _res = _PyPegen_dummy_name(p, _keyword, name_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_220[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_221[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' NAME")); } _res = NULL; @@ -39055,13 +38795,12 @@ _tmp_220_rule(Parser *p) return _res; } -// _tmp_221: 'as' NAME +// _tmp_222: 'as' NAME static void * -_tmp_221_rule(Parser *p) +_tmp_222_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -39074,21 +38813,21 @@ _tmp_221_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_221[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); + D(fprintf(stderr, "%*c> _tmp_222[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); Token * _keyword; expr_ty name_var; if ( - (_keyword = _PyPegen_expect_token(p, 654)) // token='as' + (_keyword = _PyPegen_expect_token(p, 659)) // token='as' && (name_var = _PyPegen_name_token(p)) // NAME ) { - D(fprintf(stderr, "%*c+ _tmp_221[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); + D(fprintf(stderr, "%*c+ _tmp_222[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); _res = _PyPegen_dummy_name(p, _keyword, name_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_221[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_222[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' NAME")); } _res = NULL; @@ -39097,13 +38836,12 @@ _tmp_221_rule(Parser *p) return _res; } -// _tmp_222: NEWLINE | ':' +// _tmp_223: NEWLINE | ':' static void * -_tmp_222_rule(Parser *p) +_tmp_223_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -39116,18 +38854,18 @@ _tmp_222_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_222[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NEWLINE")); + D(fprintf(stderr, "%*c> _tmp_223[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NEWLINE")); Token * newline_var; if ( (newline_var = _PyPegen_expect_token(p, NEWLINE)) // token='NEWLINE' ) { - D(fprintf(stderr, "%*c+ _tmp_222[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NEWLINE")); + D(fprintf(stderr, "%*c+ _tmp_223[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NEWLINE")); _res = newline_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_222[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_223[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "NEWLINE")); } { // ':' @@ -39135,18 +38873,18 @@ _tmp_222_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_222[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c> _tmp_223[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 11)) // token=':' ) { - D(fprintf(stderr, "%*c+ _tmp_222[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c+ _tmp_223[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_222[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_223[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':'")); } _res = NULL; @@ -39155,13 +38893,12 @@ _tmp_222_rule(Parser *p) return _res; } -// _tmp_223: 'as' NAME +// _tmp_224: 'as' NAME static void * -_tmp_223_rule(Parser *p) +_tmp_224_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -39174,21 +38911,21 @@ _tmp_223_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_223[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); + D(fprintf(stderr, "%*c> _tmp_224[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); Token * _keyword; expr_ty name_var; if ( - (_keyword = _PyPegen_expect_token(p, 654)) // token='as' + (_keyword = _PyPegen_expect_token(p, 659)) // token='as' && (name_var = _PyPegen_name_token(p)) // NAME ) { - D(fprintf(stderr, "%*c+ _tmp_223[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); + D(fprintf(stderr, "%*c+ _tmp_224[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); _res = _PyPegen_dummy_name(p, _keyword, name_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_223[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_224[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' NAME")); } _res = NULL; @@ -39197,13 +38934,12 @@ _tmp_223_rule(Parser *p) return _res; } -// _tmp_224: 'as' NAME +// _tmp_225: 'as' NAME static void * -_tmp_224_rule(Parser *p) +_tmp_225_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -39216,21 +38952,21 @@ _tmp_224_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_224[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); + D(fprintf(stderr, "%*c> _tmp_225[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); Token * _keyword; expr_ty name_var; if ( - (_keyword = _PyPegen_expect_token(p, 654)) // token='as' + (_keyword = _PyPegen_expect_token(p, 659)) // token='as' && (name_var = _PyPegen_name_token(p)) // NAME ) { - D(fprintf(stderr, "%*c+ _tmp_224[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); + D(fprintf(stderr, "%*c+ _tmp_225[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); _res = _PyPegen_dummy_name(p, _keyword, name_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_224[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_225[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' NAME")); } _res = NULL; @@ -39239,13 +38975,12 @@ _tmp_224_rule(Parser *p) return _res; } -// _tmp_225: positional_patterns ',' +// _tmp_226: positional_patterns ',' static void * -_tmp_225_rule(Parser *p) +_tmp_226_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -39258,7 +38993,7 @@ _tmp_225_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_225[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "positional_patterns ','")); + D(fprintf(stderr, "%*c> _tmp_226[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "positional_patterns ','")); Token * _literal; asdl_pattern_seq* positional_patterns_var; if ( @@ -39267,12 +39002,12 @@ _tmp_225_rule(Parser *p) (_literal = _PyPegen_expect_token(p, 12)) // token=',' ) { - D(fprintf(stderr, "%*c+ _tmp_225[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "positional_patterns ','")); + D(fprintf(stderr, "%*c+ _tmp_226[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "positional_patterns ','")); _res = _PyPegen_dummy_name(p, positional_patterns_var, _literal); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_225[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_226[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "positional_patterns ','")); } _res = NULL; @@ -39281,13 +39016,12 @@ _tmp_225_rule(Parser *p) return _res; } -// _tmp_226: '->' expression +// _tmp_227: '->' expression static void * -_tmp_226_rule(Parser *p) +_tmp_227_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -39300,7 +39034,7 @@ _tmp_226_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_226[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'->' expression")); + D(fprintf(stderr, "%*c> _tmp_227[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'->' expression")); Token * _literal; expr_ty expression_var; if ( @@ -39309,12 +39043,12 @@ _tmp_226_rule(Parser *p) (expression_var = expression_rule(p)) // expression ) { - D(fprintf(stderr, "%*c+ _tmp_226[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'->' expression")); + D(fprintf(stderr, "%*c+ _tmp_227[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'->' expression")); _res = _PyPegen_dummy_name(p, _literal, expression_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_226[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_227[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'->' expression")); } _res = NULL; @@ -39323,13 +39057,12 @@ _tmp_226_rule(Parser *p) return _res; } -// _tmp_227: '(' arguments? ')' +// _tmp_228: '(' arguments? ')' static void * -_tmp_227_rule(Parser *p) +_tmp_228_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -39342,7 +39075,7 @@ _tmp_227_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_227[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' arguments? ')'")); + D(fprintf(stderr, "%*c> _tmp_228[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' arguments? ')'")); Token * _literal; Token * _literal_1; void *_opt_var; @@ -39355,12 +39088,12 @@ _tmp_227_rule(Parser *p) (_literal_1 = _PyPegen_expect_token(p, 8)) // token=')' ) { - D(fprintf(stderr, "%*c+ _tmp_227[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' arguments? ')'")); + D(fprintf(stderr, "%*c+ _tmp_228[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' arguments? ')'")); _res = _PyPegen_dummy_name(p, _literal, _opt_var, _literal_1); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_227[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_228[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'(' arguments? ')'")); } _res = NULL; @@ -39369,13 +39102,12 @@ _tmp_227_rule(Parser *p) return _res; } -// _tmp_228: '(' arguments? ')' +// _tmp_229: '(' arguments? ')' static void * -_tmp_228_rule(Parser *p) +_tmp_229_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -39388,7 +39120,7 @@ _tmp_228_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_228[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' arguments? ')'")); + D(fprintf(stderr, "%*c> _tmp_229[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' arguments? ')'")); Token * _literal; Token * _literal_1; void *_opt_var; @@ -39401,12 +39133,12 @@ _tmp_228_rule(Parser *p) (_literal_1 = _PyPegen_expect_token(p, 8)) // token=')' ) { - D(fprintf(stderr, "%*c+ _tmp_228[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' arguments? ')'")); + D(fprintf(stderr, "%*c+ _tmp_229[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' arguments? ')'")); _res = _PyPegen_dummy_name(p, _literal, _opt_var, _literal_1); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_228[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_229[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'(' arguments? ')'")); } _res = NULL; @@ -39415,13 +39147,12 @@ _tmp_228_rule(Parser *p) return _res; } -// _loop0_230: ',' double_starred_kvpair +// _loop0_231: ',' double_starred_kvpair static asdl_seq * -_loop0_230_rule(Parser *p) +_loop0_231_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -39443,7 +39174,7 @@ _loop0_230_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_230[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' double_starred_kvpair")); + D(fprintf(stderr, "%*c> _loop0_231[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' double_starred_kvpair")); Token * _literal; KeyValuePair* elem; while ( @@ -39475,7 +39206,7 @@ _loop0_230_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_230[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_231[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' double_starred_kvpair")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -39492,13 +39223,12 @@ _loop0_230_rule(Parser *p) return _seq; } -// _gather_229: double_starred_kvpair _loop0_230 +// _gather_230: double_starred_kvpair _loop0_231 static asdl_seq * -_gather_229_rule(Parser *p) +_gather_230_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -39506,27 +39236,27 @@ _gather_229_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // double_starred_kvpair _loop0_230 + { // double_starred_kvpair _loop0_231 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_229[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "double_starred_kvpair _loop0_230")); + D(fprintf(stderr, "%*c> _gather_230[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "double_starred_kvpair _loop0_231")); KeyValuePair* elem; asdl_seq * seq; if ( (elem = double_starred_kvpair_rule(p)) // double_starred_kvpair && - (seq = _loop0_230_rule(p)) // _loop0_230 + (seq = _loop0_231_rule(p)) // _loop0_231 ) { - D(fprintf(stderr, "%*c+ _gather_229[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "double_starred_kvpair _loop0_230")); + D(fprintf(stderr, "%*c+ _gather_230[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "double_starred_kvpair _loop0_231")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_229[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "double_starred_kvpair _loop0_230")); + D(fprintf(stderr, "%*c%s _gather_230[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "double_starred_kvpair _loop0_231")); } _res = NULL; done: @@ -39534,13 +39264,12 @@ _gather_229_rule(Parser *p) return _res; } -// _tmp_231: '}' | ',' +// _tmp_232: '}' | ',' static void * -_tmp_231_rule(Parser *p) +_tmp_232_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -39553,18 +39282,18 @@ _tmp_231_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_231[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'}'")); + D(fprintf(stderr, "%*c> _tmp_232[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'}'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 26)) // token='}' ) { - D(fprintf(stderr, "%*c+ _tmp_231[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'}'")); + D(fprintf(stderr, "%*c+ _tmp_232[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'}'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_231[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_232[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'}'")); } { // ',' @@ -39572,18 +39301,18 @@ _tmp_231_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_231[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c> _tmp_232[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' ) { - D(fprintf(stderr, "%*c+ _tmp_231[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c+ _tmp_232[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_231[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_232[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "','")); } _res = NULL; @@ -39592,13 +39321,12 @@ _tmp_231_rule(Parser *p) return _res; } -// _tmp_232: '}' | ',' +// _tmp_233: '}' | ',' static void * -_tmp_232_rule(Parser *p) +_tmp_233_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -39611,18 +39339,18 @@ _tmp_232_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_232[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'}'")); + D(fprintf(stderr, "%*c> _tmp_233[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'}'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 26)) // token='}' ) { - D(fprintf(stderr, "%*c+ _tmp_232[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'}'")); + D(fprintf(stderr, "%*c+ _tmp_233[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'}'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_232[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_233[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'}'")); } { // ',' @@ -39630,18 +39358,18 @@ _tmp_232_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_232[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c> _tmp_233[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' ) { - D(fprintf(stderr, "%*c+ _tmp_232[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c+ _tmp_233[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_232[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_233[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "','")); } _res = NULL; @@ -39650,13 +39378,12 @@ _tmp_232_rule(Parser *p) return _res; } -// _tmp_233: yield_expr | star_expressions +// _tmp_234: yield_expr | star_expressions static void * -_tmp_233_rule(Parser *p) +_tmp_234_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -39669,18 +39396,18 @@ _tmp_233_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_233[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); + D(fprintf(stderr, "%*c> _tmp_234[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); expr_ty yield_expr_var; if ( (yield_expr_var = yield_expr_rule(p)) // yield_expr ) { - D(fprintf(stderr, "%*c+ _tmp_233[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr")); + D(fprintf(stderr, "%*c+ _tmp_234[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr")); _res = yield_expr_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_233[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_234[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "yield_expr")); } { // star_expressions @@ -39688,18 +39415,18 @@ _tmp_233_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_233[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions")); + D(fprintf(stderr, "%*c> _tmp_234[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions")); expr_ty star_expressions_var; if ( (star_expressions_var = star_expressions_rule(p)) // star_expressions ) { - D(fprintf(stderr, "%*c+ _tmp_233[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions")); + D(fprintf(stderr, "%*c+ _tmp_234[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions")); _res = star_expressions_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_233[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_234[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_expressions")); } _res = NULL; @@ -39708,13 +39435,12 @@ _tmp_233_rule(Parser *p) return _res; } -// _tmp_234: yield_expr | star_expressions +// _tmp_235: yield_expr | star_expressions static void * -_tmp_234_rule(Parser *p) +_tmp_235_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -39727,18 +39453,18 @@ _tmp_234_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_234[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); + D(fprintf(stderr, "%*c> _tmp_235[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); expr_ty yield_expr_var; if ( (yield_expr_var = yield_expr_rule(p)) // yield_expr ) { - D(fprintf(stderr, "%*c+ _tmp_234[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr")); + D(fprintf(stderr, "%*c+ _tmp_235[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr")); _res = yield_expr_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_234[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_235[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "yield_expr")); } { // star_expressions @@ -39746,18 +39472,18 @@ _tmp_234_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_234[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions")); + D(fprintf(stderr, "%*c> _tmp_235[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions")); expr_ty star_expressions_var; if ( (star_expressions_var = star_expressions_rule(p)) // star_expressions ) { - D(fprintf(stderr, "%*c+ _tmp_234[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions")); + D(fprintf(stderr, "%*c+ _tmp_235[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions")); _res = star_expressions_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_234[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_235[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_expressions")); } _res = NULL; @@ -39766,13 +39492,12 @@ _tmp_234_rule(Parser *p) return _res; } -// _tmp_235: '=' | '!' | ':' | '}' +// _tmp_236: '=' | '!' | ':' | '}' static void * -_tmp_235_rule(Parser *p) +_tmp_236_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -39785,18 +39510,18 @@ _tmp_235_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_235[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'='")); + D(fprintf(stderr, "%*c> _tmp_236[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'='")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 22)) // token='=' ) { - D(fprintf(stderr, "%*c+ _tmp_235[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'='")); + D(fprintf(stderr, "%*c+ _tmp_236[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'='")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_235[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_236[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'='")); } { // '!' @@ -39804,18 +39529,18 @@ _tmp_235_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_235[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'!'")); + D(fprintf(stderr, "%*c> _tmp_236[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'!'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 54)) // token='!' ) { - D(fprintf(stderr, "%*c+ _tmp_235[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'!'")); + D(fprintf(stderr, "%*c+ _tmp_236[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'!'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_235[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_236[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'!'")); } { // ':' @@ -39823,18 +39548,18 @@ _tmp_235_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_235[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c> _tmp_236[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 11)) // token=':' ) { - D(fprintf(stderr, "%*c+ _tmp_235[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c+ _tmp_236[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_235[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_236[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':'")); } { // '}' @@ -39842,18 +39567,18 @@ _tmp_235_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_235[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'}'")); + D(fprintf(stderr, "%*c> _tmp_236[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'}'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 26)) // token='}' ) { - D(fprintf(stderr, "%*c+ _tmp_235[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'}'")); + D(fprintf(stderr, "%*c+ _tmp_236[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'}'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_235[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_236[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'}'")); } _res = NULL; @@ -39862,13 +39587,12 @@ _tmp_235_rule(Parser *p) return _res; } -// _tmp_236: yield_expr | star_expressions +// _tmp_237: yield_expr | star_expressions static void * -_tmp_236_rule(Parser *p) +_tmp_237_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -39881,18 +39605,18 @@ _tmp_236_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_236[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); + D(fprintf(stderr, "%*c> _tmp_237[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); expr_ty yield_expr_var; if ( (yield_expr_var = yield_expr_rule(p)) // yield_expr ) { - D(fprintf(stderr, "%*c+ _tmp_236[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr")); + D(fprintf(stderr, "%*c+ _tmp_237[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr")); _res = yield_expr_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_236[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_237[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "yield_expr")); } { // star_expressions @@ -39900,18 +39624,18 @@ _tmp_236_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_236[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions")); + D(fprintf(stderr, "%*c> _tmp_237[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions")); expr_ty star_expressions_var; if ( (star_expressions_var = star_expressions_rule(p)) // star_expressions ) { - D(fprintf(stderr, "%*c+ _tmp_236[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions")); + D(fprintf(stderr, "%*c+ _tmp_237[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions")); _res = star_expressions_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_236[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_237[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_expressions")); } _res = NULL; @@ -39920,13 +39644,12 @@ _tmp_236_rule(Parser *p) return _res; } -// _tmp_237: '!' | ':' | '}' +// _tmp_238: '!' | ':' | '}' static void * -_tmp_237_rule(Parser *p) +_tmp_238_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -39939,18 +39662,18 @@ _tmp_237_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_237[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'!'")); + D(fprintf(stderr, "%*c> _tmp_238[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'!'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 54)) // token='!' ) { - D(fprintf(stderr, "%*c+ _tmp_237[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'!'")); + D(fprintf(stderr, "%*c+ _tmp_238[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'!'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_237[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_238[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'!'")); } { // ':' @@ -39958,18 +39681,18 @@ _tmp_237_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_237[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c> _tmp_238[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 11)) // token=':' ) { - D(fprintf(stderr, "%*c+ _tmp_237[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c+ _tmp_238[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_237[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_238[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':'")); } { // '}' @@ -39977,18 +39700,18 @@ _tmp_237_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_237[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'}'")); + D(fprintf(stderr, "%*c> _tmp_238[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'}'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 26)) // token='}' ) { - D(fprintf(stderr, "%*c+ _tmp_237[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'}'")); + D(fprintf(stderr, "%*c+ _tmp_238[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'}'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_237[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_238[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'}'")); } _res = NULL; @@ -39997,13 +39720,12 @@ _tmp_237_rule(Parser *p) return _res; } -// _tmp_238: yield_expr | star_expressions +// _tmp_239: yield_expr | star_expressions static void * -_tmp_238_rule(Parser *p) +_tmp_239_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -40016,18 +39738,18 @@ _tmp_238_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_238[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); + D(fprintf(stderr, "%*c> _tmp_239[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); expr_ty yield_expr_var; if ( (yield_expr_var = yield_expr_rule(p)) // yield_expr ) { - D(fprintf(stderr, "%*c+ _tmp_238[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr")); + D(fprintf(stderr, "%*c+ _tmp_239[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr")); _res = yield_expr_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_238[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_239[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "yield_expr")); } { // star_expressions @@ -40035,18 +39757,18 @@ _tmp_238_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_238[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions")); + D(fprintf(stderr, "%*c> _tmp_239[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions")); expr_ty star_expressions_var; if ( (star_expressions_var = star_expressions_rule(p)) // star_expressions ) { - D(fprintf(stderr, "%*c+ _tmp_238[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions")); + D(fprintf(stderr, "%*c+ _tmp_239[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions")); _res = star_expressions_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_238[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_239[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_expressions")); } _res = NULL; @@ -40055,13 +39777,12 @@ _tmp_238_rule(Parser *p) return _res; } -// _tmp_239: yield_expr | star_expressions +// _tmp_240: yield_expr | star_expressions static void * -_tmp_239_rule(Parser *p) +_tmp_240_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -40074,18 +39795,18 @@ _tmp_239_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_239[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); + D(fprintf(stderr, "%*c> _tmp_240[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); expr_ty yield_expr_var; if ( (yield_expr_var = yield_expr_rule(p)) // yield_expr ) { - D(fprintf(stderr, "%*c+ _tmp_239[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr")); + D(fprintf(stderr, "%*c+ _tmp_240[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr")); _res = yield_expr_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_239[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_240[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "yield_expr")); } { // star_expressions @@ -40093,18 +39814,18 @@ _tmp_239_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_239[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions")); + D(fprintf(stderr, "%*c> _tmp_240[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions")); expr_ty star_expressions_var; if ( (star_expressions_var = star_expressions_rule(p)) // star_expressions ) { - D(fprintf(stderr, "%*c+ _tmp_239[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions")); + D(fprintf(stderr, "%*c+ _tmp_240[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions")); _res = star_expressions_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_239[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_240[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_expressions")); } _res = NULL; @@ -40113,13 +39834,12 @@ _tmp_239_rule(Parser *p) return _res; } -// _tmp_240: '!' NAME +// _tmp_241: '!' NAME static void * -_tmp_240_rule(Parser *p) +_tmp_241_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -40132,7 +39852,7 @@ _tmp_240_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_240[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'!' NAME")); + D(fprintf(stderr, "%*c> _tmp_241[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'!' NAME")); Token * _literal; expr_ty name_var; if ( @@ -40141,12 +39861,12 @@ _tmp_240_rule(Parser *p) (name_var = _PyPegen_name_token(p)) // NAME ) { - D(fprintf(stderr, "%*c+ _tmp_240[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'!' NAME")); + D(fprintf(stderr, "%*c+ _tmp_241[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'!' NAME")); _res = _PyPegen_dummy_name(p, _literal, name_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_240[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_241[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'!' NAME")); } _res = NULL; @@ -40155,13 +39875,12 @@ _tmp_240_rule(Parser *p) return _res; } -// _tmp_241: ':' | '}' +// _tmp_242: ':' | '}' static void * -_tmp_241_rule(Parser *p) +_tmp_242_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -40174,18 +39893,18 @@ _tmp_241_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_241[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c> _tmp_242[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 11)) // token=':' ) { - D(fprintf(stderr, "%*c+ _tmp_241[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c+ _tmp_242[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_241[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_242[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':'")); } { // '}' @@ -40193,18 +39912,18 @@ _tmp_241_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_241[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'}'")); + D(fprintf(stderr, "%*c> _tmp_242[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'}'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 26)) // token='}' ) { - D(fprintf(stderr, "%*c+ _tmp_241[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'}'")); + D(fprintf(stderr, "%*c+ _tmp_242[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'}'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_241[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_242[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'}'")); } _res = NULL; @@ -40213,13 +39932,12 @@ _tmp_241_rule(Parser *p) return _res; } -// _tmp_242: yield_expr | star_expressions +// _tmp_243: yield_expr | star_expressions static void * -_tmp_242_rule(Parser *p) +_tmp_243_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -40232,18 +39950,18 @@ _tmp_242_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_242[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); + D(fprintf(stderr, "%*c> _tmp_243[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); expr_ty yield_expr_var; if ( (yield_expr_var = yield_expr_rule(p)) // yield_expr ) { - D(fprintf(stderr, "%*c+ _tmp_242[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr")); + D(fprintf(stderr, "%*c+ _tmp_243[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr")); _res = yield_expr_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_242[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_243[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "yield_expr")); } { // star_expressions @@ -40251,18 +39969,18 @@ _tmp_242_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_242[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions")); + D(fprintf(stderr, "%*c> _tmp_243[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions")); expr_ty star_expressions_var; if ( (star_expressions_var = star_expressions_rule(p)) // star_expressions ) { - D(fprintf(stderr, "%*c+ _tmp_242[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions")); + D(fprintf(stderr, "%*c+ _tmp_243[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions")); _res = star_expressions_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_242[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_243[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_expressions")); } _res = NULL; @@ -40271,13 +39989,12 @@ _tmp_242_rule(Parser *p) return _res; } -// _tmp_243: '!' NAME +// _tmp_244: '!' NAME static void * -_tmp_243_rule(Parser *p) +_tmp_244_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -40290,7 +40007,7 @@ _tmp_243_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_243[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'!' NAME")); + D(fprintf(stderr, "%*c> _tmp_244[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'!' NAME")); Token * _literal; expr_ty name_var; if ( @@ -40299,12 +40016,12 @@ _tmp_243_rule(Parser *p) (name_var = _PyPegen_name_token(p)) // NAME ) { - D(fprintf(stderr, "%*c+ _tmp_243[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'!' NAME")); + D(fprintf(stderr, "%*c+ _tmp_244[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'!' NAME")); _res = _PyPegen_dummy_name(p, _literal, name_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_243[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_244[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'!' NAME")); } _res = NULL; @@ -40313,13 +40030,12 @@ _tmp_243_rule(Parser *p) return _res; } -// _loop0_244: fstring_format_spec +// _loop0_245: fstring_format_spec static asdl_seq * -_loop0_244_rule(Parser *p) +_loop0_245_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -40341,7 +40057,7 @@ _loop0_244_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_244[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "fstring_format_spec")); + D(fprintf(stderr, "%*c> _loop0_245[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "fstring_format_spec")); expr_ty fstring_format_spec_var; while ( (fstring_format_spec_var = fstring_format_spec_rule(p)) // fstring_format_spec @@ -40364,7 +40080,7 @@ _loop0_244_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_244[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_245[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "fstring_format_spec")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -40381,13 +40097,12 @@ _loop0_244_rule(Parser *p) return _seq; } -// _tmp_245: yield_expr | star_expressions +// _tmp_246: yield_expr | star_expressions static void * -_tmp_245_rule(Parser *p) +_tmp_246_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -40400,18 +40115,18 @@ _tmp_245_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_245[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); + D(fprintf(stderr, "%*c> _tmp_246[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); expr_ty yield_expr_var; if ( (yield_expr_var = yield_expr_rule(p)) // yield_expr ) { - D(fprintf(stderr, "%*c+ _tmp_245[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr")); + D(fprintf(stderr, "%*c+ _tmp_246[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr")); _res = yield_expr_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_245[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_246[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "yield_expr")); } { // star_expressions @@ -40419,18 +40134,18 @@ _tmp_245_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_245[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions")); + D(fprintf(stderr, "%*c> _tmp_246[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions")); expr_ty star_expressions_var; if ( (star_expressions_var = star_expressions_rule(p)) // star_expressions ) { - D(fprintf(stderr, "%*c+ _tmp_245[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions")); + D(fprintf(stderr, "%*c+ _tmp_246[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions")); _res = star_expressions_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_245[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_246[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_expressions")); } _res = NULL; @@ -40439,13 +40154,12 @@ _tmp_245_rule(Parser *p) return _res; } -// _tmp_246: '!' NAME +// _tmp_247: '!' NAME static void * -_tmp_246_rule(Parser *p) +_tmp_247_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -40458,7 +40172,7 @@ _tmp_246_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_246[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'!' NAME")); + D(fprintf(stderr, "%*c> _tmp_247[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'!' NAME")); Token * _literal; expr_ty name_var; if ( @@ -40467,12 +40181,12 @@ _tmp_246_rule(Parser *p) (name_var = _PyPegen_name_token(p)) // NAME ) { - D(fprintf(stderr, "%*c+ _tmp_246[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'!' NAME")); + D(fprintf(stderr, "%*c+ _tmp_247[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'!' NAME")); _res = _PyPegen_dummy_name(p, _literal, name_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_246[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_247[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'!' NAME")); } _res = NULL; @@ -40481,13 +40195,12 @@ _tmp_246_rule(Parser *p) return _res; } -// _tmp_247: ':' | '}' +// _tmp_248: ':' | '}' static void * -_tmp_247_rule(Parser *p) +_tmp_248_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -40500,18 +40213,18 @@ _tmp_247_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_247[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c> _tmp_248[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 11)) // token=':' ) { - D(fprintf(stderr, "%*c+ _tmp_247[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c+ _tmp_248[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_247[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_248[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':'")); } { // '}' @@ -40519,18 +40232,18 @@ _tmp_247_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_247[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'}'")); + D(fprintf(stderr, "%*c> _tmp_248[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'}'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 26)) // token='}' ) { - D(fprintf(stderr, "%*c+ _tmp_247[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'}'")); + D(fprintf(stderr, "%*c+ _tmp_248[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'}'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_247[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_248[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'}'")); } _res = NULL; @@ -40539,13 +40252,12 @@ _tmp_247_rule(Parser *p) return _res; } -// _tmp_248: star_targets '=' +// _tmp_249: star_targets '=' static void * -_tmp_248_rule(Parser *p) +_tmp_249_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -40558,7 +40270,7 @@ _tmp_248_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_248[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='")); + D(fprintf(stderr, "%*c> _tmp_249[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='")); Token * _literal; expr_ty z; if ( @@ -40567,7 +40279,7 @@ _tmp_248_rule(Parser *p) (_literal = _PyPegen_expect_token(p, 22)) // token='=' ) { - D(fprintf(stderr, "%*c+ _tmp_248[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_targets '='")); + D(fprintf(stderr, "%*c+ _tmp_249[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_targets '='")); _res = z; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -40577,7 +40289,7 @@ _tmp_248_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_248[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_249[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_targets '='")); } _res = NULL; @@ -40586,13 +40298,12 @@ _tmp_248_rule(Parser *p) return _res; } -// _tmp_249: '.' | '...' +// _tmp_250: '.' | '...' static void * -_tmp_249_rule(Parser *p) +_tmp_250_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -40605,18 +40316,18 @@ _tmp_249_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_249[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'.'")); + D(fprintf(stderr, "%*c> _tmp_250[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'.'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 23)) // token='.' ) { - D(fprintf(stderr, "%*c+ _tmp_249[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'.'")); + D(fprintf(stderr, "%*c+ _tmp_250[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'.'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_249[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_250[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'.'")); } { // '...' @@ -40624,18 +40335,18 @@ _tmp_249_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_249[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'...'")); + D(fprintf(stderr, "%*c> _tmp_250[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'...'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 52)) // token='...' ) { - D(fprintf(stderr, "%*c+ _tmp_249[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'...'")); + D(fprintf(stderr, "%*c+ _tmp_250[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'...'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_249[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_250[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'...'")); } _res = NULL; @@ -40644,13 +40355,12 @@ _tmp_249_rule(Parser *p) return _res; } -// _tmp_250: '.' | '...' +// _tmp_251: '.' | '...' static void * -_tmp_250_rule(Parser *p) +_tmp_251_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -40663,18 +40373,18 @@ _tmp_250_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_250[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'.'")); + D(fprintf(stderr, "%*c> _tmp_251[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'.'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 23)) // token='.' ) { - D(fprintf(stderr, "%*c+ _tmp_250[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'.'")); + D(fprintf(stderr, "%*c+ _tmp_251[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'.'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_250[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_251[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'.'")); } { // '...' @@ -40682,18 +40392,18 @@ _tmp_250_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_250[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'...'")); + D(fprintf(stderr, "%*c> _tmp_251[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'...'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 52)) // token='...' ) { - D(fprintf(stderr, "%*c+ _tmp_250[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'...'")); + D(fprintf(stderr, "%*c+ _tmp_251[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'...'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_250[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_251[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'...'")); } _res = NULL; @@ -40702,13 +40412,12 @@ _tmp_250_rule(Parser *p) return _res; } -// _tmp_251: '@' named_expression NEWLINE +// _tmp_252: '@' named_expression NEWLINE static void * -_tmp_251_rule(Parser *p) +_tmp_252_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -40721,7 +40430,7 @@ _tmp_251_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_251[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'@' named_expression NEWLINE")); + D(fprintf(stderr, "%*c> _tmp_252[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'@' named_expression NEWLINE")); Token * _literal; expr_ty f; Token * newline_var; @@ -40733,7 +40442,7 @@ _tmp_251_rule(Parser *p) (newline_var = _PyPegen_expect_token(p, NEWLINE)) // token='NEWLINE' ) { - D(fprintf(stderr, "%*c+ _tmp_251[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'@' named_expression NEWLINE")); + D(fprintf(stderr, "%*c+ _tmp_252[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'@' named_expression NEWLINE")); _res = f; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -40743,7 +40452,7 @@ _tmp_251_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_251[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_252[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'@' named_expression NEWLINE")); } _res = NULL; @@ -40752,13 +40461,12 @@ _tmp_251_rule(Parser *p) return _res; } -// _tmp_252: ',' expression +// _tmp_253: ',' expression static void * -_tmp_252_rule(Parser *p) +_tmp_253_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -40771,7 +40479,7 @@ _tmp_252_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_252[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression")); + D(fprintf(stderr, "%*c> _tmp_253[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression")); Token * _literal; expr_ty c; if ( @@ -40780,7 +40488,7 @@ _tmp_252_rule(Parser *p) (c = expression_rule(p)) // expression ) { - D(fprintf(stderr, "%*c+ _tmp_252[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' expression")); + D(fprintf(stderr, "%*c+ _tmp_253[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' expression")); _res = c; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -40790,7 +40498,7 @@ _tmp_252_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_252[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_253[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' expression")); } _res = NULL; @@ -40799,13 +40507,12 @@ _tmp_252_rule(Parser *p) return _res; } -// _tmp_253: ',' star_expression +// _tmp_254: ',' star_expression static void * -_tmp_253_rule(Parser *p) +_tmp_254_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -40818,7 +40525,7 @@ _tmp_253_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_253[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_expression")); + D(fprintf(stderr, "%*c> _tmp_254[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_expression")); Token * _literal; expr_ty c; if ( @@ -40827,7 +40534,7 @@ _tmp_253_rule(Parser *p) (c = star_expression_rule(p)) // star_expression ) { - D(fprintf(stderr, "%*c+ _tmp_253[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' star_expression")); + D(fprintf(stderr, "%*c+ _tmp_254[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' star_expression")); _res = c; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -40837,7 +40544,7 @@ _tmp_253_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_253[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_254[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' star_expression")); } _res = NULL; @@ -40846,13 +40553,12 @@ _tmp_253_rule(Parser *p) return _res; } -// _tmp_254: 'or' conjunction +// _tmp_255: 'or' conjunction static void * -_tmp_254_rule(Parser *p) +_tmp_255_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -40865,7 +40571,7 @@ _tmp_254_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_254[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'or' conjunction")); + D(fprintf(stderr, "%*c> _tmp_255[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'or' conjunction")); Token * _keyword; expr_ty c; if ( @@ -40874,7 +40580,7 @@ _tmp_254_rule(Parser *p) (c = conjunction_rule(p)) // conjunction ) { - D(fprintf(stderr, "%*c+ _tmp_254[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'or' conjunction")); + D(fprintf(stderr, "%*c+ _tmp_255[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'or' conjunction")); _res = c; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -40884,7 +40590,7 @@ _tmp_254_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_254[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_255[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'or' conjunction")); } _res = NULL; @@ -40893,13 +40599,12 @@ _tmp_254_rule(Parser *p) return _res; } -// _tmp_255: 'and' inversion +// _tmp_256: 'and' inversion static void * -_tmp_255_rule(Parser *p) +_tmp_256_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -40912,7 +40617,7 @@ _tmp_255_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_255[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'and' inversion")); + D(fprintf(stderr, "%*c> _tmp_256[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'and' inversion")); Token * _keyword; expr_ty c; if ( @@ -40921,7 +40626,7 @@ _tmp_255_rule(Parser *p) (c = inversion_rule(p)) // inversion ) { - D(fprintf(stderr, "%*c+ _tmp_255[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'and' inversion")); + D(fprintf(stderr, "%*c+ _tmp_256[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'and' inversion")); _res = c; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -40931,7 +40636,7 @@ _tmp_255_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_255[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_256[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'and' inversion")); } _res = NULL; @@ -40940,13 +40645,12 @@ _tmp_255_rule(Parser *p) return _res; } -// _tmp_256: slice | starred_expression +// _tmp_257: slice | starred_expression static void * -_tmp_256_rule(Parser *p) +_tmp_257_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -40959,18 +40663,18 @@ _tmp_256_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_256[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "slice")); + D(fprintf(stderr, "%*c> _tmp_257[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "slice")); expr_ty slice_var; if ( (slice_var = slice_rule(p)) // slice ) { - D(fprintf(stderr, "%*c+ _tmp_256[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "slice")); + D(fprintf(stderr, "%*c+ _tmp_257[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "slice")); _res = slice_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_256[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_257[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "slice")); } { // starred_expression @@ -40978,18 +40682,18 @@ _tmp_256_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_256[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "starred_expression")); + D(fprintf(stderr, "%*c> _tmp_257[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "starred_expression")); expr_ty starred_expression_var; if ( (starred_expression_var = starred_expression_rule(p)) // starred_expression ) { - D(fprintf(stderr, "%*c+ _tmp_256[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "starred_expression")); + D(fprintf(stderr, "%*c+ _tmp_257[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "starred_expression")); _res = starred_expression_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_256[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_257[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "starred_expression")); } _res = NULL; @@ -40998,13 +40702,12 @@ _tmp_256_rule(Parser *p) return _res; } -// _tmp_257: fstring | string +// _tmp_258: fstring | string static void * -_tmp_257_rule(Parser *p) +_tmp_258_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -41017,18 +40720,18 @@ _tmp_257_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_257[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "fstring")); + D(fprintf(stderr, "%*c> _tmp_258[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "fstring")); expr_ty fstring_var; if ( (fstring_var = fstring_rule(p)) // fstring ) { - D(fprintf(stderr, "%*c+ _tmp_257[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "fstring")); + D(fprintf(stderr, "%*c+ _tmp_258[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "fstring")); _res = fstring_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_257[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_258[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "fstring")); } { // string @@ -41036,18 +40739,18 @@ _tmp_257_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_257[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "string")); + D(fprintf(stderr, "%*c> _tmp_258[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "string")); expr_ty string_var; if ( (string_var = string_rule(p)) // string ) { - D(fprintf(stderr, "%*c+ _tmp_257[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "string")); + D(fprintf(stderr, "%*c+ _tmp_258[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "string")); _res = string_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_257[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_258[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "string")); } _res = NULL; @@ -41056,13 +40759,12 @@ _tmp_257_rule(Parser *p) return _res; } -// _tmp_258: 'if' disjunction +// _tmp_259: 'if' disjunction static void * -_tmp_258_rule(Parser *p) +_tmp_259_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -41075,16 +40777,16 @@ _tmp_258_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_258[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); + D(fprintf(stderr, "%*c> _tmp_259[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); Token * _keyword; expr_ty z; if ( - (_keyword = _PyPegen_expect_token(p, 656)) // token='if' + (_keyword = _PyPegen_expect_token(p, 661)) // token='if' && (z = disjunction_rule(p)) // disjunction ) { - D(fprintf(stderr, "%*c+ _tmp_258[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); + D(fprintf(stderr, "%*c+ _tmp_259[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); _res = z; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -41094,7 +40796,7 @@ _tmp_258_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_258[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_259[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'if' disjunction")); } _res = NULL; @@ -41103,13 +40805,12 @@ _tmp_258_rule(Parser *p) return _res; } -// _tmp_259: 'if' disjunction +// _tmp_260: 'if' disjunction static void * -_tmp_259_rule(Parser *p) +_tmp_260_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -41122,16 +40823,16 @@ _tmp_259_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_259[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); + D(fprintf(stderr, "%*c> _tmp_260[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); Token * _keyword; expr_ty z; if ( - (_keyword = _PyPegen_expect_token(p, 656)) // token='if' + (_keyword = _PyPegen_expect_token(p, 661)) // token='if' && (z = disjunction_rule(p)) // disjunction ) { - D(fprintf(stderr, "%*c+ _tmp_259[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); + D(fprintf(stderr, "%*c+ _tmp_260[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); _res = z; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -41141,7 +40842,7 @@ _tmp_259_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_259[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_260[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'if' disjunction")); } _res = NULL; @@ -41150,13 +40851,79 @@ _tmp_259_rule(Parser *p) return _res; } -// _tmp_260: starred_expression | (assignment_expression | expression !':=') !'=' -static void * -_tmp_260_rule(Parser *p) +// _loop0_261: (',' bitwise_or) +static asdl_seq * +_loop0_261_rule(Parser *p) { if (p->level++ == MAXSTACK) { + _Pypegen_stack_overflow(p); + } + if (p->error_indicator) { + p->level--; + return NULL; + } + void *_res = NULL; + int _mark = p->mark; + void **_children = PyMem_Malloc(sizeof(void *)); + if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); + p->level--; + return NULL; + } + Py_ssize_t _children_capacity = 1; + Py_ssize_t _n = 0; + { // (',' bitwise_or) + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> _loop0_261[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' bitwise_or)")); + void *_tmp_275_var; + while ( + (_tmp_275_var = _tmp_275_rule(p)) // ',' bitwise_or + ) + { + _res = _tmp_275_var; + if (_n == _children_capacity) { + _children_capacity *= 2; + void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); + if (!_new_children) { + PyMem_Free(_children); + p->error_indicator = 1; + PyErr_NoMemory(); + p->level--; + return NULL; + } + _children = _new_children; + } + _children[_n++] = _res; + _mark = p->mark; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s _loop0_261[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(',' bitwise_or)")); + } + asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); + if (!_seq) { + PyMem_Free(_children); + p->error_indicator = 1; + PyErr_NoMemory(); + p->level--; + return NULL; + } + for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); + PyMem_Free(_children); + p->level--; + return _seq; +} + +// _tmp_262: starred_expression | (assignment_expression | expression !':=') !'=' +static void * +_tmp_262_rule(Parser *p) +{ + if (p->level++ == MAXSTACK) { + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -41169,18 +40936,18 @@ _tmp_260_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_260[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "starred_expression")); + D(fprintf(stderr, "%*c> _tmp_262[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "starred_expression")); expr_ty starred_expression_var; if ( (starred_expression_var = starred_expression_rule(p)) // starred_expression ) { - D(fprintf(stderr, "%*c+ _tmp_260[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "starred_expression")); + D(fprintf(stderr, "%*c+ _tmp_262[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "starred_expression")); _res = starred_expression_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_260[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_262[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "starred_expression")); } { // (assignment_expression | expression !':=') !'=' @@ -41188,20 +40955,20 @@ _tmp_260_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_260[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(assignment_expression | expression !':=') !'='")); - void *_tmp_272_var; + D(fprintf(stderr, "%*c> _tmp_262[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(assignment_expression | expression !':=') !'='")); + void *_tmp_276_var; if ( - (_tmp_272_var = _tmp_272_rule(p)) // assignment_expression | expression !':=' + (_tmp_276_var = _tmp_276_rule(p)) // assignment_expression | expression !':=' && _PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, 22) // token='=' ) { - D(fprintf(stderr, "%*c+ _tmp_260[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(assignment_expression | expression !':=') !'='")); - _res = _tmp_272_var; + D(fprintf(stderr, "%*c+ _tmp_262[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(assignment_expression | expression !':=') !'='")); + _res = _tmp_276_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_260[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_262[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(assignment_expression | expression !':=') !'='")); } _res = NULL; @@ -41210,13 +40977,12 @@ _tmp_260_rule(Parser *p) return _res; } -// _tmp_261: ',' star_target +// _tmp_263: ',' star_target static void * -_tmp_261_rule(Parser *p) +_tmp_263_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -41229,7 +40995,7 @@ _tmp_261_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_261[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_target")); + D(fprintf(stderr, "%*c> _tmp_263[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_target")); Token * _literal; expr_ty c; if ( @@ -41238,7 +41004,7 @@ _tmp_261_rule(Parser *p) (c = star_target_rule(p)) // star_target ) { - D(fprintf(stderr, "%*c+ _tmp_261[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' star_target")); + D(fprintf(stderr, "%*c+ _tmp_263[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' star_target")); _res = c; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -41248,7 +41014,7 @@ _tmp_261_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_261[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_263[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' star_target")); } _res = NULL; @@ -41257,13 +41023,12 @@ _tmp_261_rule(Parser *p) return _res; } -// _tmp_262: ',' star_target +// _tmp_264: ',' star_target static void * -_tmp_262_rule(Parser *p) +_tmp_264_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -41276,7 +41041,7 @@ _tmp_262_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_262[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_target")); + D(fprintf(stderr, "%*c> _tmp_264[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_target")); Token * _literal; expr_ty c; if ( @@ -41285,7 +41050,7 @@ _tmp_262_rule(Parser *p) (c = star_target_rule(p)) // star_target ) { - D(fprintf(stderr, "%*c+ _tmp_262[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' star_target")); + D(fprintf(stderr, "%*c+ _tmp_264[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' star_target")); _res = c; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -41295,7 +41060,7 @@ _tmp_262_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_262[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_264[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' star_target")); } _res = NULL; @@ -41304,13 +41069,57 @@ _tmp_262_rule(Parser *p) return _res; } -// _tmp_263: star_targets '=' +// _tmp_265: +// | ','.(starred_expression | (assignment_expression | expression !':=') !'=')+ ',' kwargs static void * -_tmp_263_rule(Parser *p) +_tmp_265_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); + } + if (p->error_indicator) { + p->level--; + return NULL; + } + void * _res = NULL; + int _mark = p->mark; + { // ','.(starred_expression | (assignment_expression | expression !':=') !'=')+ ',' kwargs + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> _tmp_265[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.(starred_expression | (assignment_expression | expression !':=') !'=')+ ',' kwargs")); + asdl_seq * _gather_277_var; + Token * _literal; + asdl_seq* kwargs_var; + if ( + (_gather_277_var = _gather_277_rule(p)) // ','.(starred_expression | (assignment_expression | expression !':=') !'=')+ + && + (_literal = _PyPegen_expect_token(p, 12)) // token=',' + && + (kwargs_var = kwargs_rule(p)) // kwargs + ) + { + D(fprintf(stderr, "%*c+ _tmp_265[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.(starred_expression | (assignment_expression | expression !':=') !'=')+ ',' kwargs")); + _res = _PyPegen_dummy_name(p, _gather_277_var, _literal, kwargs_var); + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s _tmp_265[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "','.(starred_expression | (assignment_expression | expression !':=') !'=')+ ',' kwargs")); + } + _res = NULL; + done: + p->level--; + return _res; +} + +// _tmp_266: star_targets '=' +static void * +_tmp_266_rule(Parser *p) +{ + if (p->level++ == MAXSTACK) { + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -41323,7 +41132,7 @@ _tmp_263_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_263[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='")); + D(fprintf(stderr, "%*c> _tmp_266[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='")); Token * _literal; expr_ty star_targets_var; if ( @@ -41332,12 +41141,12 @@ _tmp_263_rule(Parser *p) (_literal = _PyPegen_expect_token(p, 22)) // token='=' ) { - D(fprintf(stderr, "%*c+ _tmp_263[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_targets '='")); + D(fprintf(stderr, "%*c+ _tmp_266[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_targets '='")); _res = _PyPegen_dummy_name(p, star_targets_var, _literal); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_263[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_266[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_targets '='")); } _res = NULL; @@ -41346,13 +41155,12 @@ _tmp_263_rule(Parser *p) return _res; } -// _tmp_264: star_targets '=' +// _tmp_267: star_targets '=' static void * -_tmp_264_rule(Parser *p) +_tmp_267_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -41365,7 +41173,7 @@ _tmp_264_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_264[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='")); + D(fprintf(stderr, "%*c> _tmp_267[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='")); Token * _literal; expr_ty star_targets_var; if ( @@ -41374,12 +41182,12 @@ _tmp_264_rule(Parser *p) (_literal = _PyPegen_expect_token(p, 22)) // token='=' ) { - D(fprintf(stderr, "%*c+ _tmp_264[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_targets '='")); + D(fprintf(stderr, "%*c+ _tmp_267[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_targets '='")); _res = _PyPegen_dummy_name(p, star_targets_var, _literal); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_264[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_267[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_targets '='")); } _res = NULL; @@ -41388,13 +41196,12 @@ _tmp_264_rule(Parser *p) return _res; } -// _tmp_265: ')' | '**' +// _tmp_268: ')' | '**' static void * -_tmp_265_rule(Parser *p) +_tmp_268_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -41407,18 +41214,18 @@ _tmp_265_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_265[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); + D(fprintf(stderr, "%*c> _tmp_268[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 8)) // token=')' ) { - D(fprintf(stderr, "%*c+ _tmp_265[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'")); + D(fprintf(stderr, "%*c+ _tmp_268[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_265[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_268[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "')'")); } { // '**' @@ -41426,18 +41233,18 @@ _tmp_265_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_265[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**'")); + D(fprintf(stderr, "%*c> _tmp_268[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 35)) // token='**' ) { - D(fprintf(stderr, "%*c+ _tmp_265[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**'")); + D(fprintf(stderr, "%*c+ _tmp_268[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_265[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_268[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'**'")); } _res = NULL; @@ -41446,13 +41253,12 @@ _tmp_265_rule(Parser *p) return _res; } -// _tmp_266: ':' | '**' +// _tmp_269: ':' | '**' static void * -_tmp_266_rule(Parser *p) +_tmp_269_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -41465,18 +41271,18 @@ _tmp_266_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_266[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c> _tmp_269[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 11)) // token=':' ) { - D(fprintf(stderr, "%*c+ _tmp_266[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c+ _tmp_269[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_266[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_269[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':'")); } { // '**' @@ -41484,18 +41290,18 @@ _tmp_266_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_266[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**'")); + D(fprintf(stderr, "%*c> _tmp_269[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 35)) // token='**' ) { - D(fprintf(stderr, "%*c+ _tmp_266[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**'")); + D(fprintf(stderr, "%*c+ _tmp_269[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_266[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_269[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'**'")); } _res = NULL; @@ -41504,13 +41310,12 @@ _tmp_266_rule(Parser *p) return _res; } -// _tmp_267: expression ['as' star_target] +// _tmp_270: expression ['as' star_target] static void * -_tmp_267_rule(Parser *p) +_tmp_270_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -41523,22 +41328,22 @@ _tmp_267_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_267[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression ['as' star_target]")); + D(fprintf(stderr, "%*c> _tmp_270[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression ['as' star_target]")); void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings expr_ty expression_var; if ( (expression_var = expression_rule(p)) // expression && - (_opt_var = _tmp_273_rule(p), !p->error_indicator) // ['as' star_target] + (_opt_var = _tmp_279_rule(p), !p->error_indicator) // ['as' star_target] ) { - D(fprintf(stderr, "%*c+ _tmp_267[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ['as' star_target]")); + D(fprintf(stderr, "%*c+ _tmp_270[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ['as' star_target]")); _res = _PyPegen_dummy_name(p, expression_var, _opt_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_267[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_270[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression ['as' star_target]")); } _res = NULL; @@ -41547,13 +41352,12 @@ _tmp_267_rule(Parser *p) return _res; } -// _tmp_268: expressions ['as' star_target] +// _tmp_271: expressions ['as' star_target] static void * -_tmp_268_rule(Parser *p) +_tmp_271_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -41566,22 +41370,22 @@ _tmp_268_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_268[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expressions ['as' star_target]")); + D(fprintf(stderr, "%*c> _tmp_271[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expressions ['as' star_target]")); void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings expr_ty expressions_var; if ( (expressions_var = expressions_rule(p)) // expressions && - (_opt_var = _tmp_274_rule(p), !p->error_indicator) // ['as' star_target] + (_opt_var = _tmp_280_rule(p), !p->error_indicator) // ['as' star_target] ) { - D(fprintf(stderr, "%*c+ _tmp_268[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expressions ['as' star_target]")); + D(fprintf(stderr, "%*c+ _tmp_271[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expressions ['as' star_target]")); _res = _PyPegen_dummy_name(p, expressions_var, _opt_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_268[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_271[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expressions ['as' star_target]")); } _res = NULL; @@ -41590,13 +41394,12 @@ _tmp_268_rule(Parser *p) return _res; } -// _tmp_269: expression ['as' star_target] +// _tmp_272: expression ['as' star_target] static void * -_tmp_269_rule(Parser *p) +_tmp_272_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -41609,22 +41412,22 @@ _tmp_269_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_269[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression ['as' star_target]")); + D(fprintf(stderr, "%*c> _tmp_272[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression ['as' star_target]")); void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings expr_ty expression_var; if ( (expression_var = expression_rule(p)) // expression && - (_opt_var = _tmp_275_rule(p), !p->error_indicator) // ['as' star_target] + (_opt_var = _tmp_281_rule(p), !p->error_indicator) // ['as' star_target] ) { - D(fprintf(stderr, "%*c+ _tmp_269[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ['as' star_target]")); + D(fprintf(stderr, "%*c+ _tmp_272[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ['as' star_target]")); _res = _PyPegen_dummy_name(p, expression_var, _opt_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_269[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_272[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression ['as' star_target]")); } _res = NULL; @@ -41633,13 +41436,12 @@ _tmp_269_rule(Parser *p) return _res; } -// _tmp_270: expressions ['as' star_target] +// _tmp_273: expressions ['as' star_target] static void * -_tmp_270_rule(Parser *p) +_tmp_273_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -41652,22 +41454,22 @@ _tmp_270_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_270[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expressions ['as' star_target]")); + D(fprintf(stderr, "%*c> _tmp_273[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expressions ['as' star_target]")); void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings expr_ty expressions_var; if ( (expressions_var = expressions_rule(p)) // expressions && - (_opt_var = _tmp_276_rule(p), !p->error_indicator) // ['as' star_target] + (_opt_var = _tmp_282_rule(p), !p->error_indicator) // ['as' star_target] ) { - D(fprintf(stderr, "%*c+ _tmp_270[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expressions ['as' star_target]")); + D(fprintf(stderr, "%*c+ _tmp_273[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expressions ['as' star_target]")); _res = _PyPegen_dummy_name(p, expressions_var, _opt_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_270[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_273[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expressions ['as' star_target]")); } _res = NULL; @@ -41676,13 +41478,12 @@ _tmp_270_rule(Parser *p) return _res; } -// _tmp_271: 'as' NAME +// _tmp_274: 'as' NAME static void * -_tmp_271_rule(Parser *p) +_tmp_274_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -41695,21 +41496,21 @@ _tmp_271_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_271[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); + D(fprintf(stderr, "%*c> _tmp_274[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); Token * _keyword; expr_ty name_var; if ( - (_keyword = _PyPegen_expect_token(p, 654)) // token='as' + (_keyword = _PyPegen_expect_token(p, 659)) // token='as' && (name_var = _PyPegen_name_token(p)) // NAME ) { - D(fprintf(stderr, "%*c+ _tmp_271[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); + D(fprintf(stderr, "%*c+ _tmp_274[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); _res = _PyPegen_dummy_name(p, _keyword, name_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_271[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_274[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' NAME")); } _res = NULL; @@ -41718,13 +41519,53 @@ _tmp_271_rule(Parser *p) return _res; } -// _tmp_272: assignment_expression | expression !':=' +// _tmp_275: ',' bitwise_or static void * -_tmp_272_rule(Parser *p) +_tmp_275_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); + } + if (p->error_indicator) { + p->level--; + return NULL; + } + void * _res = NULL; + int _mark = p->mark; + { // ',' bitwise_or + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> _tmp_275[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' bitwise_or")); + Token * _literal; + expr_ty bitwise_or_var; + if ( + (_literal = _PyPegen_expect_token(p, 12)) // token=',' + && + (bitwise_or_var = bitwise_or_rule(p)) // bitwise_or + ) + { + D(fprintf(stderr, "%*c+ _tmp_275[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' bitwise_or")); + _res = _PyPegen_dummy_name(p, _literal, bitwise_or_var); + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s _tmp_275[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' bitwise_or")); + } + _res = NULL; + done: + p->level--; + return _res; +} + +// _tmp_276: assignment_expression | expression !':=' +static void * +_tmp_276_rule(Parser *p) +{ + if (p->level++ == MAXSTACK) { + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -41737,18 +41578,18 @@ _tmp_272_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_272[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "assignment_expression")); + D(fprintf(stderr, "%*c> _tmp_276[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "assignment_expression")); expr_ty assignment_expression_var; if ( (assignment_expression_var = assignment_expression_rule(p)) // assignment_expression ) { - D(fprintf(stderr, "%*c+ _tmp_272[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "assignment_expression")); + D(fprintf(stderr, "%*c+ _tmp_276[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "assignment_expression")); _res = assignment_expression_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_272[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_276[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "assignment_expression")); } { // expression !':=' @@ -41756,7 +41597,7 @@ _tmp_272_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_272[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression !':='")); + D(fprintf(stderr, "%*c> _tmp_276[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression !':='")); expr_ty expression_var; if ( (expression_var = expression_rule(p)) // expression @@ -41764,12 +41605,12 @@ _tmp_272_rule(Parser *p) _PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, 53) // token=':=' ) { - D(fprintf(stderr, "%*c+ _tmp_272[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression !':='")); + D(fprintf(stderr, "%*c+ _tmp_276[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression !':='")); _res = expression_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_272[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_276[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression !':='")); } _res = NULL; @@ -41778,13 +41619,130 @@ _tmp_272_rule(Parser *p) return _res; } -// _tmp_273: 'as' star_target -static void * -_tmp_273_rule(Parser *p) +// _loop0_278: ',' (starred_expression | (assignment_expression | expression !':=') !'=') +static asdl_seq * +_loop0_278_rule(Parser *p) { if (p->level++ == MAXSTACK) { + _Pypegen_stack_overflow(p); + } + if (p->error_indicator) { + p->level--; + return NULL; + } + void *_res = NULL; + int _mark = p->mark; + void **_children = PyMem_Malloc(sizeof(void *)); + if (!_children) { + p->error_indicator = 1; + PyErr_NoMemory(); + p->level--; + return NULL; + } + Py_ssize_t _children_capacity = 1; + Py_ssize_t _n = 0; + { // ',' (starred_expression | (assignment_expression | expression !':=') !'=') + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> _loop0_278[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (starred_expression | (assignment_expression | expression !':=') !'=')")); + Token * _literal; + void *elem; + while ( + (_literal = _PyPegen_expect_token(p, 12)) // token=',' + && + (elem = _tmp_283_rule(p)) // starred_expression | (assignment_expression | expression !':=') !'=' + ) + { + _res = elem; + if (_res == NULL && PyErr_Occurred()) { + p->error_indicator = 1; + PyMem_Free(_children); + p->level--; + return NULL; + } + if (_n == _children_capacity) { + _children_capacity *= 2; + void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); + if (!_new_children) { + PyMem_Free(_children); + p->error_indicator = 1; + PyErr_NoMemory(); + p->level--; + return NULL; + } + _children = _new_children; + } + _children[_n++] = _res; + _mark = p->mark; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s _loop0_278[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (starred_expression | (assignment_expression | expression !':=') !'=')")); + } + asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); + if (!_seq) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); + p->level--; + return NULL; + } + for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); + PyMem_Free(_children); + p->level--; + return _seq; +} + +// _gather_277: +// | (starred_expression | (assignment_expression | expression !':=') !'=') _loop0_278 +static asdl_seq * +_gather_277_rule(Parser *p) +{ + if (p->level++ == MAXSTACK) { + _Pypegen_stack_overflow(p); + } + if (p->error_indicator) { + p->level--; + return NULL; + } + asdl_seq * _res = NULL; + int _mark = p->mark; + { // (starred_expression | (assignment_expression | expression !':=') !'=') _loop0_278 + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> _gather_277[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(starred_expression | (assignment_expression | expression !':=') !'=') _loop0_278")); + void *elem; + asdl_seq * seq; + if ( + (elem = _tmp_283_rule(p)) // starred_expression | (assignment_expression | expression !':=') !'=' + && + (seq = _loop0_278_rule(p)) // _loop0_278 + ) + { + D(fprintf(stderr, "%*c+ _gather_277[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(starred_expression | (assignment_expression | expression !':=') !'=') _loop0_278")); + _res = _PyPegen_seq_insert_in_front(p, elem, seq); + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s _gather_277[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(starred_expression | (assignment_expression | expression !':=') !'=') _loop0_278")); + } + _res = NULL; + done: + p->level--; + return _res; +} + +// _tmp_279: 'as' star_target +static void * +_tmp_279_rule(Parser *p) +{ + if (p->level++ == MAXSTACK) { + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -41797,21 +41755,21 @@ _tmp_273_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_273[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' star_target")); + D(fprintf(stderr, "%*c> _tmp_279[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' star_target")); Token * _keyword; expr_ty star_target_var; if ( - (_keyword = _PyPegen_expect_token(p, 654)) // token='as' + (_keyword = _PyPegen_expect_token(p, 659)) // token='as' && (star_target_var = star_target_rule(p)) // star_target ) { - D(fprintf(stderr, "%*c+ _tmp_273[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' star_target")); + D(fprintf(stderr, "%*c+ _tmp_279[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' star_target")); _res = _PyPegen_dummy_name(p, _keyword, star_target_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_273[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_279[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' star_target")); } _res = NULL; @@ -41820,13 +41778,12 @@ _tmp_273_rule(Parser *p) return _res; } -// _tmp_274: 'as' star_target +// _tmp_280: 'as' star_target static void * -_tmp_274_rule(Parser *p) +_tmp_280_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -41839,21 +41796,21 @@ _tmp_274_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_274[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' star_target")); + D(fprintf(stderr, "%*c> _tmp_280[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' star_target")); Token * _keyword; expr_ty star_target_var; if ( - (_keyword = _PyPegen_expect_token(p, 654)) // token='as' + (_keyword = _PyPegen_expect_token(p, 659)) // token='as' && (star_target_var = star_target_rule(p)) // star_target ) { - D(fprintf(stderr, "%*c+ _tmp_274[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' star_target")); + D(fprintf(stderr, "%*c+ _tmp_280[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' star_target")); _res = _PyPegen_dummy_name(p, _keyword, star_target_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_274[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_280[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' star_target")); } _res = NULL; @@ -41862,13 +41819,12 @@ _tmp_274_rule(Parser *p) return _res; } -// _tmp_275: 'as' star_target +// _tmp_281: 'as' star_target static void * -_tmp_275_rule(Parser *p) +_tmp_281_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -41881,21 +41837,21 @@ _tmp_275_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_275[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' star_target")); + D(fprintf(stderr, "%*c> _tmp_281[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' star_target")); Token * _keyword; expr_ty star_target_var; if ( - (_keyword = _PyPegen_expect_token(p, 654)) // token='as' + (_keyword = _PyPegen_expect_token(p, 659)) // token='as' && (star_target_var = star_target_rule(p)) // star_target ) { - D(fprintf(stderr, "%*c+ _tmp_275[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' star_target")); + D(fprintf(stderr, "%*c+ _tmp_281[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' star_target")); _res = _PyPegen_dummy_name(p, _keyword, star_target_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_275[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_281[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' star_target")); } _res = NULL; @@ -41904,13 +41860,12 @@ _tmp_275_rule(Parser *p) return _res; } -// _tmp_276: 'as' star_target +// _tmp_282: 'as' star_target static void * -_tmp_276_rule(Parser *p) +_tmp_282_rule(Parser *p) { if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); + _Pypegen_stack_overflow(p); } if (p->error_indicator) { p->level--; @@ -41923,21 +41878,21 @@ _tmp_276_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_276[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' star_target")); + D(fprintf(stderr, "%*c> _tmp_282[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' star_target")); Token * _keyword; expr_ty star_target_var; if ( - (_keyword = _PyPegen_expect_token(p, 654)) // token='as' + (_keyword = _PyPegen_expect_token(p, 659)) // token='as' && (star_target_var = star_target_rule(p)) // star_target ) { - D(fprintf(stderr, "%*c+ _tmp_276[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' star_target")); + D(fprintf(stderr, "%*c+ _tmp_282[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' star_target")); _res = _PyPegen_dummy_name(p, _keyword, star_target_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_276[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_282[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' star_target")); } _res = NULL; @@ -41946,6 +41901,124 @@ _tmp_276_rule(Parser *p) return _res; } +// _tmp_283: starred_expression | (assignment_expression | expression !':=') !'=' +static void * +_tmp_283_rule(Parser *p) +{ + if (p->level++ == MAXSTACK) { + _Pypegen_stack_overflow(p); + } + if (p->error_indicator) { + p->level--; + return NULL; + } + void * _res = NULL; + int _mark = p->mark; + { // starred_expression + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> _tmp_283[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "starred_expression")); + expr_ty starred_expression_var; + if ( + (starred_expression_var = starred_expression_rule(p)) // starred_expression + ) + { + D(fprintf(stderr, "%*c+ _tmp_283[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "starred_expression")); + _res = starred_expression_var; + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s _tmp_283[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "starred_expression")); + } + { // (assignment_expression | expression !':=') !'=' + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> _tmp_283[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(assignment_expression | expression !':=') !'='")); + void *_tmp_284_var; + if ( + (_tmp_284_var = _tmp_284_rule(p)) // assignment_expression | expression !':=' + && + _PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, 22) // token='=' + ) + { + D(fprintf(stderr, "%*c+ _tmp_283[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(assignment_expression | expression !':=') !'='")); + _res = _tmp_284_var; + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s _tmp_283[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(assignment_expression | expression !':=') !'='")); + } + _res = NULL; + done: + p->level--; + return _res; +} + +// _tmp_284: assignment_expression | expression !':=' +static void * +_tmp_284_rule(Parser *p) +{ + if (p->level++ == MAXSTACK) { + _Pypegen_stack_overflow(p); + } + if (p->error_indicator) { + p->level--; + return NULL; + } + void * _res = NULL; + int _mark = p->mark; + { // assignment_expression + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> _tmp_284[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "assignment_expression")); + expr_ty assignment_expression_var; + if ( + (assignment_expression_var = assignment_expression_rule(p)) // assignment_expression + ) + { + D(fprintf(stderr, "%*c+ _tmp_284[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "assignment_expression")); + _res = assignment_expression_var; + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s _tmp_284[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "assignment_expression")); + } + { // expression !':=' + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> _tmp_284[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression !':='")); + expr_ty expression_var; + if ( + (expression_var = expression_rule(p)) // expression + && + _PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, 53) // token=':=' + ) + { + D(fprintf(stderr, "%*c+ _tmp_284[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression !':='")); + _res = expression_var; + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s _tmp_284[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression !':='")); + } + _res = NULL; + done: + p->level--; + return _res; +} + void * _PyPegen_parse(Parser *p) { @@ -41964,8 +42037,6 @@ _PyPegen_parse(Parser *p) result = eval_rule(p); } else if (p->start_rule == Py_func_type_input) { result = func_type_rule(p); - } else if (p->start_rule == Py_fstring_input) { - result = fstring_rule(p); } return result; diff --git a/Parser/peg_api.c b/Parser/peg_api.c index 1487ac4ff856c2..d4acc3e4935d10 100644 --- a/Parser/peg_api.c +++ b/Parser/peg_api.c @@ -1,6 +1,5 @@ #include "Python.h" -#include "tokenizer.h" #include "pegen.h" mod_ty @@ -24,5 +23,18 @@ _PyParser_ASTFromFile(FILE *fp, PyObject *filename_ob, const char *enc, return NULL; } return _PyPegen_run_parser_from_file_pointer(fp, mode, filename_ob, enc, ps1, ps2, - flags, errcode, arena); + flags, errcode, NULL, arena); } + +mod_ty +_PyParser_InteractiveASTFromFile(FILE *fp, PyObject *filename_ob, const char *enc, + int mode, const char *ps1, const char* ps2, + PyCompilerFlags *flags, int *errcode, + PyObject **interactive_src, PyArena *arena) +{ + if (PySys_Audit("compile", "OO", Py_None, filename_ob) < 0) { + return NULL; + } + return _PyPegen_run_parser_from_file_pointer(fp, mode, filename_ob, enc, ps1, ps2, + flags, errcode, interactive_src, arena); +} \ No newline at end of file diff --git a/Parser/pegen.c b/Parser/pegen.c index bfade3446a57f7..7766253a76066f 100644 --- a/Parser/pegen.c +++ b/Parser/pegen.c @@ -3,7 +3,8 @@ #include "pycore_pystate.h" // _PyThreadState_GET() #include -#include "tokenizer.h" +#include "lexer/lexer.h" +#include "tokenizer/tokenizer.h" #include "pegen.h" // Internal parser functions @@ -18,12 +19,8 @@ _PyPegen_interactive_exit(Parser *p) } Py_ssize_t -_PyPegen_byte_offset_to_character_offset(PyObject *line, Py_ssize_t col_offset) +_PyPegen_byte_offset_to_character_offset_raw(const char* str, Py_ssize_t col_offset) { - const char *str = PyUnicode_AsUTF8(line); - if (!str) { - return -1; - } Py_ssize_t len = strlen(str); if (col_offset > len + 1) { col_offset = len + 1; @@ -38,6 +35,16 @@ _PyPegen_byte_offset_to_character_offset(PyObject *line, Py_ssize_t col_offset) return size; } +Py_ssize_t +_PyPegen_byte_offset_to_character_offset(PyObject *line, Py_ssize_t col_offset) +{ + const char *str = PyUnicode_AsUTF8(line); + if (!str) { + return -1; + } + return _PyPegen_byte_offset_to_character_offset_raw(str, col_offset); +} + // Here, mark is the start of the node, while p->mark is the end. // If node==NULL, they should be the same. int @@ -877,7 +884,8 @@ _PyPegen_run_parser(Parser *p) mod_ty _PyPegen_run_parser_from_file_pointer(FILE *fp, int start_rule, PyObject *filename_ob, const char *enc, const char *ps1, const char *ps2, - PyCompilerFlags *flags, int *errcode, PyArena *arena) + PyCompilerFlags *flags, int *errcode, + PyObject **interactive_src, PyArena *arena) { struct tok_state *tok = _PyTokenizer_FromFile(fp, enc, ps1, ps2); if (tok == NULL) { @@ -907,6 +915,15 @@ _PyPegen_run_parser_from_file_pointer(FILE *fp, int start_rule, PyObject *filena result = _PyPegen_run_parser(p); _PyPegen_Parser_Free(p); + if (tok->fp_interactive && tok->interactive_src_start && result && interactive_src != NULL) { + *interactive_src = PyUnicode_FromString(tok->interactive_src_start); + if (!interactive_src || _PyArena_AddPyObject(arena, *interactive_src) < 0) { + Py_XDECREF(interactive_src); + result = NULL; + goto error; + } + } + error: _PyTokenizer_Free(tok); return result; diff --git a/Parser/pegen.h b/Parser/pegen.h index 0852bb51d4fe72..57b45a54c36c57 100644 --- a/Parser/pegen.h +++ b/Parser/pegen.h @@ -149,6 +149,7 @@ expr_ty _PyPegen_name_token(Parser *p); expr_ty _PyPegen_number_token(Parser *p); void *_PyPegen_string_token(Parser *p); Py_ssize_t _PyPegen_byte_offset_to_character_offset(PyObject *line, Py_ssize_t col_offset); +Py_ssize_t _PyPegen_byte_offset_to_character_offset_raw(const char*, Py_ssize_t col_offset); // Error handling functions and APIs typedef enum { @@ -166,6 +167,8 @@ void *_PyPegen_raise_error_known_location(Parser *p, PyObject *errtype, Py_ssize_t end_lineno, Py_ssize_t end_col_offset, const char *errmsg, va_list va); void _Pypegen_set_syntax_error(Parser* p, Token* last_token); +void _Pypegen_stack_overflow(Parser *p); + Py_LOCAL_INLINE(void *) RAISE_ERROR_KNOWN_LOCATION(Parser *p, PyObject *errtype, Py_ssize_t lineno, Py_ssize_t col_offset, @@ -348,7 +351,8 @@ void *_PyPegen_nonparen_genexp_in_call(Parser *p, expr_ty args, asdl_comprehensi Parser *_PyPegen_Parser_New(struct tok_state *, int, int, int, int *, PyArena *); void _PyPegen_Parser_Free(Parser *); mod_ty _PyPegen_run_parser_from_file_pointer(FILE *, int, PyObject *, const char *, - const char *, const char *, PyCompilerFlags *, int *, PyArena *); + const char *, const char *, PyCompilerFlags *, int *, PyObject **, + PyArena *); void *_PyPegen_run_parser(Parser *); mod_ty _PyPegen_run_parser_from_string(const char *, int, PyObject *, PyCompilerFlags *, PyArena *); asdl_stmt_seq *_PyPegen_interactive_exit(Parser *); diff --git a/Parser/pegen_errors.c b/Parser/pegen_errors.c index e543d40ccd8ab7..e15673d02dd3b0 100644 --- a/Parser/pegen_errors.c +++ b/Parser/pegen_errors.c @@ -2,7 +2,8 @@ #include #include "pycore_pyerrors.h" // _PyErr_ProgramDecodedTextObject() -#include "tokenizer.h" +#include "lexer/state.h" +#include "lexer/lexer.h" #include "pegen.h" // TOKENIZER ERRORS @@ -67,6 +68,7 @@ _Pypegen_tokenizer_error(Parser *p) const char *msg = NULL; PyObject* errtype = PyExc_SyntaxError; Py_ssize_t col_offset = -1; + p->error_indicator = 1; switch (p->tok->done) { case E_TOKEN: msg = "invalid token"; @@ -102,6 +104,10 @@ _Pypegen_tokenizer_error(Parser *p) msg = "unexpected character after line continuation character"; break; } + case E_COLUMNOVERFLOW: + PyErr_SetString(PyExc_OverflowError, + "Parser column offset overflow - source line is too big"); + return -1; default: msg = "unknown parsing error"; } @@ -213,6 +219,10 @@ _PyPegen_tokenize_full_source_to_check_for_errors(Parser *p) { void * _PyPegen_raise_error(Parser *p, PyObject *errtype, int use_mark, const char *errmsg, ...) { + // Bail out if we already have an error set. + if (p->error_indicator && PyErr_Occurred()) { + return NULL; + } if (p->fill == 0) { va_list va; va_start(va, errmsg); @@ -272,6 +282,10 @@ get_error_line_from_tokenizer_buffers(Parser *p, Py_ssize_t lineno) Py_ssize_t relative_lineno = p->starting_lineno ? lineno - p->starting_lineno + 1 : lineno; const char* buf_end = p->tok->fp_interactive ? p->tok->interactive_src_end : p->tok->inp; + if (buf_end < cur_line) { + buf_end = cur_line + strlen(cur_line); + } + for (int i = 0; i < relative_lineno - 1; i++) { char *new_line = strchr(cur_line, '\n'); // The assert is here for debug builds but the conditional that @@ -297,6 +311,10 @@ _PyPegen_raise_error_known_location(Parser *p, PyObject *errtype, Py_ssize_t end_lineno, Py_ssize_t end_col_offset, const char *errmsg, va_list va) { + // Bail out if we already have an error set. + if (p->error_indicator && PyErr_Occurred()) { + return NULL; + } PyObject *value = NULL; PyObject *errstr = NULL; PyObject *error_line = NULL; @@ -310,21 +328,6 @@ _PyPegen_raise_error_known_location(Parser *p, PyObject *errtype, end_col_offset = p->tok->cur - p->tok->line_start; } - if (p->start_rule == Py_fstring_input) { - const char *fstring_msg = "f-string: "; - Py_ssize_t len = strlen(fstring_msg) + strlen(errmsg); - - char *new_errmsg = PyMem_Malloc(len + 1); // Lengths of both strings plus NULL character - if (!new_errmsg) { - return (void *) PyErr_NoMemory(); - } - - // Copy both strings into new buffer - memcpy(new_errmsg, fstring_msg, strlen(fstring_msg)); - memcpy(new_errmsg + strlen(fstring_msg), errmsg, strlen(errmsg)); - new_errmsg[len] = 0; - errmsg = new_errmsg; - } errstr = PyUnicode_FromFormatV(errmsg, va); if (!errstr) { goto error; @@ -363,11 +366,6 @@ _PyPegen_raise_error_known_location(Parser *p, PyObject *errtype, } } - if (p->start_rule == Py_fstring_input) { - col_offset -= p->starting_col_offset; - end_col_offset -= p->starting_col_offset; - } - Py_ssize_t col_number = col_offset; Py_ssize_t end_col_number = end_col_offset; @@ -398,23 +396,17 @@ _PyPegen_raise_error_known_location(Parser *p, PyObject *errtype, Py_DECREF(errstr); Py_DECREF(value); - if (p->start_rule == Py_fstring_input) { - PyMem_Free((void *)errmsg); - } return NULL; error: Py_XDECREF(errstr); Py_XDECREF(error_line); - if (p->start_rule == Py_fstring_input) { - PyMem_Free((void *)errmsg); - } return NULL; } void _Pypegen_set_syntax_error(Parser* p, Token* last_token) { - // Existing sintax error + // Existing syntax error if (PyErr_Occurred()) { // Prioritize tokenizer errors to custom syntax errors raised // on the second phase only if the errors come from the parser. @@ -454,3 +446,11 @@ _Pypegen_set_syntax_error(Parser* p, Token* last_token) { // generic SyntaxError we just raised if errors are found. _PyPegen_tokenize_full_source_to_check_for_errors(p); } + +void +_Pypegen_stack_overflow(Parser *p) +{ + p->error_indicator = 1; + PyErr_SetString(PyExc_MemoryError, + "Parser stack overflowed - Python source too complex to parse"); +} diff --git a/Parser/string_parser.c b/Parser/string_parser.c index 72898c38b79bde..bacfd815441110 100644 --- a/Parser/string_parser.c +++ b/Parser/string_parser.c @@ -4,7 +4,7 @@ #include "pycore_bytesobject.h" // _PyBytes_DecodeEscape() #include "pycore_unicodeobject.h" // _PyUnicode_DecodeUnicodeEscapeInternal() -#include "tokenizer.h" +#include "lexer/state.h" #include "pegen.h" #include "string_parser.h" @@ -13,9 +13,15 @@ static int warn_invalid_escape_sequence(Parser *p, const char *first_invalid_escape, Token *t) { + if (p->call_invalid_rules) { + // Do not report warnings if we are in the second pass of the parser + // to avoid showing the warning twice. + return 0; + } unsigned char c = *first_invalid_escape; - if ((t->type == FSTRING_MIDDLE || t->type == FSTRING_END) && (c == '{' || c == '}')) { // in this case the tokenizer has already emitted a warning, - // see tokenizer.c:warn_invalid_escape_sequence + if ((t->type == FSTRING_MIDDLE || t->type == FSTRING_END) && (c == '{' || c == '}')) { + // in this case the tokenizer has already emitted a warning, + // see Parser/tokenizer/helpers.c:warn_invalid_escape_sequence return 0; } diff --git a/Parser/tokenizer.c b/Parser/tokenizer.c deleted file mode 100644 index 5a42f6f357317f..00000000000000 --- a/Parser/tokenizer.c +++ /dev/null @@ -1,2935 +0,0 @@ - -/* Tokenizer implementation */ - -#include "Python.h" -#include "pycore_call.h" // _PyObject_CallNoArgs() - -#include -#include - -#include "tokenizer.h" -#include "errcode.h" - -/* Alternate tab spacing */ -#define ALTTABSIZE 1 - -#define is_potential_identifier_start(c) (\ - (c >= 'a' && c <= 'z')\ - || (c >= 'A' && c <= 'Z')\ - || c == '_'\ - || (c >= 128)) - -#define is_potential_identifier_char(c) (\ - (c >= 'a' && c <= 'z')\ - || (c >= 'A' && c <= 'Z')\ - || (c >= '0' && c <= '9')\ - || c == '_'\ - || (c >= 128)) - - -/* Don't ever change this -- it would break the portability of Python code */ -#define TABSIZE 8 - -#define MAKE_TOKEN(token_type) token_setup(tok, token, token_type, p_start, p_end) -#define MAKE_TYPE_COMMENT_TOKEN(token_type, col_offset, end_col_offset) (\ - type_comment_token_setup(tok, token, token_type, col_offset, end_col_offset, p_start, p_end)) -#define ADVANCE_LINENO() \ - tok->lineno++; \ - tok->col_offset = 0; - -#define INSIDE_FSTRING(tok) (tok->tok_mode_stack_index > 0) -#define INSIDE_FSTRING_EXPR(tok) (tok->curly_bracket_expr_start_depth >= 0) -#ifdef Py_DEBUG -static inline tokenizer_mode* TOK_GET_MODE(struct tok_state* tok) { - assert(tok->tok_mode_stack_index >= 0); - assert(tok->tok_mode_stack_index < MAXFSTRINGLEVEL); - return &(tok->tok_mode_stack[tok->tok_mode_stack_index]); -} -static inline tokenizer_mode* TOK_NEXT_MODE(struct tok_state* tok) { - assert(tok->tok_mode_stack_index >= 0); - assert(tok->tok_mode_stack_index + 1 < MAXFSTRINGLEVEL); - return &(tok->tok_mode_stack[++tok->tok_mode_stack_index]); -} -#else -#define TOK_GET_MODE(tok) (&(tok->tok_mode_stack[tok->tok_mode_stack_index])) -#define TOK_NEXT_MODE(tok) (&(tok->tok_mode_stack[++tok->tok_mode_stack_index])) -#endif - -/* Forward */ -static struct tok_state *tok_new(void); -static int tok_nextc(struct tok_state *tok); -static void tok_backup(struct tok_state *tok, int c); -static int syntaxerror(struct tok_state *tok, const char *format, ...); - -/* Spaces in this constant are treated as "zero or more spaces or tabs" when - tokenizing. */ -static const char* type_comment_prefix = "# type: "; - -/* Create and initialize a new tok_state structure */ - -static struct tok_state * -tok_new(void) -{ - struct tok_state *tok = (struct tok_state *)PyMem_Malloc( - sizeof(struct tok_state)); - if (tok == NULL) - return NULL; - tok->buf = tok->cur = tok->inp = NULL; - tok->fp_interactive = 0; - tok->interactive_src_start = NULL; - tok->interactive_src_end = NULL; - tok->start = NULL; - tok->end = NULL; - tok->done = E_OK; - tok->fp = NULL; - tok->input = NULL; - tok->tabsize = TABSIZE; - tok->indent = 0; - tok->indstack[0] = 0; - tok->atbol = 1; - tok->pendin = 0; - tok->prompt = tok->nextprompt = NULL; - tok->lineno = 0; - tok->starting_col_offset = -1; - tok->col_offset = -1; - tok->level = 0; - tok->altindstack[0] = 0; - tok->decoding_state = STATE_INIT; - tok->decoding_erred = 0; - tok->enc = NULL; - tok->encoding = NULL; - tok->cont_line = 0; - tok->filename = NULL; - tok->decoding_readline = NULL; - tok->decoding_buffer = NULL; - tok->readline = NULL; - tok->type_comments = 0; - tok->interactive_underflow = IUNDERFLOW_NORMAL; - tok->str = NULL; - tok->report_warnings = 1; - tok->tok_extra_tokens = 0; - tok->comment_newline = 0; - tok->implicit_newline = 0; - tok->tok_mode_stack[0] = (tokenizer_mode){.kind =TOK_REGULAR_MODE, .f_string_quote='\0', .f_string_quote_size = 0, .f_string_debug=0}; - tok->tok_mode_stack_index = 0; -#ifdef Py_DEBUG - tok->debug = _Py_GetConfig()->parser_debug; -#endif - return tok; -} - -static char * -new_string(const char *s, Py_ssize_t len, struct tok_state *tok) -{ - char* result = (char *)PyMem_Malloc(len + 1); - if (!result) { - tok->done = E_NOMEM; - return NULL; - } - memcpy(result, s, len); - result[len] = '\0'; - return result; -} - -static char * -error_ret(struct tok_state *tok) /* XXX */ -{ - tok->decoding_erred = 1; - if ((tok->fp != NULL || tok->readline != NULL) && tok->buf != NULL) {/* see _PyTokenizer_Free */ - PyMem_Free(tok->buf); - } - tok->buf = tok->cur = tok->inp = NULL; - tok->start = NULL; - tok->end = NULL; - tok->done = E_DECODE; - return NULL; /* as if it were EOF */ -} - - -static const char * -get_normal_name(const char *s) /* for utf-8 and latin-1 */ -{ - char buf[13]; - int i; - for (i = 0; i < 12; i++) { - int c = s[i]; - if (c == '\0') - break; - else if (c == '_') - buf[i] = '-'; - else - buf[i] = tolower(c); - } - buf[i] = '\0'; - if (strcmp(buf, "utf-8") == 0 || - strncmp(buf, "utf-8-", 6) == 0) - return "utf-8"; - else if (strcmp(buf, "latin-1") == 0 || - strcmp(buf, "iso-8859-1") == 0 || - strcmp(buf, "iso-latin-1") == 0 || - strncmp(buf, "latin-1-", 8) == 0 || - strncmp(buf, "iso-8859-1-", 11) == 0 || - strncmp(buf, "iso-latin-1-", 12) == 0) - return "iso-8859-1"; - else - return s; -} - -/* Return the coding spec in S, or NULL if none is found. */ - -static int -get_coding_spec(const char *s, char **spec, Py_ssize_t size, struct tok_state *tok) -{ - Py_ssize_t i; - *spec = NULL; - /* Coding spec must be in a comment, and that comment must be - * the only statement on the source code line. */ - for (i = 0; i < size - 6; i++) { - if (s[i] == '#') - break; - if (s[i] != ' ' && s[i] != '\t' && s[i] != '\014') - return 1; - } - for (; i < size - 6; i++) { /* XXX inefficient search */ - const char* t = s + i; - if (memcmp(t, "coding", 6) == 0) { - const char* begin = NULL; - t += 6; - if (t[0] != ':' && t[0] != '=') - continue; - do { - t++; - } while (t[0] == ' ' || t[0] == '\t'); - - begin = t; - while (Py_ISALNUM(t[0]) || - t[0] == '-' || t[0] == '_' || t[0] == '.') - t++; - - if (begin < t) { - char* r = new_string(begin, t - begin, tok); - const char* q; - if (!r) - return 0; - q = get_normal_name(r); - if (r != q) { - PyMem_Free(r); - r = new_string(q, strlen(q), tok); - if (!r) - return 0; - } - *spec = r; - break; - } - } - } - return 1; -} - -/* Check whether the line contains a coding spec. If it does, - invoke the set_readline function for the new encoding. - This function receives the tok_state and the new encoding. - Return 1 on success, 0 on failure. */ - -static int -check_coding_spec(const char* line, Py_ssize_t size, struct tok_state *tok, - int set_readline(struct tok_state *, const char *)) -{ - char *cs; - if (tok->cont_line) { - /* It's a continuation line, so it can't be a coding spec. */ - tok->decoding_state = STATE_NORMAL; - return 1; - } - if (!get_coding_spec(line, &cs, size, tok)) { - return 0; - } - if (!cs) { - Py_ssize_t i; - for (i = 0; i < size; i++) { - if (line[i] == '#' || line[i] == '\n' || line[i] == '\r') - break; - if (line[i] != ' ' && line[i] != '\t' && line[i] != '\014') { - /* Stop checking coding spec after a line containing - * anything except a comment. */ - tok->decoding_state = STATE_NORMAL; - break; - } - } - return 1; - } - tok->decoding_state = STATE_NORMAL; - if (tok->encoding == NULL) { - assert(tok->decoding_readline == NULL); - if (strcmp(cs, "utf-8") != 0 && !set_readline(tok, cs)) { - error_ret(tok); - PyErr_Format(PyExc_SyntaxError, "encoding problem: %s", cs); - PyMem_Free(cs); - return 0; - } - tok->encoding = cs; - } else { /* then, compare cs with BOM */ - if (strcmp(tok->encoding, cs) != 0) { - error_ret(tok); - PyErr_Format(PyExc_SyntaxError, - "encoding problem: %s with BOM", cs); - PyMem_Free(cs); - return 0; - } - PyMem_Free(cs); - } - return 1; -} - -/* See whether the file starts with a BOM. If it does, - invoke the set_readline function with the new encoding. - Return 1 on success, 0 on failure. */ - -static int -check_bom(int get_char(struct tok_state *), - void unget_char(int, struct tok_state *), - int set_readline(struct tok_state *, const char *), - struct tok_state *tok) -{ - int ch1, ch2, ch3; - ch1 = get_char(tok); - tok->decoding_state = STATE_SEEK_CODING; - if (ch1 == EOF) { - return 1; - } else if (ch1 == 0xEF) { - ch2 = get_char(tok); - if (ch2 != 0xBB) { - unget_char(ch2, tok); - unget_char(ch1, tok); - return 1; - } - ch3 = get_char(tok); - if (ch3 != 0xBF) { - unget_char(ch3, tok); - unget_char(ch2, tok); - unget_char(ch1, tok); - return 1; - } - } else { - unget_char(ch1, tok); - return 1; - } - if (tok->encoding != NULL) - PyMem_Free(tok->encoding); - tok->encoding = new_string("utf-8", 5, tok); - if (!tok->encoding) - return 0; - /* No need to set_readline: input is already utf-8 */ - return 1; -} - -static int -tok_concatenate_interactive_new_line(struct tok_state *tok, const char *line) { - assert(tok->fp_interactive); - - if (!line) { - return 0; - } - - Py_ssize_t current_size = tok->interactive_src_end - tok->interactive_src_start; - Py_ssize_t line_size = strlen(line); - char last_char = line[line_size > 0 ? line_size - 1 : line_size]; - if (last_char != '\n') { - line_size += 1; - } - char* new_str = tok->interactive_src_start; - - new_str = PyMem_Realloc(new_str, current_size + line_size + 1); - if (!new_str) { - if (tok->interactive_src_start) { - PyMem_Free(tok->interactive_src_start); - } - tok->interactive_src_start = NULL; - tok->interactive_src_end = NULL; - tok->done = E_NOMEM; - return -1; - } - strcpy(new_str + current_size, line); - tok->implicit_newline = 0; - if (last_char != '\n') { - /* Last line does not end in \n, fake one */ - new_str[current_size + line_size - 1] = '\n'; - new_str[current_size + line_size] = '\0'; - tok->implicit_newline = 1; - } - tok->interactive_src_start = new_str; - tok->interactive_src_end = new_str + current_size + line_size; - return 0; -} - -/* Traverse and remember all f-string buffers, in order to be able to restore - them after reallocating tok->buf */ -static void -remember_fstring_buffers(struct tok_state *tok) -{ - int index; - tokenizer_mode *mode; - - for (index = tok->tok_mode_stack_index; index >= 0; --index) { - mode = &(tok->tok_mode_stack[index]); - mode->f_string_start_offset = mode->f_string_start - tok->buf; - mode->f_string_multi_line_start_offset = mode->f_string_multi_line_start - tok->buf; - } -} - -/* Traverse and restore all f-string buffers after reallocating tok->buf */ -static void -restore_fstring_buffers(struct tok_state *tok) -{ - int index; - tokenizer_mode *mode; - - for (index = tok->tok_mode_stack_index; index >= 0; --index) { - mode = &(tok->tok_mode_stack[index]); - mode->f_string_start = tok->buf + mode->f_string_start_offset; - mode->f_string_multi_line_start = tok->buf + mode->f_string_multi_line_start_offset; - } -} - -static int -set_fstring_expr(struct tok_state* tok, struct token *token, char c) { - assert(token != NULL); - assert(c == '}' || c == ':' || c == '!'); - tokenizer_mode *tok_mode = TOK_GET_MODE(tok); - - if (!tok_mode->f_string_debug || token->metadata) { - return 0; - } - - PyObject *res = PyUnicode_DecodeUTF8( - tok_mode->last_expr_buffer, - tok_mode->last_expr_size - tok_mode->last_expr_end, - NULL - ); - if (!res) { - return -1; - } - token->metadata = res; - return 0; -} - -static int -update_fstring_expr(struct tok_state *tok, char cur) -{ - assert(tok->cur != NULL); - - Py_ssize_t size = strlen(tok->cur); - tokenizer_mode *tok_mode = TOK_GET_MODE(tok); - - switch (cur) { - case 0: - if (!tok_mode->last_expr_buffer || tok_mode->last_expr_end >= 0) { - return 1; - } - char *new_buffer = PyMem_Realloc( - tok_mode->last_expr_buffer, - tok_mode->last_expr_size + size - ); - if (new_buffer == NULL) { - PyMem_Free(tok_mode->last_expr_buffer); - goto error; - } - tok_mode->last_expr_buffer = new_buffer; - strncpy(tok_mode->last_expr_buffer + tok_mode->last_expr_size, tok->cur, size); - tok_mode->last_expr_size += size; - break; - case '{': - if (tok_mode->last_expr_buffer != NULL) { - PyMem_Free(tok_mode->last_expr_buffer); - } - tok_mode->last_expr_buffer = PyMem_Malloc(size); - if (tok_mode->last_expr_buffer == NULL) { - goto error; - } - tok_mode->last_expr_size = size; - tok_mode->last_expr_end = -1; - strncpy(tok_mode->last_expr_buffer, tok->cur, size); - break; - case '}': - case '!': - case ':': - if (tok_mode->last_expr_end == -1) { - tok_mode->last_expr_end = strlen(tok->start); - } - break; - default: - Py_UNREACHABLE(); - } - return 1; -error: - tok->done = E_NOMEM; - return 0; -} - -static void -free_fstring_expressions(struct tok_state *tok) -{ - int index; - tokenizer_mode *mode; - - for (index = tok->tok_mode_stack_index; index >= 0; --index) { - mode = &(tok->tok_mode_stack[index]); - if (mode->last_expr_buffer != NULL) { - PyMem_Free(mode->last_expr_buffer); - mode->last_expr_buffer = NULL; - mode->last_expr_size = 0; - mode->last_expr_end = -1; - } - } -} - -/* Read a line of text from TOK into S, using the stream in TOK. - Return NULL on failure, else S. - - On entry, tok->decoding_buffer will be one of: - 1) NULL: need to call tok->decoding_readline to get a new line - 2) PyUnicodeObject *: decoding_feof has called tok->decoding_readline and - stored the result in tok->decoding_buffer - 3) PyByteArrayObject *: previous call to tok_readline_recode did not have enough room - (in the s buffer) to copy entire contents of the line read - by tok->decoding_readline. tok->decoding_buffer has the overflow. - In this case, tok_readline_recode is called in a loop (with an expanded buffer) - until the buffer ends with a '\n' (or until the end of the file is - reached): see tok_nextc and its calls to tok_reserve_buf. -*/ - -static int -tok_reserve_buf(struct tok_state *tok, Py_ssize_t size) -{ - Py_ssize_t cur = tok->cur - tok->buf; - Py_ssize_t oldsize = tok->inp - tok->buf; - Py_ssize_t newsize = oldsize + Py_MAX(size, oldsize >> 1); - if (newsize > tok->end - tok->buf) { - char *newbuf = tok->buf; - Py_ssize_t start = tok->start == NULL ? -1 : tok->start - tok->buf; - Py_ssize_t line_start = tok->start == NULL ? -1 : tok->line_start - tok->buf; - Py_ssize_t multi_line_start = tok->multi_line_start - tok->buf; - remember_fstring_buffers(tok); - newbuf = (char *)PyMem_Realloc(newbuf, newsize); - if (newbuf == NULL) { - tok->done = E_NOMEM; - return 0; - } - tok->buf = newbuf; - tok->cur = tok->buf + cur; - tok->inp = tok->buf + oldsize; - tok->end = tok->buf + newsize; - tok->start = start < 0 ? NULL : tok->buf + start; - tok->line_start = line_start < 0 ? NULL : tok->buf + line_start; - tok->multi_line_start = multi_line_start < 0 ? NULL : tok->buf + multi_line_start; - restore_fstring_buffers(tok); - } - return 1; -} - -static inline int -contains_null_bytes(const char* str, size_t size) { - return memchr(str, 0, size) != NULL; -} - -static int -tok_readline_recode(struct tok_state *tok) { - PyObject *line; - const char *buf; - Py_ssize_t buflen; - line = tok->decoding_buffer; - if (line == NULL) { - line = PyObject_CallNoArgs(tok->decoding_readline); - if (line == NULL) { - error_ret(tok); - goto error; - } - } - else { - tok->decoding_buffer = NULL; - } - buf = PyUnicode_AsUTF8AndSize(line, &buflen); - if (buf == NULL) { - error_ret(tok); - goto error; - } - // Make room for the null terminator *and* potentially - // an extra newline character that we may need to artificially - // add. - size_t buffer_size = buflen + 2; - if (!tok_reserve_buf(tok, buffer_size)) { - goto error; - } - memcpy(tok->inp, buf, buflen); - tok->inp += buflen; - *tok->inp = '\0'; - if (tok->fp_interactive && - tok_concatenate_interactive_new_line(tok, buf) == -1) { - goto error; - } - Py_DECREF(line); - return 1; -error: - Py_XDECREF(line); - return 0; -} - -/* Set the readline function for TOK to a StreamReader's - readline function. The StreamReader is named ENC. - - This function is called from check_bom and check_coding_spec. - - ENC is usually identical to the future value of tok->encoding, - except for the (currently unsupported) case of UTF-16. - - Return 1 on success, 0 on failure. */ - -static int -fp_setreadl(struct tok_state *tok, const char* enc) -{ - PyObject *readline, *open, *stream; - int fd; - long pos; - - fd = fileno(tok->fp); - /* Due to buffering the file offset for fd can be different from the file - * position of tok->fp. If tok->fp was opened in text mode on Windows, - * its file position counts CRLF as one char and can't be directly mapped - * to the file offset for fd. Instead we step back one byte and read to - * the end of line.*/ - pos = ftell(tok->fp); - if (pos == -1 || - lseek(fd, (off_t)(pos > 0 ? pos - 1 : pos), SEEK_SET) == (off_t)-1) { - PyErr_SetFromErrnoWithFilename(PyExc_OSError, NULL); - return 0; - } - - open = _PyImport_GetModuleAttrString("io", "open"); - if (open == NULL) { - return 0; - } - stream = PyObject_CallFunction(open, "isisOOO", - fd, "r", -1, enc, Py_None, Py_None, Py_False); - Py_DECREF(open); - if (stream == NULL) { - return 0; - } - - readline = PyObject_GetAttr(stream, &_Py_ID(readline)); - Py_DECREF(stream); - if (readline == NULL) { - return 0; - } - Py_XSETREF(tok->decoding_readline, readline); - - if (pos > 0) { - PyObject *bufobj = _PyObject_CallNoArgs(readline); - if (bufobj == NULL) { - return 0; - } - Py_DECREF(bufobj); - } - - return 1; -} - -/* Fetch the next byte from TOK. */ - -static int fp_getc(struct tok_state *tok) { - return getc(tok->fp); -} - -/* Unfetch the last byte back into TOK. */ - -static void fp_ungetc(int c, struct tok_state *tok) { - ungetc(c, tok->fp); -} - -/* 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. 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) { - /* single-byte code */ - return 1; - } - 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) { - /* \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 < 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 { - /* invalid start byte */ - return 0; - } - length = expected + 1; - for (; expected; expected--) - if (s[expected] < 0x80 || s[expected] >= 0xC0) - return 0; - return length; -} - -static int -ensure_utf8(char *line, struct tok_state *tok) -{ - int badchar = 0; - unsigned char *c; - int length; - for (c = (unsigned char *)line; *c; c += length) { - if (!(length = valid_utf8(c))) { - badchar = *c; - break; - } - } - if (badchar) { - 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); - return 0; - } - return 1; -} - -/* Fetch a byte from TOK, using the string buffer. */ - -static int -buf_getc(struct tok_state *tok) { - return Py_CHARMASK(*tok->str++); -} - -/* Unfetch a byte from TOK, using the string buffer. */ - -static void -buf_ungetc(int c, struct tok_state *tok) { - tok->str--; - assert(Py_CHARMASK(*tok->str) == c); /* tok->cur may point to read-only segment */ -} - -/* Set the readline function for TOK to ENC. For the string-based - tokenizer, this means to just record the encoding. */ - -static int -buf_setreadl(struct tok_state *tok, const char* enc) { - tok->enc = enc; - return 1; -} - -/* Return a UTF-8 encoding Python string object from the - C byte string STR, which is encoded with ENC. */ - -static PyObject * -translate_into_utf8(const char* str, const char* enc) { - PyObject *utf8; - PyObject* buf = PyUnicode_Decode(str, strlen(str), enc, NULL); - if (buf == NULL) - return NULL; - utf8 = PyUnicode_AsUTF8String(buf); - Py_DECREF(buf); - return utf8; -} - - -static char * -translate_newlines(const char *s, int exec_input, int preserve_crlf, - struct tok_state *tok) { - int skip_next_lf = 0; - size_t needed_length = strlen(s) + 2, final_length; - char *buf, *current; - char c = '\0'; - buf = PyMem_Malloc(needed_length); - if (buf == NULL) { - tok->done = E_NOMEM; - return NULL; - } - for (current = buf; *s; s++, current++) { - c = *s; - if (skip_next_lf) { - skip_next_lf = 0; - if (c == '\n') { - c = *++s; - if (!c) - break; - } - } - if (!preserve_crlf && c == '\r') { - skip_next_lf = 1; - c = '\n'; - } - *current = c; - } - /* If this is exec input, add a newline to the end of the string if - there isn't one already. */ - if (exec_input && c != '\n' && c != '\0') { - *current = '\n'; - current++; - } - *current = '\0'; - final_length = current - buf + 1; - if (final_length < needed_length && final_length) { - /* should never fail */ - char* result = PyMem_Realloc(buf, final_length); - if (result == NULL) { - PyMem_Free(buf); - } - buf = result; - } - return buf; -} - -/* Decode a byte string STR for use as the buffer of TOK. - Look for encoding declarations inside STR, and record them - inside TOK. */ - -static char * -decode_str(const char *input, int single, struct tok_state *tok, int preserve_crlf) -{ - PyObject* utf8 = NULL; - char *str; - const char *s; - const char *newl[2] = {NULL, NULL}; - int lineno = 0; - tok->input = str = translate_newlines(input, single, preserve_crlf, tok); - if (str == NULL) - return NULL; - tok->enc = NULL; - tok->str = str; - if (!check_bom(buf_getc, buf_ungetc, buf_setreadl, tok)) - return error_ret(tok); - str = tok->str; /* string after BOM if any */ - assert(str); - if (tok->enc != NULL) { - utf8 = translate_into_utf8(str, tok->enc); - if (utf8 == NULL) - return error_ret(tok); - str = PyBytes_AsString(utf8); - } - for (s = str;; s++) { - if (*s == '\0') break; - else if (*s == '\n') { - assert(lineno < 2); - newl[lineno] = s; - lineno++; - if (lineno == 2) break; - } - } - tok->enc = NULL; - /* need to check line 1 and 2 separately since check_coding_spec - assumes a single line as input */ - if (newl[0]) { - if (!check_coding_spec(str, newl[0] - str, tok, buf_setreadl)) { - return NULL; - } - if (tok->enc == NULL && tok->decoding_state != STATE_NORMAL && newl[1]) { - if (!check_coding_spec(newl[0]+1, newl[1] - newl[0], - tok, buf_setreadl)) - return NULL; - } - } - if (tok->enc != NULL) { - assert(utf8 == NULL); - utf8 = translate_into_utf8(str, tok->enc); - if (utf8 == NULL) - return error_ret(tok); - str = PyBytes_AS_STRING(utf8); - } - assert(tok->decoding_buffer == NULL); - tok->decoding_buffer = utf8; /* CAUTION */ - return str; -} - -/* Set up tokenizer for string */ - -struct tok_state * -_PyTokenizer_FromString(const char *str, int exec_input, int preserve_crlf) -{ - struct tok_state *tok = tok_new(); - char *decoded; - - if (tok == NULL) - return NULL; - decoded = decode_str(str, exec_input, tok, preserve_crlf); - if (decoded == NULL) { - _PyTokenizer_Free(tok); - return NULL; - } - - tok->buf = tok->cur = tok->inp = decoded; - tok->end = decoded; - return tok; -} - -struct tok_state * -_PyTokenizer_FromReadline(PyObject* readline, const char* enc, - int exec_input, int preserve_crlf) -{ - struct tok_state *tok = tok_new(); - if (tok == NULL) - return NULL; - if ((tok->buf = (char *)PyMem_Malloc(BUFSIZ)) == NULL) { - _PyTokenizer_Free(tok); - return NULL; - } - tok->cur = tok->inp = tok->buf; - tok->end = tok->buf + BUFSIZ; - tok->fp = NULL; - if (enc != NULL) { - tok->encoding = new_string(enc, strlen(enc), tok); - if (!tok->encoding) { - _PyTokenizer_Free(tok); - return NULL; - } - } - tok->decoding_state = STATE_NORMAL; - Py_INCREF(readline); - tok->readline = readline; - return tok; -} - -/* Set up tokenizer for UTF-8 string */ - -struct tok_state * -_PyTokenizer_FromUTF8(const char *str, int exec_input, int preserve_crlf) -{ - struct tok_state *tok = tok_new(); - char *translated; - if (tok == NULL) - return NULL; - tok->input = translated = translate_newlines(str, exec_input, preserve_crlf, tok); - if (translated == NULL) { - _PyTokenizer_Free(tok); - return NULL; - } - tok->decoding_state = STATE_NORMAL; - tok->enc = NULL; - tok->str = translated; - tok->encoding = new_string("utf-8", 5, tok); - if (!tok->encoding) { - _PyTokenizer_Free(tok); - return NULL; - } - - tok->buf = tok->cur = tok->inp = translated; - tok->end = translated; - return tok; -} - -/* Set up tokenizer for file */ - -struct tok_state * -_PyTokenizer_FromFile(FILE *fp, const char* enc, - const char *ps1, const char *ps2) -{ - struct tok_state *tok = tok_new(); - if (tok == NULL) - return NULL; - if ((tok->buf = (char *)PyMem_Malloc(BUFSIZ)) == NULL) { - _PyTokenizer_Free(tok); - return NULL; - } - tok->cur = tok->inp = tok->buf; - tok->end = tok->buf + BUFSIZ; - tok->fp = fp; - tok->prompt = ps1; - tok->nextprompt = ps2; - if (enc != NULL) { - /* Must copy encoding declaration since it - gets copied into the parse tree. */ - tok->encoding = new_string(enc, strlen(enc), tok); - if (!tok->encoding) { - _PyTokenizer_Free(tok); - return NULL; - } - tok->decoding_state = STATE_NORMAL; - } - return tok; -} - -/* Free a tok_state structure */ - -void -_PyTokenizer_Free(struct tok_state *tok) -{ - if (tok->encoding != NULL) { - PyMem_Free(tok->encoding); - } - Py_XDECREF(tok->decoding_readline); - Py_XDECREF(tok->decoding_buffer); - Py_XDECREF(tok->readline); - Py_XDECREF(tok->filename); - if ((tok->readline != NULL || tok->fp != NULL ) && tok->buf != NULL) { - PyMem_Free(tok->buf); - } - if (tok->input) { - PyMem_Free(tok->input); - } - if (tok->interactive_src_start != NULL) { - PyMem_Free(tok->interactive_src_start); - } - free_fstring_expressions(tok); - PyMem_Free(tok); -} - -void -_PyToken_Free(struct token *token) { - Py_XDECREF(token->metadata); -} - -void -_PyToken_Init(struct token *token) { - token->metadata = NULL; -} - -static int -tok_readline_raw(struct tok_state *tok) -{ - do { - if (!tok_reserve_buf(tok, BUFSIZ)) { - return 0; - } - int n_chars = (int)(tok->end - tok->inp); - size_t line_size = 0; - char *line = _Py_UniversalNewlineFgetsWithSize(tok->inp, n_chars, tok->fp, NULL, &line_size); - if (line == NULL) { - return 1; - } - if (tok->fp_interactive && - tok_concatenate_interactive_new_line(tok, line) == -1) { - return 0; - } - tok->inp += line_size; - if (tok->inp == tok->buf) { - return 0; - } - } while (tok->inp[-1] != '\n'); - return 1; -} - -static int -tok_readline_string(struct tok_state* tok) { - PyObject* line = NULL; - PyObject* raw_line = PyObject_CallNoArgs(tok->readline); - if (raw_line == NULL) { - if (PyErr_ExceptionMatches(PyExc_StopIteration)) { - PyErr_Clear(); - return 1; - } - error_ret(tok); - goto error; - } - if(tok->encoding != NULL) { - if (!PyBytes_Check(raw_line)) { - PyErr_Format(PyExc_TypeError, "readline() returned a non-bytes object"); - error_ret(tok); - goto error; - } - line = PyUnicode_Decode(PyBytes_AS_STRING(raw_line), PyBytes_GET_SIZE(raw_line), - tok->encoding, "replace"); - Py_CLEAR(raw_line); - if (line == NULL) { - error_ret(tok); - goto error; - } - } else { - if(!PyUnicode_Check(raw_line)) { - PyErr_Format(PyExc_TypeError, "readline() returned a non-string object"); - error_ret(tok); - goto error; - } - line = raw_line; - raw_line = NULL; - } - Py_ssize_t buflen; - const char* buf = PyUnicode_AsUTF8AndSize(line, &buflen); - if (buf == NULL) { - error_ret(tok); - goto error; - } - - // Make room for the null terminator *and* potentially - // an extra newline character that we may need to artificially - // add. - size_t buffer_size = buflen + 2; - if (!tok_reserve_buf(tok, buffer_size)) { - goto error; - } - memcpy(tok->inp, buf, buflen); - tok->inp += buflen; - *tok->inp = '\0'; - - tok->line_start = tok->cur; - Py_DECREF(line); - return 1; -error: - Py_XDECREF(raw_line); - Py_XDECREF(line); - return 0; -} - -static int -tok_underflow_string(struct tok_state *tok) { - char *end = strchr(tok->inp, '\n'); - if (end != NULL) { - end++; - } - else { - end = strchr(tok->inp, '\0'); - if (end == tok->inp) { - tok->done = E_EOF; - return 0; - } - } - if (tok->start == NULL) { - tok->buf = tok->cur; - } - tok->line_start = tok->cur; - ADVANCE_LINENO(); - tok->inp = end; - return 1; -} - -static int -tok_underflow_interactive(struct tok_state *tok) { - if (tok->interactive_underflow == IUNDERFLOW_STOP) { - tok->done = E_INTERACT_STOP; - return 1; - } - char *newtok = PyOS_Readline(tok->fp ? tok->fp : stdin, stdout, tok->prompt); - if (newtok != NULL) { - char *translated = translate_newlines(newtok, 0, 0, tok); - PyMem_Free(newtok); - if (translated == NULL) { - return 0; - } - newtok = translated; - } - if (tok->encoding && newtok && *newtok) { - /* Recode to UTF-8 */ - Py_ssize_t buflen; - const char* buf; - PyObject *u = translate_into_utf8(newtok, tok->encoding); - PyMem_Free(newtok); - if (u == NULL) { - tok->done = E_DECODE; - return 0; - } - buflen = PyBytes_GET_SIZE(u); - buf = PyBytes_AS_STRING(u); - newtok = PyMem_Malloc(buflen+1); - if (newtok == NULL) { - Py_DECREF(u); - tok->done = E_NOMEM; - return 0; - } - strcpy(newtok, buf); - Py_DECREF(u); - } - if (tok->fp_interactive && - tok_concatenate_interactive_new_line(tok, newtok) == -1) { - PyMem_Free(newtok); - return 0; - } - if (tok->nextprompt != NULL) { - tok->prompt = tok->nextprompt; - } - if (newtok == NULL) { - tok->done = E_INTR; - } - else if (*newtok == '\0') { - PyMem_Free(newtok); - tok->done = E_EOF; - } - else if (tok->start != NULL) { - Py_ssize_t cur_multi_line_start = tok->multi_line_start - tok->buf; - remember_fstring_buffers(tok); - size_t size = strlen(newtok); - ADVANCE_LINENO(); - if (!tok_reserve_buf(tok, size + 1)) { - PyMem_Free(tok->buf); - tok->buf = NULL; - PyMem_Free(newtok); - return 0; - } - memcpy(tok->cur, newtok, size + 1); - PyMem_Free(newtok); - tok->inp += size; - tok->multi_line_start = tok->buf + cur_multi_line_start; - restore_fstring_buffers(tok); - } - else { - remember_fstring_buffers(tok); - ADVANCE_LINENO(); - PyMem_Free(tok->buf); - tok->buf = newtok; - tok->cur = tok->buf; - tok->line_start = tok->buf; - tok->inp = strchr(tok->buf, '\0'); - tok->end = tok->inp + 1; - restore_fstring_buffers(tok); - } - if (tok->done != E_OK) { - if (tok->prompt != NULL) { - PySys_WriteStderr("\n"); - } - return 0; - } - - if (tok->tok_mode_stack_index && !update_fstring_expr(tok, 0)) { - return 0; - } - return 1; -} - -static int -tok_underflow_file(struct tok_state *tok) { - if (tok->start == NULL && !INSIDE_FSTRING(tok)) { - tok->cur = tok->inp = tok->buf; - } - if (tok->decoding_state == STATE_INIT) { - /* We have not yet determined the encoding. - If an encoding is found, use the file-pointer - reader functions from now on. */ - if (!check_bom(fp_getc, fp_ungetc, fp_setreadl, tok)) { - error_ret(tok); - return 0; - } - assert(tok->decoding_state != STATE_INIT); - } - /* Read until '\n' or EOF */ - if (tok->decoding_readline != NULL) { - /* We already have a codec associated with this input. */ - if (!tok_readline_recode(tok)) { - return 0; - } - } - else { - /* We want a 'raw' read. */ - if (!tok_readline_raw(tok)) { - return 0; - } - } - if (tok->inp == tok->cur) { - tok->done = E_EOF; - return 0; - } - tok->implicit_newline = 0; - if (tok->inp[-1] != '\n') { - assert(tok->inp + 1 < tok->end); - /* Last line does not end in \n, fake one */ - *tok->inp++ = '\n'; - *tok->inp = '\0'; - tok->implicit_newline = 1; - } - - if (tok->tok_mode_stack_index && !update_fstring_expr(tok, 0)) { - return 0; - } - - ADVANCE_LINENO(); - if (tok->decoding_state != STATE_NORMAL) { - if (tok->lineno > 2) { - tok->decoding_state = STATE_NORMAL; - } - else if (!check_coding_spec(tok->cur, strlen(tok->cur), - tok, fp_setreadl)) - { - return 0; - } - } - /* The default encoding is UTF-8, so make sure we don't have any - non-UTF-8 sequences in it. */ - if (!tok->encoding && !ensure_utf8(tok->cur, tok)) { - error_ret(tok); - return 0; - } - assert(tok->done == E_OK); - return tok->done == E_OK; -} - -static int -tok_underflow_readline(struct tok_state* tok) { - assert(tok->decoding_state == STATE_NORMAL); - assert(tok->fp == NULL && tok->input == NULL && tok->decoding_readline == NULL); - if (tok->start == NULL && !INSIDE_FSTRING(tok)) { - tok->cur = tok->inp = tok->buf; - } - if (!tok_readline_string(tok)) { - return 0; - } - if (tok->inp == tok->cur) { - tok->done = E_EOF; - return 0; - } - tok->implicit_newline = 0; - if (tok->inp[-1] != '\n') { - assert(tok->inp + 1 < tok->end); - /* Last line does not end in \n, fake one */ - *tok->inp++ = '\n'; - *tok->inp = '\0'; - tok->implicit_newline = 1; - } - - if (tok->tok_mode_stack_index && !update_fstring_expr(tok, 0)) { - return 0; - } - - ADVANCE_LINENO(); - /* The default encoding is UTF-8, so make sure we don't have any - non-UTF-8 sequences in it. */ - if (!tok->encoding && !ensure_utf8(tok->cur, tok)) { - error_ret(tok); - return 0; - } - assert(tok->done == E_OK); - return tok->done == E_OK; -} - -#if defined(Py_DEBUG) -static void -print_escape(FILE *f, const char *s, Py_ssize_t size) -{ - if (s == NULL) { - fputs("NULL", f); - return; - } - putc('"', f); - while (size-- > 0) { - unsigned char c = *s++; - switch (c) { - case '\n': fputs("\\n", f); break; - case '\r': fputs("\\r", f); break; - case '\t': fputs("\\t", f); break; - case '\f': fputs("\\f", f); break; - case '\'': fputs("\\'", f); break; - case '"': fputs("\\\"", f); break; - default: - if (0x20 <= c && c <= 0x7f) - putc(c, f); - else - fprintf(f, "\\x%02x", c); - } - } - putc('"', f); -} -#endif - -/* Get next char, updating state; error code goes into tok->done */ - -static int -tok_nextc(struct tok_state *tok) -{ - int rc; - for (;;) { - if (tok->cur != tok->inp) { - tok->col_offset++; - return Py_CHARMASK(*tok->cur++); /* Fast path */ - } - if (tok->done != E_OK) { - return EOF; - } - if (tok->readline) { - rc = tok_underflow_readline(tok); - } - else if (tok->fp == NULL) { - rc = tok_underflow_string(tok); - } - else if (tok->prompt != NULL) { - rc = tok_underflow_interactive(tok); - } - else { - rc = tok_underflow_file(tok); - } -#if defined(Py_DEBUG) - if (tok->debug) { - fprintf(stderr, "line[%d] = ", tok->lineno); - print_escape(stderr, tok->cur, tok->inp - tok->cur); - fprintf(stderr, " tok->done = %d\n", tok->done); - } -#endif - if (!rc) { - tok->cur = tok->inp; - return EOF; - } - tok->line_start = tok->cur; - - if (contains_null_bytes(tok->line_start, tok->inp - tok->line_start)) { - syntaxerror(tok, "source code cannot contain null bytes"); - tok->cur = tok->inp; - return EOF; - } - } - Py_UNREACHABLE(); -} - -/* Back-up one character */ - -static void -tok_backup(struct tok_state *tok, int c) -{ - if (c != EOF) { - if (--tok->cur < tok->buf) { - Py_FatalError("tokenizer beginning of buffer"); - } - if ((int)(unsigned char)*tok->cur != Py_CHARMASK(c)) { - Py_FatalError("tok_backup: wrong character"); - } - tok->col_offset--; - } -} - -static int -_syntaxerror_range(struct tok_state *tok, const char *format, - int col_offset, int end_col_offset, - va_list vargs) -{ - // In release builds, we don't want to overwrite a previous error, but in debug builds we - // want to fail if we are not doing it so we can fix it. - assert(tok->done != E_ERROR); - if (tok->done == E_ERROR) { - return ERRORTOKEN; - } - PyObject *errmsg, *errtext, *args; - errmsg = PyUnicode_FromFormatV(format, vargs); - if (!errmsg) { - goto error; - } - - errtext = PyUnicode_DecodeUTF8(tok->line_start, tok->cur - tok->line_start, - "replace"); - if (!errtext) { - goto error; - } - - if (col_offset == -1) { - col_offset = (int)PyUnicode_GET_LENGTH(errtext); - } - if (end_col_offset == -1) { - end_col_offset = col_offset; - } - - Py_ssize_t line_len = strcspn(tok->line_start, "\n"); - if (line_len != tok->cur - tok->line_start) { - Py_DECREF(errtext); - errtext = PyUnicode_DecodeUTF8(tok->line_start, line_len, - "replace"); - } - if (!errtext) { - goto error; - } - - args = Py_BuildValue("(O(OiiNii))", errmsg, tok->filename, tok->lineno, - col_offset, errtext, tok->lineno, end_col_offset); - if (args) { - PyErr_SetObject(PyExc_SyntaxError, args); - Py_DECREF(args); - } - -error: - Py_XDECREF(errmsg); - tok->done = E_ERROR; - return ERRORTOKEN; -} - -static int -syntaxerror(struct tok_state *tok, const char *format, ...) -{ - // This errors are cleaned on startup. Todo: Fix it. - va_list vargs; - va_start(vargs, format); - int ret = _syntaxerror_range(tok, format, -1, -1, vargs); - va_end(vargs); - return ret; -} - -static int -syntaxerror_known_range(struct tok_state *tok, - int col_offset, int end_col_offset, - const char *format, ...) -{ - va_list vargs; - va_start(vargs, format); - int ret = _syntaxerror_range(tok, format, col_offset, end_col_offset, vargs); - va_end(vargs); - return ret; -} - -static int -indenterror(struct tok_state *tok) -{ - tok->done = E_TABSPACE; - tok->cur = tok->inp; - return ERRORTOKEN; -} - -static int -parser_warn(struct tok_state *tok, PyObject *category, const char *format, ...) -{ - if (!tok->report_warnings) { - return 0; - } - - PyObject *errmsg; - va_list vargs; - va_start(vargs, format); - errmsg = PyUnicode_FromFormatV(format, vargs); - va_end(vargs); - if (!errmsg) { - goto error; - } - - if (PyErr_WarnExplicitObject(category, errmsg, tok->filename, - tok->lineno, NULL, NULL) < 0) { - if (PyErr_ExceptionMatches(category)) { - /* Replace the DeprecationWarning exception with a SyntaxError - to get a more accurate error report */ - PyErr_Clear(); - syntaxerror(tok, "%U", errmsg); - } - goto error; - } - Py_DECREF(errmsg); - return 0; - -error: - Py_XDECREF(errmsg); - tok->done = E_ERROR; - return -1; -} - -static int -warn_invalid_escape_sequence(struct tok_state *tok, int first_invalid_escape_char) -{ - - PyObject *msg = PyUnicode_FromFormat( - "invalid escape sequence '\\%c'", - (char) first_invalid_escape_char - ); - - if (msg == NULL) { - return -1; - } - - if (PyErr_WarnExplicitObject(PyExc_SyntaxWarning, msg, tok->filename, - tok->lineno, NULL, NULL) < 0) { - Py_DECREF(msg); - - if (PyErr_ExceptionMatches(PyExc_SyntaxWarning)) { - /* Replace the SyntaxWarning exception with a SyntaxError - to get a more accurate error report */ - PyErr_Clear(); - return syntaxerror(tok, "invalid escape sequence '\\%c'", (char) first_invalid_escape_char); - } - - return -1; - } - - Py_DECREF(msg); - return 0; -} - -static int -lookahead(struct tok_state *tok, const char *test) -{ - const char *s = test; - int res = 0; - while (1) { - int c = tok_nextc(tok); - if (*s == 0) { - res = !is_potential_identifier_char(c); - } - else if (c == *s) { - s++; - continue; - } - - tok_backup(tok, c); - while (s != test) { - tok_backup(tok, *--s); - } - return res; - } -} - -static int -verify_end_of_number(struct tok_state *tok, int c, const char *kind) { - if (tok->tok_extra_tokens) { - // When we are parsing extra tokens, we don't want to emit warnings - // about invalid literals, because we want to be a bit more liberal. - return 1; - } - /* Emit a deprecation warning only if the numeric literal is immediately - * followed by one of keywords which can occur after a numeric literal - * in valid code: "and", "else", "for", "if", "in", "is" and "or". - * It allows to gradually deprecate existing valid code without adding - * warning before error in most cases of invalid numeric literal (which - * would be confusing and break existing tests). - * Raise a syntax error with slightly better message than plain - * "invalid syntax" if the numeric literal is immediately followed by - * other keyword or identifier. - */ - int r = 0; - if (c == 'a') { - r = lookahead(tok, "nd"); - } - else if (c == 'e') { - r = lookahead(tok, "lse"); - } - else if (c == 'f') { - r = lookahead(tok, "or"); - } - else if (c == 'i') { - int c2 = tok_nextc(tok); - if (c2 == 'f' || c2 == 'n' || c2 == 's') { - r = 1; - } - tok_backup(tok, c2); - } - else if (c == 'o') { - r = lookahead(tok, "r"); - } - else if (c == 'n') { - r = lookahead(tok, "ot"); - } - if (r) { - tok_backup(tok, c); - if (parser_warn(tok, PyExc_SyntaxWarning, - "invalid %s literal", kind)) - { - return 0; - } - tok_nextc(tok); - } - else /* In future releases, only error will remain. */ - if (is_potential_identifier_char(c)) { - tok_backup(tok, c); - syntaxerror(tok, "invalid %s literal", kind); - return 0; - } - return 1; -} - -/* Verify that the identifier follows PEP 3131. - All identifier strings are guaranteed to be "ready" unicode objects. - */ -static int -verify_identifier(struct tok_state *tok) -{ - if (tok->tok_extra_tokens) { - return 1; - } - PyObject *s; - if (tok->decoding_erred) - return 0; - s = PyUnicode_DecodeUTF8(tok->start, tok->cur - tok->start, NULL); - if (s == NULL) { - if (PyErr_ExceptionMatches(PyExc_UnicodeDecodeError)) { - tok->done = E_DECODE; - } - else { - tok->done = E_ERROR; - } - return 0; - } - Py_ssize_t invalid = _PyUnicode_ScanIdentifier(s); - if (invalid < 0) { - Py_DECREF(s); - tok->done = E_ERROR; - return 0; - } - assert(PyUnicode_GET_LENGTH(s) > 0); - if (invalid < PyUnicode_GET_LENGTH(s)) { - Py_UCS4 ch = PyUnicode_READ_CHAR(s, invalid); - if (invalid + 1 < PyUnicode_GET_LENGTH(s)) { - /* Determine the offset in UTF-8 encoded input */ - Py_SETREF(s, PyUnicode_Substring(s, 0, invalid + 1)); - if (s != NULL) { - Py_SETREF(s, PyUnicode_AsUTF8String(s)); - } - if (s == NULL) { - tok->done = E_ERROR; - return 0; - } - tok->cur = (char *)tok->start + PyBytes_GET_SIZE(s); - } - Py_DECREF(s); - if (Py_UNICODE_ISPRINTABLE(ch)) { - syntaxerror(tok, "invalid character '%c' (U+%04X)", ch, ch); - } - else { - syntaxerror(tok, "invalid non-printable character U+%04X", ch); - } - return 0; - } - Py_DECREF(s); - return 1; -} - -static int -tok_decimal_tail(struct tok_state *tok) -{ - int c; - - while (1) { - do { - c = tok_nextc(tok); - } while (isdigit(c)); - if (c != '_') { - break; - } - c = tok_nextc(tok); - if (!isdigit(c)) { - tok_backup(tok, c); - syntaxerror(tok, "invalid decimal literal"); - return 0; - } - } - return c; -} - - -static inline int -tok_continuation_line(struct tok_state *tok) { - int c = tok_nextc(tok); - if (c == '\r') { - c = tok_nextc(tok); - } - if (c != '\n') { - tok->done = E_LINECONT; - return -1; - } - c = tok_nextc(tok); - if (c == EOF) { - tok->done = E_EOF; - tok->cur = tok->inp; - return -1; - } else { - tok_backup(tok, c); - } - return c; -} - -static int -type_comment_token_setup(struct tok_state *tok, struct token *token, int type, int col_offset, - int end_col_offset, const char *start, const char *end) -{ - token->level = tok->level; - token->lineno = token->end_lineno = tok->lineno; - token->col_offset = col_offset; - token->end_col_offset = end_col_offset; - token->start = start; - token->end = end; - return type; -} - -static int -token_setup(struct tok_state *tok, struct token *token, int type, const char *start, const char *end) -{ - assert((start == NULL && end == NULL) || (start != NULL && end != NULL)); - token->level = tok->level; - if (ISSTRINGLIT(type)) { - token->lineno = tok->first_lineno; - } - else { - token->lineno = tok->lineno; - } - token->end_lineno = tok->lineno; - token->col_offset = token->end_col_offset = -1; - token->start = start; - token->end = end; - - if (start != NULL && end != NULL) { - token->col_offset = tok->starting_col_offset; - token->end_col_offset = tok->col_offset; - } - return type; -} - - -static int -tok_get_normal_mode(struct tok_state *tok, tokenizer_mode* current_tok, struct token *token) -{ - int c; - int blankline, nonascii; - - const char *p_start = NULL; - const char *p_end = NULL; - nextline: - tok->start = NULL; - tok->starting_col_offset = -1; - blankline = 0; - - - /* Get indentation level */ - if (tok->atbol) { - int col = 0; - int altcol = 0; - tok->atbol = 0; - int cont_line_col = 0; - for (;;) { - c = tok_nextc(tok); - if (c == ' ') { - col++, altcol++; - } - else if (c == '\t') { - col = (col / tok->tabsize + 1) * tok->tabsize; - altcol = (altcol / ALTTABSIZE + 1) * ALTTABSIZE; - } - else if (c == '\014') {/* Control-L (formfeed) */ - col = altcol = 0; /* For Emacs users */ - } - else if (c == '\\') { - // Indentation cannot be split over multiple physical lines - // using backslashes. This means that if we found a backslash - // preceded by whitespace, **the first one we find** determines - // the level of indentation of whatever comes next. - cont_line_col = cont_line_col ? cont_line_col : col; - if ((c = tok_continuation_line(tok)) == -1) { - return MAKE_TOKEN(ERRORTOKEN); - } - } - else { - break; - } - } - tok_backup(tok, c); - if (c == '#' || c == '\n' || c == '\r') { - /* Lines with only whitespace and/or comments - shouldn't affect the indentation and are - not passed to the parser as NEWLINE tokens, - except *totally* empty lines in interactive - mode, which signal the end of a command group. */ - if (col == 0 && c == '\n' && tok->prompt != NULL) { - blankline = 0; /* Let it through */ - } - else if (tok->prompt != NULL && tok->lineno == 1) { - /* In interactive mode, if the first line contains - only spaces and/or a comment, let it through. */ - blankline = 0; - col = altcol = 0; - } - else { - blankline = 1; /* Ignore completely */ - } - /* We can't jump back right here since we still - may need to skip to the end of a comment */ - } - if (!blankline && tok->level == 0) { - col = cont_line_col ? cont_line_col : col; - altcol = cont_line_col ? cont_line_col : altcol; - if (col == tok->indstack[tok->indent]) { - /* No change */ - if (altcol != tok->altindstack[tok->indent]) { - return MAKE_TOKEN(indenterror(tok)); - } - } - else if (col > tok->indstack[tok->indent]) { - /* Indent -- always one */ - if (tok->indent+1 >= MAXINDENT) { - tok->done = E_TOODEEP; - tok->cur = tok->inp; - return MAKE_TOKEN(ERRORTOKEN); - } - if (altcol <= tok->altindstack[tok->indent]) { - return MAKE_TOKEN(indenterror(tok)); - } - tok->pendin++; - tok->indstack[++tok->indent] = col; - tok->altindstack[tok->indent] = altcol; - } - else /* col < tok->indstack[tok->indent] */ { - /* Dedent -- any number, must be consistent */ - while (tok->indent > 0 && - col < tok->indstack[tok->indent]) { - tok->pendin--; - tok->indent--; - } - if (col != tok->indstack[tok->indent]) { - tok->done = E_DEDENT; - tok->cur = tok->inp; - return MAKE_TOKEN(ERRORTOKEN); - } - if (altcol != tok->altindstack[tok->indent]) { - return MAKE_TOKEN(indenterror(tok)); - } - } - } - } - - tok->start = tok->cur; - tok->starting_col_offset = tok->col_offset; - - /* Return pending indents/dedents */ - if (tok->pendin != 0) { - if (tok->pendin < 0) { - if (tok->tok_extra_tokens) { - p_start = tok->cur; - p_end = tok->cur; - } - tok->pendin++; - return MAKE_TOKEN(DEDENT); - } - else { - if (tok->tok_extra_tokens) { - p_start = tok->buf; - p_end = tok->cur; - } - tok->pendin--; - return MAKE_TOKEN(INDENT); - } - } - - /* Peek ahead at the next character */ - c = tok_nextc(tok); - tok_backup(tok, c); - - again: - tok->start = NULL; - /* Skip spaces */ - do { - c = tok_nextc(tok); - } while (c == ' ' || c == '\t' || c == '\014'); - - /* Set start of current token */ - tok->start = tok->cur == NULL ? NULL : tok->cur - 1; - tok->starting_col_offset = tok->col_offset - 1; - - /* Skip comment, unless it's a type comment */ - if (c == '#') { - - const char* p = NULL; - const char *prefix, *type_start; - int current_starting_col_offset; - - while (c != EOF && c != '\n' && c != '\r') { - c = tok_nextc(tok); - } - - if (tok->tok_extra_tokens) { - p = tok->start; - } - - if (tok->type_comments) { - p = tok->start; - current_starting_col_offset = tok->starting_col_offset; - prefix = type_comment_prefix; - while (*prefix && p < tok->cur) { - if (*prefix == ' ') { - while (*p == ' ' || *p == '\t') { - p++; - current_starting_col_offset++; - } - } else if (*prefix == *p) { - p++; - current_starting_col_offset++; - } else { - break; - } - - prefix++; - } - - /* This is a type comment if we matched all of type_comment_prefix. */ - if (!*prefix) { - int is_type_ignore = 1; - // +6 in order to skip the word 'ignore' - const char *ignore_end = p + 6; - const int ignore_end_col_offset = current_starting_col_offset + 6; - tok_backup(tok, c); /* don't eat the newline or EOF */ - - type_start = p; - - /* A TYPE_IGNORE is "type: ignore" followed by the end of the token - * or anything ASCII and non-alphanumeric. */ - is_type_ignore = ( - tok->cur >= ignore_end && memcmp(p, "ignore", 6) == 0 - && !(tok->cur > ignore_end - && ((unsigned char)ignore_end[0] >= 128 || Py_ISALNUM(ignore_end[0])))); - - if (is_type_ignore) { - p_start = ignore_end; - p_end = tok->cur; - - /* If this type ignore is the only thing on the line, consume the newline also. */ - if (blankline) { - tok_nextc(tok); - tok->atbol = 1; - } - return MAKE_TYPE_COMMENT_TOKEN(TYPE_IGNORE, ignore_end_col_offset, tok->col_offset); - } else { - p_start = type_start; - p_end = tok->cur; - return MAKE_TYPE_COMMENT_TOKEN(TYPE_COMMENT, current_starting_col_offset, tok->col_offset); - } - } - } - if (tok->tok_extra_tokens) { - tok_backup(tok, c); /* don't eat the newline or EOF */ - p_start = p; - p_end = tok->cur; - tok->comment_newline = blankline; - return MAKE_TOKEN(COMMENT); - } - } - - if (tok->done == E_INTERACT_STOP) { - return MAKE_TOKEN(ENDMARKER); - } - - /* Check for EOF and errors now */ - if (c == EOF) { - if (tok->level) { - return MAKE_TOKEN(ERRORTOKEN); - } - return MAKE_TOKEN(tok->done == E_EOF ? ENDMARKER : ERRORTOKEN); - } - - /* Identifier (most frequent token!) */ - nonascii = 0; - if (is_potential_identifier_start(c)) { - /* Process the various legal combinations of b"", r"", u"", and f"". */ - int saw_b = 0, saw_r = 0, saw_u = 0, saw_f = 0; - while (1) { - if (!(saw_b || saw_u || saw_f) && (c == 'b' || c == 'B')) - saw_b = 1; - /* Since this is a backwards compatibility support literal we don't - want to support it in arbitrary order like byte literals. */ - else if (!(saw_b || saw_u || saw_r || saw_f) - && (c == 'u'|| c == 'U')) { - saw_u = 1; - } - /* ur"" and ru"" are not supported */ - else if (!(saw_r || saw_u) && (c == 'r' || c == 'R')) { - saw_r = 1; - } - else if (!(saw_f || saw_b || saw_u) && (c == 'f' || c == 'F')) { - saw_f = 1; - } - else { - break; - } - c = tok_nextc(tok); - if (c == '"' || c == '\'') { - if (saw_f) { - goto f_string_quote; - } - goto letter_quote; - } - } - while (is_potential_identifier_char(c)) { - if (c >= 128) { - nonascii = 1; - } - c = tok_nextc(tok); - } - tok_backup(tok, c); - if (nonascii && !verify_identifier(tok)) { - return MAKE_TOKEN(ERRORTOKEN); - } - - p_start = tok->start; - p_end = tok->cur; - - return MAKE_TOKEN(NAME); - } - - if (c == '\r') { - c = tok_nextc(tok); - } - - /* Newline */ - if (c == '\n') { - tok->atbol = 1; - if (blankline || tok->level > 0) { - if (tok->tok_extra_tokens) { - if (tok->comment_newline) { - tok->comment_newline = 0; - } - p_start = tok->start; - p_end = tok->cur; - return MAKE_TOKEN(NL); - } - goto nextline; - } - if (tok->comment_newline && tok->tok_extra_tokens) { - tok->comment_newline = 0; - p_start = tok->start; - p_end = tok->cur; - return MAKE_TOKEN(NL); - } - p_start = tok->start; - p_end = tok->cur - 1; /* Leave '\n' out of the string */ - tok->cont_line = 0; - return MAKE_TOKEN(NEWLINE); - } - - /* Period or number starting with period? */ - if (c == '.') { - c = tok_nextc(tok); - if (isdigit(c)) { - goto fraction; - } else if (c == '.') { - c = tok_nextc(tok); - if (c == '.') { - p_start = tok->start; - p_end = tok->cur; - return MAKE_TOKEN(ELLIPSIS); - } - else { - tok_backup(tok, c); - } - tok_backup(tok, '.'); - } - else { - tok_backup(tok, c); - } - p_start = tok->start; - p_end = tok->cur; - return MAKE_TOKEN(DOT); - } - - /* Number */ - if (isdigit(c)) { - if (c == '0') { - /* Hex, octal or binary -- maybe. */ - c = tok_nextc(tok); - if (c == 'x' || c == 'X') { - /* Hex */ - c = tok_nextc(tok); - do { - if (c == '_') { - c = tok_nextc(tok); - } - if (!isxdigit(c)) { - tok_backup(tok, c); - return MAKE_TOKEN(syntaxerror(tok, "invalid hexadecimal literal")); - } - do { - c = tok_nextc(tok); - } while (isxdigit(c)); - } while (c == '_'); - if (!verify_end_of_number(tok, c, "hexadecimal")) { - return MAKE_TOKEN(ERRORTOKEN); - } - } - else if (c == 'o' || c == 'O') { - /* Octal */ - c = tok_nextc(tok); - do { - if (c == '_') { - c = tok_nextc(tok); - } - if (c < '0' || c >= '8') { - if (isdigit(c)) { - return MAKE_TOKEN(syntaxerror(tok, - "invalid digit '%c' in octal literal", c)); - } - else { - tok_backup(tok, c); - return MAKE_TOKEN(syntaxerror(tok, "invalid octal literal")); - } - } - do { - c = tok_nextc(tok); - } while ('0' <= c && c < '8'); - } while (c == '_'); - if (isdigit(c)) { - return MAKE_TOKEN(syntaxerror(tok, - "invalid digit '%c' in octal literal", c)); - } - if (!verify_end_of_number(tok, c, "octal")) { - return MAKE_TOKEN(ERRORTOKEN); - } - } - else if (c == 'b' || c == 'B') { - /* Binary */ - c = tok_nextc(tok); - do { - if (c == '_') { - c = tok_nextc(tok); - } - if (c != '0' && c != '1') { - if (isdigit(c)) { - return MAKE_TOKEN(syntaxerror(tok, "invalid digit '%c' in binary literal", c)); - } - else { - tok_backup(tok, c); - return MAKE_TOKEN(syntaxerror(tok, "invalid binary literal")); - } - } - do { - c = tok_nextc(tok); - } while (c == '0' || c == '1'); - } while (c == '_'); - if (isdigit(c)) { - return MAKE_TOKEN(syntaxerror(tok, "invalid digit '%c' in binary literal", c)); - } - if (!verify_end_of_number(tok, c, "binary")) { - return MAKE_TOKEN(ERRORTOKEN); - } - } - else { - int nonzero = 0; - /* maybe old-style octal; c is first char of it */ - /* in any case, allow '0' as a literal */ - while (1) { - if (c == '_') { - c = tok_nextc(tok); - if (!isdigit(c)) { - tok_backup(tok, c); - return MAKE_TOKEN(syntaxerror(tok, "invalid decimal literal")); - } - } - if (c != '0') { - break; - } - c = tok_nextc(tok); - } - char* zeros_end = tok->cur; - if (isdigit(c)) { - nonzero = 1; - c = tok_decimal_tail(tok); - if (c == 0) { - return MAKE_TOKEN(ERRORTOKEN); - } - } - if (c == '.') { - c = tok_nextc(tok); - goto fraction; - } - else if (c == 'e' || c == 'E') { - goto exponent; - } - else if (c == 'j' || c == 'J') { - goto imaginary; - } - else if (nonzero && !tok->tok_extra_tokens) { - /* Old-style octal: now disallowed. */ - tok_backup(tok, c); - return MAKE_TOKEN(syntaxerror_known_range( - tok, (int)(tok->start + 1 - tok->line_start), - (int)(zeros_end - tok->line_start), - "leading zeros in decimal integer " - "literals are not permitted; " - "use an 0o prefix for octal integers")); - } - if (!verify_end_of_number(tok, c, "decimal")) { - return MAKE_TOKEN(ERRORTOKEN); - } - } - } - else { - /* Decimal */ - c = tok_decimal_tail(tok); - if (c == 0) { - return MAKE_TOKEN(ERRORTOKEN); - } - { - /* Accept floating point numbers. */ - if (c == '.') { - c = tok_nextc(tok); - fraction: - /* Fraction */ - if (isdigit(c)) { - c = tok_decimal_tail(tok); - if (c == 0) { - return MAKE_TOKEN(ERRORTOKEN); - } - } - } - if (c == 'e' || c == 'E') { - int e; - exponent: - e = c; - /* Exponent part */ - c = tok_nextc(tok); - if (c == '+' || c == '-') { - c = tok_nextc(tok); - if (!isdigit(c)) { - tok_backup(tok, c); - return MAKE_TOKEN(syntaxerror(tok, "invalid decimal literal")); - } - } else if (!isdigit(c)) { - tok_backup(tok, c); - if (!verify_end_of_number(tok, e, "decimal")) { - return MAKE_TOKEN(ERRORTOKEN); - } - tok_backup(tok, e); - p_start = tok->start; - p_end = tok->cur; - return MAKE_TOKEN(NUMBER); - } - c = tok_decimal_tail(tok); - if (c == 0) { - return MAKE_TOKEN(ERRORTOKEN); - } - } - if (c == 'j' || c == 'J') { - /* Imaginary part */ - imaginary: - c = tok_nextc(tok); - if (!verify_end_of_number(tok, c, "imaginary")) { - return MAKE_TOKEN(ERRORTOKEN); - } - } - else if (!verify_end_of_number(tok, c, "decimal")) { - return MAKE_TOKEN(ERRORTOKEN); - } - } - } - tok_backup(tok, c); - p_start = tok->start; - p_end = tok->cur; - return MAKE_TOKEN(NUMBER); - } - - f_string_quote: - if (((tolower(*tok->start) == 'f' || tolower(*tok->start) == 'r') && (c == '\'' || c == '"'))) { - int quote = c; - int quote_size = 1; /* 1 or 3 */ - - /* Nodes of type STRING, especially multi line strings - must be handled differently in order to get both - the starting line number and the column offset right. - (cf. issue 16806) */ - tok->first_lineno = tok->lineno; - tok->multi_line_start = tok->line_start; - - /* Find the quote size and start of string */ - int after_quote = tok_nextc(tok); - if (after_quote == quote) { - int after_after_quote = tok_nextc(tok); - if (after_after_quote == quote) { - quote_size = 3; - } - else { - // TODO: Check this - tok_backup(tok, after_after_quote); - tok_backup(tok, after_quote); - } - } - if (after_quote != quote) { - tok_backup(tok, after_quote); - } - - - p_start = tok->start; - p_end = tok->cur; - if (tok->tok_mode_stack_index + 1 >= MAXFSTRINGLEVEL) { - return MAKE_TOKEN(syntaxerror(tok, "too many nested f-strings")); - } - tokenizer_mode *the_current_tok = TOK_NEXT_MODE(tok); - the_current_tok->kind = TOK_FSTRING_MODE; - the_current_tok->f_string_quote = quote; - the_current_tok->f_string_quote_size = quote_size; - the_current_tok->f_string_start = tok->start; - the_current_tok->f_string_multi_line_start = tok->line_start; - the_current_tok->f_string_line_start = tok->lineno; - the_current_tok->f_string_start_offset = -1; - the_current_tok->f_string_multi_line_start_offset = -1; - the_current_tok->last_expr_buffer = NULL; - the_current_tok->last_expr_size = 0; - the_current_tok->last_expr_end = -1; - the_current_tok->f_string_debug = 0; - - switch (*tok->start) { - case 'F': - case 'f': - the_current_tok->f_string_raw = tolower(*(tok->start + 1)) == 'r'; - break; - case 'R': - case 'r': - the_current_tok->f_string_raw = 1; - break; - default: - Py_UNREACHABLE(); - } - - the_current_tok->curly_bracket_depth = 0; - the_current_tok->curly_bracket_expr_start_depth = -1; - return MAKE_TOKEN(FSTRING_START); - } - - letter_quote: - /* String */ - if (c == '\'' || c == '"') { - int quote = c; - int quote_size = 1; /* 1 or 3 */ - int end_quote_size = 0; - - /* Nodes of type STRING, especially multi line strings - must be handled differently in order to get both - the starting line number and the column offset right. - (cf. issue 16806) */ - tok->first_lineno = tok->lineno; - tok->multi_line_start = tok->line_start; - - /* Find the quote size and start of string */ - c = tok_nextc(tok); - if (c == quote) { - c = tok_nextc(tok); - if (c == quote) { - quote_size = 3; - } - else { - end_quote_size = 1; /* empty string found */ - } - } - if (c != quote) { - tok_backup(tok, c); - } - - /* Get rest of string */ - while (end_quote_size != quote_size) { - c = tok_nextc(tok); - if (tok->done == E_ERROR) { - return MAKE_TOKEN(ERRORTOKEN); - } - 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 - // the start of string, and report the error - // from the initial quote character - tok->cur = (char *)tok->start; - tok->cur++; - tok->line_start = tok->multi_line_start; - int start = tok->lineno; - tok->lineno = tok->first_lineno; - - if (INSIDE_FSTRING(tok)) { - /* When we are in an f-string, before raising the - * unterminated string literal error, check whether - * does the initial quote matches with f-strings quotes - * and if it is, then this must be a missing '}' token - * so raise the proper error */ - tokenizer_mode *the_current_tok = TOK_GET_MODE(tok); - if (the_current_tok->f_string_quote == quote && - the_current_tok->f_string_quote_size == quote_size) { - return MAKE_TOKEN(syntaxerror(tok, "f-string: expecting '}'", start)); - } - } - - if (quote_size == 3) { - syntaxerror(tok, "unterminated triple-quoted string literal" - " (detected at line %d)", start); - if (c != '\n') { - tok->done = E_EOFS; - } - return MAKE_TOKEN(ERRORTOKEN); - } - else { - syntaxerror(tok, "unterminated string literal (detected at" - " line %d)", start); - if (c != '\n') { - tok->done = E_EOLS; - } - return MAKE_TOKEN(ERRORTOKEN); - } - } - if (c == quote) { - end_quote_size += 1; - } - else { - end_quote_size = 0; - if (c == '\\') { - c = tok_nextc(tok); /* skip escaped char */ - if (c == '\r') { - c = tok_nextc(tok); - } - } - } - } - - p_start = tok->start; - p_end = tok->cur; - return MAKE_TOKEN(STRING); - } - - /* Line continuation */ - if (c == '\\') { - if ((c = tok_continuation_line(tok)) == -1) { - return MAKE_TOKEN(ERRORTOKEN); - } - tok->cont_line = 1; - goto again; /* Read next line */ - } - - /* Punctuation character */ - int is_punctuation = (c == ':' || c == '}' || c == '!' || c == '{'); - if (is_punctuation && INSIDE_FSTRING(tok) && INSIDE_FSTRING_EXPR(current_tok)) { - /* This code block gets executed before the curly_bracket_depth is incremented - * by the `{` case, so for ensuring that we are on the 0th level, we need - * to adjust it manually */ - int cursor = current_tok->curly_bracket_depth - (c != '{'); - if (cursor == 0 && !update_fstring_expr(tok, c)) { - return MAKE_TOKEN(ENDMARKER); - } - if (cursor == 0 && c != '{' && set_fstring_expr(tok, token, c)) { - return MAKE_TOKEN(ERRORTOKEN); - } - - if (c == ':' && cursor == current_tok->curly_bracket_expr_start_depth) { - current_tok->kind = TOK_FSTRING_MODE; - p_start = tok->start; - p_end = tok->cur; - return MAKE_TOKEN(_PyToken_OneChar(c)); - } - } - - /* Check for two-character token */ - { - int c2 = tok_nextc(tok); - int current_token = _PyToken_TwoChars(c, c2); - if (current_token != OP) { - int c3 = tok_nextc(tok); - int current_token3 = _PyToken_ThreeChars(c, c2, c3); - if (current_token3 != OP) { - current_token = current_token3; - } - else { - tok_backup(tok, c3); - } - p_start = tok->start; - p_end = tok->cur; - return MAKE_TOKEN(current_token); - } - tok_backup(tok, c2); - } - - /* Keep track of parentheses nesting level */ - switch (c) { - case '(': - case '[': - case '{': - if (tok->level >= MAXLEVEL) { - return MAKE_TOKEN(syntaxerror(tok, "too many nested parentheses")); - } - tok->parenstack[tok->level] = c; - tok->parenlinenostack[tok->level] = tok->lineno; - tok->parencolstack[tok->level] = (int)(tok->start - tok->line_start); - tok->level++; - if (INSIDE_FSTRING(tok)) { - current_tok->curly_bracket_depth++; - } - break; - case ')': - case ']': - case '}': - if (INSIDE_FSTRING(tok) && !current_tok->curly_bracket_depth && c == '}') { - return MAKE_TOKEN(syntaxerror(tok, "f-string: single '}' is not allowed")); - } - if (!tok->tok_extra_tokens && !tok->level) { - return MAKE_TOKEN(syntaxerror(tok, "unmatched '%c'", c)); - } - if (tok->level > 0) { - tok->level--; - int opening = tok->parenstack[tok->level]; - if (!tok->tok_extra_tokens && !((opening == '(' && c == ')') || - (opening == '[' && c == ']') || - (opening == '{' && c == '}'))) { - /* If the opening bracket belongs to an f-string's expression - part (e.g. f"{)}") and the closing bracket is an arbitrary - nested expression, then instead of matching a different - syntactical construct with it; we'll throw an unmatched - parentheses error. */ - if (INSIDE_FSTRING(tok) && opening == '{') { - assert(current_tok->curly_bracket_depth >= 0); - int previous_bracket = current_tok->curly_bracket_depth - 1; - if (previous_bracket == current_tok->curly_bracket_expr_start_depth) { - return MAKE_TOKEN(syntaxerror(tok, "f-string: unmatched '%c'", c)); - } - } - if (tok->parenlinenostack[tok->level] != tok->lineno) { - return MAKE_TOKEN(syntaxerror(tok, - "closing parenthesis '%c' does not match " - "opening parenthesis '%c' on line %d", - c, opening, tok->parenlinenostack[tok->level])); - } - else { - return MAKE_TOKEN(syntaxerror(tok, - "closing parenthesis '%c' does not match " - "opening parenthesis '%c'", - c, opening)); - } - } - } - - if (INSIDE_FSTRING(tok)) { - current_tok->curly_bracket_depth--; - if (c == '}' && current_tok->curly_bracket_depth == current_tok->curly_bracket_expr_start_depth) { - current_tok->curly_bracket_expr_start_depth--; - current_tok->kind = TOK_FSTRING_MODE; - current_tok->f_string_debug = 0; - } - } - break; - default: - break; - } - - if (!Py_UNICODE_ISPRINTABLE(c)) { - return MAKE_TOKEN(syntaxerror(tok, "invalid non-printable character U+%04X", c)); - } - - if( c == '=' && INSIDE_FSTRING_EXPR(current_tok)) { - current_tok->f_string_debug = 1; - } - - /* Punctuation character */ - p_start = tok->start; - p_end = tok->cur; - return MAKE_TOKEN(_PyToken_OneChar(c)); -} - -static int -tok_get_fstring_mode(struct tok_state *tok, tokenizer_mode* current_tok, struct token *token) -{ - const char *p_start = NULL; - const char *p_end = NULL; - int end_quote_size = 0; - int unicode_escape = 0; - - tok->start = tok->cur; - tok->first_lineno = tok->lineno; - tok->starting_col_offset = tok->col_offset; - - // If we start with a bracket, we defer to the normal mode as there is nothing for us to tokenize - // before it. - int start_char = tok_nextc(tok); - if (start_char == '{') { - int peek1 = tok_nextc(tok); - tok_backup(tok, peek1); - tok_backup(tok, start_char); - if (peek1 != '{') { - current_tok->curly_bracket_expr_start_depth++; - if (current_tok->curly_bracket_expr_start_depth >= MAX_EXPR_NESTING) { - return MAKE_TOKEN(syntaxerror(tok, "f-string: expressions nested too deeply")); - } - TOK_GET_MODE(tok)->kind = TOK_REGULAR_MODE; - return tok_get_normal_mode(tok, current_tok, token); - } - } - else { - tok_backup(tok, start_char); - } - - // Check if we are at the end of the string - for (int i = 0; i < current_tok->f_string_quote_size; i++) { - int quote = tok_nextc(tok); - if (quote != current_tok->f_string_quote) { - tok_backup(tok, quote); - goto f_string_middle; - } - } - - if (current_tok->last_expr_buffer != NULL) { - PyMem_Free(current_tok->last_expr_buffer); - current_tok->last_expr_buffer = NULL; - current_tok->last_expr_size = 0; - current_tok->last_expr_end = -1; - } - - p_start = tok->start; - p_end = tok->cur; - tok->tok_mode_stack_index--; - return MAKE_TOKEN(FSTRING_END); - -f_string_middle: - - // TODO: This is a bit of a hack, but it works for now. We need to find a better way to handle - // this. - tok->multi_line_start = tok->line_start; - while (end_quote_size != current_tok->f_string_quote_size) { - int c = tok_nextc(tok); - if (tok->done == E_ERROR) { - return MAKE_TOKEN(ERRORTOKEN); - } - if (c == EOF || (current_tok->f_string_quote_size == 1 && c == '\n')) { - if (tok->decoding_erred) { - return MAKE_TOKEN(ERRORTOKEN); - } - - assert(tok->multi_line_start != NULL); - // shift the tok_state's location into - // the start of string, and report the error - // from the initial quote character - tok->cur = (char *)current_tok->f_string_start; - tok->cur++; - tok->line_start = current_tok->f_string_multi_line_start; - int start = tok->lineno; - - tokenizer_mode *the_current_tok = TOK_GET_MODE(tok); - tok->lineno = the_current_tok->f_string_line_start; - - if (current_tok->f_string_quote_size == 3) { - return MAKE_TOKEN(syntaxerror(tok, - "unterminated triple-quoted f-string literal" - " (detected at line %d)", start)); - } - else { - return MAKE_TOKEN(syntaxerror(tok, - "unterminated f-string literal (detected at" - " line %d)", start)); - } - } - - if (c == current_tok->f_string_quote) { - end_quote_size += 1; - continue; - } else { - end_quote_size = 0; - } - - int in_format_spec = ( - current_tok->last_expr_end != -1 - && - INSIDE_FSTRING_EXPR(current_tok) - ); - if (c == '{') { - int peek = tok_nextc(tok); - if (peek != '{' || in_format_spec) { - tok_backup(tok, peek); - tok_backup(tok, c); - current_tok->curly_bracket_expr_start_depth++; - if (current_tok->curly_bracket_expr_start_depth >= MAX_EXPR_NESTING) { - return MAKE_TOKEN(syntaxerror(tok, "f-string: expressions nested too deeply")); - } - TOK_GET_MODE(tok)->kind = TOK_REGULAR_MODE; - p_start = tok->start; - p_end = tok->cur; - } else { - p_start = tok->start; - p_end = tok->cur - 1; - } - return MAKE_TOKEN(FSTRING_MIDDLE); - } else if (c == '}') { - if (unicode_escape) { - p_start = tok->start; - p_end = tok->cur; - return MAKE_TOKEN(FSTRING_MIDDLE); - } - int peek = tok_nextc(tok); - - // The tokenizer can only be in the format spec if we have already completed the expression - // scanning (indicated by the end of the expression being set) and we are not at the top level - // of the bracket stack (-1 is the top level). Since format specifiers can't legally use double - // brackets, we can bypass it here. - if (peek == '}' && !in_format_spec) { - p_start = tok->start; - p_end = tok->cur - 1; - } else { - tok_backup(tok, peek); - tok_backup(tok, c); - TOK_GET_MODE(tok)->kind = TOK_REGULAR_MODE; - p_start = tok->start; - p_end = tok->cur; - } - return MAKE_TOKEN(FSTRING_MIDDLE); - } else if (c == '\\') { - int peek = tok_nextc(tok); - if (peek == '\r') { - peek = tok_nextc(tok); - } - // Special case when the backslash is right before a curly - // brace. We have to restore and return the control back - // to the loop for the next iteration. - if (peek == '{' || peek == '}') { - if (!current_tok->f_string_raw) { - if (warn_invalid_escape_sequence(tok, peek)) { - return MAKE_TOKEN(ERRORTOKEN); - } - } - tok_backup(tok, peek); - continue; - } - - if (!current_tok->f_string_raw) { - if (peek == 'N') { - /* Handle named unicode escapes (\N{BULLET}) */ - peek = tok_nextc(tok); - if (peek == '{') { - unicode_escape = 1; - } else { - tok_backup(tok, peek); - } - } - } /* else { - skip the escaped character - }*/ - } - } - - // Backup the f-string quotes to emit a final FSTRING_MIDDLE and - // add the quotes to the FSTRING_END in the next tokenizer iteration. - for (int i = 0; i < current_tok->f_string_quote_size; i++) { - tok_backup(tok, current_tok->f_string_quote); - } - p_start = tok->start; - p_end = tok->cur; - return MAKE_TOKEN(FSTRING_MIDDLE); -} - - -static int -tok_get(struct tok_state *tok, struct token *token) -{ - tokenizer_mode *current_tok = TOK_GET_MODE(tok); - if (current_tok->kind == TOK_REGULAR_MODE) { - return tok_get_normal_mode(tok, current_tok, token); - } else { - return tok_get_fstring_mode(tok, current_tok, token); - } -} - -int -_PyTokenizer_Get(struct tok_state *tok, struct token *token) -{ - int result = tok_get(tok, token); - if (tok->decoding_erred) { - result = ERRORTOKEN; - tok->done = E_DECODE; - } - return result; -} - -#if defined(__wasi__) || (defined(__EMSCRIPTEN__) && (__EMSCRIPTEN_major__ >= 3)) -// fdopen() with borrowed fd. WASI does not provide dup() and Emscripten's -// dup() emulation with open() is slow. -typedef union { - void *cookie; - int fd; -} borrowed; - -static ssize_t -borrow_read(void *cookie, char *buf, size_t size) -{ - borrowed b = {.cookie = cookie}; - return read(b.fd, (void *)buf, size); -} - -static FILE * -fdopen_borrow(int fd) { - // supports only reading. seek fails. close and write are no-ops. - cookie_io_functions_t io_cb = {borrow_read, NULL, NULL, NULL}; - borrowed b = {.fd = fd}; - return fopencookie(b.cookie, "r", io_cb); -} -#else -static FILE * -fdopen_borrow(int fd) { - fd = _Py_dup(fd); - if (fd < 0) { - return NULL; - } - return fdopen(fd, "r"); -} -#endif - -/* Get the encoding of a Python file. Check for the coding cookie and check if - the file starts with a BOM. - - _PyTokenizer_FindEncodingFilename() returns NULL when it can't find the - encoding in the first or second line of the file (in which case the encoding - should be assumed to be UTF-8). - - The char* returned is malloc'ed via PyMem_Malloc() and thus must be freed - by the caller. */ - -char * -_PyTokenizer_FindEncodingFilename(int fd, PyObject *filename) -{ - struct tok_state *tok; - FILE *fp; - char *encoding = NULL; - - fp = fdopen_borrow(fd); - if (fp == NULL) { - return NULL; - } - tok = _PyTokenizer_FromFile(fp, NULL, NULL, NULL); - if (tok == NULL) { - fclose(fp); - return NULL; - } - if (filename != NULL) { - tok->filename = Py_NewRef(filename); - } - else { - tok->filename = PyUnicode_FromString(""); - if (tok->filename == NULL) { - fclose(fp); - _PyTokenizer_Free(tok); - return encoding; - } - } - struct token token; - // We don't want to report warnings here because it could cause infinite recursion - // if fetching the encoding shows a warning. - tok->report_warnings = 0; - while (tok->lineno < 2 && tok->done == E_OK) { - _PyToken_Init(&token); - _PyTokenizer_Get(tok, &token); - _PyToken_Free(&token); - } - fclose(fp); - if (tok->encoding) { - encoding = (char *)PyMem_Malloc(strlen(tok->encoding) + 1); - if (encoding) { - strcpy(encoding, tok->encoding); - } - } - _PyTokenizer_Free(tok); - return encoding; -} - -#ifdef Py_DEBUG -void -tok_dump(int type, char *start, char *end) -{ - fprintf(stderr, "%s", _PyParser_TokenNames[type]); - if (type == NAME || type == NUMBER || type == STRING || type == OP) - fprintf(stderr, "(%.*s)", (int)(end - start), start); -} -#endif // Py_DEBUG diff --git a/Parser/tokenizer.h b/Parser/tokenizer.h deleted file mode 100644 index 11d69fc5b2e15c..00000000000000 --- a/Parser/tokenizer.h +++ /dev/null @@ -1,148 +0,0 @@ -#ifndef Py_TOKENIZER_H -#define Py_TOKENIZER_H -#ifdef __cplusplus -extern "C" { -#endif - -#include "object.h" - -/* Tokenizer interface */ - -#include "pycore_token.h" /* For token types */ - -#define MAXINDENT 100 /* Max indentation level */ -#define MAXLEVEL 200 /* Max parentheses level */ -#define MAXFSTRINGLEVEL 150 /* Max f-string nesting level */ - -enum decoding_state { - STATE_INIT, - STATE_SEEK_CODING, - STATE_NORMAL -}; - -enum interactive_underflow_t { - /* Normal mode of operation: return a new token when asked in interactive mode */ - IUNDERFLOW_NORMAL, - /* Forcefully return ENDMARKER when asked for a new token in interactive mode. This - * can be used to prevent the tokenizer to prompt the user for new tokens */ - IUNDERFLOW_STOP, -}; - -struct token { - int level; - int lineno, col_offset, end_lineno, end_col_offset; - const char *start, *end; - PyObject *metadata; -}; - -enum tokenizer_mode_kind_t { - TOK_REGULAR_MODE, - TOK_FSTRING_MODE, -}; - -#define MAX_EXPR_NESTING 3 - -typedef struct _tokenizer_mode { - enum tokenizer_mode_kind_t kind; - - int curly_bracket_depth; - int curly_bracket_expr_start_depth; - - char f_string_quote; - int f_string_quote_size; - int f_string_raw; - const char* f_string_start; - const char* f_string_multi_line_start; - int f_string_line_start; - - Py_ssize_t f_string_start_offset; - Py_ssize_t f_string_multi_line_start_offset; - - Py_ssize_t last_expr_size; - Py_ssize_t last_expr_end; - char* last_expr_buffer; - int f_string_debug; -} tokenizer_mode; - -/* Tokenizer state */ -struct tok_state { - /* Input state; buf <= cur <= inp <= end */ - /* NB an entire line is held in the buffer */ - char *buf; /* Input buffer, or NULL; malloc'ed if fp != NULL or readline != NULL */ - char *cur; /* Next character in buffer */ - char *inp; /* End of data in buffer */ - int fp_interactive; /* If the file descriptor is interactive */ - char *interactive_src_start; /* The start of the source parsed so far in interactive mode */ - char *interactive_src_end; /* The end of the source parsed so far in interactive mode */ - const char *end; /* End of input buffer if buf != NULL */ - const char *start; /* Start of current token if not NULL */ - int done; /* E_OK normally, E_EOF at EOF, otherwise error code */ - /* NB If done != E_OK, cur must be == inp!!! */ - FILE *fp; /* Rest of input; NULL if tokenizing a string */ - int tabsize; /* Tab spacing */ - int indent; /* Current indentation index */ - int indstack[MAXINDENT]; /* Stack of indents */ - int atbol; /* Nonzero if at begin of new line */ - int pendin; /* Pending indents (if > 0) or dedents (if < 0) */ - const char *prompt, *nextprompt; /* For interactive prompting */ - int lineno; /* Current line number */ - int first_lineno; /* First line of a single line or multi line string - expression (cf. issue 16806) */ - int starting_col_offset; /* The column offset at the beginning of a token */ - int col_offset; /* Current col offset */ - int level; /* () [] {} Parentheses nesting level */ - /* Used to allow free continuations inside them */ - char parenstack[MAXLEVEL]; - int parenlinenostack[MAXLEVEL]; - int parencolstack[MAXLEVEL]; - PyObject *filename; - /* Stuff for checking on different tab sizes */ - int altindstack[MAXINDENT]; /* Stack of alternate indents */ - /* Stuff for PEP 0263 */ - enum decoding_state decoding_state; - int decoding_erred; /* whether erred in decoding */ - char *encoding; /* Source encoding. */ - int cont_line; /* whether we are in a continuation line. */ - const char* line_start; /* pointer to start of current line */ - const char* multi_line_start; /* pointer to start of first line of - a single line or multi line string - expression (cf. issue 16806) */ - PyObject *decoding_readline; /* open(...).readline */ - PyObject *decoding_buffer; - PyObject *readline; /* readline() function */ - const char* enc; /* Encoding for the current str. */ - char* str; /* Source string being tokenized (if tokenizing from a string)*/ - char* input; /* Tokenizer's newline translated copy of the string. */ - - int type_comments; /* Whether to look for type comments */ - - /* How to proceed when asked for a new token in interactive mode */ - enum interactive_underflow_t interactive_underflow; - int report_warnings; - // TODO: Factor this into its own thing - tokenizer_mode tok_mode_stack[MAXFSTRINGLEVEL]; - int tok_mode_stack_index; - int tok_extra_tokens; - int comment_newline; - int implicit_newline; -#ifdef Py_DEBUG - int debug; -#endif -}; - -extern struct tok_state *_PyTokenizer_FromString(const char *, int, int); -extern struct tok_state *_PyTokenizer_FromUTF8(const char *, int, int); -extern struct tok_state *_PyTokenizer_FromReadline(PyObject*, const char*, int, int); -extern struct tok_state *_PyTokenizer_FromFile(FILE *, const char*, - const char *, const char *); -extern void _PyTokenizer_Free(struct tok_state *); -extern void _PyToken_Free(struct token *); -extern void _PyToken_Init(struct token *); -extern int _PyTokenizer_Get(struct tok_state *, struct token *); - -#define tok_dump _Py_tok_dump - -#ifdef __cplusplus -} -#endif -#endif /* !Py_TOKENIZER_H */ diff --git a/Parser/tokenizer/file_tokenizer.c b/Parser/tokenizer/file_tokenizer.c new file mode 100644 index 00000000000000..2750527da484aa --- /dev/null +++ b/Parser/tokenizer/file_tokenizer.c @@ -0,0 +1,470 @@ +#include "Python.h" +#include "pycore_call.h" +#include "pycore_import.h" +#include "pycore_fileutils.h" +#include "errcode.h" + +#ifdef HAVE_UNISTD_H +# include // lseek(), read() +#endif + +#include "helpers.h" +#include "../lexer/state.h" +#include "../lexer/lexer.h" +#include "../lexer/buffer.h" + +static int +tok_concatenate_interactive_new_line(struct tok_state *tok, const char *line) { + assert(tok->fp_interactive); + + if (!line) { + return 0; + } + + Py_ssize_t current_size = tok->interactive_src_end - tok->interactive_src_start; + Py_ssize_t line_size = strlen(line); + char last_char = line[line_size > 0 ? line_size - 1 : line_size]; + if (last_char != '\n') { + line_size += 1; + } + char* new_str = tok->interactive_src_start; + + new_str = PyMem_Realloc(new_str, current_size + line_size + 1); + if (!new_str) { + if (tok->interactive_src_start) { + PyMem_Free(tok->interactive_src_start); + } + tok->interactive_src_start = NULL; + tok->interactive_src_end = NULL; + tok->done = E_NOMEM; + return -1; + } + strcpy(new_str + current_size, line); + tok->implicit_newline = 0; + if (last_char != '\n') { + /* Last line does not end in \n, fake one */ + new_str[current_size + line_size - 1] = '\n'; + new_str[current_size + line_size] = '\0'; + tok->implicit_newline = 1; + } + tok->interactive_src_start = new_str; + tok->interactive_src_end = new_str + current_size + line_size; + return 0; +} + +static int +tok_readline_raw(struct tok_state *tok) +{ + do { + if (!_PyLexer_tok_reserve_buf(tok, BUFSIZ)) { + return 0; + } + int n_chars = (int)(tok->end - tok->inp); + size_t line_size = 0; + char *line = _Py_UniversalNewlineFgetsWithSize(tok->inp, n_chars, tok->fp, NULL, &line_size); + if (line == NULL) { + return 1; + } + if (tok->fp_interactive && + tok_concatenate_interactive_new_line(tok, line) == -1) { + return 0; + } + tok->inp += line_size; + if (tok->inp == tok->buf) { + return 0; + } + } while (tok->inp[-1] != '\n'); + return 1; +} + +static int +tok_readline_recode(struct tok_state *tok) { + PyObject *line; + const char *buf; + Py_ssize_t buflen; + line = tok->decoding_buffer; + if (line == NULL) { + line = PyObject_CallNoArgs(tok->decoding_readline); + if (line == NULL) { + _PyTokenizer_error_ret(tok); + goto error; + } + } + else { + tok->decoding_buffer = NULL; + } + buf = PyUnicode_AsUTF8AndSize(line, &buflen); + if (buf == NULL) { + _PyTokenizer_error_ret(tok); + goto error; + } + // Make room for the null terminator *and* potentially + // an extra newline character that we may need to artificially + // add. + size_t buffer_size = buflen + 2; + if (!_PyLexer_tok_reserve_buf(tok, buffer_size)) { + goto error; + } + memcpy(tok->inp, buf, buflen); + tok->inp += buflen; + *tok->inp = '\0'; + if (tok->fp_interactive && + tok_concatenate_interactive_new_line(tok, buf) == -1) { + goto error; + } + Py_DECREF(line); + return 1; +error: + Py_XDECREF(line); + return 0; +} + +/* Fetch the next byte from TOK. */ +static int fp_getc(struct tok_state *tok) { + return getc(tok->fp); +} + +/* Unfetch the last byte back into TOK. */ +static void fp_ungetc(int c, struct tok_state *tok) { + ungetc(c, tok->fp); +} + +/* Set the readline function for TOK to a StreamReader's + readline function. The StreamReader is named ENC. + + This function is called from _PyTokenizer_check_bom and _PyTokenizer_check_coding_spec. + + ENC is usually identical to the future value of tok->encoding, + except for the (currently unsupported) case of UTF-16. + + Return 1 on success, 0 on failure. */ +static int +fp_setreadl(struct tok_state *tok, const char* enc) +{ + PyObject *readline, *open, *stream; + int fd; + long pos; + + fd = fileno(tok->fp); + /* Due to buffering the file offset for fd can be different from the file + * position of tok->fp. If tok->fp was opened in text mode on Windows, + * its file position counts CRLF as one char and can't be directly mapped + * to the file offset for fd. Instead we step back one byte and read to + * the end of line.*/ + pos = ftell(tok->fp); + if (pos == -1 || + lseek(fd, (off_t)(pos > 0 ? pos - 1 : pos), SEEK_SET) == (off_t)-1) { + PyErr_SetFromErrnoWithFilename(PyExc_OSError, NULL); + return 0; + } + + open = _PyImport_GetModuleAttrString("io", "open"); + if (open == NULL) { + return 0; + } + stream = PyObject_CallFunction(open, "isisOOO", + fd, "r", -1, enc, Py_None, Py_None, Py_False); + Py_DECREF(open); + if (stream == NULL) { + return 0; + } + + readline = PyObject_GetAttr(stream, &_Py_ID(readline)); + Py_DECREF(stream); + if (readline == NULL) { + return 0; + } + Py_XSETREF(tok->decoding_readline, readline); + + if (pos > 0) { + PyObject *bufobj = _PyObject_CallNoArgs(readline); + if (bufobj == NULL) { + return 0; + } + Py_DECREF(bufobj); + } + + return 1; +} + +static int +tok_underflow_interactive(struct tok_state *tok) { + if (tok->interactive_underflow == IUNDERFLOW_STOP) { + tok->done = E_INTERACT_STOP; + return 1; + } + char *newtok = PyOS_Readline(tok->fp ? tok->fp : stdin, stdout, tok->prompt); + if (newtok != NULL) { + char *translated = _PyTokenizer_translate_newlines(newtok, 0, 0, tok); + PyMem_Free(newtok); + if (translated == NULL) { + return 0; + } + newtok = translated; + } + if (tok->encoding && newtok && *newtok) { + /* Recode to UTF-8 */ + Py_ssize_t buflen; + const char* buf; + PyObject *u = _PyTokenizer_translate_into_utf8(newtok, tok->encoding); + PyMem_Free(newtok); + if (u == NULL) { + tok->done = E_DECODE; + return 0; + } + buflen = PyBytes_GET_SIZE(u); + buf = PyBytes_AS_STRING(u); + newtok = PyMem_Malloc(buflen+1); + if (newtok == NULL) { + Py_DECREF(u); + tok->done = E_NOMEM; + return 0; + } + strcpy(newtok, buf); + Py_DECREF(u); + } + if (tok->fp_interactive && + tok_concatenate_interactive_new_line(tok, newtok) == -1) { + PyMem_Free(newtok); + return 0; + } + if (tok->nextprompt != NULL) { + tok->prompt = tok->nextprompt; + } + if (newtok == NULL) { + tok->done = E_INTR; + } + else if (*newtok == '\0') { + PyMem_Free(newtok); + tok->done = E_EOF; + } + else if (tok->start != NULL) { + Py_ssize_t cur_multi_line_start = tok->multi_line_start - tok->buf; + _PyLexer_remember_fstring_buffers(tok); + size_t size = strlen(newtok); + ADVANCE_LINENO(); + if (!_PyLexer_tok_reserve_buf(tok, size + 1)) { + PyMem_Free(tok->buf); + tok->buf = NULL; + PyMem_Free(newtok); + return 0; + } + memcpy(tok->cur, newtok, size + 1); + PyMem_Free(newtok); + tok->inp += size; + tok->multi_line_start = tok->buf + cur_multi_line_start; + _PyLexer_restore_fstring_buffers(tok); + } + else { + _PyLexer_remember_fstring_buffers(tok); + ADVANCE_LINENO(); + PyMem_Free(tok->buf); + tok->buf = newtok; + tok->cur = tok->buf; + tok->line_start = tok->buf; + tok->inp = strchr(tok->buf, '\0'); + tok->end = tok->inp + 1; + _PyLexer_restore_fstring_buffers(tok); + } + if (tok->done != E_OK) { + if (tok->prompt != NULL) { + PySys_WriteStderr("\n"); + } + return 0; + } + + if (tok->tok_mode_stack_index && !_PyLexer_update_fstring_expr(tok, 0)) { + return 0; + } + return 1; +} + +static int +tok_underflow_file(struct tok_state *tok) { + if (tok->start == NULL && !INSIDE_FSTRING(tok)) { + tok->cur = tok->inp = tok->buf; + } + if (tok->decoding_state == STATE_INIT) { + /* We have not yet determined the encoding. + If an encoding is found, use the file-pointer + reader functions from now on. */ + if (!_PyTokenizer_check_bom(fp_getc, fp_ungetc, fp_setreadl, tok)) { + _PyTokenizer_error_ret(tok); + return 0; + } + assert(tok->decoding_state != STATE_INIT); + } + /* Read until '\n' or EOF */ + if (tok->decoding_readline != NULL) { + /* We already have a codec associated with this input. */ + if (!tok_readline_recode(tok)) { + return 0; + } + } + else { + /* We want a 'raw' read. */ + if (!tok_readline_raw(tok)) { + return 0; + } + } + if (tok->inp == tok->cur) { + tok->done = E_EOF; + return 0; + } + tok->implicit_newline = 0; + if (tok->inp[-1] != '\n') { + assert(tok->inp + 1 < tok->end); + /* Last line does not end in \n, fake one */ + *tok->inp++ = '\n'; + *tok->inp = '\0'; + tok->implicit_newline = 1; + } + + if (tok->tok_mode_stack_index && !_PyLexer_update_fstring_expr(tok, 0)) { + return 0; + } + + ADVANCE_LINENO(); + if (tok->decoding_state != STATE_NORMAL) { + if (tok->lineno > 2) { + tok->decoding_state = STATE_NORMAL; + } + else if (!_PyTokenizer_check_coding_spec(tok->cur, strlen(tok->cur), + tok, fp_setreadl)) + { + return 0; + } + } + /* The default encoding is UTF-8, so make sure we don't have any + non-UTF-8 sequences in it. */ + if (!tok->encoding && !_PyTokenizer_ensure_utf8(tok->cur, tok)) { + _PyTokenizer_error_ret(tok); + return 0; + } + assert(tok->done == E_OK); + return tok->done == E_OK; +} + +/* Set up tokenizer for file */ +struct tok_state * +_PyTokenizer_FromFile(FILE *fp, const char* enc, + const char *ps1, const char *ps2) +{ + struct tok_state *tok = _PyTokenizer_tok_new(); + if (tok == NULL) + return NULL; + if ((tok->buf = (char *)PyMem_Malloc(BUFSIZ)) == NULL) { + _PyTokenizer_Free(tok); + return NULL; + } + tok->cur = tok->inp = tok->buf; + tok->end = tok->buf + BUFSIZ; + tok->fp = fp; + tok->prompt = ps1; + tok->nextprompt = ps2; + if (ps1 || ps2) { + tok->underflow = &tok_underflow_interactive; + } else { + tok->underflow = &tok_underflow_file; + } + if (enc != NULL) { + /* Must copy encoding declaration since it + gets copied into the parse tree. */ + tok->encoding = _PyTokenizer_new_string(enc, strlen(enc), tok); + if (!tok->encoding) { + _PyTokenizer_Free(tok); + return NULL; + } + tok->decoding_state = STATE_NORMAL; + } + return tok; +} + +#if defined(__wasi__) || (defined(__EMSCRIPTEN__) && (__EMSCRIPTEN_major__ >= 3)) +// fdopen() with borrowed fd. WASI does not provide dup() and Emscripten's +// dup() emulation with open() is slow. +typedef union { + void *cookie; + int fd; +} borrowed; + +static ssize_t +borrow_read(void *cookie, char *buf, size_t size) +{ + borrowed b = {.cookie = cookie}; + return read(b.fd, (void *)buf, size); +} + +static FILE * +fdopen_borrow(int fd) { + // supports only reading. seek fails. close and write are no-ops. + cookie_io_functions_t io_cb = {borrow_read, NULL, NULL, NULL}; + borrowed b = {.fd = fd}; + return fopencookie(b.cookie, "r", io_cb); +} +#else +static FILE * +fdopen_borrow(int fd) { + fd = _Py_dup(fd); + if (fd < 0) { + return NULL; + } + return fdopen(fd, "r"); +} +#endif + +/* Get the encoding of a Python file. Check for the coding cookie and check if + the file starts with a BOM. + + _PyTokenizer_FindEncodingFilename() returns NULL when it can't find the + encoding in the first or second line of the file (in which case the encoding + should be assumed to be UTF-8). + + The char* returned is malloc'ed via PyMem_Malloc() and thus must be freed + by the caller. */ +char * +_PyTokenizer_FindEncodingFilename(int fd, PyObject *filename) +{ + struct tok_state *tok; + FILE *fp; + char *encoding = NULL; + + fp = fdopen_borrow(fd); + if (fp == NULL) { + return NULL; + } + tok = _PyTokenizer_FromFile(fp, NULL, NULL, NULL); + if (tok == NULL) { + fclose(fp); + return NULL; + } + if (filename != NULL) { + tok->filename = Py_NewRef(filename); + } + else { + tok->filename = PyUnicode_FromString(""); + if (tok->filename == NULL) { + fclose(fp); + _PyTokenizer_Free(tok); + return encoding; + } + } + struct token token; + // We don't want to report warnings here because it could cause infinite recursion + // if fetching the encoding shows a warning. + tok->report_warnings = 0; + while (tok->lineno < 2 && tok->done == E_OK) { + _PyToken_Init(&token); + _PyTokenizer_Get(tok, &token); + _PyToken_Free(&token); + } + fclose(fp); + if (tok->encoding) { + encoding = (char *)PyMem_Malloc(strlen(tok->encoding) + 1); + if (encoding) { + strcpy(encoding, tok->encoding); + } + } + _PyTokenizer_Free(tok); + return encoding; +} diff --git a/Parser/tokenizer/helpers.c b/Parser/tokenizer/helpers.c new file mode 100644 index 00000000000000..9c9d05bbef0f1a --- /dev/null +++ b/Parser/tokenizer/helpers.c @@ -0,0 +1,552 @@ +#include "Python.h" +#include "errcode.h" +#include "pycore_token.h" + +#include "../lexer/state.h" + + +/* ############## ERRORS ############## */ + +static int +_syntaxerror_range(struct tok_state *tok, const char *format, + int col_offset, int end_col_offset, + va_list vargs) +{ + // In release builds, we don't want to overwrite a previous error, but in debug builds we + // want to fail if we are not doing it so we can fix it. + assert(tok->done != E_ERROR); + if (tok->done == E_ERROR) { + return ERRORTOKEN; + } + PyObject *errmsg, *errtext, *args; + errmsg = PyUnicode_FromFormatV(format, vargs); + if (!errmsg) { + goto error; + } + + errtext = PyUnicode_DecodeUTF8(tok->line_start, tok->cur - tok->line_start, + "replace"); + if (!errtext) { + goto error; + } + + if (col_offset == -1) { + col_offset = (int)PyUnicode_GET_LENGTH(errtext); + } + if (end_col_offset == -1) { + end_col_offset = col_offset; + } + + Py_ssize_t line_len = strcspn(tok->line_start, "\n"); + if (line_len != tok->cur - tok->line_start) { + Py_DECREF(errtext); + errtext = PyUnicode_DecodeUTF8(tok->line_start, line_len, + "replace"); + } + if (!errtext) { + goto error; + } + + args = Py_BuildValue("(O(OiiNii))", errmsg, tok->filename, tok->lineno, + col_offset, errtext, tok->lineno, end_col_offset); + if (args) { + PyErr_SetObject(PyExc_SyntaxError, args); + Py_DECREF(args); + } + +error: + Py_XDECREF(errmsg); + tok->done = E_ERROR; + return ERRORTOKEN; +} + +int +_PyTokenizer_syntaxerror(struct tok_state *tok, const char *format, ...) +{ + // This errors are cleaned on startup. Todo: Fix it. + va_list vargs; + va_start(vargs, format); + int ret = _syntaxerror_range(tok, format, -1, -1, vargs); + va_end(vargs); + return ret; +} + +int +_PyTokenizer_syntaxerror_known_range(struct tok_state *tok, + int col_offset, int end_col_offset, + const char *format, ...) +{ + va_list vargs; + va_start(vargs, format); + int ret = _syntaxerror_range(tok, format, col_offset, end_col_offset, vargs); + va_end(vargs); + return ret; +} + +int +_PyTokenizer_indenterror(struct tok_state *tok) +{ + tok->done = E_TABSPACE; + tok->cur = tok->inp; + return ERRORTOKEN; +} + +char * +_PyTokenizer_error_ret(struct tok_state *tok) /* XXX */ +{ + tok->decoding_erred = 1; + if ((tok->fp != NULL || tok->readline != NULL) && tok->buf != NULL) {/* see _PyTokenizer_Free */ + PyMem_Free(tok->buf); + } + tok->buf = tok->cur = tok->inp = NULL; + tok->start = NULL; + tok->end = NULL; + tok->done = E_DECODE; + return NULL; /* as if it were EOF */ +} + +int +_PyTokenizer_warn_invalid_escape_sequence(struct tok_state *tok, int first_invalid_escape_char) +{ + if (!tok->report_warnings) { + return 0; + } + + PyObject *msg = PyUnicode_FromFormat( + "invalid escape sequence '\\%c'", + (char) first_invalid_escape_char + ); + + if (msg == NULL) { + return -1; + } + + if (PyErr_WarnExplicitObject(PyExc_SyntaxWarning, msg, tok->filename, + tok->lineno, NULL, NULL) < 0) { + Py_DECREF(msg); + + if (PyErr_ExceptionMatches(PyExc_SyntaxWarning)) { + /* Replace the SyntaxWarning exception with a SyntaxError + to get a more accurate error report */ + PyErr_Clear(); + return _PyTokenizer_syntaxerror(tok, "invalid escape sequence '\\%c'", (char) first_invalid_escape_char); + } + + return -1; + } + + Py_DECREF(msg); + return 0; +} + +int +_PyTokenizer_parser_warn(struct tok_state *tok, PyObject *category, const char *format, ...) +{ + if (!tok->report_warnings) { + return 0; + } + + PyObject *errmsg; + va_list vargs; + va_start(vargs, format); + errmsg = PyUnicode_FromFormatV(format, vargs); + va_end(vargs); + if (!errmsg) { + goto error; + } + + if (PyErr_WarnExplicitObject(category, errmsg, tok->filename, + tok->lineno, NULL, NULL) < 0) { + if (PyErr_ExceptionMatches(category)) { + /* Replace the DeprecationWarning exception with a SyntaxError + to get a more accurate error report */ + PyErr_Clear(); + _PyTokenizer_syntaxerror(tok, "%U", errmsg); + } + goto error; + } + Py_DECREF(errmsg); + return 0; + +error: + Py_XDECREF(errmsg); + tok->done = E_ERROR; + return -1; +} + + +/* ############## STRING MANIPULATION ############## */ + +char * +_PyTokenizer_new_string(const char *s, Py_ssize_t len, struct tok_state *tok) +{ + char* result = (char *)PyMem_Malloc(len + 1); + if (!result) { + tok->done = E_NOMEM; + return NULL; + } + memcpy(result, s, len); + result[len] = '\0'; + return result; +} + +PyObject * +_PyTokenizer_translate_into_utf8(const char* str, const char* enc) { + PyObject *utf8; + PyObject* buf = PyUnicode_Decode(str, strlen(str), enc, NULL); + if (buf == NULL) + return NULL; + utf8 = PyUnicode_AsUTF8String(buf); + Py_DECREF(buf); + return utf8; +} + +char * +_PyTokenizer_translate_newlines(const char *s, int exec_input, int preserve_crlf, + struct tok_state *tok) { + int skip_next_lf = 0; + size_t needed_length = strlen(s) + 2, final_length; + char *buf, *current; + char c = '\0'; + buf = PyMem_Malloc(needed_length); + if (buf == NULL) { + tok->done = E_NOMEM; + return NULL; + } + for (current = buf; *s; s++, current++) { + c = *s; + if (skip_next_lf) { + skip_next_lf = 0; + if (c == '\n') { + c = *++s; + if (!c) + break; + } + } + if (!preserve_crlf && c == '\r') { + skip_next_lf = 1; + c = '\n'; + } + *current = c; + } + /* If this is exec input, add a newline to the end of the string if + there isn't one already. */ + if (exec_input && c != '\n' && c != '\0') { + *current = '\n'; + current++; + } + *current = '\0'; + final_length = current - buf + 1; + if (final_length < needed_length && final_length) { + /* should never fail */ + char* result = PyMem_Realloc(buf, final_length); + if (result == NULL) { + PyMem_Free(buf); + } + buf = result; + } + return buf; +} + +/* ############## ENCODING STUFF ############## */ + + +/* See whether the file starts with a BOM. If it does, + invoke the set_readline function with the new encoding. + Return 1 on success, 0 on failure. */ +int +_PyTokenizer_check_bom(int get_char(struct tok_state *), + void unget_char(int, struct tok_state *), + int set_readline(struct tok_state *, const char *), + struct tok_state *tok) +{ + int ch1, ch2, ch3; + ch1 = get_char(tok); + tok->decoding_state = STATE_SEEK_CODING; + if (ch1 == EOF) { + return 1; + } else if (ch1 == 0xEF) { + ch2 = get_char(tok); + if (ch2 != 0xBB) { + unget_char(ch2, tok); + unget_char(ch1, tok); + return 1; + } + ch3 = get_char(tok); + if (ch3 != 0xBF) { + unget_char(ch3, tok); + unget_char(ch2, tok); + unget_char(ch1, tok); + return 1; + } + } else { + unget_char(ch1, tok); + return 1; + } + if (tok->encoding != NULL) + PyMem_Free(tok->encoding); + tok->encoding = _PyTokenizer_new_string("utf-8", 5, tok); + if (!tok->encoding) + return 0; + /* No need to set_readline: input is already utf-8 */ + return 1; +} + +static const char * +get_normal_name(const char *s) /* for utf-8 and latin-1 */ +{ + char buf[13]; + int i; + for (i = 0; i < 12; i++) { + int c = s[i]; + if (c == '\0') + break; + else if (c == '_') + buf[i] = '-'; + else + buf[i] = Py_TOLOWER(c); + } + buf[i] = '\0'; + if (strcmp(buf, "utf-8") == 0 || + strncmp(buf, "utf-8-", 6) == 0) + return "utf-8"; + else if (strcmp(buf, "latin-1") == 0 || + strcmp(buf, "iso-8859-1") == 0 || + strcmp(buf, "iso-latin-1") == 0 || + strncmp(buf, "latin-1-", 8) == 0 || + strncmp(buf, "iso-8859-1-", 11) == 0 || + strncmp(buf, "iso-latin-1-", 12) == 0) + return "iso-8859-1"; + else + return s; +} + +/* Return the coding spec in S, or NULL if none is found. */ +static int +get_coding_spec(const char *s, char **spec, Py_ssize_t size, struct tok_state *tok) +{ + Py_ssize_t i; + *spec = NULL; + /* Coding spec must be in a comment, and that comment must be + * the only statement on the source code line. */ + for (i = 0; i < size - 6; i++) { + if (s[i] == '#') + break; + if (s[i] != ' ' && s[i] != '\t' && s[i] != '\014') + return 1; + } + for (; i < size - 6; i++) { /* XXX inefficient search */ + const char* t = s + i; + if (memcmp(t, "coding", 6) == 0) { + const char* begin = NULL; + t += 6; + if (t[0] != ':' && t[0] != '=') + continue; + do { + t++; + } while (t[0] == ' ' || t[0] == '\t'); + + begin = t; + while (Py_ISALNUM(t[0]) || + t[0] == '-' || t[0] == '_' || t[0] == '.') + t++; + + if (begin < t) { + char* r = _PyTokenizer_new_string(begin, t - begin, tok); + const char* q; + if (!r) + return 0; + q = get_normal_name(r); + if (r != q) { + PyMem_Free(r); + r = _PyTokenizer_new_string(q, strlen(q), tok); + if (!r) + return 0; + } + *spec = r; + break; + } + } + } + return 1; +} + +/* Check whether the line contains a coding spec. If it does, + invoke the set_readline function for the new encoding. + This function receives the tok_state and the new encoding. + Return 1 on success, 0 on failure. */ +int +_PyTokenizer_check_coding_spec(const char* line, Py_ssize_t size, struct tok_state *tok, + int set_readline(struct tok_state *, const char *)) +{ + char *cs; + if (tok->cont_line) { + /* It's a continuation line, so it can't be a coding spec. */ + tok->decoding_state = STATE_NORMAL; + return 1; + } + if (!get_coding_spec(line, &cs, size, tok)) { + return 0; + } + if (!cs) { + Py_ssize_t i; + for (i = 0; i < size; i++) { + if (line[i] == '#' || line[i] == '\n' || line[i] == '\r') + break; + if (line[i] != ' ' && line[i] != '\t' && line[i] != '\014') { + /* Stop checking coding spec after a line containing + * anything except a comment. */ + tok->decoding_state = STATE_NORMAL; + break; + } + } + return 1; + } + tok->decoding_state = STATE_NORMAL; + if (tok->encoding == NULL) { + assert(tok->decoding_readline == NULL); + if (strcmp(cs, "utf-8") != 0 && !set_readline(tok, cs)) { + _PyTokenizer_error_ret(tok); + PyErr_Format(PyExc_SyntaxError, "encoding problem: %s", cs); + PyMem_Free(cs); + return 0; + } + tok->encoding = cs; + } else { /* then, compare cs with BOM */ + if (strcmp(tok->encoding, cs) != 0) { + _PyTokenizer_error_ret(tok); + PyErr_Format(PyExc_SyntaxError, + "encoding problem: %s with BOM", cs); + PyMem_Free(cs); + return 0; + } + PyMem_Free(cs); + } + return 1; +} + +/* 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. 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) { + /* single-byte code */ + return 1; + } + 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) { + /* \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 < 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 { + /* invalid start byte */ + return 0; + } + length = expected + 1; + for (; expected; expected--) + if (s[expected] < 0x80 || s[expected] >= 0xC0) + return 0; + return length; +} + +int +_PyTokenizer_ensure_utf8(char *line, struct tok_state *tok) +{ + int badchar = 0; + unsigned char *c; + int length; + for (c = (unsigned char *)line; *c; c += length) { + if (!(length = valid_utf8(c))) { + badchar = *c; + break; + } + } + if (badchar) { + 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); + return 0; + } + return 1; +} + + +/* ############## DEBUGGING STUFF ############## */ + +#ifdef Py_DEBUG +void +_PyTokenizer_print_escape(FILE *f, const char *s, Py_ssize_t size) +{ + if (s == NULL) { + fputs("NULL", f); + return; + } + putc('"', f); + while (size-- > 0) { + unsigned char c = *s++; + switch (c) { + case '\n': fputs("\\n", f); break; + case '\r': fputs("\\r", f); break; + case '\t': fputs("\\t", f); break; + case '\f': fputs("\\f", f); break; + case '\'': fputs("\\'", f); break; + case '"': fputs("\\\"", f); break; + default: + if (0x20 <= c && c <= 0x7f) + putc(c, f); + else + fprintf(f, "\\x%02x", c); + } + } + putc('"', f); +} + +void +_PyTokenizer_tok_dump(int type, char *start, char *end) +{ + fprintf(stderr, "%s", _PyParser_TokenNames[type]); + if (type == NAME || type == NUMBER || type == STRING || type == OP) + fprintf(stderr, "(%.*s)", (int)(end - start), start); +} +#endif diff --git a/Parser/tokenizer/helpers.h b/Parser/tokenizer/helpers.h new file mode 100644 index 00000000000000..42ea13cd1f853f --- /dev/null +++ b/Parser/tokenizer/helpers.h @@ -0,0 +1,37 @@ +#ifndef _PY_TOKENIZER_HELPERS_H_ +#define _PY_TOKENIZER_HELPERS_H_ + +#include "Python.h" + +#include "../lexer/state.h" + +#define ADVANCE_LINENO() \ + tok->lineno++; \ + tok->col_offset = 0; + +int _PyTokenizer_syntaxerror(struct tok_state *tok, const char *format, ...); +int _PyTokenizer_syntaxerror_known_range(struct tok_state *tok, int col_offset, int end_col_offset, const char *format, ...); +int _PyTokenizer_indenterror(struct tok_state *tok); +int _PyTokenizer_warn_invalid_escape_sequence(struct tok_state *tok, int first_invalid_escape_char); +int _PyTokenizer_parser_warn(struct tok_state *tok, PyObject *category, const char *format, ...); +char *_PyTokenizer_error_ret(struct tok_state *tok); + +char *_PyTokenizer_new_string(const char *s, Py_ssize_t len, struct tok_state *tok); +char *_PyTokenizer_translate_newlines(const char *s, int exec_input, int preserve_crlf, struct tok_state *tok); +PyObject *_PyTokenizer_translate_into_utf8(const char* str, const char* enc); + +int _PyTokenizer_check_bom(int get_char(struct tok_state *), + void unget_char(int, struct tok_state *), + int set_readline(struct tok_state *, const char *), + struct tok_state *tok); +int _PyTokenizer_check_coding_spec(const char* line, Py_ssize_t size, struct tok_state *tok, + int set_readline(struct tok_state *, const char *)); +int _PyTokenizer_ensure_utf8(char *line, struct tok_state *tok); + +#ifdef Py_DEBUG +void _PyTokenizer_print_escape(FILE *f, const char *s, Py_ssize_t size); +void _PyTokenizer_tok_dump(int type, char *start, char *end); +#endif + + +#endif diff --git a/Parser/tokenizer/readline_tokenizer.c b/Parser/tokenizer/readline_tokenizer.c new file mode 100644 index 00000000000000..a2637af9902dd3 --- /dev/null +++ b/Parser/tokenizer/readline_tokenizer.c @@ -0,0 +1,134 @@ +#include "Python.h" +#include "errcode.h" + +#include "helpers.h" +#include "../lexer/lexer.h" +#include "../lexer/state.h" +#include "../lexer/buffer.h" + +static int +tok_readline_string(struct tok_state* tok) { + PyObject* line = NULL; + PyObject* raw_line = PyObject_CallNoArgs(tok->readline); + if (raw_line == NULL) { + if (PyErr_ExceptionMatches(PyExc_StopIteration)) { + PyErr_Clear(); + return 1; + } + _PyTokenizer_error_ret(tok); + goto error; + } + if(tok->encoding != NULL) { + if (!PyBytes_Check(raw_line)) { + PyErr_Format(PyExc_TypeError, "readline() returned a non-bytes object"); + _PyTokenizer_error_ret(tok); + goto error; + } + line = PyUnicode_Decode(PyBytes_AS_STRING(raw_line), PyBytes_GET_SIZE(raw_line), + tok->encoding, "replace"); + Py_CLEAR(raw_line); + if (line == NULL) { + _PyTokenizer_error_ret(tok); + goto error; + } + } else { + if(!PyUnicode_Check(raw_line)) { + PyErr_Format(PyExc_TypeError, "readline() returned a non-string object"); + _PyTokenizer_error_ret(tok); + goto error; + } + line = raw_line; + raw_line = NULL; + } + Py_ssize_t buflen; + const char* buf = PyUnicode_AsUTF8AndSize(line, &buflen); + if (buf == NULL) { + _PyTokenizer_error_ret(tok); + goto error; + } + + // Make room for the null terminator *and* potentially + // an extra newline character that we may need to artificially + // add. + size_t buffer_size = buflen + 2; + if (!_PyLexer_tok_reserve_buf(tok, buffer_size)) { + goto error; + } + memcpy(tok->inp, buf, buflen); + tok->inp += buflen; + *tok->inp = '\0'; + + tok->line_start = tok->cur; + Py_DECREF(line); + return 1; +error: + Py_XDECREF(raw_line); + Py_XDECREF(line); + return 0; +} + +static int +tok_underflow_readline(struct tok_state* tok) { + assert(tok->decoding_state == STATE_NORMAL); + assert(tok->fp == NULL && tok->input == NULL && tok->decoding_readline == NULL); + if (tok->start == NULL && !INSIDE_FSTRING(tok)) { + tok->cur = tok->inp = tok->buf; + } + if (!tok_readline_string(tok)) { + return 0; + } + if (tok->inp == tok->cur) { + tok->done = E_EOF; + return 0; + } + tok->implicit_newline = 0; + if (tok->inp[-1] != '\n') { + assert(tok->inp + 1 < tok->end); + /* Last line does not end in \n, fake one */ + *tok->inp++ = '\n'; + *tok->inp = '\0'; + tok->implicit_newline = 1; + } + + if (tok->tok_mode_stack_index && !_PyLexer_update_fstring_expr(tok, 0)) { + return 0; + } + + ADVANCE_LINENO(); + /* The default encoding is UTF-8, so make sure we don't have any + non-UTF-8 sequences in it. */ + if (!tok->encoding && !_PyTokenizer_ensure_utf8(tok->cur, tok)) { + _PyTokenizer_error_ret(tok); + return 0; + } + assert(tok->done == E_OK); + return tok->done == E_OK; +} + +struct tok_state * +_PyTokenizer_FromReadline(PyObject* readline, const char* enc, + int exec_input, int preserve_crlf) +{ + struct tok_state *tok = _PyTokenizer_tok_new(); + if (tok == NULL) + return NULL; + if ((tok->buf = (char *)PyMem_Malloc(BUFSIZ)) == NULL) { + _PyTokenizer_Free(tok); + return NULL; + } + tok->cur = tok->inp = tok->buf; + tok->end = tok->buf + BUFSIZ; + tok->fp = NULL; + if (enc != NULL) { + tok->encoding = _PyTokenizer_new_string(enc, strlen(enc), tok); + if (!tok->encoding) { + _PyTokenizer_Free(tok); + return NULL; + } + } + tok->decoding_state = STATE_NORMAL; + tok->underflow = &tok_underflow_readline; + Py_INCREF(readline); + tok->readline = readline; + return tok; +} diff --git a/Parser/tokenizer/string_tokenizer.c b/Parser/tokenizer/string_tokenizer.c new file mode 100644 index 00000000000000..0c26d5df8d4a40 --- /dev/null +++ b/Parser/tokenizer/string_tokenizer.c @@ -0,0 +1,129 @@ +#include "Python.h" +#include "errcode.h" + +#include "helpers.h" +#include "../lexer/state.h" + +static int +tok_underflow_string(struct tok_state *tok) { + char *end = strchr(tok->inp, '\n'); + if (end != NULL) { + end++; + } + else { + end = strchr(tok->inp, '\0'); + if (end == tok->inp) { + tok->done = E_EOF; + return 0; + } + } + if (tok->start == NULL) { + tok->buf = tok->cur; + } + tok->line_start = tok->cur; + ADVANCE_LINENO(); + tok->inp = end; + return 1; +} + +/* Fetch a byte from TOK, using the string buffer. */ +static int +buf_getc(struct tok_state *tok) { + return Py_CHARMASK(*tok->str++); +} + +/* Unfetch a byte from TOK, using the string buffer. */ +static void +buf_ungetc(int c, struct tok_state *tok) { + tok->str--; + assert(Py_CHARMASK(*tok->str) == c); /* tok->cur may point to read-only segment */ +} + +/* Set the readline function for TOK to ENC. For the string-based + tokenizer, this means to just record the encoding. */ +static int +buf_setreadl(struct tok_state *tok, const char* enc) { + tok->enc = enc; + return 1; +} + +/* Decode a byte string STR for use as the buffer of TOK. + Look for encoding declarations inside STR, and record them + inside TOK. */ +static char * +decode_str(const char *input, int single, struct tok_state *tok, int preserve_crlf) +{ + PyObject* utf8 = NULL; + char *str; + const char *s; + const char *newl[2] = {NULL, NULL}; + int lineno = 0; + tok->input = str = _PyTokenizer_translate_newlines(input, single, preserve_crlf, tok); + if (str == NULL) + return NULL; + tok->enc = NULL; + tok->str = str; + if (!_PyTokenizer_check_bom(buf_getc, buf_ungetc, buf_setreadl, tok)) + return _PyTokenizer_error_ret(tok); + str = tok->str; /* string after BOM if any */ + assert(str); + if (tok->enc != NULL) { + utf8 = _PyTokenizer_translate_into_utf8(str, tok->enc); + if (utf8 == NULL) + return _PyTokenizer_error_ret(tok); + str = PyBytes_AsString(utf8); + } + for (s = str;; s++) { + if (*s == '\0') break; + else if (*s == '\n') { + assert(lineno < 2); + newl[lineno] = s; + lineno++; + if (lineno == 2) break; + } + } + tok->enc = NULL; + /* need to check line 1 and 2 separately since check_coding_spec + assumes a single line as input */ + if (newl[0]) { + if (!_PyTokenizer_check_coding_spec(str, newl[0] - str, tok, buf_setreadl)) { + return NULL; + } + if (tok->enc == NULL && tok->decoding_state != STATE_NORMAL && newl[1]) { + if (!_PyTokenizer_check_coding_spec(newl[0]+1, newl[1] - newl[0], + tok, buf_setreadl)) + return NULL; + } + } + if (tok->enc != NULL) { + assert(utf8 == NULL); + utf8 = _PyTokenizer_translate_into_utf8(str, tok->enc); + if (utf8 == NULL) + return _PyTokenizer_error_ret(tok); + str = PyBytes_AS_STRING(utf8); + } + assert(tok->decoding_buffer == NULL); + tok->decoding_buffer = utf8; /* CAUTION */ + return str; +} + +/* Set up tokenizer for string */ +struct tok_state * +_PyTokenizer_FromString(const char *str, int exec_input, int preserve_crlf) +{ + struct tok_state *tok = _PyTokenizer_tok_new(); + char *decoded; + + if (tok == NULL) + return NULL; + decoded = decode_str(str, exec_input, tok, preserve_crlf); + if (decoded == NULL) { + _PyTokenizer_Free(tok); + return NULL; + } + + tok->buf = tok->cur = tok->inp = decoded; + tok->end = decoded; + tok->underflow = &tok_underflow_string; + return tok; +} diff --git a/Parser/tokenizer/tokenizer.h b/Parser/tokenizer/tokenizer.h new file mode 100644 index 00000000000000..8fbeb2d6ae6df1 --- /dev/null +++ b/Parser/tokenizer/tokenizer.h @@ -0,0 +1,14 @@ +#ifndef Py_TOKENIZER_H +#define Py_TOKENIZER_H + +#include "Python.h" + +struct tok_state *_PyTokenizer_FromString(const char *, int, int); +struct tok_state *_PyTokenizer_FromUTF8(const char *, int, int); +struct tok_state *_PyTokenizer_FromReadline(PyObject*, const char*, int, int); +struct tok_state *_PyTokenizer_FromFile(FILE *, const char*, + const char *, const char *); + +#define tok_dump _Py_tok_dump + +#endif /* !Py_TOKENIZER_H */ diff --git a/Parser/tokenizer/utf8_tokenizer.c b/Parser/tokenizer/utf8_tokenizer.c new file mode 100644 index 00000000000000..1a925f445400fa --- /dev/null +++ b/Parser/tokenizer/utf8_tokenizer.c @@ -0,0 +1,55 @@ +#include "Python.h" +#include "errcode.h" + +#include "helpers.h" +#include "../lexer/state.h" + +static int +tok_underflow_string(struct tok_state *tok) { + char *end = strchr(tok->inp, '\n'); + if (end != NULL) { + end++; + } + else { + end = strchr(tok->inp, '\0'); + if (end == tok->inp) { + tok->done = E_EOF; + return 0; + } + } + if (tok->start == NULL) { + tok->buf = tok->cur; + } + tok->line_start = tok->cur; + ADVANCE_LINENO(); + tok->inp = end; + return 1; +} + +/* Set up tokenizer for UTF-8 string */ +struct tok_state * +_PyTokenizer_FromUTF8(const char *str, int exec_input, int preserve_crlf) +{ + struct tok_state *tok = _PyTokenizer_tok_new(); + char *translated; + if (tok == NULL) + return NULL; + tok->input = translated = _PyTokenizer_translate_newlines(str, exec_input, preserve_crlf, tok); + if (translated == NULL) { + _PyTokenizer_Free(tok); + return NULL; + } + tok->decoding_state = STATE_NORMAL; + tok->enc = NULL; + tok->str = translated; + tok->encoding = _PyTokenizer_new_string("utf-8", 5, tok); + if (!tok->encoding) { + _PyTokenizer_Free(tok); + return NULL; + } + + tok->buf = tok->cur = tok->inp = translated; + tok->end = translated; + tok->underflow = &tok_underflow_string; + return tok; +} diff --git a/Programs/_bootstrap_python.c b/Programs/_bootstrap_python.c index 6c388fc7033dd0..34f79191b4e8d7 100644 --- a/Programs/_bootstrap_python.c +++ b/Programs/_bootstrap_python.c @@ -15,8 +15,6 @@ #include "Python/frozen_modules/zipimport.h" /* End includes */ -uint32_t _Py_next_func_version = 1; - /* Empty initializer for deepfrozen modules */ int _Py_Deepfreeze_Init(void) { diff --git a/Programs/_freeze_module.c b/Programs/_freeze_module.c index e55f1d56745c4d..3de6c6816c1e61 100644 --- a/Programs/_freeze_module.c +++ b/Programs/_freeze_module.c @@ -19,11 +19,9 @@ #include #include #ifndef MS_WINDOWS -#include +# include #endif -uint32_t _Py_next_func_version = 1; - /* Empty initializer for deepfrozen modules */ int _Py_Deepfreeze_Init(void) { diff --git a/Programs/_testembed.c b/Programs/_testembed.c index 351cdc302e8cb0..30998bf80f9ce4 100644 --- a/Programs/_testembed.c +++ b/Programs/_testembed.c @@ -237,6 +237,11 @@ static void check_stdio_details(const wchar_t *encoding, const wchar_t *errors) if (errors) { config_set_string(&config, &config.stdio_errors, errors); } +#ifdef MS_WINDOWS + // gh-106659: On Windows, don't use _io._WindowsConsoleIO which always + // announce UTF-8 for sys.stdin.encoding. + config.legacy_windows_stdio = 1; +#endif config_set_program_name(&config); init_from_config_clear(&config); @@ -571,7 +576,11 @@ static int test_init_from_config(void) _PyPreConfig_InitCompatConfig(&preconfig); putenv("PYTHONMALLOC=malloc_debug"); +#ifndef Py_GIL_DISABLED preconfig.allocator = PYMEM_ALLOCATOR_MALLOC; +#else + preconfig.allocator = PYMEM_ALLOCATOR_MIMALLOC; +#endif putenv("PYTHONUTF8=0"); Py_UTF8Mode = 0; @@ -703,9 +712,14 @@ static int test_init_from_config(void) config.pathconfig_warnings = 0; config.safe_path = 1; +#ifdef Py_STATS + putenv("PYTHONSTATS="); + config._pystats = 1; +#endif putenv("PYTHONINTMAXSTRDIGITS=6666"); config.int_max_str_digits = 31337; + config.cpu_count = 4321; init_from_config_clear(&config); @@ -755,7 +769,11 @@ static int test_init_dont_parse_argv(void) static void set_most_env_vars(void) { putenv("PYTHONHASHSEED=42"); +#ifndef Py_GIL_DISABLED putenv("PYTHONMALLOC=malloc"); +#else + putenv("PYTHONMALLOC=mimalloc"); +#endif putenv("PYTHONTRACEMALLOC=2"); putenv("PYTHONPROFILEIMPORTTIME=1"); putenv("PYTHONNODEBUGRANGES=1"); @@ -773,6 +791,9 @@ static void set_most_env_vars(void) putenv("PYTHONPLATLIBDIR=env_platlibdir"); putenv("PYTHONSAFEPATH=1"); putenv("PYTHONINTMAXSTRDIGITS=4567"); +#ifdef Py_STATS + putenv("PYTHONSTATS=1"); +#endif } @@ -838,7 +859,11 @@ static int test_init_env_dev_mode_alloc(void) /* Test initialization from environment variables */ Py_IgnoreEnvironmentFlag = 0; set_all_env_vars_dev_mode(); +#ifndef Py_GIL_DISABLED putenv("PYTHONMALLOC=malloc"); +#else + putenv("PYTHONMALLOC=mimalloc"); +#endif _testembed_Py_InitializeFromConfig(); dump_config(); Py_Finalize(); @@ -1266,11 +1291,16 @@ static int _test_audit(Py_ssize_t setValue) printf("Set event failed"); return 4; } + if (PyErr_Occurred()) { + printf("Exception raised"); + return 5; + } if (sawSet != 42) { printf("Failed to see *userData change\n"); - return 5; + return 6; } + return 0; } @@ -1284,6 +1314,57 @@ static int test_audit(void) return result; } +static int test_audit_tuple(void) +{ +#define ASSERT(TEST, EXITCODE) \ + if (!(TEST)) { \ + printf("ERROR test failed at %s:%i\n", __FILE__, __LINE__); \ + return (EXITCODE); \ + } + + Py_ssize_t sawSet = 0; + + // we need at least one hook, otherwise code checking for + // PySys_AuditTuple() is skipped. + PySys_AddAuditHook(_audit_hook, &sawSet); + _testembed_Py_InitializeFromConfig(); + + ASSERT(!PyErr_Occurred(), 0); + + // pass Python tuple object + PyObject *tuple = Py_BuildValue("(i)", 444); + if (tuple == NULL) { + goto error; + } + ASSERT(PySys_AuditTuple("_testembed.set", tuple) == 0, 10); + ASSERT(!PyErr_Occurred(), 11); + ASSERT(sawSet == 444, 12); + Py_DECREF(tuple); + + // pass Python int object + PyObject *int_arg = PyLong_FromLong(555); + if (int_arg == NULL) { + goto error; + } + ASSERT(PySys_AuditTuple("_testembed.set", int_arg) == -1, 20); + ASSERT(PyErr_ExceptionMatches(PyExc_TypeError), 21); + PyErr_Clear(); + Py_DECREF(int_arg); + + // NULL is accepted and means "no arguments" + ASSERT(PySys_AuditTuple("_testembed.test_audit_tuple", NULL) == 0, 30); + ASSERT(!PyErr_Occurred(), 31); + + Py_Finalize(); + return 0; + +error: + PyErr_Print(); + return 1; + +#undef ASSERT +} + static volatile int _audit_subinterpreter_interpreter_count = 0; static int _audit_subinterpreter_hook(const char *event, PyObject *args, void *userdata) @@ -2128,6 +2209,7 @@ static struct TestCase TestCases[] = { // Audit {"test_open_code_hook", test_open_code_hook}, {"test_audit", test_audit}, + {"test_audit_tuple", test_audit_tuple}, {"test_audit_subinterpreter", test_audit_subinterpreter}, {"test_audit_run_command", test_audit_run_command}, {"test_audit_run_file", test_audit_run_file}, diff --git a/Programs/test_frozenmain.h b/Programs/test_frozenmain.h index 9058327e846dc3..4fb78cf632d70e 100644 --- a/Programs/test_frozenmain.h +++ b/Programs/test_frozenmain.h @@ -1,17 +1,17 @@ // Auto-generated by Programs/freeze_test_frozenmain.py unsigned char M_test_frozenmain[] = { 227,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0, - 0,0,0,0,0,243,164,0,0,0,151,0,100,0,100,1, - 108,0,90,0,100,0,100,1,108,1,90,1,2,0,101,2, - 100,2,171,1,0,0,0,0,0,0,1,0,2,0,101,2, - 100,3,101,0,106,6,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,171,2,0,0,0,0,0,0, - 1,0,2,0,101,1,106,8,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,171,0,0,0,0,0, - 0,0,100,4,25,0,0,0,90,5,100,5,68,0,93,20, - 0,0,90,6,2,0,101,2,100,6,101,6,40,0,100,7, - 101,5,101,6,25,0,0,0,40,0,157,4,171,1,0,0, - 0,0,0,0,1,0,140,22,0,0,4,0,121,1,41,8, + 0,0,0,0,0,243,164,0,0,0,149,0,83,0,83,1, + 75,0,114,0,83,0,83,1,75,1,114,1,92,2,34,0, + 83,2,53,1,0,0,0,0,0,0,32,0,92,2,34,0, + 83,3,92,0,82,6,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,53,2,0,0,0,0,0,0, + 32,0,92,1,82,8,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,34,0,53,0,0,0,0,0, + 0,0,83,4,5,0,0,0,114,5,83,5,19,0,72,20, + 0,0,114,6,92,2,34,0,83,6,92,6,14,0,83,7, + 92,5,92,6,5,0,0,0,14,0,51,4,53,1,0,0, + 0,0,0,0,32,0,77,22,0,0,11,0,103,1,41,8, 233,0,0,0,0,78,122,18,70,114,111,122,101,110,32,72, 101,108,108,111,32,87,111,114,108,100,122,8,115,121,115,46, 97,114,103,118,218,6,99,111,110,102,105,103,41,5,218,12, @@ -27,12 +27,12 @@ unsigned char M_test_frozenmain[] = { 0,0,218,3,107,101,121,169,0,243,0,0,0,0,250,18, 116,101,115,116,95,102,114,111,122,101,110,109,97,105,110,46, 112,121,250,8,60,109,111,100,117,108,101,62,114,18,0,0, - 0,1,0,0,0,115,102,0,0,0,240,3,1,1,1,243, + 0,1,0,0,0,115,99,0,0,0,240,3,1,1,1,243, 8,0,1,11,219,0,24,225,0,5,208,6,26,212,0,27, 217,0,5,128,106,144,35,151,40,145,40,212,0,27,216,9, - 38,208,9,26,215,9,38,209,9,38,211,9,40,168,24,209, - 9,50,128,6,240,2,6,12,2,242,0,7,1,42,128,67, - 241,14,0,5,10,136,71,144,67,144,53,152,2,152,54,160, - 35,153,59,152,45,208,10,40,214,4,41,241,15,7,1,42, - 114,16,0,0,0, + 26,215,9,38,210,9,38,211,9,40,168,24,209,9,50,128, + 6,240,2,6,12,2,242,0,7,1,42,128,67,241,14,0, + 5,10,136,71,144,67,144,53,152,2,152,54,160,35,153,59, + 152,45,208,10,40,214,4,41,241,15,7,1,42,114,16,0, + 0,0, }; diff --git a/Python/Python-ast.c b/Python/Python-ast.c index 8047b1259c5d86..699e1c157c591c 100644 --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -4,10 +4,16 @@ #include "pycore_ast.h" #include "pycore_ast_state.h" // struct ast_state #include "pycore_ceval.h" // _Py_EnterRecursiveCall +#include "pycore_lock.h" // _PyOnceFlag #include "pycore_interp.h" // _PyInterpreterState.ast #include "pycore_pystate.h" // _PyInterpreterState_GET() #include +struct validator { + int recursion_depth; /* current recursion depth */ + int recursion_limit; /* recursion limit */ +}; + // Forward declaration static int init_types(struct ast_state *state); @@ -16,7 +22,8 @@ get_ast_state(void) { PyInterpreterState *interp = _PyInterpreterState_GET(); struct ast_state *state = &interp->ast; - if (!init_types(state)) { + assert(!state->finalized); + if (_PyOnceFlag_CallOnce(&state->once, (_Py_once_fn_t *)&init_types, state) < 0) { return NULL; } return state; @@ -271,102 +278,99 @@ void _PyAST_Fini(PyInterpreterState *interp) Py_CLEAR(_Py_INTERP_CACHED_OBJECT(interp, str_replace_inf)); -#if !defined(NDEBUG) - state->initialized = -1; -#else - state->initialized = 0; -#endif + state->finalized = 1; + state->once = (_PyOnceFlag){0}; } static int init_identifiers(struct ast_state *state) { - if ((state->__dict__ = PyUnicode_InternFromString("__dict__")) == NULL) return 0; - if ((state->__doc__ = PyUnicode_InternFromString("__doc__")) == NULL) return 0; - if ((state->__match_args__ = PyUnicode_InternFromString("__match_args__")) == NULL) return 0; - if ((state->__module__ = PyUnicode_InternFromString("__module__")) == NULL) return 0; - if ((state->_attributes = PyUnicode_InternFromString("_attributes")) == NULL) return 0; - if ((state->_fields = PyUnicode_InternFromString("_fields")) == NULL) return 0; - if ((state->annotation = PyUnicode_InternFromString("annotation")) == NULL) return 0; - if ((state->arg = PyUnicode_InternFromString("arg")) == NULL) return 0; - if ((state->args = PyUnicode_InternFromString("args")) == NULL) return 0; - if ((state->argtypes = PyUnicode_InternFromString("argtypes")) == NULL) return 0; - if ((state->asname = PyUnicode_InternFromString("asname")) == NULL) return 0; - if ((state->ast = PyUnicode_InternFromString("ast")) == NULL) return 0; - if ((state->attr = PyUnicode_InternFromString("attr")) == NULL) return 0; - if ((state->bases = PyUnicode_InternFromString("bases")) == NULL) return 0; - if ((state->body = PyUnicode_InternFromString("body")) == NULL) return 0; - if ((state->bound = PyUnicode_InternFromString("bound")) == NULL) return 0; - if ((state->cases = PyUnicode_InternFromString("cases")) == NULL) return 0; - if ((state->cause = PyUnicode_InternFromString("cause")) == NULL) return 0; - if ((state->cls = PyUnicode_InternFromString("cls")) == NULL) return 0; - if ((state->col_offset = PyUnicode_InternFromString("col_offset")) == NULL) return 0; - if ((state->comparators = PyUnicode_InternFromString("comparators")) == NULL) return 0; - if ((state->context_expr = PyUnicode_InternFromString("context_expr")) == NULL) return 0; - if ((state->conversion = PyUnicode_InternFromString("conversion")) == NULL) return 0; - if ((state->ctx = PyUnicode_InternFromString("ctx")) == NULL) return 0; - if ((state->decorator_list = PyUnicode_InternFromString("decorator_list")) == NULL) return 0; - if ((state->defaults = PyUnicode_InternFromString("defaults")) == NULL) return 0; - if ((state->elt = PyUnicode_InternFromString("elt")) == NULL) return 0; - if ((state->elts = PyUnicode_InternFromString("elts")) == NULL) return 0; - if ((state->end_col_offset = PyUnicode_InternFromString("end_col_offset")) == NULL) return 0; - if ((state->end_lineno = PyUnicode_InternFromString("end_lineno")) == NULL) return 0; - if ((state->exc = PyUnicode_InternFromString("exc")) == NULL) return 0; - if ((state->finalbody = PyUnicode_InternFromString("finalbody")) == NULL) return 0; - if ((state->format_spec = PyUnicode_InternFromString("format_spec")) == NULL) return 0; - if ((state->func = PyUnicode_InternFromString("func")) == NULL) return 0; - if ((state->generators = PyUnicode_InternFromString("generators")) == NULL) return 0; - if ((state->guard = PyUnicode_InternFromString("guard")) == NULL) return 0; - if ((state->handlers = PyUnicode_InternFromString("handlers")) == NULL) return 0; - if ((state->id = PyUnicode_InternFromString("id")) == NULL) return 0; - if ((state->ifs = PyUnicode_InternFromString("ifs")) == NULL) return 0; - if ((state->is_async = PyUnicode_InternFromString("is_async")) == NULL) return 0; - if ((state->items = PyUnicode_InternFromString("items")) == NULL) return 0; - if ((state->iter = PyUnicode_InternFromString("iter")) == NULL) return 0; - if ((state->key = PyUnicode_InternFromString("key")) == NULL) return 0; - if ((state->keys = PyUnicode_InternFromString("keys")) == NULL) return 0; - if ((state->keywords = PyUnicode_InternFromString("keywords")) == NULL) return 0; - if ((state->kind = PyUnicode_InternFromString("kind")) == NULL) return 0; - if ((state->kw_defaults = PyUnicode_InternFromString("kw_defaults")) == NULL) return 0; - if ((state->kwarg = PyUnicode_InternFromString("kwarg")) == NULL) return 0; - if ((state->kwd_attrs = PyUnicode_InternFromString("kwd_attrs")) == NULL) return 0; - if ((state->kwd_patterns = PyUnicode_InternFromString("kwd_patterns")) == NULL) return 0; - if ((state->kwonlyargs = PyUnicode_InternFromString("kwonlyargs")) == NULL) return 0; - if ((state->left = PyUnicode_InternFromString("left")) == NULL) return 0; - if ((state->level = PyUnicode_InternFromString("level")) == NULL) return 0; - if ((state->lineno = PyUnicode_InternFromString("lineno")) == NULL) return 0; - if ((state->lower = PyUnicode_InternFromString("lower")) == NULL) return 0; - if ((state->module = PyUnicode_InternFromString("module")) == NULL) return 0; - if ((state->msg = PyUnicode_InternFromString("msg")) == NULL) return 0; - if ((state->name = PyUnicode_InternFromString("name")) == NULL) return 0; - if ((state->names = PyUnicode_InternFromString("names")) == NULL) return 0; - if ((state->op = PyUnicode_InternFromString("op")) == NULL) return 0; - if ((state->operand = PyUnicode_InternFromString("operand")) == NULL) return 0; - if ((state->ops = PyUnicode_InternFromString("ops")) == NULL) return 0; - if ((state->optional_vars = PyUnicode_InternFromString("optional_vars")) == NULL) return 0; - if ((state->orelse = PyUnicode_InternFromString("orelse")) == NULL) return 0; - if ((state->pattern = PyUnicode_InternFromString("pattern")) == NULL) return 0; - if ((state->patterns = PyUnicode_InternFromString("patterns")) == NULL) return 0; - if ((state->posonlyargs = PyUnicode_InternFromString("posonlyargs")) == NULL) return 0; - if ((state->rest = PyUnicode_InternFromString("rest")) == NULL) return 0; - if ((state->returns = PyUnicode_InternFromString("returns")) == NULL) return 0; - if ((state->right = PyUnicode_InternFromString("right")) == NULL) return 0; - if ((state->simple = PyUnicode_InternFromString("simple")) == NULL) return 0; - if ((state->slice = PyUnicode_InternFromString("slice")) == NULL) return 0; - if ((state->step = PyUnicode_InternFromString("step")) == NULL) return 0; - if ((state->subject = PyUnicode_InternFromString("subject")) == NULL) return 0; - if ((state->tag = PyUnicode_InternFromString("tag")) == NULL) return 0; - if ((state->target = PyUnicode_InternFromString("target")) == NULL) return 0; - if ((state->targets = PyUnicode_InternFromString("targets")) == NULL) return 0; - if ((state->test = PyUnicode_InternFromString("test")) == NULL) return 0; - if ((state->type = PyUnicode_InternFromString("type")) == NULL) return 0; - if ((state->type_comment = PyUnicode_InternFromString("type_comment")) == NULL) return 0; - if ((state->type_ignores = PyUnicode_InternFromString("type_ignores")) == NULL) return 0; - if ((state->type_params = PyUnicode_InternFromString("type_params")) == NULL) return 0; - if ((state->upper = PyUnicode_InternFromString("upper")) == NULL) return 0; - if ((state->value = PyUnicode_InternFromString("value")) == NULL) return 0; - if ((state->values = PyUnicode_InternFromString("values")) == NULL) return 0; - if ((state->vararg = PyUnicode_InternFromString("vararg")) == NULL) return 0; - return 1; + if ((state->__dict__ = PyUnicode_InternFromString("__dict__")) == NULL) return -1; + if ((state->__doc__ = PyUnicode_InternFromString("__doc__")) == NULL) return -1; + if ((state->__match_args__ = PyUnicode_InternFromString("__match_args__")) == NULL) return -1; + if ((state->__module__ = PyUnicode_InternFromString("__module__")) == NULL) return -1; + if ((state->_attributes = PyUnicode_InternFromString("_attributes")) == NULL) return -1; + if ((state->_fields = PyUnicode_InternFromString("_fields")) == NULL) return -1; + if ((state->annotation = PyUnicode_InternFromString("annotation")) == NULL) return -1; + if ((state->arg = PyUnicode_InternFromString("arg")) == NULL) return -1; + if ((state->args = PyUnicode_InternFromString("args")) == NULL) return -1; + if ((state->argtypes = PyUnicode_InternFromString("argtypes")) == NULL) return -1; + if ((state->asname = PyUnicode_InternFromString("asname")) == NULL) return -1; + if ((state->ast = PyUnicode_InternFromString("ast")) == NULL) return -1; + if ((state->attr = PyUnicode_InternFromString("attr")) == NULL) return -1; + if ((state->bases = PyUnicode_InternFromString("bases")) == NULL) return -1; + if ((state->body = PyUnicode_InternFromString("body")) == NULL) return -1; + if ((state->bound = PyUnicode_InternFromString("bound")) == NULL) return -1; + if ((state->cases = PyUnicode_InternFromString("cases")) == NULL) return -1; + if ((state->cause = PyUnicode_InternFromString("cause")) == NULL) return -1; + if ((state->cls = PyUnicode_InternFromString("cls")) == NULL) return -1; + if ((state->col_offset = PyUnicode_InternFromString("col_offset")) == NULL) return -1; + if ((state->comparators = PyUnicode_InternFromString("comparators")) == NULL) return -1; + if ((state->context_expr = PyUnicode_InternFromString("context_expr")) == NULL) return -1; + if ((state->conversion = PyUnicode_InternFromString("conversion")) == NULL) return -1; + if ((state->ctx = PyUnicode_InternFromString("ctx")) == NULL) return -1; + if ((state->decorator_list = PyUnicode_InternFromString("decorator_list")) == NULL) return -1; + if ((state->defaults = PyUnicode_InternFromString("defaults")) == NULL) return -1; + if ((state->elt = PyUnicode_InternFromString("elt")) == NULL) return -1; + if ((state->elts = PyUnicode_InternFromString("elts")) == NULL) return -1; + if ((state->end_col_offset = PyUnicode_InternFromString("end_col_offset")) == NULL) return -1; + if ((state->end_lineno = PyUnicode_InternFromString("end_lineno")) == NULL) return -1; + if ((state->exc = PyUnicode_InternFromString("exc")) == NULL) return -1; + if ((state->finalbody = PyUnicode_InternFromString("finalbody")) == NULL) return -1; + if ((state->format_spec = PyUnicode_InternFromString("format_spec")) == NULL) return -1; + if ((state->func = PyUnicode_InternFromString("func")) == NULL) return -1; + if ((state->generators = PyUnicode_InternFromString("generators")) == NULL) return -1; + if ((state->guard = PyUnicode_InternFromString("guard")) == NULL) return -1; + if ((state->handlers = PyUnicode_InternFromString("handlers")) == NULL) return -1; + if ((state->id = PyUnicode_InternFromString("id")) == NULL) return -1; + if ((state->ifs = PyUnicode_InternFromString("ifs")) == NULL) return -1; + if ((state->is_async = PyUnicode_InternFromString("is_async")) == NULL) return -1; + if ((state->items = PyUnicode_InternFromString("items")) == NULL) return -1; + if ((state->iter = PyUnicode_InternFromString("iter")) == NULL) return -1; + if ((state->key = PyUnicode_InternFromString("key")) == NULL) return -1; + if ((state->keys = PyUnicode_InternFromString("keys")) == NULL) return -1; + if ((state->keywords = PyUnicode_InternFromString("keywords")) == NULL) return -1; + if ((state->kind = PyUnicode_InternFromString("kind")) == NULL) return -1; + if ((state->kw_defaults = PyUnicode_InternFromString("kw_defaults")) == NULL) return -1; + if ((state->kwarg = PyUnicode_InternFromString("kwarg")) == NULL) return -1; + if ((state->kwd_attrs = PyUnicode_InternFromString("kwd_attrs")) == NULL) return -1; + if ((state->kwd_patterns = PyUnicode_InternFromString("kwd_patterns")) == NULL) return -1; + if ((state->kwonlyargs = PyUnicode_InternFromString("kwonlyargs")) == NULL) return -1; + if ((state->left = PyUnicode_InternFromString("left")) == NULL) return -1; + if ((state->level = PyUnicode_InternFromString("level")) == NULL) return -1; + if ((state->lineno = PyUnicode_InternFromString("lineno")) == NULL) return -1; + if ((state->lower = PyUnicode_InternFromString("lower")) == NULL) return -1; + if ((state->module = PyUnicode_InternFromString("module")) == NULL) return -1; + if ((state->msg = PyUnicode_InternFromString("msg")) == NULL) return -1; + if ((state->name = PyUnicode_InternFromString("name")) == NULL) return -1; + if ((state->names = PyUnicode_InternFromString("names")) == NULL) return -1; + if ((state->op = PyUnicode_InternFromString("op")) == NULL) return -1; + if ((state->operand = PyUnicode_InternFromString("operand")) == NULL) return -1; + if ((state->ops = PyUnicode_InternFromString("ops")) == NULL) return -1; + if ((state->optional_vars = PyUnicode_InternFromString("optional_vars")) == NULL) return -1; + if ((state->orelse = PyUnicode_InternFromString("orelse")) == NULL) return -1; + if ((state->pattern = PyUnicode_InternFromString("pattern")) == NULL) return -1; + if ((state->patterns = PyUnicode_InternFromString("patterns")) == NULL) return -1; + if ((state->posonlyargs = PyUnicode_InternFromString("posonlyargs")) == NULL) return -1; + if ((state->rest = PyUnicode_InternFromString("rest")) == NULL) return -1; + if ((state->returns = PyUnicode_InternFromString("returns")) == NULL) return -1; + if ((state->right = PyUnicode_InternFromString("right")) == NULL) return -1; + if ((state->simple = PyUnicode_InternFromString("simple")) == NULL) return -1; + if ((state->slice = PyUnicode_InternFromString("slice")) == NULL) return -1; + if ((state->step = PyUnicode_InternFromString("step")) == NULL) return -1; + if ((state->subject = PyUnicode_InternFromString("subject")) == NULL) return -1; + if ((state->tag = PyUnicode_InternFromString("tag")) == NULL) return -1; + if ((state->target = PyUnicode_InternFromString("target")) == NULL) return -1; + if ((state->targets = PyUnicode_InternFromString("targets")) == NULL) return -1; + if ((state->test = PyUnicode_InternFromString("test")) == NULL) return -1; + if ((state->type = PyUnicode_InternFromString("type")) == NULL) return -1; + if ((state->type_comment = PyUnicode_InternFromString("type_comment")) == NULL) return -1; + if ((state->type_ignores = PyUnicode_InternFromString("type_ignores")) == NULL) return -1; + if ((state->type_params = PyUnicode_InternFromString("type_params")) == NULL) return -1; + if ((state->upper = PyUnicode_InternFromString("upper")) == NULL) return -1; + if ((state->value = PyUnicode_InternFromString("value")) == NULL) return -1; + if ((state->values = PyUnicode_InternFromString("values")) == NULL) return -1; + if ((state->vararg = PyUnicode_InternFromString("vararg")) == NULL) return -1; + return 0; }; GENERATE_ASDL_SEQ_CONSTRUCTOR(mod, mod_ty) @@ -384,7 +388,8 @@ GENERATE_ASDL_SEQ_CONSTRUCTOR(pattern, pattern_ty) GENERATE_ASDL_SEQ_CONSTRUCTOR(type_ignore, type_ignore_ty) GENERATE_ASDL_SEQ_CONSTRUCTOR(type_param, type_param_ty) -static PyObject* ast2obj_mod(struct ast_state *state, void*); +static PyObject* ast2obj_mod(struct ast_state *state, struct validator *vstate, + void*); static const char * const Module_fields[]={ "body", "type_ignores", @@ -405,7 +410,8 @@ static const char * const stmt_attributes[] = { "end_lineno", "end_col_offset", }; -static PyObject* ast2obj_stmt(struct ast_state *state, void*); +static PyObject* ast2obj_stmt(struct ast_state *state, struct validator + *vstate, void*); static const char * const FunctionDef_fields[]={ "name", "args", @@ -540,7 +546,8 @@ static const char * const expr_attributes[] = { "end_lineno", "end_col_offset", }; -static PyObject* ast2obj_expr(struct ast_state *state, void*); +static PyObject* ast2obj_expr(struct ast_state *state, struct validator + *vstate, void*); static const char * const BoolOp_fields[]={ "op", "values", @@ -653,12 +660,18 @@ static const char * const Slice_fields[]={ "upper", "step", }; -static PyObject* ast2obj_expr_context(struct ast_state *state, expr_context_ty); -static PyObject* ast2obj_boolop(struct ast_state *state, boolop_ty); -static PyObject* ast2obj_operator(struct ast_state *state, operator_ty); -static PyObject* ast2obj_unaryop(struct ast_state *state, unaryop_ty); -static PyObject* ast2obj_cmpop(struct ast_state *state, cmpop_ty); -static PyObject* ast2obj_comprehension(struct ast_state *state, void*); +static PyObject* ast2obj_expr_context(struct ast_state *state, struct validator + *vstate, expr_context_ty); +static PyObject* ast2obj_boolop(struct ast_state *state, struct validator + *vstate, boolop_ty); +static PyObject* ast2obj_operator(struct ast_state *state, struct validator + *vstate, operator_ty); +static PyObject* ast2obj_unaryop(struct ast_state *state, struct validator + *vstate, unaryop_ty); +static PyObject* ast2obj_cmpop(struct ast_state *state, struct validator + *vstate, cmpop_ty); +static PyObject* ast2obj_comprehension(struct ast_state *state, struct + validator *vstate, void*); static const char * const comprehension_fields[]={ "target", "iter", @@ -671,13 +684,15 @@ static const char * const excepthandler_attributes[] = { "end_lineno", "end_col_offset", }; -static PyObject* ast2obj_excepthandler(struct ast_state *state, void*); +static PyObject* ast2obj_excepthandler(struct ast_state *state, struct + validator *vstate, void*); static const char * const ExceptHandler_fields[]={ "type", "name", "body", }; -static PyObject* ast2obj_arguments(struct ast_state *state, void*); +static PyObject* ast2obj_arguments(struct ast_state *state, struct validator + *vstate, void*); static const char * const arguments_fields[]={ "posonlyargs", "args", @@ -687,7 +702,8 @@ static const char * const arguments_fields[]={ "kwarg", "defaults", }; -static PyObject* ast2obj_arg(struct ast_state *state, void*); +static PyObject* ast2obj_arg(struct ast_state *state, struct validator *vstate, + void*); static const char * const arg_attributes[] = { "lineno", "col_offset", @@ -699,7 +715,8 @@ static const char * const arg_fields[]={ "annotation", "type_comment", }; -static PyObject* ast2obj_keyword(struct ast_state *state, void*); +static PyObject* ast2obj_keyword(struct ast_state *state, struct validator + *vstate, void*); static const char * const keyword_attributes[] = { "lineno", "col_offset", @@ -710,7 +727,8 @@ static const char * const keyword_fields[]={ "arg", "value", }; -static PyObject* ast2obj_alias(struct ast_state *state, void*); +static PyObject* ast2obj_alias(struct ast_state *state, struct validator + *vstate, void*); static const char * const alias_attributes[] = { "lineno", "col_offset", @@ -721,12 +739,14 @@ static const char * const alias_fields[]={ "name", "asname", }; -static PyObject* ast2obj_withitem(struct ast_state *state, void*); +static PyObject* ast2obj_withitem(struct ast_state *state, struct validator + *vstate, void*); static const char * const withitem_fields[]={ "context_expr", "optional_vars", }; -static PyObject* ast2obj_match_case(struct ast_state *state, void*); +static PyObject* ast2obj_match_case(struct ast_state *state, struct validator + *vstate, void*); static const char * const match_case_fields[]={ "pattern", "guard", @@ -738,7 +758,8 @@ static const char * const pattern_attributes[] = { "end_lineno", "end_col_offset", }; -static PyObject* ast2obj_pattern(struct ast_state *state, void*); +static PyObject* ast2obj_pattern(struct ast_state *state, struct validator + *vstate, void*); static const char * const MatchValue_fields[]={ "value", }; @@ -769,7 +790,8 @@ static const char * const MatchAs_fields[]={ static const char * const MatchOr_fields[]={ "patterns", }; -static PyObject* ast2obj_type_ignore(struct ast_state *state, void*); +static PyObject* ast2obj_type_ignore(struct ast_state *state, struct validator + *vstate, void*); static const char * const TypeIgnore_fields[]={ "lineno", "tag", @@ -780,7 +802,8 @@ static const char * const type_param_attributes[] = { "end_lineno", "end_col_offset", }; -static PyObject* ast2obj_type_param(struct ast_state *state, void*); +static PyObject* ast2obj_type_param(struct ast_state *state, struct validator + *vstate, void*); static const char * const TypeVar_fields[]={ "name", "bound", @@ -993,23 +1016,24 @@ add_attributes(struct ast_state *state, PyObject *type, const char * const *attr int i, result; PyObject *s, *l = PyTuple_New(num_fields); if (!l) - return 0; + return -1; for (i = 0; i < num_fields; i++) { s = PyUnicode_InternFromString(attrs[i]); if (!s) { Py_DECREF(l); - return 0; + return -1; } PyTuple_SET_ITEM(l, i, s); } - result = PyObject_SetAttr(type, state->_attributes, l) >= 0; + result = PyObject_SetAttr(type, state->_attributes, l); Py_DECREF(l); return result; } /* Conversion AST -> Python */ -static PyObject* ast2obj_list(struct ast_state *state, asdl_seq *seq, PyObject* (*func)(struct ast_state *state, void*)) +static PyObject* ast2obj_list(struct ast_state *state, struct validator *vstate, asdl_seq *seq, + PyObject* (*func)(struct ast_state *state, struct validator *vstate, void*)) { Py_ssize_t i, n = asdl_seq_LEN(seq); PyObject *result = PyList_New(n); @@ -1017,7 +1041,7 @@ static PyObject* ast2obj_list(struct ast_state *state, asdl_seq *seq, PyObject* if (!result) return NULL; for (i = 0; i < n; i++) { - value = func(state, asdl_seq_GET_UNTYPED(seq, i)); + value = func(state, vstate, asdl_seq_GET_UNTYPED(seq, i)); if (!value) { Py_DECREF(result); return NULL; @@ -1027,7 +1051,7 @@ static PyObject* ast2obj_list(struct ast_state *state, asdl_seq *seq, PyObject* return result; } -static PyObject* ast2obj_object(struct ast_state *Py_UNUSED(state), void *o) +static PyObject* ast2obj_object(struct ast_state *Py_UNUSED(state), struct validator *Py_UNUSED(vstate), void *o) { PyObject *op = (PyObject*)o; if (!op) { @@ -1039,7 +1063,7 @@ static PyObject* ast2obj_object(struct ast_state *Py_UNUSED(state), void *o) #define ast2obj_identifier ast2obj_object #define ast2obj_string ast2obj_object -static PyObject* ast2obj_int(struct ast_state *Py_UNUSED(state), long b) +static PyObject* ast2obj_int(struct ast_state *Py_UNUSED(state), struct validator *Py_UNUSED(vstate), long b) { return PyLong_FromLong(b); } @@ -1077,7 +1101,7 @@ static int obj2ast_identifier(struct ast_state *state, PyObject* obj, PyObject** { if (!PyUnicode_CheckExact(obj) && obj != Py_None) { PyErr_SetString(PyExc_TypeError, "AST identifier must be of type str"); - return 1; + return -1; } return obj2ast_object(state, obj, out, arena); } @@ -1086,7 +1110,7 @@ static int obj2ast_string(struct ast_state *state, PyObject* obj, PyObject** out { if (!PyUnicode_CheckExact(obj) && !PyBytes_CheckExact(obj)) { PyErr_SetString(PyExc_TypeError, "AST string must be of type str"); - return 1; + return -1; } return obj2ast_object(state, obj, out, arena); } @@ -1096,12 +1120,12 @@ static int obj2ast_int(struct ast_state* Py_UNUSED(state), PyObject* obj, int* o int i; if (!PyLong_Check(obj)) { PyErr_Format(PyExc_ValueError, "invalid integer value: %R", obj); - return 1; + return -1; } - i = _PyLong_AsInt(obj); + i = PyLong_AsInt(obj); if (i == -1 && PyErr_Occurred()) - return 1; + return -1; *out = i; return 0; } @@ -1126,47 +1150,40 @@ static int add_ast_fields(struct ast_state *state) static int init_types(struct ast_state *state) { - // init_types() must not be called after _PyAST_Fini() - // has been called - assert(state->initialized >= 0); - - if (state->initialized) { - return 1; - } if (init_identifiers(state) < 0) { - return 0; + return -1; } state->AST_type = PyType_FromSpec(&AST_type_spec); if (!state->AST_type) { - return 0; + return -1; } if (add_ast_fields(state) < 0) { - return 0; + return -1; } state->mod_type = make_type(state, "mod", state->AST_type, NULL, 0, "mod = Module(stmt* body, type_ignore* type_ignores)\n" " | Interactive(stmt* body)\n" " | Expression(expr body)\n" " | FunctionType(expr* argtypes, expr returns)"); - if (!state->mod_type) return 0; - if (!add_attributes(state, state->mod_type, NULL, 0)) return 0; + if (!state->mod_type) return -1; + if (add_attributes(state, state->mod_type, NULL, 0) < 0) return -1; state->Module_type = make_type(state, "Module", state->mod_type, Module_fields, 2, "Module(stmt* body, type_ignore* type_ignores)"); - if (!state->Module_type) return 0; + if (!state->Module_type) return -1; state->Interactive_type = make_type(state, "Interactive", state->mod_type, Interactive_fields, 1, "Interactive(stmt* body)"); - if (!state->Interactive_type) return 0; + if (!state->Interactive_type) return -1; state->Expression_type = make_type(state, "Expression", state->mod_type, Expression_fields, 1, "Expression(expr body)"); - if (!state->Expression_type) return 0; + if (!state->Expression_type) return -1; state->FunctionType_type = make_type(state, "FunctionType", state->mod_type, FunctionType_fields, 2, "FunctionType(expr* argtypes, expr returns)"); - if (!state->FunctionType_type) return 0; + if (!state->FunctionType_type) return -1; state->stmt_type = make_type(state, "stmt", state->AST_type, NULL, 0, "stmt = FunctionDef(identifier name, arguments args, stmt* body, expr* decorator_list, expr? returns, string? type_comment, type_param* type_params)\n" " | AsyncFunctionDef(identifier name, arguments args, stmt* body, expr* decorator_list, expr? returns, string? type_comment, type_param* type_params)\n" @@ -1196,160 +1213,161 @@ init_types(struct ast_state *state) " | Pass\n" " | Break\n" " | Continue"); - if (!state->stmt_type) return 0; - if (!add_attributes(state, state->stmt_type, stmt_attributes, 4)) return 0; + if (!state->stmt_type) return -1; + if (add_attributes(state, state->stmt_type, stmt_attributes, 4) < 0) return + -1; if (PyObject_SetAttr(state->stmt_type, state->end_lineno, Py_None) == -1) - return 0; + return -1; if (PyObject_SetAttr(state->stmt_type, state->end_col_offset, Py_None) == -1) - return 0; + return -1; state->FunctionDef_type = make_type(state, "FunctionDef", state->stmt_type, FunctionDef_fields, 7, "FunctionDef(identifier name, arguments args, stmt* body, expr* decorator_list, expr? returns, string? type_comment, type_param* type_params)"); - if (!state->FunctionDef_type) return 0; + if (!state->FunctionDef_type) return -1; if (PyObject_SetAttr(state->FunctionDef_type, state->returns, Py_None) == -1) - return 0; + return -1; if (PyObject_SetAttr(state->FunctionDef_type, state->type_comment, Py_None) == -1) - return 0; + return -1; state->AsyncFunctionDef_type = make_type(state, "AsyncFunctionDef", state->stmt_type, AsyncFunctionDef_fields, 7, "AsyncFunctionDef(identifier name, arguments args, stmt* body, expr* decorator_list, expr? returns, string? type_comment, type_param* type_params)"); - if (!state->AsyncFunctionDef_type) return 0; + if (!state->AsyncFunctionDef_type) return -1; if (PyObject_SetAttr(state->AsyncFunctionDef_type, state->returns, Py_None) == -1) - return 0; + return -1; if (PyObject_SetAttr(state->AsyncFunctionDef_type, state->type_comment, Py_None) == -1) - return 0; + return -1; state->ClassDef_type = make_type(state, "ClassDef", state->stmt_type, ClassDef_fields, 6, "ClassDef(identifier name, expr* bases, keyword* keywords, stmt* body, expr* decorator_list, type_param* type_params)"); - if (!state->ClassDef_type) return 0; + if (!state->ClassDef_type) return -1; state->Return_type = make_type(state, "Return", state->stmt_type, Return_fields, 1, "Return(expr? value)"); - if (!state->Return_type) return 0; + if (!state->Return_type) return -1; if (PyObject_SetAttr(state->Return_type, state->value, Py_None) == -1) - return 0; + return -1; state->Delete_type = make_type(state, "Delete", state->stmt_type, Delete_fields, 1, "Delete(expr* targets)"); - if (!state->Delete_type) return 0; + if (!state->Delete_type) return -1; state->Assign_type = make_type(state, "Assign", state->stmt_type, Assign_fields, 3, "Assign(expr* targets, expr value, string? type_comment)"); - if (!state->Assign_type) return 0; + if (!state->Assign_type) return -1; if (PyObject_SetAttr(state->Assign_type, state->type_comment, Py_None) == -1) - return 0; + return -1; state->TypeAlias_type = make_type(state, "TypeAlias", state->stmt_type, TypeAlias_fields, 3, "TypeAlias(expr name, type_param* type_params, expr value)"); - if (!state->TypeAlias_type) return 0; + if (!state->TypeAlias_type) return -1; state->AugAssign_type = make_type(state, "AugAssign", state->stmt_type, AugAssign_fields, 3, "AugAssign(expr target, operator op, expr value)"); - if (!state->AugAssign_type) return 0; + if (!state->AugAssign_type) return -1; state->AnnAssign_type = make_type(state, "AnnAssign", state->stmt_type, AnnAssign_fields, 4, "AnnAssign(expr target, expr annotation, expr? value, int simple)"); - if (!state->AnnAssign_type) return 0; + if (!state->AnnAssign_type) return -1; if (PyObject_SetAttr(state->AnnAssign_type, state->value, Py_None) == -1) - return 0; + return -1; state->For_type = make_type(state, "For", state->stmt_type, For_fields, 5, "For(expr target, expr iter, stmt* body, stmt* orelse, string? type_comment)"); - if (!state->For_type) return 0; + if (!state->For_type) return -1; if (PyObject_SetAttr(state->For_type, state->type_comment, Py_None) == -1) - return 0; + return -1; state->AsyncFor_type = make_type(state, "AsyncFor", state->stmt_type, AsyncFor_fields, 5, "AsyncFor(expr target, expr iter, stmt* body, stmt* orelse, string? type_comment)"); - if (!state->AsyncFor_type) return 0; + if (!state->AsyncFor_type) return -1; if (PyObject_SetAttr(state->AsyncFor_type, state->type_comment, Py_None) == -1) - return 0; + return -1; state->While_type = make_type(state, "While", state->stmt_type, While_fields, 3, "While(expr test, stmt* body, stmt* orelse)"); - if (!state->While_type) return 0; + if (!state->While_type) return -1; state->If_type = make_type(state, "If", state->stmt_type, If_fields, 3, "If(expr test, stmt* body, stmt* orelse)"); - if (!state->If_type) return 0; + if (!state->If_type) return -1; state->With_type = make_type(state, "With", state->stmt_type, With_fields, 3, "With(withitem* items, stmt* body, string? type_comment)"); - if (!state->With_type) return 0; + if (!state->With_type) return -1; if (PyObject_SetAttr(state->With_type, state->type_comment, Py_None) == -1) - return 0; + return -1; state->AsyncWith_type = make_type(state, "AsyncWith", state->stmt_type, AsyncWith_fields, 3, "AsyncWith(withitem* items, stmt* body, string? type_comment)"); - if (!state->AsyncWith_type) return 0; + if (!state->AsyncWith_type) return -1; if (PyObject_SetAttr(state->AsyncWith_type, state->type_comment, Py_None) == -1) - return 0; + return -1; state->Match_type = make_type(state, "Match", state->stmt_type, Match_fields, 2, "Match(expr subject, match_case* cases)"); - if (!state->Match_type) return 0; + if (!state->Match_type) return -1; state->Raise_type = make_type(state, "Raise", state->stmt_type, Raise_fields, 2, "Raise(expr? exc, expr? cause)"); - if (!state->Raise_type) return 0; + if (!state->Raise_type) return -1; if (PyObject_SetAttr(state->Raise_type, state->exc, Py_None) == -1) - return 0; + return -1; if (PyObject_SetAttr(state->Raise_type, state->cause, Py_None) == -1) - return 0; + return -1; state->Try_type = make_type(state, "Try", state->stmt_type, Try_fields, 4, "Try(stmt* body, excepthandler* handlers, stmt* orelse, stmt* finalbody)"); - if (!state->Try_type) return 0; + if (!state->Try_type) return -1; state->TryStar_type = make_type(state, "TryStar", state->stmt_type, TryStar_fields, 4, "TryStar(stmt* body, excepthandler* handlers, stmt* orelse, stmt* finalbody)"); - if (!state->TryStar_type) return 0; + if (!state->TryStar_type) return -1; state->Assert_type = make_type(state, "Assert", state->stmt_type, Assert_fields, 2, "Assert(expr test, expr? msg)"); - if (!state->Assert_type) return 0; + if (!state->Assert_type) return -1; if (PyObject_SetAttr(state->Assert_type, state->msg, Py_None) == -1) - return 0; + return -1; state->Import_type = make_type(state, "Import", state->stmt_type, Import_fields, 1, "Import(alias* names)"); - if (!state->Import_type) return 0; + if (!state->Import_type) return -1; state->ImportFrom_type = make_type(state, "ImportFrom", state->stmt_type, ImportFrom_fields, 3, "ImportFrom(identifier? module, alias* names, int? level)"); - if (!state->ImportFrom_type) return 0; + if (!state->ImportFrom_type) return -1; if (PyObject_SetAttr(state->ImportFrom_type, state->module, Py_None) == -1) - return 0; + return -1; if (PyObject_SetAttr(state->ImportFrom_type, state->level, Py_None) == -1) - return 0; + return -1; state->Global_type = make_type(state, "Global", state->stmt_type, Global_fields, 1, "Global(identifier* names)"); - if (!state->Global_type) return 0; + if (!state->Global_type) return -1; state->Nonlocal_type = make_type(state, "Nonlocal", state->stmt_type, Nonlocal_fields, 1, "Nonlocal(identifier* names)"); - if (!state->Nonlocal_type) return 0; + if (!state->Nonlocal_type) return -1; state->Expr_type = make_type(state, "Expr", state->stmt_type, Expr_fields, 1, "Expr(expr value)"); - if (!state->Expr_type) return 0; + if (!state->Expr_type) return -1; state->Pass_type = make_type(state, "Pass", state->stmt_type, NULL, 0, "Pass"); - if (!state->Pass_type) return 0; + if (!state->Pass_type) return -1; state->Break_type = make_type(state, "Break", state->stmt_type, NULL, 0, "Break"); - if (!state->Break_type) return 0; + if (!state->Break_type) return -1; state->Continue_type = make_type(state, "Continue", state->stmt_type, NULL, 0, "Continue"); - if (!state->Continue_type) return 0; + if (!state->Continue_type) return -1; state->expr_type = make_type(state, "expr", state->AST_type, NULL, 0, "expr = BoolOp(boolop op, expr* values)\n" " | NamedExpr(expr target, expr value)\n" @@ -1378,454 +1396,457 @@ init_types(struct ast_state *state) " | List(expr* elts, expr_context ctx)\n" " | Tuple(expr* elts, expr_context ctx)\n" " | Slice(expr? lower, expr? upper, expr? step)"); - if (!state->expr_type) return 0; - if (!add_attributes(state, state->expr_type, expr_attributes, 4)) return 0; + if (!state->expr_type) return -1; + if (add_attributes(state, state->expr_type, expr_attributes, 4) < 0) return + -1; if (PyObject_SetAttr(state->expr_type, state->end_lineno, Py_None) == -1) - return 0; + return -1; if (PyObject_SetAttr(state->expr_type, state->end_col_offset, Py_None) == -1) - return 0; + return -1; state->BoolOp_type = make_type(state, "BoolOp", state->expr_type, BoolOp_fields, 2, "BoolOp(boolop op, expr* values)"); - if (!state->BoolOp_type) return 0; + if (!state->BoolOp_type) return -1; state->NamedExpr_type = make_type(state, "NamedExpr", state->expr_type, NamedExpr_fields, 2, "NamedExpr(expr target, expr value)"); - if (!state->NamedExpr_type) return 0; + if (!state->NamedExpr_type) return -1; state->BinOp_type = make_type(state, "BinOp", state->expr_type, BinOp_fields, 3, "BinOp(expr left, operator op, expr right)"); - if (!state->BinOp_type) return 0; + if (!state->BinOp_type) return -1; state->UnaryOp_type = make_type(state, "UnaryOp", state->expr_type, UnaryOp_fields, 2, "UnaryOp(unaryop op, expr operand)"); - if (!state->UnaryOp_type) return 0; + if (!state->UnaryOp_type) return -1; state->Lambda_type = make_type(state, "Lambda", state->expr_type, Lambda_fields, 2, "Lambda(arguments args, expr body)"); - if (!state->Lambda_type) return 0; + if (!state->Lambda_type) return -1; state->IfExp_type = make_type(state, "IfExp", state->expr_type, IfExp_fields, 3, "IfExp(expr test, expr body, expr orelse)"); - if (!state->IfExp_type) return 0; + if (!state->IfExp_type) return -1; state->Dict_type = make_type(state, "Dict", state->expr_type, Dict_fields, 2, "Dict(expr* keys, expr* values)"); - if (!state->Dict_type) return 0; + if (!state->Dict_type) return -1; state->Set_type = make_type(state, "Set", state->expr_type, Set_fields, 1, "Set(expr* elts)"); - if (!state->Set_type) return 0; + if (!state->Set_type) return -1; state->ListComp_type = make_type(state, "ListComp", state->expr_type, ListComp_fields, 2, "ListComp(expr elt, comprehension* generators)"); - if (!state->ListComp_type) return 0; + if (!state->ListComp_type) return -1; state->SetComp_type = make_type(state, "SetComp", state->expr_type, SetComp_fields, 2, "SetComp(expr elt, comprehension* generators)"); - if (!state->SetComp_type) return 0; + if (!state->SetComp_type) return -1; state->DictComp_type = make_type(state, "DictComp", state->expr_type, DictComp_fields, 3, "DictComp(expr key, expr value, comprehension* generators)"); - if (!state->DictComp_type) return 0; + if (!state->DictComp_type) return -1; state->GeneratorExp_type = make_type(state, "GeneratorExp", state->expr_type, GeneratorExp_fields, 2, "GeneratorExp(expr elt, comprehension* generators)"); - if (!state->GeneratorExp_type) return 0; + if (!state->GeneratorExp_type) return -1; state->Await_type = make_type(state, "Await", state->expr_type, Await_fields, 1, "Await(expr value)"); - if (!state->Await_type) return 0; + if (!state->Await_type) return -1; state->Yield_type = make_type(state, "Yield", state->expr_type, Yield_fields, 1, "Yield(expr? value)"); - if (!state->Yield_type) return 0; + if (!state->Yield_type) return -1; if (PyObject_SetAttr(state->Yield_type, state->value, Py_None) == -1) - return 0; + return -1; state->YieldFrom_type = make_type(state, "YieldFrom", state->expr_type, YieldFrom_fields, 1, "YieldFrom(expr value)"); - if (!state->YieldFrom_type) return 0; + if (!state->YieldFrom_type) return -1; state->Compare_type = make_type(state, "Compare", state->expr_type, Compare_fields, 3, "Compare(expr left, cmpop* ops, expr* comparators)"); - if (!state->Compare_type) return 0; + if (!state->Compare_type) return -1; state->Call_type = make_type(state, "Call", state->expr_type, Call_fields, 3, "Call(expr func, expr* args, keyword* keywords)"); - if (!state->Call_type) return 0; + if (!state->Call_type) return -1; state->FormattedValue_type = make_type(state, "FormattedValue", state->expr_type, FormattedValue_fields, 3, "FormattedValue(expr value, int conversion, expr? format_spec)"); - if (!state->FormattedValue_type) return 0; + if (!state->FormattedValue_type) return -1; if (PyObject_SetAttr(state->FormattedValue_type, state->format_spec, Py_None) == -1) - return 0; + return -1; state->JoinedStr_type = make_type(state, "JoinedStr", state->expr_type, JoinedStr_fields, 1, "JoinedStr(expr* values)"); - if (!state->JoinedStr_type) return 0; + if (!state->JoinedStr_type) return -1; state->Constant_type = make_type(state, "Constant", state->expr_type, Constant_fields, 2, "Constant(constant value, string? kind)"); - if (!state->Constant_type) return 0; + if (!state->Constant_type) return -1; if (PyObject_SetAttr(state->Constant_type, state->kind, Py_None) == -1) - return 0; + return -1; state->Attribute_type = make_type(state, "Attribute", state->expr_type, Attribute_fields, 3, "Attribute(expr value, identifier attr, expr_context ctx)"); - if (!state->Attribute_type) return 0; + if (!state->Attribute_type) return -1; state->Subscript_type = make_type(state, "Subscript", state->expr_type, Subscript_fields, 3, "Subscript(expr value, expr slice, expr_context ctx)"); - if (!state->Subscript_type) return 0; + if (!state->Subscript_type) return -1; state->Starred_type = make_type(state, "Starred", state->expr_type, Starred_fields, 2, "Starred(expr value, expr_context ctx)"); - if (!state->Starred_type) return 0; + if (!state->Starred_type) return -1; state->Name_type = make_type(state, "Name", state->expr_type, Name_fields, 2, "Name(identifier id, expr_context ctx)"); - if (!state->Name_type) return 0; + if (!state->Name_type) return -1; state->List_type = make_type(state, "List", state->expr_type, List_fields, 2, "List(expr* elts, expr_context ctx)"); - if (!state->List_type) return 0; + if (!state->List_type) return -1; state->Tuple_type = make_type(state, "Tuple", state->expr_type, Tuple_fields, 2, "Tuple(expr* elts, expr_context ctx)"); - if (!state->Tuple_type) return 0; + if (!state->Tuple_type) return -1; state->Slice_type = make_type(state, "Slice", state->expr_type, Slice_fields, 3, "Slice(expr? lower, expr? upper, expr? step)"); - if (!state->Slice_type) return 0; + if (!state->Slice_type) return -1; if (PyObject_SetAttr(state->Slice_type, state->lower, Py_None) == -1) - return 0; + return -1; if (PyObject_SetAttr(state->Slice_type, state->upper, Py_None) == -1) - return 0; + return -1; if (PyObject_SetAttr(state->Slice_type, state->step, Py_None) == -1) - return 0; + return -1; state->expr_context_type = make_type(state, "expr_context", state->AST_type, NULL, 0, "expr_context = Load | Store | Del"); - if (!state->expr_context_type) return 0; - if (!add_attributes(state, state->expr_context_type, NULL, 0)) return 0; + if (!state->expr_context_type) return -1; + if (add_attributes(state, state->expr_context_type, NULL, 0) < 0) return -1; state->Load_type = make_type(state, "Load", state->expr_context_type, NULL, 0, "Load"); - if (!state->Load_type) return 0; + if (!state->Load_type) return -1; state->Load_singleton = PyType_GenericNew((PyTypeObject *)state->Load_type, NULL, NULL); - if (!state->Load_singleton) return 0; + if (!state->Load_singleton) return -1; state->Store_type = make_type(state, "Store", state->expr_context_type, NULL, 0, "Store"); - if (!state->Store_type) return 0; + if (!state->Store_type) return -1; state->Store_singleton = PyType_GenericNew((PyTypeObject *)state->Store_type, NULL, NULL); - if (!state->Store_singleton) return 0; + if (!state->Store_singleton) return -1; state->Del_type = make_type(state, "Del", state->expr_context_type, NULL, 0, "Del"); - if (!state->Del_type) return 0; + if (!state->Del_type) return -1; state->Del_singleton = PyType_GenericNew((PyTypeObject *)state->Del_type, NULL, NULL); - if (!state->Del_singleton) return 0; + if (!state->Del_singleton) return -1; state->boolop_type = make_type(state, "boolop", state->AST_type, NULL, 0, "boolop = And | Or"); - if (!state->boolop_type) return 0; - if (!add_attributes(state, state->boolop_type, NULL, 0)) return 0; + if (!state->boolop_type) return -1; + if (add_attributes(state, state->boolop_type, NULL, 0) < 0) return -1; state->And_type = make_type(state, "And", state->boolop_type, NULL, 0, "And"); - if (!state->And_type) return 0; + if (!state->And_type) return -1; state->And_singleton = PyType_GenericNew((PyTypeObject *)state->And_type, NULL, NULL); - if (!state->And_singleton) return 0; + if (!state->And_singleton) return -1; state->Or_type = make_type(state, "Or", state->boolop_type, NULL, 0, "Or"); - if (!state->Or_type) return 0; + if (!state->Or_type) return -1; state->Or_singleton = PyType_GenericNew((PyTypeObject *)state->Or_type, NULL, NULL); - if (!state->Or_singleton) return 0; + if (!state->Or_singleton) return -1; state->operator_type = make_type(state, "operator", state->AST_type, NULL, 0, "operator = Add | Sub | Mult | MatMult | Div | Mod | Pow | LShift | RShift | BitOr | BitXor | BitAnd | FloorDiv"); - if (!state->operator_type) return 0; - if (!add_attributes(state, state->operator_type, NULL, 0)) return 0; + if (!state->operator_type) return -1; + if (add_attributes(state, state->operator_type, NULL, 0) < 0) return -1; state->Add_type = make_type(state, "Add", state->operator_type, NULL, 0, "Add"); - if (!state->Add_type) return 0; + if (!state->Add_type) return -1; state->Add_singleton = PyType_GenericNew((PyTypeObject *)state->Add_type, NULL, NULL); - if (!state->Add_singleton) return 0; + if (!state->Add_singleton) return -1; state->Sub_type = make_type(state, "Sub", state->operator_type, NULL, 0, "Sub"); - if (!state->Sub_type) return 0; + if (!state->Sub_type) return -1; state->Sub_singleton = PyType_GenericNew((PyTypeObject *)state->Sub_type, NULL, NULL); - if (!state->Sub_singleton) return 0; + if (!state->Sub_singleton) return -1; state->Mult_type = make_type(state, "Mult", state->operator_type, NULL, 0, "Mult"); - if (!state->Mult_type) return 0; + if (!state->Mult_type) return -1; state->Mult_singleton = PyType_GenericNew((PyTypeObject *)state->Mult_type, NULL, NULL); - if (!state->Mult_singleton) return 0; + if (!state->Mult_singleton) return -1; state->MatMult_type = make_type(state, "MatMult", state->operator_type, NULL, 0, "MatMult"); - if (!state->MatMult_type) return 0; + if (!state->MatMult_type) return -1; state->MatMult_singleton = PyType_GenericNew((PyTypeObject *)state->MatMult_type, NULL, NULL); - if (!state->MatMult_singleton) return 0; + if (!state->MatMult_singleton) return -1; state->Div_type = make_type(state, "Div", state->operator_type, NULL, 0, "Div"); - if (!state->Div_type) return 0; + if (!state->Div_type) return -1; state->Div_singleton = PyType_GenericNew((PyTypeObject *)state->Div_type, NULL, NULL); - if (!state->Div_singleton) return 0; + if (!state->Div_singleton) return -1; state->Mod_type = make_type(state, "Mod", state->operator_type, NULL, 0, "Mod"); - if (!state->Mod_type) return 0; + if (!state->Mod_type) return -1; state->Mod_singleton = PyType_GenericNew((PyTypeObject *)state->Mod_type, NULL, NULL); - if (!state->Mod_singleton) return 0; + if (!state->Mod_singleton) return -1; state->Pow_type = make_type(state, "Pow", state->operator_type, NULL, 0, "Pow"); - if (!state->Pow_type) return 0; + if (!state->Pow_type) return -1; state->Pow_singleton = PyType_GenericNew((PyTypeObject *)state->Pow_type, NULL, NULL); - if (!state->Pow_singleton) return 0; + if (!state->Pow_singleton) return -1; state->LShift_type = make_type(state, "LShift", state->operator_type, NULL, 0, "LShift"); - if (!state->LShift_type) return 0; + if (!state->LShift_type) return -1; state->LShift_singleton = PyType_GenericNew((PyTypeObject *)state->LShift_type, NULL, NULL); - if (!state->LShift_singleton) return 0; + if (!state->LShift_singleton) return -1; state->RShift_type = make_type(state, "RShift", state->operator_type, NULL, 0, "RShift"); - if (!state->RShift_type) return 0; + if (!state->RShift_type) return -1; state->RShift_singleton = PyType_GenericNew((PyTypeObject *)state->RShift_type, NULL, NULL); - if (!state->RShift_singleton) return 0; + if (!state->RShift_singleton) return -1; state->BitOr_type = make_type(state, "BitOr", state->operator_type, NULL, 0, "BitOr"); - if (!state->BitOr_type) return 0; + if (!state->BitOr_type) return -1; state->BitOr_singleton = PyType_GenericNew((PyTypeObject *)state->BitOr_type, NULL, NULL); - if (!state->BitOr_singleton) return 0; + if (!state->BitOr_singleton) return -1; state->BitXor_type = make_type(state, "BitXor", state->operator_type, NULL, 0, "BitXor"); - if (!state->BitXor_type) return 0; + if (!state->BitXor_type) return -1; state->BitXor_singleton = PyType_GenericNew((PyTypeObject *)state->BitXor_type, NULL, NULL); - if (!state->BitXor_singleton) return 0; + if (!state->BitXor_singleton) return -1; state->BitAnd_type = make_type(state, "BitAnd", state->operator_type, NULL, 0, "BitAnd"); - if (!state->BitAnd_type) return 0; + if (!state->BitAnd_type) return -1; state->BitAnd_singleton = PyType_GenericNew((PyTypeObject *)state->BitAnd_type, NULL, NULL); - if (!state->BitAnd_singleton) return 0; + if (!state->BitAnd_singleton) return -1; state->FloorDiv_type = make_type(state, "FloorDiv", state->operator_type, NULL, 0, "FloorDiv"); - if (!state->FloorDiv_type) return 0; + if (!state->FloorDiv_type) return -1; state->FloorDiv_singleton = PyType_GenericNew((PyTypeObject *)state->FloorDiv_type, NULL, NULL); - if (!state->FloorDiv_singleton) return 0; + if (!state->FloorDiv_singleton) return -1; state->unaryop_type = make_type(state, "unaryop", state->AST_type, NULL, 0, "unaryop = Invert | Not | UAdd | USub"); - if (!state->unaryop_type) return 0; - if (!add_attributes(state, state->unaryop_type, NULL, 0)) return 0; + if (!state->unaryop_type) return -1; + if (add_attributes(state, state->unaryop_type, NULL, 0) < 0) return -1; state->Invert_type = make_type(state, "Invert", state->unaryop_type, NULL, 0, "Invert"); - if (!state->Invert_type) return 0; + if (!state->Invert_type) return -1; state->Invert_singleton = PyType_GenericNew((PyTypeObject *)state->Invert_type, NULL, NULL); - if (!state->Invert_singleton) return 0; + if (!state->Invert_singleton) return -1; state->Not_type = make_type(state, "Not", state->unaryop_type, NULL, 0, "Not"); - if (!state->Not_type) return 0; + if (!state->Not_type) return -1; state->Not_singleton = PyType_GenericNew((PyTypeObject *)state->Not_type, NULL, NULL); - if (!state->Not_singleton) return 0; + if (!state->Not_singleton) return -1; state->UAdd_type = make_type(state, "UAdd", state->unaryop_type, NULL, 0, "UAdd"); - if (!state->UAdd_type) return 0; + if (!state->UAdd_type) return -1; state->UAdd_singleton = PyType_GenericNew((PyTypeObject *)state->UAdd_type, NULL, NULL); - if (!state->UAdd_singleton) return 0; + if (!state->UAdd_singleton) return -1; state->USub_type = make_type(state, "USub", state->unaryop_type, NULL, 0, "USub"); - if (!state->USub_type) return 0; + if (!state->USub_type) return -1; state->USub_singleton = PyType_GenericNew((PyTypeObject *)state->USub_type, NULL, NULL); - if (!state->USub_singleton) return 0; + if (!state->USub_singleton) return -1; state->cmpop_type = make_type(state, "cmpop", state->AST_type, NULL, 0, "cmpop = Eq | NotEq | Lt | LtE | Gt | GtE | Is | IsNot | In | NotIn"); - if (!state->cmpop_type) return 0; - if (!add_attributes(state, state->cmpop_type, NULL, 0)) return 0; + if (!state->cmpop_type) return -1; + if (add_attributes(state, state->cmpop_type, NULL, 0) < 0) return -1; state->Eq_type = make_type(state, "Eq", state->cmpop_type, NULL, 0, "Eq"); - if (!state->Eq_type) return 0; + if (!state->Eq_type) return -1; state->Eq_singleton = PyType_GenericNew((PyTypeObject *)state->Eq_type, NULL, NULL); - if (!state->Eq_singleton) return 0; + if (!state->Eq_singleton) return -1; state->NotEq_type = make_type(state, "NotEq", state->cmpop_type, NULL, 0, "NotEq"); - if (!state->NotEq_type) return 0; + if (!state->NotEq_type) return -1; state->NotEq_singleton = PyType_GenericNew((PyTypeObject *)state->NotEq_type, NULL, NULL); - if (!state->NotEq_singleton) return 0; + if (!state->NotEq_singleton) return -1; state->Lt_type = make_type(state, "Lt", state->cmpop_type, NULL, 0, "Lt"); - if (!state->Lt_type) return 0; + if (!state->Lt_type) return -1; state->Lt_singleton = PyType_GenericNew((PyTypeObject *)state->Lt_type, NULL, NULL); - if (!state->Lt_singleton) return 0; + if (!state->Lt_singleton) return -1; state->LtE_type = make_type(state, "LtE", state->cmpop_type, NULL, 0, "LtE"); - if (!state->LtE_type) return 0; + if (!state->LtE_type) return -1; state->LtE_singleton = PyType_GenericNew((PyTypeObject *)state->LtE_type, NULL, NULL); - if (!state->LtE_singleton) return 0; + if (!state->LtE_singleton) return -1; state->Gt_type = make_type(state, "Gt", state->cmpop_type, NULL, 0, "Gt"); - if (!state->Gt_type) return 0; + if (!state->Gt_type) return -1; state->Gt_singleton = PyType_GenericNew((PyTypeObject *)state->Gt_type, NULL, NULL); - if (!state->Gt_singleton) return 0; + if (!state->Gt_singleton) return -1; state->GtE_type = make_type(state, "GtE", state->cmpop_type, NULL, 0, "GtE"); - if (!state->GtE_type) return 0; + if (!state->GtE_type) return -1; state->GtE_singleton = PyType_GenericNew((PyTypeObject *)state->GtE_type, NULL, NULL); - if (!state->GtE_singleton) return 0; + if (!state->GtE_singleton) return -1; state->Is_type = make_type(state, "Is", state->cmpop_type, NULL, 0, "Is"); - if (!state->Is_type) return 0; + if (!state->Is_type) return -1; state->Is_singleton = PyType_GenericNew((PyTypeObject *)state->Is_type, NULL, NULL); - if (!state->Is_singleton) return 0; + if (!state->Is_singleton) return -1; state->IsNot_type = make_type(state, "IsNot", state->cmpop_type, NULL, 0, "IsNot"); - if (!state->IsNot_type) return 0; + if (!state->IsNot_type) return -1; state->IsNot_singleton = PyType_GenericNew((PyTypeObject *)state->IsNot_type, NULL, NULL); - if (!state->IsNot_singleton) return 0; + if (!state->IsNot_singleton) return -1; state->In_type = make_type(state, "In", state->cmpop_type, NULL, 0, "In"); - if (!state->In_type) return 0; + if (!state->In_type) return -1; state->In_singleton = PyType_GenericNew((PyTypeObject *)state->In_type, NULL, NULL); - if (!state->In_singleton) return 0; + if (!state->In_singleton) return -1; state->NotIn_type = make_type(state, "NotIn", state->cmpop_type, NULL, 0, "NotIn"); - if (!state->NotIn_type) return 0; + if (!state->NotIn_type) return -1; state->NotIn_singleton = PyType_GenericNew((PyTypeObject *)state->NotIn_type, NULL, NULL); - if (!state->NotIn_singleton) return 0; + if (!state->NotIn_singleton) return -1; state->comprehension_type = make_type(state, "comprehension", state->AST_type, comprehension_fields, 4, "comprehension(expr target, expr iter, expr* ifs, int is_async)"); - if (!state->comprehension_type) return 0; - if (!add_attributes(state, state->comprehension_type, NULL, 0)) return 0; + if (!state->comprehension_type) return -1; + if (add_attributes(state, state->comprehension_type, NULL, 0) < 0) return + -1; state->excepthandler_type = make_type(state, "excepthandler", state->AST_type, NULL, 0, "excepthandler = ExceptHandler(expr? type, identifier? name, stmt* body)"); - if (!state->excepthandler_type) return 0; - if (!add_attributes(state, state->excepthandler_type, - excepthandler_attributes, 4)) return 0; + if (!state->excepthandler_type) return -1; + if (add_attributes(state, state->excepthandler_type, + excepthandler_attributes, 4) < 0) return -1; if (PyObject_SetAttr(state->excepthandler_type, state->end_lineno, Py_None) == -1) - return 0; + return -1; if (PyObject_SetAttr(state->excepthandler_type, state->end_col_offset, Py_None) == -1) - return 0; + return -1; state->ExceptHandler_type = make_type(state, "ExceptHandler", state->excepthandler_type, ExceptHandler_fields, 3, "ExceptHandler(expr? type, identifier? name, stmt* body)"); - if (!state->ExceptHandler_type) return 0; + if (!state->ExceptHandler_type) return -1; if (PyObject_SetAttr(state->ExceptHandler_type, state->type, Py_None) == -1) - return 0; + return -1; if (PyObject_SetAttr(state->ExceptHandler_type, state->name, Py_None) == -1) - return 0; + return -1; state->arguments_type = make_type(state, "arguments", state->AST_type, arguments_fields, 7, "arguments(arg* posonlyargs, arg* args, arg? vararg, arg* kwonlyargs, expr* kw_defaults, arg? kwarg, expr* defaults)"); - if (!state->arguments_type) return 0; - if (!add_attributes(state, state->arguments_type, NULL, 0)) return 0; + if (!state->arguments_type) return -1; + if (add_attributes(state, state->arguments_type, NULL, 0) < 0) return -1; if (PyObject_SetAttr(state->arguments_type, state->vararg, Py_None) == -1) - return 0; + return -1; if (PyObject_SetAttr(state->arguments_type, state->kwarg, Py_None) == -1) - return 0; + return -1; state->arg_type = make_type(state, "arg", state->AST_type, arg_fields, 3, "arg(identifier arg, expr? annotation, string? type_comment)"); - if (!state->arg_type) return 0; - if (!add_attributes(state, state->arg_type, arg_attributes, 4)) return 0; + if (!state->arg_type) return -1; + if (add_attributes(state, state->arg_type, arg_attributes, 4) < 0) return + -1; if (PyObject_SetAttr(state->arg_type, state->annotation, Py_None) == -1) - return 0; + return -1; if (PyObject_SetAttr(state->arg_type, state->type_comment, Py_None) == -1) - return 0; + return -1; if (PyObject_SetAttr(state->arg_type, state->end_lineno, Py_None) == -1) - return 0; + return -1; if (PyObject_SetAttr(state->arg_type, state->end_col_offset, Py_None) == -1) - return 0; + return -1; state->keyword_type = make_type(state, "keyword", state->AST_type, keyword_fields, 2, "keyword(identifier? arg, expr value)"); - if (!state->keyword_type) return 0; - if (!add_attributes(state, state->keyword_type, keyword_attributes, 4)) - return 0; + if (!state->keyword_type) return -1; + if (add_attributes(state, state->keyword_type, keyword_attributes, 4) < 0) + return -1; if (PyObject_SetAttr(state->keyword_type, state->arg, Py_None) == -1) - return 0; + return -1; if (PyObject_SetAttr(state->keyword_type, state->end_lineno, Py_None) == -1) - return 0; + return -1; if (PyObject_SetAttr(state->keyword_type, state->end_col_offset, Py_None) == -1) - return 0; + return -1; state->alias_type = make_type(state, "alias", state->AST_type, alias_fields, 2, "alias(identifier name, identifier? asname)"); - if (!state->alias_type) return 0; - if (!add_attributes(state, state->alias_type, alias_attributes, 4)) return - 0; + if (!state->alias_type) return -1; + if (add_attributes(state, state->alias_type, alias_attributes, 4) < 0) + return -1; if (PyObject_SetAttr(state->alias_type, state->asname, Py_None) == -1) - return 0; + return -1; if (PyObject_SetAttr(state->alias_type, state->end_lineno, Py_None) == -1) - return 0; + return -1; if (PyObject_SetAttr(state->alias_type, state->end_col_offset, Py_None) == -1) - return 0; + return -1; state->withitem_type = make_type(state, "withitem", state->AST_type, withitem_fields, 2, "withitem(expr context_expr, expr? optional_vars)"); - if (!state->withitem_type) return 0; - if (!add_attributes(state, state->withitem_type, NULL, 0)) return 0; + if (!state->withitem_type) return -1; + if (add_attributes(state, state->withitem_type, NULL, 0) < 0) return -1; if (PyObject_SetAttr(state->withitem_type, state->optional_vars, Py_None) == -1) - return 0; + return -1; state->match_case_type = make_type(state, "match_case", state->AST_type, match_case_fields, 3, "match_case(pattern pattern, expr? guard, stmt* body)"); - if (!state->match_case_type) return 0; - if (!add_attributes(state, state->match_case_type, NULL, 0)) return 0; + if (!state->match_case_type) return -1; + if (add_attributes(state, state->match_case_type, NULL, 0) < 0) return -1; if (PyObject_SetAttr(state->match_case_type, state->guard, Py_None) == -1) - return 0; + return -1; state->pattern_type = make_type(state, "pattern", state->AST_type, NULL, 0, "pattern = MatchValue(expr value)\n" " | MatchSingleton(constant value)\n" @@ -1835,93 +1856,90 @@ init_types(struct ast_state *state) " | MatchStar(identifier? name)\n" " | MatchAs(pattern? pattern, identifier? name)\n" " | MatchOr(pattern* patterns)"); - if (!state->pattern_type) return 0; - if (!add_attributes(state, state->pattern_type, pattern_attributes, 4)) - return 0; + if (!state->pattern_type) return -1; + if (add_attributes(state, state->pattern_type, pattern_attributes, 4) < 0) + return -1; state->MatchValue_type = make_type(state, "MatchValue", state->pattern_type, MatchValue_fields, 1, "MatchValue(expr value)"); - if (!state->MatchValue_type) return 0; + if (!state->MatchValue_type) return -1; state->MatchSingleton_type = make_type(state, "MatchSingleton", state->pattern_type, MatchSingleton_fields, 1, "MatchSingleton(constant value)"); - if (!state->MatchSingleton_type) return 0; + if (!state->MatchSingleton_type) return -1; state->MatchSequence_type = make_type(state, "MatchSequence", state->pattern_type, MatchSequence_fields, 1, "MatchSequence(pattern* patterns)"); - if (!state->MatchSequence_type) return 0; + if (!state->MatchSequence_type) return -1; state->MatchMapping_type = make_type(state, "MatchMapping", state->pattern_type, MatchMapping_fields, 3, "MatchMapping(expr* keys, pattern* patterns, identifier? rest)"); - if (!state->MatchMapping_type) return 0; + if (!state->MatchMapping_type) return -1; if (PyObject_SetAttr(state->MatchMapping_type, state->rest, Py_None) == -1) - return 0; + return -1; state->MatchClass_type = make_type(state, "MatchClass", state->pattern_type, MatchClass_fields, 4, "MatchClass(expr cls, pattern* patterns, identifier* kwd_attrs, pattern* kwd_patterns)"); - if (!state->MatchClass_type) return 0; + if (!state->MatchClass_type) return -1; state->MatchStar_type = make_type(state, "MatchStar", state->pattern_type, MatchStar_fields, 1, "MatchStar(identifier? name)"); - if (!state->MatchStar_type) return 0; + if (!state->MatchStar_type) return -1; if (PyObject_SetAttr(state->MatchStar_type, state->name, Py_None) == -1) - return 0; + return -1; state->MatchAs_type = make_type(state, "MatchAs", state->pattern_type, MatchAs_fields, 2, "MatchAs(pattern? pattern, identifier? name)"); - if (!state->MatchAs_type) return 0; + if (!state->MatchAs_type) return -1; if (PyObject_SetAttr(state->MatchAs_type, state->pattern, Py_None) == -1) - return 0; + return -1; if (PyObject_SetAttr(state->MatchAs_type, state->name, Py_None) == -1) - return 0; + return -1; state->MatchOr_type = make_type(state, "MatchOr", state->pattern_type, MatchOr_fields, 1, "MatchOr(pattern* patterns)"); - if (!state->MatchOr_type) return 0; + if (!state->MatchOr_type) return -1; state->type_ignore_type = make_type(state, "type_ignore", state->AST_type, NULL, 0, "type_ignore = TypeIgnore(int lineno, string tag)"); - if (!state->type_ignore_type) return 0; - if (!add_attributes(state, state->type_ignore_type, NULL, 0)) return 0; + if (!state->type_ignore_type) return -1; + if (add_attributes(state, state->type_ignore_type, NULL, 0) < 0) return -1; state->TypeIgnore_type = make_type(state, "TypeIgnore", state->type_ignore_type, TypeIgnore_fields, 2, "TypeIgnore(int lineno, string tag)"); - if (!state->TypeIgnore_type) return 0; + if (!state->TypeIgnore_type) return -1; state->type_param_type = make_type(state, "type_param", state->AST_type, NULL, 0, "type_param = TypeVar(identifier name, expr? bound)\n" " | ParamSpec(identifier name)\n" " | TypeVarTuple(identifier name)"); - if (!state->type_param_type) return 0; - if (!add_attributes(state, state->type_param_type, type_param_attributes, - 4)) return 0; + if (!state->type_param_type) return -1; + if (add_attributes(state, state->type_param_type, type_param_attributes, 4) + < 0) return -1; state->TypeVar_type = make_type(state, "TypeVar", state->type_param_type, TypeVar_fields, 2, "TypeVar(identifier name, expr? bound)"); - if (!state->TypeVar_type) return 0; + if (!state->TypeVar_type) return -1; if (PyObject_SetAttr(state->TypeVar_type, state->bound, Py_None) == -1) - return 0; + return -1; state->ParamSpec_type = make_type(state, "ParamSpec", state->type_param_type, ParamSpec_fields, 1, "ParamSpec(identifier name)"); - if (!state->ParamSpec_type) return 0; + if (!state->ParamSpec_type) return -1; state->TypeVarTuple_type = make_type(state, "TypeVarTuple", state->type_param_type, TypeVarTuple_fields, 1, "TypeVarTuple(identifier name)"); - if (!state->TypeVarTuple_type) return 0; + if (!state->TypeVarTuple_type) return -1; - state->recursion_depth = 0; - state->recursion_limit = 0; - state->initialized = 1; - return 1; + return 0; } static int obj2ast_mod(struct ast_state *state, PyObject* obj, mod_ty* out, @@ -3775,7 +3793,7 @@ _PyAST_TypeVarTuple(identifier name, int lineno, int col_offset, int PyObject* -ast2obj_mod(struct ast_state *state, void* _o) +ast2obj_mod(struct ast_state *state, struct validator *vstate, void* _o) { mod_ty o = (mod_ty)_o; PyObject *result = NULL, *value = NULL; @@ -3783,22 +3801,24 @@ ast2obj_mod(struct ast_state *state, void* _o) if (!o) { Py_RETURN_NONE; } - if (++state->recursion_depth > state->recursion_limit) { + if (++vstate->recursion_depth > vstate->recursion_limit) { PyErr_SetString(PyExc_RecursionError, "maximum recursion depth exceeded during ast construction"); - return 0; + return NULL; } switch (o->kind) { case Module_kind: tp = (PyTypeObject *)state->Module_type; result = PyType_GenericNew(tp, NULL, NULL); if (!result) goto failed; - value = ast2obj_list(state, (asdl_seq*)o->v.Module.body, ast2obj_stmt); + value = ast2obj_list(state, vstate, (asdl_seq*)o->v.Module.body, + ast2obj_stmt); if (!value) goto failed; if (PyObject_SetAttr(result, state->body, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_list(state, (asdl_seq*)o->v.Module.type_ignores, + value = ast2obj_list(state, vstate, + (asdl_seq*)o->v.Module.type_ignores, ast2obj_type_ignore); if (!value) goto failed; if (PyObject_SetAttr(result, state->type_ignores, value) == -1) @@ -3809,7 +3829,7 @@ ast2obj_mod(struct ast_state *state, void* _o) tp = (PyTypeObject *)state->Interactive_type; result = PyType_GenericNew(tp, NULL, NULL); if (!result) goto failed; - value = ast2obj_list(state, (asdl_seq*)o->v.Interactive.body, + value = ast2obj_list(state, vstate, (asdl_seq*)o->v.Interactive.body, ast2obj_stmt); if (!value) goto failed; if (PyObject_SetAttr(result, state->body, value) == -1) @@ -3820,7 +3840,7 @@ ast2obj_mod(struct ast_state *state, void* _o) tp = (PyTypeObject *)state->Expression_type; result = PyType_GenericNew(tp, NULL, NULL); if (!result) goto failed; - value = ast2obj_expr(state, o->v.Expression.body); + value = ast2obj_expr(state, vstate, o->v.Expression.body); if (!value) goto failed; if (PyObject_SetAttr(result, state->body, value) == -1) goto failed; @@ -3830,29 +3850,31 @@ ast2obj_mod(struct ast_state *state, void* _o) tp = (PyTypeObject *)state->FunctionType_type; result = PyType_GenericNew(tp, NULL, NULL); if (!result) goto failed; - value = ast2obj_list(state, (asdl_seq*)o->v.FunctionType.argtypes, + value = ast2obj_list(state, vstate, + (asdl_seq*)o->v.FunctionType.argtypes, ast2obj_expr); if (!value) goto failed; if (PyObject_SetAttr(result, state->argtypes, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_expr(state, o->v.FunctionType.returns); + value = ast2obj_expr(state, vstate, o->v.FunctionType.returns); if (!value) goto failed; if (PyObject_SetAttr(result, state->returns, value) == -1) goto failed; Py_DECREF(value); break; } - state->recursion_depth--; + vstate->recursion_depth--; return result; failed: + vstate->recursion_depth--; Py_XDECREF(value); Py_XDECREF(result); return NULL; } PyObject* -ast2obj_stmt(struct ast_state *state, void* _o) +ast2obj_stmt(struct ast_state *state, struct validator *vstate, void* _o) { stmt_ty o = (stmt_ty)_o; PyObject *result = NULL, *value = NULL; @@ -3860,49 +3882,51 @@ ast2obj_stmt(struct ast_state *state, void* _o) if (!o) { Py_RETURN_NONE; } - if (++state->recursion_depth > state->recursion_limit) { + if (++vstate->recursion_depth > vstate->recursion_limit) { PyErr_SetString(PyExc_RecursionError, "maximum recursion depth exceeded during ast construction"); - return 0; + return NULL; } switch (o->kind) { case FunctionDef_kind: tp = (PyTypeObject *)state->FunctionDef_type; result = PyType_GenericNew(tp, NULL, NULL); if (!result) goto failed; - value = ast2obj_identifier(state, o->v.FunctionDef.name); + value = ast2obj_identifier(state, vstate, o->v.FunctionDef.name); if (!value) goto failed; if (PyObject_SetAttr(result, state->name, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_arguments(state, o->v.FunctionDef.args); + value = ast2obj_arguments(state, vstate, o->v.FunctionDef.args); if (!value) goto failed; if (PyObject_SetAttr(result, state->args, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_list(state, (asdl_seq*)o->v.FunctionDef.body, + value = ast2obj_list(state, vstate, (asdl_seq*)o->v.FunctionDef.body, ast2obj_stmt); if (!value) goto failed; if (PyObject_SetAttr(result, state->body, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_list(state, (asdl_seq*)o->v.FunctionDef.decorator_list, + value = ast2obj_list(state, vstate, + (asdl_seq*)o->v.FunctionDef.decorator_list, ast2obj_expr); if (!value) goto failed; if (PyObject_SetAttr(result, state->decorator_list, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_expr(state, o->v.FunctionDef.returns); + value = ast2obj_expr(state, vstate, o->v.FunctionDef.returns); if (!value) goto failed; if (PyObject_SetAttr(result, state->returns, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_string(state, o->v.FunctionDef.type_comment); + value = ast2obj_string(state, vstate, o->v.FunctionDef.type_comment); if (!value) goto failed; if (PyObject_SetAttr(result, state->type_comment, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_list(state, (asdl_seq*)o->v.FunctionDef.type_params, + value = ast2obj_list(state, vstate, + (asdl_seq*)o->v.FunctionDef.type_params, ast2obj_type_param); if (!value) goto failed; if (PyObject_SetAttr(result, state->type_params, value) == -1) @@ -3913,40 +3937,41 @@ ast2obj_stmt(struct ast_state *state, void* _o) tp = (PyTypeObject *)state->AsyncFunctionDef_type; result = PyType_GenericNew(tp, NULL, NULL); if (!result) goto failed; - value = ast2obj_identifier(state, o->v.AsyncFunctionDef.name); + value = ast2obj_identifier(state, vstate, o->v.AsyncFunctionDef.name); if (!value) goto failed; if (PyObject_SetAttr(result, state->name, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_arguments(state, o->v.AsyncFunctionDef.args); + value = ast2obj_arguments(state, vstate, o->v.AsyncFunctionDef.args); if (!value) goto failed; if (PyObject_SetAttr(result, state->args, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_list(state, (asdl_seq*)o->v.AsyncFunctionDef.body, + value = ast2obj_list(state, vstate, + (asdl_seq*)o->v.AsyncFunctionDef.body, ast2obj_stmt); if (!value) goto failed; if (PyObject_SetAttr(result, state->body, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_list(state, + value = ast2obj_list(state, vstate, (asdl_seq*)o->v.AsyncFunctionDef.decorator_list, ast2obj_expr); if (!value) goto failed; if (PyObject_SetAttr(result, state->decorator_list, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_expr(state, o->v.AsyncFunctionDef.returns); + value = ast2obj_expr(state, vstate, o->v.AsyncFunctionDef.returns); if (!value) goto failed; if (PyObject_SetAttr(result, state->returns, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_string(state, o->v.AsyncFunctionDef.type_comment); + value = ast2obj_string(state, vstate, o->v.AsyncFunctionDef.type_comment); if (!value) goto failed; if (PyObject_SetAttr(result, state->type_comment, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_list(state, + value = ast2obj_list(state, vstate, (asdl_seq*)o->v.AsyncFunctionDef.type_params, ast2obj_type_param); if (!value) goto failed; @@ -3958,36 +3983,38 @@ ast2obj_stmt(struct ast_state *state, void* _o) tp = (PyTypeObject *)state->ClassDef_type; result = PyType_GenericNew(tp, NULL, NULL); if (!result) goto failed; - value = ast2obj_identifier(state, o->v.ClassDef.name); + value = ast2obj_identifier(state, vstate, o->v.ClassDef.name); if (!value) goto failed; if (PyObject_SetAttr(result, state->name, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_list(state, (asdl_seq*)o->v.ClassDef.bases, + value = ast2obj_list(state, vstate, (asdl_seq*)o->v.ClassDef.bases, ast2obj_expr); if (!value) goto failed; if (PyObject_SetAttr(result, state->bases, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_list(state, (asdl_seq*)o->v.ClassDef.keywords, + value = ast2obj_list(state, vstate, (asdl_seq*)o->v.ClassDef.keywords, ast2obj_keyword); if (!value) goto failed; if (PyObject_SetAttr(result, state->keywords, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_list(state, (asdl_seq*)o->v.ClassDef.body, + value = ast2obj_list(state, vstate, (asdl_seq*)o->v.ClassDef.body, ast2obj_stmt); if (!value) goto failed; if (PyObject_SetAttr(result, state->body, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_list(state, (asdl_seq*)o->v.ClassDef.decorator_list, + value = ast2obj_list(state, vstate, + (asdl_seq*)o->v.ClassDef.decorator_list, ast2obj_expr); if (!value) goto failed; if (PyObject_SetAttr(result, state->decorator_list, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_list(state, (asdl_seq*)o->v.ClassDef.type_params, + value = ast2obj_list(state, vstate, + (asdl_seq*)o->v.ClassDef.type_params, ast2obj_type_param); if (!value) goto failed; if (PyObject_SetAttr(result, state->type_params, value) == -1) @@ -3998,7 +4025,7 @@ ast2obj_stmt(struct ast_state *state, void* _o) tp = (PyTypeObject *)state->Return_type; result = PyType_GenericNew(tp, NULL, NULL); if (!result) goto failed; - value = ast2obj_expr(state, o->v.Return.value); + value = ast2obj_expr(state, vstate, o->v.Return.value); if (!value) goto failed; if (PyObject_SetAttr(result, state->value, value) == -1) goto failed; @@ -4008,7 +4035,7 @@ ast2obj_stmt(struct ast_state *state, void* _o) tp = (PyTypeObject *)state->Delete_type; result = PyType_GenericNew(tp, NULL, NULL); if (!result) goto failed; - value = ast2obj_list(state, (asdl_seq*)o->v.Delete.targets, + value = ast2obj_list(state, vstate, (asdl_seq*)o->v.Delete.targets, ast2obj_expr); if (!value) goto failed; if (PyObject_SetAttr(result, state->targets, value) == -1) @@ -4019,18 +4046,18 @@ ast2obj_stmt(struct ast_state *state, void* _o) tp = (PyTypeObject *)state->Assign_type; result = PyType_GenericNew(tp, NULL, NULL); if (!result) goto failed; - value = ast2obj_list(state, (asdl_seq*)o->v.Assign.targets, + value = ast2obj_list(state, vstate, (asdl_seq*)o->v.Assign.targets, ast2obj_expr); if (!value) goto failed; if (PyObject_SetAttr(result, state->targets, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_expr(state, o->v.Assign.value); + value = ast2obj_expr(state, vstate, o->v.Assign.value); if (!value) goto failed; if (PyObject_SetAttr(result, state->value, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_string(state, o->v.Assign.type_comment); + value = ast2obj_string(state, vstate, o->v.Assign.type_comment); if (!value) goto failed; if (PyObject_SetAttr(result, state->type_comment, value) == -1) goto failed; @@ -4040,18 +4067,19 @@ ast2obj_stmt(struct ast_state *state, void* _o) tp = (PyTypeObject *)state->TypeAlias_type; result = PyType_GenericNew(tp, NULL, NULL); if (!result) goto failed; - value = ast2obj_expr(state, o->v.TypeAlias.name); + value = ast2obj_expr(state, vstate, o->v.TypeAlias.name); if (!value) goto failed; if (PyObject_SetAttr(result, state->name, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_list(state, (asdl_seq*)o->v.TypeAlias.type_params, + value = ast2obj_list(state, vstate, + (asdl_seq*)o->v.TypeAlias.type_params, ast2obj_type_param); if (!value) goto failed; if (PyObject_SetAttr(result, state->type_params, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_expr(state, o->v.TypeAlias.value); + value = ast2obj_expr(state, vstate, o->v.TypeAlias.value); if (!value) goto failed; if (PyObject_SetAttr(result, state->value, value) == -1) goto failed; @@ -4061,17 +4089,17 @@ ast2obj_stmt(struct ast_state *state, void* _o) tp = (PyTypeObject *)state->AugAssign_type; result = PyType_GenericNew(tp, NULL, NULL); if (!result) goto failed; - value = ast2obj_expr(state, o->v.AugAssign.target); + value = ast2obj_expr(state, vstate, o->v.AugAssign.target); if (!value) goto failed; if (PyObject_SetAttr(result, state->target, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_operator(state, o->v.AugAssign.op); + value = ast2obj_operator(state, vstate, o->v.AugAssign.op); if (!value) goto failed; if (PyObject_SetAttr(result, state->op, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_expr(state, o->v.AugAssign.value); + value = ast2obj_expr(state, vstate, o->v.AugAssign.value); if (!value) goto failed; if (PyObject_SetAttr(result, state->value, value) == -1) goto failed; @@ -4081,22 +4109,22 @@ ast2obj_stmt(struct ast_state *state, void* _o) tp = (PyTypeObject *)state->AnnAssign_type; result = PyType_GenericNew(tp, NULL, NULL); if (!result) goto failed; - value = ast2obj_expr(state, o->v.AnnAssign.target); + value = ast2obj_expr(state, vstate, o->v.AnnAssign.target); if (!value) goto failed; if (PyObject_SetAttr(result, state->target, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_expr(state, o->v.AnnAssign.annotation); + value = ast2obj_expr(state, vstate, o->v.AnnAssign.annotation); if (!value) goto failed; if (PyObject_SetAttr(result, state->annotation, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_expr(state, o->v.AnnAssign.value); + value = ast2obj_expr(state, vstate, o->v.AnnAssign.value); if (!value) goto failed; if (PyObject_SetAttr(result, state->value, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_int(state, o->v.AnnAssign.simple); + value = ast2obj_int(state, vstate, o->v.AnnAssign.simple); if (!value) goto failed; if (PyObject_SetAttr(result, state->simple, value) == -1) goto failed; @@ -4106,27 +4134,29 @@ ast2obj_stmt(struct ast_state *state, void* _o) tp = (PyTypeObject *)state->For_type; result = PyType_GenericNew(tp, NULL, NULL); if (!result) goto failed; - value = ast2obj_expr(state, o->v.For.target); + value = ast2obj_expr(state, vstate, o->v.For.target); if (!value) goto failed; if (PyObject_SetAttr(result, state->target, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_expr(state, o->v.For.iter); + value = ast2obj_expr(state, vstate, o->v.For.iter); if (!value) goto failed; if (PyObject_SetAttr(result, state->iter, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_list(state, (asdl_seq*)o->v.For.body, ast2obj_stmt); + value = ast2obj_list(state, vstate, (asdl_seq*)o->v.For.body, + ast2obj_stmt); if (!value) goto failed; if (PyObject_SetAttr(result, state->body, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_list(state, (asdl_seq*)o->v.For.orelse, ast2obj_stmt); + value = ast2obj_list(state, vstate, (asdl_seq*)o->v.For.orelse, + ast2obj_stmt); if (!value) goto failed; if (PyObject_SetAttr(result, state->orelse, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_string(state, o->v.For.type_comment); + value = ast2obj_string(state, vstate, o->v.For.type_comment); if (!value) goto failed; if (PyObject_SetAttr(result, state->type_comment, value) == -1) goto failed; @@ -4136,29 +4166,29 @@ ast2obj_stmt(struct ast_state *state, void* _o) tp = (PyTypeObject *)state->AsyncFor_type; result = PyType_GenericNew(tp, NULL, NULL); if (!result) goto failed; - value = ast2obj_expr(state, o->v.AsyncFor.target); + value = ast2obj_expr(state, vstate, o->v.AsyncFor.target); if (!value) goto failed; if (PyObject_SetAttr(result, state->target, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_expr(state, o->v.AsyncFor.iter); + value = ast2obj_expr(state, vstate, o->v.AsyncFor.iter); if (!value) goto failed; if (PyObject_SetAttr(result, state->iter, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_list(state, (asdl_seq*)o->v.AsyncFor.body, + value = ast2obj_list(state, vstate, (asdl_seq*)o->v.AsyncFor.body, ast2obj_stmt); if (!value) goto failed; if (PyObject_SetAttr(result, state->body, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_list(state, (asdl_seq*)o->v.AsyncFor.orelse, + value = ast2obj_list(state, vstate, (asdl_seq*)o->v.AsyncFor.orelse, ast2obj_stmt); if (!value) goto failed; if (PyObject_SetAttr(result, state->orelse, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_string(state, o->v.AsyncFor.type_comment); + value = ast2obj_string(state, vstate, o->v.AsyncFor.type_comment); if (!value) goto failed; if (PyObject_SetAttr(result, state->type_comment, value) == -1) goto failed; @@ -4168,17 +4198,19 @@ ast2obj_stmt(struct ast_state *state, void* _o) tp = (PyTypeObject *)state->While_type; result = PyType_GenericNew(tp, NULL, NULL); if (!result) goto failed; - value = ast2obj_expr(state, o->v.While.test); + value = ast2obj_expr(state, vstate, o->v.While.test); if (!value) goto failed; if (PyObject_SetAttr(result, state->test, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_list(state, (asdl_seq*)o->v.While.body, ast2obj_stmt); + value = ast2obj_list(state, vstate, (asdl_seq*)o->v.While.body, + ast2obj_stmt); if (!value) goto failed; if (PyObject_SetAttr(result, state->body, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_list(state, (asdl_seq*)o->v.While.orelse, ast2obj_stmt); + value = ast2obj_list(state, vstate, (asdl_seq*)o->v.While.orelse, + ast2obj_stmt); if (!value) goto failed; if (PyObject_SetAttr(result, state->orelse, value) == -1) goto failed; @@ -4188,17 +4220,19 @@ ast2obj_stmt(struct ast_state *state, void* _o) tp = (PyTypeObject *)state->If_type; result = PyType_GenericNew(tp, NULL, NULL); if (!result) goto failed; - value = ast2obj_expr(state, o->v.If.test); + value = ast2obj_expr(state, vstate, o->v.If.test); if (!value) goto failed; if (PyObject_SetAttr(result, state->test, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_list(state, (asdl_seq*)o->v.If.body, ast2obj_stmt); + value = ast2obj_list(state, vstate, (asdl_seq*)o->v.If.body, + ast2obj_stmt); if (!value) goto failed; if (PyObject_SetAttr(result, state->body, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_list(state, (asdl_seq*)o->v.If.orelse, ast2obj_stmt); + value = ast2obj_list(state, vstate, (asdl_seq*)o->v.If.orelse, + ast2obj_stmt); if (!value) goto failed; if (PyObject_SetAttr(result, state->orelse, value) == -1) goto failed; @@ -4208,18 +4242,19 @@ ast2obj_stmt(struct ast_state *state, void* _o) tp = (PyTypeObject *)state->With_type; result = PyType_GenericNew(tp, NULL, NULL); if (!result) goto failed; - value = ast2obj_list(state, (asdl_seq*)o->v.With.items, + value = ast2obj_list(state, vstate, (asdl_seq*)o->v.With.items, ast2obj_withitem); if (!value) goto failed; if (PyObject_SetAttr(result, state->items, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_list(state, (asdl_seq*)o->v.With.body, ast2obj_stmt); + value = ast2obj_list(state, vstate, (asdl_seq*)o->v.With.body, + ast2obj_stmt); if (!value) goto failed; if (PyObject_SetAttr(result, state->body, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_string(state, o->v.With.type_comment); + value = ast2obj_string(state, vstate, o->v.With.type_comment); if (!value) goto failed; if (PyObject_SetAttr(result, state->type_comment, value) == -1) goto failed; @@ -4229,19 +4264,19 @@ ast2obj_stmt(struct ast_state *state, void* _o) tp = (PyTypeObject *)state->AsyncWith_type; result = PyType_GenericNew(tp, NULL, NULL); if (!result) goto failed; - value = ast2obj_list(state, (asdl_seq*)o->v.AsyncWith.items, + value = ast2obj_list(state, vstate, (asdl_seq*)o->v.AsyncWith.items, ast2obj_withitem); if (!value) goto failed; if (PyObject_SetAttr(result, state->items, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_list(state, (asdl_seq*)o->v.AsyncWith.body, + value = ast2obj_list(state, vstate, (asdl_seq*)o->v.AsyncWith.body, ast2obj_stmt); if (!value) goto failed; if (PyObject_SetAttr(result, state->body, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_string(state, o->v.AsyncWith.type_comment); + value = ast2obj_string(state, vstate, o->v.AsyncWith.type_comment); if (!value) goto failed; if (PyObject_SetAttr(result, state->type_comment, value) == -1) goto failed; @@ -4251,12 +4286,12 @@ ast2obj_stmt(struct ast_state *state, void* _o) tp = (PyTypeObject *)state->Match_type; result = PyType_GenericNew(tp, NULL, NULL); if (!result) goto failed; - value = ast2obj_expr(state, o->v.Match.subject); + value = ast2obj_expr(state, vstate, o->v.Match.subject); if (!value) goto failed; if (PyObject_SetAttr(result, state->subject, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_list(state, (asdl_seq*)o->v.Match.cases, + value = ast2obj_list(state, vstate, (asdl_seq*)o->v.Match.cases, ast2obj_match_case); if (!value) goto failed; if (PyObject_SetAttr(result, state->cases, value) == -1) @@ -4267,12 +4302,12 @@ ast2obj_stmt(struct ast_state *state, void* _o) tp = (PyTypeObject *)state->Raise_type; result = PyType_GenericNew(tp, NULL, NULL); if (!result) goto failed; - value = ast2obj_expr(state, o->v.Raise.exc); + value = ast2obj_expr(state, vstate, o->v.Raise.exc); if (!value) goto failed; if (PyObject_SetAttr(result, state->exc, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_expr(state, o->v.Raise.cause); + value = ast2obj_expr(state, vstate, o->v.Raise.cause); if (!value) goto failed; if (PyObject_SetAttr(result, state->cause, value) == -1) goto failed; @@ -4282,23 +4317,25 @@ ast2obj_stmt(struct ast_state *state, void* _o) tp = (PyTypeObject *)state->Try_type; result = PyType_GenericNew(tp, NULL, NULL); if (!result) goto failed; - value = ast2obj_list(state, (asdl_seq*)o->v.Try.body, ast2obj_stmt); + value = ast2obj_list(state, vstate, (asdl_seq*)o->v.Try.body, + ast2obj_stmt); if (!value) goto failed; if (PyObject_SetAttr(result, state->body, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_list(state, (asdl_seq*)o->v.Try.handlers, + value = ast2obj_list(state, vstate, (asdl_seq*)o->v.Try.handlers, ast2obj_excepthandler); if (!value) goto failed; if (PyObject_SetAttr(result, state->handlers, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_list(state, (asdl_seq*)o->v.Try.orelse, ast2obj_stmt); + value = ast2obj_list(state, vstate, (asdl_seq*)o->v.Try.orelse, + ast2obj_stmt); if (!value) goto failed; if (PyObject_SetAttr(result, state->orelse, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_list(state, (asdl_seq*)o->v.Try.finalbody, + value = ast2obj_list(state, vstate, (asdl_seq*)o->v.Try.finalbody, ast2obj_stmt); if (!value) goto failed; if (PyObject_SetAttr(result, state->finalbody, value) == -1) @@ -4309,24 +4346,25 @@ ast2obj_stmt(struct ast_state *state, void* _o) tp = (PyTypeObject *)state->TryStar_type; result = PyType_GenericNew(tp, NULL, NULL); if (!result) goto failed; - value = ast2obj_list(state, (asdl_seq*)o->v.TryStar.body, ast2obj_stmt); + value = ast2obj_list(state, vstate, (asdl_seq*)o->v.TryStar.body, + ast2obj_stmt); if (!value) goto failed; if (PyObject_SetAttr(result, state->body, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_list(state, (asdl_seq*)o->v.TryStar.handlers, + value = ast2obj_list(state, vstate, (asdl_seq*)o->v.TryStar.handlers, ast2obj_excepthandler); if (!value) goto failed; if (PyObject_SetAttr(result, state->handlers, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_list(state, (asdl_seq*)o->v.TryStar.orelse, + value = ast2obj_list(state, vstate, (asdl_seq*)o->v.TryStar.orelse, ast2obj_stmt); if (!value) goto failed; if (PyObject_SetAttr(result, state->orelse, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_list(state, (asdl_seq*)o->v.TryStar.finalbody, + value = ast2obj_list(state, vstate, (asdl_seq*)o->v.TryStar.finalbody, ast2obj_stmt); if (!value) goto failed; if (PyObject_SetAttr(result, state->finalbody, value) == -1) @@ -4337,12 +4375,12 @@ ast2obj_stmt(struct ast_state *state, void* _o) tp = (PyTypeObject *)state->Assert_type; result = PyType_GenericNew(tp, NULL, NULL); if (!result) goto failed; - value = ast2obj_expr(state, o->v.Assert.test); + value = ast2obj_expr(state, vstate, o->v.Assert.test); if (!value) goto failed; if (PyObject_SetAttr(result, state->test, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_expr(state, o->v.Assert.msg); + value = ast2obj_expr(state, vstate, o->v.Assert.msg); if (!value) goto failed; if (PyObject_SetAttr(result, state->msg, value) == -1) goto failed; @@ -4352,7 +4390,7 @@ ast2obj_stmt(struct ast_state *state, void* _o) tp = (PyTypeObject *)state->Import_type; result = PyType_GenericNew(tp, NULL, NULL); if (!result) goto failed; - value = ast2obj_list(state, (asdl_seq*)o->v.Import.names, + value = ast2obj_list(state, vstate, (asdl_seq*)o->v.Import.names, ast2obj_alias); if (!value) goto failed; if (PyObject_SetAttr(result, state->names, value) == -1) @@ -4363,18 +4401,18 @@ ast2obj_stmt(struct ast_state *state, void* _o) tp = (PyTypeObject *)state->ImportFrom_type; result = PyType_GenericNew(tp, NULL, NULL); if (!result) goto failed; - value = ast2obj_identifier(state, o->v.ImportFrom.module); + value = ast2obj_identifier(state, vstate, o->v.ImportFrom.module); if (!value) goto failed; if (PyObject_SetAttr(result, state->module, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_list(state, (asdl_seq*)o->v.ImportFrom.names, + value = ast2obj_list(state, vstate, (asdl_seq*)o->v.ImportFrom.names, ast2obj_alias); if (!value) goto failed; if (PyObject_SetAttr(result, state->names, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_int(state, o->v.ImportFrom.level); + value = ast2obj_int(state, vstate, o->v.ImportFrom.level); if (!value) goto failed; if (PyObject_SetAttr(result, state->level, value) == -1) goto failed; @@ -4384,7 +4422,7 @@ ast2obj_stmt(struct ast_state *state, void* _o) tp = (PyTypeObject *)state->Global_type; result = PyType_GenericNew(tp, NULL, NULL); if (!result) goto failed; - value = ast2obj_list(state, (asdl_seq*)o->v.Global.names, + value = ast2obj_list(state, vstate, (asdl_seq*)o->v.Global.names, ast2obj_identifier); if (!value) goto failed; if (PyObject_SetAttr(result, state->names, value) == -1) @@ -4395,7 +4433,7 @@ ast2obj_stmt(struct ast_state *state, void* _o) tp = (PyTypeObject *)state->Nonlocal_type; result = PyType_GenericNew(tp, NULL, NULL); if (!result) goto failed; - value = ast2obj_list(state, (asdl_seq*)o->v.Nonlocal.names, + value = ast2obj_list(state, vstate, (asdl_seq*)o->v.Nonlocal.names, ast2obj_identifier); if (!value) goto failed; if (PyObject_SetAttr(result, state->names, value) == -1) @@ -4406,7 +4444,7 @@ ast2obj_stmt(struct ast_state *state, void* _o) tp = (PyTypeObject *)state->Expr_type; result = PyType_GenericNew(tp, NULL, NULL); if (!result) goto failed; - value = ast2obj_expr(state, o->v.Expr.value); + value = ast2obj_expr(state, vstate, o->v.Expr.value); if (!value) goto failed; if (PyObject_SetAttr(result, state->value, value) == -1) goto failed; @@ -4428,36 +4466,37 @@ ast2obj_stmt(struct ast_state *state, void* _o) if (!result) goto failed; break; } - value = ast2obj_int(state, o->lineno); + value = ast2obj_int(state, vstate, o->lineno); if (!value) goto failed; if (PyObject_SetAttr(result, state->lineno, value) < 0) goto failed; Py_DECREF(value); - value = ast2obj_int(state, o->col_offset); + value = ast2obj_int(state, vstate, o->col_offset); if (!value) goto failed; if (PyObject_SetAttr(result, state->col_offset, value) < 0) goto failed; Py_DECREF(value); - value = ast2obj_int(state, o->end_lineno); + value = ast2obj_int(state, vstate, o->end_lineno); if (!value) goto failed; if (PyObject_SetAttr(result, state->end_lineno, value) < 0) goto failed; Py_DECREF(value); - value = ast2obj_int(state, o->end_col_offset); + value = ast2obj_int(state, vstate, o->end_col_offset); if (!value) goto failed; if (PyObject_SetAttr(result, state->end_col_offset, value) < 0) goto failed; Py_DECREF(value); - state->recursion_depth--; + vstate->recursion_depth--; return result; failed: + vstate->recursion_depth--; Py_XDECREF(value); Py_XDECREF(result); return NULL; } PyObject* -ast2obj_expr(struct ast_state *state, void* _o) +ast2obj_expr(struct ast_state *state, struct validator *vstate, void* _o) { expr_ty o = (expr_ty)_o; PyObject *result = NULL, *value = NULL; @@ -4465,22 +4504,22 @@ ast2obj_expr(struct ast_state *state, void* _o) if (!o) { Py_RETURN_NONE; } - if (++state->recursion_depth > state->recursion_limit) { + if (++vstate->recursion_depth > vstate->recursion_limit) { PyErr_SetString(PyExc_RecursionError, "maximum recursion depth exceeded during ast construction"); - return 0; + return NULL; } switch (o->kind) { case BoolOp_kind: tp = (PyTypeObject *)state->BoolOp_type; result = PyType_GenericNew(tp, NULL, NULL); if (!result) goto failed; - value = ast2obj_boolop(state, o->v.BoolOp.op); + value = ast2obj_boolop(state, vstate, o->v.BoolOp.op); if (!value) goto failed; if (PyObject_SetAttr(result, state->op, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_list(state, (asdl_seq*)o->v.BoolOp.values, + value = ast2obj_list(state, vstate, (asdl_seq*)o->v.BoolOp.values, ast2obj_expr); if (!value) goto failed; if (PyObject_SetAttr(result, state->values, value) == -1) @@ -4491,12 +4530,12 @@ ast2obj_expr(struct ast_state *state, void* _o) tp = (PyTypeObject *)state->NamedExpr_type; result = PyType_GenericNew(tp, NULL, NULL); if (!result) goto failed; - value = ast2obj_expr(state, o->v.NamedExpr.target); + value = ast2obj_expr(state, vstate, o->v.NamedExpr.target); if (!value) goto failed; if (PyObject_SetAttr(result, state->target, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_expr(state, o->v.NamedExpr.value); + value = ast2obj_expr(state, vstate, o->v.NamedExpr.value); if (!value) goto failed; if (PyObject_SetAttr(result, state->value, value) == -1) goto failed; @@ -4506,17 +4545,17 @@ ast2obj_expr(struct ast_state *state, void* _o) tp = (PyTypeObject *)state->BinOp_type; result = PyType_GenericNew(tp, NULL, NULL); if (!result) goto failed; - value = ast2obj_expr(state, o->v.BinOp.left); + value = ast2obj_expr(state, vstate, o->v.BinOp.left); if (!value) goto failed; if (PyObject_SetAttr(result, state->left, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_operator(state, o->v.BinOp.op); + value = ast2obj_operator(state, vstate, o->v.BinOp.op); if (!value) goto failed; if (PyObject_SetAttr(result, state->op, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_expr(state, o->v.BinOp.right); + value = ast2obj_expr(state, vstate, o->v.BinOp.right); if (!value) goto failed; if (PyObject_SetAttr(result, state->right, value) == -1) goto failed; @@ -4526,12 +4565,12 @@ ast2obj_expr(struct ast_state *state, void* _o) tp = (PyTypeObject *)state->UnaryOp_type; result = PyType_GenericNew(tp, NULL, NULL); if (!result) goto failed; - value = ast2obj_unaryop(state, o->v.UnaryOp.op); + value = ast2obj_unaryop(state, vstate, o->v.UnaryOp.op); if (!value) goto failed; if (PyObject_SetAttr(result, state->op, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_expr(state, o->v.UnaryOp.operand); + value = ast2obj_expr(state, vstate, o->v.UnaryOp.operand); if (!value) goto failed; if (PyObject_SetAttr(result, state->operand, value) == -1) goto failed; @@ -4541,12 +4580,12 @@ ast2obj_expr(struct ast_state *state, void* _o) tp = (PyTypeObject *)state->Lambda_type; result = PyType_GenericNew(tp, NULL, NULL); if (!result) goto failed; - value = ast2obj_arguments(state, o->v.Lambda.args); + value = ast2obj_arguments(state, vstate, o->v.Lambda.args); if (!value) goto failed; if (PyObject_SetAttr(result, state->args, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_expr(state, o->v.Lambda.body); + value = ast2obj_expr(state, vstate, o->v.Lambda.body); if (!value) goto failed; if (PyObject_SetAttr(result, state->body, value) == -1) goto failed; @@ -4556,17 +4595,17 @@ ast2obj_expr(struct ast_state *state, void* _o) tp = (PyTypeObject *)state->IfExp_type; result = PyType_GenericNew(tp, NULL, NULL); if (!result) goto failed; - value = ast2obj_expr(state, o->v.IfExp.test); + value = ast2obj_expr(state, vstate, o->v.IfExp.test); if (!value) goto failed; if (PyObject_SetAttr(result, state->test, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_expr(state, o->v.IfExp.body); + value = ast2obj_expr(state, vstate, o->v.IfExp.body); if (!value) goto failed; if (PyObject_SetAttr(result, state->body, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_expr(state, o->v.IfExp.orelse); + value = ast2obj_expr(state, vstate, o->v.IfExp.orelse); if (!value) goto failed; if (PyObject_SetAttr(result, state->orelse, value) == -1) goto failed; @@ -4576,12 +4615,14 @@ ast2obj_expr(struct ast_state *state, void* _o) tp = (PyTypeObject *)state->Dict_type; result = PyType_GenericNew(tp, NULL, NULL); if (!result) goto failed; - value = ast2obj_list(state, (asdl_seq*)o->v.Dict.keys, ast2obj_expr); + value = ast2obj_list(state, vstate, (asdl_seq*)o->v.Dict.keys, + ast2obj_expr); if (!value) goto failed; if (PyObject_SetAttr(result, state->keys, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_list(state, (asdl_seq*)o->v.Dict.values, ast2obj_expr); + value = ast2obj_list(state, vstate, (asdl_seq*)o->v.Dict.values, + ast2obj_expr); if (!value) goto failed; if (PyObject_SetAttr(result, state->values, value) == -1) goto failed; @@ -4591,7 +4632,8 @@ ast2obj_expr(struct ast_state *state, void* _o) tp = (PyTypeObject *)state->Set_type; result = PyType_GenericNew(tp, NULL, NULL); if (!result) goto failed; - value = ast2obj_list(state, (asdl_seq*)o->v.Set.elts, ast2obj_expr); + value = ast2obj_list(state, vstate, (asdl_seq*)o->v.Set.elts, + ast2obj_expr); if (!value) goto failed; if (PyObject_SetAttr(result, state->elts, value) == -1) goto failed; @@ -4601,12 +4643,13 @@ ast2obj_expr(struct ast_state *state, void* _o) tp = (PyTypeObject *)state->ListComp_type; result = PyType_GenericNew(tp, NULL, NULL); if (!result) goto failed; - value = ast2obj_expr(state, o->v.ListComp.elt); + value = ast2obj_expr(state, vstate, o->v.ListComp.elt); if (!value) goto failed; if (PyObject_SetAttr(result, state->elt, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_list(state, (asdl_seq*)o->v.ListComp.generators, + value = ast2obj_list(state, vstate, + (asdl_seq*)o->v.ListComp.generators, ast2obj_comprehension); if (!value) goto failed; if (PyObject_SetAttr(result, state->generators, value) == -1) @@ -4617,12 +4660,12 @@ ast2obj_expr(struct ast_state *state, void* _o) tp = (PyTypeObject *)state->SetComp_type; result = PyType_GenericNew(tp, NULL, NULL); if (!result) goto failed; - value = ast2obj_expr(state, o->v.SetComp.elt); + value = ast2obj_expr(state, vstate, o->v.SetComp.elt); if (!value) goto failed; if (PyObject_SetAttr(result, state->elt, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_list(state, (asdl_seq*)o->v.SetComp.generators, + value = ast2obj_list(state, vstate, (asdl_seq*)o->v.SetComp.generators, ast2obj_comprehension); if (!value) goto failed; if (PyObject_SetAttr(result, state->generators, value) == -1) @@ -4633,17 +4676,18 @@ ast2obj_expr(struct ast_state *state, void* _o) tp = (PyTypeObject *)state->DictComp_type; result = PyType_GenericNew(tp, NULL, NULL); if (!result) goto failed; - value = ast2obj_expr(state, o->v.DictComp.key); + value = ast2obj_expr(state, vstate, o->v.DictComp.key); if (!value) goto failed; if (PyObject_SetAttr(result, state->key, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_expr(state, o->v.DictComp.value); + value = ast2obj_expr(state, vstate, o->v.DictComp.value); if (!value) goto failed; if (PyObject_SetAttr(result, state->value, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_list(state, (asdl_seq*)o->v.DictComp.generators, + value = ast2obj_list(state, vstate, + (asdl_seq*)o->v.DictComp.generators, ast2obj_comprehension); if (!value) goto failed; if (PyObject_SetAttr(result, state->generators, value) == -1) @@ -4654,12 +4698,13 @@ ast2obj_expr(struct ast_state *state, void* _o) tp = (PyTypeObject *)state->GeneratorExp_type; result = PyType_GenericNew(tp, NULL, NULL); if (!result) goto failed; - value = ast2obj_expr(state, o->v.GeneratorExp.elt); + value = ast2obj_expr(state, vstate, o->v.GeneratorExp.elt); if (!value) goto failed; if (PyObject_SetAttr(result, state->elt, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_list(state, (asdl_seq*)o->v.GeneratorExp.generators, + value = ast2obj_list(state, vstate, + (asdl_seq*)o->v.GeneratorExp.generators, ast2obj_comprehension); if (!value) goto failed; if (PyObject_SetAttr(result, state->generators, value) == -1) @@ -4670,7 +4715,7 @@ ast2obj_expr(struct ast_state *state, void* _o) tp = (PyTypeObject *)state->Await_type; result = PyType_GenericNew(tp, NULL, NULL); if (!result) goto failed; - value = ast2obj_expr(state, o->v.Await.value); + value = ast2obj_expr(state, vstate, o->v.Await.value); if (!value) goto failed; if (PyObject_SetAttr(result, state->value, value) == -1) goto failed; @@ -4680,7 +4725,7 @@ ast2obj_expr(struct ast_state *state, void* _o) tp = (PyTypeObject *)state->Yield_type; result = PyType_GenericNew(tp, NULL, NULL); if (!result) goto failed; - value = ast2obj_expr(state, o->v.Yield.value); + value = ast2obj_expr(state, vstate, o->v.Yield.value); if (!value) goto failed; if (PyObject_SetAttr(result, state->value, value) == -1) goto failed; @@ -4690,7 +4735,7 @@ ast2obj_expr(struct ast_state *state, void* _o) tp = (PyTypeObject *)state->YieldFrom_type; result = PyType_GenericNew(tp, NULL, NULL); if (!result) goto failed; - value = ast2obj_expr(state, o->v.YieldFrom.value); + value = ast2obj_expr(state, vstate, o->v.YieldFrom.value); if (!value) goto failed; if (PyObject_SetAttr(result, state->value, value) == -1) goto failed; @@ -4700,7 +4745,7 @@ ast2obj_expr(struct ast_state *state, void* _o) tp = (PyTypeObject *)state->Compare_type; result = PyType_GenericNew(tp, NULL, NULL); if (!result) goto failed; - value = ast2obj_expr(state, o->v.Compare.left); + value = ast2obj_expr(state, vstate, o->v.Compare.left); if (!value) goto failed; if (PyObject_SetAttr(result, state->left, value) == -1) goto failed; @@ -4710,14 +4755,14 @@ ast2obj_expr(struct ast_state *state, void* _o) value = PyList_New(n); if (!value) goto failed; for(i = 0; i < n; i++) - PyList_SET_ITEM(value, i, ast2obj_cmpop(state, (cmpop_ty)asdl_seq_GET(o->v.Compare.ops, i))); + PyList_SET_ITEM(value, i, ast2obj_cmpop(state, vstate, (cmpop_ty)asdl_seq_GET(o->v.Compare.ops, i))); } if (!value) goto failed; if (PyObject_SetAttr(result, state->ops, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_list(state, (asdl_seq*)o->v.Compare.comparators, - ast2obj_expr); + value = ast2obj_list(state, vstate, + (asdl_seq*)o->v.Compare.comparators, ast2obj_expr); if (!value) goto failed; if (PyObject_SetAttr(result, state->comparators, value) == -1) goto failed; @@ -4727,17 +4772,18 @@ ast2obj_expr(struct ast_state *state, void* _o) tp = (PyTypeObject *)state->Call_type; result = PyType_GenericNew(tp, NULL, NULL); if (!result) goto failed; - value = ast2obj_expr(state, o->v.Call.func); + value = ast2obj_expr(state, vstate, o->v.Call.func); if (!value) goto failed; if (PyObject_SetAttr(result, state->func, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_list(state, (asdl_seq*)o->v.Call.args, ast2obj_expr); + value = ast2obj_list(state, vstate, (asdl_seq*)o->v.Call.args, + ast2obj_expr); if (!value) goto failed; if (PyObject_SetAttr(result, state->args, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_list(state, (asdl_seq*)o->v.Call.keywords, + value = ast2obj_list(state, vstate, (asdl_seq*)o->v.Call.keywords, ast2obj_keyword); if (!value) goto failed; if (PyObject_SetAttr(result, state->keywords, value) == -1) @@ -4748,17 +4794,17 @@ ast2obj_expr(struct ast_state *state, void* _o) tp = (PyTypeObject *)state->FormattedValue_type; result = PyType_GenericNew(tp, NULL, NULL); if (!result) goto failed; - value = ast2obj_expr(state, o->v.FormattedValue.value); + value = ast2obj_expr(state, vstate, o->v.FormattedValue.value); if (!value) goto failed; if (PyObject_SetAttr(result, state->value, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_int(state, o->v.FormattedValue.conversion); + value = ast2obj_int(state, vstate, o->v.FormattedValue.conversion); if (!value) goto failed; if (PyObject_SetAttr(result, state->conversion, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_expr(state, o->v.FormattedValue.format_spec); + value = ast2obj_expr(state, vstate, o->v.FormattedValue.format_spec); if (!value) goto failed; if (PyObject_SetAttr(result, state->format_spec, value) == -1) goto failed; @@ -4768,7 +4814,7 @@ ast2obj_expr(struct ast_state *state, void* _o) tp = (PyTypeObject *)state->JoinedStr_type; result = PyType_GenericNew(tp, NULL, NULL); if (!result) goto failed; - value = ast2obj_list(state, (asdl_seq*)o->v.JoinedStr.values, + value = ast2obj_list(state, vstate, (asdl_seq*)o->v.JoinedStr.values, ast2obj_expr); if (!value) goto failed; if (PyObject_SetAttr(result, state->values, value) == -1) @@ -4779,12 +4825,12 @@ ast2obj_expr(struct ast_state *state, void* _o) tp = (PyTypeObject *)state->Constant_type; result = PyType_GenericNew(tp, NULL, NULL); if (!result) goto failed; - value = ast2obj_constant(state, o->v.Constant.value); + value = ast2obj_constant(state, vstate, o->v.Constant.value); if (!value) goto failed; if (PyObject_SetAttr(result, state->value, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_string(state, o->v.Constant.kind); + value = ast2obj_string(state, vstate, o->v.Constant.kind); if (!value) goto failed; if (PyObject_SetAttr(result, state->kind, value) == -1) goto failed; @@ -4794,17 +4840,17 @@ ast2obj_expr(struct ast_state *state, void* _o) tp = (PyTypeObject *)state->Attribute_type; result = PyType_GenericNew(tp, NULL, NULL); if (!result) goto failed; - value = ast2obj_expr(state, o->v.Attribute.value); + value = ast2obj_expr(state, vstate, o->v.Attribute.value); if (!value) goto failed; if (PyObject_SetAttr(result, state->value, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_identifier(state, o->v.Attribute.attr); + value = ast2obj_identifier(state, vstate, o->v.Attribute.attr); if (!value) goto failed; if (PyObject_SetAttr(result, state->attr, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_expr_context(state, o->v.Attribute.ctx); + value = ast2obj_expr_context(state, vstate, o->v.Attribute.ctx); if (!value) goto failed; if (PyObject_SetAttr(result, state->ctx, value) == -1) goto failed; @@ -4814,17 +4860,17 @@ ast2obj_expr(struct ast_state *state, void* _o) tp = (PyTypeObject *)state->Subscript_type; result = PyType_GenericNew(tp, NULL, NULL); if (!result) goto failed; - value = ast2obj_expr(state, o->v.Subscript.value); + value = ast2obj_expr(state, vstate, o->v.Subscript.value); if (!value) goto failed; if (PyObject_SetAttr(result, state->value, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_expr(state, o->v.Subscript.slice); + value = ast2obj_expr(state, vstate, o->v.Subscript.slice); if (!value) goto failed; if (PyObject_SetAttr(result, state->slice, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_expr_context(state, o->v.Subscript.ctx); + value = ast2obj_expr_context(state, vstate, o->v.Subscript.ctx); if (!value) goto failed; if (PyObject_SetAttr(result, state->ctx, value) == -1) goto failed; @@ -4834,12 +4880,12 @@ ast2obj_expr(struct ast_state *state, void* _o) tp = (PyTypeObject *)state->Starred_type; result = PyType_GenericNew(tp, NULL, NULL); if (!result) goto failed; - value = ast2obj_expr(state, o->v.Starred.value); + value = ast2obj_expr(state, vstate, o->v.Starred.value); if (!value) goto failed; if (PyObject_SetAttr(result, state->value, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_expr_context(state, o->v.Starred.ctx); + value = ast2obj_expr_context(state, vstate, o->v.Starred.ctx); if (!value) goto failed; if (PyObject_SetAttr(result, state->ctx, value) == -1) goto failed; @@ -4849,12 +4895,12 @@ ast2obj_expr(struct ast_state *state, void* _o) tp = (PyTypeObject *)state->Name_type; result = PyType_GenericNew(tp, NULL, NULL); if (!result) goto failed; - value = ast2obj_identifier(state, o->v.Name.id); + value = ast2obj_identifier(state, vstate, o->v.Name.id); if (!value) goto failed; if (PyObject_SetAttr(result, state->id, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_expr_context(state, o->v.Name.ctx); + value = ast2obj_expr_context(state, vstate, o->v.Name.ctx); if (!value) goto failed; if (PyObject_SetAttr(result, state->ctx, value) == -1) goto failed; @@ -4864,12 +4910,13 @@ ast2obj_expr(struct ast_state *state, void* _o) tp = (PyTypeObject *)state->List_type; result = PyType_GenericNew(tp, NULL, NULL); if (!result) goto failed; - value = ast2obj_list(state, (asdl_seq*)o->v.List.elts, ast2obj_expr); + value = ast2obj_list(state, vstate, (asdl_seq*)o->v.List.elts, + ast2obj_expr); if (!value) goto failed; if (PyObject_SetAttr(result, state->elts, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_expr_context(state, o->v.List.ctx); + value = ast2obj_expr_context(state, vstate, o->v.List.ctx); if (!value) goto failed; if (PyObject_SetAttr(result, state->ctx, value) == -1) goto failed; @@ -4879,12 +4926,13 @@ ast2obj_expr(struct ast_state *state, void* _o) tp = (PyTypeObject *)state->Tuple_type; result = PyType_GenericNew(tp, NULL, NULL); if (!result) goto failed; - value = ast2obj_list(state, (asdl_seq*)o->v.Tuple.elts, ast2obj_expr); + value = ast2obj_list(state, vstate, (asdl_seq*)o->v.Tuple.elts, + ast2obj_expr); if (!value) goto failed; if (PyObject_SetAttr(result, state->elts, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_expr_context(state, o->v.Tuple.ctx); + value = ast2obj_expr_context(state, vstate, o->v.Tuple.ctx); if (!value) goto failed; if (PyObject_SetAttr(result, state->ctx, value) == -1) goto failed; @@ -4894,52 +4942,54 @@ ast2obj_expr(struct ast_state *state, void* _o) tp = (PyTypeObject *)state->Slice_type; result = PyType_GenericNew(tp, NULL, NULL); if (!result) goto failed; - value = ast2obj_expr(state, o->v.Slice.lower); + value = ast2obj_expr(state, vstate, o->v.Slice.lower); if (!value) goto failed; if (PyObject_SetAttr(result, state->lower, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_expr(state, o->v.Slice.upper); + value = ast2obj_expr(state, vstate, o->v.Slice.upper); if (!value) goto failed; if (PyObject_SetAttr(result, state->upper, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_expr(state, o->v.Slice.step); + value = ast2obj_expr(state, vstate, o->v.Slice.step); if (!value) goto failed; if (PyObject_SetAttr(result, state->step, value) == -1) goto failed; Py_DECREF(value); break; } - value = ast2obj_int(state, o->lineno); + value = ast2obj_int(state, vstate, o->lineno); if (!value) goto failed; if (PyObject_SetAttr(result, state->lineno, value) < 0) goto failed; Py_DECREF(value); - value = ast2obj_int(state, o->col_offset); + value = ast2obj_int(state, vstate, o->col_offset); if (!value) goto failed; if (PyObject_SetAttr(result, state->col_offset, value) < 0) goto failed; Py_DECREF(value); - value = ast2obj_int(state, o->end_lineno); + value = ast2obj_int(state, vstate, o->end_lineno); if (!value) goto failed; if (PyObject_SetAttr(result, state->end_lineno, value) < 0) goto failed; Py_DECREF(value); - value = ast2obj_int(state, o->end_col_offset); + value = ast2obj_int(state, vstate, o->end_col_offset); if (!value) goto failed; if (PyObject_SetAttr(result, state->end_col_offset, value) < 0) goto failed; Py_DECREF(value); - state->recursion_depth--; + vstate->recursion_depth--; return result; failed: + vstate->recursion_depth--; Py_XDECREF(value); Py_XDECREF(result); return NULL; } -PyObject* ast2obj_expr_context(struct ast_state *state, expr_context_ty o) +PyObject* ast2obj_expr_context(struct ast_state *state, struct validator + *vstate, expr_context_ty o) { switch(o) { case Load: @@ -4951,7 +5001,8 @@ PyObject* ast2obj_expr_context(struct ast_state *state, expr_context_ty o) } Py_UNREACHABLE(); } -PyObject* ast2obj_boolop(struct ast_state *state, boolop_ty o) +PyObject* ast2obj_boolop(struct ast_state *state, struct validator *vstate, + boolop_ty o) { switch(o) { case And: @@ -4961,7 +5012,8 @@ PyObject* ast2obj_boolop(struct ast_state *state, boolop_ty o) } Py_UNREACHABLE(); } -PyObject* ast2obj_operator(struct ast_state *state, operator_ty o) +PyObject* ast2obj_operator(struct ast_state *state, struct validator *vstate, + operator_ty o) { switch(o) { case Add: @@ -4993,7 +5045,8 @@ PyObject* ast2obj_operator(struct ast_state *state, operator_ty o) } Py_UNREACHABLE(); } -PyObject* ast2obj_unaryop(struct ast_state *state, unaryop_ty o) +PyObject* ast2obj_unaryop(struct ast_state *state, struct validator *vstate, + unaryop_ty o) { switch(o) { case Invert: @@ -5007,7 +5060,8 @@ PyObject* ast2obj_unaryop(struct ast_state *state, unaryop_ty o) } Py_UNREACHABLE(); } -PyObject* ast2obj_cmpop(struct ast_state *state, cmpop_ty o) +PyObject* ast2obj_cmpop(struct ast_state *state, struct validator *vstate, + cmpop_ty o) { switch(o) { case Eq: @@ -5034,7 +5088,8 @@ PyObject* ast2obj_cmpop(struct ast_state *state, cmpop_ty o) Py_UNREACHABLE(); } PyObject* -ast2obj_comprehension(struct ast_state *state, void* _o) +ast2obj_comprehension(struct ast_state *state, struct validator *vstate, void* + _o) { comprehension_ty o = (comprehension_ty)_o; PyObject *result = NULL, *value = NULL; @@ -5042,44 +5097,46 @@ ast2obj_comprehension(struct ast_state *state, void* _o) if (!o) { Py_RETURN_NONE; } - if (++state->recursion_depth > state->recursion_limit) { + if (++vstate->recursion_depth > vstate->recursion_limit) { PyErr_SetString(PyExc_RecursionError, "maximum recursion depth exceeded during ast construction"); - return 0; + return NULL; } tp = (PyTypeObject *)state->comprehension_type; result = PyType_GenericNew(tp, NULL, NULL); if (!result) return NULL; - value = ast2obj_expr(state, o->target); + value = ast2obj_expr(state, vstate, o->target); if (!value) goto failed; if (PyObject_SetAttr(result, state->target, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_expr(state, o->iter); + value = ast2obj_expr(state, vstate, o->iter); if (!value) goto failed; if (PyObject_SetAttr(result, state->iter, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_list(state, (asdl_seq*)o->ifs, ast2obj_expr); + value = ast2obj_list(state, vstate, (asdl_seq*)o->ifs, ast2obj_expr); if (!value) goto failed; if (PyObject_SetAttr(result, state->ifs, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_int(state, o->is_async); + value = ast2obj_int(state, vstate, o->is_async); if (!value) goto failed; if (PyObject_SetAttr(result, state->is_async, value) == -1) goto failed; Py_DECREF(value); - state->recursion_depth--; + vstate->recursion_depth--; return result; failed: + vstate->recursion_depth--; Py_XDECREF(value); Py_XDECREF(result); return NULL; } PyObject* -ast2obj_excepthandler(struct ast_state *state, void* _o) +ast2obj_excepthandler(struct ast_state *state, struct validator *vstate, void* + _o) { excepthandler_ty o = (excepthandler_ty)_o; PyObject *result = NULL, *value = NULL; @@ -5087,27 +5144,27 @@ ast2obj_excepthandler(struct ast_state *state, void* _o) if (!o) { Py_RETURN_NONE; } - if (++state->recursion_depth > state->recursion_limit) { + if (++vstate->recursion_depth > vstate->recursion_limit) { PyErr_SetString(PyExc_RecursionError, "maximum recursion depth exceeded during ast construction"); - return 0; + return NULL; } switch (o->kind) { case ExceptHandler_kind: tp = (PyTypeObject *)state->ExceptHandler_type; result = PyType_GenericNew(tp, NULL, NULL); if (!result) goto failed; - value = ast2obj_expr(state, o->v.ExceptHandler.type); + value = ast2obj_expr(state, vstate, o->v.ExceptHandler.type); if (!value) goto failed; if (PyObject_SetAttr(result, state->type, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_identifier(state, o->v.ExceptHandler.name); + value = ast2obj_identifier(state, vstate, o->v.ExceptHandler.name); if (!value) goto failed; if (PyObject_SetAttr(result, state->name, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_list(state, (asdl_seq*)o->v.ExceptHandler.body, + value = ast2obj_list(state, vstate, (asdl_seq*)o->v.ExceptHandler.body, ast2obj_stmt); if (!value) goto failed; if (PyObject_SetAttr(result, state->body, value) == -1) @@ -5115,36 +5172,37 @@ ast2obj_excepthandler(struct ast_state *state, void* _o) Py_DECREF(value); break; } - value = ast2obj_int(state, o->lineno); + value = ast2obj_int(state, vstate, o->lineno); if (!value) goto failed; if (PyObject_SetAttr(result, state->lineno, value) < 0) goto failed; Py_DECREF(value); - value = ast2obj_int(state, o->col_offset); + value = ast2obj_int(state, vstate, o->col_offset); if (!value) goto failed; if (PyObject_SetAttr(result, state->col_offset, value) < 0) goto failed; Py_DECREF(value); - value = ast2obj_int(state, o->end_lineno); + value = ast2obj_int(state, vstate, o->end_lineno); if (!value) goto failed; if (PyObject_SetAttr(result, state->end_lineno, value) < 0) goto failed; Py_DECREF(value); - value = ast2obj_int(state, o->end_col_offset); + value = ast2obj_int(state, vstate, o->end_col_offset); if (!value) goto failed; if (PyObject_SetAttr(result, state->end_col_offset, value) < 0) goto failed; Py_DECREF(value); - state->recursion_depth--; + vstate->recursion_depth--; return result; failed: + vstate->recursion_depth--; Py_XDECREF(value); Py_XDECREF(result); return NULL; } PyObject* -ast2obj_arguments(struct ast_state *state, void* _o) +ast2obj_arguments(struct ast_state *state, struct validator *vstate, void* _o) { arguments_ty o = (arguments_ty)_o; PyObject *result = NULL, *value = NULL; @@ -5152,59 +5210,61 @@ ast2obj_arguments(struct ast_state *state, void* _o) if (!o) { Py_RETURN_NONE; } - if (++state->recursion_depth > state->recursion_limit) { + if (++vstate->recursion_depth > vstate->recursion_limit) { PyErr_SetString(PyExc_RecursionError, "maximum recursion depth exceeded during ast construction"); - return 0; + return NULL; } tp = (PyTypeObject *)state->arguments_type; result = PyType_GenericNew(tp, NULL, NULL); if (!result) return NULL; - value = ast2obj_list(state, (asdl_seq*)o->posonlyargs, ast2obj_arg); + value = ast2obj_list(state, vstate, (asdl_seq*)o->posonlyargs, ast2obj_arg); if (!value) goto failed; if (PyObject_SetAttr(result, state->posonlyargs, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_list(state, (asdl_seq*)o->args, ast2obj_arg); + value = ast2obj_list(state, vstate, (asdl_seq*)o->args, ast2obj_arg); if (!value) goto failed; if (PyObject_SetAttr(result, state->args, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_arg(state, o->vararg); + value = ast2obj_arg(state, vstate, o->vararg); if (!value) goto failed; if (PyObject_SetAttr(result, state->vararg, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_list(state, (asdl_seq*)o->kwonlyargs, ast2obj_arg); + value = ast2obj_list(state, vstate, (asdl_seq*)o->kwonlyargs, ast2obj_arg); if (!value) goto failed; if (PyObject_SetAttr(result, state->kwonlyargs, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_list(state, (asdl_seq*)o->kw_defaults, ast2obj_expr); + value = ast2obj_list(state, vstate, (asdl_seq*)o->kw_defaults, + ast2obj_expr); if (!value) goto failed; if (PyObject_SetAttr(result, state->kw_defaults, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_arg(state, o->kwarg); + value = ast2obj_arg(state, vstate, o->kwarg); if (!value) goto failed; if (PyObject_SetAttr(result, state->kwarg, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_list(state, (asdl_seq*)o->defaults, ast2obj_expr); + value = ast2obj_list(state, vstate, (asdl_seq*)o->defaults, ast2obj_expr); if (!value) goto failed; if (PyObject_SetAttr(result, state->defaults, value) == -1) goto failed; Py_DECREF(value); - state->recursion_depth--; + vstate->recursion_depth--; return result; failed: + vstate->recursion_depth--; Py_XDECREF(value); Py_XDECREF(result); return NULL; } PyObject* -ast2obj_arg(struct ast_state *state, void* _o) +ast2obj_arg(struct ast_state *state, struct validator *vstate, void* _o) { arg_ty o = (arg_ty)_o; PyObject *result = NULL, *value = NULL; @@ -5212,59 +5272,60 @@ ast2obj_arg(struct ast_state *state, void* _o) if (!o) { Py_RETURN_NONE; } - if (++state->recursion_depth > state->recursion_limit) { + if (++vstate->recursion_depth > vstate->recursion_limit) { PyErr_SetString(PyExc_RecursionError, "maximum recursion depth exceeded during ast construction"); - return 0; + return NULL; } tp = (PyTypeObject *)state->arg_type; result = PyType_GenericNew(tp, NULL, NULL); if (!result) return NULL; - value = ast2obj_identifier(state, o->arg); + value = ast2obj_identifier(state, vstate, o->arg); if (!value) goto failed; if (PyObject_SetAttr(result, state->arg, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_expr(state, o->annotation); + value = ast2obj_expr(state, vstate, o->annotation); if (!value) goto failed; if (PyObject_SetAttr(result, state->annotation, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_string(state, o->type_comment); + value = ast2obj_string(state, vstate, o->type_comment); if (!value) goto failed; if (PyObject_SetAttr(result, state->type_comment, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_int(state, o->lineno); + value = ast2obj_int(state, vstate, o->lineno); if (!value) goto failed; if (PyObject_SetAttr(result, state->lineno, value) < 0) goto failed; Py_DECREF(value); - value = ast2obj_int(state, o->col_offset); + value = ast2obj_int(state, vstate, o->col_offset); if (!value) goto failed; if (PyObject_SetAttr(result, state->col_offset, value) < 0) goto failed; Py_DECREF(value); - value = ast2obj_int(state, o->end_lineno); + value = ast2obj_int(state, vstate, o->end_lineno); if (!value) goto failed; if (PyObject_SetAttr(result, state->end_lineno, value) < 0) goto failed; Py_DECREF(value); - value = ast2obj_int(state, o->end_col_offset); + value = ast2obj_int(state, vstate, o->end_col_offset); if (!value) goto failed; if (PyObject_SetAttr(result, state->end_col_offset, value) < 0) goto failed; Py_DECREF(value); - state->recursion_depth--; + vstate->recursion_depth--; return result; failed: + vstate->recursion_depth--; Py_XDECREF(value); Py_XDECREF(result); return NULL; } PyObject* -ast2obj_keyword(struct ast_state *state, void* _o) +ast2obj_keyword(struct ast_state *state, struct validator *vstate, void* _o) { keyword_ty o = (keyword_ty)_o; PyObject *result = NULL, *value = NULL; @@ -5272,54 +5333,55 @@ ast2obj_keyword(struct ast_state *state, void* _o) if (!o) { Py_RETURN_NONE; } - if (++state->recursion_depth > state->recursion_limit) { + if (++vstate->recursion_depth > vstate->recursion_limit) { PyErr_SetString(PyExc_RecursionError, "maximum recursion depth exceeded during ast construction"); - return 0; + return NULL; } tp = (PyTypeObject *)state->keyword_type; result = PyType_GenericNew(tp, NULL, NULL); if (!result) return NULL; - value = ast2obj_identifier(state, o->arg); + value = ast2obj_identifier(state, vstate, o->arg); if (!value) goto failed; if (PyObject_SetAttr(result, state->arg, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_expr(state, o->value); + value = ast2obj_expr(state, vstate, o->value); if (!value) goto failed; if (PyObject_SetAttr(result, state->value, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_int(state, o->lineno); + value = ast2obj_int(state, vstate, o->lineno); if (!value) goto failed; if (PyObject_SetAttr(result, state->lineno, value) < 0) goto failed; Py_DECREF(value); - value = ast2obj_int(state, o->col_offset); + value = ast2obj_int(state, vstate, o->col_offset); if (!value) goto failed; if (PyObject_SetAttr(result, state->col_offset, value) < 0) goto failed; Py_DECREF(value); - value = ast2obj_int(state, o->end_lineno); + value = ast2obj_int(state, vstate, o->end_lineno); if (!value) goto failed; if (PyObject_SetAttr(result, state->end_lineno, value) < 0) goto failed; Py_DECREF(value); - value = ast2obj_int(state, o->end_col_offset); + value = ast2obj_int(state, vstate, o->end_col_offset); if (!value) goto failed; if (PyObject_SetAttr(result, state->end_col_offset, value) < 0) goto failed; Py_DECREF(value); - state->recursion_depth--; + vstate->recursion_depth--; return result; failed: + vstate->recursion_depth--; Py_XDECREF(value); Py_XDECREF(result); return NULL; } PyObject* -ast2obj_alias(struct ast_state *state, void* _o) +ast2obj_alias(struct ast_state *state, struct validator *vstate, void* _o) { alias_ty o = (alias_ty)_o; PyObject *result = NULL, *value = NULL; @@ -5327,54 +5389,55 @@ ast2obj_alias(struct ast_state *state, void* _o) if (!o) { Py_RETURN_NONE; } - if (++state->recursion_depth > state->recursion_limit) { + if (++vstate->recursion_depth > vstate->recursion_limit) { PyErr_SetString(PyExc_RecursionError, "maximum recursion depth exceeded during ast construction"); - return 0; + return NULL; } tp = (PyTypeObject *)state->alias_type; result = PyType_GenericNew(tp, NULL, NULL); if (!result) return NULL; - value = ast2obj_identifier(state, o->name); + value = ast2obj_identifier(state, vstate, o->name); if (!value) goto failed; if (PyObject_SetAttr(result, state->name, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_identifier(state, o->asname); + value = ast2obj_identifier(state, vstate, o->asname); if (!value) goto failed; if (PyObject_SetAttr(result, state->asname, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_int(state, o->lineno); + value = ast2obj_int(state, vstate, o->lineno); if (!value) goto failed; if (PyObject_SetAttr(result, state->lineno, value) < 0) goto failed; Py_DECREF(value); - value = ast2obj_int(state, o->col_offset); + value = ast2obj_int(state, vstate, o->col_offset); if (!value) goto failed; if (PyObject_SetAttr(result, state->col_offset, value) < 0) goto failed; Py_DECREF(value); - value = ast2obj_int(state, o->end_lineno); + value = ast2obj_int(state, vstate, o->end_lineno); if (!value) goto failed; if (PyObject_SetAttr(result, state->end_lineno, value) < 0) goto failed; Py_DECREF(value); - value = ast2obj_int(state, o->end_col_offset); + value = ast2obj_int(state, vstate, o->end_col_offset); if (!value) goto failed; if (PyObject_SetAttr(result, state->end_col_offset, value) < 0) goto failed; Py_DECREF(value); - state->recursion_depth--; + vstate->recursion_depth--; return result; failed: + vstate->recursion_depth--; Py_XDECREF(value); Py_XDECREF(result); return NULL; } PyObject* -ast2obj_withitem(struct ast_state *state, void* _o) +ast2obj_withitem(struct ast_state *state, struct validator *vstate, void* _o) { withitem_ty o = (withitem_ty)_o; PyObject *result = NULL, *value = NULL; @@ -5382,34 +5445,35 @@ ast2obj_withitem(struct ast_state *state, void* _o) if (!o) { Py_RETURN_NONE; } - if (++state->recursion_depth > state->recursion_limit) { + if (++vstate->recursion_depth > vstate->recursion_limit) { PyErr_SetString(PyExc_RecursionError, "maximum recursion depth exceeded during ast construction"); - return 0; + return NULL; } tp = (PyTypeObject *)state->withitem_type; result = PyType_GenericNew(tp, NULL, NULL); if (!result) return NULL; - value = ast2obj_expr(state, o->context_expr); + value = ast2obj_expr(state, vstate, o->context_expr); if (!value) goto failed; if (PyObject_SetAttr(result, state->context_expr, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_expr(state, o->optional_vars); + value = ast2obj_expr(state, vstate, o->optional_vars); if (!value) goto failed; if (PyObject_SetAttr(result, state->optional_vars, value) == -1) goto failed; Py_DECREF(value); - state->recursion_depth--; + vstate->recursion_depth--; return result; failed: + vstate->recursion_depth--; Py_XDECREF(value); Py_XDECREF(result); return NULL; } PyObject* -ast2obj_match_case(struct ast_state *state, void* _o) +ast2obj_match_case(struct ast_state *state, struct validator *vstate, void* _o) { match_case_ty o = (match_case_ty)_o; PyObject *result = NULL, *value = NULL; @@ -5417,39 +5481,40 @@ ast2obj_match_case(struct ast_state *state, void* _o) if (!o) { Py_RETURN_NONE; } - if (++state->recursion_depth > state->recursion_limit) { + if (++vstate->recursion_depth > vstate->recursion_limit) { PyErr_SetString(PyExc_RecursionError, "maximum recursion depth exceeded during ast construction"); - return 0; + return NULL; } tp = (PyTypeObject *)state->match_case_type; result = PyType_GenericNew(tp, NULL, NULL); if (!result) return NULL; - value = ast2obj_pattern(state, o->pattern); + value = ast2obj_pattern(state, vstate, o->pattern); if (!value) goto failed; if (PyObject_SetAttr(result, state->pattern, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_expr(state, o->guard); + value = ast2obj_expr(state, vstate, o->guard); if (!value) goto failed; if (PyObject_SetAttr(result, state->guard, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_list(state, (asdl_seq*)o->body, ast2obj_stmt); + value = ast2obj_list(state, vstate, (asdl_seq*)o->body, ast2obj_stmt); if (!value) goto failed; if (PyObject_SetAttr(result, state->body, value) == -1) goto failed; Py_DECREF(value); - state->recursion_depth--; + vstate->recursion_depth--; return result; failed: + vstate->recursion_depth--; Py_XDECREF(value); Py_XDECREF(result); return NULL; } PyObject* -ast2obj_pattern(struct ast_state *state, void* _o) +ast2obj_pattern(struct ast_state *state, struct validator *vstate, void* _o) { pattern_ty o = (pattern_ty)_o; PyObject *result = NULL, *value = NULL; @@ -5457,17 +5522,17 @@ ast2obj_pattern(struct ast_state *state, void* _o) if (!o) { Py_RETURN_NONE; } - if (++state->recursion_depth > state->recursion_limit) { + if (++vstate->recursion_depth > vstate->recursion_limit) { PyErr_SetString(PyExc_RecursionError, "maximum recursion depth exceeded during ast construction"); - return 0; + return NULL; } switch (o->kind) { case MatchValue_kind: tp = (PyTypeObject *)state->MatchValue_type; result = PyType_GenericNew(tp, NULL, NULL); if (!result) goto failed; - value = ast2obj_expr(state, o->v.MatchValue.value); + value = ast2obj_expr(state, vstate, o->v.MatchValue.value); if (!value) goto failed; if (PyObject_SetAttr(result, state->value, value) == -1) goto failed; @@ -5477,7 +5542,7 @@ ast2obj_pattern(struct ast_state *state, void* _o) tp = (PyTypeObject *)state->MatchSingleton_type; result = PyType_GenericNew(tp, NULL, NULL); if (!result) goto failed; - value = ast2obj_constant(state, o->v.MatchSingleton.value); + value = ast2obj_constant(state, vstate, o->v.MatchSingleton.value); if (!value) goto failed; if (PyObject_SetAttr(result, state->value, value) == -1) goto failed; @@ -5487,7 +5552,8 @@ ast2obj_pattern(struct ast_state *state, void* _o) tp = (PyTypeObject *)state->MatchSequence_type; result = PyType_GenericNew(tp, NULL, NULL); if (!result) goto failed; - value = ast2obj_list(state, (asdl_seq*)o->v.MatchSequence.patterns, + value = ast2obj_list(state, vstate, + (asdl_seq*)o->v.MatchSequence.patterns, ast2obj_pattern); if (!value) goto failed; if (PyObject_SetAttr(result, state->patterns, value) == -1) @@ -5498,19 +5564,20 @@ ast2obj_pattern(struct ast_state *state, void* _o) tp = (PyTypeObject *)state->MatchMapping_type; result = PyType_GenericNew(tp, NULL, NULL); if (!result) goto failed; - value = ast2obj_list(state, (asdl_seq*)o->v.MatchMapping.keys, + value = ast2obj_list(state, vstate, (asdl_seq*)o->v.MatchMapping.keys, ast2obj_expr); if (!value) goto failed; if (PyObject_SetAttr(result, state->keys, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_list(state, (asdl_seq*)o->v.MatchMapping.patterns, + value = ast2obj_list(state, vstate, + (asdl_seq*)o->v.MatchMapping.patterns, ast2obj_pattern); if (!value) goto failed; if (PyObject_SetAttr(result, state->patterns, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_identifier(state, o->v.MatchMapping.rest); + value = ast2obj_identifier(state, vstate, o->v.MatchMapping.rest); if (!value) goto failed; if (PyObject_SetAttr(result, state->rest, value) == -1) goto failed; @@ -5520,24 +5587,27 @@ ast2obj_pattern(struct ast_state *state, void* _o) tp = (PyTypeObject *)state->MatchClass_type; result = PyType_GenericNew(tp, NULL, NULL); if (!result) goto failed; - value = ast2obj_expr(state, o->v.MatchClass.cls); + value = ast2obj_expr(state, vstate, o->v.MatchClass.cls); if (!value) goto failed; if (PyObject_SetAttr(result, state->cls, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_list(state, (asdl_seq*)o->v.MatchClass.patterns, + value = ast2obj_list(state, vstate, + (asdl_seq*)o->v.MatchClass.patterns, ast2obj_pattern); if (!value) goto failed; if (PyObject_SetAttr(result, state->patterns, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_list(state, (asdl_seq*)o->v.MatchClass.kwd_attrs, + value = ast2obj_list(state, vstate, + (asdl_seq*)o->v.MatchClass.kwd_attrs, ast2obj_identifier); if (!value) goto failed; if (PyObject_SetAttr(result, state->kwd_attrs, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_list(state, (asdl_seq*)o->v.MatchClass.kwd_patterns, + value = ast2obj_list(state, vstate, + (asdl_seq*)o->v.MatchClass.kwd_patterns, ast2obj_pattern); if (!value) goto failed; if (PyObject_SetAttr(result, state->kwd_patterns, value) == -1) @@ -5548,7 +5618,7 @@ ast2obj_pattern(struct ast_state *state, void* _o) tp = (PyTypeObject *)state->MatchStar_type; result = PyType_GenericNew(tp, NULL, NULL); if (!result) goto failed; - value = ast2obj_identifier(state, o->v.MatchStar.name); + value = ast2obj_identifier(state, vstate, o->v.MatchStar.name); if (!value) goto failed; if (PyObject_SetAttr(result, state->name, value) == -1) goto failed; @@ -5558,12 +5628,12 @@ ast2obj_pattern(struct ast_state *state, void* _o) tp = (PyTypeObject *)state->MatchAs_type; result = PyType_GenericNew(tp, NULL, NULL); if (!result) goto failed; - value = ast2obj_pattern(state, o->v.MatchAs.pattern); + value = ast2obj_pattern(state, vstate, o->v.MatchAs.pattern); if (!value) goto failed; if (PyObject_SetAttr(result, state->pattern, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_identifier(state, o->v.MatchAs.name); + value = ast2obj_identifier(state, vstate, o->v.MatchAs.name); if (!value) goto failed; if (PyObject_SetAttr(result, state->name, value) == -1) goto failed; @@ -5573,7 +5643,7 @@ ast2obj_pattern(struct ast_state *state, void* _o) tp = (PyTypeObject *)state->MatchOr_type; result = PyType_GenericNew(tp, NULL, NULL); if (!result) goto failed; - value = ast2obj_list(state, (asdl_seq*)o->v.MatchOr.patterns, + value = ast2obj_list(state, vstate, (asdl_seq*)o->v.MatchOr.patterns, ast2obj_pattern); if (!value) goto failed; if (PyObject_SetAttr(result, state->patterns, value) == -1) @@ -5581,36 +5651,37 @@ ast2obj_pattern(struct ast_state *state, void* _o) Py_DECREF(value); break; } - value = ast2obj_int(state, o->lineno); + value = ast2obj_int(state, vstate, o->lineno); if (!value) goto failed; if (PyObject_SetAttr(result, state->lineno, value) < 0) goto failed; Py_DECREF(value); - value = ast2obj_int(state, o->col_offset); + value = ast2obj_int(state, vstate, o->col_offset); if (!value) goto failed; if (PyObject_SetAttr(result, state->col_offset, value) < 0) goto failed; Py_DECREF(value); - value = ast2obj_int(state, o->end_lineno); + value = ast2obj_int(state, vstate, o->end_lineno); if (!value) goto failed; if (PyObject_SetAttr(result, state->end_lineno, value) < 0) goto failed; Py_DECREF(value); - value = ast2obj_int(state, o->end_col_offset); + value = ast2obj_int(state, vstate, o->end_col_offset); if (!value) goto failed; if (PyObject_SetAttr(result, state->end_col_offset, value) < 0) goto failed; Py_DECREF(value); - state->recursion_depth--; + vstate->recursion_depth--; return result; failed: + vstate->recursion_depth--; Py_XDECREF(value); Py_XDECREF(result); return NULL; } PyObject* -ast2obj_type_ignore(struct ast_state *state, void* _o) +ast2obj_type_ignore(struct ast_state *state, struct validator *vstate, void* _o) { type_ignore_ty o = (type_ignore_ty)_o; PyObject *result = NULL, *value = NULL; @@ -5618,38 +5689,39 @@ ast2obj_type_ignore(struct ast_state *state, void* _o) if (!o) { Py_RETURN_NONE; } - if (++state->recursion_depth > state->recursion_limit) { + if (++vstate->recursion_depth > vstate->recursion_limit) { PyErr_SetString(PyExc_RecursionError, "maximum recursion depth exceeded during ast construction"); - return 0; + return NULL; } switch (o->kind) { case TypeIgnore_kind: tp = (PyTypeObject *)state->TypeIgnore_type; result = PyType_GenericNew(tp, NULL, NULL); if (!result) goto failed; - value = ast2obj_int(state, o->v.TypeIgnore.lineno); + value = ast2obj_int(state, vstate, o->v.TypeIgnore.lineno); if (!value) goto failed; if (PyObject_SetAttr(result, state->lineno, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_string(state, o->v.TypeIgnore.tag); + value = ast2obj_string(state, vstate, o->v.TypeIgnore.tag); if (!value) goto failed; if (PyObject_SetAttr(result, state->tag, value) == -1) goto failed; Py_DECREF(value); break; } - state->recursion_depth--; + vstate->recursion_depth--; return result; failed: + vstate->recursion_depth--; Py_XDECREF(value); Py_XDECREF(result); return NULL; } PyObject* -ast2obj_type_param(struct ast_state *state, void* _o) +ast2obj_type_param(struct ast_state *state, struct validator *vstate, void* _o) { type_param_ty o = (type_param_ty)_o; PyObject *result = NULL, *value = NULL; @@ -5657,22 +5729,22 @@ ast2obj_type_param(struct ast_state *state, void* _o) if (!o) { Py_RETURN_NONE; } - if (++state->recursion_depth > state->recursion_limit) { + if (++vstate->recursion_depth > vstate->recursion_limit) { PyErr_SetString(PyExc_RecursionError, "maximum recursion depth exceeded during ast construction"); - return 0; + return NULL; } switch (o->kind) { case TypeVar_kind: tp = (PyTypeObject *)state->TypeVar_type; result = PyType_GenericNew(tp, NULL, NULL); if (!result) goto failed; - value = ast2obj_identifier(state, o->v.TypeVar.name); + value = ast2obj_identifier(state, vstate, o->v.TypeVar.name); if (!value) goto failed; if (PyObject_SetAttr(result, state->name, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_expr(state, o->v.TypeVar.bound); + value = ast2obj_expr(state, vstate, o->v.TypeVar.bound); if (!value) goto failed; if (PyObject_SetAttr(result, state->bound, value) == -1) goto failed; @@ -5682,7 +5754,7 @@ ast2obj_type_param(struct ast_state *state, void* _o) tp = (PyTypeObject *)state->ParamSpec_type; result = PyType_GenericNew(tp, NULL, NULL); if (!result) goto failed; - value = ast2obj_identifier(state, o->v.ParamSpec.name); + value = ast2obj_identifier(state, vstate, o->v.ParamSpec.name); if (!value) goto failed; if (PyObject_SetAttr(result, state->name, value) == -1) goto failed; @@ -5692,36 +5764,37 @@ ast2obj_type_param(struct ast_state *state, void* _o) tp = (PyTypeObject *)state->TypeVarTuple_type; result = PyType_GenericNew(tp, NULL, NULL); if (!result) goto failed; - value = ast2obj_identifier(state, o->v.TypeVarTuple.name); + value = ast2obj_identifier(state, vstate, o->v.TypeVarTuple.name); if (!value) goto failed; if (PyObject_SetAttr(result, state->name, value) == -1) goto failed; Py_DECREF(value); break; } - value = ast2obj_int(state, o->lineno); + value = ast2obj_int(state, vstate, o->lineno); if (!value) goto failed; if (PyObject_SetAttr(result, state->lineno, value) < 0) goto failed; Py_DECREF(value); - value = ast2obj_int(state, o->col_offset); + value = ast2obj_int(state, vstate, o->col_offset); if (!value) goto failed; if (PyObject_SetAttr(result, state->col_offset, value) < 0) goto failed; Py_DECREF(value); - value = ast2obj_int(state, o->end_lineno); + value = ast2obj_int(state, vstate, o->end_lineno); if (!value) goto failed; if (PyObject_SetAttr(result, state->end_lineno, value) < 0) goto failed; Py_DECREF(value); - value = ast2obj_int(state, o->end_col_offset); + value = ast2obj_int(state, vstate, o->end_col_offset); if (!value) goto failed; if (PyObject_SetAttr(result, state->end_col_offset, value) < 0) goto failed; Py_DECREF(value); - state->recursion_depth--; + vstate->recursion_depth--; return result; failed: + vstate->recursion_depth--; Py_XDECREF(value); Py_XDECREF(result); return NULL; @@ -5743,19 +5816,19 @@ obj2ast_mod(struct ast_state *state, PyObject* obj, mod_ty* out, PyArena* arena) tp = state->Module_type; isinstance = PyObject_IsInstance(obj, tp); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { asdl_stmt_seq* body; asdl_type_ignore_seq* type_ignores; if (PyObject_GetOptionalAttr(obj, state->body, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { tmp = PyList_New(0); if (tmp == NULL) { - return 1; + return -1; } } { @@ -5788,12 +5861,12 @@ obj2ast_mod(struct ast_state *state, PyObject* obj, mod_ty* out, PyArena* arena) Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->type_ignores, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { tmp = PyList_New(0); if (tmp == NULL) { - return 1; + return -1; } } { @@ -5832,18 +5905,18 @@ obj2ast_mod(struct ast_state *state, PyObject* obj, mod_ty* out, PyArena* arena) tp = state->Interactive_type; isinstance = PyObject_IsInstance(obj, tp); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { asdl_stmt_seq* body; if (PyObject_GetOptionalAttr(obj, state->body, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { tmp = PyList_New(0); if (tmp == NULL) { - return 1; + return -1; } } { @@ -5882,17 +5955,17 @@ obj2ast_mod(struct ast_state *state, PyObject* obj, mod_ty* out, PyArena* arena) tp = state->Expression_type; isinstance = PyObject_IsInstance(obj, tp); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { expr_ty body; if (PyObject_GetOptionalAttr(obj, state->body, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"body\" missing from Expression"); - return 1; + return -1; } else { int res; @@ -5911,19 +5984,19 @@ obj2ast_mod(struct ast_state *state, PyObject* obj, mod_ty* out, PyArena* arena) tp = state->FunctionType_type; isinstance = PyObject_IsInstance(obj, tp); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { asdl_expr_seq* argtypes; expr_ty returns; if (PyObject_GetOptionalAttr(obj, state->argtypes, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { tmp = PyList_New(0); if (tmp == NULL) { - return 1; + return -1; } } { @@ -5956,11 +6029,11 @@ obj2ast_mod(struct ast_state *state, PyObject* obj, mod_ty* out, PyArena* arena) Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->returns, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"returns\" missing from FunctionType"); - return 1; + return -1; } else { int res; @@ -5980,7 +6053,7 @@ obj2ast_mod(struct ast_state *state, PyObject* obj, mod_ty* out, PyArena* arena) PyErr_Format(PyExc_TypeError, "expected some sort of mod, but got %R", obj); failed: Py_XDECREF(tmp); - return 1; + return -1; } int @@ -6001,11 +6074,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* return 0; } if (PyObject_GetOptionalAttr(obj, state->lineno, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"lineno\" missing from stmt"); - return 1; + return -1; } else { int res; @@ -6018,11 +6091,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->col_offset, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"col_offset\" missing from stmt"); - return 1; + return -1; } else { int res; @@ -6035,7 +6108,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->end_lineno, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL || tmp == Py_None) { Py_CLEAR(tmp); @@ -6052,7 +6125,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->end_col_offset, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL || tmp == Py_None) { Py_CLEAR(tmp); @@ -6071,7 +6144,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* tp = state->FunctionDef_type; isinstance = PyObject_IsInstance(obj, tp); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { identifier name; @@ -6083,11 +6156,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* asdl_type_param_seq* type_params; if (PyObject_GetOptionalAttr(obj, state->name, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"name\" missing from FunctionDef"); - return 1; + return -1; } else { int res; @@ -6100,11 +6173,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->args, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"args\" missing from FunctionDef"); - return 1; + return -1; } else { int res; @@ -6117,12 +6190,12 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->body, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { tmp = PyList_New(0); if (tmp == NULL) { - return 1; + return -1; } } { @@ -6155,12 +6228,12 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->decorator_list, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { tmp = PyList_New(0); if (tmp == NULL) { - return 1; + return -1; } } { @@ -6193,7 +6266,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->returns, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL || tmp == Py_None) { Py_CLEAR(tmp); @@ -6210,7 +6283,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->type_comment, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL || tmp == Py_None) { Py_CLEAR(tmp); @@ -6227,12 +6300,12 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->type_params, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { tmp = PyList_New(0); if (tmp == NULL) { - return 1; + return -1; } } { @@ -6274,7 +6347,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* tp = state->AsyncFunctionDef_type; isinstance = PyObject_IsInstance(obj, tp); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { identifier name; @@ -6286,11 +6359,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* asdl_type_param_seq* type_params; if (PyObject_GetOptionalAttr(obj, state->name, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"name\" missing from AsyncFunctionDef"); - return 1; + return -1; } else { int res; @@ -6303,11 +6376,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->args, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"args\" missing from AsyncFunctionDef"); - return 1; + return -1; } else { int res; @@ -6320,12 +6393,12 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->body, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { tmp = PyList_New(0); if (tmp == NULL) { - return 1; + return -1; } } { @@ -6358,12 +6431,12 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->decorator_list, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { tmp = PyList_New(0); if (tmp == NULL) { - return 1; + return -1; } } { @@ -6396,7 +6469,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->returns, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL || tmp == Py_None) { Py_CLEAR(tmp); @@ -6413,7 +6486,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->type_comment, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL || tmp == Py_None) { Py_CLEAR(tmp); @@ -6430,12 +6503,12 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->type_params, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { tmp = PyList_New(0); if (tmp == NULL) { - return 1; + return -1; } } { @@ -6477,7 +6550,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* tp = state->ClassDef_type; isinstance = PyObject_IsInstance(obj, tp); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { identifier name; @@ -6488,11 +6561,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* asdl_type_param_seq* type_params; if (PyObject_GetOptionalAttr(obj, state->name, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"name\" missing from ClassDef"); - return 1; + return -1; } else { int res; @@ -6505,12 +6578,12 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->bases, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { tmp = PyList_New(0); if (tmp == NULL) { - return 1; + return -1; } } { @@ -6543,12 +6616,12 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->keywords, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { tmp = PyList_New(0); if (tmp == NULL) { - return 1; + return -1; } } { @@ -6581,12 +6654,12 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->body, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { tmp = PyList_New(0); if (tmp == NULL) { - return 1; + return -1; } } { @@ -6619,12 +6692,12 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->decorator_list, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { tmp = PyList_New(0); if (tmp == NULL) { - return 1; + return -1; } } { @@ -6657,12 +6730,12 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->type_params, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { tmp = PyList_New(0); if (tmp == NULL) { - return 1; + return -1; } } { @@ -6703,13 +6776,13 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* tp = state->Return_type; isinstance = PyObject_IsInstance(obj, tp); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { expr_ty value; if (PyObject_GetOptionalAttr(obj, state->value, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL || tmp == Py_None) { Py_CLEAR(tmp); @@ -6733,18 +6806,18 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* tp = state->Delete_type; isinstance = PyObject_IsInstance(obj, tp); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { asdl_expr_seq* targets; if (PyObject_GetOptionalAttr(obj, state->targets, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { tmp = PyList_New(0); if (tmp == NULL) { - return 1; + return -1; } } { @@ -6784,7 +6857,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* tp = state->Assign_type; isinstance = PyObject_IsInstance(obj, tp); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { asdl_expr_seq* targets; @@ -6792,12 +6865,12 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* string type_comment; if (PyObject_GetOptionalAttr(obj, state->targets, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { tmp = PyList_New(0); if (tmp == NULL) { - return 1; + return -1; } } { @@ -6830,11 +6903,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->value, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"value\" missing from Assign"); - return 1; + return -1; } else { int res; @@ -6847,7 +6920,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->type_comment, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL || tmp == Py_None) { Py_CLEAR(tmp); @@ -6871,7 +6944,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* tp = state->TypeAlias_type; isinstance = PyObject_IsInstance(obj, tp); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { expr_ty name; @@ -6879,11 +6952,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* expr_ty value; if (PyObject_GetOptionalAttr(obj, state->name, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"name\" missing from TypeAlias"); - return 1; + return -1; } else { int res; @@ -6896,12 +6969,12 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->type_params, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { tmp = PyList_New(0); if (tmp == NULL) { - return 1; + return -1; } } { @@ -6934,11 +7007,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->value, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"value\" missing from TypeAlias"); - return 1; + return -1; } else { int res; @@ -6958,7 +7031,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* tp = state->AugAssign_type; isinstance = PyObject_IsInstance(obj, tp); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { expr_ty target; @@ -6966,11 +7039,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* expr_ty value; if (PyObject_GetOptionalAttr(obj, state->target, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"target\" missing from AugAssign"); - return 1; + return -1; } else { int res; @@ -6983,11 +7056,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->op, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"op\" missing from AugAssign"); - return 1; + return -1; } else { int res; @@ -7000,11 +7073,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->value, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"value\" missing from AugAssign"); - return 1; + return -1; } else { int res; @@ -7024,7 +7097,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* tp = state->AnnAssign_type; isinstance = PyObject_IsInstance(obj, tp); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { expr_ty target; @@ -7033,11 +7106,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* int simple; if (PyObject_GetOptionalAttr(obj, state->target, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"target\" missing from AnnAssign"); - return 1; + return -1; } else { int res; @@ -7050,11 +7123,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->annotation, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"annotation\" missing from AnnAssign"); - return 1; + return -1; } else { int res; @@ -7067,7 +7140,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->value, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL || tmp == Py_None) { Py_CLEAR(tmp); @@ -7084,11 +7157,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->simple, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"simple\" missing from AnnAssign"); - return 1; + return -1; } else { int res; @@ -7108,7 +7181,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* tp = state->For_type; isinstance = PyObject_IsInstance(obj, tp); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { expr_ty target; @@ -7118,11 +7191,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* string type_comment; if (PyObject_GetOptionalAttr(obj, state->target, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"target\" missing from For"); - return 1; + return -1; } else { int res; @@ -7135,11 +7208,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->iter, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"iter\" missing from For"); - return 1; + return -1; } else { int res; @@ -7152,12 +7225,12 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->body, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { tmp = PyList_New(0); if (tmp == NULL) { - return 1; + return -1; } } { @@ -7190,12 +7263,12 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->orelse, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { tmp = PyList_New(0); if (tmp == NULL) { - return 1; + return -1; } } { @@ -7228,7 +7301,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->type_comment, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL || tmp == Py_None) { Py_CLEAR(tmp); @@ -7252,7 +7325,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* tp = state->AsyncFor_type; isinstance = PyObject_IsInstance(obj, tp); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { expr_ty target; @@ -7262,11 +7335,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* string type_comment; if (PyObject_GetOptionalAttr(obj, state->target, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"target\" missing from AsyncFor"); - return 1; + return -1; } else { int res; @@ -7279,11 +7352,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->iter, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"iter\" missing from AsyncFor"); - return 1; + return -1; } else { int res; @@ -7296,12 +7369,12 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->body, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { tmp = PyList_New(0); if (tmp == NULL) { - return 1; + return -1; } } { @@ -7334,12 +7407,12 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->orelse, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { tmp = PyList_New(0); if (tmp == NULL) { - return 1; + return -1; } } { @@ -7372,7 +7445,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->type_comment, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL || tmp == Py_None) { Py_CLEAR(tmp); @@ -7397,7 +7470,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* tp = state->While_type; isinstance = PyObject_IsInstance(obj, tp); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { expr_ty test; @@ -7405,11 +7478,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* asdl_stmt_seq* orelse; if (PyObject_GetOptionalAttr(obj, state->test, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"test\" missing from While"); - return 1; + return -1; } else { int res; @@ -7422,12 +7495,12 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->body, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { tmp = PyList_New(0); if (tmp == NULL) { - return 1; + return -1; } } { @@ -7460,12 +7533,12 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->orelse, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { tmp = PyList_New(0); if (tmp == NULL) { - return 1; + return -1; } } { @@ -7505,7 +7578,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* tp = state->If_type; isinstance = PyObject_IsInstance(obj, tp); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { expr_ty test; @@ -7513,11 +7586,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* asdl_stmt_seq* orelse; if (PyObject_GetOptionalAttr(obj, state->test, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"test\" missing from If"); - return 1; + return -1; } else { int res; @@ -7530,12 +7603,12 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->body, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { tmp = PyList_New(0); if (tmp == NULL) { - return 1; + return -1; } } { @@ -7568,12 +7641,12 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->orelse, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { tmp = PyList_New(0); if (tmp == NULL) { - return 1; + return -1; } } { @@ -7613,7 +7686,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* tp = state->With_type; isinstance = PyObject_IsInstance(obj, tp); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { asdl_withitem_seq* items; @@ -7621,12 +7694,12 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* string type_comment; if (PyObject_GetOptionalAttr(obj, state->items, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { tmp = PyList_New(0); if (tmp == NULL) { - return 1; + return -1; } } { @@ -7659,12 +7732,12 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->body, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { tmp = PyList_New(0); if (tmp == NULL) { - return 1; + return -1; } } { @@ -7697,7 +7770,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->type_comment, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL || tmp == Py_None) { Py_CLEAR(tmp); @@ -7721,7 +7794,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* tp = state->AsyncWith_type; isinstance = PyObject_IsInstance(obj, tp); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { asdl_withitem_seq* items; @@ -7729,12 +7802,12 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* string type_comment; if (PyObject_GetOptionalAttr(obj, state->items, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { tmp = PyList_New(0); if (tmp == NULL) { - return 1; + return -1; } } { @@ -7767,12 +7840,12 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->body, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { tmp = PyList_New(0); if (tmp == NULL) { - return 1; + return -1; } } { @@ -7805,7 +7878,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->type_comment, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL || tmp == Py_None) { Py_CLEAR(tmp); @@ -7829,18 +7902,18 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* tp = state->Match_type; isinstance = PyObject_IsInstance(obj, tp); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { expr_ty subject; asdl_match_case_seq* cases; if (PyObject_GetOptionalAttr(obj, state->subject, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"subject\" missing from Match"); - return 1; + return -1; } else { int res; @@ -7853,12 +7926,12 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->cases, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { tmp = PyList_New(0); if (tmp == NULL) { - return 1; + return -1; } } { @@ -7898,14 +7971,14 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* tp = state->Raise_type; isinstance = PyObject_IsInstance(obj, tp); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { expr_ty exc; expr_ty cause; if (PyObject_GetOptionalAttr(obj, state->exc, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL || tmp == Py_None) { Py_CLEAR(tmp); @@ -7922,7 +7995,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->cause, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL || tmp == Py_None) { Py_CLEAR(tmp); @@ -7946,7 +8019,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* tp = state->Try_type; isinstance = PyObject_IsInstance(obj, tp); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { asdl_stmt_seq* body; @@ -7955,12 +8028,12 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* asdl_stmt_seq* finalbody; if (PyObject_GetOptionalAttr(obj, state->body, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { tmp = PyList_New(0); if (tmp == NULL) { - return 1; + return -1; } } { @@ -7993,12 +8066,12 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->handlers, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { tmp = PyList_New(0); if (tmp == NULL) { - return 1; + return -1; } } { @@ -8031,12 +8104,12 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->orelse, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { tmp = PyList_New(0); if (tmp == NULL) { - return 1; + return -1; } } { @@ -8069,12 +8142,12 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->finalbody, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { tmp = PyList_New(0); if (tmp == NULL) { - return 1; + return -1; } } { @@ -8114,7 +8187,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* tp = state->TryStar_type; isinstance = PyObject_IsInstance(obj, tp); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { asdl_stmt_seq* body; @@ -8123,12 +8196,12 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* asdl_stmt_seq* finalbody; if (PyObject_GetOptionalAttr(obj, state->body, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { tmp = PyList_New(0); if (tmp == NULL) { - return 1; + return -1; } } { @@ -8161,12 +8234,12 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->handlers, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { tmp = PyList_New(0); if (tmp == NULL) { - return 1; + return -1; } } { @@ -8199,12 +8272,12 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->orelse, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { tmp = PyList_New(0); if (tmp == NULL) { - return 1; + return -1; } } { @@ -8237,12 +8310,12 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->finalbody, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { tmp = PyList_New(0); if (tmp == NULL) { - return 1; + return -1; } } { @@ -8282,18 +8355,18 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* tp = state->Assert_type; isinstance = PyObject_IsInstance(obj, tp); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { expr_ty test; expr_ty msg; if (PyObject_GetOptionalAttr(obj, state->test, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"test\" missing from Assert"); - return 1; + return -1; } else { int res; @@ -8306,7 +8379,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->msg, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL || tmp == Py_None) { Py_CLEAR(tmp); @@ -8330,18 +8403,18 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* tp = state->Import_type; isinstance = PyObject_IsInstance(obj, tp); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { asdl_alias_seq* names; if (PyObject_GetOptionalAttr(obj, state->names, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { tmp = PyList_New(0); if (tmp == NULL) { - return 1; + return -1; } } { @@ -8381,7 +8454,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* tp = state->ImportFrom_type; isinstance = PyObject_IsInstance(obj, tp); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { identifier module; @@ -8389,7 +8462,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* int level; if (PyObject_GetOptionalAttr(obj, state->module, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL || tmp == Py_None) { Py_CLEAR(tmp); @@ -8406,12 +8479,12 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->names, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { tmp = PyList_New(0); if (tmp == NULL) { - return 1; + return -1; } } { @@ -8444,7 +8517,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->level, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL || tmp == Py_None) { Py_CLEAR(tmp); @@ -8468,18 +8541,18 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* tp = state->Global_type; isinstance = PyObject_IsInstance(obj, tp); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { asdl_identifier_seq* names; if (PyObject_GetOptionalAttr(obj, state->names, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { tmp = PyList_New(0); if (tmp == NULL) { - return 1; + return -1; } } { @@ -8519,18 +8592,18 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* tp = state->Nonlocal_type; isinstance = PyObject_IsInstance(obj, tp); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { asdl_identifier_seq* names; if (PyObject_GetOptionalAttr(obj, state->names, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { tmp = PyList_New(0); if (tmp == NULL) { - return 1; + return -1; } } { @@ -8570,17 +8643,17 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* tp = state->Expr_type; isinstance = PyObject_IsInstance(obj, tp); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { expr_ty value; if (PyObject_GetOptionalAttr(obj, state->value, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"value\" missing from Expr"); - return 1; + return -1; } else { int res; @@ -8600,7 +8673,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* tp = state->Pass_type; isinstance = PyObject_IsInstance(obj, tp); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { @@ -8612,7 +8685,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* tp = state->Break_type; isinstance = PyObject_IsInstance(obj, tp); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { @@ -8624,7 +8697,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* tp = state->Continue_type; isinstance = PyObject_IsInstance(obj, tp); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { @@ -8637,7 +8710,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* PyErr_Format(PyExc_TypeError, "expected some sort of stmt, but got %R", obj); failed: Py_XDECREF(tmp); - return 1; + return -1; } int @@ -8658,11 +8731,11 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* return 0; } if (PyObject_GetOptionalAttr(obj, state->lineno, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"lineno\" missing from expr"); - return 1; + return -1; } else { int res; @@ -8675,11 +8748,11 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->col_offset, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"col_offset\" missing from expr"); - return 1; + return -1; } else { int res; @@ -8692,7 +8765,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->end_lineno, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL || tmp == Py_None) { Py_CLEAR(tmp); @@ -8709,7 +8782,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->end_col_offset, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL || tmp == Py_None) { Py_CLEAR(tmp); @@ -8728,18 +8801,18 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* tp = state->BoolOp_type; isinstance = PyObject_IsInstance(obj, tp); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { boolop_ty op; asdl_expr_seq* values; if (PyObject_GetOptionalAttr(obj, state->op, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"op\" missing from BoolOp"); - return 1; + return -1; } else { int res; @@ -8752,12 +8825,12 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->values, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { tmp = PyList_New(0); if (tmp == NULL) { - return 1; + return -1; } } { @@ -8797,18 +8870,18 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* tp = state->NamedExpr_type; isinstance = PyObject_IsInstance(obj, tp); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { expr_ty target; expr_ty value; if (PyObject_GetOptionalAttr(obj, state->target, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"target\" missing from NamedExpr"); - return 1; + return -1; } else { int res; @@ -8821,11 +8894,11 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->value, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"value\" missing from NamedExpr"); - return 1; + return -1; } else { int res; @@ -8845,7 +8918,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* tp = state->BinOp_type; isinstance = PyObject_IsInstance(obj, tp); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { expr_ty left; @@ -8853,11 +8926,11 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* expr_ty right; if (PyObject_GetOptionalAttr(obj, state->left, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"left\" missing from BinOp"); - return 1; + return -1; } else { int res; @@ -8870,11 +8943,11 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->op, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"op\" missing from BinOp"); - return 1; + return -1; } else { int res; @@ -8887,11 +8960,11 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->right, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"right\" missing from BinOp"); - return 1; + return -1; } else { int res; @@ -8911,18 +8984,18 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* tp = state->UnaryOp_type; isinstance = PyObject_IsInstance(obj, tp); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { unaryop_ty op; expr_ty operand; if (PyObject_GetOptionalAttr(obj, state->op, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"op\" missing from UnaryOp"); - return 1; + return -1; } else { int res; @@ -8935,11 +9008,11 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->operand, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"operand\" missing from UnaryOp"); - return 1; + return -1; } else { int res; @@ -8959,18 +9032,18 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* tp = state->Lambda_type; isinstance = PyObject_IsInstance(obj, tp); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { arguments_ty args; expr_ty body; if (PyObject_GetOptionalAttr(obj, state->args, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"args\" missing from Lambda"); - return 1; + return -1; } else { int res; @@ -8983,11 +9056,11 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->body, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"body\" missing from Lambda"); - return 1; + return -1; } else { int res; @@ -9007,7 +9080,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* tp = state->IfExp_type; isinstance = PyObject_IsInstance(obj, tp); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { expr_ty test; @@ -9015,11 +9088,11 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* expr_ty orelse; if (PyObject_GetOptionalAttr(obj, state->test, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"test\" missing from IfExp"); - return 1; + return -1; } else { int res; @@ -9032,11 +9105,11 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->body, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"body\" missing from IfExp"); - return 1; + return -1; } else { int res; @@ -9049,11 +9122,11 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->orelse, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"orelse\" missing from IfExp"); - return 1; + return -1; } else { int res; @@ -9073,19 +9146,19 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* tp = state->Dict_type; isinstance = PyObject_IsInstance(obj, tp); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { asdl_expr_seq* keys; asdl_expr_seq* values; if (PyObject_GetOptionalAttr(obj, state->keys, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { tmp = PyList_New(0); if (tmp == NULL) { - return 1; + return -1; } } { @@ -9118,12 +9191,12 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->values, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { tmp = PyList_New(0); if (tmp == NULL) { - return 1; + return -1; } } { @@ -9163,18 +9236,18 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* tp = state->Set_type; isinstance = PyObject_IsInstance(obj, tp); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { asdl_expr_seq* elts; if (PyObject_GetOptionalAttr(obj, state->elts, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { tmp = PyList_New(0); if (tmp == NULL) { - return 1; + return -1; } } { @@ -9214,18 +9287,18 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* tp = state->ListComp_type; isinstance = PyObject_IsInstance(obj, tp); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { expr_ty elt; asdl_comprehension_seq* generators; if (PyObject_GetOptionalAttr(obj, state->elt, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"elt\" missing from ListComp"); - return 1; + return -1; } else { int res; @@ -9238,12 +9311,12 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->generators, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { tmp = PyList_New(0); if (tmp == NULL) { - return 1; + return -1; } } { @@ -9283,18 +9356,18 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* tp = state->SetComp_type; isinstance = PyObject_IsInstance(obj, tp); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { expr_ty elt; asdl_comprehension_seq* generators; if (PyObject_GetOptionalAttr(obj, state->elt, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"elt\" missing from SetComp"); - return 1; + return -1; } else { int res; @@ -9307,12 +9380,12 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->generators, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { tmp = PyList_New(0); if (tmp == NULL) { - return 1; + return -1; } } { @@ -9352,7 +9425,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* tp = state->DictComp_type; isinstance = PyObject_IsInstance(obj, tp); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { expr_ty key; @@ -9360,11 +9433,11 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* asdl_comprehension_seq* generators; if (PyObject_GetOptionalAttr(obj, state->key, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"key\" missing from DictComp"); - return 1; + return -1; } else { int res; @@ -9377,11 +9450,11 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->value, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"value\" missing from DictComp"); - return 1; + return -1; } else { int res; @@ -9394,12 +9467,12 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->generators, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { tmp = PyList_New(0); if (tmp == NULL) { - return 1; + return -1; } } { @@ -9439,18 +9512,18 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* tp = state->GeneratorExp_type; isinstance = PyObject_IsInstance(obj, tp); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { expr_ty elt; asdl_comprehension_seq* generators; if (PyObject_GetOptionalAttr(obj, state->elt, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"elt\" missing from GeneratorExp"); - return 1; + return -1; } else { int res; @@ -9463,12 +9536,12 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->generators, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { tmp = PyList_New(0); if (tmp == NULL) { - return 1; + return -1; } } { @@ -9508,17 +9581,17 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* tp = state->Await_type; isinstance = PyObject_IsInstance(obj, tp); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { expr_ty value; if (PyObject_GetOptionalAttr(obj, state->value, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"value\" missing from Await"); - return 1; + return -1; } else { int res; @@ -9538,13 +9611,13 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* tp = state->Yield_type; isinstance = PyObject_IsInstance(obj, tp); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { expr_ty value; if (PyObject_GetOptionalAttr(obj, state->value, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL || tmp == Py_None) { Py_CLEAR(tmp); @@ -9568,17 +9641,17 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* tp = state->YieldFrom_type; isinstance = PyObject_IsInstance(obj, tp); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { expr_ty value; if (PyObject_GetOptionalAttr(obj, state->value, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"value\" missing from YieldFrom"); - return 1; + return -1; } else { int res; @@ -9598,7 +9671,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* tp = state->Compare_type; isinstance = PyObject_IsInstance(obj, tp); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { expr_ty left; @@ -9606,11 +9679,11 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* asdl_expr_seq* comparators; if (PyObject_GetOptionalAttr(obj, state->left, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"left\" missing from Compare"); - return 1; + return -1; } else { int res; @@ -9623,12 +9696,12 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->ops, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { tmp = PyList_New(0); if (tmp == NULL) { - return 1; + return -1; } } { @@ -9661,12 +9734,12 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->comparators, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { tmp = PyList_New(0); if (tmp == NULL) { - return 1; + return -1; } } { @@ -9706,7 +9779,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* tp = state->Call_type; isinstance = PyObject_IsInstance(obj, tp); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { expr_ty func; @@ -9714,11 +9787,11 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* asdl_keyword_seq* keywords; if (PyObject_GetOptionalAttr(obj, state->func, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"func\" missing from Call"); - return 1; + return -1; } else { int res; @@ -9731,12 +9804,12 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->args, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { tmp = PyList_New(0); if (tmp == NULL) { - return 1; + return -1; } } { @@ -9769,12 +9842,12 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->keywords, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { tmp = PyList_New(0); if (tmp == NULL) { - return 1; + return -1; } } { @@ -9814,7 +9887,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* tp = state->FormattedValue_type; isinstance = PyObject_IsInstance(obj, tp); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { expr_ty value; @@ -9822,11 +9895,11 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* expr_ty format_spec; if (PyObject_GetOptionalAttr(obj, state->value, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"value\" missing from FormattedValue"); - return 1; + return -1; } else { int res; @@ -9839,11 +9912,11 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->conversion, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"conversion\" missing from FormattedValue"); - return 1; + return -1; } else { int res; @@ -9856,7 +9929,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->format_spec, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL || tmp == Py_None) { Py_CLEAR(tmp); @@ -9881,18 +9954,18 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* tp = state->JoinedStr_type; isinstance = PyObject_IsInstance(obj, tp); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { asdl_expr_seq* values; if (PyObject_GetOptionalAttr(obj, state->values, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { tmp = PyList_New(0); if (tmp == NULL) { - return 1; + return -1; } } { @@ -9932,18 +10005,18 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* tp = state->Constant_type; isinstance = PyObject_IsInstance(obj, tp); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { constant value; string kind; if (PyObject_GetOptionalAttr(obj, state->value, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"value\" missing from Constant"); - return 1; + return -1; } else { int res; @@ -9956,7 +10029,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->kind, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL || tmp == Py_None) { Py_CLEAR(tmp); @@ -9980,7 +10053,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* tp = state->Attribute_type; isinstance = PyObject_IsInstance(obj, tp); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { expr_ty value; @@ -9988,11 +10061,11 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* expr_context_ty ctx; if (PyObject_GetOptionalAttr(obj, state->value, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"value\" missing from Attribute"); - return 1; + return -1; } else { int res; @@ -10005,11 +10078,11 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->attr, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"attr\" missing from Attribute"); - return 1; + return -1; } else { int res; @@ -10022,11 +10095,11 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->ctx, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"ctx\" missing from Attribute"); - return 1; + return -1; } else { int res; @@ -10046,7 +10119,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* tp = state->Subscript_type; isinstance = PyObject_IsInstance(obj, tp); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { expr_ty value; @@ -10054,11 +10127,11 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* expr_context_ty ctx; if (PyObject_GetOptionalAttr(obj, state->value, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"value\" missing from Subscript"); - return 1; + return -1; } else { int res; @@ -10071,11 +10144,11 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->slice, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"slice\" missing from Subscript"); - return 1; + return -1; } else { int res; @@ -10088,11 +10161,11 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->ctx, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"ctx\" missing from Subscript"); - return 1; + return -1; } else { int res; @@ -10112,18 +10185,18 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* tp = state->Starred_type; isinstance = PyObject_IsInstance(obj, tp); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { expr_ty value; expr_context_ty ctx; if (PyObject_GetOptionalAttr(obj, state->value, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"value\" missing from Starred"); - return 1; + return -1; } else { int res; @@ -10136,11 +10209,11 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->ctx, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"ctx\" missing from Starred"); - return 1; + return -1; } else { int res; @@ -10160,18 +10233,18 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* tp = state->Name_type; isinstance = PyObject_IsInstance(obj, tp); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { identifier id; expr_context_ty ctx; if (PyObject_GetOptionalAttr(obj, state->id, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"id\" missing from Name"); - return 1; + return -1; } else { int res; @@ -10184,11 +10257,11 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->ctx, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"ctx\" missing from Name"); - return 1; + return -1; } else { int res; @@ -10208,19 +10281,19 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* tp = state->List_type; isinstance = PyObject_IsInstance(obj, tp); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { asdl_expr_seq* elts; expr_context_ty ctx; if (PyObject_GetOptionalAttr(obj, state->elts, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { tmp = PyList_New(0); if (tmp == NULL) { - return 1; + return -1; } } { @@ -10253,11 +10326,11 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->ctx, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"ctx\" missing from List"); - return 1; + return -1; } else { int res; @@ -10277,19 +10350,19 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* tp = state->Tuple_type; isinstance = PyObject_IsInstance(obj, tp); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { asdl_expr_seq* elts; expr_context_ty ctx; if (PyObject_GetOptionalAttr(obj, state->elts, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { tmp = PyList_New(0); if (tmp == NULL) { - return 1; + return -1; } } { @@ -10322,11 +10395,11 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->ctx, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"ctx\" missing from Tuple"); - return 1; + return -1; } else { int res; @@ -10346,7 +10419,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* tp = state->Slice_type; isinstance = PyObject_IsInstance(obj, tp); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { expr_ty lower; @@ -10354,7 +10427,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* expr_ty step; if (PyObject_GetOptionalAttr(obj, state->lower, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL || tmp == Py_None) { Py_CLEAR(tmp); @@ -10371,7 +10444,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->upper, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL || tmp == Py_None) { Py_CLEAR(tmp); @@ -10388,7 +10461,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->step, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL || tmp == Py_None) { Py_CLEAR(tmp); @@ -10413,7 +10486,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* PyErr_Format(PyExc_TypeError, "expected some sort of expr, but got %R", obj); failed: Py_XDECREF(tmp); - return 1; + return -1; } int @@ -10424,7 +10497,7 @@ obj2ast_expr_context(struct ast_state *state, PyObject* obj, expr_context_ty* isinstance = PyObject_IsInstance(obj, state->Load_type); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { *out = Load; @@ -10432,7 +10505,7 @@ obj2ast_expr_context(struct ast_state *state, PyObject* obj, expr_context_ty* } isinstance = PyObject_IsInstance(obj, state->Store_type); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { *out = Store; @@ -10440,7 +10513,7 @@ obj2ast_expr_context(struct ast_state *state, PyObject* obj, expr_context_ty* } isinstance = PyObject_IsInstance(obj, state->Del_type); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { *out = Del; @@ -10448,7 +10521,7 @@ obj2ast_expr_context(struct ast_state *state, PyObject* obj, expr_context_ty* } PyErr_Format(PyExc_TypeError, "expected some sort of expr_context, but got %R", obj); - return 1; + return -1; } int @@ -10459,7 +10532,7 @@ obj2ast_boolop(struct ast_state *state, PyObject* obj, boolop_ty* out, PyArena* isinstance = PyObject_IsInstance(obj, state->And_type); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { *out = And; @@ -10467,7 +10540,7 @@ obj2ast_boolop(struct ast_state *state, PyObject* obj, boolop_ty* out, PyArena* } isinstance = PyObject_IsInstance(obj, state->Or_type); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { *out = Or; @@ -10475,7 +10548,7 @@ obj2ast_boolop(struct ast_state *state, PyObject* obj, boolop_ty* out, PyArena* } PyErr_Format(PyExc_TypeError, "expected some sort of boolop, but got %R", obj); - return 1; + return -1; } int @@ -10486,7 +10559,7 @@ obj2ast_operator(struct ast_state *state, PyObject* obj, operator_ty* out, isinstance = PyObject_IsInstance(obj, state->Add_type); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { *out = Add; @@ -10494,7 +10567,7 @@ obj2ast_operator(struct ast_state *state, PyObject* obj, operator_ty* out, } isinstance = PyObject_IsInstance(obj, state->Sub_type); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { *out = Sub; @@ -10502,7 +10575,7 @@ obj2ast_operator(struct ast_state *state, PyObject* obj, operator_ty* out, } isinstance = PyObject_IsInstance(obj, state->Mult_type); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { *out = Mult; @@ -10510,7 +10583,7 @@ obj2ast_operator(struct ast_state *state, PyObject* obj, operator_ty* out, } isinstance = PyObject_IsInstance(obj, state->MatMult_type); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { *out = MatMult; @@ -10518,7 +10591,7 @@ obj2ast_operator(struct ast_state *state, PyObject* obj, operator_ty* out, } isinstance = PyObject_IsInstance(obj, state->Div_type); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { *out = Div; @@ -10526,7 +10599,7 @@ obj2ast_operator(struct ast_state *state, PyObject* obj, operator_ty* out, } isinstance = PyObject_IsInstance(obj, state->Mod_type); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { *out = Mod; @@ -10534,7 +10607,7 @@ obj2ast_operator(struct ast_state *state, PyObject* obj, operator_ty* out, } isinstance = PyObject_IsInstance(obj, state->Pow_type); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { *out = Pow; @@ -10542,7 +10615,7 @@ obj2ast_operator(struct ast_state *state, PyObject* obj, operator_ty* out, } isinstance = PyObject_IsInstance(obj, state->LShift_type); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { *out = LShift; @@ -10550,7 +10623,7 @@ obj2ast_operator(struct ast_state *state, PyObject* obj, operator_ty* out, } isinstance = PyObject_IsInstance(obj, state->RShift_type); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { *out = RShift; @@ -10558,7 +10631,7 @@ obj2ast_operator(struct ast_state *state, PyObject* obj, operator_ty* out, } isinstance = PyObject_IsInstance(obj, state->BitOr_type); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { *out = BitOr; @@ -10566,7 +10639,7 @@ obj2ast_operator(struct ast_state *state, PyObject* obj, operator_ty* out, } isinstance = PyObject_IsInstance(obj, state->BitXor_type); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { *out = BitXor; @@ -10574,7 +10647,7 @@ obj2ast_operator(struct ast_state *state, PyObject* obj, operator_ty* out, } isinstance = PyObject_IsInstance(obj, state->BitAnd_type); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { *out = BitAnd; @@ -10582,7 +10655,7 @@ obj2ast_operator(struct ast_state *state, PyObject* obj, operator_ty* out, } isinstance = PyObject_IsInstance(obj, state->FloorDiv_type); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { *out = FloorDiv; @@ -10590,7 +10663,7 @@ obj2ast_operator(struct ast_state *state, PyObject* obj, operator_ty* out, } PyErr_Format(PyExc_TypeError, "expected some sort of operator, but got %R", obj); - return 1; + return -1; } int @@ -10601,7 +10674,7 @@ obj2ast_unaryop(struct ast_state *state, PyObject* obj, unaryop_ty* out, isinstance = PyObject_IsInstance(obj, state->Invert_type); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { *out = Invert; @@ -10609,7 +10682,7 @@ obj2ast_unaryop(struct ast_state *state, PyObject* obj, unaryop_ty* out, } isinstance = PyObject_IsInstance(obj, state->Not_type); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { *out = Not; @@ -10617,7 +10690,7 @@ obj2ast_unaryop(struct ast_state *state, PyObject* obj, unaryop_ty* out, } isinstance = PyObject_IsInstance(obj, state->UAdd_type); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { *out = UAdd; @@ -10625,7 +10698,7 @@ obj2ast_unaryop(struct ast_state *state, PyObject* obj, unaryop_ty* out, } isinstance = PyObject_IsInstance(obj, state->USub_type); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { *out = USub; @@ -10633,7 +10706,7 @@ obj2ast_unaryop(struct ast_state *state, PyObject* obj, unaryop_ty* out, } PyErr_Format(PyExc_TypeError, "expected some sort of unaryop, but got %R", obj); - return 1; + return -1; } int @@ -10644,7 +10717,7 @@ obj2ast_cmpop(struct ast_state *state, PyObject* obj, cmpop_ty* out, PyArena* isinstance = PyObject_IsInstance(obj, state->Eq_type); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { *out = Eq; @@ -10652,7 +10725,7 @@ obj2ast_cmpop(struct ast_state *state, PyObject* obj, cmpop_ty* out, PyArena* } isinstance = PyObject_IsInstance(obj, state->NotEq_type); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { *out = NotEq; @@ -10660,7 +10733,7 @@ obj2ast_cmpop(struct ast_state *state, PyObject* obj, cmpop_ty* out, PyArena* } isinstance = PyObject_IsInstance(obj, state->Lt_type); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { *out = Lt; @@ -10668,7 +10741,7 @@ obj2ast_cmpop(struct ast_state *state, PyObject* obj, cmpop_ty* out, PyArena* } isinstance = PyObject_IsInstance(obj, state->LtE_type); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { *out = LtE; @@ -10676,7 +10749,7 @@ obj2ast_cmpop(struct ast_state *state, PyObject* obj, cmpop_ty* out, PyArena* } isinstance = PyObject_IsInstance(obj, state->Gt_type); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { *out = Gt; @@ -10684,7 +10757,7 @@ obj2ast_cmpop(struct ast_state *state, PyObject* obj, cmpop_ty* out, PyArena* } isinstance = PyObject_IsInstance(obj, state->GtE_type); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { *out = GtE; @@ -10692,7 +10765,7 @@ obj2ast_cmpop(struct ast_state *state, PyObject* obj, cmpop_ty* out, PyArena* } isinstance = PyObject_IsInstance(obj, state->Is_type); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { *out = Is; @@ -10700,7 +10773,7 @@ obj2ast_cmpop(struct ast_state *state, PyObject* obj, cmpop_ty* out, PyArena* } isinstance = PyObject_IsInstance(obj, state->IsNot_type); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { *out = IsNot; @@ -10708,7 +10781,7 @@ obj2ast_cmpop(struct ast_state *state, PyObject* obj, cmpop_ty* out, PyArena* } isinstance = PyObject_IsInstance(obj, state->In_type); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { *out = In; @@ -10716,7 +10789,7 @@ obj2ast_cmpop(struct ast_state *state, PyObject* obj, cmpop_ty* out, PyArena* } isinstance = PyObject_IsInstance(obj, state->NotIn_type); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { *out = NotIn; @@ -10724,7 +10797,7 @@ obj2ast_cmpop(struct ast_state *state, PyObject* obj, cmpop_ty* out, PyArena* } PyErr_Format(PyExc_TypeError, "expected some sort of cmpop, but got %R", obj); - return 1; + return -1; } int @@ -10738,11 +10811,11 @@ obj2ast_comprehension(struct ast_state *state, PyObject* obj, comprehension_ty* int is_async; if (PyObject_GetOptionalAttr(obj, state->target, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"target\" missing from comprehension"); - return 1; + return -1; } else { int res; @@ -10755,11 +10828,11 @@ obj2ast_comprehension(struct ast_state *state, PyObject* obj, comprehension_ty* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->iter, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"iter\" missing from comprehension"); - return 1; + return -1; } else { int res; @@ -10772,12 +10845,12 @@ obj2ast_comprehension(struct ast_state *state, PyObject* obj, comprehension_ty* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->ifs, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { tmp = PyList_New(0); if (tmp == NULL) { - return 1; + return -1; } } { @@ -10810,11 +10883,11 @@ obj2ast_comprehension(struct ast_state *state, PyObject* obj, comprehension_ty* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->is_async, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"is_async\" missing from comprehension"); - return 1; + return -1; } else { int res; @@ -10831,7 +10904,7 @@ obj2ast_comprehension(struct ast_state *state, PyObject* obj, comprehension_ty* return 0; failed: Py_XDECREF(tmp); - return 1; + return -1; } int @@ -10852,11 +10925,11 @@ obj2ast_excepthandler(struct ast_state *state, PyObject* obj, excepthandler_ty* return 0; } if (PyObject_GetOptionalAttr(obj, state->lineno, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"lineno\" missing from excepthandler"); - return 1; + return -1; } else { int res; @@ -10869,11 +10942,11 @@ obj2ast_excepthandler(struct ast_state *state, PyObject* obj, excepthandler_ty* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->col_offset, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"col_offset\" missing from excepthandler"); - return 1; + return -1; } else { int res; @@ -10886,7 +10959,7 @@ obj2ast_excepthandler(struct ast_state *state, PyObject* obj, excepthandler_ty* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->end_lineno, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL || tmp == Py_None) { Py_CLEAR(tmp); @@ -10903,7 +10976,7 @@ obj2ast_excepthandler(struct ast_state *state, PyObject* obj, excepthandler_ty* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->end_col_offset, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL || tmp == Py_None) { Py_CLEAR(tmp); @@ -10922,7 +10995,7 @@ obj2ast_excepthandler(struct ast_state *state, PyObject* obj, excepthandler_ty* tp = state->ExceptHandler_type; isinstance = PyObject_IsInstance(obj, tp); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { expr_ty type; @@ -10930,7 +11003,7 @@ obj2ast_excepthandler(struct ast_state *state, PyObject* obj, excepthandler_ty* asdl_stmt_seq* body; if (PyObject_GetOptionalAttr(obj, state->type, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL || tmp == Py_None) { Py_CLEAR(tmp); @@ -10947,7 +11020,7 @@ obj2ast_excepthandler(struct ast_state *state, PyObject* obj, excepthandler_ty* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->name, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL || tmp == Py_None) { Py_CLEAR(tmp); @@ -10964,12 +11037,12 @@ obj2ast_excepthandler(struct ast_state *state, PyObject* obj, excepthandler_ty* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->body, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { tmp = PyList_New(0); if (tmp == NULL) { - return 1; + return -1; } } { @@ -11010,7 +11083,7 @@ obj2ast_excepthandler(struct ast_state *state, PyObject* obj, excepthandler_ty* PyErr_Format(PyExc_TypeError, "expected some sort of excepthandler, but got %R", obj); failed: Py_XDECREF(tmp); - return 1; + return -1; } int @@ -11027,12 +11100,12 @@ obj2ast_arguments(struct ast_state *state, PyObject* obj, arguments_ty* out, asdl_expr_seq* defaults; if (PyObject_GetOptionalAttr(obj, state->posonlyargs, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { tmp = PyList_New(0); if (tmp == NULL) { - return 1; + return -1; } } { @@ -11065,12 +11138,12 @@ obj2ast_arguments(struct ast_state *state, PyObject* obj, arguments_ty* out, Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->args, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { tmp = PyList_New(0); if (tmp == NULL) { - return 1; + return -1; } } { @@ -11103,7 +11176,7 @@ obj2ast_arguments(struct ast_state *state, PyObject* obj, arguments_ty* out, Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->vararg, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL || tmp == Py_None) { Py_CLEAR(tmp); @@ -11120,12 +11193,12 @@ obj2ast_arguments(struct ast_state *state, PyObject* obj, arguments_ty* out, Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->kwonlyargs, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { tmp = PyList_New(0); if (tmp == NULL) { - return 1; + return -1; } } { @@ -11158,12 +11231,12 @@ obj2ast_arguments(struct ast_state *state, PyObject* obj, arguments_ty* out, Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->kw_defaults, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { tmp = PyList_New(0); if (tmp == NULL) { - return 1; + return -1; } } { @@ -11196,7 +11269,7 @@ obj2ast_arguments(struct ast_state *state, PyObject* obj, arguments_ty* out, Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->kwarg, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL || tmp == Py_None) { Py_CLEAR(tmp); @@ -11213,12 +11286,12 @@ obj2ast_arguments(struct ast_state *state, PyObject* obj, arguments_ty* out, Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->defaults, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { tmp = PyList_New(0); if (tmp == NULL) { - return 1; + return -1; } } { @@ -11256,7 +11329,7 @@ obj2ast_arguments(struct ast_state *state, PyObject* obj, arguments_ty* out, return 0; failed: Py_XDECREF(tmp); - return 1; + return -1; } int @@ -11272,11 +11345,11 @@ obj2ast_arg(struct ast_state *state, PyObject* obj, arg_ty* out, PyArena* arena) int end_col_offset; if (PyObject_GetOptionalAttr(obj, state->arg, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"arg\" missing from arg"); - return 1; + return -1; } else { int res; @@ -11289,7 +11362,7 @@ obj2ast_arg(struct ast_state *state, PyObject* obj, arg_ty* out, PyArena* arena) Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->annotation, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL || tmp == Py_None) { Py_CLEAR(tmp); @@ -11306,7 +11379,7 @@ obj2ast_arg(struct ast_state *state, PyObject* obj, arg_ty* out, PyArena* arena) Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->type_comment, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL || tmp == Py_None) { Py_CLEAR(tmp); @@ -11323,11 +11396,11 @@ obj2ast_arg(struct ast_state *state, PyObject* obj, arg_ty* out, PyArena* arena) Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->lineno, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"lineno\" missing from arg"); - return 1; + return -1; } else { int res; @@ -11340,11 +11413,11 @@ obj2ast_arg(struct ast_state *state, PyObject* obj, arg_ty* out, PyArena* arena) Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->col_offset, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"col_offset\" missing from arg"); - return 1; + return -1; } else { int res; @@ -11357,7 +11430,7 @@ obj2ast_arg(struct ast_state *state, PyObject* obj, arg_ty* out, PyArena* arena) Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->end_lineno, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL || tmp == Py_None) { Py_CLEAR(tmp); @@ -11374,7 +11447,7 @@ obj2ast_arg(struct ast_state *state, PyObject* obj, arg_ty* out, PyArena* arena) Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->end_col_offset, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL || tmp == Py_None) { Py_CLEAR(tmp); @@ -11396,7 +11469,7 @@ obj2ast_arg(struct ast_state *state, PyObject* obj, arg_ty* out, PyArena* arena) return 0; failed: Py_XDECREF(tmp); - return 1; + return -1; } int @@ -11412,7 +11485,7 @@ obj2ast_keyword(struct ast_state *state, PyObject* obj, keyword_ty* out, int end_col_offset; if (PyObject_GetOptionalAttr(obj, state->arg, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL || tmp == Py_None) { Py_CLEAR(tmp); @@ -11429,11 +11502,11 @@ obj2ast_keyword(struct ast_state *state, PyObject* obj, keyword_ty* out, Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->value, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"value\" missing from keyword"); - return 1; + return -1; } else { int res; @@ -11446,11 +11519,11 @@ obj2ast_keyword(struct ast_state *state, PyObject* obj, keyword_ty* out, Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->lineno, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"lineno\" missing from keyword"); - return 1; + return -1; } else { int res; @@ -11463,11 +11536,11 @@ obj2ast_keyword(struct ast_state *state, PyObject* obj, keyword_ty* out, Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->col_offset, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"col_offset\" missing from keyword"); - return 1; + return -1; } else { int res; @@ -11480,7 +11553,7 @@ obj2ast_keyword(struct ast_state *state, PyObject* obj, keyword_ty* out, Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->end_lineno, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL || tmp == Py_None) { Py_CLEAR(tmp); @@ -11497,7 +11570,7 @@ obj2ast_keyword(struct ast_state *state, PyObject* obj, keyword_ty* out, Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->end_col_offset, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL || tmp == Py_None) { Py_CLEAR(tmp); @@ -11519,7 +11592,7 @@ obj2ast_keyword(struct ast_state *state, PyObject* obj, keyword_ty* out, return 0; failed: Py_XDECREF(tmp); - return 1; + return -1; } int @@ -11535,11 +11608,11 @@ obj2ast_alias(struct ast_state *state, PyObject* obj, alias_ty* out, PyArena* int end_col_offset; if (PyObject_GetOptionalAttr(obj, state->name, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"name\" missing from alias"); - return 1; + return -1; } else { int res; @@ -11552,7 +11625,7 @@ obj2ast_alias(struct ast_state *state, PyObject* obj, alias_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->asname, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL || tmp == Py_None) { Py_CLEAR(tmp); @@ -11569,11 +11642,11 @@ obj2ast_alias(struct ast_state *state, PyObject* obj, alias_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->lineno, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"lineno\" missing from alias"); - return 1; + return -1; } else { int res; @@ -11586,11 +11659,11 @@ obj2ast_alias(struct ast_state *state, PyObject* obj, alias_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->col_offset, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"col_offset\" missing from alias"); - return 1; + return -1; } else { int res; @@ -11603,7 +11676,7 @@ obj2ast_alias(struct ast_state *state, PyObject* obj, alias_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->end_lineno, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL || tmp == Py_None) { Py_CLEAR(tmp); @@ -11620,7 +11693,7 @@ obj2ast_alias(struct ast_state *state, PyObject* obj, alias_ty* out, PyArena* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->end_col_offset, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL || tmp == Py_None) { Py_CLEAR(tmp); @@ -11642,7 +11715,7 @@ obj2ast_alias(struct ast_state *state, PyObject* obj, alias_ty* out, PyArena* return 0; failed: Py_XDECREF(tmp); - return 1; + return -1; } int @@ -11654,11 +11727,11 @@ obj2ast_withitem(struct ast_state *state, PyObject* obj, withitem_ty* out, expr_ty optional_vars; if (PyObject_GetOptionalAttr(obj, state->context_expr, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"context_expr\" missing from withitem"); - return 1; + return -1; } else { int res; @@ -11671,7 +11744,7 @@ obj2ast_withitem(struct ast_state *state, PyObject* obj, withitem_ty* out, Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->optional_vars, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL || tmp == Py_None) { Py_CLEAR(tmp); @@ -11692,7 +11765,7 @@ obj2ast_withitem(struct ast_state *state, PyObject* obj, withitem_ty* out, return 0; failed: Py_XDECREF(tmp); - return 1; + return -1; } int @@ -11705,11 +11778,11 @@ obj2ast_match_case(struct ast_state *state, PyObject* obj, match_case_ty* out, asdl_stmt_seq* body; if (PyObject_GetOptionalAttr(obj, state->pattern, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"pattern\" missing from match_case"); - return 1; + return -1; } else { int res; @@ -11722,7 +11795,7 @@ obj2ast_match_case(struct ast_state *state, PyObject* obj, match_case_ty* out, Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->guard, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL || tmp == Py_None) { Py_CLEAR(tmp); @@ -11739,12 +11812,12 @@ obj2ast_match_case(struct ast_state *state, PyObject* obj, match_case_ty* out, Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->body, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { tmp = PyList_New(0); if (tmp == NULL) { - return 1; + return -1; } } { @@ -11781,7 +11854,7 @@ obj2ast_match_case(struct ast_state *state, PyObject* obj, match_case_ty* out, return 0; failed: Py_XDECREF(tmp); - return 1; + return -1; } int @@ -11802,11 +11875,11 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out, return 0; } if (PyObject_GetOptionalAttr(obj, state->lineno, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"lineno\" missing from pattern"); - return 1; + return -1; } else { int res; @@ -11819,11 +11892,11 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out, Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->col_offset, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"col_offset\" missing from pattern"); - return 1; + return -1; } else { int res; @@ -11836,11 +11909,11 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out, Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->end_lineno, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"end_lineno\" missing from pattern"); - return 1; + return -1; } else { int res; @@ -11853,11 +11926,11 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out, Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->end_col_offset, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"end_col_offset\" missing from pattern"); - return 1; + return -1; } else { int res; @@ -11872,17 +11945,17 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out, tp = state->MatchValue_type; isinstance = PyObject_IsInstance(obj, tp); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { expr_ty value; if (PyObject_GetOptionalAttr(obj, state->value, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"value\" missing from MatchValue"); - return 1; + return -1; } else { int res; @@ -11902,17 +11975,17 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out, tp = state->MatchSingleton_type; isinstance = PyObject_IsInstance(obj, tp); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { constant value; if (PyObject_GetOptionalAttr(obj, state->value, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"value\" missing from MatchSingleton"); - return 1; + return -1; } else { int res; @@ -11932,18 +12005,18 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out, tp = state->MatchSequence_type; isinstance = PyObject_IsInstance(obj, tp); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { asdl_pattern_seq* patterns; if (PyObject_GetOptionalAttr(obj, state->patterns, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { tmp = PyList_New(0); if (tmp == NULL) { - return 1; + return -1; } } { @@ -11983,7 +12056,7 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out, tp = state->MatchMapping_type; isinstance = PyObject_IsInstance(obj, tp); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { asdl_expr_seq* keys; @@ -11991,12 +12064,12 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out, identifier rest; if (PyObject_GetOptionalAttr(obj, state->keys, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { tmp = PyList_New(0); if (tmp == NULL) { - return 1; + return -1; } } { @@ -12029,12 +12102,12 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out, Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->patterns, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { tmp = PyList_New(0); if (tmp == NULL) { - return 1; + return -1; } } { @@ -12067,7 +12140,7 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out, Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->rest, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL || tmp == Py_None) { Py_CLEAR(tmp); @@ -12091,7 +12164,7 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out, tp = state->MatchClass_type; isinstance = PyObject_IsInstance(obj, tp); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { expr_ty cls; @@ -12100,11 +12173,11 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out, asdl_pattern_seq* kwd_patterns; if (PyObject_GetOptionalAttr(obj, state->cls, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"cls\" missing from MatchClass"); - return 1; + return -1; } else { int res; @@ -12117,12 +12190,12 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out, Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->patterns, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { tmp = PyList_New(0); if (tmp == NULL) { - return 1; + return -1; } } { @@ -12155,12 +12228,12 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out, Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->kwd_attrs, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { tmp = PyList_New(0); if (tmp == NULL) { - return 1; + return -1; } } { @@ -12193,12 +12266,12 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out, Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->kwd_patterns, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { tmp = PyList_New(0); if (tmp == NULL) { - return 1; + return -1; } } { @@ -12239,13 +12312,13 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out, tp = state->MatchStar_type; isinstance = PyObject_IsInstance(obj, tp); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { identifier name; if (PyObject_GetOptionalAttr(obj, state->name, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL || tmp == Py_None) { Py_CLEAR(tmp); @@ -12269,14 +12342,14 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out, tp = state->MatchAs_type; isinstance = PyObject_IsInstance(obj, tp); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { pattern_ty pattern; identifier name; if (PyObject_GetOptionalAttr(obj, state->pattern, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL || tmp == Py_None) { Py_CLEAR(tmp); @@ -12293,7 +12366,7 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out, Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->name, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL || tmp == Py_None) { Py_CLEAR(tmp); @@ -12317,18 +12390,18 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out, tp = state->MatchOr_type; isinstance = PyObject_IsInstance(obj, tp); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { asdl_pattern_seq* patterns; if (PyObject_GetOptionalAttr(obj, state->patterns, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { tmp = PyList_New(0); if (tmp == NULL) { - return 1; + return -1; } } { @@ -12369,7 +12442,7 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out, PyErr_Format(PyExc_TypeError, "expected some sort of pattern, but got %R", obj); failed: Py_XDECREF(tmp); - return 1; + return -1; } int @@ -12388,18 +12461,18 @@ obj2ast_type_ignore(struct ast_state *state, PyObject* obj, type_ignore_ty* tp = state->TypeIgnore_type; isinstance = PyObject_IsInstance(obj, tp); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { int lineno; string tag; if (PyObject_GetOptionalAttr(obj, state->lineno, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"lineno\" missing from TypeIgnore"); - return 1; + return -1; } else { int res; @@ -12412,11 +12485,11 @@ obj2ast_type_ignore(struct ast_state *state, PyObject* obj, type_ignore_ty* Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->tag, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"tag\" missing from TypeIgnore"); - return 1; + return -1; } else { int res; @@ -12436,7 +12509,7 @@ obj2ast_type_ignore(struct ast_state *state, PyObject* obj, type_ignore_ty* PyErr_Format(PyExc_TypeError, "expected some sort of type_ignore, but got %R", obj); failed: Py_XDECREF(tmp); - return 1; + return -1; } int @@ -12457,11 +12530,11 @@ obj2ast_type_param(struct ast_state *state, PyObject* obj, type_param_ty* out, return 0; } if (PyObject_GetOptionalAttr(obj, state->lineno, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"lineno\" missing from type_param"); - return 1; + return -1; } else { int res; @@ -12474,11 +12547,11 @@ obj2ast_type_param(struct ast_state *state, PyObject* obj, type_param_ty* out, Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->col_offset, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"col_offset\" missing from type_param"); - return 1; + return -1; } else { int res; @@ -12491,11 +12564,11 @@ obj2ast_type_param(struct ast_state *state, PyObject* obj, type_param_ty* out, Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->end_lineno, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"end_lineno\" missing from type_param"); - return 1; + return -1; } else { int res; @@ -12508,11 +12581,11 @@ obj2ast_type_param(struct ast_state *state, PyObject* obj, type_param_ty* out, Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->end_col_offset, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"end_col_offset\" missing from type_param"); - return 1; + return -1; } else { int res; @@ -12527,18 +12600,18 @@ obj2ast_type_param(struct ast_state *state, PyObject* obj, type_param_ty* out, tp = state->TypeVar_type; isinstance = PyObject_IsInstance(obj, tp); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { identifier name; expr_ty bound; if (PyObject_GetOptionalAttr(obj, state->name, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"name\" missing from TypeVar"); - return 1; + return -1; } else { int res; @@ -12551,7 +12624,7 @@ obj2ast_type_param(struct ast_state *state, PyObject* obj, type_param_ty* out, Py_CLEAR(tmp); } if (PyObject_GetOptionalAttr(obj, state->bound, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL || tmp == Py_None) { Py_CLEAR(tmp); @@ -12575,17 +12648,17 @@ obj2ast_type_param(struct ast_state *state, PyObject* obj, type_param_ty* out, tp = state->ParamSpec_type; isinstance = PyObject_IsInstance(obj, tp); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { identifier name; if (PyObject_GetOptionalAttr(obj, state->name, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"name\" missing from ParamSpec"); - return 1; + return -1; } else { int res; @@ -12605,17 +12678,17 @@ obj2ast_type_param(struct ast_state *state, PyObject* obj, type_param_ty* out, tp = state->TypeVarTuple_type; isinstance = PyObject_IsInstance(obj, tp); if (isinstance == -1) { - return 1; + return -1; } if (isinstance) { identifier name; if (PyObject_GetOptionalAttr(obj, state->name, &tmp) < 0) { - return 1; + return -1; } if (tmp == NULL) { PyErr_SetString(PyExc_TypeError, "required field \"name\" missing from TypeVarTuple"); - return 1; + return -1; } else { int res; @@ -12636,7 +12709,7 @@ obj2ast_type_param(struct ast_state *state, PyObject* obj, type_param_ty* out, PyErr_Format(PyExc_TypeError, "expected some sort of type_param, but got %R", obj); failed: Py_XDECREF(tmp); - return 1; + return -1; } @@ -12659,6 +12732,9 @@ astmodule_exec(PyObject *m) if (PyModule_AddIntMacro(m, PyCF_TYPE_COMMENTS) < 0) { return -1; } + if (PyModule_AddIntMacro(m, PyCF_OPTIMIZED_AST) < 0) { + return -1; + } if (PyModule_AddObjectRef(m, "mod", state->mod_type) < 0) { return -1; } @@ -13076,21 +13152,22 @@ PyObject* PyAST_mod2obj(mod_ty t) int COMPILER_STACK_FRAME_SCALE = 2; PyThreadState *tstate = _PyThreadState_GET(); if (!tstate) { - return 0; + return NULL; } - state->recursion_limit = C_RECURSION_LIMIT * COMPILER_STACK_FRAME_SCALE; - int recursion_depth = C_RECURSION_LIMIT - tstate->c_recursion_remaining; + struct validator vstate; + vstate.recursion_limit = Py_C_RECURSION_LIMIT * COMPILER_STACK_FRAME_SCALE; + int recursion_depth = Py_C_RECURSION_LIMIT - tstate->c_recursion_remaining; starting_recursion_depth = recursion_depth * COMPILER_STACK_FRAME_SCALE; - state->recursion_depth = starting_recursion_depth; + vstate.recursion_depth = starting_recursion_depth; - PyObject *result = ast2obj_mod(state, t); + PyObject *result = ast2obj_mod(state, &vstate, t); /* Check that the recursion depth counting balanced correctly */ - if (result && state->recursion_depth != starting_recursion_depth) { + if (result && vstate.recursion_depth != starting_recursion_depth) { PyErr_Format(PyExc_SystemError, "AST constructor recursion depth mismatch (before=%d, after=%d)", - starting_recursion_depth, state->recursion_depth); - return 0; + starting_recursion_depth, vstate.recursion_depth); + return NULL; } return result; } diff --git a/Python/Python-tokenize.c b/Python/Python-tokenize.c index 1b021069c5e10b..a7891709b3b44a 100644 --- a/Python/Python-tokenize.c +++ b/Python/Python-tokenize.c @@ -1,7 +1,8 @@ #include "Python.h" #include "errcode.h" -#include "../Parser/tokenizer.h" -#include "../Parser/pegen.h" // _PyPegen_byte_offset_to_character_offset() +#include "../Parser/lexer/state.h" +#include "../Parser/lexer/lexer.h" +#include "../Parser/tokenizer/tokenizer.h" #include "../Parser/pegen.h" // _PyPegen_byte_offset_to_character_offset() static struct PyModuleDef _tokenizemodule; @@ -224,7 +225,7 @@ tokenizeriter_next(tokenizeriterobject *it) col_offset = _PyPegen_byte_offset_to_character_offset(line, token.start - line_start); } if (token.end != NULL && token.end >= it->tok->line_start) { - end_col_offset = _PyPegen_byte_offset_to_character_offset(line, token.end - it->tok->line_start); + end_col_offset = _PyPegen_byte_offset_to_character_offset_raw(it->tok->line_start, token.end - it->tok->line_start); } if (it->tok->tok_extra_tokens) { diff --git a/Python/_warnings.c b/Python/_warnings.c index 40ec5f613d5bf4..d4765032824e56 100644 --- a/Python/_warnings.c +++ b/Python/_warnings.c @@ -1,12 +1,13 @@ #include "Python.h" #include "pycore_dict.h" // _PyDict_GetItemWithError() -#include "pycore_frame.h" -#include "pycore_initconfig.h" #include "pycore_interp.h" // PyInterpreterState.warnings #include "pycore_long.h" // _PyLong_GetZero() -#include "pycore_pyerrors.h" +#include "pycore_pyerrors.h" // _PyErr_Occurred() #include "pycore_pylifecycle.h" // _Py_IsInterpreterFinalizing() #include "pycore_pystate.h" // _PyThreadState_GET() +#include "pycore_sysmodule.h" // _PySys_GetAttr() +#include "pycore_traceback.h" // _Py_DisplaySourceLine() + #include "clinic/_warnings.c.h" #define MODULE_NAME "_warnings" @@ -424,15 +425,15 @@ already_warned(PyInterpreterState *interp, PyObject *registry, PyObject *key, Py_DECREF(version_obj); } else { - already_warned = PyDict_GetItemWithError(registry, key); + if (PyDict_GetItemRef(registry, key, &already_warned) < 0) { + return -1; + } if (already_warned != NULL) { int rc = PyObject_IsTrue(already_warned); + Py_DECREF(already_warned); if (rc != 0) return rc; } - else if (PyErr_Occurred()) { - return -1; - } } /* This warning wasn't found in the registry, set it. */ diff --git a/Python/assemble.c b/Python/assemble.c index b7012534d6cc4e..569454ebf3b9cb 100644 --- a/Python/assemble.c +++ b/Python/assemble.c @@ -3,9 +3,8 @@ #include "Python.h" #include "pycore_code.h" // write_location_entry_start() #include "pycore_compile.h" -#include "pycore_opcode.h" // _PyOpcode_Caches[] and opcode category macros #include "pycore_opcode_utils.h" // IS_BACKWARDS_JUMP_OPCODE -#include "pycore_opcode_metadata.h" // IS_PSEUDO_INSTR +#include "pycore_opcode_metadata.h" // is_pseudo_target, _PyOpcode_Caches #define DEFAULT_CODE_SIZE 128 @@ -18,7 +17,7 @@ #define ERROR -1 #define RETURN_IF_ERROR(X) \ - if ((X) == -1) { \ + if ((X) < 0) { \ return ERROR; \ } @@ -448,13 +447,17 @@ static PyObject * dict_keys_inorder(PyObject *dict, Py_ssize_t offset) { PyObject *tuple, *k, *v; - Py_ssize_t i, pos = 0, size = PyDict_GET_SIZE(dict); + Py_ssize_t pos = 0, size = PyDict_GET_SIZE(dict); tuple = PyTuple_New(size); if (tuple == NULL) return NULL; while (PyDict_Next(dict, &pos, &k, &v)) { - i = PyLong_AS_LONG(v); + Py_ssize_t i = PyLong_AsSsize_t(v); + if (i == -1 && PyErr_Occurred()) { + Py_DECREF(tuple); + return NULL; + } assert((i - offset) < size); assert((i - offset) >= 0); PyTuple_SET_ITEM(tuple, i - offset, Py_NewRef(k)); @@ -466,24 +469,34 @@ dict_keys_inorder(PyObject *dict, Py_ssize_t offset) extern void _Py_set_localsplus_info(int, PyObject *, unsigned char, PyObject *, PyObject *); -static void +static int compute_localsplus_info(_PyCompile_CodeUnitMetadata *umd, int nlocalsplus, PyObject *names, PyObject *kinds) { PyObject *k, *v; Py_ssize_t pos = 0; while (PyDict_Next(umd->u_varnames, &pos, &k, &v)) { - int offset = (int)PyLong_AS_LONG(v); + int offset = PyLong_AsInt(v); + if (offset == -1 && PyErr_Occurred()) { + return ERROR; + } assert(offset >= 0); assert(offset < nlocalsplus); + // For now we do not distinguish arg kinds. _PyLocals_Kind kind = CO_FAST_LOCAL; - if (PyDict_Contains(umd->u_fasthidden, k)) { + int has_key = PyDict_Contains(umd->u_fasthidden, k); + RETURN_IF_ERROR(has_key); + if (has_key) { kind |= CO_FAST_HIDDEN; } - if (PyDict_GetItem(umd->u_cellvars, k) != NULL) { + + has_key = PyDict_Contains(umd->u_cellvars, k); + RETURN_IF_ERROR(has_key); + if (has_key) { kind |= CO_FAST_CELL; } + _Py_set_localsplus_info(offset, k, kind, names, kinds); } int nlocals = (int)PyDict_GET_SIZE(umd->u_varnames); @@ -492,12 +505,18 @@ compute_localsplus_info(_PyCompile_CodeUnitMetadata *umd, int nlocalsplus, int numdropped = 0; pos = 0; while (PyDict_Next(umd->u_cellvars, &pos, &k, &v)) { - if (PyDict_GetItem(umd->u_varnames, k) != NULL) { + int has_name = PyDict_Contains(umd->u_varnames, k); + RETURN_IF_ERROR(has_name); + if (has_name) { // Skip cells that are already covered by locals. numdropped += 1; continue; } - int offset = (int)PyLong_AS_LONG(v); + + int offset = PyLong_AsInt(v); + if (offset == -1 && PyErr_Occurred()) { + return ERROR; + } assert(offset >= 0); offset += nlocals - numdropped; assert(offset < nlocalsplus); @@ -506,12 +525,16 @@ compute_localsplus_info(_PyCompile_CodeUnitMetadata *umd, int nlocalsplus, pos = 0; while (PyDict_Next(umd->u_freevars, &pos, &k, &v)) { - int offset = (int)PyLong_AS_LONG(v); + int offset = PyLong_AsInt(v); + if (offset == -1 && PyErr_Occurred()) { + return ERROR; + } assert(offset >= 0); offset += nlocals - numdropped; assert(offset < nlocalsplus); _Py_set_localsplus_info(offset, k, CO_FAST_FREE, names, kinds); } + return SUCCESS; } static PyCodeObject * @@ -556,7 +579,10 @@ makecode(_PyCompile_CodeUnitMetadata *umd, struct assembler *a, PyObject *const_ if (localspluskinds == NULL) { goto error; } - compute_localsplus_info(umd, nlocalsplus, localsplusnames, localspluskinds); + if (compute_localsplus_info(umd, nlocalsplus, + localsplusnames, localspluskinds) == ERROR) { + goto error; + } struct _PyCodeConstructor con = { .filename = filename, @@ -684,13 +710,13 @@ resolve_unconditional_jumps(instr_sequence *instrs) bool is_forward = (instr->i_oparg > i); switch(instr->i_opcode) { case JUMP: - assert(SAME_OPCODE_METADATA(JUMP, JUMP_FORWARD)); - assert(SAME_OPCODE_METADATA(JUMP, JUMP_BACKWARD)); + assert(is_pseudo_target(JUMP, JUMP_FORWARD)); + assert(is_pseudo_target(JUMP, JUMP_BACKWARD)); instr->i_opcode = is_forward ? JUMP_FORWARD : JUMP_BACKWARD; break; case JUMP_NO_INTERRUPT: - assert(SAME_OPCODE_METADATA(JUMP_NO_INTERRUPT, JUMP_FORWARD)); - assert(SAME_OPCODE_METADATA(JUMP_NO_INTERRUPT, JUMP_BACKWARD_NO_INTERRUPT)); + assert(is_pseudo_target(JUMP_NO_INTERRUPT, JUMP_FORWARD)); + assert(is_pseudo_target(JUMP_NO_INTERRUPT, JUMP_BACKWARD_NO_INTERRUPT)); instr->i_opcode = is_forward ? JUMP_FORWARD : JUMP_BACKWARD_NO_INTERRUPT; break; diff --git a/Python/ast.c b/Python/ast.c index 74c97f948d15e6..5f46d4149c2ed0 100644 --- a/Python/ast.c +++ b/Python/ast.c @@ -381,6 +381,11 @@ validate_expr(struct validator *state, expr_ty exp, expr_context_ty ctx) ret = validate_exprs(state, exp->v.Tuple.elts, ctx, 0); break; case NamedExpr_kind: + if (exp->v.NamedExpr.target->kind != Name_kind) { + PyErr_SetString(PyExc_TypeError, + "NamedExpr target must be a Name"); + return 0; + } ret = validate_expr(state, exp->v.NamedExpr.value, Load); break; /* This last case doesn't have any checking. */ @@ -768,6 +773,11 @@ validate_stmt(struct validator *state, stmt_ty stmt) validate_expr(state, stmt->v.AnnAssign.annotation, Load); break; case TypeAlias_kind: + if (stmt->v.TypeAlias.name->kind != Name_kind) { + PyErr_SetString(PyExc_TypeError, + "TypeAlias with non-Name name"); + return 0; + } ret = validate_expr(state, stmt->v.TypeAlias.name, Store) && validate_type_params(state, stmt->v.TypeAlias.type_params) && validate_expr(state, stmt->v.TypeAlias.value, Load); @@ -1046,10 +1056,10 @@ _PyAST_Validate(mod_ty mod) return 0; } /* Be careful here to prevent overflow. */ - int recursion_depth = C_RECURSION_LIMIT - tstate->c_recursion_remaining; + int recursion_depth = Py_C_RECURSION_LIMIT - tstate->c_recursion_remaining; starting_recursion_depth = recursion_depth * COMPILER_STACK_FRAME_SCALE; state.recursion_depth = starting_recursion_depth; - state.recursion_limit = C_RECURSION_LIMIT * COMPILER_STACK_FRAME_SCALE; + state.recursion_limit = Py_C_RECURSION_LIMIT * COMPILER_STACK_FRAME_SCALE; switch (mod->kind) { case Module_kind: diff --git a/Python/ast_opt.c b/Python/ast_opt.c index 82e7559e5b629a..04d7ae6eaafbc0 100644 --- a/Python/ast_opt.c +++ b/Python/ast_opt.c @@ -142,15 +142,6 @@ check_complexity(PyObject *obj, Py_ssize_t limit) } return limit; } - else if (PyFrozenSet_Check(obj)) { - Py_ssize_t i = 0; - PyObject *item; - Py_hash_t hash; - limit -= PySet_GET_SIZE(obj); - while (limit >= 0 && _PySet_NextEntry(obj, &i, &item, &hash)) { - limit = check_complexity(item, limit); - } - } return limit; } @@ -174,9 +165,8 @@ safe_multiply(PyObject *v, PyObject *w) return NULL; } } - else if (PyLong_Check(v) && (PyTuple_Check(w) || PyFrozenSet_Check(w))) { - Py_ssize_t size = PyTuple_Check(w) ? PyTuple_GET_SIZE(w) : - PySet_GET_SIZE(w); + else if (PyLong_Check(v) && PyTuple_Check(w)) { + Py_ssize_t size = PyTuple_GET_SIZE(w); if (size) { long n = PyLong_AsLong(v); if (n < 0 || n > MAX_COLLECTION_SIZE / size) { @@ -198,8 +188,7 @@ safe_multiply(PyObject *v, PyObject *w) } } else if (PyLong_Check(w) && - (PyTuple_Check(v) || PyFrozenSet_Check(v) || - PyUnicode_Check(v) || PyBytes_Check(v))) + (PyTuple_Check(v) || PyUnicode_Check(v) || PyBytes_Check(v))) { return safe_multiply(w, v); } @@ -1130,10 +1119,10 @@ _PyAST_Optimize(mod_ty mod, PyArena *arena, int optimize, int ff_features) return 0; } /* Be careful here to prevent overflow. */ - int recursion_depth = C_RECURSION_LIMIT - tstate->c_recursion_remaining; + int recursion_depth = Py_C_RECURSION_LIMIT - tstate->c_recursion_remaining; starting_recursion_depth = recursion_depth * COMPILER_STACK_FRAME_SCALE; state.recursion_depth = starting_recursion_depth; - state.recursion_limit = C_RECURSION_LIMIT * COMPILER_STACK_FRAME_SCALE; + state.recursion_limit = Py_C_RECURSION_LIMIT * COMPILER_STACK_FRAME_SCALE; int ret = astfold_mod(mod, arena, &state); assert(ret || PyErr_Occurred()); diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index 9baf233614879e..e54d5cbacdc96f 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -1,21 +1,26 @@ /* Built-in functions */ #include "Python.h" -#include #include "pycore_ast.h" // _PyAST_Validate() #include "pycore_call.h" // _PyObject_CallNoArgs() #include "pycore_ceval.h" // _PyEval_Vector() #include "pycore_compile.h" // _PyAST_Compile() -#include "pycore_dict.h" // _PyDict_GetItemWithError() #include "pycore_long.h" // _PyLong_CompactValue #include "pycore_modsupport.h" // _PyArg_NoKwnames() #include "pycore_object.h" // _Py_AddToAllObjects() #include "pycore_pyerrors.h" // _PyErr_NoMemory() #include "pycore_pystate.h" // _PyThreadState_GET() +#include "pycore_pythonrun.h" // _Py_SourceAsString() +#include "pycore_sysmodule.h" // _PySys_GetAttr() #include "pycore_tuple.h" // _PyTuple_FromArray() #include "clinic/bltinmodule.c.h" +#ifdef HAVE_UNISTD_H +# include // isatty() +#endif + + static PyObject* update_bases(PyObject *bases, PyObject *const *args, Py_ssize_t nargs) { @@ -135,18 +140,16 @@ builtin___build_class__(PyObject *self, PyObject *const *args, Py_ssize_t nargs, goto error; } - meta = _PyDict_GetItemWithError(mkw, &_Py_ID(metaclass)); + if (PyDict_GetItemRef(mkw, &_Py_ID(metaclass), &meta) < 0) { + goto error; + } if (meta != NULL) { - Py_INCREF(meta); if (PyDict_DelItem(mkw, &_Py_ID(metaclass)) < 0) { goto error; } /* metaclass is explicitly given, check if it's indeed a class */ isclass = PyType_Check(meta); } - else if (PyErr_Occurred()) { - goto error; - } } if (meta == NULL) { /* if there are no bases, use type: */ @@ -476,6 +479,7 @@ builtin_breakpoint(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyOb PyDoc_STRVAR(breakpoint_doc, "breakpoint(*args, **kws)\n\ +--\n\ \n\ Call sys.breakpointhook(*args, **kws). sys.breakpointhook() must accept\n\ whatever arguments are passed.\n\ @@ -620,7 +624,8 @@ static PyMethodDef filter_methods[] = { }; PyDoc_STRVAR(filter_doc, -"filter(function or None, iterable) --> filter object\n\ +"filter(function, iterable, /)\n\ +--\n\ \n\ Return an iterator yielding those items of iterable for which function(item)\n\ is true. If function is None, return the items that are true."); @@ -804,23 +809,40 @@ builtin_compile_impl(PyObject *module, PyObject *source, PyObject *filename, if (is_ast == -1) goto error; if (is_ast) { - if (flags & PyCF_ONLY_AST) { + if ((flags & PyCF_OPTIMIZED_AST) == PyCF_ONLY_AST) { + // return an un-optimized AST result = Py_NewRef(source); } else { - PyArena *arena; - mod_ty mod; + // Return an optimized AST or code object - arena = _PyArena_New(); - if (arena == NULL) - goto error; - mod = PyAST_obj2mod(source, arena, compile_mode); - if (mod == NULL || !_PyAST_Validate(mod)) { - _PyArena_Free(arena); + PyArena *arena = _PyArena_New(); + if (arena == NULL) { goto error; } - result = (PyObject*)_PyAST_Compile(mod, filename, - &cf, optimize, arena); + + if (flags & PyCF_ONLY_AST) { + mod_ty mod = PyAST_obj2mod(source, arena, compile_mode); + if (mod == NULL || !_PyAST_Validate(mod)) { + _PyArena_Free(arena); + goto error; + } + if (_PyCompile_AstOptimize(mod, filename, &cf, optimize, + arena) < 0) { + _PyArena_Free(arena); + goto error; + } + result = PyAST_mod2obj(mod); + } + else { + mod_ty mod = PyAST_obj2mod(source, arena, compile_mode); + if (mod == NULL || !_PyAST_Validate(mod)) { + _PyArena_Free(arena); + goto error; + } + result = (PyObject*)_PyAST_Compile(mod, filename, + &cf, optimize, arena); + } _PyArena_Free(arena); } goto finally; @@ -842,33 +864,31 @@ builtin_compile_impl(PyObject *module, PyObject *source, PyObject *filename, return result; } -/*[clinic input] -dir as builtin_dir - - arg: object = NULL - / - -Show attributes of an object. - -If called without an argument, return the names in the current scope. -Else, return an alphabetized list of names comprising (some of) the attributes -of the given object, and of attributes reachable from it. -If the object supplies a method named __dir__, it will be used; otherwise -the default dir() logic is used and returns: - for a module object: the module's attributes. - for a class object: its attributes, and recursively the attributes - of its bases. - for any other object: its attributes, its class's attributes, and - recursively the attributes of its class's base classes. -[clinic start generated code]*/ - +/* AC: cannot convert yet, as needs PEP 457 group support in inspect */ static PyObject * -builtin_dir_impl(PyObject *module, PyObject *arg) -/*[clinic end generated code: output=24f2c7a52c1e3b08 input=ed6d6ccb13d52251]*/ +builtin_dir(PyObject *self, PyObject *args) { + PyObject *arg = NULL; + + if (!PyArg_UnpackTuple(args, "dir", 0, 1, &arg)) + return NULL; return PyObject_Dir(arg); } +PyDoc_STRVAR(dir_doc, +"dir([object]) -> list of strings\n" +"\n" +"If called without an argument, return the names in the current scope.\n" +"Else, return an alphabetized list of names comprising (some of) the attributes\n" +"of the given object, and of attributes reachable from it.\n" +"If the object supplies a method named __dir__, it will be used; otherwise\n" +"the default dir() logic is used and returns:\n" +" for a module object: the module's attributes.\n" +" for a class object: its attributes, and recursively the attributes\n" +" of its bases.\n" +" for any other object: its attributes, its class's attributes, and\n" +" recursively the attributes of its class's base classes."); + /*[clinic input] divmod as builtin_divmod @@ -1138,39 +1158,36 @@ builtin_exec_impl(PyObject *module, PyObject *source, PyObject *globals, } -/*[clinic input] -getattr as builtin_getattr - - object: object - name: object - default: object = NULL - / - -Get a named attribute from an object. - -getattr(x, 'y') is equivalent to x.y -When a default argument is given, it is returned when the attribute doesn't -exist; without it, an exception is raised in that case. -[clinic start generated code]*/ - +/* AC: cannot convert yet, as needs PEP 457 group support in inspect */ static PyObject * -builtin_getattr_impl(PyObject *module, PyObject *object, PyObject *name, - PyObject *default_value) -/*[clinic end generated code: output=74ad0e225e3f701c input=d7562cd4c3556171]*/ +builtin_getattr(PyObject *self, PyObject *const *args, Py_ssize_t nargs) { - PyObject *result; + PyObject *v, *name, *result; + + if (!_PyArg_CheckPositional("getattr", nargs, 2, 3)) + return NULL; - if (default_value != NULL) { - if (PyObject_GetOptionalAttr(object, name, &result) == 0) { - return Py_NewRef(default_value); + v = args[0]; + name = args[1]; + if (nargs > 2) { + if (PyObject_GetOptionalAttr(v, name, &result) == 0) { + PyObject *dflt = args[2]; + return Py_NewRef(dflt); } } else { - result = PyObject_GetAttr(object, name); + result = PyObject_GetAttr(v, name); } return result; } +PyDoc_STRVAR(getattr_doc, +"getattr(object, name[, default]) -> value\n\ +\n\ +Get a named attribute from an object; getattr(x, 'y') is equivalent to x.y.\n\ +When a default argument is given, it is returned when the attribute doesn't\n\ +exist; without it, an exception is raised in that case."); + /*[clinic input] globals as builtin_globals @@ -1431,7 +1448,8 @@ static PyMethodDef map_methods[] = { PyDoc_STRVAR(map_doc, -"map(func, *iterables) --> map object\n\ +"map(function, /, *iterables)\n\ +--\n\ \n\ Make an iterator that computes the function using arguments from\n\ each of the iterables. Stops when the shortest iterable is exhausted."); @@ -1482,43 +1500,34 @@ PyTypeObject PyMap_Type = { }; -/*[clinic input] -next as builtin_next - - iterator: object - default: object = NULL - / - -Return the next item from the iterator. - -If default is given and the iterator is exhausted, -it is returned instead of raising StopIteration. -[clinic start generated code]*/ - +/* AC: cannot convert yet, as needs PEP 457 group support in inspect */ static PyObject * -builtin_next_impl(PyObject *module, PyObject *iterator, - PyObject *default_value) -/*[clinic end generated code: output=a38a94eeb447fef9 input=180f9984f182020f]*/ +builtin_next(PyObject *self, PyObject *const *args, Py_ssize_t nargs) { - PyObject *res; + PyObject *it, *res; - if (!PyIter_Check(iterator)) { + if (!_PyArg_CheckPositional("next", nargs, 1, 2)) + return NULL; + + it = args[0]; + if (!PyIter_Check(it)) { PyErr_Format(PyExc_TypeError, "'%.200s' object is not an iterator", - Py_TYPE(iterator)->tp_name); + Py_TYPE(it)->tp_name); return NULL; } - res = (*Py_TYPE(iterator)->tp_iternext)(iterator); + res = (*Py_TYPE(it)->tp_iternext)(it); if (res != NULL) { return res; - } else if (default_value != NULL) { + } else if (nargs > 1) { + PyObject *def = args[1]; if (PyErr_Occurred()) { if(!PyErr_ExceptionMatches(PyExc_StopIteration)) return NULL; PyErr_Clear(); } - return Py_NewRef(default_value); + return Py_NewRef(def); } else if (PyErr_Occurred()) { return NULL; } else { @@ -1527,6 +1536,12 @@ builtin_next_impl(PyObject *module, PyObject *iterator, } } +PyDoc_STRVAR(next_doc, +"next(iterator[, default])\n\ +\n\ +Return the next item from the iterator. If default is given and the iterator\n\ +is exhausted, it is returned instead of raising StopIteration."); + /*[clinic input] setattr as builtin_setattr @@ -1620,33 +1635,34 @@ builtin_hex(PyObject *module, PyObject *number) } -/*[clinic input] -iter as builtin_iter - - object: object - sentinel: object = NULL - / - -Get an iterator from an object. - -In the first form, the argument must supply its own iterator, or be a sequence. -In the second form, the callable is called until it returns the sentinel. -[clinic start generated code]*/ - +/* AC: cannot convert yet, as needs PEP 457 group support in inspect */ static PyObject * -builtin_iter_impl(PyObject *module, PyObject *object, PyObject *sentinel) -/*[clinic end generated code: output=12cf64203c195a94 input=a5d64d9d81880ba6]*/ +builtin_iter(PyObject *self, PyObject *const *args, Py_ssize_t nargs) { - if (sentinel == NULL) - return PyObject_GetIter(object); - if (!PyCallable_Check(object)) { + PyObject *v; + + if (!_PyArg_CheckPositional("iter", nargs, 1, 2)) + return NULL; + v = args[0]; + if (nargs == 1) + return PyObject_GetIter(v); + if (!PyCallable_Check(v)) { PyErr_SetString(PyExc_TypeError, - "iter(object, sentinel): object must be callable"); + "iter(v, w): v must be callable"); return NULL; } - return PyCallIter_New(object, sentinel); + PyObject *sentinel = args[1]; + return PyCallIter_New(v, sentinel); } +PyDoc_STRVAR(iter_doc, +"iter(iterable) -> iterator\n\ +iter(callable, sentinel) -> iterator\n\ +\n\ +Get an iterator from an object. In the first form, the argument must\n\ +supply its own iterator, or be a sequence.\n\ +In the second form, the callable is called until it returns the sentinel."); + /*[clinic input] aiter as builtin_aiter @@ -1750,35 +1766,27 @@ builtin_locals_impl(PyObject *module) static PyObject * -min_max(PyObject *args, PyObject *kwds, int op) +min_max(PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames, int op) { - PyObject *v, *it, *item, *val, *maxitem, *maxval, *keyfunc=NULL; - PyObject *emptytuple, *defaultval = NULL; - static char *kwlist[] = {"key", "default", NULL}; - const char *name = op == Py_LT ? "min" : "max"; - const int positional = PyTuple_Size(args) > 1; - int ret; + PyObject *it = NULL, *item, *val, *maxitem, *maxval, *keyfunc=NULL; + PyObject *defaultval = NULL; + static const char * const keywords[] = {"key", "default", NULL}; + static _PyArg_Parser _parser_min = {"|$OO:min", keywords, 0}; + static _PyArg_Parser _parser_max = {"|$OO:max", keywords, 0}; + const char *name = (op == Py_LT) ? "min" : "max"; + _PyArg_Parser *_parser = (op == Py_LT) ? &_parser_min : &_parser_max; - if (positional) { - v = args; - } - else if (!PyArg_UnpackTuple(args, name, 1, 1, &v)) { - if (PyExceptionClass_Check(PyExc_TypeError)) { - PyErr_Format(PyExc_TypeError, "%s expected at least 1 argument, got 0", name); - } + if (nargs == 0) { + PyErr_Format(PyExc_TypeError, "%s expected at least 1 argument, got 0", name); return NULL; } - emptytuple = PyTuple_New(0); - if (emptytuple == NULL) - return NULL; - ret = PyArg_ParseTupleAndKeywords(emptytuple, kwds, - (op == Py_LT) ? "|$OO:min" : "|$OO:max", - kwlist, &keyfunc, &defaultval); - Py_DECREF(emptytuple); - if (!ret) + if (kwnames != NULL && !_PyArg_ParseStackAndKeywords(args + nargs, 0, kwnames, _parser, + &keyfunc, &defaultval)) { return NULL; + } + const int positional = nargs > 1; // False iff nargs == 1 if (positional && defaultval != NULL) { PyErr_Format(PyExc_TypeError, "Cannot specify a default for %s() with multiple " @@ -1786,9 +1794,11 @@ min_max(PyObject *args, PyObject *kwds, int op) return NULL; } - it = PyObject_GetIter(v); - if (it == NULL) { - return NULL; + if (!positional) { + it = PyObject_GetIter(args[0]); + if (it == NULL) { + return NULL; + } } if (keyfunc == Py_None) { @@ -1797,7 +1807,24 @@ min_max(PyObject *args, PyObject *kwds, int op) maxitem = NULL; /* the result */ maxval = NULL; /* the value associated with the result */ - while (( item = PyIter_Next(it) )) { + while (1) { + if (it == NULL) { + if (nargs-- <= 0) { + break; + } + item = *args++; + Py_INCREF(item); + } + else { + item = PyIter_Next(it); + if (item == NULL) { + if (PyErr_Occurred()) { + goto Fail_it; + } + break; + } + } + /* get the value from the key function */ if (keyfunc != NULL) { val = PyObject_CallOneArg(keyfunc, item); @@ -1831,8 +1858,6 @@ min_max(PyObject *args, PyObject *kwds, int op) } } } - if (PyErr_Occurred()) - goto Fail_it; if (maxval == NULL) { assert(maxitem == NULL); if (defaultval != NULL) { @@ -1844,7 +1869,7 @@ min_max(PyObject *args, PyObject *kwds, int op) } else Py_DECREF(maxval); - Py_DECREF(it); + Py_XDECREF(it); return maxitem; Fail_it_item_and_val: @@ -1854,15 +1879,15 @@ min_max(PyObject *args, PyObject *kwds, int op) Fail_it: Py_XDECREF(maxval); Py_XDECREF(maxitem); - Py_DECREF(it); + Py_XDECREF(it); return NULL; } /* AC: cannot convert yet, waiting for *args support */ static PyObject * -builtin_min(PyObject *self, PyObject *args, PyObject *kwds) +builtin_min(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { - return min_max(args, kwds, Py_LT); + return min_max(args, nargs, kwnames, Py_LT); } PyDoc_STRVAR(min_doc, @@ -1872,14 +1897,14 @@ min(arg1, arg2, *args, *[, key=func]) -> value\n\ With a single iterable argument, return its smallest item. The\n\ default keyword-only argument specifies an object to return if\n\ the provided iterable is empty.\n\ -With two or more arguments, return the smallest argument."); +With two or more positional arguments, return the smallest argument."); /* AC: cannot convert yet, waiting for *args support */ static PyObject * -builtin_max(PyObject *self, PyObject *args, PyObject *kwds) +builtin_max(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { - return min_max(args, kwds, Py_GT); + return min_max(args, nargs, kwnames, Py_GT); } PyDoc_STRVAR(max_doc, @@ -1889,7 +1914,7 @@ max(arg1, arg2, *args, *[, key=func]) -> value\n\ With a single iterable argument, return its biggest item. The\n\ default keyword-only argument specifies an object to return if\n\ the provided iterable is empty.\n\ -With two or more arguments, return the largest argument."); +With two or more positional arguments, return the largest argument."); /*[clinic input] @@ -2072,11 +2097,9 @@ builtin_print_impl(PyObject *module, PyObject *args, PyObject *sep, } if (flush) { - PyObject *tmp = PyObject_CallMethodNoArgs(file, &_Py_ID(flush)); - if (tmp == NULL) { + if (_PyFile_Flush(file) < 0) { return NULL; } - Py_DECREF(tmp); } Py_RETURN_NONE; @@ -2135,11 +2158,9 @@ builtin_input_impl(PyObject *module, PyObject *prompt) } /* First of all, flush stderr */ - tmp = PyObject_CallMethodNoArgs(ferr, &_Py_ID(flush)); - if (tmp == NULL) + if (_PyFile_Flush(ferr) < 0) { PyErr_Clear(); - else - Py_DECREF(tmp); + } /* We should only use (GNU) readline if Python's sys.stdin and sys.stdout are the same as C's stdin and stdout, because we @@ -2207,11 +2228,9 @@ builtin_input_impl(PyObject *module, PyObject *prompt) if (stdin_errors_str == NULL) { goto _readline_errors; } - tmp = PyObject_CallMethodNoArgs(fout, &_Py_ID(flush)); - if (tmp == NULL) + if (_PyFile_Flush(fout) < 0) { PyErr_Clear(); - else - Py_DECREF(tmp); + } if (prompt != NULL) { /* We have a prompt, encode it as stdout would */ const char *stdout_encoding_str, *stdout_errors_str; @@ -2252,6 +2271,11 @@ builtin_input_impl(PyObject *module, PyObject *prompt) goto _readline_errors; assert(PyBytes_Check(po)); promptstr = PyBytes_AS_STRING(po); + if ((Py_ssize_t)strlen(promptstr) != PyBytes_GET_SIZE(po)) { + PyErr_SetString(PyExc_ValueError, + "input: prompt string cannot contain null characters"); + goto _readline_errors; + } } else { po = NULL; @@ -2314,11 +2338,9 @@ builtin_input_impl(PyObject *module, PyObject *prompt) if (PyFile_WriteObject(prompt, fout, Py_PRINT_RAW) != 0) return NULL; } - tmp = PyObject_CallMethodNoArgs(fout, &_Py_ID(flush)); - if (tmp == NULL) + if (_PyFile_Flush(fout) < 0) { PyErr_Clear(); - else - Py_DECREF(tmp); + } return PyFile_GetLine(fin, -1); } @@ -2444,29 +2466,20 @@ builtin_sorted(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject } -/*[clinic input] -vars as builtin_vars - - object: object = NULL - / - -Show vars. - -Without arguments, equivalent to locals(). -With an argument, equivalent to object.__dict__. -[clinic start generated code]*/ - +/* AC: cannot convert yet, as needs PEP 457 group support in inspect */ static PyObject * -builtin_vars_impl(PyObject *module, PyObject *object) -/*[clinic end generated code: output=840a7f64007a3e0a input=80cbdef9182c4ba3]*/ +builtin_vars(PyObject *self, PyObject *args) { + PyObject *v = NULL; PyObject *d; - if (object == NULL) { + if (!PyArg_UnpackTuple(args, "vars", 0, 1, &v)) + return NULL; + if (v == NULL) { d = _PyEval_GetFrameLocals(); } else { - if (PyObject_GetOptionalAttr(object, &_Py_ID(__dict__), &d) == 0) { + if (PyObject_GetOptionalAttr(v, &_Py_ID(__dict__), &d) == 0) { PyErr_SetString(PyExc_TypeError, "vars() argument must have __dict__ attribute"); } @@ -2474,6 +2487,12 @@ builtin_vars_impl(PyObject *module, PyObject *object) return d; } +PyDoc_STRVAR(vars_doc, +"vars([object]) -> dictionary\n\ +\n\ +Without arguments, equivalent to locals().\n\ +With an argument, equivalent to object.__dict__."); + /*[clinic input] sum as builtin_sum @@ -2606,7 +2625,10 @@ builtin_sum_impl(PyObject *module, PyObject *iterable, PyObject *start) } if (PyFloat_CheckExact(item)) { // Improved Kahan–BabuÅ¡ka algorithm by Arnold Neumaier - // https://www.mat.univie.ac.at/~neum/scan/01.pdf + // Neumaier, A. (1974), Rundungsfehleranalyse einiger Verfahren + // zur Summation endlicher Summen. Z. angew. Math. Mech., + // 54: 39-51. https://doi.org/10.1002/zamm.19740540106 + // https://en.wikipedia.org/wiki/Kahan_summation_algorithm#Further_enhancements double x = PyFloat_AS_DOUBLE(item); double t = f_result + x; if (fabs(f_result) >= fabs(x)) { @@ -2950,10 +2972,8 @@ static PyMethodDef zip_methods[] = { }; PyDoc_STRVAR(zip_doc, -"zip(*iterables, strict=False) --> Yield tuples until an input is exhausted.\n\ -\n\ - >>> list(zip('abcdefg', range(3), range(4)))\n\ - [('a', 0, 0), ('b', 1, 1), ('c', 2, 2)]\n\ +"zip(*iterables, strict=False)\n\ +--\n\ \n\ The zip object yields n-length tuples, where n is the number of iterables\n\ passed as positional arguments to zip(). The i-th element in every tuple\n\ @@ -2961,7 +2981,10 @@ comes from the i-th iterable argument to zip(). This continues until the\n\ shortest argument is exhausted.\n\ \n\ If strict is true and one of the arguments is exhausted before the others,\n\ -raise a ValueError."); +raise a ValueError.\n\ +\n\ + >>> list(zip('abcdefg', range(3), range(4)))\n\ + [('a', 0, 0), ('b', 1, 1), ('c', 2, 2)]"); PyTypeObject PyZip_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) @@ -3022,12 +3045,12 @@ static PyMethodDef builtin_methods[] = { BUILTIN_CHR_METHODDEF BUILTIN_COMPILE_METHODDEF BUILTIN_DELATTR_METHODDEF - BUILTIN_DIR_METHODDEF + {"dir", builtin_dir, METH_VARARGS, dir_doc}, BUILTIN_DIVMOD_METHODDEF BUILTIN_EVAL_METHODDEF BUILTIN_EXEC_METHODDEF BUILTIN_FORMAT_METHODDEF - BUILTIN_GETATTR_METHODDEF + {"getattr", _PyCFunction_CAST(builtin_getattr), METH_FASTCALL, getattr_doc}, BUILTIN_GLOBALS_METHODDEF BUILTIN_HASATTR_METHODDEF BUILTIN_HASH_METHODDEF @@ -3036,13 +3059,13 @@ static PyMethodDef builtin_methods[] = { BUILTIN_INPUT_METHODDEF BUILTIN_ISINSTANCE_METHODDEF BUILTIN_ISSUBCLASS_METHODDEF - BUILTIN_ITER_METHODDEF + {"iter", _PyCFunction_CAST(builtin_iter), METH_FASTCALL, iter_doc}, BUILTIN_AITER_METHODDEF BUILTIN_LEN_METHODDEF BUILTIN_LOCALS_METHODDEF - {"max", _PyCFunction_CAST(builtin_max), METH_VARARGS | METH_KEYWORDS, max_doc}, - {"min", _PyCFunction_CAST(builtin_min), METH_VARARGS | METH_KEYWORDS, min_doc}, - BUILTIN_NEXT_METHODDEF + {"max", _PyCFunction_CAST(builtin_max), METH_FASTCALL | METH_KEYWORDS, max_doc}, + {"min", _PyCFunction_CAST(builtin_min), METH_FASTCALL | METH_KEYWORDS, min_doc}, + {"next", _PyCFunction_CAST(builtin_next), METH_FASTCALL, next_doc}, BUILTIN_ANEXT_METHODDEF BUILTIN_OCT_METHODDEF BUILTIN_ORD_METHODDEF @@ -3053,7 +3076,7 @@ static PyMethodDef builtin_methods[] = { BUILTIN_SETATTR_METHODDEF BUILTIN_SORTED_METHODDEF BUILTIN_SUM_METHODDEF - BUILTIN_VARS_METHODDEF + {"vars", builtin_vars, METH_VARARGS, vars_doc}, {NULL, NULL}, }; @@ -3101,7 +3124,7 @@ _PyBuiltin_Init(PyInterpreterState *interp) * result, programs leaking references to None and False (etc) * couldn't be diagnosed by examining sys.getobjects(0). */ -#define ADD_TO_ALL(OBJECT) _Py_AddToAllObjects((PyObject *)(OBJECT), 0) +#define ADD_TO_ALL(OBJECT) _Py_AddToAllObjects((PyObject *)(OBJECT)) #else #define ADD_TO_ALL(OBJECT) (void)0 #endif diff --git a/Python/bootstrap_hash.c b/Python/bootstrap_hash.c index ef693e5df1fcc4..92f2301a012c0a 100644 --- a/Python/bootstrap_hash.c +++ b/Python/bootstrap_hash.c @@ -4,22 +4,25 @@ #include "pycore_pylifecycle.h" // _PyOS_URandomNonblock() #include "pycore_runtime.h" // _PyRuntime +#ifdef HAVE_UNISTD_H +# include // close() +#endif #ifdef MS_WINDOWS # include # include #else -# include +# include // O_RDONLY # ifdef HAVE_SYS_STAT_H # include # endif # ifdef HAVE_LINUX_RANDOM_H -# include +# include // GRND_NONBLOCK # endif # if defined(HAVE_SYS_RANDOM_H) && (defined(HAVE_GETRANDOM) || defined(HAVE_GETENTROPY)) -# include +# include // getrandom() # endif # if !defined(HAVE_GETRANDOM) && defined(HAVE_GETRANDOM_SYSCALL) -# include +# include // SYS_getrandom # endif #endif diff --git a/Python/bytecodes.c b/Python/bytecodes.c index 90e26d3c86b380..2011d963e3687c 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -17,7 +17,6 @@ #include "pycore_long.h" // _PyLong_GetZero() #include "pycore_moduleobject.h" // PyModuleObject #include "pycore_object.h" // _PyObject_GC_TRACK() -#include "pycore_opcode.h" // EXTRA_CASES #include "pycore_opcode_metadata.h" // uop names #include "pycore_opcode_utils.h" // MAKE_FUNCTION_* #include "pycore_pyerrors.h" // _PyErr_GetRaisedException() @@ -42,8 +41,6 @@ #include "ceval_macros.h" /* Flow control macros */ -#define DEOPT_IF(cond, instname) ((void)0) -#define ERROR_IF(cond, labelname) ((void)0) #define GO_TO_INSTRUCTION(instname) ((void)0) #define inst(name, ...) case name: @@ -53,6 +50,11 @@ #define family(name, ...) static int family_##name #define pseudo(name) static int pseudo_##name +/* Annotations */ +#define guard +#define override +#define specializing + // Dummy variables for stack effects. static PyObject *value, *value1, *value2, *left, *right, *res, *sum, *prod, *sub; static PyObject *container, *start, *stop, *v, *lhs, *rhs, *res2; @@ -66,6 +68,7 @@ static size_t jump; static uint16_t invert, counter, index, hint; #define unused 0 // Used in a macro def, can't be static static uint32_t type_version; +static _PyUOpExecutorObject *current_executor; static PyObject * dummy_func( @@ -73,10 +76,8 @@ dummy_func( _PyInterpreterFrame *frame, unsigned char opcode, unsigned int oparg, - _PyCFrame cframe, _Py_CODEUNIT *next_instr, PyObject **stack_pointer, - PyObject *kwnames, int throwflag, PyObject *args[] ) @@ -85,6 +86,7 @@ dummy_func( pop_1_error: // Dummy locals. PyObject *dummy; + _Py_CODEUNIT *this_instr; PyObject *attr; PyObject *attrs; PyObject *bottom; @@ -134,43 +136,63 @@ dummy_func( inst(NOP, (--)) { } + family(RESUME, 0) = { + RESUME_CHECK, + }; + inst(RESUME, (--)) { - assert(tstate->cframe == &cframe); - assert(frame == cframe.current_frame); - /* Possibly combine this with eval breaker */ - if (_PyFrame_GetCode(frame)->_co_instrumentation_version != tstate->interp->monitoring_version) { + TIER_ONE_ONLY + assert(frame == tstate->current_frame); + uintptr_t global_version = + _Py_atomic_load_uintptr_relaxed(&tstate->interp->ceval.eval_breaker) & + ~_PY_EVAL_EVENTS_MASK; + uintptr_t code_version = _PyFrame_GetCode(frame)->_co_instrumentation_version; + assert((code_version & 255) == 0); + if (code_version != global_version) { int err = _Py_Instrument(_PyFrame_GetCode(frame), tstate->interp); ERROR_IF(err, error); - next_instr--; + next_instr = this_instr; } - else if (oparg < 2) { - CHECK_EVAL_BREAKER(); + else { + if ((oparg & RESUME_OPARG_LOCATION_MASK) < RESUME_AFTER_YIELD_FROM) { + CHECK_EVAL_BREAKER(); + } + this_instr->op.code = RESUME_CHECK; } } + inst(RESUME_CHECK, (--)) { +#if defined(__EMSCRIPTEN__) + DEOPT_IF(_Py_emscripten_signal_clock == 0); + _Py_emscripten_signal_clock -= Py_EMSCRIPTEN_SIGNAL_HANDLING; +#endif + uintptr_t eval_breaker = _Py_atomic_load_uintptr_relaxed(&tstate->interp->ceval.eval_breaker); + uintptr_t version = _PyFrame_GetCode(frame)->_co_instrumentation_version; + assert((version & _PY_EVAL_EVENTS_MASK) == 0); + DEOPT_IF(eval_breaker != version); + } + inst(INSTRUMENTED_RESUME, (--)) { - /* Possible performance enhancement: - * We need to check the eval breaker anyway, can we - * combine the instrument verison check and the eval breaker test? - */ - if (_PyFrame_GetCode(frame)->_co_instrumentation_version != tstate->interp->monitoring_version) { + uintptr_t global_version = _Py_atomic_load_uintptr_relaxed(&tstate->interp->ceval.eval_breaker) & ~_PY_EVAL_EVENTS_MASK; + uintptr_t code_version = _PyFrame_GetCode(frame)->_co_instrumentation_version; + if (code_version != global_version) { if (_Py_Instrument(_PyFrame_GetCode(frame), tstate->interp)) { - goto error; + GOTO_ERROR(error); } - next_instr--; + next_instr = this_instr; } else { - if (oparg < 2) { + if ((oparg & RESUME_OPARG_LOCATION_MASK) < RESUME_AFTER_YIELD_FROM) { CHECK_EVAL_BREAKER(); } _PyFrame_SetStackPointer(frame, stack_pointer); int err = _Py_call_instrumentation( - tstate, oparg > 0, frame, next_instr-1); + tstate, oparg > 0, frame, this_instr); stack_pointer = _PyFrame_GetStackPointer(frame); ERROR_IF(err, error); - if (frame->prev_instr != next_instr-1) { + if (frame->instr_ptr != this_instr) { /* Instrumentation has jumped */ - next_instr = frame->prev_instr; + next_instr = this_instr; DISPATCH(); } } @@ -246,12 +268,13 @@ dummy_func( macro(END_FOR) = POP_TOP + POP_TOP; inst(INSTRUMENTED_END_FOR, (receiver, value --)) { + TIER_ONE_ONLY /* Need to create a fake StopIteration error here, * to conform to PEP 380 */ if (PyGen_Check(receiver)) { PyErr_SetObject(PyExc_StopIteration, value); - if (monitor_stop_iteration(tstate, frame, next_instr-1)) { - goto error; + if (monitor_stop_iteration(tstate, frame, this_instr)) { + GOTO_ERROR(error); } PyErr_SetRaisedException(NULL); } @@ -263,10 +286,11 @@ dummy_func( } inst(INSTRUMENTED_END_SEND, (receiver, value -- value)) { + TIER_ONE_ONLY if (PyGen_Check(receiver) || PyCoro_CheckExact(receiver)) { PyErr_SetObject(PyExc_StopIteration, value); - if (monitor_stop_iteration(tstate, frame, next_instr-1)) { - goto error; + if (monitor_stop_iteration(tstate, frame, this_instr)) { + GOTO_ERROR(error); } PyErr_SetRaisedException(NULL); } @@ -293,30 +317,35 @@ dummy_func( TO_BOOL_STR, }; - inst(TO_BOOL, (unused/1, unused/2, value -- res)) { + specializing op(_SPECIALIZE_TO_BOOL, (counter/1, value -- value)) { + TIER_ONE_ONLY #if ENABLE_SPECIALIZATION - _PyToBoolCache *cache = (_PyToBoolCache *)next_instr; - if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) { - next_instr--; + if (ADAPTIVE_COUNTER_IS_ZERO(counter)) { + next_instr = this_instr; _Py_Specialize_ToBool(value, next_instr); DISPATCH_SAME_OPARG(); } STAT_INC(TO_BOOL, deferred); - DECREMENT_ADAPTIVE_COUNTER(cache->counter); + DECREMENT_ADAPTIVE_COUNTER(this_instr[1].cache); #endif /* ENABLE_SPECIALIZATION */ + } + + op(_TO_BOOL, (value -- res)) { int err = PyObject_IsTrue(value); DECREF_INPUTS(); ERROR_IF(err < 0, error); res = err ? Py_True : Py_False; } + macro(TO_BOOL) = _SPECIALIZE_TO_BOOL + unused/2 + _TO_BOOL; + inst(TO_BOOL_BOOL, (unused/1, unused/2, value -- value)) { - DEOPT_IF(!PyBool_Check(value), TO_BOOL); + DEOPT_IF(!PyBool_Check(value)); STAT_INC(TO_BOOL, hit); } inst(TO_BOOL_INT, (unused/1, unused/2, value -- res)) { - DEOPT_IF(!PyLong_CheckExact(value), TO_BOOL); + DEOPT_IF(!PyLong_CheckExact(value)); STAT_INC(TO_BOOL, hit); if (_PyLong_IsZero((PyLongObject *)value)) { assert(_Py_IsImmortal(value)); @@ -329,7 +358,7 @@ dummy_func( } inst(TO_BOOL_LIST, (unused/1, unused/2, value -- res)) { - DEOPT_IF(!PyList_CheckExact(value), TO_BOOL); + DEOPT_IF(!PyList_CheckExact(value)); STAT_INC(TO_BOOL, hit); res = Py_SIZE(value) ? Py_True : Py_False; DECREF_INPUTS(); @@ -337,13 +366,13 @@ dummy_func( inst(TO_BOOL_NONE, (unused/1, unused/2, value -- res)) { // This one is a bit weird, because we expect *some* failures: - DEOPT_IF(!Py_IsNone(value), TO_BOOL); + DEOPT_IF(!Py_IsNone(value)); STAT_INC(TO_BOOL, hit); res = Py_False; } inst(TO_BOOL_STR, (unused/1, unused/2, value -- res)) { - DEOPT_IF(!PyUnicode_CheckExact(value), TO_BOOL); + DEOPT_IF(!PyUnicode_CheckExact(value)); STAT_INC(TO_BOOL, hit); if (value == &_Py_STR(empty)) { assert(_Py_IsImmortal(value)); @@ -359,7 +388,7 @@ dummy_func( inst(TO_BOOL_ALWAYS_TRUE, (unused/1, version/2, value -- res)) { // This one is a bit weird, because we expect *some* failures: assert(version); - DEOPT_IF(Py_TYPE(value)->tp_version_tag != version, TO_BOOL); + DEOPT_IF(Py_TYPE(value)->tp_version_tag != version); STAT_INC(TO_BOOL, hit); DECREF_INPUTS(); res = Py_True; @@ -383,11 +412,11 @@ dummy_func( }; op(_GUARD_BOTH_INT, (left, right -- left, right)) { - DEOPT_IF(!PyLong_CheckExact(left), BINARY_OP); - DEOPT_IF(!PyLong_CheckExact(right), BINARY_OP); + DEOPT_IF(!PyLong_CheckExact(left)); + DEOPT_IF(!PyLong_CheckExact(right)); } - op(_BINARY_OP_MULTIPLY_INT, (unused/1, left, right -- res)) { + op(_BINARY_OP_MULTIPLY_INT, (left, right -- res)) { STAT_INC(BINARY_OP, hit); res = _PyLong_Multiply((PyLongObject *)left, (PyLongObject *)right); _Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free); @@ -395,7 +424,7 @@ dummy_func( ERROR_IF(res == NULL, error); } - op(_BINARY_OP_ADD_INT, (unused/1, left, right -- res)) { + op(_BINARY_OP_ADD_INT, (left, right -- res)) { STAT_INC(BINARY_OP, hit); res = _PyLong_Add((PyLongObject *)left, (PyLongObject *)right); _Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free); @@ -403,7 +432,7 @@ dummy_func( ERROR_IF(res == NULL, error); } - op(_BINARY_OP_SUBTRACT_INT, (unused/1, left, right -- res)) { + op(_BINARY_OP_SUBTRACT_INT, (left, right -- res)) { STAT_INC(BINARY_OP, hit); res = _PyLong_Subtract((PyLongObject *)left, (PyLongObject *)right); _Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free); @@ -412,18 +441,18 @@ dummy_func( } macro(BINARY_OP_MULTIPLY_INT) = - _GUARD_BOTH_INT + _BINARY_OP_MULTIPLY_INT; + _GUARD_BOTH_INT + unused/1 + _BINARY_OP_MULTIPLY_INT; macro(BINARY_OP_ADD_INT) = - _GUARD_BOTH_INT + _BINARY_OP_ADD_INT; + _GUARD_BOTH_INT + unused/1 + _BINARY_OP_ADD_INT; macro(BINARY_OP_SUBTRACT_INT) = - _GUARD_BOTH_INT + _BINARY_OP_SUBTRACT_INT; + _GUARD_BOTH_INT + unused/1 + _BINARY_OP_SUBTRACT_INT; op(_GUARD_BOTH_FLOAT, (left, right -- left, right)) { - DEOPT_IF(!PyFloat_CheckExact(left), BINARY_OP); - DEOPT_IF(!PyFloat_CheckExact(right), BINARY_OP); + DEOPT_IF(!PyFloat_CheckExact(left)); + DEOPT_IF(!PyFloat_CheckExact(right)); } - op(_BINARY_OP_MULTIPLY_FLOAT, (unused/1, left, right -- res)) { + op(_BINARY_OP_MULTIPLY_FLOAT, (left, right -- res)) { STAT_INC(BINARY_OP, hit); double dres = ((PyFloatObject *)left)->ob_fval * @@ -431,7 +460,7 @@ dummy_func( DECREF_INPUTS_AND_REUSE_FLOAT(left, right, dres, res); } - op(_BINARY_OP_ADD_FLOAT, (unused/1, left, right -- res)) { + op(_BINARY_OP_ADD_FLOAT, (left, right -- res)) { STAT_INC(BINARY_OP, hit); double dres = ((PyFloatObject *)left)->ob_fval + @@ -439,7 +468,7 @@ dummy_func( DECREF_INPUTS_AND_REUSE_FLOAT(left, right, dres, res); } - op(_BINARY_OP_SUBTRACT_FLOAT, (unused/1, left, right -- res)) { + op(_BINARY_OP_SUBTRACT_FLOAT, (left, right -- res)) { STAT_INC(BINARY_OP, hit); double dres = ((PyFloatObject *)left)->ob_fval - @@ -448,18 +477,18 @@ dummy_func( } macro(BINARY_OP_MULTIPLY_FLOAT) = - _GUARD_BOTH_FLOAT + _BINARY_OP_MULTIPLY_FLOAT; + _GUARD_BOTH_FLOAT + unused/1 + _BINARY_OP_MULTIPLY_FLOAT; macro(BINARY_OP_ADD_FLOAT) = - _GUARD_BOTH_FLOAT + _BINARY_OP_ADD_FLOAT; + _GUARD_BOTH_FLOAT + unused/1 + _BINARY_OP_ADD_FLOAT; macro(BINARY_OP_SUBTRACT_FLOAT) = - _GUARD_BOTH_FLOAT + _BINARY_OP_SUBTRACT_FLOAT; + _GUARD_BOTH_FLOAT + unused/1 + _BINARY_OP_SUBTRACT_FLOAT; op(_GUARD_BOTH_UNICODE, (left, right -- left, right)) { - DEOPT_IF(!PyUnicode_CheckExact(left), BINARY_OP); - DEOPT_IF(!PyUnicode_CheckExact(right), BINARY_OP); + DEOPT_IF(!PyUnicode_CheckExact(left)); + DEOPT_IF(!PyUnicode_CheckExact(right)); } - op(_BINARY_OP_ADD_UNICODE, (unused/1, left, right -- res)) { + op(_BINARY_OP_ADD_UNICODE, (left, right -- res)) { STAT_INC(BINARY_OP, hit); res = PyUnicode_Concat(left, right); _Py_DECREF_SPECIALIZED(left, _PyUnicode_ExactDealloc); @@ -468,7 +497,7 @@ dummy_func( } macro(BINARY_OP_ADD_UNICODE) = - _GUARD_BOTH_UNICODE + _BINARY_OP_ADD_UNICODE; + _GUARD_BOTH_UNICODE + unused/1 + _BINARY_OP_ADD_UNICODE; // This is a subtle one. It's a super-instruction for // BINARY_OP_ADD_UNICODE followed by STORE_FAST @@ -477,10 +506,10 @@ dummy_func( // specializations, but there is no output. // At the end we just skip over the STORE_FAST. op(_BINARY_OP_INPLACE_ADD_UNICODE, (left, right --)) { - _Py_CODEUNIT true_next = next_instr[INLINE_CACHE_ENTRIES_BINARY_OP]; - assert(true_next.op.code == STORE_FAST); - PyObject **target_local = &GETLOCAL(true_next.op.arg); - DEOPT_IF(*target_local != left, BINARY_OP); + TIER_ONE_ONLY + assert(next_instr->op.code == STORE_FAST); + PyObject **target_local = &GETLOCAL(next_instr->op.arg); + DEOPT_IF(*target_local != left); STAT_INC(BINARY_OP, hit); /* Handle `left = left + right` or `left += right` for str. * @@ -499,35 +528,42 @@ dummy_func( _Py_DECREF_SPECIALIZED(right, _PyUnicode_ExactDealloc); ERROR_IF(*target_local == NULL, error); // The STORE_FAST is already done. - SKIP_OVER(INLINE_CACHE_ENTRIES_BINARY_OP + 1); + assert(next_instr->op.code == STORE_FAST); + SKIP_OVER(1); } macro(BINARY_OP_INPLACE_ADD_UNICODE) = - _GUARD_BOTH_UNICODE + _BINARY_OP_INPLACE_ADD_UNICODE; + _GUARD_BOTH_UNICODE + unused/1 + _BINARY_OP_INPLACE_ADD_UNICODE; family(BINARY_SUBSCR, INLINE_CACHE_ENTRIES_BINARY_SUBSCR) = { BINARY_SUBSCR_DICT, BINARY_SUBSCR_GETITEM, BINARY_SUBSCR_LIST_INT, + BINARY_SUBSCR_STR_INT, BINARY_SUBSCR_TUPLE_INT, }; - inst(BINARY_SUBSCR, (unused/1, container, sub -- res)) { + specializing op(_SPECIALIZE_BINARY_SUBSCR, (counter/1, container, sub -- container, sub)) { + TIER_ONE_ONLY #if ENABLE_SPECIALIZATION - _PyBinarySubscrCache *cache = (_PyBinarySubscrCache *)next_instr; - if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) { - next_instr--; + if (ADAPTIVE_COUNTER_IS_ZERO(counter)) { + next_instr = this_instr; _Py_Specialize_BinarySubscr(container, sub, next_instr); DISPATCH_SAME_OPARG(); } STAT_INC(BINARY_SUBSCR, deferred); - DECREMENT_ADAPTIVE_COUNTER(cache->counter); + DECREMENT_ADAPTIVE_COUNTER(this_instr[1].cache); #endif /* ENABLE_SPECIALIZATION */ + } + + op(_BINARY_SUBSCR, (container, sub -- res)) { res = PyObject_GetItem(container, sub); DECREF_INPUTS(); ERROR_IF(res == NULL, error); } + macro(BINARY_SUBSCR) = _SPECIALIZE_BINARY_SUBSCR + _BINARY_SUBSCR; + inst(BINARY_SLICE, (container, start, stop -- res)) { PyObject *slice = _PyBuildSlice_ConsumeRefs(start, stop); // Can't use ERROR_IF() here, because we haven't @@ -559,13 +595,13 @@ dummy_func( } inst(BINARY_SUBSCR_LIST_INT, (unused/1, list, sub -- res)) { - DEOPT_IF(!PyLong_CheckExact(sub), BINARY_SUBSCR); - DEOPT_IF(!PyList_CheckExact(list), BINARY_SUBSCR); + DEOPT_IF(!PyLong_CheckExact(sub)); + DEOPT_IF(!PyList_CheckExact(list)); // Deopt unless 0 <= sub < PyList_Size(list) - DEOPT_IF(!_PyLong_IsNonNegativeCompact((PyLongObject *)sub), BINARY_SUBSCR); + DEOPT_IF(!_PyLong_IsNonNegativeCompact((PyLongObject *)sub)); Py_ssize_t index = ((PyLongObject*)sub)->long_value.ob_digit[0]; - DEOPT_IF(index >= PyList_GET_SIZE(list), BINARY_SUBSCR); + DEOPT_IF(index >= PyList_GET_SIZE(list)); STAT_INC(BINARY_SUBSCR, hit); res = PyList_GET_ITEM(list, index); assert(res != NULL); @@ -574,14 +610,29 @@ dummy_func( Py_DECREF(list); } + inst(BINARY_SUBSCR_STR_INT, (unused/1, str, sub -- res)) { + DEOPT_IF(!PyLong_CheckExact(sub)); + DEOPT_IF(!PyUnicode_CheckExact(str)); + DEOPT_IF(!_PyLong_IsNonNegativeCompact((PyLongObject *)sub)); + Py_ssize_t index = ((PyLongObject*)sub)->long_value.ob_digit[0]; + DEOPT_IF(PyUnicode_GET_LENGTH(str) <= index); + // Specialize for reading an ASCII character from any string: + Py_UCS4 c = PyUnicode_READ_CHAR(str, index); + DEOPT_IF(Py_ARRAY_LENGTH(_Py_SINGLETON(strings).ascii) <= c); + STAT_INC(BINARY_SUBSCR, hit); + res = (PyObject*)&_Py_SINGLETON(strings).ascii[c]; + _Py_DECREF_SPECIALIZED(sub, (destructor)PyObject_Free); + Py_DECREF(str); + } + inst(BINARY_SUBSCR_TUPLE_INT, (unused/1, tuple, sub -- res)) { - DEOPT_IF(!PyLong_CheckExact(sub), BINARY_SUBSCR); - DEOPT_IF(!PyTuple_CheckExact(tuple), BINARY_SUBSCR); + DEOPT_IF(!PyLong_CheckExact(sub)); + DEOPT_IF(!PyTuple_CheckExact(tuple)); // Deopt unless 0 <= sub < PyTuple_Size(list) - DEOPT_IF(!_PyLong_IsNonNegativeCompact((PyLongObject *)sub), BINARY_SUBSCR); + DEOPT_IF(!_PyLong_IsNonNegativeCompact((PyLongObject *)sub)); Py_ssize_t index = ((PyLongObject*)sub)->long_value.ob_digit[0]; - DEOPT_IF(index >= PyTuple_GET_SIZE(tuple), BINARY_SUBSCR); + DEOPT_IF(index >= PyTuple_GET_SIZE(tuple)); STAT_INC(BINARY_SUBSCR, hit); res = PyTuple_GET_ITEM(tuple, index); assert(res != NULL); @@ -591,42 +642,37 @@ dummy_func( } inst(BINARY_SUBSCR_DICT, (unused/1, dict, sub -- res)) { - DEOPT_IF(!PyDict_CheckExact(dict), BINARY_SUBSCR); + DEOPT_IF(!PyDict_CheckExact(dict)); STAT_INC(BINARY_SUBSCR, hit); - res = PyDict_GetItemWithError(dict, sub); - if (res == NULL) { - if (!_PyErr_Occurred(tstate)) { - _PyErr_SetKeyError(sub); - } - DECREF_INPUTS(); - ERROR_IF(true, error); + int rc = PyDict_GetItemRef(dict, sub, &res); + if (rc == 0) { + _PyErr_SetKeyError(sub); } - Py_INCREF(res); // Do this before DECREF'ing dict, sub DECREF_INPUTS(); + ERROR_IF(rc <= 0, error); // not found or error } inst(BINARY_SUBSCR_GETITEM, (unused/1, container, sub -- unused)) { - DEOPT_IF(tstate->interp->eval_frame, BINARY_SUBSCR); + DEOPT_IF(tstate->interp->eval_frame); PyTypeObject *tp = Py_TYPE(container); - DEOPT_IF(!PyType_HasFeature(tp, Py_TPFLAGS_HEAPTYPE), BINARY_SUBSCR); + DEOPT_IF(!PyType_HasFeature(tp, Py_TPFLAGS_HEAPTYPE)); PyHeapTypeObject *ht = (PyHeapTypeObject *)tp; PyObject *cached = ht->_spec_cache.getitem; - DEOPT_IF(cached == NULL, BINARY_SUBSCR); + DEOPT_IF(cached == NULL); assert(PyFunction_Check(cached)); PyFunctionObject *getitem = (PyFunctionObject *)cached; uint32_t cached_version = ht->_spec_cache.getitem_version; - DEOPT_IF(getitem->func_version != cached_version, BINARY_SUBSCR); + DEOPT_IF(getitem->func_version != cached_version); PyCodeObject *code = (PyCodeObject *)getitem->func_code; assert(code->co_argcount == 2); - DEOPT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize), BINARY_SUBSCR); + DEOPT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize)); STAT_INC(BINARY_SUBSCR, hit); Py_INCREF(getitem); _PyInterpreterFrame *new_frame = _PyFrame_PushUnchecked(tstate, getitem, 2); STACK_SHRINK(2); new_frame->localsplus[0] = container; new_frame->localsplus[1] = sub; - SKIP_OVER(INLINE_CACHE_ENTRIES_BINARY_SUBSCR); - frame->return_offset = 0; + frame->return_offset = (uint16_t)(next_instr - this_instr); DISPATCH_INLINED(new_frame); } @@ -645,32 +691,37 @@ dummy_func( STORE_SUBSCR_LIST_INT, }; - inst(STORE_SUBSCR, (unused/1, v, container, sub -- )) { + specializing op(_SPECIALIZE_STORE_SUBSCR, (counter/1, container, sub -- container, sub)) { + TIER_ONE_ONLY #if ENABLE_SPECIALIZATION - _PyStoreSubscrCache *cache = (_PyStoreSubscrCache *)next_instr; - if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) { - next_instr--; + if (ADAPTIVE_COUNTER_IS_ZERO(counter)) { + next_instr = this_instr; _Py_Specialize_StoreSubscr(container, sub, next_instr); DISPATCH_SAME_OPARG(); } STAT_INC(STORE_SUBSCR, deferred); - DECREMENT_ADAPTIVE_COUNTER(cache->counter); + DECREMENT_ADAPTIVE_COUNTER(this_instr[1].cache); #endif /* ENABLE_SPECIALIZATION */ + } + + op(_STORE_SUBSCR, (v, container, sub -- )) { /* container[sub] = v */ int err = PyObject_SetItem(container, sub, v); DECREF_INPUTS(); ERROR_IF(err, error); } + macro(STORE_SUBSCR) = _SPECIALIZE_STORE_SUBSCR + _STORE_SUBSCR; + inst(STORE_SUBSCR_LIST_INT, (unused/1, value, list, sub -- )) { - DEOPT_IF(!PyLong_CheckExact(sub), STORE_SUBSCR); - DEOPT_IF(!PyList_CheckExact(list), STORE_SUBSCR); + DEOPT_IF(!PyLong_CheckExact(sub)); + DEOPT_IF(!PyList_CheckExact(list)); // Ensure nonnegative, zero-or-one-digit ints. - DEOPT_IF(!_PyLong_IsNonNegativeCompact((PyLongObject *)sub), STORE_SUBSCR); + DEOPT_IF(!_PyLong_IsNonNegativeCompact((PyLongObject *)sub)); Py_ssize_t index = ((PyLongObject*)sub)->long_value.ob_digit[0]; // Ensure index < len(list) - DEOPT_IF(index >= PyList_GET_SIZE(list), STORE_SUBSCR); + DEOPT_IF(index >= PyList_GET_SIZE(list)); STAT_INC(STORE_SUBSCR, hit); PyObject *old_value = PyList_GET_ITEM(list, index); @@ -682,7 +733,7 @@ dummy_func( } inst(STORE_SUBSCR_DICT, (unused/1, value, dict, sub -- )) { - DEOPT_IF(!PyDict_CheckExact(dict), STORE_SUBSCR); + DEOPT_IF(!PyDict_CheckExact(dict)); STAT_INC(STORE_SUBSCR, hit); int err = _PyDict_SetItem_Take2((PyDictObject *)dict, sub, value); Py_DECREF(dict); @@ -711,6 +762,7 @@ dummy_func( } inst(RAISE_VARARGS, (args[oparg] -- )) { + TIER_ONE_ONLY PyObject *cause = NULL, *exc = NULL; switch (oparg) { case 2: @@ -722,7 +774,7 @@ dummy_func( case 0: if (do_raise(tstate, exc, cause)) { assert(oparg == 0); - monitor_reraise(tstate, frame, next_instr-1); + monitor_reraise(tstate, frame, this_instr); goto exception_unwind; } break; @@ -735,36 +787,50 @@ dummy_func( } inst(INTERPRETER_EXIT, (retval --)) { + TIER_ONE_ONLY assert(frame == &entry_frame); assert(_PyFrame_IsIncomplete(frame)); - /* Restore previous cframe and return. */ - tstate->cframe = cframe.previous; - assert(tstate->cframe->current_frame == frame->previous); + /* Restore previous frame and return. */ + tstate->current_frame = frame->previous; assert(!_PyErr_Occurred(tstate)); tstate->c_recursion_remaining += PY_EVAL_C_STACK_UNITS; return retval; } - inst(RETURN_VALUE, (retval --)) { - STACK_SHRINK(1); + // The stack effect here is ambiguous. + // We definitely pop the return value off the stack on entry. + // We also push it onto the stack on exit, but that's a + // different frame, and it's accounted for by _PUSH_FRAME. + op(_POP_FRAME, (retval --)) { + #if TIER_ONE + assert(frame != &entry_frame); + #endif + STORE_SP(); assert(EMPTY()); - _PyFrame_SetStackPointer(frame, stack_pointer); _Py_LeaveRecursiveCallPy(tstate); - assert(frame != &entry_frame); // GH-99729: We need to unlink the frame *before* clearing it: _PyInterpreterFrame *dying = frame; - frame = cframe.current_frame = dying->previous; - _PyEvalFrameClearAndPop(tstate, dying); - frame->prev_instr += frame->return_offset; + frame = tstate->current_frame = dying->previous; + _PyEval_FrameClearAndPop(tstate, dying); _PyFrame_StackPush(frame, retval); - goto resume_frame; + LOAD_SP(); + LOAD_IP(frame->return_offset); +#if LLTRACE && TIER_ONE + lltrace = maybe_lltrace_resume_frame(frame, &entry_frame, GLOBALS()); + if (lltrace < 0) { + goto exit_unwind; + } +#endif } + macro(RETURN_VALUE) = + _POP_FRAME; + inst(INSTRUMENTED_RETURN_VALUE, (retval --)) { int err = _Py_call_instrumentation_arg( tstate, PY_MONITORING_EVENT_PY_RETURN, - frame, next_instr-1, retval); - if (err) goto error; + frame, this_instr, retval); + if (err) GOTO_ERROR(error); STACK_SHRINK(1); assert(EMPTY()); _PyFrame_SetStackPointer(frame, stack_pointer); @@ -772,35 +838,23 @@ dummy_func( assert(frame != &entry_frame); // GH-99729: We need to unlink the frame *before* clearing it: _PyInterpreterFrame *dying = frame; - frame = cframe.current_frame = dying->previous; - _PyEvalFrameClearAndPop(tstate, dying); - frame->prev_instr += frame->return_offset; + frame = tstate->current_frame = dying->previous; + _PyEval_FrameClearAndPop(tstate, dying); _PyFrame_StackPush(frame, retval); + LOAD_IP(frame->return_offset); goto resume_frame; } - inst(RETURN_CONST, (--)) { - PyObject *retval = GETITEM(FRAME_CO_CONSTS, oparg); - Py_INCREF(retval); - assert(EMPTY()); - _PyFrame_SetStackPointer(frame, stack_pointer); - _Py_LeaveRecursiveCallPy(tstate); - assert(frame != &entry_frame); - // GH-99729: We need to unlink the frame *before* clearing it: - _PyInterpreterFrame *dying = frame; - frame = cframe.current_frame = dying->previous; - _PyEvalFrameClearAndPop(tstate, dying); - frame->prev_instr += frame->return_offset; - _PyFrame_StackPush(frame, retval); - goto resume_frame; - } + macro(RETURN_CONST) = + LOAD_CONST + + _POP_FRAME; inst(INSTRUMENTED_RETURN_CONST, (--)) { PyObject *retval = GETITEM(FRAME_CO_CONSTS, oparg); int err = _Py_call_instrumentation_arg( tstate, PY_MONITORING_EVENT_PY_RETURN, - frame, next_instr-1, retval); - if (err) goto error; + frame, this_instr, retval); + if (err) GOTO_ERROR(error); Py_INCREF(retval); assert(EMPTY()); _PyFrame_SetStackPointer(frame, stack_pointer); @@ -808,10 +862,10 @@ dummy_func( assert(frame != &entry_frame); // GH-99729: We need to unlink the frame *before* clearing it: _PyInterpreterFrame *dying = frame; - frame = cframe.current_frame = dying->previous; - _PyEvalFrameClearAndPop(tstate, dying); - frame->prev_instr += frame->return_offset; + frame = tstate->current_frame = dying->previous; + _PyEval_FrameClearAndPop(tstate, dying); _PyFrame_StackPush(frame, retval); + LOAD_IP(frame->return_offset); goto resume_frame; } @@ -856,7 +910,7 @@ dummy_func( if (PyAsyncGen_CheckExact(aiter)) { awaitable = type->tp_as_async->am_anext(aiter); if (awaitable == NULL) { - goto error; + GOTO_ERROR(error); } } else { if (type->tp_as_async != NULL){ @@ -866,7 +920,7 @@ dummy_func( if (getter != NULL) { next_iter = (*getter)(aiter); if (next_iter == NULL) { - goto error; + GOTO_ERROR(error); } } else { @@ -874,7 +928,7 @@ dummy_func( "'async for' requires an iterator with " "__anext__ method, got %.100s", type->tp_name); - goto error; + GOTO_ERROR(error); } awaitable = _PyCoro_GetAwaitableIter(next_iter); @@ -886,7 +940,7 @@ dummy_func( Py_TYPE(next_iter)->tp_name); Py_DECREF(next_iter); - goto error; + GOTO_ERROR(error); } else { Py_DECREF(next_iter); } @@ -923,17 +977,20 @@ dummy_func( SEND_GEN, }; - inst(SEND, (unused/1, receiver, v -- receiver, retval)) { + specializing op(_SPECIALIZE_SEND, (counter/1, receiver, unused -- receiver, unused)) { + TIER_ONE_ONLY #if ENABLE_SPECIALIZATION - _PySendCache *cache = (_PySendCache *)next_instr; - if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) { - next_instr--; + if (ADAPTIVE_COUNTER_IS_ZERO(counter)) { + next_instr = this_instr; _Py_Specialize_Send(receiver, next_instr); DISPATCH_SAME_OPARG(); } STAT_INC(SEND, deferred); - DECREMENT_ADAPTIVE_COUNTER(cache->counter); + DECREMENT_ADAPTIVE_COUNTER(this_instr[1].cache); #endif /* ENABLE_SPECIALIZATION */ + } + + op(_SEND, (receiver, v -- receiver, retval)) { assert(frame != &entry_frame); if ((tstate->interp->eval_frame == NULL) && (Py_TYPE(receiver) == &PyGen_Type || Py_TYPE(receiver) == &PyCoro_Type) && @@ -941,13 +998,13 @@ dummy_func( { PyGenObject *gen = (PyGenObject *)receiver; _PyInterpreterFrame *gen_frame = (_PyInterpreterFrame *)gen->gi_iframe; - frame->return_offset = oparg; STACK_SHRINK(1); _PyFrame_StackPush(gen_frame, v); gen->gi_frame_state = FRAME_EXECUTING; gen->gi_exc_state.previous_item = tstate->exc_info; tstate->exc_info = &gen->gi_exc_state; - SKIP_OVER(INLINE_CACHE_ENTRIES_SEND); + assert(next_instr - this_instr + oparg <= UINT16_MAX); + frame->return_offset = (uint16_t)(next_instr - this_instr + oparg); DISPATCH_INLINED(gen_frame); } if (Py_IsNone(v) && PyIter_Check(receiver)) { @@ -959,103 +1016,117 @@ dummy_func( if (retval == NULL) { if (_PyErr_ExceptionMatches(tstate, PyExc_StopIteration) ) { - monitor_raise(tstate, frame, next_instr-1); + monitor_raise(tstate, frame, this_instr); } if (_PyGen_FetchStopIterationValue(&retval) == 0) { assert(retval != NULL); JUMPBY(oparg); } else { - goto error; + GOTO_ERROR(error); } } Py_DECREF(v); } + macro(SEND) = _SPECIALIZE_SEND + _SEND; + inst(SEND_GEN, (unused/1, receiver, v -- receiver, unused)) { - DEOPT_IF(tstate->interp->eval_frame, SEND); + DEOPT_IF(tstate->interp->eval_frame); PyGenObject *gen = (PyGenObject *)receiver; - DEOPT_IF(Py_TYPE(gen) != &PyGen_Type && - Py_TYPE(gen) != &PyCoro_Type, SEND); - DEOPT_IF(gen->gi_frame_state >= FRAME_EXECUTING, SEND); + DEOPT_IF(Py_TYPE(gen) != &PyGen_Type && Py_TYPE(gen) != &PyCoro_Type); + DEOPT_IF(gen->gi_frame_state >= FRAME_EXECUTING); STAT_INC(SEND, hit); _PyInterpreterFrame *gen_frame = (_PyInterpreterFrame *)gen->gi_iframe; - frame->return_offset = oparg; STACK_SHRINK(1); _PyFrame_StackPush(gen_frame, v); gen->gi_frame_state = FRAME_EXECUTING; gen->gi_exc_state.previous_item = tstate->exc_info; tstate->exc_info = &gen->gi_exc_state; - SKIP_OVER(INLINE_CACHE_ENTRIES_SEND); + assert(next_instr - this_instr + oparg <= UINT16_MAX); + frame->return_offset = (uint16_t)(next_instr - this_instr + oparg); DISPATCH_INLINED(gen_frame); } inst(INSTRUMENTED_YIELD_VALUE, (retval -- unused)) { assert(frame != &entry_frame); - assert(oparg >= 0); /* make the generator identify this as HAS_ARG */ + frame->instr_ptr = next_instr; PyGenObject *gen = _PyFrame_GetGenerator(frame); - gen->gi_frame_state = FRAME_SUSPENDED; + assert(FRAME_SUSPENDED_YIELD_FROM == FRAME_SUSPENDED + 1); + assert(oparg == 0 || oparg == 1); + gen->gi_frame_state = FRAME_SUSPENDED + oparg; _PyFrame_SetStackPointer(frame, stack_pointer - 1); int err = _Py_call_instrumentation_arg( tstate, PY_MONITORING_EVENT_PY_YIELD, - frame, next_instr-1, retval); - if (err) goto error; + frame, this_instr, retval); + if (err) GOTO_ERROR(error); tstate->exc_info = gen->gi_exc_state.previous_item; gen->gi_exc_state.previous_item = NULL; _Py_LeaveRecursiveCallPy(tstate); _PyInterpreterFrame *gen_frame = frame; - frame = cframe.current_frame = frame->previous; + frame = tstate->current_frame = frame->previous; gen_frame->previous = NULL; _PyFrame_StackPush(frame, retval); + /* We don't know which of these is relevant here, so keep them equal */ + assert(INLINE_CACHE_ENTRIES_SEND == INLINE_CACHE_ENTRIES_FOR_ITER); + LOAD_IP(1 + INLINE_CACHE_ENTRIES_SEND); goto resume_frame; } inst(YIELD_VALUE, (retval -- unused)) { + TIER_ONE_ONLY // 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 >= 0); /* make the generator identify this as HAS_ARG */ assert(frame != &entry_frame); + frame->instr_ptr = next_instr; PyGenObject *gen = _PyFrame_GetGenerator(frame); - gen->gi_frame_state = FRAME_SUSPENDED; + assert(FRAME_SUSPENDED_YIELD_FROM == FRAME_SUSPENDED + 1); + assert(oparg == 0 || oparg == 1); + gen->gi_frame_state = FRAME_SUSPENDED + oparg; _PyFrame_SetStackPointer(frame, stack_pointer - 1); tstate->exc_info = gen->gi_exc_state.previous_item; gen->gi_exc_state.previous_item = NULL; _Py_LeaveRecursiveCallPy(tstate); _PyInterpreterFrame *gen_frame = frame; - frame = cframe.current_frame = frame->previous; + frame = tstate->current_frame = frame->previous; gen_frame->previous = NULL; _PyFrame_StackPush(frame, retval); + /* We don't know which of these is relevant here, so keep them equal */ + assert(INLINE_CACHE_ENTRIES_SEND == INLINE_CACHE_ENTRIES_FOR_ITER); + LOAD_IP(1 + INLINE_CACHE_ENTRIES_SEND); goto resume_frame; } inst(POP_EXCEPT, (exc_value -- )) { _PyErr_StackItem *exc_info = tstate->exc_info; - Py_XSETREF(exc_info->exc_value, exc_value); + Py_XSETREF(exc_info->exc_value, exc_value == Py_None ? NULL : exc_value); } inst(RERAISE, (values[oparg], exc -- values[oparg])) { + TIER_ONE_ONLY assert(oparg >= 0 && oparg <= 2); if (oparg) { PyObject *lasti = values[0]; if (PyLong_Check(lasti)) { - frame->prev_instr = _PyCode_CODE(_PyFrame_GetCode(frame)) + PyLong_AsLong(lasti); + frame->instr_ptr = _PyCode_CODE(_PyFrame_GetCode(frame)) + PyLong_AsLong(lasti); assert(!_PyErr_Occurred(tstate)); } else { assert(PyLong_Check(lasti)); _PyErr_SetString(tstate, PyExc_SystemError, "lasti is not an int"); - goto error; + GOTO_ERROR(error); } } assert(exc && PyExceptionInstance_Check(exc)); Py_INCREF(exc); _PyErr_SetRaisedException(tstate, exc); - monitor_reraise(tstate, frame, next_instr-1); + monitor_reraise(tstate, frame, this_instr); goto exception_unwind; } inst(END_ASYNC_FOR, (awaitable, exc -- )) { + TIER_ONE_ONLY assert(exc && PyExceptionInstance_Check(exc)); if (PyErr_GivenExceptionMatches(exc, PyExc_StopAsyncIteration)) { DECREF_INPUTS(); @@ -1063,12 +1134,13 @@ dummy_func( else { Py_INCREF(exc); _PyErr_SetRaisedException(tstate, exc); - monitor_reraise(tstate, frame, next_instr-1); + monitor_reraise(tstate, frame, this_instr); goto exception_unwind; } } inst(CLEANUP_THROW, (sub_iter, last_sent_val, exc_value -- none, value)) { + TIER_ONE_ONLY assert(throwflag); assert(exc_value && PyExceptionInstance_Check(exc_value)); if (PyErr_GivenExceptionMatches(exc_value, PyExc_StopIteration)) { @@ -1078,7 +1150,7 @@ dummy_func( } else { _PyErr_SetRaisedException(tstate, Py_NewRef(exc_value)); - monitor_reraise(tstate, frame, next_instr-1); + monitor_reraise(tstate, frame, this_instr); goto exception_unwind; } } @@ -1096,7 +1168,6 @@ dummy_func( } } - inst(STORE_NAME, (v -- )) { PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); PyObject *ns = LOCALS(); @@ -1122,7 +1193,7 @@ dummy_func( if (ns == NULL) { _PyErr_Format(tstate, PyExc_SystemError, "no locals when deleting %R", name); - goto error; + GOTO_ERROR(error); } err = PyObject_DelItem(ns, name); // Can't use ERROR_IF here. @@ -1130,7 +1201,7 @@ dummy_func( _PyEval_FormatExcCheckArg(tstate, PyExc_NameError, NAME_ERROR_MSG, name); - goto error; + GOTO_ERROR(error); } } @@ -1140,26 +1211,33 @@ dummy_func( UNPACK_SEQUENCE_LIST, }; - inst(UNPACK_SEQUENCE, (unused/1, seq -- unused[oparg])) { + specializing op(_SPECIALIZE_UNPACK_SEQUENCE, (counter/1, seq -- seq)) { + TIER_ONE_ONLY #if ENABLE_SPECIALIZATION - _PyUnpackSequenceCache *cache = (_PyUnpackSequenceCache *)next_instr; - if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) { - next_instr--; + if (ADAPTIVE_COUNTER_IS_ZERO(counter)) { + next_instr = this_instr; _Py_Specialize_UnpackSequence(seq, next_instr, oparg); DISPATCH_SAME_OPARG(); } STAT_INC(UNPACK_SEQUENCE, deferred); - DECREMENT_ADAPTIVE_COUNTER(cache->counter); + DECREMENT_ADAPTIVE_COUNTER(this_instr[1].cache); #endif /* ENABLE_SPECIALIZATION */ + (void)seq; + (void)counter; + } + + op(_UNPACK_SEQUENCE, (seq -- unused[oparg])) { PyObject **top = stack_pointer + oparg - 1; int res = _PyEval_UnpackIterable(tstate, seq, oparg, -1, top); DECREF_INPUTS(); ERROR_IF(res == 0, error); } + macro(UNPACK_SEQUENCE) = _SPECIALIZE_UNPACK_SEQUENCE + _UNPACK_SEQUENCE; + inst(UNPACK_SEQUENCE_TWO_TUPLE, (unused/1, seq -- values[oparg])) { - DEOPT_IF(!PyTuple_CheckExact(seq), UNPACK_SEQUENCE); - DEOPT_IF(PyTuple_GET_SIZE(seq) != 2, UNPACK_SEQUENCE); + DEOPT_IF(!PyTuple_CheckExact(seq)); + DEOPT_IF(PyTuple_GET_SIZE(seq) != 2); assert(oparg == 2); STAT_INC(UNPACK_SEQUENCE, hit); values[0] = Py_NewRef(PyTuple_GET_ITEM(seq, 1)); @@ -1168,8 +1246,8 @@ dummy_func( } inst(UNPACK_SEQUENCE_TUPLE, (unused/1, seq -- values[oparg])) { - DEOPT_IF(!PyTuple_CheckExact(seq), UNPACK_SEQUENCE); - DEOPT_IF(PyTuple_GET_SIZE(seq) != oparg, UNPACK_SEQUENCE); + DEOPT_IF(!PyTuple_CheckExact(seq)); + DEOPT_IF(PyTuple_GET_SIZE(seq) != oparg); STAT_INC(UNPACK_SEQUENCE, hit); PyObject **items = _PyTuple_ITEMS(seq); for (int i = oparg; --i >= 0; ) { @@ -1179,8 +1257,8 @@ dummy_func( } inst(UNPACK_SEQUENCE_LIST, (unused/1, seq -- values[oparg])) { - DEOPT_IF(!PyList_CheckExact(seq), UNPACK_SEQUENCE); - DEOPT_IF(PyList_GET_SIZE(seq) != oparg, UNPACK_SEQUENCE); + DEOPT_IF(!PyList_CheckExact(seq)); + DEOPT_IF(PyList_GET_SIZE(seq) != oparg); STAT_INC(UNPACK_SEQUENCE, hit); PyObject **items = _PyList_ITEMS(seq); for (int i = oparg; --i >= 0; ) { @@ -1203,24 +1281,29 @@ dummy_func( STORE_ATTR_WITH_HINT, }; - inst(STORE_ATTR, (unused/1, unused/3, v, owner --)) { + specializing op(_SPECIALIZE_STORE_ATTR, (counter/1, owner -- owner)) { + TIER_ONE_ONLY #if ENABLE_SPECIALIZATION - _PyAttrCache *cache = (_PyAttrCache *)next_instr; - if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) { + if (ADAPTIVE_COUNTER_IS_ZERO(counter)) { PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); - next_instr--; + next_instr = this_instr; _Py_Specialize_StoreAttr(owner, next_instr, name); DISPATCH_SAME_OPARG(); } STAT_INC(STORE_ATTR, deferred); - DECREMENT_ADAPTIVE_COUNTER(cache->counter); + DECREMENT_ADAPTIVE_COUNTER(this_instr[1].cache); #endif /* ENABLE_SPECIALIZATION */ + } + + op(_STORE_ATTR, (v, owner --)) { PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); int err = PyObject_SetAttr(owner, name, v); DECREF_INPUTS(); ERROR_IF(err, error); } + macro(STORE_ATTR) = _SPECIALIZE_STORE_ATTR + unused/3 + _STORE_ATTR; + inst(DELETE_ATTR, (owner --)) { PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); int err = PyObject_DelAttr(owner, name); @@ -1245,11 +1328,11 @@ dummy_func( _PyEval_FormatExcCheckArg(tstate, PyExc_NameError, NAME_ERROR_MSG, name); } - goto error; + GOTO_ERROR(error); } } - op(_LOAD_LOCALS, ( -- locals)) { + inst(LOAD_LOCALS, ( -- locals)) { locals = LOCALS(); if (locals == NULL) { _PyErr_SetString(tstate, PyExc_SystemError, @@ -1259,66 +1342,87 @@ dummy_func( Py_INCREF(locals); } - macro(LOAD_LOCALS) = _LOAD_LOCALS; - - op(_LOAD_FROM_DICT_OR_GLOBALS, (mod_or_class_dict -- v)) { + inst(LOAD_FROM_DICT_OR_GLOBALS, (mod_or_class_dict -- v)) { PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); if (PyMapping_GetOptionalItem(mod_or_class_dict, name, &v) < 0) { - Py_DECREF(mod_or_class_dict); - goto error; + GOTO_ERROR(error); } - Py_DECREF(mod_or_class_dict); if (v == NULL) { - v = PyDict_GetItemWithError(GLOBALS(), name); - if (v != NULL) { - Py_INCREF(v); + if (PyDict_GetItemRef(GLOBALS(), name, &v) < 0) { + GOTO_ERROR(error); } - else if (_PyErr_Occurred(tstate)) { - goto error; - } - else { + if (v == NULL) { if (PyMapping_GetOptionalItem(BUILTINS(), name, &v) < 0) { - goto error; + GOTO_ERROR(error); } if (v == NULL) { _PyEval_FormatExcCheckArg( tstate, PyExc_NameError, NAME_ERROR_MSG, name); - goto error; + GOTO_ERROR(error); } } } + DECREF_INPUTS(); } - macro(LOAD_NAME) = _LOAD_LOCALS + _LOAD_FROM_DICT_OR_GLOBALS; - - macro(LOAD_FROM_DICT_OR_GLOBALS) = _LOAD_FROM_DICT_OR_GLOBALS; + inst(LOAD_NAME, (-- v)) { + PyObject *mod_or_class_dict = LOCALS(); + if (mod_or_class_dict == NULL) { + _PyErr_SetString(tstate, PyExc_SystemError, + "no locals found"); + ERROR_IF(true, error); + } + PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); + if (PyMapping_GetOptionalItem(mod_or_class_dict, name, &v) < 0) { + GOTO_ERROR(error); + } + if (v == NULL) { + if (PyDict_GetItemRef(GLOBALS(), name, &v) < 0) { + GOTO_ERROR(error); + } + if (v == NULL) { + if (PyMapping_GetOptionalItem(BUILTINS(), name, &v) < 0) { + GOTO_ERROR(error); + } + if (v == NULL) { + _PyEval_FormatExcCheckArg( + tstate, PyExc_NameError, + NAME_ERROR_MSG, name); + GOTO_ERROR(error); + } + } + } + } family(LOAD_GLOBAL, INLINE_CACHE_ENTRIES_LOAD_GLOBAL) = { LOAD_GLOBAL_MODULE, LOAD_GLOBAL_BUILTIN, }; - inst(LOAD_GLOBAL, (unused/1, unused/1, unused/1, unused/1 -- null if (oparg & 1), v)) { + specializing op(_SPECIALIZE_LOAD_GLOBAL, (counter/1 -- )) { + TIER_ONE_ONLY #if ENABLE_SPECIALIZATION - _PyLoadGlobalCache *cache = (_PyLoadGlobalCache *)next_instr; - if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) { + if (ADAPTIVE_COUNTER_IS_ZERO(counter)) { PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1); - next_instr--; + next_instr = this_instr; _Py_Specialize_LoadGlobal(GLOBALS(), BUILTINS(), next_instr, name); DISPATCH_SAME_OPARG(); } STAT_INC(LOAD_GLOBAL, deferred); - DECREMENT_ADAPTIVE_COUNTER(cache->counter); + DECREMENT_ADAPTIVE_COUNTER(this_instr[1].cache); #endif /* ENABLE_SPECIALIZATION */ + } + + op(_LOAD_GLOBAL, ( -- res, null if (oparg & 1))) { PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1); if (PyDict_CheckExact(GLOBALS()) && PyDict_CheckExact(BUILTINS())) { - v = _PyDict_LoadGlobal((PyDictObject *)GLOBALS(), - (PyDictObject *)BUILTINS(), - name); - if (v == NULL) { + res = _PyDict_LoadGlobal((PyDictObject *)GLOBALS(), + (PyDictObject *)BUILTINS(), + name); + if (res == NULL) { if (!_PyErr_Occurred(tstate)) { /* _PyDict_LoadGlobal() returns NULL without raising * an exception if the key doesn't exist */ @@ -1327,17 +1431,16 @@ dummy_func( } ERROR_IF(true, error); } - Py_INCREF(v); + Py_INCREF(res); } else { /* Slow-path if globals or builtins is not a dict */ - /* namespace 1: globals */ - ERROR_IF(PyMapping_GetOptionalItem(GLOBALS(), name, &v) < 0, error); - if (v == NULL) { + ERROR_IF(PyMapping_GetOptionalItem(GLOBALS(), name, &res) < 0, error); + if (res == NULL) { /* namespace 2: builtins */ - ERROR_IF(PyMapping_GetOptionalItem(BUILTINS(), name, &v) < 0, error); - if (v == NULL) { + ERROR_IF(PyMapping_GetOptionalItem(BUILTINS(), name, &res) < 0, error); + if (res == NULL) { _PyEval_FormatExcCheckArg( tstate, PyExc_NameError, NAME_ERROR_MSG, name); @@ -1348,35 +1451,42 @@ dummy_func( null = NULL; } + macro(LOAD_GLOBAL) = + _SPECIALIZE_LOAD_GLOBAL + + counter/1 + + globals_version/1 + + builtins_version/1 + + _LOAD_GLOBAL; + op(_GUARD_GLOBALS_VERSION, (version/1 --)) { PyDictObject *dict = (PyDictObject *)GLOBALS(); - DEOPT_IF(!PyDict_CheckExact(dict), LOAD_GLOBAL); - DEOPT_IF(dict->ma_keys->dk_version != version, LOAD_GLOBAL); + DEOPT_IF(!PyDict_CheckExact(dict)); + DEOPT_IF(dict->ma_keys->dk_version != version); assert(DK_IS_UNICODE(dict->ma_keys)); } op(_GUARD_BUILTINS_VERSION, (version/1 --)) { PyDictObject *dict = (PyDictObject *)BUILTINS(); - DEOPT_IF(!PyDict_CheckExact(dict), LOAD_GLOBAL); - DEOPT_IF(dict->ma_keys->dk_version != version, LOAD_GLOBAL); + DEOPT_IF(!PyDict_CheckExact(dict)); + DEOPT_IF(dict->ma_keys->dk_version != version); assert(DK_IS_UNICODE(dict->ma_keys)); } - op(_LOAD_GLOBAL_MODULE, (index/1 -- null if (oparg & 1), res)) { + op(_LOAD_GLOBAL_MODULE, (index/1 -- res, null if (oparg & 1))) { PyDictObject *dict = (PyDictObject *)GLOBALS(); PyDictUnicodeEntry *entries = DK_UNICODE_ENTRIES(dict->ma_keys); res = entries[index].me_value; - DEOPT_IF(res == NULL, LOAD_GLOBAL); + DEOPT_IF(res == NULL); Py_INCREF(res); STAT_INC(LOAD_GLOBAL, hit); null = NULL; } - op(_LOAD_GLOBAL_BUILTINS, (index/1 -- null if (oparg & 1), res)) { + op(_LOAD_GLOBAL_BUILTINS, (index/1 -- res, null if (oparg & 1))) { PyDictObject *bdict = (PyDictObject *)BUILTINS(); PyDictUnicodeEntry *entries = DK_UNICODE_ENTRIES(bdict->ma_keys); res = entries[index].me_value; - DEOPT_IF(res == NULL, LOAD_GLOBAL); + DEOPT_IF(res == NULL); Py_INCREF(res); STAT_INC(LOAD_GLOBAL, hit); null = NULL; @@ -1406,7 +1516,7 @@ dummy_func( PyObject *initial = GETLOCAL(oparg); PyObject *cell = PyCell_New(initial); if (cell == NULL) { - goto resume_with_error; + GOTO_ERROR(error); } SETLOCAL(oparg, cell); } @@ -1418,7 +1528,7 @@ dummy_func( // Fortunately we don't need its superpower. if (oldobj == NULL) { _PyEval_FormatExcUnbound(tstate, _PyFrame_GetCode(frame), oparg); - goto error; + GOTO_ERROR(error); } PyCell_SET(cell, NULL); Py_DECREF(oldobj); @@ -1430,19 +1540,18 @@ dummy_func( assert(oparg >= 0 && oparg < _PyFrame_GetCode(frame)->co_nlocalsplus); name = PyTuple_GET_ITEM(_PyFrame_GetCode(frame)->co_localsplusnames, oparg); if (PyMapping_GetOptionalItem(class_dict, name, &value) < 0) { - Py_DECREF(class_dict); - goto error; + GOTO_ERROR(error); } - Py_DECREF(class_dict); if (!value) { PyObject *cell = GETLOCAL(oparg); value = PyCell_GET(cell); if (value == NULL) { _PyEval_FormatExcUnbound(tstate, _PyFrame_GetCode(frame), oparg); - goto error; + GOTO_ERROR(error); } Py_INCREF(value); } + Py_DECREF(class_dict); } inst(LOAD_DEREF, ( -- value)) { @@ -1518,7 +1627,7 @@ dummy_func( inst(BUILD_SET, (values[oparg] -- set)) { set = PySet_New(NULL); if (set == NULL) - goto error; + GOTO_ERROR(error); int err = 0; for (int i = 0; i < oparg; i++) { PyObject *item = values[i]; @@ -1537,9 +1646,6 @@ dummy_func( values, 2, values+1, 2, oparg); - if (map == NULL) - goto error; - DECREF_INPUTS(); ERROR_IF(map == NULL, error); } @@ -1553,34 +1659,17 @@ dummy_func( ERROR_IF(true, error); } /* check if __annotations__ in locals()... */ - if (PyDict_CheckExact(LOCALS())) { - ann_dict = _PyDict_GetItemWithError(LOCALS(), - &_Py_ID(__annotations__)); - if (ann_dict == NULL) { - ERROR_IF(_PyErr_Occurred(tstate), error); - /* ...if not, create a new one */ - ann_dict = PyDict_New(); - ERROR_IF(ann_dict == NULL, error); - err = PyDict_SetItem(LOCALS(), &_Py_ID(__annotations__), - ann_dict); - Py_DECREF(ann_dict); - ERROR_IF(err, error); - } + ERROR_IF(PyMapping_GetOptionalItem(LOCALS(), &_Py_ID(__annotations__), &ann_dict) < 0, error); + if (ann_dict == NULL) { + ann_dict = PyDict_New(); + ERROR_IF(ann_dict == NULL, error); + err = PyObject_SetItem(LOCALS(), &_Py_ID(__annotations__), + ann_dict); + Py_DECREF(ann_dict); + ERROR_IF(err, error); } else { - /* do the same if locals() is not a dict */ - ERROR_IF(PyMapping_GetOptionalItem(LOCALS(), &_Py_ID(__annotations__), &ann_dict) < 0, error); - if (ann_dict == NULL) { - ann_dict = PyDict_New(); - ERROR_IF(ann_dict == NULL, error); - err = PyObject_SetItem(LOCALS(), &_Py_ID(__annotations__), - ann_dict); - Py_DECREF(ann_dict); - ERROR_IF(err, error); - } - else { - Py_DECREF(ann_dict); - } + Py_DECREF(ann_dict); } } @@ -1589,7 +1678,7 @@ dummy_func( PyTuple_GET_SIZE(keys) != (Py_ssize_t)oparg) { _PyErr_SetString(tstate, PyExc_SystemError, "bad BUILD_CONST_KEY_MAP keys argument"); - goto error; // Pop the keys and values. + GOTO_ERROR(error); // Pop the keys and values. } map = _PyDict_FromItems( &PyTuple_GET_ITEM(keys, 0), 1, @@ -1598,8 +1687,7 @@ dummy_func( ERROR_IF(map == NULL, error); } - inst(DICT_UPDATE, (update --)) { - PyObject *dict = PEEK(oparg + 1); // update is still on the stack + inst(DICT_UPDATE, (dict, unused[oparg - 1], update -- dict, unused[oparg - 1])) { if (PyDict_Update(dict, update) < 0) { if (_PyErr_ExceptionMatches(tstate, PyExc_AttributeError)) { _PyErr_Format(tstate, PyExc_TypeError, @@ -1612,30 +1700,26 @@ dummy_func( DECREF_INPUTS(); } - inst(DICT_MERGE, (update --)) { - PyObject *dict = PEEK(oparg + 1); // update is still on the stack - + inst(DICT_MERGE, (callable, unused, unused, dict, unused[oparg - 1], update -- callable, unused, unused, dict, unused[oparg - 1])) { if (_PyDict_MergeEx(dict, update, 2) < 0) { - _PyEval_FormatKwargsError(tstate, PEEK(3 + oparg), update); + _PyEval_FormatKwargsError(tstate, callable, update); DECREF_INPUTS(); ERROR_IF(true, error); } DECREF_INPUTS(); } - inst(MAP_ADD, (key, value --)) { - PyObject *dict = PEEK(oparg + 2); // key, value are still on the stack + inst(MAP_ADD, (dict, unused[oparg - 1], key, value -- dict, unused[oparg - 1])) { assert(PyDict_CheckExact(dict)); /* dict[key] = value */ // Do not DECREF INPUTS because the function steals the references ERROR_IF(_PyDict_SetItem_Take2((PyDictObject *)dict, key, value) != 0, error); } - inst(INSTRUMENTED_LOAD_SUPER_ATTR, (unused/9, unused, unused, unused -- unused if (oparg & 1), unused)) { - _PySuperAttrCache *cache = (_PySuperAttrCache *)next_instr; + inst(INSTRUMENTED_LOAD_SUPER_ATTR, (unused/1, unused, unused, unused -- unused, unused if (oparg & 1))) { // cancel out the decrement that will happen in LOAD_SUPER_ATTR; we // don't want to specialize instrumented instructions - INCREMENT_ADAPTIVE_COUNTER(cache->counter); + INCREMENT_ADAPTIVE_COUNTER(this_instr[1].cache); GO_TO_INSTRUCTION(LOAD_SUPER_ATTR); } @@ -1644,28 +1728,29 @@ dummy_func( LOAD_SUPER_ATTR_METHOD, }; - inst(LOAD_SUPER_ATTR, (unused/1, global_super, class, self -- res2 if (oparg & 1), res)) { - PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 2); - int load_method = oparg & 1; + specializing op(_SPECIALIZE_LOAD_SUPER_ATTR, (counter/1, global_super, class, unused -- global_super, class, unused)) { + TIER_ONE_ONLY #if ENABLE_SPECIALIZATION - _PySuperAttrCache *cache = (_PySuperAttrCache *)next_instr; - if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) { - next_instr--; + int load_method = oparg & 1; + if (ADAPTIVE_COUNTER_IS_ZERO(counter)) { + next_instr = this_instr; _Py_Specialize_LoadSuperAttr(global_super, class, next_instr, load_method); DISPATCH_SAME_OPARG(); } STAT_INC(LOAD_SUPER_ATTR, deferred); - DECREMENT_ADAPTIVE_COUNTER(cache->counter); + DECREMENT_ADAPTIVE_COUNTER(this_instr[1].cache); #endif /* ENABLE_SPECIALIZATION */ + } + op(_LOAD_SUPER_ATTR, (global_super, class, self -- attr, null if (oparg & 1))) { + TIER_ONE_ONLY if (opcode == INSTRUMENTED_LOAD_SUPER_ATTR) { PyObject *arg = oparg & 2 ? class : &_PyInstrumentation_MISSING; int err = _Py_call_instrumentation_2args( tstate, PY_MONITORING_EVENT_CALL, - frame, next_instr-1, global_super, arg); + frame, this_instr, global_super, arg); ERROR_IF(err, error); } - // we make no attempt to optimize here; specializations should // handle any case whose performance we care about PyObject *stack[] = {class, self}; @@ -1675,12 +1760,12 @@ dummy_func( if (super == NULL) { _Py_call_instrumentation_exc2( tstate, PY_MONITORING_EVENT_C_RAISE, - frame, next_instr-1, global_super, arg); + frame, this_instr, global_super, arg); } else { int err = _Py_call_instrumentation_2args( tstate, PY_MONITORING_EVENT_C_RETURN, - frame, next_instr-1, global_super, arg); + frame, this_instr, global_super, arg); if (err < 0) { Py_CLEAR(super); } @@ -1688,11 +1773,15 @@ dummy_func( } DECREF_INPUTS(); ERROR_IF(super == NULL, error); - res = PyObject_GetAttr(super, name); + PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 2); + attr = PyObject_GetAttr(super, name); Py_DECREF(super); - ERROR_IF(res == NULL, error); + ERROR_IF(attr == NULL, error); + null = NULL; } + macro(LOAD_SUPER_ATTR) = _SPECIALIZE_LOAD_SUPER_ATTR + _LOAD_SUPER_ATTR; + pseudo(LOAD_SUPER_METHOD) = { LOAD_SUPER_ATTR, }; @@ -1705,39 +1794,38 @@ dummy_func( LOAD_SUPER_ATTR, }; - inst(LOAD_SUPER_ATTR_ATTR, (unused/1, global_super, class, self -- res2 if (oparg & 1), res)) { + inst(LOAD_SUPER_ATTR_ATTR, (unused/1, global_super, class, self -- attr, unused if (0))) { assert(!(oparg & 1)); - DEOPT_IF(global_super != (PyObject *)&PySuper_Type, LOAD_SUPER_ATTR); - DEOPT_IF(!PyType_Check(class), LOAD_SUPER_ATTR); + DEOPT_IF(global_super != (PyObject *)&PySuper_Type); + DEOPT_IF(!PyType_Check(class)); STAT_INC(LOAD_SUPER_ATTR, hit); PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 2); - res = _PySuper_Lookup((PyTypeObject *)class, self, name, NULL); + attr = _PySuper_Lookup((PyTypeObject *)class, self, name, NULL); DECREF_INPUTS(); - ERROR_IF(res == NULL, error); + ERROR_IF(attr == NULL, error); } - inst(LOAD_SUPER_ATTR_METHOD, (unused/1, global_super, class, self -- res2, res)) { + inst(LOAD_SUPER_ATTR_METHOD, (unused/1, global_super, class, self -- attr, self_or_null)) { assert(oparg & 1); - DEOPT_IF(global_super != (PyObject *)&PySuper_Type, LOAD_SUPER_ATTR); - DEOPT_IF(!PyType_Check(class), LOAD_SUPER_ATTR); + DEOPT_IF(global_super != (PyObject *)&PySuper_Type); + DEOPT_IF(!PyType_Check(class)); STAT_INC(LOAD_SUPER_ATTR, hit); PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 2); PyTypeObject *cls = (PyTypeObject *)class; int method_found = 0; - res2 = _PySuper_Lookup(cls, self, name, + attr = _PySuper_Lookup(cls, self, name, Py_TYPE(self)->tp_getattro == PyObject_GenericGetAttr ? &method_found : NULL); Py_DECREF(global_super); Py_DECREF(class); - if (res2 == NULL) { + if (attr == NULL) { Py_DECREF(self); ERROR_IF(true, error); } if (method_found) { - res = self; // transfer ownership + self_or_null = self; // transfer ownership } else { Py_DECREF(self); - res = res2; - res2 = NULL; + self_or_null = NULL; } } @@ -1756,54 +1844,58 @@ dummy_func( LOAD_ATTR_NONDESCRIPTOR_NO_DICT, }; - inst(LOAD_ATTR, (unused/9, owner -- res2 if (oparg & 1), res)) { + specializing op(_SPECIALIZE_LOAD_ATTR, (counter/1, owner -- owner)) { + TIER_ONE_ONLY #if ENABLE_SPECIALIZATION - _PyAttrCache *cache = (_PyAttrCache *)next_instr; - if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) { + if (ADAPTIVE_COUNTER_IS_ZERO(counter)) { PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1); - next_instr--; + next_instr = this_instr; _Py_Specialize_LoadAttr(owner, next_instr, name); DISPATCH_SAME_OPARG(); } STAT_INC(LOAD_ATTR, deferred); - DECREMENT_ADAPTIVE_COUNTER(cache->counter); + DECREMENT_ADAPTIVE_COUNTER(this_instr[1].cache); #endif /* ENABLE_SPECIALIZATION */ + } + + op(_LOAD_ATTR, (owner -- attr, self_or_null if (oparg & 1))) { PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 1); if (oparg & 1) { /* Designed to work in tandem with CALL, pushes two values. */ - PyObject* meth = NULL; - if (_PyObject_GetMethod(owner, name, &meth)) { + attr = NULL; + if (_PyObject_GetMethod(owner, name, &attr)) { /* We can bypass temporary bound method object. meth is unbound method and obj is self. - meth | self | arg1 | ... | argN */ - assert(meth != NULL); // No errors on this branch - res2 = meth; - res = owner; // Transfer ownership + assert(attr != NULL); // No errors on this branch + self_or_null = owner; // Transfer ownership } else { /* meth is not an unbound method (but a regular attr, or something was returned by a descriptor protocol). Set the second element of the stack to NULL, to signal CALL that it's not a method call. - NULL | meth | arg1 | ... | argN */ DECREF_INPUTS(); - ERROR_IF(meth == NULL, error); - res2 = NULL; - res = meth; + ERROR_IF(attr == NULL, error); + self_or_null = NULL; } } else { /* Classic, pushes one value. */ - res = PyObject_GetAttr(owner, name); + attr = PyObject_GetAttr(owner, name); DECREF_INPUTS(); - ERROR_IF(res == NULL, error); + ERROR_IF(attr == NULL, error); } } + macro(LOAD_ATTR) = + _SPECIALIZE_LOAD_ATTR + + unused/8 + + _LOAD_ATTR; + pseudo(LOAD_METHOD) = { LOAD_ATTR, }; @@ -1811,23 +1903,23 @@ dummy_func( op(_GUARD_TYPE_VERSION, (type_version/2, owner -- owner)) { PyTypeObject *tp = Py_TYPE(owner); assert(type_version != 0); - DEOPT_IF(tp->tp_version_tag != type_version, LOAD_ATTR); + DEOPT_IF(tp->tp_version_tag != type_version); } op(_CHECK_MANAGED_OBJECT_HAS_VALUES, (owner -- owner)) { assert(Py_TYPE(owner)->tp_dictoffset < 0); assert(Py_TYPE(owner)->tp_flags & Py_TPFLAGS_MANAGED_DICT); - PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner); - DEOPT_IF(!_PyDictOrValues_IsValues(dorv), LOAD_ATTR); + PyDictOrValues *dorv = _PyObject_DictOrValuesPointer(owner); + DEOPT_IF(!_PyDictOrValues_IsValues(*dorv) && !_PyObject_MakeInstanceAttributesFromDict(owner, dorv)); } - op(_LOAD_ATTR_INSTANCE_VALUE, (index/1, owner -- res2 if (oparg & 1), res)) { + op(_LOAD_ATTR_INSTANCE_VALUE, (index/1, owner -- attr, null if (oparg & 1))) { PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner); - res = _PyDictOrValues_GetValues(dorv)->values[index]; - DEOPT_IF(res == NULL, LOAD_ATTR); + attr = _PyDictOrValues_GetValues(dorv)->values[index]; + DEOPT_IF(attr == NULL); STAT_INC(LOAD_ATTR, hit); - Py_INCREF(res); - res2 = NULL; + Py_INCREF(attr); + null = NULL; DECREF_INPUTS(); } @@ -1838,141 +1930,165 @@ dummy_func( _LOAD_ATTR_INSTANCE_VALUE + unused/5; // Skip over rest of cache - inst(LOAD_ATTR_MODULE, (unused/1, type_version/2, index/1, unused/5, owner -- res2 if (oparg & 1), res)) { - DEOPT_IF(!PyModule_CheckExact(owner), LOAD_ATTR); + op(_CHECK_ATTR_MODULE, (type_version/2, owner -- owner)) { + DEOPT_IF(!PyModule_CheckExact(owner)); PyDictObject *dict = (PyDictObject *)((PyModuleObject *)owner)->md_dict; assert(dict != NULL); - DEOPT_IF(dict->ma_keys->dk_version != type_version, LOAD_ATTR); + DEOPT_IF(dict->ma_keys->dk_version != type_version); + } + + op(_LOAD_ATTR_MODULE, (index/1, owner -- attr, null if (oparg & 1))) { + PyDictObject *dict = (PyDictObject *)((PyModuleObject *)owner)->md_dict; assert(dict->ma_keys->dk_kind == DICT_KEYS_UNICODE); assert(index < dict->ma_keys->dk_nentries); PyDictUnicodeEntry *ep = DK_UNICODE_ENTRIES(dict->ma_keys) + index; - res = ep->me_value; - DEOPT_IF(res == NULL, LOAD_ATTR); + attr = ep->me_value; + DEOPT_IF(attr == NULL); STAT_INC(LOAD_ATTR, hit); - Py_INCREF(res); - res2 = NULL; + Py_INCREF(attr); + null = NULL; DECREF_INPUTS(); } - inst(LOAD_ATTR_WITH_HINT, (unused/1, type_version/2, index/1, unused/5, owner -- res2 if (oparg & 1), res)) { - PyTypeObject *tp = Py_TYPE(owner); - assert(type_version != 0); - DEOPT_IF(tp->tp_version_tag != type_version, LOAD_ATTR); - assert(tp->tp_flags & Py_TPFLAGS_MANAGED_DICT); + macro(LOAD_ATTR_MODULE) = + unused/1 + + _CHECK_ATTR_MODULE + + _LOAD_ATTR_MODULE + + unused/5; + + op(_CHECK_ATTR_WITH_HINT, (owner -- owner)) { + assert(Py_TYPE(owner)->tp_flags & Py_TPFLAGS_MANAGED_DICT); PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner); - DEOPT_IF(_PyDictOrValues_IsValues(dorv), LOAD_ATTR); + DEOPT_IF(_PyDictOrValues_IsValues(dorv)); PyDictObject *dict = (PyDictObject *)_PyDictOrValues_GetDict(dorv); - DEOPT_IF(dict == NULL, LOAD_ATTR); + DEOPT_IF(dict == NULL); assert(PyDict_CheckExact((PyObject *)dict)); + } + + op(_LOAD_ATTR_WITH_HINT, (hint/1, owner -- attr, null if (oparg & 1))) { + PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner); + PyDictObject *dict = (PyDictObject *)_PyDictOrValues_GetDict(dorv); + DEOPT_IF(hint >= (size_t)dict->ma_keys->dk_nentries); PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1); - uint16_t hint = index; - DEOPT_IF(hint >= (size_t)dict->ma_keys->dk_nentries, LOAD_ATTR); if (DK_IS_UNICODE(dict->ma_keys)) { PyDictUnicodeEntry *ep = DK_UNICODE_ENTRIES(dict->ma_keys) + hint; - DEOPT_IF(ep->me_key != name, LOAD_ATTR); - res = ep->me_value; + DEOPT_IF(ep->me_key != name); + attr = ep->me_value; } else { PyDictKeyEntry *ep = DK_ENTRIES(dict->ma_keys) + hint; - DEOPT_IF(ep->me_key != name, LOAD_ATTR); - res = ep->me_value; + DEOPT_IF(ep->me_key != name); + attr = ep->me_value; } - DEOPT_IF(res == NULL, LOAD_ATTR); + DEOPT_IF(attr == NULL); STAT_INC(LOAD_ATTR, hit); - Py_INCREF(res); - res2 = NULL; + Py_INCREF(attr); + null = NULL; DECREF_INPUTS(); } - inst(LOAD_ATTR_SLOT, (unused/1, type_version/2, index/1, unused/5, owner -- res2 if (oparg & 1), res)) { - PyTypeObject *tp = Py_TYPE(owner); - assert(type_version != 0); - DEOPT_IF(tp->tp_version_tag != type_version, LOAD_ATTR); + macro(LOAD_ATTR_WITH_HINT) = + unused/1 + + _GUARD_TYPE_VERSION + + _CHECK_ATTR_WITH_HINT + + _LOAD_ATTR_WITH_HINT + + unused/5; + + op(_LOAD_ATTR_SLOT, (index/1, owner -- attr, null if (oparg & 1))) { char *addr = (char *)owner + index; - res = *(PyObject **)addr; - DEOPT_IF(res == NULL, LOAD_ATTR); + attr = *(PyObject **)addr; + DEOPT_IF(attr == NULL); STAT_INC(LOAD_ATTR, hit); - Py_INCREF(res); - res2 = NULL; + Py_INCREF(attr); + null = NULL; DECREF_INPUTS(); } - inst(LOAD_ATTR_CLASS, (unused/1, type_version/2, unused/2, descr/4, cls -- res2 if (oparg & 1), res)) { + macro(LOAD_ATTR_SLOT) = + unused/1 + + _GUARD_TYPE_VERSION + + _LOAD_ATTR_SLOT + // NOTE: This action may also deopt + unused/5; - DEOPT_IF(!PyType_Check(cls), LOAD_ATTR); - DEOPT_IF(((PyTypeObject *)cls)->tp_version_tag != type_version, - LOAD_ATTR); + op(_CHECK_ATTR_CLASS, (type_version/2, owner -- owner)) { + DEOPT_IF(!PyType_Check(owner)); assert(type_version != 0); + DEOPT_IF(((PyTypeObject *)owner)->tp_version_tag != type_version); + } + + op(_LOAD_ATTR_CLASS, (descr/4, owner -- attr, null if (oparg & 1))) { STAT_INC(LOAD_ATTR, hit); - res2 = NULL; - res = descr; - assert(res != NULL); - Py_INCREF(res); + assert(descr != NULL); + attr = Py_NewRef(descr); + null = NULL; DECREF_INPUTS(); } - inst(LOAD_ATTR_PROPERTY, (unused/1, type_version/2, func_version/2, fget/4, owner -- unused if (oparg & 1), unused)) { - DEOPT_IF(tstate->interp->eval_frame, LOAD_ATTR); + macro(LOAD_ATTR_CLASS) = + unused/1 + + _CHECK_ATTR_CLASS + + unused/2 + + _LOAD_ATTR_CLASS; + + inst(LOAD_ATTR_PROPERTY, (unused/1, type_version/2, func_version/2, fget/4, owner -- unused, unused if (0))) { + assert((oparg & 1) == 0); + DEOPT_IF(tstate->interp->eval_frame); PyTypeObject *cls = Py_TYPE(owner); - DEOPT_IF(cls->tp_version_tag != type_version, LOAD_ATTR); assert(type_version != 0); + DEOPT_IF(cls->tp_version_tag != type_version); assert(Py_IS_TYPE(fget, &PyFunction_Type)); PyFunctionObject *f = (PyFunctionObject *)fget; assert(func_version != 0); - DEOPT_IF(f->func_version != func_version, LOAD_ATTR); + DEOPT_IF(f->func_version != func_version); PyCodeObject *code = (PyCodeObject *)f->func_code; assert(code->co_argcount == 1); - DEOPT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize), LOAD_ATTR); + DEOPT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize)); STAT_INC(LOAD_ATTR, hit); Py_INCREF(fget); _PyInterpreterFrame *new_frame = _PyFrame_PushUnchecked(tstate, f, 1); // Manipulate stack directly because we exit with DISPATCH_INLINED(). - SET_TOP(NULL); - int shrink_stack = !(oparg & 1); - STACK_SHRINK(shrink_stack); + STACK_SHRINK(1); new_frame->localsplus[0] = owner; - SKIP_OVER(INLINE_CACHE_ENTRIES_LOAD_ATTR); - frame->return_offset = 0; + frame->return_offset = (uint16_t)(next_instr - this_instr); DISPATCH_INLINED(new_frame); } - inst(LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN, (unused/1, type_version/2, func_version/2, getattribute/4, owner -- unused if (oparg & 1), unused)) { - DEOPT_IF(tstate->interp->eval_frame, LOAD_ATTR); + inst(LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN, (unused/1, type_version/2, func_version/2, getattribute/4, owner -- unused, unused if (0))) { + assert((oparg & 1) == 0); + DEOPT_IF(tstate->interp->eval_frame); PyTypeObject *cls = Py_TYPE(owner); - DEOPT_IF(cls->tp_version_tag != type_version, LOAD_ATTR); assert(type_version != 0); + DEOPT_IF(cls->tp_version_tag != type_version); assert(Py_IS_TYPE(getattribute, &PyFunction_Type)); PyFunctionObject *f = (PyFunctionObject *)getattribute; assert(func_version != 0); - DEOPT_IF(f->func_version != func_version, LOAD_ATTR); + DEOPT_IF(f->func_version != func_version); PyCodeObject *code = (PyCodeObject *)f->func_code; assert(code->co_argcount == 2); - DEOPT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize), LOAD_ATTR); + DEOPT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize)); STAT_INC(LOAD_ATTR, hit); PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 1); Py_INCREF(f); _PyInterpreterFrame *new_frame = _PyFrame_PushUnchecked(tstate, f, 2); // Manipulate stack directly because we exit with DISPATCH_INLINED(). - SET_TOP(NULL); - int shrink_stack = !(oparg & 1); - STACK_SHRINK(shrink_stack); + STACK_SHRINK(1); new_frame->localsplus[0] = owner; new_frame->localsplus[1] = Py_NewRef(name); - SKIP_OVER(INLINE_CACHE_ENTRIES_LOAD_ATTR); - frame->return_offset = 0; + frame->return_offset = (uint16_t)(next_instr - this_instr); DISPATCH_INLINED(new_frame); } - inst(STORE_ATTR_INSTANCE_VALUE, (unused/1, type_version/2, index/1, value, owner --)) { - PyTypeObject *tp = Py_TYPE(owner); - assert(type_version != 0); - DEOPT_IF(tp->tp_version_tag != type_version, STORE_ATTR); - assert(tp->tp_flags & Py_TPFLAGS_MANAGED_DICT); + op(_GUARD_DORV_VALUES, (owner -- owner)) { + assert(Py_TYPE(owner)->tp_flags & Py_TPFLAGS_MANAGED_DICT); + PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner); + DEOPT_IF(!_PyDictOrValues_IsValues(dorv)); + } + + op(_STORE_ATTR_INSTANCE_VALUE, (index/1, value, owner --)) { PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner); - DEOPT_IF(!_PyDictOrValues_IsValues(dorv), STORE_ATTR); STAT_INC(STORE_ATTR, hit); PyDictValues *values = _PyDictOrValues_GetValues(dorv); PyObject *old_value = values->values[index]; @@ -1986,33 +2102,39 @@ dummy_func( Py_DECREF(owner); } + macro(STORE_ATTR_INSTANCE_VALUE) = + unused/1 + + _GUARD_TYPE_VERSION + + _GUARD_DORV_VALUES + + _STORE_ATTR_INSTANCE_VALUE; + inst(STORE_ATTR_WITH_HINT, (unused/1, type_version/2, hint/1, value, owner --)) { PyTypeObject *tp = Py_TYPE(owner); assert(type_version != 0); - DEOPT_IF(tp->tp_version_tag != type_version, STORE_ATTR); + DEOPT_IF(tp->tp_version_tag != type_version); assert(tp->tp_flags & Py_TPFLAGS_MANAGED_DICT); PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner); - DEOPT_IF(_PyDictOrValues_IsValues(dorv), STORE_ATTR); + DEOPT_IF(_PyDictOrValues_IsValues(dorv)); PyDictObject *dict = (PyDictObject *)_PyDictOrValues_GetDict(dorv); - DEOPT_IF(dict == NULL, STORE_ATTR); + DEOPT_IF(dict == NULL); assert(PyDict_CheckExact((PyObject *)dict)); PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); - DEOPT_IF(hint >= (size_t)dict->ma_keys->dk_nentries, STORE_ATTR); + DEOPT_IF(hint >= (size_t)dict->ma_keys->dk_nentries); PyObject *old_value; uint64_t new_version; if (DK_IS_UNICODE(dict->ma_keys)) { PyDictUnicodeEntry *ep = DK_UNICODE_ENTRIES(dict->ma_keys) + hint; - DEOPT_IF(ep->me_key != name, STORE_ATTR); + DEOPT_IF(ep->me_key != name); old_value = ep->me_value; - DEOPT_IF(old_value == NULL, STORE_ATTR); + DEOPT_IF(old_value == NULL); new_version = _PyDict_NotifyEvent(tstate->interp, PyDict_EVENT_MODIFIED, dict, name, value); ep->me_value = value; } else { PyDictKeyEntry *ep = DK_ENTRIES(dict->ma_keys) + hint; - DEOPT_IF(ep->me_key != name, STORE_ATTR); + DEOPT_IF(ep->me_key != name); old_value = ep->me_value; - DEOPT_IF(old_value == NULL, STORE_ATTR); + DEOPT_IF(old_value == NULL); new_version = _PyDict_NotifyEvent(tstate->interp, PyDict_EVENT_MODIFIED, dict, name, value); ep->me_value = value; } @@ -2027,10 +2149,7 @@ dummy_func( Py_DECREF(owner); } - inst(STORE_ATTR_SLOT, (unused/1, type_version/2, index/1, value, owner --)) { - PyTypeObject *tp = Py_TYPE(owner); - assert(type_version != 0); - DEOPT_IF(tp->tp_version_tag != type_version, STORE_ATTR); + op(_STORE_ATTR_SLOT, (index/1, value, owner --)) { char *addr = (char *)owner + index; STAT_INC(STORE_ATTR, hit); PyObject *old_value = *(PyObject **)addr; @@ -2039,23 +2158,31 @@ dummy_func( Py_DECREF(owner); } + macro(STORE_ATTR_SLOT) = + unused/1 + + _GUARD_TYPE_VERSION + + _STORE_ATTR_SLOT; + family(COMPARE_OP, INLINE_CACHE_ENTRIES_COMPARE_OP) = { COMPARE_OP_FLOAT, COMPARE_OP_INT, COMPARE_OP_STR, }; - inst(COMPARE_OP, (unused/1, left, right -- res)) { + specializing op(_SPECIALIZE_COMPARE_OP, (counter/1, left, right -- left, right)) { + TIER_ONE_ONLY #if ENABLE_SPECIALIZATION - _PyCompareOpCache *cache = (_PyCompareOpCache *)next_instr; - if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) { - next_instr--; + if (ADAPTIVE_COUNTER_IS_ZERO(counter)) { + next_instr = this_instr; _Py_Specialize_CompareOp(left, right, next_instr, oparg); DISPATCH_SAME_OPARG(); } STAT_INC(COMPARE_OP, deferred); - DECREMENT_ADAPTIVE_COUNTER(cache->counter); + DECREMENT_ADAPTIVE_COUNTER(this_instr[1].cache); #endif /* ENABLE_SPECIALIZATION */ + } + + op(_COMPARE_OP, (left, right -- res)) { assert((oparg >> 5) <= Py_GE); res = PyObject_RichCompare(left, right, oparg >> 5); DECREF_INPUTS(); @@ -2068,9 +2195,11 @@ dummy_func( } } + macro(COMPARE_OP) = _SPECIALIZE_COMPARE_OP + _COMPARE_OP; + inst(COMPARE_OP_FLOAT, (unused/1, left, right -- res)) { - DEOPT_IF(!PyFloat_CheckExact(left), COMPARE_OP); - DEOPT_IF(!PyFloat_CheckExact(right), COMPARE_OP); + DEOPT_IF(!PyFloat_CheckExact(left)); + DEOPT_IF(!PyFloat_CheckExact(right)); STAT_INC(COMPARE_OP, hit); double dleft = PyFloat_AS_DOUBLE(left); double dright = PyFloat_AS_DOUBLE(right); @@ -2084,10 +2213,10 @@ dummy_func( // Similar to COMPARE_OP_FLOAT inst(COMPARE_OP_INT, (unused/1, left, right -- res)) { - DEOPT_IF(!PyLong_CheckExact(left), COMPARE_OP); - DEOPT_IF(!PyLong_CheckExact(right), COMPARE_OP); - DEOPT_IF(!_PyLong_IsCompact((PyLongObject *)left), COMPARE_OP); - DEOPT_IF(!_PyLong_IsCompact((PyLongObject *)right), COMPARE_OP); + DEOPT_IF(!PyLong_CheckExact(left)); + DEOPT_IF(!PyLong_CheckExact(right)); + DEOPT_IF(!_PyLong_IsCompact((PyLongObject *)left)); + DEOPT_IF(!_PyLong_IsCompact((PyLongObject *)right)); STAT_INC(COMPARE_OP, hit); assert(_PyLong_DigitCount((PyLongObject *)left) <= 1 && _PyLong_DigitCount((PyLongObject *)right) <= 1); @@ -2103,8 +2232,8 @@ dummy_func( // Similar to COMPARE_OP_FLOAT, but for ==, != only inst(COMPARE_OP_STR, (unused/1, left, right -- res)) { - DEOPT_IF(!PyUnicode_CheckExact(left), COMPARE_OP); - DEOPT_IF(!PyUnicode_CheckExact(right), COMPARE_OP); + DEOPT_IF(!PyUnicode_CheckExact(left)); + DEOPT_IF(!PyUnicode_CheckExact(right)); STAT_INC(COMPARE_OP, hit); int eq = _PyUnicode_Equal(left, right); assert((oparg >> 5) == Py_EQ || (oparg >> 5) == Py_NE); @@ -2164,6 +2293,7 @@ dummy_func( } inst(IMPORT_NAME, (level, fromlist -- res)) { + TIER_ONE_ONLY PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); res = import_name(tstate, frame, name, fromlist, level); DECREF_INPUTS(); @@ -2171,39 +2301,55 @@ dummy_func( } inst(IMPORT_FROM, (from -- from, res)) { + TIER_ONE_ONLY PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); res = import_from(tstate, from, name); ERROR_IF(res == NULL, error); } inst(JUMP_FORWARD, (--)) { + TIER_ONE_ONLY JUMPBY(oparg); } - inst(JUMP_BACKWARD, (--)) { + inst(JUMP_BACKWARD, (unused/1 --)) { CHECK_EVAL_BREAKER(); - _Py_CODEUNIT *here = next_instr - 1; assert(oparg <= INSTR_OFFSET()); - JUMPBY(1-oparg); + JUMPBY(-oparg); #if ENABLE_SPECIALIZATION - here[1].cache += (1 << OPTIMIZER_BITS_IN_COUNTER); - if (here[1].cache > tstate->interp->optimizer_backedge_threshold && - // Double-check that the opcode isn't instrumented or something: - here->op.code == JUMP_BACKWARD && - // _PyOptimizer_BackEdge is going to change frame->prev_instr, - // which breaks line event calculations: - next_instr->op.code != INSTRUMENTED_LINE - ) - { - OBJECT_STAT_INC(optimization_attempts); - frame = _PyOptimizer_BackEdge(frame, here, next_instr, stack_pointer); - if (frame == NULL) { - frame = cframe.current_frame; - goto resume_with_error; + this_instr[1].cache += (1 << OPTIMIZER_BITS_IN_COUNTER); + /* We are using unsigned values, but we really want signed values, so + * do the 2s complement comparison manually */ + uint16_t ucounter = this_instr[1].cache + (1 << 15); + uint16_t threshold = tstate->interp->optimizer_backedge_threshold + (1 << 15); + // Double-check that the opcode isn't instrumented or something: + if (ucounter > threshold && this_instr->op.code == JUMP_BACKWARD) { + OPT_STAT_INC(attempts); + _Py_CODEUNIT *start = this_instr; + /* Back up over EXTENDED_ARGs so optimizer sees the whole instruction */ + while (oparg > 255) { + oparg >>= 8; + start--; + } + int optimized = _PyOptimizer_Optimize(frame, start, stack_pointer); + ERROR_IF(optimized < 0, error); + if (optimized) { + // Rewind and enter the executor: + assert(start->op.code == ENTER_EXECUTOR); + next_instr = start; + this_instr[1].cache &= ((1 << OPTIMIZER_BITS_IN_COUNTER) - 1); + } + else { + int backoff = this_instr[1].cache & ((1 << OPTIMIZER_BITS_IN_COUNTER) - 1); + if (backoff < MINIMUM_TIER2_BACKOFF) { + backoff = MINIMUM_TIER2_BACKOFF; + } + else if (backoff < 15 - OPTIMIZER_BITS_IN_COUNTER) { + backoff++; + } + assert(backoff <= 15 - OPTIMIZER_BITS_IN_COUNTER); + this_instr[1].cache = ((1 << 16) - ((1 << OPTIMIZER_BITS_IN_COUNTER) << backoff)) | backoff; } - assert(frame == cframe.current_frame); - here[1].cache &= ((1 << OPTIMIZER_BITS_IN_COUNTER) -1); - goto resume_frame; } #endif /* ENABLE_SPECIALIZATION */ } @@ -2219,33 +2365,48 @@ dummy_func( }; inst(ENTER_EXECUTOR, (--)) { + TIER_ONE_ONLY CHECK_EVAL_BREAKER(); PyCodeObject *code = _PyFrame_GetCode(frame); _PyExecutorObject *executor = (_PyExecutorObject *)code->co_executors->executors[oparg&255]; - int original_oparg = executor->vm_data.oparg | (oparg & 0xfffff00); - JUMPBY(1-original_oparg); - frame->prev_instr = next_instr - 1; - Py_INCREF(executor); - frame = executor->execute(executor, frame, stack_pointer); - if (frame == NULL) { - frame = cframe.current_frame; - goto resume_with_error; + if (executor->vm_data.valid) { + Py_INCREF(executor); + current_executor = (_PyUOpExecutorObject *)executor; + GOTO_TIER_TWO(); + } + else { + /* ENTER_EXECUTOR will be the first code unit of the instruction */ + assert(oparg < 256); + code->co_executors->executors[oparg] = NULL; + opcode = this_instr->op.code = executor->vm_data.opcode; + this_instr->op.arg = executor->vm_data.oparg; + oparg = executor->vm_data.oparg; + Py_DECREF(executor); + next_instr = this_instr; + DISPATCH_GOTO(); } - goto resume_frame; } - inst(POP_JUMP_IF_FALSE, (cond -- )) { + replaced op(_POP_JUMP_IF_FALSE, (cond -- )) { assert(PyBool_Check(cond)); - JUMPBY(oparg * Py_IsFalse(cond)); + int flag = Py_IsFalse(cond); + #if ENABLE_SPECIALIZATION + this_instr[1].cache = (this_instr[1].cache << 1) | flag; + #endif + JUMPBY(oparg * flag); } - inst(POP_JUMP_IF_TRUE, (cond -- )) { + replaced op(_POP_JUMP_IF_TRUE, (cond -- )) { assert(PyBool_Check(cond)); - JUMPBY(oparg * Py_IsTrue(cond)); + int flag = Py_IsTrue(cond); + #if ENABLE_SPECIALIZATION + this_instr[1].cache = (this_instr[1].cache << 1) | flag; + #endif + JUMPBY(oparg * flag); } - op(IS_NONE, (value -- b)) { + op(_IS_NONE, (value -- b)) { if (Py_IsNone(value)) { b = Py_True; } @@ -2255,11 +2416,16 @@ dummy_func( } } - macro(POP_JUMP_IF_NONE) = IS_NONE + POP_JUMP_IF_TRUE; + macro(POP_JUMP_IF_TRUE) = unused/1 + _POP_JUMP_IF_TRUE; - macro(POP_JUMP_IF_NOT_NONE) = IS_NONE + POP_JUMP_IF_FALSE; + macro(POP_JUMP_IF_FALSE) = unused/1 + _POP_JUMP_IF_FALSE; + + macro(POP_JUMP_IF_NONE) = unused/1 + _IS_NONE + _POP_JUMP_IF_TRUE; + + macro(POP_JUMP_IF_NOT_NONE) = unused/1 + _IS_NONE + _POP_JUMP_IF_FALSE; inst(JUMP_BACKWARD_NO_INTERRUPT, (--)) { + TIER_ONE_ONLY /* This bytecode is used in the `yield from` or `await` loop. * If there is an interrupt, we want it handled in the innermost * generator or coroutine, so we deliberately do not check it here. @@ -2324,7 +2490,7 @@ dummy_func( _PyErr_SetString(tstate, PyExc_TypeError, "cannot 'yield from' a coroutine object " "in a non-coroutine generator"); - goto error; + GOTO_ERROR(error); } iter = iterable; } @@ -2335,7 +2501,7 @@ dummy_func( /* `iterable` is not a generator. */ iter = PyObject_GetIter(iterable); if (iter == NULL) { - goto error; + GOTO_ERROR(error); } DECREF_INPUTS(); } @@ -2354,33 +2520,35 @@ dummy_func( FOR_ITER_GEN, }; - inst(FOR_ITER, (unused/1, iter -- iter, next)) { + specializing op(_SPECIALIZE_FOR_ITER, (counter/1, iter -- iter)) { + TIER_ONE_ONLY #if ENABLE_SPECIALIZATION - _PyForIterCache *cache = (_PyForIterCache *)next_instr; - if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) { - next_instr--; + if (ADAPTIVE_COUNTER_IS_ZERO(counter)) { + next_instr = this_instr; _Py_Specialize_ForIter(iter, next_instr, oparg); DISPATCH_SAME_OPARG(); } STAT_INC(FOR_ITER, deferred); - DECREMENT_ADAPTIVE_COUNTER(cache->counter); + DECREMENT_ADAPTIVE_COUNTER(this_instr[1].cache); #endif /* ENABLE_SPECIALIZATION */ + } + + replaced op(_FOR_ITER, (iter -- iter, next)) { /* before: [iter]; after: [iter, iter()] *or* [] (and jump over END_FOR.) */ next = (*Py_TYPE(iter)->tp_iternext)(iter); if (next == NULL) { if (_PyErr_Occurred(tstate)) { if (!_PyErr_ExceptionMatches(tstate, PyExc_StopIteration)) { - goto error; + GOTO_ERROR(error); } - monitor_raise(tstate, frame, next_instr-1); + monitor_raise(tstate, frame, this_instr); _PyErr_Clear(tstate); } /* iterator ended normally */ - assert(next_instr[INLINE_CACHE_ENTRIES_FOR_ITER + oparg].op.code == END_FOR || - next_instr[INLINE_CACHE_ENTRIES_FOR_ITER + oparg].op.code == INSTRUMENTED_END_FOR); + assert(next_instr[oparg].op.code == END_FOR || + next_instr[oparg].op.code == INSTRUMENTED_END_FOR); Py_DECREF(iter); STACK_SHRINK(1); - SKIP_OVER(INLINE_CACHE_ENTRIES_FOR_ITER); /* Jump forward oparg, then skip following END_FOR instruction */ JUMPBY(oparg + 1); DISPATCH(); @@ -2388,39 +2556,59 @@ dummy_func( // Common case: no jump, leave it to the code generator } - inst(INSTRUMENTED_FOR_ITER, ( -- )) { - _Py_CODEUNIT *here = next_instr-1; + op(_FOR_ITER_TIER_TWO, (iter -- iter, next)) { + /* before: [iter]; after: [iter, iter()] *or* [] (and jump over END_FOR.) */ + next = (*Py_TYPE(iter)->tp_iternext)(iter); + if (next == NULL) { + if (_PyErr_Occurred(tstate)) { + if (!_PyErr_ExceptionMatches(tstate, PyExc_StopIteration)) { + GOTO_ERROR(error); + } + _PyErr_Clear(tstate); + } + /* iterator ended normally */ + Py_DECREF(iter); + STACK_SHRINK(1); + /* The translator sets the deopt target just past END_FOR */ + DEOPT_IF(true); + } + // Common case: no jump, leave it to the code generator + } + + macro(FOR_ITER) = _SPECIALIZE_FOR_ITER + _FOR_ITER; + + inst(INSTRUMENTED_FOR_ITER, (unused/1 -- )) { _Py_CODEUNIT *target; PyObject *iter = TOP(); PyObject *next = (*Py_TYPE(iter)->tp_iternext)(iter); if (next != NULL) { PUSH(next); - target = next_instr + INLINE_CACHE_ENTRIES_FOR_ITER; + target = next_instr; } else { if (_PyErr_Occurred(tstate)) { if (!_PyErr_ExceptionMatches(tstate, PyExc_StopIteration)) { - goto error; + GOTO_ERROR(error); } - monitor_raise(tstate, frame, here); + monitor_raise(tstate, frame, this_instr); _PyErr_Clear(tstate); } /* iterator ended normally */ - assert(next_instr[INLINE_CACHE_ENTRIES_FOR_ITER + oparg].op.code == END_FOR || - next_instr[INLINE_CACHE_ENTRIES_FOR_ITER + oparg].op.code == INSTRUMENTED_END_FOR); + assert(next_instr[oparg].op.code == END_FOR || + next_instr[oparg].op.code == INSTRUMENTED_END_FOR); STACK_SHRINK(1); Py_DECREF(iter); /* Skip END_FOR */ - target = next_instr + INLINE_CACHE_ENTRIES_FOR_ITER + oparg + 1; + target = next_instr + oparg + 1; } - INSTRUMENTED_JUMP(here, target, PY_MONITORING_EVENT_BRANCH); + INSTRUMENTED_JUMP(this_instr, target, PY_MONITORING_EVENT_BRANCH); } op(_ITER_CHECK_LIST, (iter -- iter)) { - DEOPT_IF(Py_TYPE(iter) != &PyListIter_Type, FOR_ITER); + DEOPT_IF(Py_TYPE(iter) != &PyListIter_Type); } - op(_ITER_JUMP_LIST, (iter -- iter)) { + replaced op(_ITER_JUMP_LIST, (iter -- iter)) { _PyListIterObject *it = (_PyListIterObject *)iter; assert(Py_TYPE(iter) == &PyListIter_Type); STAT_INC(FOR_ITER, hit); @@ -2432,7 +2620,6 @@ dummy_func( } Py_DECREF(iter); STACK_SHRINK(1); - SKIP_OVER(INLINE_CACHE_ENTRIES_FOR_ITER); /* Jump forward oparg, then skip following END_FOR instruction */ JUMPBY(oparg + 1); DISPATCH(); @@ -2440,21 +2627,12 @@ dummy_func( } // Only used by Tier 2 - op(_IS_ITER_EXHAUSTED_LIST, (iter -- iter, exhausted)) { + op(_GUARD_NOT_EXHAUSTED_LIST, (iter -- iter)) { _PyListIterObject *it = (_PyListIterObject *)iter; assert(Py_TYPE(iter) == &PyListIter_Type); PyListObject *seq = it->it_seq; - if (seq == NULL) { - exhausted = Py_True; - } - else if (it->it_index >= PyList_GET_SIZE(seq)) { - Py_DECREF(seq); - it->it_seq = NULL; - exhausted = Py_True; - } - else { - exhausted = Py_False; - } + DEOPT_IF(seq == NULL); + DEOPT_IF(it->it_index >= PyList_GET_SIZE(seq)); } op(_ITER_NEXT_LIST, (iter -- iter, next)) { @@ -2473,10 +2651,10 @@ dummy_func( _ITER_NEXT_LIST; op(_ITER_CHECK_TUPLE, (iter -- iter)) { - DEOPT_IF(Py_TYPE(iter) != &PyTupleIter_Type, FOR_ITER); + DEOPT_IF(Py_TYPE(iter) != &PyTupleIter_Type); } - op(_ITER_JUMP_TUPLE, (iter -- iter)) { + replaced op(_ITER_JUMP_TUPLE, (iter -- iter)) { _PyTupleIterObject *it = (_PyTupleIterObject *)iter; assert(Py_TYPE(iter) == &PyTupleIter_Type); STAT_INC(FOR_ITER, hit); @@ -2488,7 +2666,6 @@ dummy_func( } Py_DECREF(iter); STACK_SHRINK(1); - SKIP_OVER(INLINE_CACHE_ENTRIES_FOR_ITER); /* Jump forward oparg, then skip following END_FOR instruction */ JUMPBY(oparg + 1); DISPATCH(); @@ -2496,21 +2673,12 @@ dummy_func( } // Only used by Tier 2 - op(_IS_ITER_EXHAUSTED_TUPLE, (iter -- iter, exhausted)) { + op(_GUARD_NOT_EXHAUSTED_TUPLE, (iter -- iter)) { _PyTupleIterObject *it = (_PyTupleIterObject *)iter; assert(Py_TYPE(iter) == &PyTupleIter_Type); PyTupleObject *seq = it->it_seq; - if (seq == NULL) { - exhausted = Py_True; - } - else if (it->it_index >= PyTuple_GET_SIZE(seq)) { - Py_DECREF(seq); - it->it_seq = NULL; - exhausted = Py_True; - } - else { - exhausted = Py_False; - } + DEOPT_IF(seq == NULL); + DEOPT_IF(it->it_index >= PyTuple_GET_SIZE(seq)); } op(_ITER_NEXT_TUPLE, (iter -- iter, next)) { @@ -2530,17 +2698,16 @@ dummy_func( op(_ITER_CHECK_RANGE, (iter -- iter)) { _PyRangeIterObject *r = (_PyRangeIterObject *)iter; - DEOPT_IF(Py_TYPE(r) != &PyRangeIter_Type, FOR_ITER); + DEOPT_IF(Py_TYPE(r) != &PyRangeIter_Type); } - op(_ITER_JUMP_RANGE, (iter -- iter)) { + replaced op(_ITER_JUMP_RANGE, (iter -- iter)) { _PyRangeIterObject *r = (_PyRangeIterObject *)iter; assert(Py_TYPE(r) == &PyRangeIter_Type); STAT_INC(FOR_ITER, hit); if (r->len <= 0) { STACK_SHRINK(1); Py_DECREF(r); - SKIP_OVER(INLINE_CACHE_ENTRIES_FOR_ITER); // Jump over END_FOR instruction. JUMPBY(oparg + 1); DISPATCH(); @@ -2548,10 +2715,10 @@ dummy_func( } // Only used by Tier 2 - op(_IS_ITER_EXHAUSTED_RANGE, (iter -- iter, exhausted)) { + op(_GUARD_NOT_EXHAUSTED_RANGE, (iter -- iter)) { _PyRangeIterObject *r = (_PyRangeIterObject *)iter; assert(Py_TYPE(r) == &PyRangeIter_Type); - exhausted = r->len <= 0 ? Py_True : Py_False; + DEOPT_IF(r->len <= 0); } op(_ITER_NEXT_RANGE, (iter -- iter, next)) { @@ -2572,20 +2739,20 @@ dummy_func( _ITER_NEXT_RANGE; inst(FOR_ITER_GEN, (unused/1, iter -- iter, unused)) { - DEOPT_IF(tstate->interp->eval_frame, FOR_ITER); + DEOPT_IF(tstate->interp->eval_frame); PyGenObject *gen = (PyGenObject *)iter; - DEOPT_IF(Py_TYPE(gen) != &PyGen_Type, FOR_ITER); - DEOPT_IF(gen->gi_frame_state >= FRAME_EXECUTING, FOR_ITER); + DEOPT_IF(Py_TYPE(gen) != &PyGen_Type); + DEOPT_IF(gen->gi_frame_state >= FRAME_EXECUTING); STAT_INC(FOR_ITER, hit); _PyInterpreterFrame *gen_frame = (_PyInterpreterFrame *)gen->gi_iframe; - frame->return_offset = oparg; _PyFrame_StackPush(gen_frame, Py_None); gen->gi_frame_state = FRAME_EXECUTING; gen->gi_exc_state.previous_item = tstate->exc_info; tstate->exc_info = &gen->gi_exc_state; - SKIP_OVER(INLINE_CACHE_ENTRIES_FOR_ITER); assert(next_instr[oparg].op.code == END_FOR || next_instr[oparg].op.code == INSTRUMENTED_END_FOR); + assert(next_instr - this_instr + oparg <= UINT16_MAX); + frame->return_offset = (uint16_t)(next_instr - this_instr + oparg); DISPATCH_INLINED(gen_frame); } @@ -2598,7 +2765,7 @@ dummy_func( "asynchronous context manager protocol", Py_TYPE(mgr)->tp_name); } - goto error; + GOTO_ERROR(error); } exit = _PyObject_LookupSpecial(mgr, &_Py_ID(__aexit__)); if (exit == NULL) { @@ -2610,10 +2777,10 @@ dummy_func( Py_TYPE(mgr)->tp_name); } Py_DECREF(enter); - goto error; + GOTO_ERROR(error); } DECREF_INPUTS(); - res = _PyObject_CallNoArgs(enter); + res = _PyObject_CallNoArgsTstate(tstate, enter); Py_DECREF(enter); if (res == NULL) { Py_DECREF(exit); @@ -2633,7 +2800,7 @@ dummy_func( "context manager protocol", Py_TYPE(mgr)->tp_name); } - goto error; + GOTO_ERROR(error); } exit = _PyObject_LookupSpecial(mgr, &_Py_ID(__exit__)); if (exit == NULL) { @@ -2645,10 +2812,10 @@ dummy_func( Py_TYPE(mgr)->tp_name); } Py_DECREF(enter); - goto error; + GOTO_ERROR(error); } DECREF_INPUTS(); - res = _PyObject_CallNoArgs(enter); + res = _PyObject_CallNoArgsTstate(tstate, enter); Py_DECREF(enter); if (res == NULL) { Py_DECREF(exit); @@ -2684,15 +2851,15 @@ dummy_func( ERROR_IF(res == NULL, error); } - pseudo(SETUP_FINALLY) = { + pseudo(SETUP_FINALLY, (HAS_ARG)) = { NOP, }; - pseudo(SETUP_CLEANUP) = { + pseudo(SETUP_CLEANUP, (HAS_ARG)) = { NOP, }; - pseudo(SETUP_WITH) = { + pseudo(SETUP_WITH, (HAS_ARG)) = { NOP, }; @@ -2712,163 +2879,173 @@ dummy_func( exc_info->exc_value = Py_NewRef(new_exc); } - inst(LOAD_ATTR_METHOD_WITH_VALUES, (unused/1, type_version/2, keys_version/2, descr/4, self -- res2 if (1), res)) { + op(_GUARD_DORV_VALUES_INST_ATTR_FROM_DICT, (owner -- owner)) { + assert(Py_TYPE(owner)->tp_flags & Py_TPFLAGS_MANAGED_DICT); + PyDictOrValues *dorv = _PyObject_DictOrValuesPointer(owner); + DEOPT_IF(!_PyDictOrValues_IsValues(*dorv) && !_PyObject_MakeInstanceAttributesFromDict(owner, dorv)); + } + + op(_GUARD_KEYS_VERSION, (keys_version/2, owner -- owner)) { + PyTypeObject *owner_cls = Py_TYPE(owner); + PyHeapTypeObject *owner_heap_type = (PyHeapTypeObject *)owner_cls; + DEOPT_IF(owner_heap_type->ht_cached_keys->dk_version != keys_version); + } + + op(_LOAD_ATTR_METHOD_WITH_VALUES, (descr/4, owner -- attr, self if (1))) { assert(oparg & 1); /* Cached method object */ - PyTypeObject *self_cls = Py_TYPE(self); - assert(type_version != 0); - DEOPT_IF(self_cls->tp_version_tag != type_version, LOAD_ATTR); - assert(self_cls->tp_flags & Py_TPFLAGS_MANAGED_DICT); - PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(self); - DEOPT_IF(!_PyDictOrValues_IsValues(dorv), LOAD_ATTR); - PyHeapTypeObject *self_heap_type = (PyHeapTypeObject *)self_cls; - DEOPT_IF(self_heap_type->ht_cached_keys->dk_version != - keys_version, LOAD_ATTR); STAT_INC(LOAD_ATTR, hit); assert(descr != NULL); - res2 = Py_NewRef(descr); - assert(_PyType_HasFeature(Py_TYPE(res2), Py_TPFLAGS_METHOD_DESCRIPTOR)); - res = self; + attr = Py_NewRef(descr); + assert(_PyType_HasFeature(Py_TYPE(attr), Py_TPFLAGS_METHOD_DESCRIPTOR)); + self = owner; } - inst(LOAD_ATTR_METHOD_NO_DICT, (unused/1, type_version/2, unused/2, descr/4, self -- res2 if (1), res)) { + macro(LOAD_ATTR_METHOD_WITH_VALUES) = + unused/1 + + _GUARD_TYPE_VERSION + + _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT + + _GUARD_KEYS_VERSION + + _LOAD_ATTR_METHOD_WITH_VALUES; + + op(_LOAD_ATTR_METHOD_NO_DICT, (descr/4, owner -- attr, self if (1))) { assert(oparg & 1); - PyTypeObject *self_cls = Py_TYPE(self); - DEOPT_IF(self_cls->tp_version_tag != type_version, LOAD_ATTR); - assert(self_cls->tp_dictoffset == 0); + assert(Py_TYPE(owner)->tp_dictoffset == 0); STAT_INC(LOAD_ATTR, hit); assert(descr != NULL); assert(_PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_METHOD_DESCRIPTOR)); - res2 = Py_NewRef(descr); - res = self; + attr = Py_NewRef(descr); + self = owner; } - inst(LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES, (unused/1, type_version/2, keys_version/2, descr/4, self -- res2 if (0), res)) { + macro(LOAD_ATTR_METHOD_NO_DICT) = + unused/1 + + _GUARD_TYPE_VERSION + + unused/2 + + _LOAD_ATTR_METHOD_NO_DICT; + + op(_LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES, (descr/4, owner -- attr, unused if (0))) { assert((oparg & 1) == 0); - PyTypeObject *self_cls = Py_TYPE(self); - assert(type_version != 0); - DEOPT_IF(self_cls->tp_version_tag != type_version, LOAD_ATTR); - assert(self_cls->tp_flags & Py_TPFLAGS_MANAGED_DICT); - PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(self); - DEOPT_IF(!_PyDictOrValues_IsValues(dorv), LOAD_ATTR); - PyHeapTypeObject *self_heap_type = (PyHeapTypeObject *)self_cls; - DEOPT_IF(self_heap_type->ht_cached_keys->dk_version != - keys_version, LOAD_ATTR); STAT_INC(LOAD_ATTR, hit); assert(descr != NULL); DECREF_INPUTS(); - res = Py_NewRef(descr); + attr = Py_NewRef(descr); } - inst(LOAD_ATTR_NONDESCRIPTOR_NO_DICT, (unused/1, type_version/2, unused/2, descr/4, self -- res2 if (0), res)) { + macro(LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES) = + unused/1 + + _GUARD_TYPE_VERSION + + _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT + + _GUARD_KEYS_VERSION + + _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES; + + op(_LOAD_ATTR_NONDESCRIPTOR_NO_DICT, (descr/4, owner -- attr, unused if (0))) { assert((oparg & 1) == 0); - PyTypeObject *self_cls = Py_TYPE(self); - assert(type_version != 0); - DEOPT_IF(self_cls->tp_version_tag != type_version, LOAD_ATTR); - assert(self_cls->tp_dictoffset == 0); + assert(Py_TYPE(owner)->tp_dictoffset == 0); STAT_INC(LOAD_ATTR, hit); assert(descr != NULL); DECREF_INPUTS(); - res = Py_NewRef(descr); + attr = Py_NewRef(descr); } - inst(LOAD_ATTR_METHOD_LAZY_DICT, (unused/1, type_version/2, unused/2, descr/4, self -- res2 if (1), res)) { - assert(oparg & 1); - PyTypeObject *self_cls = Py_TYPE(self); - DEOPT_IF(self_cls->tp_version_tag != type_version, LOAD_ATTR); - Py_ssize_t dictoffset = self_cls->tp_dictoffset; + macro(LOAD_ATTR_NONDESCRIPTOR_NO_DICT) = + unused/1 + + _GUARD_TYPE_VERSION + + unused/2 + + _LOAD_ATTR_NONDESCRIPTOR_NO_DICT; + + op(_CHECK_ATTR_METHOD_LAZY_DICT, (owner -- owner)) { + Py_ssize_t dictoffset = Py_TYPE(owner)->tp_dictoffset; assert(dictoffset > 0); - PyObject *dict = *(PyObject **)((char *)self + dictoffset); + PyObject *dict = *(PyObject **)((char *)owner + dictoffset); /* This object has a __dict__, just not yet created */ - DEOPT_IF(dict != NULL, LOAD_ATTR); + DEOPT_IF(dict != NULL); + } + + op(_LOAD_ATTR_METHOD_LAZY_DICT, (descr/4, owner -- attr, self if (1))) { + assert(oparg & 1); STAT_INC(LOAD_ATTR, hit); assert(descr != NULL); assert(_PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_METHOD_DESCRIPTOR)); - res2 = Py_NewRef(descr); - res = self; + attr = Py_NewRef(descr); + self = owner; } - inst(KW_NAMES, (--)) { - ASSERT_KWNAMES_IS_NULL(); - assert(oparg < PyTuple_GET_SIZE(FRAME_CO_CONSTS)); - kwnames = GETITEM(FRAME_CO_CONSTS, oparg); - } + macro(LOAD_ATTR_METHOD_LAZY_DICT) = + unused/1 + + _GUARD_TYPE_VERSION + + _CHECK_ATTR_METHOD_LAZY_DICT + + unused/2 + + _LOAD_ATTR_METHOD_LAZY_DICT; - inst(INSTRUMENTED_CALL, ( -- )) { - int is_meth = PEEK(oparg+2) != NULL; + inst(INSTRUMENTED_CALL, (unused/3 -- )) { + int is_meth = PEEK(oparg + 1) != NULL; int total_args = oparg + is_meth; - PyObject *function = PEEK(total_args + 1); + PyObject *function = PEEK(oparg + 2); PyObject *arg = total_args == 0 ? &_PyInstrumentation_MISSING : PEEK(total_args); int err = _Py_call_instrumentation_2args( tstate, PY_MONITORING_EVENT_CALL, - frame, next_instr-1, function, arg); + frame, this_instr, function, arg); ERROR_IF(err, error); - _PyCallCache *cache = (_PyCallCache *)next_instr; - INCREMENT_ADAPTIVE_COUNTER(cache->counter); + INCREMENT_ADAPTIVE_COUNTER(this_instr[1].cache); GO_TO_INSTRUCTION(CALL); } // Cache layout: counter/1, func_version/2 - // Neither CALL_INTRINSIC_1/2 nor CALL_FUNCTION_EX are members! + // CALL_INTRINSIC_1/2, CALL_KW, and CALL_FUNCTION_EX aren't members! family(CALL, INLINE_CACHE_ENTRIES_CALL) = { CALL_BOUND_METHOD_EXACT_ARGS, CALL_PY_EXACT_ARGS, CALL_PY_WITH_DEFAULTS, - CALL_NO_KW_TYPE_1, - CALL_NO_KW_STR_1, - CALL_NO_KW_TUPLE_1, + CALL_TYPE_1, + CALL_STR_1, + CALL_TUPLE_1, CALL_BUILTIN_CLASS, - CALL_NO_KW_BUILTIN_O, - CALL_NO_KW_BUILTIN_FAST, + CALL_BUILTIN_O, + CALL_BUILTIN_FAST, CALL_BUILTIN_FAST_WITH_KEYWORDS, - CALL_NO_KW_LEN, - CALL_NO_KW_ISINSTANCE, - CALL_NO_KW_LIST_APPEND, - CALL_NO_KW_METHOD_DESCRIPTOR_O, + CALL_LEN, + CALL_ISINSTANCE, + CALL_LIST_APPEND, + CALL_METHOD_DESCRIPTOR_O, CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS, - CALL_NO_KW_METHOD_DESCRIPTOR_NOARGS, - CALL_NO_KW_METHOD_DESCRIPTOR_FAST, - CALL_NO_KW_ALLOC_AND_ENTER_INIT, + CALL_METHOD_DESCRIPTOR_NOARGS, + CALL_METHOD_DESCRIPTOR_FAST, + CALL_ALLOC_AND_ENTER_INIT, }; - // On entry, the stack is either - // [NULL, callable, arg1, arg2, ...] - // or - // [method, self, arg1, arg2, ...] - // (Some args may be keywords, see KW_NAMES, which sets 'kwnames'.) - // On exit, the stack is [result]. - // When calling Python, inline the call using DISPATCH_INLINED(). - inst(CALL, (unused/1, unused/2, method, callable, args[oparg] -- res)) { - int is_meth = method != NULL; - int total_args = oparg; - if (is_meth) { - callable = method; - args--; - total_args++; - } + specializing op(_SPECIALIZE_CALL, (counter/1, callable, self_or_null, args[oparg] -- callable, self_or_null, args[oparg])) { + TIER_ONE_ONLY #if ENABLE_SPECIALIZATION - _PyCallCache *cache = (_PyCallCache *)next_instr; - if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) { - next_instr--; - _Py_Specialize_Call(callable, next_instr, total_args, kwnames); + if (ADAPTIVE_COUNTER_IS_ZERO(counter)) { + next_instr = this_instr; + _Py_Specialize_Call(callable, next_instr, oparg + (self_or_null != NULL)); DISPATCH_SAME_OPARG(); } STAT_INC(CALL, deferred); - DECREMENT_ADAPTIVE_COUNTER(cache->counter); + DECREMENT_ADAPTIVE_COUNTER(this_instr[1].cache); #endif /* ENABLE_SPECIALIZATION */ - if (!is_meth && Py_TYPE(callable) == &PyMethod_Type) { - is_meth = 1; // For consistenct; it's dead, though + } + + // When calling Python, inline the call using DISPATCH_INLINED(). + op(_CALL, (callable, self_or_null, args[oparg] -- res)) { + // oparg counts all of the args, but *not* self: + int total_args = oparg; + if (self_or_null != NULL) { + args--; + total_args++; + } + else if (Py_TYPE(callable) == &PyMethod_Type) { args--; total_args++; PyObject *self = ((PyMethodObject *)callable)->im_self; args[0] = Py_NewRef(self); - method = ((PyMethodObject *)callable)->im_func; + PyObject *method = ((PyMethodObject *)callable)->im_func; args[-1] = Py_NewRef(method); Py_DECREF(callable); callable = method; } - int positional_args = total_args - KWNAMES_LEN(); // Check if the call can be inlined or not if (Py_TYPE(callable) == &PyFunction_Type && tstate->interp->eval_frame == NULL && @@ -2878,43 +3055,40 @@ dummy_func( PyObject *locals = code_flags & CO_OPTIMIZED ? NULL : Py_NewRef(PyFunction_GET_GLOBALS(callable)); _PyInterpreterFrame *new_frame = _PyEvalFramePushAndInit( tstate, (PyFunctionObject *)callable, locals, - args, positional_args, kwnames + args, total_args, NULL ); - kwnames = NULL; // Manipulate stack directly since we leave using DISPATCH_INLINED(). STACK_SHRINK(oparg + 2); // The frame has stolen all the arguments from the stack, // so there is no need to clean them up. if (new_frame == NULL) { - goto error; + GOTO_ERROR(error); } - SKIP_OVER(INLINE_CACHE_ENTRIES_CALL); - frame->return_offset = 0; + frame->return_offset = (uint16_t)(next_instr - this_instr); DISPATCH_INLINED(new_frame); } /* Callable is not a normal Python function */ res = PyObject_Vectorcall( callable, args, - positional_args | PY_VECTORCALL_ARGUMENTS_OFFSET, - kwnames); + total_args | PY_VECTORCALL_ARGUMENTS_OFFSET, + NULL); if (opcode == INSTRUMENTED_CALL) { PyObject *arg = total_args == 0 ? - &_PyInstrumentation_MISSING : PEEK(total_args); + &_PyInstrumentation_MISSING : args[0]; if (res == NULL) { _Py_call_instrumentation_exc2( tstate, PY_MONITORING_EVENT_C_RAISE, - frame, next_instr-1, callable, arg); + frame, this_instr, callable, arg); } else { int err = _Py_call_instrumentation_2args( tstate, PY_MONITORING_EVENT_C_RETURN, - frame, next_instr-1, callable, arg); + frame, this_instr, callable, arg); if (err < 0) { Py_CLEAR(res); } } } - kwnames = NULL; assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); Py_DECREF(callable); for (int i = 0; i < total_args; i++) { @@ -2924,71 +3098,116 @@ dummy_func( CHECK_EVAL_BREAKER(); } - // Start out with [NULL, bound_method, arg1, arg2, ...] - // Transform to [callable, self, arg1, arg2, ...] - // Then fall through to CALL_PY_EXACT_ARGS - inst(CALL_BOUND_METHOD_EXACT_ARGS, (unused/1, unused/2, method, callable, unused[oparg] -- unused)) { - DEOPT_IF(method != NULL, CALL); - DEOPT_IF(Py_TYPE(callable) != &PyMethod_Type, CALL); + macro(CALL) = _SPECIALIZE_CALL + unused/2 + _CALL; + + op(_CHECK_CALL_BOUND_METHOD_EXACT_ARGS, (callable, null, unused[oparg] -- callable, null, unused[oparg])) { + DEOPT_IF(null != NULL); + DEOPT_IF(Py_TYPE(callable) != &PyMethod_Type); + } + + op(_INIT_CALL_BOUND_METHOD_EXACT_ARGS, (callable, unused, unused[oparg] -- func, self, unused[oparg])) { STAT_INC(CALL, hit); - PyObject *self = ((PyMethodObject *)callable)->im_self; - PEEK(oparg + 1) = Py_NewRef(self); // callable - PyObject *meth = ((PyMethodObject *)callable)->im_func; - PEEK(oparg + 2) = Py_NewRef(meth); // method + self = Py_NewRef(((PyMethodObject *)callable)->im_self); + stack_pointer[-1 - oparg] = self; // Patch stack as it is used by _INIT_CALL_PY_EXACT_ARGS + func = Py_NewRef(((PyMethodObject *)callable)->im_func); + stack_pointer[-2 - oparg] = func; // This is used by CALL, upon deoptimization Py_DECREF(callable); - GO_TO_INSTRUCTION(CALL_PY_EXACT_ARGS); } - inst(CALL_PY_EXACT_ARGS, (unused/1, func_version/2, method, callable, args[oparg] -- unused)) { - ASSERT_KWNAMES_IS_NULL(); - DEOPT_IF(tstate->interp->eval_frame, CALL); - int is_meth = method != NULL; + op(_CHECK_PEP_523, (--)) { + DEOPT_IF(tstate->interp->eval_frame); + } + + op(_CHECK_FUNCTION_EXACT_ARGS, (func_version/2, callable, self_or_null, unused[oparg] -- callable, self_or_null, unused[oparg])) { + DEOPT_IF(!PyFunction_Check(callable)); + PyFunctionObject *func = (PyFunctionObject *)callable; + DEOPT_IF(func->func_version != func_version); + PyCodeObject *code = (PyCodeObject *)func->func_code; + DEOPT_IF(code->co_argcount != oparg + (self_or_null != NULL)); + } + + op(_CHECK_STACK_SPACE, (callable, unused, unused[oparg] -- callable, unused, unused[oparg])) { + PyFunctionObject *func = (PyFunctionObject *)callable; + PyCodeObject *code = (PyCodeObject *)func->func_code; + DEOPT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize)); + DEOPT_IF(tstate->py_recursion_remaining <= 1); + } + + op(_INIT_CALL_PY_EXACT_ARGS, (callable, self_or_null, args[oparg] -- new_frame: _PyInterpreterFrame*)) { int argcount = oparg; - if (is_meth) { - callable = method; + if (self_or_null != NULL) { args--; argcount++; } - DEOPT_IF(!PyFunction_Check(callable), CALL); - PyFunctionObject *func = (PyFunctionObject *)callable; - DEOPT_IF(func->func_version != func_version, CALL); - PyCodeObject *code = (PyCodeObject *)func->func_code; - DEOPT_IF(code->co_argcount != argcount, CALL); - DEOPT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize), CALL); STAT_INC(CALL, hit); - _PyInterpreterFrame *new_frame = _PyFrame_PushUnchecked(tstate, func, argcount); + PyFunctionObject *func = (PyFunctionObject *)callable; + new_frame = _PyFrame_PushUnchecked(tstate, func, argcount); for (int i = 0; i < argcount; i++) { new_frame->localsplus[i] = args[i]; } - // Manipulate stack directly since we leave using DISPATCH_INLINED(). - STACK_SHRINK(oparg + 2); - SKIP_OVER(INLINE_CACHE_ENTRIES_CALL); - frame->return_offset = 0; - DISPATCH_INLINED(new_frame); } - inst(CALL_PY_WITH_DEFAULTS, (unused/1, func_version/2, method, callable, args[oparg] -- unused)) { - ASSERT_KWNAMES_IS_NULL(); - DEOPT_IF(tstate->interp->eval_frame, CALL); - int is_meth = method != NULL; + // The 'unused' output effect represents the return value + // (which will be pushed when the frame returns). + // It is needed so CALL_PY_EXACT_ARGS matches its family. + op(_PUSH_FRAME, (new_frame: _PyInterpreterFrame* -- unused if (0))) { + // Write it out explicitly because it's subtly different. + // Eventually this should be the only occurrence of this code. + assert(tstate->interp->eval_frame == NULL); + STORE_SP(); + new_frame->previous = frame; + CALL_STAT_INC(inlined_py_calls); + frame = tstate->current_frame = new_frame; + tstate->py_recursion_remaining--; + LOAD_SP(); + LOAD_IP(0); +#if LLTRACE && TIER_ONE + lltrace = maybe_lltrace_resume_frame(frame, &entry_frame, GLOBALS()); + if (lltrace < 0) { + goto exit_unwind; + } +#endif + } + + macro(CALL_BOUND_METHOD_EXACT_ARGS) = + unused/1 + // Skip over the counter + _CHECK_PEP_523 + + _CHECK_CALL_BOUND_METHOD_EXACT_ARGS + + _INIT_CALL_BOUND_METHOD_EXACT_ARGS + + _CHECK_FUNCTION_EXACT_ARGS + + _CHECK_STACK_SPACE + + _INIT_CALL_PY_EXACT_ARGS + + _SAVE_RETURN_OFFSET + + _PUSH_FRAME; + + macro(CALL_PY_EXACT_ARGS) = + unused/1 + // Skip over the counter + _CHECK_PEP_523 + + _CHECK_FUNCTION_EXACT_ARGS + + _CHECK_STACK_SPACE + + _INIT_CALL_PY_EXACT_ARGS + + _SAVE_RETURN_OFFSET + + _PUSH_FRAME; + + inst(CALL_PY_WITH_DEFAULTS, (unused/1, func_version/2, callable, self_or_null, args[oparg] -- unused)) { + DEOPT_IF(tstate->interp->eval_frame); int argcount = oparg; - if (is_meth) { - callable = method; + if (self_or_null != NULL) { args--; argcount++; } - DEOPT_IF(!PyFunction_Check(callable), CALL); + DEOPT_IF(!PyFunction_Check(callable)); PyFunctionObject *func = (PyFunctionObject *)callable; - DEOPT_IF(func->func_version != func_version, CALL); + DEOPT_IF(func->func_version != func_version); PyCodeObject *code = (PyCodeObject *)func->func_code; assert(func->func_defaults); assert(PyTuple_CheckExact(func->func_defaults)); int defcount = (int)PyTuple_GET_SIZE(func->func_defaults); assert(defcount <= code->co_argcount); int min_args = code->co_argcount - defcount; - DEOPT_IF(argcount > code->co_argcount, CALL); - DEOPT_IF(argcount < min_args, CALL); - DEOPT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize), CALL); + DEOPT_IF(argcount > code->co_argcount); + DEOPT_IF(argcount < min_args); + DEOPT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize)); STAT_INC(CALL, hit); _PyInterpreterFrame *new_frame = _PyFrame_PushUnchecked(tstate, func, code->co_argcount); for (int i = 0; i < argcount; i++) { @@ -3000,28 +3219,25 @@ dummy_func( } // Manipulate stack and cache directly since we leave using DISPATCH_INLINED(). STACK_SHRINK(oparg + 2); - SKIP_OVER(INLINE_CACHE_ENTRIES_CALL); - frame->return_offset = 0; + frame->return_offset = (uint16_t)(next_instr - this_instr); DISPATCH_INLINED(new_frame); } - inst(CALL_NO_KW_TYPE_1, (unused/1, unused/2, null, callable, args[oparg] -- res)) { - ASSERT_KWNAMES_IS_NULL(); + inst(CALL_TYPE_1, (unused/1, unused/2, callable, null, args[oparg] -- res)) { assert(oparg == 1); - DEOPT_IF(null != NULL, CALL); + DEOPT_IF(null != NULL); PyObject *obj = args[0]; - DEOPT_IF(callable != (PyObject *)&PyType_Type, CALL); + DEOPT_IF(callable != (PyObject *)&PyType_Type); STAT_INC(CALL, hit); res = Py_NewRef(Py_TYPE(obj)); Py_DECREF(obj); Py_DECREF(&PyType_Type); // I.e., callable } - inst(CALL_NO_KW_STR_1, (unused/1, unused/2, null, callable, args[oparg] -- res)) { - ASSERT_KWNAMES_IS_NULL(); + inst(CALL_STR_1, (unused/1, unused/2, callable, null, args[oparg] -- res)) { assert(oparg == 1); - DEOPT_IF(null != NULL, CALL); - DEOPT_IF(callable != (PyObject *)&PyUnicode_Type, CALL); + DEOPT_IF(null != NULL); + DEOPT_IF(callable != (PyObject *)&PyUnicode_Type); STAT_INC(CALL, hit); PyObject *arg = args[0]; res = PyObject_Str(arg); @@ -3031,11 +3247,10 @@ dummy_func( CHECK_EVAL_BREAKER(); } - inst(CALL_NO_KW_TUPLE_1, (unused/1, unused/2, null, callable, args[oparg] -- res)) { - ASSERT_KWNAMES_IS_NULL(); + inst(CALL_TUPLE_1, (unused/1, unused/2, callable, null, args[oparg] -- res)) { assert(oparg == 1); - DEOPT_IF(null != NULL, CALL); - DEOPT_IF(callable != (PyObject *)&PyTuple_Type, CALL); + DEOPT_IF(null != NULL); + DEOPT_IF(callable != (PyObject *)&PyTuple_Type); STAT_INC(CALL, hit); PyObject *arg = args[0]; res = PySequence_Tuple(arg); @@ -3045,32 +3260,31 @@ dummy_func( CHECK_EVAL_BREAKER(); } - inst(CALL_NO_KW_ALLOC_AND_ENTER_INIT, (unused/1, unused/2, null, callable, args[oparg] -- unused)) { + inst(CALL_ALLOC_AND_ENTER_INIT, (unused/1, unused/2, callable, null, args[oparg] -- unused)) { /* This instruction does the following: * 1. Creates the object (by calling ``object.__new__``) * 2. Pushes a shim frame to the frame stack (to cleanup after ``__init__``) * 3. Pushes the frame for ``__init__`` to the frame stack * */ - ASSERT_KWNAMES_IS_NULL(); - _PyCallCache *cache = (_PyCallCache *)next_instr; - DEOPT_IF(null != NULL, CALL); - DEOPT_IF(!PyType_Check(callable), CALL); + _PyCallCache *cache = (_PyCallCache *)&this_instr[1]; + DEOPT_IF(null != NULL); + DEOPT_IF(!PyType_Check(callable)); PyTypeObject *tp = (PyTypeObject *)callable; - DEOPT_IF(tp->tp_version_tag != read_u32(cache->func_version), CALL); + DEOPT_IF(tp->tp_version_tag != read_u32(cache->func_version)); PyHeapTypeObject *cls = (PyHeapTypeObject *)callable; PyFunctionObject *init = (PyFunctionObject *)cls->_spec_cache.init; PyCodeObject *code = (PyCodeObject *)init->func_code; - DEOPT_IF(code->co_argcount != oparg+1, CALL); - DEOPT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize + _Py_InitCleanup.co_framesize), CALL); + DEOPT_IF(code->co_argcount != oparg+1); + DEOPT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize + _Py_InitCleanup.co_framesize)); STAT_INC(CALL, hit); PyObject *self = _PyType_NewManagedObject(tp); if (self == NULL) { - goto error; + GOTO_ERROR(error); } Py_DECREF(tp); _PyInterpreterFrame *shim = _PyFrame_PushTrampolineUnchecked( - tstate, (PyCodeObject *)&_Py_InitCleanup, 1, 0); - assert(_PyCode_CODE((PyCodeObject *)shim->f_executable)[1].op.code == EXIT_INIT_CHECK); + tstate, (PyCodeObject *)&_Py_InitCleanup, 1); + assert(_PyCode_CODE((PyCodeObject *)shim->f_executable)[0].op.code == EXIT_INIT_CHECK); /* Push self onto stack of shim */ Py_INCREF(self); shim->localsplus[0] = self; @@ -3081,15 +3295,13 @@ dummy_func( for (int i = 0; i < oparg; i++) { init_frame->localsplus[i+1] = args[i]; } - SKIP_OVER(INLINE_CACHE_ENTRIES_CALL); - frame->prev_instr = next_instr - 1; - frame->return_offset = 0; + frame->return_offset = (uint16_t)(next_instr - this_instr); STACK_SHRINK(oparg+2); _PyFrame_SetStackPointer(frame, stack_pointer); /* Link frames */ init_frame->previous = shim; shim->previous = frame; - frame = cframe.current_frame = init_frame; + frame = tstate->current_frame = init_frame; CALL_STAT_INC(inlined_py_calls); /* Account for pushing the extra frame. * We don't check recursion depth here, @@ -3104,26 +3316,21 @@ dummy_func( PyErr_Format(PyExc_TypeError, "__init__() should return None, not '%.200s'", Py_TYPE(should_be_none)->tp_name); - goto error; + GOTO_ERROR(error); } } - inst(CALL_BUILTIN_CLASS, (unused/1, unused/2, method, callable, args[oparg] -- res)) { - int is_meth = method != NULL; + inst(CALL_BUILTIN_CLASS, (unused/1, unused/2, callable, self_or_null, args[oparg] -- res)) { int total_args = oparg; - if (is_meth) { - callable = method; + if (self_or_null != NULL) { args--; total_args++; } - int kwnames_len = KWNAMES_LEN(); - DEOPT_IF(!PyType_Check(callable), CALL); + DEOPT_IF(!PyType_Check(callable)); PyTypeObject *tp = (PyTypeObject *)callable; - DEOPT_IF(tp->tp_vectorcall == NULL, CALL); + DEOPT_IF(tp->tp_vectorcall == NULL); STAT_INC(CALL, hit); - res = tp->tp_vectorcall((PyObject *)tp, args, - total_args - kwnames_len, kwnames); - kwnames = NULL; + res = tp->tp_vectorcall((PyObject *)tp, args, total_args, NULL); /* Free the arguments. */ for (int i = 0; i < total_args; i++) { Py_DECREF(args[i]); @@ -3133,25 +3340,22 @@ dummy_func( CHECK_EVAL_BREAKER(); } - inst(CALL_NO_KW_BUILTIN_O, (unused/1, unused/2, method, callable, args[oparg] -- res)) { + inst(CALL_BUILTIN_O, (unused/1, unused/2, callable, self_or_null, args[oparg] -- res)) { /* Builtin METH_O functions */ - ASSERT_KWNAMES_IS_NULL(); - int is_meth = method != NULL; int total_args = oparg; - if (is_meth) { - callable = method; + if (self_or_null != NULL) { args--; total_args++; } - DEOPT_IF(total_args != 1, CALL); - DEOPT_IF(!PyCFunction_CheckExact(callable), CALL); - DEOPT_IF(PyCFunction_GET_FLAGS(callable) != METH_O, CALL); + DEOPT_IF(total_args != 1); + DEOPT_IF(!PyCFunction_CheckExact(callable)); + DEOPT_IF(PyCFunction_GET_FLAGS(callable) != METH_O); STAT_INC(CALL, hit); PyCFunction cfunc = PyCFunction_GET_FUNCTION(callable); // This is slower but CPython promises to check all non-vectorcall // function calls. if (_Py_EnterRecursiveCallTstate(tstate, " while calling a Python object")) { - goto error; + GOTO_ERROR(error); } PyObject *arg = args[0]; res = _PyCFunction_TrampolineCall(cfunc, PyCFunction_GET_SELF(callable), arg); @@ -3164,18 +3368,15 @@ dummy_func( CHECK_EVAL_BREAKER(); } - inst(CALL_NO_KW_BUILTIN_FAST, (unused/1, unused/2, method, callable, args[oparg] -- res)) { + inst(CALL_BUILTIN_FAST, (unused/1, unused/2, callable, self_or_null, args[oparg] -- res)) { /* Builtin METH_FASTCALL functions, without keywords */ - ASSERT_KWNAMES_IS_NULL(); - int is_meth = method != NULL; int total_args = oparg; - if (is_meth) { - callable = method; + if (self_or_null != NULL) { args--; total_args++; } - DEOPT_IF(!PyCFunction_CheckExact(callable), CALL); - DEOPT_IF(PyCFunction_GET_FLAGS(callable) != METH_FASTCALL, CALL); + DEOPT_IF(!PyCFunction_CheckExact(callable)); + DEOPT_IF(PyCFunction_GET_FLAGS(callable) != METH_FASTCALL); STAT_INC(CALL, hit); PyCFunction cfunc = PyCFunction_GET_FUNCTION(callable); /* res = func(self, args, nargs) */ @@ -3199,31 +3400,22 @@ dummy_func( CHECK_EVAL_BREAKER(); } - inst(CALL_BUILTIN_FAST_WITH_KEYWORDS, (unused/1, unused/2, method, callable, args[oparg] -- res)) { + inst(CALL_BUILTIN_FAST_WITH_KEYWORDS, (unused/1, unused/2, callable, self_or_null, args[oparg] -- res)) { /* Builtin METH_FASTCALL | METH_KEYWORDS functions */ - int is_meth = method != NULL; int total_args = oparg; - if (is_meth) { - callable = method; + if (self_or_null != NULL) { args--; total_args++; } - DEOPT_IF(!PyCFunction_CheckExact(callable), CALL); - DEOPT_IF(PyCFunction_GET_FLAGS(callable) != - (METH_FASTCALL | METH_KEYWORDS), CALL); + DEOPT_IF(!PyCFunction_CheckExact(callable)); + DEOPT_IF(PyCFunction_GET_FLAGS(callable) != (METH_FASTCALL | METH_KEYWORDS)); STAT_INC(CALL, hit); /* res = func(self, args, nargs, kwnames) */ _PyCFunctionFastWithKeywords cfunc = (_PyCFunctionFastWithKeywords)(void(*)(void)) PyCFunction_GET_FUNCTION(callable); - res = cfunc( - PyCFunction_GET_SELF(callable), - args, - total_args - KWNAMES_LEN(), - kwnames - ); + res = cfunc(PyCFunction_GET_SELF(callable), args, total_args, NULL); assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); - kwnames = NULL; /* Free the arguments. */ for (int i = 0; i < total_args; i++) { @@ -3234,24 +3426,21 @@ dummy_func( CHECK_EVAL_BREAKER(); } - inst(CALL_NO_KW_LEN, (unused/1, unused/2, method, callable, args[oparg] -- res)) { - ASSERT_KWNAMES_IS_NULL(); + inst(CALL_LEN, (unused/1, unused/2, callable, self_or_null, args[oparg] -- res)) { /* len(o) */ - int is_meth = method != NULL; int total_args = oparg; - if (is_meth) { - callable = method; + if (self_or_null != NULL) { args--; total_args++; } - DEOPT_IF(total_args != 1, CALL); + DEOPT_IF(total_args != 1); PyInterpreterState *interp = tstate->interp; - DEOPT_IF(callable != interp->callable_cache.len, CALL); + DEOPT_IF(callable != interp->callable_cache.len); STAT_INC(CALL, hit); PyObject *arg = args[0]; Py_ssize_t len_i = PyObject_Length(arg); if (len_i < 0) { - goto error; + GOTO_ERROR(error); } res = PyLong_FromSsize_t(len_i); assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); @@ -3261,25 +3450,22 @@ dummy_func( ERROR_IF(res == NULL, error); } - inst(CALL_NO_KW_ISINSTANCE, (unused/1, unused/2, method, callable, args[oparg] -- res)) { - ASSERT_KWNAMES_IS_NULL(); + inst(CALL_ISINSTANCE, (unused/1, unused/2, callable, self_or_null, args[oparg] -- res)) { /* isinstance(o, o2) */ - int is_meth = method != NULL; int total_args = oparg; - if (is_meth) { - callable = method; + if (self_or_null != NULL) { args--; total_args++; } - DEOPT_IF(total_args != 2, CALL); + DEOPT_IF(total_args != 2); PyInterpreterState *interp = tstate->interp; - DEOPT_IF(callable != interp->callable_cache.isinstance, CALL); + DEOPT_IF(callable != interp->callable_cache.isinstance); STAT_INC(CALL, hit); PyObject *cls = args[1]; PyObject *inst = args[0]; int retval = PyObject_IsInstance(inst, cls); if (retval < 0) { - goto error; + GOTO_ERROR(error); } res = PyBool_FromLong(retval); assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); @@ -3291,49 +3477,46 @@ dummy_func( } // This is secretly a super-instruction - inst(CALL_NO_KW_LIST_APPEND, (unused/1, unused/2, method, self, args[oparg] -- unused)) { - ASSERT_KWNAMES_IS_NULL(); + inst(CALL_LIST_APPEND, (unused/1, unused/2, callable, self, args[oparg] -- unused)) { + TIER_ONE_ONLY assert(oparg == 1); - assert(method != NULL); PyInterpreterState *interp = tstate->interp; - DEOPT_IF(method != interp->callable_cache.list_append, CALL); - DEOPT_IF(!PyList_Check(self), CALL); + DEOPT_IF(callable != interp->callable_cache.list_append); + assert(self != NULL); + DEOPT_IF(!PyList_Check(self)); STAT_INC(CALL, hit); if (_PyList_AppendTakeRef((PyListObject *)self, args[0]) < 0) { goto pop_1_error; // Since arg is DECREF'ed already } Py_DECREF(self); - Py_DECREF(method); + Py_DECREF(callable); STACK_SHRINK(3); - // CALL + POP_TOP - SKIP_OVER(INLINE_CACHE_ENTRIES_CALL + 1); - assert(next_instr[-1].op.code == POP_TOP); + // Skip POP_TOP + assert(next_instr->op.code == POP_TOP); + SKIP_OVER(1); DISPATCH(); } - inst(CALL_NO_KW_METHOD_DESCRIPTOR_O, (unused/1, unused/2, method, unused, args[oparg] -- res)) { - ASSERT_KWNAMES_IS_NULL(); - int is_meth = method != NULL; + inst(CALL_METHOD_DESCRIPTOR_O, (unused/1, unused/2, callable, self_or_null, args[oparg] -- res)) { int total_args = oparg; - if (is_meth) { + if (self_or_null != NULL) { args--; total_args++; } - PyMethodDescrObject *callable = - (PyMethodDescrObject *)PEEK(total_args + 1); - DEOPT_IF(total_args != 2, CALL); - DEOPT_IF(!Py_IS_TYPE(callable, &PyMethodDescr_Type), CALL); - PyMethodDef *meth = callable->d_method; - DEOPT_IF(meth->ml_flags != METH_O, CALL); + PyMethodDescrObject *method = (PyMethodDescrObject *)callable; + DEOPT_IF(total_args != 2); + DEOPT_IF(!Py_IS_TYPE(method, &PyMethodDescr_Type)); + PyMethodDef *meth = method->d_method; + DEOPT_IF(meth->ml_flags != METH_O); PyObject *arg = args[1]; PyObject *self = args[0]; - DEOPT_IF(!Py_IS_TYPE(self, callable->d_common.d_type), CALL); + DEOPT_IF(!Py_IS_TYPE(self, method->d_common.d_type)); STAT_INC(CALL, hit); PyCFunction cfunc = meth->ml_meth; // This is slower but CPython promises to check all non-vectorcall // function calls. if (_Py_EnterRecursiveCallTstate(tstate, " while calling a Python object")) { - goto error; + GOTO_ERROR(error); } res = _PyCFunction_TrampolineCall(cfunc, self, arg); _Py_LeaveRecursiveCallTstate(tstate); @@ -3345,28 +3528,25 @@ dummy_func( CHECK_EVAL_BREAKER(); } - inst(CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS, (unused/1, unused/2, method, unused, args[oparg] -- res)) { - int is_meth = method != NULL; + inst(CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS, (unused/1, unused/2, callable, self_or_null, args[oparg] -- res)) { int total_args = oparg; - if (is_meth) { + if (self_or_null != NULL) { args--; total_args++; } - PyMethodDescrObject *callable = - (PyMethodDescrObject *)PEEK(total_args + 1); - DEOPT_IF(!Py_IS_TYPE(callable, &PyMethodDescr_Type), CALL); - PyMethodDef *meth = callable->d_method; - DEOPT_IF(meth->ml_flags != (METH_FASTCALL|METH_KEYWORDS), CALL); - PyTypeObject *d_type = callable->d_common.d_type; + PyMethodDescrObject *method = (PyMethodDescrObject *)callable; + DEOPT_IF(!Py_IS_TYPE(method, &PyMethodDescr_Type)); + PyMethodDef *meth = method->d_method; + DEOPT_IF(meth->ml_flags != (METH_FASTCALL|METH_KEYWORDS)); + PyTypeObject *d_type = method->d_common.d_type; PyObject *self = args[0]; - DEOPT_IF(!Py_IS_TYPE(self, d_type), CALL); + DEOPT_IF(!Py_IS_TYPE(self, d_type)); STAT_INC(CALL, hit); int nargs = total_args - 1; _PyCFunctionFastWithKeywords cfunc = (_PyCFunctionFastWithKeywords)(void(*)(void))meth->ml_meth; - res = cfunc(self, args + 1, nargs - KWNAMES_LEN(), kwnames); + res = cfunc(self, args + 1, nargs, NULL); assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); - kwnames = NULL; /* Free the arguments. */ for (int i = 0; i < total_args; i++) { @@ -3377,28 +3557,26 @@ dummy_func( CHECK_EVAL_BREAKER(); } - inst(CALL_NO_KW_METHOD_DESCRIPTOR_NOARGS, (unused/1, unused/2, method, unused, args[oparg] -- res)) { - ASSERT_KWNAMES_IS_NULL(); + inst(CALL_METHOD_DESCRIPTOR_NOARGS, (unused/1, unused/2, callable, self_or_null, args[oparg] -- res)) { assert(oparg == 0 || oparg == 1); - int is_meth = method != NULL; int total_args = oparg; - if (is_meth) { + if (self_or_null != NULL) { args--; total_args++; } - DEOPT_IF(total_args != 1, CALL); - PyMethodDescrObject *callable = (PyMethodDescrObject *)SECOND(); - DEOPT_IF(!Py_IS_TYPE(callable, &PyMethodDescr_Type), CALL); - PyMethodDef *meth = callable->d_method; + DEOPT_IF(total_args != 1); + PyMethodDescrObject *method = (PyMethodDescrObject *)callable; + DEOPT_IF(!Py_IS_TYPE(method, &PyMethodDescr_Type)); + PyMethodDef *meth = method->d_method; PyObject *self = args[0]; - DEOPT_IF(!Py_IS_TYPE(self, callable->d_common.d_type), CALL); - DEOPT_IF(meth->ml_flags != METH_NOARGS, CALL); + DEOPT_IF(!Py_IS_TYPE(self, method->d_common.d_type)); + DEOPT_IF(meth->ml_flags != METH_NOARGS); STAT_INC(CALL, hit); PyCFunction cfunc = meth->ml_meth; // This is slower but CPython promises to check all non-vectorcall // function calls. if (_Py_EnterRecursiveCallTstate(tstate, " while calling a Python object")) { - goto error; + GOTO_ERROR(error); } res = _PyCFunction_TrampolineCall(cfunc, self, NULL); _Py_LeaveRecursiveCallTstate(tstate); @@ -3409,22 +3587,19 @@ dummy_func( CHECK_EVAL_BREAKER(); } - inst(CALL_NO_KW_METHOD_DESCRIPTOR_FAST, (unused/1, unused/2, method, unused, args[oparg] -- res)) { - ASSERT_KWNAMES_IS_NULL(); - int is_meth = method != NULL; + inst(CALL_METHOD_DESCRIPTOR_FAST, (unused/1, unused/2, callable, self_or_null, args[oparg] -- res)) { int total_args = oparg; - if (is_meth) { + if (self_or_null != NULL) { args--; total_args++; } - PyMethodDescrObject *callable = - (PyMethodDescrObject *)PEEK(total_args + 1); + PyMethodDescrObject *method = (PyMethodDescrObject *)callable; /* Builtin METH_FASTCALL methods, without keywords */ - DEOPT_IF(!Py_IS_TYPE(callable, &PyMethodDescr_Type), CALL); - PyMethodDef *meth = callable->d_method; - DEOPT_IF(meth->ml_flags != METH_FASTCALL, CALL); + DEOPT_IF(!Py_IS_TYPE(method, &PyMethodDescr_Type)); + PyMethodDef *meth = method->d_method; + DEOPT_IF(meth->ml_flags != METH_FASTCALL); PyObject *self = args[0]; - DEOPT_IF(!Py_IS_TYPE(self, callable->d_common.d_type), CALL); + DEOPT_IF(!Py_IS_TYPE(self, method->d_common.d_type)); STAT_INC(CALL, hit); _PyCFunctionFast cfunc = (_PyCFunctionFast)(void(*)(void))meth->ml_meth; @@ -3440,21 +3615,107 @@ dummy_func( CHECK_EVAL_BREAKER(); } + inst(INSTRUMENTED_CALL_KW, ( -- )) { + int is_meth = PEEK(oparg + 2) != NULL; + int total_args = oparg + is_meth; + PyObject *function = PEEK(oparg + 3); + PyObject *arg = total_args == 0 ? &_PyInstrumentation_MISSING + : PEEK(total_args + 1); + int err = _Py_call_instrumentation_2args( + tstate, PY_MONITORING_EVENT_CALL, + frame, this_instr, function, arg); + ERROR_IF(err, error); + GO_TO_INSTRUCTION(CALL_KW); + } + + inst(CALL_KW, (callable, self_or_null, args[oparg], kwnames -- res)) { + // oparg counts all of the args, but *not* self: + int total_args = oparg; + if (self_or_null != NULL) { + args--; + total_args++; + } + if (self_or_null == NULL && Py_TYPE(callable) == &PyMethod_Type) { + args--; + total_args++; + PyObject *self = ((PyMethodObject *)callable)->im_self; + args[0] = Py_NewRef(self); + PyObject *method = ((PyMethodObject *)callable)->im_func; + args[-1] = Py_NewRef(method); + Py_DECREF(callable); + callable = method; + } + int positional_args = total_args - (int)PyTuple_GET_SIZE(kwnames); + // Check if the call can be inlined or not + if (Py_TYPE(callable) == &PyFunction_Type && + tstate->interp->eval_frame == NULL && + ((PyFunctionObject *)callable)->vectorcall == _PyFunction_Vectorcall) + { + int code_flags = ((PyCodeObject*)PyFunction_GET_CODE(callable))->co_flags; + PyObject *locals = code_flags & CO_OPTIMIZED ? NULL : Py_NewRef(PyFunction_GET_GLOBALS(callable)); + _PyInterpreterFrame *new_frame = _PyEvalFramePushAndInit( + tstate, (PyFunctionObject *)callable, locals, + args, positional_args, kwnames + ); + Py_DECREF(kwnames); + // Manipulate stack directly since we leave using DISPATCH_INLINED(). + STACK_SHRINK(oparg + 3); + // The frame has stolen all the arguments from the stack, + // so there is no need to clean them up. + if (new_frame == NULL) { + GOTO_ERROR(error); + } + assert(next_instr - this_instr == 1); + frame->return_offset = 1; + DISPATCH_INLINED(new_frame); + } + /* Callable is not a normal Python function */ + res = PyObject_Vectorcall( + callable, args, + positional_args | PY_VECTORCALL_ARGUMENTS_OFFSET, + kwnames); + if (opcode == INSTRUMENTED_CALL_KW) { + PyObject *arg = total_args == 0 ? + &_PyInstrumentation_MISSING : args[0]; + if (res == NULL) { + _Py_call_instrumentation_exc2( + tstate, PY_MONITORING_EVENT_C_RAISE, + frame, this_instr, callable, arg); + } + else { + int err = _Py_call_instrumentation_2args( + tstate, PY_MONITORING_EVENT_C_RETURN, + frame, this_instr, callable, arg); + if (err < 0) { + Py_CLEAR(res); + } + } + } + Py_DECREF(kwnames); + assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); + Py_DECREF(callable); + for (int i = 0; i < total_args; i++) { + Py_DECREF(args[i]); + } + ERROR_IF(res == NULL, error); + CHECK_EVAL_BREAKER(); + } + inst(INSTRUMENTED_CALL_FUNCTION_EX, ( -- )) { GO_TO_INSTRUCTION(CALL_FUNCTION_EX); } - inst(CALL_FUNCTION_EX, (unused, func, callargs, kwargs if (oparg & 1) -- result)) { + inst(CALL_FUNCTION_EX, (func, unused, callargs, kwargs if (oparg & 1) -- result)) { // DICT_MERGE is called before this opcode if there are kwargs. // It converts all dict subtypes in kwargs into regular dicts. assert(kwargs == NULL || PyDict_CheckExact(kwargs)); if (!PyTuple_CheckExact(callargs)) { if (check_args_iterable(tstate, func, callargs) < 0) { - goto error; + GOTO_ERROR(error); } PyObject *tuple = PySequence_Tuple(callargs); if (tuple == NULL) { - goto error; + GOTO_ERROR(error); } Py_SETREF(callargs, tuple); } @@ -3467,18 +3728,18 @@ dummy_func( PyTuple_GET_ITEM(callargs, 0) : Py_None; int err = _Py_call_instrumentation_2args( tstate, PY_MONITORING_EVENT_CALL, - frame, next_instr-1, func, arg); - if (err) goto error; + frame, this_instr, func, arg); + if (err) GOTO_ERROR(error); result = PyObject_Call(func, callargs, kwargs); if (result == NULL) { _Py_call_instrumentation_exc2( tstate, PY_MONITORING_EVENT_C_RAISE, - frame, next_instr-1, func, arg); + frame, this_instr, func, arg); } else { int err = _Py_call_instrumentation_2args( tstate, PY_MONITORING_EVENT_C_RETURN, - frame, next_instr-1, func, arg); + frame, this_instr, func, arg); if (err < 0) { Py_CLEAR(result); } @@ -3499,15 +3760,16 @@ dummy_func( // Need to manually shrink the stack since we exit with DISPATCH_INLINED. STACK_SHRINK(oparg + 3); if (new_frame == NULL) { - goto error; + GOTO_ERROR(error); } - frame->return_offset = 0; + assert(next_instr - this_instr == 1); + frame->return_offset = 1; DISPATCH_INLINED(new_frame); } result = PyObject_Call(func, callargs, kwargs); } DECREF_INPUTS(); - assert(PEEK(3 + (oparg & 1)) == NULL); + assert(PEEK(2 + (oparg & 1)) == NULL); ERROR_IF(result == NULL, error); CHECK_EVAL_BREAKER(); } @@ -3519,10 +3781,11 @@ dummy_func( Py_DECREF(codeobj); if (func_obj == NULL) { - goto error; + GOTO_ERROR(error); } - func_obj->func_version = ((PyCodeObject *)codeobj)->co_version; + _PyFunction_SetVersion( + func_obj, ((PyCodeObject *)codeobj)->co_version); func = (PyObject *)func_obj; } @@ -3554,15 +3817,17 @@ dummy_func( } inst(RETURN_GENERATOR, (--)) { + TIER_ONE_ONLY assert(PyFunction_Check(frame->f_funcobj)); PyFunctionObject *func = (PyFunctionObject *)frame->f_funcobj; PyGenObject *gen = (PyGenObject *)_Py_MakeCoro(func); if (gen == NULL) { - goto error; + GOTO_ERROR(error); } assert(EMPTY()); _PyFrame_SetStackPointer(frame, stack_pointer); _PyInterpreterFrame *gen_frame = (_PyInterpreterFrame *)gen->gi_iframe; + frame->instr_ptr = next_instr; _PyFrame_Copy(frame, gen_frame); assert(frame->frame_obj == NULL); gen->gi_frame_state = FRAME_CREATED; @@ -3571,8 +3836,9 @@ dummy_func( assert(frame != &entry_frame); _PyInterpreterFrame *prev = frame->previous; _PyThreadState_PopFrame(tstate, frame); - frame = cframe.current_frame = prev; + frame = tstate->current_frame = prev; _PyFrame_StackPush(frame, (PyObject *)gen); + LOAD_IP(frame->return_offset); goto resume_frame; } @@ -3616,25 +3882,30 @@ dummy_func( top = Py_NewRef(bottom); } - inst(BINARY_OP, (unused/1, lhs, rhs -- res)) { + specializing op(_SPECIALIZE_BINARY_OP, (counter/1, lhs, rhs -- lhs, rhs)) { + TIER_ONE_ONLY #if ENABLE_SPECIALIZATION - _PyBinaryOpCache *cache = (_PyBinaryOpCache *)next_instr; - if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) { - next_instr--; + if (ADAPTIVE_COUNTER_IS_ZERO(counter)) { + next_instr = this_instr; _Py_Specialize_BinaryOp(lhs, rhs, next_instr, oparg, LOCALS_ARRAY); DISPATCH_SAME_OPARG(); } STAT_INC(BINARY_OP, deferred); - DECREMENT_ADAPTIVE_COUNTER(cache->counter); + DECREMENT_ADAPTIVE_COUNTER(this_instr[1].cache); #endif /* ENABLE_SPECIALIZATION */ assert(NB_ADD <= oparg); assert(oparg <= NB_INPLACE_XOR); + } + + op(_BINARY_OP, (lhs, rhs -- res)) { assert(_PyEval_BinaryOps[oparg]); res = _PyEval_BinaryOps[oparg](lhs, rhs); DECREF_INPUTS(); ERROR_IF(res == NULL, error); } + macro(BINARY_OP) = _SPECIALIZE_BINARY_OP + _BINARY_OP; + inst(SWAP, (bottom, unused[oparg-2], top -- top, unused[oparg-2], bottom)) { assert(oparg >= 2); @@ -3642,12 +3913,11 @@ dummy_func( inst(INSTRUMENTED_INSTRUCTION, ( -- )) { int next_opcode = _Py_call_instrumentation_instruction( - tstate, frame, next_instr-1); + tstate, frame, this_instr); ERROR_IF(next_opcode < 0, error); - next_instr--; + next_instr = this_instr; if (_PyOpcode_Caches[next_opcode]) { - _PyBinaryOpCache *cache = (_PyBinaryOpCache *)(next_instr+1); - INCREMENT_ADAPTIVE_COUNTER(cache->counter); + INCREMENT_ADAPTIVE_COUNTER(this_instr[1].cache); } assert(next_opcode > 0 && next_opcode < 256); opcode = next_opcode; @@ -3655,59 +3925,72 @@ dummy_func( } inst(INSTRUMENTED_JUMP_FORWARD, ( -- )) { - INSTRUMENTED_JUMP(next_instr-1, next_instr+oparg, PY_MONITORING_EVENT_JUMP); + INSTRUMENTED_JUMP(this_instr, next_instr + oparg, PY_MONITORING_EVENT_JUMP); } - inst(INSTRUMENTED_JUMP_BACKWARD, ( -- )) { + inst(INSTRUMENTED_JUMP_BACKWARD, (unused/1 -- )) { CHECK_EVAL_BREAKER(); - INSTRUMENTED_JUMP(next_instr-1, next_instr+1-oparg, PY_MONITORING_EVENT_JUMP); + INSTRUMENTED_JUMP(this_instr, next_instr - oparg, PY_MONITORING_EVENT_JUMP); } - inst(INSTRUMENTED_POP_JUMP_IF_TRUE, ( -- )) { + inst(INSTRUMENTED_POP_JUMP_IF_TRUE, (unused/1 -- )) { PyObject *cond = POP(); assert(PyBool_Check(cond)); - _Py_CODEUNIT *here = next_instr - 1; - int offset = Py_IsTrue(cond) * oparg; - INSTRUMENTED_JUMP(here, next_instr + offset, PY_MONITORING_EVENT_BRANCH); + int flag = Py_IsTrue(cond); + int offset = flag * oparg; + #if ENABLE_SPECIALIZATION + this_instr[1].cache = (this_instr[1].cache << 1) | flag; + #endif + INSTRUMENTED_JUMP(this_instr, next_instr + offset, PY_MONITORING_EVENT_BRANCH); } - inst(INSTRUMENTED_POP_JUMP_IF_FALSE, ( -- )) { + inst(INSTRUMENTED_POP_JUMP_IF_FALSE, (unused/1 -- )) { PyObject *cond = POP(); assert(PyBool_Check(cond)); - _Py_CODEUNIT *here = next_instr - 1; - int offset = Py_IsFalse(cond) * oparg; - INSTRUMENTED_JUMP(here, next_instr + offset, PY_MONITORING_EVENT_BRANCH); + int flag = Py_IsFalse(cond); + int offset = flag * oparg; + #if ENABLE_SPECIALIZATION + this_instr[1].cache = (this_instr[1].cache << 1) | flag; + #endif + INSTRUMENTED_JUMP(this_instr, next_instr + offset, PY_MONITORING_EVENT_BRANCH); } - inst(INSTRUMENTED_POP_JUMP_IF_NONE, ( -- )) { + inst(INSTRUMENTED_POP_JUMP_IF_NONE, (unused/1 -- )) { PyObject *value = POP(); - _Py_CODEUNIT *here = next_instr-1; + int flag = Py_IsNone(value); int offset; - if (Py_IsNone(value)) { + if (flag) { offset = oparg; } else { Py_DECREF(value); offset = 0; } - INSTRUMENTED_JUMP(here, next_instr + offset, PY_MONITORING_EVENT_BRANCH); + #if ENABLE_SPECIALIZATION + this_instr[1].cache = (this_instr[1].cache << 1) | flag; + #endif + INSTRUMENTED_JUMP(this_instr, next_instr + offset, PY_MONITORING_EVENT_BRANCH); } - inst(INSTRUMENTED_POP_JUMP_IF_NOT_NONE, ( -- )) { + inst(INSTRUMENTED_POP_JUMP_IF_NOT_NONE, (unused/1 -- )) { PyObject *value = POP(); - _Py_CODEUNIT *here = next_instr-1; int offset; - if (Py_IsNone(value)) { + int nflag = Py_IsNone(value); + if (nflag) { offset = 0; } else { Py_DECREF(value); offset = oparg; } - INSTRUMENTED_JUMP(here, next_instr + offset, PY_MONITORING_EVENT_BRANCH); + #if ENABLE_SPECIALIZATION + this_instr[1].cache = (this_instr[1].cache << 1) | !nflag; + #endif + INSTRUMENTED_JUMP(this_instr, next_instr + offset, PY_MONITORING_EVENT_BRANCH); } inst(EXTENDED_ARG, ( -- )) { + TIER_ONE_ONLY assert(oparg); opcode = next_instr->op.code; oparg = oparg << 8 | next_instr->op.arg; @@ -3716,43 +3999,81 @@ dummy_func( } inst(CACHE, (--)) { + TIER_ONE_ONLY assert(0 && "Executing a cache."); Py_UNREACHABLE(); } inst(RESERVED, (--)) { + TIER_ONE_ONLY assert(0 && "Executing RESERVED instruction."); Py_UNREACHABLE(); } ///////// Tier-2 only opcodes ///////// - op(_POP_JUMP_IF_FALSE, (flag -- )) { - if (Py_IsFalse(flag)) { - pc = oparg; - } + op (_GUARD_IS_TRUE_POP, (flag -- )) { + DEOPT_IF(Py_IsFalse(flag)); + assert(Py_IsTrue(flag)); } - op(_POP_JUMP_IF_TRUE, (flag -- )) { - if (Py_IsTrue(flag)) { - pc = oparg; - } + op (_GUARD_IS_FALSE_POP, (flag -- )) { + DEOPT_IF(Py_IsTrue(flag)); + assert(Py_IsFalse(flag)); } - op(JUMP_TO_TOP, (--)) { - pc = 0; + op (_GUARD_IS_NONE_POP, (val -- )) { + DEOPT_IF(!Py_IsNone(val)); + } + + op (_GUARD_IS_NOT_NONE_POP, (val -- )) { + DEOPT_IF(Py_IsNone(val)); + Py_DECREF(val); + } + + op(_JUMP_TO_TOP, (--)) { + next_uop = current_executor->trace; CHECK_EVAL_BREAKER(); } - op(SAVE_IP, (--)) { - frame->prev_instr = ip_offset + oparg; + op(_SET_IP, (--)) { + TIER_TWO_ONLY + // TODO: Put the code pointer in `operand` to avoid indirection via `frame` + frame->instr_ptr = _PyCode_CODE(_PyFrame_GetCode(frame)) + oparg; } - op(EXIT_TRACE, (--)) { - frame->prev_instr--; // Back up to just before destination - _PyFrame_SetStackPointer(frame, stack_pointer); - Py_DECREF(self); - return frame; + op(_SAVE_RETURN_OFFSET, (--)) { + #if TIER_ONE + frame->return_offset = (uint16_t)(next_instr - this_instr); + #endif + #if TIER_TWO + frame->return_offset = oparg; + #endif + } + + op(_EXIT_TRACE, (--)) { + TIER_TWO_ONLY + DEOPT_IF(1); + } + + op(_INSERT, (unused[oparg], top -- top, unused[oparg])) { + // Inserts TOS at position specified by oparg; + memmove(&stack_pointer[-1 - oparg], &stack_pointer[-oparg], oparg * sizeof(stack_pointer[0])); + } + + op(_CHECK_VALIDITY, (--)) { + TIER_TWO_ONLY + DEOPT_IF(!current_executor->base.vm_data.valid); + } + + op(_LOAD_CONST_INLINE_BORROW, (ptr/4 -- value)) { + value = ptr; + } + + /* Internal -- for testing executors */ + op(_INTERNAL_INCREMENT_OPT_COUNTER, (opt --)) { + _PyCounterOptimizerObject *exe = (_PyCounterOptimizerObject *)opt; + exe->count++; } diff --git a/Python/ceval.c b/Python/ceval.c index 30f722e45e476b..b3b542f8ddea37 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -14,8 +14,7 @@ #include "pycore_long.h" // _PyLong_GetZero() #include "pycore_moduleobject.h" // PyModuleObject #include "pycore_object.h" // _PyObject_GC_TRACK() -#include "pycore_opcode.h" // EXTRA_CASES -#include "pycore_opcode_metadata.h" +#include "pycore_opcode_metadata.h" // EXTRA_CASES #include "pycore_opcode_utils.h" // MAKE_FUNCTION_* #include "pycore_pyerrors.h" // _PyErr_GetRaisedException() #include "pycore_pystate.h" // _PyInterpreterState_GET() @@ -25,7 +24,9 @@ #include "pycore_sysmodule.h" // _PySys_Audit() #include "pycore_tuple.h" // _PyTuple_ITEMS() #include "pycore_typeobject.h" // _PySuper_Lookup() +#include "pycore_uop_ids.h" // Uops #include "pycore_uops.h" // _PyUOpExecutorObject +#include "pycore_pyerrors.h" #include "pycore_dict.h" #include "dictobject.h" @@ -35,9 +36,7 @@ #include "pydtrace.h" #include "setobject.h" - -#include -#include +#include // bool #ifdef Py_DEBUG /* For debugging the interpreter: */ @@ -48,12 +47,13 @@ # error "ceval.c must be build with Py_BUILD_CORE define for best performance" #endif -#if !defined(Py_DEBUG) && !defined(Py_TRACE_REFS) +#if !defined(Py_DEBUG) && !defined(Py_TRACE_REFS) && !defined(Py_GIL_DISABLED) // 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. // Define them as macros to make sure that they are always inlined by the // preprocessor. +// TODO: implement Py_DECREF macro for Py_GIL_DISABLED #undef Py_DECREF #define Py_DECREF(arg) \ @@ -109,11 +109,24 @@ dump_stack(_PyInterpreterFrame *frame, PyObject **stack_pointer) if (ptr != stack_base) { printf(", "); } - if (PyObject_Print(*ptr, stdout, 0) != 0) { + if (*ptr == NULL) { + printf(""); + continue; + } + if ( + *ptr == Py_None + || PyBool_Check(*ptr) + || PyLong_CheckExact(*ptr) + || PyFloat_CheckExact(*ptr) + || PyUnicode_CheckExact(*ptr) + ) { + if (PyObject_Print(*ptr, stdout, 0) == 0) { + continue; + } PyErr_Clear(); - printf("<%s object at %p>", - Py_TYPE(*ptr)->tp_name, (void *)(*ptr)); } + // Don't call __repr__(), it might recurse into the interpreter. + printf("<%s at %p>", Py_TYPE(*ptr)->tp_name, (void *)(*ptr)); } printf("]\n"); fflush(stdout); @@ -123,17 +136,14 @@ dump_stack(_PyInterpreterFrame *frame, PyObject **stack_pointer) static void lltrace_instruction(_PyInterpreterFrame *frame, PyObject **stack_pointer, - _Py_CODEUNIT *next_instr) + _Py_CODEUNIT *next_instr, + int opcode, + int oparg) { if (frame->owner == FRAME_OWNED_BY_CSTACK) { return; } - /* This dump_stack() operation is risky, since the repr() of some - objects enters the interpreter recursively. It is also slow. - So you might want to comment it out. */ dump_stack(frame, stack_pointer); - int oparg = next_instr->op.arg; - int opcode = next_instr->op.code; const char *opname = _PyOpcode_OpName[opcode]; assert(opname != NULL); int offset = (int)(next_instr - _PyCode_CODE(_PyFrame_GetCode(frame))); @@ -179,6 +189,34 @@ lltrace_resume_frame(_PyInterpreterFrame *frame) fflush(stdout); PyErr_SetRaisedException(exc); } + +static int +maybe_lltrace_resume_frame(_PyInterpreterFrame *frame, _PyInterpreterFrame *skip_frame, PyObject *globals) +{ + if (globals == NULL) { + return 0; + } + if (frame == skip_frame) { + return 0; + } + int r = PyDict_Contains(globals, &_Py_ID(__lltrace__)); + if (r < 0) { + return -1; + } + int lltrace = r * 5; // Levels 1-4 only trace uops + if (!lltrace) { + // Can also be controlled by environment variable + char *python_lltrace = Py_GETENV("PYTHON_LLTRACE"); + if (python_lltrace != NULL && *python_lltrace >= '0') { + lltrace = *python_lltrace - '0'; // TODO: Parse an int and all that + } + } + if (lltrace >= 5) { + lltrace_resume_frame(frame); + } + return lltrace; +} + #endif static void monitor_raise(PyThreadState *tstate, @@ -212,8 +250,6 @@ _PyEvalFramePushAndInit(PyThreadState *tstate, PyFunctionObject *func, static _PyInterpreterFrame * _PyEvalFramePushAndInit_Ex(PyThreadState *tstate, PyFunctionObject *func, PyObject *locals, Py_ssize_t nargs, PyObject *callargs, PyObject *kwargs); -static void -_PyEvalFrameClearAndPop(PyThreadState *tstate, _PyInterpreterFrame *frame); #ifdef HAVE_ERRNO_H #include @@ -472,7 +508,9 @@ _PyEval_MatchClass(PyThreadState *tstate, PyObject *subject, PyObject *type, } if (match_self) { // Easy. Copy the subject itself, and move on to kwargs. - PyList_Append(attrs, subject); + if (PyList_Append(attrs, subject) < 0) { + goto fail; + } } else { for (Py_ssize_t i = 0; i < nargs; i++) { @@ -488,7 +526,10 @@ _PyEval_MatchClass(PyThreadState *tstate, PyObject *subject, PyObject *type, if (attr == NULL) { goto fail; } - PyList_Append(attrs, attr); + if (PyList_Append(attrs, attr) < 0) { + Py_DECREF(attr); + goto fail; + } Py_DECREF(attr); } } @@ -501,7 +542,10 @@ _PyEval_MatchClass(PyThreadState *tstate, PyObject *subject, PyObject *type, if (attr == NULL) { goto fail; } - PyList_Append(attrs, attr); + if (PyList_Append(attrs, attr) < 0) { + Py_DECREF(attr); + goto fail; + } Py_DECREF(attr); } Py_SETREF(attrs, PyList_AsTuple(attrs)); @@ -570,7 +614,6 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) #include "ceval_macros.h" - int _Py_CheckRecursiveCallPy( PyThreadState *tstate) { @@ -592,26 +635,21 @@ int _Py_CheckRecursiveCallPy( return 0; } -static inline int _Py_EnterRecursivePy(PyThreadState *tstate) { - return (tstate->py_recursion_remaining-- <= 0) && - _Py_CheckRecursiveCallPy(tstate); -} - - -static inline void _Py_LeaveRecursiveCallPy(PyThreadState *tstate) { - tstate->py_recursion_remaining++; -} static const _Py_CODEUNIT _Py_INTERPRETER_TRAMPOLINE_INSTRUCTIONS[] = { /* Put a NOP at the start, so that the IP points into * the code, rather than before it */ { .op.code = NOP, .op.arg = 0 }, - { .op.code = INTERPRETER_EXIT, .op.arg = 0 }, - { .op.code = RESUME, .op.arg = 0 } + { .op.code = INTERPRETER_EXIT, .op.arg = 0 }, /* reached on return */ + { .op.code = NOP, .op.arg = 0 }, + { .op.code = INTERPRETER_EXIT, .op.arg = 0 }, /* reached on yield */ + { .op.code = RESUME, .op.arg = RESUME_OPARG_DEPTH1_MASK | RESUME_AT_FUNC_START } }; extern const struct _PyCode_DEF(8) _Py_InitCleanup; +extern const char *_PyUOpName(int index); + /* Disable unused label warnings. They are handy for debugging, even if computed gotos aren't used. */ @@ -629,6 +667,15 @@ extern const struct _PyCode_DEF(8) _Py_InitCleanup; * so consume 3 units of C stack */ #define PY_EVAL_C_STACK_UNITS 2 +#if defined(_MSC_VER) && defined(_Py_USING_PGO) +/* gh-111786: _PyEval_EvalFrameDefault is too large to optimize for speed with + PGO on MSVC. Disable that optimization temporarily. If this is fixed + upstream, we should gate this on the version of MSVC. + */ +# pragma optimize("t", off) +/* This setting is reversed below following _PyEval_EvalFrameDefault */ +#endif + PyObject* _Py_HOT_FUNCTION _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int throwflag) { @@ -643,25 +690,15 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int #ifdef Py_STATS int lastopcode = 0; #endif - // opcode is an 8-bit value to improve the code generated by MSVC - // for the big switch below (in combination with the EXTRA_CASES macro). - uint8_t opcode; /* Current opcode */ + uint8_t opcode; /* Current opcode */ int oparg; /* Current opcode argument, if any */ #ifdef LLTRACE int lltrace = 0; #endif - _PyCFrame cframe; _PyInterpreterFrame entry_frame; - PyObject *kwnames = NULL; // Borrowed reference. Reset by CALL instructions. - /* WARNING: Because the _PyCFrame lives on the C stack, - * but can be accessed from a heap allocated object (tstate) - * strict stack discipline must be maintained. - */ - _PyCFrame *prev_cframe = tstate->cframe; - cframe.previous = prev_cframe; - tstate->cframe = &cframe; + #ifdef Py_DEBUG /* Set these to invalid but identifiable values for debugging. */ @@ -672,14 +709,14 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int entry_frame.f_builtins = (PyObject*)0xaaa4; #endif entry_frame.f_executable = Py_None; - entry_frame.prev_instr = (_Py_CODEUNIT *)_Py_INTERPRETER_TRAMPOLINE_INSTRUCTIONS; + entry_frame.instr_ptr = (_Py_CODEUNIT *)_Py_INTERPRETER_TRAMPOLINE_INSTRUCTIONS + 1; entry_frame.stacktop = 0; entry_frame.owner = FRAME_OWNED_BY_CSTACK; entry_frame.return_offset = 0; /* Push frame */ - entry_frame.previous = prev_cframe->current_frame; + entry_frame.previous = tstate->current_frame; frame->previous = &entry_frame; - cframe.current_frame = frame; + tstate->current_frame = frame; tstate->c_recursion_remaining -= (PY_EVAL_C_STACK_UNITS - 1); if (_Py_EnterRecursiveCallTstate(tstate, "")) { @@ -696,43 +733,34 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int /* Because this avoids the RESUME, * we need to update instrumentation */ _Py_Instrument(_PyFrame_GetCode(frame), tstate->interp); - monitor_throw(tstate, frame, frame->prev_instr); + monitor_throw(tstate, frame, frame->instr_ptr); /* TO DO -- Monitor throw entry. */ goto resume_with_error; } + /* State shared between Tier 1 and Tier 2 interpreter */ + _PyUOpExecutorObject *current_executor = NULL; + /* Local "register" variables. * These are cached values from the frame and code object. */ _Py_CODEUNIT *next_instr; PyObject **stack_pointer; -/* Sets the above local variables from the frame */ -#define SET_LOCALS_FROM_FRAME() \ - /* Jump back to the last instruction executed... */ \ - next_instr = frame->prev_instr + 1; \ - stack_pointer = _PyFrame_GetStackPointer(frame); start_frame: if (_Py_EnterRecursivePy(tstate)) { goto exit_unwind; } + next_instr = frame->instr_ptr; resume_frame: - SET_LOCALS_FROM_FRAME(); + stack_pointer = _PyFrame_GetStackPointer(frame); #ifdef LLTRACE - { - if (frame != &entry_frame && GLOBALS()) { - int r = PyDict_Contains(GLOBALS(), &_Py_ID(__lltrace__)); - if (r < 0) { - goto exit_unwind; - } - lltrace = r; - } - if (lltrace) { - lltrace_resume_frame(frame); - } + lltrace = maybe_lltrace_resume_frame(frame, &entry_frame, GLOBALS()); + if (lltrace < 0) { + goto exit_unwind; } #endif @@ -756,7 +784,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int #include "generated_cases.c.h" /* INSTRUMENTED_LINE has to be here, rather than in bytecodes.c, - * because it needs to capture frame->prev_instr before it is updated, + * because it needs to capture frame->instr_ptr before it is updated, * as happens in the standard instruction prologue. */ #if USE_COMPUTED_GOTOS @@ -765,8 +793,8 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int case INSTRUMENTED_LINE: #endif { - _Py_CODEUNIT *prev = frame->prev_instr; - _Py_CODEUNIT *here = frame->prev_instr = next_instr; + _Py_CODEUNIT *prev = frame->instr_ptr; + _Py_CODEUNIT *here = frame->instr_ptr = next_instr; _PyFrame_SetStackPointer(frame, stack_pointer); int original_opcode = _Py_call_instrumentation_line( tstate, frame, here, prev); @@ -775,7 +803,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int next_instr = here+1; goto error; } - next_instr = frame->prev_instr; + next_instr = frame->instr_ptr; if (next_instr != here) { DISPATCH(); } @@ -793,7 +821,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int #if USE_COMPUTED_GOTOS _unknown_opcode: #else - EXTRA_CASES // From pycore_opcode.h, a 'case' for each unused opcode + EXTRA_CASES // From pycore_opcode_metadata.h, a 'case' for each unused opcode #endif /* Tell C compilers not to hold the opcode variable in the loop. next_instr points the current instruction without TARGET(). */ @@ -829,7 +857,6 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int pop_1_error: STACK_SHRINK(1); error: - kwnames = NULL; /* Double-check exception status. */ #ifdef NDEBUG if (!_PyErr_Occurred(tstate)) { @@ -851,7 +878,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int monitor_raise(tstate, frame, next_instr-1); exception_unwind: { - /* We can't use frame->f_lasti here, as RERAISE may have set it */ + /* We can't use frame->instr_ptr here, as RERAISE may have set it */ int offset = INSTR_OFFSET()-1; int level, handler, lasti; if (get_exception_handler(_PyFrame_GetCode(frame), offset, &level, &handler, &lasti) == 0) { @@ -891,11 +918,17 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int Python main loop. */ PyObject *exc = _PyErr_GetRaisedException(tstate); PUSH(exc); - JUMPTO(handler); + next_instr = _PyCode_CODE(_PyFrame_GetCode(frame)) + handler; + if (monitor_handled(tstate, frame, next_instr, exc) < 0) { goto exception_unwind; } /* Resume normal execution */ +#ifdef LLTRACE + if (lltrace >= 5) { + lltrace_resume_frame(frame); + } +#endif DISPATCH(); } } @@ -906,26 +939,147 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int assert(frame != &entry_frame); // GH-99729: We need to unlink the frame *before* clearing it: _PyInterpreterFrame *dying = frame; - frame = cframe.current_frame = dying->previous; - _PyEvalFrameClearAndPop(tstate, dying); + frame = tstate->current_frame = dying->previous; + _PyEval_FrameClearAndPop(tstate, dying); frame->return_offset = 0; if (frame == &entry_frame) { - /* Restore previous cframe and exit */ - tstate->cframe = cframe.previous; - assert(tstate->cframe->current_frame == frame->previous); + /* Restore previous frame and exit */ + tstate->current_frame = frame->previous; tstate->c_recursion_remaining += PY_EVAL_C_STACK_UNITS; return NULL; } resume_with_error: - SET_LOCALS_FROM_FRAME(); + next_instr = frame->instr_ptr; + stack_pointer = _PyFrame_GetStackPointer(frame); goto error; + + +// The Tier 2 interpreter is also here! +enter_tier_two: + +#undef LOAD_IP +#define LOAD_IP(UNUSED) (void)0 + +#undef GOTO_ERROR +#define GOTO_ERROR(LABEL) goto LABEL ## _tier_two + +#undef DEOPT_IF +#define DEOPT_IF(COND, INSTNAME) \ + if ((COND)) { \ + goto deoptimize;\ + } + +#ifdef Py_STATS +// Disable these macros that apply to Tier 1 stats when we are in Tier 2 +#undef STAT_INC +#define STAT_INC(opname, name) ((void)0) +#undef STAT_DEC +#define STAT_DEC(opname, name) ((void)0) +#undef CALL_STAT_INC +#define CALL_STAT_INC(name) ((void)0) +#endif + +#undef ENABLE_SPECIALIZATION +#define ENABLE_SPECIALIZATION 0 + +#ifdef Py_DEBUG + #define DPRINTF(level, ...) \ + if (lltrace >= (level)) { printf(__VA_ARGS__); } +#else + #define DPRINTF(level, ...) +#endif + + OPT_STAT_INC(traces_executed); + _PyUOpInstruction *next_uop = current_executor->trace; + uint16_t uopcode; +#ifdef Py_STATS + uint64_t trace_uop_execution_counter = 0; +#endif + + for (;;) { + uopcode = next_uop->opcode; + DPRINTF(3, + "%4d: uop %s, oparg %d, operand %" PRIu64 ", target %d, stack_level %d\n", + (int)(next_uop - current_executor->trace), + _PyUOpName(uopcode), + next_uop->oparg, + next_uop->operand, + next_uop->target, + (int)(stack_pointer - _PyFrame_Stackbase(frame))); + next_uop++; + OPT_STAT_INC(uops_executed); + UOP_STAT_INC(uopcode, execution_count); +#ifdef Py_STATS + trace_uop_execution_counter++; +#endif + + switch (uopcode) { + +#include "executor_cases.c.h" + + default: +#ifdef Py_DEBUG + { + fprintf(stderr, "Unknown uop %d, oparg %d, operand %" PRIu64 " @ %d\n", + opcode, next_uop[-1].oparg, next_uop[-1].operand, + (int)(next_uop - current_executor->trace - 1)); + Py_FatalError("Unknown uop"); + } +#else + Py_UNREACHABLE(); +#endif + + } + } + +// Jump here from ERROR_IF(..., unbound_local_error) +unbound_local_error_tier_two: + _PyEval_FormatExcCheckArg(tstate, PyExc_UnboundLocalError, + UNBOUNDLOCAL_ERROR_MSG, + PyTuple_GetItem(_PyFrame_GetCode(frame)->co_localsplusnames, oparg) + ); + goto error_tier_two; + +// JUMP to any of these from ERROR_IF(..., error) +pop_4_error_tier_two: + STACK_SHRINK(1); +pop_3_error_tier_two: + STACK_SHRINK(1); +pop_2_error_tier_two: + STACK_SHRINK(1); +pop_1_error_tier_two: + STACK_SHRINK(1); +error_tier_two: + DPRINTF(2, "Error: [UOp %d (%s), oparg %d, operand %" PRIu64 ", target %d @ %d -> %s]\n", + uopcode, _PyUOpName(uopcode), next_uop[-1].oparg, next_uop[-1].operand, next_uop[-1].target, + (int)(next_uop - current_executor->trace - 1), + _PyOpcode_OpName[frame->instr_ptr->op.code]); + OPT_HIST(trace_uop_execution_counter, trace_run_length_hist); + frame->return_offset = 0; // Don't leave this random + _PyFrame_SetStackPointer(frame, stack_pointer); + Py_DECREF(current_executor); + goto resume_with_error; + +// Jump here from DEOPT_IF() +deoptimize: + next_instr = next_uop[-1].target + _PyCode_CODE(_PyFrame_GetCode(frame)); + DPRINTF(2, "DEOPT: [UOp %d (%s), oparg %d, operand %" PRIu64 ", target %d @ %d -> %s]\n", + uopcode, _PyUOpName(uopcode), next_uop[-1].oparg, next_uop[-1].operand, next_uop[-1].target, + (int)(next_uop - current_executor->trace - 1), + _PyOpcode_OpName[frame->instr_ptr->op.code]); + OPT_HIST(trace_uop_execution_counter, trace_run_length_hist); + UOP_STAT_INC(uopcode, miss); + Py_DECREF(current_executor); + DISPATCH(); + } #if defined(__GNUC__) # pragma GCC diagnostic pop #elif defined(_MSC_VER) /* MS_WINDOWS */ # pragma warning(pop) +# pragma optimize("", on) #endif static void @@ -1333,9 +1487,33 @@ initialize_locals(PyThreadState *tstate, PyFunctionObject *func, goto kw_fail; } - _PyErr_Format(tstate, PyExc_TypeError, - "%U() got an unexpected keyword argument '%S'", - func->func_qualname, keyword); + PyObject* suggestion_keyword = NULL; + if (total_args > co->co_posonlyargcount) { + PyObject* possible_keywords = PyList_New(total_args - co->co_posonlyargcount); + + if (!possible_keywords) { + PyErr_Clear(); + } else { + for (Py_ssize_t k = co->co_posonlyargcount; k < total_args; k++) { + PyList_SET_ITEM(possible_keywords, k - co->co_posonlyargcount, co_varnames[k]); + } + + suggestion_keyword = _Py_CalculateSuggestions(possible_keywords, keyword); + Py_DECREF(possible_keywords); + } + } + + if (suggestion_keyword) { + _PyErr_Format(tstate, PyExc_TypeError, + "%U() got an unexpected keyword argument '%S'. Did you mean '%S'?", + func->func_qualname, keyword, suggestion_keyword); + Py_DECREF(suggestion_keyword); + } else { + _PyErr_Format(tstate, PyExc_TypeError, + "%U() got an unexpected keyword argument '%S'", + func->func_qualname, keyword); + } + goto kw_fail; } @@ -1408,14 +1586,14 @@ initialize_locals(PyThreadState *tstate, PyFunctionObject *func, continue; PyObject *varname = PyTuple_GET_ITEM(co->co_localsplusnames, i); if (func->func_kwdefaults != NULL) { - PyObject *def = PyDict_GetItemWithError(func->func_kwdefaults, varname); + PyObject *def; + if (PyDict_GetItemRef(func->func_kwdefaults, varname, &def) < 0) { + goto fail_post_args; + } if (def) { - localsplus[i] = Py_NewRef(def); + localsplus[i] = def; continue; } - else if (_PyErr_Occurred(tstate)) { - goto fail_post_args; - } } missing++; } @@ -1477,8 +1655,8 @@ clear_gen_frame(PyThreadState *tstate, _PyInterpreterFrame * frame) frame->previous = NULL; } -static void -_PyEvalFrameClearAndPop(PyThreadState *tstate, _PyInterpreterFrame * frame) +void +_PyEval_FrameClearAndPop(PyThreadState *tstate, _PyInterpreterFrame * frame) { if (frame->owner == FRAME_OWNED_BY_THREAD) { clear_thread_frame(tstate, frame); @@ -1730,6 +1908,13 @@ do_raise(PyThreadState *tstate, PyObject *exc, PyObject *cause) fixed_cause = _PyObject_CallNoArgs(cause); if (fixed_cause == NULL) goto raise_error; + if (!PyExceptionInstance_Check(fixed_cause)) { + _PyErr_Format(tstate, PyExc_TypeError, + "calling %R should have returned an instance of " + "BaseException, not %R", + cause, Py_TYPE(fixed_cause)); + goto raise_error; + } Py_DECREF(cause); } else if (PyExceptionInstance_Check(cause)) { @@ -1926,6 +2111,9 @@ do_monitor_exc(PyThreadState *tstate, _PyInterpreterFrame *frame, _Py_CODEUNIT *instr, int event) { assert(event < _PY_MONITORING_UNGROUPED_EVENTS); + if (_PyFrame_GetCode(frame)->co_flags & CO_NO_MONITORING_EVENTS) { + return 0; + } PyObject *exc = PyErr_GetRaisedException(); assert(exc != NULL); int err = _Py_call_instrumentation_arg(tstate, event, frame, instr, exc); @@ -1939,28 +2127,30 @@ do_monitor_exc(PyThreadState *tstate, _PyInterpreterFrame *frame, return err; } -static inline int -no_tools_for_event(PyThreadState *tstate, _PyInterpreterFrame *frame, int event) +static inline bool +no_tools_for_global_event(PyThreadState *tstate, int event) { + return tstate->interp->monitors.tools[event] == 0; +} + +static inline bool +no_tools_for_local_event(PyThreadState *tstate, _PyInterpreterFrame *frame, int event) +{ + assert(event < _PY_MONITORING_LOCAL_EVENTS); _PyCoMonitoringData *data = _PyFrame_GetCode(frame)->_co_monitoring; if (data) { - if (data->active_monitors.tools[event] == 0) { - return 1; - } + return data->active_monitors.tools[event] == 0; } else { - if (tstate->interp->monitors.tools[event] == 0) { - return 1; - } + return no_tools_for_global_event(tstate, event); } - return 0; } static void monitor_raise(PyThreadState *tstate, _PyInterpreterFrame *frame, _Py_CODEUNIT *instr) { - if (no_tools_for_event(tstate, frame, PY_MONITORING_EVENT_RAISE)) { + if (no_tools_for_global_event(tstate, PY_MONITORING_EVENT_RAISE)) { return; } do_monitor_exc(tstate, frame, instr, PY_MONITORING_EVENT_RAISE); @@ -1970,7 +2160,7 @@ static void monitor_reraise(PyThreadState *tstate, _PyInterpreterFrame *frame, _Py_CODEUNIT *instr) { - if (no_tools_for_event(tstate, frame, PY_MONITORING_EVENT_RERAISE)) { + if (no_tools_for_global_event(tstate, PY_MONITORING_EVENT_RERAISE)) { return; } do_monitor_exc(tstate, frame, instr, PY_MONITORING_EVENT_RERAISE); @@ -1980,7 +2170,7 @@ static int monitor_stop_iteration(PyThreadState *tstate, _PyInterpreterFrame *frame, _Py_CODEUNIT *instr) { - if (no_tools_for_event(tstate, frame, PY_MONITORING_EVENT_STOP_ITERATION)) { + if (no_tools_for_local_event(tstate, frame, PY_MONITORING_EVENT_STOP_ITERATION)) { return 0; } return do_monitor_exc(tstate, frame, instr, PY_MONITORING_EVENT_STOP_ITERATION); @@ -1991,7 +2181,7 @@ monitor_unwind(PyThreadState *tstate, _PyInterpreterFrame *frame, _Py_CODEUNIT *instr) { - if (no_tools_for_event(tstate, frame, PY_MONITORING_EVENT_PY_UNWIND)) { + if (no_tools_for_global_event(tstate, PY_MONITORING_EVENT_PY_UNWIND)) { return; } do_monitor_exc(tstate, frame, instr, PY_MONITORING_EVENT_PY_UNWIND); @@ -2003,7 +2193,7 @@ monitor_handled(PyThreadState *tstate, _PyInterpreterFrame *frame, _Py_CODEUNIT *instr, PyObject *exc) { - if (no_tools_for_event(tstate, frame, PY_MONITORING_EVENT_EXCEPTION_HANDLED)) { + if (no_tools_for_global_event(tstate, PY_MONITORING_EVENT_EXCEPTION_HANDLED)) { return 0; } return _Py_call_instrumentation_arg(tstate, PY_MONITORING_EVENT_EXCEPTION_HANDLED, frame, instr, exc); @@ -2014,10 +2204,10 @@ monitor_throw(PyThreadState *tstate, _PyInterpreterFrame *frame, _Py_CODEUNIT *instr) { - if (no_tools_for_event(tstate, frame, PY_MONITORING_EVENT_PY_THROW)) { + if (no_tools_for_global_event(tstate, PY_MONITORING_EVENT_PY_THROW)) { return; } - _Py_call_instrumentation_exc0(tstate, PY_MONITORING_EVENT_PY_THROW, frame, instr); + do_monitor_exc(tstate, frame, instr, PY_MONITORING_EVENT_PY_THROW); } void @@ -2057,7 +2247,7 @@ PyEval_SetProfile(Py_tracefunc func, PyObject *arg) PyThreadState *tstate = _PyThreadState_GET(); if (_PyEval_SetProfile(tstate, func, arg) < 0) { /* Log _PySys_Audit() error */ - _PyErr_WriteUnraisableMsg("in PyEval_SetProfile", NULL); + PyErr_FormatUnraisable("Exception ignored in PyEval_SetProfile"); } } @@ -2074,7 +2264,7 @@ PyEval_SetProfileAllThreads(Py_tracefunc func, PyObject *arg) while (ts) { if (_PyEval_SetProfile(ts, func, arg) < 0) { - _PyErr_WriteUnraisableMsg("in PyEval_SetProfileAllThreads", NULL); + PyErr_FormatUnraisable("Exception ignored in PyEval_SetProfileAllThreads"); } HEAD_LOCK(runtime); ts = PyThreadState_Next(ts); @@ -2088,7 +2278,7 @@ PyEval_SetTrace(Py_tracefunc func, PyObject *arg) PyThreadState *tstate = _PyThreadState_GET(); if (_PyEval_SetTrace(tstate, func, arg) < 0) { /* Log _PySys_Audit() error */ - _PyErr_WriteUnraisableMsg("in PyEval_SetTrace", NULL); + PyErr_FormatUnraisable("Exception ignored in PyEval_SetTrace"); } } @@ -2105,7 +2295,7 @@ PyEval_SetTraceAllThreads(Py_tracefunc func, PyObject *arg) while (ts) { if (_PyEval_SetTrace(ts, func, arg) < 0) { - _PyErr_WriteUnraisableMsg("in PyEval_SetTraceAllThreads", NULL); + PyErr_FormatUnraisable("Exception ignored in PyEval_SetTraceAllThreads"); } HEAD_LOCK(runtime); ts = PyThreadState_Next(ts); @@ -2215,13 +2405,9 @@ PyEval_GetBuiltins(void) PyObject * _PyEval_GetBuiltin(PyObject *name) { - PyThreadState *tstate = _PyThreadState_GET(); - PyObject *attr = PyDict_GetItemWithError(PyEval_GetBuiltins(), name); - if (attr) { - Py_INCREF(attr); - } - else if (!_PyErr_Occurred(tstate)) { - _PyErr_SetObject(tstate, PyExc_AttributeError, name); + PyObject *attr; + if (PyMapping_GetOptionalItem(PyEval_GetBuiltins(), name, &attr) == 0) { + PyErr_SetObject(PyExc_AttributeError, name); } return attr; } @@ -2279,7 +2465,7 @@ int PyEval_MergeCompilerFlags(PyCompilerFlags *cf) { PyThreadState *tstate = _PyThreadState_GET(); - _PyInterpreterFrame *current_frame = tstate->cframe->current_frame; + _PyInterpreterFrame *current_frame = tstate->current_frame; int result = cf->cf_flags != 0; if (current_frame != NULL) { @@ -2372,12 +2558,12 @@ static PyObject * import_name(PyThreadState *tstate, _PyInterpreterFrame *frame, PyObject *name, PyObject *fromlist, PyObject *level) { - PyObject *import_func = _PyDict_GetItemWithError(frame->f_builtins, - &_Py_ID(__import__)); + PyObject *import_func; + if (PyMapping_GetOptionalItem(frame->f_builtins, &_Py_ID(__import__), &import_func) < 0) { + return NULL; + } if (import_func == NULL) { - if (!_PyErr_Occurred(tstate)) { - _PyErr_SetString(tstate, PyExc_ImportError, "__import__ not found"); - } + _PyErr_SetString(tstate, PyExc_ImportError, "__import__ not found"); return NULL; } @@ -2388,7 +2574,8 @@ import_name(PyThreadState *tstate, _PyInterpreterFrame *frame, /* Fast path for not overloaded __import__. */ if (_PyImport_IsDefaultImportFunc(tstate->interp, import_func)) { - int ilevel = _PyLong_AsInt(level); + Py_DECREF(import_func); + int ilevel = PyLong_AsInt(level); if (ilevel == -1 && _PyErr_Occurred(tstate)) { return NULL; } @@ -2401,7 +2588,6 @@ import_name(PyThreadState *tstate, _PyInterpreterFrame *frame, } PyObject* args[5] = {name, frame->f_globals, locals, fromlist, level}; - Py_INCREF(import_func); PyObject *res = PyObject_Vectorcall(import_func, args, 5, NULL); Py_DECREF(import_func); return res; @@ -2419,11 +2605,10 @@ import_from(PyThreadState *tstate, PyObject *v, PyObject *name) /* Issue #17636: in case this failed because of a circular relative import, try to fallback on reading the module directly from sys.modules. */ - pkgname = PyObject_GetAttr(v, &_Py_ID(__name__)); - if (pkgname == NULL) { - goto error; + if (PyObject_GetOptionalAttr(v, &_Py_ID(__name__), &pkgname) < 0) { + return NULL; } - if (!PyUnicode_Check(pkgname)) { + if (pkgname == NULL || !PyUnicode_Check(pkgname)) { Py_CLEAR(pkgname); goto error; } @@ -2440,42 +2625,59 @@ import_from(PyThreadState *tstate, PyObject *v, PyObject *name) Py_DECREF(pkgname); return x; error: - pkgpath = PyModule_GetFilenameObject(v); if (pkgname == NULL) { pkgname_or_unknown = PyUnicode_FromString(""); if (pkgname_or_unknown == NULL) { - Py_XDECREF(pkgpath); return NULL; } } else { pkgname_or_unknown = pkgname; } + pkgpath = NULL; + if (PyModule_Check(v)) { + pkgpath = PyModule_GetFilenameObject(v); + if (pkgpath == NULL) { + if (!PyErr_ExceptionMatches(PyExc_SystemError)) { + Py_DECREF(pkgname_or_unknown); + return NULL; + } + // module filename missing + _PyErr_Clear(tstate); + } + } if (pkgpath == NULL || !PyUnicode_Check(pkgpath)) { - _PyErr_Clear(tstate); + Py_CLEAR(pkgpath); errmsg = PyUnicode_FromFormat( "cannot import name %R from %R (unknown location)", name, pkgname_or_unknown ); - /* NULL checks for errmsg and pkgname done by PyErr_SetImportError. */ - _PyErr_SetImportErrorWithNameFrom(errmsg, pkgname, NULL, name); } else { - PyObject *spec = PyObject_GetAttr(v, &_Py_ID(__spec__)); + PyObject *spec; + int rc = PyObject_GetOptionalAttr(v, &_Py_ID(__spec__), &spec); + if (rc > 0) { + rc = _PyModuleSpec_IsInitializing(spec); + Py_DECREF(spec); + } + if (rc < 0) { + Py_DECREF(pkgname_or_unknown); + Py_DECREF(pkgpath); + return NULL; + } const char *fmt = - _PyModuleSpec_IsInitializing(spec) ? + rc ? "cannot import name %R from partially initialized module %R " "(most likely due to a circular import) (%S)" : "cannot import name %R from %R (%S)"; - Py_XDECREF(spec); errmsg = PyUnicode_FromFormat(fmt, name, pkgname_or_unknown, pkgpath); - /* NULL checks for errmsg and pkgname done by PyErr_SetImportError. */ - _PyErr_SetImportErrorWithNameFrom(errmsg, pkgname, pkgpath, name); } + /* NULL checks for errmsg and pkgname done by PyErr_SetImportError. */ + _PyErr_SetImportErrorWithNameFrom(errmsg, pkgname, pkgpath, name); Py_XDECREF(errmsg); - Py_XDECREF(pkgname_or_unknown); + Py_DECREF(pkgname_or_unknown); Py_XDECREF(pkgpath); return NULL; } diff --git a/Python/ceval_gil.c b/Python/ceval_gil.c index 7c9ad07cc7207b..d70abbc27606b4 100644 --- a/Python/ceval_gil.c +++ b/Python/ceval_gil.c @@ -1,12 +1,12 @@ #include "Python.h" -#include "pycore_atomic.h" // _Py_atomic_int #include "pycore_ceval.h" // _PyEval_SignalReceived() -#include "pycore_pyerrors.h" // _PyErr_GetRaisedException() -#include "pycore_pylifecycle.h" // _PyErr_Print() #include "pycore_initconfig.h" // _PyStatus_OK() #include "pycore_interp.h" // _Py_RunGC() +#include "pycore_pyerrors.h" // _PyErr_GetRaisedException() +#include "pycore_pylifecycle.h" // _PyErr_Print() #include "pycore_pymem.h" // _PyMem_IsPtrFreed() +#include "pycore_pystats.h" // _Py_PrintSpecializationStats() /* Notes about the implementation: @@ -56,123 +56,62 @@ #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. */ +/* bpo-40010: eval_breaker should be recomputed if there + is a pending signal: signal received by another thread which cannot + handle signals. + Similarly, we set CALLS_TO_DO and ASYNC_EXCEPTION to match the thread. +*/ static inline void -COMPUTE_EVAL_BREAKER(PyInterpreterState *interp, - struct _ceval_runtime_state *ceval, - struct _ceval_state *ceval2) +update_eval_breaker_from_thread(PyInterpreterState *interp, PyThreadState *tstate) { - _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_IsMainThread() && _Py_IsMainInterpreter(interp) - &&_Py_atomic_load_relaxed_int32(&ceval->pending_mainthread.calls_to_do)) - | ceval2->pending.async_exc - | _Py_atomic_load_relaxed_int32(&ceval2->gc_scheduled)); -} + if (tstate == NULL) { + return; + } + if (_Py_IsMainThread()) { + int32_t calls_to_do = _Py_atomic_load_int32_relaxed( + &_PyRuntime.ceval.pending_mainthread.calls_to_do); + if (calls_to_do) { + _Py_set_eval_breaker_bit(interp, _PY_CALLS_TO_DO_BIT, 1); + } + if (_Py_ThreadCanHandleSignals(interp)) { + if (_Py_atomic_load_int(&_PyRuntime.signals.is_tripped)) { + _Py_set_eval_breaker_bit(interp, _PY_SIGNALS_PENDING_BIT, 1); + } + } + } + if (tstate->async_exc != NULL) { + _Py_set_eval_breaker_bit(interp, _PY_ASYNC_EXCEPTION_BIT, 1); + } +} 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); + _Py_set_eval_breaker_bit(interp, _PY_GIL_DROP_REQUEST_BIT, 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); + _Py_set_eval_breaker_bit(interp, _PY_GIL_DROP_REQUEST_BIT, 0); } static inline void -SIGNAL_PENDING_CALLS(struct _pending_calls *pending, PyInterpreterState *interp) +SIGNAL_PENDING_CALLS(PyInterpreterState *interp) { - struct _ceval_runtime_state *ceval = &interp->runtime->ceval; - struct _ceval_state *ceval2 = &interp->ceval; - _Py_atomic_store_relaxed(&pending->calls_to_do, 1); - COMPUTE_EVAL_BREAKER(interp, ceval, ceval2); + _Py_set_eval_breaker_bit(interp, _PY_CALLS_TO_DO_BIT, 1); } static inline void UNSIGNAL_PENDING_CALLS(PyInterpreterState *interp) { - struct _ceval_runtime_state *ceval = &interp->runtime->ceval; - struct _ceval_state *ceval2 = &interp->ceval; - if (_Py_IsMainThread() && _Py_IsMainInterpreter(interp)) { - _Py_atomic_store_relaxed(&ceval->pending_mainthread.calls_to_do, 0); - } - _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); + _Py_set_eval_breaker_bit(interp, _PY_CALLS_TO_DO_BIT, 0); } - -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). */ @@ -180,9 +119,6 @@ is_tstate_valid(PyThreadState *tstate) #include #include -#include "pycore_atomic.h" - - #include "condvar.h" #define MUTEX_INIT(mut) \ @@ -226,8 +162,7 @@ is_tstate_valid(PyThreadState *tstate) static void _gil_initialize(struct _gil_runtime_state *gil) { - _Py_atomic_int uninitialized = {-1}; - gil->locked = uninitialized; + gil->locked = -1; gil->interval = DEFAULT_INTERVAL; } @@ -236,7 +171,7 @@ static int gil_created(struct _gil_runtime_state *gil) if (gil == NULL) { return 0; } - return (_Py_atomic_load_explicit(&gil->locked, _Py_memory_order_acquire) >= 0); + return (_Py_atomic_load_int_acquire(&gil->locked) >= 0); } static void create_gil(struct _gil_runtime_state *gil) @@ -249,9 +184,9 @@ static void create_gil(struct _gil_runtime_state *gil) #ifdef FORCE_SWITCHING COND_INIT(gil->switch_cond); #endif - _Py_atomic_store_relaxed(&gil->last_holder, 0); + _Py_atomic_store_ptr_relaxed(&gil->last_holder, 0); _Py_ANNOTATE_RWLOCK_CREATE(&gil->locked); - _Py_atomic_store_explicit(&gil->locked, 0, _Py_memory_order_release); + _Py_atomic_store_int_release(&gil->locked, 0); } static void destroy_gil(struct _gil_runtime_state *gil) @@ -265,8 +200,7 @@ static void destroy_gil(struct _gil_runtime_state *gil) COND_FINI(gil->switch_cond); MUTEX_FINI(gil->switch_mutex); #endif - _Py_atomic_store_explicit(&gil->locked, -1, - _Py_memory_order_release); + _Py_atomic_store_int_release(&gil->locked, -1); _Py_ANNOTATE_RWLOCK_DESTROY(&gil->locked); } @@ -280,8 +214,9 @@ static void recreate_gil(struct _gil_runtime_state *gil) #endif static void -drop_gil(struct _ceval_state *ceval, PyThreadState *tstate) +drop_gil(PyInterpreterState *interp, PyThreadState *tstate) { + struct _ceval_state *ceval = &interp->ceval; /* If tstate is NULL, the caller is indicating that we're releasing the GIL for the last time in this thread. This is particularly relevant when the current thread state is finalizing or its @@ -292,7 +227,7 @@ drop_gil(struct _ceval_state *ceval, PyThreadState *tstate) // XXX assert(tstate == NULL || !tstate->_status.cleared); struct _gil_runtime_state *gil = ceval->gil; - if (!_Py_atomic_load_relaxed(&gil->locked)) { + if (!_Py_atomic_load_ptr_relaxed(&gil->locked)) { Py_FatalError("drop_gil: GIL is not locked"); } @@ -301,12 +236,12 @@ drop_gil(struct _ceval_state *ceval, PyThreadState *tstate) /* 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); + _Py_atomic_store_ptr_relaxed(&gil->last_holder, tstate); } MUTEX_LOCK(gil->mutex); _Py_ANNOTATE_RWLOCK_RELEASED(&gil->locked, /*is_write=*/1); - _Py_atomic_store_relaxed(&gil->locked, 0); + _Py_atomic_store_int_relaxed(&gil->locked, 0); COND_SIGNAL(gil->cond); MUTEX_UNLOCK(gil->mutex); @@ -319,12 +254,12 @@ drop_gil(struct _ceval_state *ceval, PyThreadState *tstate) the GIL, and that's the only time we might delete the interpreter, so checking tstate first prevents the crash. See https://github.com/python/cpython/issues/104341. */ - if (tstate != NULL && _Py_atomic_load_relaxed(&ceval->gil_drop_request)) { + if (tstate != NULL && _Py_eval_breaker_bit_is_set(interp, _PY_GIL_DROP_REQUEST_BIT)) { MUTEX_LOCK(gil->switch_mutex); /* Not switched yet => wait */ - if (((PyThreadState*)_Py_atomic_load_relaxed(&gil->last_holder)) == tstate) + if (((PyThreadState*)_Py_atomic_load_ptr_relaxed(&gil->last_holder)) == tstate) { - assert(is_tstate_valid(tstate)); + assert(_PyThreadState_CheckConsistency(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 @@ -338,28 +273,6 @@ drop_gil(struct _ceval_state *ceval, PyThreadState *tstate) } -/* 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); - if (finalizing == NULL) { - finalizing = _PyInterpreterState_GetFinalizing(tstate->interp); - } - return (finalizing != NULL && finalizing != tstate); -} - - /* Take the GIL. The function saves errno at entry and restores its value at exit. @@ -375,7 +288,7 @@ take_gil(PyThreadState *tstate) // XXX It may be more correct to check tstate->_status.finalizing. // XXX assert(!tstate->_status.cleared); - if (tstate_must_exit(tstate)) { + if (_PyThreadState_MustExit(tstate)) { /* bpo-39877: If Py_Finalize() has been called and tstate is not the thread which called Py_Finalize(), exit immediately the thread. @@ -385,22 +298,17 @@ take_gil(PyThreadState *tstate) PyThread_exit_thread(); } - assert(is_tstate_valid(tstate)); + assert(_PyThreadState_CheckConsistency(tstate)); PyInterpreterState *interp = tstate->interp; - struct _ceval_state *ceval = &interp->ceval; - struct _gil_runtime_state *gil = ceval->gil; + struct _gil_runtime_state *gil = interp->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; - } - int drop_requested = 0; - while (_Py_atomic_load_relaxed(&gil->locked)) { + while (_Py_atomic_load_int_relaxed(&gil->locked)) { unsigned long saved_switchnum = gil->switch_number; unsigned long interval = (gil->interval >= 1 ? gil->interval : 1); @@ -410,10 +318,10 @@ take_gil(PyThreadState *tstate) /* 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) && + _Py_atomic_load_int_relaxed(&gil->locked) && gil->switch_number == saved_switchnum) { - if (tstate_must_exit(tstate)) { + if (_PyThreadState_MustExit(tstate)) { MUTEX_UNLOCK(gil->mutex); // gh-96387: If the loop requested a drop request in a previous // iteration, reset the request. Otherwise, drop_gil() can @@ -426,25 +334,24 @@ take_gil(PyThreadState *tstate) } PyThread_exit_thread(); } - assert(is_tstate_valid(tstate)); + assert(_PyThreadState_CheckConsistency(tstate)); SET_GIL_DROP_REQUEST(interp); drop_requested = 1; } } -_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_atomic_store_int_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); + if (tstate != (PyThreadState*)_Py_atomic_load_ptr_relaxed(&gil->last_holder)) { + _Py_atomic_store_ptr_relaxed(&gil->last_holder, tstate); ++gil->switch_number; } @@ -453,7 +360,7 @@ take_gil(PyThreadState *tstate) MUTEX_UNLOCK(gil->switch_mutex); #endif - if (tstate_must_exit(tstate)) { + if (_PyThreadState_MustExit(tstate)) { /* bpo-36475: If Py_Finalize() has been called and tstate is not the thread which called Py_Finalize(), exit immediately the thread. @@ -462,27 +369,13 @@ take_gil(PyThreadState *tstate) in take_gil() while the main thread called wait_for_thread_shutdown() from Py_Finalize(). */ MUTEX_UNLOCK(gil->mutex); - drop_gil(ceval, tstate); + drop_gil(interp, tstate); PyThread_exit_thread(); } - assert(is_tstate_valid(tstate)); - - if (_Py_atomic_load_relaxed(&ceval->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. + assert(_PyThreadState_CheckConsistency(tstate)); - Note: RESET_GIL_DROP_REQUEST() calls COMPUTE_EVAL_BREAKER(). */ - COMPUTE_EVAL_BREAKER(interp, &_PyRuntime.ceval, ceval); - } - - /* Don't access tstate if the thread must exit */ - if (tstate->async_exc != NULL) { - _PyEval_SignalAsyncExc(tstate->interp); - } + RESET_GIL_DROP_REQUEST(interp); + update_eval_breaker_from_thread(interp, tstate); MUTEX_UNLOCK(gil->mutex); @@ -530,10 +423,10 @@ PyEval_ThreadsInitialized(void) static inline int current_thread_holds_gil(struct _gil_runtime_state *gil, PyThreadState *tstate) { - if (((PyThreadState*)_Py_atomic_load_relaxed(&gil->last_holder)) != tstate) { + if (((PyThreadState*)_Py_atomic_load_ptr_relaxed(&gil->last_holder)) != tstate) { return 0; } - return _Py_atomic_load_relaxed(&gil->locked); + return _Py_atomic_load_int_relaxed(&gil->locked); } static void @@ -554,29 +447,25 @@ init_own_gil(PyInterpreterState *interp, struct _gil_runtime_state *gil) interp->ceval.own_gil = 1; } -PyStatus +void _PyEval_InitGIL(PyThreadState *tstate, int own_gil) { assert(tstate->interp->ceval.gil == NULL); - int locked; if (!own_gil) { /* The interpreter will share the main interpreter's instead. */ PyInterpreterState *main_interp = _PyInterpreterState_Main(); assert(tstate->interp != main_interp); struct _gil_runtime_state *gil = main_interp->ceval.gil; init_shared_gil(tstate->interp, gil); - locked = current_thread_holds_gil(gil, tstate); + assert(!current_thread_holds_gil(gil, tstate)); } else { PyThread_init_thread(); init_own_gil(tstate->interp, &tstate->interp->_gil); - locked = 0; - } - if (!locked) { - take_gil(tstate); } - return _PyStatus_OK(); + // Lock the GIL and mark the current thread as attached. + _PyThreadState_Attach(tstate); } void @@ -642,8 +531,7 @@ PyEval_ReleaseLock(void) /* 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_state *ceval = &tstate->interp->ceval; - drop_gil(ceval, tstate); + drop_gil(tstate->interp, tstate); } void @@ -659,33 +547,21 @@ _PyEval_ReleaseLock(PyInterpreterState *interp, PyThreadState *tstate) /* If tstate is NULL then we do not expect the current thread to acquire the GIL ever again. */ assert(tstate == NULL || tstate->interp == interp); - struct _ceval_state *ceval = &interp->ceval; - drop_gil(ceval, tstate); + drop_gil(interp, tstate); } void PyEval_AcquireThread(PyThreadState *tstate) { _Py_EnsureTstateNotNULL(tstate); - - take_gil(tstate); - - if (_PyThreadState_SwapNoGIL(tstate) != NULL) { - Py_FatalError("non-NULL old thread state"); - } + _PyThreadState_Attach(tstate); } void PyEval_ReleaseThread(PyThreadState *tstate) { - assert(is_tstate_valid(tstate)); - - PyThreadState *new_tstate = _PyThreadState_SwapNoGIL(NULL); - if (new_tstate != tstate) { - Py_FatalError("wrong thread state"); - } - struct _ceval_state *ceval = &tstate->interp->ceval; - drop_gil(ceval, tstate); + assert(_PyThreadState_CheckConsistency(tstate)); + _PyThreadState_Detach(tstate); } #ifdef HAVE_FORK @@ -706,9 +582,7 @@ _PyEval_ReInitThreads(PyThreadState *tstate) 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"); - } + _PyMutex_at_fork_reinit(&pending->mutex); /* Destroy all threads except the current one */ _PyThreadState_DeleteExcept(tstate); @@ -722,18 +596,14 @@ _PyEval_ReInitThreads(PyThreadState *tstate) void _PyEval_SignalAsyncExc(PyInterpreterState *interp) { - SIGNAL_ASYNC_EXC(interp); + _Py_set_eval_breaker_bit(interp, _PY_ASYNC_EXCEPTION_BIT, 1); } PyThreadState * PyEval_SaveThread(void) { - PyThreadState *tstate = _PyThreadState_SwapNoGIL(NULL); - _Py_EnsureTstateNotNULL(tstate); - - struct _ceval_state *ceval = &tstate->interp->ceval; - assert(gil_created(ceval->gil)); - drop_gil(ceval, tstate); + PyThreadState *tstate = _PyThreadState_GET(); + _PyThreadState_Detach(tstate); return tstate; } @@ -741,10 +611,7 @@ void PyEval_RestoreThread(PyThreadState *tstate) { _Py_EnsureTstateNotNULL(tstate); - - take_gil(tstate); - - _PyThreadState_SwapNoGIL(tstate); + _PyThreadState_Attach(tstate); } @@ -773,28 +640,15 @@ PyEval_RestoreThread(PyThreadState *tstate) 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); + if (_Py_ThreadCanHandleSignals(interp)) { + _Py_set_eval_breaker_bit(interp, _PY_SIGNALS_PENDING_BIT, 1); + } } /* Push one item onto the queue while holding the lock. */ static int _push_pending_call(struct _pending_calls *pending, - int (*func)(void *), void *arg) + _Py_pending_call_func func, void *arg, int flags) { int i = pending->last; int j = (i + 1) % NPENDINGCALLS; @@ -803,13 +657,16 @@ _push_pending_call(struct _pending_calls *pending, } pending->calls[i].func = func; pending->calls[i].arg = arg; + pending->calls[i].flags = flags; pending->last = j; + assert(pending->calls_to_do < NPENDINGCALLS); + pending->calls_to_do++; return 0; } static int _next_pending_call(struct _pending_calls *pending, - int (**func)(void *), void **arg) + int (**func)(void *), void **arg, int *flags) { int i = pending->first; if (i == pending->last) { @@ -819,18 +676,21 @@ _next_pending_call(struct _pending_calls *pending, } *func = pending->calls[i].func; *arg = pending->calls[i].arg; + *flags = pending->calls[i].flags; return i; } /* 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 (**func)(void *), void **arg, int *flags) { - int i = _next_pending_call(pending, func, arg); + int i = _next_pending_call(pending, func, arg, flags); if (i >= 0) { pending->calls[i] = (struct _pending_call){0}; pending->first = (i + 1) % NPENDINGCALLS; + assert(pending->calls_to_do > 0); + pending->calls_to_do--; } } @@ -841,87 +701,74 @@ _pop_pending_call(struct _pending_calls *pending, int _PyEval_AddPendingCall(PyInterpreterState *interp, - int (*func)(void *), void *arg, - int mainthreadonly) + _Py_pending_call_func func, void *arg, int flags) { - assert(!mainthreadonly || _Py_IsMainInterpreter(interp)); + assert(!(flags & _Py_PENDING_MAINTHREADONLY) + || _Py_IsMainInterpreter(interp)); struct _pending_calls *pending = &interp->ceval.pending; - if (mainthreadonly) { + if (flags & _Py_PENDING_MAINTHREADONLY) { /* The main thread only exists in the main interpreter. */ assert(_Py_IsMainInterpreter(interp)); pending = &_PyRuntime.ceval.pending_mainthread; } - /* 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); + PyMutex_Lock(&pending->mutex); + int result = _push_pending_call(pending, func, arg, flags); + PyMutex_Unlock(&pending->mutex); /* signal main loop */ - SIGNAL_PENDING_CALLS(pending, interp); + SIGNAL_PENDING_CALLS(interp); return result; } int -Py_AddPendingCall(int (*func)(void *), void *arg) +Py_AddPendingCall(_Py_pending_call_func func, void *arg) { /* Legacy users of this API will continue to target the main thread (of the main interpreter). */ PyInterpreterState *interp = _PyInterpreterState_Main(); - return _PyEval_AddPendingCall(interp, func, arg, 1); + return _PyEval_AddPendingCall(interp, func, arg, _Py_PENDING_MAINTHREADONLY); } static int handle_signals(PyThreadState *tstate) { - assert(is_tstate_valid(tstate)); + assert(_PyThreadState_CheckConsistency(tstate)); + _Py_set_eval_breaker_bit(tstate->interp, _PY_SIGNALS_PENDING_BIT, 0); 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); + _Py_set_eval_breaker_bit(tstate->interp, _PY_SIGNALS_PENDING_BIT, 1); return -1; } return 0; } -static inline int -maybe_has_pending_calls(PyInterpreterState *interp) -{ - struct _pending_calls *pending = &interp->ceval.pending; - if (_Py_atomic_load_relaxed_int32(&pending->calls_to_do)) { - return 1; - } - if (!_Py_IsMainThread() || !_Py_IsMainInterpreter(interp)) { - return 0; - } - pending = &_PyRuntime.ceval.pending_mainthread; - return _Py_atomic_load_relaxed_int32(&pending->calls_to_do); -} - static int _make_pending_calls(struct _pending_calls *pending) { /* perform a bounded number of calls, in case of recursion */ for (int i=0; ilock, WAIT_LOCK); - _pop_pending_call(pending, &func, &arg); - PyThread_release_lock(pending->lock); + PyMutex_Lock(&pending->mutex); + _pop_pending_call(pending, &func, &arg, &flags); + PyMutex_Unlock(&pending->mutex); /* having released the lock, perform the callback */ if (func == NULL) { break; } - if (func(arg) != 0) { + int res = func(arg); + if ((flags & _Py_PENDING_RAWFREE) && arg != NULL) { + PyMem_RawFree(arg); + } + if (res != 0) { return -1; } } @@ -936,7 +783,7 @@ make_pending_calls(PyInterpreterState *interp) /* Only one thread (per interpreter) may run the pending calls at once. In the same way, we don't do recursive pending calls. */ - PyThread_acquire_lock(pending->lock, WAIT_LOCK); + PyMutex_Lock(&pending->mutex); if (pending->busy) { /* A pending call was added after another thread was already handling the pending calls (and had already "unsignaled"). @@ -948,11 +795,11 @@ make_pending_calls(PyInterpreterState *interp) care of any remaining pending calls. Until then, though, all the interpreter's threads will be tripping the eval breaker every time it's checked. */ - PyThread_release_lock(pending->lock); + PyMutex_Unlock(&pending->mutex); return 0; } pending->busy = 1; - PyThread_release_lock(pending->lock); + PyMutex_Unlock(&pending->mutex); /* unsignal before starting to call callbacks, so that any callback added in-between re-signals */ @@ -961,7 +808,7 @@ make_pending_calls(PyInterpreterState *interp) if (_make_pending_calls(pending) != 0) { pending->busy = 0; /* There might not be more calls to make, but we play it safe. */ - SIGNAL_PENDING_CALLS(pending, interp); + SIGNAL_PENDING_CALLS(interp); return -1; } @@ -969,7 +816,7 @@ make_pending_calls(PyInterpreterState *interp) if (_make_pending_calls(pending_main) != 0) { pending->busy = 0; /* There might not be more calls to make, but we play it safe. */ - SIGNAL_PENDING_CALLS(pending_main, interp); + SIGNAL_PENDING_CALLS(interp); return -1; } } @@ -982,7 +829,7 @@ void _Py_FinishPendingCalls(PyThreadState *tstate) { assert(PyGILState_Check()); - assert(is_tstate_valid(tstate)); + assert(_PyThreadState_CheckConsistency(tstate)); if (make_pending_calls(tstate->interp) < 0) { PyObject *exc = _PyErr_GetRaisedException(tstate); @@ -1023,7 +870,7 @@ Py_MakePendingCalls(void) assert(PyGILState_Check()); PyThreadState *tstate = _PyThreadState_GET(); - assert(is_tstate_valid(tstate)); + assert(_PyThreadState_CheckConsistency(tstate)); /* Only execute pending calls on the main thread. */ if (!_Py_IsMainThread() || !_Py_IsMainInterpreter(tstate->interp)) { @@ -1033,23 +880,9 @@ Py_MakePendingCalls(void) } void -_PyEval_InitState(PyInterpreterState *interp, PyThread_type_lock pending_lock) +_PyEval_InitState(PyInterpreterState *interp) { _gil_initialize(&interp->_gil); - - struct _pending_calls *pending = &interp->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; - } } @@ -1114,70 +947,49 @@ _PyEval_FiniState(struct _ceval_state *ceval) int _Py_HandlePending(PyThreadState *tstate) { - _PyRuntimeState * const runtime = &_PyRuntime; - struct _ceval_runtime_state *ceval = &runtime->ceval; - struct _ceval_state *interp_ceval_state = &tstate->interp->ceval; + PyInterpreterState *interp = tstate->interp; /* Pending signals */ - if (_Py_atomic_load_relaxed_int32(&ceval->signals_pending)) { + if (_Py_eval_breaker_bit_is_set(interp, _PY_SIGNALS_PENDING_BIT)) { if (handle_signals(tstate) != 0) { return -1; } } /* Pending calls */ - if (maybe_has_pending_calls(tstate->interp)) { - if (make_pending_calls(tstate->interp) != 0) { + if (_Py_eval_breaker_bit_is_set(interp, _PY_CALLS_TO_DO_BIT)) { + if (make_pending_calls(interp) != 0) { return -1; } } /* GC scheduled to run */ - if (_Py_atomic_load_relaxed_int32(&interp_ceval_state->gc_scheduled)) { - _Py_atomic_store_relaxed(&interp_ceval_state->gc_scheduled, 0); - COMPUTE_EVAL_BREAKER(tstate->interp, ceval, interp_ceval_state); + if (_Py_eval_breaker_bit_is_set(interp, _PY_GC_SCHEDULED_BIT)) { + _Py_set_eval_breaker_bit(interp, _PY_GC_SCHEDULED_BIT, 0); _Py_RunGC(tstate); } /* GIL drop request */ - if (_Py_atomic_load_relaxed_int32(&interp_ceval_state->gil_drop_request)) { + if (_Py_eval_breaker_bit_is_set(interp, _PY_GIL_DROP_REQUEST_BIT)) { /* Give another thread a chance */ - if (_PyThreadState_SwapNoGIL(NULL) != tstate) { - Py_FatalError("tstate mix-up"); - } - drop_gil(interp_ceval_state, tstate); + _PyThreadState_Detach(tstate); /* Other threads may run now */ - take_gil(tstate); - - if (_PyThreadState_SwapNoGIL(tstate) != NULL) { - Py_FatalError("orphan tstate"); - } + _PyThreadState_Attach(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; + if (_Py_eval_breaker_bit_is_set(interp, _PY_ASYNC_EXCEPTION_BIT)) { + _Py_set_eval_breaker_bit(interp, _PY_ASYNC_EXCEPTION_BIT, 0); + if (tstate->async_exc != NULL) { + PyObject *exc = tstate->async_exc; + tstate->async_exc = NULL; + _PyErr_SetNone(tstate, exc); + Py_DECREF(exc); + return -1; + } } - - - // It is possible that some of the conditions that trigger the eval breaker - // are called in a different thread than the Python thread. An example of - // this is 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, interp_ceval_state); - return 0; } diff --git a/Python/ceval_macros.h b/Python/ceval_macros.h index 8dc8b754485856..a3606b17b71c62 100644 --- a/Python/ceval_macros.h +++ b/Python/ceval_macros.h @@ -1,4 +1,4 @@ -// Macros and other things needed by ceval.c, executor.c, and bytecodes.c +// Macros and other things needed by ceval.c, and bytecodes.c /* Computed GOTOs, or the-optimization-commonly-but-improperly-known-as-"threaded code" @@ -60,29 +60,28 @@ #endif #ifdef Py_STATS -#define INSTRUCTION_START(op) \ +#define INSTRUCTION_STATS(op) \ do { \ - frame->prev_instr = next_instr++; \ OPCODE_EXE_INC(op); \ - if (_py_stats) _py_stats->opcode_stats[lastopcode].pair_count[op]++; \ + if (_Py_stats) _Py_stats->opcode_stats[lastopcode].pair_count[op]++; \ lastopcode = op; \ } while (0) #else -#define INSTRUCTION_START(op) (frame->prev_instr = next_instr++) +#define INSTRUCTION_STATS(op) ((void)0) #endif #if USE_COMPUTED_GOTOS -# define TARGET(op) TARGET_##op: INSTRUCTION_START(op); +# define TARGET(op) TARGET_##op: # define DISPATCH_GOTO() goto *opcode_targets[opcode] #else -# define TARGET(op) case op: TARGET_##op: INSTRUCTION_START(op); +# define TARGET(op) case op: TARGET_##op: # define DISPATCH_GOTO() goto dispatch_opcode #endif /* PRE_DISPATCH_GOTO() does lltrace if enabled. Normally a no-op */ #ifdef LLTRACE -#define PRE_DISPATCH_GOTO() if (lltrace) { \ - lltrace_instruction(frame, stack_pointer, next_instr); } +#define PRE_DISPATCH_GOTO() if (lltrace >= 5) { \ + lltrace_instruction(frame, stack_pointer, next_instr, opcode, oparg); } #else #define PRE_DISPATCH_GOTO() ((void)0) #endif @@ -107,18 +106,20 @@ do { \ assert(tstate->interp->eval_frame == NULL); \ _PyFrame_SetStackPointer(frame, stack_pointer); \ - frame->prev_instr = next_instr - 1; \ (NEW_FRAME)->previous = frame; \ - frame = cframe.current_frame = (NEW_FRAME); \ + frame = tstate->current_frame = (NEW_FRAME); \ CALL_STAT_INC(inlined_py_calls); \ goto start_frame; \ } while (0) +// Use this instead of 'goto error' so Tier 2 can go to a different label +#define GOTO_ERROR(LABEL) goto LABEL + #define CHECK_EVAL_BREAKER() \ _Py_CHECK_EMSCRIPTEN_SIGNALS_PERIODICALLY(); \ - if (_Py_atomic_load_relaxed_int32(&tstate->interp->ceval.eval_breaker)) { \ + if (_Py_atomic_load_uintptr_relaxed(&tstate->interp->ceval.eval_breaker) & _PY_EVAL_EVENTS_MASK) { \ if (_Py_HandlePending(tstate) != 0) { \ - goto error; \ + GOTO_ERROR(error); \ } \ } @@ -146,7 +147,6 @@ GETITEM(PyObject *v, Py_ssize_t i) { opcode = word.op.code; \ oparg = word.op.arg; \ } while (0) -#define JUMPTO(x) (next_instr = _PyCode_CODE(_PyFrame_GetCode(frame)) + (x)) /* JUMPBY makes the generator identify the instruction as a jump. SKIP_OVER is * for advancing to the next instruction, taking into account cache entries @@ -258,10 +258,6 @@ GETITEM(PyObject *v, Py_ssize_t i) { if (ADAPTIVE_COUNTER_IS_ZERO(next_instr->cache)) { \ STAT_INC((INSTNAME), deopt); \ } \ - else { \ - /* This is about to be (incorrectly) incremented: */ \ - STAT_DEC((INSTNAME), deferred); \ - } \ } while (0) #else #define UPDATE_MISS_STATS(INSTNAME) ((void)0) @@ -311,9 +307,6 @@ GETITEM(PyObject *v, Py_ssize_t i) { " in enclosing scope" #define NAME_ERROR_MSG "name '%.200s' is not defined" -#define KWNAMES_LEN() \ - (kwnames == NULL ? 0 : ((int)PyTuple_GET_SIZE(kwnames))) - #define DECREF_INPUTS_AND_REUSE_FLOAT(left, right, dval, result) \ do { \ if (Py_REFCNT(left) == 1) { \ @@ -328,7 +321,7 @@ do { \ }\ else { \ result = PyFloat_FromDouble(dval); \ - if ((result) == NULL) goto error; \ + if ((result) == NULL) GOTO_ERROR(error); \ _Py_DECREF_NO_DEALLOC(left); \ _Py_DECREF_NO_DEALLOC(right); \ } \ @@ -356,11 +349,49 @@ static const convertion_func_ptr CONVERSION_FUNCTIONS[4] = { [FVC_ASCII] = PyObject_ASCII }; -#define ASSERT_KWNAMES_IS_NULL() assert(kwnames == NULL) - // 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 + +static inline int _Py_EnterRecursivePy(PyThreadState *tstate) { + return (tstate->py_recursion_remaining-- <= 0) && + _Py_CheckRecursiveCallPy(tstate); +} + +static inline void _Py_LeaveRecursiveCallPy(PyThreadState *tstate) { + tstate->py_recursion_remaining++; +} + +/* Marker to specify tier 1 only instructions */ +#define TIER_ONE_ONLY + +/* Marker to specify tier 2 only instructions */ +#define TIER_TWO_ONLY + +/* Implementation of "macros" that modify the instruction pointer, + * stack pointer, or frame pointer. + * These need to treated differently by tier 1 and 2. + * The Tier 1 version is here; Tier 2 is inlined in ceval.c. */ + +#define LOAD_IP(OFFSET) do { \ + next_instr = frame->instr_ptr + (OFFSET); \ + } while (0) + +/* There's no STORE_IP(), it's inlined by the code generator. */ + +#define STORE_SP() \ +_PyFrame_SetStackPointer(frame, stack_pointer) + +#define LOAD_SP() \ +stack_pointer = _PyFrame_GetStackPointer(frame); + +/* Tier-switching macros. */ + +#define GOTO_TIER_TWO() goto enter_tier_two; + +#define CURRENT_OPARG() (next_uop[-1].oparg) + +#define CURRENT_OPERAND() (next_uop[-1].operand) diff --git a/Python/clinic/Python-tokenize.c.h b/Python/clinic/Python-tokenize.c.h index 28f5075826e36f..730fa8ef2a2154 100644 --- a/Python/clinic/Python-tokenize.c.h +++ b/Python/clinic/Python-tokenize.c.h @@ -3,10 +3,10 @@ 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() +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() #endif - +#include "pycore_modsupport.h" // _PyArg_UnpackKeywords() static PyObject * tokenizeriter_new_impl(PyTypeObject *type, PyObject *readline, @@ -80,4 +80,4 @@ tokenizeriter_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) exit: return return_value; } -/*[clinic end generated code: output=48be65a2808bdfa6 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=dcd6ec48f06a092e input=a9049054013a1b77]*/ diff --git a/Python/clinic/_warnings.c.h b/Python/clinic/_warnings.c.h index c71663919852ff..98dc49db3059b1 100644 --- a/Python/clinic/_warnings.c.h +++ b/Python/clinic/_warnings.c.h @@ -3,10 +3,11 @@ 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() +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() #endif - +#include "pycore_abstract.h" // _PyNumber_Index() +#include "pycore_modsupport.h" // _PyArg_UnpackKeywords() PyDoc_STRVAR(warnings_warn__doc__, "warn($module, /, message, category=None, stacklevel=1, source=None, *,\n" @@ -194,7 +195,7 @@ warnings_warn_explicit(PyObject *module, PyObject *const *args, Py_ssize_t nargs goto exit; } filename = args[2]; - lineno = _PyLong_AsInt(args[3]); + lineno = PyLong_AsInt(args[3]); if (lineno == -1 && PyErr_Occurred()) { goto exit; } @@ -243,4 +244,4 @@ warnings_filters_mutated(PyObject *module, PyObject *Py_UNUSED(ignored)) { return warnings_filters_mutated_impl(module); } -/*[clinic end generated code: output=f8d67e0f75771c36 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=f2d4214c382717a6 input=a9049054013a1b77]*/ diff --git a/Python/clinic/bltinmodule.c.h b/Python/clinic/bltinmodule.c.h index b0d05dde956efd..8d40e659b54a57 100644 --- a/Python/clinic/bltinmodule.c.h +++ b/Python/clinic/bltinmodule.c.h @@ -3,10 +3,10 @@ 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() +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() #endif - +#include "pycore_modsupport.h" // _PyArg_UnpackKeywords() PyDoc_STRVAR(builtin___import____doc__, "__import__($module, /, name, globals=None, locals=None, fromlist=(),\n" @@ -99,7 +99,7 @@ builtin___import__(PyObject *module, PyObject *const *args, Py_ssize_t nargs, Py goto skip_optional_pos; } } - level = _PyLong_AsInt(args[4]); + level = PyLong_AsInt(args[4]); if (level == -1 && PyErr_Occurred()) { goto exit; } @@ -242,7 +242,7 @@ builtin_chr(PyObject *module, PyObject *arg) PyObject *return_value = NULL; int i; - i = _PyLong_AsInt(arg); + i = PyLong_AsInt(arg); if (i == -1 && PyErr_Occurred()) { goto exit; } @@ -342,7 +342,7 @@ builtin_compile(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObj goto skip_optional_pos; } if (args[3]) { - flags = _PyLong_AsInt(args[3]); + flags = PyLong_AsInt(args[3]); if (flags == -1 && PyErr_Occurred()) { goto exit; } @@ -360,7 +360,7 @@ builtin_compile(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObj } } if (args[5]) { - optimize = _PyLong_AsInt(args[5]); + optimize = PyLong_AsInt(args[5]); if (optimize == -1 && PyErr_Occurred()) { goto exit; } @@ -372,7 +372,7 @@ builtin_compile(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObj if (!noptargs) { goto skip_optional_kwonly; } - feature_version = _PyLong_AsInt(args[6]); + feature_version = PyLong_AsInt(args[6]); if (feature_version == -1 && PyErr_Occurred()) { goto exit; } @@ -383,49 +383,6 @@ builtin_compile(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObj return return_value; } -PyDoc_STRVAR(builtin_dir__doc__, -"dir($module, arg=, /)\n" -"--\n" -"\n" -"Show attributes of an object.\n" -"\n" -"If called without an argument, return the names in the current scope.\n" -"Else, return an alphabetized list of names comprising (some of) the attributes\n" -"of the given object, and of attributes reachable from it.\n" -"If the object supplies a method named __dir__, it will be used; otherwise\n" -"the default dir() logic is used and returns:\n" -" for a module object: the module\'s attributes.\n" -" for a class object: its attributes, and recursively the attributes\n" -" of its bases.\n" -" for any other object: its attributes, its class\'s attributes, and\n" -" recursively the attributes of its class\'s base classes."); - -#define BUILTIN_DIR_METHODDEF \ - {"dir", _PyCFunction_CAST(builtin_dir), METH_FASTCALL, builtin_dir__doc__}, - -static PyObject * -builtin_dir_impl(PyObject *module, PyObject *arg); - -static PyObject * -builtin_dir(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - PyObject *arg = NULL; - - if (!_PyArg_CheckPositional("dir", nargs, 0, 1)) { - goto exit; - } - if (nargs < 1) { - goto skip_optional; - } - arg = args[0]; -skip_optional: - return_value = builtin_dir_impl(module, arg); - -exit: - return return_value; -} - PyDoc_STRVAR(builtin_divmod__doc__, "divmod($module, x, y, /)\n" "--\n" @@ -586,47 +543,6 @@ builtin_exec(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject return return_value; } -PyDoc_STRVAR(builtin_getattr__doc__, -"getattr($module, object, name, default=, /)\n" -"--\n" -"\n" -"Get a named attribute from an object.\n" -"\n" -"getattr(x, \'y\') is equivalent to x.y\n" -"When a default argument is given, it is returned when the attribute doesn\'t\n" -"exist; without it, an exception is raised in that case."); - -#define BUILTIN_GETATTR_METHODDEF \ - {"getattr", _PyCFunction_CAST(builtin_getattr), METH_FASTCALL, builtin_getattr__doc__}, - -static PyObject * -builtin_getattr_impl(PyObject *module, PyObject *object, PyObject *name, - PyObject *default_value); - -static PyObject * -builtin_getattr(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - PyObject *object; - PyObject *name; - PyObject *default_value = NULL; - - if (!_PyArg_CheckPositional("getattr", nargs, 2, 3)) { - goto exit; - } - object = args[0]; - name = args[1]; - if (nargs < 3) { - goto skip_optional; - } - default_value = args[2]; -skip_optional: - return_value = builtin_getattr_impl(module, object, name, default_value); - -exit: - return return_value; -} - PyDoc_STRVAR(builtin_globals__doc__, "globals($module, /)\n" "--\n" @@ -692,44 +608,6 @@ PyDoc_STRVAR(builtin_id__doc__, #define BUILTIN_ID_METHODDEF \ {"id", (PyCFunction)builtin_id, METH_O, builtin_id__doc__}, -PyDoc_STRVAR(builtin_next__doc__, -"next($module, iterator, default=, /)\n" -"--\n" -"\n" -"Return the next item from the iterator.\n" -"\n" -"If default is given and the iterator is exhausted,\n" -"it is returned instead of raising StopIteration."); - -#define BUILTIN_NEXT_METHODDEF \ - {"next", _PyCFunction_CAST(builtin_next), METH_FASTCALL, builtin_next__doc__}, - -static PyObject * -builtin_next_impl(PyObject *module, PyObject *iterator, - PyObject *default_value); - -static PyObject * -builtin_next(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - PyObject *iterator; - PyObject *default_value = NULL; - - if (!_PyArg_CheckPositional("next", nargs, 1, 2)) { - goto exit; - } - iterator = args[0]; - if (nargs < 2) { - goto skip_optional; - } - default_value = args[1]; -skip_optional: - return_value = builtin_next_impl(module, iterator, default_value); - -exit: - return return_value; -} - PyDoc_STRVAR(builtin_setattr__doc__, "setattr($module, obj, name, value, /)\n" "--\n" @@ -821,43 +699,6 @@ PyDoc_STRVAR(builtin_hex__doc__, #define BUILTIN_HEX_METHODDEF \ {"hex", (PyCFunction)builtin_hex, METH_O, builtin_hex__doc__}, -PyDoc_STRVAR(builtin_iter__doc__, -"iter($module, object, sentinel=, /)\n" -"--\n" -"\n" -"Get an iterator from an object.\n" -"\n" -"In the first form, the argument must supply its own iterator, or be a sequence.\n" -"In the second form, the callable is called until it returns the sentinel."); - -#define BUILTIN_ITER_METHODDEF \ - {"iter", _PyCFunction_CAST(builtin_iter), METH_FASTCALL, builtin_iter__doc__}, - -static PyObject * -builtin_iter_impl(PyObject *module, PyObject *object, PyObject *sentinel); - -static PyObject * -builtin_iter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - PyObject *object; - PyObject *sentinel = NULL; - - if (!_PyArg_CheckPositional("iter", nargs, 1, 2)) { - goto exit; - } - object = args[0]; - if (nargs < 2) { - goto skip_optional; - } - sentinel = args[1]; -skip_optional: - return_value = builtin_iter_impl(module, object, sentinel); - -exit: - return return_value; -} - PyDoc_STRVAR(builtin_aiter__doc__, "aiter($module, async_iterable, /)\n" "--\n" @@ -1236,41 +1077,6 @@ builtin_round(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObjec return return_value; } -PyDoc_STRVAR(builtin_vars__doc__, -"vars($module, object=, /)\n" -"--\n" -"\n" -"Show vars.\n" -"\n" -"Without arguments, equivalent to locals().\n" -"With an argument, equivalent to object.__dict__."); - -#define BUILTIN_VARS_METHODDEF \ - {"vars", _PyCFunction_CAST(builtin_vars), METH_FASTCALL, builtin_vars__doc__}, - -static PyObject * -builtin_vars_impl(PyObject *module, PyObject *object); - -static PyObject * -builtin_vars(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - PyObject *object = NULL; - - if (!_PyArg_CheckPositional("vars", nargs, 0, 1)) { - goto exit; - } - if (nargs < 1) { - goto skip_optional; - } - object = args[0]; -skip_optional: - return_value = builtin_vars_impl(module, object); - -exit: - return return_value; -} - PyDoc_STRVAR(builtin_sum__doc__, "sum($module, iterable, /, start=0)\n" "--\n" @@ -1406,4 +1212,4 @@ builtin_issubclass(PyObject *module, PyObject *const *args, Py_ssize_t nargs) exit: return return_value; } -/*[clinic end generated code: output=ef2f16ece134d62d input=a9049054013a1b77]*/ +/*[clinic end generated code: output=31bded5d08647a57 input=a9049054013a1b77]*/ diff --git a/Python/clinic/context.c.h b/Python/clinic/context.c.h index 27c375717bff96..997ac6f63384a9 100644 --- a/Python/clinic/context.c.h +++ b/Python/clinic/context.c.h @@ -2,11 +2,7 @@ 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 - +#include "pycore_modsupport.h" // _PyArg_CheckPositional() PyDoc_STRVAR(_contextvars_Context_get__doc__, "get($self, key, default=None, /)\n" @@ -183,4 +179,4 @@ PyDoc_STRVAR(_contextvars_ContextVar_reset__doc__, #define _CONTEXTVARS_CONTEXTVAR_RESET_METHODDEF \ {"reset", (PyCFunction)_contextvars_ContextVar_reset, METH_O, _contextvars_ContextVar_reset__doc__}, -/*[clinic end generated code: output=0c94d4b919500438 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=b667826178444c3f input=a9049054013a1b77]*/ diff --git a/Python/clinic/import.c.h b/Python/clinic/import.c.h index dec9ea90b863c7..5edeaef656ef62 100644 --- a/Python/clinic/import.c.h +++ b/Python/clinic/import.c.h @@ -3,10 +3,10 @@ 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() +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() #endif - +#include "pycore_modsupport.h" // _PyArg_CheckPositional() PyDoc_STRVAR(_imp_lock_held__doc__, "lock_held($module, /)\n" @@ -411,7 +411,7 @@ _imp__override_frozen_modules_for_tests(PyObject *module, PyObject *arg) PyObject *return_value = NULL; int override; - override = _PyLong_AsInt(arg); + override = PyLong_AsInt(arg); if (override == -1 && PyErr_Occurred()) { goto exit; } @@ -442,7 +442,7 @@ _imp__override_multi_interp_extensions_check(PyObject *module, PyObject *arg) PyObject *return_value = NULL; int override; - override = _PyLong_AsInt(arg); + override = PyLong_AsInt(arg); if (override == -1 && PyErr_Occurred()) { goto exit; } @@ -605,10 +605,6 @@ _imp_source_hash(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyOb if (PyObject_GetBuffer(args[1], &source, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&source, 'C')) { - _PyArg_BadArgument("source_hash", "argument 'source'", "contiguous buffer", args[1]); - goto exit; - } return_value = _imp_source_hash_impl(module, key, &source); exit: @@ -627,4 +623,4 @@ _imp_source_hash(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyOb #ifndef _IMP_EXEC_DYNAMIC_METHODDEF #define _IMP_EXEC_DYNAMIC_METHODDEF #endif /* !defined(_IMP_EXEC_DYNAMIC_METHODDEF) */ -/*[clinic end generated code: output=a95ec234672280a2 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=dbd63707bd40b07c input=a9049054013a1b77]*/ diff --git a/Python/clinic/instrumentation.c.h b/Python/clinic/instrumentation.c.h index cf3984ca24bbfe..8dae747c44a543 100644 --- a/Python/clinic/instrumentation.c.h +++ b/Python/clinic/instrumentation.c.h @@ -2,11 +2,7 @@ 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 - +#include "pycore_modsupport.h" // _PyArg_CheckPositional() PyDoc_STRVAR(monitoring_use_tool_id__doc__, "use_tool_id($module, tool_id, name, /)\n" @@ -29,7 +25,7 @@ monitoring_use_tool_id(PyObject *module, PyObject *const *args, Py_ssize_t nargs if (!_PyArg_CheckPositional("use_tool_id", nargs, 2, 2)) { goto exit; } - tool_id = _PyLong_AsInt(args[0]); + tool_id = PyLong_AsInt(args[0]); if (tool_id == -1 && PyErr_Occurred()) { goto exit; } @@ -57,7 +53,7 @@ monitoring_free_tool_id(PyObject *module, PyObject *arg) PyObject *return_value = NULL; int tool_id; - tool_id = _PyLong_AsInt(arg); + tool_id = PyLong_AsInt(arg); if (tool_id == -1 && PyErr_Occurred()) { goto exit; } @@ -84,7 +80,7 @@ monitoring_get_tool(PyObject *module, PyObject *arg) PyObject *return_value = NULL; int tool_id; - tool_id = _PyLong_AsInt(arg); + tool_id = PyLong_AsInt(arg); if (tool_id == -1 && PyErr_Occurred()) { goto exit; } @@ -117,11 +113,11 @@ monitoring_register_callback(PyObject *module, PyObject *const *args, Py_ssize_t if (!_PyArg_CheckPositional("register_callback", nargs, 3, 3)) { goto exit; } - tool_id = _PyLong_AsInt(args[0]); + tool_id = PyLong_AsInt(args[0]); if (tool_id == -1 && PyErr_Occurred()) { goto exit; } - event = _PyLong_AsInt(args[1]); + event = PyLong_AsInt(args[1]); if (event == -1 && PyErr_Occurred()) { goto exit; } @@ -150,7 +146,7 @@ monitoring_get_events(PyObject *module, PyObject *arg) int tool_id; int _return_value; - tool_id = _PyLong_AsInt(arg); + tool_id = PyLong_AsInt(arg); if (tool_id == -1 && PyErr_Occurred()) { goto exit; } @@ -185,11 +181,11 @@ monitoring_set_events(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("set_events", nargs, 2, 2)) { goto exit; } - tool_id = _PyLong_AsInt(args[0]); + tool_id = PyLong_AsInt(args[0]); if (tool_id == -1 && PyErr_Occurred()) { goto exit; } - event_set = _PyLong_AsInt(args[1]); + event_set = PyLong_AsInt(args[1]); if (event_set == -1 && PyErr_Occurred()) { goto exit; } @@ -222,7 +218,7 @@ monitoring_get_local_events(PyObject *module, PyObject *const *args, Py_ssize_t if (!_PyArg_CheckPositional("get_local_events", nargs, 2, 2)) { goto exit; } - tool_id = _PyLong_AsInt(args[0]); + tool_id = PyLong_AsInt(args[0]); if (tool_id == -1 && PyErr_Occurred()) { goto exit; } @@ -260,12 +256,12 @@ monitoring_set_local_events(PyObject *module, PyObject *const *args, Py_ssize_t if (!_PyArg_CheckPositional("set_local_events", nargs, 3, 3)) { goto exit; } - tool_id = _PyLong_AsInt(args[0]); + tool_id = PyLong_AsInt(args[0]); if (tool_id == -1 && PyErr_Occurred()) { goto exit; } code = args[1]; - event_set = _PyLong_AsInt(args[2]); + event_set = PyLong_AsInt(args[2]); if (event_set == -1 && PyErr_Occurred()) { goto exit; } @@ -308,4 +304,4 @@ monitoring__all_events(PyObject *module, PyObject *Py_UNUSED(ignored)) { return monitoring__all_events_impl(module); } -/*[clinic end generated code: output=11cc0803875b3ffa input=a9049054013a1b77]*/ +/*[clinic end generated code: output=14ffc0884a6de50a input=a9049054013a1b77]*/ diff --git a/Python/clinic/marshal.c.h b/Python/clinic/marshal.c.h index a593b980544b72..e6b0f1999a41c5 100644 --- a/Python/clinic/marshal.c.h +++ b/Python/clinic/marshal.c.h @@ -2,11 +2,7 @@ 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 - +#include "pycore_modsupport.h" // _PyArg_CheckPositional() PyDoc_STRVAR(marshal_dump__doc__, "dump($module, value, file, version=version, /)\n" @@ -48,7 +44,7 @@ marshal_dump(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (nargs < 3) { goto skip_optional; } - version = _PyLong_AsInt(args[2]); + version = PyLong_AsInt(args[2]); if (version == -1 && PyErr_Occurred()) { goto exit; } @@ -112,7 +108,7 @@ marshal_dumps(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (nargs < 2) { goto skip_optional; } - version = _PyLong_AsInt(args[1]); + version = PyLong_AsInt(args[1]); if (version == -1 && PyErr_Occurred()) { goto exit; } @@ -147,10 +143,6 @@ marshal_loads(PyObject *module, PyObject *arg) if (PyObject_GetBuffer(arg, &bytes, PyBUF_SIMPLE) != 0) { goto exit; } - if (!PyBuffer_IsContiguous(&bytes, 'C')) { - _PyArg_BadArgument("loads", "argument", "contiguous buffer", arg); - goto exit; - } return_value = marshal_loads_impl(module, &bytes); exit: @@ -161,4 +153,4 @@ marshal_loads(PyObject *module, PyObject *arg) return return_value; } -/*[clinic end generated code: output=12082d61d2942473 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=92d2d47aac9128ee input=a9049054013a1b77]*/ diff --git a/Python/clinic/sysmodule.c.h b/Python/clinic/sysmodule.c.h index a95a32f65edb89..93b8385a5b4097 100644 --- a/Python/clinic/sysmodule.c.h +++ b/Python/clinic/sysmodule.c.h @@ -3,10 +3,10 @@ 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() +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() #endif - +#include "pycore_modsupport.h" // _PyArg_UnpackKeywords() PyDoc_STRVAR(sys_addaudithook__doc__, "addaudithook($module, /, hook)\n" @@ -289,6 +289,40 @@ sys_intern(PyObject *module, PyObject *arg) return return_value; } +PyDoc_STRVAR(sys__is_interned__doc__, +"_is_interned($module, string, /)\n" +"--\n" +"\n" +"Return True if the given string is \"interned\"."); + +#define SYS__IS_INTERNED_METHODDEF \ + {"_is_interned", (PyCFunction)sys__is_interned, METH_O, sys__is_interned__doc__}, + +static int +sys__is_interned_impl(PyObject *module, PyObject *string); + +static PyObject * +sys__is_interned(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + PyObject *string; + int _return_value; + + if (!PyUnicode_Check(arg)) { + _PyArg_BadArgument("_is_interned", "argument", "str", arg); + goto exit; + } + string = arg; + _return_value = sys__is_interned_impl(module, string); + if ((_return_value == -1) && PyErr_Occurred()) { + goto exit; + } + return_value = PyBool_FromLong((long)_return_value); + +exit: + return return_value; +} + PyDoc_STRVAR(sys__settraceallthreads__doc__, "_settraceallthreads($module, arg, /)\n" "--\n" @@ -444,7 +478,7 @@ sys_setrecursionlimit(PyObject *module, PyObject *arg) PyObject *return_value = NULL; int new_limit; - new_limit = _PyLong_AsInt(arg); + new_limit = PyLong_AsInt(arg); if (new_limit == -1 && PyErr_Occurred()) { goto exit; } @@ -507,7 +541,7 @@ sys_set_coroutine_origin_tracking_depth(PyObject *module, PyObject *const *args, if (!args) { goto exit; } - depth = _PyLong_AsInt(args[0]); + depth = PyLong_AsInt(args[0]); if (depth == -1 && PyErr_Occurred()) { goto exit; } @@ -675,7 +709,7 @@ sys_setdlopenflags(PyObject *module, PyObject *arg) PyObject *return_value = NULL; int new_val; - new_val = _PyLong_AsInt(arg); + new_val = PyLong_AsInt(arg); if (new_val == -1 && PyErr_Occurred()) { goto exit; } @@ -730,7 +764,7 @@ sys_mdebug(PyObject *module, PyObject *arg) PyObject *return_value = NULL; int flag; - flag = _PyLong_AsInt(arg); + flag = PyLong_AsInt(arg); if (flag == -1 && PyErr_Occurred()) { goto exit; } @@ -808,7 +842,7 @@ sys_set_int_max_str_digits(PyObject *module, PyObject *const *args, Py_ssize_t n if (!args) { goto exit; } - maxdigits = _PyLong_AsInt(args[0]); + maxdigits = PyLong_AsInt(args[0]); if (maxdigits == -1 && PyErr_Occurred()) { goto exit; } @@ -969,7 +1003,7 @@ sys__getframe(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (nargs < 1) { goto skip_optional; } - depth = _PyLong_AsInt(args[0]); + depth = PyLong_AsInt(args[0]); if (depth == -1 && PyErr_Occurred()) { goto exit; } @@ -1121,7 +1155,7 @@ PyDoc_STRVAR(sys__stats_on__doc__, "_stats_on($module, /)\n" "--\n" "\n" -"Turns on stats gathering (stats gathering is on by default)."); +"Turns on stats gathering (stats gathering is off by default)."); #define SYS__STATS_ON_METHODDEF \ {"_stats_on", (PyCFunction)sys__stats_on, METH_NOARGS, sys__stats_on__doc__}, @@ -1143,7 +1177,7 @@ PyDoc_STRVAR(sys__stats_off__doc__, "_stats_off($module, /)\n" "--\n" "\n" -"Turns off stats gathering (stats gathering is on by default)."); +"Turns off stats gathering (stats gathering is off by default)."); #define SYS__STATS_OFF_METHODDEF \ {"_stats_off", (PyCFunction)sys__stats_off, METH_NOARGS, sys__stats_off__doc__}, @@ -1187,18 +1221,30 @@ PyDoc_STRVAR(sys__stats_dump__doc__, "_stats_dump($module, /)\n" "--\n" "\n" -"Dump stats to file, and clears the stats."); +"Dump stats to file, and clears the stats.\n" +"\n" +"Return False if no statistics were not dumped because stats gathering was off."); #define SYS__STATS_DUMP_METHODDEF \ {"_stats_dump", (PyCFunction)sys__stats_dump, METH_NOARGS, sys__stats_dump__doc__}, -static PyObject * +static int sys__stats_dump_impl(PyObject *module); static PyObject * sys__stats_dump(PyObject *module, PyObject *Py_UNUSED(ignored)) { - return sys__stats_dump_impl(module); + PyObject *return_value = NULL; + int _return_value; + + _return_value = sys__stats_dump_impl(module); + if ((_return_value == -1) && PyErr_Occurred()) { + goto exit; + } + return_value = PyBool_FromLong((long)_return_value); + +exit: + return return_value; } #endif /* defined(Py_STATS) */ @@ -1358,7 +1404,7 @@ sys__getframemodulename(PyObject *module, PyObject *const *args, Py_ssize_t narg if (!noptargs) { goto skip_optional_pos; } - depth = _PyLong_AsInt(args[0]); + depth = PyLong_AsInt(args[0]); if (depth == -1 && PyErr_Occurred()) { goto exit; } @@ -1369,6 +1415,34 @@ sys__getframemodulename(PyObject *module, PyObject *const *args, Py_ssize_t narg return return_value; } +PyDoc_STRVAR(sys__get_cpu_count_config__doc__, +"_get_cpu_count_config($module, /)\n" +"--\n" +"\n" +"Private function for getting PyConfig.cpu_count"); + +#define SYS__GET_CPU_COUNT_CONFIG_METHODDEF \ + {"_get_cpu_count_config", (PyCFunction)sys__get_cpu_count_config, METH_NOARGS, sys__get_cpu_count_config__doc__}, + +static int +sys__get_cpu_count_config_impl(PyObject *module); + +static PyObject * +sys__get_cpu_count_config(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + PyObject *return_value = NULL; + int _return_value; + + _return_value = sys__get_cpu_count_config_impl(module); + if ((_return_value == -1) && PyErr_Occurred()) { + goto exit; + } + return_value = PyLong_FromLong((long)_return_value); + +exit: + return return_value; +} + #ifndef SYS_GETWINDOWSVERSION_METHODDEF #define SYS_GETWINDOWSVERSION_METHODDEF #endif /* !defined(SYS_GETWINDOWSVERSION_METHODDEF) */ @@ -1412,4 +1486,4 @@ sys__getframemodulename(PyObject *module, PyObject *const *args, Py_ssize_t narg #ifndef SYS_GETANDROIDAPILEVEL_METHODDEF #define SYS_GETANDROIDAPILEVEL_METHODDEF #endif /* !defined(SYS_GETANDROIDAPILEVEL_METHODDEF) */ -/*[clinic end generated code: output=41937e0843c68009 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=3dc3b2cb0ce38ebb input=a9049054013a1b77]*/ diff --git a/Python/clinic/traceback.c.h b/Python/clinic/traceback.c.h index 3c344934971643..aee08d6ad97047 100644 --- a/Python/clinic/traceback.c.h +++ b/Python/clinic/traceback.c.h @@ -3,10 +3,10 @@ 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() +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() #endif - +#include "pycore_modsupport.h" // _PyArg_UnpackKeywords() PyDoc_STRVAR(tb_new__doc__, "TracebackType(tb_next, tb_frame, tb_lasti, tb_lineno)\n" @@ -65,11 +65,11 @@ tb_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) goto exit; } tb_frame = (PyFrameObject *)fastargs[1]; - tb_lasti = _PyLong_AsInt(fastargs[2]); + tb_lasti = PyLong_AsInt(fastargs[2]); if (tb_lasti == -1 && PyErr_Occurred()) { goto exit; } - tb_lineno = _PyLong_AsInt(fastargs[3]); + tb_lineno = PyLong_AsInt(fastargs[3]); if (tb_lineno == -1 && PyErr_Occurred()) { goto exit; } @@ -78,4 +78,4 @@ tb_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) exit: return return_value; } -/*[clinic end generated code: output=7bc9927e362fdfb7 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=4e2f6b935841b09c input=a9049054013a1b77]*/ diff --git a/Python/codecs.c b/Python/codecs.c index 4e47ff93a3691b..d8fe7b22063a80 100644 --- a/Python/codecs.c +++ b/Python/codecs.c @@ -14,7 +14,6 @@ Copyright (c) Corporation for National Research Initiatives. #include "pycore_pyerrors.h" // _PyErr_FormatNote() #include "pycore_pystate.h" // _PyInterpreterState_GET() #include "pycore_ucnhash.h" // _PyUnicode_Name_CAPI -#include const char *Py_hexdigits = "0123456789abcdef"; @@ -147,15 +146,14 @@ PyObject *_PyCodec_Lookup(const char *encoding) PyUnicode_InternInPlace(&v); /* First, try to lookup the name in the registry dictionary */ - PyObject *result = PyDict_GetItemWithError(interp->codec_search_cache, v); + PyObject *result; + if (PyDict_GetItemRef(interp->codec_search_cache, v, &result) < 0) { + goto onError; + } if (result != NULL) { - Py_INCREF(result); Py_DECREF(v); return result; } - else if (PyErr_Occurred()) { - goto onError; - } /* Next, scan the search functions in order of registration */ const Py_ssize_t len = PyList_Size(interp->codec_search_path); @@ -617,20 +615,19 @@ int PyCodec_RegisterError(const char *name, PyObject *error) the error handling callback for strict encoding will be returned. */ PyObject *PyCodec_LookupError(const char *name) { - PyObject *handler = NULL; - PyInterpreterState *interp = _PyInterpreterState_GET(); if (interp->codec_search_path == NULL && _PyCodecRegistry_Init()) return NULL; if (name==NULL) name = "strict"; - handler = _PyDict_GetItemStringWithError(interp->codec_error_registry, name); - if (handler) { - Py_INCREF(handler); + PyObject *handler; + if (PyDict_GetItemStringRef(interp->codec_error_registry, name, &handler) < 0) { + return NULL; } - else if (!PyErr_Occurred()) { + if (handler == NULL) { PyErr_Format(PyExc_LookupError, "unknown error handler name '%.400s'", name); + return NULL; } return handler; } @@ -934,8 +931,6 @@ PyObject *PyCodec_BackslashReplaceErrors(PyObject *exc) return Py_BuildValue("(Nn)", res, end); } -static _PyUnicode_Name_CAPI *ucnhash_capi = NULL; - PyObject *PyCodec_NameReplaceErrors(PyObject *exc) { if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeEncodeError)) { @@ -956,13 +951,9 @@ PyObject *PyCodec_NameReplaceErrors(PyObject *exc) return NULL; if (!(object = PyUnicodeEncodeError_GetObject(exc))) return NULL; - if (!ucnhash_capi) { - /* load the unicode data module */ - ucnhash_capi = (_PyUnicode_Name_CAPI *)PyCapsule_Import( - PyUnicodeData_CAPSULE_NAME, 1); - if (!ucnhash_capi) { - return NULL; - } + _PyUnicode_Name_CAPI *ucnhash_capi = _PyUnicode_GetNameCAPI(); + if (ucnhash_capi == NULL) { + return NULL; } for (i = start, ressize = 0; i < end; ++i) { /* object is guaranteed to be "ready" */ diff --git a/Python/compile.c b/Python/compile.c index b673e3ac6c1cc5..2a6291ccb51b0c 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -24,6 +24,7 @@ #include #include "Python.h" +#include "opcode.h" #include "pycore_ast.h" // _PyAST_GetDocString() #define NEED_OPCODE_TABLES #include "pycore_opcode_utils.h" @@ -70,9 +71,7 @@ && ((C)->u->u_ste->ste_type == ModuleBlock)) typedef _PyCompilerSrcLocation location; -typedef _PyCfgInstruction cfg_instr; -typedef _PyCfgBasicblock basicblock; -typedef _PyCfgBuilder cfg_builder; +typedef struct _PyCfgBuilder cfg_builder; #define LOCATION(LNO, END_LNO, COL, END_COL) \ ((const _PyCompilerSrcLocation){(LNO), (END_LNO), (COL), (END_COL)}) @@ -101,7 +100,7 @@ static jump_target_label NO_LABEL = {-1}; } #define USE_LABEL(C, LBL) \ - RETURN_IF_ERROR(instr_sequence_use_label(INSTR_SEQUENCE(C), (LBL).id)) + RETURN_IF_ERROR(_PyCompile_InstructionSequence_UseLabel(INSTR_SEQUENCE(C), (LBL).id)) /* fblockinfo tracks the current frame block. @@ -218,8 +217,9 @@ instr_sequence_new_label(instr_sequence *seq) return lbl; } -static int -instr_sequence_use_label(instr_sequence *seq, int lbl) { +int +_PyCompile_InstructionSequence_UseLabel(instr_sequence *seq, int lbl) +{ int old_size = seq->s_labelmap_size; RETURN_IF_ERROR( _PyCompile_EnsureArrayLargeEnough(lbl, @@ -238,8 +238,9 @@ instr_sequence_use_label(instr_sequence *seq, int lbl) { #define MAX_OPCODE 511 -static int -instr_sequence_addop(instr_sequence *seq, int opcode, int oparg, location loc) +int +_PyCompile_InstructionSequence_Addop(instr_sequence *seq, int opcode, int oparg, + location loc) { assert(0 <= opcode && opcode <= MAX_OPCODE); assert(IS_WITHIN_OPCODE_RANGE(opcode)); @@ -288,10 +289,12 @@ instr_sequence_fini(instr_sequence *seq) { seq->s_instrs = NULL; } -static int -instr_sequence_to_cfg(instr_sequence *seq, cfg_builder *g) { - memset(g, 0, sizeof(cfg_builder)); - RETURN_IF_ERROR(_PyCfgBuilder_Init(g)); +static cfg_builder* +instr_sequence_to_cfg(instr_sequence *seq) { + cfg_builder *g = _PyCfgBuilder_New(); + if (g == NULL) { + return NULL; + } /* There can be more than one label for the same offset. The * offset2lbl maping selects one of them which we use consistently. @@ -300,7 +303,7 @@ instr_sequence_to_cfg(instr_sequence *seq, cfg_builder *g) { int *offset2lbl = PyMem_Malloc(seq->s_used * sizeof(int)); if (offset2lbl == NULL) { PyErr_NoMemory(); - return ERROR; + goto error; } for (int i = 0; i < seq->s_used; i++) { offset2lbl[i] = -1; @@ -336,23 +339,17 @@ instr_sequence_to_cfg(instr_sequence *seq, cfg_builder *g) { goto error; } } - PyMem_Free(offset2lbl); - - int nblocks = 0; - for (basicblock *b = g->g_block_list; b != NULL; b = b->b_list) { - nblocks++; - } - if ((size_t)nblocks > SIZE_MAX / sizeof(basicblock *)) { - PyErr_NoMemory(); - return ERROR; + if (_PyCfgBuilder_CheckSize(g) < 0) { + goto error; } - return SUCCESS; + PyMem_Free(offset2lbl); + return g; error: + _PyCfgBuilder_Free(g); PyMem_Free(offset2lbl); - return ERROR; + return NULL; } - /* The following items change on entry and exit of code blocks. They must be saved and restored when returning to a block. */ @@ -561,6 +558,24 @@ _PyAST_Compile(mod_ty mod, PyObject *filename, PyCompilerFlags *pflags, return co; } +int +_PyCompile_AstOptimize(mod_ty mod, PyObject *filename, PyCompilerFlags *cf, + int optimize, PyArena *arena) +{ + PyFutureFeatures future; + if (!_PyFuture_FromAST(mod, filename, &future)) { + return -1; + } + int flags = future.ff_features | cf->cf_flags; + if (optimize == -1) { + optimize = _Py_GetConfig()->optimization_level; + } + if (!_PyAST_Optimize(mod, arena, optimize, flags)) { + return -1; + } + return 0; +} + static void compiler_free(struct compiler *c) { @@ -781,35 +796,12 @@ stack_effect(int opcode, int oparg, int jump) // Specialized instructions are not supported. return PY_INVALID_STACK_EFFECT; } - int popped, pushed; - if (jump > 0) { - popped = _PyOpcode_num_popped(opcode, oparg, true); - pushed = _PyOpcode_num_pushed(opcode, oparg, true); - } - else { - popped = _PyOpcode_num_popped(opcode, oparg, false); - pushed = _PyOpcode_num_pushed(opcode, oparg, false); - } + int popped = _PyOpcode_num_popped(opcode, oparg); + int pushed = _PyOpcode_num_pushed(opcode, oparg); if (popped < 0 || pushed < 0) { return PY_INVALID_STACK_EFFECT; } - if (jump >= 0) { - return pushed - popped; - } - if (jump < 0) { - // Compute max(pushed - popped, alt_pushed - alt_popped) - int alt_popped = _PyOpcode_num_popped(opcode, oparg, true); - int alt_pushed = _PyOpcode_num_pushed(opcode, oparg, true); - if (alt_popped < 0 || alt_pushed < 0) { - return PY_INVALID_STACK_EFFECT; - } - int diff = pushed - popped; - int alt_diff = alt_pushed - alt_popped; - if (alt_diff > diff) { - return alt_diff; - } - return diff; - } + return pushed - popped; } // Pseudo ops @@ -868,49 +860,49 @@ PyCompile_OpcodeStackEffect(int opcode, int oparg) } int -PyUnstable_OpcodeIsValid(int opcode) +_PyCompile_OpcodeIsValid(int opcode) { return IS_VALID_OPCODE(opcode); } int -PyUnstable_OpcodeHasArg(int opcode) +_PyCompile_OpcodeHasArg(int opcode) { return OPCODE_HAS_ARG(opcode); } int -PyUnstable_OpcodeHasConst(int opcode) +_PyCompile_OpcodeHasConst(int opcode) { return OPCODE_HAS_CONST(opcode); } int -PyUnstable_OpcodeHasName(int opcode) +_PyCompile_OpcodeHasName(int opcode) { return OPCODE_HAS_NAME(opcode); } int -PyUnstable_OpcodeHasJump(int opcode) +_PyCompile_OpcodeHasJump(int opcode) { return OPCODE_HAS_JUMP(opcode); } int -PyUnstable_OpcodeHasFree(int opcode) +_PyCompile_OpcodeHasFree(int opcode) { return OPCODE_HAS_FREE(opcode); } int -PyUnstable_OpcodeHasLocal(int opcode) +_PyCompile_OpcodeHasLocal(int opcode) { return OPCODE_HAS_LOCAL(opcode); } int -PyUnstable_OpcodeHasExc(int opcode) +_PyCompile_OpcodeHasExc(int opcode) { return IS_BLOCK_PUSH_OPCODE(opcode); } @@ -920,7 +912,7 @@ codegen_addop_noarg(instr_sequence *seq, int opcode, location loc) { assert(!OPCODE_HAS_ARG(opcode)); assert(!IS_ASSEMBLER_OPCODE(opcode)); - return instr_sequence_addop(seq, opcode, 0, loc); + return _PyCompile_InstructionSequence_Addop(seq, opcode, 0, loc); } static Py_ssize_t @@ -1110,7 +1102,7 @@ compiler_addop_name(struct compiler_unit *u, location loc, arg <<= 1; } if (opcode == LOAD_METHOD) { - assert(SAME_OPCODE_METADATA(LOAD_METHOD, LOAD_ATTR)); + assert(is_pseudo_target(LOAD_METHOD, LOAD_ATTR)); opcode = LOAD_ATTR; arg <<= 1; arg |= 1; @@ -1120,18 +1112,18 @@ compiler_addop_name(struct compiler_unit *u, location loc, arg |= 2; } if (opcode == LOAD_SUPER_METHOD) { - assert(SAME_OPCODE_METADATA(LOAD_SUPER_METHOD, LOAD_SUPER_ATTR)); + assert(is_pseudo_target(LOAD_SUPER_METHOD, LOAD_SUPER_ATTR)); opcode = LOAD_SUPER_ATTR; arg <<= 2; arg |= 3; } if (opcode == LOAD_ZERO_SUPER_ATTR) { - assert(SAME_OPCODE_METADATA(LOAD_ZERO_SUPER_ATTR, LOAD_SUPER_ATTR)); + assert(is_pseudo_target(LOAD_ZERO_SUPER_ATTR, LOAD_SUPER_ATTR)); opcode = LOAD_SUPER_ATTR; arg <<= 2; } if (opcode == LOAD_ZERO_SUPER_METHOD) { - assert(SAME_OPCODE_METADATA(LOAD_ZERO_SUPER_METHOD, LOAD_SUPER_ATTR)); + assert(is_pseudo_target(LOAD_ZERO_SUPER_METHOD, LOAD_SUPER_ATTR)); opcode = LOAD_SUPER_ATTR; arg <<= 2; arg |= 1; @@ -1153,7 +1145,7 @@ codegen_addop_i(instr_sequence *seq, int opcode, Py_ssize_t oparg, location loc) int oparg_ = Py_SAFE_DOWNCAST(oparg, Py_ssize_t, int); assert(!IS_ASSEMBLER_OPCODE(opcode)); - return instr_sequence_addop(seq, opcode, oparg_, loc); + return _PyCompile_InstructionSequence_Addop(seq, opcode, oparg_, loc); } static int @@ -1163,7 +1155,7 @@ codegen_addop_j(instr_sequence *seq, location loc, assert(IS_LABEL(target)); assert(OPCODE_HAS_JUMP(opcode) || IS_BLOCK_PUSH_OPCODE(opcode)); assert(!IS_ASSEMBLER_OPCODE(opcode)); - return instr_sequence_addop(seq, opcode, target.id, loc); + return _PyCompile_InstructionSequence_Addop(seq, opcode, target.id, loc); } #define RETURN_IF_ERROR_IN_SCOPE(C, CALL) { \ @@ -1367,7 +1359,7 @@ compiler_enter_scope(struct compiler *c, identifier name, else { RETURN_IF_ERROR(compiler_set_qualname(c)); } - ADDOP_I(c, loc, RESUME, 0); + ADDOP_I(c, loc, RESUME, RESUME_AT_FUNC_START); if (u->u_scope_type == COMPILER_SCOPE_MODULE) { loc.lineno = -1; @@ -1391,8 +1383,8 @@ compiler_exit_scope(struct compiler *c) assert(c->u); /* we are deleting from a list so this really shouldn't fail */ if (PySequence_DelItem(c->c_stack, n) < 0) { - _PyErr_WriteUnraisableMsg("on removing the last compiler " - "stack item", NULL); + PyErr_FormatUnraisable("Exception ignored on removing " + "the last compiler stack item"); } } else { @@ -1534,9 +1526,9 @@ compiler_add_yield_from(struct compiler *c, location loc, int await) // 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, loc, SETUP_FINALLY, fail); - ADDOP_I(c, loc, YIELD_VALUE, 0); + ADDOP_I(c, loc, YIELD_VALUE, 1); ADDOP(c, NO_LOCATION, POP_BLOCK); - ADDOP_I(c, loc, RESUME, await ? 3 : 2); + ADDOP_I(c, loc, RESUME, await ? RESUME_AFTER_AWAIT : RESUME_AFTER_YIELD_FROM); ADDOP_JUMP(c, loc, JUMP_NO_INTERRUPT, send); USE_LABEL(c, fail); @@ -2361,11 +2353,6 @@ compiler_function(struct compiler *c, stmt_ty s, int is_async) int is_generic = asdl_seq_LEN(type_params) > 0; - if (is_generic) { - // Used by the CALL to the type parameters function. - ADDOP(c, loc, PUSH_NULL); - } - funcflags = compiler_default_arguments(c, loc, args); if (funcflags == -1) { return ERROR; @@ -2436,8 +2423,12 @@ compiler_function(struct compiler *c, stmt_ty s, int is_async) Py_DECREF(co); if (num_typeparam_args > 0) { ADDOP_I(c, loc, SWAP, num_typeparam_args + 1); + ADDOP_I(c, loc, CALL, num_typeparam_args - 1); + } + else { + ADDOP(c, loc, PUSH_NULL); + ADDOP_I(c, loc, CALL, 0); } - ADDOP_I(c, loc, CALL, num_typeparam_args); } RETURN_IF_ERROR(compiler_apply_decorators(c, decos)); @@ -2565,8 +2556,8 @@ compiler_class_body(struct compiler *c, stmt_ty s, int firstlineno) // these instructions should be attributed to the class line, // not a decorator line loc = LOC(s); - ADDOP(c, loc, PUSH_NULL); ADDOP(c, loc, LOAD_BUILD_CLASS); + ADDOP(c, loc, PUSH_NULL); /* 3. load a function (or closure) made from the code object */ if (compiler_make_closure(c, loc, co, 0) < 0) { @@ -2598,7 +2589,6 @@ compiler_class(struct compiler *c, stmt_ty s) int is_generic = asdl_seq_LEN(type_params) > 0; if (is_generic) { Py_XSETREF(c->u->u_private, Py_NewRef(s->v.ClassDef.name)); - ADDOP(c, loc, PUSH_NULL); PyObject *type_params_name = PyUnicode_FromFormat("", s->v.ClassDef.name); if (!type_params_name) { @@ -2666,6 +2656,7 @@ compiler_class(struct compiler *c, stmt_ty s) return ERROR; } Py_DECREF(co); + ADDOP(c, loc, PUSH_NULL); ADDOP_I(c, loc, CALL, 0); } else { RETURN_IF_ERROR(compiler_call_helper(c, loc, 2, @@ -2716,7 +2707,6 @@ compiler_typealias(struct compiler *c, stmt_ty s) int is_generic = asdl_seq_LEN(type_params) > 0; PyObject *name = s->v.TypeAlias.name->v.Name.id; if (is_generic) { - ADDOP(c, loc, PUSH_NULL); PyObject *type_params_name = PyUnicode_FromFormat("", name); if (!type_params_name) { @@ -2756,6 +2746,7 @@ compiler_typealias(struct compiler *c, stmt_ty s) return ERROR; } Py_DECREF(co); + ADDOP(c, loc, PUSH_NULL); ADDOP_I(c, loc, CALL, 0); } RETURN_IF_ERROR(compiler_nameop(c, loc, name, Store)); @@ -2906,7 +2897,7 @@ compiler_jump_if(struct compiler *c, location loc, compiler_jump_if(c, loc, e->v.IfExp.test, next2, 0)); RETURN_IF_ERROR( compiler_jump_if(c, loc, e->v.IfExp.body, next, cond)); - ADDOP_JUMP(c, NO_LOCATION, JUMP, end); + ADDOP_JUMP(c, NO_LOCATION, JUMP_NO_INTERRUPT, end); USE_LABEL(c, next2); RETURN_IF_ERROR( @@ -2935,12 +2926,12 @@ compiler_jump_if(struct compiler *c, location loc, ADDOP(c, LOC(e), TO_BOOL); ADDOP_JUMP(c, LOC(e), cond ? POP_JUMP_IF_TRUE : POP_JUMP_IF_FALSE, next); NEW_JUMP_TARGET_LABEL(c, end); - ADDOP_JUMP(c, NO_LOCATION, JUMP, end); + ADDOP_JUMP(c, NO_LOCATION, JUMP_NO_INTERRUPT, end); USE_LABEL(c, cleanup); ADDOP(c, LOC(e), POP_TOP); if (!cond) { - ADDOP_JUMP(c, NO_LOCATION, JUMP, next); + ADDOP_JUMP(c, NO_LOCATION, JUMP_NO_INTERRUPT, next); } USE_LABEL(c, end); @@ -2972,7 +2963,7 @@ compiler_ifexp(struct compiler *c, expr_ty e) compiler_jump_if(c, LOC(e), e->v.IfExp.test, next, 0)); VISIT(c, expr, e->v.IfExp.body); - ADDOP_JUMP(c, NO_LOCATION, JUMP, end); + ADDOP_JUMP(c, NO_LOCATION, JUMP_NO_INTERRUPT, end); USE_LABEL(c, next); VISIT(c, expr, e->v.IfExp.orelse); @@ -3050,7 +3041,7 @@ compiler_if(struct compiler *c, stmt_ty s) VISIT_SEQ(c, stmt, s->v.If.body); if (asdl_seq_LEN(s->v.If.orelse)) { - ADDOP_JUMP(c, NO_LOCATION, JUMP, end); + ADDOP_JUMP(c, NO_LOCATION, JUMP_NO_INTERRUPT, end); USE_LABEL(c, next); VISIT_SEQ(c, stmt, s->v.If.orelse); @@ -3246,18 +3237,6 @@ compiler_continue(struct compiler *c, location loc) } -static location -location_of_last_executing_statement(asdl_stmt_seq *stmts) -{ - for (Py_ssize_t i = asdl_seq_LEN(stmts) - 1; i >= 0; i++) { - location loc = LOC((stmt_ty)asdl_seq_GET(stmts, i)); - if (loc.lineno > 0) { - return loc; - } - } - return NO_LOCATION; -} - /* Code generated for "try: finally: " is as follows: SETUP_FINALLY L @@ -3315,7 +3294,7 @@ compiler_try_finally(struct compiler *c, stmt_ty s) compiler_pop_fblock(c, FINALLY_TRY, body); VISIT_SEQ(c, stmt, s->v.Try.finalbody); - ADDOP_JUMP(c, NO_LOCATION, JUMP, exit); + ADDOP_JUMP(c, NO_LOCATION, JUMP_NO_INTERRUPT, exit); /* `finally` block */ USE_LABEL(c, end); @@ -3326,9 +3305,9 @@ compiler_try_finally(struct compiler *c, stmt_ty s) RETURN_IF_ERROR( compiler_push_fblock(c, loc, FINALLY_END, end, NO_LABEL, NULL)); VISIT_SEQ(c, stmt, s->v.Try.finalbody); - loc = location_of_last_executing_statement(s->v.Try.finalbody); compiler_pop_fblock(c, FINALLY_END, end); + loc = NO_LOCATION; ADDOP_I(c, loc, RERAISE, 0); USE_LABEL(c, cleanup); @@ -3365,7 +3344,7 @@ compiler_try_star_finally(struct compiler *c, stmt_ty s) compiler_pop_fblock(c, FINALLY_TRY, body); VISIT_SEQ(c, stmt, s->v.TryStar.finalbody); - ADDOP_JUMP(c, NO_LOCATION, JUMP, exit); + ADDOP_JUMP(c, NO_LOCATION, JUMP_NO_INTERRUPT, exit); /* `finally` block */ USE_LABEL(c, end); @@ -3377,9 +3356,9 @@ compiler_try_star_finally(struct compiler *c, stmt_ty s) compiler_push_fblock(c, loc, FINALLY_END, end, NO_LABEL, NULL)); VISIT_SEQ(c, stmt, s->v.TryStar.finalbody); - loc = location_of_last_executing_statement(s->v.Try.finalbody); compiler_pop_fblock(c, FINALLY_END, end); + loc = NO_LOCATION; ADDOP_I(c, loc, RERAISE, 0); USE_LABEL(c, cleanup); @@ -3440,7 +3419,7 @@ compiler_try_except(struct compiler *c, stmt_ty s) if (s->v.Try.orelse && asdl_seq_LEN(s->v.Try.orelse)) { VISIT_SEQ(c, stmt, s->v.Try.orelse); } - ADDOP_JUMP(c, NO_LOCATION, JUMP, end); + ADDOP_JUMP(c, NO_LOCATION, JUMP_NO_INTERRUPT, end); n = asdl_seq_LEN(s->v.Try.handlers); USE_LABEL(c, except); @@ -3504,7 +3483,7 @@ compiler_try_except(struct compiler *c, stmt_ty s) compiler_nameop(c, NO_LOCATION, handler->v.ExceptHandler.name, Store)); RETURN_IF_ERROR( compiler_nameop(c, NO_LOCATION, handler->v.ExceptHandler.name, Del)); - ADDOP_JUMP(c, NO_LOCATION, JUMP, end); + ADDOP_JUMP(c, NO_LOCATION, JUMP_NO_INTERRUPT, end); /* except: */ USE_LABEL(c, cleanup_end); @@ -3532,7 +3511,7 @@ compiler_try_except(struct compiler *c, stmt_ty s) compiler_pop_fblock(c, HANDLER_CLEANUP, cleanup_body); ADDOP(c, NO_LOCATION, POP_BLOCK); ADDOP(c, NO_LOCATION, POP_EXCEPT); - ADDOP_JUMP(c, NO_LOCATION, JUMP, end); + ADDOP_JUMP(c, NO_LOCATION, JUMP_NO_INTERRUPT, end); } USE_LABEL(c, except); @@ -3620,7 +3599,7 @@ compiler_try_star_except(struct compiler *c, stmt_ty s) VISIT_SEQ(c, stmt, s->v.TryStar.body); compiler_pop_fblock(c, TRY_EXCEPT, body); ADDOP(c, NO_LOCATION, POP_BLOCK); - ADDOP_JUMP(c, NO_LOCATION, JUMP, orelse); + ADDOP_JUMP(c, NO_LOCATION, JUMP_NO_INTERRUPT, orelse); Py_ssize_t n = asdl_seq_LEN(s->v.TryStar.handlers); USE_LABEL(c, except); @@ -3702,7 +3681,7 @@ compiler_try_star_except(struct compiler *c, stmt_ty s) RETURN_IF_ERROR( compiler_nameop(c, NO_LOCATION, handler->v.ExceptHandler.name, Del)); } - ADDOP_JUMP(c, NO_LOCATION, JUMP, except); + ADDOP_JUMP(c, NO_LOCATION, JUMP_NO_INTERRUPT, except); /* except: */ USE_LABEL(c, cleanup_end); @@ -3719,11 +3698,11 @@ compiler_try_star_except(struct compiler *c, stmt_ty s) /* add exception raised to the res list */ ADDOP_I(c, NO_LOCATION, LIST_APPEND, 3); // exc ADDOP(c, NO_LOCATION, POP_TOP); // lasti - ADDOP_JUMP(c, NO_LOCATION, JUMP, except_with_error); + ADDOP_JUMP(c, NO_LOCATION, JUMP_NO_INTERRUPT, except_with_error); USE_LABEL(c, except); ADDOP(c, NO_LOCATION, NOP); // to hold a propagated location info - ADDOP_JUMP(c, NO_LOCATION, JUMP, except_with_error); + ADDOP_JUMP(c, NO_LOCATION, JUMP_NO_INTERRUPT, except_with_error); USE_LABEL(c, no_match); ADDOP(c, loc, POP_TOP); // match (None) @@ -3733,7 +3712,7 @@ compiler_try_star_except(struct compiler *c, stmt_ty s) if (i == n - 1) { /* Add exc to the list (if not None it's the unhandled part of the EG) */ ADDOP_I(c, NO_LOCATION, LIST_APPEND, 1); - ADDOP_JUMP(c, NO_LOCATION, JUMP, reraise_star); + ADDOP_JUMP(c, NO_LOCATION, JUMP_NO_INTERRUPT, reraise_star); } } /* artificial */ @@ -3749,7 +3728,7 @@ compiler_try_star_except(struct compiler *c, stmt_ty s) ADDOP(c, NO_LOCATION, POP_TOP); ADDOP(c, NO_LOCATION, POP_BLOCK); ADDOP(c, NO_LOCATION, POP_EXCEPT); - ADDOP_JUMP(c, NO_LOCATION, JUMP, end); + ADDOP_JUMP(c, NO_LOCATION, JUMP_NO_INTERRUPT, end); USE_LABEL(c, reraise); ADDOP(c, NO_LOCATION, POP_BLOCK); @@ -3957,7 +3936,7 @@ compiler_assert(struct compiler *c, stmt_ty s) VISIT(c, expr, s->v.Assert.msg); ADDOP_I(c, LOC(s), CALL, 0); } - ADDOP_I(c, LOC(s), RAISE_VARARGS, 1); + ADDOP_I(c, LOC(s->v.Assert.test), RAISE_VARARGS, 1); USE_LABEL(c, end); return SUCCESS; @@ -4158,7 +4137,7 @@ addop_yield(struct compiler *c, location loc) { ADDOP_I(c, loc, CALL_INTRINSIC_1, INTRINSIC_ASYNC_GEN_WRAP); } ADDOP_I(c, loc, YIELD_VALUE, 0); - ADDOP_I(c, loc, RESUME, 1); + ADDOP_I(c, loc, RESUME, RESUME_AFTER_YIELD); return SUCCESS; } @@ -4199,9 +4178,20 @@ compiler_nameop(struct compiler *c, location loc, optype = OP_DEREF; break; case LOCAL: - if (_PyST_IsFunctionLike(c->u->u_ste) || - (PyDict_GetItem(c->u->u_metadata.u_fasthidden, mangled) == Py_True)) + if (_PyST_IsFunctionLike(c->u->u_ste)) { optype = OP_FAST; + } + else { + PyObject *item; + if (PyDict_GetItemRef(c->u->u_metadata.u_fasthidden, mangled, + &item) < 0) { + goto error; + } + if (item == Py_True) { + optype = OP_FAST; + } + Py_XDECREF(item); + } break; case GLOBAL_IMPLICIT: if (_PyST_IsFunctionLike(c->u->u_ste)) @@ -4226,7 +4216,7 @@ compiler_nameop(struct compiler *c, location loc, op = LOAD_FROM_DICT_OR_DEREF; // First load the locals if (codegen_addop_noarg(INSTR_SEQUENCE(c), LOAD_LOCALS, loc) < 0) { - return ERROR; + goto error; } } else if (c->u->u_ste->ste_can_see_class_scope) { @@ -4234,7 +4224,7 @@ compiler_nameop(struct compiler *c, location loc, // First load the classdict if (compiler_addop_o(c->u, loc, LOAD_DEREF, c->u->u_metadata.u_freevars, &_Py_ID(__classdict__)) < 0) { - return ERROR; + goto error; } } else { @@ -4261,7 +4251,7 @@ compiler_nameop(struct compiler *c, location loc, // First load the classdict if (compiler_addop_o(c->u, loc, LOAD_DEREF, c->u->u_metadata.u_freevars, &_Py_ID(__classdict__)) < 0) { - return ERROR; + goto error; } } else { op = LOAD_GLOBAL; @@ -4295,6 +4285,10 @@ compiler_nameop(struct compiler *c, location loc, arg <<= 1; } return codegen_addop_i(INSTR_SEQUENCE(c), op, arg, loc); + +error: + Py_DECREF(mangled); + return ERROR; } static int @@ -4632,7 +4626,7 @@ compiler_compare(struct compiler *c, expr_ty e) VISIT(c, expr, (expr_ty)asdl_seq_GET(e->v.Compare.comparators, n)); ADDOP_COMPARE(c, loc, asdl_seq_GET(e->v.Compare.ops, n)); NEW_JUMP_TARGET_LABEL(c, end); - ADDOP_JUMP(c, NO_LOCATION, JUMP, end); + ADDOP_JUMP(c, NO_LOCATION, JUMP_NO_INTERRUPT, end); USE_LABEL(c, cleanup); ADDOP_I(c, loc, SWAP, 2); @@ -4838,7 +4832,7 @@ load_args_for_super(struct compiler *c, expr_ty e) { // load super() global PyObject *super_name = e->v.Call.func->v.Name.id; - RETURN_IF_ERROR(compiler_nameop(c, loc, super_name, Load)); + RETURN_IF_ERROR(compiler_nameop(c, LOC(e->v.Call.func), super_name, Load)); if (asdl_seq_LEN(e->v.Call.args) == 2) { VISIT(c, expr, asdl_seq_GET(e->v.Call.args, 0)); @@ -4952,9 +4946,13 @@ maybe_optimize_method_call(struct compiler *c, expr_ty e) VISIT_SEQ(c, keyword, kwds); RETURN_IF_ERROR( compiler_call_simple_kw_helper(c, loc, kwds, kwdsl)); + loc = update_start_location_to_match_attr(c, LOC(e), meth); + ADDOP_I(c, loc, CALL_KW, argsl + kwdsl); + } + else { + loc = update_start_location_to_match_attr(c, LOC(e), meth); + ADDOP_I(c, loc, CALL, argsl); } - loc = update_start_location_to_match_attr(c, LOC(e), meth); - ADDOP_I(c, loc, CALL, argsl + kwdsl); return 1; } @@ -4994,9 +4992,9 @@ compiler_call(struct compiler *c, expr_ty e) return SUCCESS; } RETURN_IF_ERROR(check_caller(c, e->v.Call.func)); + VISIT(c, expr, e->v.Call.func); location loc = LOC(e->v.Call.func); ADDOP(c, loc, PUSH_NULL); - VISIT(c, expr, e->v.Call.func); loc = LOC(e); return compiler_call_helper(c, loc, 0, e->v.Call.args, @@ -5021,8 +5019,12 @@ compiler_joined_str(struct compiler *c, expr_ty e) } else { VISIT_SEQ(c, expr, e->v.JoinedStr.values); - if (asdl_seq_LEN(e->v.JoinedStr.values) != 1) { - ADDOP_I(c, loc, BUILD_STRING, asdl_seq_LEN(e->v.JoinedStr.values)); + if (value_count > 1) { + ADDOP_I(c, loc, BUILD_STRING, value_count); + } + else if (value_count == 0) { + _Py_DECLARE_STR(empty, ""); + ADDOP_LOAD_CONST_NEW(c, loc, Py_NewRef(&_Py_STR(empty))); } } return SUCCESS; @@ -5120,7 +5122,7 @@ compiler_subkwargs(struct compiler *c, location loc, } /* Used by compiler_call_helper and maybe_optimize_method_call to emit - * KW_NAMES before CALL. + * a tuple of keyword names before CALL. */ static int compiler_call_simple_kw_helper(struct compiler *c, location loc, @@ -5135,12 +5137,7 @@ compiler_call_simple_kw_helper(struct compiler *c, location loc, keyword_ty kw = asdl_seq_GET(keywords, i); PyTuple_SET_ITEM(names, i, Py_NewRef(kw->arg)); } - Py_ssize_t arg = compiler_add_const(c->c_const_cache, c->u, names); - if (arg < 0) { - return ERROR; - } - Py_DECREF(names); - ADDOP_I(c, loc, KW_NAMES, arg); + ADDOP_LOAD_CONST_NEW(c, loc, names); return SUCCESS; } @@ -5185,8 +5182,11 @@ compiler_call_helper(struct compiler *c, location loc, VISIT_SEQ(c, keyword, keywords); RETURN_IF_ERROR( compiler_call_simple_kw_helper(c, loc, keywords, nkwelts)); + ADDOP_I(c, loc, CALL_KW, n + nelts + nkwelts); + } + else { + ADDOP_I(c, loc, CALL, n + nelts); } - ADDOP_I(c, loc, CALL, n + nelts + nkwelts); return SUCCESS; ex_call: @@ -5500,6 +5500,8 @@ typedef struct { PyObject *pushed_locals; PyObject *temp_symbols; PyObject *fast_hidden; + jump_target_label cleanup; + jump_target_label end; } inlined_comprehension_state; static int @@ -5523,8 +5525,13 @@ push_inlined_comprehension_state(struct compiler *c, location loc, if ((symbol & DEF_LOCAL && !(symbol & DEF_NONLOCAL)) || in_class_block) { if (!_PyST_IsFunctionLike(c->u->u_ste)) { // non-function scope: override this name to use fast locals - PyObject *orig = PyDict_GetItem(c->u->u_metadata.u_fasthidden, k); - if (orig != Py_True) { + PyObject *orig; + if (PyDict_GetItemRef(c->u->u_metadata.u_fasthidden, k, &orig) < 0) { + return ERROR; + } + int orig_is_true = (orig == Py_True); + Py_XDECREF(orig); + if (!orig_is_true) { if (PyDict_SetItem(c->u->u_metadata.u_fasthidden, k, Py_True) < 0) { return ERROR; } @@ -5605,11 +5612,45 @@ push_inlined_comprehension_state(struct compiler *c, location loc, // `pushed_locals` on the stack, but this will be reversed when we swap // out the comprehension result in pop_inlined_comprehension_state ADDOP_I(c, loc, SWAP, PyList_GET_SIZE(state->pushed_locals) + 1); + + // Add our own cleanup handler to restore comprehension locals in case + // of exception, so they have the correct values inside an exception + // handler or finally block. + NEW_JUMP_TARGET_LABEL(c, cleanup); + state->cleanup = cleanup; + NEW_JUMP_TARGET_LABEL(c, end); + state->end = end; + + // no need to push an fblock for this "virtual" try/finally; there can't + // be return/continue/break inside a comprehension + ADDOP_JUMP(c, loc, SETUP_FINALLY, cleanup); } return SUCCESS; } +static int +restore_inlined_comprehension_locals(struct compiler *c, location loc, + inlined_comprehension_state state) +{ + PyObject *k; + // pop names we pushed to stack earlier + Py_ssize_t npops = PyList_GET_SIZE(state.pushed_locals); + // Preserve the comprehension result (or exception) as TOS. This + // reverses the SWAP we did in push_inlined_comprehension_state to get + // the outermost iterable to TOS, so we can still just iterate + // pushed_locals in simple reverse order + ADDOP_I(c, loc, SWAP, npops + 1); + for (Py_ssize_t i = npops - 1; i >= 0; --i) { + k = PyList_GetItem(state.pushed_locals, i); + if (k == NULL) { + return ERROR; + } + ADDOP_NAME(c, loc, STORE_FAST_MAYBE_NULL, k, varnames); + } + return SUCCESS; +} + static int pop_inlined_comprehension_state(struct compiler *c, location loc, inlined_comprehension_state state) @@ -5626,19 +5667,22 @@ pop_inlined_comprehension_state(struct compiler *c, location loc, Py_CLEAR(state.temp_symbols); } if (state.pushed_locals) { - // pop names we pushed to stack earlier - Py_ssize_t npops = PyList_GET_SIZE(state.pushed_locals); - // Preserve the list/dict/set result of the comprehension as TOS. This - // reverses the SWAP we did in push_inlined_comprehension_state to get - // the outermost iterable to TOS, so we can still just iterate - // pushed_locals in simple reverse order - ADDOP_I(c, loc, SWAP, npops + 1); - for (Py_ssize_t i = npops - 1; i >= 0; --i) { - k = PyList_GetItem(state.pushed_locals, i); - if (k == NULL) { - return ERROR; - } - ADDOP_NAME(c, loc, STORE_FAST_MAYBE_NULL, k, varnames); + ADDOP(c, NO_LOCATION, POP_BLOCK); + ADDOP_JUMP(c, NO_LOCATION, JUMP_NO_INTERRUPT, state.end); + + // cleanup from an exception inside the comprehension + USE_LABEL(c, state.cleanup); + // discard incomplete comprehension result (beneath exc on stack) + ADDOP_I(c, NO_LOCATION, SWAP, 2); + ADDOP(c, NO_LOCATION, POP_TOP); + if (restore_inlined_comprehension_locals(c, loc, state) < 0) { + return ERROR; + } + ADDOP_I(c, NO_LOCATION, RERAISE, 0); + + USE_LABEL(c, state.end); + if (restore_inlined_comprehension_locals(c, loc, state) < 0) { + return ERROR; } Py_CLEAR(state.pushed_locals); } @@ -5681,7 +5725,7 @@ compiler_comprehension(struct compiler *c, expr_ty e, int type, expr_ty val) { PyCodeObject *co = NULL; - inlined_comprehension_state inline_state = {NULL, NULL}; + inlined_comprehension_state inline_state = {NULL, NULL, NULL, NO_LABEL, NO_LABEL}; comprehension_ty outermost; int scope_type = c->u->u_scope_type; int is_top_level_await = IS_TOP_LEVEL_AWAIT(c); @@ -5872,7 +5916,7 @@ compiler_with_except_finish(struct compiler *c, jump_target_label cleanup) { ADDOP(c, NO_LOCATION, POP_TOP); ADDOP(c, NO_LOCATION, POP_TOP); NEW_JUMP_TARGET_LABEL(c, exit); - ADDOP_JUMP(c, NO_LOCATION, JUMP, exit); + ADDOP_JUMP(c, NO_LOCATION, JUMP_NO_INTERRUPT, exit); USE_LABEL(c, cleanup); POP_EXCEPT_AND_RERAISE(c, NO_LOCATION); @@ -7366,7 +7410,7 @@ compiler_match_inner(struct compiler *c, stmt_ty s, pattern_context *pc) ADDOP(c, LOC(m->pattern), POP_TOP); } VISIT_SEQ(c, stmt, m->body); - ADDOP_JUMP(c, NO_LOCATION, JUMP, end); + ADDOP_JUMP(c, NO_LOCATION, JUMP_NO_INTERRUPT, end); // If the pattern fails to match, we want the line number of the // cleanup to be associated with the failed pattern, not the last line // of the body @@ -7493,201 +7537,6 @@ _PyCompile_ConstCacheMergeOne(PyObject *const_cache, PyObject **obj) return SUCCESS; } - -static int * -build_cellfixedoffsets(_PyCompile_CodeUnitMetadata *umd) -{ - int nlocals = (int)PyDict_GET_SIZE(umd->u_varnames); - int ncellvars = (int)PyDict_GET_SIZE(umd->u_cellvars); - int nfreevars = (int)PyDict_GET_SIZE(umd->u_freevars); - - int noffsets = ncellvars + nfreevars; - int *fixed = PyMem_New(int, noffsets); - if (fixed == NULL) { - PyErr_NoMemory(); - return NULL; - } - for (int i = 0; i < noffsets; i++) { - fixed[i] = nlocals + i; - } - - PyObject *varname, *cellindex; - Py_ssize_t pos = 0; - while (PyDict_Next(umd->u_cellvars, &pos, &varname, &cellindex)) { - PyObject *varindex = PyDict_GetItem(umd->u_varnames, varname); - if (varindex != NULL) { - assert(PyLong_AS_LONG(cellindex) < INT_MAX); - assert(PyLong_AS_LONG(varindex) < INT_MAX); - int oldindex = (int)PyLong_AS_LONG(cellindex); - int argoffset = (int)PyLong_AS_LONG(varindex); - fixed[oldindex] = argoffset; - } - } - - return fixed; -} - -#define IS_GENERATOR(CF) \ - ((CF) & (CO_GENERATOR | CO_COROUTINE | CO_ASYNC_GENERATOR)) - -static int -insert_prefix_instructions(_PyCompile_CodeUnitMetadata *umd, basicblock *entryblock, - int *fixed, int nfreevars, int code_flags) -{ - assert(umd->u_firstlineno > 0); - - /* Add the generator prefix instructions. */ - if (IS_GENERATOR(code_flags)) { - /* Note that RETURN_GENERATOR + POP_TOP have a net stack effect - * of 0. This is because RETURN_GENERATOR pushes an element - * with _PyFrame_StackPush before switching stacks. - */ - cfg_instr make_gen = { - .i_opcode = RETURN_GENERATOR, - .i_oparg = 0, - .i_loc = LOCATION(umd->u_firstlineno, umd->u_firstlineno, -1, -1), - .i_target = NULL, - }; - RETURN_IF_ERROR(_PyBasicblock_InsertInstruction(entryblock, 0, &make_gen)); - cfg_instr pop_top = { - .i_opcode = POP_TOP, - .i_oparg = 0, - .i_loc = NO_LOCATION, - .i_target = NULL, - }; - RETURN_IF_ERROR(_PyBasicblock_InsertInstruction(entryblock, 1, &pop_top)); - } - - /* Set up cells for any variable that escapes, to be put in a closure. */ - const int ncellvars = (int)PyDict_GET_SIZE(umd->u_cellvars); - if (ncellvars) { - // umd->u_cellvars has the cells out of order so we sort them - // before adding the MAKE_CELL instructions. Note that we - // adjust for arg cells, which come first. - const int nvars = ncellvars + (int)PyDict_GET_SIZE(umd->u_varnames); - int *sorted = PyMem_RawCalloc(nvars, sizeof(int)); - if (sorted == NULL) { - PyErr_NoMemory(); - return ERROR; - } - for (int i = 0; i < ncellvars; i++) { - sorted[fixed[i]] = i + 1; - } - for (int i = 0, ncellsused = 0; ncellsused < ncellvars; i++) { - int oldindex = sorted[i] - 1; - if (oldindex == -1) { - continue; - } - cfg_instr make_cell = { - .i_opcode = MAKE_CELL, - // This will get fixed in offset_derefs(). - .i_oparg = oldindex, - .i_loc = NO_LOCATION, - .i_target = NULL, - }; - if (_PyBasicblock_InsertInstruction(entryblock, ncellsused, &make_cell) < 0) { - PyMem_RawFree(sorted); - return ERROR; - } - ncellsused += 1; - } - PyMem_RawFree(sorted); - } - - if (nfreevars) { - cfg_instr copy_frees = { - .i_opcode = COPY_FREE_VARS, - .i_oparg = nfreevars, - .i_loc = NO_LOCATION, - .i_target = NULL, - }; - RETURN_IF_ERROR(_PyBasicblock_InsertInstruction(entryblock, 0, ©_frees)); - } - - return SUCCESS; -} - -static int -fix_cell_offsets(_PyCompile_CodeUnitMetadata *umd, basicblock *entryblock, int *fixedmap) -{ - int nlocals = (int)PyDict_GET_SIZE(umd->u_varnames); - int ncellvars = (int)PyDict_GET_SIZE(umd->u_cellvars); - int nfreevars = (int)PyDict_GET_SIZE(umd->u_freevars); - int noffsets = ncellvars + nfreevars; - - // First deal with duplicates (arg cells). - int numdropped = 0; - for (int i = 0; i < noffsets ; i++) { - if (fixedmap[i] == i + nlocals) { - fixedmap[i] -= numdropped; - } - else { - // It was a duplicate (cell/arg). - numdropped += 1; - } - } - - // Then update offsets, either relative to locals or by cell2arg. - for (basicblock *b = entryblock; b != NULL; b = b->b_next) { - for (int i = 0; i < b->b_iused; i++) { - cfg_instr *inst = &b->b_instr[i]; - // This is called before extended args are generated. - assert(inst->i_opcode != EXTENDED_ARG); - int oldoffset = inst->i_oparg; - switch(inst->i_opcode) { - case MAKE_CELL: - case LOAD_CLOSURE: - case LOAD_DEREF: - case STORE_DEREF: - case DELETE_DEREF: - case LOAD_FROM_DICT_OR_DEREF: - assert(oldoffset >= 0); - assert(oldoffset < noffsets); - assert(fixedmap[oldoffset] >= 0); - inst->i_oparg = fixedmap[oldoffset]; - } - } - } - - return numdropped; -} - - -static int -prepare_localsplus(_PyCompile_CodeUnitMetadata *umd, cfg_builder *g, int code_flags) -{ - assert(PyDict_GET_SIZE(umd->u_varnames) < INT_MAX); - assert(PyDict_GET_SIZE(umd->u_cellvars) < INT_MAX); - assert(PyDict_GET_SIZE(umd->u_freevars) < INT_MAX); - int nlocals = (int)PyDict_GET_SIZE(umd->u_varnames); - int ncellvars = (int)PyDict_GET_SIZE(umd->u_cellvars); - int nfreevars = (int)PyDict_GET_SIZE(umd->u_freevars); - assert(INT_MAX - nlocals - ncellvars > 0); - assert(INT_MAX - nlocals - ncellvars - nfreevars > 0); - int nlocalsplus = nlocals + ncellvars + nfreevars; - int* cellfixedoffsets = build_cellfixedoffsets(umd); - if (cellfixedoffsets == NULL) { - return ERROR; - } - - - // This must be called before fix_cell_offsets(). - if (insert_prefix_instructions(umd, g->g_entryblock, cellfixedoffsets, nfreevars, code_flags)) { - PyMem_Free(cellfixedoffsets); - return ERROR; - } - - int numdropped = fix_cell_offsets(umd, g->g_entryblock, cellfixedoffsets); - PyMem_Free(cellfixedoffsets); // At this point we're done with it. - cellfixedoffsets = NULL; - if (numdropped < 0) { - return ERROR; - } - - nlocalsplus -= numdropped; - return nlocalsplus; -} - static int add_return_at_end(struct compiler *c, int addNone) { @@ -7701,12 +7550,11 @@ add_return_at_end(struct compiler *c, int addNone) return SUCCESS; } -static int cfg_to_instr_sequence(cfg_builder *g, instr_sequence *seq); - static PyCodeObject * optimize_and_assemble_code_unit(struct compiler_unit *u, PyObject *const_cache, int code_flags, PyObject *filename) { + cfg_builder *g = NULL; instr_sequence optimized_instrs; memset(&optimized_instrs, 0, sizeof(instr_sequence)); @@ -7715,51 +7563,28 @@ optimize_and_assemble_code_unit(struct compiler_unit *u, PyObject *const_cache, if (consts == NULL) { goto error; } - cfg_builder g; - if (instr_sequence_to_cfg(&u->u_instr_sequence, &g) < 0) { + g = instr_sequence_to_cfg(&u->u_instr_sequence); + if (g == NULL) { goto error; } - int nparams = (int)PyList_GET_SIZE(u->u_ste->ste_varnames); int nlocals = (int)PyDict_GET_SIZE(u->u_metadata.u_varnames); + int nparams = (int)PyList_GET_SIZE(u->u_ste->ste_varnames); assert(u->u_metadata.u_firstlineno); - if (_PyCfg_OptimizeCodeUnit(&g, consts, const_cache, nlocals, + + if (_PyCfg_OptimizeCodeUnit(g, consts, const_cache, nlocals, nparams, u->u_metadata.u_firstlineno) < 0) { goto error; } - int stackdepth = _PyCfg_Stackdepth(&g); - if (stackdepth < 0) { + int stackdepth; + int nlocalsplus; + if (_PyCfg_OptimizedCfgToInstructionSequence(g, &u->u_metadata, code_flags, + &stackdepth, &nlocalsplus, + &optimized_instrs) < 0) { goto error; } - /* prepare_localsplus adds instructions for generators that push - * and pop an item on the stack. This assertion makes sure there - * is space on the stack for that. - * It should always be true, because a generator must have at - * least one expression or call to INTRINSIC_STOPITERATION_ERROR, - * which requires stackspace. - */ - assert(!(IS_GENERATOR(code_flags) && stackdepth == 0)); - /** Assembly **/ - int nlocalsplus = prepare_localsplus(&u->u_metadata, &g, code_flags); - if (nlocalsplus < 0) { - goto error; - } - - _PyCfg_ConvertPseudoOps(g.g_entryblock); - - /* Order of basic blocks must have been determined by now */ - - if (_PyCfg_ResolveJumps(&g) < 0) { - goto error; - } - - /* Can't modify the bytecode after computing jump offsets. */ - - if (cfg_to_instr_sequence(&g, &optimized_instrs) < 0) { - goto error; - } co = _PyAssemble_MakeCodeObject(&u->u_metadata, const_cache, consts, stackdepth, &optimized_instrs, nlocalsplus, @@ -7768,7 +7593,7 @@ optimize_and_assemble_code_unit(struct compiler_unit *u, PyObject *const_cache, error: Py_XDECREF(consts); instr_sequence_fini(&optimized_instrs); - _PyCfgBuilder_Fini(&g); + _PyCfgBuilder_Free(g); return co; } @@ -7791,39 +7616,6 @@ optimize_and_assemble(struct compiler *c, int addNone) return optimize_and_assemble_code_unit(u, const_cache, code_flags, filename); } -static int -cfg_to_instr_sequence(cfg_builder *g, instr_sequence *seq) -{ - int lbl = 0; - for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) { - b->b_label = (jump_target_label){lbl}; - lbl += b->b_iused; - } - for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) { - RETURN_IF_ERROR(instr_sequence_use_label(seq, b->b_label.id)); - for (int i = 0; i < b->b_iused; i++) { - cfg_instr *instr = &b->b_instr[i]; - if (OPCODE_HAS_JUMP(instr->i_opcode)) { - instr->i_oparg = instr->i_target->b_label.id; - } - RETURN_IF_ERROR( - instr_sequence_addop(seq, instr->i_opcode, instr->i_oparg, instr->i_loc)); - - _PyCompile_ExceptHandlerInfo *hi = &seq->s_instrs[seq->s_used-1].i_except_handler_info; - if (instr->i_except != NULL) { - hi->h_label = instr->i_except->b_label.id; - hi->h_startdepth = instr->i_except->b_startdepth; - hi->h_preserve_lasti = instr->i_except->b_preserve_lasti; - } - else { - hi->h_label = -1; - } - } - } - return SUCCESS; -} - - /* Access to compiler optimizations for unit tests. * * _PyCompile_CodeGen takes and AST, applies code-gen and @@ -7873,7 +7665,7 @@ instructions_to_instr_sequence(PyObject *instructions, instr_sequence *seq) for (int i = 0; i < num_insts; i++) { if (is_target[i]) { - if (instr_sequence_use_label(seq, i) < 0) { + if (_PyCompile_InstructionSequence_UseLabel(seq, i) < 0) { goto error; } } @@ -7913,7 +7705,7 @@ instructions_to_instr_sequence(PyObject *instructions, instr_sequence *seq) if (PyErr_Occurred()) { goto error; } - if (instr_sequence_addop(seq, opcode, oparg, loc) < 0) { + if (_PyCompile_InstructionSequence_Addop(seq, opcode, oparg, loc) < 0) { goto error; } } @@ -7924,23 +7716,26 @@ instructions_to_instr_sequence(PyObject *instructions, instr_sequence *seq) return ERROR; } -static int -instructions_to_cfg(PyObject *instructions, cfg_builder *g) +static cfg_builder* +instructions_to_cfg(PyObject *instructions) { + cfg_builder *g = NULL; instr_sequence seq; memset(&seq, 0, sizeof(instr_sequence)); if (instructions_to_instr_sequence(instructions, &seq) < 0) { goto error; } - if (instr_sequence_to_cfg(&seq, g) < 0) { + g = instr_sequence_to_cfg(&seq); + if (g == NULL) { goto error; } instr_sequence_fini(&seq); - return SUCCESS; + return g; error: + _PyCfgBuilder_Free(g); instr_sequence_fini(&seq); - return ERROR; + return NULL; } static PyObject * @@ -7979,42 +7774,14 @@ instr_sequence_to_instructions(instr_sequence *seq) static PyObject * cfg_to_instructions(cfg_builder *g) { - PyObject *instructions = PyList_New(0); - if (instructions == NULL) { + instr_sequence seq; + memset(&seq, 0, sizeof(seq)); + if (_PyCfg_ToInstructionSequence(g, &seq) < 0) { return NULL; } - int lbl = 0; - for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) { - b->b_label = (jump_target_label){lbl}; - lbl += b->b_iused; - } - for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) { - for (int i = 0; i < b->b_iused; i++) { - cfg_instr *instr = &b->b_instr[i]; - location loc = instr->i_loc; - int arg = HAS_TARGET(instr->i_opcode) ? - instr->i_target->b_label.id : 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 *res = instr_sequence_to_instructions(&seq); + instr_sequence_fini(&seq); + return res; } // C implementation of inspect.cleandoc() @@ -8196,34 +7963,36 @@ _PyCompile_CodeGen(PyObject *ast, PyObject *filename, PyCompilerFlags *pflags, PyObject * _PyCompile_OptimizeCfg(PyObject *instructions, PyObject *consts, int nlocals) { + cfg_builder *g = NULL; PyObject *res = NULL; PyObject *const_cache = PyDict_New(); if (const_cache == NULL) { return NULL; } - cfg_builder g; - if (instructions_to_cfg(instructions, &g) < 0) { + g = instructions_to_cfg(instructions); + if (g == NULL) { goto error; } int nparams = 0, firstlineno = 1; - if (_PyCfg_OptimizeCodeUnit(&g, consts, const_cache, nlocals, + if (_PyCfg_OptimizeCodeUnit(g, consts, const_cache, nlocals, nparams, firstlineno) < 0) { goto error; } - res = cfg_to_instructions(&g); + res = cfg_to_instructions(g); error: Py_DECREF(const_cache); - _PyCfgBuilder_Fini(&g); + _PyCfgBuilder_Free(g); return res; } -int _PyCfg_JumpLabelsToTargets(basicblock *entryblock); +int _PyCfg_JumpLabelsToTargets(cfg_builder *g); PyCodeObject * _PyCompile_Assemble(_PyCompile_CodeUnitMetadata *umd, PyObject *filename, PyObject *instructions) { + cfg_builder *g = NULL; PyCodeObject *co = NULL; instr_sequence optimized_instrs; memset(&optimized_instrs, 0, sizeof(instr_sequence)); @@ -8233,37 +8002,20 @@ _PyCompile_Assemble(_PyCompile_CodeUnitMetadata *umd, PyObject *filename, return NULL; } - cfg_builder g; - if (instructions_to_cfg(instructions, &g) < 0) { - goto error; - } - - if (_PyCfg_JumpLabelsToTargets(g.g_entryblock) < 0) { + g = instructions_to_cfg(instructions); + if (g == NULL) { goto error; } - int stackdepth = _PyCfg_Stackdepth(&g); - if (stackdepth < 0) { + if (_PyCfg_JumpLabelsToTargets(g) < 0) { goto error; } int code_flags = 0; - int nlocalsplus = prepare_localsplus(umd, &g, code_flags); - if (nlocalsplus < 0) { - goto error; - } - - _PyCfg_ConvertPseudoOps(g.g_entryblock); - - /* Order of basic blocks must have been determined by now */ - - if (_PyCfg_ResolveJumps(&g) < 0) { - goto error; - } - - /* Can't modify the bytecode after computing jump offsets. */ - - if (cfg_to_instr_sequence(&g, &optimized_instrs) < 0) { + int stackdepth, nlocalsplus; + if (_PyCfg_OptimizedCfgToInstructionSequence(g, umd, code_flags, + &stackdepth, &nlocalsplus, + &optimized_instrs) < 0) { goto error; } @@ -8278,7 +8030,7 @@ _PyCompile_Assemble(_PyCompile_CodeUnitMetadata *umd, PyObject *filename, error: Py_DECREF(const_cache); - _PyCfgBuilder_Fini(&g); + _PyCfgBuilder_Free(g); instr_sequence_fini(&optimized_instrs); return co; } diff --git a/Python/condvar.h b/Python/condvar.h index 4ddc5311cf8fad..d54db94f2c871d 100644 --- a/Python/condvar.h +++ b/Python/condvar.h @@ -41,7 +41,8 @@ #define _CONDVAR_IMPL_H_ #include "Python.h" -#include "pycore_condvar.h" +#include "pycore_pythread.h" // _POSIX_THREADS + #ifdef _POSIX_THREADS /* diff --git a/Python/critical_section.c b/Python/critical_section.c new file mode 100644 index 00000000000000..2214d80eeb297b --- /dev/null +++ b/Python/critical_section.c @@ -0,0 +1,100 @@ +#include "Python.h" + +#include "pycore_lock.h" +#include "pycore_critical_section.h" + +static_assert(_Alignof(_PyCriticalSection) >= 4, + "critical section must be aligned to at least 4 bytes"); + +void +_PyCriticalSection_BeginSlow(_PyCriticalSection *c, PyMutex *m) +{ + PyThreadState *tstate = _PyThreadState_GET(); + c->mutex = NULL; + c->prev = (uintptr_t)tstate->critical_section; + tstate->critical_section = (uintptr_t)c; + + _PyMutex_LockSlow(m); + c->mutex = m; +} + +void +_PyCriticalSection2_BeginSlow(_PyCriticalSection2 *c, PyMutex *m1, PyMutex *m2, + int is_m1_locked) +{ + PyThreadState *tstate = _PyThreadState_GET(); + c->base.mutex = NULL; + c->mutex2 = NULL; + c->base.prev = tstate->critical_section; + tstate->critical_section = (uintptr_t)c | _Py_CRITICAL_SECTION_TWO_MUTEXES; + + if (!is_m1_locked) { + PyMutex_Lock(m1); + } + PyMutex_Lock(m2); + c->base.mutex = m1; + c->mutex2 = m2; +} + +static _PyCriticalSection * +untag_critical_section(uintptr_t tag) +{ + return (_PyCriticalSection *)(tag & ~_Py_CRITICAL_SECTION_MASK); +} + +// Release all locks held by critical sections. This is called by +// _PyThreadState_Detach. +void +_PyCriticalSection_SuspendAll(PyThreadState *tstate) +{ + uintptr_t *tagptr = &tstate->critical_section; + while (_PyCriticalSection_IsActive(*tagptr)) { + _PyCriticalSection *c = untag_critical_section(*tagptr); + + if (c->mutex) { + PyMutex_Unlock(c->mutex); + if ((*tagptr & _Py_CRITICAL_SECTION_TWO_MUTEXES)) { + _PyCriticalSection2 *c2 = (_PyCriticalSection2 *)c; + if (c2->mutex2) { + PyMutex_Unlock(c2->mutex2); + } + } + } + + *tagptr |= _Py_CRITICAL_SECTION_INACTIVE; + tagptr = &c->prev; + } +} + +void +_PyCriticalSection_Resume(PyThreadState *tstate) +{ + uintptr_t p = tstate->critical_section; + _PyCriticalSection *c = untag_critical_section(p); + assert(!_PyCriticalSection_IsActive(p)); + + PyMutex *m1 = c->mutex; + c->mutex = NULL; + + PyMutex *m2 = NULL; + _PyCriticalSection2 *c2 = NULL; + if ((p & _Py_CRITICAL_SECTION_TWO_MUTEXES)) { + c2 = (_PyCriticalSection2 *)c; + m2 = c2->mutex2; + c2->mutex2 = NULL; + } + + if (m1) { + PyMutex_Lock(m1); + } + if (m2) { + PyMutex_Lock(m2); + } + + c->mutex = m1; + if (m2) { + c2->mutex2 = m2; + } + + tstate->critical_section &= ~_Py_CRITICAL_SECTION_INACTIVE; +} diff --git a/Python/crossinterp.c b/Python/crossinterp.c new file mode 100644 index 00000000000000..c6ed7daeb1074a --- /dev/null +++ b/Python/crossinterp.c @@ -0,0 +1,2294 @@ + +/* API for managing interactions between isolated interpreters */ + +#include "Python.h" +#include "pycore_ceval.h" // _Py_simple_func +#include "pycore_crossinterp.h" // struct _xid +#include "pycore_initconfig.h" // _PyStatus_OK() +#include "pycore_namespace.h" //_PyNamespace_New() +#include "pycore_pyerrors.h" // _PyErr_Clear() +#include "pycore_pystate.h" // _PyInterpreterState_GET() +#include "pycore_typeobject.h" // _PyType_GetModuleName() +#include "pycore_weakref.h" // _PyWeakref_GET_REF() + + +/**************/ +/* exceptions */ +/**************/ + +/* InterpreterError extends Exception */ + +static PyTypeObject _PyExc_InterpreterError = { + PyVarObject_HEAD_INIT(NULL, 0) + .tp_name = "InterpreterError", + .tp_doc = PyDoc_STR("An interpreter was not found."), + //.tp_base = (PyTypeObject *)PyExc_BaseException, +}; +PyObject *PyExc_InterpreterError = (PyObject *)&_PyExc_InterpreterError; + +/* InterpreterNotFoundError extends InterpreterError */ + +static PyTypeObject _PyExc_InterpreterNotFoundError = { + PyVarObject_HEAD_INIT(NULL, 0) + .tp_name = "InterpreterNotFoundError", + .tp_doc = PyDoc_STR("An interpreter was not found."), + .tp_base = &_PyExc_InterpreterError, +}; +PyObject *PyExc_InterpreterNotFoundError = (PyObject *)&_PyExc_InterpreterNotFoundError; + +/* lifecycle */ + +static int +init_exceptions(PyInterpreterState *interp) +{ + _PyExc_InterpreterError.tp_base = (PyTypeObject *)PyExc_BaseException; + if (_PyStaticType_InitBuiltin(interp, &_PyExc_InterpreterError) < 0) { + return -1; + } + if (_PyStaticType_InitBuiltin(interp, &_PyExc_InterpreterNotFoundError) < 0) { + return -1; + } + return 0; +} + +static void +fini_exceptions(PyInterpreterState *interp) +{ + _PyStaticType_Dealloc(interp, &_PyExc_InterpreterNotFoundError); + _PyStaticType_Dealloc(interp, &_PyExc_InterpreterError); +} + + +/***************************/ +/* cross-interpreter calls */ +/***************************/ + +int +_Py_CallInInterpreter(PyInterpreterState *interp, + _Py_simple_func func, void *arg) +{ + if (interp == _PyThreadState_GetCurrent()->interp) { + return func(arg); + } + // XXX Emit a warning if this fails? + _PyEval_AddPendingCall(interp, (_Py_pending_call_func)func, arg, 0); + return 0; +} + +int +_Py_CallInInterpreterAndRawFree(PyInterpreterState *interp, + _Py_simple_func func, void *arg) +{ + if (interp == _PyThreadState_GetCurrent()->interp) { + int res = func(arg); + PyMem_RawFree(arg); + return res; + } + // XXX Emit a warning if this fails? + _PyEval_AddPendingCall(interp, func, arg, _Py_PENDING_RAWFREE); + return 0; +} + + +/**************************/ +/* cross-interpreter data */ +/**************************/ + +_PyCrossInterpreterData * +_PyCrossInterpreterData_New(void) +{ + _PyCrossInterpreterData *xid = PyMem_RawMalloc( + sizeof(_PyCrossInterpreterData)); + if (xid == NULL) { + PyErr_NoMemory(); + } + return xid; +} + +void +_PyCrossInterpreterData_Free(_PyCrossInterpreterData *xid) +{ + PyInterpreterState *interp = PyInterpreterState_Get(); + _PyCrossInterpreterData_Clear(interp, xid); + PyMem_RawFree(xid); +} + + +/* exceptions */ + +static PyStatus +_init_not_shareable_error_type(PyInterpreterState *interp) +{ + const char *name = "_interpreters.NotShareableError"; + PyObject *base = PyExc_ValueError; + PyObject *ns = NULL; + PyObject *exctype = PyErr_NewException(name, base, ns); + if (exctype == NULL) { + PyErr_Clear(); + return _PyStatus_ERR("could not initialize NotShareableError"); + } + + interp->xi.PyExc_NotShareableError = exctype; + return _PyStatus_OK(); +} + +static void +_fini_not_shareable_error_type(PyInterpreterState *interp) +{ + Py_CLEAR(interp->xi.PyExc_NotShareableError); +} + +static PyObject * +_get_not_shareable_error_type(PyInterpreterState *interp) +{ + assert(interp->xi.PyExc_NotShareableError != NULL); + return interp->xi.PyExc_NotShareableError; +} + + +/* defining cross-interpreter data */ + +static inline void +_xidata_init(_PyCrossInterpreterData *data) +{ + // If the value is being reused + // then _xidata_clear() should have been called already. + assert(data->data == NULL); + assert(data->obj == NULL); + *data = (_PyCrossInterpreterData){0}; + data->interpid = -1; +} + +static inline void +_xidata_clear(_PyCrossInterpreterData *data) +{ + // _PyCrossInterpreterData only has two members that need to be + // cleaned up, if set: "data" must be freed and "obj" must be decref'ed. + // In both cases the original (owning) interpreter must be used, + // which is the caller's responsibility to ensure. + if (data->data != NULL) { + if (data->free != NULL) { + data->free(data->data); + } + data->data = NULL; + } + Py_CLEAR(data->obj); +} + +void +_PyCrossInterpreterData_Init(_PyCrossInterpreterData *data, + PyInterpreterState *interp, + void *shared, PyObject *obj, + xid_newobjectfunc new_object) +{ + assert(data != NULL); + assert(new_object != NULL); + _xidata_init(data); + data->data = shared; + if (obj != NULL) { + assert(interp != NULL); + // released in _PyCrossInterpreterData_Clear() + data->obj = Py_NewRef(obj); + } + // Ideally every object would know its owning interpreter. + // Until then, we have to rely on the caller to identify it + // (but we don't need it in all cases). + data->interpid = (interp != NULL) ? interp->id : -1; + data->new_object = new_object; +} + +int +_PyCrossInterpreterData_InitWithSize(_PyCrossInterpreterData *data, + PyInterpreterState *interp, + const size_t size, PyObject *obj, + xid_newobjectfunc new_object) +{ + assert(size > 0); + // For now we always free the shared data in the same interpreter + // where it was allocated, so the interpreter is required. + assert(interp != NULL); + _PyCrossInterpreterData_Init(data, interp, NULL, obj, new_object); + data->data = PyMem_RawMalloc(size); + if (data->data == NULL) { + return -1; + } + data->free = PyMem_RawFree; + return 0; +} + +void +_PyCrossInterpreterData_Clear(PyInterpreterState *interp, + _PyCrossInterpreterData *data) +{ + assert(data != NULL); + // This must be called in the owning interpreter. + assert(interp == NULL + || data->interpid == -1 + || data->interpid == interp->id); + _xidata_clear(data); +} + + +/* using cross-interpreter data */ + +static int +_check_xidata(PyThreadState *tstate, _PyCrossInterpreterData *data) +{ + // data->data can be anything, including NULL, so we don't check it. + + // data->obj may be NULL, so we don't check it. + + if (data->interpid < 0) { + _PyErr_SetString(tstate, PyExc_SystemError, "missing interp"); + return -1; + } + + if (data->new_object == NULL) { + _PyErr_SetString(tstate, PyExc_SystemError, "missing new_object func"); + return -1; + } + + // data->free may be NULL, so we don't check it. + + return 0; +} + +static crossinterpdatafunc _lookup_getdata_from_registry( + PyInterpreterState *, PyObject *); + +static crossinterpdatafunc +_lookup_getdata(PyInterpreterState *interp, PyObject *obj) +{ + /* Cross-interpreter objects are looked up by exact match on the class. + We can reassess this policy when we move from a global registry to a + tp_* slot. */ + return _lookup_getdata_from_registry(interp, obj); +} + +crossinterpdatafunc +_PyCrossInterpreterData_Lookup(PyObject *obj) +{ + PyInterpreterState *interp = _PyInterpreterState_GET(); + return _lookup_getdata(interp, obj); +} + +static inline void +_set_xid_lookup_failure(PyInterpreterState *interp, + PyObject *obj, const char *msg) +{ + PyObject *exctype = _get_not_shareable_error_type(interp); + assert(exctype != NULL); + if (msg != NULL) { + assert(obj == NULL); + PyErr_SetString(exctype, msg); + } + else if (obj == NULL) { + PyErr_SetString(exctype, + "object does not support cross-interpreter data"); + } + else { + PyErr_Format(exctype, + "%S does not support cross-interpreter data", obj); + } +} + +int +_PyObject_CheckCrossInterpreterData(PyObject *obj) +{ + PyInterpreterState *interp = _PyInterpreterState_GET(); + crossinterpdatafunc getdata = _lookup_getdata(interp, obj); + if (getdata == NULL) { + if (!PyErr_Occurred()) { + _set_xid_lookup_failure(interp, obj, NULL); + } + return -1; + } + return 0; +} + +int +_PyObject_GetCrossInterpreterData(PyObject *obj, _PyCrossInterpreterData *data) +{ + PyThreadState *tstate = _PyThreadState_GetCurrent(); +#ifdef Py_DEBUG + // The caller must hold the GIL + _Py_EnsureTstateNotNULL(tstate); +#endif + PyInterpreterState *interp = tstate->interp; + + // Reset data before re-populating. + *data = (_PyCrossInterpreterData){0}; + data->interpid = -1; + + // Call the "getdata" func for the object. + Py_INCREF(obj); + crossinterpdatafunc getdata = _lookup_getdata(interp, obj); + if (getdata == NULL) { + Py_DECREF(obj); + if (!PyErr_Occurred()) { + _set_xid_lookup_failure(interp, obj, NULL); + } + return -1; + } + int res = getdata(tstate, obj, data); + Py_DECREF(obj); + if (res != 0) { + return -1; + } + + // Fill in the blanks and validate the result. + data->interpid = interp->id; + if (_check_xidata(tstate, data) != 0) { + (void)_PyCrossInterpreterData_Release(data); + return -1; + } + + return 0; +} + +PyObject * +_PyCrossInterpreterData_NewObject(_PyCrossInterpreterData *data) +{ + return data->new_object(data); +} + +static int +_call_clear_xidata(void *data) +{ + _xidata_clear((_PyCrossInterpreterData *)data); + return 0; +} + +static int +_xidata_release(_PyCrossInterpreterData *data, int rawfree) +{ + if ((data->data == NULL || data->free == NULL) && data->obj == NULL) { + // Nothing to release! + if (rawfree) { + PyMem_RawFree(data); + } + else { + data->data = NULL; + } + return 0; + } + + // Switch to the original interpreter. + PyInterpreterState *interp = _PyInterpreterState_LookUpID(data->interpid); + if (interp == NULL) { + // The interpreter was already destroyed. + // This function shouldn't have been called. + // XXX Someone leaked some memory... + assert(PyErr_Occurred()); + if (rawfree) { + PyMem_RawFree(data); + } + return -1; + } + + // "Release" the data and/or the object. + if (rawfree) { + return _Py_CallInInterpreterAndRawFree(interp, _call_clear_xidata, data); + } + else { + return _Py_CallInInterpreter(interp, _call_clear_xidata, data); + } +} + +int +_PyCrossInterpreterData_Release(_PyCrossInterpreterData *data) +{ + return _xidata_release(data, 0); +} + +int +_PyCrossInterpreterData_ReleaseAndRawFree(_PyCrossInterpreterData *data) +{ + return _xidata_release(data, 1); +} + + +/* registry of {type -> crossinterpdatafunc} */ + +/* For now we use a global registry of shareable classes. An + alternative would be to add a tp_* slot for a class's + crossinterpdatafunc. It would be simpler and more efficient. */ + +static inline struct _xidregistry * +_get_global_xidregistry(_PyRuntimeState *runtime) +{ + return &runtime->xi.registry; +} + +static inline struct _xidregistry * +_get_xidregistry(PyInterpreterState *interp) +{ + return &interp->xi.registry; +} + +static inline struct _xidregistry * +_get_xidregistry_for_type(PyInterpreterState *interp, PyTypeObject *cls) +{ + struct _xidregistry *registry = _get_global_xidregistry(interp->runtime); + if (cls->tp_flags & Py_TPFLAGS_HEAPTYPE) { + registry = _get_xidregistry(interp); + } + return registry; +} + +static int +_xidregistry_add_type(struct _xidregistry *xidregistry, + PyTypeObject *cls, crossinterpdatafunc getdata) +{ + struct _xidregitem *newhead = PyMem_RawMalloc(sizeof(struct _xidregitem)); + if (newhead == NULL) { + return -1; + } + *newhead = (struct _xidregitem){ + // We do not keep a reference, to avoid keeping the class alive. + .cls = cls, + .refcount = 1, + .getdata = getdata, + }; + if (cls->tp_flags & Py_TPFLAGS_HEAPTYPE) { + // XXX Assign a callback to clear the entry from the registry? + newhead->weakref = PyWeakref_NewRef((PyObject *)cls, NULL); + if (newhead->weakref == NULL) { + PyMem_RawFree(newhead); + return -1; + } + } + newhead->next = xidregistry->head; + if (newhead->next != NULL) { + newhead->next->prev = newhead; + } + xidregistry->head = newhead; + return 0; +} + +static struct _xidregitem * +_xidregistry_remove_entry(struct _xidregistry *xidregistry, + struct _xidregitem *entry) +{ + struct _xidregitem *next = entry->next; + if (entry->prev != NULL) { + assert(entry->prev->next == entry); + entry->prev->next = next; + } + else { + assert(xidregistry->head == entry); + xidregistry->head = next; + } + if (next != NULL) { + next->prev = entry->prev; + } + Py_XDECREF(entry->weakref); + PyMem_RawFree(entry); + return next; +} + +static void +_xidregistry_clear(struct _xidregistry *xidregistry) +{ + struct _xidregitem *cur = xidregistry->head; + xidregistry->head = NULL; + while (cur != NULL) { + struct _xidregitem *next = cur->next; + Py_XDECREF(cur->weakref); + PyMem_RawFree(cur); + cur = next; + } +} + +static void +_xidregistry_lock(struct _xidregistry *registry) +{ + if (registry->global) { + PyMutex_Lock(®istry->mutex); + } + // else: Within an interpreter we rely on the GIL instead of a separate lock. +} + +static void +_xidregistry_unlock(struct _xidregistry *registry) +{ + if (registry->global) { + PyMutex_Unlock(®istry->mutex); + } +} + +static struct _xidregitem * +_xidregistry_find_type(struct _xidregistry *xidregistry, PyTypeObject *cls) +{ + struct _xidregitem *cur = xidregistry->head; + while (cur != NULL) { + if (cur->weakref != NULL) { + // cur is/was a heap type. + PyObject *registered = _PyWeakref_GET_REF(cur->weakref); + if (registered == NULL) { + // The weakly ref'ed object was freed. + cur = _xidregistry_remove_entry(xidregistry, cur); + continue; + } + assert(PyType_Check(registered)); + assert(cur->cls == (PyTypeObject *)registered); + assert(cur->cls->tp_flags & Py_TPFLAGS_HEAPTYPE); + Py_DECREF(registered); + } + if (cur->cls == cls) { + return cur; + } + cur = cur->next; + } + return NULL; +} + +int +_PyCrossInterpreterData_RegisterClass(PyTypeObject *cls, + crossinterpdatafunc getdata) +{ + if (!PyType_Check(cls)) { + PyErr_Format(PyExc_ValueError, "only classes may be registered"); + return -1; + } + if (getdata == NULL) { + PyErr_Format(PyExc_ValueError, "missing 'getdata' func"); + return -1; + } + + int res = 0; + PyInterpreterState *interp = _PyInterpreterState_GET(); + struct _xidregistry *xidregistry = _get_xidregistry_for_type(interp, cls); + _xidregistry_lock(xidregistry); + + struct _xidregitem *matched = _xidregistry_find_type(xidregistry, cls); + if (matched != NULL) { + assert(matched->getdata == getdata); + matched->refcount += 1; + goto finally; + } + + res = _xidregistry_add_type(xidregistry, cls, getdata); + +finally: + _xidregistry_unlock(xidregistry); + return res; +} + +int +_PyCrossInterpreterData_UnregisterClass(PyTypeObject *cls) +{ + int res = 0; + PyInterpreterState *interp = _PyInterpreterState_GET(); + struct _xidregistry *xidregistry = _get_xidregistry_for_type(interp, cls); + _xidregistry_lock(xidregistry); + + struct _xidregitem *matched = _xidregistry_find_type(xidregistry, cls); + if (matched != NULL) { + assert(matched->refcount > 0); + matched->refcount -= 1; + if (matched->refcount == 0) { + (void)_xidregistry_remove_entry(xidregistry, matched); + } + res = 1; + } + + _xidregistry_unlock(xidregistry); + return res; +} + +static crossinterpdatafunc +_lookup_getdata_from_registry(PyInterpreterState *interp, PyObject *obj) +{ + PyTypeObject *cls = Py_TYPE(obj); + + struct _xidregistry *xidregistry = _get_xidregistry_for_type(interp, cls); + _xidregistry_lock(xidregistry); + + struct _xidregitem *matched = _xidregistry_find_type(xidregistry, cls); + crossinterpdatafunc func = matched != NULL ? matched->getdata : NULL; + + _xidregistry_unlock(xidregistry); + return func; +} + +/* cross-interpreter data for builtin types */ + +// bytes + +struct _shared_bytes_data { + char *bytes; + Py_ssize_t len; +}; + +static PyObject * +_new_bytes_object(_PyCrossInterpreterData *data) +{ + struct _shared_bytes_data *shared = (struct _shared_bytes_data *)(data->data); + return PyBytes_FromStringAndSize(shared->bytes, shared->len); +} + +static int +_bytes_shared(PyThreadState *tstate, PyObject *obj, + _PyCrossInterpreterData *data) +{ + if (_PyCrossInterpreterData_InitWithSize( + data, tstate->interp, sizeof(struct _shared_bytes_data), obj, + _new_bytes_object + ) < 0) + { + return -1; + } + struct _shared_bytes_data *shared = (struct _shared_bytes_data *)data->data; + if (PyBytes_AsStringAndSize(obj, &shared->bytes, &shared->len) < 0) { + _PyCrossInterpreterData_Clear(tstate->interp, data); + return -1; + } + return 0; +} + +// str + +struct _shared_str_data { + int kind; + const void *buffer; + Py_ssize_t len; +}; + +static PyObject * +_new_str_object(_PyCrossInterpreterData *data) +{ + struct _shared_str_data *shared = (struct _shared_str_data *)(data->data); + return PyUnicode_FromKindAndData(shared->kind, shared->buffer, shared->len); +} + +static int +_str_shared(PyThreadState *tstate, PyObject *obj, + _PyCrossInterpreterData *data) +{ + if (_PyCrossInterpreterData_InitWithSize( + data, tstate->interp, sizeof(struct _shared_str_data), obj, + _new_str_object + ) < 0) + { + return -1; + } + struct _shared_str_data *shared = (struct _shared_str_data *)data->data; + shared->kind = PyUnicode_KIND(obj); + shared->buffer = PyUnicode_DATA(obj); + shared->len = PyUnicode_GET_LENGTH(obj); + return 0; +} + +// int + +static PyObject * +_new_long_object(_PyCrossInterpreterData *data) +{ + return PyLong_FromSsize_t((Py_ssize_t)(data->data)); +} + +static int +_long_shared(PyThreadState *tstate, PyObject *obj, + _PyCrossInterpreterData *data) +{ + /* Note that this means the size of shareable ints is bounded by + * sys.maxsize. Hence on 32-bit architectures that is half the + * size of maximum shareable ints on 64-bit. + */ + Py_ssize_t value = PyLong_AsSsize_t(obj); + if (value == -1 && PyErr_Occurred()) { + if (PyErr_ExceptionMatches(PyExc_OverflowError)) { + PyErr_SetString(PyExc_OverflowError, "try sending as bytes"); + } + return -1; + } + _PyCrossInterpreterData_Init(data, tstate->interp, (void *)value, NULL, + _new_long_object); + // data->obj and data->free remain NULL + return 0; +} + +// float + +static PyObject * +_new_float_object(_PyCrossInterpreterData *data) +{ + double * value_ptr = data->data; + return PyFloat_FromDouble(*value_ptr); +} + +static int +_float_shared(PyThreadState *tstate, PyObject *obj, + _PyCrossInterpreterData *data) +{ + if (_PyCrossInterpreterData_InitWithSize( + data, tstate->interp, sizeof(double), NULL, + _new_float_object + ) < 0) + { + return -1; + } + double *shared = (double *)data->data; + *shared = PyFloat_AsDouble(obj); + return 0; +} + +// None + +static PyObject * +_new_none_object(_PyCrossInterpreterData *data) +{ + // XXX Singleton refcounts are problematic across interpreters... + return Py_NewRef(Py_None); +} + +static int +_none_shared(PyThreadState *tstate, PyObject *obj, + _PyCrossInterpreterData *data) +{ + _PyCrossInterpreterData_Init(data, tstate->interp, NULL, NULL, + _new_none_object); + // data->data, data->obj and data->free remain NULL + return 0; +} + +// bool + +static PyObject * +_new_bool_object(_PyCrossInterpreterData *data) +{ + if (data->data){ + Py_RETURN_TRUE; + } + Py_RETURN_FALSE; +} + +static int +_bool_shared(PyThreadState *tstate, PyObject *obj, + _PyCrossInterpreterData *data) +{ + _PyCrossInterpreterData_Init(data, tstate->interp, + (void *) (Py_IsTrue(obj) ? (uintptr_t) 1 : (uintptr_t) 0), NULL, + _new_bool_object); + // data->obj and data->free remain NULL + return 0; +} + +// tuple + +struct _shared_tuple_data { + Py_ssize_t len; + _PyCrossInterpreterData **data; +}; + +static PyObject * +_new_tuple_object(_PyCrossInterpreterData *data) +{ + struct _shared_tuple_data *shared = (struct _shared_tuple_data *)(data->data); + PyObject *tuple = PyTuple_New(shared->len); + if (tuple == NULL) { + return NULL; + } + + for (Py_ssize_t i = 0; i < shared->len; i++) { + PyObject *item = _PyCrossInterpreterData_NewObject(shared->data[i]); + if (item == NULL){ + Py_DECREF(tuple); + return NULL; + } + PyTuple_SET_ITEM(tuple, i, item); + } + return tuple; +} + +static void +_tuple_shared_free(void* data) +{ + struct _shared_tuple_data *shared = (struct _shared_tuple_data *)(data); +#ifndef NDEBUG + int64_t interpid = PyInterpreterState_GetID(_PyInterpreterState_GET()); +#endif + for (Py_ssize_t i = 0; i < shared->len; i++) { + if (shared->data[i] != NULL) { + assert(shared->data[i]->interpid == interpid); + _PyCrossInterpreterData_Release(shared->data[i]); + PyMem_RawFree(shared->data[i]); + shared->data[i] = NULL; + } + } + PyMem_Free(shared->data); + PyMem_RawFree(shared); +} + +static int +_tuple_shared(PyThreadState *tstate, PyObject *obj, + _PyCrossInterpreterData *data) +{ + Py_ssize_t len = PyTuple_GET_SIZE(obj); + if (len < 0) { + return -1; + } + struct _shared_tuple_data *shared = PyMem_RawMalloc(sizeof(struct _shared_tuple_data)); + if (shared == NULL){ + PyErr_NoMemory(); + return -1; + } + + shared->len = len; + shared->data = (_PyCrossInterpreterData **) PyMem_Calloc(shared->len, sizeof(_PyCrossInterpreterData *)); + if (shared->data == NULL) { + PyErr_NoMemory(); + return -1; + } + + for (Py_ssize_t i = 0; i < shared->len; i++) { + _PyCrossInterpreterData *data = _PyCrossInterpreterData_New(); + if (data == NULL) { + goto error; // PyErr_NoMemory already set + } + PyObject *item = PyTuple_GET_ITEM(obj, i); + + int res = -1; + if (!_Py_EnterRecursiveCallTstate(tstate, " while sharing a tuple")) { + res = _PyObject_GetCrossInterpreterData(item, data); + _Py_LeaveRecursiveCallTstate(tstate); + } + if (res < 0) { + PyMem_RawFree(data); + goto error; + } + shared->data[i] = data; + } + _PyCrossInterpreterData_Init( + data, tstate->interp, shared, obj, _new_tuple_object); + data->free = _tuple_shared_free; + return 0; + +error: + _tuple_shared_free(shared); + return -1; +} + +// registration + +static void +_register_builtins_for_crossinterpreter_data(struct _xidregistry *xidregistry) +{ + // None + if (_xidregistry_add_type(xidregistry, (PyTypeObject *)PyObject_Type(Py_None), _none_shared) != 0) { + Py_FatalError("could not register None for cross-interpreter sharing"); + } + + // int + if (_xidregistry_add_type(xidregistry, &PyLong_Type, _long_shared) != 0) { + Py_FatalError("could not register int for cross-interpreter sharing"); + } + + // bytes + if (_xidregistry_add_type(xidregistry, &PyBytes_Type, _bytes_shared) != 0) { + Py_FatalError("could not register bytes for cross-interpreter sharing"); + } + + // str + if (_xidregistry_add_type(xidregistry, &PyUnicode_Type, _str_shared) != 0) { + Py_FatalError("could not register str for cross-interpreter sharing"); + } + + // bool + if (_xidregistry_add_type(xidregistry, &PyBool_Type, _bool_shared) != 0) { + Py_FatalError("could not register bool for cross-interpreter sharing"); + } + + // float + if (_xidregistry_add_type(xidregistry, &PyFloat_Type, _float_shared) != 0) { + Py_FatalError("could not register float for cross-interpreter sharing"); + } + + // tuple + if (_xidregistry_add_type(xidregistry, &PyTuple_Type, _tuple_shared) != 0) { + Py_FatalError("could not register tuple for cross-interpreter sharing"); + } +} + +/* registry lifecycle */ + +static void +_xidregistry_init(struct _xidregistry *registry) +{ + if (registry->initialized) { + return; + } + registry->initialized = 1; + + if (registry->global) { + // Registering the builtins is cheap so we don't bother doing it lazily. + assert(registry->head == NULL); + _register_builtins_for_crossinterpreter_data(registry); + } +} + +static void +_xidregistry_fini(struct _xidregistry *registry) +{ + if (!registry->initialized) { + return; + } + registry->initialized = 0; + + _xidregistry_clear(registry); +} + + +/*************************/ +/* convenience utilities */ +/*************************/ + +static const char * +_copy_string_obj_raw(PyObject *strobj, Py_ssize_t *p_size) +{ + Py_ssize_t size = -1; + const char *str = PyUnicode_AsUTF8AndSize(strobj, &size); + if (str == NULL) { + return NULL; + } + + char *copied = PyMem_RawMalloc(size+1); + if (copied == NULL) { + PyErr_NoMemory(); + return NULL; + } + strcpy(copied, str); + if (p_size != NULL) { + *p_size = size; + } + return copied; +} + + +static int +_convert_exc_to_TracebackException(PyObject *exc, PyObject **p_tbexc) +{ + PyObject *args = NULL; + PyObject *kwargs = NULL; + PyObject *create = NULL; + + // This is inspired by _PyErr_Display(). + PyObject *tbmod = PyImport_ImportModule("traceback"); + if (tbmod == NULL) { + return -1; + } + PyObject *tbexc_type = PyObject_GetAttrString(tbmod, "TracebackException"); + Py_DECREF(tbmod); + if (tbexc_type == NULL) { + return -1; + } + create = PyObject_GetAttrString(tbexc_type, "from_exception"); + Py_DECREF(tbexc_type); + if (create == NULL) { + return -1; + } + + args = PyTuple_Pack(1, exc); + if (args == NULL) { + goto error; + } + + kwargs = PyDict_New(); + if (kwargs == NULL) { + goto error; + } + if (PyDict_SetItemString(kwargs, "save_exc_type", Py_False) < 0) { + goto error; + } + if (PyDict_SetItemString(kwargs, "lookup_lines", Py_False) < 0) { + goto error; + } + + PyObject *tbexc = PyObject_Call(create, args, kwargs); + Py_DECREF(args); + Py_DECREF(kwargs); + Py_DECREF(create); + if (tbexc == NULL) { + goto error; + } + + *p_tbexc = tbexc; + return 0; + +error: + Py_XDECREF(args); + Py_XDECREF(kwargs); + Py_XDECREF(create); + return -1; +} + + +static const char * +_format_TracebackException(PyObject *tbexc) +{ + PyObject *lines = PyObject_CallMethod(tbexc, "format", NULL); + if (lines == NULL) { + return NULL; + } + PyObject *formatted_obj = PyUnicode_Join(&_Py_STR(empty), lines); + Py_DECREF(lines); + if (formatted_obj == NULL) { + return NULL; + } + + Py_ssize_t size = -1; + const char *formatted = _copy_string_obj_raw(formatted_obj, &size); + Py_DECREF(formatted_obj); + // We remove trailing the newline added by TracebackException.format(). + assert(formatted[size-1] == '\n'); + ((char *)formatted)[size-1] = '\0'; + return formatted; +} + + +static int +_release_xid_data(_PyCrossInterpreterData *data, int rawfree) +{ + PyObject *exc = PyErr_GetRaisedException(); + int res = rawfree + ? _PyCrossInterpreterData_Release(data) + : _PyCrossInterpreterData_ReleaseAndRawFree(data); + if (res < 0) { + /* The owning interpreter is already destroyed. */ + _PyCrossInterpreterData_Clear(NULL, data); + // XXX Emit a warning? + PyErr_Clear(); + } + PyErr_SetRaisedException(exc); + return res; +} + + +/***********************/ +/* exception snapshots */ +/***********************/ + +static int +_excinfo_init_type(struct _excinfo_type *info, PyObject *exc) +{ + /* Note that this copies directly rather than into an intermediate + struct and does not clear on error. If we need that then we + should have a separate function to wrap this one + and do all that there. */ + PyObject *strobj = NULL; + + PyTypeObject *type = Py_TYPE(exc); + if (type->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN) { + assert(_Py_IsImmortal((PyObject *)type)); + info->builtin = type; + } + else { + // Only builtin types are preserved. + info->builtin = NULL; + } + + // __name__ + strobj = PyType_GetName(type); + if (strobj == NULL) { + return -1; + } + info->name = _copy_string_obj_raw(strobj, NULL); + Py_DECREF(strobj); + if (info->name == NULL) { + return -1; + } + + // __qualname__ + strobj = PyType_GetQualName(type); + if (strobj == NULL) { + return -1; + } + info->qualname = _copy_string_obj_raw(strobj, NULL); + Py_DECREF(strobj); + if (info->name == NULL) { + return -1; + } + + // __module__ + strobj = _PyType_GetModuleName(type); + if (strobj == NULL) { + return -1; + } + info->module = _copy_string_obj_raw(strobj, NULL); + Py_DECREF(strobj); + if (info->name == NULL) { + return -1; + } + + return 0; +} + +static void +_excinfo_clear_type(struct _excinfo_type *info) +{ + if (info->builtin != NULL) { + assert(info->builtin->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN); + assert(_Py_IsImmortal((PyObject *)info->builtin)); + } + if (info->name != NULL) { + PyMem_RawFree((void *)info->name); + } + if (info->qualname != NULL) { + PyMem_RawFree((void *)info->qualname); + } + if (info->module != NULL) { + PyMem_RawFree((void *)info->module); + } + *info = (struct _excinfo_type){NULL}; +} + +static void +_excinfo_normalize_type(struct _excinfo_type *info, + const char **p_module, const char **p_qualname) +{ + if (info->name == NULL) { + assert(info->builtin == NULL); + assert(info->qualname == NULL); + assert(info->module == NULL); + // This is inspired by TracebackException.format_exception_only(). + *p_module = NULL; + *p_qualname = NULL; + return; + } + + const char *module = info->module; + const char *qualname = info->qualname; + if (qualname == NULL) { + qualname = info->name; + } + assert(module != NULL); + if (strcmp(module, "builtins") == 0) { + module = NULL; + } + else if (strcmp(module, "__main__") == 0) { + module = NULL; + } + *p_qualname = qualname; + *p_module = module; +} + +static void +_PyXI_excinfo_Clear(_PyXI_excinfo *info) +{ + _excinfo_clear_type(&info->type); + if (info->msg != NULL) { + PyMem_RawFree((void *)info->msg); + } + if (info->errdisplay != NULL) { + PyMem_RawFree((void *)info->errdisplay); + } + *info = (_PyXI_excinfo){{NULL}}; +} + +static PyObject * +_PyXI_excinfo_format(_PyXI_excinfo *info) +{ + const char *module, *qualname; + _excinfo_normalize_type(&info->type, &module, &qualname); + if (qualname != NULL) { + if (module != NULL) { + if (info->msg != NULL) { + return PyUnicode_FromFormat("%s.%s: %s", + module, qualname, info->msg); + } + else { + return PyUnicode_FromFormat("%s.%s", module, qualname); + } + } + else { + if (info->msg != NULL) { + return PyUnicode_FromFormat("%s: %s", qualname, info->msg); + } + else { + return PyUnicode_FromString(qualname); + } + } + } + else if (info->msg != NULL) { + return PyUnicode_FromString(info->msg); + } + else { + Py_RETURN_NONE; + } +} + +static const char * +_PyXI_excinfo_InitFromException(_PyXI_excinfo *info, PyObject *exc) +{ + assert(exc != NULL); + + if (PyErr_GivenExceptionMatches(exc, PyExc_MemoryError)) { + _PyXI_excinfo_Clear(info); + return NULL; + } + const char *failure = NULL; + + if (_excinfo_init_type(&info->type, exc) < 0) { + failure = "error while initializing exception type snapshot"; + goto error; + } + + // Extract the exception message. + PyObject *msgobj = PyObject_Str(exc); + if (msgobj == NULL) { + failure = "error while formatting exception"; + goto error; + } + info->msg = _copy_string_obj_raw(msgobj, NULL); + Py_DECREF(msgobj); + if (info->msg == NULL) { + failure = "error while copying exception message"; + goto error; + } + + // Pickle a traceback.TracebackException. + PyObject *tbexc = NULL; + if (_convert_exc_to_TracebackException(exc, &tbexc) < 0) { +#ifdef Py_DEBUG + PyErr_FormatUnraisable("Exception ignored while creating TracebackException"); +#endif + PyErr_Clear(); + } + else { + info->errdisplay = _format_TracebackException(tbexc); + Py_DECREF(tbexc); + if (info->errdisplay == NULL) { +#ifdef Py_DEBUG + PyErr_FormatUnraisable("Exception ignored while formating TracebackException"); +#endif + PyErr_Clear(); + } + } + + return NULL; + +error: + assert(failure != NULL); + _PyXI_excinfo_Clear(info); + return failure; +} + +static void +_PyXI_excinfo_Apply(_PyXI_excinfo *info, PyObject *exctype) +{ + PyObject *tbexc = NULL; + if (info->errdisplay != NULL) { + tbexc = PyUnicode_FromString(info->errdisplay); + if (tbexc == NULL) { + PyErr_Clear(); + } + } + + PyObject *formatted = _PyXI_excinfo_format(info); + PyErr_SetObject(exctype, formatted); + Py_DECREF(formatted); + + if (tbexc != NULL) { + PyObject *exc = PyErr_GetRaisedException(); + if (PyObject_SetAttrString(exc, "_errdisplay", tbexc) < 0) { +#ifdef Py_DEBUG + PyErr_FormatUnraisable("Exception ignored when setting _errdisplay"); +#endif + PyErr_Clear(); + } + Py_DECREF(tbexc); + PyErr_SetRaisedException(exc); + } +} + +static PyObject * +_PyXI_excinfo_TypeAsObject(_PyXI_excinfo *info) +{ + PyObject *ns = _PyNamespace_New(NULL); + if (ns == NULL) { + return NULL; + } + int empty = 1; + + if (info->type.name != NULL) { + PyObject *name = PyUnicode_FromString(info->type.name); + if (name == NULL) { + goto error; + } + int res = PyObject_SetAttrString(ns, "__name__", name); + Py_DECREF(name); + if (res < 0) { + goto error; + } + empty = 0; + } + + if (info->type.qualname != NULL) { + PyObject *qualname = PyUnicode_FromString(info->type.qualname); + if (qualname == NULL) { + goto error; + } + int res = PyObject_SetAttrString(ns, "__qualname__", qualname); + Py_DECREF(qualname); + if (res < 0) { + goto error; + } + empty = 0; + } + + if (info->type.module != NULL) { + PyObject *module = PyUnicode_FromString(info->type.module); + if (module == NULL) { + goto error; + } + int res = PyObject_SetAttrString(ns, "__module__", module); + Py_DECREF(module); + if (res < 0) { + goto error; + } + empty = 0; + } + + if (empty) { + Py_CLEAR(ns); + } + + return ns; + +error: + Py_DECREF(ns); + return NULL; +} + +static PyObject * +_PyXI_excinfo_AsObject(_PyXI_excinfo *info) +{ + PyObject *ns = _PyNamespace_New(NULL); + if (ns == NULL) { + return NULL; + } + int res; + + PyObject *type = _PyXI_excinfo_TypeAsObject(info); + if (type == NULL) { + if (PyErr_Occurred()) { + goto error; + } + type = Py_NewRef(Py_None); + } + res = PyObject_SetAttrString(ns, "type", type); + Py_DECREF(type); + if (res < 0) { + goto error; + } + + PyObject *msg = info->msg != NULL + ? PyUnicode_FromString(info->msg) + : Py_NewRef(Py_None); + if (msg == NULL) { + goto error; + } + res = PyObject_SetAttrString(ns, "msg", msg); + Py_DECREF(msg); + if (res < 0) { + goto error; + } + + PyObject *formatted = _PyXI_excinfo_format(info); + if (formatted == NULL) { + goto error; + } + res = PyObject_SetAttrString(ns, "formatted", formatted); + Py_DECREF(formatted); + if (res < 0) { + goto error; + } + + if (info->errdisplay != NULL) { + PyObject *tbexc = PyUnicode_FromString(info->errdisplay); + if (tbexc == NULL) { + PyErr_Clear(); + } + else { + res = PyObject_SetAttrString(ns, "errdisplay", tbexc); + Py_DECREF(tbexc); + if (res < 0) { + goto error; + } + } + } + + return ns; + +error: + Py_DECREF(ns); + return NULL; +} + + +/***************************/ +/* short-term data sharing */ +/***************************/ + +/* error codes */ + +static int +_PyXI_ApplyErrorCode(_PyXI_errcode code, PyInterpreterState *interp) +{ + assert(!PyErr_Occurred()); + switch (code) { + case _PyXI_ERR_NO_ERROR: // fall through + case _PyXI_ERR_UNCAUGHT_EXCEPTION: + // There is nothing to apply. +#ifdef Py_DEBUG + Py_UNREACHABLE(); +#endif + return 0; + case _PyXI_ERR_OTHER: + // XXX msg? + PyErr_SetNone(PyExc_RuntimeError); + break; + case _PyXI_ERR_NO_MEMORY: + PyErr_NoMemory(); + break; + case _PyXI_ERR_ALREADY_RUNNING: + assert(interp != NULL); + assert(_PyInterpreterState_IsRunningMain(interp)); + _PyInterpreterState_FailIfRunningMain(interp); + break; + case _PyXI_ERR_MAIN_NS_FAILURE: + PyErr_SetString(PyExc_RuntimeError, + "failed to get __main__ namespace"); + break; + case _PyXI_ERR_APPLY_NS_FAILURE: + PyErr_SetString(PyExc_RuntimeError, + "failed to apply namespace to __main__"); + break; + case _PyXI_ERR_NOT_SHAREABLE: + _set_xid_lookup_failure(interp, NULL, NULL); + break; + default: +#ifdef Py_DEBUG + Py_UNREACHABLE(); +#else + PyErr_Format(PyExc_RuntimeError, "unsupported error code %d", code); +#endif + } + assert(PyErr_Occurred()); + return -1; +} + +/* shared exceptions */ + +static const char * +_PyXI_InitError(_PyXI_error *error, PyObject *excobj, _PyXI_errcode code) +{ + if (error->interp == NULL) { + error->interp = PyInterpreterState_Get(); + } + + const char *failure = NULL; + if (code == _PyXI_ERR_UNCAUGHT_EXCEPTION) { + // There is an unhandled exception we need to propagate. + failure = _PyXI_excinfo_InitFromException(&error->uncaught, excobj); + if (failure != NULL) { + // We failed to initialize error->uncaught. + // XXX Print the excobj/traceback? Emit a warning? + // XXX Print the current exception/traceback? + if (PyErr_ExceptionMatches(PyExc_MemoryError)) { + error->code = _PyXI_ERR_NO_MEMORY; + } + else { + error->code = _PyXI_ERR_OTHER; + } + PyErr_Clear(); + } + else { + error->code = code; + } + assert(error->code != _PyXI_ERR_NO_ERROR); + } + else { + // There is an error code we need to propagate. + assert(excobj == NULL); + assert(code != _PyXI_ERR_NO_ERROR); + error->code = code; + _PyXI_excinfo_Clear(&error->uncaught); + } + return failure; +} + +PyObject * +_PyXI_ApplyError(_PyXI_error *error) +{ + if (error->code == _PyXI_ERR_UNCAUGHT_EXCEPTION) { + // Raise an exception that proxies the propagated exception. + return _PyXI_excinfo_AsObject(&error->uncaught); + } + else if (error->code == _PyXI_ERR_NOT_SHAREABLE) { + // Propagate the exception directly. + _set_xid_lookup_failure(error->interp, NULL, error->uncaught.msg); + } + else { + // Raise an exception corresponding to the code. + assert(error->code != _PyXI_ERR_NO_ERROR); + (void)_PyXI_ApplyErrorCode(error->code, error->interp); + if (error->uncaught.type.name != NULL || error->uncaught.msg != NULL) { + // __context__ will be set to a proxy of the propagated exception. + PyObject *exc = PyErr_GetRaisedException(); + _PyXI_excinfo_Apply(&error->uncaught, PyExc_RuntimeError); + PyObject *exc2 = PyErr_GetRaisedException(); + PyException_SetContext(exc, exc2); + PyErr_SetRaisedException(exc); + } + } + assert(PyErr_Occurred()); + return NULL; +} + +/* shared namespaces */ + +/* Shared namespaces are expected to have relatively short lifetimes. + This means dealloc of a shared namespace will normally happen "soon". + Namespace items hold cross-interpreter data, which must get released. + If the namespace/items are cleared in a different interpreter than + where the items' cross-interpreter data was set then that will cause + pending calls to be used to release the cross-interpreter data. + The tricky bit is that the pending calls can happen sufficiently + later that the namespace/items might already be deallocated. This is + a problem if the cross-interpreter data is allocated as part of a + namespace item. If that's the case then we must ensure the shared + namespace is only cleared/freed *after* that data has been released. */ + +typedef struct _sharednsitem { + const char *name; + _PyCrossInterpreterData *data; + // We could have a "PyCrossInterpreterData _data" field, so it would + // be allocated as part of the item and avoid an extra allocation. + // However, doing so adds a bunch of complexity because we must + // ensure the item isn't freed before a pending call might happen + // in a different interpreter to release the XI data. +} _PyXI_namespace_item; + +static int +_sharednsitem_is_initialized(_PyXI_namespace_item *item) +{ + if (item->name != NULL) { + return 1; + } + return 0; +} + +static int +_sharednsitem_init(_PyXI_namespace_item *item, PyObject *key) +{ + item->name = _copy_string_obj_raw(key, NULL); + if (item->name == NULL) { + assert(!_sharednsitem_is_initialized(item)); + return -1; + } + item->data = NULL; + assert(_sharednsitem_is_initialized(item)); + return 0; +} + +static int +_sharednsitem_has_value(_PyXI_namespace_item *item, int64_t *p_interpid) +{ + if (item->data == NULL) { + return 0; + } + if (p_interpid != NULL) { + *p_interpid = item->data->interpid; + } + return 1; +} + +static int +_sharednsitem_set_value(_PyXI_namespace_item *item, PyObject *value) +{ + assert(_sharednsitem_is_initialized(item)); + assert(item->data == NULL); + item->data = PyMem_RawMalloc(sizeof(_PyCrossInterpreterData)); + if (item->data == NULL) { + PyErr_NoMemory(); + return -1; + } + if (_PyObject_GetCrossInterpreterData(value, item->data) != 0) { + PyMem_RawFree(item->data); + item->data = NULL; + // The caller may want to propagate PyExc_NotShareableError + // if currently switched between interpreters. + return -1; + } + return 0; +} + +static void +_sharednsitem_clear_value(_PyXI_namespace_item *item) +{ + _PyCrossInterpreterData *data = item->data; + if (data != NULL) { + item->data = NULL; + int rawfree = 1; + (void)_release_xid_data(data, rawfree); + } +} + +static void +_sharednsitem_clear(_PyXI_namespace_item *item) +{ + if (item->name != NULL) { + PyMem_RawFree((void *)item->name); + item->name = NULL; + } + _sharednsitem_clear_value(item); +} + +static int +_sharednsitem_copy_from_ns(struct _sharednsitem *item, PyObject *ns) +{ + assert(item->name != NULL); + assert(item->data == NULL); + PyObject *value = PyDict_GetItemString(ns, item->name); // borrowed + if (value == NULL) { + if (PyErr_Occurred()) { + return -1; + } + // When applied, this item will be set to the default (or fail). + return 0; + } + if (_sharednsitem_set_value(item, value) < 0) { + return -1; + } + return 0; +} + +static int +_sharednsitem_apply(_PyXI_namespace_item *item, PyObject *ns, PyObject *dflt) +{ + PyObject *name = PyUnicode_FromString(item->name); + if (name == NULL) { + return -1; + } + PyObject *value; + if (item->data != NULL) { + value = _PyCrossInterpreterData_NewObject(item->data); + if (value == NULL) { + Py_DECREF(name); + return -1; + } + } + else { + value = Py_NewRef(dflt); + } + int res = PyDict_SetItem(ns, name, value); + Py_DECREF(name); + Py_DECREF(value); + return res; +} + +struct _sharedns { + Py_ssize_t len; + _PyXI_namespace_item *items; +}; + +static _PyXI_namespace * +_sharedns_new(void) +{ + _PyXI_namespace *ns = PyMem_RawCalloc(sizeof(_PyXI_namespace), 1); + if (ns == NULL) { + PyErr_NoMemory(); + return NULL; + } + *ns = (_PyXI_namespace){ 0 }; + return ns; +} + +static int +_sharedns_is_initialized(_PyXI_namespace *ns) +{ + if (ns->len == 0) { + assert(ns->items == NULL); + return 0; + } + + assert(ns->len > 0); + assert(ns->items != NULL); + assert(_sharednsitem_is_initialized(&ns->items[0])); + assert(ns->len == 1 + || _sharednsitem_is_initialized(&ns->items[ns->len - 1])); + return 1; +} + +#define HAS_COMPLETE_DATA 1 +#define HAS_PARTIAL_DATA 2 + +static int +_sharedns_has_xidata(_PyXI_namespace *ns, int64_t *p_interpid) +{ + // We expect _PyXI_namespace to always be initialized. + assert(_sharedns_is_initialized(ns)); + int res = 0; + _PyXI_namespace_item *item0 = &ns->items[0]; + if (!_sharednsitem_is_initialized(item0)) { + return 0; + } + int64_t interpid0 = -1; + if (!_sharednsitem_has_value(item0, &interpid0)) { + return 0; + } + if (ns->len > 1) { + // At this point we know it is has at least partial data. + _PyXI_namespace_item *itemN = &ns->items[ns->len-1]; + if (!_sharednsitem_is_initialized(itemN)) { + res = HAS_PARTIAL_DATA; + goto finally; + } + int64_t interpidN = -1; + if (!_sharednsitem_has_value(itemN, &interpidN)) { + res = HAS_PARTIAL_DATA; + goto finally; + } + assert(interpidN == interpid0); + } + res = HAS_COMPLETE_DATA; + *p_interpid = interpid0; + +finally: + return res; +} + +static void +_sharedns_clear(_PyXI_namespace *ns) +{ + if (!_sharedns_is_initialized(ns)) { + return; + } + + // If the cross-interpreter data were allocated as part of + // _PyXI_namespace_item (instead of dynamically), this is where + // we would need verify that we are clearing the items in the + // correct interpreter, to avoid a race with releasing the XI data + // via a pending call. See _sharedns_has_xidata(). + for (Py_ssize_t i=0; i < ns->len; i++) { + _sharednsitem_clear(&ns->items[i]); + } + PyMem_RawFree(ns->items); + ns->items = NULL; + ns->len = 0; +} + +static void +_sharedns_free(_PyXI_namespace *ns) +{ + _sharedns_clear(ns); + PyMem_RawFree(ns); +} + +static int +_sharedns_init(_PyXI_namespace *ns, PyObject *names) +{ + assert(!_sharedns_is_initialized(ns)); + assert(names != NULL); + Py_ssize_t len = PyDict_CheckExact(names) + ? PyDict_Size(names) + : PySequence_Size(names); + if (len < 0) { + return -1; + } + if (len == 0) { + PyErr_SetString(PyExc_ValueError, "empty namespaces not allowed"); + return -1; + } + assert(len > 0); + + // Allocate the items. + _PyXI_namespace_item *items = + PyMem_RawCalloc(sizeof(struct _sharednsitem), len); + if (items == NULL) { + PyErr_NoMemory(); + return -1; + } + + // Fill in the names. + Py_ssize_t i = -1; + if (PyDict_CheckExact(names)) { + Py_ssize_t pos = 0; + for (i=0; i < len; i++) { + PyObject *key; + if (!PyDict_Next(names, &pos, &key, NULL)) { + // This should not be possible. + assert(0); + goto error; + } + if (_sharednsitem_init(&items[i], key) < 0) { + goto error; + } + } + } + else if (PySequence_Check(names)) { + for (i=0; i < len; i++) { + PyObject *key = PySequence_GetItem(names, i); + if (key == NULL) { + goto error; + } + int res = _sharednsitem_init(&items[i], key); + Py_DECREF(key); + if (res < 0) { + goto error; + } + } + } + else { + PyErr_SetString(PyExc_NotImplementedError, + "non-sequence namespace not supported"); + goto error; + } + + ns->items = items; + ns->len = len; + assert(_sharedns_is_initialized(ns)); + return 0; + +error: + for (Py_ssize_t j=0; j < i; j++) { + _sharednsitem_clear(&items[j]); + } + PyMem_RawFree(items); + assert(!_sharedns_is_initialized(ns)); + return -1; +} + +void +_PyXI_FreeNamespace(_PyXI_namespace *ns) +{ + if (!_sharedns_is_initialized(ns)) { + return; + } + + int64_t interpid = -1; + if (!_sharedns_has_xidata(ns, &interpid)) { + _sharedns_free(ns); + return; + } + + if (interpid == PyInterpreterState_GetID(_PyInterpreterState_GET())) { + _sharedns_free(ns); + } + else { + // If we weren't always dynamically allocating the cross-interpreter + // data in each item then we would need to using a pending call + // to call _sharedns_free(), to avoid the race between freeing + // the shared namespace and releasing the XI data. + _sharedns_free(ns); + } +} + +_PyXI_namespace * +_PyXI_NamespaceFromNames(PyObject *names) +{ + if (names == NULL || names == Py_None) { + return NULL; + } + + _PyXI_namespace *ns = _sharedns_new(); + if (ns == NULL) { + return NULL; + } + + if (_sharedns_init(ns, names) < 0) { + PyMem_RawFree(ns); + if (PySequence_Size(names) == 0) { + PyErr_Clear(); + } + return NULL; + } + + return ns; +} + +#ifndef NDEBUG +static int _session_is_active(_PyXI_session *); +#endif +static void _propagate_not_shareable_error(_PyXI_session *); + +int +_PyXI_FillNamespaceFromDict(_PyXI_namespace *ns, PyObject *nsobj, + _PyXI_session *session) +{ + // session must be entered already, if provided. + assert(session == NULL || _session_is_active(session)); + assert(_sharedns_is_initialized(ns)); + for (Py_ssize_t i=0; i < ns->len; i++) { + _PyXI_namespace_item *item = &ns->items[i]; + if (_sharednsitem_copy_from_ns(item, nsobj) < 0) { + _propagate_not_shareable_error(session); + // Clear out the ones we set so far. + for (Py_ssize_t j=0; j < i; j++) { + _sharednsitem_clear_value(&ns->items[j]); + } + return -1; + } + } + return 0; +} + +// All items are expected to be shareable. +static _PyXI_namespace * +_PyXI_NamespaceFromDict(PyObject *nsobj, _PyXI_session *session) +{ + // session must be entered already, if provided. + assert(session == NULL || _session_is_active(session)); + if (nsobj == NULL || nsobj == Py_None) { + return NULL; + } + if (!PyDict_CheckExact(nsobj)) { + PyErr_SetString(PyExc_TypeError, "expected a dict"); + return NULL; + } + + _PyXI_namespace *ns = _sharedns_new(); + if (ns == NULL) { + return NULL; + } + + if (_sharedns_init(ns, nsobj) < 0) { + if (PyDict_Size(nsobj) == 0) { + PyMem_RawFree(ns); + PyErr_Clear(); + return NULL; + } + goto error; + } + + if (_PyXI_FillNamespaceFromDict(ns, nsobj, session) < 0) { + goto error; + } + + return ns; + +error: + assert(PyErr_Occurred() + || (session != NULL && session->error_override != NULL)); + _sharedns_free(ns); + return NULL; +} + +int +_PyXI_ApplyNamespace(_PyXI_namespace *ns, PyObject *nsobj, PyObject *dflt) +{ + for (Py_ssize_t i=0; i < ns->len; i++) { + if (_sharednsitem_apply(&ns->items[i], nsobj, dflt) != 0) { + return -1; + } + } + return 0; +} + + +/**********************/ +/* high-level helpers */ +/**********************/ + +/* enter/exit a cross-interpreter session */ + +static void +_enter_session(_PyXI_session *session, PyInterpreterState *interp) +{ + // Set here and cleared in _exit_session(). + assert(!session->own_init_tstate); + assert(session->init_tstate == NULL); + assert(session->prev_tstate == NULL); + // Set elsewhere and cleared in _exit_session(). + assert(!session->running); + assert(session->main_ns == NULL); + // Set elsewhere and cleared in _capture_current_exception(). + assert(session->error_override == NULL); + // Set elsewhere and cleared in _PyXI_ApplyCapturedException(). + assert(session->error == NULL); + + // Switch to interpreter. + PyThreadState *tstate = PyThreadState_Get(); + PyThreadState *prev = tstate; + if (interp != tstate->interp) { + tstate = PyThreadState_New(interp); + tstate->_whence = _PyThreadState_WHENCE_EXEC; + // XXX Possible GILState issues? + session->prev_tstate = PyThreadState_Swap(tstate); + assert(session->prev_tstate == prev); + session->own_init_tstate = 1; + } + session->init_tstate = tstate; + session->prev_tstate = prev; +} + +static void +_exit_session(_PyXI_session *session) +{ + PyThreadState *tstate = session->init_tstate; + assert(tstate != NULL); + assert(PyThreadState_Get() == tstate); + + // Release any of the entered interpreters resources. + if (session->main_ns != NULL) { + Py_CLEAR(session->main_ns); + } + + // Ensure this thread no longer owns __main__. + if (session->running) { + _PyInterpreterState_SetNotRunningMain(tstate->interp); + assert(!PyErr_Occurred()); + session->running = 0; + } + + // Switch back. + assert(session->prev_tstate != NULL); + if (session->prev_tstate != session->init_tstate) { + assert(session->own_init_tstate); + session->own_init_tstate = 0; + PyThreadState_Clear(tstate); + PyThreadState_Swap(session->prev_tstate); + PyThreadState_Delete(tstate); + } + else { + assert(!session->own_init_tstate); + } + session->prev_tstate = NULL; + session->init_tstate = NULL; +} + +#ifndef NDEBUG +static int +_session_is_active(_PyXI_session *session) +{ + return (session->init_tstate != NULL); +} +#endif + +static void +_propagate_not_shareable_error(_PyXI_session *session) +{ + if (session == NULL) { + return; + } + PyInterpreterState *interp = _PyInterpreterState_GET(); + if (PyErr_ExceptionMatches(_get_not_shareable_error_type(interp))) { + // We want to propagate the exception directly. + session->_error_override = _PyXI_ERR_NOT_SHAREABLE; + session->error_override = &session->_error_override; + } +} + +static void +_capture_current_exception(_PyXI_session *session) +{ + assert(session->error == NULL); + if (!PyErr_Occurred()) { + assert(session->error_override == NULL); + return; + } + + // Handle the exception override. + _PyXI_errcode *override = session->error_override; + session->error_override = NULL; + _PyXI_errcode errcode = override != NULL + ? *override + : _PyXI_ERR_UNCAUGHT_EXCEPTION; + + // Pop the exception object. + PyObject *excval = NULL; + if (errcode == _PyXI_ERR_UNCAUGHT_EXCEPTION) { + // We want to actually capture the current exception. + excval = PyErr_GetRaisedException(); + } + else if (errcode == _PyXI_ERR_ALREADY_RUNNING) { + // We don't need the exception info. + PyErr_Clear(); + } + else { + // We could do a variety of things here, depending on errcode. + // However, for now we simply capture the exception and save + // the errcode. + excval = PyErr_GetRaisedException(); + } + + // Capture the exception. + _PyXI_error *err = &session->_error; + *err = (_PyXI_error){ + .interp = session->init_tstate->interp, + }; + const char *failure; + if (excval == NULL) { + failure = _PyXI_InitError(err, NULL, errcode); + } + else { + failure = _PyXI_InitError(err, excval, _PyXI_ERR_UNCAUGHT_EXCEPTION); + Py_DECREF(excval); + if (failure == NULL && override != NULL) { + err->code = errcode; + } + } + + // Handle capture failure. + if (failure != NULL) { + // XXX Make this error message more generic. + fprintf(stderr, + "RunFailedError: script raised an uncaught exception (%s)", + failure); + err = NULL; + } + + // Finished! + assert(!PyErr_Occurred()); + session->error = err; +} + +PyObject * +_PyXI_ApplyCapturedException(_PyXI_session *session) +{ + assert(!PyErr_Occurred()); + assert(session->error != NULL); + PyObject *res = _PyXI_ApplyError(session->error); + assert((res == NULL) != (PyErr_Occurred() == NULL)); + session->error = NULL; + return res; +} + +int +_PyXI_HasCapturedException(_PyXI_session *session) +{ + return session->error != NULL; +} + +int +_PyXI_Enter(_PyXI_session *session, + PyInterpreterState *interp, PyObject *nsupdates) +{ + // Convert the attrs for cross-interpreter use. + _PyXI_namespace *sharedns = NULL; + if (nsupdates != NULL) { + sharedns = _PyXI_NamespaceFromDict(nsupdates, NULL); + if (sharedns == NULL && PyErr_Occurred()) { + assert(session->error == NULL); + return -1; + } + } + + // Switch to the requested interpreter (if necessary). + _enter_session(session, interp); + _PyXI_errcode errcode = _PyXI_ERR_UNCAUGHT_EXCEPTION; + + // Ensure this thread owns __main__. + if (_PyInterpreterState_SetRunningMain(interp) < 0) { + // In the case where we didn't switch interpreters, it would + // be more efficient to leave the exception in place and return + // immediately. However, life is simpler if we don't. + errcode = _PyXI_ERR_ALREADY_RUNNING; + goto error; + } + session->running = 1; + + // Cache __main__.__dict__. + PyObject *main_mod = PyUnstable_InterpreterState_GetMainModule(interp); + if (main_mod == NULL) { + errcode = _PyXI_ERR_MAIN_NS_FAILURE; + goto error; + } + PyObject *ns = PyModule_GetDict(main_mod); // borrowed + Py_DECREF(main_mod); + if (ns == NULL) { + errcode = _PyXI_ERR_MAIN_NS_FAILURE; + goto error; + } + session->main_ns = Py_NewRef(ns); + + // Apply the cross-interpreter data. + if (sharedns != NULL) { + if (_PyXI_ApplyNamespace(sharedns, ns, NULL) < 0) { + errcode = _PyXI_ERR_APPLY_NS_FAILURE; + goto error; + } + _PyXI_FreeNamespace(sharedns); + } + + errcode = _PyXI_ERR_NO_ERROR; + assert(!PyErr_Occurred()); + return 0; + +error: + assert(PyErr_Occurred()); + // We want to propagate all exceptions here directly (best effort). + assert(errcode != _PyXI_ERR_UNCAUGHT_EXCEPTION); + session->error_override = &errcode; + _capture_current_exception(session); + _exit_session(session); + if (sharedns != NULL) { + _PyXI_FreeNamespace(sharedns); + } + return -1; +} + +void +_PyXI_Exit(_PyXI_session *session) +{ + _capture_current_exception(session); + _exit_session(session); +} + + +/*********************/ +/* runtime lifecycle */ +/*********************/ + +PyStatus +_PyXI_Init(PyInterpreterState *interp) +{ + PyStatus status; + + // Initialize the XID registry. + if (_Py_IsMainInterpreter(interp)) { + _xidregistry_init(_get_global_xidregistry(interp->runtime)); + } + _xidregistry_init(_get_xidregistry(interp)); + + // Initialize exceptions (heap types). + status = _init_not_shareable_error_type(interp); + if (_PyStatus_EXCEPTION(status)) { + return status; + } + + return _PyStatus_OK(); +} + +// _PyXI_Fini() must be called before the interpreter is cleared, +// since we must clear some heap objects. + +void +_PyXI_Fini(PyInterpreterState *interp) +{ + // Finalize exceptions (heap types). + _fini_not_shareable_error_type(interp); + + // Finalize the XID registry. + _xidregistry_fini(_get_xidregistry(interp)); + if (_Py_IsMainInterpreter(interp)) { + _xidregistry_fini(_get_global_xidregistry(interp->runtime)); + } +} + +PyStatus +_PyXI_InitTypes(PyInterpreterState *interp) +{ + if (init_exceptions(interp) < 0) { + return _PyStatus_ERR("failed to initialize an exception type"); + } + return _PyStatus_OK(); +} + +void +_PyXI_FiniTypes(PyInterpreterState *interp) +{ + fini_exceptions(interp); +} diff --git a/Python/dtoa.c b/Python/dtoa.c index c5e343b82f74c5..6e3162f80bdae1 100644 --- a/Python/dtoa.c +++ b/Python/dtoa.c @@ -172,10 +172,6 @@ typedef uint64_t ULLong; #define Bug(x) {fprintf(stderr, "%s\n", x); exit(1);} #endif -#ifdef __cplusplus -extern "C" { -#endif - typedef union { double d; ULong L[2]; } U; #ifdef IEEE_8087 @@ -313,7 +309,7 @@ BCinfo { // struct Bigint is defined in pycore_dtoa.h. typedef struct Bigint Bigint; -#ifndef Py_USING_MEMORY_DEBUGGER +#if !defined(Py_GIL_DISABLED) && !defined(Py_USING_MEMORY_DEBUGGER) /* Memory management: memory is allocated from, and returned to, Kmax+1 pools of memory, where pool k (0 <= k <= Kmax) is for Bigints b with b->maxwds == @@ -432,7 +428,7 @@ Bfree(Bigint *v) } } -#endif /* Py_USING_MEMORY_DEBUGGER */ +#endif /* !defined(Py_GIL_DISABLED) && !defined(Py_USING_MEMORY_DEBUGGER) */ #define Bcopy(x,y) memcpy((char *)&x->sign, (char *)&y->sign, \ y->wds*sizeof(Long) + 2*sizeof(int)) @@ -677,10 +673,17 @@ mult(Bigint *a, Bigint *b) static Bigint * pow5mult(Bigint *b, int k) { - Bigint *b1, *p5, *p51; + Bigint *b1, *p5, **p5s; int i; static const int p05[3] = { 5, 25, 125 }; + // For double-to-string conversion, the maximum value of k is limited by + // DBL_MAX_10_EXP (308), the maximum decimal base-10 exponent for binary64. + // For string-to-double conversion, the extreme case is constrained by our + // hardcoded exponent limit before we underflow of -512, adjusted by + // STRTOD_DIGLIM-DBL_DIG-1, giving a maximum of k=535. + assert(0 <= k && k < 1024); + if ((i = k & 3)) { b = multadd(b, p05[i-1], 0); if (b == NULL) @@ -690,18 +693,11 @@ pow5mult(Bigint *b, int k) if (!(k >>= 2)) return b; PyInterpreterState *interp = _PyInterpreterState_GET(); - p5 = interp->dtoa.p5s; - if (!p5) { - /* first time */ - p5 = i2b(625); - if (p5 == NULL) { - Bfree(b); - return NULL; - } - interp->dtoa.p5s = p5; - p5->next = 0; - } + p5s = interp->dtoa.p5s; for(;;) { + assert(p5s != interp->dtoa.p5s + Bigint_Pow5size); + p5 = *p5s; + p5s++; if (k & 1) { b1 = mult(b, p5); Bfree(b); @@ -711,17 +707,6 @@ pow5mult(Bigint *b, int k) } if (!(k >>= 1)) break; - p51 = p5->next; - if (!p51) { - p51 = mult(p5,p5); - if (p51 == NULL) { - Bfree(b); - return NULL; - } - p51->next = 0; - p5->next = p51; - } - p5 = p51; } return b; } @@ -2813,8 +2798,44 @@ _Py_dg_dtoa(double dd, int mode, int ndigits, _Py_dg_freedtoa(s0); return NULL; } -#ifdef __cplusplus -} -#endif #endif // _PY_SHORT_FLOAT_REPR == 1 + +PyStatus +_PyDtoa_Init(PyInterpreterState *interp) +{ +#if _PY_SHORT_FLOAT_REPR == 1 && !defined(Py_USING_MEMORY_DEBUGGER) + Bigint **p5s = interp->dtoa.p5s; + + // 5**4 = 625 + Bigint *p5 = i2b(625); + if (p5 == NULL) { + return PyStatus_NoMemory(); + } + p5s[0] = p5; + + // compute 5**8, 5**16, 5**32, ..., 5**512 + for (Py_ssize_t i = 1; i < Bigint_Pow5size; i++) { + p5 = mult(p5, p5); + if (p5 == NULL) { + return PyStatus_NoMemory(); + } + p5s[i] = p5; + } + +#endif + return PyStatus_Ok(); +} + +void +_PyDtoa_Fini(PyInterpreterState *interp) +{ +#if _PY_SHORT_FLOAT_REPR == 1 && !defined(Py_USING_MEMORY_DEBUGGER) + Bigint **p5s = interp->dtoa.p5s; + for (Py_ssize_t i = 0; i < Bigint_Pow5size; i++) { + Bigint *p5 = p5s[i]; + p5s[i] = NULL; + Bfree(p5); + } +#endif +} diff --git a/Python/dup2.c b/Python/dup2.c index a1df0492099163..936211f27ec737 100644 --- a/Python/dup2.c +++ b/Python/dup2.c @@ -11,9 +11,9 @@ * Return fd2 if all went well; return BADEXIT otherwise. */ -#include -#include -#include +#include // errno +#include // fcntl() +#include // close() #define BADEXIT -1 diff --git a/Python/dynload_hpux.c b/Python/dynload_hpux.c index a53373038ed859..1c44722ff9a2d0 100644 --- a/Python/dynload_hpux.c +++ b/Python/dynload_hpux.c @@ -5,7 +5,7 @@ #include #include "Python.h" -#include "importdl.h" +#include "pycore_importdl.h" #if defined(__hp9000s300) #define FUNCNAME_PATTERN "_%.20s_%.200s" diff --git a/Python/dynload_shlib.c b/Python/dynload_shlib.c index 6761bba457983b..5a37a83805ba78 100644 --- a/Python/dynload_shlib.c +++ b/Python/dynload_shlib.c @@ -4,7 +4,7 @@ #include "Python.h" #include "pycore_interp.h" // _PyInterpreterState.dlopenflags #include "pycore_pystate.h" // _PyInterpreterState_GET() -#include "importdl.h" +#include "pycore_importdl.h" #include #include diff --git a/Python/dynload_stub.c b/Python/dynload_stub.c index 59160483caa448..11f7e5f643f79e 100644 --- a/Python/dynload_stub.c +++ b/Python/dynload_stub.c @@ -3,7 +3,7 @@ not present. */ #include "Python.h" -#include "importdl.h" +#include "pycore_importdl.h" const char *_PyImport_DynLoadFiletab[] = {NULL}; diff --git a/Python/dynload_win.c b/Python/dynload_win.c index acab05e2c6def3..a0ac31c80a5f6e 100644 --- a/Python/dynload_win.c +++ b/Python/dynload_win.c @@ -5,29 +5,10 @@ #include "pycore_fileutils.h" // _Py_add_relfile() #include "pycore_pystate.h" // _PyInterpreterState_GET() -#ifdef HAVE_DIRECT_H -#include -#endif -#include - -#include "importdl.h" -#include "patchlevel.h" +#include "pycore_importdl.h" // dl_funcptr +#include "patchlevel.h" // PY_MAJOR_VERSION #include -#ifdef _DEBUG -#define PYD_DEBUG_SUFFIX "_d" -#else -#define PYD_DEBUG_SUFFIX "" -#endif - -#ifdef PYD_PLATFORM_TAG -#define PYD_TAGGED_SUFFIX PYD_DEBUG_SUFFIX ".cp" Py_STRINGIFY(PY_MAJOR_VERSION) Py_STRINGIFY(PY_MINOR_VERSION) "-" PYD_PLATFORM_TAG ".pyd" -#else -#define PYD_TAGGED_SUFFIX PYD_DEBUG_SUFFIX ".cp" Py_STRINGIFY(PY_MAJOR_VERSION) Py_STRINGIFY(PY_MINOR_VERSION) ".pyd" -#endif - -#define PYD_UNTAGGED_SUFFIX PYD_DEBUG_SUFFIX ".pyd" - const char *_PyImport_DynLoadFiletab[] = { PYD_TAGGED_SUFFIX, PYD_UNTAGGED_SUFFIX, diff --git a/Python/emscripten_signal.c b/Python/emscripten_signal.c index d617ddfeb37c5a..561b5b73cd6b70 100644 --- a/Python/emscripten_signal.c +++ b/Python/emscripten_signal.c @@ -38,19 +38,17 @@ _Py_CheckEmscriptenSignals(void) } } - #define PY_EMSCRIPTEN_SIGNAL_INTERVAL 50 -static int emscripten_signal_clock = PY_EMSCRIPTEN_SIGNAL_INTERVAL; +int _Py_emscripten_signal_clock = PY_EMSCRIPTEN_SIGNAL_INTERVAL; void _Py_CheckEmscriptenSignalsPeriodically(void) { - if (!Py_EMSCRIPTEN_SIGNAL_HANDLING) { - return; - } - emscripten_signal_clock--; - if (emscripten_signal_clock == 0) { - emscripten_signal_clock = PY_EMSCRIPTEN_SIGNAL_INTERVAL; + if (_Py_emscripten_signal_clock == 0) { + _Py_emscripten_signal_clock = PY_EMSCRIPTEN_SIGNAL_INTERVAL; _Py_CheckEmscriptenSignals(); } + else if (Py_EMSCRIPTEN_SIGNAL_HANDLING) { + _Py_emscripten_signal_clock--; + } } diff --git a/Python/emscripten_trampoline.c b/Python/emscripten_trampoline.c new file mode 100644 index 00000000000000..2a80ec4f18d757 --- /dev/null +++ b/Python/emscripten_trampoline.c @@ -0,0 +1,82 @@ +#if defined(PY_CALL_TRAMPOLINE) + +#include // EM_JS +#include +#include "pycore_runtime.h" // _PyRuntime + + +/** + * This is the GoogleChromeLabs approved way to feature detect type-reflection: + * https://github.com/GoogleChromeLabs/wasm-feature-detect/blob/main/src/detectors/type-reflection/index.js + */ +EM_JS(int, _PyEM_detect_type_reflection, (), { + return "Function" in WebAssembly; +}); + +void +_Py_EmscriptenTrampoline_Init(_PyRuntimeState *runtime) +{ + runtime->wasm_type_reflection_available = _PyEM_detect_type_reflection(); +} + +/** + * Backwards compatible trampoline works with all JS runtimes + */ +EM_JS(PyObject*, +_PyEM_TrampolineCall_JavaScript, (PyCFunctionWithKeywords func, + PyObject *arg1, + PyObject *arg2, + PyObject *arg3), +{ + return wasmTable.get(func)(arg1, arg2, arg3); +} +); + +/** + * In runtimes with WebAssembly type reflection, count the number of parameters + * and cast to the appropriate signature + */ +EM_JS(int, _PyEM_CountFuncParams, (PyCFunctionWithKeywords func), +{ + let n = _PyEM_CountFuncParams.cache.get(func); + + if (n !== undefined) { + return n; + } + n = WebAssembly.Function.type(wasmTable.get(func)).parameters.length; + _PyEM_CountFuncParams.cache.set(func, n); + return n; +} +_PyEM_CountFuncParams.cache = new Map(); +) + + +typedef PyObject* (*zero_arg)(void); +typedef PyObject* (*one_arg)(PyObject*); +typedef PyObject* (*two_arg)(PyObject*, PyObject*); +typedef PyObject* (*three_arg)(PyObject*, PyObject*, PyObject*); + + +PyObject* +_PyEM_TrampolineCall_Reflection(PyCFunctionWithKeywords func, + PyObject* self, + PyObject* args, + PyObject* kw) +{ + switch (_PyEM_CountFuncParams(func)) { + case 0: + return ((zero_arg)func)(); + case 1: + return ((one_arg)func)(self); + case 2: + return ((two_arg)func)(self, args); + case 3: + return ((three_arg)func)(self, args, kw); + default: + PyErr_SetString(PyExc_SystemError, + "Handler takes too many arguments"); + return NULL; + } +} + +#endif diff --git a/Python/errors.c b/Python/errors.c index 916958c9a0ab00..e5f176a5dd208e 100644 --- a/Python/errors.c +++ b/Python/errors.c @@ -10,18 +10,12 @@ #include "pycore_sysmodule.h" // _PySys_Audit() #include "pycore_traceback.h" // _PyTraceBack_FromFrame() -#include #ifdef MS_WINDOWS # include # include # include // _sys_nerr #endif - -#ifdef __cplusplus -extern "C" { -#endif - /* Forward declarations */ static PyObject * _PyErr_FormatV(PyThreadState *tstate, PyObject *exception, @@ -127,11 +121,11 @@ _PyErr_GetTopmostException(PyThreadState *tstate) _PyErr_StackItem *exc_info = tstate->exc_info; assert(exc_info); - while ((exc_info->exc_value == NULL || exc_info->exc_value == Py_None) && - exc_info->previous_item != NULL) + while (exc_info->exc_value == NULL && exc_info->previous_item != NULL) { exc_info = exc_info->previous_item; } + assert(!Py_IsNone(exc_info->exc_value)); return exc_info; } @@ -292,8 +286,10 @@ _PyErr_SetString(PyThreadState *tstate, PyObject *exception, const char *string) { PyObject *value = PyUnicode_FromString(string); - _PyErr_SetObject(tstate, exception, value); - Py_XDECREF(value); + if (value != NULL) { + _PyErr_SetObject(tstate, exception, value); + Py_DECREF(value); + } } void @@ -596,7 +592,7 @@ PyErr_GetHandledException(void) void _PyErr_SetHandledException(PyThreadState *tstate, PyObject *exc) { - Py_XSETREF(tstate->exc_info->exc_value, Py_XNewRef(exc)); + Py_XSETREF(tstate->exc_info->exc_value, Py_XNewRef(exc == Py_None ? NULL : exc)); } void @@ -891,7 +887,15 @@ PyErr_SetFromErrnoWithFilenameObjects(PyObject *exc, PyObject *filenameObject, P PyObject * PyErr_SetFromErrnoWithFilename(PyObject *exc, const char *filename) { - PyObject *name = filename ? PyUnicode_DecodeFSDefault(filename) : NULL; + PyObject *name = NULL; + if (filename) { + int i = errno; + name = PyUnicode_DecodeFSDefault(filename); + if (name == NULL) { + return NULL; + } + errno = i; + } PyObject *result = PyErr_SetFromErrnoWithFilenameObjects(exc, name, NULL); Py_XDECREF(name); return result; @@ -988,7 +992,16 @@ PyObject *PyErr_SetExcFromWindowsErrWithFilename( int ierr, const char *filename) { - PyObject *name = filename ? PyUnicode_DecodeFSDefault(filename) : NULL; + PyObject *name = NULL; + if (filename) { + if ((DWORD)ierr == 0) { + ierr = (int)GetLastError(); + } + name = PyUnicode_DecodeFSDefault(filename); + if (name == NULL) { + return NULL; + } + } PyObject *ret = PyErr_SetExcFromWindowsErrWithFilenameObjects(exc, ierr, name, @@ -1012,7 +1025,16 @@ PyObject *PyErr_SetFromWindowsErrWithFilename( int ierr, const char *filename) { - PyObject *name = filename ? PyUnicode_DecodeFSDefault(filename) : NULL; + PyObject *name = NULL; + if (filename) { + if ((DWORD)ierr == 0) { + ierr = (int)GetLastError(); + } + name = PyUnicode_DecodeFSDefault(filename); + if (name == NULL) { + return NULL; + } + } PyObject *result = PyErr_SetExcFromWindowsErrWithFilenameObjects( PyExc_OSError, ierr, name, NULL); @@ -1137,9 +1159,10 @@ _PyErr_FormatV(PyThreadState *tstate, PyObject *exception, _PyErr_Clear(tstate); string = PyUnicode_FromFormatV(format, vargs); - - _PyErr_SetObject(tstate, exception, string); - Py_XDECREF(string); + if (string != NULL) { + _PyErr_SetObject(tstate, exception, string); + Py_DECREF(string); + } return NULL; } @@ -1485,11 +1508,9 @@ write_unraisable_exc_file(PyThreadState *tstate, PyObject *exc_type, } /* Explicitly call file.flush() */ - PyObject *res = PyObject_CallMethodNoArgs(file, &_Py_ID(flush)); - if (!res) { + if (_PyFile_Flush(file) < 0) { return -1; } - Py_DECREF(res); return 0; } @@ -1548,14 +1569,16 @@ _PyErr_WriteUnraisableDefaultHook(PyObject *args) for Python to handle it. For example, when a destructor raises an exception or during garbage collection (gc.collect()). - If err_msg_str is non-NULL, the error message is formatted as: - "Exception ignored %s" % err_msg_str. Otherwise, use "Exception ignored in" - error message. + If format is non-NULL, the error message is formatted using format and + variable arguments as in PyUnicode_FromFormat(). + Otherwise, use "Exception ignored in" error message. An exception must be set when calling this function. */ -void -_PyErr_WriteUnraisableMsg(const char *err_msg_str, PyObject *obj) + +static void +format_unraisable_v(const char *format, va_list va, PyObject *obj) { + const char *err_msg_str; PyThreadState *tstate = _PyThreadState_GET(); _Py_EnsureTstateNotNULL(tstate); @@ -1589,8 +1612,8 @@ _PyErr_WriteUnraisableMsg(const char *err_msg_str, PyObject *obj) } } - if (err_msg_str != NULL) { - err_msg = PyUnicode_FromFormat("Exception ignored %s", err_msg_str); + if (format != NULL) { + err_msg = PyUnicode_FromFormatV(format, va); if (err_msg == NULL) { PyErr_Clear(); } @@ -1655,11 +1678,30 @@ _PyErr_WriteUnraisableMsg(const char *err_msg_str, PyObject *obj) _PyErr_Clear(tstate); /* Just in case */ } +void +PyErr_FormatUnraisable(const char *format, ...) +{ + va_list va; + + va_start(va, format); + format_unraisable_v(format, va, NULL); + va_end(va); +} + +static void +format_unraisable(PyObject *obj, const char *format, ...) +{ + va_list va; + + va_start(va, format); + format_unraisable_v(format, va, obj); + va_end(va); +} void PyErr_WriteUnraisable(PyObject *obj) { - _PyErr_WriteUnraisableMsg(NULL, obj); + format_unraisable(obj, NULL); } @@ -1748,13 +1790,11 @@ PyErr_SyntaxLocationObjectEx(PyObject *filename, int lineno, int col_offset, } } if ((PyObject *)Py_TYPE(exc) != PyExc_SyntaxError) { - if (PyObject_GetOptionalAttr(exc, &_Py_ID(msg), &tmp) < 0) { + int rc = PyObject_HasAttrWithError(exc, &_Py_ID(msg)); + if (rc < 0) { _PyErr_Clear(tstate); } - else if (tmp) { - Py_DECREF(tmp); - } - else { + else if (!rc) { tmp = PyObject_Str(exc); if (tmp) { if (PyObject_SetAttr(exc, &_Py_ID(msg), tmp)) { @@ -1767,13 +1807,11 @@ PyErr_SyntaxLocationObjectEx(PyObject *filename, int lineno, int col_offset, } } - if (PyObject_GetOptionalAttr(exc, &_Py_ID(print_file_and_line), &tmp) < 0) { + rc = PyObject_HasAttrWithError(exc, &_Py_ID(print_file_and_line)); + if (rc < 0) { _PyErr_Clear(tstate); } - else if (tmp) { - Py_DECREF(tmp); - } - else { + else if (!rc) { if (PyObject_SetAttr(exc, &_Py_ID(print_file_and_line), Py_None)) { _PyErr_Clear(tstate); } @@ -1896,7 +1934,3 @@ PyErr_ProgramTextObject(PyObject *filename, int lineno) { return _PyErr_ProgramDecodedTextObject(filename, lineno, NULL); } - -#ifdef __cplusplus -} -#endif diff --git a/Python/executor.c b/Python/executor.c deleted file mode 100644 index 57525df202d861..00000000000000 --- a/Python/executor.c +++ /dev/null @@ -1,126 +0,0 @@ -#include "Python.h" - -#include "pycore_call.h" -#include "pycore_ceval.h" -#include "pycore_dict.h" -#include "pycore_emscripten_signal.h" -#include "pycore_intrinsics.h" -#include "pycore_long.h" -#include "pycore_object.h" -#include "pycore_opcode_metadata.h" -#include "pycore_opcode_utils.h" -#include "pycore_pyerrors.h" -#include "pycore_range.h" -#include "pycore_setobject.h" // _PySet_Update() -#include "pycore_sliceobject.h" -#include "pycore_uops.h" - -#include "ceval_macros.h" - - -#undef ASSERT_KWNAMES_IS_NULL -#define ASSERT_KWNAMES_IS_NULL() (void)0 - -#undef DEOPT_IF -#define DEOPT_IF(COND, INSTNAME) \ - if ((COND)) { \ - goto deoptimize; \ - } - -#undef ENABLE_SPECIALIZATION -#define ENABLE_SPECIALIZATION 0 - - -_PyInterpreterFrame * -_PyUopExecute(_PyExecutorObject *executor, _PyInterpreterFrame *frame, PyObject **stack_pointer) -{ -#ifdef Py_DEBUG - char *uop_debug = Py_GETENV("PYTHONUOPSDEBUG"); - int lltrace = 0; - if (uop_debug != NULL && *uop_debug >= '0') { - lltrace = *uop_debug - '0'; // TODO: Parse an int and all that - } - #define DPRINTF(level, ...) \ - if (lltrace >= (level)) { fprintf(stderr, __VA_ARGS__); } -#else - #define DPRINTF(level, ...) -#endif - - DPRINTF(3, - "Entering _PyUopExecute for %s (%s:%d) at byte offset %ld\n", - PyUnicode_AsUTF8(_PyFrame_GetCode(frame)->co_qualname), - PyUnicode_AsUTF8(_PyFrame_GetCode(frame)->co_filename), - _PyFrame_GetCode(frame)->co_firstlineno, - 2 * (long)(frame->prev_instr + 1 - - (_Py_CODEUNIT *)_PyFrame_GetCode(frame)->co_code_adaptive)); - - PyThreadState *tstate = _PyThreadState_GET(); - _PyUOpExecutorObject *self = (_PyUOpExecutorObject *)executor; - - CHECK_EVAL_BREAKER(); - - OBJECT_STAT_INC(optimization_traces_executed); - _Py_CODEUNIT *ip_offset = (_Py_CODEUNIT *)_PyFrame_GetCode(frame)->co_code_adaptive; - int pc = 0; - int opcode; - int oparg; - uint64_t operand; - - for (;;) { - opcode = self->trace[pc].opcode; - oparg = self->trace[pc].oparg; - operand = self->trace[pc].operand; - DPRINTF(3, - "%4d: uop %s, oparg %d, operand %" PRIu64 ", stack_level %d\n", - pc, - opcode < 256 ? _PyOpcode_OpName[opcode] : _PyOpcode_uop_name[opcode], - oparg, - operand, - (int)(stack_pointer - _PyFrame_Stackbase(frame))); - pc++; - OBJECT_STAT_INC(optimization_uops_executed); - switch (opcode) { - -#include "executor_cases.c.h" - - default: - { - fprintf(stderr, "Unknown uop %d, operand %" PRIu64 "\n", opcode, operand); - Py_FatalError("Unknown uop"); - } - - } - } - -unbound_local_error: - _PyEval_FormatExcCheckArg(tstate, PyExc_UnboundLocalError, - UNBOUNDLOCAL_ERROR_MSG, - PyTuple_GetItem(_PyFrame_GetCode(frame)->co_localsplusnames, oparg) - ); - goto error; - -pop_4_error: - STACK_SHRINK(1); -pop_3_error: - STACK_SHRINK(1); -pop_2_error: - STACK_SHRINK(1); -pop_1_error: - STACK_SHRINK(1); -error: - // On ERROR_IF we return NULL as the frame. - // The caller recovers the frame from cframe.current_frame. - DPRINTF(2, "Error: [Opcode %d, operand %" PRIu64 "]\n", opcode, operand); - _PyFrame_SetStackPointer(frame, stack_pointer); - Py_DECREF(self); - return NULL; - -deoptimize: - // On DEOPT_IF we just repeat the last instruction. - // This presumes nothing was popped from the stack (nor pushed). - DPRINTF(2, "DEOPT: [Opcode %d, operand %" PRIu64 "]\n", opcode, operand); - frame->prev_instr--; // Back up to just before destination - _PyFrame_SetStackPointer(frame, stack_pointer); - Py_DECREF(self); - return frame; -} diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h index 9363b4955087db..ea4caa9a97ab39 100644 --- a/Python/executor_cases.c.h +++ b/Python/executor_cases.c.h @@ -1,98 +1,122 @@ -// This file is generated by Tools/cases_generator/generate_cases.py +// This file is generated by Tools/cases_generator/tier2_generator.py // from: // Python/bytecodes.c // Do not edit! - case NOP: { +#ifdef TIER_ONE + #error "This file is for Tier 2 only" +#endif +#define TIER_TWO 2 + + case _NOP: { + break; + } + + case _RESUME_CHECK: { + #if defined(__EMSCRIPTEN__) + if (_Py_emscripten_signal_clock == 0) goto deoptimize; + _Py_emscripten_signal_clock -= Py_EMSCRIPTEN_SIGNAL_HANDLING; + #endif + uintptr_t eval_breaker = _Py_atomic_load_uintptr_relaxed(&tstate->interp->ceval.eval_breaker); + uintptr_t version = _PyFrame_GetCode(frame)->_co_instrumentation_version; + assert((version & _PY_EVAL_EVENTS_MASK) == 0); + if (eval_breaker != version) goto deoptimize; break; } - case LOAD_FAST_CHECK: { + /* _INSTRUMENTED_RESUME is not a viable micro-op for tier 2 */ + + case _LOAD_FAST_CHECK: { PyObject *value; + oparg = CURRENT_OPARG(); value = GETLOCAL(oparg); - if (value == NULL) goto unbound_local_error; + if (value == NULL) goto unbound_local_error_tier_two; Py_INCREF(value); - STACK_GROW(1); - stack_pointer[-1] = value; + stack_pointer[0] = value; + stack_pointer += 1; break; } - case LOAD_FAST: { + case _LOAD_FAST: { PyObject *value; + oparg = CURRENT_OPARG(); value = GETLOCAL(oparg); assert(value != NULL); Py_INCREF(value); - STACK_GROW(1); - stack_pointer[-1] = value; + stack_pointer[0] = value; + stack_pointer += 1; break; } - case LOAD_FAST_AND_CLEAR: { + case _LOAD_FAST_AND_CLEAR: { PyObject *value; + oparg = CURRENT_OPARG(); value = GETLOCAL(oparg); // do not use SETLOCAL here, it decrefs the old value GETLOCAL(oparg) = NULL; - STACK_GROW(1); - stack_pointer[-1] = value; + stack_pointer[0] = value; + stack_pointer += 1; break; } - case LOAD_CONST: { + case _LOAD_CONST: { PyObject *value; + oparg = CURRENT_OPARG(); value = GETITEM(FRAME_CO_CONSTS, oparg); Py_INCREF(value); - STACK_GROW(1); - stack_pointer[-1] = value; + stack_pointer[0] = value; + stack_pointer += 1; break; } - case STORE_FAST: { + case _STORE_FAST: { PyObject *value; + oparg = CURRENT_OPARG(); value = stack_pointer[-1]; SETLOCAL(oparg, value); - STACK_SHRINK(1); + stack_pointer += -1; break; } - case POP_TOP: { + case _POP_TOP: { PyObject *value; value = stack_pointer[-1]; Py_DECREF(value); - STACK_SHRINK(1); + stack_pointer += -1; break; } - case PUSH_NULL: { + case _PUSH_NULL: { PyObject *res; res = NULL; - STACK_GROW(1); - stack_pointer[-1] = res; + stack_pointer[0] = res; + stack_pointer += 1; break; } - case END_SEND: { + case _END_SEND: { PyObject *value; PyObject *receiver; value = stack_pointer[-1]; receiver = stack_pointer[-2]; Py_DECREF(receiver); - STACK_SHRINK(1); - stack_pointer[-1] = value; + stack_pointer[-2] = value; + stack_pointer += -1; break; } - case UNARY_NEGATIVE: { + case _UNARY_NEGATIVE: { PyObject *value; PyObject *res; value = stack_pointer[-1]; res = PyNumber_Negative(value); Py_DECREF(value); - if (res == NULL) goto pop_1_error; + if (res == NULL) goto pop_1_error_tier_two; stack_pointer[-1] = res; break; } - case UNARY_NOT: { + case _UNARY_NOT: { PyObject *value; PyObject *res; value = stack_pointer[-1]; @@ -102,42 +126,31 @@ break; } - case TO_BOOL: { - static_assert(INLINE_CACHE_ENTRIES_TO_BOOL == 3, "incorrect cache size"); + case _TO_BOOL: { PyObject *value; PyObject *res; value = stack_pointer[-1]; - #if ENABLE_SPECIALIZATION - _PyToBoolCache *cache = (_PyToBoolCache *)next_instr; - if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) { - next_instr--; - _Py_Specialize_ToBool(value, next_instr); - DISPATCH_SAME_OPARG(); - } - STAT_INC(TO_BOOL, deferred); - DECREMENT_ADAPTIVE_COUNTER(cache->counter); - #endif /* ENABLE_SPECIALIZATION */ int err = PyObject_IsTrue(value); Py_DECREF(value); - if (err < 0) goto pop_1_error; + if (err < 0) goto pop_1_error_tier_two; res = err ? Py_True : Py_False; stack_pointer[-1] = res; break; } - case TO_BOOL_BOOL: { + case _TO_BOOL_BOOL: { PyObject *value; value = stack_pointer[-1]; - DEOPT_IF(!PyBool_Check(value), TO_BOOL); + if (!PyBool_Check(value)) goto deoptimize; STAT_INC(TO_BOOL, hit); break; } - case TO_BOOL_INT: { + case _TO_BOOL_INT: { PyObject *value; PyObject *res; value = stack_pointer[-1]; - DEOPT_IF(!PyLong_CheckExact(value), TO_BOOL); + if (!PyLong_CheckExact(value)) goto deoptimize; STAT_INC(TO_BOOL, hit); if (_PyLong_IsZero((PyLongObject *)value)) { assert(_Py_IsImmortal(value)); @@ -151,11 +164,11 @@ break; } - case TO_BOOL_LIST: { + case _TO_BOOL_LIST: { PyObject *value; PyObject *res; value = stack_pointer[-1]; - DEOPT_IF(!PyList_CheckExact(value), TO_BOOL); + if (!PyList_CheckExact(value)) goto deoptimize; STAT_INC(TO_BOOL, hit); res = Py_SIZE(value) ? Py_True : Py_False; Py_DECREF(value); @@ -163,23 +176,23 @@ break; } - case TO_BOOL_NONE: { + case _TO_BOOL_NONE: { PyObject *value; PyObject *res; value = stack_pointer[-1]; // This one is a bit weird, because we expect *some* failures: - DEOPT_IF(!Py_IsNone(value), TO_BOOL); + if (!Py_IsNone(value)) goto deoptimize; STAT_INC(TO_BOOL, hit); res = Py_False; stack_pointer[-1] = res; break; } - case TO_BOOL_STR: { + case _TO_BOOL_STR: { PyObject *value; PyObject *res; value = stack_pointer[-1]; - DEOPT_IF(!PyUnicode_CheckExact(value), TO_BOOL); + if (!PyUnicode_CheckExact(value)) goto deoptimize; STAT_INC(TO_BOOL, hit); if (value == &_Py_STR(empty)) { assert(_Py_IsImmortal(value)); @@ -194,14 +207,14 @@ break; } - case TO_BOOL_ALWAYS_TRUE: { + case _TO_BOOL_ALWAYS_TRUE: { PyObject *value; PyObject *res; value = stack_pointer[-1]; - uint32_t version = (uint32_t)operand; + uint32_t version = (uint32_t)CURRENT_OPERAND(); // This one is a bit weird, because we expect *some* failures: assert(version); - DEOPT_IF(Py_TYPE(value)->tp_version_tag != version, TO_BOOL); + if (Py_TYPE(value)->tp_version_tag != version) goto deoptimize; STAT_INC(TO_BOOL, hit); Py_DECREF(value); res = Py_True; @@ -209,13 +222,13 @@ break; } - case UNARY_INVERT: { + case _UNARY_INVERT: { PyObject *value; PyObject *res; value = stack_pointer[-1]; res = PyNumber_Invert(value); Py_DECREF(value); - if (res == NULL) goto pop_1_error; + if (res == NULL) goto pop_1_error_tier_two; stack_pointer[-1] = res; break; } @@ -225,8 +238,8 @@ PyObject *left; right = stack_pointer[-1]; left = stack_pointer[-2]; - DEOPT_IF(!PyLong_CheckExact(left), BINARY_OP); - DEOPT_IF(!PyLong_CheckExact(right), BINARY_OP); + if (!PyLong_CheckExact(left)) goto deoptimize; + if (!PyLong_CheckExact(right)) goto deoptimize; break; } @@ -240,9 +253,9 @@ res = _PyLong_Multiply((PyLongObject *)left, (PyLongObject *)right); _Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free); _Py_DECREF_SPECIALIZED(left, (destructor)PyObject_Free); - if (res == NULL) goto pop_2_error; - STACK_SHRINK(1); - stack_pointer[-1] = res; + if (res == NULL) goto pop_2_error_tier_two; + stack_pointer[-2] = res; + stack_pointer += -1; break; } @@ -256,9 +269,9 @@ res = _PyLong_Add((PyLongObject *)left, (PyLongObject *)right); _Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free); _Py_DECREF_SPECIALIZED(left, (destructor)PyObject_Free); - if (res == NULL) goto pop_2_error; - STACK_SHRINK(1); - stack_pointer[-1] = res; + if (res == NULL) goto pop_2_error_tier_two; + stack_pointer[-2] = res; + stack_pointer += -1; break; } @@ -272,9 +285,9 @@ res = _PyLong_Subtract((PyLongObject *)left, (PyLongObject *)right); _Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free); _Py_DECREF_SPECIALIZED(left, (destructor)PyObject_Free); - if (res == NULL) goto pop_2_error; - STACK_SHRINK(1); - stack_pointer[-1] = res; + if (res == NULL) goto pop_2_error_tier_two; + stack_pointer[-2] = res; + stack_pointer += -1; break; } @@ -283,8 +296,8 @@ PyObject *left; right = stack_pointer[-1]; left = stack_pointer[-2]; - DEOPT_IF(!PyFloat_CheckExact(left), BINARY_OP); - DEOPT_IF(!PyFloat_CheckExact(right), BINARY_OP); + if (!PyFloat_CheckExact(left)) goto deoptimize; + if (!PyFloat_CheckExact(right)) goto deoptimize; break; } @@ -296,11 +309,11 @@ left = stack_pointer[-2]; STAT_INC(BINARY_OP, hit); double dres = - ((PyFloatObject *)left)->ob_fval * - ((PyFloatObject *)right)->ob_fval; + ((PyFloatObject *)left)->ob_fval * + ((PyFloatObject *)right)->ob_fval; DECREF_INPUTS_AND_REUSE_FLOAT(left, right, dres, res); - STACK_SHRINK(1); - stack_pointer[-1] = res; + stack_pointer[-2] = res; + stack_pointer += -1; break; } @@ -312,11 +325,11 @@ left = stack_pointer[-2]; STAT_INC(BINARY_OP, hit); double dres = - ((PyFloatObject *)left)->ob_fval + - ((PyFloatObject *)right)->ob_fval; + ((PyFloatObject *)left)->ob_fval + + ((PyFloatObject *)right)->ob_fval; DECREF_INPUTS_AND_REUSE_FLOAT(left, right, dres, res); - STACK_SHRINK(1); - stack_pointer[-1] = res; + stack_pointer[-2] = res; + stack_pointer += -1; break; } @@ -328,11 +341,11 @@ left = stack_pointer[-2]; STAT_INC(BINARY_OP, hit); double dres = - ((PyFloatObject *)left)->ob_fval - - ((PyFloatObject *)right)->ob_fval; + ((PyFloatObject *)left)->ob_fval - + ((PyFloatObject *)right)->ob_fval; DECREF_INPUTS_AND_REUSE_FLOAT(left, right, dres, res); - STACK_SHRINK(1); - stack_pointer[-1] = res; + stack_pointer[-2] = res; + stack_pointer += -1; break; } @@ -341,8 +354,8 @@ PyObject *left; right = stack_pointer[-1]; left = stack_pointer[-2]; - DEOPT_IF(!PyUnicode_CheckExact(left), BINARY_OP); - DEOPT_IF(!PyUnicode_CheckExact(right), BINARY_OP); + if (!PyUnicode_CheckExact(left)) goto deoptimize; + if (!PyUnicode_CheckExact(right)) goto deoptimize; break; } @@ -356,39 +369,28 @@ res = PyUnicode_Concat(left, right); _Py_DECREF_SPECIALIZED(left, _PyUnicode_ExactDealloc); _Py_DECREF_SPECIALIZED(right, _PyUnicode_ExactDealloc); - if (res == NULL) goto pop_2_error; - STACK_SHRINK(1); - stack_pointer[-1] = res; + if (res == NULL) goto pop_2_error_tier_two; + stack_pointer[-2] = res; + stack_pointer += -1; break; } - case BINARY_SUBSCR: { - static_assert(INLINE_CACHE_ENTRIES_BINARY_SUBSCR == 1, "incorrect cache size"); + case _BINARY_SUBSCR: { PyObject *sub; PyObject *container; PyObject *res; sub = stack_pointer[-1]; container = stack_pointer[-2]; - #if ENABLE_SPECIALIZATION - _PyBinarySubscrCache *cache = (_PyBinarySubscrCache *)next_instr; - if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) { - next_instr--; - _Py_Specialize_BinarySubscr(container, sub, next_instr); - DISPATCH_SAME_OPARG(); - } - STAT_INC(BINARY_SUBSCR, deferred); - DECREMENT_ADAPTIVE_COUNTER(cache->counter); - #endif /* ENABLE_SPECIALIZATION */ res = PyObject_GetItem(container, sub); Py_DECREF(container); Py_DECREF(sub); - if (res == NULL) goto pop_2_error; - STACK_SHRINK(1); - stack_pointer[-1] = res; + if (res == NULL) goto pop_2_error_tier_two; + stack_pointer[-2] = res; + stack_pointer += -1; break; } - case BINARY_SLICE: { + case _BINARY_SLICE: { PyObject *stop; PyObject *start; PyObject *container; @@ -407,13 +409,13 @@ Py_DECREF(slice); } Py_DECREF(container); - if (res == NULL) goto pop_3_error; - STACK_SHRINK(2); - stack_pointer[-1] = res; + if (res == NULL) goto pop_3_error_tier_two; + stack_pointer[-3] = res; + stack_pointer += -2; break; } - case STORE_SLICE: { + case _STORE_SLICE: { PyObject *stop; PyObject *start; PyObject *container; @@ -433,178 +435,186 @@ } Py_DECREF(v); Py_DECREF(container); - if (err) goto pop_4_error; - STACK_SHRINK(4); + if (err) goto pop_4_error_tier_two; + stack_pointer += -4; break; } - case BINARY_SUBSCR_LIST_INT: { + case _BINARY_SUBSCR_LIST_INT: { PyObject *sub; PyObject *list; PyObject *res; sub = stack_pointer[-1]; list = stack_pointer[-2]; - DEOPT_IF(!PyLong_CheckExact(sub), BINARY_SUBSCR); - DEOPT_IF(!PyList_CheckExact(list), BINARY_SUBSCR); - + if (!PyLong_CheckExact(sub)) goto deoptimize; + if (!PyList_CheckExact(list)) goto deoptimize; // Deopt unless 0 <= sub < PyList_Size(list) - DEOPT_IF(!_PyLong_IsNonNegativeCompact((PyLongObject *)sub), BINARY_SUBSCR); + if (!_PyLong_IsNonNegativeCompact((PyLongObject *)sub)) goto deoptimize; Py_ssize_t index = ((PyLongObject*)sub)->long_value.ob_digit[0]; - DEOPT_IF(index >= PyList_GET_SIZE(list), BINARY_SUBSCR); + if (index >= PyList_GET_SIZE(list)) goto deoptimize; STAT_INC(BINARY_SUBSCR, hit); res = PyList_GET_ITEM(list, index); assert(res != NULL); Py_INCREF(res); _Py_DECREF_SPECIALIZED(sub, (destructor)PyObject_Free); Py_DECREF(list); - STACK_SHRINK(1); - stack_pointer[-1] = res; + stack_pointer[-2] = res; + stack_pointer += -1; + break; + } + + case _BINARY_SUBSCR_STR_INT: { + PyObject *sub; + PyObject *str; + PyObject *res; + sub = stack_pointer[-1]; + str = stack_pointer[-2]; + if (!PyLong_CheckExact(sub)) goto deoptimize; + if (!PyUnicode_CheckExact(str)) goto deoptimize; + if (!_PyLong_IsNonNegativeCompact((PyLongObject *)sub)) goto deoptimize; + Py_ssize_t index = ((PyLongObject*)sub)->long_value.ob_digit[0]; + if (PyUnicode_GET_LENGTH(str) <= index) goto deoptimize; + // Specialize for reading an ASCII character from any string: + Py_UCS4 c = PyUnicode_READ_CHAR(str, index); + if (Py_ARRAY_LENGTH(_Py_SINGLETON(strings).ascii) <= c) goto deoptimize; + STAT_INC(BINARY_SUBSCR, hit); + res = (PyObject*)&_Py_SINGLETON(strings).ascii[c]; + _Py_DECREF_SPECIALIZED(sub, (destructor)PyObject_Free); + Py_DECREF(str); + stack_pointer[-2] = res; + stack_pointer += -1; break; } - case BINARY_SUBSCR_TUPLE_INT: { + case _BINARY_SUBSCR_TUPLE_INT: { PyObject *sub; PyObject *tuple; PyObject *res; sub = stack_pointer[-1]; tuple = stack_pointer[-2]; - DEOPT_IF(!PyLong_CheckExact(sub), BINARY_SUBSCR); - DEOPT_IF(!PyTuple_CheckExact(tuple), BINARY_SUBSCR); - + if (!PyLong_CheckExact(sub)) goto deoptimize; + if (!PyTuple_CheckExact(tuple)) goto deoptimize; // Deopt unless 0 <= sub < PyTuple_Size(list) - DEOPT_IF(!_PyLong_IsNonNegativeCompact((PyLongObject *)sub), BINARY_SUBSCR); + if (!_PyLong_IsNonNegativeCompact((PyLongObject *)sub)) goto deoptimize; Py_ssize_t index = ((PyLongObject*)sub)->long_value.ob_digit[0]; - DEOPT_IF(index >= PyTuple_GET_SIZE(tuple), BINARY_SUBSCR); + if (index >= PyTuple_GET_SIZE(tuple)) goto deoptimize; STAT_INC(BINARY_SUBSCR, hit); res = PyTuple_GET_ITEM(tuple, index); assert(res != NULL); Py_INCREF(res); _Py_DECREF_SPECIALIZED(sub, (destructor)PyObject_Free); Py_DECREF(tuple); - STACK_SHRINK(1); - stack_pointer[-1] = res; + stack_pointer[-2] = res; + stack_pointer += -1; break; } - case BINARY_SUBSCR_DICT: { + case _BINARY_SUBSCR_DICT: { PyObject *sub; PyObject *dict; PyObject *res; sub = stack_pointer[-1]; dict = stack_pointer[-2]; - DEOPT_IF(!PyDict_CheckExact(dict), BINARY_SUBSCR); + if (!PyDict_CheckExact(dict)) goto deoptimize; STAT_INC(BINARY_SUBSCR, hit); - res = PyDict_GetItemWithError(dict, sub); - if (res == NULL) { - if (!_PyErr_Occurred(tstate)) { - _PyErr_SetKeyError(sub); - } - Py_DECREF(dict); - Py_DECREF(sub); - if (true) goto pop_2_error; + int rc = PyDict_GetItemRef(dict, sub, &res); + if (rc == 0) { + _PyErr_SetKeyError(sub); } - Py_INCREF(res); // Do this before DECREF'ing dict, sub Py_DECREF(dict); Py_DECREF(sub); - STACK_SHRINK(1); - stack_pointer[-1] = res; + if (rc <= 0) goto pop_2_error_tier_two; + // not found or error + stack_pointer[-2] = res; + stack_pointer += -1; break; } - case LIST_APPEND: { + /* _BINARY_SUBSCR_GETITEM is not a viable micro-op for tier 2 */ + + case _LIST_APPEND: { PyObject *v; PyObject *list; + oparg = CURRENT_OPARG(); v = stack_pointer[-1]; list = stack_pointer[-2 - (oparg-1)]; - if (_PyList_AppendTakeRef((PyListObject *)list, v) < 0) goto pop_1_error; - STACK_SHRINK(1); + if (_PyList_AppendTakeRef((PyListObject *)list, v) < 0) goto pop_1_error_tier_two; + stack_pointer += -1; break; } - case SET_ADD: { + case _SET_ADD: { PyObject *v; PyObject *set; + oparg = CURRENT_OPARG(); v = stack_pointer[-1]; set = stack_pointer[-2 - (oparg-1)]; int err = PySet_Add(set, v); Py_DECREF(v); - if (err) goto pop_1_error; - STACK_SHRINK(1); + if (err) goto pop_1_error_tier_two; + stack_pointer += -1; break; } - case STORE_SUBSCR: { - static_assert(INLINE_CACHE_ENTRIES_STORE_SUBSCR == 1, "incorrect cache size"); + case _STORE_SUBSCR: { PyObject *sub; PyObject *container; PyObject *v; sub = stack_pointer[-1]; container = stack_pointer[-2]; v = stack_pointer[-3]; - #if ENABLE_SPECIALIZATION - _PyStoreSubscrCache *cache = (_PyStoreSubscrCache *)next_instr; - if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) { - next_instr--; - _Py_Specialize_StoreSubscr(container, sub, next_instr); - DISPATCH_SAME_OPARG(); - } - STAT_INC(STORE_SUBSCR, deferred); - DECREMENT_ADAPTIVE_COUNTER(cache->counter); - #endif /* ENABLE_SPECIALIZATION */ /* container[sub] = v */ int err = PyObject_SetItem(container, sub, v); Py_DECREF(v); Py_DECREF(container); Py_DECREF(sub); - if (err) goto pop_3_error; - STACK_SHRINK(3); + if (err) goto pop_3_error_tier_two; + stack_pointer += -3; break; } - case STORE_SUBSCR_LIST_INT: { + case _STORE_SUBSCR_LIST_INT: { PyObject *sub; PyObject *list; PyObject *value; sub = stack_pointer[-1]; list = stack_pointer[-2]; value = stack_pointer[-3]; - DEOPT_IF(!PyLong_CheckExact(sub), STORE_SUBSCR); - DEOPT_IF(!PyList_CheckExact(list), STORE_SUBSCR); - + if (!PyLong_CheckExact(sub)) goto deoptimize; + if (!PyList_CheckExact(list)) goto deoptimize; // Ensure nonnegative, zero-or-one-digit ints. - DEOPT_IF(!_PyLong_IsNonNegativeCompact((PyLongObject *)sub), STORE_SUBSCR); + if (!_PyLong_IsNonNegativeCompact((PyLongObject *)sub)) goto deoptimize; Py_ssize_t index = ((PyLongObject*)sub)->long_value.ob_digit[0]; // Ensure index < len(list) - DEOPT_IF(index >= PyList_GET_SIZE(list), STORE_SUBSCR); + if (index >= PyList_GET_SIZE(list)) goto deoptimize; STAT_INC(STORE_SUBSCR, hit); - PyObject *old_value = PyList_GET_ITEM(list, index); PyList_SET_ITEM(list, index, value); assert(old_value != NULL); Py_DECREF(old_value); _Py_DECREF_SPECIALIZED(sub, (destructor)PyObject_Free); Py_DECREF(list); - STACK_SHRINK(3); + stack_pointer += -3; break; } - case STORE_SUBSCR_DICT: { + case _STORE_SUBSCR_DICT: { PyObject *sub; PyObject *dict; PyObject *value; sub = stack_pointer[-1]; dict = stack_pointer[-2]; value = stack_pointer[-3]; - DEOPT_IF(!PyDict_CheckExact(dict), STORE_SUBSCR); + if (!PyDict_CheckExact(dict)) goto deoptimize; STAT_INC(STORE_SUBSCR, hit); int err = _PyDict_SetItem_Take2((PyDictObject *)dict, sub, value); Py_DECREF(dict); - if (err) goto pop_3_error; - STACK_SHRINK(3); + if (err) goto pop_3_error_tier_two; + stack_pointer += -3; break; } - case DELETE_SUBSCR: { + case _DELETE_SUBSCR: { PyObject *sub; PyObject *container; sub = stack_pointer[-1]; @@ -613,99 +623,124 @@ int err = PyObject_DelItem(container, sub); Py_DECREF(container); Py_DECREF(sub); - if (err) goto pop_2_error; - STACK_SHRINK(2); + if (err) goto pop_2_error_tier_two; + stack_pointer += -2; break; } - case CALL_INTRINSIC_1: { + case _CALL_INTRINSIC_1: { PyObject *value; PyObject *res; + oparg = CURRENT_OPARG(); value = stack_pointer[-1]; assert(oparg <= MAX_INTRINSIC_1); res = _PyIntrinsics_UnaryFunctions[oparg].func(tstate, value); Py_DECREF(value); - if (res == NULL) goto pop_1_error; + if (res == NULL) goto pop_1_error_tier_two; stack_pointer[-1] = res; break; } - case CALL_INTRINSIC_2: { + case _CALL_INTRINSIC_2: { PyObject *value1; PyObject *value2; PyObject *res; + oparg = CURRENT_OPARG(); value1 = stack_pointer[-1]; value2 = stack_pointer[-2]; assert(oparg <= MAX_INTRINSIC_2); res = _PyIntrinsics_BinaryFunctions[oparg].func(tstate, value2, value1); Py_DECREF(value2); Py_DECREF(value1); - if (res == NULL) goto pop_2_error; - STACK_SHRINK(1); - stack_pointer[-1] = res; + if (res == NULL) goto pop_2_error_tier_two; + stack_pointer[-2] = res; + stack_pointer += -1; + break; + } + + case _POP_FRAME: { + PyObject *retval; + retval = stack_pointer[-1]; + #if TIER_ONE + assert(frame != &entry_frame); + #endif + stack_pointer += -1; + _PyFrame_SetStackPointer(frame, stack_pointer); + assert(EMPTY()); + _Py_LeaveRecursiveCallPy(tstate); + // GH-99729: We need to unlink the frame *before* clearing it: + _PyInterpreterFrame *dying = frame; + frame = tstate->current_frame = dying->previous; + _PyEval_FrameClearAndPop(tstate, dying); + _PyFrame_StackPush(frame, retval); + LOAD_SP(); + LOAD_IP(frame->return_offset); + #if LLTRACE && TIER_ONE + lltrace = maybe_lltrace_resume_frame(frame, &entry_frame, GLOBALS()); + if (lltrace < 0) { + goto exit_unwind; + } + #endif break; } - case GET_AITER: { + /* _INSTRUMENTED_RETURN_VALUE is not a viable micro-op for tier 2 */ + + /* _INSTRUMENTED_RETURN_CONST is not a viable micro-op for tier 2 */ + + case _GET_AITER: { PyObject *obj; PyObject *iter; obj = stack_pointer[-1]; unaryfunc getter = NULL; PyTypeObject *type = Py_TYPE(obj); - if (type->tp_as_async != NULL) { getter = type->tp_as_async->am_aiter; } - if (getter == NULL) { _PyErr_Format(tstate, PyExc_TypeError, "'async for' requires an object with " "__aiter__ method, got %.100s", type->tp_name); Py_DECREF(obj); - if (true) goto pop_1_error; + if (true) goto pop_1_error_tier_two; } - iter = (*getter)(obj); Py_DECREF(obj); - if (iter == NULL) goto pop_1_error; - + if (iter == NULL) goto pop_1_error_tier_two; if (Py_TYPE(iter)->tp_as_async == NULL || - Py_TYPE(iter)->tp_as_async->am_anext == NULL) { - + Py_TYPE(iter)->tp_as_async->am_anext == NULL) { _PyErr_Format(tstate, PyExc_TypeError, "'async for' received an object from __aiter__ " "that does not implement __anext__: %.100s", Py_TYPE(iter)->tp_name); Py_DECREF(iter); - if (true) goto pop_1_error; + if (true) goto pop_1_error_tier_two; } stack_pointer[-1] = iter; break; } - case GET_ANEXT: { + case _GET_ANEXT: { PyObject *aiter; PyObject *awaitable; aiter = stack_pointer[-1]; unaryfunc getter = NULL; PyObject *next_iter = NULL; PyTypeObject *type = Py_TYPE(aiter); - if (PyAsyncGen_CheckExact(aiter)) { awaitable = type->tp_as_async->am_anext(aiter); if (awaitable == NULL) { - goto error; + GOTO_ERROR(error); } } else { if (type->tp_as_async != NULL){ getter = type->tp_as_async->am_anext; } - if (getter != NULL) { next_iter = (*getter)(aiter); if (next_iter == NULL) { - goto error; + GOTO_ERROR(error); } } else { @@ -713,9 +748,8 @@ "'async for' requires an iterator with " "__anext__ method, got %.100s", type->tp_name); - goto error; + GOTO_ERROR(error); } - awaitable = _PyCoro_GetAwaitableIter(next_iter); if (awaitable == NULL) { _PyErr_FormatFromCause( @@ -723,30 +757,27 @@ "'async for' received an invalid object " "from __anext__: %.100s", Py_TYPE(next_iter)->tp_name); - Py_DECREF(next_iter); - goto error; + GOTO_ERROR(error); } else { Py_DECREF(next_iter); } } - STACK_GROW(1); - stack_pointer[-1] = awaitable; + stack_pointer[0] = awaitable; + stack_pointer += 1; break; } - case GET_AWAITABLE: { + case _GET_AWAITABLE: { PyObject *iterable; PyObject *iter; + oparg = CURRENT_OPARG(); iterable = stack_pointer[-1]; iter = _PyCoro_GetAwaitableIter(iterable); - if (iter == NULL) { _PyEval_FormatAwaitableError(tstate, Py_TYPE(iterable), oparg); } - Py_DECREF(iterable); - if (iter != NULL && PyCoro_CheckExact(iter)) { PyObject *yf = _PyGen_yf((PyGenObject*)iter); if (yf != NULL) { @@ -760,44 +791,50 @@ /* The code below jumps to `error` if `iter` is NULL. */ } } - - if (iter == NULL) goto pop_1_error; + if (iter == NULL) goto pop_1_error_tier_two; stack_pointer[-1] = iter; break; } - case POP_EXCEPT: { + /* _SEND is not a viable micro-op for tier 2 */ + + /* _SEND_GEN is not a viable micro-op for tier 2 */ + + /* _INSTRUMENTED_YIELD_VALUE is not a viable micro-op for tier 2 */ + + case _POP_EXCEPT: { PyObject *exc_value; exc_value = stack_pointer[-1]; _PyErr_StackItem *exc_info = tstate->exc_info; - Py_XSETREF(exc_info->exc_value, exc_value); - STACK_SHRINK(1); + Py_XSETREF(exc_info->exc_value, exc_value == Py_None ? NULL : exc_value); + stack_pointer += -1; break; } - case LOAD_ASSERTION_ERROR: { + case _LOAD_ASSERTION_ERROR: { PyObject *value; value = Py_NewRef(PyExc_AssertionError); - STACK_GROW(1); - stack_pointer[-1] = value; + stack_pointer[0] = value; + stack_pointer += 1; break; } - case LOAD_BUILD_CLASS: { + case _LOAD_BUILD_CLASS: { PyObject *bc; - if (PyMapping_GetOptionalItem(BUILTINS(), &_Py_ID(__build_class__), &bc) < 0) goto error; + if (PyMapping_GetOptionalItem(BUILTINS(), &_Py_ID(__build_class__), &bc) < 0) goto error_tier_two; if (bc == NULL) { _PyErr_SetString(tstate, PyExc_NameError, "__build_class__ not found"); - if (true) goto error; + if (true) goto error_tier_two; } - STACK_GROW(1); - stack_pointer[-1] = bc; + stack_pointer[0] = bc; + stack_pointer += 1; break; } - case STORE_NAME: { + case _STORE_NAME: { PyObject *v; + oparg = CURRENT_OPARG(); v = stack_pointer[-1]; PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); PyObject *ns = LOCALS(); @@ -806,175 +843,158 @@ _PyErr_Format(tstate, PyExc_SystemError, "no locals found when storing %R", name); Py_DECREF(v); - if (true) goto pop_1_error; + if (true) goto pop_1_error_tier_two; } if (PyDict_CheckExact(ns)) - err = PyDict_SetItem(ns, name, v); + err = PyDict_SetItem(ns, name, v); else - err = PyObject_SetItem(ns, name, v); + err = PyObject_SetItem(ns, name, v); Py_DECREF(v); - if (err) goto pop_1_error; - STACK_SHRINK(1); + if (err) goto pop_1_error_tier_two; + stack_pointer += -1; break; } - case DELETE_NAME: { + case _DELETE_NAME: { + oparg = CURRENT_OPARG(); PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); PyObject *ns = LOCALS(); int err; if (ns == NULL) { _PyErr_Format(tstate, PyExc_SystemError, "no locals when deleting %R", name); - goto error; + GOTO_ERROR(error); } err = PyObject_DelItem(ns, name); // Can't use ERROR_IF here. if (err != 0) { _PyEval_FormatExcCheckArg(tstate, PyExc_NameError, - NAME_ERROR_MSG, - name); - goto error; + NAME_ERROR_MSG, + name); + GOTO_ERROR(error); } break; } - case UNPACK_SEQUENCE: { - static_assert(INLINE_CACHE_ENTRIES_UNPACK_SEQUENCE == 1, "incorrect cache size"); + case _UNPACK_SEQUENCE: { PyObject *seq; + oparg = CURRENT_OPARG(); seq = stack_pointer[-1]; - #if ENABLE_SPECIALIZATION - _PyUnpackSequenceCache *cache = (_PyUnpackSequenceCache *)next_instr; - if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) { - next_instr--; - _Py_Specialize_UnpackSequence(seq, next_instr, oparg); - DISPATCH_SAME_OPARG(); - } - STAT_INC(UNPACK_SEQUENCE, deferred); - DECREMENT_ADAPTIVE_COUNTER(cache->counter); - #endif /* ENABLE_SPECIALIZATION */ PyObject **top = stack_pointer + oparg - 1; int res = _PyEval_UnpackIterable(tstate, seq, oparg, -1, top); Py_DECREF(seq); - if (res == 0) goto pop_1_error; - STACK_SHRINK(1); - STACK_GROW(oparg); + if (res == 0) goto pop_1_error_tier_two; + stack_pointer += -1 + oparg; break; } - case UNPACK_SEQUENCE_TWO_TUPLE: { + case _UNPACK_SEQUENCE_TWO_TUPLE: { PyObject *seq; PyObject **values; + oparg = CURRENT_OPARG(); seq = stack_pointer[-1]; - values = stack_pointer - 1; - DEOPT_IF(!PyTuple_CheckExact(seq), UNPACK_SEQUENCE); - DEOPT_IF(PyTuple_GET_SIZE(seq) != 2, UNPACK_SEQUENCE); + values = &stack_pointer[-1]; + if (!PyTuple_CheckExact(seq)) goto deoptimize; + if (PyTuple_GET_SIZE(seq) != 2) goto deoptimize; assert(oparg == 2); STAT_INC(UNPACK_SEQUENCE, hit); values[0] = Py_NewRef(PyTuple_GET_ITEM(seq, 1)); values[1] = Py_NewRef(PyTuple_GET_ITEM(seq, 0)); Py_DECREF(seq); - STACK_SHRINK(1); - STACK_GROW(oparg); + stack_pointer += -1 + oparg; break; } - case UNPACK_SEQUENCE_TUPLE: { + case _UNPACK_SEQUENCE_TUPLE: { PyObject *seq; PyObject **values; + oparg = CURRENT_OPARG(); seq = stack_pointer[-1]; - values = stack_pointer - 1; - DEOPT_IF(!PyTuple_CheckExact(seq), UNPACK_SEQUENCE); - DEOPT_IF(PyTuple_GET_SIZE(seq) != oparg, UNPACK_SEQUENCE); + values = &stack_pointer[-1]; + if (!PyTuple_CheckExact(seq)) goto deoptimize; + if (PyTuple_GET_SIZE(seq) != oparg) goto deoptimize; STAT_INC(UNPACK_SEQUENCE, hit); PyObject **items = _PyTuple_ITEMS(seq); for (int i = oparg; --i >= 0; ) { *values++ = Py_NewRef(items[i]); } Py_DECREF(seq); - STACK_SHRINK(1); - STACK_GROW(oparg); + stack_pointer += -1 + oparg; break; } - case UNPACK_SEQUENCE_LIST: { + case _UNPACK_SEQUENCE_LIST: { PyObject *seq; PyObject **values; + oparg = CURRENT_OPARG(); seq = stack_pointer[-1]; - values = stack_pointer - 1; - DEOPT_IF(!PyList_CheckExact(seq), UNPACK_SEQUENCE); - DEOPT_IF(PyList_GET_SIZE(seq) != oparg, UNPACK_SEQUENCE); + values = &stack_pointer[-1]; + if (!PyList_CheckExact(seq)) goto deoptimize; + if (PyList_GET_SIZE(seq) != oparg) goto deoptimize; STAT_INC(UNPACK_SEQUENCE, hit); PyObject **items = _PyList_ITEMS(seq); for (int i = oparg; --i >= 0; ) { *values++ = Py_NewRef(items[i]); } Py_DECREF(seq); - STACK_SHRINK(1); - STACK_GROW(oparg); + stack_pointer += -1 + oparg; break; } - case UNPACK_EX: { + case _UNPACK_EX: { PyObject *seq; + oparg = CURRENT_OPARG(); seq = stack_pointer[-1]; int totalargs = 1 + (oparg & 0xFF) + (oparg >> 8); PyObject **top = stack_pointer + totalargs - 1; int res = _PyEval_UnpackIterable(tstate, seq, oparg & 0xFF, oparg >> 8, top); Py_DECREF(seq); - if (res == 0) goto pop_1_error; - STACK_GROW((oparg & 0xFF) + (oparg >> 8)); + if (res == 0) goto pop_1_error_tier_two; + stack_pointer += (oparg >> 8) + (oparg & 0xFF); break; } - case STORE_ATTR: { - static_assert(INLINE_CACHE_ENTRIES_STORE_ATTR == 4, "incorrect cache size"); + case _STORE_ATTR: { PyObject *owner; PyObject *v; + oparg = CURRENT_OPARG(); owner = stack_pointer[-1]; v = stack_pointer[-2]; - #if ENABLE_SPECIALIZATION - _PyAttrCache *cache = (_PyAttrCache *)next_instr; - if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) { - PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); - next_instr--; - _Py_Specialize_StoreAttr(owner, next_instr, name); - DISPATCH_SAME_OPARG(); - } - STAT_INC(STORE_ATTR, deferred); - DECREMENT_ADAPTIVE_COUNTER(cache->counter); - #endif /* ENABLE_SPECIALIZATION */ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); int err = PyObject_SetAttr(owner, name, v); Py_DECREF(v); Py_DECREF(owner); - if (err) goto pop_2_error; - STACK_SHRINK(2); + if (err) goto pop_2_error_tier_two; + stack_pointer += -2; break; } - case DELETE_ATTR: { + case _DELETE_ATTR: { PyObject *owner; + oparg = CURRENT_OPARG(); owner = stack_pointer[-1]; PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); int err = PyObject_DelAttr(owner, name); Py_DECREF(owner); - if (err) goto pop_1_error; - STACK_SHRINK(1); + if (err) goto pop_1_error_tier_two; + stack_pointer += -1; break; } - case STORE_GLOBAL: { + case _STORE_GLOBAL: { PyObject *v; + oparg = CURRENT_OPARG(); v = stack_pointer[-1]; PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); int err = PyDict_SetItem(GLOBALS(), name, v); Py_DECREF(v); - if (err) goto pop_1_error; - STACK_SHRINK(1); + if (err) goto pop_1_error_tier_two; + stack_pointer += -1; break; } - case DELETE_GLOBAL: { + case _DELETE_GLOBAL: { + oparg = CURRENT_OPARG(); PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); int err; err = PyDict_DelItem(GLOBALS(), name); @@ -982,9 +1002,9 @@ if (err != 0) { if (_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) { _PyEval_FormatExcCheckArg(tstate, PyExc_NameError, - NAME_ERROR_MSG, name); + NAME_ERROR_MSG, name); } - goto error; + GOTO_ERROR(error); } break; } @@ -995,232 +1015,267 @@ if (locals == NULL) { _PyErr_SetString(tstate, PyExc_SystemError, "no locals found"); - if (true) goto error; + if (true) goto error_tier_two; } Py_INCREF(locals); - STACK_GROW(1); - stack_pointer[-1] = locals; + stack_pointer[0] = locals; + stack_pointer += 1; break; } case _LOAD_FROM_DICT_OR_GLOBALS: { PyObject *mod_or_class_dict; PyObject *v; + oparg = CURRENT_OPARG(); mod_or_class_dict = stack_pointer[-1]; PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); if (PyMapping_GetOptionalItem(mod_or_class_dict, name, &v) < 0) { - Py_DECREF(mod_or_class_dict); - goto error; + GOTO_ERROR(error); } - Py_DECREF(mod_or_class_dict); if (v == NULL) { - v = PyDict_GetItemWithError(GLOBALS(), name); - if (v != NULL) { - Py_INCREF(v); - } - else if (_PyErr_Occurred(tstate)) { - goto error; + if (PyDict_GetItemRef(GLOBALS(), name, &v) < 0) { + GOTO_ERROR(error); } - else { + if (v == NULL) { if (PyMapping_GetOptionalItem(BUILTINS(), name, &v) < 0) { - goto error; + GOTO_ERROR(error); } if (v == NULL) { _PyEval_FormatExcCheckArg( - tstate, PyExc_NameError, - NAME_ERROR_MSG, name); - goto error; + tstate, PyExc_NameError, + NAME_ERROR_MSG, name); + GOTO_ERROR(error); } } } + Py_DECREF(mod_or_class_dict); stack_pointer[-1] = v; break; } - case LOAD_GLOBAL: { - static_assert(INLINE_CACHE_ENTRIES_LOAD_GLOBAL == 4, "incorrect cache size"); - PyObject *null = NULL; + case _LOAD_NAME: { PyObject *v; - #if ENABLE_SPECIALIZATION - _PyLoadGlobalCache *cache = (_PyLoadGlobalCache *)next_instr; - if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) { - PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1); - next_instr--; - _Py_Specialize_LoadGlobal(GLOBALS(), BUILTINS(), next_instr, name); - DISPATCH_SAME_OPARG(); - } - STAT_INC(LOAD_GLOBAL, deferred); - DECREMENT_ADAPTIVE_COUNTER(cache->counter); - #endif /* ENABLE_SPECIALIZATION */ + oparg = CURRENT_OPARG(); + PyObject *mod_or_class_dict = LOCALS(); + if (mod_or_class_dict == NULL) { + _PyErr_SetString(tstate, PyExc_SystemError, + "no locals found"); + if (true) goto error_tier_two; + } + PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); + if (PyMapping_GetOptionalItem(mod_or_class_dict, name, &v) < 0) { + GOTO_ERROR(error); + } + if (v == NULL) { + if (PyDict_GetItemRef(GLOBALS(), name, &v) < 0) { + GOTO_ERROR(error); + } + if (v == NULL) { + if (PyMapping_GetOptionalItem(BUILTINS(), name, &v) < 0) { + GOTO_ERROR(error); + } + if (v == NULL) { + _PyEval_FormatExcCheckArg( + tstate, PyExc_NameError, + NAME_ERROR_MSG, name); + GOTO_ERROR(error); + } + } + } + stack_pointer[0] = v; + stack_pointer += 1; + break; + } + + case _LOAD_GLOBAL: { + PyObject *res; + PyObject *null = NULL; + oparg = CURRENT_OPARG(); PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1); if (PyDict_CheckExact(GLOBALS()) && PyDict_CheckExact(BUILTINS())) { - v = _PyDict_LoadGlobal((PyDictObject *)GLOBALS(), - (PyDictObject *)BUILTINS(), - name); - if (v == NULL) { + res = _PyDict_LoadGlobal((PyDictObject *)GLOBALS(), + (PyDictObject *)BUILTINS(), + name); + if (res == NULL) { if (!_PyErr_Occurred(tstate)) { /* _PyDict_LoadGlobal() returns NULL without raising * an exception if the key doesn't exist */ _PyEval_FormatExcCheckArg(tstate, PyExc_NameError, - NAME_ERROR_MSG, name); + NAME_ERROR_MSG, name); } - if (true) goto error; + if (true) goto error_tier_two; } - Py_INCREF(v); + Py_INCREF(res); } else { /* Slow-path if globals or builtins is not a dict */ - /* namespace 1: globals */ - if (PyMapping_GetOptionalItem(GLOBALS(), name, &v) < 0) goto error; - if (v == NULL) { + if (PyMapping_GetOptionalItem(GLOBALS(), name, &res) < 0) goto error_tier_two; + if (res == NULL) { /* namespace 2: builtins */ - if (PyMapping_GetOptionalItem(BUILTINS(), name, &v) < 0) goto error; - if (v == NULL) { + if (PyMapping_GetOptionalItem(BUILTINS(), name, &res) < 0) goto error_tier_two; + if (res == NULL) { _PyEval_FormatExcCheckArg( - tstate, PyExc_NameError, - NAME_ERROR_MSG, name); - if (true) goto error; + tstate, PyExc_NameError, + NAME_ERROR_MSG, name); + if (true) goto error_tier_two; } } } null = NULL; - STACK_GROW(1); - STACK_GROW(((oparg & 1) ? 1 : 0)); - if (oparg & 1) { stack_pointer[-1 - (oparg & 1 ? 1 : 0)] = null; } - stack_pointer[-1] = v; + stack_pointer[0] = res; + if (oparg & 1) stack_pointer[1] = null; + stack_pointer += 1 + (oparg & 1); break; } case _GUARD_GLOBALS_VERSION: { - uint16_t version = (uint16_t)operand; + uint16_t version = (uint16_t)CURRENT_OPERAND(); PyDictObject *dict = (PyDictObject *)GLOBALS(); - DEOPT_IF(!PyDict_CheckExact(dict), LOAD_GLOBAL); - DEOPT_IF(dict->ma_keys->dk_version != version, LOAD_GLOBAL); + if (!PyDict_CheckExact(dict)) goto deoptimize; + if (dict->ma_keys->dk_version != version) goto deoptimize; assert(DK_IS_UNICODE(dict->ma_keys)); break; } case _GUARD_BUILTINS_VERSION: { - uint16_t version = (uint16_t)operand; + uint16_t version = (uint16_t)CURRENT_OPERAND(); PyDictObject *dict = (PyDictObject *)BUILTINS(); - DEOPT_IF(!PyDict_CheckExact(dict), LOAD_GLOBAL); - DEOPT_IF(dict->ma_keys->dk_version != version, LOAD_GLOBAL); + if (!PyDict_CheckExact(dict)) goto deoptimize; + if (dict->ma_keys->dk_version != version) goto deoptimize; assert(DK_IS_UNICODE(dict->ma_keys)); break; } case _LOAD_GLOBAL_MODULE: { - PyObject *null = NULL; PyObject *res; - uint16_t index = (uint16_t)operand; + PyObject *null = NULL; + oparg = CURRENT_OPARG(); + uint16_t index = (uint16_t)CURRENT_OPERAND(); PyDictObject *dict = (PyDictObject *)GLOBALS(); PyDictUnicodeEntry *entries = DK_UNICODE_ENTRIES(dict->ma_keys); res = entries[index].me_value; - DEOPT_IF(res == NULL, LOAD_GLOBAL); + if (res == NULL) goto deoptimize; Py_INCREF(res); STAT_INC(LOAD_GLOBAL, hit); null = NULL; - STACK_GROW(1); - STACK_GROW(((oparg & 1) ? 1 : 0)); - if (oparg & 1) { stack_pointer[-1 - (oparg & 1 ? 1 : 0)] = null; } - stack_pointer[-1] = res; + stack_pointer[0] = res; + if (oparg & 1) stack_pointer[1] = null; + stack_pointer += 1 + (oparg & 1); break; } case _LOAD_GLOBAL_BUILTINS: { - PyObject *null = NULL; PyObject *res; - uint16_t index = (uint16_t)operand; + PyObject *null = NULL; + oparg = CURRENT_OPARG(); + uint16_t index = (uint16_t)CURRENT_OPERAND(); PyDictObject *bdict = (PyDictObject *)BUILTINS(); PyDictUnicodeEntry *entries = DK_UNICODE_ENTRIES(bdict->ma_keys); res = entries[index].me_value; - DEOPT_IF(res == NULL, LOAD_GLOBAL); + if (res == NULL) goto deoptimize; Py_INCREF(res); STAT_INC(LOAD_GLOBAL, hit); null = NULL; - STACK_GROW(1); - STACK_GROW(((oparg & 1) ? 1 : 0)); - if (oparg & 1) { stack_pointer[-1 - (oparg & 1 ? 1 : 0)] = null; } - stack_pointer[-1] = res; + stack_pointer[0] = res; + if (oparg & 1) stack_pointer[1] = null; + stack_pointer += 1 + (oparg & 1); break; } - case DELETE_FAST: { + case _DELETE_FAST: { + oparg = CURRENT_OPARG(); PyObject *v = GETLOCAL(oparg); - if (v == NULL) goto unbound_local_error; + if (v == NULL) goto unbound_local_error_tier_two; SETLOCAL(oparg, NULL); break; } - case DELETE_DEREF: { + case _MAKE_CELL: { + oparg = CURRENT_OPARG(); + // "initial" is probably NULL but not if it's an arg (or set + // via PyFrame_LocalsToFast() before MAKE_CELL has run). + PyObject *initial = GETLOCAL(oparg); + PyObject *cell = PyCell_New(initial); + if (cell == NULL) { + GOTO_ERROR(error); + } + SETLOCAL(oparg, cell); + break; + } + + case _DELETE_DEREF: { + oparg = CURRENT_OPARG(); PyObject *cell = GETLOCAL(oparg); PyObject *oldobj = PyCell_GET(cell); // Can't use ERROR_IF here. // Fortunately we don't need its superpower. if (oldobj == NULL) { _PyEval_FormatExcUnbound(tstate, _PyFrame_GetCode(frame), oparg); - goto error; + GOTO_ERROR(error); } PyCell_SET(cell, NULL); Py_DECREF(oldobj); break; } - case LOAD_FROM_DICT_OR_DEREF: { + case _LOAD_FROM_DICT_OR_DEREF: { PyObject *class_dict; PyObject *value; + oparg = CURRENT_OPARG(); class_dict = stack_pointer[-1]; PyObject *name; assert(class_dict); assert(oparg >= 0 && oparg < _PyFrame_GetCode(frame)->co_nlocalsplus); name = PyTuple_GET_ITEM(_PyFrame_GetCode(frame)->co_localsplusnames, oparg); if (PyMapping_GetOptionalItem(class_dict, name, &value) < 0) { - Py_DECREF(class_dict); - goto error; + GOTO_ERROR(error); } - Py_DECREF(class_dict); if (!value) { PyObject *cell = GETLOCAL(oparg); value = PyCell_GET(cell); if (value == NULL) { _PyEval_FormatExcUnbound(tstate, _PyFrame_GetCode(frame), oparg); - goto error; + GOTO_ERROR(error); } Py_INCREF(value); } + Py_DECREF(class_dict); stack_pointer[-1] = value; break; } - case LOAD_DEREF: { + case _LOAD_DEREF: { PyObject *value; + oparg = CURRENT_OPARG(); PyObject *cell = GETLOCAL(oparg); value = PyCell_GET(cell); if (value == NULL) { _PyEval_FormatExcUnbound(tstate, _PyFrame_GetCode(frame), oparg); - if (true) goto error; + if (true) goto error_tier_two; } Py_INCREF(value); - STACK_GROW(1); - stack_pointer[-1] = value; + stack_pointer[0] = value; + stack_pointer += 1; break; } - case STORE_DEREF: { + case _STORE_DEREF: { PyObject *v; + oparg = CURRENT_OPARG(); v = stack_pointer[-1]; PyObject *cell = GETLOCAL(oparg); PyObject *oldobj = PyCell_GET(cell); PyCell_SET(cell, v); Py_XDECREF(oldobj); - STACK_SHRINK(1); + stack_pointer += -1; break; } - case COPY_FREE_VARS: { + case _COPY_FREE_VARS: { + oparg = CURRENT_OPARG(); /* Copy closure variables to free variables */ PyCodeObject *co = _PyFrame_GetCode(frame); assert(PyFunction_Check(frame->f_funcobj)); @@ -1234,366 +1289,341 @@ break; } - case BUILD_STRING: { + case _BUILD_STRING: { PyObject **pieces; PyObject *str; - pieces = stack_pointer - oparg; + oparg = CURRENT_OPARG(); + pieces = &stack_pointer[-oparg]; str = _PyUnicode_JoinArray(&_Py_STR(empty), pieces, oparg); for (int _i = oparg; --_i >= 0;) { Py_DECREF(pieces[_i]); } - if (str == NULL) { STACK_SHRINK(oparg); goto error; } - STACK_SHRINK(oparg); - STACK_GROW(1); - stack_pointer[-1] = str; + if (str == NULL) { stack_pointer += -oparg; goto error_tier_two; } + stack_pointer[-oparg] = str; + stack_pointer += 1 - oparg; break; } - case BUILD_TUPLE: { + case _BUILD_TUPLE: { PyObject **values; PyObject *tup; - values = stack_pointer - oparg; + oparg = CURRENT_OPARG(); + values = &stack_pointer[-oparg]; tup = _PyTuple_FromArraySteal(values, oparg); - if (tup == NULL) { STACK_SHRINK(oparg); goto error; } - STACK_SHRINK(oparg); - STACK_GROW(1); - stack_pointer[-1] = tup; + if (tup == NULL) { stack_pointer += -oparg; goto error_tier_two; } + stack_pointer[-oparg] = tup; + stack_pointer += 1 - oparg; break; } - case BUILD_LIST: { + case _BUILD_LIST: { PyObject **values; PyObject *list; - values = stack_pointer - oparg; + oparg = CURRENT_OPARG(); + values = &stack_pointer[-oparg]; list = _PyList_FromArraySteal(values, oparg); - if (list == NULL) { STACK_SHRINK(oparg); goto error; } - STACK_SHRINK(oparg); - STACK_GROW(1); - stack_pointer[-1] = list; + if (list == NULL) { stack_pointer += -oparg; goto error_tier_two; } + stack_pointer[-oparg] = list; + stack_pointer += 1 - oparg; break; } - case LIST_EXTEND: { + case _LIST_EXTEND: { PyObject *iterable; PyObject *list; + oparg = CURRENT_OPARG(); iterable = stack_pointer[-1]; list = stack_pointer[-2 - (oparg-1)]; PyObject *none_val = _PyList_Extend((PyListObject *)list, iterable); if (none_val == NULL) { if (_PyErr_ExceptionMatches(tstate, PyExc_TypeError) && - (Py_TYPE(iterable)->tp_iter == NULL && !PySequence_Check(iterable))) + (Py_TYPE(iterable)->tp_iter == NULL && !PySequence_Check(iterable))) { _PyErr_Clear(tstate); _PyErr_Format(tstate, PyExc_TypeError, - "Value after * must be an iterable, not %.200s", - Py_TYPE(iterable)->tp_name); + "Value after * must be an iterable, not %.200s", + Py_TYPE(iterable)->tp_name); } Py_DECREF(iterable); - if (true) goto pop_1_error; + if (true) goto pop_1_error_tier_two; } assert(Py_IsNone(none_val)); Py_DECREF(iterable); - STACK_SHRINK(1); + stack_pointer += -1; break; } - case SET_UPDATE: { + case _SET_UPDATE: { PyObject *iterable; PyObject *set; + oparg = CURRENT_OPARG(); iterable = stack_pointer[-1]; set = stack_pointer[-2 - (oparg-1)]; int err = _PySet_Update(set, iterable); Py_DECREF(iterable); - if (err < 0) goto pop_1_error; - STACK_SHRINK(1); + if (err < 0) goto pop_1_error_tier_two; + stack_pointer += -1; break; } - case BUILD_SET: { + case _BUILD_SET: { PyObject **values; PyObject *set; - values = stack_pointer - oparg; + oparg = CURRENT_OPARG(); + values = &stack_pointer[-oparg]; set = PySet_New(NULL); if (set == NULL) - goto error; + GOTO_ERROR(error); int err = 0; for (int i = 0; i < oparg; i++) { PyObject *item = values[i]; if (err == 0) - err = PySet_Add(set, item); + err = PySet_Add(set, item); Py_DECREF(item); } if (err != 0) { Py_DECREF(set); - if (true) { STACK_SHRINK(oparg); goto error; } + if (true) { stack_pointer += -oparg; goto error_tier_two; } } - STACK_SHRINK(oparg); - STACK_GROW(1); - stack_pointer[-1] = set; + stack_pointer[-oparg] = set; + stack_pointer += 1 - oparg; break; } - case BUILD_MAP: { + case _BUILD_MAP: { PyObject **values; PyObject *map; - values = stack_pointer - oparg*2; + oparg = CURRENT_OPARG(); + values = &stack_pointer[-oparg*2]; map = _PyDict_FromItems( - values, 2, - values+1, 2, - oparg); - if (map == NULL) - goto error; - + values, 2, + values+1, 2, + oparg); for (int _i = oparg*2; --_i >= 0;) { Py_DECREF(values[_i]); } - if (map == NULL) { STACK_SHRINK(oparg*2); goto error; } - STACK_SHRINK(oparg*2); - STACK_GROW(1); - stack_pointer[-1] = map; + if (map == NULL) { stack_pointer += -oparg*2; goto error_tier_two; } + stack_pointer[-oparg*2] = map; + stack_pointer += 1 - oparg*2; break; } - case SETUP_ANNOTATIONS: { + case _SETUP_ANNOTATIONS: { int err; PyObject *ann_dict; if (LOCALS() == NULL) { _PyErr_Format(tstate, PyExc_SystemError, "no locals found when setting up annotations"); - if (true) goto error; + if (true) goto error_tier_two; } /* check if __annotations__ in locals()... */ - if (PyDict_CheckExact(LOCALS())) { - ann_dict = _PyDict_GetItemWithError(LOCALS(), - &_Py_ID(__annotations__)); - if (ann_dict == NULL) { - if (_PyErr_Occurred(tstate)) goto error; - /* ...if not, create a new one */ - ann_dict = PyDict_New(); - if (ann_dict == NULL) goto error; - err = PyDict_SetItem(LOCALS(), &_Py_ID(__annotations__), - ann_dict); - Py_DECREF(ann_dict); - if (err) goto error; - } + if (PyMapping_GetOptionalItem(LOCALS(), &_Py_ID(__annotations__), &ann_dict) < 0) goto error_tier_two; + if (ann_dict == NULL) { + ann_dict = PyDict_New(); + if (ann_dict == NULL) goto error_tier_two; + err = PyObject_SetItem(LOCALS(), &_Py_ID(__annotations__), + ann_dict); + Py_DECREF(ann_dict); + if (err) goto error_tier_two; } else { - /* do the same if locals() is not a dict */ - if (PyMapping_GetOptionalItem(LOCALS(), &_Py_ID(__annotations__), &ann_dict) < 0) goto error; - if (ann_dict == NULL) { - ann_dict = PyDict_New(); - if (ann_dict == NULL) goto error; - err = PyObject_SetItem(LOCALS(), &_Py_ID(__annotations__), - ann_dict); - Py_DECREF(ann_dict); - if (err) goto error; - } - else { - Py_DECREF(ann_dict); - } + Py_DECREF(ann_dict); } break; } - case BUILD_CONST_KEY_MAP: { + case _BUILD_CONST_KEY_MAP: { PyObject *keys; PyObject **values; PyObject *map; + oparg = CURRENT_OPARG(); keys = stack_pointer[-1]; - values = stack_pointer - 1 - oparg; + values = &stack_pointer[-1 - oparg]; if (!PyTuple_CheckExact(keys) || PyTuple_GET_SIZE(keys) != (Py_ssize_t)oparg) { _PyErr_SetString(tstate, PyExc_SystemError, "bad BUILD_CONST_KEY_MAP keys argument"); - goto error; // Pop the keys and values. + GOTO_ERROR(error); // Pop the keys and values. } map = _PyDict_FromItems( - &PyTuple_GET_ITEM(keys, 0), 1, - values, 1, oparg); + &PyTuple_GET_ITEM(keys, 0), 1, + values, 1, oparg); for (int _i = oparg; --_i >= 0;) { Py_DECREF(values[_i]); } Py_DECREF(keys); - if (map == NULL) { STACK_SHRINK(oparg); goto pop_1_error; } - STACK_SHRINK(oparg); - stack_pointer[-1] = map; + if (map == NULL) { stack_pointer += -1 - oparg; goto error_tier_two; } + stack_pointer[-1 - oparg] = map; + stack_pointer += -oparg; break; } - case DICT_UPDATE: { + case _DICT_UPDATE: { PyObject *update; + PyObject *dict; + oparg = CURRENT_OPARG(); update = stack_pointer[-1]; - PyObject *dict = PEEK(oparg + 1); // update is still on the stack + dict = stack_pointer[-2 - (oparg - 1)]; if (PyDict_Update(dict, update) < 0) { if (_PyErr_ExceptionMatches(tstate, PyExc_AttributeError)) { _PyErr_Format(tstate, PyExc_TypeError, - "'%.200s' object is not a mapping", - Py_TYPE(update)->tp_name); + "'%.200s' object is not a mapping", + Py_TYPE(update)->tp_name); } Py_DECREF(update); - if (true) goto pop_1_error; + if (true) goto pop_1_error_tier_two; } Py_DECREF(update); - STACK_SHRINK(1); + stack_pointer += -1; break; } - case DICT_MERGE: { + case _DICT_MERGE: { PyObject *update; + PyObject *dict; + PyObject *callable; + oparg = CURRENT_OPARG(); update = stack_pointer[-1]; - PyObject *dict = PEEK(oparg + 1); // update is still on the stack - + dict = stack_pointer[-2 - (oparg - 1)]; + callable = stack_pointer[-5 - (oparg - 1)]; if (_PyDict_MergeEx(dict, update, 2) < 0) { - _PyEval_FormatKwargsError(tstate, PEEK(3 + oparg), update); + _PyEval_FormatKwargsError(tstate, callable, update); Py_DECREF(update); - if (true) goto pop_1_error; + if (true) goto pop_1_error_tier_two; } Py_DECREF(update); - STACK_SHRINK(1); + stack_pointer += -1; break; } - case MAP_ADD: { + case _MAP_ADD: { PyObject *value; PyObject *key; + PyObject *dict; + oparg = CURRENT_OPARG(); value = stack_pointer[-1]; key = stack_pointer[-2]; - PyObject *dict = PEEK(oparg + 2); // key, value are still on the stack + dict = stack_pointer[-3 - (oparg - 1)]; assert(PyDict_CheckExact(dict)); /* dict[key] = value */ // Do not DECREF INPUTS because the function steals the references - if (_PyDict_SetItem_Take2((PyDictObject *)dict, key, value) != 0) goto pop_2_error; - STACK_SHRINK(2); + if (_PyDict_SetItem_Take2((PyDictObject *)dict, key, value) != 0) goto pop_2_error_tier_two; + stack_pointer += -2; break; } - case LOAD_SUPER_ATTR_ATTR: { + /* _INSTRUMENTED_LOAD_SUPER_ATTR is not a viable micro-op for tier 2 */ + + case _LOAD_SUPER_ATTR_ATTR: { PyObject *self; PyObject *class; PyObject *global_super; - PyObject *res2 = NULL; - PyObject *res; + PyObject *attr; + oparg = CURRENT_OPARG(); self = stack_pointer[-1]; class = stack_pointer[-2]; global_super = stack_pointer[-3]; assert(!(oparg & 1)); - DEOPT_IF(global_super != (PyObject *)&PySuper_Type, LOAD_SUPER_ATTR); - DEOPT_IF(!PyType_Check(class), LOAD_SUPER_ATTR); + if (global_super != (PyObject *)&PySuper_Type) goto deoptimize; + if (!PyType_Check(class)) goto deoptimize; STAT_INC(LOAD_SUPER_ATTR, hit); PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 2); - res = _PySuper_Lookup((PyTypeObject *)class, self, name, NULL); + attr = _PySuper_Lookup((PyTypeObject *)class, self, name, NULL); Py_DECREF(global_super); Py_DECREF(class); Py_DECREF(self); - if (res == NULL) goto pop_3_error; - STACK_SHRINK(2); - STACK_GROW(((oparg & 1) ? 1 : 0)); - if (oparg & 1) { stack_pointer[-1 - (oparg & 1 ? 1 : 0)] = res2; } - stack_pointer[-1] = res; + if (attr == NULL) goto pop_3_error_tier_two; + stack_pointer[-3] = attr; + stack_pointer += -2 + ((0) ? 1 : 0); break; } - case LOAD_SUPER_ATTR_METHOD: { + case _LOAD_SUPER_ATTR_METHOD: { PyObject *self; PyObject *class; PyObject *global_super; - PyObject *res2; - PyObject *res; + PyObject *attr; + PyObject *self_or_null; + oparg = CURRENT_OPARG(); self = stack_pointer[-1]; class = stack_pointer[-2]; global_super = stack_pointer[-3]; assert(oparg & 1); - DEOPT_IF(global_super != (PyObject *)&PySuper_Type, LOAD_SUPER_ATTR); - DEOPT_IF(!PyType_Check(class), LOAD_SUPER_ATTR); + if (global_super != (PyObject *)&PySuper_Type) goto deoptimize; + if (!PyType_Check(class)) goto deoptimize; STAT_INC(LOAD_SUPER_ATTR, hit); PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 2); PyTypeObject *cls = (PyTypeObject *)class; int method_found = 0; - res2 = _PySuper_Lookup(cls, self, name, + attr = _PySuper_Lookup(cls, self, name, Py_TYPE(self)->tp_getattro == PyObject_GenericGetAttr ? &method_found : NULL); Py_DECREF(global_super); Py_DECREF(class); - if (res2 == NULL) { + if (attr == NULL) { Py_DECREF(self); - if (true) goto pop_3_error; + if (true) goto pop_3_error_tier_two; } if (method_found) { - res = self; // transfer ownership + self_or_null = self; // transfer ownership } else { Py_DECREF(self); - res = res2; - res2 = NULL; + self_or_null = NULL; } - STACK_SHRINK(1); - stack_pointer[-2] = res2; - stack_pointer[-1] = res; + stack_pointer[-3] = attr; + stack_pointer[-2] = self_or_null; + stack_pointer += -1; break; } - case LOAD_ATTR: { - static_assert(INLINE_CACHE_ENTRIES_LOAD_ATTR == 9, "incorrect cache size"); + case _LOAD_ATTR: { PyObject *owner; - PyObject *res2 = NULL; - PyObject *res; + PyObject *attr; + PyObject *self_or_null = NULL; + oparg = CURRENT_OPARG(); owner = stack_pointer[-1]; - #if ENABLE_SPECIALIZATION - _PyAttrCache *cache = (_PyAttrCache *)next_instr; - if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) { - PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1); - next_instr--; - _Py_Specialize_LoadAttr(owner, next_instr, name); - DISPATCH_SAME_OPARG(); - } - STAT_INC(LOAD_ATTR, deferred); - DECREMENT_ADAPTIVE_COUNTER(cache->counter); - #endif /* ENABLE_SPECIALIZATION */ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 1); if (oparg & 1) { /* Designed to work in tandem with CALL, pushes two values. */ - PyObject* meth = NULL; - if (_PyObject_GetMethod(owner, name, &meth)) { + attr = NULL; + if (_PyObject_GetMethod(owner, name, &attr)) { /* We can bypass temporary bound method object. meth is unbound method and obj is self. - meth | self | arg1 | ... | argN */ - assert(meth != NULL); // No errors on this branch - res2 = meth; - res = owner; // Transfer ownership + assert(attr != NULL); // No errors on this branch + self_or_null = owner; // Transfer ownership } else { /* meth is not an unbound method (but a regular attr, or something was returned by a descriptor protocol). Set the second element of the stack to NULL, to signal CALL that it's not a method call. - NULL | meth | arg1 | ... | argN - */ + */ Py_DECREF(owner); - if (meth == NULL) goto pop_1_error; - res2 = NULL; - res = meth; + if (attr == NULL) goto pop_1_error_tier_two; + self_or_null = NULL; } } else { /* Classic, pushes one value. */ - res = PyObject_GetAttr(owner, name); + attr = PyObject_GetAttr(owner, name); Py_DECREF(owner); - if (res == NULL) goto pop_1_error; + if (attr == NULL) goto pop_1_error_tier_two; } - STACK_GROW(((oparg & 1) ? 1 : 0)); - if (oparg & 1) { stack_pointer[-1 - (oparg & 1 ? 1 : 0)] = res2; } - stack_pointer[-1] = res; + stack_pointer[-1] = attr; + if (oparg & 1) stack_pointer[0] = self_or_null; + stack_pointer += (oparg & 1); break; } case _GUARD_TYPE_VERSION: { PyObject *owner; owner = stack_pointer[-1]; - uint32_t type_version = (uint32_t)operand; + uint32_t type_version = (uint32_t)CURRENT_OPERAND(); PyTypeObject *tp = Py_TYPE(owner); assert(type_version != 0); - DEOPT_IF(tp->tp_version_tag != type_version, LOAD_ATTR); + if (tp->tp_version_tag != type_version) goto deoptimize; break; } @@ -1602,71 +1632,242 @@ owner = stack_pointer[-1]; assert(Py_TYPE(owner)->tp_dictoffset < 0); assert(Py_TYPE(owner)->tp_flags & Py_TPFLAGS_MANAGED_DICT); - PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner); - DEOPT_IF(!_PyDictOrValues_IsValues(dorv), LOAD_ATTR); + PyDictOrValues *dorv = _PyObject_DictOrValuesPointer(owner); + if (!_PyDictOrValues_IsValues(*dorv) && !_PyObject_MakeInstanceAttributesFromDict(owner, dorv)) goto deoptimize; break; } case _LOAD_ATTR_INSTANCE_VALUE: { PyObject *owner; - PyObject *res2 = NULL; - PyObject *res; + PyObject *attr; + PyObject *null = NULL; + oparg = CURRENT_OPARG(); owner = stack_pointer[-1]; - uint16_t index = (uint16_t)operand; + uint16_t index = (uint16_t)CURRENT_OPERAND(); PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner); - res = _PyDictOrValues_GetValues(dorv)->values[index]; - DEOPT_IF(res == NULL, LOAD_ATTR); + attr = _PyDictOrValues_GetValues(dorv)->values[index]; + if (attr == NULL) goto deoptimize; STAT_INC(LOAD_ATTR, hit); - Py_INCREF(res); - res2 = NULL; + Py_INCREF(attr); + null = NULL; Py_DECREF(owner); - STACK_GROW(((oparg & 1) ? 1 : 0)); - if (oparg & 1) { stack_pointer[-1 - (oparg & 1 ? 1 : 0)] = res2; } - stack_pointer[-1] = res; + stack_pointer[-1] = attr; + if (oparg & 1) stack_pointer[0] = null; + stack_pointer += (oparg & 1); + break; + } + + case _CHECK_ATTR_MODULE: { + PyObject *owner; + owner = stack_pointer[-1]; + uint32_t type_version = (uint32_t)CURRENT_OPERAND(); + if (!PyModule_CheckExact(owner)) goto deoptimize; + PyDictObject *dict = (PyDictObject *)((PyModuleObject *)owner)->md_dict; + assert(dict != NULL); + if (dict->ma_keys->dk_version != type_version) goto deoptimize; + break; + } + + case _LOAD_ATTR_MODULE: { + PyObject *owner; + PyObject *attr; + PyObject *null = NULL; + oparg = CURRENT_OPARG(); + owner = stack_pointer[-1]; + uint16_t index = (uint16_t)CURRENT_OPERAND(); + PyDictObject *dict = (PyDictObject *)((PyModuleObject *)owner)->md_dict; + assert(dict->ma_keys->dk_kind == DICT_KEYS_UNICODE); + assert(index < dict->ma_keys->dk_nentries); + PyDictUnicodeEntry *ep = DK_UNICODE_ENTRIES(dict->ma_keys) + index; + attr = ep->me_value; + if (attr == NULL) goto deoptimize; + STAT_INC(LOAD_ATTR, hit); + Py_INCREF(attr); + null = NULL; + Py_DECREF(owner); + stack_pointer[-1] = attr; + if (oparg & 1) stack_pointer[0] = null; + stack_pointer += (oparg & 1); + break; + } + + case _CHECK_ATTR_WITH_HINT: { + PyObject *owner; + owner = stack_pointer[-1]; + assert(Py_TYPE(owner)->tp_flags & Py_TPFLAGS_MANAGED_DICT); + PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner); + if (_PyDictOrValues_IsValues(dorv)) goto deoptimize; + PyDictObject *dict = (PyDictObject *)_PyDictOrValues_GetDict(dorv); + if (dict == NULL) goto deoptimize; + assert(PyDict_CheckExact((PyObject *)dict)); + break; + } + + case _LOAD_ATTR_WITH_HINT: { + PyObject *owner; + PyObject *attr; + PyObject *null = NULL; + oparg = CURRENT_OPARG(); + owner = stack_pointer[-1]; + uint16_t hint = (uint16_t)CURRENT_OPERAND(); + PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner); + PyDictObject *dict = (PyDictObject *)_PyDictOrValues_GetDict(dorv); + if (hint >= (size_t)dict->ma_keys->dk_nentries) goto deoptimize; + PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1); + if (DK_IS_UNICODE(dict->ma_keys)) { + PyDictUnicodeEntry *ep = DK_UNICODE_ENTRIES(dict->ma_keys) + hint; + if (ep->me_key != name) goto deoptimize; + attr = ep->me_value; + } + else { + PyDictKeyEntry *ep = DK_ENTRIES(dict->ma_keys) + hint; + if (ep->me_key != name) goto deoptimize; + attr = ep->me_value; + } + if (attr == NULL) goto deoptimize; + STAT_INC(LOAD_ATTR, hit); + Py_INCREF(attr); + null = NULL; + Py_DECREF(owner); + stack_pointer[-1] = attr; + if (oparg & 1) stack_pointer[0] = null; + stack_pointer += (oparg & 1); + break; + } + + case _LOAD_ATTR_SLOT: { + PyObject *owner; + PyObject *attr; + PyObject *null = NULL; + oparg = CURRENT_OPARG(); + owner = stack_pointer[-1]; + uint16_t index = (uint16_t)CURRENT_OPERAND(); + char *addr = (char *)owner + index; + attr = *(PyObject **)addr; + if (attr == NULL) goto deoptimize; + STAT_INC(LOAD_ATTR, hit); + Py_INCREF(attr); + null = NULL; + Py_DECREF(owner); + stack_pointer[-1] = attr; + if (oparg & 1) stack_pointer[0] = null; + stack_pointer += (oparg & 1); + break; + } + + case _CHECK_ATTR_CLASS: { + PyObject *owner; + owner = stack_pointer[-1]; + uint32_t type_version = (uint32_t)CURRENT_OPERAND(); + if (!PyType_Check(owner)) goto deoptimize; + assert(type_version != 0); + if (((PyTypeObject *)owner)->tp_version_tag != type_version) goto deoptimize; + break; + } + + case _LOAD_ATTR_CLASS: { + PyObject *owner; + PyObject *attr; + PyObject *null = NULL; + oparg = CURRENT_OPARG(); + owner = stack_pointer[-1]; + PyObject *descr = (PyObject *)CURRENT_OPERAND(); + STAT_INC(LOAD_ATTR, hit); + assert(descr != NULL); + attr = Py_NewRef(descr); + null = NULL; + Py_DECREF(owner); + stack_pointer[-1] = attr; + if (oparg & 1) stack_pointer[0] = null; + stack_pointer += (oparg & 1); + break; + } + + /* _LOAD_ATTR_PROPERTY is not a viable micro-op for tier 2 */ + + /* _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN is not a viable micro-op for tier 2 */ + + case _GUARD_DORV_VALUES: { + PyObject *owner; + owner = stack_pointer[-1]; + assert(Py_TYPE(owner)->tp_flags & Py_TPFLAGS_MANAGED_DICT); + PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner); + if (!_PyDictOrValues_IsValues(dorv)) goto deoptimize; + break; + } + + case _STORE_ATTR_INSTANCE_VALUE: { + PyObject *owner; + PyObject *value; + owner = stack_pointer[-1]; + value = stack_pointer[-2]; + uint16_t index = (uint16_t)CURRENT_OPERAND(); + PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner); + STAT_INC(STORE_ATTR, hit); + PyDictValues *values = _PyDictOrValues_GetValues(dorv); + PyObject *old_value = values->values[index]; + values->values[index] = value; + if (old_value == NULL) { + _PyDictValues_AddToInsertionOrder(values, index); + } + else { + Py_DECREF(old_value); + } + Py_DECREF(owner); + stack_pointer += -2; + break; + } + + /* _STORE_ATTR_WITH_HINT is not a viable micro-op for tier 2 */ + + case _STORE_ATTR_SLOT: { + PyObject *owner; + PyObject *value; + owner = stack_pointer[-1]; + value = stack_pointer[-2]; + uint16_t index = (uint16_t)CURRENT_OPERAND(); + char *addr = (char *)owner + index; + STAT_INC(STORE_ATTR, hit); + PyObject *old_value = *(PyObject **)addr; + *(PyObject **)addr = value; + Py_XDECREF(old_value); + Py_DECREF(owner); + stack_pointer += -2; break; } - case COMPARE_OP: { - static_assert(INLINE_CACHE_ENTRIES_COMPARE_OP == 1, "incorrect cache size"); + case _COMPARE_OP: { PyObject *right; PyObject *left; PyObject *res; + oparg = CURRENT_OPARG(); right = stack_pointer[-1]; left = stack_pointer[-2]; - #if ENABLE_SPECIALIZATION - _PyCompareOpCache *cache = (_PyCompareOpCache *)next_instr; - if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) { - next_instr--; - _Py_Specialize_CompareOp(left, right, next_instr, oparg); - DISPATCH_SAME_OPARG(); - } - STAT_INC(COMPARE_OP, deferred); - DECREMENT_ADAPTIVE_COUNTER(cache->counter); - #endif /* ENABLE_SPECIALIZATION */ assert((oparg >> 5) <= Py_GE); res = PyObject_RichCompare(left, right, oparg >> 5); Py_DECREF(left); Py_DECREF(right); - if (res == NULL) goto pop_2_error; + if (res == NULL) goto pop_2_error_tier_two; if (oparg & 16) { int res_bool = PyObject_IsTrue(res); Py_DECREF(res); - if (res_bool < 0) goto pop_2_error; + if (res_bool < 0) goto pop_2_error_tier_two; res = res_bool ? Py_True : Py_False; } - STACK_SHRINK(1); - stack_pointer[-1] = res; + stack_pointer[-2] = res; + stack_pointer += -1; break; } - case COMPARE_OP_FLOAT: { + case _COMPARE_OP_FLOAT: { PyObject *right; PyObject *left; PyObject *res; + oparg = CURRENT_OPARG(); right = stack_pointer[-1]; left = stack_pointer[-2]; - DEOPT_IF(!PyFloat_CheckExact(left), COMPARE_OP); - DEOPT_IF(!PyFloat_CheckExact(right), COMPARE_OP); + if (!PyFloat_CheckExact(left)) goto deoptimize; + if (!PyFloat_CheckExact(right)) goto deoptimize; STAT_INC(COMPARE_OP, hit); double dleft = PyFloat_AS_DOUBLE(left); double dright = PyFloat_AS_DOUBLE(right); @@ -1676,21 +1877,22 @@ _Py_DECREF_SPECIALIZED(right, _PyFloat_ExactDealloc); res = (sign_ish & oparg) ? Py_True : Py_False; // It's always a bool, so we don't care about oparg & 16. - STACK_SHRINK(1); - stack_pointer[-1] = res; + stack_pointer[-2] = res; + stack_pointer += -1; break; } - case COMPARE_OP_INT: { + case _COMPARE_OP_INT: { PyObject *right; PyObject *left; PyObject *res; + oparg = CURRENT_OPARG(); right = stack_pointer[-1]; left = stack_pointer[-2]; - DEOPT_IF(!PyLong_CheckExact(left), COMPARE_OP); - DEOPT_IF(!PyLong_CheckExact(right), COMPARE_OP); - DEOPT_IF(!_PyLong_IsCompact((PyLongObject *)left), COMPARE_OP); - DEOPT_IF(!_PyLong_IsCompact((PyLongObject *)right), COMPARE_OP); + if (!PyLong_CheckExact(left)) goto deoptimize; + if (!PyLong_CheckExact(right)) goto deoptimize; + if (!_PyLong_IsCompact((PyLongObject *)left)) goto deoptimize; + if (!_PyLong_IsCompact((PyLongObject *)right)) goto deoptimize; STAT_INC(COMPARE_OP, hit); assert(_PyLong_DigitCount((PyLongObject *)left) <= 1 && _PyLong_DigitCount((PyLongObject *)right) <= 1); @@ -1702,19 +1904,20 @@ _Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free); res = (sign_ish & oparg) ? Py_True : Py_False; // It's always a bool, so we don't care about oparg & 16. - STACK_SHRINK(1); - stack_pointer[-1] = res; + stack_pointer[-2] = res; + stack_pointer += -1; break; } - case COMPARE_OP_STR: { + case _COMPARE_OP_STR: { PyObject *right; PyObject *left; PyObject *res; + oparg = CURRENT_OPARG(); right = stack_pointer[-1]; left = stack_pointer[-2]; - DEOPT_IF(!PyUnicode_CheckExact(left), COMPARE_OP); - DEOPT_IF(!PyUnicode_CheckExact(right), COMPARE_OP); + if (!PyUnicode_CheckExact(left)) goto deoptimize; + if (!PyUnicode_CheckExact(right)) goto deoptimize; STAT_INC(COMPARE_OP, hit); int eq = _PyUnicode_Equal(left, right); assert((oparg >> 5) == Py_EQ || (oparg >> 5) == Py_NE); @@ -1725,43 +1928,45 @@ assert(COMPARISON_NOT_EQUALS + 1 == COMPARISON_EQUALS); res = ((COMPARISON_NOT_EQUALS + eq) & oparg) ? Py_True : Py_False; // It's always a bool, so we don't care about oparg & 16. - STACK_SHRINK(1); - stack_pointer[-1] = res; + stack_pointer[-2] = res; + stack_pointer += -1; break; } - case IS_OP: { + case _IS_OP: { PyObject *right; PyObject *left; PyObject *b; + oparg = CURRENT_OPARG(); right = stack_pointer[-1]; left = stack_pointer[-2]; int res = Py_Is(left, right) ^ oparg; Py_DECREF(left); Py_DECREF(right); b = res ? Py_True : Py_False; - STACK_SHRINK(1); - stack_pointer[-1] = b; + stack_pointer[-2] = b; + stack_pointer += -1; break; } - case CONTAINS_OP: { + case _CONTAINS_OP: { PyObject *right; PyObject *left; PyObject *b; + oparg = CURRENT_OPARG(); right = stack_pointer[-1]; left = stack_pointer[-2]; int res = PySequence_Contains(right, left); Py_DECREF(left); Py_DECREF(right); - if (res < 0) goto pop_2_error; + if (res < 0) goto pop_2_error_tier_two; b = (res ^ oparg) ? Py_True : Py_False; - STACK_SHRINK(1); - stack_pointer[-1] = b; + stack_pointer[-2] = b; + stack_pointer += -1; break; } - case CHECK_EG_MATCH: { + case _CHECK_EG_MATCH: { PyObject *match_type; PyObject *exc_value; PyObject *rest; @@ -1771,20 +1976,17 @@ if (_PyEval_CheckExceptStarTypeValid(tstate, match_type) < 0) { Py_DECREF(exc_value); Py_DECREF(match_type); - if (true) goto pop_2_error; + if (true) goto pop_2_error_tier_two; } - match = NULL; rest = NULL; int res = _PyEval_ExceptionGroupMatch(exc_value, match_type, - &match, &rest); + &match, &rest); Py_DECREF(exc_value); Py_DECREF(match_type); - if (res < 0) goto pop_2_error; - + if (res < 0) goto pop_2_error_tier_two; assert((match == NULL) == (rest == NULL)); - if (match == NULL) goto pop_2_error; - + if (match == NULL) goto pop_2_error_tier_two; if (!Py_IsNone(match)) { PyErr_SetHandledException(match); } @@ -1793,7 +1995,7 @@ break; } - case CHECK_EXC_MATCH: { + case _CHECK_EXC_MATCH: { PyObject *right; PyObject *left; PyObject *b; @@ -1801,10 +2003,9 @@ left = stack_pointer[-2]; assert(PyExceptionInstance_Check(left)); if (_PyEval_CheckExceptTypeValid(tstate, right) < 0) { - Py_DECREF(right); - if (true) goto pop_1_error; + Py_DECREF(right); + if (true) goto pop_1_error_tier_two; } - int res = PyErr_GivenExceptionMatches(left, right); Py_DECREF(right); b = res ? Py_True : Py_False; @@ -1812,7 +2013,13 @@ break; } - case IS_NONE: { + /* _JUMP_BACKWARD is not a viable micro-op for tier 2 */ + + /* _POP_JUMP_IF_FALSE is not a viable micro-op for tier 2 */ + + /* _POP_JUMP_IF_TRUE is not a viable micro-op for tier 2 */ + + case _IS_NONE: { PyObject *value; PyObject *b; value = stack_pointer[-1]; @@ -1827,25 +2034,26 @@ break; } - case GET_LEN: { + case _GET_LEN: { PyObject *obj; PyObject *len_o; obj = stack_pointer[-1]; // PUSH(len(TOS)) Py_ssize_t len_i = PyObject_Length(obj); - if (len_i < 0) goto error; + if (len_i < 0) goto error_tier_two; len_o = PyLong_FromSsize_t(len_i); - if (len_o == NULL) goto error; - STACK_GROW(1); - stack_pointer[-1] = len_o; + if (len_o == NULL) goto error_tier_two; + stack_pointer[0] = len_o; + stack_pointer += 1; break; } - case MATCH_CLASS: { + case _MATCH_CLASS: { PyObject *names; PyObject *type; PyObject *subject; PyObject *attrs; + oparg = CURRENT_OPARG(); names = stack_pointer[-1]; type = stack_pointer[-2]; subject = stack_pointer[-3]; @@ -1860,37 +2068,38 @@ assert(PyTuple_CheckExact(attrs)); // Success! } else { - if (_PyErr_Occurred(tstate)) goto pop_3_error; + if (_PyErr_Occurred(tstate)) goto pop_3_error_tier_two; + // Error! attrs = Py_None; // Failure! } - STACK_SHRINK(2); - stack_pointer[-1] = attrs; + stack_pointer[-3] = attrs; + stack_pointer += -2; break; } - case MATCH_MAPPING: { + case _MATCH_MAPPING: { PyObject *subject; PyObject *res; subject = stack_pointer[-1]; int match = Py_TYPE(subject)->tp_flags & Py_TPFLAGS_MAPPING; res = match ? Py_True : Py_False; - STACK_GROW(1); - stack_pointer[-1] = res; + stack_pointer[0] = res; + stack_pointer += 1; break; } - case MATCH_SEQUENCE: { + case _MATCH_SEQUENCE: { PyObject *subject; PyObject *res; subject = stack_pointer[-1]; int match = Py_TYPE(subject)->tp_flags & Py_TPFLAGS_SEQUENCE; res = match ? Py_True : Py_False; - STACK_GROW(1); - stack_pointer[-1] = res; + stack_pointer[0] = res; + stack_pointer += 1; break; } - case MATCH_KEYS: { + case _MATCH_KEYS: { PyObject *keys; PyObject *subject; PyObject *values_or_none; @@ -1898,25 +2107,25 @@ subject = stack_pointer[-2]; // On successful match, PUSH(values). Otherwise, PUSH(None). values_or_none = _PyEval_MatchKeys(tstate, subject, keys); - if (values_or_none == NULL) goto error; - STACK_GROW(1); - stack_pointer[-1] = values_or_none; + if (values_or_none == NULL) goto error_tier_two; + stack_pointer[0] = values_or_none; + stack_pointer += 1; break; } - case GET_ITER: { + case _GET_ITER: { PyObject *iterable; PyObject *iter; iterable = stack_pointer[-1]; /* before: [obj]; after [getiter(obj)] */ iter = PyObject_GetIter(iterable); Py_DECREF(iterable); - if (iter == NULL) goto pop_1_error; + if (iter == NULL) goto pop_1_error_tier_two; stack_pointer[-1] = iter; break; } - case GET_YIELD_FROM_ITER: { + case _GET_YIELD_FROM_ITER: { PyObject *iterable; PyObject *iter; iterable = stack_pointer[-1]; @@ -1929,7 +2138,7 @@ _PyErr_SetString(tstate, PyExc_TypeError, "cannot 'yield from' a coroutine object " "in a non-coroutine generator"); - goto error; + GOTO_ERROR(error); } iter = iterable; } @@ -1940,7 +2149,7 @@ /* `iterable` is not a generator. */ iter = PyObject_GetIter(iterable); if (iter == NULL) { - goto error; + GOTO_ERROR(error); } Py_DECREF(iterable); } @@ -1948,33 +2157,52 @@ break; } - case _ITER_CHECK_LIST: { - PyObject *iter; - iter = stack_pointer[-1]; - DEOPT_IF(Py_TYPE(iter) != &PyListIter_Type, FOR_ITER); - break; - } + /* _FOR_ITER is not a viable micro-op for tier 2 */ - case _IS_ITER_EXHAUSTED_LIST: { + case _FOR_ITER_TIER_TWO: { PyObject *iter; - PyObject *exhausted; + PyObject *next; iter = stack_pointer[-1]; - _PyListIterObject *it = (_PyListIterObject *)iter; + /* before: [iter]; after: [iter, iter()] *or* [] (and jump over END_FOR.) */ + next = (*Py_TYPE(iter)->tp_iternext)(iter); + if (next == NULL) { + if (_PyErr_Occurred(tstate)) { + if (!_PyErr_ExceptionMatches(tstate, PyExc_StopIteration)) { + GOTO_ERROR(error); + } + _PyErr_Clear(tstate); + } + /* iterator ended normally */ + Py_DECREF(iter); + STACK_SHRINK(1); + /* The translator sets the deopt target just past END_FOR */ + if (true) goto deoptimize; + } + // Common case: no jump, leave it to the code generator + stack_pointer[0] = next; + stack_pointer += 1; + break; + } + + /* _INSTRUMENTED_FOR_ITER is not a viable micro-op for tier 2 */ + + case _ITER_CHECK_LIST: { + PyObject *iter; + iter = stack_pointer[-1]; + if (Py_TYPE(iter) != &PyListIter_Type) goto deoptimize; + break; + } + + /* _ITER_JUMP_LIST is not a viable micro-op for tier 2 */ + + case _GUARD_NOT_EXHAUSTED_LIST: { + PyObject *iter; + iter = stack_pointer[-1]; + _PyListIterObject *it = (_PyListIterObject *)iter; assert(Py_TYPE(iter) == &PyListIter_Type); PyListObject *seq = it->it_seq; - if (seq == NULL) { - exhausted = Py_True; - } - else if (it->it_index >= PyList_GET_SIZE(seq)) { - Py_DECREF(seq); - it->it_seq = NULL; - exhausted = Py_True; - } - else { - exhausted = Py_False; - } - STACK_GROW(1); - stack_pointer[-1] = exhausted; + if (seq == NULL) goto deoptimize; + if (it->it_index >= PyList_GET_SIZE(seq)) goto deoptimize; break; } @@ -1988,38 +2216,28 @@ assert(seq); assert(it->it_index < PyList_GET_SIZE(seq)); next = Py_NewRef(PyList_GET_ITEM(seq, it->it_index++)); - STACK_GROW(1); - stack_pointer[-1] = next; + stack_pointer[0] = next; + stack_pointer += 1; break; } case _ITER_CHECK_TUPLE: { PyObject *iter; iter = stack_pointer[-1]; - DEOPT_IF(Py_TYPE(iter) != &PyTupleIter_Type, FOR_ITER); + if (Py_TYPE(iter) != &PyTupleIter_Type) goto deoptimize; break; } - case _IS_ITER_EXHAUSTED_TUPLE: { + /* _ITER_JUMP_TUPLE is not a viable micro-op for tier 2 */ + + case _GUARD_NOT_EXHAUSTED_TUPLE: { PyObject *iter; - PyObject *exhausted; iter = stack_pointer[-1]; _PyTupleIterObject *it = (_PyTupleIterObject *)iter; assert(Py_TYPE(iter) == &PyTupleIter_Type); PyTupleObject *seq = it->it_seq; - if (seq == NULL) { - exhausted = Py_True; - } - else if (it->it_index >= PyTuple_GET_SIZE(seq)) { - Py_DECREF(seq); - it->it_seq = NULL; - exhausted = Py_True; - } - else { - exhausted = Py_False; - } - STACK_GROW(1); - stack_pointer[-1] = exhausted; + if (seq == NULL) goto deoptimize; + if (it->it_index >= PyTuple_GET_SIZE(seq)) goto deoptimize; break; } @@ -2033,8 +2251,8 @@ assert(seq); assert(it->it_index < PyTuple_GET_SIZE(seq)); next = Py_NewRef(PyTuple_GET_ITEM(seq, it->it_index++)); - STACK_GROW(1); - stack_pointer[-1] = next; + stack_pointer[0] = next; + stack_pointer += 1; break; } @@ -2042,19 +2260,18 @@ PyObject *iter; iter = stack_pointer[-1]; _PyRangeIterObject *r = (_PyRangeIterObject *)iter; - DEOPT_IF(Py_TYPE(r) != &PyRangeIter_Type, FOR_ITER); + if (Py_TYPE(r) != &PyRangeIter_Type) goto deoptimize; break; } - case _IS_ITER_EXHAUSTED_RANGE: { + /* _ITER_JUMP_RANGE is not a viable micro-op for tier 2 */ + + case _GUARD_NOT_EXHAUSTED_RANGE: { PyObject *iter; - PyObject *exhausted; iter = stack_pointer[-1]; _PyRangeIterObject *r = (_PyRangeIterObject *)iter; assert(Py_TYPE(r) == &PyRangeIter_Type); - exhausted = r->len <= 0 ? Py_True : Py_False; - STACK_GROW(1); - stack_pointer[-1] = exhausted; + if (r->len <= 0) goto deoptimize; break; } @@ -2069,13 +2286,98 @@ r->start = value + r->step; r->len--; next = PyLong_FromLong(value); - if (next == NULL) goto error; - STACK_GROW(1); - stack_pointer[-1] = next; + if (next == NULL) goto error_tier_two; + stack_pointer[0] = next; + stack_pointer += 1; break; } - case WITH_EXCEPT_START: { + /* _FOR_ITER_GEN is not a viable micro-op for tier 2 */ + + case _BEFORE_ASYNC_WITH: { + PyObject *mgr; + PyObject *exit; + PyObject *res; + mgr = stack_pointer[-1]; + PyObject *enter = _PyObject_LookupSpecial(mgr, &_Py_ID(__aenter__)); + if (enter == NULL) { + if (!_PyErr_Occurred(tstate)) { + _PyErr_Format(tstate, PyExc_TypeError, + "'%.200s' object does not support the " + "asynchronous context manager protocol", + Py_TYPE(mgr)->tp_name); + } + GOTO_ERROR(error); + } + exit = _PyObject_LookupSpecial(mgr, &_Py_ID(__aexit__)); + if (exit == NULL) { + if (!_PyErr_Occurred(tstate)) { + _PyErr_Format(tstate, PyExc_TypeError, + "'%.200s' object does not support the " + "asynchronous context manager protocol " + "(missed __aexit__ method)", + Py_TYPE(mgr)->tp_name); + } + Py_DECREF(enter); + GOTO_ERROR(error); + } + Py_DECREF(mgr); + res = _PyObject_CallNoArgsTstate(tstate, enter); + Py_DECREF(enter); + if (res == NULL) { + Py_DECREF(exit); + if (true) goto pop_1_error_tier_two; + } + stack_pointer[-1] = exit; + stack_pointer[0] = res; + stack_pointer += 1; + break; + } + + case _BEFORE_WITH: { + PyObject *mgr; + PyObject *exit; + PyObject *res; + mgr = stack_pointer[-1]; + /* pop the context manager, push its __exit__ and the + * value returned from calling its __enter__ + */ + PyObject *enter = _PyObject_LookupSpecial(mgr, &_Py_ID(__enter__)); + if (enter == NULL) { + if (!_PyErr_Occurred(tstate)) { + _PyErr_Format(tstate, PyExc_TypeError, + "'%.200s' object does not support the " + "context manager protocol", + Py_TYPE(mgr)->tp_name); + } + GOTO_ERROR(error); + } + exit = _PyObject_LookupSpecial(mgr, &_Py_ID(__exit__)); + if (exit == NULL) { + if (!_PyErr_Occurred(tstate)) { + _PyErr_Format(tstate, PyExc_TypeError, + "'%.200s' object does not support the " + "context manager protocol " + "(missed __exit__ method)", + Py_TYPE(mgr)->tp_name); + } + Py_DECREF(enter); + GOTO_ERROR(error); + } + Py_DECREF(mgr); + res = _PyObject_CallNoArgsTstate(tstate, enter); + Py_DECREF(enter); + if (res == NULL) { + Py_DECREF(exit); + if (true) goto pop_1_error_tier_two; + } + stack_pointer[-1] = exit; + stack_pointer[0] = res; + stack_pointer += 1; + break; + } + + case _WITH_EXCEPT_START: { PyObject *val; PyObject *lasti; PyObject *exit_func; @@ -2090,9 +2392,8 @@ - exit_func: FOURTH = the context.__exit__ bound method We call FOURTH(type(TOP), TOP, GetTraceback(TOP)). Then we push the __exit__ return value. - */ + */ PyObject *exc, *tb; - assert(val && PyExceptionInstance_Check(val)); exc = PyExceptionInstance_Class(val); tb = PyException_GetTraceback(val); @@ -2106,14 +2407,14 @@ (void)lasti; // Shut up compiler warning if asserts are off PyObject *stack[4] = {NULL, exc, val, tb}; res = PyObject_Vectorcall(exit_func, stack + 1, - 3 | PY_VECTORCALL_ARGUMENTS_OFFSET, NULL); - if (res == NULL) goto error; - STACK_GROW(1); - stack_pointer[-1] = res; + 3 | PY_VECTORCALL_ARGUMENTS_OFFSET, NULL); + if (res == NULL) goto error_tier_two; + stack_pointer[0] = res; + stack_pointer += 1; break; } - case PUSH_EXC_INFO: { + case _PUSH_EXC_INFO: { PyObject *new_exc; PyObject *prev_exc; new_exc = stack_pointer[-1]; @@ -2126,160 +2427,420 @@ } assert(PyExceptionInstance_Check(new_exc)); exc_info->exc_value = Py_NewRef(new_exc); - STACK_GROW(1); - stack_pointer[-2] = prev_exc; - stack_pointer[-1] = new_exc; + stack_pointer[-1] = prev_exc; + stack_pointer[0] = new_exc; + stack_pointer += 1; + break; + } + + case _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT: { + PyObject *owner; + owner = stack_pointer[-1]; + assert(Py_TYPE(owner)->tp_flags & Py_TPFLAGS_MANAGED_DICT); + PyDictOrValues *dorv = _PyObject_DictOrValuesPointer(owner); + if (!_PyDictOrValues_IsValues(*dorv) && !_PyObject_MakeInstanceAttributesFromDict(owner, dorv)) goto deoptimize; + break; + } + + case _GUARD_KEYS_VERSION: { + PyObject *owner; + owner = stack_pointer[-1]; + uint32_t keys_version = (uint32_t)CURRENT_OPERAND(); + PyTypeObject *owner_cls = Py_TYPE(owner); + PyHeapTypeObject *owner_heap_type = (PyHeapTypeObject *)owner_cls; + if (owner_heap_type->ht_cached_keys->dk_version != keys_version) goto deoptimize; break; } - case CALL_NO_KW_TYPE_1: { + case _LOAD_ATTR_METHOD_WITH_VALUES: { + PyObject *owner; + PyObject *attr; + PyObject *self = NULL; + oparg = CURRENT_OPARG(); + owner = stack_pointer[-1]; + PyObject *descr = (PyObject *)CURRENT_OPERAND(); + assert(oparg & 1); + /* Cached method object */ + STAT_INC(LOAD_ATTR, hit); + assert(descr != NULL); + attr = Py_NewRef(descr); + assert(_PyType_HasFeature(Py_TYPE(attr), Py_TPFLAGS_METHOD_DESCRIPTOR)); + self = owner; + stack_pointer[-1] = attr; + if (1) stack_pointer[0] = self; + stack_pointer += ((1) ? 1 : 0); + break; + } + + case _LOAD_ATTR_METHOD_NO_DICT: { + PyObject *owner; + PyObject *attr; + PyObject *self = NULL; + oparg = CURRENT_OPARG(); + owner = stack_pointer[-1]; + PyObject *descr = (PyObject *)CURRENT_OPERAND(); + assert(oparg & 1); + assert(Py_TYPE(owner)->tp_dictoffset == 0); + STAT_INC(LOAD_ATTR, hit); + assert(descr != NULL); + assert(_PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_METHOD_DESCRIPTOR)); + attr = Py_NewRef(descr); + self = owner; + stack_pointer[-1] = attr; + if (1) stack_pointer[0] = self; + stack_pointer += ((1) ? 1 : 0); + break; + } + + case _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES: { + PyObject *owner; + PyObject *attr; + oparg = CURRENT_OPARG(); + owner = stack_pointer[-1]; + PyObject *descr = (PyObject *)CURRENT_OPERAND(); + assert((oparg & 1) == 0); + STAT_INC(LOAD_ATTR, hit); + assert(descr != NULL); + Py_DECREF(owner); + attr = Py_NewRef(descr); + stack_pointer[-1] = attr; + stack_pointer += ((0) ? 1 : 0); + break; + } + + case _LOAD_ATTR_NONDESCRIPTOR_NO_DICT: { + PyObject *owner; + PyObject *attr; + oparg = CURRENT_OPARG(); + owner = stack_pointer[-1]; + PyObject *descr = (PyObject *)CURRENT_OPERAND(); + assert((oparg & 1) == 0); + assert(Py_TYPE(owner)->tp_dictoffset == 0); + STAT_INC(LOAD_ATTR, hit); + assert(descr != NULL); + Py_DECREF(owner); + attr = Py_NewRef(descr); + stack_pointer[-1] = attr; + stack_pointer += ((0) ? 1 : 0); + break; + } + + case _CHECK_ATTR_METHOD_LAZY_DICT: { + PyObject *owner; + owner = stack_pointer[-1]; + Py_ssize_t dictoffset = Py_TYPE(owner)->tp_dictoffset; + assert(dictoffset > 0); + PyObject *dict = *(PyObject **)((char *)owner + dictoffset); + /* This object has a __dict__, just not yet created */ + if (dict != NULL) goto deoptimize; + break; + } + + case _LOAD_ATTR_METHOD_LAZY_DICT: { + PyObject *owner; + PyObject *attr; + PyObject *self = NULL; + oparg = CURRENT_OPARG(); + owner = stack_pointer[-1]; + PyObject *descr = (PyObject *)CURRENT_OPERAND(); + assert(oparg & 1); + STAT_INC(LOAD_ATTR, hit); + assert(descr != NULL); + assert(_PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_METHOD_DESCRIPTOR)); + attr = Py_NewRef(descr); + self = owner; + stack_pointer[-1] = attr; + if (1) stack_pointer[0] = self; + stack_pointer += ((1) ? 1 : 0); + break; + } + + /* _INSTRUMENTED_CALL is not a viable micro-op for tier 2 */ + + /* _CALL is not a viable micro-op for tier 2 */ + + case _CHECK_CALL_BOUND_METHOD_EXACT_ARGS: { + PyObject *null; + PyObject *callable; + oparg = CURRENT_OPARG(); + null = stack_pointer[-1 - oparg]; + callable = stack_pointer[-2 - oparg]; + if (null != NULL) goto deoptimize; + if (Py_TYPE(callable) != &PyMethod_Type) goto deoptimize; + break; + } + + case _INIT_CALL_BOUND_METHOD_EXACT_ARGS: { + PyObject *callable; + PyObject *func; + PyObject *self; + oparg = CURRENT_OPARG(); + callable = stack_pointer[-2 - oparg]; + STAT_INC(CALL, hit); + self = Py_NewRef(((PyMethodObject *)callable)->im_self); + stack_pointer[-1 - oparg] = self; // Patch stack as it is used by _INIT_CALL_PY_EXACT_ARGS + func = Py_NewRef(((PyMethodObject *)callable)->im_func); + stack_pointer[-2 - oparg] = func; // This is used by CALL, upon deoptimization + Py_DECREF(callable); + stack_pointer[-2 - oparg] = func; + stack_pointer[-1 - oparg] = self; + break; + } + + case _CHECK_PEP_523: { + if (tstate->interp->eval_frame) goto deoptimize; + break; + } + + case _CHECK_FUNCTION_EXACT_ARGS: { + PyObject *self_or_null; + PyObject *callable; + oparg = CURRENT_OPARG(); + self_or_null = stack_pointer[-1 - oparg]; + callable = stack_pointer[-2 - oparg]; + uint32_t func_version = (uint32_t)CURRENT_OPERAND(); + if (!PyFunction_Check(callable)) goto deoptimize; + PyFunctionObject *func = (PyFunctionObject *)callable; + if (func->func_version != func_version) goto deoptimize; + PyCodeObject *code = (PyCodeObject *)func->func_code; + if (code->co_argcount != oparg + (self_or_null != NULL)) goto deoptimize; + break; + } + + case _CHECK_STACK_SPACE: { + PyObject *callable; + oparg = CURRENT_OPARG(); + callable = stack_pointer[-2 - oparg]; + PyFunctionObject *func = (PyFunctionObject *)callable; + PyCodeObject *code = (PyCodeObject *)func->func_code; + if (!_PyThreadState_HasStackSpace(tstate, code->co_framesize)) goto deoptimize; + if (tstate->py_recursion_remaining <= 1) goto deoptimize; + break; + } + + case _INIT_CALL_PY_EXACT_ARGS: { PyObject **args; + PyObject *self_or_null; PyObject *callable; + _PyInterpreterFrame *new_frame; + oparg = CURRENT_OPARG(); + args = &stack_pointer[-oparg]; + self_or_null = stack_pointer[-1 - oparg]; + callable = stack_pointer[-2 - oparg]; + int argcount = oparg; + if (self_or_null != NULL) { + args--; + argcount++; + } + STAT_INC(CALL, hit); + PyFunctionObject *func = (PyFunctionObject *)callable; + new_frame = _PyFrame_PushUnchecked(tstate, func, argcount); + for (int i = 0; i < argcount; i++) { + new_frame->localsplus[i] = args[i]; + } + stack_pointer[-2 - oparg] = (PyObject *)new_frame; + stack_pointer += -1 - oparg; + break; + } + + case _PUSH_FRAME: { + _PyInterpreterFrame *new_frame; + new_frame = (_PyInterpreterFrame *)stack_pointer[-1]; + // Write it out explicitly because it's subtly different. + // Eventually this should be the only occurrence of this code. + assert(tstate->interp->eval_frame == NULL); + stack_pointer += -1; + _PyFrame_SetStackPointer(frame, stack_pointer); + new_frame->previous = frame; + CALL_STAT_INC(inlined_py_calls); + frame = tstate->current_frame = new_frame; + tstate->py_recursion_remaining--; + LOAD_SP(); + LOAD_IP(0); + #if LLTRACE && TIER_ONE + lltrace = maybe_lltrace_resume_frame(frame, &entry_frame, GLOBALS()); + if (lltrace < 0) { + goto exit_unwind; + } + #endif + stack_pointer += ((0) ? 1 : 0); + break; + } + + /* _CALL_PY_WITH_DEFAULTS is not a viable micro-op for tier 2 */ + + case _CALL_TYPE_1: { + PyObject **args; PyObject *null; + PyObject *callable; PyObject *res; - args = stack_pointer - oparg; - callable = stack_pointer[-1 - oparg]; - null = stack_pointer[-2 - oparg]; - ASSERT_KWNAMES_IS_NULL(); + oparg = CURRENT_OPARG(); + args = &stack_pointer[-oparg]; + null = stack_pointer[-1 - oparg]; + callable = stack_pointer[-2 - oparg]; assert(oparg == 1); - DEOPT_IF(null != NULL, CALL); + if (null != NULL) goto deoptimize; PyObject *obj = args[0]; - DEOPT_IF(callable != (PyObject *)&PyType_Type, CALL); + if (callable != (PyObject *)&PyType_Type) goto deoptimize; STAT_INC(CALL, hit); res = Py_NewRef(Py_TYPE(obj)); Py_DECREF(obj); Py_DECREF(&PyType_Type); // I.e., callable - STACK_SHRINK(oparg); - STACK_SHRINK(1); - stack_pointer[-1] = res; + stack_pointer[-2 - oparg] = res; + stack_pointer += -1 - oparg; break; } - case CALL_NO_KW_STR_1: { + case _CALL_STR_1: { PyObject **args; - PyObject *callable; PyObject *null; + PyObject *callable; PyObject *res; - args = stack_pointer - oparg; - callable = stack_pointer[-1 - oparg]; - null = stack_pointer[-2 - oparg]; - ASSERT_KWNAMES_IS_NULL(); + oparg = CURRENT_OPARG(); + args = &stack_pointer[-oparg]; + null = stack_pointer[-1 - oparg]; + callable = stack_pointer[-2 - oparg]; assert(oparg == 1); - DEOPT_IF(null != NULL, CALL); - DEOPT_IF(callable != (PyObject *)&PyUnicode_Type, CALL); + if (null != NULL) goto deoptimize; + if (callable != (PyObject *)&PyUnicode_Type) goto deoptimize; STAT_INC(CALL, hit); PyObject *arg = args[0]; res = PyObject_Str(arg); Py_DECREF(arg); Py_DECREF(&PyUnicode_Type); // I.e., callable - if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; } - STACK_SHRINK(oparg); - STACK_SHRINK(1); - stack_pointer[-1] = res; + if (res == NULL) { stack_pointer += -2 - oparg; goto error_tier_two; } + stack_pointer[-2 - oparg] = res; + stack_pointer += -1 - oparg; CHECK_EVAL_BREAKER(); break; } - case CALL_NO_KW_TUPLE_1: { + case _CALL_TUPLE_1: { PyObject **args; - PyObject *callable; PyObject *null; + PyObject *callable; PyObject *res; - args = stack_pointer - oparg; - callable = stack_pointer[-1 - oparg]; - null = stack_pointer[-2 - oparg]; - ASSERT_KWNAMES_IS_NULL(); + oparg = CURRENT_OPARG(); + args = &stack_pointer[-oparg]; + null = stack_pointer[-1 - oparg]; + callable = stack_pointer[-2 - oparg]; assert(oparg == 1); - DEOPT_IF(null != NULL, CALL); - DEOPT_IF(callable != (PyObject *)&PyTuple_Type, CALL); + if (null != NULL) goto deoptimize; + if (callable != (PyObject *)&PyTuple_Type) goto deoptimize; STAT_INC(CALL, hit); PyObject *arg = args[0]; res = PySequence_Tuple(arg); Py_DECREF(arg); Py_DECREF(&PyTuple_Type); // I.e., tuple - if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; } - STACK_SHRINK(oparg); - STACK_SHRINK(1); - stack_pointer[-1] = res; + if (res == NULL) { stack_pointer += -2 - oparg; goto error_tier_two; } + stack_pointer[-2 - oparg] = res; + stack_pointer += -1 - oparg; CHECK_EVAL_BREAKER(); break; } - case EXIT_INIT_CHECK: { + /* _CALL_ALLOC_AND_ENTER_INIT is not a viable micro-op for tier 2 */ + + case _EXIT_INIT_CHECK: { PyObject *should_be_none; should_be_none = stack_pointer[-1]; assert(STACK_LEVEL() == 2); if (should_be_none != Py_None) { PyErr_Format(PyExc_TypeError, - "__init__() should return None, not '%.200s'", - Py_TYPE(should_be_none)->tp_name); - goto error; + "__init__() should return None, not '%.200s'", + Py_TYPE(should_be_none)->tp_name); + GOTO_ERROR(error); + } + stack_pointer += -1; + break; + } + + case _CALL_BUILTIN_CLASS: { + PyObject **args; + PyObject *self_or_null; + PyObject *callable; + PyObject *res; + oparg = CURRENT_OPARG(); + args = &stack_pointer[-oparg]; + self_or_null = stack_pointer[-1 - oparg]; + callable = stack_pointer[-2 - oparg]; + int total_args = oparg; + if (self_or_null != NULL) { + args--; + total_args++; + } + if (!PyType_Check(callable)) goto deoptimize; + PyTypeObject *tp = (PyTypeObject *)callable; + if (tp->tp_vectorcall == NULL) goto deoptimize; + STAT_INC(CALL, hit); + res = tp->tp_vectorcall((PyObject *)tp, args, total_args, NULL); + /* Free the arguments. */ + for (int i = 0; i < total_args; i++) { + Py_DECREF(args[i]); } - STACK_SHRINK(1); + Py_DECREF(tp); + if (res == NULL) { stack_pointer += -2 - oparg; goto error_tier_two; } + stack_pointer[-2 - oparg] = res; + stack_pointer += -1 - oparg; + CHECK_EVAL_BREAKER(); break; } - case CALL_NO_KW_BUILTIN_O: { + case _CALL_BUILTIN_O: { PyObject **args; + PyObject *self_or_null; PyObject *callable; - PyObject *method; PyObject *res; - args = stack_pointer - oparg; - callable = stack_pointer[-1 - oparg]; - method = stack_pointer[-2 - oparg]; + oparg = CURRENT_OPARG(); + args = &stack_pointer[-oparg]; + self_or_null = stack_pointer[-1 - oparg]; + callable = stack_pointer[-2 - oparg]; /* Builtin METH_O functions */ - ASSERT_KWNAMES_IS_NULL(); - int is_meth = method != NULL; int total_args = oparg; - if (is_meth) { - callable = method; + if (self_or_null != NULL) { args--; total_args++; } - DEOPT_IF(total_args != 1, CALL); - DEOPT_IF(!PyCFunction_CheckExact(callable), CALL); - DEOPT_IF(PyCFunction_GET_FLAGS(callable) != METH_O, CALL); + if (total_args != 1) goto deoptimize; + if (!PyCFunction_CheckExact(callable)) goto deoptimize; + if (PyCFunction_GET_FLAGS(callable) != METH_O) goto deoptimize; STAT_INC(CALL, hit); PyCFunction cfunc = PyCFunction_GET_FUNCTION(callable); // This is slower but CPython promises to check all non-vectorcall // function calls. if (_Py_EnterRecursiveCallTstate(tstate, " while calling a Python object")) { - goto error; + GOTO_ERROR(error); } PyObject *arg = args[0]; res = _PyCFunction_TrampolineCall(cfunc, PyCFunction_GET_SELF(callable), arg); _Py_LeaveRecursiveCallTstate(tstate); assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); - Py_DECREF(arg); Py_DECREF(callable); - if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; } - STACK_SHRINK(oparg); - STACK_SHRINK(1); - stack_pointer[-1] = res; + if (res == NULL) { stack_pointer += -2 - oparg; goto error_tier_two; } + stack_pointer[-2 - oparg] = res; + stack_pointer += -1 - oparg; CHECK_EVAL_BREAKER(); break; } - case CALL_NO_KW_BUILTIN_FAST: { + case _CALL_BUILTIN_FAST: { PyObject **args; + PyObject *self_or_null; PyObject *callable; - PyObject *method; PyObject *res; - args = stack_pointer - oparg; - callable = stack_pointer[-1 - oparg]; - method = stack_pointer[-2 - oparg]; + oparg = CURRENT_OPARG(); + args = &stack_pointer[-oparg]; + self_or_null = stack_pointer[-1 - oparg]; + callable = stack_pointer[-2 - oparg]; /* Builtin METH_FASTCALL functions, without keywords */ - ASSERT_KWNAMES_IS_NULL(); - int is_meth = method != NULL; int total_args = oparg; - if (is_meth) { - callable = method; + if (self_or_null != NULL) { args--; total_args++; } - DEOPT_IF(!PyCFunction_CheckExact(callable), CALL); - DEOPT_IF(PyCFunction_GET_FLAGS(callable) != METH_FASTCALL, CALL); + if (!PyCFunction_CheckExact(callable)) goto deoptimize; + if (PyCFunction_GET_FLAGS(callable) != METH_FASTCALL) goto deoptimize; STAT_INC(CALL, hit); PyCFunction cfunc = PyCFunction_GET_FUNCTION(callable); /* res = func(self, args, nargs) */ @@ -2288,131 +2849,157 @@ args, total_args); assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); + /* Free the arguments. */ + for (int i = 0; i < total_args; i++) { + Py_DECREF(args[i]); + } + Py_DECREF(callable); + if (res == NULL) { stack_pointer += -2 - oparg; goto error_tier_two; } + /* Not deopting because this doesn't mean our optimization was + wrong. `res` can be NULL for valid reasons. Eg. getattr(x, + 'invalid'). In those cases an exception is set, so we must + handle it. + */ + stack_pointer[-2 - oparg] = res; + stack_pointer += -1 - oparg; + CHECK_EVAL_BREAKER(); + break; + } + case _CALL_BUILTIN_FAST_WITH_KEYWORDS: { + PyObject **args; + PyObject *self_or_null; + PyObject *callable; + PyObject *res; + oparg = CURRENT_OPARG(); + args = &stack_pointer[-oparg]; + self_or_null = stack_pointer[-1 - oparg]; + callable = stack_pointer[-2 - oparg]; + /* Builtin METH_FASTCALL | METH_KEYWORDS functions */ + int total_args = oparg; + if (self_or_null != NULL) { + args--; + total_args++; + } + if (!PyCFunction_CheckExact(callable)) goto deoptimize; + if (PyCFunction_GET_FLAGS(callable) != (METH_FASTCALL | METH_KEYWORDS)) goto deoptimize; + STAT_INC(CALL, hit); + /* res = func(self, args, nargs, kwnames) */ + _PyCFunctionFastWithKeywords cfunc = + (_PyCFunctionFastWithKeywords)(void(*)(void)) + PyCFunction_GET_FUNCTION(callable); + res = cfunc(PyCFunction_GET_SELF(callable), args, total_args, NULL); + assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); /* Free the arguments. */ for (int i = 0; i < total_args; i++) { Py_DECREF(args[i]); } Py_DECREF(callable); - if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; } - /* Not deopting because this doesn't mean our optimization was - wrong. `res` can be NULL for valid reasons. Eg. getattr(x, - 'invalid'). In those cases an exception is set, so we must - handle it. - */ - STACK_SHRINK(oparg); - STACK_SHRINK(1); - stack_pointer[-1] = res; + if (res == NULL) { stack_pointer += -2 - oparg; goto error_tier_two; } + stack_pointer[-2 - oparg] = res; + stack_pointer += -1 - oparg; CHECK_EVAL_BREAKER(); break; } - case CALL_NO_KW_LEN: { + case _CALL_LEN: { PyObject **args; + PyObject *self_or_null; PyObject *callable; - PyObject *method; PyObject *res; - args = stack_pointer - oparg; - callable = stack_pointer[-1 - oparg]; - method = stack_pointer[-2 - oparg]; - ASSERT_KWNAMES_IS_NULL(); + oparg = CURRENT_OPARG(); + args = &stack_pointer[-oparg]; + self_or_null = stack_pointer[-1 - oparg]; + callable = stack_pointer[-2 - oparg]; /* len(o) */ - int is_meth = method != NULL; int total_args = oparg; - if (is_meth) { - callable = method; + if (self_or_null != NULL) { args--; total_args++; } - DEOPT_IF(total_args != 1, CALL); + if (total_args != 1) goto deoptimize; PyInterpreterState *interp = tstate->interp; - DEOPT_IF(callable != interp->callable_cache.len, CALL); + if (callable != interp->callable_cache.len) goto deoptimize; STAT_INC(CALL, hit); PyObject *arg = args[0]; Py_ssize_t len_i = PyObject_Length(arg); if (len_i < 0) { - goto error; + GOTO_ERROR(error); } res = PyLong_FromSsize_t(len_i); assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); - Py_DECREF(callable); Py_DECREF(arg); - if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; } - STACK_SHRINK(oparg); - STACK_SHRINK(1); - stack_pointer[-1] = res; + if (res == NULL) { stack_pointer += -2 - oparg; goto error_tier_two; } + stack_pointer[-2 - oparg] = res; + stack_pointer += -1 - oparg; break; } - case CALL_NO_KW_ISINSTANCE: { + case _CALL_ISINSTANCE: { PyObject **args; + PyObject *self_or_null; PyObject *callable; - PyObject *method; PyObject *res; - args = stack_pointer - oparg; - callable = stack_pointer[-1 - oparg]; - method = stack_pointer[-2 - oparg]; - ASSERT_KWNAMES_IS_NULL(); + oparg = CURRENT_OPARG(); + args = &stack_pointer[-oparg]; + self_or_null = stack_pointer[-1 - oparg]; + callable = stack_pointer[-2 - oparg]; /* isinstance(o, o2) */ - int is_meth = method != NULL; int total_args = oparg; - if (is_meth) { - callable = method; + if (self_or_null != NULL) { args--; total_args++; } - DEOPT_IF(total_args != 2, CALL); + if (total_args != 2) goto deoptimize; PyInterpreterState *interp = tstate->interp; - DEOPT_IF(callable != interp->callable_cache.isinstance, CALL); + if (callable != interp->callable_cache.isinstance) goto deoptimize; STAT_INC(CALL, hit); PyObject *cls = args[1]; PyObject *inst = args[0]; int retval = PyObject_IsInstance(inst, cls); if (retval < 0) { - goto error; + GOTO_ERROR(error); } res = PyBool_FromLong(retval); assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); - Py_DECREF(inst); Py_DECREF(cls); Py_DECREF(callable); - if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; } - STACK_SHRINK(oparg); - STACK_SHRINK(1); - stack_pointer[-1] = res; + if (res == NULL) { stack_pointer += -2 - oparg; goto error_tier_two; } + stack_pointer[-2 - oparg] = res; + stack_pointer += -1 - oparg; break; } - case CALL_NO_KW_METHOD_DESCRIPTOR_O: { + case _CALL_METHOD_DESCRIPTOR_O: { PyObject **args; - PyObject *method; + PyObject *self_or_null; + PyObject *callable; PyObject *res; - args = stack_pointer - oparg; - method = stack_pointer[-2 - oparg]; - ASSERT_KWNAMES_IS_NULL(); - int is_meth = method != NULL; + oparg = CURRENT_OPARG(); + args = &stack_pointer[-oparg]; + self_or_null = stack_pointer[-1 - oparg]; + callable = stack_pointer[-2 - oparg]; int total_args = oparg; - if (is_meth) { + if (self_or_null != NULL) { args--; total_args++; } - PyMethodDescrObject *callable = - (PyMethodDescrObject *)PEEK(total_args + 1); - DEOPT_IF(total_args != 2, CALL); - DEOPT_IF(!Py_IS_TYPE(callable, &PyMethodDescr_Type), CALL); - PyMethodDef *meth = callable->d_method; - DEOPT_IF(meth->ml_flags != METH_O, CALL); + PyMethodDescrObject *method = (PyMethodDescrObject *)callable; + if (total_args != 2) goto deoptimize; + if (!Py_IS_TYPE(method, &PyMethodDescr_Type)) goto deoptimize; + PyMethodDef *meth = method->d_method; + if (meth->ml_flags != METH_O) goto deoptimize; PyObject *arg = args[1]; PyObject *self = args[0]; - DEOPT_IF(!Py_IS_TYPE(self, callable->d_common.d_type), CALL); + if (!Py_IS_TYPE(self, method->d_common.d_type)) goto deoptimize; STAT_INC(CALL, hit); PyCFunction cfunc = meth->ml_meth; // This is slower but CPython promises to check all non-vectorcall // function calls. if (_Py_EnterRecursiveCallTstate(tstate, " while calling a Python object")) { - goto error; + GOTO_ERROR(error); } res = _PyCFunction_TrampolineCall(cfunc, self, arg); _Py_LeaveRecursiveCallTstate(tstate); @@ -2420,79 +3007,117 @@ Py_DECREF(self); Py_DECREF(arg); Py_DECREF(callable); - if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; } - STACK_SHRINK(oparg); - STACK_SHRINK(1); - stack_pointer[-1] = res; + if (res == NULL) { stack_pointer += -2 - oparg; goto error_tier_two; } + stack_pointer[-2 - oparg] = res; + stack_pointer += -1 - oparg; + CHECK_EVAL_BREAKER(); + break; + } + + case _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS: { + PyObject **args; + PyObject *self_or_null; + PyObject *callable; + PyObject *res; + oparg = CURRENT_OPARG(); + args = &stack_pointer[-oparg]; + self_or_null = stack_pointer[-1 - oparg]; + callable = stack_pointer[-2 - oparg]; + int total_args = oparg; + if (self_or_null != NULL) { + args--; + total_args++; + } + PyMethodDescrObject *method = (PyMethodDescrObject *)callable; + if (!Py_IS_TYPE(method, &PyMethodDescr_Type)) goto deoptimize; + PyMethodDef *meth = method->d_method; + if (meth->ml_flags != (METH_FASTCALL|METH_KEYWORDS)) goto deoptimize; + PyTypeObject *d_type = method->d_common.d_type; + PyObject *self = args[0]; + if (!Py_IS_TYPE(self, d_type)) goto deoptimize; + STAT_INC(CALL, hit); + int nargs = total_args - 1; + _PyCFunctionFastWithKeywords cfunc = + (_PyCFunctionFastWithKeywords)(void(*)(void))meth->ml_meth; + res = cfunc(self, args + 1, nargs, NULL); + assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); + /* Free the arguments. */ + for (int i = 0; i < total_args; i++) { + Py_DECREF(args[i]); + } + Py_DECREF(callable); + if (res == NULL) { stack_pointer += -2 - oparg; goto error_tier_two; } + stack_pointer[-2 - oparg] = res; + stack_pointer += -1 - oparg; CHECK_EVAL_BREAKER(); break; } - case CALL_NO_KW_METHOD_DESCRIPTOR_NOARGS: { + case _CALL_METHOD_DESCRIPTOR_NOARGS: { PyObject **args; - PyObject *method; + PyObject *self_or_null; + PyObject *callable; PyObject *res; - args = stack_pointer - oparg; - method = stack_pointer[-2 - oparg]; - ASSERT_KWNAMES_IS_NULL(); + oparg = CURRENT_OPARG(); + args = &stack_pointer[-oparg]; + self_or_null = stack_pointer[-1 - oparg]; + callable = stack_pointer[-2 - oparg]; assert(oparg == 0 || oparg == 1); - int is_meth = method != NULL; int total_args = oparg; - if (is_meth) { + if (self_or_null != NULL) { args--; total_args++; } - DEOPT_IF(total_args != 1, CALL); - PyMethodDescrObject *callable = (PyMethodDescrObject *)SECOND(); - DEOPT_IF(!Py_IS_TYPE(callable, &PyMethodDescr_Type), CALL); - PyMethodDef *meth = callable->d_method; + if (total_args != 1) goto deoptimize; + PyMethodDescrObject *method = (PyMethodDescrObject *)callable; + if (!Py_IS_TYPE(method, &PyMethodDescr_Type)) goto deoptimize; + PyMethodDef *meth = method->d_method; PyObject *self = args[0]; - DEOPT_IF(!Py_IS_TYPE(self, callable->d_common.d_type), CALL); - DEOPT_IF(meth->ml_flags != METH_NOARGS, CALL); + if (!Py_IS_TYPE(self, method->d_common.d_type)) goto deoptimize; + if (meth->ml_flags != METH_NOARGS) goto deoptimize; STAT_INC(CALL, hit); PyCFunction cfunc = meth->ml_meth; // This is slower but CPython promises to check all non-vectorcall // function calls. if (_Py_EnterRecursiveCallTstate(tstate, " while calling a Python object")) { - goto error; + GOTO_ERROR(error); } res = _PyCFunction_TrampolineCall(cfunc, self, NULL); _Py_LeaveRecursiveCallTstate(tstate); assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); Py_DECREF(self); Py_DECREF(callable); - if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; } - STACK_SHRINK(oparg); - STACK_SHRINK(1); - stack_pointer[-1] = res; + if (res == NULL) { stack_pointer += -2 - oparg; goto error_tier_two; } + stack_pointer[-2 - oparg] = res; + stack_pointer += -1 - oparg; CHECK_EVAL_BREAKER(); break; } - case CALL_NO_KW_METHOD_DESCRIPTOR_FAST: { + case _CALL_METHOD_DESCRIPTOR_FAST: { PyObject **args; - PyObject *method; + PyObject *self_or_null; + PyObject *callable; PyObject *res; - args = stack_pointer - oparg; - method = stack_pointer[-2 - oparg]; - ASSERT_KWNAMES_IS_NULL(); - int is_meth = method != NULL; + oparg = CURRENT_OPARG(); + args = &stack_pointer[-oparg]; + self_or_null = stack_pointer[-1 - oparg]; + callable = stack_pointer[-2 - oparg]; int total_args = oparg; - if (is_meth) { + if (self_or_null != NULL) { args--; total_args++; } - PyMethodDescrObject *callable = - (PyMethodDescrObject *)PEEK(total_args + 1); + PyMethodDescrObject *method = (PyMethodDescrObject *)callable; /* Builtin METH_FASTCALL methods, without keywords */ - DEOPT_IF(!Py_IS_TYPE(callable, &PyMethodDescr_Type), CALL); - PyMethodDef *meth = callable->d_method; - DEOPT_IF(meth->ml_flags != METH_FASTCALL, CALL); + if (!Py_IS_TYPE(method, &PyMethodDescr_Type)) goto deoptimize; + PyMethodDef *meth = method->d_method; + if (meth->ml_flags != METH_FASTCALL) goto deoptimize; PyObject *self = args[0]; - DEOPT_IF(!Py_IS_TYPE(self, callable->d_common.d_type), CALL); + if (!Py_IS_TYPE(self, method->d_common.d_type)) goto deoptimize; STAT_INC(CALL, hit); _PyCFunctionFast cfunc = - (_PyCFunctionFast)(void(*)(void))meth->ml_meth; + (_PyCFunctionFast)(void(*)(void))meth->ml_meth; int nargs = total_args - 1; res = cfunc(self, args + 1, nargs); assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); @@ -2501,101 +3126,108 @@ Py_DECREF(args[i]); } Py_DECREF(callable); - if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; } - STACK_SHRINK(oparg); - STACK_SHRINK(1); - stack_pointer[-1] = res; + if (res == NULL) { stack_pointer += -2 - oparg; goto error_tier_two; } + stack_pointer[-2 - oparg] = res; + stack_pointer += -1 - oparg; CHECK_EVAL_BREAKER(); break; } - case MAKE_FUNCTION: { + /* _INSTRUMENTED_CALL_KW is not a viable micro-op for tier 2 */ + + /* _CALL_KW is not a viable micro-op for tier 2 */ + + /* _INSTRUMENTED_CALL_FUNCTION_EX is not a viable micro-op for tier 2 */ + + /* _CALL_FUNCTION_EX is not a viable micro-op for tier 2 */ + + case _MAKE_FUNCTION: { PyObject *codeobj; PyObject *func; codeobj = stack_pointer[-1]; - PyFunctionObject *func_obj = (PyFunctionObject *) - PyFunction_New(codeobj, GLOBALS()); - + PyFunction_New(codeobj, GLOBALS()); Py_DECREF(codeobj); if (func_obj == NULL) { - goto error; + GOTO_ERROR(error); } - - func_obj->func_version = ((PyCodeObject *)codeobj)->co_version; + _PyFunction_SetVersion( + func_obj, ((PyCodeObject *)codeobj)->co_version); func = (PyObject *)func_obj; stack_pointer[-1] = func; break; } - case SET_FUNCTION_ATTRIBUTE: { + case _SET_FUNCTION_ATTRIBUTE: { PyObject *func; PyObject *attr; + oparg = CURRENT_OPARG(); func = stack_pointer[-1]; attr = stack_pointer[-2]; assert(PyFunction_Check(func)); PyFunctionObject *func_obj = (PyFunctionObject *)func; switch(oparg) { case MAKE_FUNCTION_CLOSURE: - assert(func_obj->func_closure == NULL); - func_obj->func_closure = attr; - break; + assert(func_obj->func_closure == NULL); + func_obj->func_closure = attr; + break; case MAKE_FUNCTION_ANNOTATIONS: - assert(func_obj->func_annotations == NULL); - func_obj->func_annotations = attr; - break; + assert(func_obj->func_annotations == NULL); + func_obj->func_annotations = attr; + break; case MAKE_FUNCTION_KWDEFAULTS: - assert(PyDict_CheckExact(attr)); - assert(func_obj->func_kwdefaults == NULL); - func_obj->func_kwdefaults = attr; - break; + assert(PyDict_CheckExact(attr)); + assert(func_obj->func_kwdefaults == NULL); + func_obj->func_kwdefaults = attr; + break; case MAKE_FUNCTION_DEFAULTS: - assert(PyTuple_CheckExact(attr)); - assert(func_obj->func_defaults == NULL); - func_obj->func_defaults = attr; - break; + assert(PyTuple_CheckExact(attr)); + assert(func_obj->func_defaults == NULL); + func_obj->func_defaults = attr; + break; default: - Py_UNREACHABLE(); + Py_UNREACHABLE(); } - STACK_SHRINK(1); - stack_pointer[-1] = func; + stack_pointer[-2] = func; + stack_pointer += -1; break; } - case BUILD_SLICE: { + case _BUILD_SLICE: { PyObject *step = NULL; PyObject *stop; PyObject *start; PyObject *slice; - if (oparg == 3) { step = stack_pointer[-(oparg == 3 ? 1 : 0)]; } - stop = stack_pointer[-1 - (oparg == 3 ? 1 : 0)]; - start = stack_pointer[-2 - (oparg == 3 ? 1 : 0)]; + oparg = CURRENT_OPARG(); + if (oparg == 3) { step = stack_pointer[-((oparg == 3) ? 1 : 0)]; } + stop = stack_pointer[-1 - ((oparg == 3) ? 1 : 0)]; + start = stack_pointer[-2 - ((oparg == 3) ? 1 : 0)]; slice = PySlice_New(start, stop, step); Py_DECREF(start); Py_DECREF(stop); Py_XDECREF(step); - if (slice == NULL) { STACK_SHRINK(((oparg == 3) ? 1 : 0)); goto pop_2_error; } - STACK_SHRINK(((oparg == 3) ? 1 : 0)); - STACK_SHRINK(1); - stack_pointer[-1] = slice; + if (slice == NULL) { stack_pointer += -2 - ((oparg == 3) ? 1 : 0); goto error_tier_two; } + stack_pointer[-2 - ((oparg == 3) ? 1 : 0)] = slice; + stack_pointer += -1 - ((oparg == 3) ? 1 : 0); break; } - case CONVERT_VALUE: { + case _CONVERT_VALUE: { PyObject *value; PyObject *result; + oparg = CURRENT_OPARG(); value = stack_pointer[-1]; convertion_func_ptr conv_fn; assert(oparg >= FVC_STR && oparg <= FVC_ASCII); conv_fn = CONVERSION_FUNCTIONS[oparg]; result = conv_fn(value); Py_DECREF(value); - if (result == NULL) goto pop_1_error; + if (result == NULL) goto pop_1_error_tier_two; stack_pointer[-1] = result; break; } - case FORMAT_SIMPLE: { + case _FORMAT_SIMPLE: { PyObject *value; PyObject *res; value = stack_pointer[-1]; @@ -2604,7 +3236,7 @@ if (!PyUnicode_CheckExact(value)) { res = PyObject_Format(value, NULL); Py_DECREF(value); - if (res == NULL) goto pop_1_error; + if (res == NULL) goto pop_1_error_tier_two; } else { res = value; @@ -2613,7 +3245,7 @@ break; } - case FORMAT_WITH_SPEC: { + case _FORMAT_WITH_SPEC: { PyObject *fmt_spec; PyObject *value; PyObject *res; @@ -2622,55 +3254,45 @@ res = PyObject_Format(value, fmt_spec); Py_DECREF(value); Py_DECREF(fmt_spec); - if (res == NULL) goto pop_2_error; - STACK_SHRINK(1); - stack_pointer[-1] = res; + if (res == NULL) goto pop_2_error_tier_two; + stack_pointer[-2] = res; + stack_pointer += -1; break; } - case COPY: { + case _COPY: { PyObject *bottom; PyObject *top; + oparg = CURRENT_OPARG(); bottom = stack_pointer[-1 - (oparg-1)]; assert(oparg > 0); top = Py_NewRef(bottom); - STACK_GROW(1); - stack_pointer[-1] = top; + stack_pointer[0] = top; + stack_pointer += 1; break; } - case BINARY_OP: { - static_assert(INLINE_CACHE_ENTRIES_BINARY_OP == 1, "incorrect cache size"); + case _BINARY_OP: { PyObject *rhs; PyObject *lhs; PyObject *res; + oparg = CURRENT_OPARG(); rhs = stack_pointer[-1]; lhs = stack_pointer[-2]; - #if ENABLE_SPECIALIZATION - _PyBinaryOpCache *cache = (_PyBinaryOpCache *)next_instr; - if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) { - next_instr--; - _Py_Specialize_BinaryOp(lhs, rhs, next_instr, oparg, LOCALS_ARRAY); - DISPATCH_SAME_OPARG(); - } - STAT_INC(BINARY_OP, deferred); - DECREMENT_ADAPTIVE_COUNTER(cache->counter); - #endif /* ENABLE_SPECIALIZATION */ - assert(NB_ADD <= oparg); - assert(oparg <= NB_INPLACE_XOR); assert(_PyEval_BinaryOps[oparg]); res = _PyEval_BinaryOps[oparg](lhs, rhs); Py_DECREF(lhs); Py_DECREF(rhs); - if (res == NULL) goto pop_2_error; - STACK_SHRINK(1); - stack_pointer[-1] = res; + if (res == NULL) goto pop_2_error_tier_two; + stack_pointer[-2] = res; + stack_pointer += -1; break; } - case SWAP: { + case _SWAP: { PyObject *top; PyObject *bottom; + oparg = CURRENT_OPARG(); top = stack_pointer[-1]; bottom = stack_pointer[-2 - (oparg-2)]; assert(oparg >= 2); @@ -2679,41 +3301,118 @@ break; } - case _POP_JUMP_IF_FALSE: { + /* _INSTRUMENTED_INSTRUCTION is not a viable micro-op for tier 2 */ + + /* _INSTRUMENTED_JUMP_FORWARD is not a viable micro-op for tier 2 */ + + /* _INSTRUMENTED_JUMP_BACKWARD is not a viable micro-op for tier 2 */ + + /* _INSTRUMENTED_POP_JUMP_IF_TRUE is not a viable micro-op for tier 2 */ + + /* _INSTRUMENTED_POP_JUMP_IF_FALSE is not a viable micro-op for tier 2 */ + + /* _INSTRUMENTED_POP_JUMP_IF_NONE is not a viable micro-op for tier 2 */ + + /* _INSTRUMENTED_POP_JUMP_IF_NOT_NONE is not a viable micro-op for tier 2 */ + + case _GUARD_IS_TRUE_POP: { PyObject *flag; flag = stack_pointer[-1]; - if (Py_IsFalse(flag)) { - pc = oparg; - } - STACK_SHRINK(1); + if (Py_IsFalse(flag)) goto deoptimize; + assert(Py_IsTrue(flag)); + stack_pointer += -1; break; } - case _POP_JUMP_IF_TRUE: { + case _GUARD_IS_FALSE_POP: { PyObject *flag; flag = stack_pointer[-1]; - if (Py_IsTrue(flag)) { - pc = oparg; - } - STACK_SHRINK(1); + if (Py_IsTrue(flag)) goto deoptimize; + assert(Py_IsFalse(flag)); + stack_pointer += -1; + break; + } + + case _GUARD_IS_NONE_POP: { + PyObject *val; + val = stack_pointer[-1]; + if (!Py_IsNone(val)) goto deoptimize; + stack_pointer += -1; break; } - case JUMP_TO_TOP: { - pc = 0; + case _GUARD_IS_NOT_NONE_POP: { + PyObject *val; + val = stack_pointer[-1]; + if (Py_IsNone(val)) goto deoptimize; + Py_DECREF(val); + stack_pointer += -1; + break; + } + + case _JUMP_TO_TOP: { + next_uop = current_executor->trace; CHECK_EVAL_BREAKER(); break; } - case SAVE_IP: { - frame->prev_instr = ip_offset + oparg; + case _SET_IP: { + oparg = CURRENT_OPARG(); + TIER_TWO_ONLY + // TODO: Put the code pointer in `operand` to avoid indirection via `frame` + frame->instr_ptr = _PyCode_CODE(_PyFrame_GetCode(frame)) + oparg; break; } - case EXIT_TRACE: { - frame->prev_instr--; // Back up to just before destination - _PyFrame_SetStackPointer(frame, stack_pointer); - Py_DECREF(self); - return frame; + case _SAVE_RETURN_OFFSET: { + oparg = CURRENT_OPARG(); + #if TIER_ONE + frame->return_offset = (uint16_t)(next_instr - this_instr); + #endif + #if TIER_TWO + frame->return_offset = oparg; + #endif break; } + + case _EXIT_TRACE: { + TIER_TWO_ONLY + if (1) goto deoptimize; + break; + } + + case _INSERT: { + PyObject *top; + oparg = CURRENT_OPARG(); + top = stack_pointer[-1]; + // Inserts TOS at position specified by oparg; + memmove(&stack_pointer[-1 - oparg], &stack_pointer[-oparg], oparg * sizeof(stack_pointer[0])); + stack_pointer[-1 - oparg] = top; + break; + } + + case _CHECK_VALIDITY: { + TIER_TWO_ONLY + if (!current_executor->base.vm_data.valid) goto deoptimize; + break; + } + + case _LOAD_CONST_INLINE_BORROW: { + PyObject *value; + PyObject *ptr = (PyObject *)CURRENT_OPERAND(); + value = ptr; + stack_pointer[0] = value; + stack_pointer += 1; + break; + } + + case _INTERNAL_INCREMENT_OPT_COUNTER: { + PyObject *opt; + opt = stack_pointer[-1]; + _PyCounterOptimizerObject *exe = (_PyCounterOptimizerObject *)opt; + exe->count++; + stack_pointer += -1; + break; + } + +#undef TIER_TWO diff --git a/Python/fileutils.c b/Python/fileutils.c index 19b23f6bd18b30..882d3299575cf3 100644 --- a/Python/fileutils.c +++ b/Python/fileutils.c @@ -2,8 +2,11 @@ #include "pycore_fileutils.h" // fileutils definitions #include "pycore_runtime.h" // _PyRuntime #include "osdefs.h" // SEP -#include + #include // mbstowcs() +#ifdef HAVE_UNISTD_H +# include // getcwd() +#endif #ifdef MS_WINDOWS # include @@ -19,7 +22,7 @@ extern int winerror_to_errno(int); #endif #ifdef HAVE_LANGINFO_H -#include +# include // nl_langinfo(CODESET) #endif #ifdef HAVE_SYS_IOCTL_H @@ -27,12 +30,12 @@ extern int winerror_to_errno(int); #endif #ifdef HAVE_NON_UNICODE_WCHAR_T_REPRESENTATION -#include +# include // iconv_open() #endif #ifdef HAVE_FCNTL_H -#include -#endif /* HAVE_FCNTL_H */ +# include // fcntl(F_GETFD) +#endif #ifdef O_CLOEXEC /* Does open() support the O_CLOEXEC flag? Possible values: @@ -1236,6 +1239,7 @@ _Py_fstat_noraise(int fd, struct _Py_stat_struct *status) BY_HANDLE_FILE_INFORMATION info; FILE_BASIC_INFO basicInfo; FILE_ID_INFO idInfo; + FILE_ID_INFO *pIdInfo = &idInfo; HANDLE h; int type; @@ -1268,15 +1272,19 @@ _Py_fstat_noraise(int fd, struct _Py_stat_struct *status) } if (!GetFileInformationByHandle(h, &info) || - !GetFileInformationByHandleEx(h, FileBasicInfo, &basicInfo, sizeof(basicInfo)) || - !GetFileInformationByHandleEx(h, FileIdInfo, &idInfo, sizeof(idInfo))) { + !GetFileInformationByHandleEx(h, FileBasicInfo, &basicInfo, sizeof(basicInfo))) { /* The Win32 error is already set, but we also set errno for callers who expect it */ errno = winerror_to_errno(GetLastError()); return -1; } - _Py_attribute_data_to_stat(&info, 0, &basicInfo, &idInfo, status); + if (!GetFileInformationByHandleEx(h, FileIdInfo, &idInfo, sizeof(idInfo))) { + /* Failed to get FileIdInfo, so do not pass it along */ + pIdInfo = NULL; + } + + _Py_attribute_data_to_stat(&info, 0, &basicInfo, pIdInfo, status); return 0; #else return fstat(fd, status); @@ -1790,6 +1798,7 @@ _Py_fopen_obj(PyObject *path, const char *mode) Py_END_ALLOW_THREADS } while (f == NULL && errno == EINTR && !(async_err = PyErr_CheckSignals())); + int saved_errno = errno; PyMem_Free(wpath); #else PyObject *bytes; @@ -1812,13 +1821,14 @@ _Py_fopen_obj(PyObject *path, const char *mode) Py_END_ALLOW_THREADS } while (f == NULL && errno == EINTR && !(async_err = PyErr_CheckSignals())); - + int saved_errno = errno; Py_DECREF(bytes); #endif if (async_err) return NULL; if (f == NULL) { + errno = saved_errno; PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path); return NULL; } @@ -2377,12 +2387,14 @@ _Py_find_basename(const wchar_t *filename) path, which will be within the original buffer. Guaranteed to not make the path longer, and will not fail. 'size' is the length of the path, if known. If -1, the first null character will be assumed - to be the end of the path. */ + to be the end of the path. 'normsize' will be set to contain the + length of the resulting normalized path. */ wchar_t * -_Py_normpath(wchar_t *path, Py_ssize_t size) +_Py_normpath_and_size(wchar_t *path, Py_ssize_t size, Py_ssize_t *normsize) { assert(path != NULL); - if (!path[0] || size == 0) { + if ((size < 0 && !path[0]) || size == 0) { + *normsize = 0; return path; } wchar_t *pEnd = size >= 0 ? &path[size] : NULL; @@ -2431,11 +2443,7 @@ _Py_normpath(wchar_t *path, Py_ssize_t size) *p2++ = lastC = *p1; } } - if (sepCount) { - minP2 = p2; // Invalid path - } else { - minP2 = p2 - 1; // Absolute path has SEP at minP2 - } + minP2 = p2 - 1; } #else // Skip past two leading SEPs @@ -2495,13 +2503,28 @@ _Py_normpath(wchar_t *path, Py_ssize_t size) while (--p2 != minP2 && *p2 == SEP) { *p2 = L'\0'; } + } else { + --p2; } + *normsize = p2 - path + 1; #undef SEP_OR_END #undef IS_SEP #undef IS_END return path; } +/* In-place path normalisation. Returns the start of the normalized + path, which will be within the original buffer. Guaranteed to not + make the path longer, and will not fail. 'size' is the length of + the path, if known. If -1, the first null character will be assumed + to be the end of the path. */ +wchar_t * +_Py_normpath(wchar_t *path, Py_ssize_t size) +{ + Py_ssize_t norm_length; + return _Py_normpath_and_size(path, size, &norm_length); +} + /* Get the current directory. buflen is the buffer size in wide characters including the null character. Decode the path from the locale encoding. @@ -2855,9 +2878,9 @@ _Py_GetLocaleconvNumeric(struct lconv *lc, * non-opened fd in the middle. * 2b. If fdwalk(3) isn't available, just do a plain close(2) loop. */ -#ifdef __FreeBSD__ +#ifdef HAVE_CLOSEFROM # define USE_CLOSEFROM -#endif /* __FreeBSD__ */ +#endif /* HAVE_CLOSEFROM */ #ifdef HAVE_FDWALK # define USE_FDWALK @@ -2899,7 +2922,7 @@ _Py_closerange(int first, int last) #ifdef USE_CLOSEFROM if (last >= sysconf(_SC_OPEN_MAX)) { /* Any errors encountered while closing file descriptors are ignored */ - closefrom(first); + (void)closefrom(first); } else #endif /* USE_CLOSEFROM */ @@ -2920,3 +2943,27 @@ _Py_closerange(int first, int last) #endif /* USE_FDWALK */ _Py_END_SUPPRESS_IPH } + + +#ifndef MS_WINDOWS +// Ticks per second used by clock() and times() functions. +// See os.times() and time.process_time() implementations. +int +_Py_GetTicksPerSecond(long *ticks_per_second) +{ +#if defined(HAVE_SYSCONF) && defined(_SC_CLK_TCK) + long value = sysconf(_SC_CLK_TCK); + if (value < 1) { + return -1; + } + *ticks_per_second = value; +#elif defined(HZ) + assert(HZ >= 1); + *ticks_per_second = HZ; +#else + // Magic fallback value; may be bogus + *ticks_per_second = 60; +#endif + return 0; +} +#endif diff --git a/Python/flowgraph.c b/Python/flowgraph.c index a72b85d45aa27d..dad945761a4a58 100644 --- a/Python/flowgraph.c +++ b/Python/flowgraph.c @@ -24,19 +24,80 @@ typedef _PyCompilerSrcLocation location; typedef _PyCfgJumpTargetLabel jump_target_label; -typedef _PyCfgBasicblock basicblock; -typedef _PyCfgBuilder cfg_builder; -typedef _PyCfgInstruction cfg_instr; + +typedef struct _PyCfgInstruction { + int i_opcode; + int i_oparg; + _PyCompilerSrcLocation i_loc; + struct _PyCfgBasicblock *i_target; /* target block (if jump instruction) */ + struct _PyCfgBasicblock *i_except; /* target block when exception is raised */ +} cfg_instr; + +typedef struct _PyCfgBasicblock { + /* Each basicblock in a compilation unit is linked via b_list in the + reverse order that the block are allocated. b_list points to the next + block in this list, not to be confused with b_next, which is next by + control flow. */ + struct _PyCfgBasicblock *b_list; + /* The label of this block if it is a jump target, -1 otherwise */ + _PyCfgJumpTargetLabel b_label; + /* Exception stack at start of block, used by assembler to create the exception handling table */ + struct _PyCfgExceptStack *b_exceptstack; + /* pointer to an array of instructions, initially NULL */ + cfg_instr *b_instr; + /* If b_next is non-NULL, it is a pointer to the next + block reached by normal control flow. */ + struct _PyCfgBasicblock *b_next; + /* number of instructions used */ + int b_iused; + /* length of instruction array (b_instr) */ + int b_ialloc; + /* Used by add_checks_for_loads_of_unknown_variables */ + uint64_t b_unsafe_locals_mask; + /* Number of predecessors that a block has. */ + int b_predecessors; + /* depth of stack upon entry of block, computed by stackdepth() */ + int b_startdepth; + /* Basic block is an exception handler that preserves lasti */ + unsigned b_preserve_lasti : 1; + /* Used by compiler passes to mark whether they have visited a basic block. */ + unsigned b_visited : 1; + /* b_except_handler is used by the cold-detection algorithm to mark exception targets */ + unsigned b_except_handler : 1; + /* b_cold is true if this block is not perf critical (like an exception handler) */ + unsigned b_cold : 1; + /* b_warm is used by the cold-detection algorithm to mark blocks which are definitely not cold */ + unsigned b_warm : 1; +} basicblock; + + +struct _PyCfgBuilder { + /* The entryblock, at which control flow begins. All blocks of the + CFG are reachable through the b_next links */ + struct _PyCfgBasicblock *g_entryblock; + /* Pointer to the most recently allocated block. By following + b_list links, you can reach all allocated blocks. */ + struct _PyCfgBasicblock *g_block_list; + /* pointer to the block currently being constructed */ + struct _PyCfgBasicblock *g_curblock; + /* label for the next instruction to be placed */ + _PyCfgJumpTargetLabel g_current_label; +}; + +typedef struct _PyCfgBuilder cfg_builder; static const jump_target_label NO_LABEL = {-1}; #define SAME_LABEL(L1, L2) ((L1).id == (L2).id) #define IS_LABEL(L) (!SAME_LABEL((L), (NO_LABEL))) +#define LOCATION(LNO, END_LNO, COL, END_COL) \ + ((const _PyCompilerSrcLocation){(LNO), (END_LNO), (COL), (END_COL)}) static inline int is_block_push(cfg_instr *i) { + assert(OPCODE_HAS_ARG(i->i_opcode) || !IS_BLOCK_PUSH_OPCODE(i->i_opcode)); return IS_BLOCK_PUSH_OPCODE(i->i_opcode); } @@ -50,7 +111,7 @@ is_jump(cfg_instr *i) #define INSTR_SET_OP1(I, OP, ARG) \ do { \ assert(OPCODE_HAS_ARG(OP)); \ - _PyCfgInstruction *_instr__ptr_ = (I); \ + cfg_instr *_instr__ptr_ = (I); \ _instr__ptr_->i_opcode = (OP); \ _instr__ptr_->i_oparg = (ARG); \ } while (0); @@ -59,7 +120,7 @@ is_jump(cfg_instr *i) #define INSTR_SET_OP0(I, OP) \ do { \ assert(!OPCODE_HAS_ARG(OP)); \ - _PyCfgInstruction *_instr__ptr_ = (I); \ + cfg_instr *_instr__ptr_ = (I); \ _instr__ptr_->i_opcode = (OP); \ _instr__ptr_->i_oparg = 0; \ } while (0); @@ -148,8 +209,8 @@ basicblock_last_instr(const basicblock *b) { } static inline int -basicblock_nofallthrough(const _PyCfgBasicblock *b) { - _PyCfgInstruction *last = basicblock_last_instr(b); +basicblock_nofallthrough(const basicblock *b) { + cfg_instr *last = basicblock_last_instr(b); return (last && (IS_SCOPE_EXIT_OPCODE(last->i_opcode) || IS_UNCONDITIONAL_JUMP_OPCODE(last->i_opcode))); @@ -175,8 +236,8 @@ copy_basicblock(cfg_builder *g, basicblock *block) return result; } -int -_PyBasicblock_InsertInstruction(basicblock *block, int pos, cfg_instr *instr) { +static int +basicblock_insert_instruction(basicblock *block, int pos, cfg_instr *instr) { RETURN_IF_ERROR(basicblock_next_instr(block)); for (int i = block->b_iused - 1; i > pos; i--) { block->b_instr[i] = block->b_instr[i-1]; @@ -201,8 +262,8 @@ dump_instr(cfg_instr *i) if (HAS_TARGET(i->i_opcode)) { sprintf(arg, "target: %p [%d] ", i->i_target, i->i_oparg); } - fprintf(stderr, "line: %d, opcode: %d %s%s\n", - i->i_loc.lineno, i->i_opcode, arg, jump); + fprintf(stderr, "line: %d, %s (%d) %s%s\n", + i->i_loc.lineno, _PyOpcode_OpName[i->i_opcode], i->i_opcode, arg, jump); } static inline int @@ -311,8 +372,8 @@ cfg_builder_check(cfg_builder *g) } #endif -int -_PyCfgBuilder_Init(cfg_builder *g) +static int +init_cfg_builder(cfg_builder *g) { g->g_block_list = NULL; basicblock *block = cfg_builder_new_block(g); @@ -324,9 +385,28 @@ _PyCfgBuilder_Init(cfg_builder *g) return SUCCESS; } +cfg_builder * +_PyCfgBuilder_New(void) +{ + cfg_builder *g = PyMem_Malloc(sizeof(cfg_builder)); + if (g == NULL) { + PyErr_NoMemory(); + return NULL; + } + memset(g, 0, sizeof(cfg_builder)); + if (init_cfg_builder(g) < 0) { + PyMem_Free(g); + return NULL; + } + return g; +} + void -_PyCfgBuilder_Fini(cfg_builder* g) +_PyCfgBuilder_Free(cfg_builder *g) { + if (g == NULL) { + return; + } assert(cfg_builder_check(g)); basicblock *b = g->g_block_list; while (b != NULL) { @@ -337,6 +417,21 @@ _PyCfgBuilder_Fini(cfg_builder* g) PyObject_Free((void *)b); b = next; } + PyMem_Free(g); +} + +int +_PyCfgBuilder_CheckSize(cfg_builder *g) +{ + int nblocks = 0; + for (basicblock *b = g->g_block_list; b != NULL; b = b->b_list) { + nblocks++; + } + if ((size_t)nblocks > SIZE_MAX / sizeof(basicblock *)) { + PyErr_NoMemory(); + return ERROR; + } + return SUCCESS; } int @@ -354,6 +449,15 @@ _PyCfgBuilder_Addop(cfg_builder *g, int opcode, int oparg, location loc) } +static basicblock * +next_nonempty_block(basicblock *b) +{ + while (b && b->b_iused == 0) { + b = b->b_next; + } + return b; +} + /***** debugging helpers *****/ #ifndef NDEBUG @@ -369,25 +473,20 @@ no_redundant_nops(cfg_builder *g) { return true; } -static bool -no_empty_basic_blocks(cfg_builder *g) { - for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) { - if (b->b_iused == 0) { - return false; - } - } - return true; -} - static bool no_redundant_jumps(cfg_builder *g) { for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) { cfg_instr *last = basicblock_last_instr(b); if (last != NULL) { if (IS_UNCONDITIONAL_JUMP_OPCODE(last->i_opcode)) { - assert(last->i_target != b->b_next); - if (last->i_target == b->b_next) { - return false; + basicblock *next = next_nonempty_block(b->b_next); + basicblock *jump_target = next_nonempty_block(last->i_target); + if (jump_target == next) { + assert(next); + if (last->i_loc.lineno == next->b_instr[0].i_loc.lineno) { + assert(0); + return false; + } } } } @@ -437,7 +536,7 @@ normalize_jumps_in_block(cfg_builder *g, basicblock *b) { if (backwards_jump == NULL) { return ERROR; } - basicblock_addop(backwards_jump, JUMP, target->b_label.id, NO_LOCATION); + basicblock_addop(backwards_jump, JUMP, target->b_label.id, last->i_loc); backwards_jump->b_instr[0].i_target = target; last->i_opcode = reversed_opcode; last->i_target = b->b_next; @@ -450,7 +549,7 @@ normalize_jumps_in_block(cfg_builder *g, basicblock *b) { static int -normalize_jumps(_PyCfgBuilder *g) +normalize_jumps(cfg_builder *g) { basicblock *entryblock = g->g_entryblock; for (basicblock *b = entryblock; b != NULL; b = b->b_next) { @@ -463,14 +562,6 @@ normalize_jumps(_PyCfgBuilder *g) return SUCCESS; } -int -_PyCfg_ResolveJumps(_PyCfgBuilder *g) -{ - RETURN_IF_ERROR(normalize_jumps(g)); - assert(no_redundant_jumps(g)); - return SUCCESS; -} - static int check_cfg(cfg_builder *g) { for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) { @@ -489,16 +580,23 @@ check_cfg(cfg_builder *g) { return SUCCESS; } -/* Calculate the actual jump target from the target_label */ static int -translate_jump_labels_to_targets(basicblock *entryblock) +get_max_label(basicblock *entryblock) { - int max_label = -1; + int lbl = -1; for (basicblock *b = entryblock; b != NULL; b = b->b_next) { - if (b->b_label.id > max_label) { - max_label = b->b_label.id; + if (b->b_label.id > lbl) { + lbl = b->b_label.id; } } + return lbl; +} + +/* Calculate the actual jump target from the target_label */ +static int +translate_jump_labels_to_targets(basicblock *entryblock) +{ + int max_label = get_max_label(entryblock); size_t mapsize = sizeof(basicblock *) * (max_label + 1); basicblock **label2block = (basicblock **)PyMem_Malloc(mapsize); if (!label2block) { @@ -529,9 +627,9 @@ translate_jump_labels_to_targets(basicblock *entryblock) } int -_PyCfg_JumpLabelsToTargets(basicblock *entryblock) +_PyCfg_JumpLabelsToTargets(cfg_builder *g) { - return translate_jump_labels_to_targets(entryblock); + return translate_jump_labels_to_targets(g->g_entryblock); } static int @@ -553,34 +651,39 @@ mark_except_handlers(basicblock *entryblock) { } -typedef _PyCfgExceptStack ExceptStack; +struct _PyCfgExceptStack { + basicblock *handlers[CO_MAXBLOCKS+2]; + int depth; +}; + static basicblock * -push_except_block(ExceptStack *stack, cfg_instr *setup) { +push_except_block(struct _PyCfgExceptStack *stack, cfg_instr *setup) { assert(is_block_push(setup)); int opcode = setup->i_opcode; basicblock * target = setup->i_target; if (opcode == SETUP_WITH || opcode == SETUP_CLEANUP) { target->b_preserve_lasti = 1; } + assert(stack->depth <= CO_MAXBLOCKS); stack->handlers[++stack->depth] = target; return target; } static basicblock * -pop_except_block(ExceptStack *stack) { +pop_except_block(struct _PyCfgExceptStack *stack) { assert(stack->depth > 0); return stack->handlers[--stack->depth]; } static basicblock * -except_stack_top(ExceptStack *stack) { +except_stack_top(struct _PyCfgExceptStack *stack) { return stack->handlers[stack->depth]; } -static ExceptStack * +static struct _PyCfgExceptStack * make_except_stack(void) { - ExceptStack *new = PyMem_Malloc(sizeof(ExceptStack)); + struct _PyCfgExceptStack *new = PyMem_Malloc(sizeof(struct _PyCfgExceptStack)); if (new == NULL) { PyErr_NoMemory(); return NULL; @@ -590,14 +693,14 @@ make_except_stack(void) { return new; } -static ExceptStack * -copy_except_stack(ExceptStack *stack) { - ExceptStack *copy = PyMem_Malloc(sizeof(ExceptStack)); +static struct _PyCfgExceptStack * +copy_except_stack(struct _PyCfgExceptStack *stack) { + struct _PyCfgExceptStack *copy = PyMem_Malloc(sizeof(struct _PyCfgExceptStack)); if (copy == NULL) { PyErr_NoMemory(); return NULL; } - memcpy(copy, stack, sizeof(ExceptStack)); + memcpy(copy, stack, sizeof(struct _PyCfgExceptStack)); return copy; } @@ -633,8 +736,8 @@ stackdepth_push(basicblock ***sp, basicblock *b, int depth) /* Find the flow path that needs the largest stack. We assume that * cycles in the flow graph have no net effect on the stack depth. */ -int -_PyCfg_Stackdepth(cfg_builder *g) +static int +calculate_stackdepth(cfg_builder *g) { basicblock *entryblock = g->g_entryblock; for (basicblock *b = entryblock; b != NULL; b = b->b_next) { @@ -723,7 +826,7 @@ label_exception_targets(basicblock *entryblock) { if (todo_stack == NULL) { return ERROR; } - ExceptStack *except_stack = make_except_stack(); + struct _PyCfgExceptStack *except_stack = make_except_stack(); if (except_stack == NULL) { PyMem_Free(todo_stack); PyErr_NoMemory(); @@ -743,11 +846,12 @@ label_exception_targets(basicblock *entryblock) { assert(except_stack != NULL); b->b_exceptstack = NULL; handler = except_stack_top(except_stack); + int last_yield_except_depth = -1; for (int i = 0; i < b->b_iused; i++) { cfg_instr *instr = &b->b_instr[i]; if (is_block_push(instr)) { if (!instr->i_target->b_visited) { - ExceptStack *copy = copy_except_stack(except_stack); + struct _PyCfgExceptStack *copy = copy_except_stack(except_stack); if (copy == NULL) { goto error; } @@ -766,7 +870,7 @@ label_exception_targets(basicblock *entryblock) { assert(i == b->b_iused -1); if (!instr->i_target->b_visited) { if (BB_HAS_FALLTHROUGH(b)) { - ExceptStack *copy = copy_except_stack(except_stack); + struct _PyCfgExceptStack *copy = copy_except_stack(except_stack); if (copy == NULL) { goto error; } @@ -781,10 +885,21 @@ label_exception_targets(basicblock *entryblock) { todo++; } } - else { - if (instr->i_opcode == YIELD_VALUE) { - instr->i_oparg = except_stack->depth; + else if (instr->i_opcode == YIELD_VALUE) { + instr->i_except = handler; + last_yield_except_depth = except_stack->depth; + } + else if (instr->i_opcode == RESUME) { + instr->i_except = handler; + if (instr->i_oparg != RESUME_AT_FUNC_START) { + assert(last_yield_except_depth >= 0); + if (last_yield_except_depth == 1) { + instr->i_oparg |= RESUME_OPARG_DEPTH1_MASK; + } + last_yield_except_depth = -1; } + } + else { instr->i_except = handler; } } @@ -850,35 +965,6 @@ mark_reachable(basicblock *entryblock) { return SUCCESS; } -static void -eliminate_empty_basic_blocks(cfg_builder *g) { - /* Eliminate empty blocks */ - 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; - } - 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++) { - cfg_instr *instr = &b->b_instr[i]; - if (HAS_TARGET(instr->i_opcode)) { - basicblock *target = instr->i_target; - while (target->b_iused == 0) { - target = target->b_next; - } - instr->i_target = target; - assert(instr->i_target && instr->i_target->b_iused > 0); - } - } - } -} - static int remove_redundant_nops(basicblock *bb) { /* Remove NOPs when legal to do so. */ @@ -907,13 +993,20 @@ remove_redundant_nops(basicblock *bb) { } } else { - basicblock* next = bb->b_next; - while (next && next->b_iused == 0) { - next = next->b_next; - } + basicblock *next = next_nonempty_block(bb->b_next); /* or if last instruction in BB and next BB has same line number */ if (next) { - if (lineno == next->b_instr[0].i_loc.lineno) { + location next_loc = NO_LOCATION; + for (int next_i=0; next_i < next->b_iused; next_i++) { + cfg_instr *instr = &next->b_instr[next_i]; + if (instr->i_opcode == NOP && instr->i_loc.lineno == NO_LOCATION.lineno) { + /* Skip over NOPs without location, they will be removed */ + continue; + } + next_loc = instr->i_loc; + break; + } + if (lineno == next_loc.lineno) { continue; } } @@ -983,22 +1076,31 @@ remove_redundant_jumps(cfg_builder *g) { * of that jump. If it is, then the jump instruction is redundant and * can be deleted. */ - assert(no_empty_basic_blocks(g)); + for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) { cfg_instr *last = basicblock_last_instr(b); - assert(last != NULL); + if (last == NULL) { + continue; + } assert(!IS_ASSEMBLER_OPCODE(last->i_opcode)); if (IS_UNCONDITIONAL_JUMP_OPCODE(last->i_opcode)) { - if (last->i_target == NULL) { + basicblock* jump_target = next_nonempty_block(last->i_target); + if (jump_target == NULL) { PyErr_SetString(PyExc_SystemError, "jump with NULL target"); return ERROR; } - if (last->i_target == b->b_next) { - assert(b->b_next->b_iused); - INSTR_SET_OP0(last, NOP); + basicblock *next = next_nonempty_block(b->b_next); + if (jump_target == next) { + if (last->i_loc.lineno == NO_LOCATION.lineno) { + b->b_iused--; + } + else { + INSTR_SET_OP0(last, NOP); + } } } } + return SUCCESS; } @@ -1037,11 +1139,15 @@ jump_thread(cfg_instr *inst, cfg_instr *target, int opcode) assert(is_jump(target)); // bpo-45773: If inst->i_target == target->i_target, then nothing actually // changes (and we fall into an infinite loop): - if ((inst->i_loc.lineno == target->i_loc.lineno || target->i_loc.lineno == -1) && + if ((inst->i_loc.lineno == target->i_loc.lineno || + inst->i_loc.lineno == -1 || target->i_loc.lineno == -1) && inst->i_target != target->i_target) { inst->i_target = target->i_target; inst->i_opcode = opcode; + if (inst->i_loc.lineno == -1) { + inst->i_loc = target->i_loc; + } return true; } return false; @@ -1504,9 +1610,14 @@ optimize_basic_block(PyObject *const_cache, basicblock *bb, PyObject *consts) } break; case JUMP: + case JUMP_NO_INTERRUPT: switch (target->i_opcode) { case JUMP: i -= jump_thread(inst, target, JUMP); + continue; + case JUMP_NO_INTERRUPT: + i -= jump_thread(inst, target, opcode); + continue; } break; case FOR_ITER: @@ -1534,12 +1645,10 @@ optimize_basic_block(PyObject *const_cache, basicblock *bb, PyObject *consts) INSTR_SET_OP0(inst, NOP); } break; - case KW_NAMES: - break; - case PUSH_NULL: - if (nextop == LOAD_GLOBAL && (inst[1].i_opcode & 1) == 0) { - INSTR_SET_OP0(inst, NOP); - inst[1].i_oparg |= 1; + case LOAD_GLOBAL: + if (nextop == PUSH_NULL && (oparg & 1) == 0) { + INSTR_SET_OP1(inst, LOAD_GLOBAL, oparg | 1); + INSTR_SET_OP0(&bb->b_instr[i + 1], NOP); } break; case COMPARE_OP: @@ -1608,11 +1717,9 @@ optimize_cfg(cfg_builder *g, PyObject *consts, PyObject *const_cache) { assert(PyDict_CheckExact(const_cache)); RETURN_IF_ERROR(check_cfg(g)); - eliminate_empty_basic_blocks(g); for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) { RETURN_IF_ERROR(inline_small_exit_blocks(b)); } - assert(no_empty_basic_blocks(g)); for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) { RETURN_IF_ERROR(optimize_basic_block(const_cache, b, consts)); assert(b->b_predecessors == 0); @@ -1627,14 +1734,21 @@ optimize_cfg(cfg_builder *g, PyObject *consts, PyObject *const_cache) for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) { if (b->b_predecessors == 0) { b->b_iused = 0; + b->b_except_handler = 0; } } for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) { remove_redundant_nops(b); } - eliminate_empty_basic_blocks(g); - assert(no_redundant_nops(g)); RETURN_IF_ERROR(remove_redundant_jumps(g)); + + for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) { + remove_redundant_nops(b); + } + + RETURN_IF_ERROR(remove_redundant_jumps(g)); + + assert(no_redundant_jumps(g)); return SUCCESS; } @@ -1684,7 +1798,6 @@ insert_superinstructions(cfg_builder *g) for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) { remove_redundant_nops(b); } - eliminate_empty_basic_blocks(g); assert(no_redundant_nops(g)); } @@ -2038,6 +2151,8 @@ push_cold_blocks_to_end(cfg_builder *g) { } RETURN_IF_ERROR(mark_cold(entryblock)); + int next_lbl = get_max_label(g->g_entryblock) + 1; + /* If we have a cold block with fallthrough to a warm block, add */ /* an explicit jump instead of fallthrough */ for (basicblock *b = entryblock; b != NULL; b = b->b_next) { @@ -2046,7 +2161,10 @@ push_cold_blocks_to_end(cfg_builder *g) { if (explicit_jump == NULL) { return ERROR; } - basicblock_addop(explicit_jump, JUMP, b->b_next->b_label.id, NO_LOCATION); + if (!IS_LABEL(b->b_next->b_label)) { + b->b_next->b_label.id = next_lbl++; + } + basicblock_addop(explicit_jump, JUMP_NO_INTERRUPT, b->b_next->b_label.id, NO_LOCATION); explicit_jump->b_cold = 1; explicit_jump->b_next = b->b_next; b->b_next = explicit_jump; @@ -2103,22 +2221,21 @@ push_cold_blocks_to_end(cfg_builder *g) { return SUCCESS; } -void -_PyCfg_ConvertPseudoOps(basicblock *entryblock) +static void +convert_pseudo_ops(basicblock *entryblock) { for (basicblock *b = entryblock; b != NULL; b = b->b_next) { for (int i = 0; i < b->b_iused; i++) { cfg_instr *instr = &b->b_instr[i]; if (is_block_push(instr) || instr->i_opcode == POP_BLOCK) { - assert(SAME_OPCODE_METADATA(instr->i_opcode, NOP)); INSTR_SET_OP0(instr, NOP); } else if (instr->i_opcode == LOAD_CLOSURE) { - assert(SAME_OPCODE_METADATA(LOAD_CLOSURE, LOAD_FAST)); + assert(is_pseudo_target(LOAD_CLOSURE, LOAD_FAST)); instr->i_opcode = LOAD_FAST; } else if (instr->i_opcode == STORE_FAST_MAYBE_NULL) { - assert(SAME_OPCODE_METADATA(STORE_FAST_MAYBE_NULL, STORE_FAST)); + assert(is_pseudo_target(STORE_FAST_MAYBE_NULL, STORE_FAST)); instr->i_opcode = STORE_FAST; } } @@ -2141,6 +2258,7 @@ is_exit_without_lineno(basicblock *b) { return true; } + /* PEP 626 mandates that the f_lineno of a frame is correct * after a frame terminates. It would be prohibitively expensive * to continuously update the f_lineno field at runtime, @@ -2153,15 +2271,18 @@ is_exit_without_lineno(basicblock *b) { static int duplicate_exits_without_lineno(cfg_builder *g) { - assert(no_empty_basic_blocks(g)); + int next_lbl = get_max_label(g->g_entryblock) + 1; + /* Copy all exit blocks without line number that are targets of a jump. */ basicblock *entryblock = g->g_entryblock; for (basicblock *b = entryblock; b != NULL; b = b->b_next) { cfg_instr *last = basicblock_last_instr(b); - assert(last != NULL); + if (last == NULL) { + continue; + } if (is_jump(last)) { - basicblock *target = last->i_target; + basicblock *target = next_nonempty_block(last->i_target); if (is_exit_without_lineno(target) && target->b_predecessors > 1) { basicblock *new_target = copy_basicblock(g, target); if (new_target == NULL) { @@ -2172,6 +2293,7 @@ duplicate_exits_without_lineno(cfg_builder *g) target->b_predecessors--; new_target->b_predecessors = 1; new_target->b_next = target->b_next; + new_target->b_label.id = next_lbl++; target->b_next = new_target; } } @@ -2217,9 +2339,10 @@ propagate_line_numbers(basicblock *entryblock) { } } if (BB_HAS_FALLTHROUGH(b) && b->b_next->b_predecessors == 1) { - assert(b->b_next->b_iused); - if (b->b_next->b_instr[0].i_loc.lineno < 0) { - b->b_next->b_instr[0].i_loc = prev_location; + if (b->b_next->b_iused > 0) { + if (b->b_next->b_instr[0].i_loc.lineno < 0) { + b->b_next->b_instr[0].i_loc = prev_location; + } } } if (is_jump(last)) { @@ -2293,3 +2416,285 @@ _PyCfg_OptimizeCodeUnit(cfg_builder *g, PyObject *consts, PyObject *const_cache, RETURN_IF_ERROR(resolve_line_numbers(g, firstlineno)); return SUCCESS; } + +static int * +build_cellfixedoffsets(_PyCompile_CodeUnitMetadata *umd) +{ + int nlocals = (int)PyDict_GET_SIZE(umd->u_varnames); + int ncellvars = (int)PyDict_GET_SIZE(umd->u_cellvars); + int nfreevars = (int)PyDict_GET_SIZE(umd->u_freevars); + + int noffsets = ncellvars + nfreevars; + int *fixed = PyMem_New(int, noffsets); + if (fixed == NULL) { + PyErr_NoMemory(); + return NULL; + } + for (int i = 0; i < noffsets; i++) { + fixed[i] = nlocals + i; + } + + PyObject *varname, *cellindex; + Py_ssize_t pos = 0; + while (PyDict_Next(umd->u_cellvars, &pos, &varname, &cellindex)) { + PyObject *varindex; + if (PyDict_GetItemRef(umd->u_varnames, varname, &varindex) < 0) { + goto error; + } + if (varindex == NULL) { + continue; + } + + int argoffset = PyLong_AsInt(varindex); + Py_DECREF(varindex); + if (argoffset == -1 && PyErr_Occurred()) { + goto error; + } + + int oldindex = PyLong_AsInt(cellindex); + if (oldindex == -1 && PyErr_Occurred()) { + goto error; + } + fixed[oldindex] = argoffset; + } + return fixed; + +error: + PyMem_Free(fixed); + return NULL; +} + +#define IS_GENERATOR(CF) \ + ((CF) & (CO_GENERATOR | CO_COROUTINE | CO_ASYNC_GENERATOR)) + +static int +insert_prefix_instructions(_PyCompile_CodeUnitMetadata *umd, basicblock *entryblock, + int *fixed, int nfreevars, int code_flags) +{ + assert(umd->u_firstlineno > 0); + + /* Add the generator prefix instructions. */ + if (IS_GENERATOR(code_flags)) { + /* Note that RETURN_GENERATOR + POP_TOP have a net stack effect + * of 0. This is because RETURN_GENERATOR pushes an element + * with _PyFrame_StackPush before switching stacks. + */ + + location loc = LOCATION(umd->u_firstlineno, umd->u_firstlineno, -1, -1); + cfg_instr make_gen = { + .i_opcode = RETURN_GENERATOR, + .i_oparg = 0, + .i_loc = loc, + .i_target = NULL, + }; + RETURN_IF_ERROR(basicblock_insert_instruction(entryblock, 0, &make_gen)); + cfg_instr pop_top = { + .i_opcode = POP_TOP, + .i_oparg = 0, + .i_loc = loc, + .i_target = NULL, + }; + RETURN_IF_ERROR(basicblock_insert_instruction(entryblock, 1, &pop_top)); + } + + /* Set up cells for any variable that escapes, to be put in a closure. */ + const int ncellvars = (int)PyDict_GET_SIZE(umd->u_cellvars); + if (ncellvars) { + // umd->u_cellvars has the cells out of order so we sort them + // before adding the MAKE_CELL instructions. Note that we + // adjust for arg cells, which come first. + const int nvars = ncellvars + (int)PyDict_GET_SIZE(umd->u_varnames); + int *sorted = PyMem_RawCalloc(nvars, sizeof(int)); + if (sorted == NULL) { + PyErr_NoMemory(); + return ERROR; + } + for (int i = 0; i < ncellvars; i++) { + sorted[fixed[i]] = i + 1; + } + for (int i = 0, ncellsused = 0; ncellsused < ncellvars; i++) { + int oldindex = sorted[i] - 1; + if (oldindex == -1) { + continue; + } + cfg_instr make_cell = { + .i_opcode = MAKE_CELL, + // This will get fixed in offset_derefs(). + .i_oparg = oldindex, + .i_loc = NO_LOCATION, + .i_target = NULL, + }; + if (basicblock_insert_instruction(entryblock, ncellsused, &make_cell) < 0) { + PyMem_RawFree(sorted); + return ERROR; + } + ncellsused += 1; + } + PyMem_RawFree(sorted); + } + + if (nfreevars) { + cfg_instr copy_frees = { + .i_opcode = COPY_FREE_VARS, + .i_oparg = nfreevars, + .i_loc = NO_LOCATION, + .i_target = NULL, + }; + RETURN_IF_ERROR(basicblock_insert_instruction(entryblock, 0, ©_frees)); + } + + return SUCCESS; +} + +static int +fix_cell_offsets(_PyCompile_CodeUnitMetadata *umd, basicblock *entryblock, int *fixedmap) +{ + int nlocals = (int)PyDict_GET_SIZE(umd->u_varnames); + int ncellvars = (int)PyDict_GET_SIZE(umd->u_cellvars); + int nfreevars = (int)PyDict_GET_SIZE(umd->u_freevars); + int noffsets = ncellvars + nfreevars; + + // First deal with duplicates (arg cells). + int numdropped = 0; + for (int i = 0; i < noffsets ; i++) { + if (fixedmap[i] == i + nlocals) { + fixedmap[i] -= numdropped; + } + else { + // It was a duplicate (cell/arg). + numdropped += 1; + } + } + + // Then update offsets, either relative to locals or by cell2arg. + for (basicblock *b = entryblock; b != NULL; b = b->b_next) { + for (int i = 0; i < b->b_iused; i++) { + cfg_instr *inst = &b->b_instr[i]; + // This is called before extended args are generated. + assert(inst->i_opcode != EXTENDED_ARG); + int oldoffset = inst->i_oparg; + switch(inst->i_opcode) { + case MAKE_CELL: + case LOAD_CLOSURE: + case LOAD_DEREF: + case STORE_DEREF: + case DELETE_DEREF: + case LOAD_FROM_DICT_OR_DEREF: + assert(oldoffset >= 0); + assert(oldoffset < noffsets); + assert(fixedmap[oldoffset] >= 0); + inst->i_oparg = fixedmap[oldoffset]; + } + } + } + + return numdropped; +} + +static int +prepare_localsplus(_PyCompile_CodeUnitMetadata *umd, cfg_builder *g, int code_flags) +{ + assert(PyDict_GET_SIZE(umd->u_varnames) < INT_MAX); + assert(PyDict_GET_SIZE(umd->u_cellvars) < INT_MAX); + assert(PyDict_GET_SIZE(umd->u_freevars) < INT_MAX); + int nlocals = (int)PyDict_GET_SIZE(umd->u_varnames); + int ncellvars = (int)PyDict_GET_SIZE(umd->u_cellvars); + int nfreevars = (int)PyDict_GET_SIZE(umd->u_freevars); + assert(INT_MAX - nlocals - ncellvars > 0); + assert(INT_MAX - nlocals - ncellvars - nfreevars > 0); + int nlocalsplus = nlocals + ncellvars + nfreevars; + int* cellfixedoffsets = build_cellfixedoffsets(umd); + if (cellfixedoffsets == NULL) { + return ERROR; + } + + // This must be called before fix_cell_offsets(). + if (insert_prefix_instructions(umd, g->g_entryblock, cellfixedoffsets, nfreevars, code_flags)) { + PyMem_Free(cellfixedoffsets); + return ERROR; + } + + int numdropped = fix_cell_offsets(umd, g->g_entryblock, cellfixedoffsets); + PyMem_Free(cellfixedoffsets); // At this point we're done with it. + cellfixedoffsets = NULL; + if (numdropped < 0) { + return ERROR; + } + + nlocalsplus -= numdropped; + return nlocalsplus; +} + +int +_PyCfg_ToInstructionSequence(cfg_builder *g, _PyCompile_InstructionSequence *seq) +{ + int lbl = 0; + for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) { + b->b_label = (jump_target_label){lbl}; + lbl += b->b_iused; + } + for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) { + RETURN_IF_ERROR(_PyCompile_InstructionSequence_UseLabel(seq, b->b_label.id)); + for (int i = 0; i < b->b_iused; i++) { + cfg_instr *instr = &b->b_instr[i]; + if (OPCODE_HAS_JUMP(instr->i_opcode)) { + instr->i_oparg = instr->i_target->b_label.id; + } + RETURN_IF_ERROR( + _PyCompile_InstructionSequence_Addop( + seq, instr->i_opcode, instr->i_oparg, instr->i_loc)); + + _PyCompile_ExceptHandlerInfo *hi = &seq->s_instrs[seq->s_used-1].i_except_handler_info; + if (instr->i_except != NULL) { + hi->h_label = instr->i_except->b_label.id; + hi->h_startdepth = instr->i_except->b_startdepth; + hi->h_preserve_lasti = instr->i_except->b_preserve_lasti; + } + else { + hi->h_label = -1; + } + } + } + return SUCCESS; +} + + +int +_PyCfg_OptimizedCfgToInstructionSequence(cfg_builder *g, + _PyCompile_CodeUnitMetadata *umd, int code_flags, + int *stackdepth, int *nlocalsplus, + _PyCompile_InstructionSequence *seq) +{ + *stackdepth = calculate_stackdepth(g); + if (*stackdepth < 0) { + return ERROR; + } + + /* prepare_localsplus adds instructions for generators that push + * and pop an item on the stack. This assertion makes sure there + * is space on the stack for that. + * It should always be true, because a generator must have at + * least one expression or call to INTRINSIC_STOPITERATION_ERROR, + * which requires stackspace. + */ + assert(!(IS_GENERATOR(code_flags) && *stackdepth == 0)); + + *nlocalsplus = prepare_localsplus(umd, g, code_flags); + if (*nlocalsplus < 0) { + return ERROR; + } + + convert_pseudo_ops(g->g_entryblock); + + /* Order of basic blocks must have been determined by now */ + + RETURN_IF_ERROR(normalize_jumps(g)); + assert(no_redundant_jumps(g)); + + /* Can't modify the bytecode after computing jump offsets. */ + if (_PyCfg_ToInstructionSequence(g, seq) < 0) { + return ERROR; + } + + return SUCCESS; +} diff --git a/Python/frame.c b/Python/frame.c index 581e4f95710fe2..2865b2eab603c2 100644 --- a/Python/frame.c +++ b/Python/frame.c @@ -90,7 +90,7 @@ take_ownership(PyFrameObject *f, _PyInterpreterFrame *frame) // This may be a newly-created generator or coroutine frame. Since it's // dead anyways, just pretend that the first RESUME ran: PyCodeObject *code = _PyFrame_GetCode(frame); - frame->prev_instr = _PyCode_CODE(code) + code->_co_firsttraceable; + frame->instr_ptr = _PyCode_CODE(code) + code->_co_firsttraceable + 1; } assert(!_PyFrame_IsIncomplete(frame)); assert(f->f_back == NULL); @@ -124,7 +124,7 @@ _PyFrame_ClearExceptCode(_PyInterpreterFrame *frame) _PyFrame_GetGenerator(frame)->gi_frame_state == FRAME_CLEARED); // GH-99729: Clearing this frame can expose the stack (via finalizers). It's // crucial that this frame has been unlinked, and is no longer visible: - assert(_PyThreadState_GET()->cframe->current_frame != frame); + assert(_PyThreadState_GET()->current_frame != frame); if (frame->frame_obj) { PyFrameObject *f = frame->frame_obj; frame->frame_obj = NULL; @@ -167,10 +167,10 @@ PyUnstable_InterpreterFrame_GetLine(_PyInterpreterFrame *frame) return PyCode_Addr2Line(_PyFrame_GetCode(frame), addr); } -const PyTypeObject *const PyUnstable_ExecutableKinds[PY_EXECUTABLE_KINDS+1] = { - [PY_EXECUTABLE_KIND_SKIP] = &_PyNone_Type, - [PY_EXECUTABLE_KIND_PY_FUNCTION] = &PyCode_Type, - [PY_EXECUTABLE_KIND_BUILTIN_FUNCTION] = &PyMethod_Type, - [PY_EXECUTABLE_KIND_METHOD_DESCRIPTOR] = &PyMethodDescr_Type, - [PY_EXECUTABLE_KINDS] = NULL, +const PyTypeObject *const PyUnstable_ExecutableKinds[PyUnstable_EXECUTABLE_KINDS+1] = { + [PyUnstable_EXECUTABLE_KIND_SKIP] = &_PyNone_Type, + [PyUnstable_EXECUTABLE_KIND_PY_FUNCTION] = &PyCode_Type, + [PyUnstable_EXECUTABLE_KIND_BUILTIN_FUNCTION] = &PyMethod_Type, + [PyUnstable_EXECUTABLE_KIND_METHOD_DESCRIPTOR] = &PyMethodDescr_Type, + [PyUnstable_EXECUTABLE_KINDS] = NULL, }; diff --git a/Python/frozen.c b/Python/frozen.c index 6b977710e6e342..77f51a7f750965 100644 --- a/Python/frozen.c +++ b/Python/frozen.c @@ -80,7 +80,6 @@ extern PyObject *_Py_get__sitebuiltins_toplevel(void); extern PyObject *_Py_get_genericpath_toplevel(void); extern PyObject *_Py_get_ntpath_toplevel(void); extern PyObject *_Py_get_posixpath_toplevel(void); -extern PyObject *_Py_get_posixpath_toplevel(void); extern PyObject *_Py_get_os_toplevel(void); extern PyObject *_Py_get_site_toplevel(void); extern PyObject *_Py_get_stat_toplevel(void); @@ -88,59 +87,54 @@ extern PyObject *_Py_get_importlib_util_toplevel(void); extern PyObject *_Py_get_importlib_machinery_toplevel(void); extern PyObject *_Py_get_runpy_toplevel(void); extern PyObject *_Py_get___hello___toplevel(void); -extern PyObject *_Py_get___hello___toplevel(void); -extern PyObject *_Py_get___hello___toplevel(void); -extern PyObject *_Py_get___hello___toplevel(void); -extern PyObject *_Py_get___phello___toplevel(void); extern PyObject *_Py_get___phello___toplevel(void); extern PyObject *_Py_get___phello___ham_toplevel(void); -extern PyObject *_Py_get___phello___ham_toplevel(void); extern PyObject *_Py_get___phello___ham_eggs_toplevel(void); extern PyObject *_Py_get___phello___spam_toplevel(void); extern PyObject *_Py_get_frozen_only_toplevel(void); /* End extern declarations */ static const struct _frozen bootstrap_modules[] = { - {"_frozen_importlib", _Py_M__importlib__bootstrap, (int)sizeof(_Py_M__importlib__bootstrap), false, GET_CODE(importlib__bootstrap)}, - {"_frozen_importlib_external", _Py_M__importlib__bootstrap_external, (int)sizeof(_Py_M__importlib__bootstrap_external), false, GET_CODE(importlib__bootstrap_external)}, - {"zipimport", _Py_M__zipimport, (int)sizeof(_Py_M__zipimport), false, GET_CODE(zipimport)}, + {"_frozen_importlib", _Py_M__importlib__bootstrap, (int)sizeof(_Py_M__importlib__bootstrap), false}, + {"_frozen_importlib_external", _Py_M__importlib__bootstrap_external, (int)sizeof(_Py_M__importlib__bootstrap_external), false}, + {"zipimport", _Py_M__zipimport, (int)sizeof(_Py_M__zipimport), false}, {0, 0, 0} /* bootstrap sentinel */ }; static const struct _frozen stdlib_modules[] = { /* stdlib - startup, without site (python -S) */ - {"abc", _Py_M__abc, (int)sizeof(_Py_M__abc), false, GET_CODE(abc)}, - {"codecs", _Py_M__codecs, (int)sizeof(_Py_M__codecs), false, GET_CODE(codecs)}, - {"io", _Py_M__io, (int)sizeof(_Py_M__io), false, GET_CODE(io)}, + {"abc", _Py_M__abc, (int)sizeof(_Py_M__abc), false}, + {"codecs", _Py_M__codecs, (int)sizeof(_Py_M__codecs), false}, + {"io", _Py_M__io, (int)sizeof(_Py_M__io), false}, /* stdlib - startup, with site */ - {"_collections_abc", _Py_M___collections_abc, (int)sizeof(_Py_M___collections_abc), false, GET_CODE(_collections_abc)}, - {"_sitebuiltins", _Py_M___sitebuiltins, (int)sizeof(_Py_M___sitebuiltins), false, GET_CODE(_sitebuiltins)}, - {"genericpath", _Py_M__genericpath, (int)sizeof(_Py_M__genericpath), false, GET_CODE(genericpath)}, - {"ntpath", _Py_M__ntpath, (int)sizeof(_Py_M__ntpath), false, GET_CODE(ntpath)}, - {"posixpath", _Py_M__posixpath, (int)sizeof(_Py_M__posixpath), false, GET_CODE(posixpath)}, - {"os.path", _Py_M__posixpath, (int)sizeof(_Py_M__posixpath), false, GET_CODE(posixpath)}, - {"os", _Py_M__os, (int)sizeof(_Py_M__os), false, GET_CODE(os)}, - {"site", _Py_M__site, (int)sizeof(_Py_M__site), false, GET_CODE(site)}, - {"stat", _Py_M__stat, (int)sizeof(_Py_M__stat), false, GET_CODE(stat)}, + {"_collections_abc", _Py_M___collections_abc, (int)sizeof(_Py_M___collections_abc), false}, + {"_sitebuiltins", _Py_M___sitebuiltins, (int)sizeof(_Py_M___sitebuiltins), false}, + {"genericpath", _Py_M__genericpath, (int)sizeof(_Py_M__genericpath), false}, + {"ntpath", _Py_M__ntpath, (int)sizeof(_Py_M__ntpath), false}, + {"posixpath", _Py_M__posixpath, (int)sizeof(_Py_M__posixpath), false}, + {"os.path", _Py_M__posixpath, (int)sizeof(_Py_M__posixpath), false}, + {"os", _Py_M__os, (int)sizeof(_Py_M__os), false}, + {"site", _Py_M__site, (int)sizeof(_Py_M__site), false}, + {"stat", _Py_M__stat, (int)sizeof(_Py_M__stat), false}, /* runpy - run module with -m */ - {"importlib.util", _Py_M__importlib_util, (int)sizeof(_Py_M__importlib_util), false, GET_CODE(importlib_util)}, - {"importlib.machinery", _Py_M__importlib_machinery, (int)sizeof(_Py_M__importlib_machinery), false, GET_CODE(importlib_machinery)}, - {"runpy", _Py_M__runpy, (int)sizeof(_Py_M__runpy), false, GET_CODE(runpy)}, + {"importlib.util", _Py_M__importlib_util, (int)sizeof(_Py_M__importlib_util), false}, + {"importlib.machinery", _Py_M__importlib_machinery, (int)sizeof(_Py_M__importlib_machinery), false}, + {"runpy", _Py_M__runpy, (int)sizeof(_Py_M__runpy), false}, {0, 0, 0} /* stdlib sentinel */ }; static const struct _frozen test_modules[] = { - {"__hello__", _Py_M____hello__, (int)sizeof(_Py_M____hello__), false, GET_CODE(__hello__)}, - {"__hello_alias__", _Py_M____hello__, (int)sizeof(_Py_M____hello__), false, GET_CODE(__hello__)}, - {"__phello_alias__", _Py_M____hello__, (int)sizeof(_Py_M____hello__), true, GET_CODE(__hello__)}, - {"__phello_alias__.spam", _Py_M____hello__, (int)sizeof(_Py_M____hello__), false, GET_CODE(__hello__)}, - {"__phello__", _Py_M____phello__, (int)sizeof(_Py_M____phello__), true, GET_CODE(__phello__)}, - {"__phello__.__init__", _Py_M____phello__, (int)sizeof(_Py_M____phello__), false, GET_CODE(__phello__)}, - {"__phello__.ham", _Py_M____phello___ham, (int)sizeof(_Py_M____phello___ham), true, GET_CODE(__phello___ham)}, - {"__phello__.ham.__init__", _Py_M____phello___ham, (int)sizeof(_Py_M____phello___ham), false, GET_CODE(__phello___ham)}, - {"__phello__.ham.eggs", _Py_M____phello___ham_eggs, (int)sizeof(_Py_M____phello___ham_eggs), false, GET_CODE(__phello___ham_eggs)}, - {"__phello__.spam", _Py_M____phello___spam, (int)sizeof(_Py_M____phello___spam), false, GET_CODE(__phello___spam)}, - {"__hello_only__", _Py_M__frozen_only, (int)sizeof(_Py_M__frozen_only), false, GET_CODE(frozen_only)}, + {"__hello__", _Py_M____hello__, (int)sizeof(_Py_M____hello__), false}, + {"__hello_alias__", _Py_M____hello__, (int)sizeof(_Py_M____hello__), false}, + {"__phello_alias__", _Py_M____hello__, (int)sizeof(_Py_M____hello__), true}, + {"__phello_alias__.spam", _Py_M____hello__, (int)sizeof(_Py_M____hello__), false}, + {"__phello__", _Py_M____phello__, (int)sizeof(_Py_M____phello__), true}, + {"__phello__.__init__", _Py_M____phello__, (int)sizeof(_Py_M____phello__), false}, + {"__phello__.ham", _Py_M____phello___ham, (int)sizeof(_Py_M____phello___ham), true}, + {"__phello__.ham.__init__", _Py_M____phello___ham, (int)sizeof(_Py_M____phello___ham), false}, + {"__phello__.ham.eggs", _Py_M____phello___ham_eggs, (int)sizeof(_Py_M____phello___ham_eggs), false}, + {"__phello__.spam", _Py_M____phello___spam, (int)sizeof(_Py_M____phello___spam), false}, + {"__hello_only__", _Py_M__frozen_only, (int)sizeof(_Py_M__frozen_only), false}, {0, 0, 0} /* test sentinel */ }; const struct _frozen *_PyImport_FrozenBootstrap = bootstrap_modules; diff --git a/Python/frozenmain.c b/Python/frozenmain.c index 767f9804903a9e..3ce9476c9ad46c 100644 --- a/Python/frozenmain.c +++ b/Python/frozenmain.c @@ -3,7 +3,11 @@ #include "Python.h" #include "pycore_pystate.h" // _Py_GetConfig() #include "pycore_runtime.h" // _PyRuntime_Initialize() -#include + +#ifdef HAVE_UNISTD_H +# include // isatty() +#endif + #ifdef MS_WINDOWS extern void PyWinFreeze_ExeInit(void); diff --git a/Python/gc.c b/Python/gc.c new file mode 100644 index 00000000000000..9f9a755f6ac95e --- /dev/null +++ b/Python/gc.c @@ -0,0 +1,1943 @@ +// This implements the reference cycle garbage collector. +// The Python module inteface to the collector is in gcmodule.c. +// See https://devguide.python.org/internals/garbage-collector/ + +#include "Python.h" +#include "pycore_ceval.h" // _Py_set_eval_breaker_bit() +#include "pycore_context.h" +#include "pycore_dict.h" // _PyDict_MaybeUntrack() +#include "pycore_initconfig.h" +#include "pycore_interp.h" // PyInterpreterState.gc +#include "pycore_object.h" +#include "pycore_pyerrors.h" +#include "pycore_pystate.h" // _PyThreadState_GET() +#include "pycore_weakref.h" // _PyWeakref_ClearRef() +#include "pydtrace.h" + +typedef struct _gc_runtime_state GCState; + +#ifdef Py_DEBUG +# define GC_DEBUG +#endif + +#define GC_NEXT _PyGCHead_NEXT +#define GC_PREV _PyGCHead_PREV + +// update_refs() set this bit for all objects in current generation. +// subtract_refs() and move_unreachable() uses this to distinguish +// visited object is in GCing or not. +// +// move_unreachable() removes this flag from reachable objects. +// Only unreachable objects have this flag. +// +// No objects in interpreter have this flag after GC ends. +#define PREV_MASK_COLLECTING _PyGC_PREV_MASK_COLLECTING + +// Lowest bit of _gc_next is used for UNREACHABLE flag. +// +// This flag represents the object is in unreachable list in move_unreachable() +// +// Although this flag is used only in move_unreachable(), move_unreachable() +// doesn't clear this flag to skip unnecessary iteration. +// move_legacy_finalizers() removes this flag instead. +// Between them, unreachable list is not normal list and we can not use +// most gc_list_* functions for it. +#define NEXT_MASK_UNREACHABLE (1) + +#define AS_GC(op) _Py_AS_GC(op) +#define FROM_GC(gc) _Py_FROM_GC(gc) + +// Automatically choose the generation that needs collecting. +#define GENERATION_AUTO (-1) + +static inline int +gc_is_collecting(PyGC_Head *g) +{ + return (g->_gc_prev & PREV_MASK_COLLECTING) != 0; +} + +static inline void +gc_clear_collecting(PyGC_Head *g) +{ + g->_gc_prev &= ~PREV_MASK_COLLECTING; +} + +static inline Py_ssize_t +gc_get_refs(PyGC_Head *g) +{ + return (Py_ssize_t)(g->_gc_prev >> _PyGC_PREV_SHIFT); +} + +static inline void +gc_set_refs(PyGC_Head *g, Py_ssize_t refs) +{ + g->_gc_prev = (g->_gc_prev & ~_PyGC_PREV_MASK) + | ((uintptr_t)(refs) << _PyGC_PREV_SHIFT); +} + +static inline void +gc_reset_refs(PyGC_Head *g, Py_ssize_t refs) +{ + g->_gc_prev = (g->_gc_prev & _PyGC_PREV_MASK_FINALIZED) + | PREV_MASK_COLLECTING + | ((uintptr_t)(refs) << _PyGC_PREV_SHIFT); +} + +static inline void +gc_decref(PyGC_Head *g) +{ + _PyObject_ASSERT_WITH_MSG(FROM_GC(g), + gc_get_refs(g) > 0, + "refcount is too small"); + g->_gc_prev -= 1 << _PyGC_PREV_SHIFT; +} + + +#define GEN_HEAD(gcstate, n) (&(gcstate)->generations[n].head) + + +static GCState * +get_gc_state(void) +{ + PyInterpreterState *interp = _PyInterpreterState_GET(); + return &interp->gc; +} + + +void +_PyGC_InitState(GCState *gcstate) +{ +#define INIT_HEAD(GEN) \ + do { \ + GEN.head._gc_next = (uintptr_t)&GEN.head; \ + GEN.head._gc_prev = (uintptr_t)&GEN.head; \ + } while (0) + + for (int i = 0; i < NUM_GENERATIONS; i++) { + assert(gcstate->generations[i].count == 0); + INIT_HEAD(gcstate->generations[i]); + }; + gcstate->generation0 = GEN_HEAD(gcstate, 0); + INIT_HEAD(gcstate->permanent_generation); + +#undef INIT_HEAD +} + + +PyStatus +_PyGC_Init(PyInterpreterState *interp) +{ + GCState *gcstate = &interp->gc; + + gcstate->garbage = PyList_New(0); + if (gcstate->garbage == NULL) { + return _PyStatus_NO_MEMORY(); + } + + gcstate->callbacks = PyList_New(0); + if (gcstate->callbacks == NULL) { + return _PyStatus_NO_MEMORY(); + } + + return _PyStatus_OK(); +} + + +/* +_gc_prev values +--------------- + +Between collections, _gc_prev is used for doubly linked list. + +Lowest two bits of _gc_prev are used for flags. +PREV_MASK_COLLECTING is used only while collecting and cleared before GC ends +or _PyObject_GC_UNTRACK() is called. + +During a collection, _gc_prev is temporary used for gc_refs, and the gc list +is singly linked until _gc_prev is restored. + +gc_refs + At the start of a collection, update_refs() copies the true refcount + to gc_refs, for each object in the generation being collected. + subtract_refs() then adjusts gc_refs so that it equals the number of + times an object is referenced directly from outside the generation + being collected. + +PREV_MASK_COLLECTING + Objects in generation being collected are marked PREV_MASK_COLLECTING in + update_refs(). + + +_gc_next values +--------------- + +_gc_next takes these values: + +0 + The object is not tracked + +!= 0 + Pointer to the next object in the GC list. + Additionally, lowest bit is used temporary for + NEXT_MASK_UNREACHABLE flag described below. + +NEXT_MASK_UNREACHABLE + move_unreachable() then moves objects not reachable (whether directly or + indirectly) from outside the generation into an "unreachable" set and + set this flag. + + Objects that are found to be reachable have gc_refs set to 1. + When this flag is set for the reachable object, the object must be in + "unreachable" set. + The flag is unset and the object is moved back to "reachable" set. + + move_legacy_finalizers() will remove this flag from "unreachable" set. +*/ + +/*** list functions ***/ + +static inline void +gc_list_init(PyGC_Head *list) +{ + // List header must not have flags. + // We can assign pointer by simple cast. + list->_gc_prev = (uintptr_t)list; + list->_gc_next = (uintptr_t)list; +} + +static inline int +gc_list_is_empty(PyGC_Head *list) +{ + return (list->_gc_next == (uintptr_t)list); +} + +/* Append `node` to `list`. */ +static inline void +gc_list_append(PyGC_Head *node, PyGC_Head *list) +{ + PyGC_Head *last = (PyGC_Head *)list->_gc_prev; + + // last <-> node + _PyGCHead_SET_PREV(node, last); + _PyGCHead_SET_NEXT(last, node); + + // node <-> list + _PyGCHead_SET_NEXT(node, list); + list->_gc_prev = (uintptr_t)node; +} + +/* Remove `node` from the gc list it's currently in. */ +static inline void +gc_list_remove(PyGC_Head *node) +{ + PyGC_Head *prev = GC_PREV(node); + PyGC_Head *next = GC_NEXT(node); + + _PyGCHead_SET_NEXT(prev, next); + _PyGCHead_SET_PREV(next, prev); + + node->_gc_next = 0; /* object is not currently tracked */ +} + +/* Move `node` from the gc list it's currently in (which is not explicitly + * named here) to the end of `list`. This is semantically the same as + * gc_list_remove(node) followed by gc_list_append(node, list). + */ +static void +gc_list_move(PyGC_Head *node, PyGC_Head *list) +{ + /* Unlink from current list. */ + PyGC_Head *from_prev = GC_PREV(node); + PyGC_Head *from_next = GC_NEXT(node); + _PyGCHead_SET_NEXT(from_prev, from_next); + _PyGCHead_SET_PREV(from_next, from_prev); + + /* Relink at end of new list. */ + // list must not have flags. So we can skip macros. + PyGC_Head *to_prev = (PyGC_Head*)list->_gc_prev; + _PyGCHead_SET_PREV(node, to_prev); + _PyGCHead_SET_NEXT(to_prev, node); + list->_gc_prev = (uintptr_t)node; + _PyGCHead_SET_NEXT(node, list); +} + +/* append list `from` onto list `to`; `from` becomes an empty list */ +static void +gc_list_merge(PyGC_Head *from, PyGC_Head *to) +{ + assert(from != to); + if (!gc_list_is_empty(from)) { + PyGC_Head *to_tail = GC_PREV(to); + PyGC_Head *from_head = GC_NEXT(from); + PyGC_Head *from_tail = GC_PREV(from); + assert(from_head != from); + assert(from_tail != from); + + _PyGCHead_SET_NEXT(to_tail, from_head); + _PyGCHead_SET_PREV(from_head, to_tail); + + _PyGCHead_SET_NEXT(from_tail, to); + _PyGCHead_SET_PREV(to, from_tail); + } + gc_list_init(from); +} + +static Py_ssize_t +gc_list_size(PyGC_Head *list) +{ + PyGC_Head *gc; + Py_ssize_t n = 0; + for (gc = GC_NEXT(list); gc != list; gc = GC_NEXT(gc)) { + n++; + } + return n; +} + +/* Walk the list and mark all objects as non-collecting */ +static inline void +gc_list_clear_collecting(PyGC_Head *collectable) +{ + PyGC_Head *gc; + for (gc = GC_NEXT(collectable); gc != collectable; gc = GC_NEXT(gc)) { + gc_clear_collecting(gc); + } +} + +/* Append objects in a GC list to a Python list. + * Return 0 if all OK, < 0 if error (out of memory for list) + */ +static int +append_objects(PyObject *py_list, PyGC_Head *gc_list) +{ + PyGC_Head *gc; + for (gc = GC_NEXT(gc_list); gc != gc_list; gc = GC_NEXT(gc)) { + PyObject *op = FROM_GC(gc); + if (op != py_list) { + if (PyList_Append(py_list, op)) { + return -1; /* exception */ + } + } + } + return 0; +} + +// Constants for validate_list's flags argument. +enum flagstates {collecting_clear_unreachable_clear, + collecting_clear_unreachable_set, + collecting_set_unreachable_clear, + collecting_set_unreachable_set}; + +#ifdef GC_DEBUG +// validate_list checks list consistency. And it works as document +// describing when flags are expected to be set / unset. +// `head` must be a doubly-linked gc list, although it's fine (expected!) if +// the prev and next pointers are "polluted" with flags. +// What's checked: +// - The `head` pointers are not polluted. +// - The objects' PREV_MASK_COLLECTING and NEXT_MASK_UNREACHABLE flags are all +// `set or clear, as specified by the 'flags' argument. +// - The prev and next pointers are mutually consistent. +static void +validate_list(PyGC_Head *head, enum flagstates flags) +{ + assert((head->_gc_prev & PREV_MASK_COLLECTING) == 0); + assert((head->_gc_next & NEXT_MASK_UNREACHABLE) == 0); + uintptr_t prev_value = 0, next_value = 0; + switch (flags) { + case collecting_clear_unreachable_clear: + break; + case collecting_set_unreachable_clear: + prev_value = PREV_MASK_COLLECTING; + break; + case collecting_clear_unreachable_set: + next_value = NEXT_MASK_UNREACHABLE; + break; + case collecting_set_unreachable_set: + prev_value = PREV_MASK_COLLECTING; + next_value = NEXT_MASK_UNREACHABLE; + break; + default: + assert(! "bad internal flags argument"); + } + PyGC_Head *prev = head; + PyGC_Head *gc = GC_NEXT(head); + while (gc != head) { + PyGC_Head *trueprev = GC_PREV(gc); + PyGC_Head *truenext = (PyGC_Head *)(gc->_gc_next & ~NEXT_MASK_UNREACHABLE); + assert(truenext != NULL); + assert(trueprev == prev); + assert((gc->_gc_prev & PREV_MASK_COLLECTING) == prev_value); + assert((gc->_gc_next & NEXT_MASK_UNREACHABLE) == next_value); + prev = gc; + gc = truenext; + } + assert(prev == GC_PREV(head)); +} +#else +#define validate_list(x, y) do{}while(0) +#endif + +/*** end of list stuff ***/ + + +/* Set all gc_refs = ob_refcnt. After this, gc_refs is > 0 and + * PREV_MASK_COLLECTING bit is set for all objects in containers. + */ +static void +update_refs(PyGC_Head *containers) +{ + PyGC_Head *next; + PyGC_Head *gc = GC_NEXT(containers); + + while (gc != containers) { + next = GC_NEXT(gc); + /* Move any object that might have become immortal to the + * permanent generation as the reference count is not accurately + * reflecting the actual number of live references to this object + */ + if (_Py_IsImmortal(FROM_GC(gc))) { + gc_list_move(gc, &get_gc_state()->permanent_generation.head); + gc = next; + continue; + } + gc_reset_refs(gc, Py_REFCNT(FROM_GC(gc))); + /* Python's cyclic gc should never see an incoming refcount + * of 0: if something decref'ed to 0, it should have been + * deallocated immediately at that time. + * Possible cause (if the assert triggers): a tp_dealloc + * routine left a gc-aware object tracked during its teardown + * phase, and did something-- or allowed something to happen -- + * that called back into Python. gc can trigger then, and may + * see the still-tracked dying object. Before this assert + * was added, such mistakes went on to allow gc to try to + * delete the object again. In a debug build, that caused + * a mysterious segfault, when _Py_ForgetReference tried + * to remove the object from the doubly-linked list of all + * objects a second time. In a release build, an actual + * double deallocation occurred, which leads to corruption + * of the allocator's internal bookkeeping pointers. That's + * so serious that maybe this should be a release-build + * check instead of an assert? + */ + _PyObject_ASSERT(FROM_GC(gc), gc_get_refs(gc) != 0); + gc = next; + } +} + +/* A traversal callback for subtract_refs. */ +static int +visit_decref(PyObject *op, void *parent) +{ + OBJECT_STAT_INC(object_visits); + _PyObject_ASSERT(_PyObject_CAST(parent), !_PyObject_IsFreed(op)); + + if (_PyObject_IS_GC(op)) { + PyGC_Head *gc = AS_GC(op); + /* We're only interested in gc_refs for objects in the + * generation being collected, which can be recognized + * because only they have positive gc_refs. + */ + if (gc_is_collecting(gc)) { + gc_decref(gc); + } + } + return 0; +} + +/* Subtract internal references from gc_refs. After this, gc_refs is >= 0 + * for all objects in containers, and is GC_REACHABLE for all tracked gc + * objects not in containers. The ones with gc_refs > 0 are directly + * reachable from outside containers, and so can't be collected. + */ +static void +subtract_refs(PyGC_Head *containers) +{ + traverseproc traverse; + PyGC_Head *gc = GC_NEXT(containers); + for (; gc != containers; gc = GC_NEXT(gc)) { + PyObject *op = FROM_GC(gc); + traverse = Py_TYPE(op)->tp_traverse; + (void) traverse(op, + visit_decref, + op); + } +} + +/* A traversal callback for move_unreachable. */ +static int +visit_reachable(PyObject *op, void *arg) +{ + PyGC_Head *reachable = arg; + OBJECT_STAT_INC(object_visits); + if (!_PyObject_IS_GC(op)) { + return 0; + } + + PyGC_Head *gc = AS_GC(op); + const Py_ssize_t gc_refs = gc_get_refs(gc); + + // Ignore objects in other generation. + // This also skips objects "to the left" of the current position in + // move_unreachable's scan of the 'young' list - they've already been + // traversed, and no longer have the PREV_MASK_COLLECTING flag. + if (! gc_is_collecting(gc)) { + return 0; + } + // It would be a logic error elsewhere if the collecting flag were set on + // an untracked object. + assert(gc->_gc_next != 0); + + if (gc->_gc_next & NEXT_MASK_UNREACHABLE) { + /* This had gc_refs = 0 when move_unreachable got + * to it, but turns out it's reachable after all. + * Move it back to move_unreachable's 'young' list, + * and move_unreachable will eventually get to it + * again. + */ + // Manually unlink gc from unreachable list because the list functions + // don't work right in the presence of NEXT_MASK_UNREACHABLE flags. + PyGC_Head *prev = GC_PREV(gc); + PyGC_Head *next = (PyGC_Head*)(gc->_gc_next & ~NEXT_MASK_UNREACHABLE); + _PyObject_ASSERT(FROM_GC(prev), + prev->_gc_next & NEXT_MASK_UNREACHABLE); + _PyObject_ASSERT(FROM_GC(next), + next->_gc_next & NEXT_MASK_UNREACHABLE); + prev->_gc_next = gc->_gc_next; // copy NEXT_MASK_UNREACHABLE + _PyGCHead_SET_PREV(next, prev); + + gc_list_append(gc, reachable); + gc_set_refs(gc, 1); + } + else if (gc_refs == 0) { + /* This is in move_unreachable's 'young' list, but + * the traversal hasn't yet gotten to it. All + * we need to do is tell move_unreachable that it's + * reachable. + */ + gc_set_refs(gc, 1); + } + /* Else there's nothing to do. + * If gc_refs > 0, it must be in move_unreachable's 'young' + * list, and move_unreachable will eventually get to it. + */ + else { + _PyObject_ASSERT_WITH_MSG(op, gc_refs > 0, "refcount is too small"); + } + return 0; +} + +/* Move the unreachable objects from young to unreachable. After this, + * all objects in young don't have PREV_MASK_COLLECTING flag and + * unreachable have the flag. + * All objects in young after this are directly or indirectly reachable + * from outside the original young; and all objects in unreachable are + * not. + * + * This function restores _gc_prev pointer. young and unreachable are + * doubly linked list after this function. + * But _gc_next in unreachable list has NEXT_MASK_UNREACHABLE flag. + * So we can not gc_list_* functions for unreachable until we remove the flag. + */ +static void +move_unreachable(PyGC_Head *young, PyGC_Head *unreachable) +{ + // previous elem in the young list, used for restore gc_prev. + PyGC_Head *prev = young; + PyGC_Head *gc = GC_NEXT(young); + + /* Invariants: all objects "to the left" of us in young are reachable + * (directly or indirectly) from outside the young list as it was at entry. + * + * All other objects from the original young "to the left" of us are in + * unreachable now, and have NEXT_MASK_UNREACHABLE. All objects to the + * left of us in 'young' now have been scanned, and no objects here + * or to the right have been scanned yet. + */ + + while (gc != young) { + if (gc_get_refs(gc)) { + /* gc is definitely reachable from outside the + * original 'young'. Mark it as such, and traverse + * its pointers to find any other objects that may + * be directly reachable from it. Note that the + * call to tp_traverse may append objects to young, + * so we have to wait until it returns to determine + * the next object to visit. + */ + PyObject *op = FROM_GC(gc); + traverseproc traverse = Py_TYPE(op)->tp_traverse; + _PyObject_ASSERT_WITH_MSG(op, gc_get_refs(gc) > 0, + "refcount is too small"); + // NOTE: visit_reachable may change gc->_gc_next when + // young->_gc_prev == gc. Don't do gc = GC_NEXT(gc) before! + (void) traverse(op, + visit_reachable, + (void *)young); + // relink gc_prev to prev element. + _PyGCHead_SET_PREV(gc, prev); + // gc is not COLLECTING state after here. + gc_clear_collecting(gc); + prev = gc; + } + else { + /* This *may* be unreachable. To make progress, + * assume it is. gc isn't directly reachable from + * any object we've already traversed, but may be + * reachable from an object we haven't gotten to yet. + * visit_reachable will eventually move gc back into + * young if that's so, and we'll see it again. + */ + // Move gc to unreachable. + // No need to gc->next->prev = prev because it is single linked. + prev->_gc_next = gc->_gc_next; + + // We can't use gc_list_append() here because we use + // NEXT_MASK_UNREACHABLE here. + PyGC_Head *last = GC_PREV(unreachable); + // NOTE: Since all objects in unreachable set has + // NEXT_MASK_UNREACHABLE flag, we set it unconditionally. + // But this may pollute the unreachable list head's 'next' pointer + // too. That's semantically senseless but expedient here - the + // damage is repaired when this function ends. + last->_gc_next = (NEXT_MASK_UNREACHABLE | (uintptr_t)gc); + _PyGCHead_SET_PREV(gc, last); + gc->_gc_next = (NEXT_MASK_UNREACHABLE | (uintptr_t)unreachable); + unreachable->_gc_prev = (uintptr_t)gc; + } + gc = (PyGC_Head*)prev->_gc_next; + } + // young->_gc_prev must be last element remained in the list. + young->_gc_prev = (uintptr_t)prev; + // don't let the pollution of the list head's next pointer leak + unreachable->_gc_next &= ~NEXT_MASK_UNREACHABLE; +} + +static void +untrack_tuples(PyGC_Head *head) +{ + PyGC_Head *next, *gc = GC_NEXT(head); + while (gc != head) { + PyObject *op = FROM_GC(gc); + next = GC_NEXT(gc); + if (PyTuple_CheckExact(op)) { + _PyTuple_MaybeUntrack(op); + } + gc = next; + } +} + +/* Try to untrack all currently tracked dictionaries */ +static void +untrack_dicts(PyGC_Head *head) +{ + PyGC_Head *next, *gc = GC_NEXT(head); + while (gc != head) { + PyObject *op = FROM_GC(gc); + next = GC_NEXT(gc); + if (PyDict_CheckExact(op)) { + _PyDict_MaybeUntrack(op); + } + gc = next; + } +} + +/* Return true if object has a pre-PEP 442 finalization method. */ +static int +has_legacy_finalizer(PyObject *op) +{ + return Py_TYPE(op)->tp_del != NULL; +} + +/* Move the objects in unreachable with tp_del slots into `finalizers`. + * + * This function also removes NEXT_MASK_UNREACHABLE flag + * from _gc_next in unreachable. + */ +static void +move_legacy_finalizers(PyGC_Head *unreachable, PyGC_Head *finalizers) +{ + PyGC_Head *gc, *next; + assert((unreachable->_gc_next & NEXT_MASK_UNREACHABLE) == 0); + + /* March over unreachable. Move objects with finalizers into + * `finalizers`. + */ + for (gc = GC_NEXT(unreachable); gc != unreachable; gc = next) { + PyObject *op = FROM_GC(gc); + + _PyObject_ASSERT(op, gc->_gc_next & NEXT_MASK_UNREACHABLE); + gc->_gc_next &= ~NEXT_MASK_UNREACHABLE; + next = (PyGC_Head*)gc->_gc_next; + + if (has_legacy_finalizer(op)) { + gc_clear_collecting(gc); + gc_list_move(gc, finalizers); + } + } +} + +static inline void +clear_unreachable_mask(PyGC_Head *unreachable) +{ + /* Check that the list head does not have the unreachable bit set */ + assert(((uintptr_t)unreachable & NEXT_MASK_UNREACHABLE) == 0); + + PyGC_Head *gc, *next; + assert((unreachable->_gc_next & NEXT_MASK_UNREACHABLE) == 0); + for (gc = GC_NEXT(unreachable); gc != unreachable; gc = next) { + _PyObject_ASSERT((PyObject*)FROM_GC(gc), gc->_gc_next & NEXT_MASK_UNREACHABLE); + gc->_gc_next &= ~NEXT_MASK_UNREACHABLE; + next = (PyGC_Head*)gc->_gc_next; + } + validate_list(unreachable, collecting_set_unreachable_clear); +} + +/* A traversal callback for move_legacy_finalizer_reachable. */ +static int +visit_move(PyObject *op, void *arg) +{ + PyGC_Head *tolist = arg; + OBJECT_STAT_INC(object_visits); + if (_PyObject_IS_GC(op)) { + PyGC_Head *gc = AS_GC(op); + if (gc_is_collecting(gc)) { + gc_list_move(gc, tolist); + gc_clear_collecting(gc); + } + } + return 0; +} + +/* Move objects that are reachable from finalizers, from the unreachable set + * into finalizers set. + */ +static void +move_legacy_finalizer_reachable(PyGC_Head *finalizers) +{ + traverseproc traverse; + PyGC_Head *gc = GC_NEXT(finalizers); + for (; gc != finalizers; gc = GC_NEXT(gc)) { + /* Note that the finalizers list may grow during this. */ + traverse = Py_TYPE(FROM_GC(gc))->tp_traverse; + (void) traverse(FROM_GC(gc), + visit_move, + (void *)finalizers); + } +} + +/* Clear all weakrefs to unreachable objects, and if such a weakref has a + * callback, invoke it if necessary. Note that it's possible for such + * weakrefs to be outside the unreachable set -- indeed, those are precisely + * the weakrefs whose callbacks must be invoked. See gc_weakref.txt for + * overview & some details. Some weakrefs with callbacks may be reclaimed + * directly by this routine; the number reclaimed is the return value. Other + * weakrefs with callbacks may be moved into the `old` generation. Objects + * moved into `old` have gc_refs set to GC_REACHABLE; the objects remaining in + * unreachable are left at GC_TENTATIVELY_UNREACHABLE. When this returns, + * no object in `unreachable` is weakly referenced anymore. + */ +static int +handle_weakrefs(PyGC_Head *unreachable, PyGC_Head *old) +{ + PyGC_Head *gc; + PyObject *op; /* generally FROM_GC(gc) */ + PyWeakReference *wr; /* generally a cast of op */ + PyGC_Head wrcb_to_call; /* weakrefs with callbacks to call */ + PyGC_Head *next; + int num_freed = 0; + + gc_list_init(&wrcb_to_call); + + /* Clear all weakrefs to the objects in unreachable. If such a weakref + * also has a callback, move it into `wrcb_to_call` if the callback + * needs to be invoked. Note that we cannot invoke any callbacks until + * all weakrefs to unreachable objects are cleared, lest the callback + * resurrect an unreachable object via a still-active weakref. We + * make another pass over wrcb_to_call, invoking callbacks, after this + * pass completes. + */ + for (gc = GC_NEXT(unreachable); gc != unreachable; gc = next) { + PyWeakReference **wrlist; + + op = FROM_GC(gc); + next = GC_NEXT(gc); + + if (PyWeakref_Check(op)) { + /* A weakref inside the unreachable set must be cleared. If we + * allow its callback to execute inside delete_garbage(), it + * could expose objects that have tp_clear already called on + * them. Or, it could resurrect unreachable objects. One way + * this can happen is if some container objects do not implement + * tp_traverse. Then, wr_object can be outside the unreachable + * set but can be deallocated as a result of breaking the + * reference cycle. If we don't clear the weakref, the callback + * will run and potentially cause a crash. See bpo-38006 for + * one example. + */ + _PyWeakref_ClearRef((PyWeakReference *)op); + } + + if (! _PyType_SUPPORTS_WEAKREFS(Py_TYPE(op))) { + continue; + } + + /* It supports weakrefs. Does it have any? + * + * This is never triggered for static types so we can avoid the + * (slightly) more costly _PyObject_GET_WEAKREFS_LISTPTR(). + */ + wrlist = _PyObject_GET_WEAKREFS_LISTPTR_FROM_OFFSET(op); + + /* `op` may have some weakrefs. March over the list, clear + * all the weakrefs, and move the weakrefs with callbacks + * that must be called into wrcb_to_call. + */ + for (wr = *wrlist; wr != NULL; wr = *wrlist) { + PyGC_Head *wrasgc; /* AS_GC(wr) */ + + /* _PyWeakref_ClearRef clears the weakref but leaves + * the callback pointer intact. Obscure: it also + * changes *wrlist. + */ + _PyObject_ASSERT((PyObject *)wr, wr->wr_object == op); + _PyWeakref_ClearRef(wr); + _PyObject_ASSERT((PyObject *)wr, wr->wr_object == Py_None); + if (wr->wr_callback == NULL) { + /* no callback */ + continue; + } + + /* Headache time. `op` is going away, and is weakly referenced by + * `wr`, which has a callback. Should the callback be invoked? If wr + * is also trash, no: + * + * 1. There's no need to call it. The object and the weakref are + * both going away, so it's legitimate to pretend the weakref is + * going away first. The user has to ensure a weakref outlives its + * referent if they want a guarantee that the wr callback will get + * invoked. + * + * 2. It may be catastrophic to call it. If the callback is also in + * cyclic trash (CT), then although the CT is unreachable from + * outside the current generation, CT may be reachable from the + * callback. Then the callback could resurrect insane objects. + * + * Since the callback is never needed and may be unsafe in this case, + * wr is simply left in the unreachable set. Note that because we + * already called _PyWeakref_ClearRef(wr), its callback will never + * trigger. + * + * OTOH, if wr isn't part of CT, we should invoke the callback: the + * weakref outlived the trash. Note that since wr isn't CT in this + * case, its callback can't be CT either -- wr acted as an external + * root to this generation, and therefore its callback did too. So + * nothing in CT is reachable from the callback either, so it's hard + * to imagine how calling it later could create a problem for us. wr + * is moved to wrcb_to_call in this case. + */ + if (gc_is_collecting(AS_GC((PyObject *)wr))) { + /* it should already have been cleared above */ + assert(wr->wr_object == Py_None); + continue; + } + + /* Create a new reference so that wr can't go away + * before we can process it again. + */ + Py_INCREF(wr); + + /* Move wr to wrcb_to_call, for the next pass. */ + wrasgc = AS_GC((PyObject *)wr); + assert(wrasgc != next); /* wrasgc is reachable, but + next isn't, so they can't + be the same */ + gc_list_move(wrasgc, &wrcb_to_call); + } + } + + /* Invoke the callbacks we decided to honor. It's safe to invoke them + * because they can't reference unreachable objects. + */ + while (! gc_list_is_empty(&wrcb_to_call)) { + PyObject *temp; + PyObject *callback; + + gc = (PyGC_Head*)wrcb_to_call._gc_next; + op = FROM_GC(gc); + _PyObject_ASSERT(op, PyWeakref_Check(op)); + wr = (PyWeakReference *)op; + callback = wr->wr_callback; + _PyObject_ASSERT(op, callback != NULL); + + /* copy-paste of weakrefobject.c's handle_callback() */ + temp = PyObject_CallOneArg(callback, (PyObject *)wr); + if (temp == NULL) { + PyErr_WriteUnraisable(callback); + } + else { + Py_DECREF(temp); + } + + /* Give up the reference we created in the first pass. When + * op's refcount hits 0 (which it may or may not do right now), + * op's tp_dealloc will decref op->wr_callback too. Note + * that the refcount probably will hit 0 now, and because this + * weakref was reachable to begin with, gc didn't already + * add it to its count of freed objects. Example: a reachable + * weak value dict maps some key to this reachable weakref. + * The callback removes this key->weakref mapping from the + * dict, leaving no other references to the weakref (excepting + * ours). + */ + Py_DECREF(op); + if (wrcb_to_call._gc_next == (uintptr_t)gc) { + /* object is still alive -- move it */ + gc_list_move(gc, old); + } + else { + ++num_freed; + } + } + + return num_freed; +} + +static void +debug_cycle(const char *msg, PyObject *op) +{ + PySys_FormatStderr("gc: %s <%s %p>\n", + msg, Py_TYPE(op)->tp_name, op); +} + +/* Handle uncollectable garbage (cycles with tp_del slots, and stuff reachable + * only from such cycles). + * If _PyGC_DEBUG_SAVEALL, all objects in finalizers are appended to the module + * garbage list (a Python list), else only the objects in finalizers with + * __del__ methods are appended to garbage. All objects in finalizers are + * merged into the old list regardless. + */ +static void +handle_legacy_finalizers(PyThreadState *tstate, + GCState *gcstate, + PyGC_Head *finalizers, PyGC_Head *old) +{ + assert(!_PyErr_Occurred(tstate)); + assert(gcstate->garbage != NULL); + + PyGC_Head *gc = GC_NEXT(finalizers); + for (; gc != finalizers; gc = GC_NEXT(gc)) { + PyObject *op = FROM_GC(gc); + + if ((gcstate->debug & _PyGC_DEBUG_SAVEALL) || has_legacy_finalizer(op)) { + if (PyList_Append(gcstate->garbage, op) < 0) { + _PyErr_Clear(tstate); + break; + } + } + } + + gc_list_merge(finalizers, old); +} + +/* Run first-time finalizers (if any) on all the objects in collectable. + * Note that this may remove some (or even all) of the objects from the + * list, due to refcounts falling to 0. + */ +static void +finalize_garbage(PyThreadState *tstate, PyGC_Head *collectable) +{ + destructor finalize; + PyGC_Head seen; + + /* While we're going through the loop, `finalize(op)` may cause op, or + * other objects, to be reclaimed via refcounts falling to zero. So + * there's little we can rely on about the structure of the input + * `collectable` list across iterations. For safety, we always take the + * first object in that list and move it to a temporary `seen` list. + * If objects vanish from the `collectable` and `seen` lists we don't + * care. + */ + gc_list_init(&seen); + + while (!gc_list_is_empty(collectable)) { + PyGC_Head *gc = GC_NEXT(collectable); + PyObject *op = FROM_GC(gc); + gc_list_move(gc, &seen); + if (!_PyGCHead_FINALIZED(gc) && + (finalize = Py_TYPE(op)->tp_finalize) != NULL) + { + _PyGCHead_SET_FINALIZED(gc); + Py_INCREF(op); + finalize(op); + assert(!_PyErr_Occurred(tstate)); + Py_DECREF(op); + } + } + gc_list_merge(&seen, collectable); +} + +/* Break reference cycles by clearing the containers involved. This is + * tricky business as the lists can be changing and we don't know which + * objects may be freed. It is possible I screwed something up here. + */ +static void +delete_garbage(PyThreadState *tstate, GCState *gcstate, + PyGC_Head *collectable, PyGC_Head *old) +{ + assert(!_PyErr_Occurred(tstate)); + + while (!gc_list_is_empty(collectable)) { + PyGC_Head *gc = GC_NEXT(collectable); + PyObject *op = FROM_GC(gc); + + _PyObject_ASSERT_WITH_MSG(op, Py_REFCNT(op) > 0, + "refcount is too small"); + + if (gcstate->debug & _PyGC_DEBUG_SAVEALL) { + assert(gcstate->garbage != NULL); + if (PyList_Append(gcstate->garbage, op) < 0) { + _PyErr_Clear(tstate); + } + } + else { + inquiry clear; + if ((clear = Py_TYPE(op)->tp_clear) != NULL) { + Py_INCREF(op); + (void) clear(op); + if (_PyErr_Occurred(tstate)) { + PyErr_FormatUnraisable("Exception ignored in tp_clear of %s", + Py_TYPE(op)->tp_name); + } + Py_DECREF(op); + } + } + if (GC_NEXT(collectable) == gc) { + /* object is still alive, move it, it may die later */ + gc_clear_collecting(gc); + gc_list_move(gc, old); + } + } +} + + +// Show stats for objects in each generations +static void +show_stats_each_generations(GCState *gcstate) +{ + char buf[100]; + size_t pos = 0; + + for (int i = 0; i < NUM_GENERATIONS && pos < sizeof(buf); i++) { + pos += PyOS_snprintf(buf+pos, sizeof(buf)-pos, + " %zd", + gc_list_size(GEN_HEAD(gcstate, i))); + } + + PySys_FormatStderr( + "gc: objects in each generation:%s\n" + "gc: objects in permanent generation: %zd\n", + buf, gc_list_size(&gcstate->permanent_generation.head)); +} + +/* Deduce which objects among "base" are unreachable from outside the list + and move them to 'unreachable'. The process consist in the following steps: + +1. Copy all reference counts to a different field (gc_prev is used to hold + this copy to save memory). +2. Traverse all objects in "base" and visit all referred objects using + "tp_traverse" and for every visited object, subtract 1 to the reference + count (the one that we copied in the previous step). After this step, all + objects that can be reached directly from outside must have strictly positive + reference count, while all unreachable objects must have a count of exactly 0. +3. Identify all unreachable objects (the ones with 0 reference count) and move + them to the "unreachable" list. This step also needs to move back to "base" all + objects that were initially marked as unreachable but are referred transitively + by the reachable objects (the ones with strictly positive reference count). + +Contracts: + + * The "base" has to be a valid list with no mask set. + + * The "unreachable" list must be uninitialized (this function calls + gc_list_init over 'unreachable'). + +IMPORTANT: This function leaves 'unreachable' with the NEXT_MASK_UNREACHABLE +flag set but it does not clear it to skip unnecessary iteration. Before the +flag is cleared (for example, by using 'clear_unreachable_mask' function or +by a call to 'move_legacy_finalizers'), the 'unreachable' list is not a normal +list and we can not use most gc_list_* functions for it. */ +static inline void +deduce_unreachable(PyGC_Head *base, PyGC_Head *unreachable) { + validate_list(base, collecting_clear_unreachable_clear); + /* Using ob_refcnt and gc_refs, calculate which objects in the + * container set are reachable from outside the set (i.e., have a + * refcount greater than 0 when all the references within the + * set are taken into account). + */ + update_refs(base); // gc_prev is used for gc_refs + subtract_refs(base); + + /* Leave everything reachable from outside base in base, and move + * everything else (in base) to unreachable. + * + * NOTE: This used to move the reachable objects into a reachable + * set instead. But most things usually turn out to be reachable, + * so it's more efficient to move the unreachable things. It "sounds slick" + * to move the unreachable objects, until you think about it - the reason it + * pays isn't actually obvious. + * + * Suppose we create objects A, B, C in that order. They appear in the young + * generation in the same order. If B points to A, and C to B, and C is + * reachable from outside, then the adjusted refcounts will be 0, 0, and 1 + * respectively. + * + * When move_unreachable finds A, A is moved to the unreachable list. The + * same for B when it's first encountered. Then C is traversed, B is moved + * _back_ to the reachable list. B is eventually traversed, and then A is + * moved back to the reachable list. + * + * So instead of not moving at all, the reachable objects B and A are moved + * twice each. Why is this a win? A straightforward algorithm to move the + * reachable objects instead would move A, B, and C once each. + * + * The key is that this dance leaves the objects in order C, B, A - it's + * reversed from the original order. On all _subsequent_ scans, none of + * them will move. Since most objects aren't in cycles, this can save an + * unbounded number of moves across an unbounded number of later collections. + * It can cost more only the first time the chain is scanned. + * + * Drawback: move_unreachable is also used to find out what's still trash + * after finalizers may resurrect objects. In _that_ case most unreachable + * objects will remain unreachable, so it would be more efficient to move + * the reachable objects instead. But this is a one-time cost, probably not + * worth complicating the code to speed just a little. + */ + gc_list_init(unreachable); + move_unreachable(base, unreachable); // gc_prev is pointer again + validate_list(base, collecting_clear_unreachable_clear); + validate_list(unreachable, collecting_set_unreachable_set); +} + +/* Handle objects that may have resurrected after a call to 'finalize_garbage', moving + them to 'old_generation' and placing the rest on 'still_unreachable'. + + Contracts: + * After this function 'unreachable' must not be used anymore and 'still_unreachable' + will contain the objects that did not resurrect. + + * The "still_unreachable" list must be uninitialized (this function calls + gc_list_init over 'still_unreachable'). + +IMPORTANT: After a call to this function, the 'still_unreachable' set will have the +PREV_MARK_COLLECTING set, but the objects in this set are going to be removed so +we can skip the expense of clearing the flag to avoid extra iteration. */ +static inline void +handle_resurrected_objects(PyGC_Head *unreachable, PyGC_Head* still_unreachable, + PyGC_Head *old_generation) +{ + // Remove the PREV_MASK_COLLECTING from unreachable + // to prepare it for a new call to 'deduce_unreachable' + gc_list_clear_collecting(unreachable); + + // After the call to deduce_unreachable, the 'still_unreachable' set will + // have the PREV_MARK_COLLECTING set, but the objects are going to be + // removed so we can skip the expense of clearing the flag. + PyGC_Head* resurrected = unreachable; + deduce_unreachable(resurrected, still_unreachable); + clear_unreachable_mask(still_unreachable); + + // Move the resurrected objects to the old generation for future collection. + gc_list_merge(resurrected, old_generation); +} + + +/* Invoke progress callbacks to notify clients that garbage collection + * is starting or stopping + */ +static void +invoke_gc_callback(PyThreadState *tstate, const char *phase, + int generation, Py_ssize_t collected, + Py_ssize_t uncollectable) +{ + assert(!_PyErr_Occurred(tstate)); + + /* we may get called very early */ + GCState *gcstate = &tstate->interp->gc; + if (gcstate->callbacks == NULL) { + return; + } + + /* The local variable cannot be rebound, check it for sanity */ + assert(PyList_CheckExact(gcstate->callbacks)); + PyObject *info = NULL; + if (PyList_GET_SIZE(gcstate->callbacks) != 0) { + info = Py_BuildValue("{sisnsn}", + "generation", generation, + "collected", collected, + "uncollectable", uncollectable); + if (info == NULL) { + PyErr_FormatUnraisable("Exception ignored on invoking gc callbacks"); + return; + } + } + + PyObject *phase_obj = PyUnicode_FromString(phase); + if (phase_obj == NULL) { + Py_XDECREF(info); + PyErr_FormatUnraisable("Exception ignored on invoking gc callbacks"); + return; + } + + PyObject *stack[] = {phase_obj, info}; + for (Py_ssize_t i=0; icallbacks); i++) { + PyObject *r, *cb = PyList_GET_ITEM(gcstate->callbacks, i); + Py_INCREF(cb); /* make sure cb doesn't go away */ + r = PyObject_Vectorcall(cb, stack, 2, NULL); + if (r == NULL) { + PyErr_WriteUnraisable(cb); + } + else { + Py_DECREF(r); + } + Py_DECREF(cb); + } + Py_DECREF(phase_obj); + Py_XDECREF(info); + assert(!_PyErr_Occurred(tstate)); +} + + +/* Find the oldest generation (highest numbered) where the count + * exceeds the threshold. Objects in the that generation and + * generations younger than it will be collected. */ +static int +gc_select_generation(GCState *gcstate) +{ + for (int i = NUM_GENERATIONS-1; i >= 0; i--) { + if (gcstate->generations[i].count > gcstate->generations[i].threshold) { + /* Avoid quadratic performance degradation in number + of tracked objects (see also issue #4074): + + To limit the cost of garbage collection, there are two strategies; + - make each collection faster, e.g. by scanning fewer objects + - do less collections + This heuristic is about the latter strategy. + + In addition to the various configurable thresholds, we only trigger a + full collection if the ratio + + long_lived_pending / long_lived_total + + is above a given value (hardwired to 25%). + + The reason is that, while "non-full" collections (i.e., collections of + the young and middle generations) will always examine roughly the same + number of objects -- determined by the aforementioned thresholds --, + the cost of a full collection is proportional to the total number of + long-lived objects, which is virtually unbounded. + + Indeed, it has been remarked that doing a full collection every + of object creations entails a dramatic performance + degradation in workloads which consist in creating and storing lots of + long-lived objects (e.g. building a large list of GC-tracked objects would + show quadratic performance, instead of linear as expected: see issue #4074). + + Using the above ratio, instead, yields amortized linear performance in + the total number of objects (the effect of which can be summarized + thusly: "each full garbage collection is more and more costly as the + number of objects grows, but we do fewer and fewer of them"). + + This heuristic was suggested by Martin von Löwis on python-dev in + June 2008. His original analysis and proposal can be found at: + http://mail.python.org/pipermail/python-dev/2008-June/080579.html + */ + if (i == NUM_GENERATIONS - 1 + && gcstate->long_lived_pending < gcstate->long_lived_total / 4) + { + continue; + } + return i; + } + } + return -1; +} + + +/* This is the main function. Read this to understand how the + * collection process works. */ +static Py_ssize_t +gc_collect_main(PyThreadState *tstate, int generation, _PyGC_Reason reason) +{ + int i; + Py_ssize_t m = 0; /* # objects collected */ + Py_ssize_t n = 0; /* # unreachable objects that couldn't be collected */ + PyGC_Head *young; /* the generation we are examining */ + PyGC_Head *old; /* next older generation */ + PyGC_Head unreachable; /* non-problematic unreachable trash */ + PyGC_Head finalizers; /* objects with, & reachable from, __del__ */ + PyGC_Head *gc; + _PyTime_t t1 = 0; /* initialize to prevent a compiler warning */ + GCState *gcstate = &tstate->interp->gc; + + // gc_collect_main() must not be called before _PyGC_Init + // or after _PyGC_Fini() + assert(gcstate->garbage != NULL); + assert(!_PyErr_Occurred(tstate)); + + int expected = 0; + if (!_Py_atomic_compare_exchange_int(&gcstate->collecting, &expected, 1)) { + // Don't start a garbage collection if one is already in progress. + return 0; + } + + if (generation == GENERATION_AUTO) { + // Select the oldest generation that needs collecting. We will collect + // objects from that generation and all generations younger than it. + generation = gc_select_generation(gcstate); + if (generation < 0) { + // No generation needs to be collected. + _Py_atomic_store_int(&gcstate->collecting, 0); + return 0; + } + } + + assert(generation >= 0 && generation < NUM_GENERATIONS); + +#ifdef Py_STATS + if (_Py_stats) { + _Py_stats->object_stats.object_visits = 0; + } +#endif + GC_STAT_ADD(generation, collections, 1); + + if (reason != _Py_GC_REASON_SHUTDOWN) { + invoke_gc_callback(tstate, "start", generation, 0, 0); + } + + if (gcstate->debug & _PyGC_DEBUG_STATS) { + PySys_WriteStderr("gc: collecting generation %d...\n", generation); + show_stats_each_generations(gcstate); + t1 = _PyTime_GetPerfCounter(); + } + + if (PyDTrace_GC_START_ENABLED()) { + PyDTrace_GC_START(generation); + } + + /* update collection and allocation counters */ + if (generation+1 < NUM_GENERATIONS) { + gcstate->generations[generation+1].count += 1; + } + for (i = 0; i <= generation; i++) { + gcstate->generations[i].count = 0; + } + + /* merge younger generations with one we are currently collecting */ + for (i = 0; i < generation; i++) { + gc_list_merge(GEN_HEAD(gcstate, i), GEN_HEAD(gcstate, generation)); + } + + /* handy references */ + young = GEN_HEAD(gcstate, generation); + if (generation < NUM_GENERATIONS-1) { + old = GEN_HEAD(gcstate, generation+1); + } + else { + old = young; + } + validate_list(old, collecting_clear_unreachable_clear); + + deduce_unreachable(young, &unreachable); + + untrack_tuples(young); + /* Move reachable objects to next generation. */ + if (young != old) { + if (generation == NUM_GENERATIONS - 2) { + gcstate->long_lived_pending += gc_list_size(young); + } + gc_list_merge(young, old); + } + else { + /* We only un-track dicts in full collections, to avoid quadratic + dict build-up. See issue #14775. */ + untrack_dicts(young); + gcstate->long_lived_pending = 0; + gcstate->long_lived_total = gc_list_size(young); + } + + /* All objects in unreachable are trash, but objects reachable from + * legacy finalizers (e.g. tp_del) can't safely be deleted. + */ + gc_list_init(&finalizers); + // NEXT_MASK_UNREACHABLE is cleared here. + // After move_legacy_finalizers(), unreachable is normal list. + move_legacy_finalizers(&unreachable, &finalizers); + /* finalizers contains the unreachable objects with a legacy finalizer; + * unreachable objects reachable *from* those are also uncollectable, + * and we move those into the finalizers list too. + */ + move_legacy_finalizer_reachable(&finalizers); + + validate_list(&finalizers, collecting_clear_unreachable_clear); + validate_list(&unreachable, collecting_set_unreachable_clear); + + /* Print debugging information. */ + if (gcstate->debug & _PyGC_DEBUG_COLLECTABLE) { + for (gc = GC_NEXT(&unreachable); gc != &unreachable; gc = GC_NEXT(gc)) { + debug_cycle("collectable", FROM_GC(gc)); + } + } + + /* Clear weakrefs and invoke callbacks as necessary. */ + m += handle_weakrefs(&unreachable, old); + + validate_list(old, collecting_clear_unreachable_clear); + validate_list(&unreachable, collecting_set_unreachable_clear); + + /* Call tp_finalize on objects which have one. */ + finalize_garbage(tstate, &unreachable); + + /* Handle any objects that may have resurrected after the call + * to 'finalize_garbage' and continue the collection with the + * objects that are still unreachable */ + PyGC_Head final_unreachable; + handle_resurrected_objects(&unreachable, &final_unreachable, old); + + /* Call tp_clear on objects in the final_unreachable set. This will cause + * the reference cycles to be broken. It may also cause some objects + * in finalizers to be freed. + */ + m += gc_list_size(&final_unreachable); + delete_garbage(tstate, gcstate, &final_unreachable, old); + + /* Collect statistics on uncollectable objects found and print + * debugging information. */ + for (gc = GC_NEXT(&finalizers); gc != &finalizers; gc = GC_NEXT(gc)) { + n++; + if (gcstate->debug & _PyGC_DEBUG_UNCOLLECTABLE) + debug_cycle("uncollectable", FROM_GC(gc)); + } + if (gcstate->debug & _PyGC_DEBUG_STATS) { + double d = _PyTime_AsSecondsDouble(_PyTime_GetPerfCounter() - t1); + PySys_WriteStderr( + "gc: done, %zd unreachable, %zd uncollectable, %.4fs elapsed\n", + n+m, n, d); + } + + /* Append instances in the uncollectable set to a Python + * reachable list of garbage. The programmer has to deal with + * this if they insist on creating this type of structure. + */ + handle_legacy_finalizers(tstate, gcstate, &finalizers, old); + validate_list(old, collecting_clear_unreachable_clear); + + /* Clear free list only during the collection of the highest + * generation */ + if (generation == NUM_GENERATIONS-1) { + _PyGC_ClearAllFreeLists(tstate->interp); + } + + if (_PyErr_Occurred(tstate)) { + if (reason == _Py_GC_REASON_SHUTDOWN) { + _PyErr_Clear(tstate); + } + else { + PyErr_FormatUnraisable("Exception ignored in garbage collection"); + } + } + + /* Update stats */ + struct gc_generation_stats *stats = &gcstate->generation_stats[generation]; + stats->collections++; + stats->collected += m; + stats->uncollectable += n; + + GC_STAT_ADD(generation, objects_collected, m); +#ifdef Py_STATS + if (_Py_stats) { + GC_STAT_ADD(generation, object_visits, + _Py_stats->object_stats.object_visits); + _Py_stats->object_stats.object_visits = 0; + } +#endif + + if (PyDTrace_GC_DONE_ENABLED()) { + PyDTrace_GC_DONE(n + m); + } + + if (reason != _Py_GC_REASON_SHUTDOWN) { + invoke_gc_callback(tstate, "stop", generation, m, n); + } + + assert(!_PyErr_Occurred(tstate)); + _Py_atomic_store_int(&gcstate->collecting, 0); + return n + m; +} + +static int +referrersvisit(PyObject* obj, void *arg) +{ + PyObject *objs = arg; + Py_ssize_t i; + for (i = 0; i < PyTuple_GET_SIZE(objs); i++) { + if (PyTuple_GET_ITEM(objs, i) == obj) { + return 1; + } + } + return 0; +} + +static int +gc_referrers_for(PyObject *objs, PyGC_Head *list, PyObject *resultlist) +{ + PyGC_Head *gc; + PyObject *obj; + traverseproc traverse; + for (gc = GC_NEXT(list); gc != list; gc = GC_NEXT(gc)) { + obj = FROM_GC(gc); + traverse = Py_TYPE(obj)->tp_traverse; + if (obj == objs || obj == resultlist) { + continue; + } + if (traverse(obj, referrersvisit, objs)) { + if (PyList_Append(resultlist, obj) < 0) { + return 0; /* error */ + } + } + } + return 1; /* no error */ +} + +PyObject * +_PyGC_GetReferrers(PyInterpreterState *interp, PyObject *objs) +{ + PyObject *result = PyList_New(0); + if (!result) { + return NULL; + } + + GCState *gcstate = &interp->gc; + for (int i = 0; i < NUM_GENERATIONS; i++) { + if (!(gc_referrers_for(objs, GEN_HEAD(gcstate, i), result))) { + Py_DECREF(result); + return NULL; + } + } + return result; +} + +PyObject * +_PyGC_GetObjects(PyInterpreterState *interp, Py_ssize_t generation) +{ + assert(generation >= -1 && generation < NUM_GENERATIONS); + GCState *gcstate = &interp->gc; + + PyObject *result = PyList_New(0); + if (result == NULL) { + return NULL; + } + + if (generation == -1) { + /* If generation is -1, get all objects from all generations */ + for (int i = 0; i < NUM_GENERATIONS; i++) { + if (append_objects(result, GEN_HEAD(gcstate, i))) { + goto error; + } + } + } + else { + if (append_objects(result, GEN_HEAD(gcstate, generation))) { + goto error; + } + } + + return result; +error: + Py_DECREF(result); + return NULL; +} + +void +_PyGC_Freeze(PyInterpreterState *interp) +{ + GCState *gcstate = &interp->gc; + for (int i = 0; i < NUM_GENERATIONS; ++i) { + gc_list_merge(GEN_HEAD(gcstate, i), &gcstate->permanent_generation.head); + gcstate->generations[i].count = 0; + } +} + +void +_PyGC_Unfreeze(PyInterpreterState *interp) +{ + GCState *gcstate = &interp->gc; + gc_list_merge(&gcstate->permanent_generation.head, + GEN_HEAD(gcstate, NUM_GENERATIONS-1)); +} + +Py_ssize_t +_PyGC_GetFreezeCount(PyInterpreterState *interp) +{ + GCState *gcstate = &interp->gc; + return gc_list_size(&gcstate->permanent_generation.head); +} + +/* C API for controlling the state of the garbage collector */ +int +PyGC_Enable(void) +{ + GCState *gcstate = get_gc_state(); + int old_state = gcstate->enabled; + gcstate->enabled = 1; + return old_state; +} + +int +PyGC_Disable(void) +{ + GCState *gcstate = get_gc_state(); + int old_state = gcstate->enabled; + gcstate->enabled = 0; + return old_state; +} + +int +PyGC_IsEnabled(void) +{ + GCState *gcstate = get_gc_state(); + return gcstate->enabled; +} + +/* Public API to invoke gc.collect() from C */ +Py_ssize_t +PyGC_Collect(void) +{ + PyThreadState *tstate = _PyThreadState_GET(); + GCState *gcstate = &tstate->interp->gc; + + if (!gcstate->enabled) { + return 0; + } + + Py_ssize_t n; + PyObject *exc = _PyErr_GetRaisedException(tstate); + n = gc_collect_main(tstate, NUM_GENERATIONS - 1, _Py_GC_REASON_MANUAL); + _PyErr_SetRaisedException(tstate, exc); + + return n; +} + +Py_ssize_t +_PyGC_Collect(PyThreadState *tstate, int generation, _PyGC_Reason reason) +{ + return gc_collect_main(tstate, generation, reason); +} + +Py_ssize_t +_PyGC_CollectNoFail(PyThreadState *tstate) +{ + /* Ideally, this function is only called on interpreter shutdown, + and therefore not recursively. Unfortunately, when there are daemon + threads, a daemon thread can start a cyclic garbage collection + during interpreter shutdown (and then never finish it). + See http://bugs.python.org/issue8713#msg195178 for an example. + */ + return gc_collect_main(tstate, NUM_GENERATIONS - 1, _Py_GC_REASON_SHUTDOWN); +} + +void +_PyGC_DumpShutdownStats(PyInterpreterState *interp) +{ + GCState *gcstate = &interp->gc; + if (!(gcstate->debug & _PyGC_DEBUG_SAVEALL) + && gcstate->garbage != NULL && PyList_GET_SIZE(gcstate->garbage) > 0) { + const char *message; + if (gcstate->debug & _PyGC_DEBUG_UNCOLLECTABLE) { + message = "gc: %zd uncollectable objects at shutdown"; + } + else { + message = "gc: %zd uncollectable objects at shutdown; " \ + "use gc.set_debug(gc.DEBUG_UNCOLLECTABLE) to list them"; + } + /* PyErr_WarnFormat does too many things and we are at shutdown, + the warnings module's dependencies (e.g. linecache) may be gone + already. */ + if (PyErr_WarnExplicitFormat(PyExc_ResourceWarning, "gc", 0, + "gc", NULL, message, + PyList_GET_SIZE(gcstate->garbage))) + { + PyErr_WriteUnraisable(NULL); + } + if (gcstate->debug & _PyGC_DEBUG_UNCOLLECTABLE) { + PyObject *repr = NULL, *bytes = NULL; + repr = PyObject_Repr(gcstate->garbage); + if (!repr || !(bytes = PyUnicode_EncodeFSDefault(repr))) { + PyErr_WriteUnraisable(gcstate->garbage); + } + else { + PySys_WriteStderr( + " %s\n", + PyBytes_AS_STRING(bytes) + ); + } + Py_XDECREF(repr); + Py_XDECREF(bytes); + } + } +} + + +void +_PyGC_Fini(PyInterpreterState *interp) +{ + GCState *gcstate = &interp->gc; + Py_CLEAR(gcstate->garbage); + Py_CLEAR(gcstate->callbacks); + + /* We expect that none of this interpreters objects are shared + with other interpreters. + See https://github.com/python/cpython/issues/90228. */ +} + +/* for debugging */ +void +_PyGC_Dump(PyGC_Head *g) +{ + _PyObject_Dump(FROM_GC(g)); +} + + +#ifdef Py_DEBUG +static int +visit_validate(PyObject *op, void *parent_raw) +{ + PyObject *parent = _PyObject_CAST(parent_raw); + if (_PyObject_IsFreed(op)) { + _PyObject_ASSERT_FAILED_MSG(parent, + "PyObject_GC_Track() object is not valid"); + } + return 0; +} +#endif + + +/* extension modules might be compiled with GC support so these + functions must always be available */ + +void +PyObject_GC_Track(void *op_raw) +{ + PyObject *op = _PyObject_CAST(op_raw); + if (_PyObject_GC_IS_TRACKED(op)) { + _PyObject_ASSERT_FAILED_MSG(op, + "object already tracked " + "by the garbage collector"); + } + _PyObject_GC_TRACK(op); + +#ifdef Py_DEBUG + /* Check that the object is valid: validate objects traversed + by tp_traverse() */ + traverseproc traverse = Py_TYPE(op)->tp_traverse; + (void)traverse(op, visit_validate, op); +#endif +} + +void +PyObject_GC_UnTrack(void *op_raw) +{ + PyObject *op = _PyObject_CAST(op_raw); + /* Obscure: the Py_TRASHCAN mechanism requires that we be able to + * call PyObject_GC_UnTrack twice on an object. + */ + if (_PyObject_GC_IS_TRACKED(op)) { + _PyObject_GC_UNTRACK(op); + } +} + +int +PyObject_IS_GC(PyObject *obj) +{ + return _PyObject_IS_GC(obj); +} + +void +_Py_ScheduleGC(PyInterpreterState *interp) +{ + _Py_set_eval_breaker_bit(interp, _PY_GC_SCHEDULED_BIT, 1); +} + +void +_PyObject_GC_Link(PyObject *op) +{ + PyGC_Head *g = AS_GC(op); + assert(((uintptr_t)g & (sizeof(uintptr_t)-1)) == 0); // g must be correctly aligned + + PyThreadState *tstate = _PyThreadState_GET(); + GCState *gcstate = &tstate->interp->gc; + g->_gc_next = 0; + g->_gc_prev = 0; + gcstate->generations[0].count++; /* number of allocated GC objects */ + if (gcstate->generations[0].count > gcstate->generations[0].threshold && + gcstate->enabled && + gcstate->generations[0].threshold && + !_Py_atomic_load_int_relaxed(&gcstate->collecting) && + !_PyErr_Occurred(tstate)) + { + _Py_ScheduleGC(tstate->interp); + } +} + +void +_Py_RunGC(PyThreadState *tstate) +{ + gc_collect_main(tstate, GENERATION_AUTO, _Py_GC_REASON_HEAP); +} + +static PyObject * +gc_alloc(size_t basicsize, size_t presize) +{ + PyThreadState *tstate = _PyThreadState_GET(); + if (basicsize > PY_SSIZE_T_MAX - presize) { + return _PyErr_NoMemory(tstate); + } + size_t size = presize + basicsize; + char *mem = PyObject_Malloc(size); + if (mem == NULL) { + return _PyErr_NoMemory(tstate); + } + ((PyObject **)mem)[0] = NULL; + ((PyObject **)mem)[1] = NULL; + PyObject *op = (PyObject *)(mem + presize); + _PyObject_GC_Link(op); + return op; +} + +PyObject * +_PyObject_GC_New(PyTypeObject *tp) +{ + size_t presize = _PyType_PreHeaderSize(tp); + PyObject *op = gc_alloc(_PyObject_SIZE(tp), presize); + if (op == NULL) { + return NULL; + } + _PyObject_Init(op, tp); + return op; +} + +PyVarObject * +_PyObject_GC_NewVar(PyTypeObject *tp, Py_ssize_t nitems) +{ + PyVarObject *op; + + if (nitems < 0) { + PyErr_BadInternalCall(); + return NULL; + } + size_t presize = _PyType_PreHeaderSize(tp); + size_t size = _PyObject_VAR_SIZE(tp, nitems); + op = (PyVarObject *)gc_alloc(size, presize); + if (op == NULL) { + return NULL; + } + _PyObject_InitVar(op, tp, nitems); + return op; +} + +PyObject * +PyUnstable_Object_GC_NewWithExtraData(PyTypeObject *tp, size_t extra_size) +{ + size_t presize = _PyType_PreHeaderSize(tp); + PyObject *op = gc_alloc(_PyObject_SIZE(tp) + extra_size, presize); + if (op == NULL) { + return NULL; + } + memset(op, 0, _PyObject_SIZE(tp) + extra_size); + _PyObject_Init(op, tp); + return op; +} + +PyVarObject * +_PyObject_GC_Resize(PyVarObject *op, Py_ssize_t nitems) +{ + const size_t basicsize = _PyObject_VAR_SIZE(Py_TYPE(op), nitems); + const size_t presize = _PyType_PreHeaderSize(((PyObject *)op)->ob_type); + _PyObject_ASSERT((PyObject *)op, !_PyObject_GC_IS_TRACKED(op)); + if (basicsize > (size_t)PY_SSIZE_T_MAX - presize) { + return (PyVarObject *)PyErr_NoMemory(); + } + char *mem = (char *)op - presize; + mem = (char *)PyObject_Realloc(mem, presize + basicsize); + if (mem == NULL) { + return (PyVarObject *)PyErr_NoMemory(); + } + op = (PyVarObject *) (mem + presize); + Py_SET_SIZE(op, nitems); + return op; +} + +void +PyObject_GC_Del(void *op) +{ + size_t presize = _PyType_PreHeaderSize(((PyObject *)op)->ob_type); + PyGC_Head *g = AS_GC(op); + if (_PyObject_GC_IS_TRACKED(op)) { + gc_list_remove(g); +#ifdef Py_DEBUG + PyObject *exc = PyErr_GetRaisedException(); + if (PyErr_WarnExplicitFormat(PyExc_ResourceWarning, "gc", 0, + "gc", NULL, "Object of type %s is not untracked before destruction", + ((PyObject*)op)->ob_type->tp_name)) { + PyErr_WriteUnraisable(NULL); + } + PyErr_SetRaisedException(exc); +#endif + } + GCState *gcstate = get_gc_state(); + if (gcstate->generations[0].count > 0) { + gcstate->generations[0].count--; + } + PyObject_Free(((char *)op)-presize); +} + +int +PyObject_GC_IsTracked(PyObject* obj) +{ + if (_PyObject_IS_GC(obj) && _PyObject_GC_IS_TRACKED(obj)) { + return 1; + } + return 0; +} + +int +PyObject_GC_IsFinalized(PyObject *obj) +{ + if (_PyObject_IS_GC(obj) && _PyGC_FINALIZED(obj)) { + return 1; + } + return 0; +} + +void +PyUnstable_GC_VisitObjects(gcvisitobjects_t callback, void *arg) +{ + size_t i; + GCState *gcstate = get_gc_state(); + int origenstate = gcstate->enabled; + gcstate->enabled = 0; + for (i = 0; i < NUM_GENERATIONS; i++) { + PyGC_Head *gc_list, *gc; + gc_list = GEN_HEAD(gcstate, i); + for (gc = GC_NEXT(gc_list); gc != gc_list; gc = GC_NEXT(gc)) { + PyObject *op = FROM_GC(gc); + Py_INCREF(op); + int res = callback(op, arg); + Py_DECREF(op); + if (!res) { + goto done; + } + } + } +done: + gcstate->enabled = origenstate; +} diff --git a/Python/gc_free_threading.c b/Python/gc_free_threading.c new file mode 100644 index 00000000000000..b1d88ff84a9a9e --- /dev/null +++ b/Python/gc_free_threading.c @@ -0,0 +1,30 @@ +#include "Python.h" +#include "pycore_pystate.h" // _PyFreeListState_GET() +#include "pycore_tstate.h" // _PyThreadStateImpl + +#ifdef Py_GIL_DISABLED + +/* Clear all free lists + * All free lists are cleared during the collection of the highest generation. + * Allocated items in the free list may keep a pymalloc arena occupied. + * Clearing the free lists may give back memory to the OS earlier. + * Free-threading version: Since freelists are managed per thread, + * GC should clear all freelists by traversing all threads. + */ +void +_PyGC_ClearAllFreeLists(PyInterpreterState *interp) +{ + _PyDict_ClearFreeList(interp); + _PyAsyncGen_ClearFreeLists(interp); + _PyContext_ClearFreeList(interp); + + HEAD_LOCK(&_PyRuntime); + _PyThreadStateImpl *tstate = (_PyThreadStateImpl *)interp->threads.head; + while (tstate != NULL) { + _Py_ClearFreeLists(&tstate->freelist_state, 0); + tstate = (_PyThreadStateImpl *)tstate->base.next; + } + HEAD_UNLOCK(&_PyRuntime); +} + +#endif diff --git a/Python/gc_gil.c b/Python/gc_gil.c new file mode 100644 index 00000000000000..873fad8a3746aa --- /dev/null +++ b/Python/gc_gil.c @@ -0,0 +1,21 @@ +#include "Python.h" +#include "pycore_pystate.h" // _Py_ClearFreeLists() + +#ifndef Py_GIL_DISABLED + +/* Clear all free lists + * All free lists are cleared during the collection of the highest generation. + * Allocated items in the free list may keep a pymalloc arena occupied. + * Clearing the free lists may give back memory to the OS earlier. + */ +void +_PyGC_ClearAllFreeLists(PyInterpreterState *interp) +{ + _PyDict_ClearFreeList(interp); + _PyAsyncGen_ClearFreeLists(interp); + _PyContext_ClearFreeList(interp); + + _Py_ClearFreeLists(&interp->freelist_state, 0); +} + +#endif diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h index 7250240ac2396c..1e995b62a72fcf 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -1,423 +1,310 @@ -// This file is generated by Tools/cases_generator/generate_cases.py +// This file is generated by Tools/cases_generator/tier1_generator.py // from: // Python/bytecodes.c // Do not edit! - TARGET(NOP) { - DISPATCH(); - } +#ifdef TIER_TWO + #error "This file is for Tier 1 only" +#endif +#define TIER_ONE 1 - TARGET(RESUME) { - assert(tstate->cframe == &cframe); - assert(frame == cframe.current_frame); - /* Possibly combine this with eval breaker */ - if (_PyFrame_GetCode(frame)->_co_instrumentation_version != tstate->interp->monitoring_version) { - int err = _Py_Instrument(_PyFrame_GetCode(frame), tstate->interp); - if (err) goto error; - next_instr--; + + TARGET(BEFORE_ASYNC_WITH) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(BEFORE_ASYNC_WITH); + PyObject *mgr; + PyObject *exit; + PyObject *res; + mgr = stack_pointer[-1]; + PyObject *enter = _PyObject_LookupSpecial(mgr, &_Py_ID(__aenter__)); + if (enter == NULL) { + if (!_PyErr_Occurred(tstate)) { + _PyErr_Format(tstate, PyExc_TypeError, + "'%.200s' object does not support the " + "asynchronous context manager protocol", + Py_TYPE(mgr)->tp_name); + } + GOTO_ERROR(error); + } + exit = _PyObject_LookupSpecial(mgr, &_Py_ID(__aexit__)); + if (exit == NULL) { + if (!_PyErr_Occurred(tstate)) { + _PyErr_Format(tstate, PyExc_TypeError, + "'%.200s' object does not support the " + "asynchronous context manager protocol " + "(missed __aexit__ method)", + Py_TYPE(mgr)->tp_name); + } + Py_DECREF(enter); + GOTO_ERROR(error); } - else if (oparg < 2) { - CHECK_EVAL_BREAKER(); + Py_DECREF(mgr); + res = _PyObject_CallNoArgsTstate(tstate, enter); + Py_DECREF(enter); + if (res == NULL) { + Py_DECREF(exit); + if (true) goto pop_1_error; } + stack_pointer[-1] = exit; + stack_pointer[0] = res; + stack_pointer += 1; DISPATCH(); } - TARGET(INSTRUMENTED_RESUME) { - /* Possible performance enhancement: - * We need to check the eval breaker anyway, can we - * combine the instrument verison check and the eval breaker test? + TARGET(BEFORE_WITH) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(BEFORE_WITH); + PyObject *mgr; + PyObject *exit; + PyObject *res; + mgr = stack_pointer[-1]; + /* pop the context manager, push its __exit__ and the + * value returned from calling its __enter__ */ - if (_PyFrame_GetCode(frame)->_co_instrumentation_version != tstate->interp->monitoring_version) { - if (_Py_Instrument(_PyFrame_GetCode(frame), tstate->interp)) { - goto error; + PyObject *enter = _PyObject_LookupSpecial(mgr, &_Py_ID(__enter__)); + if (enter == NULL) { + if (!_PyErr_Occurred(tstate)) { + _PyErr_Format(tstate, PyExc_TypeError, + "'%.200s' object does not support the " + "context manager protocol", + Py_TYPE(mgr)->tp_name); } - next_instr--; + GOTO_ERROR(error); } - else { - if (oparg < 2) { - CHECK_EVAL_BREAKER(); - } - _PyFrame_SetStackPointer(frame, stack_pointer); - int err = _Py_call_instrumentation( - tstate, oparg > 0, frame, next_instr-1); - stack_pointer = _PyFrame_GetStackPointer(frame); - if (err) goto error; - if (frame->prev_instr != next_instr-1) { - /* Instrumentation has jumped */ - next_instr = frame->prev_instr; - DISPATCH(); + exit = _PyObject_LookupSpecial(mgr, &_Py_ID(__exit__)); + if (exit == NULL) { + if (!_PyErr_Occurred(tstate)) { + _PyErr_Format(tstate, PyExc_TypeError, + "'%.200s' object does not support the " + "context manager protocol " + "(missed __exit__ method)", + Py_TYPE(mgr)->tp_name); } + Py_DECREF(enter); + GOTO_ERROR(error); } + Py_DECREF(mgr); + res = _PyObject_CallNoArgsTstate(tstate, enter); + Py_DECREF(enter); + if (res == NULL) { + Py_DECREF(exit); + if (true) goto pop_1_error; + } + stack_pointer[-1] = exit; + stack_pointer[0] = res; + stack_pointer += 1; DISPATCH(); } - TARGET(LOAD_FAST_CHECK) { - PyObject *value; - value = GETLOCAL(oparg); - if (value == NULL) goto unbound_local_error; - Py_INCREF(value); - STACK_GROW(1); - stack_pointer[-1] = value; - DISPATCH(); - } - - TARGET(LOAD_FAST) { - PyObject *value; - value = GETLOCAL(oparg); - assert(value != NULL); - Py_INCREF(value); - STACK_GROW(1); - stack_pointer[-1] = value; - DISPATCH(); - } - - TARGET(LOAD_FAST_AND_CLEAR) { - PyObject *value; - value = GETLOCAL(oparg); - // do not use SETLOCAL here, it decrefs the old value - GETLOCAL(oparg) = NULL; - STACK_GROW(1); - stack_pointer[-1] = value; - DISPATCH(); - } - - TARGET(LOAD_FAST_LOAD_FAST) { - PyObject *value1; - PyObject *value2; - uint32_t oparg1 = oparg >> 4; - uint32_t oparg2 = oparg & 15; - value1 = GETLOCAL(oparg1); - value2 = GETLOCAL(oparg2); - Py_INCREF(value1); - Py_INCREF(value2); - STACK_GROW(2); - stack_pointer[-2] = value1; - stack_pointer[-1] = value2; - DISPATCH(); - } - - TARGET(LOAD_CONST) { - PyObject *value; - value = GETITEM(FRAME_CO_CONSTS, oparg); - Py_INCREF(value); - STACK_GROW(1); - stack_pointer[-1] = value; - DISPATCH(); - } - - TARGET(STORE_FAST) { - PyObject *value; - value = stack_pointer[-1]; - SETLOCAL(oparg, value); - STACK_SHRINK(1); - DISPATCH(); - } - - TARGET(STORE_FAST_LOAD_FAST) { - PyObject *value1; - PyObject *value2; - value1 = stack_pointer[-1]; - uint32_t oparg1 = oparg >> 4; - uint32_t oparg2 = oparg & 15; - SETLOCAL(oparg1, value1); - value2 = GETLOCAL(oparg2); - Py_INCREF(value2); - stack_pointer[-1] = value2; - DISPATCH(); - } - - TARGET(STORE_FAST_STORE_FAST) { - PyObject *value1; - PyObject *value2; - value1 = stack_pointer[-1]; - value2 = stack_pointer[-2]; - uint32_t oparg1 = oparg >> 4; - uint32_t oparg2 = oparg & 15; - SETLOCAL(oparg1, value1); - SETLOCAL(oparg2, value2); - STACK_SHRINK(2); - DISPATCH(); - } - - TARGET(POP_TOP) { - PyObject *value; - value = stack_pointer[-1]; - Py_DECREF(value); - STACK_SHRINK(1); + TARGET(BINARY_OP) { + frame->instr_ptr = next_instr; + next_instr += 2; + INSTRUCTION_STATS(BINARY_OP); + PREDICTED(BINARY_OP); + _Py_CODEUNIT *this_instr = next_instr - 2; + PyObject *rhs; + PyObject *lhs; + PyObject *res; + // _SPECIALIZE_BINARY_OP + rhs = stack_pointer[-1]; + lhs = stack_pointer[-2]; + { + uint16_t counter = read_u16(&this_instr[1].cache); + TIER_ONE_ONLY + #if ENABLE_SPECIALIZATION + if (ADAPTIVE_COUNTER_IS_ZERO(counter)) { + next_instr = this_instr; + _Py_Specialize_BinaryOp(lhs, rhs, next_instr, oparg, LOCALS_ARRAY); + DISPATCH_SAME_OPARG(); + } + STAT_INC(BINARY_OP, deferred); + DECREMENT_ADAPTIVE_COUNTER(this_instr[1].cache); + #endif /* ENABLE_SPECIALIZATION */ + assert(NB_ADD <= oparg); + assert(oparg <= NB_INPLACE_XOR); + } + // _BINARY_OP + { + assert(_PyEval_BinaryOps[oparg]); + res = _PyEval_BinaryOps[oparg](lhs, rhs); + Py_DECREF(lhs); + Py_DECREF(rhs); + if (res == NULL) goto pop_2_error; + } + stack_pointer[-2] = res; + stack_pointer += -1; DISPATCH(); } - TARGET(PUSH_NULL) { + TARGET(BINARY_OP_ADD_FLOAT) { + frame->instr_ptr = next_instr; + next_instr += 2; + INSTRUCTION_STATS(BINARY_OP_ADD_FLOAT); + static_assert(INLINE_CACHE_ENTRIES_BINARY_OP == 1, "incorrect cache size"); + PyObject *right; + PyObject *left; PyObject *res; - res = NULL; - STACK_GROW(1); - stack_pointer[-1] = res; + // _GUARD_BOTH_FLOAT + right = stack_pointer[-1]; + left = stack_pointer[-2]; + { + DEOPT_IF(!PyFloat_CheckExact(left), BINARY_OP); + DEOPT_IF(!PyFloat_CheckExact(right), BINARY_OP); + } + /* Skip 1 cache entry */ + // _BINARY_OP_ADD_FLOAT + { + STAT_INC(BINARY_OP, hit); + double dres = + ((PyFloatObject *)left)->ob_fval + + ((PyFloatObject *)right)->ob_fval; + DECREF_INPUTS_AND_REUSE_FLOAT(left, right, dres, res); + } + stack_pointer[-2] = res; + stack_pointer += -1; DISPATCH(); } - TARGET(END_FOR) { - PyObject *value; - // POP_TOP - value = stack_pointer[-1]; + TARGET(BINARY_OP_ADD_INT) { + frame->instr_ptr = next_instr; + next_instr += 2; + INSTRUCTION_STATS(BINARY_OP_ADD_INT); + static_assert(INLINE_CACHE_ENTRIES_BINARY_OP == 1, "incorrect cache size"); + PyObject *right; + PyObject *left; + PyObject *res; + // _GUARD_BOTH_INT + right = stack_pointer[-1]; + left = stack_pointer[-2]; { - Py_DECREF(value); + DEOPT_IF(!PyLong_CheckExact(left), BINARY_OP); + DEOPT_IF(!PyLong_CheckExact(right), BINARY_OP); } - // POP_TOP - value = stack_pointer[-2]; + /* Skip 1 cache entry */ + // _BINARY_OP_ADD_INT { - Py_DECREF(value); + STAT_INC(BINARY_OP, hit); + res = _PyLong_Add((PyLongObject *)left, (PyLongObject *)right); + _Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free); + _Py_DECREF_SPECIALIZED(left, (destructor)PyObject_Free); + if (res == NULL) goto pop_2_error; } - STACK_SHRINK(2); + stack_pointer[-2] = res; + stack_pointer += -1; DISPATCH(); } - TARGET(INSTRUMENTED_END_FOR) { - PyObject *value; - PyObject *receiver; - value = stack_pointer[-1]; - receiver = stack_pointer[-2]; - /* Need to create a fake StopIteration error here, - * to conform to PEP 380 */ - if (PyGen_Check(receiver)) { - PyErr_SetObject(PyExc_StopIteration, value); - if (monitor_stop_iteration(tstate, frame, next_instr-1)) { - goto error; - } - PyErr_SetRaisedException(NULL); + TARGET(BINARY_OP_ADD_UNICODE) { + frame->instr_ptr = next_instr; + next_instr += 2; + INSTRUCTION_STATS(BINARY_OP_ADD_UNICODE); + static_assert(INLINE_CACHE_ENTRIES_BINARY_OP == 1, "incorrect cache size"); + PyObject *right; + PyObject *left; + PyObject *res; + // _GUARD_BOTH_UNICODE + right = stack_pointer[-1]; + left = stack_pointer[-2]; + { + DEOPT_IF(!PyUnicode_CheckExact(left), BINARY_OP); + DEOPT_IF(!PyUnicode_CheckExact(right), BINARY_OP); } - Py_DECREF(receiver); - Py_DECREF(value); - STACK_SHRINK(2); + /* Skip 1 cache entry */ + // _BINARY_OP_ADD_UNICODE + { + STAT_INC(BINARY_OP, hit); + res = PyUnicode_Concat(left, right); + _Py_DECREF_SPECIALIZED(left, _PyUnicode_ExactDealloc); + _Py_DECREF_SPECIALIZED(right, _PyUnicode_ExactDealloc); + if (res == NULL) goto pop_2_error; + } + stack_pointer[-2] = res; + stack_pointer += -1; DISPATCH(); } - TARGET(END_SEND) { - PyObject *value; - PyObject *receiver; - value = stack_pointer[-1]; - receiver = stack_pointer[-2]; - Py_DECREF(receiver); - STACK_SHRINK(1); - stack_pointer[-1] = value; - DISPATCH(); - } - - TARGET(INSTRUMENTED_END_SEND) { - PyObject *value; - PyObject *receiver; - value = stack_pointer[-1]; - receiver = stack_pointer[-2]; - if (PyGen_Check(receiver) || PyCoro_CheckExact(receiver)) { - PyErr_SetObject(PyExc_StopIteration, value); - if (monitor_stop_iteration(tstate, frame, next_instr-1)) { - goto error; - } - PyErr_SetRaisedException(NULL); - } - Py_DECREF(receiver); - STACK_SHRINK(1); - stack_pointer[-1] = value; - DISPATCH(); - } - - TARGET(UNARY_NEGATIVE) { - PyObject *value; - PyObject *res; - value = stack_pointer[-1]; - res = PyNumber_Negative(value); - Py_DECREF(value); - if (res == NULL) goto pop_1_error; - stack_pointer[-1] = res; - DISPATCH(); - } - - TARGET(UNARY_NOT) { - PyObject *value; - PyObject *res; - value = stack_pointer[-1]; - assert(PyBool_Check(value)); - res = Py_IsFalse(value) ? Py_True : Py_False; - stack_pointer[-1] = res; - DISPATCH(); - } - - TARGET(TO_BOOL) { - PREDICTED(TO_BOOL); - static_assert(INLINE_CACHE_ENTRIES_TO_BOOL == 3, "incorrect cache size"); - PyObject *value; - PyObject *res; - value = stack_pointer[-1]; - #if ENABLE_SPECIALIZATION - _PyToBoolCache *cache = (_PyToBoolCache *)next_instr; - if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) { - next_instr--; - _Py_Specialize_ToBool(value, next_instr); - DISPATCH_SAME_OPARG(); - } - STAT_INC(TO_BOOL, deferred); - DECREMENT_ADAPTIVE_COUNTER(cache->counter); - #endif /* ENABLE_SPECIALIZATION */ - int err = PyObject_IsTrue(value); - Py_DECREF(value); - if (err < 0) goto pop_1_error; - res = err ? Py_True : Py_False; - stack_pointer[-1] = res; - next_instr += 3; - DISPATCH(); - } - - TARGET(TO_BOOL_BOOL) { - PyObject *value; - value = stack_pointer[-1]; - DEOPT_IF(!PyBool_Check(value), TO_BOOL); - STAT_INC(TO_BOOL, hit); - next_instr += 3; - DISPATCH(); - } - - TARGET(TO_BOOL_INT) { - PyObject *value; - PyObject *res; - value = stack_pointer[-1]; - DEOPT_IF(!PyLong_CheckExact(value), TO_BOOL); - STAT_INC(TO_BOOL, hit); - if (_PyLong_IsZero((PyLongObject *)value)) { - assert(_Py_IsImmortal(value)); - res = Py_False; - } - else { - Py_DECREF(value); - res = Py_True; - } - stack_pointer[-1] = res; - next_instr += 3; - DISPATCH(); - } - - TARGET(TO_BOOL_LIST) { - PyObject *value; - PyObject *res; - value = stack_pointer[-1]; - DEOPT_IF(!PyList_CheckExact(value), TO_BOOL); - STAT_INC(TO_BOOL, hit); - res = Py_SIZE(value) ? Py_True : Py_False; - Py_DECREF(value); - stack_pointer[-1] = res; - next_instr += 3; - DISPATCH(); - } - - TARGET(TO_BOOL_NONE) { - PyObject *value; - PyObject *res; - value = stack_pointer[-1]; - // This one is a bit weird, because we expect *some* failures: - DEOPT_IF(!Py_IsNone(value), TO_BOOL); - STAT_INC(TO_BOOL, hit); - res = Py_False; - stack_pointer[-1] = res; - next_instr += 3; - DISPATCH(); - } - - TARGET(TO_BOOL_STR) { - PyObject *value; - PyObject *res; - value = stack_pointer[-1]; - DEOPT_IF(!PyUnicode_CheckExact(value), TO_BOOL); - STAT_INC(TO_BOOL, hit); - if (value == &_Py_STR(empty)) { - assert(_Py_IsImmortal(value)); - res = Py_False; - } - else { - assert(Py_SIZE(value)); - Py_DECREF(value); - res = Py_True; - } - stack_pointer[-1] = res; - next_instr += 3; - DISPATCH(); - } - - TARGET(TO_BOOL_ALWAYS_TRUE) { - PyObject *value; - PyObject *res; - value = stack_pointer[-1]; - uint32_t version = read_u32(&next_instr[1].cache); - // This one is a bit weird, because we expect *some* failures: - assert(version); - DEOPT_IF(Py_TYPE(value)->tp_version_tag != version, TO_BOOL); - STAT_INC(TO_BOOL, hit); - Py_DECREF(value); - res = Py_True; - stack_pointer[-1] = res; - next_instr += 3; - DISPATCH(); - } - - TARGET(UNARY_INVERT) { - PyObject *value; - PyObject *res; - value = stack_pointer[-1]; - res = PyNumber_Invert(value); - Py_DECREF(value); - if (res == NULL) goto pop_1_error; - stack_pointer[-1] = res; - DISPATCH(); - } - - TARGET(BINARY_OP_MULTIPLY_INT) { + TARGET(BINARY_OP_INPLACE_ADD_UNICODE) { + frame->instr_ptr = next_instr; + next_instr += 2; + INSTRUCTION_STATS(BINARY_OP_INPLACE_ADD_UNICODE); + static_assert(INLINE_CACHE_ENTRIES_BINARY_OP == 1, "incorrect cache size"); PyObject *right; PyObject *left; - PyObject *res; - // _GUARD_BOTH_INT + // _GUARD_BOTH_UNICODE right = stack_pointer[-1]; left = stack_pointer[-2]; { - DEOPT_IF(!PyLong_CheckExact(left), BINARY_OP); - DEOPT_IF(!PyLong_CheckExact(right), BINARY_OP); + DEOPT_IF(!PyUnicode_CheckExact(left), BINARY_OP); + DEOPT_IF(!PyUnicode_CheckExact(right), BINARY_OP); } - // _BINARY_OP_MULTIPLY_INT + /* Skip 1 cache entry */ + // _BINARY_OP_INPLACE_ADD_UNICODE { + TIER_ONE_ONLY + assert(next_instr->op.code == STORE_FAST); + PyObject **target_local = &GETLOCAL(next_instr->op.arg); + DEOPT_IF(*target_local != left, BINARY_OP); STAT_INC(BINARY_OP, hit); - res = _PyLong_Multiply((PyLongObject *)left, (PyLongObject *)right); - _Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free); - _Py_DECREF_SPECIALIZED(left, (destructor)PyObject_Free); - if (res == NULL) goto pop_2_error; + /* Handle `left = left + right` or `left += right` for str. + * + * When possible, extend `left` in place rather than + * allocating a new PyUnicodeObject. This attempts to avoid + * quadratic behavior when one neglects to use str.join(). + * + * If `left` has only two references remaining (one from + * the stack, one in the locals), DECREFing `left` leaves + * only the locals reference, so PyUnicode_Append knows + * that the string is safe to mutate. + */ + assert(Py_REFCNT(left) >= 2); + _Py_DECREF_NO_DEALLOC(left); + PyUnicode_Append(target_local, right); + _Py_DECREF_SPECIALIZED(right, _PyUnicode_ExactDealloc); + if (*target_local == NULL) goto pop_2_error; + // The STORE_FAST is already done. + assert(next_instr->op.code == STORE_FAST); + SKIP_OVER(1); } - STACK_SHRINK(1); - stack_pointer[-1] = res; - next_instr += 1; + stack_pointer += -2; DISPATCH(); } - TARGET(BINARY_OP_ADD_INT) { + TARGET(BINARY_OP_MULTIPLY_FLOAT) { + frame->instr_ptr = next_instr; + next_instr += 2; + INSTRUCTION_STATS(BINARY_OP_MULTIPLY_FLOAT); + static_assert(INLINE_CACHE_ENTRIES_BINARY_OP == 1, "incorrect cache size"); PyObject *right; PyObject *left; PyObject *res; - // _GUARD_BOTH_INT + // _GUARD_BOTH_FLOAT right = stack_pointer[-1]; left = stack_pointer[-2]; { - DEOPT_IF(!PyLong_CheckExact(left), BINARY_OP); - DEOPT_IF(!PyLong_CheckExact(right), BINARY_OP); + DEOPT_IF(!PyFloat_CheckExact(left), BINARY_OP); + DEOPT_IF(!PyFloat_CheckExact(right), BINARY_OP); } - // _BINARY_OP_ADD_INT + /* Skip 1 cache entry */ + // _BINARY_OP_MULTIPLY_FLOAT { STAT_INC(BINARY_OP, hit); - res = _PyLong_Add((PyLongObject *)left, (PyLongObject *)right); - _Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free); - _Py_DECREF_SPECIALIZED(left, (destructor)PyObject_Free); - if (res == NULL) goto pop_2_error; + double dres = + ((PyFloatObject *)left)->ob_fval * + ((PyFloatObject *)right)->ob_fval; + DECREF_INPUTS_AND_REUSE_FLOAT(left, right, dres, res); } - STACK_SHRINK(1); - stack_pointer[-1] = res; - next_instr += 1; + stack_pointer[-2] = res; + stack_pointer += -1; DISPATCH(); } - TARGET(BINARY_OP_SUBTRACT_INT) { + TARGET(BINARY_OP_MULTIPLY_INT) { + frame->instr_ptr = next_instr; + next_instr += 2; + INSTRUCTION_STATS(BINARY_OP_MULTIPLY_INT); + static_assert(INLINE_CACHE_ENTRIES_BINARY_OP == 1, "incorrect cache size"); PyObject *right; PyObject *left; PyObject *res; @@ -428,21 +315,25 @@ DEOPT_IF(!PyLong_CheckExact(left), BINARY_OP); DEOPT_IF(!PyLong_CheckExact(right), BINARY_OP); } - // _BINARY_OP_SUBTRACT_INT + /* Skip 1 cache entry */ + // _BINARY_OP_MULTIPLY_INT { STAT_INC(BINARY_OP, hit); - res = _PyLong_Subtract((PyLongObject *)left, (PyLongObject *)right); + res = _PyLong_Multiply((PyLongObject *)left, (PyLongObject *)right); _Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free); _Py_DECREF_SPECIALIZED(left, (destructor)PyObject_Free); if (res == NULL) goto pop_2_error; } - STACK_SHRINK(1); - stack_pointer[-1] = res; - next_instr += 1; + stack_pointer[-2] = res; + stack_pointer += -1; DISPATCH(); } - TARGET(BINARY_OP_MULTIPLY_FLOAT) { + TARGET(BINARY_OP_SUBTRACT_FLOAT) { + frame->instr_ptr = next_instr; + next_instr += 2; + INSTRUCTION_STATS(BINARY_OP_SUBTRACT_FLOAT); + static_assert(INLINE_CACHE_ENTRIES_BINARY_OP == 1, "incorrect cache size"); PyObject *right; PyObject *left; PyObject *res; @@ -453,164 +344,53 @@ DEOPT_IF(!PyFloat_CheckExact(left), BINARY_OP); DEOPT_IF(!PyFloat_CheckExact(right), BINARY_OP); } - // _BINARY_OP_MULTIPLY_FLOAT + /* Skip 1 cache entry */ + // _BINARY_OP_SUBTRACT_FLOAT { STAT_INC(BINARY_OP, hit); double dres = - ((PyFloatObject *)left)->ob_fval * - ((PyFloatObject *)right)->ob_fval; + ((PyFloatObject *)left)->ob_fval - + ((PyFloatObject *)right)->ob_fval; DECREF_INPUTS_AND_REUSE_FLOAT(left, right, dres, res); } - STACK_SHRINK(1); - stack_pointer[-1] = res; - next_instr += 1; + stack_pointer[-2] = res; + stack_pointer += -1; DISPATCH(); } - TARGET(BINARY_OP_ADD_FLOAT) { + TARGET(BINARY_OP_SUBTRACT_INT) { + frame->instr_ptr = next_instr; + next_instr += 2; + INSTRUCTION_STATS(BINARY_OP_SUBTRACT_INT); + static_assert(INLINE_CACHE_ENTRIES_BINARY_OP == 1, "incorrect cache size"); PyObject *right; PyObject *left; PyObject *res; - // _GUARD_BOTH_FLOAT + // _GUARD_BOTH_INT right = stack_pointer[-1]; left = stack_pointer[-2]; { - DEOPT_IF(!PyFloat_CheckExact(left), BINARY_OP); - DEOPT_IF(!PyFloat_CheckExact(right), BINARY_OP); + DEOPT_IF(!PyLong_CheckExact(left), BINARY_OP); + DEOPT_IF(!PyLong_CheckExact(right), BINARY_OP); } - // _BINARY_OP_ADD_FLOAT + /* Skip 1 cache entry */ + // _BINARY_OP_SUBTRACT_INT { STAT_INC(BINARY_OP, hit); - double dres = - ((PyFloatObject *)left)->ob_fval + - ((PyFloatObject *)right)->ob_fval; - DECREF_INPUTS_AND_REUSE_FLOAT(left, right, dres, res); + res = _PyLong_Subtract((PyLongObject *)left, (PyLongObject *)right); + _Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free); + _Py_DECREF_SPECIALIZED(left, (destructor)PyObject_Free); + if (res == NULL) goto pop_2_error; } - STACK_SHRINK(1); - stack_pointer[-1] = res; - next_instr += 1; - DISPATCH(); - } - - TARGET(BINARY_OP_SUBTRACT_FLOAT) { - PyObject *right; - PyObject *left; - PyObject *res; - // _GUARD_BOTH_FLOAT - right = stack_pointer[-1]; - left = stack_pointer[-2]; - { - DEOPT_IF(!PyFloat_CheckExact(left), BINARY_OP); - DEOPT_IF(!PyFloat_CheckExact(right), BINARY_OP); - } - // _BINARY_OP_SUBTRACT_FLOAT - { - STAT_INC(BINARY_OP, hit); - double dres = - ((PyFloatObject *)left)->ob_fval - - ((PyFloatObject *)right)->ob_fval; - DECREF_INPUTS_AND_REUSE_FLOAT(left, right, dres, res); - } - STACK_SHRINK(1); - stack_pointer[-1] = res; - next_instr += 1; - DISPATCH(); - } - - TARGET(BINARY_OP_ADD_UNICODE) { - PyObject *right; - PyObject *left; - PyObject *res; - // _GUARD_BOTH_UNICODE - right = stack_pointer[-1]; - left = stack_pointer[-2]; - { - DEOPT_IF(!PyUnicode_CheckExact(left), BINARY_OP); - DEOPT_IF(!PyUnicode_CheckExact(right), BINARY_OP); - } - // _BINARY_OP_ADD_UNICODE - { - STAT_INC(BINARY_OP, hit); - res = PyUnicode_Concat(left, right); - _Py_DECREF_SPECIALIZED(left, _PyUnicode_ExactDealloc); - _Py_DECREF_SPECIALIZED(right, _PyUnicode_ExactDealloc); - if (res == NULL) goto pop_2_error; - } - STACK_SHRINK(1); - stack_pointer[-1] = res; - next_instr += 1; - DISPATCH(); - } - - TARGET(BINARY_OP_INPLACE_ADD_UNICODE) { - PyObject *right; - PyObject *left; - // _GUARD_BOTH_UNICODE - right = stack_pointer[-1]; - left = stack_pointer[-2]; - { - DEOPT_IF(!PyUnicode_CheckExact(left), BINARY_OP); - DEOPT_IF(!PyUnicode_CheckExact(right), BINARY_OP); - } - // _BINARY_OP_INPLACE_ADD_UNICODE - { - _Py_CODEUNIT true_next = next_instr[INLINE_CACHE_ENTRIES_BINARY_OP]; - assert(true_next.op.code == STORE_FAST); - PyObject **target_local = &GETLOCAL(true_next.op.arg); - DEOPT_IF(*target_local != left, BINARY_OP); - STAT_INC(BINARY_OP, hit); - /* Handle `left = left + right` or `left += right` for str. - * - * When possible, extend `left` in place rather than - * allocating a new PyUnicodeObject. This attempts to avoid - * quadratic behavior when one neglects to use str.join(). - * - * If `left` has only two references remaining (one from - * the stack, one in the locals), DECREFing `left` leaves - * only the locals reference, so PyUnicode_Append knows - * that the string is safe to mutate. - */ - assert(Py_REFCNT(left) >= 2); - _Py_DECREF_NO_DEALLOC(left); - PyUnicode_Append(target_local, right); - _Py_DECREF_SPECIALIZED(right, _PyUnicode_ExactDealloc); - if (*target_local == NULL) goto pop_2_error; - // The STORE_FAST is already done. - SKIP_OVER(INLINE_CACHE_ENTRIES_BINARY_OP + 1); - } - STACK_SHRINK(2); - DISPATCH(); - } - - TARGET(BINARY_SUBSCR) { - PREDICTED(BINARY_SUBSCR); - static_assert(INLINE_CACHE_ENTRIES_BINARY_SUBSCR == 1, "incorrect cache size"); - PyObject *sub; - PyObject *container; - PyObject *res; - sub = stack_pointer[-1]; - container = stack_pointer[-2]; - #if ENABLE_SPECIALIZATION - _PyBinarySubscrCache *cache = (_PyBinarySubscrCache *)next_instr; - if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) { - next_instr--; - _Py_Specialize_BinarySubscr(container, sub, next_instr); - DISPATCH_SAME_OPARG(); - } - STAT_INC(BINARY_SUBSCR, deferred); - DECREMENT_ADAPTIVE_COUNTER(cache->counter); - #endif /* ENABLE_SPECIALIZATION */ - res = PyObject_GetItem(container, sub); - Py_DECREF(container); - Py_DECREF(sub); - if (res == NULL) goto pop_2_error; - STACK_SHRINK(1); - stack_pointer[-1] = res; - next_instr += 1; + stack_pointer[-2] = res; + stack_pointer += -1; DISPATCH(); } TARGET(BINARY_SLICE) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(BINARY_SLICE); PyObject *stop; PyObject *start; PyObject *container; @@ -630,115 +410,82 @@ } Py_DECREF(container); if (res == NULL) goto pop_3_error; - STACK_SHRINK(2); - stack_pointer[-1] = res; - DISPATCH(); - } - - TARGET(STORE_SLICE) { - PyObject *stop; - PyObject *start; - PyObject *container; - PyObject *v; - stop = stack_pointer[-1]; - start = stack_pointer[-2]; - container = stack_pointer[-3]; - v = stack_pointer[-4]; - PyObject *slice = _PyBuildSlice_ConsumeRefs(start, stop); - int err; - if (slice == NULL) { - err = 1; - } - else { - err = PyObject_SetItem(container, slice, v); - Py_DECREF(slice); - } - Py_DECREF(v); - Py_DECREF(container); - if (err) goto pop_4_error; - STACK_SHRINK(4); - DISPATCH(); - } - - TARGET(BINARY_SUBSCR_LIST_INT) { - PyObject *sub; - PyObject *list; - PyObject *res; - sub = stack_pointer[-1]; - list = stack_pointer[-2]; - DEOPT_IF(!PyLong_CheckExact(sub), BINARY_SUBSCR); - DEOPT_IF(!PyList_CheckExact(list), BINARY_SUBSCR); - - // Deopt unless 0 <= sub < PyList_Size(list) - DEOPT_IF(!_PyLong_IsNonNegativeCompact((PyLongObject *)sub), BINARY_SUBSCR); - Py_ssize_t index = ((PyLongObject*)sub)->long_value.ob_digit[0]; - DEOPT_IF(index >= PyList_GET_SIZE(list), BINARY_SUBSCR); - STAT_INC(BINARY_SUBSCR, hit); - res = PyList_GET_ITEM(list, index); - assert(res != NULL); - Py_INCREF(res); - _Py_DECREF_SPECIALIZED(sub, (destructor)PyObject_Free); - Py_DECREF(list); - STACK_SHRINK(1); - stack_pointer[-1] = res; - next_instr += 1; + stack_pointer[-3] = res; + stack_pointer += -2; DISPATCH(); } - TARGET(BINARY_SUBSCR_TUPLE_INT) { + TARGET(BINARY_SUBSCR) { + frame->instr_ptr = next_instr; + next_instr += 2; + INSTRUCTION_STATS(BINARY_SUBSCR); + PREDICTED(BINARY_SUBSCR); + _Py_CODEUNIT *this_instr = next_instr - 2; PyObject *sub; - PyObject *tuple; + PyObject *container; PyObject *res; + // _SPECIALIZE_BINARY_SUBSCR sub = stack_pointer[-1]; - tuple = stack_pointer[-2]; - DEOPT_IF(!PyLong_CheckExact(sub), BINARY_SUBSCR); - DEOPT_IF(!PyTuple_CheckExact(tuple), BINARY_SUBSCR); - - // Deopt unless 0 <= sub < PyTuple_Size(list) - DEOPT_IF(!_PyLong_IsNonNegativeCompact((PyLongObject *)sub), BINARY_SUBSCR); - Py_ssize_t index = ((PyLongObject*)sub)->long_value.ob_digit[0]; - DEOPT_IF(index >= PyTuple_GET_SIZE(tuple), BINARY_SUBSCR); - STAT_INC(BINARY_SUBSCR, hit); - res = PyTuple_GET_ITEM(tuple, index); - assert(res != NULL); - Py_INCREF(res); - _Py_DECREF_SPECIALIZED(sub, (destructor)PyObject_Free); - Py_DECREF(tuple); - STACK_SHRINK(1); - stack_pointer[-1] = res; - next_instr += 1; + container = stack_pointer[-2]; + { + uint16_t counter = read_u16(&this_instr[1].cache); + TIER_ONE_ONLY + #if ENABLE_SPECIALIZATION + if (ADAPTIVE_COUNTER_IS_ZERO(counter)) { + next_instr = this_instr; + _Py_Specialize_BinarySubscr(container, sub, next_instr); + DISPATCH_SAME_OPARG(); + } + STAT_INC(BINARY_SUBSCR, deferred); + DECREMENT_ADAPTIVE_COUNTER(this_instr[1].cache); + #endif /* ENABLE_SPECIALIZATION */ + } + // _BINARY_SUBSCR + { + res = PyObject_GetItem(container, sub); + Py_DECREF(container); + Py_DECREF(sub); + if (res == NULL) goto pop_2_error; + } + stack_pointer[-2] = res; + stack_pointer += -1; DISPATCH(); } TARGET(BINARY_SUBSCR_DICT) { + frame->instr_ptr = next_instr; + next_instr += 2; + INSTRUCTION_STATS(BINARY_SUBSCR_DICT); + static_assert(INLINE_CACHE_ENTRIES_BINARY_SUBSCR == 1, "incorrect cache size"); PyObject *sub; PyObject *dict; PyObject *res; + /* Skip 1 cache entry */ sub = stack_pointer[-1]; dict = stack_pointer[-2]; DEOPT_IF(!PyDict_CheckExact(dict), BINARY_SUBSCR); STAT_INC(BINARY_SUBSCR, hit); - res = PyDict_GetItemWithError(dict, sub); - if (res == NULL) { - if (!_PyErr_Occurred(tstate)) { - _PyErr_SetKeyError(sub); - } - Py_DECREF(dict); - Py_DECREF(sub); - if (true) goto pop_2_error; + int rc = PyDict_GetItemRef(dict, sub, &res); + if (rc == 0) { + _PyErr_SetKeyError(sub); } - Py_INCREF(res); // Do this before DECREF'ing dict, sub Py_DECREF(dict); Py_DECREF(sub); - STACK_SHRINK(1); - stack_pointer[-1] = res; - next_instr += 1; + if (rc <= 0) goto pop_2_error; + // not found or error + stack_pointer[-2] = res; + stack_pointer += -1; DISPATCH(); } TARGET(BINARY_SUBSCR_GETITEM) { + _Py_CODEUNIT *this_instr = frame->instr_ptr = next_instr; + next_instr += 2; + INSTRUCTION_STATS(BINARY_SUBSCR_GETITEM); + static_assert(INLINE_CACHE_ENTRIES_BINARY_SUBSCR == 1, "incorrect cache size"); PyObject *sub; PyObject *container; + /* Skip 1 cache entry */ sub = stack_pointer[-1]; container = stack_pointer[-2]; DEOPT_IF(tstate->interp->eval_frame, BINARY_SUBSCR); @@ -760,552 +507,1821 @@ STACK_SHRINK(2); new_frame->localsplus[0] = container; new_frame->localsplus[1] = sub; - SKIP_OVER(INLINE_CACHE_ENTRIES_BINARY_SUBSCR); - frame->return_offset = 0; + frame->return_offset = (uint16_t)(next_instr - this_instr); DISPATCH_INLINED(new_frame); - STACK_SHRINK(1); } - TARGET(LIST_APPEND) { - PyObject *v; + TARGET(BINARY_SUBSCR_LIST_INT) { + frame->instr_ptr = next_instr; + next_instr += 2; + INSTRUCTION_STATS(BINARY_SUBSCR_LIST_INT); + static_assert(INLINE_CACHE_ENTRIES_BINARY_SUBSCR == 1, "incorrect cache size"); + PyObject *sub; PyObject *list; - v = stack_pointer[-1]; - list = stack_pointer[-2 - (oparg-1)]; - if (_PyList_AppendTakeRef((PyListObject *)list, v) < 0) goto pop_1_error; - STACK_SHRINK(1); - DISPATCH(); - } - - TARGET(SET_ADD) { - PyObject *v; - PyObject *set; - v = stack_pointer[-1]; - set = stack_pointer[-2 - (oparg-1)]; - int err = PySet_Add(set, v); - Py_DECREF(v); - if (err) goto pop_1_error; - STACK_SHRINK(1); + PyObject *res; + /* Skip 1 cache entry */ + sub = stack_pointer[-1]; + list = stack_pointer[-2]; + DEOPT_IF(!PyLong_CheckExact(sub), BINARY_SUBSCR); + DEOPT_IF(!PyList_CheckExact(list), BINARY_SUBSCR); + // Deopt unless 0 <= sub < PyList_Size(list) + DEOPT_IF(!_PyLong_IsNonNegativeCompact((PyLongObject *)sub), BINARY_SUBSCR); + Py_ssize_t index = ((PyLongObject*)sub)->long_value.ob_digit[0]; + DEOPT_IF(index >= PyList_GET_SIZE(list), BINARY_SUBSCR); + STAT_INC(BINARY_SUBSCR, hit); + res = PyList_GET_ITEM(list, index); + assert(res != NULL); + Py_INCREF(res); + _Py_DECREF_SPECIALIZED(sub, (destructor)PyObject_Free); + Py_DECREF(list); + stack_pointer[-2] = res; + stack_pointer += -1; DISPATCH(); } - TARGET(STORE_SUBSCR) { - PREDICTED(STORE_SUBSCR); - static_assert(INLINE_CACHE_ENTRIES_STORE_SUBSCR == 1, "incorrect cache size"); + TARGET(BINARY_SUBSCR_STR_INT) { + frame->instr_ptr = next_instr; + next_instr += 2; + INSTRUCTION_STATS(BINARY_SUBSCR_STR_INT); + static_assert(INLINE_CACHE_ENTRIES_BINARY_SUBSCR == 1, "incorrect cache size"); PyObject *sub; - PyObject *container; - PyObject *v; + PyObject *str; + PyObject *res; + /* Skip 1 cache entry */ sub = stack_pointer[-1]; - container = stack_pointer[-2]; - v = stack_pointer[-3]; - #if ENABLE_SPECIALIZATION - _PyStoreSubscrCache *cache = (_PyStoreSubscrCache *)next_instr; - if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) { - next_instr--; - _Py_Specialize_StoreSubscr(container, sub, next_instr); - DISPATCH_SAME_OPARG(); - } - STAT_INC(STORE_SUBSCR, deferred); - DECREMENT_ADAPTIVE_COUNTER(cache->counter); - #endif /* ENABLE_SPECIALIZATION */ - /* container[sub] = v */ - int err = PyObject_SetItem(container, sub, v); - Py_DECREF(v); - Py_DECREF(container); - Py_DECREF(sub); - if (err) goto pop_3_error; - STACK_SHRINK(3); - next_instr += 1; + str = stack_pointer[-2]; + DEOPT_IF(!PyLong_CheckExact(sub), BINARY_SUBSCR); + DEOPT_IF(!PyUnicode_CheckExact(str), BINARY_SUBSCR); + DEOPT_IF(!_PyLong_IsNonNegativeCompact((PyLongObject *)sub), BINARY_SUBSCR); + Py_ssize_t index = ((PyLongObject*)sub)->long_value.ob_digit[0]; + DEOPT_IF(PyUnicode_GET_LENGTH(str) <= index, BINARY_SUBSCR); + // Specialize for reading an ASCII character from any string: + Py_UCS4 c = PyUnicode_READ_CHAR(str, index); + DEOPT_IF(Py_ARRAY_LENGTH(_Py_SINGLETON(strings).ascii) <= c, BINARY_SUBSCR); + STAT_INC(BINARY_SUBSCR, hit); + res = (PyObject*)&_Py_SINGLETON(strings).ascii[c]; + _Py_DECREF_SPECIALIZED(sub, (destructor)PyObject_Free); + Py_DECREF(str); + stack_pointer[-2] = res; + stack_pointer += -1; DISPATCH(); } - TARGET(STORE_SUBSCR_LIST_INT) { + TARGET(BINARY_SUBSCR_TUPLE_INT) { + frame->instr_ptr = next_instr; + next_instr += 2; + INSTRUCTION_STATS(BINARY_SUBSCR_TUPLE_INT); + static_assert(INLINE_CACHE_ENTRIES_BINARY_SUBSCR == 1, "incorrect cache size"); PyObject *sub; - PyObject *list; - PyObject *value; + PyObject *tuple; + PyObject *res; + /* Skip 1 cache entry */ sub = stack_pointer[-1]; - list = stack_pointer[-2]; - value = stack_pointer[-3]; - DEOPT_IF(!PyLong_CheckExact(sub), STORE_SUBSCR); - DEOPT_IF(!PyList_CheckExact(list), STORE_SUBSCR); - - // Ensure nonnegative, zero-or-one-digit ints. - DEOPT_IF(!_PyLong_IsNonNegativeCompact((PyLongObject *)sub), STORE_SUBSCR); + tuple = stack_pointer[-2]; + DEOPT_IF(!PyLong_CheckExact(sub), BINARY_SUBSCR); + DEOPT_IF(!PyTuple_CheckExact(tuple), BINARY_SUBSCR); + // Deopt unless 0 <= sub < PyTuple_Size(list) + DEOPT_IF(!_PyLong_IsNonNegativeCompact((PyLongObject *)sub), BINARY_SUBSCR); Py_ssize_t index = ((PyLongObject*)sub)->long_value.ob_digit[0]; - // Ensure index < len(list) - DEOPT_IF(index >= PyList_GET_SIZE(list), STORE_SUBSCR); - STAT_INC(STORE_SUBSCR, hit); - - PyObject *old_value = PyList_GET_ITEM(list, index); - PyList_SET_ITEM(list, index, value); - assert(old_value != NULL); - Py_DECREF(old_value); + DEOPT_IF(index >= PyTuple_GET_SIZE(tuple), BINARY_SUBSCR); + STAT_INC(BINARY_SUBSCR, hit); + res = PyTuple_GET_ITEM(tuple, index); + assert(res != NULL); + Py_INCREF(res); _Py_DECREF_SPECIALIZED(sub, (destructor)PyObject_Free); - Py_DECREF(list); - STACK_SHRINK(3); - next_instr += 1; + Py_DECREF(tuple); + stack_pointer[-2] = res; + stack_pointer += -1; DISPATCH(); } - TARGET(STORE_SUBSCR_DICT) { - PyObject *sub; - PyObject *dict; - PyObject *value; - sub = stack_pointer[-1]; - dict = stack_pointer[-2]; - value = stack_pointer[-3]; - DEOPT_IF(!PyDict_CheckExact(dict), STORE_SUBSCR); - STAT_INC(STORE_SUBSCR, hit); - int err = _PyDict_SetItem_Take2((PyDictObject *)dict, sub, value); - Py_DECREF(dict); - if (err) goto pop_3_error; - STACK_SHRINK(3); + TARGET(BUILD_CONST_KEY_MAP) { + frame->instr_ptr = next_instr; next_instr += 1; + INSTRUCTION_STATS(BUILD_CONST_KEY_MAP); + PyObject *keys; + PyObject **values; + PyObject *map; + keys = stack_pointer[-1]; + values = &stack_pointer[-1 - oparg]; + if (!PyTuple_CheckExact(keys) || + PyTuple_GET_SIZE(keys) != (Py_ssize_t)oparg) { + _PyErr_SetString(tstate, PyExc_SystemError, + "bad BUILD_CONST_KEY_MAP keys argument"); + GOTO_ERROR(error); // Pop the keys and values. + } + map = _PyDict_FromItems( + &PyTuple_GET_ITEM(keys, 0), 1, + values, 1, oparg); + for (int _i = oparg; --_i >= 0;) { + Py_DECREF(values[_i]); + } + Py_DECREF(keys); + if (map == NULL) { stack_pointer += -1 - oparg; goto error; } + stack_pointer[-1 - oparg] = map; + stack_pointer += -oparg; DISPATCH(); } - TARGET(DELETE_SUBSCR) { - PyObject *sub; - PyObject *container; - sub = stack_pointer[-1]; - container = stack_pointer[-2]; - /* del container[sub] */ - int err = PyObject_DelItem(container, sub); - Py_DECREF(container); - Py_DECREF(sub); - if (err) goto pop_2_error; - STACK_SHRINK(2); - DISPATCH(); - } - - TARGET(CALL_INTRINSIC_1) { - PyObject *value; - PyObject *res; - value = stack_pointer[-1]; - assert(oparg <= MAX_INTRINSIC_1); - res = _PyIntrinsics_UnaryFunctions[oparg].func(tstate, value); - Py_DECREF(value); - if (res == NULL) goto pop_1_error; - stack_pointer[-1] = res; + TARGET(BUILD_LIST) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(BUILD_LIST); + PyObject **values; + PyObject *list; + values = &stack_pointer[-oparg]; + list = _PyList_FromArraySteal(values, oparg); + if (list == NULL) { stack_pointer += -oparg; goto error; } + stack_pointer[-oparg] = list; + stack_pointer += 1 - oparg; DISPATCH(); } - TARGET(CALL_INTRINSIC_2) { - PyObject *value1; - PyObject *value2; - PyObject *res; - value1 = stack_pointer[-1]; - value2 = stack_pointer[-2]; - assert(oparg <= MAX_INTRINSIC_2); - res = _PyIntrinsics_BinaryFunctions[oparg].func(tstate, value2, value1); - Py_DECREF(value2); - Py_DECREF(value1); - if (res == NULL) goto pop_2_error; - STACK_SHRINK(1); - stack_pointer[-1] = res; + TARGET(BUILD_MAP) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(BUILD_MAP); + PyObject **values; + PyObject *map; + values = &stack_pointer[-oparg*2]; + map = _PyDict_FromItems( + values, 2, + values+1, 2, + oparg); + for (int _i = oparg*2; --_i >= 0;) { + Py_DECREF(values[_i]); + } + if (map == NULL) { stack_pointer += -oparg*2; goto error; } + stack_pointer[-oparg*2] = map; + stack_pointer += 1 - oparg*2; DISPATCH(); } - TARGET(RAISE_VARARGS) { - PyObject **args; - args = stack_pointer - oparg; - PyObject *cause = NULL, *exc = NULL; - switch (oparg) { - case 2: - cause = args[1]; - /* fall through */ - case 1: - exc = args[0]; - /* fall through */ - case 0: - if (do_raise(tstate, exc, cause)) { - assert(oparg == 0); - monitor_reraise(tstate, frame, next_instr-1); - goto exception_unwind; - } - break; - default: - _PyErr_SetString(tstate, PyExc_SystemError, - "bad RAISE_VARARGS oparg"); - break; + TARGET(BUILD_SET) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(BUILD_SET); + PyObject **values; + PyObject *set; + values = &stack_pointer[-oparg]; + set = PySet_New(NULL); + if (set == NULL) + GOTO_ERROR(error); + int err = 0; + for (int i = 0; i < oparg; i++) { + PyObject *item = values[i]; + if (err == 0) + err = PySet_Add(set, item); + Py_DECREF(item); } - if (true) { STACK_SHRINK(oparg); goto error; } - STACK_SHRINK(oparg); + if (err != 0) { + Py_DECREF(set); + if (true) { stack_pointer += -oparg; goto error; } + } + stack_pointer[-oparg] = set; + stack_pointer += 1 - oparg; + DISPATCH(); } - TARGET(INTERPRETER_EXIT) { - PyObject *retval; - retval = stack_pointer[-1]; - assert(frame == &entry_frame); - assert(_PyFrame_IsIncomplete(frame)); - /* Restore previous cframe and return. */ - tstate->cframe = cframe.previous; - assert(tstate->cframe->current_frame == frame->previous); - assert(!_PyErr_Occurred(tstate)); - tstate->c_recursion_remaining += PY_EVAL_C_STACK_UNITS; - return retval; - STACK_SHRINK(1); + TARGET(BUILD_SLICE) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(BUILD_SLICE); + PyObject *step = NULL; + PyObject *stop; + PyObject *start; + PyObject *slice; + if (oparg == 3) { step = stack_pointer[-((oparg == 3) ? 1 : 0)]; } + stop = stack_pointer[-1 - ((oparg == 3) ? 1 : 0)]; + start = stack_pointer[-2 - ((oparg == 3) ? 1 : 0)]; + slice = PySlice_New(start, stop, step); + Py_DECREF(start); + Py_DECREF(stop); + Py_XDECREF(step); + if (slice == NULL) { stack_pointer += -2 - ((oparg == 3) ? 1 : 0); goto error; } + stack_pointer[-2 - ((oparg == 3) ? 1 : 0)] = slice; + stack_pointer += -1 - ((oparg == 3) ? 1 : 0); + DISPATCH(); } - TARGET(RETURN_VALUE) { - PyObject *retval; - retval = stack_pointer[-1]; - STACK_SHRINK(1); - assert(EMPTY()); - _PyFrame_SetStackPointer(frame, stack_pointer); - _Py_LeaveRecursiveCallPy(tstate); - assert(frame != &entry_frame); - // GH-99729: We need to unlink the frame *before* clearing it: - _PyInterpreterFrame *dying = frame; - frame = cframe.current_frame = dying->previous; - _PyEvalFrameClearAndPop(tstate, dying); - frame->prev_instr += frame->return_offset; - _PyFrame_StackPush(frame, retval); - goto resume_frame; - STACK_SHRINK(1); + TARGET(BUILD_STRING) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(BUILD_STRING); + PyObject **pieces; + PyObject *str; + pieces = &stack_pointer[-oparg]; + str = _PyUnicode_JoinArray(&_Py_STR(empty), pieces, oparg); + for (int _i = oparg; --_i >= 0;) { + Py_DECREF(pieces[_i]); + } + if (str == NULL) { stack_pointer += -oparg; goto error; } + stack_pointer[-oparg] = str; + stack_pointer += 1 - oparg; + DISPATCH(); } - TARGET(INSTRUMENTED_RETURN_VALUE) { - PyObject *retval; - retval = stack_pointer[-1]; - int err = _Py_call_instrumentation_arg( - tstate, PY_MONITORING_EVENT_PY_RETURN, - frame, next_instr-1, retval); - if (err) goto error; - STACK_SHRINK(1); - assert(EMPTY()); - _PyFrame_SetStackPointer(frame, stack_pointer); - _Py_LeaveRecursiveCallPy(tstate); - assert(frame != &entry_frame); - // GH-99729: We need to unlink the frame *before* clearing it: - _PyInterpreterFrame *dying = frame; - frame = cframe.current_frame = dying->previous; - _PyEvalFrameClearAndPop(tstate, dying); - frame->prev_instr += frame->return_offset; - _PyFrame_StackPush(frame, retval); - goto resume_frame; - STACK_SHRINK(1); + TARGET(BUILD_TUPLE) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(BUILD_TUPLE); + PyObject **values; + PyObject *tup; + values = &stack_pointer[-oparg]; + tup = _PyTuple_FromArraySteal(values, oparg); + if (tup == NULL) { stack_pointer += -oparg; goto error; } + stack_pointer[-oparg] = tup; + stack_pointer += 1 - oparg; + DISPATCH(); } - TARGET(RETURN_CONST) { - PyObject *retval = GETITEM(FRAME_CO_CONSTS, oparg); - Py_INCREF(retval); - assert(EMPTY()); - _PyFrame_SetStackPointer(frame, stack_pointer); - _Py_LeaveRecursiveCallPy(tstate); - assert(frame != &entry_frame); - // GH-99729: We need to unlink the frame *before* clearing it: - _PyInterpreterFrame *dying = frame; - frame = cframe.current_frame = dying->previous; - _PyEvalFrameClearAndPop(tstate, dying); - frame->prev_instr += frame->return_offset; - _PyFrame_StackPush(frame, retval); - goto resume_frame; + TARGET(CACHE) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(CACHE); + TIER_ONE_ONLY + assert(0 && "Executing a cache."); + Py_UNREACHABLE(); } - TARGET(INSTRUMENTED_RETURN_CONST) { - PyObject *retval = GETITEM(FRAME_CO_CONSTS, oparg); - int err = _Py_call_instrumentation_arg( - tstate, PY_MONITORING_EVENT_PY_RETURN, - frame, next_instr-1, retval); - if (err) goto error; - Py_INCREF(retval); - assert(EMPTY()); - _PyFrame_SetStackPointer(frame, stack_pointer); - _Py_LeaveRecursiveCallPy(tstate); - assert(frame != &entry_frame); - // GH-99729: We need to unlink the frame *before* clearing it: - _PyInterpreterFrame *dying = frame; - frame = cframe.current_frame = dying->previous; - _PyEvalFrameClearAndPop(tstate, dying); - frame->prev_instr += frame->return_offset; - _PyFrame_StackPush(frame, retval); - goto resume_frame; + TARGET(CALL) { + frame->instr_ptr = next_instr; + next_instr += 4; + INSTRUCTION_STATS(CALL); + PREDICTED(CALL); + _Py_CODEUNIT *this_instr = next_instr - 4; + PyObject **args; + PyObject *self_or_null; + PyObject *callable; + PyObject *res; + // _SPECIALIZE_CALL + args = &stack_pointer[-oparg]; + self_or_null = stack_pointer[-1 - oparg]; + callable = stack_pointer[-2 - oparg]; + { + uint16_t counter = read_u16(&this_instr[1].cache); + TIER_ONE_ONLY + #if ENABLE_SPECIALIZATION + if (ADAPTIVE_COUNTER_IS_ZERO(counter)) { + next_instr = this_instr; + _Py_Specialize_Call(callable, next_instr, oparg + (self_or_null != NULL)); + DISPATCH_SAME_OPARG(); + } + STAT_INC(CALL, deferred); + DECREMENT_ADAPTIVE_COUNTER(this_instr[1].cache); + #endif /* ENABLE_SPECIALIZATION */ + } + /* Skip 2 cache entries */ + // _CALL + { + // oparg counts all of the args, but *not* self: + int total_args = oparg; + if (self_or_null != NULL) { + args--; + total_args++; + } + else if (Py_TYPE(callable) == &PyMethod_Type) { + args--; + total_args++; + PyObject *self = ((PyMethodObject *)callable)->im_self; + args[0] = Py_NewRef(self); + PyObject *method = ((PyMethodObject *)callable)->im_func; + args[-1] = Py_NewRef(method); + Py_DECREF(callable); + callable = method; + } + // Check if the call can be inlined or not + if (Py_TYPE(callable) == &PyFunction_Type && + tstate->interp->eval_frame == NULL && + ((PyFunctionObject *)callable)->vectorcall == _PyFunction_Vectorcall) + { + int code_flags = ((PyCodeObject*)PyFunction_GET_CODE(callable))->co_flags; + PyObject *locals = code_flags & CO_OPTIMIZED ? NULL : Py_NewRef(PyFunction_GET_GLOBALS(callable)); + _PyInterpreterFrame *new_frame = _PyEvalFramePushAndInit( + tstate, (PyFunctionObject *)callable, locals, + args, total_args, NULL + ); + // Manipulate stack directly since we leave using DISPATCH_INLINED(). + STACK_SHRINK(oparg + 2); + // The frame has stolen all the arguments from the stack, + // so there is no need to clean them up. + if (new_frame == NULL) { + GOTO_ERROR(error); + } + frame->return_offset = (uint16_t)(next_instr - this_instr); + DISPATCH_INLINED(new_frame); + } + /* Callable is not a normal Python function */ + res = PyObject_Vectorcall( + callable, args, + total_args | PY_VECTORCALL_ARGUMENTS_OFFSET, + NULL); + if (opcode == INSTRUMENTED_CALL) { + PyObject *arg = total_args == 0 ? + &_PyInstrumentation_MISSING : args[0]; + if (res == NULL) { + _Py_call_instrumentation_exc2( + tstate, PY_MONITORING_EVENT_C_RAISE, + frame, this_instr, callable, arg); + } + else { + int err = _Py_call_instrumentation_2args( + tstate, PY_MONITORING_EVENT_C_RETURN, + frame, this_instr, callable, arg); + if (err < 0) { + Py_CLEAR(res); + } + } + } + assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); + Py_DECREF(callable); + for (int i = 0; i < total_args; i++) { + Py_DECREF(args[i]); + } + if (res == NULL) { stack_pointer += -2 - oparg; goto error; } + } + stack_pointer[-2 - oparg] = res; + stack_pointer += -1 - oparg; + CHECK_EVAL_BREAKER(); + DISPATCH(); } - TARGET(GET_AITER) { - PyObject *obj; - PyObject *iter; - obj = stack_pointer[-1]; - unaryfunc getter = NULL; - PyTypeObject *type = Py_TYPE(obj); - - if (type->tp_as_async != NULL) { - getter = type->tp_as_async->am_aiter; - } - - if (getter == NULL) { - _PyErr_Format(tstate, PyExc_TypeError, - "'async for' requires an object with " - "__aiter__ method, got %.100s", - type->tp_name); - Py_DECREF(obj); - if (true) goto pop_1_error; + TARGET(CALL_ALLOC_AND_ENTER_INIT) { + _Py_CODEUNIT *this_instr = frame->instr_ptr = next_instr; + next_instr += 4; + INSTRUCTION_STATS(CALL_ALLOC_AND_ENTER_INIT); + static_assert(INLINE_CACHE_ENTRIES_CALL == 3, "incorrect cache size"); + PyObject **args; + PyObject *null; + PyObject *callable; + /* Skip 1 cache entry */ + /* Skip 2 cache entries */ + args = &stack_pointer[-oparg]; + null = stack_pointer[-1 - oparg]; + callable = stack_pointer[-2 - oparg]; + /* This instruction does the following: + * 1. Creates the object (by calling ``object.__new__``) + * 2. Pushes a shim frame to the frame stack (to cleanup after ``__init__``) + * 3. Pushes the frame for ``__init__`` to the frame stack + * */ + _PyCallCache *cache = (_PyCallCache *)&this_instr[1]; + DEOPT_IF(null != NULL, CALL); + DEOPT_IF(!PyType_Check(callable), CALL); + PyTypeObject *tp = (PyTypeObject *)callable; + DEOPT_IF(tp->tp_version_tag != read_u32(cache->func_version), CALL); + PyHeapTypeObject *cls = (PyHeapTypeObject *)callable; + PyFunctionObject *init = (PyFunctionObject *)cls->_spec_cache.init; + PyCodeObject *code = (PyCodeObject *)init->func_code; + DEOPT_IF(code->co_argcount != oparg+1, CALL); + DEOPT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize + _Py_InitCleanup.co_framesize), CALL); + STAT_INC(CALL, hit); + PyObject *self = _PyType_NewManagedObject(tp); + if (self == NULL) { + GOTO_ERROR(error); } - - iter = (*getter)(obj); - Py_DECREF(obj); - if (iter == NULL) goto pop_1_error; - - if (Py_TYPE(iter)->tp_as_async == NULL || - Py_TYPE(iter)->tp_as_async->am_anext == NULL) { - - _PyErr_Format(tstate, PyExc_TypeError, - "'async for' received an object from __aiter__ " - "that does not implement __anext__: %.100s", - Py_TYPE(iter)->tp_name); - Py_DECREF(iter); - if (true) goto pop_1_error; + Py_DECREF(tp); + _PyInterpreterFrame *shim = _PyFrame_PushTrampolineUnchecked( + tstate, (PyCodeObject *)&_Py_InitCleanup, 1); + assert(_PyCode_CODE((PyCodeObject *)shim->f_executable)[0].op.code == EXIT_INIT_CHECK); + /* Push self onto stack of shim */ + Py_INCREF(self); + shim->localsplus[0] = self; + Py_INCREF(init); + _PyInterpreterFrame *init_frame = _PyFrame_PushUnchecked(tstate, init, oparg+1); + /* Copy self followed by args to __init__ frame */ + init_frame->localsplus[0] = self; + for (int i = 0; i < oparg; i++) { + init_frame->localsplus[i+1] = args[i]; } - stack_pointer[-1] = iter; - DISPATCH(); + frame->return_offset = (uint16_t)(next_instr - this_instr); + STACK_SHRINK(oparg+2); + _PyFrame_SetStackPointer(frame, stack_pointer); + /* Link frames */ + init_frame->previous = shim; + shim->previous = frame; + frame = tstate->current_frame = init_frame; + CALL_STAT_INC(inlined_py_calls); + /* Account for pushing the extra frame. + * We don't check recursion depth here, + * as it will be checked after start_frame */ + tstate->py_recursion_remaining--; + goto start_frame; } - TARGET(GET_ANEXT) { - PyObject *aiter; - PyObject *awaitable; - aiter = stack_pointer[-1]; - unaryfunc getter = NULL; - PyObject *next_iter = NULL; - PyTypeObject *type = Py_TYPE(aiter); - - if (PyAsyncGen_CheckExact(aiter)) { - awaitable = type->tp_as_async->am_anext(aiter); - if (awaitable == NULL) { - goto error; - } - } else { - if (type->tp_as_async != NULL){ - getter = type->tp_as_async->am_anext; - } - - if (getter != NULL) { - next_iter = (*getter)(aiter); - if (next_iter == NULL) { - goto error; - } + TARGET(CALL_BOUND_METHOD_EXACT_ARGS) { + _Py_CODEUNIT *this_instr = frame->instr_ptr = next_instr; + next_instr += 4; + INSTRUCTION_STATS(CALL_BOUND_METHOD_EXACT_ARGS); + static_assert(INLINE_CACHE_ENTRIES_CALL == 3, "incorrect cache size"); + PyObject *null; + PyObject *callable; + PyObject *func; + PyObject *self; + PyObject *self_or_null; + PyObject **args; + _PyInterpreterFrame *new_frame; + /* Skip 1 cache entry */ + // _CHECK_PEP_523 + { + DEOPT_IF(tstate->interp->eval_frame, CALL); + } + // _CHECK_CALL_BOUND_METHOD_EXACT_ARGS + null = stack_pointer[-1 - oparg]; + callable = stack_pointer[-2 - oparg]; + { + DEOPT_IF(null != NULL, CALL); + DEOPT_IF(Py_TYPE(callable) != &PyMethod_Type, CALL); + } + // _INIT_CALL_BOUND_METHOD_EXACT_ARGS + { + STAT_INC(CALL, hit); + self = Py_NewRef(((PyMethodObject *)callable)->im_self); + stack_pointer[-1 - oparg] = self; // Patch stack as it is used by _INIT_CALL_PY_EXACT_ARGS + func = Py_NewRef(((PyMethodObject *)callable)->im_func); + stack_pointer[-2 - oparg] = func; // This is used by CALL, upon deoptimization + Py_DECREF(callable); + } + // _CHECK_FUNCTION_EXACT_ARGS + self_or_null = self; + callable = func; + { + uint32_t func_version = read_u32(&this_instr[2].cache); + DEOPT_IF(!PyFunction_Check(callable), CALL); + PyFunctionObject *func = (PyFunctionObject *)callable; + DEOPT_IF(func->func_version != func_version, CALL); + PyCodeObject *code = (PyCodeObject *)func->func_code; + DEOPT_IF(code->co_argcount != oparg + (self_or_null != NULL), CALL); + } + // _CHECK_STACK_SPACE + { + PyFunctionObject *func = (PyFunctionObject *)callable; + PyCodeObject *code = (PyCodeObject *)func->func_code; + DEOPT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize), CALL); + DEOPT_IF(tstate->py_recursion_remaining <= 1, CALL); + } + // _INIT_CALL_PY_EXACT_ARGS + args = &stack_pointer[-oparg]; + self_or_null = stack_pointer[-1 - oparg]; + { + int argcount = oparg; + if (self_or_null != NULL) { + args--; + argcount++; } - else { - _PyErr_Format(tstate, PyExc_TypeError, - "'async for' requires an iterator with " - "__anext__ method, got %.100s", - type->tp_name); - goto error; + STAT_INC(CALL, hit); + PyFunctionObject *func = (PyFunctionObject *)callable; + new_frame = _PyFrame_PushUnchecked(tstate, func, argcount); + for (int i = 0; i < argcount; i++) { + new_frame->localsplus[i] = args[i]; } - - awaitable = _PyCoro_GetAwaitableIter(next_iter); - if (awaitable == NULL) { - _PyErr_FormatFromCause( - PyExc_TypeError, - "'async for' received an invalid object " - "from __anext__: %.100s", - Py_TYPE(next_iter)->tp_name); - - Py_DECREF(next_iter); - goto error; - } else { - Py_DECREF(next_iter); + } + // _SAVE_RETURN_OFFSET + { + #if TIER_ONE + frame->return_offset = (uint16_t)(next_instr - this_instr); + #endif + #if TIER_TWO + frame->return_offset = oparg; + #endif + } + // _PUSH_FRAME + { + // Write it out explicitly because it's subtly different. + // Eventually this should be the only occurrence of this code. + assert(tstate->interp->eval_frame == NULL); + stack_pointer += -2 - oparg; + _PyFrame_SetStackPointer(frame, stack_pointer); + new_frame->previous = frame; + CALL_STAT_INC(inlined_py_calls); + frame = tstate->current_frame = new_frame; + tstate->py_recursion_remaining--; + LOAD_SP(); + LOAD_IP(0); + #if LLTRACE && TIER_ONE + lltrace = maybe_lltrace_resume_frame(frame, &entry_frame, GLOBALS()); + if (lltrace < 0) { + goto exit_unwind; } + #endif } - STACK_GROW(1); - stack_pointer[-1] = awaitable; + stack_pointer += ((0) ? 1 : 0); DISPATCH(); } - TARGET(GET_AWAITABLE) { - PyObject *iterable; - PyObject *iter; - iterable = stack_pointer[-1]; - iter = _PyCoro_GetAwaitableIter(iterable); - - if (iter == NULL) { - _PyEval_FormatAwaitableError(tstate, Py_TYPE(iterable), oparg); + TARGET(CALL_BUILTIN_CLASS) { + frame->instr_ptr = next_instr; + next_instr += 4; + INSTRUCTION_STATS(CALL_BUILTIN_CLASS); + static_assert(INLINE_CACHE_ENTRIES_CALL == 3, "incorrect cache size"); + PyObject **args; + PyObject *self_or_null; + PyObject *callable; + PyObject *res; + /* Skip 1 cache entry */ + /* Skip 2 cache entries */ + args = &stack_pointer[-oparg]; + self_or_null = stack_pointer[-1 - oparg]; + callable = stack_pointer[-2 - oparg]; + int total_args = oparg; + if (self_or_null != NULL) { + args--; + total_args++; } - - Py_DECREF(iterable); - - if (iter != NULL && PyCoro_CheckExact(iter)) { - PyObject *yf = _PyGen_yf((PyGenObject*)iter); - if (yf != NULL) { - /* `iter` is a coroutine object that is being - awaited, `yf` is a pointer to the current awaitable - being awaited on. */ - Py_DECREF(yf); - Py_CLEAR(iter); - _PyErr_SetString(tstate, PyExc_RuntimeError, - "coroutine is being awaited already"); - /* The code below jumps to `error` if `iter` is NULL. */ - } + DEOPT_IF(!PyType_Check(callable), CALL); + PyTypeObject *tp = (PyTypeObject *)callable; + DEOPT_IF(tp->tp_vectorcall == NULL, CALL); + STAT_INC(CALL, hit); + res = tp->tp_vectorcall((PyObject *)tp, args, total_args, NULL); + /* Free the arguments. */ + for (int i = 0; i < total_args; i++) { + Py_DECREF(args[i]); } - - if (iter == NULL) goto pop_1_error; - stack_pointer[-1] = iter; + Py_DECREF(tp); + if (res == NULL) { stack_pointer += -2 - oparg; goto error; } + stack_pointer[-2 - oparg] = res; + stack_pointer += -1 - oparg; + CHECK_EVAL_BREAKER(); DISPATCH(); } - TARGET(SEND) { - PREDICTED(SEND); - static_assert(INLINE_CACHE_ENTRIES_SEND == 1, "incorrect cache size"); - PyObject *v; - PyObject *receiver; - PyObject *retval; - v = stack_pointer[-1]; - receiver = stack_pointer[-2]; - #if ENABLE_SPECIALIZATION - _PySendCache *cache = (_PySendCache *)next_instr; - if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) { - next_instr--; - _Py_Specialize_Send(receiver, next_instr); - DISPATCH_SAME_OPARG(); - } - STAT_INC(SEND, deferred); - DECREMENT_ADAPTIVE_COUNTER(cache->counter); - #endif /* ENABLE_SPECIALIZATION */ - assert(frame != &entry_frame); - if ((tstate->interp->eval_frame == NULL) && - (Py_TYPE(receiver) == &PyGen_Type || Py_TYPE(receiver) == &PyCoro_Type) && - ((PyGenObject *)receiver)->gi_frame_state < FRAME_EXECUTING) - { - PyGenObject *gen = (PyGenObject *)receiver; - _PyInterpreterFrame *gen_frame = (_PyInterpreterFrame *)gen->gi_iframe; - frame->return_offset = oparg; - STACK_SHRINK(1); - _PyFrame_StackPush(gen_frame, v); - gen->gi_frame_state = FRAME_EXECUTING; - gen->gi_exc_state.previous_item = tstate->exc_info; - tstate->exc_info = &gen->gi_exc_state; - SKIP_OVER(INLINE_CACHE_ENTRIES_SEND); - DISPATCH_INLINED(gen_frame); + TARGET(CALL_BUILTIN_FAST) { + frame->instr_ptr = next_instr; + next_instr += 4; + INSTRUCTION_STATS(CALL_BUILTIN_FAST); + static_assert(INLINE_CACHE_ENTRIES_CALL == 3, "incorrect cache size"); + PyObject **args; + PyObject *self_or_null; + PyObject *callable; + PyObject *res; + /* Skip 1 cache entry */ + /* Skip 2 cache entries */ + args = &stack_pointer[-oparg]; + self_or_null = stack_pointer[-1 - oparg]; + callable = stack_pointer[-2 - oparg]; + /* Builtin METH_FASTCALL functions, without keywords */ + int total_args = oparg; + if (self_or_null != NULL) { + args--; + total_args++; } - if (Py_IsNone(v) && PyIter_Check(receiver)) { - retval = Py_TYPE(receiver)->tp_iternext(receiver); + DEOPT_IF(!PyCFunction_CheckExact(callable), CALL); + DEOPT_IF(PyCFunction_GET_FLAGS(callable) != METH_FASTCALL, CALL); + STAT_INC(CALL, hit); + PyCFunction cfunc = PyCFunction_GET_FUNCTION(callable); + /* res = func(self, args, nargs) */ + res = ((_PyCFunctionFast)(void(*)(void))cfunc)( + PyCFunction_GET_SELF(callable), + args, + total_args); + assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); + /* Free the arguments. */ + for (int i = 0; i < total_args; i++) { + Py_DECREF(args[i]); } - else { - retval = PyObject_CallMethodOneArg(receiver, &_Py_ID(send), v); + Py_DECREF(callable); + if (res == NULL) { stack_pointer += -2 - oparg; goto error; } + /* Not deopting because this doesn't mean our optimization was + wrong. `res` can be NULL for valid reasons. Eg. getattr(x, + 'invalid'). In those cases an exception is set, so we must + handle it. + */ + stack_pointer[-2 - oparg] = res; + stack_pointer += -1 - oparg; + CHECK_EVAL_BREAKER(); + DISPATCH(); + } + + TARGET(CALL_BUILTIN_FAST_WITH_KEYWORDS) { + frame->instr_ptr = next_instr; + next_instr += 4; + INSTRUCTION_STATS(CALL_BUILTIN_FAST_WITH_KEYWORDS); + static_assert(INLINE_CACHE_ENTRIES_CALL == 3, "incorrect cache size"); + PyObject **args; + PyObject *self_or_null; + PyObject *callable; + PyObject *res; + /* Skip 1 cache entry */ + /* Skip 2 cache entries */ + args = &stack_pointer[-oparg]; + self_or_null = stack_pointer[-1 - oparg]; + callable = stack_pointer[-2 - oparg]; + /* Builtin METH_FASTCALL | METH_KEYWORDS functions */ + int total_args = oparg; + if (self_or_null != NULL) { + args--; + total_args++; } - if (retval == NULL) { - if (_PyErr_ExceptionMatches(tstate, PyExc_StopIteration) - ) { - monitor_raise(tstate, frame, next_instr-1); - } - if (_PyGen_FetchStopIterationValue(&retval) == 0) { - assert(retval != NULL); - JUMPBY(oparg); - } - else { - goto error; - } + DEOPT_IF(!PyCFunction_CheckExact(callable), CALL); + DEOPT_IF(PyCFunction_GET_FLAGS(callable) != (METH_FASTCALL | METH_KEYWORDS), CALL); + STAT_INC(CALL, hit); + /* res = func(self, args, nargs, kwnames) */ + _PyCFunctionFastWithKeywords cfunc = + (_PyCFunctionFastWithKeywords)(void(*)(void)) + PyCFunction_GET_FUNCTION(callable); + res = cfunc(PyCFunction_GET_SELF(callable), args, total_args, NULL); + assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); + /* Free the arguments. */ + for (int i = 0; i < total_args; i++) { + Py_DECREF(args[i]); } - Py_DECREF(v); - stack_pointer[-1] = retval; - next_instr += 1; + Py_DECREF(callable); + if (res == NULL) { stack_pointer += -2 - oparg; goto error; } + stack_pointer[-2 - oparg] = res; + stack_pointer += -1 - oparg; + CHECK_EVAL_BREAKER(); DISPATCH(); } - TARGET(SEND_GEN) { - PyObject *v; - PyObject *receiver; - v = stack_pointer[-1]; - receiver = stack_pointer[-2]; - DEOPT_IF(tstate->interp->eval_frame, SEND); - PyGenObject *gen = (PyGenObject *)receiver; - DEOPT_IF(Py_TYPE(gen) != &PyGen_Type && - Py_TYPE(gen) != &PyCoro_Type, SEND); - DEOPT_IF(gen->gi_frame_state >= FRAME_EXECUTING, SEND); - STAT_INC(SEND, hit); - _PyInterpreterFrame *gen_frame = (_PyInterpreterFrame *)gen->gi_iframe; - frame->return_offset = oparg; - STACK_SHRINK(1); - _PyFrame_StackPush(gen_frame, v); - gen->gi_frame_state = FRAME_EXECUTING; - gen->gi_exc_state.previous_item = tstate->exc_info; - tstate->exc_info = &gen->gi_exc_state; - SKIP_OVER(INLINE_CACHE_ENTRIES_SEND); - DISPATCH_INLINED(gen_frame); + TARGET(CALL_BUILTIN_O) { + frame->instr_ptr = next_instr; + next_instr += 4; + INSTRUCTION_STATS(CALL_BUILTIN_O); + static_assert(INLINE_CACHE_ENTRIES_CALL == 3, "incorrect cache size"); + PyObject **args; + PyObject *self_or_null; + PyObject *callable; + PyObject *res; + /* Skip 1 cache entry */ + /* Skip 2 cache entries */ + args = &stack_pointer[-oparg]; + self_or_null = stack_pointer[-1 - oparg]; + callable = stack_pointer[-2 - oparg]; + /* Builtin METH_O functions */ + int total_args = oparg; + if (self_or_null != NULL) { + args--; + total_args++; + } + DEOPT_IF(total_args != 1, CALL); + DEOPT_IF(!PyCFunction_CheckExact(callable), CALL); + DEOPT_IF(PyCFunction_GET_FLAGS(callable) != METH_O, CALL); + STAT_INC(CALL, hit); + PyCFunction cfunc = PyCFunction_GET_FUNCTION(callable); + // This is slower but CPython promises to check all non-vectorcall + // function calls. + if (_Py_EnterRecursiveCallTstate(tstate, " while calling a Python object")) { + GOTO_ERROR(error); + } + PyObject *arg = args[0]; + res = _PyCFunction_TrampolineCall(cfunc, PyCFunction_GET_SELF(callable), arg); + _Py_LeaveRecursiveCallTstate(tstate); + assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); + Py_DECREF(arg); + Py_DECREF(callable); + if (res == NULL) { stack_pointer += -2 - oparg; goto error; } + stack_pointer[-2 - oparg] = res; + stack_pointer += -1 - oparg; + CHECK_EVAL_BREAKER(); + DISPATCH(); + } + + TARGET(CALL_FUNCTION_EX) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(CALL_FUNCTION_EX); + PREDICTED(CALL_FUNCTION_EX); + _Py_CODEUNIT *this_instr = next_instr - 1; + PyObject *kwargs = NULL; + PyObject *callargs; + PyObject *func; + PyObject *result; + if (oparg & 1) { kwargs = stack_pointer[-(oparg & 1)]; } + callargs = stack_pointer[-1 - (oparg & 1)]; + func = stack_pointer[-3 - (oparg & 1)]; + // DICT_MERGE is called before this opcode if there are kwargs. + // It converts all dict subtypes in kwargs into regular dicts. + assert(kwargs == NULL || PyDict_CheckExact(kwargs)); + if (!PyTuple_CheckExact(callargs)) { + if (check_args_iterable(tstate, func, callargs) < 0) { + GOTO_ERROR(error); + } + PyObject *tuple = PySequence_Tuple(callargs); + if (tuple == NULL) { + GOTO_ERROR(error); + } + Py_SETREF(callargs, tuple); + } + assert(PyTuple_CheckExact(callargs)); + EVAL_CALL_STAT_INC_IF_FUNCTION(EVAL_CALL_FUNCTION_EX, func); + if (opcode == INSTRUMENTED_CALL_FUNCTION_EX && + !PyFunction_Check(func) && !PyMethod_Check(func) + ) { + PyObject *arg = PyTuple_GET_SIZE(callargs) > 0 ? + PyTuple_GET_ITEM(callargs, 0) : Py_None; + int err = _Py_call_instrumentation_2args( + tstate, PY_MONITORING_EVENT_CALL, + frame, this_instr, func, arg); + if (err) GOTO_ERROR(error); + result = PyObject_Call(func, callargs, kwargs); + if (result == NULL) { + _Py_call_instrumentation_exc2( + tstate, PY_MONITORING_EVENT_C_RAISE, + frame, this_instr, func, arg); + } + else { + int err = _Py_call_instrumentation_2args( + tstate, PY_MONITORING_EVENT_C_RETURN, + frame, this_instr, func, arg); + if (err < 0) { + Py_CLEAR(result); + } + } + } + else { + if (Py_TYPE(func) == &PyFunction_Type && + tstate->interp->eval_frame == NULL && + ((PyFunctionObject *)func)->vectorcall == _PyFunction_Vectorcall) { + assert(PyTuple_CheckExact(callargs)); + Py_ssize_t nargs = PyTuple_GET_SIZE(callargs); + int code_flags = ((PyCodeObject *)PyFunction_GET_CODE(func))->co_flags; + PyObject *locals = code_flags & CO_OPTIMIZED ? NULL : Py_NewRef(PyFunction_GET_GLOBALS(func)); + _PyInterpreterFrame *new_frame = _PyEvalFramePushAndInit_Ex(tstate, + (PyFunctionObject *)func, locals, + nargs, callargs, kwargs); + // Need to manually shrink the stack since we exit with DISPATCH_INLINED. + STACK_SHRINK(oparg + 3); + if (new_frame == NULL) { + GOTO_ERROR(error); + } + assert(next_instr - this_instr == 1); + frame->return_offset = 1; + DISPATCH_INLINED(new_frame); + } + result = PyObject_Call(func, callargs, kwargs); + } + Py_DECREF(func); + Py_DECREF(callargs); + Py_XDECREF(kwargs); + assert(PEEK(2 + (oparg & 1)) == NULL); + if (result == NULL) { stack_pointer += -3 - (oparg & 1); goto error; } + stack_pointer[-3 - (oparg & 1)] = result; + stack_pointer += -2 - (oparg & 1); + CHECK_EVAL_BREAKER(); + DISPATCH(); + } + + TARGET(CALL_INTRINSIC_1) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(CALL_INTRINSIC_1); + PyObject *value; + PyObject *res; + value = stack_pointer[-1]; + assert(oparg <= MAX_INTRINSIC_1); + res = _PyIntrinsics_UnaryFunctions[oparg].func(tstate, value); + Py_DECREF(value); + if (res == NULL) goto pop_1_error; + stack_pointer[-1] = res; + DISPATCH(); + } + + TARGET(CALL_INTRINSIC_2) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(CALL_INTRINSIC_2); + PyObject *value1; + PyObject *value2; + PyObject *res; + value1 = stack_pointer[-1]; + value2 = stack_pointer[-2]; + assert(oparg <= MAX_INTRINSIC_2); + res = _PyIntrinsics_BinaryFunctions[oparg].func(tstate, value2, value1); + Py_DECREF(value2); + Py_DECREF(value1); + if (res == NULL) goto pop_2_error; + stack_pointer[-2] = res; + stack_pointer += -1; + DISPATCH(); + } + + TARGET(CALL_ISINSTANCE) { + frame->instr_ptr = next_instr; + next_instr += 4; + INSTRUCTION_STATS(CALL_ISINSTANCE); + static_assert(INLINE_CACHE_ENTRIES_CALL == 3, "incorrect cache size"); + PyObject **args; + PyObject *self_or_null; + PyObject *callable; + PyObject *res; + /* Skip 1 cache entry */ + /* Skip 2 cache entries */ + args = &stack_pointer[-oparg]; + self_or_null = stack_pointer[-1 - oparg]; + callable = stack_pointer[-2 - oparg]; + /* isinstance(o, o2) */ + int total_args = oparg; + if (self_or_null != NULL) { + args--; + total_args++; + } + DEOPT_IF(total_args != 2, CALL); + PyInterpreterState *interp = tstate->interp; + DEOPT_IF(callable != interp->callable_cache.isinstance, CALL); + STAT_INC(CALL, hit); + PyObject *cls = args[1]; + PyObject *inst = args[0]; + int retval = PyObject_IsInstance(inst, cls); + if (retval < 0) { + GOTO_ERROR(error); + } + res = PyBool_FromLong(retval); + assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); + Py_DECREF(inst); + Py_DECREF(cls); + Py_DECREF(callable); + if (res == NULL) { stack_pointer += -2 - oparg; goto error; } + stack_pointer[-2 - oparg] = res; + stack_pointer += -1 - oparg; + DISPATCH(); + } + + TARGET(CALL_KW) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(CALL_KW); + PREDICTED(CALL_KW); + _Py_CODEUNIT *this_instr = next_instr - 1; + PyObject *kwnames; + PyObject **args; + PyObject *self_or_null; + PyObject *callable; + PyObject *res; + kwnames = stack_pointer[-1]; + args = &stack_pointer[-1 - oparg]; + self_or_null = stack_pointer[-2 - oparg]; + callable = stack_pointer[-3 - oparg]; + // oparg counts all of the args, but *not* self: + int total_args = oparg; + if (self_or_null != NULL) { + args--; + total_args++; + } + if (self_or_null == NULL && Py_TYPE(callable) == &PyMethod_Type) { + args--; + total_args++; + PyObject *self = ((PyMethodObject *)callable)->im_self; + args[0] = Py_NewRef(self); + PyObject *method = ((PyMethodObject *)callable)->im_func; + args[-1] = Py_NewRef(method); + Py_DECREF(callable); + callable = method; + } + int positional_args = total_args - (int)PyTuple_GET_SIZE(kwnames); + // Check if the call can be inlined or not + if (Py_TYPE(callable) == &PyFunction_Type && + tstate->interp->eval_frame == NULL && + ((PyFunctionObject *)callable)->vectorcall == _PyFunction_Vectorcall) + { + int code_flags = ((PyCodeObject*)PyFunction_GET_CODE(callable))->co_flags; + PyObject *locals = code_flags & CO_OPTIMIZED ? NULL : Py_NewRef(PyFunction_GET_GLOBALS(callable)); + _PyInterpreterFrame *new_frame = _PyEvalFramePushAndInit( + tstate, (PyFunctionObject *)callable, locals, + args, positional_args, kwnames + ); + Py_DECREF(kwnames); + // Manipulate stack directly since we leave using DISPATCH_INLINED(). + STACK_SHRINK(oparg + 3); + // The frame has stolen all the arguments from the stack, + // so there is no need to clean them up. + if (new_frame == NULL) { + GOTO_ERROR(error); + } + assert(next_instr - this_instr == 1); + frame->return_offset = 1; + DISPATCH_INLINED(new_frame); + } + /* Callable is not a normal Python function */ + res = PyObject_Vectorcall( + callable, args, + positional_args | PY_VECTORCALL_ARGUMENTS_OFFSET, + kwnames); + if (opcode == INSTRUMENTED_CALL_KW) { + PyObject *arg = total_args == 0 ? + &_PyInstrumentation_MISSING : args[0]; + if (res == NULL) { + _Py_call_instrumentation_exc2( + tstate, PY_MONITORING_EVENT_C_RAISE, + frame, this_instr, callable, arg); + } + else { + int err = _Py_call_instrumentation_2args( + tstate, PY_MONITORING_EVENT_C_RETURN, + frame, this_instr, callable, arg); + if (err < 0) { + Py_CLEAR(res); + } + } + } + Py_DECREF(kwnames); + assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); + Py_DECREF(callable); + for (int i = 0; i < total_args; i++) { + Py_DECREF(args[i]); + } + if (res == NULL) { stack_pointer += -3 - oparg; goto error; } + stack_pointer[-3 - oparg] = res; + stack_pointer += -2 - oparg; + CHECK_EVAL_BREAKER(); + DISPATCH(); + } + + TARGET(CALL_LEN) { + frame->instr_ptr = next_instr; + next_instr += 4; + INSTRUCTION_STATS(CALL_LEN); + static_assert(INLINE_CACHE_ENTRIES_CALL == 3, "incorrect cache size"); + PyObject **args; + PyObject *self_or_null; + PyObject *callable; + PyObject *res; + /* Skip 1 cache entry */ + /* Skip 2 cache entries */ + args = &stack_pointer[-oparg]; + self_or_null = stack_pointer[-1 - oparg]; + callable = stack_pointer[-2 - oparg]; + /* len(o) */ + int total_args = oparg; + if (self_or_null != NULL) { + args--; + total_args++; + } + DEOPT_IF(total_args != 1, CALL); + PyInterpreterState *interp = tstate->interp; + DEOPT_IF(callable != interp->callable_cache.len, CALL); + STAT_INC(CALL, hit); + PyObject *arg = args[0]; + Py_ssize_t len_i = PyObject_Length(arg); + if (len_i < 0) { + GOTO_ERROR(error); + } + res = PyLong_FromSsize_t(len_i); + assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); + Py_DECREF(callable); + Py_DECREF(arg); + if (res == NULL) { stack_pointer += -2 - oparg; goto error; } + stack_pointer[-2 - oparg] = res; + stack_pointer += -1 - oparg; + DISPATCH(); + } + + TARGET(CALL_LIST_APPEND) { + frame->instr_ptr = next_instr; + next_instr += 4; + INSTRUCTION_STATS(CALL_LIST_APPEND); + static_assert(INLINE_CACHE_ENTRIES_CALL == 3, "incorrect cache size"); + PyObject **args; + PyObject *self; + PyObject *callable; + /* Skip 1 cache entry */ + /* Skip 2 cache entries */ + args = &stack_pointer[-oparg]; + self = stack_pointer[-1 - oparg]; + callable = stack_pointer[-2 - oparg]; + TIER_ONE_ONLY + assert(oparg == 1); + PyInterpreterState *interp = tstate->interp; + DEOPT_IF(callable != interp->callable_cache.list_append, CALL); + assert(self != NULL); + DEOPT_IF(!PyList_Check(self), CALL); + STAT_INC(CALL, hit); + if (_PyList_AppendTakeRef((PyListObject *)self, args[0]) < 0) { + goto pop_1_error; // Since arg is DECREF'ed already + } + Py_DECREF(self); + Py_DECREF(callable); + STACK_SHRINK(3); + // Skip POP_TOP + assert(next_instr->op.code == POP_TOP); + SKIP_OVER(1); + DISPATCH(); + } + + TARGET(CALL_METHOD_DESCRIPTOR_FAST) { + frame->instr_ptr = next_instr; + next_instr += 4; + INSTRUCTION_STATS(CALL_METHOD_DESCRIPTOR_FAST); + static_assert(INLINE_CACHE_ENTRIES_CALL == 3, "incorrect cache size"); + PyObject **args; + PyObject *self_or_null; + PyObject *callable; + PyObject *res; + /* Skip 1 cache entry */ + /* Skip 2 cache entries */ + args = &stack_pointer[-oparg]; + self_or_null = stack_pointer[-1 - oparg]; + callable = stack_pointer[-2 - oparg]; + int total_args = oparg; + if (self_or_null != NULL) { + args--; + total_args++; + } + PyMethodDescrObject *method = (PyMethodDescrObject *)callable; + /* Builtin METH_FASTCALL methods, without keywords */ + DEOPT_IF(!Py_IS_TYPE(method, &PyMethodDescr_Type), CALL); + PyMethodDef *meth = method->d_method; + DEOPT_IF(meth->ml_flags != METH_FASTCALL, CALL); + PyObject *self = args[0]; + DEOPT_IF(!Py_IS_TYPE(self, method->d_common.d_type), CALL); + STAT_INC(CALL, hit); + _PyCFunctionFast cfunc = + (_PyCFunctionFast)(void(*)(void))meth->ml_meth; + int nargs = total_args - 1; + res = cfunc(self, args + 1, nargs); + assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); + /* Clear the stack of the arguments. */ + for (int i = 0; i < total_args; i++) { + Py_DECREF(args[i]); + } + Py_DECREF(callable); + if (res == NULL) { stack_pointer += -2 - oparg; goto error; } + stack_pointer[-2 - oparg] = res; + stack_pointer += -1 - oparg; + CHECK_EVAL_BREAKER(); + DISPATCH(); + } + + TARGET(CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS) { + frame->instr_ptr = next_instr; + next_instr += 4; + INSTRUCTION_STATS(CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS); + static_assert(INLINE_CACHE_ENTRIES_CALL == 3, "incorrect cache size"); + PyObject **args; + PyObject *self_or_null; + PyObject *callable; + PyObject *res; + /* Skip 1 cache entry */ + /* Skip 2 cache entries */ + args = &stack_pointer[-oparg]; + self_or_null = stack_pointer[-1 - oparg]; + callable = stack_pointer[-2 - oparg]; + int total_args = oparg; + if (self_or_null != NULL) { + args--; + total_args++; + } + PyMethodDescrObject *method = (PyMethodDescrObject *)callable; + DEOPT_IF(!Py_IS_TYPE(method, &PyMethodDescr_Type), CALL); + PyMethodDef *meth = method->d_method; + DEOPT_IF(meth->ml_flags != (METH_FASTCALL|METH_KEYWORDS), CALL); + PyTypeObject *d_type = method->d_common.d_type; + PyObject *self = args[0]; + DEOPT_IF(!Py_IS_TYPE(self, d_type), CALL); + STAT_INC(CALL, hit); + int nargs = total_args - 1; + _PyCFunctionFastWithKeywords cfunc = + (_PyCFunctionFastWithKeywords)(void(*)(void))meth->ml_meth; + res = cfunc(self, args + 1, nargs, NULL); + assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); + /* Free the arguments. */ + for (int i = 0; i < total_args; i++) { + Py_DECREF(args[i]); + } + Py_DECREF(callable); + if (res == NULL) { stack_pointer += -2 - oparg; goto error; } + stack_pointer[-2 - oparg] = res; + stack_pointer += -1 - oparg; + CHECK_EVAL_BREAKER(); + DISPATCH(); + } + + TARGET(CALL_METHOD_DESCRIPTOR_NOARGS) { + frame->instr_ptr = next_instr; + next_instr += 4; + INSTRUCTION_STATS(CALL_METHOD_DESCRIPTOR_NOARGS); + static_assert(INLINE_CACHE_ENTRIES_CALL == 3, "incorrect cache size"); + PyObject **args; + PyObject *self_or_null; + PyObject *callable; + PyObject *res; + /* Skip 1 cache entry */ + /* Skip 2 cache entries */ + args = &stack_pointer[-oparg]; + self_or_null = stack_pointer[-1 - oparg]; + callable = stack_pointer[-2 - oparg]; + assert(oparg == 0 || oparg == 1); + int total_args = oparg; + if (self_or_null != NULL) { + args--; + total_args++; + } + DEOPT_IF(total_args != 1, CALL); + PyMethodDescrObject *method = (PyMethodDescrObject *)callable; + DEOPT_IF(!Py_IS_TYPE(method, &PyMethodDescr_Type), CALL); + PyMethodDef *meth = method->d_method; + PyObject *self = args[0]; + DEOPT_IF(!Py_IS_TYPE(self, method->d_common.d_type), CALL); + DEOPT_IF(meth->ml_flags != METH_NOARGS, CALL); + STAT_INC(CALL, hit); + PyCFunction cfunc = meth->ml_meth; + // This is slower but CPython promises to check all non-vectorcall + // function calls. + if (_Py_EnterRecursiveCallTstate(tstate, " while calling a Python object")) { + GOTO_ERROR(error); + } + res = _PyCFunction_TrampolineCall(cfunc, self, NULL); + _Py_LeaveRecursiveCallTstate(tstate); + assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); + Py_DECREF(self); + Py_DECREF(callable); + if (res == NULL) { stack_pointer += -2 - oparg; goto error; } + stack_pointer[-2 - oparg] = res; + stack_pointer += -1 - oparg; + CHECK_EVAL_BREAKER(); + DISPATCH(); + } + + TARGET(CALL_METHOD_DESCRIPTOR_O) { + frame->instr_ptr = next_instr; + next_instr += 4; + INSTRUCTION_STATS(CALL_METHOD_DESCRIPTOR_O); + static_assert(INLINE_CACHE_ENTRIES_CALL == 3, "incorrect cache size"); + PyObject **args; + PyObject *self_or_null; + PyObject *callable; + PyObject *res; + /* Skip 1 cache entry */ + /* Skip 2 cache entries */ + args = &stack_pointer[-oparg]; + self_or_null = stack_pointer[-1 - oparg]; + callable = stack_pointer[-2 - oparg]; + int total_args = oparg; + if (self_or_null != NULL) { + args--; + total_args++; + } + PyMethodDescrObject *method = (PyMethodDescrObject *)callable; + DEOPT_IF(total_args != 2, CALL); + DEOPT_IF(!Py_IS_TYPE(method, &PyMethodDescr_Type), CALL); + PyMethodDef *meth = method->d_method; + DEOPT_IF(meth->ml_flags != METH_O, CALL); + PyObject *arg = args[1]; + PyObject *self = args[0]; + DEOPT_IF(!Py_IS_TYPE(self, method->d_common.d_type), CALL); + STAT_INC(CALL, hit); + PyCFunction cfunc = meth->ml_meth; + // This is slower but CPython promises to check all non-vectorcall + // function calls. + if (_Py_EnterRecursiveCallTstate(tstate, " while calling a Python object")) { + GOTO_ERROR(error); + } + res = _PyCFunction_TrampolineCall(cfunc, self, arg); + _Py_LeaveRecursiveCallTstate(tstate); + assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); + Py_DECREF(self); + Py_DECREF(arg); + Py_DECREF(callable); + if (res == NULL) { stack_pointer += -2 - oparg; goto error; } + stack_pointer[-2 - oparg] = res; + stack_pointer += -1 - oparg; + CHECK_EVAL_BREAKER(); + DISPATCH(); + } + + TARGET(CALL_PY_EXACT_ARGS) { + _Py_CODEUNIT *this_instr = frame->instr_ptr = next_instr; + next_instr += 4; + INSTRUCTION_STATS(CALL_PY_EXACT_ARGS); + static_assert(INLINE_CACHE_ENTRIES_CALL == 3, "incorrect cache size"); + PyObject *self_or_null; + PyObject *callable; + PyObject **args; + _PyInterpreterFrame *new_frame; + /* Skip 1 cache entry */ + // _CHECK_PEP_523 + { + DEOPT_IF(tstate->interp->eval_frame, CALL); + } + // _CHECK_FUNCTION_EXACT_ARGS + self_or_null = stack_pointer[-1 - oparg]; + callable = stack_pointer[-2 - oparg]; + { + uint32_t func_version = read_u32(&this_instr[2].cache); + DEOPT_IF(!PyFunction_Check(callable), CALL); + PyFunctionObject *func = (PyFunctionObject *)callable; + DEOPT_IF(func->func_version != func_version, CALL); + PyCodeObject *code = (PyCodeObject *)func->func_code; + DEOPT_IF(code->co_argcount != oparg + (self_or_null != NULL), CALL); + } + // _CHECK_STACK_SPACE + { + PyFunctionObject *func = (PyFunctionObject *)callable; + PyCodeObject *code = (PyCodeObject *)func->func_code; + DEOPT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize), CALL); + DEOPT_IF(tstate->py_recursion_remaining <= 1, CALL); + } + // _INIT_CALL_PY_EXACT_ARGS + args = &stack_pointer[-oparg]; + self_or_null = stack_pointer[-1 - oparg]; + { + int argcount = oparg; + if (self_or_null != NULL) { + args--; + argcount++; + } + STAT_INC(CALL, hit); + PyFunctionObject *func = (PyFunctionObject *)callable; + new_frame = _PyFrame_PushUnchecked(tstate, func, argcount); + for (int i = 0; i < argcount; i++) { + new_frame->localsplus[i] = args[i]; + } + } + // _SAVE_RETURN_OFFSET + { + #if TIER_ONE + frame->return_offset = (uint16_t)(next_instr - this_instr); + #endif + #if TIER_TWO + frame->return_offset = oparg; + #endif + } + // _PUSH_FRAME + { + // Write it out explicitly because it's subtly different. + // Eventually this should be the only occurrence of this code. + assert(tstate->interp->eval_frame == NULL); + stack_pointer += -2 - oparg; + _PyFrame_SetStackPointer(frame, stack_pointer); + new_frame->previous = frame; + CALL_STAT_INC(inlined_py_calls); + frame = tstate->current_frame = new_frame; + tstate->py_recursion_remaining--; + LOAD_SP(); + LOAD_IP(0); + #if LLTRACE && TIER_ONE + lltrace = maybe_lltrace_resume_frame(frame, &entry_frame, GLOBALS()); + if (lltrace < 0) { + goto exit_unwind; + } + #endif + } + stack_pointer += ((0) ? 1 : 0); + DISPATCH(); + } + + TARGET(CALL_PY_WITH_DEFAULTS) { + _Py_CODEUNIT *this_instr = frame->instr_ptr = next_instr; + next_instr += 4; + INSTRUCTION_STATS(CALL_PY_WITH_DEFAULTS); + static_assert(INLINE_CACHE_ENTRIES_CALL == 3, "incorrect cache size"); + PyObject **args; + PyObject *self_or_null; + PyObject *callable; + /* Skip 1 cache entry */ + args = &stack_pointer[-oparg]; + self_or_null = stack_pointer[-1 - oparg]; + callable = stack_pointer[-2 - oparg]; + uint32_t func_version = read_u32(&this_instr[2].cache); + DEOPT_IF(tstate->interp->eval_frame, CALL); + int argcount = oparg; + if (self_or_null != NULL) { + args--; + argcount++; + } + DEOPT_IF(!PyFunction_Check(callable), CALL); + PyFunctionObject *func = (PyFunctionObject *)callable; + DEOPT_IF(func->func_version != func_version, CALL); + PyCodeObject *code = (PyCodeObject *)func->func_code; + assert(func->func_defaults); + assert(PyTuple_CheckExact(func->func_defaults)); + int defcount = (int)PyTuple_GET_SIZE(func->func_defaults); + assert(defcount <= code->co_argcount); + int min_args = code->co_argcount - defcount; + DEOPT_IF(argcount > code->co_argcount, CALL); + DEOPT_IF(argcount < min_args, CALL); + DEOPT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize), CALL); + STAT_INC(CALL, hit); + _PyInterpreterFrame *new_frame = _PyFrame_PushUnchecked(tstate, func, code->co_argcount); + for (int i = 0; i < argcount; i++) { + new_frame->localsplus[i] = args[i]; + } + for (int i = argcount; i < code->co_argcount; i++) { + PyObject *def = PyTuple_GET_ITEM(func->func_defaults, i - min_args); + new_frame->localsplus[i] = Py_NewRef(def); + } + // Manipulate stack and cache directly since we leave using DISPATCH_INLINED(). + STACK_SHRINK(oparg + 2); + frame->return_offset = (uint16_t)(next_instr - this_instr); + DISPATCH_INLINED(new_frame); + } + + TARGET(CALL_STR_1) { + frame->instr_ptr = next_instr; + next_instr += 4; + INSTRUCTION_STATS(CALL_STR_1); + static_assert(INLINE_CACHE_ENTRIES_CALL == 3, "incorrect cache size"); + PyObject **args; + PyObject *null; + PyObject *callable; + PyObject *res; + /* Skip 1 cache entry */ + /* Skip 2 cache entries */ + args = &stack_pointer[-oparg]; + null = stack_pointer[-1 - oparg]; + callable = stack_pointer[-2 - oparg]; + assert(oparg == 1); + DEOPT_IF(null != NULL, CALL); + DEOPT_IF(callable != (PyObject *)&PyUnicode_Type, CALL); + STAT_INC(CALL, hit); + PyObject *arg = args[0]; + res = PyObject_Str(arg); + Py_DECREF(arg); + Py_DECREF(&PyUnicode_Type); // I.e., callable + if (res == NULL) { stack_pointer += -2 - oparg; goto error; } + stack_pointer[-2 - oparg] = res; + stack_pointer += -1 - oparg; + CHECK_EVAL_BREAKER(); + DISPATCH(); + } + + TARGET(CALL_TUPLE_1) { + frame->instr_ptr = next_instr; + next_instr += 4; + INSTRUCTION_STATS(CALL_TUPLE_1); + static_assert(INLINE_CACHE_ENTRIES_CALL == 3, "incorrect cache size"); + PyObject **args; + PyObject *null; + PyObject *callable; + PyObject *res; + /* Skip 1 cache entry */ + /* Skip 2 cache entries */ + args = &stack_pointer[-oparg]; + null = stack_pointer[-1 - oparg]; + callable = stack_pointer[-2 - oparg]; + assert(oparg == 1); + DEOPT_IF(null != NULL, CALL); + DEOPT_IF(callable != (PyObject *)&PyTuple_Type, CALL); + STAT_INC(CALL, hit); + PyObject *arg = args[0]; + res = PySequence_Tuple(arg); + Py_DECREF(arg); + Py_DECREF(&PyTuple_Type); // I.e., tuple + if (res == NULL) { stack_pointer += -2 - oparg; goto error; } + stack_pointer[-2 - oparg] = res; + stack_pointer += -1 - oparg; + CHECK_EVAL_BREAKER(); + DISPATCH(); + } + + TARGET(CALL_TYPE_1) { + frame->instr_ptr = next_instr; + next_instr += 4; + INSTRUCTION_STATS(CALL_TYPE_1); + static_assert(INLINE_CACHE_ENTRIES_CALL == 3, "incorrect cache size"); + PyObject **args; + PyObject *null; + PyObject *callable; + PyObject *res; + /* Skip 1 cache entry */ + /* Skip 2 cache entries */ + args = &stack_pointer[-oparg]; + null = stack_pointer[-1 - oparg]; + callable = stack_pointer[-2 - oparg]; + assert(oparg == 1); + DEOPT_IF(null != NULL, CALL); + PyObject *obj = args[0]; + DEOPT_IF(callable != (PyObject *)&PyType_Type, CALL); + STAT_INC(CALL, hit); + res = Py_NewRef(Py_TYPE(obj)); + Py_DECREF(obj); + Py_DECREF(&PyType_Type); // I.e., callable + stack_pointer[-2 - oparg] = res; + stack_pointer += -1 - oparg; + DISPATCH(); + } + + TARGET(CHECK_EG_MATCH) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(CHECK_EG_MATCH); + PyObject *match_type; + PyObject *exc_value; + PyObject *rest; + PyObject *match; + match_type = stack_pointer[-1]; + exc_value = stack_pointer[-2]; + if (_PyEval_CheckExceptStarTypeValid(tstate, match_type) < 0) { + Py_DECREF(exc_value); + Py_DECREF(match_type); + if (true) goto pop_2_error; + } + match = NULL; + rest = NULL; + int res = _PyEval_ExceptionGroupMatch(exc_value, match_type, + &match, &rest); + Py_DECREF(exc_value); + Py_DECREF(match_type); + if (res < 0) goto pop_2_error; + assert((match == NULL) == (rest == NULL)); + if (match == NULL) goto pop_2_error; + if (!Py_IsNone(match)) { + PyErr_SetHandledException(match); + } + stack_pointer[-2] = rest; + stack_pointer[-1] = match; + DISPATCH(); + } + + TARGET(CHECK_EXC_MATCH) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(CHECK_EXC_MATCH); + PyObject *right; + PyObject *left; + PyObject *b; + right = stack_pointer[-1]; + left = stack_pointer[-2]; + assert(PyExceptionInstance_Check(left)); + if (_PyEval_CheckExceptTypeValid(tstate, right) < 0) { + Py_DECREF(right); + if (true) goto pop_1_error; + } + int res = PyErr_GivenExceptionMatches(left, right); + Py_DECREF(right); + b = res ? Py_True : Py_False; + stack_pointer[-1] = b; + DISPATCH(); } - TARGET(INSTRUMENTED_YIELD_VALUE) { - PyObject *retval; - retval = stack_pointer[-1]; - assert(frame != &entry_frame); - assert(oparg >= 0); /* make the generator identify this as HAS_ARG */ - PyGenObject *gen = _PyFrame_GetGenerator(frame); - gen->gi_frame_state = FRAME_SUSPENDED; - _PyFrame_SetStackPointer(frame, stack_pointer - 1); - int err = _Py_call_instrumentation_arg( - tstate, PY_MONITORING_EVENT_PY_YIELD, - frame, next_instr-1, retval); - if (err) goto error; - tstate->exc_info = gen->gi_exc_state.previous_item; - gen->gi_exc_state.previous_item = NULL; - _Py_LeaveRecursiveCallPy(tstate); - _PyInterpreterFrame *gen_frame = frame; - frame = cframe.current_frame = frame->previous; - gen_frame->previous = NULL; - _PyFrame_StackPush(frame, retval); - goto resume_frame; + TARGET(CLEANUP_THROW) { + _Py_CODEUNIT *this_instr = frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(CLEANUP_THROW); + PyObject *exc_value; + PyObject *last_sent_val; + PyObject *sub_iter; + PyObject *none; + PyObject *value; + exc_value = stack_pointer[-1]; + last_sent_val = stack_pointer[-2]; + sub_iter = stack_pointer[-3]; + TIER_ONE_ONLY + assert(throwflag); + assert(exc_value && PyExceptionInstance_Check(exc_value)); + if (PyErr_GivenExceptionMatches(exc_value, PyExc_StopIteration)) { + value = Py_NewRef(((PyStopIterationObject *)exc_value)->value); + Py_DECREF(sub_iter); + Py_DECREF(last_sent_val); + Py_DECREF(exc_value); + none = Py_None; + } + else { + _PyErr_SetRaisedException(tstate, Py_NewRef(exc_value)); + monitor_reraise(tstate, frame, this_instr); + goto exception_unwind; + } + stack_pointer[-3] = none; + stack_pointer[-2] = value; + stack_pointer += -1; + DISPATCH(); + } + + TARGET(COMPARE_OP) { + frame->instr_ptr = next_instr; + next_instr += 2; + INSTRUCTION_STATS(COMPARE_OP); + PREDICTED(COMPARE_OP); + _Py_CODEUNIT *this_instr = next_instr - 2; + PyObject *right; + PyObject *left; + PyObject *res; + // _SPECIALIZE_COMPARE_OP + right = stack_pointer[-1]; + left = stack_pointer[-2]; + { + uint16_t counter = read_u16(&this_instr[1].cache); + TIER_ONE_ONLY + #if ENABLE_SPECIALIZATION + if (ADAPTIVE_COUNTER_IS_ZERO(counter)) { + next_instr = this_instr; + _Py_Specialize_CompareOp(left, right, next_instr, oparg); + DISPATCH_SAME_OPARG(); + } + STAT_INC(COMPARE_OP, deferred); + DECREMENT_ADAPTIVE_COUNTER(this_instr[1].cache); + #endif /* ENABLE_SPECIALIZATION */ + } + // _COMPARE_OP + { + assert((oparg >> 5) <= Py_GE); + res = PyObject_RichCompare(left, right, oparg >> 5); + Py_DECREF(left); + Py_DECREF(right); + if (res == NULL) goto pop_2_error; + if (oparg & 16) { + int res_bool = PyObject_IsTrue(res); + Py_DECREF(res); + if (res_bool < 0) goto pop_2_error; + res = res_bool ? Py_True : Py_False; + } + } + stack_pointer[-2] = res; + stack_pointer += -1; + DISPATCH(); + } + + TARGET(COMPARE_OP_FLOAT) { + frame->instr_ptr = next_instr; + next_instr += 2; + INSTRUCTION_STATS(COMPARE_OP_FLOAT); + static_assert(INLINE_CACHE_ENTRIES_COMPARE_OP == 1, "incorrect cache size"); + PyObject *right; + PyObject *left; + PyObject *res; + /* Skip 1 cache entry */ + right = stack_pointer[-1]; + left = stack_pointer[-2]; + DEOPT_IF(!PyFloat_CheckExact(left), COMPARE_OP); + DEOPT_IF(!PyFloat_CheckExact(right), COMPARE_OP); + STAT_INC(COMPARE_OP, hit); + double dleft = PyFloat_AS_DOUBLE(left); + double dright = PyFloat_AS_DOUBLE(right); + // 1 if NaN, 2 if <, 4 if >, 8 if ==; this matches low four bits of the oparg + int sign_ish = COMPARISON_BIT(dleft, dright); + _Py_DECREF_SPECIALIZED(left, _PyFloat_ExactDealloc); + _Py_DECREF_SPECIALIZED(right, _PyFloat_ExactDealloc); + res = (sign_ish & oparg) ? Py_True : Py_False; + // It's always a bool, so we don't care about oparg & 16. + stack_pointer[-2] = res; + stack_pointer += -1; + DISPATCH(); + } + + TARGET(COMPARE_OP_INT) { + frame->instr_ptr = next_instr; + next_instr += 2; + INSTRUCTION_STATS(COMPARE_OP_INT); + static_assert(INLINE_CACHE_ENTRIES_COMPARE_OP == 1, "incorrect cache size"); + PyObject *right; + PyObject *left; + PyObject *res; + /* Skip 1 cache entry */ + right = stack_pointer[-1]; + left = stack_pointer[-2]; + DEOPT_IF(!PyLong_CheckExact(left), COMPARE_OP); + DEOPT_IF(!PyLong_CheckExact(right), COMPARE_OP); + DEOPT_IF(!_PyLong_IsCompact((PyLongObject *)left), COMPARE_OP); + DEOPT_IF(!_PyLong_IsCompact((PyLongObject *)right), COMPARE_OP); + STAT_INC(COMPARE_OP, hit); + assert(_PyLong_DigitCount((PyLongObject *)left) <= 1 && + _PyLong_DigitCount((PyLongObject *)right) <= 1); + Py_ssize_t ileft = _PyLong_CompactValue((PyLongObject *)left); + Py_ssize_t iright = _PyLong_CompactValue((PyLongObject *)right); + // 2 if <, 4 if >, 8 if ==; this matches the low 4 bits of the oparg + int sign_ish = COMPARISON_BIT(ileft, iright); + _Py_DECREF_SPECIALIZED(left, (destructor)PyObject_Free); + _Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free); + res = (sign_ish & oparg) ? Py_True : Py_False; + // It's always a bool, so we don't care about oparg & 16. + stack_pointer[-2] = res; + stack_pointer += -1; + DISPATCH(); + } + + TARGET(COMPARE_OP_STR) { + frame->instr_ptr = next_instr; + next_instr += 2; + INSTRUCTION_STATS(COMPARE_OP_STR); + static_assert(INLINE_CACHE_ENTRIES_COMPARE_OP == 1, "incorrect cache size"); + PyObject *right; + PyObject *left; + PyObject *res; + /* Skip 1 cache entry */ + right = stack_pointer[-1]; + left = stack_pointer[-2]; + DEOPT_IF(!PyUnicode_CheckExact(left), COMPARE_OP); + DEOPT_IF(!PyUnicode_CheckExact(right), COMPARE_OP); + STAT_INC(COMPARE_OP, hit); + int eq = _PyUnicode_Equal(left, right); + assert((oparg >> 5) == Py_EQ || (oparg >> 5) == Py_NE); + _Py_DECREF_SPECIALIZED(left, _PyUnicode_ExactDealloc); + _Py_DECREF_SPECIALIZED(right, _PyUnicode_ExactDealloc); + assert(eq == 0 || eq == 1); + assert((oparg & 0xf) == COMPARISON_NOT_EQUALS || (oparg & 0xf) == COMPARISON_EQUALS); + assert(COMPARISON_NOT_EQUALS + 1 == COMPARISON_EQUALS); + res = ((COMPARISON_NOT_EQUALS + eq) & oparg) ? Py_True : Py_False; + // It's always a bool, so we don't care about oparg & 16. + stack_pointer[-2] = res; + stack_pointer += -1; + DISPATCH(); + } + + TARGET(CONTAINS_OP) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(CONTAINS_OP); + PyObject *right; + PyObject *left; + PyObject *b; + right = stack_pointer[-1]; + left = stack_pointer[-2]; + int res = PySequence_Contains(right, left); + Py_DECREF(left); + Py_DECREF(right); + if (res < 0) goto pop_2_error; + b = (res ^ oparg) ? Py_True : Py_False; + stack_pointer[-2] = b; + stack_pointer += -1; + DISPATCH(); + } + + TARGET(CONVERT_VALUE) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(CONVERT_VALUE); + PyObject *value; + PyObject *result; + value = stack_pointer[-1]; + convertion_func_ptr conv_fn; + assert(oparg >= FVC_STR && oparg <= FVC_ASCII); + conv_fn = CONVERSION_FUNCTIONS[oparg]; + result = conv_fn(value); + Py_DECREF(value); + if (result == NULL) goto pop_1_error; + stack_pointer[-1] = result; + DISPATCH(); + } + + TARGET(COPY) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(COPY); + PyObject *bottom; + PyObject *top; + bottom = stack_pointer[-1 - (oparg-1)]; + assert(oparg > 0); + top = Py_NewRef(bottom); + stack_pointer[0] = top; + stack_pointer += 1; + DISPATCH(); + } + + TARGET(COPY_FREE_VARS) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(COPY_FREE_VARS); + /* Copy closure variables to free variables */ + PyCodeObject *co = _PyFrame_GetCode(frame); + assert(PyFunction_Check(frame->f_funcobj)); + PyObject *closure = ((PyFunctionObject *)frame->f_funcobj)->func_closure; + assert(oparg == co->co_nfreevars); + int offset = co->co_nlocalsplus - oparg; + for (int i = 0; i < oparg; ++i) { + PyObject *o = PyTuple_GET_ITEM(closure, i); + frame->localsplus[offset + i] = Py_NewRef(o); + } + DISPATCH(); + } + + TARGET(DELETE_ATTR) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(DELETE_ATTR); + PyObject *owner; + owner = stack_pointer[-1]; + PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); + int err = PyObject_DelAttr(owner, name); + Py_DECREF(owner); + if (err) goto pop_1_error; + stack_pointer += -1; + DISPATCH(); + } + + TARGET(DELETE_DEREF) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(DELETE_DEREF); + PyObject *cell = GETLOCAL(oparg); + PyObject *oldobj = PyCell_GET(cell); + // Can't use ERROR_IF here. + // Fortunately we don't need its superpower. + if (oldobj == NULL) { + _PyEval_FormatExcUnbound(tstate, _PyFrame_GetCode(frame), oparg); + GOTO_ERROR(error); + } + PyCell_SET(cell, NULL); + Py_DECREF(oldobj); + DISPATCH(); + } + + TARGET(DELETE_FAST) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(DELETE_FAST); + PyObject *v = GETLOCAL(oparg); + if (v == NULL) goto unbound_local_error; + SETLOCAL(oparg, NULL); + DISPATCH(); + } + + TARGET(DELETE_GLOBAL) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(DELETE_GLOBAL); + PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); + int err; + err = PyDict_DelItem(GLOBALS(), name); + // Can't use ERROR_IF here. + if (err != 0) { + if (_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) { + _PyEval_FormatExcCheckArg(tstate, PyExc_NameError, + NAME_ERROR_MSG, name); + } + GOTO_ERROR(error); + } + DISPATCH(); + } + + TARGET(DELETE_NAME) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(DELETE_NAME); + PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); + PyObject *ns = LOCALS(); + int err; + if (ns == NULL) { + _PyErr_Format(tstate, PyExc_SystemError, + "no locals when deleting %R", name); + GOTO_ERROR(error); + } + err = PyObject_DelItem(ns, name); + // Can't use ERROR_IF here. + if (err != 0) { + _PyEval_FormatExcCheckArg(tstate, PyExc_NameError, + NAME_ERROR_MSG, + name); + GOTO_ERROR(error); + } + DISPATCH(); } - TARGET(YIELD_VALUE) { - PyObject *retval; - retval = stack_pointer[-1]; - // 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 >= 0); /* make the generator identify this as HAS_ARG */ - assert(frame != &entry_frame); - PyGenObject *gen = _PyFrame_GetGenerator(frame); - gen->gi_frame_state = FRAME_SUSPENDED; - _PyFrame_SetStackPointer(frame, stack_pointer - 1); - tstate->exc_info = gen->gi_exc_state.previous_item; - gen->gi_exc_state.previous_item = NULL; - _Py_LeaveRecursiveCallPy(tstate); - _PyInterpreterFrame *gen_frame = frame; - frame = cframe.current_frame = frame->previous; - gen_frame->previous = NULL; - _PyFrame_StackPush(frame, retval); - goto resume_frame; + TARGET(DELETE_SUBSCR) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(DELETE_SUBSCR); + PyObject *sub; + PyObject *container; + sub = stack_pointer[-1]; + container = stack_pointer[-2]; + /* del container[sub] */ + int err = PyObject_DelItem(container, sub); + Py_DECREF(container); + Py_DECREF(sub); + if (err) goto pop_2_error; + stack_pointer += -2; + DISPATCH(); } - TARGET(POP_EXCEPT) { - PyObject *exc_value; - exc_value = stack_pointer[-1]; - _PyErr_StackItem *exc_info = tstate->exc_info; - Py_XSETREF(exc_info->exc_value, exc_value); - STACK_SHRINK(1); + TARGET(DICT_MERGE) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(DICT_MERGE); + PyObject *update; + PyObject *dict; + PyObject *callable; + update = stack_pointer[-1]; + dict = stack_pointer[-2 - (oparg - 1)]; + callable = stack_pointer[-5 - (oparg - 1)]; + if (_PyDict_MergeEx(dict, update, 2) < 0) { + _PyEval_FormatKwargsError(tstate, callable, update); + Py_DECREF(update); + if (true) goto pop_1_error; + } + Py_DECREF(update); + stack_pointer += -1; DISPATCH(); } - TARGET(RERAISE) { - PyObject *exc; - PyObject **values; - exc = stack_pointer[-1]; - values = stack_pointer - 1 - oparg; - assert(oparg >= 0 && oparg <= 2); - if (oparg) { - PyObject *lasti = values[0]; - if (PyLong_Check(lasti)) { - frame->prev_instr = _PyCode_CODE(_PyFrame_GetCode(frame)) + PyLong_AsLong(lasti); - assert(!_PyErr_Occurred(tstate)); - } - else { - assert(PyLong_Check(lasti)); - _PyErr_SetString(tstate, PyExc_SystemError, "lasti is not an int"); - goto error; + TARGET(DICT_UPDATE) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(DICT_UPDATE); + PyObject *update; + PyObject *dict; + update = stack_pointer[-1]; + dict = stack_pointer[-2 - (oparg - 1)]; + if (PyDict_Update(dict, update) < 0) { + if (_PyErr_ExceptionMatches(tstate, PyExc_AttributeError)) { + _PyErr_Format(tstate, PyExc_TypeError, + "'%.200s' object is not a mapping", + Py_TYPE(update)->tp_name); } + Py_DECREF(update); + if (true) goto pop_1_error; } - assert(exc && PyExceptionInstance_Check(exc)); - Py_INCREF(exc); - _PyErr_SetRaisedException(tstate, exc); - monitor_reraise(tstate, frame, next_instr-1); - goto exception_unwind; - STACK_SHRINK(1); + Py_DECREF(update); + stack_pointer += -1; + DISPATCH(); } TARGET(END_ASYNC_FOR) { + _Py_CODEUNIT *this_instr = frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(END_ASYNC_FOR); PyObject *exc; PyObject *awaitable; exc = stack_pointer[-1]; awaitable = stack_pointer[-2]; + TIER_ONE_ONLY assert(exc && PyExceptionInstance_Check(exc)); if (PyErr_GivenExceptionMatches(exc, PyExc_StopAsyncIteration)) { Py_DECREF(awaitable); @@ -1314,625 +2330,1037 @@ else { Py_INCREF(exc); _PyErr_SetRaisedException(tstate, exc); - monitor_reraise(tstate, frame, next_instr-1); + monitor_reraise(tstate, frame, this_instr); goto exception_unwind; } - STACK_SHRINK(2); + stack_pointer += -2; DISPATCH(); } - TARGET(CLEANUP_THROW) { - PyObject *exc_value; - PyObject *last_sent_val; - PyObject *sub_iter; - PyObject *none; + TARGET(END_FOR) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(END_FOR); PyObject *value; - exc_value = stack_pointer[-1]; - last_sent_val = stack_pointer[-2]; - sub_iter = stack_pointer[-3]; - assert(throwflag); - assert(exc_value && PyExceptionInstance_Check(exc_value)); - if (PyErr_GivenExceptionMatches(exc_value, PyExc_StopIteration)) { - value = Py_NewRef(((PyStopIterationObject *)exc_value)->value); - Py_DECREF(sub_iter); - Py_DECREF(last_sent_val); - Py_DECREF(exc_value); - none = Py_None; + // _POP_TOP + value = stack_pointer[-1]; + { + Py_DECREF(value); + } + // _POP_TOP + value = stack_pointer[-2]; + { + Py_DECREF(value); + } + stack_pointer += -2; + DISPATCH(); + } + + TARGET(END_SEND) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(END_SEND); + PyObject *value; + PyObject *receiver; + value = stack_pointer[-1]; + receiver = stack_pointer[-2]; + Py_DECREF(receiver); + stack_pointer[-2] = value; + stack_pointer += -1; + DISPATCH(); + } + + TARGET(ENTER_EXECUTOR) { + _Py_CODEUNIT *this_instr = frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(ENTER_EXECUTOR); + TIER_ONE_ONLY + CHECK_EVAL_BREAKER(); + PyCodeObject *code = _PyFrame_GetCode(frame); + _PyExecutorObject *executor = (_PyExecutorObject *)code->co_executors->executors[oparg&255]; + if (executor->vm_data.valid) { + Py_INCREF(executor); + current_executor = (_PyUOpExecutorObject *)executor; + GOTO_TIER_TWO(); } else { - _PyErr_SetRaisedException(tstate, Py_NewRef(exc_value)); - monitor_reraise(tstate, frame, next_instr-1); - goto exception_unwind; + /* ENTER_EXECUTOR will be the first code unit of the instruction */ + assert(oparg < 256); + code->co_executors->executors[oparg] = NULL; + opcode = this_instr->op.code = executor->vm_data.opcode; + this_instr->op.arg = executor->vm_data.oparg; + oparg = executor->vm_data.oparg; + Py_DECREF(executor); + next_instr = this_instr; + DISPATCH_GOTO(); + } + DISPATCH(); + } + + TARGET(EXIT_INIT_CHECK) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(EXIT_INIT_CHECK); + PyObject *should_be_none; + should_be_none = stack_pointer[-1]; + assert(STACK_LEVEL() == 2); + if (should_be_none != Py_None) { + PyErr_Format(PyExc_TypeError, + "__init__() should return None, not '%.200s'", + Py_TYPE(should_be_none)->tp_name); + GOTO_ERROR(error); + } + stack_pointer += -1; + DISPATCH(); + } + + TARGET(EXTENDED_ARG) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(EXTENDED_ARG); + TIER_ONE_ONLY + assert(oparg); + opcode = next_instr->op.code; + oparg = oparg << 8 | next_instr->op.arg; + PRE_DISPATCH_GOTO(); + DISPATCH_GOTO(); + } + + TARGET(FORMAT_SIMPLE) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(FORMAT_SIMPLE); + PyObject *value; + PyObject *res; + value = stack_pointer[-1]; + /* If value is a unicode object, then we know the result + * of format(value) is value itself. */ + if (!PyUnicode_CheckExact(value)) { + res = PyObject_Format(value, NULL); + Py_DECREF(value); + if (res == NULL) goto pop_1_error; + } + else { + res = value; + } + stack_pointer[-1] = res; + DISPATCH(); + } + + TARGET(FORMAT_WITH_SPEC) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(FORMAT_WITH_SPEC); + PyObject *fmt_spec; + PyObject *value; + PyObject *res; + fmt_spec = stack_pointer[-1]; + value = stack_pointer[-2]; + res = PyObject_Format(value, fmt_spec); + Py_DECREF(value); + Py_DECREF(fmt_spec); + if (res == NULL) goto pop_2_error; + stack_pointer[-2] = res; + stack_pointer += -1; + DISPATCH(); + } + + TARGET(FOR_ITER) { + frame->instr_ptr = next_instr; + next_instr += 2; + INSTRUCTION_STATS(FOR_ITER); + PREDICTED(FOR_ITER); + _Py_CODEUNIT *this_instr = next_instr - 2; + PyObject *iter; + PyObject *next; + // _SPECIALIZE_FOR_ITER + iter = stack_pointer[-1]; + { + uint16_t counter = read_u16(&this_instr[1].cache); + TIER_ONE_ONLY + #if ENABLE_SPECIALIZATION + if (ADAPTIVE_COUNTER_IS_ZERO(counter)) { + next_instr = this_instr; + _Py_Specialize_ForIter(iter, next_instr, oparg); + DISPATCH_SAME_OPARG(); + } + STAT_INC(FOR_ITER, deferred); + DECREMENT_ADAPTIVE_COUNTER(this_instr[1].cache); + #endif /* ENABLE_SPECIALIZATION */ + } + // _FOR_ITER + { + /* before: [iter]; after: [iter, iter()] *or* [] (and jump over END_FOR.) */ + next = (*Py_TYPE(iter)->tp_iternext)(iter); + if (next == NULL) { + if (_PyErr_Occurred(tstate)) { + if (!_PyErr_ExceptionMatches(tstate, PyExc_StopIteration)) { + GOTO_ERROR(error); + } + monitor_raise(tstate, frame, this_instr); + _PyErr_Clear(tstate); + } + /* iterator ended normally */ + assert(next_instr[oparg].op.code == END_FOR || + next_instr[oparg].op.code == INSTRUMENTED_END_FOR); + Py_DECREF(iter); + STACK_SHRINK(1); + /* Jump forward oparg, then skip following END_FOR instruction */ + JUMPBY(oparg + 1); + DISPATCH(); + } + // Common case: no jump, leave it to the code generator + } + stack_pointer[0] = next; + stack_pointer += 1; + DISPATCH(); + } + + TARGET(FOR_ITER_GEN) { + _Py_CODEUNIT *this_instr = frame->instr_ptr = next_instr; + next_instr += 2; + INSTRUCTION_STATS(FOR_ITER_GEN); + static_assert(INLINE_CACHE_ENTRIES_FOR_ITER == 1, "incorrect cache size"); + PyObject *iter; + /* Skip 1 cache entry */ + iter = stack_pointer[-1]; + DEOPT_IF(tstate->interp->eval_frame, FOR_ITER); + PyGenObject *gen = (PyGenObject *)iter; + DEOPT_IF(Py_TYPE(gen) != &PyGen_Type, FOR_ITER); + DEOPT_IF(gen->gi_frame_state >= FRAME_EXECUTING, FOR_ITER); + STAT_INC(FOR_ITER, hit); + _PyInterpreterFrame *gen_frame = (_PyInterpreterFrame *)gen->gi_iframe; + _PyFrame_StackPush(gen_frame, Py_None); + gen->gi_frame_state = FRAME_EXECUTING; + gen->gi_exc_state.previous_item = tstate->exc_info; + tstate->exc_info = &gen->gi_exc_state; + assert(next_instr[oparg].op.code == END_FOR || + next_instr[oparg].op.code == INSTRUMENTED_END_FOR); + assert(next_instr - this_instr + oparg <= UINT16_MAX); + frame->return_offset = (uint16_t)(next_instr - this_instr + oparg); + DISPATCH_INLINED(gen_frame); + } + + TARGET(FOR_ITER_LIST) { + frame->instr_ptr = next_instr; + next_instr += 2; + INSTRUCTION_STATS(FOR_ITER_LIST); + static_assert(INLINE_CACHE_ENTRIES_FOR_ITER == 1, "incorrect cache size"); + PyObject *iter; + PyObject *next; + /* Skip 1 cache entry */ + // _ITER_CHECK_LIST + iter = stack_pointer[-1]; + { + DEOPT_IF(Py_TYPE(iter) != &PyListIter_Type, FOR_ITER); + } + // _ITER_JUMP_LIST + { + _PyListIterObject *it = (_PyListIterObject *)iter; + assert(Py_TYPE(iter) == &PyListIter_Type); + STAT_INC(FOR_ITER, hit); + PyListObject *seq = it->it_seq; + if (seq == NULL || it->it_index >= PyList_GET_SIZE(seq)) { + if (seq != NULL) { + it->it_seq = NULL; + Py_DECREF(seq); + } + Py_DECREF(iter); + STACK_SHRINK(1); + /* Jump forward oparg, then skip following END_FOR instruction */ + JUMPBY(oparg + 1); + DISPATCH(); + } + } + // _ITER_NEXT_LIST + { + _PyListIterObject *it = (_PyListIterObject *)iter; + assert(Py_TYPE(iter) == &PyListIter_Type); + PyListObject *seq = it->it_seq; + assert(seq); + assert(it->it_index < PyList_GET_SIZE(seq)); + next = Py_NewRef(PyList_GET_ITEM(seq, it->it_index++)); } - STACK_SHRINK(1); - stack_pointer[-2] = none; - stack_pointer[-1] = value; - DISPATCH(); - } - - TARGET(LOAD_ASSERTION_ERROR) { - PyObject *value; - value = Py_NewRef(PyExc_AssertionError); - STACK_GROW(1); - stack_pointer[-1] = value; + stack_pointer[0] = next; + stack_pointer += 1; DISPATCH(); } - TARGET(LOAD_BUILD_CLASS) { - PyObject *bc; - if (PyMapping_GetOptionalItem(BUILTINS(), &_Py_ID(__build_class__), &bc) < 0) goto error; - if (bc == NULL) { - _PyErr_SetString(tstate, PyExc_NameError, - "__build_class__ not found"); - if (true) goto error; + TARGET(FOR_ITER_RANGE) { + frame->instr_ptr = next_instr; + next_instr += 2; + INSTRUCTION_STATS(FOR_ITER_RANGE); + static_assert(INLINE_CACHE_ENTRIES_FOR_ITER == 1, "incorrect cache size"); + PyObject *iter; + PyObject *next; + /* Skip 1 cache entry */ + // _ITER_CHECK_RANGE + iter = stack_pointer[-1]; + { + _PyRangeIterObject *r = (_PyRangeIterObject *)iter; + DEOPT_IF(Py_TYPE(r) != &PyRangeIter_Type, FOR_ITER); } - STACK_GROW(1); - stack_pointer[-1] = bc; - DISPATCH(); - } - - TARGET(STORE_NAME) { - PyObject *v; - v = stack_pointer[-1]; - PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); - PyObject *ns = LOCALS(); - int err; - if (ns == NULL) { - _PyErr_Format(tstate, PyExc_SystemError, - "no locals found when storing %R", name); - Py_DECREF(v); - if (true) goto pop_1_error; + // _ITER_JUMP_RANGE + { + _PyRangeIterObject *r = (_PyRangeIterObject *)iter; + assert(Py_TYPE(r) == &PyRangeIter_Type); + STAT_INC(FOR_ITER, hit); + if (r->len <= 0) { + STACK_SHRINK(1); + Py_DECREF(r); + // Jump over END_FOR instruction. + JUMPBY(oparg + 1); + DISPATCH(); + } } - if (PyDict_CheckExact(ns)) - err = PyDict_SetItem(ns, name, v); - else - err = PyObject_SetItem(ns, name, v); - Py_DECREF(v); - if (err) goto pop_1_error; - STACK_SHRINK(1); + // _ITER_NEXT_RANGE + { + _PyRangeIterObject *r = (_PyRangeIterObject *)iter; + assert(Py_TYPE(r) == &PyRangeIter_Type); + assert(r->len > 0); + long value = r->start; + r->start = value + r->step; + r->len--; + next = PyLong_FromLong(value); + if (next == NULL) goto error; + } + stack_pointer[0] = next; + stack_pointer += 1; DISPATCH(); } - TARGET(DELETE_NAME) { - PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); - PyObject *ns = LOCALS(); - int err; - if (ns == NULL) { - _PyErr_Format(tstate, PyExc_SystemError, - "no locals when deleting %R", name); - goto error; + TARGET(FOR_ITER_TUPLE) { + frame->instr_ptr = next_instr; + next_instr += 2; + INSTRUCTION_STATS(FOR_ITER_TUPLE); + static_assert(INLINE_CACHE_ENTRIES_FOR_ITER == 1, "incorrect cache size"); + PyObject *iter; + PyObject *next; + /* Skip 1 cache entry */ + // _ITER_CHECK_TUPLE + iter = stack_pointer[-1]; + { + DEOPT_IF(Py_TYPE(iter) != &PyTupleIter_Type, FOR_ITER); } - err = PyObject_DelItem(ns, name); - // Can't use ERROR_IF here. - if (err != 0) { - _PyEval_FormatExcCheckArg(tstate, PyExc_NameError, - NAME_ERROR_MSG, - name); - goto error; + // _ITER_JUMP_TUPLE + { + _PyTupleIterObject *it = (_PyTupleIterObject *)iter; + assert(Py_TYPE(iter) == &PyTupleIter_Type); + STAT_INC(FOR_ITER, hit); + PyTupleObject *seq = it->it_seq; + if (seq == NULL || it->it_index >= PyTuple_GET_SIZE(seq)) { + if (seq != NULL) { + it->it_seq = NULL; + Py_DECREF(seq); + } + Py_DECREF(iter); + STACK_SHRINK(1); + /* Jump forward oparg, then skip following END_FOR instruction */ + JUMPBY(oparg + 1); + DISPATCH(); + } + } + // _ITER_NEXT_TUPLE + { + _PyTupleIterObject *it = (_PyTupleIterObject *)iter; + assert(Py_TYPE(iter) == &PyTupleIter_Type); + PyTupleObject *seq = it->it_seq; + assert(seq); + assert(it->it_index < PyTuple_GET_SIZE(seq)); + next = Py_NewRef(PyTuple_GET_ITEM(seq, it->it_index++)); } + stack_pointer[0] = next; + stack_pointer += 1; DISPATCH(); } - TARGET(UNPACK_SEQUENCE) { - PREDICTED(UNPACK_SEQUENCE); - static_assert(INLINE_CACHE_ENTRIES_UNPACK_SEQUENCE == 1, "incorrect cache size"); - PyObject *seq; - seq = stack_pointer[-1]; - #if ENABLE_SPECIALIZATION - _PyUnpackSequenceCache *cache = (_PyUnpackSequenceCache *)next_instr; - if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) { - next_instr--; - _Py_Specialize_UnpackSequence(seq, next_instr, oparg); - DISPATCH_SAME_OPARG(); - } - STAT_INC(UNPACK_SEQUENCE, deferred); - DECREMENT_ADAPTIVE_COUNTER(cache->counter); - #endif /* ENABLE_SPECIALIZATION */ - PyObject **top = stack_pointer + oparg - 1; - int res = _PyEval_UnpackIterable(tstate, seq, oparg, -1, top); - Py_DECREF(seq); - if (res == 0) goto pop_1_error; - STACK_SHRINK(1); - STACK_GROW(oparg); + TARGET(GET_AITER) { + frame->instr_ptr = next_instr; next_instr += 1; + INSTRUCTION_STATS(GET_AITER); + PyObject *obj; + PyObject *iter; + obj = stack_pointer[-1]; + unaryfunc getter = NULL; + PyTypeObject *type = Py_TYPE(obj); + if (type->tp_as_async != NULL) { + getter = type->tp_as_async->am_aiter; + } + if (getter == NULL) { + _PyErr_Format(tstate, PyExc_TypeError, + "'async for' requires an object with " + "__aiter__ method, got %.100s", + type->tp_name); + Py_DECREF(obj); + if (true) goto pop_1_error; + } + iter = (*getter)(obj); + Py_DECREF(obj); + if (iter == NULL) goto pop_1_error; + if (Py_TYPE(iter)->tp_as_async == NULL || + Py_TYPE(iter)->tp_as_async->am_anext == NULL) { + _PyErr_Format(tstate, PyExc_TypeError, + "'async for' received an object from __aiter__ " + "that does not implement __anext__: %.100s", + Py_TYPE(iter)->tp_name); + Py_DECREF(iter); + if (true) goto pop_1_error; + } + stack_pointer[-1] = iter; DISPATCH(); } - TARGET(UNPACK_SEQUENCE_TWO_TUPLE) { - PyObject *seq; - PyObject **values; - seq = stack_pointer[-1]; - values = stack_pointer - 1; - DEOPT_IF(!PyTuple_CheckExact(seq), UNPACK_SEQUENCE); - DEOPT_IF(PyTuple_GET_SIZE(seq) != 2, UNPACK_SEQUENCE); - assert(oparg == 2); - STAT_INC(UNPACK_SEQUENCE, hit); - values[0] = Py_NewRef(PyTuple_GET_ITEM(seq, 1)); - values[1] = Py_NewRef(PyTuple_GET_ITEM(seq, 0)); - Py_DECREF(seq); - STACK_SHRINK(1); - STACK_GROW(oparg); + TARGET(GET_ANEXT) { + frame->instr_ptr = next_instr; next_instr += 1; + INSTRUCTION_STATS(GET_ANEXT); + PyObject *aiter; + PyObject *awaitable; + aiter = stack_pointer[-1]; + unaryfunc getter = NULL; + PyObject *next_iter = NULL; + PyTypeObject *type = Py_TYPE(aiter); + if (PyAsyncGen_CheckExact(aiter)) { + awaitable = type->tp_as_async->am_anext(aiter); + if (awaitable == NULL) { + GOTO_ERROR(error); + } + } else { + if (type->tp_as_async != NULL){ + getter = type->tp_as_async->am_anext; + } + if (getter != NULL) { + next_iter = (*getter)(aiter); + if (next_iter == NULL) { + GOTO_ERROR(error); + } + } + else { + _PyErr_Format(tstate, PyExc_TypeError, + "'async for' requires an iterator with " + "__anext__ method, got %.100s", + type->tp_name); + GOTO_ERROR(error); + } + awaitable = _PyCoro_GetAwaitableIter(next_iter); + if (awaitable == NULL) { + _PyErr_FormatFromCause( + PyExc_TypeError, + "'async for' received an invalid object " + "from __anext__: %.100s", + Py_TYPE(next_iter)->tp_name); + Py_DECREF(next_iter); + GOTO_ERROR(error); + } else { + Py_DECREF(next_iter); + } + } + stack_pointer[0] = awaitable; + stack_pointer += 1; DISPATCH(); } - TARGET(UNPACK_SEQUENCE_TUPLE) { - PyObject *seq; - PyObject **values; - seq = stack_pointer[-1]; - values = stack_pointer - 1; - DEOPT_IF(!PyTuple_CheckExact(seq), UNPACK_SEQUENCE); - DEOPT_IF(PyTuple_GET_SIZE(seq) != oparg, UNPACK_SEQUENCE); - STAT_INC(UNPACK_SEQUENCE, hit); - PyObject **items = _PyTuple_ITEMS(seq); - for (int i = oparg; --i >= 0; ) { - *values++ = Py_NewRef(items[i]); - } - Py_DECREF(seq); - STACK_SHRINK(1); - STACK_GROW(oparg); + TARGET(GET_AWAITABLE) { + frame->instr_ptr = next_instr; next_instr += 1; + INSTRUCTION_STATS(GET_AWAITABLE); + PyObject *iterable; + PyObject *iter; + iterable = stack_pointer[-1]; + iter = _PyCoro_GetAwaitableIter(iterable); + if (iter == NULL) { + _PyEval_FormatAwaitableError(tstate, Py_TYPE(iterable), oparg); + } + Py_DECREF(iterable); + if (iter != NULL && PyCoro_CheckExact(iter)) { + PyObject *yf = _PyGen_yf((PyGenObject*)iter); + if (yf != NULL) { + /* `iter` is a coroutine object that is being + awaited, `yf` is a pointer to the current awaitable + being awaited on. */ + Py_DECREF(yf); + Py_CLEAR(iter); + _PyErr_SetString(tstate, PyExc_RuntimeError, + "coroutine is being awaited already"); + /* The code below jumps to `error` if `iter` is NULL. */ + } + } + if (iter == NULL) goto pop_1_error; + stack_pointer[-1] = iter; DISPATCH(); } - TARGET(UNPACK_SEQUENCE_LIST) { - PyObject *seq; - PyObject **values; - seq = stack_pointer[-1]; - values = stack_pointer - 1; - DEOPT_IF(!PyList_CheckExact(seq), UNPACK_SEQUENCE); - DEOPT_IF(PyList_GET_SIZE(seq) != oparg, UNPACK_SEQUENCE); - STAT_INC(UNPACK_SEQUENCE, hit); - PyObject **items = _PyList_ITEMS(seq); - for (int i = oparg; --i >= 0; ) { - *values++ = Py_NewRef(items[i]); - } - Py_DECREF(seq); - STACK_SHRINK(1); - STACK_GROW(oparg); + TARGET(GET_ITER) { + frame->instr_ptr = next_instr; next_instr += 1; + INSTRUCTION_STATS(GET_ITER); + PyObject *iterable; + PyObject *iter; + iterable = stack_pointer[-1]; + /* before: [obj]; after [getiter(obj)] */ + iter = PyObject_GetIter(iterable); + Py_DECREF(iterable); + if (iter == NULL) goto pop_1_error; + stack_pointer[-1] = iter; DISPATCH(); } - TARGET(UNPACK_EX) { - PyObject *seq; - seq = stack_pointer[-1]; - int totalargs = 1 + (oparg & 0xFF) + (oparg >> 8); - PyObject **top = stack_pointer + totalargs - 1; - int res = _PyEval_UnpackIterable(tstate, seq, oparg & 0xFF, oparg >> 8, top); - Py_DECREF(seq); - if (res == 0) goto pop_1_error; - STACK_GROW((oparg & 0xFF) + (oparg >> 8)); + TARGET(GET_LEN) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(GET_LEN); + PyObject *obj; + PyObject *len_o; + obj = stack_pointer[-1]; + // PUSH(len(TOS)) + Py_ssize_t len_i = PyObject_Length(obj); + if (len_i < 0) goto error; + len_o = PyLong_FromSsize_t(len_i); + if (len_o == NULL) goto error; + stack_pointer[0] = len_o; + stack_pointer += 1; DISPATCH(); } - TARGET(STORE_ATTR) { - PREDICTED(STORE_ATTR); - static_assert(INLINE_CACHE_ENTRIES_STORE_ATTR == 4, "incorrect cache size"); - PyObject *owner; - PyObject *v; - owner = stack_pointer[-1]; - v = stack_pointer[-2]; - #if ENABLE_SPECIALIZATION - _PyAttrCache *cache = (_PyAttrCache *)next_instr; - if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) { - PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); - next_instr--; - _Py_Specialize_StoreAttr(owner, next_instr, name); - DISPATCH_SAME_OPARG(); + TARGET(GET_YIELD_FROM_ITER) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(GET_YIELD_FROM_ITER); + PyObject *iterable; + PyObject *iter; + iterable = stack_pointer[-1]; + /* before: [obj]; after [getiter(obj)] */ + if (PyCoro_CheckExact(iterable)) { + /* `iterable` is a coroutine */ + if (!(_PyFrame_GetCode(frame)->co_flags & (CO_COROUTINE | CO_ITERABLE_COROUTINE))) { + /* and it is used in a 'yield from' expression of a + regular generator. */ + _PyErr_SetString(tstate, PyExc_TypeError, + "cannot 'yield from' a coroutine object " + "in a non-coroutine generator"); + GOTO_ERROR(error); + } + iter = iterable; } - STAT_INC(STORE_ATTR, deferred); - DECREMENT_ADAPTIVE_COUNTER(cache->counter); - #endif /* ENABLE_SPECIALIZATION */ - PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); - int err = PyObject_SetAttr(owner, name, v); - Py_DECREF(v); - Py_DECREF(owner); - if (err) goto pop_2_error; - STACK_SHRINK(2); - next_instr += 4; + else if (PyGen_CheckExact(iterable)) { + iter = iterable; + } + else { + /* `iterable` is not a generator. */ + iter = PyObject_GetIter(iterable); + if (iter == NULL) { + GOTO_ERROR(error); + } + Py_DECREF(iterable); + } + stack_pointer[-1] = iter; DISPATCH(); } - TARGET(DELETE_ATTR) { - PyObject *owner; - owner = stack_pointer[-1]; + TARGET(IMPORT_FROM) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(IMPORT_FROM); + PyObject *from; + PyObject *res; + from = stack_pointer[-1]; + TIER_ONE_ONLY PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); - int err = PyObject_DelAttr(owner, name); - Py_DECREF(owner); - if (err) goto pop_1_error; - STACK_SHRINK(1); + res = import_from(tstate, from, name); + if (res == NULL) goto error; + stack_pointer[0] = res; + stack_pointer += 1; DISPATCH(); } - TARGET(STORE_GLOBAL) { - PyObject *v; - v = stack_pointer[-1]; + TARGET(IMPORT_NAME) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(IMPORT_NAME); + PyObject *fromlist; + PyObject *level; + PyObject *res; + fromlist = stack_pointer[-1]; + level = stack_pointer[-2]; + TIER_ONE_ONLY PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); - int err = PyDict_SetItem(GLOBALS(), name, v); - Py_DECREF(v); - if (err) goto pop_1_error; - STACK_SHRINK(1); + res = import_name(tstate, frame, name, fromlist, level); + Py_DECREF(level); + Py_DECREF(fromlist); + if (res == NULL) goto pop_2_error; + stack_pointer[-2] = res; + stack_pointer += -1; DISPATCH(); } - TARGET(DELETE_GLOBAL) { - PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); - int err; - err = PyDict_DelItem(GLOBALS(), name); - // Can't use ERROR_IF here. - if (err != 0) { - if (_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) { - _PyEval_FormatExcCheckArg(tstate, PyExc_NameError, - NAME_ERROR_MSG, name); - } - goto error; - } - DISPATCH(); + TARGET(INSTRUMENTED_CALL) { + _Py_CODEUNIT *this_instr = frame->instr_ptr = next_instr; + next_instr += 4; + INSTRUCTION_STATS(INSTRUMENTED_CALL); + /* Skip 3 cache entries */ + int is_meth = PEEK(oparg + 1) != NULL; + int total_args = oparg + is_meth; + PyObject *function = PEEK(oparg + 2); + PyObject *arg = total_args == 0 ? + &_PyInstrumentation_MISSING : PEEK(total_args); + int err = _Py_call_instrumentation_2args( + tstate, PY_MONITORING_EVENT_CALL, + frame, this_instr, function, arg); + if (err) goto error; + INCREMENT_ADAPTIVE_COUNTER(this_instr[1].cache); + GO_TO_INSTRUCTION(CALL); } - TARGET(LOAD_LOCALS) { - PyObject *locals; - locals = LOCALS(); - if (locals == NULL) { - _PyErr_SetString(tstate, PyExc_SystemError, - "no locals found"); - if (true) goto error; - } - Py_INCREF(locals); - STACK_GROW(1); - stack_pointer[-1] = locals; - DISPATCH(); + TARGET(INSTRUMENTED_CALL_FUNCTION_EX) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(INSTRUMENTED_CALL_FUNCTION_EX); + GO_TO_INSTRUCTION(CALL_FUNCTION_EX); } - TARGET(LOAD_NAME) { - PyObject *locals; - PyObject *mod_or_class_dict; - PyObject *v; - // _LOAD_LOCALS - { - locals = LOCALS(); - if (locals == NULL) { - _PyErr_SetString(tstate, PyExc_SystemError, - "no locals found"); - if (true) goto error; - } - Py_INCREF(locals); - } - // _LOAD_FROM_DICT_OR_GLOBALS - mod_or_class_dict = locals; - { - PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); - if (PyMapping_GetOptionalItem(mod_or_class_dict, name, &v) < 0) { - Py_DECREF(mod_or_class_dict); - goto error; - } - Py_DECREF(mod_or_class_dict); - if (v == NULL) { - v = PyDict_GetItemWithError(GLOBALS(), name); - if (v != NULL) { - Py_INCREF(v); - } - else if (_PyErr_Occurred(tstate)) { - goto error; - } - else { - if (PyMapping_GetOptionalItem(BUILTINS(), name, &v) < 0) { - goto error; - } - if (v == NULL) { - _PyEval_FormatExcCheckArg( - tstate, PyExc_NameError, - NAME_ERROR_MSG, name); - goto error; - } - } + TARGET(INSTRUMENTED_CALL_KW) { + _Py_CODEUNIT *this_instr = frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(INSTRUMENTED_CALL_KW); + int is_meth = PEEK(oparg + 2) != NULL; + int total_args = oparg + is_meth; + PyObject *function = PEEK(oparg + 3); + PyObject *arg = total_args == 0 ? &_PyInstrumentation_MISSING + : PEEK(total_args + 1); + int err = _Py_call_instrumentation_2args( + tstate, PY_MONITORING_EVENT_CALL, + frame, this_instr, function, arg); + if (err) goto error; + GO_TO_INSTRUCTION(CALL_KW); + } + + TARGET(INSTRUMENTED_END_FOR) { + _Py_CODEUNIT *this_instr = frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(INSTRUMENTED_END_FOR); + PyObject *value; + PyObject *receiver; + value = stack_pointer[-1]; + receiver = stack_pointer[-2]; + TIER_ONE_ONLY + /* Need to create a fake StopIteration error here, + * to conform to PEP 380 */ + if (PyGen_Check(receiver)) { + PyErr_SetObject(PyExc_StopIteration, value); + if (monitor_stop_iteration(tstate, frame, this_instr)) { + GOTO_ERROR(error); } + PyErr_SetRaisedException(NULL); } - STACK_GROW(1); - stack_pointer[-1] = v; + Py_DECREF(receiver); + Py_DECREF(value); + stack_pointer += -2; DISPATCH(); } - TARGET(LOAD_FROM_DICT_OR_GLOBALS) { - PyObject *mod_or_class_dict; - PyObject *v; - mod_or_class_dict = stack_pointer[-1]; - PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); - if (PyMapping_GetOptionalItem(mod_or_class_dict, name, &v) < 0) { - Py_DECREF(mod_or_class_dict); - goto error; - } - Py_DECREF(mod_or_class_dict); - if (v == NULL) { - v = PyDict_GetItemWithError(GLOBALS(), name); - if (v != NULL) { - Py_INCREF(v); - } - else if (_PyErr_Occurred(tstate)) { - goto error; - } - else { - if (PyMapping_GetOptionalItem(BUILTINS(), name, &v) < 0) { - goto error; - } - if (v == NULL) { - _PyEval_FormatExcCheckArg( - tstate, PyExc_NameError, - NAME_ERROR_MSG, name); - goto error; - } + TARGET(INSTRUMENTED_END_SEND) { + _Py_CODEUNIT *this_instr = frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(INSTRUMENTED_END_SEND); + PyObject *value; + PyObject *receiver; + value = stack_pointer[-1]; + receiver = stack_pointer[-2]; + TIER_ONE_ONLY + if (PyGen_Check(receiver) || PyCoro_CheckExact(receiver)) { + PyErr_SetObject(PyExc_StopIteration, value); + if (monitor_stop_iteration(tstate, frame, this_instr)) { + GOTO_ERROR(error); } + PyErr_SetRaisedException(NULL); } - stack_pointer[-1] = v; + Py_DECREF(receiver); + stack_pointer[-2] = value; + stack_pointer += -1; DISPATCH(); } - TARGET(LOAD_GLOBAL) { - PREDICTED(LOAD_GLOBAL); - static_assert(INLINE_CACHE_ENTRIES_LOAD_GLOBAL == 4, "incorrect cache size"); - PyObject *null = NULL; - PyObject *v; - #if ENABLE_SPECIALIZATION - _PyLoadGlobalCache *cache = (_PyLoadGlobalCache *)next_instr; - if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) { - PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1); - next_instr--; - _Py_Specialize_LoadGlobal(GLOBALS(), BUILTINS(), next_instr, name); - DISPATCH_SAME_OPARG(); - } - STAT_INC(LOAD_GLOBAL, deferred); - DECREMENT_ADAPTIVE_COUNTER(cache->counter); - #endif /* ENABLE_SPECIALIZATION */ - PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1); - if (PyDict_CheckExact(GLOBALS()) - && PyDict_CheckExact(BUILTINS())) - { - v = _PyDict_LoadGlobal((PyDictObject *)GLOBALS(), - (PyDictObject *)BUILTINS(), - name); - if (v == NULL) { - if (!_PyErr_Occurred(tstate)) { - /* _PyDict_LoadGlobal() returns NULL without raising - * an exception if the key doesn't exist */ - _PyEval_FormatExcCheckArg(tstate, PyExc_NameError, - NAME_ERROR_MSG, name); - } - if (true) goto error; - } - Py_INCREF(v); + TARGET(INSTRUMENTED_FOR_ITER) { + _Py_CODEUNIT *this_instr = frame->instr_ptr = next_instr; + next_instr += 2; + INSTRUCTION_STATS(INSTRUMENTED_FOR_ITER); + /* Skip 1 cache entry */ + _Py_CODEUNIT *target; + PyObject *iter = TOP(); + PyObject *next = (*Py_TYPE(iter)->tp_iternext)(iter); + if (next != NULL) { + PUSH(next); + target = next_instr; } else { - /* Slow-path if globals or builtins is not a dict */ - - /* namespace 1: globals */ - if (PyMapping_GetOptionalItem(GLOBALS(), name, &v) < 0) goto error; - if (v == NULL) { - /* namespace 2: builtins */ - if (PyMapping_GetOptionalItem(BUILTINS(), name, &v) < 0) goto error; - if (v == NULL) { - _PyEval_FormatExcCheckArg( - tstate, PyExc_NameError, - NAME_ERROR_MSG, name); - if (true) goto error; + if (_PyErr_Occurred(tstate)) { + if (!_PyErr_ExceptionMatches(tstate, PyExc_StopIteration)) { + GOTO_ERROR(error); } + monitor_raise(tstate, frame, this_instr); + _PyErr_Clear(tstate); } + /* iterator ended normally */ + assert(next_instr[oparg].op.code == END_FOR || + next_instr[oparg].op.code == INSTRUMENTED_END_FOR); + STACK_SHRINK(1); + Py_DECREF(iter); + /* Skip END_FOR */ + target = next_instr + oparg + 1; } - null = NULL; - STACK_GROW(1); - STACK_GROW(((oparg & 1) ? 1 : 0)); - if (oparg & 1) { stack_pointer[-1 - (oparg & 1 ? 1 : 0)] = null; } - stack_pointer[-1] = v; - next_instr += 4; + INSTRUMENTED_JUMP(this_instr, target, PY_MONITORING_EVENT_BRANCH); DISPATCH(); } - TARGET(LOAD_GLOBAL_MODULE) { - PyObject *null = NULL; - PyObject *res; - // _GUARD_GLOBALS_VERSION - { - uint16_t version = read_u16(&next_instr[1].cache); - PyDictObject *dict = (PyDictObject *)GLOBALS(); - DEOPT_IF(!PyDict_CheckExact(dict), LOAD_GLOBAL); - DEOPT_IF(dict->ma_keys->dk_version != version, LOAD_GLOBAL); - assert(DK_IS_UNICODE(dict->ma_keys)); - } - // _LOAD_GLOBAL_MODULE - { - uint16_t index = read_u16(&next_instr[3].cache); - PyDictObject *dict = (PyDictObject *)GLOBALS(); - PyDictUnicodeEntry *entries = DK_UNICODE_ENTRIES(dict->ma_keys); - res = entries[index].me_value; - DEOPT_IF(res == NULL, LOAD_GLOBAL); - Py_INCREF(res); - STAT_INC(LOAD_GLOBAL, hit); - null = NULL; + TARGET(INSTRUMENTED_INSTRUCTION) { + _Py_CODEUNIT *this_instr = frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(INSTRUMENTED_INSTRUCTION); + int next_opcode = _Py_call_instrumentation_instruction( + tstate, frame, this_instr); + if (next_opcode < 0) goto error; + next_instr = this_instr; + if (_PyOpcode_Caches[next_opcode]) { + INCREMENT_ADAPTIVE_COUNTER(this_instr[1].cache); } - STACK_GROW(1); - STACK_GROW(((oparg & 1) ? 1 : 0)); - if (oparg & 1) { stack_pointer[-1 - (oparg & 1 ? 1 : 0)] = null; } - stack_pointer[-1] = res; - next_instr += 4; + assert(next_opcode > 0 && next_opcode < 256); + opcode = next_opcode; + DISPATCH_GOTO(); + } + + TARGET(INSTRUMENTED_JUMP_BACKWARD) { + _Py_CODEUNIT *this_instr = frame->instr_ptr = next_instr; + next_instr += 2; + INSTRUCTION_STATS(INSTRUMENTED_JUMP_BACKWARD); + /* Skip 1 cache entry */ + CHECK_EVAL_BREAKER(); + INSTRUMENTED_JUMP(this_instr, next_instr - oparg, PY_MONITORING_EVENT_JUMP); DISPATCH(); } - TARGET(LOAD_GLOBAL_BUILTIN) { - PyObject *null = NULL; - PyObject *res; - // _GUARD_GLOBALS_VERSION - { - uint16_t version = read_u16(&next_instr[1].cache); - PyDictObject *dict = (PyDictObject *)GLOBALS(); - DEOPT_IF(!PyDict_CheckExact(dict), LOAD_GLOBAL); - DEOPT_IF(dict->ma_keys->dk_version != version, LOAD_GLOBAL); - assert(DK_IS_UNICODE(dict->ma_keys)); - } - // _GUARD_BUILTINS_VERSION - { - uint16_t version = read_u16(&next_instr[2].cache); - PyDictObject *dict = (PyDictObject *)BUILTINS(); - DEOPT_IF(!PyDict_CheckExact(dict), LOAD_GLOBAL); - DEOPT_IF(dict->ma_keys->dk_version != version, LOAD_GLOBAL); - assert(DK_IS_UNICODE(dict->ma_keys)); - } - // _LOAD_GLOBAL_BUILTINS - { - uint16_t index = read_u16(&next_instr[3].cache); - PyDictObject *bdict = (PyDictObject *)BUILTINS(); - PyDictUnicodeEntry *entries = DK_UNICODE_ENTRIES(bdict->ma_keys); - res = entries[index].me_value; - DEOPT_IF(res == NULL, LOAD_GLOBAL); - Py_INCREF(res); - STAT_INC(LOAD_GLOBAL, hit); - null = NULL; - } - STACK_GROW(1); - STACK_GROW(((oparg & 1) ? 1 : 0)); - if (oparg & 1) { stack_pointer[-1 - (oparg & 1 ? 1 : 0)] = null; } - stack_pointer[-1] = res; - next_instr += 4; + TARGET(INSTRUMENTED_JUMP_FORWARD) { + _Py_CODEUNIT *this_instr = frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(INSTRUMENTED_JUMP_FORWARD); + INSTRUMENTED_JUMP(this_instr, next_instr + oparg, PY_MONITORING_EVENT_JUMP); DISPATCH(); } - TARGET(DELETE_FAST) { - PyObject *v = GETLOCAL(oparg); - if (v == NULL) goto unbound_local_error; - SETLOCAL(oparg, NULL); + TARGET(INSTRUMENTED_LOAD_SUPER_ATTR) { + _Py_CODEUNIT *this_instr = frame->instr_ptr = next_instr; + next_instr += 2; + INSTRUCTION_STATS(INSTRUMENTED_LOAD_SUPER_ATTR); + /* Skip 1 cache entry */ + // cancel out the decrement that will happen in LOAD_SUPER_ATTR; we + // don't want to specialize instrumented instructions + INCREMENT_ADAPTIVE_COUNTER(this_instr[1].cache); + GO_TO_INSTRUCTION(LOAD_SUPER_ATTR); + } + + TARGET(INSTRUMENTED_POP_JUMP_IF_FALSE) { + _Py_CODEUNIT *this_instr = frame->instr_ptr = next_instr; + next_instr += 2; + INSTRUCTION_STATS(INSTRUMENTED_POP_JUMP_IF_FALSE); + /* Skip 1 cache entry */ + PyObject *cond = POP(); + assert(PyBool_Check(cond)); + int flag = Py_IsFalse(cond); + int offset = flag * oparg; + #if ENABLE_SPECIALIZATION + this_instr[1].cache = (this_instr[1].cache << 1) | flag; + #endif + INSTRUMENTED_JUMP(this_instr, next_instr + offset, PY_MONITORING_EVENT_BRANCH); DISPATCH(); } - TARGET(MAKE_CELL) { - // "initial" is probably NULL but not if it's an arg (or set - // via PyFrame_LocalsToFast() before MAKE_CELL has run). - PyObject *initial = GETLOCAL(oparg); - PyObject *cell = PyCell_New(initial); - if (cell == NULL) { - goto resume_with_error; + TARGET(INSTRUMENTED_POP_JUMP_IF_NONE) { + _Py_CODEUNIT *this_instr = frame->instr_ptr = next_instr; + next_instr += 2; + INSTRUCTION_STATS(INSTRUMENTED_POP_JUMP_IF_NONE); + /* Skip 1 cache entry */ + PyObject *value = POP(); + int flag = Py_IsNone(value); + int offset; + if (flag) { + offset = oparg; } - SETLOCAL(oparg, cell); + else { + Py_DECREF(value); + offset = 0; + } + #if ENABLE_SPECIALIZATION + this_instr[1].cache = (this_instr[1].cache << 1) | flag; + #endif + INSTRUMENTED_JUMP(this_instr, next_instr + offset, PY_MONITORING_EVENT_BRANCH); DISPATCH(); } - TARGET(DELETE_DEREF) { - PyObject *cell = GETLOCAL(oparg); - PyObject *oldobj = PyCell_GET(cell); - // Can't use ERROR_IF here. - // Fortunately we don't need its superpower. - if (oldobj == NULL) { - _PyEval_FormatExcUnbound(tstate, _PyFrame_GetCode(frame), oparg); - goto error; + TARGET(INSTRUMENTED_POP_JUMP_IF_NOT_NONE) { + _Py_CODEUNIT *this_instr = frame->instr_ptr = next_instr; + next_instr += 2; + INSTRUCTION_STATS(INSTRUMENTED_POP_JUMP_IF_NOT_NONE); + /* Skip 1 cache entry */ + PyObject *value = POP(); + int offset; + int nflag = Py_IsNone(value); + if (nflag) { + offset = 0; } - PyCell_SET(cell, NULL); - Py_DECREF(oldobj); + else { + Py_DECREF(value); + offset = oparg; + } + #if ENABLE_SPECIALIZATION + this_instr[1].cache = (this_instr[1].cache << 1) | !nflag; + #endif + INSTRUMENTED_JUMP(this_instr, next_instr + offset, PY_MONITORING_EVENT_BRANCH); DISPATCH(); } - TARGET(LOAD_FROM_DICT_OR_DEREF) { - PyObject *class_dict; - PyObject *value; - class_dict = stack_pointer[-1]; - PyObject *name; - assert(class_dict); - assert(oparg >= 0 && oparg < _PyFrame_GetCode(frame)->co_nlocalsplus); - name = PyTuple_GET_ITEM(_PyFrame_GetCode(frame)->co_localsplusnames, oparg); - if (PyMapping_GetOptionalItem(class_dict, name, &value) < 0) { - Py_DECREF(class_dict); - goto error; + TARGET(INSTRUMENTED_POP_JUMP_IF_TRUE) { + _Py_CODEUNIT *this_instr = frame->instr_ptr = next_instr; + next_instr += 2; + INSTRUCTION_STATS(INSTRUMENTED_POP_JUMP_IF_TRUE); + /* Skip 1 cache entry */ + PyObject *cond = POP(); + assert(PyBool_Check(cond)); + int flag = Py_IsTrue(cond); + int offset = flag * oparg; + #if ENABLE_SPECIALIZATION + this_instr[1].cache = (this_instr[1].cache << 1) | flag; + #endif + INSTRUMENTED_JUMP(this_instr, next_instr + offset, PY_MONITORING_EVENT_BRANCH); + DISPATCH(); + } + + TARGET(INSTRUMENTED_RESUME) { + _Py_CODEUNIT *this_instr = frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(INSTRUMENTED_RESUME); + uintptr_t global_version = _Py_atomic_load_uintptr_relaxed(&tstate->interp->ceval.eval_breaker) & ~_PY_EVAL_EVENTS_MASK; + uintptr_t code_version = _PyFrame_GetCode(frame)->_co_instrumentation_version; + if (code_version != global_version) { + if (_Py_Instrument(_PyFrame_GetCode(frame), tstate->interp)) { + GOTO_ERROR(error); + } + next_instr = this_instr; } - Py_DECREF(class_dict); - if (!value) { - PyObject *cell = GETLOCAL(oparg); - value = PyCell_GET(cell); - if (value == NULL) { - _PyEval_FormatExcUnbound(tstate, _PyFrame_GetCode(frame), oparg); - goto error; + else { + if ((oparg & RESUME_OPARG_LOCATION_MASK) < RESUME_AFTER_YIELD_FROM) { + CHECK_EVAL_BREAKER(); + } + _PyFrame_SetStackPointer(frame, stack_pointer); + int err = _Py_call_instrumentation( + tstate, oparg > 0, frame, this_instr); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (err) goto error; + if (frame->instr_ptr != this_instr) { + /* Instrumentation has jumped */ + next_instr = this_instr; + DISPATCH(); } - Py_INCREF(value); } - stack_pointer[-1] = value; DISPATCH(); } - TARGET(LOAD_DEREF) { - PyObject *value; - PyObject *cell = GETLOCAL(oparg); - value = PyCell_GET(cell); - if (value == NULL) { - _PyEval_FormatExcUnbound(tstate, _PyFrame_GetCode(frame), oparg); - if (true) goto error; - } - Py_INCREF(value); - STACK_GROW(1); - stack_pointer[-1] = value; - DISPATCH(); + TARGET(INSTRUMENTED_RETURN_CONST) { + _Py_CODEUNIT *this_instr = frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(INSTRUMENTED_RETURN_CONST); + PyObject *retval = GETITEM(FRAME_CO_CONSTS, oparg); + int err = _Py_call_instrumentation_arg( + tstate, PY_MONITORING_EVENT_PY_RETURN, + frame, this_instr, retval); + if (err) GOTO_ERROR(error); + Py_INCREF(retval); + assert(EMPTY()); + _PyFrame_SetStackPointer(frame, stack_pointer); + _Py_LeaveRecursiveCallPy(tstate); + assert(frame != &entry_frame); + // GH-99729: We need to unlink the frame *before* clearing it: + _PyInterpreterFrame *dying = frame; + frame = tstate->current_frame = dying->previous; + _PyEval_FrameClearAndPop(tstate, dying); + _PyFrame_StackPush(frame, retval); + LOAD_IP(frame->return_offset); + goto resume_frame; } - TARGET(STORE_DEREF) { - PyObject *v; - v = stack_pointer[-1]; - PyObject *cell = GETLOCAL(oparg); - PyObject *oldobj = PyCell_GET(cell); - PyCell_SET(cell, v); - Py_XDECREF(oldobj); + TARGET(INSTRUMENTED_RETURN_VALUE) { + _Py_CODEUNIT *this_instr = frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(INSTRUMENTED_RETURN_VALUE); + PyObject *retval; + retval = stack_pointer[-1]; + int err = _Py_call_instrumentation_arg( + tstate, PY_MONITORING_EVENT_PY_RETURN, + frame, this_instr, retval); + if (err) GOTO_ERROR(error); STACK_SHRINK(1); + assert(EMPTY()); + _PyFrame_SetStackPointer(frame, stack_pointer); + _Py_LeaveRecursiveCallPy(tstate); + assert(frame != &entry_frame); + // GH-99729: We need to unlink the frame *before* clearing it: + _PyInterpreterFrame *dying = frame; + frame = tstate->current_frame = dying->previous; + _PyEval_FrameClearAndPop(tstate, dying); + _PyFrame_StackPush(frame, retval); + LOAD_IP(frame->return_offset); + goto resume_frame; + } + + TARGET(INSTRUMENTED_YIELD_VALUE) { + _Py_CODEUNIT *this_instr = frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(INSTRUMENTED_YIELD_VALUE); + PyObject *retval; + retval = stack_pointer[-1]; + assert(frame != &entry_frame); + frame->instr_ptr = next_instr; + PyGenObject *gen = _PyFrame_GetGenerator(frame); + assert(FRAME_SUSPENDED_YIELD_FROM == FRAME_SUSPENDED + 1); + assert(oparg == 0 || oparg == 1); + gen->gi_frame_state = FRAME_SUSPENDED + oparg; + _PyFrame_SetStackPointer(frame, stack_pointer - 1); + int err = _Py_call_instrumentation_arg( + tstate, PY_MONITORING_EVENT_PY_YIELD, + frame, this_instr, retval); + if (err) GOTO_ERROR(error); + tstate->exc_info = gen->gi_exc_state.previous_item; + gen->gi_exc_state.previous_item = NULL; + _Py_LeaveRecursiveCallPy(tstate); + _PyInterpreterFrame *gen_frame = frame; + frame = tstate->current_frame = frame->previous; + gen_frame->previous = NULL; + _PyFrame_StackPush(frame, retval); + /* We don't know which of these is relevant here, so keep them equal */ + assert(INLINE_CACHE_ENTRIES_SEND == INLINE_CACHE_ENTRIES_FOR_ITER); + LOAD_IP(1 + INLINE_CACHE_ENTRIES_SEND); + goto resume_frame; + } + + TARGET(INTERPRETER_EXIT) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(INTERPRETER_EXIT); + PyObject *retval; + retval = stack_pointer[-1]; + TIER_ONE_ONLY + assert(frame == &entry_frame); + assert(_PyFrame_IsIncomplete(frame)); + /* Restore previous frame and return. */ + tstate->current_frame = frame->previous; + assert(!_PyErr_Occurred(tstate)); + tstate->c_recursion_remaining += PY_EVAL_C_STACK_UNITS; + return retval; + } + + TARGET(IS_OP) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(IS_OP); + PyObject *right; + PyObject *left; + PyObject *b; + right = stack_pointer[-1]; + left = stack_pointer[-2]; + int res = Py_Is(left, right) ^ oparg; + Py_DECREF(left); + Py_DECREF(right); + b = res ? Py_True : Py_False; + stack_pointer[-2] = b; + stack_pointer += -1; DISPATCH(); } - TARGET(COPY_FREE_VARS) { - /* Copy closure variables to free variables */ - PyCodeObject *co = _PyFrame_GetCode(frame); - assert(PyFunction_Check(frame->f_funcobj)); - PyObject *closure = ((PyFunctionObject *)frame->f_funcobj)->func_closure; - assert(oparg == co->co_nfreevars); - int offset = co->co_nlocalsplus - oparg; - for (int i = 0; i < oparg; ++i) { - PyObject *o = PyTuple_GET_ITEM(closure, i); - frame->localsplus[offset + i] = Py_NewRef(o); + TARGET(JUMP_BACKWARD) { + _Py_CODEUNIT *this_instr = frame->instr_ptr = next_instr; + next_instr += 2; + INSTRUCTION_STATS(JUMP_BACKWARD); + /* Skip 1 cache entry */ + CHECK_EVAL_BREAKER(); + assert(oparg <= INSTR_OFFSET()); + JUMPBY(-oparg); + #if ENABLE_SPECIALIZATION + this_instr[1].cache += (1 << OPTIMIZER_BITS_IN_COUNTER); + /* We are using unsigned values, but we really want signed values, so + * do the 2s complement comparison manually */ + uint16_t ucounter = this_instr[1].cache + (1 << 15); + uint16_t threshold = tstate->interp->optimizer_backedge_threshold + (1 << 15); + // Double-check that the opcode isn't instrumented or something: + if (ucounter > threshold && this_instr->op.code == JUMP_BACKWARD) { + OPT_STAT_INC(attempts); + _Py_CODEUNIT *start = this_instr; + /* Back up over EXTENDED_ARGs so optimizer sees the whole instruction */ + while (oparg > 255) { + oparg >>= 8; + start--; + } + int optimized = _PyOptimizer_Optimize(frame, start, stack_pointer); + if (optimized < 0) goto error; + if (optimized) { + // Rewind and enter the executor: + assert(start->op.code == ENTER_EXECUTOR); + next_instr = start; + this_instr[1].cache &= ((1 << OPTIMIZER_BITS_IN_COUNTER) - 1); + } + else { + int backoff = this_instr[1].cache & ((1 << OPTIMIZER_BITS_IN_COUNTER) - 1); + if (backoff < MINIMUM_TIER2_BACKOFF) { + backoff = MINIMUM_TIER2_BACKOFF; + } + else if (backoff < 15 - OPTIMIZER_BITS_IN_COUNTER) { + backoff++; + } + assert(backoff <= 15 - OPTIMIZER_BITS_IN_COUNTER); + this_instr[1].cache = ((1 << 16) - ((1 << OPTIMIZER_BITS_IN_COUNTER) << backoff)) | backoff; + } } + #endif /* ENABLE_SPECIALIZATION */ DISPATCH(); } - TARGET(BUILD_STRING) { - PyObject **pieces; - PyObject *str; - pieces = stack_pointer - oparg; - str = _PyUnicode_JoinArray(&_Py_STR(empty), pieces, oparg); - for (int _i = oparg; --_i >= 0;) { - Py_DECREF(pieces[_i]); - } - if (str == NULL) { STACK_SHRINK(oparg); goto error; } - STACK_SHRINK(oparg); - STACK_GROW(1); - stack_pointer[-1] = str; + TARGET(JUMP_BACKWARD_NO_INTERRUPT) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(JUMP_BACKWARD_NO_INTERRUPT); + TIER_ONE_ONLY + /* This bytecode is used in the `yield from` or `await` loop. + * If there is an interrupt, we want it handled in the innermost + * generator or coroutine, so we deliberately do not check it here. + * (see bpo-30039). + */ + JUMPBY(-oparg); DISPATCH(); } - TARGET(BUILD_TUPLE) { - PyObject **values; - PyObject *tup; - values = stack_pointer - oparg; - tup = _PyTuple_FromArraySteal(values, oparg); - if (tup == NULL) { STACK_SHRINK(oparg); goto error; } - STACK_SHRINK(oparg); - STACK_GROW(1); - stack_pointer[-1] = tup; + TARGET(JUMP_FORWARD) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(JUMP_FORWARD); + TIER_ONE_ONLY + JUMPBY(oparg); DISPATCH(); } - TARGET(BUILD_LIST) { - PyObject **values; + TARGET(LIST_APPEND) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(LIST_APPEND); + PyObject *v; PyObject *list; - values = stack_pointer - oparg; - list = _PyList_FromArraySteal(values, oparg); - if (list == NULL) { STACK_SHRINK(oparg); goto error; } - STACK_SHRINK(oparg); - STACK_GROW(1); - stack_pointer[-1] = list; + v = stack_pointer[-1]; + list = stack_pointer[-2 - (oparg-1)]; + if (_PyList_AppendTakeRef((PyListObject *)list, v) < 0) goto pop_1_error; + stack_pointer += -1; DISPATCH(); } TARGET(LIST_EXTEND) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(LIST_EXTEND); PyObject *iterable; PyObject *list; iterable = stack_pointer[-1]; @@ -1940,559 +3368,462 @@ PyObject *none_val = _PyList_Extend((PyListObject *)list, iterable); if (none_val == NULL) { if (_PyErr_ExceptionMatches(tstate, PyExc_TypeError) && - (Py_TYPE(iterable)->tp_iter == NULL && !PySequence_Check(iterable))) + (Py_TYPE(iterable)->tp_iter == NULL && !PySequence_Check(iterable))) { _PyErr_Clear(tstate); _PyErr_Format(tstate, PyExc_TypeError, - "Value after * must be an iterable, not %.200s", - Py_TYPE(iterable)->tp_name); + "Value after * must be an iterable, not %.200s", + Py_TYPE(iterable)->tp_name); } Py_DECREF(iterable); if (true) goto pop_1_error; } assert(Py_IsNone(none_val)); Py_DECREF(iterable); - STACK_SHRINK(1); - DISPATCH(); - } - - TARGET(SET_UPDATE) { - PyObject *iterable; - PyObject *set; - iterable = stack_pointer[-1]; - set = stack_pointer[-2 - (oparg-1)]; - int err = _PySet_Update(set, iterable); - Py_DECREF(iterable); - if (err < 0) goto pop_1_error; - STACK_SHRINK(1); - DISPATCH(); - } - - TARGET(BUILD_SET) { - PyObject **values; - PyObject *set; - values = stack_pointer - oparg; - set = PySet_New(NULL); - if (set == NULL) - goto error; - int err = 0; - for (int i = 0; i < oparg; i++) { - PyObject *item = values[i]; - if (err == 0) - err = PySet_Add(set, item); - Py_DECREF(item); - } - if (err != 0) { - Py_DECREF(set); - if (true) { STACK_SHRINK(oparg); goto error; } - } - STACK_SHRINK(oparg); - STACK_GROW(1); - stack_pointer[-1] = set; + stack_pointer += -1; DISPATCH(); } - TARGET(BUILD_MAP) { - PyObject **values; - PyObject *map; - values = stack_pointer - oparg*2; - map = _PyDict_FromItems( - values, 2, - values+1, 2, - oparg); - if (map == NULL) - goto error; - - for (int _i = oparg*2; --_i >= 0;) { - Py_DECREF(values[_i]); - } - if (map == NULL) { STACK_SHRINK(oparg*2); goto error; } - STACK_SHRINK(oparg*2); - STACK_GROW(1); - stack_pointer[-1] = map; + TARGET(LOAD_ASSERTION_ERROR) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(LOAD_ASSERTION_ERROR); + PyObject *value; + value = Py_NewRef(PyExc_AssertionError); + stack_pointer[0] = value; + stack_pointer += 1; DISPATCH(); } - TARGET(SETUP_ANNOTATIONS) { - int err; - PyObject *ann_dict; - if (LOCALS() == NULL) { - _PyErr_Format(tstate, PyExc_SystemError, - "no locals found when setting up annotations"); - if (true) goto error; - } - /* check if __annotations__ in locals()... */ - if (PyDict_CheckExact(LOCALS())) { - ann_dict = _PyDict_GetItemWithError(LOCALS(), - &_Py_ID(__annotations__)); - if (ann_dict == NULL) { - if (_PyErr_Occurred(tstate)) goto error; - /* ...if not, create a new one */ - ann_dict = PyDict_New(); - if (ann_dict == NULL) goto error; - err = PyDict_SetItem(LOCALS(), &_Py_ID(__annotations__), - ann_dict); - Py_DECREF(ann_dict); - if (err) goto error; + TARGET(LOAD_ATTR) { + frame->instr_ptr = next_instr; + next_instr += 10; + INSTRUCTION_STATS(LOAD_ATTR); + PREDICTED(LOAD_ATTR); + _Py_CODEUNIT *this_instr = next_instr - 10; + PyObject *owner; + PyObject *attr; + PyObject *self_or_null = NULL; + // _SPECIALIZE_LOAD_ATTR + owner = stack_pointer[-1]; + { + uint16_t counter = read_u16(&this_instr[1].cache); + TIER_ONE_ONLY + #if ENABLE_SPECIALIZATION + if (ADAPTIVE_COUNTER_IS_ZERO(counter)) { + PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1); + next_instr = this_instr; + _Py_Specialize_LoadAttr(owner, next_instr, name); + DISPATCH_SAME_OPARG(); } + STAT_INC(LOAD_ATTR, deferred); + DECREMENT_ADAPTIVE_COUNTER(this_instr[1].cache); + #endif /* ENABLE_SPECIALIZATION */ } - else { - /* do the same if locals() is not a dict */ - if (PyMapping_GetOptionalItem(LOCALS(), &_Py_ID(__annotations__), &ann_dict) < 0) goto error; - if (ann_dict == NULL) { - ann_dict = PyDict_New(); - if (ann_dict == NULL) goto error; - err = PyObject_SetItem(LOCALS(), &_Py_ID(__annotations__), - ann_dict); - Py_DECREF(ann_dict); - if (err) goto error; + /* Skip 8 cache entries */ + // _LOAD_ATTR + { + PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 1); + if (oparg & 1) { + /* Designed to work in tandem with CALL, pushes two values. */ + attr = NULL; + if (_PyObject_GetMethod(owner, name, &attr)) { + /* We can bypass temporary bound method object. + meth is unbound method and obj is self. + meth | self | arg1 | ... | argN + */ + assert(attr != NULL); // No errors on this branch + self_or_null = owner; // Transfer ownership + } + else { + /* meth is not an unbound method (but a regular attr, or + something was returned by a descriptor protocol). Set + the second element of the stack to NULL, to signal + CALL that it's not a method call. + NULL | meth | arg1 | ... | argN + */ + Py_DECREF(owner); + if (attr == NULL) goto pop_1_error; + self_or_null = NULL; + } } else { - Py_DECREF(ann_dict); + /* Classic, pushes one value. */ + attr = PyObject_GetAttr(owner, name); + Py_DECREF(owner); + if (attr == NULL) goto pop_1_error; } } + stack_pointer[-1] = attr; + if (oparg & 1) stack_pointer[0] = self_or_null; + stack_pointer += (oparg & 1); DISPATCH(); } - TARGET(BUILD_CONST_KEY_MAP) { - PyObject *keys; - PyObject **values; - PyObject *map; - keys = stack_pointer[-1]; - values = stack_pointer - 1 - oparg; - if (!PyTuple_CheckExact(keys) || - PyTuple_GET_SIZE(keys) != (Py_ssize_t)oparg) { - _PyErr_SetString(tstate, PyExc_SystemError, - "bad BUILD_CONST_KEY_MAP keys argument"); - goto error; // Pop the keys and values. - } - map = _PyDict_FromItems( - &PyTuple_GET_ITEM(keys, 0), 1, - values, 1, oparg); - for (int _i = oparg; --_i >= 0;) { - Py_DECREF(values[_i]); + TARGET(LOAD_ATTR_CLASS) { + _Py_CODEUNIT *this_instr = frame->instr_ptr = next_instr; + next_instr += 10; + INSTRUCTION_STATS(LOAD_ATTR_CLASS); + static_assert(INLINE_CACHE_ENTRIES_LOAD_ATTR == 9, "incorrect cache size"); + PyObject *owner; + PyObject *attr; + PyObject *null = NULL; + /* Skip 1 cache entry */ + // _CHECK_ATTR_CLASS + owner = stack_pointer[-1]; + { + uint32_t type_version = read_u32(&this_instr[2].cache); + DEOPT_IF(!PyType_Check(owner), LOAD_ATTR); + assert(type_version != 0); + DEOPT_IF(((PyTypeObject *)owner)->tp_version_tag != type_version, LOAD_ATTR); } - Py_DECREF(keys); - if (map == NULL) { STACK_SHRINK(oparg); goto pop_1_error; } - STACK_SHRINK(oparg); - stack_pointer[-1] = map; - DISPATCH(); - } - - TARGET(DICT_UPDATE) { - PyObject *update; - update = stack_pointer[-1]; - PyObject *dict = PEEK(oparg + 1); // update is still on the stack - if (PyDict_Update(dict, update) < 0) { - if (_PyErr_ExceptionMatches(tstate, PyExc_AttributeError)) { - _PyErr_Format(tstate, PyExc_TypeError, - "'%.200s' object is not a mapping", - Py_TYPE(update)->tp_name); - } - Py_DECREF(update); - if (true) goto pop_1_error; + /* Skip 2 cache entries */ + // _LOAD_ATTR_CLASS + { + PyObject *descr = read_obj(&this_instr[6].cache); + STAT_INC(LOAD_ATTR, hit); + assert(descr != NULL); + attr = Py_NewRef(descr); + null = NULL; + Py_DECREF(owner); } - Py_DECREF(update); - STACK_SHRINK(1); + stack_pointer[-1] = attr; + if (oparg & 1) stack_pointer[0] = null; + stack_pointer += (oparg & 1); DISPATCH(); } - TARGET(DICT_MERGE) { - PyObject *update; - update = stack_pointer[-1]; - PyObject *dict = PEEK(oparg + 1); // update is still on the stack - - if (_PyDict_MergeEx(dict, update, 2) < 0) { - _PyEval_FormatKwargsError(tstate, PEEK(3 + oparg), update); - Py_DECREF(update); - if (true) goto pop_1_error; - } - Py_DECREF(update); + TARGET(LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN) { + _Py_CODEUNIT *this_instr = frame->instr_ptr = next_instr; + next_instr += 10; + INSTRUCTION_STATS(LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN); + static_assert(INLINE_CACHE_ENTRIES_LOAD_ATTR == 9, "incorrect cache size"); + PyObject *owner; + /* Skip 1 cache entry */ + owner = stack_pointer[-1]; + uint32_t type_version = read_u32(&this_instr[2].cache); + uint32_t func_version = read_u32(&this_instr[4].cache); + PyObject *getattribute = read_obj(&this_instr[6].cache); + assert((oparg & 1) == 0); + DEOPT_IF(tstate->interp->eval_frame, LOAD_ATTR); + PyTypeObject *cls = Py_TYPE(owner); + assert(type_version != 0); + DEOPT_IF(cls->tp_version_tag != type_version, LOAD_ATTR); + assert(Py_IS_TYPE(getattribute, &PyFunction_Type)); + PyFunctionObject *f = (PyFunctionObject *)getattribute; + assert(func_version != 0); + DEOPT_IF(f->func_version != func_version, LOAD_ATTR); + PyCodeObject *code = (PyCodeObject *)f->func_code; + assert(code->co_argcount == 2); + DEOPT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize), LOAD_ATTR); + STAT_INC(LOAD_ATTR, hit); + PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 1); + Py_INCREF(f); + _PyInterpreterFrame *new_frame = _PyFrame_PushUnchecked(tstate, f, 2); + // Manipulate stack directly because we exit with DISPATCH_INLINED(). STACK_SHRINK(1); - DISPATCH(); - } - - TARGET(MAP_ADD) { - PyObject *value; - PyObject *key; - value = stack_pointer[-1]; - key = stack_pointer[-2]; - PyObject *dict = PEEK(oparg + 2); // key, value are still on the stack - assert(PyDict_CheckExact(dict)); - /* dict[key] = value */ - // Do not DECREF INPUTS because the function steals the references - if (_PyDict_SetItem_Take2((PyDictObject *)dict, key, value) != 0) goto pop_2_error; - STACK_SHRINK(2); - DISPATCH(); - } - - TARGET(INSTRUMENTED_LOAD_SUPER_ATTR) { - _PySuperAttrCache *cache = (_PySuperAttrCache *)next_instr; - // cancel out the decrement that will happen in LOAD_SUPER_ATTR; we - // don't want to specialize instrumented instructions - INCREMENT_ADAPTIVE_COUNTER(cache->counter); - GO_TO_INSTRUCTION(LOAD_SUPER_ATTR); - STACK_SHRINK(2); - STACK_GROW(((oparg & 1) ? 1 : 0)); + new_frame->localsplus[0] = owner; + new_frame->localsplus[1] = Py_NewRef(name); + frame->return_offset = (uint16_t)(next_instr - this_instr); + DISPATCH_INLINED(new_frame); } - TARGET(LOAD_SUPER_ATTR) { - PREDICTED(LOAD_SUPER_ATTR); - static_assert(INLINE_CACHE_ENTRIES_LOAD_SUPER_ATTR == 1, "incorrect cache size"); - PyObject *self; - PyObject *class; - PyObject *global_super; - PyObject *res2 = NULL; - PyObject *res; - self = stack_pointer[-1]; - class = stack_pointer[-2]; - global_super = stack_pointer[-3]; - PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 2); - int load_method = oparg & 1; - #if ENABLE_SPECIALIZATION - _PySuperAttrCache *cache = (_PySuperAttrCache *)next_instr; - if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) { - next_instr--; - _Py_Specialize_LoadSuperAttr(global_super, class, next_instr, load_method); - DISPATCH_SAME_OPARG(); - } - STAT_INC(LOAD_SUPER_ATTR, deferred); - DECREMENT_ADAPTIVE_COUNTER(cache->counter); - #endif /* ENABLE_SPECIALIZATION */ - - if (opcode == INSTRUMENTED_LOAD_SUPER_ATTR) { - PyObject *arg = oparg & 2 ? class : &_PyInstrumentation_MISSING; - int err = _Py_call_instrumentation_2args( - tstate, PY_MONITORING_EVENT_CALL, - frame, next_instr-1, global_super, arg); - if (err) goto pop_3_error; - } - - // we make no attempt to optimize here; specializations should - // handle any case whose performance we care about - PyObject *stack[] = {class, self}; - PyObject *super = PyObject_Vectorcall(global_super, stack, oparg & 2, NULL); - if (opcode == INSTRUMENTED_LOAD_SUPER_ATTR) { - PyObject *arg = oparg & 2 ? class : &_PyInstrumentation_MISSING; - if (super == NULL) { - _Py_call_instrumentation_exc2( - tstate, PY_MONITORING_EVENT_C_RAISE, - frame, next_instr-1, global_super, arg); - } - else { - int err = _Py_call_instrumentation_2args( - tstate, PY_MONITORING_EVENT_C_RETURN, - frame, next_instr-1, global_super, arg); - if (err < 0) { - Py_CLEAR(super); - } - } + TARGET(LOAD_ATTR_INSTANCE_VALUE) { + _Py_CODEUNIT *this_instr = frame->instr_ptr = next_instr; + next_instr += 10; + INSTRUCTION_STATS(LOAD_ATTR_INSTANCE_VALUE); + static_assert(INLINE_CACHE_ENTRIES_LOAD_ATTR == 9, "incorrect cache size"); + PyObject *owner; + PyObject *attr; + PyObject *null = NULL; + /* Skip 1 cache entry */ + // _GUARD_TYPE_VERSION + owner = stack_pointer[-1]; + { + uint32_t type_version = read_u32(&this_instr[2].cache); + PyTypeObject *tp = Py_TYPE(owner); + assert(type_version != 0); + DEOPT_IF(tp->tp_version_tag != type_version, LOAD_ATTR); } - Py_DECREF(global_super); - Py_DECREF(class); - Py_DECREF(self); - if (super == NULL) goto pop_3_error; - res = PyObject_GetAttr(super, name); - Py_DECREF(super); - if (res == NULL) goto pop_3_error; - STACK_SHRINK(2); - STACK_GROW(((oparg & 1) ? 1 : 0)); - if (oparg & 1) { stack_pointer[-1 - (oparg & 1 ? 1 : 0)] = res2; } - stack_pointer[-1] = res; - next_instr += 1; - DISPATCH(); - } - - TARGET(LOAD_SUPER_ATTR_ATTR) { - PyObject *self; - PyObject *class; - PyObject *global_super; - PyObject *res2 = NULL; - PyObject *res; - self = stack_pointer[-1]; - class = stack_pointer[-2]; - global_super = stack_pointer[-3]; - assert(!(oparg & 1)); - DEOPT_IF(global_super != (PyObject *)&PySuper_Type, LOAD_SUPER_ATTR); - DEOPT_IF(!PyType_Check(class), LOAD_SUPER_ATTR); - STAT_INC(LOAD_SUPER_ATTR, hit); - PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 2); - res = _PySuper_Lookup((PyTypeObject *)class, self, name, NULL); - Py_DECREF(global_super); - Py_DECREF(class); - Py_DECREF(self); - if (res == NULL) goto pop_3_error; - STACK_SHRINK(2); - STACK_GROW(((oparg & 1) ? 1 : 0)); - if (oparg & 1) { stack_pointer[-1 - (oparg & 1 ? 1 : 0)] = res2; } - stack_pointer[-1] = res; - next_instr += 1; - DISPATCH(); - } - - TARGET(LOAD_SUPER_ATTR_METHOD) { - PyObject *self; - PyObject *class; - PyObject *global_super; - PyObject *res2; - PyObject *res; - self = stack_pointer[-1]; - class = stack_pointer[-2]; - global_super = stack_pointer[-3]; - assert(oparg & 1); - DEOPT_IF(global_super != (PyObject *)&PySuper_Type, LOAD_SUPER_ATTR); - DEOPT_IF(!PyType_Check(class), LOAD_SUPER_ATTR); - STAT_INC(LOAD_SUPER_ATTR, hit); - PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 2); - PyTypeObject *cls = (PyTypeObject *)class; - int method_found = 0; - res2 = _PySuper_Lookup(cls, self, name, - Py_TYPE(self)->tp_getattro == PyObject_GenericGetAttr ? &method_found : NULL); - Py_DECREF(global_super); - Py_DECREF(class); - if (res2 == NULL) { - Py_DECREF(self); - if (true) goto pop_3_error; + // _CHECK_MANAGED_OBJECT_HAS_VALUES + { + assert(Py_TYPE(owner)->tp_dictoffset < 0); + assert(Py_TYPE(owner)->tp_flags & Py_TPFLAGS_MANAGED_DICT); + PyDictOrValues *dorv = _PyObject_DictOrValuesPointer(owner); + DEOPT_IF(!_PyDictOrValues_IsValues(*dorv) && !_PyObject_MakeInstanceAttributesFromDict(owner, dorv), LOAD_ATTR); } - if (method_found) { - res = self; // transfer ownership - } else { - Py_DECREF(self); - res = res2; - res2 = NULL; + // _LOAD_ATTR_INSTANCE_VALUE + { + uint16_t index = read_u16(&this_instr[4].cache); + PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner); + attr = _PyDictOrValues_GetValues(dorv)->values[index]; + DEOPT_IF(attr == NULL, LOAD_ATTR); + STAT_INC(LOAD_ATTR, hit); + Py_INCREF(attr); + null = NULL; + Py_DECREF(owner); } - STACK_SHRINK(1); - stack_pointer[-2] = res2; - stack_pointer[-1] = res; - next_instr += 1; + /* Skip 5 cache entries */ + stack_pointer[-1] = attr; + if (oparg & 1) stack_pointer[0] = null; + stack_pointer += (oparg & 1); DISPATCH(); } - TARGET(LOAD_ATTR) { - PREDICTED(LOAD_ATTR); + TARGET(LOAD_ATTR_METHOD_LAZY_DICT) { + _Py_CODEUNIT *this_instr = frame->instr_ptr = next_instr; + next_instr += 10; + INSTRUCTION_STATS(LOAD_ATTR_METHOD_LAZY_DICT); static_assert(INLINE_CACHE_ENTRIES_LOAD_ATTR == 9, "incorrect cache size"); PyObject *owner; - PyObject *res2 = NULL; - PyObject *res; + PyObject *attr; + PyObject *self = NULL; + /* Skip 1 cache entry */ + // _GUARD_TYPE_VERSION owner = stack_pointer[-1]; - #if ENABLE_SPECIALIZATION - _PyAttrCache *cache = (_PyAttrCache *)next_instr; - if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) { - PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1); - next_instr--; - _Py_Specialize_LoadAttr(owner, next_instr, name); - DISPATCH_SAME_OPARG(); + { + uint32_t type_version = read_u32(&this_instr[2].cache); + PyTypeObject *tp = Py_TYPE(owner); + assert(type_version != 0); + DEOPT_IF(tp->tp_version_tag != type_version, LOAD_ATTR); } - STAT_INC(LOAD_ATTR, deferred); - DECREMENT_ADAPTIVE_COUNTER(cache->counter); - #endif /* ENABLE_SPECIALIZATION */ - PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 1); - if (oparg & 1) { - /* Designed to work in tandem with CALL, pushes two values. */ - PyObject* meth = NULL; - if (_PyObject_GetMethod(owner, name, &meth)) { - /* We can bypass temporary bound method object. - meth is unbound method and obj is self. - - meth | self | arg1 | ... | argN - */ - assert(meth != NULL); // No errors on this branch - res2 = meth; - res = owner; // Transfer ownership - } - else { - /* meth is not an unbound method (but a regular attr, or - something was returned by a descriptor protocol). Set - the second element of the stack to NULL, to signal - CALL that it's not a method call. + // _CHECK_ATTR_METHOD_LAZY_DICT + { + Py_ssize_t dictoffset = Py_TYPE(owner)->tp_dictoffset; + assert(dictoffset > 0); + PyObject *dict = *(PyObject **)((char *)owner + dictoffset); + /* This object has a __dict__, just not yet created */ + DEOPT_IF(dict != NULL, LOAD_ATTR); + } + /* Skip 2 cache entries */ + // _LOAD_ATTR_METHOD_LAZY_DICT + { + PyObject *descr = read_obj(&this_instr[6].cache); + assert(oparg & 1); + STAT_INC(LOAD_ATTR, hit); + assert(descr != NULL); + assert(_PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_METHOD_DESCRIPTOR)); + attr = Py_NewRef(descr); + self = owner; + } + stack_pointer[-1] = attr; + if (1) stack_pointer[0] = self; + stack_pointer += ((1) ? 1 : 0); + DISPATCH(); + } - NULL | meth | arg1 | ... | argN - */ - Py_DECREF(owner); - if (meth == NULL) goto pop_1_error; - res2 = NULL; - res = meth; - } + TARGET(LOAD_ATTR_METHOD_NO_DICT) { + _Py_CODEUNIT *this_instr = frame->instr_ptr = next_instr; + next_instr += 10; + INSTRUCTION_STATS(LOAD_ATTR_METHOD_NO_DICT); + static_assert(INLINE_CACHE_ENTRIES_LOAD_ATTR == 9, "incorrect cache size"); + PyObject *owner; + PyObject *attr; + PyObject *self = NULL; + /* Skip 1 cache entry */ + // _GUARD_TYPE_VERSION + owner = stack_pointer[-1]; + { + uint32_t type_version = read_u32(&this_instr[2].cache); + PyTypeObject *tp = Py_TYPE(owner); + assert(type_version != 0); + DEOPT_IF(tp->tp_version_tag != type_version, LOAD_ATTR); } - else { - /* Classic, pushes one value. */ - res = PyObject_GetAttr(owner, name); - Py_DECREF(owner); - if (res == NULL) goto pop_1_error; + /* Skip 2 cache entries */ + // _LOAD_ATTR_METHOD_NO_DICT + { + PyObject *descr = read_obj(&this_instr[6].cache); + assert(oparg & 1); + assert(Py_TYPE(owner)->tp_dictoffset == 0); + STAT_INC(LOAD_ATTR, hit); + assert(descr != NULL); + assert(_PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_METHOD_DESCRIPTOR)); + attr = Py_NewRef(descr); + self = owner; } - STACK_GROW(((oparg & 1) ? 1 : 0)); - if (oparg & 1) { stack_pointer[-1 - (oparg & 1 ? 1 : 0)] = res2; } - stack_pointer[-1] = res; - next_instr += 9; + stack_pointer[-1] = attr; + if (1) stack_pointer[0] = self; + stack_pointer += ((1) ? 1 : 0); DISPATCH(); } - TARGET(LOAD_ATTR_INSTANCE_VALUE) { + TARGET(LOAD_ATTR_METHOD_WITH_VALUES) { + _Py_CODEUNIT *this_instr = frame->instr_ptr = next_instr; + next_instr += 10; + INSTRUCTION_STATS(LOAD_ATTR_METHOD_WITH_VALUES); + static_assert(INLINE_CACHE_ENTRIES_LOAD_ATTR == 9, "incorrect cache size"); PyObject *owner; - PyObject *res2 = NULL; - PyObject *res; + PyObject *attr; + PyObject *self = NULL; + /* Skip 1 cache entry */ // _GUARD_TYPE_VERSION owner = stack_pointer[-1]; { - uint32_t type_version = read_u32(&next_instr[1].cache); + uint32_t type_version = read_u32(&this_instr[2].cache); PyTypeObject *tp = Py_TYPE(owner); assert(type_version != 0); DEOPT_IF(tp->tp_version_tag != type_version, LOAD_ATTR); } - // _CHECK_MANAGED_OBJECT_HAS_VALUES + // _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT { - assert(Py_TYPE(owner)->tp_dictoffset < 0); assert(Py_TYPE(owner)->tp_flags & Py_TPFLAGS_MANAGED_DICT); - PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner); - DEOPT_IF(!_PyDictOrValues_IsValues(dorv), LOAD_ATTR); + PyDictOrValues *dorv = _PyObject_DictOrValuesPointer(owner); + DEOPT_IF(!_PyDictOrValues_IsValues(*dorv) && !_PyObject_MakeInstanceAttributesFromDict(owner, dorv), LOAD_ATTR); } - // _LOAD_ATTR_INSTANCE_VALUE + // _GUARD_KEYS_VERSION { - uint16_t index = read_u16(&next_instr[3].cache); - PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner); - res = _PyDictOrValues_GetValues(dorv)->values[index]; - DEOPT_IF(res == NULL, LOAD_ATTR); + uint32_t keys_version = read_u32(&this_instr[4].cache); + PyTypeObject *owner_cls = Py_TYPE(owner); + PyHeapTypeObject *owner_heap_type = (PyHeapTypeObject *)owner_cls; + DEOPT_IF(owner_heap_type->ht_cached_keys->dk_version != keys_version, LOAD_ATTR); + } + // _LOAD_ATTR_METHOD_WITH_VALUES + { + PyObject *descr = read_obj(&this_instr[6].cache); + assert(oparg & 1); + /* Cached method object */ STAT_INC(LOAD_ATTR, hit); - Py_INCREF(res); - res2 = NULL; - Py_DECREF(owner); + assert(descr != NULL); + attr = Py_NewRef(descr); + assert(_PyType_HasFeature(Py_TYPE(attr), Py_TPFLAGS_METHOD_DESCRIPTOR)); + self = owner; } - STACK_GROW(((oparg & 1) ? 1 : 0)); - if (oparg & 1) { stack_pointer[-1 - (oparg & 1 ? 1 : 0)] = res2; } - stack_pointer[-1] = res; - next_instr += 9; + stack_pointer[-1] = attr; + if (1) stack_pointer[0] = self; + stack_pointer += ((1) ? 1 : 0); DISPATCH(); } TARGET(LOAD_ATTR_MODULE) { + _Py_CODEUNIT *this_instr = frame->instr_ptr = next_instr; + next_instr += 10; + INSTRUCTION_STATS(LOAD_ATTR_MODULE); + static_assert(INLINE_CACHE_ENTRIES_LOAD_ATTR == 9, "incorrect cache size"); PyObject *owner; - PyObject *res2 = NULL; - PyObject *res; + PyObject *attr; + PyObject *null = NULL; + /* Skip 1 cache entry */ + // _CHECK_ATTR_MODULE owner = stack_pointer[-1]; - uint32_t type_version = read_u32(&next_instr[1].cache); - uint16_t index = read_u16(&next_instr[3].cache); - DEOPT_IF(!PyModule_CheckExact(owner), LOAD_ATTR); - PyDictObject *dict = (PyDictObject *)((PyModuleObject *)owner)->md_dict; - assert(dict != NULL); - DEOPT_IF(dict->ma_keys->dk_version != type_version, LOAD_ATTR); - assert(dict->ma_keys->dk_kind == DICT_KEYS_UNICODE); - assert(index < dict->ma_keys->dk_nentries); - PyDictUnicodeEntry *ep = DK_UNICODE_ENTRIES(dict->ma_keys) + index; - res = ep->me_value; - DEOPT_IF(res == NULL, LOAD_ATTR); - STAT_INC(LOAD_ATTR, hit); - Py_INCREF(res); - res2 = NULL; - Py_DECREF(owner); - STACK_GROW(((oparg & 1) ? 1 : 0)); - if (oparg & 1) { stack_pointer[-1 - (oparg & 1 ? 1 : 0)] = res2; } - stack_pointer[-1] = res; - next_instr += 9; + { + uint32_t type_version = read_u32(&this_instr[2].cache); + DEOPT_IF(!PyModule_CheckExact(owner), LOAD_ATTR); + PyDictObject *dict = (PyDictObject *)((PyModuleObject *)owner)->md_dict; + assert(dict != NULL); + DEOPT_IF(dict->ma_keys->dk_version != type_version, LOAD_ATTR); + } + // _LOAD_ATTR_MODULE + { + uint16_t index = read_u16(&this_instr[4].cache); + PyDictObject *dict = (PyDictObject *)((PyModuleObject *)owner)->md_dict; + assert(dict->ma_keys->dk_kind == DICT_KEYS_UNICODE); + assert(index < dict->ma_keys->dk_nentries); + PyDictUnicodeEntry *ep = DK_UNICODE_ENTRIES(dict->ma_keys) + index; + attr = ep->me_value; + DEOPT_IF(attr == NULL, LOAD_ATTR); + STAT_INC(LOAD_ATTR, hit); + Py_INCREF(attr); + null = NULL; + Py_DECREF(owner); + } + /* Skip 5 cache entries */ + stack_pointer[-1] = attr; + if (oparg & 1) stack_pointer[0] = null; + stack_pointer += (oparg & 1); DISPATCH(); } - TARGET(LOAD_ATTR_WITH_HINT) { + TARGET(LOAD_ATTR_NONDESCRIPTOR_NO_DICT) { + _Py_CODEUNIT *this_instr = frame->instr_ptr = next_instr; + next_instr += 10; + INSTRUCTION_STATS(LOAD_ATTR_NONDESCRIPTOR_NO_DICT); + static_assert(INLINE_CACHE_ENTRIES_LOAD_ATTR == 9, "incorrect cache size"); PyObject *owner; - PyObject *res2 = NULL; - PyObject *res; + PyObject *attr; + /* Skip 1 cache entry */ + // _GUARD_TYPE_VERSION owner = stack_pointer[-1]; - uint32_t type_version = read_u32(&next_instr[1].cache); - uint16_t index = read_u16(&next_instr[3].cache); - PyTypeObject *tp = Py_TYPE(owner); - assert(type_version != 0); - DEOPT_IF(tp->tp_version_tag != type_version, LOAD_ATTR); - assert(tp->tp_flags & Py_TPFLAGS_MANAGED_DICT); - PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner); - DEOPT_IF(_PyDictOrValues_IsValues(dorv), LOAD_ATTR); - PyDictObject *dict = (PyDictObject *)_PyDictOrValues_GetDict(dorv); - DEOPT_IF(dict == NULL, LOAD_ATTR); - assert(PyDict_CheckExact((PyObject *)dict)); - PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1); - uint16_t hint = index; - DEOPT_IF(hint >= (size_t)dict->ma_keys->dk_nentries, LOAD_ATTR); - if (DK_IS_UNICODE(dict->ma_keys)) { - PyDictUnicodeEntry *ep = DK_UNICODE_ENTRIES(dict->ma_keys) + hint; - DEOPT_IF(ep->me_key != name, LOAD_ATTR); - res = ep->me_value; + { + uint32_t type_version = read_u32(&this_instr[2].cache); + PyTypeObject *tp = Py_TYPE(owner); + assert(type_version != 0); + DEOPT_IF(tp->tp_version_tag != type_version, LOAD_ATTR); } - else { - PyDictKeyEntry *ep = DK_ENTRIES(dict->ma_keys) + hint; - DEOPT_IF(ep->me_key != name, LOAD_ATTR); - res = ep->me_value; + /* Skip 2 cache entries */ + // _LOAD_ATTR_NONDESCRIPTOR_NO_DICT + { + PyObject *descr = read_obj(&this_instr[6].cache); + assert((oparg & 1) == 0); + assert(Py_TYPE(owner)->tp_dictoffset == 0); + STAT_INC(LOAD_ATTR, hit); + assert(descr != NULL); + Py_DECREF(owner); + attr = Py_NewRef(descr); } - DEOPT_IF(res == NULL, LOAD_ATTR); - STAT_INC(LOAD_ATTR, hit); - Py_INCREF(res); - res2 = NULL; - Py_DECREF(owner); - STACK_GROW(((oparg & 1) ? 1 : 0)); - if (oparg & 1) { stack_pointer[-1 - (oparg & 1 ? 1 : 0)] = res2; } - stack_pointer[-1] = res; - next_instr += 9; + stack_pointer[-1] = attr; + stack_pointer += ((0) ? 1 : 0); DISPATCH(); } - TARGET(LOAD_ATTR_SLOT) { + TARGET(LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES) { + _Py_CODEUNIT *this_instr = frame->instr_ptr = next_instr; + next_instr += 10; + INSTRUCTION_STATS(LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES); + static_assert(INLINE_CACHE_ENTRIES_LOAD_ATTR == 9, "incorrect cache size"); PyObject *owner; - PyObject *res2 = NULL; - PyObject *res; + PyObject *attr; + /* Skip 1 cache entry */ + // _GUARD_TYPE_VERSION owner = stack_pointer[-1]; - uint32_t type_version = read_u32(&next_instr[1].cache); - uint16_t index = read_u16(&next_instr[3].cache); - PyTypeObject *tp = Py_TYPE(owner); - assert(type_version != 0); - DEOPT_IF(tp->tp_version_tag != type_version, LOAD_ATTR); - char *addr = (char *)owner + index; - res = *(PyObject **)addr; - DEOPT_IF(res == NULL, LOAD_ATTR); - STAT_INC(LOAD_ATTR, hit); - Py_INCREF(res); - res2 = NULL; - Py_DECREF(owner); - STACK_GROW(((oparg & 1) ? 1 : 0)); - if (oparg & 1) { stack_pointer[-1 - (oparg & 1 ? 1 : 0)] = res2; } - stack_pointer[-1] = res; - next_instr += 9; - DISPATCH(); - } - - TARGET(LOAD_ATTR_CLASS) { - PyObject *cls; - PyObject *res2 = NULL; - PyObject *res; - cls = stack_pointer[-1]; - uint32_t type_version = read_u32(&next_instr[1].cache); - PyObject *descr = read_obj(&next_instr[5].cache); - - DEOPT_IF(!PyType_Check(cls), LOAD_ATTR); - DEOPT_IF(((PyTypeObject *)cls)->tp_version_tag != type_version, - LOAD_ATTR); - assert(type_version != 0); - - STAT_INC(LOAD_ATTR, hit); - res2 = NULL; - res = descr; - assert(res != NULL); - Py_INCREF(res); - Py_DECREF(cls); - STACK_GROW(((oparg & 1) ? 1 : 0)); - if (oparg & 1) { stack_pointer[-1 - (oparg & 1 ? 1 : 0)] = res2; } - stack_pointer[-1] = res; - next_instr += 9; + { + uint32_t type_version = read_u32(&this_instr[2].cache); + PyTypeObject *tp = Py_TYPE(owner); + assert(type_version != 0); + DEOPT_IF(tp->tp_version_tag != type_version, LOAD_ATTR); + } + // _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT + { + assert(Py_TYPE(owner)->tp_flags & Py_TPFLAGS_MANAGED_DICT); + PyDictOrValues *dorv = _PyObject_DictOrValuesPointer(owner); + DEOPT_IF(!_PyDictOrValues_IsValues(*dorv) && !_PyObject_MakeInstanceAttributesFromDict(owner, dorv), LOAD_ATTR); + } + // _GUARD_KEYS_VERSION + { + uint32_t keys_version = read_u32(&this_instr[4].cache); + PyTypeObject *owner_cls = Py_TYPE(owner); + PyHeapTypeObject *owner_heap_type = (PyHeapTypeObject *)owner_cls; + DEOPT_IF(owner_heap_type->ht_cached_keys->dk_version != keys_version, LOAD_ATTR); + } + // _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES + { + PyObject *descr = read_obj(&this_instr[6].cache); + assert((oparg & 1) == 0); + STAT_INC(LOAD_ATTR, hit); + assert(descr != NULL); + Py_DECREF(owner); + attr = Py_NewRef(descr); + } + stack_pointer[-1] = attr; + stack_pointer += ((0) ? 1 : 0); DISPATCH(); } TARGET(LOAD_ATTR_PROPERTY) { + _Py_CODEUNIT *this_instr = frame->instr_ptr = next_instr; + next_instr += 10; + INSTRUCTION_STATS(LOAD_ATTR_PROPERTY); + static_assert(INLINE_CACHE_ENTRIES_LOAD_ATTR == 9, "incorrect cache size"); PyObject *owner; + /* Skip 1 cache entry */ owner = stack_pointer[-1]; - uint32_t type_version = read_u32(&next_instr[1].cache); - uint32_t func_version = read_u32(&next_instr[3].cache); - PyObject *fget = read_obj(&next_instr[5].cache); + uint32_t type_version = read_u32(&this_instr[2].cache); + uint32_t func_version = read_u32(&this_instr[4].cache); + PyObject *fget = read_obj(&this_instr[6].cache); + assert((oparg & 1) == 0); DEOPT_IF(tstate->interp->eval_frame, LOAD_ATTR); - PyTypeObject *cls = Py_TYPE(owner); - DEOPT_IF(cls->tp_version_tag != type_version, LOAD_ATTR); assert(type_version != 0); + DEOPT_IF(cls->tp_version_tag != type_version, LOAD_ATTR); assert(Py_IS_TYPE(fget, &PyFunction_Type)); PyFunctionObject *f = (PyFunctionObject *)fget; assert(func_version != 0); @@ -2504,513 +3835,663 @@ Py_INCREF(fget); _PyInterpreterFrame *new_frame = _PyFrame_PushUnchecked(tstate, f, 1); // Manipulate stack directly because we exit with DISPATCH_INLINED(). - SET_TOP(NULL); - int shrink_stack = !(oparg & 1); - STACK_SHRINK(shrink_stack); - new_frame->localsplus[0] = owner; - SKIP_OVER(INLINE_CACHE_ENTRIES_LOAD_ATTR); - frame->return_offset = 0; - DISPATCH_INLINED(new_frame); - STACK_GROW(((oparg & 1) ? 1 : 0)); - } - - TARGET(LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN) { - PyObject *owner; - owner = stack_pointer[-1]; - uint32_t type_version = read_u32(&next_instr[1].cache); - uint32_t func_version = read_u32(&next_instr[3].cache); - PyObject *getattribute = read_obj(&next_instr[5].cache); - DEOPT_IF(tstate->interp->eval_frame, LOAD_ATTR); - PyTypeObject *cls = Py_TYPE(owner); - DEOPT_IF(cls->tp_version_tag != type_version, LOAD_ATTR); - assert(type_version != 0); - assert(Py_IS_TYPE(getattribute, &PyFunction_Type)); - PyFunctionObject *f = (PyFunctionObject *)getattribute; - assert(func_version != 0); - DEOPT_IF(f->func_version != func_version, LOAD_ATTR); - PyCodeObject *code = (PyCodeObject *)f->func_code; - assert(code->co_argcount == 2); - DEOPT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize), LOAD_ATTR); - STAT_INC(LOAD_ATTR, hit); - - PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 1); - Py_INCREF(f); - _PyInterpreterFrame *new_frame = _PyFrame_PushUnchecked(tstate, f, 2); - // Manipulate stack directly because we exit with DISPATCH_INLINED(). - SET_TOP(NULL); - int shrink_stack = !(oparg & 1); - STACK_SHRINK(shrink_stack); + STACK_SHRINK(1); new_frame->localsplus[0] = owner; - new_frame->localsplus[1] = Py_NewRef(name); - SKIP_OVER(INLINE_CACHE_ENTRIES_LOAD_ATTR); - frame->return_offset = 0; + frame->return_offset = (uint16_t)(next_instr - this_instr); DISPATCH_INLINED(new_frame); - STACK_GROW(((oparg & 1) ? 1 : 0)); } - TARGET(STORE_ATTR_INSTANCE_VALUE) { + TARGET(LOAD_ATTR_SLOT) { + _Py_CODEUNIT *this_instr = frame->instr_ptr = next_instr; + next_instr += 10; + INSTRUCTION_STATS(LOAD_ATTR_SLOT); + static_assert(INLINE_CACHE_ENTRIES_LOAD_ATTR == 9, "incorrect cache size"); PyObject *owner; - PyObject *value; + PyObject *attr; + PyObject *null = NULL; + /* Skip 1 cache entry */ + // _GUARD_TYPE_VERSION owner = stack_pointer[-1]; - value = stack_pointer[-2]; - uint32_t type_version = read_u32(&next_instr[1].cache); - uint16_t index = read_u16(&next_instr[3].cache); - PyTypeObject *tp = Py_TYPE(owner); - assert(type_version != 0); - DEOPT_IF(tp->tp_version_tag != type_version, STORE_ATTR); - assert(tp->tp_flags & Py_TPFLAGS_MANAGED_DICT); - PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner); - DEOPT_IF(!_PyDictOrValues_IsValues(dorv), STORE_ATTR); - STAT_INC(STORE_ATTR, hit); - PyDictValues *values = _PyDictOrValues_GetValues(dorv); - PyObject *old_value = values->values[index]; - values->values[index] = value; - if (old_value == NULL) { - _PyDictValues_AddToInsertionOrder(values, index); + { + uint32_t type_version = read_u32(&this_instr[2].cache); + PyTypeObject *tp = Py_TYPE(owner); + assert(type_version != 0); + DEOPT_IF(tp->tp_version_tag != type_version, LOAD_ATTR); } - else { - Py_DECREF(old_value); + // _LOAD_ATTR_SLOT + { + uint16_t index = read_u16(&this_instr[4].cache); + char *addr = (char *)owner + index; + attr = *(PyObject **)addr; + DEOPT_IF(attr == NULL, LOAD_ATTR); + STAT_INC(LOAD_ATTR, hit); + Py_INCREF(attr); + null = NULL; + Py_DECREF(owner); } - Py_DECREF(owner); - STACK_SHRINK(2); - next_instr += 4; + /* Skip 5 cache entries */ + stack_pointer[-1] = attr; + if (oparg & 1) stack_pointer[0] = null; + stack_pointer += (oparg & 1); DISPATCH(); } - TARGET(STORE_ATTR_WITH_HINT) { + TARGET(LOAD_ATTR_WITH_HINT) { + _Py_CODEUNIT *this_instr = frame->instr_ptr = next_instr; + next_instr += 10; + INSTRUCTION_STATS(LOAD_ATTR_WITH_HINT); + static_assert(INLINE_CACHE_ENTRIES_LOAD_ATTR == 9, "incorrect cache size"); PyObject *owner; - PyObject *value; + PyObject *attr; + PyObject *null = NULL; + /* Skip 1 cache entry */ + // _GUARD_TYPE_VERSION owner = stack_pointer[-1]; - value = stack_pointer[-2]; - uint32_t type_version = read_u32(&next_instr[1].cache); - uint16_t hint = read_u16(&next_instr[3].cache); - PyTypeObject *tp = Py_TYPE(owner); - assert(type_version != 0); - DEOPT_IF(tp->tp_version_tag != type_version, STORE_ATTR); - assert(tp->tp_flags & Py_TPFLAGS_MANAGED_DICT); - PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner); - DEOPT_IF(_PyDictOrValues_IsValues(dorv), STORE_ATTR); - PyDictObject *dict = (PyDictObject *)_PyDictOrValues_GetDict(dorv); - DEOPT_IF(dict == NULL, STORE_ATTR); - assert(PyDict_CheckExact((PyObject *)dict)); - PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); - DEOPT_IF(hint >= (size_t)dict->ma_keys->dk_nentries, STORE_ATTR); - PyObject *old_value; - uint64_t new_version; - if (DK_IS_UNICODE(dict->ma_keys)) { - PyDictUnicodeEntry *ep = DK_UNICODE_ENTRIES(dict->ma_keys) + hint; - DEOPT_IF(ep->me_key != name, STORE_ATTR); - old_value = ep->me_value; - DEOPT_IF(old_value == NULL, STORE_ATTR); - new_version = _PyDict_NotifyEvent(tstate->interp, PyDict_EVENT_MODIFIED, dict, name, value); - ep->me_value = value; + { + uint32_t type_version = read_u32(&this_instr[2].cache); + PyTypeObject *tp = Py_TYPE(owner); + assert(type_version != 0); + DEOPT_IF(tp->tp_version_tag != type_version, LOAD_ATTR); } - else { - PyDictKeyEntry *ep = DK_ENTRIES(dict->ma_keys) + hint; - DEOPT_IF(ep->me_key != name, STORE_ATTR); - old_value = ep->me_value; - DEOPT_IF(old_value == NULL, STORE_ATTR); - new_version = _PyDict_NotifyEvent(tstate->interp, PyDict_EVENT_MODIFIED, dict, name, value); - ep->me_value = value; + // _CHECK_ATTR_WITH_HINT + { + assert(Py_TYPE(owner)->tp_flags & Py_TPFLAGS_MANAGED_DICT); + PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner); + DEOPT_IF(_PyDictOrValues_IsValues(dorv), LOAD_ATTR); + PyDictObject *dict = (PyDictObject *)_PyDictOrValues_GetDict(dorv); + DEOPT_IF(dict == NULL, LOAD_ATTR); + assert(PyDict_CheckExact((PyObject *)dict)); + } + // _LOAD_ATTR_WITH_HINT + { + uint16_t hint = read_u16(&this_instr[4].cache); + PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner); + PyDictObject *dict = (PyDictObject *)_PyDictOrValues_GetDict(dorv); + DEOPT_IF(hint >= (size_t)dict->ma_keys->dk_nentries, LOAD_ATTR); + PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1); + if (DK_IS_UNICODE(dict->ma_keys)) { + PyDictUnicodeEntry *ep = DK_UNICODE_ENTRIES(dict->ma_keys) + hint; + DEOPT_IF(ep->me_key != name, LOAD_ATTR); + attr = ep->me_value; + } + else { + PyDictKeyEntry *ep = DK_ENTRIES(dict->ma_keys) + hint; + DEOPT_IF(ep->me_key != name, LOAD_ATTR); + attr = ep->me_value; + } + DEOPT_IF(attr == NULL, LOAD_ATTR); + STAT_INC(LOAD_ATTR, hit); + Py_INCREF(attr); + null = NULL; + Py_DECREF(owner); } - Py_DECREF(old_value); - STAT_INC(STORE_ATTR, hit); - /* Ensure dict is GC tracked if it needs to be */ - if (!_PyObject_GC_IS_TRACKED(dict) && _PyObject_GC_MAY_BE_TRACKED(value)) { - _PyObject_GC_TRACK(dict); + /* Skip 5 cache entries */ + stack_pointer[-1] = attr; + if (oparg & 1) stack_pointer[0] = null; + stack_pointer += (oparg & 1); + DISPATCH(); + } + + TARGET(LOAD_BUILD_CLASS) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(LOAD_BUILD_CLASS); + PyObject *bc; + if (PyMapping_GetOptionalItem(BUILTINS(), &_Py_ID(__build_class__), &bc) < 0) goto error; + if (bc == NULL) { + _PyErr_SetString(tstate, PyExc_NameError, + "__build_class__ not found"); + if (true) goto error; } - /* PEP 509 */ - dict->ma_version_tag = new_version; - Py_DECREF(owner); - STACK_SHRINK(2); - next_instr += 4; + stack_pointer[0] = bc; + stack_pointer += 1; DISPATCH(); } - TARGET(STORE_ATTR_SLOT) { - PyObject *owner; + TARGET(LOAD_CONST) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(LOAD_CONST); PyObject *value; - owner = stack_pointer[-1]; - value = stack_pointer[-2]; - uint32_t type_version = read_u32(&next_instr[1].cache); - uint16_t index = read_u16(&next_instr[3].cache); - PyTypeObject *tp = Py_TYPE(owner); - assert(type_version != 0); - DEOPT_IF(tp->tp_version_tag != type_version, STORE_ATTR); - char *addr = (char *)owner + index; - STAT_INC(STORE_ATTR, hit); - PyObject *old_value = *(PyObject **)addr; - *(PyObject **)addr = value; - Py_XDECREF(old_value); - Py_DECREF(owner); - STACK_SHRINK(2); - next_instr += 4; + value = GETITEM(FRAME_CO_CONSTS, oparg); + Py_INCREF(value); + stack_pointer[0] = value; + stack_pointer += 1; DISPATCH(); } - TARGET(COMPARE_OP) { - PREDICTED(COMPARE_OP); - static_assert(INLINE_CACHE_ENTRIES_COMPARE_OP == 1, "incorrect cache size"); - PyObject *right; - PyObject *left; - PyObject *res; - right = stack_pointer[-1]; - left = stack_pointer[-2]; - #if ENABLE_SPECIALIZATION - _PyCompareOpCache *cache = (_PyCompareOpCache *)next_instr; - if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) { - next_instr--; - _Py_Specialize_CompareOp(left, right, next_instr, oparg); - DISPATCH_SAME_OPARG(); - } - STAT_INC(COMPARE_OP, deferred); - DECREMENT_ADAPTIVE_COUNTER(cache->counter); - #endif /* ENABLE_SPECIALIZATION */ - assert((oparg >> 5) <= Py_GE); - res = PyObject_RichCompare(left, right, oparg >> 5); - Py_DECREF(left); - Py_DECREF(right); - if (res == NULL) goto pop_2_error; - if (oparg & 16) { - int res_bool = PyObject_IsTrue(res); - Py_DECREF(res); - if (res_bool < 0) goto pop_2_error; - res = res_bool ? Py_True : Py_False; - } - STACK_SHRINK(1); - stack_pointer[-1] = res; + TARGET(LOAD_DEREF) { + frame->instr_ptr = next_instr; next_instr += 1; + INSTRUCTION_STATS(LOAD_DEREF); + PyObject *value; + PyObject *cell = GETLOCAL(oparg); + value = PyCell_GET(cell); + if (value == NULL) { + _PyEval_FormatExcUnbound(tstate, _PyFrame_GetCode(frame), oparg); + if (true) goto error; + } + Py_INCREF(value); + stack_pointer[0] = value; + stack_pointer += 1; DISPATCH(); } - TARGET(COMPARE_OP_FLOAT) { - PyObject *right; - PyObject *left; - PyObject *res; - right = stack_pointer[-1]; - left = stack_pointer[-2]; - DEOPT_IF(!PyFloat_CheckExact(left), COMPARE_OP); - DEOPT_IF(!PyFloat_CheckExact(right), COMPARE_OP); - STAT_INC(COMPARE_OP, hit); - double dleft = PyFloat_AS_DOUBLE(left); - double dright = PyFloat_AS_DOUBLE(right); - // 1 if NaN, 2 if <, 4 if >, 8 if ==; this matches low four bits of the oparg - int sign_ish = COMPARISON_BIT(dleft, dright); - _Py_DECREF_SPECIALIZED(left, _PyFloat_ExactDealloc); - _Py_DECREF_SPECIALIZED(right, _PyFloat_ExactDealloc); - res = (sign_ish & oparg) ? Py_True : Py_False; - // It's always a bool, so we don't care about oparg & 16. - STACK_SHRINK(1); - stack_pointer[-1] = res; + TARGET(LOAD_FAST) { + frame->instr_ptr = next_instr; next_instr += 1; + INSTRUCTION_STATS(LOAD_FAST); + PyObject *value; + value = GETLOCAL(oparg); + assert(value != NULL); + Py_INCREF(value); + stack_pointer[0] = value; + stack_pointer += 1; DISPATCH(); } - TARGET(COMPARE_OP_INT) { - PyObject *right; - PyObject *left; - PyObject *res; - right = stack_pointer[-1]; - left = stack_pointer[-2]; - DEOPT_IF(!PyLong_CheckExact(left), COMPARE_OP); - DEOPT_IF(!PyLong_CheckExact(right), COMPARE_OP); - DEOPT_IF(!_PyLong_IsCompact((PyLongObject *)left), COMPARE_OP); - DEOPT_IF(!_PyLong_IsCompact((PyLongObject *)right), COMPARE_OP); - STAT_INC(COMPARE_OP, hit); - assert(_PyLong_DigitCount((PyLongObject *)left) <= 1 && - _PyLong_DigitCount((PyLongObject *)right) <= 1); - Py_ssize_t ileft = _PyLong_CompactValue((PyLongObject *)left); - Py_ssize_t iright = _PyLong_CompactValue((PyLongObject *)right); - // 2 if <, 4 if >, 8 if ==; this matches the low 4 bits of the oparg - int sign_ish = COMPARISON_BIT(ileft, iright); - _Py_DECREF_SPECIALIZED(left, (destructor)PyObject_Free); - _Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free); - res = (sign_ish & oparg) ? Py_True : Py_False; - // It's always a bool, so we don't care about oparg & 16. - STACK_SHRINK(1); - stack_pointer[-1] = res; + TARGET(LOAD_FAST_AND_CLEAR) { + frame->instr_ptr = next_instr; next_instr += 1; + INSTRUCTION_STATS(LOAD_FAST_AND_CLEAR); + PyObject *value; + value = GETLOCAL(oparg); + // do not use SETLOCAL here, it decrefs the old value + GETLOCAL(oparg) = NULL; + stack_pointer[0] = value; + stack_pointer += 1; DISPATCH(); } - TARGET(COMPARE_OP_STR) { - PyObject *right; - PyObject *left; - PyObject *res; - right = stack_pointer[-1]; - left = stack_pointer[-2]; - DEOPT_IF(!PyUnicode_CheckExact(left), COMPARE_OP); - DEOPT_IF(!PyUnicode_CheckExact(right), COMPARE_OP); - STAT_INC(COMPARE_OP, hit); - int eq = _PyUnicode_Equal(left, right); - assert((oparg >> 5) == Py_EQ || (oparg >> 5) == Py_NE); - _Py_DECREF_SPECIALIZED(left, _PyUnicode_ExactDealloc); - _Py_DECREF_SPECIALIZED(right, _PyUnicode_ExactDealloc); - assert(eq == 0 || eq == 1); - assert((oparg & 0xf) == COMPARISON_NOT_EQUALS || (oparg & 0xf) == COMPARISON_EQUALS); - assert(COMPARISON_NOT_EQUALS + 1 == COMPARISON_EQUALS); - res = ((COMPARISON_NOT_EQUALS + eq) & oparg) ? Py_True : Py_False; - // It's always a bool, so we don't care about oparg & 16. - STACK_SHRINK(1); - stack_pointer[-1] = res; + TARGET(LOAD_FAST_CHECK) { + frame->instr_ptr = next_instr; next_instr += 1; + INSTRUCTION_STATS(LOAD_FAST_CHECK); + PyObject *value; + value = GETLOCAL(oparg); + if (value == NULL) goto unbound_local_error; + Py_INCREF(value); + stack_pointer[0] = value; + stack_pointer += 1; DISPATCH(); } - TARGET(IS_OP) { - PyObject *right; - PyObject *left; - PyObject *b; - right = stack_pointer[-1]; - left = stack_pointer[-2]; - int res = Py_Is(left, right) ^ oparg; - Py_DECREF(left); - Py_DECREF(right); - b = res ? Py_True : Py_False; - STACK_SHRINK(1); - stack_pointer[-1] = b; + TARGET(LOAD_FAST_LOAD_FAST) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(LOAD_FAST_LOAD_FAST); + PyObject *value1; + PyObject *value2; + uint32_t oparg1 = oparg >> 4; + uint32_t oparg2 = oparg & 15; + value1 = GETLOCAL(oparg1); + value2 = GETLOCAL(oparg2); + Py_INCREF(value1); + Py_INCREF(value2); + stack_pointer[0] = value1; + stack_pointer[1] = value2; + stack_pointer += 2; DISPATCH(); } - TARGET(CONTAINS_OP) { - PyObject *right; - PyObject *left; - PyObject *b; - right = stack_pointer[-1]; - left = stack_pointer[-2]; - int res = PySequence_Contains(right, left); - Py_DECREF(left); - Py_DECREF(right); - if (res < 0) goto pop_2_error; - b = (res ^ oparg) ? Py_True : Py_False; - STACK_SHRINK(1); - stack_pointer[-1] = b; + TARGET(LOAD_FROM_DICT_OR_DEREF) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(LOAD_FROM_DICT_OR_DEREF); + PyObject *class_dict; + PyObject *value; + class_dict = stack_pointer[-1]; + PyObject *name; + assert(class_dict); + assert(oparg >= 0 && oparg < _PyFrame_GetCode(frame)->co_nlocalsplus); + name = PyTuple_GET_ITEM(_PyFrame_GetCode(frame)->co_localsplusnames, oparg); + if (PyMapping_GetOptionalItem(class_dict, name, &value) < 0) { + GOTO_ERROR(error); + } + if (!value) { + PyObject *cell = GETLOCAL(oparg); + value = PyCell_GET(cell); + if (value == NULL) { + _PyEval_FormatExcUnbound(tstate, _PyFrame_GetCode(frame), oparg); + GOTO_ERROR(error); + } + Py_INCREF(value); + } + Py_DECREF(class_dict); + stack_pointer[-1] = value; DISPATCH(); } - TARGET(CHECK_EG_MATCH) { - PyObject *match_type; - PyObject *exc_value; - PyObject *rest; - PyObject *match; - match_type = stack_pointer[-1]; - exc_value = stack_pointer[-2]; - if (_PyEval_CheckExceptStarTypeValid(tstate, match_type) < 0) { - Py_DECREF(exc_value); - Py_DECREF(match_type); - if (true) goto pop_2_error; + TARGET(LOAD_FROM_DICT_OR_GLOBALS) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(LOAD_FROM_DICT_OR_GLOBALS); + PyObject *mod_or_class_dict; + PyObject *v; + mod_or_class_dict = stack_pointer[-1]; + PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); + if (PyMapping_GetOptionalItem(mod_or_class_dict, name, &v) < 0) { + GOTO_ERROR(error); } + if (v == NULL) { + if (PyDict_GetItemRef(GLOBALS(), name, &v) < 0) { + GOTO_ERROR(error); + } + if (v == NULL) { + if (PyMapping_GetOptionalItem(BUILTINS(), name, &v) < 0) { + GOTO_ERROR(error); + } + if (v == NULL) { + _PyEval_FormatExcCheckArg( + tstate, PyExc_NameError, + NAME_ERROR_MSG, name); + GOTO_ERROR(error); + } + } + } + Py_DECREF(mod_or_class_dict); + stack_pointer[-1] = v; + DISPATCH(); + } - match = NULL; - rest = NULL; - int res = _PyEval_ExceptionGroupMatch(exc_value, match_type, - &match, &rest); - Py_DECREF(exc_value); - Py_DECREF(match_type); - if (res < 0) goto pop_2_error; - - assert((match == NULL) == (rest == NULL)); - if (match == NULL) goto pop_2_error; - - if (!Py_IsNone(match)) { - PyErr_SetHandledException(match); + TARGET(LOAD_GLOBAL) { + frame->instr_ptr = next_instr; + next_instr += 5; + INSTRUCTION_STATS(LOAD_GLOBAL); + PREDICTED(LOAD_GLOBAL); + _Py_CODEUNIT *this_instr = next_instr - 5; + PyObject *res; + PyObject *null = NULL; + // _SPECIALIZE_LOAD_GLOBAL + { + uint16_t counter = read_u16(&this_instr[1].cache); + TIER_ONE_ONLY + #if ENABLE_SPECIALIZATION + if (ADAPTIVE_COUNTER_IS_ZERO(counter)) { + PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1); + next_instr = this_instr; + _Py_Specialize_LoadGlobal(GLOBALS(), BUILTINS(), next_instr, name); + DISPATCH_SAME_OPARG(); + } + STAT_INC(LOAD_GLOBAL, deferred); + DECREMENT_ADAPTIVE_COUNTER(this_instr[1].cache); + #endif /* ENABLE_SPECIALIZATION */ + } + /* Skip 1 cache entry */ + /* Skip 1 cache entry */ + /* Skip 1 cache entry */ + // _LOAD_GLOBAL + { + PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1); + if (PyDict_CheckExact(GLOBALS()) + && PyDict_CheckExact(BUILTINS())) + { + res = _PyDict_LoadGlobal((PyDictObject *)GLOBALS(), + (PyDictObject *)BUILTINS(), + name); + if (res == NULL) { + if (!_PyErr_Occurred(tstate)) { + /* _PyDict_LoadGlobal() returns NULL without raising + * an exception if the key doesn't exist */ + _PyEval_FormatExcCheckArg(tstate, PyExc_NameError, + NAME_ERROR_MSG, name); + } + if (true) goto error; + } + Py_INCREF(res); + } + else { + /* Slow-path if globals or builtins is not a dict */ + /* namespace 1: globals */ + if (PyMapping_GetOptionalItem(GLOBALS(), name, &res) < 0) goto error; + if (res == NULL) { + /* namespace 2: builtins */ + if (PyMapping_GetOptionalItem(BUILTINS(), name, &res) < 0) goto error; + if (res == NULL) { + _PyEval_FormatExcCheckArg( + tstate, PyExc_NameError, + NAME_ERROR_MSG, name); + if (true) goto error; + } + } + } + null = NULL; } - stack_pointer[-2] = rest; - stack_pointer[-1] = match; + stack_pointer[0] = res; + if (oparg & 1) stack_pointer[1] = null; + stack_pointer += 1 + (oparg & 1); DISPATCH(); } - TARGET(CHECK_EXC_MATCH) { - PyObject *right; - PyObject *left; - PyObject *b; - right = stack_pointer[-1]; - left = stack_pointer[-2]; - assert(PyExceptionInstance_Check(left)); - if (_PyEval_CheckExceptTypeValid(tstate, right) < 0) { - Py_DECREF(right); - if (true) goto pop_1_error; + TARGET(LOAD_GLOBAL_BUILTIN) { + _Py_CODEUNIT *this_instr = frame->instr_ptr = next_instr; + next_instr += 5; + INSTRUCTION_STATS(LOAD_GLOBAL_BUILTIN); + static_assert(INLINE_CACHE_ENTRIES_LOAD_GLOBAL == 4, "incorrect cache size"); + PyObject *res; + PyObject *null = NULL; + /* Skip 1 cache entry */ + // _GUARD_GLOBALS_VERSION + { + uint16_t version = read_u16(&this_instr[2].cache); + PyDictObject *dict = (PyDictObject *)GLOBALS(); + DEOPT_IF(!PyDict_CheckExact(dict), LOAD_GLOBAL); + DEOPT_IF(dict->ma_keys->dk_version != version, LOAD_GLOBAL); + assert(DK_IS_UNICODE(dict->ma_keys)); } - - int res = PyErr_GivenExceptionMatches(left, right); - Py_DECREF(right); - b = res ? Py_True : Py_False; - stack_pointer[-1] = b; + // _GUARD_BUILTINS_VERSION + { + uint16_t version = read_u16(&this_instr[3].cache); + PyDictObject *dict = (PyDictObject *)BUILTINS(); + DEOPT_IF(!PyDict_CheckExact(dict), LOAD_GLOBAL); + DEOPT_IF(dict->ma_keys->dk_version != version, LOAD_GLOBAL); + assert(DK_IS_UNICODE(dict->ma_keys)); + } + // _LOAD_GLOBAL_BUILTINS + { + uint16_t index = read_u16(&this_instr[4].cache); + PyDictObject *bdict = (PyDictObject *)BUILTINS(); + PyDictUnicodeEntry *entries = DK_UNICODE_ENTRIES(bdict->ma_keys); + res = entries[index].me_value; + DEOPT_IF(res == NULL, LOAD_GLOBAL); + Py_INCREF(res); + STAT_INC(LOAD_GLOBAL, hit); + null = NULL; + } + stack_pointer[0] = res; + if (oparg & 1) stack_pointer[1] = null; + stack_pointer += 1 + (oparg & 1); DISPATCH(); } - TARGET(IMPORT_NAME) { - PyObject *fromlist; - PyObject *level; + TARGET(LOAD_GLOBAL_MODULE) { + _Py_CODEUNIT *this_instr = frame->instr_ptr = next_instr; + next_instr += 5; + INSTRUCTION_STATS(LOAD_GLOBAL_MODULE); + static_assert(INLINE_CACHE_ENTRIES_LOAD_GLOBAL == 4, "incorrect cache size"); PyObject *res; - fromlist = stack_pointer[-1]; - level = stack_pointer[-2]; - PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); - res = import_name(tstate, frame, name, fromlist, level); - Py_DECREF(level); - Py_DECREF(fromlist); - if (res == NULL) goto pop_2_error; - STACK_SHRINK(1); - stack_pointer[-1] = res; + PyObject *null = NULL; + /* Skip 1 cache entry */ + // _GUARD_GLOBALS_VERSION + { + uint16_t version = read_u16(&this_instr[2].cache); + PyDictObject *dict = (PyDictObject *)GLOBALS(); + DEOPT_IF(!PyDict_CheckExact(dict), LOAD_GLOBAL); + DEOPT_IF(dict->ma_keys->dk_version != version, LOAD_GLOBAL); + assert(DK_IS_UNICODE(dict->ma_keys)); + } + /* Skip 1 cache entry */ + // _LOAD_GLOBAL_MODULE + { + uint16_t index = read_u16(&this_instr[4].cache); + PyDictObject *dict = (PyDictObject *)GLOBALS(); + PyDictUnicodeEntry *entries = DK_UNICODE_ENTRIES(dict->ma_keys); + res = entries[index].me_value; + DEOPT_IF(res == NULL, LOAD_GLOBAL); + Py_INCREF(res); + STAT_INC(LOAD_GLOBAL, hit); + null = NULL; + } + stack_pointer[0] = res; + if (oparg & 1) stack_pointer[1] = null; + stack_pointer += 1 + (oparg & 1); DISPATCH(); } - TARGET(IMPORT_FROM) { - PyObject *from; - PyObject *res; - from = stack_pointer[-1]; - PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); - res = import_from(tstate, from, name); - if (res == NULL) goto error; - STACK_GROW(1); - stack_pointer[-1] = res; + TARGET(LOAD_LOCALS) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(LOAD_LOCALS); + PyObject *locals; + locals = LOCALS(); + if (locals == NULL) { + _PyErr_SetString(tstate, PyExc_SystemError, + "no locals found"); + if (true) goto error; + } + Py_INCREF(locals); + stack_pointer[0] = locals; + stack_pointer += 1; DISPATCH(); } - TARGET(JUMP_FORWARD) { - JUMPBY(oparg); + TARGET(LOAD_NAME) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(LOAD_NAME); + PyObject *v; + PyObject *mod_or_class_dict = LOCALS(); + if (mod_or_class_dict == NULL) { + _PyErr_SetString(tstate, PyExc_SystemError, + "no locals found"); + if (true) goto error; + } + PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); + if (PyMapping_GetOptionalItem(mod_or_class_dict, name, &v) < 0) { + GOTO_ERROR(error); + } + if (v == NULL) { + if (PyDict_GetItemRef(GLOBALS(), name, &v) < 0) { + GOTO_ERROR(error); + } + if (v == NULL) { + if (PyMapping_GetOptionalItem(BUILTINS(), name, &v) < 0) { + GOTO_ERROR(error); + } + if (v == NULL) { + _PyEval_FormatExcCheckArg( + tstate, PyExc_NameError, + NAME_ERROR_MSG, name); + GOTO_ERROR(error); + } + } + } + stack_pointer[0] = v; + stack_pointer += 1; DISPATCH(); } - TARGET(JUMP_BACKWARD) { - CHECK_EVAL_BREAKER(); - _Py_CODEUNIT *here = next_instr - 1; - assert(oparg <= INSTR_OFFSET()); - JUMPBY(1-oparg); - #if ENABLE_SPECIALIZATION - here[1].cache += (1 << OPTIMIZER_BITS_IN_COUNTER); - if (here[1].cache > tstate->interp->optimizer_backedge_threshold && - // Double-check that the opcode isn't instrumented or something: - here->op.code == JUMP_BACKWARD && - // _PyOptimizer_BackEdge is going to change frame->prev_instr, - // which breaks line event calculations: - next_instr->op.code != INSTRUMENTED_LINE - ) + TARGET(LOAD_SUPER_ATTR) { + frame->instr_ptr = next_instr; + next_instr += 2; + INSTRUCTION_STATS(LOAD_SUPER_ATTR); + PREDICTED(LOAD_SUPER_ATTR); + _Py_CODEUNIT *this_instr = next_instr - 2; + PyObject *class; + PyObject *global_super; + PyObject *self; + PyObject *attr; + PyObject *null = NULL; + // _SPECIALIZE_LOAD_SUPER_ATTR + class = stack_pointer[-2]; + global_super = stack_pointer[-3]; { - OBJECT_STAT_INC(optimization_attempts); - frame = _PyOptimizer_BackEdge(frame, here, next_instr, stack_pointer); - if (frame == NULL) { - frame = cframe.current_frame; - goto resume_with_error; + uint16_t counter = read_u16(&this_instr[1].cache); + TIER_ONE_ONLY + #if ENABLE_SPECIALIZATION + int load_method = oparg & 1; + if (ADAPTIVE_COUNTER_IS_ZERO(counter)) { + next_instr = this_instr; + _Py_Specialize_LoadSuperAttr(global_super, class, next_instr, load_method); + DISPATCH_SAME_OPARG(); } - assert(frame == cframe.current_frame); - here[1].cache &= ((1 << OPTIMIZER_BITS_IN_COUNTER) -1); - goto resume_frame; + STAT_INC(LOAD_SUPER_ATTR, deferred); + DECREMENT_ADAPTIVE_COUNTER(this_instr[1].cache); + #endif /* ENABLE_SPECIALIZATION */ } - #endif /* ENABLE_SPECIALIZATION */ - DISPATCH(); - } - - TARGET(ENTER_EXECUTOR) { - CHECK_EVAL_BREAKER(); - - PyCodeObject *code = _PyFrame_GetCode(frame); - _PyExecutorObject *executor = (_PyExecutorObject *)code->co_executors->executors[oparg&255]; - int original_oparg = executor->vm_data.oparg | (oparg & 0xfffff00); - JUMPBY(1-original_oparg); - frame->prev_instr = next_instr - 1; - Py_INCREF(executor); - frame = executor->execute(executor, frame, stack_pointer); - if (frame == NULL) { - frame = cframe.current_frame; - goto resume_with_error; + // _LOAD_SUPER_ATTR + self = stack_pointer[-1]; + { + TIER_ONE_ONLY + if (opcode == INSTRUMENTED_LOAD_SUPER_ATTR) { + PyObject *arg = oparg & 2 ? class : &_PyInstrumentation_MISSING; + int err = _Py_call_instrumentation_2args( + tstate, PY_MONITORING_EVENT_CALL, + frame, this_instr, global_super, arg); + if (err) goto pop_3_error; + } + // we make no attempt to optimize here; specializations should + // handle any case whose performance we care about + PyObject *stack[] = {class, self}; + PyObject *super = PyObject_Vectorcall(global_super, stack, oparg & 2, NULL); + if (opcode == INSTRUMENTED_LOAD_SUPER_ATTR) { + PyObject *arg = oparg & 2 ? class : &_PyInstrumentation_MISSING; + if (super == NULL) { + _Py_call_instrumentation_exc2( + tstate, PY_MONITORING_EVENT_C_RAISE, + frame, this_instr, global_super, arg); + } + else { + int err = _Py_call_instrumentation_2args( + tstate, PY_MONITORING_EVENT_C_RETURN, + frame, this_instr, global_super, arg); + if (err < 0) { + Py_CLEAR(super); + } + } + } + Py_DECREF(global_super); + Py_DECREF(class); + Py_DECREF(self); + if (super == NULL) goto pop_3_error; + PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 2); + attr = PyObject_GetAttr(super, name); + Py_DECREF(super); + if (attr == NULL) goto pop_3_error; + null = NULL; } - goto resume_frame; - } - - TARGET(POP_JUMP_IF_FALSE) { - PyObject *cond; - cond = stack_pointer[-1]; - assert(PyBool_Check(cond)); - JUMPBY(oparg * Py_IsFalse(cond)); - STACK_SHRINK(1); + stack_pointer[-3] = attr; + if (oparg & 1) stack_pointer[-2] = null; + stack_pointer += -2 + (oparg & 1); DISPATCH(); } - TARGET(POP_JUMP_IF_TRUE) { - PyObject *cond; - cond = stack_pointer[-1]; - assert(PyBool_Check(cond)); - JUMPBY(oparg * Py_IsTrue(cond)); - STACK_SHRINK(1); + TARGET(LOAD_SUPER_ATTR_ATTR) { + frame->instr_ptr = next_instr; + next_instr += 2; + INSTRUCTION_STATS(LOAD_SUPER_ATTR_ATTR); + static_assert(INLINE_CACHE_ENTRIES_LOAD_SUPER_ATTR == 1, "incorrect cache size"); + PyObject *self; + PyObject *class; + PyObject *global_super; + PyObject *attr; + /* Skip 1 cache entry */ + self = stack_pointer[-1]; + class = stack_pointer[-2]; + global_super = stack_pointer[-3]; + assert(!(oparg & 1)); + DEOPT_IF(global_super != (PyObject *)&PySuper_Type, LOAD_SUPER_ATTR); + DEOPT_IF(!PyType_Check(class), LOAD_SUPER_ATTR); + STAT_INC(LOAD_SUPER_ATTR, hit); + PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 2); + attr = _PySuper_Lookup((PyTypeObject *)class, self, name, NULL); + Py_DECREF(global_super); + Py_DECREF(class); + Py_DECREF(self); + if (attr == NULL) goto pop_3_error; + stack_pointer[-3] = attr; + stack_pointer += -2 + ((0) ? 1 : 0); DISPATCH(); } - TARGET(POP_JUMP_IF_NONE) { - PyObject *value; - PyObject *b; - PyObject *cond; - // IS_NONE - value = stack_pointer[-1]; - { - if (Py_IsNone(value)) { - b = Py_True; - } - else { - b = Py_False; - Py_DECREF(value); - } + TARGET(LOAD_SUPER_ATTR_METHOD) { + frame->instr_ptr = next_instr; + next_instr += 2; + INSTRUCTION_STATS(LOAD_SUPER_ATTR_METHOD); + static_assert(INLINE_CACHE_ENTRIES_LOAD_SUPER_ATTR == 1, "incorrect cache size"); + PyObject *self; + PyObject *class; + PyObject *global_super; + PyObject *attr; + PyObject *self_or_null; + /* Skip 1 cache entry */ + self = stack_pointer[-1]; + class = stack_pointer[-2]; + global_super = stack_pointer[-3]; + assert(oparg & 1); + DEOPT_IF(global_super != (PyObject *)&PySuper_Type, LOAD_SUPER_ATTR); + DEOPT_IF(!PyType_Check(class), LOAD_SUPER_ATTR); + STAT_INC(LOAD_SUPER_ATTR, hit); + PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 2); + PyTypeObject *cls = (PyTypeObject *)class; + int method_found = 0; + attr = _PySuper_Lookup(cls, self, name, + Py_TYPE(self)->tp_getattro == PyObject_GenericGetAttr ? &method_found : NULL); + Py_DECREF(global_super); + Py_DECREF(class); + if (attr == NULL) { + Py_DECREF(self); + if (true) goto pop_3_error; } - // POP_JUMP_IF_TRUE - cond = b; - { - assert(PyBool_Check(cond)); - JUMPBY(oparg * Py_IsTrue(cond)); + if (method_found) { + self_or_null = self; // transfer ownership + } else { + Py_DECREF(self); + self_or_null = NULL; } - STACK_SHRINK(1); + stack_pointer[-3] = attr; + stack_pointer[-2] = self_or_null; + stack_pointer += -1; DISPATCH(); } - TARGET(POP_JUMP_IF_NOT_NONE) { - PyObject *value; - PyObject *b; - PyObject *cond; - // IS_NONE - value = stack_pointer[-1]; - { - if (Py_IsNone(value)) { - b = Py_True; - } - else { - b = Py_False; - Py_DECREF(value); - } - } - // POP_JUMP_IF_FALSE - cond = b; - { - assert(PyBool_Check(cond)); - JUMPBY(oparg * Py_IsFalse(cond)); + TARGET(MAKE_CELL) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(MAKE_CELL); + // "initial" is probably NULL but not if it's an arg (or set + // via PyFrame_LocalsToFast() before MAKE_CELL has run). + PyObject *initial = GETLOCAL(oparg); + PyObject *cell = PyCell_New(initial); + if (cell == NULL) { + GOTO_ERROR(error); } - STACK_SHRINK(1); + SETLOCAL(oparg, cell); DISPATCH(); } - TARGET(JUMP_BACKWARD_NO_INTERRUPT) { - /* This bytecode is used in the `yield from` or `await` loop. - * If there is an interrupt, we want it handled in the innermost - * generator or coroutine, so we deliberately do not check it here. - * (see bpo-30039). - */ - JUMPBY(-oparg); + TARGET(MAKE_FUNCTION) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(MAKE_FUNCTION); + PyObject *codeobj; + PyObject *func; + codeobj = stack_pointer[-1]; + PyFunctionObject *func_obj = (PyFunctionObject *) + PyFunction_New(codeobj, GLOBALS()); + Py_DECREF(codeobj); + if (func_obj == NULL) { + GOTO_ERROR(error); + } + _PyFunction_SetVersion( + func_obj, ((PyCodeObject *)codeobj)->co_version); + func = (PyObject *)func_obj; + stack_pointer[-1] = func; DISPATCH(); } - TARGET(GET_LEN) { - PyObject *obj; - PyObject *len_o; - obj = stack_pointer[-1]; - // PUSH(len(TOS)) - Py_ssize_t len_i = PyObject_Length(obj); - if (len_i < 0) goto error; - len_o = PyLong_FromSsize_t(len_i); - if (len_o == NULL) goto error; - STACK_GROW(1); - stack_pointer[-1] = len_o; + TARGET(MAP_ADD) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(MAP_ADD); + PyObject *value; + PyObject *key; + PyObject *dict; + value = stack_pointer[-1]; + key = stack_pointer[-2]; + dict = stack_pointer[-3 - (oparg - 1)]; + assert(PyDict_CheckExact(dict)); + /* dict[key] = value */ + // Do not DECREF INPUTS because the function steals the references + if (_PyDict_SetItem_Take2((PyDictObject *)dict, key, value) != 0) goto pop_2_error; + stack_pointer += -2; DISPATCH(); } TARGET(MATCH_CLASS) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(MATCH_CLASS); PyObject *names; PyObject *type; PyObject *subject; @@ -3030,432 +4511,193 @@ } else { if (_PyErr_Occurred(tstate)) goto pop_3_error; + // Error! attrs = Py_None; // Failure! } - STACK_SHRINK(2); - stack_pointer[-1] = attrs; - DISPATCH(); - } - - TARGET(MATCH_MAPPING) { - PyObject *subject; - PyObject *res; - subject = stack_pointer[-1]; - int match = Py_TYPE(subject)->tp_flags & Py_TPFLAGS_MAPPING; - res = match ? Py_True : Py_False; - STACK_GROW(1); - stack_pointer[-1] = res; - DISPATCH(); - } - - TARGET(MATCH_SEQUENCE) { - PyObject *subject; - PyObject *res; - subject = stack_pointer[-1]; - int match = Py_TYPE(subject)->tp_flags & Py_TPFLAGS_SEQUENCE; - res = match ? Py_True : Py_False; - STACK_GROW(1); - stack_pointer[-1] = res; + stack_pointer[-3] = attrs; + stack_pointer += -2; DISPATCH(); } TARGET(MATCH_KEYS) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(MATCH_KEYS); PyObject *keys; PyObject *subject; PyObject *values_or_none; - keys = stack_pointer[-1]; - subject = stack_pointer[-2]; - // On successful match, PUSH(values). Otherwise, PUSH(None). - values_or_none = _PyEval_MatchKeys(tstate, subject, keys); - if (values_or_none == NULL) goto error; - STACK_GROW(1); - stack_pointer[-1] = values_or_none; - DISPATCH(); - } - - TARGET(GET_ITER) { - PyObject *iterable; - PyObject *iter; - iterable = stack_pointer[-1]; - /* before: [obj]; after [getiter(obj)] */ - iter = PyObject_GetIter(iterable); - Py_DECREF(iterable); - if (iter == NULL) goto pop_1_error; - stack_pointer[-1] = iter; - DISPATCH(); - } - - TARGET(GET_YIELD_FROM_ITER) { - PyObject *iterable; - PyObject *iter; - iterable = stack_pointer[-1]; - /* before: [obj]; after [getiter(obj)] */ - if (PyCoro_CheckExact(iterable)) { - /* `iterable` is a coroutine */ - if (!(_PyFrame_GetCode(frame)->co_flags & (CO_COROUTINE | CO_ITERABLE_COROUTINE))) { - /* and it is used in a 'yield from' expression of a - regular generator. */ - _PyErr_SetString(tstate, PyExc_TypeError, - "cannot 'yield from' a coroutine object " - "in a non-coroutine generator"); - goto error; - } - iter = iterable; - } - else if (PyGen_CheckExact(iterable)) { - iter = iterable; - } - else { - /* `iterable` is not a generator. */ - iter = PyObject_GetIter(iterable); - if (iter == NULL) { - goto error; - } - Py_DECREF(iterable); - } - stack_pointer[-1] = iter; - DISPATCH(); - } - - TARGET(FOR_ITER) { - PREDICTED(FOR_ITER); - static_assert(INLINE_CACHE_ENTRIES_FOR_ITER == 1, "incorrect cache size"); - PyObject *iter; - PyObject *next; - iter = stack_pointer[-1]; - #if ENABLE_SPECIALIZATION - _PyForIterCache *cache = (_PyForIterCache *)next_instr; - if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) { - next_instr--; - _Py_Specialize_ForIter(iter, next_instr, oparg); - DISPATCH_SAME_OPARG(); - } - STAT_INC(FOR_ITER, deferred); - DECREMENT_ADAPTIVE_COUNTER(cache->counter); - #endif /* ENABLE_SPECIALIZATION */ - /* before: [iter]; after: [iter, iter()] *or* [] (and jump over END_FOR.) */ - next = (*Py_TYPE(iter)->tp_iternext)(iter); - if (next == NULL) { - if (_PyErr_Occurred(tstate)) { - if (!_PyErr_ExceptionMatches(tstate, PyExc_StopIteration)) { - goto error; - } - monitor_raise(tstate, frame, next_instr-1); - _PyErr_Clear(tstate); - } - /* iterator ended normally */ - assert(next_instr[INLINE_CACHE_ENTRIES_FOR_ITER + oparg].op.code == END_FOR || - next_instr[INLINE_CACHE_ENTRIES_FOR_ITER + oparg].op.code == INSTRUMENTED_END_FOR); - Py_DECREF(iter); - STACK_SHRINK(1); - SKIP_OVER(INLINE_CACHE_ENTRIES_FOR_ITER); - /* Jump forward oparg, then skip following END_FOR instruction */ - JUMPBY(oparg + 1); - DISPATCH(); - } - // Common case: no jump, leave it to the code generator - STACK_GROW(1); - stack_pointer[-1] = next; - next_instr += 1; - DISPATCH(); - } - - TARGET(INSTRUMENTED_FOR_ITER) { - _Py_CODEUNIT *here = next_instr-1; - _Py_CODEUNIT *target; - PyObject *iter = TOP(); - PyObject *next = (*Py_TYPE(iter)->tp_iternext)(iter); - if (next != NULL) { - PUSH(next); - target = next_instr + INLINE_CACHE_ENTRIES_FOR_ITER; - } - else { - if (_PyErr_Occurred(tstate)) { - if (!_PyErr_ExceptionMatches(tstate, PyExc_StopIteration)) { - goto error; - } - monitor_raise(tstate, frame, here); - _PyErr_Clear(tstate); - } - /* iterator ended normally */ - assert(next_instr[INLINE_CACHE_ENTRIES_FOR_ITER + oparg].op.code == END_FOR || - next_instr[INLINE_CACHE_ENTRIES_FOR_ITER + oparg].op.code == INSTRUMENTED_END_FOR); - STACK_SHRINK(1); - Py_DECREF(iter); - /* Skip END_FOR */ - target = next_instr + INLINE_CACHE_ENTRIES_FOR_ITER + oparg + 1; - } - INSTRUMENTED_JUMP(here, target, PY_MONITORING_EVENT_BRANCH); - DISPATCH(); - } - - TARGET(FOR_ITER_LIST) { - PyObject *iter; - PyObject *next; - // _ITER_CHECK_LIST - iter = stack_pointer[-1]; - { - DEOPT_IF(Py_TYPE(iter) != &PyListIter_Type, FOR_ITER); - } - // _ITER_JUMP_LIST - { - _PyListIterObject *it = (_PyListIterObject *)iter; - assert(Py_TYPE(iter) == &PyListIter_Type); - STAT_INC(FOR_ITER, hit); - PyListObject *seq = it->it_seq; - if (seq == NULL || it->it_index >= PyList_GET_SIZE(seq)) { - if (seq != NULL) { - it->it_seq = NULL; - Py_DECREF(seq); - } - Py_DECREF(iter); - STACK_SHRINK(1); - SKIP_OVER(INLINE_CACHE_ENTRIES_FOR_ITER); - /* Jump forward oparg, then skip following END_FOR instruction */ - JUMPBY(oparg + 1); - DISPATCH(); - } - } - // _ITER_NEXT_LIST - { - _PyListIterObject *it = (_PyListIterObject *)iter; - assert(Py_TYPE(iter) == &PyListIter_Type); - PyListObject *seq = it->it_seq; - assert(seq); - assert(it->it_index < PyList_GET_SIZE(seq)); - next = Py_NewRef(PyList_GET_ITEM(seq, it->it_index++)); - } - STACK_GROW(1); - stack_pointer[-1] = next; - next_instr += 1; - DISPATCH(); - } - - TARGET(FOR_ITER_TUPLE) { - PyObject *iter; - PyObject *next; - // _ITER_CHECK_TUPLE - iter = stack_pointer[-1]; - { - DEOPT_IF(Py_TYPE(iter) != &PyTupleIter_Type, FOR_ITER); - } - // _ITER_JUMP_TUPLE - { - _PyTupleIterObject *it = (_PyTupleIterObject *)iter; - assert(Py_TYPE(iter) == &PyTupleIter_Type); - STAT_INC(FOR_ITER, hit); - PyTupleObject *seq = it->it_seq; - if (seq == NULL || it->it_index >= PyTuple_GET_SIZE(seq)) { - if (seq != NULL) { - it->it_seq = NULL; - Py_DECREF(seq); - } - Py_DECREF(iter); - STACK_SHRINK(1); - SKIP_OVER(INLINE_CACHE_ENTRIES_FOR_ITER); - /* Jump forward oparg, then skip following END_FOR instruction */ - JUMPBY(oparg + 1); - DISPATCH(); - } - } - // _ITER_NEXT_TUPLE - { - _PyTupleIterObject *it = (_PyTupleIterObject *)iter; - assert(Py_TYPE(iter) == &PyTupleIter_Type); - PyTupleObject *seq = it->it_seq; - assert(seq); - assert(it->it_index < PyTuple_GET_SIZE(seq)); - next = Py_NewRef(PyTuple_GET_ITEM(seq, it->it_index++)); - } - STACK_GROW(1); - stack_pointer[-1] = next; - next_instr += 1; - DISPATCH(); - } - - TARGET(FOR_ITER_RANGE) { - PyObject *iter; - PyObject *next; - // _ITER_CHECK_RANGE - iter = stack_pointer[-1]; - { - _PyRangeIterObject *r = (_PyRangeIterObject *)iter; - DEOPT_IF(Py_TYPE(r) != &PyRangeIter_Type, FOR_ITER); - } - // _ITER_JUMP_RANGE - { - _PyRangeIterObject *r = (_PyRangeIterObject *)iter; - assert(Py_TYPE(r) == &PyRangeIter_Type); - STAT_INC(FOR_ITER, hit); - if (r->len <= 0) { - STACK_SHRINK(1); - Py_DECREF(r); - SKIP_OVER(INLINE_CACHE_ENTRIES_FOR_ITER); - // Jump over END_FOR instruction. - JUMPBY(oparg + 1); - DISPATCH(); - } - } - // _ITER_NEXT_RANGE - { - _PyRangeIterObject *r = (_PyRangeIterObject *)iter; - assert(Py_TYPE(r) == &PyRangeIter_Type); - assert(r->len > 0); - long value = r->start; - r->start = value + r->step; - r->len--; - next = PyLong_FromLong(value); - if (next == NULL) goto error; - } - STACK_GROW(1); - stack_pointer[-1] = next; - next_instr += 1; + keys = stack_pointer[-1]; + subject = stack_pointer[-2]; + // On successful match, PUSH(values). Otherwise, PUSH(None). + values_or_none = _PyEval_MatchKeys(tstate, subject, keys); + if (values_or_none == NULL) goto error; + stack_pointer[0] = values_or_none; + stack_pointer += 1; DISPATCH(); } - TARGET(FOR_ITER_GEN) { - PyObject *iter; - iter = stack_pointer[-1]; - DEOPT_IF(tstate->interp->eval_frame, FOR_ITER); - PyGenObject *gen = (PyGenObject *)iter; - DEOPT_IF(Py_TYPE(gen) != &PyGen_Type, FOR_ITER); - DEOPT_IF(gen->gi_frame_state >= FRAME_EXECUTING, FOR_ITER); - STAT_INC(FOR_ITER, hit); - _PyInterpreterFrame *gen_frame = (_PyInterpreterFrame *)gen->gi_iframe; - frame->return_offset = oparg; - _PyFrame_StackPush(gen_frame, Py_None); - gen->gi_frame_state = FRAME_EXECUTING; - gen->gi_exc_state.previous_item = tstate->exc_info; - tstate->exc_info = &gen->gi_exc_state; - SKIP_OVER(INLINE_CACHE_ENTRIES_FOR_ITER); - assert(next_instr[oparg].op.code == END_FOR || - next_instr[oparg].op.code == INSTRUMENTED_END_FOR); - DISPATCH_INLINED(gen_frame); - STACK_GROW(1); + TARGET(MATCH_MAPPING) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(MATCH_MAPPING); + PyObject *subject; + PyObject *res; + subject = stack_pointer[-1]; + int match = Py_TYPE(subject)->tp_flags & Py_TPFLAGS_MAPPING; + res = match ? Py_True : Py_False; + stack_pointer[0] = res; + stack_pointer += 1; + DISPATCH(); } - TARGET(BEFORE_ASYNC_WITH) { - PyObject *mgr; - PyObject *exit; + TARGET(MATCH_SEQUENCE) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(MATCH_SEQUENCE); + PyObject *subject; PyObject *res; - mgr = stack_pointer[-1]; - PyObject *enter = _PyObject_LookupSpecial(mgr, &_Py_ID(__aenter__)); - if (enter == NULL) { - if (!_PyErr_Occurred(tstate)) { - _PyErr_Format(tstate, PyExc_TypeError, - "'%.200s' object does not support the " - "asynchronous context manager protocol", - Py_TYPE(mgr)->tp_name); + subject = stack_pointer[-1]; + int match = Py_TYPE(subject)->tp_flags & Py_TPFLAGS_SEQUENCE; + res = match ? Py_True : Py_False; + stack_pointer[0] = res; + stack_pointer += 1; + DISPATCH(); + } + + TARGET(NOP) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(NOP); + DISPATCH(); + } + + TARGET(POP_EXCEPT) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(POP_EXCEPT); + PyObject *exc_value; + exc_value = stack_pointer[-1]; + _PyErr_StackItem *exc_info = tstate->exc_info; + Py_XSETREF(exc_info->exc_value, exc_value == Py_None ? NULL : exc_value); + stack_pointer += -1; + DISPATCH(); + } + + TARGET(POP_JUMP_IF_FALSE) { + _Py_CODEUNIT *this_instr = frame->instr_ptr = next_instr; + next_instr += 2; + INSTRUCTION_STATS(POP_JUMP_IF_FALSE); + PyObject *cond; + /* Skip 1 cache entry */ + cond = stack_pointer[-1]; + assert(PyBool_Check(cond)); + int flag = Py_IsFalse(cond); + #if ENABLE_SPECIALIZATION + this_instr[1].cache = (this_instr[1].cache << 1) | flag; + #endif + JUMPBY(oparg * flag); + stack_pointer += -1; + DISPATCH(); + } + + TARGET(POP_JUMP_IF_NONE) { + _Py_CODEUNIT *this_instr = frame->instr_ptr = next_instr; + next_instr += 2; + INSTRUCTION_STATS(POP_JUMP_IF_NONE); + PyObject *value; + PyObject *b; + PyObject *cond; + /* Skip 1 cache entry */ + // _IS_NONE + value = stack_pointer[-1]; + { + if (Py_IsNone(value)) { + b = Py_True; } - goto error; - } - exit = _PyObject_LookupSpecial(mgr, &_Py_ID(__aexit__)); - if (exit == NULL) { - if (!_PyErr_Occurred(tstate)) { - _PyErr_Format(tstate, PyExc_TypeError, - "'%.200s' object does not support the " - "asynchronous context manager protocol " - "(missed __aexit__ method)", - Py_TYPE(mgr)->tp_name); + else { + b = Py_False; + Py_DECREF(value); } - Py_DECREF(enter); - goto error; } - Py_DECREF(mgr); - res = _PyObject_CallNoArgs(enter); - Py_DECREF(enter); - if (res == NULL) { - Py_DECREF(exit); - if (true) goto pop_1_error; + // _POP_JUMP_IF_TRUE + cond = b; + { + assert(PyBool_Check(cond)); + int flag = Py_IsTrue(cond); + #if ENABLE_SPECIALIZATION + this_instr[1].cache = (this_instr[1].cache << 1) | flag; + #endif + JUMPBY(oparg * flag); } - STACK_GROW(1); - stack_pointer[-2] = exit; - stack_pointer[-1] = res; + stack_pointer += -1; DISPATCH(); } - TARGET(BEFORE_WITH) { - PyObject *mgr; - PyObject *exit; - PyObject *res; - mgr = stack_pointer[-1]; - /* pop the context manager, push its __exit__ and the - * value returned from calling its __enter__ - */ - PyObject *enter = _PyObject_LookupSpecial(mgr, &_Py_ID(__enter__)); - if (enter == NULL) { - if (!_PyErr_Occurred(tstate)) { - _PyErr_Format(tstate, PyExc_TypeError, - "'%.200s' object does not support the " - "context manager protocol", - Py_TYPE(mgr)->tp_name); + TARGET(POP_JUMP_IF_NOT_NONE) { + _Py_CODEUNIT *this_instr = frame->instr_ptr = next_instr; + next_instr += 2; + INSTRUCTION_STATS(POP_JUMP_IF_NOT_NONE); + PyObject *value; + PyObject *b; + PyObject *cond; + /* Skip 1 cache entry */ + // _IS_NONE + value = stack_pointer[-1]; + { + if (Py_IsNone(value)) { + b = Py_True; } - goto error; - } - exit = _PyObject_LookupSpecial(mgr, &_Py_ID(__exit__)); - if (exit == NULL) { - if (!_PyErr_Occurred(tstate)) { - _PyErr_Format(tstate, PyExc_TypeError, - "'%.200s' object does not support the " - "context manager protocol " - "(missed __exit__ method)", - Py_TYPE(mgr)->tp_name); + else { + b = Py_False; + Py_DECREF(value); } - Py_DECREF(enter); - goto error; } - Py_DECREF(mgr); - res = _PyObject_CallNoArgs(enter); - Py_DECREF(enter); - if (res == NULL) { - Py_DECREF(exit); - if (true) goto pop_1_error; + // _POP_JUMP_IF_FALSE + cond = b; + { + assert(PyBool_Check(cond)); + int flag = Py_IsFalse(cond); + #if ENABLE_SPECIALIZATION + this_instr[1].cache = (this_instr[1].cache << 1) | flag; + #endif + JUMPBY(oparg * flag); } - STACK_GROW(1); - stack_pointer[-2] = exit; - stack_pointer[-1] = res; + stack_pointer += -1; DISPATCH(); } - TARGET(WITH_EXCEPT_START) { - PyObject *val; - PyObject *lasti; - PyObject *exit_func; - PyObject *res; - val = stack_pointer[-1]; - lasti = stack_pointer[-3]; - exit_func = stack_pointer[-4]; - /* At the top of the stack are 4 values: - - val: TOP = exc_info() - - unused: SECOND = previous exception - - lasti: THIRD = lasti of exception in exc_info() - - exit_func: FOURTH = the context.__exit__ bound method - We call FOURTH(type(TOP), TOP, GetTraceback(TOP)). - Then we push the __exit__ return value. - */ - PyObject *exc, *tb; + TARGET(POP_JUMP_IF_TRUE) { + _Py_CODEUNIT *this_instr = frame->instr_ptr = next_instr; + next_instr += 2; + INSTRUCTION_STATS(POP_JUMP_IF_TRUE); + PyObject *cond; + /* Skip 1 cache entry */ + cond = stack_pointer[-1]; + assert(PyBool_Check(cond)); + int flag = Py_IsTrue(cond); + #if ENABLE_SPECIALIZATION + this_instr[1].cache = (this_instr[1].cache << 1) | flag; + #endif + JUMPBY(oparg * flag); + stack_pointer += -1; + DISPATCH(); + } - assert(val && PyExceptionInstance_Check(val)); - exc = PyExceptionInstance_Class(val); - tb = PyException_GetTraceback(val); - if (tb == NULL) { - tb = Py_None; - } - else { - Py_DECREF(tb); - } - assert(PyLong_Check(lasti)); - (void)lasti; // Shut up compiler warning if asserts are off - PyObject *stack[4] = {NULL, exc, val, tb}; - res = PyObject_Vectorcall(exit_func, stack + 1, - 3 | PY_VECTORCALL_ARGUMENTS_OFFSET, NULL); - if (res == NULL) goto error; - STACK_GROW(1); - stack_pointer[-1] = res; + TARGET(POP_TOP) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(POP_TOP); + PyObject *value; + value = stack_pointer[-1]; + Py_DECREF(value); + stack_pointer += -1; DISPATCH(); } TARGET(PUSH_EXC_INFO) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(PUSH_EXC_INFO); PyObject *new_exc; PyObject *prev_exc; new_exc = stack_pointer[-1]; @@ -3468,1333 +4710,1188 @@ } assert(PyExceptionInstance_Check(new_exc)); exc_info->exc_value = Py_NewRef(new_exc); - STACK_GROW(1); - stack_pointer[-2] = prev_exc; - stack_pointer[-1] = new_exc; + stack_pointer[-1] = prev_exc; + stack_pointer[0] = new_exc; + stack_pointer += 1; DISPATCH(); } - TARGET(LOAD_ATTR_METHOD_WITH_VALUES) { - PyObject *self; - PyObject *res2; + TARGET(PUSH_NULL) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(PUSH_NULL); PyObject *res; - self = stack_pointer[-1]; - uint32_t type_version = read_u32(&next_instr[1].cache); - uint32_t keys_version = read_u32(&next_instr[3].cache); - PyObject *descr = read_obj(&next_instr[5].cache); - assert(oparg & 1); - /* Cached method object */ - PyTypeObject *self_cls = Py_TYPE(self); - assert(type_version != 0); - DEOPT_IF(self_cls->tp_version_tag != type_version, LOAD_ATTR); - assert(self_cls->tp_flags & Py_TPFLAGS_MANAGED_DICT); - PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(self); - DEOPT_IF(!_PyDictOrValues_IsValues(dorv), LOAD_ATTR); - PyHeapTypeObject *self_heap_type = (PyHeapTypeObject *)self_cls; - DEOPT_IF(self_heap_type->ht_cached_keys->dk_version != - keys_version, LOAD_ATTR); - STAT_INC(LOAD_ATTR, hit); - assert(descr != NULL); - res2 = Py_NewRef(descr); - assert(_PyType_HasFeature(Py_TYPE(res2), Py_TPFLAGS_METHOD_DESCRIPTOR)); - res = self; - STACK_GROW(1); - stack_pointer[-2] = res2; - stack_pointer[-1] = res; - next_instr += 9; + res = NULL; + stack_pointer[0] = res; + stack_pointer += 1; DISPATCH(); } - TARGET(LOAD_ATTR_METHOD_NO_DICT) { - PyObject *self; - PyObject *res2; - PyObject *res; - self = stack_pointer[-1]; - uint32_t type_version = read_u32(&next_instr[1].cache); - PyObject *descr = read_obj(&next_instr[5].cache); - assert(oparg & 1); - PyTypeObject *self_cls = Py_TYPE(self); - DEOPT_IF(self_cls->tp_version_tag != type_version, LOAD_ATTR); - assert(self_cls->tp_dictoffset == 0); - STAT_INC(LOAD_ATTR, hit); - assert(descr != NULL); - assert(_PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_METHOD_DESCRIPTOR)); - res2 = Py_NewRef(descr); - res = self; - STACK_GROW(1); - stack_pointer[-2] = res2; - stack_pointer[-1] = res; - next_instr += 9; - DISPATCH(); + TARGET(RAISE_VARARGS) { + _Py_CODEUNIT *this_instr = frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(RAISE_VARARGS); + PyObject **args; + args = &stack_pointer[-oparg]; + TIER_ONE_ONLY + PyObject *cause = NULL, *exc = NULL; + switch (oparg) { + case 2: + cause = args[1]; + /* fall through */ + case 1: + exc = args[0]; + /* fall through */ + case 0: + if (do_raise(tstate, exc, cause)) { + assert(oparg == 0); + monitor_reraise(tstate, frame, this_instr); + goto exception_unwind; + } + break; + default: + _PyErr_SetString(tstate, PyExc_SystemError, + "bad RAISE_VARARGS oparg"); + break; + } + if (true) { stack_pointer += -oparg; goto error; } } - TARGET(LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES) { - PyObject *self; - PyObject *res; - self = stack_pointer[-1]; - uint32_t type_version = read_u32(&next_instr[1].cache); - uint32_t keys_version = read_u32(&next_instr[3].cache); - PyObject *descr = read_obj(&next_instr[5].cache); - assert((oparg & 1) == 0); - PyTypeObject *self_cls = Py_TYPE(self); - assert(type_version != 0); - DEOPT_IF(self_cls->tp_version_tag != type_version, LOAD_ATTR); - assert(self_cls->tp_flags & Py_TPFLAGS_MANAGED_DICT); - PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(self); - DEOPT_IF(!_PyDictOrValues_IsValues(dorv), LOAD_ATTR); - PyHeapTypeObject *self_heap_type = (PyHeapTypeObject *)self_cls; - DEOPT_IF(self_heap_type->ht_cached_keys->dk_version != - keys_version, LOAD_ATTR); - STAT_INC(LOAD_ATTR, hit); - assert(descr != NULL); - Py_DECREF(self); - res = Py_NewRef(descr); - stack_pointer[-1] = res; - next_instr += 9; - DISPATCH(); + TARGET(RERAISE) { + _Py_CODEUNIT *this_instr = frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(RERAISE); + PyObject *exc; + PyObject **values; + exc = stack_pointer[-1]; + values = &stack_pointer[-1 - oparg]; + TIER_ONE_ONLY + assert(oparg >= 0 && oparg <= 2); + if (oparg) { + PyObject *lasti = values[0]; + if (PyLong_Check(lasti)) { + frame->instr_ptr = _PyCode_CODE(_PyFrame_GetCode(frame)) + PyLong_AsLong(lasti); + assert(!_PyErr_Occurred(tstate)); + } + else { + assert(PyLong_Check(lasti)); + _PyErr_SetString(tstate, PyExc_SystemError, "lasti is not an int"); + GOTO_ERROR(error); + } + } + assert(exc && PyExceptionInstance_Check(exc)); + Py_INCREF(exc); + _PyErr_SetRaisedException(tstate, exc); + monitor_reraise(tstate, frame, this_instr); + goto exception_unwind; } - TARGET(LOAD_ATTR_NONDESCRIPTOR_NO_DICT) { - PyObject *self; - PyObject *res; - self = stack_pointer[-1]; - uint32_t type_version = read_u32(&next_instr[1].cache); - PyObject *descr = read_obj(&next_instr[5].cache); - assert((oparg & 1) == 0); - PyTypeObject *self_cls = Py_TYPE(self); - assert(type_version != 0); - DEOPT_IF(self_cls->tp_version_tag != type_version, LOAD_ATTR); - assert(self_cls->tp_dictoffset == 0); - STAT_INC(LOAD_ATTR, hit); - assert(descr != NULL); - Py_DECREF(self); - res = Py_NewRef(descr); - stack_pointer[-1] = res; - next_instr += 9; - DISPATCH(); + TARGET(RESERVED) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(RESERVED); + TIER_ONE_ONLY + assert(0 && "Executing RESERVED instruction."); + Py_UNREACHABLE(); } - TARGET(LOAD_ATTR_METHOD_LAZY_DICT) { - PyObject *self; - PyObject *res2; - PyObject *res; - self = stack_pointer[-1]; - uint32_t type_version = read_u32(&next_instr[1].cache); - PyObject *descr = read_obj(&next_instr[5].cache); - assert(oparg & 1); - PyTypeObject *self_cls = Py_TYPE(self); - DEOPT_IF(self_cls->tp_version_tag != type_version, LOAD_ATTR); - Py_ssize_t dictoffset = self_cls->tp_dictoffset; - assert(dictoffset > 0); - PyObject *dict = *(PyObject **)((char *)self + dictoffset); - /* This object has a __dict__, just not yet created */ - DEOPT_IF(dict != NULL, LOAD_ATTR); - STAT_INC(LOAD_ATTR, hit); - assert(descr != NULL); - assert(_PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_METHOD_DESCRIPTOR)); - res2 = Py_NewRef(descr); - res = self; - STACK_GROW(1); - stack_pointer[-2] = res2; - stack_pointer[-1] = res; - next_instr += 9; + TARGET(RESUME) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(RESUME); + PREDICTED(RESUME); + _Py_CODEUNIT *this_instr = next_instr - 1; + TIER_ONE_ONLY + assert(frame == tstate->current_frame); + uintptr_t global_version = + _Py_atomic_load_uintptr_relaxed(&tstate->interp->ceval.eval_breaker) & + ~_PY_EVAL_EVENTS_MASK; + uintptr_t code_version = _PyFrame_GetCode(frame)->_co_instrumentation_version; + assert((code_version & 255) == 0); + if (code_version != global_version) { + int err = _Py_Instrument(_PyFrame_GetCode(frame), tstate->interp); + if (err) goto error; + next_instr = this_instr; + } + else { + if ((oparg & RESUME_OPARG_LOCATION_MASK) < RESUME_AFTER_YIELD_FROM) { + CHECK_EVAL_BREAKER(); + } + this_instr->op.code = RESUME_CHECK; + } DISPATCH(); } - TARGET(KW_NAMES) { - ASSERT_KWNAMES_IS_NULL(); - assert(oparg < PyTuple_GET_SIZE(FRAME_CO_CONSTS)); - kwnames = GETITEM(FRAME_CO_CONSTS, oparg); + TARGET(RESUME_CHECK) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(RESUME_CHECK); + static_assert(0 == 0, "incorrect cache size"); + #if defined(__EMSCRIPTEN__) + DEOPT_IF(_Py_emscripten_signal_clock == 0, RESUME); + _Py_emscripten_signal_clock -= Py_EMSCRIPTEN_SIGNAL_HANDLING; + #endif + uintptr_t eval_breaker = _Py_atomic_load_uintptr_relaxed(&tstate->interp->ceval.eval_breaker); + uintptr_t version = _PyFrame_GetCode(frame)->_co_instrumentation_version; + assert((version & _PY_EVAL_EVENTS_MASK) == 0); + DEOPT_IF(eval_breaker != version, RESUME); DISPATCH(); } - TARGET(INSTRUMENTED_CALL) { - int is_meth = PEEK(oparg+2) != NULL; - int total_args = oparg + is_meth; - PyObject *function = PEEK(total_args + 1); - PyObject *arg = total_args == 0 ? - &_PyInstrumentation_MISSING : PEEK(total_args); - int err = _Py_call_instrumentation_2args( - tstate, PY_MONITORING_EVENT_CALL, - frame, next_instr-1, function, arg); - if (err) goto error; - _PyCallCache *cache = (_PyCallCache *)next_instr; - INCREMENT_ADAPTIVE_COUNTER(cache->counter); - GO_TO_INSTRUCTION(CALL); + TARGET(RETURN_CONST) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(RETURN_CONST); + PyObject *value; + PyObject *retval; + // _LOAD_CONST + { + value = GETITEM(FRAME_CO_CONSTS, oparg); + Py_INCREF(value); + } + // _POP_FRAME + retval = value; + { + #if TIER_ONE + assert(frame != &entry_frame); + #endif + _PyFrame_SetStackPointer(frame, stack_pointer); + assert(EMPTY()); + _Py_LeaveRecursiveCallPy(tstate); + // GH-99729: We need to unlink the frame *before* clearing it: + _PyInterpreterFrame *dying = frame; + frame = tstate->current_frame = dying->previous; + _PyEval_FrameClearAndPop(tstate, dying); + _PyFrame_StackPush(frame, retval); + LOAD_SP(); + LOAD_IP(frame->return_offset); + #if LLTRACE && TIER_ONE + lltrace = maybe_lltrace_resume_frame(frame, &entry_frame, GLOBALS()); + if (lltrace < 0) { + goto exit_unwind; + } + #endif + } + DISPATCH(); } - TARGET(CALL) { - PREDICTED(CALL); - static_assert(INLINE_CACHE_ENTRIES_CALL == 3, "incorrect cache size"); - PyObject **args; - PyObject *callable; - PyObject *method; - PyObject *res; - args = stack_pointer - oparg; - callable = stack_pointer[-1 - oparg]; - method = stack_pointer[-2 - oparg]; - int is_meth = method != NULL; - int total_args = oparg; - if (is_meth) { - callable = method; - args--; - total_args++; + TARGET(RETURN_GENERATOR) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(RETURN_GENERATOR); + TIER_ONE_ONLY + assert(PyFunction_Check(frame->f_funcobj)); + PyFunctionObject *func = (PyFunctionObject *)frame->f_funcobj; + PyGenObject *gen = (PyGenObject *)_Py_MakeCoro(func); + if (gen == NULL) { + GOTO_ERROR(error); } - #if ENABLE_SPECIALIZATION - _PyCallCache *cache = (_PyCallCache *)next_instr; - if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) { - next_instr--; - _Py_Specialize_Call(callable, next_instr, total_args, kwnames); - DISPATCH_SAME_OPARG(); - } - STAT_INC(CALL, deferred); - DECREMENT_ADAPTIVE_COUNTER(cache->counter); - #endif /* ENABLE_SPECIALIZATION */ - if (!is_meth && Py_TYPE(callable) == &PyMethod_Type) { - is_meth = 1; // For consistenct; it's dead, though - args--; - total_args++; - PyObject *self = ((PyMethodObject *)callable)->im_self; - args[0] = Py_NewRef(self); - method = ((PyMethodObject *)callable)->im_func; - args[-1] = Py_NewRef(method); - Py_DECREF(callable); - callable = method; + assert(EMPTY()); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyInterpreterFrame *gen_frame = (_PyInterpreterFrame *)gen->gi_iframe; + frame->instr_ptr = next_instr; + _PyFrame_Copy(frame, gen_frame); + assert(frame->frame_obj == NULL); + gen->gi_frame_state = FRAME_CREATED; + gen_frame->owner = FRAME_OWNED_BY_GENERATOR; + _Py_LeaveRecursiveCallPy(tstate); + assert(frame != &entry_frame); + _PyInterpreterFrame *prev = frame->previous; + _PyThreadState_PopFrame(tstate, frame); + frame = tstate->current_frame = prev; + _PyFrame_StackPush(frame, (PyObject *)gen); + LOAD_IP(frame->return_offset); + goto resume_frame; + } + + TARGET(RETURN_VALUE) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(RETURN_VALUE); + PyObject *retval; + retval = stack_pointer[-1]; + #if TIER_ONE + assert(frame != &entry_frame); + #endif + stack_pointer += -1; + _PyFrame_SetStackPointer(frame, stack_pointer); + assert(EMPTY()); + _Py_LeaveRecursiveCallPy(tstate); + // GH-99729: We need to unlink the frame *before* clearing it: + _PyInterpreterFrame *dying = frame; + frame = tstate->current_frame = dying->previous; + _PyEval_FrameClearAndPop(tstate, dying); + _PyFrame_StackPush(frame, retval); + LOAD_SP(); + LOAD_IP(frame->return_offset); + #if LLTRACE && TIER_ONE + lltrace = maybe_lltrace_resume_frame(frame, &entry_frame, GLOBALS()); + if (lltrace < 0) { + goto exit_unwind; } - int positional_args = total_args - KWNAMES_LEN(); - // Check if the call can be inlined or not - if (Py_TYPE(callable) == &PyFunction_Type && - tstate->interp->eval_frame == NULL && - ((PyFunctionObject *)callable)->vectorcall == _PyFunction_Vectorcall) + #endif + DISPATCH(); + } + + TARGET(SEND) { + frame->instr_ptr = next_instr; + next_instr += 2; + INSTRUCTION_STATS(SEND); + PREDICTED(SEND); + _Py_CODEUNIT *this_instr = next_instr - 2; + PyObject *receiver; + PyObject *v; + PyObject *retval; + // _SPECIALIZE_SEND + receiver = stack_pointer[-2]; { - int code_flags = ((PyCodeObject*)PyFunction_GET_CODE(callable))->co_flags; - PyObject *locals = code_flags & CO_OPTIMIZED ? NULL : Py_NewRef(PyFunction_GET_GLOBALS(callable)); - _PyInterpreterFrame *new_frame = _PyEvalFramePushAndInit( - tstate, (PyFunctionObject *)callable, locals, - args, positional_args, kwnames - ); - kwnames = NULL; - // Manipulate stack directly since we leave using DISPATCH_INLINED(). - STACK_SHRINK(oparg + 2); - // The frame has stolen all the arguments from the stack, - // so there is no need to clean them up. - if (new_frame == NULL) { - goto error; + uint16_t counter = read_u16(&this_instr[1].cache); + TIER_ONE_ONLY + #if ENABLE_SPECIALIZATION + if (ADAPTIVE_COUNTER_IS_ZERO(counter)) { + next_instr = this_instr; + _Py_Specialize_Send(receiver, next_instr); + DISPATCH_SAME_OPARG(); } - SKIP_OVER(INLINE_CACHE_ENTRIES_CALL); - frame->return_offset = 0; - DISPATCH_INLINED(new_frame); + STAT_INC(SEND, deferred); + DECREMENT_ADAPTIVE_COUNTER(this_instr[1].cache); + #endif /* ENABLE_SPECIALIZATION */ } - /* Callable is not a normal Python function */ - res = PyObject_Vectorcall( - callable, args, - positional_args | PY_VECTORCALL_ARGUMENTS_OFFSET, - kwnames); - if (opcode == INSTRUMENTED_CALL) { - PyObject *arg = total_args == 0 ? - &_PyInstrumentation_MISSING : PEEK(total_args); - if (res == NULL) { - _Py_call_instrumentation_exc2( - tstate, PY_MONITORING_EVENT_C_RAISE, - frame, next_instr-1, callable, arg); + // _SEND + v = stack_pointer[-1]; + { + assert(frame != &entry_frame); + if ((tstate->interp->eval_frame == NULL) && + (Py_TYPE(receiver) == &PyGen_Type || Py_TYPE(receiver) == &PyCoro_Type) && + ((PyGenObject *)receiver)->gi_frame_state < FRAME_EXECUTING) + { + PyGenObject *gen = (PyGenObject *)receiver; + _PyInterpreterFrame *gen_frame = (_PyInterpreterFrame *)gen->gi_iframe; + STACK_SHRINK(1); + _PyFrame_StackPush(gen_frame, v); + gen->gi_frame_state = FRAME_EXECUTING; + gen->gi_exc_state.previous_item = tstate->exc_info; + tstate->exc_info = &gen->gi_exc_state; + assert(next_instr - this_instr + oparg <= UINT16_MAX); + frame->return_offset = (uint16_t)(next_instr - this_instr + oparg); + DISPATCH_INLINED(gen_frame); + } + if (Py_IsNone(v) && PyIter_Check(receiver)) { + retval = Py_TYPE(receiver)->tp_iternext(receiver); } else { - int err = _Py_call_instrumentation_2args( - tstate, PY_MONITORING_EVENT_C_RETURN, - frame, next_instr-1, callable, arg); - if (err < 0) { - Py_CLEAR(res); + retval = PyObject_CallMethodOneArg(receiver, &_Py_ID(send), v); + } + if (retval == NULL) { + if (_PyErr_ExceptionMatches(tstate, PyExc_StopIteration) + ) { + monitor_raise(tstate, frame, this_instr); + } + if (_PyGen_FetchStopIterationValue(&retval) == 0) { + assert(retval != NULL); + JUMPBY(oparg); + } + else { + GOTO_ERROR(error); } } + Py_DECREF(v); } - kwnames = NULL; - assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); - Py_DECREF(callable); - for (int i = 0; i < total_args; i++) { - Py_DECREF(args[i]); - } - if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; } - STACK_SHRINK(oparg); - STACK_SHRINK(1); - stack_pointer[-1] = res; - next_instr += 3; - CHECK_EVAL_BREAKER(); + stack_pointer[-1] = retval; DISPATCH(); } - TARGET(CALL_BOUND_METHOD_EXACT_ARGS) { - PyObject *callable; - PyObject *method; - callable = stack_pointer[-1 - oparg]; - method = stack_pointer[-2 - oparg]; - DEOPT_IF(method != NULL, CALL); - DEOPT_IF(Py_TYPE(callable) != &PyMethod_Type, CALL); - STAT_INC(CALL, hit); - PyObject *self = ((PyMethodObject *)callable)->im_self; - PEEK(oparg + 1) = Py_NewRef(self); // callable - PyObject *meth = ((PyMethodObject *)callable)->im_func; - PEEK(oparg + 2) = Py_NewRef(meth); // method - Py_DECREF(callable); - GO_TO_INSTRUCTION(CALL_PY_EXACT_ARGS); - STACK_SHRINK(oparg); - STACK_SHRINK(1); - } - - TARGET(CALL_PY_EXACT_ARGS) { - PREDICTED(CALL_PY_EXACT_ARGS); - PyObject **args; - PyObject *callable; - PyObject *method; - args = stack_pointer - oparg; - callable = stack_pointer[-1 - oparg]; - method = stack_pointer[-2 - oparg]; - uint32_t func_version = read_u32(&next_instr[1].cache); - ASSERT_KWNAMES_IS_NULL(); - DEOPT_IF(tstate->interp->eval_frame, CALL); - int is_meth = method != NULL; - int argcount = oparg; - if (is_meth) { - callable = method; - args--; - argcount++; - } - DEOPT_IF(!PyFunction_Check(callable), CALL); - PyFunctionObject *func = (PyFunctionObject *)callable; - DEOPT_IF(func->func_version != func_version, CALL); - PyCodeObject *code = (PyCodeObject *)func->func_code; - DEOPT_IF(code->co_argcount != argcount, CALL); - DEOPT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize), CALL); - STAT_INC(CALL, hit); - _PyInterpreterFrame *new_frame = _PyFrame_PushUnchecked(tstate, func, argcount); - for (int i = 0; i < argcount; i++) { - new_frame->localsplus[i] = args[i]; - } - // Manipulate stack directly since we leave using DISPATCH_INLINED(). - STACK_SHRINK(oparg + 2); - SKIP_OVER(INLINE_CACHE_ENTRIES_CALL); - frame->return_offset = 0; - DISPATCH_INLINED(new_frame); - STACK_SHRINK(oparg); + TARGET(SEND_GEN) { + _Py_CODEUNIT *this_instr = frame->instr_ptr = next_instr; + next_instr += 2; + INSTRUCTION_STATS(SEND_GEN); + static_assert(INLINE_CACHE_ENTRIES_SEND == 1, "incorrect cache size"); + PyObject *v; + PyObject *receiver; + /* Skip 1 cache entry */ + v = stack_pointer[-1]; + receiver = stack_pointer[-2]; + DEOPT_IF(tstate->interp->eval_frame, SEND); + PyGenObject *gen = (PyGenObject *)receiver; + DEOPT_IF(Py_TYPE(gen) != &PyGen_Type && Py_TYPE(gen) != &PyCoro_Type, SEND); + DEOPT_IF(gen->gi_frame_state >= FRAME_EXECUTING, SEND); + STAT_INC(SEND, hit); + _PyInterpreterFrame *gen_frame = (_PyInterpreterFrame *)gen->gi_iframe; STACK_SHRINK(1); + _PyFrame_StackPush(gen_frame, v); + gen->gi_frame_state = FRAME_EXECUTING; + gen->gi_exc_state.previous_item = tstate->exc_info; + tstate->exc_info = &gen->gi_exc_state; + assert(next_instr - this_instr + oparg <= UINT16_MAX); + frame->return_offset = (uint16_t)(next_instr - this_instr + oparg); + DISPATCH_INLINED(gen_frame); } - TARGET(CALL_PY_WITH_DEFAULTS) { - PyObject **args; - PyObject *callable; - PyObject *method; - args = stack_pointer - oparg; - callable = stack_pointer[-1 - oparg]; - method = stack_pointer[-2 - oparg]; - uint32_t func_version = read_u32(&next_instr[1].cache); - ASSERT_KWNAMES_IS_NULL(); - DEOPT_IF(tstate->interp->eval_frame, CALL); - int is_meth = method != NULL; - int argcount = oparg; - if (is_meth) { - callable = method; - args--; - argcount++; - } - DEOPT_IF(!PyFunction_Check(callable), CALL); - PyFunctionObject *func = (PyFunctionObject *)callable; - DEOPT_IF(func->func_version != func_version, CALL); - PyCodeObject *code = (PyCodeObject *)func->func_code; - assert(func->func_defaults); - assert(PyTuple_CheckExact(func->func_defaults)); - int defcount = (int)PyTuple_GET_SIZE(func->func_defaults); - assert(defcount <= code->co_argcount); - int min_args = code->co_argcount - defcount; - DEOPT_IF(argcount > code->co_argcount, CALL); - DEOPT_IF(argcount < min_args, CALL); - DEOPT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize), CALL); - STAT_INC(CALL, hit); - _PyInterpreterFrame *new_frame = _PyFrame_PushUnchecked(tstate, func, code->co_argcount); - for (int i = 0; i < argcount; i++) { - new_frame->localsplus[i] = args[i]; - } - for (int i = argcount; i < code->co_argcount; i++) { - PyObject *def = PyTuple_GET_ITEM(func->func_defaults, i - min_args); - new_frame->localsplus[i] = Py_NewRef(def); + TARGET(SETUP_ANNOTATIONS) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(SETUP_ANNOTATIONS); + int err; + PyObject *ann_dict; + if (LOCALS() == NULL) { + _PyErr_Format(tstate, PyExc_SystemError, + "no locals found when setting up annotations"); + if (true) goto error; + } + /* check if __annotations__ in locals()... */ + if (PyMapping_GetOptionalItem(LOCALS(), &_Py_ID(__annotations__), &ann_dict) < 0) goto error; + if (ann_dict == NULL) { + ann_dict = PyDict_New(); + if (ann_dict == NULL) goto error; + err = PyObject_SetItem(LOCALS(), &_Py_ID(__annotations__), + ann_dict); + Py_DECREF(ann_dict); + if (err) goto error; + } + else { + Py_DECREF(ann_dict); } - // Manipulate stack and cache directly since we leave using DISPATCH_INLINED(). - STACK_SHRINK(oparg + 2); - SKIP_OVER(INLINE_CACHE_ENTRIES_CALL); - frame->return_offset = 0; - DISPATCH_INLINED(new_frame); - STACK_SHRINK(oparg); - STACK_SHRINK(1); - } - - TARGET(CALL_NO_KW_TYPE_1) { - PyObject **args; - PyObject *callable; - PyObject *null; - PyObject *res; - args = stack_pointer - oparg; - callable = stack_pointer[-1 - oparg]; - null = stack_pointer[-2 - oparg]; - ASSERT_KWNAMES_IS_NULL(); - assert(oparg == 1); - DEOPT_IF(null != NULL, CALL); - PyObject *obj = args[0]; - DEOPT_IF(callable != (PyObject *)&PyType_Type, CALL); - STAT_INC(CALL, hit); - res = Py_NewRef(Py_TYPE(obj)); - Py_DECREF(obj); - Py_DECREF(&PyType_Type); // I.e., callable - STACK_SHRINK(oparg); - STACK_SHRINK(1); - stack_pointer[-1] = res; - next_instr += 3; DISPATCH(); } - TARGET(CALL_NO_KW_STR_1) { - PyObject **args; - PyObject *callable; - PyObject *null; - PyObject *res; - args = stack_pointer - oparg; - callable = stack_pointer[-1 - oparg]; - null = stack_pointer[-2 - oparg]; - ASSERT_KWNAMES_IS_NULL(); - assert(oparg == 1); - DEOPT_IF(null != NULL, CALL); - DEOPT_IF(callable != (PyObject *)&PyUnicode_Type, CALL); - STAT_INC(CALL, hit); - PyObject *arg = args[0]; - res = PyObject_Str(arg); - Py_DECREF(arg); - Py_DECREF(&PyUnicode_Type); // I.e., callable - if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; } - STACK_SHRINK(oparg); - STACK_SHRINK(1); - stack_pointer[-1] = res; - next_instr += 3; - CHECK_EVAL_BREAKER(); + TARGET(SET_ADD) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(SET_ADD); + PyObject *v; + PyObject *set; + v = stack_pointer[-1]; + set = stack_pointer[-2 - (oparg-1)]; + int err = PySet_Add(set, v); + Py_DECREF(v); + if (err) goto pop_1_error; + stack_pointer += -1; DISPATCH(); } - TARGET(CALL_NO_KW_TUPLE_1) { - PyObject **args; - PyObject *callable; - PyObject *null; - PyObject *res; - args = stack_pointer - oparg; - callable = stack_pointer[-1 - oparg]; - null = stack_pointer[-2 - oparg]; - ASSERT_KWNAMES_IS_NULL(); - assert(oparg == 1); - DEOPT_IF(null != NULL, CALL); - DEOPT_IF(callable != (PyObject *)&PyTuple_Type, CALL); - STAT_INC(CALL, hit); - PyObject *arg = args[0]; - res = PySequence_Tuple(arg); - Py_DECREF(arg); - Py_DECREF(&PyTuple_Type); // I.e., tuple - if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; } - STACK_SHRINK(oparg); - STACK_SHRINK(1); - stack_pointer[-1] = res; - next_instr += 3; - CHECK_EVAL_BREAKER(); + TARGET(SET_FUNCTION_ATTRIBUTE) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(SET_FUNCTION_ATTRIBUTE); + PyObject *func; + PyObject *attr; + func = stack_pointer[-1]; + attr = stack_pointer[-2]; + assert(PyFunction_Check(func)); + PyFunctionObject *func_obj = (PyFunctionObject *)func; + switch(oparg) { + case MAKE_FUNCTION_CLOSURE: + assert(func_obj->func_closure == NULL); + func_obj->func_closure = attr; + break; + case MAKE_FUNCTION_ANNOTATIONS: + assert(func_obj->func_annotations == NULL); + func_obj->func_annotations = attr; + break; + case MAKE_FUNCTION_KWDEFAULTS: + assert(PyDict_CheckExact(attr)); + assert(func_obj->func_kwdefaults == NULL); + func_obj->func_kwdefaults = attr; + break; + case MAKE_FUNCTION_DEFAULTS: + assert(PyTuple_CheckExact(attr)); + assert(func_obj->func_defaults == NULL); + func_obj->func_defaults = attr; + break; + default: + Py_UNREACHABLE(); + } + stack_pointer[-2] = func; + stack_pointer += -1; DISPATCH(); } - TARGET(CALL_NO_KW_ALLOC_AND_ENTER_INIT) { - PyObject **args; - PyObject *callable; - PyObject *null; - args = stack_pointer - oparg; - callable = stack_pointer[-1 - oparg]; - null = stack_pointer[-2 - oparg]; - /* This instruction does the following: - * 1. Creates the object (by calling ``object.__new__``) - * 2. Pushes a shim frame to the frame stack (to cleanup after ``__init__``) - * 3. Pushes the frame for ``__init__`` to the frame stack - * */ - ASSERT_KWNAMES_IS_NULL(); - _PyCallCache *cache = (_PyCallCache *)next_instr; - DEOPT_IF(null != NULL, CALL); - DEOPT_IF(!PyType_Check(callable), CALL); - PyTypeObject *tp = (PyTypeObject *)callable; - DEOPT_IF(tp->tp_version_tag != read_u32(cache->func_version), CALL); - PyHeapTypeObject *cls = (PyHeapTypeObject *)callable; - PyFunctionObject *init = (PyFunctionObject *)cls->_spec_cache.init; - PyCodeObject *code = (PyCodeObject *)init->func_code; - DEOPT_IF(code->co_argcount != oparg+1, CALL); - DEOPT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize + _Py_InitCleanup.co_framesize), CALL); - STAT_INC(CALL, hit); - PyObject *self = _PyType_NewManagedObject(tp); - if (self == NULL) { - goto error; + TARGET(SET_UPDATE) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(SET_UPDATE); + PyObject *iterable; + PyObject *set; + iterable = stack_pointer[-1]; + set = stack_pointer[-2 - (oparg-1)]; + int err = _PySet_Update(set, iterable); + Py_DECREF(iterable); + if (err < 0) goto pop_1_error; + stack_pointer += -1; + DISPATCH(); + } + + TARGET(STORE_ATTR) { + frame->instr_ptr = next_instr; + next_instr += 5; + INSTRUCTION_STATS(STORE_ATTR); + PREDICTED(STORE_ATTR); + _Py_CODEUNIT *this_instr = next_instr - 5; + PyObject *owner; + PyObject *v; + // _SPECIALIZE_STORE_ATTR + owner = stack_pointer[-1]; + { + uint16_t counter = read_u16(&this_instr[1].cache); + TIER_ONE_ONLY + #if ENABLE_SPECIALIZATION + if (ADAPTIVE_COUNTER_IS_ZERO(counter)) { + PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); + next_instr = this_instr; + _Py_Specialize_StoreAttr(owner, next_instr, name); + DISPATCH_SAME_OPARG(); + } + STAT_INC(STORE_ATTR, deferred); + DECREMENT_ADAPTIVE_COUNTER(this_instr[1].cache); + #endif /* ENABLE_SPECIALIZATION */ } - Py_DECREF(tp); - _PyInterpreterFrame *shim = _PyFrame_PushTrampolineUnchecked( - tstate, (PyCodeObject *)&_Py_InitCleanup, 1, 0); - assert(_PyCode_CODE((PyCodeObject *)shim->f_executable)[1].op.code == EXIT_INIT_CHECK); - /* Push self onto stack of shim */ - Py_INCREF(self); - shim->localsplus[0] = self; - Py_INCREF(init); - _PyInterpreterFrame *init_frame = _PyFrame_PushUnchecked(tstate, init, oparg+1); - /* Copy self followed by args to __init__ frame */ - init_frame->localsplus[0] = self; - for (int i = 0; i < oparg; i++) { - init_frame->localsplus[i+1] = args[i]; + /* Skip 3 cache entries */ + // _STORE_ATTR + v = stack_pointer[-2]; + { + PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); + int err = PyObject_SetAttr(owner, name, v); + Py_DECREF(v); + Py_DECREF(owner); + if (err) goto pop_2_error; } - SKIP_OVER(INLINE_CACHE_ENTRIES_CALL); - frame->prev_instr = next_instr - 1; - frame->return_offset = 0; - STACK_SHRINK(oparg+2); - _PyFrame_SetStackPointer(frame, stack_pointer); - /* Link frames */ - init_frame->previous = shim; - shim->previous = frame; - frame = cframe.current_frame = init_frame; - CALL_STAT_INC(inlined_py_calls); - /* Account for pushing the extra frame. - * We don't check recursion depth here, - * as it will be checked after start_frame */ - tstate->py_recursion_remaining--; - goto start_frame; - STACK_SHRINK(oparg); - STACK_SHRINK(1); + stack_pointer += -2; + DISPATCH(); } - TARGET(EXIT_INIT_CHECK) { - PyObject *should_be_none; - should_be_none = stack_pointer[-1]; - assert(STACK_LEVEL() == 2); - if (should_be_none != Py_None) { - PyErr_Format(PyExc_TypeError, - "__init__() should return None, not '%.200s'", - Py_TYPE(should_be_none)->tp_name); - goto error; + TARGET(STORE_ATTR_INSTANCE_VALUE) { + _Py_CODEUNIT *this_instr = frame->instr_ptr = next_instr; + next_instr += 5; + INSTRUCTION_STATS(STORE_ATTR_INSTANCE_VALUE); + static_assert(INLINE_CACHE_ENTRIES_STORE_ATTR == 4, "incorrect cache size"); + PyObject *owner; + PyObject *value; + /* Skip 1 cache entry */ + // _GUARD_TYPE_VERSION + owner = stack_pointer[-1]; + { + uint32_t type_version = read_u32(&this_instr[2].cache); + PyTypeObject *tp = Py_TYPE(owner); + assert(type_version != 0); + DEOPT_IF(tp->tp_version_tag != type_version, STORE_ATTR); } - STACK_SHRINK(1); + // _GUARD_DORV_VALUES + { + assert(Py_TYPE(owner)->tp_flags & Py_TPFLAGS_MANAGED_DICT); + PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner); + DEOPT_IF(!_PyDictOrValues_IsValues(dorv), STORE_ATTR); + } + // _STORE_ATTR_INSTANCE_VALUE + value = stack_pointer[-2]; + { + uint16_t index = read_u16(&this_instr[4].cache); + PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner); + STAT_INC(STORE_ATTR, hit); + PyDictValues *values = _PyDictOrValues_GetValues(dorv); + PyObject *old_value = values->values[index]; + values->values[index] = value; + if (old_value == NULL) { + _PyDictValues_AddToInsertionOrder(values, index); + } + else { + Py_DECREF(old_value); + } + Py_DECREF(owner); + } + stack_pointer += -2; DISPATCH(); } - TARGET(CALL_BUILTIN_CLASS) { - PyObject **args; - PyObject *callable; - PyObject *method; - PyObject *res; - args = stack_pointer - oparg; - callable = stack_pointer[-1 - oparg]; - method = stack_pointer[-2 - oparg]; - int is_meth = method != NULL; - int total_args = oparg; - if (is_meth) { - callable = method; - args--; - total_args++; + TARGET(STORE_ATTR_SLOT) { + _Py_CODEUNIT *this_instr = frame->instr_ptr = next_instr; + next_instr += 5; + INSTRUCTION_STATS(STORE_ATTR_SLOT); + static_assert(INLINE_CACHE_ENTRIES_STORE_ATTR == 4, "incorrect cache size"); + PyObject *owner; + PyObject *value; + /* Skip 1 cache entry */ + // _GUARD_TYPE_VERSION + owner = stack_pointer[-1]; + { + uint32_t type_version = read_u32(&this_instr[2].cache); + PyTypeObject *tp = Py_TYPE(owner); + assert(type_version != 0); + DEOPT_IF(tp->tp_version_tag != type_version, STORE_ATTR); } - int kwnames_len = KWNAMES_LEN(); - DEOPT_IF(!PyType_Check(callable), CALL); - PyTypeObject *tp = (PyTypeObject *)callable; - DEOPT_IF(tp->tp_vectorcall == NULL, CALL); - STAT_INC(CALL, hit); - res = tp->tp_vectorcall((PyObject *)tp, args, - total_args - kwnames_len, kwnames); - kwnames = NULL; - /* Free the arguments. */ - for (int i = 0; i < total_args; i++) { - Py_DECREF(args[i]); + // _STORE_ATTR_SLOT + value = stack_pointer[-2]; + { + uint16_t index = read_u16(&this_instr[4].cache); + char *addr = (char *)owner + index; + STAT_INC(STORE_ATTR, hit); + PyObject *old_value = *(PyObject **)addr; + *(PyObject **)addr = value; + Py_XDECREF(old_value); + Py_DECREF(owner); } - Py_DECREF(tp); - if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; } - STACK_SHRINK(oparg); - STACK_SHRINK(1); - stack_pointer[-1] = res; - next_instr += 3; - CHECK_EVAL_BREAKER(); + stack_pointer += -2; DISPATCH(); } - TARGET(CALL_NO_KW_BUILTIN_O) { - PyObject **args; - PyObject *callable; - PyObject *method; - PyObject *res; - args = stack_pointer - oparg; - callable = stack_pointer[-1 - oparg]; - method = stack_pointer[-2 - oparg]; - /* Builtin METH_O functions */ - ASSERT_KWNAMES_IS_NULL(); - int is_meth = method != NULL; - int total_args = oparg; - if (is_meth) { - callable = method; - args--; - total_args++; + TARGET(STORE_ATTR_WITH_HINT) { + _Py_CODEUNIT *this_instr = frame->instr_ptr = next_instr; + next_instr += 5; + INSTRUCTION_STATS(STORE_ATTR_WITH_HINT); + static_assert(INLINE_CACHE_ENTRIES_STORE_ATTR == 4, "incorrect cache size"); + PyObject *owner; + PyObject *value; + /* Skip 1 cache entry */ + owner = stack_pointer[-1]; + value = stack_pointer[-2]; + uint32_t type_version = read_u32(&this_instr[2].cache); + uint16_t hint = read_u16(&this_instr[4].cache); + PyTypeObject *tp = Py_TYPE(owner); + assert(type_version != 0); + DEOPT_IF(tp->tp_version_tag != type_version, STORE_ATTR); + assert(tp->tp_flags & Py_TPFLAGS_MANAGED_DICT); + PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner); + DEOPT_IF(_PyDictOrValues_IsValues(dorv), STORE_ATTR); + PyDictObject *dict = (PyDictObject *)_PyDictOrValues_GetDict(dorv); + DEOPT_IF(dict == NULL, STORE_ATTR); + assert(PyDict_CheckExact((PyObject *)dict)); + PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); + DEOPT_IF(hint >= (size_t)dict->ma_keys->dk_nentries, STORE_ATTR); + PyObject *old_value; + uint64_t new_version; + if (DK_IS_UNICODE(dict->ma_keys)) { + PyDictUnicodeEntry *ep = DK_UNICODE_ENTRIES(dict->ma_keys) + hint; + DEOPT_IF(ep->me_key != name, STORE_ATTR); + old_value = ep->me_value; + DEOPT_IF(old_value == NULL, STORE_ATTR); + new_version = _PyDict_NotifyEvent(tstate->interp, PyDict_EVENT_MODIFIED, dict, name, value); + ep->me_value = value; } - DEOPT_IF(total_args != 1, CALL); - DEOPT_IF(!PyCFunction_CheckExact(callable), CALL); - DEOPT_IF(PyCFunction_GET_FLAGS(callable) != METH_O, CALL); - STAT_INC(CALL, hit); - PyCFunction cfunc = PyCFunction_GET_FUNCTION(callable); - // This is slower but CPython promises to check all non-vectorcall - // function calls. - if (_Py_EnterRecursiveCallTstate(tstate, " while calling a Python object")) { - goto error; + else { + PyDictKeyEntry *ep = DK_ENTRIES(dict->ma_keys) + hint; + DEOPT_IF(ep->me_key != name, STORE_ATTR); + old_value = ep->me_value; + DEOPT_IF(old_value == NULL, STORE_ATTR); + new_version = _PyDict_NotifyEvent(tstate->interp, PyDict_EVENT_MODIFIED, dict, name, value); + ep->me_value = value; } - PyObject *arg = args[0]; - res = _PyCFunction_TrampolineCall(cfunc, PyCFunction_GET_SELF(callable), arg); - _Py_LeaveRecursiveCallTstate(tstate); - assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); + Py_DECREF(old_value); + STAT_INC(STORE_ATTR, hit); + /* Ensure dict is GC tracked if it needs to be */ + if (!_PyObject_GC_IS_TRACKED(dict) && _PyObject_GC_MAY_BE_TRACKED(value)) { + _PyObject_GC_TRACK(dict); + } + /* PEP 509 */ + dict->ma_version_tag = new_version; + Py_DECREF(owner); + stack_pointer += -2; + DISPATCH(); + } + + TARGET(STORE_DEREF) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(STORE_DEREF); + PyObject *v; + v = stack_pointer[-1]; + PyObject *cell = GETLOCAL(oparg); + PyObject *oldobj = PyCell_GET(cell); + PyCell_SET(cell, v); + Py_XDECREF(oldobj); + stack_pointer += -1; + DISPATCH(); + } - Py_DECREF(arg); - Py_DECREF(callable); - if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; } - STACK_SHRINK(oparg); - STACK_SHRINK(1); - stack_pointer[-1] = res; - next_instr += 3; - CHECK_EVAL_BREAKER(); + TARGET(STORE_FAST) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(STORE_FAST); + PyObject *value; + value = stack_pointer[-1]; + SETLOCAL(oparg, value); + stack_pointer += -1; DISPATCH(); } - TARGET(CALL_NO_KW_BUILTIN_FAST) { - PyObject **args; - PyObject *callable; - PyObject *method; - PyObject *res; - args = stack_pointer - oparg; - callable = stack_pointer[-1 - oparg]; - method = stack_pointer[-2 - oparg]; - /* Builtin METH_FASTCALL functions, without keywords */ - ASSERT_KWNAMES_IS_NULL(); - int is_meth = method != NULL; - int total_args = oparg; - if (is_meth) { - callable = method; - args--; - total_args++; - } - DEOPT_IF(!PyCFunction_CheckExact(callable), CALL); - DEOPT_IF(PyCFunction_GET_FLAGS(callable) != METH_FASTCALL, CALL); - STAT_INC(CALL, hit); - PyCFunction cfunc = PyCFunction_GET_FUNCTION(callable); - /* res = func(self, args, nargs) */ - res = ((_PyCFunctionFast)(void(*)(void))cfunc)( - PyCFunction_GET_SELF(callable), - args, - total_args); - assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); + TARGET(STORE_FAST_LOAD_FAST) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(STORE_FAST_LOAD_FAST); + PyObject *value1; + PyObject *value2; + value1 = stack_pointer[-1]; + uint32_t oparg1 = oparg >> 4; + uint32_t oparg2 = oparg & 15; + SETLOCAL(oparg1, value1); + value2 = GETLOCAL(oparg2); + Py_INCREF(value2); + stack_pointer[-1] = value2; + DISPATCH(); + } - /* Free the arguments. */ - for (int i = 0; i < total_args; i++) { - Py_DECREF(args[i]); - } - Py_DECREF(callable); - if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; } - /* Not deopting because this doesn't mean our optimization was - wrong. `res` can be NULL for valid reasons. Eg. getattr(x, - 'invalid'). In those cases an exception is set, so we must - handle it. - */ - STACK_SHRINK(oparg); - STACK_SHRINK(1); - stack_pointer[-1] = res; - next_instr += 3; - CHECK_EVAL_BREAKER(); + TARGET(STORE_FAST_STORE_FAST) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(STORE_FAST_STORE_FAST); + PyObject *value1; + PyObject *value2; + value1 = stack_pointer[-1]; + value2 = stack_pointer[-2]; + uint32_t oparg1 = oparg >> 4; + uint32_t oparg2 = oparg & 15; + SETLOCAL(oparg1, value1); + SETLOCAL(oparg2, value2); + stack_pointer += -2; DISPATCH(); } - TARGET(CALL_BUILTIN_FAST_WITH_KEYWORDS) { - PyObject **args; - PyObject *callable; - PyObject *method; - PyObject *res; - args = stack_pointer - oparg; - callable = stack_pointer[-1 - oparg]; - method = stack_pointer[-2 - oparg]; - /* Builtin METH_FASTCALL | METH_KEYWORDS functions */ - int is_meth = method != NULL; - int total_args = oparg; - if (is_meth) { - callable = method; - args--; - total_args++; - } - DEOPT_IF(!PyCFunction_CheckExact(callable), CALL); - DEOPT_IF(PyCFunction_GET_FLAGS(callable) != - (METH_FASTCALL | METH_KEYWORDS), CALL); - STAT_INC(CALL, hit); - /* res = func(self, args, nargs, kwnames) */ - _PyCFunctionFastWithKeywords cfunc = - (_PyCFunctionFastWithKeywords)(void(*)(void)) - PyCFunction_GET_FUNCTION(callable); - res = cfunc( - PyCFunction_GET_SELF(callable), - args, - total_args - KWNAMES_LEN(), - kwnames - ); - assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); - kwnames = NULL; + TARGET(STORE_GLOBAL) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(STORE_GLOBAL); + PyObject *v; + v = stack_pointer[-1]; + PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); + int err = PyDict_SetItem(GLOBALS(), name, v); + Py_DECREF(v); + if (err) goto pop_1_error; + stack_pointer += -1; + DISPATCH(); + } - /* Free the arguments. */ - for (int i = 0; i < total_args; i++) { - Py_DECREF(args[i]); + TARGET(STORE_NAME) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(STORE_NAME); + PyObject *v; + v = stack_pointer[-1]; + PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); + PyObject *ns = LOCALS(); + int err; + if (ns == NULL) { + _PyErr_Format(tstate, PyExc_SystemError, + "no locals found when storing %R", name); + Py_DECREF(v); + if (true) goto pop_1_error; } - Py_DECREF(callable); - if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; } - STACK_SHRINK(oparg); - STACK_SHRINK(1); - stack_pointer[-1] = res; - next_instr += 3; - CHECK_EVAL_BREAKER(); + if (PyDict_CheckExact(ns)) + err = PyDict_SetItem(ns, name, v); + else + err = PyObject_SetItem(ns, name, v); + Py_DECREF(v); + if (err) goto pop_1_error; + stack_pointer += -1; DISPATCH(); } - TARGET(CALL_NO_KW_LEN) { - PyObject **args; - PyObject *callable; - PyObject *method; - PyObject *res; - args = stack_pointer - oparg; - callable = stack_pointer[-1 - oparg]; - method = stack_pointer[-2 - oparg]; - ASSERT_KWNAMES_IS_NULL(); - /* len(o) */ - int is_meth = method != NULL; - int total_args = oparg; - if (is_meth) { - callable = method; - args--; - total_args++; + TARGET(STORE_SLICE) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(STORE_SLICE); + PyObject *stop; + PyObject *start; + PyObject *container; + PyObject *v; + stop = stack_pointer[-1]; + start = stack_pointer[-2]; + container = stack_pointer[-3]; + v = stack_pointer[-4]; + PyObject *slice = _PyBuildSlice_ConsumeRefs(start, stop); + int err; + if (slice == NULL) { + err = 1; } - DEOPT_IF(total_args != 1, CALL); - PyInterpreterState *interp = tstate->interp; - DEOPT_IF(callable != interp->callable_cache.len, CALL); - STAT_INC(CALL, hit); - PyObject *arg = args[0]; - Py_ssize_t len_i = PyObject_Length(arg); - if (len_i < 0) { - goto error; + else { + err = PyObject_SetItem(container, slice, v); + Py_DECREF(slice); } - res = PyLong_FromSsize_t(len_i); - assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); - - Py_DECREF(callable); - Py_DECREF(arg); - if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; } - STACK_SHRINK(oparg); - STACK_SHRINK(1); - stack_pointer[-1] = res; - next_instr += 3; + Py_DECREF(v); + Py_DECREF(container); + if (err) goto pop_4_error; + stack_pointer += -4; DISPATCH(); } - TARGET(CALL_NO_KW_ISINSTANCE) { - PyObject **args; - PyObject *callable; - PyObject *method; - PyObject *res; - args = stack_pointer - oparg; - callable = stack_pointer[-1 - oparg]; - method = stack_pointer[-2 - oparg]; - ASSERT_KWNAMES_IS_NULL(); - /* isinstance(o, o2) */ - int is_meth = method != NULL; - int total_args = oparg; - if (is_meth) { - callable = method; - args--; - total_args++; + TARGET(STORE_SUBSCR) { + frame->instr_ptr = next_instr; + next_instr += 2; + INSTRUCTION_STATS(STORE_SUBSCR); + PREDICTED(STORE_SUBSCR); + _Py_CODEUNIT *this_instr = next_instr - 2; + PyObject *sub; + PyObject *container; + PyObject *v; + // _SPECIALIZE_STORE_SUBSCR + sub = stack_pointer[-1]; + container = stack_pointer[-2]; + { + uint16_t counter = read_u16(&this_instr[1].cache); + TIER_ONE_ONLY + #if ENABLE_SPECIALIZATION + if (ADAPTIVE_COUNTER_IS_ZERO(counter)) { + next_instr = this_instr; + _Py_Specialize_StoreSubscr(container, sub, next_instr); + DISPATCH_SAME_OPARG(); + } + STAT_INC(STORE_SUBSCR, deferred); + DECREMENT_ADAPTIVE_COUNTER(this_instr[1].cache); + #endif /* ENABLE_SPECIALIZATION */ } - DEOPT_IF(total_args != 2, CALL); - PyInterpreterState *interp = tstate->interp; - DEOPT_IF(callable != interp->callable_cache.isinstance, CALL); - STAT_INC(CALL, hit); - PyObject *cls = args[1]; - PyObject *inst = args[0]; - int retval = PyObject_IsInstance(inst, cls); - if (retval < 0) { - goto error; + // _STORE_SUBSCR + v = stack_pointer[-3]; + { + /* container[sub] = v */ + int err = PyObject_SetItem(container, sub, v); + Py_DECREF(v); + Py_DECREF(container); + Py_DECREF(sub); + if (err) goto pop_3_error; } - res = PyBool_FromLong(retval); - assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); - - Py_DECREF(inst); - Py_DECREF(cls); - Py_DECREF(callable); - if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; } - STACK_SHRINK(oparg); - STACK_SHRINK(1); - stack_pointer[-1] = res; - next_instr += 3; + stack_pointer += -3; DISPATCH(); } - TARGET(CALL_NO_KW_LIST_APPEND) { - PyObject **args; - PyObject *self; - PyObject *method; - args = stack_pointer - oparg; - self = stack_pointer[-1 - oparg]; - method = stack_pointer[-2 - oparg]; - ASSERT_KWNAMES_IS_NULL(); - assert(oparg == 1); - assert(method != NULL); - PyInterpreterState *interp = tstate->interp; - DEOPT_IF(method != interp->callable_cache.list_append, CALL); - DEOPT_IF(!PyList_Check(self), CALL); - STAT_INC(CALL, hit); - if (_PyList_AppendTakeRef((PyListObject *)self, args[0]) < 0) { - goto pop_1_error; // Since arg is DECREF'ed already - } - Py_DECREF(self); - Py_DECREF(method); - STACK_SHRINK(3); - // CALL + POP_TOP - SKIP_OVER(INLINE_CACHE_ENTRIES_CALL + 1); - assert(next_instr[-1].op.code == POP_TOP); + TARGET(STORE_SUBSCR_DICT) { + frame->instr_ptr = next_instr; + next_instr += 2; + INSTRUCTION_STATS(STORE_SUBSCR_DICT); + static_assert(INLINE_CACHE_ENTRIES_STORE_SUBSCR == 1, "incorrect cache size"); + PyObject *sub; + PyObject *dict; + PyObject *value; + /* Skip 1 cache entry */ + sub = stack_pointer[-1]; + dict = stack_pointer[-2]; + value = stack_pointer[-3]; + DEOPT_IF(!PyDict_CheckExact(dict), STORE_SUBSCR); + STAT_INC(STORE_SUBSCR, hit); + int err = _PyDict_SetItem_Take2((PyDictObject *)dict, sub, value); + Py_DECREF(dict); + if (err) goto pop_3_error; + stack_pointer += -3; DISPATCH(); - STACK_SHRINK(oparg); - STACK_SHRINK(1); } - TARGET(CALL_NO_KW_METHOD_DESCRIPTOR_O) { - PyObject **args; - PyObject *method; - PyObject *res; - args = stack_pointer - oparg; - method = stack_pointer[-2 - oparg]; - ASSERT_KWNAMES_IS_NULL(); - int is_meth = method != NULL; - int total_args = oparg; - if (is_meth) { - args--; - total_args++; - } - PyMethodDescrObject *callable = - (PyMethodDescrObject *)PEEK(total_args + 1); - DEOPT_IF(total_args != 2, CALL); - DEOPT_IF(!Py_IS_TYPE(callable, &PyMethodDescr_Type), CALL); - PyMethodDef *meth = callable->d_method; - DEOPT_IF(meth->ml_flags != METH_O, CALL); - PyObject *arg = args[1]; - PyObject *self = args[0]; - DEOPT_IF(!Py_IS_TYPE(self, callable->d_common.d_type), CALL); - STAT_INC(CALL, hit); - PyCFunction cfunc = meth->ml_meth; - // This is slower but CPython promises to check all non-vectorcall - // function calls. - if (_Py_EnterRecursiveCallTstate(tstate, " while calling a Python object")) { - goto error; - } - res = _PyCFunction_TrampolineCall(cfunc, self, arg); - _Py_LeaveRecursiveCallTstate(tstate); - assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); - Py_DECREF(self); - Py_DECREF(arg); - Py_DECREF(callable); - if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; } - STACK_SHRINK(oparg); - STACK_SHRINK(1); - stack_pointer[-1] = res; - next_instr += 3; - CHECK_EVAL_BREAKER(); + TARGET(STORE_SUBSCR_LIST_INT) { + frame->instr_ptr = next_instr; + next_instr += 2; + INSTRUCTION_STATS(STORE_SUBSCR_LIST_INT); + static_assert(INLINE_CACHE_ENTRIES_STORE_SUBSCR == 1, "incorrect cache size"); + PyObject *sub; + PyObject *list; + PyObject *value; + /* Skip 1 cache entry */ + sub = stack_pointer[-1]; + list = stack_pointer[-2]; + value = stack_pointer[-3]; + DEOPT_IF(!PyLong_CheckExact(sub), STORE_SUBSCR); + DEOPT_IF(!PyList_CheckExact(list), STORE_SUBSCR); + // Ensure nonnegative, zero-or-one-digit ints. + DEOPT_IF(!_PyLong_IsNonNegativeCompact((PyLongObject *)sub), STORE_SUBSCR); + Py_ssize_t index = ((PyLongObject*)sub)->long_value.ob_digit[0]; + // Ensure index < len(list) + DEOPT_IF(index >= PyList_GET_SIZE(list), STORE_SUBSCR); + STAT_INC(STORE_SUBSCR, hit); + PyObject *old_value = PyList_GET_ITEM(list, index); + PyList_SET_ITEM(list, index, value); + assert(old_value != NULL); + Py_DECREF(old_value); + _Py_DECREF_SPECIALIZED(sub, (destructor)PyObject_Free); + Py_DECREF(list); + stack_pointer += -3; DISPATCH(); } - TARGET(CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS) { - PyObject **args; - PyObject *method; - PyObject *res; - args = stack_pointer - oparg; - method = stack_pointer[-2 - oparg]; - int is_meth = method != NULL; - int total_args = oparg; - if (is_meth) { - args--; - total_args++; - } - PyMethodDescrObject *callable = - (PyMethodDescrObject *)PEEK(total_args + 1); - DEOPT_IF(!Py_IS_TYPE(callable, &PyMethodDescr_Type), CALL); - PyMethodDef *meth = callable->d_method; - DEOPT_IF(meth->ml_flags != (METH_FASTCALL|METH_KEYWORDS), CALL); - PyTypeObject *d_type = callable->d_common.d_type; - PyObject *self = args[0]; - DEOPT_IF(!Py_IS_TYPE(self, d_type), CALL); - STAT_INC(CALL, hit); - int nargs = total_args - 1; - _PyCFunctionFastWithKeywords cfunc = - (_PyCFunctionFastWithKeywords)(void(*)(void))meth->ml_meth; - res = cfunc(self, args + 1, nargs - KWNAMES_LEN(), kwnames); - assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); - kwnames = NULL; - - /* Free the arguments. */ - for (int i = 0; i < total_args; i++) { - Py_DECREF(args[i]); - } - Py_DECREF(callable); - if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; } - STACK_SHRINK(oparg); - STACK_SHRINK(1); - stack_pointer[-1] = res; - next_instr += 3; - CHECK_EVAL_BREAKER(); + TARGET(SWAP) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(SWAP); + PyObject *top; + PyObject *bottom; + top = stack_pointer[-1]; + bottom = stack_pointer[-2 - (oparg-2)]; + assert(oparg >= 2); + stack_pointer[-2 - (oparg-2)] = top; + stack_pointer[-1] = bottom; DISPATCH(); } - TARGET(CALL_NO_KW_METHOD_DESCRIPTOR_NOARGS) { - PyObject **args; - PyObject *method; + TARGET(TO_BOOL) { + frame->instr_ptr = next_instr; + next_instr += 4; + INSTRUCTION_STATS(TO_BOOL); + PREDICTED(TO_BOOL); + _Py_CODEUNIT *this_instr = next_instr - 4; + PyObject *value; PyObject *res; - args = stack_pointer - oparg; - method = stack_pointer[-2 - oparg]; - ASSERT_KWNAMES_IS_NULL(); - assert(oparg == 0 || oparg == 1); - int is_meth = method != NULL; - int total_args = oparg; - if (is_meth) { - args--; - total_args++; + // _SPECIALIZE_TO_BOOL + value = stack_pointer[-1]; + { + uint16_t counter = read_u16(&this_instr[1].cache); + TIER_ONE_ONLY + #if ENABLE_SPECIALIZATION + if (ADAPTIVE_COUNTER_IS_ZERO(counter)) { + next_instr = this_instr; + _Py_Specialize_ToBool(value, next_instr); + DISPATCH_SAME_OPARG(); + } + STAT_INC(TO_BOOL, deferred); + DECREMENT_ADAPTIVE_COUNTER(this_instr[1].cache); + #endif /* ENABLE_SPECIALIZATION */ } - DEOPT_IF(total_args != 1, CALL); - PyMethodDescrObject *callable = (PyMethodDescrObject *)SECOND(); - DEOPT_IF(!Py_IS_TYPE(callable, &PyMethodDescr_Type), CALL); - PyMethodDef *meth = callable->d_method; - PyObject *self = args[0]; - DEOPT_IF(!Py_IS_TYPE(self, callable->d_common.d_type), CALL); - DEOPT_IF(meth->ml_flags != METH_NOARGS, CALL); - STAT_INC(CALL, hit); - PyCFunction cfunc = meth->ml_meth; - // This is slower but CPython promises to check all non-vectorcall - // function calls. - if (_Py_EnterRecursiveCallTstate(tstate, " while calling a Python object")) { - goto error; + /* Skip 2 cache entries */ + // _TO_BOOL + { + int err = PyObject_IsTrue(value); + Py_DECREF(value); + if (err < 0) goto pop_1_error; + res = err ? Py_True : Py_False; } - res = _PyCFunction_TrampolineCall(cfunc, self, NULL); - _Py_LeaveRecursiveCallTstate(tstate); - assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); - Py_DECREF(self); - Py_DECREF(callable); - if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; } - STACK_SHRINK(oparg); - STACK_SHRINK(1); stack_pointer[-1] = res; - next_instr += 3; - CHECK_EVAL_BREAKER(); DISPATCH(); } - TARGET(CALL_NO_KW_METHOD_DESCRIPTOR_FAST) { - PyObject **args; - PyObject *method; + TARGET(TO_BOOL_ALWAYS_TRUE) { + _Py_CODEUNIT *this_instr = frame->instr_ptr = next_instr; + next_instr += 4; + INSTRUCTION_STATS(TO_BOOL_ALWAYS_TRUE); + static_assert(INLINE_CACHE_ENTRIES_TO_BOOL == 3, "incorrect cache size"); + PyObject *value; PyObject *res; - args = stack_pointer - oparg; - method = stack_pointer[-2 - oparg]; - ASSERT_KWNAMES_IS_NULL(); - int is_meth = method != NULL; - int total_args = oparg; - if (is_meth) { - args--; - total_args++; - } - PyMethodDescrObject *callable = - (PyMethodDescrObject *)PEEK(total_args + 1); - /* Builtin METH_FASTCALL methods, without keywords */ - DEOPT_IF(!Py_IS_TYPE(callable, &PyMethodDescr_Type), CALL); - PyMethodDef *meth = callable->d_method; - DEOPT_IF(meth->ml_flags != METH_FASTCALL, CALL); - PyObject *self = args[0]; - DEOPT_IF(!Py_IS_TYPE(self, callable->d_common.d_type), CALL); - STAT_INC(CALL, hit); - _PyCFunctionFast cfunc = - (_PyCFunctionFast)(void(*)(void))meth->ml_meth; - int nargs = total_args - 1; - res = cfunc(self, args + 1, nargs); - assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); - /* Clear the stack of the arguments. */ - for (int i = 0; i < total_args; i++) { - Py_DECREF(args[i]); - } - Py_DECREF(callable); - if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; } - STACK_SHRINK(oparg); - STACK_SHRINK(1); + /* Skip 1 cache entry */ + value = stack_pointer[-1]; + uint32_t version = read_u32(&this_instr[2].cache); + // This one is a bit weird, because we expect *some* failures: + assert(version); + DEOPT_IF(Py_TYPE(value)->tp_version_tag != version, TO_BOOL); + STAT_INC(TO_BOOL, hit); + Py_DECREF(value); + res = Py_True; stack_pointer[-1] = res; - next_instr += 3; - CHECK_EVAL_BREAKER(); DISPATCH(); } - TARGET(INSTRUMENTED_CALL_FUNCTION_EX) { - GO_TO_INSTRUCTION(CALL_FUNCTION_EX); - } - - TARGET(CALL_FUNCTION_EX) { - PREDICTED(CALL_FUNCTION_EX); - PyObject *kwargs = NULL; - PyObject *callargs; - PyObject *func; - PyObject *result; - if (oparg & 1) { kwargs = stack_pointer[-(oparg & 1 ? 1 : 0)]; } - callargs = stack_pointer[-1 - (oparg & 1 ? 1 : 0)]; - func = stack_pointer[-2 - (oparg & 1 ? 1 : 0)]; - // DICT_MERGE is called before this opcode if there are kwargs. - // It converts all dict subtypes in kwargs into regular dicts. - assert(kwargs == NULL || PyDict_CheckExact(kwargs)); - if (!PyTuple_CheckExact(callargs)) { - if (check_args_iterable(tstate, func, callargs) < 0) { - goto error; - } - PyObject *tuple = PySequence_Tuple(callargs); - if (tuple == NULL) { - goto error; - } - Py_SETREF(callargs, tuple); - } - assert(PyTuple_CheckExact(callargs)); - EVAL_CALL_STAT_INC_IF_FUNCTION(EVAL_CALL_FUNCTION_EX, func); - if (opcode == INSTRUMENTED_CALL_FUNCTION_EX && - !PyFunction_Check(func) && !PyMethod_Check(func) - ) { - PyObject *arg = PyTuple_GET_SIZE(callargs) > 0 ? - PyTuple_GET_ITEM(callargs, 0) : Py_None; - int err = _Py_call_instrumentation_2args( - tstate, PY_MONITORING_EVENT_CALL, - frame, next_instr-1, func, arg); - if (err) goto error; - result = PyObject_Call(func, callargs, kwargs); - if (result == NULL) { - _Py_call_instrumentation_exc2( - tstate, PY_MONITORING_EVENT_C_RAISE, - frame, next_instr-1, func, arg); - } - else { - int err = _Py_call_instrumentation_2args( - tstate, PY_MONITORING_EVENT_C_RETURN, - frame, next_instr-1, func, arg); - if (err < 0) { - Py_CLEAR(result); - } - } - } - else { - if (Py_TYPE(func) == &PyFunction_Type && - tstate->interp->eval_frame == NULL && - ((PyFunctionObject *)func)->vectorcall == _PyFunction_Vectorcall) { - assert(PyTuple_CheckExact(callargs)); - Py_ssize_t nargs = PyTuple_GET_SIZE(callargs); - int code_flags = ((PyCodeObject *)PyFunction_GET_CODE(func))->co_flags; - PyObject *locals = code_flags & CO_OPTIMIZED ? NULL : Py_NewRef(PyFunction_GET_GLOBALS(func)); - - _PyInterpreterFrame *new_frame = _PyEvalFramePushAndInit_Ex(tstate, - (PyFunctionObject *)func, locals, - nargs, callargs, kwargs); - // Need to manually shrink the stack since we exit with DISPATCH_INLINED. - STACK_SHRINK(oparg + 3); - if (new_frame == NULL) { - goto error; - } - frame->return_offset = 0; - DISPATCH_INLINED(new_frame); - } - result = PyObject_Call(func, callargs, kwargs); - } - Py_DECREF(func); - Py_DECREF(callargs); - Py_XDECREF(kwargs); - assert(PEEK(3 + (oparg & 1)) == NULL); - if (result == NULL) { STACK_SHRINK(((oparg & 1) ? 1 : 0)); goto pop_3_error; } - STACK_SHRINK(((oparg & 1) ? 1 : 0)); - STACK_SHRINK(2); - stack_pointer[-1] = result; - CHECK_EVAL_BREAKER(); + TARGET(TO_BOOL_BOOL) { + frame->instr_ptr = next_instr; + next_instr += 4; + INSTRUCTION_STATS(TO_BOOL_BOOL); + static_assert(INLINE_CACHE_ENTRIES_TO_BOOL == 3, "incorrect cache size"); + PyObject *value; + /* Skip 1 cache entry */ + /* Skip 2 cache entries */ + value = stack_pointer[-1]; + DEOPT_IF(!PyBool_Check(value), TO_BOOL); + STAT_INC(TO_BOOL, hit); DISPATCH(); } - TARGET(MAKE_FUNCTION) { - PyObject *codeobj; - PyObject *func; - codeobj = stack_pointer[-1]; - - PyFunctionObject *func_obj = (PyFunctionObject *) - PyFunction_New(codeobj, GLOBALS()); - - Py_DECREF(codeobj); - if (func_obj == NULL) { - goto error; + TARGET(TO_BOOL_INT) { + frame->instr_ptr = next_instr; + next_instr += 4; + INSTRUCTION_STATS(TO_BOOL_INT); + static_assert(INLINE_CACHE_ENTRIES_TO_BOOL == 3, "incorrect cache size"); + PyObject *value; + PyObject *res; + /* Skip 1 cache entry */ + /* Skip 2 cache entries */ + value = stack_pointer[-1]; + DEOPT_IF(!PyLong_CheckExact(value), TO_BOOL); + STAT_INC(TO_BOOL, hit); + if (_PyLong_IsZero((PyLongObject *)value)) { + assert(_Py_IsImmortal(value)); + res = Py_False; } - - func_obj->func_version = ((PyCodeObject *)codeobj)->co_version; - func = (PyObject *)func_obj; - stack_pointer[-1] = func; - DISPATCH(); - } - - TARGET(SET_FUNCTION_ATTRIBUTE) { - PyObject *func; - PyObject *attr; - func = stack_pointer[-1]; - attr = stack_pointer[-2]; - assert(PyFunction_Check(func)); - PyFunctionObject *func_obj = (PyFunctionObject *)func; - switch(oparg) { - case MAKE_FUNCTION_CLOSURE: - assert(func_obj->func_closure == NULL); - func_obj->func_closure = attr; - break; - case MAKE_FUNCTION_ANNOTATIONS: - assert(func_obj->func_annotations == NULL); - func_obj->func_annotations = attr; - break; - case MAKE_FUNCTION_KWDEFAULTS: - assert(PyDict_CheckExact(attr)); - assert(func_obj->func_kwdefaults == NULL); - func_obj->func_kwdefaults = attr; - break; - case MAKE_FUNCTION_DEFAULTS: - assert(PyTuple_CheckExact(attr)); - assert(func_obj->func_defaults == NULL); - func_obj->func_defaults = attr; - break; - default: - Py_UNREACHABLE(); + else { + Py_DECREF(value); + res = Py_True; } - STACK_SHRINK(1); - stack_pointer[-1] = func; + stack_pointer[-1] = res; DISPATCH(); } - TARGET(RETURN_GENERATOR) { - assert(PyFunction_Check(frame->f_funcobj)); - PyFunctionObject *func = (PyFunctionObject *)frame->f_funcobj; - PyGenObject *gen = (PyGenObject *)_Py_MakeCoro(func); - if (gen == NULL) { - goto error; - } - assert(EMPTY()); - _PyFrame_SetStackPointer(frame, stack_pointer); - _PyInterpreterFrame *gen_frame = (_PyInterpreterFrame *)gen->gi_iframe; - _PyFrame_Copy(frame, gen_frame); - assert(frame->frame_obj == NULL); - gen->gi_frame_state = FRAME_CREATED; - gen_frame->owner = FRAME_OWNED_BY_GENERATOR; - _Py_LeaveRecursiveCallPy(tstate); - assert(frame != &entry_frame); - _PyInterpreterFrame *prev = frame->previous; - _PyThreadState_PopFrame(tstate, frame); - frame = cframe.current_frame = prev; - _PyFrame_StackPush(frame, (PyObject *)gen); - goto resume_frame; - } - - TARGET(BUILD_SLICE) { - PyObject *step = NULL; - PyObject *stop; - PyObject *start; - PyObject *slice; - if (oparg == 3) { step = stack_pointer[-(oparg == 3 ? 1 : 0)]; } - stop = stack_pointer[-1 - (oparg == 3 ? 1 : 0)]; - start = stack_pointer[-2 - (oparg == 3 ? 1 : 0)]; - slice = PySlice_New(start, stop, step); - Py_DECREF(start); - Py_DECREF(stop); - Py_XDECREF(step); - if (slice == NULL) { STACK_SHRINK(((oparg == 3) ? 1 : 0)); goto pop_2_error; } - STACK_SHRINK(((oparg == 3) ? 1 : 0)); - STACK_SHRINK(1); - stack_pointer[-1] = slice; + TARGET(TO_BOOL_LIST) { + frame->instr_ptr = next_instr; + next_instr += 4; + INSTRUCTION_STATS(TO_BOOL_LIST); + static_assert(INLINE_CACHE_ENTRIES_TO_BOOL == 3, "incorrect cache size"); + PyObject *value; + PyObject *res; + /* Skip 1 cache entry */ + /* Skip 2 cache entries */ + value = stack_pointer[-1]; + DEOPT_IF(!PyList_CheckExact(value), TO_BOOL); + STAT_INC(TO_BOOL, hit); + res = Py_SIZE(value) ? Py_True : Py_False; + Py_DECREF(value); + stack_pointer[-1] = res; DISPATCH(); } - TARGET(CONVERT_VALUE) { + TARGET(TO_BOOL_NONE) { + frame->instr_ptr = next_instr; + next_instr += 4; + INSTRUCTION_STATS(TO_BOOL_NONE); + static_assert(INLINE_CACHE_ENTRIES_TO_BOOL == 3, "incorrect cache size"); PyObject *value; - PyObject *result; + PyObject *res; + /* Skip 1 cache entry */ + /* Skip 2 cache entries */ value = stack_pointer[-1]; - convertion_func_ptr conv_fn; - assert(oparg >= FVC_STR && oparg <= FVC_ASCII); - conv_fn = CONVERSION_FUNCTIONS[oparg]; - result = conv_fn(value); - Py_DECREF(value); - if (result == NULL) goto pop_1_error; - stack_pointer[-1] = result; + // This one is a bit weird, because we expect *some* failures: + DEOPT_IF(!Py_IsNone(value), TO_BOOL); + STAT_INC(TO_BOOL, hit); + res = Py_False; + stack_pointer[-1] = res; DISPATCH(); } - TARGET(FORMAT_SIMPLE) { + TARGET(TO_BOOL_STR) { + frame->instr_ptr = next_instr; + next_instr += 4; + INSTRUCTION_STATS(TO_BOOL_STR); + static_assert(INLINE_CACHE_ENTRIES_TO_BOOL == 3, "incorrect cache size"); PyObject *value; PyObject *res; + /* Skip 1 cache entry */ + /* Skip 2 cache entries */ value = stack_pointer[-1]; - /* If value is a unicode object, then we know the result - * of format(value) is value itself. */ - if (!PyUnicode_CheckExact(value)) { - res = PyObject_Format(value, NULL); - Py_DECREF(value); - if (res == NULL) goto pop_1_error; + DEOPT_IF(!PyUnicode_CheckExact(value), TO_BOOL); + STAT_INC(TO_BOOL, hit); + if (value == &_Py_STR(empty)) { + assert(_Py_IsImmortal(value)); + res = Py_False; } else { - res = value; + assert(Py_SIZE(value)); + Py_DECREF(value); + res = Py_True; } stack_pointer[-1] = res; DISPATCH(); } - TARGET(FORMAT_WITH_SPEC) { - PyObject *fmt_spec; + TARGET(UNARY_INVERT) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(UNARY_INVERT); PyObject *value; PyObject *res; - fmt_spec = stack_pointer[-1]; - value = stack_pointer[-2]; - res = PyObject_Format(value, fmt_spec); + value = stack_pointer[-1]; + res = PyNumber_Invert(value); Py_DECREF(value); - Py_DECREF(fmt_spec); - if (res == NULL) goto pop_2_error; - STACK_SHRINK(1); + if (res == NULL) goto pop_1_error; stack_pointer[-1] = res; DISPATCH(); } - TARGET(COPY) { - PyObject *bottom; - PyObject *top; - bottom = stack_pointer[-1 - (oparg-1)]; - assert(oparg > 0); - top = Py_NewRef(bottom); - STACK_GROW(1); - stack_pointer[-1] = top; + TARGET(UNARY_NEGATIVE) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(UNARY_NEGATIVE); + PyObject *value; + PyObject *res; + value = stack_pointer[-1]; + res = PyNumber_Negative(value); + Py_DECREF(value); + if (res == NULL) goto pop_1_error; + stack_pointer[-1] = res; DISPATCH(); } - TARGET(BINARY_OP) { - PREDICTED(BINARY_OP); - static_assert(INLINE_CACHE_ENTRIES_BINARY_OP == 1, "incorrect cache size"); - PyObject *rhs; - PyObject *lhs; + TARGET(UNARY_NOT) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(UNARY_NOT); + PyObject *value; PyObject *res; - rhs = stack_pointer[-1]; - lhs = stack_pointer[-2]; - #if ENABLE_SPECIALIZATION - _PyBinaryOpCache *cache = (_PyBinaryOpCache *)next_instr; - if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) { - next_instr--; - _Py_Specialize_BinaryOp(lhs, rhs, next_instr, oparg, LOCALS_ARRAY); - DISPATCH_SAME_OPARG(); - } - STAT_INC(BINARY_OP, deferred); - DECREMENT_ADAPTIVE_COUNTER(cache->counter); - #endif /* ENABLE_SPECIALIZATION */ - assert(NB_ADD <= oparg); - assert(oparg <= NB_INPLACE_XOR); - assert(_PyEval_BinaryOps[oparg]); - res = _PyEval_BinaryOps[oparg](lhs, rhs); - Py_DECREF(lhs); - Py_DECREF(rhs); - if (res == NULL) goto pop_2_error; - STACK_SHRINK(1); + value = stack_pointer[-1]; + assert(PyBool_Check(value)); + res = Py_IsFalse(value) ? Py_True : Py_False; stack_pointer[-1] = res; - next_instr += 1; DISPATCH(); } - TARGET(SWAP) { - PyObject *top; - PyObject *bottom; - top = stack_pointer[-1]; - bottom = stack_pointer[-2 - (oparg-2)]; - assert(oparg >= 2); - stack_pointer[-2 - (oparg-2)] = top; - stack_pointer[-1] = bottom; + TARGET(UNPACK_EX) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(UNPACK_EX); + PyObject *seq; + seq = stack_pointer[-1]; + int totalargs = 1 + (oparg & 0xFF) + (oparg >> 8); + PyObject **top = stack_pointer + totalargs - 1; + int res = _PyEval_UnpackIterable(tstate, seq, oparg & 0xFF, oparg >> 8, top); + Py_DECREF(seq); + if (res == 0) goto pop_1_error; + stack_pointer += (oparg >> 8) + (oparg & 0xFF); DISPATCH(); } - TARGET(INSTRUMENTED_INSTRUCTION) { - int next_opcode = _Py_call_instrumentation_instruction( - tstate, frame, next_instr-1); - if (next_opcode < 0) goto error; - next_instr--; - if (_PyOpcode_Caches[next_opcode]) { - _PyBinaryOpCache *cache = (_PyBinaryOpCache *)(next_instr+1); - INCREMENT_ADAPTIVE_COUNTER(cache->counter); + TARGET(UNPACK_SEQUENCE) { + frame->instr_ptr = next_instr; + next_instr += 2; + INSTRUCTION_STATS(UNPACK_SEQUENCE); + PREDICTED(UNPACK_SEQUENCE); + _Py_CODEUNIT *this_instr = next_instr - 2; + PyObject *seq; + // _SPECIALIZE_UNPACK_SEQUENCE + seq = stack_pointer[-1]; + { + uint16_t counter = read_u16(&this_instr[1].cache); + TIER_ONE_ONLY + #if ENABLE_SPECIALIZATION + if (ADAPTIVE_COUNTER_IS_ZERO(counter)) { + next_instr = this_instr; + _Py_Specialize_UnpackSequence(seq, next_instr, oparg); + DISPATCH_SAME_OPARG(); + } + STAT_INC(UNPACK_SEQUENCE, deferred); + DECREMENT_ADAPTIVE_COUNTER(this_instr[1].cache); + #endif /* ENABLE_SPECIALIZATION */ + (void)seq; + (void)counter; } - assert(next_opcode > 0 && next_opcode < 256); - opcode = next_opcode; - DISPATCH_GOTO(); - } - - TARGET(INSTRUMENTED_JUMP_FORWARD) { - INSTRUMENTED_JUMP(next_instr-1, next_instr+oparg, PY_MONITORING_EVENT_JUMP); - DISPATCH(); - } - - TARGET(INSTRUMENTED_JUMP_BACKWARD) { - CHECK_EVAL_BREAKER(); - INSTRUMENTED_JUMP(next_instr-1, next_instr+1-oparg, PY_MONITORING_EVENT_JUMP); + // _UNPACK_SEQUENCE + { + PyObject **top = stack_pointer + oparg - 1; + int res = _PyEval_UnpackIterable(tstate, seq, oparg, -1, top); + Py_DECREF(seq); + if (res == 0) goto pop_1_error; + } + stack_pointer += -1 + oparg; DISPATCH(); } - TARGET(INSTRUMENTED_POP_JUMP_IF_TRUE) { - PyObject *cond = POP(); - assert(PyBool_Check(cond)); - _Py_CODEUNIT *here = next_instr - 1; - int offset = Py_IsTrue(cond) * oparg; - INSTRUMENTED_JUMP(here, next_instr + offset, PY_MONITORING_EVENT_BRANCH); + TARGET(UNPACK_SEQUENCE_LIST) { + frame->instr_ptr = next_instr; + next_instr += 2; + INSTRUCTION_STATS(UNPACK_SEQUENCE_LIST); + static_assert(INLINE_CACHE_ENTRIES_UNPACK_SEQUENCE == 1, "incorrect cache size"); + PyObject *seq; + PyObject **values; + /* Skip 1 cache entry */ + seq = stack_pointer[-1]; + values = &stack_pointer[-1]; + DEOPT_IF(!PyList_CheckExact(seq), UNPACK_SEQUENCE); + DEOPT_IF(PyList_GET_SIZE(seq) != oparg, UNPACK_SEQUENCE); + STAT_INC(UNPACK_SEQUENCE, hit); + PyObject **items = _PyList_ITEMS(seq); + for (int i = oparg; --i >= 0; ) { + *values++ = Py_NewRef(items[i]); + } + Py_DECREF(seq); + stack_pointer += -1 + oparg; DISPATCH(); } - TARGET(INSTRUMENTED_POP_JUMP_IF_FALSE) { - PyObject *cond = POP(); - assert(PyBool_Check(cond)); - _Py_CODEUNIT *here = next_instr - 1; - int offset = Py_IsFalse(cond) * oparg; - INSTRUMENTED_JUMP(here, next_instr + offset, PY_MONITORING_EVENT_BRANCH); + TARGET(UNPACK_SEQUENCE_TUPLE) { + frame->instr_ptr = next_instr; + next_instr += 2; + INSTRUCTION_STATS(UNPACK_SEQUENCE_TUPLE); + static_assert(INLINE_CACHE_ENTRIES_UNPACK_SEQUENCE == 1, "incorrect cache size"); + PyObject *seq; + PyObject **values; + /* Skip 1 cache entry */ + seq = stack_pointer[-1]; + values = &stack_pointer[-1]; + DEOPT_IF(!PyTuple_CheckExact(seq), UNPACK_SEQUENCE); + DEOPT_IF(PyTuple_GET_SIZE(seq) != oparg, UNPACK_SEQUENCE); + STAT_INC(UNPACK_SEQUENCE, hit); + PyObject **items = _PyTuple_ITEMS(seq); + for (int i = oparg; --i >= 0; ) { + *values++ = Py_NewRef(items[i]); + } + Py_DECREF(seq); + stack_pointer += -1 + oparg; DISPATCH(); } - TARGET(INSTRUMENTED_POP_JUMP_IF_NONE) { - PyObject *value = POP(); - _Py_CODEUNIT *here = next_instr-1; - int offset; - if (Py_IsNone(value)) { - offset = oparg; - } - else { - Py_DECREF(value); - offset = 0; - } - INSTRUMENTED_JUMP(here, next_instr + offset, PY_MONITORING_EVENT_BRANCH); + TARGET(UNPACK_SEQUENCE_TWO_TUPLE) { + frame->instr_ptr = next_instr; + next_instr += 2; + INSTRUCTION_STATS(UNPACK_SEQUENCE_TWO_TUPLE); + static_assert(INLINE_CACHE_ENTRIES_UNPACK_SEQUENCE == 1, "incorrect cache size"); + PyObject *seq; + PyObject **values; + /* Skip 1 cache entry */ + seq = stack_pointer[-1]; + values = &stack_pointer[-1]; + DEOPT_IF(!PyTuple_CheckExact(seq), UNPACK_SEQUENCE); + DEOPT_IF(PyTuple_GET_SIZE(seq) != 2, UNPACK_SEQUENCE); + assert(oparg == 2); + STAT_INC(UNPACK_SEQUENCE, hit); + values[0] = Py_NewRef(PyTuple_GET_ITEM(seq, 1)); + values[1] = Py_NewRef(PyTuple_GET_ITEM(seq, 0)); + Py_DECREF(seq); + stack_pointer += -1 + oparg; DISPATCH(); } - TARGET(INSTRUMENTED_POP_JUMP_IF_NOT_NONE) { - PyObject *value = POP(); - _Py_CODEUNIT *here = next_instr-1; - int offset; - if (Py_IsNone(value)) { - offset = 0; + TARGET(WITH_EXCEPT_START) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(WITH_EXCEPT_START); + PyObject *val; + PyObject *lasti; + PyObject *exit_func; + PyObject *res; + val = stack_pointer[-1]; + lasti = stack_pointer[-3]; + exit_func = stack_pointer[-4]; + /* At the top of the stack are 4 values: + - val: TOP = exc_info() + - unused: SECOND = previous exception + - lasti: THIRD = lasti of exception in exc_info() + - exit_func: FOURTH = the context.__exit__ bound method + We call FOURTH(type(TOP), TOP, GetTraceback(TOP)). + Then we push the __exit__ return value. + */ + PyObject *exc, *tb; + assert(val && PyExceptionInstance_Check(val)); + exc = PyExceptionInstance_Class(val); + tb = PyException_GetTraceback(val); + if (tb == NULL) { + tb = Py_None; } else { - Py_DECREF(value); - offset = oparg; + Py_DECREF(tb); } - INSTRUMENTED_JUMP(here, next_instr + offset, PY_MONITORING_EVENT_BRANCH); + assert(PyLong_Check(lasti)); + (void)lasti; // Shut up compiler warning if asserts are off + PyObject *stack[4] = {NULL, exc, val, tb}; + res = PyObject_Vectorcall(exit_func, stack + 1, + 3 | PY_VECTORCALL_ARGUMENTS_OFFSET, NULL); + if (res == NULL) goto error; + stack_pointer[0] = res; + stack_pointer += 1; DISPATCH(); } - TARGET(EXTENDED_ARG) { - assert(oparg); - opcode = next_instr->op.code; - oparg = oparg << 8 | next_instr->op.arg; - PRE_DISPATCH_GOTO(); - DISPATCH_GOTO(); - } - - TARGET(CACHE) { - assert(0 && "Executing a cache."); - Py_UNREACHABLE(); - } - - TARGET(RESERVED) { - assert(0 && "Executing RESERVED instruction."); - Py_UNREACHABLE(); + TARGET(YIELD_VALUE) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(YIELD_VALUE); + PyObject *retval; + retval = stack_pointer[-1]; + TIER_ONE_ONLY + // 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(frame != &entry_frame); + frame->instr_ptr = next_instr; + PyGenObject *gen = _PyFrame_GetGenerator(frame); + assert(FRAME_SUSPENDED_YIELD_FROM == FRAME_SUSPENDED + 1); + assert(oparg == 0 || oparg == 1); + gen->gi_frame_state = FRAME_SUSPENDED + oparg; + _PyFrame_SetStackPointer(frame, stack_pointer - 1); + tstate->exc_info = gen->gi_exc_state.previous_item; + gen->gi_exc_state.previous_item = NULL; + _Py_LeaveRecursiveCallPy(tstate); + _PyInterpreterFrame *gen_frame = frame; + frame = tstate->current_frame = frame->previous; + gen_frame->previous = NULL; + _PyFrame_StackPush(frame, retval); + /* We don't know which of these is relevant here, so keep them equal */ + assert(INLINE_CACHE_ENTRIES_SEND == INLINE_CACHE_ENTRIES_FOR_ITER); + LOAD_IP(1 + INLINE_CACHE_ENTRIES_SEND); + goto resume_frame; } +#undef TIER_ONE diff --git a/Python/getargs.c b/Python/getargs.c index 916e46578a454b..0c4ce282f48764 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -1,27 +1,22 @@ /* New getargs implementation */ +#define PY_CXX_CONST const #include "Python.h" +#include "pycore_abstract.h" // _PyNumber_Index() #include "pycore_dict.h" // _PyDict_HasOnlyStringKeys() +#include "pycore_modsupport.h" // export _PyArg_NoKeywords() #include "pycore_pylifecycle.h" // _PyArg_Fini #include "pycore_tuple.h" // _PyTuple_ITEMS() -#include -#include - - -#ifdef __cplusplus -extern "C" { -#endif - /* Export Stable ABIs (abi only) */ PyAPI_FUNC(int) _PyArg_Parse_SizeT(PyObject *, const char *, ...); PyAPI_FUNC(int) _PyArg_ParseTuple_SizeT(PyObject *, const char *, ...); PyAPI_FUNC(int) _PyArg_ParseTupleAndKeywords_SizeT(PyObject *, PyObject *, - const char *, char **, ...); + const char *, const char * const *, ...); PyAPI_FUNC(int) _PyArg_VaParse_SizeT(PyObject *, const char *, va_list); PyAPI_FUNC(int) _PyArg_VaParseTupleAndKeywords_SizeT(PyObject *, PyObject *, - const char *, char **, va_list); + const char *, const char * const *, va_list); #define FLAG_COMPAT 1 @@ -53,14 +48,14 @@ static void seterror(Py_ssize_t, const char *, int *, const char *, const char * static const char *convertitem(PyObject *, const char **, va_list *, int, int *, char *, size_t, freelist_t *); static const char *converttuple(PyObject *, const char **, va_list *, int, - int *, char *, size_t, int, freelist_t *); + int *, char *, size_t, freelist_t *); static const char *convertsimple(PyObject *, const char **, va_list *, int, char *, size_t, freelist_t *); static Py_ssize_t convertbuffer(PyObject *, const void **p, const char **); static int getbuffer(PyObject *, Py_buffer *, const char**); static int vgetargskeywords(PyObject *, PyObject *, - const char *, char **, va_list *, int); + const char *, const char * const *, va_list *, int); static int vgetargskeywordsfast(PyObject *, PyObject *, struct _PyArg_Parser *, va_list *, int); static int vgetargskeywordsfast_impl(PyObject *const *args, Py_ssize_t nargs, @@ -460,7 +455,7 @@ seterror(Py_ssize_t iarg, const char *msg, int *levels, const char *fname, static const char * converttuple(PyObject *arg, const char **p_format, va_list *p_va, int flags, - int *levels, char *msgbuf, size_t bufsize, int toplevel, + int *levels, char *msgbuf, size_t bufsize, freelist_t *freelist) { int level = 0; @@ -483,14 +478,13 @@ converttuple(PyObject *arg, const char **p_format, va_list *p_va, int flags, } else if (c == ':' || c == ';' || c == '\0') break; - else if (level == 0 && Py_ISALPHA(c)) + else if (level == 0 && Py_ISALPHA(c) && c != 'e') n++; } if (!PySequence_Check(arg) || PyBytes_Check(arg)) { levels[0] = 0; PyOS_snprintf(msgbuf, bufsize, - toplevel ? "expected %d arguments, not %.50s" : "must be %d-item sequence, not %.50s", n, arg == Py_None ? "None" : Py_TYPE(arg)->tp_name); @@ -500,18 +494,9 @@ converttuple(PyObject *arg, const char **p_format, va_list *p_va, int flags, len = PySequence_Size(arg); if (len != n) { levels[0] = 0; - if (toplevel) { - PyOS_snprintf(msgbuf, bufsize, - "expected %d argument%s, not %zd", - n, - n == 1 ? "" : "s", - len); - } - else { - PyOS_snprintf(msgbuf, bufsize, - "must be sequence of length %d, not %zd", - n, len); - } + PyOS_snprintf(msgbuf, bufsize, + "must be sequence of length %d, not %zd", + n, len); return msgbuf; } @@ -554,7 +539,7 @@ convertitem(PyObject *arg, const char **p_format, va_list *p_va, int flags, if (*format == '(' /* ')' */) { format++; msg = converttuple(arg, &format, p_va, flags, levels, msgbuf, - bufsize, 0, freelist); + bufsize, freelist); if (msg == NULL) format++; } @@ -1193,17 +1178,15 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, arg, msgbuf, bufsize); format++; - /* Caller is interested in Py_buffer, and the object - supports it directly. */ + /* Caller is interested in Py_buffer, and the object supports it + directly. The request implicitly asks for PyBUF_SIMPLE, so the + result is C-contiguous with format 'B'. */ if (PyObject_GetBuffer(arg, (Py_buffer*)p, PyBUF_WRITABLE) < 0) { PyErr_Clear(); return converterr("read-write bytes-like object", arg, msgbuf, bufsize); } - if (!PyBuffer_IsContiguous((Py_buffer*)p, 'C')) { - PyBuffer_Release((Py_buffer*)p); - return converterr("contiguous buffer", arg, msgbuf, bufsize); - } + assert(PyBuffer_IsContiguous((Py_buffer *)p, 'C')); if (addcleanup(p, freelist, cleanup_buffer)) { return converterr( "(cleanup problem)", @@ -1248,15 +1231,12 @@ convertbuffer(PyObject *arg, const void **p, const char **errmsg) static int getbuffer(PyObject *arg, Py_buffer *view, const char **errmsg) { + /* PyBUF_SIMPLE implies C-contiguous */ if (PyObject_GetBuffer(arg, view, PyBUF_SIMPLE) != 0) { *errmsg = "bytes-like object"; return -1; } - if (!PyBuffer_IsContiguous(view, 'C')) { - PyBuffer_Release(view); - *errmsg = "contiguous buffer"; - return -1; - } + assert(PyBuffer_IsContiguous(view, 'C')); return 0; } @@ -1268,7 +1248,7 @@ int PyArg_ParseTupleAndKeywords(PyObject *args, PyObject *keywords, const char *format, - char **kwlist, ...) + const char * const *kwlist, ...) { int retval; va_list va; @@ -1292,7 +1272,7 @@ int _PyArg_ParseTupleAndKeywords_SizeT(PyObject *args, PyObject *keywords, const char *format, - char **kwlist, ...) + const char * const *kwlist, ...) { int retval; va_list va; @@ -1318,7 +1298,7 @@ int PyArg_VaParseTupleAndKeywords(PyObject *args, PyObject *keywords, const char *format, - char **kwlist, va_list va) + const char * const *kwlist, va_list va) { int retval; va_list lva; @@ -1343,7 +1323,7 @@ int _PyArg_VaParseTupleAndKeywords_SizeT(PyObject *args, PyObject *keywords, const char *format, - char **kwlist, va_list va) + const char * const *kwlist, va_list va) { int retval; va_list lva; @@ -1481,7 +1461,7 @@ PyArg_ValidateKeywordArguments(PyObject *kwargs) static int vgetargskeywords(PyObject *args, PyObject *kwargs, const char *format, - char **kwlist, va_list *p_va, int flags) + const char * const *kwlist, va_list *p_va, int flags) { char msgbuf[512]; int levels[32]; @@ -1491,7 +1471,6 @@ vgetargskeywords(PyObject *args, PyObject *kwargs, const char *format, int i, pos, len; int skip = 0; Py_ssize_t nargs, nkwargs; - PyObject *current_arg; freelistentry_t static_entries[STATIC_FREELIST_ENTRIES]; freelist_t freelist; @@ -1621,17 +1600,17 @@ vgetargskeywords(PyObject *args, PyObject *kwargs, const char *format, return cleanreturn(0, &freelist); } if (!skip) { + PyObject *current_arg; if (i < nargs) { - current_arg = PyTuple_GET_ITEM(args, i); + current_arg = Py_NewRef(PyTuple_GET_ITEM(args, i)); } else if (nkwargs && i >= pos) { - current_arg = _PyDict_GetItemStringWithError(kwargs, kwlist[i]); + if (PyDict_GetItemStringRef(kwargs, kwlist[i], ¤t_arg) < 0) { + return cleanreturn(0, &freelist); + } if (current_arg) { --nkwargs; } - else if (PyErr_Occurred()) { - return cleanreturn(0, &freelist); - } } else { current_arg = NULL; @@ -1640,6 +1619,7 @@ vgetargskeywords(PyObject *args, PyObject *kwargs, const char *format, if (current_arg) { msg = convertitem(current_arg, &format, p_va, flags, levels, msgbuf, sizeof(msgbuf), &freelist); + Py_DECREF(current_arg); if (msg) { seterror(i+1, msg, levels, fname, custom_msg); return cleanreturn(0, &freelist); @@ -1710,8 +1690,12 @@ vgetargskeywords(PyObject *args, PyObject *kwargs, const char *format, Py_ssize_t j; /* make sure there are no arguments given by name and position */ for (i = pos; i < nargs; i++) { - current_arg = _PyDict_GetItemStringWithError(kwargs, kwlist[i]); + PyObject *current_arg; + if (PyDict_GetItemStringRef(kwargs, kwlist[i], ¤t_arg) < 0) { + return cleanreturn(0, &freelist); + } if (current_arg) { + Py_DECREF(current_arg); /* arg present in tuple and in dict */ PyErr_Format(PyExc_TypeError, "argument for %.200s%s given by name ('%s') " @@ -1721,9 +1705,6 @@ vgetargskeywords(PyObject *args, PyObject *kwargs, const char *format, kwlist[i], i+1); return cleanreturn(0, &freelist); } - else if (PyErr_Occurred()) { - return cleanreturn(0, &freelist); - } } /* make sure there are no extraneous keyword arguments */ j = 0; @@ -1735,7 +1716,7 @@ vgetargskeywords(PyObject *args, PyObject *kwargs, const char *format, return cleanreturn(0, &freelist); } for (i = pos; i < len; i++) { - if (_PyUnicode_EqualToASCIIString(key, kwlist[i])) { + if (PyUnicode_EqualToUTF8(key, kwlist[i])) { match = 1; break; } @@ -1887,8 +1868,9 @@ new_kwtuple(const char * const *keywords, int total, int pos) } static int -_parser_init(struct _PyArg_Parser *parser) +_parser_init(void *arg) { + struct _PyArg_Parser *parser = (struct _PyArg_Parser *)arg; const char * const *keywords = parser->keywords; assert(keywords != NULL); assert(parser->pos == 0 && @@ -1899,7 +1881,7 @@ _parser_init(struct _PyArg_Parser *parser) int len, pos; if (scan_keywords(keywords, &len, &pos) < 0) { - return 0; + return -1; } const char *fname, *custommsg = NULL; @@ -1908,7 +1890,7 @@ _parser_init(struct _PyArg_Parser *parser) assert(parser->fname == NULL); if (parse_format(parser->format, len, pos, &fname, &custommsg, &min, &max) < 0) { - return 0; + return -1; } } else { @@ -1921,7 +1903,7 @@ _parser_init(struct _PyArg_Parser *parser) if (kwtuple == NULL) { kwtuple = new_kwtuple(keywords, len, pos); if (kwtuple == NULL) { - return 0; + return -1; } owned = 1; } @@ -1935,40 +1917,27 @@ _parser_init(struct _PyArg_Parser *parser) parser->min = min; parser->max = max; parser->kwtuple = kwtuple; - parser->initialized = owned ? 1 : -1; + parser->is_kwtuple_owned = owned; assert(parser->next == NULL); - parser->next = _PyRuntime.getargs.static_parsers; - _PyRuntime.getargs.static_parsers = parser; - return 1; + parser->next = _Py_atomic_load_ptr(&_PyRuntime.getargs.static_parsers); + do { + // compare-exchange updates parser->next on failure + } while (_Py_atomic_compare_exchange_ptr(&_PyRuntime.getargs.static_parsers, + &parser->next, parser)); + return 0; } static int parser_init(struct _PyArg_Parser *parser) { - // volatile as it can be modified by other threads - // and should not be optimized or reordered by compiler - if (*((volatile int *)&parser->initialized)) { - assert(parser->kwtuple != NULL); - return 1; - } - PyThread_acquire_lock(_PyRuntime.getargs.mutex, WAIT_LOCK); - // Check again if another thread initialized the parser - // while we were waiting for the lock. - if (*((volatile int *)&parser->initialized)) { - assert(parser->kwtuple != NULL); - PyThread_release_lock(_PyRuntime.getargs.mutex); - return 1; - } - int ret = _parser_init(parser); - PyThread_release_lock(_PyRuntime.getargs.mutex); - return ret; + return _PyOnceFlag_CallOnce(&parser->once, &_parser_init, parser); } static void parser_clear(struct _PyArg_Parser *parser) { - if (parser->initialized == 1) { + if (parser->is_kwtuple_owned) { Py_CLEAR(parser->kwtuple); } } @@ -1985,7 +1954,7 @@ find_keyword(PyObject *kwnames, PyObject *const *kwstack, PyObject *key) /* kwname == key will normally find a match in since keyword keys should be interned strings; if not retry below in a new loop. */ if (kwname == key) { - return kwstack[i]; + return Py_NewRef(kwstack[i]); } } @@ -1993,7 +1962,7 @@ find_keyword(PyObject *kwnames, PyObject *const *kwstack, PyObject *key) PyObject *kwname = PyTuple_GET_ITEM(kwnames, i); assert(PyUnicode_Check(kwname)); if (_PyUnicode_EQ(kwname, key)) { - return kwstack[i]; + return Py_NewRef(kwstack[i]); } } return NULL; @@ -2013,7 +1982,6 @@ vgetargskeywordsfast_impl(PyObject *const *args, Py_ssize_t nargs, PyObject *keyword; int i, pos, len; Py_ssize_t nkwargs; - PyObject *current_arg; freelistentry_t static_entries[STATIC_FREELIST_ENTRIES]; freelist_t freelist; PyObject *const *kwstack = NULL; @@ -2036,7 +2004,7 @@ vgetargskeywordsfast_impl(PyObject *const *args, Py_ssize_t nargs, return 0; } - if (!parser_init(parser)) { + if (parser_init(parser) < 0) { return 0; } @@ -2108,14 +2076,14 @@ vgetargskeywordsfast_impl(PyObject *const *args, Py_ssize_t nargs, } assert(!IS_END_OF_FORMAT(*format)); + PyObject *current_arg; if (i < nargs) { - current_arg = args[i]; + current_arg = Py_NewRef(args[i]); } else if (nkwargs && i >= pos) { keyword = PyTuple_GET_ITEM(kwtuple, i - pos); if (kwargs != NULL) { - current_arg = PyDict_GetItemWithError(kwargs, keyword); - if (!current_arg && PyErr_Occurred()) { + if (PyDict_GetItemRef(kwargs, keyword, ¤t_arg) < 0) { return cleanreturn(0, &freelist); } } @@ -2133,6 +2101,7 @@ vgetargskeywordsfast_impl(PyObject *const *args, Py_ssize_t nargs, if (current_arg) { msg = convertitem(current_arg, &format, p_va, flags, levels, msgbuf, sizeof(msgbuf), &freelist); + Py_DECREF(current_arg); if (msg) { seterror(i+1, msg, levels, parser->fname, parser->custom_msg); return cleanreturn(0, &freelist); @@ -2183,10 +2152,10 @@ vgetargskeywordsfast_impl(PyObject *const *args, Py_ssize_t nargs, if (nkwargs > 0) { /* make sure there are no arguments given by name and position */ for (i = pos; i < nargs; i++) { + PyObject *current_arg; keyword = PyTuple_GET_ITEM(kwtuple, i - pos); if (kwargs != NULL) { - current_arg = PyDict_GetItemWithError(kwargs, keyword); - if (!current_arg && PyErr_Occurred()) { + if (PyDict_GetItemRef(kwargs, keyword, ¤t_arg) < 0) { return cleanreturn(0, &freelist); } } @@ -2194,6 +2163,7 @@ vgetargskeywordsfast_impl(PyObject *const *args, Py_ssize_t nargs, current_arg = find_keyword(kwnames, kwstack, keyword); } if (current_arg) { + Py_DECREF(current_arg); /* arg present in tuple and in dict */ PyErr_Format(PyExc_TypeError, "argument for %.200s%s given by name ('%U') " @@ -2248,7 +2218,6 @@ _PyArg_UnpackKeywords(PyObject *const *args, Py_ssize_t nargs, int i, posonly, minposonly, maxargs; int reqlimit = minkw ? maxpos + minkw : minpos; Py_ssize_t nkwargs; - PyObject *current_arg; PyObject * const *kwstack = NULL; assert(kwargs == NULL || PyDict_Check(kwargs)); @@ -2268,7 +2237,7 @@ _PyArg_UnpackKeywords(PyObject *const *args, Py_ssize_t nargs, args = buf; } - if (!parser_init(parser)) { + if (parser_init(parser) < 0) { return NULL; } @@ -2343,11 +2312,11 @@ _PyArg_UnpackKeywords(PyObject *const *args, Py_ssize_t nargs, /* copy keyword args using kwtuple to drive process */ for (i = Py_MAX((int)nargs, posonly); i < maxargs; i++) { + PyObject *current_arg; if (nkwargs) { keyword = PyTuple_GET_ITEM(kwtuple, i - posonly); if (kwargs != NULL) { - current_arg = PyDict_GetItemWithError(kwargs, keyword); - if (!current_arg && PyErr_Occurred()) { + if (PyDict_GetItemRef(kwargs, keyword, ¤t_arg) < 0) { return NULL; } } @@ -2365,6 +2334,7 @@ _PyArg_UnpackKeywords(PyObject *const *args, Py_ssize_t nargs, buf[i] = current_arg; if (current_arg) { + Py_DECREF(current_arg); --nkwargs; } else if (i < minpos || (maxpos <= i && i < reqlimit)) { @@ -2382,10 +2352,10 @@ _PyArg_UnpackKeywords(PyObject *const *args, Py_ssize_t nargs, if (nkwargs > 0) { /* make sure there are no arguments given by name and position */ for (i = posonly; i < nargs; i++) { + PyObject *current_arg; keyword = PyTuple_GET_ITEM(kwtuple, i - posonly); if (kwargs != NULL) { - current_arg = PyDict_GetItemWithError(kwargs, keyword); - if (!current_arg && PyErr_Occurred()) { + if (PyDict_GetItemRef(kwargs, keyword, ¤t_arg) < 0) { return NULL; } } @@ -2393,6 +2363,7 @@ _PyArg_UnpackKeywords(PyObject *const *args, Py_ssize_t nargs, current_arg = find_keyword(kwnames, kwstack, keyword); } if (current_arg) { + Py_DECREF(current_arg); /* arg present in tuple and in dict */ PyErr_Format(PyExc_TypeError, "argument for %.200s%s given by name ('%U') " @@ -2424,7 +2395,6 @@ _PyArg_UnpackKeywordsWithVararg(PyObject *const *args, Py_ssize_t nargs, int i, posonly, minposonly, maxargs; int reqlimit = minkw ? maxpos + minkw : minpos; Py_ssize_t nkwargs; - PyObject *current_arg; PyObject * const *kwstack = NULL; assert(kwargs == NULL || PyDict_Check(kwargs)); @@ -2444,7 +2414,7 @@ _PyArg_UnpackKeywordsWithVararg(PyObject *const *args, Py_ssize_t nargs, args = buf; } - if (!parser_init(parser)) { + if (parser_init(parser) < 0) { return NULL; } @@ -2497,13 +2467,12 @@ _PyArg_UnpackKeywordsWithVararg(PyObject *const *args, Py_ssize_t nargs, } /* copy keyword args using kwtuple to drive process */ - for (i = Py_MAX((int)nargs, posonly) - - Py_SAFE_DOWNCAST(varargssize, Py_ssize_t, int); i < maxargs; i++) { + for (i = Py_MAX((int)nargs, posonly) - Py_SAFE_DOWNCAST(varargssize, Py_ssize_t, int); i < maxargs; i++) { + PyObject *current_arg; if (nkwargs) { keyword = PyTuple_GET_ITEM(kwtuple, i - posonly); if (kwargs != NULL) { - current_arg = PyDict_GetItemWithError(kwargs, keyword); - if (!current_arg && PyErr_Occurred()) { + if (PyDict_GetItemRef(kwargs, keyword, ¤t_arg) < 0) { goto exit; } } @@ -2528,7 +2497,7 @@ _PyArg_UnpackKeywordsWithVararg(PyObject *const *args, Py_ssize_t nargs, * * Otherwise, we leave a place at `buf[vararg]` for vararg tuple * so the index is `i + 1`. */ - if (nargs < vararg) { + if (nargs < vararg && i != vararg) { buf[i] = current_arg; } else { @@ -2536,6 +2505,7 @@ _PyArg_UnpackKeywordsWithVararg(PyObject *const *args, Py_ssize_t nargs, } if (current_arg) { + Py_DECREF(current_arg); --nkwargs; } else if (i < minpos || (maxpos <= i && i < reqlimit)) { @@ -2868,7 +2838,3 @@ _PyArg_Fini(void) } _PyRuntime.getargs.static_parsers = NULL; } - -#ifdef __cplusplus -}; -#endif diff --git a/Python/getopt.c b/Python/getopt.c index 4135bf1446ecfc..f64c89fa22734a 100644 --- a/Python/getopt.c +++ b/Python/getopt.c @@ -29,10 +29,6 @@ #include #include "pycore_getopt.h" -#ifdef __cplusplus -extern "C" { -#endif - int _PyOS_opterr = 1; /* generate error messages */ Py_ssize_t _PyOS_optind = 1; /* index into argv array */ const wchar_t *_PyOS_optarg = NULL; /* optional argument */ @@ -172,8 +168,3 @@ int _PyOS_GetOpt(Py_ssize_t argc, wchar_t * const *argv, int *longindex) return option; } - -#ifdef __cplusplus -} -#endif - diff --git a/Python/hamt.c b/Python/hamt.c index 24265edc2c3fd4..a8fbb00b807934 100644 --- a/Python/hamt.c +++ b/Python/hamt.c @@ -1,9 +1,10 @@ #include "Python.h" - -#include "pycore_bitutils.h" // _Py_popcount32 +#include "pycore_bitutils.h" // _Py_popcount32() #include "pycore_hamt.h" #include "pycore_initconfig.h" // _PyStatus_OK() +#include "pycore_long.h" // _PyLong_Format() #include "pycore_object.h" // _PyObject_GC_TRACK() + #include // offsetof() /* diff --git a/Python/hashtable.c b/Python/hashtable.c index 4e22a1a5509eb5..faf68fe4ff0bca 100644 --- a/Python/hashtable.c +++ b/Python/hashtable.c @@ -45,7 +45,7 @@ */ #include "Python.h" -#include "pycore_hashtable.h" +#include "pycore_hashtable.h" // export _Py_hashtable_new() #include "pycore_pyhash.h" // _Py_HashPointerRaw() #define HASHTABLE_MIN_SIZE 16 @@ -226,7 +226,6 @@ _Py_hashtable_set(_Py_hashtable_t *ht, const void *key, void *value) assert(entry == NULL); #endif - entry = ht->alloc.malloc(sizeof(_Py_hashtable_entry_t)); if (entry == NULL) { /* memory allocation failed */ diff --git a/Python/import.c b/Python/import.c index 56b2dc1a4ada2c..2dd95d8364a0be 100644 --- a/Python/import.c +++ b/Python/import.c @@ -1,7 +1,6 @@ /* Module definition and import implementation */ #include "Python.h" - #include "pycore_hashtable.h" // _Py_hashtable_new_full() #include "pycore_import.h" // _PyImport_BootstrapImp() #include "pycore_initconfig.h" // _PyStatus_OK() @@ -15,17 +14,15 @@ #include "pycore_pystate.h" // _PyInterpreterState_GET() #include "pycore_sysmodule.h" // _PySys_Audit() #include "pycore_weakref.h" // _PyWeakref_GET_REF() + #include "marshal.h" // PyMarshal_ReadObjectFromString() -#include "importdl.h" // _PyImport_DynLoadFiletab +#include "pycore_importdl.h" // _PyImport_DynLoadFiletab #include "pydtrace.h" // PyDTrace_IMPORT_FIND_LOAD_START_ENABLED() #include // bool #ifdef HAVE_FCNTL_H #include #endif -#ifdef __cplusplus -extern "C" { -#endif /*[clinic input] @@ -255,18 +252,21 @@ import_ensure_initialized(PyInterpreterState *interp, PyObject *mod, PyObject *n NOTE: because of this, initializing must be set *before* stuffing the new module in sys.modules. */ - spec = PyObject_GetAttr(mod, &_Py_ID(__spec__)); - int busy = _PyModuleSpec_IsInitializing(spec); - Py_XDECREF(spec); - if (busy) { - /* Wait until module is done importing. */ - PyObject *value = PyObject_CallMethodOneArg( - IMPORTLIB(interp), &_Py_ID(_lock_unlock_module), name); - if (value == NULL) { - return -1; - } - Py_DECREF(value); + int rc = PyObject_GetOptionalAttr(mod, &_Py_ID(__spec__), &spec); + if (rc > 0) { + rc = _PyModuleSpec_IsInitializing(spec); + Py_DECREF(spec); + } + if (rc <= 0) { + return rc; + } + /* Wait until module is done importing. */ + PyObject *value = PyObject_CallMethodOneArg( + IMPORTLIB(interp), &_Py_ID(_lock_unlock_module), name); + if (value == NULL) { + return -1; } + Py_DECREF(value); return 0; } @@ -398,8 +398,8 @@ remove_module(PyThreadState *tstate, PyObject *name) PyObject *modules = MODULES(tstate->interp); if (PyDict_CheckExact(modules)) { - PyObject *mod = _PyDict_Pop(modules, name, Py_None); - Py_XDECREF(mod); + // Error is reported to the caller + (void)PyDict_Pop(modules, name, NULL); } else if (PyMapping_DelItem(modules, name) < 0) { if (_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) { @@ -418,11 +418,7 @@ remove_module(PyThreadState *tstate, PyObject *name) Py_ssize_t _PyImport_GetNextModuleIndex(void) { - PyThread_acquire_lock(EXTENSIONS.mutex, WAIT_LOCK); - LAST_MODULE_INDEX++; - Py_ssize_t index = LAST_MODULE_INDEX; - PyThread_release_lock(EXTENSIONS.mutex); - return index; + return _Py_atomic_add_ssize(&LAST_MODULE_INDEX, 1) + 1; } static const char * @@ -587,7 +583,7 @@ _PyImport_ClearModulesByIndex(PyInterpreterState *interp) if (PyList_SetSlice(MODULES_BY_INDEX(interp), 0, PyList_GET_SIZE(MODULES_BY_INDEX(interp)), NULL)) { - PyErr_WriteUnraisable(MODULES_BY_INDEX(interp)); + PyErr_FormatUnraisable("Exception ignored on clearing interpreters module list"); } } @@ -882,13 +878,13 @@ gets even messier. static inline void extensions_lock_acquire(void) { - PyThread_acquire_lock(_PyRuntime.imports.extensions.mutex, WAIT_LOCK); + PyMutex_Lock(&_PyRuntime.imports.extensions.mutex); } static inline void extensions_lock_release(void) { - PyThread_release_lock(_PyRuntime.imports.extensions.mutex); + PyMutex_Unlock(&_PyRuntime.imports.extensions.mutex); } /* Magic for extension modules (built-in as well as dynamically @@ -2005,7 +2001,6 @@ look_up_frozen(const char *name) struct frozen_info { PyObject *nameobj; const char *data; - PyObject *(*get_code)(void); Py_ssize_t size; bool is_package; bool is_alias; @@ -2039,7 +2034,6 @@ find_frozen(PyObject *nameobj, struct frozen_info *info) if (info != NULL) { info->nameobj = nameobj; // borrowed info->data = (const char *)p->code; - info->get_code = p->get_code; info->size = p->size; info->is_package = p->is_package; if (p->size < 0) { @@ -2051,10 +2045,6 @@ find_frozen(PyObject *nameobj, struct frozen_info *info) info->is_alias = resolve_module_alias(name, _PyImport_FrozenAliases, &info->origname); } - if (p->code == NULL && p->size == 0 && p->get_code != NULL) { - /* It is only deepfrozen. */ - return FROZEN_OKAY; - } if (p->code == NULL) { /* It is frozen but marked as un-importable. */ return FROZEN_EXCLUDED; @@ -2069,11 +2059,6 @@ find_frozen(PyObject *nameobj, struct frozen_info *info) static PyObject * unmarshal_frozen_code(PyInterpreterState *interp, struct frozen_info *info) { - if (info->get_code && _Py_IsMainInterpreter(interp)) { - PyObject *code = info->get_code(); - assert(code != NULL); - return code; - } PyObject *co = PyMarshal_ReadObjectFromString(info->data, info->size); if (co == NULL) { /* Does not contain executable code. */ @@ -2373,19 +2358,24 @@ get_path_importer(PyThreadState *tstate, PyObject *path_importer_cache, PyObject *importer; Py_ssize_t j, nhooks; - /* These conditions are the caller's responsibility: */ - assert(PyList_Check(path_hooks)); - assert(PyDict_Check(path_importer_cache)); + if (!PyList_Check(path_hooks)) { + PyErr_SetString(PyExc_RuntimeError, "sys.path_hooks is not a list"); + return NULL; + } + if (!PyDict_Check(path_importer_cache)) { + PyErr_SetString(PyExc_RuntimeError, "sys.path_importer_cache is not a dict"); + return NULL; + } nhooks = PyList_Size(path_hooks); if (nhooks < 0) return NULL; /* Shouldn't happen */ - importer = PyDict_GetItemWithError(path_importer_cache, p); - if (importer != NULL || _PyErr_Occurred(tstate)) { - return Py_XNewRef(importer); + if (PyDict_GetItemRef(path_importer_cache, p, &importer) != 0) { + // found or error + return importer; } - + // not found /* set path_importer_cache[p] to None to avoid recursion */ if (PyDict_SetItem(path_importer_cache, p, Py_None) != 0) return NULL; @@ -2418,11 +2408,22 @@ PyImport_GetImporter(PyObject *path) { PyThreadState *tstate = _PyThreadState_GET(); PyObject *path_importer_cache = PySys_GetObject("path_importer_cache"); + if (path_importer_cache == NULL) { + PyErr_SetString(PyExc_RuntimeError, "lost sys.path_importer_cache"); + return NULL; + } + Py_INCREF(path_importer_cache); PyObject *path_hooks = PySys_GetObject("path_hooks"); - if (path_importer_cache == NULL || path_hooks == NULL) { + if (path_hooks == NULL) { + PyErr_SetString(PyExc_RuntimeError, "lost sys.path_hooks"); + Py_DECREF(path_importer_cache); return NULL; } - return get_path_importer(tstate, path_importer_cache, path_hooks, path); + Py_INCREF(path_hooks); + PyObject *importer = get_path_importer(tstate, path_importer_cache, path_hooks, path); + Py_DECREF(path_hooks); + Py_DECREF(path_importer_cache); + return importer; } @@ -2434,12 +2435,11 @@ int _PyImport_InitDefaultImportFunc(PyInterpreterState *interp) { // Get the __import__ function - PyObject *import_func = _PyDict_GetItemStringWithError(interp->builtins, - "__import__"); - if (import_func == NULL) { + PyObject *import_func; + if (PyDict_GetItemStringRef(interp->builtins, "__import__", &import_func) <= 0) { return -1; } - IMPORT_FUNC(interp) = Py_NewRef(import_func); + IMPORT_FUNC(interp) = import_func; return 0; } @@ -2564,7 +2564,7 @@ resolve_name(PyThreadState *tstate, PyObject *name, PyObject *globals, int level { PyObject *abs_name; PyObject *package = NULL; - PyObject *spec; + PyObject *spec = NULL; Py_ssize_t last_dot; PyObject *base; int level_up; @@ -2577,20 +2577,18 @@ resolve_name(PyThreadState *tstate, PyObject *name, PyObject *globals, int level _PyErr_SetString(tstate, PyExc_TypeError, "globals must be a dict"); goto error; } - package = PyDict_GetItemWithError(globals, &_Py_ID(__package__)); + if (PyDict_GetItemRef(globals, &_Py_ID(__package__), &package) < 0) { + goto error; + } if (package == Py_None) { + Py_DECREF(package); package = NULL; } - else if (package == NULL && _PyErr_Occurred(tstate)) { - goto error; - } - spec = PyDict_GetItemWithError(globals, &_Py_ID(__spec__)); - if (spec == NULL && _PyErr_Occurred(tstate)) { + if (PyDict_GetItemRef(globals, &_Py_ID(__spec__), &spec) < 0) { goto error; } if (package != NULL) { - Py_INCREF(package); if (!PyUnicode_Check(package)) { _PyErr_SetString(tstate, PyExc_TypeError, "package must be a string"); @@ -2634,16 +2632,15 @@ resolve_name(PyThreadState *tstate, PyObject *name, PyObject *globals, int level goto error; } - package = PyDict_GetItemWithError(globals, &_Py_ID(__name__)); + if (PyDict_GetItemRef(globals, &_Py_ID(__name__), &package) < 0) { + goto error; + } if (package == NULL) { - if (!_PyErr_Occurred(tstate)) { - _PyErr_SetString(tstate, PyExc_KeyError, - "'__name__' not in globals"); - } + _PyErr_SetString(tstate, PyExc_KeyError, + "'__name__' not in globals"); goto error; } - Py_INCREF(package); if (!PyUnicode_Check(package)) { _PyErr_SetString(tstate, PyExc_TypeError, "__name__ must be a string"); @@ -2691,6 +2688,7 @@ resolve_name(PyThreadState *tstate, PyObject *name, PyObject *globals, int level } } + Py_XDECREF(spec); base = PyUnicode_Substring(package, 0, last_dot); Py_DECREF(package); if (base == NULL || PyUnicode_GET_LENGTH(name) == 0) { @@ -2707,6 +2705,7 @@ resolve_name(PyThreadState *tstate, PyObject *name, PyObject *globals, int level "with no known parent package"); error: + Py_XDECREF(spec); Py_XDECREF(package); return NULL; } @@ -2898,12 +2897,11 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *globals, } } else { - PyObject *path; - if (PyObject_GetOptionalAttr(mod, &_Py_ID(__path__), &path) < 0) { + int has_path = PyObject_HasAttrWithError(mod, &_Py_ID(__path__)); + if (has_path < 0) { goto error; } - if (path) { - Py_DECREF(path); + if (has_path) { final_mod = PyObject_CallMethodObjArgs( IMPORTLIB(interp), &_Py_ID(_handle_fromlist), mod, fromlist, IMPORT_FUNC(interp), NULL); @@ -3156,13 +3154,13 @@ _PyImport_FiniCore(PyInterpreterState *interp) int verbose = _PyInterpreterState_GetConfig(interp)->verbose; if (_PySys_ClearAttrString(interp, "meta_path", verbose) < 0) { - PyErr_WriteUnraisable(NULL); + PyErr_FormatUnraisable("Exception ignored on clearing sys.meta_path"); } // XXX Pull in most of finalize_modules() in pylifecycle.c. if (_PySys_ClearAttrString(interp, "modules", verbose) < 0) { - PyErr_WriteUnraisable(NULL); + PyErr_FormatUnraisable("Exception ignored on clearing sys.modules"); } if (IMPORT_LOCK(interp) != NULL) { @@ -3242,10 +3240,10 @@ _PyImport_FiniExternal(PyInterpreterState *interp) // XXX Uninstall importlib metapath importers here? if (_PySys_ClearAttrString(interp, "path_importer_cache", verbose) < 0) { - PyErr_WriteUnraisable(NULL); + PyErr_FormatUnraisable("Exception ignored on clearing sys.path_importer_cache"); } if (_PySys_ClearAttrString(interp, "path_hooks", verbose) < 0) { - PyErr_WriteUnraisable(NULL); + PyErr_FormatUnraisable("Exception ignored on clearing sys.path_hooks"); } } @@ -3567,7 +3565,7 @@ _imp_get_frozen_object_impl(PyObject *module, PyObject *name, if (info.nameobj == NULL) { info.nameobj = name; } - if (info.size == 0 && info.get_code == NULL) { + if (info.size == 0) { /* Does not contain executable code. */ set_frozen_error(FROZEN_INVALID, name); return NULL; @@ -3883,8 +3881,3 @@ PyInit__imp(void) { return PyModuleDef_Init(&imp_module); } - - -#ifdef __cplusplus -} -#endif diff --git a/Python/importdl.c b/Python/importdl.c index 9ab0a5ad33aaac..7dfd301d77efb4 100644 --- a/Python/importdl.c +++ b/Python/importdl.c @@ -15,7 +15,7 @@ */ #ifdef HAVE_DYNAMIC_LOADING -#include "importdl.h" +#include "pycore_importdl.h" #ifdef MS_WINDOWS extern dl_funcptr _PyImport_FindSharedFuncptrWindows(const char *prefix, diff --git a/Python/importdl.h b/Python/importdl.h deleted file mode 100644 index 9171adc2770689..00000000000000 --- a/Python/importdl.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef Py_IMPORTDL_H -#define Py_IMPORTDL_H - -#ifdef __cplusplus -extern "C" { -#endif - - -extern const char *_PyImport_DynLoadFiletab[]; - -extern PyObject *_PyImport_LoadDynamicModuleWithSpec(PyObject *spec, FILE *); - -typedef PyObject *(*PyModInitFunction)(void); - -/* Max length of module suffix searched for -- accommodates "module.slb" */ -#define MAXSUFFIXSIZE 12 - -#ifdef MS_WINDOWS -#include -typedef FARPROC dl_funcptr; -#else -typedef void (*dl_funcptr)(void); -#endif - - -#ifdef __cplusplus -} -#endif -#endif /* !Py_IMPORTDL_H */ diff --git a/Python/initconfig.c b/Python/initconfig.c index 787e583262406c..a6d8c176156617 100644 --- a/Python/initconfig.c +++ b/Python/initconfig.c @@ -9,6 +9,7 @@ #include "pycore_pylifecycle.h" // _Py_PreInitializeFromConfig() #include "pycore_pymem.h" // _PyMem_SetDefaultAllocator() #include "pycore_pystate.h" // _PyThreadState_GET() +#include "pycore_pystats.h" // _Py_StatsOn() #include "osdefs.h" // DELIM @@ -23,6 +24,109 @@ # endif #endif +/* --- PyConfig spec ---------------------------------------------- */ + +typedef enum { + PyConfig_MEMBER_INT = 0, + PyConfig_MEMBER_UINT = 1, + PyConfig_MEMBER_ULONG = 2, + + PyConfig_MEMBER_WSTR = 10, + PyConfig_MEMBER_WSTR_OPT = 11, + PyConfig_MEMBER_WSTR_LIST = 12, +} PyConfigMemberType; + +typedef struct { + const char *name; + size_t offset; + PyConfigMemberType type; +} PyConfigSpec; + +#define SPEC(MEMBER, TYPE) \ + {#MEMBER, offsetof(PyConfig, MEMBER), PyConfig_MEMBER_##TYPE} + +static const PyConfigSpec PYCONFIG_SPEC[] = { + SPEC(_config_init, UINT), + SPEC(isolated, UINT), + SPEC(use_environment, UINT), + SPEC(dev_mode, UINT), + SPEC(install_signal_handlers, UINT), + SPEC(use_hash_seed, UINT), + SPEC(hash_seed, ULONG), + SPEC(faulthandler, UINT), + SPEC(tracemalloc, UINT), + SPEC(perf_profiling, UINT), + SPEC(import_time, UINT), + SPEC(code_debug_ranges, UINT), + SPEC(show_ref_count, UINT), + SPEC(dump_refs, UINT), + SPEC(dump_refs_file, WSTR_OPT), + SPEC(malloc_stats, UINT), + SPEC(filesystem_encoding, WSTR), + SPEC(filesystem_errors, WSTR), + SPEC(pycache_prefix, WSTR_OPT), + SPEC(parse_argv, UINT), + SPEC(orig_argv, WSTR_LIST), + SPEC(argv, WSTR_LIST), + SPEC(xoptions, WSTR_LIST), + SPEC(warnoptions, WSTR_LIST), + SPEC(site_import, UINT), + SPEC(bytes_warning, UINT), + SPEC(warn_default_encoding, UINT), + SPEC(inspect, UINT), + SPEC(interactive, UINT), + SPEC(optimization_level, UINT), + SPEC(parser_debug, UINT), + SPEC(write_bytecode, UINT), + SPEC(verbose, UINT), + SPEC(quiet, UINT), + SPEC(user_site_directory, UINT), + SPEC(configure_c_stdio, UINT), + SPEC(buffered_stdio, UINT), + SPEC(stdio_encoding, WSTR), + SPEC(stdio_errors, WSTR), +#ifdef MS_WINDOWS + SPEC(legacy_windows_stdio, UINT), +#endif + SPEC(check_hash_pycs_mode, WSTR), + SPEC(use_frozen_modules, UINT), + SPEC(safe_path, UINT), + SPEC(int_max_str_digits, INT), + SPEC(cpu_count, INT), + SPEC(pathconfig_warnings, UINT), + SPEC(program_name, WSTR), + SPEC(pythonpath_env, WSTR_OPT), + SPEC(home, WSTR_OPT), + SPEC(platlibdir, WSTR), + SPEC(sys_path_0, WSTR_OPT), + SPEC(module_search_paths_set, UINT), + SPEC(module_search_paths, WSTR_LIST), + SPEC(stdlib_dir, WSTR_OPT), + SPEC(executable, WSTR_OPT), + SPEC(base_executable, WSTR_OPT), + SPEC(prefix, WSTR_OPT), + SPEC(base_prefix, WSTR_OPT), + SPEC(exec_prefix, WSTR_OPT), + SPEC(base_exec_prefix, WSTR_OPT), + SPEC(skip_source_first_line, UINT), + SPEC(run_command, WSTR_OPT), + SPEC(run_module, WSTR_OPT), + SPEC(run_filename, WSTR_OPT), + SPEC(_install_importlib, UINT), + SPEC(_init_main, UINT), + SPEC(_is_python_build, UINT), +#ifdef Py_STATS + SPEC(_pystats, UINT), +#endif +#ifdef Py_DEBUG + SPEC(run_presite, WSTR_OPT), +#endif + {NULL, 0, 0}, +}; + +#undef SPEC + + /* --- Command line options --------------------------------------- */ /* Short usage message (with %s for argv0) */ @@ -129,13 +233,22 @@ The following implementation-specific options are available:\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." + The default is sys.int_info.default_max_str_digits. 0 disables.\n\ +\n\ +-X cpu_count=[n|default]: Override the return value of os.cpu_count(),\n\ + os.process_cpu_count(), and multiprocessing.cpu_count(). This can help users who need\n\ + to limit resources in a container." #ifdef Py_STATS "\n\ \n\ -X pystats: Enable pystats collection at startup." #endif +#ifdef Py_DEBUG +"\n\ +\n\ +-X presite=package.module: import this module before site.py is run." +#endif ; /* Envvars that don't have equivalent command-line options are listed first */ @@ -167,14 +280,22 @@ static const char usage_envvars[] = " locale coercion and locale compatibility warnings on stderr.\n" "PYTHONBREAKPOINT: if this variable is set to 0, it disables the default\n" " debugger. It can be set to the callable of your debugger of choice.\n" +"PYTHON_CPU_COUNT: Overrides the return value of os.process_cpu_count(),\n" +" os.cpu_count(), and multiprocessing.cpu_count() if set to a positive integer.\n" "PYTHONDEVMODE: enable the development mode.\n" "PYTHONPYCACHEPREFIX: root directory for bytecode cache (pyc) files.\n" "PYTHONWARNDEFAULTENCODING: enable opt-in EncodingWarning for 'encoding=None'.\n" -"PYTHONNODEBUGRANGES: If this variable is set, it disables the inclusion of the \n" +"PYTHONNODEBUGRANGES: if this variable is set, it disables the inclusion of the \n" " tables mapping extra location information (end line, start column offset \n" " and end column offset) to every instruction in code objects. This is useful \n" " when smaller code objects and pyc files are desired as well as suppressing the \n" " extra visual location indicators when the interpreter displays tracebacks.\n" +"PYTHON_FROZEN_MODULES : if this variable is set, it determines whether or not \n" +" frozen modules should be used. The default is \"on\" (or \"off\" if you are \n" +" running a local build).\n" +"PYTHON_COLORS : If this variable is set to 1, the interpreter will" +" colorize various kinds of output. Setting it to 0 deactivates this behavior.\n" +"PYTHON_HISTORY : the location of a .python_history file.\n" "These variables have equivalent command-line parameters (see --help for details):\n" "PYTHONDEBUG : enable parser debug mode (-d)\n" "PYTHONDONTWRITEBYTECODE : don't write .pyc files (-B)\n" @@ -186,7 +307,14 @@ static const char usage_envvars[] = "PYTHONSAFEPATH : don't prepend a potentially unsafe path to sys.path (-P)\n" "PYTHONUNBUFFERED : disable stdout/stderr buffering (-u)\n" "PYTHONVERBOSE : trace import statements (-v)\n" -"PYTHONWARNINGS=arg : warning control (-W arg)\n"; +"PYTHONWARNINGS=arg : warning control (-W arg)\n" +#ifdef Py_STATS +"PYTHONSTATS : turns on statistics gathering\n" +#endif +#ifdef Py_DEBUG +"PYTHON_PRESITE=pkg.mod : import this module before site.py is run\n" +#endif +; #if defined(MS_WINDOWS) # define PYTHONHOMEHELP "\\python{major}{minor}" @@ -335,21 +463,34 @@ int PyStatus_IsExit(PyStatus status) int PyStatus_Exception(PyStatus status) { return _PyStatus_EXCEPTION(status); } -PyObject* +void _PyErr_SetFromPyStatus(PyStatus status) { if (!_PyStatus_IS_ERROR(status)) { PyErr_Format(PyExc_SystemError, - "%s() expects an error PyStatus", - _PyStatus_GET_FUNC()); + "_PyErr_SetFromPyStatus() status is not an error"); + return; } - else if (status.func) { - PyErr_Format(PyExc_ValueError, "%s: %s", status.func, status.err_msg); + + const char *err_msg = status.err_msg; + if (err_msg == NULL || strlen(err_msg) == 0) { + PyErr_Format(PyExc_SystemError, + "_PyErr_SetFromPyStatus() status has no error message"); + return; + } + + if (strcmp(err_msg, _PyStatus_NO_MEMORY_ERRMSG) == 0) { + PyErr_NoMemory(); + return; + } + + const char *func = status.func; + if (func) { + PyErr_Format(PyExc_RuntimeError, "%s: %s", func, err_msg); } else { - PyErr_Format(PyExc_ValueError, "%s", status.err_msg); + PyErr_Format(PyExc_RuntimeError, "%s", err_msg); } - return NULL; } @@ -615,8 +756,13 @@ config_check_consistency(const PyConfig *config) assert(config->_is_python_build >= 0); assert(config->safe_path >= 0); assert(config->int_max_str_digits >= 0); + // cpu_count can be -1 if the user doesn't override it. + assert(config->cpu_count != 0); // config->use_frozen_modules is initialized later // by _PyConfig_InitImportConfig(). +#ifdef Py_STATS + assert(config->_pystats >= 0); +#endif return 1; } #endif @@ -651,6 +797,7 @@ PyConfig_Clear(PyConfig *config) CLEAR(config->exec_prefix); CLEAR(config->base_exec_prefix); CLEAR(config->platlibdir); + CLEAR(config->sys_path_0); CLEAR(config->filesystem_encoding); CLEAR(config->filesystem_errors); @@ -660,6 +807,9 @@ PyConfig_Clear(PyConfig *config) CLEAR(config->run_module); CLEAR(config->run_filename); CLEAR(config->check_hash_pycs_mode); +#ifdef Py_DEBUG + CLEAR(config->run_presite); +#endif _PyWideStringList_Clear(&config->orig_argv); #undef CLEAR @@ -711,6 +861,7 @@ _PyConfig_InitCompatConfig(PyConfig *config) config->int_max_str_digits = -1; config->_is_python_build = 0; config->code_debug_ranges = 1; + config->cpu_count = -1; } @@ -848,100 +999,47 @@ PyConfig_SetBytesString(PyConfig *config, wchar_t **config_str, PyStatus _PyConfig_Copy(PyConfig *config, const PyConfig *config2) { - PyStatus status; - PyConfig_Clear(config); -#define COPY_ATTR(ATTR) config->ATTR = config2->ATTR -#define COPY_WSTR_ATTR(ATTR) \ - do { \ - status = PyConfig_SetString(config, &config->ATTR, config2->ATTR); \ - if (_PyStatus_EXCEPTION(status)) { \ - return status; \ - } \ - } while (0) -#define COPY_WSTRLIST(LIST) \ - do { \ - if (_PyWideStringList_Copy(&config->LIST, &config2->LIST) < 0) { \ - return _PyStatus_NO_MEMORY(); \ - } \ - } while (0) - - COPY_ATTR(_config_init); - COPY_ATTR(isolated); - COPY_ATTR(use_environment); - COPY_ATTR(dev_mode); - COPY_ATTR(install_signal_handlers); - COPY_ATTR(use_hash_seed); - COPY_ATTR(hash_seed); - 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); - COPY_ATTR(dump_refs); - COPY_ATTR(dump_refs_file); - COPY_ATTR(malloc_stats); - - COPY_WSTR_ATTR(pycache_prefix); - COPY_WSTR_ATTR(pythonpath_env); - COPY_WSTR_ATTR(home); - COPY_WSTR_ATTR(program_name); - - COPY_ATTR(parse_argv); - COPY_WSTRLIST(argv); - COPY_WSTRLIST(warnoptions); - COPY_WSTRLIST(xoptions); - COPY_WSTRLIST(module_search_paths); - COPY_ATTR(module_search_paths_set); - COPY_WSTR_ATTR(stdlib_dir); - - COPY_WSTR_ATTR(executable); - COPY_WSTR_ATTR(base_executable); - COPY_WSTR_ATTR(prefix); - COPY_WSTR_ATTR(base_prefix); - COPY_WSTR_ATTR(exec_prefix); - COPY_WSTR_ATTR(base_exec_prefix); - COPY_WSTR_ATTR(platlibdir); - - COPY_ATTR(site_import); - COPY_ATTR(bytes_warning); - COPY_ATTR(warn_default_encoding); - COPY_ATTR(inspect); - COPY_ATTR(interactive); - COPY_ATTR(optimization_level); - COPY_ATTR(parser_debug); - COPY_ATTR(write_bytecode); - COPY_ATTR(verbose); - COPY_ATTR(quiet); - COPY_ATTR(user_site_directory); - COPY_ATTR(configure_c_stdio); - COPY_ATTR(buffered_stdio); - COPY_WSTR_ATTR(filesystem_encoding); - COPY_WSTR_ATTR(filesystem_errors); - COPY_WSTR_ATTR(stdio_encoding); - COPY_WSTR_ATTR(stdio_errors); -#ifdef MS_WINDOWS - COPY_ATTR(legacy_windows_stdio); -#endif - COPY_ATTR(skip_source_first_line); - COPY_WSTR_ATTR(run_command); - COPY_WSTR_ATTR(run_module); - COPY_WSTR_ATTR(run_filename); - COPY_WSTR_ATTR(check_hash_pycs_mode); - COPY_ATTR(pathconfig_warnings); - COPY_ATTR(_init_main); - COPY_ATTR(use_frozen_modules); - COPY_ATTR(safe_path); - COPY_WSTRLIST(orig_argv); - COPY_ATTR(_is_python_build); - COPY_ATTR(int_max_str_digits); - -#undef COPY_ATTR -#undef COPY_WSTR_ATTR -#undef COPY_WSTRLIST + PyStatus status; + const PyConfigSpec *spec = PYCONFIG_SPEC; + for (; spec->name != NULL; spec++) { + char *member = (char *)config + spec->offset; + char *member2 = (char *)config2 + spec->offset; + switch (spec->type) { + case PyConfig_MEMBER_INT: + case PyConfig_MEMBER_UINT: + { + *(int*)member = *(int*)member2; + break; + } + case PyConfig_MEMBER_ULONG: + { + *(unsigned long*)member = *(unsigned long*)member2; + break; + } + case PyConfig_MEMBER_WSTR: + case PyConfig_MEMBER_WSTR_OPT: + { + const wchar_t *str = *(const wchar_t**)member2; + status = PyConfig_SetString(config, (wchar_t**)member, str); + if (_PyStatus_EXCEPTION(status)) { + return status; + } + break; + } + case PyConfig_MEMBER_WSTR_LIST: + { + if (_PyWideStringList_Copy((PyWideStringList*)member, + (const PyWideStringList*)member2) < 0) { + return _PyStatus_NO_MEMORY(); + } + break; + } + default: + Py_UNREACHABLE(); + } + } return _PyStatus_OK(); } @@ -954,118 +1052,69 @@ _PyConfig_AsDict(const PyConfig *config) return NULL; } -#define SET_ITEM(KEY, EXPR) \ - do { \ - PyObject *obj = (EXPR); \ - if (obj == NULL) { \ - goto fail; \ - } \ - int res = PyDict_SetItemString(dict, (KEY), obj); \ - Py_DECREF(obj); \ - if (res < 0) { \ - goto fail; \ - } \ - } while (0) -#define SET_ITEM_INT(ATTR) \ - SET_ITEM(#ATTR, PyLong_FromLong(config->ATTR)) -#define SET_ITEM_UINT(ATTR) \ - SET_ITEM(#ATTR, PyLong_FromUnsignedLong(config->ATTR)) -#define FROM_WSTRING(STR) \ - ((STR != NULL) ? \ - PyUnicode_FromWideChar(STR, -1) \ - : Py_NewRef(Py_None)) -#define SET_ITEM_WSTR(ATTR) \ - SET_ITEM(#ATTR, FROM_WSTRING(config->ATTR)) -#define SET_ITEM_WSTRLIST(LIST) \ - SET_ITEM(#LIST, _PyWideStringList_AsList(&config->LIST)) - - SET_ITEM_INT(_config_init); - SET_ITEM_INT(isolated); - SET_ITEM_INT(use_environment); - SET_ITEM_INT(dev_mode); - SET_ITEM_INT(install_signal_handlers); - SET_ITEM_INT(use_hash_seed); - 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); - SET_ITEM_INT(dump_refs); - SET_ITEM_INT(malloc_stats); - SET_ITEM_WSTR(filesystem_encoding); - SET_ITEM_WSTR(filesystem_errors); - SET_ITEM_WSTR(pycache_prefix); - SET_ITEM_WSTR(program_name); - SET_ITEM_INT(parse_argv); - SET_ITEM_WSTRLIST(argv); - SET_ITEM_WSTRLIST(xoptions); - SET_ITEM_WSTRLIST(warnoptions); - SET_ITEM_WSTR(pythonpath_env); - SET_ITEM_WSTR(home); - SET_ITEM_INT(module_search_paths_set); - SET_ITEM_WSTRLIST(module_search_paths); - SET_ITEM_WSTR(stdlib_dir); - SET_ITEM_WSTR(executable); - SET_ITEM_WSTR(base_executable); - SET_ITEM_WSTR(prefix); - SET_ITEM_WSTR(base_prefix); - SET_ITEM_WSTR(exec_prefix); - SET_ITEM_WSTR(base_exec_prefix); - SET_ITEM_WSTR(platlibdir); - SET_ITEM_INT(site_import); - SET_ITEM_INT(bytes_warning); - SET_ITEM_INT(warn_default_encoding); - SET_ITEM_INT(inspect); - SET_ITEM_INT(interactive); - SET_ITEM_INT(optimization_level); - SET_ITEM_INT(parser_debug); - SET_ITEM_INT(write_bytecode); - SET_ITEM_INT(verbose); - SET_ITEM_INT(quiet); - SET_ITEM_INT(user_site_directory); - SET_ITEM_INT(configure_c_stdio); - SET_ITEM_INT(buffered_stdio); - SET_ITEM_WSTR(stdio_encoding); - SET_ITEM_WSTR(stdio_errors); -#ifdef MS_WINDOWS - SET_ITEM_INT(legacy_windows_stdio); -#endif - SET_ITEM_INT(skip_source_first_line); - SET_ITEM_WSTR(run_command); - SET_ITEM_WSTR(run_module); - SET_ITEM_WSTR(run_filename); - SET_ITEM_INT(_install_importlib); - SET_ITEM_WSTR(check_hash_pycs_mode); - SET_ITEM_INT(pathconfig_warnings); - SET_ITEM_INT(_init_main); - SET_ITEM_WSTRLIST(orig_argv); - SET_ITEM_INT(use_frozen_modules); - SET_ITEM_INT(safe_path); - SET_ITEM_INT(_is_python_build); - SET_ITEM_INT(int_max_str_digits); + const PyConfigSpec *spec = PYCONFIG_SPEC; + for (; spec->name != NULL; spec++) { + char *member = (char *)config + spec->offset; + PyObject *obj; + switch (spec->type) { + case PyConfig_MEMBER_INT: + case PyConfig_MEMBER_UINT: + { + int value = *(int*)member; + obj = PyLong_FromLong(value); + break; + } + case PyConfig_MEMBER_ULONG: + { + unsigned long value = *(unsigned long*)member; + obj = PyLong_FromUnsignedLong(value); + break; + } + case PyConfig_MEMBER_WSTR: + case PyConfig_MEMBER_WSTR_OPT: + { + const wchar_t *wstr = *(const wchar_t**)member; + if (wstr != NULL) { + obj = PyUnicode_FromWideChar(wstr, -1); + } + else { + obj = Py_NewRef(Py_None); + } + break; + } + case PyConfig_MEMBER_WSTR_LIST: + { + const PyWideStringList *list = (const PyWideStringList*)member; + obj = _PyWideStringList_AsList(list); + break; + } + default: + Py_UNREACHABLE(); + } + if (obj == NULL) { + Py_DECREF(dict); + return NULL; + } + int res = PyDict_SetItemString(dict, spec->name, obj); + Py_DECREF(obj); + if (res < 0) { + Py_DECREF(dict); + return NULL; + } + } return dict; - -fail: - Py_DECREF(dict); - return NULL; - -#undef FROM_WSTRING -#undef SET_ITEM -#undef SET_ITEM_INT -#undef SET_ITEM_UINT -#undef SET_ITEM_WSTR -#undef SET_ITEM_WSTRLIST } static PyObject* config_dict_get(PyObject *dict, const char *name) { - PyObject *item = _PyDict_GetItemStringWithError(dict, name); - if (item == NULL && !PyErr_Occurred()) { + PyObject *item; + if (PyDict_GetItemStringRef(dict, name, &item) < 0) { + return NULL; + } + if (item == NULL) { PyErr_Format(PyExc_ValueError, "missing config key: %s", name); return NULL; } @@ -1094,7 +1143,8 @@ config_dict_get_int(PyObject *dict, const char *name, int *result) if (item == NULL) { return -1; } - int value = _PyLong_AsInt(item); + int value = PyLong_AsInt(item); + Py_DECREF(item); if (value == -1 && PyErr_Occurred()) { if (PyErr_ExceptionMatches(PyExc_TypeError)) { config_dict_invalid_type(name); @@ -1117,6 +1167,7 @@ config_dict_get_ulong(PyObject *dict, const char *name, unsigned long *result) return -1; } unsigned long value = PyLong_AsUnsignedLong(item); + Py_DECREF(item); if (value == (unsigned long)-1 && PyErr_Occurred()) { if (PyErr_ExceptionMatches(PyExc_TypeError)) { config_dict_invalid_type(name); @@ -1139,27 +1190,33 @@ config_dict_get_wstr(PyObject *dict, const char *name, PyConfig *config, if (item == NULL) { return -1; } + PyStatus status; if (item == Py_None) { status = PyConfig_SetString(config, result, NULL); } else if (!PyUnicode_Check(item)) { config_dict_invalid_type(name); - return -1; + goto error; } else { wchar_t *wstr = PyUnicode_AsWideCharString(item, NULL); if (wstr == NULL) { - return -1; + goto error; } status = PyConfig_SetString(config, result, wstr); PyMem_Free(wstr); } if (_PyStatus_EXCEPTION(status)) { PyErr_NoMemory(); - return -1; + goto error; } + Py_DECREF(item); return 0; + +error: + Py_DECREF(item); + return -1; } @@ -1173,6 +1230,7 @@ config_dict_get_wstrlist(PyObject *dict, const char *name, PyConfig *config, } if (!PyList_CheckExact(list)) { + Py_DECREF(list); config_dict_invalid_type(name); return -1; } @@ -1206,10 +1264,12 @@ config_dict_get_wstrlist(PyObject *dict, const char *name, PyConfig *config, goto error; } _PyWideStringList_Clear(&wstrlist); + Py_DECREF(list); return 0; error: _PyWideStringList_Clear(&wstrlist); + Py_DECREF(list); return -1; } @@ -1222,128 +1282,81 @@ _PyConfig_FromDict(PyConfig *config, PyObject *dict) return -1; } -#define CHECK_VALUE(NAME, TEST) \ - if (!(TEST)) { \ - config_dict_invalid_value(NAME); \ - return -1; \ + const PyConfigSpec *spec = PYCONFIG_SPEC; + for (; spec->name != NULL; spec++) { + char *member = (char *)config + spec->offset; + switch (spec->type) { + case PyConfig_MEMBER_INT: + if (config_dict_get_int(dict, spec->name, (int*)member) < 0) { + return -1; + } + break; + case PyConfig_MEMBER_UINT: + { + int value; + if (config_dict_get_int(dict, spec->name, &value) < 0) { + return -1; + } + if (value < 0) { + config_dict_invalid_value(spec->name); + return -1; + } + *(int*)member = value; + break; + } + case PyConfig_MEMBER_ULONG: + { + if (config_dict_get_ulong(dict, spec->name, + (unsigned long*)member) < 0) { + return -1; + } + break; + } + case PyConfig_MEMBER_WSTR: + { + wchar_t **wstr = (wchar_t**)member; + if (config_dict_get_wstr(dict, spec->name, config, wstr) < 0) { + return -1; + } + if (*wstr == NULL) { + config_dict_invalid_value(spec->name); + return -1; + } + break; + } + case PyConfig_MEMBER_WSTR_OPT: + { + wchar_t **wstr = (wchar_t**)member; + if (config_dict_get_wstr(dict, spec->name, config, wstr) < 0) { + return -1; + } + break; + } + case PyConfig_MEMBER_WSTR_LIST: + { + if (config_dict_get_wstrlist(dict, spec->name, config, + (PyWideStringList*)member) < 0) { + return -1; + } + break; + } + default: + Py_UNREACHABLE(); + } } -#define GET_UINT(KEY) \ - do { \ - if (config_dict_get_int(dict, #KEY, &config->KEY) < 0) { \ - return -1; \ - } \ - CHECK_VALUE(#KEY, config->KEY >= 0); \ - } while (0) -#define GET_INT(KEY) \ - do { \ - if (config_dict_get_int(dict, #KEY, &config->KEY) < 0) { \ - return -1; \ - } \ - } while (0) -#define GET_WSTR(KEY) \ - do { \ - if (config_dict_get_wstr(dict, #KEY, config, &config->KEY) < 0) { \ - return -1; \ - } \ - CHECK_VALUE(#KEY, config->KEY != NULL); \ - } while (0) -#define GET_WSTR_OPT(KEY) \ - do { \ - if (config_dict_get_wstr(dict, #KEY, config, &config->KEY) < 0) { \ - return -1; \ - } \ - } while (0) -#define GET_WSTRLIST(KEY) \ - do { \ - if (config_dict_get_wstrlist(dict, #KEY, config, &config->KEY) < 0) { \ - return -1; \ - } \ - } while (0) - GET_UINT(_config_init); - CHECK_VALUE("_config_init", - config->_config_init == _PyConfig_INIT_COMPAT - || config->_config_init == _PyConfig_INIT_PYTHON - || config->_config_init == _PyConfig_INIT_ISOLATED); - GET_UINT(isolated); - GET_UINT(use_environment); - GET_UINT(dev_mode); - GET_UINT(install_signal_handlers); - GET_UINT(use_hash_seed); - if (config_dict_get_ulong(dict, "hash_seed", &config->hash_seed) < 0) { + if (!(config->_config_init == _PyConfig_INIT_COMPAT + || config->_config_init == _PyConfig_INIT_PYTHON + || config->_config_init == _PyConfig_INIT_ISOLATED)) + { + config_dict_invalid_value("_config_init"); + return -1; + } + + if (config->hash_seed > MAX_HASH_SEED) { + config_dict_invalid_value("hash_seed"); return -1; } - 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); - GET_UINT(dump_refs); - GET_UINT(malloc_stats); - GET_WSTR(filesystem_encoding); - GET_WSTR(filesystem_errors); - GET_WSTR_OPT(pycache_prefix); - GET_UINT(parse_argv); - GET_WSTRLIST(orig_argv); - GET_WSTRLIST(argv); - GET_WSTRLIST(xoptions); - GET_WSTRLIST(warnoptions); - GET_UINT(site_import); - GET_UINT(bytes_warning); - GET_UINT(warn_default_encoding); - GET_UINT(inspect); - GET_UINT(interactive); - GET_UINT(optimization_level); - GET_UINT(parser_debug); - GET_UINT(write_bytecode); - GET_UINT(verbose); - GET_UINT(quiet); - GET_UINT(user_site_directory); - GET_UINT(configure_c_stdio); - GET_UINT(buffered_stdio); - GET_WSTR(stdio_encoding); - GET_WSTR(stdio_errors); -#ifdef MS_WINDOWS - GET_UINT(legacy_windows_stdio); -#endif - GET_WSTR(check_hash_pycs_mode); - - GET_UINT(pathconfig_warnings); - GET_WSTR(program_name); - GET_WSTR_OPT(pythonpath_env); - GET_WSTR_OPT(home); - GET_WSTR(platlibdir); - - // Path configuration output - GET_UINT(module_search_paths_set); - GET_WSTRLIST(module_search_paths); - GET_WSTR_OPT(stdlib_dir); - GET_WSTR_OPT(executable); - GET_WSTR_OPT(base_executable); - GET_WSTR_OPT(prefix); - GET_WSTR_OPT(base_prefix); - GET_WSTR_OPT(exec_prefix); - GET_WSTR_OPT(base_exec_prefix); - - GET_UINT(skip_source_first_line); - GET_WSTR_OPT(run_command); - GET_WSTR_OPT(run_module); - GET_WSTR_OPT(run_filename); - - GET_UINT(_install_importlib); - GET_UINT(_init_main); - GET_UINT(use_frozen_modules); - GET_UINT(safe_path); - GET_UINT(_is_python_build); - GET_INT(int_max_str_digits); - -#undef CHECK_VALUE -#undef GET_UINT -#undef GET_INT -#undef GET_WSTR -#undef GET_WSTR_OPT return 0; } @@ -1634,6 +1647,45 @@ config_read_env_vars(PyConfig *config) return _PyStatus_OK(); } +static PyStatus +config_init_cpu_count(PyConfig *config) +{ + const char *env = config_get_env(config, "PYTHON_CPU_COUNT"); + if (env) { + int cpu_count = -1; + if (strcmp(env, "default") == 0) { + cpu_count = -1; + } + else if (_Py_str_to_int(env, &cpu_count) < 0 || cpu_count < 1) { + goto error; + } + config->cpu_count = cpu_count; + } + + const wchar_t *xoption = config_get_xoption(config, L"cpu_count"); + if (xoption) { + int cpu_count = -1; + const wchar_t *sep = wcschr(xoption, L'='); + if (sep) { + if (wcscmp(sep + 1, L"default") == 0) { + cpu_count = -1; + } + else if (config_wstr_to_int(sep + 1, &cpu_count) < 0 || cpu_count < 1) { + goto error; + } + } + else { + goto error; + } + config->cpu_count = cpu_count; + } + return _PyStatus_OK(); + +error: + return _PyStatus_ERR("-X cpu_count=n option: n is missing or an invalid number, " + "n must be greater than 0"); +} + static PyStatus config_init_perf_profiling(PyConfig *config) { @@ -1774,6 +1826,36 @@ config_init_pycache_prefix(PyConfig *config) } +#ifdef Py_DEBUG +static PyStatus +config_init_run_presite(PyConfig *config) +{ + assert(config->run_presite == NULL); + + const wchar_t *xoption = config_get_xoption(config, L"presite"); + if (xoption) { + const wchar_t *sep = wcschr(xoption, L'='); + if (sep && wcslen(sep) > 1) { + config->run_presite = _PyMem_RawWcsdup(sep + 1); + if (config->run_presite == NULL) { + return _PyStatus_NO_MEMORY(); + } + } + else { + // PYTHON_PRESITE env var ignored + // if "-X presite=" option is used + config->run_presite = NULL; + } + return _PyStatus_OK(); + } + + return CONFIG_GET_ENV_DUP(config, &config->run_presite, + L"PYTHON_PRESITE", + "PYTHON_PRESITE"); +} +#endif + + static PyStatus config_read_complex_options(PyConfig *config) { @@ -1816,12 +1898,29 @@ config_read_complex_options(PyConfig *config) } } + if (config->cpu_count < 0) { + status = config_init_cpu_count(config); + if (_PyStatus_EXCEPTION(status)) { + return status; + } + } + if (config->pycache_prefix == NULL) { status = config_init_pycache_prefix(config); if (_PyStatus_EXCEPTION(status)) { return status; } } + +#ifdef Py_DEBUG + if (config->run_presite == NULL) { + status = config_init_run_presite(config); + if (_PyStatus_EXCEPTION(status)) { + return status; + } + } +#endif + return _PyStatus_OK(); } @@ -2039,6 +2138,19 @@ config_init_import(PyConfig *config, int compute_path_config) return status; } + const char *env = config_get_env(config, "PYTHON_FROZEN_MODULES"); + if (env == NULL) { + } + else if (strcmp(env, "on") == 0) { + config->use_frozen_modules = 1; + } + else if (strcmp(env, "off") == 0) { + config->use_frozen_modules = 0; + } else { + return PyStatus_Error("bad value for PYTHON_FROZEN_MODULES " + "(expected \"on\" or \"off\")"); + } + /* -X frozen_modules=[on|off] */ const wchar_t *value = config_get_xoption_value(config, L"frozen_modules"); if (value == NULL) { @@ -2089,7 +2201,13 @@ config_read(PyConfig *config, int compute_path_config) #ifdef Py_STATS if (config_get_xoption(config, L"pystats")) { - _py_stats = &_py_stats_struct; + config->_pystats = 1; + } + else if (config_get_env(config, "PYTHONSTATS")) { + config->_pystats = 1; + } + if (config->_pystats < 0) { + config->_pystats = 0; } #endif @@ -2227,6 +2345,13 @@ _PyConfig_Write(const PyConfig *config, _PyRuntimeState *runtime) { return _PyStatus_NO_MEMORY(); } + +#ifdef Py_STATS + if (config->_pystats) { + _Py_StatsOn(); + } +#endif + return _PyStatus_OK(); } @@ -3057,6 +3182,7 @@ _Py_DumpPathConfig(PyThreadState *tstate) PySys_WriteStderr(" import site = %i\n", config->site_import); PySys_WriteStderr(" is in build tree = %i\n", config->_is_python_build); DUMP_CONFIG("stdlib dir", stdlib_dir); + DUMP_CONFIG("sys.path[0]", sys_path_0); #undef DUMP_CONFIG #define DUMP_SYS(NAME) \ diff --git a/Python/instrumentation.c b/Python/instrumentation.c index 123c20dfe1a99b..533aece210202b 100644 --- a/Python/instrumentation.c +++ b/Python/instrumentation.c @@ -1,29 +1,27 @@ #include "Python.h" + +#include "opcode_ids.h" + +#include "pycore_bitutils.h" // _Py_popcount32 #include "pycore_call.h" +#include "pycore_ceval.h" // _PY_EVAL_EVENTS_BITS +#include "pycore_code.h" // _PyCode_Clear_Executors() #include "pycore_frame.h" #include "pycore_interp.h" #include "pycore_long.h" #include "pycore_modsupport.h" // _PyModule_CreateInitialized() #include "pycore_namespace.h" #include "pycore_object.h" -#include "pycore_opcode.h" +#include "pycore_opcode_metadata.h" // IS_VALID_OPCODE, _PyOpcode_Caches #include "pycore_pyerrors.h" #include "pycore_pystate.h" // _PyInterpreterState_GET() /* Uncomment this to dump debugging output when assertions fail */ // #define INSTRUMENT_DEBUG 1 -PyObject _PyInstrumentation_DISABLE = -{ - .ob_refcnt = _Py_IMMORTAL_REFCNT, - .ob_type = &PyBaseObject_Type -}; +PyObject _PyInstrumentation_DISABLE = _PyObject_HEAD_INIT(&PyBaseObject_Type); -PyObject _PyInstrumentation_MISSING = -{ - .ob_refcnt = _Py_IMMORTAL_REFCNT, - .ob_type = &PyBaseObject_Type -}; +PyObject _PyInstrumentation_MISSING = _PyObject_HEAD_INIT(&PyBaseObject_Type); static const int8_t EVENT_FOR_OPCODE[256] = { [RETURN_CONST] = PY_MONITORING_EVENT_PY_RETURN, @@ -32,6 +30,8 @@ static const int8_t EVENT_FOR_OPCODE[256] = { [INSTRUMENTED_RETURN_VALUE] = PY_MONITORING_EVENT_PY_RETURN, [CALL] = PY_MONITORING_EVENT_CALL, [INSTRUMENTED_CALL] = PY_MONITORING_EVENT_CALL, + [CALL_KW] = PY_MONITORING_EVENT_CALL, + [INSTRUMENTED_CALL_KW] = PY_MONITORING_EVENT_CALL, [CALL_FUNCTION_EX] = PY_MONITORING_EVENT_CALL, [INSTRUMENTED_CALL_FUNCTION_EX] = PY_MONITORING_EVENT_CALL, [LOAD_SUPER_ATTR] = PY_MONITORING_EVENT_CALL, @@ -64,6 +64,7 @@ static const uint8_t DE_INSTRUMENT[256] = { [INSTRUMENTED_RETURN_VALUE] = RETURN_VALUE, [INSTRUMENTED_RETURN_CONST] = RETURN_CONST, [INSTRUMENTED_CALL] = CALL, + [INSTRUMENTED_CALL_KW] = CALL_KW, [INSTRUMENTED_CALL_FUNCTION_EX] = CALL_FUNCTION_EX, [INSTRUMENTED_YIELD_VALUE] = YIELD_VALUE, [INSTRUMENTED_JUMP_FORWARD] = JUMP_FORWARD, @@ -85,6 +86,8 @@ static const uint8_t INSTRUMENTED_OPCODES[256] = { [INSTRUMENTED_RETURN_VALUE] = INSTRUMENTED_RETURN_VALUE, [CALL] = INSTRUMENTED_CALL, [INSTRUMENTED_CALL] = INSTRUMENTED_CALL, + [CALL_KW] = INSTRUMENTED_CALL_KW, + [INSTRUMENTED_CALL_KW] = INSTRUMENTED_CALL_KW, [CALL_FUNCTION_EX] = INSTRUMENTED_CALL_FUNCTION_EX, [INSTRUMENTED_CALL_FUNCTION_EX] = INSTRUMENTED_CALL_FUNCTION_EX, [YIELD_VALUE] = INSTRUMENTED_YIELD_VALUE, @@ -120,7 +123,7 @@ static inline bool opcode_has_event(int opcode) { return ( - opcode < INSTRUMENTED_LINE && + opcode != INSTRUMENTED_LINE && INSTRUMENTED_OPCODES[opcode] > 0 ); } @@ -135,9 +138,9 @@ is_instrumented(int opcode) #ifndef NDEBUG static inline bool -monitors_equals(_Py_Monitors a, _Py_Monitors b) +monitors_equals(_Py_LocalMonitors a, _Py_LocalMonitors b) { - for (int i = 0; i < _PY_MONITORING_UNGROUPED_EVENTS; i++) { + for (int i = 0; i < _PY_MONITORING_LOCAL_EVENTS; i++) { if (a.tools[i] != b.tools[i]) { return false; } @@ -146,42 +149,47 @@ monitors_equals(_Py_Monitors a, _Py_Monitors b) } #endif -static inline _Py_Monitors -monitors_sub(_Py_Monitors a, _Py_Monitors b) +static inline _Py_LocalMonitors +monitors_sub(_Py_LocalMonitors a, _Py_LocalMonitors b) { - _Py_Monitors res; - for (int i = 0; i < _PY_MONITORING_UNGROUPED_EVENTS; i++) { + _Py_LocalMonitors res; + for (int i = 0; i < _PY_MONITORING_LOCAL_EVENTS; i++) { res.tools[i] = a.tools[i] & ~b.tools[i]; } return res; } #ifndef NDEBUG -static inline _Py_Monitors -monitors_and(_Py_Monitors a, _Py_Monitors b) +static inline _Py_LocalMonitors +monitors_and(_Py_LocalMonitors a, _Py_LocalMonitors b) { - _Py_Monitors res; - for (int i = 0; i < _PY_MONITORING_UNGROUPED_EVENTS; i++) { + _Py_LocalMonitors res; + for (int i = 0; i < _PY_MONITORING_LOCAL_EVENTS; i++) { res.tools[i] = a.tools[i] & b.tools[i]; } return res; } #endif -static inline _Py_Monitors -monitors_or(_Py_Monitors a, _Py_Monitors b) +/* The union of the *local* events in a and b. + * Global events like RAISE are ignored. + * Used for instrumentation, as only local + * events get instrumented. + */ +static inline _Py_LocalMonitors +local_union(_Py_GlobalMonitors a, _Py_LocalMonitors b) { - _Py_Monitors res; - for (int i = 0; i < _PY_MONITORING_UNGROUPED_EVENTS; i++) { + _Py_LocalMonitors res; + for (int i = 0; i < _PY_MONITORING_LOCAL_EVENTS; i++) { res.tools[i] = a.tools[i] | b.tools[i]; } return res; } static inline bool -monitors_are_empty(_Py_Monitors m) +monitors_are_empty(_Py_LocalMonitors m) { - for (int i = 0; i < _PY_MONITORING_UNGROUPED_EVENTS; i++) { + for (int i = 0; i < _PY_MONITORING_LOCAL_EVENTS; i++) { if (m.tools[i]) { return false; } @@ -190,9 +198,9 @@ monitors_are_empty(_Py_Monitors m) } static inline bool -multiple_tools(_Py_Monitors *m) +multiple_tools(_Py_LocalMonitors *m) { - for (int i = 0; i < _PY_MONITORING_UNGROUPED_EVENTS; i++) { + for (int i = 0; i < _PY_MONITORING_LOCAL_EVENTS; i++) { if (_Py_popcount32(m->tools[i]) > 1) { return true; } @@ -201,7 +209,19 @@ multiple_tools(_Py_Monitors *m) } static inline _PyMonitoringEventSet -get_events(_Py_Monitors *m, int tool_id) +get_local_events(_Py_LocalMonitors *m, int tool_id) +{ + _PyMonitoringEventSet result = 0; + for (int e = 0; e < _PY_MONITORING_LOCAL_EVENTS; e++) { + if ((m->tools[e] >> tool_id) & 1) { + result |= (1 << e); + } + } + return result; +} + +static inline _PyMonitoringEventSet +get_events(_Py_GlobalMonitors *m, int tool_id) { _PyMonitoringEventSet result = 0; for (int e = 0; e < _PY_MONITORING_UNGROUPED_EVENTS; e++) { @@ -279,7 +299,7 @@ _PyInstruction_GetLength(PyCodeObject *code, int offset) if (opcode == ENTER_EXECUTOR) { int exec_index = _PyCode_CODE(code)[offset].op.arg; _PyExecutorObject *exec = code->co_executors->executors[exec_index]; - opcode = exec->vm_data.opcode; + opcode = _PyOpcode_Deopt[exec->vm_data.opcode]; } assert(opcode != ENTER_EXECUTOR); @@ -343,7 +363,7 @@ dump_instrumentation_data_per_instruction(PyCodeObject *code, _PyCoMonitoringDat } static void -dump_monitors(const char *prefix, _Py_Monitors monitors, FILE*out) +dump_global_monitors(const char *prefix, _Py_GlobalMonitors monitors, FILE*out) { fprintf(out, "%s monitors:\n", prefix); for (int event = 0; event < _PY_MONITORING_UNGROUPED_EVENTS; event++) { @@ -351,37 +371,13 @@ dump_monitors(const char *prefix, _Py_Monitors monitors, FILE*out) } } -/* Like _Py_GetBaseOpcode but without asserts. - * Does its best to give the right answer, but won't abort - * if something is wrong */ -static int -get_base_opcode_best_attempt(PyCodeObject *code, int offset) +static void +dump_local_monitors(const char *prefix, _Py_LocalMonitors monitors, FILE*out) { - int opcode = _Py_OPCODE(_PyCode_CODE(code)[offset]); - if (INSTRUMENTED_OPCODES[opcode] != opcode) { - /* Not instrumented */ - return _PyOpcode_Deopt[opcode] == 0 ? opcode : _PyOpcode_Deopt[opcode]; - } - if (opcode == INSTRUMENTED_INSTRUCTION) { - if (code->_co_monitoring->per_instruction_opcodes[offset] == 0) { - return opcode; - } - opcode = code->_co_monitoring->per_instruction_opcodes[offset]; - } - if (opcode == INSTRUMENTED_LINE) { - if (code->_co_monitoring->lines[offset].original_opcode == 0) { - return opcode; - } - opcode = code->_co_monitoring->lines[offset].original_opcode; - } - int deinstrumented = DE_INSTRUMENT[opcode]; - if (deinstrumented) { - return deinstrumented; - } - if (_PyOpcode_Deopt[opcode] == 0) { - return opcode; + fprintf(out, "%s monitors:\n", prefix); + for (int event = 0; event < _PY_MONITORING_LOCAL_EVENTS; event++) { + fprintf(out, " Event %d: Tools %x\n", event, monitors.tools[event]); } - return _PyOpcode_Deopt[opcode]; } /* No error checking -- Don't use this for anything but experimental debugging */ @@ -396,9 +392,9 @@ dump_instrumentation_data(PyCodeObject *code, int star, FILE*out) fprintf(out, "NULL\n"); return; } - dump_monitors("Global", _PyInterpreterState_GET()->monitors, out); - dump_monitors("Code", data->local_monitors, out); - dump_monitors("Active", data->active_monitors, out); + dump_global_monitors("Global", _PyInterpreterState_GET()->monitors, out); + dump_local_monitors("Code", data->local_monitors, out); + dump_local_monitors("Active", data->active_monitors, out); int code_len = (int)Py_SIZE(code); bool starred = false; for (int i = 0; i < code_len; i += _PyInstruction_GetLength(code, i)) { @@ -437,11 +433,13 @@ dump_instrumentation_data(PyCodeObject *code, int star, FILE*out) static bool valid_opcode(int opcode) { - if (opcode > 0 && + if (opcode == INSTRUMENTED_LINE) { + return true; + } + if (IS_VALID_OPCODE(opcode) && + opcode != CACHE && opcode != RESERVED && - opcode < 255 && - _PyOpcode_OpName[opcode] && - _PyOpcode_OpName[opcode][0] != '<') + opcode < 255) { return true; } @@ -455,18 +453,23 @@ sanity_check_instrumentation(PyCodeObject *code) if (data == NULL) { return; } - _Py_Monitors active_monitors = _PyInterpreterState_GET()->monitors; + _Py_GlobalMonitors global_monitors = _PyInterpreterState_GET()->monitors; + _Py_LocalMonitors active_monitors; if (code->_co_monitoring) { - _Py_Monitors local_monitors = code->_co_monitoring->local_monitors; - active_monitors = monitors_or(active_monitors, local_monitors); + _Py_LocalMonitors local_monitors = code->_co_monitoring->local_monitors; + active_monitors = local_union(global_monitors, local_monitors); + } + else { + _Py_LocalMonitors empty = (_Py_LocalMonitors) { 0 }; + active_monitors = local_union(global_monitors, empty); } assert(monitors_equals( code->_co_monitoring->active_monitors, - active_monitors) - ); + active_monitors)); int code_len = (int)Py_SIZE(code); for (int i = 0; i < code_len;) { - int opcode = _PyCode_CODE(code)[i].op.code; + _Py_CODEUNIT *instr = &_PyCode_CODE(code)[i]; + int opcode = instr->op.code; int base_opcode = _Py_GetBaseOpcode(code, i); CHECK(valid_opcode(opcode)); CHECK(valid_opcode(base_opcode)); @@ -486,23 +489,30 @@ sanity_check_instrumentation(PyCodeObject *code) opcode = data->lines[i].original_opcode; CHECK(opcode != END_FOR); CHECK(opcode != RESUME); + CHECK(opcode != RESUME_CHECK); CHECK(opcode != INSTRUMENTED_RESUME); if (!is_instrumented(opcode)) { CHECK(_PyOpcode_Deopt[opcode] == opcode); } CHECK(opcode != INSTRUMENTED_LINE); } - else if (data->lines && !is_instrumented(opcode)) { - CHECK(data->lines[i].original_opcode == 0 || - data->lines[i].original_opcode == base_opcode || - DE_INSTRUMENT[data->lines[i].original_opcode] == base_opcode); + else if (data->lines) { + /* If original_opcode is INSTRUMENTED_INSTRUCTION + * *and* we are executing a INSTRUMENTED_LINE instruction + * that has de-instrumented itself, then we will execute + * an invalid INSTRUMENTED_INSTRUCTION */ + CHECK(data->lines[i].original_opcode != INSTRUMENTED_INSTRUCTION); + } + if (opcode == INSTRUMENTED_INSTRUCTION) { + CHECK(data->per_instruction_opcodes[i] != 0); + opcode = data->per_instruction_opcodes[i]; } if (is_instrumented(opcode)) { CHECK(DE_INSTRUMENT[opcode] == base_opcode); int event = EVENT_FOR_OPCODE[DE_INSTRUMENT[opcode]]; if (event < 0) { /* RESUME fixup */ - event = _PyCode_CODE(code)[i].op.arg; + event = instr->op.arg ? 1: 0; } CHECK(active_monitors.tools[event] != 0); } @@ -564,6 +574,7 @@ de_instrument(PyCodeObject *code, int i, int event) _Py_CODEUNIT *instr = &_PyCode_CODE(code)[i]; uint8_t *opcode_ptr = &instr->op.code; int opcode = *opcode_ptr; + assert(opcode != ENTER_EXECUTOR); if (opcode == INSTRUMENTED_LINE) { opcode_ptr = &code->_co_monitoring->lines[i].original_opcode; opcode = *opcode_ptr; @@ -587,30 +598,30 @@ static void de_instrument_line(PyCodeObject *code, int i) { _Py_CODEUNIT *instr = &_PyCode_CODE(code)[i]; - uint8_t *opcode_ptr = &instr->op.code; - int opcode =*opcode_ptr; + int opcode = instr->op.code; if (opcode != INSTRUMENTED_LINE) { return; } _PyCoLineInstrumentationData *lines = &code->_co_monitoring->lines[i]; int original_opcode = lines->original_opcode; + if (original_opcode == INSTRUMENTED_INSTRUCTION) { + lines->original_opcode = code->_co_monitoring->per_instruction_opcodes[i]; + } CHECK(original_opcode != 0); CHECK(original_opcode == _PyOpcode_Deopt[original_opcode]); - *opcode_ptr = instr->op.code = original_opcode; + instr->op.code = original_opcode; if (_PyOpcode_Caches[original_opcode]) { instr[1].cache = adaptive_counter_warmup(); } - assert(*opcode_ptr != INSTRUMENTED_LINE); assert(instr->op.code != INSTRUMENTED_LINE); } - static void de_instrument_per_instruction(PyCodeObject *code, int i) { _Py_CODEUNIT *instr = &_PyCode_CODE(code)[i]; uint8_t *opcode_ptr = &instr->op.code; - int opcode =*opcode_ptr; + int opcode = *opcode_ptr; if (opcode == INSTRUMENTED_LINE) { opcode_ptr = &code->_co_monitoring->lines[i].original_opcode; opcode = *opcode_ptr; @@ -621,10 +632,11 @@ de_instrument_per_instruction(PyCodeObject *code, int i) int original_opcode = code->_co_monitoring->per_instruction_opcodes[i]; CHECK(original_opcode != 0); CHECK(original_opcode == _PyOpcode_Deopt[original_opcode]); - instr->op.code = original_opcode; + *opcode_ptr = original_opcode; if (_PyOpcode_Caches[original_opcode]) { instr[1].cache = adaptive_counter_warmup(); } + assert(*opcode_ptr != INSTRUMENTED_INSTRUCTION); assert(instr->op.code != INSTRUMENTED_INSTRUCTION); /* Keep things clean for sanity check */ code->_co_monitoring->per_instruction_opcodes[i] = 0; @@ -645,7 +657,7 @@ instrument(PyCodeObject *code, int i) if (opcode == INSTRUMENTED_INSTRUCTION) { opcode_ptr = &code->_co_monitoring->per_instruction_opcodes[i]; opcode = *opcode_ptr; - CHECK(!is_instrumented(opcode)); + CHECK(opcode != INSTRUMENTED_INSTRUCTION && opcode != INSTRUMENTED_LINE); CHECK(opcode == _PyOpcode_Deopt[opcode]); } CHECK(opcode != 0); @@ -664,7 +676,7 @@ static void instrument_line(PyCodeObject *code, int i) { uint8_t *opcode_ptr = &_PyCode_CODE(code)[i].op.code; - int opcode =*opcode_ptr; + int opcode = *opcode_ptr; if (opcode == INSTRUMENTED_LINE) { return; } @@ -679,13 +691,14 @@ instrument_per_instruction(PyCodeObject *code, int i) { _Py_CODEUNIT *instr = &_PyCode_CODE(code)[i]; uint8_t *opcode_ptr = &instr->op.code; - int opcode =*opcode_ptr; + int opcode = *opcode_ptr; if (opcode == INSTRUMENTED_LINE) { _PyCoLineInstrumentationData *lines = &code->_co_monitoring->lines[i]; opcode_ptr = &lines->original_opcode; opcode = *opcode_ptr; } if (opcode == INSTRUMENTED_INSTRUCTION) { + assert(code->_co_monitoring->per_instruction_opcodes[i] > 0); return; } CHECK(opcode != 0); @@ -875,17 +888,34 @@ static inline int most_significant_bit(uint8_t bits) { return MOST_SIGNIFICANT_BITS[bits]; } +static uint32_t +global_version(PyInterpreterState *interp) +{ + return interp->ceval.eval_breaker & ~_PY_EVAL_EVENTS_MASK; +} + +static void +set_global_version(PyInterpreterState *interp, uint32_t version) +{ + assert((version & _PY_EVAL_EVENTS_MASK) == 0); + uintptr_t old = _Py_atomic_load_uintptr(&interp->ceval.eval_breaker); + intptr_t new; + do { + new = (old & _PY_EVAL_EVENTS_MASK) | version; + } while (!_Py_atomic_compare_exchange_uintptr(&interp->ceval.eval_breaker, &old, new)); +} + static bool is_version_up_to_date(PyCodeObject *code, PyInterpreterState *interp) { - return interp->monitoring_version == code->_co_instrumentation_version; + return global_version(interp) == code->_co_instrumentation_version; } #ifndef NDEBUG static bool instrumentation_cross_checks(PyInterpreterState *interp, PyCodeObject *code) { - _Py_Monitors expected = monitors_or( + _Py_LocalMonitors expected = local_union( interp->monitors, code->_co_monitoring->local_monitors); return monitors_equals(code->_co_monitoring->active_monitors, expected); @@ -914,12 +944,7 @@ get_tools_for_instruction(PyCodeObject *code, PyInterpreterState *interp, int i, } } else { - if (code->_co_monitoring) { - tools = code->_co_monitoring->active_monitors.tools[event]; - } - else { - tools = interp->monitors.tools[event]; - } + tools = interp->monitors.tools[event]; } return tools; } @@ -961,7 +986,7 @@ call_instrumentation_vector( /* Offset visible to user should be the offset in bytes, as that is the * convention for APIs involving code offsets. */ int bytes_offset = offset * (int)sizeof(_Py_CODEUNIT); - PyObject *offset_obj = PyLong_FromSsize_t(bytes_offset); + PyObject *offset_obj = PyLong_FromLong(bytes_offset); if (offset_obj == NULL) { return -1; } @@ -1040,9 +1065,7 @@ _Py_call_instrumentation_jump( { assert(event == PY_MONITORING_EVENT_JUMP || event == PY_MONITORING_EVENT_BRANCH); - assert(frame->prev_instr == instr); - /* Event should occur after the jump */ - frame->prev_instr = target; + assert(frame->instr_ptr == instr); PyCodeObject *code = _PyFrame_GetCode(frame); int to = (int)(target - _PyCode_CODE(code)); PyObject *to_obj = PyLong_FromLong(to * (int)sizeof(_Py_CODEUNIT)); @@ -1055,12 +1078,10 @@ _Py_call_instrumentation_jump( if (err) { return NULL; } - if (frame->prev_instr != target) { + if (frame->instr_ptr != instr) { /* The callback has caused a jump (by setting the line number) */ - return frame->prev_instr; + return frame->instr_ptr; } - /* Reset prev_instr for INSTRUMENTED_LINE */ - frame->prev_instr = instr; return target; } @@ -1081,16 +1102,6 @@ call_instrumentation_vector_protected( assert(_PyErr_Occurred(tstate)); } -void -_Py_call_instrumentation_exc0( - PyThreadState *tstate, int event, - _PyInterpreterFrame *frame, _Py_CODEUNIT *instr) -{ - assert(_PyErr_Occurred(tstate)); - PyObject *args[3] = { NULL, NULL, NULL }; - call_instrumentation_vector_protected(tstate, event, frame, instr, 2, args); -} - void _Py_call_instrumentation_exc2( PyThreadState *tstate, int event, @@ -1119,7 +1130,6 @@ _Py_Instrumentation_GetLine(PyCodeObject *code, int index) int _Py_call_instrumentation_line(PyThreadState *tstate, _PyInterpreterFrame* frame, _Py_CODEUNIT *instr, _Py_CODEUNIT *prev) { - frame->prev_instr = instr; PyCodeObject *code = _PyFrame_GetCode(frame); assert(is_version_up_to_date(code, tstate->interp)); assert(instrumentation_cross_checks(tstate->interp, code)); @@ -1127,7 +1137,6 @@ _Py_call_instrumentation_line(PyThreadState *tstate, _PyInterpreterFrame* frame, _PyCoMonitoringData *monitoring = code->_co_monitoring; _PyCoLineInstrumentationData *line_data = &monitoring->lines[i]; - uint8_t original_opcode = line_data->original_opcode; if (tstate->tracing) { goto done; } @@ -1135,6 +1144,7 @@ _Py_call_instrumentation_line(PyThreadState *tstate, _PyInterpreterFrame* frame, int8_t line_delta = line_data->line_delta; int line = compute_line(code, i, line_delta); assert(line >= 0); + assert(prev != NULL); int prev_index = (int)(prev - _PyCode_CODE(code)); int prev_line = _Py_Instrumentation_GetLine(code, prev_index); if (prev_line == line) { @@ -1151,14 +1161,46 @@ _Py_call_instrumentation_line(PyThreadState *tstate, _PyInterpreterFrame* frame, (interp->monitors.tools[PY_MONITORING_EVENT_LINE] | code->_co_monitoring->local_monitors.tools[PY_MONITORING_EVENT_LINE] ); - PyObject *line_obj = PyLong_FromSsize_t(line); + /* Special case sys.settrace to avoid boxing the line number, + * only to immediately unbox it. */ + if (tools & (1 << PY_MONITORING_SYS_TRACE_ID)) { + if (tstate->c_tracefunc != NULL && line >= 0) { + PyFrameObject *frame_obj = _PyFrame_GetFrameObject(frame); + if (frame_obj == NULL) { + return -1; + } + if (frame_obj->f_trace_lines) { + /* Need to set tracing and what_event as if using + * the instrumentation call. */ + int old_what = tstate->what_event; + tstate->what_event = PY_MONITORING_EVENT_LINE; + tstate->tracing++; + /* Call c_tracefunc directly, having set the line number. */ + Py_INCREF(frame_obj); + frame_obj->f_lineno = line; + int err = tstate->c_tracefunc(tstate->c_traceobj, frame_obj, PyTrace_LINE, Py_None); + frame_obj->f_lineno = 0; + tstate->tracing--; + tstate->what_event = old_what; + Py_DECREF(frame_obj); + if (err) { + return -1; + } + } + } + tools &= (255 - (1 << PY_MONITORING_SYS_TRACE_ID)); + } + if (tools == 0) { + goto done; + } + PyObject *line_obj = PyLong_FromLong(line); if (line_obj == NULL) { return -1; } PyObject *args[3] = { NULL, (PyObject *)code, line_obj }; - while (tools) { + do { int tool = most_significant_bit(tools); - assert(tool >= 0 && tool < 8); + assert(tool >= 0 && tool < PY_MONITORING_SYS_PROFILE_ID); assert(tools & (1 << tool)); tools &= ~(1 << tool); int res = call_one_instrument(interp, tstate, &args[1], @@ -1176,11 +1218,13 @@ _Py_call_instrumentation_line(PyThreadState *tstate, _PyInterpreterFrame* frame, /* DISABLE */ remove_line_tools(code, i, 1 << tool); } - } + } while (tools); Py_DECREF(line_obj); + uint8_t original_opcode; done: + original_opcode = line_data->original_opcode; assert(original_opcode != 0); - assert(original_opcode < INSTRUMENTED_LINE); + assert(original_opcode != INSTRUMENTED_LINE); assert(_PyOpcode_Deopt[original_opcode] == original_opcode); return original_opcode; } @@ -1205,7 +1249,7 @@ _Py_call_instrumentation_instruction(PyThreadState *tstate, _PyInterpreterFrame* code->_co_monitoring->local_monitors.tools[PY_MONITORING_EVENT_INSTRUCTION] ); int bytes_offset = offset * (int)sizeof(_Py_CODEUNIT); - PyObject *offset_obj = PyLong_FromSsize_t(bytes_offset); + PyObject *offset_obj = PyLong_FromLong(bytes_offset); if (offset_obj == NULL) { return -1; } @@ -1257,9 +1301,13 @@ initialize_tools(PyCodeObject *code) for (int i = 0; i < code_len; i++) { _Py_CODEUNIT *instr = &_PyCode_CODE(code)[i]; int opcode = instr->op.code; + assert(opcode != ENTER_EXECUTOR); if (opcode == INSTRUMENTED_LINE) { opcode = code->_co_monitoring->lines[i].original_opcode; } + if (opcode == INSTRUMENTED_INSTRUCTION) { + opcode = code->_co_monitoring->per_instruction_opcodes[i]; + } bool instrumented = is_instrumented(opcode); if (instrumented) { opcode = DE_INSTRUMENT[opcode]; @@ -1418,7 +1466,7 @@ initialize_lines(PyCodeObject *code) } static void -initialize_line_tools(PyCodeObject *code, _Py_Monitors *all_events) +initialize_line_tools(PyCodeObject *code, _Py_LocalMonitors *all_events) { uint8_t *line_tools = code->_co_monitoring->line_tools; assert(line_tools != NULL); @@ -1438,8 +1486,8 @@ allocate_instrumentation_data(PyCodeObject *code) PyErr_NoMemory(); return -1; } - code->_co_monitoring->local_monitors = (_Py_Monitors){ 0 }; - code->_co_monitoring->active_monitors = (_Py_Monitors){ 0 }; + code->_co_monitoring->local_monitors = (_Py_LocalMonitors){ 0 }; + code->_co_monitoring->active_monitors = (_Py_LocalMonitors){ 0 }; code->_co_monitoring->tools = NULL; code->_co_monitoring->lines = NULL; code->_co_monitoring->line_tools = NULL; @@ -1456,7 +1504,7 @@ update_instrumentation_data(PyCodeObject *code, PyInterpreterState *interp) if (allocate_instrumentation_data(code)) { return -1; } - _Py_Monitors all_events = monitors_or( + _Py_LocalMonitors all_events = local_union( interp->monitors, code->_co_monitoring->local_monitors); bool multitools = multiple_tools(&all_events); @@ -1518,20 +1566,31 @@ _Py_Instrument(PyCodeObject *code, PyInterpreterState *interp) { if (is_version_up_to_date(code, interp)) { assert( - interp->monitoring_version == 0 || + (interp->ceval.eval_breaker & ~_PY_EVAL_EVENTS_MASK) == 0 || instrumentation_cross_checks(interp, code) ); return 0; } + if (code->co_executors != NULL) { + _PyCode_Clear_Executors(code); + } + _Py_Executors_InvalidateDependency(interp, code); int code_len = (int)Py_SIZE(code); + /* Exit early to avoid creating instrumentation + * data for potential statically allocated code + * objects. + * See https://github.com/python/cpython/issues/108390 */ + if (code->co_flags & CO_NO_MONITORING_EVENTS) { + return 0; + } if (update_instrumentation_data(code, interp)) { return -1; } - _Py_Monitors active_events = monitors_or( + _Py_LocalMonitors active_events = local_union( interp->monitors, code->_co_monitoring->local_monitors); - _Py_Monitors new_events; - _Py_Monitors removed_events; + _Py_LocalMonitors new_events; + _Py_LocalMonitors removed_events; bool restarted = interp->last_restart_version > code->_co_instrumentation_version; if (restarted) { @@ -1544,7 +1603,7 @@ _Py_Instrument(PyCodeObject *code, PyInterpreterState *interp) assert(monitors_are_empty(monitors_and(new_events, removed_events))); } code->_co_monitoring->active_monitors = active_events; - code->_co_instrumentation_version = interp->monitoring_version; + code->_co_instrumentation_version = global_version(interp); if (monitors_are_empty(new_events) && monitors_are_empty(removed_events)) { #ifdef INSTRUMENT_DEBUG sanity_check_instrumentation(code); @@ -1555,7 +1614,9 @@ _Py_Instrument(PyCodeObject *code, PyInterpreterState *interp) for (int i = code->_co_firsttraceable; i < code_len; i+= _PyInstruction_GetLength(code, i)) { _Py_CODEUNIT *instr = &_PyCode_CODE(code)[i]; CHECK(instr->op.code != 0); + assert(instr->op.code != ENTER_EXECUTOR); int base_opcode = _Py_GetBaseOpcode(code, i); + assert(base_opcode != ENTER_EXECUTOR); if (opcode_has_event(base_opcode)) { int8_t event; if (base_opcode == RESUME) { @@ -1606,7 +1667,9 @@ _Py_Instrument(PyCodeObject *code, PyInterpreterState *interp) i += _PyInstruction_GetLength(code, i); } } - +#ifdef INSTRUMENT_DEBUG + sanity_check_instrumentation(code); +#endif uint8_t new_line_tools = new_events.tools[PY_MONITORING_EVENT_LINE]; uint8_t new_per_instruction_tools = new_events.tools[PY_MONITORING_EVENT_INSTRUCTION]; @@ -1655,7 +1718,7 @@ instrument_all_executing_code_objects(PyInterpreterState *interp) { PyThreadState* ts = PyInterpreterState_ThreadHead(interp); HEAD_UNLOCK(runtime); while (ts) { - _PyInterpreterFrame *frame = ts->cframe->current_frame; + _PyInterpreterFrame *frame = ts->current_frame; while (frame) { if (frame->owner != FRAME_OWNED_BY_CSTACK) { if (_Py_Instrument(_PyFrame_GetCode(frame), interp)) { @@ -1672,10 +1735,22 @@ instrument_all_executing_code_objects(PyInterpreterState *interp) { } static void -set_events(_Py_Monitors *m, int tool_id, _PyMonitoringEventSet events) +set_events(_Py_GlobalMonitors *m, int tool_id, _PyMonitoringEventSet events) { assert(0 <= tool_id && tool_id < PY_MONITORING_TOOL_IDS); for (int e = 0; e < _PY_MONITORING_UNGROUPED_EVENTS; e++) { + uint8_t *tools = &m->tools[e]; + int active = (events >> e) & 1; + *tools &= ~(1 << tool_id); + *tools |= (active << tool_id); + } +} + +static void +set_local_events(_Py_LocalMonitors *m, int tool_id, _PyMonitoringEventSet events) +{ + assert(0 <= tool_id && tool_id < PY_MONITORING_TOOL_IDS); + for (int e = 0; e < _PY_MONITORING_LOCAL_EVENTS; e++) { uint8_t *tools = &m->tools[e]; int val = (events >> e) & 1; *tools &= ~(1 << tool_id); @@ -1695,6 +1770,10 @@ check_tool(PyInterpreterState *interp, int tool_id) return 0; } +/* We share the eval-breaker with flags, so the monitoring + * version goes in the top 24 bits */ +#define MONITORING_VERSION_INCREMENT (1 << _PY_EVAL_EVENTS_BITS) + int _PyMonitoring_SetEvents(int tool_id, _PyMonitoringEventSet events) { @@ -1709,7 +1788,13 @@ _PyMonitoring_SetEvents(int tool_id, _PyMonitoringEventSet events) return 0; } set_events(&interp->monitors, tool_id, events); - interp->monitoring_version++; + uint32_t new_version = global_version(interp) + MONITORING_VERSION_INCREMENT; + if (new_version == 0) { + PyErr_Format(PyExc_OverflowError, "events set too many times"); + return -1; + } + set_global_version(interp, new_version); + _Py_Executors_InvalidateAll(interp); return instrument_all_executing_code_objects(interp); } @@ -1718,29 +1803,51 @@ _PyMonitoring_SetLocalEvents(PyCodeObject *code, int tool_id, _PyMonitoringEvent { assert(0 <= tool_id && tool_id < PY_MONITORING_TOOL_IDS); PyInterpreterState *interp = _PyInterpreterState_GET(); - assert(events < (1 << _PY_MONITORING_UNGROUPED_EVENTS)); + assert(events < (1 << _PY_MONITORING_LOCAL_EVENTS)); + if (code->_co_firsttraceable >= Py_SIZE(code)) { + PyErr_Format(PyExc_SystemError, "cannot instrument shim code object '%U'", code->co_name); + return -1; + } if (check_tool(interp, tool_id)) { return -1; } if (allocate_instrumentation_data(code)) { return -1; } - _Py_Monitors *local = &code->_co_monitoring->local_monitors; - uint32_t existing_events = get_events(local, tool_id); + _Py_LocalMonitors *local = &code->_co_monitoring->local_monitors; + uint32_t existing_events = get_local_events(local, tool_id); if (existing_events == events) { return 0; } - set_events(local, tool_id, events); + set_local_events(local, tool_id, events); if (is_version_up_to_date(code, interp)) { /* Force instrumentation update */ - code->_co_instrumentation_version = UINT64_MAX; + code->_co_instrumentation_version -= MONITORING_VERSION_INCREMENT; } + _Py_Executors_InvalidateDependency(interp, code); if (_Py_Instrument(code, interp)) { return -1; } return 0; } +int +_PyMonitoring_GetLocalEvents(PyCodeObject *code, int tool_id, _PyMonitoringEventSet *events) +{ + assert(0 <= tool_id && tool_id < PY_MONITORING_TOOL_IDS); + PyInterpreterState *interp = _PyInterpreterState_GET(); + if (check_tool(interp, tool_id)) { + return -1; + } + if (code->_co_monitoring == NULL) { + *events = 0; + return 0; + } + _Py_LocalMonitors *local = &code->_co_monitoring->local_monitors; + *events = get_local_events(local, tool_id); + return 0; +} + /*[clinic input] module monitoring [clinic start generated code]*/ @@ -1861,6 +1968,9 @@ monitoring_register_callback_impl(PyObject *module, int tool_id, int event, PyErr_Format(PyExc_ValueError, "invalid event %d", event); return NULL; } + if (PySys_Audit("sys.monitoring.register_callback", "O", func) < 0) { + return NULL; + } if (func == Py_None) { func = NULL; } @@ -1886,7 +1996,7 @@ monitoring_get_events_impl(PyObject *module, int tool_id) if (check_valid_tool(tool_id)) { return -1; } - _Py_Monitors *m = &_PyInterpreterState_GET()->monitors; + _Py_GlobalMonitors *m = &_PyInterpreterState_GET()->monitors; _PyMonitoringEventSet event_set = get_events(m, tool_id); return event_set; } @@ -1949,7 +2059,7 @@ monitoring_get_local_events_impl(PyObject *module, int tool_id, _PyMonitoringEventSet event_set = 0; _PyCoMonitoringData *data = ((PyCodeObject *)code)->_co_monitoring; if (data != NULL) { - for (int e = 0; e < _PY_MONITORING_UNGROUPED_EVENTS; e++) { + for (int e = 0; e < _PY_MONITORING_LOCAL_EVENTS; e++) { if ((data->local_monitors.tools[e] >> tool_id) & 1) { event_set |= (1 << e); } @@ -1983,15 +2093,16 @@ monitoring_set_local_events_impl(PyObject *module, int tool_id, if (check_valid_tool(tool_id)) { return NULL; } - if (event_set < 0 || event_set >= (1 << _PY_MONITORING_EVENTS)) { - PyErr_Format(PyExc_ValueError, "invalid event set 0x%x", event_set); - return NULL; - } if ((event_set & C_RETURN_EVENTS) && (event_set & C_CALL_EVENTS) != C_CALL_EVENTS) { PyErr_Format(PyExc_ValueError, "cannot set C_RETURN or C_RAISE events independently"); return NULL; } event_set &= ~C_RETURN_EVENTS; + if (event_set < 0 || event_set >= (1 << _PY_MONITORING_LOCAL_EVENTS)) { + PyErr_Format(PyExc_ValueError, "invalid local event set 0x%x", event_set); + return NULL; + } + if (_PyMonitoring_SetLocalEvents((PyCodeObject*)code, tool_id, event_set)) { return NULL; } @@ -2012,8 +2123,14 @@ monitoring_restart_events_impl(PyObject *module) * last restart version < current version */ PyInterpreterState *interp = _PyInterpreterState_GET(); - interp->last_restart_version = interp->monitoring_version + 1; - interp->monitoring_version = interp->last_restart_version + 1; + uint32_t restart_version = global_version(interp) + MONITORING_VERSION_INCREMENT; + uint32_t new_version = restart_version + MONITORING_VERSION_INCREMENT; + if (new_version <= MONITORING_VERSION_INCREMENT) { + PyErr_Format(PyExc_OverflowError, "events set too many times"); + return NULL; + } + interp->last_restart_version = restart_version; + set_global_version(interp, new_version); if (instrument_all_executing_code_objects(interp)) { return NULL; } diff --git a/Python/intrinsics.c b/Python/intrinsics.c index 61a8e75872d2e2..d3146973b75178 100644 --- a/Python/intrinsics.c +++ b/Python/intrinsics.c @@ -4,11 +4,13 @@ #include "Python.h" #include "pycore_frame.h" #include "pycore_function.h" -#include "pycore_runtime.h" #include "pycore_global_objects.h" -#include "pycore_intrinsics.h" -#include "pycore_pyerrors.h" -#include "pycore_typevarobject.h" +#include "pycore_compile.h" // _PyCompile_GetUnaryIntrinsicName, etc +#include "pycore_intrinsics.h" // INTRINSIC_PRINT +#include "pycore_pyerrors.h" // _PyErr_SetString() +#include "pycore_runtime.h" // _Py_ID() +#include "pycore_sysmodule.h" // _PySys_GetAttr() +#include "pycore_typevarobject.h" // _Py_make_typevar() /******** Unary functions ********/ @@ -120,7 +122,7 @@ import_all_from(PyThreadState *tstate, PyObject *locals, PyObject *v) static PyObject * import_star(PyThreadState* tstate, PyObject *from) { - _PyInterpreterFrame *frame = tstate->cframe->current_frame; + _PyInterpreterFrame *frame = tstate->current_frame; if (_PyFrame_FastToLocalsWithError(frame) < 0) { return NULL; } @@ -142,7 +144,7 @@ import_star(PyThreadState* tstate, PyObject *from) static PyObject * stopiteration_error(PyThreadState* tstate, PyObject *exc) { - _PyInterpreterFrame *frame = tstate->cframe->current_frame; + _PyInterpreterFrame *frame = tstate->current_frame; assert(frame->owner == FRAME_OWNED_BY_GENERATOR); assert(PyExceptionInstance_Check(exc)); const char *msg = NULL; @@ -268,7 +270,7 @@ _PyIntrinsics_BinaryFunctions[] = { #undef INTRINSIC_FUNC_ENTRY PyObject* -_PyUnstable_GetUnaryIntrinsicName(int index) +_PyCompile_GetUnaryIntrinsicName(int index) { if (index < 0 || index > MAX_INTRINSIC_1) { return NULL; @@ -277,7 +279,7 @@ _PyUnstable_GetUnaryIntrinsicName(int index) } PyObject* -_PyUnstable_GetBinaryIntrinsicName(int index) +_PyCompile_GetBinaryIntrinsicName(int index) { if (index < 0 || index > MAX_INTRINSIC_2) { return NULL; diff --git a/Python/legacy_tracing.c b/Python/legacy_tracing.c index 48db51731cfdb0..ccbb3eb3f7c82a 100644 --- a/Python/legacy_tracing.c +++ b/Python/legacy_tracing.c @@ -2,12 +2,13 @@ * Provides callables to forward PEP 669 events to legacy events. */ -#include #include "Python.h" -#include "opcode.h" -#include "pycore_ceval.h" +#include "pycore_ceval.h" // export _PyEval_SetProfile() #include "pycore_object.h" -#include "pycore_sysmodule.h" +#include "pycore_sysmodule.h" // _PySys_Audit() + +#include "opcode.h" +#include typedef struct _PyLegacyEventHandler { PyObject_HEAD @@ -45,7 +46,7 @@ call_profile_func(_PyLegacyEventHandler *self, PyObject *arg) } static PyObject * -sys_profile_func2( +sys_profile_start( _PyLegacyEventHandler *self, PyObject *const *args, size_t nargsf, PyObject *kwnames ) { @@ -55,7 +56,17 @@ sys_profile_func2( } static PyObject * -sys_profile_func3( +sys_profile_throw( + _PyLegacyEventHandler *self, PyObject *const *args, + size_t nargsf, PyObject *kwnames +) { + assert(kwnames == NULL); + assert(PyVectorcall_NARGS(nargsf) == 3); + return call_profile_func(self, Py_None); +} + +static PyObject * +sys_profile_return( _PyLegacyEventHandler *self, PyObject *const *args, size_t nargsf, PyObject *kwnames ) { @@ -71,7 +82,7 @@ sys_profile_unwind( ) { assert(kwnames == NULL); assert(PyVectorcall_NARGS(nargsf) == 3); - return call_profile_func(self, Py_None); + return call_profile_func(self, NULL); } static PyObject * @@ -106,6 +117,35 @@ sys_profile_call_or_return( Py_RETURN_NONE; } +int +_PyEval_SetOpcodeTrace( + PyFrameObject *frame, + bool enable +) { + assert(frame != NULL); + assert(PyCode_Check(frame->f_frame->f_executable)); + + PyCodeObject *code = (PyCodeObject *)frame->f_frame->f_executable; + _PyMonitoringEventSet events = 0; + + if (_PyMonitoring_GetLocalEvents(code, PY_MONITORING_SYS_TRACE_ID, &events) < 0) { + return -1; + } + + if (enable) { + if (events & (1 << PY_MONITORING_EVENT_INSTRUCTION)) { + return 0; + } + events |= (1 << PY_MONITORING_EVENT_INSTRUCTION); + } else { + if (!(events & (1 << PY_MONITORING_EVENT_INSTRUCTION))) { + return 0; + } + events &= (~(1 << PY_MONITORING_EVENT_INSTRUCTION)); + } + return _PyMonitoring_SetLocalEvents(code, PY_MONITORING_SYS_TRACE_ID, events); +} + static PyObject * call_trace_func(_PyLegacyEventHandler *self, PyObject *arg) { @@ -119,6 +159,12 @@ call_trace_func(_PyLegacyEventHandler *self, PyObject *arg) "Missing frame when calling trace function."); return NULL; } + if (frame->f_trace_opcodes) { + if (_PyEval_SetOpcodeTrace(frame, true) != 0) { + return NULL; + } + } + Py_INCREF(frame); int err = tstate->c_tracefunc(tstate->c_traceobj, frame, self->event, arg); Py_DECREF(frame); @@ -153,7 +199,7 @@ sys_trace_exception_func( } static PyObject * -sys_trace_func2( +sys_trace_start( _PyLegacyEventHandler *self, PyObject *const *args, size_t nargsf, PyObject *kwnames ) { @@ -163,7 +209,7 @@ sys_trace_func2( } static PyObject * -sys_trace_unwind( +sys_trace_throw( _PyLegacyEventHandler *self, PyObject *const *args, size_t nargsf, PyObject *kwnames ) { @@ -172,6 +218,16 @@ sys_trace_unwind( return call_trace_func(self, Py_None); } +static PyObject * +sys_trace_unwind( + _PyLegacyEventHandler *self, PyObject *const *args, + size_t nargsf, PyObject *kwnames +) { + assert(kwnames == NULL); + assert(PyVectorcall_NARGS(nargsf) == 3); + return call_trace_func(self, NULL); +} + static PyObject * sys_trace_return( _PyLegacyEventHandler *self, PyObject *const *args, @@ -209,11 +265,14 @@ sys_trace_instruction_func( "Missing frame when calling trace function."); return NULL; } - if (!frame->f_trace_opcodes) { + PyThreadState *tstate = _PyThreadState_GET(); + if (!tstate->c_tracefunc || !frame->f_trace_opcodes) { + if (_PyEval_SetOpcodeTrace(frame, false) != 0) { + return NULL; + } Py_RETURN_NONE; } Py_INCREF(frame); - PyThreadState *tstate = _PyThreadState_GET(); int err = tstate->c_tracefunc(tstate->c_traceobj, frame, self->event, Py_None); frame->f_lineno = 0; Py_DECREF(frame); @@ -256,7 +315,7 @@ sys_trace_line_func( Py_RETURN_NONE; } assert(PyVectorcall_NARGS(nargsf) == 2); - int line = _PyLong_AsInt(args[1]); + int line = PyLong_AsInt(args[1]); assert(line >= 0); PyFrameObject *frame = PyEval_GetFrame(); if (frame == NULL) { @@ -282,9 +341,9 @@ sys_trace_jump_func( Py_RETURN_NONE; } assert(PyVectorcall_NARGS(nargsf) == 3); - int from = _PyLong_AsInt(args[1])/sizeof(_Py_CODEUNIT); + int from = PyLong_AsInt(args[1])/sizeof(_Py_CODEUNIT); assert(from >= 0); - int to = _PyLong_AsInt(args[2])/sizeof(_Py_CODEUNIT); + int to = PyLong_AsInt(args[2])/sizeof(_Py_CODEUNIT); assert(to >= 0); if (to > from) { /* Forward jump */ @@ -372,12 +431,17 @@ _PyEval_SetProfile(PyThreadState *tstate, Py_tracefunc func, PyObject *arg) if (!tstate->interp->sys_profile_initialized) { tstate->interp->sys_profile_initialized = true; if (set_callbacks(PY_MONITORING_SYS_PROFILE_ID, - (vectorcallfunc)sys_profile_func2, PyTrace_CALL, + (vectorcallfunc)sys_profile_start, PyTrace_CALL, PY_MONITORING_EVENT_PY_START, PY_MONITORING_EVENT_PY_RESUME)) { return -1; } if (set_callbacks(PY_MONITORING_SYS_PROFILE_ID, - (vectorcallfunc)sys_profile_func3, PyTrace_RETURN, + (vectorcallfunc)sys_profile_throw, PyTrace_CALL, + PY_MONITORING_EVENT_PY_THROW, -1)) { + return -1; + } + if (set_callbacks(PY_MONITORING_SYS_PROFILE_ID, + (vectorcallfunc)sys_profile_return, PyTrace_RETURN, PY_MONITORING_EVENT_PY_RETURN, PY_MONITORING_EVENT_PY_YIELD)) { return -1; } @@ -416,7 +480,8 @@ _PyEval_SetProfile(PyThreadState *tstate, Py_tracefunc func, PyObject *arg) events = (1 << PY_MONITORING_EVENT_PY_START) | (1 << PY_MONITORING_EVENT_PY_RESUME) | (1 << PY_MONITORING_EVENT_PY_RETURN) | (1 << PY_MONITORING_EVENT_PY_YIELD) | - (1 << PY_MONITORING_EVENT_CALL) | (1 << PY_MONITORING_EVENT_PY_UNWIND); + (1 << PY_MONITORING_EVENT_CALL) | (1 << PY_MONITORING_EVENT_PY_UNWIND) | + (1 << PY_MONITORING_EVENT_PY_THROW); } return _PyMonitoring_SetEvents(PY_MONITORING_SYS_PROFILE_ID, events); } @@ -440,12 +505,12 @@ _PyEval_SetTrace(PyThreadState *tstate, Py_tracefunc func, PyObject *arg) if (!tstate->interp->sys_trace_initialized) { tstate->interp->sys_trace_initialized = true; if (set_callbacks(PY_MONITORING_SYS_TRACE_ID, - (vectorcallfunc)sys_trace_func2, PyTrace_CALL, + (vectorcallfunc)sys_trace_start, PyTrace_CALL, PY_MONITORING_EVENT_PY_START, PY_MONITORING_EVENT_PY_RESUME)) { return -1; } if (set_callbacks(PY_MONITORING_SYS_TRACE_ID, - (vectorcallfunc)sys_trace_func2, PyTrace_CALL, + (vectorcallfunc)sys_trace_throw, PyTrace_CALL, PY_MONITORING_EVENT_PY_THROW, -1)) { return -1; } @@ -504,9 +569,15 @@ _PyEval_SetTrace(PyThreadState *tstate, Py_tracefunc func, PyObject *arg) (1 << PY_MONITORING_EVENT_PY_UNWIND) | (1 << PY_MONITORING_EVENT_PY_THROW) | (1 << PY_MONITORING_EVENT_STOP_ITERATION) | (1 << PY_MONITORING_EVENT_EXCEPTION_HANDLED); - if (tstate->interp->f_opcode_trace_set) { - events |= (1 << PY_MONITORING_EVENT_INSTRUCTION); + + PyFrameObject* frame = PyEval_GetFrame(); + if (frame->f_trace_opcodes) { + int ret = _PyEval_SetOpcodeTrace(frame, true); + if (ret != 0) { + return ret; + } } } + return _PyMonitoring_SetEvents(PY_MONITORING_SYS_TRACE_ID, events); } diff --git a/Python/lock.c b/Python/lock.c new file mode 100644 index 00000000000000..f0ff1176941da8 --- /dev/null +++ b/Python/lock.c @@ -0,0 +1,461 @@ +// Lock implementation + +#include "Python.h" + +#include "pycore_lock.h" +#include "pycore_parking_lot.h" +#include "pycore_semaphore.h" + +#ifdef MS_WINDOWS +#define WIN32_LEAN_AND_MEAN +#include // SwitchToThread() +#elif defined(HAVE_SCHED_H) +#include // sched_yield() +#endif + +// If a thread waits on a lock for longer than TIME_TO_BE_FAIR_NS (1 ms), then +// the unlocking thread directly hands off ownership of the lock. This avoids +// starvation. +static const _PyTime_t TIME_TO_BE_FAIR_NS = 1000*1000; + +// Spin for a bit before parking the thread. This is only enabled for +// `--disable-gil` builds because it is unlikely to be helpful if the GIL is +// enabled. +#if Py_GIL_DISABLED +static const int MAX_SPIN_COUNT = 40; +#else +static const int MAX_SPIN_COUNT = 0; +#endif + +struct mutex_entry { + // The time after which the unlocking thread should hand off lock ownership + // directly to the waiting thread. Written by the waiting thread. + _PyTime_t time_to_be_fair; + + // Set to 1 if the lock was handed off. Written by the unlocking thread. + int handed_off; +}; + +static void +_Py_yield(void) +{ +#ifdef MS_WINDOWS + SwitchToThread(); +#elif defined(HAVE_SCHED_H) + sched_yield(); +#endif +} + +void +_PyMutex_LockSlow(PyMutex *m) +{ + _PyMutex_LockTimed(m, -1, _PY_LOCK_DETACH); +} + +PyLockStatus +_PyMutex_LockTimed(PyMutex *m, _PyTime_t timeout, _PyLockFlags flags) +{ + uint8_t v = _Py_atomic_load_uint8_relaxed(&m->v); + if ((v & _Py_LOCKED) == 0) { + if (_Py_atomic_compare_exchange_uint8(&m->v, &v, v|_Py_LOCKED)) { + return PY_LOCK_ACQUIRED; + } + } + else if (timeout == 0) { + return PY_LOCK_FAILURE; + } + + _PyTime_t now = _PyTime_GetMonotonicClock(); + _PyTime_t endtime = 0; + if (timeout > 0) { + endtime = _PyTime_Add(now, timeout); + } + + struct mutex_entry entry = { + .time_to_be_fair = now + TIME_TO_BE_FAIR_NS, + .handed_off = 0, + }; + + Py_ssize_t spin_count = 0; + for (;;) { + if ((v & _Py_LOCKED) == 0) { + // The lock is unlocked. Try to grab it. + if (_Py_atomic_compare_exchange_uint8(&m->v, &v, v|_Py_LOCKED)) { + return PY_LOCK_ACQUIRED; + } + continue; + } + + if (!(v & _Py_HAS_PARKED) && spin_count < MAX_SPIN_COUNT) { + // Spin for a bit. + _Py_yield(); + spin_count++; + continue; + } + + if (timeout == 0) { + return PY_LOCK_FAILURE; + } + + uint8_t newv = v; + if (!(v & _Py_HAS_PARKED)) { + // We are the first waiter. Set the _Py_HAS_PARKED flag. + newv = v | _Py_HAS_PARKED; + if (!_Py_atomic_compare_exchange_uint8(&m->v, &v, newv)) { + continue; + } + } + + int ret = _PyParkingLot_Park(&m->v, &newv, sizeof(newv), timeout, + &entry, (flags & _PY_LOCK_DETACH) != 0); + if (ret == Py_PARK_OK) { + if (entry.handed_off) { + // We own the lock now. + assert(_Py_atomic_load_uint8_relaxed(&m->v) & _Py_LOCKED); + return PY_LOCK_ACQUIRED; + } + } + else if (ret == Py_PARK_INTR && (flags & _PY_LOCK_HANDLE_SIGNALS)) { + if (Py_MakePendingCalls() < 0) { + return PY_LOCK_INTR; + } + } + else if (ret == Py_PARK_TIMEOUT) { + assert(timeout >= 0); + return PY_LOCK_FAILURE; + } + + if (timeout > 0) { + timeout = _PyDeadline_Get(endtime); + if (timeout <= 0) { + // Avoid negative values because those mean block forever. + timeout = 0; + } + } + + v = _Py_atomic_load_uint8_relaxed(&m->v); + } +} + +static void +mutex_unpark(PyMutex *m, struct mutex_entry *entry, int has_more_waiters) +{ + uint8_t v = 0; + if (entry) { + _PyTime_t now = _PyTime_GetMonotonicClock(); + int should_be_fair = now > entry->time_to_be_fair; + + entry->handed_off = should_be_fair; + if (should_be_fair) { + v |= _Py_LOCKED; + } + if (has_more_waiters) { + v |= _Py_HAS_PARKED; + } + } + _Py_atomic_store_uint8(&m->v, v); +} + +int +_PyMutex_TryUnlock(PyMutex *m) +{ + uint8_t v = _Py_atomic_load_uint8(&m->v); + for (;;) { + if ((v & _Py_LOCKED) == 0) { + // error: the mutex is not locked + return -1; + } + else if ((v & _Py_HAS_PARKED)) { + // wake up a single thread + _PyParkingLot_Unpark(&m->v, (_Py_unpark_fn_t *)mutex_unpark, m); + return 0; + } + else if (_Py_atomic_compare_exchange_uint8(&m->v, &v, _Py_UNLOCKED)) { + // fast-path: no waiters + return 0; + } + } +} + +void +_PyMutex_UnlockSlow(PyMutex *m) +{ + if (_PyMutex_TryUnlock(m) < 0) { + Py_FatalError("unlocking mutex that is not locked"); + } +} + +// _PyRawMutex stores a linked list of `struct raw_mutex_entry`, one for each +// thread waiting on the mutex, directly in the mutex itself. +struct raw_mutex_entry { + struct raw_mutex_entry *next; + _PySemaphore sema; +}; + +void +_PyRawMutex_LockSlow(_PyRawMutex *m) +{ + struct raw_mutex_entry waiter; + _PySemaphore_Init(&waiter.sema); + + uintptr_t v = _Py_atomic_load_uintptr(&m->v); + for (;;) { + if ((v & _Py_LOCKED) == 0) { + // Unlocked: try to grab it (even if it has a waiter). + if (_Py_atomic_compare_exchange_uintptr(&m->v, &v, v|_Py_LOCKED)) { + break; + } + continue; + } + + // Locked: try to add ourselves as a waiter. + waiter.next = (struct raw_mutex_entry *)(v & ~1); + uintptr_t desired = ((uintptr_t)&waiter)|_Py_LOCKED; + if (!_Py_atomic_compare_exchange_uintptr(&m->v, &v, desired)) { + continue; + } + + // Wait for us to be woken up. Note that we still have to lock the + // mutex ourselves: it is NOT handed off to us. + _PySemaphore_Wait(&waiter.sema, -1, /*detach=*/0); + } + + _PySemaphore_Destroy(&waiter.sema); +} + +void +_PyRawMutex_UnlockSlow(_PyRawMutex *m) +{ + uintptr_t v = _Py_atomic_load_uintptr(&m->v); + for (;;) { + if ((v & _Py_LOCKED) == 0) { + Py_FatalError("unlocking mutex that is not locked"); + } + + struct raw_mutex_entry *waiter = (struct raw_mutex_entry *)(v & ~1); + if (waiter) { + uintptr_t next_waiter = (uintptr_t)waiter->next; + if (_Py_atomic_compare_exchange_uintptr(&m->v, &v, next_waiter)) { + _PySemaphore_Wakeup(&waiter->sema); + return; + } + } + else { + if (_Py_atomic_compare_exchange_uintptr(&m->v, &v, _Py_UNLOCKED)) { + return; + } + } + } +} + +void +_PyEvent_Notify(PyEvent *evt) +{ + uintptr_t v = _Py_atomic_exchange_uint8(&evt->v, _Py_LOCKED); + if (v == _Py_UNLOCKED) { + // no waiters + return; + } + else if (v == _Py_LOCKED) { + // event already set + return; + } + else { + assert(v == _Py_HAS_PARKED); + _PyParkingLot_UnparkAll(&evt->v); + } +} + +void +PyEvent_Wait(PyEvent *evt) +{ + while (!PyEvent_WaitTimed(evt, -1)) + ; +} + +int +PyEvent_WaitTimed(PyEvent *evt, _PyTime_t timeout_ns) +{ + for (;;) { + uint8_t v = _Py_atomic_load_uint8(&evt->v); + if (v == _Py_LOCKED) { + // event already set + return 1; + } + if (v == _Py_UNLOCKED) { + if (!_Py_atomic_compare_exchange_uint8(&evt->v, &v, _Py_HAS_PARKED)) { + continue; + } + } + + uint8_t expected = _Py_HAS_PARKED; + (void) _PyParkingLot_Park(&evt->v, &expected, sizeof(evt->v), + timeout_ns, NULL, 1); + + return _Py_atomic_load_uint8(&evt->v) == _Py_LOCKED; + } +} + +static int +unlock_once(_PyOnceFlag *o, int res) +{ + // On success (res=0), we set the state to _Py_ONCE_INITIALIZED. + // On failure (res=-1), we reset the state to _Py_UNLOCKED. + uint8_t new_value; + switch (res) { + case -1: new_value = _Py_UNLOCKED; break; + case 0: new_value = _Py_ONCE_INITIALIZED; break; + default: { + Py_FatalError("invalid result from _PyOnceFlag_CallOnce"); + Py_UNREACHABLE(); + break; + } + } + + uint8_t old_value = _Py_atomic_exchange_uint8(&o->v, new_value); + if ((old_value & _Py_HAS_PARKED) != 0) { + // wake up anyone waiting on the once flag + _PyParkingLot_UnparkAll(&o->v); + } + return res; +} + +int +_PyOnceFlag_CallOnceSlow(_PyOnceFlag *flag, _Py_once_fn_t *fn, void *arg) +{ + uint8_t v = _Py_atomic_load_uint8(&flag->v); + for (;;) { + if (v == _Py_UNLOCKED) { + if (!_Py_atomic_compare_exchange_uint8(&flag->v, &v, _Py_LOCKED)) { + continue; + } + int res = fn(arg); + return unlock_once(flag, res); + } + + if (v == _Py_ONCE_INITIALIZED) { + return 0; + } + + // The once flag is initializing (locked). + assert((v & _Py_LOCKED)); + if (!(v & _Py_HAS_PARKED)) { + // We are the first waiter. Set the _Py_HAS_PARKED flag. + uint8_t new_value = v | _Py_HAS_PARKED; + if (!_Py_atomic_compare_exchange_uint8(&flag->v, &v, new_value)) { + continue; + } + v = new_value; + } + + // Wait for initialization to finish. + _PyParkingLot_Park(&flag->v, &v, sizeof(v), -1, NULL, 1); + v = _Py_atomic_load_uint8(&flag->v); + } +} + +#define _Py_WRITE_LOCKED 1 +#define _PyRWMutex_READER_SHIFT 2 +#define _Py_RWMUTEX_MAX_READERS (UINTPTR_MAX >> _PyRWMutex_READER_SHIFT) + +static uintptr_t +rwmutex_set_parked_and_wait(_PyRWMutex *rwmutex, uintptr_t bits) +{ + // Set _Py_HAS_PARKED and wait until we are woken up. + if ((bits & _Py_HAS_PARKED) == 0) { + uintptr_t newval = bits | _Py_HAS_PARKED; + if (!_Py_atomic_compare_exchange_uintptr(&rwmutex->bits, + &bits, newval)) { + return bits; + } + bits = newval; + } + + _PyParkingLot_Park(&rwmutex->bits, &bits, sizeof(bits), -1, NULL, 1); + return _Py_atomic_load_uintptr_relaxed(&rwmutex->bits); +} + +// The number of readers holding the lock +static uintptr_t +rwmutex_reader_count(uintptr_t bits) +{ + return bits >> _PyRWMutex_READER_SHIFT; +} + +void +_PyRWMutex_RLock(_PyRWMutex *rwmutex) +{ + uintptr_t bits = _Py_atomic_load_uintptr_relaxed(&rwmutex->bits); + for (;;) { + if ((bits & _Py_WRITE_LOCKED)) { + // A writer already holds the lock. + bits = rwmutex_set_parked_and_wait(rwmutex, bits); + continue; + } + else if ((bits & _Py_HAS_PARKED)) { + // Reader(s) hold the lock (or just gave up the lock), but there is + // at least one waiting writer. We can't grab the lock because we + // don't want to starve the writer. Instead, we park ourselves and + // wait for the writer to eventually wake us up. + bits = rwmutex_set_parked_and_wait(rwmutex, bits); + continue; + } + else { + // The lock is unlocked or read-locked. Try to grab it. + assert(rwmutex_reader_count(bits) < _Py_RWMUTEX_MAX_READERS); + uintptr_t newval = bits + (1 << _PyRWMutex_READER_SHIFT); + if (!_Py_atomic_compare_exchange_uintptr(&rwmutex->bits, + &bits, newval)) { + continue; + } + return; + } + } +} + +void +_PyRWMutex_RUnlock(_PyRWMutex *rwmutex) +{ + uintptr_t bits = _Py_atomic_add_uintptr(&rwmutex->bits, -(1 << _PyRWMutex_READER_SHIFT)); + assert(rwmutex_reader_count(bits) > 0 && "lock was not read-locked"); + bits -= (1 << _PyRWMutex_READER_SHIFT); + + if (rwmutex_reader_count(bits) == 0 && (bits & _Py_HAS_PARKED)) { + _PyParkingLot_UnparkAll(&rwmutex->bits); + return; + } +} + +void +_PyRWMutex_Lock(_PyRWMutex *rwmutex) +{ + uintptr_t bits = _Py_atomic_load_uintptr_relaxed(&rwmutex->bits); + for (;;) { + // If there are no active readers and it's not already write-locked, + // then we can grab the lock. + if ((bits & ~_Py_HAS_PARKED) == 0) { + if (!_Py_atomic_compare_exchange_uintptr(&rwmutex->bits, + &bits, + bits | _Py_WRITE_LOCKED)) { + continue; + } + return; + } + + // Otherwise, we have to wait. + bits = rwmutex_set_parked_and_wait(rwmutex, bits); + } +} + +void +_PyRWMutex_Unlock(_PyRWMutex *rwmutex) +{ + uintptr_t old_bits = _Py_atomic_exchange_uintptr(&rwmutex->bits, 0); + + assert((old_bits & _Py_WRITE_LOCKED) && "lock was not write-locked"); + assert(rwmutex_reader_count(old_bits) == 0 && "lock was read-locked"); + + if ((old_bits & _Py_HAS_PARKED) != 0) { + _PyParkingLot_UnparkAll(&rwmutex->bits); + } +} diff --git a/Python/modsupport.c b/Python/modsupport.c index 18b3322ae81d11..e9abf304e6502c 100644 --- a/Python/modsupport.c +++ b/Python/modsupport.c @@ -88,6 +88,24 @@ static PyObject *do_mklist(const char**, va_list *, char, Py_ssize_t); static PyObject *do_mkdict(const char**, va_list *, char, Py_ssize_t); static PyObject *do_mkvalue(const char**, va_list *); +static int +check_end(const char **p_format, char endchar) +{ + const char *f = *p_format; + while (*f != endchar) { + if (*f != ' ' && *f != '\t' && *f != ',' && *f != ':') { + PyErr_SetString(PyExc_SystemError, + "Unmatched paren in format"); + return 0; + } + f++; + } + if (endchar) { + f++; + } + *p_format = f; + return 1; +} static void do_ignore(const char **p_format, va_list *p_va, char endchar, Py_ssize_t n) @@ -108,14 +126,9 @@ do_ignore(const char **p_format, va_list *p_va, char endchar, Py_ssize_t n) } } Py_XDECREF(v); - if (**p_format != endchar) { - PyErr_SetString(PyExc_SystemError, - "Unmatched paren in format"); + if (!check_end(p_format, endchar)) { return; } - if (endchar) { - ++*p_format; - } } static PyObject * @@ -157,14 +170,10 @@ do_mkdict(const char **p_format, va_list *p_va, char endchar, Py_ssize_t n) Py_DECREF(k); Py_DECREF(v); } - if (**p_format != endchar) { + if (!check_end(p_format, endchar)) { Py_DECREF(d); - PyErr_SetString(PyExc_SystemError, - "Unmatched paren in format"); return NULL; } - if (endchar) - ++*p_format; return d; } @@ -191,14 +200,10 @@ do_mklist(const char **p_format, va_list *p_va, char endchar, Py_ssize_t n) } PyList_SET_ITEM(v, i, w); } - if (**p_format != endchar) { + if (!check_end(p_format, endchar)) { Py_DECREF(v); - PyErr_SetString(PyExc_SystemError, - "Unmatched paren in format"); return NULL; } - if (endchar) - ++*p_format; return v; } @@ -221,14 +226,9 @@ do_mkstack(PyObject **stack, const char **p_format, va_list *p_va, } stack[i] = w; } - if (**p_format != endchar) { - PyErr_SetString(PyExc_SystemError, - "Unmatched paren in format"); + if (!check_end(p_format, endchar)) { goto error; } - if (endchar) { - ++*p_format; - } return 0; error: @@ -261,14 +261,10 @@ do_mktuple(const char **p_format, va_list *p_va, char endchar, Py_ssize_t n) } PyTuple_SET_ITEM(v, i, w); } - if (**p_format != endchar) { + if (!check_end(p_format, endchar)) { Py_DECREF(v); - PyErr_SetString(PyExc_SystemError, - "Unmatched paren in format"); return NULL; } - if (endchar) - ++*p_format; return v; } diff --git a/Python/mystrtoul.c b/Python/mystrtoul.c index e6fe154eed611a..fcd3e27f17f4e9 100644 --- a/Python/mystrtoul.c +++ b/Python/mystrtoul.c @@ -1,16 +1,22 @@ +// strtol() and strtoul(), renamed to avoid conflicts. +// +// API: +// +// - PyOS_strtol(): convert string to C long integer. +// - PyOS_strtoul(): convert string to C unsigned long integer. + #include "Python.h" #include "pycore_long.h" // _PyLong_DigitValue #if defined(__sgi) && !defined(_SGI_MP_SOURCE) -#define _SGI_MP_SOURCE +# define _SGI_MP_SOURCE #endif /* strtol and strtoul, renamed to avoid conflicts */ -#include #ifdef HAVE_ERRNO_H -#include +# include // errno #endif /* Static overflow check values for bases 2 through 36. @@ -75,7 +81,7 @@ static const int digitlimit[] = { 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, /* 20 - 29 */ 13, 12, 12, 12, 12, 12, 12}; /* 30 - 36 */ #else -#error "Need table for SIZEOF_LONG" +# error "Need table for SIZEOF_LONG" #endif /* diff --git a/Python/opcode_targets.h b/Python/opcode_targets.h index d84d253c912a28..e664e638bdb749 100644 --- a/Python/opcode_targets.h +++ b/Python/opcode_targets.h @@ -1,193 +1,123 @@ static void *opcode_targets[256] = { &&TARGET_CACHE, - &&TARGET_POP_TOP, - &&TARGET_PUSH_NULL, - &&TARGET_INTERPRETER_EXIT, + &&TARGET_BEFORE_ASYNC_WITH, + &&TARGET_BEFORE_WITH, + &&TARGET_BINARY_OP_INPLACE_ADD_UNICODE, + &&TARGET_BINARY_SLICE, + &&TARGET_BINARY_SUBSCR, + &&TARGET_CHECK_EG_MATCH, + &&TARGET_CHECK_EXC_MATCH, + &&TARGET_CLEANUP_THROW, + &&TARGET_DELETE_SUBSCR, + &&TARGET_END_ASYNC_FOR, &&TARGET_END_FOR, &&TARGET_END_SEND, - &&TARGET_TO_BOOL, - &&TARGET_TO_BOOL_ALWAYS_TRUE, - &&TARGET_TO_BOOL_BOOL, - &&TARGET_NOP, - &&TARGET_TO_BOOL_INT, - &&TARGET_UNARY_NEGATIVE, - &&TARGET_UNARY_NOT, - &&TARGET_TO_BOOL_LIST, - &&TARGET_TO_BOOL_NONE, - &&TARGET_UNARY_INVERT, &&TARGET_EXIT_INIT_CHECK, - &&TARGET_RESERVED, - &&TARGET_TO_BOOL_STR, - &&TARGET_BINARY_OP_MULTIPLY_INT, - &&TARGET_BINARY_OP_ADD_INT, - &&TARGET_BINARY_OP_SUBTRACT_INT, - &&TARGET_BINARY_OP_MULTIPLY_FLOAT, - &&TARGET_BINARY_OP_ADD_FLOAT, - &&TARGET_MAKE_FUNCTION, - &&TARGET_BINARY_SUBSCR, - &&TARGET_BINARY_SLICE, - &&TARGET_STORE_SLICE, - &&TARGET_BINARY_OP_SUBTRACT_FLOAT, - &&TARGET_BINARY_OP_ADD_UNICODE, - &&TARGET_GET_LEN, - &&TARGET_MATCH_MAPPING, - &&TARGET_MATCH_SEQUENCE, - &&TARGET_MATCH_KEYS, - &&TARGET_BINARY_OP_INPLACE_ADD_UNICODE, - &&TARGET_PUSH_EXC_INFO, - &&TARGET_CHECK_EXC_MATCH, - &&TARGET_CHECK_EG_MATCH, - &&TARGET_BINARY_SUBSCR_DICT, - &&TARGET_BINARY_SUBSCR_GETITEM, &&TARGET_FORMAT_SIMPLE, &&TARGET_FORMAT_WITH_SPEC, - &&TARGET_BINARY_SUBSCR_LIST_INT, - &&TARGET_BINARY_SUBSCR_TUPLE_INT, - &&TARGET_STORE_SUBSCR_DICT, - &&TARGET_STORE_SUBSCR_LIST_INT, - &&TARGET_SEND_GEN, - &&TARGET_UNPACK_SEQUENCE_TWO_TUPLE, - &&TARGET_UNPACK_SEQUENCE_TUPLE, - &&TARGET_WITH_EXCEPT_START, &&TARGET_GET_AITER, + &&TARGET_RESERVED, &&TARGET_GET_ANEXT, - &&TARGET_BEFORE_ASYNC_WITH, - &&TARGET_BEFORE_WITH, - &&TARGET_END_ASYNC_FOR, - &&TARGET_CLEANUP_THROW, - &&TARGET_UNPACK_SEQUENCE_LIST, - &&TARGET_STORE_ATTR_INSTANCE_VALUE, - &&TARGET_STORE_ATTR_SLOT, - &&TARGET_STORE_ATTR_WITH_HINT, - &&TARGET_STORE_SUBSCR, - &&TARGET_DELETE_SUBSCR, - &&TARGET_LOAD_GLOBAL_MODULE, - &&TARGET_LOAD_GLOBAL_BUILTIN, - &&TARGET_LOAD_SUPER_ATTR_ATTR, - &&TARGET_LOAD_SUPER_ATTR_METHOD, - &&TARGET_LOAD_ATTR_INSTANCE_VALUE, - &&TARGET_LOAD_ATTR_MODULE, &&TARGET_GET_ITER, + &&TARGET_GET_LEN, &&TARGET_GET_YIELD_FROM_ITER, - &&TARGET_LOAD_ATTR_WITH_HINT, - &&TARGET_LOAD_BUILD_CLASS, - &&TARGET_LOAD_ATTR_SLOT, - &&TARGET_LOAD_ATTR_CLASS, + &&TARGET_INTERPRETER_EXIT, &&TARGET_LOAD_ASSERTION_ERROR, + &&TARGET_LOAD_BUILD_CLASS, + &&TARGET_LOAD_LOCALS, + &&TARGET_MAKE_FUNCTION, + &&TARGET_MATCH_KEYS, + &&TARGET_MATCH_MAPPING, + &&TARGET_MATCH_SEQUENCE, + &&TARGET_NOP, + &&TARGET_POP_EXCEPT, + &&TARGET_POP_TOP, + &&TARGET_PUSH_EXC_INFO, + &&TARGET_PUSH_NULL, &&TARGET_RETURN_GENERATOR, - &&TARGET_LOAD_ATTR_PROPERTY, - &&TARGET_LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN, - &&TARGET_LOAD_ATTR_METHOD_WITH_VALUES, - &&TARGET_LOAD_ATTR_METHOD_NO_DICT, - &&TARGET_LOAD_ATTR_METHOD_LAZY_DICT, - &&TARGET_LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES, - &&TARGET_LOAD_ATTR_NONDESCRIPTOR_NO_DICT, &&TARGET_RETURN_VALUE, - &&TARGET_COMPARE_OP_FLOAT, &&TARGET_SETUP_ANNOTATIONS, - &&TARGET_COMPARE_OP_INT, - &&TARGET_LOAD_LOCALS, - &&TARGET_COMPARE_OP_STR, - &&TARGET_POP_EXCEPT, - &&TARGET_STORE_NAME, - &&TARGET_DELETE_NAME, - &&TARGET_UNPACK_SEQUENCE, - &&TARGET_FOR_ITER, - &&TARGET_UNPACK_EX, - &&TARGET_STORE_ATTR, - &&TARGET_DELETE_ATTR, - &&TARGET_STORE_GLOBAL, - &&TARGET_DELETE_GLOBAL, - &&TARGET_SWAP, - &&TARGET_LOAD_CONST, - &&TARGET_LOAD_NAME, - &&TARGET_BUILD_TUPLE, + &&TARGET_STORE_SLICE, + &&TARGET_STORE_SUBSCR, + &&TARGET_TO_BOOL, + &&TARGET_UNARY_INVERT, + &&TARGET_UNARY_NEGATIVE, + &&TARGET_UNARY_NOT, + &&TARGET_WITH_EXCEPT_START, + &&TARGET_BINARY_OP, + &&TARGET_BUILD_CONST_KEY_MAP, &&TARGET_BUILD_LIST, - &&TARGET_BUILD_SET, &&TARGET_BUILD_MAP, - &&TARGET_LOAD_ATTR, + &&TARGET_BUILD_SET, + &&TARGET_BUILD_SLICE, + &&TARGET_BUILD_STRING, + &&TARGET_BUILD_TUPLE, + &&TARGET_CALL, + &&TARGET_CALL_FUNCTION_EX, + &&TARGET_CALL_INTRINSIC_1, + &&TARGET_CALL_INTRINSIC_2, + &&TARGET_CALL_KW, &&TARGET_COMPARE_OP, - &&TARGET_IMPORT_NAME, - &&TARGET_IMPORT_FROM, - &&TARGET_JUMP_FORWARD, - &&TARGET_FOR_ITER_LIST, - &&TARGET_FOR_ITER_TUPLE, - &&TARGET_FOR_ITER_RANGE, - &&TARGET_POP_JUMP_IF_FALSE, - &&TARGET_POP_JUMP_IF_TRUE, - &&TARGET_LOAD_GLOBAL, - &&TARGET_IS_OP, &&TARGET_CONTAINS_OP, - &&TARGET_RERAISE, + &&TARGET_CONVERT_VALUE, &&TARGET_COPY, - &&TARGET_RETURN_CONST, - &&TARGET_BINARY_OP, - &&TARGET_SEND, - &&TARGET_LOAD_FAST, - &&TARGET_STORE_FAST, + &&TARGET_COPY_FREE_VARS, + &&TARGET_DELETE_ATTR, + &&TARGET_DELETE_DEREF, &&TARGET_DELETE_FAST, - &&TARGET_LOAD_FAST_CHECK, - &&TARGET_POP_JUMP_IF_NOT_NONE, - &&TARGET_POP_JUMP_IF_NONE, - &&TARGET_RAISE_VARARGS, + &&TARGET_DELETE_GLOBAL, + &&TARGET_DELETE_NAME, + &&TARGET_DICT_MERGE, + &&TARGET_DICT_UPDATE, + &&TARGET_ENTER_EXECUTOR, + &&TARGET_EXTENDED_ARG, + &&TARGET_FOR_ITER, &&TARGET_GET_AWAITABLE, - &&TARGET_FOR_ITER_GEN, - &&TARGET_BUILD_SLICE, + &&TARGET_IMPORT_FROM, + &&TARGET_IMPORT_NAME, + &&TARGET_IS_OP, + &&TARGET_JUMP_BACKWARD, &&TARGET_JUMP_BACKWARD_NO_INTERRUPT, - &&TARGET_MAKE_CELL, - &&TARGET_CALL_BOUND_METHOD_EXACT_ARGS, + &&TARGET_JUMP_FORWARD, + &&TARGET_LIST_APPEND, + &&TARGET_LIST_EXTEND, + &&TARGET_LOAD_ATTR, + &&TARGET_LOAD_CONST, &&TARGET_LOAD_DEREF, - &&TARGET_STORE_DEREF, - &&TARGET_DELETE_DEREF, - &&TARGET_JUMP_BACKWARD, - &&TARGET_LOAD_SUPER_ATTR, - &&TARGET_CALL_FUNCTION_EX, + &&TARGET_LOAD_FAST, &&TARGET_LOAD_FAST_AND_CLEAR, - &&TARGET_EXTENDED_ARG, - &&TARGET_LIST_APPEND, - &&TARGET_SET_ADD, + &&TARGET_LOAD_FAST_CHECK, + &&TARGET_LOAD_FAST_LOAD_FAST, + &&TARGET_LOAD_FROM_DICT_OR_DEREF, + &&TARGET_LOAD_FROM_DICT_OR_GLOBALS, + &&TARGET_LOAD_GLOBAL, + &&TARGET_LOAD_NAME, + &&TARGET_LOAD_SUPER_ATTR, + &&TARGET_MAKE_CELL, &&TARGET_MAP_ADD, - &&TARGET_CALL_PY_EXACT_ARGS, - &&TARGET_COPY_FREE_VARS, - &&TARGET_YIELD_VALUE, - &&TARGET_RESUME, &&TARGET_MATCH_CLASS, - &&TARGET_CALL_PY_WITH_DEFAULTS, - &&TARGET_CALL_NO_KW_TYPE_1, - &&TARGET_CALL_NO_KW_STR_1, - &&TARGET_BUILD_CONST_KEY_MAP, - &&TARGET_BUILD_STRING, - &&TARGET_CONVERT_VALUE, - &&TARGET_CALL_NO_KW_TUPLE_1, - &&TARGET_CALL_BUILTIN_CLASS, - &&TARGET_CALL_NO_KW_BUILTIN_O, - &&TARGET_LIST_EXTEND, + &&TARGET_POP_JUMP_IF_FALSE, + &&TARGET_POP_JUMP_IF_NONE, + &&TARGET_POP_JUMP_IF_NOT_NONE, + &&TARGET_POP_JUMP_IF_TRUE, + &&TARGET_RAISE_VARARGS, + &&TARGET_RERAISE, + &&TARGET_RETURN_CONST, + &&TARGET_SEND, + &&TARGET_SET_ADD, + &&TARGET_SET_FUNCTION_ATTRIBUTE, &&TARGET_SET_UPDATE, - &&TARGET_DICT_MERGE, - &&TARGET_DICT_UPDATE, - &&TARGET_CALL_NO_KW_BUILTIN_FAST, - &&TARGET_CALL_BUILTIN_FAST_WITH_KEYWORDS, - &&TARGET_LOAD_FAST_LOAD_FAST, + &&TARGET_STORE_ATTR, + &&TARGET_STORE_DEREF, + &&TARGET_STORE_FAST, &&TARGET_STORE_FAST_LOAD_FAST, &&TARGET_STORE_FAST_STORE_FAST, - &&TARGET_CALL, - &&TARGET_KW_NAMES, - &&TARGET_CALL_INTRINSIC_1, - &&TARGET_CALL_INTRINSIC_2, - &&TARGET_LOAD_FROM_DICT_OR_GLOBALS, - &&TARGET_LOAD_FROM_DICT_OR_DEREF, - &&TARGET_SET_FUNCTION_ATTRIBUTE, - &&TARGET_CALL_NO_KW_LEN, - &&TARGET_CALL_NO_KW_ISINSTANCE, - &&TARGET_CALL_NO_KW_LIST_APPEND, - &&TARGET_CALL_NO_KW_METHOD_DESCRIPTOR_O, - &&TARGET_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS, - &&TARGET_CALL_NO_KW_METHOD_DESCRIPTOR_NOARGS, - &&TARGET_CALL_NO_KW_METHOD_DESCRIPTOR_FAST, - &&TARGET_CALL_NO_KW_ALLOC_AND_ENTER_INIT, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, + &&TARGET_STORE_GLOBAL, + &&TARGET_STORE_NAME, + &&TARGET_SWAP, + &&TARGET_UNPACK_EX, + &&TARGET_UNPACK_SEQUENCE, + &&TARGET_YIELD_VALUE, &&_unknown_opcode, &&_unknown_opcode, &&_unknown_opcode, @@ -218,6 +148,76 @@ static void *opcode_targets[256] = { &&_unknown_opcode, &&_unknown_opcode, &&_unknown_opcode, + &&TARGET_RESUME, + &&TARGET_BINARY_OP_ADD_FLOAT, + &&TARGET_BINARY_OP_ADD_INT, + &&TARGET_BINARY_OP_ADD_UNICODE, + &&TARGET_BINARY_OP_MULTIPLY_FLOAT, + &&TARGET_BINARY_OP_MULTIPLY_INT, + &&TARGET_BINARY_OP_SUBTRACT_FLOAT, + &&TARGET_BINARY_OP_SUBTRACT_INT, + &&TARGET_BINARY_SUBSCR_DICT, + &&TARGET_BINARY_SUBSCR_GETITEM, + &&TARGET_BINARY_SUBSCR_LIST_INT, + &&TARGET_BINARY_SUBSCR_STR_INT, + &&TARGET_BINARY_SUBSCR_TUPLE_INT, + &&TARGET_CALL_ALLOC_AND_ENTER_INIT, + &&TARGET_CALL_BOUND_METHOD_EXACT_ARGS, + &&TARGET_CALL_BUILTIN_CLASS, + &&TARGET_CALL_BUILTIN_FAST, + &&TARGET_CALL_BUILTIN_FAST_WITH_KEYWORDS, + &&TARGET_CALL_BUILTIN_O, + &&TARGET_CALL_ISINSTANCE, + &&TARGET_CALL_LEN, + &&TARGET_CALL_LIST_APPEND, + &&TARGET_CALL_METHOD_DESCRIPTOR_FAST, + &&TARGET_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS, + &&TARGET_CALL_METHOD_DESCRIPTOR_NOARGS, + &&TARGET_CALL_METHOD_DESCRIPTOR_O, + &&TARGET_CALL_PY_EXACT_ARGS, + &&TARGET_CALL_PY_WITH_DEFAULTS, + &&TARGET_CALL_STR_1, + &&TARGET_CALL_TUPLE_1, + &&TARGET_CALL_TYPE_1, + &&TARGET_COMPARE_OP_FLOAT, + &&TARGET_COMPARE_OP_INT, + &&TARGET_COMPARE_OP_STR, + &&TARGET_FOR_ITER_GEN, + &&TARGET_FOR_ITER_LIST, + &&TARGET_FOR_ITER_RANGE, + &&TARGET_FOR_ITER_TUPLE, + &&TARGET_LOAD_ATTR_CLASS, + &&TARGET_LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN, + &&TARGET_LOAD_ATTR_INSTANCE_VALUE, + &&TARGET_LOAD_ATTR_METHOD_LAZY_DICT, + &&TARGET_LOAD_ATTR_METHOD_NO_DICT, + &&TARGET_LOAD_ATTR_METHOD_WITH_VALUES, + &&TARGET_LOAD_ATTR_MODULE, + &&TARGET_LOAD_ATTR_NONDESCRIPTOR_NO_DICT, + &&TARGET_LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES, + &&TARGET_LOAD_ATTR_PROPERTY, + &&TARGET_LOAD_ATTR_SLOT, + &&TARGET_LOAD_ATTR_WITH_HINT, + &&TARGET_LOAD_GLOBAL_BUILTIN, + &&TARGET_LOAD_GLOBAL_MODULE, + &&TARGET_LOAD_SUPER_ATTR_ATTR, + &&TARGET_LOAD_SUPER_ATTR_METHOD, + &&TARGET_RESUME_CHECK, + &&TARGET_SEND_GEN, + &&TARGET_STORE_ATTR_INSTANCE_VALUE, + &&TARGET_STORE_ATTR_SLOT, + &&TARGET_STORE_ATTR_WITH_HINT, + &&TARGET_STORE_SUBSCR_DICT, + &&TARGET_STORE_SUBSCR_LIST_INT, + &&TARGET_TO_BOOL_ALWAYS_TRUE, + &&TARGET_TO_BOOL_BOOL, + &&TARGET_TO_BOOL_INT, + &&TARGET_TO_BOOL_LIST, + &&TARGET_TO_BOOL_NONE, + &&TARGET_TO_BOOL_STR, + &&TARGET_UNPACK_SEQUENCE_LIST, + &&TARGET_UNPACK_SEQUENCE_TUPLE, + &&TARGET_UNPACK_SEQUENCE_TWO_TUPLE, &&_unknown_opcode, &&_unknown_opcode, &&_unknown_opcode, @@ -229,30 +229,30 @@ static void *opcode_targets[256] = { &&_unknown_opcode, &&_unknown_opcode, &&_unknown_opcode, - &&TARGET_ENTER_EXECUTOR, &&_unknown_opcode, &&_unknown_opcode, &&_unknown_opcode, &&_unknown_opcode, &&_unknown_opcode, &&_unknown_opcode, - &&TARGET_INSTRUMENTED_LOAD_SUPER_ATTR, - &&TARGET_INSTRUMENTED_POP_JUMP_IF_NONE, - &&TARGET_INSTRUMENTED_POP_JUMP_IF_NOT_NONE, &&TARGET_INSTRUMENTED_RESUME, - &&TARGET_INSTRUMENTED_CALL, + &&TARGET_INSTRUMENTED_END_FOR, + &&TARGET_INSTRUMENTED_END_SEND, &&TARGET_INSTRUMENTED_RETURN_VALUE, + &&TARGET_INSTRUMENTED_RETURN_CONST, &&TARGET_INSTRUMENTED_YIELD_VALUE, + &&TARGET_INSTRUMENTED_LOAD_SUPER_ATTR, + &&TARGET_INSTRUMENTED_FOR_ITER, + &&TARGET_INSTRUMENTED_CALL, + &&TARGET_INSTRUMENTED_CALL_KW, &&TARGET_INSTRUMENTED_CALL_FUNCTION_EX, + &&TARGET_INSTRUMENTED_INSTRUCTION, &&TARGET_INSTRUMENTED_JUMP_FORWARD, &&TARGET_INSTRUMENTED_JUMP_BACKWARD, - &&TARGET_INSTRUMENTED_RETURN_CONST, - &&TARGET_INSTRUMENTED_FOR_ITER, - &&TARGET_INSTRUMENTED_POP_JUMP_IF_FALSE, &&TARGET_INSTRUMENTED_POP_JUMP_IF_TRUE, - &&TARGET_INSTRUMENTED_END_FOR, - &&TARGET_INSTRUMENTED_END_SEND, - &&TARGET_INSTRUMENTED_INSTRUCTION, + &&TARGET_INSTRUMENTED_POP_JUMP_IF_FALSE, + &&TARGET_INSTRUMENTED_POP_JUMP_IF_NONE, + &&TARGET_INSTRUMENTED_POP_JUMP_IF_NOT_NONE, &&TARGET_INSTRUMENTED_LINE, - &&_unknown_opcode + &&_unknown_opcode, }; diff --git a/Python/optimizer.c b/Python/optimizer.c index d2ed8dfcd2cff2..227d6be0092419 100644 --- a/Python/optimizer.c +++ b/Python/optimizer.c @@ -1,18 +1,25 @@ #include "Python.h" #include "opcode.h" #include "pycore_interp.h" -#include "pycore_opcode.h" -#include "pycore_opcode_metadata.h" -#include "pycore_opcode_utils.h" +#include "pycore_bitutils.h" // _Py_popcount32() +#include "pycore_opcode_metadata.h" // _PyOpcode_OpName[] +#include "pycore_opcode_utils.h" // MAX_REAL_OPCODE +#include "pycore_optimizer.h" // _Py_uop_analyze_and_optimize() #include "pycore_pystate.h" // _PyInterpreterState_GET() +#include "pycore_uop_ids.h" #include "pycore_uops.h" #include "cpython/optimizer.h" #include #include #include +#define NEED_OPCODE_METADATA +#include "pycore_uop_metadata.h" // Uop tables +#undef NEED_OPCODE_METADATA + #define MAX_EXECUTORS_SIZE 256 + static bool has_space_for_executor(PyCodeObject *code, _Py_CODEUNIT *instr) { @@ -103,13 +110,15 @@ error_optimize( _PyOptimizerObject* self, PyCodeObject *code, _Py_CODEUNIT *instr, - _PyExecutorObject **exec) + _PyExecutorObject **exec, + int Py_UNUSED(stack_entries)) { + assert(0); PyErr_Format(PyExc_SystemError, "Should never call error_optimize"); return -1; } -static PyTypeObject DefaultOptimizer_Type = { +PyTypeObject _PyDefaultOptimizer_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) .tp_name = "noop_optimizer", .tp_basicsize = sizeof(_PyOptimizerObject), @@ -118,10 +127,10 @@ static PyTypeObject DefaultOptimizer_Type = { }; _PyOptimizerObject _PyOptimizer_Default = { - PyObject_HEAD_INIT(&DefaultOptimizer_Type) + PyObject_HEAD_INIT(&_PyDefaultOptimizer_Type) .optimize = error_optimize, - .resume_threshold = UINT16_MAX, - .backedge_threshold = UINT16_MAX, + .resume_threshold = INT16_MAX, + .backedge_threshold = INT16_MAX, }; _PyOptimizerObject * @@ -152,27 +161,23 @@ PyUnstable_SetOptimizer(_PyOptimizerObject *optimizer) Py_DECREF(old); } -_PyInterpreterFrame * -_PyOptimizer_BackEdge(_PyInterpreterFrame *frame, _Py_CODEUNIT *src, _Py_CODEUNIT *dest, PyObject **stack_pointer) +int +_PyOptimizer_Optimize(_PyInterpreterFrame *frame, _Py_CODEUNIT *start, PyObject **stack_pointer) { - assert(src->op.code == JUMP_BACKWARD); PyCodeObject *code = (PyCodeObject *)frame->f_executable; assert(PyCode_Check(code)); PyInterpreterState *interp = _PyInterpreterState_GET(); - if (!has_space_for_executor(code, src)) { - goto jump_to_destination; + if (!has_space_for_executor(code, start)) { + return 0; } _PyOptimizerObject *opt = interp->optimizer; _PyExecutorObject *executor = NULL; - int err = opt->optimize(opt, code, dest, &executor); + int err = opt->optimize(opt, code, start, &executor, (int)(stack_pointer - _PyFrame_Stackbase(frame))); if (err <= 0) { assert(executor == NULL); - if (err < 0) { - return NULL; - } - goto jump_to_destination; + return err; } - int index = get_index_for_executor(code, src); + int index = get_index_for_executor(code, start); if (index < 0) { /* Out of memory. Don't raise and assume that the * error will show up elsewhere. @@ -181,16 +186,11 @@ _PyOptimizer_BackEdge(_PyInterpreterFrame *frame, _Py_CODEUNIT *src, _Py_CODEUNI * it might get confused by the executor disappearing, * but there is not much we can do about that here. */ Py_DECREF(executor); - goto jump_to_destination; + return 0; } - insert_executor(code, src, index, executor); - assert(frame->prev_instr == src); - frame->prev_instr = dest - 1; - return executor->execute(executor, frame, stack_pointer); -jump_to_destination: - frame->prev_instr = dest - 1; - _PyFrame_SetStackPointer(frame, stack_pointer); - return frame; + insert_executor(code, start, index, executor); + Py_DECREF(executor); + return 1; } _PyExecutorObject * @@ -210,110 +210,28 @@ PyUnstable_GetExecutor(PyCodeObject *code, int offset) return NULL; } -/** Test support **/ - - -typedef struct { - _PyOptimizerObject base; - int64_t count; -} _PyCounterOptimizerObject; - -typedef struct { - _PyExecutorObject executor; - _PyCounterOptimizerObject *optimizer; - _Py_CODEUNIT *next_instr; -} _PyCounterExecutorObject; - -static void -counter_dealloc(_PyCounterExecutorObject *self) { - Py_DECREF(self->optimizer); - PyObject_Free(self); -} - -static PyTypeObject CounterExecutor_Type = { - PyVarObject_HEAD_INIT(&PyType_Type, 0) - .tp_name = "counting_executor", - .tp_basicsize = sizeof(_PyCounterExecutorObject), - .tp_itemsize = 0, - .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION, - .tp_dealloc = (destructor)counter_dealloc, -}; - -static _PyInterpreterFrame * -counter_execute(_PyExecutorObject *self, _PyInterpreterFrame *frame, PyObject **stack_pointer) -{ - ((_PyCounterExecutorObject *)self)->optimizer->count++; - _PyFrame_SetStackPointer(frame, stack_pointer); - frame->prev_instr = ((_PyCounterExecutorObject *)self)->next_instr - 1; - Py_DECREF(self); - return frame; -} - -static int -counter_optimize( - _PyOptimizerObject* self, - PyCodeObject *code, - _Py_CODEUNIT *instr, - _PyExecutorObject **exec_ptr) -{ - _PyCounterExecutorObject *executor = (_PyCounterExecutorObject *)_PyObject_New(&CounterExecutor_Type); - if (executor == NULL) { - return -1; - } - executor->executor.execute = counter_execute; - Py_INCREF(self); - executor->optimizer = (_PyCounterOptimizerObject *)self; - executor->next_instr = instr; - *exec_ptr = (_PyExecutorObject *)executor; - return 1; -} - static PyObject * -counter_get_counter(PyObject *self, PyObject *args) +is_valid(PyObject *self, PyObject *Py_UNUSED(ignored)) { - return PyLong_FromLongLong(((_PyCounterOptimizerObject *)self)->count); + return PyBool_FromLong(((_PyExecutorObject *)self)->vm_data.valid); } -static PyMethodDef counter_methods[] = { - { "get_count", counter_get_counter, METH_NOARGS, NULL }, +static PyMethodDef executor_methods[] = { + { "is_valid", is_valid, METH_NOARGS, NULL }, { NULL, NULL }, }; -static PyTypeObject CounterOptimizer_Type = { - PyVarObject_HEAD_INIT(&PyType_Type, 0) - .tp_name = "Counter optimizer", - .tp_basicsize = sizeof(_PyCounterOptimizerObject), - .tp_itemsize = 0, - .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION, - .tp_methods = counter_methods, -}; - -PyObject * -PyUnstable_Optimizer_NewCounter(void) -{ - _PyCounterOptimizerObject *opt = (_PyCounterOptimizerObject *)_PyObject_New(&CounterOptimizer_Type); - if (opt == NULL) { - return NULL; - } - opt->base.optimize = counter_optimize; - opt->base.resume_threshold = UINT16_MAX; - opt->base.backedge_threshold = 0; - opt->count = 0; - return (PyObject *)opt; -} - ///////////////////// Experimental UOp Optimizer ///////////////////// static void uop_dealloc(_PyUOpExecutorObject *self) { + _Py_ExecutorClear((_PyExecutorObject *)self); PyObject_Free(self); } -static const char * -uop_name(int index) { - if (index <= MAX_REAL_OPCODE) { - return _PyOpcode_OpName[index]; - } +const char * +_PyUOpName(int index) +{ return _PyOpcode_uop_name[index]; } @@ -331,7 +249,7 @@ uop_item(_PyUOpExecutorObject *self, Py_ssize_t index) PyErr_SetNone(PyExc_IndexError); return NULL; } - const char *name = uop_name(self->trace[index].opcode); + const char *name = _PyUOpName(self->trace[index].opcode); if (name == NULL) { name = ""; } @@ -359,83 +277,130 @@ PySequenceMethods uop_as_sequence = { .sq_item = (ssizeargfunc)uop_item, }; -static PyTypeObject UOpExecutor_Type = { +PyTypeObject _PyUOpExecutor_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) .tp_name = "uop_executor", - .tp_basicsize = sizeof(_PyUOpExecutorObject) - sizeof(_PyUOpInstruction), + .tp_basicsize = offsetof(_PyUOpExecutorObject, trace), .tp_itemsize = sizeof(_PyUOpInstruction), .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION, .tp_dealloc = (destructor)uop_dealloc, .tp_as_sequence = &uop_as_sequence, + .tp_methods = executor_methods, }; -static int -translate_bytecode_to_trace( - PyCodeObject *code, - _Py_CODEUNIT *instr, - _PyUOpInstruction *trace, - int buffer_size) -{ - _Py_CODEUNIT *initial_instr = instr; - int trace_length = 0; - int max_length = buffer_size; - int reserved = 0; +/* TO DO -- Generate these tables */ +static const uint16_t +_PyUOp_Replacements[MAX_UOP_ID + 1] = { + [_ITER_JUMP_RANGE] = _GUARD_NOT_EXHAUSTED_RANGE, + [_ITER_JUMP_LIST] = _GUARD_NOT_EXHAUSTED_LIST, + [_ITER_JUMP_TUPLE] = _GUARD_NOT_EXHAUSTED_TUPLE, + [_FOR_ITER] = _FOR_ITER_TIER_TWO, +}; -#ifdef Py_DEBUG - char *uop_debug = Py_GETENV("PYTHONUOPSDEBUG"); - int lltrace = 0; - if (uop_debug != NULL && *uop_debug >= '0') { - lltrace = *uop_debug - '0'; // TODO: Parse an int and all that - } -#endif +static const uint16_t +BRANCH_TO_GUARD[4][2] = { + [POP_JUMP_IF_FALSE - POP_JUMP_IF_FALSE][0] = _GUARD_IS_TRUE_POP, + [POP_JUMP_IF_FALSE - POP_JUMP_IF_FALSE][1] = _GUARD_IS_FALSE_POP, + [POP_JUMP_IF_TRUE - POP_JUMP_IF_FALSE][0] = _GUARD_IS_FALSE_POP, + [POP_JUMP_IF_TRUE - POP_JUMP_IF_FALSE][1] = _GUARD_IS_TRUE_POP, + [POP_JUMP_IF_NONE - POP_JUMP_IF_FALSE][0] = _GUARD_IS_NOT_NONE_POP, + [POP_JUMP_IF_NONE - POP_JUMP_IF_FALSE][1] = _GUARD_IS_NONE_POP, + [POP_JUMP_IF_NOT_NONE - POP_JUMP_IF_FALSE][0] = _GUARD_IS_NONE_POP, + [POP_JUMP_IF_NOT_NONE - POP_JUMP_IF_FALSE][1] = _GUARD_IS_NOT_NONE_POP, +}; + +#define TRACE_STACK_SIZE 5 + +#define CONFIDENCE_RANGE 1000 +#define CONFIDENCE_CUTOFF 333 #ifdef Py_DEBUG #define DPRINTF(level, ...) \ - if (lltrace >= (level)) { fprintf(stderr, __VA_ARGS__); } + if (lltrace >= (level)) { printf(__VA_ARGS__); } #else #define DPRINTF(level, ...) #endif -#define ADD_TO_TRACE(OPCODE, OPARG, OPERAND) \ + +#define ADD_TO_TRACE(OPCODE, OPARG, OPERAND, TARGET) \ DPRINTF(2, \ " ADD_TO_TRACE(%s, %d, %" PRIu64 ")\n", \ - uop_name(OPCODE), \ + _PyUOpName(OPCODE), \ (OPARG), \ (uint64_t)(OPERAND)); \ assert(trace_length < max_length); \ - assert(reserved > 0); \ - reserved--; \ trace[trace_length].opcode = (OPCODE); \ trace[trace_length].oparg = (OPARG); \ trace[trace_length].operand = (OPERAND); \ + trace[trace_length].target = (TARGET); \ trace_length++; #define INSTR_IP(INSTR, CODE) \ ((uint32_t)((INSTR) - ((_Py_CODEUNIT *)(CODE)->co_code_adaptive))) -#define ADD_TO_STUB(INDEX, OPCODE, OPARG, OPERAND) \ - DPRINTF(2, " ADD_TO_STUB(%d, %s, %d, %" PRIu64 ")\n", \ - (INDEX), \ - uop_name(OPCODE), \ - (OPARG), \ - (uint64_t)(OPERAND)); \ - assert(reserved > 0); \ - reserved--; \ - trace[(INDEX)].opcode = (OPCODE); \ - trace[(INDEX)].oparg = (OPARG); \ - trace[(INDEX)].operand = (OPERAND); - // Reserve space for n uops #define RESERVE_RAW(n, opname) \ if (trace_length + (n) > max_length) { \ DPRINTF(2, "No room for %s (need %d, got %d)\n", \ (opname), (n), max_length - trace_length); \ + OPT_STAT_INC(trace_too_long); \ goto done; \ + } + +// Reserve space for N uops, plus 3 for _SET_IP, _CHECK_VALIDITY and _EXIT_TRACE +#define RESERVE(needed) RESERVE_RAW((needed) + 3, _PyUOpName(opcode)) + +// Trace stack operations (used by _PUSH_FRAME, _POP_FRAME) +#define TRACE_STACK_PUSH() \ + if (trace_stack_depth >= TRACE_STACK_SIZE) { \ + DPRINTF(2, "Trace stack overflow\n"); \ + OPT_STAT_INC(trace_stack_overflow); \ + ADD_TO_TRACE(_EXIT_TRACE, 0, 0, 0); \ + goto done; \ + } \ + trace_stack[trace_stack_depth].code = code; \ + trace_stack[trace_stack_depth].instr = instr; \ + trace_stack_depth++; +#define TRACE_STACK_POP() \ + if (trace_stack_depth <= 0) { \ + Py_FatalError("Trace stack underflow\n"); \ } \ - reserved = (n); // Keep ADD_TO_TRACE / ADD_TO_STUB honest + trace_stack_depth--; \ + code = trace_stack[trace_stack_depth].code; \ + instr = trace_stack[trace_stack_depth].instr; -// Reserve space for main+stub uops, plus 2 for SAVE_IP and EXIT_TRACE -#define RESERVE(main, stub) RESERVE_RAW((main) + (stub) + 2, uop_name(opcode)) +/* Returns 1 on success, + * 0 if it failed to produce a worthwhile trace, + * and -1 on an error. + */ +static int +translate_bytecode_to_trace( + PyCodeObject *code, + _Py_CODEUNIT *instr, + _PyUOpInstruction *trace, + int buffer_size, + _PyBloomFilter *dependencies) +{ + bool progress_needed = true; + PyCodeObject *initial_code = code; + _Py_BloomFilter_Add(dependencies, initial_code); + _Py_CODEUNIT *initial_instr = instr; + int trace_length = 0; + int max_length = buffer_size; + struct { + PyCodeObject *code; + _Py_CODEUNIT *instr; + } trace_stack[TRACE_STACK_SIZE]; + int trace_stack_depth = 0; + int confidence = CONFIDENCE_RANGE; // Adjusted by branch instructions + +#ifdef Py_DEBUG + char *python_lltrace = Py_GETENV("PYTHON_LLTRACE"); + int lltrace = 0; + if (python_lltrace != NULL && *python_lltrace >= '0') { + lltrace = *python_lltrace - '0'; // TODO: Parse an int and all that + } +#endif DPRINTF(4, "Optimizing %s (%s:%d) at byte offset %d\n", @@ -443,72 +408,105 @@ translate_bytecode_to_trace( PyUnicode_AsUTF8(code->co_filename), code->co_firstlineno, 2 * INSTR_IP(initial_instr, code)); + uint32_t target = 0; +top: // Jump here after _PUSH_FRAME or likely branches for (;;) { - RESERVE_RAW(2, "epilogue"); // Always need space for SAVE_IP and EXIT_TRACE - ADD_TO_TRACE(SAVE_IP, INSTR_IP(instr, code), 0); + target = INSTR_IP(instr, code); + RESERVE_RAW(3, "epilogue"); // Always need space for _SET_IP, _CHECK_VALIDITY and _EXIT_TRACE + ADD_TO_TRACE(_SET_IP, target, 0, target); + ADD_TO_TRACE(_CHECK_VALIDITY, 0, 0, target); uint32_t opcode = instr->op.code; uint32_t oparg = instr->op.arg; - uint32_t extras = 0; - - while (opcode == EXTENDED_ARG) { - instr++; - extras += 1; - opcode = instr->op.code; - oparg = (oparg << 8) | instr->op.arg; - } + uint32_t extended = 0; if (opcode == ENTER_EXECUTOR) { + assert(oparg < 256); _PyExecutorObject *executor = - (_PyExecutorObject *)code->co_executors->executors[oparg&255]; + (_PyExecutorObject *)code->co_executors->executors[oparg]; opcode = executor->vm_data.opcode; DPRINTF(2, " * ENTER_EXECUTOR -> %s\n", _PyOpcode_OpName[opcode]); - oparg = (oparg & 0xffffff00) | executor->vm_data.oparg; + oparg = executor->vm_data.oparg; } - switch (opcode) { - - case POP_JUMP_IF_NONE: - { - RESERVE(2, 2); - ADD_TO_TRACE(IS_NONE, 0, 0); - opcode = POP_JUMP_IF_TRUE; - goto pop_jump_if_bool; + if (opcode == EXTENDED_ARG) { + instr++; + extended = 1; + opcode = instr->op.code; + oparg = (oparg << 8) | instr->op.arg; + if (opcode == EXTENDED_ARG) { + instr--; + goto done; } + } + assert(opcode != ENTER_EXECUTOR && opcode != EXTENDED_ARG); - case POP_JUMP_IF_NOT_NONE: - { - RESERVE(2, 2); - ADD_TO_TRACE(IS_NONE, 0, 0); - opcode = POP_JUMP_IF_FALSE; - goto pop_jump_if_bool; + /* Special case the first instruction, + * so that we can guarantee forward progress */ + if (progress_needed) { + progress_needed = false; + if (opcode == JUMP_BACKWARD || opcode == JUMP_BACKWARD_NO_INTERRUPT) { + instr += 1 + _PyOpcode_Caches[opcode] - (int32_t)oparg; + initial_instr = instr; + continue; + } + else { + if (OPCODE_HAS_DEOPT(opcode)) { + opcode = _PyOpcode_Deopt[opcode]; + } + assert(!OPCODE_HAS_DEOPT(opcode)); } + } + switch (opcode) { + case POP_JUMP_IF_NONE: + case POP_JUMP_IF_NOT_NONE: case POP_JUMP_IF_FALSE: case POP_JUMP_IF_TRUE: { -pop_jump_if_bool: - // Assume jump unlikely (TODO: handle jump likely case) - RESERVE(1, 2); - _Py_CODEUNIT *target_instr = - instr + 1 + _PyOpcode_Caches[_PyOpcode_Deopt[opcode]] + oparg; - max_length -= 2; // Really the start of the stubs - uint32_t uopcode = opcode == POP_JUMP_IF_TRUE ? - _POP_JUMP_IF_TRUE : _POP_JUMP_IF_FALSE; - ADD_TO_TRACE(uopcode, max_length, 0); - ADD_TO_STUB(max_length, SAVE_IP, INSTR_IP(target_instr, code), 0); - ADD_TO_STUB(max_length + 1, EXIT_TRACE, 0, 0); + RESERVE(1); + int counter = instr[1].cache; + int bitcount = _Py_popcount32(counter); + int jump_likely = bitcount > 8; + if (jump_likely) { + confidence = confidence * bitcount / 16; + } + else { + confidence = confidence * (16 - bitcount) / 16; + } + if (confidence < CONFIDENCE_CUTOFF) { + DPRINTF(2, "Confidence too low (%d)\n", confidence); + OPT_STAT_INC(low_confidence); + goto done; + } + uint32_t uopcode = BRANCH_TO_GUARD[opcode - POP_JUMP_IF_FALSE][jump_likely]; + _Py_CODEUNIT *next_instr = instr + 1 + _PyOpcode_Caches[_PyOpcode_Deopt[opcode]]; + DPRINTF(2, "%s(%d): counter=%x, bitcount=%d, likely=%d, confidence=%d, uopcode=%s\n", + _PyOpcode_OpName[opcode], oparg, + counter, bitcount, jump_likely, confidence, _PyUOpName(uopcode)); + ADD_TO_TRACE(uopcode, max_length, 0, target); + if (jump_likely) { + _Py_CODEUNIT *target_instr = next_instr + oparg; + DPRINTF(2, "Jump likely (%x = %d bits), continue at byte offset %d\n", + instr[1].cache, bitcount, 2 * INSTR_IP(target_instr, code)); + instr = target_instr; + goto top; + } break; } case JUMP_BACKWARD: + case JUMP_BACKWARD_NO_INTERRUPT: { - if (instr + 2 - oparg == initial_instr) { - RESERVE(1, 0); - ADD_TO_TRACE(JUMP_TO_TOP, 0, 0); + _Py_CODEUNIT *target = instr + 1 + _PyOpcode_Caches[opcode] - (int)oparg; + if (target == initial_instr) { + /* We have looped round to the start */ + RESERVE(1); + ADD_TO_TRACE(_JUMP_TO_TOP, 0, 0, 0); } else { + OPT_STAT_INC(inner_loop); DPRINTF(2, "JUMP_BACKWARD not to top ends trace\n"); } goto done; @@ -516,76 +514,39 @@ translate_bytecode_to_trace( case JUMP_FORWARD: { - RESERVE(0, 0); - // This will emit two SAVE_IP instructions; leave it to the optimizer + RESERVE(0); + // This will emit two _SET_IP instructions; leave it to the optimizer instr += oparg; break; } - case FOR_ITER_LIST: - case FOR_ITER_TUPLE: - case FOR_ITER_RANGE: - { - RESERVE(4, 3); - int check_op, exhausted_op, next_op; - switch (opcode) { - case FOR_ITER_LIST: - check_op = _ITER_CHECK_LIST; - exhausted_op = _IS_ITER_EXHAUSTED_LIST; - next_op = _ITER_NEXT_LIST; - break; - case FOR_ITER_TUPLE: - check_op = _ITER_CHECK_TUPLE; - exhausted_op = _IS_ITER_EXHAUSTED_TUPLE; - next_op = _ITER_NEXT_TUPLE; - break; - case FOR_ITER_RANGE: - check_op = _ITER_CHECK_RANGE; - exhausted_op = _IS_ITER_EXHAUSTED_RANGE; - next_op = _ITER_NEXT_RANGE; - break; - default: - Py_UNREACHABLE(); - } - // Assume jump unlikely (can a for-loop exit be likely?) - _Py_CODEUNIT *target_instr = // +1 at the end skips over END_FOR - instr + 1 + _PyOpcode_Caches[_PyOpcode_Deopt[opcode]] + oparg + 1; - max_length -= 3; // Really the start of the stubs - ADD_TO_TRACE(check_op, 0, 0); - ADD_TO_TRACE(exhausted_op, 0, 0); - ADD_TO_TRACE(_POP_JUMP_IF_TRUE, max_length, 0); - ADD_TO_TRACE(next_op, 0, 0); - - ADD_TO_STUB(max_length + 0, POP_TOP, 0, 0); - ADD_TO_STUB(max_length + 1, SAVE_IP, INSTR_IP(target_instr, code), 0); - ADD_TO_STUB(max_length + 2, EXIT_TRACE, 0, 0); - break; - } - default: { const struct opcode_macro_expansion *expansion = &_PyOpcode_macro_expansion[opcode]; if (expansion->nuops > 0) { - // Reserve space for nuops (+ SAVE_IP + EXIT_TRACE) + // Reserve space for nuops (+ _SET_IP + _EXIT_TRACE) int nuops = expansion->nuops; - RESERVE(nuops, 0); + RESERVE(nuops); + if (expansion->uops[nuops-1].uop == _POP_FRAME) { + // Check for trace stack underflow now: + // We can't bail e.g. in the middle of + // LOAD_CONST + _POP_FRAME. + if (trace_stack_depth == 0) { + DPRINTF(2, "Trace stack underflow\n"); + OPT_STAT_INC(trace_stack_underflow); + goto done; + } + } uint32_t orig_oparg = oparg; // For OPARG_TOP/BOTTOM for (int i = 0; i < nuops; i++) { oparg = orig_oparg; + uint32_t uop = expansion->uops[i].uop; uint64_t operand = 0; // Add one to account for the actual opcode/oparg pair: int offset = expansion->uops[i].offset + 1; switch (expansion->uops[i].size) { case OPARG_FULL: - if (extras && OPCODE_HAS_JUMP(opcode)) { - if (opcode == JUMP_BACKWARD_NO_INTERRUPT) { - oparg -= extras; - } - else { - assert(opcode != JUMP_BACKWARD); - oparg += extras; - } - } + assert(opcode != JUMP_BACKWARD_NO_INTERRUPT && opcode != JUMP_BACKWARD); break; case OPARG_CACHE_1: operand = read_u16(&instr[offset].cache); @@ -602,6 +563,19 @@ translate_bytecode_to_trace( case OPARG_BOTTOM: // Second half of super-instr oparg = orig_oparg & 0xF; break; + case OPARG_SAVE_RETURN_OFFSET: // op=_SAVE_RETURN_OFFSET; oparg=return_offset + oparg = offset; + assert(uop == _SAVE_RETURN_OFFSET); + break; + case OPARG_REPLACED: + uop = _PyUOp_Replacements[uop]; + assert(uop != 0); + if (uop == _FOR_ITER_TIER_TWO) { + target += 1 + INLINE_CACHE_ENTRIES_FOR_ITER + oparg + 1 + extended; + assert(_PyCode_CODE(code)[target-1].op.code == END_FOR || + _PyCode_CODE(code)[target-1].op.code == INSTRUMENTED_END_FOR); + } + break; default: fprintf(stderr, "opcode=%d, oparg=%d; nuops=%d, i=%d; size=%d, offset=%d\n", @@ -610,11 +584,68 @@ translate_bytecode_to_trace( expansion->uops[i].offset); Py_FatalError("garbled expansion"); } - ADD_TO_TRACE(expansion->uops[i].uop, oparg, operand); + ADD_TO_TRACE(uop, oparg, operand, target); + if (uop == _POP_FRAME) { + TRACE_STACK_POP(); + DPRINTF(2, + "Returning to %s (%s:%d) at byte offset %d\n", + PyUnicode_AsUTF8(code->co_qualname), + PyUnicode_AsUTF8(code->co_filename), + code->co_firstlineno, + 2 * INSTR_IP(instr, code)); + goto top; + } + if (uop == _PUSH_FRAME) { + assert(i + 1 == nuops); + int func_version_offset = + offsetof(_PyCallCache, func_version)/sizeof(_Py_CODEUNIT) + // Add one to account for the actual opcode/oparg pair: + + 1; + uint32_t func_version = read_u32(&instr[func_version_offset].cache); + PyFunctionObject *func = _PyFunction_LookupByVersion(func_version); + DPRINTF(3, "Function object: %p\n", func); + if (func != NULL) { + PyCodeObject *new_code = (PyCodeObject *)PyFunction_GET_CODE(func); + if (new_code == code) { + // Recursive call, bail (we could be here forever). + DPRINTF(2, "Bailing on recursive call to %s (%s:%d)\n", + PyUnicode_AsUTF8(new_code->co_qualname), + PyUnicode_AsUTF8(new_code->co_filename), + new_code->co_firstlineno); + OPT_STAT_INC(recursive_call); + ADD_TO_TRACE(_EXIT_TRACE, 0, 0, 0); + goto done; + } + if (new_code->co_version != func_version) { + // func.__code__ was updated. + // Perhaps it may happen again, so don't bother tracing. + // TODO: Reason about this -- is it better to bail or not? + DPRINTF(2, "Bailing because co_version != func_version\n"); + ADD_TO_TRACE(_EXIT_TRACE, 0, 0, 0); + goto done; + } + // Increment IP to the return address + instr += _PyOpcode_Caches[_PyOpcode_Deopt[opcode]] + 1; + TRACE_STACK_PUSH(); + _Py_BloomFilter_Add(dependencies, new_code); + code = new_code; + instr = _PyCode_CODE(code); + DPRINTF(2, + "Continuing in %s (%s:%d) at byte offset %d\n", + PyUnicode_AsUTF8(code->co_qualname), + PyUnicode_AsUTF8(code->co_filename), + code->co_firstlineno, + 2 * INSTR_IP(instr, code)); + goto top; + } + ADD_TO_TRACE(_EXIT_TRACE, 0, 0, 0); + goto done; + } } break; } - DPRINTF(2, "Unsupported opcode %s\n", uop_name(opcode)); + DPRINTF(2, "Unsupported opcode %s\n", _PyOpcode_OpName[opcode]); + OPT_UNSUPPORTED_OPCODE(opcode); goto done; // Break out of loop } // End default @@ -626,57 +657,132 @@ translate_bytecode_to_trace( } // End for (;;) done: - // Skip short traces like SAVE_IP, LOAD_FAST, SAVE_IP, EXIT_TRACE - if (trace_length > 3) { - ADD_TO_TRACE(EXIT_TRACE, 0, 0); - DPRINTF(1, - "Created a trace for %s (%s:%d) at byte offset %d -- length %d\n", - PyUnicode_AsUTF8(code->co_qualname), - PyUnicode_AsUTF8(code->co_filename), - code->co_firstlineno, - 2 * INSTR_IP(initial_instr, code), - trace_length); - if (max_length < buffer_size && trace_length < max_length) { - // Move the stubs back to be immediately after the main trace - // (which ends at trace_length) - DPRINTF(2, - "Moving %d stub uops back by %d\n", - buffer_size - max_length, - max_length - trace_length); - memmove(trace + trace_length, - trace + max_length, - (buffer_size - max_length) * sizeof(_PyUOpInstruction)); - // Patch up the jump targets - for (int i = 0; i < trace_length; i++) { - if (trace[i].opcode == _POP_JUMP_IF_FALSE || - trace[i].opcode == _POP_JUMP_IF_TRUE) - { - int target = trace[i].oparg; - if (target >= max_length) { - target += trace_length - max_length; - trace[i].oparg = target; - } - } - } - } - trace_length += buffer_size - max_length; - return trace_length; + while (trace_stack_depth > 0) { + TRACE_STACK_POP(); } - else { + assert(code == initial_code); + // Skip short traces like _SET_IP, LOAD_FAST, _SET_IP, _EXIT_TRACE + if (progress_needed || trace_length < 5) { + OPT_STAT_INC(trace_too_short); DPRINTF(4, "No trace for %s (%s:%d) at byte offset %d\n", PyUnicode_AsUTF8(code->co_qualname), PyUnicode_AsUTF8(code->co_filename), code->co_firstlineno, 2 * INSTR_IP(initial_instr, code)); + return 0; } - return 0; + ADD_TO_TRACE(_EXIT_TRACE, 0, 0, target); + DPRINTF(1, + "Created a trace for %s (%s:%d) at byte offset %d -- length %d\n", + PyUnicode_AsUTF8(code->co_qualname), + PyUnicode_AsUTF8(code->co_filename), + code->co_firstlineno, + 2 * INSTR_IP(initial_instr, code), + trace_length); + OPT_HIST(trace_length + buffer_size - max_length, trace_length_hist); + return 1; +} #undef RESERVE #undef RESERVE_RAW #undef INSTR_IP #undef ADD_TO_TRACE #undef DPRINTF + +#define UNSET_BIT(array, bit) (array[(bit)>>5] &= ~(1<<((bit)&31))) +#define SET_BIT(array, bit) (array[(bit)>>5] |= (1<<((bit)&31))) +#define BIT_IS_SET(array, bit) (array[(bit)>>5] & (1<<((bit)&31))) + +/* Count the number of used uops, and mark them in the bit vector `used`. + * This can be done in a single pass using simple reachability analysis, + * as there are no backward jumps. + * NOPs are excluded from the count. +*/ +static int +compute_used(_PyUOpInstruction *buffer, uint32_t *used) +{ + int count = 0; + SET_BIT(used, 0); + for (int i = 0; i < _Py_UOP_MAX_TRACE_LENGTH; i++) { + if (!BIT_IS_SET(used, i)) { + continue; + } + count++; + int opcode = buffer[i].opcode; + if (opcode == _JUMP_TO_TOP || opcode == _EXIT_TRACE) { + continue; + } + /* All other micro-ops fall through, so i+1 is reachable */ + SET_BIT(used, i+1); + assert(opcode <= MAX_UOP_ID); + if (_PyUop_Flags[opcode] & HAS_JUMP_FLAG) { + /* Mark target as reachable */ + SET_BIT(used, buffer[i].oparg); + } + if (opcode == NOP) { + count--; + UNSET_BIT(used, i); + } + } + return count; +} + +/* Makes an executor from a buffer of uops. + * Account for the buffer having gaps and NOPs by computing a "used" + * bit vector and only copying the used uops. Here "used" means reachable + * and not a NOP. + */ +static _PyExecutorObject * +make_executor_from_uops(_PyUOpInstruction *buffer, _PyBloomFilter *dependencies) +{ + uint32_t used[(_Py_UOP_MAX_TRACE_LENGTH + 31)/32] = { 0 }; + int length = compute_used(buffer, used); + _PyUOpExecutorObject *executor = PyObject_NewVar(_PyUOpExecutorObject, &_PyUOpExecutor_Type, length); + if (executor == NULL) { + return NULL; + } + int dest = length - 1; + /* Scan backwards, so that we see the destinations of jumps before the jumps themselves. */ + for (int i = _Py_UOP_MAX_TRACE_LENGTH-1; i >= 0; i--) { + if (!BIT_IS_SET(used, i)) { + continue; + } + executor->trace[dest] = buffer[i]; + int opcode = buffer[i].opcode; + if (opcode == _POP_JUMP_IF_FALSE || + opcode == _POP_JUMP_IF_TRUE) + { + /* The oparg of the target will already have been set to its new offset */ + int oparg = executor->trace[dest].oparg; + executor->trace[dest].oparg = buffer[oparg].oparg; + } + /* Set the oparg to be the destination offset, + * so that we can set the oparg of earlier jumps correctly. */ + buffer[i].oparg = dest; + dest--; + } + assert(dest == -1); + _Py_ExecutorInit((_PyExecutorObject *)executor, dependencies); +#ifdef Py_DEBUG + char *python_lltrace = Py_GETENV("PYTHON_LLTRACE"); + int lltrace = 0; + if (python_lltrace != NULL && *python_lltrace >= '0') { + lltrace = *python_lltrace - '0'; // TODO: Parse an int and all that + } + if (lltrace >= 2) { + printf("Optimized executor (length %d):\n", length); + for (int i = 0; i < length; i++) { + printf("%4d %s(%d, %d, %" PRIu64 ")\n", + i, + _PyUOpName(executor->trace[i].opcode), + executor->trace[i].oparg, + executor->trace[i].target, + executor->trace[i].operand); + } + } +#endif + return (_PyExecutorObject *)executor; } static int @@ -684,22 +790,31 @@ uop_optimize( _PyOptimizerObject *self, PyCodeObject *code, _Py_CODEUNIT *instr, - _PyExecutorObject **exec_ptr) + _PyExecutorObject **exec_ptr, + int curr_stackentries) { - _PyUOpInstruction trace[_Py_UOP_MAX_TRACE_LENGTH]; - int trace_length = translate_bytecode_to_trace(code, instr, trace, _Py_UOP_MAX_TRACE_LENGTH); - if (trace_length <= 0) { + _PyBloomFilter dependencies; + _Py_BloomFilter_Init(&dependencies); + _PyUOpInstruction buffer[_Py_UOP_MAX_TRACE_LENGTH]; + int err = translate_bytecode_to_trace(code, instr, buffer, _Py_UOP_MAX_TRACE_LENGTH, &dependencies); + if (err <= 0) { // Error or nothing translated - return trace_length; + return err; } - OBJECT_STAT_INC(optimization_traces_created); - _PyUOpExecutorObject *executor = PyObject_NewVar(_PyUOpExecutorObject, &UOpExecutor_Type, trace_length); + OPT_STAT_INC(traces_created); + char *uop_optimize = Py_GETENV("PYTHONUOPSOPTIMIZE"); + if (uop_optimize == NULL || *uop_optimize > '0') { + err = _Py_uop_analyze_and_optimize(code, buffer, _Py_UOP_MAX_TRACE_LENGTH, curr_stackentries); + if (err < 0) { + return -1; + } + } + _PyExecutorObject *executor = make_executor_from_uops(buffer, &dependencies); if (executor == NULL) { return -1; } - executor->base.execute = _PyUopExecute; - memcpy(executor->trace, trace, trace_length * sizeof(_PyUOpInstruction)); - *exec_ptr = (_PyExecutorObject *)executor; + OPT_HIST(Py_SIZE(executor), optimized_trace_length_hist); + *exec_ptr = executor; return 1; } @@ -708,7 +823,7 @@ uop_opt_dealloc(PyObject *self) { PyObject_Free(self); } -static PyTypeObject UOpOptimizer_Type = { +PyTypeObject _PyUOpOptimizer_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) .tp_name = "uop_optimizer", .tp_basicsize = sizeof(_PyOptimizerObject), @@ -720,14 +835,305 @@ static PyTypeObject UOpOptimizer_Type = { PyObject * PyUnstable_Optimizer_NewUOpOptimizer(void) { - _PyOptimizerObject *opt = PyObject_New(_PyOptimizerObject, &UOpOptimizer_Type); + _PyOptimizerObject *opt = PyObject_New(_PyOptimizerObject, &_PyUOpOptimizer_Type); if (opt == NULL) { return NULL; } opt->optimize = uop_optimize; - opt->resume_threshold = UINT16_MAX; + opt->resume_threshold = INT16_MAX; // Need at least 3 iterations to settle specializations. // A few lower bits of the counter are reserved for other flags. - opt->backedge_threshold = 3 << OPTIMIZER_BITS_IN_COUNTER; + opt->backedge_threshold = 16 << OPTIMIZER_BITS_IN_COUNTER; return (PyObject *)opt; } + +static void +counter_dealloc(_PyUOpExecutorObject *self) { + PyObject *opt = (PyObject *)self->trace[0].operand; + Py_DECREF(opt); + uop_dealloc(self); +} + +PyTypeObject _PyCounterExecutor_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + .tp_name = "counting_executor", + .tp_basicsize = offsetof(_PyUOpExecutorObject, trace), + .tp_itemsize = sizeof(_PyUOpInstruction), + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION, + .tp_dealloc = (destructor)counter_dealloc, + .tp_methods = executor_methods, +}; + +static int +counter_optimize( + _PyOptimizerObject* self, + PyCodeObject *code, + _Py_CODEUNIT *instr, + _PyExecutorObject **exec_ptr, + int Py_UNUSED(curr_stackentries) +) +{ + int oparg = instr->op.arg; + while (instr->op.code == EXTENDED_ARG) { + instr++; + oparg = (oparg << 8) | instr->op.arg; + } + if (instr->op.code != JUMP_BACKWARD) { + /* Counter optimizer can only handle backward edges */ + return 0; + } + _Py_CODEUNIT *target = instr + 1 + _PyOpcode_Caches[JUMP_BACKWARD] - oparg; + _PyUOpInstruction buffer[3] = { + { .opcode = _LOAD_CONST_INLINE_BORROW, .operand = (uintptr_t)self }, + { .opcode = _INTERNAL_INCREMENT_OPT_COUNTER }, + { .opcode = _EXIT_TRACE, .target = (uint32_t)(target - _PyCode_CODE(code)) } + }; + _PyBloomFilter empty; + _Py_BloomFilter_Init(&empty); + _PyExecutorObject *executor = make_executor_from_uops(buffer, &empty); + if (executor == NULL) { + return -1; + } + Py_INCREF(self); + Py_SET_TYPE(executor, &_PyCounterExecutor_Type); + *exec_ptr = executor; + return 1; +} + +static PyObject * +counter_get_counter(PyObject *self, PyObject *args) +{ + return PyLong_FromLongLong(((_PyCounterOptimizerObject *)self)->count); +} + +static PyMethodDef counter_optimizer_methods[] = { + { "get_count", counter_get_counter, METH_NOARGS, NULL }, + { NULL, NULL }, +}; + +PyTypeObject _PyCounterOptimizer_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + .tp_name = "Counter optimizer", + .tp_basicsize = sizeof(_PyCounterOptimizerObject), + .tp_itemsize = 0, + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION, + .tp_methods = counter_optimizer_methods, + .tp_dealloc = (destructor)PyObject_Del, +}; + +PyObject * +PyUnstable_Optimizer_NewCounter(void) +{ + _PyCounterOptimizerObject *opt = (_PyCounterOptimizerObject *)_PyObject_New(&_PyCounterOptimizer_Type); + if (opt == NULL) { + return NULL; + } + opt->base.optimize = counter_optimize; + opt->base.resume_threshold = INT16_MAX; + opt->base.backedge_threshold = 0; + opt->count = 0; + return (PyObject *)opt; +} + + +/***************************************** + * Executor management + ****************************************/ + +/* We use a bloomfilter with k = 6, m = 256 + * The choice of k and the following constants + * could do with a more rigourous analysis, + * but here is a simple analysis: + * + * We want to keep the false positive rate low. + * For n = 5 (a trace depends on 5 objects), + * we expect 30 bits set, giving a false positive + * rate of (30/256)**6 == 2.5e-6 which is plenty + * good enough. + * + * However with n = 10 we expect 60 bits set (worst case), + * giving a false positive of (60/256)**6 == 0.0001 + * + * We choose k = 6, rather than a higher number as + * it means the false positive rate grows slower for high n. + * + * n = 5, k = 6 => fp = 2.6e-6 + * n = 5, k = 8 => fp = 3.5e-7 + * n = 10, k = 6 => fp = 1.6e-4 + * n = 10, k = 8 => fp = 0.9e-4 + * n = 15, k = 6 => fp = 0.18% + * n = 15, k = 8 => fp = 0.23% + * n = 20, k = 6 => fp = 1.1% + * n = 20, k = 8 => fp = 2.3% + * + * The above analysis assumes perfect hash functions, + * but those don't exist, so the real false positive + * rates may be worse. + */ + +#define K 6 + +#define SEED 20221211 + +/* TO DO -- Use more modern hash functions with better distribution of bits */ +static uint64_t +address_to_hash(void *ptr) { + assert(ptr != NULL); + uint64_t uhash = SEED; + uintptr_t addr = (uintptr_t)ptr; + for (int i = 0; i < SIZEOF_VOID_P; i++) { + uhash ^= addr & 255; + uhash *= (uint64_t)_PyHASH_MULTIPLIER; + addr >>= 8; + } + return uhash; +} + +void +_Py_BloomFilter_Init(_PyBloomFilter *bloom) +{ + for (int i = 0; i < BLOOM_FILTER_WORDS; i++) { + bloom->bits[i] = 0; + } +} + +/* We want K hash functions that each set 1 bit. + * A hash function that sets 1 bit in M bits can be trivially + * derived from a log2(M) bit hash function. + * So we extract 8 (log2(256)) bits at a time from + * the 64bit hash. */ +void +_Py_BloomFilter_Add(_PyBloomFilter *bloom, void *ptr) +{ + uint64_t hash = address_to_hash(ptr); + assert(K <= 8); + for (int i = 0; i < K; i++) { + uint8_t bits = hash & 255; + bloom->bits[bits >> 5] |= (1 << (bits&31)); + hash >>= 8; + } +} + +static bool +bloom_filter_may_contain(_PyBloomFilter *bloom, _PyBloomFilter *hashes) +{ + for (int i = 0; i < BLOOM_FILTER_WORDS; i++) { + if ((bloom->bits[i] & hashes->bits[i]) != hashes->bits[i]) { + return false; + } + } + return true; +} + +static void +link_executor(_PyExecutorObject *executor) +{ + PyInterpreterState *interp = _PyInterpreterState_GET(); + _PyExecutorLinkListNode *links = &executor->vm_data.links; + _PyExecutorObject *head = interp->executor_list_head; + if (head == NULL) { + interp->executor_list_head = executor; + links->previous = NULL; + links->next = NULL; + } + else { + _PyExecutorObject *next = head->vm_data.links.next; + links->previous = head; + links->next = next; + if (next != NULL) { + next->vm_data.links.previous = executor; + } + head->vm_data.links.next = executor; + } + executor->vm_data.linked = true; + /* executor_list_head must be first in list */ + assert(interp->executor_list_head->vm_data.links.previous == NULL); +} + +static void +unlink_executor(_PyExecutorObject *executor) +{ + if (!executor->vm_data.linked) { + return; + } + _PyExecutorLinkListNode *links = &executor->vm_data.links; + _PyExecutorObject *next = links->next; + _PyExecutorObject *prev = links->previous; + if (next != NULL) { + next->vm_data.links.previous = prev; + } + if (prev != NULL) { + prev->vm_data.links.next = next; + } + else { + // prev == NULL implies that executor is the list head + PyInterpreterState *interp = PyInterpreterState_Get(); + assert(interp->executor_list_head == executor); + interp->executor_list_head = next; + } + executor->vm_data.linked = false; +} + +/* This must be called by optimizers before using the executor */ +void +_Py_ExecutorInit(_PyExecutorObject *executor, _PyBloomFilter *dependency_set) +{ + executor->vm_data.valid = true; + for (int i = 0; i < BLOOM_FILTER_WORDS; i++) { + executor->vm_data.bloom.bits[i] = dependency_set->bits[i]; + } + link_executor(executor); +} + +/* This must be called by executors during dealloc */ +void +_Py_ExecutorClear(_PyExecutorObject *executor) +{ + unlink_executor(executor); +} + +void +_Py_Executor_DependsOn(_PyExecutorObject *executor, void *obj) +{ + assert(executor->vm_data.valid = true); + _Py_BloomFilter_Add(&executor->vm_data.bloom, obj); +} + +/* Invalidate all executors that depend on `obj` + * May cause other executors to be invalidated as well + */ +void +_Py_Executors_InvalidateDependency(PyInterpreterState *interp, void *obj) +{ + _PyBloomFilter obj_filter; + _Py_BloomFilter_Init(&obj_filter); + _Py_BloomFilter_Add(&obj_filter, obj); + /* Walk the list of executors */ + /* TO DO -- Use a tree to avoid traversing as many objects */ + for (_PyExecutorObject *exec = interp->executor_list_head; exec != NULL;) { + assert(exec->vm_data.valid); + _PyExecutorObject *next = exec->vm_data.links.next; + if (bloom_filter_may_contain(&exec->vm_data.bloom, &obj_filter)) { + exec->vm_data.valid = false; + unlink_executor(exec); + } + exec = next; + } +} + +/* Invalidate all executors */ +void +_Py_Executors_InvalidateAll(PyInterpreterState *interp) +{ + /* Walk the list of executors */ + for (_PyExecutorObject *exec = interp->executor_list_head; exec != NULL;) { + assert(exec->vm_data.valid); + _PyExecutorObject *next = exec->vm_data.links.next; + exec->vm_data.links.next = NULL; + exec->vm_data.links.previous = NULL; + exec->vm_data.valid = false; + exec->vm_data.linked = false; + exec = next; + } + interp->executor_list_head = NULL; +} diff --git a/Python/optimizer_analysis.c b/Python/optimizer_analysis.c new file mode 100644 index 00000000000000..4eb2d9711f5e56 --- /dev/null +++ b/Python/optimizer_analysis.c @@ -0,0 +1,65 @@ +#include "Python.h" +#include "opcode.h" +#include "pycore_interp.h" +#include "pycore_opcode_metadata.h" +#include "pycore_opcode_utils.h" +#include "pycore_pystate.h" // _PyInterpreterState_GET() +#include "pycore_uop_metadata.h" +#include "pycore_uops.h" +#include "pycore_long.h" +#include "cpython/optimizer.h" +#include +#include +#include +#include "pycore_optimizer.h" + +static void +remove_unneeded_uops(_PyUOpInstruction *buffer, int buffer_size) +{ + int last_set_ip = -1; + bool maybe_invalid = false; + for (int pc = 0; pc < buffer_size; pc++) { + int opcode = buffer[pc].opcode; + if (opcode == _SET_IP) { + buffer[pc].opcode = NOP; + last_set_ip = pc; + } + else if (opcode == _CHECK_VALIDITY) { + if (maybe_invalid) { + maybe_invalid = false; + } + else { + buffer[pc].opcode = NOP; + } + } + else if (opcode == _JUMP_TO_TOP || opcode == _EXIT_TRACE) { + break; + } + else { + if (_PyUop_Flags[opcode] & HAS_ESCAPES_FLAG) { + maybe_invalid = true; + if (last_set_ip >= 0) { + buffer[last_set_ip].opcode = _SET_IP; + } + } + if ((_PyUop_Flags[opcode] & HAS_ERROR_FLAG) || opcode == _PUSH_FRAME) { + if (last_set_ip >= 0) { + buffer[last_set_ip].opcode = _SET_IP; + } + } + } + } +} + + +int +_Py_uop_analyze_and_optimize( + PyCodeObject *co, + _PyUOpInstruction *buffer, + int buffer_size, + int curr_stacklen +) +{ + remove_unneeded_uops(buffer, buffer_size); + return 0; +} diff --git a/Python/parking_lot.c b/Python/parking_lot.c new file mode 100644 index 00000000000000..d44c1b4b93b4d2 --- /dev/null +++ b/Python/parking_lot.c @@ -0,0 +1,379 @@ +#include "Python.h" + +#include "pycore_llist.h" +#include "pycore_lock.h" // _PyRawMutex +#include "pycore_parking_lot.h" +#include "pycore_pyerrors.h" // _Py_FatalErrorFormat +#include "pycore_pystate.h" // _PyThreadState_GET +#include "pycore_semaphore.h" // _PySemaphore + +#include + + +typedef struct { + // The mutex protects the waiter queue and the num_waiters counter. + _PyRawMutex mutex; + + // Linked list of `struct wait_entry` waiters in this bucket. + struct llist_node root; + size_t num_waiters; +} Bucket; + +struct wait_entry { + void *park_arg; + uintptr_t addr; + _PySemaphore sema; + struct llist_node node; + bool is_unparking; +}; + +// Prime number to avoid correlations with memory addresses. +// We want this to be roughly proportional to the number of CPU cores +// to minimize contention on the bucket locks, but not too big to avoid +// wasting memory. The exact choice does not matter much. +#define NUM_BUCKETS 257 + +#define BUCKET_INIT(b, i) [i] = { .root = LLIST_INIT(b[i].root) } +#define BUCKET_INIT_2(b, i) BUCKET_INIT(b, i), BUCKET_INIT(b, i+1) +#define BUCKET_INIT_4(b, i) BUCKET_INIT_2(b, i), BUCKET_INIT_2(b, i+2) +#define BUCKET_INIT_8(b, i) BUCKET_INIT_4(b, i), BUCKET_INIT_4(b, i+4) +#define BUCKET_INIT_16(b, i) BUCKET_INIT_8(b, i), BUCKET_INIT_8(b, i+8) +#define BUCKET_INIT_32(b, i) BUCKET_INIT_16(b, i), BUCKET_INIT_16(b, i+16) +#define BUCKET_INIT_64(b, i) BUCKET_INIT_32(b, i), BUCKET_INIT_32(b, i+32) +#define BUCKET_INIT_128(b, i) BUCKET_INIT_64(b, i), BUCKET_INIT_64(b, i+64) +#define BUCKET_INIT_256(b, i) BUCKET_INIT_128(b, i), BUCKET_INIT_128(b, i+128) + +// Table of waiters (hashed by address) +static Bucket buckets[NUM_BUCKETS] = { + BUCKET_INIT_256(buckets, 0), + BUCKET_INIT(buckets, 256), +}; + +void +_PySemaphore_Init(_PySemaphore *sema) +{ +#if defined(MS_WINDOWS) + sema->platform_sem = CreateSemaphore( + NULL, // attributes + 0, // initial count + 10, // maximum count + NULL // unnamed + ); + if (!sema->platform_sem) { + Py_FatalError("parking_lot: CreateSemaphore failed"); + } +#elif defined(_Py_USE_SEMAPHORES) + if (sem_init(&sema->platform_sem, /*pshared=*/0, /*value=*/0) < 0) { + Py_FatalError("parking_lot: sem_init failed"); + } +#else + if (pthread_mutex_init(&sema->mutex, NULL) != 0) { + Py_FatalError("parking_lot: pthread_mutex_init failed"); + } + if (pthread_cond_init(&sema->cond, NULL)) { + Py_FatalError("parking_lot: pthread_cond_init failed"); + } + sema->counter = 0; +#endif +} + +void +_PySemaphore_Destroy(_PySemaphore *sema) +{ +#if defined(MS_WINDOWS) + CloseHandle(sema->platform_sem); +#elif defined(_Py_USE_SEMAPHORES) + sem_destroy(&sema->platform_sem); +#else + pthread_mutex_destroy(&sema->mutex); + pthread_cond_destroy(&sema->cond); +#endif +} + +static int +_PySemaphore_PlatformWait(_PySemaphore *sema, _PyTime_t timeout) +{ + int res; +#if defined(MS_WINDOWS) + DWORD wait; + DWORD millis = 0; + if (timeout < 0) { + millis = INFINITE; + } + else { + millis = (DWORD) (timeout / 1000000); + } + wait = WaitForSingleObjectEx(sema->platform_sem, millis, FALSE); + if (wait == WAIT_OBJECT_0) { + res = Py_PARK_OK; + } + else if (wait == WAIT_TIMEOUT) { + res = Py_PARK_TIMEOUT; + } + else { + res = Py_PARK_INTR; + } +#elif defined(_Py_USE_SEMAPHORES) + int err; + if (timeout >= 0) { + struct timespec ts; + +#if defined(CLOCK_MONOTONIC) && defined(HAVE_SEM_CLOCKWAIT) + _PyTime_t deadline = _PyTime_Add(_PyTime_GetMonotonicClock(), timeout); + + _PyTime_AsTimespec_clamp(deadline, &ts); + + err = sem_clockwait(&sema->platform_sem, CLOCK_MONOTONIC, &ts); +#else + _PyTime_t deadline = _PyTime_Add(_PyTime_GetSystemClock(), timeout); + + _PyTime_AsTimespec_clamp(deadline, &ts); + + err = sem_timedwait(&sema->platform_sem, &ts); +#endif + } + else { + err = sem_wait(&sema->platform_sem); + } + if (err == -1) { + err = errno; + if (err == EINTR) { + res = Py_PARK_INTR; + } + else if (err == ETIMEDOUT) { + res = Py_PARK_TIMEOUT; + } + else { + _Py_FatalErrorFormat(__func__, + "unexpected error from semaphore: %d", + err); + } + } + else { + res = Py_PARK_OK; + } +#else + pthread_mutex_lock(&sema->mutex); + int err = 0; + if (sema->counter == 0) { + if (timeout >= 0) { + struct timespec ts; + + _PyTime_t deadline = _PyTime_Add(_PyTime_GetSystemClock(), timeout); + _PyTime_AsTimespec_clamp(deadline, &ts); + + err = pthread_cond_timedwait(&sema->cond, &sema->mutex, &ts); + } + else { + err = pthread_cond_wait(&sema->cond, &sema->mutex); + } + } + if (sema->counter > 0) { + sema->counter--; + res = Py_PARK_OK; + } + else if (err) { + res = Py_PARK_TIMEOUT; + } + else { + res = Py_PARK_INTR; + } + pthread_mutex_unlock(&sema->mutex); +#endif + return res; +} + +int +_PySemaphore_Wait(_PySemaphore *sema, _PyTime_t timeout, int detach) +{ + PyThreadState *tstate = NULL; + if (detach) { + tstate = _PyThreadState_GET(); + if (tstate) { + PyEval_ReleaseThread(tstate); + } + } + + int res = _PySemaphore_PlatformWait(sema, timeout); + + if (detach && tstate) { + PyEval_AcquireThread(tstate); + } + return res; +} + +void +_PySemaphore_Wakeup(_PySemaphore *sema) +{ +#if defined(MS_WINDOWS) + if (!ReleaseSemaphore(sema->platform_sem, 1, NULL)) { + Py_FatalError("parking_lot: ReleaseSemaphore failed"); + } +#elif defined(_Py_USE_SEMAPHORES) + int err = sem_post(&sema->platform_sem); + if (err != 0) { + Py_FatalError("parking_lot: sem_post failed"); + } +#else + pthread_mutex_lock(&sema->mutex); + sema->counter++; + pthread_cond_signal(&sema->cond); + pthread_mutex_unlock(&sema->mutex); +#endif +} + +static void +enqueue(Bucket *bucket, const void *address, struct wait_entry *wait) +{ + llist_insert_tail(&bucket->root, &wait->node); + ++bucket->num_waiters; +} + +static struct wait_entry * +dequeue(Bucket *bucket, const void *address) +{ + // find the first waiter that is waiting on `address` + struct llist_node *root = &bucket->root; + struct llist_node *node; + llist_for_each(node, root) { + struct wait_entry *wait = llist_data(node, struct wait_entry, node); + if (wait->addr == (uintptr_t)address) { + llist_remove(node); + --bucket->num_waiters; + return wait; + } + } + return NULL; +} + +static void +dequeue_all(Bucket *bucket, const void *address, struct llist_node *dst) +{ + // remove and append all matching waiters to dst + struct llist_node *root = &bucket->root; + struct llist_node *node; + llist_for_each_safe(node, root) { + struct wait_entry *wait = llist_data(node, struct wait_entry, node); + if (wait->addr == (uintptr_t)address) { + llist_remove(node); + llist_insert_tail(dst, node); + --bucket->num_waiters; + } + } +} + +// Checks that `*addr == *expected` (only works for 1, 2, 4, or 8 bytes) +static int +atomic_memcmp(const void *addr, const void *expected, size_t addr_size) +{ + switch (addr_size) { + case 1: return _Py_atomic_load_uint8(addr) == *(const uint8_t *)expected; + case 2: return _Py_atomic_load_uint16(addr) == *(const uint16_t *)expected; + case 4: return _Py_atomic_load_uint32(addr) == *(const uint32_t *)expected; + case 8: return _Py_atomic_load_uint64(addr) == *(const uint64_t *)expected; + default: Py_UNREACHABLE(); + } +} + +int +_PyParkingLot_Park(const void *addr, const void *expected, size_t size, + _PyTime_t timeout_ns, void *park_arg, int detach) +{ + struct wait_entry wait = { + .park_arg = park_arg, + .addr = (uintptr_t)addr, + .is_unparking = false, + }; + + Bucket *bucket = &buckets[((uintptr_t)addr) % NUM_BUCKETS]; + + _PyRawMutex_Lock(&bucket->mutex); + if (!atomic_memcmp(addr, expected, size)) { + _PyRawMutex_Unlock(&bucket->mutex); + return Py_PARK_AGAIN; + } + _PySemaphore_Init(&wait.sema); + enqueue(bucket, addr, &wait); + _PyRawMutex_Unlock(&bucket->mutex); + + int res = _PySemaphore_Wait(&wait.sema, timeout_ns, detach); + if (res == Py_PARK_OK) { + goto done; + } + + // timeout or interrupt + _PyRawMutex_Lock(&bucket->mutex); + if (wait.is_unparking) { + _PyRawMutex_Unlock(&bucket->mutex); + // Another thread has started to unpark us. Wait until we process the + // wakeup signal. + do { + res = _PySemaphore_Wait(&wait.sema, -1, detach); + } while (res != Py_PARK_OK); + goto done; + } + else { + llist_remove(&wait.node); + --bucket->num_waiters; + } + _PyRawMutex_Unlock(&bucket->mutex); + +done: + _PySemaphore_Destroy(&wait.sema); + return res; + +} + +void +_PyParkingLot_Unpark(const void *addr, _Py_unpark_fn_t *fn, void *arg) +{ + Bucket *bucket = &buckets[((uintptr_t)addr) % NUM_BUCKETS]; + + // Find the first waiter that is waiting on `addr` + _PyRawMutex_Lock(&bucket->mutex); + struct wait_entry *waiter = dequeue(bucket, addr); + if (waiter) { + waiter->is_unparking = true; + + int has_more_waiters = (bucket->num_waiters > 0); + fn(arg, waiter->park_arg, has_more_waiters); + } + else { + fn(arg, NULL, 0); + } + _PyRawMutex_Unlock(&bucket->mutex); + + if (waiter) { + // Wakeup the waiter outside of the bucket lock + _PySemaphore_Wakeup(&waiter->sema); + } +} + +void +_PyParkingLot_UnparkAll(const void *addr) +{ + struct llist_node head = LLIST_INIT(head); + Bucket *bucket = &buckets[((uintptr_t)addr) % NUM_BUCKETS]; + + _PyRawMutex_Lock(&bucket->mutex); + dequeue_all(bucket, addr, &head); + _PyRawMutex_Unlock(&bucket->mutex); + + struct llist_node *node; + llist_for_each_safe(node, &head) { + struct wait_entry *waiter = llist_data(node, struct wait_entry, node); + llist_remove(node); + _PySemaphore_Wakeup(&waiter->sema); + } +} + +void +_PyParkingLot_AfterFork(void) +{ + // After a fork only one thread remains. That thread cannot be blocked + // so all entries in the parking lot are for dead threads. + memset(buckets, 0, sizeof(buckets)); + for (Py_ssize_t i = 0; i < NUM_BUCKETS; i++) { + llist_init(&buckets[i].root); + } +} diff --git a/Python/pathconfig.c b/Python/pathconfig.c index afffa134e893ba..50c60093cd4e32 100644 --- a/Python/pathconfig.c +++ b/Python/pathconfig.c @@ -1,23 +1,21 @@ /* Path configuration like module_search_path (sys.path) */ #include "Python.h" -#include "marshal.h" // PyMarshal_ReadObjectFromString -#include "osdefs.h" // DELIM -#include "pycore_initconfig.h" -#include "pycore_fileutils.h" +#include "pycore_initconfig.h" // _PyStatus_OK() +#include "pycore_fileutils.h" // _Py_wgetcwd() #include "pycore_pathconfig.h" #include "pycore_pymem.h" // _PyMem_SetDefaultAllocator() #include + +#include "marshal.h" // PyMarshal_ReadObjectFromString +#include "osdefs.h" // DELIM + #ifdef MS_WINDOWS # include // GetFullPathNameW(), MAX_PATH # include # include #endif -#ifdef __cplusplus -extern "C" { -#endif - /* External interface */ @@ -498,8 +496,3 @@ _PyPathConfig_ComputeSysPath0(const PyWideStringList *argv, PyObject **path0_p) *path0_p = path0_obj; return 1; } - - -#ifdef __cplusplus -} -#endif diff --git a/Python/perf_trampoline.c b/Python/perf_trampoline.c index b8885a303977d0..750ba18d3510ed 100644 --- a/Python/perf_trampoline.c +++ b/Python/perf_trampoline.c @@ -130,7 +130,7 @@ any DWARF information available for them). */ #include "Python.h" -#include "pycore_ceval.h" +#include "pycore_ceval.h" // _PyPerf_Callbacks #include "pycore_frame.h" #include "pycore_interp.h" @@ -140,9 +140,9 @@ any DWARF information available for them). #include #include #include -#include +#include // mmap() #include -#include +#include // sysconf() #if defined(__arm__) || defined(__arm64__) || defined(__aarch64__) #define PY_HAVE_INVALIDATE_ICACHE @@ -192,7 +192,7 @@ typedef struct trampoline_api_st trampoline_api_t; #define perf_code_arena _PyRuntime.ceval.perf.code_arena #define trampoline_api _PyRuntime.ceval.perf.trampoline_api #define perf_map_file _PyRuntime.ceval.perf.map_file - +#define persist_after_fork _PyRuntime.ceval.perf.persist_after_fork static void perf_map_write_entry(void *state, const void *code_addr, @@ -216,10 +216,24 @@ perf_map_write_entry(void *state, const void *code_addr, PyMem_RawFree(perf_map_entry); } +static void* +perf_map_init_state(void) +{ + PyUnstable_PerfMapState_Init(); + return NULL; +} + +static int +perf_map_free_state(void *state) +{ + PyUnstable_PerfMapState_Fini(); + return 0; +} + _PyPerf_Callbacks _Py_perfmap_callbacks = { - NULL, + &perf_map_init_state, &perf_map_write_entry, - NULL, + &perf_map_free_state, }; static int @@ -233,10 +247,9 @@ new_code_arena(void) mem_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, // fd (not used here) 0); // offset (not used here) - if (!memory) { + if (memory == MAP_FAILED) { PyErr_SetFromErrno(PyExc_OSError); - _PyErr_WriteUnraisableMsg( - "Failed to create new mmap for perf trampoline", NULL); + PyErr_FormatUnraisable("Failed to create new mmap for perf trampoline"); perf_status = PERF_STATUS_FAILED; return -1; } @@ -260,9 +273,8 @@ new_code_arena(void) 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); + PyErr_FormatUnraisable("Failed to set mmap for perf trampoline to " + "PROT_READ | PROT_EXEC"); return -1; } @@ -276,8 +288,7 @@ new_code_arena(void) if (new_arena == NULL) { PyErr_NoMemory(); munmap(memory, mem_size); - _PyErr_WriteUnraisableMsg("Failed to allocate new code arena struct", - NULL); + PyErr_FormatUnraisable("Failed to allocate new code arena struct for perf trampoline"); return -1; } @@ -360,6 +371,26 @@ py_trampoline_evaluator(PyThreadState *ts, _PyInterpreterFrame *frame, } #endif // PY_HAVE_PERF_TRAMPOLINE +int PyUnstable_PerfTrampoline_CompileCode(PyCodeObject *co) +{ +#ifdef PY_HAVE_PERF_TRAMPOLINE + 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) { + py_trampoline new_trampoline = compile_trampoline(); + if (new_trampoline == NULL) { + return 0; + } + trampoline_api.write_state(trampoline_api.state, new_trampoline, + perf_code_arena->code_size, co); + return _PyCode_SetExtra((PyObject *)co, extra_code_index, + (void *)new_trampoline); + } +#endif // PY_HAVE_PERF_TRAMPOLINE + return 0; +} + int _PyIsPerfTrampolineActive(void) { @@ -398,7 +429,6 @@ _PyPerfTrampoline_SetCallbacks(_PyPerf_Callbacks *callbacks) 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; } @@ -417,6 +447,7 @@ _PyPerfTrampoline_Init(int activate) } if (!activate) { tstate->interp->eval_frame = NULL; + perf_status = PERF_STATUS_NO_INIT; } else { tstate->interp->eval_frame = py_trampoline_evaluator; @@ -427,6 +458,9 @@ _PyPerfTrampoline_Init(int activate) if (extra_code_index == -1) { return -1; } + if (trampoline_api.state == NULL && trampoline_api.init_state != NULL) { + trampoline_api.state = trampoline_api.init_state(); + } perf_status = PERF_STATUS_OK; } #endif @@ -437,12 +471,34 @@ int _PyPerfTrampoline_Fini(void) { #ifdef PY_HAVE_PERF_TRAMPOLINE + if (perf_status != PERF_STATUS_OK) { + return 0; + } PyThreadState *tstate = _PyThreadState_GET(); if (tstate->interp->eval_frame == py_trampoline_evaluator) { tstate->interp->eval_frame = NULL; } - free_code_arenas(); + if (perf_status == PERF_STATUS_OK) { + trampoline_api.free_state(trampoline_api.state); + } extra_code_index = -1; + perf_status = PERF_STATUS_NO_INIT; +#endif + return 0; +} + +void _PyPerfTrampoline_FreeArenas(void) { +#ifdef PY_HAVE_PERF_TRAMPOLINE + free_code_arenas(); +#endif + return; +} + +int +PyUnstable_PerfTrampoline_SetPersistAfterFork(int enable){ +#ifdef PY_HAVE_PERF_TRAMPOLINE + persist_after_fork = enable; + return persist_after_fork; #endif return 0; } @@ -451,12 +507,21 @@ PyStatus _PyPerfTrampoline_AfterFork_Child(void) { #ifdef PY_HAVE_PERF_TRAMPOLINE - // Restart trampoline in file in child. - int was_active = _PyIsPerfTrampolineActive(); - _PyPerfTrampoline_Fini(); - PyUnstable_PerfMapState_Fini(); - if (was_active) { - _PyPerfTrampoline_Init(1); + if (persist_after_fork) { + _PyPerfTrampoline_Fini(); + char filename[256]; + pid_t parent_pid = getppid(); + snprintf(filename, sizeof(filename), "/tmp/perf-%d.map", parent_pid); + if (PyUnstable_CopyPerfMapFile(filename) != 0) { + return PyStatus_Error("Failed to copy perf map file."); + } + } else { + // 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/Python/pyhash.c b/Python/pyhash.c index b2bdab5099d86a..141407c265677a 100644 --- a/Python/pyhash.c +++ b/Python/pyhash.c @@ -14,10 +14,6 @@ # include #endif -#ifdef __cplusplus -extern "C" { -#endif - _Py_HashSecret_t _Py_HashSecret = {{0}}; #if Py_HASH_ALGORITHM == Py_HASH_EXTERNAL @@ -87,8 +83,6 @@ static Py_ssize_t hashstats[Py_HASH_STATS_MAX + 1] = {0}; */ -Py_hash_t _Py_HashPointer(const void *); - Py_hash_t _Py_HashDouble(PyObject *inst, double v) { @@ -136,23 +130,13 @@ _Py_HashDouble(PyObject *inst, double v) } Py_hash_t -_Py_HashPointerRaw(const void *p) +Py_HashPointer(const void *ptr) { - size_t y = (size_t)p; - /* bottom 3 or 4 bits are likely to be 0; rotate y by 4 to avoid - excessive hash collisions for dicts and sets */ - y = (y >> 4) | (y << (8 * SIZEOF_VOID_P - 4)); - return (Py_hash_t)y; -} - -Py_hash_t -_Py_HashPointer(const void *p) -{ - Py_hash_t x = _Py_HashPointerRaw(p); - if (x == -1) { - x = -2; + Py_hash_t hash = _Py_HashPointerRaw(ptr); + if (hash == -1) { + hash = -2; } - return x; + return hash; } Py_hash_t @@ -503,7 +487,3 @@ pysiphash(const void *src, Py_ssize_t src_sz) { static PyHash_FuncDef PyHash_Func = {pysiphash, "siphash24", 64, 128}; #endif - -#ifdef __cplusplus -} -#endif diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index 7a17f92b550c05..4198f6a38f0e56 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -17,7 +17,7 @@ #include "pycore_list.h" // _PyList_Fini() #include "pycore_long.h" // _PyLong_InitTypes() #include "pycore_object.h" // _PyDebug_PrintTotalRefs() -#include "pycore_pathconfig.h" // _PyConfig_WritePathConfig() +#include "pycore_pathconfig.h" // _PyPathConfig_UpdateGlobal() #include "pycore_pyerrors.h" // _PyErr_Occurred() #include "pycore_pylifecycle.h" // _PyErr_Print() #include "pycore_pymem.h" // _PyObject_DebugMallocStats() @@ -32,13 +32,17 @@ #include "pycore_typevarobject.h" // _Py_clear_generic_types() #include "pycore_unicodeobject.h" // _PyUnicode_InitTypes() #include "pycore_weakref.h" // _PyWeakref_GET_REF() + #include "opcode.h" #include // setlocale() #include // getenv() +#ifdef HAVE_UNISTD_H +# include // isatty() +#endif #if defined(__APPLE__) -#include +# include #endif #ifdef HAVE_SIGNAL_H @@ -57,12 +61,7 @@ # undef BYTE #endif -#define PUTS(fd, str) _Py_write_noraise(fd, str, (int)strlen(str)) - - -#ifdef __cplusplus -extern "C" { -#endif +#define PUTS(fd, str) (void)_Py_write_noraise(fd, str, (int)strlen(str)) /* Forward declarations */ @@ -129,7 +128,7 @@ _PyRuntime_Finalize(void) } int -_Py_IsFinalizing(void) +Py_IsFinalizing(void) { return _PyRuntimeState_GetFinalizing(&_PyRuntime) != NULL; } @@ -529,11 +528,6 @@ pycore_init_runtime(_PyRuntimeState *runtime, return status; } - status = _PyTime_Init(); - if (_PyStatus_EXCEPTION(status)) { - return status; - } - status = _PyImport_Init(); if (_PyStatus_EXCEPTION(status)) { return status; @@ -582,44 +576,33 @@ init_interp_settings(PyInterpreterState *interp, interp->feature_flags |= Py_RTFLAGS_MULTI_INTERP_EXTENSIONS; } - /* We check "gil" in init_interp_create_gil(). */ + switch (config->gil) { + case PyInterpreterConfig_DEFAULT_GIL: break; + case PyInterpreterConfig_SHARED_GIL: break; + case PyInterpreterConfig_OWN_GIL: break; + default: + return _PyStatus_ERR("invalid interpreter config 'gil' value"); + } return _PyStatus_OK(); } -static PyStatus +static void init_interp_create_gil(PyThreadState *tstate, int gil) { - PyStatus status; - /* finalize_interp_delete() comment explains why _PyEval_FiniGIL() is only called here. */ // XXX This is broken with a per-interpreter GIL. _PyEval_FiniGIL(tstate->interp); /* Auto-thread-state API */ - status = _PyGILState_SetTstate(tstate); - if (_PyStatus_EXCEPTION(status)) { - return status; - } + _PyGILState_SetTstate(tstate); - int own_gil; - switch (gil) { - case PyInterpreterConfig_DEFAULT_GIL: own_gil = 0; break; - case PyInterpreterConfig_SHARED_GIL: own_gil = 0; break; - case PyInterpreterConfig_OWN_GIL: own_gil = 1; break; - default: - return _PyStatus_ERR("invalid interpreter config 'gil' value"); - } + int own_gil = (gil == PyInterpreterConfig_OWN_GIL); /* Create the GIL and take it */ - status = _PyEval_InitGIL(tstate, own_gil); - if (_PyStatus_EXCEPTION(status)) { - return status; - } - - return _PyStatus_OK(); + _PyEval_InitGIL(tstate, own_gil); } @@ -629,10 +612,12 @@ pycore_create_interpreter(_PyRuntimeState *runtime, PyThreadState **tstate_p) { PyStatus status; - PyInterpreterState *interp = PyInterpreterState_New(); - if (interp == NULL) { - return _PyStatus_ERR("can't make main interpreter"); + PyInterpreterState *interp; + status = _PyInterpreterState_New(NULL, &interp); + if (_PyStatus_EXCEPTION(status)) { + return status; } + assert(interp != NULL); assert(_Py_IsMainInterpreter(interp)); status = _PyConfig_Copy(&interp->config, src_config); @@ -654,18 +639,14 @@ pycore_create_interpreter(_PyRuntimeState *runtime, return status; } - PyThreadState *tstate = _PyThreadState_New(interp); + PyThreadState *tstate = _PyThreadState_New(interp, + _PyThreadState_WHENCE_INTERP); if (tstate == NULL) { return _PyStatus_ERR("can't make first thread"); } _PyThreadState_Bind(tstate); - // XXX For now we do this before the GIL is created. - (void) _PyThreadState_SwapNoGIL(tstate); - status = init_interp_create_gil(tstate, config.gil); - if (_PyStatus_EXCEPTION(status)) { - return status; - } + init_interp_create_gil(tstate, config.gil); *tstate_p = tstate; return _PyStatus_OK(); @@ -738,6 +719,12 @@ pycore_init_types(PyInterpreterState *interp) if (_PyStatus_EXCEPTION(status)) { return status; } + + status = _PyXI_InitTypes(interp); + if (_PyStatus_EXCEPTION(status)) { + return status; + } + return _PyStatus_OK(); } @@ -762,18 +749,30 @@ pycore_init_builtins(PyThreadState *tstate) } interp->builtins = Py_NewRef(builtins_dict); - PyObject *isinstance = PyDict_GetItem(builtins_dict, &_Py_ID(isinstance)); - assert(isinstance); + PyObject *isinstance = PyDict_GetItemWithError(builtins_dict, &_Py_ID(isinstance)); + if (!isinstance) { + goto error; + } interp->callable_cache.isinstance = isinstance; - PyObject *len = PyDict_GetItem(builtins_dict, &_Py_ID(len)); - assert(len); + + PyObject *len = PyDict_GetItemWithError(builtins_dict, &_Py_ID(len)); + if (!len) { + goto error; + } interp->callable_cache.len = len; + PyObject *list_append = _PyType_Lookup(&PyList_Type, &_Py_ID(append)); - assert(list_append); + if (list_append == NULL) { + goto error; + } interp->callable_cache.list_append = list_append; + PyObject *object__getattribute__ = _PyType_Lookup(&PyBaseObject_Type, &_Py_ID(__getattribute__)); - assert(object__getattribute__); + if (object__getattribute__ == NULL) { + goto error; + } interp->callable_cache.object__getattribute__ = object__getattribute__; + if (_PyBuiltins_AddExceptions(bimod) < 0) { return _PyStatus_ERR("failed to add exceptions to builtins"); } @@ -812,16 +811,16 @@ pycore_interp_init(PyThreadState *tstate) return status; } + status = _PyDtoa_Init(interp); + if (_PyStatus_EXCEPTION(status)) { + return status; + } + // The GC must be initialized before the first GC collection. status = _PyGC_Init(interp); if (_PyStatus_EXCEPTION(status)) { return status; } - // Intern strings in deep-frozen modules first so that others - // can use it instead of creating a heap allocated string. - if (_Py_Deepfreeze_Init() < 0) { - return _PyStatus_ERR("failed to initialize deep-frozen modules"); - } status = pycore_init_types(interp); if (_PyStatus_EXCEPTION(status)) { @@ -847,6 +846,11 @@ pycore_interp_init(PyThreadState *tstate) goto done; } + status = _PyXI_Init(interp); + if (_PyStatus_EXCEPTION(status)) { + goto done; + } + const PyConfig *config = _PyInterpreterState_GetConfig(interp); status = _PyImport_InitCore(tstate, sysmod, config->_install_importlib); @@ -1069,6 +1073,38 @@ pyinit_main_reconfigure(PyThreadState *tstate) } +#ifdef Py_DEBUG +static void +run_presite(PyThreadState *tstate) +{ + PyInterpreterState *interp = tstate->interp; + const PyConfig *config = _PyInterpreterState_GetConfig(interp); + + if (!config->run_presite) { + return; + } + + PyObject *presite_modname = PyUnicode_FromWideChar( + config->run_presite, + wcslen(config->run_presite) + ); + if (presite_modname == NULL) { + fprintf(stderr, "Could not convert pre-site module name to unicode\n"); + Py_DECREF(presite_modname); + } + else { + PyObject *presite = PyImport_Import(presite_modname); + if (presite == NULL) { + fprintf(stderr, "pre-site import failed:\n"); + _PyErr_Print(tstate); + } + Py_XDECREF(presite); + Py_DECREF(presite_modname); + } +} +#endif + + static PyStatus init_interp_main(PyThreadState *tstate) { @@ -1150,6 +1186,10 @@ init_interp_main(PyThreadState *tstate) return status; } +#ifdef Py_DEBUG + run_presite(tstate); +#endif + status = add_main_module(interp); if (_PyStatus_EXCEPTION(status)) { return status; @@ -1186,7 +1226,7 @@ init_interp_main(PyThreadState *tstate) // Turn on experimental tier 2 (uops-based) optimizer if (is_main_interp) { - char *envvar = Py_GETENV("PYTHONUOPS"); + char *envvar = Py_GETENV("PYTHON_UOPS"); int enabled = envvar != NULL && *envvar > '0'; if (_Py_get_xoption(&config->xoptions, L"uops") != NULL) { enabled = 1; @@ -1201,6 +1241,31 @@ init_interp_main(PyThreadState *tstate) } } + if (!is_main_interp) { + // The main interpreter is handled in Py_Main(), for now. + if (config->sys_path_0 != NULL) { + PyObject *path0 = PyUnicode_FromWideChar(config->sys_path_0, -1); + if (path0 == NULL) { + return _PyStatus_ERR("can't initialize sys.path[0]"); + } + PyObject *sysdict = interp->sysdict; + if (sysdict == NULL) { + Py_DECREF(path0); + return _PyStatus_ERR("can't initialize sys.path[0]"); + } + PyObject *sys_path = PyDict_GetItemWithError(sysdict, &_Py_ID(path)); + if (sys_path == NULL) { + Py_DECREF(path0); + return _PyStatus_ERR("can't initialize sys.path[0]"); + } + int res = PyList_Insert(sys_path, 0, path0); + Py_DECREF(path0); + if (res) { + return _PyStatus_ERR("can't initialize sys.path[0]"); + } + } + } + assert(!_PyErr_Occurred(tstate)); return _PyStatus_OK(); @@ -1345,13 +1410,13 @@ finalize_modules_delete_special(PyThreadState *tstate, int verbose) PySys_WriteStderr("# clear builtins._\n"); } if (PyDict_SetItemString(interp->builtins, "_", Py_None) < 0) { - PyErr_WriteUnraisable(NULL); + PyErr_FormatUnraisable("Exception ignored on setting builtin variable _"); } const char * const *p; for (p = sys_deletes; *p != NULL; p++) { if (_PySys_ClearAttrString(interp, *p, verbose) < 0) { - PyErr_WriteUnraisable(NULL); + PyErr_FormatUnraisable("Exception ignored on clearing sys.%s", *p); } } for (p = sys_files; *p != NULL; p+=2) { @@ -1360,17 +1425,17 @@ finalize_modules_delete_special(PyThreadState *tstate, int verbose) if (verbose) { PySys_WriteStderr("# restore sys.%s\n", name); } - PyObject *value = _PyDict_GetItemStringWithError(interp->sysdict, - orig_name); + PyObject *value; + if (PyDict_GetItemStringRef(interp->sysdict, orig_name, &value) < 0) { + PyErr_FormatUnraisable("Exception ignored on restoring sys.%s", name); + } if (value == NULL) { - if (_PyErr_Occurred(tstate)) { - PyErr_WriteUnraisable(NULL); - } - value = Py_None; + value = Py_NewRef(Py_None); } if (PyDict_SetItemString(interp->sysdict, name, value) < 0) { - PyErr_WriteUnraisable(NULL); + PyErr_FormatUnraisable("Exception ignored on restoring sys.%s", name); } + Py_DECREF(value); } } @@ -1380,7 +1445,7 @@ finalize_remove_modules(PyObject *modules, int verbose) { PyObject *weaklist = PyList_New(0); if (weaklist == NULL) { - PyErr_WriteUnraisable(NULL); + PyErr_FormatUnraisable("Exception ignored on removing modules"); } #define STORE_MODULE_WEAKREF(name, mod) \ @@ -1389,13 +1454,13 @@ finalize_remove_modules(PyObject *modules, int verbose) if (wr) { \ PyObject *tup = PyTuple_Pack(2, name, wr); \ if (!tup || PyList_Append(weaklist, tup) < 0) { \ - PyErr_WriteUnraisable(NULL); \ + PyErr_FormatUnraisable("Exception ignored on removing modules"); \ } \ Py_XDECREF(tup); \ Py_DECREF(wr); \ } \ else { \ - PyErr_WriteUnraisable(NULL); \ + PyErr_FormatUnraisable("Exception ignored on removing modules"); \ } \ } @@ -1406,7 +1471,7 @@ finalize_remove_modules(PyObject *modules, int verbose) } \ STORE_MODULE_WEAKREF(name, mod); \ if (PyObject_SetItem(modules, name, Py_None) < 0) { \ - PyErr_WriteUnraisable(NULL); \ + PyErr_FormatUnraisable("Exception ignored on removing modules"); \ } \ } @@ -1420,14 +1485,14 @@ finalize_remove_modules(PyObject *modules, int verbose) else { PyObject *iterator = PyObject_GetIter(modules); if (iterator == NULL) { - PyErr_WriteUnraisable(NULL); + PyErr_FormatUnraisable("Exception ignored on removing modules"); } else { PyObject *key; while ((key = PyIter_Next(iterator))) { PyObject *value = PyObject_GetItem(modules, key); if (value == NULL) { - PyErr_WriteUnraisable(NULL); + PyErr_FormatUnraisable("Exception ignored on removing modules"); continue; } CLEAR_MODULE(key, value); @@ -1435,7 +1500,7 @@ finalize_remove_modules(PyObject *modules, int verbose) Py_DECREF(key); } if (PyErr_Occurred()) { - PyErr_WriteUnraisable(NULL); + PyErr_FormatUnraisable("Exception ignored on removing modules"); } Py_DECREF(iterator); } @@ -1455,7 +1520,7 @@ finalize_clear_modules_dict(PyObject *modules) } else { if (PyObject_CallMethodNoArgs(modules, &_Py_ID(clear)) == NULL) { - PyErr_WriteUnraisable(NULL); + PyErr_FormatUnraisable("Exception ignored on clearing sys.modules"); } } } @@ -1467,11 +1532,11 @@ finalize_restore_builtins(PyThreadState *tstate) PyInterpreterState *interp = tstate->interp; PyObject *dict = PyDict_Copy(interp->builtins); if (dict == NULL) { - PyErr_WriteUnraisable(NULL); + PyErr_FormatUnraisable("Exception ignored on restoring builtins"); } PyDict_Clear(interp->builtins); if (PyDict_Update(interp->builtins, interp->builtins_copy)) { - PyErr_WriteUnraisable(NULL); + PyErr_FormatUnraisable("Exception ignored on restoring builtins"); } Py_XDECREF(dict); } @@ -1629,27 +1694,20 @@ flush_std_files(void) PyThreadState *tstate = _PyThreadState_GET(); PyObject *fout = _PySys_GetAttr(tstate, &_Py_ID(stdout)); PyObject *ferr = _PySys_GetAttr(tstate, &_Py_ID(stderr)); - PyObject *tmp; int status = 0; if (fout != NULL && fout != Py_None && !file_is_closed(fout)) { - tmp = PyObject_CallMethodNoArgs(fout, &_Py_ID(flush)); - if (tmp == NULL) { - PyErr_WriteUnraisable(fout); + if (_PyFile_Flush(fout) < 0) { + PyErr_FormatUnraisable("Exception ignored on flushing sys.stdout"); status = -1; } - else - Py_DECREF(tmp); } if (ferr != NULL && ferr != Py_None && !file_is_closed(ferr)) { - tmp = PyObject_CallMethodNoArgs(ferr, &_Py_ID(flush)); - if (tmp == NULL) { + if (_PyFile_Flush(ferr) < 0) { PyErr_Clear(); status = -1; } - else - Py_DECREF(tmp); } return status; @@ -1675,6 +1733,7 @@ finalize_interp_types(PyInterpreterState *interp) { _PyUnicode_FiniTypes(interp); _PySys_FiniTypes(interp); + _PyXI_FiniTypes(interp); _PyExc_Fini(interp); _PyAsyncGen_Fini(interp); _PyContext_Fini(interp); @@ -1693,13 +1752,16 @@ finalize_interp_types(PyInterpreterState *interp) _PyUnicode_ClearInterned(interp); _PyDict_Fini(interp); - _PyList_Fini(interp); - _PyTuple_Fini(interp); _PySlice_Fini(interp); _PyUnicode_Fini(interp); - _PyFloat_Fini(interp); + + _PyFreeListState *state = _PyFreeListState_GET(); + _PyTuple_Fini(state); + _PyList_Fini(state); + _PyFloat_Fini(state); + #ifdef Py_DEBUG _PyStaticObjects_CheckRefcnt(interp); #endif @@ -1711,8 +1773,10 @@ finalize_interp_clear(PyThreadState *tstate) { int is_main_interp = _Py_IsMainInterpreter(tstate->interp); + _PyXI_Fini(tstate->interp); _PyExc_ClearExceptionGroupType(tstate->interp); _Py_clear_generic_types(tstate->interp); + _PyDtoa_Fini(tstate->interp); /* Clear interpreter state and all thread states */ _PyInterpreterState_Clear(tstate); @@ -1728,11 +1792,15 @@ finalize_interp_clear(PyThreadState *tstate) _Py_HashRandomization_Fini(); _PyArg_Fini(); _Py_ClearFileSystemEncoding(); - _Py_Deepfreeze_Fini(); _PyPerfTrampoline_Fini(); + _PyPerfTrampoline_FreeArenas(); } finalize_interp_types(tstate->interp); + + /* finalize_interp_types may allocate Python objects so we may need to + abandon mimalloc segments again */ + _PyThreadState_ClearMimallocHeaps(tstate); } @@ -1787,7 +1855,6 @@ Py_FinalizeEx(void) */ _PyAtExit_Call(tstate->interp); - PyUnstable_PerfMapState_Fini(); /* Copy the core config, PyInterpreterState_Delete() free the core config memory */ @@ -1944,31 +2011,30 @@ Py_FinalizeEx(void) // XXX Ensure finalizer errors are handled properly. finalize_interp_clear(tstate); - finalize_interp_delete(tstate->interp); - -#ifdef Py_REF_DEBUG - if (show_ref_count) { - _PyDebug_PrintTotalRefs(); - } - _Py_FinalizeRefTotal(runtime); -#endif - _Py_FinalizeAllocatedBlocks(runtime); #ifdef Py_TRACE_REFS /* Display addresses (& refcnts) of all objects still alive. * An address can be used to find the repr of the object, printed - * above by _Py_PrintReferences. - */ - + * above by _Py_PrintReferences. */ if (dump_refs) { _Py_PrintReferenceAddresses(tstate->interp, stderr); } - if (dump_refs_fp != NULL) { _Py_PrintReferenceAddresses(tstate->interp, dump_refs_fp); fclose(dump_refs_fp); } #endif /* Py_TRACE_REFS */ + + finalize_interp_delete(tstate->interp); + +#ifdef Py_REF_DEBUG + if (show_ref_count) { + _PyDebug_PrintTotalRefs(); + } + _Py_FinalizeRefTotal(runtime); +#endif + _Py_FinalizeAllocatedBlocks(runtime); + #ifdef WITH_PYMALLOC if (malloc_stats) { _PyObject_DebugMallocStats(stderr); @@ -2026,28 +2092,21 @@ new_interpreter(PyThreadState **tstate_p, const PyInterpreterConfig *config) return _PyStatus_OK(); } - PyThreadState *tstate = _PyThreadState_New(interp); - if (tstate == NULL) { - PyInterpreterState_Delete(interp); - *tstate_p = NULL; - return _PyStatus_OK(); - } - _PyThreadState_Bind(tstate); - - // XXX For now we do this before the GIL is created. - PyThreadState *save_tstate = _PyThreadState_SwapNoGIL(tstate); - int has_gil = 0; + // XXX Might new_interpreter() have been called without the GIL held? + PyThreadState *save_tstate = _PyThreadState_GET(); + PyThreadState *tstate = NULL; /* From this point until the init_interp_create_gil() call, we must not do anything that requires that the GIL be held (or otherwise exist). That applies whether or not the new interpreter has its own GIL (e.g. the main interpreter). */ + if (save_tstate != NULL) { + _PyThreadState_Detach(save_tstate); + } /* Copy the current interpreter config into the new interpreter */ const PyConfig *src_config; if (save_tstate != NULL) { - // XXX Might new_interpreter() have been called without the GIL held? - _PyEval_ReleaseLock(save_tstate->interp, save_tstate); src_config = _PyInterpreterState_GetConfig(save_tstate->interp); } else @@ -2069,11 +2128,16 @@ new_interpreter(PyThreadState **tstate_p, const PyInterpreterConfig *config) goto error; } - status = init_interp_create_gil(tstate, config->gil); - if (_PyStatus_EXCEPTION(status)) { + tstate = _PyThreadState_New(interp, _PyThreadState_WHENCE_INTERP); + if (tstate == NULL) { + status = _PyStatus_NO_MEMORY(); goto error; } - has_gil = 1; + + _PyThreadState_Bind(tstate); + init_interp_create_gil(tstate, config->gil); + + /* No objects have been created yet. */ status = pycore_interp_init(tstate); if (_PyStatus_EXCEPTION(status)) { @@ -2090,17 +2154,14 @@ new_interpreter(PyThreadState **tstate_p, const PyInterpreterConfig *config) error: *tstate_p = NULL; - - /* Oops, it didn't work. Undo it all. */ - PyErr_PrintEx(0); - if (has_gil) { - PyThreadState_Swap(save_tstate); + if (tstate != NULL) { + PyThreadState_Clear(tstate); + _PyThreadState_Detach(tstate); + PyThreadState_Delete(tstate); } - else { - _PyThreadState_SwapNoGIL(save_tstate); + if (save_tstate != NULL) { + _PyThreadState_Attach(save_tstate); } - PyThreadState_Clear(tstate); - PyThreadState_Delete(tstate); PyInterpreterState_Delete(interp); return status; @@ -2145,7 +2206,7 @@ Py_EndInterpreter(PyThreadState *tstate) if (tstate != _PyThreadState_GET()) { Py_FatalError("thread is not current"); } - if (tstate->cframe->current_frame != NULL) { + if (tstate->current_frame != NULL) { Py_FatalError("thread still has a frame"); } interp->finalizing = 1; @@ -2193,7 +2254,7 @@ _Py_IsInterpreterFinalizing(PyInterpreterState *interp) static PyStatus add_main_module(PyInterpreterState *interp) { - PyObject *m, *d, *loader, *ann_dict; + PyObject *m, *d, *ann_dict; m = PyImport_AddModule("__main__"); if (m == NULL) return _PyStatus_ERR("can't create __main__ module"); @@ -2206,10 +2267,11 @@ add_main_module(PyInterpreterState *interp) } Py_DECREF(ann_dict); - if (_PyDict_GetItemStringWithError(d, "__builtins__") == NULL) { - if (PyErr_Occurred()) { - return _PyStatus_ERR("Failed to test __main__.__builtins__"); - } + int has_builtins = PyDict_ContainsString(d, "__builtins__"); + if (has_builtins < 0) { + return _PyStatus_ERR("Failed to test __main__.__builtins__"); + } + if (!has_builtins) { PyObject *bimod = PyImport_ImportModule("builtins"); if (bimod == NULL) { return _PyStatus_ERR("Failed to retrieve builtins module"); @@ -2225,11 +2287,13 @@ add_main_module(PyInterpreterState *interp) * will be set if __main__ gets further initialized later in the startup * process. */ - loader = _PyDict_GetItemStringWithError(d, "__loader__"); - if (loader == NULL || loader == Py_None) { - if (PyErr_Occurred()) { - return _PyStatus_ERR("Failed to test __main__.__loader__"); - } + PyObject *loader; + if (PyDict_GetItemStringRef(d, "__loader__", &loader) < 0) { + return _PyStatus_ERR("Failed to test __main__.__loader__"); + } + int has_loader = !(loader == NULL || loader == Py_None); + Py_XDECREF(loader); + if (!has_loader) { PyObject *loader = _PyImport_GetImportlibLoader(interp, "BuiltinImporter"); if (loader == NULL) { @@ -2619,13 +2683,9 @@ _Py_FatalError_PrintExc(PyThreadState *tstate) Py_DECREF(exc); /* sys.stderr may be buffered: call sys.stderr.flush() */ - PyObject *res = PyObject_CallMethodNoArgs(ferr, &_Py_ID(flush)); - if (res == NULL) { + if (_PyFile_Flush(ferr) < 0) { _PyErr_Clear(tstate); } - else { - Py_DECREF(res); - } return has_tb; } @@ -2971,14 +3031,14 @@ wait_for_thread_shutdown(PyThreadState *tstate) PyObject *threading = PyImport_GetModule(&_Py_ID(threading)); if (threading == NULL) { if (_PyErr_Occurred(tstate)) { - PyErr_WriteUnraisable(NULL); + PyErr_FormatUnraisable("Exception ignored on threading shutdown"); } /* else: threading not imported */ return; } result = PyObject_CallMethodNoArgs(threading, &_Py_ID(_shutdown)); if (result == NULL) { - PyErr_WriteUnraisable(threading); + PyErr_FormatUnraisable("Exception ignored on threading shutdown"); } else { Py_DECREF(result); @@ -2989,13 +3049,13 @@ wait_for_thread_shutdown(PyThreadState *tstate) int Py_AtExit(void (*func)(void)) { struct _atexit_runtime_state *state = &_PyRuntime.atexit; - PyThread_acquire_lock(state->mutex, WAIT_LOCK); + PyMutex_Lock(&state->mutex); if (state->ncallbacks >= NEXITFUNCS) { - PyThread_release_lock(state->mutex); + PyMutex_Unlock(&state->mutex); return -1; } state->callbacks[state->ncallbacks++] = func; - PyThread_release_lock(state->mutex); + PyMutex_Unlock(&state->mutex); return 0; } @@ -3005,18 +3065,18 @@ call_ll_exitfuncs(_PyRuntimeState *runtime) atexit_callbackfunc exitfunc; struct _atexit_runtime_state *state = &runtime->atexit; - PyThread_acquire_lock(state->mutex, WAIT_LOCK); + PyMutex_Lock(&state->mutex); while (state->ncallbacks > 0) { /* pop last function from the list */ state->ncallbacks--; exitfunc = state->callbacks[state->ncallbacks]; state->callbacks[state->ncallbacks] = NULL; - PyThread_release_lock(state->mutex); + PyMutex_Unlock(&state->mutex); exitfunc(); - PyThread_acquire_lock(state->mutex, WAIT_LOCK); + PyMutex_Lock(&state->mutex); } - PyThread_release_lock(state->mutex); + PyMutex_Unlock(&state->mutex); fflush(stdout); fflush(stderr); @@ -3137,7 +3197,3 @@ PyOS_setsig(int sig, PyOS_sighandler_t handler) return oldhandler; #endif } - -#ifdef __cplusplus -} -#endif diff --git a/Python/pystate.c b/Python/pystate.c index a1864cc3249e2f..eaf77b0da62a84 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -4,17 +4,19 @@ #include "Python.h" #include "pycore_ceval.h" #include "pycore_code.h" // stats +#include "pycore_critical_section.h" // _PyCriticalSection_Resume() #include "pycore_dtoa.h" // _dtoa_state_INIT() +#include "pycore_emscripten_trampoline.h" // _Py_EmscriptenTrampoline_Init() #include "pycore_frame.h" -#include "pycore_initconfig.h" +#include "pycore_initconfig.h" // _PyStatus_OK() #include "pycore_object.h" // _PyType_InitCache() -#include "pycore_pyerrors.h" -#include "pycore_pylifecycle.h" +#include "pycore_parking_lot.h" // _PyParkingLot_AfterFork() +#include "pycore_pyerrors.h" // _PyErr_Clear() +#include "pycore_pylifecycle.h" // _PyAST_Fini() #include "pycore_pymem.h" // _PyMem_SetDefaultAllocator() #include "pycore_pystate.h" #include "pycore_runtime_init.h" // _PyRuntimeState_INIT #include "pycore_sysmodule.h" // _PySys_Audit() -#include "pycore_weakref.h" // _PyWeakref_GET_REF() /* -------------------------------------------------------------------------- CAUTION @@ -27,16 +29,12 @@ to avoid the expense of doing their own locking). -------------------------------------------------------------------------- */ #ifdef HAVE_DLOPEN -#ifdef HAVE_DLFCN_H -#include -#endif -#if !HAVE_DECL_RTLD_LAZY -#define RTLD_LAZY 1 -#endif -#endif - -#ifdef __cplusplus -extern "C" { +# ifdef HAVE_DLFCN_H +# include +# endif +# if !HAVE_DECL_RTLD_LAZY +# define RTLD_LAZY 1 +# endif #endif @@ -238,6 +236,8 @@ tstate_is_bound(PyThreadState *tstate) static void bind_gilstate_tstate(PyThreadState *); static void unbind_gilstate_tstate(PyThreadState *); +static void tstate_mimalloc_bind(PyThreadState *); + static void bind_tstate(PyThreadState *tstate) { @@ -258,6 +258,9 @@ bind_tstate(PyThreadState *tstate) tstate->native_thread_id = PyThread_get_thread_native_id(); #endif + // mimalloc state needs to be initialized from the active thread. + tstate_mimalloc_bind(tstate); + tstate->_status.bound = 1; } @@ -265,10 +268,10 @@ static void unbind_tstate(PyThreadState *tstate) { assert(tstate != NULL); - // XXX assert(tstate_is_alive(tstate)); assert(tstate_is_bound(tstate)); - // XXX assert(!tstate->_status.active); +#ifndef HAVE_PTHREAD_STUBS assert(tstate->thread_id > 0); +#endif #ifdef PY_HAVE_THREAD_NATIVE_ID assert(tstate->native_thread_id > 0); #endif @@ -381,58 +384,29 @@ _Py_COMP_DIAG_IGNORE_DEPR_DECLS static const _PyRuntimeState initial = _PyRuntimeState_INIT(_PyRuntime); _Py_COMP_DIAG_POP -#define NUMLOCKS 9 #define LOCKS_INIT(runtime) \ { \ &(runtime)->interpreters.mutex, \ - &(runtime)->xidregistry.mutex, \ - &(runtime)->getargs.mutex, \ - &(runtime)->unicode_state.ids.lock, \ + &(runtime)->xi.registry.mutex, \ + &(runtime)->unicode_state.ids.mutex, \ &(runtime)->imports.extensions.mutex, \ - &(runtime)->ceval.pending_mainthread.lock, \ + &(runtime)->ceval.pending_mainthread.mutex, \ &(runtime)->atexit.mutex, \ &(runtime)->audit_hooks.mutex, \ &(runtime)->allocators.mutex, \ } -static int -alloc_for_runtime(PyThread_type_lock locks[NUMLOCKS]) -{ - /* Force default allocator, since _PyRuntimeState_Fini() must - use the same allocator than this function. */ - PyMemAllocatorEx old_alloc; - _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); - - for (int i = 0; i < NUMLOCKS; i++) { - PyThread_type_lock lock = PyThread_allocate_lock(); - if (lock == NULL) { - for (int j = 0; j < i; j++) { - PyThread_free_lock(locks[j]); - locks[j] = NULL; - } - break; - } - locks[i] = lock; - } - - PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); - return 0; -} - static void init_runtime(_PyRuntimeState *runtime, void *open_code_hook, void *open_code_userdata, _Py_AuditHookEntry *audit_hook_head, - Py_ssize_t unicode_next_index, - PyThread_type_lock locks[NUMLOCKS]) + Py_ssize_t unicode_next_index) { - if (runtime->_initialized) { - Py_FatalError("runtime already initialized"); - } - assert(!runtime->preinitializing && - !runtime->preinitialized && - !runtime->core_initialized && - !runtime->initialized); + assert(!runtime->preinitializing); + assert(!runtime->preinitialized); + assert(!runtime->core_initialized); + assert(!runtime->initialized); + assert(!runtime->_initialized); runtime->open_code_hook = open_code_hook; runtime->open_code_userdata = open_code_userdata; @@ -440,17 +414,15 @@ init_runtime(_PyRuntimeState *runtime, PyPreConfig_InitPythonConfig(&runtime->preconfig); - PyThread_type_lock *lockptrs[NUMLOCKS] = LOCKS_INIT(runtime); - for (int i = 0; i < NUMLOCKS; i++) { - assert(locks[i] != NULL); - *lockptrs[i] = locks[i]; - } - // Set it to the ID of the main thread of the main interpreter. runtime->main_thread = PyThread_get_thread_ident(); runtime->unicode_state.ids.next_index = unicode_next_index; +#if defined(__EMSCRIPTEN__) && defined(PY_CALL_TRAMPOLINE) + _Py_EmscriptenTrampoline_Init(runtime); +#endif + runtime->_initialized = 1; } @@ -467,15 +439,11 @@ _PyRuntimeState_Init(_PyRuntimeState *runtime) // is called multiple times. Py_ssize_t unicode_next_index = runtime->unicode_state.ids.next_index; - PyThread_type_lock locks[NUMLOCKS]; - if (alloc_for_runtime(locks) != 0) { - return _PyStatus_NO_MEMORY(); - } - if (runtime->_initialized) { // Py_Initialize() must be running again. // Reset to _PyRuntimeState_INIT. memcpy(runtime, &initial, sizeof(*runtime)); + assert(!runtime->_initialized); } if (gilstate_tss_init(runtime) != 0) { @@ -489,7 +457,7 @@ _PyRuntimeState_Init(_PyRuntimeState *runtime) } init_runtime(runtime, open_code_hook, open_code_userdata, audit_hook_head, - unicode_next_index, locks); + unicode_next_index); return _PyStatus_OK(); } @@ -509,23 +477,6 @@ _PyRuntimeState_Fini(_PyRuntimeState *runtime) if (PyThread_tss_is_created(&runtime->trashTSSkey)) { PyThread_tss_delete(&runtime->trashTSSkey); } - - /* Force the allocator used by _PyRuntimeState_Init(). */ - PyMemAllocatorEx old_alloc; - _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); -#define FREE_LOCK(LOCK) \ - if (LOCK != NULL) { \ - PyThread_free_lock(LOCK); \ - LOCK = NULL; \ - } - - PyThread_type_lock *lockptrs[NUMLOCKS] = LOCKS_INIT(runtime); - for (int i = 0; i < NUMLOCKS; i++) { - FREE_LOCK(*lockptrs[i]); - } - -#undef FREE_LOCK - PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); } #ifdef HAVE_FORK @@ -537,24 +488,19 @@ _PyRuntimeState_ReInitThreads(_PyRuntimeState *runtime) // This was initially set in _PyRuntimeState_Init(). runtime->main_thread = PyThread_get_thread_ident(); - /* Force default allocator, since _PyRuntimeState_Fini() must - use the same allocator than this function. */ - PyMemAllocatorEx old_alloc; - _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); + // Clears the parking lot. Any waiting threads are dead. This must be + // called before releasing any locks that use the parking lot. + _PyParkingLot_AfterFork(); - PyThread_type_lock *lockptrs[NUMLOCKS] = LOCKS_INIT(runtime); - int reinit_err = 0; - for (int i = 0; i < NUMLOCKS; i++) { - reinit_err += _PyThread_at_fork_reinit(lockptrs[i]); + // Re-initialize global locks + PyMutex *locks[] = LOCKS_INIT(runtime); + for (size_t i = 0; i < Py_ARRAY_LENGTH(locks); i++) { + _PyMutex_at_fork_reinit(locks[i]); } - PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); - /* bpo-42540: id_mutex is freed by _PyInterpreterState_Delete, which does * not force the default allocator. */ - reinit_err += _PyThread_at_fork_reinit(&runtime->interpreters.main->id_mutex); - - if (reinit_err < 0) { + if (_PyThread_at_fork_reinit(&runtime->interpreters.main->id_mutex) < 0) { return _PyStatus_ERR("Failed to reinitialize runtime locks"); } @@ -590,24 +536,6 @@ _PyInterpreterState_Enable(_PyRuntimeState *runtime) { struct pyinterpreters *interpreters = &runtime->interpreters; interpreters->next_id = 0; - - /* Py_Finalize() calls _PyRuntimeState_Fini() which clears the mutex. - Create a new mutex if needed. */ - if (interpreters->mutex == NULL) { - /* Force default allocator, since _PyRuntimeState_Fini() must - use the same allocator than this function. */ - PyMemAllocatorEx old_alloc; - _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); - - interpreters->mutex = PyThread_allocate_lock(); - - PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); - - if (interpreters->mutex == NULL) { - return _PyStatus_ERR("Can't initialize threads for interpreter"); - } - } - return _PyStatus_OK(); } @@ -647,14 +575,13 @@ free_interpreter(PyInterpreterState *interp) main interpreter. We fix those fields here, in addition to the other dynamically initialized fields. */ -static void +static PyStatus init_interpreter(PyInterpreterState *interp, _PyRuntimeState *runtime, int64_t id, - PyInterpreterState *next, - PyThread_type_lock pending_lock) + PyInterpreterState *next) { if (interp->_initialized) { - Py_FatalError("interpreter already initialized"); + return _PyStatus_ERR("interpreter already initialized"); } assert(runtime != NULL); @@ -675,7 +602,12 @@ init_interpreter(PyInterpreterState *interp, memcpy(&interp->obmalloc.pools.used, temp, sizeof(temp)); } - _PyEval_InitState(interp, pending_lock); + PyStatus status = _PyObject_InitState(interp); + if (_PyStatus_EXCEPTION(status)) { + return status; + } + + _PyEval_InitState(interp); _PyGC_InitState(&interp->gc); PyConfig_InitPythonConfig(&interp->config); _PyType_InitCache(interp); @@ -693,48 +625,47 @@ init_interpreter(PyInterpreterState *interp, interp->optimizer = &_PyOptimizer_Default; interp->optimizer_backedge_threshold = _PyOptimizer_Default.backedge_threshold; interp->optimizer_resume_threshold = _PyOptimizer_Default.backedge_threshold; + interp->next_func_version = 1; + interp->executor_list_head = NULL; if (interp != &runtime->_main_interpreter) { /* Fix the self-referential, statically initialized fields. */ interp->dtoa = (struct _dtoa_state)_dtoa_state_INIT(interp); } - interp->f_opcode_trace_set = false; + interp->_initialized = 1; + return _PyStatus_OK(); } -PyInterpreterState * -PyInterpreterState_New(void) + +PyStatus +_PyInterpreterState_New(PyThreadState *tstate, PyInterpreterState **pinterp) { - PyInterpreterState *interp; - _PyRuntimeState *runtime = &_PyRuntime; - PyThreadState *tstate = current_fast_get(runtime); + *pinterp = NULL; - /* tstate is NULL when Py_InitializeFromConfig() calls - PyInterpreterState_New() to create the main interpreter. */ - if (_PySys_Audit(tstate, "cpython.PyInterpreterState_New", NULL) < 0) { - return NULL; - } + // Don't get runtime from tstate since tstate can be NULL + _PyRuntimeState *runtime = &_PyRuntime; - PyThread_type_lock pending_lock = PyThread_allocate_lock(); - if (pending_lock == NULL) { - if (tstate != NULL) { - _PyErr_NoMemory(tstate); + // tstate is NULL when pycore_create_interpreter() calls + // _PyInterpreterState_New() to create the main interpreter. + if (tstate != NULL) { + if (_PySys_Audit(tstate, "cpython.PyInterpreterState_New", NULL) < 0) { + return _PyStatus_ERR("sys.audit failed"); } - return NULL; } - /* Don't get runtime from tstate since tstate can be NULL. */ - struct pyinterpreters *interpreters = &runtime->interpreters; - /* We completely serialize creation of multiple interpreters, since it simplifies things here and blocking concurrent calls isn't a problem. Regardless, we must fully block subinterpreter creation until after the main interpreter is created. */ HEAD_LOCK(runtime); + struct pyinterpreters *interpreters = &runtime->interpreters; int64_t id = interpreters->next_id; interpreters->next_id += 1; // Allocate the interpreter and add it to the runtime state. + PyInterpreterState *interp; + PyStatus status; PyInterpreterState *old_head = interpreters->head; if (old_head == NULL) { // We are creating the main interpreter. @@ -753,36 +684,55 @@ PyInterpreterState_New(void) interp = alloc_interpreter(); if (interp == NULL) { + status = _PyStatus_NO_MEMORY(); goto error; } // Set to _PyInterpreterState_INIT. - memcpy(interp, &initial._main_interpreter, - sizeof(*interp)); + memcpy(interp, &initial._main_interpreter, sizeof(*interp)); if (id < 0) { /* overflow or Py_Initialize() not called yet! */ - if (tstate != NULL) { - _PyErr_SetString(tstate, PyExc_RuntimeError, - "failed to get an interpreter ID"); - } + status = _PyStatus_ERR("failed to get an interpreter ID"); goto error; } } interpreters->head = interp; - init_interpreter(interp, runtime, id, old_head, pending_lock); + status = init_interpreter(interp, runtime, + id, old_head); + if (_PyStatus_EXCEPTION(status)) { + goto error; + } HEAD_UNLOCK(runtime); - return interp; + + assert(interp != NULL); + *pinterp = interp; + return _PyStatus_OK(); error: HEAD_UNLOCK(runtime); - PyThread_free_lock(pending_lock); if (interp != NULL) { free_interpreter(interp); } - return NULL; + return status; +} + + +PyInterpreterState * +PyInterpreterState_New(void) +{ + // tstate can be NULL + PyThreadState *tstate = current_fast_get(&_PyRuntime); + + PyInterpreterState *interp; + PyStatus status = _PyInterpreterState_New(tstate, &interp); + if (_PyStatus_EXCEPTION(status)) { + Py_ExitStatusException(status); + } + assert(interp != NULL); + return interp; } @@ -841,6 +791,10 @@ interpreter_clear(PyInterpreterState *interp, PyThreadState *tstate) Py_CLEAR(interp->audit_hooks); + // At this time, all the threads should be cleared so we don't need + // atomic operations for eval_breaker + interp->ceval.eval_breaker = 0; + for (int i = 0; i < _PY_MONITORING_UNGROUPED_EVENTS; i++) { interp->monitors.tools[i] = 0; } @@ -917,7 +871,6 @@ interpreter_clear(PyInterpreterState *interp, PyThreadState *tstate) interp->code_watchers[i] = NULL; } interp->active_code_watchers = 0; - interp->f_opcode_trace_set = false; // XXX Once we have one allocator per interpreter (i.e. // per-interpreter GC) we must ensure that all of the interpreter's // objects have been cleaned up at the point. @@ -945,6 +898,7 @@ _PyInterpreterState_Clear(PyThreadState *tstate) static inline void tstate_deactivate(PyThreadState *tstate); +static void tstate_set_detached(PyThreadState *tstate); static void zapthreads(PyInterpreterState *interp); void @@ -958,15 +912,11 @@ PyInterpreterState_Delete(PyInterpreterState *interp) PyThreadState *tcur = current_fast_get(runtime); if (tcur != NULL && interp == tcur->interp) { /* Unset current thread. After this, many C API calls become crashy. */ - current_fast_clear(runtime); - tstate_deactivate(tcur); - _PyEval_ReleaseLock(interp, NULL); + _PyThreadState_Detach(tcur); } zapthreads(interp); - _PyEval_FiniState(&interp->ceval); - // XXX These two calls should be done at the end of clear_interpreter(), // but currently some objects get decref'ed after that. #ifdef Py_REF_DEBUG @@ -1000,6 +950,9 @@ PyInterpreterState_Delete(PyInterpreterState *interp) if (interp->id_mutex != NULL) { PyThread_free_lock(interp->id_mutex); } + + _PyObject_FiniState(interp); + free_interpreter(interp); } @@ -1052,6 +1005,61 @@ _PyInterpreterState_DeleteExceptMain(_PyRuntimeState *runtime) #endif +int +_PyInterpreterState_SetRunningMain(PyInterpreterState *interp) +{ + if (_PyInterpreterState_FailIfRunningMain(interp) < 0) { + return -1; + } + PyThreadState *tstate = current_fast_get(&_PyRuntime); + _Py_EnsureTstateNotNULL(tstate); + if (tstate->interp != interp) { + PyErr_SetString(PyExc_RuntimeError, + "current tstate has wrong interpreter"); + return -1; + } + interp->threads.main = tstate; + return 0; +} + +void +_PyInterpreterState_SetNotRunningMain(PyInterpreterState *interp) +{ + PyThreadState *tstate = interp->threads.main; + assert(tstate == current_fast_get(&_PyRuntime)); + + if (tstate->on_delete != NULL) { + // The threading module was imported for the first time in this + // thread, so it was set as threading._main_thread. (See gh-75698.) + // The thread has finished running the Python program so we mark + // the thread object as finished. + assert(tstate->_whence != _PyThreadState_WHENCE_THREADING); + tstate->on_delete(tstate->on_delete_data); + tstate->on_delete = NULL; + tstate->on_delete_data = NULL; + } + + interp->threads.main = NULL; +} + +int +_PyInterpreterState_IsRunningMain(PyInterpreterState *interp) +{ + return (interp->threads.main != NULL); +} + +int +_PyInterpreterState_FailIfRunningMain(PyInterpreterState *interp) +{ + if (interp->threads.main != NULL) { + PyErr_SetString(PyExc_RuntimeError, + "interpreter already running"); + return -1; + } + return 0; +} + + //---------- // accessors //---------- @@ -1111,8 +1119,10 @@ _PyInterpreterState_IDDecref(PyInterpreterState *interp) PyThread_release_lock(interp->id_mutex); if (refcount == 0 && interp->requires_idref) { - // XXX Using the "head" thread isn't strictly correct. - PyThreadState *tstate = PyInterpreterState_ThreadHead(interp); + PyThreadState *tstate = _PyThreadState_New(interp, + _PyThreadState_WHENCE_INTERP); + _PyThreadState_Bind(tstate); + // XXX Possible GILState issues? PyThreadState *save_tstate = _PyThreadState_Swap(runtime, tstate); Py_EndInterpreter(tstate); @@ -1211,7 +1221,7 @@ _PyInterpreterState_LookUpID(int64_t requested_id) HEAD_UNLOCK(runtime); } if (interp == NULL && !PyErr_Occurred()) { - PyErr_Format(PyExc_RuntimeError, + PyErr_Format(PyExc_InterpreterNotFoundError, "unrecognized interpreter ID %lld", requested_id); } return interp; @@ -1255,18 +1265,24 @@ allocate_chunk(int size_in_bytes, _PyStackChunk* previous) return res; } -static PyThreadState * +static _PyThreadStateImpl * alloc_threadstate(void) { - return PyMem_RawCalloc(1, sizeof(PyThreadState)); + return PyMem_RawCalloc(1, sizeof(_PyThreadStateImpl)); } static void -free_threadstate(PyThreadState *tstate) +free_threadstate(_PyThreadStateImpl *tstate) { // The initial thread state of the interpreter is allocated // as part of the interpreter state so should not be freed. - if (tstate != &tstate->interp->_initial_thread) { + if (tstate == &tstate->base.interp->_initial_thread) { + // Restore to _PyThreadState_INIT. + memcpy(tstate, + &initial._main_interpreter._initial_thread, + sizeof(*tstate)); + } + else { PyMem_RawFree(tstate); } } @@ -1280,9 +1296,10 @@ free_threadstate(PyThreadState *tstate) */ static void -init_threadstate(PyThreadState *tstate, - PyInterpreterState *interp, uint64_t id) +init_threadstate(_PyThreadStateImpl *_tstate, + PyInterpreterState *interp, uint64_t id, int whence) { + PyThreadState *tstate = (PyThreadState *)_tstate; if (tstate->_status.initialized) { Py_FatalError("thread state already initialized"); } @@ -1294,6 +1311,10 @@ init_threadstate(PyThreadState *tstate, assert(tstate->next == NULL); assert(tstate->prev == NULL); + assert(tstate->_whence == _PyThreadState_WHENCE_NOTSET); + assert(whence >= 0 && whence <= _PyThreadState_WHENCE_EXEC); + tstate->_whence = whence; + assert(id > 0); tstate->id = id; @@ -1301,7 +1322,7 @@ init_threadstate(PyThreadState *tstate, tstate->py_recursion_limit = interp->ceval.recursion_limit, tstate->py_recursion_remaining = interp->ceval.recursion_limit, - tstate->c_recursion_remaining = C_RECURSION_LIMIT; + tstate->c_recursion_remaining = Py_C_RECURSION_LIMIT; tstate->exc_info = &tstate->exc_state; @@ -1309,7 +1330,7 @@ init_threadstate(PyThreadState *tstate, // This is cleared when PyGILState_Ensure() creates the thread state. tstate->gilstate_counter = 1; - tstate->cframe = &tstate->root_cframe; + tstate->current_frame = NULL; tstate->datastack_chunk = NULL; tstate->datastack_top = NULL; tstate->datastack_limit = NULL; @@ -1323,8 +1344,6 @@ add_threadstate(PyInterpreterState *interp, PyThreadState *tstate, PyThreadState *next) { assert(interp->threads.head != tstate); - assert((next != NULL && tstate->id != 1) || - (next == NULL && tstate->id == 1)); if (next != NULL) { assert(next->prev == NULL || next->prev == tstate); next->prev = tstate; @@ -1335,15 +1354,15 @@ add_threadstate(PyInterpreterState *interp, PyThreadState *tstate, } static PyThreadState * -new_threadstate(PyInterpreterState *interp) +new_threadstate(PyInterpreterState *interp, int whence) { - PyThreadState *tstate; + _PyThreadStateImpl *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(); + _PyThreadStateImpl *new_tstate = alloc_threadstate(); int used_newtstate; if (new_tstate == NULL) { return NULL; @@ -1358,10 +1377,10 @@ new_threadstate(PyInterpreterState *interp) PyThreadState *old_head = interp->threads.head; if (old_head == NULL) { // It's the interpreter's initial thread state. - assert(id == 1); used_newtstate = 0; tstate = &interp->_initial_thread; } + // XXX Re-use interp->_initial_thread if not in use? else { // Every valid interpreter must have at least one thread. assert(id > 1); @@ -1374,21 +1393,22 @@ new_threadstate(PyInterpreterState *interp) sizeof(*tstate)); } - init_threadstate(tstate, interp, id); - add_threadstate(interp, tstate, old_head); + init_threadstate(tstate, interp, id, whence); + add_threadstate(interp, (PyThreadState *)tstate, 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; + return (PyThreadState *)tstate; } PyThreadState * PyThreadState_New(PyInterpreterState *interp) { - PyThreadState *tstate = new_threadstate(interp); + PyThreadState *tstate = new_threadstate(interp, + _PyThreadState_WHENCE_UNKNOWN); if (tstate) { bind_tstate(tstate); // This makes sure there's a gilstate tstate bound @@ -1402,16 +1422,16 @@ PyThreadState_New(PyInterpreterState *interp) // This must be followed by a call to _PyThreadState_Bind(); PyThreadState * -_PyThreadState_New(PyInterpreterState *interp) +_PyThreadState_New(PyInterpreterState *interp, int whence) { - return new_threadstate(interp); + return new_threadstate(interp, whence); } // We keep this for stable ABI compabibility. PyAPI_FUNC(PyThreadState*) _PyThreadState_Prealloc(PyInterpreterState *interp) { - return _PyThreadState_New(interp); + return _PyThreadState_New(interp, _PyThreadState_WHENCE_UNKNOWN); } // We keep this around for (accidental) stable ABI compatibility. @@ -1435,10 +1455,19 @@ clear_datastack(PyThreadState *tstate) } } +void +_Py_ClearFreeLists(_PyFreeListState *state, int is_finalization) +{ + _PyFloat_ClearFreeList(state, is_finalization); + _PyTuple_ClearFreeList(state, is_finalization); + _PyList_ClearFreeList(state, is_finalization); +} + void PyThreadState_Clear(PyThreadState *tstate) { assert(tstate->_status.initialized && !tstate->_status.cleared); + assert(current_fast_get(&_PyRuntime)->interp == tstate->interp); // XXX assert(!tstate->_status.bound || tstate->_status.unbound); tstate->_status.finalizing = 1; // just in case @@ -1451,7 +1480,7 @@ PyThreadState_Clear(PyThreadState *tstate) int verbose = _PyInterpreterState_GetConfig(tstate->interp)->verbose; - if (verbose && tstate->cframe->current_frame != NULL) { + if (verbose && tstate->current_frame != NULL) { /* bpo-20526: After the main thread calls _PyInterpreterState_SetFinalizing() in Py_FinalizeEx() (or in Py_EndInterpreter() for subinterpreters), @@ -1508,8 +1537,21 @@ PyThreadState_Clear(PyThreadState *tstate) Py_CLEAR(tstate->context); if (tstate->on_delete != NULL) { + // For the "main" thread of each interpreter, this is meant + // to be done in _PyInterpreterState_SetNotRunningMain(). + // That leaves threads created by the threading module, + // and any threads killed by forking. + // However, we also accommodate "main" threads that still + // don't call _PyInterpreterState_SetNotRunningMain() yet. tstate->on_delete(tstate->on_delete_data); } +#ifdef Py_GIL_DISABLED + // Each thread should clear own freelists in free-threading builds. + _PyFreeListState *freelist_state = &((_PyThreadStateImpl*)tstate)->freelist_state; + _Py_ClearFreeLists(freelist_state, 0); +#endif + + _PyThreadState_ClearMimallocHeaps(tstate); tstate->_status.cleared = 1; @@ -1522,6 +1564,7 @@ static void tstate_delete_common(PyThreadState *tstate) { assert(tstate->_status.cleared && !tstate->_status.finalized); + assert(tstate->state != _Py_THREAD_ATTACHED); PyInterpreterState *interp = tstate->interp; if (interp == NULL) { @@ -1563,7 +1606,7 @@ zapthreads(PyInterpreterState *interp) while ((tstate = interp->threads.head) != NULL) { tstate_verify_not_active(tstate); tstate_delete_common(tstate); - free_threadstate(tstate); + free_threadstate((_PyThreadStateImpl *)tstate); } } @@ -1574,7 +1617,7 @@ PyThreadState_Delete(PyThreadState *tstate) _Py_EnsureTstateNotNULL(tstate); tstate_verify_not_active(tstate); tstate_delete_common(tstate); - free_threadstate(tstate); + free_threadstate((_PyThreadStateImpl *)tstate); } @@ -1582,10 +1625,11 @@ void _PyThreadState_DeleteCurrent(PyThreadState *tstate) { _Py_EnsureTstateNotNULL(tstate); + tstate_set_detached(tstate); tstate_delete_common(tstate); current_fast_clear(tstate->interp->runtime); _PyEval_ReleaseLock(tstate->interp, NULL); - free_threadstate(tstate); + free_threadstate((_PyThreadStateImpl *)tstate); } void @@ -1635,7 +1679,7 @@ _PyThreadState_DeleteExcept(PyThreadState *tstate) for (p = list; p; p = next) { next = p->next; PyThreadState_Clear(p); - free_threadstate(p); + free_threadstate((_PyThreadStateImpl *)p); } } @@ -1738,6 +1782,88 @@ tstate_deactivate(PyThreadState *tstate) // It will still be used in PyGILState_Ensure(). } +static int +tstate_try_attach(PyThreadState *tstate) +{ +#ifdef Py_GIL_DISABLED + int expected = _Py_THREAD_DETACHED; + if (_Py_atomic_compare_exchange_int( + &tstate->state, + &expected, + _Py_THREAD_ATTACHED)) { + return 1; + } + return 0; +#else + assert(tstate->state == _Py_THREAD_DETACHED); + tstate->state = _Py_THREAD_ATTACHED; + return 1; +#endif +} + +static void +tstate_set_detached(PyThreadState *tstate) +{ + assert(tstate->state == _Py_THREAD_ATTACHED); +#ifdef Py_GIL_DISABLED + _Py_atomic_store_int(&tstate->state, _Py_THREAD_DETACHED); +#else + tstate->state = _Py_THREAD_DETACHED; +#endif +} + +void +_PyThreadState_Attach(PyThreadState *tstate) +{ +#if defined(Py_DEBUG) + // This is called from PyEval_RestoreThread(). Similar + // to it, we need to ensure errno doesn't change. + int err = errno; +#endif + + _Py_EnsureTstateNotNULL(tstate); + if (current_fast_get(&_PyRuntime) != NULL) { + Py_FatalError("non-NULL old thread state"); + } + + _PyEval_AcquireLock(tstate); + + // XXX assert(tstate_is_alive(tstate)); + current_fast_set(&_PyRuntime, tstate); + tstate_activate(tstate); + + if (!tstate_try_attach(tstate)) { + // TODO: Once stop-the-world GC is implemented for --disable-gil builds + // this will need to wait until the GC completes. For now, this case + // should never happen. + Py_FatalError("thread attach failed"); + } + + // Resume previous critical section. This acquires the lock(s) from the + // top-most critical section. + if (tstate->critical_section != 0) { + _PyCriticalSection_Resume(tstate); + } + +#if defined(Py_DEBUG) + errno = err; +#endif +} + +void +_PyThreadState_Detach(PyThreadState *tstate) +{ + // XXX assert(tstate_is_alive(tstate) && tstate_is_bound(tstate)); + assert(tstate->state == _Py_THREAD_ATTACHED); + assert(tstate == current_fast_get(&_PyRuntime)); + if (tstate->critical_section != 0) { + _PyCriticalSection_SuspendAll(tstate); + } + tstate_set_detached(tstate); + tstate_deactivate(tstate); + current_fast_clear(&_PyRuntime); + _PyEval_ReleaseLock(tstate->interp, tstate); +} //---------- // other API @@ -1796,7 +1922,7 @@ PyThreadState_SetAsyncExc(unsigned long id, PyObject *exc) //--------------------------------- PyThreadState * -_PyThreadState_UncheckedGet(void) +PyThreadState_GetUnchecked(void) { return current_fast_get(&_PyRuntime); } @@ -1810,56 +1936,15 @@ PyThreadState_Get(void) return tstate; } - -static void -_swap_thread_states(_PyRuntimeState *runtime, - PyThreadState *oldts, PyThreadState *newts) -{ - // XXX Do this only if oldts != NULL? - current_fast_clear(runtime); - - if (oldts != NULL) { - // XXX assert(tstate_is_alive(oldts) && tstate_is_bound(oldts)); - tstate_deactivate(oldts); - } - - if (newts != NULL) { - // XXX assert(tstate_is_alive(newts)); - assert(tstate_is_bound(newts)); - current_fast_set(runtime, newts); - tstate_activate(newts); - } -} - -PyThreadState * -_PyThreadState_SwapNoGIL(PyThreadState *newts) -{ -#if defined(Py_DEBUG) - /* This can be called from PyEval_RestoreThread(). Similar - to it, we need to ensure errno doesn't change. - */ - int err = errno; -#endif - - PyThreadState *oldts = current_fast_get(&_PyRuntime); - _swap_thread_states(&_PyRuntime, oldts, newts); - -#if defined(Py_DEBUG) - errno = err; -#endif - return oldts; -} - PyThreadState * _PyThreadState_Swap(_PyRuntimeState *runtime, PyThreadState *newts) { PyThreadState *oldts = current_fast_get(runtime); if (oldts != NULL) { - _PyEval_ReleaseLock(oldts->interp, oldts); + _PyThreadState_Detach(oldts); } - _swap_thread_states(runtime, oldts, newts); if (newts != NULL) { - _PyEval_AcquireLock(newts); + _PyThreadState_Attach(newts); } return oldts; } @@ -1874,6 +1959,10 @@ PyThreadState_Swap(PyThreadState *newts) void _PyThreadState_Bind(PyThreadState *tstate) { + // gh-104690: If Python is being finalized and PyInterpreterState_Delete() + // was called, tstate becomes a dangling pointer. + assert(_PyThreadState_CheckConsistency(tstate)); + bind_tstate(tstate); // This makes sure there's a gilstate tstate bound // as soon as possible. @@ -1882,6 +1971,20 @@ _PyThreadState_Bind(PyThreadState *tstate) } } +#if defined(Py_GIL_DISABLED) && !defined(Py_LIMITED_API) +uintptr_t +_Py_GetThreadLocal_Addr(void) +{ +#ifdef HAVE_THREAD_LOCAL + // gh-112535: Use the address of the thread-local PyThreadState variable as + // a unique identifier for the current thread. Each thread has a unique + // _Py_tss_tstate variable with a unique address. + return (uintptr_t)&_Py_tss_tstate; +#else +# error "no supported thread-local variable storage classifier" +#endif +} +#endif /***********************************/ /* routines for advanced debuggers */ @@ -1952,7 +2055,7 @@ _PyThread_CurrentFrames(void) for (i = runtime->interpreters.head; i != NULL; i = i->next) { PyThreadState *t; for (t = i->threads.head; t != NULL; t = t->next) { - _PyInterpreterFrame *frame = t->cframe->current_frame; + _PyInterpreterFrame *frame = t->current_frame; frame = _PyFrame_GetFirstComplete(frame); if (frame == NULL) { continue; @@ -2082,7 +2185,7 @@ _PyGILState_Fini(PyInterpreterState *interp) // XXX Drop this. -PyStatus +void _PyGILState_SetTstate(PyThreadState *tstate) { /* must init with valid states */ @@ -2092,7 +2195,7 @@ _PyGILState_SetTstate(PyThreadState *tstate) if (!_Py_IsMainInterpreter(tstate->interp)) { /* Currently, PyGILState is shared by all interpreters. The main * interpreter is responsible to initialize it. */ - return _PyStatus_OK(); + return; } #ifndef NDEBUG @@ -2102,8 +2205,6 @@ _PyGILState_SetTstate(PyThreadState *tstate) assert(gilstate_tss_get(runtime) == tstate); assert(tstate->gilstate_counter == 1); #endif - - return _PyStatus_OK(); } PyInterpreterState * @@ -2164,7 +2265,9 @@ PyGILState_Ensure(void) int has_gil; if (tcur == NULL) { /* Create a new Python thread state for this thread */ - tcur = new_threadstate(runtime->gilstate.autoInterpreterState); + // XXX Use PyInterpreterState_EnsureThreadState()? + tcur = new_threadstate(runtime->gilstate.autoInterpreterState, + _PyThreadState_WHENCE_GILSTATE); if (tcur == NULL) { Py_FatalError("Couldn't create thread-state for new thread"); } @@ -2242,496 +2345,9 @@ PyGILState_Release(PyGILState_STATE oldstate) } -/**************************/ -/* cross-interpreter data */ -/**************************/ - -/* cross-interpreter data */ - -static inline void -_xidata_init(_PyCrossInterpreterData *data) -{ - // If the value is being reused - // then _xidata_clear() should have been called already. - assert(data->data == NULL); - assert(data->obj == NULL); - *data = (_PyCrossInterpreterData){0}; - data->interp = -1; -} - -static inline void -_xidata_clear(_PyCrossInterpreterData *data) -{ - if (data->free != NULL) { - data->free(data->data); - } - data->data = NULL; - Py_CLEAR(data->obj); -} - -void -_PyCrossInterpreterData_Init(_PyCrossInterpreterData *data, - PyInterpreterState *interp, - void *shared, PyObject *obj, - xid_newobjectfunc new_object) -{ - assert(data != NULL); - assert(new_object != NULL); - _xidata_init(data); - data->data = shared; - if (obj != NULL) { - assert(interp != NULL); - // released in _PyCrossInterpreterData_Clear() - data->obj = Py_NewRef(obj); - } - // Ideally every object would know its owning interpreter. - // Until then, we have to rely on the caller to identify it - // (but we don't need it in all cases). - data->interp = (interp != NULL) ? interp->id : -1; - data->new_object = new_object; -} - -int -_PyCrossInterpreterData_InitWithSize(_PyCrossInterpreterData *data, - PyInterpreterState *interp, - const size_t size, PyObject *obj, - xid_newobjectfunc new_object) -{ - assert(size > 0); - // For now we always free the shared data in the same interpreter - // where it was allocated, so the interpreter is required. - assert(interp != NULL); - _PyCrossInterpreterData_Init(data, interp, NULL, obj, new_object); - data->data = PyMem_RawMalloc(size); - if (data->data == NULL) { - return -1; - } - data->free = PyMem_RawFree; - return 0; -} - -void -_PyCrossInterpreterData_Clear(PyInterpreterState *interp, - _PyCrossInterpreterData *data) -{ - assert(data != NULL); - // This must be called in the owning interpreter. - assert(interp == NULL || data->interp == interp->id); - _xidata_clear(data); -} - -static int -_check_xidata(PyThreadState *tstate, _PyCrossInterpreterData *data) -{ - // data->data can be anything, including NULL, so we don't check it. - - // data->obj may be NULL, so we don't check it. - - if (data->interp < 0) { - _PyErr_SetString(tstate, PyExc_SystemError, "missing interp"); - return -1; - } - - if (data->new_object == NULL) { - _PyErr_SetString(tstate, PyExc_SystemError, "missing new_object func"); - return -1; - } - - // data->free may be NULL, so we don't check it. - - return 0; -} - -crossinterpdatafunc _PyCrossInterpreterData_Lookup(PyObject *); - -/* This is a separate func from _PyCrossInterpreterData_Lookup in order - to keep the registry code separate. */ -static crossinterpdatafunc -_lookup_getdata(PyObject *obj) -{ - crossinterpdatafunc getdata = _PyCrossInterpreterData_Lookup(obj); - if (getdata == NULL && PyErr_Occurred() == 0) - PyErr_Format(PyExc_ValueError, - "%S does not support cross-interpreter data", obj); - return getdata; -} - -int -_PyObject_CheckCrossInterpreterData(PyObject *obj) -{ - crossinterpdatafunc getdata = _lookup_getdata(obj); - if (getdata == NULL) { - return -1; - } - return 0; -} - -int -_PyObject_GetCrossInterpreterData(PyObject *obj, _PyCrossInterpreterData *data) -{ - _PyRuntimeState *runtime = &_PyRuntime; - PyThreadState *tstate = current_fast_get(runtime); -#ifdef Py_DEBUG - // The caller must hold the GIL - _Py_EnsureTstateNotNULL(tstate); -#endif - PyInterpreterState *interp = tstate->interp; - - // Reset data before re-populating. - *data = (_PyCrossInterpreterData){0}; - data->interp = -1; - - // Call the "getdata" func for the object. - Py_INCREF(obj); - crossinterpdatafunc getdata = _lookup_getdata(obj); - if (getdata == NULL) { - Py_DECREF(obj); - return -1; - } - int res = getdata(tstate, obj, data); - Py_DECREF(obj); - if (res != 0) { - return -1; - } - - // Fill in the blanks and validate the result. - data->interp = interp->id; - if (_check_xidata(tstate, data) != 0) { - (void)_PyCrossInterpreterData_Release(data); - return -1; - } - - return 0; -} - -PyObject * -_PyCrossInterpreterData_NewObject(_PyCrossInterpreterData *data) -{ - return data->new_object(data); -} - -typedef void (*releasefunc)(PyInterpreterState *, void *); - -static void -_call_in_interpreter(PyInterpreterState *interp, releasefunc func, void *arg) -{ - /* We would use Py_AddPendingCall() if it weren't specific to the - * main interpreter (see bpo-33608). In the meantime we take a - * naive approach. - */ - _PyRuntimeState *runtime = interp->runtime; - PyThreadState *save_tstate = NULL; - if (interp != current_fast_get(runtime)->interp) { - // XXX Using the "head" thread isn't strictly correct. - PyThreadState *tstate = PyInterpreterState_ThreadHead(interp); - // XXX Possible GILState issues? - save_tstate = _PyThreadState_Swap(runtime, tstate); - } - - // XXX Once the GIL is per-interpreter, this should be called with the - // calling interpreter's GIL released and the target interpreter's held. - func(interp, arg); - - // Switch back. - if (save_tstate != NULL) { - _PyThreadState_Swap(runtime, save_tstate); - } -} - -int -_PyCrossInterpreterData_Release(_PyCrossInterpreterData *data) -{ - if (data->free == NULL && data->obj == NULL) { - // Nothing to release! - data->data = NULL; - return 0; - } - - // Switch to the original interpreter. - PyInterpreterState *interp = _PyInterpreterState_LookUpID(data->interp); - if (interp == NULL) { - // The interpreter was already destroyed. - // This function shouldn't have been called. - // XXX Someone leaked some memory... - assert(PyErr_Occurred()); - return -1; - } - - // "Release" the data and/or the object. - _call_in_interpreter(interp, - (releasefunc)_PyCrossInterpreterData_Clear, data); - return 0; -} - -/* registry of {type -> crossinterpdatafunc} */ - -/* For now we use a global registry of shareable classes. An - alternative would be to add a tp_* slot for a class's - crossinterpdatafunc. It would be simpler and more efficient. */ - -static int -_xidregistry_add_type(struct _xidregistry *xidregistry, PyTypeObject *cls, - crossinterpdatafunc getdata) -{ - // Note that we effectively replace already registered classes - // rather than failing. - struct _xidregitem *newhead = PyMem_RawMalloc(sizeof(struct _xidregitem)); - if (newhead == NULL) { - return -1; - } - // XXX Assign a callback to clear the entry from the registry? - newhead->cls = PyWeakref_NewRef((PyObject *)cls, NULL); - if (newhead->cls == NULL) { - PyMem_RawFree(newhead); - return -1; - } - newhead->getdata = getdata; - newhead->prev = NULL; - newhead->next = xidregistry->head; - if (newhead->next != NULL) { - newhead->next->prev = newhead; - } - xidregistry->head = newhead; - return 0; -} - -static struct _xidregitem * -_xidregistry_remove_entry(struct _xidregistry *xidregistry, - struct _xidregitem *entry) -{ - struct _xidregitem *next = entry->next; - if (entry->prev != NULL) { - assert(entry->prev->next == entry); - entry->prev->next = next; - } - else { - assert(xidregistry->head == entry); - xidregistry->head = next; - } - if (next != NULL) { - next->prev = entry->prev; - } - Py_DECREF(entry->cls); - PyMem_RawFree(entry); - return next; -} - -static struct _xidregitem * -_xidregistry_find_type(struct _xidregistry *xidregistry, PyTypeObject *cls) -{ - struct _xidregitem *cur = xidregistry->head; - while (cur != NULL) { - PyObject *registered = _PyWeakref_GET_REF(cur->cls); - if (registered == NULL) { - // The weakly ref'ed object was freed. - cur = _xidregistry_remove_entry(xidregistry, cur); - } - else { - assert(PyType_Check(registered)); - if (registered == (PyObject *)cls) { - Py_DECREF(registered); - return cur; - } - Py_DECREF(registered); - cur = cur->next; - } - } - return NULL; -} - -static void _register_builtins_for_crossinterpreter_data(struct _xidregistry *xidregistry); - -int -_PyCrossInterpreterData_RegisterClass(PyTypeObject *cls, - crossinterpdatafunc getdata) -{ - if (!PyType_Check(cls)) { - PyErr_Format(PyExc_ValueError, "only classes may be registered"); - return -1; - } - if (getdata == NULL) { - PyErr_Format(PyExc_ValueError, "missing 'getdata' func"); - return -1; - } - - struct _xidregistry *xidregistry = &_PyRuntime.xidregistry ; - PyThread_acquire_lock(xidregistry->mutex, WAIT_LOCK); - if (xidregistry->head == NULL) { - _register_builtins_for_crossinterpreter_data(xidregistry); - } - int res = _xidregistry_add_type(xidregistry, cls, getdata); - PyThread_release_lock(xidregistry->mutex); - return res; -} - -int -_PyCrossInterpreterData_UnregisterClass(PyTypeObject *cls) -{ - int res = 0; - struct _xidregistry *xidregistry = &_PyRuntime.xidregistry ; - PyThread_acquire_lock(xidregistry->mutex, WAIT_LOCK); - struct _xidregitem *matched = _xidregistry_find_type(xidregistry, cls); - if (matched != NULL) { - (void)_xidregistry_remove_entry(xidregistry, matched); - res = 1; - } - PyThread_release_lock(xidregistry->mutex); - return res; -} - - -/* Cross-interpreter objects are looked up by exact match on the class. - We can reassess this policy when we move from a global registry to a - tp_* slot. */ - -crossinterpdatafunc -_PyCrossInterpreterData_Lookup(PyObject *obj) -{ - struct _xidregistry *xidregistry = &_PyRuntime.xidregistry ; - PyObject *cls = PyObject_Type(obj); - PyThread_acquire_lock(xidregistry->mutex, WAIT_LOCK); - if (xidregistry->head == NULL) { - _register_builtins_for_crossinterpreter_data(xidregistry); - } - struct _xidregitem *matched = _xidregistry_find_type(xidregistry, - (PyTypeObject *)cls); - Py_DECREF(cls); - PyThread_release_lock(xidregistry->mutex); - return matched != NULL ? matched->getdata : NULL; -} - -/* cross-interpreter data for builtin types */ - -struct _shared_bytes_data { - char *bytes; - Py_ssize_t len; -}; - -static PyObject * -_new_bytes_object(_PyCrossInterpreterData *data) -{ - struct _shared_bytes_data *shared = (struct _shared_bytes_data *)(data->data); - return PyBytes_FromStringAndSize(shared->bytes, shared->len); -} - -static int -_bytes_shared(PyThreadState *tstate, PyObject *obj, - _PyCrossInterpreterData *data) -{ - if (_PyCrossInterpreterData_InitWithSize( - data, tstate->interp, sizeof(struct _shared_bytes_data), obj, - _new_bytes_object - ) < 0) - { - return -1; - } - struct _shared_bytes_data *shared = (struct _shared_bytes_data *)data->data; - if (PyBytes_AsStringAndSize(obj, &shared->bytes, &shared->len) < 0) { - _PyCrossInterpreterData_Clear(tstate->interp, data); - return -1; - } - return 0; -} - -struct _shared_str_data { - int kind; - const void *buffer; - Py_ssize_t len; -}; - -static PyObject * -_new_str_object(_PyCrossInterpreterData *data) -{ - struct _shared_str_data *shared = (struct _shared_str_data *)(data->data); - return PyUnicode_FromKindAndData(shared->kind, shared->buffer, shared->len); -} - -static int -_str_shared(PyThreadState *tstate, PyObject *obj, - _PyCrossInterpreterData *data) -{ - if (_PyCrossInterpreterData_InitWithSize( - data, tstate->interp, sizeof(struct _shared_str_data), obj, - _new_str_object - ) < 0) - { - return -1; - } - struct _shared_str_data *shared = (struct _shared_str_data *)data->data; - shared->kind = PyUnicode_KIND(obj); - shared->buffer = PyUnicode_DATA(obj); - shared->len = PyUnicode_GET_LENGTH(obj); - return 0; -} - -static PyObject * -_new_long_object(_PyCrossInterpreterData *data) -{ - return PyLong_FromSsize_t((Py_ssize_t)(data->data)); -} - -static int -_long_shared(PyThreadState *tstate, PyObject *obj, - _PyCrossInterpreterData *data) -{ - /* Note that this means the size of shareable ints is bounded by - * sys.maxsize. Hence on 32-bit architectures that is half the - * size of maximum shareable ints on 64-bit. - */ - Py_ssize_t value = PyLong_AsSsize_t(obj); - if (value == -1 && PyErr_Occurred()) { - if (PyErr_ExceptionMatches(PyExc_OverflowError)) { - PyErr_SetString(PyExc_OverflowError, "try sending as bytes"); - } - return -1; - } - _PyCrossInterpreterData_Init(data, tstate->interp, (void *)value, NULL, - _new_long_object); - // data->obj and data->free remain NULL - return 0; -} - -static PyObject * -_new_none_object(_PyCrossInterpreterData *data) -{ - // XXX Singleton refcounts are problematic across interpreters... - return Py_NewRef(Py_None); -} - -static int -_none_shared(PyThreadState *tstate, PyObject *obj, - _PyCrossInterpreterData *data) -{ - _PyCrossInterpreterData_Init(data, tstate->interp, NULL, NULL, - _new_none_object); - // data->data, data->obj and data->free remain NULL - return 0; -} - -static void -_register_builtins_for_crossinterpreter_data(struct _xidregistry *xidregistry) -{ - // None - if (_xidregistry_add_type(xidregistry, (PyTypeObject *)PyObject_Type(Py_None), _none_shared) != 0) { - Py_FatalError("could not register None for cross-interpreter sharing"); - } - - // int - if (_xidregistry_add_type(xidregistry, &PyLong_Type, _long_shared) != 0) { - Py_FatalError("could not register int for cross-interpreter sharing"); - } - - // bytes - if (_xidregistry_add_type(xidregistry, &PyBytes_Type, _bytes_shared) != 0) { - Py_FatalError("could not register bytes for cross-interpreter sharing"); - } - - // str - if (_xidregistry_add_type(xidregistry, &PyUnicode_Type, _str_shared) != 0) { - Py_FatalError("could not register str for cross-interpreter sharing"); - } -} - +/*************/ +/* Other API */ +/*************/ _PyFrameEvalFunction _PyInterpreterState_GetEvalFrameFunc(PyInterpreterState *interp) @@ -2857,6 +2473,112 @@ _PyThreadState_PopFrame(PyThreadState *tstate, _PyInterpreterFrame * frame) } -#ifdef __cplusplus +#ifndef NDEBUG +// Check that a Python thread state valid. In practice, this function is used +// on a Python debug build to check if 'tstate' is a dangling pointer, if the +// PyThreadState memory has been freed. +// +// Usage: +// +// assert(_PyThreadState_CheckConsistency(tstate)); +int +_PyThreadState_CheckConsistency(PyThreadState *tstate) +{ + assert(!_PyMem_IsPtrFreed(tstate)); + assert(!_PyMem_IsPtrFreed(tstate->interp)); + return 1; +} +#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 can be a dangling pointer (point to freed memory): only tstate value +// is used, the pointer is not deferenced. +// +// tstate must be non-NULL. +int +_PyThreadState_MustExit(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. */ + unsigned long finalizing_id = _PyRuntimeState_GetFinalizingID(&_PyRuntime); + PyThreadState *finalizing = _PyRuntimeState_GetFinalizing(&_PyRuntime); + if (finalizing == NULL) { + // XXX This isn't completely safe from daemon thraeds, + // since tstate might be a dangling pointer. + finalizing = _PyInterpreterState_GetFinalizing(tstate->interp); + finalizing_id = _PyInterpreterState_GetFinalizingID(tstate->interp); + } + // XXX else check &_PyRuntime._main_interpreter._initial_thread + if (finalizing == NULL) { + return 0; + } + else if (finalizing == tstate) { + return 0; + } + else if (finalizing_id == PyThread_get_thread_ident()) { + /* gh-109793: we must have switched interpreters. */ + return 0; + } + return 1; +} + +/********************/ +/* mimalloc support */ +/********************/ + +static void +tstate_mimalloc_bind(PyThreadState *tstate) +{ +#ifdef Py_GIL_DISABLED + struct _mimalloc_thread_state *mts = &((_PyThreadStateImpl*)tstate)->mimalloc; + + // Initialize the mimalloc thread state. This must be called from the + // same thread that will use the thread state. The "mem" heap doubles as + // the "backing" heap. + mi_tld_t *tld = &mts->tld; + _mi_tld_init(tld, &mts->heaps[_Py_MIMALLOC_HEAP_MEM]); + + // Exiting threads push any remaining in-use segments to the abandoned + // pool to be re-claimed later by other threads. We use per-interpreter + // pools to keep Python objects from different interpreters separate. + tld->segments.abandoned = &tstate->interp->mimalloc.abandoned_pool; + + // Initialize each heap + for (uint8_t i = 0; i < _Py_MIMALLOC_HEAP_COUNT; i++) { + _mi_heap_init_ex(&mts->heaps[i], tld, _mi_arena_id_none(), false, i); + } + + // By default, object allocations use _Py_MIMALLOC_HEAP_OBJECT. + // _PyObject_GC_New() and similar functions temporarily override this to + // use one of the GC heaps. + mts->current_object_heap = &mts->heaps[_Py_MIMALLOC_HEAP_OBJECT]; +#endif } + +void +_PyThreadState_ClearMimallocHeaps(PyThreadState *tstate) +{ +#ifdef Py_GIL_DISABLED + if (!tstate->_status.bound) { + // The mimalloc heaps are only initialized when the thread is bound. + return; + } + + _PyThreadStateImpl *tstate_impl = (_PyThreadStateImpl *)tstate; + for (Py_ssize_t i = 0; i < _Py_MIMALLOC_HEAP_COUNT; i++) { + // Abandon all segments in use by this thread. This pushes them to + // a shared pool to later be reclaimed by other threads. It's important + // to do this before the thread state is destroyed so that objects + // remain visible to the GC. + _mi_heap_collect_abandon(&tstate_impl->mimalloc.heaps[i]); + } #endif +} diff --git a/Python/pystrcmp.c b/Python/pystrcmp.c index 9224ce4c706055..9796cb013ad450 100644 --- a/Python/pystrcmp.c +++ b/Python/pystrcmp.c @@ -11,11 +11,11 @@ PyOS_mystrnicmp(const char *s1, const char *s2, Py_ssize_t size) return 0; p1 = (const unsigned char *)s1; p2 = (const unsigned char *)s2; - for (; (--size > 0) && *p1 && *p2 && (tolower(*p1) == tolower(*p2)); + for (; (--size > 0) && *p1 && *p2 && (Py_TOLOWER(*p1) == Py_TOLOWER(*p2)); p1++, p2++) { ; } - return tolower(*p1) - tolower(*p2); + return Py_TOLOWER(*p1) - Py_TOLOWER(*p2); } int @@ -23,8 +23,8 @@ PyOS_mystricmp(const char *s1, const char *s2) { const unsigned char *p1 = (const unsigned char *)s1; const unsigned char *p2 = (const unsigned char *)s2; - for (; *p1 && *p2 && (tolower(*p1) == tolower(*p2)); p1++, p2++) { + for (; *p1 && *p2 && (Py_TOLOWER(*p1) == Py_TOLOWER(*p2)); p1++, p2++) { ; } - return (tolower(*p1) - tolower(*p2)); + return (Py_TOLOWER(*p1) - Py_TOLOWER(*p2)); } diff --git a/Python/pystrhex.c b/Python/pystrhex.c index ce456b79f1655f..38484f5a7d4227 100644 --- a/Python/pystrhex.c +++ b/Python/pystrhex.c @@ -3,7 +3,6 @@ #include "Python.h" #include "pycore_strhex.h" // _Py_strhex_with_sep() #include "pycore_unicodeobject.h" // _PyUnicode_CheckConsistency() -#include // abs() static PyObject *_Py_strhex_impl(const char* argbuf, const Py_ssize_t arglen, PyObject* sep, int bytes_per_sep_group, @@ -44,7 +43,7 @@ static PyObject *_Py_strhex_impl(const char* argbuf, const Py_ssize_t arglen, bytes_per_sep_group = 0; } - unsigned int abs_bytes_per_sep = abs(bytes_per_sep_group); + unsigned int abs_bytes_per_sep = Py_ABS(bytes_per_sep_group); Py_ssize_t resultlen = 0; if (bytes_per_sep_group && arglen > 0) { /* How many sep characters we'll be inserting. */ diff --git a/Python/pystrtod.c b/Python/pystrtod.c index 9bb060e3d11979..16bf06f0e6cca2 100644 --- a/Python/pystrtod.c +++ b/Python/pystrtod.c @@ -3,7 +3,8 @@ #include #include "pycore_dtoa.h" // _Py_dg_strtod() #include "pycore_pymath.h" // _PY_SHORT_FLOAT_REPR -#include + +#include // localeconv() /* Case-insensitive string match used for nan and inf detection; t should be lower-case. Returns 1 for a successful match, 0 otherwise. */ diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 721c527745c44a..5f305aa00e08b9 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -12,17 +12,18 @@ #include "Python.h" -#include "pycore_ast.h" // PyAST_mod2obj -#include "pycore_ceval.h" // _Py_EnterRecursiveCall +#include "pycore_ast.h" // PyAST_mod2obj() +#include "pycore_ceval.h" // _Py_EnterRecursiveCall() #include "pycore_compile.h" // _PyAST_Compile() #include "pycore_interp.h" // PyInterpreterState.importlib #include "pycore_object.h" // _PyDebug_PrintTotalRefs() #include "pycore_parser.h" // _PyParser_ASTFromString() -#include "pycore_pyerrors.h" // _PyErr_GetRaisedException, _Py_Offer_Suggestions -#include "pycore_pylifecycle.h" // _Py_UnhandledKeyboardInterrupt +#include "pycore_pyerrors.h" // _PyErr_GetRaisedException() +#include "pycore_pylifecycle.h" // _Py_FdIsInteractive() #include "pycore_pystate.h" // _PyInterpreterState_GET() +#include "pycore_pythonrun.h" // export _PyRun_InteractiveLoopObject() #include "pycore_sysmodule.h" // _PySys_Audit() -#include "pycore_traceback.h" // _PyTraceBack_Print_Indented() +#include "pycore_traceback.h" // _PyTraceBack_Print() #include "errcode.h" // E_EOF #include "marshal.h" // PyMarshal_ReadLongFromFile() @@ -36,22 +37,20 @@ # include "windows.h" #endif - -#ifdef __cplusplus -extern "C" { -#endif - /* Forward */ static void flush_io(void); static PyObject *run_mod(mod_ty, PyObject *, PyObject *, PyObject *, - PyCompilerFlags *, PyArena *); + PyCompilerFlags *, PyArena *, PyObject*, int); static PyObject *run_pyc_file(FILE *, PyObject *, PyObject *, PyCompilerFlags *); static int PyRun_InteractiveOneObjectEx(FILE *, PyObject *, PyCompilerFlags *); static PyObject* pyrun_file(FILE *fp, PyObject *filename, int start, PyObject *globals, PyObject *locals, int closeit, PyCompilerFlags *flags); - +static PyObject * +_PyRun_StringFlagsWithName(const char *str, PyObject* name, int start, + PyObject *globals, PyObject *locals, PyCompilerFlags *flags, + int generate_new_source); int _PyRun_AnyFileObject(FILE *fp, PyObject *filename, int closeit, @@ -182,7 +181,8 @@ PyRun_InteractiveLoopFlags(FILE *fp, const char *filename, PyCompilerFlags *flag // Call _PyParser_ASTFromFile() with sys.stdin.encoding, sys.ps1 and sys.ps2 static int pyrun_one_parse_ast(FILE *fp, PyObject *filename, - PyCompilerFlags *flags, PyArena *arena, mod_ty *pmod) + PyCompilerFlags *flags, PyArena *arena, + mod_ty *pmod, PyObject** interactive_src) { PyThreadState *tstate = _PyThreadState_GET(); @@ -240,9 +240,9 @@ pyrun_one_parse_ast(FILE *fp, PyObject *filename, } int errcode = 0; - *pmod = _PyParser_ASTFromFile(fp, filename, encoding, - Py_single_input, ps1, ps2, - flags, &errcode, arena); + *pmod = _PyParser_InteractiveASTFromFile(fp, filename, encoding, + Py_single_input, ps1, ps2, + flags, &errcode, interactive_src, arena); Py_XDECREF(ps1_obj); Py_XDECREF(ps2_obj); Py_XDECREF(encoding_obj); @@ -270,7 +270,8 @@ PyRun_InteractiveOneObjectEx(FILE *fp, PyObject *filename, } mod_ty mod; - int parse_res = pyrun_one_parse_ast(fp, filename, flags, arena, &mod); + PyObject *interactive_src; + int parse_res = pyrun_one_parse_ast(fp, filename, flags, arena, &mod, &interactive_src); if (parse_res != 0) { _PyArena_Free(arena); return parse_res; @@ -283,7 +284,7 @@ PyRun_InteractiveOneObjectEx(FILE *fp, PyObject *filename, } PyObject *main_dict = PyModule_GetDict(main_module); // borrowed ref - PyObject *res = run_mod(mod, filename, main_dict, main_dict, flags, arena); + PyObject *res = run_mod(mod, filename, main_dict, main_dict, flags, arena, interactive_src, 1); _PyArena_Free(arena); Py_DECREF(main_module); if (res == NULL) { @@ -412,10 +413,11 @@ _PyRun_SimpleFileObject(FILE *fp, PyObject *filename, int closeit, PyObject *dict = PyModule_GetDict(main_module); // borrowed ref int set_file_name = 0; - if (_PyDict_GetItemStringWithError(dict, "__file__") == NULL) { - if (PyErr_Occurred()) { - goto done; - } + int has_file = PyDict_ContainsString(dict, "__file__"); + if (has_file < 0) { + goto done; + } + if (!has_file) { if (PyDict_SetItemString(dict, "__file__", filename) < 0) { goto done; } @@ -500,16 +502,25 @@ PyRun_SimpleFileExFlags(FILE *fp, const char *filename, int closeit, int -PyRun_SimpleStringFlags(const char *command, PyCompilerFlags *flags) -{ +_PyRun_SimpleStringFlagsWithName(const char *command, const char* name, PyCompilerFlags *flags) { PyObject *main_module = PyImport_AddModuleRef("__main__"); if (main_module == NULL) { return -1; } PyObject *dict = PyModule_GetDict(main_module); // borrowed ref - PyObject *res = PyRun_StringFlags(command, Py_file_input, - dict, dict, flags); + PyObject *res = NULL; + if (name == NULL) { + res = PyRun_StringFlags(command, Py_file_input, dict, dict, flags); + } else { + PyObject* the_name = PyUnicode_FromString(name); + if (!the_name) { + PyErr_Print(); + return -1; + } + res = _PyRun_StringFlagsWithName(command, the_name, Py_file_input, dict, dict, flags, 0); + Py_DECREF(the_name); + } Py_DECREF(main_module); if (res == NULL) { PyErr_Print(); @@ -520,204 +531,12 @@ PyRun_SimpleStringFlags(const char *command, PyCompilerFlags *flags) return 0; } -static int -parse_syntax_error(PyObject *err, PyObject **message, PyObject **filename, - Py_ssize_t *lineno, Py_ssize_t *offset, - Py_ssize_t* end_lineno, Py_ssize_t* end_offset, - PyObject **text) +int +PyRun_SimpleStringFlags(const char *command, PyCompilerFlags *flags) { - Py_ssize_t hold; - PyObject *v; - - *message = NULL; - *filename = NULL; - - /* new style errors. `err' is an instance */ - *message = PyObject_GetAttr(err, &_Py_ID(msg)); - if (!*message) - goto finally; - - v = PyObject_GetAttr(err, &_Py_ID(filename)); - if (!v) - goto finally; - if (v == Py_None) { - Py_DECREF(v); - _Py_DECLARE_STR(anon_string, ""); - *filename = Py_NewRef(&_Py_STR(anon_string)); - } - else { - *filename = v; - } - - v = PyObject_GetAttr(err, &_Py_ID(lineno)); - if (!v) - goto finally; - hold = PyLong_AsSsize_t(v); - Py_DECREF(v); - if (hold < 0 && PyErr_Occurred()) - goto finally; - *lineno = hold; - - v = PyObject_GetAttr(err, &_Py_ID(offset)); - if (!v) - goto finally; - if (v == Py_None) { - *offset = -1; - Py_DECREF(v); - } else { - hold = PyLong_AsSsize_t(v); - Py_DECREF(v); - if (hold < 0 && PyErr_Occurred()) - goto finally; - *offset = hold; - } - - if (Py_TYPE(err) == (PyTypeObject*)PyExc_SyntaxError) { - v = PyObject_GetAttr(err, &_Py_ID(end_lineno)); - if (!v) { - PyErr_Clear(); - *end_lineno = *lineno; - } - else if (v == Py_None) { - *end_lineno = *lineno; - Py_DECREF(v); - } else { - hold = PyLong_AsSsize_t(v); - Py_DECREF(v); - if (hold < 0 && PyErr_Occurred()) - goto finally; - *end_lineno = hold; - } - - v = PyObject_GetAttr(err, &_Py_ID(end_offset)); - if (!v) { - PyErr_Clear(); - *end_offset = -1; - } - else if (v == Py_None) { - *end_offset = -1; - Py_DECREF(v); - } else { - hold = PyLong_AsSsize_t(v); - Py_DECREF(v); - if (hold < 0 && PyErr_Occurred()) - goto finally; - *end_offset = hold; - } - } else { - // SyntaxError subclasses - *end_lineno = *lineno; - *end_offset = -1; - } - - v = PyObject_GetAttr(err, &_Py_ID(text)); - if (!v) - goto finally; - if (v == Py_None) { - Py_DECREF(v); - *text = NULL; - } - else { - *text = v; - } - return 1; - -finally: - Py_XDECREF(*message); - Py_XDECREF(*filename); - return 0; + return _PyRun_SimpleStringFlagsWithName(command, NULL, flags); } -static int -print_error_text(PyObject *f, Py_ssize_t offset, Py_ssize_t end_offset, - PyObject *text_obj) -{ - size_t caret_repetitions = (end_offset > 0 && end_offset > offset) ? - end_offset - offset : 1; - - /* Convert text to a char pointer; return if error */ - const char *text = PyUnicode_AsUTF8(text_obj); - if (text == NULL) { - return -1; - } - - /* Convert offset from 1-based to 0-based */ - offset--; - - /* Strip leading whitespace from text, adjusting offset as we go */ - while (*text == ' ' || *text == '\t' || *text == '\f') { - text++; - offset--; - } - - /* Calculate text length excluding trailing newline */ - Py_ssize_t len = strlen(text); - if (len > 0 && text[len-1] == '\n') { - len--; - } - - /* Clip offset to at most len */ - if (offset > len) { - offset = len; - } - - /* Skip past newlines embedded in text */ - for (;;) { - const char *nl = strchr(text, '\n'); - if (nl == NULL) { - break; - } - Py_ssize_t inl = nl - text; - if (inl >= offset) { - break; - } - inl += 1; - text += inl; - len -= inl; - offset -= (int)inl; - } - - /* Print text */ - if (PyFile_WriteString(" ", f) < 0) { - return -1; - } - if (PyFile_WriteString(text, f) < 0) { - return -1; - } - - /* Make sure there's a newline at the end */ - if (text[len] != '\n') { - if (PyFile_WriteString("\n", f) < 0) { - return -1; - } - } - - /* Don't print caret if it points to the left of the text */ - if (offset < 0) { - return 0; - } - - /* Write caret line */ - if (PyFile_WriteString(" ", f) < 0) { - return -1; - } - while (--offset >= 0) { - if (PyFile_WriteString(" ", f) < 0) { - return -1; - } - } - for (size_t caret_iter=0; caret_iter < caret_repetitions ; caret_iter++) { - if (PyFile_WriteString("^", f) < 0) { - return -1; - } - } - if (PyFile_WriteString("\n", f) < 0) { - return -1; - } - return 0; -} - - int _Py_HandleSystemExit(int *exitcode_p) { @@ -831,7 +650,7 @@ _PyErr_PrintEx(PyThreadState *tstate, int set_sys_last_vars) PyErr_Clear(); goto done; } - _PyErr_WriteUnraisableMsg("in audit hook", NULL); + PyErr_FormatUnraisable("Exception ignored in audit hook"); } if (hook) { PyObject* args[3] = {typ, exc, tb}; @@ -886,29 +705,13 @@ struct exception_print_context { PyObject *file; PyObject *seen; // Prevent cycles in recursion - int exception_group_depth; // nesting level of current exception group - bool need_close; // Need a closing bottom frame - int max_group_width; // Maximum number of children of each EG - int max_group_depth; // Maximum nesting level of EGs }; -#define EXC_MARGIN(ctx) ((ctx)->exception_group_depth ? "| " : "") -#define EXC_INDENT(ctx) (2 * (ctx)->exception_group_depth) - -static int -write_indented_margin(struct exception_print_context *ctx, PyObject *f) -{ - return _Py_WriteIndentedMargin(EXC_INDENT(ctx), EXC_MARGIN(ctx), f); -} - static int print_exception_invalid_type(struct exception_print_context *ctx, PyObject *value) { PyObject *f = ctx->file; - if (_Py_WriteIndent(EXC_INDENT(ctx), f) < 0) { - return -1; - } const char *const msg = "TypeError: print_exception(): Exception expected " "for value, "; if (PyFile_WriteString(msg, f) < 0) { @@ -932,15 +735,7 @@ print_exception_traceback(struct exception_print_context *ctx, PyObject *value) PyObject *tb = PyException_GetTraceback(value); if (tb && tb != Py_None) { const char *header = EXCEPTION_TB_HEADER; - const char *header_margin = EXC_MARGIN(ctx); - if (_PyBaseExceptionGroup_Check(value)) { - header = EXCEPTION_GROUP_TB_HEADER; - if (ctx->exception_group_depth == 1) { - header_margin = "+ "; - } - } - err = _PyTraceBack_Print_Indented( - tb, EXC_INDENT(ctx), EXC_MARGIN(ctx), header_margin, header, f); + err = _PyTraceBack_Print(tb, header, f); } Py_XDECREF(tb); return err; @@ -962,16 +757,20 @@ print_exception_file_and_line(struct exception_print_context *ctx, } Py_DECREF(tmp); - PyObject *message, *filename, *text; - Py_ssize_t lineno, offset, end_lineno, end_offset; - if (!parse_syntax_error(*value_p, &message, &filename, - &lineno, &offset, - &end_lineno, &end_offset, &text)) { - PyErr_Clear(); - return 0; + PyObject *filename = NULL; + Py_ssize_t lineno = 0; + PyObject* v = PyObject_GetAttr(*value_p, &_Py_ID(filename)); + if (!v) { + return -1; + } + if (v == Py_None) { + Py_DECREF(v); + _Py_DECLARE_STR(anon_string, ""); + filename = Py_NewRef(&_Py_STR(anon_string)); + } + else { + filename = v; } - - Py_SETREF(*value_p, message); PyObject *line = PyUnicode_FromFormat(" File \"%S\", line %zd\n", filename, lineno); @@ -979,40 +778,16 @@ print_exception_file_and_line(struct exception_print_context *ctx, if (line == NULL) { goto error; } - if (write_indented_margin(ctx, f) < 0) { - goto error; - } if (PyFile_WriteObject(line, f, Py_PRINT_RAW) < 0) { goto error; } Py_CLEAR(line); - if (text != NULL) { - Py_ssize_t line_size; - const char *error_line = PyUnicode_AsUTF8AndSize(text, &line_size); - // If the location of the error spawn multiple lines, we want - // to just print the first one and highlight everything until - // the end of that one since we don't support multi-line error - // messages. - if (end_lineno > lineno) { - end_offset = (error_line != NULL) ? line_size : -1; - } - // Limit the amount of '^' that we can display to - // the size of the text in the source line. - if (error_line != NULL && end_offset > line_size + 1) { - end_offset = line_size + 1; - } - if (print_error_text(f, offset, end_offset, text) < 0) { - goto error; - } - Py_DECREF(text); - } assert(!PyErr_Occurred()); return 0; error: Py_XDECREF(line); - Py_XDECREF(text); return -1; } @@ -1023,11 +798,14 @@ print_exception_message(struct exception_print_context *ctx, PyObject *type, { PyObject *f = ctx->file; - assert(PyExceptionClass_Check(type)); - - if (write_indented_margin(ctx, f) < 0) { + if (PyErr_GivenExceptionMatches(value, PyExc_MemoryError)) { + // The Python APIs in this function require allocating memory + // for various objects. If we're out of memory, we can't do that, return -1; } + + assert(PyExceptionClass_Check(type)); + PyObject *modulename = PyObject_GetAttr(type, &_Py_ID(__module__)); if (modulename == NULL || !PyUnicode_Check(modulename)) { Py_XDECREF(modulename); @@ -1101,108 +879,6 @@ print_exception_message(struct exception_print_context *ctx, PyObject *type, return 0; } -static int -print_exception_suggestions(struct exception_print_context *ctx, - PyObject *value) -{ - PyObject *f = ctx->file; - PyObject *suggestions = _Py_Offer_Suggestions(value); - if (suggestions) { - if (PyFile_WriteObject(suggestions, f, Py_PRINT_RAW) < 0) { - goto error; - } - Py_DECREF(suggestions); - } - else if (PyErr_Occurred()) { - PyErr_Clear(); - } - return 0; -error: - Py_XDECREF(suggestions); - return -1; -} - -static int -print_exception_notes(struct exception_print_context *ctx, PyObject *value) -{ - PyObject *f = ctx->file; - - if (!PyExceptionInstance_Check(value)) { - return 0; - } - - PyObject *notes; - int res = PyObject_GetOptionalAttr(value, &_Py_ID(__notes__), ¬es); - if (res <= 0) { - return res; - } - if (!PySequence_Check(notes) || PyUnicode_Check(notes) || PyBytes_Check(notes)) { - res = 0; - if (write_indented_margin(ctx, f) < 0) { - res = -1; - } - PyObject *s = PyObject_Repr(notes); - if (s == NULL) { - PyErr_Clear(); - res = PyFile_WriteString("<__notes__ repr() failed>", f); - } - else { - res = PyFile_WriteObject(s, f, Py_PRINT_RAW); - Py_DECREF(s); - } - Py_DECREF(notes); - if (PyFile_WriteString("\n", f) < 0) { - res = -1; - } - return res; - } - Py_ssize_t num_notes = PySequence_Length(notes); - PyObject *lines = NULL; - for (Py_ssize_t ni = 0; ni < num_notes; ni++) { - PyObject *note = PySequence_GetItem(notes, ni); - PyObject *note_str = PyObject_Str(note); - Py_DECREF(note); - - if (note_str == NULL) { - PyErr_Clear(); - if (PyFile_WriteString("", f) < 0) { - goto error; - } - } - else { - lines = PyUnicode_Splitlines(note_str, 1); - Py_DECREF(note_str); - - if (lines == NULL) { - goto error; - } - - Py_ssize_t n = PyList_GET_SIZE(lines); - for (Py_ssize_t i = 0; i < n; i++) { - PyObject *line = PyList_GET_ITEM(lines, i); - assert(PyUnicode_Check(line)); - if (write_indented_margin(ctx, f) < 0) { - goto error; - } - if (PyFile_WriteObject(line, f, Py_PRINT_RAW) < 0) { - goto error; - } - } - Py_CLEAR(lines); - } - if (PyFile_WriteString("\n", f) < 0) { - goto error; - } - } - - Py_DECREF(notes); - return 0; -error: - Py_XDECREF(lines); - Py_DECREF(notes); - return -1; -} - static int print_exception(struct exception_print_context *ctx, PyObject *value) { @@ -1219,7 +895,7 @@ print_exception(struct exception_print_context *ctx, PyObject *value) goto error; } - /* grab the type now because value can change below */ + /* grab the type and notes now because value can change below */ PyObject *type = (PyObject *) Py_TYPE(value); if (print_exception_file_and_line(ctx, &value) < 0) { @@ -1228,16 +904,9 @@ print_exception(struct exception_print_context *ctx, PyObject *value) if (print_exception_message(ctx, type, value) < 0) { goto error; } - if (print_exception_suggestions(ctx, value) < 0) { - goto error; - } if (PyFile_WriteString("\n", f) < 0) { goto error; } - if (print_exception_notes(ctx, value) < 0) { - goto error; - } - Py_DECREF(value); assert(!PyErr_Occurred()); return 0; @@ -1265,29 +934,18 @@ print_chained(struct exception_print_context* ctx, PyObject *value, if (_Py_EnterRecursiveCall(" in print_chained")) { return -1; } - bool need_close = ctx->need_close; int res = print_exception_recursive(ctx, value); - ctx->need_close = need_close; _Py_LeaveRecursiveCall(); if (res < 0) { return -1; } - if (write_indented_margin(ctx, f) < 0) { - return -1; - } if (PyFile_WriteString("\n", f) < 0) { return -1; } - if (write_indented_margin(ctx, f) < 0) { - return -1; - } if (PyFile_WriteString(message, f) < 0) { return -1; } - if (write_indented_margin(ctx, f) < 0) { - return -1; - } if (PyFile_WriteString("\n", f) < 0) { return -1; } @@ -1364,133 +1022,6 @@ print_exception_cause_and_context(struct exception_print_context *ctx, return 0; } -static int -print_exception_group(struct exception_print_context *ctx, PyObject *value) -{ - PyObject *f = ctx->file; - - if (ctx->exception_group_depth > ctx->max_group_depth) { - /* depth exceeds limit */ - - if (write_indented_margin(ctx, f) < 0) { - return -1; - } - - PyObject *line = PyUnicode_FromFormat("... (max_group_depth is %d)\n", - ctx->max_group_depth); - if (line == NULL) { - return -1; - } - int err = PyFile_WriteObject(line, f, Py_PRINT_RAW); - Py_DECREF(line); - return err; - } - - if (ctx->exception_group_depth == 0) { - ctx->exception_group_depth += 1; - } - if (print_exception(ctx, value) < 0) { - return -1; - } - - PyObject *excs = ((PyBaseExceptionGroupObject *)value)->excs; - assert(excs && PyTuple_Check(excs)); - Py_ssize_t num_excs = PyTuple_GET_SIZE(excs); - assert(num_excs > 0); - Py_ssize_t n; - if (num_excs <= ctx->max_group_width) { - n = num_excs; - } - else { - n = ctx->max_group_width + 1; - } - - ctx->need_close = false; - for (Py_ssize_t i = 0; i < n; i++) { - bool last_exc = (i == n - 1); - if (last_exc) { - // The closing frame may be added in a recursive call - ctx->need_close = true; - } - - if (_Py_WriteIndent(EXC_INDENT(ctx), f) < 0) { - return -1; - } - bool truncated = (i >= ctx->max_group_width); - PyObject *line; - if (!truncated) { - line = PyUnicode_FromFormat( - "%s+---------------- %zd ----------------\n", - (i == 0) ? "+-" : " ", i + 1); - } - else { - line = PyUnicode_FromFormat( - "%s+---------------- ... ----------------\n", - (i == 0) ? "+-" : " "); - } - if (line == NULL) { - return -1; - } - int err = PyFile_WriteObject(line, f, Py_PRINT_RAW); - Py_DECREF(line); - if (err < 0) { - return -1; - } - - ctx->exception_group_depth += 1; - PyObject *exc = PyTuple_GET_ITEM(excs, i); - - if (!truncated) { - if (_Py_EnterRecursiveCall(" in print_exception_group")) { - return -1; - } - int res = print_exception_recursive(ctx, exc); - _Py_LeaveRecursiveCall(); - if (res < 0) { - return -1; - } - } - else { - Py_ssize_t excs_remaining = num_excs - ctx->max_group_width; - - if (write_indented_margin(ctx, f) < 0) { - return -1; - } - - PyObject *line = PyUnicode_FromFormat( - "and %zd more exception%s\n", - excs_remaining, excs_remaining > 1 ? "s" : ""); - - if (line == NULL) { - return -1; - } - - int err = PyFile_WriteObject(line, f, Py_PRINT_RAW); - Py_DECREF(line); - if (err < 0) { - return -1; - } - } - - if (last_exc && ctx->need_close) { - if (_Py_WriteIndent(EXC_INDENT(ctx), f) < 0) { - return -1; - } - if (PyFile_WriteString( - "+------------------------------------\n", f) < 0) { - return -1; - } - ctx->need_close = false; - } - ctx->exception_group_depth -= 1; - } - - if (ctx->exception_group_depth == 1) { - ctx->exception_group_depth -= 1; - } - return 0; -} - static int print_exception_recursive(struct exception_print_context *ctx, PyObject *value) { @@ -1503,12 +1034,7 @@ print_exception_recursive(struct exception_print_context *ctx, PyObject *value) goto error; } } - if (!_PyBaseExceptionGroup_Check(value)) { - if (print_exception(ctx, value) < 0) { - goto error; - } - } - else if (print_exception_group(ctx, value) < 0) { + if (print_exception(ctx, value) < 0) { goto error; } assert(!PyErr_Occurred()); @@ -1520,12 +1046,10 @@ print_exception_recursive(struct exception_print_context *ctx, PyObject *value) return -1; } -#define PyErr_MAX_GROUP_WIDTH 15 -#define PyErr_MAX_GROUP_DEPTH 10 - void _PyErr_Display(PyObject *file, PyObject *unused, PyObject *value, PyObject *tb) { + assert(value != NULL); assert(file != NULL && file != Py_None); if (PyExceptionInstance_Check(value) && tb != NULL && PyTraceBack_Check(tb)) { @@ -1540,12 +1064,42 @@ _PyErr_Display(PyObject *file, PyObject *unused, PyObject *value, PyObject *tb) } } + int unhandled_keyboard_interrupt = _PyRuntime.signals.unhandled_keyboard_interrupt; + + // Try first with the stdlib traceback module + PyObject *traceback_module = PyImport_ImportModule("traceback"); + + if (traceback_module == NULL) { + goto fallback; + } + + PyObject *print_exception_fn = PyObject_GetAttrString(traceback_module, "_print_exception_bltin"); + + if (print_exception_fn == NULL || !PyCallable_Check(print_exception_fn)) { + Py_DECREF(traceback_module); + goto fallback; + } + + PyObject* result = PyObject_CallOneArg(print_exception_fn, value); + + Py_DECREF(traceback_module); + Py_XDECREF(print_exception_fn); + if (result) { + Py_DECREF(result); + _PyRuntime.signals.unhandled_keyboard_interrupt = unhandled_keyboard_interrupt; + return; + } +fallback: + _PyRuntime.signals.unhandled_keyboard_interrupt = unhandled_keyboard_interrupt; +#ifdef Py_DEBUG + if (PyErr_Occurred()) { + PyErr_FormatUnraisable( + "Exception ignored in the internal traceback machinery"); + } +#endif + PyErr_Clear(); struct exception_print_context ctx; ctx.file = file; - ctx.exception_group_depth = 0; - ctx.need_close = false; - ctx.max_group_width = PyErr_MAX_GROUP_WIDTH; - ctx.max_group_depth = PyErr_MAX_GROUP_DEPTH; /* We choose to ignore seen being possibly NULL, and report at least the main exception (it could be a MemoryError). @@ -1562,14 +1116,10 @@ _PyErr_Display(PyObject *file, PyObject *unused, PyObject *value, PyObject *tb) Py_XDECREF(ctx.seen); /* Call file.flush() */ - PyObject *res = PyObject_CallMethodNoArgs(file, &_Py_ID(flush)); - if (!res) { + if (_PyFile_Flush(file) < 0) { /* Silently ignore file.flush() error */ PyErr_Clear(); } - else { - Py_DECREF(res); - } } void @@ -1600,9 +1150,10 @@ void PyErr_DisplayException(PyObject *exc) PyErr_Display(NULL, exc, NULL); } -PyObject * -PyRun_StringFlags(const char *str, int start, PyObject *globals, - PyObject *locals, PyCompilerFlags *flags) +static PyObject * +_PyRun_StringFlagsWithName(const char *str, PyObject* name, int start, + PyObject *globals, PyObject *locals, PyCompilerFlags *flags, + int generate_new_source) { PyObject *ret = NULL; mod_ty mod; @@ -1612,17 +1163,36 @@ PyRun_StringFlags(const char *str, int start, PyObject *globals, if (arena == NULL) return NULL; + PyObject* source = NULL; _Py_DECLARE_STR(anon_string, ""); - mod = _PyParser_ASTFromString( - str, &_Py_STR(anon_string), start, flags, arena); - if (mod != NULL) - ret = run_mod(mod, &_Py_STR(anon_string), globals, locals, flags, arena); + if (name) { + source = PyUnicode_FromString(str); + if (!source) { + PyErr_Clear(); + } + } else { + name = &_Py_STR(anon_string); + } + + mod = _PyParser_ASTFromString(str, name, start, flags, arena); + + if (mod != NULL) { + ret = run_mod(mod, name, globals, locals, flags, arena, source, generate_new_source); + } + Py_XDECREF(source); _PyArena_Free(arena); return ret; } +PyObject * +PyRun_StringFlags(const char *str, int start, PyObject *globals, + PyObject *locals, PyCompilerFlags *flags) { + + return _PyRun_StringFlagsWithName(str, NULL, start, globals, locals, flags, 0); +} + static PyObject * pyrun_file(FILE *fp, PyObject *filename, int start, PyObject *globals, PyObject *locals, int closeit, PyCompilerFlags *flags) @@ -1642,7 +1212,7 @@ pyrun_file(FILE *fp, PyObject *filename, int start, PyObject *globals, PyObject *ret; if (mod != NULL) { - ret = run_mod(mod, filename, globals, locals, flags, arena); + ret = run_mod(mod, filename, globals, locals, flags, arena, NULL, 0); } else { ret = NULL; @@ -1674,11 +1244,7 @@ flush_io_stream(PyThreadState *tstate, PyObject *name) { PyObject *f = _PySys_GetAttr(tstate, name); if (f != NULL) { - PyObject *r = PyObject_CallMethodNoArgs(f, &_Py_ID(flush)); - if (r) { - Py_DECREF(r); - } - else { + if (_PyFile_Flush(f) < 0) { PyErr_Clear(); } } @@ -1712,13 +1278,17 @@ run_eval_code_obj(PyThreadState *tstate, PyCodeObject *co, PyObject *globals, Py _PyRuntime.signals.unhandled_keyboard_interrupt = 0; /* Set globals['__builtins__'] if it doesn't exist */ - if (globals != NULL && _PyDict_GetItemStringWithError(globals, "__builtins__") == NULL) { - if (PyErr_Occurred() || - PyDict_SetItemString(globals, "__builtins__", - tstate->interp->builtins) < 0) - { + if (globals != NULL) { + int has_builtins = PyDict_ContainsString(globals, "__builtins__"); + if (has_builtins < 0) { return NULL; } + if (!has_builtins) { + if (PyDict_SetItemString(globals, "__builtins__", + tstate->interp->builtins) < 0) { + return NULL; + } + } } v = PyEval_EvalCode((PyObject*)co, globals, locals); @@ -1730,12 +1300,76 @@ run_eval_code_obj(PyThreadState *tstate, PyCodeObject *co, PyObject *globals, Py static PyObject * run_mod(mod_ty mod, PyObject *filename, PyObject *globals, PyObject *locals, - PyCompilerFlags *flags, PyArena *arena) + PyCompilerFlags *flags, PyArena *arena, PyObject* interactive_src, + int generate_new_source) { PyThreadState *tstate = _PyThreadState_GET(); - PyCodeObject *co = _PyAST_Compile(mod, filename, flags, -1, arena); - if (co == NULL) + PyObject* interactive_filename = filename; + if (interactive_src) { + PyInterpreterState *interp = tstate->interp; + if (generate_new_source) { + interactive_filename = PyUnicode_FromFormat( + "%U-%d", filename, interp->_interactive_src_count++); + } else { + Py_INCREF(interactive_filename); + } + if (interactive_filename == NULL) { + return NULL; + } + } + + PyCodeObject *co = _PyAST_Compile(mod, interactive_filename, flags, -1, arena); + if (co == NULL) { + if (interactive_src) { + Py_DECREF(interactive_filename); + } return NULL; + } + + if (interactive_src) { + PyObject *linecache_module = PyImport_ImportModule("linecache"); + + if (linecache_module == NULL) { + Py_DECREF(co); + Py_DECREF(interactive_filename); + return NULL; + } + + PyObject *print_tb_func = PyObject_GetAttrString(linecache_module, "_register_code"); + + if (print_tb_func == NULL) { + Py_DECREF(co); + Py_DECREF(interactive_filename); + Py_DECREF(linecache_module); + return NULL; + } + + if (!PyCallable_Check(print_tb_func)) { + Py_DECREF(co); + Py_DECREF(interactive_filename); + Py_DECREF(linecache_module); + Py_DECREF(print_tb_func); + PyErr_SetString(PyExc_ValueError, "linecache._register_code is not callable"); + return NULL; + } + + PyObject* result = PyObject_CallFunction( + print_tb_func, "OOO", + interactive_filename, + interactive_src, + filename + ); + + Py_DECREF(interactive_filename); + + Py_DECREF(linecache_module); + Py_XDECREF(print_tb_func); + Py_XDECREF(result); + if (!result) { + Py_DECREF(co); + return NULL; + } + } if (_PySys_Audit(tstate, "exec", "O", co) < 0) { Py_DECREF(co); @@ -1806,6 +1440,11 @@ Py_CompileStringObject(const char *str, PyObject *filename, int start, return NULL; } if (flags && (flags->cf_flags & PyCF_ONLY_AST)) { + if ((flags->cf_flags & PyCF_OPTIMIZED_AST) == PyCF_OPTIMIZED_AST) { + if (_PyCompile_AstOptimize(mod, filename, flags, optimize, arena) < 0) { + return NULL; + } + } PyObject *result = PyAST_mod2obj(mod); _PyArena_Free(arena); return result; @@ -2016,7 +1655,3 @@ PyRun_InteractiveLoop(FILE *f, const char *p) { return PyRun_InteractiveLoopFlags(f, p, NULL); } - -#ifdef __cplusplus -} -#endif diff --git a/Python/pytime.c b/Python/pytime.c index 49cd5f4e8ea617..77cb95f8feb179 100644 --- a/Python/pytime.c +++ b/Python/pytime.c @@ -1,5 +1,10 @@ #include "Python.h" #include "pycore_time.h" // _PyTime_t + +#include // gmtime_r() +#ifdef HAVE_SYS_TIME_H +# include // gettimeofday() +#endif #ifdef MS_WINDOWS # include // struct timeval #endif @@ -50,6 +55,43 @@ #endif +static _PyTime_t +_PyTime_GCD(_PyTime_t x, _PyTime_t y) +{ + // Euclidean algorithm + assert(x >= 1); + assert(y >= 1); + while (y != 0) { + _PyTime_t tmp = y; + y = x % y; + x = tmp; + } + assert(x >= 1); + return x; +} + + +int +_PyTimeFraction_Set(_PyTimeFraction *frac, _PyTime_t numer, _PyTime_t denom) +{ + if (numer < 1 || denom < 1) { + return -1; + } + + _PyTime_t gcd = _PyTime_GCD(numer, denom); + frac->numer = numer / gcd; + frac->denom = denom / gcd; + return 0; +} + + +double +_PyTimeFraction_Resolution(const _PyTimeFraction *frac) +{ + return (double)frac->numer / (double)frac->denom / 1e9; +} + + static void pytime_time_t_overflow(void) { @@ -147,11 +189,17 @@ _PyTime_Mul(_PyTime_t t, _PyTime_t k) } - - _PyTime_t -_PyTime_MulDiv(_PyTime_t ticks, _PyTime_t mul, _PyTime_t div) +_PyTimeFraction_Mul(_PyTime_t ticks, const _PyTimeFraction *frac) { + const _PyTime_t mul = frac->numer; + const _PyTime_t div = frac->denom; + + if (div == 1) { + // Fast-path taken by mach_absolute_time() with 1/1 time base. + return _PyTime_Mul(ticks, mul); + } + /* Compute (ticks * mul / div) in two parts to reduce the risk of integer overflow: compute the integer part, and then the remaining part. @@ -465,7 +513,7 @@ _PyTime_FromNanosecondsObject(_PyTime_t *tp, PyObject *obj) #ifdef HAVE_CLOCK_GETTIME static int -pytime_fromtimespec(_PyTime_t *tp, struct timespec *ts, int raise_exc) +pytime_fromtimespec(_PyTime_t *tp, const struct timespec *ts, int raise_exc) { _PyTime_t t, tv_nsec; @@ -488,7 +536,7 @@ pytime_fromtimespec(_PyTime_t *tp, struct timespec *ts, int raise_exc) } int -_PyTime_FromTimespec(_PyTime_t *tp, struct timespec *ts) +_PyTime_FromTimespec(_PyTime_t *tp, const struct timespec *ts) { return pytime_fromtimespec(tp, ts, 1); } @@ -630,6 +678,16 @@ _PyTime_AsNanosecondsObject(_PyTime_t t) return PyLong_FromLongLong((long long)ns); } +_PyTime_t +_PyTime_FromSecondsDouble(double seconds, _PyTime_round_t round) +{ + _PyTime_t tp; + if(pytime_from_double(&tp, seconds, round, SEC_TO_NS) < 0) { + return -1; + } + return tp; +} + static _PyTime_t pytime_divide_round_up(const _PyTime_t t, const _PyTime_t k) @@ -1001,51 +1059,34 @@ _PyTime_GetSystemClockWithInfo(_PyTime_t *t, _Py_clock_info_t *info) #ifdef __APPLE__ static int -py_mach_timebase_info(_PyTime_t *pnumer, _PyTime_t *pdenom, int raise) +py_mach_timebase_info(_PyTimeFraction *base, int raise) { - static mach_timebase_info_data_t timebase; - /* According to the Technical Q&A QA1398, mach_timebase_info() cannot - fail: https://developer.apple.com/library/mac/#qa/qa1398/ */ + mach_timebase_info_data_t timebase; + // According to the Technical Q&A QA1398, mach_timebase_info() cannot + // fail: https://developer.apple.com/library/mac/#qa/qa1398/ (void)mach_timebase_info(&timebase); - /* Sanity check: should never occur in practice */ - if (timebase.numer < 1 || timebase.denom < 1) { + // Check that timebase.numer and timebase.denom can be casted to + // _PyTime_t. In practice, timebase uses uint32_t, so casting cannot + // overflow. At the end, only make sure that the type is uint32_t + // (_PyTime_t is 64-bit long). + Py_BUILD_ASSERT(sizeof(timebase.numer) <= sizeof(_PyTime_t)); + Py_BUILD_ASSERT(sizeof(timebase.denom) <= sizeof(_PyTime_t)); + _PyTime_t numer = (_PyTime_t)timebase.numer; + _PyTime_t denom = (_PyTime_t)timebase.denom; + + // Known time bases: + // + // * (1, 1) on Intel: 1 ns + // * (1000000000, 33333335) on PowerPC: ~30 ns + // * (1000000000, 25000000) on PowerPC: 40 ns + if (_PyTimeFraction_Set(base, numer, denom) < 0) { if (raise) { PyErr_SetString(PyExc_RuntimeError, "invalid mach_timebase_info"); } return -1; } - - /* Check that timebase.numer and timebase.denom can be casted to - _PyTime_t. In practice, timebase uses uint32_t, so casting cannot - overflow. At the end, only make sure that the type is uint32_t - (_PyTime_t is 64-bit long). */ - static_assert(sizeof(timebase.numer) <= sizeof(_PyTime_t), - "timebase.numer is larger than _PyTime_t"); - static_assert(sizeof(timebase.denom) <= sizeof(_PyTime_t), - "timebase.denom is larger than _PyTime_t"); - - /* Make sure that _PyTime_MulDiv(ticks, timebase_numer, timebase_denom) - cannot overflow. - - Known time bases: - - * (1, 1) on Intel - * (1000000000, 33333335) or (1000000000, 25000000) on PowerPC - - None of these time bases can overflow with 64-bit _PyTime_t, but - check for overflow, just in case. */ - if ((_PyTime_t)timebase.numer > _PyTime_MAX / (_PyTime_t)timebase.denom) { - if (raise) { - PyErr_SetString(PyExc_OverflowError, - "mach_timebase_info is too large"); - } - return -1; - } - - *pnumer = (_PyTime_t)timebase.numer; - *pdenom = (_PyTime_t)timebase.denom; return 0; } #endif @@ -1094,17 +1135,16 @@ py_get_monotonic_clock(_PyTime_t *tp, _Py_clock_info_t *info, int raise_exc) } #elif defined(__APPLE__) - static _PyTime_t timebase_numer = 0; - static _PyTime_t timebase_denom = 0; - if (timebase_denom == 0) { - if (py_mach_timebase_info(&timebase_numer, &timebase_denom, raise_exc) < 0) { + static _PyTimeFraction base = {0, 0}; + if (base.denom == 0) { + if (py_mach_timebase_info(&base, raise_exc) < 0) { return -1; } } if (info) { info->implementation = "mach_absolute_time()"; - info->resolution = (double)timebase_numer / (double)timebase_denom * 1e-9; + info->resolution = _PyTimeFraction_Resolution(&base); info->monotonic = 1; info->adjustable = 0; } @@ -1114,7 +1154,7 @@ py_get_monotonic_clock(_PyTime_t *tp, _Py_clock_info_t *info, int raise_exc) assert(uticks <= (uint64_t)_PyTime_MAX); _PyTime_t ticks = (_PyTime_t)uticks; - _PyTime_t ns = _PyTime_MulDiv(ticks, timebase_numer, timebase_denom); + _PyTime_t ns = _PyTimeFraction_Mul(ticks, &base); *tp = pytime_from_nanoseconds(ns); #elif defined(__hpux) @@ -1198,7 +1238,7 @@ _PyTime_GetMonotonicClockWithInfo(_PyTime_t *tp, _Py_clock_info_t *info) #ifdef MS_WINDOWS static int -py_win_perf_counter_frequency(LONGLONG *pfrequency, int raise) +py_win_perf_counter_frequency(_PyTimeFraction *base, int raise) { LONGLONG frequency; @@ -1210,25 +1250,20 @@ py_win_perf_counter_frequency(LONGLONG *pfrequency, int raise) // Since Windows XP, frequency cannot be zero. assert(frequency >= 1); - /* Make also sure that (ticks * SEC_TO_NS) cannot overflow in - _PyTime_MulDiv(), with ticks < frequency. - - Known QueryPerformanceFrequency() values: - - * 10,000,000 (10 MHz): 100 ns resolution - * 3,579,545 Hz (3.6 MHz): 279 ns resolution + Py_BUILD_ASSERT(sizeof(_PyTime_t) == sizeof(frequency)); + _PyTime_t denom = (_PyTime_t)frequency; - None of these frequencies can overflow with 64-bit _PyTime_t, but - check for integer overflow just in case. */ - if (frequency > _PyTime_MAX / SEC_TO_NS) { + // Known QueryPerformanceFrequency() values: + // + // * 10,000,000 (10 MHz): 100 ns resolution + // * 3,579,545 Hz (3.6 MHz): 279 ns resolution + if (_PyTimeFraction_Set(base, SEC_TO_NS, denom) < 0) { if (raise) { - PyErr_SetString(PyExc_OverflowError, - "QueryPerformanceFrequency is too large"); + PyErr_SetString(PyExc_RuntimeError, + "invalid QueryPerformanceFrequency"); } return -1; } - - *pfrequency = frequency; return 0; } @@ -1238,16 +1273,16 @@ py_get_win_perf_counter(_PyTime_t *tp, _Py_clock_info_t *info, int raise_exc) { assert(info == NULL || raise_exc); - static LONGLONG frequency = 0; - if (frequency == 0) { - if (py_win_perf_counter_frequency(&frequency, raise_exc) < 0) { + static _PyTimeFraction base = {0, 0}; + if (base.denom == 0) { + if (py_win_perf_counter_frequency(&base, raise_exc) < 0) { return -1; } } if (info) { info->implementation = "QueryPerformanceCounter()"; - info->resolution = 1.0 / (double)frequency; + info->resolution = _PyTimeFraction_Resolution(&base); info->monotonic = 1; info->adjustable = 0; } @@ -1263,7 +1298,7 @@ py_get_win_perf_counter(_PyTime_t *tp, _Py_clock_info_t *info, int raise_exc) "LONGLONG is larger than _PyTime_t"); ticks = (_PyTime_t)ticksll; - _PyTime_t ns = _PyTime_MulDiv(ticks, SEC_TO_NS, (_PyTime_t)frequency); + _PyTime_t ns = _PyTimeFraction_Mul(ticks, &base); *tp = pytime_from_nanoseconds(ns); return 0; } diff --git a/Python/specialize.c b/Python/specialize.c index de329ef1195cbf..13e0440dd9dd0d 100644 --- a/Python/specialize.c +++ b/Python/specialize.c @@ -1,26 +1,31 @@ #include "Python.h" + +#include "opcode.h" + #include "pycore_code.h" #include "pycore_descrobject.h" // _PyMethodWrapper_Type -#include "pycore_dict.h" +#include "pycore_dict.h" // DICT_KEYS_UNICODE #include "pycore_function.h" // _PyFunction_GetVersionForCurrentState() -#include "pycore_global_strings.h" // _Py_ID() -#include "pycore_long.h" +#include "pycore_long.h" // _PyLong_IsNonNegativeCompact() #include "pycore_moduleobject.h" #include "pycore_object.h" -#include "pycore_opcode.h" // _PyOpcode_Caches +#include "pycore_opcode_metadata.h" // _PyOpcode_Caches +#include "pycore_uop_metadata.h" // _PyOpcode_uop_name +#include "pycore_opcode_utils.h" // RESUME_AT_FUNC_START #include "pycore_pylifecycle.h" // _PyOS_URandomNonblock() - +#include "pycore_runtime.h" // _Py_ID() #include // rand() + /* For guidance on adding or extending families of instructions see * ./adaptive.md */ #ifdef Py_STATS GCStats _py_gc_stats[NUM_GENERATIONS] = { 0 }; -PyStats _py_stats_struct = { .gc_stats = &_py_gc_stats[0] }; -PyStats *_py_stats = NULL; +static PyStats _Py_stats_struct = { .gc_stats = _py_gc_stats }; +PyStats *_Py_stats = NULL; #define ADD_STAT_TO_DICT(res, field) \ do { \ @@ -80,7 +85,7 @@ add_stat_dict( int opcode, const char *name) { - SpecializationStats *stats = &_py_stats_struct.opcode_stats[opcode].specialization; + SpecializationStats *stats = &_Py_stats_struct.opcode_stats[opcode].specialization; PyObject *d = stats_to_dict(stats); if (d == NULL) { return -1; @@ -90,7 +95,6 @@ add_stat_dict( return err; } -#ifdef Py_STATS PyObject* _Py_GetSpecializationStats(void) { PyObject *stats = PyDict_New(); @@ -117,12 +121,11 @@ _Py_GetSpecializationStats(void) { } return stats; } -#endif #define PRINT_STAT(i, field) \ if (stats[i].field) { \ - fprintf(out, " opcode[%d]." #field " : %" PRIu64 "\n", i, stats[i].field); \ + fprintf(out, " opcode[%s]." #field " : %" PRIu64 "\n", _PyOpcode_OpName[i], stats[i].field); \ } static void @@ -130,11 +133,11 @@ print_spec_stats(FILE *out, OpcodeStats *stats) { /* Mark some opcodes as specializable for stats, * even though we don't specialize them yet. */ - fprintf(out, "opcode[%d].specializable : 1\n", BINARY_SLICE); - fprintf(out, "opcode[%d].specializable : 1\n", STORE_SLICE); + fprintf(out, "opcode[BINARY_SLICE].specializable : 1\n"); + fprintf(out, "opcode[STORE_SLICE].specializable : 1\n"); for (int i = 0; i < 256; i++) { - if (_PyOpcode_Caches[i]) { - fprintf(out, "opcode[%d].specializable : 1\n", i); + if (_PyOpcode_Caches[i] && i != JUMP_BACKWARD) { + fprintf(out, "opcode[%s].specializable : 1\n", _PyOpcode_OpName[i]); } PRINT_STAT(i, specialization.success); PRINT_STAT(i, specialization.failure); @@ -146,14 +149,14 @@ print_spec_stats(FILE *out, OpcodeStats *stats) for (int j = 0; j < SPECIALIZATION_FAILURE_KINDS; j++) { uint64_t val = stats[i].specialization.failure_kinds[j]; if (val) { - fprintf(out, " opcode[%d].specialization.failure_kinds[%d] : %" - PRIu64 "\n", i, j, val); + fprintf(out, " opcode[%s].specialization.failure_kinds[%d] : %" + PRIu64 "\n", _PyOpcode_OpName[i], j, val); } } for (int j = 0; j < 256; j++) { if (stats[i].pair_count[j]) { - fprintf(out, "opcode[%d].pair_count[%d] : %" PRIu64 "\n", - i, j, stats[i].pair_count[j]); + fprintf(out, "opcode[%s].pair_count[%s] : %" PRIu64 "\n", + _PyOpcode_OpName[i], _PyOpcode_OpName[j], stats[i].pair_count[j]); } } } @@ -192,15 +195,12 @@ print_object_stats(FILE *out, ObjectStats *stats) fprintf(out, "Object materialize dict (new key): %" PRIu64 "\n", stats->dict_materialized_new_key); fprintf(out, "Object materialize dict (too big): %" PRIu64 "\n", stats->dict_materialized_too_big); fprintf(out, "Object materialize dict (str subclass): %" PRIu64 "\n", stats->dict_materialized_str_subclass); + fprintf(out, "Object dematerialize dict: %" PRIu64 "\n", stats->dict_dematerialized); fprintf(out, "Object method cache hits: %" PRIu64 "\n", stats->type_cache_hits); fprintf(out, "Object method cache misses: %" PRIu64 "\n", stats->type_cache_misses); fprintf(out, "Object method cache collisions: %" PRIu64 "\n", stats->type_cache_collisions); fprintf(out, "Object method cache dunder hits: %" PRIu64 "\n", stats->type_cache_dunder_hits); fprintf(out, "Object method cache dunder misses: %" PRIu64 "\n", stats->type_cache_dunder_misses); - fprintf(out, "Optimization attempts: %" PRIu64 "\n", stats->optimization_attempts); - fprintf(out, "Optimization traces created: %" PRIu64 "\n", stats->optimization_traces_created); - fprintf(out, "Optimization traces executed: %" PRIu64 "\n", stats->optimization_traces_executed); - fprintf(out, "Optimization uops executed: %" PRIu64 "\n", stats->optimization_uops_executed); } static void @@ -214,26 +214,120 @@ print_gc_stats(FILE *out, GCStats *stats) } static void -print_stats(FILE *out, PyStats *stats) { +print_histogram(FILE *out, const char *name, uint64_t hist[_Py_UOP_HIST_SIZE]) +{ + for (int i = 0; i < _Py_UOP_HIST_SIZE; i++) { + fprintf(out, "%s[%" PRIu64"]: %" PRIu64 "\n", name, (uint64_t)1 << i, hist[i]); + } +} + +static void +print_optimization_stats(FILE *out, OptimizationStats *stats) +{ + fprintf(out, "Optimization attempts: %" PRIu64 "\n", stats->attempts); + fprintf(out, "Optimization traces created: %" PRIu64 "\n", stats->traces_created); + fprintf(out, "Optimization traces executed: %" PRIu64 "\n", stats->traces_executed); + fprintf(out, "Optimization uops executed: %" PRIu64 "\n", stats->uops_executed); + fprintf(out, "Optimization trace stack overflow: %" PRIu64 "\n", stats->trace_stack_overflow); + fprintf(out, "Optimization trace stack underflow: %" PRIu64 "\n", stats->trace_stack_underflow); + fprintf(out, "Optimization trace too long: %" PRIu64 "\n", stats->trace_too_long); + fprintf(out, "Optimization trace too short: %" PRIu64 "\n", stats->trace_too_short); + fprintf(out, "Optimization inner loop: %" PRIu64 "\n", stats->inner_loop); + fprintf(out, "Optimization recursive call: %" PRIu64 "\n", stats->recursive_call); + fprintf(out, "Optimization low confidence: %" PRIu64 "\n", stats->low_confidence); + + print_histogram(out, "Trace length", stats->trace_length_hist); + print_histogram(out, "Trace run length", stats->trace_run_length_hist); + print_histogram(out, "Optimized trace length", stats->optimized_trace_length_hist); + + const char* const* names; + for (int i = 0; i < 512; i++) { + if (i < 256) { + names = _PyOpcode_OpName; + } else { + names = _PyOpcode_uop_name; + } + if (stats->opcode[i].execution_count) { + fprintf(out, "uops[%s].execution_count : %" PRIu64 "\n", names[i], stats->opcode[i].execution_count); + } + if (stats->opcode[i].miss) { + fprintf(out, "uops[%s].specialization.miss : %" PRIu64 "\n", names[i], stats->opcode[i].miss); + } + } + + for (int i = 0; i < 256; i++) { + if (stats->unsupported_opcode[i]) { + fprintf( + out, + "unsupported_opcode[%s].count : %" PRIu64 "\n", + _PyOpcode_OpName[i], + stats->unsupported_opcode[i] + ); + } + } +} + +static void +print_stats(FILE *out, PyStats *stats) +{ print_spec_stats(out, stats->opcode_stats); print_call_stats(out, &stats->call_stats); print_object_stats(out, &stats->object_stats); print_gc_stats(out, stats->gc_stats); + print_optimization_stats(out, &stats->optimization_stats); +} + +void +_Py_StatsOn(void) +{ + _Py_stats = &_Py_stats_struct; +} + +void +_Py_StatsOff(void) +{ + _Py_stats = NULL; } void _Py_StatsClear(void) { - for (int i = 0; i < NUM_GENERATIONS; i++) { - _py_gc_stats[i] = (GCStats) { 0 }; + memset(&_py_gc_stats, 0, sizeof(_py_gc_stats)); + memset(&_Py_stats_struct, 0, sizeof(_Py_stats_struct)); + _Py_stats_struct.gc_stats = _py_gc_stats; +} + +static int +mem_is_zero(unsigned char *ptr, size_t size) +{ + for (size_t i=0; i < size; i++) { + if (*ptr != 0) { + return 0; + } + ptr++; } - _py_stats_struct = (PyStats) { 0 }; - _py_stats_struct.gc_stats = _py_gc_stats; + return 1; } -void +int _Py_PrintSpecializationStats(int to_file) { + PyStats *stats = &_Py_stats_struct; +#define MEM_IS_ZERO(DATA) mem_is_zero((unsigned char*)DATA, sizeof(*(DATA))) + int is_zero = ( + MEM_IS_ZERO(stats->gc_stats) // is a pointer + && MEM_IS_ZERO(&stats->opcode_stats) + && MEM_IS_ZERO(&stats->call_stats) + && MEM_IS_ZERO(&stats->object_stats) + ); +#undef MEM_IS_ZERO + if (is_zero) { + // gh-108753: -X pystats command line was used, but then _stats_off() + // and _stats_clear() have been called: in this case, avoid printing + // useless "all zeros" statistics. + return 0; + } + FILE *out = stderr; if (to_file) { /* Write to a file instead of stderr. */ @@ -249,8 +343,8 @@ _Py_PrintSpecializationStats(int to_file) char hex_name[41]; _PyOS_URandomNonblock(rand, 20); for (int i = 0; i < 20; i++) { - hex_name[2*i] = "0123456789abcdef"[rand[i]&15]; - hex_name[2*i+1] = "0123456789abcdef"[(rand[i]>>4)&15]; + hex_name[2*i] = Py_hexdigits[rand[i]&15]; + hex_name[2*i+1] = Py_hexdigits[(rand[i]>>4)&15]; } hex_name[40] = '\0'; char buf[64]; @@ -264,26 +358,25 @@ _Py_PrintSpecializationStats(int to_file) else { fprintf(out, "Specialization stats:\n"); } - print_stats(out, &_py_stats_struct); + print_stats(out, stats); if (out != stderr) { fclose(out); } + return 1; } -#ifdef Py_STATS - #define SPECIALIZATION_FAIL(opcode, kind) \ do { \ - if (_py_stats) { \ - _py_stats->opcode_stats[opcode].specialization.failure_kinds[kind]++; \ + if (_Py_stats) { \ + _Py_stats->opcode_stats[opcode].specialization.failure_kinds[kind]++; \ } \ } while (0) -#endif -#endif +#endif // Py_STATS + #ifndef SPECIALIZATION_FAIL -#define SPECIALIZATION_FAIL(opcode, kind) ((void)0) +# define SPECIALIZATION_FAIL(opcode, kind) ((void)0) #endif // Initialize warmup counters and insert superinstructions. This cannot fail. @@ -298,7 +391,23 @@ _PyCode_Quicken(PyCodeObject *code) assert(opcode < MIN_INSTRUMENTED_OPCODE); int caches = _PyOpcode_Caches[opcode]; if (caches) { - instructions[i + 1].cache = adaptive_counter_warmup(); + // The initial value depends on the opcode + int initial_value; + switch (opcode) { + case JUMP_BACKWARD: + initial_value = 0; + break; + case POP_JUMP_IF_FALSE: + case POP_JUMP_IF_TRUE: + case POP_JUMP_IF_NONE: + case POP_JUMP_IF_NOT_NONE: + initial_value = 0x5555; // Alternating 0, 1 bits + break; + default: + initial_value = adaptive_counter_warmup(); + break; + } + instructions[i + 1].cache = initial_value; i += caches; } } @@ -363,7 +472,6 @@ _PyCode_Quicken(PyCodeObject *code) #define SPEC_FAIL_SUBSCR_ARRAY_SLICE 10 #define SPEC_FAIL_SUBSCR_LIST_SLICE 11 #define SPEC_FAIL_SUBSCR_TUPLE_SLICE 12 -#define SPEC_FAIL_SUBSCR_STRING_INT 13 #define SPEC_FAIL_SUBSCR_STRING_SLICE 14 #define SPEC_FAIL_SUBSCR_BUFFER_INT 15 #define SPEC_FAIL_SUBSCR_BUFFER_SLICE 16 @@ -418,7 +526,6 @@ _PyCode_Quicken(PyCodeObject *code) #define SPEC_FAIL_CALL_STR 24 #define SPEC_FAIL_CALL_CLASS_NO_VECTORCALL 25 #define SPEC_FAIL_CALL_CLASS_MUTABLE 26 -#define SPEC_FAIL_CALL_KWNAMES 27 #define SPEC_FAIL_CALL_METHOD_WRAPPER 28 #define SPEC_FAIL_CALL_OPERATOR_WRAPPER 29 #define SPEC_FAIL_CALL_INIT_NOT_SIMPLE 30 @@ -479,6 +586,7 @@ _PyCode_Quicken(PyCodeObject *code) 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 uint32_t type_get_version(PyTypeObject *t, int opcode); static int specialize_module_load_attr( @@ -637,7 +745,7 @@ analyze_descriptor(PyTypeObject *type, PyObject *name, PyObject **descr, int sto if (desc_cls == &PyMemberDescr_Type) { PyMemberDescrObject *member = (PyMemberDescrObject *)descriptor; struct PyMemberDef *dmem = member->d_member; - if (dmem->type == Py_T_OBJECT_EX) { + if (dmem->type == Py_T_OBJECT_EX || dmem->type == _Py_T_OBJECT) { return OBJECT_SLOT; } return OTHER_SLOT; @@ -686,8 +794,10 @@ specialize_dict_access( return 0; } _PyAttrCache *cache = (_PyAttrCache *)(instr + 1); - PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner); - if (_PyDictOrValues_IsValues(dorv)) { + PyDictOrValues *dorv = _PyObject_DictOrValuesPointer(owner); + if (_PyDictOrValues_IsValues(*dorv) || + _PyObject_MakeInstanceAttributesFromDict(owner, dorv)) + { // Virtual dictionary PyDictKeysObject *keys = ((PyHeapTypeObject *)type)->ht_cached_keys; assert(PyUnicode_CheckExact(name)); @@ -705,12 +815,16 @@ specialize_dict_access( instr->op.code = values_op; } else { - PyDictObject *dict = (PyDictObject *)_PyDictOrValues_GetDict(dorv); + PyDictObject *dict = (PyDictObject *)_PyDictOrValues_GetDict(*dorv); if (dict == NULL || !PyDict_CheckExact(dict)) { SPECIALIZATION_FAIL(base_op, SPEC_FAIL_NO_DICT); return 0; } // We found an instance with a __dict__. + if (dict->ma_values) { + SPECIALIZATION_FAIL(base_op, SPEC_FAIL_ATTR_NON_STRING_OR_SPLIT); + return 0; + } Py_ssize_t index = _PyDict_LookupIndex(dict, name); if (index != (uint16_t)index) { @@ -761,6 +875,9 @@ _Py_Specialize_LoadAttr(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name) PyObject *descr = NULL; DescriptorClassification kind = analyze_descriptor(type, name, &descr, 0); assert(descr != NULL || kind == ABSENT || kind == GETSET_OVERRIDDEN); + if (type_get_version(type, LOAD_ATTR) == 0) { + goto fail; + } switch(kind) { case OVERRIDING: SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_OVERRIDING_DESCRIPTOR); @@ -794,6 +911,10 @@ _Py_Specialize_LoadAttr(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name) if (!function_check_args(fget, 1, LOAD_ATTR)) { goto fail; } + if (instr->op.arg & 1) { + SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_METHOD); + goto fail; + } uint32_t version = function_get_version(fget, LOAD_ATTR); if (version == 0) { goto fail; @@ -827,7 +948,7 @@ _Py_Specialize_LoadAttr(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name) SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OUT_OF_RANGE); goto fail; } - assert(dmem->type == Py_T_OBJECT_EX); + assert(dmem->type == Py_T_OBJECT_EX || dmem->type == _Py_T_OBJECT); assert(offset > 0); cache->index = (uint16_t)offset; write_u32(cache->version, type->tp_version_tag); @@ -860,6 +981,10 @@ _Py_Specialize_LoadAttr(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name) if (!function_check_args(descr, 2, LOAD_ATTR)) { goto fail; } + if (instr->op.arg & 1) { + SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_METHOD); + goto fail; + } uint32_t version = function_get_version(descr, LOAD_ATTR); if (version == 0) { goto fail; @@ -936,6 +1061,9 @@ _Py_Specialize_StoreAttr(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name) } PyObject *descr; DescriptorClassification kind = analyze_descriptor(type, name, &descr, 1); + if (type_get_version(type, STORE_ATTR) == 0) { + goto fail; + } switch(kind) { case OVERRIDING: SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_ATTR_OVERRIDING_DESCRIPTOR); @@ -963,7 +1091,7 @@ _Py_Specialize_StoreAttr(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name) SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_OUT_OF_RANGE); goto fail; } - assert(dmem->type == Py_T_OBJECT_EX); + assert(dmem->type == Py_T_OBJECT_EX || dmem->type == _Py_T_OBJECT); assert(offset > 0); cache->index = (uint16_t)offset; write_u32(cache->version, type->tp_version_tag); @@ -1048,7 +1176,7 @@ load_attr_fail_kind(DescriptorClassification kind) } Py_UNREACHABLE(); } -#endif +#endif // Py_STATS static int specialize_class_load_attr(PyObject *owner, _Py_CODEUNIT *instr, @@ -1062,6 +1190,9 @@ specialize_class_load_attr(PyObject *owner, _Py_CODEUNIT *instr, PyObject *descr = NULL; DescriptorClassification kind = 0; kind = analyze_descriptor((PyTypeObject *)owner, name, &descr, 0); + if (type_get_version((PyTypeObject *)owner, LOAD_ATTR) == 0) { + return -1; + } switch (kind) { case METHOD: case NON_DESCRIPTOR: @@ -1093,9 +1224,11 @@ PyObject *descr, DescriptorClassification kind, bool is_method) assert(descr != NULL); assert((is_method && kind == METHOD) || (!is_method && kind == NON_DESCRIPTOR)); if (owner_cls->tp_flags & Py_TPFLAGS_MANAGED_DICT) { - PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner); + PyDictOrValues *dorv = _PyObject_DictOrValuesPointer(owner); PyDictKeysObject *keys = ((PyHeapTypeObject *)owner_cls)->ht_cached_keys; - if (!_PyDictOrValues_IsValues(dorv)) { + if (!_PyDictOrValues_IsValues(*dorv) && + !_PyObject_MakeInstanceAttributesFromDict(owner, dorv)) + { SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_HAS_MANAGED_DICT); return 0; } @@ -1260,16 +1393,7 @@ _Py_Specialize_LoadGlobal( static int binary_subscr_fail_kind(PyTypeObject *container_type, PyObject *sub) { - if (container_type == &PyUnicode_Type) { - if (PyLong_CheckExact(sub)) { - return SPEC_FAIL_SUBSCR_STRING_INT; - } - if (PySlice_Check(sub)) { - return SPEC_FAIL_SUBSCR_STRING_SLICE; - } - return SPEC_FAIL_OTHER; - } - else if (strcmp(container_type->tp_name, "array.array") == 0) { + if (strcmp(container_type->tp_name, "array.array") == 0) { if (PyLong_CheckExact(sub)) { return SPEC_FAIL_SUBSCR_ARRAY_INT; } @@ -1294,7 +1418,7 @@ binary_subscr_fail_kind(PyTypeObject *container_type, PyObject *sub) } return SPEC_FAIL_OTHER; } -#endif +#endif // Py_STATS static int function_kind(PyCodeObject *code) { @@ -1341,6 +1465,18 @@ function_get_version(PyObject *o, int opcode) return version; } +/* Returning 0 indicates a failure. */ +static uint32_t +type_get_version(PyTypeObject *t, int opcode) +{ + uint32_t version = t->tp_version_tag; + if (version == 0) { + SPECIALIZATION_FAIL(opcode, SPEC_FAIL_OUT_OF_VERSIONS); + return 0; + } + return version; +} + void _Py_Specialize_BinarySubscr( PyObject *container, PyObject *sub, _Py_CODEUNIT *instr) @@ -1376,6 +1512,19 @@ _Py_Specialize_BinarySubscr( PySlice_Check(sub) ? SPEC_FAIL_SUBSCR_TUPLE_SLICE : SPEC_FAIL_OTHER); goto fail; } + if (container_type == &PyUnicode_Type) { + if (PyLong_CheckExact(sub)) { + if (_PyLong_IsNonNegativeCompact((PyLongObject *)sub)) { + instr->op.code = BINARY_SUBSCR_STR_INT; + goto success; + } + SPECIALIZATION_FAIL(BINARY_SUBSCR, SPEC_FAIL_OUT_OF_RANGE); + goto fail; + } + SPECIALIZATION_FAIL(BINARY_SUBSCR, + PySlice_Check(sub) ? SPEC_FAIL_SUBSCR_STRING_SLICE : SPEC_FAIL_OTHER); + goto fail; + } if (container_type == &PyDict_Type) { instr->op.code = BINARY_SUBSCR_DICT; goto success; @@ -1520,7 +1669,7 @@ _Py_Specialize_StoreSubscr(PyObject *container, PyObject *sub, _Py_CODEUNIT *ins } goto fail; } -#endif +#endif // Py_STATS SPECIALIZATION_FAIL(STORE_SUBSCR, SPEC_FAIL_OTHER); fail: STAT_INC(STORE_SUBSCR, failure); @@ -1569,24 +1718,23 @@ get_init_for_simple_managed_python_class(PyTypeObject *tp) } static int -specialize_class_call(PyObject *callable, _Py_CODEUNIT *instr, int nargs, - PyObject *kwnames) +specialize_class_call(PyObject *callable, _Py_CODEUNIT *instr, int nargs) { assert(PyType_Check(callable)); PyTypeObject *tp = _PyType_CAST(callable); if (tp->tp_flags & Py_TPFLAGS_IMMUTABLETYPE) { int oparg = instr->op.arg; - if (nargs == 1 && kwnames == NULL && oparg == 1) { + if (nargs == 1 && oparg == 1) { if (tp == &PyUnicode_Type) { - instr->op.code = CALL_NO_KW_STR_1; + instr->op.code = CALL_STR_1; return 0; } else if (tp == &PyType_Type) { - instr->op.code = CALL_NO_KW_TYPE_1; + instr->op.code = CALL_TYPE_1; return 0; } else if (tp == &PyTuple_Type) { - instr->op.code = CALL_NO_KW_TUPLE_1; + instr->op.code = CALL_TUPLE_1; return 0; } } @@ -1600,18 +1748,17 @@ specialize_class_call(PyObject *callable, _Py_CODEUNIT *instr, int nargs, } if (tp->tp_new == PyBaseObject_Type.tp_new) { PyFunctionObject *init = get_init_for_simple_managed_python_class(tp); + if (type_get_version(tp, CALL) == 0) { + return -1; + } if (init != NULL) { if (((PyCodeObject *)init->func_code)->co_argcount != nargs+1) { SPECIALIZATION_FAIL(CALL, SPEC_FAIL_WRONG_NUMBER_ARGUMENTS); return -1; } - if (kwnames) { - SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_KWNAMES); - return -1; - } _PyCallCache *cache = (_PyCallCache *)(instr + 1); write_u32(cache->func_version, tp->tp_version_tag); - _Py_SET_OPCODE(*instr, CALL_NO_KW_ALLOC_AND_ENTER_INIT); + _Py_SET_OPCODE(*instr, CALL_ALLOC_AND_ENTER_INIT); return 0; } return -1; @@ -1665,17 +1812,12 @@ meth_descr_call_fail_kind(int ml_flags) return SPEC_FAIL_CALL_BAD_CALL_FLAGS; } } -#endif +#endif // Py_STATS static int specialize_method_descriptor(PyMethodDescrObject *descr, _Py_CODEUNIT *instr, - int nargs, PyObject *kwnames) + int nargs) { - if (kwnames) { - SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_KWNAMES); - return -1; - } - switch (descr->d_method->ml_flags & (METH_VARARGS | METH_FASTCALL | METH_NOARGS | METH_O | METH_KEYWORDS | METH_METHOD)) { @@ -1684,7 +1826,7 @@ specialize_method_descriptor(PyMethodDescrObject *descr, _Py_CODEUNIT *instr, SPECIALIZATION_FAIL(CALL, SPEC_FAIL_WRONG_NUMBER_ARGUMENTS); return -1; } - instr->op.code = CALL_NO_KW_METHOD_DESCRIPTOR_NOARGS; + instr->op.code = CALL_METHOD_DESCRIPTOR_NOARGS; return 0; } case METH_O: { @@ -1698,14 +1840,14 @@ specialize_method_descriptor(PyMethodDescrObject *descr, _Py_CODEUNIT *instr, bool pop = (next.op.code == POP_TOP); int oparg = instr->op.arg; if ((PyObject *)descr == list_append && oparg == 1 && pop) { - instr->op.code = CALL_NO_KW_LIST_APPEND; + instr->op.code = CALL_LIST_APPEND; return 0; } - instr->op.code = CALL_NO_KW_METHOD_DESCRIPTOR_O; + instr->op.code = CALL_METHOD_DESCRIPTOR_O; return 0; } case METH_FASTCALL: { - instr->op.code = CALL_NO_KW_METHOD_DESCRIPTOR_FAST; + instr->op.code = CALL_METHOD_DESCRIPTOR_FAST; return 0; } case METH_FASTCALL | METH_KEYWORDS: { @@ -1719,7 +1861,7 @@ specialize_method_descriptor(PyMethodDescrObject *descr, _Py_CODEUNIT *instr, static int specialize_py_call(PyFunctionObject *func, _Py_CODEUNIT *instr, int nargs, - PyObject *kwnames, bool bound_method) + bool bound_method) { _PyCallCache *cache = (_PyCallCache *)(instr + 1); PyCodeObject *code = (PyCodeObject *)func->func_code; @@ -1729,10 +1871,6 @@ specialize_py_call(PyFunctionObject *func, _Py_CODEUNIT *instr, int nargs, SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_PEP_523); return -1; } - if (kwnames) { - SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_KWNAMES); - return -1; - } if (kind != SIMPLE_FUNCTION) { SPECIALIZATION_FAIL(CALL, kind); return -1; @@ -1768,8 +1906,7 @@ specialize_py_call(PyFunctionObject *func, _Py_CODEUNIT *instr, int nargs, } static int -specialize_c_call(PyObject *callable, _Py_CODEUNIT *instr, int nargs, - PyObject *kwnames) +specialize_c_call(PyObject *callable, _Py_CODEUNIT *instr, int nargs) { if (PyCFunction_GET_FUNCTION(callable) == NULL) { return 1; @@ -1778,10 +1915,6 @@ specialize_c_call(PyObject *callable, _Py_CODEUNIT *instr, int nargs, (METH_VARARGS | METH_FASTCALL | METH_NOARGS | METH_O | METH_KEYWORDS | METH_METHOD)) { case METH_O: { - if (kwnames) { - SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_KWNAMES); - return -1; - } if (nargs != 1) { SPECIALIZATION_FAIL(CALL, SPEC_FAIL_WRONG_NUMBER_ARGUMENTS); return 1; @@ -1789,26 +1922,22 @@ specialize_c_call(PyObject *callable, _Py_CODEUNIT *instr, int nargs, /* len(o) */ PyInterpreterState *interp = _PyInterpreterState_GET(); if (callable == interp->callable_cache.len) { - instr->op.code = CALL_NO_KW_LEN; + instr->op.code = CALL_LEN; return 0; } - instr->op.code = CALL_NO_KW_BUILTIN_O; + instr->op.code = CALL_BUILTIN_O; return 0; } case METH_FASTCALL: { - if (kwnames) { - SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_KWNAMES); - return -1; - } if (nargs == 2) { /* isinstance(o1, o2) */ PyInterpreterState *interp = _PyInterpreterState_GET(); if (callable == interp->callable_cache.isinstance) { - instr->op.code = CALL_NO_KW_ISINSTANCE; + instr->op.code = CALL_ISINSTANCE; return 0; } } - instr->op.code = CALL_NO_KW_BUILTIN_FAST; + instr->op.code = CALL_BUILTIN_FAST; return 0; } case METH_FASTCALL | METH_KEYWORDS: { @@ -1846,15 +1975,11 @@ call_fail_kind(PyObject *callable) } return SPEC_FAIL_OTHER; } -#endif +#endif // Py_STATS -/* TODO: - - Specialize calling classes. -*/ void -_Py_Specialize_Call(PyObject *callable, _Py_CODEUNIT *instr, int nargs, - PyObject *kwnames) +_Py_Specialize_Call(PyObject *callable, _Py_CODEUNIT *instr, int nargs) { assert(ENABLE_SPECIALIZATION); assert(_PyOpcode_Caches[CALL] == INLINE_CACHE_ENTRIES_CALL); @@ -1862,25 +1987,23 @@ _Py_Specialize_Call(PyObject *callable, _Py_CODEUNIT *instr, int nargs, _PyCallCache *cache = (_PyCallCache *)(instr + 1); int fail; if (PyCFunction_CheckExact(callable)) { - fail = specialize_c_call(callable, instr, nargs, kwnames); + fail = specialize_c_call(callable, instr, nargs); } else if (PyFunction_Check(callable)) { - fail = specialize_py_call((PyFunctionObject *)callable, instr, nargs, - kwnames, false); + fail = specialize_py_call((PyFunctionObject *)callable, instr, nargs, false); } else if (PyType_Check(callable)) { - fail = specialize_class_call(callable, instr, nargs, kwnames); + fail = specialize_class_call(callable, instr, nargs); } else if (Py_IS_TYPE(callable, &PyMethodDescr_Type)) { - fail = specialize_method_descriptor((PyMethodDescrObject *)callable, - instr, nargs, kwnames); + fail = specialize_method_descriptor((PyMethodDescrObject *)callable, instr, nargs); } else if (PyMethod_Check(callable)) { PyObject *func = ((PyMethodObject *)callable)->im_func; if (PyFunction_Check(func)) { - fail = specialize_py_call((PyFunctionObject *)func, - instr, nargs+1, kwnames, true); - } else { + fail = specialize_py_call((PyFunctionObject *)func, instr, nargs+1, true); + } + else { SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_BOUND_METHOD); fail = -1; } @@ -1970,7 +2093,7 @@ binary_op_fail_kind(int oparg, PyObject *lhs, PyObject *rhs) } Py_UNREACHABLE(); } -#endif +#endif // Py_STATS void _Py_Specialize_BinaryOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr, @@ -2077,7 +2200,7 @@ compare_op_fail_kind(PyObject *lhs, PyObject *rhs) } return SPEC_FAIL_OTHER; } -#endif +#endif // Py_STATS void _Py_Specialize_CompareOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr, @@ -2140,7 +2263,7 @@ unpack_sequence_fail_kind(PyObject *seq) } return SPEC_FAIL_OTHER; } -#endif +#endif // Py_STATS void _Py_Specialize_UnpackSequence(PyObject *seq, _Py_CODEUNIT *instr, int oparg) @@ -2181,7 +2304,6 @@ _Py_Specialize_UnpackSequence(PyObject *seq, _Py_CODEUNIT *instr, int oparg) } #ifdef Py_STATS - int _PySpecialization_ClassifyIterator(PyObject *iter) { @@ -2252,8 +2374,7 @@ int } return SPEC_FAIL_OTHER; } - -#endif +#endif // Py_STATS void _Py_Specialize_ForIter(PyObject *iter, _Py_CODEUNIT *instr, int oparg) @@ -2370,7 +2491,10 @@ _Py_Specialize_ToBool(PyObject *value, _Py_CODEUNIT *instr) SPECIALIZATION_FAIL(TO_BOOL, SPEC_FAIL_OUT_OF_VERSIONS); goto failure; } - uint32_t version = Py_TYPE(value)->tp_version_tag; + uint32_t version = type_get_version(Py_TYPE(value), TO_BOOL); + if (version == 0) { + goto failure; + } instr->op.code = TO_BOOL_ALWAYS_TRUE; write_u32(cache->version, version); assert(version); @@ -2406,7 +2530,7 @@ _Py_Specialize_ToBool(PyObject *value, _Py_CODEUNIT *instr) goto failure; } SPECIALIZATION_FAIL(TO_BOOL, SPEC_FAIL_OTHER); -#endif +#endif // Py_STATS failure: STAT_INC(TO_BOOL, failure); instr->op.code = TO_BOOL; @@ -2418,7 +2542,7 @@ _Py_Specialize_ToBool(PyObject *value, _Py_CODEUNIT *instr) } /* Code init cleanup. - * CALL_NO_KW_ALLOC_AND_ENTER_INIT will set up + * CALL_ALLOC_AND_ENTER_INIT will set up * the frame to execute the EXIT_INIT_CHECK * instruction. * Ends with a RESUME so that it is not traced. @@ -2434,11 +2558,11 @@ static const PyBytesObject no_location = { }; const struct _PyCode_DEF(8) _Py_InitCleanup = { - _PyVarObject_HEAD_INIT(&PyCode_Type, 4) + _PyVarObject_HEAD_INIT(&PyCode_Type, 3), .co_consts = (PyObject *)&_Py_SINGLETON(tuple_empty), .co_names = (PyObject *)&_Py_SINGLETON(tuple_empty), .co_exceptiontable = (PyObject *)&_Py_SINGLETON(bytes_empty), - .co_flags = CO_OPTIMIZED, + .co_flags = CO_OPTIMIZED | CO_NO_MONITORING_EVENTS, .co_localsplusnames = (PyObject *)&_Py_SINGLETON(tuple_empty), .co_localspluskinds = (PyObject *)&_Py_SINGLETON(bytes_empty), .co_filename = &_Py_ID(__init__), @@ -2449,9 +2573,8 @@ const struct _PyCode_DEF(8) _Py_InitCleanup = { .co_stacksize = 2, .co_framesize = 2 + FRAME_SPECIALS_SIZE, .co_code_adaptive = { - NOP, 0, EXIT_INIT_CHECK, 0, RETURN_VALUE, 0, - RESUME, 0, + RESUME, RESUME_AT_FUNC_START, } }; diff --git a/Python/stdlib_module_names.h b/Python/stdlib_module_names.h index 13b1764f0886d1..2445a5c838a7d7 100644 --- a/Python/stdlib_module_names.h +++ b/Python/stdlib_module_names.h @@ -76,7 +76,9 @@ static const char* _Py_stdlib_module_names[] = { "_string", "_strptime", "_struct", +"_suggestions", "_symtable", +"_sysconfig", "_thread", "_threading_local", "_tkinter", diff --git a/Python/suggestions.c b/Python/suggestions.c index 47aeb08180f6b1..a09b3ce6d9dab2 100644 --- a/Python/suggestions.c +++ b/Python/suggestions.c @@ -1,11 +1,8 @@ #include "Python.h" +#include "pycore_code.h" // _PyCode_GetVarnames() #include "pycore_frame.h" -#include "pycore_runtime.h" // _PyRuntime -#include "pycore_global_objects.h" // _Py_ID() - -#include "pycore_pyerrors.h" -#include "pycore_code.h" // _PyCode_GetVarnames() -#include "stdlib_module_names.h" // _Py_stdlib_module_names +#include "pycore_pyerrors.h" // export _Py_UTF8_Edit_Cost() +#include "pycore_runtime.h" // _Py_ID() #define MAX_CANDIDATE_ITEMS 750 #define MAX_STRING_SIZE 40 @@ -126,8 +123,8 @@ levenshtein_distance(const char *a, size_t a_size, return result; } -static inline PyObject * -calculate_suggestions(PyObject *dir, +PyObject * +_Py_CalculateSuggestions(PyObject *dir, PyObject *name) { assert(!PyErr_Occurred()); @@ -179,227 +176,6 @@ calculate_suggestions(PyObject *dir, return Py_XNewRef(suggestion); } -static PyObject * -get_suggestions_for_attribute_error(PyAttributeErrorObject *exc) -{ - PyObject *name = exc->name; // borrowed reference - PyObject *obj = exc->obj; // borrowed reference - - // Abort if we don't have an attribute name or we have an invalid one - if (name == NULL || obj == NULL || !PyUnicode_CheckExact(name)) { - return NULL; - } - - PyObject *dir = PyObject_Dir(obj); - if (dir == NULL) { - return NULL; - } - - PyObject *suggestions = calculate_suggestions(dir, name); - Py_DECREF(dir); - return suggestions; -} - -static PyObject * -offer_suggestions_for_attribute_error(PyAttributeErrorObject *exc) -{ - PyObject* suggestion = get_suggestions_for_attribute_error(exc); - if (suggestion == NULL) { - return NULL; - } - // Add a trailer ". Did you mean: (...)?" - PyObject* result = PyUnicode_FromFormat(". Did you mean: %R?", suggestion); - Py_DECREF(suggestion); - return result; -} - -static PyObject * -get_suggestions_for_name_error(PyObject* name, PyFrameObject* frame) -{ - PyCodeObject *code = PyFrame_GetCode(frame); - assert(code != NULL && code->co_localsplusnames != NULL); - - PyObject *varnames = _PyCode_GetVarnames(code); - Py_DECREF(code); - if (varnames == NULL) { - return NULL; - } - PyObject *dir = PySequence_List(varnames); - Py_DECREF(varnames); - if (dir == NULL) { - return NULL; - } - - // Are we inside a method and the instance has an attribute called 'name'? - int res = PySequence_Contains(dir, &_Py_ID(self)); - if (res < 0) { - goto error; - } - if (res > 0) { - PyObject* locals = PyFrame_GetLocals(frame); - if (!locals) { - goto error; - } - PyObject* self = PyDict_GetItemWithError(locals, &_Py_ID(self)); /* borrowed */ - if (!self) { - Py_DECREF(locals); - goto error; - } - - PyObject *value; - res = PyObject_GetOptionalAttr(self, name, &value); - Py_DECREF(locals); - if (res < 0) { - goto error; - } - if (value) { - Py_DECREF(value); - Py_DECREF(dir); - return PyUnicode_FromFormat("self.%U", name); - } - } - - PyObject *suggestions = calculate_suggestions(dir, name); - Py_DECREF(dir); - if (suggestions != NULL || PyErr_Occurred()) { - return suggestions; - } - - dir = PySequence_List(frame->f_frame->f_globals); - if (dir == NULL) { - return NULL; - } - suggestions = calculate_suggestions(dir, name); - Py_DECREF(dir); - if (suggestions != NULL || PyErr_Occurred()) { - return suggestions; - } - - dir = PySequence_List(frame->f_frame->f_builtins); - if (dir == NULL) { - return NULL; - } - suggestions = calculate_suggestions(dir, name); - Py_DECREF(dir); - - return suggestions; - -error: - Py_DECREF(dir); - return NULL; -} - -static bool -is_name_stdlib_module(PyObject* name) -{ - const char* the_name = PyUnicode_AsUTF8(name); - Py_ssize_t len = Py_ARRAY_LENGTH(_Py_stdlib_module_names); - for (Py_ssize_t i = 0; i < len; i++) { - if (strcmp(the_name, _Py_stdlib_module_names[i]) == 0) { - return 1; - } - } - return 0; -} - -static PyObject * -offer_suggestions_for_name_error(PyNameErrorObject *exc) -{ - PyObject *name = exc->name; // borrowed reference - PyTracebackObject *traceback = (PyTracebackObject *) exc->traceback; // borrowed reference - // Abort if we don't have a variable name or we have an invalid one - // or if we don't have a traceback to work with - if (name == NULL || !PyUnicode_CheckExact(name) || - traceback == NULL || !Py_IS_TYPE(traceback, &PyTraceBack_Type) - ) { - return NULL; - } - - // Move to the traceback of the exception - while (1) { - PyTracebackObject *next = traceback->tb_next; - if (next == NULL || !Py_IS_TYPE(next, &PyTraceBack_Type)) { - break; - } - else { - traceback = next; - } - } - - PyFrameObject *frame = traceback->tb_frame; - assert(frame != NULL); - - PyObject* suggestion = get_suggestions_for_name_error(name, frame); - if (suggestion == NULL && PyErr_Occurred()) { - return NULL; - } - - // Add a trailer ". Did you mean: (...)?" - PyObject* result = NULL; - if (!is_name_stdlib_module(name)) { - if (suggestion == NULL) { - return NULL; - } - result = PyUnicode_FromFormat(". Did you mean: %R?", suggestion); - } else if (suggestion == NULL) { - result = PyUnicode_FromFormat(". Did you forget to import %R?", name); - } else { - result = PyUnicode_FromFormat(". Did you mean: %R? Or did you forget to import %R?", suggestion, name); - } - Py_XDECREF(suggestion); - return result; -} - -static PyObject * -offer_suggestions_for_import_error(PyImportErrorObject *exc) -{ - PyObject *mod_name = exc->name; // borrowed reference - PyObject *name = exc->name_from; // borrowed reference - if (name == NULL || mod_name == NULL || name == Py_None || - !PyUnicode_CheckExact(name) || !PyUnicode_CheckExact(mod_name)) { - return NULL; - } - - PyObject* mod = PyImport_GetModule(mod_name); - if (mod == NULL) { - return NULL; - } - - PyObject *dir = PyObject_Dir(mod); - Py_DECREF(mod); - if (dir == NULL) { - return NULL; - } - - PyObject *suggestion = calculate_suggestions(dir, name); - Py_DECREF(dir); - if (!suggestion) { - return NULL; - } - - PyObject* result = PyUnicode_FromFormat(". Did you mean: %R?", suggestion); - Py_DECREF(suggestion); - return result; -} - -// Offer suggestions for a given exception. Returns a python string object containing the -// suggestions. This function returns NULL if no suggestion was found or if an exception happened, -// users must call PyErr_Occurred() to disambiguate. -PyObject * -_Py_Offer_Suggestions(PyObject *exception) -{ - PyObject *result = NULL; - assert(!PyErr_Occurred()); - if (Py_IS_TYPE(exception, (PyTypeObject*)PyExc_AttributeError)) { - result = offer_suggestions_for_attribute_error((PyAttributeErrorObject *) exception); - } else if (Py_IS_TYPE(exception, (PyTypeObject*)PyExc_NameError)) { - result = offer_suggestions_for_name_error((PyNameErrorObject *) exception); - } else if (Py_IS_TYPE(exception, (PyTypeObject*)PyExc_ImportError)) { - result = offer_suggestions_for_import_error((PyImportErrorObject *) exception); - } - return result; -} - Py_ssize_t _Py_UTF8_Edit_Cost(PyObject *a, PyObject *b, Py_ssize_t max_cost) { diff --git a/Python/symtable.c b/Python/symtable.c index e9adbd5d29b1f9..83137b491f282c 100644 --- a/Python/symtable.c +++ b/Python/symtable.c @@ -1,9 +1,11 @@ #include "Python.h" -#include "pycore_ast.h" // identifier, stmt_ty +#include "pycore_ast.h" // stmt_ty #include "pycore_parser.h" // _PyParser_ASTFromString() #include "pycore_pystate.h" // _PyThreadState_GET() #include "pycore_symtable.h" // PySTEntryObject +// Set this to 1 to dump all symtables to stdout for debugging +#define _PY_DUMP_SYMTABLE 0 /* error strings used for warnings */ #define GLOBAL_PARAM \ @@ -150,9 +152,8 @@ ste_new(struct symtable *st, identifier name, _Py_block_ty block, static PyObject * ste_repr(PySTEntryObject *ste) { - return PyUnicode_FromFormat("", - ste->ste_name, - PyLong_AS_LONG(ste->ste_id), ste->ste_lineno); + return PyUnicode_FromFormat("", + ste->ste_name, ste->ste_id, ste->ste_lineno); } static void @@ -252,6 +253,109 @@ static int symtable_visit_pattern(struct symtable *st, pattern_ty s); static int symtable_raise_if_annotation_block(struct symtable *st, const char *, expr_ty); static int symtable_raise_if_comprehension_block(struct symtable *st, expr_ty); +/* For debugging purposes only */ +#if _PY_DUMP_SYMTABLE +static void _dump_symtable(PySTEntryObject* ste, PyObject* prefix) +{ + const char *blocktype = ""; + switch (ste->ste_type) { + case FunctionBlock: blocktype = "FunctionBlock"; break; + case ClassBlock: blocktype = "ClassBlock"; break; + case ModuleBlock: blocktype = "ModuleBlock"; break; + case AnnotationBlock: blocktype = "AnnotationBlock"; break; + case TypeVarBoundBlock: blocktype = "TypeVarBoundBlock"; break; + case TypeAliasBlock: blocktype = "TypeAliasBlock"; break; + case TypeParamBlock: blocktype = "TypeParamBlock"; break; + } + const char *comptype = ""; + switch (ste->ste_comprehension) { + case ListComprehension: comptype = " ListComprehension"; break; + case DictComprehension: comptype = " DictComprehension"; break; + case SetComprehension: comptype = " SetComprehension"; break; + case GeneratorExpression: comptype = " GeneratorExpression"; break; + case NoComprehension: break; + } + PyObject* msg = PyUnicode_FromFormat( + ( + "%U=== Symtable for %U ===\n" + "%U%s%s\n" + "%U%s%s%s%s%s%s%s%s%s%s%s%s%s\n" + "%Ulineno: %d col_offset: %d\n" + "%U--- Symbols ---\n" + ), + prefix, + ste->ste_name, + prefix, + blocktype, + comptype, + prefix, + ste->ste_nested ? " nested" : "", + ste->ste_free ? " free" : "", + ste->ste_child_free ? " child_free" : "", + ste->ste_generator ? " generator" : "", + ste->ste_coroutine ? " coroutine" : "", + ste->ste_varargs ? " varargs" : "", + ste->ste_varkeywords ? " varkeywords" : "", + ste->ste_returns_value ? " returns_value" : "", + ste->ste_needs_class_closure ? " needs_class_closure" : "", + ste->ste_needs_classdict ? " needs_classdict" : "", + ste->ste_comp_inlined ? " comp_inlined" : "", + ste->ste_comp_iter_target ? " comp_iter_target" : "", + ste->ste_can_see_class_scope ? " can_see_class_scope" : "", + prefix, + ste->ste_lineno, + ste->ste_col_offset, + prefix + ); + assert(msg != NULL); + printf("%s", PyUnicode_AsUTF8(msg)); + Py_DECREF(msg); + PyObject *name, *value; + Py_ssize_t pos = 0; + while (PyDict_Next(ste->ste_symbols, &pos, &name, &value)) { + int scope = _PyST_GetScope(ste, name); + long flags = _PyST_GetSymbol(ste, name); + printf("%s %s: ", PyUnicode_AsUTF8(prefix), PyUnicode_AsUTF8(name)); + if (flags & DEF_GLOBAL) printf(" DEF_GLOBAL"); + if (flags & DEF_LOCAL) printf(" DEF_LOCAL"); + if (flags & DEF_PARAM) printf(" DEF_PARAM"); + if (flags & DEF_NONLOCAL) printf(" DEF_NONLOCAL"); + if (flags & USE) printf(" USE"); + if (flags & DEF_FREE) printf(" DEF_FREE"); + if (flags & DEF_FREE_CLASS) printf(" DEF_FREE_CLASS"); + if (flags & DEF_IMPORT) printf(" DEF_IMPORT"); + if (flags & DEF_ANNOT) printf(" DEF_ANNOT"); + if (flags & DEF_COMP_ITER) printf(" DEF_COMP_ITER"); + if (flags & DEF_TYPE_PARAM) printf(" DEF_TYPE_PARAM"); + if (flags & DEF_COMP_CELL) printf(" DEF_COMP_CELL"); + switch (scope) { + case LOCAL: printf(" LOCAL"); break; + case GLOBAL_EXPLICIT: printf(" GLOBAL_EXPLICIT"); break; + case GLOBAL_IMPLICIT: printf(" GLOBAL_IMPLICIT"); break; + case FREE: printf(" FREE"); break; + case CELL: printf(" CELL"); break; + } + printf("\n"); + } + printf("%s--- Children ---\n", PyUnicode_AsUTF8(prefix)); + PyObject *new_prefix = PyUnicode_FromFormat(" %U", prefix); + assert(new_prefix != NULL); + for (Py_ssize_t i = 0; i < PyList_GET_SIZE(ste->ste_children); i++) { + PyObject *child = PyList_GetItem(ste->ste_children, i); + assert(child != NULL && PySTEntry_Check(child)); + _dump_symtable((PySTEntryObject *)child, new_prefix); + } + Py_DECREF(new_prefix); +} + +static void dump_symtable(PySTEntryObject* ste) +{ + PyObject *empty = PyUnicode_FromString(""); + assert(empty != NULL); + _dump_symtable(ste, empty); + Py_DECREF(empty); +} +#endif #define DUPLICATE_ARGUMENT \ "duplicate argument '%U' in function definition" @@ -312,10 +416,10 @@ _PySymtable_Build(mod_ty mod, PyObject *filename, PyFutureFeatures *future) return NULL; } /* Be careful here to prevent overflow. */ - int recursion_depth = C_RECURSION_LIMIT - tstate->c_recursion_remaining; + int recursion_depth = Py_C_RECURSION_LIMIT - tstate->c_recursion_remaining; starting_recursion_depth = recursion_depth * COMPILER_STACK_FRAME_SCALE; st->recursion_depth = starting_recursion_depth; - st->recursion_limit = C_RECURSION_LIMIT * COMPILER_STACK_FRAME_SCALE; + st->recursion_limit = Py_C_RECURSION_LIMIT * COMPILER_STACK_FRAME_SCALE; /* Make the initial symbol information gathering pass */ if (!symtable_enter_block(st, &_Py_ID(top), ModuleBlock, (void *)mod, 0, 0, 0, 0)) { @@ -361,8 +465,12 @@ _PySymtable_Build(mod_ty mod, PyObject *filename, PyFutureFeatures *future) return NULL; } /* Make the second symbol analysis pass */ - if (symtable_analyze(st)) + if (symtable_analyze(st)) { +#if _PY_DUMP_SYMTABLE + dump_symtable(st->st_top); +#endif return st; + } _PySymtable_Free(st); return NULL; error: @@ -389,18 +497,14 @@ _PySymtable_Lookup(struct symtable *st, void *key) k = PyLong_FromVoidPtr(key); if (k == NULL) return NULL; - v = PyDict_GetItemWithError(st->st_blocks, k); - Py_DECREF(k); - - if (v) { - assert(PySTEntry_Check(v)); - } - else if (!PyErr_Occurred()) { + if (PyDict_GetItemRef(st->st_blocks, k, &v) == 0) { PyErr_SetString(PyExc_KeyError, "unknown symbol table entry"); } + Py_DECREF(k); - return (PySTEntryObject *)Py_XNewRef(v); + assert(v == NULL || PySTEntry_Check(v)); + return (PySTEntryObject *)v; } long @@ -523,6 +627,7 @@ analyze_name(PySTEntryObject *ste, PyObject *scopes, PyObject *name, long flags, PyObject *bound, PyObject *local, PyObject *free, PyObject *global, PyObject *type_params, PySTEntryObject *class_entry) { + int contains; if (flags & DEF_GLOBAL) { if (flags & DEF_NONLOCAL) { PyErr_Format(PyExc_SyntaxError, @@ -543,14 +648,22 @@ analyze_name(PySTEntryObject *ste, PyObject *scopes, PyObject *name, long flags, "nonlocal declaration not allowed at module level"); return error_at_directive(ste, name); } - if (!PySet_Contains(bound, name)) { + contains = PySet_Contains(bound, name); + if (contains < 0) { + return 0; + } + if (!contains) { PyErr_Format(PyExc_SyntaxError, "no binding for nonlocal '%U' found", name); return error_at_directive(ste, name); } - if (PySet_Contains(type_params, name)) { + contains = PySet_Contains(type_params, name); + if (contains < 0) { + return 0; + } + if (contains) { PyErr_Format(PyExc_SyntaxError, "nonlocal binding not allowed for type parameter '%U'", name); @@ -599,17 +712,29 @@ analyze_name(PySTEntryObject *ste, PyObject *scopes, PyObject *name, long flags, Note that having a non-NULL bound implies that the block is nested. */ - if (bound && PySet_Contains(bound, name)) { - SET_SCOPE(scopes, name, FREE); - ste->ste_free = 1; - return PySet_Add(free, name) >= 0; + if (bound) { + contains = PySet_Contains(bound, name); + if (contains < 0) { + return 0; + } + if (contains) { + SET_SCOPE(scopes, name, FREE); + ste->ste_free = 1; + return PySet_Add(free, name) >= 0; + } } /* If a parent has a global statement, then call it global explicit? It could also be global implicit. */ - if (global && PySet_Contains(global, name)) { - SET_SCOPE(scopes, name, GLOBAL_IMPLICIT); - return 1; + if (global) { + contains = PySet_Contains(global, name); + if (contains < 0) { + return 0; + } + if (contains) { + SET_SCOPE(scopes, name, GLOBAL_IMPLICIT); + return 1; + } } if (ste->ste_nested) ste->ste_free = 1; @@ -712,8 +837,19 @@ analyze_cells(PyObject *scopes, PyObject *free, PyObject *inlined_cells) scope = PyLong_AS_LONG(v); if (scope != LOCAL) continue; - if (!PySet_Contains(free, name) && !PySet_Contains(inlined_cells, name)) - continue; + int contains = PySet_Contains(free, name); + if (contains < 0) { + goto error; + } + if (!contains) { + contains = PySet_Contains(inlined_cells, name); + if (contains < 0) { + goto error; + } + if (!contains) { + continue; + } + } /* Replace LOCAL with CELL for this name, and remove from free. It is safe to replace the value of name in the dict, because it will not cause a resize. @@ -764,7 +900,11 @@ update_symbols(PyObject *symbols, PyObject *scopes, long scope, flags; assert(PyLong_Check(v)); flags = PyLong_AS_LONG(v); - if (PySet_Contains(inlined_cells, name)) { + int contains = PySet_Contains(inlined_cells, name); + if (contains < 0) { + return 0; + } + if (contains) { flags |= DEF_COMP_CELL; } v_scope = PyDict_GetItemWithError(scopes, name); @@ -801,8 +941,7 @@ update_symbols(PyObject *symbols, PyObject *scopes, the class that has the same name as a local or global in the class scope. */ - if (classflag && - PyLong_AS_LONG(v) & (DEF_BOUND | DEF_GLOBAL)) { + if (classflag) { long flags = PyLong_AS_LONG(v) | DEF_FREE_CLASS; v_new = PyLong_FromLong(flags); if (!v_new) { @@ -822,9 +961,15 @@ update_symbols(PyObject *symbols, PyObject *scopes, goto error; } /* Handle global symbol */ - if (bound && !PySet_Contains(bound, name)) { - Py_DECREF(name); - continue; /* it's a global */ + if (bound) { + int contains = PySet_Contains(bound, name); + if (contains < 0) { + goto error; + } + if (!contains) { + Py_DECREF(name); + continue; /* it's a global */ + } } /* Propagate new free symbol up the lexical stack */ if (PyDict_SetItem(symbols, name, v_free) < 0) { @@ -832,6 +977,12 @@ update_symbols(PyObject *symbols, PyObject *scopes, } Py_DECREF(name); } + + /* Check if loop ended because of exception in PyIter_Next */ + if (PyErr_Occurred()) { + goto error; + } + Py_DECREF(itr); Py_DECREF(v_free); return 1; @@ -1037,7 +1188,7 @@ analyze_block(PySTEntryObject *ste, PyObject *bound, PyObject *free, goto error; /* Records the results of the analysis in the symbol table entry */ if (!update_symbols(ste->ste_symbols, scopes, bound, newfree, inlined_cells, - ste->ste_type == ClassBlock)) + (ste->ste_type == ClassBlock) || ste->ste_can_see_class_scope)) goto error; temp = PyNumber_InPlaceOr(free, newfree); @@ -1664,14 +1815,14 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s) break; case Try_kind: VISIT_SEQ(st, stmt, s->v.Try.body); - VISIT_SEQ(st, stmt, s->v.Try.orelse); VISIT_SEQ(st, excepthandler, s->v.Try.handlers); + VISIT_SEQ(st, stmt, s->v.Try.orelse); VISIT_SEQ(st, stmt, s->v.Try.finalbody); break; case TryStar_kind: VISIT_SEQ(st, stmt, s->v.TryStar.body); - VISIT_SEQ(st, stmt, s->v.TryStar.orelse); VISIT_SEQ(st, excepthandler, s->v.TryStar.handlers); + VISIT_SEQ(st, stmt, s->v.TryStar.orelse); VISIT_SEQ(st, stmt, s->v.TryStar.finalbody); break; case Assert_kind: @@ -1969,6 +2120,17 @@ symtable_visit_expr(struct symtable *st, expr_ty e) VISIT(st, expr, e->v.UnaryOp.operand); break; case Lambda_kind: { + if (st->st_cur->ste_can_see_class_scope) { + // gh-109118 + PyErr_Format(PyExc_SyntaxError, + "Cannot use lambda in annotation scope within class scope"); + PyErr_RangedSyntaxLocationObject(st->st_filename, + e->lineno, + e->col_offset + 1, + e->end_lineno, + e->end_col_offset + 1); + VISIT_QUIT(st, 0); + } if (e->v.Lambda.args->defaults) VISIT_SEQ(st, expr, e->v.Lambda.args->defaults); if (e->v.Lambda.args->kw_defaults) @@ -2418,6 +2580,18 @@ symtable_handle_comprehension(struct symtable *st, expr_ty e, identifier scope_name, asdl_comprehension_seq *generators, expr_ty elt, expr_ty value) { + if (st->st_cur->ste_can_see_class_scope) { + // gh-109118 + PyErr_Format(PyExc_SyntaxError, + "Cannot use comprehension in annotation scope within class scope"); + PyErr_RangedSyntaxLocationObject(st->st_filename, + e->lineno, + e->col_offset + 1, + e->end_lineno, + e->end_col_offset + 1); + VISIT_QUIT(st, 0); + } + int is_generator = (e->kind == GeneratorExp_kind); comprehension_ty outermost = ((comprehension_ty) asdl_seq_GET(generators, 0)); diff --git a/Python/sysmodule.c b/Python/sysmodule.c index be026d95ba7e77..c2de4ecdc8ce0f 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -23,25 +23,30 @@ Data members: #include "pycore_long.h" // _PY_LONG_MAX_STR_DIGITS_THRESHOLD #include "pycore_modsupport.h" // _PyModule_CreateInitialized() #include "pycore_namespace.h" // _PyNamespace_New() -#include "pycore_object.h" // _PyObject_IS_GC(), _PyObject_DebugTypeStats() +#include "pycore_object.h" // _PyObject_DebugTypeStats() #include "pycore_pathconfig.h" // _PyPathConfig_ComputeSysPath0() #include "pycore_pyerrors.h" // _PyErr_GetRaisedException() #include "pycore_pylifecycle.h" // _PyErr_WriteUnraisableDefaultHook() #include "pycore_pymath.h" // _PY_SHORT_FLOAT_REPR #include "pycore_pymem.h" // _PyMem_SetDefaultAllocator() #include "pycore_pystate.h" // _PyThreadState_GET() +#include "pycore_pystats.h" // _Py_PrintSpecializationStats() #include "pycore_structseq.h" // _PyStructSequence_InitBuiltinWithFlags() +#include "pycore_sysmodule.h" // export _PySys_GetSizeOf() #include "pycore_tuple.h" // _PyTuple_FromArray() #include "frameobject.h" // PyFrame_FastToLocalsWithError() -#include "pydtrace.h" +#include "pydtrace.h" // PyDTrace_AUDIT() #include "osdefs.h" // DELIM #include "stdlib_module_names.h" // _Py_stdlib_module_names -#include + +#ifdef HAVE_UNISTD_H +# include // getpid() +#endif #ifdef MS_WINDOWS -#define WIN32_LEAN_AND_MEAN -#include +# define WIN32_LEAN_AND_MEAN +# include #endif /* MS_WINDOWS */ #ifdef MS_COREDLL @@ -51,11 +56,11 @@ extern const char *PyWin_DLLVersionString; #endif #ifdef __EMSCRIPTEN__ -#include +# include #endif #ifdef HAVE_FCNTL_H -#include +# include #endif /*[clinic input] @@ -65,6 +70,7 @@ module sys #include "clinic/sysmodule.c.h" + PyObject * _PySys_GetAttr(PyThreadState *tstate, PyObject *name) { @@ -87,7 +93,12 @@ _PySys_GetObject(PyInterpreterState *interp, const char *name) if (sysdict == NULL) { return NULL; } - return _PyDict_GetItemStringWithError(sysdict, name); + PyObject *value; + if (PyDict_GetItemStringRef(sysdict, name, &value) != 1) { + return NULL; + } + Py_DECREF(value); // return a borrowed reference + return value; } PyObject * @@ -99,6 +110,9 @@ PySys_GetObject(const char *name) PyObject *value = _PySys_GetObject(tstate->interp, name); /* XXX Suppress a new exception if it was raised and restore * the old one. */ + if (_PyErr_Occurred(tstate)) { + PyErr_FormatUnraisable("Exception ignored in PySys_GetObject()"); + } _PyErr_SetRaisedException(tstate, exc); return value; } @@ -111,11 +125,9 @@ sys_set_object(PyInterpreterState *interp, PyObject *key, PyObject *v) } PyObject *sd = interp->sysdict; if (v == NULL) { - v = _PyDict_Pop(sd, key, Py_None); - if (v == NULL) { + if (PyDict_Pop(sd, key, NULL) < 0) { return -1; } - Py_DECREF(v); return 0; } else { @@ -180,9 +192,7 @@ static int sys_audit_tstate(PyThreadState *ts, const char *event, const char *argFormat, va_list vargs) { - /* N format is inappropriate, because you do not know - whether the reference is consumed by the call. - Assert rather than exception for perf reasons */ + assert(event != NULL); assert(!argFormat || !strchr(argFormat, 'N')); if (!ts) { @@ -327,6 +337,21 @@ PySys_Audit(const char *event, const char *argFormat, ...) return res; } +int +PySys_AuditTuple(const char *event, PyObject *args) +{ + if (args == NULL) { + return PySys_Audit(event, NULL); + } + + if (!PyTuple_Check(args)) { + PyErr_Format(PyExc_TypeError, "args must be tuple, got %s", + Py_TYPE(args)->tp_name); + return -1; + } + return PySys_Audit(event, "O", args); +} + /* We expose this function primarily for our own cleanup during * finalization. In general, it should not need to be called, * and as such the function is not exported. @@ -426,15 +451,9 @@ PySys_AddAuditHook(Py_AuditHookFunction hook, void *userData) e->hookCFunction = (Py_AuditHookFunction)hook; e->userData = userData; - if (runtime->audit_hooks.mutex == NULL) { - /* The runtime must not be initialized yet. */ - add_audit_hook_entry_unlocked(runtime, e); - } - else { - PyThread_acquire_lock(runtime->audit_hooks.mutex, WAIT_LOCK); - add_audit_hook_entry_unlocked(runtime, e); - PyThread_release_lock(runtime->audit_hooks.mutex); - } + PyMutex_Lock(&runtime->audit_hooks.mutex); + add_audit_hook_entry_unlocked(runtime, e); + PyMutex_Unlock(&runtime->audit_hooks.mutex); return 0; } @@ -498,6 +517,9 @@ sys_audit(PyObject *self, PyObject *const *args, Py_ssize_t argc) return NULL; } + assert(args[0] != NULL); + assert(PyUnicode_Check(args[0])); + if (!should_audit(tstate->interp)) { Py_RETURN_NONE; } @@ -961,6 +983,23 @@ sys_intern_impl(PyObject *module, PyObject *s) } +/*[clinic input] +sys._is_interned -> bool + + string: unicode + / + +Return True if the given string is "interned". +[clinic start generated code]*/ + +static int +sys__is_interned_impl(PyObject *module, PyObject *string) +/*[clinic end generated code: output=c3678267b4e9d7ed input=039843e17883b606]*/ +{ + return PyUnicode_CHECK_INTERNED(string); +} + + /* * Cached interned string objects used for calling the profile and * trace functions. @@ -1676,6 +1715,13 @@ static PyObject * sys__enablelegacywindowsfsencoding_impl(PyObject *module) /*[clinic end generated code: output=f5c3855b45e24fe9 input=2bfa931a20704492]*/ { + if (PyErr_WarnEx(PyExc_DeprecationWarning, + "sys._enablelegacywindowsfsencoding() is deprecated and will be " + "removed in Python 3.16. Use PYTHONLEGACYWINDOWSFSENCODING " + "instead.", 1)) + { + return NULL; + } if (_PyUnicode_EnableLegacyWindowsFSEncoding() < 0) { return NULL; } @@ -1954,7 +2000,7 @@ sys__getframe_impl(PyObject *module, int depth) /*[clinic end generated code: output=d438776c04d59804 input=c1be8a6464b11ee5]*/ { PyThreadState *tstate = _PyThreadState_GET(); - _PyInterpreterFrame *frame = tstate->cframe->current_frame; + _PyInterpreterFrame *frame = tstate->current_frame; if (frame != NULL) { while (depth > 0) { @@ -2030,11 +2076,6 @@ sys_call_tracing_impl(PyObject *module, PyObject *func, PyObject *funcargs) return _PyEval_CallTracing(func, funcargs); } - -#ifdef __cplusplus -extern "C" { -#endif - /*[clinic input] sys._debugmallocstats @@ -2063,10 +2104,6 @@ sys__debugmallocstats_impl(PyObject *module) extern PyObject *_Py_GetObjects(PyObject *, PyObject *); #endif -#ifdef __cplusplus -} -#endif - /*[clinic input] sys._clear_type_cache @@ -2095,35 +2132,36 @@ static PyObject * sys_is_finalizing_impl(PyObject *module) /*[clinic end generated code: output=735b5ff7962ab281 input=f0df747a039948a5]*/ { - return PyBool_FromLong(_Py_IsFinalizing()); + return PyBool_FromLong(Py_IsFinalizing()); } + #ifdef Py_STATS /*[clinic input] sys._stats_on -Turns on stats gathering (stats gathering is on by default). +Turns on stats gathering (stats gathering is off by default). [clinic start generated code]*/ static PyObject * sys__stats_on_impl(PyObject *module) -/*[clinic end generated code: output=aca53eafcbb4d9fe input=8ddc6df94e484f3a]*/ +/*[clinic end generated code: output=aca53eafcbb4d9fe input=43b5bfe145299e55]*/ { - _py_stats = &_py_stats_struct; + _Py_StatsOn(); Py_RETURN_NONE; } /*[clinic input] sys._stats_off -Turns off stats gathering (stats gathering is on by default). +Turns off stats gathering (stats gathering is off by default). [clinic start generated code]*/ static PyObject * sys__stats_off_impl(PyObject *module) -/*[clinic end generated code: output=1534c1ee63812214 input=b3e50e71ecf29f66]*/ +/*[clinic end generated code: output=1534c1ee63812214 input=d1a84c60c56cbce2]*/ { - _py_stats = NULL; + _Py_StatsOff(); Py_RETURN_NONE; } @@ -2142,21 +2180,23 @@ sys__stats_clear_impl(PyObject *module) } /*[clinic input] -sys._stats_dump +sys._stats_dump -> bool Dump stats to file, and clears the stats. + +Return False if no statistics were not dumped because stats gathering was off. [clinic start generated code]*/ -static PyObject * +static int sys__stats_dump_impl(PyObject *module) -/*[clinic end generated code: output=79f796fb2b4ddf05 input=92346f16d64f6f95]*/ +/*[clinic end generated code: output=6e346b4ba0de4489 input=31a489e39418b2a5]*/ { - _Py_PrintSpecializationStats(1); + int res = _Py_PrintSpecializationStats(1); _Py_StatsClear(); - Py_RETURN_NONE; + return res; } +#endif // Py_STATS -#endif #ifdef ANDROID_API_LEVEL /*[clinic input] @@ -2270,7 +2310,7 @@ sys__getframemodulename_impl(PyObject *module, int depth) if (PySys_Audit("sys._getframemodulename", "i", depth) < 0) { return NULL; } - _PyInterpreterFrame *f = _PyThreadState_GET()->cframe->current_frame; + _PyInterpreterFrame *f = _PyThreadState_GET()->current_frame; while (f && (_PyFrame_IsIncomplete(f) || depth-- > 0)) { f = f->previous; } @@ -2285,10 +2325,19 @@ sys__getframemodulename_impl(PyObject *module, int depth) return Py_NewRef(r); } +/*[clinic input] +sys._get_cpu_count_config -> int -#ifdef __cplusplus -extern "C" { -#endif +Private function for getting PyConfig.cpu_count +[clinic start generated code]*/ + +static int +sys__get_cpu_count_config_impl(PyObject *module) +/*[clinic end generated code: output=36611bb5efad16dc input=523e1ade2204084e]*/ +{ + const PyConfig *config = _Py_GetConfig(); + return config->cpu_count; +} static PerfMapState perf_map_state; @@ -2331,7 +2380,7 @@ PyAPI_FUNC(int) PyUnstable_WritePerfMapEntry( #ifndef MS_WINDOWS if (perf_map_state.perf_map == NULL) { int ret = PyUnstable_PerfMapState_Init(); - if(ret != 0){ + if (ret != 0){ return ret; } } @@ -2358,6 +2407,41 @@ PyAPI_FUNC(void) PyUnstable_PerfMapState_Fini(void) { #endif } +PyAPI_FUNC(int) PyUnstable_CopyPerfMapFile(const char* parent_filename) { +#ifndef MS_WINDOWS + FILE* from = fopen(parent_filename, "r"); + if (!from) { + return -1; + } + if (perf_map_state.perf_map == NULL) { + int ret = PyUnstable_PerfMapState_Init(); + if (ret != 0) { + return ret; + } + } + char buf[4096]; + PyThread_acquire_lock(perf_map_state.map_lock, 1); + int fflush_result = 0, result = 0; + while (1) { + size_t bytes_read = fread(buf, 1, sizeof(buf), from); + size_t bytes_written = fwrite(buf, 1, bytes_read, perf_map_state.perf_map); + fflush_result = fflush(perf_map_state.perf_map); + if (fflush_result != 0 || bytes_read == 0 || bytes_written < bytes_read) { + result = -1; + goto close_and_release; + } + if (bytes_read < sizeof(buf) && feof(from)) { + goto close_and_release; + } + } +close_and_release: + fclose(from); + PyThread_release_lock(perf_map_state.map_lock); + return result; +#endif + return 0; +} + #ifdef __cplusplus } #endif @@ -2396,6 +2480,7 @@ static PyMethodDef sys_methods[] = { SYS_GETWINDOWSVERSION_METHODDEF SYS__ENABLELEGACYWINDOWSFSENCODING_METHODDEF SYS_INTERN_METHODDEF + SYS__IS_INTERNED_METHODDEF SYS_IS_FINALIZING_METHODDEF SYS_MDEBUG_METHODDEF SYS_SETSWITCHINTERVAL_METHODDEF @@ -2428,6 +2513,7 @@ static PyMethodDef sys_methods[] = { SYS__STATS_CLEAR_METHODDEF SYS__STATS_DUMP_METHODDEF #endif + SYS__GET_CPU_COUNT_CONFIG_METHODDEF {NULL, NULL} // sentinel }; @@ -3490,7 +3576,9 @@ _PySys_UpdateConfig(PyThreadState *tstate) if (config->pycache_prefix != NULL) { SET_SYS_FROM_WSTR("pycache_prefix", config->pycache_prefix); } else { - PyDict_SetItemString(sysdict, "pycache_prefix", Py_None); + if (PyDict_SetItemString(sysdict, "pycache_prefix", Py_None) < 0) { + return -1; + } } COPY_LIST("argv", config->argv); @@ -3504,7 +3592,9 @@ _PySys_UpdateConfig(PyThreadState *tstate) SET_SYS_FROM_WSTR("_stdlib_dir", stdlibdir); } else { - PyDict_SetItemString(sysdict, "_stdlib_dir", Py_None); + if (PyDict_SetItemString(sysdict, "_stdlib_dir", Py_None) < 0) { + return -1; + } } #undef SET_SYS_FROM_WSTR @@ -3514,6 +3604,9 @@ _PySys_UpdateConfig(PyThreadState *tstate) // sys.flags PyObject *flags = _PySys_GetObject(interp, "flags"); // borrowed ref if (flags == NULL) { + if (!_PyErr_Occurred(tstate)) { + _PyErr_SetString(tstate, PyExc_RuntimeError, "lost sys.flags"); + } return -1; } if (set_flags_from_config(interp, flags) < 0) { diff --git a/Python/thread.c b/Python/thread.c index 7fc53f9b61360b..fefae8391617f7 100644 --- a/Python/thread.c +++ b/Python/thread.c @@ -6,17 +6,38 @@ Stuff shared by all thread_*.h files is collected here. */ #include "Python.h" +#include "pycore_ceval.h" // _PyEval_MakePendingCalls() #include "pycore_pystate.h" // _PyInterpreterState_GET() #include "pycore_structseq.h" // _PyStructSequence_FiniBuiltin() -#include "pycore_pythread.h" +#include "pycore_pythread.h" // _POSIX_THREADS #ifndef DONT_HAVE_STDIO_H -#include +# include #endif #include +// Define PY_TIMEOUT_MAX constant. +#ifdef _POSIX_THREADS + // PyThread_acquire_lock_timed() uses _PyTime_FromNanoseconds(us * 1000), + // convert microseconds to nanoseconds. +# define PY_TIMEOUT_MAX_VALUE (LLONG_MAX / 1000) +#elif defined (NT_THREADS) + // WaitForSingleObject() accepts timeout in milliseconds in the range + // [0; 0xFFFFFFFE] (DWORD type). INFINITE value (0xFFFFFFFF) means no + // timeout. 0xFFFFFFFE milliseconds is around 49.7 days. +# if 0xFFFFFFFELL < LLONG_MAX / 1000 +# define PY_TIMEOUT_MAX_VALUE (0xFFFFFFFELL * 1000) +# else +# define PY_TIMEOUT_MAX_VALUE LLONG_MAX +# endif +#else +# define PY_TIMEOUT_MAX_VALUE LLONG_MAX +#endif +const long long PY_TIMEOUT_MAX = PY_TIMEOUT_MAX_VALUE; + + static void PyThread__init_thread(void); /* Forward */ #define initialized _PyRuntime.threads.initialized @@ -72,6 +93,89 @@ PyThread_set_stacksize(size_t size) } +int +PyThread_ParseTimeoutArg(PyObject *arg, int blocking, PY_TIMEOUT_T *timeout_p) +{ + assert(_PyTime_FromSeconds(-1) == PyThread_UNSET_TIMEOUT); + if (arg == NULL || arg == Py_None) { + *timeout_p = blocking ? PyThread_UNSET_TIMEOUT : 0; + return 0; + } + if (!blocking) { + PyErr_SetString(PyExc_ValueError, + "can't specify a timeout for a non-blocking call"); + return -1; + } + + _PyTime_t timeout; + if (_PyTime_FromSecondsObject(&timeout, arg, _PyTime_ROUND_TIMEOUT) < 0) { + return -1; + } + if (timeout < 0) { + PyErr_SetString(PyExc_ValueError, + "timeout value must be a non-negative number"); + return -1; + } + + if (_PyTime_AsMicroseconds(timeout, + _PyTime_ROUND_TIMEOUT) > PY_TIMEOUT_MAX) { + PyErr_SetString(PyExc_OverflowError, + "timeout value is too large"); + return -1; + } + *timeout_p = timeout; + return 0; +} + +PyLockStatus +PyThread_acquire_lock_timed_with_retries(PyThread_type_lock lock, + PY_TIMEOUT_T timeout) +{ + PyThreadState *tstate = _PyThreadState_GET(); + _PyTime_t endtime = 0; + if (timeout > 0) { + endtime = _PyDeadline_Init(timeout); + } + + PyLockStatus r; + do { + _PyTime_t microseconds; + microseconds = _PyTime_AsMicroseconds(timeout, _PyTime_ROUND_CEILING); + + /* first a simple non-blocking try without releasing the GIL */ + r = PyThread_acquire_lock_timed(lock, 0, 0); + if (r == PY_LOCK_FAILURE && microseconds != 0) { + Py_BEGIN_ALLOW_THREADS + r = PyThread_acquire_lock_timed(lock, microseconds, 1); + Py_END_ALLOW_THREADS + } + + if (r == PY_LOCK_INTR) { + /* Run signal handlers if we were interrupted. Propagate + * exceptions from signal handlers, such as KeyboardInterrupt, by + * passing up PY_LOCK_INTR. */ + if (_PyEval_MakePendingCalls(tstate) < 0) { + return PY_LOCK_INTR; + } + + /* If we're using a timeout, recompute the timeout after processing + * signals, since those can take time. */ + if (timeout > 0) { + timeout = _PyDeadline_Get(endtime); + + /* Check for negative values, since those mean block forever. + */ + if (timeout < 0) { + r = PY_LOCK_FAILURE; + } + } + } + } while (r == PY_LOCK_INTR); /* Retry if we were interrupted. */ + + return r; +} + + /* Thread Specific Storage (TSS) API Cross-platform components of TSS API implementation. diff --git a/Python/thread_nt.h b/Python/thread_nt.h index 26f441bd6d3c56..14b9cddc24c0ec 100644 --- a/Python/thread_nt.h +++ b/Python/thread_nt.h @@ -182,9 +182,9 @@ bootstrap(void *call) return 0; } -unsigned long -PyThread_start_new_thread(void (*func)(void *), void *arg) -{ +int +PyThread_start_joinable_thread(void (*func)(void *), void *arg, + PyThread_ident_t* ident, PyThread_handle_t* handle) { HANDLE hThread; unsigned threadID; callobj *obj; @@ -194,7 +194,7 @@ PyThread_start_new_thread(void (*func)(void *), void *arg) obj = (callobj*)HeapAlloc(GetProcessHeap(), 0, sizeof(*obj)); if (!obj) - return PYTHREAD_INVALID_THREAD_ID; + return -1; obj->func = func; obj->arg = arg; PyThreadState *tstate = _PyThreadState_GET(); @@ -207,22 +207,51 @@ PyThread_start_new_thread(void (*func)(void *), void *arg) /* I've seen errno == EAGAIN here, which means "there are * too many threads". */ - int e = errno; - threadID = (unsigned)-1; HeapFree(GetProcessHeap(), 0, obj); + return -1; } - else { - CloseHandle(hThread); + *ident = threadID; + // The cast is safe since HANDLE is pointer-sized + *handle = (PyThread_handle_t) hThread; + return 0; +} + +unsigned long +PyThread_start_new_thread(void (*func)(void *), void *arg) { + PyThread_handle_t handle; + PyThread_ident_t ident; + if (PyThread_start_joinable_thread(func, arg, &ident, &handle)) { + return PYTHREAD_INVALID_THREAD_ID; } - return threadID; + CloseHandle((HANDLE) handle); + // The cast is safe since the ident is really an unsigned int + return (unsigned long) ident; +} + +int +PyThread_join_thread(PyThread_handle_t handle) { + HANDLE hThread = (HANDLE) handle; + int errored = (WaitForSingleObject(hThread, INFINITE) != WAIT_OBJECT_0); + CloseHandle(hThread); + return errored; +} + +int +PyThread_detach_thread(PyThread_handle_t handle) { + HANDLE hThread = (HANDLE) handle; + return (CloseHandle(hThread) == 0); +} + +void +PyThread_update_thread_after_fork(PyThread_ident_t* ident, PyThread_handle_t* handle) { } /* * Return the thread Id instead of a handle. The Id is said to uniquely identify the * thread in the system */ -unsigned long -PyThread_get_thread_ident(void) +PyThread_ident_t +PyThread_get_thread_ident_ex(void) { if (!initialized) PyThread_init_thread(); @@ -230,6 +259,13 @@ PyThread_get_thread_ident(void) return GetCurrentThreadId(); } +unsigned long +PyThread_get_thread_ident(void) +{ + return (unsigned long) PyThread_get_thread_ident_ex(); +} + + #ifdef PY_HAVE_THREAD_NATIVE_ID /* * Return the native Thread ID (TID) of the calling thread. diff --git a/Python/thread_pthread.h b/Python/thread_pthread.h index f96c57da64636d..fb3b79fc160502 100644 --- a/Python/thread_pthread.h +++ b/Python/thread_pthread.h @@ -1,4 +1,5 @@ -#include "pycore_interp.h" // _PyInterpreterState.threads.stacksize +#include "pycore_interp.h" // _PyInterpreterState.threads.stacksize +#include "pycore_pythread.h" // _POSIX_SEMAPHORES /* Posix threads interface */ @@ -19,6 +20,8 @@ # include /* syscall(SYS_gettid) */ #elif defined(__FreeBSD__) # include /* pthread_getthreadid_np() */ +#elif defined(__FreeBSD_kernel__) +# include /* syscall(SYS_thr_self) */ #elif defined(__OpenBSD__) # include /* getthrid() */ #elif defined(_AIX) @@ -84,10 +87,10 @@ /* On FreeBSD 4.x, _POSIX_SEMAPHORES is defined empty, so we need to add 0 to make it work there as well. */ #if (_POSIX_SEMAPHORES+0) == -1 -#define HAVE_BROKEN_POSIX_SEMAPHORES +# define HAVE_BROKEN_POSIX_SEMAPHORES #else -#include -#include +# include +# include #endif #endif @@ -234,8 +237,8 @@ pythread_wrapper(void *arg) return NULL; } -unsigned long -PyThread_start_new_thread(void (*func)(void *), void *arg) +static int +do_start_joinable_thread(void (*func)(void *), void *arg, pthread_t* out_id) { pthread_t th; int status; @@ -251,7 +254,7 @@ PyThread_start_new_thread(void (*func)(void *), void *arg) #if defined(THREAD_STACK_SIZE) || defined(PTHREAD_SYSTEM_SCHED_SUPPORTED) if (pthread_attr_init(&attrs) != 0) - return PYTHREAD_INVALID_THREAD_ID; + return -1; #endif #if defined(THREAD_STACK_SIZE) PyThreadState *tstate = _PyThreadState_GET(); @@ -260,7 +263,7 @@ PyThread_start_new_thread(void (*func)(void *), void *arg) if (tss != 0) { if (pthread_attr_setstacksize(&attrs, tss) != 0) { pthread_attr_destroy(&attrs); - return PYTHREAD_INVALID_THREAD_ID; + return -1; } } #endif @@ -271,7 +274,7 @@ PyThread_start_new_thread(void (*func)(void *), void *arg) pythread_callback *callback = PyMem_RawMalloc(sizeof(pythread_callback)); if (callback == NULL) { - return PYTHREAD_INVALID_THREAD_ID; + return -1; } callback->func = func; @@ -291,11 +294,34 @@ PyThread_start_new_thread(void (*func)(void *), void *arg) if (status != 0) { PyMem_RawFree(callback); - return PYTHREAD_INVALID_THREAD_ID; + return -1; } + *out_id = th; + return 0; +} - pthread_detach(th); +int +PyThread_start_joinable_thread(void (*func)(void *), void *arg, + PyThread_ident_t* ident, PyThread_handle_t* handle) { + pthread_t th = (pthread_t) 0; + if (do_start_joinable_thread(func, arg, &th)) { + return -1; + } + *ident = (PyThread_ident_t) th; + *handle = (PyThread_handle_t) th; + assert(th == (pthread_t) *ident); + assert(th == (pthread_t) *handle); + return 0; +} +unsigned long +PyThread_start_new_thread(void (*func)(void *), void *arg) +{ + pthread_t th = (pthread_t) 0; + if (do_start_joinable_thread(func, arg, &th)) { + return PYTHREAD_INVALID_THREAD_ID; + } + pthread_detach(th); #if SIZEOF_PTHREAD_T <= SIZEOF_LONG return (unsigned long) th; #else @@ -303,20 +329,46 @@ PyThread_start_new_thread(void (*func)(void *), void *arg) #endif } +int +PyThread_join_thread(PyThread_handle_t th) { + return pthread_join((pthread_t) th, NULL); +} + +int +PyThread_detach_thread(PyThread_handle_t th) { + return pthread_detach((pthread_t) th); +} + +void +PyThread_update_thread_after_fork(PyThread_ident_t* ident, PyThread_handle_t* handle) { + // The thread id might have been updated in the forked child + pthread_t th = pthread_self(); + *ident = (PyThread_ident_t) th; + *handle = (PyThread_handle_t) th; + assert(th == (pthread_t) *ident); + assert(th == (pthread_t) *handle); +} + /* XXX This implementation is considered (to quote Tim Peters) "inherently hosed" because: - It does not guarantee the promise that a non-zero integer is returned. - The cast to unsigned long is inherently unsafe. - It is not clear that the 'volatile' (for AIX?) are any longer necessary. */ -unsigned long -PyThread_get_thread_ident(void) -{ +PyThread_ident_t +PyThread_get_thread_ident_ex(void) { volatile pthread_t threadid; if (!initialized) PyThread_init_thread(); threadid = pthread_self(); - return (unsigned long) threadid; + assert(threadid == (pthread_t) (PyThread_ident_t) threadid); + return (PyThread_ident_t) threadid; +} + +unsigned long +PyThread_get_thread_ident(void) +{ + return (unsigned long) PyThread_get_thread_ident_ex(); } #ifdef PY_HAVE_THREAD_NATIVE_ID @@ -334,6 +386,9 @@ PyThread_get_thread_native_id(void) #elif defined(__FreeBSD__) int native_id; native_id = pthread_getthreadid_np(); +#elif defined(__FreeBSD_kernel__) + long native_id; + syscall(SYS_thr_self, &native_id); #elif defined(__OpenBSD__) pid_t native_id; native_id = getthrid(); diff --git a/Python/thread_pthread_stubs.h b/Python/thread_pthread_stubs.h index 56e5b6141924b4..4741e594e52e65 100644 --- a/Python/thread_pthread_stubs.h +++ b/Python/thread_pthread_stubs.h @@ -40,7 +40,7 @@ pthread_cond_init(pthread_cond_t *restrict cond, return 0; } -PyAPI_FUNC(int)pthread_cond_destroy(pthread_cond_t *cond) +PyAPI_FUNC(int) pthread_cond_destroy(pthread_cond_t *cond) { return 0; } @@ -94,6 +94,15 @@ pthread_detach(pthread_t thread) return 0; } +int +pthread_join(pthread_t thread, void** value_ptr) +{ + if (value_ptr) { + *value_ptr = NULL; + } + return 0; +} + PyAPI_FUNC(pthread_t) pthread_self(void) { return 0; diff --git a/Python/traceback.c b/Python/traceback.c index ca524b1b9af78b..abd429ac6c1f71 100644 --- a/Python/traceback.c +++ b/Python/traceback.c @@ -3,9 +3,9 @@ #include "Python.h" -#include "pycore_ast.h" // asdl_seq_* +#include "pycore_ast.h" // asdl_seq_GET() #include "pycore_call.h" // _PyObject_CallMethodFormat() -#include "pycore_compile.h" // _PyAST_Optimize +#include "pycore_compile.h" // _PyAST_Optimize() #include "pycore_fileutils.h" // _Py_BEGIN_SUPPRESS_IPH #include "pycore_frame.h" // _PyFrame_GetCode() #include "pycore_interp.h" // PyInterpreterState.gc @@ -13,24 +13,25 @@ #include "pycore_pyarena.h" // _PyArena_Free() #include "pycore_pyerrors.h" // _PyErr_GetRaisedException() #include "pycore_pystate.h" // _PyThreadState_GET() +#include "pycore_sysmodule.h" // _PySys_GetAttr() #include "pycore_traceback.h" // EXCEPTION_TB_HEADER -#include "../Parser/pegen.h" // _PyPegen_byte_offset_to_character_offset() #include "frameobject.h" // PyFrame_New() #include "osdefs.h" // SEP -#ifdef HAVE_FCNTL_H -# include +#ifdef HAVE_UNISTD_H +# include // lseek() #endif + #define OFF(x) offsetof(PyTracebackObject, x) +#define PUTS(fd, str) (void)_Py_write_noraise(fd, str, (int)strlen(str)) -#define PUTS(fd, str) _Py_write_noraise(fd, str, (int)strlen(str)) #define MAX_STRING_LENGTH 500 #define MAX_FRAME_DEPTH 100 #define MAX_NTHREADS 100 -/* Function from Parser/tokenizer.c */ +/* Function from Parser/tokenizer/file_tokenizer.c */ extern char* _PyTokenizer_FindEncodingFilename(int, PyObject *); /*[clinic input] @@ -107,6 +108,26 @@ tb_next_get(PyTracebackObject *self, void *Py_UNUSED(_)) return Py_NewRef(ret); } +static int +tb_get_lineno(PyTracebackObject* tb) { + _PyInterpreterFrame* frame = tb->tb_frame->f_frame; + assert(frame != NULL); + return PyCode_Addr2Line(_PyFrame_GetCode(frame), tb->tb_lasti); +} + +static PyObject * +tb_lineno_get(PyTracebackObject *self, void *Py_UNUSED(_)) +{ + int lineno = self->tb_lineno; + if (lineno == -1) { + lineno = tb_get_lineno(self); + if (lineno < 0) { + Py_RETURN_NONE; + } + } + return PyLong_FromLong(lineno); +} + static int tb_next_set(PyTracebackObject *self, PyObject *new_next, void *Py_UNUSED(_)) { @@ -150,12 +171,12 @@ static PyMethodDef tb_methods[] = { static PyMemberDef tb_memberlist[] = { {"tb_frame", _Py_T_OBJECT, OFF(tb_frame), Py_READONLY|Py_AUDIT_READ}, {"tb_lasti", Py_T_INT, OFF(tb_lasti), Py_READONLY}, - {"tb_lineno", Py_T_INT, OFF(tb_lineno), Py_READONLY}, {NULL} /* Sentinel */ }; static PyGetSetDef tb_getsetters[] = { {"tb_next", (getter)tb_next_get, (setter)tb_next_set, NULL, NULL}, + {"tb_lineno", (getter)tb_lineno_get, NULL, NULL, NULL}, {NULL} /* Sentinel */ }; @@ -234,8 +255,7 @@ _PyTraceBack_FromFrame(PyObject *tb_next, PyFrameObject *frame) assert(tb_next == NULL || PyTraceBack_Check(tb_next)); assert(frame != NULL); int addr = _PyInterpreterFrame_LASTI(frame->f_frame) * sizeof(_Py_CODEUNIT); - return tb_create_raw((PyTracebackObject *)tb_next, frame, addr, - PyFrame_GetLineNumber(frame)); + return tb_create_raw((PyTracebackObject *)tb_next, frame, addr, -1); } @@ -395,27 +415,9 @@ _Py_WriteIndent(int indent, PyObject *f) return 0; } -/* Writes indent spaces, followed by the margin if it is not `\0`. - Returns 0 on success and non-zero on failure. - */ -int -_Py_WriteIndentedMargin(int indent, const char *margin, PyObject *f) -{ - if (_Py_WriteIndent(indent, f) < 0) { - return -1; - } - if (margin) { - if (PyFile_WriteString(margin, f) < 0) { - return -1; - } - } - return 0; -} - static int -display_source_line_with_margin(PyObject *f, PyObject *filename, int lineno, int indent, - int margin_indent, const char *margin, - int *truncation, PyObject **line) +display_source_line(PyObject *f, PyObject *filename, int lineno, int indent, + int *truncation, PyObject **line) { int fd; int i; @@ -543,10 +545,6 @@ display_source_line_with_margin(PyObject *f, PyObject *filename, int lineno, int *truncation = i - indent; } - if (_Py_WriteIndentedMargin(margin_indent, margin, f) < 0) { - goto error; - } - /* Write some spaces before the line */ if (_Py_WriteIndent(indent, f) < 0) { goto error; @@ -572,144 +570,11 @@ int _Py_DisplaySourceLine(PyObject *f, PyObject *filename, int lineno, int indent, int *truncation, PyObject **line) { - return display_source_line_with_margin(f, filename, lineno, indent, 0, - NULL, truncation, line); + return display_source_line(f, filename, lineno, indent, truncation, line); } -/* AST based Traceback Specialization - * - * When displaying a new traceback line, for certain syntactical constructs - * (e.g a subscript, an arithmetic operation) we try to create a representation - * that separates the primary source of error from the rest. - * - * Example specialization of BinOp nodes: - * Traceback (most recent call last): - * File "/home/isidentical/cpython/cpython/t.py", line 10, in - * add_values(1, 2, 'x', 3, 4) - * File "/home/isidentical/cpython/cpython/t.py", line 2, in add_values - * return a + b + c + d + e - * ~~~~~~^~~ - * TypeError: 'NoneType' object is not subscriptable - */ #define IS_WHITESPACE(c) (((c) == ' ') || ((c) == '\t') || ((c) == '\f')) - -static int -extract_anchors_from_expr(const char *segment_str, expr_ty expr, Py_ssize_t *left_anchor, Py_ssize_t *right_anchor, - char** primary_error_char, char** secondary_error_char) -{ - switch (expr->kind) { - case BinOp_kind: { - expr_ty left = expr->v.BinOp.left; - expr_ty right = expr->v.BinOp.right; - for (int i = left->end_col_offset; i < right->col_offset; i++) { - if (IS_WHITESPACE(segment_str[i])) { - continue; - } - - *left_anchor = i; - *right_anchor = i + 1; - - // Check whether if this a two-character operator (e.g //) - if (i + 1 < right->col_offset && !IS_WHITESPACE(segment_str[i + 1])) { - ++*right_anchor; - } - - // Set the error characters - *primary_error_char = "~"; - *secondary_error_char = "^"; - break; - } - return 1; - } - case Subscript_kind: { - *left_anchor = expr->v.Subscript.value->end_col_offset; - *right_anchor = expr->v.Subscript.slice->end_col_offset + 1; - - // Set the error characters - *primary_error_char = "~"; - *secondary_error_char = "^"; - return 1; - } - default: - return 0; - } -} - -static int -extract_anchors_from_stmt(const char *segment_str, stmt_ty statement, Py_ssize_t *left_anchor, Py_ssize_t *right_anchor, - char** primary_error_char, char** secondary_error_char) -{ - switch (statement->kind) { - case Expr_kind: { - return extract_anchors_from_expr(segment_str, statement->v.Expr.value, left_anchor, right_anchor, - primary_error_char, secondary_error_char); - } - default: - return 0; - } -} - -static int -extract_anchors_from_line(PyObject *filename, PyObject *line, - Py_ssize_t start_offset, Py_ssize_t end_offset, - Py_ssize_t *left_anchor, Py_ssize_t *right_anchor, - char** primary_error_char, char** secondary_error_char) -{ - int res = -1; - PyArena *arena = NULL; - PyObject *segment = PyUnicode_Substring(line, start_offset, end_offset); - if (!segment) { - goto done; - } - - const char *segment_str = PyUnicode_AsUTF8(segment); - if (!segment_str) { - goto done; - } - - arena = _PyArena_New(); - if (!arena) { - goto done; - } - - PyCompilerFlags flags = _PyCompilerFlags_INIT; - - mod_ty module = _PyParser_ASTFromString(segment_str, filename, Py_file_input, - &flags, arena); - if (!module) { - goto done; - } - if (!_PyAST_Optimize(module, arena, _Py_GetConfig()->optimization_level, 0)) { - goto done; - } - - assert(module->kind == Module_kind); - if (asdl_seq_LEN(module->v.Module.body) == 1) { - stmt_ty statement = asdl_seq_GET(module->v.Module.body, 0); - res = extract_anchors_from_stmt(segment_str, statement, left_anchor, right_anchor, - primary_error_char, secondary_error_char); - } else { - res = 0; - } - -done: - if (res > 0) { - // Normalize the AST offsets to byte offsets and adjust them with the - // start of the actual line (instead of the source code segment). - assert(segment != NULL); - assert(*left_anchor >= 0); - assert(*right_anchor >= 0); - *left_anchor = _PyPegen_byte_offset_to_character_offset(segment, *left_anchor) + start_offset; - *right_anchor = _PyPegen_byte_offset_to_character_offset(segment, *right_anchor) + start_offset; - } - Py_XDECREF(segment); - if (arena) { - _PyArena_Free(arena); - } - return res; -} - #define _TRACEBACK_SOURCE_LINE_INDENT 4 static inline int @@ -723,42 +588,14 @@ ignore_source_errors(void) { return 0; } -static inline int -print_error_location_carets(PyObject *f, int offset, Py_ssize_t start_offset, Py_ssize_t end_offset, - Py_ssize_t right_start_offset, Py_ssize_t left_end_offset, - const char *primary, const char *secondary) { - int special_chars = (left_end_offset != -1 || right_start_offset != -1); - const char *str; - while (++offset <= end_offset) { - if (offset <= start_offset) { - str = " "; - } else if (special_chars && left_end_offset < offset && offset <= right_start_offset) { - str = secondary; - } else { - str = primary; - } - if (PyFile_WriteString(str, f) < 0) { - return -1; - } - } - if (PyFile_WriteString("\n", f) < 0) { - return -1; - } - return 0; -} - static int tb_displayline(PyTracebackObject* tb, PyObject *f, PyObject *filename, int lineno, - PyFrameObject *frame, PyObject *name, int margin_indent, const char *margin) + PyFrameObject *frame, PyObject *name) { if (filename == NULL || name == NULL) { return -1; } - if (_Py_WriteIndentedMargin(margin_indent, margin, f) < 0) { - return -1; - } - PyObject *line = PyUnicode_FromFormat(" File \"%U\", line %d, in %U\n", filename, lineno, name); if (line == NULL) { @@ -775,118 +612,13 @@ tb_displayline(PyTracebackObject* tb, PyObject *f, PyObject *filename, int linen int truncation = _TRACEBACK_SOURCE_LINE_INDENT; PyObject* source_line = NULL; - int rc = display_source_line_with_margin( + int rc = display_source_line( f, filename, lineno, _TRACEBACK_SOURCE_LINE_INDENT, - margin_indent, margin, &truncation, &source_line); + &truncation, &source_line); if (rc != 0 || !source_line) { /* ignore errors since we can't report them, can we? */ err = ignore_source_errors(); - goto done; - } - - int code_offset = tb->tb_lasti; - PyCodeObject* code = _PyFrame_GetCode(frame->f_frame); - const Py_ssize_t source_line_len = PyUnicode_GET_LENGTH(source_line); - - int start_line; - int end_line; - int start_col_byte_offset; - int end_col_byte_offset; - if (!PyCode_Addr2Location(code, code_offset, &start_line, &start_col_byte_offset, - &end_line, &end_col_byte_offset)) { - goto done; - } - - if (start_line < 0 || end_line < 0 - || start_col_byte_offset < 0 - || end_col_byte_offset < 0) - { - goto done; - } - - // When displaying errors, we will use the following generic structure: - // - // ERROR LINE ERROR LINE ERROR LINE ERROR LINE ERROR LINE ERROR LINE ERROR LINE - // ~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^~~~~~~~~~~~~~~~~~~~ - // | |-> left_end_offset | |-> end_offset - // |-> start_offset |-> right_start_offset - // - // In general we will only have (start_offset, end_offset) but we can gather more information - // by analyzing the AST of the text between *start_offset* and *end_offset*. If this succeeds - // we could get *left_end_offset* and *right_start_offset* and some selection of characters for - // the different ranges (primary_error_char and secondary_error_char). If we cannot obtain the - // AST information or we cannot identify special ranges within it, then left_end_offset and - // right_end_offset will be set to -1. - // - // To keep the column indicators pertinent, they are not shown when the primary character - // spans the whole line. - - // Convert the utf-8 byte offset to the actual character offset so we print the right number of carets. - assert(source_line); - Py_ssize_t start_offset = _PyPegen_byte_offset_to_character_offset(source_line, start_col_byte_offset); - if (start_offset < 0) { - err = ignore_source_errors() < 0; - goto done; - } - - Py_ssize_t end_offset = _PyPegen_byte_offset_to_character_offset(source_line, end_col_byte_offset); - if (end_offset < 0) { - err = ignore_source_errors() < 0; - goto done; - } - - Py_ssize_t left_end_offset = -1; - Py_ssize_t right_start_offset = -1; - - char *primary_error_char = "^"; - char *secondary_error_char = primary_error_char; - - if (start_line == end_line) { - int res = extract_anchors_from_line(filename, source_line, start_offset, end_offset, - &left_end_offset, &right_start_offset, - &primary_error_char, &secondary_error_char); - if (res < 0 && ignore_source_errors() < 0) { - goto done; - } - } - else { - // If this is a multi-line expression, then we will highlight until - // the last non-whitespace character. - const char *source_line_str = PyUnicode_AsUTF8(source_line); - if (!source_line_str) { - goto done; - } - - Py_ssize_t i = source_line_len; - while (--i >= 0) { - if (!IS_WHITESPACE(source_line_str[i])) { - break; - } - } - - end_offset = i + 1; - } - - // Elide indicators if primary char spans the frame line - Py_ssize_t stripped_line_len = source_line_len - truncation - _TRACEBACK_SOURCE_LINE_INDENT; - bool has_secondary_ranges = (left_end_offset != -1 || right_start_offset != -1); - if (end_offset - start_offset == stripped_line_len && !has_secondary_ranges) { - goto done; } - - if (_Py_WriteIndentedMargin(margin_indent, margin, f) < 0) { - err = -1; - goto done; - } - - if (print_error_location_carets(f, truncation, start_offset, end_offset, - right_start_offset, left_end_offset, - primary_error_char, secondary_error_char) < 0) { - err = -1; - goto done; - } - -done: Py_XDECREF(source_line); return err; } @@ -911,8 +643,7 @@ tb_print_line_repeated(PyObject *f, long cnt) } static int -tb_printinternal(PyTracebackObject *tb, PyObject *f, long limit, - int indent, const char *margin) +tb_printinternal(PyTracebackObject *tb, PyObject *f, long limit) { PyCodeObject *code = NULL; Py_ssize_t depth = 0; @@ -931,9 +662,13 @@ tb_printinternal(PyTracebackObject *tb, PyObject *f, long limit, } while (tb != NULL) { code = PyFrame_GetCode(tb->tb_frame); + int tb_lineno = tb->tb_lineno; + if (tb_lineno == -1) { + tb_lineno = tb_get_lineno(tb); + } if (last_file == NULL || code->co_filename != last_file || - last_line == -1 || tb->tb_lineno != last_line || + last_line == -1 || tb_lineno != last_line || last_name == NULL || code->co_name != last_name) { if (cnt > TB_RECURSIVE_CUTOFF) { if (tb_print_line_repeated(f, cnt) < 0) { @@ -941,14 +676,14 @@ tb_printinternal(PyTracebackObject *tb, PyObject *f, long limit, } } last_file = code->co_filename; - last_line = tb->tb_lineno; + last_line = tb_lineno; last_name = code->co_name; cnt = 0; } cnt++; if (cnt <= TB_RECURSIVE_CUTOFF) { - if (tb_displayline(tb, f, code->co_filename, tb->tb_lineno, - tb->tb_frame, code->co_name, indent, margin) < 0) { + if (tb_displayline(tb, f, code->co_filename, tb_lineno, + tb->tb_frame, code->co_name) < 0) { goto error; } @@ -973,8 +708,7 @@ tb_printinternal(PyTracebackObject *tb, PyObject *f, long limit, #define PyTraceBack_LIMIT 1000 int -_PyTraceBack_Print_Indented(PyObject *v, int indent, const char *margin, - const char *header_margin, const char *header, PyObject *f) +_PyTraceBack_Print(PyObject *v, const char *header, PyObject *f) { PyObject *limitv; long limit = PyTraceBack_LIMIT; @@ -997,15 +731,12 @@ _PyTraceBack_Print_Indented(PyObject *v, int indent, const char *margin, return 0; } } - if (_Py_WriteIndentedMargin(indent, header_margin, f) < 0) { - return -1; - } if (PyFile_WriteString(header, f) < 0) { return -1; } - if (tb_printinternal((PyTracebackObject *)v, f, limit, indent, margin) < 0) { + if (tb_printinternal((PyTracebackObject *)v, f, limit) < 0) { return -1; } @@ -1015,12 +746,8 @@ _PyTraceBack_Print_Indented(PyObject *v, int indent, const char *margin, int PyTraceBack_Print(PyObject *v, PyObject *f) { - int indent = 0; - const char *margin = NULL; - const char *header_margin = NULL; const char *header = EXCEPTION_TB_HEADER; - - return _PyTraceBack_Print_Indented(v, indent, margin, header_margin, header, f); + return _PyTraceBack_Print(v, header, f); } /* Format an integer in range [0; 0xffffffff] to decimal and write it @@ -1047,7 +774,7 @@ _Py_DumpDecimal(int fd, size_t value) value /= 10; } while (value); - _Py_write_noraise(fd, ptr, end - ptr); + (void)_Py_write_noraise(fd, ptr, end - ptr); } /* Format an integer as hexadecimal with width digits into fd file descriptor. @@ -1072,7 +799,7 @@ _Py_DumpHexadecimal(int fd, uintptr_t value, Py_ssize_t width) value >>= 4; } while ((end - ptr) < width || value); - _Py_write_noraise(fd, ptr, end - ptr); + (void)_Py_write_noraise(fd, ptr, end - ptr); } void @@ -1125,7 +852,7 @@ _Py_DumpASCII(int fd, PyObject *text) } if (!need_escape) { // The string can be written with a single write() syscall - _Py_write_noraise(fd, str, size); + (void)_Py_write_noraise(fd, str, size); goto done; } } @@ -1135,7 +862,7 @@ _Py_DumpASCII(int fd, PyObject *text) if (' ' <= ch && ch <= 126) { /* printable ASCII character */ char c = (char)ch; - _Py_write_noraise(fd, &c, 1); + (void)_Py_write_noraise(fd, &c, 1); } else if (ch <= 0xff) { PUTS(fd, "\\x"); @@ -1197,23 +924,45 @@ dump_frame(int fd, _PyInterpreterFrame *frame) PUTS(fd, "\n"); } +static int +tstate_is_freed(PyThreadState *tstate) +{ + if (_PyMem_IsPtrFreed(tstate)) { + return 1; + } + if (_PyMem_IsPtrFreed(tstate->interp)) { + return 1; + } + return 0; +} + + +static int +interp_is_freed(PyInterpreterState *interp) +{ + return _PyMem_IsPtrFreed(interp); +} + + static void dump_traceback(int fd, PyThreadState *tstate, int write_header) { - _PyInterpreterFrame *frame; - unsigned int depth; - if (write_header) { PUTS(fd, "Stack (most recent call first):\n"); } - frame = tstate->cframe->current_frame; + if (tstate_is_freed(tstate)) { + PUTS(fd, " \n"); + return; + } + + _PyInterpreterFrame *frame = tstate->current_frame; if (frame == NULL) { PUTS(fd, " \n"); return; } - depth = 0; + unsigned int depth = 0; while (1) { if (MAX_FRAME_DEPTH <= depth) { PUTS(fd, " ...\n"); @@ -1277,9 +1026,6 @@ const char* _Py_DumpTracebackThreads(int fd, PyInterpreterState *interp, PyThreadState *current_tstate) { - PyThreadState *tstate; - unsigned int nthreads; - if (current_tstate == NULL) { /* _Py_DumpTracebackThreads() is called from signal handlers by faulthandler. @@ -1295,6 +1041,10 @@ _Py_DumpTracebackThreads(int fd, PyInterpreterState *interp, current_tstate = PyGILState_GetThisThreadState(); } + if (current_tstate != NULL && tstate_is_freed(current_tstate)) { + return "tstate is freed"; + } + if (interp == NULL) { if (current_tstate == NULL) { interp = _PyGILState_GetInterpreterStateUnsafe(); @@ -1309,14 +1059,18 @@ _Py_DumpTracebackThreads(int fd, PyInterpreterState *interp, } assert(interp != NULL); + if (interp_is_freed(interp)) { + return "interp is freed"; + } + /* Get the current interpreter from the current thread */ - tstate = PyInterpreterState_ThreadHead(interp); + PyThreadState *tstate = PyInterpreterState_ThreadHead(interp); if (tstate == NULL) return "unable to get the thread head state"; /* Dump the traceback of each thread */ tstate = PyInterpreterState_ThreadHead(interp); - nthreads = 0; + unsigned int nthreads = 0; _Py_BEGIN_SUPPRESS_IPH do { diff --git a/Python/tracemalloc.c b/Python/tracemalloc.c index f8ad939dccaccd..19b64c619feb6a 100644 --- a/Python/tracemalloc.c +++ b/Python/tracemalloc.c @@ -2,11 +2,12 @@ #include "pycore_fileutils.h" // _Py_write_noraise() #include "pycore_gc.h" // PyGC_Head #include "pycore_hashtable.h" // _Py_hashtable_t -#include "pycore_object.h" // _PyType_PreHeaderSize +#include "pycore_object.h" // _PyType_PreHeaderSize() #include "pycore_pymem.h" // _Py_tracemalloc_config #include "pycore_runtime.h" // _Py_ID() -#include "pycore_traceback.h" +#include "pycore_traceback.h" // _Py_DumpASCII() #include + #include "frameobject.h" // _PyInterpreterFrame_GetLine #include // malloc() @@ -1247,7 +1248,7 @@ tracemalloc_get_traceback(unsigned int domain, uintptr_t ptr) } -#define PUTS(fd, str) _Py_write_noraise(fd, str, (int)strlen(str)) +#define PUTS(fd, str) (void)_Py_write_noraise(fd, str, (int)strlen(str)) static void _PyMem_DumpFrame(int fd, frame_t * frame) diff --git a/Python/vm-state.md b/Python/vm-state.md new file mode 100644 index 00000000000000..4c68ba3b575cc8 --- /dev/null +++ b/Python/vm-state.md @@ -0,0 +1,90 @@ +# Python VM State + +## Definition of Tiers + +- **Tier 1** is the classic Python bytecode interpreter. + This includes the specializing adaptive interpreter described in [PEP 659](https://peps.python.org/pep-0659/) and introduced in Python 3.11. +- **Tier 2**, also known as the micro-instruction ("uop") interpreter, is a new interpreter with a different instruction format. + It will be introduced in Python 3.13, and also forms the basis for a JIT using copy-and-patch technology that is likely to be introduced at the same time (but, unlike the Tier 2 interpreter, hasn't landed in the main branch yet). + +# Frame state + +Almost all interpreter state is nominally stored in the frame structure. +A pointer to the current frame is held in `frame`. It contains: + +- **local variables** (a.k.a. "fast locals") +- **evaluation stack** (tacked onto the end of the locals) +- **stack top** (an integer giving the top of the evaluation stack) +- **instruction pointer** +- **code object**, which holds things like the array of instructions, lists of constants and names referenced by certain instructions, the exception handling table, and the table that translates instruction offsets to line numbers +- **return offset**, only relevant during calls, telling the interpreter where to return + +There are some other fields in the frame structure of less importance; notably frames are linked together in a singly-linked list via the `previous` pointer, pointing from callee to caller. +The frame also holds a pointer to the current function, globals, builtins, and the locals converted to dict (used to support the `locals()` built-in). + +## Fast locals and evaluation stack + +The frame contains a single array of object pointers, `localsplus`, which contains both the fast locals and the stack. +The top of the stack, including the locals, is indicated by `stacktop`. +For example, in a function with three locals, if the stack contains one value, `frame->stacktop == 4`. + +The interpreters share an implementation which uses the same memory but caches the depth (as a pointer) in a C local, `stack_pointer`. +We aren't sure yet exactly how the JIT will implement the stack; likely some of the values near the top of the stack will be held in registers. + +## Instruction pointer + +The canonical, in-memory, representation of the instruction pointer is `frame->instr_ptr`. +It always points to an instruction in the bytecode array of the frame's code object. +Dispatching on `frame->instr_ptr` would be very inefficient, so in Tier 1 we cache the upcoming value of `frame->instr_ptr` in the C local `next_instr`. + +## Tier 2 + +- `stack_pointer` is the same as in Tier 1 (but may be different in the JIT). +- At runtime we do not need a cache representation of `frame->instr_ptr`, as all stores to `frame->instr_ptr` are explicit. +- During optimization we track the value of `frame->instr_ptr`, emitting `_SET_IP` whenever `frame->instr_ptr` would have been updated. + +The Tier 2 instruction pointer is strictly internal to the Tier 2 interpreter, so isn't visible to any other part of the code. + +## Unwinding + +Unwinding uses exception tables to find the next point at which normal execution can occur, or fail if there are no exception handlers. +During unwinding both the stack and the instruction pointer should be in their canonical, in-memory representation. + +## Jumps in bytecode + +The implementation of jumps within a single Tier 2 superblock/trace is just that, an implementation. +The implementation in the JIT and in the Tier 2 interpreter will necessarily be different. +What is in common is that representation in the Tier 2 optimizer. + +We need the following types of jumps: + +- Conditional branches within the superblock. These must only go forwards and be within the superblock. +- Terminal exits. These go back to the Tier 1 interpreter and cannot be modified. +- Loop end jumps. These go backwards, must be within the superblock, cannot be modified, and can only go to the start of the superblock. +- Patchable exits. These initially exit to code that tracks whether the exit is hot (presumably with a counter) and can be patched. + +Currently, we don't have patchable exits. +Patching exits should be fairly straightforward in the interpreter. +It will be more complex in the JIT. + +(We might also consider deoptimizations as a separate jump type.) + +# Thread state and interpreter state + +Another important piece of VM state is the **thread state**, held in `tstate`. +The current frame pointer, `frame`, is always equal to `tstate->current_frame`. +The thread state also holds the exception state (`tstate->exc_info`) and the recursion counters (`tstate->c_recursion_remaining` and `tstate->py_recursion_remaining`). + +The thread state is also used to access the **interpreter state** (`tstate->interp`), which is important since the "eval breaker" flags are stored there (`tstate->interp->ceval.eval_breaker`, an "atomic" variable), as well as the "PEP 523 function" (`tstate->interp->eval_frame`). +The interpreter state also holds the optimizer state (`optimizer` and some counters). +Note that the eval breaker may be moved to the thread state soon as part of the multicore (PEP 703) work. + +# Tier 2 IR format + +The tier 2 IR (Internal Representation) format is also the basis for the Tier 2 interpreter (though the two formats may eventually differ). This format is also used as the input to the machine code generator (the JIT compiler). + +Tier 2 IR entries are all the same size; there is no equivalent to `EXTENDED_ARG` or trailing inline cache entries. Each instruction is a struct with the following fields (all integers of varying sizes): + +- **opcode**: Sometimes the same as a Tier 1 opcode, sometimes a separate micro opcode. Tier 2 opcodes are 9 bits (as opposed to Tier 1 opcodes, which fit in 8 bits). By convention, Tier 2 opcode names start with `_`. +- **oparg**: The argument. Usually the same as the Tier 1 oparg after expansion of `EXTENDED_ARG` prefixes. Up to 32 bits. +- **operand**: An aditional argument, Typically the value of *one* cache item from the Tier 1 inline cache, up to 64 bits. diff --git a/README.rst b/README.rst index 4ab26565a13e03..9343c830ce1f0f 100644 --- a/README.rst +++ b/README.rst @@ -1,4 +1,4 @@ -This is Python version 3.13.0 alpha 0 +This is Python version 3.13.0 alpha 2 ===================================== .. image:: https://github.com/python/cpython/workflows/Tests/badge.svg @@ -76,6 +76,9 @@ to macOS framework and universal builds. Refer to `Mac/README.rst On Windows, see `PCbuild/readme.txt `_. +To build Windows installer, see `Tools/msi/README.txt +`_. + If you wish, you can create a subdirectory and invoke configure from there. For example:: @@ -177,7 +180,7 @@ is printed about a failed test or a traceback or core dump is produced, something is wrong. By default, tests are prevented from overusing resources like disk space and -memory. To enable these tests, run ``make testall``. +memory. To enable these tests, run ``make buildbottest``. If any tests fail, you can re-run the failing test(s) in verbose mode. For example, if ``test_os`` and ``test_gdb`` failed, you can run:: @@ -203,38 +206,14 @@ directories installed using ``make altinstall`` contain the major and minor version and can thus live side-by-side. ``make install`` also creates ``${prefix}/bin/python3`` which refers to ``${prefix}/bin/python3.X``. If you intend to install multiple versions using the same prefix you must decide which -version (if any) is your "primary" version. Install that version using ``make -install``. Install all other versions using ``make altinstall``. +version (if any) is your "primary" version. Install that version using +``make install``. Install all other versions using ``make altinstall``. For example, if you want to install Python 2.7, 3.6, and 3.13 with 3.13 being the primary version, you would execute ``make install`` in your 3.13 build directory and ``make altinstall`` in the others. -Issue Tracker and Mailing List ------------------------------- - -Bug reports are welcome! You can use Github to `report bugs -`_, and/or `submit pull requests -`_. - -You can also follow development discussion on the `python-dev mailing list -`_. - - -Proposals for enhancement -------------------------- - -If you have a proposal to change Python, you may want to send an email to the -`comp.lang.python`_ or `python-ideas`_ mailing lists for initial feedback. A -Python Enhancement Proposal (PEP) may be submitted if your idea gains ground. -All current PEPs, as well as guidelines for submitting a new PEP, are listed at -`peps.python.org `_. - -.. _python-ideas: https://mail.python.org/mailman/listinfo/python-ideas/ -.. _comp.lang.python: https://mail.python.org/mailman/listinfo/python-list - - Release Schedule ---------------- diff --git a/Tools/build/deepfreeze.py b/Tools/build/deepfreeze.py index a11fe6a62811ab..05633e3f77af49 100644 --- a/Tools/build/deepfreeze.py +++ b/Tools/build/deepfreeze.py @@ -6,7 +6,6 @@ by Python 3.10, and 3.11 features are not available. """ import argparse -import ast import builtins import collections import contextlib @@ -17,13 +16,13 @@ from typing import Dict, FrozenSet, TextIO, Tuple import umarshal -from generate_global_objects import get_identifiers_and_strings + +ROOT = os.path.dirname(os.path.dirname(os.path.dirname(__file__))) verbose = False -identifiers, strings = get_identifiers_and_strings() -# This must be kept in sync with opcode.py -RESUME = 151 +# This must be kept in sync with Tools/cases_generator/analyzer.py +RESUME = 149 def isprintable(b: bytes) -> bool: return all(0x20 <= c < 0x7f for c in b) @@ -114,13 +113,28 @@ def __init__(self, file: TextIO) -> None: self.hits, self.misses = 0, 0 self.finis: list[str] = [] self.inits: list[str] = [] + self.identifiers, self.strings = self.get_identifiers_and_strings() self.write('#include "Python.h"') + self.write('#include "internal/pycore_object.h"') self.write('#include "internal/pycore_gc.h"') self.write('#include "internal/pycore_code.h"') self.write('#include "internal/pycore_frame.h"') self.write('#include "internal/pycore_long.h"') self.write("") + def get_identifiers_and_strings(self) -> tuple[set[str], dict[str, str]]: + filename = os.path.join(ROOT, "Include", "internal", "pycore_global_strings.h") + with open(filename) as fp: + lines = fp.readlines() + identifiers: set[str] = set() + strings: dict[str, str] = {} + for line in lines: + if m := re.search(r"STRUCT_FOR_ID\((\w+)\)", line): + identifiers.add(m.group(1)) + if m := re.search(r'STRUCT_FOR_STR\((\w+), "(.*?)"\)', line): + strings[m.group(2)] = m.group(1) + return identifiers, strings + @contextlib.contextmanager def indent(self) -> None: save_level = self.level @@ -141,14 +155,10 @@ def block(self, prefix: str, suffix: str = "") -> None: self.write("}" + suffix) def object_head(self, typename: str) -> None: - with self.block(".ob_base =", ","): - self.write(f".ob_refcnt = _Py_IMMORTAL_REFCNT,") - self.write(f".ob_type = &{typename},") + self.write(f".ob_base = _PyObject_HEAD_INIT(&{typename}),") def object_var_head(self, typename: str, size: int) -> None: - with self.block(".ob_base =", ","): - self.object_head(typename) - self.write(f".ob_size = {size},") + self.write(f".ob_base = _PyVarObject_HEAD_INIT(&{typename}, {size}),") def field(self, obj: object, name: str) -> None: self.write(f".{name} = {getattr(obj, name)},") @@ -171,9 +181,9 @@ def generate_bytes(self, name: str, b: bytes) -> str: return f"& {name}.ob_base.ob_base" def generate_unicode(self, name: str, s: str) -> str: - if s in strings: - return f"&_Py_STR({strings[s]})" - if s in identifiers: + if s in self.strings: + return f"&_Py_STR({self.strings[s]})" + if s in self.identifiers: return f"&_Py_ID({s})" if len(s) == 1: c = ord(s) @@ -284,10 +294,12 @@ def generate_code(self, name: str, code: types.CodeType) -> str: self.write(f".co_linetable = {co_linetable},") self.write(f"._co_cached = NULL,") self.write(f".co_code_adaptive = {co_code_adaptive},") - for i, op in enumerate(code.co_code[::2]): + first_traceable = 0 + for op in code.co_code[::2]: if op == RESUME: - self.write(f"._co_firsttraceable = {i},") break + first_traceable += 1 + self.write(f"._co_firsttraceable = {first_traceable},") name_as_code = f"(PyCodeObject *)&{name}" self.finis.append(f"_PyStaticCode_Fini({name_as_code});") self.inits.append(f"_PyStaticCode_Init({name_as_code})") @@ -441,12 +453,10 @@ def is_frozen_header(source: str) -> bool: def decode_frozen_data(source: str) -> types.CodeType: - lines = source.splitlines() - while lines and re.match(FROZEN_DATA_LINE, lines[0]) is None: - del lines[0] - while lines and re.match(FROZEN_DATA_LINE, lines[-1]) is None: - del lines[-1] - values: Tuple[int, ...] = ast.literal_eval("".join(lines).strip()) + values: list[int] = [] + for line in source.splitlines(): + if re.match(FROZEN_DATA_LINE, line): + values.extend([int(x) for x in line.split(",") if x.strip()]) data = bytes(values) return umarshal.loads(data) @@ -478,7 +488,10 @@ def generate(args: list[str], output: TextIO) -> None: parser = argparse.ArgumentParser() parser.add_argument("-o", "--output", help="Defaults to deepfreeze.c", default="deepfreeze.c") parser.add_argument("-v", "--verbose", action="store_true", help="Print diagnostics") -parser.add_argument('args', nargs="+", help="Input file and module name (required) in file:modname format") +group = parser.add_mutually_exclusive_group(required=True) +group.add_argument("-f", "--file", help="read rule lines from a file") +group.add_argument('args', nargs="*", default=(), + help="Input file and module name (required) in file:modname format") @contextlib.contextmanager def report_time(label: str): @@ -496,9 +509,18 @@ def main() -> None: args = parser.parse_args() verbose = args.verbose output = args.output + + if args.file: + if verbose: + print(f"Reading targets from {args.file}") + with open(args.file, "rt", encoding="utf-8-sig") as fin: + rules = [x.strip() for x in fin] + else: + rules = args.args + with open(output, "w", encoding="utf-8") as file: with report_time("generate"): - generate(args.args, file) + generate(rules, file) if verbose: print(f"Wrote {os.path.getsize(output)} bytes to {output}") diff --git a/Tools/build/freeze_modules.py b/Tools/build/freeze_modules.py index ee4dd2f8682ba4..a541b4b33c519b 100644 --- a/Tools/build/freeze_modules.py +++ b/Tools/build/freeze_modules.py @@ -21,6 +21,7 @@ # .gitattributes and .gitignore files needs to be updated. FROZEN_MODULES_DIR = os.path.join(ROOT_DIR, 'Python', 'frozen_modules') DEEPFROZEN_MODULES_DIR = os.path.join(ROOT_DIR, 'Python', 'deepfreeze') +DEEPFREEZE_MAPPING_FNAME = 'deepfreeze_mappings.txt' FROZEN_FILE = os.path.join(ROOT_DIR, 'Python', 'frozen.c') MAKEFILE = os.path.join(ROOT_DIR, 'Makefile.pre.in') @@ -467,17 +468,27 @@ def replace_block(lines, start_marker, end_marker, replacements, file): return lines[:start_pos + 1] + replacements + lines[end_pos:] -def regen_frozen(modules, frozen_modules: bool): +class UniqueList(list): + def __init__(self): + self._seen = set() + + def append(self, item): + if item in self._seen: + return + super().append(item) + self._seen.add(item) + + +def regen_frozen(modules): headerlines = [] parentdir = os.path.dirname(FROZEN_FILE) - if frozen_modules: - for src in _iter_sources(modules): - # Adding a comment to separate sections here doesn't add much, - # so we don't. - header = relpath_for_posix_display(src.frozenfile, parentdir) - headerlines.append(f'#include "{header}"') - - externlines = [] + for src in _iter_sources(modules): + # Adding a comment to separate sections here doesn't add much, + # so we don't. + header = relpath_for_posix_display(src.frozenfile, parentdir) + headerlines.append(f'#include "{header}"') + + externlines = UniqueList() bootstraplines = [] stdliblines = [] testlines = [] @@ -504,14 +515,9 @@ def regen_frozen(modules, frozen_modules: bool): get_code_name = "_Py_get_%s_toplevel" % code_name externlines.append("extern PyObject *%s(void);" % get_code_name) - symbol = mod.symbol pkg = 'true' if mod.ispkg else 'false' - if not frozen_modules: - line = ('{"%s", NULL, 0, %s, GET_CODE(%s)},' - ) % (mod.name, pkg, code_name) - else: - line = ('{"%s", %s, (int)sizeof(%s), %s, GET_CODE(%s)},' - ) % (mod.name, symbol, symbol, pkg, code_name) + size = f"(int)sizeof({mod.symbol})" + line = f'{{"{mod.name}", {mod.symbol}, {size}, {pkg}}},' lines.append(line) if mod.isalias: @@ -585,7 +591,7 @@ def regen_makefile(modules): pyfiles = [] frozenfiles = [] rules = [''] - deepfreezerules = ["Python/deepfreeze/deepfreeze.c: $(DEEPFREEZE_DEPS)", + deepfreezerules = ["$(DEEPFREEZE_C): $(DEEPFREEZE_DEPS)", "\t$(PYTHON_FOR_FREEZE) $(srcdir)/Tools/build/deepfreeze.py \\"] for src in _iter_sources(modules): frozen_header = relpath_for_posix_display(src.frozenfile, ROOT_DIR) @@ -651,7 +657,9 @@ def regen_pcbuild(modules): projlines = [] filterlines = [] corelines = [] - deepfreezerules = ['\t'] + deepfreezemappings = [] for src in _iter_sources(modules): pyfile = relpath_for_windows_display(src.pyfile, ROOT_DIR) header = relpath_for_windows_display(src.frozenfile, ROOT_DIR) @@ -659,16 +667,15 @@ def regen_pcbuild(modules): projlines.append(f' ') projlines.append(f' {src.frozenid}') projlines.append(f' $(IntDir){intfile}') - projlines.append(f' $(PySourcePath){header}') + projlines.append(f' $(GeneratedFrozenModulesDir){header}') projlines.append(f' ') filterlines.append(f' ') filterlines.append(' Python Files') filterlines.append(' ') - deepfreezerules.append(f'\t\t "$(PySourcePath){header}:{src.frozenid}" ^') - deepfreezerules.append('\t\t "-o" "$(PySourcePath)Python\\deepfreeze\\deepfreeze.c"\'/>' ) + deepfreezemappings.append(f' \n') - corelines.append(f' ') + corelines.append(f' ') print(f'# Updating {os.path.relpath(PCBUILD_PROJECT)}') with updating_file_with_tmpfile(PCBUILD_PROJECT) as (infile, outfile): @@ -681,6 +688,26 @@ def regen_pcbuild(modules): PCBUILD_PROJECT, ) outfile.writelines(lines) + with updating_file_with_tmpfile(PCBUILD_PROJECT) as (infile, outfile): + lines = infile.readlines() + lines = replace_block( + lines, + '', + '', + deepfreezemappings, + PCBUILD_PROJECT, + ) + outfile.writelines(lines) + with updating_file_with_tmpfile(PCBUILD_PROJECT) as (infile, outfile): + lines = infile.readlines() + lines = replace_block( + lines, + '', + '', + [deepfreezemappingsfile, ], + PCBUILD_PROJECT, + ) + outfile.writelines(lines) with updating_file_with_tmpfile(PCBUILD_PROJECT) as (infile, outfile): lines = infile.readlines() lines = replace_block( @@ -718,20 +745,14 @@ def regen_pcbuild(modules): ####################################### # the script -parser = argparse.ArgumentParser() -parser.add_argument("--frozen-modules", action="store_true", - help="Use both frozen and deepfrozen modules. (default: uses only deepfrozen modules)") - def main(): - args = parser.parse_args() - frozen_modules: bool = args.frozen_modules # Expand the raw specs, preserving order. modules = list(parse_frozen_specs()) # Regen build-related files. regen_makefile(modules) regen_pcbuild(modules) - regen_frozen(modules, frozen_modules) + regen_frozen(modules) if __name__ == '__main__': diff --git a/Tools/build/generate_opcode_h.py b/Tools/build/generate_opcode_h.py deleted file mode 100644 index 3a817326c94cbb..00000000000000 --- a/Tools/build/generate_opcode_h.py +++ /dev/null @@ -1,171 +0,0 @@ -# This script generates the opcode.h header file. - -import sys -import tokenize - -SCRIPT_NAME = "Tools/build/generate_opcode_h.py" -PYTHON_OPCODE = "Lib/opcode.py" - -header = f""" -// Auto-generated by {SCRIPT_NAME} from {PYTHON_OPCODE} - -#ifndef Py_OPCODE_H -#define Py_OPCODE_H -#ifdef __cplusplus -extern "C" {{ -#endif - - -/* Instruction opcodes for compiled code */ -""".lstrip() - -footer = """ - -#ifdef __cplusplus -} -#endif -#endif /* !Py_OPCODE_H */ -""" - -internal_header = f""" -// Auto-generated by {SCRIPT_NAME} from {PYTHON_OPCODE} - -#ifndef Py_INTERNAL_OPCODE_H -#define Py_INTERNAL_OPCODE_H -#ifdef __cplusplus -extern "C" {{ -#endif - -#ifndef Py_BUILD_CORE -# error "this header requires Py_BUILD_CORE define" -#endif - -#include "opcode.h" -""".lstrip() - -internal_footer = """ -#ifdef __cplusplus -} -#endif -#endif // !Py_INTERNAL_OPCODE_H -""" - -DEFINE = "#define {:<38} {:>3}\n" - -UINT32_MASK = (1<<32)-1 - -def get_python_module_dict(filename): - mod = {} - with tokenize.open(filename) as fp: - code = fp.read() - exec(code, mod) - return mod - -def main(opcode_py, - _opcode_metadata_py='Lib/_opcode_metadata.py', - outfile='Include/opcode.h', - opcode_targets_h='Python/opcode_targets.h', - internaloutfile='Include/internal/pycore_opcode.h'): - - _opcode_metadata = get_python_module_dict(_opcode_metadata_py) - - opcode = get_python_module_dict(opcode_py) - opmap = opcode['opmap'] - opname = opcode['opname'] - - MIN_INSTRUMENTED_OPCODE = opcode["MIN_INSTRUMENTED_OPCODE"] - - NUM_OPCODES = len(opname) - used = [ False ] * len(opname) - next_op = 1 - - for name, op in opmap.items(): - used[op] = True - - specialized_opmap = {} - opname_including_specialized = opname.copy() - for name in _opcode_metadata['_specialized_instructions']: - while used[next_op]: - next_op += 1 - specialized_opmap[name] = next_op - opname_including_specialized[next_op] = name - used[next_op] = True - - with open(outfile, 'w') as fobj, open(internaloutfile, 'w') as iobj: - fobj.write(header) - iobj.write(internal_header) - - for name in opname: - if name in opmap: - op = opmap[name] - if op == MIN_INSTRUMENTED_OPCODE: - fobj.write(DEFINE.format("MIN_INSTRUMENTED_OPCODE", MIN_INSTRUMENTED_OPCODE)) - - fobj.write(DEFINE.format(name, op)) - - - for name, op in specialized_opmap.items(): - fobj.write(DEFINE.format(name, op)) - - iobj.write("\nextern const uint8_t _PyOpcode_Caches[256];\n") - iobj.write("\nextern const uint8_t _PyOpcode_Deopt[256];\n") - iobj.write("\n#ifdef NEED_OPCODE_TABLES\n") - - iobj.write("\nconst uint8_t _PyOpcode_Caches[256] = {\n") - for name, entries in opcode["_inline_cache_entries"].items(): - iobj.write(f" [{name}] = {entries},\n") - iobj.write("};\n") - - deoptcodes = {} - for basic, op in opmap.items(): - if op < 256: - deoptcodes[basic] = basic - for basic, family in _opcode_metadata["_specializations"].items(): - for specialized in family: - deoptcodes[specialized] = basic - iobj.write("\nconst uint8_t _PyOpcode_Deopt[256] = {\n") - for opt, deopt in sorted(deoptcodes.items()): - iobj.write(f" [{opt}] = {deopt},\n") - iobj.write("};\n") - iobj.write("#endif // NEED_OPCODE_TABLES\n") - - fobj.write("\n") - for i, (op, _) in enumerate(opcode["_nb_ops"]): - fobj.write(DEFINE.format(op, i)) - - iobj.write("\n") - iobj.write(f"\nextern const char *const _PyOpcode_OpName[{NUM_OPCODES}];\n") - iobj.write("\n#ifdef NEED_OPCODE_TABLES\n") - iobj.write(f"const char *const _PyOpcode_OpName[{NUM_OPCODES}] = {{\n") - for op, name in enumerate(opname_including_specialized): - if name[0] != "<": - op = name - iobj.write(f''' [{op}] = "{name}",\n''') - iobj.write("};\n") - iobj.write("#endif // NEED_OPCODE_TABLES\n") - - iobj.write("\n") - iobj.write("#define EXTRA_CASES \\\n") - for i, flag in enumerate(used): - if not flag: - iobj.write(f" case {i}: \\\n") - iobj.write(" ;\n") - - fobj.write(footer) - iobj.write(internal_footer) - - with open(opcode_targets_h, "w") as f: - targets = ["_unknown_opcode"] * 256 - for op, name in enumerate(opname_including_specialized): - if op < 256 and not name.startswith("<"): - targets[op] = f"TARGET_{name}" - - f.write("static void *opcode_targets[256] = {\n") - f.write(",\n".join([f" &&{s}" for s in targets])) - f.write("\n};\n") - - print(f"{outfile} regenerated from {opcode_py}") - - -if __name__ == '__main__': - main(sys.argv[1], sys.argv[2], sys.argv[3], sys.argv[4], sys.argv[5]) diff --git a/Tools/build/generate_sbom.py b/Tools/build/generate_sbom.py new file mode 100644 index 00000000000000..282ee20cc402b0 --- /dev/null +++ b/Tools/build/generate_sbom.py @@ -0,0 +1,310 @@ +"""Tool for generating Software Bill of Materials (SBOM) for Python's dependencies""" +import os +import re +import hashlib +import json +import glob +import pathlib +import subprocess +import sys +import typing +from urllib.request import urlopen + +CPYTHON_ROOT_DIR = pathlib.Path(__file__).parent.parent.parent + +# Before adding a new entry to this list, double check that +# the license expression is a valid SPDX license expression: +# See: https://spdx.org/licenses +ALLOWED_LICENSE_EXPRESSIONS = { + "MIT", + "CC0-1.0", + "Apache-2.0", + "BSD-2-Clause", +} + +# Properties which are required for our purposes. +REQUIRED_PROPERTIES_PACKAGE = frozenset([ + "SPDXID", + "name", + "versionInfo", + "downloadLocation", + "checksums", + "licenseConcluded", + "externalRefs", + "originator", + "primaryPackagePurpose", +]) + + +class PackageFiles(typing.NamedTuple): + """Structure for describing the files of a package""" + include: list[str] + exclude: list[str] | None = None + + +# SBOMS don't have a method to specify the sources of files +# so we need to do that external to the SBOM itself. Add new +# values to 'exclude' if we create new files within tracked +# directories that aren't sourced from third-party packages. +PACKAGE_TO_FILES = { + # NOTE: pip's entry in this structure is automatically generated in + # the 'discover_pip_sbom_package()' function below. + "mpdecimal": PackageFiles( + include=["Modules/_decimal/libmpdec/**"] + ), + "expat": PackageFiles( + include=["Modules/expat/**"] + ), + "macholib": PackageFiles( + include=["Lib/ctypes/macholib/**"], + exclude=[ + "Lib/ctypes/macholib/README.ctypes", + "Lib/ctypes/macholib/fetch_macholib", + "Lib/ctypes/macholib/fetch_macholib.bat", + ], + ), + "libb2": PackageFiles( + include=["Modules/_blake2/impl/**"] + ), + "hacl-star": PackageFiles( + include=["Modules/_hacl/**"], + exclude=[ + "Modules/_hacl/refresh.sh", + "Modules/_hacl/README.md", + "Modules/_hacl/python_hacl_namespace.h", + ] + ), +} + + +def spdx_id(value: str) -> str: + """Encode a value into characters that are valid in an SPDX ID""" + return re.sub(r"[^a-zA-Z0-9.\-]+", "-", value) + + +def error_if(value: bool, error_message: str) -> None: + """Prints an error if a comparison fails along with a link to the devguide""" + if value: + print(error_message) + print("See 'https://devguide.python.org/developer-workflow/sbom' for more information.") + sys.exit(1) + + +def filter_gitignored_paths(paths: list[str]) -> list[str]: + """ + Filter out paths excluded by the gitignore file. + The output of 'git check-ignore --non-matching --verbose' looks + like this for non-matching (included) files: + + '::' + + And looks like this for matching (excluded) files: + + '.gitignore:9:*.a Tools/lib.a' + """ + # Filter out files in gitignore. + # Non-matching files show up as '::' + git_check_ignore_proc = subprocess.run( + ["git", "check-ignore", "--verbose", "--non-matching", *paths], + check=False, + stdout=subprocess.PIPE, + ) + # 1 means matches, 0 means no matches. + assert git_check_ignore_proc.returncode in (0, 1) + + # Return the list of paths sorted + git_check_ignore_lines = git_check_ignore_proc.stdout.decode().splitlines() + return sorted([line.split()[-1] for line in git_check_ignore_lines if line.startswith("::")]) + + +def discover_pip_sbom_package(sbom_data: dict[str, typing.Any]) -> None: + """pip is a part of a packaging ecosystem (Python, surprise!) so it's actually + automatable to discover the metadata we need like the version and checksums + so let's do that on behalf of our friends at the PyPA. + """ + global PACKAGE_TO_FILES + + ensurepip_bundled_dir = CPYTHON_ROOT_DIR / "Lib/ensurepip/_bundled" + pip_wheels = [] + + # Find the hopefully one pip wheel in the bundled directory. + for wheel_filename in os.listdir(ensurepip_bundled_dir): + if wheel_filename.startswith("pip-"): + pip_wheels.append(wheel_filename) + if len(pip_wheels) != 1: + print("Zero or multiple pip wheels detected in 'Lib/ensurepip/_bundled'") + sys.exit(1) + pip_wheel_filename = pip_wheels[0] + + # Add the wheel filename to the list of files so the SBOM file + # and relationship generator can work its magic on the wheel too. + PACKAGE_TO_FILES["pip"] = PackageFiles( + include=[f"Lib/ensurepip/_bundled/{pip_wheel_filename}"] + ) + + # Wheel filename format puts the version right after the project name. + pip_version = pip_wheel_filename.split("-")[1] + pip_checksum_sha256 = hashlib.sha256( + (ensurepip_bundled_dir / pip_wheel_filename).read_bytes() + ).hexdigest() + + # Get pip's download location from PyPI. Check that the checksum is correct too. + try: + raw_text = urlopen(f"https://pypi.org/pypi/pip/{pip_version}/json").read() + pip_release_metadata = json.loads(raw_text) + url: dict[str, typing.Any] + + # Look for a matching artifact filename and then check + # its remote checksum to the local one. + for url in pip_release_metadata["urls"]: + if url["filename"] == pip_wheel_filename: + break + else: + raise ValueError(f"No matching filename on PyPI for '{pip_wheel_filename}'") + if url["digests"]["sha256"] != pip_checksum_sha256: + raise ValueError(f"Local pip checksum doesn't match artifact on PyPI") + + # Successfully found the download URL for the matching artifact. + pip_download_url = url["url"] + + except (OSError, ValueError) as e: + print(f"Couldn't fetch pip's metadata from PyPI: {e}") + sys.exit(1) + + # Remove pip from the existing SBOM packages if it's there + # and then overwrite its entry with our own generated one. + sbom_data["packages"] = [ + sbom_package + for sbom_package in sbom_data["packages"] + if sbom_package["name"] != "pip" + ] + sbom_data["packages"].append( + { + "SPDXID": spdx_id("SPDXRef-PACKAGE-pip"), + "name": "pip", + "versionInfo": pip_version, + "originator": "Organization: Python Packaging Authority", + "licenseConcluded": "MIT", + "downloadLocation": pip_download_url, + "checksums": [ + {"algorithm": "SHA256", "checksumValue": pip_checksum_sha256} + ], + "externalRefs": [ + { + "referenceCategory": "SECURITY", + "referenceLocator": f"cpe:2.3:a:pypa:pip:{pip_version}:*:*:*:*:*:*:*", + "referenceType": "cpe23Type", + }, + { + "referenceCategory": "PACKAGE_MANAGER", + "referenceLocator": f"pkg:pypi/pip@{pip_version}", + "referenceType": "purl", + }, + ], + "primaryPackagePurpose": "SOURCE", + } + ) + + +def main() -> None: + sbom_path = CPYTHON_ROOT_DIR / "Misc/sbom.spdx.json" + sbom_data = json.loads(sbom_path.read_bytes()) + + # Insert pip's SBOM metadata from the wheel. + discover_pip_sbom_package(sbom_data) + + # Ensure all packages in this tool are represented also in the SBOM file. + error_if( + {package["name"] for package in sbom_data["packages"]} != set(PACKAGE_TO_FILES), + "Packages defined in SBOM tool don't match those defined in SBOM file.", + ) + + # Make a bunch of assertions about the SBOM data to ensure it's consistent. + for package in sbom_data["packages"]: + # Properties and ID must be properly formed. + error_if( + "name" not in package, + "Package is missing the 'name' field" + ) + error_if( + set(package.keys()) != REQUIRED_PROPERTIES_PACKAGE, + f"Package '{package['name']}' is missing required fields", + ) + error_if( + package["SPDXID"] != spdx_id(f"SPDXRef-PACKAGE-{package['name']}"), + f"Package '{package['name']}' has a malformed SPDXID", + ) + + # Version must be in the download and external references. + version = package["versionInfo"] + error_if( + version not in package["downloadLocation"], + f"Version '{version}' for package '{package['name']} not in 'downloadLocation' field", + ) + error_if( + any(version not in ref["referenceLocator"] for ref in package["externalRefs"]), + ( + f"Version '{version}' for package '{package['name']} not in " + f"all 'externalRefs[].referenceLocator' fields" + ), + ) + + # License must be on the approved list for SPDX. + license_concluded = package["licenseConcluded"] + error_if( + license_concluded not in ALLOWED_LICENSE_EXPRESSIONS, + f"License identifier '{license_concluded}' not in SBOM tool allowlist" + ) + + # Regenerate file information from current data. + sbom_files = [] + sbom_relationships = [] + + # We call 'sorted()' here a lot to avoid filesystem scan order issues. + for name, files in sorted(PACKAGE_TO_FILES.items()): + package_spdx_id = spdx_id(f"SPDXRef-PACKAGE-{name}") + exclude = files.exclude or () + for include in sorted(files.include): + # Find all the paths and then filter them through .gitignore. + paths = glob.glob(include, root_dir=CPYTHON_ROOT_DIR, recursive=True) + paths = filter_gitignored_paths(paths) + error_if( + len(paths) == 0, + f"No valid paths found at path '{include}' for package '{name}", + ) + + for path in paths: + # Skip directories and excluded files + if not (CPYTHON_ROOT_DIR / path).is_file() or path in exclude: + continue + + # SPDX requires SHA1 to be used for files, but we provide SHA256 too. + data = (CPYTHON_ROOT_DIR / path).read_bytes() + checksum_sha1 = hashlib.sha1(data).hexdigest() + checksum_sha256 = hashlib.sha256(data).hexdigest() + + file_spdx_id = spdx_id(f"SPDXRef-FILE-{path}") + sbom_files.append({ + "SPDXID": file_spdx_id, + "fileName": path, + "checksums": [ + {"algorithm": "SHA1", "checksumValue": checksum_sha1}, + {"algorithm": "SHA256", "checksumValue": checksum_sha256}, + ], + }) + + # Tie each file back to its respective package. + sbom_relationships.append({ + "spdxElementId": package_spdx_id, + "relatedSpdxElement": file_spdx_id, + "relationshipType": "CONTAINS", + }) + + # Update the SBOM on disk + sbom_data["files"] = sbom_files + sbom_data["relationships"] = sbom_relationships + sbom_path.write_text(json.dumps(sbom_data, indent=2, sort_keys=True)) + + +if __name__ == "__main__": + main() diff --git a/Tools/build/generate_stdlib_module_names.py b/Tools/build/generate_stdlib_module_names.py index 72f6923c7c316a..5dce4e042d1eb4 100644 --- a/Tools/build/generate_stdlib_module_names.py +++ b/Tools/build/generate_stdlib_module_names.py @@ -28,6 +28,7 @@ '_testbuffer', '_testcapi', '_testclinic', + '_testclinic_limited', '_testconsole', '_testimportmultiple', '_testinternalcapi', @@ -35,6 +36,7 @@ '_testsinglephase', '_xxsubinterpreters', '_xxinterpchannels', + '_xxinterpqueues', '_xxtestfuzz', 'idlelib.idle_test', 'test', diff --git a/Tools/build/generate_token.py b/Tools/build/generate_token.py index 3bd307c1733867..16c38841e44a4d 100755 --- a/Tools/build/generate_token.py +++ b/Tools/build/generate_token.py @@ -50,7 +50,7 @@ def update_file(file, content): token_h_template = f"""\ -/* {AUTO_GENERATED_BY_SCRIPT} */ +// {AUTO_GENERATED_BY_SCRIPT} """ token_h_template += """\ @@ -84,7 +84,7 @@ def update_file(file, content): (x) == FSTRING_MIDDLE) -// Symbols exported for test_peg_generator +// Export these 4 symbols for 'test_peg_generator' PyAPI_DATA(const char * const) _PyParser_TokenNames[]; /* Token names */ PyAPI_FUNC(int) _PyToken_OneChar(int); PyAPI_FUNC(int) _PyToken_TwoChars(int, int); diff --git a/Tools/build/mypy.ini b/Tools/build/mypy.ini new file mode 100644 index 00000000000000..cf1dac7fde5ac5 --- /dev/null +++ b/Tools/build/mypy.ini @@ -0,0 +1,13 @@ +[mypy] +files = Tools/build/generate_sbom.py +pretty = True + +# Make sure Python can still be built +# using Python 3.10 for `PYTHON_FOR_REGEN`... +python_version = 3.10 + +# ...And be strict: +strict = True +strict_concatenate = True +enable_error_code = ignore-without-code,redundant-expr,truthy-bool,possibly-undefined +warn_unreachable = True diff --git a/Tools/build/regen-configure.sh b/Tools/build/regen-configure.sh new file mode 100755 index 00000000000000..e34a36c1a573e5 --- /dev/null +++ b/Tools/build/regen-configure.sh @@ -0,0 +1,31 @@ +#!/usr/bin/env bash + +set -e -x + +# The check_generated_files job of .github/workflows/build.yml must kept in +# sync with this script. Use the same container image than the job so the job +# doesn't need to run autoreconf in a container. +IMAGE="ubuntu:22.04" +DEPENDENCIES="autotools-dev autoconf autoconf-archive pkg-config" +AUTORECONF="autoreconf -ivf -Werror" + +WORK_DIR="/src" +SHELL_CMD="apt-get update && apt-get -yq install $DEPENDENCIES && cd $WORK_DIR && $AUTORECONF" + +abs_srcdir=$(cd $(dirname $0)/../..; pwd) + +if podman --version &>/dev/null; then + RUNTIME="podman" +elif docker --version &>/dev/null; then + RUNTIME="docker" +else + echo "$@ needs either Podman or Docker container runtime." >&2 + exit 1 +fi + +PATH_OPT="" +if command -v selinuxenabled >/dev/null && selinuxenabled; then + PATH_OPT=":Z" +fi + +"$RUNTIME" run --rm -v "$abs_srcdir:$WORK_DIR$PATH_OPT" "$IMAGE" /usr/bin/bash -c "$SHELL_CMD" diff --git a/Tools/build/smelly.py b/Tools/build/smelly.py index 276a5ab2cc84c6..7c534269c57a09 100755 --- a/Tools/build/smelly.py +++ b/Tools/build/smelly.py @@ -11,6 +11,16 @@ if sys.platform == 'darwin': ALLOWED_PREFIXES += ('__Py',) +# mimalloc doesn't use static, but it's symbols are not exported +# from the shared library. They do show up in the static library +# before its linked into an executable. +ALLOWED_STATIC_PREFIXES = ('mi_', '_mi_') + +# "Legacy": some old symbols are prefixed by "PY_". +EXCEPTIONS = frozenset({ + 'PY_TIMEOUT_MAX', +}) + IGNORED_EXTENSION = "_ctypes_test" # Ignore constructor and destructor functions IGNORED_SYMBOLS = {'_init', '_fini'} @@ -54,7 +64,7 @@ def get_exported_symbols(library, dynamic=False): return stdout -def get_smelly_symbols(stdout): +def get_smelly_symbols(stdout, dynamic=False): smelly_symbols = [] python_symbols = [] local_symbols = [] @@ -72,7 +82,9 @@ def get_smelly_symbols(stdout): symbol = parts[-1] result = '%s (type: %s)' % (symbol, symtype) - if symbol.startswith(ALLOWED_PREFIXES): + if (symbol.startswith(ALLOWED_PREFIXES) or + symbol in EXCEPTIONS or + (not dynamic and symbol.startswith(ALLOWED_STATIC_PREFIXES))): python_symbols.append(result) continue @@ -90,7 +102,7 @@ def get_smelly_symbols(stdout): def check_library(library, dynamic=False): nm_output = get_exported_symbols(library, dynamic) - smelly_symbols, python_symbols = get_smelly_symbols(nm_output) + smelly_symbols, python_symbols = get_smelly_symbols(nm_output, dynamic) if not smelly_symbols: print(f"OK: no smelly symbol found ({len(python_symbols)} Python symbols)") diff --git a/Tools/build/stable_abi.py b/Tools/build/stable_abi.py index 7cba788ff33578..85c437d521a15a 100644 --- a/Tools/build/stable_abi.py +++ b/Tools/build/stable_abi.py @@ -521,7 +521,7 @@ def gcc_get_limited_api_macros(headers): api_hexversion = sys.version_info.major << 24 | sys.version_info.minor << 16 - preprocesor_output_with_macros = subprocess.check_output( + preprocessor_output_with_macros = subprocess.check_output( sysconfig.get_config_var("CC").split() + [ # Prevent the expansion of the exported macros so we can @@ -540,7 +540,7 @@ def gcc_get_limited_api_macros(headers): return { target for target in re.findall( - r"#define (\w+)", preprocesor_output_with_macros + r"#define (\w+)", preprocessor_output_with_macros ) } @@ -561,7 +561,7 @@ def gcc_get_limited_api_definitions(headers): Requires Python built with a GCC-compatible compiler. (clang might work) """ api_hexversion = sys.version_info.major << 24 | sys.version_info.minor << 16 - preprocesor_output = subprocess.check_output( + preprocessor_output = subprocess.check_output( sysconfig.get_config_var("CC").split() + [ # Prevent the expansion of the exported macros so we can capture @@ -581,13 +581,13 @@ def gcc_get_limited_api_definitions(headers): stderr=subprocess.DEVNULL, ) stable_functions = set( - re.findall(r"__PyAPI_FUNC\(.*?\)\s*(.*?)\s*\(", preprocesor_output) + re.findall(r"__PyAPI_FUNC\(.*?\)\s*(.*?)\s*\(", preprocessor_output) ) stable_exported_data = set( - re.findall(r"__EXPORT_DATA\((.*?)\)", preprocesor_output) + re.findall(r"__EXPORT_DATA\((.*?)\)", preprocessor_output) ) stable_data = set( - re.findall(r"__PyAPI_DATA\(.*?\)[\s\*\(]*([^);]*)\)?.*;", preprocesor_output) + re.findall(r"__PyAPI_DATA\(.*?\)[\s\*\(]*([^);]*)\)?.*;", preprocessor_output) ) return stable_data | stable_exported_data | stable_functions diff --git a/Tools/build/umarshal.py b/Tools/build/umarshal.py index f61570cbaff751..8198a1780b8dad 100644 --- a/Tools/build/umarshal.py +++ b/Tools/build/umarshal.py @@ -1,4 +1,4 @@ -# Implementat marshal.loads() in pure Python +# Implementation of marshal.loads() in pure Python import ast @@ -125,10 +125,10 @@ def r_long64(self) -> int: x |= buf[1] << 8 x |= buf[2] << 16 x |= buf[3] << 24 - x |= buf[1] << 32 - x |= buf[1] << 40 - x |= buf[1] << 48 - x |= buf[1] << 56 + x |= buf[4] << 32 + x |= buf[5] << 40 + x |= buf[6] << 48 + x |= buf[7] << 56 x |= -(x & (1<<63)) # Sign-extend return x diff --git a/Tools/build/verify_ensurepip_wheels.py b/Tools/build/verify_ensurepip_wheels.py index 09fd5d9e3103ac..29897425da6c03 100755 --- a/Tools/build/verify_ensurepip_wheels.py +++ b/Tools/build/verify_ensurepip_wheels.py @@ -1,4 +1,4 @@ -#! /usr/bin/env python3 +#!/usr/bin/env python3 """ Compare checksums for wheels in :mod:`ensurepip` against the Cheeseshop. @@ -35,11 +35,17 @@ def print_error(file_path: str, message: str) -> None: def verify_wheel(package_name: str) -> bool: # Find the package on disk - package_path = next(WHEEL_DIR.glob(f"{package_name}*.whl"), None) - if not package_path: - print_error("", f"Could not find a {package_name} wheel on disk.") + package_paths = list(WHEEL_DIR.glob(f"{package_name}*.whl")) + if len(package_paths) != 1: + if package_paths: + for p in package_paths: + print_error(p, f"Found more than one wheel for package {package_name}.") + else: + print_error("", f"Could not find a {package_name} wheel on disk.") return False + package_path = package_paths[0] + print(f"Verifying checksum for {package_path}.") # Find the version of the package used by ensurepip diff --git a/Tools/buildbot/test.bat b/Tools/buildbot/test.bat index 25c796a60e173d..781f9a4c8206c8 100644 --- a/Tools/buildbot/test.bat +++ b/Tools/buildbot/test.bat @@ -5,7 +5,7 @@ setlocal set PATH=%PATH%;%SystemRoot%\SysNative\OpenSSH;%SystemRoot%\System32\OpenSSH set here=%~dp0 set rt_opts=-q -d -set regrtest_args=-j1 +set regrtest_args= set arm32_ssh= :CheckOpts @@ -23,7 +23,7 @@ if "%PROCESSOR_ARCHITECTURE%"=="ARM" if "%arm32_ssh%"=="true" goto NativeExecuti if "%arm32_ssh%"=="true" goto :Arm32Ssh :NativeExecution -call "%here%..\..\PCbuild\rt.bat" %rt_opts% -uall -rwW --slowest --timeout=1200 --fail-env-changed %regrtest_args% +call "%here%..\..\PCbuild\rt.bat" %rt_opts% --slow-ci %regrtest_args% exit /b %ERRORLEVEL% :Arm32Ssh @@ -35,7 +35,7 @@ if NOT "%REMOTE_PYTHON_DIR:~-1,1%"=="\" (set REMOTE_PYTHON_DIR=%REMOTE_PYTHON_DI set TEMP_ARGS=--temp %REMOTE_PYTHON_DIR%temp -set rt_args=%rt_opts% %dashU% -rwW --slowest --timeout=1200 --fail-env-changed %regrtest_args% %TEMP_ARGS% +set rt_args=%rt_opts% --slow-ci %dashU% %regrtest_args% %TEMP_ARGS% ssh %SSH_SERVER% "set TEMP=%REMOTE_PYTHON_DIR%temp& cd %REMOTE_PYTHON_DIR% & %REMOTE_PYTHON_DIR%PCbuild\rt.bat" %rt_args% set ERR=%ERRORLEVEL% scp %SSH_SERVER%:"%REMOTE_PYTHON_DIR%test-results.xml" "%PYTHON_SOURCE%\test-results.xml" diff --git a/Tools/c-analyzer/TODO b/Tools/c-analyzer/TODO index 27a535814ea52b..3d599538510bd9 100644 --- a/Tools/c-analyzer/TODO +++ b/Tools/c-analyzer/TODO @@ -428,8 +428,8 @@ Objects/typeobject.c:type_new():PyId___slots__ _Py_IDENTIFIER( Objects/unicodeobject.c:unicodeiter_reduce():PyId_iter _Py_IDENTIFIER(iter) Objects/weakrefobject.c:proxy_bytes():PyId___bytes__ _Py_IDENTIFIER(__bytes__) Objects/weakrefobject.c:weakref_repr():PyId___name__ _Py_IDENTIFIER(__name__) -Parser/tokenizer.c:fp_setreadl():PyId_open _Py_IDENTIFIER(open) -Parser/tokenizer.c:fp_setreadl():PyId_readline _Py_IDENTIFIER(readline) +Parser/tokenizer/file_tokenizer.c:fp_setreadl():PyId_open _Py_IDENTIFIER(open) +Parser/tokenizer/file_tokenizer.c:fp_setreadl():PyId_readline _Py_IDENTIFIER(readline) Python/Python-ast.c:ast_type_reduce():PyId___dict__ _Py_IDENTIFIER(__dict__) Python/Python-ast.c:make_type():PyId___module__ _Py_IDENTIFIER(__module__) Python/_warnings.c:PyId_stderr _Py_IDENTIFIER(stderr) diff --git a/Tools/c-analyzer/c_analyzer/__init__.py b/Tools/c-analyzer/c_analyzer/__init__.py index 171fa25102bffc..b83ffc087a08d8 100644 --- a/Tools/c-analyzer/c_analyzer/__init__.py +++ b/Tools/c-analyzer/c_analyzer/__init__.py @@ -18,7 +18,7 @@ def analyze(filenmes, **kwargs): - results = iter_analyis_results(filenames, **kwargs) + results = iter_analysis_results(filenames, **kwargs) return Analysis.from_results(results) diff --git a/Tools/c-analyzer/c_parser/info.py b/Tools/c-analyzer/c_parser/info.py index 799f9237877447..f96172e8ca8dfb 100644 --- a/Tools/c-analyzer/c_parser/info.py +++ b/Tools/c-analyzer/c_parser/info.py @@ -206,7 +206,7 @@ def from_row(cls, row, **markers): row = _tables.fix_row(row, **markers) return cls(*row) - # We have to provde _make() becaose we implemented __new__(). + # We have to provide _make() because we implemented __new__(). @classmethod def _make(cls, iterable): diff --git a/Tools/c-analyzer/c_parser/preprocessor/__init__.py b/Tools/c-analyzer/c_parser/preprocessor/__init__.py index cdc1a4e1269059..30a86cbd7dc494 100644 --- a/Tools/c-analyzer/c_parser/preprocessor/__init__.py +++ b/Tools/c-analyzer/c_parser/preprocessor/__init__.py @@ -2,6 +2,7 @@ import logging import os import os.path +import platform import re import sys @@ -242,6 +243,8 @@ def _get_default_compiler(): return 'unix' if os.name == 'nt': return 'msvc' + if sys.platform == 'darwin' and 'clang' in platform.python_compiler(): + return 'clang' return 'unix' diff --git a/Tools/c-analyzer/c_parser/preprocessor/gcc.py b/Tools/c-analyzer/c_parser/preprocessor/gcc.py index 415a2ba63dfe68..6ece70c77fd55c 100644 --- a/Tools/c-analyzer/c_parser/preprocessor/gcc.py +++ b/Tools/c-analyzer/c_parser/preprocessor/gcc.py @@ -3,14 +3,21 @@ from . import common as _common -# Modules/socketmodule.h uses pycore_time.h which needs the Py_BUILD_CORE -# macro. Usually it's defined by the C file which includes it. -# Other header files have a similar issue. -NEED_BUILD_CORE = { - 'cjkcodecs.h', - 'multibytecodec.h', - 'socketmodule.h', -} +# The following C files must not built with Py_BUILD_CORE. +FILES_WITHOUT_INTERNAL_CAPI = frozenset(( + # Modules/ + '_testcapimodule.c', + '_testclinic_limited.c', + 'xxlimited.c', + 'xxlimited_35.c', +)) + +# C files in the fhe following directories must not be built with +# Py_BUILD_CORE. +DIRS_WITHOUT_INTERNAL_CAPI = frozenset(( + # Modules/_testcapi/ + '_testcapi', +)) TOOL = 'gcc' @@ -70,7 +77,10 @@ def preprocess(filename, filename = _normpath(filename, cwd) postargs = POST_ARGS - if os.path.basename(filename) in NEED_BUILD_CORE: + basename = os.path.basename(filename) + dirname = os.path.basename(os.path.dirname(filename)) + if (basename not in FILES_WITHOUT_INTERNAL_CAPI + and dirname not in DIRS_WITHOUT_INTERNAL_CAPI): postargs += ('-DPy_BUILD_CORE=1',) text = _common.preprocess( diff --git a/Tools/c-analyzer/cpython/_files.py b/Tools/c-analyzer/cpython/_files.py index ee9e46f7e5e95f..a9bf0a1961222a 100644 --- a/Tools/c-analyzer/cpython/_files.py +++ b/Tools/c-analyzer/cpython/_files.py @@ -9,6 +9,7 @@ # Technically, this is covered by "Include/*.h": #'Include/cpython/*.h', 'Include/internal/*.h', + 'Include/internal/mimalloc/**/*.h', 'Modules/**/*.h', 'Modules/**/*.c', 'Objects/**/*.h', diff --git a/Tools/c-analyzer/cpython/_parser.py b/Tools/c-analyzer/cpython/_parser.py index 9bc7285e18b2fb..444063d2148934 100644 --- a/Tools/c-analyzer/cpython/_parser.py +++ b/Tools/c-analyzer/cpython/_parser.py @@ -70,7 +70,6 @@ def clean_lines(text): Python/thread_pthread_stubs.h # only huge constants (safe but parsing is slow) -Modules/_ssl_data.h Modules/_ssl_data_31.h Modules/_ssl_data_300.h Modules/_ssl_data_111.h @@ -88,6 +87,11 @@ def clean_lines(text): # not actually source Python/bytecodes.c +# mimalloc +Objects/mimalloc/*.c +Include/internal/mimalloc/*.h +Include/internal/mimalloc/mimalloc/*.h + # @end=conf@ ''') @@ -108,6 +112,7 @@ def clean_lines(text): * . * ./Include * ./Include/internal +* ./Include/internal/mimalloc Modules/_decimal/**/*.c Modules/_decimal/libmpdec Modules/_elementtree.c Modules/expat @@ -313,6 +318,7 @@ def clean_lines(text): _abs('Objects/stringlib/unicode_format.h'): (10_000, 400), _abs('Objects/typeobject.c'): (35_000, 200), _abs('Python/compile.c'): (20_000, 500), + _abs('Python/parking_lot.c'): (40_000, 1000), _abs('Python/pylifecycle.c'): (500_000, 5000), _abs('Python/pystate.c'): (500_000, 5000), @@ -326,7 +332,7 @@ def clean_lines(text): _abs('Python/stdlib_module_names.h'): (5_000, 500), # These large files are currently ignored (see above). - _abs('Modules/_ssl_data.h'): (80_000, 10_000), + _abs('Modules/_ssl_data_31.h'): (80_000, 10_000), _abs('Modules/_ssl_data_300.h'): (80_000, 10_000), _abs('Modules/_ssl_data_111.h'): (80_000, 10_000), _abs('Modules/cjkcodecs/mappings_*.h'): (160_000, 2_000), diff --git a/Tools/c-analyzer/cpython/globals-to-fix.tsv b/Tools/c-analyzer/cpython/globals-to-fix.tsv index dedcb3141457c0..e3a1b5d532bda2 100644 --- a/Tools/c-analyzer/cpython/globals-to-fix.tsv +++ b/Tools/c-analyzer/cpython/globals-to-fix.tsv @@ -57,6 +57,7 @@ Objects/genobject.c - _PyCoroWrapper_Type - Objects/interpreteridobject.c - PyInterpreterID_Type - Objects/iterobject.c - PyCallIter_Type - Objects/iterobject.c - PySeqIter_Type - +Objects/iterobject.c - _PyAnextAwaitable_Type - Objects/listobject.c - PyListIter_Type - Objects/listobject.c - PyListRevIter_Type - Objects/listobject.c - PyList_Type - @@ -70,6 +71,7 @@ Objects/moduleobject.c - PyModule_Type - Objects/namespaceobject.c - _PyNamespace_Type - Objects/object.c - _PyNone_Type - Objects/object.c - _PyNotImplemented_Type - +Objects/object.c - _PyAnextAwaitable_Type - Objects/odictobject.c - PyODictItems_Type - Objects/odictobject.c - PyODictIter_Type - Objects/odictobject.c - PyODictKeys_Type - @@ -113,8 +115,6 @@ Objects/codeobject.c - _PyLineIterator - Objects/codeobject.c - _PyPositionsIterator - Objects/genericaliasobject.c - _Py_GenericAliasIterType - # Not in a .h file: -Objects/iterobject.c - _PyAnextAwaitable_Type - -# Not in a .h file: Objects/memoryobject.c - _PyMemoryIter_Type - Objects/unicodeobject.c - _PyUnicodeASCIIIter_Type - Objects/unionobject.c - _PyUnion_Type - @@ -290,6 +290,10 @@ Objects/exceptions.c - PyExc_UnicodeWarning - Objects/exceptions.c - PyExc_BytesWarning - Objects/exceptions.c - PyExc_ResourceWarning - Objects/exceptions.c - PyExc_EncodingWarning - +Python/crossinterp.c - _PyExc_InterpreterError - +Python/crossinterp.c - _PyExc_InterpreterNotFoundError - +Python/crossinterp.c - PyExc_InterpreterError - +Python/crossinterp.c - PyExc_InterpreterNotFoundError - ##----------------------- ## singletons @@ -322,6 +326,12 @@ 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/_testclinic.c - DeprStarInit - +Modules/_testclinic.c - DeprStarInitNoInline - +Modules/_testclinic.c - DeprStarNew - +Modules/_testclinic.c - DeprKwdInit - +Modules/_testclinic.c - DeprKwdInitNoInline - +Modules/_testclinic.c - DeprKwdNew - ################################## @@ -412,20 +422,12 @@ Modules/_ctypes/_ctypes.c - _unpickle - Modules/_ctypes/_ctypes.c PyCArrayType_from_ctype cache - Modules/_cursesmodule.c - ModDict - Modules/_datetimemodule.c datetime_strptime module - -Modules/_datetimemodule.c - PyDateTime_TimeZone_UTC - -Modules/_datetimemodule.c - PyDateTime_Epoch - -Modules/_datetimemodule.c - us_per_ms - -Modules/_datetimemodule.c - us_per_second - -Modules/_datetimemodule.c - us_per_minute - -Modules/_datetimemodule.c - us_per_hour - -Modules/_datetimemodule.c - us_per_day - -Modules/_datetimemodule.c - us_per_week - -Modules/_datetimemodule.c - seconds_per_day - ## state Modules/_ctypes/_ctypes.c - _ctypes_ptrtype_cache - Modules/_ctypes/_ctypes.c - global_state - Modules/_ctypes/ctypes.h - global_state - +Modules/_datetimemodule.c - _datetime_global_state - Modules/_tkinter.c - tcl_lock - Modules/_tkinter.c - excInCmd - Modules/_tkinter.c - valInCmd - diff --git a/Tools/c-analyzer/cpython/ignored.tsv b/Tools/c-analyzer/cpython/ignored.tsv index 099f20b5a1b433..2f9e80d6ab6737 100644 --- a/Tools/c-analyzer/cpython/ignored.tsv +++ b/Tools/c-analyzer/cpython/ignored.tsv @@ -50,6 +50,9 @@ Python/getversion.c - version - Python/bootstrap_hash.c - _Py_HashSecret_Initialized - Python/pyhash.c - _Py_HashSecret - +## thread-safe hashtable (internal locks) +Python/parking_lot.c - buckets - + ################################## ## state tied to Py_Main() @@ -85,6 +88,10 @@ Parser/myreadline.c - PyOS_ReadlineFunctionPointer - Python/initconfig.c - _Py_StandardStreamEncoding - Python/initconfig.c - _Py_StandardStreamErrors - +# Internal constant list +Python/initconfig.c - PYCONFIG_SPEC - + + ##----------------------- ## public C-API @@ -158,6 +165,10 @@ Python/pylifecycle.c fatal_error reentrant - # explicitly protected, internal-only Modules/_xxinterpchannelsmodule.c - _globals - +Modules/_xxinterpqueuesmodule.c - _globals - + +# set once during module init +Modules/_decimal/_decimal.c - minalloc_is_set - ################################## @@ -325,7 +336,7 @@ Objects/unicodeobject.c unicode_encode_call_errorhandler argparse - Objects/unicodeobject.c unicode_translate_call_errorhandler argparse - Parser/parser.c - reserved_keywords - Parser/parser.c - soft_keywords - -Parser/tokenizer.c - type_comment_prefix - +Parser/lexer/lexer.c - type_comment_prefix - Python/ast_opt.c fold_unaryop ops - Python/ceval.c - _PyEval_BinaryOps - Python/ceval.c - _Py_INTERPRETER_TRAMPOLINE_INSTRUCTIONS - @@ -364,11 +375,11 @@ Python/sysmodule.c - perf_map_state - Python/sysmodule.c - _PySys_ImplCacheTag - Python/sysmodule.c - _PySys_ImplName - Python/sysmodule.c - whatstrings - -Python/optimizer.c - DefaultOptimizer_Type - -Python/optimizer.c - CounterExecutor_Type - -Python/optimizer.c - CounterOptimizer_Type - -Python/optimizer.c - UOpExecutor_Type - -Python/optimizer.c - UOpOptimizer_Type - +Python/optimizer.c - _PyDefaultOptimizer_Type - +Python/optimizer.c - _PyCounterExecutor_Type - +Python/optimizer.c - _PyCounterOptimizer_Type - +Python/optimizer.c - _PyUOpExecutor_Type - +Python/optimizer.c - _PyUOpOptimizer_Type - Python/optimizer.c - _PyOptimizer_Default - ##----------------------- @@ -419,6 +430,8 @@ Modules/_testbuffer.c staticarray_init kwlist - Modules/_testcapi/buffer.c - testBufType - Modules/_testcapi/code.c get_code_extra_index key - Modules/_testcapi/datetime.c - test_run_counter - +Modules/_testcapi/docstring.c - DocStringNoSignatureTest - +Modules/_testcapi/docstring.c - DocStringUnrepresentableSignatureTest - Modules/_testcapi/exceptions.c - PyRecursingInfinitelyError_Type - Modules/_testcapi/heaptype.c - _testcapimodule - Modules/_testcapi/mem.c - FmData - @@ -429,6 +442,7 @@ Modules/_testcapi/watchers.c - g_dict_watch_events - Modules/_testcapi/watchers.c - g_dict_watchers_installed - Modules/_testcapi/watchers.c - g_type_modified_events - Modules/_testcapi/watchers.c - g_type_watchers_installed - +Modules/_testcapi/watchers.c - code_watcher_ids - Modules/_testcapi/watchers.c - num_code_object_created_events - Modules/_testcapi/watchers.c - num_code_object_destroyed_events - Modules/_testcapi/watchers.c - pyfunc_watchers - @@ -517,7 +531,7 @@ Modules/_testcapimodule.c make_exception_with_doc kwlist - Modules/_testcapimodule.c raise_SIGINT_then_send_None PyId_send - Modules/_testcapimodule.c slot_tp_del PyId___tp_del__ - Modules/_testcapimodule.c test_capsule buffer - -Modules/_testcapimodule.c test_empty_argparse kwlist - +Modules/_testcapimodule.c getargs_empty kwlist - Modules/_testcapimodule.c test_structmembers_new keywords - Modules/_testcapimodule.c getargs_s_hash_int keywords - Modules/_testcapimodule.c - g_dict_watch_events - @@ -552,7 +566,6 @@ Modules/_testmultiphase.c - def_nonascii_latin - Modules/_testmultiphase.c - def_nonmodule - Modules/_testmultiphase.c - def_nonmodule_with_exec_slots - Modules/_testmultiphase.c - def_nonmodule_with_methods - -Modules/_testmultiphase.c - imp_dummy_def - Modules/_testmultiphase.c - main_def - Modules/_testmultiphase.c - main_slots - Modules/_testmultiphase.c - meth_state_access_slots - @@ -574,29 +587,36 @@ Modules/_testmultiphase.c - uninitialized_def - Modules/_testsinglephase.c - global_state - Modules/_xxtestfuzz/_xxtestfuzz.c - _fuzzmodule - Modules/_xxtestfuzz/_xxtestfuzz.c - module_methods - -Modules/_xxtestfuzz/fuzzer.c - SRE_FLAG_DEBUG - +Modules/_xxtestfuzz/fuzzer.c - RE_FLAG_DEBUG - Modules/_xxtestfuzz/fuzzer.c - ast_literal_eval_method - +Modules/_xxtestfuzz/fuzzer.c - bytesio_type - Modules/_xxtestfuzz/fuzzer.c - compiled_patterns - Modules/_xxtestfuzz/fuzzer.c - csv_error - Modules/_xxtestfuzz/fuzzer.c - csv_module - Modules/_xxtestfuzz/fuzzer.c - json_loads_method - Modules/_xxtestfuzz/fuzzer.c - regex_patterns - -Modules/_xxtestfuzz/fuzzer.c - sre_compile_method - -Modules/_xxtestfuzz/fuzzer.c - sre_error_exception - +Modules/_xxtestfuzz/fuzzer.c - re_compile_method - +Modules/_xxtestfuzz/fuzzer.c - re_error_exception - Modules/_xxtestfuzz/fuzzer.c - struct_error - Modules/_xxtestfuzz/fuzzer.c - struct_unpack_method - +Modules/_xxtestfuzz/fuzzer.c - xmlparser_type - +Modules/_xxtestfuzz/fuzzer.c - pycompile_scratch - +Modules/_xxtestfuzz/fuzzer.c - start_vals - +Modules/_xxtestfuzz/fuzzer.c - optimize_vals - Modules/_xxtestfuzz/fuzzer.c LLVMFuzzerTestOneInput CSV_READER_INITIALIZED - Modules/_xxtestfuzz/fuzzer.c LLVMFuzzerTestOneInput JSON_LOADS_INITIALIZED - Modules/_xxtestfuzz/fuzzer.c LLVMFuzzerTestOneInput SRE_COMPILE_INITIALIZED - Modules/_xxtestfuzz/fuzzer.c LLVMFuzzerTestOneInput SRE_MATCH_INITIALIZED - Modules/_xxtestfuzz/fuzzer.c LLVMFuzzerTestOneInput STRUCT_UNPACK_INITIALIZED - Modules/_xxtestfuzz/fuzzer.c LLVMFuzzerTestOneInput AST_LITERAL_EVAL_INITIALIZED - +Modules/_xxtestfuzz/fuzzer.c LLVMFuzzerTestOneInput ELEMENTTREE_PARSEWHOLE_INITIALIZED - ##----------------------- ## the analyzer should have ignored these # XXX Fix the analyzer. ## forward/extern references +Include/internal/pycore_importdl.h - _PyImport_DynLoadFiletab - Include/py_curses.h - PyCurses_API - Include/pydecimal.h - _decimal_api - Modules/_blake2/blake2module.c - blake2b_type_spec - @@ -658,7 +678,6 @@ Objects/object.c - _PyLineIterator - Objects/object.c - _PyPositionsIterator - Python/perf_trampoline.c - _Py_trampoline_func_start - Python/perf_trampoline.c - _Py_trampoline_func_end - -Python/importdl.h - _PyImport_DynLoadFiletab - Modules/expat/xmlrole.c - prolog0 - Modules/expat/xmlrole.c - prolog1 - Modules/expat/xmlrole.c - prolog2 - @@ -714,3 +733,6 @@ Modules/expat/xmlrole.c - error - ## other Modules/_io/_iomodule.c - _PyIO_Module - Modules/_sqlite/module.c - _sqlite3module - +Python/optimizer_analysis.c - _Py_PartitionRootNode_Type - +Python/optimizer_analysis.c - _Py_UOpsAbstractInterpContext_Type - +Modules/clinic/md5module.c.h _md5_md5 _keywords - diff --git a/Tools/cases_generator/README.md b/Tools/cases_generator/README.md index fc9331656fe787..ed802e44f31ad5 100644 --- a/Tools/cases_generator/README.md +++ b/Tools/cases_generator/README.md @@ -7,10 +7,14 @@ What's currently here: - `lexer.py`: lexer for C, originally written by Mark Shannon - `plexer.py`: OO interface on top of lexer.py; main class: `PLexer` -- `parser.py`: Parser for instruction definition DSL; main class `Parser` +- `parsing.py`: Parser for instruction definition DSL; main class `Parser` - `generate_cases.py`: driver script to read `Python/bytecodes.c` and write `Python/generated_cases.c.h` (and several other files) -- `test_generator.py`: tests, require manual running using `pytest` +- `analysis.py`: `Analyzer` class used to read the input files +- `flags.py`: abstractions related to metadata flags for instructions +- `formatting.py`: `Formatter` class used to write the output files +- `instructions.py`: classes to analyze and write instructions +- `stacking.py`: code to handle generalized stack effects Note that there is some dummy C code at the top and bottom of `Python/bytecodes.c` diff --git a/Tools/cases_generator/_typing_backports.py b/Tools/cases_generator/_typing_backports.py new file mode 100644 index 00000000000000..c2aa50804cefe2 --- /dev/null +++ b/Tools/cases_generator/_typing_backports.py @@ -0,0 +1,15 @@ +"""Backports from newer versions of the typing module. + +We backport these features here so that Python can still build +while using an older Python version for PYTHON_FOR_REGEN. +""" + +from typing import NoReturn + + +def assert_never(obj: NoReturn) -> NoReturn: + """Statically assert that a line of code is unreachable. + + Backport of typing.assert_never (introduced in Python 3.11). + """ + raise AssertionError(f"Expected code to be unreachable, but got: {obj}") diff --git a/Tools/cases_generator/analysis.py b/Tools/cases_generator/analysis.py deleted file mode 100644 index 2db1cd01c19ae5..00000000000000 --- a/Tools/cases_generator/analysis.py +++ /dev/null @@ -1,411 +0,0 @@ -import re -import sys -import typing - -from flags import InstructionFlags, variable_used -from formatting import prettify_filename, UNUSED -from instructions import ( - ActiveCacheEffect, - Component, - Instruction, - InstructionOrCacheEffect, - MacroInstruction, - MacroParts, - OverriddenInstructionPlaceHolder, - PseudoInstruction, -) -import parsing -from parsing import StackEffect - -BEGIN_MARKER = "// BEGIN BYTECODES //" -END_MARKER = "// END BYTECODES //" - -RESERVED_WORDS = { - "co_consts": "Use FRAME_CO_CONSTS.", - "co_names": "Use FRAME_CO_NAMES.", -} - -RE_PREDICTED = r"^\s*(?:GO_TO_INSTRUCTION\(|DEOPT_IF\(.*?,\s*)(\w+)\);\s*(?://.*)?$" - - -class Analyzer: - """Parse input, analyze it, and write to output.""" - - input_filenames: list[str] - errors: int = 0 - warnings: int = 0 - - def __init__(self, input_filenames: list[str]): - self.input_filenames = input_filenames - - def message(self, msg: str, node: parsing.Node) -> None: - lineno = 0 - filename = "" - if context := node.context: - filename = context.owner.filename - # Use line number of first non-comment in the node - for token in context.owner.tokens[context.begin : context.end]: - lineno = token.line - if token.kind != "COMMENT": - break - print(f"{filename}:{lineno}: {msg}", file=sys.stderr) - - def error(self, msg: str, node: parsing.Node) -> None: - self.message("error: " + msg, node) - self.errors += 1 - - def warning(self, msg: str, node: parsing.Node) -> None: - self.message("warning: " + msg, node) - self.warnings += 1 - - def note(self, msg: str, node: parsing.Node) -> None: - self.message("note: " + msg, node) - - everything: list[ - parsing.InstDef - | parsing.Macro - | parsing.Pseudo - | OverriddenInstructionPlaceHolder - ] - instrs: dict[str, Instruction] # Includes ops - macros: dict[str, parsing.Macro] - macro_instrs: dict[str, MacroInstruction] - families: dict[str, parsing.Family] - pseudos: dict[str, parsing.Pseudo] - pseudo_instrs: dict[str, PseudoInstruction] - - def parse(self) -> None: - """Parse the source text. - - We only want the parser to see the stuff between the - begin and end markers. - """ - - self.everything = [] - self.instrs = {} - self.macros = {} - self.families = {} - self.pseudos = {} - - instrs_idx: dict[str, int] = dict() - - for filename in self.input_filenames: - self.parse_file(filename, instrs_idx) - - files = " + ".join(self.input_filenames) - n_instrs = 0 - n_ops = 0 - for instr in self.instrs.values(): - if instr.kind == "op": - n_ops += 1 - else: - n_instrs += 1 - print( - f"Read {n_instrs} instructions, {n_ops} ops, " - f"{len(self.macros)} macros, {len(self.pseudos)} pseudos, " - f"and {len(self.families)} families from {files}", - file=sys.stderr, - ) - - def parse_file(self, filename: str, instrs_idx: dict[str, int]) -> None: - with open(filename) as file: - src = file.read() - - psr = parsing.Parser(src, filename=prettify_filename(filename)) - - # Skip until begin marker - while tkn := psr.next(raw=True): - if tkn.text == BEGIN_MARKER: - break - else: - raise psr.make_syntax_error( - f"Couldn't find {BEGIN_MARKER!r} in {psr.filename}" - ) - start = psr.getpos() - - # Find end marker, then delete everything after it - while tkn := psr.next(raw=True): - if tkn.text == END_MARKER: - break - del psr.tokens[psr.getpos() - 1 :] - - # Parse from start - psr.setpos(start) - thing: parsing.Node | None - thing_first_token = psr.peek() - while thing := psr.definition(): - thing = typing.cast( - parsing.InstDef | parsing.Macro | parsing.Pseudo | parsing.Family, thing - ) - if ws := [w for w in RESERVED_WORDS if variable_used(thing, w)]: - self.error( - f"'{ws[0]}' is a reserved word. {RESERVED_WORDS[ws[0]]}", thing - ) - - match thing: - case parsing.InstDef(name=name): - if name in self.instrs: - if not thing.override: - raise psr.make_syntax_error( - f"Duplicate definition of '{name}' @ {thing.context} " - f"previous definition @ {self.instrs[name].inst.context}", - thing_first_token, - ) - self.everything[ - instrs_idx[name] - ] = OverriddenInstructionPlaceHolder(name=name) - if name not in self.instrs and thing.override: - raise psr.make_syntax_error( - f"Definition of '{name}' @ {thing.context} is supposed to be " - "an override but no previous definition exists.", - thing_first_token, - ) - self.instrs[name] = Instruction(thing) - instrs_idx[name] = len(self.everything) - self.everything.append(thing) - case parsing.Macro(name): - self.macros[name] = thing - self.everything.append(thing) - case parsing.Family(name): - self.families[name] = thing - case parsing.Pseudo(name): - self.pseudos[name] = thing - self.everything.append(thing) - case _: - typing.assert_never(thing) - if not psr.eof(): - raise psr.make_syntax_error(f"Extra stuff at the end of {filename}") - - def analyze(self) -> None: - """Analyze the inputs. - - Raises SystemExit if there is an error. - """ - self.analyze_macros_and_pseudos() - self.find_predictions() - self.map_families() - self.check_families() - - def find_predictions(self) -> None: - """Find the instructions that need PREDICTED() labels.""" - for instr in self.instrs.values(): - targets: set[str] = set() - for line in instr.block_text: - if m := re.match(RE_PREDICTED, line): - targets.add(m.group(1)) - for target in targets: - if target_instr := self.instrs.get(target): - target_instr.predicted = True - elif target_macro := self.macro_instrs.get(target): - target_macro.predicted = True - else: - self.error( - f"Unknown instruction {target!r} predicted in {instr.name!r}", - instr.inst, # TODO: Use better location - ) - - def map_families(self) -> None: - """Link instruction names back to their family, if they have one.""" - for family in self.families.values(): - for member in [family.name] + family.members: - if member_instr := self.instrs.get(member): - if ( - member_instr.family is not family - and member_instr.family is not None - ): - self.error( - f"Instruction {member} is a member of multiple families " - f"({member_instr.family.name}, {family.name}).", - family, - ) - else: - member_instr.family = family - elif not self.macro_instrs.get(member): - self.error( - f"Unknown instruction {member!r} referenced in family {family.name!r}", - family, - ) - - def check_families(self) -> None: - """Check each family: - - - Must have at least 2 members (including head) - - Head and all members must be known instructions - - Head and all members must have the same cache, input and output effects - """ - for family in self.families.values(): - if family.name not in self.macro_instrs and family.name not in self.instrs: - self.error( - f"Family {family.name!r} has unknown instruction {family.name!r}", - family, - ) - members = [ - member - for member in family.members - if member in self.instrs or member in self.macro_instrs - ] - if members != family.members: - unknown = set(family.members) - set(members) - self.error( - f"Family {family.name!r} has unknown members: {unknown}", family - ) - expected_effects = self.effect_counts(family.name) - for member in members: - member_effects = self.effect_counts(member) - if member_effects != expected_effects: - self.error( - f"Family {family.name!r} has inconsistent " - f"(cache, input, output) effects:\n" - f" {family.name} = {expected_effects}; " - f"{member} = {member_effects}", - family, - ) - - def effect_counts(self, name: str) -> tuple[int, int, int]: - if instr := self.instrs.get(name): - cache = instr.cache_offset - input = len(instr.input_effects) - output = len(instr.output_effects) - elif mac := self.macro_instrs.get(name): - cache = mac.cache_offset - input, output = 0, 0 - for part in mac.parts: - if isinstance(part, Component): - # A component may pop what the previous component pushed, - # so we offset the input/output counts by that. - delta_i = len(part.instr.input_effects) - delta_o = len(part.instr.output_effects) - offset = min(delta_i, output) - input += delta_i - offset - output += delta_o - offset - else: - assert False, f"Unknown instruction {name!r}" - return cache, input, output - - def analyze_macros_and_pseudos(self) -> None: - """Analyze each macro and pseudo instruction.""" - self.macro_instrs = {} - self.pseudo_instrs = {} - for name, macro in self.macros.items(): - self.macro_instrs[name] = mac = self.analyze_macro(macro) - self.check_macro_consistency(mac) - for name, pseudo in self.pseudos.items(): - self.pseudo_instrs[name] = self.analyze_pseudo(pseudo) - - # TODO: Merge with similar code in stacking.py, write_components() - def check_macro_consistency(self, mac: MacroInstruction) -> None: - def get_var_names(instr: Instruction) -> dict[str, StackEffect]: - vars: dict[str, StackEffect] = {} - for eff in instr.input_effects + instr.output_effects: - if eff.name == UNUSED: - continue - if eff.name in vars: - if vars[eff.name] != eff: - self.error( - f"Instruction {instr.name!r} has " - f"inconsistent type/cond/size for variable " - f"{eff.name!r}: {vars[eff.name]} vs {eff}", - instr.inst, - ) - else: - vars[eff.name] = eff - return vars - - all_vars: dict[str, StackEffect] = {} - # print("Checking", mac.name) - prevop: Instruction | None = None - for part in mac.parts: - if not isinstance(part, Component): - continue - vars = get_var_names(part.instr) - # print(" //", part.instr.name, "//", vars) - for name, eff in vars.items(): - if name in all_vars: - if all_vars[name] != eff: - self.error( - f"Macro {mac.name!r} has " - f"inconsistent type/cond/size for variable " - f"{name!r}: " - f"{all_vars[name]} vs {eff} in {part.instr.name!r}", - mac.macro, - ) - else: - all_vars[name] = eff - if prevop is not None: - pushes = list(prevop.output_effects) - pops = list(reversed(part.instr.input_effects)) - copies: list[tuple[StackEffect, StackEffect]] = [] - while pushes and pops and pushes[-1] == pops[0]: - src, dst = pushes.pop(), pops.pop(0) - if src.name == dst.name or dst.name == UNUSED: - continue - copies.append((src, dst)) - reads = set(copy[0].name for copy in copies) - writes = set(copy[1].name for copy in copies) - if reads & writes: - self.error( - f"Macro {mac.name!r} has conflicting copies " - f"(source of one copy is destination of another): " - f"{reads & writes}", - mac.macro, - ) - prevop = part.instr - - def analyze_macro(self, macro: parsing.Macro) -> MacroInstruction: - components = self.check_macro_components(macro) - parts: MacroParts = [] - flags = InstructionFlags.newEmpty() - offset = 0 - for component in components: - match component: - case parsing.CacheEffect() as ceffect: - parts.append(ceffect) - offset += ceffect.size - case Instruction() as instr: - part, offset = self.analyze_instruction(instr, offset) - parts.append(part) - flags.add(instr.instr_flags) - case _: - typing.assert_never(component) - format = "IB" - if offset: - format += "C" + "0" * (offset - 1) - return MacroInstruction(macro.name, format, flags, macro, parts, offset) - - def analyze_pseudo(self, pseudo: parsing.Pseudo) -> PseudoInstruction: - targets = [self.instrs[target] for target in pseudo.targets] - assert targets - # Make sure the targets have the same fmt - fmts = list(set([t.instr_fmt for t in targets])) - assert len(fmts) == 1 - assert len(list(set([t.instr_flags.bitmap() for t in targets]))) == 1 - return PseudoInstruction(pseudo.name, targets, fmts[0], targets[0].instr_flags) - - def analyze_instruction( - self, instr: Instruction, offset: int - ) -> tuple[Component, int]: - active_effects: list[ActiveCacheEffect] = [] - for ceffect in instr.cache_effects: - if ceffect.name != UNUSED: - active_effects.append(ActiveCacheEffect(ceffect, offset)) - offset += ceffect.size - return ( - Component(instr, active_effects), - offset, - ) - - def check_macro_components( - self, macro: parsing.Macro - ) -> list[InstructionOrCacheEffect]: - components: list[InstructionOrCacheEffect] = [] - for uop in macro.uops: - match uop: - case parsing.OpName(name): - if name not in self.instrs: - self.error(f"Unknown instruction {name!r}", macro) - components.append(self.instrs[name]) - case parsing.CacheEffect(): - components.append(uop) - case _: - typing.assert_never(uop) - return components diff --git a/Tools/cases_generator/analyzer.py b/Tools/cases_generator/analyzer.py new file mode 100644 index 00000000000000..82ef8888bfcee5 --- /dev/null +++ b/Tools/cases_generator/analyzer.py @@ -0,0 +1,723 @@ +from dataclasses import dataclass +import lexer +import parser +from typing import Optional + + +@dataclass +class Properties: + escapes: bool + infallible: bool + deopts: bool + oparg: bool + jumps: bool + eval_breaker: bool + ends_with_eval_breaker: bool + needs_this: bool + always_exits: bool + stores_sp: bool + tier_one_only: bool + uses_co_consts: bool + uses_co_names: bool + uses_locals: bool + has_free: bool + + def dump(self, indent: str) -> None: + print(indent, end="") + text = ", ".join([f"{key}: {value}" for (key, value) in self.__dict__.items()]) + print(indent, text, sep="") + + @staticmethod + def from_list(properties: list["Properties"]) -> "Properties": + return Properties( + escapes=any(p.escapes for p in properties), + infallible=all(p.infallible for p in properties), + deopts=any(p.deopts for p in properties), + oparg=any(p.oparg for p in properties), + jumps=any(p.jumps for p in properties), + eval_breaker=any(p.eval_breaker for p in properties), + ends_with_eval_breaker=any(p.ends_with_eval_breaker for p in properties), + needs_this=any(p.needs_this for p in properties), + always_exits=any(p.always_exits for p in properties), + stores_sp=any(p.stores_sp for p in properties), + tier_one_only=any(p.tier_one_only for p in properties), + uses_co_consts=any(p.uses_co_consts for p in properties), + uses_co_names=any(p.uses_co_names for p in properties), + uses_locals=any(p.uses_locals for p in properties), + has_free=any(p.has_free for p in properties), + ) + + +SKIP_PROPERTIES = Properties( + escapes=False, + infallible=True, + deopts=False, + oparg=False, + jumps=False, + eval_breaker=False, + ends_with_eval_breaker=False, + needs_this=False, + always_exits=False, + stores_sp=False, + tier_one_only=False, + uses_co_consts=False, + uses_co_names=False, + uses_locals=False, + has_free=False, +) + + +@dataclass +class Skip: + "Unused cache entry" + size: int + + @property + def name(self) -> str: + return f"unused/{self.size}" + + @property + def properties(self) -> Properties: + return SKIP_PROPERTIES + + +@dataclass +class StackItem: + name: str + type: str | None + condition: str | None + size: str + peek: bool = False + + def __str__(self) -> str: + cond = f" if ({self.condition})" if self.condition else "" + size = f"[{self.size}]" if self.size != "1" else "" + type = "" if self.type is None else f"{self.type} " + return f"{type}{self.name}{size}{cond} {self.peek}" + + def is_array(self) -> bool: + return self.type == "PyObject **" + + +@dataclass +class StackEffect: + inputs: list[StackItem] + outputs: list[StackItem] + + def __str__(self) -> str: + return f"({', '.join([str(i) for i in self.inputs])} -- {', '.join([str(i) for i in self.outputs])})" + + +@dataclass +class CacheEntry: + name: str + size: int + + def __str__(self) -> str: + return f"{self.name}/{self.size}" + + +@dataclass +class Uop: + name: str + context: parser.Context | None + annotations: list[str] + stack: StackEffect + caches: list[CacheEntry] + body: list[lexer.Token] + properties: Properties + _size: int = -1 + implicitly_created: bool = False + + def dump(self, indent: str) -> None: + print( + indent, self.name, ", ".join(self.annotations) if self.annotations else "" + ) + print(indent, self.stack, ", ".join([str(c) for c in self.caches])) + self.properties.dump(" " + indent) + + @property + def size(self) -> int: + if self._size < 0: + self._size = sum(c.size for c in self.caches) + return self._size + + def is_viable(self) -> bool: + if self.name == "_SAVE_RETURN_OFFSET": + return True # Adjusts next_instr, but only in tier 1 code + if self.properties.needs_this: + return False + if "INSTRUMENTED" in self.name: + return False + if "replaced" in self.annotations: + return False + if self.name in ("INTERPRETER_EXIT", "JUMP_BACKWARD"): + return False + if len([c for c in self.caches if c.name != "unused"]) > 1: + return False + return True + + def is_super(self) -> bool: + for tkn in self.body: + if tkn.kind == "IDENTIFIER" and tkn.text == "oparg1": + return True + return False + + +Part = Uop | Skip + + +@dataclass +class Instruction: + name: str + parts: list[Part] + _properties: Properties | None + is_target: bool = False + family: Optional["Family"] = None + opcode: int = -1 + + @property + def properties(self) -> Properties: + if self._properties is None: + self._properties = self._compute_properties() + return self._properties + + def _compute_properties(self) -> Properties: + return Properties.from_list([part.properties for part in self.parts]) + + def dump(self, indent: str) -> None: + print(indent, self.name, "=", ", ".join([part.name for part in self.parts])) + self.properties.dump(" " + indent) + + @property + def size(self) -> int: + return 1 + sum(part.size for part in self.parts) + + def is_super(self) -> bool: + if len(self.parts) != 1: + return False + uop = self.parts[0] + if isinstance(uop, Uop): + return uop.is_super() + else: + return False + + +@dataclass +class PseudoInstruction: + name: str + targets: list[Instruction] + flags: list[str] + opcode: int = -1 + + def dump(self, indent: str) -> None: + print(indent, self.name, "->", " or ".join([t.name for t in self.targets])) + + @property + def properties(self) -> Properties: + return Properties.from_list([i.properties for i in self.targets]) + + +@dataclass +class Family: + name: str + size: str + members: list[Instruction] + + def dump(self, indent: str) -> None: + print(indent, self.name, "= ", ", ".join([m.name for m in self.members])) + + +@dataclass +class Analysis: + instructions: dict[str, Instruction] + uops: dict[str, Uop] + families: dict[str, Family] + pseudos: dict[str, PseudoInstruction] + opmap: dict[str, int] + have_arg: int + min_instrumented: int + + +def analysis_error(message: str, tkn: lexer.Token) -> SyntaxError: + # To do -- support file and line output + # Construct a SyntaxError instance from message and token + return lexer.make_syntax_error(message, tkn.filename, tkn.line, tkn.column, "") + + +def override_error( + name: str, + context: parser.Context | None, + prev_context: parser.Context | None, + token: lexer.Token, +) -> SyntaxError: + return analysis_error( + f"Duplicate definition of '{name}' @ {context} " + f"previous definition @ {prev_context}", + token, + ) + + +def convert_stack_item(item: parser.StackEffect) -> StackItem: + return StackItem(item.name, item.type, item.cond, (item.size or "1")) + + +def analyze_stack(op: parser.InstDef) -> StackEffect: + inputs: list[StackItem] = [ + convert_stack_item(i) for i in op.inputs if isinstance(i, parser.StackEffect) + ] + outputs: list[StackItem] = [convert_stack_item(i) for i in op.outputs] + for input, output in zip(inputs, outputs): + if input.name == output.name: + input.peek = output.peek = True + return StackEffect(inputs, outputs) + + +def analyze_caches(inputs: list[parser.InputEffect]) -> list[CacheEntry]: + caches: list[parser.CacheEffect] = [ + i for i in inputs if isinstance(i, parser.CacheEffect) + ] + for cache in caches: + if cache.name == "unused": + raise analysis_error( + "Unused cache entry in op. Move to enclosing macro.", cache.tokens[0] + ) + return [CacheEntry(i.name, int(i.size)) for i in caches] + + +def variable_used(node: parser.InstDef, name: str) -> bool: + """Determine whether a variable with a given name is used in a node.""" + return any( + token.kind == "IDENTIFIER" and token.text == name for token in node.tokens + ) + + +def is_infallible(op: parser.InstDef) -> bool: + return not ( + variable_used(op, "ERROR_IF") + or variable_used(op, "error") + or variable_used(op, "pop_1_error") + or variable_used(op, "exception_unwind") + or variable_used(op, "resume_with_error") + ) + + +NON_ESCAPING_FUNCTIONS = ( + "Py_INCREF", + "_PyDictOrValues_IsValues", + "_PyObject_DictOrValuesPointer", + "_PyDictOrValues_GetValues", + "_PyObject_MakeInstanceAttributesFromDict", + "Py_DECREF", + "_Py_DECREF_SPECIALIZED", + "DECREF_INPUTS_AND_REUSE_FLOAT", + "PyUnicode_Append", + "_PyLong_IsZero", + "Py_SIZE", + "Py_TYPE", + "PyList_GET_ITEM", + "PyTuple_GET_ITEM", + "PyList_GET_SIZE", + "PyTuple_GET_SIZE", + "Py_ARRAY_LENGTH", + "Py_Unicode_GET_LENGTH", + "PyUnicode_READ_CHAR", + "_Py_SINGLETON", + "PyUnicode_GET_LENGTH", + "_PyLong_IsCompact", + "_PyLong_IsNonNegativeCompact", + "_PyLong_CompactValue", + "_Py_NewRef", + "_Py_IsImmortal", + "_Py_STR", + "_PyLong_Add", + "_PyLong_Multiply", + "_PyLong_Subtract", + "Py_NewRef", + "_PyList_ITEMS", + "_PyTuple_ITEMS", + "_PyList_AppendTakeRef", + "_Py_atomic_load_uintptr_relaxed", + "_PyFrame_GetCode", + "_PyThreadState_HasStackSpace", +) + +ESCAPING_FUNCTIONS = ( + "import_name", + "import_from", +) + + +def makes_escaping_api_call(instr: parser.InstDef) -> bool: + if "CALL_INTRINSIC" in instr.name: + return True + tkns = iter(instr.tokens) + for tkn in tkns: + if tkn.kind != lexer.IDENTIFIER: + continue + try: + next_tkn = next(tkns) + except StopIteration: + return False + if next_tkn.kind != lexer.LPAREN: + continue + if tkn.text in ESCAPING_FUNCTIONS: + return True + if not tkn.text.startswith("Py") and not tkn.text.startswith("_Py"): + continue + if tkn.text.endswith("Check"): + continue + if tkn.text.startswith("Py_Is"): + continue + if tkn.text.endswith("CheckExact"): + continue + if tkn.text in NON_ESCAPING_FUNCTIONS: + continue + return True + return False + + + +EXITS = { + "DISPATCH", + "GO_TO_INSTRUCTION", + "Py_UNREACHABLE", + "DISPATCH_INLINED", + "DISPATCH_GOTO", +} + + +def eval_breaker_at_end(op: parser.InstDef) -> bool: + return op.tokens[-5].text == "CHECK_EVAL_BREAKER" + + +def always_exits(op: parser.InstDef) -> bool: + depth = 0 + tkn_iter = iter(op.tokens) + for tkn in tkn_iter: + if tkn.kind == "LBRACE": + depth += 1 + elif tkn.kind == "RBRACE": + depth -= 1 + elif depth > 1: + continue + elif tkn.kind == "GOTO" or tkn.kind == "RETURN": + return True + elif tkn.kind == "KEYWORD": + if tkn.text in EXITS: + return True + elif tkn.kind == "IDENTIFIER": + if tkn.text in EXITS: + return True + if tkn.text == "DEOPT_IF" or tkn.text == "ERROR_IF": + next(tkn_iter) # '(' + t = next(tkn_iter) + if t.text == "true": + return True + return False + + +def compute_properties(op: parser.InstDef) -> Properties: + has_free = ( + variable_used(op, "PyCell_New") + or variable_used(op, "PyCell_GET") + or variable_used(op, "PyCell_SET") + ) + return Properties( + escapes=makes_escaping_api_call(op), + infallible=is_infallible(op), + deopts=variable_used(op, "DEOPT_IF"), + oparg=variable_used(op, "oparg"), + jumps=variable_used(op, "JUMPBY"), + eval_breaker=variable_used(op, "CHECK_EVAL_BREAKER"), + ends_with_eval_breaker=eval_breaker_at_end(op), + needs_this=variable_used(op, "this_instr"), + always_exits=always_exits(op), + stores_sp=variable_used(op, "STORE_SP"), + tier_one_only=variable_used(op, "TIER_ONE_ONLY"), + uses_co_consts=variable_used(op, "FRAME_CO_CONSTS"), + uses_co_names=variable_used(op, "FRAME_CO_NAMES"), + uses_locals=(variable_used(op, "GETLOCAL") or variable_used(op, "SETLOCAL")) + and not has_free, + has_free=has_free, + ) + + +def make_uop(name: str, op: parser.InstDef, inputs: list[parser.InputEffect]) -> Uop: + return Uop( + name=name, + context=op.context, + annotations=op.annotations, + stack=analyze_stack(op), + caches=analyze_caches(inputs), + body=op.block.tokens, + properties=compute_properties(op), + ) + + +def add_op(op: parser.InstDef, uops: dict[str, Uop]) -> None: + assert op.kind == "op" + if op.name in uops: + if "override" not in op.annotations: + raise override_error( + op.name, op.context, uops[op.name].context, op.tokens[0] + ) + uops[op.name] = make_uop(op.name, op, op.inputs) + + +def add_instruction( + name: str, parts: list[Part], instructions: dict[str, Instruction] +) -> None: + instructions[name] = Instruction(name, parts, None) + + +def desugar_inst( + inst: parser.InstDef, instructions: dict[str, Instruction], uops: dict[str, Uop] +) -> None: + assert inst.kind == "inst" + name = inst.name + op_inputs: list[parser.InputEffect] = [] + parts: list[Part] = [] + uop_index = -1 + # Move unused cache entries to the Instruction, removing them from the Uop. + for input in inst.inputs: + if isinstance(input, parser.CacheEffect) and input.name == "unused": + parts.append(Skip(input.size)) + else: + op_inputs.append(input) + if uop_index < 0: + uop_index = len(parts) + # Place holder for the uop. + parts.append(Skip(0)) + uop = make_uop("_" + inst.name, inst, op_inputs) + uop.implicitly_created = True + uops[inst.name] = uop + if uop_index < 0: + parts.append(uop) + else: + parts[uop_index] = uop + add_instruction(name, parts, instructions) + + +def add_macro( + macro: parser.Macro, instructions: dict[str, Instruction], uops: dict[str, Uop] +) -> None: + parts: list[Uop | Skip] = [] + for part in macro.uops: + match part: + case parser.OpName(): + if part.name not in uops: + analysis_error(f"No Uop named {part.name}", macro.tokens[0]) + parts.append(uops[part.name]) + case parser.CacheEffect(): + parts.append(Skip(part.size)) + case _: + assert False + assert parts + add_instruction(macro.name, parts, instructions) + + +def add_family( + pfamily: parser.Family, + instructions: dict[str, Instruction], + families: dict[str, Family], +) -> None: + family = Family( + pfamily.name, + pfamily.size, + [instructions[member_name] for member_name in pfamily.members], + ) + for member in family.members: + member.family = family + # The head of the family is an implicit jump target for DEOPTs + instructions[family.name].is_target = True + families[family.name] = family + + +def add_pseudo( + pseudo: parser.Pseudo, + instructions: dict[str, Instruction], + pseudos: dict[str, PseudoInstruction], +) -> None: + pseudos[pseudo.name] = PseudoInstruction( + pseudo.name, + [instructions[target] for target in pseudo.targets], + pseudo.flags, + ) + + +def assign_opcodes( + instructions: dict[str, Instruction], + families: dict[str, Family], + pseudos: dict[str, PseudoInstruction], +) -> tuple[dict[str, int], int, int]: + """Assigns opcodes, then returns the opmap, + have_arg and min_instrumented values""" + instmap: dict[str, int] = {} + + # 0 is reserved for cache entries. This helps debugging. + instmap["CACHE"] = 0 + + # 17 is reserved as it is the initial value for the specializing counter. + # This helps catch cases where we attempt to execute a cache. + instmap["RESERVED"] = 17 + + # 149 is RESUME - it is hard coded as such in Tools/build/deepfreeze.py + instmap["RESUME"] = 149 + + # This is an historical oddity. + instmap["BINARY_OP_INPLACE_ADD_UNICODE"] = 3 + + instmap["INSTRUMENTED_LINE"] = 254 + + instrumented = [name for name in instructions if name.startswith("INSTRUMENTED")] + + # Special case: this instruction is implemented in ceval.c + # rather than bytecodes.c, so we need to add it explicitly + # here (at least until we add something to bytecodes.c to + # declare external instructions). + instrumented.append("INSTRUMENTED_LINE") + + specialized: set[str] = set() + no_arg: list[str] = [] + has_arg: list[str] = [] + + for family in families.values(): + specialized.update(inst.name for inst in family.members) + + for inst in instructions.values(): + name = inst.name + if name in specialized: + continue + if name in instrumented: + continue + if inst.properties.oparg: + has_arg.append(name) + else: + no_arg.append(name) + + # Specialized ops appear in their own section + # Instrumented opcodes are at the end of the valid range + min_internal = 150 + min_instrumented = 254 - (len(instrumented) - 1) + assert min_internal + len(specialized) < min_instrumented + + next_opcode = 1 + + def add_instruction(name: str) -> None: + nonlocal next_opcode + if name in instmap: + return # Pre-defined name + while next_opcode in instmap.values(): + next_opcode += 1 + instmap[name] = next_opcode + next_opcode += 1 + + for name in sorted(no_arg): + add_instruction(name) + for name in sorted(has_arg): + add_instruction(name) + # For compatibility + next_opcode = min_internal + for name in sorted(specialized): + add_instruction(name) + next_opcode = min_instrumented + for name in instrumented: + add_instruction(name) + + for name in instructions: + instructions[name].opcode = instmap[name] + + for op, name in enumerate(sorted(pseudos), 256): + instmap[name] = op + pseudos[name].opcode = op + + return instmap, len(no_arg), min_instrumented + + +def analyze_forest(forest: list[parser.AstNode]) -> Analysis: + instructions: dict[str, Instruction] = {} + uops: dict[str, Uop] = {} + families: dict[str, Family] = {} + pseudos: dict[str, PseudoInstruction] = {} + for node in forest: + match node: + case parser.InstDef(name): + if node.kind == "inst": + desugar_inst(node, instructions, uops) + else: + assert node.kind == "op" + add_op(node, uops) + case parser.Macro(): + pass + case parser.Family(): + pass + case parser.Pseudo(): + pass + case _: + assert False + for node in forest: + if isinstance(node, parser.Macro): + add_macro(node, instructions, uops) + for node in forest: + match node: + case parser.Family(): + add_family(node, instructions, families) + case parser.Pseudo(): + add_pseudo(node, instructions, pseudos) + case _: + pass + for uop in uops.values(): + tkn_iter = iter(uop.body) + for tkn in tkn_iter: + if tkn.kind == "IDENTIFIER" and tkn.text == "GO_TO_INSTRUCTION": + if next(tkn_iter).kind != "LPAREN": + continue + target = next(tkn_iter) + if target.kind != "IDENTIFIER": + continue + if target.text in instructions: + instructions[target.text].is_target = True + # Special case BINARY_OP_INPLACE_ADD_UNICODE + # BINARY_OP_INPLACE_ADD_UNICODE is not a normal family member, + # as it is the wrong size, but we need it to maintain an + # historical optimization. + if "BINARY_OP_INPLACE_ADD_UNICODE" in instructions: + inst = instructions["BINARY_OP_INPLACE_ADD_UNICODE"] + inst.family = families["BINARY_OP"] + families["BINARY_OP"].members.append(inst) + opmap, first_arg, min_instrumented = assign_opcodes( + instructions, families, pseudos + ) + return Analysis( + instructions, uops, families, pseudos, opmap, first_arg, min_instrumented + ) + + +def analyze_files(filenames: list[str]) -> Analysis: + return analyze_forest(parser.parse_files(filenames)) + + +def dump_analysis(analysis: Analysis) -> None: + print("Uops:") + for u in analysis.uops.values(): + u.dump(" ") + print("Instructions:") + for i in analysis.instructions.values(): + i.dump(" ") + print("Families:") + for f in analysis.families.values(): + f.dump(" ") + print("Pseudos:") + for p in analysis.pseudos.values(): + p.dump(" ") + + +if __name__ == "__main__": + import sys + + if len(sys.argv) < 2: + print("No input") + else: + filenames = sys.argv[1:] + dump_analysis(analyze_files(filenames)) diff --git a/Tools/cases_generator/cwriter.py b/Tools/cases_generator/cwriter.py new file mode 100644 index 00000000000000..069f0177a74018 --- /dev/null +++ b/Tools/cases_generator/cwriter.py @@ -0,0 +1,146 @@ +import contextlib +from lexer import Token +from typing import TextIO, Iterator + + +class CWriter: + "A writer that understands tokens and how to format C code" + + last_token: Token | None + + def __init__(self, out: TextIO, indent: int, line_directives: bool): + self.out = out + self.base_column = indent * 4 + self.indents = [i * 4 for i in range(indent + 1)] + self.line_directives = line_directives + self.last_token = None + self.newline = True + + def set_position(self, tkn: Token) -> None: + if self.last_token is not None: + if self.last_token.line < tkn.line: + self.out.write("\n") + if self.line_directives: + self.out.write(f'#line {tkn.line} "{tkn.filename}"\n') + self.out.write(" " * self.indents[-1]) + else: + gap = tkn.column - self.last_token.end_column + self.out.write(" " * gap) + elif self.newline: + self.out.write(" " * self.indents[-1]) + self.last_token = tkn + self.newline = False + + def emit_at(self, txt: str, where: Token) -> None: + self.set_position(where) + self.out.write(txt) + + def maybe_dedent(self, txt: str) -> None: + parens = txt.count("(") - txt.count(")") + if parens < 0: + self.indents.pop() + braces = txt.count("{") - txt.count("}") + if braces < 0 or is_label(txt): + self.indents.pop() + + def maybe_indent(self, txt: str) -> None: + parens = txt.count("(") - txt.count(")") + if parens > 0: + if self.last_token: + offset = self.last_token.end_column - 1 + if offset <= self.indents[-1] or offset > 40: + offset = self.indents[-1] + 4 + else: + offset = self.indents[-1] + 4 + self.indents.append(offset) + if is_label(txt): + self.indents.append(self.indents[-1] + 4) + else: + braces = txt.count("{") - txt.count("}") + if braces > 0: + assert braces == 1 + if 'extern "C"' in txt: + self.indents.append(self.indents[-1]) + else: + self.indents.append(self.indents[-1] + 4) + + def emit_text(self, txt: str) -> None: + self.out.write(txt) + + def emit_multiline_comment(self, tkn: Token) -> None: + self.set_position(tkn) + lines = tkn.text.splitlines(True) + first = True + for line in lines: + text = line.lstrip() + if first: + spaces = 0 + else: + spaces = self.indents[-1] + if text.startswith("*"): + spaces += 1 + else: + spaces += 3 + first = False + self.out.write(" " * spaces) + self.out.write(text) + + def emit_token(self, tkn: Token) -> None: + if tkn.kind == "COMMENT" and "\n" in tkn.text: + return self.emit_multiline_comment(tkn) + self.maybe_dedent(tkn.text) + self.set_position(tkn) + self.emit_text(tkn.text) + self.maybe_indent(tkn.text) + + def emit_str(self, txt: str) -> None: + self.maybe_dedent(txt) + if self.newline and txt: + if txt[0] != "\n": + self.out.write(" " * self.indents[-1]) + self.newline = False + self.emit_text(txt) + if txt.endswith("\n"): + self.newline = True + self.maybe_indent(txt) + self.last_token = None + + def emit(self, txt: str | Token) -> None: + if isinstance(txt, Token): + self.emit_token(txt) + elif isinstance(txt, str): + self.emit_str(txt) + else: + assert False + + def start_line(self) -> None: + if not self.newline: + self.out.write("\n") + self.newline = True + self.last_token = None + + @contextlib.contextmanager + def header_guard(self, name: str) -> Iterator[None]: + self.out.write( + f""" +#ifndef {name} +#define {name} +#ifdef __cplusplus +extern "C" {{ +#endif + +""" + ) + yield + self.out.write( + f""" +#ifdef __cplusplus +}} +#endif +#endif /* !{name} */ +""" + ) + + +def is_label(txt: str) -> bool: + return not txt.startswith("//") and txt.endswith(":") diff --git a/Tools/cases_generator/flags.py b/Tools/cases_generator/flags.py deleted file mode 100644 index f7ebdeb0d65677..00000000000000 --- a/Tools/cases_generator/flags.py +++ /dev/null @@ -1,102 +0,0 @@ -import dataclasses - -from formatting import Formatter -import lexer as lx -import parsing - - -@dataclasses.dataclass -class InstructionFlags: - """Construct and manipulate instruction flags""" - - HAS_ARG_FLAG: bool - HAS_CONST_FLAG: bool - HAS_NAME_FLAG: bool - HAS_JUMP_FLAG: bool - HAS_FREE_FLAG: bool - HAS_LOCAL_FLAG: bool - - def __post_init__(self): - self.bitmask = {name: (1 << i) for i, name in enumerate(self.names())} - - @staticmethod - def fromInstruction(instr: parsing.Node): - - has_free = ( - variable_used(instr, "PyCell_New") - or variable_used(instr, "PyCell_GET") - or variable_used(instr, "PyCell_SET") - ) - - return InstructionFlags( - HAS_ARG_FLAG=variable_used(instr, "oparg"), - HAS_CONST_FLAG=variable_used(instr, "FRAME_CO_CONSTS"), - HAS_NAME_FLAG=variable_used(instr, "FRAME_CO_NAMES"), - HAS_JUMP_FLAG=variable_used(instr, "JUMPBY"), - HAS_FREE_FLAG=has_free, - HAS_LOCAL_FLAG=( - variable_used(instr, "GETLOCAL") or variable_used(instr, "SETLOCAL") - ) - and not has_free, - ) - - @staticmethod - def newEmpty(): - return InstructionFlags(False, False, False, False, False, False) - - def add(self, other: "InstructionFlags") -> None: - for name, value in dataclasses.asdict(other).items(): - if value: - setattr(self, name, value) - - def names(self, value=None) -> list[str]: - if value is None: - return list(dataclasses.asdict(self).keys()) - return [n for n, v in dataclasses.asdict(self).items() if v == value] - - def bitmap(self) -> int: - flags = 0 - for name in self.names(): - if getattr(self, name): - flags |= self.bitmask[name] - return flags - - @classmethod - def emit_macros(cls, out: Formatter): - flags = cls.newEmpty() - for name, value in flags.bitmask.items(): - out.emit(f"#define {name} ({value})") - - for name, value in flags.bitmask.items(): - out.emit( - f"#define OPCODE_{name[:-len('_FLAG')]}(OP) " - f"(_PyOpcode_opcode_metadata[OP].flags & ({name}))" - ) - - -def variable_used(node: parsing.Node, name: str) -> bool: - """Determine whether a variable with a given name is used in a node.""" - return any( - token.kind == "IDENTIFIER" and token.text == name for token in node.tokens - ) - - -def variable_used_unspecialized(node: parsing.Node, name: str) -> bool: - """Like variable_used(), but skips #if ENABLE_SPECIALIZATION blocks.""" - tokens: list[lx.Token] = [] - skipping = False - for i, token in enumerate(node.tokens): - if token.kind == "MACRO": - text = "".join(token.text.split()) - # TODO: Handle nested #if - if text == "#if": - if ( - i + 1 < len(node.tokens) - and node.tokens[i + 1].text == "ENABLE_SPECIALIZATION" - ): - skipping = True - elif text in ("#else", "#endif"): - skipping = False - if not skipping: - tokens.append(token) - return any(token.kind == "IDENTIFIER" and token.text == name for token in tokens) diff --git a/Tools/cases_generator/formatting.py b/Tools/cases_generator/formatting.py deleted file mode 100644 index 5894751bd9635c..00000000000000 --- a/Tools/cases_generator/formatting.py +++ /dev/null @@ -1,205 +0,0 @@ -import contextlib -import re -import typing - -from parsing import StackEffect, Family - -UNUSED = "unused" - - -class Formatter: - """Wraps an output stream with the ability to indent etc.""" - - stream: typing.TextIO - prefix: str - emit_line_directives: bool = False - lineno: int # Next line number, 1-based - filename: str # Slightly improved stream.filename - nominal_lineno: int - nominal_filename: str - - def __init__( - self, - stream: typing.TextIO, - indent: int, - emit_line_directives: bool = False, - comment: str = "//", - ) -> None: - self.stream = stream - self.prefix = " " * indent - self.emit_line_directives = emit_line_directives - self.comment = comment - self.lineno = 1 - self.filename = prettify_filename(self.stream.name) - self.nominal_lineno = 1 - self.nominal_filename = self.filename - - def write_raw(self, s: str) -> None: - self.stream.write(s) - newlines = s.count("\n") - self.lineno += newlines - self.nominal_lineno += newlines - - def emit(self, arg: str) -> None: - if arg: - self.write_raw(f"{self.prefix}{arg}\n") - else: - self.write_raw("\n") - - def set_lineno(self, lineno: int, filename: str) -> None: - if self.emit_line_directives: - if lineno != self.nominal_lineno or filename != self.nominal_filename: - self.emit(f'#line {lineno} "{filename}"') - self.nominal_lineno = lineno - self.nominal_filename = filename - - def reset_lineno(self) -> None: - if self.lineno != self.nominal_lineno or self.filename != self.nominal_filename: - self.set_lineno(self.lineno + 1, self.filename) - - @contextlib.contextmanager - def indent(self): - self.prefix += " " - yield - self.prefix = self.prefix[:-4] - - @contextlib.contextmanager - def block(self, head: str, tail: str = ""): - if head: - self.emit(head + " {") - else: - self.emit("{") - with self.indent(): - yield - self.emit("}" + tail) - - def stack_adjust( - self, - input_effects: list[StackEffect], - output_effects: list[StackEffect], - ): - shrink, isym = list_effect_size(input_effects) - grow, osym = list_effect_size(output_effects) - diff = grow - shrink - if isym and isym != osym: - self.emit(f"STACK_SHRINK({isym});") - if diff < 0: - self.emit(f"STACK_SHRINK({-diff});") - if diff > 0: - self.emit(f"STACK_GROW({diff});") - if osym and osym != isym: - self.emit(f"STACK_GROW({osym});") - - def declare(self, dst: StackEffect, src: StackEffect | None): - if dst.name == UNUSED or dst.cond == "0": - return - typ = f"{dst.type}" if dst.type else "PyObject *" - if src: - cast = self.cast(dst, src) - initexpr = f"{cast}{src.name}" - if src.cond and src.cond != "1": - initexpr = f"{parenthesize_cond(src.cond)} ? {initexpr} : NULL" - init = f" = {initexpr}" - elif dst.cond and dst.cond != "1": - init = " = NULL" - else: - init = "" - sepa = "" if typ.endswith("*") else " " - self.emit(f"{typ}{sepa}{dst.name}{init};") - - def assign(self, dst: StackEffect, src: StackEffect): - if src.name == UNUSED or dst.name == UNUSED: - return - cast = self.cast(dst, src) - if re.match(r"^REG\(oparg(\d+)\)$", dst.name): - self.emit(f"Py_XSETREF({dst.name}, {cast}{src.name});") - else: - stmt = f"{dst.name} = {cast}{src.name};" - if src.cond and src.cond != "1": - if src.cond == "0": - # It will not be executed - return - stmt = f"if ({src.cond}) {{ {stmt} }}" - self.emit(stmt) - - def cast(self, dst: StackEffect, src: StackEffect) -> str: - return f"({dst.type or 'PyObject *'})" if src.type != dst.type else "" - - def static_assert_family_size( - self, name: str, family: Family | None, cache_offset: int - ) -> None: - """Emit a static_assert for the size of a family, if known. - - This will fail at compile time if the cache size computed from - the instruction definition does not match the size of the struct - used by specialize.c. - """ - if family and name == family.name: - cache_size = family.size - if cache_size: - self.emit( - f"static_assert({cache_size} == {cache_offset}, " - f'"incorrect cache size");' - ) - - -def prettify_filename(filename: str) -> str: - # Make filename more user-friendly and less platform-specific, - # it is only used for error reporting at this point. - filename = filename.replace("\\", "/") - if filename.startswith("./"): - filename = filename[2:] - if filename.endswith(".new"): - filename = filename[:-4] - return filename - - -def list_effect_size(effects: list[StackEffect]) -> tuple[int, str]: - numeric = 0 - symbolic: list[str] = [] - for effect in effects: - diff, sym = effect_size(effect) - numeric += diff - if sym: - symbolic.append(maybe_parenthesize(sym)) - return numeric, " + ".join(symbolic) - - -def effect_size(effect: StackEffect) -> tuple[int, str]: - """Return the 'size' impact of a stack effect. - - Returns a tuple (numeric, symbolic) where: - - - numeric is an int giving the statically analyzable size of the effect - - symbolic is a string representing a variable effect (e.g. 'oparg*2') - - At most one of these will be non-zero / non-empty. - """ - if effect.size: - assert not effect.cond, "Array effects cannot have a condition" - return 0, effect.size - elif effect.cond: - if effect.cond in ("0", "1"): - return int(effect.cond), "" - return 0, f"{maybe_parenthesize(effect.cond)} ? 1 : 0" - else: - return 1, "" - - -def maybe_parenthesize(sym: str) -> str: - """Add parentheses around a string if it contains an operator. - - An exception is made for '*' which is common and harmless - in the context where the symbolic size is used. - """ - if re.match(r"^[\s\w*]+$", sym): - return sym - else: - return f"({sym})" - - -def parenthesize_cond(cond: str) -> str: - """Parenthesize a condition, but only if it contains ?: itself.""" - if "?" in cond: - cond = f"({cond})" - return cond diff --git a/Tools/cases_generator/generate_cases.py b/Tools/cases_generator/generate_cases.py deleted file mode 100644 index d35a16a80e8d00..00000000000000 --- a/Tools/cases_generator/generate_cases.py +++ /dev/null @@ -1,651 +0,0 @@ -"""Generate the main interpreter switch. -Reads the instruction definitions from bytecodes.c. -Writes the cases to generated_cases.c.h, which is #included in ceval.c. -""" - -import argparse -import os -import posixpath -import sys -import typing - -import stacking # Early import to avoid circular import -from analysis import Analyzer -from formatting import Formatter, list_effect_size -from flags import InstructionFlags, variable_used -from instructions import ( - AnyInstruction, - Component, - Instruction, - MacroInstruction, - MacroParts, - PseudoInstruction, - StackEffect, - OverriddenInstructionPlaceHolder, - TIER_TWO, -) -import parsing -from parsing import StackEffect - - -HERE = os.path.dirname(__file__) -ROOT = os.path.join(HERE, "../..") -THIS = os.path.relpath(__file__, ROOT).replace(os.path.sep, posixpath.sep) - -DEFAULT_INPUT = os.path.relpath(os.path.join(ROOT, "Python/bytecodes.c")) -DEFAULT_OUTPUT = os.path.relpath(os.path.join(ROOT, "Python/generated_cases.c.h")) -DEFAULT_METADATA_OUTPUT = os.path.relpath( - os.path.join(ROOT, "Include/internal/pycore_opcode_metadata.h") -) -DEFAULT_PYMETADATA_OUTPUT = os.path.relpath( - os.path.join(ROOT, "Lib/_opcode_metadata.py") -) -DEFAULT_EXECUTOR_OUTPUT = os.path.relpath( - os.path.join(ROOT, "Python/executor_cases.c.h") -) - -# Constants used instead of size for macro expansions. -# Note: 1, 2, 4 must match actual cache entry sizes. -OPARG_SIZES = { - "OPARG_FULL": 0, - "OPARG_CACHE_1": 1, - "OPARG_CACHE_2": 2, - "OPARG_CACHE_4": 4, - "OPARG_TOP": 5, - "OPARG_BOTTOM": 6, -} - -INSTR_FMT_PREFIX = "INSTR_FMT_" - -arg_parser = argparse.ArgumentParser( - description="Generate the code for the interpreter switch.", - formatter_class=argparse.ArgumentDefaultsHelpFormatter, -) -arg_parser.add_argument( - "-o", "--output", type=str, help="Generated code", default=DEFAULT_OUTPUT -) -arg_parser.add_argument( - "-m", - "--metadata", - type=str, - help="Generated C metadata", - default=DEFAULT_METADATA_OUTPUT, -) -arg_parser.add_argument( - "-p", - "--pymetadata", - type=str, - help="Generated Python metadata", - default=DEFAULT_PYMETADATA_OUTPUT, -) -arg_parser.add_argument( - "-l", "--emit-line-directives", help="Emit #line directives", action="store_true" -) -arg_parser.add_argument( - "input", nargs=argparse.REMAINDER, help="Instruction definition file(s)" -) -arg_parser.add_argument( - "-e", - "--executor-cases", - type=str, - help="Write executor cases to this file", - default=DEFAULT_EXECUTOR_OUTPUT, -) - - -class Generator(Analyzer): - def get_stack_effect_info( - self, thing: parsing.InstDef | parsing.Macro | parsing.Pseudo - ) -> tuple[AnyInstruction | None, str | None, str | None]: - def effect_str(effects: list[StackEffect]) -> str: - n_effect, sym_effect = list_effect_size(effects) - if sym_effect: - return f"{sym_effect} + {n_effect}" if n_effect else sym_effect - return str(n_effect) - - instr: AnyInstruction | None - popped: str | None - pushed: str | None - match thing: - case parsing.InstDef(): - if thing.kind != "op": - instr = self.instrs[thing.name] - popped = effect_str(instr.input_effects) - pushed = effect_str(instr.output_effects) - else: - instr = None - popped = "" - pushed = "" - case parsing.Macro(): - instr = self.macro_instrs[thing.name] - popped, pushed = stacking.get_stack_effect_info_for_macro(instr) - case parsing.Pseudo(): - instr = self.pseudo_instrs[thing.name] - popped = pushed = None - # Calculate stack effect, and check that it's the the same - # for all targets. - for target in self.pseudos[thing.name].targets: - target_instr = self.instrs.get(target) - # Currently target is always an instr. This could change - # in the future, e.g., if we have a pseudo targetting a - # macro instruction. - assert target_instr - target_popped = effect_str(target_instr.input_effects) - target_pushed = effect_str(target_instr.output_effects) - if popped is None and pushed is None: - popped, pushed = target_popped, target_pushed - else: - assert popped == target_popped - assert pushed == target_pushed - case _: - typing.assert_never(thing) - return instr, popped, pushed - - def write_stack_effect_functions(self) -> None: - popped_data: list[tuple[AnyInstruction, str]] = [] - pushed_data: list[tuple[AnyInstruction, str]] = [] - for thing in self.everything: - if isinstance(thing, OverriddenInstructionPlaceHolder): - continue - instr, popped, pushed = self.get_stack_effect_info(thing) - if instr is not None: - assert popped is not None and pushed is not None - popped_data.append((instr, popped)) - pushed_data.append((instr, pushed)) - - def write_function( - direction: str, data: list[tuple[AnyInstruction, str]] - ) -> None: - self.out.emit("") - self.out.emit("#ifndef NEED_OPCODE_METADATA") - self.out.emit( - f"extern int _PyOpcode_num_{direction}(int opcode, int oparg, bool jump);" - ) - self.out.emit("#else") - self.out.emit("int") - self.out.emit( - f"_PyOpcode_num_{direction}(int opcode, int oparg, bool jump) {{" - ) - self.out.emit(" switch(opcode) {") - for instr, effect in data: - self.out.emit(f" case {instr.name}:") - self.out.emit(f" return {effect};") - self.out.emit(" default:") - self.out.emit(" return -1;") - self.out.emit(" }") - self.out.emit("}") - self.out.emit("#endif") - - write_function("popped", popped_data) - write_function("pushed", pushed_data) - self.out.emit("") - - def from_source_files(self) -> str: - filenames = [] - for filename in self.input_filenames: - try: - filename = os.path.relpath(filename, ROOT) - except ValueError: - # May happen on Windows if root and temp on different volumes - pass - filenames.append(filename) - paths = f"\n{self.out.comment} ".join(filenames) - return f"{self.out.comment} from:\n{self.out.comment} {paths}\n" - - def write_provenance_header(self): - self.out.write_raw(f"{self.out.comment} This file is generated by {THIS}\n") - self.out.write_raw(self.from_source_files()) - self.out.write_raw(f"{self.out.comment} Do not edit!\n") - - def write_metadata(self, metadata_filename: str, pymetadata_filename: str) -> None: - """Write instruction metadata to output file.""" - - # Compute the set of all instruction formats. - all_formats: set[str] = set() - for thing in self.everything: - format: str | None - match thing: - case OverriddenInstructionPlaceHolder(): - continue - case parsing.InstDef(): - format = self.instrs[thing.name].instr_fmt - case parsing.Macro(): - format = self.macro_instrs[thing.name].instr_fmt - case parsing.Pseudo(): - format = None - for target in self.pseudos[thing.name].targets: - target_instr = self.instrs.get(target) - assert target_instr - if format is None: - format = target_instr.instr_fmt - else: - assert format == target_instr.instr_fmt - assert format is not None - case _: - typing.assert_never(thing) - all_formats.add(format) - - # Turn it into a sorted list of enum values. - format_enums = [INSTR_FMT_PREFIX + format for format in sorted(all_formats)] - - with open(metadata_filename, "w") as f: - # Create formatter - self.out = Formatter(f, 0) - - self.write_provenance_header() - - self.out.emit("\n#include ") - - self.write_pseudo_instrs() - - self.out.emit("") - self.write_uop_items(lambda name, counter: f"#define {name} {counter}") - - self.write_stack_effect_functions() - - # Write the enum definition for instruction formats. - with self.out.block("enum InstructionFormat", ";"): - for enum in format_enums: - self.out.emit(enum + ",") - - self.out.emit("") - self.out.emit( - "#define IS_VALID_OPCODE(OP) \\\n" - " (((OP) >= 0) && ((OP) < OPCODE_METADATA_SIZE) && \\\n" - " (_PyOpcode_opcode_metadata[(OP)].valid_entry))" - ) - - self.out.emit("") - InstructionFlags.emit_macros(self.out) - - self.out.emit("") - with self.out.block("struct opcode_metadata", ";"): - self.out.emit("bool valid_entry;") - self.out.emit("enum InstructionFormat instr_format;") - self.out.emit("int flags;") - self.out.emit("") - - with self.out.block("struct opcode_macro_expansion", ";"): - self.out.emit("int nuops;") - self.out.emit( - "struct { int16_t uop; int8_t size; int8_t offset; } uops[8];" - ) - self.out.emit("") - - for key, value in OPARG_SIZES.items(): - self.out.emit(f"#define {key} {value}") - self.out.emit("") - - self.out.emit( - "#define OPCODE_METADATA_FMT(OP) " - "(_PyOpcode_opcode_metadata[(OP)].instr_format)" - ) - self.out.emit("#define SAME_OPCODE_METADATA(OP1, OP2) \\") - self.out.emit( - " (OPCODE_METADATA_FMT(OP1) == OPCODE_METADATA_FMT(OP2))" - ) - self.out.emit("") - - # Write metadata array declaration - self.out.emit("#define OPCODE_METADATA_SIZE 512") - self.out.emit("#define OPCODE_UOP_NAME_SIZE 512") - self.out.emit("#define OPCODE_MACRO_EXPANSION_SIZE 256") - self.out.emit("") - self.out.emit("#ifndef NEED_OPCODE_METADATA") - self.out.emit( - "extern const struct opcode_metadata " - "_PyOpcode_opcode_metadata[OPCODE_METADATA_SIZE];" - ) - self.out.emit( - "extern const struct opcode_macro_expansion " - "_PyOpcode_macro_expansion[OPCODE_MACRO_EXPANSION_SIZE];" - ) - self.out.emit( - "extern const char * const _PyOpcode_uop_name[OPCODE_UOP_NAME_SIZE];" - ) - self.out.emit("#else // if NEED_OPCODE_METADATA") - - self.out.emit( - "const struct opcode_metadata " - "_PyOpcode_opcode_metadata[OPCODE_METADATA_SIZE] = {" - ) - - # Write metadata for each instruction - for thing in self.everything: - match thing: - case OverriddenInstructionPlaceHolder(): - continue - case parsing.InstDef(): - if thing.kind != "op": - self.write_metadata_for_inst(self.instrs[thing.name]) - case parsing.Macro(): - self.write_metadata_for_macro(self.macro_instrs[thing.name]) - case parsing.Pseudo(): - self.write_metadata_for_pseudo(self.pseudo_instrs[thing.name]) - case _: - typing.assert_never(thing) - - # Write end of array - self.out.emit("};") - - with self.out.block( - "const struct opcode_macro_expansion " - "_PyOpcode_macro_expansion[OPCODE_MACRO_EXPANSION_SIZE] =", - ";", - ): - # Write macro expansion for each non-pseudo instruction - for thing in self.everything: - match thing: - case OverriddenInstructionPlaceHolder(): - pass - case parsing.InstDef(name=name): - instr = self.instrs[name] - # Since an 'op' is not a bytecode, it has no expansion; but 'inst' is - if instr.kind == "inst" and instr.is_viable_uop(): - # Construct a dummy Component -- input/output mappings are not used - part = Component(instr, instr.active_caches) - self.write_macro_expansions(instr.name, [part]) - elif instr.kind == "inst" and variable_used( - instr.inst, "oparg1" - ): - assert variable_used( - instr.inst, "oparg2" - ), "Half super-instr?" - self.write_super_expansions(instr.name) - case parsing.Macro(): - mac = self.macro_instrs[thing.name] - self.write_macro_expansions(mac.name, mac.parts) - case parsing.Pseudo(): - pass - case _: - typing.assert_never(thing) - - with self.out.block( - "const char * const _PyOpcode_uop_name[OPCODE_UOP_NAME_SIZE] =", ";" - ): - self.write_uop_items(lambda name, counter: f'[{name}] = "{name}",') - - self.out.emit("#endif // NEED_OPCODE_METADATA") - - with open(pymetadata_filename, "w") as f: - # Create formatter - self.out = Formatter(f, 0, comment="#") - - self.write_provenance_header() - - self.out.emit("") - self.out.emit("_specializations = {") - for name, family in self.families.items(): - with self.out.indent(): - self.out.emit(f'"{family.name}": [') - with self.out.indent(): - for m in family.members: - self.out.emit(f'"{m}",') - self.out.emit(f"],") - self.out.emit("}") - - # Handle special case - self.out.emit("") - self.out.emit("# An irregular case:") - self.out.emit( - '_specializations["BINARY_OP"].append(' - '"BINARY_OP_INPLACE_ADD_UNICODE")' - ) - - # Make list of specialized instructions - self.out.emit("") - self.out.emit( - "_specialized_instructions = [" - "opcode for family in _specializations.values() for opcode in family" - "]" - ) - - def write_pseudo_instrs(self) -> None: - """Write the IS_PSEUDO_INSTR macro""" - self.out.emit("\n\n#define IS_PSEUDO_INSTR(OP) ( \\") - for op in self.pseudos: - self.out.emit(f" ((OP) == {op}) || \\") - self.out.emit(f" 0)") - - def write_uop_items(self, make_text: typing.Callable[[str, int], str]) -> None: - """Write '#define XXX NNN' for each uop""" - counter = 300 # TODO: Avoid collision with pseudo instructions - seen = set() - - def add(name: str) -> None: - if name in seen: - return - nonlocal counter - self.out.emit(make_text(name, counter)) - counter += 1 - seen.add(name) - - # These two are first by convention - add("EXIT_TRACE") - add("SAVE_IP") - - for instr in self.instrs.values(): - if instr.kind == "op" and instr.is_viable_uop(): - add(instr.name) - - def write_macro_expansions(self, name: str, parts: MacroParts) -> None: - """Write the macro expansions for a macro-instruction.""" - # TODO: Refactor to share code with write_cody(), is_viaible_uop(), etc. - offset = 0 # Cache effect offset - expansions: list[tuple[str, int, int]] = [] # [(name, size, offset), ...] - for part in parts: - if isinstance(part, Component): - # All component instructions must be viable uops - if not part.instr.is_viable_uop(): - # This note just reminds us about macros that cannot - # be expanded to Tier 2 uops. It is not an error. - # It is sometimes emitted for macros that have a - # manual translation in translate_bytecode_to_trace() - # in Python/optimizer.c. - self.note( - f"Part {part.instr.name} of {name} is not a viable uop", - part.instr.inst, - ) - return - if not part.active_caches: - size, offset = OPARG_SIZES["OPARG_FULL"], 0 - else: - # If this assert triggers, is_viable_uops() lied - assert len(part.active_caches) == 1, (name, part.instr.name) - cache = part.active_caches[0] - size, offset = cache.effect.size, cache.offset - expansions.append((part.instr.name, size, offset)) - assert len(expansions) > 0, f"Macro {name} has empty expansion?!" - self.write_expansions(name, expansions) - - def write_super_expansions(self, name: str) -> None: - """Write special macro expansions for super-instructions. - - If you get an assertion failure here, you probably have accidentally - violated one of the assumptions here. - - - A super-instruction's name is of the form FIRST_SECOND where - FIRST and SECOND are regular instructions whose name has the - form FOO_BAR. Thus, there must be exactly 3 underscores. - Example: LOAD_CONST_STORE_FAST. - - - A super-instruction's body uses `oparg1 and `oparg2`, and no - other instruction's body uses those variable names. - - - A super-instruction has no active (used) cache entries. - - In the expansion, the first instruction's operand is all but the - bottom 4 bits of the super-instruction's oparg, and the second - instruction's operand is the bottom 4 bits. We use the special - size codes OPARG_TOP and OPARG_BOTTOM for these. - """ - pieces = name.split("_") - assert len(pieces) == 4, f"{name} doesn't look like a super-instr" - name1 = "_".join(pieces[:2]) - name2 = "_".join(pieces[2:]) - assert name1 in self.instrs, f"{name1} doesn't match any instr" - assert name2 in self.instrs, f"{name2} doesn't match any instr" - instr1 = self.instrs[name1] - instr2 = self.instrs[name2] - assert not instr1.active_caches, f"{name1} has active caches" - assert not instr2.active_caches, f"{name2} has active caches" - expansions: list[tuple[str, int, int]] = [ - (name1, OPARG_SIZES["OPARG_TOP"], 0), - (name2, OPARG_SIZES["OPARG_BOTTOM"], 0), - ] - self.write_expansions(name, expansions) - - def write_expansions( - self, name: str, expansions: list[tuple[str, int, int]] - ) -> None: - pieces = [ - f"{{ {name}, {size}, {offset} }}" for name, size, offset in expansions - ] - self.out.emit( - f"[{name}] = " - f"{{ .nuops = {len(pieces)}, .uops = {{ {', '.join(pieces)} }} }}," - ) - - def emit_metadata_entry(self, name: str, fmt: str, flags: InstructionFlags) -> None: - flag_names = flags.names(value=True) - if not flag_names: - flag_names.append("0") - self.out.emit( - f" [{name}] = {{ true, {INSTR_FMT_PREFIX}{fmt}," - f" {' | '.join(flag_names)} }}," - ) - - def write_metadata_for_inst(self, instr: Instruction) -> None: - """Write metadata for a single instruction.""" - self.emit_metadata_entry(instr.name, instr.instr_fmt, instr.instr_flags) - - def write_metadata_for_macro(self, mac: MacroInstruction) -> None: - """Write metadata for a macro-instruction.""" - self.emit_metadata_entry(mac.name, mac.instr_fmt, mac.instr_flags) - - def write_metadata_for_pseudo(self, ps: PseudoInstruction) -> None: - """Write metadata for a macro-instruction.""" - self.emit_metadata_entry(ps.name, ps.instr_fmt, ps.instr_flags) - - def write_instructions( - self, output_filename: str, emit_line_directives: bool - ) -> None: - """Write instructions to output file.""" - with open(output_filename, "w") as f: - # Create formatter - self.out = Formatter(f, 8, emit_line_directives) - - self.write_provenance_header() - - # Write and count instructions of all kinds - n_instrs = 0 - n_macros = 0 - for thing in self.everything: - match thing: - case OverriddenInstructionPlaceHolder(): - self.write_overridden_instr_place_holder(thing) - case parsing.InstDef(): - if thing.kind != "op": - n_instrs += 1 - self.write_instr(self.instrs[thing.name]) - case parsing.Macro(): - n_macros += 1 - mac = self.macro_instrs[thing.name] - stacking.write_macro_instr(mac, self.out, self.families.get(mac.name)) - # self.write_macro(self.macro_instrs[thing.name]) - case parsing.Pseudo(): - pass - case _: - typing.assert_never(thing) - - print( - f"Wrote {n_instrs} instructions and {n_macros} macros " - f"to {output_filename}", - file=sys.stderr, - ) - - def write_executor_instructions( - self, executor_filename: str, emit_line_directives: bool - ) -> None: - """Generate cases for the Tier 2 interpreter.""" - n_instrs = 0 - n_uops = 0 - with open(executor_filename, "w") as f: - self.out = Formatter(f, 8, emit_line_directives) - self.write_provenance_header() - for thing in self.everything: - match thing: - case OverriddenInstructionPlaceHolder(): - # TODO: Is this helpful? - self.write_overridden_instr_place_holder(thing) - case parsing.InstDef(): - instr = self.instrs[thing.name] - if instr.is_viable_uop(): - if instr.kind == "op": - n_uops += 1 - else: - n_instrs += 1 - self.out.emit("") - with self.out.block(f"case {thing.name}:"): - instr.write(self.out, tier=TIER_TWO) - if instr.check_eval_breaker: - self.out.emit("CHECK_EVAL_BREAKER();") - self.out.emit("break;") - # elif instr.kind != "op": - # print(f"NOTE: {thing.name} is not a viable uop") - case parsing.Macro(): - pass - case parsing.Pseudo(): - pass - case _: - typing.assert_never(thing) - print( - f"Wrote {n_instrs} instructions and {n_uops} ops to {executor_filename}", - file=sys.stderr, - ) - - def write_overridden_instr_place_holder( - self, place_holder: OverriddenInstructionPlaceHolder - ) -> None: - self.out.emit("") - self.out.emit( - f"{self.out.comment} TARGET({place_holder.name}) overridden by later definition" - ) - - def write_instr(self, instr: Instruction) -> None: - name = instr.name - self.out.emit("") - if instr.inst.override: - self.out.emit("{self.out.comment} Override") - with self.out.block(f"TARGET({name})"): - if instr.predicted: - self.out.emit(f"PREDICTED({name});") - instr.write(self.out) - if not instr.always_exits: - if instr.check_eval_breaker: - self.out.emit("CHECK_EVAL_BREAKER();") - self.out.emit(f"DISPATCH();") - - -def main(): - """Parse command line, parse input, analyze, write output.""" - args = arg_parser.parse_args() # Prints message and sys.exit(2) on error - if len(args.input) == 0: - args.input.append(DEFAULT_INPUT) - - # Raises OSError if input unreadable - a = Generator(args.input) - - a.parse() # Raises SyntaxError on failure - a.analyze() # Prints messages and sets a.errors on failure - if a.errors: - sys.exit(f"Found {a.errors} errors") - - # These raise OSError if output can't be written - a.write_instructions(args.output, args.emit_line_directives) - a.write_metadata(args.metadata, args.pymetadata) - a.write_executor_instructions(args.executor_cases, args.emit_line_directives) - - -if __name__ == "__main__": - main() diff --git a/Tools/cases_generator/generators_common.py b/Tools/cases_generator/generators_common.py new file mode 100644 index 00000000000000..5a42a05c5c2ef2 --- /dev/null +++ b/Tools/cases_generator/generators_common.py @@ -0,0 +1,215 @@ +from pathlib import Path +from typing import TextIO + +from analyzer import ( + Instruction, + Uop, + analyze_files, + Properties, + Skip, +) +from cwriter import CWriter +from typing import Callable, Mapping, TextIO, Iterator +from lexer import Token +from stack import StackOffset, Stack + + +ROOT = Path(__file__).parent.parent.parent +DEFAULT_INPUT = (ROOT / "Python/bytecodes.c").absolute().as_posix() + + +def root_relative_path(filename: str) -> str: + try: + return Path(filename).absolute().relative_to(ROOT).as_posix() + except ValueError: + # Not relative to root, just return original path. + return filename + + +def write_header(generator: str, sources: list[str], outfile: TextIO, comment: str = "//") -> None: + outfile.write( + f"""{comment} This file is generated by {root_relative_path(generator)} +{comment} from: +{comment} {", ".join(root_relative_path(src) for src in sources)} +{comment} Do not edit! +""" + ) + + +def emit_to(out: CWriter, tkn_iter: Iterator[Token], end: str) -> None: + parens = 0 + for tkn in tkn_iter: + if tkn.kind == end and parens == 0: + return + if tkn.kind == "LPAREN": + parens += 1 + if tkn.kind == "RPAREN": + parens -= 1 + out.emit(tkn) + + +def replace_deopt( + out: CWriter, + tkn: Token, + tkn_iter: Iterator[Token], + uop: Uop, + unused: Stack, + inst: Instruction | None, +) -> None: + out.emit_at("DEOPT_IF", tkn) + out.emit(next(tkn_iter)) + emit_to(out, tkn_iter, "RPAREN") + next(tkn_iter) # Semi colon + out.emit(", ") + assert inst is not None + assert inst.family is not None + out.emit(inst.family.name) + out.emit(");\n") + + +def replace_error( + out: CWriter, + tkn: Token, + tkn_iter: Iterator[Token], + uop: Uop, + stack: Stack, + inst: Instruction | None, +) -> None: + out.emit_at("if ", tkn) + out.emit(next(tkn_iter)) + emit_to(out, tkn_iter, "COMMA") + label = next(tkn_iter).text + next(tkn_iter) # RPAREN + next(tkn_iter) # Semi colon + out.emit(") ") + c_offset = stack.peek_offset.to_c() + try: + offset = -int(c_offset) + close = ";\n" + except ValueError: + offset = None + out.emit(f"{{ stack_pointer += {c_offset}; ") + close = "; }\n" + out.emit("goto ") + if offset: + out.emit(f"pop_{offset}_") + out.emit(label) + out.emit(close) + + +def replace_decrefs( + out: CWriter, + tkn: Token, + tkn_iter: Iterator[Token], + uop: Uop, + stack: Stack, + inst: Instruction | None, +) -> None: + next(tkn_iter) + next(tkn_iter) + next(tkn_iter) + out.emit_at("", tkn) + for var in uop.stack.inputs: + if var.name == "unused" or var.name == "null" or var.peek: + continue + if var.size != "1": + out.emit(f"for (int _i = {var.size}; --_i >= 0;) {{\n") + out.emit(f"Py_DECREF({var.name}[_i]);\n") + out.emit("}\n") + elif var.condition: + out.emit(f"Py_XDECREF({var.name});\n") + else: + out.emit(f"Py_DECREF({var.name});\n") + + +def replace_store_sp( + out: CWriter, + tkn: Token, + tkn_iter: Iterator[Token], + uop: Uop, + stack: Stack, + inst: Instruction | None, +) -> None: + next(tkn_iter) + next(tkn_iter) + next(tkn_iter) + out.emit_at("", tkn) + stack.flush(out) + out.emit("_PyFrame_SetStackPointer(frame, stack_pointer);\n") + + +def replace_check_eval_breaker( + out: CWriter, + tkn: Token, + tkn_iter: Iterator[Token], + uop: Uop, + stack: Stack, + inst: Instruction | None, +) -> None: + next(tkn_iter) + next(tkn_iter) + next(tkn_iter) + if not uop.properties.ends_with_eval_breaker: + out.emit_at("CHECK_EVAL_BREAKER();", tkn) + + +REPLACEMENT_FUNCTIONS = { + "DEOPT_IF": replace_deopt, + "ERROR_IF": replace_error, + "DECREF_INPUTS": replace_decrefs, + "CHECK_EVAL_BREAKER": replace_check_eval_breaker, + "STORE_SP": replace_store_sp, +} + +ReplacementFunctionType = Callable[ + [CWriter, Token, Iterator[Token], Uop, Stack, Instruction | None], None +] + + +def emit_tokens( + out: CWriter, + uop: Uop, + stack: Stack, + inst: Instruction | None, + replacement_functions: Mapping[ + str, ReplacementFunctionType + ] = REPLACEMENT_FUNCTIONS, +) -> None: + tkns = uop.body[1:-1] + if not tkns: + return + tkn_iter = iter(tkns) + out.start_line() + for tkn in tkn_iter: + if tkn.kind == "IDENTIFIER" and tkn.text in replacement_functions: + replacement_functions[tkn.text](out, tkn, tkn_iter, uop, stack, inst) + else: + out.emit(tkn) + + +def cflags(p: Properties) -> str: + flags: list[str] = [] + if p.oparg: + flags.append("HAS_ARG_FLAG") + if p.uses_co_consts: + flags.append("HAS_CONST_FLAG") + if p.uses_co_names: + flags.append("HAS_NAME_FLAG") + if p.jumps: + flags.append("HAS_JUMP_FLAG") + if p.has_free: + flags.append("HAS_FREE_FLAG") + if p.uses_locals: + flags.append("HAS_LOCAL_FLAG") + if p.eval_breaker: + flags.append("HAS_EVAL_BREAK_FLAG") + if p.deopts: + flags.append("HAS_DEOPT_FLAG") + if not p.infallible: + flags.append("HAS_ERROR_FLAG") + if p.escapes: + flags.append("HAS_ESCAPES_FLAG") + if flags: + return " | ".join(flags) + else: + return "0" diff --git a/Tools/cases_generator/instructions.py b/Tools/cases_generator/instructions.py deleted file mode 100644 index aa94dbb07ea1c0..00000000000000 --- a/Tools/cases_generator/instructions.py +++ /dev/null @@ -1,343 +0,0 @@ -import dataclasses -import re -import typing - -from flags import InstructionFlags, variable_used, variable_used_unspecialized -from formatting import ( - Formatter, - UNUSED, - list_effect_size, -) -import lexer as lx -import parsing -from parsing import StackEffect -import stacking - -BITS_PER_CODE_UNIT = 16 - - -@dataclasses.dataclass -class ActiveCacheEffect: - """Wraps a CacheEffect that is actually used, in context.""" - - effect: parsing.CacheEffect - offset: int - - -FORBIDDEN_NAMES_IN_UOPS = ( - "resume_with_error", - "kwnames", - "next_instr", - "oparg1", # Proxy for super-instructions like LOAD_FAST_LOAD_FAST - "JUMPBY", - "DISPATCH", - "INSTRUMENTED_JUMP", - "throwflag", - "exception_unwind", - "import_from", - "import_name", - "_PyObject_CallNoArgs", # Proxy for BEFORE_WITH -) - - -# Interpreter tiers -TIER_ONE: typing.Final = 1 # Specializing adaptive interpreter (PEP 659) -TIER_TWO: typing.Final = 2 # Experimental tracing interpreter -Tiers: typing.TypeAlias = typing.Literal[1, 2] - - -@dataclasses.dataclass -class Instruction: - """An instruction with additional data and code.""" - - # Parts of the underlying instruction definition - inst: parsing.InstDef - kind: typing.Literal["inst", "op"] - name: str - block: parsing.Block - block_text: list[str] # Block.text, less curlies, less PREDICT() calls - block_line: int # First line of block in original code - - # Computed by constructor - always_exits: bool - has_deopt: bool - cache_offset: int - cache_effects: list[parsing.CacheEffect] - input_effects: list[StackEffect] - output_effects: list[StackEffect] - unmoved_names: frozenset[str] - instr_fmt: str - instr_flags: InstructionFlags - active_caches: list[ActiveCacheEffect] - - # Set later - family: parsing.Family | None = None - predicted: bool = False - - def __init__(self, inst: parsing.InstDef): - self.inst = inst - self.kind = inst.kind - self.name = inst.name - self.block = inst.block - self.block_text, self.check_eval_breaker, self.block_line = extract_block_text( - self.block - ) - self.always_exits = always_exits(self.block_text) - self.has_deopt = variable_used(self.inst, "DEOPT_IF") - self.cache_effects = [ - effect for effect in inst.inputs if isinstance(effect, parsing.CacheEffect) - ] - self.cache_offset = sum(c.size for c in self.cache_effects) - self.input_effects = [ - effect for effect in inst.inputs if isinstance(effect, StackEffect) - ] - self.output_effects = inst.outputs # For consistency/completeness - unmoved_names: set[str] = set() - for ieffect, oeffect in zip(self.input_effects, self.output_effects): - if ieffect == oeffect and ieffect.name == oeffect.name: - unmoved_names.add(ieffect.name) - else: - break - self.unmoved_names = frozenset(unmoved_names) - - self.instr_flags = InstructionFlags.fromInstruction(inst) - - self.active_caches = [] - offset = 0 - for effect in self.cache_effects: - if effect.name != UNUSED: - self.active_caches.append(ActiveCacheEffect(effect, offset)) - offset += effect.size - - if self.instr_flags.HAS_ARG_FLAG: - fmt = "IB" - else: - fmt = "IX" - if offset: - fmt += "C" + "0" * (offset - 1) - self.instr_fmt = fmt - - def is_viable_uop(self) -> bool: - """Whether this instruction is viable as a uop.""" - dprint: typing.Callable[..., None] = lambda *args, **kwargs: None - # if self.name.startswith("CALL"): - # dprint = print - - if self.name == "EXIT_TRACE": - return True # This has 'return frame' but it's okay - if self.always_exits: - dprint(f"Skipping {self.name} because it always exits") - return False - if len(self.active_caches) > 1: - # print(f"Skipping {self.name} because it has >1 cache entries") - return False - res = True - for forbidden in FORBIDDEN_NAMES_IN_UOPS: - # NOTE: To disallow unspecialized uops, use - # if variable_used(self.inst, forbidden): - if variable_used_unspecialized(self.inst, forbidden): - dprint(f"Skipping {self.name} because it uses {forbidden}") - res = False - return res - - def write(self, out: Formatter, tier: Tiers = TIER_ONE) -> None: - """Write one instruction, sans prologue and epilogue.""" - - # Write a static assertion that a family's cache size is correct - out.static_assert_family_size(self.name, self.family, self.cache_offset) - - # Write input stack effect variable declarations and initializations - stacking.write_single_instr(self, out, tier) - - # Skip the rest if the block always exits - if self.always_exits: - return - - # Write cache effect - if tier == TIER_ONE and self.cache_offset: - out.emit(f"next_instr += {self.cache_offset};") - - def write_body( - self, - out: Formatter, - dedent: int, - active_caches: list[ActiveCacheEffect], - tier: Tiers = TIER_ONE, - ) -> None: - """Write the instruction body.""" - # Write cache effect variable declarations and initializations - for active in active_caches: - ceffect = active.effect - bits = ceffect.size * BITS_PER_CODE_UNIT - if bits == 64: - # NOTE: We assume that 64-bit data in the cache - # is always an object pointer. - # If this becomes false, we need a way to specify - # syntactically what type the cache data is. - typ = "PyObject *" - func = "read_obj" - else: - typ = f"uint{bits}_t " - func = f"read_u{bits}" - if tier == TIER_ONE: - out.emit( - f"{typ}{ceffect.name} = {func}(&next_instr[{active.offset}].cache);" - ) - else: - out.emit(f"{typ}{ceffect.name} = ({typ.strip()})operand;") - - # Write the body, substituting a goto for ERROR_IF() and other stuff - assert dedent <= 0 - extra = " " * -dedent - names_to_skip = self.unmoved_names | frozenset({UNUSED, "null"}) - offset = 0 - context = self.block.context - assert context is not None and context.owner is not None - filename = context.owner.filename - for line in self.block_text: - out.set_lineno(self.block_line + offset, filename) - offset += 1 - if m := re.match(r"(\s*)ERROR_IF\((.+), (\w+)\);\s*(?://.*)?$", line): - space, cond, label = m.groups() - space = extra + space - # ERROR_IF() must pop the inputs from the stack. - # The code block is responsible for DECREF()ing them. - # NOTE: If the label doesn't exist, just add it to ceval.c. - - # Don't pop common input/output effects at the bottom! - # These aren't DECREF'ed so they can stay. - ieffs = list(self.input_effects) - oeffs = list(self.output_effects) - while ( - ieffs - and oeffs - and ieffs[0] == oeffs[0] - and ieffs[0].name == oeffs[0].name - ): - ieffs.pop(0) - oeffs.pop(0) - ninputs, symbolic = list_effect_size(ieffs) - if ninputs: - label = f"pop_{ninputs}_{label}" - if symbolic: - out.write_raw( - f"{space}if ({cond}) {{ STACK_SHRINK({symbolic}); goto {label}; }}\n" - ) - else: - out.write_raw(f"{space}if ({cond}) goto {label};\n") - elif m := re.match(r"(\s*)DECREF_INPUTS\(\);\s*(?://.*)?$", line): - out.reset_lineno() - space = extra + m.group(1) - for ieff in self.input_effects: - if ieff.name in names_to_skip: - continue - if ieff.size: - out.write_raw( - f"{space}for (int _i = {ieff.size}; --_i >= 0;) {{\n" - ) - out.write_raw(f"{space} Py_DECREF({ieff.name}[_i]);\n") - out.write_raw(f"{space}}}\n") - else: - decref = "XDECREF" if ieff.cond else "DECREF" - out.write_raw(f"{space}Py_{decref}({ieff.name});\n") - else: - out.write_raw(extra + line) - out.reset_lineno() - - -InstructionOrCacheEffect = Instruction | parsing.CacheEffect - - -@dataclasses.dataclass -class Component: - instr: Instruction - active_caches: list[ActiveCacheEffect] - - -MacroParts = list[Component | parsing.CacheEffect] - - -@dataclasses.dataclass -class MacroInstruction: - """A macro instruction.""" - - name: str - instr_fmt: str - instr_flags: InstructionFlags - macro: parsing.Macro - parts: MacroParts - cache_offset: int - predicted: bool = False - - -@dataclasses.dataclass -class PseudoInstruction: - """A pseudo instruction.""" - - name: str - targets: list[Instruction] - instr_fmt: str - instr_flags: InstructionFlags - - -@dataclasses.dataclass -class OverriddenInstructionPlaceHolder: - name: str - - -AnyInstruction = Instruction | MacroInstruction | PseudoInstruction - - -def extract_block_text(block: parsing.Block) -> tuple[list[str], bool, int]: - # Get lines of text with proper dedent - blocklines = block.text.splitlines(True) - first_token: lx.Token = block.tokens[0] # IndexError means the context is broken - block_line = first_token.begin[0] - - # Remove blank lines from both ends - while blocklines and not blocklines[0].strip(): - blocklines.pop(0) - block_line += 1 - while blocklines and not blocklines[-1].strip(): - blocklines.pop() - - # Remove leading and trailing braces - assert blocklines and blocklines[0].strip() == "{" - assert blocklines and blocklines[-1].strip() == "}" - blocklines.pop() - blocklines.pop(0) - block_line += 1 - - # Remove trailing blank lines - while blocklines and not blocklines[-1].strip(): - blocklines.pop() - - # Separate CHECK_EVAL_BREAKER() macro from end - check_eval_breaker = ( - blocklines != [] and blocklines[-1].strip() == "CHECK_EVAL_BREAKER();" - ) - if check_eval_breaker: - del blocklines[-1] - - return blocklines, check_eval_breaker, block_line - - -def always_exits(lines: list[str]) -> bool: - """Determine whether a block always ends in a return/goto/etc.""" - if not lines: - return False - line = lines[-1].rstrip() - # Indent must match exactly (TODO: Do something better) - if line[:12] != " " * 12: - return False - line = line[12:] - return line.startswith( - ( - "goto ", - "return ", - "DISPATCH", - "GO_TO_", - "Py_UNREACHABLE()", - "ERROR_IF(true, ", - ) - ) diff --git a/Tools/cases_generator/interpreter_definition.md b/Tools/cases_generator/interpreter_definition.md index f141848631d04a..5c4238756748a7 100644 --- a/Tools/cases_generator/interpreter_definition.md +++ b/Tools/cases_generator/interpreter_definition.md @@ -108,7 +108,7 @@ and a piece of C code describing its semantics:: NAME [":" type] [ "if" "(" C-expression ")" ] type: - NAME + NAME ["*"] stream: NAME "/" size diff --git a/Tools/cases_generator/lexer.py b/Tools/cases_generator/lexer.py index fe9c05ede5aa47..c3c2954a42083f 100644 --- a/Tools/cases_generator/lexer.py +++ b/Tools/cases_generator/lexer.py @@ -4,168 +4,267 @@ import re from dataclasses import dataclass +from collections.abc import Iterator -def choice(*opts): + +def choice(*opts: str) -> str: return "|".join("(%s)" % opt for opt in opts) + # Regexes # Longer operators must go before shorter ones. -PLUSPLUS = r'\+\+' -MINUSMINUS = r'--' +PLUSPLUS = r"\+\+" +MINUSMINUS = r"--" # -> -ARROW = r'->' -ELLIPSIS = r'\.\.\.' +ARROW = r"->" +ELLIPSIS = r"\.\.\." # Assignment operators -TIMESEQUAL = r'\*=' -DIVEQUAL = r'/=' -MODEQUAL = r'%=' -PLUSEQUAL = r'\+=' -MINUSEQUAL = r'-=' -LSHIFTEQUAL = r'<<=' -RSHIFTEQUAL = r'>>=' -ANDEQUAL = r'&=' -OREQUAL = r'\|=' -XOREQUAL = r'\^=' +TIMESEQUAL = r"\*=" +DIVEQUAL = r"/=" +MODEQUAL = r"%=" +PLUSEQUAL = r"\+=" +MINUSEQUAL = r"-=" +LSHIFTEQUAL = r"<<=" +RSHIFTEQUAL = r">>=" +ANDEQUAL = r"&=" +OREQUAL = r"\|=" +XOREQUAL = r"\^=" # Operators -PLUS = r'\+' -MINUS = r'-' -TIMES = r'\*' -DIVIDE = r'/' -MOD = r'%' -NOT = r'~' -XOR = r'\^' -LOR = r'\|\|' -LAND = r'&&' -LSHIFT = r'<<' -RSHIFT = r'>>' -LE = r'<=' -GE = r'>=' -EQ = r'==' -NE = r'!=' -LT = r'<' -GT = r'>' -LNOT = r'!' -OR = r'\|' -AND = r'&' -EQUALS = r'=' +PLUS = r"\+" +MINUS = r"-" +TIMES = r"\*" +DIVIDE = r"/" +MOD = r"%" +NOT = r"~" +XOR = r"\^" +LOR = r"\|\|" +LAND = r"&&" +LSHIFT = r"<<" +RSHIFT = r">>" +LE = r"<=" +GE = r">=" +EQ = r"==" +NE = r"!=" +LT = r"<" +GT = r">" +LNOT = r"!" +OR = r"\|" +AND = r"&" +EQUALS = r"=" # ? -CONDOP = r'\?' +CONDOP = r"\?" # Delimiters -LPAREN = r'\(' -RPAREN = r'\)' -LBRACKET = r'\[' -RBRACKET = r'\]' -LBRACE = r'\{' -RBRACE = r'\}' -COMMA = r',' -PERIOD = r'\.' -SEMI = r';' -COLON = r':' -BACKSLASH = r'\\' - -operators = { op: pattern for op, pattern in globals().items() if op == op.upper() } +LPAREN = r"\(" +RPAREN = r"\)" +LBRACKET = r"\[" +RBRACKET = r"\]" +LBRACE = r"\{" +RBRACE = r"\}" +COMMA = r"," +PERIOD = r"\." +SEMI = r";" +COLON = r":" +BACKSLASH = r"\\" + +operators = {op: pattern for op, pattern in globals().items() if op == op.upper()} for op in operators: globals()[op] = op -opmap = { pattern.replace("\\", "") or '\\' : op for op, pattern in operators.items() } +opmap = {pattern.replace("\\", "") or "\\": op for op, pattern in operators.items()} # Macros -macro = r'# *(ifdef|ifndef|undef|define|error|endif|if|else|include|#)' -MACRO = 'MACRO' +macro = r"# *(ifdef|ifndef|undef|define|error|endif|if|else|include|#)" +CMACRO = "CMACRO" + +id_re = r"[a-zA-Z_][0-9a-zA-Z_]*" +IDENTIFIER = "IDENTIFIER" -id_re = r'[a-zA-Z_][0-9a-zA-Z_]*' -IDENTIFIER = 'IDENTIFIER' -suffix = r'([uU]?[lL]?[lL]?)' -octal = r'0[0-7]+' + suffix -hex = r'0[xX][0-9a-fA-F]+' -decimal_digits = r'(0|[1-9][0-9]*)' +suffix = r"([uU]?[lL]?[lL]?)" +octal = r"0[0-7]+" + suffix +hex = r"0[xX][0-9a-fA-F]+" +decimal_digits = r"(0|[1-9][0-9]*)" decimal = decimal_digits + suffix exponent = r"""([eE][-+]?[0-9]+)""" fraction = r"""([0-9]*\.[0-9]+)|([0-9]+\.)""" -float = '(((('+fraction+')'+exponent+'?)|([0-9]+'+exponent+'))[FfLl]?)' +float = "((((" + fraction + ")" + exponent + "?)|([0-9]+" + exponent + "))[FfLl]?)" number_re = choice(octal, hex, float, decimal) -NUMBER = 'NUMBER' +NUMBER = "NUMBER" simple_escape = r"""([a-zA-Z._~!=&\^\-\\?'"])""" decimal_escape = r"""(\d+)""" hex_escape = r"""(x[0-9a-fA-F]+)""" -escape_sequence = r"""(\\("""+simple_escape+'|'+decimal_escape+'|'+hex_escape+'))' -string_char = r"""([^"\\\n]|"""+escape_sequence+')' -str_re = '"'+string_char+'*"' -STRING = 'STRING' -char = r'\'.\'' # TODO: escape sequence -CHARACTER = 'CHARACTER' +escape_sequence = ( + r"""(\\(""" + simple_escape + "|" + decimal_escape + "|" + hex_escape + "))" +) +string_char = r"""([^"\\\n]|""" + escape_sequence + ")" +str_re = '"' + string_char + '*"' +STRING = "STRING" +char = r"\'.\'" # TODO: escape sequence +CHARACTER = "CHARACTER" -comment_re = r'//.*|/\*([^*]|\*[^/])*\*/' -COMMENT = 'COMMENT' +comment_re = r"(//.*)|/\*([^*]|\*[^/])*\*/" +COMMENT = "COMMENT" newline = r"\n" -invalid = r"\S" # A single non-space character that's not caught by any of the other patterns -matcher = re.compile(choice(id_re, number_re, str_re, char, newline, macro, comment_re, *operators.values(), invalid)) -letter = re.compile(r'[a-zA-Z_]') - -kwds = ( - 'AUTO', 'BREAK', 'CASE', 'CHAR', 'CONST', - 'CONTINUE', 'DEFAULT', 'DO', 'DOUBLE', 'ELSE', 'ENUM', 'EXTERN', - 'FLOAT', 'FOR', 'GOTO', 'IF', 'INLINE', 'INT', 'LONG', 'OVERRIDE', - 'REGISTER', 'OFFSETOF', - 'RESTRICT', 'RETURN', 'SHORT', 'SIGNED', 'SIZEOF', 'STATIC', 'STRUCT', - 'SWITCH', 'TYPEDEF', 'UNION', 'UNSIGNED', 'VOID', - 'VOLATILE', 'WHILE' +invalid = ( + r"\S" # A single non-space character that's not caught by any of the other patterns +) +matcher = re.compile( + choice( + id_re, + number_re, + str_re, + char, + newline, + macro, + comment_re, + *operators.values(), + invalid, + ) ) -for name in kwds: - globals()[name] = name -keywords = { name.lower() : name for name in kwds } +letter = re.compile(r"[a-zA-Z_]") + + +kwds = [] +AUTO = "AUTO" +kwds.append(AUTO) +BREAK = "BREAK" +kwds.append(BREAK) +CASE = "CASE" +kwds.append(CASE) +CHAR = "CHAR" +kwds.append(CHAR) +CONST = "CONST" +kwds.append(CONST) +CONTINUE = "CONTINUE" +kwds.append(CONTINUE) +DEFAULT = "DEFAULT" +kwds.append(DEFAULT) +DO = "DO" +kwds.append(DO) +DOUBLE = "DOUBLE" +kwds.append(DOUBLE) +ELSE = "ELSE" +kwds.append(ELSE) +ENUM = "ENUM" +kwds.append(ENUM) +EXTERN = "EXTERN" +kwds.append(EXTERN) +FLOAT = "FLOAT" +kwds.append(FLOAT) +FOR = "FOR" +kwds.append(FOR) +GOTO = "GOTO" +kwds.append(GOTO) +IF = "IF" +kwds.append(IF) +INLINE = "INLINE" +kwds.append(INLINE) +INT = "INT" +kwds.append(INT) +LONG = "LONG" +kwds.append(LONG) +OFFSETOF = "OFFSETOF" +kwds.append(OFFSETOF) +RESTRICT = "RESTRICT" +kwds.append(RESTRICT) +RETURN = "RETURN" +kwds.append(RETURN) +SHORT = "SHORT" +kwds.append(SHORT) +SIGNED = "SIGNED" +kwds.append(SIGNED) +SIZEOF = "SIZEOF" +kwds.append(SIZEOF) +STATIC = "STATIC" +kwds.append(STATIC) +STRUCT = "STRUCT" +kwds.append(STRUCT) +SWITCH = "SWITCH" +kwds.append(SWITCH) +TYPEDEF = "TYPEDEF" +kwds.append(TYPEDEF) +UNION = "UNION" +kwds.append(UNION) +UNSIGNED = "UNSIGNED" +kwds.append(UNSIGNED) +VOID = "VOID" +kwds.append(VOID) +VOLATILE = "VOLATILE" +kwds.append(VOLATILE) +WHILE = "WHILE" +kwds.append(WHILE) +# An instruction in the DSL +INST = "INST" +kwds.append(INST) +# A micro-op in the DSL +OP = "OP" +kwds.append(OP) +# A macro in the DSL +MACRO = "MACRO" +kwds.append(MACRO) +keywords = {name.lower(): name for name in kwds} + +ANNOTATION = "ANNOTATION" +annotations = {"specializing", "guard", "override", "register", "replaced"} + +__all__ = [] +__all__.extend(kwds) def make_syntax_error( - message: str, filename: str, line: int, column: int, line_text: str, + message: str, + filename: str | None, + line: int, + column: int, + line_text: str, ) -> SyntaxError: return SyntaxError(message, (filename, line, column, line_text)) @dataclass(slots=True) class Token: + filename: str kind: str text: str begin: tuple[int, int] end: tuple[int, int] @property - def line(self): + def line(self) -> int: return self.begin[0] @property - def column(self): + def column(self) -> int: return self.begin[1] @property - def end_line(self): + def end_line(self) -> int: return self.end[0] @property - def end_column(self): + def end_column(self) -> int: return self.end[1] @property - def width(self): + def width(self) -> int: return self.end[1] - self.begin[1] - def replaceText(self, txt): + def replaceText(self, txt: str) -> "Token": assert isinstance(txt, str) - return Token(self.kind, txt, self.begin, self.end) + return Token(self.filename, self.kind, txt, self.begin, self.end) - def __repr__(self): + def __repr__(self) -> str: b0, b1 = self.begin e0, e1 = self.end if b0 == e0: @@ -174,82 +273,86 @@ def __repr__(self): return f"{self.kind}({self.text!r}, {b0}:{b1}, {e0}:{e1})" -def tokenize(src, line=1, filename=None): +def tokenize(src: str, line: int = 1, filename: str = "") -> Iterator[Token]: linestart = -1 for m in matcher.finditer(src): start, end = m.span() text = m.group(0) if text in keywords: kind = keywords[text] + elif text in annotations: + kind = ANNOTATION elif letter.match(text): kind = IDENTIFIER - elif text == '...': + elif text == "...": kind = ELLIPSIS - elif text == '.': + elif text == ".": kind = PERIOD - elif text[0] in '0123456789.': + elif text[0] in "0123456789.": kind = NUMBER elif text[0] == '"': kind = STRING elif text in opmap: kind = opmap[text] - elif text == '\n': + elif text == "\n": linestart = start line += 1 - kind = '\n' + kind = "\n" elif text[0] == "'": kind = CHARACTER - elif text[0] == '#': - kind = MACRO - elif text[0] == '/' and text[1] in '/*': + elif text[0] == "#": + kind = CMACRO + elif text[0] == "/" and text[1] in "/*": kind = COMMENT else: lineend = src.find("\n", start) if lineend == -1: lineend = len(src) - raise make_syntax_error(f"Bad token: {text}", - filename, line, start-linestart+1, src[linestart:lineend]) + raise make_syntax_error( + f"Bad token: {text}", + filename, + line, + start - linestart + 1, + src[linestart:lineend], + ) if kind == COMMENT: - begin = line, start-linestart - newlines = text.count('\n') + begin = line, start - linestart + newlines = text.count("\n") if newlines: - linestart = start + text.rfind('\n') + linestart = start + text.rfind("\n") line += newlines else: - begin = line, start-linestart + begin = line, start - linestart if kind != "\n": - yield Token(kind, text, begin, (line, start-linestart+len(text))) - - -__all__ = [] -__all__.extend([kind for kind in globals() if kind.upper() == kind]) + yield Token(filename, kind, text, begin, (line, start - linestart + len(text))) def to_text(tkns: list[Token], dedent: int = 0) -> str: res: list[str] = [] - line, col = -1, 1+dedent + line, col = -1, 1 + dedent for tkn in tkns: if line == -1: line, _ = tkn.begin l, c = tkn.begin - #assert(l >= line), (line, txt, start, end) + # assert(l >= line), (line, txt, start, end) while l > line: line += 1 - res.append('\n') - col = 1+dedent - res.append(' '*(c-col)) + res.append("\n") + col = 1 + dedent + res.append(" " * (c - col)) text = tkn.text - if dedent != 0 and tkn.kind == 'COMMENT' and '\n' in text: + if dedent != 0 and tkn.kind == "COMMENT" and "\n" in text: if dedent < 0: - text = text.replace('\n', '\n' + ' '*-dedent) + text = text.replace("\n", "\n" + " " * -dedent) # TODO: dedent > 0 res.append(text) line, col = tkn.end - return ''.join(res) + return "".join(res) if __name__ == "__main__": import sys + filename = sys.argv[1] if filename == "-c": src = sys.argv[2] diff --git a/Tools/cases_generator/mypy.ini b/Tools/cases_generator/mypy.ini new file mode 100644 index 00000000000000..8e5a31851c596e --- /dev/null +++ b/Tools/cases_generator/mypy.ini @@ -0,0 +1,15 @@ +[mypy] +files = Tools/cases_generator/ +pretty = True + +# Make sure Python can still be built +# using Python 3.10 for `PYTHON_FOR_REGEN`... +python_version = 3.10 + +# ...And be strict: +strict = True +strict_concatenate = True +enable_error_code = ignore-without-code,redundant-expr,truthy-bool,possibly-undefined +warn_unreachable = True +allow_redefinition = True +implicit_reexport = True diff --git a/Tools/cases_generator/opcode_id_generator.py b/Tools/cases_generator/opcode_id_generator.py new file mode 100644 index 00000000000000..dbea3d0b622c87 --- /dev/null +++ b/Tools/cases_generator/opcode_id_generator.py @@ -0,0 +1,65 @@ +"""Generate the list of opcode IDs. +Reads the instruction definitions from bytecodes.c. +Writes the IDs to opcode._ids.h by default. +""" + +import argparse +import os.path +import sys + +from analyzer import ( + Analysis, + Instruction, + analyze_files, +) +from generators_common import ( + DEFAULT_INPUT, + ROOT, + write_header, +) +from cwriter import CWriter +from typing import TextIO + + +DEFAULT_OUTPUT = ROOT / "Include/opcode_ids.h" + + +def generate_opcode_header( + filenames: list[str], analysis: Analysis, outfile: TextIO +) -> None: + write_header(__file__, filenames, outfile) + out = CWriter(outfile, 0, False) + with out.header_guard("Py_OPCODE_IDS_H"): + out.emit("/* Instruction opcodes for compiled code */\n") + + def write_define(name: str, op: int) -> None: + out.emit(f"#define {name:<38} {op:>3}\n") + + for op, name in sorted([(op, name) for (name, op) in analysis.opmap.items()]): + write_define(name, op) + + out.emit("\n") + write_define("HAVE_ARGUMENT", analysis.have_arg) + write_define("MIN_INSTRUMENTED_OPCODE", analysis.min_instrumented) + + +arg_parser = argparse.ArgumentParser( + description="Generate the header file with all opcode IDs.", + formatter_class=argparse.ArgumentDefaultsHelpFormatter, +) + +arg_parser.add_argument( + "-o", "--output", type=str, help="Generated code", default=DEFAULT_OUTPUT +) + +arg_parser.add_argument( + "input", nargs=argparse.REMAINDER, help="Instruction definition file(s)" +) + +if __name__ == "__main__": + args = arg_parser.parse_args() + if len(args.input) == 0: + args.input.append(DEFAULT_INPUT) + data = analyze_files(args.input) + with open(args.output, "w") as outfile: + generate_opcode_header(args.input, data, outfile) diff --git a/Tools/cases_generator/opcode_metadata_generator.py b/Tools/cases_generator/opcode_metadata_generator.py new file mode 100644 index 00000000000000..9b7df9a54c7b3b --- /dev/null +++ b/Tools/cases_generator/opcode_metadata_generator.py @@ -0,0 +1,386 @@ +"""Generate uop metedata. +Reads the instruction definitions from bytecodes.c. +Writes the metadata to pycore_uop_metadata.h by default. +""" + +import argparse +import os.path +import sys + +from analyzer import ( + Analysis, + Instruction, + analyze_files, + Skip, + Uop, +) +from generators_common import ( + DEFAULT_INPUT, + ROOT, + write_header, + cflags, + StackOffset, +) +from cwriter import CWriter +from typing import TextIO +from stack import get_stack_effect + +# Constants used instead of size for macro expansions. +# Note: 1, 2, 4 must match actual cache entry sizes. +OPARG_KINDS = { + "OPARG_FULL": 0, + "OPARG_CACHE_1": 1, + "OPARG_CACHE_2": 2, + "OPARG_CACHE_4": 4, + "OPARG_TOP": 5, + "OPARG_BOTTOM": 6, + "OPARG_SAVE_RETURN_OFFSET": 7, + # Skip 8 as the other powers of 2 are sizes + "OPARG_REPLACED": 9, +} + +FLAGS = [ + "ARG", + "CONST", + "NAME", + "JUMP", + "FREE", + "LOCAL", + "EVAL_BREAK", + "DEOPT", + "ERROR", + "ESCAPES", +] + + +def generate_flag_macros(out: CWriter) -> None: + for i, flag in enumerate(FLAGS): + out.emit(f"#define HAS_{flag}_FLAG ({1< None: + for name, value in OPARG_KINDS.items(): + out.emit(f"#define {name} {value}\n") + out.emit("\n") + + +def emit_stack_effect_function( + out: CWriter, direction: str, data: list[tuple[str, str]] +) -> None: + out.emit(f"extern int _PyOpcode_num_{direction}(int opcode, int oparg);\n") + out.emit("#ifdef NEED_OPCODE_METADATA\n") + out.emit(f"int _PyOpcode_num_{direction}(int opcode, int oparg) {{\n") + out.emit("switch(opcode) {\n") + for name, effect in data: + out.emit(f"case {name}:\n") + out.emit(f" return {effect};\n") + out.emit("default:\n") + out.emit(" return -1;\n") + out.emit("}\n") + out.emit("}\n\n") + out.emit("#endif\n\n") + + +def generate_stack_effect_functions(analysis: Analysis, out: CWriter) -> None: + popped_data: list[tuple[str, str]] = [] + pushed_data: list[tuple[str, str]] = [] + for inst in analysis.instructions.values(): + stack = get_stack_effect(inst) + popped = (-stack.base_offset).to_c() + pushed = (stack.top_offset - stack.base_offset).to_c() + popped_data.append((inst.name, popped)) + pushed_data.append((inst.name, pushed)) + emit_stack_effect_function(out, "popped", sorted(popped_data)) + emit_stack_effect_function(out, "pushed", sorted(pushed_data)) + + +def generate_is_pseudo(analysis: Analysis, out: CWriter) -> None: + """Write the IS_PSEUDO_INSTR macro""" + out.emit("\n\n#define IS_PSEUDO_INSTR(OP) ( \\\n") + for op in analysis.pseudos: + out.emit(f"((OP) == {op}) || \\\n") + out.emit("0") + out.emit(")\n\n") + + +def get_format(inst: Instruction) -> str: + if inst.properties.oparg: + format = "INSTR_FMT_IB" + else: + format = "INSTR_FMT_IX" + if inst.size > 1: + format += "C" + format += "0" * (inst.size - 2) + return format + + +def generate_instruction_formats(analysis: Analysis, out: CWriter) -> None: + # Compute the set of all instruction formats. + formats: set[str] = set() + for inst in analysis.instructions.values(): + formats.add(get_format(inst)) + # Generate an enum for it + out.emit("enum InstructionFormat {\n") + next_id = 1 + for format in sorted(formats): + out.emit(f"{format} = {next_id},\n") + next_id += 1 + out.emit("};\n\n") + + +def generate_deopt_table(analysis: Analysis, out: CWriter) -> None: + out.emit("extern const uint8_t _PyOpcode_Deopt[256];\n") + out.emit("#ifdef NEED_OPCODE_METADATA\n") + out.emit("const uint8_t _PyOpcode_Deopt[256] = {\n") + deopts: list[tuple[str, str]] = [] + for inst in analysis.instructions.values(): + deopt = inst.name + if inst.family is not None: + deopt = inst.family.name + deopts.append((inst.name, deopt)) + deopts.append(("INSTRUMENTED_LINE", "INSTRUMENTED_LINE")) + for name, deopt in sorted(deopts): + out.emit(f"[{name}] = {deopt},\n") + out.emit("};\n\n") + out.emit("#endif // NEED_OPCODE_METADATA\n\n") + + +def generate_cache_table(analysis: Analysis, out: CWriter) -> None: + out.emit("extern const uint8_t _PyOpcode_Caches[256];\n") + out.emit("#ifdef NEED_OPCODE_METADATA\n") + out.emit("const uint8_t _PyOpcode_Caches[256] = {\n") + for inst in analysis.instructions.values(): + if inst.family and inst.family.name != inst.name: + continue + if inst.name.startswith("INSTRUMENTED"): + continue + if inst.size > 1: + out.emit(f"[{inst.name}] = {inst.size-1},\n") + out.emit("};\n") + out.emit("#endif\n\n") + + +def generate_name_table(analysis: Analysis, out: CWriter) -> None: + table_size = 256 + len(analysis.pseudos) + out.emit(f"extern const char *_PyOpcode_OpName[{table_size}];\n") + out.emit("#ifdef NEED_OPCODE_METADATA\n") + out.emit(f"const char *_PyOpcode_OpName[{table_size}] = {{\n") + names = list(analysis.instructions) + list(analysis.pseudos) + names.append("INSTRUMENTED_LINE") + for name in sorted(names): + out.emit(f'[{name}] = "{name}",\n') + out.emit("};\n") + out.emit("#endif\n\n") + + +def generate_metadata_table(analysis: Analysis, out: CWriter) -> None: + table_size = 256 + len(analysis.pseudos) + out.emit("struct opcode_metadata {\n") + out.emit("uint8_t valid_entry;\n") + out.emit("int8_t instr_format;\n") + out.emit("int16_t flags;\n") + out.emit("};\n\n") + out.emit( + f"extern const struct opcode_metadata _PyOpcode_opcode_metadata[{table_size}];\n" + ) + out.emit("#ifdef NEED_OPCODE_METADATA\n") + out.emit( + f"const struct opcode_metadata _PyOpcode_opcode_metadata[{table_size}] = {{\n" + ) + for inst in sorted(analysis.instructions.values(), key=lambda t: t.name): + out.emit( + f"[{inst.name}] = {{ true, {get_format(inst)}, {cflags(inst.properties)} }},\n" + ) + for pseudo in sorted(analysis.pseudos.values(), key=lambda t: t.name): + flags = cflags(pseudo.properties) + for flag in pseudo.flags: + if flags == "0": + flags = f"{flag}_FLAG" + else: + flags += f" | {flag}_FLAG" + out.emit(f"[{pseudo.name}] = {{ true, -1, {flags} }},\n") + out.emit("};\n") + out.emit("#endif\n\n") + + +def generate_expansion_table(analysis: Analysis, out: CWriter) -> None: + expansions_table: dict[str, list[tuple[str, int, int]]] = {} + for inst in sorted(analysis.instructions.values(), key=lambda t: t.name): + offset: int = 0 # Cache effect offset + expansions: list[tuple[str, int, int]] = [] # [(name, size, offset), ...] + if inst.is_super(): + pieces = inst.name.split("_") + assert len(pieces) == 4, f"{inst.name} doesn't look like a super-instr" + name1 = "_".join(pieces[:2]) + name2 = "_".join(pieces[2:]) + assert name1 in analysis.instructions, f"{name1} doesn't match any instr" + assert name2 in analysis.instructions, f"{name2} doesn't match any instr" + instr1 = analysis.instructions[name1] + instr2 = analysis.instructions[name2] + assert ( + len(instr1.parts) == 1 + ), f"{name1} is not a good superinstruction part" + assert ( + len(instr2.parts) == 1 + ), f"{name2} is not a good superinstruction part" + expansions.append((instr1.parts[0].name, OPARG_KINDS["OPARG_TOP"], 0)) + expansions.append((instr2.parts[0].name, OPARG_KINDS["OPARG_BOTTOM"], 0)) + elif not is_viable_expansion(inst): + continue + else: + for part in inst.parts: + size = part.size + if part.name == "_SAVE_RETURN_OFFSET": + size = OPARG_KINDS["OPARG_SAVE_RETURN_OFFSET"] + if isinstance(part, Uop): + # Skip specializations + if "specializing" in part.annotations: + continue + if "replaced" in part.annotations: + size = OPARG_KINDS["OPARG_REPLACED"] + expansions.append((part.name, size, offset if size else 0)) + offset += part.size + expansions_table[inst.name] = expansions + max_uops = max(len(ex) for ex in expansions_table.values()) + out.emit(f"#define MAX_UOP_PER_EXPANSION {max_uops}\n") + out.emit("struct opcode_macro_expansion {\n") + out.emit("int nuops;\n") + out.emit( + "struct { int16_t uop; int8_t size; int8_t offset; } uops[MAX_UOP_PER_EXPANSION];\n" + ) + out.emit("};\n") + out.emit( + "extern const struct opcode_macro_expansion _PyOpcode_macro_expansion[256];\n\n" + ) + out.emit("#ifdef NEED_OPCODE_METADATA\n") + out.emit("const struct opcode_macro_expansion\n") + out.emit("_PyOpcode_macro_expansion[256] = {\n") + for inst_name, expansions in expansions_table.items(): + uops = [ + f"{{ {name}, {size}, {offset} }}" for (name, size, offset) in expansions + ] + out.emit( + f'[{inst_name}] = {{ .nuops = {len(expansions)}, .uops = {{ {", ".join(uops)} }} }},\n' + ) + out.emit("};\n") + out.emit("#endif // NEED_OPCODE_METADATA\n\n") + + +def is_viable_expansion(inst: Instruction) -> bool: + "An instruction can be expanded if all its parts are viable for tier 2" + for part in inst.parts: + if isinstance(part, Uop): + # Skip specializing and replaced uops + if "specializing" in part.annotations: + continue + if "replaced" in part.annotations: + continue + if part.properties.tier_one_only or not part.is_viable(): + return False + return True + + +def generate_extra_cases(analysis: Analysis, out: CWriter) -> None: + out.emit("#define EXTRA_CASES \\\n") + valid_opcodes = set(analysis.opmap.values()) + for op in range(256): + if op not in valid_opcodes: + out.emit(f" case {op}: \\\n") + out.emit(" ;\n") + + +def generate_pseudo_targets(analysis: Analysis, out: CWriter) -> None: + table_size = len(analysis.pseudos) + max_targets = max(len(pseudo.targets) for pseudo in analysis.pseudos.values()) + out.emit("struct pseudo_targets {\n") + out.emit(f"uint8_t targets[{max_targets + 1}];\n") + out.emit("};\n") + out.emit( + f"extern const struct pseudo_targets _PyOpcode_PseudoTargets[{table_size}];\n" + ) + out.emit("#ifdef NEED_OPCODE_METADATA\n") + out.emit( + f"const struct pseudo_targets _PyOpcode_PseudoTargets[{table_size}] = {{\n" + ) + for pseudo in analysis.pseudos.values(): + targets = ["0"] * (max_targets + 1) + for i, target in enumerate(pseudo.targets): + targets[i] = target.name + out.emit(f"[{pseudo.name}-256] = {{ {{ {', '.join(targets)} }} }},\n") + out.emit("};\n\n") + out.emit("#endif // NEED_OPCODE_METADATA\n") + out.emit("static inline bool\n") + out.emit("is_pseudo_target(int pseudo, int target) {\n") + out.emit(f"if (pseudo < 256 || pseudo >= {256+table_size}) {{\n") + out.emit(f"return false;\n") + out.emit("}\n") + out.emit( + f"for (int i = 0; _PyOpcode_PseudoTargets[pseudo-256].targets[i]; i++) {{\n" + ) + out.emit( + f"if (_PyOpcode_PseudoTargets[pseudo-256].targets[i] == target) return true;\n" + ) + out.emit("}\n") + out.emit(f"return false;\n") + out.emit("}\n\n") + + +def generate_opcode_metadata( + filenames: list[str], analysis: Analysis, outfile: TextIO +) -> None: + write_header(__file__, filenames, outfile) + out = CWriter(outfile, 0, False) + with out.header_guard("Py_CORE_OPCODE_METADATA_H"): + out.emit("#ifndef Py_BUILD_CORE\n") + out.emit('# error "this header requires Py_BUILD_CORE define"\n') + out.emit("#endif\n\n") + out.emit("#include // bool\n") + out.emit('#include "opcode_ids.h"\n') + generate_is_pseudo(analysis, out) + out.emit('#include "pycore_uop_ids.h"\n') + generate_stack_effect_functions(analysis, out) + generate_instruction_formats(analysis, out) + table_size = 256 + len(analysis.pseudos) + out.emit("#define IS_VALID_OPCODE(OP) \\\n") + out.emit(f" (((OP) >= 0) && ((OP) < {table_size}) && \\\n") + out.emit(" (_PyOpcode_opcode_metadata[(OP)].valid_entry))\n\n") + generate_flag_macros(out) + generate_oparg_macros(out) + generate_metadata_table(analysis, out) + generate_expansion_table(analysis, out) + generate_name_table(analysis, out) + generate_cache_table(analysis, out) + generate_deopt_table(analysis, out) + generate_extra_cases(analysis, out) + generate_pseudo_targets(analysis, out) + + +arg_parser = argparse.ArgumentParser( + description="Generate the header file with opcode metadata.", + formatter_class=argparse.ArgumentDefaultsHelpFormatter, +) + + +DEFAULT_OUTPUT = ROOT / "Include/internal/pycore_opcode_metadata.h" + + +arg_parser.add_argument( + "-o", "--output", type=str, help="Generated code", default=DEFAULT_OUTPUT +) + +arg_parser.add_argument( + "input", nargs=argparse.REMAINDER, help="Instruction definition file(s)" +) + +if __name__ == "__main__": + args = arg_parser.parse_args() + if len(args.input) == 0: + args.input.append(DEFAULT_INPUT) + data = analyze_files(args.input) + with open(args.output, "w") as outfile: + generate_opcode_metadata(args.input, data, outfile) diff --git a/Tools/cases_generator/parser.py b/Tools/cases_generator/parser.py new file mode 100644 index 00000000000000..2b77d14d21143f --- /dev/null +++ b/Tools/cases_generator/parser.py @@ -0,0 +1,66 @@ +from parsing import ( + InstDef, + Macro, + Pseudo, + Family, + Parser, + Context, + CacheEffect, + StackEffect, + InputEffect, + OpName, + AstNode, +) + + +def prettify_filename(filename: str) -> str: + # Make filename more user-friendly and less platform-specific, + # it is only used for error reporting at this point. + filename = filename.replace("\\", "/") + if filename.startswith("./"): + filename = filename[2:] + if filename.endswith(".new"): + filename = filename[:-4] + return filename + + +BEGIN_MARKER = "// BEGIN BYTECODES //" +END_MARKER = "// END BYTECODES //" + + +def parse_files(filenames: list[str]) -> list[AstNode]: + result: list[AstNode] = [] + for filename in filenames: + with open(filename) as file: + src = file.read() + + psr = Parser(src, filename=prettify_filename(filename)) + + # Skip until begin marker + while tkn := psr.next(raw=True): + if tkn.text == BEGIN_MARKER: + break + else: + raise psr.make_syntax_error( + f"Couldn't find {BEGIN_MARKER!r} in {psr.filename}" + ) + start = psr.getpos() + + # Find end marker, then delete everything after it + while tkn := psr.next(raw=True): + if tkn.text == END_MARKER: + break + del psr.tokens[psr.getpos() - 1 :] + + # Parse from start + psr.setpos(start) + thing_first_token = psr.peek() + while node := psr.definition(): + assert node is not None + result.append(node) # type: ignore[arg-type] + if not psr.eof(): + psr.backup() + raise psr.make_syntax_error( + f"Extra stuff at the end of {filename}", psr.next(True) + ) + return result diff --git a/Tools/cases_generator/parsing.py b/Tools/cases_generator/parsing.py index 5610ac661a8945..60c185dcef58e9 100644 --- a/Tools/cases_generator/parsing.py +++ b/Tools/cases_generator/parsing.py @@ -32,7 +32,7 @@ class Context(NamedTuple): end: int owner: PLexer - def __repr__(self): + def __repr__(self) -> str: return f"<{self.owner.filename}: {self.begin}-{self.end}>" @@ -75,7 +75,7 @@ class StackEffect(Node): size: str = "" # Optional `[size]` # Note: size cannot be combined with type or cond - def __repr__(self): + def __repr__(self) -> str: items = [self.name, self.type, self.cond, self.size] while items and items[-1] == "": del items[-1] @@ -105,8 +105,7 @@ class OpName(Node): @dataclass class InstHeader(Node): - override: bool - register: bool + annotations: list[str] kind: Literal["inst", "op"] name: str inputs: list[InputEffect] @@ -115,8 +114,7 @@ class InstHeader(Node): @dataclass class InstDef(Node): - override: bool - register: bool + annotations: list[str] kind: Literal["inst", "op"] name: str inputs: list[InputEffect] @@ -140,20 +138,22 @@ class Family(Node): @dataclass class Pseudo(Node): name: str - targets: list[str] # opcodes this can be replaced by + flags: list[str] # instr flags to set on the pseudo instruction + targets: list[str] # opcodes this can be replaced by +AstNode = InstDef | Macro | Pseudo | Family class Parser(PLexer): @contextual - def definition(self) -> InstDef | Macro | Pseudo | Family | None: - if inst := self.inst_def(): - return inst + def definition(self) -> AstNode | None: if macro := self.macro_def(): return macro if family := self.family_def(): return family if pseudo := self.pseudo_def(): return pseudo + if inst := self.inst_def(): + return inst return None @contextual @@ -161,8 +161,7 @@ def inst_def(self) -> InstDef | None: if hdr := self.inst_header(): if block := self.block(): return InstDef( - hdr.override, - hdr.register, + hdr.annotations, hdr.kind, hdr.name, hdr.inputs, @@ -174,13 +173,15 @@ def inst_def(self) -> InstDef | None: @contextual def inst_header(self) -> InstHeader | None: - # [override] inst(NAME) - # | [override] [register] inst(NAME, (inputs -- outputs)) - # | [override] [register] op(NAME, (inputs -- outputs)) - # TODO: Make INST a keyword in the lexer. - override = bool(self.expect(lx.OVERRIDE)) - register = bool(self.expect(lx.REGISTER)) - if (tkn := self.expect(lx.IDENTIFIER)) and tkn.text in ("inst", "op"): + # annotation* inst(NAME, (inputs -- outputs)) + # | annotation* op(NAME, (inputs -- outputs)) + annotations = [] + while anno := self.expect(lx.ANNOTATION): + annotations.append(anno.text) + tkn = self.expect(lx.INST) + if not tkn: + tkn = self.expect(lx.OP) + if tkn: kind = cast(Literal["inst", "op"], tkn.text) if self.expect(lx.LPAREN) and (tkn := self.expect(lx.IDENTIFIER)): name = tkn.text @@ -188,7 +189,7 @@ def inst_header(self) -> InstHeader | None: inp, outp = self.io_effect() if self.expect(lx.RPAREN): if (tkn := self.peek()) and tkn.kind == lx.LBRACE: - return InstHeader(override, register, kind, name, inp, outp) + return InstHeader(annotations, kind, name, inp, outp) return None def io_effect(self) -> tuple[list[InputEffect], list[OutputEffect]]: @@ -252,12 +253,14 @@ def cache_effect(self) -> CacheEffect | None: @contextual def stack_effect(self) -> StackEffect | None: - # IDENTIFIER [':' IDENTIFIER] ['if' '(' expression ')'] + # IDENTIFIER [':' IDENTIFIER [TIMES]] ['if' '(' expression ')'] # | IDENTIFIER '[' expression ']' if tkn := self.expect(lx.IDENTIFIER): type_text = "" if self.expect(lx.COLON): type_text = self.require(lx.IDENTIFIER).text.strip() + if self.expect(lx.TIMES): + type_text += " *" cond_text = "" if self.expect(lx.IF): self.require(lx.LPAREN) @@ -310,7 +313,7 @@ def op(self) -> OpName | None: @contextual def macro_def(self) -> Macro | None: - if (tkn := self.expect(lx.IDENTIFIER)) and tkn.text == "macro": + if tkn := self.expect(lx.MACRO): if self.expect(lx.LPAREN): if tkn := self.expect(lx.IDENTIFIER): if self.expect(lx.RPAREN): @@ -360,7 +363,8 @@ def family_def(self) -> Family | None: if tkn := self.expect(lx.IDENTIFIER): if self.expect(lx.COMMA): if not (size := self.expect(lx.IDENTIFIER)): - raise self.make_syntax_error("Expected identifier") + if not (size := self.expect(lx.NUMBER)): + raise self.make_syntax_error("Expected identifier or number") if self.expect(lx.RPAREN): if self.expect(lx.EQUALS): if not self.expect(lx.LBRACE): @@ -372,19 +376,39 @@ def family_def(self) -> Family | None: ) return None + def flags(self) -> list[str]: + here = self.getpos() + if self.expect(lx.LPAREN): + if tkn := self.expect(lx.IDENTIFIER): + flags = [tkn.text] + while self.expect(lx.COMMA): + if tkn := self.expect(lx.IDENTIFIER): + flags.append(tkn.text) + else: + break + if not self.expect(lx.RPAREN): + raise self.make_syntax_error("Expected comma or right paren") + return flags + self.setpos(here) + return [] + @contextual def pseudo_def(self) -> Pseudo | None: if (tkn := self.expect(lx.IDENTIFIER)) and tkn.text == "pseudo": size = None if self.expect(lx.LPAREN): if tkn := self.expect(lx.IDENTIFIER): + if self.expect(lx.COMMA): + flags = self.flags() + else: + flags = [] if self.expect(lx.RPAREN): if self.expect(lx.EQUALS): if not self.expect(lx.LBRACE): raise self.make_syntax_error("Expected {") if members := self.members(): if self.expect(lx.RBRACE) and self.expect(lx.SEMI): - return Pseudo(tkn.text, members) + return Pseudo(tkn.text, flags, members) return None def members(self) -> list[str] | None: diff --git a/Tools/cases_generator/py_metadata_generator.py b/Tools/cases_generator/py_metadata_generator.py new file mode 100644 index 00000000000000..43811fdacc8a9e --- /dev/null +++ b/Tools/cases_generator/py_metadata_generator.py @@ -0,0 +1,97 @@ +"""Generate uop metedata. +Reads the instruction definitions from bytecodes.c. +Writes the metadata to pycore_uop_metadata.h by default. +""" + +import argparse + +from analyzer import ( + Analysis, + analyze_files, +) +from generators_common import ( + DEFAULT_INPUT, + ROOT, + root_relative_path, + write_header, +) +from cwriter import CWriter +from typing import TextIO + + + +DEFAULT_OUTPUT = ROOT / "Lib/_opcode_metadata.py" + + +def get_specialized(analysis: Analysis) -> set[str]: + specialized: set[str] = set() + for family in analysis.families.values(): + for member in family.members: + specialized.add(member.name) + return specialized + + +def generate_specializations(analysis: Analysis, out: CWriter) -> None: + out.emit("_specializations = {\n") + for family in analysis.families.values(): + out.emit(f'"{family.name}": [\n') + for member in family.members: + out.emit(f' "{member.name}",\n') + out.emit("],\n") + out.emit("}\n\n") + + +def generate_specialized_opmap(analysis: Analysis, out: CWriter) -> None: + out.emit("_specialized_opmap = {\n") + names = [] + for family in analysis.families.values(): + for member in family.members: + if member.name == family.name: + continue + names.append(member.name) + for name in sorted(names): + out.emit(f"'{name}': {analysis.opmap[name]},\n") + out.emit("}\n\n") + + +def generate_opmap(analysis: Analysis, out: CWriter) -> None: + specialized = get_specialized(analysis) + out.emit("opmap = {\n") + for inst, op in analysis.opmap.items(): + if inst not in specialized: + out.emit(f"'{inst}': {analysis.opmap[inst]},\n") + out.emit("}\n\n") + + +def generate_py_metadata( + filenames: list[str], analysis: Analysis, outfile: TextIO +) -> None: + write_header(__file__, filenames, outfile, "#") + out = CWriter(outfile, 0, False) + generate_specializations(analysis, out) + generate_specialized_opmap(analysis, out) + generate_opmap(analysis, out) + out.emit(f"HAVE_ARGUMENT = {analysis.have_arg}\n") + out.emit(f"MIN_INSTRUMENTED_OPCODE = {analysis.min_instrumented}\n") + + +arg_parser = argparse.ArgumentParser( + description="Generate the Python file with opcode metadata.", + formatter_class=argparse.ArgumentDefaultsHelpFormatter, +) + +arg_parser.add_argument( + "-o", "--output", type=str, help="Generated code", default=DEFAULT_OUTPUT +) + +arg_parser.add_argument( + "input", nargs=argparse.REMAINDER, help="Instruction definition file(s)" +) + +if __name__ == "__main__": + args = arg_parser.parse_args() + if len(args.input) == 0: + args.input.append(DEFAULT_INPUT) + data = analyze_files(args.input) + with open(args.output, "w") as outfile: + generate_py_metadata(args.input, data, outfile) diff --git a/Tools/cases_generator/stack.py b/Tools/cases_generator/stack.py new file mode 100644 index 00000000000000..d351037a663ca2 --- /dev/null +++ b/Tools/cases_generator/stack.py @@ -0,0 +1,206 @@ +import re +from analyzer import StackItem, Instruction, Uop +from dataclasses import dataclass +from cwriter import CWriter + + +def maybe_parenthesize(sym: str) -> str: + """Add parentheses around a string if it contains an operator + and is not already parenthesized. + + An exception is made for '*' which is common and harmless + in the context where the symbolic size is used. + """ + if sym.startswith("(") and sym.endswith(")"): + return sym + if re.match(r"^[\s\w*]+$", sym): + return sym + else: + return f"({sym})" + + +def var_size(var: StackItem) -> str: + if var.condition: + # Special case simplification + if var.condition == "oparg & 1" and var.size == "1": + return f"({var.condition})" + else: + return f"(({var.condition}) ? {var.size} : 0)" + else: + return var.size + +@dataclass +class StackOffset: + "The stack offset of the virtual base of the stack from the physical stack pointer" + + popped: list[str] + pushed: list[str] + + @staticmethod + def empty() -> "StackOffset": + return StackOffset([], []) + + def pop(self, item: StackItem) -> None: + self.popped.append(var_size(item)) + + def push(self, item: StackItem) -> None: + self.pushed.append(var_size(item)) + + def __sub__(self, other: "StackOffset") -> "StackOffset": + return StackOffset( + self.popped + other.pushed, + self.pushed + other.popped + ) + + def __neg__(self) -> "StackOffset": + return StackOffset(self.pushed, self.popped) + + def simplify(self) -> None: + "Remove matching values from both the popped and pushed list" + if not self.popped or not self.pushed: + return + # Sort the list so the lexically largest element is last. + popped = sorted(self.popped) + pushed = sorted(self.pushed) + self.popped = [] + self.pushed = [] + while popped and pushed: + pop = popped.pop() + push = pushed.pop() + if pop == push: + pass + elif pop > push: + # if pop > push, there can be no element in pushed matching pop. + self.popped.append(pop) + pushed.append(push) + else: + self.pushed.append(push) + popped.append(pop) + self.popped.extend(popped) + self.pushed.extend(pushed) + + def to_c(self) -> str: + self.simplify() + int_offset = 0 + symbol_offset = "" + for item in self.popped: + try: + int_offset -= int(item) + except ValueError: + symbol_offset += f" - {maybe_parenthesize(item)}" + for item in self.pushed: + try: + int_offset += int(item) + except ValueError: + symbol_offset += f" + {maybe_parenthesize(item)}" + if symbol_offset and not int_offset: + res = symbol_offset + else: + res = f"{int_offset}{symbol_offset}" + if res.startswith(" + "): + res = res[3:] + if res.startswith(" - "): + res = "-" + res[3:] + return res + + def clear(self) -> None: + self.popped = [] + self.pushed = [] + + +class SizeMismatch(Exception): + pass + + +class Stack: + def __init__(self) -> None: + self.top_offset = StackOffset.empty() + self.base_offset = StackOffset.empty() + self.peek_offset = StackOffset.empty() + self.variables: list[StackItem] = [] + self.defined: set[str] = set() + + def pop(self, var: StackItem) -> str: + self.top_offset.pop(var) + if not var.peek: + self.peek_offset.pop(var) + indirect = "&" if var.is_array() else "" + if self.variables: + popped = self.variables.pop() + if popped.size != var.size: + raise SizeMismatch( + f"Size mismatch when popping '{popped.name}' from stack to assign to {var.name}. " + f"Expected {var.size} got {popped.size}" + ) + if popped.name == var.name: + return "" + elif popped.name == "unused": + self.defined.add(var.name) + return ( + f"{var.name} = {indirect}stack_pointer[{self.top_offset.to_c()}];\n" + ) + elif var.name == "unused": + return "" + else: + self.defined.add(var.name) + return f"{var.name} = {popped.name};\n" + self.base_offset.pop(var) + if var.name == "unused": + return "" + else: + self.defined.add(var.name) + cast = f"({var.type})" if (not indirect and var.type) else "" + assign = ( + f"{var.name} = {cast}{indirect}stack_pointer[{self.base_offset.to_c()}];" + ) + if var.condition: + return f"if ({var.condition}) {{ {assign} }}\n" + return f"{assign}\n" + + def push(self, var: StackItem) -> str: + self.variables.append(var) + if var.is_array() and var.name not in self.defined and var.name != "unused": + c_offset = self.top_offset.to_c() + self.top_offset.push(var) + self.defined.add(var.name) + return f"{var.name} = &stack_pointer[{c_offset}];\n" + else: + self.top_offset.push(var) + return "" + + def flush(self, out: CWriter) -> None: + for var in self.variables: + if not var.peek: + cast = "(PyObject *)" if var.type else "" + if var.name != "unused" and not var.is_array(): + if var.condition: + out.emit(f"if ({var.condition}) ") + out.emit( + f"stack_pointer[{self.base_offset.to_c()}] = {cast}{var.name};\n" + ) + self.base_offset.push(var) + if self.base_offset.to_c() != self.top_offset.to_c(): + print("base", self.base_offset.to_c(), "top", self.top_offset.to_c()) + assert False + number = self.base_offset.to_c() + if number != "0": + out.emit(f"stack_pointer += {number};\n") + self.variables = [] + self.base_offset.clear() + self.top_offset.clear() + self.peek_offset.clear() + + def as_comment(self) -> str: + return f"/* Variables: {[v.name for v in self.variables]}. Base offset: {self.base_offset.to_c()}. Top offset: {self.top_offset.to_c()} */" + + +def get_stack_effect(inst: Instruction) -> Stack: + stack = Stack() + for uop in inst.parts: + if not isinstance(uop, Uop): + continue + for var in reversed(uop.stack.inputs): + stack.pop(var) + for i, var in enumerate(uop.stack.outputs): + stack.push(var) + return stack diff --git a/Tools/cases_generator/stacking.py b/Tools/cases_generator/stacking.py deleted file mode 100644 index 23eca3037f896d..00000000000000 --- a/Tools/cases_generator/stacking.py +++ /dev/null @@ -1,400 +0,0 @@ -import dataclasses -import typing - -from formatting import ( - Formatter, - UNUSED, - maybe_parenthesize, - parenthesize_cond, -) -from instructions import ( - ActiveCacheEffect, - Instruction, - MacroInstruction, - Component, - Tiers, - TIER_ONE, -) -from parsing import StackEffect, CacheEffect, Family - - -@dataclasses.dataclass -class StackOffset: - """Represent the stack offset for a PEEK or POKE. - - - At stack_pointer[0], deep and high are both empty. - (Note that that is an invalid stack reference.) - - Below stack top, only deep is non-empty. - - Above stack top, only high is non-empty. - - In complex cases, both deep and high may be non-empty. - - All this would be much simpler if all stack entries were the same - size, but with conditional and array effects, they aren't. - The offsets are each represented by a list of StackEffect objects. - The name in the StackEffects is unused. - """ - - deep: list[StackEffect] = dataclasses.field(default_factory=list) - high: list[StackEffect] = dataclasses.field(default_factory=list) - - def clone(self) -> "StackOffset": - return StackOffset(list(self.deep), list(self.high)) - - def negate(self) -> "StackOffset": - return StackOffset(list(self.high), list(self.deep)) - - def deeper(self, eff: StackEffect) -> None: - if eff in self.high: - self.high.remove(eff) - else: - self.deep.append(eff) - - def higher(self, eff: StackEffect) -> None: - if eff in self.deep: - self.deep.remove(eff) - else: - self.high.append(eff) - - def as_terms(self) -> list[tuple[str, str]]: - num = 0 - terms: list[tuple[str, str]] = [] - for eff in self.deep: - if eff.size: - terms.append(("-", maybe_parenthesize(eff.size))) - elif eff.cond and eff.cond != "1": - terms.append(("-", f"({parenthesize_cond(eff.cond)} ? 1 : 0)")) - elif eff.cond != "0": - num -= 1 - for eff in self.high: - if eff.size: - terms.append(("+", maybe_parenthesize(eff.size))) - elif eff.cond and eff.cond != "1": - terms.append(("+", f"({parenthesize_cond(eff.cond)} ? 1 : 0)")) - elif eff.cond != "0": - num += 1 - if num < 0: - terms.insert(0, ("-", str(-num))) - elif num > 0: - terms.append(("+", str(num))) - return terms - - def as_index(self) -> str: - terms = self.as_terms() - return make_index(terms) - - -def make_index(terms: list[tuple[str, str]]) -> str: - # Produce an index expression from the terms honoring PEP 8, - # surrounding binary ops with spaces but not unary minus - index = "" - for sign, term in terms: - if index: - index += f" {sign} {term}" - elif sign == "+": - index = term - else: - index = sign + term - return index or "0" - - -@dataclasses.dataclass -class StackItem: - offset: StackOffset - effect: StackEffect - - def as_variable(self, lax: bool = False) -> str: - """Return e.g. stack_pointer[-1].""" - terms = self.offset.as_terms() - if self.effect.size: - terms.insert(0, ("+", "stack_pointer")) - index = make_index(terms) - if self.effect.size: - res = index - else: - res = f"stack_pointer[{index}]" - if not lax: - # Check that we're not reading or writing above stack top. - # Skip this for output variable initialization (lax=True). - assert ( - self.effect in self.offset.deep and not self.offset.high - ), f"Push or pop above current stack level: {res}" - return res - - -@dataclasses.dataclass -class CopyEffect: - src: StackEffect - dst: StackEffect - - -class EffectManager: - """Manage stack effects and offsets for an instruction.""" - - instr: Instruction - active_caches: list[ActiveCacheEffect] - peeks: list[StackItem] - pokes: list[StackItem] - copies: list[CopyEffect] # See merge() - # Track offsets from stack pointer - min_offset: StackOffset - final_offset: StackOffset - - def __init__( - self, - instr: Instruction, - active_caches: list[ActiveCacheEffect], - pred: "EffectManager | None" = None, - ): - self.instr = instr - self.active_caches = active_caches - self.peeks = [] - self.pokes = [] - self.copies = [] - self.final_offset = pred.final_offset.clone() if pred else StackOffset() - for eff in reversed(instr.input_effects): - self.final_offset.deeper(eff) - self.peeks.append(StackItem(offset=self.final_offset.clone(), effect=eff)) - self.min_offset = self.final_offset.clone() - for eff in instr.output_effects: - self.pokes.append(StackItem(offset=self.final_offset.clone(), effect=eff)) - self.final_offset.higher(eff) - - if pred: - # Replace push(x) + pop(y) with copy(x, y). - # Check that the sources and destinations are disjoint. - sources: set[str] = set() - destinations: set[str] = set() - while ( - pred.pokes - and self.peeks - and pred.pokes[-1].effect == self.peeks[-1].effect - ): - src = pred.pokes.pop(-1).effect - dst = self.peeks.pop(0).effect - pred.final_offset.deeper(src) - if dst.name != UNUSED: - destinations.add(dst.name) - if dst.name != src.name: - sources.add(src.name) - self.copies.append(CopyEffect(src, dst)) - # TODO: Turn this into an error (pass an Analyzer instance?) - assert sources & destinations == set(), ( - pred.instr.name, - self.instr.name, - sources, - destinations, - ) - - def adjust_deeper(self, eff: StackEffect) -> None: - for peek in self.peeks: - peek.offset.deeper(eff) - for poke in self.pokes: - poke.offset.deeper(eff) - self.min_offset.deeper(eff) - self.final_offset.deeper(eff) - - def adjust_higher(self, eff: StackEffect) -> None: - for peek in self.peeks: - peek.offset.higher(eff) - for poke in self.pokes: - poke.offset.higher(eff) - self.min_offset.higher(eff) - self.final_offset.higher(eff) - - def adjust(self, offset: StackOffset) -> None: - for down in offset.deep: - self.adjust_deeper(down) - for up in offset.high: - self.adjust_higher(up) - - def adjust_inverse(self, offset: StackOffset) -> None: - for down in offset.deep: - self.adjust_higher(down) - for up in offset.high: - self.adjust_deeper(up) - - def collect_vars(self) -> dict[str, StackEffect]: - """Collect all variables, skipping unused ones.""" - vars: dict[str, StackEffect] = {} - - def add(eff: StackEffect) -> None: - if eff.name != UNUSED: - if eff.name in vars: - # TODO: Make this an error - assert vars[eff.name] == eff, ( - self.instr.name, - eff.name, - vars[eff.name], - eff, - ) - else: - vars[eff.name] = eff - - for copy in self.copies: - add(copy.src) - add(copy.dst) - for peek in self.peeks: - add(peek.effect) - for poke in self.pokes: - add(poke.effect) - - return vars - - -def less_than(a: StackOffset, b: StackOffset) -> bool: - # TODO: Handle more cases - if a.high != b.high: - return False - return a.deep[: len(b.deep)] == b.deep - - -def get_managers(parts: list[Component]) -> list[EffectManager]: - managers: list[EffectManager] = [] - pred: EffectManager | None = None - for part in parts: - mgr = EffectManager(part.instr, part.active_caches, pred) - managers.append(mgr) - pred = mgr - return managers - - -def get_stack_effect_info_for_macro(mac: MacroInstruction) -> tuple[str, str]: - """Get the stack effect info for a macro instruction. - - Returns a tuple (popped, pushed) where each is a string giving a - symbolic expression for the number of values popped/pushed. - """ - parts = [part for part in mac.parts if isinstance(part, Component)] - managers = get_managers(parts) - popped = StackOffset() - for mgr in managers: - if less_than(mgr.min_offset, popped): - popped = mgr.min_offset.clone() - # Compute pushed = final - popped - pushed = managers[-1].final_offset.clone() - for effect in popped.deep: - pushed.higher(effect) - for effect in popped.high: - pushed.deeper(effect) - return popped.negate().as_index(), pushed.as_index() - - -def write_single_instr( - instr: Instruction, out: Formatter, tier: Tiers = TIER_ONE -) -> None: - try: - write_components( - [Component(instr, instr.active_caches)], - out, - tier, - ) - except AssertionError as err: - raise AssertionError(f"Error writing instruction {instr.name}") from err - - -def write_macro_instr( - mac: MacroInstruction, out: Formatter, family: Family | None -) -> None: - parts = [part for part in mac.parts if isinstance(part, Component)] - - cache_adjust = 0 - for part in mac.parts: - match part: - case CacheEffect(size=size): - cache_adjust += size - case Component(instr=instr): - cache_adjust += instr.cache_offset - case _: - typing.assert_never(part) - - out.emit("") - with out.block(f"TARGET({mac.name})"): - if mac.predicted: - out.emit(f"PREDICTED({mac.name});") - out.static_assert_family_size(mac.name, family, cache_adjust) - try: - write_components(parts, out, TIER_ONE) - except AssertionError as err: - raise AssertionError(f"Error writing macro {mac.name}") from err - if cache_adjust: - out.emit(f"next_instr += {cache_adjust};") - out.emit("DISPATCH();") - - -def write_components( - parts: list[Component], - out: Formatter, - tier: Tiers, -) -> None: - managers = get_managers(parts) - - all_vars: dict[str, StackEffect] = {} - for mgr in managers: - for name, eff in mgr.collect_vars().items(): - if name in all_vars: - # TODO: Turn this into an error -- variable conflict - assert all_vars[name] == eff, ( - name, - mgr.instr.name, - all_vars[name], - eff, - ) - else: - all_vars[name] = eff - - # Declare all variables - for name, eff in all_vars.items(): - out.declare(eff, None) - - for mgr in managers: - if len(parts) > 1: - out.emit(f"// {mgr.instr.name}") - - for copy in mgr.copies: - if copy.src.name != copy.dst.name: - out.assign(copy.dst, copy.src) - for peek in mgr.peeks: - out.assign( - peek.effect, - StackEffect( - peek.as_variable(), - peek.effect.type, - peek.effect.cond, - peek.effect.size, - ), - ) - # Initialize array outputs - for poke in mgr.pokes: - if poke.effect.size and poke.effect.name not in mgr.instr.unmoved_names: - out.assign( - poke.effect, - StackEffect( - poke.as_variable(lax=True), - poke.effect.type, - poke.effect.cond, - poke.effect.size, - ), - ) - - if len(parts) == 1: - mgr.instr.write_body(out, 0, mgr.active_caches, tier) - else: - with out.block(""): - mgr.instr.write_body(out, -4, mgr.active_caches, tier) - - if mgr is managers[-1]: - out.stack_adjust(mgr.final_offset.deep, mgr.final_offset.high) - # Use clone() since adjust_inverse() mutates final_offset - mgr.adjust_inverse(mgr.final_offset.clone()) - - for poke in mgr.pokes: - if not poke.effect.size and poke.effect.name not in mgr.instr.unmoved_names: - out.assign( - StackEffect( - poke.as_variable(), - poke.effect.type, - poke.effect.cond, - poke.effect.size, - ), - poke.effect, - ) diff --git a/Tools/cases_generator/target_generator.py b/Tools/cases_generator/target_generator.py new file mode 100644 index 00000000000000..44a699c92bbd22 --- /dev/null +++ b/Tools/cases_generator/target_generator.py @@ -0,0 +1,54 @@ +"""Generate targets for computed goto dispatch +Reads the instruction definitions from bytecodes.c. +Writes the table to opcode_targets.h by default. +""" + +import argparse + +from analyzer import ( + Analysis, + analyze_files, +) +from generators_common import ( + DEFAULT_INPUT, + ROOT, +) +from cwriter import CWriter +from typing import TextIO + + +DEFAULT_OUTPUT = ROOT / "Python/opcode_targets.h" + + +def write_opcode_targets(analysis: Analysis, out: CWriter) -> None: + """Write header file that defines the jump target table""" + targets = ["&&_unknown_opcode,\n"] * 256 + for name, op in analysis.opmap.items(): + if op < 256: + targets[op] = f"&&TARGET_{name},\n" + out.emit("static void *opcode_targets[256] = {\n") + for target in targets: + out.emit(target) + out.emit("};\n") + +arg_parser = argparse.ArgumentParser( + description="Generate the file with dispatch targets.", + formatter_class=argparse.ArgumentDefaultsHelpFormatter, +) + +arg_parser.add_argument( + "-o", "--output", type=str, help="Generated code", default=DEFAULT_OUTPUT +) + +arg_parser.add_argument( + "input", nargs=argparse.REMAINDER, help="Instruction definition file(s)" +) + +if __name__ == "__main__": + args = arg_parser.parse_args() + if len(args.input) == 0: + args.input.append(DEFAULT_INPUT) + data = analyze_files(args.input) + with open(args.output, "w") as outfile: + out = CWriter(outfile, 0, False) + write_opcode_targets(data, out) diff --git a/Tools/cases_generator/tier1_generator.py b/Tools/cases_generator/tier1_generator.py new file mode 100644 index 00000000000000..aba36ec74e5766 --- /dev/null +++ b/Tools/cases_generator/tier1_generator.py @@ -0,0 +1,200 @@ +"""Generate the main interpreter switch. +Reads the instruction definitions from bytecodes.c. +Writes the cases to generated_cases.c.h, which is #included in ceval.c. +""" + +import argparse +import os.path +import sys + +from analyzer import ( + Analysis, + Instruction, + Uop, + Part, + analyze_files, + Skip, + StackItem, + analysis_error, +) +from generators_common import ( + DEFAULT_INPUT, + ROOT, + write_header, + emit_tokens, +) +from cwriter import CWriter +from typing import TextIO, Iterator +from lexer import Token +from stack import StackOffset, Stack, SizeMismatch + + +DEFAULT_OUTPUT = ROOT / "Python/generated_cases.c.h" + + +FOOTER = "#undef TIER_ONE\n" + + +def declare_variables(inst: Instruction, out: CWriter) -> None: + variables = {"unused"} + for uop in inst.parts: + if isinstance(uop, Uop): + for var in reversed(uop.stack.inputs): + if var.name not in variables: + type = var.type if var.type else "PyObject *" + variables.add(var.name) + if var.condition: + out.emit(f"{type}{var.name} = NULL;\n") + else: + out.emit(f"{type}{var.name};\n") + for var in uop.stack.outputs: + if var.name not in variables: + variables.add(var.name) + type = var.type if var.type else "PyObject *" + if var.condition: + out.emit(f"{type}{var.name} = NULL;\n") + else: + out.emit(f"{type}{var.name};\n") + + +def write_uop( + uop: Part, out: CWriter, offset: int, stack: Stack, inst: Instruction, braces: bool +) -> int: + # out.emit(stack.as_comment() + "\n") + if isinstance(uop, Skip): + entries = "entries" if uop.size > 1 else "entry" + out.emit(f"/* Skip {uop.size} cache {entries} */\n") + return offset + uop.size + try: + out.start_line() + if braces: + out.emit(f"// {uop.name}\n") + for var in reversed(uop.stack.inputs): + out.emit(stack.pop(var)) + if braces: + out.emit("{\n") + if not uop.properties.stores_sp: + for i, var in enumerate(uop.stack.outputs): + out.emit(stack.push(var)) + for cache in uop.caches: + if cache.name != "unused": + if cache.size == 4: + type = "PyObject *" + reader = "read_obj" + else: + type = f"uint{cache.size*16}_t " + reader = f"read_u{cache.size*16}" + out.emit( + f"{type}{cache.name} = {reader}(&this_instr[{offset}].cache);\n" + ) + offset += cache.size + emit_tokens(out, uop, stack, inst) + if uop.properties.stores_sp: + for i, var in enumerate(uop.stack.outputs): + out.emit(stack.push(var)) + if braces: + out.start_line() + out.emit("}\n") + # out.emit(stack.as_comment() + "\n") + return offset + except SizeMismatch as ex: + raise analysis_error(ex.args[0], uop.body[0]) + + +def uses_this(inst: Instruction) -> bool: + if inst.properties.needs_this: + return True + for uop in inst.parts: + if isinstance(uop, Skip): + continue + for cache in uop.caches: + if cache.name != "unused": + return True + return False + + +def generate_tier1( + filenames: list[str], analysis: Analysis, outfile: TextIO, lines: bool +) -> None: + write_header(__file__, filenames, outfile) + outfile.write( + """ +#ifdef TIER_TWO + #error "This file is for Tier 1 only" +#endif +#define TIER_ONE 1 +""" + ) + out = CWriter(outfile, 2, lines) + out.emit("\n") + for name, inst in sorted(analysis.instructions.items()): + needs_this = uses_this(inst) + out.emit("\n") + out.emit(f"TARGET({name}) {{\n") + if needs_this and not inst.is_target: + out.emit(f"_Py_CODEUNIT *this_instr = frame->instr_ptr = next_instr;\n") + else: + out.emit(f"frame->instr_ptr = next_instr;\n") + out.emit(f"next_instr += {inst.size};\n") + out.emit(f"INSTRUCTION_STATS({name});\n") + if inst.is_target: + out.emit(f"PREDICTED({name});\n") + if needs_this: + out.emit(f"_Py_CODEUNIT *this_instr = next_instr - {inst.size};\n") + if inst.family is not None: + out.emit( + f"static_assert({inst.family.size} == {inst.size-1}" + ', "incorrect cache size");\n' + ) + declare_variables(inst, out) + offset = 1 # The instruction itself + stack = Stack() + for part in inst.parts: + # Only emit braces if more than one uop + insert_braces = len([p for p in inst.parts if isinstance(p, Uop)]) > 1 + offset = write_uop(part, out, offset, stack, inst, insert_braces) + out.start_line() + if not inst.parts[-1].properties.always_exits: + stack.flush(out) + if inst.parts[-1].properties.ends_with_eval_breaker: + out.emit("CHECK_EVAL_BREAKER();\n") + out.emit("DISPATCH();\n") + out.start_line() + out.emit("}") + out.emit("\n") + outfile.write(FOOTER) + + +arg_parser = argparse.ArgumentParser( + description="Generate the code for the interpreter switch.", + formatter_class=argparse.ArgumentDefaultsHelpFormatter, +) + +arg_parser.add_argument( + "-o", "--output", type=str, help="Generated code", default=DEFAULT_OUTPUT +) + +arg_parser.add_argument( + "-l", "--emit-line-directives", help="Emit #line directives", action="store_true" +) + +arg_parser.add_argument( + "input", nargs=argparse.REMAINDER, help="Instruction definition file(s)" +) + + +def generate_tier1_from_files( + filenames: list[str], outfilename: str, lines: bool +) -> None: + data = analyze_files(filenames) + with open(outfilename, "w") as outfile: + generate_tier1(filenames, data, outfile, lines) + + +if __name__ == "__main__": + args = arg_parser.parse_args() + if len(args.input) == 0: + args.input.append(DEFAULT_INPUT) + data = analyze_files(args.input) + with open(args.output, "w") as outfile: + generate_tier1(args.input, data, outfile, args.emit_line_directives) diff --git a/Tools/cases_generator/tier2_generator.py b/Tools/cases_generator/tier2_generator.py new file mode 100644 index 00000000000000..7897b89b2752a7 --- /dev/null +++ b/Tools/cases_generator/tier2_generator.py @@ -0,0 +1,196 @@ +"""Generate the cases for the tier 2 interpreter. +Reads the instruction definitions from bytecodes.c. +Writes the cases to executor_cases.c.h, which is #included in ceval.c. +""" + +import argparse +import os.path +import sys + +from analyzer import ( + Analysis, + Instruction, + Uop, + Part, + analyze_files, + Skip, + StackItem, + analysis_error, +) +from generators_common import ( + DEFAULT_INPUT, + ROOT, + write_header, + emit_tokens, + emit_to, + REPLACEMENT_FUNCTIONS, +) +from cwriter import CWriter +from typing import TextIO, Iterator +from lexer import Token +from stack import StackOffset, Stack, SizeMismatch + +DEFAULT_OUTPUT = ROOT / "Python/executor_cases.c.h" + + +def declare_variables(uop: Uop, out: CWriter) -> None: + variables = {"unused"} + for var in reversed(uop.stack.inputs): + if var.name not in variables: + type = var.type if var.type else "PyObject *" + variables.add(var.name) + if var.condition: + out.emit(f"{type}{var.name} = NULL;\n") + else: + out.emit(f"{type}{var.name};\n") + for var in uop.stack.outputs: + if var.name not in variables: + variables.add(var.name) + type = var.type if var.type else "PyObject *" + if var.condition: + out.emit(f"{type}{var.name} = NULL;\n") + else: + out.emit(f"{type}{var.name};\n") + + +def tier2_replace_error( + out: CWriter, + tkn: Token, + tkn_iter: Iterator[Token], + uop: Uop, + stack: Stack, + inst: Instruction | None, +) -> None: + out.emit_at("if ", tkn) + out.emit(next(tkn_iter)) + emit_to(out, tkn_iter, "COMMA") + label = next(tkn_iter).text + next(tkn_iter) # RPAREN + next(tkn_iter) # Semi colon + out.emit(") ") + c_offset = stack.peek_offset.to_c() + try: + offset = -int(c_offset) + close = ";\n" + except ValueError: + offset = None + out.emit(f"{{ stack_pointer += {c_offset}; ") + close = "; }\n" + out.emit("goto ") + if offset: + out.emit(f"pop_{offset}_") + out.emit(label + "_tier_two") + out.emit(close) + + +def tier2_replace_deopt( + out: CWriter, + tkn: Token, + tkn_iter: Iterator[Token], + uop: Uop, + unused: Stack, + inst: Instruction | None, +) -> None: + out.emit_at("if ", tkn) + out.emit(next(tkn_iter)) + emit_to(out, tkn_iter, "RPAREN") + next(tkn_iter) # Semi colon + out.emit(") goto deoptimize;\n") + + +TIER2_REPLACEMENT_FUNCTIONS = REPLACEMENT_FUNCTIONS.copy() +TIER2_REPLACEMENT_FUNCTIONS["ERROR_IF"] = tier2_replace_error +TIER2_REPLACEMENT_FUNCTIONS["DEOPT_IF"] = tier2_replace_deopt + + +def write_uop(uop: Uop, out: CWriter, stack: Stack) -> None: + try: + out.start_line() + if uop.properties.oparg: + out.emit("oparg = CURRENT_OPARG();\n") + for var in reversed(uop.stack.inputs): + out.emit(stack.pop(var)) + if not uop.properties.stores_sp: + for i, var in enumerate(uop.stack.outputs): + out.emit(stack.push(var)) + for cache in uop.caches: + if cache.name != "unused": + if cache.size == 4: + type = cast = "PyObject *" + else: + type = f"uint{cache.size*16}_t " + cast = f"uint{cache.size*16}_t" + out.emit(f"{type}{cache.name} = ({cast})CURRENT_OPERAND();\n") + emit_tokens(out, uop, stack, None, TIER2_REPLACEMENT_FUNCTIONS) + if uop.properties.stores_sp: + for i, var in enumerate(uop.stack.outputs): + out.emit(stack.push(var)) + except SizeMismatch as ex: + raise analysis_error(ex.args[0], uop.body[0]) + + +SKIPS = ("_EXTENDED_ARG",) + + +def generate_tier2( + filenames: list[str], analysis: Analysis, outfile: TextIO, lines: bool +) -> None: + write_header(__file__, filenames, outfile) + outfile.write( + """ +#ifdef TIER_ONE + #error "This file is for Tier 2 only" +#endif +#define TIER_TWO 2 +""" + ) + out = CWriter(outfile, 2, lines) + out.emit("\n") + for name, uop in analysis.uops.items(): + if uop.properties.tier_one_only: + continue + if uop.is_super(): + continue + if not uop.is_viable(): + out.emit(f"/* {uop.name} is not a viable micro-op for tier 2 */\n\n") + continue + out.emit(f"case {uop.name}: {{\n") + declare_variables(uop, out) + stack = Stack() + write_uop(uop, out, stack) + out.start_line() + if not uop.properties.always_exits: + stack.flush(out) + if uop.properties.ends_with_eval_breaker: + out.emit("CHECK_EVAL_BREAKER();\n") + out.emit("break;\n") + out.start_line() + out.emit("}") + out.emit("\n\n") + outfile.write("#undef TIER_TWO\n") + + +arg_parser = argparse.ArgumentParser( + description="Generate the code for the tier 2 interpreter.", + formatter_class=argparse.ArgumentDefaultsHelpFormatter, +) + +arg_parser.add_argument( + "-o", "--output", type=str, help="Generated code", default=DEFAULT_OUTPUT +) + +arg_parser.add_argument( + "-l", "--emit-line-directives", help="Emit #line directives", action="store_true" +) + +arg_parser.add_argument( + "input", nargs=argparse.REMAINDER, help="Instruction definition file(s)" +) + +if __name__ == "__main__": + args = arg_parser.parse_args() + if len(args.input) == 0: + args.input.append(DEFAULT_INPUT) + data = analyze_files(args.input) + with open(args.output, "w") as outfile: + generate_tier2(args.input, data, outfile, args.emit_line_directives) diff --git a/Tools/cases_generator/uop_id_generator.py b/Tools/cases_generator/uop_id_generator.py new file mode 100644 index 00000000000000..633249f1c6b1fe --- /dev/null +++ b/Tools/cases_generator/uop_id_generator.py @@ -0,0 +1,80 @@ +"""Generate the list of uop IDs. +Reads the instruction definitions from bytecodes.c. +Writes the IDs to pycore_uop_ids.h by default. +""" + +import argparse +import os.path +import sys + +from analyzer import ( + Analysis, + Instruction, + analyze_files, +) +from generators_common import ( + DEFAULT_INPUT, + ROOT, + write_header, +) +from cwriter import CWriter +from typing import TextIO + + +DEFAULT_OUTPUT = ROOT / "Include/internal/pycore_uop_ids.h" + + +def generate_uop_ids( + filenames: list[str], analysis: Analysis, outfile: TextIO, distinct_namespace: bool +) -> None: + write_header(__file__, filenames, outfile) + out = CWriter(outfile, 0, False) + with out.header_guard("Py_CORE_UOP_IDS_H"): + next_id = 1 if distinct_namespace else 300 + # These two are first by convention + out.emit(f"#define _EXIT_TRACE {next_id}\n") + next_id += 1 + out.emit(f"#define _SET_IP {next_id}\n") + next_id += 1 + PRE_DEFINED = {"_EXIT_TRACE", "_SET_IP"} + + for uop in analysis.uops.values(): + if uop.name in PRE_DEFINED: + continue + if uop.properties.tier_one_only: + continue + if uop.implicitly_created and not distinct_namespace: + out.emit(f"#define {uop.name} {uop.name[1:]}\n") + else: + out.emit(f"#define {uop.name} {next_id}\n") + next_id += 1 + + out.emit(f"#define MAX_UOP_ID {next_id-1}\n") + + +arg_parser = argparse.ArgumentParser( + description="Generate the header file with all uop IDs.", + formatter_class=argparse.ArgumentDefaultsHelpFormatter, +) + +arg_parser.add_argument( + "-o", "--output", type=str, help="Generated code", default=DEFAULT_OUTPUT +) +arg_parser.add_argument( + "-n", + "--namespace", + help="Give uops a distinct namespace", + action="store_true", +) + +arg_parser.add_argument( + "input", nargs=argparse.REMAINDER, help="Instruction definition file(s)" +) + +if __name__ == "__main__": + args = arg_parser.parse_args() + if len(args.input) == 0: + args.input.append(DEFAULT_INPUT) + data = analyze_files(args.input) + with open(args.output, "w") as outfile: + generate_uop_ids(args.input, data, outfile, args.namespace) diff --git a/Tools/cases_generator/uop_metadata_generator.py b/Tools/cases_generator/uop_metadata_generator.py new file mode 100644 index 00000000000000..d4f3a096d2acc1 --- /dev/null +++ b/Tools/cases_generator/uop_metadata_generator.py @@ -0,0 +1,73 @@ +"""Generate uop metedata. +Reads the instruction definitions from bytecodes.c. +Writes the metadata to pycore_uop_metadata.h by default. +""" + +import argparse + +from analyzer import ( + Analysis, + analyze_files, +) +from generators_common import ( + DEFAULT_INPUT, + ROOT, + write_header, + cflags, +) +from cwriter import CWriter +from typing import TextIO + + +DEFAULT_OUTPUT = ROOT / "Include/internal/pycore_uop_metadata.h" + + +def generate_names_and_flags(analysis: Analysis, out: CWriter) -> None: + out.emit("extern const uint16_t _PyUop_Flags[MAX_UOP_ID+1];\n") + out.emit("extern const char * const _PyOpcode_uop_name[MAX_UOP_ID+1];\n\n") + out.emit("#ifdef NEED_OPCODE_METADATA\n") + out.emit("const uint16_t _PyUop_Flags[MAX_UOP_ID+1] = {\n") + for uop in analysis.uops.values(): + if uop.is_viable() and not uop.properties.tier_one_only: + out.emit(f"[{uop.name}] = {cflags(uop.properties)},\n") + + out.emit("};\n\n") + out.emit("const char *const _PyOpcode_uop_name[MAX_UOP_ID+1] = {\n") + for uop in sorted(analysis.uops.values(), key=lambda t: t.name): + if uop.is_viable() and not uop.properties.tier_one_only: + out.emit(f'[{uop.name}] = "{uop.name}",\n') + out.emit("};\n") + out.emit("#endif // NEED_OPCODE_METADATA\n\n") + + +def generate_uop_metadata( + filenames: list[str], analysis: Analysis, outfile: TextIO +) -> None: + write_header(__file__, filenames, outfile) + out = CWriter(outfile, 0, False) + with out.header_guard("Py_CORE_UOP_METADATA_H"): + out.emit("#include \n") + out.emit('#include "pycore_uop_ids.h"\n') + generate_names_and_flags(analysis, out) + + +arg_parser = argparse.ArgumentParser( + description="Generate the header file with uop metadata.", + formatter_class=argparse.ArgumentDefaultsHelpFormatter, +) + +arg_parser.add_argument( + "-o", "--output", type=str, help="Generated code", default=DEFAULT_OUTPUT +) + +arg_parser.add_argument( + "input", nargs=argparse.REMAINDER, help="Instruction definition file(s)" +) + +if __name__ == "__main__": + args = arg_parser.parse_args() + if len(args.input) == 0: + args.input.append(DEFAULT_INPUT) + data = analyze_files(args.input) + with open(args.output, "w") as outfile: + generate_uop_metadata(args.input, data, outfile) diff --git a/Tools/clinic/.ruff.toml b/Tools/clinic/.ruff.toml new file mode 100644 index 00000000000000..cbb3a9a8f3a8c2 --- /dev/null +++ b/Tools/clinic/.ruff.toml @@ -0,0 +1,29 @@ +target-version = "py310" +fix = true +select = [ + "F", # Enable all pyflakes rules + "UP", # Enable all pyupgrade rules by default + "RUF100", # Ban unused `# noqa` comments + "PGH004", # Ban blanket `# noqa` comments (only ignore specific error codes) +] +ignore = [ + # Unnecessary parentheses to functools.lru_cache: just leads to unnecessary churn. + # https://github.com/python/cpython/pull/104684#discussion_r1199653347. + "UP011", + # Use format specifiers instead of %-style formatting. + # Doesn't always make code more readable. + "UP031", + # Use f-strings instead of format specifiers. + # Doesn't always make code more readable. + "UP032", + # Use PEP-604 unions rather than tuples for isinstance() checks. + # Makes code slower and more verbose. https://github.com/astral-sh/ruff/issues/7871. + "UP038", +] +unfixable = [ + # The autofixes sometimes do the wrong things for these; + # it's better to have to manually look at the code and see how it needs fixing + "F841", # Detects unused variables + "F601", # Detects dictionaries that have duplicate keys + "F602", # Also detects dictionaries that have duplicate keys +] diff --git a/Tools/clinic/clinic.py b/Tools/clinic/clinic.py index 423cdfb939c161..f6f95580f1a177 100755 --- a/Tools/clinic/clinic.py +++ b/Tools/clinic/clinic.py @@ -13,7 +13,6 @@ import collections import contextlib import copy -import cpp import dataclasses as dc import enum import functools @@ -35,6 +34,7 @@ Iterator, Sequence, ) +from operator import attrgetter from types import FunctionType, NoneType from typing import ( TYPE_CHECKING, @@ -49,6 +49,13 @@ overload, ) + +# Local imports. +import libclinic +import libclinic.cpp +from libclinic import ClinicError + + # TODO: # # soon: @@ -60,22 +67,9 @@ # and keyword-only # -version = '1' - -NO_VARARG = "PY_SSIZE_T_MAX" -CLINIC_PREFIX = "__clinic_" -CLINIC_PREFIXED_ARGS = { - "_keywords", - "_parser", - "args", - "argsbuf", - "fastargs", - "kwargs", - "kwnames", - "nargs", - "noptargs", - "return_value", -} + +# match '#define Py_LIMITED_API' +LIMITED_CAPI_REGEX = re.compile(r'#define +Py_LIMITED_API') class Sentinels(enum.Enum): @@ -98,65 +92,8 @@ def __repr__(self) -> str: NULL = Null() -sig_end_marker = '--' - -Appender = Callable[[str], None] -Outputter = Callable[[], str] TemplateDict = dict[str, str] -class _TextAccumulator(NamedTuple): - text: list[str] - append: Appender - output: Outputter - -def _text_accumulator() -> _TextAccumulator: - text: list[str] = [] - def output() -> str: - s = ''.join(text) - text.clear() - return s - return _TextAccumulator(text, text.append, output) - - -class TextAccumulator(NamedTuple): - append: Appender - output: Outputter - -def text_accumulator() -> TextAccumulator: - """ - Creates a simple text accumulator / joiner. - - Returns a pair of callables: - append, output - "append" appends a string to the accumulator. - "output" returns the contents of the accumulator - joined together (''.join(accumulator)) and - empties the accumulator. - """ - text, append, output = _text_accumulator() - return TextAccumulator(append, output) - - -@dc.dataclass -class ClinicError(Exception): - message: str - _: dc.KW_ONLY - lineno: int | None = None - filename: str | None = None - - def __post_init__(self) -> None: - super().__init__(self.message) - - def report(self, *, warn_only: bool = False) -> str: - msg = "Warning" if warn_only else "Error" - if self.filename is not None: - msg += f" in file {self.filename!r}" - if self.lineno is not None: - msg += f" on line {self.lineno}" - msg += ":\n" - msg += f"{self.message}\n" - return msg - @overload def warn_or_fail( @@ -208,19 +145,6 @@ def fail( warn_or_fail(*args, filename=filename, line_number=line_number, fail=True) -def quoted_for_c_string(s: str) -> str: - for old, new in ( - ('\\', '\\\\'), # must be first! - ('"', '\\"'), - ("'", "\\'"), - ): - s = s.replace(old, new) - return s - -def c_repr(s: str) -> str: - return '"' + s + '"' - - is_legal_c_identifier = re.compile('^[A-Za-z_][A-Za-z0-9_]*$').match def is_legal_py_identifier(s: str) -> bool: @@ -245,20 +169,6 @@ def ensure_legal_c_identifier(s: str) -> str: return s + "_value" return s -def rstrip_lines(s: str) -> str: - text, add, output = _text_accumulator() - for line in s.split('\n'): - add(line.rstrip()) - add('\n') - text.pop() - return output() - -def format_escape(s: str) -> str: - # double up curly-braces, this string will be used - # as part of a format_map() template later - s = s.replace('{', '{{') - s = s.replace('}', '}}') - return s def linear_format(s: str, **kwargs: str) -> str: """ @@ -274,19 +184,16 @@ def linear_format(s: str, **kwargs: str) -> str: by the indent of the source line. * A newline will be added to the end. """ - - add, output = text_accumulator() + lines = [] for line in s.split('\n'): indent, curly, trailing = line.partition('{') if not curly: - add(line) - add('\n') + lines.extend([line, "\n"]) continue name, curly, trailing = trailing.partition('}') if not curly or name not in kwargs: - add(line) - add('\n') + lines.extend([line, "\n"]) continue if trailing: @@ -300,94 +207,11 @@ def linear_format(s: str, **kwargs: str) -> str: if not value: continue - value = textwrap.indent(rstrip_lines(value), indent) - add(value) - add('\n') - - return output()[:-1] + stripped = [line.rstrip() for line in value.split("\n")] + value = textwrap.indent("\n".join(stripped), indent) + lines.extend([value, "\n"]) -def indent_all_lines(s: str, prefix: str) -> str: - """ - Returns 's', with 'prefix' prepended to all lines. - - If the last line is empty, prefix is not prepended - to it. (If s is blank, returns s unchanged.) - - (textwrap.indent only adds to non-blank lines.) - """ - split = s.split('\n') - last = split.pop() - final = [] - for line in split: - final.append(prefix) - final.append(line) - final.append('\n') - if last: - final.append(prefix) - final.append(last) - return ''.join(final) - -def suffix_all_lines(s: str, suffix: str) -> str: - """ - Returns 's', with 'suffix' appended to all lines. - - If the last line is empty, suffix is not appended - to it. (If s is blank, returns s unchanged.) - """ - split = s.split('\n') - last = split.pop() - final = [] - for line in split: - final.append(line) - final.append(suffix) - final.append('\n') - if last: - final.append(last) - final.append(suffix) - return ''.join(final) - - -def version_splitter(s: str) -> tuple[int, ...]: - """Splits a version string into a tuple of integers. - - The following ASCII characters are allowed, and employ - the following conversions: - a -> -3 - b -> -2 - c -> -1 - (This permits Python-style version strings such as "1.4b3".) - """ - version: list[int] = [] - accumulator: list[str] = [] - def flush() -> None: - if not accumulator: - fail(f'Unsupported version string: {s!r}') - version.append(int(''.join(accumulator))) - accumulator.clear() - - for c in s: - if c.isdigit(): - accumulator.append(c) - elif c == '.': - flush() - elif c in 'abc': - flush() - version.append('abc'.index(c) - 3) - else: - fail(f'Illegal character {c!r} in version string {s!r}') - flush() - return tuple(version) - -def version_comparitor(version1: str, version2: str) -> Literal[-1, 0, 1]: - iterator = itertools.zip_longest( - version_splitter(version1), version_splitter(version2), fillvalue=0 - ) - for a, b in iterator: - if a < b: - return -1 - if a > b: - return 1 - return 0 + return "".join(lines[:-1]) class CRenderData: @@ -442,6 +266,10 @@ def __init__(self) -> None: # The C statements required to clean up after the impl call. self.cleanup: list[str] = [] + # The C statements to generate critical sections (per-object locking). + self.lock: list[str] = [] + self.unlock: list[str] = [] + class FormatCounterFormatter(string.Formatter): """ @@ -469,7 +297,7 @@ class Language(metaclass=abc.ABCMeta): checksum_line = "" def __init__(self, filename: str) -> None: - pass + ... @abc.abstractmethod def render( @@ -477,10 +305,10 @@ def render( clinic: Clinic | None, signatures: Iterable[Module | Class | Function] ) -> str: - pass + ... def parse_line(self, line: str) -> None: - pass + ... def validate(self) -> None: def assert_only_one( @@ -621,38 +449,12 @@ def permute_optional_groups( return tuple(accumulator) -def strip_leading_and_trailing_blank_lines(s: str) -> str: - lines = s.rstrip().split('\n') - while lines: - line = lines[0] - if line.strip(): - break - del lines[0] - return '\n'.join(lines) - -@functools.lru_cache() -def normalize_snippet( - s: str, - *, - indent: int = 0 -) -> str: - """ - Reformats s: - * removes leading and trailing blank lines - * ensures that it does not end with a newline - * dedents so the first nonwhite character on any line is at column "indent" - """ - s = strip_leading_and_trailing_blank_lines(s) - s = textwrap.dedent(s) - if indent: - s = textwrap.indent(s, ' ' * indent) - return s - - def declare_parser( f: Function, *, - hasformat: bool = False + hasformat: bool = False, + clinic: Clinic, + limited_capi: bool, ) -> str: """ Generates the code template for a static local PyArg_Parser variable, @@ -671,7 +473,11 @@ def declare_parser( p for p in f.parameters.values() if not p.is_positional_only() and not p.is_vararg() ]) - if num_keywords == 0: + if limited_capi: + declarations = """ + #define KWTUPLE NULL + """ + elif num_keywords == 0: declarations = """ #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) # define KWTUPLE (PyObject *)&_Py_SINGLETON(tuple_empty) @@ -700,6 +506,10 @@ def declare_parser( #endif // !Py_BUILD_CORE """ % num_keywords + condition = '#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)' + clinic.add_include('pycore_gc.h', 'PyGC_Head', condition=condition) + clinic.add_include('pycore_runtime.h', '_Py_ID()', condition=condition) + declarations += """ static const char * const _keywords[] = {{{keywords_c} NULL}}; static _PyArg_Parser _parser = {{ @@ -709,62 +519,7 @@ def declare_parser( }}; #undef KWTUPLE """ % (format_ or fname) - return normalize_snippet(declarations) - - -def wrap_declarations( - text: str, - length: int = 78 -) -> str: - """ - A simple-minded text wrapper for C function declarations. - - It views a declaration line as looking like this: - xxxxxxxx(xxxxxxxxx,xxxxxxxxx) - If called with length=30, it would wrap that line into - xxxxxxxx(xxxxxxxxx, - xxxxxxxxx) - (If the declaration has zero or one parameters, this - function won't wrap it.) - - If this doesn't work properly, it's probably better to - start from scratch with a more sophisticated algorithm, - rather than try and improve/debug this dumb little function. - """ - lines = [] - for line in text.split('\n'): - prefix, _, after_l_paren = line.partition('(') - if not after_l_paren: - lines.append(line) - continue - in_paren, _, after_r_paren = after_l_paren.partition(')') - if not _: - lines.append(line) - continue - if ',' not in in_paren: - lines.append(line) - continue - parameters = [x.strip() + ", " for x in in_paren.split(',')] - prefix += "(" - if len(prefix) < length: - spaces = " " * len(prefix) - else: - spaces = " " * 4 - - while parameters: - line = prefix - first = True - while parameters: - if (not first and - (len(line) + len(parameters[0]) > length)): - break - line += parameters.pop(0) - first = False - if not parameters: - line = line.rstrip(", ") + ")" + after_r_paren - lines.append(line.rstrip()) - prefix = spaces - return "\n".join(lines) + return libclinic.normalize_snippet(declarations) class CLanguage(Language): @@ -776,63 +531,124 @@ class CLanguage(Language): stop_line = "[{dsl_name} start generated code]*/" checksum_line = "/*[{dsl_name} end generated code: {arguments}]*/" - PARSER_PROTOTYPE_KEYWORD: Final[str] = normalize_snippet(""" + NO_VARARG: Final[str] = "PY_SSIZE_T_MAX" + + PARSER_PROTOTYPE_KEYWORD: Final[str] = libclinic.normalize_snippet(""" static PyObject * {c_basename}({self_type}{self_name}, PyObject *args, PyObject *kwargs) """) - PARSER_PROTOTYPE_KEYWORD___INIT__: Final[str] = normalize_snippet(""" + PARSER_PROTOTYPE_KEYWORD___INIT__: Final[str] = libclinic.normalize_snippet(""" static int {c_basename}({self_type}{self_name}, PyObject *args, PyObject *kwargs) """) - PARSER_PROTOTYPE_VARARGS: Final[str] = normalize_snippet(""" + PARSER_PROTOTYPE_VARARGS: Final[str] = libclinic.normalize_snippet(""" static PyObject * {c_basename}({self_type}{self_name}, PyObject *args) """) - PARSER_PROTOTYPE_FASTCALL: Final[str] = normalize_snippet(""" + PARSER_PROTOTYPE_FASTCALL: Final[str] = libclinic.normalize_snippet(""" static PyObject * {c_basename}({self_type}{self_name}, PyObject *const *args, Py_ssize_t nargs) """) - PARSER_PROTOTYPE_FASTCALL_KEYWORDS: Final[str] = normalize_snippet(""" + PARSER_PROTOTYPE_FASTCALL_KEYWORDS: Final[str] = libclinic.normalize_snippet(""" static PyObject * {c_basename}({self_type}{self_name}, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) """) - PARSER_PROTOTYPE_DEF_CLASS: Final[str] = normalize_snippet(""" + PARSER_PROTOTYPE_DEF_CLASS: Final[str] = libclinic.normalize_snippet(""" static PyObject * {c_basename}({self_type}{self_name}, PyTypeObject *{defining_class_name}, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) """) - PARSER_PROTOTYPE_NOARGS: Final[str] = normalize_snippet(""" + PARSER_PROTOTYPE_NOARGS: Final[str] = libclinic.normalize_snippet(""" static PyObject * {c_basename}({self_type}{self_name}, PyObject *Py_UNUSED(ignored)) """) - METH_O_PROTOTYPE: Final[str] = normalize_snippet(""" + PARSER_PROTOTYPE_GETTER: Final[str] = libclinic.normalize_snippet(""" + static PyObject * + {c_basename}({self_type}{self_name}, void *Py_UNUSED(context)) + """) + PARSER_PROTOTYPE_SETTER: Final[str] = libclinic.normalize_snippet(""" + static int + {c_basename}({self_type}{self_name}, PyObject *value, void *Py_UNUSED(context)) + """) + METH_O_PROTOTYPE: Final[str] = libclinic.normalize_snippet(""" static PyObject * {c_basename}({impl_parameters}) """) - DOCSTRING_PROTOTYPE_VAR: Final[str] = normalize_snippet(""" + DOCSTRING_PROTOTYPE_VAR: Final[str] = libclinic.normalize_snippet(""" PyDoc_VAR({c_basename}__doc__); """) - DOCSTRING_PROTOTYPE_STRVAR: Final[str] = normalize_snippet(""" + DOCSTRING_PROTOTYPE_STRVAR: Final[str] = libclinic.normalize_snippet(""" PyDoc_STRVAR({c_basename}__doc__, {docstring}); """) - IMPL_DEFINITION_PROTOTYPE: Final[str] = normalize_snippet(""" + GETSET_DOCSTRING_PROTOTYPE_STRVAR: Final[str] = libclinic.normalize_snippet(""" + PyDoc_STRVAR({getset_basename}__doc__, + {docstring}); + #define {getset_basename}_HAS_DOCSTR + """) + IMPL_DEFINITION_PROTOTYPE: Final[str] = libclinic.normalize_snippet(""" static {impl_return_type} {c_basename}_impl({impl_parameters}) """) - METHODDEF_PROTOTYPE_DEFINE: Final[str] = normalize_snippet(r""" + METHODDEF_PROTOTYPE_DEFINE: Final[str] = libclinic.normalize_snippet(r""" #define {methoddef_name} \ {{"{name}", {methoddef_cast}{c_basename}{methoddef_cast_end}, {methoddef_flags}, {c_basename}__doc__}}, """) - METHODDEF_PROTOTYPE_IFNDEF: Final[str] = normalize_snippet(""" + GETTERDEF_PROTOTYPE_DEFINE: Final[str] = libclinic.normalize_snippet(r""" + #if defined({getset_basename}_HAS_DOCSTR) + # define {getset_basename}_DOCSTR {getset_basename}__doc__ + #else + # define {getset_basename}_DOCSTR NULL + #endif + #if defined({getset_name}_GETSETDEF) + # undef {getset_name}_GETSETDEF + # define {getset_name}_GETSETDEF {{"{name}", (getter){getset_basename}_get, (setter){getset_basename}_set, {getset_basename}_DOCSTR}}, + #else + # define {getset_name}_GETSETDEF {{"{name}", (getter){getset_basename}_get, NULL, {getset_basename}_DOCSTR}}, + #endif + """) + SETTERDEF_PROTOTYPE_DEFINE: Final[str] = libclinic.normalize_snippet(r""" + #if defined({getset_name}_HAS_DOCSTR) + # define {getset_basename}_DOCSTR {getset_basename}__doc__ + #else + # define {getset_basename}_DOCSTR NULL + #endif + #if defined({getset_name}_GETSETDEF) + # undef {getset_name}_GETSETDEF + # define {getset_name}_GETSETDEF {{"{name}", (getter){getset_basename}_get, (setter){getset_basename}_set, {getset_basename}_DOCSTR}}, + #else + # define {getset_name}_GETSETDEF {{"{name}", NULL, (setter){getset_basename}_set, NULL}}, + #endif + """) + METHODDEF_PROTOTYPE_IFNDEF: Final[str] = libclinic.normalize_snippet(""" #ifndef {methoddef_name} #define {methoddef_name} #endif /* !defined({methoddef_name}) */ """) + COMPILER_DEPRECATION_WARNING_PROTOTYPE: Final[str] = r""" + // Emit compiler warnings when we get to Python {major}.{minor}. + #if PY_VERSION_HEX >= 0x{major:02x}{minor:02x}00C0 + # error {message} + #elif PY_VERSION_HEX >= 0x{major:02x}{minor:02x}00A0 + # ifdef _MSC_VER + # pragma message ({message}) + # else + # warning {message} + # endif + #endif + """ + DEPRECATION_WARNING_PROTOTYPE: Final[str] = r""" + if ({condition}) {{{{{errcheck} + if (PyErr_WarnEx(PyExc_DeprecationWarning, + {message}, 1)) + {{{{ + goto exit; + }}}} + }}}} + """ def __init__(self, filename: str) -> None: super().__init__(filename) - self.cpp = cpp.Monitor(filename) - self.cpp.fail = fail # type: ignore[method-assign] + self.cpp = libclinic.cpp.Monitor(filename) def parse_line(self, line: str) -> None: self.cpp.writeline(line) @@ -850,25 +666,162 @@ def render( function = o return self.render_function(clinic, function) - def docstring_for_c_string( + def compiler_deprecated_warning( + self, + func: Function, + parameters: list[Parameter], + ) -> str | None: + minversion: VersionTuple | None = None + for p in parameters: + for version in p.deprecated_positional, p.deprecated_keyword: + if version and (not minversion or minversion > version): + minversion = version + if not minversion: + return None + + # Format the preprocessor warning and error messages. + assert isinstance(self.cpp.filename, str) + message = f"Update the clinic input of {func.full_name!r}." + code = self.COMPILER_DEPRECATION_WARNING_PROTOTYPE.format( + major=minversion[0], + minor=minversion[1], + message=libclinic.c_repr(message), + ) + return libclinic.normalize_snippet(code) + + def deprecate_positional_use( + self, + func: Function, + params: dict[int, Parameter], + ) -> str: + assert len(params) > 0 + first_pos = next(iter(params)) + last_pos = next(reversed(params)) + + # Format the deprecation message. + if len(params) == 1: + condition = f"nargs == {first_pos+1}" + amount = f"{first_pos+1} " if first_pos else "" + pl = "s" + else: + condition = f"nargs > {first_pos} && nargs <= {last_pos+1}" + amount = f"more than {first_pos} " if first_pos else "" + pl = "s" if first_pos != 1 else "" + message = ( + f"Passing {amount}positional argument{pl} to " + f"{func.fulldisplayname}() is deprecated." + ) + + for (major, minor), group in itertools.groupby( + params.values(), key=attrgetter("deprecated_positional") + ): + names = [repr(p.name) for p in group] + pstr = libclinic.pprint_words(names) + if len(names) == 1: + message += ( + f" Parameter {pstr} will become a keyword-only parameter " + f"in Python {major}.{minor}." + ) + else: + message += ( + f" Parameters {pstr} will become keyword-only parameters " + f"in Python {major}.{minor}." + ) + + # Append deprecation warning to docstring. + docstring = textwrap.fill(f"Note: {message}") + func.docstring += f"\n\n{docstring}\n" + # Format and return the code block. + code = self.DEPRECATION_WARNING_PROTOTYPE.format( + condition=condition, + errcheck="", + message=libclinic.wrapped_c_string_literal(message, width=64, + subsequent_indent=20), + ) + return libclinic.normalize_snippet(code, indent=4) + + def deprecate_keyword_use( self, - f: Function + func: Function, + params: dict[int, Parameter], + argname_fmt: str | None, + *, + fastcall: bool, + limited_capi: bool, + clinic: Clinic, ) -> str: - text, add, output = _text_accumulator() - # turn docstring into a properly quoted C string - for line in f.docstring.split('\n'): - add('"') - add(quoted_for_c_string(line)) - add('\\n"\n') - - if text[-2] == sig_end_marker: - # If we only have a signature, add the blank line that the - # __text_signature__ getter expects to be there. - add('"\\n"') + assert len(params) > 0 + last_param = next(reversed(params.values())) + + # Format the deprecation message. + containscheck = "" + conditions = [] + for i, p in params.items(): + if p.is_optional(): + if argname_fmt: + conditions.append(f"nargs < {i+1} && {argname_fmt % i}") + elif fastcall: + conditions.append(f"nargs < {i+1} && PySequence_Contains(kwnames, &_Py_ID({p.name}))") + containscheck = "PySequence_Contains" + clinic.add_include('pycore_runtime.h', '_Py_ID()') + else: + conditions.append(f"nargs < {i+1} && PyDict_Contains(kwargs, &_Py_ID({p.name}))") + containscheck = "PyDict_Contains" + clinic.add_include('pycore_runtime.h', '_Py_ID()') + else: + conditions = [f"nargs < {i+1}"] + condition = ") || (".join(conditions) + if len(conditions) > 1: + condition = f"(({condition}))" + if last_param.is_optional(): + if fastcall: + if limited_capi: + condition = f"kwnames && PyTuple_Size(kwnames) && {condition}" + else: + condition = f"kwnames && PyTuple_GET_SIZE(kwnames) && {condition}" + else: + if limited_capi: + condition = f"kwargs && PyDict_Size(kwargs) && {condition}" + else: + condition = f"kwargs && PyDict_GET_SIZE(kwargs) && {condition}" + names = [repr(p.name) for p in params.values()] + pstr = libclinic.pprint_words(names) + pl = 's' if len(params) != 1 else '' + message = ( + f"Passing keyword argument{pl} {pstr} to " + f"{func.fulldisplayname}() is deprecated." + ) + + for (major, minor), group in itertools.groupby( + params.values(), key=attrgetter("deprecated_keyword") + ): + names = [repr(p.name) for p in group] + pstr = libclinic.pprint_words(names) + pl = 's' if len(names) != 1 else '' + message += ( + f" Parameter{pl} {pstr} will become positional-only " + f"in Python {major}.{minor}." + ) + + if containscheck: + errcheck = f""" + if (PyErr_Occurred()) {{{{ // {containscheck}() above can fail + goto exit; + }}}}""" else: - text.pop() - add('"') - return ''.join(text) + errcheck = "" + if argname_fmt: + # Append deprecation warning to docstring. + docstring = textwrap.fill(f"Note: {message}") + func.docstring += f"\n\n{docstring}\n" + # Format and return the code block. + code = self.DEPRECATION_WARNING_PROTOTYPE.format( + condition=condition, + errcheck=errcheck, + message=libclinic.wrapped_c_string_literal(message, width=64, + subsequent_indent=20), + ) + return libclinic.normalize_snippet(code, indent=4) def output_templates( self, @@ -885,11 +838,20 @@ def output_templates( del parameters[0] converters = [p.converter for p in parameters] + # Copy includes from parameters to Clinic + for converter in converters: + include = converter.include + if include: + clinic.add_include(include.filename, include.reason, + condition=include.condition) + if f.critical_section: + clinic.add_include('pycore_critical_section.h', 'Py_BEGIN_CRITICAL_SECTION()') has_option_groups = parameters and (parameters[0].group or parameters[-1].group) - default_return_converter = f.return_converter.type == 'PyObject *' + simple_return = (f.return_converter.type == 'PyObject *' + and not f.critical_section) new_or_init = f.kind.new_or_init - vararg: int | str = NO_VARARG + vararg: int | str = self.NO_VARARG pos_only = min_pos = max_pos = min_kw_only = pseudo_args = 0 for i, p in enumerate(parameters, 1): if p.is_keyword_only(): @@ -897,12 +859,12 @@ def output_templates( if not p.is_optional(): min_kw_only = i - max_pos elif p.is_vararg(): - if vararg != NO_VARARG: + if vararg != self.NO_VARARG: fail("Too many var args") pseudo_args += 1 vararg = i - 1 else: - if vararg == NO_VARARG: + if vararg == self.NO_VARARG: max_pos = i if p.is_positional_only(): pos_only = i @@ -932,6 +894,19 @@ def output_templates( methoddef_define = self.METHODDEF_PROTOTYPE_DEFINE if new_or_init and not f.docstring: docstring_prototype = docstring_definition = '' + elif f.kind is GETTER: + methoddef_define = self.GETTERDEF_PROTOTYPE_DEFINE + if f.docstring: + docstring_prototype = '' + docstring_definition = self.GETSET_DOCSTRING_PROTOTYPE_STRVAR + else: + docstring_prototype = docstring_definition = '' + elif f.kind is SETTER: + if f.docstring: + fail("docstrings are only supported for @getter, not @setter") + return_value_declaration = "int {return_value};" + methoddef_define = self.SETTERDEF_PROTOTYPE_DEFINE + docstring_prototype = docstring_definition = '' else: docstring_prototype = self.DOCSTRING_PROTOTYPE_VAR docstring_definition = self.DOCSTRING_PROTOTYPE_STRVAR @@ -947,20 +922,22 @@ def parser_body( declarations: str = '' ) -> str: nonlocal parser_body_fields - add, output = text_accumulator() - add(prototype) + lines = [] + lines.append(prototype) parser_body_fields = fields - preamble = normalize_snippet(""" + preamble = libclinic.normalize_snippet(""" {{ {return_value_declaration} {parser_declarations} {declarations} {initializers} """) + "\n" - finale = normalize_snippet(""" + finale = libclinic.normalize_snippet(""" {modifications} + {lock} {return_value} = {c_basename}_impl({impl_arguments}); + {unlock} {return_conversion} {post_parsing} @@ -970,33 +947,52 @@ def parser_body( }} """) for field in preamble, *fields, finale: - add('\n') - add(field) - return linear_format(output(), parser_declarations=declarations) + lines.append(field) + return linear_format("\n".join(lines), parser_declarations=declarations) + + fastcall = not new_or_init + limited_capi = clinic.limited_capi + if limited_capi and (pseudo_args or + (any(p.is_optional() for p in parameters) and + any(p.is_keyword_only() and not p.is_optional() for p in parameters)) or + any(c.broken_limited_capi for c in converters)): + warn(f"Function {f.full_name} cannot use limited C API") + limited_capi = False parsearg: str | None + if f.kind in {GETTER, SETTER} and parameters: + fail(f"@{f.kind.name.lower()} method cannot define parameters") + if not parameters: parser_code: list[str] | None - if not requires_defining_class: + if f.kind is GETTER: + flags = "" # This should end up unused + parser_prototype = self.PARSER_PROTOTYPE_GETTER + parser_code = [] + elif f.kind is SETTER: + flags = "" + parser_prototype = self.PARSER_PROTOTYPE_SETTER + parser_code = [] + elif not requires_defining_class: # no parameters, METH_NOARGS flags = "METH_NOARGS" parser_prototype = self.PARSER_PROTOTYPE_NOARGS parser_code = [] else: - assert not new_or_init + assert fastcall flags = "METH_METHOD|METH_FASTCALL|METH_KEYWORDS" parser_prototype = self.PARSER_PROTOTYPE_DEF_CLASS - return_error = ('return NULL;' if default_return_converter + return_error = ('return NULL;' if simple_return else 'goto exit;') - parser_code = [normalize_snippet(""" + parser_code = [libclinic.normalize_snippet(""" if (nargs) {{ PyErr_SetString(PyExc_TypeError, "{name}() takes no arguments"); %s }} """ % return_error, indent=4)] - if default_return_converter: + if simple_return: parser_definition = '\n'.join([ parser_prototype, '{{', @@ -1013,7 +1009,7 @@ def parser_body( converters[0].format_unit == 'O'): meth_o_prototype = self.METH_O_PROTOTYPE - if default_return_converter: + if simple_return: # maps perfectly to METH_O, doesn't need a return converter. # so we skip making a parse function # and call directly into the impl function. @@ -1029,13 +1025,13 @@ def parser_body( argname = 'arg' if parameters[0].name == argname: argname += '_' - parser_prototype = normalize_snippet(""" + parser_prototype = libclinic.normalize_snippet(""" static PyObject * {c_basename}({self_type}{self_name}, PyObject *%s) """ % argname) displayname = parameters[0].get_displayname(0) - parsearg = converters[0].parse_arg(argname, displayname) + parsearg = converters[0].parse_arg(argname, displayname, limited_capi=limited_capi) if parsearg is None: parsearg = """ if (!PyArg_Parse(%s, "{format_units}:{name}", {parse_arguments})) {{ @@ -1043,7 +1039,7 @@ def parser_body( }} """ % argname parser_definition = parser_body(parser_prototype, - normalize_snippet(parsearg, indent=4)) + libclinic.normalize_snippet(parsearg, indent=4)) elif has_option_groups: # positional parameters with option groups @@ -1055,7 +1051,7 @@ def parser_body( parser_definition = parser_body(parser_prototype, ' {option_group_parsing}') elif not requires_defining_class and pos_only == len(parameters) - pseudo_args: - if not new_or_init: + if fastcall: # positional-only, but no option groups # we only need one call to _PyArg_ParseStack @@ -1069,26 +1065,63 @@ def parser_body( flags = "METH_VARARGS" parser_prototype = self.PARSER_PROTOTYPE_VARARGS - nargs = 'PyTuple_GET_SIZE(args)' - argname_fmt = 'PyTuple_GET_ITEM(args, %d)' - + if limited_capi: + nargs = 'PyTuple_Size(args)' + argname_fmt = 'PyTuple_GetItem(args, %d)' + else: + nargs = 'PyTuple_GET_SIZE(args)' + argname_fmt = 'PyTuple_GET_ITEM(args, %d)' left_args = f"{nargs} - {max_pos}" - max_args = NO_VARARG if (vararg != NO_VARARG) else max_pos - parser_code = [normalize_snippet(""" - if (!_PyArg_CheckPositional("{name}", %s, %d, %s)) {{ - goto exit; - }} - """ % (nargs, min_pos, max_args), indent=4)] + max_args = self.NO_VARARG if (vararg != self.NO_VARARG) else max_pos + if limited_capi: + parser_code = [] + if nargs != 'nargs': + nargs_def = f'Py_ssize_t nargs = {nargs};' + parser_code.append(libclinic.normalize_snippet(nargs_def, indent=4)) + nargs = 'nargs' + if min_pos == max_args: + pl = '' if min_pos == 1 else 's' + parser_code.append(libclinic.normalize_snippet(f""" + if ({nargs} != {min_pos}) {{{{ + PyErr_Format(PyExc_TypeError, "{{name}} expected {min_pos} argument{pl}, got %zd", {nargs}); + goto exit; + }}}} + """, + indent=4)) + else: + if min_pos: + pl = '' if min_pos == 1 else 's' + parser_code.append(libclinic.normalize_snippet(f""" + if ({nargs} < {min_pos}) {{{{ + PyErr_Format(PyExc_TypeError, "{{name}} expected at least {min_pos} argument{pl}, got %zd", {nargs}); + goto exit; + }}}} + """, + indent=4)) + if max_args != self.NO_VARARG: + pl = '' if max_args == 1 else 's' + parser_code.append(libclinic.normalize_snippet(f""" + if ({nargs} > {max_args}) {{{{ + PyErr_Format(PyExc_TypeError, "{{name}} expected at most {max_args} argument{pl}, got %zd", {nargs}); + goto exit; + }}}} + """, + indent=4)) + else: + clinic.add_include('pycore_modsupport.h', + '_PyArg_CheckPositional()') + parser_code = [libclinic.normalize_snippet(f""" + if (!_PyArg_CheckPositional("{{name}}", {nargs}, {min_pos}, {max_args})) {{{{ + goto exit; + }}}} + """, indent=4)] has_optional = False for i, p in enumerate(parameters): - displayname = p.get_displayname(i+1) - argname = argname_fmt % i - if p.is_vararg(): - if not new_or_init: - parser_code.append(normalize_snippet(""" + if fastcall: + parser_code.append(libclinic.normalize_snippet(""" %s = PyTuple_New(%s); if (!%s) {{ goto exit; @@ -1105,7 +1138,7 @@ def parser_body( max_pos ), indent=4)) else: - parser_code.append(normalize_snippet(""" + parser_code.append(libclinic.normalize_snippet(""" %s = PyTuple_GetSlice(%d, -1); """ % ( p.converter.parser_name, @@ -1113,32 +1146,40 @@ def parser_body( ), indent=4)) continue - parsearg = p.converter.parse_arg(argname, displayname) + displayname = p.get_displayname(i+1) + argname = argname_fmt % i + parsearg = p.converter.parse_arg(argname, displayname, limited_capi=limited_capi) if parsearg is None: parser_code = None break if has_optional or p.is_optional(): has_optional = True - parser_code.append(normalize_snippet(""" + parser_code.append(libclinic.normalize_snippet(""" if (%s < %d) {{ goto skip_optional; }} """, indent=4) % (nargs, i + 1)) - parser_code.append(normalize_snippet(parsearg, indent=4)) + parser_code.append(libclinic.normalize_snippet(parsearg, indent=4)) if parser_code is not None: if has_optional: parser_code.append("skip_optional:") else: - if not new_or_init: - parser_code = [normalize_snippet(""" + if limited_capi: + fastcall = False + if fastcall: + clinic.add_include('pycore_modsupport.h', + '_PyArg_ParseStack()') + parser_code = [libclinic.normalize_snippet(""" if (!_PyArg_ParseStack(args, nargs, "{format_units}:{name}", {parse_arguments})) {{ goto exit; }} """, indent=4)] else: - parser_code = [normalize_snippet(""" + flags = "METH_VARARGS" + parser_prototype = self.PARSER_PROTOTYPE_VARARGS + parser_code = [libclinic.normalize_snippet(""" if (!PyArg_ParseTuple(args, "{format_units}:{name}", {parse_arguments})) {{ goto exit; @@ -1147,135 +1188,201 @@ def parser_body( parser_definition = parser_body(parser_prototype, *parser_code) else: - has_optional_kw = (max(pos_only, min_pos) + min_kw_only < len(converters) - int(vararg != NO_VARARG)) - if vararg == NO_VARARG: - args_declaration = "_PyArg_UnpackKeywords", "%s, %s, %s" % ( - min_pos, - max_pos, - min_kw_only - ) - nargs = "nargs" - else: - args_declaration = "_PyArg_UnpackKeywordsWithVararg", "%s, %s, %s, %s" % ( - min_pos, - max_pos, - min_kw_only, - vararg - ) - nargs = f"Py_MIN(nargs, {max_pos})" if max_pos else "0" - if not new_or_init: - flags = "METH_FASTCALL|METH_KEYWORDS" - parser_prototype = self.PARSER_PROTOTYPE_FASTCALL_KEYWORDS - argname_fmt = 'args[%d]' - declarations = declare_parser(f) - declarations += "\nPyObject *argsbuf[%s];" % len(converters) - if has_optional_kw: - declarations += "\nPy_ssize_t noptargs = %s + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - %d;" % (nargs, min_pos + min_kw_only) - parser_code = [normalize_snippet(""" - args = %s(args, nargs, NULL, kwnames, &_parser, %s, argsbuf); - if (!args) {{ - goto exit; - }} - """ % args_declaration, indent=4)] + deprecated_positionals: dict[int, Parameter] = {} + deprecated_keywords: dict[int, Parameter] = {} + for i, p in enumerate(parameters): + if p.deprecated_positional: + deprecated_positionals[i] = p + if p.deprecated_keyword: + deprecated_keywords[i] = p + + has_optional_kw = ( + max(pos_only, min_pos) + min_kw_only + < len(converters) - int(vararg != self.NO_VARARG) + ) + + if limited_capi: + parser_code = None + fastcall = False else: - # positional-or-keyword arguments - flags = "METH_VARARGS|METH_KEYWORDS" - parser_prototype = self.PARSER_PROTOTYPE_KEYWORD - argname_fmt = 'fastargs[%d]' - declarations = declare_parser(f) - declarations += "\nPyObject *argsbuf[%s];" % len(converters) - declarations += "\nPyObject * const *fastargs;" - declarations += "\nPy_ssize_t nargs = PyTuple_GET_SIZE(args);" - if has_optional_kw: - declarations += "\nPy_ssize_t noptargs = %s + (kwargs ? PyDict_GET_SIZE(kwargs) : 0) - %d;" % (nargs, min_pos + min_kw_only) - parser_code = [normalize_snippet(""" - fastargs = %s(_PyTuple_CAST(args)->ob_item, nargs, kwargs, NULL, &_parser, %s, argsbuf); - if (!fastargs) {{ - goto exit; - }} - """ % args_declaration, indent=4)] + if vararg == self.NO_VARARG: + clinic.add_include('pycore_modsupport.h', + '_PyArg_UnpackKeywords()') + args_declaration = "_PyArg_UnpackKeywords", "%s, %s, %s" % ( + min_pos, + max_pos, + min_kw_only + ) + nargs = "nargs" + else: + clinic.add_include('pycore_modsupport.h', + '_PyArg_UnpackKeywordsWithVararg()') + args_declaration = "_PyArg_UnpackKeywordsWithVararg", "%s, %s, %s, %s" % ( + min_pos, + max_pos, + min_kw_only, + vararg + ) + nargs = f"Py_MIN(nargs, {max_pos})" if max_pos else "0" + + if fastcall: + flags = "METH_FASTCALL|METH_KEYWORDS" + parser_prototype = self.PARSER_PROTOTYPE_FASTCALL_KEYWORDS + argname_fmt = 'args[%d]' + declarations = declare_parser(f, clinic=clinic, + limited_capi=clinic.limited_capi) + declarations += "\nPyObject *argsbuf[%s];" % len(converters) + if has_optional_kw: + declarations += "\nPy_ssize_t noptargs = %s + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - %d;" % (nargs, min_pos + min_kw_only) + parser_code = [libclinic.normalize_snippet(""" + args = %s(args, nargs, NULL, kwnames, &_parser, %s, argsbuf); + if (!args) {{ + goto exit; + }} + """ % args_declaration, indent=4)] + else: + # positional-or-keyword arguments + flags = "METH_VARARGS|METH_KEYWORDS" + parser_prototype = self.PARSER_PROTOTYPE_KEYWORD + argname_fmt = 'fastargs[%d]' + declarations = declare_parser(f, clinic=clinic, + limited_capi=clinic.limited_capi) + declarations += "\nPyObject *argsbuf[%s];" % len(converters) + declarations += "\nPyObject * const *fastargs;" + declarations += "\nPy_ssize_t nargs = PyTuple_GET_SIZE(args);" + if has_optional_kw: + declarations += "\nPy_ssize_t noptargs = %s + (kwargs ? PyDict_GET_SIZE(kwargs) : 0) - %d;" % (nargs, min_pos + min_kw_only) + parser_code = [libclinic.normalize_snippet(""" + fastargs = %s(_PyTuple_CAST(args)->ob_item, nargs, kwargs, NULL, &_parser, %s, argsbuf); + if (!fastargs) {{ + goto exit; + }} + """ % args_declaration, indent=4)] if requires_defining_class: flags = 'METH_METHOD|' + flags parser_prototype = self.PARSER_PROTOTYPE_DEF_CLASS - add_label: str | None = None - for i, p in enumerate(parameters): - if isinstance(p.converter, defining_class_converter): - raise ValueError("defining_class should be the first " - "parameter (after self)") - displayname = p.get_displayname(i+1) - parsearg = p.converter.parse_arg(argname_fmt % i, displayname) - if parsearg is None: - parser_code = None - break - if add_label and (i == pos_only or i == max_pos): - parser_code.append("%s:" % add_label) - add_label = None - if not p.is_optional(): - parser_code.append(normalize_snippet(parsearg, indent=4)) - elif i < pos_only: - add_label = 'skip_optional_posonly' - parser_code.append(normalize_snippet(""" - if (nargs < %d) {{ - goto %s; - }} - """ % (i + 1, add_label), indent=4)) - if has_optional_kw: - parser_code.append(normalize_snippet(""" - noptargs--; - """, indent=4)) - parser_code.append(normalize_snippet(parsearg, indent=4)) - else: - if i < max_pos: - label = 'skip_optional_pos' - first_opt = max(min_pos, pos_only) - else: - label = 'skip_optional_kwonly' - first_opt = max_pos + min_kw_only - if vararg != NO_VARARG: - first_opt += 1 - if i == first_opt: - add_label = label - parser_code.append(normalize_snippet(""" - if (!noptargs) {{ + if parser_code is not None: + if deprecated_keywords: + code = self.deprecate_keyword_use(f, deprecated_keywords, argname_fmt, + clinic=clinic, + fastcall=fastcall, + limited_capi=limited_capi) + parser_code.append(code) + + add_label: str | None = None + for i, p in enumerate(parameters): + if isinstance(p.converter, defining_class_converter): + raise ValueError("defining_class should be the first " + "parameter (after self)") + displayname = p.get_displayname(i+1) + parsearg = p.converter.parse_arg(argname_fmt % i, displayname, limited_capi=limited_capi) + if parsearg is None: + parser_code = None + break + if add_label and (i == pos_only or i == max_pos): + parser_code.append("%s:" % add_label) + add_label = None + if not p.is_optional(): + parser_code.append(libclinic.normalize_snippet(parsearg, indent=4)) + elif i < pos_only: + add_label = 'skip_optional_posonly' + parser_code.append(libclinic.normalize_snippet(""" + if (nargs < %d) {{ goto %s; }} - """ % add_label, indent=4)) - if i + 1 == len(parameters): - parser_code.append(normalize_snippet(parsearg, indent=4)) + """ % (i + 1, add_label), indent=4)) + if has_optional_kw: + parser_code.append(libclinic.normalize_snippet(""" + noptargs--; + """, indent=4)) + parser_code.append(libclinic.normalize_snippet(parsearg, indent=4)) else: - add_label = label - parser_code.append(normalize_snippet(""" - if (%s) {{ - """ % (argname_fmt % i), indent=4)) - parser_code.append(normalize_snippet(parsearg, indent=8)) - parser_code.append(normalize_snippet(""" - if (!--noptargs) {{ + if i < max_pos: + label = 'skip_optional_pos' + first_opt = max(min_pos, pos_only) + else: + label = 'skip_optional_kwonly' + first_opt = max_pos + min_kw_only + if vararg != self.NO_VARARG: + first_opt += 1 + if i == first_opt: + add_label = label + parser_code.append(libclinic.normalize_snippet(""" + if (!noptargs) {{ goto %s; }} - }} - """ % add_label, indent=4)) + """ % add_label, indent=4)) + if i + 1 == len(parameters): + parser_code.append(libclinic.normalize_snippet(parsearg, indent=4)) + else: + add_label = label + parser_code.append(libclinic.normalize_snippet(""" + if (%s) {{ + """ % (argname_fmt % i), indent=4)) + parser_code.append(libclinic.normalize_snippet(parsearg, indent=8)) + parser_code.append(libclinic.normalize_snippet(""" + if (!--noptargs) {{ + goto %s; + }} + }} + """ % add_label, indent=4)) if parser_code is not None: if add_label: parser_code.append("%s:" % add_label) else: - declarations = declare_parser(f, hasformat=True) - if not new_or_init: - parser_code = [normalize_snippet(""" + declarations = declare_parser(f, clinic=clinic, + hasformat=True, + limited_capi=limited_capi) + if limited_capi: + # positional-or-keyword arguments + assert not fastcall + flags = "METH_VARARGS|METH_KEYWORDS" + parser_prototype = self.PARSER_PROTOTYPE_KEYWORD + parser_code = [libclinic.normalize_snippet(""" + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "{format_units}:{name}", _keywords, + {parse_arguments})) + goto exit; + """, indent=4)] + declarations = "static char *_keywords[] = {{{keywords_c} NULL}};" + if deprecated_positionals or deprecated_keywords: + declarations += "\nPy_ssize_t nargs = PyTuple_Size(args);" + + elif fastcall: + clinic.add_include('pycore_modsupport.h', + '_PyArg_ParseStackAndKeywords()') + parser_code = [libclinic.normalize_snippet(""" if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser{parse_arguments_comma} {parse_arguments})) {{ goto exit; }} """, indent=4)] else: - parser_code = [normalize_snippet(""" + clinic.add_include('pycore_modsupport.h', + '_PyArg_ParseTupleAndKeywordsFast()') + parser_code = [libclinic.normalize_snippet(""" if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser, {parse_arguments})) {{ goto exit; }} """, indent=4)] + if deprecated_positionals or deprecated_keywords: + declarations += "\nPy_ssize_t nargs = PyTuple_GET_SIZE(args);" + if deprecated_keywords: + code = self.deprecate_keyword_use(f, deprecated_keywords, None, + clinic=clinic, + fastcall=fastcall, + limited_capi=limited_capi) + parser_code.append(code) + + if deprecated_positionals: + code = self.deprecate_positional_use(f, deprecated_positionals) + # Insert the deprecation code before parameter parsing. + parser_code.insert(0, code) + + assert parser_prototype is not None parser_definition = parser_body(parser_prototype, *parser_code, declarations=declarations) @@ -1300,13 +1407,17 @@ def parser_body( if not parses_keywords: declarations = '{base_type_ptr}' - fields.insert(0, normalize_snippet(""" + clinic.add_include('pycore_modsupport.h', + '_PyArg_NoKeywords()') + fields.insert(0, libclinic.normalize_snippet(""" if ({self_type_check}!_PyArg_NoKeywords("{name}", kwargs)) {{ goto exit; }} """, indent=4)) if not parses_positional: - fields.insert(0, normalize_snippet(""" + clinic.add_include('pycore_modsupport.h', + '_PyArg_NoPositional()') + fields.insert(0, libclinic.normalize_snippet(""" if ({self_type_check}!_PyArg_NoPositional("{name}", args)) {{ goto exit; }} @@ -1316,9 +1427,13 @@ def parser_body( declarations=declarations) + methoddef_cast_end = "" if flags in ('METH_NOARGS', 'METH_O', 'METH_VARARGS'): methoddef_cast = "(PyCFunction)" - methoddef_cast_end = "" + elif f.kind is GETTER: + methoddef_cast = "" # This should end up unused + elif limited_capi: + methoddef_cast = "(PyCFunction)(void(*)(void))" else: methoddef_cast = "_PyCFunction_CAST(" methoddef_cast_end = ")" @@ -1356,6 +1471,10 @@ def parser_body( parser_definition = parser_definition.replace("{return_value_declaration}", return_value_declaration) + compiler_warning = self.compiler_deprecated_warning(f, parameters) + if compiler_warning: + parser_definition = compiler_warning + "\n\n" + parser_definition + d = { "docstring_prototype" : docstring_prototype, "docstring_definition" : docstring_definition, @@ -1387,7 +1506,8 @@ def group_to_variable_name(group: int) -> str: def render_option_group_parsing( self, f: Function, - template_dict: TemplateDict + template_dict: TemplateDict, + limited_capi: bool, ) -> None: # positional only, grouped, optional arguments! # can be optional on the left or right. @@ -1407,7 +1527,7 @@ def render_option_group_parsing( # Clinic prefers groups on the left. So in the above example, # five arguments would map to B+C, not C+D. - add, output = text_accumulator() + out = [] parameters = list(f.parameters.values()) if isinstance(parameters[0].converter, self_converter): del parameters[0] @@ -1435,14 +1555,18 @@ def render_option_group_parsing( count_min = sys.maxsize count_max = -1 - add("switch (PyTuple_GET_SIZE(args)) {\n") + if limited_capi: + nargs = 'PyTuple_Size(args)' + else: + nargs = 'PyTuple_GET_SIZE(args)' + out.append(f"switch ({nargs}) {{\n") for subset in permute_optional_groups(left, required, right): count = len(subset) count_min = min(count_min, count) count_max = max(count_max, count) if count == 0: - add(""" case 0: + out.append(""" case 0: break; """) continue @@ -1474,14 +1598,15 @@ def render_option_group_parsing( """ s = linear_format(s, group_booleans=lines) s = s.format_map(d) - add(s) + out.append(s) - add(" default:\n") + out.append(" default:\n") s = ' PyErr_SetString(PyExc_TypeError, "{} requires {} to {} arguments");\n' - add(s.format(f.full_name, count_min, count_max)) - add(' goto exit;\n') - add("}") - template_dict['option_group_parsing'] = format_escape(output()) + out.append(s.format(f.full_name, count_min, count_max)) + out.append(' goto exit;\n') + out.append("}") + + template_dict['option_group_parsing'] = libclinic.format_escape("".join(out)) def render_function( self, @@ -1491,7 +1616,6 @@ def render_function( if f is None or clinic is None: return "" - add, output = text_accumulator() data = CRenderData() assert f.parameters, "We should always have a 'self' at this point!" @@ -1504,10 +1628,23 @@ def render_function( selfless = parameters[1:] assert isinstance(f_self.converter, self_converter), "No self parameter in " + repr(f.full_name) + "!" + if f.critical_section: + match len(f.target_critical_section): + case 0: + lock = 'Py_BEGIN_CRITICAL_SECTION({self_name});' + unlock = 'Py_END_CRITICAL_SECTION();' + case 1: + lock = 'Py_BEGIN_CRITICAL_SECTION({target_critical_section});' + unlock = 'Py_END_CRITICAL_SECTION();' + case _: + lock = 'Py_BEGIN_CRITICAL_SECTION2({target_critical_section});' + unlock = 'Py_END_CRITICAL_SECTION2();' + data.lock.append(lock) + data.unlock.append(unlock) + last_group = 0 first_optional = len(selfless) positional = selfless and selfless[-1].is_positional_only() - new_or_init = f.kind.new_or_init has_option_groups = False # offset i by -1 because first_optional needs to ignore self @@ -1551,37 +1688,35 @@ def render_function( full_name = f.full_name template_dict = {'full_name': full_name} - - if new_or_init: - assert isinstance(f.cls, Class) - name = f.cls.name - else: - name = f.name - - template_dict['name'] = name - - if f.c_basename: - c_basename = f.c_basename + template_dict['name'] = f.displayname + if f.kind in {GETTER, SETTER}: + template_dict['getset_name'] = f.c_basename.upper() + template_dict['getset_basename'] = f.c_basename + if f.kind is GETTER: + template_dict['c_basename'] = f.c_basename + "_get" + elif f.kind is SETTER: + template_dict['c_basename'] = f.c_basename + "_set" + # Implicitly add the setter value parameter. + data.impl_parameters.append("PyObject *value") + data.impl_arguments.append("value") else: - fields = full_name.split(".") - if fields[-1] == '__new__': - fields.pop() - c_basename = "_".join(fields) - - template_dict['c_basename'] = c_basename - - template_dict['methoddef_name'] = c_basename.upper() + "_METHODDEF" - - template_dict['docstring'] = self.docstring_for_c_string(f) + template_dict['methoddef_name'] = f.c_basename.upper() + "_METHODDEF" + template_dict['c_basename'] = f.c_basename + template_dict['docstring'] = libclinic.docstring_for_c_string(f.docstring) template_dict['self_name'] = template_dict['self_type'] = template_dict['self_type_check'] = '' + template_dict['target_critical_section'] = ', '.join(f.target_critical_section) for converter in converters: converter.set_template_dict(template_dict) f.return_converter.render(f, data) - template_dict['impl_return_type'] = f.return_converter.type + if f.kind is SETTER: + # All setters return an int. + template_dict['impl_return_type'] = 'int' + else: + template_dict['impl_return_type'] = f.return_converter.type - template_dict['declarations'] = format_escape("\n".join(data.declarations)) + template_dict['declarations'] = libclinic.format_escape("\n".join(data.declarations)) template_dict['initializers'] = "\n\n".join(data.initializers) template_dict['modifications'] = '\n\n'.join(data.modifications) template_dict['keywords_c'] = ' '.join('"' + k + '",' @@ -1597,10 +1732,14 @@ def render_function( template_dict['parse_arguments_comma'] = ''; template_dict['impl_parameters'] = ", ".join(data.impl_parameters) template_dict['impl_arguments'] = ", ".join(data.impl_arguments) - template_dict['return_conversion'] = format_escape("".join(data.return_conversion).rstrip()) - template_dict['post_parsing'] = format_escape("".join(data.post_parsing).rstrip()) - template_dict['cleanup'] = format_escape("".join(data.cleanup)) + + template_dict['return_conversion'] = libclinic.format_escape("".join(data.return_conversion).rstrip()) + template_dict['post_parsing'] = libclinic.format_escape("".join(data.post_parsing).rstrip()) + template_dict['cleanup'] = libclinic.format_escape("".join(data.cleanup)) + template_dict['return_value'] = data.return_value + template_dict['lock'] = "\n".join(data.lock) + template_dict['unlock'] = "\n".join(data.unlock) # used by unpack tuple code generator unpack_min = first_optional @@ -1609,7 +1748,8 @@ def render_function( template_dict['unpack_max'] = str(unpack_max) if has_option_groups: - self.render_option_group_parsing(f, template_dict) + self.render_option_group_parsing(f, template_dict, + limited_capi=clinic.limited_capi) # buffers, not destination for name, destination in clinic.destination_buffers.items(): @@ -1624,6 +1764,8 @@ def render_function( modifications=template_dict['modifications'], post_parsing=template_dict['post_parsing'], cleanup=template_dict['cleanup'], + lock=template_dict['lock'], + unlock=template_dict['unlock'], ) # Only generate the "exit:" label @@ -1638,12 +1780,12 @@ def render_function( # mild hack: # reflow long impl declarations if name in {"impl_prototype", "impl_definition"}: - s = wrap_declarations(s) + s = libclinic.wrap_declarations(s) if clinic.line_prefix: - s = indent_all_lines(s, clinic.line_prefix) + s = libclinic.indent_all_lines(s, clinic.line_prefix) if clinic.line_suffix: - s = suffix_all_lines(s, clinic.line_suffix) + s = libclinic.suffix_all_lines(s, clinic.line_suffix) destination.append(s) @@ -1803,7 +1945,7 @@ def _line(self, lookahead: bool = False) -> str: return line def parse_verbatim_block(self) -> Block: - add, output = text_accumulator() + lines = [] self.block_start_line_number = self.line_number while self.input: @@ -1812,12 +1954,12 @@ def parse_verbatim_block(self) -> Block: if dsl_name: self.dsl_name = dsl_name break - add(line) + lines.append(line) - return Block(output()) + return Block("".join(lines)) def parse_clinic_block(self, dsl_name: str) -> Block: - input_add, input_output = text_accumulator() + in_lines = [] self.block_start_line_number = self.line_number + 1 stop_line = self.language.stop_line.format(dsl_name=dsl_name) body_prefix = self.language.body_prefix.format(dsl_name=dsl_name) @@ -1845,7 +1987,7 @@ def is_stop_line(line: str) -> bool: line = line.lstrip() assert line.startswith(body_prefix) line = line.removeprefix(body_prefix) - input_add(line) + in_lines.append(line) # consume output and checksum line, if present. if self.last_dsl_name == dsl_name: @@ -1859,7 +2001,7 @@ def is_stop_line(line: str) -> bool: assert checksum_re is not None # scan forward for checksum line - output_add, output_output = text_accumulator() + out_lines = [] arguments = None while self.input: line = self._line(lookahead=True) @@ -1867,12 +2009,12 @@ def is_stop_line(line: str) -> bool: arguments = match.group(1) if match else None if arguments: break - output_add(line) + out_lines.append(line) if self.is_start_line(line): break output: str | None - output = output_output() + output = "".join(out_lines) if arguments: d = {} for field in shlex.split(arguments): @@ -1900,7 +2042,27 @@ def is_stop_line(line: str) -> bool: self.input.extend(reversed(output_lines)) output = None - return Block(input_output(), dsl_name, output=output) + return Block("".join(in_lines), dsl_name, output=output) + + +@dc.dataclass(slots=True, frozen=True) +class Include: + """ + An include like: #include "pycore_long.h" // _Py_ID() + """ + # Example: "pycore_long.h". + filename: str + + # Example: "_Py_ID()". + reason: str + + # None means unconditional include. + # Example: "#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)". + condition: str | None + + def sort_key(self) -> tuple[str, str]: + # order: '#if' comes before 'NO_CONDITION' + return (self.condition or 'NO_CONDITION', self.filename) @dc.dataclass(slots=True) @@ -1908,11 +2070,16 @@ class BlockPrinter: language: Language f: io.StringIO = dc.field(default_factory=io.StringIO) + # '#include "header.h" // reason': column of '//' comment + INCLUDE_COMMENT_COLUMN: Final[int] = 35 + def print_block( self, block: Block, *, - core_includes: bool = False + core_includes: bool = False, + limited_capi: bool, + header_includes: dict[str, Include], ) -> None: input = block.input output = block.output @@ -1941,14 +2108,31 @@ def print_block( write("\n") output = '' - if core_includes: - output += textwrap.dedent(""" - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - # include "pycore_gc.h" // PyGC_Head - # include "pycore_runtime.h" // _Py_ID() - #endif + if core_includes and header_includes: + # Emit optional "#include" directives for C headers + output += '\n' + + current_condition: str | None = None + includes = sorted(header_includes.values(), key=Include.sort_key) + for include in includes: + if include.condition != current_condition: + if current_condition: + output += '#endif\n' + current_condition = include.condition + if include.condition: + output += f'{include.condition}\n' + + if current_condition: + line = f'# include "{include.filename}"' + else: + line = f'#include "{include.filename}"' + if include.reason: + comment = f'// {include.reason}\n' + line = line.ljust(self.INCLUDE_COMMENT_COLUMN - 1) + comment + output += line - """) + if current_condition: + output += '#endif\n' input = ''.join(block.input) output += ''.join(block.output) @@ -1981,26 +2165,26 @@ class BufferSeries: def __init__(self) -> None: self._start = 0 - self._array: list[_TextAccumulator] = [] - self._constructor = _text_accumulator + self._array: list[list[str]] = [] - def __getitem__(self, i: int) -> _TextAccumulator: + def __getitem__(self, i: int) -> list[str]: i -= self._start if i < 0: self._start += i - prefix = [self._constructor() for x in range(-i)] + prefix: list[list[str]] = [[] for x in range(-i)] self._array = prefix + self._array i = 0 while i >= len(self._array): - self._array.append(self._constructor()) + self._array.append([]) return self._array[i] def clear(self) -> None: for ta in self._array: - ta.text.clear() + ta.clear() def dump(self) -> str: - texts = [ta.output() for ta in self._array] + texts = ["".join(ta) for ta in self._array] + self.clear() return "".join(texts) @@ -2063,7 +2247,7 @@ def dump(self) -> str: def write_file(filename: str, new_contents: str) -> None: try: - with open(filename, 'r', encoding="utf-8") as fp: + with open(filename, encoding="utf-8") as fp: old_contents = fp.read() if old_contents == new_contents: @@ -2092,7 +2276,7 @@ def __init__(self, clinic: Clinic) -> None: ... def parse(self, block: Block) -> None: ... -clinic = None +clinic: Clinic | None = None class Clinic: presets_text = """ @@ -2144,6 +2328,7 @@ def __init__( printer: BlockPrinter | None = None, *, filename: str, + limited_capi: bool, verify: bool = True, ) -> None: # maps strings to Parser objects. @@ -2154,10 +2339,13 @@ def __init__( fail("Custom printers are broken right now") self.printer = printer or BlockPrinter(language) self.verify = verify + self.limited_capi = limited_capi self.filename = filename self.modules: ModuleDict = {} self.classes: ClassDict = {} self.functions: list[Function] = [] + # dict: include name => Include instance + self.includes: dict[str, Include] = {} self.line_prefix = self.line_suffix = '' @@ -2182,7 +2370,7 @@ def __init__( 'impl_definition': d('block'), } - DestBufferType = dict[str, _TextAccumulator] + DestBufferType = dict[str, list[str]] DestBufferList = list[DestBufferType] self.destination_buffers_stack: DestBufferList = [] @@ -2216,6 +2404,24 @@ def __init__( global clinic clinic = self + def add_include(self, name: str, reason: str, + *, condition: str | None = None) -> None: + try: + existing = self.includes[name] + except KeyError: + pass + else: + if existing.condition and not condition: + # If the previous include has a condition and the new one is + # unconditional, override the include. + pass + else: + # Already included, do nothing. Only mention a single reason, + # no need to list all of them. + return + + self.includes[name] = Include(name, reason, condition) + def add_destination( self, name: str, @@ -2236,7 +2442,7 @@ def get_destination_buffer( self, name: str, item: int = 0 - ) -> _TextAccumulator: + ) -> list[str]: d = self.get_destination(name) return d.buffers[item] @@ -2251,7 +2457,9 @@ def parse(self, input: str) -> str: self.parsers[dsl_name] = parsers[dsl_name](self) parser = self.parsers[dsl_name] parser.parse(block) - printer.print_block(block) + printer.print_block(block, + limited_capi=self.limited_capi, + header_includes=self.includes) # these are destinations not buffers for name, destination in self.destinations.items(): @@ -2266,7 +2474,9 @@ def parse(self, input: str) -> str: block.input = "dump " + name + "\n" warn("Destination buffer " + repr(name) + " not empty at end of file, emptying.") printer.write("\n") - printer.print_block(block) + printer.print_block(block, + limited_capi=self.limited_capi, + header_includes=self.includes) continue if destination.type == 'file': @@ -2291,14 +2501,17 @@ def parse(self, input: str) -> str: block.input = 'preserve\n' printer_2 = BlockPrinter(self.language) - printer_2.print_block(block, core_includes=True) + printer_2.print_block(block, + core_includes=True, + limited_capi=self.limited_capi, + header_includes=self.includes) write_file(destination.filename, printer_2.f.getvalue()) continue return printer.f.getvalue() def _module_and_class( - self, fields: Iterable[str] + self, fields: Sequence[str] ) -> tuple[Module | Clinic, Class | None]: """ fields should be an iterable of field names. @@ -2307,37 +2520,33 @@ def _module_and_class( this function is only ever used to find the parent of where a new class/module should go. """ - parent: Clinic | Module | Class - child: Module | Class | None - module: Clinic | Module + parent: Clinic | Module | Class = self + module: Clinic | Module = self cls: Class | None = None - so_far: list[str] = [] - parent = module = self - - for field in fields: - so_far.append(field) + for idx, field in enumerate(fields): if not isinstance(parent, Class): - child = parent.modules.get(field) - if child: - parent = module = child + if field in parent.modules: + parent = module = parent.modules[field] continue - if not hasattr(parent, 'classes'): - return module, cls - child = parent.classes.get(field) - if not child: - fullname = ".".join(so_far) + if field in parent.classes: + parent = cls = parent.classes[field] + else: + fullname = ".".join(fields[idx:]) fail(f"Parent class or module {fullname!r} does not exist.") - cls = parent = child return module, cls + def __repr__(self) -> str: + return "" + def parse_file( filename: str, *, + limited_capi: bool, + output: str | None = None, verify: bool = True, - output: str | None = None ) -> None: if not output: output = filename @@ -2359,8 +2568,14 @@ def parse_file( if not find_start_re.search(raw): return + if LIMITED_CAPI_REGEX.search(raw): + limited_capi = True + assert isinstance(language, CLanguage) - clinic = Clinic(language, verify=verify, filename=filename) + clinic = Clinic(language, + verify=verify, + filename=filename, + limited_capi=limited_capi) cooked = clinic.parse(raw) write_file(output, cooked) @@ -2498,6 +2713,8 @@ class FunctionKind(enum.Enum): CLASS_METHOD = enum.auto() METHOD_INIT = enum.auto() METHOD_NEW = enum.auto() + GETTER = enum.auto() + SETTER = enum.auto() @functools.cached_property def new_or_init(self) -> bool: @@ -2513,6 +2730,8 @@ def __repr__(self) -> str: CLASS_METHOD: Final = FunctionKind.CLASS_METHOD METHOD_INIT: Final = FunctionKind.METHOD_INIT METHOD_NEW: Final = FunctionKind.METHOD_NEW +GETTER: Final = FunctionKind.GETTER +SETTER: Final = FunctionKind.SETTER ParamDict = dict[str, "Parameter"] ReturnConverterType = Callable[..., "CReturnConverter"] @@ -2535,7 +2754,7 @@ class Function: name: str module: Module | Clinic cls: Class | None - c_basename: str | None + c_basename: str full_name: str return_converter: CReturnConverter kind: FunctionKind @@ -2547,12 +2766,36 @@ class Function: # functions with optional groups because we can't represent # those accurately with inspect.Signature in 3.4. docstring_only: bool = False + critical_section: bool = False + target_critical_section: list[str] = dc.field(default_factory=list) def __post_init__(self) -> None: self.parent = self.cls or self.module self.self_converter: self_converter | None = None self.__render_parameters__: list[Parameter] | None = None + @functools.cached_property + def displayname(self) -> str: + """Pretty-printable name.""" + if self.kind.new_or_init: + assert isinstance(self.cls, Class) + return self.cls.name + else: + return self.name + + @functools.cached_property + def fulldisplayname(self) -> str: + parent: Class | Module | Clinic | None + if self.kind.new_or_init: + parent = getattr(self.cls, "parent", None) + else: + parent = self.parent + name = self.displayname + while isinstance(parent, (Module, Class)): + name = f"{parent.name}.{name}" + parent = parent.parent + return name + @property def render_parameters(self) -> list[Parameter]: if not self.__render_parameters__: @@ -2575,7 +2818,8 @@ def methoddef_flags(self) -> str | None: case FunctionKind.STATIC_METHOD: flags.append('METH_STATIC') case _ as kind: - assert kind is FunctionKind.CALLABLE, f"unknown kind: {kind!r}" + acceptable_kinds = {FunctionKind.CALLABLE, FunctionKind.GETTER, FunctionKind.SETTER} + assert kind in acceptable_kinds, f"unknown kind: {kind!r}" if self.coexist: flags.append('METH_COEXIST') return '|'.join(flags) @@ -2592,6 +2836,9 @@ def copy(self, **overrides: Any) -> Function: return f +VersionTuple = tuple[int, int] + + @dc.dataclass(repr=False, slots=True) class Parameter: """ @@ -2606,6 +2853,9 @@ class Parameter: annotation: object = inspect.Parameter.empty docstring: str = '' group: int = 0 + # (`None` signifies that there is no deprecation) + deprecated_positional: VersionTuple | None = None + deprecated_keyword: VersionTuple | None = None right_bracket_count: int = dc.field(init=False, default=0) def __repr__(self) -> str: @@ -2639,11 +2889,16 @@ def copy( def get_displayname(self, i: int) -> str: if i == 0: - return '"argument"' + return 'argument' if not self.is_positional_only(): - return f'"argument {self.name!r}"' + return f'argument {self.name!r}' else: - return f'"argument {i}"' + return f'argument {i}' + + def render_docstring(self) -> str: + lines = [f" {self.name}"] + lines.extend(f" {line}" for line in self.docstring.split("\n")) + return "\n".join(lines).rstrip() CConverterClassT = TypeVar("CConverterClassT", bound=type["CConverter"]) @@ -2681,9 +2936,7 @@ def closure(f: CConverterClassT) -> CConverterClassT: if not kwargs: added_f = f else: - # mypy's special-casing for functools.partial - # can't quite grapple with this code here - added_f = functools.partial(f, **kwargs) # type: ignore[arg-type] + added_f = functools.partial(f, **kwargs) if format_unit: legacy_converters[format_unit] = added_f return f @@ -2691,7 +2944,7 @@ def closure(f: CConverterClassT) -> CConverterClassT: class CConverterAutoRegister(type): def __init__( - cls, name: str, bases: tuple[type, ...], classdict: dict[str, Any] + cls, name: str, bases: tuple[type[object], ...], classdict: dict[str, Any] ) -> None: converter_cls = cast(type["CConverter"], cls) add_c_converter(converter_cls) @@ -2724,7 +2977,7 @@ class CConverter(metaclass=CConverterAutoRegister): # If not None, default must be isinstance() of this type. # (You can also specify a tuple of types.) - default_type: bltns.type[Any] | tuple[bltns.type[Any], ...] | None = None + default_type: bltns.type[object] | tuple[bltns.type[object], ...] | None = None # "default" converted into a C value, as a string. # Or None if there is no default. @@ -2800,6 +3053,9 @@ class CConverter(metaclass=CConverterAutoRegister): # Only set by self_converter. signature_name: str | None = None + include: Include | None = None + broken_limited_capi: bool = False + # keep in sync with self_converter.__init__! def __init__(self, # Positional args: @@ -2862,6 +3118,9 @@ def __getattr__(self, attr): f"Note: accessing self.function inside converter_init is disallowed!" ) return super().__getattr__(attr) + # this branch is just here for coverage reporting + else: # pragma: no cover + pass def converter_init(self) -> None: pass @@ -2957,11 +3216,11 @@ def parse_argument(self, args: list[str]) -> None: args.append(self.converter) if self.encoding: - args.append(c_repr(self.encoding)) + args.append(libclinic.c_repr(self.encoding)) elif self.subclass_of: args.append(self.subclass_of) - s = ("&" if self.parse_by_reference else "") + self.name + s = ("&" if self.parse_by_reference else "") + self.parser_name args.append(s) if self.length: @@ -3054,41 +3313,80 @@ def pre_render(self) -> None: """ pass - def parse_arg(self, argname: str, displayname: str) -> str | None: + def bad_argument(self, displayname: str, expected: str, *, limited_capi: bool, expected_literal: bool = True) -> str: + assert '"' not in expected + if limited_capi: + if expected_literal: + return (f'PyErr_Format(PyExc_TypeError, ' + f'"{{{{name}}}}() {displayname} must be {expected}, not %.50s", ' + f'{{argname}} == Py_None ? "None" : Py_TYPE({{argname}})->tp_name);') + else: + return (f'PyErr_Format(PyExc_TypeError, ' + f'"{{{{name}}}}() {displayname} must be %.50s, not %.50s", ' + f'"{expected}", ' + f'{{argname}} == Py_None ? "None" : Py_TYPE({{argname}})->tp_name);') + else: + if expected_literal: + expected = f'"{expected}"' + if clinic is not None: + clinic.add_include('pycore_modsupport.h', '_PyArg_BadArgument()') + return f'_PyArg_BadArgument("{{{{name}}}}", "{displayname}", {expected}, {{argname}});' + + def format_code(self, fmt: str, *, + argname: str, + bad_argument: str | None = None, + bad_argument2: str | None = None, + **kwargs: Any) -> str: + if '{bad_argument}' in fmt: + if not bad_argument: + raise TypeError("required 'bad_argument' argument") + fmt = fmt.replace('{bad_argument}', bad_argument) + if '{bad_argument2}' in fmt: + if not bad_argument2: + raise TypeError("required 'bad_argument2' argument") + fmt = fmt.replace('{bad_argument2}', bad_argument2) + return fmt.format(argname=argname, paramname=self.parser_name, **kwargs) + + def parse_arg(self, argname: str, displayname: str, *, limited_capi: bool) -> str | None: if self.format_unit == 'O&': - return """ + return self.format_code(""" if (!{converter}({argname}, &{paramname})) {{{{ goto exit; }}}} - """.format(argname=argname, paramname=self.parser_name, - converter=self.converter) + """, + argname=argname, + converter=self.converter) if self.format_unit == 'O!': cast = '(%s)' % self.type if self.type != 'PyObject *' else '' if self.subclass_of in type_checks: typecheck, typename = type_checks[self.subclass_of] - return """ + return self.format_code(""" if (!{typecheck}({argname})) {{{{ - _PyArg_BadArgument("{{name}}", {displayname}, "{typename}", {argname}); + {bad_argument} goto exit; }}}} {paramname} = {cast}{argname}; - """.format(argname=argname, paramname=self.parser_name, - displayname=displayname, typecheck=typecheck, - typename=typename, cast=cast) - return """ + """, + argname=argname, + bad_argument=self.bad_argument(displayname, typename, limited_capi=limited_capi), + typecheck=typecheck, typename=typename, cast=cast) + return self.format_code(""" if (!PyObject_TypeCheck({argname}, {subclass_of})) {{{{ - _PyArg_BadArgument("{{name}}", {displayname}, ({subclass_of})->tp_name, {argname}); + {bad_argument} goto exit; }}}} {paramname} = {cast}{argname}; - """.format(argname=argname, paramname=self.parser_name, - subclass_of=self.subclass_of, cast=cast, - displayname=displayname) + """, + argname=argname, + bad_argument=self.bad_argument(displayname, '({subclass_of})->tp_name', + expected_literal=False, limited_capi=limited_capi), + subclass_of=self.subclass_of, cast=cast) if self.format_unit == 'O': cast = '(%s)' % self.type if self.type != 'PyObject *' else '' - return """ + return self.format_code(""" {paramname} = {cast}{argname}; - """.format(argname=argname, paramname=self.parser_name, cast=cast) + """, + argname=argname, cast=cast) return None def set_template_dict(self, template_dict: TemplateDict) -> None: @@ -3096,11 +3394,17 @@ def set_template_dict(self, template_dict: TemplateDict) -> None: @property def parser_name(self) -> str: - if self.name in CLINIC_PREFIXED_ARGS: # bpo-39741 - return CLINIC_PREFIX + self.name + if self.name in libclinic.CLINIC_PREFIXED_ARGS: # bpo-39741 + return libclinic.CLINIC_PREFIX + self.name else: return self.name + def add_include(self, name: str, reason: str, + *, condition: str | None = None) -> None: + if self.include is not None: + raise ValueError("a converter only supports a single include") + self.include = Include(name, reason, condition) + type_checks = { '&PyLong_Type': ('PyLong_Check', 'int'), '&PyTuple_Type': ('PyTuple_Check', 'tuple'), @@ -3139,7 +3443,7 @@ def parser_name(self) -> str: ReturnConverterDict = dict[str, ReturnConverterType] return_converters: ReturnConverterDict = {} -TypeSet = set[bltns.type[Any]] +TypeSet = set[bltns.type[object]] class bool_converter(CConverter): @@ -3153,26 +3457,28 @@ def converter_init(self, *, accept: TypeSet = {object}) -> None: self.format_unit = 'i' elif accept != {object}: fail(f"bool_converter: illegal 'accept' argument {accept!r}") - if self.default is not unspecified: + if self.default is not unspecified and self.default is not unknown: self.default = bool(self.default) self.c_default = str(int(self.default)) - def parse_arg(self, argname: str, displayname: str) -> str | None: + def parse_arg(self, argname: str, displayname: str, *, limited_capi: bool) -> str | None: if self.format_unit == 'i': - return """ - {paramname} = _PyLong_AsInt({argname}); + return self.format_code(""" + {paramname} = PyLong_AsInt({argname}); if ({paramname} == -1 && PyErr_Occurred()) {{{{ goto exit; }}}} - """.format(argname=argname, paramname=self.parser_name) + """, + argname=argname) elif self.format_unit == 'p': - return """ + return self.format_code(""" {paramname} = PyObject_IsTrue({argname}); if ({paramname} < 0) {{{{ goto exit; }}}} - """.format(argname=argname, paramname=self.parser_name) - return super().parse_arg(argname, displayname) + """, + argname=argname) + return super().parse_arg(argname, displayname, limited_capi=limited_capi) class defining_class_converter(CConverter): """ @@ -3208,9 +3514,9 @@ def converter_init(self) -> None: if self.c_default == '"\'"': self.c_default = r"'\''" - def parse_arg(self, argname: str, displayname: str) -> str | None: + def parse_arg(self, argname: str, displayname: str, *, limited_capi: bool) -> str | None: if self.format_unit == 'c': - return """ + return self.format_code(""" if (PyBytes_Check({argname}) && PyBytes_GET_SIZE({argname}) == 1) {{{{ {paramname} = PyBytes_AS_STRING({argname})[0]; }}}} @@ -3218,12 +3524,14 @@ def parse_arg(self, argname: str, displayname: str) -> str | None: {paramname} = PyByteArray_AS_STRING({argname})[0]; }}}} else {{{{ - _PyArg_BadArgument("{{name}}", {displayname}, "a byte string of length 1", {argname}); + {bad_argument} goto exit; }}}} - """.format(argname=argname, paramname=self.parser_name, - displayname=displayname) - return super().parse_arg(argname, displayname) + """, + argname=argname, + bad_argument=self.bad_argument(displayname, 'a byte string of length 1', limited_capi=limited_capi), + ) + return super().parse_arg(argname, displayname, limited_capi=limited_capi) @add_legacy_c_converter('B', bitwise=True) @@ -3237,9 +3545,9 @@ def converter_init(self, *, bitwise: bool = False) -> None: if bitwise: self.format_unit = 'B' - def parse_arg(self, argname: str, displayname: str) -> str | None: + def parse_arg(self, argname: str, displayname: str, *, limited_capi: bool) -> str | None: if self.format_unit == 'b': - return """ + return self.format_code(""" {{{{ long ival = PyLong_AsLong({argname}); if (ival == -1 && PyErr_Occurred()) {{{{ @@ -3259,9 +3567,10 @@ def parse_arg(self, argname: str, displayname: str) -> str | None: {paramname} = (unsigned char) ival; }}}} }}}} - """.format(argname=argname, paramname=self.parser_name) + """, + argname=argname) elif self.format_unit == 'B': - return """ + return self.format_code(""" {{{{ unsigned long ival = PyLong_AsUnsignedLongMask({argname}); if (ival == (unsigned long)-1 && PyErr_Occurred()) {{{{ @@ -3271,8 +3580,9 @@ def parse_arg(self, argname: str, displayname: str) -> str | None: {paramname} = (unsigned char) ival; }}}} }}}} - """.format(argname=argname, paramname=self.parser_name) - return super().parse_arg(argname, displayname) + """, + argname=argname) + return super().parse_arg(argname, displayname, limited_capi=limited_capi) class byte_converter(unsigned_char_converter): pass @@ -3282,9 +3592,9 @@ class short_converter(CConverter): format_unit = 'h' c_ignored_default = "0" - def parse_arg(self, argname: str, displayname: str) -> str | None: + def parse_arg(self, argname: str, displayname: str, *, limited_capi: bool) -> str | None: if self.format_unit == 'h': - return """ + return self.format_code(""" {{{{ long ival = PyLong_AsLong({argname}); if (ival == -1 && PyErr_Occurred()) {{{{ @@ -3304,8 +3614,9 @@ def parse_arg(self, argname: str, displayname: str) -> str | None: {paramname} = (short) ival; }}}} }}}} - """.format(argname=argname, paramname=self.parser_name) - return super().parse_arg(argname, displayname) + """, + argname=argname) + return super().parse_arg(argname, displayname, limited_capi=limited_capi) class unsigned_short_converter(CConverter): type = 'unsigned short' @@ -3317,16 +3628,36 @@ def converter_init(self, *, bitwise: bool = False) -> None: self.format_unit = 'H' else: self.converter = '_PyLong_UnsignedShort_Converter' + self.add_include('pycore_long.h', + '_PyLong_UnsignedShort_Converter()') - def parse_arg(self, argname: str, displayname: str) -> str | None: + def parse_arg(self, argname: str, displayname: str, *, limited_capi: bool) -> str | None: if self.format_unit == 'H': - return """ + return self.format_code(""" {paramname} = (unsigned short)PyLong_AsUnsignedLongMask({argname}); if ({paramname} == (unsigned short)-1 && PyErr_Occurred()) {{{{ goto exit; }}}} - """.format(argname=argname, paramname=self.parser_name) - return super().parse_arg(argname, displayname) + """, + argname=argname) + if not limited_capi: + return super().parse_arg(argname, displayname, limited_capi=limited_capi) + # NOTE: Raises OverflowError for negative integer. + return self.format_code(""" + {{{{ + unsigned long uval = PyLong_AsUnsignedLong({argname}); + if (uval == (unsigned long)-1 && PyErr_Occurred()) {{{{ + goto exit; + }}}} + if (uval > USHRT_MAX) {{{{ + PyErr_SetString(PyExc_OverflowError, + "Python int too large for C unsigned short"); + goto exit; + }}}} + {paramname} = (unsigned short) uval; + }}}} + """, + argname=argname) @add_legacy_c_converter('C', accept={str}) class int_converter(CConverter): @@ -3345,28 +3676,31 @@ def converter_init( if type is not None: self.type = type - def parse_arg(self, argname: str, displayname: str) -> str | None: + def parse_arg(self, argname: str, displayname: str, *, limited_capi: bool) -> str | None: if self.format_unit == 'i': - return """ - {paramname} = _PyLong_AsInt({argname}); + return self.format_code(""" + {paramname} = PyLong_AsInt({argname}); if ({paramname} == -1 && PyErr_Occurred()) {{{{ goto exit; }}}} - """.format(argname=argname, paramname=self.parser_name) + """, + argname=argname) elif self.format_unit == 'C': - return """ + return self.format_code(""" if (!PyUnicode_Check({argname})) {{{{ - _PyArg_BadArgument("{{name}}", {displayname}, "a unicode character", {argname}); + {bad_argument} goto exit; }}}} if (PyUnicode_GET_LENGTH({argname}) != 1) {{{{ - _PyArg_BadArgument("{{name}}", {displayname}, "a unicode character", {argname}); + {bad_argument} goto exit; }}}} {paramname} = PyUnicode_READ_CHAR({argname}, 0); - """.format(argname=argname, paramname=self.parser_name, - displayname=displayname) - return super().parse_arg(argname, displayname) + """, + argname=argname, + bad_argument=self.bad_argument(displayname, 'a unicode character', limited_capi=limited_capi), + ) + return super().parse_arg(argname, displayname, limited_capi=limited_capi) class unsigned_int_converter(CConverter): type = 'unsigned int' @@ -3378,16 +3712,36 @@ def converter_init(self, *, bitwise: bool = False) -> None: self.format_unit = 'I' else: self.converter = '_PyLong_UnsignedInt_Converter' + self.add_include('pycore_long.h', + '_PyLong_UnsignedInt_Converter()') - def parse_arg(self, argname: str, displayname: str) -> str | None: + def parse_arg(self, argname: str, displayname: str, *, limited_capi: bool) -> str | None: if self.format_unit == 'I': - return """ + return self.format_code(""" {paramname} = (unsigned int)PyLong_AsUnsignedLongMask({argname}); if ({paramname} == (unsigned int)-1 && PyErr_Occurred()) {{{{ goto exit; }}}} - """.format(argname=argname, paramname=self.parser_name) - return super().parse_arg(argname, displayname) + """, + argname=argname) + if not limited_capi: + return super().parse_arg(argname, displayname, limited_capi=limited_capi) + # NOTE: Raises OverflowError for negative integer. + return self.format_code(""" + {{{{ + unsigned long uval = PyLong_AsUnsignedLong({argname}); + if (uval == (unsigned long)-1 && PyErr_Occurred()) {{{{ + goto exit; + }}}} + if (uval > UINT_MAX) {{{{ + PyErr_SetString(PyExc_OverflowError, + "Python int too large for C unsigned int"); + goto exit; + }}}} + {paramname} = (unsigned int) uval; + }}}} + """, + argname=argname) class long_converter(CConverter): type = 'long' @@ -3395,15 +3749,16 @@ class long_converter(CConverter): format_unit = 'l' c_ignored_default = "0" - def parse_arg(self, argname: str, displayname: str) -> str | None: + def parse_arg(self, argname: str, displayname: str, *, limited_capi: bool) -> str | None: if self.format_unit == 'l': - return """ + return self.format_code(""" {paramname} = PyLong_AsLong({argname}); if ({paramname} == -1 && PyErr_Occurred()) {{{{ goto exit; }}}} - """.format(argname=argname, paramname=self.parser_name) - return super().parse_arg(argname, displayname) + """, + argname=argname) + return super().parse_arg(argname, displayname, limited_capi=limited_capi) class unsigned_long_converter(CConverter): type = 'unsigned long' @@ -3415,18 +3770,31 @@ def converter_init(self, *, bitwise: bool = False) -> None: self.format_unit = 'k' else: self.converter = '_PyLong_UnsignedLong_Converter' + self.add_include('pycore_long.h', + '_PyLong_UnsignedLong_Converter()') - def parse_arg(self, argname: str, displayname: str) -> str | None: + def parse_arg(self, argname: str, displayname: str, *, limited_capi: bool) -> str | None: if self.format_unit == 'k': - return """ + return self.format_code(""" if (!PyLong_Check({argname})) {{{{ - _PyArg_BadArgument("{{name}}", {displayname}, "int", {argname}); + {bad_argument} goto exit; }}}} {paramname} = PyLong_AsUnsignedLongMask({argname}); - """.format(argname=argname, paramname=self.parser_name, - displayname=displayname) - return super().parse_arg(argname, displayname) + """, + argname=argname, + bad_argument=self.bad_argument(displayname, 'int', limited_capi=limited_capi), + ) + if not limited_capi: + return super().parse_arg(argname, displayname, limited_capi=limited_capi) + # NOTE: Raises OverflowError for negative integer. + return self.format_code(""" + {paramname} = PyLong_AsUnsignedLong({argname}); + if ({paramname} == (unsigned long)-1 && PyErr_Occurred()) {{{{ + goto exit; + }}}} + """, + argname=argname) class long_long_converter(CConverter): type = 'long long' @@ -3434,15 +3802,16 @@ class long_long_converter(CConverter): format_unit = 'L' c_ignored_default = "0" - def parse_arg(self, argname: str, displayname: str) -> str | None: + def parse_arg(self, argname: str, displayname: str, *, limited_capi: bool) -> str | None: if self.format_unit == 'L': - return """ + return self.format_code(""" {paramname} = PyLong_AsLongLong({argname}); if ({paramname} == -1 && PyErr_Occurred()) {{{{ goto exit; }}}} - """.format(argname=argname, paramname=self.parser_name) - return super().parse_arg(argname, displayname) + """, + argname=argname) + return super().parse_arg(argname, displayname, limited_capi=limited_capi) class unsigned_long_long_converter(CConverter): type = 'unsigned long long' @@ -3454,18 +3823,31 @@ def converter_init(self, *, bitwise: bool = False) -> None: self.format_unit = 'K' else: self.converter = '_PyLong_UnsignedLongLong_Converter' + self.add_include('pycore_long.h', + '_PyLong_UnsignedLongLong_Converter()') - def parse_arg(self, argname: str, displayname: str) -> str | None: + def parse_arg(self, argname: str, displayname: str, *, limited_capi: bool) -> str | None: if self.format_unit == 'K': - return """ + return self.format_code(""" if (!PyLong_Check({argname})) {{{{ - _PyArg_BadArgument("{{name}}", {displayname}, "int", {argname}); + {bad_argument} goto exit; }}}} {paramname} = PyLong_AsUnsignedLongLongMask({argname}); - """.format(argname=argname, paramname=self.parser_name, - displayname=displayname) - return super().parse_arg(argname, displayname) + """, + argname=argname, + bad_argument=self.bad_argument(displayname, 'int', limited_capi=limited_capi), + ) + if not limited_capi: + return super().parse_arg(argname, displayname, limited_capi=limited_capi) + # NOTE: Raises OverflowError for negative integer. + return self.format_code(""" + {paramname} = PyLong_AsUnsignedLongLong({argname}); + if ({paramname} == (unsigned long long)-1 && PyErr_Occurred()) {{{{ + goto exit; + }}}} + """, + argname=argname) class Py_ssize_t_converter(CConverter): type = 'Py_ssize_t' @@ -3475,17 +3857,24 @@ def converter_init(self, *, accept: TypeSet = {int}) -> None: if accept == {int}: self.format_unit = 'n' self.default_type = int + self.add_include('pycore_abstract.h', '_PyNumber_Index()') elif accept == {int, NoneType}: self.converter = '_Py_convert_optional_to_ssize_t' + self.add_include('pycore_abstract.h', + '_Py_convert_optional_to_ssize_t()') else: fail(f"Py_ssize_t_converter: illegal 'accept' argument {accept!r}") - def parse_arg(self, argname: str, displayname: str) -> str | None: + def parse_arg(self, argname: str, displayname: str, *, limited_capi: bool) -> str | None: if self.format_unit == 'n': - return """ + if limited_capi: + PyNumber_Index = 'PyNumber_Index' + else: + PyNumber_Index = '_PyNumber_Index' + return self.format_code(""" {{{{ Py_ssize_t ival = -1; - PyObject *iobj = _PyNumber_Index({argname}); + PyObject *iobj = {PyNumber_Index}({argname}); if (iobj != NULL) {{{{ ival = PyLong_AsSsize_t(iobj); Py_DECREF(iobj); @@ -3495,8 +3884,28 @@ def parse_arg(self, argname: str, displayname: str) -> str | None: }}}} {paramname} = ival; }}}} - """.format(argname=argname, paramname=self.parser_name) - return super().parse_arg(argname, displayname) + """, + argname=argname, + PyNumber_Index=PyNumber_Index) + if not limited_capi: + return super().parse_arg(argname, displayname, limited_capi=limited_capi) + return self.format_code(""" + if ({argname} != Py_None) {{{{ + if (PyIndex_Check({argname})) {{{{ + {paramname} = PyNumber_AsSsize_t({argname}, PyExc_OverflowError); + if ({paramname} == -1 && PyErr_Occurred()) {{{{ + goto exit; + }}}} + }}}} + else {{{{ + {bad_argument} + goto exit; + }}}} + }}}} + """, + argname=argname, + bad_argument=self.bad_argument(displayname, 'integer or None', limited_capi=limited_capi), + ) class slice_index_converter(CConverter): @@ -3505,38 +3914,97 @@ class slice_index_converter(CConverter): def converter_init(self, *, accept: TypeSet = {int, NoneType}) -> None: if accept == {int}: self.converter = '_PyEval_SliceIndexNotNone' + self.nullable = False elif accept == {int, NoneType}: self.converter = '_PyEval_SliceIndex' + self.nullable = True else: fail(f"slice_index_converter: illegal 'accept' argument {accept!r}") + def parse_arg(self, argname: str, displayname: str, *, limited_capi: bool) -> str | None: + if not limited_capi: + return super().parse_arg(argname, displayname, limited_capi=limited_capi) + if self.nullable: + return self.format_code(""" + if (!Py_IsNone({argname})) {{{{ + if (PyIndex_Check({argname})) {{{{ + {paramname} = PyNumber_AsSsize_t({argname}, NULL); + if ({paramname} == -1 && PyErr_Occurred()) {{{{ + return 0; + }}}} + }}}} + else {{{{ + PyErr_SetString(PyExc_TypeError, + "slice indices must be integers or " + "None or have an __index__ method"); + goto exit; + }}}} + }}}} + """, + argname=argname) + else: + return self.format_code(""" + if (PyIndex_Check({argname})) {{{{ + {paramname} = PyNumber_AsSsize_t({argname}, NULL); + if ({paramname} == -1 && PyErr_Occurred()) {{{{ + goto exit; + }}}} + }}}} + else {{{{ + PyErr_SetString(PyExc_TypeError, + "slice indices must be integers or " + "have an __index__ method"); + goto exit; + }}}} + """, + argname=argname) + class size_t_converter(CConverter): type = 'size_t' converter = '_PyLong_Size_t_Converter' c_ignored_default = "0" - def parse_arg(self, argname: str, displayname: str) -> str | None: + def converter_init(self, *, accept: TypeSet = {int, NoneType}) -> None: + self.add_include('pycore_long.h', + '_PyLong_Size_t_Converter()') + + def parse_arg(self, argname: str, displayname: str, *, limited_capi: bool) -> str | None: if self.format_unit == 'n': - return """ + return self.format_code(""" {paramname} = PyNumber_AsSsize_t({argname}, PyExc_OverflowError); if ({paramname} == -1 && PyErr_Occurred()) {{{{ goto exit; }}}} - """.format(argname=argname, paramname=self.parser_name) - return super().parse_arg(argname, displayname) + """, + argname=argname) + if not limited_capi: + return super().parse_arg(argname, displayname, limited_capi=limited_capi) + # NOTE: Raises OverflowError for negative integer. + return self.format_code(""" + {paramname} = PyLong_AsSize_t({argname}); + if ({paramname} == (size_t)-1 && PyErr_Occurred()) {{{{ + goto exit; + }}}} + """, + argname=argname) class fildes_converter(CConverter): type = 'int' converter = '_PyLong_FileDescriptor_Converter' + def converter_init(self, *, accept: TypeSet = {int, NoneType}) -> None: + self.add_include('pycore_fileutils.h', + '_PyLong_FileDescriptor_Converter()') + def _parse_arg(self, argname: str, displayname: str) -> str | None: - return """ + return self.format_code(""" {paramname} = PyObject_AsFileDescriptor({argname}); if ({paramname} == -1) {{{{ goto exit; }}}} - """.format(argname=argname, paramname=self.name) + """, + argname=argname) class float_converter(CConverter): @@ -3545,9 +4013,9 @@ class float_converter(CConverter): format_unit = 'f' c_ignored_default = "0.0" - def parse_arg(self, argname: str, displayname: str) -> str | None: + def parse_arg(self, argname: str, displayname: str, *, limited_capi: bool) -> str | None: if self.format_unit == 'f': - return """ + return self.format_code(""" if (PyFloat_CheckExact({argname})) {{{{ {paramname} = (float) (PyFloat_AS_DOUBLE({argname})); }}}} @@ -3558,8 +4026,9 @@ def parse_arg(self, argname: str, displayname: str) -> str | None: goto exit; }}}} }}}} - """.format(argname=argname, paramname=self.parser_name) - return super().parse_arg(argname, displayname) + """, + argname=argname) + return super().parse_arg(argname, displayname, limited_capi=limited_capi) class double_converter(CConverter): type = 'double' @@ -3567,9 +4036,9 @@ class double_converter(CConverter): format_unit = 'd' c_ignored_default = "0.0" - def parse_arg(self, argname: str, displayname: str) -> str | None: + def parse_arg(self, argname: str, displayname: str, *, limited_capi: bool) -> str | None: if self.format_unit == 'd': - return """ + return self.format_code(""" if (PyFloat_CheckExact({argname})) {{{{ {paramname} = PyFloat_AS_DOUBLE({argname}); }}}} @@ -3580,8 +4049,9 @@ def parse_arg(self, argname: str, displayname: str) -> str | None: goto exit; }}}} }}}} - """.format(argname=argname, paramname=self.parser_name) - return super().parse_arg(argname, displayname) + """, + argname=argname) + return super().parse_arg(argname, displayname, limited_capi=limited_capi) class Py_complex_converter(CConverter): @@ -3590,15 +4060,16 @@ class Py_complex_converter(CConverter): format_unit = 'D' c_ignored_default = "{0.0, 0.0}" - def parse_arg(self, argname: str, displayname: str) -> str | None: + def parse_arg(self, argname: str, displayname: str, *, limited_capi: bool) -> str | None: if self.format_unit == 'D': - return """ + return self.format_code(""" {paramname} = PyComplex_AsCComplex({argname}); if (PyErr_Occurred()) {{{{ goto exit; }}}} - """.format(argname=argname, paramname=self.parser_name) - return super().parse_arg(argname, displayname) + """, + argname=argname) + return super().parse_arg(argname, displayname, limited_capi=limited_capi) class object_converter(CConverter): @@ -3636,7 +4107,7 @@ class buffer: pass class rwbuffer: pass class robuffer: pass -StrConverterKeyType = tuple[frozenset[type], bool, bool] +StrConverterKeyType = tuple[frozenset[type[object]], bool, bool] def str_converter_key( types: TypeSet, encoding: bool | str | None, zeroes: bool @@ -3683,11 +4154,11 @@ def post_parsing(self) -> str: else: return "" - def parse_arg(self, argname: str, displayname: str) -> str | None: + def parse_arg(self, argname: str, displayname: str, *, limited_capi: bool) -> str | None: if self.format_unit == 's': - return """ + return self.format_code(""" if (!PyUnicode_Check({argname})) {{{{ - _PyArg_BadArgument("{{name}}", {displayname}, "str", {argname}); + {bad_argument} goto exit; }}}} Py_ssize_t {length_name}; @@ -3699,10 +4170,12 @@ def parse_arg(self, argname: str, displayname: str) -> str | None: PyErr_SetString(PyExc_ValueError, "embedded null character"); goto exit; }}}} - """.format(argname=argname, paramname=self.parser_name, - displayname=displayname, length_name=self.length_name) + """, + argname=argname, + bad_argument=self.bad_argument(displayname, 'str', limited_capi=limited_capi), + length_name=self.length_name) if self.format_unit == 'z': - return """ + return self.format_code(""" if ({argname} == Py_None) {{{{ {paramname} = NULL; }}}} @@ -3718,12 +4191,14 @@ def parse_arg(self, argname: str, displayname: str) -> str | None: }}}} }}}} else {{{{ - _PyArg_BadArgument("{{name}}", {displayname}, "str or None", {argname}); + {bad_argument} goto exit; }}}} - """.format(argname=argname, paramname=self.parser_name, - displayname=displayname, length_name=self.length_name) - return super().parse_arg(argname, displayname) + """, + argname=argname, + bad_argument=self.bad_argument(displayname, 'str or None', limited_capi=limited_capi), + length_name=self.length_name) + return super().parse_arg(argname, displayname, limited_capi=limited_capi) # # This is the fourth or fifth rewrite of registering all the @@ -3785,51 +4260,57 @@ class PyBytesObject_converter(CConverter): format_unit = 'S' # accept = {bytes} - def parse_arg(self, argname: str, displayname: str) -> str | None: + def parse_arg(self, argname: str, displayname: str, *, limited_capi: bool) -> str | None: if self.format_unit == 'S': - return """ + return self.format_code(""" if (!PyBytes_Check({argname})) {{{{ - _PyArg_BadArgument("{{name}}", {displayname}, "bytes", {argname}); + {bad_argument} goto exit; }}}} {paramname} = ({type}){argname}; - """.format(argname=argname, paramname=self.parser_name, - type=self.type, displayname=displayname) - return super().parse_arg(argname, displayname) + """, + argname=argname, + bad_argument=self.bad_argument(displayname, 'bytes', limited_capi=limited_capi), + type=self.type) + return super().parse_arg(argname, displayname, limited_capi=limited_capi) class PyByteArrayObject_converter(CConverter): type = 'PyByteArrayObject *' format_unit = 'Y' # accept = {bytearray} - def parse_arg(self, argname: str, displayname: str) -> str | None: + def parse_arg(self, argname: str, displayname: str, *, limited_capi: bool) -> str | None: if self.format_unit == 'Y': - return """ + return self.format_code(""" if (!PyByteArray_Check({argname})) {{{{ - _PyArg_BadArgument("{{name}}", {displayname}, "bytearray", {argname}); + {bad_argument} goto exit; }}}} {paramname} = ({type}){argname}; - """.format(argname=argname, paramname=self.parser_name, - type=self.type, displayname=displayname) - return super().parse_arg(argname, displayname) + """, + argname=argname, + bad_argument=self.bad_argument(displayname, 'bytearray', limited_capi=limited_capi), + type=self.type) + return super().parse_arg(argname, displayname, limited_capi=limited_capi) class unicode_converter(CConverter): type = 'PyObject *' default_type = (str, Null, NoneType) format_unit = 'U' - def parse_arg(self, argname: str, displayname: str) -> str | None: + def parse_arg(self, argname: str, displayname: str, *, limited_capi: bool) -> str | None: if self.format_unit == 'U': - return """ + return self.format_code(""" if (!PyUnicode_Check({argname})) {{{{ - _PyArg_BadArgument("{{name}}", {displayname}, "str", {argname}); + {bad_argument} goto exit; }}}} {paramname} = {argname}; - """.format(argname=argname, paramname=self.parser_name, - displayname=displayname) - return super().parse_arg(argname, displayname) + """, + argname=argname, + bad_argument=self.bad_argument(displayname, 'str', limited_capi=limited_capi), + ) + return super().parse_arg(argname, displayname, limited_capi=limited_capi) @add_legacy_c_converter('u') @add_legacy_c_converter('u#', zeroes=True) @@ -3863,25 +4344,26 @@ def cleanup(self) -> str: if self.length: return "" else: - return """\ -PyMem_Free((void *){name}); -""".format(name=self.name) + return f"""PyMem_Free((void *){self.parser_name});\n""" - def parse_arg(self, argname: str, argnum: str) -> str | None: + def parse_arg(self, argname: str, displayname: str, *, limited_capi: bool) -> str | None: if not self.length: if self.accept == {str}: - return """ + return self.format_code(""" if (!PyUnicode_Check({argname})) {{{{ - _PyArg_BadArgument("{{name}}", {argnum}, "str", {argname}); + {bad_argument} goto exit; }}}} {paramname} = PyUnicode_AsWideCharString({argname}, NULL); if ({paramname} == NULL) {{{{ goto exit; }}}} - """.format(argname=argname, paramname=self.name, argnum=argnum) + """, + argname=argname, + bad_argument=self.bad_argument(displayname, 'str', limited_capi=limited_capi), + ) elif self.accept == {str, NoneType}: - return """ + return self.format_code(""" if ({argname} == Py_None) {{{{ {paramname} = NULL; }}}} @@ -3892,11 +4374,14 @@ def parse_arg(self, argname: str, argnum: str) -> str | None: }}}} }}}} else {{{{ - _PyArg_BadArgument("{{name}}", {argnum}, "str or None", {argname}); + {bad_argument} goto exit; }}}} - """.format(argname=argname, paramname=self.name, argnum=argnum) - return super().parse_arg(argname, argnum) + """, + argname=argname, + bad_argument=self.bad_argument(displayname, 'str or None', limited_capi=limited_capi), + ) + return super().parse_arg(argname, displayname, limited_capi=limited_capi) @add_legacy_c_converter('s*', accept={str, buffer}) @add_legacy_c_converter('z*', accept={str, buffer, NoneType}) @@ -3930,20 +4415,19 @@ def cleanup(self) -> str: name = self.name return "".join(["if (", name, ".obj) {\n PyBuffer_Release(&", name, ");\n}\n"]) - def parse_arg(self, argname: str, displayname: str) -> str | None: + def parse_arg(self, argname: str, displayname: str, *, limited_capi: bool) -> str | None: + # PyBUF_SIMPLE guarantees that the format units of the buffers are C-contiguous. if self.format_unit == 'y*': - return """ + return self.format_code(""" if (PyObject_GetBuffer({argname}, &{paramname}, PyBUF_SIMPLE) != 0) {{{{ goto exit; }}}} - if (!PyBuffer_IsContiguous(&{paramname}, 'C')) {{{{ - _PyArg_BadArgument("{{name}}", {displayname}, "contiguous buffer", {argname}); - goto exit; - }}}} - """.format(argname=argname, paramname=self.parser_name, - displayname=displayname) + """, + argname=argname, + bad_argument=self.bad_argument(displayname, 'contiguous buffer', limited_capi=limited_capi), + ) elif self.format_unit == 's*': - return """ + return self.format_code(""" if (PyUnicode_Check({argname})) {{{{ Py_ssize_t len; const char *ptr = PyUnicode_AsUTF8AndSize({argname}, &len); @@ -3956,33 +4440,29 @@ def parse_arg(self, argname: str, displayname: str) -> str | None: if (PyObject_GetBuffer({argname}, &{paramname}, PyBUF_SIMPLE) != 0) {{{{ goto exit; }}}} - if (!PyBuffer_IsContiguous(&{paramname}, 'C')) {{{{ - _PyArg_BadArgument("{{name}}", {displayname}, "contiguous buffer", {argname}); - goto exit; - }}}} }}}} - """.format(argname=argname, paramname=self.parser_name, - displayname=displayname) + """, + argname=argname, + bad_argument=self.bad_argument(displayname, 'contiguous buffer', limited_capi=limited_capi), + ) elif self.format_unit == 'w*': - return """ + return self.format_code(""" if (PyObject_GetBuffer({argname}, &{paramname}, PyBUF_WRITABLE) < 0) {{{{ - PyErr_Clear(); - _PyArg_BadArgument("{{name}}", {displayname}, "read-write bytes-like object", {argname}); + {bad_argument} goto exit; }}}} - if (!PyBuffer_IsContiguous(&{paramname}, 'C')) {{{{ - _PyArg_BadArgument("{{name}}", {displayname}, "contiguous buffer", {argname}); - goto exit; - }}}} - """.format(argname=argname, paramname=self.parser_name, - displayname=displayname) - return super().parse_arg(argname, displayname) + """, + argname=argname, + bad_argument=self.bad_argument(displayname, 'read-write bytes-like object', limited_capi=limited_capi), + bad_argument2=self.bad_argument(displayname, 'contiguous buffer', limited_capi=limited_capi), + ) + return super().parse_arg(argname, displayname, limited_capi=limited_capi) def correct_name_for_self( f: Function ) -> tuple[str, str]: - if f.kind in (CALLABLE, METHOD_INIT): + if f.kind in {CALLABLE, METHOD_INIT, GETTER, SETTER}: if f.cls: return "PyObject *", "self" return "PyObject *", "module" @@ -3990,7 +4470,7 @@ def correct_name_for_self( return "void *", "null" if f.kind in (CLASS_METHOD, METHOD_NEW): return "PyTypeObject *", "type" - raise RuntimeError("Unhandled type of function f: " + repr(f.kind)) + raise AssertionError(f"Unhandled type of function f: {f.kind!r}") def required_type_for_self_for_parser( f: Function @@ -4126,7 +4606,7 @@ class CReturnConverterAutoRegister(type): def __init__( cls: ReturnConverterType, name: str, - bases: tuple[type, ...], + bases: tuple[type[object], ...], classdict: dict[str, Any] ) -> None: add_c_return_converter(cls) @@ -4422,18 +4902,29 @@ class ParamState(enum.IntEnum): RIGHT_SQUARE_AFTER = 6 +class FunctionNames(NamedTuple): + full_name: str + c_basename: str + + class DSLParser: function: Function | None state: StateKeeper keyword_only: bool positional_only: bool + deprecated_positional: VersionTuple | None + deprecated_keyword: VersionTuple | None group: int parameter_state: ParamState indent: IndentStack kind: FunctionKind coexist: bool + forced_text_signature: str | None parameter_continuation: str preserve_output: bool + critical_section: bool + target_critical_section: list[str] + from_version_re = re.compile(r'([*/]) +\[from +(.+)\]') def __init__(self, clinic: Clinic) -> None: self.clinic = clinic @@ -4457,20 +4948,18 @@ def reset(self) -> None: self.state = self.state_dsl_start self.keyword_only = False self.positional_only = False + self.deprecated_positional = None + self.deprecated_keyword = None self.group = 0 self.parameter_state: ParamState = ParamState.START self.indent = IndentStack() self.kind = CALLABLE self.coexist = False + self.forced_text_signature = None self.parameter_continuation = '' self.preserve_output = False - - def directive_version(self, required: str) -> None: - global version - if version_comparitor(version, required) < 0: - fail("Insufficient Clinic version!\n" - f" Version: {version}\n" - f" Required: {required}") + self.critical_section = False + self.target_critical_section = [] def directive_module(self, name: str) -> None: fields = name.split('.')[:-1] @@ -4592,6 +5081,30 @@ def at_classmethod(self) -> None: fail("Can't set @classmethod, function is not a normal callable") self.kind = CLASS_METHOD + def at_critical_section(self, *args: str) -> None: + if len(args) > 2: + fail("Up to 2 critical section variables are supported") + self.target_critical_section.extend(args) + self.critical_section = True + + def at_getter(self) -> None: + match self.kind: + case FunctionKind.GETTER: + fail("Cannot apply @getter twice to the same function!") + case FunctionKind.SETTER: + fail("Cannot apply both @getter and @setter to the same function!") + case _: + self.kind = FunctionKind.GETTER + + def at_setter(self) -> None: + match self.kind: + case FunctionKind.SETTER: + fail("Cannot apply @setter twice to the same function!") + case FunctionKind.GETTER: + fail("Cannot apply both @getter and @setter to the same function!") + case _: + self.kind = FunctionKind.SETTER + def at_staticmethod(self) -> None: if self.kind is not CALLABLE: fail("Can't set @staticmethod, function is not a normal callable") @@ -4602,6 +5115,11 @@ def at_coexist(self) -> None: fail("Called @coexist twice!") self.coexist = True + def at_text_signature(self, text_signature: str) -> None: + if self.forced_text_signature: + fail("Called @text_signature twice!") + self.forced_text_signature = text_signature + def parse(self, block: Block) -> None: self.reset() self.block = block @@ -4619,7 +5137,7 @@ def parse(self, block: Block) -> None: exc.lineno = line_number raise - self.do_post_block_processing_cleanup() + self.do_post_block_processing_cleanup(line_number) block.output.extend(self.clinic.language.render(self.clinic, block.signatures)) if self.preserve_output: @@ -4672,6 +5190,45 @@ def state_dsl_start(self, line: str) -> None: self.next(self.state_modulename_name, line) + @staticmethod + def parse_function_names(line: str) -> FunctionNames: + left, as_, right = line.partition(' as ') + full_name = left.strip() + c_basename = right.strip() + if as_ and not c_basename: + fail("No C basename provided after 'as' keyword") + if not c_basename: + fields = full_name.split(".") + if fields[-1] == '__new__': + fields.pop() + c_basename = "_".join(fields) + if not is_legal_py_identifier(full_name): + fail(f"Illegal function name: {full_name!r}") + if not is_legal_c_identifier(c_basename): + fail(f"Illegal C basename: {c_basename!r}") + return FunctionNames(full_name=full_name, c_basename=c_basename) + + def update_function_kind(self, fullname: str) -> None: + fields = fullname.split('.') + name = fields.pop() + _, cls = self.clinic._module_and_class(fields) + if name in unsupported_special_methods: + fail(f"{name!r} is a special method and cannot be converted to Argument Clinic!") + + if name == '__new__': + if (self.kind is CLASS_METHOD) and cls: + self.kind = METHOD_NEW + else: + fail("'__new__' must be a class method!") + elif name == '__init__': + if (self.kind is CALLABLE) and cls: + self.kind = METHOD_INIT + else: + fail( + "'__init__' must be a normal method; " + f"got '{self.kind}'!" + ) + def state_modulename_name(self, line: str) -> None: # looking for declaration, which establishes the leftmost column # line should be @@ -4694,15 +5251,10 @@ def state_modulename_name(self, line: str) -> None: # are we cloning? before, equals, existing = line.rpartition('=') - c_basename: str | None if equals: - full_name, _, c_basename = before.partition(' as ') - full_name = full_name.strip() - c_basename = c_basename.strip() + full_name, c_basename = self.parse_function_names(before) existing = existing.strip() - if (is_legal_py_identifier(full_name) and - (not c_basename or is_legal_c_identifier(c_basename)) and - is_legal_py_identifier(existing)): + if is_legal_py_identifier(existing): # we're cloning! fields = [x.strip() for x in existing.split('.')] function_name = fields.pop() @@ -4720,13 +5272,26 @@ def state_modulename_name(self, line: str) -> None: function_name = fields.pop() module, cls = self.clinic._module_and_class(fields) - if not (existing_function.kind is self.kind and existing_function.coexist == self.coexist): - fail("'kind' of function and cloned function don't match! " - "(@classmethod/@staticmethod/@coexist)") - function = existing_function.copy( - name=function_name, full_name=full_name, module=module, - cls=cls, c_basename=c_basename, docstring='' - ) + self.update_function_kind(full_name) + overrides: dict[str, Any] = { + "name": function_name, + "full_name": full_name, + "module": module, + "cls": cls, + "c_basename": c_basename, + "docstring": "", + } + if not (existing_function.kind is self.kind and + existing_function.coexist == self.coexist): + # Allow __new__ or __init__ methods. + if existing_function.kind.new_or_init: + overrides["kind"] = self.kind + # Future enhancement: allow custom return converters + overrides["return_converter"] = CReturnConverter() + else: + fail("'kind' of function and cloned function don't match! " + "(@classmethod/@staticmethod/@coexist)") + function = existing_function.copy(**overrides) self.function = function self.block.signatures.append(function) (cls or module).functions.append(function) @@ -4735,18 +5300,12 @@ def state_modulename_name(self, line: str) -> None: line, _, returns = line.partition('->') returns = returns.strip() - - full_name, _, c_basename = line.partition(' as ') - full_name = full_name.strip() - c_basename = c_basename.strip() or None - - if not is_legal_py_identifier(full_name): - fail(f"Illegal function name: {full_name!r}") - if c_basename and not is_legal_c_identifier(c_basename): - fail(f"Illegal C basename: {c_basename!r}") + full_name, c_basename = self.parse_function_names(line) return_converter = None if returns: + if self.kind in {GETTER, SETTER}: + fail(f"@{self.kind.name.lower()} method cannot define a return type") ast_input = f"def x() -> {returns}: pass" try: module_node = ast.parse(ast_input) @@ -4768,26 +5327,21 @@ def state_modulename_name(self, line: str) -> None: function_name = fields.pop() module, cls = self.clinic._module_and_class(fields) - fields = full_name.split('.') - if fields[-1] in unsupported_special_methods: - fail(f"{fields[-1]} is a special method and cannot be converted to Argument Clinic! (Yet.)") - - if fields[-1] == '__new__': - if (self.kind is not CLASS_METHOD) or (not cls): - fail("__new__ must be a class method!") - self.kind = METHOD_NEW - elif fields[-1] == '__init__': - if (self.kind is not CALLABLE) or (not cls): - fail("__init__ must be a normal method, not a class or static method!") - self.kind = METHOD_INIT - if not return_converter: - return_converter = init_return_converter() + if self.kind in {GETTER, SETTER}: + if not cls: + fail("@getter and @setter must be methods") + + self.update_function_kind(full_name) + if self.kind is METHOD_INIT and not return_converter: + return_converter = init_return_converter() if not return_converter: return_converter = CReturnConverter() self.function = Function(name=function_name, full_name=full_name, module=module, cls=cls, c_basename=c_basename, - return_converter=return_converter, kind=self.kind, coexist=self.coexist) + return_converter=return_converter, kind=self.kind, coexist=self.coexist, + critical_section=self.critical_section, + target_critical_section=self.target_critical_section) self.block.signatures.append(self.function) # insert a self converter automatically @@ -4905,16 +5459,23 @@ def state_parameter(self, line: str) -> None: self.parameter_continuation = line[:-1] return + line = line.lstrip() + version: VersionTuple | None = None + match = self.from_version_re.fullmatch(line) + if match: + line = match[1] + version = self.parse_version(match[2]) + func = self.function - match line.lstrip(): + match line: case '*': - self.parse_star(func) + self.parse_star(func, version) case '[': self.parse_opening_square_bracket(func) case ']': self.parse_closing_square_bracket(func) case '/': - self.parse_slash(func) + self.parse_slash(func, version) case param: self.parse_parameter(param) @@ -4998,11 +5559,11 @@ def parse_parameter(self, line: str) -> None: parameter_name = parameter.arg name, legacy, kwargs = self.parse_converter(parameter.annotation) + value: object if not default: if self.parameter_state is ParamState.OPTIONAL: fail(f"Can't have a parameter without a default ({parameter_name!r}) " "after a parameter with a default!") - value: Sentinels | Null if is_vararg: value = NULL kwargs.setdefault('c_default', "NULL") @@ -5055,13 +5616,14 @@ def bad_node(self, node: ast.AST) -> None: # but at least make an attempt at ensuring it's a valid expression. try: value = eval(default) - if value is unspecified: - fail("'unspecified' is not a legal default value!") except NameError: pass # probably a named constant except Exception as e: fail("Malformed expression given as default value " f"{default!r} caused {e!r}") + else: + if value is unspecified: + fail("'unspecified' is not a legal default value!") if bad: fail(f"Unsupported expression as default value: {default!r}") @@ -5115,7 +5677,7 @@ def bad_node(self, node: ast.AST) -> None: if isinstance(value, (bool, NoneType)): c_default = "Py_" + py_default elif isinstance(value, str): - c_default = c_repr(value) + c_default = libclinic.c_repr(value) else: c_default = py_default @@ -5179,7 +5741,9 @@ def bad_node(self, node: ast.AST) -> None: "after 'self'.") - p = Parameter(parameter_name, kind, function=self.function, converter=converter, default=value, group=self.group) + p = Parameter(parameter_name, kind, function=self.function, + converter=converter, default=value, group=self.group, + deprecated_positional=self.deprecated_positional) names = [k.name for k in self.function.parameters.values()] if parameter_name in names[1:]: @@ -5212,11 +5776,43 @@ def parse_converter( "Annotations must be either a name, a function call, or a string." ) - def parse_star(self, function: Function) -> None: - """Parse keyword-only parameter marker '*'.""" - if self.keyword_only: - fail(f"Function {function.name!r} uses '*' more than once.") - self.keyword_only = True + def parse_version(self, thenceforth: str) -> VersionTuple: + """Parse Python version in `[from ...]` marker.""" + assert isinstance(self.function, Function) + + try: + major, minor = thenceforth.split(".") + return int(major), int(minor) + except ValueError: + fail( + f"Function {self.function.name!r}: expected format '[from major.minor]' " + f"where 'major' and 'minor' are integers; got {thenceforth!r}" + ) + + def parse_star(self, function: Function, version: VersionTuple | None) -> None: + """Parse keyword-only parameter marker '*'. + + The 'version' parameter signifies the future version from which + the marker will take effect (None means it is already in effect). + """ + if version is None: + if self.keyword_only: + fail(f"Function {function.name!r} uses '*' more than once.") + self.check_previous_star() + self.check_remaining_star() + self.keyword_only = True + else: + if self.keyword_only: + fail(f"Function {function.name!r}: '* [from ...]' must precede '*'") + if self.deprecated_positional: + if self.deprecated_positional == version: + fail(f"Function {function.name!r} uses '* [from " + f"{version[0]}.{version[1]}]' more than once.") + if self.deprecated_positional < version: + fail(f"Function {function.name!r}: '* [from " + f"{version[0]}.{version[1]}]' must precede '* [from " + f"{self.deprecated_positional[0]}.{self.deprecated_positional[1]}]'") + self.deprecated_positional = version def parse_opening_square_bracket(self, function: Function) -> None: """Parse opening parameter group symbol '['.""" @@ -5250,11 +5846,44 @@ def parse_closing_square_bracket(self, function: Function) -> None: f"has an unsupported group configuration. " f"(Unexpected state {st}.c)") - def parse_slash(self, function: Function) -> None: - """Parse positional-only parameter marker '/'.""" - if self.positional_only: - fail(f"Function {function.name!r} uses '/' more than once.") + def parse_slash(self, function: Function, version: VersionTuple | None) -> None: + """Parse positional-only parameter marker '/'. + + The 'version' parameter signifies the future version from which + the marker will take effect (None means it is already in effect). + """ + if version is None: + if self.deprecated_keyword: + fail(f"Function {function.name!r}: '/' must precede '/ [from ...]'") + if self.deprecated_positional: + fail(f"Function {function.name!r}: '/' must precede '* [from ...]'") + if self.keyword_only: + fail(f"Function {function.name!r}: '/' must precede '*'") + if self.positional_only: + fail(f"Function {function.name!r} uses '/' more than once.") + else: + if self.deprecated_keyword: + if self.deprecated_keyword == version: + fail(f"Function {function.name!r} uses '/ [from " + f"{version[0]}.{version[1]}]' more than once.") + if self.deprecated_keyword > version: + fail(f"Function {function.name!r}: '/ [from " + f"{version[0]}.{version[1]}]' must precede '/ [from " + f"{self.deprecated_keyword[0]}.{self.deprecated_keyword[1]}]'") + if self.deprecated_positional: + fail(f"Function {function.name!r}: '/ [from ...]' must precede '* [from ...]'") + if self.keyword_only: + fail(f"Function {function.name!r}: '/ [from ...]' must precede '*'") self.positional_only = True + self.deprecated_keyword = version + if version is not None: + found = False + for p in reversed(function.parameters.values()): + found = p.kind is inspect.Parameter.POSITIONAL_OR_KEYWORD + break + if not found: + fail(f"Function {function.name!r} specifies '/ [from ...]' " + f"without preceding parameters.") # REQUIRED and OPTIONAL are allowed here, that allows positional-only # without option groups to work (and have default values!) allowed = { @@ -5266,19 +5895,13 @@ def parse_slash(self, function: Function) -> None: if (self.parameter_state not in allowed) or self.group: fail(f"Function {function.name!r} has an unsupported group configuration. " f"(Unexpected state {self.parameter_state}.d)") - if self.keyword_only: - fail(f"Function {function.name!r} mixes keyword-only and " - "positional-only parameters, which is unsupported.") # fixup preceding parameters for p in function.parameters.values(): - if p.is_vararg(): - continue - if (p.kind is not inspect.Parameter.POSITIONAL_OR_KEYWORD and - not isinstance(p.converter, self_converter) - ): - fail(f"Function {function.name!r} mixes keyword-only and " - "positional-only parameters, which is unsupported.") - p.kind = inspect.Parameter.POSITIONAL_ONLY + if p.kind is inspect.Parameter.POSITIONAL_OR_KEYWORD: + if version is None: + p.kind = inspect.Parameter.POSITIONAL_ONLY + elif p.deprecated_keyword is None: + p.deprecated_keyword = version def state_parameter_docstring_start(self, line: str) -> None: assert self.indent.margin is not None, "self.margin.infer() has not yet been called to set the margin" @@ -5288,6 +5911,11 @@ def state_parameter_docstring_start(self, line: str) -> None: def docstring_append(self, obj: Function | Parameter, line: str) -> None: """Add a rstripped line to the current docstring.""" + # gh-80282: We filter out non-ASCII characters from the docstring, + # since historically, some compilers may balk on non-ASCII input. + # If you're using Argument Clinic in an external project, + # you may not need to support the same array of platforms as CPython, + # so you may be able to remove this restriction. matches = re.finditer(r'[^\x00-\x7F]', line) if offending := ", ".join([repr(m[0]) for m in matches]): warn("Non-ascii characters are not allowed in docstrings:", @@ -5333,165 +5961,152 @@ def state_function_docstring(self, line: str) -> None: self.docstring_append(self.function, line) - def format_docstring(self) -> str: - f = self.function - assert f is not None - - new_or_init = f.kind.new_or_init - if new_or_init and not f.docstring: - # don't render a docstring at all, no signature, nothing. - return f.docstring - - text, add, output = _text_accumulator() - parameters = f.render_parameters - - ## - ## docstring first line - ## - - if new_or_init: - # classes get *just* the name of the class - # not __new__, not __init__, and not module.classname - assert f.cls - add(f.cls.name) + def format_docstring_signature( + self, f: Function, parameters: list[Parameter] + ) -> str: + lines = [] + lines.append(f.displayname) + if self.forced_text_signature: + lines.append(self.forced_text_signature) + elif f.kind in {GETTER, SETTER}: + # @getter and @setter do not need signatures like a method or a function. + return '' else: - add(f.name) - add('(') - - # populate "right_bracket_count" field for every parameter - assert parameters, "We should always have a self parameter. " + repr(f) - assert isinstance(parameters[0].converter, self_converter) - # self is always positional-only. - assert parameters[0].is_positional_only() - assert parameters[0].right_bracket_count == 0 - positional_only = True - for p in parameters[1:]: - if not p.is_positional_only(): - positional_only = False - else: - assert positional_only - if positional_only: - p.right_bracket_count = abs(p.group) - else: - # don't put any right brackets around non-positional-only parameters, ever. - p.right_bracket_count = 0 - - right_bracket_count = 0 - - def fix_right_bracket_count(desired: int) -> str: - nonlocal right_bracket_count - s = '' - while right_bracket_count < desired: - s += '[' - right_bracket_count += 1 - while right_bracket_count > desired: - s += ']' - right_bracket_count -= 1 - return s - - need_slash = False - added_slash = False - need_a_trailing_slash = False - - # we only need a trailing slash: - # * if this is not a "docstring_only" signature - # * and if the last *shown* parameter is - # positional only - if not f.docstring_only: - for p in reversed(parameters): - if not p.converter.show_in_signature: - continue - if p.is_positional_only(): - need_a_trailing_slash = True - break + lines.append('(') + + # populate "right_bracket_count" field for every parameter + assert parameters, "We should always have a self parameter. " + repr(f) + assert isinstance(parameters[0].converter, self_converter) + # self is always positional-only. + assert parameters[0].is_positional_only() + assert parameters[0].right_bracket_count == 0 + positional_only = True + for p in parameters[1:]: + if not p.is_positional_only(): + positional_only = False + else: + assert positional_only + if positional_only: + p.right_bracket_count = abs(p.group) + else: + # don't put any right brackets around non-positional-only parameters, ever. + p.right_bracket_count = 0 + + right_bracket_count = 0 + + def fix_right_bracket_count(desired: int) -> str: + nonlocal right_bracket_count + s = '' + while right_bracket_count < desired: + s += '[' + right_bracket_count += 1 + while right_bracket_count > desired: + s += ']' + right_bracket_count -= 1 + return s + + need_slash = False + added_slash = False + need_a_trailing_slash = False + + # we only need a trailing slash: + # * if this is not a "docstring_only" signature + # * and if the last *shown* parameter is + # positional only + if not f.docstring_only: + for p in reversed(parameters): + if not p.converter.show_in_signature: + continue + if p.is_positional_only(): + need_a_trailing_slash = True + break - added_star = False + added_star = False - first_parameter = True - last_p = parameters[-1] - line_length = len(''.join(text)) - indent = " " * line_length - def add_parameter(text: str) -> None: - nonlocal line_length - nonlocal first_parameter - if first_parameter: - s = text - first_parameter = False - else: - s = ' ' + text - if line_length + len(s) >= 72: - add('\n') - add(indent) - line_length = len(indent) + first_parameter = True + last_p = parameters[-1] + line_length = len(''.join(lines)) + indent = " " * line_length + def add_parameter(text: str) -> None: + nonlocal line_length + nonlocal first_parameter + if first_parameter: s = text - line_length += len(s) - add(s) - - for p in parameters: - if not p.converter.show_in_signature: - continue - assert p.name + first_parameter = False + else: + s = ' ' + text + if line_length + len(s) >= 72: + lines.extend(["\n", indent]) + line_length = len(indent) + s = text + line_length += len(s) + lines.append(s) + + for p in parameters: + if not p.converter.show_in_signature: + continue + assert p.name - is_self = isinstance(p.converter, self_converter) - if is_self and f.docstring_only: - # this isn't a real machine-parsable signature, - # so let's not print the "self" parameter - continue + is_self = isinstance(p.converter, self_converter) + if is_self and f.docstring_only: + # this isn't a real machine-parsable signature, + # so let's not print the "self" parameter + continue - if p.is_positional_only(): - need_slash = not f.docstring_only - elif need_slash and not (added_slash or p.is_positional_only()): - added_slash = True - add_parameter('/,') - - if p.is_keyword_only() and not added_star: - added_star = True - add_parameter('*,') - - p_add, p_output = text_accumulator() - p_add(fix_right_bracket_count(p.right_bracket_count)) - - if isinstance(p.converter, self_converter): - # annotate first parameter as being a "self". - # - # if inspect.Signature gets this function, - # and it's already bound, the self parameter - # will be stripped off. - # - # if it's not bound, it should be marked - # as positional-only. - # - # note: we don't print "self" for __init__, - # because this isn't actually the signature - # for __init__. (it can't be, __init__ doesn't - # have a docstring.) if this is an __init__ - # (or __new__), then this signature is for - # calling the class to construct a new instance. - p_add('$') + if p.is_positional_only(): + need_slash = not f.docstring_only + elif need_slash and not (added_slash or p.is_positional_only()): + added_slash = True + add_parameter('/,') + + if p.is_keyword_only() and not added_star: + added_star = True + add_parameter('*,') + + p_lines = [fix_right_bracket_count(p.right_bracket_count)] + + if isinstance(p.converter, self_converter): + # annotate first parameter as being a "self". + # + # if inspect.Signature gets this function, + # and it's already bound, the self parameter + # will be stripped off. + # + # if it's not bound, it should be marked + # as positional-only. + # + # note: we don't print "self" for __init__, + # because this isn't actually the signature + # for __init__. (it can't be, __init__ doesn't + # have a docstring.) if this is an __init__ + # (or __new__), then this signature is for + # calling the class to construct a new instance. + p_lines.append('$') - if p.is_vararg(): - p_add("*") + if p.is_vararg(): + p_lines.append("*") - name = p.converter.signature_name or p.name - p_add(name) + name = p.converter.signature_name or p.name + p_lines.append(name) - if not p.is_vararg() and p.converter.is_optional(): - p_add('=') - value = p.converter.py_default - if not value: - value = repr(p.converter.default) - p_add(value) + if not p.is_vararg() and p.converter.is_optional(): + p_lines.append('=') + value = p.converter.py_default + if not value: + value = repr(p.converter.default) + p_lines.append(value) - if (p != last_p) or need_a_trailing_slash: - p_add(',') + if (p != last_p) or need_a_trailing_slash: + p_lines.append(',') - add_parameter(p_output()) + p_output = "".join(p_lines) + add_parameter(p_output) - add(fix_right_bracket_count(0)) - if need_a_trailing_slash: - add_parameter('/') - add(')') + lines.append(fix_right_bracket_count(0)) + if need_a_trailing_slash: + add_parameter('/') + lines.append(')') # PEP 8 says: # @@ -5503,41 +6118,28 @@ def add_parameter(text: str) -> None: # therefore this is commented out: # # if f.return_converter.py_default: - # add(' -> ') - # add(f.return_converter.py_default) + # lines.append(' -> ') + # lines.append(f.return_converter.py_default) if not f.docstring_only: - add("\n" + sig_end_marker + "\n") + lines.append("\n" + libclinic.SIG_END_MARKER + "\n") - docstring_first_line = output() + signature_line = "".join(lines) # now fix up the places where the brackets look wrong - docstring_first_line = docstring_first_line.replace(', ]', ',] ') + return signature_line.replace(', ]', ',] ') - # okay. now we're officially building the "parameters" section. - # create substitution text for {parameters} - spacer_line = False - for p in parameters: - if not p.docstring.strip(): - continue - if spacer_line: - add('\n') - else: - spacer_line = True - add(" ") - add(p.name) - add('\n') - add(textwrap.indent(rstrip_lines(p.docstring.rstrip()), " ")) - parameters_output = output() - if parameters_output: - parameters_output += '\n' - - ## - ## docstring body - ## - - docstring = f.docstring.rstrip() - lines = [line.rstrip() for line in docstring.split('\n')] + @staticmethod + def format_docstring_parameters(params: list[Parameter]) -> str: + """Create substitution text for {parameters}""" + return "".join(p.render_docstring() + "\n" for p in params if p.docstring) + + def format_docstring(self) -> str: + assert self.function is not None + f = self.function + # For the following special cases, it does not make sense to render a docstring. + if f.kind in {METHOD_INIT, METHOD_NEW, GETTER, SETTER} and not f.docstring: + return f.docstring # Enforce the summary line! # The first line of a docstring should be a summary of the function. @@ -5551,6 +6153,7 @@ def add_parameter(text: str) -> None: # Guido said Clinic should enforce this: # http://mail.python.org/pipermail/python-dev/2013-June/127110.html + lines = f.docstring.split('\n') if len(lines) >= 2: if lines[1]: fail(f"Docstring for {f.full_name!r} does not have a summary line!\n" @@ -5562,45 +6165,62 @@ def add_parameter(text: str) -> None: # between it and the {parameters} we're about to add. lines.append('') - parameters_marker_count = len(docstring.split('{parameters}')) - 1 + parameters_marker_count = len(f.docstring.split('{parameters}')) - 1 if parameters_marker_count > 1: fail('You may not specify {parameters} more than once in a docstring!') + # insert signature at front and params after the summary line if not parameters_marker_count: - # insert after summary line lines.insert(2, '{parameters}') + lines.insert(0, '{signature}') - # insert at front of docstring - lines.insert(0, docstring_first_line) - + # finalize docstring + params = f.render_parameters + parameters = self.format_docstring_parameters(params) + signature = self.format_docstring_signature(f, params) docstring = "\n".join(lines) + return linear_format(docstring, + signature=signature, + parameters=parameters).rstrip() + + def check_remaining_star(self, lineno: int | None = None) -> None: + assert isinstance(self.function, Function) + + if self.keyword_only: + symbol = '*' + elif self.deprecated_positional: + symbol = '* [from ...]' + else: + return - add(docstring) - docstring = output() + for p in reversed(self.function.parameters.values()): + if self.keyword_only: + if p.kind == inspect.Parameter.KEYWORD_ONLY: + return + elif self.deprecated_positional: + if p.deprecated_positional == self.deprecated_positional: + return + break - docstring = linear_format(docstring, parameters=parameters_output) - docstring = docstring.rstrip() + fail(f"Function {self.function.name!r} specifies {symbol!r} " + f"without following parameters.", line_number=lineno) - return docstring + def check_previous_star(self, lineno: int | None = None) -> None: + assert isinstance(self.function, Function) - def do_post_block_processing_cleanup(self) -> None: + for p in self.function.parameters.values(): + if p.kind == inspect.Parameter.VAR_POSITIONAL: + fail(f"Function {self.function.name!r} uses '*' more than once.") + + + def do_post_block_processing_cleanup(self, lineno: int) -> None: """ Called when processing the block is done. """ if not self.function: return - if self.keyword_only: - values = self.function.parameters.values() - if not values: - no_parameter_after_star = True - else: - last_parameter = next(reversed(list(values))) - no_parameter_after_star = last_parameter.kind != inspect.Parameter.KEYWORD_ONLY - if no_parameter_after_star: - fail(f"Function {self.function.name!r} specifies '*' " - "without any parameters afterwards.") - + self.check_remaining_star(lineno) self.function.docstring = self.format_docstring() @@ -5621,9 +6241,6 @@ def do_post_block_processing_cleanup(self) -> None: } -clinic = None - - def create_cli() -> argparse.ArgumentParser: cmdline = argparse.ArgumentParser( prog="clinic.py", @@ -5633,7 +6250,7 @@ def create_cli() -> argparse.ArgumentParser: with writing argument parsing code for builtins and providing introspection signatures ("docstrings") for CPython builtins. -For more information see https://docs.python.org/3/howto/clinic.html""") +For more information see https://devguide.python.org/development-tools/clinic/""") cmdline.add_argument("-f", "--force", action='store_true', help="force output regeneration") cmdline.add_argument("-o", "--output", type=str, @@ -5647,6 +6264,11 @@ def create_cli() -> argparse.ArgumentParser: help="walk --srcdir to run over all relevant files") cmdline.add_argument("--srcdir", type=str, default=os.curdir, help="the directory tree to walk in --make mode") + cmdline.add_argument("--exclude", type=str, action="append", + help=("a file to exclude in --make mode; " + "can be given multiple times")) + cmdline.add_argument("--limited", dest="limited_capi", action='store_true', + help="use the Limited C API") cmdline.add_argument("filename", metavar="FILE", type=str, nargs="*", help="the list of files to process") return cmdline @@ -5718,6 +6340,11 @@ def run_clinic(parser: argparse.ArgumentParser, ns: argparse.Namespace) -> None: parser.error("can't use -o or filenames with --make") if not ns.srcdir: parser.error("--srcdir must not be empty with --make") + if ns.exclude: + excludes = [os.path.join(ns.srcdir, f) for f in ns.exclude] + excludes = [os.path.normpath(f) for f in excludes] + else: + excludes = [] for root, dirs, files in os.walk(ns.srcdir): for rcs_dir in ('.svn', '.git', '.hg', 'build', 'externals'): if rcs_dir in dirs: @@ -5727,9 +6354,13 @@ def run_clinic(parser: argparse.ArgumentParser, ns: argparse.Namespace) -> None: if not filename.endswith(('.c', '.cpp', '.h')): continue path = os.path.join(root, filename) + path = os.path.normpath(path) + if path in excludes: + continue if ns.verbose: print(path) - parse_file(path, verify=not ns.force) + parse_file(path, + verify=not ns.force, limited_capi=ns.limited_capi) return if not ns.filename: @@ -5741,7 +6372,8 @@ def run_clinic(parser: argparse.ArgumentParser, ns: argparse.Namespace) -> None: for filename in ns.filename: if ns.verbose: print(filename) - parse_file(filename, output=ns.output, verify=not ns.force) + parse_file(filename, output=ns.output, + verify=not ns.force, limited_capi=ns.limited_capi) def main(argv: list[str] | None = None) -> NoReturn: diff --git a/Tools/clinic/libclinic/__init__.py b/Tools/clinic/libclinic/__init__.py new file mode 100644 index 00000000000000..d4e7a0c5cf7b76 --- /dev/null +++ b/Tools/clinic/libclinic/__init__.py @@ -0,0 +1,52 @@ +from typing import Final + +from .errors import ( + ClinicError, +) +from .formatting import ( + SIG_END_MARKER, + c_repr, + docstring_for_c_string, + format_escape, + indent_all_lines, + normalize_snippet, + pprint_words, + suffix_all_lines, + wrap_declarations, + wrapped_c_string_literal, +) + + +__all__ = [ + # Error handling + "ClinicError", + + # Formatting helpers + "SIG_END_MARKER", + "c_repr", + "docstring_for_c_string", + "format_escape", + "indent_all_lines", + "normalize_snippet", + "pprint_words", + "suffix_all_lines", + "wrap_declarations", + "wrapped_c_string_literal", +] + + +CLINIC_PREFIX: Final = "__clinic_" +CLINIC_PREFIXED_ARGS: Final = frozenset( + { + "_keywords", + "_parser", + "args", + "argsbuf", + "fastargs", + "kwargs", + "kwnames", + "nargs", + "noptargs", + "return_value", + } +) diff --git a/Tools/clinic/cpp.py b/Tools/clinic/libclinic/cpp.py similarity index 88% rename from Tools/clinic/cpp.py rename to Tools/clinic/libclinic/cpp.py index 876105120c97f2..e115d65a88e1b6 100644 --- a/Tools/clinic/cpp.py +++ b/Tools/clinic/libclinic/cpp.py @@ -3,6 +3,11 @@ import sys from typing import NoReturn +from .errors import ParseError + + +__all__ = ["Monitor"] + TokenAndCondition = tuple[str, str] TokenStack = list[TokenAndCondition] @@ -32,7 +37,7 @@ class Monitor: Anyway this implementation seems to work well enough for the CPython sources. """ - filename: str | None = None + filename: str _: dc.KW_ONLY verbose: bool = False @@ -59,14 +64,8 @@ def condition(self) -> str: """ return " && ".join(condition for token, condition in self.stack) - def fail(self, *a: object) -> NoReturn: - if self.filename: - filename = " " + self.filename - else: - filename = '' - print("Error at" + filename, "line", self.line_number, ":") - print(" ", ' '.join(str(x) for x in a)) - sys.exit(-1) + def fail(self, msg: str) -> NoReturn: + raise ParseError(msg, filename=self.filename, lineno=self.line_number) def writeline(self, line: str) -> None: self.line_number += 1 @@ -74,7 +73,7 @@ def writeline(self, line: str) -> None: def pop_stack() -> TokenAndCondition: if not self.stack: - self.fail("#" + token + " without matching #if / #ifdef / #ifndef!") + self.fail(f"#{token} without matching #if / #ifdef / #ifndef!") return self.stack.pop() if self.continuation: @@ -145,7 +144,7 @@ def pop_stack() -> TokenAndCondition: if token in {'if', 'ifdef', 'ifndef', 'elif'}: if not condition: - self.fail("Invalid format for #" + token + " line: no argument!") + self.fail(f"Invalid format for #{token} line: no argument!") if token in {'if', 'elif'}: if not is_a_simple_defined(condition): condition = "(" + condition + ")" @@ -155,7 +154,8 @@ def pop_stack() -> TokenAndCondition: else: fields = condition.split() if len(fields) != 1: - self.fail("Invalid format for #" + token + " line: should be exactly one argument!") + self.fail(f"Invalid format for #{token} line: " + "should be exactly one argument!") symbol = fields[0] condition = 'defined(' + symbol + ')' if token == 'ifndef': @@ -178,11 +178,17 @@ def pop_stack() -> TokenAndCondition: if self.verbose: print(self.status()) -if __name__ == '__main__': - for filename in sys.argv[1:]: + +def _main(filenames: list[str] | None = None) -> None: + filenames = filenames or sys.argv[1:] + for filename in filenames: with open(filename) as f: cpp = Monitor(filename, verbose=True) print() print(filename) - for line_number, line in enumerate(f.read().split('\n'), 1): + for line in f: cpp.writeline(line) + + +if __name__ == '__main__': + _main() diff --git a/Tools/clinic/libclinic/errors.py b/Tools/clinic/libclinic/errors.py new file mode 100644 index 00000000000000..afb21b02386fe7 --- /dev/null +++ b/Tools/clinic/libclinic/errors.py @@ -0,0 +1,26 @@ +import dataclasses as dc + + +@dc.dataclass +class ClinicError(Exception): + message: str + _: dc.KW_ONLY + lineno: int | None = None + filename: str | None = None + + def __post_init__(self) -> None: + super().__init__(self.message) + + def report(self, *, warn_only: bool = False) -> str: + msg = "Warning" if warn_only else "Error" + if self.filename is not None: + msg += f" in file {self.filename!r}" + if self.lineno is not None: + msg += f" on line {self.lineno}" + msg += ":\n" + msg += f"{self.message}\n" + return msg + + +class ParseError(ClinicError): + pass diff --git a/Tools/clinic/libclinic/formatting.py b/Tools/clinic/libclinic/formatting.py new file mode 100644 index 00000000000000..8b3ad7ba566bc8 --- /dev/null +++ b/Tools/clinic/libclinic/formatting.py @@ -0,0 +1,173 @@ +"""A collection of string formatting helpers.""" + +import functools +import textwrap +from typing import Final + + +SIG_END_MARKER: Final = "--" + + +def docstring_for_c_string(docstring: str) -> str: + lines = [] + # Turn docstring into a properly quoted C string. + for line in docstring.split("\n"): + lines.append('"') + lines.append(_quoted_for_c_string(line)) + lines.append('\\n"\n') + + if lines[-2] == SIG_END_MARKER: + # If we only have a signature, add the blank line that the + # __text_signature__ getter expects to be there. + lines.append('"\\n"') + else: + lines.pop() + lines.append('"') + return "".join(lines) + + +def _quoted_for_c_string(text: str) -> str: + """Helper for docstring_for_c_string().""" + for old, new in ( + ("\\", "\\\\"), # must be first! + ('"', '\\"'), + ("'", "\\'"), + ): + text = text.replace(old, new) + return text + + +def c_repr(text: str) -> str: + return '"' + text + '"' + + +def wrapped_c_string_literal( + text: str, + *, + width: int = 72, + suffix: str = "", + initial_indent: int = 0, + subsequent_indent: int = 4 +) -> str: + wrapped = textwrap.wrap( + text, + width=width, + replace_whitespace=False, + drop_whitespace=False, + break_on_hyphens=False, + ) + separator = c_repr(suffix + "\n" + subsequent_indent * " ") + return initial_indent * " " + c_repr(separator.join(wrapped)) + + +def _add_prefix_and_suffix(text: str, *, prefix: str = "", suffix: str = "") -> str: + """Return 'text' with 'prefix' prepended and 'suffix' appended to all lines. + + If the last line is empty, it remains unchanged. + If text is blank, return text unchanged. + + (textwrap.indent only adds to non-blank lines.) + """ + *split, last = text.split("\n") + lines = [prefix + line + suffix + "\n" for line in split] + if last: + lines.append(prefix + last + suffix) + return "".join(lines) + + +def indent_all_lines(text: str, prefix: str) -> str: + return _add_prefix_and_suffix(text, prefix=prefix) + + +def suffix_all_lines(text: str, suffix: str) -> str: + return _add_prefix_and_suffix(text, suffix=suffix) + + +def pprint_words(items: list[str]) -> str: + if len(items) <= 2: + return " and ".join(items) + return ", ".join(items[:-1]) + " and " + items[-1] + + +def _strip_leading_and_trailing_blank_lines(text: str) -> str: + lines = text.rstrip().split("\n") + while lines: + line = lines[0] + if line.strip(): + break + del lines[0] + return "\n".join(lines) + + +@functools.lru_cache() +def normalize_snippet(text: str, *, indent: int = 0) -> str: + """ + Reformats 'text': + * removes leading and trailing blank lines + * ensures that it does not end with a newline + * dedents so the first nonwhite character on any line is at column "indent" + """ + text = _strip_leading_and_trailing_blank_lines(text) + text = textwrap.dedent(text) + if indent: + text = textwrap.indent(text, " " * indent) + return text + + +def format_escape(text: str) -> str: + # double up curly-braces, this string will be used + # as part of a format_map() template later + text = text.replace("{", "{{") + text = text.replace("}", "}}") + return text + + +def wrap_declarations(text: str, length: int = 78) -> str: + """ + A simple-minded text wrapper for C function declarations. + + It views a declaration line as looking like this: + xxxxxxxx(xxxxxxxxx,xxxxxxxxx) + If called with length=30, it would wrap that line into + xxxxxxxx(xxxxxxxxx, + xxxxxxxxx) + (If the declaration has zero or one parameters, this + function won't wrap it.) + + If this doesn't work properly, it's probably better to + start from scratch with a more sophisticated algorithm, + rather than try and improve/debug this dumb little function. + """ + lines = [] + for line in text.split("\n"): + prefix, _, after_l_paren = line.partition("(") + if not after_l_paren: + lines.append(line) + continue + in_paren, _, after_r_paren = after_l_paren.partition(")") + if not _: + lines.append(line) + continue + if "," not in in_paren: + lines.append(line) + continue + parameters = [x.strip() + ", " for x in in_paren.split(",")] + prefix += "(" + if len(prefix) < length: + spaces = " " * len(prefix) + else: + spaces = " " * 4 + + while parameters: + line = prefix + first = True + while parameters: + if not first and (len(line) + len(parameters[0]) > length): + break + line += parameters.pop(0) + first = False + if not parameters: + line = line.rstrip(", ") + ")" + after_r_paren + lines.append(line.rstrip()) + prefix = spaces + return "\n".join(lines) diff --git a/Tools/clinic/requirements-dev.txt b/Tools/clinic/requirements-dev.txt deleted file mode 100644 index e9529f3527e95e..00000000000000 --- a/Tools/clinic/requirements-dev.txt +++ /dev/null @@ -1,2 +0,0 @@ -# Requirements file for external linters and checks we run on Tools/clinic/ in CI -mypy==1.4.1 diff --git a/Tools/freeze/README b/Tools/freeze/README index 9b3ea1f2c723b1..516077bc7daa89 100644 --- a/Tools/freeze/README +++ b/Tools/freeze/README @@ -218,6 +218,11 @@ source tree). It is possible to create frozen programs that don't have a console window, by specifying the option '-s windows'. See the Usage below. +Usage under macOS +----------------- + +On macOS the freeze tool is not supported for framework builds. + Usage ----- diff --git a/Tools/freeze/freeze.py b/Tools/freeze/freeze.py index bc5e43f4853deb..de9772732cdb5d 100755 --- a/Tools/freeze/freeze.py +++ b/Tools/freeze/freeze.py @@ -136,6 +136,11 @@ def main(): makefile = 'Makefile' subsystem = 'console' + if sys.platform == "darwin" and sysconfig.get_config_var("PYTHONFRAMEWORK"): + print(f"{sys.argv[0]} cannot be used with framework builds of Python", file=sys.stderr) + sys.exit(1) + + # parse command line by first replacing any "-i" options with the # file contents. pos = 1 diff --git a/Tools/freeze/test/freeze.py b/Tools/freeze/test/freeze.py index 92e97cb261719c..1e3687dbb807a6 100644 --- a/Tools/freeze/test/freeze.py +++ b/Tools/freeze/test/freeze.py @@ -1,14 +1,22 @@ import os import os.path -import re import shlex import shutil import subprocess +import sysconfig +from test import support + + +def get_python_source_dir(): + src_dir = sysconfig.get_config_var('abs_srcdir') + if not src_dir: + src_dir = sysconfig.get_config_var('srcdir') + return os.path.abspath(src_dir) TESTS_DIR = os.path.dirname(__file__) TOOL_ROOT = os.path.dirname(TESTS_DIR) -SRCDIR = os.path.dirname(os.path.dirname(TOOL_ROOT)) +SRCDIR = get_python_source_dir() MAKE = shutil.which('make') FREEZE = os.path.join(TOOL_ROOT, 'freeze.py') @@ -19,8 +27,10 @@ class UnsupportedError(Exception): """The operation isn't supported.""" -def _run_quiet(cmd, cwd=None): - #print(f'# {" ".join(shlex.quote(a) for a in cmd)}') +def _run_quiet(cmd, *, cwd=None): + if cwd: + print('+', 'cd', cwd, flush=True) + print('+', shlex.join(cmd), flush=True) try: return subprocess.run( cmd, @@ -40,8 +50,8 @@ def _run_quiet(cmd, cwd=None): raise -def _run_stdout(cmd, cwd=None): - proc = _run_quiet(cmd, cwd) +def _run_stdout(cmd): + proc = _run_quiet(cmd) return proc.stdout.strip() @@ -75,60 +85,26 @@ def ensure_opt(args, name, value): def copy_source_tree(newroot, oldroot): - print(f'copying the source tree into {newroot}...') + print(f'copying the source tree from {oldroot} to {newroot}...') if os.path.exists(newroot): if newroot == SRCDIR: raise Exception('this probably isn\'t what you wanted') shutil.rmtree(newroot) - def ignore_non_src(src, names): - """Turns what could be a 1000M copy into a 100M copy.""" - # Don't copy the ~600M+ of needless git repo metadata. - # source only, ignore cached .pyc files. - subdirs_to_skip = {'.git', '__pycache__'} - if os.path.basename(src) == 'Doc': - # Another potential ~250M+ of non test related data. - subdirs_to_skip.add('build') - subdirs_to_skip.add('venv') - return subdirs_to_skip - - shutil.copytree(oldroot, newroot, ignore=ignore_non_src) + shutil.copytree(oldroot, newroot, ignore=support.copy_python_src_ignore) if os.path.exists(os.path.join(newroot, 'Makefile')): - _run_quiet([MAKE, 'clean'], newroot) - - -def get_makefile_var(builddir, name): - regex = re.compile(rf'^{name} *=\s*(.*?)\s*$') - filename = os.path.join(builddir, 'Makefile') - try: - infile = open(filename, encoding='utf-8') - except FileNotFoundError: - return None - with infile: - for line in infile: - m = regex.match(line) - if m: - value, = m.groups() - return value or '' - return None - - -def get_config_var(builddir, name): - python = os.path.join(builddir, 'python') - if os.path.isfile(python): - cmd = [python, '-c', - f'import sysconfig; print(sysconfig.get_config_var("{name}"))'] - try: - return _run_stdout(cmd) - except subprocess.CalledProcessError: - pass - return get_makefile_var(builddir, name) + # Out-of-tree builds require a clean srcdir. "make clean" keeps + # the "python" program, so use "make distclean" instead. + _run_quiet([MAKE, 'distclean'], cwd=newroot) ################################## # freezing def prepare(script=None, outdir=None): + print() + print("cwd:", os.getcwd()) + if not outdir: outdir = OUTDIR os.makedirs(outdir, exist_ok=True) @@ -151,37 +127,33 @@ def prepare(script=None, outdir=None): # Run configure. print(f'configuring python in {builddir}...') - cmd = [ - os.path.join(srcdir, 'configure'), - *shlex.split(get_config_var(SRCDIR, 'CONFIG_ARGS') or ''), - ] + config_args = shlex.split(sysconfig.get_config_var('CONFIG_ARGS') or '') + cmd = [os.path.join(srcdir, 'configure'), *config_args] ensure_opt(cmd, 'cache-file', os.path.join(outdir, 'python-config.cache')) prefix = os.path.join(outdir, 'python-installation') ensure_opt(cmd, 'prefix', prefix) - _run_quiet(cmd, builddir) + _run_quiet(cmd, cwd=builddir) if not MAKE: raise UnsupportedError('make') - cores = os.cpu_count() + cores = os.process_cpu_count() if cores and cores >= 3: # this test is most often run as part of the whole suite with a lot # of other tests running in parallel, from 1-2 vCPU systems up to # people's NNN core beasts. Don't attempt to use it all. - parallel = f'-j{cores*2//3}' + jobs = cores * 2 // 3 + parallel = f'-j{jobs}' else: parallel = '-j2' # Build python. print(f'building python {parallel=} in {builddir}...') - if os.path.exists(os.path.join(srcdir, 'Makefile')): - # Out-of-tree builds require a clean srcdir. - _run_quiet([MAKE, '-C', srcdir, 'clean']) - _run_quiet([MAKE, '-C', builddir, parallel]) + _run_quiet([MAKE, parallel], cwd=builddir) # Install the build. print(f'installing python into {prefix}...') - _run_quiet([MAKE, '-C', builddir, 'install']) + _run_quiet([MAKE, 'install'], cwd=builddir) python = os.path.join(prefix, 'bin', 'python3') return outdir, scriptfile, python @@ -194,8 +166,8 @@ def freeze(python, scriptfile, outdir): print(f'freezing {scriptfile}...') os.makedirs(outdir, exist_ok=True) # Use -E to ignore PYTHONSAFEPATH - _run_quiet([python, '-E', FREEZE, '-o', outdir, scriptfile], outdir) - _run_quiet([MAKE, '-C', os.path.dirname(scriptfile)]) + _run_quiet([python, '-E', FREEZE, '-o', outdir, scriptfile], cwd=outdir) + _run_quiet([MAKE], cwd=os.path.dirname(scriptfile)) name = os.path.basename(scriptfile).rpartition('.')[0] executable = os.path.join(outdir, name) diff --git a/Tools/gdb/libpython.py b/Tools/gdb/libpython.py index 78b0c08d25ab01..5ef55524c11be2 100755 --- a/Tools/gdb/libpython.py +++ b/Tools/gdb/libpython.py @@ -1065,9 +1065,9 @@ def _f_nlocalsplus(self): def _f_lasti(self): codeunit_p = gdb.lookup_type("_Py_CODEUNIT").pointer() - prev_instr = self._gdbval["prev_instr"] + instr_ptr = self._gdbval["instr_ptr"] first_instr = self._f_code().field("co_code_adaptive").cast(codeunit_p) - return int(prev_instr - first_instr) + return int(instr_ptr - first_instr) def is_shim(self): return self._f_special("owner", int) == FRAME_OWNED_BY_CSTACK diff --git a/Tools/importbench/importbench.py b/Tools/importbench/importbench.py index 0c4b3bc73517c5..eb101fe616c587 100644 --- a/Tools/importbench/importbench.py +++ b/Tools/importbench/importbench.py @@ -165,8 +165,8 @@ def using_bytecode_benchmark(seconds, repeat): def main(import_, options): if options.source_file: - with options.source_file: - prev_results = json.load(options.source_file) + with open(options.source_file, 'r', encoding='utf-8') as source_file: + prev_results = json.load(source_file) else: prev_results = {} __builtins__.__import__ = import_ @@ -218,8 +218,8 @@ def main(import_, options): new_result/old_result) print(benchmark_name, ':', result) if options.dest_file: - with options.dest_file: - json.dump(new_results, options.dest_file, indent=2) + with open(options.dest_file, 'w', encoding='utf-8') as dest_file: + json.dump(new_results, dest_file, indent=2) if __name__ == '__main__': @@ -229,11 +229,9 @@ def main(import_, options): parser.add_argument('-b', '--builtin', dest='builtin', action='store_true', default=False, help="use the built-in __import__") parser.add_argument('-r', '--read', dest='source_file', - type=argparse.FileType('r'), help='file to read benchmark data from to compare ' 'against') parser.add_argument('-w', '--write', dest='dest_file', - type=argparse.FileType('w'), help='file to write benchmark data to') parser.add_argument('--benchmark', dest='benchmark', help='specific benchmark to run') diff --git a/Tools/lockbench/lockbench.py b/Tools/lockbench/lockbench.py new file mode 100644 index 00000000000000..9833d703e00cbb --- /dev/null +++ b/Tools/lockbench/lockbench.py @@ -0,0 +1,53 @@ +# Measure the performance of PyMutex and PyThread_type_lock locks +# with short critical sections. +# +# Usage: python Tools/lockbench/lockbench.py [CRITICAL_SECTION_LENGTH] +# +# How to interpret the results: +# +# Acquisitions (kHz): Reports the total number of lock acquisitions in +# thousands of acquisitions per second. This is the most important metric, +# particularly for the 1 thread case because even in multithreaded programs, +# most locks acquisitions are not contended. Values for 2+ threads are +# only meaningful for `--disable-gil` builds, because the GIL prevents most +# situations where there is lock contention with short critical sections. +# +# Fairness: A measure of how evenly the lock acquisitions are distributed. +# A fairness of 1.0 means that all threads acquired the lock the same number +# of times. A fairness of 1/N means that only one thread ever acquired the +# lock. +# See https://en.wikipedia.org/wiki/Fairness_measure#Jain's_fairness_index + +from _testinternalcapi import benchmark_locks +import sys + +# Max number of threads to test +MAX_THREADS = 10 + +# How much "work" to do while holding the lock +CRITICAL_SECTION_LENGTH = 1 + + +def jains_fairness(values): + # Jain's fairness index + # See https://en.wikipedia.org/wiki/Fairness_measure + return (sum(values) ** 2) / (len(values) * sum(x ** 2 for x in values)) + +def main(): + print("Lock Type Threads Acquisitions (kHz) Fairness") + for lock_type in ["PyMutex", "PyThread_type_lock"]: + use_pymutex = (lock_type == "PyMutex") + for num_threads in range(1, MAX_THREADS + 1): + acquisitions, thread_iters = benchmark_locks( + num_threads, use_pymutex, CRITICAL_SECTION_LENGTH) + + acquisitions /= 1000 # report in kHz for readability + fairness = jains_fairness(thread_iters) + + print(f"{lock_type: <20}{num_threads: <18}{acquisitions: >5.0f}{fairness: >20.2f}") + + +if __name__ == "__main__": + if len(sys.argv) > 1: + CRITICAL_SECTION_LENGTH = int(sys.argv[1]) + main() diff --git a/Tools/msi/README.txt b/Tools/msi/README.txt index 8c6ec516f18e9d..c25ada8397cd95 100644 --- a/Tools/msi/README.txt +++ b/Tools/msi/README.txt @@ -73,6 +73,13 @@ building on a recent Windows version, use the Control Panel (Programs | Programs and Features | Turn Windows Features on or off) and ensure that the entry ".NET Framework 3.5 (includes .NET 2.0 and 3.0)" is enabled. +For Python 3.11.x and above, enable "Microsoft .NET Framework 4.8 Advanced Services" +instead of "Microsoft .NET Framework Version 3.5" available for Windows 10 and above. +Also make sure "MSVC v143 - VS 2022 C++ ARM64 build tools" are selected under +"Desktop Development with C++" in "Visual Studio installer" even if you are not +building on ARM64 along with other x64 related v143 build tools. This is because for +3.11.x and above we have upgraded to Wix-3.14. + For testing, the installer should be built with the Tools/msi/build.bat script: diff --git a/Tools/msi/dev/dev_files.wxs b/Tools/msi/dev/dev_files.wxs index 21f9c848cc6be5..4357dc86d9d356 100644 --- a/Tools/msi/dev/dev_files.wxs +++ b/Tools/msi/dev/dev_files.wxs @@ -3,7 +3,7 @@ - + diff --git a/Tools/msi/test/test_files.wxs b/Tools/msi/test/test_files.wxs index 87e164cb6759f6..bb9b258692a62f 100644 --- a/Tools/msi/test/test_files.wxs +++ b/Tools/msi/test/test_files.wxs @@ -1,41 +1,41 @@ - + - + - + - + - + - + - + - + - + diff --git a/Tools/patchcheck/patchcheck.py b/Tools/patchcheck/patchcheck.py index fa3a43af6e6048..af1f0584bb5403 100755 --- a/Tools/patchcheck/patchcheck.py +++ b/Tools/patchcheck/patchcheck.py @@ -11,6 +11,13 @@ import untabify +def get_python_source_dir(): + src_dir = sysconfig.get_config_var('abs_srcdir') + if not src_dir: + src_dir = sysconfig.get_config_var('srcdir') + return os.path.abspath(src_dir) + + # Excluded directories which are copies of external libraries: # don't check their coding style EXCLUDE_DIRS = [ @@ -18,12 +25,13 @@ os.path.join('Modules', 'expat'), os.path.join('Modules', 'zlib'), ] -SRCDIR = sysconfig.get_config_var('srcdir') +SRCDIR = get_python_source_dir() def n_files_str(count): """Return 'N file(s)' with the proper plurality on 'file'.""" - return "{} file{}".format(count, "s" if count != 1 else "") + s = "s" if count != 1 else "" + return f"{count} file{s}" def status(message, modal=False, info=None): @@ -77,7 +85,7 @@ def get_git_remote_default_branch(remote_name): It is typically called 'main', but may differ """ - cmd = "git remote show {}".format(remote_name).split() + cmd = f"git remote show {remote_name}".split() env = os.environ.copy() env['LANG'] = 'C' try: @@ -164,9 +172,9 @@ def report_modified_files(file_paths): if count == 0: return n_files_str(count) else: - lines = ["{}:".format(n_files_str(count))] + lines = [f"{n_files_str(count)}:"] for path in file_paths: - lines.append(" {}".format(path)) + lines.append(f" {path}") return "\n".join(lines) @@ -205,27 +213,6 @@ def normalize_c_whitespace(file_paths): return fixed -ws_re = re.compile(br'\s+(\r?\n)$') - -@status("Fixing docs whitespace", info=report_modified_files) -def normalize_docs_whitespace(file_paths): - fixed = [] - for path in file_paths: - abspath = os.path.join(SRCDIR, path) - try: - with open(abspath, 'rb') as f: - lines = f.readlines() - new_lines = [ws_re.sub(br'\1', line) for line in lines] - if new_lines != lines: - shutil.copyfile(abspath, abspath + '.bak') - with open(abspath, 'wb') as f: - f.writelines(new_lines) - fixed.append(path) - except Exception as err: - print('Cannot fix %s: %s' % (path, err)) - return fixed - - @status("Docs modified", modal=True) def docs_modified(file_paths): """Report if any file in the Doc directory has been changed.""" @@ -244,6 +231,7 @@ def reported_news(file_paths): return any(p.startswith(os.path.join('Misc', 'NEWS.d', 'next')) for p in file_paths) + @status("configure regenerated", modal=True, info=str) def regenerated_configure(file_paths): """Check if configure has been regenerated.""" @@ -252,6 +240,7 @@ def regenerated_configure(file_paths): else: return "not needed" + @status("pyconfig.h.in regenerated", modal=True, info=str) def regenerated_pyconfig_h_in(file_paths): """Check if pyconfig.h.in has been regenerated.""" @@ -260,6 +249,7 @@ def regenerated_pyconfig_h_in(file_paths): else: return "not needed" + def ci(pull_request): if pull_request == 'false': print('Not a pull request; skipping') @@ -268,19 +258,18 @@ def ci(pull_request): file_paths = changed_files(base_branch) python_files = [fn for fn in file_paths if fn.endswith('.py')] c_files = [fn for fn in file_paths if fn.endswith(('.c', '.h'))] - doc_files = [fn for fn in file_paths if fn.startswith('Doc') and - fn.endswith(('.rst', '.inc'))] fixed = [] fixed.extend(normalize_whitespace(python_files)) fixed.extend(normalize_c_whitespace(c_files)) - fixed.extend(normalize_docs_whitespace(doc_files)) if not fixed: print('No whitespace issues found') else: - print(f'Please fix the {len(fixed)} file(s) with whitespace issues') - print('(on UNIX you can run `make patchcheck` to make the fixes)') + count = len(fixed) + print(f'Please fix the {n_files_str(count)} with whitespace issues') + print('(on Unix you can run `make patchcheck` to make the fixes)') sys.exit(1) + def main(): base_branch = get_base_branch() file_paths = changed_files(base_branch) @@ -293,8 +282,6 @@ def main(): normalize_whitespace(python_files) # C rules enforcement. normalize_c_whitespace(c_files) - # Doc whitespace enforcement. - normalize_docs_whitespace(doc_files) # Docs updated. docs_modified(doc_files) # Misc/ACKS changed. diff --git a/Tools/patchcheck/untabify.py b/Tools/patchcheck/untabify.py index 861c83ced90f24..5c9d1208540830 100755 --- a/Tools/patchcheck/untabify.py +++ b/Tools/patchcheck/untabify.py @@ -21,8 +21,7 @@ def main(): if optname == '-t': tabsize = int(optvalue) - for filename in args: - process(filename, tabsize) + return max(process(filename, tabsize) for filename in args) def process(filename, tabsize, verbose=True): @@ -32,10 +31,10 @@ def process(filename, tabsize, verbose=True): encoding = f.encoding except IOError as msg: print("%r: I/O error: %s" % (filename, msg)) - return + return 2 newtext = text.expandtabs(tabsize) if newtext == text: - return + return 0 backup = filename + "~" try: os.unlink(backup) @@ -49,7 +48,8 @@ def process(filename, tabsize, verbose=True): f.write(newtext) if verbose: print(filename) + return 1 if __name__ == '__main__': - main() + raise SystemExit(main()) diff --git a/Tools/peg_generator/mypy.ini b/Tools/peg_generator/mypy.ini index 17323722c85ad0..f38f21bed004b2 100644 --- a/Tools/peg_generator/mypy.ini +++ b/Tools/peg_generator/mypy.ini @@ -1,26 +1,23 @@ [mypy] -files = pegen - -follow_imports = error -no_implicit_optional = True -strict_optional = True - -#check_untyped_defs = True -disallow_untyped_calls = True -disallow_untyped_defs = True +files = Tools/peg_generator/pegen +pretty = True +show_traceback = True -disallow_any_generics = true -disallow_any_unimported = True -disallow_incomplete_defs = True -disallow_subclassing_any = True +# Make sure the peg_generator can be run using Python 3.10: +python_version = 3.10 -warn_unused_configs = True -warn_unused_ignores = true -warn_redundant_casts = true -warn_no_return = True +# Be strict... +strict = True +warn_unreachable = True +enable_error_code = truthy-bool,ignore-without-code,redundant-expr -show_traceback = True -show_error_codes = True +# This causes *many* false positives on the peg_generator +# due to pegen.grammar.GrammarVisitor returning Any from visit() and generic_visit(). +# It would be possible to workaround the false positives using asserts, +# but it would be pretty tedious, and probably isn't worth it. +warn_return_any = False -[mypy-pegen.grammar_parser] -strict_optional = False +# Not all of the strictest settings can be enabled +# on generated Python code yet: +[mypy-pegen.grammar_parser.*] +disable_error_code = redundant-expr diff --git a/Tools/peg_generator/peg_extension/peg_extension.c b/Tools/peg_generator/peg_extension/peg_extension.c index 7df134b5ade8bb..b081240ffff017 100644 --- a/Tools/peg_generator/peg_extension/peg_extension.c +++ b/Tools/peg_generator/peg_extension/peg_extension.c @@ -52,7 +52,7 @@ parse_file(PyObject *self, PyObject *args, PyObject *kwds) PyCompilerFlags flags = _PyCompilerFlags_INIT; mod_ty res = _PyPegen_run_parser_from_file_pointer( fp, Py_file_input, filename_ob, - NULL, NULL, NULL, &flags, NULL, arena); + NULL, NULL, NULL, &flags, NULL, NULL, arena); fclose(fp); if (res == NULL) { goto error; diff --git a/Tools/peg_generator/pegen/__main__.py b/Tools/peg_generator/pegen/__main__.py index 2910d6ccf1c694..262c8a6db68f6e 100755 --- a/Tools/peg_generator/pegen/__main__.py +++ b/Tools/peg_generator/pegen/__main__.py @@ -12,7 +12,10 @@ import traceback from typing import Tuple -from pegen.build import Grammar, Parser, ParserGenerator, Tokenizer +from pegen.grammar import Grammar +from pegen.parser import Parser +from pegen.parser_generator import ParserGenerator +from pegen.tokenizer import Tokenizer from pegen.validator import validate_grammar diff --git a/Tools/peg_generator/pegen/ast_dump.py b/Tools/peg_generator/pegen/ast_dump.py index 2c57d0932fda37..07f8799c114f5d 100644 --- a/Tools/peg_generator/pegen/ast_dump.py +++ b/Tools/peg_generator/pegen/ast_dump.py @@ -66,6 +66,4 @@ def _format(node: Any, level: int = 0) -> Tuple[str, bool]: if all(cls.__name__ != "AST" for cls in node.__class__.__mro__): raise TypeError("expected AST, got %r" % node.__class__.__name__) - if indent is not None and not isinstance(indent, str): - indent = " " * indent return _format(node)[0] diff --git a/Tools/peg_generator/pegen/build.py b/Tools/peg_generator/pegen/build.py index e41330fade94e3..00295c984d1bb6 100644 --- a/Tools/peg_generator/pegen/build.py +++ b/Tools/peg_generator/pegen/build.py @@ -1,11 +1,12 @@ import itertools +import logging import os import pathlib import sys import sysconfig import tempfile import tokenize -from typing import IO, Dict, List, Optional, Set, Tuple +from typing import IO, Any, Dict, List, Optional, Set, Tuple from pegen.c_generator import CParserGenerator from pegen.grammar import Grammar @@ -18,6 +19,7 @@ MOD_DIR = pathlib.Path(__file__).resolve().parent TokenDefinitions = Tuple[Dict[int, str], Dict[str, int], Set[str]] +Incomplete = Any # TODO: install `types-setuptools` and remove this alias def get_extra_flags(compiler_flags: str, compiler_py_flags_nodist: str) -> List[str]: @@ -28,7 +30,7 @@ def get_extra_flags(compiler_flags: str, compiler_py_flags_nodist: str) -> List[ return f"{flags} {py_flags_nodist}".split() -def fixup_build_ext(cmd): +def fixup_build_ext(cmd: Incomplete) -> None: """Function needed to make build_ext tests pass. When Python was built with --enable-shared on Unix, -L. is not enough to @@ -74,7 +76,7 @@ def compile_c_extension( keep_asserts: bool = True, disable_optimization: bool = False, library_dir: Optional[str] = None, -) -> str: +) -> pathlib.Path: """Compile the generated source for a parser generator into an extension module. The extension module will be generated in the same directory as the provided path @@ -89,6 +91,7 @@ def compile_c_extension( static library of the common parser sources (this is useful in case you are creating multiple extensions). """ + import setuptools.command.build_ext import setuptools.logging from setuptools import Extension, Distribution @@ -97,7 +100,7 @@ def compile_c_extension( from setuptools._distutils.sysconfig import customize_compiler if verbose: - setuptools.logging.set_threshold(setuptools.logging.logging.DEBUG) + setuptools.logging.set_threshold(logging.DEBUG) source_file_path = pathlib.Path(generated_source_path) extension_name = source_file_path.stem @@ -120,7 +123,14 @@ def compile_c_extension( common_sources = [ str(MOD_DIR.parent.parent.parent / "Python" / "Python-ast.c"), str(MOD_DIR.parent.parent.parent / "Python" / "asdl.c"), - str(MOD_DIR.parent.parent.parent / "Parser" / "tokenizer.c"), + str(MOD_DIR.parent.parent.parent / "Parser" / "lexer" / "lexer.c"), + str(MOD_DIR.parent.parent.parent / "Parser" / "lexer" / "state.c"), + str(MOD_DIR.parent.parent.parent / "Parser" / "lexer" / "buffer.c"), + str(MOD_DIR.parent.parent.parent / "Parser" / "tokenizer" / "string_tokenizer.c"), + str(MOD_DIR.parent.parent.parent / "Parser" / "tokenizer" / "file_tokenizer.c"), + str(MOD_DIR.parent.parent.parent / "Parser" / "tokenizer" / "utf8_tokenizer.c"), + str(MOD_DIR.parent.parent.parent / "Parser" / "tokenizer" / "readline_tokenizer.c"), + str(MOD_DIR.parent.parent.parent / "Parser" / "tokenizer" / "helpers.c"), str(MOD_DIR.parent.parent.parent / "Parser" / "pegen.c"), str(MOD_DIR.parent.parent.parent / "Parser" / "pegen_errors.c"), str(MOD_DIR.parent.parent.parent / "Parser" / "action_helpers.c"), @@ -129,8 +139,15 @@ def compile_c_extension( ] include_dirs = [ str(MOD_DIR.parent.parent.parent / "Include" / "internal"), + str(MOD_DIR.parent.parent.parent / "Include" / "internal" / "mimalloc"), str(MOD_DIR.parent.parent.parent / "Parser"), + str(MOD_DIR.parent.parent.parent / "Parser" / "lexer"), + str(MOD_DIR.parent.parent.parent / "Parser" / "tokenizer"), ] + if sys.platform == "win32": + # HACK: The location of pyconfig.h has moved within our build, and + # setuptools hasn't updated for it yet. So add the path manually for now + include_dirs.append(pathlib.Path(sysconfig.get_config_h_filename()).parent) extension = Extension( extension_name, sources=[generated_source_path], @@ -139,6 +156,7 @@ def compile_c_extension( ) dist = Distribution({"name": extension_name, "ext_modules": [extension]}) cmd = dist.get_command_obj("build_ext") + assert isinstance(cmd, setuptools.command.build_ext.build_ext) fixup_build_ext(cmd) cmd.build_lib = str(source_file_path.parent) cmd.include_dirs = include_dirs @@ -155,6 +173,7 @@ def compile_c_extension( library_filename = compiler.library_filename(extension_name, output_dir=library_dir) if newer_group(common_sources, library_filename, "newer"): if sys.platform == "win32": + assert compiler.static_lib_format pdb = compiler.static_lib_format % (extension_name, ".pdb") compile_opts = [f"/Fd{library_dir}\\{pdb}"] compile_opts.extend(extra_compile_args) @@ -207,7 +226,7 @@ def compile_c_extension( ext_path, libraries=cmd.get_libraries(extension), extra_postargs=extra_link_args, - export_symbols=cmd.get_export_symbols(extension), + export_symbols=cmd.get_export_symbols(extension), # type: ignore[no-untyped-call] debug=cmd.debug, build_temp=cmd.build_temp, ) diff --git a/Tools/peg_generator/pegen/c_generator.py b/Tools/peg_generator/pegen/c_generator.py index f57b6275f671d3..7cdd5debe9a225 100644 --- a/Tools/peg_generator/pegen/c_generator.py +++ b/Tools/peg_generator/pegen/c_generator.py @@ -38,7 +38,11 @@ #endif #ifdef __wasi__ -# define MAXSTACK 4000 +# ifdef Py_DEBUG +# define MAXSTACK 1000 +# else +# define MAXSTACK 4000 +# endif #else # define MAXSTACK 6000 #endif @@ -375,8 +379,7 @@ def __init__( def add_level(self) -> None: self.print("if (p->level++ == MAXSTACK) {") with self.indent(): - self.print("p->error_indicator = 1;") - self.print("PyErr_NoMemory();") + self.print("_Pypegen_stack_overflow(p);") self.print("}") def remove_level(self) -> None: diff --git a/Tools/peg_generator/pegen/grammar.py b/Tools/peg_generator/pegen/grammar.py index 03d60d01026f85..1ee9d100b61f49 100644 --- a/Tools/peg_generator/pegen/grammar.py +++ b/Tools/peg_generator/pegen/grammar.py @@ -35,7 +35,13 @@ def generic_visit(self, node: Iterable[Any], *args: Any, **kwargs: Any) -> Any: class Grammar: def __init__(self, rules: Iterable[Rule], metas: Iterable[Tuple[str, Optional[str]]]): - self.rules = {rule.name: rule for rule in rules} + # Check if there are repeated rules in "rules" + all_rules = {} + for rule in rules: + if rule.name in all_rules: + raise GrammarError(f"Repeated rule {rule.name!r}") + all_rules[rule.name] = rule + self.rules = all_rules self.metas = dict(metas) def __str__(self) -> str: @@ -112,8 +118,7 @@ def __str__(self) -> str: return self.value def __iter__(self) -> Iterable[str]: - if False: - yield + yield from () class NameLeaf(Leaf): @@ -335,8 +340,7 @@ def __str__(self) -> str: return f"~" def __iter__(self) -> Iterator[Tuple[str, str]]: - if False: - yield + yield from () def __eq__(self, other: object) -> bool: if not isinstance(other, Cut): @@ -349,7 +353,7 @@ def initial_names(self) -> AbstractSet[str]: Plain = Union[Leaf, Group] Item = Union[Plain, Opt, Repeat, Forced, Lookahead, Rhs, Cut] -RuleName = Tuple[str, str] +RuleName = Tuple[str, Optional[str]] MetaTuple = Tuple[str, Optional[str]] MetaList = List[MetaTuple] RuleList = List[Rule] diff --git a/Tools/peg_generator/pegen/keywordgen.py b/Tools/peg_generator/pegen/keywordgen.py index bbf13267e5763b..52611eae044e58 100644 --- a/Tools/peg_generator/pegen/keywordgen.py +++ b/Tools/peg_generator/pegen/keywordgen.py @@ -35,30 +35,30 @@ issoftkeyword = frozenset(softkwlist).__contains__ '''.lstrip() + def main() -> None: parser = argparse.ArgumentParser( description="Generate the Lib/keywords.py file from the grammar." ) parser.add_argument( - "grammar", type=str, help="The file with the grammar definition in PEG format" + "grammar", help="The file with the grammar definition in PEG format" ) parser.add_argument( - "tokens_file", type=argparse.FileType("r"), help="The file with the token definitions" + "tokens_file", help="The file with the token definitions" ) parser.add_argument( "keyword_file", - type=argparse.FileType("w"), help="The path to write the keyword definitions", ) args = parser.parse_args() grammar, _, _ = build_parser(args.grammar) - with args.tokens_file as tok_file: + with open(args.tokens_file) as tok_file: all_tokens, exact_tok, non_exact_tok = generate_token_definitions(tok_file) gen = CParserGenerator(grammar, all_tokens, exact_tok, non_exact_tok, file=None) gen.collect_rules() - with args.keyword_file as thefile: + with open(args.keyword_file, 'w') as thefile: all_keywords = sorted(list(gen.keywords.keys())) all_soft_keywords = sorted(gen.soft_keywords) diff --git a/Tools/peg_generator/pegen/parser.py b/Tools/peg_generator/pegen/parser.py index 034e8e6017a22d..ed0aec9db2443f 100644 --- a/Tools/peg_generator/pegen/parser.py +++ b/Tools/peg_generator/pegen/parser.py @@ -10,7 +10,6 @@ from pegen.tokenizer import Mark, Tokenizer, exact_token_types T = TypeVar("T") -P = TypeVar("P", bound="Parser") F = TypeVar("F", bound=Callable[..., Any]) @@ -21,7 +20,7 @@ def logger(method: F) -> F: """ method_name = method.__name__ - def logger_wrapper(self: P, *args: object) -> T: + def logger_wrapper(self: "Parser", *args: object) -> Any: if not self._verbose: return method(self, *args) argsr = ",".join(repr(arg) for arg in args) @@ -33,7 +32,7 @@ def logger_wrapper(self: P, *args: object) -> T: print(f"{fill}... {method_name}({argsr}) --> {tree!s:.200}") return tree - logger_wrapper.__wrapped__ = method # type: ignore + logger_wrapper.__wrapped__ = method # type: ignore[attr-defined] return cast(F, logger_wrapper) @@ -41,7 +40,7 @@ def memoize(method: F) -> F: """Memoize a symbol method.""" method_name = method.__name__ - def memoize_wrapper(self: P, *args: object) -> T: + def memoize_wrapper(self: "Parser", *args: object) -> Any: mark = self._mark() key = mark, method_name, args # Fast path: cache hit, and not verbose. @@ -70,15 +69,17 @@ def memoize_wrapper(self: P, *args: object) -> T: self._reset(endmark) return tree - memoize_wrapper.__wrapped__ = method # type: ignore + memoize_wrapper.__wrapped__ = method # type: ignore[attr-defined] return cast(F, memoize_wrapper) -def memoize_left_rec(method: Callable[[P], Optional[T]]) -> Callable[[P], Optional[T]]: +def memoize_left_rec( + method: Callable[["Parser"], Optional[T]] +) -> Callable[["Parser"], Optional[T]]: """Memoize a left-recursive symbol method.""" method_name = method.__name__ - def memoize_left_rec_wrapper(self: P) -> Optional[T]: + def memoize_left_rec_wrapper(self: "Parser") -> Optional[T]: mark = self._mark() key = mark, method_name, () # Fast path: cache hit, and not verbose. @@ -152,7 +153,7 @@ def memoize_left_rec_wrapper(self: P) -> Optional[T]: self._reset(endmark) return tree - memoize_left_rec_wrapper.__wrapped__ = method # type: ignore + memoize_left_rec_wrapper.__wrapped__ = method # type: ignore[attr-defined] return memoize_left_rec_wrapper diff --git a/Tools/peg_generator/pegen/testutil.py b/Tools/peg_generator/pegen/testutil.py index 9fcca928b08ee5..0e85b844ef152b 100644 --- a/Tools/peg_generator/pegen/testutil.py +++ b/Tools/peg_generator/pegen/testutil.py @@ -37,7 +37,7 @@ def generate_parser(grammar: Grammar) -> Type[Parser]: def run_parser(file: IO[bytes], parser_class: Type[Parser], *, verbose: bool = False) -> Any: # Run a parser on a file (stream). - tokenizer = Tokenizer(tokenize.generate_tokens(file.readline)) # type: ignore # typeshed issue #3515 + tokenizer = Tokenizer(tokenize.generate_tokens(file.readline)) # type: ignore[arg-type] # typeshed issue #3515 parser = parser_class(tokenizer, verbose=verbose) result = parser.start() if result is None: @@ -52,7 +52,7 @@ def parse_string( if dedent: source = textwrap.dedent(source) file = io.StringIO(source) - return run_parser(file, parser_class, verbose=verbose) # type: ignore # typeshed issue #3515 + return run_parser(file, parser_class, verbose=verbose) # type: ignore[arg-type] # typeshed issue #3515 def make_parser(source: str) -> Type[Parser]: @@ -116,7 +116,7 @@ def generate_parser_c_extension( def print_memstats() -> bool: MiB: Final = 2**20 try: - import psutil # type: ignore + import psutil except ImportError: return False print("Memory stats:") diff --git a/Tools/requirements-dev.txt b/Tools/requirements-dev.txt new file mode 100644 index 00000000000000..b89f86a35d6115 --- /dev/null +++ b/Tools/requirements-dev.txt @@ -0,0 +1,7 @@ +# Requirements file for external linters and checks we run on +# Tools/clinic, Tools/cases_generator/, and Tools/peg_generator/ in CI +mypy==1.8.0 + +# needed for peg_generator: +types-psutil==5.9.5.17 +types-setuptools==69.0.0.0 diff --git a/Tools/requirements-hypothesis.txt b/Tools/requirements-hypothesis.txt new file mode 100644 index 00000000000000..0e6e16ae198162 --- /dev/null +++ b/Tools/requirements-hypothesis.txt @@ -0,0 +1,4 @@ +# Requirements file for hypothesis that +# we use to run our property-based tests in CI. + +hypothesis==6.92.2 diff --git a/Tools/scripts/run_tests.py b/Tools/scripts/run_tests.py deleted file mode 100644 index 445a34ae3e8eee..00000000000000 --- a/Tools/scripts/run_tests.py +++ /dev/null @@ -1,92 +0,0 @@ -"""Run Python's test suite in a fast, rigorous way. - -The defaults are meant to be reasonably thorough, while skipping certain -tests that can be time-consuming or resource-intensive (e.g. largefile), -or distracting (e.g. audio and gui). These defaults can be overridden by -simply passing a -u option to this script. - -""" - -import os -import shlex -import sys -import sysconfig -import test.support - - -def is_multiprocess_flag(arg): - return arg.startswith('-j') or arg.startswith('--multiprocess') - - -def is_resource_use_flag(arg): - return arg.startswith('-u') or arg.startswith('--use') - -def is_python_flag(arg): - return arg.startswith('-p') or arg.startswith('--python') - - -def main(regrtest_args): - args = [sys.executable, - '-u', # Unbuffered stdout and stderr - '-W', 'default', # Warnings set to 'default' - '-bb', # Warnings about bytes/bytearray - ] - - cross_compile = '_PYTHON_HOST_PLATFORM' in os.environ - if (hostrunner := os.environ.get("_PYTHON_HOSTRUNNER")) is None: - hostrunner = sysconfig.get_config_var("HOSTRUNNER") - if cross_compile: - # emulate -E, but keep PYTHONPATH + cross compile env vars, so - # test executable can load correct sysconfigdata file. - keep = { - '_PYTHON_PROJECT_BASE', - '_PYTHON_HOST_PLATFORM', - '_PYTHON_SYSCONFIGDATA_NAME', - 'PYTHONPATH' - } - environ = { - name: value for name, value in os.environ.items() - if not name.startswith(('PYTHON', '_PYTHON')) or name in keep - } - else: - environ = os.environ.copy() - args.append("-E") - - # Allow user-specified interpreter options to override our defaults. - args.extend(test.support.args_from_interpreter_flags()) - - args.extend(['-m', 'test', # Run the test suite - '-r', # Randomize test order - '-w', # Re-run failed tests in verbose mode - ]) - if sys.platform == 'win32': - args.append('-n') # Silence alerts under Windows - if not any(is_multiprocess_flag(arg) for arg in regrtest_args): - if cross_compile and hostrunner: - # For now use only two cores for cross-compiled builds; - # hostrunner can be expensive. - args.extend(['-j', '2']) - else: - args.extend(['-j', '0']) # Use all CPU cores - if not any(is_resource_use_flag(arg) for arg in regrtest_args): - args.extend(['-u', 'all,-largefile,-audio,-gui']) - - if cross_compile and hostrunner: - # If HOSTRUNNER is set and -p/--python option is not given, then - # use hostrunner to execute python binary for tests. - if not any(is_python_flag(arg) for arg in regrtest_args): - buildpython = sysconfig.get_config_var("BUILDPYTHON") - args.extend(["--python", f"{hostrunner} {buildpython}"]) - - args.extend(regrtest_args) - - print(shlex.join(args)) - if sys.platform == 'win32': - from subprocess import call - sys.exit(call(args)) - else: - os.execve(sys.executable, args, environ) - - -if __name__ == '__main__': - main(sys.argv[1:]) diff --git a/Tools/scripts/summarize_stats.py b/Tools/scripts/summarize_stats.py index f798b2f772d08a..df8a7fddfb8866 100644 --- a/Tools/scripts/summarize_stats.py +++ b/Tools/scripts/summarize_stats.py @@ -2,653 +2,1178 @@ default stats folders. """ +from __future__ import annotations + +# NOTE: Bytecode introspection modules (opcode, dis, etc.) should only +# be imported when loading a single dataset. When comparing datasets, it +# could get it wrong, leading to subtle errors. + import argparse import collections -import json -import os.path -import opcode +from collections.abc import KeysView from datetime import date +import enum +import functools import itertools +import json +from operator import itemgetter +import os +from pathlib import Path +import re import sys +from typing import Any, Callable, TextIO, TypeAlias + + +RawData: TypeAlias = dict[str, Any] +Rows: TypeAlias = list[tuple] +Columns: TypeAlias = tuple[str, ...] +RowCalculator: TypeAlias = Callable[["Stats"], Rows] + + +# TODO: Check for parity + if os.name == "nt": DEFAULT_DIR = "c:\\temp\\py_stats\\" else: DEFAULT_DIR = "/tmp/py_stats/" -#Create list of all instruction names -specialized = iter(opcode._specialized_instructions) -opname = ["<0>"] -for name in opcode.opname[1:]: - if name.startswith("<"): - try: - name = next(specialized) - except StopIteration: - pass - opname.append(name) - -# opcode_name --> opcode -# Sort alphabetically. -opmap = {name: i for i, name in enumerate(opname)} -opmap = dict(sorted(opmap.items())) + +SOURCE_DIR = Path(__file__).parents[2] + TOTAL = "specialization.hit", "specialization.miss", "execution_count" -def format_ratio(num, den): - """ - Format a ratio as a percentage. When the denominator is 0, returns the empty - string. - """ - if den == 0: - return "" - else: - return f"{num/den:.01%}" -def join_rows(a_rows, b_rows): - """ - Joins two tables together, side-by-side, where the first column in each is a - common key. - """ - if len(a_rows) == 0 and len(b_rows) == 0: - return [] +def pretty(name: str) -> str: + return name.replace("_", " ").lower() - if len(a_rows): - a_ncols = list(set(len(x) for x in a_rows)) - if len(a_ncols) != 1: - raise ValueError("Table a is ragged") - if len(b_rows): - b_ncols = list(set(len(x) for x in b_rows)) - if len(b_ncols) != 1: - raise ValueError("Table b is ragged") +def _load_metadata_from_source(): + def get_defines(filepath: Path, prefix: str = "SPEC_FAIL"): + with open(SOURCE_DIR / filepath) as spec_src: + defines = collections.defaultdict(list) + start = "#define " + prefix + "_" + for line in spec_src: + line = line.strip() + if not line.startswith(start): + continue + line = line[len(start) :] + name, val = line.split() + defines[int(val.strip())].append(name.strip()) + return defines + + import opcode + + return { + "_specialized_instructions": [ + op for op in opcode._specialized_opmap.keys() if "__" not in op # type: ignore + ], + "_stats_defines": get_defines( + Path("Include") / "cpython" / "pystats.h", "EVAL_CALL" + ), + "_defines": get_defines(Path("Python") / "specialize.c"), + } + + +def load_raw_data(input: Path) -> RawData: + if input.is_file(): + with open(input, "r") as fd: + data = json.load(fd) - if len(a_rows) and len(b_rows) and a_ncols[0] != b_ncols[0]: - raise ValueError("Tables have different widths") + data["_stats_defines"] = {int(k): v for k, v in data["_stats_defines"].items()} + data["_defines"] = {int(k): v for k, v in data["_defines"].items()} - if len(a_rows): - ncols = a_ncols[0] - else: - ncols = b_ncols[0] - - default = [""] * (ncols - 1) - a_data = {x[0]: x[1:] for x in a_rows} - b_data = {x[0]: x[1:] for x in b_rows} - - if len(a_data) != len(a_rows) or len(b_data) != len(b_rows): - raise ValueError("Duplicate keys") - - # To preserve ordering, use A's keys as is and then add any in B that aren't - # in A - keys = list(a_data.keys()) + [k for k in b_data.keys() if k not in a_data] - return [(k, *a_data.get(k, default), *b_data.get(k, default)) for k in keys] - -def calculate_specialization_stats(family_stats, total): - rows = [] - for key in sorted(family_stats): - if key.startswith("specialization.failure_kinds"): - continue - if key in ("specialization.hit", "specialization.miss"): - label = key[len("specialization."):] - elif key == "execution_count": - continue - elif key in ("specialization.success", "specialization.failure", "specializable"): - continue - elif key.startswith("pair"): - continue - else: - label = key - rows.append((f"{label:>12}", f"{family_stats[key]:>12}", format_ratio(family_stats[key], total))) - return rows - -def calculate_specialization_success_failure(family_stats): - total_attempts = 0 - for key in ("specialization.success", "specialization.failure"): - total_attempts += family_stats.get(key, 0) - rows = [] - if total_attempts: - for key in ("specialization.success", "specialization.failure"): - label = key[len("specialization."):] - label = label[0].upper() + label[1:] - val = family_stats.get(key, 0) - rows.append((label, val, format_ratio(val, total_attempts))) - return rows - -def calculate_specialization_failure_kinds(name, family_stats, defines): - total_failures = family_stats.get("specialization.failure", 0) - failure_kinds = [ 0 ] * 40 - for key in family_stats: - if not key.startswith("specialization.failure_kind"): - continue - _, index = key[:-1].split("[") - index = int(index) - failure_kinds[index] = family_stats[key] - failures = [(value, index) for (index, value) in enumerate(failure_kinds)] - failures.sort(reverse=True) - rows = [] - for value, index in failures: - if not value: - continue - rows.append((kind_to_text(index, defines, name), value, format_ratio(value, total_failures))) - return rows - -def print_specialization_stats(name, family_stats, defines): - if "specializable" not in family_stats: - return - total = sum(family_stats.get(kind, 0) for kind in TOTAL) - if total == 0: - return - with Section(name, 3, f"specialization stats for {name} family"): - rows = calculate_specialization_stats(family_stats, total) - emit_table(("Kind", "Count", "Ratio"), rows) - rows = calculate_specialization_success_failure(family_stats) - if rows: - print_title("Specialization attempts", 4) - emit_table(("", "Count:", "Ratio:"), rows) - rows = calculate_specialization_failure_kinds(name, family_stats, defines) - emit_table(("Failure kind", "Count:", "Ratio:"), rows) - -def print_comparative_specialization_stats(name, base_family_stats, head_family_stats, defines): - if "specializable" not in base_family_stats: - return - - base_total = sum(base_family_stats.get(kind, 0) for kind in TOTAL) - head_total = sum(head_family_stats.get(kind, 0) for kind in TOTAL) - if base_total + head_total == 0: - return - with Section(name, 3, f"specialization stats for {name} family"): - base_rows = calculate_specialization_stats(base_family_stats, base_total) - head_rows = calculate_specialization_stats(head_family_stats, head_total) - emit_table( - ("Kind", "Base Count", "Base Ratio", "Head Count", "Head Ratio"), - join_rows(base_rows, head_rows) - ) - base_rows = calculate_specialization_success_failure(base_family_stats) - head_rows = calculate_specialization_success_failure(head_family_stats) - rows = join_rows(base_rows, head_rows) - if rows: - print_title("Specialization attempts", 4) - emit_table(("", "Base Count:", "Base Ratio:", "Head Count:", "Head Ratio:"), rows) - base_rows = calculate_specialization_failure_kinds(name, base_family_stats, defines) - head_rows = calculate_specialization_failure_kinds(name, head_family_stats, defines) - emit_table( - ("Failure kind", "Base Count:", "Base Ratio:", "Head Count:", "Head Ratio:"), - join_rows(base_rows, head_rows) - ) + return data -def gather_stats(input): - # Note the output of this function must be JSON-serializable + elif input.is_dir(): + stats = collections.Counter[str]() - if os.path.isfile(input): - with open(input, "r") as fd: - return json.load(fd) - elif os.path.isdir(input): - stats = collections.Counter() - for filename in os.listdir(input): - with open(os.path.join(input, filename)) as fd: + for filename in input.iterdir(): + with open(filename) as fd: for line in fd: try: key, value = line.split(":") except ValueError: - print(f"Unparsable line: '{line.strip()}' in {filename}", file=sys.stderr) + print( + f"Unparsable line: '{line.strip()}' in {filename}", + file=sys.stderr, + ) continue - key = key.strip() - value = int(value) - stats[key] += value - stats['__nfiles__'] += 1 - return stats + stats[key.strip()] += int(value) + stats["__nfiles__"] += 1 + + data = dict(stats) + data.update(_load_metadata_from_source()) + return data + else: raise ValueError(f"{input:r} is not a file or directory path") -def extract_opcode_stats(stats): - opcode_stats = [ {} for _ in range(256) ] - for key, value in stats.items(): - if not key.startswith("opcode"): - continue - n, _, rest = key[7:].partition("]") - opcode_stats[int(n)][rest.strip(".")] = value - return opcode_stats - -def parse_kinds(spec_src, prefix="SPEC_FAIL"): - defines = collections.defaultdict(list) - start = "#define " + prefix + "_" - for line in spec_src: - line = line.strip() - if not line.startswith(start): - continue - line = line[len(start):] - name, val = line.split() - defines[int(val.strip())].append(name.strip()) - return defines - -def pretty(defname): - return defname.replace("_", " ").lower() - -def kind_to_text(kind, defines, opname): - if kind <= 8: - return pretty(defines[kind][0]) - if opname == "LOAD_SUPER_ATTR": - opname = "SUPER" - elif opname.endswith("ATTR"): - opname = "ATTR" - elif opname in ("FOR_ITER", "SEND"): - opname = "ITER" - elif opname.endswith("SUBSCR"): - opname = "SUBSCR" - for name in defines[kind]: - if name.startswith(opname): - return pretty(name[len(opname)+1:]) - return "kind " + str(kind) - -def categorized_counts(opcode_stats): - basic = 0 - specialized = 0 - not_specialized = 0 - specialized_instructions = { - op for op in opcode._specialized_instructions - if "__" not in op} - for i, opcode_stat in enumerate(opcode_stats): - if "execution_count" not in opcode_stat: - continue - count = opcode_stat['execution_count'] - name = opname[i] - if "specializable" in opcode_stat: - not_specialized += count - elif name in specialized_instructions: - miss = opcode_stat.get("specialization.miss", 0) - not_specialized += miss - specialized += count - miss + +def save_raw_data(data: RawData, json_output: TextIO): + json.dump(data, json_output) + + +class OpcodeStats: + """ + Manages the data related to specific set of opcodes, e.g. tier1 (with prefix + "opcode") or tier2 (with prefix "uops"). + """ + + def __init__(self, data: dict[str, Any], defines, specialized_instructions): + self._data = data + self._defines = defines + self._specialized_instructions = specialized_instructions + + def get_opcode_names(self) -> KeysView[str]: + return self._data.keys() + + def get_pair_counts(self) -> dict[tuple[str, str], int]: + pair_counts = {} + for name_i, opcode_stat in self._data.items(): + for key, value in opcode_stat.items(): + if value and key.startswith("pair_count"): + name_j, _, _ = key[len("pair_count") + 1 :].partition("]") + pair_counts[(name_i, name_j)] = value + return pair_counts + + def get_total_execution_count(self) -> int: + return sum(x.get("execution_count", 0) for x in self._data.values()) + + def get_execution_counts(self) -> dict[str, tuple[int, int]]: + counts = {} + for name, opcode_stat in self._data.items(): + if "execution_count" in opcode_stat: + count = opcode_stat["execution_count"] + miss = 0 + if "specializable" not in opcode_stat: + miss = opcode_stat.get("specialization.miss", 0) + counts[name] = (count, miss) + return counts + + @functools.cache + def _get_pred_succ( + self, + ) -> tuple[dict[str, collections.Counter], dict[str, collections.Counter]]: + pair_counts = self.get_pair_counts() + + predecessors: dict[str, collections.Counter] = collections.defaultdict( + collections.Counter + ) + successors: dict[str, collections.Counter] = collections.defaultdict( + collections.Counter + ) + for (first, second), count in pair_counts.items(): + if count: + predecessors[second][first] = count + successors[first][second] = count + + return predecessors, successors + + def get_predecessors(self, opcode: str) -> collections.Counter[str]: + return self._get_pred_succ()[0][opcode] + + def get_successors(self, opcode: str) -> collections.Counter[str]: + return self._get_pred_succ()[1][opcode] + + def _get_stats_for_opcode(self, opcode: str) -> dict[str, int]: + return self._data[opcode] + + def get_specialization_total(self, opcode: str) -> int: + family_stats = self._get_stats_for_opcode(opcode) + return sum(family_stats.get(kind, 0) for kind in TOTAL) + + def get_specialization_counts(self, opcode: str) -> dict[str, int]: + family_stats = self._get_stats_for_opcode(opcode) + + result = {} + for key, value in sorted(family_stats.items()): + if key.startswith("specialization."): + label = key[len("specialization.") :] + if label in ("success", "failure") or label.startswith("failure_kinds"): + continue + elif key in ( + "execution_count", + "specializable", + ) or key.startswith("pair"): + continue + else: + label = key + result[label] = value + + return result + + def get_specialization_success_failure(self, opcode: str) -> dict[str, int]: + family_stats = self._get_stats_for_opcode(opcode) + result = {} + for key in ("specialization.success", "specialization.failure"): + label = key[len("specialization.") :] + val = family_stats.get(key, 0) + result[label] = val + return result + + def get_specialization_failure_total(self, opcode: str) -> int: + return self._get_stats_for_opcode(opcode).get("specialization.failure", 0) + + def get_specialization_failure_kinds(self, opcode: str) -> dict[str, int]: + def kind_to_text(kind: int, opcode: str): + if kind <= 8: + return pretty(self._defines[kind][0]) + if opcode == "LOAD_SUPER_ATTR": + opcode = "SUPER" + elif opcode.endswith("ATTR"): + opcode = "ATTR" + elif opcode in ("FOR_ITER", "SEND"): + opcode = "ITER" + elif opcode.endswith("SUBSCR"): + opcode = "SUBSCR" + for name in self._defines[kind]: + if name.startswith(opcode): + return pretty(name[len(opcode) + 1 :]) + return "kind " + str(kind) + + family_stats = self._get_stats_for_opcode(opcode) + failure_kinds = [0] * 40 + for key in family_stats: + if not key.startswith("specialization.failure_kind"): + continue + index = int(key[:-1].split("[")[1]) + failure_kinds[index] = family_stats[key] + return { + kind_to_text(index, opcode): value + for (index, value) in enumerate(failure_kinds) + if value + } + + def is_specializable(self, opcode: str) -> bool: + return "specializable" in self._get_stats_for_opcode(opcode) + + def get_specialized_total_counts(self) -> tuple[int, int, int]: + basic = 0 + specialized_hits = 0 + specialized_misses = 0 + not_specialized = 0 + for opcode, opcode_stat in self._data.items(): + if "execution_count" not in opcode_stat: + continue + count = opcode_stat["execution_count"] + if "specializable" in opcode_stat: + not_specialized += count + elif opcode in self._specialized_instructions: + miss = opcode_stat.get("specialization.miss", 0) + specialized_hits += count - miss + specialized_misses += miss + else: + basic += count + return basic, specialized_hits, specialized_misses, not_specialized + + def get_deferred_counts(self) -> dict[str, int]: + return { + opcode: opcode_stat.get("specialization.deferred", 0) + for opcode, opcode_stat in self._data.items() + if opcode != "RESUME" + } + + def get_misses_counts(self) -> dict[str, int]: + return { + opcode: opcode_stat.get("specialization.miss", 0) + for opcode, opcode_stat in self._data.items() + if not self.is_specializable(opcode) + } + + def get_opcode_counts(self) -> dict[str, int]: + counts = {} + for opcode, entry in self._data.items(): + count = entry.get("count", 0) + if count: + counts[opcode] = count + return counts + + +class Stats: + def __init__(self, data: RawData): + self._data = data + + def get(self, key: str) -> int: + return self._data.get(key, 0) + + @functools.cache + def get_opcode_stats(self, prefix: str) -> OpcodeStats: + opcode_stats = collections.defaultdict[str, dict](dict) + for key, value in self._data.items(): + if not key.startswith(prefix): + continue + name, _, rest = key[len(prefix) + 1 :].partition("]") + opcode_stats[name][rest.strip(".")] = value + return OpcodeStats( + opcode_stats, + self._data["_defines"], + self._data["_specialized_instructions"], + ) + + def get_call_stats(self) -> dict[str, int]: + defines = self._data["_stats_defines"] + result = {} + for key, value in sorted(self._data.items()): + if "Calls to" in key: + result[key] = value + elif key.startswith("Calls "): + name, index = key[:-1].split("[") + label = f"{name} ({pretty(defines[int(index)][0])})" + result[label] = value + + for key, value in sorted(self._data.items()): + if key.startswith("Frame"): + result[key] = value + + return result + + def get_object_stats(self) -> dict[str, tuple[int, int]]: + total_materializations = self._data.get("Object new values", 0) + total_allocations = self._data.get("Object allocations", 0) + self._data.get( + "Object allocations from freelist", 0 + ) + total_increfs = self._data.get( + "Object interpreter increfs", 0 + ) + self._data.get("Object increfs", 0) + total_decrefs = self._data.get( + "Object interpreter decrefs", 0 + ) + self._data.get("Object decrefs", 0) + + result = {} + for key, value in self._data.items(): + if key.startswith("Object"): + if "materialize" in key: + den = total_materializations + elif "allocations" in key: + den = total_allocations + elif "increfs" in key: + den = total_increfs + elif "decrefs" in key: + den = total_decrefs + else: + den = None + label = key[6:].strip() + label = label[0].upper() + label[1:] + result[label] = (value, den) + return result + + def get_gc_stats(self) -> list[dict[str, int]]: + gc_stats: list[dict[str, int]] = [] + for key, value in self._data.items(): + if not key.startswith("GC"): + continue + n, _, rest = key[3:].partition("]") + name = rest.strip() + gen_n = int(n) + while len(gc_stats) <= gen_n: + gc_stats.append({}) + gc_stats[gen_n][name] = value + return gc_stats + + def get_optimization_stats(self) -> dict[str, tuple[int, int | None]]: + if "Optimization attempts" not in self._data: + return {} + + attempts = self._data["Optimization attempts"] + created = self._data["Optimization traces created"] + executed = self._data["Optimization traces executed"] + uops = self._data["Optimization uops executed"] + trace_stack_overflow = self._data["Optimization trace stack overflow"] + trace_stack_underflow = self._data["Optimization trace stack underflow"] + trace_too_long = self._data["Optimization trace too long"] + trace_too_short = self._data["Optimization trace too short"] + inner_loop = self._data["Optimization inner loop"] + recursive_call = self._data["Optimization recursive call"] + low_confidence = self._data["Optimization low confidence"] + + return { + "Optimization attempts": (attempts, None), + "Traces created": (created, attempts), + "Trace stack overflow": (trace_stack_overflow, attempts), + "Trace stack underflow": (trace_stack_underflow, attempts), + "Trace too long": (trace_too_long, attempts), + "Trace too short": (trace_too_short, attempts), + "Inner loop found": (inner_loop, attempts), + "Recursive call": (recursive_call, attempts), + "Low confidence": (low_confidence, attempts), + "Traces executed": (executed, None), + "Uops executed": (uops, executed), + } + + def get_histogram(self, prefix: str) -> list[tuple[int, int]]: + rows = [] + for k, v in self._data.items(): + match = re.match(f"{prefix}\\[([0-9]+)\\]", k) + if match is not None: + entry = int(match.groups()[0]) + rows.append((entry, v)) + rows.sort() + return rows + + +class Count(int): + def markdown(self) -> str: + return format(self, ",d") + + +class Ratio: + def __init__(self, num: int, den: int | None, percentage: bool = True): + self.num = num + self.den = den + self.percentage = percentage + + def __float__(self): + if self.den == 0: + return 0.0 + elif self.den is None: + return self.num + else: + return self.num / self.den + + def markdown(self) -> str: + if self.den is None: + return "" + elif self.den == 0: + if self.num != 0: + return f"{self.num:,} / 0 !!" + return "" + elif self.percentage: + return f"{self.num / self.den:,.01%}" + else: + return f"{self.num / self.den:,.02f}" + + +class DiffRatio(Ratio): + def __init__(self, base: int | str, head: int | str): + if isinstance(base, str) or isinstance(head, str): + super().__init__(0, 0) else: - basic += count - return basic, not_specialized, specialized + super().__init__(head - base, base) + + +class JoinMode(enum.Enum): + # Join using the first column as a key + SIMPLE = 0 + # Join using the first column as a key, and indicate the change in the + # second column of each input table as a new column + CHANGE = 1 + # Join using the first column as a key, indicating the change in the second + # column of each input table as a ne column, and omit all other columns + CHANGE_ONE_COLUMN = 2 + + +class Table: + """ + A Table defines how to convert a set of Stats into a specific set of rows + displaying some aspect of the data. + """ + + def __init__( + self, + column_names: Columns, + calc_rows: RowCalculator, + join_mode: JoinMode = JoinMode.SIMPLE, + ): + self.columns = column_names + self.calc_rows = calc_rows + self.join_mode = join_mode + + def join_row(self, key: str, row_a: tuple, row_b: tuple) -> tuple: + match self.join_mode: + case JoinMode.SIMPLE: + return (key, *row_a, *row_b) + case JoinMode.CHANGE: + return (key, *row_a, *row_b, DiffRatio(row_a[0], row_b[0])) + case JoinMode.CHANGE_ONE_COLUMN: + return (key, row_a[0], row_b[0], DiffRatio(row_a[0], row_b[0])) + + def join_columns(self, columns: Columns) -> Columns: + match self.join_mode: + case JoinMode.SIMPLE: + return ( + columns[0], + *("Base " + x for x in columns[1:]), + *("Head " + x for x in columns[1:]), + ) + case JoinMode.CHANGE: + return ( + columns[0], + *("Base " + x for x in columns[1:]), + *("Head " + x for x in columns[1:]), + ) + ("Change:",) + case JoinMode.CHANGE_ONE_COLUMN: + return ( + columns[0], + "Base " + columns[1], + "Head " + columns[1], + "Change:", + ) + + def join_tables(self, rows_a: Rows, rows_b: Rows) -> tuple[Columns, Rows]: + ncols = len(self.columns) + + default = ("",) * (ncols - 1) + data_a = {x[0]: x[1:] for x in rows_a} + data_b = {x[0]: x[1:] for x in rows_b} + + if len(data_a) != len(rows_a) or len(data_b) != len(rows_b): + raise ValueError("Duplicate keys") + + # To preserve ordering, use A's keys as is and then add any in B that + # aren't in A + keys = list(data_a.keys()) + [k for k in data_b.keys() if k not in data_a] + rows = [ + self.join_row(k, data_a.get(k, default), data_b.get(k, default)) + for k in keys + ] + if self.join_mode in (JoinMode.CHANGE, JoinMode.CHANGE_ONE_COLUMN): + rows.sort(key=lambda row: abs(float(row[-1])), reverse=True) + + columns = self.join_columns(self.columns) + return columns, rows + + def get_table( + self, base_stats: Stats, head_stats: Stats | None = None + ) -> tuple[Columns, Rows]: + if head_stats is None: + rows = self.calc_rows(base_stats) + return self.columns, rows + else: + rows_a = self.calc_rows(base_stats) + rows_b = self.calc_rows(head_stats) + cols, rows = self.join_tables(rows_a, rows_b) + return cols, rows -def print_title(name, level=2): - print("#"*level, name) - print() class Section: + """ + A Section defines a section of the output document. + """ - def __init__(self, title, level=2, summary=None): + def __init__( + self, + title: str = "", + summary: str = "", + part_iter=None, + comparative: bool = True, + ): self.title = title - self.level = level - if summary is None: + if not summary: self.summary = title.lower() else: self.summary = summary + if part_iter is None: + part_iter = [] + if isinstance(part_iter, list): - def __enter__(self): - print_title(self.title, self.level) - print("
") - print("", self.summary, "") - print() - return self - - def __exit__(*args): - print() - print("
") - print() - -def to_str(x): - if isinstance(x, int): - return format(x, ",d") - else: - return str(x) - -def emit_table(header, rows): - width = len(header) - header_line = "|" - under_line = "|" - for item in header: - under = "---" - if item.endswith(":"): - item = item[:-1] - under += ":" - header_line += item + " | " - under_line += under + "|" - print(header_line) - print(under_line) - for row in rows: - if width is not None and len(row) != width: - raise ValueError("Wrong number of elements in row '" + str(row) + "'") - print("|", " | ".join(to_str(i) for i in row), "|") - print() - -def calculate_execution_counts(opcode_stats, total): - counts = [] - for i, opcode_stat in enumerate(opcode_stats): - if "execution_count" in opcode_stat: - count = opcode_stat['execution_count'] - miss = 0 - if "specializable" not in opcode_stat: - miss = opcode_stat.get("specialization.miss") - counts.append((count, opname[i], miss)) - counts.sort(reverse=True) - cumulative = 0 - rows = [] - for (count, name, miss) in counts: - cumulative += count - if miss: - miss = format_ratio(miss, count) + def iter_parts(base_stats: Stats, head_stats: Stats | None): + yield from part_iter + + self.part_iter = iter_parts else: - miss = "" - rows.append((name, count, format_ratio(count, total), - format_ratio(cumulative, total), miss)) - return rows - -def emit_execution_counts(opcode_stats, total): - with Section("Execution counts", summary="execution counts for all instructions"): - rows = calculate_execution_counts(opcode_stats, total) - emit_table( - ("Name", "Count:", "Self:", "Cumulative:", "Miss ratio:"), - rows - ) + self.part_iter = part_iter + self.comparative = comparative -def emit_comparative_execution_counts( - base_opcode_stats, base_total, head_opcode_stats, head_total -): - with Section("Execution counts", summary="execution counts for all instructions"): - base_rows = calculate_execution_counts(base_opcode_stats, base_total) - head_rows = calculate_execution_counts(head_opcode_stats, head_total) - base_data = dict((x[0], x[1:]) for x in base_rows) - head_data = dict((x[0], x[1:]) for x in head_rows) - opcodes = set(base_data.keys()) | set(head_data.keys()) - rows = [] - default = [0, "0.0%", "0.0%", 0] - for opcode in opcodes: - base_entry = base_data.get(opcode, default) - head_entry = head_data.get(opcode, default) - if base_entry[0] == 0: - change = 1 +def calc_execution_count_table(prefix: str) -> RowCalculator: + def calc(stats: Stats) -> Rows: + opcode_stats = stats.get_opcode_stats(prefix) + counts = opcode_stats.get_execution_counts() + total = opcode_stats.get_total_execution_count() + cumulative = 0 + rows: Rows = [] + for opcode, (count, miss) in sorted( + counts.items(), key=itemgetter(1), reverse=True + ): + cumulative += count + if miss: + miss_val = Ratio(miss, count) else: - change = (head_entry[0] - base_entry[0]) / base_entry[0] + miss_val = None rows.append( - (opcode, base_entry[0], head_entry[0], - f"{100*change:0.1f}%")) + ( + opcode, + Count(count), + Ratio(count, total), + Ratio(cumulative, total), + miss_val, + ) + ) + return rows - rows.sort(key=lambda x: -abs(float(x[-1][:-1]))) + return calc - emit_table( - ("Name", "Base Count:", "Head Count:", "Change:"), - rows - ) -def get_defines(): - spec_path = os.path.join(os.path.dirname(__file__), "../../Python/specialize.c") - with open(spec_path) as spec_src: - defines = parse_kinds(spec_src) - return defines - -def emit_specialization_stats(opcode_stats): - defines = get_defines() - with Section("Specialization stats", summary="specialization stats by family"): - for i, opcode_stat in enumerate(opcode_stats): - name = opname[i] - print_specialization_stats(name, opcode_stat, defines) - -def emit_comparative_specialization_stats(base_opcode_stats, head_opcode_stats): - defines = get_defines() - with Section("Specialization stats", summary="specialization stats by family"): - for i, (base_opcode_stat, head_opcode_stat) in enumerate(zip(base_opcode_stats, head_opcode_stats)): - name = opname[i] - print_comparative_specialization_stats(name, base_opcode_stat, head_opcode_stat, defines) - -def calculate_specialization_effectiveness(opcode_stats, total): - basic, not_specialized, specialized = categorized_counts(opcode_stats) - return [ - ("Basic", basic, format_ratio(basic, total)), - ("Not specialized", not_specialized, format_ratio(not_specialized, total)), - ("Specialized", specialized, format_ratio(specialized, total)), - ] - -def emit_specialization_overview(opcode_stats, total): - with Section("Specialization effectiveness"): - rows = calculate_specialization_effectiveness(opcode_stats, total) - emit_table(("Instructions", "Count:", "Ratio:"), rows) - for title, field in (("Deferred", "specialization.deferred"), ("Misses", "specialization.miss")): - total = 0 - counts = [] - for i, opcode_stat in enumerate(opcode_stats): - # Avoid double counting misses - if title == "Misses" and "specializable" in opcode_stat: - continue - value = opcode_stat.get(field, 0) - counts.append((value, opname[i])) - total += value - counts.sort(reverse=True) - if total: - with Section(f"{title} by instruction", 3): - rows = [ (name, count, format_ratio(count, total)) for (count, name) in counts[:10] ] - emit_table(("Name", "Count:", "Ratio:"), rows) - -def emit_comparative_specialization_overview(base_opcode_stats, base_total, head_opcode_stats, head_total): - with Section("Specialization effectiveness"): - base_rows = calculate_specialization_effectiveness(base_opcode_stats, base_total) - head_rows = calculate_specialization_effectiveness(head_opcode_stats, head_total) - emit_table( - ("Instructions", "Base Count:", "Base Ratio:", "Head Count:", "Head Ratio:"), - join_rows(base_rows, head_rows) - ) +def execution_count_section() -> Section: + return Section( + "Execution counts", + "execution counts for all instructions", + [ + Table( + ("Name", "Count:", "Self:", "Cumulative:", "Miss ratio:"), + calc_execution_count_table("opcode"), + join_mode=JoinMode.CHANGE_ONE_COLUMN, + ) + ], + ) -def get_stats_defines(): - stats_path = os.path.join(os.path.dirname(__file__), "../../Include/pystats.h") - with open(stats_path) as stats_src: - defines = parse_kinds(stats_src, prefix="EVAL_CALL") - return defines - -def calculate_call_stats(stats): - defines = get_stats_defines() - total = 0 - for key, value in stats.items(): - if "Calls to" in key: - total += value - rows = [] - for key, value in stats.items(): - if "Calls to" in key: - rows.append((key, value, format_ratio(value, total))) - elif key.startswith("Calls "): - name, index = key[:-1].split("[") - index = int(index) - label = name + " (" + pretty(defines[index][0]) + ")" - rows.append((label, value, format_ratio(value, total))) - for key, value in stats.items(): - if key.startswith("Frame"): - rows.append((key, value, format_ratio(value, total))) - return rows - -def emit_call_stats(stats): - with Section("Call stats", summary="Inlined calls and frame stats"): - rows = calculate_call_stats(stats) - emit_table(("", "Count:", "Ratio:"), rows) - -def emit_comparative_call_stats(base_stats, head_stats): - with Section("Call stats", summary="Inlined calls and frame stats"): - base_rows = calculate_call_stats(base_stats) - head_rows = calculate_call_stats(head_stats) - rows = join_rows(base_rows, head_rows) - rows.sort(key=lambda x: -float(x[-1][:-1])) - emit_table( - ("", "Base Count:", "Base Ratio:", "Head Count:", "Head Ratio:"), - rows - ) -def calculate_object_stats(stats): - total_materializations = stats.get("Object new values") - total_allocations = stats.get("Object allocations") + stats.get("Object allocations from freelist") - total_increfs = stats.get("Object interpreter increfs") + stats.get("Object increfs") - total_decrefs = stats.get("Object interpreter decrefs") + stats.get("Object decrefs") - rows = [] - for key, value in stats.items(): - if key.startswith("Object"): - if "materialize" in key: - ratio = format_ratio(value, total_materializations) - elif "allocations" in key: - ratio = format_ratio(value, total_allocations) - elif "increfs" in key: - ratio = format_ratio(value, total_increfs) - elif "decrefs" in key: - ratio = format_ratio(value, total_decrefs) - else: - ratio = "" - label = key[6:].strip() - label = label[0].upper() + label[1:] - rows.append((label, value, ratio)) - return rows - -def calculate_gc_stats(stats): - gc_stats = [] - for key, value in stats.items(): - if not key.startswith("GC"): - continue - n, _, rest = key[3:].partition("]") - name = rest.strip() - gen_n = int(n) - while len(gc_stats) <= gen_n: - gc_stats.append({}) - gc_stats[gen_n][name] = value - return [ - (i, gen["collections"], gen["objects collected"], gen["object visits"]) - for (i, gen) in enumerate(gc_stats) - ] - -def emit_object_stats(stats): - with Section("Object stats", summary="allocations, frees and dict materializatons"): - rows = calculate_object_stats(stats) - emit_table(("", "Count:", "Ratio:"), rows) - -def emit_comparative_object_stats(base_stats, head_stats): - with Section("Object stats", summary="allocations, frees and dict materializatons"): - base_rows = calculate_object_stats(base_stats) - head_rows = calculate_object_stats(head_stats) - emit_table(("", "Base Count:", "Base Ratio:", "Head Count:", "Head Ratio:"), join_rows(base_rows, head_rows)) - -def emit_gc_stats(stats): - with Section("GC stats", summary="GC collections and effectiveness"): - rows = calculate_gc_stats(stats) - emit_table(("Generation:", "Collections:", "Objects collected:", "Object visits:"), rows) - -def emit_comparative_gc_stats(base_stats, head_stats): - with Section("GC stats", summary="GC collections and effectiveness"): - base_rows = calculate_gc_stats(base_stats) - head_rows = calculate_gc_stats(head_stats) - emit_table( - ("Generation:", - "Base collections:", "Head collections:", - "Base objects collected:", "Head objects collected:", - "Base object visits:", "Head object visits:"), - join_rows(base_rows, head_rows)) - -def get_total(opcode_stats): - total = 0 - for opcode_stat in opcode_stats: - if "execution_count" in opcode_stat: - total += opcode_stat['execution_count'] - return total - -def emit_pair_counts(opcode_stats, total): - pair_counts = [] - for i, opcode_stat in enumerate(opcode_stats): - if i == 0: - continue - for key, value in opcode_stat.items(): - if key.startswith("pair_count"): - x, _, _ = key[11:].partition("]") - if value: - pair_counts.append((value, (i, int(x)))) - with Section("Pair counts", summary="Pair counts for top 100 pairs"): - pair_counts.sort(reverse=True) +def pair_count_section() -> Section: + def calc_pair_count_table(stats: Stats) -> Rows: + opcode_stats = stats.get_opcode_stats("opcode") + pair_counts = opcode_stats.get_pair_counts() + total = opcode_stats.get_total_execution_count() + cumulative = 0 - rows = [] - for (count, pair) in itertools.islice(pair_counts, 100): - i, j = pair + rows: Rows = [] + for (opcode_i, opcode_j), count in itertools.islice( + sorted(pair_counts.items(), key=itemgetter(1), reverse=True), 100 + ): cumulative += count - rows.append((opname[i] + " " + opname[j], count, format_ratio(count, total), - format_ratio(cumulative, total))) - emit_table(("Pair", "Count:", "Self:", "Cumulative:"), - rows - ) - with Section("Predecessor/Successor Pairs", summary="Top 5 predecessors and successors of each opcode"): - predecessors = collections.defaultdict(collections.Counter) - successors = collections.defaultdict(collections.Counter) - total_predecessors = collections.Counter() - total_successors = collections.Counter() - for count, (first, second) in pair_counts: - if count: - predecessors[second][first] = count - successors[first][second] = count - total_predecessors[second] += count - total_successors[first] += count - for name, i in opmap.items(): - total1 = total_predecessors[i] - total2 = total_successors[i] - if total1 == 0 and total2 == 0: - continue - pred_rows = succ_rows = () - if total1: - pred_rows = [(opname[pred], count, f"{count/total1:.1%}") - for (pred, count) in predecessors[i].most_common(5)] - if total2: - succ_rows = [(opname[succ], count, f"{count/total2:.1%}") - for (succ, count) in successors[i].most_common(5)] - with Section(name, 3, f"Successors and predecessors for {name}"): - emit_table(("Predecessors", "Count:", "Percentage:"), - pred_rows + rows.append( + ( + f"{opcode_i} {opcode_j}", + Count(count), + Ratio(count, total), + Ratio(cumulative, total), ) - emit_table(("Successors", "Count:", "Percentage:"), - succ_rows + ) + return rows + + return Section( + "Pair counts", + "Pair counts for top 100 pairs", + [ + Table( + ("Pair", "Count:", "Self:", "Cumulative:"), + calc_pair_count_table, + ) + ], + comparative=False, + ) + + +def pre_succ_pairs_section() -> Section: + def iter_pre_succ_pairs_tables(base_stats: Stats, head_stats: Stats | None = None): + assert head_stats is None + + opcode_stats = base_stats.get_opcode_stats("opcode") + + for opcode in opcode_stats.get_opcode_names(): + predecessors = opcode_stats.get_predecessors(opcode) + successors = opcode_stats.get_successors(opcode) + predecessors_total = predecessors.total() + successors_total = successors.total() + if predecessors_total == 0 and successors_total == 0: + continue + pred_rows = [ + (pred, Count(count), Ratio(count, predecessors_total)) + for (pred, count) in predecessors.most_common(5) + ] + succ_rows = [ + (succ, Count(count), Ratio(count, successors_total)) + for (succ, count) in successors.most_common(5) + ] + + yield Section( + opcode, + f"Successors and predecessors for {opcode}", + [ + Table( + ("Predecessors", "Count:", "Percentage:"), + lambda *_: pred_rows, # type: ignore + ), + Table( + ("Successors", "Count:", "Percentage:"), + lambda *_: succ_rows, # type: ignore + ), + ], + ) + + return Section( + "Predecessor/Successor Pairs", + "Top 5 predecessors and successors of each opcode", + iter_pre_succ_pairs_tables, + comparative=False, + ) + + +def specialization_section() -> Section: + def calc_specialization_table(opcode: str) -> RowCalculator: + def calc(stats: Stats) -> Rows: + opcode_stats = stats.get_opcode_stats("opcode") + total = opcode_stats.get_specialization_total(opcode) + specialization_counts = opcode_stats.get_specialization_counts(opcode) + + return [ + ( + f"{label:>12}", + Count(count), + Ratio(count, total), ) + for label, count in specialization_counts.items() + ] + + return calc + + def calc_specialization_success_failure_table(name: str) -> RowCalculator: + def calc(stats: Stats) -> Rows: + values = stats.get_opcode_stats( + "opcode" + ).get_specialization_success_failure(name) + total = sum(values.values()) + if total: + return [ + (label.capitalize(), Count(val), Ratio(val, total)) + for label, val in values.items() + ] + else: + return [] + + return calc + + def calc_specialization_failure_kind_table(name: str) -> RowCalculator: + def calc(stats: Stats) -> Rows: + opcode_stats = stats.get_opcode_stats("opcode") + failures = opcode_stats.get_specialization_failure_kinds(name) + total = opcode_stats.get_specialization_failure_total(name) + + return sorted( + [ + (label, Count(value), Ratio(value, total)) + for label, value in failures.items() + if value + ], + key=itemgetter(1), + reverse=True, + ) + + return calc + + def iter_specialization_tables(base_stats: Stats, head_stats: Stats | None = None): + opcode_base_stats = base_stats.get_opcode_stats("opcode") + names = opcode_base_stats.get_opcode_names() + if head_stats is not None: + opcode_head_stats = head_stats.get_opcode_stats("opcode") + names &= opcode_head_stats.get_opcode_names() # type: ignore + else: + opcode_head_stats = None + + for opcode in sorted(names): + if not opcode_base_stats.is_specializable(opcode): + continue + if opcode_base_stats.get_specialization_total(opcode) == 0 and ( + opcode_head_stats is None + or opcode_head_stats.get_specialization_total(opcode) == 0 + ): + continue + yield Section( + opcode, + f"specialization stats for {opcode} family", + [ + Table( + ("Kind", "Count:", "Ratio:"), + calc_specialization_table(opcode), + JoinMode.CHANGE, + ), + Table( + ("", "Count:", "Ratio:"), + calc_specialization_success_failure_table(opcode), + JoinMode.CHANGE, + ), + Table( + ("Failure kind", "Count:", "Ratio:"), + calc_specialization_failure_kind_table(opcode), + JoinMode.CHANGE, + ), + ], + ) -def output_single_stats(stats): - opcode_stats = extract_opcode_stats(stats) - total = get_total(opcode_stats) - emit_execution_counts(opcode_stats, total) - emit_pair_counts(opcode_stats, total) - emit_specialization_stats(opcode_stats) - emit_specialization_overview(opcode_stats, total) - emit_call_stats(stats) - emit_object_stats(stats) - emit_gc_stats(stats) - with Section("Meta stats", summary="Meta statistics"): - emit_table(("", "Count:"), [('Number of data files', stats['__nfiles__'])]) - - -def output_comparative_stats(base_stats, head_stats): - base_opcode_stats = extract_opcode_stats(base_stats) - base_total = get_total(base_opcode_stats) - - head_opcode_stats = extract_opcode_stats(head_stats) - head_total = get_total(head_opcode_stats) - - emit_comparative_execution_counts( - base_opcode_stats, base_total, head_opcode_stats, head_total + return Section( + "Specialization stats", + "specialization stats by family", + iter_specialization_tables, ) - emit_comparative_specialization_stats( - base_opcode_stats, head_opcode_stats + + +def specialization_effectiveness_section() -> Section: + def calc_specialization_effectiveness_table(stats: Stats) -> Rows: + opcode_stats = stats.get_opcode_stats("opcode") + total = opcode_stats.get_total_execution_count() + + ( + basic, + specialized_hits, + specialized_misses, + not_specialized, + ) = opcode_stats.get_specialized_total_counts() + + return [ + ("Basic", Count(basic), Ratio(basic, total)), + ( + "Not specialized", + Count(not_specialized), + Ratio(not_specialized, total), + ), + ( + "Specialized hits", + Count(specialized_hits), + Ratio(specialized_hits, total), + ), + ( + "Specialized misses", + Count(specialized_misses), + Ratio(specialized_misses, total), + ), + ] + + def calc_deferred_by_table(stats: Stats) -> Rows: + opcode_stats = stats.get_opcode_stats("opcode") + deferred_counts = opcode_stats.get_deferred_counts() + total = sum(deferred_counts.values()) + if total == 0: + return [] + + return [ + (name, Count(value), Ratio(value, total)) + for name, value in sorted( + deferred_counts.items(), key=itemgetter(1), reverse=True + )[:10] + ] + + def calc_misses_by_table(stats: Stats) -> Rows: + opcode_stats = stats.get_opcode_stats("opcode") + misses_counts = opcode_stats.get_misses_counts() + total = sum(misses_counts.values()) + if total == 0: + return [] + + return [ + (name, Count(value), Ratio(value, total)) + for name, value in sorted( + misses_counts.items(), key=itemgetter(1), reverse=True + )[:10] + ] + + return Section( + "Specialization effectiveness", + "", + [ + Table( + ("Instructions", "Count:", "Ratio:"), + calc_specialization_effectiveness_table, + JoinMode.CHANGE, + ), + Section( + "Deferred by instruction", + "", + [ + Table( + ("Name", "Count:", "Ratio:"), + calc_deferred_by_table, + JoinMode.CHANGE, + ) + ], + ), + Section( + "Misses by instruction", + "", + [ + Table( + ("Name", "Count:", "Ratio:"), + calc_misses_by_table, + JoinMode.CHANGE, + ) + ], + ), + ], ) - emit_comparative_specialization_overview( - base_opcode_stats, base_total, head_opcode_stats, head_total + + +def call_stats_section() -> Section: + def calc_call_stats_table(stats: Stats) -> Rows: + call_stats = stats.get_call_stats() + total = sum(v for k, v in call_stats.items() if "Calls to" in k) + return [ + (key, Count(value), Ratio(value, total)) + for key, value in call_stats.items() + ] + + return Section( + "Call stats", + "Inlined calls and frame stats", + [ + Table( + ("", "Count:", "Ratio:"), + calc_call_stats_table, + JoinMode.CHANGE, + ) + ], ) - emit_comparative_call_stats(base_stats, head_stats) - emit_comparative_object_stats(base_stats, head_stats) - emit_comparative_gc_stats(base_stats, head_stats) - -def output_stats(inputs, json_output=None): - if len(inputs) == 1: - stats = gather_stats(inputs[0]) - if json_output is not None: - json.dump(stats, json_output) - output_single_stats(stats) - elif len(inputs) == 2: - if json_output is not None: - raise ValueError( - "Can not output to JSON when there are multiple inputs" + + +def object_stats_section() -> Section: + def calc_object_stats_table(stats: Stats) -> Rows: + object_stats = stats.get_object_stats() + return [ + (label, Count(value), Ratio(value, den)) + for label, (value, den) in object_stats.items() + ] + + return Section( + "Object stats", + "allocations, frees and dict materializatons", + [ + Table( + ("", "Count:", "Ratio:"), + calc_object_stats_table, + JoinMode.CHANGE, + ) + ], + ) + + +def gc_stats_section() -> Section: + def calc_gc_stats(stats: Stats) -> Rows: + gc_stats = stats.get_gc_stats() + + return [ + ( + Count(i), + Count(gen["collections"]), + Count(gen["objects collected"]), + Count(gen["object visits"]), + ) + for (i, gen) in enumerate(gc_stats) + ] + + return Section( + "GC stats", + "GC collections and effectiveness", + [ + Table( + ("Generation:", "Collections:", "Objects collected:", "Object visits:"), + calc_gc_stats, + ) + ], + ) + + +def optimization_section() -> Section: + def calc_optimization_table(stats: Stats) -> Rows: + optimization_stats = stats.get_optimization_stats() + + return [ + ( + label, + Count(value), + Ratio(value, den, percentage=label != "Uops executed"), ) + for label, (value, den) in optimization_stats.items() + ] + + def calc_histogram_table(key: str, den: str) -> RowCalculator: + def calc(stats: Stats) -> Rows: + histogram = stats.get_histogram(key) + denominator = stats.get(den) + + rows: Rows = [] + last_non_zero = 0 + for k, v in histogram: + if v != 0: + last_non_zero = len(rows) + rows.append( + ( + f"<= {k:,d}", + Count(v), + Ratio(v, denominator), + ) + ) + # Don't include any zero entries at the end + rows = rows[: last_non_zero + 1] + return rows + + return calc + + def calc_unsupported_opcodes_table(stats: Stats) -> Rows: + unsupported_opcodes = stats.get_opcode_stats("unsupported_opcode") + return sorted( + [ + (opcode, Count(count)) + for opcode, count in unsupported_opcodes.get_opcode_counts().items() + ], + key=itemgetter(1), + reverse=True, + ) - base_stats = gather_stats(inputs[0]) - head_stats = gather_stats(inputs[1]) - output_comparative_stats(base_stats, head_stats) + def iter_optimization_tables(base_stats: Stats, head_stats: Stats | None = None): + if not base_stats.get_optimization_stats() or ( + head_stats is not None and not head_stats.get_optimization_stats() + ): + return + + yield Table(("", "Count:", "Ratio:"), calc_optimization_table, JoinMode.CHANGE) + for name, den in [ + ("Trace length", "Optimization traces created"), + ("Optimized trace length", "Optimization traces created"), + ("Trace run length", "Optimization traces executed"), + ]: + yield Section( + f"{name} histogram", + "", + [ + Table( + ("Range", "Count:", "Ratio:"), + calc_histogram_table(name, den), + JoinMode.CHANGE, + ) + ], + ) + yield Section( + "Uop execution stats", + "", + [ + Table( + ("Name", "Count:", "Self:", "Cumulative:", "Miss ratio:"), + calc_execution_count_table("uops"), + JoinMode.CHANGE_ONE_COLUMN, + ) + ], + ) + yield Section( + "Unsupported opcodes", + "", + [ + Table( + ("Opcode", "Count:"), + calc_unsupported_opcodes_table, + JoinMode.CHANGE, + ) + ], + ) + + return Section( + "Optimization (Tier 2) stats", + "statistics about the Tier 2 optimizer", + iter_optimization_tables, + ) + + +def meta_stats_section() -> Section: + def calc_rows(stats: Stats) -> Rows: + return [("Number of data files", Count(stats.get("__nfiles__")))] + + return Section( + "Meta stats", + "Meta statistics", + [Table(("", "Count:"), calc_rows, JoinMode.CHANGE)], + ) + + +LAYOUT = [ + execution_count_section(), + pair_count_section(), + pre_succ_pairs_section(), + specialization_section(), + specialization_effectiveness_section(), + call_stats_section(), + object_stats_section(), + gc_stats_section(), + optimization_section(), + meta_stats_section(), +] + + +def output_markdown( + out: TextIO, + obj: Section | Table | list, + base_stats: Stats, + head_stats: Stats | None = None, + level: int = 2, +) -> None: + def to_markdown(x): + if hasattr(x, "markdown"): + return x.markdown() + elif isinstance(x, str): + return x + elif x is None: + return "" + else: + raise TypeError(f"Can't convert {x} to markdown") + + match obj: + case Section(): + if obj.title: + print("#" * level, obj.title, file=out) + print(file=out) + print("
", file=out) + print("", obj.summary, "", file=out) + print(file=out) + if head_stats is not None and obj.comparative is False: + print("Not included in comparative output.\n") + else: + for part in obj.part_iter(base_stats, head_stats): + output_markdown(out, part, base_stats, head_stats, level=level + 1) + print(file=out) + if obj.title: + print("
", file=out) + print(file=out) + + case Table(): + header, rows = obj.get_table(base_stats, head_stats) + if len(rows) == 0: + return + + width = len(header) + header_line = "|" + under_line = "|" + for item in header: + under = "---" + if item.endswith(":"): + item = item[:-1] + under += ":" + header_line += item + " | " + under_line += under + "|" + print(header_line, file=out) + print(under_line, file=out) + for row in rows: + if len(row) != width: + raise ValueError( + "Wrong number of elements in row '" + str(row) + "'" + ) + print("|", " | ".join(to_markdown(i) for i in row), "|", file=out) + print(file=out) + + case list(): + for part in obj: + output_markdown(out, part, base_stats, head_stats, level=level) + + print("---", file=out) + print("Stats gathered on:", date.today(), file=out) + + +def output_stats(inputs: list[Path], json_output=str | None): + match len(inputs): + case 1: + data = load_raw_data(Path(inputs[0])) + if json_output is not None: + with open(json_output, 'w', encoding='utf-8') as f: + save_raw_data(data, f) # type: ignore + stats = Stats(data) + output_markdown(sys.stdout, LAYOUT, stats) + case 2: + if json_output is not None: + raise ValueError( + "Can not output to JSON when there are multiple inputs" + ) + base_data = load_raw_data(Path(inputs[0])) + head_data = load_raw_data(Path(inputs[1])) + base_stats = Stats(base_data) + head_stats = Stats(head_data) + output_markdown(sys.stdout, LAYOUT, base_stats, head_stats) - print("---") - print("Stats gathered on:", date.today()) def main(): parser = argparse.ArgumentParser(description="Summarize pystats results") @@ -665,14 +1190,13 @@ def main(): If one source is provided, its stats are printed. If two sources are provided, comparative stats are printed. Default is {DEFAULT_DIR}. - """ + """, ) parser.add_argument( "--json-output", nargs="?", - type=argparse.FileType("w"), - help="Output complete raw results to the given JSON file." + help="Output complete raw results to the given JSON file.", ) args = parser.parse_args() @@ -682,5 +1206,6 @@ def main(): output_stats(args.inputs, json_output=args.json_output) + if __name__ == "__main__": main() diff --git a/Tools/ssl/make_ssl_data.py b/Tools/ssl/make_ssl_data.py index ab1134ed8c4f77..98608716576792 100755 --- a/Tools/ssl/make_ssl_data.py +++ b/Tools/ssl/make_ssl_data.py @@ -23,7 +23,7 @@ ) parser.add_argument("srcdir", help="OpenSSL source directory") parser.add_argument( - "output", nargs="?", type=argparse.FileType("w"), default=sys.stdout + "output", nargs="?", default=None ) @@ -126,8 +126,13 @@ def main(): lines.append("") lines.extend(gen_error_codes(args)) - for line in lines: - args.output.write(line + "\n") + if args.output is None: + for line in lines: + print(line) + else: + with open(args.output, 'w') as output: + for line in lines: + print(line, file=output) if __name__ == "__main__": diff --git a/Tools/ssl/multissltests.py b/Tools/ssl/multissltests.py index f9809c9b54665b..120e3883adc795 100755 --- a/Tools/ssl/multissltests.py +++ b/Tools/ssl/multissltests.py @@ -46,9 +46,9 @@ ] OPENSSL_RECENT_VERSIONS = [ - "1.1.1u", - "3.0.9", - "3.1.1", + "1.1.1w", + "3.0.11", + "3.1.3", ] LIBRESSL_OLD_VERSIONS = [ @@ -151,7 +151,10 @@ class AbstractBuilder(object): build_template = None depend_target = None install_target = 'install' - jobs = os.cpu_count() + if hasattr(os, 'process_cpu_count'): + jobs = os.process_cpu_count() + else: + jobs = os.cpu_count() module_files = ( os.path.join(PYTHONROOT, "Modules/_ssl.c"), diff --git a/Tools/unicode/dawg.py b/Tools/unicode/dawg.py new file mode 100644 index 00000000000000..b74d602f6e1d79 --- /dev/null +++ b/Tools/unicode/dawg.py @@ -0,0 +1,533 @@ +# Original Algorithm: +# By Steve Hanov, 2011. Released to the public domain. +# Please see http://stevehanov.ca/blog/index.php?id=115 for the accompanying article. +# +# Adapted for PyPy/CPython by Carl Friedrich Bolz-Tereick +# +# Based on Daciuk, Jan, et al. "Incremental construction of minimal acyclic finite-state automata." +# Computational linguistics 26.1 (2000): 3-16. +# +# Updated 2014 to use DAWG as a mapping; see +# Kowaltowski, T.; CL. Lucchesi (1993), "Applications of finite automata representing large vocabularies", +# Software-Practice and Experience 1993 + +from collections import defaultdict +from functools import cached_property + + +# This class represents a node in the directed acyclic word graph (DAWG). It +# has a list of edges to other nodes. It has functions for testing whether it +# is equivalent to another node. Nodes are equivalent if they have identical +# edges, and each identical edge leads to identical states. The __hash__ and +# __eq__ functions allow it to be used as a key in a python dictionary. + + +class DawgNode: + + def __init__(self, dawg): + self.id = dawg.next_id + dawg.next_id += 1 + self.final = False + self.edges = {} + + self.linear_edges = None # later: list of (string, next_state) + + def __str__(self): + if self.final: + arr = ["1"] + else: + arr = ["0"] + + for (label, node) in sorted(self.edges.items()): + arr.append(label) + arr.append(str(node.id)) + + return "_".join(arr) + __repr__ = __str__ + + def _as_tuple(self): + edges = sorted(self.edges.items()) + edge_tuple = tuple((label, node.id) for label, node in edges) + return (self.final, edge_tuple) + + def __hash__(self): + return hash(self._as_tuple()) + + def __eq__(self, other): + return self._as_tuple() == other._as_tuple() + + @cached_property + def num_reachable_linear(self): + # returns the number of different paths to final nodes reachable from + # this one + + count = 0 + # staying at self counts as a path if self is final + if self.final: + count += 1 + for label, node in self.linear_edges: + count += node.num_reachable_linear + + return count + + +class Dawg: + def __init__(self): + self.previous_word = "" + self.next_id = 0 + self.root = DawgNode(self) + + # Here is a list of nodes that have not been checked for duplication. + self.unchecked_nodes = [] + + # To deduplicate, maintain a dictionary with + # minimized_nodes[canonical_node] is canonical_node. + # Based on __hash__ and __eq__, minimized_nodes[n] is the + # canonical node equal to n. + # In other words, self.minimized_nodes[x] == x for all nodes found in + # the dict. + self.minimized_nodes = {} + + # word: value mapping + self.data = {} + # value: word mapping + self.inverse = {} + + def insert(self, word, value): + if not all(0 <= ord(c) < 128 for c in word): + raise ValueError("Use 7-bit ASCII characters only") + if word <= self.previous_word: + raise ValueError("Error: Words must be inserted in alphabetical order.") + if value in self.inverse: + raise ValueError(f"value {value} is duplicate, got it for word {self.inverse[value]} and now {word}") + + # find common prefix between word and previous word + common_prefix = 0 + for i in range(min(len(word), len(self.previous_word))): + if word[i] != self.previous_word[i]: + break + common_prefix += 1 + + # Check the unchecked_nodes for redundant nodes, proceeding from last + # one down to the common prefix size. Then truncate the list at that + # point. + self._minimize(common_prefix) + + self.data[word] = value + self.inverse[value] = word + + # add the suffix, starting from the correct node mid-way through the + # graph + if len(self.unchecked_nodes) == 0: + node = self.root + else: + node = self.unchecked_nodes[-1][2] + + for letter in word[common_prefix:]: + next_node = DawgNode(self) + node.edges[letter] = next_node + self.unchecked_nodes.append((node, letter, next_node)) + node = next_node + + node.final = True + self.previous_word = word + + def finish(self): + if not self.data: + raise ValueError("need at least one word in the dawg") + # minimize all unchecked_nodes + self._minimize(0) + + self._linearize_edges() + + topoorder, linear_data, inverse = self._topological_order() + return self.compute_packed(topoorder), linear_data, inverse + + def _minimize(self, down_to): + # proceed from the leaf up to a certain point + for i in range(len(self.unchecked_nodes) - 1, down_to - 1, -1): + (parent, letter, child) = self.unchecked_nodes[i] + if child in self.minimized_nodes: + # replace the child with the previously encountered one + parent.edges[letter] = self.minimized_nodes[child] + else: + # add the state to the minimized nodes. + self.minimized_nodes[child] = child + self.unchecked_nodes.pop() + + def _lookup(self, word): + """ Return an integer 0 <= k < number of strings in dawg + where word is the kth successful traversal of the dawg. """ + node = self.root + skipped = 0 # keep track of number of final nodes that we skipped + index = 0 + while index < len(word): + for label, child in node.linear_edges: + if word[index] == label[0]: + if word[index:index + len(label)] == label: + if node.final: + skipped += 1 + index += len(label) + node = child + break + else: + return None + skipped += child.num_reachable_linear + else: + return None + return skipped + + def enum_all_nodes(self): + stack = [self.root] + done = set() + while stack: + node = stack.pop() + if node.id in done: + continue + yield node + done.add(node.id) + for label, child in sorted(node.edges.items()): + stack.append(child) + + def prettyprint(self): + for node in sorted(self.enum_all_nodes(), key=lambda e: e.id): + s_final = " final" if node.final else "" + print(f"{node.id}: ({node}) {s_final}") + for label, child in sorted(node.edges.items()): + print(f" {label} goto {child.id}") + + def _inverse_lookup(self, number): + assert 0, "not working in the current form, but keep it as the pure python version of compact lookup" + result = [] + node = self.root + while 1: + if node.final: + if pos == 0: + return "".join(result) + pos -= 1 + for label, child in sorted(node.edges.items()): + nextpos = pos - child.num_reachable_linear + if nextpos < 0: + result.append(label) + node = child + break + else: + pos = nextpos + else: + assert 0 + + def _linearize_edges(self): + # compute "linear" edges. the idea is that long chains of edges without + # any of the intermediate states being final or any extra incoming or + # outgoing edges can be represented by having removing them, and + # instead using longer strings as edge labels (instead of single + # characters) + incoming = defaultdict(list) + nodes = sorted(self.enum_all_nodes(), key=lambda e: e.id) + for node in nodes: + for label, child in sorted(node.edges.items()): + incoming[child].append(node) + for node in nodes: + node.linear_edges = [] + for label, child in sorted(node.edges.items()): + s = [label] + while len(child.edges) == 1 and len(incoming[child]) == 1 and not child.final: + (c, child), = child.edges.items() + s.append(c) + node.linear_edges.append((''.join(s), child)) + + def _topological_order(self): + # compute reachable linear nodes, and the set of incoming edges for each node + order = [] + stack = [self.root] + seen = set() + while stack: + # depth first traversal + node = stack.pop() + if node.id in seen: + continue + seen.add(node.id) + order.append(node) + for label, child in node.linear_edges: + stack.append(child) + + # do a (slightly bad) topological sort + incoming = defaultdict(set) + for node in order: + for label, child in node.linear_edges: + incoming[child].add((label, node)) + no_incoming = [order[0]] + topoorder = [] + positions = {} + while no_incoming: + node = no_incoming.pop() + topoorder.append(node) + positions[node] = len(topoorder) + # use "reversed" to make sure that the linear_edges get reorderd + # from their alphabetical order as little as necessary (no_incoming + # is LIFO) + for label, child in reversed(node.linear_edges): + incoming[child].discard((label, node)) + if not incoming[child]: + no_incoming.append(child) + del incoming[child] + # check result + assert set(topoorder) == set(order) + assert len(set(topoorder)) == len(topoorder) + + for node in order: + node.linear_edges.sort(key=lambda element: positions[element[1]]) + + for node in order: + for label, child in node.linear_edges: + assert positions[child] > positions[node] + # number the nodes. afterwards every input string in the set has a + # unique number in the 0 <= number < len(data). We then put the data in + # self.data into a linear list using these numbers as indexes. + topoorder[0].num_reachable_linear + linear_data = [None] * len(self.data) + inverse = {} # maps value back to index + for word, value in self.data.items(): + index = self._lookup(word) + linear_data[index] = value + inverse[value] = index + + return topoorder, linear_data, inverse + + def compute_packed(self, order): + def compute_chunk(node, offsets): + """ compute the packed node/edge data for a node. result is a + list of bytes as long as order. the jump distance calculations use + the offsets dictionary to know where in the final big output + bytestring the individual nodes will end up. """ + result = bytearray() + offset = offsets[node] + encode_varint_unsigned(number_add_bits(node.num_reachable_linear, node.final), result) + if len(node.linear_edges) == 0: + assert node.final + encode_varint_unsigned(0, result) # add a 0 saying "done" + prev_child_offset = offset + len(result) + for edgeindex, (label, targetnode) in enumerate(node.linear_edges): + label = label.encode('ascii') + child_offset = offsets[targetnode] + child_offset_difference = child_offset - prev_child_offset + + info = number_add_bits(child_offset_difference, len(label) == 1, edgeindex == len(node.linear_edges) - 1) + if edgeindex == 0: + assert info != 0 + encode_varint_unsigned(info, result) + prev_child_offset = child_offset + if len(label) > 1: + encode_varint_unsigned(len(label), result) + result.extend(label) + return result + + def compute_new_offsets(chunks, offsets): + """ Given a list of chunks, compute the new offsets (by adding the + chunk lengths together). Also check if we cannot shrink the output + further because none of the node offsets are smaller now. if that's + the case return None. """ + new_offsets = {} + curr_offset = 0 + should_continue = False + for node, result in zip(order, chunks): + if curr_offset < offsets[node]: + # the new offset is below the current assumption, this + # means we can shrink the output more + should_continue = True + new_offsets[node] = curr_offset + curr_offset += len(result) + if not should_continue: + return None + return new_offsets + + # assign initial offsets to every node + offsets = {} + for i, node in enumerate(order): + # we don't know position of the edge yet, just use something big as + # the starting position. we'll have to do further iterations anyway, + # but the size is at least a lower limit then + offsets[node] = i * 2 ** 30 + + + # due to the variable integer width encoding of edge targets we need to + # run this to fixpoint. in the process we shrink the output more and + # more until we can't any more. at any point we can stop and use the + # output, but we might need padding zero bytes when joining the chunks + # to have the correct jump distances + last_offsets = None + while 1: + chunks = [compute_chunk(node, offsets) for node in order] + last_offsets = offsets + offsets = compute_new_offsets(chunks, offsets) + if offsets is None: # couldn't shrink + break + + # build the final packed string + total_result = bytearray() + for node, result in zip(order, chunks): + node_offset = last_offsets[node] + if node_offset > len(total_result): + # need to pad to get the offsets correct + padding = b"\x00" * (node_offset - len(total_result)) + total_result.extend(padding) + assert node_offset == len(total_result) + total_result.extend(result) + return bytes(total_result) + + +# ______________________________________________________________________ +# the following functions operate on the packed representation + +def number_add_bits(x, *bits): + for bit in bits: + assert bit == 0 or bit == 1 + x = (x << 1) | bit + return x + +def encode_varint_unsigned(i, res): + # https://en.wikipedia.org/wiki/LEB128 unsigned variant + more = True + startlen = len(res) + if i < 0: + raise ValueError("only positive numbers supported", i) + while more: + lowest7bits = i & 0b1111111 + i >>= 7 + if i == 0: + more = False + else: + lowest7bits |= 0b10000000 + res.append(lowest7bits) + return len(res) - startlen + +def number_split_bits(x, n, acc=()): + if n == 1: + return x >> 1, x & 1 + if n == 2: + return x >> 2, (x >> 1) & 1, x & 1 + assert 0, "implement me!" + +def decode_varint_unsigned(b, index=0): + res = 0 + shift = 0 + while True: + byte = b[index] + res = res | ((byte & 0b1111111) << shift) + index += 1 + shift += 7 + if not (byte & 0b10000000): + return res, index + +def decode_node(packed, node): + x, node = decode_varint_unsigned(packed, node) + node_count, final = number_split_bits(x, 1) + return node_count, final, node + +def decode_edge(packed, edgeindex, prev_child_offset, offset): + x, offset = decode_varint_unsigned(packed, offset) + if x == 0 and edgeindex == 0: + raise KeyError # trying to decode past a final node + child_offset_difference, len1, last_edge = number_split_bits(x, 2) + child_offset = prev_child_offset + child_offset_difference + if len1: + size = 1 + else: + size, offset = decode_varint_unsigned(packed, offset) + return child_offset, last_edge, size, offset + +def _match_edge(packed, s, size, node_offset, stringpos): + if size > 1 and stringpos + size > len(s): + # past the end of the string, can't match + return False + for i in range(size): + if packed[node_offset + i] != s[stringpos + i]: + # if a subsequent char of an edge doesn't match, the word isn't in + # the dawg + if i > 0: + raise KeyError + return False + return True + +def lookup(packed, data, s): + return data[_lookup(packed, s)] + +def _lookup(packed, s): + stringpos = 0 + node_offset = 0 + skipped = 0 # keep track of number of final nodes that we skipped + false = False + while stringpos < len(s): + #print(f"{node_offset=} {stringpos=}") + _, final, edge_offset = decode_node(packed, node_offset) + prev_child_offset = edge_offset + edgeindex = 0 + while 1: + child_offset, last_edge, size, edgelabel_chars_offset = decode_edge(packed, edgeindex, prev_child_offset, edge_offset) + #print(f" {edge_offset=} {child_offset=} {last_edge=} {size=} {edgelabel_chars_offset=}") + edgeindex += 1 + prev_child_offset = child_offset + if _match_edge(packed, s, size, edgelabel_chars_offset, stringpos): + # match + if final: + skipped += 1 + stringpos += size + node_offset = child_offset + break + if last_edge: + raise KeyError + descendant_count, _, _ = decode_node(packed, child_offset) + skipped += descendant_count + edge_offset = edgelabel_chars_offset + size + _, final, _ = decode_node(packed, node_offset) + if final: + return skipped + raise KeyError + +def inverse_lookup(packed, inverse, x): + pos = inverse[x] + return _inverse_lookup(packed, pos) + +def _inverse_lookup(packed, pos): + result = bytearray() + node_offset = 0 + while 1: + node_count, final, edge_offset = decode_node(packed, node_offset) + if final: + if pos == 0: + return bytes(result) + pos -= 1 + prev_child_offset = edge_offset + edgeindex = 0 + while 1: + child_offset, last_edge, size, edgelabel_chars_offset = decode_edge(packed, edgeindex, prev_child_offset, edge_offset) + edgeindex += 1 + prev_child_offset = child_offset + descendant_count, _, _ = decode_node(packed, child_offset) + nextpos = pos - descendant_count + if nextpos < 0: + assert edgelabel_chars_offset >= 0 + result.extend(packed[edgelabel_chars_offset: edgelabel_chars_offset + size]) + node_offset = child_offset + break + elif not last_edge: + pos = nextpos + edge_offset = edgelabel_chars_offset + size + else: + raise KeyError + else: + raise KeyError + + +def build_compression_dawg(ucdata): + d = Dawg() + ucdata.sort() + for name, value in ucdata: + d.insert(name, value) + packed, pos_to_code, reversedict = d.finish() + print("size of dawg [KiB]", round(len(packed) / 1024, 2)) + # check that lookup and inverse_lookup work correctly on the input data + for name, value in ucdata: + assert lookup(packed, pos_to_code, name.encode('ascii')) == value + assert inverse_lookup(packed, reversedict, value) == name.encode('ascii') + return packed, pos_to_code diff --git a/Tools/unicode/genmap_japanese.py b/Tools/unicode/genmap_japanese.py index 21de37b62bced0..838317fa54175e 100644 --- a/Tools/unicode/genmap_japanese.py +++ b/Tools/unicode/genmap_japanese.py @@ -2,7 +2,7 @@ # genmap_ja_codecs.py: Japanese Codecs Map Generator # # Original Author: Hye-Shik Chang -# Modified Author: Dong-hee Na +# Modified Author: Donghee Na # import os diff --git a/Tools/unicode/genmap_korean.py b/Tools/unicode/genmap_korean.py index 4b94a6c43e5382..4432a3601b7e3b 100644 --- a/Tools/unicode/genmap_korean.py +++ b/Tools/unicode/genmap_korean.py @@ -2,7 +2,7 @@ # genmap_korean.py: Korean Codecs Map Generator # # Original Author: Hye-Shik Chang -# Modified Author: Dong-hee Na +# Modified Author: Donghee Na # import os diff --git a/Tools/unicode/genmap_schinese.py b/Tools/unicode/genmap_schinese.py index 647c0333ed2728..862f1def71d122 100644 --- a/Tools/unicode/genmap_schinese.py +++ b/Tools/unicode/genmap_schinese.py @@ -2,7 +2,7 @@ # genmap_schinese.py: Simplified Chinese Codecs Map Generator # # Original Author: Hye-Shik Chang -# Modified Author: Dong-hee Na +# Modified Author: Donghee Na # import os import re diff --git a/Tools/unicode/genmap_support.py b/Tools/unicode/genmap_support.py index 5e1d9ee77b0002..4649bc3b7125fe 100644 --- a/Tools/unicode/genmap_support.py +++ b/Tools/unicode/genmap_support.py @@ -2,7 +2,7 @@ # genmap_support.py: Multibyte Codec Map Generator # # Original Author: Hye-Shik Chang -# Modified Author: Dong-hee Na +# Modified Author: Donghee Na # diff --git a/Tools/unicode/makeunicodedata.py b/Tools/unicode/makeunicodedata.py index 034642db06e48b..a5ac09eb96f19a 100644 --- a/Tools/unicode/makeunicodedata.py +++ b/Tools/unicode/makeunicodedata.py @@ -44,7 +44,7 @@ # * Doc/library/stdtypes.rst, and # * Doc/library/unicodedata.rst # * Doc/reference/lexical_analysis.rst (two occurrences) -UNIDATA_VERSION = "15.0.0" +UNIDATA_VERSION = "15.1.0" UNICODE_DATA = "UnicodeData%s.txt" COMPOSITION_EXCLUSIONS = "CompositionExclusions%s.txt" EASTASIAN_WIDTH = "EastAsianWidth%s.txt" @@ -101,15 +101,16 @@ # these ranges need to match unicodedata.c:is_unified_ideograph cjk_ranges = [ - ('3400', '4DBF'), - ('4E00', '9FFF'), - ('20000', '2A6DF'), - ('2A700', '2B739'), - ('2B740', '2B81D'), - ('2B820', '2CEA1'), - ('2CEB0', '2EBE0'), - ('30000', '3134A'), - ('31350', '323AF'), + ('3400', '4DBF'), # CJK Ideograph Extension A CJK + ('4E00', '9FFF'), # CJK Ideograph + ('20000', '2A6DF'), # CJK Ideograph Extension B + ('2A700', '2B739'), # CJK Ideograph Extension C + ('2B740', '2B81D'), # CJK Ideograph Extension D + ('2B820', '2CEA1'), # CJK Ideograph Extension E + ('2CEB0', '2EBE0'), # CJK Ideograph Extension F + ('2EBF0', '2EE5D'), # CJK Ideograph Extension I + ('30000', '3134A'), # CJK Ideograph Extension G + ('31350', '323AF'), # CJK Ideograph Extension H ] @@ -622,120 +623,12 @@ def makeunicodetype(unicode, trace): # unicode name database def makeunicodename(unicode, trace): + from dawg import build_compression_dawg FILE = "Modules/unicodename_db.h" print("--- Preparing", FILE, "...") - # collect names - names = [None] * len(unicode.chars) - - for char in unicode.chars: - record = unicode.table[char] - if record: - name = record.name.strip() - if name and name[0] != "<": - names[char] = name + chr(0) - - print(len([n for n in names if n is not None]), "distinct names") - - # collect unique words from names (note that we differ between - # words inside a sentence, and words ending a sentence. the - # latter includes the trailing null byte. - - words = {} - n = b = 0 - for char in unicode.chars: - name = names[char] - if name: - w = name.split() - b = b + len(name) - n = n + len(w) - for w in w: - l = words.get(w) - if l: - l.append(None) - else: - words[w] = [len(words)] - - print(n, "words in text;", b, "bytes") - - wordlist = list(words.items()) - - # sort on falling frequency, then by name - def word_key(a): - aword, alist = a - return -len(alist), aword - wordlist.sort(key=word_key) - - # figure out how many phrasebook escapes we need - escapes = 0 - while escapes * 256 < len(wordlist): - escapes = escapes + 1 - print(escapes, "escapes") - - short = 256 - escapes - - assert short > 0 - - print(short, "short indexes in lexicon") - - # statistics - n = 0 - for i in range(short): - n = n + len(wordlist[i][1]) - print(n, "short indexes in phrasebook") - - # pick the most commonly used words, and sort the rest on falling - # length (to maximize overlap) - - wordlist, wordtail = wordlist[:short], wordlist[short:] - wordtail.sort(key=lambda a: a[0], reverse=True) - wordlist.extend(wordtail) - - # generate lexicon from words - - lexicon_offset = [0] - lexicon = "" - words = {} - - # build a lexicon string - offset = 0 - for w, x in wordlist: - # encoding: bit 7 indicates last character in word (chr(128) - # indicates the last character in an entire string) - ww = w[:-1] + chr(ord(w[-1])+128) - # reuse string tails, when possible - o = lexicon.find(ww) - if o < 0: - o = offset - lexicon = lexicon + ww - offset = offset + len(w) - words[w] = len(lexicon_offset) - lexicon_offset.append(o) - - lexicon = list(map(ord, lexicon)) - - # generate phrasebook from names and lexicon - phrasebook = [0] - phrasebook_offset = [0] * len(unicode.chars) - for char in unicode.chars: - name = names[char] - if name: - w = name.split() - phrasebook_offset[char] = len(phrasebook) - for w in w: - i = words[w] - if i < short: - phrasebook.append(i) - else: - # store as two bytes - phrasebook.append((i>>8) + short) - phrasebook.append(i&255) - - assert getsize(phrasebook) == 1 - - # # unicode name hash table # extract names @@ -747,12 +640,6 @@ def word_key(a): if name and name[0] != "<": data.append((name, char)) - # the magic number 47 was chosen to minimize the number of - # collisions on the current data set. if you like, change it - # and see what happens... - - codehash = Hash("code", data, 47) - print("--- Writing", FILE, "...") with open(FILE, "w") as fp: @@ -761,24 +648,22 @@ def word_key(a): fprint("/* this file was generated by %s %s */" % (SCRIPT, VERSION)) fprint() fprint("#define NAME_MAXLEN", 256) + assert max(len(x) for x in data) < 256 fprint() - fprint("/* lexicon */") - Array("lexicon", lexicon).dump(fp, trace) - Array("lexicon_offset", lexicon_offset).dump(fp, trace) - - # split decomposition index table - offset1, offset2, shift = splitbins(phrasebook_offset, trace) - - fprint("/* code->name phrasebook */") - fprint("#define phrasebook_shift", shift) - fprint("#define phrasebook_short", short) - - Array("phrasebook", phrasebook).dump(fp, trace) - Array("phrasebook_offset1", offset1).dump(fp, trace) - Array("phrasebook_offset2", offset2).dump(fp, trace) fprint("/* name->code dictionary */") - codehash.dump(fp, trace) + packed_dawg, pos_to_codepoint = build_compression_dawg(data) + notfound = len(pos_to_codepoint) + inverse_list = [notfound] * len(unicode.chars) + for pos, codepoint in enumerate(pos_to_codepoint): + inverse_list[codepoint] = pos + Array("packed_name_dawg", list(packed_dawg)).dump(fp, trace) + Array("dawg_pos_to_codepoint", pos_to_codepoint).dump(fp, trace) + index1, index2, shift = splitbins(inverse_list, trace) + fprint("#define DAWG_CODEPOINT_TO_POS_SHIFT", shift) + fprint("#define DAWG_CODEPOINT_TO_POS_NOTFOUND", notfound) + Array("dawg_codepoint_to_pos_index1", index1).dump(fp, trace) + Array("dawg_codepoint_to_pos_index2", index2).dump(fp, trace) fprint() fprint('static const unsigned int aliases_start = %#x;' % @@ -1105,11 +990,15 @@ def __init__(self, version, cjk_check=True): table[i].east_asian_width = widths[i] self.widths = widths - for char, (p,) in UcdFile(DERIVED_CORE_PROPERTIES, version).expanded(): + for char, (propname, *propinfo) in UcdFile(DERIVED_CORE_PROPERTIES, version).expanded(): + if propinfo: + # this is not a binary property, ignore it + continue + if table[char]: # Some properties (e.g. Default_Ignorable_Code_Point) # apply to unassigned code points; ignore them - table[char].binary_properties.add(p) + table[char].binary_properties.add(propname) for char_range, value in UcdFile(LINE_BREAK, version): if value not in MANDATORY_LINE_BREAKS: @@ -1183,94 +1072,6 @@ def uselatin1(self): self.chars = list(range(256)) -# hash table tools - -# this is a straight-forward reimplementation of Python's built-in -# dictionary type, using a static data structure, and a custom string -# hash algorithm. - -def myhash(s, magic): - h = 0 - for c in map(ord, s.upper()): - h = (h * magic) + c - ix = h & 0xff000000 - if ix: - h = (h ^ ((ix>>24) & 0xff)) & 0x00ffffff - return h - - -SIZES = [ - (4,3), (8,3), (16,3), (32,5), (64,3), (128,3), (256,29), (512,17), - (1024,9), (2048,5), (4096,83), (8192,27), (16384,43), (32768,3), - (65536,45), (131072,9), (262144,39), (524288,39), (1048576,9), - (2097152,5), (4194304,3), (8388608,33), (16777216,27) -] - - -class Hash: - def __init__(self, name, data, magic): - # turn a (key, value) list into a static hash table structure - - # determine table size - for size, poly in SIZES: - if size > len(data): - poly = size + poly - break - else: - raise AssertionError("ran out of polynomials") - - print(size, "slots in hash table") - - table = [None] * size - - mask = size-1 - - n = 0 - - hash = myhash - - # initialize hash table - for key, value in data: - h = hash(key, magic) - i = (~h) & mask - v = table[i] - if v is None: - table[i] = value - continue - incr = (h ^ (h >> 3)) & mask - if not incr: - incr = mask - while 1: - n = n + 1 - i = (i + incr) & mask - v = table[i] - if v is None: - table[i] = value - break - incr = incr << 1 - if incr > mask: - incr = incr ^ poly - - print(n, "collisions") - self.collisions = n - - for i in range(len(table)): - if table[i] is None: - table[i] = 0 - - self.data = Array(name + "_hash", table) - self.magic = magic - self.name = name - self.size = size - self.poly = poly - - def dump(self, file, trace): - # write data to file, as a C array - self.data.dump(file, trace) - file.write("#define %s_magic %d\n" % (self.name, self.magic)) - file.write("#define %s_size %d\n" % (self.name, self.size)) - file.write("#define %s_poly %d\n" % (self.name, self.poly)) - # stuff to deal with arrays of unsigned integers diff --git a/Tools/wasm/README.md b/Tools/wasm/README.md index cd749dee8920c6..beb857f69e40da 100644 --- a/Tools/wasm/README.md +++ b/Tools/wasm/README.md @@ -79,7 +79,7 @@ PIC. To populate the build cache, run: ```shell . /opt/emsdk/emsdk_env.sh embuilder build zlib bzip2 MINIMAL_PIC -embuilder build --pic zlib bzip2 MINIMAL_PIC +embuilder --pic build zlib bzip2 MINIMAL_PIC ``` @@ -141,7 +141,7 @@ and header files with debug builds. #### Cross compile to wasm32-emscripten for node ```shell -./Tools/wasm/wasm_build.py emscripten-browser-dl +./Tools/wasm/wasm_build.py emscripten-node-dl ``` The command is roughly equivalent to: @@ -298,102 +298,68 @@ AddType application/wasm wasm ## WASI (wasm32-wasi) -WASI builds require the [WASI SDK](https://github.com/WebAssembly/wasi-sdk) 16.0+. -See `.devcontainer/Dockerfile` for an example of how to download and -install the WASI SDK. +**NOTE**: The instructions below assume a Unix-based OS due to cross-compilation for CPython being set up for `./configure`. -### Build +### Prerequisites + +Developing for WASI requires two additional tools to be installed beyond the typical tools required to build CPython: + +1. The [WASI SDK](https://github.com/WebAssembly/wasi-sdk) 16.0+ +2. A WASI host/runtime ([wasmtime](https://wasmtime.dev) 14+ is recommended and what the instructions below assume) -The script ``wasi-env`` sets necessary compiler and linker flags as well as -``pkg-config`` overrides. The script assumes that WASI-SDK is installed in -``/opt/wasi-sdk`` or ``$WASI_SDK_PATH``. +All of this is provided in the [devcontainer](https://devguide.python.org/getting-started/setup-building/#contribute-using-github-codespaces) if you don't want to install these tools locally. -There are two scripts you can use to do a WASI build from a source checkout. You can either use: +### Building +Building for WASI requires doing a cross-build where you have a "build" Python to help produce a WASI build of CPython (technically it's a "host x host" cross-build because the build Python is also the target Python while the host build is the WASI build; yes, it's confusing terminology). In the end you should have a build Python in `cross-build/build` and a WASI build in `cross-build/wasm32-wasi`. + +The easiest way to do a build is to use the `wasi.py` script. You can either have it perform the entire build process from start to finish in one step, or you can do it in discrete steps that mirror running `configure` and `make` for each of the two builds of Python you end up producing (which are beneficial when you only need to do a specific step after getting a complete build, e.g. editing some code and you just need to run `make` for the WASI build). The script is designed to self-document what actions it is performing on your behalf, both as a way to check its work but also for educaitonal purposes. + +The discrete steps for building via `wasi.py` are: ```shell -./Tools/wasm/wasm_build.py wasi build +python Tools/wasm/wasi.py configure-build-python +python Tools/wasm/wasi.py make-build-python +python Tools/wasm/wasi.py configure-host +python Tools/wasm/wasi.py make-host ``` -or: +To do it all in a single command, run: ```shell -./Tools/wasm/build_wasi.sh +python Tools/wasm/wasi.py build ``` -The commands are equivalent to the following steps: - -- Make sure `Modules/Setup.local` exists -- Make sure the necessary build tools are installed: - - [WASI SDK](https://github.com/WebAssembly/wasi-sdk) (which ships with `clang`) - - `make` - - `pkg-config` (on Linux) -- Create the build Python - - `mkdir -p builddir/build` - - `pushd builddir/build` - - Get the build platform - - Python: `sysconfig.get_config_var("BUILD_GNU_TYPE")` - - Shell: `../../config.guess` - - `../../configure -C` - - `make all` - - ```PYTHON_VERSION=`./python -c 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}")'` ``` - - `popd` -- Create the host/WASI Python - - `mkdir builddir/wasi` - - `pushd builddir/wasi` - - `../../Tools/wasm/wasi-env ../../configure -C --host=wasm32-unknown-wasi --build=$(../../config.guess) --with-build-python=../build/python` - - `CONFIG_SITE=../../Tools/wasm/config.site-wasm32-wasi` - - `HOSTRUNNER="wasmtime run --mapdir /::$(dirname $(dirname $(pwd))) --env PYTHONPATH=/builddir/wasi/build/lib.wasi-wasm32-$PYTHON_VERSION $(pwd)/python.wasm --"` - - Maps the source checkout to `/` in the WASI runtime - - Stdlib gets loaded from `/Lib` - - Gets `_sysconfigdata__wasi_wasm32-wasi.py` on to `sys.path` via `PYTHONPATH` - - Set by `wasi-env` - - `WASI_SDK_PATH` - - `WASI_SYSROOT` - - `CC` - - `CPP` - - `CXX` - - `LDSHARED` - - `AR` - - `RANLIB` - - `CFLAGS` - - `LDFLAGS` - - `PKG_CONFIG_PATH` - - `PKG_CONFIG_LIBDIR` - - `PKG_CONFIG_SYSROOT_DIR` - - `PATH` - - `make all` - +That will: -### Running - -If you followed the instructions above, you can run the interpreter via e.g., `wasmtime` from within the `Tools/wasi` directory (make sure to set/change `$PYTHON_VERSION` and do note the paths are relative to running in`builddir/wasi` for simplicity only): +1. Run `configure` for the build Python (same as `wasi.py configure-build-python`) +2. Run `make` for the build Python (`wasi.py make-build-python`) +3. Run `configure` for the WASI build (`wasi.py configure-host`) +4. Run `make` for the WASI build (`wasi.py make-host`) +See the `--help` for the various options available for each of the subcommands which controls things like the location of the WASI SDK, the command to use with the WASI host/runtime, etc. Also note that you can use `--` as a separator for any of the `configure`-related commands -- including `build` itself -- to pass arguments to the underlying `configure` call. For example, if you want a pydebug build that also caches the results from `configure`, you can do: ```shell -wasmtime run --mapdir /::../.. --env PYTHONPATH=/builddir/wasi/build/lib.wasi-wasm32-$PYTHON_VERSION python.wasm -- +python Tools/wasm/wasi.py build -- -C --with-pydebug ``` -There are also helpers provided by `Tools/wasm/wasm_build.py` as listed below. Also, if you used `Tools/wasm/build_wasi.sh`, a `run_wasi.sh` file will be created in `builddir/wasi` which will run the above command for you (it also uses absolute paths, so it can be executed from anywhere). - -#### REPL - +The `wasi.py` script is able to infer details from the build Python, and so you only technically need to specify `--with-pydebug` once via `configure-build-python` as this will lead to `configure-host` detecting its use if you use the discrete steps: ```shell -./Tools/wasm/wasm_build.py wasi repl +python Tools/wasm/wasi.py configure-build-python -- -C --with-pydebug +python Tools/wasm/wasi.py make-build-python +python Tools/wasm/wasi.py configure-host -- -C +python Tools/wasm/wasi.py make-host ``` -#### Tests +### Running + +If you used `wasi.py` to do your build then there will be a `cross-build/wasm32-wasi/python.sh` file which you can use to run the `python.wasm` file (see the output from the `configure-host` subcommand): ```shell -./Tools/wasm/wasm_build.py wasi test +cross-build/wasm32-wasi/python.sh --version ``` -### Debugging +While you _can_ run `python.wasm` directly, Python will fail to start up without certain things being set (e.g. `PYTHONPATH` for `sysconfig` data). As such, the `python.sh` file records these details for you. -* ``wasmtime run -g`` generates debugging symbols for gdb and lldb. The - feature is currently broken, see - https://github.com/bytecodealliance/wasmtime/issues/4669 . -* The environment variable ``RUST_LOG=wasi_common`` enables debug and - trace logging. -## Detect WebAssembly builds +## Detecting WebAssembly builds ### Python code @@ -402,15 +368,17 @@ import os, sys if sys.platform == "emscripten": # Python on Emscripten + ... if sys.platform == "wasi": # Python on WASI + ... if os.name == "posix": # WASM platforms identify as POSIX-like. # Windows does not provide os.uname(). machine = os.uname().machine if machine.startswith("wasm"): - # WebAssembly (wasm32, wasm64 in the future) + # WebAssembly (wasm32, wasm64 potentially in the future) ``` ```python diff --git a/Tools/wasm/mypy.ini b/Tools/wasm/mypy.ini new file mode 100644 index 00000000000000..4de0a30c260f5f --- /dev/null +++ b/Tools/wasm/mypy.ini @@ -0,0 +1,11 @@ +[mypy] +files = Tools/wasm/wasm_*.py +pretty = True +show_traceback = True + +# Make sure the wasm can be run using Python 3.8: +python_version = 3.8 + +# Be strict... +strict = True +enable_error_code = truthy-bool,ignore-without-code diff --git a/Tools/wasm/wasi.py b/Tools/wasm/wasi.py new file mode 100644 index 00000000000000..34c0e9375e24c8 --- /dev/null +++ b/Tools/wasm/wasi.py @@ -0,0 +1,328 @@ +#!/usr/bin/env python3 + +import argparse +import contextlib +import functools +import os +try: + from os import process_cpu_count as cpu_count +except ImportError: + from os import cpu_count +import pathlib +import shutil +import subprocess +import sys +import sysconfig +import tempfile + + +CHECKOUT = pathlib.Path(__file__).parent.parent.parent +CROSS_BUILD_DIR = CHECKOUT / "cross-build" +BUILD_DIR = CROSS_BUILD_DIR / "build" +HOST_TRIPLE = "wasm32-wasi" +HOST_DIR = CROSS_BUILD_DIR / HOST_TRIPLE + + +def updated_env(updates={}): + """Create a new dict representing the environment to use. + + The changes made to the execution environment are printed out. + """ + env_defaults = {} + # https://reproducible-builds.org/docs/source-date-epoch/ + git_epoch_cmd = ["git", "log", "-1", "--pretty=%ct"] + try: + epoch = subprocess.check_output(git_epoch_cmd, encoding="utf-8").strip() + env_defaults["SOURCE_DATE_EPOCH"] = epoch + except subprocess.CalledProcessError: + pass # Might be building from a tarball. + # This layering lets SOURCE_DATE_EPOCH from os.environ takes precedence. + environment = env_defaults | os.environ | updates + + env_diff = {} + for key, value in environment.items(): + if os.environ.get(key) != value: + env_diff[key] = value + + print("🌎 Environment changes:") + for key in sorted(env_diff.keys()): + print(f" {key}={env_diff[key]}") + + return environment + + +def subdir(working_dir, *, clean_ok=False): + """Decorator to change to a working directory.""" + def decorator(func): + @functools.wraps(func) + def wrapper(context): + try: + tput_output = subprocess.check_output(["tput", "cols"], + encoding="utf-8") + terminal_width = int(tput_output.strip()) + except subprocess.CalledProcessError: + terminal_width = 80 + print("⎯" * terminal_width) + print("ðŸ“", working_dir) + if clean_ok and context.clean and working_dir.exists(): + print(f"🚮 Deleting directory (--clean)...") + shutil.rmtree(working_dir) + + working_dir.mkdir(parents=True, exist_ok=True) + + with contextlib.chdir(working_dir): + return func(context, working_dir) + + return wrapper + + return decorator + + +def call(command, *, quiet, **kwargs): + """Execute a command. + + If 'quiet' is true, then redirect stdout and stderr to a temporary file. + """ + print("â¯", " ".join(map(str, command))) + if not quiet: + stdout = None + stderr = None + else: + stdout = tempfile.NamedTemporaryFile("w", encoding="utf-8", + delete=False, + prefix="cpython-wasi-", + suffix=".log") + stderr = subprocess.STDOUT + print(f"📠Logging output to {stdout.name} (--quiet)...") + + subprocess.check_call(command, **kwargs, stdout=stdout, stderr=stderr) + + +def build_platform(): + """The name of the build/host platform.""" + # Can also be found via `config.guess`.` + return sysconfig.get_config_var("BUILD_GNU_TYPE") + + +def build_python_path(): + """The path to the build Python binary.""" + binary = BUILD_DIR / "python" + if not binary.is_file(): + binary = binary.with_suffix(".exe") + if not binary.is_file(): + raise FileNotFoundError("Unable to find `python(.exe)` in " + f"{BUILD_DIR}") + + return binary + + +@subdir(BUILD_DIR, clean_ok=True) +def configure_build_python(context, working_dir): + """Configure the build/host Python.""" + local_setup = CHECKOUT / "Modules" / "Setup.local" + if local_setup.exists(): + print(f"👠{local_setup} exists ...") + else: + print(f"📠Touching {local_setup} ...") + local_setup.touch() + + configure = [os.path.relpath(CHECKOUT / 'configure', working_dir)] + if context.args: + configure.extend(context.args) + + call(configure, quiet=context.quiet) + + +@subdir(BUILD_DIR) +def make_build_python(context, working_dir): + """Make/build the build Python.""" + call(["make", "--jobs", str(cpu_count()), "all"], + quiet=context.quiet) + + binary = build_python_path() + cmd = [binary, "-c", + "import sys; " + "print(f'{sys.version_info.major}.{sys.version_info.minor}')"] + version = subprocess.check_output(cmd, encoding="utf-8").strip() + + print(f"🎉 {binary} {version}") + + +def find_wasi_sdk(): + """Find the path to wasi-sdk.""" + if wasi_sdk_path := os.environ.get("WASI_SDK_PATH"): + return pathlib.Path(wasi_sdk_path) + elif (default_path := pathlib.Path("/opt/wasi-sdk")).exists(): + return default_path + + +def wasi_sdk_env(context): + """Calculate environment variables for building with wasi-sdk.""" + wasi_sdk_path = context.wasi_sdk_path + sysroot = wasi_sdk_path / "share" / "wasi-sysroot" + env = {"CC": "clang", "CPP": "clang-cpp", "CXX": "clang++", + "LDSHARED": "wasm-ld", "AR": "llvm-ar", "RANLIB": "ranlib"} + + for env_var, binary_name in list(env.items()): + env[env_var] = os.fsdecode(wasi_sdk_path / "bin" / binary_name) + + if wasi_sdk_path != pathlib.Path("/opt/wasi-sdk"): + for compiler in ["CC", "CPP", "CXX"]: + env[compiler] += f" --sysroot={sysroot}" + + env["PKG_CONFIG_PATH"] = "" + env["PKG_CONFIG_LIBDIR"] = os.pathsep.join( + map(os.fsdecode, + [sysroot / "lib" / "pkgconfig", + sysroot / "share" / "pkgconfig"])) + env["PKG_CONFIG_SYSROOT_DIR"] = os.fsdecode(sysroot) + + env["WASI_SDK_PATH"] = os.fsdecode(wasi_sdk_path) + env["WASI_SYSROOT"] = os.fsdecode(sysroot) + + env["PATH"] = os.pathsep.join([os.fsdecode(wasi_sdk_path / "bin"), + os.environ["PATH"]]) + + return env + + +@subdir(HOST_DIR, clean_ok=True) +def configure_wasi_python(context, working_dir): + """Configure the WASI/host build.""" + if not context.wasi_sdk_path or not context.wasi_sdk_path.exists(): + raise ValueError("WASI-SDK not found; " + "download from " + "https://github.com/WebAssembly/wasi-sdk and/or " + "specify via $WASI_SDK_PATH or --wasi-sdk") + + config_site = os.fsdecode(CHECKOUT / "Tools" / "wasm" / "config.site-wasm32-wasi") + + wasi_build_dir = working_dir.relative_to(CHECKOUT) + + python_build_dir = BUILD_DIR / "build" + lib_dirs = list(python_build_dir.glob("lib.*")) + assert len(lib_dirs) == 1, f"Expected a single lib.* directory in {python_build_dir}" + lib_dir = os.fsdecode(lib_dirs[0]) + pydebug = lib_dir.endswith("-pydebug") + python_version = lib_dir.removesuffix("-pydebug").rpartition("-")[-1] + sysconfig_data = f"{wasi_build_dir}/build/lib.wasi-wasm32-{python_version}" + if pydebug: + sysconfig_data += "-pydebug" + + # Use PYTHONPATH to include sysconfig data which must be anchored to the + # WASI guest's `/` directory. + host_runner = context.host_runner.format(GUEST_DIR="/", + HOST_DIR=CHECKOUT, + ENV_VAR_NAME="PYTHONPATH", + ENV_VAR_VALUE=f"/{sysconfig_data}", + PYTHON_WASM=working_dir / "python.wasm") + env_additions = {"CONFIG_SITE": config_site, "HOSTRUNNER": host_runner} + build_python = os.fsdecode(build_python_path()) + # The path to `configure` MUST be relative, else `python.wasm` is unable + # to find the stdlib due to Python not recognizing that it's being + # executed from within a checkout. + configure = [os.path.relpath(CHECKOUT / 'configure', working_dir), + f"--host={HOST_TRIPLE}", + f"--build={build_platform()}", + f"--with-build-python={build_python}"] + if pydebug: + configure.append("--with-pydebug") + if context.args: + configure.extend(context.args) + call(configure, + env=updated_env(env_additions | wasi_sdk_env(context)), + quiet=context.quiet) + + exec_script = working_dir / "python.sh" + with exec_script.open("w", encoding="utf-8") as file: + file.write(f'#!/bin/sh\nexec {host_runner} "$@"\n') + exec_script.chmod(0o755) + print(f"ðŸƒâ€â™€ï¸ Created {exec_script} ... ") + sys.stdout.flush() + + +@subdir(HOST_DIR) +def make_wasi_python(context, working_dir): + """Run `make` for the WASI/host build.""" + call(["make", "--jobs", str(cpu_count()), "all"], + env=updated_env(), + quiet=context.quiet) + + exec_script = working_dir / "python.sh" + subprocess.check_call([exec_script, "--version"]) + + +def build_all(context): + """Build everything.""" + steps = [configure_build_python, make_build_python, configure_wasi_python, + make_wasi_python] + for step in steps: + step(context) + + +def main(): + default_host_runner = (f"{shutil.which('wasmtime')} run " + # Make sure the stack size will work for a pydebug + # build. + # The 8388608 value comes from `ulimit -s` under Linux + # which equates to 8291 KiB. + "--wasm max-wasm-stack=8388608 " + # Enable thread support. + "--wasm threads=y --wasi threads=y " + # Map the checkout to / to load the stdlib from /Lib. + "--dir {HOST_DIR}::{GUEST_DIR} " + # Set PYTHONPATH to the sysconfig data. + "--env {ENV_VAR_NAME}={ENV_VAR_VALUE} " + # Path to the WASM binary. + "{PYTHON_WASM}") + + parser = argparse.ArgumentParser() + subcommands = parser.add_subparsers(dest="subcommand") + build = subcommands.add_parser("build", help="Build everything") + configure_build = subcommands.add_parser("configure-build-python", + help="Run `configure` for the " + "build Python") + make_build = subcommands.add_parser("make-build-python", + help="Run `make` for the build Python") + configure_host = subcommands.add_parser("configure-host", + help="Run `configure` for the " + "host/WASI (pydebug builds " + "are inferred from the build " + "Python)") + make_host = subcommands.add_parser("make-host", + help="Run `make` for the host/WASI") + for subcommand in build, configure_build, make_build, configure_host, make_host: + subcommand.add_argument("--quiet", action="store_true", default=False, + dest="quiet", + help="Redirect output from subprocesses to a log file") + for subcommand in build, configure_build, configure_host: + subcommand.add_argument("--clean", action="store_true", default=False, + dest="clean", + help="Delete any relevant directories before building") + for subcommand in build, configure_build, configure_host: + subcommand.add_argument("args", nargs="*", + help="Extra arguments to pass to `configure`") + for subcommand in build, configure_host: + subcommand.add_argument("--wasi-sdk", type=pathlib.Path, + dest="wasi_sdk_path", + default=find_wasi_sdk(), + help="Path to wasi-sdk; defaults to " + "$WASI_SDK_PATH or /opt/wasi-sdk") + subcommand.add_argument("--host-runner", action="store", + default=default_host_runner, dest="host_runner", + help="Command template for running the WebAssembly " + "code (default meant for wasmtime 14 or newer: " + f"`{default_host_runner}`)") + + context = parser.parse_args() + + dispatch = {"configure-build-python": configure_build_python, + "make-build-python": make_build_python, + "configure-host": configure_wasi_python, + "make-host": make_wasi_python, + "build": build_all} + dispatch[context.subcommand](context) + + +if __name__ == "__main__": + main() diff --git a/Tools/wasm/wasm_assets.py b/Tools/wasm/wasm_assets.py index f1c8e0bf007f4c..ffa5e303412c46 100755 --- a/Tools/wasm/wasm_assets.py +++ b/Tools/wasm/wasm_assets.py @@ -16,6 +16,7 @@ import sys import sysconfig import zipfile +from typing import Dict # source directory SRCDIR = pathlib.Path(__file__).parent.parent.parent.absolute() @@ -110,7 +111,8 @@ def get_builddir(args: argparse.Namespace) -> pathlib.Path: def get_sysconfigdata(args: argparse.Namespace) -> pathlib.Path: """Get path to sysconfigdata relative to build root""" - data_name = sysconfig._get_sysconfigdata_name() + assert isinstance(args.builddir, pathlib.Path) + data_name: str = sysconfig._get_sysconfigdata_name() # type: ignore[attr-defined] if not data_name.startswith(SYSCONFIG_NAMES): raise ValueError( f"Invalid sysconfig data name '{data_name}'.", SYSCONFIG_NAMES @@ -146,7 +148,7 @@ def filterfunc(filename: str) -> bool: pzf.writepy(entry, filterfunc=filterfunc) -def detect_extension_modules(args: argparse.Namespace): +def detect_extension_modules(args: argparse.Namespace) -> Dict[str, bool]: modules = {} # disabled by Modules/Setup.local ? @@ -161,7 +163,7 @@ def detect_extension_modules(args: argparse.Namespace): # disabled by configure? with open(args.sysconfig_data) as f: data = f.read() - loc = {} + loc: Dict[str, Dict[str, str]] = {} exec(data, globals(), loc) for key, value in loc["build_time_vars"].items(): @@ -195,7 +197,7 @@ def path(val: str) -> pathlib.Path: ) -def main(): +def main() -> None: args = parser.parse_args() relative_prefix = args.prefix.relative_to(pathlib.Path("/")) diff --git a/Tools/wasm/wasm_build.py b/Tools/wasm/wasm_build.py index c9947057a90754..c0b9999a5dad03 100755 --- a/Tools/wasm/wasm_build.py +++ b/Tools/wasm/wasm_build.py @@ -40,7 +40,17 @@ import webbrowser # for Python 3.8 -from typing import Any, Callable, Dict, Iterable, List, Optional, Tuple, Union +from typing import ( + cast, + Any, + Callable, + Dict, + Iterable, + List, + Optional, + Tuple, + Union, +) logger = logging.getLogger("wasm_build") @@ -64,7 +74,7 @@ (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") +_MISSING = pathlib.Path("MISSING") WASM_WEBSERVER = WASMTOOLS / "wasm_webserver.py" @@ -109,7 +119,7 @@ def parse_emconfig( emconfig: pathlib.Path = EM_CONFIG, -) -> Tuple[pathlib.PurePath, pathlib.PurePath]: +) -> Tuple[pathlib.Path, pathlib.Path]: """Parse EM_CONFIG file and lookup EMSCRIPTEN_ROOT and NODE_JS. The ".emscripten" config file is a Python snippet that uses "EM_CONFIG" @@ -150,11 +160,11 @@ def read_python_version(configure: pathlib.Path = CONFIGURE) -> str: class ConditionError(ValueError): - def __init__(self, info: str, text: str): + def __init__(self, info: str, text: str) -> None: self.info = info self.text = text - def __str__(self): + def __str__(self) -> str: return f"{type(self).__name__}: '{self.info}'\n{self.text}" @@ -180,19 +190,19 @@ class Platform: name: str pythonexe: str config_site: Optional[pathlib.PurePath] - configure_wrapper: Optional[pathlib.PurePath] + configure_wrapper: Optional[pathlib.Path] make_wrapper: Optional[pathlib.PurePath] - environ: dict + environ: Dict[str, Any] check: Callable[[], None] # Used for build_emports(). ports: Optional[pathlib.PurePath] cc: Optional[pathlib.PurePath] - def getenv(self, profile: "BuildProfile") -> dict: + def getenv(self, profile: "BuildProfile") -> Dict[str, Any]: return self.environ.copy() -def _check_clean_src(): +def _check_clean_src() -> None: candidates = [ SRCDIR / "Programs" / "python.o", SRCDIR / "Python" / "frozen_modules" / "importlib._bootstrap.h", @@ -202,7 +212,7 @@ def _check_clean_src(): raise DirtySourceDirectory(os.fspath(candidate), CLEAN_SRCDIR) -def _check_native(): +def _check_native() -> None: if not any(shutil.which(cc) for cc in ["cc", "gcc", "clang"]): raise MissingDependency("cc", INSTALL_NATIVE) if not shutil.which("make"): @@ -234,12 +244,12 @@ def _check_native(): ) -def _check_emscripten(): +def _check_emscripten() -> None: if EMSCRIPTEN_ROOT is _MISSING: raise MissingDependency("Emscripten SDK EM_CONFIG", INSTALL_EMSDK) # sanity check emconfigure = EMSCRIPTEN.configure_wrapper - if not emconfigure.exists(): + if emconfigure is not None and not emconfigure.exists(): raise MissingDependency(os.fspath(emconfigure), INSTALL_EMSDK) # version check version_txt = EMSCRIPTEN_ROOT / "emscripten-version.txt" @@ -250,7 +260,10 @@ def _check_emscripten(): if version.endswith("-git"): # git / upstream / tot-upstream installation version = version[:-4] - version_tuple = tuple(int(v) for v in version.split(".")) + version_tuple = cast( + Tuple[int, int, int], + tuple(int(v) for v in version.split(".")) + ) if version_tuple < EMSDK_MIN_VERSION: raise ConditionError( os.fspath(version_txt), @@ -293,7 +306,7 @@ def _check_emscripten(): ) -def _check_wasi(): +def _check_wasi() -> None: wasm_ld = WASI_SDK_PATH / "bin" / "wasm-ld" if not wasm_ld.exists(): raise MissingDependency(os.fspath(wasm_ld), INSTALL_WASI_SDK) @@ -400,7 +413,7 @@ class EmscriptenTarget(enum.Enum): node_debug = "node-debug" @property - def is_browser(self): + def is_browser(self) -> bool: cls = type(self) return self in {cls.browser, cls.browser_debug} @@ -421,7 +434,7 @@ class SupportLevel(enum.Enum): experimental = "experimental, may be broken" broken = "broken / unavailable" - def __bool__(self): + def __bool__(self) -> bool: cls = type(self) return self in {cls.supported, cls.working} @@ -500,10 +513,14 @@ def make_cmd(self) -> List[str]: cmd.insert(0, os.fspath(platform.make_wrapper)) return cmd - def getenv(self) -> dict: + def getenv(self) -> Dict[str, Any]: """Generate environ dict for platform""" env = os.environ.copy() - env.setdefault("MAKEFLAGS", f"-j{os.cpu_count()}") + if hasattr(os, 'process_cpu_count'): + cpu_count = os.process_cpu_count() + else: + cpu_count = os.cpu_count() + env.setdefault("MAKEFLAGS", f"-j{cpu_count}") platenv = self.host.platform.getenv(self) for key, value in platenv.items(): if value is None: @@ -529,7 +546,7 @@ def _run_cmd( cmd: Iterable[str], args: Iterable[str] = (), cwd: Optional[pathlib.Path] = None, - ): + ) -> int: cmd = list(cmd) cmd.extend(args) if cwd is None: @@ -541,46 +558,46 @@ def _run_cmd( env=self.getenv(), ) - def _check_execute(self): + def _check_execute(self) -> None: if self.is_browser: raise ValueError(f"Cannot execute on {self.target}") - def run_build(self, *args): + def run_build(self, *args: str) -> None: """Run configure (if necessary) and make""" if not self.makefile.exists(): logger.info("Makefile not found, running configure") self.run_configure(*args) self.run_make("all", *args) - def run_configure(self, *args): + def run_configure(self, *args: str) -> int: """Run configure script to generate Makefile""" os.makedirs(self.builddir, exist_ok=True) return self._run_cmd(self.configure_cmd, args) - def run_make(self, *args): + def run_make(self, *args: str) -> int: """Run make (defaults to build all)""" return self._run_cmd(self.make_cmd, args) - def run_pythoninfo(self, *args): + def run_pythoninfo(self, *args: str) -> int: """Run 'make pythoninfo'""" self._check_execute() return self.run_make("pythoninfo", *args) - def run_test(self, target: str, testopts: Optional[str] = None): + def run_test(self, target: str, testopts: Optional[str] = None) -> int: """Run buildbottests""" self._check_execute() if testopts is None: testopts = self.default_testopts return self.run_make(target, f"TESTOPTS={testopts}") - def run_py(self, *args): + def run_py(self, *args: str) -> int: """Run Python with hostrunner""" self._check_execute() - self.run_make( + return self.run_make( "--eval", f"run: all; $(HOSTRUNNER) ./$(PYTHON) {shlex.join(args)}", "run" ) - def run_browser(self, bind="127.0.0.1", port=8000): + def run_browser(self, bind: str = "127.0.0.1", port: int = 8000) -> None: """Run WASM webserver and open build in browser""" relbuilddir = self.builddir.relative_to(SRCDIR) url = f"http://{bind}:{port}/{relbuilddir}/python.html" @@ -611,7 +628,7 @@ def run_browser(self, bind="127.0.0.1", port=8000): except KeyboardInterrupt: pass - def clean(self, all: bool = False): + def clean(self, all: bool = False) -> None: """Clean build directory""" if all: if self.builddir.exists(): @@ -619,7 +636,7 @@ def clean(self, all: bool = False): elif self.makefile.exists(): self.run_make("clean") - def build_emports(self, force: bool = False): + def build_emports(self, force: bool = False) -> None: """Pre-build emscripten ports.""" platform = self.host.platform if platform.ports is None or platform.cc is None: @@ -829,7 +846,7 @@ def build_emports(self, force: bool = False): ) -def main(): +def main() -> None: args = parser.parse_args() logging.basicConfig( level=logging.INFO if args.verbose else logging.ERROR, diff --git a/Tools/wasm/wasm_webserver.py b/Tools/wasm/wasm_webserver.py index 186bd57fc2067d..3d1d5d42a1e8c4 100755 --- a/Tools/wasm/wasm_webserver.py +++ b/Tools/wasm/wasm_webserver.py @@ -21,21 +21,21 @@ class MyHTTPRequestHandler(server.SimpleHTTPRequestHandler): } ) - def end_headers(self): + def end_headers(self) -> None: self.send_my_headers() super().end_headers() - def send_my_headers(self): + def send_my_headers(self) -> None: self.send_header("Cross-Origin-Opener-Policy", "same-origin") self.send_header("Cross-Origin-Embedder-Policy", "require-corp") -def main(): +def main() -> None: args = parser.parse_args() if not args.bind: args.bind = None - server.test( + server.test( # type: ignore[attr-defined] HandlerClass=MyHTTPRequestHandler, protocol="HTTP/1.1", port=args.port, diff --git a/aclocal.m4 b/aclocal.m4 index da8ee95b9c7f6b..09ae5d1aa8a608 100644 --- a/aclocal.m4 +++ b/aclocal.m4 @@ -1,4 +1,4 @@ -# generated automatically by aclocal 1.16.4 -*- Autoconf -*- +# generated automatically by aclocal 1.16.5 -*- Autoconf -*- # Copyright (C) 1996-2021 Free Software Foundation, Inc. @@ -276,7 +276,7 @@ AC_DEFUN([AX_CHECK_OPENSSL], [ ]) # pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- -# serial 11 (pkg-config-0.29.1) +# serial 12 (pkg-config-0.29.2) dnl Copyright © 2004 Scott James Remnant . dnl Copyright © 2012-2015 Dan Nicholson @@ -318,7 +318,7 @@ dnl dnl See the "Since" comment for each macro you use to see what version dnl of the macros you require. m4_defun([PKG_PREREQ], -[m4_define([PKG_MACROS_VERSION], [0.29.1]) +[m4_define([PKG_MACROS_VERSION], [0.29.2]) m4_if(m4_version_compare(PKG_MACROS_VERSION, [$1]), -1, [m4_fatal([pkg.m4 version $1 or higher is required but ]PKG_MACROS_VERSION[ found])]) ])dnl PKG_PREREQ @@ -419,7 +419,7 @@ AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl pkg_failed=no -AC_MSG_CHECKING([for $1]) +AC_MSG_CHECKING([for $2]) _PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) _PKG_CONFIG([$1][_LIBS], [libs], [$2]) @@ -429,11 +429,11 @@ and $1[]_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details.]) if test $pkg_failed = yes; then - AC_MSG_RESULT([no]) + AC_MSG_RESULT([no]) _PKG_SHORT_ERRORS_SUPPORTED if test $_pkg_short_errors_supported = yes; then $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1` - else + else $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1` fi # Put the nasty error message in config.log where it belongs @@ -450,7 +450,7 @@ installed software in a non-standard prefix. _PKG_TEXT])[]dnl ]) elif test $pkg_failed = untried; then - AC_MSG_RESULT([no]) + AC_MSG_RESULT([no]) m4_default([$4], [AC_MSG_FAILURE( [The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full @@ -551,74 +551,6 @@ AS_VAR_COPY([$1], [pkg_cv_][$1]) AS_VAR_IF([$1], [""], [$5], [$4])dnl ])dnl PKG_CHECK_VAR -dnl PKG_WITH_MODULES(VARIABLE-PREFIX, MODULES, -dnl [ACTION-IF-FOUND],[ACTION-IF-NOT-FOUND], -dnl [DESCRIPTION], [DEFAULT]) -dnl ------------------------------------------ -dnl -dnl Prepare a "--with-" configure option using the lowercase -dnl [VARIABLE-PREFIX] name, merging the behaviour of AC_ARG_WITH and -dnl PKG_CHECK_MODULES in a single macro. -AC_DEFUN([PKG_WITH_MODULES], -[ -m4_pushdef([with_arg], m4_tolower([$1])) - -m4_pushdef([description], - [m4_default([$5], [build with ]with_arg[ support])]) - -m4_pushdef([def_arg], [m4_default([$6], [auto])]) -m4_pushdef([def_action_if_found], [AS_TR_SH([with_]with_arg)=yes]) -m4_pushdef([def_action_if_not_found], [AS_TR_SH([with_]with_arg)=no]) - -m4_case(def_arg, - [yes],[m4_pushdef([with_without], [--without-]with_arg)], - [m4_pushdef([with_without],[--with-]with_arg)]) - -AC_ARG_WITH(with_arg, - AS_HELP_STRING(with_without, description[ @<:@default=]def_arg[@:>@]),, - [AS_TR_SH([with_]with_arg)=def_arg]) - -AS_CASE([$AS_TR_SH([with_]with_arg)], - [yes],[PKG_CHECK_MODULES([$1],[$2],$3,$4)], - [auto],[PKG_CHECK_MODULES([$1],[$2], - [m4_n([def_action_if_found]) $3], - [m4_n([def_action_if_not_found]) $4])]) - -m4_popdef([with_arg]) -m4_popdef([description]) -m4_popdef([def_arg]) - -])dnl PKG_WITH_MODULES - -dnl PKG_HAVE_WITH_MODULES(VARIABLE-PREFIX, MODULES, -dnl [DESCRIPTION], [DEFAULT]) -dnl ----------------------------------------------- -dnl -dnl Convenience macro to trigger AM_CONDITIONAL after PKG_WITH_MODULES -dnl check._[VARIABLE-PREFIX] is exported as make variable. -AC_DEFUN([PKG_HAVE_WITH_MODULES], -[ -PKG_WITH_MODULES([$1],[$2],,,[$3],[$4]) - -AM_CONDITIONAL([HAVE_][$1], - [test "$AS_TR_SH([with_]m4_tolower([$1]))" = "yes"]) -])dnl PKG_HAVE_WITH_MODULES - -dnl PKG_HAVE_DEFINE_WITH_MODULES(VARIABLE-PREFIX, MODULES, -dnl [DESCRIPTION], [DEFAULT]) -dnl ------------------------------------------------------ -dnl -dnl Convenience macro to run AM_CONDITIONAL and AC_DEFINE after -dnl PKG_WITH_MODULES check. HAVE_[VARIABLE-PREFIX] is exported as make -dnl and preprocessor variable. -AC_DEFUN([PKG_HAVE_DEFINE_WITH_MODULES], -[ -PKG_HAVE_WITH_MODULES([$1],[$2],[$3],[$4]) - -AS_IF([test "$AS_TR_SH([with_]m4_tolower([$1]))" = "yes"], - [AC_DEFINE([HAVE_][$1], 1, [Enable ]m4_tolower([$1])[ support])]) -])dnl PKG_HAVE_DEFINE_WITH_MODULES - # AM_CONDITIONAL -*- Autoconf -*- # Copyright (C) 1997-2021 Free Software Foundation, Inc. diff --git a/configure b/configure index 80b4a001c6d6d7..b1153df4d7ec52 100755 --- a/configure +++ b/configure @@ -669,6 +669,8 @@ MODULE__TESTBUFFER_FALSE MODULE__TESTBUFFER_TRUE MODULE__TESTINTERNALCAPI_FALSE MODULE__TESTINTERNALCAPI_TRUE +MODULE__TESTCLINIC_LIMITED_FALSE +MODULE__TESTCLINIC_LIMITED_TRUE MODULE__TESTCLINIC_FALSE MODULE__TESTCLINIC_TRUE MODULE__TESTCAPI_FALSE @@ -767,6 +769,8 @@ MODULE__MULTIPROCESSING_FALSE MODULE__MULTIPROCESSING_TRUE MODULE__ZONEINFO_FALSE MODULE__ZONEINFO_TRUE +MODULE__XXINTERPQUEUES_FALSE +MODULE__XXINTERPQUEUES_TRUE MODULE__XXINTERPCHANNELS_FALSE MODULE__XXINTERPCHANNELS_TRUE MODULE__XXSUBINTERPRETERS_FALSE @@ -858,6 +862,8 @@ DTRACE_OBJS DTRACE_HEADERS DFLAGS DTRACE +WITH_MIMALLOC +MIMALLOC_HEADERS GDBM_LIBS GDBM_CFLAGS X11_LIBS @@ -1063,6 +1069,7 @@ with_suffix enable_shared with_static_libpython enable_profiling +enable_gil with_pydebug with_trace_refs enable_pystats @@ -1075,6 +1082,7 @@ with_dsymutil with_address_sanitizer with_memory_sanitizer with_undefined_behavior_sanitizer +with_thread_sanitizer with_hash_algorithm with_tzpath with_libs @@ -1085,6 +1093,7 @@ enable_loadable_sqlite_extensions with_dbmliborder enable_ipv6 with_doc_strings +with_mimalloc with_pymalloc with_freelists with_c_locale_coercion @@ -1789,6 +1798,8 @@ Optional Features: no) --enable-profiling enable C-level code profiling with gprof (default is no) + --disable-gil enable experimental support for running without the + GIL (default is no) --enable-pystats enable internal statistics gathering (default is no) --enable-optimizations enable expensive, stable optimizations (PGO, etc.) (default is no) @@ -1850,6 +1861,8 @@ Optional Packages: --with-undefined-behavior-sanitizer enable UndefinedBehaviorSanitizer undefined behaviour detector, 'ubsan' (default is no) + --with-thread-sanitizer enable ThreadSanitizer data race detector, 'tsan' + (default is no) --with-hash-algorithm=[fnv|siphash13|siphash24] select hash algorithm for use in Python/pyhash.c (default is SipHash13) @@ -1869,6 +1882,8 @@ Optional Packages: value is a colon separated string with the backend names `ndbm', `gdbm' and `bdb'. --with-doc-strings enable documentation strings (default is yes) + --with-mimalloc build with mimalloc memory allocator (default is yes + if C11 stdatomic.h is available.) --with-pymalloc enable specialized mallocs (default is yes) --with-freelists enable object freelists (default is yes) --with-c-locale-coercion @@ -4279,6 +4294,15 @@ then darwin*) MACHDEP="darwin";; '') MACHDEP="unknown";; esac + + if test "$ac_sys_system" = "SunOS"; then + # For Solaris, there isn't an OS version specific macro defined + # in most compilers, so we define one here. + SUNOS_VERSION=`echo $ac_sys_release | sed -e 's!\.\(0-9\)$!.0\1!g' | tr -d '.'` + +printf "%s\n" "#define Py_SUNOS_VERSION $SUNOS_VERSION" >>confdefs.h + + fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: \"$MACHDEP\"" >&5 printf "%s\n" "\"$MACHDEP\"" >&6; } @@ -6716,200 +6740,16 @@ fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for the platform triplet based on compiler characteristics" >&5 printf %s "checking for the platform triplet based on compiler characteristics... " >&6; } -cat > conftest.c <=6) && defined(_MIPSEL) -# if _MIPS_SIM == _ABIO32 - mipsisa32r6el-linux-gnu -# elif _MIPS_SIM == _ABIN32 - mipsisa64r6el-linux-gnuabin32 -# elif _MIPS_SIM == _ABI64 - mipsisa64r6el-linux-gnuabi64 -# else -# error unknown platform triplet -# endif -# elif defined(__mips_hard_float) && defined(__mips_isa_rev) && (__mips_isa_rev >=6) -# if _MIPS_SIM == _ABIO32 - mipsisa32r6-linux-gnu -# elif _MIPS_SIM == _ABIN32 - mipsisa64r6-linux-gnuabin32 -# elif _MIPS_SIM == _ABI64 - mipsisa64r6-linux-gnuabi64 -# else -# error unknown platform triplet -# endif -# elif defined(__mips_hard_float) && defined(_MIPSEL) -# if _MIPS_SIM == _ABIO32 - mipsel-linux-gnu -# elif _MIPS_SIM == _ABIN32 - mips64el-linux-gnuabin32 -# elif _MIPS_SIM == _ABI64 - mips64el-linux-gnuabi64 -# else -# error unknown platform triplet -# endif -# elif defined(__mips_hard_float) -# if _MIPS_SIM == _ABIO32 - mips-linux-gnu -# elif _MIPS_SIM == _ABIN32 - mips64-linux-gnuabin32 -# elif _MIPS_SIM == _ABI64 - mips64-linux-gnuabi64 -# else -# error unknown platform triplet -# endif -# elif defined(__or1k__) - or1k-linux-gnu -# elif defined(__powerpc__) && defined(__SPE__) - powerpc-linux-gnuspe -# elif defined(__powerpc64__) -# if defined(__LITTLE_ENDIAN__) - powerpc64le-linux-gnu -# else - powerpc64-linux-gnu -# endif -# elif defined(__powerpc__) - powerpc-linux-gnu -# elif defined(__s390x__) - s390x-linux-gnu -# elif defined(__s390__) - s390-linux-gnu -# elif defined(__sh__) && defined(__LITTLE_ENDIAN__) - sh4-linux-gnu -# elif defined(__sparc__) && defined(__arch64__) - sparc64-linux-gnu -# elif defined(__sparc__) - sparc-linux-gnu -# elif defined(__riscv) -# if __riscv_xlen == 32 - riscv32-linux-gnu -# elif __riscv_xlen == 64 - riscv64-linux-gnu -# else -# error unknown platform triplet -# endif -# else -# error unknown platform triplet -# endif -#elif defined(__FreeBSD_kernel__) -# if defined(__LP64__) - x86_64-kfreebsd-gnu -# elif defined(__i386__) - i386-kfreebsd-gnu -# else -# error unknown platform triplet -# endif -#elif defined(__gnu_hurd__) - i386-gnu -#elif defined(__APPLE__) - darwin -#elif defined(__VXWORKS__) - vxworks -#elif defined(__wasm32__) -# if defined(__EMSCRIPTEN__) - wasm32-emscripten -# elif defined(__wasi__) -# if defined(_REENTRANT) - wasm32-wasi-threads -# else - wasm32-wasi -# endif -# else -# error unknown wasm32 platform -# endif -#elif defined(__wasm64__) -# if defined(__EMSCRIPTEN__) - wasm64-emscripten -# elif defined(__wasi__) - wasm64-wasi -# else -# error unknown wasm64 platform -# endif -#else -# error unknown platform triplet -#endif - -EOF - -if $CPP $CPPFLAGS conftest.c >conftest.out 2>/dev/null; then - PLATFORM_TRIPLET=`grep -v '^#' conftest.out | grep -v '^ *$' | tr -d ' '` - case "$build_os" in - linux-musl*) - PLATFORM_TRIPLET=`echo "$PLATFORM_TRIPLET" | sed 's/linux-gnu/linux-musl/'` - ;; - esac +if $CPP $CPPFLAGS $srcdir/Misc/platform_triplet.c >conftest.out 2>/dev/null; then + PLATFORM_TRIPLET=`grep '^PLATFORM_TRIPLET=' conftest.out | tr -d ' '` + PLATFORM_TRIPLET="${PLATFORM_TRIPLET#PLATFORM_TRIPLET=}" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PLATFORM_TRIPLET" >&5 printf "%s\n" "$PLATFORM_TRIPLET" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none" >&5 printf "%s\n" "none" >&6; } fi -rm -f conftest.c conftest.out +rm -f conftest.out { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for multiarch" >&5 printf %s "checking for multiarch... " >&6; } @@ -8024,6 +7864,36 @@ fi ABIFLAGS="" +# Check for --disable-gil +# --disable-gil +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for --disable-gil" >&5 +printf %s "checking for --disable-gil... " >&6; } +# Check whether --enable-gil was given. +if test ${enable_gil+y} +then : + enableval=$enable_gil; if test "x$enable_gil" = xyes +then : + disable_gil=no +else $as_nop + disable_gil=yes +fi +else $as_nop + disable_gil=no + +fi + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $disable_gil" >&5 +printf "%s\n" "$disable_gil" >&6; } + +if test "$disable_gil" = "yes" +then + +printf "%s\n" "#define Py_GIL_DISABLED 1" >>confdefs.h + + # Add "t" for "threaded" + ABIFLAGS="${ABIFLAGS}t" +fi + # Check for --with-pydebug { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for --with-pydebug" >&5 printf %s "checking for --with-pydebug... " >&6; } @@ -8743,7 +8613,10 @@ printf "%s\n" "$as_me: llvm-profdata found via xcrun: ${LLVM_PROFDATA}" >&6;} fi fi LLVM_PROF_ERR=no -case $CC in + +# GNU Autoconf recommends the use of expr instead of basename. +CC_BASENAME=$(expr "//$CC" : '.*/\(.*\)') +case "$CC_BASENAME" in *clang*) # Any changes made here should be reflected in the GCC+Darwin case below PGO_PROF_GEN_FLAG="-fprofile-instr-generate" @@ -9405,10 +9278,15 @@ then : # without this, configure fails to find pthread_create, sem_init, # etc because they are only available in the sysroot for # wasm32-wasi-threads. + # Note: wasi-threads requires --import-memory. + # Note: wasi requires --export-memory. + # Note: --export-memory is implicit unless --import-memory is given + # Note: this requires LLVM >= 16. as_fn_append CFLAGS " -target wasm32-wasi-threads -pthread" as_fn_append CFLAGS_NODIST " -target wasm32-wasi-threads -pthread" as_fn_append LDFLAGS_NODIST " -target wasm32-wasi-threads -pthread" as_fn_append LDFLAGS_NODIST " -Wl,--import-memory" + as_fn_append LDFLAGS_NODIST " -Wl,--export-memory" as_fn_append LDFLAGS_NODIST " -Wl,--max-memory=10485760" fi @@ -9572,7 +9450,7 @@ fi # ICC doesn't recognize the option, but only emits a warning ## XXX does it emit an unused result warning and can it be disabled? - case $CC in #( + case "$CC_BASENAME" in #( *icc*) : ac_cv_disable_unused_result_warning=no @@ -10153,7 +10031,7 @@ rm -f core conftest.err conftest.$ac_objext conftest.beam \ ;; esac -case "$CC" in +case "$CC_BASENAME" in *mpicc*) CFLAGS_NODIST="$CFLAGS_NODIST" ;; @@ -10501,12 +10379,6 @@ if test "x$ac_cv_header_grp_h" = xyes then : printf "%s\n" "#define HAVE_GRP_H 1" >>confdefs.h -fi -ac_fn_c_check_header_compile "$LINENO" "ieeefp.h" "ac_cv_header_ieeefp_h" "$ac_includes_default" -if test "x$ac_cv_header_ieeefp_h" = xyes -then : - printf "%s\n" "#define HAVE_IEEEFP_H 1" >>confdefs.h - fi ac_fn_c_check_header_compile "$LINENO" "io.h" "ac_cv_header_io_h" "$ac_includes_default" if test "x$ac_cv_header_io_h" = xyes @@ -10861,6 +10733,12 @@ if test "x$ac_cv_header_sys_times_h" = xyes then : printf "%s\n" "#define HAVE_SYS_TIMES_H 1" >>confdefs.h +fi +ac_fn_c_check_header_compile "$LINENO" "sys/timerfd.h" "ac_cv_header_sys_timerfd_h" "$ac_includes_default" +if test "x$ac_cv_header_sys_timerfd_h" = xyes +then : + printf "%s\n" "#define HAVE_SYS_TIMERFD_H 1" >>confdefs.h + fi ac_fn_c_check_header_compile "$LINENO" "sys/types.h" "ac_cv_header_sys_types_h" "$ac_includes_default" if test "x$ac_cv_header_sys_types_h" = xyes @@ -11153,6 +11031,7 @@ fi # On Linux, netlink.h requires asm/types.h +# On FreeBSD, netlink.h is located in netlink/netlink.h ac_fn_c_check_header_compile "$LINENO" "linux/netlink.h" "ac_cv_header_linux_netlink_h" " #ifdef HAVE_ASM_TYPES_H #include @@ -11167,6 +11046,20 @@ then : printf "%s\n" "#define HAVE_LINUX_NETLINK_H 1" >>confdefs.h fi +ac_fn_c_check_header_compile "$LINENO" "netlink/netlink.h" "ac_cv_header_netlink_netlink_h" " +#ifdef HAVE_ASM_TYPES_H +#include +#endif +#ifdef HAVE_SYS_SOCKET_H +#include +#endif + +" +if test "x$ac_cv_header_netlink_netlink_h" = xyes +then : + printf "%s\n" "#define HAVE_NETLINK_NETLINK_H 1" >>confdefs.h + +fi # On Linux, qrtr.h requires asm/types.h @@ -12616,6 +12509,28 @@ with_ubsan="no" fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for --with-thread-sanitizer" >&5 +printf %s "checking for --with-thread-sanitizer... " >&6; } + +# Check whether --with-thread_sanitizer was given. +if test ${with_thread_sanitizer+y} +then : + withval=$with_thread_sanitizer; +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $withval" >&5 +printf "%s\n" "$withval" >&6; } +BASECFLAGS="-fsanitize=thread $BASECFLAGS" +LDFLAGS="-fsanitize=thread $LDFLAGS" +with_tsan="yes" + +else $as_nop + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +with_tsan="no" + +fi + + # Set info about shared libraries. @@ -13152,8 +13067,8 @@ then : pkg_failed=no -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for LIBUUID" >&5 -printf %s "checking for LIBUUID... " >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for uuid >= 2.20" >&5 +printf %s "checking for uuid >= 2.20... " >&6; } if test -n "$LIBUUID_CFLAGS"; then pkg_cv_LIBUUID_CFLAGS="$LIBUUID_CFLAGS" @@ -13193,7 +13108,7 @@ fi if test $pkg_failed = yes; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then @@ -13333,7 +13248,7 @@ LIBS=$save_LIBS elif test $pkg_failed = untried; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } save_CFLAGS=$CFLAGS @@ -14041,8 +13956,8 @@ then : pkg_failed=no -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for LIBFFI" >&5 -printf %s "checking for LIBFFI... " >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for libffi" >&5 +printf %s "checking for libffi... " >&6; } if test -n "$LIBFFI_CFLAGS"; then pkg_cv_LIBFFI_CFLAGS="$LIBFFI_CFLAGS" @@ -14082,7 +13997,7 @@ fi if test $pkg_failed = yes; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then @@ -14169,7 +14084,7 @@ LIBS=$save_LIBS elif test $pkg_failed = untried; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } save_CFLAGS=$CFLAGS @@ -14573,8 +14488,8 @@ fi pkg_failed=no -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for LIBSQLITE3" >&5 -printf %s "checking for LIBSQLITE3... " >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for sqlite3 >= 3.15.2" >&5 +printf %s "checking for sqlite3 >= 3.15.2... " >&6; } if test -n "$LIBSQLITE3_CFLAGS"; then pkg_cv_LIBSQLITE3_CFLAGS="$LIBSQLITE3_CFLAGS" @@ -14614,7 +14529,7 @@ fi if test $pkg_failed = yes; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then @@ -14636,7 +14551,7 @@ fi elif test $pkg_failed = untried; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } LIBSQLITE3_CFLAGS=${LIBSQLITE3_CFLAGS-""} @@ -15337,8 +15252,8 @@ for _QUERY in \ pkg_failed=no -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for TCLTK" >&5 -printf %s "checking for TCLTK... " >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $_QUERY" >&5 +printf %s "checking for $_QUERY... " >&6; } if test -n "$TCLTK_CFLAGS"; then pkg_cv_TCLTK_CFLAGS="$TCLTK_CFLAGS" @@ -15378,7 +15293,7 @@ fi if test $pkg_failed = yes; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then @@ -15396,7 +15311,7 @@ fi found_tcltk=no elif test $pkg_failed = untried; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } found_tcltk=no else @@ -15434,8 +15349,8 @@ case $ac_sys_system in #( pkg_failed=no -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for X11" >&5 -printf %s "checking for X11... " >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for x11" >&5 +printf %s "checking for x11... " >&6; } if test -n "$X11_CFLAGS"; then pkg_cv_X11_CFLAGS="$X11_CFLAGS" @@ -15475,7 +15390,7 @@ fi if test $pkg_failed = yes; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then @@ -15502,7 +15417,7 @@ Alternatively, you may set the environment variables X11_CFLAGS and X11_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details." "$LINENO" 5 elif test $pkg_failed = untried; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} @@ -16623,7 +16538,7 @@ ipv6type=unknown ipv6lib=none ipv6trylibc=no -if test "$ipv6" = "yes"; then +if test "$ipv6" = yes -a "$cross_compiling" = no; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking ipv6 stack type" >&5 printf %s "checking ipv6 stack type... " >&6; } for i in inria kame linux-glibc linux-inet6 solaris toshiba v6d zeta; @@ -16889,6 +16804,129 @@ fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $with_doc_strings" >&5 printf "%s\n" "$with_doc_strings" >&6; } +# Check for stdatomic.h, required for mimalloc. +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for stdatomic.h" >&5 +printf %s "checking for stdatomic.h... " >&6; } +if test ${ac_cv_header_stdatomic_h+y} +then : + printf %s "(cached) " >&6 +else $as_nop + +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + + #include + atomic_int int_var; + atomic_uintptr_t uintptr_var; + int main() { + atomic_store_explicit(&int_var, 5, memory_order_relaxed); + atomic_store_explicit(&uintptr_var, 0, memory_order_relaxed); + int loaded_value = atomic_load_explicit(&int_var, memory_order_seq_cst); + return 0; + } + + +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + ac_cv_header_stdatomic_h=yes +else $as_nop + ac_cv_header_stdatomic_h=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext + +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdatomic_h" >&5 +printf "%s\n" "$ac_cv_header_stdatomic_h" >&6; } + +if test "x$ac_cv_header_stdatomic_h" = xyes +then : + + +printf "%s\n" "#define HAVE_STD_ATOMIC 1" >>confdefs.h + + +fi + +# Check for GCC >= 4.7 and clang __atomic builtin functions +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for builtin __atomic_load_n and __atomic_store_n functions" >&5 +printf %s "checking for builtin __atomic_load_n and __atomic_store_n functions... " >&6; } +if test ${ac_cv_builtin_atomic+y} +then : + printf %s "(cached) " >&6 +else $as_nop + +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + + int val; + int main() { + __atomic_store_n(&val, 1, __ATOMIC_SEQ_CST); + (void)__atomic_load_n(&val, __ATOMIC_SEQ_CST); + return 0; + } + + +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + ac_cv_builtin_atomic=yes +else $as_nop + ac_cv_builtin_atomic=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext + +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_builtin_atomic" >&5 +printf "%s\n" "$ac_cv_builtin_atomic" >&6; } + +if test "x$ac_cv_builtin_atomic" = xyes +then : + + +printf "%s\n" "#define HAVE_BUILTIN_ATOMIC 1" >>confdefs.h + + +fi + +# --with-mimalloc +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for --with-mimalloc" >&5 +printf %s "checking for --with-mimalloc... " >&6; } + +# Check whether --with-mimalloc was given. +if test ${with_mimalloc+y} +then : + withval=$with_mimalloc; +else $as_nop + with_mimalloc="$ac_cv_header_stdatomic_h" + +fi + + +if test "$with_mimalloc" != no; then + if test "$ac_cv_header_stdatomic_h" != yes; then + # mimalloc-atomic.h wants C11 stdatomic.h on POSIX + as_fn_error $? "mimalloc requires stdatomic.h, use --without-mimalloc to disable mimalloc." "$LINENO" 5 + fi + with_mimalloc=yes + +printf "%s\n" "#define WITH_MIMALLOC 1" >>confdefs.h + + MIMALLOC_HEADERS='$(MIMALLOC_HEADERS)' + +elif test "$disable_gil" = "yes"; then + as_fn_error $? "--disable-gil requires mimalloc memory allocator (--with-mimalloc)." "$LINENO" 5 +fi + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $with_mimalloc" >&5 +printf "%s\n" "$with_mimalloc" >&6; } + + + # Check for Python-specific malloc support { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for --with-pymalloc" >&5 printf %s "checking for --with-pymalloc... " >&6; } @@ -17108,8 +17146,8 @@ PLATFORM_OBJS= case $ac_sys_system in #( Emscripten) : - as_fn_append PLATFORM_OBJS ' Python/emscripten_signal.o' - as_fn_append PLATFORM_HEADERS ' $(srcdir)/Include/internal/pycore_emscripten_signal.h' + as_fn_append PLATFORM_OBJS ' Python/emscripten_signal.o Python/emscripten_trampoline.o' + as_fn_append PLATFORM_HEADERS ' $(srcdir)/Include/internal/pycore_emscripten_signal.h $(srcdir)/Include/internal/pycore_emscripten_trampoline.h' ;; #( *) : ;; @@ -17214,6 +17252,12 @@ if test "x$ac_cv_func_clock" = xyes then : printf "%s\n" "#define HAVE_CLOCK 1" >>confdefs.h +fi +ac_fn_c_check_func "$LINENO" "closefrom" "ac_cv_func_closefrom" +if test "x$ac_cv_func_closefrom" = xyes +then : + printf "%s\n" "#define HAVE_CLOSEFROM 1" >>confdefs.h + fi ac_fn_c_check_func "$LINENO" "close_range" "ac_cv_func_close_range" if test "x$ac_cv_func_close_range" = xyes @@ -17760,6 +17804,12 @@ if test "x$ac_cv_func_posix_spawnp" = xyes then : printf "%s\n" "#define HAVE_POSIX_SPAWNP 1" >>confdefs.h +fi +ac_fn_c_check_func "$LINENO" "posix_spawn_file_actions_addclosefrom_np" "ac_cv_func_posix_spawn_file_actions_addclosefrom_np" +if test "x$ac_cv_func_posix_spawn_file_actions_addclosefrom_np" = xyes +then : + printf "%s\n" "#define HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSEFROM_NP 1" >>confdefs.h + fi ac_fn_c_check_func "$LINENO" "pread" "ac_cv_func_pread" if test "x$ac_cv_func_pread" = xyes @@ -18918,6 +18968,50 @@ fi + + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for timerfd_create" >&5 +printf %s "checking for timerfd_create... " >&6; } +if test ${ac_cv_func_timerfd_create+y} +then : + printf %s "(cached) " >&6 +else $as_nop + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#ifdef HAVE_SYS_TIMERFD_H +#include +#endif + +int +main (void) +{ +void *x=timerfd_create + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + ac_cv_func_timerfd_create=yes +else $as_nop + ac_cv_func_timerfd_create=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_timerfd_create" >&5 +printf "%s\n" "$ac_cv_func_timerfd_create" >&6; } + if test "x$ac_cv_func_timerfd_create" = xyes +then : + +printf "%s\n" "#define HAVE_TIMERFD_CREATE 1" >>confdefs.h + +fi + + + + # On some systems (eg. FreeBSD 5), we would find a definition of the # functions ctermid_r, setgroups in the library, but no prototype # (e.g. because we use _XOPEN_SOURCE). See whether we can take their @@ -19389,8 +19483,8 @@ fi pkg_failed=no -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ZLIB" >&5 -printf %s "checking for ZLIB... " >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for zlib >= 1.2.0" >&5 +printf %s "checking for zlib >= 1.2.0... " >&6; } if test -n "$ZLIB_CFLAGS"; then pkg_cv_ZLIB_CFLAGS="$ZLIB_CFLAGS" @@ -19430,7 +19524,7 @@ fi if test $pkg_failed = yes; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then @@ -19573,7 +19667,7 @@ LIBS=$save_LIBS elif test $pkg_failed = untried; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } save_CFLAGS=$CFLAGS @@ -19737,8 +19831,8 @@ fi pkg_failed=no -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for BZIP2" >&5 -printf %s "checking for BZIP2... " >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for bzip2" >&5 +printf %s "checking for bzip2... " >&6; } if test -n "$BZIP2_CFLAGS"; then pkg_cv_BZIP2_CFLAGS="$BZIP2_CFLAGS" @@ -19778,7 +19872,7 @@ fi if test $pkg_failed = yes; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then @@ -19874,7 +19968,7 @@ LIBS=$save_LIBS elif test $pkg_failed = untried; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } save_CFLAGS=$CFLAGS @@ -19965,8 +20059,8 @@ fi pkg_failed=no -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for LIBLZMA" >&5 -printf %s "checking for LIBLZMA... " >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for liblzma" >&5 +printf %s "checking for liblzma... " >&6; } if test -n "$LIBLZMA_CFLAGS"; then pkg_cv_LIBLZMA_CFLAGS="$LIBLZMA_CFLAGS" @@ -20006,7 +20100,7 @@ fi if test $pkg_failed = yes; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then @@ -20102,7 +20196,7 @@ LIBS=$save_LIBS elif test $pkg_failed = untried; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } save_CFLAGS=$CFLAGS @@ -21736,6 +21830,7 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext #if defined(MAJOR_IN_MKDEV) #include #elif defined(MAJOR_IN_SYSMACROS) +#include #include #else #include @@ -23713,6 +23808,7 @@ printf "%s\n" "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h # # * The Python implementation (always 'cpython-' for us) # * The major and minor version numbers +# * --disable-gil (adds a 't') # * --with-pydebug (adds a 'd') # # Thus for example, Python 3.2 built with wide unicode, pydebug, and pymalloc, @@ -23732,8 +23828,9 @@ SOABI='cpython-'`echo $VERSION | tr -d .`${ABIFLAGS}${PLATFORM_TRIPLET:+-$PLATFO { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $SOABI" >&5 printf "%s\n" "$SOABI" >&6; } -# Release and debug (Py_DEBUG) ABI are compatible, but not Py_TRACE_REFS ABI -if test "$Py_DEBUG" = 'true' -a "$with_trace_refs" != "yes"; then +# Release build, debug build (Py_DEBUG), and trace refs build (Py_TRACE_REFS) +# are ABI compatible +if test "$Py_DEBUG" = 'true'; then # Similar to SOABI but remove "d" flag from ABIFLAGS ALT_SOABI='cpython-'`echo $VERSION | tr -d .``echo $ABIFLAGS | tr -d d`${PLATFORM_TRIPLET:+-$PLATFORM_TRIPLET} @@ -23943,8 +24040,8 @@ then : pkg_failed=no -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for LIBREADLINE" >&5 -printf %s "checking for LIBREADLINE... " >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for readline" >&5 +printf %s "checking for readline... " >&6; } if test -n "$LIBREADLINE_CFLAGS"; then pkg_cv_LIBREADLINE_CFLAGS="$LIBREADLINE_CFLAGS" @@ -23984,7 +24081,7 @@ fi if test $pkg_failed = yes; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then @@ -24077,7 +24174,7 @@ LIBS=$save_LIBS elif test $pkg_failed = untried; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } save_CFLAGS=$CFLAGS @@ -24174,8 +24271,8 @@ then : pkg_failed=no -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for LIBEDIT" >&5 -printf %s "checking for LIBEDIT... " >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for libedit" >&5 +printf %s "checking for libedit... " >&6; } if test -n "$LIBEDIT_CFLAGS"; then pkg_cv_LIBEDIT_CFLAGS="$LIBEDIT_CFLAGS" @@ -24215,7 +24312,7 @@ fi if test $pkg_failed = yes; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then @@ -24310,7 +24407,7 @@ LIBS=$save_LIBS elif test $pkg_failed = untried; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } save_CFLAGS=$CFLAGS @@ -24736,6 +24833,25 @@ printf "%s\n" "#define HAVE_RL_APPEND_HISTORY 1" >>confdefs.h fi + # in readline as well as newer editline (April 2023) + ac_fn_c_check_type "$LINENO" "rl_compdisp_func_t" "ac_cv_type_rl_compdisp_func_t" " + #include /* Must be first for Gnu Readline */ + #ifdef WITH_EDITLINE + # include + #else + # include + # include + #endif + +" +if test "x$ac_cv_type_rl_compdisp_func_t" = xyes +then : + +printf "%s\n" "#define HAVE_RL_COMPDISP_FUNC_T 1" >>confdefs.h + +fi + + CFLAGS=$save_CFLAGS @@ -25043,8 +25159,8 @@ then : if test "$ac_sys_system" != "Darwin"; then pkg_failed=no -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for CURSES" >&5 -printf %s "checking for CURSES... " >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ncursesw" >&5 +printf %s "checking for ncursesw... " >&6; } if test -n "$CURSES_CFLAGS"; then pkg_cv_CURSES_CFLAGS="$CURSES_CFLAGS" @@ -25084,7 +25200,7 @@ fi if test $pkg_failed = yes; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then @@ -25162,7 +25278,7 @@ LIBS=$save_LIBS elif test $pkg_failed = untried; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } save_CFLAGS=$CFLAGS @@ -25243,8 +25359,8 @@ then : pkg_failed=no -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for CURSES" >&5 -printf %s "checking for CURSES... " >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ncurses" >&5 +printf %s "checking for ncurses... " >&6; } if test -n "$CURSES_CFLAGS"; then pkg_cv_CURSES_CFLAGS="$CURSES_CFLAGS" @@ -25284,7 +25400,7 @@ fi if test $pkg_failed = yes; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then @@ -25360,7 +25476,7 @@ LIBS=$save_LIBS elif test $pkg_failed = untried; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } save_CFLAGS=$CFLAGS @@ -25437,7 +25553,7 @@ fi fi CURSES_CFLAGS=$(echo $CURSES_CFLAGS | sed 's/-D_XOPEN_SOURCE=600//g') -if test "$have_curses" = no -a "$ac_sys_system" = "Darwin"; then +if test "$have_curses" != no -a "$ac_sys_system" = "Darwin"; then as_fn_append CURSES_CFLAGS " -D_XOPEN_SOURCE_EXTENDED=1" printf "%s\n" "#define HAVE_NCURSESW 1" >>confdefs.h @@ -25478,8 +25594,8 @@ then : pkg_failed=no -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for PANEL" >&5 -printf %s "checking for PANEL... " >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for panelw" >&5 +printf %s "checking for panelw... " >&6; } if test -n "$PANEL_CFLAGS"; then pkg_cv_PANEL_CFLAGS="$PANEL_CFLAGS" @@ -25519,7 +25635,7 @@ fi if test $pkg_failed = yes; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then @@ -25595,7 +25711,7 @@ LIBS=$save_LIBS elif test $pkg_failed = untried; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } save_CFLAGS=$CFLAGS @@ -25674,8 +25790,8 @@ then : pkg_failed=no -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for PANEL" >&5 -printf %s "checking for PANEL... " >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for panel" >&5 +printf %s "checking for panel... " >&6; } if test -n "$PANEL_CFLAGS"; then pkg_cv_PANEL_CFLAGS="$PANEL_CFLAGS" @@ -25715,7 +25831,7 @@ fi if test $pkg_failed = yes; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then @@ -25791,7 +25907,7 @@ LIBS=$save_LIBS elif test $pkg_failed = untried; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } save_CFLAGS=$CFLAGS @@ -26713,11 +26829,16 @@ SRCDIRS="\ Modules/_sqlite \ Modules/_sre \ Modules/_testcapi \ + Modules/_testinternalcapi \ Modules/_xxtestfuzz \ Modules/cjkcodecs \ Modules/expat \ Objects \ + Objects/mimalloc \ + Objects/mimalloc/prim \ Parser \ + Parser/tokenizer \ + Parser/lexer \ Programs \ Python \ Python/frozen_modules \ @@ -26873,95 +26994,6 @@ printf "%s\n" "#define HAVE_IPA_PURE_CONST_BUG 1" >>confdefs.h esac fi -# Check for stdatomic.h -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for stdatomic.h" >&5 -printf %s "checking for stdatomic.h... " >&6; } -if test ${ac_cv_header_stdatomic_h+y} -then : - printf %s "(cached) " >&6 -else $as_nop - -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - - - #include - atomic_int int_var; - atomic_uintptr_t uintptr_var; - int main(void) { - atomic_store_explicit(&int_var, 5, memory_order_relaxed); - atomic_store_explicit(&uintptr_var, 0, memory_order_relaxed); - int loaded_value = atomic_load_explicit(&int_var, memory_order_seq_cst); - return 0; - } - - -_ACEOF -if ac_fn_c_try_link "$LINENO" -then : - ac_cv_header_stdatomic_h=yes -else $as_nop - ac_cv_header_stdatomic_h=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ - conftest$ac_exeext conftest.$ac_ext - -fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdatomic_h" >&5 -printf "%s\n" "$ac_cv_header_stdatomic_h" >&6; } - -if test "x$ac_cv_header_stdatomic_h" = xyes -then : - - -printf "%s\n" "#define HAVE_STD_ATOMIC 1" >>confdefs.h - - -fi - -# Check for GCC >= 4.7 and clang __atomic builtin functions -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for builtin __atomic_load_n and __atomic_store_n functions" >&5 -printf %s "checking for builtin __atomic_load_n and __atomic_store_n functions... " >&6; } -if test ${ac_cv_builtin_atomic+y} -then : - printf %s "(cached) " >&6 -else $as_nop - -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - - - int val; - int main(void) { - __atomic_store_n(&val, 1, __ATOMIC_SEQ_CST); - (void)__atomic_load_n(&val, __ATOMIC_SEQ_CST); - return 0; - } - - -_ACEOF -if ac_fn_c_try_link "$LINENO" -then : - ac_cv_builtin_atomic=yes -else $as_nop - ac_cv_builtin_atomic=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ - conftest$ac_exeext conftest.$ac_ext - -fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_builtin_atomic" >&5 -printf "%s\n" "$ac_cv_builtin_atomic" >&6; } - -if test "x$ac_cv_builtin_atomic" = xyes -then : - - -printf "%s\n" "#define HAVE_BUILTIN_ATOMIC 1" >>confdefs.h - - -fi - # ensurepip option { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ensurepip" >&5 printf %s "checking for ensurepip... " >&6; } @@ -27472,7 +27504,12 @@ then : else $as_nop - rpath_arg="-Wl,-rpath=" + if test "$ac_sys_system" = "Darwin" + then + rpath_arg="-Wl,-rpath," + else + rpath_arg="-Wl,-rpath=" + fi fi @@ -27781,8 +27818,8 @@ then : pkg_failed=no -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for LIBB2" >&5 -printf %s "checking for LIBB2... " >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for libb2" >&5 +printf %s "checking for libb2... " >&6; } if test -n "$LIBB2_CFLAGS"; then pkg_cv_LIBB2_CFLAGS="$LIBB2_CFLAGS" @@ -27822,7 +27859,7 @@ fi if test $pkg_failed = yes; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then @@ -27840,7 +27877,7 @@ fi have_libb2=no elif test $pkg_failed = untried; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } have_libb2=no else @@ -27889,6 +27926,96 @@ fi printf "%s\n" "$TEST_MODULES" >&6; } +# gh-109054: Check if -latomic is needed to get atomic functions. +# On Linux aarch64, GCC may require programs and libraries to be linked +# explicitly to libatomic. Call _Py_atomic_or_uint64() which may require +# libatomic __atomic_fetch_or_8(), or not, depending on the C compiler and the +# compiler flags. +# +# gh-112779: On RISC-V, GCC 12 and earlier require libatomic support for 1-byte +# and 2-byte operations, but not for 8-byte operations. +# +# Avoid #include or #include . The header +# requires header which is only written below by AC_OUTPUT below. +# If the check is done after AC_OUTPUT, modifying LIBS has no effect +# anymore. cannot be included alone, it's designed to be included +# by : it expects other includes and macros to be defined. +save_CPPFLAGS=$CPPFLAGS +CPPFLAGS="${BASECPPFLAGS} -I. -I${srcdir}/Include ${CPPFLAGS}" + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether libatomic is needed by " >&5 +printf %s "checking whether libatomic is needed by ... " >&6; } +if test ${ac_cv_libatomic_needed+y} +then : + printf %s "(cached) " >&6 +else $as_nop + if test "$cross_compiling" = yes +then : + ac_cv_libatomic_needed=no +else $as_nop + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +// pyatomic.h needs uint64_t and Py_ssize_t types +#include // int64_t, intptr_t +#ifdef HAVE_SYS_TYPES_H +# include // ssize_t +#endif +// Code adapted from Include/pyport.h +#if HAVE_SSIZE_T +typedef ssize_t Py_ssize_t; +#elif SIZEOF_VOID_P == SIZEOF_SIZE_T +typedef intptr_t Py_ssize_t; +#else +# error "unable to define Py_ssize_t" +#endif + +#include "pyatomic.h" + +int main() +{ + uint64_t value; + _Py_atomic_store_uint64(&value, 2); + if (_Py_atomic_or_uint64(&value, 8) != 2) { + return 1; // error + } + if (_Py_atomic_load_uint64(&value) != 10) { + return 1; // error + } + uint8_t byte = 0xb8; + if (_Py_atomic_or_uint8(&byte, 0x2d) != 0xb8) { + return 1; // error + } + if (_Py_atomic_load_uint8(&byte) != 0xbd) { + return 1; // error + } + return 0; // all good +} + +_ACEOF +if ac_fn_c_try_run "$LINENO" +then : + ac_cv_libatomic_needed=no +else $as_nop + ac_cv_libatomic_needed=yes +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_libatomic_needed" >&5 +printf "%s\n" "$ac_cv_libatomic_needed" >&6; } + +if test "x$ac_cv_libatomic_needed" = xyes +then : + LIBS="${LIBS} -latomic" + LIBATOMIC=${LIBATOMIC-"-latomic"} +fi +CPPFLAGS=$save_CPPFLAGS + + +# stdlib # stdlib not available @@ -27937,6 +28064,7 @@ case $ac_sys_system in #( py_cv_module__tkinter=n/a py_cv_module__xxsubinterpreters=n/a py_cv_module__xxinterpchannels=n/a + py_cv_module__xxinterpqueues=n/a py_cv_module_grp=n/a py_cv_module_pwd=n/a py_cv_module_resource=n/a @@ -28436,6 +28564,28 @@ then : +fi + + + if test "$py_cv_module__xxinterpqueues" != "n/a" +then : + py_cv_module__xxinterpqueues=yes +fi + if test "$py_cv_module__xxinterpqueues" = yes; then + MODULE__XXINTERPQUEUES_TRUE= + MODULE__XXINTERPQUEUES_FALSE='#' +else + MODULE__XXINTERPQUEUES_TRUE='#' + MODULE__XXINTERPQUEUES_FALSE= +fi + + as_fn_append MODULE_BLOCK "MODULE__XXINTERPQUEUES_STATE=$py_cv_module__xxinterpqueues$as_nl" + if test "x$py_cv_module__xxinterpqueues" = xyes +then : + + + + fi @@ -30037,7 +30187,7 @@ fi then : - + as_fn_append MODULE_BLOCK "MODULE__TESTCAPI_LDFLAGS=$LIBATOMIC$as_nl" fi if test "$py_cv_module__testcapi" = yes; then @@ -30090,6 +30240,44 @@ fi printf "%s\n" "$py_cv_module__testclinic" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module _testclinic_limited" >&5 +printf %s "checking for stdlib extension module _testclinic_limited... " >&6; } + if test "$py_cv_module__testclinic_limited" != "n/a" +then : + + if test "$TEST_MODULES" = yes +then : + if true +then : + py_cv_module__testclinic_limited=yes +else $as_nop + py_cv_module__testclinic_limited=missing +fi +else $as_nop + py_cv_module__testclinic_limited=disabled +fi + +fi + as_fn_append MODULE_BLOCK "MODULE__TESTCLINIC_LIMITED_STATE=$py_cv_module__testclinic_limited$as_nl" + if test "x$py_cv_module__testclinic_limited" = xyes +then : + + + + +fi + if test "$py_cv_module__testclinic_limited" = yes; then + MODULE__TESTCLINIC_LIMITED_TRUE= + MODULE__TESTCLINIC_LIMITED_FALSE='#' +else + MODULE__TESTCLINIC_LIMITED_TRUE='#' + MODULE__TESTCLINIC_LIMITED_FALSE= +fi + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $py_cv_module__testclinic_limited" >&5 +printf "%s\n" "$py_cv_module__testclinic_limited" >&6; } + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module _testinternalcapi" >&5 printf %s "checking for stdlib extension module _testinternalcapi... " >&6; } if test "$py_cv_module__testinternalcapi" != "n/a" @@ -30362,7 +30550,7 @@ printf %s "checking for stdlib extension module xxlimited... " >&6; } if test "$py_cv_module_xxlimited" != "n/a" then : - if test "$with_trace_refs" = "no" + if true then : if test "$ac_cv_func_dlopen" = yes then : @@ -30400,7 +30588,7 @@ printf %s "checking for stdlib extension module xxlimited_35... " >&6; } if test "$py_cv_module_xxlimited_35" != "n/a" then : - if test "$with_trace_refs" = "no" + if true then : if test "$ac_cv_func_dlopen" = yes then : @@ -30443,6 +30631,7 @@ ac_config_files="$ac_config_files Modules/Setup.bootstrap Modules/Setup.stdlib" ac_config_files="$ac_config_files Modules/ld_so_aix" +# Generate files like pyconfig.h cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure @@ -30633,6 +30822,10 @@ if test -z "${MODULE__XXINTERPCHANNELS_TRUE}" && test -z "${MODULE__XXINTERPCHAN as_fn_error $? "conditional \"MODULE__XXINTERPCHANNELS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${MODULE__XXINTERPQUEUES_TRUE}" && test -z "${MODULE__XXINTERPQUEUES_FALSE}"; then + as_fn_error $? "conditional \"MODULE__XXINTERPQUEUES\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${MODULE__ZONEINFO_TRUE}" && test -z "${MODULE__ZONEINFO_FALSE}"; then as_fn_error $? "conditional \"MODULE__ZONEINFO\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 @@ -30829,6 +31022,10 @@ if test -z "${MODULE__TESTCLINIC_TRUE}" && test -z "${MODULE__TESTCLINIC_FALSE}" as_fn_error $? "conditional \"MODULE__TESTCLINIC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${MODULE__TESTCLINIC_LIMITED_TRUE}" && test -z "${MODULE__TESTCLINIC_LIMITED_FALSE}"; then + as_fn_error $? "conditional \"MODULE__TESTCLINIC_LIMITED\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${MODULE__TESTINTERNALCAPI_TRUE}" && test -z "${MODULE__TESTINTERNALCAPI_FALSE}"; then as_fn_error $? "conditional \"MODULE__TESTINTERNALCAPI\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 @@ -32102,3 +32299,8 @@ CPython core team, see https://peps.python.org/pep-0011/ for more information. " >&2;} fi +if test "$ac_cv_header_stdatomic_h" != "yes"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: Your compiler or platform does have a working C11 stdatomic.h. A future version of Python may require stdatomic.h." >&5 +printf "%s\n" "$as_me: Your compiler or platform does have a working C11 stdatomic.h. A future version of Python may require stdatomic.h." >&6;} +fi + diff --git a/configure.ac b/configure.ac index 8a84eaf6b370a1..9587e6d63499aa 100644 --- a/configure.ac +++ b/configure.ac @@ -1,15 +1,12 @@ -dnl *************************************************** -dnl * Please run autoreconf -if to test your changes! * -dnl *************************************************** +dnl ************************************************************ +dnl * Please run autoreconf -ivf -Werror to test your changes! * +dnl ************************************************************ dnl dnl Python's configure script requires autoconf 2.71, autoconf-archive, -dnl pkgconf's m4 macros. +dnl aclocal 1.16, and pkg-config. dnl -dnl It is recommended to use a cpython_autoconf container to regenerate the -dnl configure script: -dnl -dnl podman run --rm --pull=always -v $(pwd):/src:Z quay.io/tiran/cpython_autoconf:271 -dnl docker run --rm --pull=always -v $(pwd):/src quay.io/tiran/cpython_autoconf:271 +dnl It is recommended to use the Tools/build/regen-configure.sh shell script +dnl to regenerate the configure script. dnl # Set VERSION so we only need to edit in one place (i.e., here) @@ -590,6 +587,14 @@ then darwin*) MACHDEP="darwin";; '') MACHDEP="unknown";; esac + + if test "$ac_sys_system" = "SunOS"; then + # For Solaris, there isn't an OS version specific macro defined + # in most compilers, so we define one here. + SUNOS_VERSION=`echo $ac_sys_release | sed -e 's!\.\([0-9]\)$!.0\1!g' | tr -d '.'` + AC_DEFINE_UNQUOTED([Py_SUNOS_VERSION], [$SUNOS_VERSION], + [The version of SunOS/Solaris as reported by `uname -r' without the dot.]) + fi fi AC_MSG_RESULT(["$MACHDEP"]) @@ -921,198 +926,14 @@ fi AC_MSG_CHECKING([for the platform triplet based on compiler characteristics]) -cat > conftest.c <=6) && defined(_MIPSEL) -# if _MIPS_SIM == _ABIO32 - mipsisa32r6el-linux-gnu -# elif _MIPS_SIM == _ABIN32 - mipsisa64r6el-linux-gnuabin32 -# elif _MIPS_SIM == _ABI64 - mipsisa64r6el-linux-gnuabi64 -# else -# error unknown platform triplet -# endif -# elif defined(__mips_hard_float) && defined(__mips_isa_rev) && (__mips_isa_rev >=6) -# if _MIPS_SIM == _ABIO32 - mipsisa32r6-linux-gnu -# elif _MIPS_SIM == _ABIN32 - mipsisa64r6-linux-gnuabin32 -# elif _MIPS_SIM == _ABI64 - mipsisa64r6-linux-gnuabi64 -# else -# error unknown platform triplet -# endif -# elif defined(__mips_hard_float) && defined(_MIPSEL) -# if _MIPS_SIM == _ABIO32 - mipsel-linux-gnu -# elif _MIPS_SIM == _ABIN32 - mips64el-linux-gnuabin32 -# elif _MIPS_SIM == _ABI64 - mips64el-linux-gnuabi64 -# else -# error unknown platform triplet -# endif -# elif defined(__mips_hard_float) -# if _MIPS_SIM == _ABIO32 - mips-linux-gnu -# elif _MIPS_SIM == _ABIN32 - mips64-linux-gnuabin32 -# elif _MIPS_SIM == _ABI64 - mips64-linux-gnuabi64 -# else -# error unknown platform triplet -# endif -# elif defined(__or1k__) - or1k-linux-gnu -# elif defined(__powerpc__) && defined(__SPE__) - powerpc-linux-gnuspe -# elif defined(__powerpc64__) -# if defined(__LITTLE_ENDIAN__) - powerpc64le-linux-gnu -# else - powerpc64-linux-gnu -# endif -# elif defined(__powerpc__) - powerpc-linux-gnu -# elif defined(__s390x__) - s390x-linux-gnu -# elif defined(__s390__) - s390-linux-gnu -# elif defined(__sh__) && defined(__LITTLE_ENDIAN__) - sh4-linux-gnu -# elif defined(__sparc__) && defined(__arch64__) - sparc64-linux-gnu -# elif defined(__sparc__) - sparc-linux-gnu -# elif defined(__riscv) -# if __riscv_xlen == 32 - riscv32-linux-gnu -# elif __riscv_xlen == 64 - riscv64-linux-gnu -# else -# error unknown platform triplet -# endif -# else -# error unknown platform triplet -# endif -#elif defined(__FreeBSD_kernel__) -# if defined(__LP64__) - x86_64-kfreebsd-gnu -# elif defined(__i386__) - i386-kfreebsd-gnu -# else -# error unknown platform triplet -# endif -#elif defined(__gnu_hurd__) - i386-gnu -#elif defined(__APPLE__) - darwin -#elif defined(__VXWORKS__) - vxworks -#elif defined(__wasm32__) -# if defined(__EMSCRIPTEN__) - wasm32-emscripten -# elif defined(__wasi__) -# if defined(_REENTRANT) - wasm32-wasi-threads -# else - wasm32-wasi -# endif -# else -# error unknown wasm32 platform -# endif -#elif defined(__wasm64__) -# if defined(__EMSCRIPTEN__) - wasm64-emscripten -# elif defined(__wasi__) - wasm64-wasi -# else -# error unknown wasm64 platform -# endif -#else -# error unknown platform triplet -#endif - -EOF - -if $CPP $CPPFLAGS conftest.c >conftest.out 2>/dev/null; then - PLATFORM_TRIPLET=`grep -v '^#' conftest.out | grep -v '^ *$' | tr -d ' '` - case "$build_os" in - linux-musl*) - PLATFORM_TRIPLET=`echo "$PLATFORM_TRIPLET" | sed 's/linux-gnu/linux-musl/'` - ;; - esac +if $CPP $CPPFLAGS $srcdir/Misc/platform_triplet.c >conftest.out 2>/dev/null; then + PLATFORM_TRIPLET=`grep '^PLATFORM_TRIPLET=' conftest.out | tr -d ' '` + PLATFORM_TRIPLET="${PLATFORM_TRIPLET@%:@PLATFORM_TRIPLET=}" AC_MSG_RESULT([$PLATFORM_TRIPLET]) else AC_MSG_RESULT([none]) fi -rm -f conftest.c conftest.out +rm -f conftest.out AC_MSG_CHECKING([for multiarch]) AS_CASE([$ac_sys_system], @@ -1673,6 +1494,23 @@ fi AC_SUBST([ABIFLAGS]) ABIFLAGS="" +# Check for --disable-gil +# --disable-gil +AC_MSG_CHECKING([for --disable-gil]) +AC_ARG_ENABLE([gil], + [AS_HELP_STRING([--disable-gil], [enable experimental support for running without the GIL (default is no)])], + [AS_VAR_IF([enable_gil], [yes], [disable_gil=no], [disable_gil=yes])], [disable_gil=no] +) +AC_MSG_RESULT([$disable_gil]) + +if test "$disable_gil" = "yes" +then + AC_DEFINE([Py_GIL_DISABLED], [1], + [Define if you want to disable the GIL]) + # Add "t" for "threaded" + ABIFLAGS="${ABIFLAGS}t" +fi + # Check for --with-pydebug AC_MSG_CHECKING([for --with-pydebug]) AC_ARG_WITH([pydebug], @@ -1978,7 +1816,10 @@ then fi fi LLVM_PROF_ERR=no -case $CC in + +# GNU Autoconf recommends the use of expr instead of basename. +AS_VAR_SET([CC_BASENAME], [$(expr "//$CC" : '.*/\(.*\)')]) +case "$CC_BASENAME" in *clang*) # Any changes made here should be reflected in the GCC+Darwin case below PGO_PROF_GEN_FLAG="-fprofile-instr-generate" @@ -2318,10 +2159,15 @@ AS_CASE([$ac_sys_system], # without this, configure fails to find pthread_create, sem_init, # etc because they are only available in the sysroot for # wasm32-wasi-threads. + # Note: wasi-threads requires --import-memory. + # Note: wasi requires --export-memory. + # Note: --export-memory is implicit unless --import-memory is given + # Note: this requires LLVM >= 16. AS_VAR_APPEND([CFLAGS], [" -target wasm32-wasi-threads -pthread"]) AS_VAR_APPEND([CFLAGS_NODIST], [" -target wasm32-wasi-threads -pthread"]) AS_VAR_APPEND([LDFLAGS_NODIST], [" -target wasm32-wasi-threads -pthread"]) AS_VAR_APPEND([LDFLAGS_NODIST], [" -Wl,--import-memory"]) + AS_VAR_APPEND([LDFLAGS_NODIST], [" -Wl,--export-memory"]) AS_VAR_APPEND([LDFLAGS_NODIST], [" -Wl,--max-memory=10485760"]) ]) @@ -2409,7 +2255,7 @@ yes) # ICC doesn't recognize the option, but only emits a warning ## XXX does it emit an unused result warning and can it be disabled? - AS_CASE([$CC], + AS_CASE(["$CC_BASENAME"], [*icc*], [ac_cv_disable_unused_result_warning=no] [PY_CHECK_CC_WARNING([disable], [unused-result])]) AS_VAR_IF([ac_cv_disable_unused_result_warning], [yes], @@ -2655,7 +2501,7 @@ yes) ;; esac -case "$CC" in +case "$CC_BASENAME" in *mpicc*) CFLAGS_NODIST="$CFLAGS_NODIST" ;; @@ -2848,14 +2694,14 @@ AC_DEFINE([STDC_HEADERS], [1], # checks for header files AC_CHECK_HEADERS([ \ alloca.h asm/types.h bluetooth.h conio.h direct.h dlfcn.h endian.h errno.h fcntl.h grp.h \ - ieeefp.h io.h langinfo.h libintl.h libutil.h linux/auxvec.h sys/auxv.h linux/fs.h linux/limits.h linux/memfd.h \ + io.h langinfo.h libintl.h libutil.h linux/auxvec.h sys/auxv.h linux/fs.h linux/limits.h linux/memfd.h \ linux/random.h linux/soundcard.h \ linux/tipc.h linux/wait.h netdb.h net/ethernet.h netinet/in.h netpacket/packet.h poll.h process.h pthread.h pty.h \ sched.h setjmp.h shadow.h signal.h spawn.h stropts.h sys/audioio.h sys/bsdtty.h sys/devpoll.h \ sys/endian.h sys/epoll.h sys/event.h sys/eventfd.h sys/file.h sys/ioctl.h sys/kern_control.h \ sys/loadavg.h sys/lock.h sys/memfd.h sys/mkdev.h sys/mman.h sys/modem.h sys/param.h sys/poll.h \ sys/random.h sys/resource.h sys/select.h sys/sendfile.h sys/socket.h sys/soundcard.h sys/stat.h \ - sys/statvfs.h sys/sys_domain.h sys/syscall.h sys/sysmacros.h sys/termio.h sys/time.h sys/times.h \ + sys/statvfs.h sys/sys_domain.h sys/syscall.h sys/sysmacros.h sys/termio.h sys/time.h sys/times.h sys/timerfd.h \ sys/types.h sys/uio.h sys/un.h sys/utsname.h sys/wait.h sys/xattr.h sysexits.h syslog.h \ termios.h util.h utime.h utmp.h \ ]) @@ -2880,7 +2726,8 @@ AC_CHECK_HEADERS([net/if.h], [], [], ]) # On Linux, netlink.h requires asm/types.h -AC_CHECK_HEADERS([linux/netlink.h], [], [], [ +# On FreeBSD, netlink.h is located in netlink/netlink.h +AC_CHECK_HEADERS([linux/netlink.h netlink/netlink.h], [], [], [ #ifdef HAVE_ASM_TYPES_H #include #endif @@ -3220,6 +3067,24 @@ AC_MSG_RESULT([no]) with_ubsan="no" ]) +AC_MSG_CHECKING([for --with-thread-sanitizer]) +AC_ARG_WITH( + [thread_sanitizer], + [AS_HELP_STRING( + [--with-thread-sanitizer], + [enable ThreadSanitizer data race detector, 'tsan' (default is no)] + )], +[ +AC_MSG_RESULT([$withval]) +BASECFLAGS="-fsanitize=thread $BASECFLAGS" +LDFLAGS="-fsanitize=thread $LDFLAGS" +with_tsan="yes" +], +[ +AC_MSG_RESULT([no]) +with_tsan="no" +]) + # Set info about shared libraries. AC_SUBST([SHLIB_SUFFIX]) AC_SUBST([LDSHARED]) @@ -4502,7 +4367,7 @@ ipv6type=unknown ipv6lib=none ipv6trylibc=no -if test "$ipv6" = "yes"; then +if test "$ipv6" = yes -a "$cross_compiling" = no; then AC_MSG_CHECKING([ipv6 stack type]) for i in inria kame linux-glibc linux-inet6 solaris toshiba v6d zeta; do @@ -4652,6 +4517,73 @@ then fi AC_MSG_RESULT([$with_doc_strings]) +# Check for stdatomic.h, required for mimalloc. +AC_CACHE_CHECK([for stdatomic.h], [ac_cv_header_stdatomic_h], [ +AC_LINK_IFELSE( +[ + AC_LANG_SOURCE([[ + #include + atomic_int int_var; + atomic_uintptr_t uintptr_var; + int main() { + atomic_store_explicit(&int_var, 5, memory_order_relaxed); + atomic_store_explicit(&uintptr_var, 0, memory_order_relaxed); + int loaded_value = atomic_load_explicit(&int_var, memory_order_seq_cst); + return 0; + } + ]]) +],[ac_cv_header_stdatomic_h=yes],[ac_cv_header_stdatomic_h=no]) +]) + +AS_VAR_IF([ac_cv_header_stdatomic_h], [yes], [ + AC_DEFINE(HAVE_STD_ATOMIC, 1, + [Has stdatomic.h with atomic_int and atomic_uintptr_t]) +]) + +# Check for GCC >= 4.7 and clang __atomic builtin functions +AC_CACHE_CHECK([for builtin __atomic_load_n and __atomic_store_n functions], [ac_cv_builtin_atomic], [ +AC_LINK_IFELSE( +[ + AC_LANG_SOURCE([[ + int val; + int main() { + __atomic_store_n(&val, 1, __ATOMIC_SEQ_CST); + (void)__atomic_load_n(&val, __ATOMIC_SEQ_CST); + return 0; + } + ]]) +],[ac_cv_builtin_atomic=yes],[ac_cv_builtin_atomic=no]) +]) + +AS_VAR_IF([ac_cv_builtin_atomic], [yes], [ + AC_DEFINE(HAVE_BUILTIN_ATOMIC, 1, [Has builtin __atomic_load_n() and __atomic_store_n() functions]) +]) + +# --with-mimalloc +AC_MSG_CHECKING([for --with-mimalloc]) +AC_ARG_WITH([mimalloc], + [AS_HELP_STRING([--with-mimalloc], + [build with mimalloc memory allocator (default is yes if C11 stdatomic.h is available.)])], + [], + [with_mimalloc="$ac_cv_header_stdatomic_h"] +) + +if test "$with_mimalloc" != no; then + if test "$ac_cv_header_stdatomic_h" != yes; then + # mimalloc-atomic.h wants C11 stdatomic.h on POSIX + AC_MSG_ERROR([mimalloc requires stdatomic.h, use --without-mimalloc to disable mimalloc.]) + fi + with_mimalloc=yes + AC_DEFINE([WITH_MIMALLOC], [1], [Define if you want to compile in mimalloc memory allocator.]) + AC_SUBST([MIMALLOC_HEADERS], ['$(MIMALLOC_HEADERS)']) +elif test "$disable_gil" = "yes"; then + AC_MSG_ERROR([--disable-gil requires mimalloc memory allocator (--with-mimalloc).]) +fi + +AC_MSG_RESULT([$with_mimalloc]) +AC_SUBST([WITH_MIMALLOC]) +AC_SUBST([MIMALLOC_HEADERS]) + # Check for Python-specific malloc support AC_MSG_CHECKING([for --with-pymalloc]) AC_ARG_WITH( @@ -4773,8 +4705,8 @@ PLATFORM_OBJS= AS_CASE([$ac_sys_system], [Emscripten], [ - AS_VAR_APPEND([PLATFORM_OBJS], [' Python/emscripten_signal.o']) - AS_VAR_APPEND([PLATFORM_HEADERS], [' $(srcdir)/Include/internal/pycore_emscripten_signal.h']) + AS_VAR_APPEND([PLATFORM_OBJS], [' Python/emscripten_signal.o Python/emscripten_trampoline.o']) + AS_VAR_APPEND([PLATFORM_HEADERS], [' $(srcdir)/Include/internal/pycore_emscripten_signal.h $(srcdir)/Include/internal/pycore_emscripten_trampoline.h']) ], ) AC_SUBST([PLATFORM_HEADERS]) @@ -4831,7 +4763,7 @@ fi # checks for library functions AC_CHECK_FUNCS([ \ - accept4 alarm bind_textdomain_codeset chmod chown clock close_range confstr \ + accept4 alarm bind_textdomain_codeset chmod chown clock closefrom close_range confstr \ copy_file_range ctermid dup dup3 execv explicit_bzero explicit_memset \ faccessat fchmod fchmodat fchown fchownat fdopendir fdwalk fexecve \ fork fork1 fpathconf fstatat ftime ftruncate futimens futimes futimesat \ @@ -4843,6 +4775,7 @@ AC_CHECK_FUNCS([ \ lockf lstat lutimes madvise mbrtowc memrchr mkdirat mkfifo mkfifoat \ mknod mknodat mktime mmap mremap nice openat opendir pathconf pause pipe \ pipe2 plock poll posix_fadvise posix_fallocate posix_spawn posix_spawnp \ + posix_spawn_file_actions_addclosefrom_np \ pread preadv preadv2 pthread_condattr_setclock pthread_init pthread_kill \ pwrite pwritev pwritev2 readlink readlinkat readv realpath renameat \ rtpSpawn sched_get_priority_max sched_rr_get_interval sched_setaffinity \ @@ -4907,6 +4840,13 @@ PY_CHECK_FUNC([eventfd], [ #endif ]) +PY_CHECK_FUNC([timerfd_create], [ +#ifdef HAVE_SYS_TIMERFD_H +#include +#endif +], +[HAVE_TIMERFD_CREATE]) + # On some systems (eg. FreeBSD 5), we would find a definition of the # functions ctermid_r, setgroups in the library, but no prototype # (e.g. because we use _XOPEN_SOURCE). See whether we can take their @@ -5180,6 +5120,7 @@ AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #if defined(MAJOR_IN_MKDEV) #include #elif defined(MAJOR_IN_SYSMACROS) +#include #include #else #include @@ -5849,6 +5790,7 @@ AC_C_BIGENDIAN # # * The Python implementation (always 'cpython-' for us) # * The major and minor version numbers +# * --disable-gil (adds a 't') # * --with-pydebug (adds a 'd') # # Thus for example, Python 3.2 built with wide unicode, pydebug, and pymalloc, @@ -5864,8 +5806,9 @@ AC_MSG_CHECKING([SOABI]) SOABI='cpython-'`echo $VERSION | tr -d .`${ABIFLAGS}${PLATFORM_TRIPLET:+-$PLATFORM_TRIPLET} AC_MSG_RESULT([$SOABI]) -# Release and debug (Py_DEBUG) ABI are compatible, but not Py_TRACE_REFS ABI -if test "$Py_DEBUG" = 'true' -a "$with_trace_refs" != "yes"; then +# Release build, debug build (Py_DEBUG), and trace refs build (Py_TRACE_REFS) +# are ABI compatible +if test "$Py_DEBUG" = 'true'; then # Similar to SOABI but remove "d" flag from ABIFLAGS AC_SUBST([ALT_SOABI]) ALT_SOABI='cpython-'`echo $VERSION | tr -d .``echo $ABIFLAGS | tr -d d`${PLATFORM_TRIPLET:+-$PLATFORM_TRIPLET} @@ -6143,6 +6086,13 @@ AS_VAR_IF([with_readline], [no], [ AC_DEFINE([HAVE_RL_APPEND_HISTORY], [1], [Define if readline supports append_history]) ]) + # in readline as well as newer editline (April 2023) + AC_CHECK_TYPE([rl_compdisp_func_t], + [AC_DEFINE([HAVE_RL_COMPDISP_FUNC_T], [1], + [Define if readline supports rl_compdisp_func_t])], + [], + [readline_includes]) + m4_undefine([readline_includes]) ])dnl WITH_SAVE_ENV() ]) @@ -6349,9 +6299,11 @@ dnl remove _XOPEN_SOURCE macro from curses cflags. pyconfig.h sets dnl the macro to 700. CURSES_CFLAGS=$(echo $CURSES_CFLAGS | sed 's/-D_XOPEN_SOURCE=600//g') -if test "$have_curses" = no -a "$ac_sys_system" = "Darwin"; then +if test "$have_curses" != no -a "$ac_sys_system" = "Darwin"; then dnl On macOS, there is no separate /usr/lib/libncursesw nor libpanelw. - dnl If we are here, we found a locally-supplied version of libncursesw. + dnl System-supplied ncurses combines libncurses/libpanel and supports wide + dnl characters, so we can use it like ncursesw. + dnl If a locally-supplied version of libncursesw is found, we will use that. dnl There should also be a libpanelw. dnl _XOPEN_SOURCE defines are usually excluded for macOS, but we need dnl _XOPEN_SOURCE_EXTENDED here for ncurses wide char support. @@ -6649,11 +6601,16 @@ SRCDIRS="\ Modules/_sqlite \ Modules/_sre \ Modules/_testcapi \ + Modules/_testinternalcapi \ Modules/_xxtestfuzz \ Modules/cjkcodecs \ Modules/expat \ Objects \ + Objects/mimalloc \ + Objects/mimalloc/prim \ Parser \ + Parser/tokenizer \ + Parser/lexer \ Programs \ Python \ Python/frozen_modules \ @@ -6748,49 +6705,6 @@ if test "$ac_cv_gcc_asm_for_x87" = yes; then esac fi -# Check for stdatomic.h -AC_CACHE_CHECK([for stdatomic.h], [ac_cv_header_stdatomic_h], [ -AC_LINK_IFELSE( -[ - AC_LANG_SOURCE([[ - #include - atomic_int int_var; - atomic_uintptr_t uintptr_var; - int main(void) { - atomic_store_explicit(&int_var, 5, memory_order_relaxed); - atomic_store_explicit(&uintptr_var, 0, memory_order_relaxed); - int loaded_value = atomic_load_explicit(&int_var, memory_order_seq_cst); - return 0; - } - ]]) -],[ac_cv_header_stdatomic_h=yes],[ac_cv_header_stdatomic_h=no]) -]) - -AS_VAR_IF([ac_cv_header_stdatomic_h], [yes], [ - AC_DEFINE([HAVE_STD_ATOMIC], [1], - [Has stdatomic.h with atomic_int and atomic_uintptr_t]) -]) - -# Check for GCC >= 4.7 and clang __atomic builtin functions -AC_CACHE_CHECK([for builtin __atomic_load_n and __atomic_store_n functions], [ac_cv_builtin_atomic], [ -AC_LINK_IFELSE( -[ - AC_LANG_SOURCE([[ - int val; - int main(void) { - __atomic_store_n(&val, 1, __ATOMIC_SEQ_CST); - (void)__atomic_load_n(&val, __ATOMIC_SEQ_CST); - return 0; - } - ]]) -],[ac_cv_builtin_atomic=yes],[ac_cv_builtin_atomic=no]) -]) - -AS_VAR_IF([ac_cv_builtin_atomic], [yes], [ - AC_DEFINE([HAVE_BUILTIN_ATOMIC], [1], - [Has builtin __atomic_load_n() and __atomic_store_n() functions]) -]) - # ensurepip option AC_MSG_CHECKING([for ensurepip]) AC_ARG_WITH([ensurepip], @@ -6913,7 +6827,12 @@ AX_CHECK_OPENSSL([have_openssl=yes],[have_openssl=no]) AS_VAR_IF([GNULD], [yes], [ rpath_arg="-Wl,--enable-new-dtags,-rpath=" ], [ - rpath_arg="-Wl,-rpath=" + if test "$ac_sys_system" = "Darwin" + then + rpath_arg="-Wl,-rpath," + else + rpath_arg="-Wl,-rpath=" + fi ]) AC_MSG_CHECKING([for --with-openssl-rpath]) @@ -7125,6 +7044,74 @@ AC_ARG_ENABLE([test-modules], AC_MSG_RESULT([$TEST_MODULES]) AC_SUBST([TEST_MODULES]) +# gh-109054: Check if -latomic is needed to get atomic functions. +# On Linux aarch64, GCC may require programs and libraries to be linked +# explicitly to libatomic. Call _Py_atomic_or_uint64() which may require +# libatomic __atomic_fetch_or_8(), or not, depending on the C compiler and the +# compiler flags. +# +# gh-112779: On RISC-V, GCC 12 and earlier require libatomic support for 1-byte +# and 2-byte operations, but not for 8-byte operations. +# +# Avoid #include or #include . The header +# requires header which is only written below by AC_OUTPUT below. +# If the check is done after AC_OUTPUT, modifying LIBS has no effect +# anymore. cannot be included alone, it's designed to be included +# by : it expects other includes and macros to be defined. +_SAVE_VAR([CPPFLAGS]) +CPPFLAGS="${BASECPPFLAGS} -I. -I${srcdir}/Include ${CPPFLAGS}" + +AC_CACHE_CHECK([whether libatomic is needed by ], + [ac_cv_libatomic_needed], +[AC_RUN_IFELSE([AC_LANG_SOURCE([[ +// pyatomic.h needs uint64_t and Py_ssize_t types +#include // int64_t, intptr_t +#ifdef HAVE_SYS_TYPES_H +# include // ssize_t +#endif +// Code adapted from Include/pyport.h +#if HAVE_SSIZE_T +typedef ssize_t Py_ssize_t; +#elif SIZEOF_VOID_P == SIZEOF_SIZE_T +typedef intptr_t Py_ssize_t; +#else +# error "unable to define Py_ssize_t" +#endif + +#include "pyatomic.h" + +int main() +{ + uint64_t value; + _Py_atomic_store_uint64(&value, 2); + if (_Py_atomic_or_uint64(&value, 8) != 2) { + return 1; // error + } + if (_Py_atomic_load_uint64(&value) != 10) { + return 1; // error + } + uint8_t byte = 0xb8; + if (_Py_atomic_or_uint8(&byte, 0x2d) != 0xb8) { + return 1; // error + } + if (_Py_atomic_load_uint8(&byte) != 0xbd) { + return 1; // error + } + return 0; // all good +} +]])], + [ac_cv_libatomic_needed=no], dnl build succeeded + [ac_cv_libatomic_needed=yes], dnl build failed + [ac_cv_libatomic_needed=no]) dnl cross compilation +]) + +AS_VAR_IF([ac_cv_libatomic_needed], [yes], + [LIBS="${LIBS} -latomic" + LIBATOMIC=${LIBATOMIC-"-latomic"}]) +_RESTORE_VAR([CPPFLAGS]) + + +# stdlib AC_DEFUN([PY_STDLIB_MOD_SET_NA], [ m4_foreach([mod], [$@], [ AS_VAR_SET([py_cv_module_]mod, [n/a])]) @@ -7158,6 +7145,7 @@ AS_CASE([$ac_sys_system], [_tkinter], [_xxsubinterpreters], [_xxinterpchannels], + [_xxinterpqueues], [grp], [pwd], [resource], @@ -7274,6 +7262,7 @@ PY_STDLIB_MOD_SIMPLE([_struct]) PY_STDLIB_MOD_SIMPLE([_typing]) PY_STDLIB_MOD_SIMPLE([_xxsubinterpreters]) PY_STDLIB_MOD_SIMPLE([_xxinterpchannels]) +PY_STDLIB_MOD_SIMPLE([_xxinterpqueues]) PY_STDLIB_MOD_SIMPLE([_zoneinfo]) dnl multiprocessing modules @@ -7392,8 +7381,12 @@ PY_STDLIB_MOD([_hashlib], [], [test "$ac_cv_working_openssl_hashlib" = yes], [$OPENSSL_INCLUDES], [$OPENSSL_LDFLAGS $OPENSSL_LDFLAGS_RPATH $LIBCRYPTO_LIBS]) dnl test modules -PY_STDLIB_MOD([_testcapi], [test "$TEST_MODULES" = yes]) +PY_STDLIB_MOD([_testcapi], + [test "$TEST_MODULES" = yes], + dnl Modules/_testcapi needs -latomic for 32bit AIX build + [], [], [$LIBATOMIC]) PY_STDLIB_MOD([_testclinic], [test "$TEST_MODULES" = yes]) +PY_STDLIB_MOD([_testclinic_limited], [test "$TEST_MODULES" = yes]) PY_STDLIB_MOD([_testinternalcapi], [test "$TEST_MODULES" = yes]) PY_STDLIB_MOD([_testbuffer], [test "$TEST_MODULES" = yes]) PY_STDLIB_MOD([_testimportmultiple], [test "$TEST_MODULES" = yes], [test "$ac_cv_func_dlopen" = yes]) @@ -7405,10 +7398,9 @@ PY_STDLIB_MOD([_ctypes_test], [], [$LIBM]) dnl Limited API template modules. -dnl The limited C API is not compatible with the Py_TRACE_REFS macro. dnl Emscripten does not support shared libraries yet. -PY_STDLIB_MOD([xxlimited], [test "$with_trace_refs" = "no"], [test "$ac_cv_func_dlopen" = yes]) -PY_STDLIB_MOD([xxlimited_35], [test "$with_trace_refs" = "no"], [test "$ac_cv_func_dlopen" = yes]) +PY_STDLIB_MOD([xxlimited], [], [test "$ac_cv_func_dlopen" = yes]) +PY_STDLIB_MOD([xxlimited_35], [], [test "$ac_cv_func_dlopen" = yes]) # substitute multiline block, must come after last PY_STDLIB_MOD() AC_SUBST([MODULE_BLOCK]) @@ -7425,6 +7417,7 @@ AC_CONFIG_FILES(m4_normalize([ Modules/Setup.stdlib ])) AC_CONFIG_FILES([Modules/ld_so_aix], [chmod +x Modules/ld_so_aix]) +# Generate files like pyconfig.h AC_OUTPUT AC_MSG_NOTICE([creating Modules/Setup.local]) @@ -7460,3 +7453,10 @@ AS_VAR_IF([PY_SUPPORT_TIER], [0], [AC_MSG_WARN([ Platform "$host" with compiler "$ac_cv_cc_name" is not supported by the CPython core team, see https://peps.python.org/pep-0011/ for more information. ])]) + +if test "$ac_cv_header_stdatomic_h" != "yes"; then + AC_MSG_NOTICE(m4_normalize([ + Your compiler or platform does have a working C11 stdatomic.h. A future + version of Python may require stdatomic.h. + ])) +fi diff --git a/pyconfig.h.in b/pyconfig.h.in index dab8ebf64371f3..d8a9f68951afbd 100644 --- a/pyconfig.h.in +++ b/pyconfig.h.in @@ -157,6 +157,9 @@ /* Define to 1 if you have the `clock_settime' function. */ #undef HAVE_CLOCK_SETTIME +/* Define to 1 if you have the `closefrom' function. */ +#undef HAVE_CLOSEFROM + /* Define to 1 if you have the `close_range' function. */ #undef HAVE_CLOSE_RANGE @@ -607,9 +610,6 @@ /* Define this if you have le64toh() */ #undef HAVE_HTOLE64 -/* Define to 1 if you have the header file. */ -#undef HAVE_IEEEFP_H - /* Define to 1 if you have the `if_nameindex' function. */ #undef HAVE_IF_NAMEINDEX @@ -841,6 +841,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_NETINET_IN_H +/* Define to 1 if you have the header file. */ +#undef HAVE_NETLINK_NETLINK_H + /* Define to 1 if you have the header file. */ #undef HAVE_NETPACKET_PACKET_H @@ -902,6 +905,10 @@ /* Define to 1 if you have the `posix_spawnp' function. */ #undef HAVE_POSIX_SPAWNP +/* Define to 1 if you have the `posix_spawn_file_actions_addclosefrom_np' + function. */ +#undef HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSEFROM_NP + /* Define to 1 if you have the `pread' function. */ #undef HAVE_PREAD @@ -983,6 +990,9 @@ /* Define if you can turn off readline's signal handling. */ #undef HAVE_RL_CATCH_SIGNAL +/* Define if readline supports rl_compdisp_func_t */ +#undef HAVE_RL_COMPDISP_FUNC_T + /* Define if you have readline 2.2 */ #undef HAVE_RL_COMPLETION_APPEND_CHARACTER @@ -1363,6 +1373,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TERMIO_H +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TIMERFD_H + /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TIMES_H @@ -1405,6 +1418,9 @@ /* Define to 1 if you have the `timegm' function. */ #undef HAVE_TIMEGM +/* Define if you have the 'timerfd_create' function. */ +#undef HAVE_TIMERFD_CREATE + /* Define to 1 if you have the `times' function. */ #undef HAVE_TIMES @@ -1602,6 +1618,9 @@ /* Defined if Python is built as a shared library. */ #undef Py_ENABLE_SHARED +/* Define if you want to disable the GIL */ +#undef Py_GIL_DISABLED + /* Define hash algorithm for str, bytes and memoryview. SipHash24: 1, FNV: 2, SipHash13: 3, externally defined: 0 */ #undef Py_HASH_ALGORITHM @@ -1609,6 +1628,9 @@ /* Define if you want to enable internal statistics gathering. */ #undef Py_STATS +/* The version of SunOS/Solaris as reported by `uname -r' without the dot. */ +#undef Py_SUNOS_VERSION + /* Define if you want to enable tracing references for debugging purpose */ #undef Py_TRACE_REFS @@ -1809,6 +1831,9 @@ /* Define to 1 if libintl is needed for locale functions. */ #undef WITH_LIBINTL +/* Define if you want to compile in mimalloc memory allocator. */ +#undef WITH_MIMALLOC + /* Define if you want to produce an OpenStep/Rhapsody framework (shared library plus accessory files). */ #undef WITH_NEXT_FRAMEWORK